diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/8253pit.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/8253pit.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/8253pit.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/8253pit.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,3 @@
 /*
  * 8253/8254 Programmable Interval Timer
  */
-
-#ifndef _8253PIT_H
-#define _8253PIT_H
-
-#define PIT_TICK_RATE 	1193180UL
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -256,5 +256,5 @@
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* _ALPHA_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,8 @@
+#ifndef __ASM_ALPHA_BITSPERLONG_H
+#define __ASM_ALPHA_BITSPERLONG_H
+
+#define __BITS_PER_LONG 64
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_ALPHA_BITSPERLONG_H */
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/errno.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/errno.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/errno.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/errno.h	2009-09-09 18:13:59.000000000 -0400
@@ -120,4 +120,6 @@
 #define	EOWNERDEAD	136	/* Owner died */
 #define	ENOTRECOVERABLE	137	/* State not recoverable */
 
+#define	ERFKILL		138	/* Operation not possible due to RF-kill */
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,30 +3,12 @@
 
 /* Dummy header just to define km_type. */
 
-
 #ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
+#define  __WITH_KM_FENCE
 #endif
 
-enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_IRQ0,
-D(10)	KM_IRQ1,
-D(11)	KM_SOFTIRQ0,
-D(12)	KM_SOFTIRQ1,
-D(13)	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
-#undef D
+#undef __WITH_KM_FENCE
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/page.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -93,6 +93,6 @@
 					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _ALPHA_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/pci.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -237,19 +237,6 @@
 extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 				    struct pci_bus_region *region);
 
-static inline struct resource *
-pcibios_select_root(struct pci_dev *pdev, struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
 static inline int pci_proc_domain(struct pci_bus *bus)
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/percpu.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/percpu.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/percpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/percpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,7 @@
 
 #ifndef MODULE
 #define SHIFT_PERCPU_PTR(var, offset) RELOC_HIDE(&per_cpu_var(var), (offset))
-#define PER_CPU_ATTRIBUTES
+#define PER_CPU_DEF_ATTRIBUTES
 #else
 /*
  * To calculate addresses of locally defined variables, GCC uses 32-bit
@@ -49,7 +49,7 @@
 		: "=&r"(__ptr), "=&r"(tmp_gp));		\
 	(typeof(&per_cpu_var(var)))(__ptr + (offset)); })
 
-#define PER_CPU_ATTRIBUTES	__used
+#define PER_CPU_DEF_ATTRIBUTES	__used
 
 #endif /* MODULE */
 
@@ -71,7 +71,7 @@
 #define __get_cpu_var(var)		per_cpu_var(var)
 #define __raw_get_cpu_var(var)		per_cpu_var(var)
 
-#define PER_CPU_ATTRIBUTES
+#define PER_CPU_DEF_ATTRIBUTES
 
 #endif /* SMP */
 
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/signal.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -111,7 +111,7 @@
 #define SIG_UNBLOCK        2	/* for unblocking signals */
 #define SIG_SETMASK        3	/* for setting the signal mask */
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct osf_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/suspend.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/suspend.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/suspend.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef __ALPHA_SUSPEND_H
-#define __ALPHA_SUSPEND_H
-
-/* Dummy include. */
-
-#endif  /* __ALPHA_SUSPEND_H */
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,7 @@
 	.task		= &tsk,			\
 	.exec_domain	= &default_exec_domain,	\
 	.addr_limit	= KERNEL_DS,		\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,7 +9,7 @@
 
 #include <asm-generic/tlb.h>
 
-#define __pte_free_tlb(tlb, pte)			pte_free((tlb)->mm, pte)
-#define __pmd_free_tlb(tlb, pmd)			pmd_free((tlb)->mm, pmd)
+#define __pte_free_tlb(tlb, pte, address)		pte_free((tlb)->mm, pte)
+#define __pmd_free_tlb(tlb, pmd, address)		pmd_free((tlb)->mm, pmd)
  
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/alpha/include/asm/types.h linux-libre-2.6.31-gnu/arch/alpha/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/alpha/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,9 +25,6 @@
  * These aren't exported outside the kernel to avoid name space clashes
  */
 #ifdef __KERNEL__
-
-#define BITS_PER_LONG 64
-
 #ifndef __ASSEMBLY__
 
 typedef u64 dma_addr_t;
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/init_task.c linux-libre-2.6.31-gnu/arch/alpha/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,10 +10,7 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
 struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_mm);
 EXPORT_SYMBOL(init_task);
 
 union thread_union init_thread_union
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_alpha.c linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_alpha.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_alpha.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_alpha.c	2009-09-09 18:13:59.000000000 -0400
@@ -227,7 +227,7 @@
 	.name		= "timer",
 };
 
-static struct hw_interrupt_type rtc_irq_type = {
+static struct irq_chip rtc_irq_type = {
 	.typename	= "RTC",
 	.startup	= rtc_startup,
 	.shutdown	= rtc_enable_disable,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_i8259.c linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_i8259.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_i8259.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_i8259.c	2009-09-09 18:13:59.000000000 -0400
@@ -83,7 +83,7 @@
 		i8259a_enable_irq(irq);
 }
 
-struct hw_interrupt_type i8259a_irq_type = {
+struct irq_chip i8259a_irq_type = {
 	.typename	= "XT-PIC",
 	.startup	= i8259a_startup_irq,
 	.shutdown	= i8259a_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_impl.h linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_impl.h
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_impl.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_impl.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,7 @@
 extern void i8259a_mask_and_ack_irq(unsigned int);
 extern unsigned int i8259a_startup_irq(unsigned int);
 extern void i8259a_end_irq(unsigned int);
-extern struct hw_interrupt_type i8259a_irq_type;
+extern struct irq_chip i8259a_irq_type;
 extern void init_i8259a_irqs(void);
 
 extern void handle_irq(int irq);
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_pyxis.c linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_pyxis.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_pyxis.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_pyxis.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 	*(vulp)PYXIS_INT_MASK;
 }
 
-static struct hw_interrupt_type pyxis_irq_type = {
+static struct irq_chip pyxis_irq_type = {
 	.typename	= "PYXIS",
 	.startup	= pyxis_startup_irq,
 	.shutdown	= pyxis_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_srm.c linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_srm.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/irq_srm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/irq_srm.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,7 @@
 }
 
 /* Handle interrupts from the SRM, assuming no additional weirdness.  */
-static struct hw_interrupt_type srm_irq_type = {
+static struct irq_chip srm_irq_type = {
 	.typename	= "SRM",
 	.startup	= srm_startup_irq,
 	.shutdown	= srm_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/osf_sys.c linux-libre-2.6.31-gnu/arch/alpha/kernel/osf_sys.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/osf_sys.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/osf_sys.c	2009-09-09 18:13:59.000000000 -0400
@@ -371,8 +371,6 @@
 	int retval = -EINVAL;
 	char *name;
 
-	lock_kernel();
-
 	name = getname(path);
 	retval = PTR_ERR(name);
 	if (IS_ERR(name))
@@ -392,7 +390,6 @@
 	}
 	putname(name);
  out:
-	unlock_kernel();
 	return retval;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/alpha/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/setup.c linux-libre-2.6.31-gnu/arch/alpha/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -252,9 +252,9 @@
 }
 
 #define PFN_MAX		PFN_DOWN(0x80000000)
-#define for_each_mem_cluster(memdesc, cluster, i)		\
-	for ((cluster) = (memdesc)->cluster, (i) = 0;		\
-	     (i) < (memdesc)->numclusters; (i)++, (cluster)++)
+#define for_each_mem_cluster(memdesc, _cluster, i)		\
+	for ((_cluster) = (memdesc)->cluster, (i) = 0;		\
+	     (i) < (memdesc)->numclusters; (i)++, (_cluster)++)
 
 static unsigned long __init
 get_mem_size_limit(char *s)
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_alcor.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_alcor.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_alcor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_alcor.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,7 +89,7 @@
 		alcor_enable_irq(irq);
 }
 
-static struct hw_interrupt_type alcor_irq_type = {
+static struct irq_chip alcor_irq_type = {
 	.typename	= "ALCOR",
 	.startup	= alcor_startup_irq,
 	.shutdown	= alcor_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_cabriolet.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_cabriolet.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_cabriolet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_cabriolet.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,7 +71,7 @@
 		cabriolet_enable_irq(irq);
 }
 
-static struct hw_interrupt_type cabriolet_irq_type = {
+static struct irq_chip cabriolet_irq_type = {
 	.typename	= "CABRIOLET",
 	.startup	= cabriolet_startup_irq,
 	.shutdown	= cabriolet_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_dp264.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_dp264.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_dp264.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_dp264.c	2009-09-09 18:13:59.000000000 -0400
@@ -176,25 +176,29 @@
 	}
 }
 
-static void
+static int
 dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
 { 
 	spin_lock(&dp264_irq_lock);
 	cpu_set_irq_affinity(irq, *affinity);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
+
+	return 0;
 }
 
-static void
+static int
 clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
 { 
 	spin_lock(&dp264_irq_lock);
 	cpu_set_irq_affinity(irq - 16, *affinity);
 	tsunami_update_irq_hw(cached_irq_mask);
 	spin_unlock(&dp264_irq_lock);
+
+	return 0;
 }
 
-static struct hw_interrupt_type dp264_irq_type = {
+static struct irq_chip dp264_irq_type = {
 	.typename	= "DP264",
 	.startup	= dp264_startup_irq,
 	.shutdown	= dp264_disable_irq,
@@ -205,7 +209,7 @@
 	.set_affinity	= dp264_set_affinity,
 };
 
-static struct hw_interrupt_type clipper_irq_type = {
+static struct irq_chip clipper_irq_type = {
 	.typename	= "CLIPPER",
 	.startup	= clipper_startup_irq,
 	.shutdown	= clipper_disable_irq,
@@ -294,7 +298,7 @@
 }
 
 static void __init
-init_tsunami_irqs(struct hw_interrupt_type * ops, int imin, int imax)
+init_tsunami_irqs(struct irq_chip * ops, int imin, int imax)
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_eb64p.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_eb64p.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_eb64p.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_eb64p.c	2009-09-09 18:13:59.000000000 -0400
@@ -69,7 +69,7 @@
 		eb64p_enable_irq(irq);
 }
 
-static struct hw_interrupt_type eb64p_irq_type = {
+static struct irq_chip eb64p_irq_type = {
 	.typename	= "EB64P",
 	.startup	= eb64p_startup_irq,
 	.shutdown	= eb64p_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_eiger.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_eiger.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_eiger.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_eiger.c	2009-09-09 18:13:59.000000000 -0400
@@ -80,7 +80,7 @@
 		eiger_enable_irq(irq);
 }
 
-static struct hw_interrupt_type eiger_irq_type = {
+static struct irq_chip eiger_irq_type = {
 	.typename	= "EIGER",
 	.startup	= eiger_startup_irq,
 	.shutdown	= eiger_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_jensen.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_jensen.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_jensen.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_jensen.c	2009-09-09 18:13:59.000000000 -0400
@@ -118,7 +118,7 @@
 		i8259a_end_irq(1);
 }
 
-static struct hw_interrupt_type jensen_local_irq_type = {
+static struct irq_chip jensen_local_irq_type = {
 	.typename	= "LOCAL",
 	.startup	= jensen_local_startup,
 	.shutdown	= jensen_local_shutdown,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_marvel.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_marvel.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_marvel.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_marvel.c	2009-09-09 18:13:59.000000000 -0400
@@ -169,7 +169,7 @@
 	return 0; 
 }
 
-static struct hw_interrupt_type marvel_legacy_irq_type = {
+static struct irq_chip marvel_legacy_irq_type = {
 	.typename	= "LEGACY",
 	.startup	= marvel_irq_noop_return,
 	.shutdown	= marvel_irq_noop,
@@ -179,7 +179,7 @@
 	.end		= marvel_irq_noop,
 };
 
-static struct hw_interrupt_type io7_lsi_irq_type = {
+static struct irq_chip io7_lsi_irq_type = {
 	.typename	= "LSI",
 	.startup	= io7_startup_irq,
 	.shutdown	= io7_disable_irq,
@@ -189,7 +189,7 @@
 	.end		= io7_end_irq,
 };
 
-static struct hw_interrupt_type io7_msi_irq_type = {
+static struct irq_chip io7_msi_irq_type = {
 	.typename	= "MSI",
 	.startup	= io7_startup_irq,
 	.shutdown	= io7_disable_irq,
@@ -273,8 +273,8 @@
 
 static void __init
 init_io7_irqs(struct io7 *io7, 
-	      struct hw_interrupt_type *lsi_ops,
-	      struct hw_interrupt_type *msi_ops)
+	      struct irq_chip *lsi_ops,
+	      struct irq_chip *msi_ops)
 {
 	long base = (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT) + 16;
 	long i;
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_mikasa.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_mikasa.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_mikasa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_mikasa.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,7 +68,7 @@
 		mikasa_enable_irq(irq);
 }
 
-static struct hw_interrupt_type mikasa_irq_type = {
+static struct irq_chip mikasa_irq_type = {
 	.typename	= "MIKASA",
 	.startup	= mikasa_startup_irq,
 	.shutdown	= mikasa_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_noritake.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_noritake.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_noritake.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_noritake.c	2009-09-09 18:13:59.000000000 -0400
@@ -73,7 +73,7 @@
                 noritake_enable_irq(irq);
 }
 
-static struct hw_interrupt_type noritake_irq_type = {
+static struct irq_chip noritake_irq_type = {
 	.typename	= "NORITAKE",
 	.startup	= noritake_startup_irq,
 	.shutdown	= noritake_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_rawhide.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_rawhide.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_rawhide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_rawhide.c	2009-09-09 18:13:59.000000000 -0400
@@ -135,7 +135,7 @@
 		rawhide_enable_irq(irq);
 }
 
-static struct hw_interrupt_type rawhide_irq_type = {
+static struct irq_chip rawhide_irq_type = {
 	.typename	= "RAWHIDE",
 	.startup	= rawhide_startup_irq,
 	.shutdown	= rawhide_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_ruffian.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_ruffian.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_ruffian.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_ruffian.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
+#include <linux/timex.h>
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_rx164.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_rx164.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_rx164.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_rx164.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,7 +72,7 @@
 		rx164_enable_irq(irq);
 }
 
-static struct hw_interrupt_type rx164_irq_type = {
+static struct irq_chip rx164_irq_type = {
 	.typename	= "RX164",
 	.startup	= rx164_startup_irq,
 	.shutdown	= rx164_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_sable.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_sable.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_sable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_sable.c	2009-09-09 18:13:59.000000000 -0400
@@ -501,7 +501,7 @@
 	spin_unlock(&sable_lynx_irq_lock);
 }
 
-static struct hw_interrupt_type sable_lynx_irq_type = {
+static struct irq_chip sable_lynx_irq_type = {
 	.typename	= "SABLE/LYNX",
 	.startup	= sable_lynx_startup_irq,
 	.shutdown	= sable_lynx_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_takara.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_takara.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_takara.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_takara.c	2009-09-09 18:13:59.000000000 -0400
@@ -74,7 +74,7 @@
 		takara_enable_irq(irq);
 }
 
-static struct hw_interrupt_type takara_irq_type = {
+static struct irq_chip takara_irq_type = {
 	.typename	= "TAKARA",
 	.startup	= takara_startup_irq,
 	.shutdown	= takara_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_titan.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_titan.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_titan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_titan.c	2009-09-09 18:13:59.000000000 -0400
@@ -157,13 +157,15 @@
 
 }
 
-static void
+static int
 titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
 { 
 	spin_lock(&titan_irq_lock);
 	titan_cpu_set_irq_affinity(irq - 16, *affinity);
 	titan_update_irq_hw(titan_cached_irq_mask);
 	spin_unlock(&titan_irq_lock);
+
+	return 0;
 }
 
 static void
@@ -183,7 +185,7 @@
 
 
 static void __init
-init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax)
+init_titan_irqs(struct irq_chip * ops, int imin, int imax)
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
@@ -192,7 +194,7 @@
 	}
 }
 
-static struct hw_interrupt_type titan_irq_type = {
+static struct irq_chip titan_irq_type = {
        .typename       = "TITAN",
        .startup        = titan_startup_irq,
        .shutdown       = titan_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_wildfire.c linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_wildfire.c
--- linux-libre-2.6.30-gnu/arch/alpha/kernel/sys_wildfire.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/kernel/sys_wildfire.c	2009-09-09 18:13:59.000000000 -0400
@@ -157,7 +157,7 @@
 		wildfire_enable_irq(irq);
 }
 
-static struct hw_interrupt_type wildfire_irq_type = {
+static struct irq_chip wildfire_irq_type = {
 	.typename	= "WILDFIRE",
 	.startup	= wildfire_startup_irq,
 	.shutdown	= wildfire_disable_irq,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/mm/extable.c linux-libre-2.6.31-gnu/arch/alpha/mm/extable.c
--- linux-libre-2.6.30-gnu/arch/alpha/mm/extable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/mm/extable.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,27 @@
 	     cmp_ex, swap_ex);
 }
 
+#ifdef CONFIG_MODULES
+/*
+ * Any entry referring to the module init will be at the beginning or
+ * the end.
+ */
+void trim_init_extable(struct module *m)
+{
+	/*trim the beginning*/
+	while (m->num_exentries &&
+	       within_module_init(ex_to_addr(&m->extable[0]), m)) {
+		m->extable++;
+		m->num_exentries--;
+	}
+	/*trim the end*/
+	while (m->num_exentries &&
+	       within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]),
+				  m))
+		m->num_exentries--;
+}
+#endif /* CONFIG_MODULES */
+
 const struct exception_table_entry *
 search_extable(const struct exception_table_entry *first,
 	       const struct exception_table_entry *last,
diff -druN linux-libre-2.6.30-gnu/arch/alpha/mm/fault.c linux-libre-2.6.31-gnu/arch/alpha/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/alpha/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -146,7 +146,7 @@
 	/* If for any reason at all we couldn't handle the fault,
 	   make sure we exit gracefully rather than endlessly redo
 	   the fault.  */
-	fault = handle_mm_fault(mm, vma, address, cause > 0);
+	fault = handle_mm_fault(mm, vma, address, cause > 0 ? FAULT_FLAG_WRITE : 0);
 	up_read(&mm->mmap_sem);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
diff -druN linux-libre-2.6.30-gnu/arch/alpha/mm/numa.c linux-libre-2.6.31-gnu/arch/alpha/mm/numa.c
--- linux-libre-2.6.30-gnu/arch/alpha/mm/numa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/alpha/mm/numa.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,9 +28,9 @@
 #define DBGDCONT(args...)
 #endif
 
-#define for_each_mem_cluster(memdesc, cluster, i)		\
-	for ((cluster) = (memdesc)->cluster, (i) = 0;		\
-	     (i) < (memdesc)->numclusters; (i)++, (cluster)++)
+#define for_each_mem_cluster(memdesc, _cluster, i)		\
+	for ((_cluster) = (memdesc)->cluster, (i) = 0;		\
+	     (i) < (memdesc)->numclusters; (i)++, (_cluster)++)
 
 static void __init show_mem_layout(void)
 {
diff -druN linux-libre-2.6.30-gnu/arch/arm/boot/compressed/head.S linux-libre-2.6.31-gnu/arch/arm/boot/compressed/head.S
--- linux-libre-2.6.30-gnu/arch/arm/boot/compressed/head.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/boot/compressed/head.S	2009-09-09 18:13:59.000000000 -0400
@@ -438,6 +438,9 @@
 		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
 		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
 		orr	r0, r0, #0x0030
+#ifdef CONFIG_CPU_ENDIAN_BE8
+		orr	r0, r0, #1 << 25	@ big-endian page tables
+#endif
 		bl	__common_mmu_cache_on
 		mov	r0, #0
 		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
@@ -455,6 +458,9 @@
 		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
 		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
 		orr	r0, r0, #0x003c		@ write buffer
+#ifdef CONFIG_CPU_ENDIAN_BE8
+		orr	r0, r0, #1 << 25	@ big-endian page tables
+#endif
 		orrne	r0, r0, #1		@ MMU enabled
 		movne	r1, #-1
 		mcrne	p15, 0, r3, c2, c0, 0	@ load page table pointer
@@ -668,6 +674,15 @@
 		b	__armv4_mmu_cache_off
 		b	__armv5tej_mmu_cache_flush
 
+#ifdef CONFIG_CPU_FEROCEON_OLD_ID
+		/* this conflicts with the standard ARMv5TE entry */
+		.long	0x41009260		@ Old Feroceon
+		.long	0xff00fff0
+		b	__armv4_mmu_cache_on
+		b	__armv4_mmu_cache_off
+		b	__armv5tej_mmu_cache_flush
+#endif
+
 		.word	0x66015261		@ FA526
 		.word	0xff01fff1
 		b	__fa526_cache_on
diff -druN linux-libre-2.6.30-gnu/arch/arm/boot/compressed/Makefile linux-libre-2.6.31-gnu/arch/arm/boot/compressed/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/boot/compressed/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/boot/compressed/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 OBJS		+= head-sharpsl.o
 endif
 
-ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+ifeq ($(CONFIG_CPU_ENDIAN_BE32),y)
 ifeq ($(CONFIG_CPU_CP15),y)
 OBJS		+= big-endian.o
 else
@@ -78,6 +78,9 @@
 # linker symbols.  We only define initrd_phys and params_phys if the
 # machine class defined the corresponding makefile variable.
 LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR)
+ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
+LDFLAGS_vmlinux += --be8
+endif
 ifneq ($(INITRD_PHYS),)
 LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS)
 endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/boot/compressed/misc.c linux-libre-2.6.31-gnu/arch/arm/boot/compressed/misc.c
--- linux-libre-2.6.30-gnu/arch/arm/boot/compressed/misc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/boot/compressed/misc.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,6 @@
 
 static void putstr(const char *ptr);
 
-#include <linux/compiler.h>
 #include <mach/uncompress.h>
 
 #ifdef CONFIG_DEBUG_ICEDCC
diff -druN linux-libre-2.6.30-gnu/arch/arm/common/clkdev.c linux-libre-2.6.31-gnu/arch/arm/common/clkdev.c
--- linux-libre-2.6.30-gnu/arch/arm/common/clkdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/common/clkdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/mutex.h>
+#include <linux/clk.h>
 
 #include <asm/clkdev.h>
 #include <mach/clkdev.h>
@@ -135,6 +136,24 @@
 }
 EXPORT_SYMBOL(clkdev_alloc);
 
+int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
+	struct device *dev)
+{
+	struct clk *r = clk_get(dev, id);
+	struct clk_lookup *l;
+
+	if (IS_ERR(r))
+		return PTR_ERR(r);
+
+	l = clkdev_alloc(r, alias, alias_dev_name);
+	clk_put(r);
+	if (!l)
+		return -ENODEV;
+	clkdev_add(l);
+	return 0;
+}
+EXPORT_SYMBOL(clk_add_alias);
+
 /*
  * clkdev_drop - remove a clock dynamically allocated
  */
diff -druN linux-libre-2.6.30-gnu/arch/arm/common/gic.c linux-libre-2.6.31-gnu/arch/arm/common/gic.c
--- linux-libre-2.6.30-gnu/arch/arm/common/gic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/common/gic.c	2009-09-09 18:13:59.000000000 -0400
@@ -109,7 +109,7 @@
 }
 
 #ifdef CONFIG_SMP
-static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
+static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
 {
 	void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
 	unsigned int shift = (irq % 4) * 8;
@@ -117,11 +117,13 @@
 	u32 val;
 
 	spin_lock(&irq_controller_lock);
-	irq_desc[irq].cpu = cpu;
+	irq_desc[irq].node = cpu;
 	val = readl(reg) & ~(0xff << shift);
 	val |= 1 << (cpu + shift);
 	writel(val, reg);
 	spin_unlock(&irq_controller_lock);
+
+	return 0;
 }
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/common/Kconfig linux-libre-2.6.31-gnu/arch/arm/common/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/common/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/common/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -4,6 +4,14 @@
 config ARM_VIC
 	bool
 
+config ARM_VIC_NR
+	int
+	default 2
+	depends on ARM_VIC
+	help
+	  The maximum number of VICs available in the system, for
+	  power management.
+
 config ICST525
 	bool
 
@@ -27,10 +35,6 @@
 config SHARP_PARAM
 	bool
 
-config SHARPSL_PM
-	bool
-	select APM_EMULATION
-
 config SHARP_SCOOP
 	bool
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/common/Makefile linux-libre-2.6.31-gnu/arch/arm/common/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/common/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/common/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 obj-$(CONFIG_TIMER_ACORN)	+= time-acorn.o
 obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
 obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
-obj-$(CONFIG_SHARPSL_PM)	+= sharpsl_pm.o
 obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
 obj-$(CONFIG_ARCH_IXP2000)	+= uengine.o
 obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/common/sharpsl_pm.c linux-libre-2.6.31-gnu/arch/arm/common/sharpsl_pm.c
--- linux-libre-2.6.30-gnu/arch/arm/common/sharpsl_pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/common/sharpsl_pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,859 +0,0 @@
-/*
- * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00
- * series of PDAs
- *
- * Copyright (c) 2004-2005 Richard Purdie
- *
- * Based on code written by Sharp for 2.4 kernels
- *
- * 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.
- *
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/apm_bios.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/apm-emulation.h>
-#include <linux/suspend.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <mach/pm.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/regs-rtc.h>
-#include <mach/sharpsl.h>
-#include <asm/hardware/sharpsl_pm.h>
-
-/*
- * Constants
- */
-#define SHARPSL_CHARGE_ON_TIME_INTERVAL        (msecs_to_jiffies(1*60*1000))  /* 1 min */
-#define SHARPSL_CHARGE_FINISH_TIME             (msecs_to_jiffies(10*60*1000)) /* 10 min */
-#define SHARPSL_BATCHK_TIME                    (msecs_to_jiffies(15*1000))    /* 15 sec */
-#define SHARPSL_BATCHK_TIME_SUSPEND            (60*10)                        /* 10 min */
-
-#define SHARPSL_WAIT_CO_TIME                   15  /* 15 sec */
-#define SHARPSL_WAIT_DISCHARGE_ON              100 /* 100 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP   10  /* 10 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT   10  /* 10 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN   10  /* 10 msec */
-#define SHARPSL_CHARGE_WAIT_TIME               15  /* 15 msec */
-#define SHARPSL_CHARGE_CO_CHECK_TIME           5   /* 5 msec */
-#define SHARPSL_CHARGE_RETRY_CNT               1   /* eqv. 10 min */
-
-/*
- * Prototypes
- */
-#ifdef CONFIG_PM
-static int sharpsl_off_charge_battery(void);
-static int sharpsl_check_battery_voltage(void);
-static int sharpsl_fatal_check(void);
-#endif
-static int sharpsl_check_battery_temp(void);
-static int sharpsl_ac_check(void);
-static int sharpsl_average_value(int ad);
-static void sharpsl_average_clear(void);
-static void sharpsl_charge_toggle(struct work_struct *private_);
-static void sharpsl_battery_thread(struct work_struct *private_);
-
-
-/*
- * Variables
- */
-struct sharpsl_pm_status sharpsl_pm;
-DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
-DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
-DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
-
-
-static int get_percentage(int voltage)
-{
-	int i = sharpsl_pm.machinfo->bat_levels - 1;
-	int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
-	struct battery_thresh *thresh;
-
-	if (sharpsl_pm.charge_mode == CHRG_ON)
-		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
-	else
-		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
-
-	while (i > 0 && (voltage > thresh[i].voltage))
-		i--;
-
-	return thresh[i].percentage;
-}
-
-static int get_apm_status(int voltage)
-{
-	int low_thresh, high_thresh;
-
-	if (sharpsl_pm.charge_mode == CHRG_ON) {
-		high_thresh = sharpsl_pm.machinfo->status_high_acin;
-		low_thresh = sharpsl_pm.machinfo->status_low_acin;
-	} else {
-		high_thresh = sharpsl_pm.machinfo->status_high_noac;
-		low_thresh = sharpsl_pm.machinfo->status_low_noac;
-	}
-
-	if (voltage >= high_thresh)
-		return APM_BATTERY_STATUS_HIGH;
-	if (voltage >= low_thresh)
-		return APM_BATTERY_STATUS_LOW;
-	return APM_BATTERY_STATUS_CRITICAL;
-}
-
-void sharpsl_battery_kick(void)
-{
-	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
-}
-EXPORT_SYMBOL(sharpsl_battery_kick);
-
-
-static void sharpsl_battery_thread(struct work_struct *private_)
-{
-	int voltage, percent, apm_status, i = 0;
-
-	if (!sharpsl_pm.machinfo)
-		return;
-
-	sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
-
-	/* Corgi cannot confirm when battery fully charged so periodically kick! */
-	if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
-			&& time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
-		schedule_delayed_work(&toggle_charger, 0);
-
-	while(1) {
-		voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
-
-		if (voltage > 0) break;
-		if (i++ > 5) {
-			voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
-			dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
-			break;
-		}
-	}
-
-	voltage = sharpsl_average_value(voltage);
-	apm_status = get_apm_status(voltage);
-	percent = get_percentage(voltage);
-
-	/* At low battery voltages, the voltage has a tendency to start
-           creeping back up so we try to avoid this here */
-	if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) ||  percent <= sharpsl_pm.battstat.mainbat_percent) {
-		sharpsl_pm.battstat.mainbat_voltage = voltage;
-		sharpsl_pm.battstat.mainbat_status = apm_status;
-		sharpsl_pm.battstat.mainbat_percent = percent;
-	}
-
-	dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage,
-			sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
-
-#ifdef CONFIG_BACKLIGHT_CORGI
-	/* If battery is low. limit backlight intensity to save power. */
-	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
-			&& ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
-			(sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
-		if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
-			sharpsl_pm.machinfo->backlight_limit(1);
-			sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
-		}
-	} else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
-		sharpsl_pm.machinfo->backlight_limit(0);
-		sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
-	}
-#endif
-
-	/* Suspend if critical battery level */
-	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
-			&& (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
-			&& !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
-		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
-		dev_err(sharpsl_pm.dev, "Fatal Off\n");
-		apm_queue_event(APM_CRITICAL_SUSPEND);
-	}
-
-	schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
-}
-
-void sharpsl_pm_led(int val)
-{
-	if (val == SHARPSL_LED_ERROR) {
-		dev_err(sharpsl_pm.dev, "Charging Error!\n");
-	} else if (val == SHARPSL_LED_ON) {
-		dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
-		led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
-	} else {
-		dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
-		led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
-	}
-}
-
-static void sharpsl_charge_on(void)
-{
-	dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
-
-	sharpsl_pm.full_count = 0;
-	sharpsl_pm.charge_mode = CHRG_ON;
-	schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
-	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
-}
-
-static void sharpsl_charge_off(void)
-{
-	dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
-
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm_led(SHARPSL_LED_OFF);
-	sharpsl_pm.charge_mode = CHRG_OFF;
-
-	schedule_delayed_work(&sharpsl_bat, 0);
-}
-
-static void sharpsl_charge_error(void)
-{
-	sharpsl_pm_led(SHARPSL_LED_ERROR);
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm.charge_mode = CHRG_ERROR;
-}
-
-static void sharpsl_charge_toggle(struct work_struct *private_)
-{
-	dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies);
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
-		sharpsl_charge_off();
-		return;
-	} else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
-		sharpsl_charge_error();
-		return;
-	}
-
-	sharpsl_pm_led(SHARPSL_LED_ON);
-	sharpsl_pm.machinfo->charge(0);
-	mdelay(SHARPSL_CHARGE_WAIT_TIME);
-	sharpsl_pm.machinfo->charge(1);
-
-	sharpsl_pm.charge_start_time = jiffies;
-}
-
-static void sharpsl_ac_timer(unsigned long data)
-{
-	int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
-
-	dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin);
-
-	sharpsl_average_clear();
-	if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
-		sharpsl_charge_on();
-	else if (sharpsl_pm.charge_mode == CHRG_ON)
-		sharpsl_charge_off();
-
-	schedule_delayed_work(&sharpsl_bat, 0);
-}
-
-
-irqreturn_t sharpsl_ac_isr(int irq, void *dev_id)
-{
-	/* Delay the event slightly to debounce */
-	/* Must be a smaller delay than the chrg_full_isr below */
-	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
-
-	return IRQ_HANDLED;
-}
-
-static void sharpsl_chrg_full_timer(unsigned long data)
-{
-	dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
-
-	sharpsl_pm.full_count++;
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
-		dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
-		if (sharpsl_pm.charge_mode == CHRG_ON)
-			sharpsl_charge_off();
-	} else if (sharpsl_pm.full_count < 2) {
-		dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
-		schedule_delayed_work(&toggle_charger, 0);
-	} else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
-		dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
-		schedule_delayed_work(&toggle_charger, 0);
-	} else {
-		sharpsl_charge_off();
-		sharpsl_pm.charge_mode = CHRG_DONE;
-		dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
-	}
-}
-
-/* Charging Finished Interrupt (Not present on Corgi) */
-/* Can trigger at the same time as an AC status change so
-   delay until after that has been processed */
-irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
-{
-	if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
-		return IRQ_HANDLED;
-
-	/* delay until after any ac interrupt */
-	mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
-
-	return IRQ_HANDLED;
-}
-
-irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id)
-{
-	int is_fatal = 0;
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) {
-		dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
-		is_fatal = 1;
-	}
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) {
-		dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
-		is_fatal = 1;
-	}
-
-	if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
-		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
-		apm_queue_event(APM_CRITICAL_SUSPEND);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Maintain an average of the last 10 readings
- */
-#define SHARPSL_CNV_VALUE_NUM    10
-static int sharpsl_ad_index;
-
-static void sharpsl_average_clear(void)
-{
-	sharpsl_ad_index = 0;
-}
-
-static int sharpsl_average_value(int ad)
-{
-	int i, ad_val = 0;
-	static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
-
-	if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
-		sharpsl_ad_index = 0;
-		return ad;
-	}
-
-	sharpsl_ad[sharpsl_ad_index] = ad;
-	sharpsl_ad_index++;
-	if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
-		for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
-			sharpsl_ad[i] = sharpsl_ad[i+1];
-		sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
-	}
-	for (i=0; i < sharpsl_ad_index; i++)
-		ad_val += sharpsl_ad[i];
-
-	return (ad_val / sharpsl_ad_index);
-}
-
-/*
- * Take an array of 5 integers, remove the maximum and minimum values
- * and return the average.
- */
-static int get_select_val(int *val)
-{
-	int i, j, k, temp, sum = 0;
-
-	/* Find MAX val */
-	temp = val[0];
-	j=0;
-	for (i=1; i<5; i++) {
-		if (temp < val[i]) {
-			temp = val[i];
-			j = i;
-		}
-	}
-
-	/* Find MIN val */
-	temp = val[4];
-	k=4;
-	for (i=3; i>=0; i--) {
-		if (temp > val[i]) {
-			temp = val[i];
-			k = i;
-		}
-	}
-
-	for (i=0; i<5; i++)
-		if (i != j && i != k )
-			sum += val[i];
-
-	dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]);
-
-	return (sum/3);
-}
-
-static int sharpsl_check_battery_temp(void)
-{
-	int val, i, buff[5];
-
-	/* Check battery temperature */
-	for (i=0; i<5; i++) {
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
-		sharpsl_pm.machinfo->measure_temp(1);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP);
-		sharpsl_pm.machinfo->measure_temp(0);
-	}
-
-	val = get_select_val(buff);
-
-	dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
-	if (val > sharpsl_pm.machinfo->charge_on_temp) {
-		printk(KERN_WARNING "Not charging: temperature out of limits.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int sharpsl_check_battery_voltage(void)
-{
-	int val, i, buff[5];
-
-	/* disable charge, enable discharge */
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm.machinfo->discharge(1);
-	mdelay(SHARPSL_WAIT_DISCHARGE_ON);
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(1);
-
-	/* Check battery voltage */
-	for (i=0; i<5; i++) {
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
-	}
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(0);
-
-	sharpsl_pm.machinfo->discharge(0);
-
-	val = get_select_val(buff);
-	dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
-
-	if (val < sharpsl_pm.machinfo->charge_on_volt)
-		return -1;
-
-	return 0;
-}
-#endif
-
-static int sharpsl_ac_check(void)
-{
-	int temp, i, buff[5];
-
-	for (i=0; i<5; i++) {
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
-	}
-
-	temp = get_select_val(buff);
-	dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
-
-	if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
-		dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	sharpsl_pm.flags |= SHARPSL_SUSPENDED;
-	flush_scheduled_work();
-
-	if (sharpsl_pm.charge_mode == CHRG_ON)
-		sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
-	else
-		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
-
-	return 0;
-}
-
-static int sharpsl_pm_resume(struct platform_device *pdev)
-{
-	/* Clear the reset source indicators as they break the bootloader upon reboot */
-	RCSR = 0x0f;
-	sharpsl_average_clear();
-	sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
-	sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
-
-	return 0;
-}
-
-static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
-{
-	dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR);
-
-	dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
-	/* not charging and AC-IN! */
-
-	if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
-		dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
-		sharpsl_pm.charge_mode = CHRG_OFF;
-		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
-		sharpsl_off_charge_battery();
-	}
-
-	sharpsl_pm.machinfo->presuspend();
-
-	PEDR = 0xffffffff; /* clear it */
-
-	sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
-	if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
-		RTSR &= RTSR_ALE;
-		RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
-		dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR);
-		sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
-	} else if (alarm_enable) {
-		RTSR &= RTSR_ALE;
-		RTAR = alarm_time;
-		dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR);
-	} else {
-		dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
-	}
-
-	pxa_pm_enter(state);
-
-	sharpsl_pm.machinfo->postsuspend();
-
-	dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR);
-}
-
-static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
-{
-	if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) )
-	{
-		if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
-			dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
-			corgi_goto_sleep(alarm_time, alarm_enable, state);
-			return 1;
-		}
-		if(sharpsl_off_charge_battery()) {
-			dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
-			corgi_goto_sleep(alarm_time, alarm_enable, state);
-			return 1;
-		}
-		dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
-	}
-
-	if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) )
-	{
-		dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
-		corgi_goto_sleep(alarm_time, alarm_enable, state);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int corgi_pxa_pm_enter(suspend_state_t state)
-{
-	unsigned long alarm_time = RTAR;
-	unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
-
-	dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
-
-	corgi_goto_sleep(alarm_time, alarm_status, state);
-
-	while (corgi_enter_suspend(alarm_time,alarm_status,state))
-		{}
-
-	if (sharpsl_pm.machinfo->earlyresume)
-		sharpsl_pm.machinfo->earlyresume();
-
-	dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
-
-	return 0;
-}
-
-/*
- * Check for fatal battery errors
- * Fatal returns -1
- */
-static int sharpsl_fatal_check(void)
-{
-	int buff[5], temp, i, acin;
-
-	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
-
-	/* Check AC-Adapter */
-	acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
-
-	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
-		sharpsl_pm.machinfo->charge(0);
-		udelay(100);
-		sharpsl_pm.machinfo->discharge(1);	/* enable discharge */
-		mdelay(SHARPSL_WAIT_DISCHARGE_ON);
-	}
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(1);
-
-	/* Check battery : check inserting battery ? */
-	for (i=0; i<5; i++) {
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
-	}
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(0);
-
-	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
-		udelay(100);
-		sharpsl_pm.machinfo->charge(1);
-		sharpsl_pm.machinfo->discharge(0);
-	}
-
-	temp = get_select_val(buff);
-	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
-
-	if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
-			(!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
-		return -1;
-	return 0;
-}
-
-static int sharpsl_off_charge_error(void)
-{
-	dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm_led(SHARPSL_LED_ERROR);
-	sharpsl_pm.charge_mode = CHRG_ERROR;
-	return 1;
-}
-
-/*
- * Charging Control while suspended
- * Return 1 - go straight to sleep
- * Return 0 - sleep or wakeup depending on other factors
- */
-static int sharpsl_off_charge_battery(void)
-{
-	int time;
-
-	dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
-
-	if (sharpsl_pm.charge_mode == CHRG_OFF) {
-		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
-
-		/* AC Check */
-		if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
-			return sharpsl_off_charge_error();
-
-		/* Start Charging */
-		sharpsl_pm_led(SHARPSL_LED_ON);
-		sharpsl_pm.machinfo->charge(0);
-		mdelay(SHARPSL_CHARGE_WAIT_TIME);
-		sharpsl_pm.machinfo->charge(1);
-
-		sharpsl_pm.charge_mode = CHRG_ON;
-		sharpsl_pm.full_count = 0;
-
-		return 1;
-	} else if (sharpsl_pm.charge_mode != CHRG_ON) {
-		return 1;
-	}
-
-	if (sharpsl_pm.full_count == 0) {
-		int time;
-
-		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
-
-		if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
-			return sharpsl_off_charge_error();
-
-		sharpsl_pm.machinfo->charge(0);
-		mdelay(SHARPSL_CHARGE_WAIT_TIME);
-		sharpsl_pm.machinfo->charge(1);
-		sharpsl_pm.charge_mode = CHRG_ON;
-
-		mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
-
-		time = RCNR;
-		while(1) {
-			/* Check if any wakeup event had occurred */
-			if (sharpsl_pm.machinfo->charger_wakeup() != 0)
-				return 0;
-			/* Check for timeout */
-			if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
-				return 1;
-			if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
-				dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n");
-	   			sharpsl_pm.full_count++;
-				sharpsl_pm.machinfo->charge(0);
-				mdelay(SHARPSL_CHARGE_WAIT_TIME);
-				sharpsl_pm.machinfo->charge(1);
-				return 1;
-			}
-		}
-	}
-
-	dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
-
-	mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
-
-	time = RCNR;
-	while(1) {
-		/* Check if any wakeup event had occurred */
-		if (sharpsl_pm.machinfo->charger_wakeup() != 0)
-			return 0;
-		/* Check for timeout */
-		if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
-			if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
-				dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
-				sharpsl_pm.full_count = 0;
-			}
-			sharpsl_pm.full_count++;
-			return 1;
-		}
-		if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
-			dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
-			sharpsl_pm_led(SHARPSL_LED_OFF);
-			sharpsl_pm.machinfo->charge(0);
-			sharpsl_pm.charge_mode = CHRG_DONE;
-			return 1;
-		}
-	}
-}
-#else
-#define sharpsl_pm_suspend	NULL
-#define sharpsl_pm_resume	NULL
-#endif
-
-static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent);
-}
-
-static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage);
-}
-
-static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL);
-static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL);
-
-extern void (*apm_get_power_status)(struct apm_power_info *);
-
-static void sharpsl_apm_get_power_status(struct apm_power_info *info)
-{
-	info->ac_line_status = sharpsl_pm.battstat.ac_status;
-
-	if (sharpsl_pm.charge_mode == CHRG_ON)
-		info->battery_status = APM_BATTERY_STATUS_CHARGING;
-	else
-		info->battery_status = sharpsl_pm.battstat.mainbat_status;
-
-	info->battery_flag = (1 << info->battery_status);
-	info->battery_life = sharpsl_pm.battstat.mainbat_percent;
-}
-
-#ifdef CONFIG_PM
-static struct platform_suspend_ops sharpsl_pm_ops = {
-	.enter		= corgi_pxa_pm_enter,
-	.valid		= suspend_valid_only_mem,
-};
-#endif
-
-static int __init sharpsl_pm_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	sharpsl_pm.dev = &pdev->dev;
-	sharpsl_pm.machinfo = pdev->dev.platform_data;
-	sharpsl_pm.charge_mode = CHRG_OFF;
-	sharpsl_pm.flags = 0;
-
-	init_timer(&sharpsl_pm.ac_timer);
-	sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
-
-	init_timer(&sharpsl_pm.chrg_full_timer);
-	sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
-
-	led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
-
-	sharpsl_pm.machinfo->init();
-
-	ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage);
-	ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage);
-	if (ret != 0)
-		dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret);
-
-	apm_get_power_status = sharpsl_apm_get_power_status;
-
-#ifdef CONFIG_PM
-	suspend_set_ops(&sharpsl_pm_ops);
-#endif
-
-	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
-
-	return 0;
-}
-
-static int sharpsl_pm_remove(struct platform_device *pdev)
-{
-	suspend_set_ops(NULL);
-
-	device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
-	device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
-
-	led_trigger_unregister_simple(sharpsl_charge_led_trigger);
-
-	sharpsl_pm.machinfo->exit();
-
-	del_timer_sync(&sharpsl_pm.chrg_full_timer);
-	del_timer_sync(&sharpsl_pm.ac_timer);
-
-	return 0;
-}
-
-static struct platform_driver sharpsl_pm_driver = {
-	.probe		= sharpsl_pm_probe,
-	.remove		= sharpsl_pm_remove,
-	.suspend	= sharpsl_pm_suspend,
-	.resume		= sharpsl_pm_resume,
-	.driver		= {
-		.name		= "sharpsl-pm",
-	},
-};
-
-static int __devinit sharpsl_pm_init(void)
-{
-	return platform_driver_register(&sharpsl_pm_driver);
-}
-
-static void sharpsl_pm_exit(void)
-{
- 	platform_driver_unregister(&sharpsl_pm_driver);
-}
-
-late_initcall(sharpsl_pm_init);
-module_exit(sharpsl_pm_exit);
diff -druN linux-libre-2.6.30-gnu/arch/arm/common/vic.c linux-libre-2.6.31-gnu/arch/arm/common/vic.c
--- linux-libre-2.6.30-gnu/arch/arm/common/vic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/common/vic.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/io.h>
+#include <linux/sysdev.h>
 
 #include <asm/mach/irq.h>
 #include <asm/hardware/vic.h>
@@ -39,11 +40,223 @@
 	writel(1 << irq, base + VIC_INT_ENABLE);
 }
 
+/**
+ * vic_init2 - common initialisation code
+ * @base: Base of the VIC.
+ *
+ * Common initialisation code for registeration
+ * and resume.
+*/
+static void vic_init2(void __iomem *base)
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
+		writel(VIC_VECT_CNTL_ENABLE | i, reg);
+	}
+
+	writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+}
+
+#if defined(CONFIG_PM)
+/**
+ * struct vic_device - VIC PM device
+ * @sysdev: The system device which is registered.
+ * @irq: The IRQ number for the base of the VIC.
+ * @base: The register base for the VIC.
+ * @resume_sources: A bitmask of interrupts for resume.
+ * @resume_irqs: The IRQs enabled for resume.
+ * @int_select: Save for VIC_INT_SELECT.
+ * @int_enable: Save for VIC_INT_ENABLE.
+ * @soft_int: Save for VIC_INT_SOFT.
+ * @protect: Save for VIC_PROTECT.
+ */
+struct vic_device {
+	struct sys_device sysdev;
+
+	void __iomem	*base;
+	int		irq;
+	u32		resume_sources;
+	u32		resume_irqs;
+	u32		int_select;
+	u32		int_enable;
+	u32		soft_int;
+	u32		protect;
+};
+
+/* we cannot allocate memory when VICs are initially registered */
+static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
+
+static inline struct vic_device *to_vic(struct sys_device *sys)
+{
+	return container_of(sys, struct vic_device, sysdev);
+}
+
+static int vic_id;
+
+static int vic_class_resume(struct sys_device *dev)
+{
+	struct vic_device *vic = to_vic(dev);
+	void __iomem *base = vic->base;
+
+	printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
+
+	/* re-initialise static settings */
+	vic_init2(base);
+
+	writel(vic->int_select, base + VIC_INT_SELECT);
+	writel(vic->protect, base + VIC_PROTECT);
+
+	/* set the enabled ints and then clear the non-enabled */
+	writel(vic->int_enable, base + VIC_INT_ENABLE);
+	writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR);
+
+	/* and the same for the soft-int register */
+
+	writel(vic->soft_int, base + VIC_INT_SOFT);
+	writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
+
+	return 0;
+}
+
+static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct vic_device *vic = to_vic(dev);
+	void __iomem *base = vic->base;
+
+	printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
+
+	vic->int_select = readl(base + VIC_INT_SELECT);
+	vic->int_enable = readl(base + VIC_INT_ENABLE);
+	vic->soft_int = readl(base + VIC_INT_SOFT);
+	vic->protect = readl(base + VIC_PROTECT);
+
+	/* set the interrupts (if any) that are used for
+	 * resuming the system */
+
+	writel(vic->resume_irqs, base + VIC_INT_ENABLE);
+	writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
+
+	return 0;
+}
+
+struct sysdev_class vic_class = {
+	.name		= "vic",
+	.suspend	= vic_class_suspend,
+	.resume		= vic_class_resume,
+};
+
+/**
+ * vic_pm_register - Register a VIC for later power management control
+ * @base: The base address of the VIC.
+ * @irq: The base IRQ for the VIC.
+ * @resume_sources: bitmask of interrupts allowed for resume sources.
+ *
+ * Register the VIC with the system device tree so that it can be notified
+ * of suspend and resume requests and ensure that the correct actions are
+ * taken to re-instate the settings on resume.
+ */
+static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
+{
+	struct vic_device *v;
+
+	if (vic_id >= ARRAY_SIZE(vic_devices))
+		printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
+	else {
+		v = &vic_devices[vic_id];
+		v->base = base;
+		v->resume_sources = resume_sources;
+		v->irq = irq;
+		vic_id++;
+	}
+}
+
+/**
+ * vic_pm_init - initicall to register VIC pm
+ *
+ * This is called via late_initcall() to register
+ * the resources for the VICs due to the early
+ * nature of the VIC's registration.
+*/
+static int __init vic_pm_init(void)
+{
+	struct vic_device *dev = vic_devices;
+	int err;
+	int id;
+
+	if (vic_id == 0)
+		return 0;
+
+	err = sysdev_class_register(&vic_class);
+	if (err) {
+		printk(KERN_ERR "%s: cannot register class\n", __func__);
+		return err;
+	}
+
+	for (id = 0; id < vic_id; id++, dev++) {
+		dev->sysdev.id = id;
+		dev->sysdev.cls = &vic_class;
+
+		err = sysdev_register(&dev->sysdev);
+		if (err) {
+			printk(KERN_ERR "%s: failed to register device\n",
+			       __func__);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+late_initcall(vic_pm_init);
+
+static struct vic_device *vic_from_irq(unsigned int irq)
+{
+        struct vic_device *v = vic_devices;
+	unsigned int base_irq = irq & ~31;
+	int id;
+
+	for (id = 0; id < vic_id; id++, v++) {
+		if (v->irq == base_irq)
+			return v;
+	}
+
+	return NULL;
+}
+
+static int vic_set_wake(unsigned int irq, unsigned int on)
+{
+	struct vic_device *v = vic_from_irq(irq);
+	unsigned int off = irq & 31;
+	u32 bit = 1 << off;
+
+	if (!v)
+		return -EINVAL;
+
+	if (!(bit & v->resume_sources))
+		return -EINVAL;
+
+	if (on)
+		v->resume_irqs |= bit;
+	else
+		v->resume_irqs &= ~bit;
+
+	return 0;
+}
+
+#else
+static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
+
+#define vic_set_wake NULL
+#endif /* CONFIG_PM */
+
 static struct irq_chip vic_chip = {
 	.name	= "VIC",
 	.ack	= vic_mask_irq,
 	.mask	= vic_mask_irq,
 	.unmask	= vic_unmask_irq,
+	.set_wake = vic_set_wake,
 };
 
 /**
@@ -51,9 +264,10 @@
  * @base: iomem base address
  * @irq_start: starting interrupt number, must be muliple of 32
  * @vic_sources: bitmask of interrupt sources to allow
+ * @resume_sources: bitmask of interrupt sources to allow for resume
  */
 void __init vic_init(void __iomem *base, unsigned int irq_start,
-		     u32 vic_sources)
+		     u32 vic_sources, u32 resume_sources)
 {
 	unsigned int i;
 
@@ -77,12 +291,7 @@
 		writel(value, base + VIC_PL190_VECT_ADDR);
 	}
 
-	for (i = 0; i < 16; i++) {
-		void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
-		writel(VIC_VECT_CNTL_ENABLE | i, reg);
-	}
-
-	writel(32, base + VIC_PL190_DEF_VECT_ADDR);
+	vic_init2(base);
 
 	for (i = 0; i < 32; i++) {
 		if (vic_sources & (1 << i)) {
@@ -94,4 +303,6 @@
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
 	}
+
+	vic_pm_register(base, irq_start, resume_sources);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/cm_x300_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/cm_x300_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/cm_x300_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/cm_x300_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc3
-# Tue Aug 19 11:26:54 2008
+# Linux kernel version: 2.6.30-rc8
+# Thu Jun  4 09:53:21 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -22,8 +22,6 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
@@ -44,15 +42,24 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=18
-# CONFIG_CGROUPS is not set
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -61,31 +68,37 @@
 # CONFIG_IPC_NS is not set
 # CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
@@ -93,19 +106,13 @@
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
 CONFIG_HAVE_CLK=y
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -113,11 +120,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -133,7 +137,7 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
 
 #
 # System Type
@@ -143,10 +147,10 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
@@ -167,14 +171,17 @@
 # CONFIG_ARCH_ORION5X is not set
 # CONFIG_ARCH_PNX4008 is not set
 CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_MMP is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Intel PXA2xx/PXA3xx Implementations
@@ -187,16 +194,24 @@
 # CONFIG_CPU_PXA310 is not set
 # CONFIG_CPU_PXA320 is not set
 # CONFIG_CPU_PXA930 is not set
+# CONFIG_CPU_PXA935 is not set
 # CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
 # CONFIG_ARCH_LUBBOCK is not set
 # CONFIG_MACH_LOGICPD_PXA270 is not set
 # CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_MP900C is not set
 # CONFIG_ARCH_PXA_IDP is not set
 # CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_VIPER is not set
 # CONFIG_ARCH_PXA_ESERIES is not set
-# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_H5000 is not set
 # CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_EXEDA is not set
 # CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_COLIBRI300 is not set
+# CONFIG_MACH_COLIBRI320 is not set
 # CONFIG_MACH_ZYLONITE is not set
 # CONFIG_MACH_LITTLETON is not set
 # CONFIG_MACH_TAVOREVB is not set
@@ -204,19 +219,15 @@
 # CONFIG_MACH_ARMCORE is not set
 CONFIG_MACH_CM_X300=y
 # CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_HIMALAYA is not set
+# CONFIG_MACH_MIOA701 is not set
 # CONFIG_MACH_PCM027 is not set
 # CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_MACH_CSB726 is not set
 # CONFIG_PXA_EZX is not set
 CONFIG_PXA3xx=y
 # CONFIG_PXA_PWM is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+CONFIG_PLAT_PXA=y
 
 #
 # Processor Type
@@ -241,6 +252,7 @@
 CONFIG_OUTER_CACHE=y
 CONFIG_CACHE_XSC3L2=y
 CONFIG_IWMMXT=y
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
@@ -256,25 +268,33 @@
 CONFIG_NO_HZ=y
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 # CONFIG_PREEMPT is not set
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HIGHMEM=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -287,7 +307,7 @@
 # CONFIG_KEXEC is not set
 
 #
-# CPU Frequency scaling
+# CPU Power Management
 #
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
@@ -304,6 +324,7 @@
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
 # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_IDLE is not set
 
 #
 # Floating point emulation
@@ -320,6 +341,8 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
@@ -376,6 +399,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -385,7 +409,9 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -407,8 +433,7 @@
 #
 # Bluetooth device drivers
 #
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIBTUSB is not set
 # CONFIG_BT_HCIBTSDIO is not set
 # CONFIG_BT_HCIUART is not set
 # CONFIG_BT_HCIBCM203X is not set
@@ -416,19 +441,15 @@
 # CONFIG_BT_HCIBFUSB is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
 # CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -453,6 +474,7 @@
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 # CONFIG_MTD_AFS_PARTS is not set
@@ -494,7 +516,6 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_SHARP_SL is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -516,16 +537,23 @@
 # CONFIG_MTD_NAND_ECC_SMC is not set
 # CONFIG_MTD_NAND_MUSEUM_IDS is not set
 # CONFIG_MTD_NAND_H1900 is not set
+# CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_SHARPSL is not set
 CONFIG_MTD_NAND_PXA3xx=y
+# CONFIG_MTD_NAND_PXA3xx_BUILTIN is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
 # CONFIG_MTD_NAND_PLATFORM is not set
 # CONFIG_MTD_ALAUDA is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -585,11 +613,15 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -604,11 +636,17 @@
 CONFIG_DM9000=y
 CONFIG_DM9000_DEBUGLEVEL=0
 CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_ETHOC is not set
 # CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
@@ -624,10 +662,13 @@
 # CONFIG_LIBERTAS_DEBUG is not set
 # CONFIG_USB_ZD1201 is not set
 # CONFIG_USB_NET_RNDIS_WLAN is not set
-# CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_HOSTAP is not set
 
 #
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -677,18 +718,21 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
 # CONFIG_TOUCHSCREEN_INEXIO is not set
 # CONFIG_TOUCHSCREEN_MK712 is not set
 # CONFIG_TOUCHSCREEN_PENMOUNT is not set
 # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
-# CONFIG_TOUCHSCREEN_UCB1400 is not set
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -721,10 +765,10 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
@@ -763,12 +807,8 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -782,6 +822,10 @@
 # CONFIG_GPIO_SYSFS is not set
 
 #
+# Memory mapped GPIO expanders:
+#
+
+#
 # I2C GPIO expanders:
 #
 # CONFIG_GPIO_MAX732X is not set
@@ -798,12 +842,14 @@
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
@@ -811,12 +857,19 @@
 #
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_T7L66XB is not set
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
@@ -842,6 +895,7 @@
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -862,12 +916,15 @@
 #
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_OVERLAY is not set
 # CONFIG_FB_PXA_SMARTPANEL is not set
 # CONFIG_FB_PXA_PARAMETERS is not set
 # CONFIG_FB_MBX is not set
 # CONFIG_FB_W100 is not set
-# CONFIG_FB_AM200EPD is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -899,9 +956,11 @@
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
 CONFIG_SOUND=m
+# CONFIG_SOUND_OSS_CORE is not set
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
+CONFIG_SND_JACK=y
 # CONFIG_SND_SEQUENCER is not set
 # CONFIG_SND_MIXER_OSS is not set
 # CONFIG_SND_PCM_OSS is not set
@@ -916,12 +975,15 @@
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
 CONFIG_SND_ARM=y
+CONFIG_SND_PXA2XX_LIB=m
 # CONFIG_SND_PXA2XX_AC97 is not set
 CONFIG_SND_USB=y
 # CONFIG_SND_USB_AUDIO is not set
 # CONFIG_SND_USB_CAIAQ is not set
 CONFIG_SND_SOC=m
 CONFIG_SND_PXA2XX_SOC=m
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
 # CONFIG_SOUND_PRIME is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
@@ -932,9 +994,39 @@
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
 # CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -952,11 +1044,14 @@
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
@@ -965,6 +1060,7 @@
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 # CONFIG_USB_MUSB_HDRC is not set
 
 #
@@ -973,20 +1069,20 @@
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
@@ -994,7 +1090,6 @@
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_ONETOUCH is not set
 # CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_SIERRA is not set
 # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
@@ -1015,6 +1110,7 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -1022,7 +1118,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -1031,13 +1126,20 @@
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=m
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
 #
 CONFIG_MMC_BLOCK=m
 CONFIG_MMC_BLOCK_BOUNCE=y
@@ -1045,10 +1147,12 @@
 # CONFIG_MMC_TEST is not set
 
 #
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
 #
 CONFIG_MMC_PXA=m
 # CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 
@@ -1057,7 +1161,10 @@
 #
 # CONFIG_LEDS_PCA9532 is not set
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
 # CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
 
 #
 # LED Triggers
@@ -1065,7 +1172,13 @@
 CONFIG_LEDS_TRIGGERS=y
 # CONFIG_LEDS_TRIGGER_TIMER is not set
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
 # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1096,6 +1209,7 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
@@ -1105,28 +1219,27 @@
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+CONFIG_RTC_DRV_V3020=y
 
 #
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_PXA is not set
 # CONFIG_DMADEVICES is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1135,15 +1248,18 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1153,6 +1269,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1173,15 +1294,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1201,6 +1320,7 @@
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1209,6 +1329,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1313,6 +1434,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1329,6 +1451,7 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
@@ -1336,22 +1459,38 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_ERRORS is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1363,17 +1502,28 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
 
 #
 # Crypto core or helper
 #
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_AUTHENC is not set
 # CONFIG_CRYPTO_TEST is not set
@@ -1442,15 +1592,21 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC_T10DIF=y
@@ -1460,7 +1616,10 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/davinci_all_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/davinci_all_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/davinci_all_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/davinci_all_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Wed Apr 15 08:16:53 2009
+# Linux kernel version: 2.6.30-rc7
+# Tue May 26 07:24:28 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -179,6 +179,7 @@
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_W90X900 is not set
+CONFIG_AINTC=y
 
 #
 # TI DaVinci Implementations
@@ -188,11 +189,17 @@
 # DaVinci Core Type
 #
 CONFIG_ARCH_DAVINCI_DM644x=y
+CONFIG_ARCH_DAVINCI_DM355=y
+CONFIG_ARCH_DAVINCI_DM646x=y
 
 #
 # DaVinci Board Type
 #
 CONFIG_MACH_DAVINCI_EVM=y
+CONFIG_MACH_SFFSDR=y
+CONFIG_MACH_DAVINCI_DM355_EVM=y
+CONFIG_MACH_DM355_LEOPARD=y
+CONFIG_MACH_DAVINCI_DM6467_EVM=y
 CONFIG_DAVINCI_MUX=y
 CONFIG_DAVINCI_MUX_DEBUG=y
 CONFIG_DAVINCI_MUX_WARNINGS=y
@@ -245,7 +252,7 @@
 CONFIG_HZ=100
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 # CONFIG_HIGHMEM is not set
@@ -661,7 +668,10 @@
 CONFIG_MII=y
 # CONFIG_AX88796 is not set
 # CONFIG_SMC91X is not set
-# CONFIG_DM9000 is not set
+CONFIG_TI_DAVINCI_EMAC=y
+CONFIG_DM9000=y
+CONFIG_DM9000_DEBUGLEVEL=4
+# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
 # CONFIG_ETHOC is not set
 # CONFIG_SMC911X is not set
 # CONFIG_SMSC911X is not set
@@ -963,6 +973,7 @@
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_MFD_ASIC3 is not set
+# CONFIG_MFD_DM355EVM_MSP is not set
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_TPS65010 is not set
@@ -1317,6 +1328,7 @@
 # MMC/SD/SDIO Host Controller Drivers
 #
 # CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_DAVINCI is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
@@ -1778,6 +1790,7 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_DECOMPRESS_GZIP=y
+CONFIG_GENERIC_ALLOCATOR=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/ep93xx_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/ep93xx_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/ep93xx_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/ep93xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,12 +1,19 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc1
-# Sat Dec 16 06:05:24 2006
+# Linux kernel version: 2.6.30-rc3
+# Tue May 19 12:26:49 2009
 #
 CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
 # CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
 CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -15,42 +22,54 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 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_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -58,31 +77,38 @@
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=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_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-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
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -96,6 +122,7 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_FREEZER is not set
 
 #
 # System Type
@@ -105,29 +132,40 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 CONFIG_ARCH_EP93XX=y
 # CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
 # CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
-# CONFIG_ARCH_IOP13XX is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
 
 #
@@ -138,14 +176,24 @@
 #
 # EP93xx Platforms
 #
+# CONFIG_EP93XX_SDCE0_PHYS_OFFSET is not set
+CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET=y
 CONFIG_MACH_ADSSPHERE=y
+CONFIG_MACH_EDB93XX=y
+CONFIG_MACH_EDB9301=y
 CONFIG_MACH_EDB9302=y
-CONFIG_MACH_EDB9302A=y
+CONFIG_MACH_EDB9307=y
 CONFIG_MACH_EDB9312=y
 CONFIG_MACH_EDB9315=y
-CONFIG_MACH_EDB9315A=y
 CONFIG_MACH_GESBC9312=y
+CONFIG_MACH_MICRO9=y
+CONFIG_MACH_MICRO9H=y
+CONFIG_MACH_MICRO9M=y
+CONFIG_MACH_MICRO9L=y
 CONFIG_MACH_TS72XX=y
+CONFIG_EP93XX_EARLY_UART1=y
+# CONFIG_EP93XX_EARLY_UART2 is not set
+# CONFIG_EP93XX_EARLY_UART3 is not set
 
 #
 # Processor Type
@@ -154,6 +202,7 @@
 CONFIG_CPU_ARM920T=y
 CONFIG_CPU_32v4T=y
 CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_NOIFAR=y
 CONFIG_CPU_CACHE_V4WT=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_COPY_V4WB=y
@@ -168,34 +217,47 @@
 # CONFIG_CPU_ICACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
 CONFIG_ARM_VIC=y
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
 #
 CONFIG_ARM_AMBA=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCCARD is not set
 
 #
 # Kernel Features
 #
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 # CONFIG_PREEMPT is not set
 CONFIG_HZ=100
-# CONFIG_AEABI is not set
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -205,6 +267,12 @@
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="console=ttyAM0,115200 root=/dev/nfs ip=bootp"
 # CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
 
 #
 # Floating point emulation
@@ -221,32 +289,31 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
-# CONFIG_APM is not set
-
-#
-# Networking
-#
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_NET=y
 
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 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_XFRM_STATISTICS is not set
 CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -267,6 +334,7 @@
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -276,6 +344,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
@@ -289,25 +358,15 @@
 # CONFIG_IPV6_SIT is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -317,20 +376,28 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN 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_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -339,41 +406,39 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # 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=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 CONFIG_MTD_REDBOOT_PARTS=y
 CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
 # CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
 # CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
 #
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -404,16 +469,13 @@
 # CONFIG_MTD_RAM is not set
 CONFIG_MTD_ROM=y
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -431,49 +493,58 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_VERIFY_WRITE=y
 # CONFIG_MTD_NAND_ECC_SMC is not set
-CONFIG_MTD_NAND_TS7250=y
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_TS7250 is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
-
-#
-# OneNAND Flash Device Drivers
-#
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
+# LPDDR flash memory drivers
 #
+# CONFIG_MTD_LPDDR is not set
 
 #
-# Block devices
+# UBI - Unsorted block images
 #
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 CONFIG_BLK_DEV_NBD=y
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_SCSI_PROC_FS is not set
@@ -495,6 +566,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -502,92 +574,71 @@
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # 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
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
+# CONFIG_VETH is not set
 # CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_EP93XX_ETH=y
+# CONFIG_AX88796 is not set
 # CONFIG_SMC91X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
 
 #
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
+# Wireless LAN
 #
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Enable WiMAX (Networking options) to see the WiMAX drivers
 #
-# CONFIG_NET_RADIO is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_RTL8150=y
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
 # CONFIG_ISDN is not set
 
 #
@@ -605,6 +656,7 @@
 # Character devices
 #
 # CONFIG_VT is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -621,104 +673,101 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_EP93XX_WATCHDOG=y
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
 
 #
-# TPM devices
+# I2C Hardware Bus support
 #
-# CONFIG_TCG_TPM is not set
 
 #
-# I2C support
+# I2C system bus drivers (mostly embedded / system-on-chip)
 #
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
 
 #
-# I2C Algorithms
+# External I2C/SMBus adapter drivers
 #
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
 
 #
-# I2C Hardware Bus support
+# Other I2C/SMBus bus drivers
 #
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
 # CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_EEPROM_LEGACY=y
+# CONFIG_DS1682 is not set
 # CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
 CONFIG_I2C_DEBUG_CORE=y
 CONFIG_I2C_DEBUG_ALGO=y
 CONFIG_I2C_DEBUG_BUS=y
 CONFIG_I2C_DEBUG_CHIP=y
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
 
 #
-# SPI support
+# Memory mapped GPIO expanders:
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
 
 #
-# Dallas's 1-wire bus
+# I2C GPIO expanders:
 #
-# CONFIG_W1 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
 
 #
-# Hardware Monitoring support
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
 #
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -732,158 +781,188 @@
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
 
 #
-# Misc devices
+# Watchdog Device Drivers
 #
-# CONFIG_TIFM_CORE is not set
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
 
 #
-# LED devices
+# USB-based Watchdog Cards
 #
-# CONFIG_NEW_LEDS is not set
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
-# LED drivers
+# Sonics Silicon Backplane
 #
+# CONFIG_SSB is not set
 
 #
-# LED Triggers
+# Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
 
 #
-# Digital Video Broadcasting Devices
+# Multimedia drivers
 #
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 # CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
-# Sound
+# Display device support
 #
+# CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_SOUND is not set
-
-#
-# USB support
-#
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
 CONFIG_USB_DYNAMIC_MINORS=y
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
-# USB Input Devices
-#
-
-#
-# USB HID Boot Protocol drivers
-#
-
-#
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-CONFIG_USB_RTL8150=y
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
-
-#
 # USB port drivers
 #
-
-#
-# USB Serial Converter support
-#
 CONFIG_USB_SERIAL=y
 CONFIG_USB_SERIAL_CONSOLE=y
+# CONFIG_USB_EZUSB is not set
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_AIRCABLE is not set
-# CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ARK3116 is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
 # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CP210X is not set
 # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
@@ -895,6 +974,7 @@
 # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
 # CONFIG_USB_SERIAL_GARMIN is not set
 # CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
 # CONFIG_USB_SERIAL_KEYSPAN is not set
 # CONFIG_USB_SERIAL_KLSI is not set
@@ -902,16 +982,23 @@
 # CONFIG_USB_SERIAL_MCT_U232 is not set
 # CONFIG_USB_SERIAL_MOS7720 is not set
 # CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
 # CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=y
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
 # CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
 # CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
 # CONFIG_USB_SERIAL_TI is not set
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OPTION is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
 # CONFIG_USB_SERIAL_DEBUG is not set
 
 #
@@ -920,38 +1007,34 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
 # 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
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY 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
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
 
 #
-# MMC/SD Card support
+# OTG and related infrastructure
 #
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_MMC is not set
-
-#
-# Real Time Clock
-#
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -965,24 +1048,55 @@
 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
 
 #
-# RTC drivers
+# I2C RTC drivers
 #
-# CONFIG_RTC_DRV_X1205 is not set
 CONFIG_RTC_DRV_DS1307=y
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 CONFIG_RTC_DRV_M48T86=y
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
 CONFIG_RTC_DRV_EP93XX=y
+# CONFIG_RTC_DRV_PL030 is not set
 # CONFIG_RTC_DRV_PL031 is not set
-# CONFIG_RTC_DRV_TEST is not set
-# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -991,27 +1105,31 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
 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 is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1032,16 +1150,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1049,33 +1164,35 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 # CONFIG_JFFS2_SUMMARY is not set
 # CONFIG_JFFS2_FS_XATTR is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 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 is not set
 CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
@@ -1087,7 +1204,6 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -1109,10 +1225,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
+# CONFIG_SYSV68_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=y
@@ -1153,49 +1266,83 @@
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
 #
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 CONFIG_DEBUG_SLAB=y
 # CONFIG_DEBUG_SLAB_LEAK is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
-CONFIG_FRAME_POINTER=y
-CONFIG_FORCED_INLINING=y
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
 
@@ -1204,21 +1351,115 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
 
 #
-# Cryptographic options
+# Crypto core or helper
 #
-# CONFIG_CRYPTO is not set
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 CONFIG_LIBCRC32C=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/kb9202_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/kb9202_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/kb9202_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/kb9202_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,109 +1,246 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Sun Aug 14 19:26:59 2005
+# Linux kernel version: 2.6.30-rc8
+# Wed Jun  3 13:52:33 2009
 #
 CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-CONFIG_UID16=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
+CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
 
 #
-# General setup
+# RCU Subsystem
 #
-CONFIG_LOCALVERSION=""
-# CONFIG_SWAP is not set
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-# CONFIG_KOBJECT_UEVENT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS 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_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
-# Loadable module support
+# IO Schedulers
 #
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
 
 #
 # System Type
 #
-# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
 # CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP3XX is not set
-# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_AAEC2000 is not set
-CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
 CONFIG_ARCH_AT91RM9200=y
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+# CONFIG_ARCH_AT91SAM9263 is not set
+# CONFIG_ARCH_AT91SAM9RL is not set
+# CONFIG_ARCH_AT91SAM9G20 is not set
+# CONFIG_ARCH_AT91CAP9 is not set
+# CONFIG_ARCH_AT91X40 is not set
+CONFIG_AT91_PMC_UNIT=y
 
 #
-# AT91RM9200 Implementations
+# AT91RM9200 Board Type
 #
+# CONFIG_MACH_ONEARM is not set
 # CONFIG_ARCH_AT91RM9200DK is not set
 # CONFIG_MACH_AT91RM9200EK is not set
 # CONFIG_MACH_CSB337 is not set
 # CONFIG_MACH_CSB637 is not set
 # CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_ATEB9200 is not set
 CONFIG_MACH_KB9200=y
+# CONFIG_MACH_PICOTUX2XX is not set
+# CONFIG_MACH_KAFA is not set
+# CONFIG_MACH_ECBAT91 is not set
+# CONFIG_MACH_YL9200 is not set
+
+#
+# AT91 Board Options
+#
+
+#
+# AT91 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_TIMER_HZ=128
+CONFIG_AT91_EARLY_DBGU=y
+# CONFIG_AT91_EARLY_USART0 is not set
+# CONFIG_AT91_EARLY_USART1 is not set
+# CONFIG_AT91_EARLY_USART2 is not set
+# CONFIG_AT91_EARLY_USART3 is not set
+# CONFIG_AT91_EARLY_USART4 is not set
+# CONFIG_AT91_EARLY_USART5 is not set
 
 #
 # Processor Type
 #
 CONFIG_CPU_32=y
 CONFIG_CPU_ARM920T=y
-CONFIG_CPU_32v4=y
+CONFIG_CPU_32v4T=y
 CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_NOIFAR=y
 CONFIG_CPU_CACHE_V4WT=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_COPY_V4WB=y
 CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
 
 #
 # Processor Features
@@ -112,23 +249,48 @@
 # CONFIG_CPU_ICACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
 
 #
 # Bus support
 #
-CONFIG_ISA_DMA_API=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCCARD is not set
 
 #
 # Kernel Features
 #
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 # CONFIG_LEDS is not set
 CONFIG_ALIGNMENT_TRAP=y
 
@@ -137,8 +299,16 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x10000000
 CONFIG_ZBOOT_ROM_BSS=0x20040000
-CONFIG_ZBOOT_ROM=y
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_CMDLINE="noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
 
 #
 # Floating point emulation
@@ -149,19 +319,93 @@
 #
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
 
 #
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
 CONFIG_BINFMT_MISC=y
-# CONFIG_ARTHUR is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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=y
+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_ARPD 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 is not set
+# 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_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -170,53 +414,156 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-CONFIG_DEBUG_DRIVER=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
-# Memory Technology Devices (MTD)
+# User Modules And Translation Layers
 #
-# CONFIG_MTD is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
-# Parallel port support
+# RAM/ROM/Flash chip drivers
 #
-# CONFIG_PARPORT is not set
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
 
 #
-# Plug and Play support
+# Mapping drivers for chip access
 #
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
-# Block devices
+# Self-contained MTD device drivers
 #
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_ATMEL=y
+# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set
+CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
+# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_ATMEL_TCB_CLKSRC=y
+CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0
+CONFIG_ATMEL_SSC=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 
 #
-# IO Schedulers
+# EEPROM support
 #
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -232,145 +579,87 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-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_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_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_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# 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
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_ARM_AT91_ETHER=y
+# CONFIG_AX88796 is not set
 # CONFIG_SMC91X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
+# Wireless LAN
 #
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Enable WiMAX (Networking options) to see the WiMAX drivers
 #
-# CONFIG_NET_RADIO is not set
 
 #
-# Wan interfaces
+# USB Network Adapters
 #
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-
-#
-# ISDN subsystem
-#
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_ISDN is not set
 
 #
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -380,7 +669,6 @@
 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
 
@@ -390,23 +678,25 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -419,215 +709,362 @@
 #
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_ATMEL_PDC=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
 
 #
-# IPMI
+# Memory mapped GPIO expanders:
 #
-# CONFIG_IPMI_HANDLER is not set
 
 #
-# Watchdog Cards
+# I2C GPIO expanders:
 #
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_AT91RM9200_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
 
 #
-# Ftape, the floppy tape device driver
+# PCI GPIO expanders:
 #
-# CONFIG_RAW_DRIVER is not set
 
 #
-# TPM devices
+# SPI GPIO expanders:
 #
-# CONFIG_AT91_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
 
 #
-# I2C support
+# Watchdog Device Drivers
 #
-# CONFIG_I2C is not set
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91RM9200_WATCHDOG=y
 
 #
-# Misc devices
+# USB-based Watchdog Cards
 #
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
 
 #
-# Digital Video Broadcasting Devices
+# Multimedia drivers
 #
-# CONFIG_DVB is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
 
 #
-# Console display driver support
+# Frame buffer hardware drivers
 #
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
 
 #
-# Sound
+# Display device support
 #
-# CONFIG_SOUND is not set
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
-# USB support
+# Console display driver support
 #
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
 
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-
-#
-# USB Input Devices
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
-# CONFIG_USB_HID is not set
 
 #
-# USB HID Boot Protocol drivers
+# also be needed; see USB_STORAGE Help for more info
 #
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
 
 #
 # USB Imaging devices
 #
+# CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
+# USB port drivers
 #
-# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_SERIAL is not set
 
 #
-# Video4Linux support is needed for USB Multimedia device support
+# USB Miscellaneous drivers
 #
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY 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
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
 
 #
-# USB Network Adapters
+# OTG and related infrastructure
 #
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# USB port drivers
+# MMC/SD/SDIO Card Drivers
 #
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
 
 #
-# USB Serial Converter support
+# MMC/SD/SDIO Host Controller Drivers
 #
-# CONFIG_USB_SERIAL is not set
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_AT91=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS 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
 
 #
-# USB Miscellaneous drivers
+# RTC interfaces
 #
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
-# CONFIG_USB_IDMOUSE is not set
+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
 
 #
-# USB DSL modem support
+# SPI RTC drivers
 #
 
 #
-# USB Gadget Support
+# Platform RTC drivers
 #
-# CONFIG_USB_GADGET is not set
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
-# MMC/SD Card support
+# on-CPU RTC drivers
 #
-# CONFIG_MMC is not set
+CONFIG_RTC_DRV_AT91RM9200=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
-# XFS support
+# Caches
 #
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
+# CONFIG_FSCACHE is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -639,7 +1076,7 @@
 # DOS/FAT/NT Filesystems
 #
 CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+# CONFIG_MSDOS_FS is not set
 CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
@@ -649,53 +1086,70 @@
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
-CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_UBIFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFSD is not set
+# CONFIG_NFS_V4 is not set
 CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
 CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
@@ -719,7 +1173,7 @@
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ASCII=y
+# CONFIG_NLS_ASCII is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -733,47 +1187,119 @@
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_MAGIC_SYSRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_PREEMPT 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
 
 #
-# Security options
+# Tracers
 #
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
 
 #
-# Cryptographic options
+# Security options
 #
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/kirkwood_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/kirkwood_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/kirkwood_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/kirkwood_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -182,6 +182,7 @@
 CONFIG_MACH_DB88F6281_BP=y
 CONFIG_MACH_RD88F6192_NAS=y
 CONFIG_MACH_RD88F6281=y
+CONFIG_MACH_MV88F6281GTW_GE=y
 CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_TS219=y
 CONFIG_PLAT_ORION=y
@@ -270,7 +271,9 @@
 #
 # CPU Power Management
 #
-# CONFIG_CPU_IDLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
 
 #
 # Floating point emulation
@@ -626,7 +629,7 @@
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_PMP=y
-# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_AHCI=y
 # CONFIG_SATA_SIL24 is not set
 CONFIG_ATA_SFF=y
 # CONFIG_SATA_SVW is not set
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/magician_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/magician_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/magician_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/magician_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -190,6 +190,7 @@
 # CONFIG_MACH_SAAR is not set
 # CONFIG_MACH_ARMCORE is not set
 # CONFIG_MACH_CM_X300 is not set
+CONFIG_MACH_H4700=y
 CONFIG_MACH_MAGICIAN=y
 # CONFIG_MACH_MIOA701 is not set
 # CONFIG_MACH_PCM027 is not set
@@ -828,7 +829,7 @@
 #
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_ASIC3 is not set
+CONFIG_MFD_ASIC3=y
 CONFIG_HTC_EGPIO=y
 CONFIG_HTC_PASIC3=y
 # CONFIG_TPS65010 is not set
@@ -891,7 +892,7 @@
 # CONFIG_FB_PXA_SMARTPANEL is not set
 # CONFIG_FB_PXA_PARAMETERS is not set
 # CONFIG_FB_MBX is not set
-# CONFIG_FB_W100 is not set
+CONFIG_FB_W100=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/mini2440_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/mini2440_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/mini2440_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/mini2440_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2097 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc6
+# Wed May 20 12:29:51 2009
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_MMU=y
+CONFIG_NO_IOPORT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# 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"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+CONFIG_ARCH_S3C2410=y
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_PLAT_S3C24XX=y
+CONFIG_S3C2410_CLOCK=y
+CONFIG_CPU_S3C244X=y
+CONFIG_S3C24XX_PWM=y
+CONFIG_S3C24XX_GPIO_EXTRA=0
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+CONFIG_S3C24XX_ADC=y
+CONFIG_PLAT_S3C=y
+CONFIG_CPU_LLSERIAL_S3C2440_ONLY=y
+CONFIG_CPU_LLSERIAL_S3C2440=y
+
+#
+# Boot options
+#
+# CONFIG_S3C_BOOT_WATCHDOG is not set
+# CONFIG_S3C_BOOT_ERROR_RESET is not set
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
+
+#
+# Power management
+#
+# CONFIG_S3C2410_PM_DEBUG is not set
+# CONFIG_S3C2410_PM_CHECK is not set
+CONFIG_S3C_LOWLEVEL_UART_PORT=0
+CONFIG_S3C_GPIO_SPACE=0
+
+#
+# S3C2400 Machines
+#
+CONFIG_S3C2410_PM=y
+CONFIG_S3C2410_GPIO=y
+
+#
+# S3C2410 Machines
+#
+# CONFIG_ARCH_SMDK2410 is not set
+# CONFIG_ARCH_H1940 is not set
+# CONFIG_MACH_N30 is not set
+# CONFIG_ARCH_BAST is not set
+# CONFIG_MACH_OTOM is not set
+# CONFIG_MACH_AML_M5900 is not set
+# CONFIG_MACH_TCT_HAMMER is not set
+# CONFIG_MACH_VR1000 is not set
+# CONFIG_MACH_QT2410 is not set
+
+#
+# S3C2412 Machines
+#
+# CONFIG_MACH_JIVE is not set
+# CONFIG_MACH_SMDK2413 is not set
+# CONFIG_MACH_SMDK2412 is not set
+# CONFIG_MACH_VSTMS is not set
+CONFIG_CPU_S3C2440=y
+CONFIG_S3C2440_DMA=y
+
+#
+# S3C2440 Machines
+#
+# CONFIG_MACH_ANUBIS is not set
+# CONFIG_MACH_OSIRIS is not set
+# CONFIG_MACH_RX3715 is not set
+# CONFIG_ARCH_S3C2440 is not set
+# CONFIG_MACH_NEXCODER_2440 is not set
+# CONFIG_MACH_AT2440EVB is not set
+CONFIG_MACH_MINI2440=y
+
+#
+# S3C2442 Machines
+#
+
+#
+# S3C2443 Machines
+#
+# CONFIG_MACH_SMDK2443 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=200
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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 is not set
+# 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_LRO is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+CONFIG_CFG80211_REG_DEBUG=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_MINSTREL=y
+# CONFIG_MAC80211_RC_DEFAULT_PID is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel"
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=y
+CONFIG_RFD_FTL=y
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_S3C2410=y
+# CONFIG_MTD_NAND_S3C2410_DEBUG is not set
+# CONFIG_MTD_NAND_S3C2410_HWECC is not set
+# CONFIG_MTD_NAND_S3C2410_CLKSTOP is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=y
+CONFIG_MTD_QINFO_PROBE=y
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_DEBUGLEVEL=4
+# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+# CONFIG_LIBERTAS_USB is not set
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_SPI is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_AR9170_USB is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=m
+CONFIG_ZD1211RW_DEBUG=y
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV 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_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_UARTS=3
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_S3C2440=y
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=128
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_S3C2410=y
+CONFIG_I2C_SIMTEC=y
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_S3C24XX=y
+# CONFIG_SPI_S3C24XX_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IBMAEM is not set
+# CONFIG_SENSORS_IBMPEX is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+CONFIG_SENSORS_LM75=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=m
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_S3C2410_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+CONFIG_SOC_CAMERA_PLATFORM=m
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+CONFIG_USB_GSPCA_ZC3XX=m
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_CX231XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_PWC_INPUT_EVDEV is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_S3C2410=y
+# CONFIG_FB_S3C2410_DEBUG is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_S3C24XX_SOC=y
+CONFIG_SND_S3C24XX_SOC_I2S=y
+# CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650 is not set
+CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_L3=y
+CONFIG_SND_SOC_UDA134X=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+# CONFIG_USB_STORAGE_FREECOM is not set
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP210X=m
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+CONFIG_USB_SERIAL_SPCP8X5=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY 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
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+CONFIG_USB_GADGET_S3C2410=y
+CONFIG_USB_S3C2410=y
+# CONFIG_USB_S3C2410_DEBUG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_S3C=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_S3C24XX=y
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_PWM is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+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=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_S3C=y
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# 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
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_ROMFS_ON_MTD=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_S3C_UART=0
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_FILE_CAPABILITIES=y
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/mx21_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/mx21_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/mx21_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/mx21_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1170 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc1
+# Tue Apr 14 16:58:09 2009
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# Freescale MXC Implementations
+#
+# CONFIG_ARCH_MX1 is not set
+CONFIG_ARCH_MX2=y
+# CONFIG_ARCH_MX3 is not set
+CONFIG_MACH_MX21=y
+# CONFIG_MACH_MX27 is not set
+
+#
+# MX2 platforms:
+#
+CONFIG_MACH_MX21ADS=y
+# CONFIG_MXC_IRQ_PRIOR is not set
+CONFIG_MXC_PWM=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_UNIX is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# 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=y
+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_ARPD 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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=3
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_MXC=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_CS89x0=y
+CONFIG_CS89x0_NONISA_IRQ=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# 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_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_IMX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_IMX=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_MXC=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# 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_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/mx27_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/mx27_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/mx27_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/mx27_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,15 +1,15 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc1
-# Wed Apr  8 10:18:06 2009
+# Linux kernel version: 2.6.31-rc4
+# Fri Jul 24 16:08:06 2009
 #
 CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-# CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -18,14 +18,13 @@
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -85,7 +84,12 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -99,6 +103,12 @@
 CONFIG_KRETPROBES=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
@@ -111,7 +121,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -138,13 +148,14 @@
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
-# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -153,25 +164,25 @@
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
-CONFIG_ARCH_MXC=y
 # CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM is not set
-# CONFIG_ARCH_W90X900 is not set
 
 #
 # Freescale MXC Implementations
@@ -188,6 +199,8 @@
 CONFIG_MACH_MX27ADS=y
 CONFIG_MACH_PCM038=y
 CONFIG_MACH_PCM970_BASEBOARD=y
+CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_MX27LITE=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
 
@@ -213,7 +226,6 @@
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
-# CONFIG_OUTER_CACHE is not set
 CONFIG_COMMON_CLKDEV=y
 
 #
@@ -238,7 +250,6 @@
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 # CONFIG_HIGHMEM is not set
@@ -253,10 +264,11 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
 
 #
 # Boot options
@@ -361,6 +373,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -474,7 +487,16 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_MXC=y
 # CONFIG_MTD_ONENAND is not set
 
 #
@@ -485,7 +507,15 @@
 #
 # UBI - Unsorted block images
 #
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
@@ -494,7 +524,21 @@
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-# CONFIG_MISC_DEVICES is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -508,7 +552,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -534,6 +577,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 CONFIG_FEC=y
 # CONFIG_FEC2 is not set
 # CONFIG_NETDEV_1000 is not set
@@ -580,6 +625,11 @@
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -592,6 +642,7 @@
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
 # CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -644,6 +695,7 @@
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_IMX=y
 # CONFIG_I2C_OCORES is not set
@@ -668,7 +720,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -719,6 +770,7 @@
 #
 # CONFIG_W1_MASTER_DS2482 is not set
 CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_DS1WM is not set
 # CONFIG_W1_MASTER_GPIO is not set
 
 #
@@ -753,54 +805,16 @@
 # CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_ALLOW_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-# CONFIG_DVB_CORE is not set
-CONFIG_VIDEO_MEDIA=y
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=y
-CONFIG_MEDIA_TUNER_TDA8290=y
-CONFIG_MEDIA_TUNER_TDA9887=y
-CONFIG_MEDIA_TUNER_TEA5761=y
-CONFIG_MEDIA_TUNER_TEA5767=y
-CONFIG_MEDIA_TUNER_MT20XX=y
-CONFIG_MEDIA_TUNER_XC2028=y
-CONFIG_MEDIA_TUNER_XC5000=y
-CONFIG_MEDIA_TUNER_MC44S803=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_V4L1=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_SOC_CAMERA is not set
-# CONFIG_RADIO_ADAPTERS is not set
-# CONFIG_DAB is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -917,6 +931,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -962,12 +977,15 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -1021,6 +1039,12 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1119,25 +1143,11 @@
 CONFIG_NOP_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1151,16 +1161,104 @@
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
 CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_RATIONAL=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 # CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
@@ -1168,6 +1266,8 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/mx3_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/mx3_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/mx3_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/mx3_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,15 +1,15 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc1
-# Wed Apr  8 11:06:37 2009
+# Linux kernel version: 2.6.31-rc4
+# Tue Jul 28 14:11:34 2009
 #
 CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-# CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -18,14 +18,13 @@
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -86,7 +85,12 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -97,6 +101,11 @@
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
@@ -109,7 +118,7 @@
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -136,13 +145,14 @@
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
-# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -151,25 +161,25 @@
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
-CONFIG_ARCH_MXC=y
 # CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM is not set
-# CONFIG_ARCH_W90X900 is not set
 
 #
 # Freescale MXC Implementations
@@ -178,6 +188,7 @@
 # CONFIG_ARCH_MX2 is not set
 CONFIG_ARCH_MX3=y
 CONFIG_ARCH_MX31=y
+CONFIG_ARCH_MX35=y
 
 #
 # MX3 platforms:
@@ -185,12 +196,19 @@
 CONFIG_MACH_MX31ADS=y
 CONFIG_MACH_MX31ADS_WM1133_EV1=y
 CONFIG_MACH_PCM037=y
+CONFIG_MACH_PCM037_EET=y
 CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_MX31_3DS=y
 CONFIG_MACH_MX31MOBOARD=y
+CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_QONG=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_ARMADILLO5X0=y
+CONFIG_MACH_MX35_3DS=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
+CONFIG_ARCH_HAS_RNGA=y
+CONFIG_ARCH_MXC_IOMUX_V3=y
 
 #
 # Processor Type
@@ -218,6 +236,7 @@
 # CONFIG_CPU_BPREDICT_DISABLE is not set
 CONFIG_OUTER_CACHE=y
 CONFIG_CACHE_L2X0=y
+# CONFIG_ARM_ERRATA_411920 is not set
 CONFIG_COMMON_CLKDEV=y
 
 #
@@ -242,7 +261,6 @@
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 # CONFIG_HIGHMEM is not set
@@ -257,10 +275,11 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
 
 #
 # Boot options
@@ -362,6 +381,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -465,7 +485,16 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_MXC=y
 # CONFIG_MTD_ONENAND is not set
 
 #
@@ -476,10 +505,30 @@
 #
 # UBI - Unsorted block images
 #
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -493,7 +542,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -528,7 +576,7 @@
 # CONFIG_ETHOC is not set
 # CONFIG_SMC911X is not set
 CONFIG_SMSC911X=y
-# CONFIG_DNET is not set
+CONFIG_DNET=y
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -537,8 +585,10 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_CS89x0=y
-CONFIG_CS89x0_NONISA_IRQ=y
+# CONFIG_CS89x0 is not set
+# CONFIG_KS8842 is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -609,6 +659,7 @@
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_IMX=y
 # CONFIG_I2C_OCORES is not set
@@ -633,7 +684,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -669,6 +719,7 @@
 #
 # CONFIG_W1_MASTER_DS2482 is not set
 CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_DS1WM is not set
 # CONFIG_W1_MASTER_GPIO is not set
 
 #
@@ -703,6 +754,8 @@
 # CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
@@ -711,10 +764,8 @@
 CONFIG_MFD_WM8352_CONFIG_MODE_0=y
 CONFIG_MFD_WM8350_I2C=y
 # CONFIG_MFD_PCF50633 is not set
-
-#
-# Multimedia devices
-#
+# CONFIG_AB3100_CORE is not set
+CONFIG_MEDIA_SUPPORT=y
 
 #
 # Multimedia core support
@@ -758,8 +809,10 @@
 CONFIG_SOC_CAMERA_MT9V022=y
 CONFIG_SOC_CAMERA_TW9910=y
 # CONFIG_SOC_CAMERA_PLATFORM is not set
-# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_SOC_CAMERA_OV772X=y
+CONFIG_MX3_VIDEO=y
 CONFIG_VIDEO_MX3=y
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
 
@@ -847,8 +900,11 @@
 # CONFIG_REGULATOR_DEBUG is not set
 # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
 # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
 # CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
 CONFIG_REGULATOR_WM8350=y
+# CONFIG_REGULATOR_LP3971 is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -861,10 +917,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -921,6 +979,12 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -937,6 +1001,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -979,22 +1044,7 @@
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_ARM_UNWIND=y
@@ -1094,9 +1144,9 @@
 #
 # Compression
 #
-# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_DEFLATE=y
 # CONFIG_CRYPTO_ZLIB is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_LZO=y
 
 #
 # Random Number Generation
@@ -1109,9 +1159,10 @@
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_RATIONAL=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 # CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
@@ -1119,6 +1170,8 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/omap3_evm_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/omap3_evm_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/omap3_evm_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/omap3_evm_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1528 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc5
+# Mon May 18 14:01:52 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS 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_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OVERO is not set
+CONFIG_MACH_OMAP3EVM=y
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE 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=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+CONFIG_SMC911X=y
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=y
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ZERO_HNPTEST is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TWL4030_USB is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+CONFIG_MMC_OMAP_HS=m
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS 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_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/omap_4430sdp_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/omap_4430sdp_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/omap_4430sdp_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/omap_4430sdp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,866 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc7
+# Tue Jun  9 12:36:23 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# TI OMAP Implementations
+#
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+CONFIG_ARCH_OMAP4=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_MUX is not set
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP_4430SDP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_DISABLE=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_ARM_GIC=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_NR_CPUS=2
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_LOCAL_TIMERS=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_UNEVICTABLE_LRU is not set
+CONFIG_HAVE_MLOCK=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M console=ttyS0,115200n8 initrd=0x81600000,20M ramdisk_size=20480"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# 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_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/omap_zoom2_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/omap_zoom2_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/omap_zoom2_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/omap_zoom2_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1211 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc5
+# Fri Oct 10 11:49:41 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_HAVE_CLK=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OMAP_LDP is not set
+CONFIG_MACH_OMAP_ZOOM2=y
+# CONFIG_MACH_OVERO is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+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_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# 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
+# 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_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# 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_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_NEW_LEDS 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
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+
+#
+# Voltage and Current regulators
+#
+# CONFIG_REGULATOR is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS 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_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/orion5x_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/orion5x_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/orion5x_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/orion5x_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -903,7 +903,8 @@
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_RAW_DRIVER is not set
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/rx51_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/rx51_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/rx51_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/rx51_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -282,7 +282,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs rw console=ttyMTD5"
+CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log console=tty0 console=ttyS2,115200n8"
 # CONFIG_XIP_KERNEL is not set
 # CONFIG_KEXEC is not set
 
@@ -1354,7 +1354,7 @@
 # CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_ISP1301_OMAP is not set
 CONFIG_TWL4030_USB=y
-CONFIG_MMC=m
+CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
@@ -1449,7 +1449,8 @@
 # on-CPU RTC drivers
 #
 # CONFIG_DMADEVICES is not set
-# CONFIG_REGULATOR is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_TWL4030=y
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/s3c2410_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/s3c2410_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/s3c2410_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/s3c2410_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -260,6 +260,7 @@
 CONFIG_SMDK2440_CPU2440=y
 CONFIG_MACH_AT2440EVB=y
 CONFIG_CPU_S3C2442=y
+CONFIG_MACH_MINI2440=y
 
 #
 # S3C2442 Machines
@@ -2298,7 +2299,6 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
-CONFIG_DEBUG_S3C_PORT=y
 CONFIG_DEBUG_S3C_UART=0
 
 #
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/s3c6400_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/s3c6400_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/s3c6400_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/s3c6400_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -816,7 +816,6 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
-CONFIG_DEBUG_S3C_PORT=y
 CONFIG_DEBUG_S3C_UART=0
 
 #
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/stmp378x_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/stmp378x_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/stmp378x_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/stmp378x_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1141 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc2
+# Thu Apr 23 02:44:13 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-default"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_INITRAMFS_COMPRESSION_NONE is not set
+CONFIG_INITRAMFS_COMPRESSION_GZIP=y
+# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set
+# CONFIG_INITRAMFS_COMPRESSION_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_ARCH_STMP3XXX=y
+
+#
+# Freescale STMP3xxx implementations
+#
+# CONFIG_ARCH_STMP37XX is not set
+CONFIG_ARCH_STMP378X=y
+# CONFIG_MACH_STMP37XX is not set
+CONFIG_MACH_STMP378X=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HIGHMEM=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySDBG0,115200 mem=32M"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+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_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_TESTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=6144
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_VIDEO_V4L1_COMPAT is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# 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_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_SELFTEST=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SLAB_LEAK=y
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_TRACE_IRQFLAGS=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+CONFIG_DEBUG_KOBJECT=y
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+CONFIG_FUNCTION_TRACER=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+CONFIG_CONTEXT_SWITCH_TRACER=y
+# CONFIG_EVENT_TRACER is not set
+CONFIG_BOOT_TRACER=y
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_STACK_TRACER=y
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+# CONFIG_SECURITY_TOMOYO is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/stmp37xx_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/stmp37xx_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/stmp37xx_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/stmp37xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1002 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29.1
+# Mon Apr 20 04:41:26 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-default"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_ARCH_STMP3XXX=y
+
+#
+# Freescale STMP3xxx implementations
+#
+CONFIG_ARCH_STMP37XX=y
+# CONFIG_ARCH_STMP378X is not set
+CONFIG_MACH_STMP37XX=y
+# CONFIG_MACH_STMP378X is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySDBG0,115200 mem=32M lcd_panel=lms350 rdinit=/bin/sh ignore_loglevel"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+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_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=6144
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_STMP_DBG is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_VIDEO_V4L1_COMPAT is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# 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_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+CONFIG_FUNCTION_TRACER=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_BOOT_TRACER=y
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_STACK_TRACER=y
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/tct_hammer_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/tct_hammer_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/tct_hammer_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/tct_hammer_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -857,7 +857,6 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_S3C_PORT is not set
 CONFIG_DEBUG_S3C_UART=0
 
 #
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/u300_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/u300_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/u300_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/configs/u300_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1127 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc3
+# Thu Jul 16 23:36:10 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+# CONFIG_AIO is not set
+
+#
+# Performance Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_U300=y
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# ST-Ericsson AB U300/U330/U335/U365 Platform
+#
+
+#
+# ST-Ericsson Mobile Platform Products
+#
+CONFIG_MACH_U300=y
+
+#
+# ST-Ericsson U300/U330/U335/U365 Feature Selections
+#
+# CONFIG_MACH_U300_BS2X is not set
+# CONFIG_MACH_U300_BS330 is not set
+CONFIG_MACH_U300_BS335=y
+# CONFIG_MACH_U300_BS365 is not set
+# CONFIG_MACH_U300_SINGLE_RAM is not set
+CONFIG_MACH_U300_DUAL_RAM=y
+CONFIG_U300_DEBUG=y
+# CONFIG_MACH_U300_SEMI_IS_SHARED is not set
+
+#
+# All the settings below must match the bootloader's settings
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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 is not set
+# 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_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+CONFIG_I2C_STU300=y
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_PL022=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_COH901327_WATCHDOG=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+CONFIG_AB3100_CORE=y
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_DEBUG=y
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_ARMMMCI=y
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+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
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+# CONFIG_AUXDISPLAY is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# 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=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/configs/w90p910_defconfig linux-libre-2.6.31-gnu/arch/arm/configs/w90p910_defconfig
--- linux-libre-2.6.30-gnu/arch/arm/configs/w90p910_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/configs/w90p910_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,11 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc8-git8
-# Sat Nov 15 10:05:00 2008
+# Linux kernel version: 2.6.30
+# Wed Jun 10 22:09:25 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_GPIO=y
 # CONFIG_GENERIC_TIME is not set
 # CONFIG_GENERIC_CLOCKEVENTS is not set
 CONFIG_MMU=y
@@ -22,8 +22,6 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -42,10 +40,19 @@
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
@@ -56,52 +63,53 @@
 # CONFIG_PID_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+# CONFIG_INITRAMFS_COMPRESSION_NONE is not set
+# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set
+# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set
+# CONFIG_INITRAMFS_COMPRESSION_LZMA is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
 CONFIG_LBD=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_LSF=y
 CONFIG_BLK_DEV_BSG=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -117,7 +125,7 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
 
 #
 # System Type
@@ -127,10 +135,10 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
@@ -151,23 +159,17 @@
 # CONFIG_ARCH_ORION5X is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
 CONFIG_ARCH_W90X900=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
 CONFIG_CPU_W90P910=y
 
 #
@@ -198,6 +200,7 @@
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
 # CONFIG_OUTER_CACHE is not set
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
@@ -209,27 +212,32 @@
 #
 # Kernel Features
 #
-# CONFIG_TICK_ONESHOT is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -237,12 +245,17 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0
 CONFIG_ZBOOT_ROM_BSS=0
-CONFIG_CMDLINE="root=/dev/ram0 console=ttyS0,115200n8 initrd=0xa00000,4000000 mem=64M"
+CONFIG_CMDLINE="root=/dev/ram0 console=ttyS0,115200n8 rdinit=/sbin/init mem=64M"
 # CONFIG_XIP_KERNEL is not set
 CONFIG_KEXEC=y
 CONFIG_ATAGS_PROC=y
 
 #
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
 # Floating point emulation
 #
 
@@ -258,6 +271,8 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
@@ -282,11 +297,93 @@
 CONFIG_FIRMWARE_IN_KERNEL=y
 CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -300,9 +397,41 @@
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 
@@ -354,38 +483,57 @@
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+# CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
 # Non-8250 serial port support
 #
-CONFIG_SERIAL_W90X900=y
-# CONFIG_SERIAL_W90X900_PORT1 is not set
-# CONFIG_SERIAL_W90X900_PORT2 is not set
-# CONFIG_SERIAL_W90X900_PORT3 is not set
-# CONFIG_SERIAL_W90X900_PORT4 is not set
-CONFIG_SERIAL_W90X900_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
@@ -393,10 +541,11 @@
 #
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_T7L66XB is not set
-# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
 
 #
 # Multimedia devices
@@ -433,33 +582,131 @@
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_SOUND is not set
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_NEW_LEDS is not set
 CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
 # CONFIG_QUOTA is not set
@@ -469,6 +716,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -486,15 +738,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -502,15 +752,22 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 
 #
 # Partition Types
@@ -586,18 +843,36 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_ARM_UNWIND=y
 # CONFIG_DEBUG_USER is not set
 
 #
@@ -605,14 +880,15 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
 #
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
@@ -620,7 +896,10 @@
 # CONFIG_CRC32 is not set
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
-CONFIG_PLIST=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/arm/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -159,8 +159,6 @@
 
 #else /* ARM_ARCH_6 */
 
-#include <asm/system.h>
-
 #ifdef CONFIG_SMP
 #error SMP not supported on pre-ARMv6 CPUs
 #endif
@@ -249,6 +247,6 @@
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/arm/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/cacheflush.h linux-libre-2.6.31-gnu/arch/arm/include/asm/cacheflush.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/cacheflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/cacheflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -429,6 +429,14 @@
 		__flush_anon_page(vma, page, vmaddr);
 }
 
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+static inline void flush_kernel_dcache_page(struct page *page)
+{
+	/* highmem pages are always flushed upon kunmap already */
+	if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
+		__cpuc_flush_dcache_page(page_address(page));
+}
+
 #define flush_dcache_mmap_lock(mapping) \
 	spin_lock_irq(&(mapping)->tree_lock)
 #define flush_dcache_mmap_unlock(mapping) \
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/cputype.h linux-libre-2.6.31-gnu/arch/arm/include/asm/cputype.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/cputype.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/cputype.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,21 @@
 #define CPUID_TCM	2
 #define CPUID_TLBTYPE	3
 
+#define CPUID_EXT_PFR0	"c1, 0"
+#define CPUID_EXT_PFR1	"c1, 1"
+#define CPUID_EXT_DFR0	"c1, 2"
+#define CPUID_EXT_AFR0	"c1, 3"
+#define CPUID_EXT_MMFR0	"c1, 4"
+#define CPUID_EXT_MMFR1	"c1, 5"
+#define CPUID_EXT_MMFR2	"c1, 6"
+#define CPUID_EXT_MMFR3	"c1, 7"
+#define CPUID_EXT_ISAR0	"c2, 0"
+#define CPUID_EXT_ISAR1	"c2, 1"
+#define CPUID_EXT_ISAR2	"c2, 2"
+#define CPUID_EXT_ISAR3	"c2, 3"
+#define CPUID_EXT_ISAR4	"c2, 4"
+#define CPUID_EXT_ISAR5	"c2, 5"
+
 #ifdef CONFIG_CPU_CP15
 #define read_cpuid(reg)							\
 	({								\
@@ -18,9 +33,19 @@
 		    : "cc");						\
 		__val;							\
 	})
+#define read_cpuid_ext(ext_reg)						\
+	({								\
+		unsigned int __val;					\
+		asm("mrc	p15, 0, %0, c0, " ext_reg		\
+		    : "=r" (__val)					\
+		    :							\
+		    : "cc");						\
+		__val;							\
+	})
 #else
 extern unsigned int processor_id;
 #define read_cpuid(reg) (processor_id)
+#define read_cpuid_ext(reg) 0
 #endif
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/arm_twd.h linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/arm_twd.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/arm_twd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/arm_twd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-#ifndef __ASM_HARDWARE_TWD_H
-#define __ASM_HARDWARE_TWD_H
-
-#define TWD_TIMER_LOAD 			0x00
-#define TWD_TIMER_COUNTER		0x04
-#define TWD_TIMER_CONTROL		0x08
-#define TWD_TIMER_INTSTAT		0x0C
-
-#define TWD_WDOG_LOAD			0x20
-#define TWD_WDOG_COUNTER		0x24
-#define TWD_WDOG_CONTROL		0x28
-#define TWD_WDOG_INTSTAT		0x2C
-#define TWD_WDOG_RESETSTAT		0x30
-#define TWD_WDOG_DISABLE		0x34
-
-#define TWD_TIMER_CONTROL_ENABLE	(1 << 0)
-#define TWD_TIMER_CONTROL_ONESHOT	(0 << 1)
-#define TWD_TIMER_CONTROL_PERIODIC	(1 << 1)
-#define TWD_TIMER_CONTROL_IT_ENABLE	(1 << 2)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/cache-l2x0.h linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/cache-l2x0.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/cache-l2x0.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/cache-l2x0.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,8 @@
 #define L2X0_CACHE_TYPE			0x004
 #define L2X0_CTRL			0x100
 #define L2X0_AUX_CTRL			0x104
+#define L2X0_TAG_LATENCY_CTRL		0x108
+#define L2X0_DATA_LATENCY_CTRL		0x10C
 #define L2X0_EVENT_CNT_CTRL		0x200
 #define L2X0_EVENT_CNT1_CFG		0x204
 #define L2X0_EVENT_CNT0_CFG		0x208
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/pl080.h linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/pl080.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/pl080.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/pl080.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,138 @@
+/* arch/arm/include/asm/hardware/pl080.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * ARM PrimeCell PL080 DMA controller
+ *
+ * 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.
+*/
+
+/* Note, there are some Samsung updates to this controller block which
+ * make it not entierly compatible with the PL080 specification from
+ * ARM. When in doubt, check the Samsung documentation first.
+ *
+ * The Samsung defines are PL080S, and add an extra controll register,
+ * the ability to move more than 2^11 counts of data and some extra
+ * OneNAND features.
+*/
+
+#define PL080_INT_STATUS			(0x00)
+#define PL080_TC_STATUS				(0x04)
+#define PL080_TC_CLEAR				(0x08)
+#define PL080_ERR_STATUS			(0x0C)
+#define PL080_ERR_CLEAR				(0x10)
+#define PL080_RAW_TC_STATUS			(0x14)
+#define PL080_RAW_ERR_STATUS			(0x18)
+#define PL080_EN_CHAN				(0x1c)
+#define PL080_SOFT_BREQ				(0x20)
+#define PL080_SOFT_SREQ				(0x24)
+#define PL080_SOFT_LBREQ			(0x28)
+#define PL080_SOFT_LSREQ			(0x2C)
+
+#define PL080_CONFIG				(0x30)
+#define PL080_CONFIG_M2_BE			(1 << 2)
+#define PL080_CONFIG_M1_BE			(1 << 1)
+#define PL080_CONFIG_ENABLE			(1 << 0)
+
+#define PL080_SYNC				(0x34)
+
+/* Per channel configuration registers */
+
+#define PL008_Cx_STRIDE				(0x20)
+#define PL080_Cx_BASE(x)			((0x100 + (x * 0x20)))
+#define PL080_Cx_SRC_ADDR(x)			((0x100 + (x * 0x20)))
+#define PL080_Cx_DST_ADDR(x)			((0x104 + (x * 0x20)))
+#define PL080_Cx_LLI(x)				((0x108 + (x * 0x20)))
+#define PL080_Cx_CONTROL(x)			((0x10C + (x * 0x20)))
+#define PL080_Cx_CONFIG(x)			((0x110 + (x * 0x20)))
+#define PL080S_Cx_CONTROL2(x)			((0x110 + (x * 0x20)))
+#define PL080S_Cx_CONFIG(x)			((0x114 + (x * 0x20)))
+
+#define PL080_CH_SRC_ADDR			(0x00)
+#define PL080_CH_DST_ADDR			(0x04)
+#define PL080_CH_LLI				(0x08)
+#define PL080_CH_CONTROL			(0x0C)
+#define PL080_CH_CONFIG				(0x10)
+#define PL080S_CH_CONTROL2			(0x10)
+#define PL080S_CH_CONFIG			(0x14)
+
+#define PL080_LLI_ADDR_MASK			(0x3fffffff << 2)
+#define PL080_LLI_ADDR_SHIFT			(2)
+#define PL080_LLI_LM_AHB2			(1 << 0)
+
+#define PL080_CONTROL_TC_IRQ_EN			(1 << 31)
+#define PL080_CONTROL_PROT_MASK			(0x7 << 28)
+#define PL080_CONTROL_PROT_SHIFT		(28)
+#define PL080_CONTROL_PROT_SYS			(1 << 28)
+#define PL080_CONTROL_DST_INCR			(1 << 27)
+#define PL080_CONTROL_SRC_INCR			(1 << 26)
+#define PL080_CONTROL_DST_AHB2			(1 << 25)
+#define PL080_CONTROL_SRC_AHB2			(1 << 24)
+#define PL080_CONTROL_DWIDTH_MASK		(0x7 << 21)
+#define PL080_CONTROL_DWIDTH_SHIFT		(21)
+#define PL080_CONTROL_SWIDTH_MASK		(0x7 << 18)
+#define PL080_CONTROL_SWIDTH_SHIFT		(18)
+#define PL080_CONTROL_DB_SIZE_MASK		(0x7 << 15)
+#define PL080_CONTROL_DB_SIZE_SHIFT		(15)
+#define PL080_CONTROL_SB_SIZE_MASK		(0x7 << 12)
+#define PL080_CONTROL_SB_SIZE_SHIFT		(12)
+#define PL080_CONTROL_TRANSFER_SIZE_MASK	(0xfff << 0)
+#define PL080_CONTROL_TRANSFER_SIZE_SHIFT	(0)
+
+#define PL080_BSIZE_1				(0x0)
+#define PL080_BSIZE_4				(0x1)
+#define PL080_BSIZE_8				(0x2)
+#define PL080_BSIZE_16				(0x3)
+#define PL080_BSIZE_32				(0x4)
+#define PL080_BSIZE_64				(0x5)
+#define PL080_BSIZE_128				(0x6)
+#define PL080_BSIZE_256				(0x7)
+
+#define PL080_WIDTH_8BIT			(0x0)
+#define PL080_WIDTH_16BIT			(0x1)
+#define PL080_WIDTH_32BIT			(0x2)
+
+#define PL080_CONFIG_HALT			(1 << 18)
+#define PL080_CONFIG_ACTIVE			(1 << 17)  /* RO */
+#define PL080_CONFIG_LOCK			(1 << 16)
+#define PL080_CONFIG_TC_IRQ_MASK		(1 << 15)
+#define PL080_CONFIG_ERR_IRQ_MASK		(1 << 14)
+#define PL080_CONFIG_FLOW_CONTROL_MASK		(0x7 << 11)
+#define PL080_CONFIG_FLOW_CONTROL_SHIFT		(11)
+#define PL080_CONFIG_DST_SEL_MASK		(0xf << 6)
+#define PL080_CONFIG_DST_SEL_SHIFT		(6)
+#define PL080_CONFIG_SRC_SEL_MASK		(0xf << 1)
+#define PL080_CONFIG_SRC_SEL_SHIFT		(1)
+#define PL080_CONFIG_ENABLE			(1 << 0)
+
+#define PL080_FLOW_MEM2MEM			(0x0)
+#define PL080_FLOW_MEM2PER			(0x1)
+#define PL080_FLOW_PER2MEM			(0x2)
+#define PL080_FLOW_SRC2DST			(0x3)
+#define PL080_FLOW_SRC2DST_DST			(0x4)
+#define PL080_FLOW_MEM2PER_PER			(0x5)
+#define PL080_FLOW_PER2MEM_PER			(0x6)
+#define PL080_FLOW_SRC2DST_SRC			(0x7)
+
+/* DMA linked list chain structure */
+
+struct pl080_lli {
+	u32	src_addr;
+	u32	dst_addr;
+	u32	next_lli;
+	u32	control0;
+};
+
+struct pl080s_lli {
+	u32	src_addr;
+	u32	dst_addr;
+	u32	next_lli;
+	u32	control0;
+	u32	control1;
+};
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/sharpsl_pm.h linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/sharpsl_pm.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/sharpsl_pm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/sharpsl_pm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,106 +0,0 @@
-/*
- * SharpSL Battery/PM Driver
- *
- * Copyright (c) 2004-2005 Richard Purdie
- *
- * 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.
- *
- */
-
-#include <linux/interrupt.h>
-
-struct sharpsl_charger_machinfo {
-	void (*init)(void);
-	void (*exit)(void);
-	int gpio_acin;
-	int gpio_batfull;
-	int batfull_irq;
-	int gpio_batlock;
-	int gpio_fatal;
-	void (*discharge)(int);
-	void (*discharge1)(int);
-	void (*charge)(int);
-	void (*measure_temp)(int);
-	void (*presuspend)(void);
-	void (*postsuspend)(void);
-	void (*earlyresume)(void);
-	unsigned long (*read_devdata)(int);
-#define SHARPSL_BATT_VOLT       1
-#define SHARPSL_BATT_TEMP       2
-#define SHARPSL_ACIN_VOLT       3
-#define SHARPSL_STATUS_ACIN     4
-#define SHARPSL_STATUS_LOCK     5
-#define SHARPSL_STATUS_CHRGFULL 6
-#define SHARPSL_STATUS_FATAL    7
-	unsigned long (*charger_wakeup)(void);
-	int (*should_wakeup)(unsigned int resume_on_alarm);
-	void (*backlight_limit)(int);
-	int (*backlight_get_status) (void);
-	int charge_on_volt;
-	int charge_on_temp;
-	int charge_acin_high;
-	int charge_acin_low;
-	int fatal_acin_volt;
-	int fatal_noacin_volt;
-	int bat_levels;
-	struct battery_thresh *bat_levels_noac;
-	struct battery_thresh *bat_levels_acin;
-	struct battery_thresh *bat_levels_noac_bl;
-	struct battery_thresh *bat_levels_acin_bl;
-	int status_high_acin;
-	int status_low_acin;
-	int status_high_noac;
-	int status_low_noac;
-};
-
-struct battery_thresh {
-	int voltage;
-	int percentage;
-};
-
-struct battery_stat {
-	int ac_status;         /* APM AC Present/Not Present */
-	int mainbat_status;    /* APM Main Battery Status */
-	int mainbat_percent;   /* Main Battery Percentage Charge */
-	int mainbat_voltage;   /* Main Battery Voltage */
-};
-
-struct sharpsl_pm_status {
-	struct device *dev;
-	struct timer_list ac_timer;
-	struct timer_list chrg_full_timer;
-
-	int charge_mode;
-#define CHRG_ERROR    (-1)
-#define CHRG_OFF      (0)
-#define CHRG_ON       (1)
-#define CHRG_DONE     (2)
-
-	unsigned int flags;
-#define SHARPSL_SUSPENDED       (1 << 0)  /* Device is Suspended */
-#define SHARPSL_ALARM_ACTIVE    (1 << 1)  /* Alarm is for charging event (not user) */
-#define SHARPSL_BL_LIMIT        (1 << 2)  /* Backlight Intensity Limited */
-#define SHARPSL_APM_QUEUED      (1 << 3)  /* APM Event Queued */
-#define SHARPSL_DO_OFFLINE_CHRG (1 << 4)  /* Trigger the offline charger */
-
-	int full_count;
-	unsigned long charge_start_time;
-	struct sharpsl_charger_machinfo *machinfo;
-	struct battery_stat battstat;
-};
-
-extern struct sharpsl_pm_status sharpsl_pm;
-
-
-#define SHARPSL_LED_ERROR  2
-#define SHARPSL_LED_ON     1
-#define SHARPSL_LED_OFF    0
-
-void sharpsl_battery_kick(void);
-void sharpsl_pm_led(int val);
-irqreturn_t sharpsl_ac_isr(int irq, void *dev_id);
-irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id);
-irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id);
-
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/vic.h linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/vic.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/hardware/vic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/hardware/vic.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,7 @@
 #define VIC_PL192_VECT_ADDR		0xF00
 
 #ifndef __ASSEMBLY__
-void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources);
+void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
 #endif
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/localtimer.h linux-libre-2.6.31-gnu/arch/arm/include/asm/localtimer.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/localtimer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/localtimer.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ *  arch/arm/include/asm/localtimer.h
+ *
+ *  Copyright (C) 2004-2005 ARM Ltd.
+ *
+ * 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.
+ */
+#ifndef __ASM_ARM_LOCALTIMER_H
+#define __ASM_ARM_LOCALTIMER_H
+
+struct clock_event_device;
+
+/*
+ * Setup a per-cpu timer, whether it be a local timer or dummy broadcast
+ */
+void percpu_timer_setup(void);
+
+/*
+ * Called from assembly, this is the local timer IRQ handler
+ */
+asmlinkage void do_local_timer(struct pt_regs *);
+
+
+#ifdef CONFIG_LOCAL_TIMERS
+
+#ifdef CONFIG_HAVE_ARM_TWD
+
+#include "smp_twd.h"
+
+#define local_timer_ack()	twd_timer_ack()
+#define local_timer_stop()	twd_timer_stop()
+
+#else
+
+/*
+ * Platform provides this to acknowledge a local timer IRQ.
+ * Returns true if the local timer IRQ is to be processed.
+ */
+int local_timer_ack(void);
+
+/*
+ * Stop a local timer interrupt.
+ */
+void local_timer_stop(void);
+
+#endif
+
+/*
+ * Setup a local timer interrupt for a CPU.
+ */
+void local_timer_setup(struct clock_event_device *);
+
+#else
+
+static inline void local_timer_stop(void)
+{
+}
+
+#endif
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/mach/map.h linux-libre-2.6.31-gnu/arch/arm/include/asm/mach/map.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/mach/map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/mach/map.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,14 @@
 
 #ifdef CONFIG_MMU
 extern void iotable_init(struct map_desc *, int);
+
+struct mem_type;
+extern const struct mem_type *get_mem_type(unsigned int type);
+/*
+ * external interface to remap single page with appropriate type
+ */
+extern int ioremap_page(unsigned long virt, unsigned long phys,
+			const struct mem_type *mtype);
 #else
 #define iotable_init(map,num)	do { } while (0)
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/mman.h linux-libre-2.6.31-gnu/arch/arm/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __ARM_MMAN_H__
 #define __ARM_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/page.h linux-libre-2.6.31-gnu/arch/arm/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT		12
-#define PAGE_SIZE		(1UL << PAGE_SHIFT)
+#define PAGE_SIZE		(_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK		(~(PAGE_SIZE-1))
 
 #ifndef __ASSEMBLY__
@@ -202,6 +202,6 @@
 	(((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
 	 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/pci.h linux-libre-2.6.31-gnu/arch/arm/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -65,19 +65,6 @@
 pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 			struct pci_bus_region *region);
 
-static inline struct resource *
-pcibios_select_root(struct pci_dev *pdev, struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 /*
  * Dummy implementation; always return 0.
  */
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/arm/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -285,15 +285,6 @@
 #define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG)
 #define pte_special(pte)	(0)
 
-/*
- * The following only works if pte_present() is not true.
- */
-#define pte_file(pte)		(pte_val(pte) & L_PTE_FILE)
-#define pte_to_pgoff(x)		(pte_val(x) >> 2)
-#define pgoff_to_pte(x)		__pte(((x) << 2) | L_PTE_FILE)
-
-#define PTE_FILE_MAX_BITS	30
-
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
@@ -342,7 +333,7 @@
 	return __va(ptr);
 }
 
-#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
+#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
@@ -384,16 +375,50 @@
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-/* Encode and decode a swap entry.
+/*
+ * Encode and decode a swap entry.  Swap entries are stored in the Linux
+ * page tables as follows:
  *
- * We support up to 32GB of swap on 4k machines
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *   <--------------- offset --------------------> <--- type --> 0 0
+ *
+ * This gives us up to 127 swap files and 32GB per swap file.  Note that
+ * the offset field is always non-zero.
  */
-#define __swp_type(x)		(((x).val >> 2) & 0x7f)
-#define __swp_offset(x)		((x).val >> 9)
-#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) })
+#define __SWP_TYPE_SHIFT	2
+#define __SWP_TYPE_BITS		7
+#define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
+#define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
+
+#define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
+#define __swp_offset(x)		((x).val >> __SWP_OFFSET_SHIFT)
+#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
+
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
 
+/*
+ * It is an error for the kernel to have more swap files than we can
+ * encode in the PTEs.  This ensures that we know when MAX_SWAPFILES
+ * is increased beyond what we presently support.
+ */
+#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
+
+/*
+ * Encode and decode a file entry.  File entries are stored in the Linux
+ * page tables as follows:
+ *
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *   <------------------------ offset -------------------------> 1 0
+ */
+#define pte_file(pte)		(pte_val(pte) & L_PTE_FILE)
+#define pte_to_pgoff(x)		(pte_val(x) >> 2)
+#define pgoff_to_pte(x)		__pte(((x) << 2) | L_PTE_FILE)
+
+#define PTE_FILE_MAX_BITS	30
+
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 /* FIXME: this is not correct */
 #define kern_addr_valid(addr)	(1)
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/processor.h linux-libre-2.6.31-gnu/arch/arm/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -71,6 +71,7 @@
 		regs->ARM_cpsr = USR26_MODE;				\
 	if (elf_hwcap & HWCAP_THUMB && pc & 1)				\
 		regs->ARM_cpsr |= PSR_T_BIT;				\
+	regs->ARM_cpsr |= PSR_ENDSTATE;					\
 	regs->ARM_pc = pc & ~1;		/* pc */			\
 	regs->ARM_sp = sp;		/* sp */			\
 	regs->ARM_r2 = stack[2];	/* r2 (envp) */			\
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/ptrace.h linux-libre-2.6.31-gnu/arch/arm/include/asm/ptrace.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/ptrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/ptrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,7 @@
 #define PSR_F_BIT	0x00000040
 #define PSR_I_BIT	0x00000080
 #define PSR_A_BIT	0x00000100
+#define PSR_E_BIT	0x00000200
 #define PSR_J_BIT	0x01000000
 #define PSR_Q_BIT	0x08000000
 #define PSR_V_BIT	0x10000000
@@ -65,6 +66,22 @@
 #define PSR_x		0x0000ff00	/* Extension		*/
 #define PSR_c		0x000000ff	/* Control		*/
 
+/*
+ * ARMv7 groups of APSR bits
+ */
+#define PSR_ISET_MASK	0x01000010	/* ISA state (J, T) mask */
+#define PSR_IT_MASK	0x0600fc00	/* If-Then execution state mask */
+#define PSR_ENDIAN_MASK	0x00000200	/* Endianness state mask */
+
+/*
+ * Default endianness state
+ */
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define PSR_ENDSTATE	PSR_E_BIT
+#else
+#define PSR_ENDSTATE	0
+#endif
+
 #ifndef __ASSEMBLY__
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/setup.h linux-libre-2.6.31-gnu/arch/arm/include/asm/setup.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/setup.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/setup.h	2009-09-09 18:13:59.000000000 -0400
@@ -201,7 +201,8 @@
 struct membank {
 	unsigned long start;
 	unsigned long size;
-	int           node;
+	unsigned short node;
+	unsigned short highmem;
 };
 
 struct meminfo {
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/signal.h linux-libre-2.6.31-gnu/arch/arm/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -111,7 +111,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/sizes.h linux-libre-2.6.31-gnu/arch/arm/include/asm/sizes.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/sizes.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/sizes.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,7 @@
 #define SZ_512				0x00000200
 
 #define SZ_1K                           0x00000400
+#define SZ_2K                           0x00000800
 #define SZ_4K                           0x00001000
 #define SZ_8K                           0x00002000
 #define SZ_16K                          0x00004000
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/smp.h linux-libre-2.6.31-gnu/arch/arm/include/asm/smp.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/smp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/smp.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,7 @@
 asmlinkage void do_IPI(struct pt_regs *regs);
 
 /*
- * Setup the SMP cpu_possible_map
+ * Setup the set of possible CPUs (via set_cpu_possible)
  */
 extern void smp_init_cpus(void);
 
@@ -56,11 +56,6 @@
 extern void smp_cross_call(const struct cpumask *mask);
 
 /*
- * Broadcast a clock event to other CPUs.
- */
-extern void smp_timer_broadcast(const struct cpumask *mask);
-
-/*
  * Boot a secondary CPU, and assign it the specified idle task.
  * This also gives us the initial stack to use for this CPU.
  */
@@ -101,43 +96,8 @@
 #define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
 
 /*
- * Local timer interrupt handling function (can be IPI'ed).
- */
-extern void local_timer_interrupt(void);
-
-#ifdef CONFIG_LOCAL_TIMERS
-
-/*
- * Stop a local timer interrupt.
- */
-extern void local_timer_stop(void);
-
-/*
- * Platform provides this to acknowledge a local timer IRQ
- */
-extern int local_timer_ack(void);
-
-#else
-
-static inline void local_timer_stop(void)
-{
-}
-
-#endif
-
-/*
- * Setup a local timer interrupt for a CPU.
- */
-extern void local_timer_setup(void);
-
-/*
  * show local interrupt info
  */
 extern void show_local_irqs(struct seq_file *);
 
-/*
- * Called from assembly, this is the local timer IRQ handler
- */
-asmlinkage void do_local_timer(struct pt_regs *);
-
 #endif /* ifndef __ASM_ARM_SMP_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/smp_scu.h linux-libre-2.6.31-gnu/arch/arm/include/asm/smp_scu.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/smp_scu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/smp_scu.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef __ASMARM_ARCH_SCU_H
+#define __ASMARM_ARCH_SCU_H
+
+unsigned int scu_get_core_count(void __iomem *);
+void scu_enable(void __iomem *);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/smp_twd.h linux-libre-2.6.31-gnu/arch/arm/include/asm/smp_twd.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/smp_twd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/smp_twd.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef __ASMARM_SMP_TWD_H
+#define __ASMARM_SMP_TWD_H
+
+struct clock_event_device;
+
+extern void __iomem *twd_base;
+
+void twd_timer_stop(void);
+int twd_timer_ack(void);
+void twd_timer_setup(struct clock_event_device *);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/suspend.h linux-libre-2.6.31-gnu/arch/arm/include/asm/suspend.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/suspend.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-#ifndef _ASMARM_SUSPEND_H
-#define _ASMARM_SUSPEND_H
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/arm/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -73,7 +73,7 @@
 	.task		= &tsk,						\
 	.exec_domain	= &default_exec_domain,				\
 	.flags		= 0,						\
-	.preempt_count	= 1,						\
+	.preempt_count	= INIT_PREEMPT_COUNT,				\
 	.addr_limit	= KERNEL_DS,					\
 	.cpu_domain	= domain_val(DOMAIN_USER, DOMAIN_MANAGER) |	\
 			  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |	\
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/tlbflush.h linux-libre-2.6.31-gnu/arch/arm/include/asm/tlbflush.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/tlbflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/tlbflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -40,6 +40,12 @@
 #define TLB_V6_I_ASID	(1 << 18)
 
 #define TLB_BTB		(1 << 28)
+
+/* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */
+#define TLB_V7_UIS_PAGE	(1 << 19)
+#define TLB_V7_UIS_FULL (1 << 20)
+#define TLB_V7_UIS_ASID (1 << 21)
+
 #define TLB_L2CLEAN_FR	(1 << 29)		/* Feroceon */
 #define TLB_DCLEAN	(1 << 30)
 #define TLB_WB		(1 << 31)
@@ -176,9 +182,17 @@
 # define v6wbi_always_flags	(-1UL)
 #endif
 
+#ifdef CONFIG_SMP
+#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+			 TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
+#else
+#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+			 TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
+#endif
+
 #ifdef CONFIG_CPU_TLB_V7
-# define v7wbi_possible_flags	v6wbi_tlb_flags
-# define v7wbi_always_flags	v6wbi_tlb_flags
+# define v7wbi_possible_flags	v7wbi_tlb_flags
+# define v7wbi_always_flags	v7wbi_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
@@ -316,6 +330,8 @@
 		asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
 	if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
 		asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
+	if (tlb_flag(TLB_V7_UIS_FULL))
+		asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
 
 	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
@@ -351,6 +367,8 @@
 		asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
 	if (tlb_flag(TLB_V6_I_ASID))
 		asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
+	if (tlb_flag(TLB_V7_UIS_ASID))
+		asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");
 
 	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
@@ -389,6 +407,8 @@
 		asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
+	if (tlb_flag(TLB_V7_UIS_PAGE))
+		asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
 
 	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
@@ -424,6 +444,8 @@
 		asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
+	if (tlb_flag(TLB_V7_UIS_PAGE))
+		asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
 
 	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/arm/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -102,8 +102,8 @@
 }
 
 #define tlb_remove_page(tlb,page)	free_page_and_swap_cache(page)
-#define pte_free_tlb(tlb, ptep)		pte_free((tlb)->mm, ptep)
-#define pmd_free_tlb(tlb, pmdp)		pmd_free((tlb)->mm, pmdp)
+#define pte_free_tlb(tlb, ptep, addr)	pte_free((tlb)->mm, ptep)
+#define pmd_free_tlb(tlb, pmdp, addr)	pmd_free((tlb)->mm, pmdp)
 
 #define tlb_migrate_finish(mm)		do { } while (0)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/uaccess.h linux-libre-2.6.31-gnu/arch/arm/include/asm/uaccess.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/uaccess.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/uaccess.h	2009-09-09 18:13:59.000000000 -0400
@@ -386,7 +386,9 @@
 #ifdef CONFIG_MMU
 extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
 extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
+extern unsigned long __must_check __copy_to_user_std(void __user *to, const void *from, unsigned long n);
 extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
+extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned long n);
 #else
 #define __copy_from_user(to,from,n)	(memcpy(to, (void __force *)from, n), 0)
 #define __copy_to_user(to,from,n)	(memcpy((void __force *)to, from, n), 0)
diff -druN linux-libre-2.6.30-gnu/arch/arm/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/arm/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/arm/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -389,6 +389,8 @@
 #define __NR_inotify_init1		(__NR_SYSCALL_BASE+360)
 #define __NR_preadv			(__NR_SYSCALL_BASE+361)
 #define __NR_pwritev			(__NR_SYSCALL_BASE+362)
+#define __NR_rt_tgsigqueueinfo		(__NR_SYSCALL_BASE+363)
+#define __NR_perf_counter_open		(__NR_SYSCALL_BASE+364)
 
 /*
  * The following SWIs are ARM private.
diff -druN linux-libre-2.6.30-gnu/arch/arm/Kconfig linux-libre-2.6.31-gnu/arch/arm/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -34,15 +34,12 @@
 
 config GENERIC_GPIO
 	bool
-	default n
 
 config GENERIC_TIME
 	bool
-	default n
 
 config GENERIC_CLOCKEVENTS
 	bool
-	default n
 
 config GENERIC_CLOCKEVENTS_BROADCAST
 	bool
@@ -55,7 +52,6 @@
 
 config NO_IOPORT
 	bool
-	default n
 
 config EISA
 	bool
@@ -126,11 +122,9 @@
 
 config ARCH_HAS_ILOG2_U32
 	bool
-	default n
 
 config ARCH_HAS_ILOG2_U64
 	bool
-	default n
 
 config GENERIC_HWEIGHT
 	bool
@@ -253,6 +247,14 @@
 	help
 	  Support for Cirrus Logic 711x/721x based boards.
 
+config ARCH_GEMINI
+	bool "Cortina Systems Gemini"
+	select CPU_FA526
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Support for the Cortina Systems Gemini family SoCs
+
 config ARCH_EBSA110
 	bool "EBSA-110"
 	select CPU_SA110
@@ -277,14 +279,6 @@
 	help
 	  This enables support for the Cirrus EP93xx series of CPUs.
 
-config ARCH_GEMINI
-	bool "Cortina Systems Gemini"
-	select CPU_FA526
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	help
-	  Support for the Cortina Systems Gemini family SoCs
-
 config ARCH_FOOTBRIDGE
 	bool "FootBridge"
 	select CPU_SA110
@@ -293,6 +287,30 @@
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
 
+config ARCH_MXC
+	bool "Freescale MXC/iMX-based"
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select ARCH_MTD_XIP
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_CLK
+	help
+	  Support for Freescale MXC/iMX-based family of processors
+
+config ARCH_STMP3XXX
+	bool "Freescale STMP3xxx"
+	select CPU_ARM926T
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select ARCH_REQUIRE_GPIOLIB
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select USB_ARCH_HAS_EHCI
+	help
+	  Support for systems based on the Freescale 3xxx CPUs.
+
 config ARCH_NETX
 	bool "Hilscher NetX based"
 	select CPU_ARM926T
@@ -309,15 +327,6 @@
 	help
 	  This enables support for systems based on the Hynix HMS720x
 
-config ARCH_IMX
-	bool "IMX"
-	select CPU_ARM920T
-	select GENERIC_GPIO
-	select GENERIC_TIME
-	select GENERIC_CLOCKEVENTS
-	help
-	  Support for Motorola's i.MX family of processors (MX1, MXL).
-
 config ARCH_IOP13XX
 	bool "IOP13xx-based"
 	depends on MMU
@@ -398,6 +407,7 @@
 	select CPU_FEROCEON
 	select PCI
 	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select PLAT_ORION
@@ -405,28 +415,6 @@
 	  Support for the following Marvell Kirkwood series SoCs:
 	  88F6180, 88F6192 and 88F6281.
 
-config ARCH_KS8695
-	bool "Micrel/Kendin KS8695"
-	select CPU_ARM922T
-	select GENERIC_GPIO
-        select ARCH_REQUIRE_GPIOLIB
-	help
-	  Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
-	  System-on-Chip devices.
-
-config ARCH_NS9XXX
-	bool "NetSilicon NS9xxx"
-	select CPU_ARM926T
-	select GENERIC_GPIO
-	select GENERIC_TIME
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK
-	help
-	  Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
-	  System.
-
-	  <http://www.digi.com/products/microprocessors/index.jsp>
-
 config ARCH_LOKI
 	bool "Marvell Loki (88RC8480)"
 	select CPU_FEROCEON
@@ -441,6 +429,7 @@
 	select CPU_FEROCEON
 	select PCI
 	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select PLAT_ORION
@@ -448,23 +437,13 @@
 	  Support for the following Marvell MV78xx0 series SoCs:
 	  MV781x0, MV782x0.
 
-config ARCH_MXC
-	bool "Freescale MXC/iMX-based"
-	select GENERIC_TIME
-	select GENERIC_CLOCKEVENTS
-	select ARCH_MTD_XIP
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	select HAVE_CLK
-	help
-	  Support for Freescale MXC/iMX-based family of processors
-
 config ARCH_ORION5X
 	bool "Marvell Orion"
 	depends on MMU
 	select CPU_FEROCEON
 	select PCI
 	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select PLAT_ORION
@@ -473,6 +452,52 @@
 	  Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
 	  Orion-2 (5281), Orion-1-90 (6183).
 
+config ARCH_MMP
+	bool "Marvell PXA168/910"
+	depends on MMU
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select TICK_ONESHOT
+	select PLAT_PXA
+	help
+	  Support for Marvell's PXA168/910 processor line.
+
+config ARCH_KS8695
+	bool "Micrel/Kendin KS8695"
+	select CPU_ARM922T
+	select GENERIC_GPIO
+        select ARCH_REQUIRE_GPIOLIB
+	help
+	  Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
+	  System-on-Chip devices.
+
+config ARCH_NS9XXX
+	bool "NetSilicon NS9xxx"
+	select CPU_ARM926T
+	select GENERIC_GPIO
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK
+	help
+	  Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
+	  System.
+
+	  <http://www.digi.com/products/microprocessors/index.jsp>
+
+config ARCH_W90X900
+	bool "Nuvoton W90X900 CPU"
+	select CPU_ARM926T
+	select ARCH_REQUIRE_GPIOLIB
+	select GENERIC_GPIO
+	select COMMON_CLKDEV
+	help
+		Support for Nuvoton (Winbond logic dept.) ARM9 processor,You
+		can login www.mcuos.com or www.nuvoton.com to know more.
+
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	select CPU_ARM926T
@@ -495,19 +520,16 @@
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
-config ARCH_MMP
-	bool "Marvell PXA168/910"
-	depends on MMU
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	select HAVE_CLK
-	select COMMON_CLKDEV
+config ARCH_MSM
+	bool "Qualcomm MSM"
+	select CPU_V6
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
-	select TICK_ONESHOT
-	select PLAT_PXA
 	help
-	  Support for Marvell's PXA168/910 processor line.
+	  Support for Qualcomm MSM7K based systems.  This runs on the ARM11
+	  apps processor of the MSM7K and depends on a shared memory
+	  interface to the ARM9 modem processor which runs the baseband stack
+	  and controls some vital subsystems (clock and power control, etc).
 
 config ARCH_RPC
 	bool "RiscPC"
@@ -576,6 +598,20 @@
 	  core with a wide array of integrated devices for
 	  hand-held and low-power applications.
 
+config ARCH_U300
+	bool "ST-Ericsson U300 Series"
+	depends on MMU
+	select CPU_ARM926T
+	select ARM_AMBA
+	select ARM_VIC
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select GENERIC_GPIO
+	help
+	  Support for ST-Ericsson U300 series mobile platforms.
+
 config ARCH_DAVINCI
 	bool "TI DaVinci"
 	select CPU_ARM926T
@@ -587,6 +623,7 @@
 	select ZONE_DMA
 	select HAVE_IDE
 	select COMMON_CLKDEV
+	select GENERIC_ALLOCATOR
 	help
 	  Support for TI's DaVinci platform.
 
@@ -600,24 +637,6 @@
 	help
 	  Support for TI's OMAP platform (OMAP1 and OMAP2).
 
-config ARCH_MSM
-	bool "Qualcomm MSM"
-	select CPU_V6
-	select GENERIC_TIME
-	select GENERIC_CLOCKEVENTS
-	help
-	  Support for Qualcomm MSM7K based systems.  This runs on the ARM11
-	  apps processor of the MSM7K and depends on a shared memory
-	  interface to the ARM9 modem processor which runs the baseband stack
-	  and controls some vital subsystems (clock and power control, etc).
-
-config ARCH_W90X900
-	bool "Nuvoton W90X900 CPU"
-	select CPU_ARM926T
-	help
-		Support for Nuvoton (Winbond logic dept.) ARM9 processor,You
-		can login www.mcuos.com or www.nuvoton.com to know more.
-
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -681,9 +700,9 @@
 source "arch/arm/mach-s3c6410/Kconfig"
 endif
 
-source "arch/arm/mach-lh7a40x/Kconfig"
+source "arch/arm/plat-stmp3xxx/Kconfig"
 
-source "arch/arm/mach-imx/Kconfig"
+source "arch/arm/mach-lh7a40x/Kconfig"
 
 source "arch/arm/mach-h720x/Kconfig"
 
@@ -707,6 +726,8 @@
 
 source "arch/arm/mach-msm/Kconfig"
 
+source "arch/arm/mach-u300/Kconfig"
+
 source "arch/arm/mach-w90x900/Kconfig"
 
 # Definitions to make life easier
@@ -859,8 +880,11 @@
 
 config SMP
 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
+	depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
+		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4)
+	depends on GENERIC_CLOCKEVENTS
 	select USE_GENERIC_SMP_HELPERS
+	select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4)
 	help
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -878,6 +902,18 @@
 
 	  If you don't know what to do here, say N.
 
+config HAVE_ARM_SCU
+	bool
+	depends on SMP
+	help
+	  This option enables support for the ARM system coherency unit
+
+config HAVE_ARM_TWD
+	bool
+	depends on SMP
+	help
+	  This options enables support for the ARM timer and watchdog unit
+
 choice
 	prompt "Memory split"
 	default VMSPLIT_3G
@@ -916,8 +952,10 @@
 
 config LOCAL_TIMERS
 	bool "Use local timer interrupts"
-	depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || REALVIEW_EB_A9MP)
+	depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
+		REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4)
 	default y
+	select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4)
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
@@ -979,7 +1017,6 @@
 
 config ARCH_HAS_HOLES_MEMORYMODEL
 	bool
-	default n
 
 # Discontigmem is deprecated
 config ARCH_DISCONTIGMEM_ENABLE
@@ -1022,12 +1059,12 @@
 config LEDS
 	bool "Timer and CPU usage LEDs"
 	depends on ARCH_CDB89712 || ARCH_EBSA110 || \
-		   ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \
+		   ARCH_EBSA285 || ARCH_INTEGRATOR || \
 		   ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
 		   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
 		   ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
 		   ARCH_AT91 || ARCH_DAVINCI || \
-		   ARCH_KS8695 || MACH_RD88F5182
+		   ARCH_KS8695 || MACH_RD88F5182 || ARCH_REALVIEW
 	help
 	  If you say Y here, the LEDs on your machine will be used
 	  to provide useful information about your current system status.
@@ -1085,6 +1122,22 @@
 	  correct operation of some network protocols. With an IP-only
 	  configuration it is safe to say N, otherwise say Y.
 
+config UACCESS_WITH_MEMCPY
+	bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user() (EXPERIMENTAL)"
+	depends on MMU && EXPERIMENTAL
+	default y if CPU_FEROCEON
+	help
+	  Implement faster copy_to_user and clear_user methods for CPU
+	  cores where a 8-word STM instruction give significantly higher
+	  memory write throughput than a sequence of individual 32bit stores.
+
+	  A possible side effect is a slight increase in scheduling latency
+	  between threads sharing the same address space if they invoke
+	  such copy operations with large buffers.
+
+	  However, if the CPU data cache is using a write-allocate mode,
+	  this option is unlikely to provide any performance gain.
+
 endmenu
 
 menu "Boot options"
@@ -1188,7 +1241,7 @@
 
 menu "CPU Power Management"
 
-if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA)
+if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_PXA || ARCH_S3C64XX)
 
 source "drivers/cpufreq/Kconfig"
 
@@ -1213,14 +1266,15 @@
 
 	  If in doubt, say Y.
 
-config CPU_FREQ_IMX
-	tristate "CPUfreq driver for i.MX CPUs"
-	depends on ARCH_IMX && CPU_FREQ
-	default n
-	help
-	  This enables the CPUfreq driver for i.MX CPUs.
+config CPU_FREQ_PXA
+	bool
+	depends on CPU_FREQ && ARCH_PXA && PXA25x
+	default y
+	select CPU_FREQ_DEFAULT_GOV_USERSPACE
 
-	  If in doubt, say N.
+config CPU_FREQ_S3C64XX
+	bool "CPUfreq support for Samsung S3C64XX CPUs"
+	depends on CPU_FREQ && CPU_S3C6410
 
 endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/Kconfig.debug linux-libre-2.6.31-gnu/arch/arm/Kconfig.debug
--- linux-libre-2.6.30-gnu/arch/arm/Kconfig.debug	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/Kconfig.debug	2009-09-09 18:13:59.000000000 -0400
@@ -99,14 +99,6 @@
 	  output to the second serial port on these devices.  Saying N will
 	  cause the debug messages to appear on the first serial port.
 
-config DEBUG_S3C_PORT
-	depends on DEBUG_LL && PLAT_S3C
-	bool "Kernel low-level debugging messages via S3C UART"
-	help
-	  Say Y here if you want debug print routines to go to one of the
-	  S3C internal UARTs. The chosen UART must have been configured
-	  before it is used.
-
 config DEBUG_S3C_UART
 	depends on PLAT_S3C
 	int "S3C UART to use for low-level debug"
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/calls.S linux-libre-2.6.31-gnu/arch/arm/kernel/calls.S
--- linux-libre-2.6.30-gnu/arch/arm/kernel/calls.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/calls.S	2009-09-09 18:13:59.000000000 -0400
@@ -372,6 +372,8 @@
 /* 360 */	CALL(sys_inotify_init1)
 		CALL(sys_preadv)
 		CALL(sys_pwritev)
+		CALL(sys_rt_tgsigqueueinfo)
+		CALL(sys_perf_counter_open)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/entry-armv.S linux-libre-2.6.31-gnu/arch/arm/kernel/entry-armv.S
--- linux-libre-2.6.30-gnu/arch/arm/kernel/entry-armv.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/entry-armv.S	2009-09-09 18:13:59.000000000 -0400
@@ -482,6 +482,9 @@
 	subeq	r4, r2, #4			@ ARM instr at LR - 4
 	subne	r4, r2, #2			@ Thumb instr at LR - 2
 1:	ldreqt	r0, [r4]
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	reveq	r0, r0				@ little endian instruction
+#endif
 	beq	call_fpe
 	@ Thumb instruction
 #if __LINUX_ARM_ARCH__ >= 7
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/entry-common.S linux-libre-2.6.31-gnu/arch/arm/kernel/entry-common.S
--- linux-libre-2.6.30-gnu/arch/arm/kernel/entry-common.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/entry-common.S	2009-09-09 18:13:59.000000000 -0400
@@ -148,7 +148,7 @@
 	sub r0, r0, #MCOUNT_INSN_SIZE
 	mov lr, pc
 	mov pc, r2
-	mov lr, r1				@ restore lr
+	ldr lr, [fp, #-4]			@ restore lr
 	ldmia sp!, {r0-r3, pc}
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
@@ -210,6 +210,9 @@
   A710(	teq	ip, #0x0f000000						)
   A710(	bne	.Larm710bug						)
 #endif
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	rev	r10, r10			@ little endian instruction
+#endif
 
 #elif defined(CONFIG_AEABI)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/init_task.c linux-libre-2.6.31-gnu/arch/arm/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,10 +14,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/irq.c linux-libre-2.6.31-gnu/arch/arm/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,17 +98,6 @@
 	return 0;
 }
 
-/* Handle bad interrupts */
-static struct irq_desc bad_irq_desc = {
-	.handle_irq = handle_bad_irq,
-	.lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock),
-};
-
-#ifdef CONFIG_CPUMASK_OFFSTACK
-/* We are not allocating bad_irq_desc.affinity or .pending_mask */
-#error "ARM architecture does not support CONFIG_CPUMASK_OFFSTACK."
-#endif
-
 /*
  * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
  * come via this function.  Instead, they should provide their
@@ -124,10 +113,13 @@
 	 * Some hardware gives randomly wrong interrupts.  Rather
 	 * than crashing, do something sensible.
 	 */
-	if (irq >= NR_IRQS)
-		handle_bad_irq(irq, &bad_irq_desc);
-	else
+	if (unlikely(irq >= NR_IRQS)) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING "Bad IRQ%u\n", irq);
+		ack_bad_irq(irq);
+	} else {
 		generic_handle_irq(irq);
+	}
 
 	/* AT91 specific workaround */
 	irq_finish(irq);
@@ -165,10 +157,6 @@
 	for (irq = 0; irq < NR_IRQS; irq++)
 		irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
 
-#ifdef CONFIG_SMP
-	cpumask_setall(bad_irq_desc.affinity);
-	bad_irq_desc.cpu = smp_processor_id();
-#endif
 	init_arch_irq();
 }
 
@@ -176,7 +164,7 @@
 
 static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
 {
-	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu);
+	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->node, cpu);
 
 	spin_lock_irq(&desc->lock);
 	desc->chip->set_affinity(irq, cpumask_of(cpu));
@@ -195,7 +183,7 @@
 	for (i = 0; i < NR_IRQS; i++) {
 		struct irq_desc *desc = irq_desc + i;
 
-		if (desc->cpu == cpu) {
+		if (desc->node == cpu) {
 			unsigned int newcpu = cpumask_any_and(desc->affinity,
 							      cpu_online_mask);
 			if (newcpu >= nr_cpu_ids) {
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/Makefile linux-libre-2.6.31-gnu/arch/arm/kernel/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/kernel/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,8 @@
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
 obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
+obj-$(CONFIG_HAVE_ARM_TWD)	+= smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-decode.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/process.c linux-libre-2.6.31-gnu/arch/arm/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -114,9 +114,6 @@
 /*
  * Function pointers to optional machine specific functions
  */
-void (*pm_idle)(void);
-EXPORT_SYMBOL(pm_idle);
-
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
@@ -130,20 +127,19 @@
  */
 static void default_idle(void)
 {
-	if (hlt_counter)
-		cpu_relax();
-	else {
-		local_irq_disable();
-		if (!need_resched())
-			arch_idle();
-		local_irq_enable();
-	}
+	if (!need_resched())
+		arch_idle();
+	local_irq_enable();
 }
 
+void (*pm_idle)(void) = default_idle;
+EXPORT_SYMBOL(pm_idle);
+
 /*
- * The idle thread.  We try to conserve power, while trying to keep
- * overall latency low.  The architecture specific idle is passed
- * a value to indicate the level of "idleness" of the system.
+ * The idle thread, has rather strange semantics for calling pm_idle,
+ * but this is what x86 does and we need to do the same, so that
+ * things like cpuidle get called in the same way.  The only difference
+ * is that we always respect 'hlt_counter' to prevent low power idle.
  */
 void cpu_idle(void)
 {
@@ -151,21 +147,31 @@
 
 	/* endless idle loop with no priority at all */
 	while (1) {
-		void (*idle)(void) = pm_idle;
-
+		tick_nohz_stop_sched_tick(1);
+		leds_event(led_idle_start);
+		while (!need_resched()) {
 #ifdef CONFIG_HOTPLUG_CPU
-		if (cpu_is_offline(smp_processor_id())) {
-			leds_event(led_idle_start);
-			cpu_die();
-		}
+			if (cpu_is_offline(smp_processor_id()))
+				cpu_die();
 #endif
 
-		if (!idle)
-			idle = default_idle;
-		leds_event(led_idle_start);
-		tick_nohz_stop_sched_tick(1);
-		while (!need_resched())
-			idle();
+			local_irq_disable();
+			if (hlt_counter) {
+				local_irq_enable();
+				cpu_relax();
+			} else {
+				stop_critical_timings();
+				pm_idle();
+				start_critical_timings();
+				/*
+				 * This will eventually be removed - pm_idle
+				 * functions should always return with IRQs
+				 * enabled.
+				 */
+				WARN_ON(irqs_disabled());
+				local_irq_enable();
+			}
+		}
 		leds_event(led_idle_end);
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
@@ -352,6 +358,23 @@
 "	.size	kernel_thread_helper, . - kernel_thread_helper\n"
 "	.previous");
 
+#ifdef CONFIG_ARM_UNWIND
+extern void kernel_thread_exit(long code);
+asm(	".section .text\n"
+"	.align\n"
+"	.type	kernel_thread_exit, #function\n"
+"kernel_thread_exit:\n"
+"	.fnstart\n"
+"	.cantunwind\n"
+"	bl	do_exit\n"
+"	nop\n"
+"	.fnend\n"
+"	.size	kernel_thread_exit, . - kernel_thread_exit\n"
+"	.previous");
+#else
+#define kernel_thread_exit	do_exit
+#endif
+
 /*
  * Create a kernel thread.
  */
@@ -363,9 +386,9 @@
 
 	regs.ARM_r1 = (unsigned long)arg;
 	regs.ARM_r2 = (unsigned long)fn;
-	regs.ARM_r3 = (unsigned long)do_exit;
+	regs.ARM_r3 = (unsigned long)kernel_thread_exit;
 	regs.ARM_pc = (unsigned long)kernel_thread_helper;
-	regs.ARM_cpsr = SVC_MODE;
+	regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE;
 
 	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/signal.c linux-libre-2.6.31-gnu/arch/arm/kernel/signal.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/signal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/signal.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,7 +133,7 @@
 }
 
 #ifdef CONFIG_CRUNCH
-static int preserve_crunch_context(struct crunch_sigframe *frame)
+static int preserve_crunch_context(struct crunch_sigframe __user *frame)
 {
 	char kbuf[sizeof(*frame) + 8];
 	struct crunch_sigframe *kframe;
@@ -146,7 +146,7 @@
 	return __copy_to_user(frame, kframe, sizeof(*frame));
 }
 
-static int restore_crunch_context(struct crunch_sigframe *frame)
+static int restore_crunch_context(struct crunch_sigframe __user *frame)
 {
 	char kbuf[sizeof(*frame) + 8];
 	struct crunch_sigframe *kframe;
@@ -426,9 +426,13 @@
 		 */
 		thumb = handler & 1;
 
-		if (thumb)
+		if (thumb) {
 			cpsr |= PSR_T_BIT;
-		else
+#if __LINUX_ARM_ARCH__ >= 7
+			/* clear the If-Then Thumb-2 execution state */
+			cpsr &= ~PSR_IT_MASK;
+#endif
+		} else
 			cpsr &= ~PSR_T_BIT;
 	}
 #endif
@@ -532,7 +536,7 @@
 	return err;
 }
 
-static inline void restart_syscall(struct pt_regs *regs)
+static inline void setup_syscall_restart(struct pt_regs *regs)
 {
 	regs->ARM_r0 = regs->ARM_ORIG_r0;
 	regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
@@ -567,7 +571,7 @@
 			}
 			/* fallthrough */
 		case -ERESTARTNOINTR:
-			restart_syscall(regs);
+			setup_syscall_restart(regs);
 		}
 	}
 
@@ -691,7 +695,7 @@
 		if (regs->ARM_r0 == -ERESTARTNOHAND ||
 		    regs->ARM_r0 == -ERESTARTSYS ||
 		    regs->ARM_r0 == -ERESTARTNOINTR) {
-			restart_syscall(regs);
+			setup_syscall_restart(regs);
 		}
 	}
 	single_step_set(current);
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/smp.c linux-libre-2.6.31-gnu/arch/arm/kernel/smp.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,16 +22,20 @@
 #include <linux/smp.h>
 #include <linux/seq_file.h>
 #include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/clockchips.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
+#include <asm/cputype.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
+#include <asm/localtimer.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
@@ -163,7 +167,7 @@
 	 * Take this CPU offline.  Once we clear this, we can't return,
 	 * and we must not schedule until we're ready to give up the cpu.
 	 */
-	cpu_clear(cpu, cpu_online_map);
+	set_cpu_online(cpu, false);
 
 	/*
 	 * OK - migrate IRQs away from this CPU
@@ -274,9 +278,9 @@
 	local_fiq_enable();
 
 	/*
-	 * Setup local timer for this CPU.
+	 * Setup the percpu timer for this CPU.
 	 */
-	local_timer_setup();
+	percpu_timer_setup();
 
 	calibrate_delay();
 
@@ -285,7 +289,7 @@
 	/*
 	 * OK, now it's safe to let the boot CPU continue
 	 */
-	cpu_set(cpu, cpu_online_map);
+	set_cpu_online(cpu, true);
 
 	/*
 	 * OK, it's off to the idle thread for us
@@ -383,10 +387,16 @@
 	seq_putc(p, '\n');
 }
 
+/*
+ * Timer (local or broadcast) support
+ */
+static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
+
 static void ipi_timer(void)
 {
+	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
 	irq_enter();
-	local_timer_interrupt();
+	evt->event_handler(evt);
 	irq_exit();
 }
 
@@ -405,6 +415,42 @@
 }
 #endif
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+static void smp_timer_broadcast(const struct cpumask *mask)
+{
+	send_ipi_message(mask, IPI_TIMER);
+}
+
+static void broadcast_timer_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+}
+
+static void local_timer_setup(struct clock_event_device *evt)
+{
+	evt->name	= "dummy_timer";
+	evt->features	= CLOCK_EVT_FEAT_ONESHOT |
+			  CLOCK_EVT_FEAT_PERIODIC |
+			  CLOCK_EVT_FEAT_DUMMY;
+	evt->rating	= 400;
+	evt->mult	= 1;
+	evt->set_mode	= broadcast_timer_set_mode;
+	evt->broadcast	= smp_timer_broadcast;
+
+	clockevents_register_device(evt);
+}
+#endif
+
+void __cpuinit percpu_timer_setup(void)
+{
+	unsigned int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
+
+	evt->cpumask = cpumask_of(cpu);
+
+	local_timer_setup(evt);
+}
+
 static DEFINE_SPINLOCK(stop_lock);
 
 /*
@@ -417,7 +463,7 @@
 	dump_stack();
 	spin_unlock(&stop_lock);
 
-	cpu_clear(cpu, cpu_online_map);
+	set_cpu_online(cpu, false);
 
 	local_fiq_disable();
 	local_irq_disable();
@@ -501,11 +547,6 @@
 	send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
 }
 
-void smp_timer_broadcast(const struct cpumask *mask)
-{
-	send_ipi_message(mask, IPI_TIMER);
-}
-
 void smp_send_stop(void)
 {
 	cpumask_t mask = cpu_online_map;
@@ -545,6 +586,12 @@
 	unsigned long ta_end;
 };
 
+/* all SMP configurations have the extended CPUID registers */
+static inline int tlb_ops_need_broadcast(void)
+{
+	return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
+}
+
 static inline void ipi_flush_tlb_all(void *ignored)
 {
 	local_flush_tlb_all();
@@ -587,51 +634,61 @@
 
 void flush_tlb_all(void)
 {
-	on_each_cpu(ipi_flush_tlb_all, NULL, 1);
+	if (tlb_ops_need_broadcast())
+		on_each_cpu(ipi_flush_tlb_all, NULL, 1);
+	else
+		local_flush_tlb_all();
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
 {
-	on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, &mm->cpu_vm_mask);
+	if (tlb_ops_need_broadcast())
+		on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, &mm->cpu_vm_mask);
+	else
+		local_flush_tlb_mm(mm);
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
 {
-	struct tlb_args ta;
-
-	ta.ta_vma = vma;
-	ta.ta_start = uaddr;
-
-	on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, &vma->vm_mm->cpu_vm_mask);
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_vma = vma;
+		ta.ta_start = uaddr;
+		on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, &vma->vm_mm->cpu_vm_mask);
+	} else
+		local_flush_tlb_page(vma, uaddr);
 }
 
 void flush_tlb_kernel_page(unsigned long kaddr)
 {
-	struct tlb_args ta;
-
-	ta.ta_start = kaddr;
-
-	on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_start = kaddr;
+		on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
+	} else
+		local_flush_tlb_kernel_page(kaddr);
 }
 
 void flush_tlb_range(struct vm_area_struct *vma,
                      unsigned long start, unsigned long end)
 {
-	struct tlb_args ta;
-
-	ta.ta_vma = vma;
-	ta.ta_start = start;
-	ta.ta_end = end;
-
-	on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, &vma->vm_mm->cpu_vm_mask);
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_vma = vma;
+		ta.ta_start = start;
+		ta.ta_end = end;
+		on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, &vma->vm_mm->cpu_vm_mask);
+	} else
+		local_flush_tlb_range(vma, start, end);
 }
 
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
-	struct tlb_args ta;
-
-	ta.ta_start = start;
-	ta.ta_end = end;
-
-	on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
+	if (tlb_ops_need_broadcast()) {
+		struct tlb_args ta;
+		ta.ta_start = start;
+		ta.ta_end = end;
+		on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
+	} else
+		local_flush_tlb_kernel_range(start, end);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/smp_scu.c linux-libre-2.6.31-gnu/arch/arm/kernel/smp_scu.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/smp_scu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/smp_scu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,48 @@
+/*
+ *  linux/arch/arm/kernel/smp_scu.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/smp_scu.h>
+#include <asm/cacheflush.h>
+
+#define SCU_CTRL		0x00
+#define SCU_CONFIG		0x04
+#define SCU_CPU_STATUS		0x08
+#define SCU_INVALIDATE		0x0c
+#define SCU_FPGA_REVISION	0x10
+
+/*
+ * Get the number of CPU cores from the SCU configuration
+ */
+unsigned int __init scu_get_core_count(void __iomem *scu_base)
+{
+	unsigned int ncores = __raw_readl(scu_base + SCU_CONFIG);
+	return (ncores & 0x03) + 1;
+}
+
+/*
+ * Enable the SCU
+ */
+void __init scu_enable(void __iomem *scu_base)
+{
+	u32 scu_ctrl;
+
+	scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
+	scu_ctrl |= 1;
+	__raw_writel(scu_ctrl, scu_base + SCU_CTRL);
+
+	/*
+	 * Ensure that the data accessed by CPU0 before the SCU was
+	 * initialised is visible to the other CPUs.
+	 */
+	flush_cache_all();
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/smp_twd.c linux-libre-2.6.31-gnu/arch/arm/kernel/smp_twd.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/smp_twd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/smp_twd.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,175 @@
+/*
+ *  linux/arch/arm/kernel/smp_twd.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/jiffies.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/smp_twd.h>
+#include <asm/hardware/gic.h>
+
+#define TWD_TIMER_LOAD 			0x00
+#define TWD_TIMER_COUNTER		0x04
+#define TWD_TIMER_CONTROL		0x08
+#define TWD_TIMER_INTSTAT		0x0C
+
+#define TWD_WDOG_LOAD			0x20
+#define TWD_WDOG_COUNTER		0x24
+#define TWD_WDOG_CONTROL		0x28
+#define TWD_WDOG_INTSTAT		0x2C
+#define TWD_WDOG_RESETSTAT		0x30
+#define TWD_WDOG_DISABLE		0x34
+
+#define TWD_TIMER_CONTROL_ENABLE	(1 << 0)
+#define TWD_TIMER_CONTROL_ONESHOT	(0 << 1)
+#define TWD_TIMER_CONTROL_PERIODIC	(1 << 1)
+#define TWD_TIMER_CONTROL_IT_ENABLE	(1 << 2)
+
+/* set up by the platform code */
+void __iomem *twd_base;
+
+static unsigned long twd_timer_rate;
+
+static void twd_set_mode(enum clock_event_mode mode,
+			struct clock_event_device *clk)
+{
+	unsigned long ctrl;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* timer load already set up */
+		ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
+			| TWD_TIMER_CONTROL_PERIODIC;
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* period set, and timer enabled in 'next_event' hook */
+		ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		ctrl = 0;
+	}
+
+	__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
+}
+
+static int twd_set_next_event(unsigned long evt,
+			struct clock_event_device *unused)
+{
+	unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+
+	ctrl |= TWD_TIMER_CONTROL_ENABLE;
+
+	__raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
+	__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
+
+	return 0;
+}
+
+/*
+ * local_timer_ack: checks for a local timer interrupt.
+ *
+ * If a local timer interrupt has occurred, acknowledge and return 1.
+ * Otherwise, return 0.
+ */
+int twd_timer_ack(void)
+{
+	if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
+		__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
+		return 1;
+	}
+
+	return 0;
+}
+
+static void __cpuinit twd_calibrate_rate(void)
+{
+	unsigned long load, count;
+	u64 waitjiffies;
+
+	/*
+	 * If this is the first time round, we need to work out how fast
+	 * the timer ticks
+	 */
+	if (twd_timer_rate == 0) {
+		printk(KERN_INFO "Calibrating local timer... ");
+
+		/* Wait for a tick to start */
+		waitjiffies = get_jiffies_64() + 1;
+
+		while (get_jiffies_64() < waitjiffies)
+			udelay(10);
+
+		/* OK, now the tick has started, let's get the timer going */
+		waitjiffies += 5;
+
+				 /* enable, no interrupt or reload */
+		__raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
+
+				 /* maximum value */
+		__raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
+
+		while (get_jiffies_64() < waitjiffies)
+			udelay(10);
+
+		count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
+
+		twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
+
+		printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
+			(twd_timer_rate / 100000) % 100);
+	}
+
+	load = twd_timer_rate / HZ;
+
+	__raw_writel(load, twd_base + TWD_TIMER_LOAD);
+}
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit twd_timer_setup(struct clock_event_device *clk)
+{
+	unsigned long flags;
+
+	twd_calibrate_rate();
+
+	clk->name = "local_timer";
+	clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	clk->rating = 350;
+	clk->set_mode = twd_set_mode;
+	clk->set_next_event = twd_set_next_event;
+	clk->shift = 20;
+	clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift);
+	clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
+	clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
+
+	/* Make sure our local interrupt controller has this enabled */
+	local_irq_save(flags);
+	get_irq_chip(clk->irq)->unmask(clk->irq);
+	local_irq_restore(flags);
+
+	clockevents_register_device(clk);
+}
+
+/*
+ * take a local timer down
+ */
+void __cpuexit twd_timer_stop(void)
+{
+	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/unwind.c linux-libre-2.6.31-gnu/arch/arm/kernel/unwind.c
--- linux-libre-2.6.30-gnu/arch/arm/kernel/unwind.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/unwind.c	2009-09-09 18:13:59.000000000 -0400
@@ -212,7 +212,8 @@
 			ctrl->vrs[14] = *vsp++;
 		ctrl->vrs[SP] = (unsigned long)vsp;
 	} else if (insn == 0xb0) {
-		ctrl->vrs[PC] = ctrl->vrs[LR];
+		if (ctrl->vrs[PC] == 0)
+			ctrl->vrs[PC] = ctrl->vrs[LR];
 		/* no further processing */
 		ctrl->entries = 0;
 	} else if (insn == 0xb1) {
@@ -309,18 +310,20 @@
 	}
 
 	while (ctrl.entries > 0) {
-		int urc;
-
-		if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
-			return -URC_FAILURE;
-		urc = unwind_exec_insn(&ctrl);
+		int urc = unwind_exec_insn(&ctrl);
 		if (urc < 0)
 			return urc;
+		if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
+			return -URC_FAILURE;
 	}
 
 	if (ctrl.vrs[PC] == 0)
 		ctrl.vrs[PC] = ctrl.vrs[LR];
 
+	/* check for infinite loop */
+	if (frame->pc == ctrl.vrs[PC])
+		return -URC_FAILURE;
+
 	frame->fp = ctrl.vrs[FP];
 	frame->sp = ctrl.vrs[SP];
 	frame->lr = ctrl.vrs[LR];
@@ -332,7 +335,6 @@
 void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 {
 	struct stackframe frame;
-	unsigned long high, low;
 	register unsigned long current_sp asm ("sp");
 
 	pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
@@ -362,9 +364,6 @@
 		frame.pc = thread_saved_pc(tsk);
 	}
 
-	low = frame.sp & ~(THREAD_SIZE - 1);
-	high = low + THREAD_SIZE;
-
 	while (1) {
 		int urc;
 		unsigned long where = frame.pc;
diff -druN linux-libre-2.6.30-gnu/arch/arm/kernel/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/arm/kernel/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/arm/kernel/vmlinux.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/kernel/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,7 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
+#include <asm/page.h>
 	
 OUTPUT_ARCH(arm)
 ENTRY(stext)
@@ -63,7 +64,7 @@
 			usr/built-in.o(.init.ramfs)
 		__initramfs_end = .;
 #endif
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__per_cpu_load = .;
 		__per_cpu_start = .;
 			*(.data.percpu.page_aligned)
@@ -73,7 +74,7 @@
 #ifndef CONFIG_XIP_KERNEL
 		__init_begin = _stext;
 		INIT_DATA
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__init_end = .;
 #endif
 	}
@@ -84,6 +85,14 @@
 		*(.exitcall.exit)
 		*(.ARM.exidx.exit.text)
 		*(.ARM.extab.exit.text)
+#ifndef CONFIG_HOTPLUG_CPU
+		*(.ARM.exidx.cpuexit.text)
+		*(.ARM.extab.cpuexit.text)
+#endif
+#ifndef CONFIG_HOTPLUG
+		*(.ARM.exidx.devexit.text)
+		*(.ARM.extab.devexit.text)
+#endif
 #ifndef CONFIG_MMU
 		*(.fixup)
 		*(__ex_table)
@@ -110,7 +119,7 @@
 		*(.got)			/* Global offset table		*/
 	}
 
-	RODATA
+	RO_DATA(PAGE_SIZE)
 
 	_etext = .;			/* End of text and rodata section */
 
@@ -141,6 +150,7 @@
 
 	.data : AT(__data_loc) {
 		_data = .;		/* address in memory */
+		_sdata = .;
 
 		/*
 		 * first, the init task union, aligned
@@ -149,17 +159,17 @@
 		*(.data.init_task)
 
 #ifdef CONFIG_XIP_KERNEL
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__init_begin = .;
 		INIT_DATA
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__init_end = .;
 #endif
 
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__nosave_begin = .;
 		*(.data.nosave)
-		. = ALIGN(4096);
+		. = ALIGN(PAGE_SIZE);
 		__nosave_end = .;
 
 		/*
@@ -192,6 +202,7 @@
 		__bss_start = .;	/* BSS				*/
 		*(.bss)
 		*(COMMON)
+		__bss_stop = .;
 		_end = .;
 	}
 					/* Stabs debugging sections.	*/
diff -druN linux-libre-2.6.30-gnu/arch/arm/lib/clear_user.S linux-libre-2.6.31-gnu/arch/arm/lib/clear_user.S
--- linux-libre-2.6.30-gnu/arch/arm/lib/clear_user.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/lib/clear_user.S	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,8 @@
  *          : sz   - number of bytes to clear
  * Returns  : number of bytes NOT cleared
  */
-ENTRY(__clear_user)
+ENTRY(__clear_user_std)
+WEAK(__clear_user)
 		stmfd	sp!, {r1, lr}
 		mov	r2, #0
 		cmp	r1, #4
diff -druN linux-libre-2.6.30-gnu/arch/arm/lib/copy_to_user.S linux-libre-2.6.31-gnu/arch/arm/lib/copy_to_user.S
--- linux-libre-2.6.30-gnu/arch/arm/lib/copy_to_user.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/lib/copy_to_user.S	2009-09-09 18:13:59.000000000 -0400
@@ -86,7 +86,8 @@
 
 	.text
 
-ENTRY(__copy_to_user)
+ENTRY(__copy_to_user_std)
+WEAK(__copy_to_user)
 
 #include "copy_template.S"
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/lib/Makefile linux-libre-2.6.31-gnu/arch/arm/lib/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/lib/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/lib/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,9 @@
 endif
 endif
 
+# using lib_ here won't override already available weak symbols
+obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o
+
 lib-$(CONFIG_MMU) += $(mmu-y)
 
 ifeq ($(CONFIG_CPU_32v3),y)
diff -druN linux-libre-2.6.30-gnu/arch/arm/lib/uaccess_with_memcpy.c linux-libre-2.6.31-gnu/arch/arm/lib/uaccess_with_memcpy.c
--- linux-libre-2.6.30-gnu/arch/arm/lib/uaccess_with_memcpy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/lib/uaccess_with_memcpy.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,228 @@
+/*
+ *  linux/arch/arm/lib/uaccess_with_memcpy.c
+ *
+ *  Written by: Lennert Buytenhek and Nicolas Pitre
+ *  Copyright (C) 2009 Marvell Semiconductor
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/uaccess.h>
+#include <linux/rwsem.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h> /* for in_atomic() */
+#include <asm/current.h>
+#include <asm/page.h>
+
+static int
+pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
+{
+	unsigned long addr = (unsigned long)_addr;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	spinlock_t *ptl;
+
+	pgd = pgd_offset(current->mm, addr);
+	if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd)))
+		return 0;
+
+	pmd = pmd_offset(pgd, addr);
+	if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
+		return 0;
+
+	pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
+	if (unlikely(!pte_present(*pte) || !pte_young(*pte) ||
+	    !pte_write(*pte) || !pte_dirty(*pte))) {
+		pte_unmap_unlock(pte, ptl);
+		return 0;
+	}
+
+	*ptep = pte;
+	*ptlp = ptl;
+
+	return 1;
+}
+
+static unsigned long noinline
+__copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
+{
+	int atomic;
+
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
+		memcpy((void *)to, from, n);
+		return 0;
+	}
+
+	/* the mmap semaphore is taken only if not in an atomic context */
+	atomic = in_atomic();
+
+	if (!atomic)
+		down_read(&current->mm->mmap_sem);
+	while (n) {
+		pte_t *pte;
+		spinlock_t *ptl;
+		int tocopy;
+
+		while (!pin_page_for_write(to, &pte, &ptl)) {
+			if (!atomic)
+				up_read(&current->mm->mmap_sem);
+			if (__put_user(0, (char __user *)to))
+				goto out;
+			if (!atomic)
+				down_read(&current->mm->mmap_sem);
+		}
+
+		tocopy = (~(unsigned long)to & ~PAGE_MASK) + 1;
+		if (tocopy > n)
+			tocopy = n;
+
+		memcpy((void *)to, from, tocopy);
+		to += tocopy;
+		from += tocopy;
+		n -= tocopy;
+
+		pte_unmap_unlock(pte, ptl);
+	}
+	if (!atomic)
+		up_read(&current->mm->mmap_sem);
+
+out:
+	return n;
+}
+
+unsigned long
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	/*
+	 * This test is stubbed out of the main function above to keep
+	 * the overhead for small copies low by avoiding a large
+	 * register dump on the stack just to reload them right away.
+	 * With frame pointer disabled, tail call optimization kicks in
+	 * as well making this test almost invisible.
+	 */
+	if (n < 64)
+		return __copy_to_user_std(to, from, n);
+	return __copy_to_user_memcpy(to, from, n);
+}
+	
+static unsigned long noinline
+__clear_user_memset(void __user *addr, unsigned long n)
+{
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
+		memset((void *)addr, 0, n);
+		return 0;
+	}
+
+	down_read(&current->mm->mmap_sem);
+	while (n) {
+		pte_t *pte;
+		spinlock_t *ptl;
+		int tocopy;
+
+		while (!pin_page_for_write(addr, &pte, &ptl)) {
+			up_read(&current->mm->mmap_sem);
+			if (__put_user(0, (char __user *)addr))
+				goto out;
+			down_read(&current->mm->mmap_sem);
+		}
+
+		tocopy = (~(unsigned long)addr & ~PAGE_MASK) + 1;
+		if (tocopy > n)
+			tocopy = n;
+
+		memset((void *)addr, 0, tocopy);
+		addr += tocopy;
+		n -= tocopy;
+
+		pte_unmap_unlock(pte, ptl);
+	}
+	up_read(&current->mm->mmap_sem);
+
+out:
+	return n;
+}
+
+unsigned long __clear_user(void __user *addr, unsigned long n)
+{
+	/* See rational for this in __copy_to_user() above. */
+	if (n < 64)
+		return __clear_user_std(addr, n);
+	return __clear_user_memset(addr, n);
+}
+
+#if 0
+
+/*
+ * This code is disabled by default, but kept around in case the chosen
+ * thresholds need to be revalidated.  Some overhead (small but still)
+ * would be implied by a runtime determined variable threshold, and
+ * so far the measurement on concerned targets didn't show a worthwhile
+ * variation.
+ *
+ * Note that a fairly precise sched_clock() implementation is needed
+ * for results to make some sense.
+ */
+
+#include <linux/vmalloc.h>
+
+static int __init test_size_treshold(void)
+{
+	struct page *src_page, *dst_page;
+	void *user_ptr, *kernel_ptr;
+	unsigned long long t0, t1, t2;
+	int size, ret;
+
+	ret = -ENOMEM;
+	src_page = alloc_page(GFP_KERNEL);
+	if (!src_page)
+		goto no_src;
+	dst_page = alloc_page(GFP_KERNEL);
+	if (!dst_page)
+		goto no_dst;
+	kernel_ptr = page_address(src_page);
+	user_ptr = vmap(&dst_page, 1, VM_IOREMAP, __pgprot(__P010));
+	if (!user_ptr)
+		goto no_vmap;
+
+	/* warm up the src page dcache */
+	ret = __copy_to_user_memcpy(user_ptr, kernel_ptr, PAGE_SIZE);
+
+	for (size = PAGE_SIZE; size >= 4; size /= 2) {
+		t0 = sched_clock();
+		ret |= __copy_to_user_memcpy(user_ptr, kernel_ptr, size);
+		t1 = sched_clock();
+		ret |= __copy_to_user_std(user_ptr, kernel_ptr, size);
+		t2 = sched_clock();
+		printk("copy_to_user: %d %llu %llu\n", size, t1 - t0, t2 - t1);
+	}
+
+	for (size = PAGE_SIZE; size >= 4; size /= 2) {
+		t0 = sched_clock();
+		ret |= __clear_user_memset(user_ptr, size);
+		t1 = sched_clock();
+		ret |= __clear_user_std(user_ptr, size);
+		t2 = sched_clock();
+		printk("clear_user: %d %llu %llu\n", size, t1 - t0, t2 - t1);
+	}
+
+	if (ret)
+		ret = -EFAULT;
+
+	vunmap(user_ptr);
+no_vmap:
+	put_page(dst_page);
+no_dst:
+	put_page(src_page);
+no_src:
+	return ret;
+}
+
+subsys_initcall(test_size_treshold);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-at91/board-afeb-9260v1.c linux-libre-2.6.31-gnu/arch/arm/mach-at91/board-afeb-9260v1.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-at91/board-afeb-9260v1.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-at91/board-afeb-9260v1.c	2009-09-09 18:13:59.000000000 -0400
@@ -156,6 +156,8 @@
  * MCI (SD/MMC)
  */
 static struct at91_mmc_data __initdata afeb9260_mmc_data = {
+	.det_pin 	= AT91_PIN_PC9,
+	.wp_pin 	= AT91_PIN_PC4,
 	.slot_b		= 1,
 	.wire4		= 1,
 };
@@ -164,6 +166,8 @@
 
 static struct i2c_board_info __initdata afeb9260_i2c_devices[] = {
 	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
+	}, {
 		I2C_BOARD_INFO("fm3130", 0x68),
 	}, {
 		I2C_BOARD_INFO("24c64", 0x50),
@@ -196,6 +200,8 @@
 	/* I2C */
 	at91_add_device_i2c(afeb9260_i2c_devices,
 			ARRAY_SIZE(afeb9260_i2c_devices));
+	/* Audio */
+	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
 }
 
 MACHINE_START(AFEB9260, "Custom afeb9260 board")
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-at91/board-sam9g20ek.c linux-libre-2.6.31-gnu/arch/arm/mach-at91/board-sam9g20ek.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-at91/board-sam9g20ek.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-at91/board-sam9g20ek.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,8 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/at73c213.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
 #include <linux/clk.h>
 
 #include <mach/hardware.h>
@@ -218,6 +220,63 @@
 	}
 };
 
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+	{
+		.gpio		= AT91_PIN_PA30,
+		.code		= BTN_3,
+		.desc		= "Button 3",
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+	{
+		.gpio		= AT91_PIN_PA31,
+		.code		= BTN_4,
+		.desc		= "Button 4",
+		.active_low	= 1,
+		.wakeup		= 1,
+	}
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+	.buttons	= ek_buttons,
+	.nbuttons	= ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &ek_button_data,
+	}
+};
+
+static void __init ek_add_device_buttons(void)
+{
+	at91_set_gpio_input(AT91_PIN_PA30, 1);	/* btn3 */
+	at91_set_deglitch(AT91_PIN_PA30, 1);
+	at91_set_gpio_input(AT91_PIN_PA31, 1);	/* btn4 */
+	at91_set_deglitch(AT91_PIN_PA31, 1);
+
+	platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
+
+static struct i2c_board_info __initdata ek_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("24c512", 0x50),
+	},
+};
+
+
 static void __init ek_board_init(void)
 {
 	/* Serial */
@@ -235,9 +294,11 @@
 	/* MMC */
 	at91_add_device_mmc(0, &ek_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+	/* Push Buttons */
+	ek_add_device_buttons();
 	/* PCK0 provides MCLK to the WM8731 */
 	at91_set_B_periph(AT91_PIN_PC1, 0);
 	/* SSC (for WM8731) */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-at91/board-sam9rlek.c linux-libre-2.6.31-gnu/arch/arm/mach-at91/board-sam9rlek.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-at91/board-sam9rlek.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-at91/board-sam9rlek.c	2009-09-09 18:13:59.000000000 -0400
@@ -186,19 +186,21 @@
 static void at91_lcdc_power_control(int on)
 {
 	if (on)
-		at91_set_gpio_value(AT91_PIN_PA30, 0);	/* power up */
+		at91_set_gpio_value(AT91_PIN_PC1, 0);	/* power up */
 	else
-		at91_set_gpio_value(AT91_PIN_PA30, 1);	/* power down */
+		at91_set_gpio_value(AT91_PIN_PC1, 1);	/* power down */
 }
 
 /* Driver datas */
 static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+	.lcdcon_is_backlight            = true,
 	.default_bpp			= 16,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
 	.default_lcdcon2		= AT91SAM9RL_DEFAULT_LCDCON2,
 	.default_monspecs		= &at91fb_default_monspecs,
 	.atmel_lcdfb_power_control	= at91_lcdc_power_control,
 	.guard_time			= 1,
+	.lcd_wiring_mode		= ATMEL_LCDC_WIRING_RGB,
 };
 
 #else
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-at91/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-at91/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-at91/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-at91/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,6 +43,25 @@
 #define clk_is_sys(x)		((x)->type & CLK_TYPE_SYSTEM)
 
 
+/*
+ * Chips have some kind of clocks : group them by functionality
+ */
+#define cpu_has_utmi()		(  cpu_is_at91cap9() \
+				|| cpu_is_at91sam9rl())
+
+#define cpu_has_800M_plla()	(cpu_is_at91sam9g20())
+
+#define cpu_has_pllb()		(!cpu_is_at91sam9rl())
+
+#define cpu_has_upll()		(0)
+
+/* USB host HS & FS */
+#define cpu_has_uhp()		(!cpu_is_at91sam9rl())
+
+/* USB device FS only */
+#define cpu_has_udpfs()		(!cpu_is_at91sam9rl())
+
+
 static LIST_HEAD(clocks);
 static DEFINE_SPINLOCK(clk_lock);
 
@@ -140,7 +159,7 @@
 };
 static struct clk uhpck = {
 	.name		= "uhpck",
-	.parent		= &pllb,
+	/*.parent		= ... we choose parent at runtime */
 	.mode		= pmc_sys_mode,
 };
 
@@ -173,7 +192,11 @@
 		case AT91_PMC_CSS_PLLA:
 			return &plla;
 		case AT91_PMC_CSS_PLLB:
-			return &pllb;
+			if (cpu_has_upll())
+				/* CSS_PLLB == CSS_UPLL */
+				return &utmi_clk;
+			else if (cpu_has_pllb())
+				return &pllb;
 	}
 
 	return NULL;
@@ -322,7 +345,7 @@
 			u32	pckr;
 
 			pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
-			pckr &= AT91_PMC_CSS_PLLB;	/* clock selection */
+			pckr &= AT91_PMC_CSS;	/* clock selection */
 			pckr |= prescale << 2;
 			at91_sys_write(AT91_PMC_PCKR(clk->id), pckr);
 			clk->rate_hz = actual;
@@ -361,7 +384,7 @@
 }
 EXPORT_SYMBOL(clk_set_parent);
 
-/* establish PCK0..PCK3 parentage and rate */
+/* establish PCK0..PCKN parentage and rate */
 static void __init init_programmable_clock(struct clk *clk)
 {
 	struct clk	*parent;
@@ -389,11 +412,13 @@
 	seq_printf(s, "MOR  = %8x\n", at91_sys_read(AT91_CKGR_MOR));
 	seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
 	seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
-	if (!cpu_is_at91sam9rl())
+	if (cpu_has_pllb())
 		seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
-	if (cpu_is_at91cap9() || cpu_is_at91sam9rl())
+	if (cpu_has_utmi())
 		seq_printf(s, "UCKR = %8x\n", uckr = at91_sys_read(AT91_CKGR_UCKR));
 	seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
+	if (cpu_has_upll())
+		seq_printf(s, "USB  = %8x\n", at91_sys_read(AT91_PMC_USB));
 	seq_printf(s, "SR   = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
 
 	seq_printf(s, "\n");
@@ -554,16 +579,60 @@
 	&clk32k,
 	&main_clk,
 	&plla,
-	&pllb,
-
-	/* PLLB children (USB) */
-	&udpck,
-	&uhpck,
 
 	/* MCK */
 	&mck
 };
 
+/* PLLB generated USB full speed clock init */
+static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)
+{
+	/*
+	 * USB clock init:  choose 48 MHz PLLB value,
+	 * disable 48MHz clock during usb peripheral suspend.
+	 *
+	 * REVISIT:  assumes MCK doesn't derive from PLLB!
+	 */
+	uhpck.parent = &pllb;
+
+	at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
+	pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
+	if (cpu_is_at91rm9200()) {
+		uhpck.pmc_mask = AT91RM9200_PMC_UHP;
+		udpck.pmc_mask = AT91RM9200_PMC_UDP;
+		at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
+	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
+		uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
+		udpck.pmc_mask = AT91SAM926x_PMC_UDP;
+	} else if (cpu_is_at91cap9()) {
+		uhpck.pmc_mask = AT91CAP9_PMC_UHP;
+	}
+	at91_sys_write(AT91_CKGR_PLLBR, 0);
+
+	udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+	uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
+}
+
+/* UPLL generated USB full speed clock init */
+static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
+{
+	/*
+	 * USB clock init: choose 480 MHz from UPLL,
+	 */
+	unsigned int usbr = AT91_PMC_USBS_UPLL;
+
+	/* Setup divider by 10 to reach 48 MHz */
+	usbr |= ((10 - 1) << 8) & AT91_PMC_OHCIUSBDIV;
+
+	at91_sys_write(AT91_PMC_USB, usbr);
+
+	/* Now set uhpck values */
+	uhpck.parent = &utmi_clk;
+	uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
+	uhpck.rate_hz = utmi_clk.parent->rate_hz;
+	uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
+}
+
 int __init at91_clock_init(unsigned long main_clock)
 {
 	unsigned tmp, freq, mckr;
@@ -585,43 +654,37 @@
 
 	/* report if PLLA is more than mildly overclocked */
 	plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
-	if ((!cpu_is_at91sam9g20() && plla.rate_hz > 209000000)
-	   || (cpu_is_at91sam9g20() && plla.rate_hz > 800000000))
+	if ((!cpu_has_800M_plla() && plla.rate_hz > 209000000)
+	   || (cpu_has_800M_plla() && plla.rate_hz > 800000000))
 		pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
 
-	/*
-	 * USB clock init:  choose 48 MHz PLLB value,
-	 * disable 48MHz clock during usb peripheral suspend.
-	 *
-	 * REVISIT:  assumes MCK doesn't derive from PLLB!
-	 */
-	at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
-	pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
-	if (cpu_is_at91rm9200()) {
-		uhpck.pmc_mask = AT91RM9200_PMC_UHP;
-		udpck.pmc_mask = AT91RM9200_PMC_UDP;
-		at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
-	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
-		uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-		udpck.pmc_mask = AT91SAM926x_PMC_UDP;
-	} else if (cpu_is_at91cap9()) {
-		uhpck.pmc_mask = AT91CAP9_PMC_UHP;
+
+	if (cpu_has_upll() && !cpu_has_pllb()) {
+		/* setup UTMI clock as the fourth primary clock
+		 * (instead of pllb) */
+		utmi_clk.type |= CLK_TYPE_PRIMARY;
+		utmi_clk.id = 3;
 	}
-	at91_sys_write(AT91_CKGR_PLLBR, 0);
 
-	udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
-	uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
 
 	/*
 	 * USB HS clock init
 	 */
-	if (cpu_is_at91cap9() || cpu_is_at91sam9rl()) {
+	if (cpu_has_utmi())
 		/*
 		 * multiplier is hard-wired to 40
 		 * (obtain the USB High Speed 480 MHz when input is 12 MHz)
 		 */
 		utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz;
-	}
+
+	/*
+	 * USB FS clock init
+	 */
+	if (cpu_has_pllb())
+		at91_pllb_usbfs_clock_init(main_clock);
+	if (cpu_has_upll())
+		/* assumes that we choose UPLL for USB and not PLLA */
+		at91_upll_usbfs_clock_init(main_clock);
 
 	/*
 	 * MCK and CPU derive from one of those primary clocks.
@@ -631,21 +694,31 @@
 	mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
 	freq = mck.parent->rate_hz;
 	freq /= (1 << ((mckr & AT91_PMC_PRES) >> 2));				/* prescale */
-	if (cpu_is_at91rm9200())
+	if (cpu_is_at91rm9200()) {
 		mck.rate_hz = freq / (1 + ((mckr & AT91_PMC_MDIV) >> 8));	/* mdiv */
-	else if (cpu_is_at91sam9g20()) {
+	} else if (cpu_is_at91sam9g20()) {
 		mck.rate_hz = (mckr & AT91_PMC_MDIV) ?
 			freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq;	/* mdiv ; (x >> 7) = ((x >> 8) * 2) */
 		if (mckr & AT91_PMC_PDIV)
 			freq /= 2;		/* processor clock division */
-	} else
+	} else {
 		mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8));      /* mdiv */
+	}
 
 	/* Register the PMC's standard clocks */
 	for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
 		list_add_tail(&standard_pmc_clocks[i]->node, &clocks);
 
-	if (cpu_is_at91cap9() || cpu_is_at91sam9rl())
+	if (cpu_has_pllb())
+		list_add_tail(&pllb.node, &clocks);
+
+	if (cpu_has_uhp())
+		list_add_tail(&uhpck.node, &clocks);
+
+	if (cpu_has_udpfs())
+		list_add_tail(&udpck.node, &clocks);
+
+	if (cpu_has_utmi())
 		list_add_tail(&utmi_clk.node, &clocks);
 
 	/* MCK and CPU clock are "always on" */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-at91/include/mach/at91_pmc.h linux-libre-2.6.31-gnu/arch/arm/mach-at91/include/mach/at91_pmc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-at91/include/mach/at91_pmc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-at91/include/mach/at91_pmc.h	2009-09-09 18:13:59.000000000 -0400
@@ -23,7 +23,7 @@
 #define		AT91_PMC_PCK		(1 <<  0)		/* Processor Clock */
 #define		AT91RM9200_PMC_UDP	(1 <<  1)		/* USB Devcice Port Clock [AT91RM9200 only] */
 #define		AT91RM9200_PMC_MCKUDP	(1 <<  2)		/* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
-#define		AT91CAP9_PMC_DDR	(1 <<  2)		/* DDR Clock [AT91CAP9 revC only] */
+#define		AT91CAP9_PMC_DDR	(1 <<  2)		/* DDR Clock [CAP9 revC & some SAM9 only] */
 #define		AT91RM9200_PMC_UHP	(1 <<  4)		/* USB Host Port Clock [AT91RM9200 only] */
 #define		AT91SAM926x_PMC_UHP	(1 <<  6)		/* USB Host Port Clock [AT91SAM926x only] */
 #define		AT91CAP9_PMC_UHP	(1 <<  6)		/* USB Host Port Clock [AT91CAP9 only] */
@@ -39,11 +39,11 @@
 #define	AT91_PMC_PCDR		(AT91_PMC + 0x14)	/* Peripheral Clock Disable Register */
 #define	AT91_PMC_PCSR		(AT91_PMC + 0x18)	/* Peripheral Clock Status Register */
 
-#define	AT91_CKGR_UCKR		(AT91_PMC + 0x1C)	/* UTMI Clock Register [SAM9RL, CAP9] */
+#define	AT91_CKGR_UCKR		(AT91_PMC + 0x1C)	/* UTMI Clock Register [some SAM9, CAP9] */
 #define		AT91_PMC_UPLLEN		(1   << 16)		/* UTMI PLL Enable */
 #define		AT91_PMC_UPLLCOUNT	(0xf << 20)		/* UTMI PLL Start-up Time */
 #define		AT91_PMC_BIASEN		(1   << 24)		/* UTMI BIAS Enable */
-#define		AT91_PMC_BIASCOUNT	(0xf << 28)		/* UTMI PLL Start-up Time */
+#define		AT91_PMC_BIASCOUNT	(0xf << 28)		/* UTMI BIAS Start-up Time */
 
 #define	AT91_CKGR_MOR		(AT91_PMC + 0x20)	/* Main Oscillator Register [not on SAM9RL] */
 #define		AT91_PMC_MOSCEN		(1    << 0)		/* Main Oscillator Enable */
@@ -72,6 +72,7 @@
 #define			AT91_PMC_CSS_MAIN		(1 << 0)
 #define			AT91_PMC_CSS_PLLA		(2 << 0)
 #define			AT91_PMC_CSS_PLLB		(3 << 0)
+#define			AT91_PMC_CSS_UPLL		(3 << 0)	/* [some SAM9 only] */
 #define		AT91_PMC_PRES		(7 <<  2)		/* Master Clock Prescaler */
 #define			AT91_PMC_PRES_1			(0 << 2)
 #define			AT91_PMC_PRES_2			(1 << 2)
@@ -88,12 +89,25 @@
 #define			AT91SAM9_PMC_MDIV_1		(0 << 8)	/* [SAM9,CAP9 only] */
 #define			AT91SAM9_PMC_MDIV_2		(1 << 8)
 #define			AT91SAM9_PMC_MDIV_4		(2 << 8)
-#define			AT91SAM9_PMC_MDIV_6		(3 << 8)
+#define			AT91SAM9_PMC_MDIV_6		(3 << 8)	/* [some SAM9 only] */
+#define			AT91SAM9_PMC_MDIV_3		(3 << 8)	/* [some SAM9 only] */
 #define		AT91_PMC_PDIV		(1 << 12)		/* Processor Clock Division [some SAM9 only] */
 #define			AT91_PMC_PDIV_1			(0 << 12)
 #define			AT91_PMC_PDIV_2			(1 << 12)
+#define		AT91_PMC_PLLADIV2	(1 << 12)		/* PLLA divisor by 2 [some SAM9 only] */
+#define			AT91_PMC_PLLADIV2_OFF		(0 << 12)
+#define			AT91_PMC_PLLADIV2_ON		(1 << 12)
 
-#define	AT91_PMC_PCKR(n)	(AT91_PMC + 0x40 + ((n) * 4))	/* Programmable Clock 0-3 Registers */
+#define	AT91_PMC_USB		(AT91_PMC + 0x38)	/* USB Clock Register [some SAM9 only] */
+#define		AT91_PMC_USBS		(0x1 <<  0)		/* USB OHCI Input clock selection */
+#define			AT91_PMC_USBS_PLLA		(0 << 0)
+#define			AT91_PMC_USBS_UPLL		(1 << 0)
+#define		AT91_PMC_OHCIUSBDIV	(0xF <<  8)		/* Divider for USB OHCI Clock */
+
+#define	AT91_PMC_PCKR(n)	(AT91_PMC + 0x40 + ((n) * 4))	/* Programmable Clock 0-N Registers */
+#define		AT91_PMC_CSSMCK		(0x1 <<  8)		/* CSS or Master Clock Selection */
+#define			AT91_PMC_CSSMCK_CSS		(0 << 8)
+#define			AT91_PMC_CSSMCK_MCK		(1 << 8)
 
 #define	AT91_PMC_IER		(AT91_PMC + 0x60)	/* Interrupt Enable Register */
 #define	AT91_PMC_IDR		(AT91_PMC + 0x64)	/* Interrupt Disable Register */
@@ -102,7 +116,7 @@
 #define		AT91_PMC_LOCKA		(1 <<  1)		/* PLLA Lock */
 #define		AT91_PMC_LOCKB		(1 <<  2)		/* PLLB Lock */
 #define		AT91_PMC_MCKRDY		(1 <<  3)		/* Master Clock */
-#define		AT91_PMC_LOCKU		(1 <<  6)		/* UPLL Lock [AT91CAP9 only] */
+#define		AT91_PMC_LOCKU		(1 <<  6)		/* UPLL Lock [some SAM9, AT91CAP9 only] */
 #define		AT91_PMC_OSCSEL		(1 <<  7)		/* Slow Clock Oscillator [AT91CAP9 revC only] */
 #define		AT91_PMC_PCK0RDY	(1 <<  8)		/* Programmable Clock 0 */
 #define		AT91_PMC_PCK1RDY	(1 <<  9)		/* Programmable Clock 1 */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-at91/include/mach/at_hdmac.h linux-libre-2.6.31-gnu/arch/arm/mach-at91/include/mach/at_hdmac.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-at91/include/mach/at_hdmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-at91/include/mach/at_hdmac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * Header file for the Atmel AHB DMA Controller driver
+ *
+ * Copyright (C) 2008 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.
+ */
+#ifndef AT_HDMAC_H
+#define AT_HDMAC_H
+
+#include <linux/dmaengine.h>
+
+/**
+ * struct at_dma_platform_data - Controller configuration parameters
+ * @nr_channels: Number of channels supported by hardware (max 8)
+ * @cap_mask: dma_capability flags supported by the platform
+ */
+struct at_dma_platform_data {
+	unsigned int	nr_channels;
+	dma_cap_mask_t  cap_mask;
+};
+
+/**
+ * enum at_dma_slave_width - DMA slave register access width.
+ * @AT_DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
+ * @AT_DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
+ * @AT_DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
+ */
+enum at_dma_slave_width {
+	AT_DMA_SLAVE_WIDTH_8BIT = 0,
+	AT_DMA_SLAVE_WIDTH_16BIT,
+	AT_DMA_SLAVE_WIDTH_32BIT,
+};
+
+/**
+ * struct at_dma_slave - Controller-specific information about a slave
+ * @dma_dev: required DMA master device
+ * @tx_reg: physical address of data register used for
+ *	memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ *	peripheral-to-memory transfers
+ * @reg_width: peripheral register width
+ * @cfg: Platform-specific initializer for the CFG register
+ * @ctrla: Platform-specific initializer for the CTRLA register
+ */
+struct at_dma_slave {
+	struct device		*dma_dev;
+	dma_addr_t		tx_reg;
+	dma_addr_t		rx_reg;
+	enum at_dma_slave_width	reg_width;
+	u32			cfg;
+	u32			ctrla;
+};
+
+
+/* Platform-configurable bits in CFG */
+#define	ATC_SRC_PER(h)		(0xFU & (h))	/* Channel src rq associated with periph handshaking ifc h */
+#define	ATC_DST_PER(h)		((0xFU & (h)) <<  4)	/* Channel dst rq associated with periph handshaking ifc h */
+#define	ATC_SRC_REP		(0x1 <<  8)	/* Source Replay Mod */
+#define	ATC_SRC_H2SEL		(0x1 <<  9)	/* Source Handshaking Mod */
+#define		ATC_SRC_H2SEL_SW	(0x0 <<  9)
+#define		ATC_SRC_H2SEL_HW	(0x1 <<  9)
+#define	ATC_DST_REP		(0x1 << 12)	/* Destination Replay Mod */
+#define	ATC_DST_H2SEL		(0x1 << 13)	/* Destination Handshaking Mod */
+#define		ATC_DST_H2SEL_SW	(0x0 << 13)
+#define		ATC_DST_H2SEL_HW	(0x1 << 13)
+#define	ATC_SOD			(0x1 << 16)	/* Stop On Done */
+#define	ATC_LOCK_IF		(0x1 << 20)	/* Interface Lock */
+#define	ATC_LOCK_B		(0x1 << 21)	/* AHB Bus Lock */
+#define	ATC_LOCK_IF_L		(0x1 << 22)	/* Master Interface Arbiter Lock */
+#define		ATC_LOCK_IF_L_CHUNK	(0x0 << 22)
+#define		ATC_LOCK_IF_L_BUFFER	(0x1 << 22)
+#define	ATC_AHB_PROT_MASK	(0x7 << 24)	/* AHB Protection */
+#define	ATC_FIFOCFG_MASK	(0x3 << 28)	/* FIFO Request Configuration */
+#define		ATC_FIFOCFG_LARGESTBURST	(0x0 << 28)
+#define		ATC_FIFOCFG_HALFFIFO		(0x1 << 28)
+#define		ATC_FIFOCFG_ENOUGHSPACE		(0x2 << 28)
+
+/* Platform-configurable bits in CTRLA */
+#define	ATC_SCSIZE_MASK		(0x7 << 16)	/* Source Chunk Transfer Size */
+#define		ATC_SCSIZE_1		(0x0 << 16)
+#define		ATC_SCSIZE_4		(0x1 << 16)
+#define		ATC_SCSIZE_8		(0x2 << 16)
+#define		ATC_SCSIZE_16		(0x3 << 16)
+#define		ATC_SCSIZE_32		(0x4 << 16)
+#define		ATC_SCSIZE_64		(0x5 << 16)
+#define		ATC_SCSIZE_128		(0x6 << 16)
+#define		ATC_SCSIZE_256		(0x7 << 16)
+#define	ATC_DCSIZE_MASK		(0x7 << 20)	/* Destination Chunk Transfer Size */
+#define		ATC_DCSIZE_1		(0x0 << 20)
+#define		ATC_DCSIZE_4		(0x1 << 20)
+#define		ATC_DCSIZE_8		(0x2 << 20)
+#define		ATC_DCSIZE_16		(0x3 << 20)
+#define		ATC_DCSIZE_32		(0x4 << 20)
+#define		ATC_DCSIZE_64		(0x5 << 20)
+#define		ATC_DCSIZE_128		(0x6 << 20)
+#define		ATC_DCSIZE_256		(0x7 << 20)
+
+#endif /* AT_HDMAC_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm355-evm.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm355-evm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm355-evm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm355-evm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,297 @@
+/*
+ * TI DaVinci EVM board support
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) MontaVista Software, Inc. 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/hardware.h>
+#include <mach/dm355.h>
+#include <mach/psc.h>
+#include <mach/common.h>
+#include <mach/i2c.h>
+#include <mach/serial.h>
+#include <mach/nand.h>
+#include <mach/mmc.h>
+
+#define DAVINCI_ASYNC_EMIF_CONTROL_BASE		0x01e10000
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE	0x02000000
+
+/* NOTE:  this is geared for the standard config, with a socketed
+ * 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors.  If you
+ * swap chips, maybe with a different block size, partitioning may
+ * need to be changed.
+ */
+#define NAND_BLOCK_SIZE		SZ_128K
+
+static struct mtd_partition davinci_nand_partitions[] = {
+	{
+		/* UBL (a few copies) plus U-Boot */
+		.name		= "bootloader",
+		.offset		= 0,
+		.size		= 15 * NAND_BLOCK_SIZE,
+		.mask_flags	= MTD_WRITEABLE, /* force read-only */
+	}, {
+		/* U-Boot environment */
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 1 * NAND_BLOCK_SIZE,
+		.mask_flags	= 0,
+	}, {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_4M,
+		.mask_flags	= 0,
+	}, {
+		.name		= "filesystem1",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_512M,
+		.mask_flags	= 0,
+	}, {
+		.name		= "filesystem2",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= 0,
+	}
+	/* two blocks with bad block table (and mirror) at the end */
+};
+
+static struct davinci_nand_pdata davinci_nand_data = {
+	.mask_chipsel		= BIT(14),
+	.parts			= davinci_nand_partitions,
+	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
+	.ecc_mode		= NAND_ECC_HW_SYNDROME,
+	.options		= NAND_USE_FLASH_BBT,
+};
+
+static struct resource davinci_nand_resources[] = {
+	{
+		.start		= DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
+		.end		= DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= DAVINCI_ASYNC_EMIF_CONTROL_BASE,
+		.end		= DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device davinci_nand_device = {
+	.name			= "davinci_nand",
+	.id			= 0,
+
+	.num_resources		= ARRAY_SIZE(davinci_nand_resources),
+	.resource		= davinci_nand_resources,
+
+	.dev			= {
+		.platform_data	= &davinci_nand_data,
+	},
+};
+
+static struct davinci_i2c_platform_data i2c_pdata = {
+	.bus_freq	= 400	/* kHz */,
+	.bus_delay	= 0	/* usec */,
+};
+
+static int dm355evm_mmc_gpios = -EINVAL;
+
+static void dm355evm_mmcsd_gpios(unsigned gpio)
+{
+	gpio_request(gpio + 0, "mmc0_ro");
+	gpio_request(gpio + 1, "mmc0_cd");
+	gpio_request(gpio + 2, "mmc1_ro");
+	gpio_request(gpio + 3, "mmc1_cd");
+
+	/* we "know" these are input-only so we don't
+	 * need to call gpio_direction_input()
+	 */
+
+	dm355evm_mmc_gpios = gpio;
+}
+
+static struct i2c_board_info dm355evm_i2c_info[] = {
+	{ I2C_BOARD_INFO("dm355evm_msp", 0x25),
+		.platform_data = dm355evm_mmcsd_gpios,
+		/* plus irq */ },
+	/* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */
+	/* { I2C_BOARD_INFO("tvp5146", 0x5d), }, */
+};
+
+static void __init evm_init_i2c(void)
+{
+	davinci_init_i2c(&i2c_pdata);
+
+	gpio_request(5, "dm355evm_msp");
+	gpio_direction_input(5);
+	dm355evm_i2c_info[0].irq = gpio_to_irq(5);
+
+	i2c_register_board_info(1, dm355evm_i2c_info,
+			ARRAY_SIZE(dm355evm_i2c_info));
+}
+
+static struct resource dm355evm_dm9000_rsrc[] = {
+	{
+		/* addr */
+		.start	= 0x04014000,
+		.end	= 0x04014001,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		/* data */
+		.start	= 0x04014002,
+		.end	= 0x04014003,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.flags	= IORESOURCE_IRQ
+			| IORESOURCE_IRQ_HIGHEDGE /* rising (active high) */,
+	},
+};
+
+static struct platform_device dm355evm_dm9000 = {
+	.name		= "dm9000",
+	.id		= -1,
+	.resource	= dm355evm_dm9000_rsrc,
+	.num_resources	= ARRAY_SIZE(dm355evm_dm9000_rsrc),
+};
+
+static struct platform_device *davinci_evm_devices[] __initdata = {
+	&dm355evm_dm9000,
+	&davinci_nand_device,
+};
+
+static struct davinci_uart_config uart_config __initdata = {
+	.enabled_uarts = (1 << 0),
+};
+
+static void __init dm355_evm_map_io(void)
+{
+	dm355_init();
+}
+
+static int dm355evm_mmc_get_cd(int module)
+{
+	if (!gpio_is_valid(dm355evm_mmc_gpios))
+		return -ENXIO;
+	/* low == card present */
+	return !gpio_get_value_cansleep(dm355evm_mmc_gpios + 2 * module + 1);
+}
+
+static int dm355evm_mmc_get_ro(int module)
+{
+	if (!gpio_is_valid(dm355evm_mmc_gpios))
+		return -ENXIO;
+	/* high == card's write protect switch active */
+	return gpio_get_value_cansleep(dm355evm_mmc_gpios + 2 * module + 0);
+}
+
+static struct davinci_mmc_config dm355evm_mmc_config = {
+	.get_cd		= dm355evm_mmc_get_cd,
+	.get_ro		= dm355evm_mmc_get_ro,
+	.wires		= 4,
+	.max_freq       = 50000000,
+	.caps           = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+	.version	= MMC_CTLR_VERSION_1,
+};
+
+/* Don't connect anything to J10 unless you're only using USB host
+ * mode *and* have to do so with some kind of gender-bender.  If
+ * you have proper Mini-B or Mini-A cables (or Mini-A adapters)
+ * the ID pin won't need any help.
+ */
+#ifdef CONFIG_USB_MUSB_PERIPHERAL
+#define USB_ID_VALUE	0	/* ID pulled high; *should* float */
+#else
+#define USB_ID_VALUE	1	/* ID pulled low */
+#endif
+
+static struct spi_eeprom at25640a = {
+	.byte_len	= SZ_64K / 8,
+	.name		= "at25640a",
+	.page_size	= 32,
+	.flags		= EE_ADDR2,
+};
+
+static struct spi_board_info dm355_evm_spi_info[] __initconst = {
+	{
+		.modalias	= "at25",
+		.platform_data	= &at25640a,
+		.max_speed_hz	= 10 * 1000 * 1000,	/* at 3v3 */
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.mode		= SPI_MODE_0,
+	},
+};
+
+static __init void dm355_evm_init(void)
+{
+	struct clk *aemif;
+
+	gpio_request(1, "dm9000");
+	gpio_direction_input(1);
+	dm355evm_dm9000_rsrc[2].start = gpio_to_irq(1);
+
+	aemif = clk_get(&dm355evm_dm9000.dev, "aemif");
+	if (IS_ERR(aemif))
+		WARN("%s: unable to get AEMIF clock\n", __func__);
+	else
+		clk_enable(aemif);
+
+	platform_add_devices(davinci_evm_devices,
+			     ARRAY_SIZE(davinci_evm_devices));
+	evm_init_i2c();
+	davinci_serial_init(&uart_config);
+
+	/* NOTE:  NAND flash timings set by the UBL are slower than
+	 * needed by MT29F16G08FAA chips ... EMIF.A1CR is 0x40400204
+	 * but could be 0x0400008c for about 25% faster page reads.
+	 */
+
+	gpio_request(2, "usb_id_toggle");
+	gpio_direction_output(2, USB_ID_VALUE);
+	/* irlml6401 switches over 1A in under 8 msec */
+	setup_usb(500, 8);
+
+	davinci_setup_mmc(0, &dm355evm_mmc_config);
+	davinci_setup_mmc(1, &dm355evm_mmc_config);
+
+	dm355_init_spi0(BIT(0), dm355_evm_spi_info,
+			ARRAY_SIZE(dm355_evm_spi_info));
+}
+
+static __init void dm355_evm_irq_init(void)
+{
+	davinci_irq_init();
+}
+
+MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
+	.phys_io      = IO_PHYS,
+	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
+	.boot_params  = (0x80000100),
+	.map_io	      = dm355_evm_map_io,
+	.init_irq     = dm355_evm_irq_init,
+	.timer	      = &davinci_timer,
+	.init_machine = dm355_evm_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm355-leopard.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm355-leopard.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm355-leopard.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm355-leopard.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,295 @@
+/*
+ * DM355 leopard board support
+ *
+ * Based on board-dm355-evm.c
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/hardware.h>
+#include <mach/dm355.h>
+#include <mach/psc.h>
+#include <mach/common.h>
+#include <mach/i2c.h>
+#include <mach/serial.h>
+#include <mach/nand.h>
+#include <mach/mmc.h>
+
+#define DAVINCI_ASYNC_EMIF_CONTROL_BASE		0x01e10000
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE	0x02000000
+
+/* NOTE:  this is geared for the standard config, with a socketed
+ * 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors.  If you
+ * swap chips, maybe with a different block size, partitioning may
+ * need to be changed.
+ */
+#define NAND_BLOCK_SIZE		SZ_128K
+
+static struct mtd_partition davinci_nand_partitions[] = {
+	{
+		/* UBL (a few copies) plus U-Boot */
+		.name		= "bootloader",
+		.offset		= 0,
+		.size		= 15 * NAND_BLOCK_SIZE,
+		.mask_flags	= MTD_WRITEABLE, /* force read-only */
+	}, {
+		/* U-Boot environment */
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 1 * NAND_BLOCK_SIZE,
+		.mask_flags	= 0,
+	}, {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_4M,
+		.mask_flags	= 0,
+	}, {
+		.name		= "filesystem1",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_512M,
+		.mask_flags	= 0,
+	}, {
+		.name		= "filesystem2",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= 0,
+	}
+	/* two blocks with bad block table (and mirror) at the end */
+};
+
+static struct davinci_nand_pdata davinci_nand_data = {
+	.mask_chipsel		= BIT(14),
+	.parts			= davinci_nand_partitions,
+	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
+	.ecc_mode		= NAND_ECC_HW_SYNDROME,
+	.options		= NAND_USE_FLASH_BBT,
+};
+
+static struct resource davinci_nand_resources[] = {
+	{
+		.start		= DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
+		.end		= DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= DAVINCI_ASYNC_EMIF_CONTROL_BASE,
+		.end		= DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device davinci_nand_device = {
+	.name			= "davinci_nand",
+	.id			= 0,
+
+	.num_resources		= ARRAY_SIZE(davinci_nand_resources),
+	.resource		= davinci_nand_resources,
+
+	.dev			= {
+		.platform_data	= &davinci_nand_data,
+	},
+};
+
+static struct davinci_i2c_platform_data i2c_pdata = {
+	.bus_freq	= 400	/* kHz */,
+	.bus_delay	= 0	/* usec */,
+};
+
+static int leopard_mmc_gpio = -EINVAL;
+
+static void dm355leopard_mmcsd_gpios(unsigned gpio)
+{
+	gpio_request(gpio + 0, "mmc0_ro");
+	gpio_request(gpio + 1, "mmc0_cd");
+	gpio_request(gpio + 2, "mmc1_ro");
+	gpio_request(gpio + 3, "mmc1_cd");
+
+	/* we "know" these are input-only so we don't
+	 * need to call gpio_direction_input()
+	 */
+
+	leopard_mmc_gpio = gpio;
+}
+
+static struct i2c_board_info dm355leopard_i2c_info[] = {
+	{ I2C_BOARD_INFO("dm355leopard_msp", 0x25),
+		.platform_data = dm355leopard_mmcsd_gpios,
+		/* plus irq */ },
+	/* { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }, */
+	/* { I2C_BOARD_INFO("tvp5146", 0x5d), }, */
+};
+
+static void __init leopard_init_i2c(void)
+{
+	davinci_init_i2c(&i2c_pdata);
+
+	gpio_request(5, "dm355leopard_msp");
+	gpio_direction_input(5);
+	dm355leopard_i2c_info[0].irq = gpio_to_irq(5);
+
+	i2c_register_board_info(1, dm355leopard_i2c_info,
+			ARRAY_SIZE(dm355leopard_i2c_info));
+}
+
+static struct resource dm355leopard_dm9000_rsrc[] = {
+	{
+		/* addr */
+		.start	= 0x04000000,
+		.end	= 0x04000001,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		/* data */
+		.start	= 0x04000016,
+		.end	= 0x04000017,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.flags	= IORESOURCE_IRQ
+			| IORESOURCE_IRQ_HIGHEDGE /* rising (active high) */,
+	},
+};
+
+static struct platform_device dm355leopard_dm9000 = {
+	.name		= "dm9000",
+	.id		= -1,
+	.resource	= dm355leopard_dm9000_rsrc,
+	.num_resources	= ARRAY_SIZE(dm355leopard_dm9000_rsrc),
+};
+
+static struct platform_device *davinci_leopard_devices[] __initdata = {
+	&dm355leopard_dm9000,
+	&davinci_nand_device,
+};
+
+static struct davinci_uart_config uart_config __initdata = {
+	.enabled_uarts = (1 << 0),
+};
+
+static void __init dm355_leopard_map_io(void)
+{
+	dm355_init();
+}
+
+static int dm355leopard_mmc_get_cd(int module)
+{
+	if (!gpio_is_valid(leopard_mmc_gpio))
+		return -ENXIO;
+	/* low == card present */
+	return !gpio_get_value_cansleep(leopard_mmc_gpio + 2 * module + 1);
+}
+
+static int dm355leopard_mmc_get_ro(int module)
+{
+	if (!gpio_is_valid(leopard_mmc_gpio))
+		return -ENXIO;
+	/* high == card's write protect switch active */
+	return gpio_get_value_cansleep(leopard_mmc_gpio + 2 * module + 0);
+}
+
+static struct davinci_mmc_config dm355leopard_mmc_config = {
+	.get_cd		= dm355leopard_mmc_get_cd,
+	.get_ro		= dm355leopard_mmc_get_ro,
+	.wires		= 4,
+	.max_freq       = 50000000,
+	.caps           = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+};
+
+/* Don't connect anything to J10 unless you're only using USB host
+ * mode *and* have to do so with some kind of gender-bender.  If
+ * you have proper Mini-B or Mini-A cables (or Mini-A adapters)
+ * the ID pin won't need any help.
+ */
+#ifdef CONFIG_USB_MUSB_PERIPHERAL
+#define USB_ID_VALUE	0	/* ID pulled high; *should* float */
+#else
+#define USB_ID_VALUE	1	/* ID pulled low */
+#endif
+
+static struct spi_eeprom at25640a = {
+	.byte_len	= SZ_64K / 8,
+	.name		= "at25640a",
+	.page_size	= 32,
+	.flags		= EE_ADDR2,
+};
+
+static struct spi_board_info dm355_leopard_spi_info[] __initconst = {
+	{
+		.modalias	= "at25",
+		.platform_data	= &at25640a,
+		.max_speed_hz	= 10 * 1000 * 1000,	/* at 3v3 */
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.mode		= SPI_MODE_0,
+	},
+};
+
+static __init void dm355_leopard_init(void)
+{
+	struct clk *aemif;
+
+	gpio_request(9, "dm9000");
+	gpio_direction_input(9);
+	dm355leopard_dm9000_rsrc[2].start = gpio_to_irq(9);
+
+	aemif = clk_get(&dm355leopard_dm9000.dev, "aemif");
+	if (IS_ERR(aemif))
+		WARN("%s: unable to get AEMIF clock\n", __func__);
+	else
+		clk_enable(aemif);
+
+	platform_add_devices(davinci_leopard_devices,
+			     ARRAY_SIZE(davinci_leopard_devices));
+	leopard_init_i2c();
+	davinci_serial_init(&uart_config);
+
+	/* NOTE:  NAND flash timings set by the UBL are slower than
+	 * needed by MT29F16G08FAA chips ... EMIF.A1CR is 0x40400204
+	 * but could be 0x0400008c for about 25% faster page reads.
+	 */
+
+	gpio_request(2, "usb_id_toggle");
+	gpio_direction_output(2, USB_ID_VALUE);
+	/* irlml6401 switches over 1A in under 8 msec */
+	setup_usb(500, 8);
+
+	davinci_setup_mmc(0, &dm355leopard_mmc_config);
+	davinci_setup_mmc(1, &dm355leopard_mmc_config);
+
+	dm355_init_spi0(BIT(0), dm355_leopard_spi_info,
+			ARRAY_SIZE(dm355_leopard_spi_info));
+}
+
+static __init void dm355_leopard_irq_init(void)
+{
+	davinci_irq_init();
+}
+
+MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
+	.phys_io      = IO_PHYS,
+	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
+	.boot_params  = (0x80000100),
+	.map_io	      = dm355_leopard_map_io,
+	.init_irq     = dm355_leopard_irq_init,
+	.timer	      = &davinci_timer,
+	.init_machine = dm355_leopard_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm644x-evm.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm644x-evm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,12 +16,11 @@
 #include <linux/gpio.h>
 #include <linux/leds.h>
 #include <linux/memory.h>
-#include <linux/etherdevice.h>
 
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
 #include <linux/i2c/at24.h>
-
+#include <linux/etherdevice.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
@@ -44,6 +43,8 @@
 #include <mach/mux.h>
 #include <mach/psc.h>
 #include <mach/nand.h>
+#include <mach/mmc.h>
+#include <mach/emac.h>
 
 #define DM644X_EVM_PHY_MASK		(0x2)
 #define DM644X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
@@ -436,45 +437,15 @@
  *  - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL)
  *  - ... newer boards may have more
  */
-static struct memory_accessor *at24_mem_acc;
-
-static void at24_setup(struct memory_accessor *mem_acc, void *context)
-{
-	DECLARE_MAC_BUF(mac_str);
-	char mac_addr[6];
-
-	at24_mem_acc = mem_acc;
-
-	/* Read MAC addr from EEPROM */
-	if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x7f00, 6) == 6) {
-		printk(KERN_INFO "Read MAC addr from EEPROM: %s\n",
-		       print_mac(mac_str, mac_addr));
-	}
-}
 
 static struct at24_platform_data eeprom_info = {
 	.byte_len	= (256*1024) / 8,
 	.page_size	= 64,
 	.flags		= AT24_FLAG_ADDR16,
-	.setup          = at24_setup,
+	.setup          = davinci_get_mac_addr,
+	.context	= (void *)0x7f00,
 };
 
-int dm6446evm_eeprom_read(void *buf, off_t off, size_t count)
-{
-	if (at24_mem_acc)
-		return at24_mem_acc->read(at24_mem_acc, buf, off, count);
-	return -ENODEV;
-}
-EXPORT_SYMBOL(dm6446evm_eeprom_read);
-
-int dm6446evm_eeprom_write(void *buf, off_t off, size_t count)
-{
-	if (at24_mem_acc)
-		return at24_mem_acc->write(at24_mem_acc, buf, off, count);
-	return -ENODEV;
-}
-EXPORT_SYMBOL(dm6446evm_eeprom_write);
-
 /*
  * MSP430 supports RTC, card detection, input from IR remote, and
  * a bit more.  It triggers interrupts on GPIO(7) from pressing
@@ -545,6 +516,27 @@
 	return (buf[3] << 8) | buf[2];
 }
 
+static int dm6444evm_mmc_get_cd(int module)
+{
+	int status = dm6444evm_msp430_get_pins();
+
+	return (status < 0) ? status : !(status & BIT(1));
+}
+
+static int dm6444evm_mmc_get_ro(int module)
+{
+	int status = dm6444evm_msp430_get_pins();
+
+	return (status < 0) ? status : status & BIT(6 + 8);
+}
+
+static struct davinci_mmc_config dm6446evm_mmc_config = {
+	.get_cd		= dm6444evm_mmc_get_cd,
+	.get_ro		= dm6444evm_mmc_get_ro,
+	.wires		= 4,
+	.version	= MMC_CTLR_VERSION_1
+};
+
 static struct i2c_board_info __initdata i2c_info[] =  {
 	{
 		I2C_BOARD_INFO("dm6446evm_msp", 0x23),
@@ -598,7 +590,6 @@
 static void __init
 davinci_evm_map_io(void)
 {
-	davinci_map_common_io();
 	dm644x_init();
 }
 
@@ -639,6 +630,7 @@
 static __init void davinci_evm_init(void)
 {
 	struct clk *aemif_clk;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	aemif_clk = clk_get(NULL, "aemif");
 	clk_enable(aemif_clk);
@@ -671,8 +663,13 @@
 			     ARRAY_SIZE(davinci_evm_devices));
 	evm_init_i2c();
 
+	davinci_setup_mmc(0, &dm6446evm_mmc_config);
+
 	davinci_serial_init(&uart_config);
 
+	soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK;
+	soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY;
+
 	/* Register the fixup for PHY on DaVinci */
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
 					davinci_phy_fixup);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm646x-evm.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm646x-evm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-dm646x-evm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-dm646x-evm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,261 @@
+/*
+ * TI DaVinci DM646X EVM board
+ *
+ * Derived from: arch/arm/mach-davinci/board-evm.c
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * (C) 2007-2008, MontaVista Software, Inc.
+ *
+ * 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.
+ *
+ */
+
+/**************************************************************************
+ * Included Files
+ **************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/root_dev.h>
+#include <linux/dma-mapping.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/i2c/pcf857x.h>
+#include <linux/etherdevice.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/dm646x.h>
+#include <mach/common.h>
+#include <mach/psc.h>
+#include <mach/serial.h>
+#include <mach/i2c.h>
+#include <mach/mmc.h>
+#include <mach/emac.h>
+
+#define DM646X_EVM_PHY_MASK		(0x2)
+#define DM646X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
+
+static struct davinci_uart_config uart_config __initdata = {
+	.enabled_uarts = (1 << 0),
+};
+
+/* LEDS */
+
+static struct gpio_led evm_leds[] = {
+	{ .name = "DS1", .active_low = 1, },
+	{ .name = "DS2", .active_low = 1, },
+	{ .name = "DS3", .active_low = 1, },
+	{ .name = "DS4", .active_low = 1, },
+};
+
+static __initconst struct gpio_led_platform_data evm_led_data = {
+	.num_leds = ARRAY_SIZE(evm_leds),
+	.leds     = evm_leds,
+};
+
+static struct platform_device *evm_led_dev;
+
+static int evm_led_setup(struct i2c_client *client, int gpio,
+			unsigned int ngpio, void *c)
+{
+	struct gpio_led *leds = evm_leds;
+	int status;
+
+	while (ngpio--) {
+		leds->gpio = gpio++;
+		leds++;
+	};
+
+	evm_led_dev = platform_device_alloc("leds-gpio", 0);
+	platform_device_add_data(evm_led_dev, &evm_led_data,
+				sizeof(evm_led_data));
+
+	evm_led_dev->dev.parent = &client->dev;
+	status = platform_device_add(evm_led_dev);
+	if (status < 0) {
+		platform_device_put(evm_led_dev);
+		evm_led_dev = NULL;
+	}
+	return status;
+}
+
+static int evm_led_teardown(struct i2c_client *client, int gpio,
+				unsigned ngpio, void *c)
+{
+	if (evm_led_dev) {
+		platform_device_unregister(evm_led_dev);
+		evm_led_dev = NULL;
+	}
+	return 0;
+}
+
+static int evm_sw_gpio[4] = { -EINVAL, -EINVAL, -EINVAL, -EINVAL };
+
+static int evm_sw_setup(struct i2c_client *client, int gpio,
+			unsigned ngpio, void *c)
+{
+	int status;
+	int i;
+	char label[10];
+
+	for (i = 0; i < 4; ++i) {
+		snprintf(label, 10, "user_sw%d", i);
+		status = gpio_request(gpio, label);
+		if (status)
+			goto out_free;
+		evm_sw_gpio[i] = gpio++;
+
+		status = gpio_direction_input(evm_sw_gpio[i]);
+		if (status) {
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+			goto out_free;
+		}
+
+		status = gpio_export(evm_sw_gpio[i], 0);
+		if (status) {
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+			goto out_free;
+		}
+	}
+	return status;
+out_free:
+	for (i = 0; i < 4; ++i) {
+		if (evm_sw_gpio[i] != -EINVAL) {
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+		}
+	}
+	return status;
+}
+
+static int evm_sw_teardown(struct i2c_client *client, int gpio,
+			unsigned ngpio, void *c)
+{
+	int i;
+
+	for (i = 0; i < 4; ++i) {
+		if (evm_sw_gpio[i] != -EINVAL) {
+			gpio_unexport(evm_sw_gpio[i]);
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int evm_pcf_setup(struct i2c_client *client, int gpio,
+			unsigned int ngpio, void *c)
+{
+	int status;
+
+	if (ngpio < 8)
+		return -EINVAL;
+
+	status = evm_sw_setup(client, gpio, 4, c);
+	if (status)
+		return status;
+
+	return evm_led_setup(client, gpio+4, 4, c);
+}
+
+static int evm_pcf_teardown(struct i2c_client *client, int gpio,
+			unsigned int ngpio, void *c)
+{
+	BUG_ON(ngpio < 8);
+
+	evm_sw_teardown(client, gpio, 4, c);
+	evm_led_teardown(client, gpio+4, 4, c);
+
+	return 0;
+}
+
+static struct pcf857x_platform_data pcf_data = {
+	.gpio_base	= DAVINCI_N_GPIO+1,
+	.setup		= evm_pcf_setup,
+	.teardown	= evm_pcf_teardown,
+};
+
+/* Most of this EEPROM is unused, but U-Boot uses some data:
+ *  - 0x7f00, 6 bytes Ethernet Address
+ *  - ... newer boards may have more
+ */
+
+static struct at24_platform_data eeprom_info = {
+	.byte_len       = (256*1024) / 8,
+	.page_size      = 64,
+	.flags          = AT24_FLAG_ADDR16,
+	.setup          = davinci_get_mac_addr,
+	.context	= (void *)0x7f00,
+};
+
+static struct i2c_board_info __initdata i2c_info[] =  {
+	{
+		I2C_BOARD_INFO("24c256", 0x50),
+		.platform_data  = &eeprom_info,
+	},
+	{
+		I2C_BOARD_INFO("pcf8574a", 0x38),
+		.platform_data	= &pcf_data,
+	},
+};
+
+static struct davinci_i2c_platform_data i2c_pdata = {
+	.bus_freq       = 100 /* kHz */,
+	.bus_delay      = 0 /* usec */,
+};
+
+static void __init evm_init_i2c(void)
+{
+	davinci_init_i2c(&i2c_pdata);
+	i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
+}
+
+static void __init davinci_map_io(void)
+{
+	dm646x_init();
+}
+
+static __init void evm_init(void)
+{
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	evm_init_i2c();
+	davinci_serial_init(&uart_config);
+
+	soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK;
+	soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY;
+}
+
+static __init void davinci_dm646x_evm_irq_init(void)
+{
+	davinci_irq_init();
+}
+
+MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
+	.phys_io      = IO_PHYS,
+	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
+	.boot_params  = (0x80000100),
+	.map_io       = davinci_map_io,
+	.init_irq     = davinci_dm646x_evm_irq_init,
+	.timer        = &davinci_timer,
+	.init_machine = evm_init,
+MACHINE_END
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-sffsdr.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-sffsdr.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/board-sffsdr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/board-sffsdr.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,188 @@
+/*
+ * Lyrtech SFFSDR board support.
+ *
+ * Copyright (C) 2008 Philip Balister, OpenSDR <philip@opensdr.com>
+ * Copyright (C) 2008 Lyrtech <www.lyrtech.com>
+ *
+ * Based on DV-EVM platform, original copyright follows:
+ *
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/etherdevice.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/dm644x.h>
+#include <mach/common.h>
+#include <mach/i2c.h>
+#include <mach/serial.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+
+#define SFFSDR_PHY_MASK		(0x2)
+#define SFFSDR_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
+
+#define DAVINCI_ASYNC_EMIF_CONTROL_BASE   0x01e00000
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE  0x02000000
+
+struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
+	/* U-Boot Environment: Block 0
+	 * UBL:                Block 1
+	 * U-Boot:             Blocks 6-7 (256 kb)
+	 * Integrity Kernel:   Blocks 8-31 (3 Mb)
+	 * Integrity Data:     Blocks 100-END
+	 */
+	{
+		.name		= "Linux Kernel",
+		.offset		= 32 * SZ_128K,
+		.size		= 16 * SZ_128K, /* 2 Mb */
+		.mask_flags	= MTD_WRITEABLE, /* Force read-only */
+	},
+	{
+		.name		= "Linux ROOT",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 256 * SZ_128K, /* 32 Mb */
+		.mask_flags	= 0, /* R/W */
+	},
+};
+
+static struct flash_platform_data davinci_sffsdr_nandflash_data = {
+	.parts		= davinci_sffsdr_nandflash_partition,
+	.nr_parts	= ARRAY_SIZE(davinci_sffsdr_nandflash_partition),
+};
+
+static struct resource davinci_sffsdr_nandflash_resource[] = {
+	{
+		.start		= DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
+		.end		= DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= DAVINCI_ASYNC_EMIF_CONTROL_BASE,
+		.end		= DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device davinci_sffsdr_nandflash_device = {
+	.name		= "davinci_nand", /* Name of driver */
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &davinci_sffsdr_nandflash_data,
+	},
+	.num_resources	= ARRAY_SIZE(davinci_sffsdr_nandflash_resource),
+	.resource	= davinci_sffsdr_nandflash_resource,
+};
+
+static struct emac_platform_data sffsdr_emac_pdata = {
+	.phy_mask	= SFFSDR_PHY_MASK,
+	.mdio_max_freq	= SFFSDR_MDIO_FREQUENCY,
+};
+
+static struct at24_platform_data eeprom_info = {
+	.byte_len	= (64*1024) / 8,
+	.page_size	= 32,
+	.flags		= AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info __initdata i2c_info[] =  {
+	{
+		I2C_BOARD_INFO("24lc64", 0x50),
+		.platform_data	= &eeprom_info,
+	},
+	/* Other I2C devices:
+	 * MSP430,  addr 0x23 (not used)
+	 * PCA9543, addr 0x70 (setup done by U-Boot)
+	 * ADS7828, addr 0x48 (ADC for voltage monitoring.)
+	 */
+};
+
+static struct davinci_i2c_platform_data i2c_pdata = {
+	.bus_freq	= 20 /* kHz */,
+	.bus_delay	= 100 /* usec */,
+};
+
+static void __init sffsdr_init_i2c(void)
+{
+	davinci_init_i2c(&i2c_pdata);
+	i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
+}
+
+static struct platform_device *davinci_sffsdr_devices[] __initdata = {
+	&davinci_sffsdr_nandflash_device,
+};
+
+static struct davinci_uart_config uart_config __initdata = {
+	.enabled_uarts = (1 << 0),
+};
+
+static void __init davinci_sffsdr_map_io(void)
+{
+	dm644x_init();
+}
+
+static __init void davinci_sffsdr_init(void)
+{
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	platform_add_devices(davinci_sffsdr_devices,
+			     ARRAY_SIZE(davinci_sffsdr_devices));
+	sffsdr_init_i2c();
+	davinci_serial_init(&uart_config);
+	soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK;
+	soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY;
+	setup_usb(0, 0); /* We support only peripheral mode. */
+
+	/* mux VLYNQ pins */
+	davinci_cfg_reg(DM644X_VLYNQEN);
+	davinci_cfg_reg(DM644X_VLYNQWD);
+}
+
+static __init void davinci_sffsdr_irq_init(void)
+{
+	davinci_irq_init();
+}
+
+MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
+	/* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
+	.phys_io      = IO_PHYS,
+	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
+	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
+	.map_io	      = davinci_sffsdr_map_io,
+	.init_irq     = davinci_sffsdr_irq_init,
+	.timer	      = &davinci_timer,
+	.init_machine = davinci_sffsdr_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,7 +42,8 @@
 	if (clk->parent)
 		__clk_enable(clk->parent);
 	if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
-		davinci_psc_config(psc_domain(clk), clk->lpsc, 1);
+		davinci_psc_config(psc_domain(clk), clk->psc_ctlr,
+				clk->lpsc, 1);
 }
 
 static void __clk_disable(struct clk *clk)
@@ -50,7 +51,8 @@
 	if (WARN_ON(clk->usecount == 0))
 		return;
 	if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
-		davinci_psc_config(psc_domain(clk), clk->lpsc, 0);
+		davinci_psc_config(psc_domain(clk), clk->psc_ctlr,
+				clk->lpsc, 0);
 	if (clk->parent)
 		__clk_disable(clk->parent);
 }
@@ -164,11 +166,11 @@
 			continue;
 
 		/* ignore if in Disabled or SwRstDisable states */
-		if (!davinci_psc_is_clk_active(ck->lpsc))
+		if (!davinci_psc_is_clk_active(ck->psc_ctlr, ck->lpsc))
 			continue;
 
 		pr_info("Clocks: disable unused %s\n", ck->name);
-		davinci_psc_config(psc_domain(ck), ck->lpsc, 0);
+		davinci_psc_config(psc_domain(ck), ck->psc_ctlr, ck->lpsc, 0);
 	}
 	spin_unlock_irq(&clockfw_lock);
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/clock.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/clock.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/clock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -67,6 +67,7 @@
 	u8			usecount;
 	u8			flags;
 	u8			lpsc;
+	u8			psc_ctlr;
 	struct clk              *parent;
 	struct pll_data         *pll_data;
 	u32                     div_reg;
@@ -93,4 +94,7 @@
 	}
 
 int davinci_clk_init(struct davinci_clk *clocks);
+
+extern struct platform_device davinci_wdt_device;
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/common.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/common.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/common.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,108 @@
+/*
+ * Code commons to all DaVinci SoCs.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2009 (c) MontaVista Software, Inc. 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/module.h>
+#include <linux/io.h>
+#include <linux/etherdevice.h>
+
+#include <asm/tlb.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/cputype.h>
+#include <mach/emac.h>
+
+#include "clock.h"
+
+struct davinci_soc_info davinci_soc_info;
+EXPORT_SYMBOL(davinci_soc_info);
+
+void __iomem *davinci_intc_base;
+int davinci_intc_type;
+
+void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context)
+{
+	char *mac_addr = davinci_soc_info.emac_pdata->mac_addr;
+	off_t offset = (off_t)context;
+
+	/* Read MAC addr from EEPROM */
+	if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
+		pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
+}
+
+static struct davinci_id * __init davinci_get_id(u32 jtag_id)
+{
+	int i;
+	struct davinci_id *dip;
+	u8 variant = (jtag_id & 0xf0000000) >> 28;
+	u16 part_no = (jtag_id & 0x0ffff000) >> 12;
+
+	for (i = 0, dip = davinci_soc_info.ids; i < davinci_soc_info.ids_num;
+			i++, dip++)
+		/* Don't care about the manufacturer right now */
+		if ((dip->part_no == part_no) && (dip->variant == variant))
+			return dip;
+
+	return NULL;
+}
+
+void __init davinci_common_init(struct davinci_soc_info *soc_info)
+{
+	int ret;
+	struct davinci_id *dip;
+
+	if (!soc_info) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	memcpy(&davinci_soc_info, soc_info, sizeof(struct davinci_soc_info));
+
+	if (davinci_soc_info.io_desc && (davinci_soc_info.io_desc_num > 0))
+		iotable_init(davinci_soc_info.io_desc,
+				davinci_soc_info.io_desc_num);
+
+	/*
+	 * Normally devicemaps_init() would flush caches and tlb after
+	 * mdesc->map_io(), but we must also do it here because of the CPU
+	 * revision check below.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+
+	/*
+	 * We want to check CPU revision early for cpu_is_xxxx() macros.
+	 * IO space mapping must be initialized before we can do that.
+	 */
+	davinci_soc_info.jtag_id = __raw_readl(davinci_soc_info.jtag_id_base);
+
+	dip = davinci_get_id(davinci_soc_info.jtag_id);
+	if (!dip) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	davinci_soc_info.cpu_id = dip->cpu_id;
+	pr_info("DaVinci %s variant 0x%x\n", dip->name, dip->variant);
+
+	if (davinci_soc_info.cpu_clks) {
+		ret = davinci_clk_init(davinci_soc_info.cpu_clks);
+
+		if (ret != 0)
+			goto err;
+	}
+
+	davinci_intc_base = davinci_soc_info.intc_base;
+	davinci_intc_type = davinci_soc_info.intc_type;
+	return;
+
+err:
+	pr_err("davinci_common_init: SoC Initialization failed\n");
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/cp_intc.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/cp_intc.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/cp_intc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/cp_intc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ * TI Common Platform Interrupt Controller (cp_intc) driver
+ *
+ * Author: Steve Chen <schen@mvista.com>
+ * Copyright (C) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/cp_intc.h>
+
+static void __iomem *cp_intc_base;
+
+static inline unsigned int cp_intc_read(unsigned offset)
+{
+	return __raw_readl(cp_intc_base + offset);
+}
+
+static inline void cp_intc_write(unsigned long value, unsigned offset)
+{
+	__raw_writel(value, cp_intc_base + offset);
+}
+
+static void cp_intc_ack_irq(unsigned int irq)
+{
+	cp_intc_write(irq, CP_INTC_SYS_STAT_IDX_CLR);
+}
+
+/* Disable interrupt */
+static void cp_intc_mask_irq(unsigned int irq)
+{
+	/* XXX don't know why we need to disable nIRQ here... */
+	cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR);
+	cp_intc_write(irq, CP_INTC_SYS_ENABLE_IDX_CLR);
+	cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET);
+}
+
+/* Enable interrupt */
+static void cp_intc_unmask_irq(unsigned int irq)
+{
+	cp_intc_write(irq, CP_INTC_SYS_ENABLE_IDX_SET);
+}
+
+static int cp_intc_set_irq_type(unsigned int irq, unsigned int flow_type)
+{
+	unsigned reg		= BIT_WORD(irq);
+	unsigned mask		= BIT_MASK(irq);
+	unsigned polarity	= cp_intc_read(CP_INTC_SYS_POLARITY(reg));
+	unsigned type		= cp_intc_read(CP_INTC_SYS_TYPE(reg));
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_RISING:
+		polarity |= mask;
+		type |= mask;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		polarity &= ~mask;
+		type |= mask;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		polarity |= mask;
+		type &= ~mask;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		polarity &= ~mask;
+		type &= ~mask;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cp_intc_write(polarity, CP_INTC_SYS_POLARITY(reg));
+	cp_intc_write(type, CP_INTC_SYS_TYPE(reg));
+
+	return 0;
+}
+
+static struct irq_chip cp_intc_irq_chip = {
+	.name		= "cp_intc",
+	.ack		= cp_intc_ack_irq,
+	.mask		= cp_intc_mask_irq,
+	.unmask		= cp_intc_unmask_irq,
+	.set_type	= cp_intc_set_irq_type,
+};
+
+void __init cp_intc_init(void __iomem *base, unsigned short num_irq,
+			 u8 *irq_prio)
+{
+	unsigned num_reg	= BITS_TO_LONGS(num_irq);
+	int i;
+
+	cp_intc_base = base;
+
+	cp_intc_write(0, CP_INTC_GLOBAL_ENABLE);
+
+	/* Disable all host interrupts */
+	cp_intc_write(0, CP_INTC_HOST_ENABLE(0));
+
+	/* Disable system interrupts */
+	for (i = 0; i < num_reg; i++)
+		cp_intc_write(~0, CP_INTC_SYS_ENABLE_CLR(i));
+
+	/* Set to normal mode, no nesting, no priority hold */
+	cp_intc_write(0, CP_INTC_CTRL);
+	cp_intc_write(0, CP_INTC_HOST_CTRL);
+
+	/* Clear system interrupt status */
+	for (i = 0; i < num_reg; i++)
+		cp_intc_write(~0, CP_INTC_SYS_STAT_CLR(i));
+
+	/* Enable nIRQ (what about nFIQ?) */
+	cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET);
+
+	/*
+	 * Priority is determined by host channel: lower channel number has
+	 * higher priority i.e. channel 0 has highest priority and channel 31
+	 * had the lowest priority.
+	 */
+	num_reg = (num_irq + 3) >> 2;	/* 4 channels per register */
+	if (irq_prio) {
+		unsigned j, k;
+		u32 val;
+
+		for (k = i = 0; i < num_reg; i++) {
+			for (val = j = 0; j < 4; j++, k++) {
+				val >>= 8;
+				if (k < num_irq)
+					val |= irq_prio[k] << 24;
+			}
+
+			cp_intc_write(val, CP_INTC_CHAN_MAP(i));
+		}
+	} else	{
+		/*
+		 * Default everything to channel 15 if priority not specified.
+		 * Note that channel 0-1 are mapped to nFIQ and channels 2-31
+		 * are mapped to nIRQ.
+		 */
+		for (i = 0; i < num_reg; i++)
+			cp_intc_write(0x0f0f0f0f, CP_INTC_CHAN_MAP(i));
+	}
+
+	/* Set up genirq dispatching for cp_intc */
+	for (i = 0; i < num_irq; i++) {
+		set_irq_chip(i, &cp_intc_irq_chip);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+		set_irq_handler(i, handle_edge_irq);
+	}
+
+	/* Enable global interrupt */
+	cp_intc_write(1, CP_INTC_GLOBAL_ENABLE);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/devices.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/devices.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/devices.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/devices.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,14 @@
 #include <mach/irqs.h>
 #include <mach/cputype.h>
 #include <mach/mux.h>
+#include <mach/edma.h>
+#include <mach/mmc.h>
+#include <mach/time.h>
 
 #define DAVINCI_I2C_BASE	     0x01C21000
+#define DAVINCI_MMCSD0_BASE	     0x01E10000
+#define DM355_MMCSD0_BASE	     0x01E11000
+#define DM355_MMCSD1_BASE	     0x01E00000
 
 static struct resource i2c_resources[] = {
 	{
@@ -54,3 +60,208 @@
 	(void) platform_device_register(&davinci_i2c_device);
 }
 
+#if	defined(CONFIG_MMC_DAVINCI) || defined(CONFIG_MMC_DAVINCI_MODULE)
+
+static u64 mmcsd0_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource mmcsd0_resources[] = {
+	{
+		/* different on dm355 */
+		.start = DAVINCI_MMCSD0_BASE,
+		.end   = DAVINCI_MMCSD0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	/* IRQs:  MMC/SD, then SDIO */
+	{
+		.start = IRQ_MMCINT,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		/* different on dm355 */
+		.start = IRQ_SDIOINT,
+		.flags = IORESOURCE_IRQ,
+	},
+	/* DMA channels: RX, then TX */
+	{
+		.start = DAVINCI_DMA_MMCRXEVT,
+		.flags = IORESOURCE_DMA,
+	}, {
+		.start = DAVINCI_DMA_MMCTXEVT,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device davinci_mmcsd0_device = {
+	.name = "davinci_mmc",
+	.id = 0,
+	.dev = {
+		.dma_mask = &mmcsd0_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources = ARRAY_SIZE(mmcsd0_resources),
+	.resource = mmcsd0_resources,
+};
+
+static u64 mmcsd1_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource mmcsd1_resources[] = {
+	{
+		.start = DM355_MMCSD1_BASE,
+		.end   = DM355_MMCSD1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	/* IRQs:  MMC/SD, then SDIO */
+	{
+		.start = IRQ_DM355_MMCINT1,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = IRQ_DM355_SDIOINT1,
+		.flags = IORESOURCE_IRQ,
+	},
+	/* DMA channels: RX, then TX */
+	{
+		.start = 30,	/* rx */
+		.flags = IORESOURCE_DMA,
+	}, {
+		.start = 31,	/* tx */
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device davinci_mmcsd1_device = {
+	.name = "davinci_mmc",
+	.id = 1,
+	.dev = {
+		.dma_mask = &mmcsd1_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources = ARRAY_SIZE(mmcsd1_resources),
+	.resource = mmcsd1_resources,
+};
+
+
+void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config)
+{
+	struct platform_device	*pdev = NULL;
+
+	if (WARN_ON(cpu_is_davinci_dm646x()))
+		return;
+
+	/* REVISIT: update PINMUX, ARM_IRQMUX, and EDMA_EVTMUX here too;
+	 * for example if MMCSD1 is used for SDIO, maybe DAT2 is unused.
+	 *
+	 * FIXME dm6441 (no MMC/SD), dm357 (one), and dm335 (two) are
+	 * not handled right here ...
+	 */
+	switch (module) {
+	case 1:
+		if (!cpu_is_davinci_dm355())
+			break;
+
+		/* REVISIT we may not need all these pins if e.g. this
+		 * is a hard-wired SDIO device...
+		 */
+		davinci_cfg_reg(DM355_SD1_CMD);
+		davinci_cfg_reg(DM355_SD1_CLK);
+		davinci_cfg_reg(DM355_SD1_DATA0);
+		davinci_cfg_reg(DM355_SD1_DATA1);
+		davinci_cfg_reg(DM355_SD1_DATA2);
+		davinci_cfg_reg(DM355_SD1_DATA3);
+
+		pdev = &davinci_mmcsd1_device;
+		break;
+	case 0:
+		if (cpu_is_davinci_dm355()) {
+			mmcsd0_resources[0].start = DM355_MMCSD0_BASE;
+			mmcsd0_resources[0].end = DM355_MMCSD0_BASE + SZ_4K - 1;
+			mmcsd0_resources[2].start = IRQ_DM355_SDIOINT0;
+
+			/* expose all 6 MMC0 signals:  CLK, CMD, DATA[0..3] */
+			davinci_cfg_reg(DM355_MMCSD0);
+
+			/* enable RX EDMA */
+			davinci_cfg_reg(DM355_EVT26_MMC0_RX);
+		}
+
+		else if (cpu_is_davinci_dm644x()) {
+			/* REVISIT: should this be in board-init code? */
+			void __iomem *base =
+				IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE);
+
+			/* Power-on 3.3V IO cells */
+			__raw_writel(0, base + DM64XX_VDD3P3V_PWDN);
+			/*Set up the pull regiter for MMC */
+			davinci_cfg_reg(DM644X_MSTK);
+		}
+
+		pdev = &davinci_mmcsd0_device;
+		break;
+	}
+
+	if (WARN_ON(!pdev))
+		return;
+
+	pdev->dev.platform_data = config;
+	platform_device_register(pdev);
+}
+
+#else
+
+void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config)
+{
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct resource wdt_resources[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device davinci_wdt_device = {
+	.name		= "watchdog",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(wdt_resources),
+	.resource	= wdt_resources,
+};
+
+static void davinci_init_wdt(void)
+{
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	wdt_resources[0].start = (resource_size_t)soc_info->wdt_base;
+	wdt_resources[0].end = (resource_size_t)soc_info->wdt_base + SZ_1K - 1;
+
+	platform_device_register(&davinci_wdt_device);
+}
+
+/*-------------------------------------------------------------------------*/
+
+struct davinci_timer_instance davinci_timer_instance[2] = {
+	{
+		.base		= IO_ADDRESS(DAVINCI_TIMER0_BASE),
+		.bottom_irq	= IRQ_TINT0_TINT12,
+		.top_irq	= IRQ_TINT0_TINT34,
+	},
+	{
+		.base		= IO_ADDRESS(DAVINCI_TIMER1_BASE),
+		.bottom_irq	= IRQ_TINT1_TINT12,
+		.top_irq	= IRQ_TINT1_TINT34,
+	},
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init davinci_init_devices(void)
+{
+	/* please keep these calls, and their implementations above,
+	 * in alphabetical order so they're easier to sort through.
+	 */
+	davinci_init_wdt();
+
+	return 0;
+}
+arch_initcall(davinci_init_devices);
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/dm355.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/dm355.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/dm355.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/dm355.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,730 @@
+/*
+ * TI DaVinci DM355 chip specific setup
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/serial_8250.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <linux/spi/spi.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/dm355.h>
+#include <mach/clock.h>
+#include <mach/cputype.h>
+#include <mach/edma.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+#include <mach/irqs.h>
+#include <mach/time.h>
+#include <mach/serial.h>
+#include <mach/common.h>
+
+#include "clock.h"
+#include "mux.h"
+
+#define DM355_UART2_BASE	(IO_PHYS + 0x206000)
+
+/*
+ * Device specific clocks
+ */
+#define DM355_REF_FREQ		24000000	/* 24 or 36 MHz */
+
+static struct pll_data pll1_data = {
+	.num       = 1,
+	.phys_base = DAVINCI_PLL1_BASE,
+	.flags     = PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
+};
+
+static struct pll_data pll2_data = {
+	.num       = 2,
+	.phys_base = DAVINCI_PLL2_BASE,
+	.flags     = PLL_HAS_PREDIV,
+};
+
+static struct clk ref_clk = {
+	.name = "ref_clk",
+	/* FIXME -- crystal rate is board-specific */
+	.rate = DM355_REF_FREQ,
+};
+
+static struct clk pll1_clk = {
+	.name = "pll1",
+	.parent = &ref_clk,
+	.flags = CLK_PLL,
+	.pll_data = &pll1_data,
+};
+
+static struct clk pll1_aux_clk = {
+	.name = "pll1_aux_clk",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL | PRE_PLL,
+};
+
+static struct clk pll1_sysclk1 = {
+	.name = "pll1_sysclk1",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV1,
+};
+
+static struct clk pll1_sysclk2 = {
+	.name = "pll1_sysclk2",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV2,
+};
+
+static struct clk pll1_sysclk3 = {
+	.name = "pll1_sysclk3",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV3,
+};
+
+static struct clk pll1_sysclk4 = {
+	.name = "pll1_sysclk4",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV4,
+};
+
+static struct clk pll1_sysclkbp = {
+	.name = "pll1_sysclkbp",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL | PRE_PLL,
+	.div_reg = BPDIV
+};
+
+static struct clk vpss_dac_clk = {
+	.name = "vpss_dac",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM355_LPSC_VPSS_DAC,
+};
+
+static struct clk vpss_master_clk = {
+	.name = "vpss_master",
+	.parent = &pll1_sysclk4,
+	.lpsc = DAVINCI_LPSC_VPSSMSTR,
+	.flags = CLK_PSC,
+};
+
+static struct clk vpss_slave_clk = {
+	.name = "vpss_slave",
+	.parent = &pll1_sysclk4,
+	.lpsc = DAVINCI_LPSC_VPSSSLV,
+};
+
+
+static struct clk clkout1_clk = {
+	.name = "clkout1",
+	.parent = &pll1_aux_clk,
+	/* NOTE:  clkout1 can be externally gated by muxing GPIO-18 */
+};
+
+static struct clk clkout2_clk = {
+	.name = "clkout2",
+	.parent = &pll1_sysclkbp,
+};
+
+static struct clk pll2_clk = {
+	.name = "pll2",
+	.parent = &ref_clk,
+	.flags = CLK_PLL,
+	.pll_data = &pll2_data,
+};
+
+static struct clk pll2_sysclk1 = {
+	.name = "pll2_sysclk1",
+	.parent = &pll2_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV1,
+};
+
+static struct clk pll2_sysclkbp = {
+	.name = "pll2_sysclkbp",
+	.parent = &pll2_clk,
+	.flags = CLK_PLL | PRE_PLL,
+	.div_reg = BPDIV
+};
+
+static struct clk clkout3_clk = {
+	.name = "clkout3",
+	.parent = &pll2_sysclkbp,
+	/* NOTE:  clkout3 can be externally gated by muxing GPIO-16 */
+};
+
+static struct clk arm_clk = {
+	.name = "arm_clk",
+	.parent = &pll1_sysclk1,
+	.lpsc = DAVINCI_LPSC_ARM,
+	.flags = ALWAYS_ENABLED,
+};
+
+/*
+ * NOT LISTED below, and not touched by Linux
+ *   - in SyncReset state by default
+ *	.lpsc = DAVINCI_LPSC_TPCC,
+ *	.lpsc = DAVINCI_LPSC_TPTC0,
+ *	.lpsc = DAVINCI_LPSC_TPTC1,
+ *	.lpsc = DAVINCI_LPSC_DDR_EMIF, .parent = &sysclk2_clk,
+ *	.lpsc = DAVINCI_LPSC_MEMSTICK,
+ *   - in Enabled state by default
+ *	.lpsc = DAVINCI_LPSC_SYSTEM_SUBSYS,
+ *	.lpsc = DAVINCI_LPSC_SCR2,	// "bus"
+ *	.lpsc = DAVINCI_LPSC_SCR3,	// "bus"
+ *	.lpsc = DAVINCI_LPSC_SCR4,	// "bus"
+ *	.lpsc = DAVINCI_LPSC_CROSSBAR,	// "emulation"
+ *	.lpsc = DAVINCI_LPSC_CFG27,	// "test"
+ *	.lpsc = DAVINCI_LPSC_CFG3,	// "test"
+ *	.lpsc = DAVINCI_LPSC_CFG5,	// "test"
+ */
+
+static struct clk mjcp_clk = {
+	.name = "mjcp",
+	.parent = &pll1_sysclk1,
+	.lpsc = DAVINCI_LPSC_IMCOP,
+};
+
+static struct clk uart0_clk = {
+	.name = "uart0",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_UART0,
+};
+
+static struct clk uart1_clk = {
+	.name = "uart1",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_UART1,
+};
+
+static struct clk uart2_clk = {
+	.name = "uart2",
+	.parent = &pll1_sysclk2,
+	.lpsc = DAVINCI_LPSC_UART2,
+};
+
+static struct clk i2c_clk = {
+	.name = "i2c",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_I2C,
+};
+
+static struct clk asp0_clk = {
+	.name = "asp0",
+	.parent = &pll1_sysclk2,
+	.lpsc = DAVINCI_LPSC_McBSP,
+};
+
+static struct clk asp1_clk = {
+	.name = "asp1",
+	.parent = &pll1_sysclk2,
+	.lpsc = DM355_LPSC_McBSP1,
+};
+
+static struct clk mmcsd0_clk = {
+	.name = "mmcsd0",
+	.parent = &pll1_sysclk2,
+	.lpsc = DAVINCI_LPSC_MMC_SD,
+};
+
+static struct clk mmcsd1_clk = {
+	.name = "mmcsd1",
+	.parent = &pll1_sysclk2,
+	.lpsc = DM355_LPSC_MMC_SD1,
+};
+
+static struct clk spi0_clk = {
+	.name = "spi0",
+	.parent = &pll1_sysclk2,
+	.lpsc = DAVINCI_LPSC_SPI,
+};
+
+static struct clk spi1_clk = {
+	.name = "spi1",
+	.parent = &pll1_sysclk2,
+	.lpsc = DM355_LPSC_SPI1,
+};
+
+static struct clk spi2_clk = {
+	.name = "spi2",
+	.parent = &pll1_sysclk2,
+	.lpsc = DM355_LPSC_SPI2,
+};
+
+static struct clk gpio_clk = {
+	.name = "gpio",
+	.parent = &pll1_sysclk2,
+	.lpsc = DAVINCI_LPSC_GPIO,
+};
+
+static struct clk aemif_clk = {
+	.name = "aemif",
+	.parent = &pll1_sysclk2,
+	.lpsc = DAVINCI_LPSC_AEMIF,
+};
+
+static struct clk pwm0_clk = {
+	.name = "pwm0",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_PWM0,
+};
+
+static struct clk pwm1_clk = {
+	.name = "pwm1",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_PWM1,
+};
+
+static struct clk pwm2_clk = {
+	.name = "pwm2",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_PWM2,
+};
+
+static struct clk pwm3_clk = {
+	.name = "pwm3",
+	.parent = &pll1_aux_clk,
+	.lpsc = DM355_LPSC_PWM3,
+};
+
+static struct clk timer0_clk = {
+	.name = "timer0",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_TIMER0,
+};
+
+static struct clk timer1_clk = {
+	.name = "timer1",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_TIMER1,
+};
+
+static struct clk timer2_clk = {
+	.name = "timer2",
+	.parent = &pll1_aux_clk,
+	.lpsc = DAVINCI_LPSC_TIMER2,
+	.usecount = 1,              /* REVISIT: why cant' this be disabled? */
+};
+
+static struct clk timer3_clk = {
+	.name = "timer3",
+	.parent = &pll1_aux_clk,
+	.lpsc = DM355_LPSC_TIMER3,
+};
+
+static struct clk rto_clk = {
+	.name = "rto",
+	.parent = &pll1_aux_clk,
+	.lpsc = DM355_LPSC_RTO,
+};
+
+static struct clk usb_clk = {
+	.name = "usb",
+	.parent = &pll1_sysclk2,
+	.lpsc = DAVINCI_LPSC_USB,
+};
+
+static struct davinci_clk dm355_clks[] = {
+	CLK(NULL, "ref", &ref_clk),
+	CLK(NULL, "pll1", &pll1_clk),
+	CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
+	CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
+	CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
+	CLK(NULL, "pll1_sysclk4", &pll1_sysclk4),
+	CLK(NULL, "pll1_aux", &pll1_aux_clk),
+	CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp),
+	CLK(NULL, "vpss_dac", &vpss_dac_clk),
+	CLK(NULL, "vpss_master", &vpss_master_clk),
+	CLK(NULL, "vpss_slave", &vpss_slave_clk),
+	CLK(NULL, "clkout1", &clkout1_clk),
+	CLK(NULL, "clkout2", &clkout2_clk),
+	CLK(NULL, "pll2", &pll2_clk),
+	CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
+	CLK(NULL, "pll2_sysclkbp", &pll2_sysclkbp),
+	CLK(NULL, "clkout3", &clkout3_clk),
+	CLK(NULL, "arm", &arm_clk),
+	CLK(NULL, "mjcp", &mjcp_clk),
+	CLK(NULL, "uart0", &uart0_clk),
+	CLK(NULL, "uart1", &uart1_clk),
+	CLK(NULL, "uart2", &uart2_clk),
+	CLK("i2c_davinci.1", NULL, &i2c_clk),
+	CLK("soc-audio.0", NULL, &asp0_clk),
+	CLK("soc-audio.1", NULL, &asp1_clk),
+	CLK("davinci_mmc.0", NULL, &mmcsd0_clk),
+	CLK("davinci_mmc.1", NULL, &mmcsd1_clk),
+	CLK(NULL, "spi0", &spi0_clk),
+	CLK(NULL, "spi1", &spi1_clk),
+	CLK(NULL, "spi2", &spi2_clk),
+	CLK(NULL, "gpio", &gpio_clk),
+	CLK(NULL, "aemif", &aemif_clk),
+	CLK(NULL, "pwm0", &pwm0_clk),
+	CLK(NULL, "pwm1", &pwm1_clk),
+	CLK(NULL, "pwm2", &pwm2_clk),
+	CLK(NULL, "pwm3", &pwm3_clk),
+	CLK(NULL, "timer0", &timer0_clk),
+	CLK(NULL, "timer1", &timer1_clk),
+	CLK("watchdog", NULL, &timer2_clk),
+	CLK(NULL, "timer3", &timer3_clk),
+	CLK(NULL, "rto", &rto_clk),
+	CLK(NULL, "usb", &usb_clk),
+	CLK(NULL, NULL, NULL),
+};
+
+/*----------------------------------------------------------------------*/
+
+static u64 dm355_spi0_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource dm355_spi0_resources[] = {
+	{
+		.start = 0x01c66000,
+		.end   = 0x01c667ff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_DM355_SPINT0_1,
+		.flags = IORESOURCE_IRQ,
+	},
+	/* Not yet used, so not included:
+	 * IORESOURCE_IRQ:
+	 *  - IRQ_DM355_SPINT0_0
+	 * IORESOURCE_DMA:
+	 *  - DAVINCI_DMA_SPI_SPIX
+	 *  - DAVINCI_DMA_SPI_SPIR
+	 */
+};
+
+static struct platform_device dm355_spi0_device = {
+	.name = "spi_davinci",
+	.id = 0,
+	.dev = {
+		.dma_mask = &dm355_spi0_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources = ARRAY_SIZE(dm355_spi0_resources),
+	.resource = dm355_spi0_resources,
+};
+
+void __init dm355_init_spi0(unsigned chipselect_mask,
+		struct spi_board_info *info, unsigned len)
+{
+	/* for now, assume we need MISO */
+	davinci_cfg_reg(DM355_SPI0_SDI);
+
+	/* not all slaves will be wired up */
+	if (chipselect_mask & BIT(0))
+		davinci_cfg_reg(DM355_SPI0_SDENA0);
+	if (chipselect_mask & BIT(1))
+		davinci_cfg_reg(DM355_SPI0_SDENA1);
+
+	spi_register_board_info(info, len);
+
+	platform_device_register(&dm355_spi0_device);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define PINMUX0		0x00
+#define PINMUX1		0x04
+#define PINMUX2		0x08
+#define PINMUX3		0x0c
+#define PINMUX4		0x10
+#define INTMUX		0x18
+#define EVTMUX		0x1c
+
+/*
+ * Device specific mux setup
+ *
+ *	soc	description	mux  mode   mode  mux	 dbg
+ *				reg  offset mask  mode
+ */
+static const struct mux_config dm355_pins[] = {
+#ifdef CONFIG_DAVINCI_MUX
+MUX_CFG(DM355,	MMCSD0,		4,   2,     1,	  0,	 false)
+
+MUX_CFG(DM355,	SD1_CLK,	3,   6,     1,	  1,	 false)
+MUX_CFG(DM355,	SD1_CMD,	3,   7,     1,	  1,	 false)
+MUX_CFG(DM355,	SD1_DATA3,	3,   8,     3,	  1,	 false)
+MUX_CFG(DM355,	SD1_DATA2,	3,   10,    3,	  1,	 false)
+MUX_CFG(DM355,	SD1_DATA1,	3,   12,    3,	  1,	 false)
+MUX_CFG(DM355,	SD1_DATA0,	3,   14,    3,	  1,	 false)
+
+MUX_CFG(DM355,	I2C_SDA,	3,   19,    1,	  1,	 false)
+MUX_CFG(DM355,	I2C_SCL,	3,   20,    1,	  1,	 false)
+
+MUX_CFG(DM355,	MCBSP0_BDX,	3,   0,     1,	  1,	 false)
+MUX_CFG(DM355,	MCBSP0_X,	3,   1,     1,	  1,	 false)
+MUX_CFG(DM355,	MCBSP0_BFSX,	3,   2,     1,	  1,	 false)
+MUX_CFG(DM355,	MCBSP0_BDR,	3,   3,     1,	  1,	 false)
+MUX_CFG(DM355,	MCBSP0_R,	3,   4,     1,	  1,	 false)
+MUX_CFG(DM355,	MCBSP0_BFSR,	3,   5,     1,	  1,	 false)
+
+MUX_CFG(DM355,	SPI0_SDI,	4,   1,     1,    0,	 false)
+MUX_CFG(DM355,	SPI0_SDENA0,	4,   0,     1,    0,	 false)
+MUX_CFG(DM355,	SPI0_SDENA1,	3,   28,    1,    1,	 false)
+
+INT_CFG(DM355,  INT_EDMA_CC,	      2,    1,    1,     false)
+INT_CFG(DM355,  INT_EDMA_TC0_ERR,     3,    1,    1,     false)
+INT_CFG(DM355,  INT_EDMA_TC1_ERR,     4,    1,    1,     false)
+
+EVT_CFG(DM355,  EVT8_ASP1_TX,	      0,    1,    0,     false)
+EVT_CFG(DM355,  EVT9_ASP1_RX,	      1,    1,    0,     false)
+EVT_CFG(DM355,  EVT26_MMC0_RX,	      2,    1,    0,     false)
+#endif
+};
+
+static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+	[IRQ_DM355_CCDC_VDINT0]		= 2,
+	[IRQ_DM355_CCDC_VDINT1]		= 6,
+	[IRQ_DM355_CCDC_VDINT2]		= 6,
+	[IRQ_DM355_IPIPE_HST]		= 6,
+	[IRQ_DM355_H3AINT]		= 6,
+	[IRQ_DM355_IPIPE_SDR]		= 6,
+	[IRQ_DM355_IPIPEIFINT]		= 6,
+	[IRQ_DM355_OSDINT]		= 7,
+	[IRQ_DM355_VENCINT]		= 6,
+	[IRQ_ASQINT]			= 6,
+	[IRQ_IMXINT]			= 6,
+	[IRQ_USBINT]			= 4,
+	[IRQ_DM355_RTOINT]		= 4,
+	[IRQ_DM355_UARTINT2]		= 7,
+	[IRQ_DM355_TINT6]		= 7,
+	[IRQ_CCINT0]			= 5,	/* dma */
+	[IRQ_CCERRINT]			= 5,	/* dma */
+	[IRQ_TCERRINT0]			= 5,	/* dma */
+	[IRQ_TCERRINT]			= 5,	/* dma */
+	[IRQ_DM355_SPINT2_1]		= 7,
+	[IRQ_DM355_TINT7]		= 4,
+	[IRQ_DM355_SDIOINT0]		= 7,
+	[IRQ_MBXINT]			= 7,
+	[IRQ_MBRINT]			= 7,
+	[IRQ_MMCINT]			= 7,
+	[IRQ_DM355_MMCINT1]		= 7,
+	[IRQ_DM355_PWMINT3]		= 7,
+	[IRQ_DDRINT]			= 7,
+	[IRQ_AEMIFINT]			= 7,
+	[IRQ_DM355_SDIOINT1]		= 4,
+	[IRQ_TINT0_TINT12]		= 2,	/* clockevent */
+	[IRQ_TINT0_TINT34]		= 2,	/* clocksource */
+	[IRQ_TINT1_TINT12]		= 7,	/* DSP timer */
+	[IRQ_TINT1_TINT34]		= 7,	/* system tick */
+	[IRQ_PWMINT0]			= 7,
+	[IRQ_PWMINT1]			= 7,
+	[IRQ_PWMINT2]			= 7,
+	[IRQ_I2C]			= 3,
+	[IRQ_UARTINT0]			= 3,
+	[IRQ_UARTINT1]			= 3,
+	[IRQ_DM355_SPINT0_0]		= 3,
+	[IRQ_DM355_SPINT0_1]		= 3,
+	[IRQ_DM355_GPIO0]		= 3,
+	[IRQ_DM355_GPIO1]		= 7,
+	[IRQ_DM355_GPIO2]		= 4,
+	[IRQ_DM355_GPIO3]		= 4,
+	[IRQ_DM355_GPIO4]		= 7,
+	[IRQ_DM355_GPIO5]		= 7,
+	[IRQ_DM355_GPIO6]		= 7,
+	[IRQ_DM355_GPIO7]		= 7,
+	[IRQ_DM355_GPIO8]		= 7,
+	[IRQ_DM355_GPIO9]		= 7,
+	[IRQ_DM355_GPIOBNK0]		= 7,
+	[IRQ_DM355_GPIOBNK1]		= 7,
+	[IRQ_DM355_GPIOBNK2]		= 7,
+	[IRQ_DM355_GPIOBNK3]		= 7,
+	[IRQ_DM355_GPIOBNK4]		= 7,
+	[IRQ_DM355_GPIOBNK5]		= 7,
+	[IRQ_DM355_GPIOBNK6]		= 7,
+	[IRQ_COMMTX]			= 7,
+	[IRQ_COMMRX]			= 7,
+	[IRQ_EMUINT]			= 7,
+};
+
+/*----------------------------------------------------------------------*/
+
+static const s8 dma_chan_dm355_no_event[] = {
+	12, 13, 24, 56, 57,
+	58, 59, 60, 61, 62,
+	63,
+	-1
+};
+
+static struct edma_soc_info dm355_edma_info = {
+	.n_channel	= 64,
+	.n_region	= 4,
+	.n_slot		= 128,
+	.n_tc		= 2,
+	.noevent	= dma_chan_dm355_no_event,
+};
+
+static struct resource edma_resources[] = {
+	{
+		.name	= "edma_cc",
+		.start	= 0x01c00000,
+		.end	= 0x01c00000 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc0",
+		.start	= 0x01c10000,
+		.end	= 0x01c10000 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc1",
+		.start	= 0x01c10400,
+		.end	= 0x01c10400 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_CCINT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_CCERRINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	/* not using (or muxing) TC*_ERR */
+};
+
+static struct platform_device dm355_edma_device = {
+	.name			= "edma",
+	.id			= -1,
+	.dev.platform_data	= &dm355_edma_info,
+	.num_resources		= ARRAY_SIZE(edma_resources),
+	.resource		= edma_resources,
+};
+
+/*----------------------------------------------------------------------*/
+
+static struct map_desc dm355_io_desc[] = {
+	{
+		.virtual	= IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= SRAM_VIRT,
+		.pfn		= __phys_to_pfn(0x00010000),
+		.length		= SZ_32K,
+		/* MT_MEMORY_NONCACHED requires supersection alignment */
+		.type		= MT_DEVICE,
+	},
+};
+
+/* Contents of JTAG ID register used to identify exact cpu type */
+static struct davinci_id dm355_ids[] = {
+	{
+		.variant	= 0x0,
+		.part_no	= 0xb73b,
+		.manufacturer	= 0x00f,
+		.cpu_id		= DAVINCI_CPU_ID_DM355,
+		.name		= "dm355",
+	},
+};
+
+static void __iomem *dm355_psc_bases[] = {
+	IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
+};
+
+/*
+ * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
+ * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
+ * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
+ * T1_TOP: Timer 1, top   :  <unused>
+ */
+struct davinci_timer_info dm355_timer_info = {
+	.timers		= davinci_timer_instance,
+	.clockevent_id	= T0_BOT,
+	.clocksource_id	= T0_TOP,
+};
+
+static struct plat_serial8250_port dm355_serial_platform_data[] = {
+	{
+		.mapbase	= DAVINCI_UART0_BASE,
+		.irq		= IRQ_UARTINT0,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	},
+	{
+		.mapbase	= DAVINCI_UART1_BASE,
+		.irq		= IRQ_UARTINT1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	},
+	{
+		.mapbase	= DM355_UART2_BASE,
+		.irq		= IRQ_DM355_UARTINT2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	},
+	{
+		.flags		= 0
+	},
+};
+
+static struct platform_device dm355_serial_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= dm355_serial_platform_data,
+	},
+};
+
+static struct davinci_soc_info davinci_soc_info_dm355 = {
+	.io_desc		= dm355_io_desc,
+	.io_desc_num		= ARRAY_SIZE(dm355_io_desc),
+	.jtag_id_base		= IO_ADDRESS(0x01c40028),
+	.ids			= dm355_ids,
+	.ids_num		= ARRAY_SIZE(dm355_ids),
+	.cpu_clks		= dm355_clks,
+	.psc_bases		= dm355_psc_bases,
+	.psc_bases_num		= ARRAY_SIZE(dm355_psc_bases),
+	.pinmux_base		= IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE),
+	.pinmux_pins		= dm355_pins,
+	.pinmux_pins_num	= ARRAY_SIZE(dm355_pins),
+	.intc_base		= IO_ADDRESS(DAVINCI_ARM_INTC_BASE),
+	.intc_type		= DAVINCI_INTC_TYPE_AINTC,
+	.intc_irq_prios		= dm355_default_priorities,
+	.intc_irq_num		= DAVINCI_N_AINTC_IRQ,
+	.timer_info		= &dm355_timer_info,
+	.wdt_base		= IO_ADDRESS(DAVINCI_WDOG_BASE),
+	.gpio_base		= IO_ADDRESS(DAVINCI_GPIO_BASE),
+	.gpio_num		= 104,
+	.gpio_irq		= IRQ_DM355_GPIOBNK0,
+	.serial_dev		= &dm355_serial_device,
+	.sram_dma		= 0x00010000,
+	.sram_len		= SZ_32K,
+};
+
+void __init dm355_init(void)
+{
+	davinci_common_init(&davinci_soc_info_dm355);
+}
+
+static int __init dm355_init_devices(void)
+{
+	if (!cpu_is_davinci_dm355())
+		return 0;
+
+	davinci_cfg_reg(DM355_INT_EDMA_CC);
+	platform_device_register(&dm355_edma_device);
+	return 0;
+}
+postcore_initcall(dm355_init_devices);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/dm644x.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/dm644x.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/dm644x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/dm644x.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
+#include <linux/serial_8250.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/map.h>
 
 #include <mach/dm644x.h>
 #include <mach/clock.h>
@@ -20,6 +24,9 @@
 #include <mach/irqs.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
+#include <mach/time.h>
+#include <mach/serial.h>
+#include <mach/common.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -312,7 +319,14 @@
 	CLK(NULL, NULL, NULL),
 };
 
-#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE)
+static struct emac_platform_data dm644x_emac_pdata = {
+	.ctrl_reg_offset	= DM644X_EMAC_CNTRL_OFFSET,
+	.ctrl_mod_reg_offset	= DM644X_EMAC_CNTRL_MOD_OFFSET,
+	.ctrl_ram_offset	= DM644X_EMAC_CNTRL_RAM_OFFSET,
+	.mdio_reg_offset	= DM644X_EMAC_MDIO_OFFSET,
+	.ctrl_ram_size		= DM644X_EMAC_CNTRL_RAM_SIZE,
+	.version		= EMAC_VERSION_1,
+};
 
 static struct resource dm644x_emac_resources[] = {
 	{
@@ -330,11 +344,15 @@
 static struct platform_device dm644x_emac_device = {
        .name		= "davinci_emac",
        .id		= 1,
+       .dev = {
+	       .platform_data	= &dm644x_emac_pdata,
+       },
        .num_resources	= ARRAY_SIZE(dm644x_emac_resources),
        .resource	= dm644x_emac_resources,
 };
 
-#endif
+#define PINMUX0		0x00
+#define PINMUX1		0x04
 
 /*
  * Device specific mux setup
@@ -343,6 +361,7 @@
  *				reg  offset mask  mode
  */
 static const struct mux_config dm644x_pins[] = {
+#ifdef CONFIG_DAVINCI_MUX
 MUX_CFG(DM644X, HDIREN,		0,   16,    1,	  1,	 true)
 MUX_CFG(DM644X, ATAEN,		0,   17,    1,	  1,	 true)
 MUX_CFG(DM644X, ATAEN_DISABLE,	0,   17,    1,	  0,	 true)
@@ -383,8 +402,76 @@
 
 MUX_CFG(DM644X, LOEEN,		0,   24,    1,	  1,	 true)
 MUX_CFG(DM644X, LFLDEN,		0,   25,    1,	  1,	 false)
+#endif
 };
 
+/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
+static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+	[IRQ_VDINT0]		= 2,
+	[IRQ_VDINT1]		= 6,
+	[IRQ_VDINT2]		= 6,
+	[IRQ_HISTINT]		= 6,
+	[IRQ_H3AINT]		= 6,
+	[IRQ_PRVUINT]		= 6,
+	[IRQ_RSZINT]		= 6,
+	[7]			= 7,
+	[IRQ_VENCINT]		= 6,
+	[IRQ_ASQINT]		= 6,
+	[IRQ_IMXINT]		= 6,
+	[IRQ_VLCDINT]		= 6,
+	[IRQ_USBINT]		= 4,
+	[IRQ_EMACINT]		= 4,
+	[14]			= 7,
+	[15]			= 7,
+	[IRQ_CCINT0]		= 5,	/* dma */
+	[IRQ_CCERRINT]		= 5,	/* dma */
+	[IRQ_TCERRINT0]		= 5,	/* dma */
+	[IRQ_TCERRINT]		= 5,	/* dma */
+	[IRQ_PSCIN]		= 7,
+	[21]			= 7,
+	[IRQ_IDE]		= 4,
+	[23]			= 7,
+	[IRQ_MBXINT]		= 7,
+	[IRQ_MBRINT]		= 7,
+	[IRQ_MMCINT]		= 7,
+	[IRQ_SDIOINT]		= 7,
+	[28]			= 7,
+	[IRQ_DDRINT]		= 7,
+	[IRQ_AEMIFINT]		= 7,
+	[IRQ_VLQINT]		= 4,
+	[IRQ_TINT0_TINT12]	= 2,	/* clockevent */
+	[IRQ_TINT0_TINT34]	= 2,	/* clocksource */
+	[IRQ_TINT1_TINT12]	= 7,	/* DSP timer */
+	[IRQ_TINT1_TINT34]	= 7,	/* system tick */
+	[IRQ_PWMINT0]		= 7,
+	[IRQ_PWMINT1]		= 7,
+	[IRQ_PWMINT2]		= 7,
+	[IRQ_I2C]		= 3,
+	[IRQ_UARTINT0]		= 3,
+	[IRQ_UARTINT1]		= 3,
+	[IRQ_UARTINT2]		= 3,
+	[IRQ_SPINT0]		= 3,
+	[IRQ_SPINT1]		= 3,
+	[45]			= 7,
+	[IRQ_DSP2ARM0]		= 4,
+	[IRQ_DSP2ARM1]		= 4,
+	[IRQ_GPIO0]		= 7,
+	[IRQ_GPIO1]		= 7,
+	[IRQ_GPIO2]		= 7,
+	[IRQ_GPIO3]		= 7,
+	[IRQ_GPIO4]		= 7,
+	[IRQ_GPIO5]		= 7,
+	[IRQ_GPIO6]		= 7,
+	[IRQ_GPIO7]		= 7,
+	[IRQ_GPIOBNK0]		= 7,
+	[IRQ_GPIOBNK1]		= 7,
+	[IRQ_GPIOBNK2]		= 7,
+	[IRQ_GPIOBNK3]		= 7,
+	[IRQ_GPIOBNK4]		= 7,
+	[IRQ_COMMTX]		= 7,
+	[IRQ_COMMRX]		= 7,
+	[IRQ_EMUINT]		= 7,
+};
 
 /*----------------------------------------------------------------------*/
 
@@ -444,10 +531,118 @@
 };
 
 /*----------------------------------------------------------------------*/
+
+static struct map_desc dm644x_io_desc[] = {
+	{
+		.virtual	= IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= SRAM_VIRT,
+		.pfn		= __phys_to_pfn(0x00008000),
+		.length		= SZ_16K,
+		/* MT_MEMORY_NONCACHED requires supersection alignment */
+		.type		= MT_DEVICE,
+	},
+};
+
+/* Contents of JTAG ID register used to identify exact cpu type */
+static struct davinci_id dm644x_ids[] = {
+	{
+		.variant	= 0x0,
+		.part_no	= 0xb700,
+		.manufacturer	= 0x017,
+		.cpu_id		= DAVINCI_CPU_ID_DM6446,
+		.name		= "dm6446",
+	},
+};
+
+static void __iomem *dm644x_psc_bases[] = {
+	IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
+};
+
+/*
+ * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
+ * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
+ * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
+ * T1_TOP: Timer 1, top   :  <unused>
+ */
+struct davinci_timer_info dm644x_timer_info = {
+	.timers		= davinci_timer_instance,
+	.clockevent_id	= T0_BOT,
+	.clocksource_id	= T0_TOP,
+};
+
+static struct plat_serial8250_port dm644x_serial_platform_data[] = {
+	{
+		.mapbase	= DAVINCI_UART0_BASE,
+		.irq		= IRQ_UARTINT0,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	},
+	{
+		.mapbase	= DAVINCI_UART1_BASE,
+		.irq		= IRQ_UARTINT1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	},
+	{
+		.mapbase	= DAVINCI_UART2_BASE,
+		.irq		= IRQ_UARTINT2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+	},
+	{
+		.flags		= 0
+	},
+};
+
+static struct platform_device dm644x_serial_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= dm644x_serial_platform_data,
+	},
+};
+
+static struct davinci_soc_info davinci_soc_info_dm644x = {
+	.io_desc		= dm644x_io_desc,
+	.io_desc_num		= ARRAY_SIZE(dm644x_io_desc),
+	.jtag_id_base		= IO_ADDRESS(0x01c40028),
+	.ids			= dm644x_ids,
+	.ids_num		= ARRAY_SIZE(dm644x_ids),
+	.cpu_clks		= dm644x_clks,
+	.psc_bases		= dm644x_psc_bases,
+	.psc_bases_num		= ARRAY_SIZE(dm644x_psc_bases),
+	.pinmux_base		= IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE),
+	.pinmux_pins		= dm644x_pins,
+	.pinmux_pins_num	= ARRAY_SIZE(dm644x_pins),
+	.intc_base		= IO_ADDRESS(DAVINCI_ARM_INTC_BASE),
+	.intc_type		= DAVINCI_INTC_TYPE_AINTC,
+	.intc_irq_prios 	= dm644x_default_priorities,
+	.intc_irq_num		= DAVINCI_N_AINTC_IRQ,
+	.timer_info		= &dm644x_timer_info,
+	.wdt_base		= IO_ADDRESS(DAVINCI_WDOG_BASE),
+	.gpio_base		= IO_ADDRESS(DAVINCI_GPIO_BASE),
+	.gpio_num		= 71,
+	.gpio_irq		= IRQ_GPIOBNK0,
+	.serial_dev		= &dm644x_serial_device,
+	.emac_pdata		= &dm644x_emac_pdata,
+	.sram_dma		= 0x00008000,
+	.sram_len		= SZ_16K,
+};
+
 void __init dm644x_init(void)
 {
-	davinci_clk_init(dm644x_clks);
-	davinci_mux_register(dm644x_pins, ARRAY_SIZE(dm644x_pins));
+	davinci_common_init(&davinci_soc_info_dm644x);
 }
 
 static int __init dm644x_init_devices(void)
@@ -456,6 +651,7 @@
 		return 0;
 
 	platform_device_register(&dm644x_edma_device);
+	platform_device_register(&dm644x_emac_device);
 	return 0;
 }
 postcore_initcall(dm644x_init_devices);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/dm646x.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/dm646x.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/dm646x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/dm646x.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,636 @@
+/*
+ * TI DaVinci DM644x chip specific setup
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/serial_8250.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/dm646x.h>
+#include <mach/clock.h>
+#include <mach/cputype.h>
+#include <mach/edma.h>
+#include <mach/irqs.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+#include <mach/time.h>
+#include <mach/serial.h>
+#include <mach/common.h>
+
+#include "clock.h"
+#include "mux.h"
+
+/*
+ * Device specific clocks
+ */
+#define DM646X_REF_FREQ		27000000
+#define DM646X_AUX_FREQ		24000000
+
+static struct pll_data pll1_data = {
+	.num       = 1,
+	.phys_base = DAVINCI_PLL1_BASE,
+};
+
+static struct pll_data pll2_data = {
+	.num       = 2,
+	.phys_base = DAVINCI_PLL2_BASE,
+};
+
+static struct clk ref_clk = {
+	.name = "ref_clk",
+	.rate = DM646X_REF_FREQ,
+};
+
+static struct clk aux_clkin = {
+	.name = "aux_clkin",
+	.rate = DM646X_AUX_FREQ,
+};
+
+static struct clk pll1_clk = {
+	.name = "pll1",
+	.parent = &ref_clk,
+	.pll_data = &pll1_data,
+	.flags = CLK_PLL,
+};
+
+static struct clk pll1_sysclk1 = {
+	.name = "pll1_sysclk1",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV1,
+};
+
+static struct clk pll1_sysclk2 = {
+	.name = "pll1_sysclk2",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV2,
+};
+
+static struct clk pll1_sysclk3 = {
+	.name = "pll1_sysclk3",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV3,
+};
+
+static struct clk pll1_sysclk4 = {
+	.name = "pll1_sysclk4",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV4,
+};
+
+static struct clk pll1_sysclk5 = {
+	.name = "pll1_sysclk5",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV5,
+};
+
+static struct clk pll1_sysclk6 = {
+	.name = "pll1_sysclk6",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV6,
+};
+
+static struct clk pll1_sysclk8 = {
+	.name = "pll1_sysclk8",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV8,
+};
+
+static struct clk pll1_sysclk9 = {
+	.name = "pll1_sysclk9",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV9,
+};
+
+static struct clk pll1_sysclkbp = {
+	.name = "pll1_sysclkbp",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL | PRE_PLL,
+	.div_reg = BPDIV,
+};
+
+static struct clk pll1_aux_clk = {
+	.name = "pll1_aux_clk",
+	.parent = &pll1_clk,
+	.flags = CLK_PLL | PRE_PLL,
+};
+
+static struct clk pll2_clk = {
+	.name = "pll2_clk",
+	.parent = &ref_clk,
+	.pll_data = &pll2_data,
+	.flags = CLK_PLL,
+};
+
+static struct clk pll2_sysclk1 = {
+	.name = "pll2_sysclk1",
+	.parent = &pll2_clk,
+	.flags = CLK_PLL,
+	.div_reg = PLLDIV1,
+};
+
+static struct clk dsp_clk = {
+	.name = "dsp",
+	.parent = &pll1_sysclk1,
+	.lpsc = DM646X_LPSC_C64X_CPU,
+	.flags = PSC_DSP,
+	.usecount = 1,			/* REVISIT how to disable? */
+};
+
+static struct clk arm_clk = {
+	.name = "arm",
+	.parent = &pll1_sysclk2,
+	.lpsc = DM646X_LPSC_ARM,
+	.flags = ALWAYS_ENABLED,
+};
+
+static struct clk uart0_clk = {
+	.name = "uart0",
+	.parent = &aux_clkin,
+	.lpsc = DM646X_LPSC_UART0,
+};
+
+static struct clk uart1_clk = {
+	.name = "uart1",
+	.parent = &aux_clkin,
+	.lpsc = DM646X_LPSC_UART1,
+};
+
+static struct clk uart2_clk = {
+	.name = "uart2",
+	.parent = &aux_clkin,
+	.lpsc = DM646X_LPSC_UART2,
+};
+
+static struct clk i2c_clk = {
+	.name = "I2CCLK",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_I2C,
+};
+
+static struct clk gpio_clk = {
+	.name = "gpio",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_GPIO,
+};
+
+static struct clk aemif_clk = {
+	.name = "aemif",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_AEMIF,
+	.flags = ALWAYS_ENABLED,
+};
+
+static struct clk emac_clk = {
+	.name = "emac",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_EMAC,
+};
+
+static struct clk pwm0_clk = {
+	.name = "pwm0",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_PWM0,
+	.usecount = 1,            /* REVIST: disabling hangs system */
+};
+
+static struct clk pwm1_clk = {
+	.name = "pwm1",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_PWM1,
+	.usecount = 1,            /* REVIST: disabling hangs system */
+};
+
+static struct clk timer0_clk = {
+	.name = "timer0",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_TIMER0,
+};
+
+static struct clk timer1_clk = {
+	.name = "timer1",
+	.parent = &pll1_sysclk3,
+	.lpsc = DM646X_LPSC_TIMER1,
+};
+
+static struct clk timer2_clk = {
+	.name = "timer2",
+	.parent = &pll1_sysclk3,
+	.flags = ALWAYS_ENABLED, /* no LPSC, always enabled; c.f. spruep9a */
+};
+
+static struct clk vpif0_clk = {
+	.name = "vpif0",
+	.parent = &ref_clk,
+	.lpsc = DM646X_LPSC_VPSSMSTR,
+	.flags = ALWAYS_ENABLED,
+};
+
+static struct clk vpif1_clk = {
+	.name = "vpif1",
+	.parent = &ref_clk,
+	.lpsc = DM646X_LPSC_VPSSSLV,
+	.flags = ALWAYS_ENABLED,
+};
+
+struct davinci_clk dm646x_clks[] = {
+	CLK(NULL, "ref", &ref_clk),
+	CLK(NULL, "aux", &aux_clkin),
+	CLK(NULL, "pll1", &pll1_clk),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk1),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk2),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk3),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk4),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk5),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk6),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk8),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclk9),
+	CLK(NULL, "pll1_sysclk", &pll1_sysclkbp),
+	CLK(NULL, "pll1_aux", &pll1_aux_clk),
+	CLK(NULL, "pll2", &pll2_clk),
+	CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
+	CLK(NULL, "dsp", &dsp_clk),
+	CLK(NULL, "arm", &arm_clk),
+	CLK(NULL, "uart0", &uart0_clk),
+	CLK(NULL, "uart1", &uart1_clk),
+	CLK(NULL, "uart2", &uart2_clk),
+	CLK("i2c_davinci.1", NULL, &i2c_clk),
+	CLK(NULL, "gpio", &gpio_clk),
+	CLK(NULL, "aemif", &aemif_clk),
+	CLK("davinci_emac.1", NULL, &emac_clk),
+	CLK(NULL, "pwm0", &pwm0_clk),
+	CLK(NULL, "pwm1", &pwm1_clk),
+	CLK(NULL, "timer0", &timer0_clk),
+	CLK(NULL, "timer1", &timer1_clk),
+	CLK("watchdog", NULL, &timer2_clk),
+	CLK(NULL, "vpif0", &vpif0_clk),
+	CLK(NULL, "vpif1", &vpif1_clk),
+	CLK(NULL, NULL, NULL),
+};
+
+static struct emac_platform_data dm646x_emac_pdata = {
+	.ctrl_reg_offset	= DM646X_EMAC_CNTRL_OFFSET,
+	.ctrl_mod_reg_offset	= DM646X_EMAC_CNTRL_MOD_OFFSET,
+	.ctrl_ram_offset	= DM646X_EMAC_CNTRL_RAM_OFFSET,
+	.mdio_reg_offset	= DM646X_EMAC_MDIO_OFFSET,
+	.ctrl_ram_size		= DM646X_EMAC_CNTRL_RAM_SIZE,
+	.version		= EMAC_VERSION_2,
+};
+
+static struct resource dm646x_emac_resources[] = {
+	{
+		.start	= DM646X_EMAC_BASE,
+		.end	= DM646X_EMAC_BASE + 0x47ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_DM646X_EMACRXTHINT,
+		.end	= IRQ_DM646X_EMACRXTHINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DM646X_EMACRXINT,
+		.end	= IRQ_DM646X_EMACRXINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DM646X_EMACTXINT,
+		.end	= IRQ_DM646X_EMACTXINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_DM646X_EMACMISCINT,
+		.end	= IRQ_DM646X_EMACMISCINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device dm646x_emac_device = {
+	.name		= "davinci_emac",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &dm646x_emac_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(dm646x_emac_resources),
+	.resource	= dm646x_emac_resources,
+};
+
+#define PINMUX0		0x00
+#define PINMUX1		0x04
+
+/*
+ * Device specific mux setup
+ *
+ *	soc	description	mux  mode   mode  mux	 dbg
+ *				reg  offset mask  mode
+ */
+static const struct mux_config dm646x_pins[] = {
+#ifdef CONFIG_DAVINCI_MUX
+MUX_CFG(DM646X, ATAEN,		0,   0,     1,	  1,	 true)
+
+MUX_CFG(DM646X, AUDCK1,		0,   29,    1,	  0,	 false)
+
+MUX_CFG(DM646X, AUDCK0,		0,   28,    1,	  0,	 false)
+
+MUX_CFG(DM646X, CRGMUX,			0,   24,    7,    5,	 true)
+
+MUX_CFG(DM646X, STSOMUX_DISABLE,	0,   22,    3,    0,	 true)
+
+MUX_CFG(DM646X, STSIMUX_DISABLE,	0,   20,    3,    0,	 true)
+
+MUX_CFG(DM646X, PTSOMUX_DISABLE,	0,   18,    3,    0,	 true)
+
+MUX_CFG(DM646X, PTSIMUX_DISABLE,	0,   16,    3,    0,	 true)
+
+MUX_CFG(DM646X, STSOMUX,		0,   22,    3,    2,	 true)
+
+MUX_CFG(DM646X, STSIMUX,		0,   20,    3,    2,	 true)
+
+MUX_CFG(DM646X, PTSOMUX_PARALLEL,	0,   18,    3,    2,	 true)
+
+MUX_CFG(DM646X, PTSIMUX_PARALLEL,	0,   16,    3,    2,	 true)
+
+MUX_CFG(DM646X, PTSOMUX_SERIAL,		0,   18,    3,    3,	 true)
+
+MUX_CFG(DM646X, PTSIMUX_SERIAL,		0,   16,    3,    3,	 true)
+#endif
+};
+
+static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+	[IRQ_DM646X_VP_VERTINT0]        = 7,
+	[IRQ_DM646X_VP_VERTINT1]        = 7,
+	[IRQ_DM646X_VP_VERTINT2]        = 7,
+	[IRQ_DM646X_VP_VERTINT3]        = 7,
+	[IRQ_DM646X_VP_ERRINT]          = 7,
+	[IRQ_DM646X_RESERVED_1]         = 7,
+	[IRQ_DM646X_RESERVED_2]         = 7,
+	[IRQ_DM646X_WDINT]              = 7,
+	[IRQ_DM646X_CRGENINT0]          = 7,
+	[IRQ_DM646X_CRGENINT1]          = 7,
+	[IRQ_DM646X_TSIFINT0]           = 7,
+	[IRQ_DM646X_TSIFINT1]           = 7,
+	[IRQ_DM646X_VDCEINT]            = 7,
+	[IRQ_DM646X_USBINT]             = 7,
+	[IRQ_DM646X_USBDMAINT]          = 7,
+	[IRQ_DM646X_PCIINT]             = 7,
+	[IRQ_CCINT0]                    = 7,    /* dma */
+	[IRQ_CCERRINT]                  = 7,    /* dma */
+	[IRQ_TCERRINT0]                 = 7,    /* dma */
+	[IRQ_TCERRINT]                  = 7,    /* dma */
+	[IRQ_DM646X_TCERRINT2]          = 7,
+	[IRQ_DM646X_TCERRINT3]          = 7,
+	[IRQ_DM646X_IDE]                = 7,
+	[IRQ_DM646X_HPIINT]             = 7,
+	[IRQ_DM646X_EMACRXTHINT]        = 7,
+	[IRQ_DM646X_EMACRXINT]          = 7,
+	[IRQ_DM646X_EMACTXINT]          = 7,
+	[IRQ_DM646X_EMACMISCINT]        = 7,
+	[IRQ_DM646X_MCASP0TXINT]        = 7,
+	[IRQ_DM646X_MCASP0RXINT]        = 7,
+	[IRQ_AEMIFINT]                  = 7,
+	[IRQ_DM646X_RESERVED_3]         = 7,
+	[IRQ_DM646X_MCASP1TXINT]        = 7,    /* clockevent */
+	[IRQ_TINT0_TINT34]              = 7,    /* clocksource */
+	[IRQ_TINT1_TINT12]              = 7,    /* DSP timer */
+	[IRQ_TINT1_TINT34]              = 7,    /* system tick */
+	[IRQ_PWMINT0]                   = 7,
+	[IRQ_PWMINT1]                   = 7,
+	[IRQ_DM646X_VLQINT]             = 7,
+	[IRQ_I2C]                       = 7,
+	[IRQ_UARTINT0]                  = 7,
+	[IRQ_UARTINT1]                  = 7,
+	[IRQ_DM646X_UARTINT2]           = 7,
+	[IRQ_DM646X_SPINT0]             = 7,
+	[IRQ_DM646X_SPINT1]             = 7,
+	[IRQ_DM646X_DSP2ARMINT]         = 7,
+	[IRQ_DM646X_RESERVED_4]         = 7,
+	[IRQ_DM646X_PSCINT]             = 7,
+	[IRQ_DM646X_GPIO0]              = 7,
+	[IRQ_DM646X_GPIO1]              = 7,
+	[IRQ_DM646X_GPIO2]              = 7,
+	[IRQ_DM646X_GPIO3]              = 7,
+	[IRQ_DM646X_GPIO4]              = 7,
+	[IRQ_DM646X_GPIO5]              = 7,
+	[IRQ_DM646X_GPIO6]              = 7,
+	[IRQ_DM646X_GPIO7]              = 7,
+	[IRQ_DM646X_GPIOBNK0]           = 7,
+	[IRQ_DM646X_GPIOBNK1]           = 7,
+	[IRQ_DM646X_GPIOBNK2]           = 7,
+	[IRQ_DM646X_DDRINT]             = 7,
+	[IRQ_DM646X_AEMIFINT]           = 7,
+	[IRQ_COMMTX]                    = 7,
+	[IRQ_COMMRX]                    = 7,
+	[IRQ_EMUINT]                    = 7,
+};
+
+/*----------------------------------------------------------------------*/
+
+static const s8 dma_chan_dm646x_no_event[] = {
+	 0,  1,  2,  3, 13,
+	14, 15, 24, 25, 26,
+	27, 30, 31, 54, 55,
+	56,
+	-1
+};
+
+static struct edma_soc_info dm646x_edma_info = {
+	.n_channel	= 64,
+	.n_region	= 6,	/* 0-1, 4-7 */
+	.n_slot		= 512,
+	.n_tc		= 4,
+	.noevent	= dma_chan_dm646x_no_event,
+};
+
+static struct resource edma_resources[] = {
+	{
+		.name	= "edma_cc",
+		.start	= 0x01c00000,
+		.end	= 0x01c00000 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc0",
+		.start	= 0x01c10000,
+		.end	= 0x01c10000 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc1",
+		.start	= 0x01c10400,
+		.end	= 0x01c10400 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc2",
+		.start	= 0x01c10800,
+		.end	= 0x01c10800 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc3",
+		.start	= 0x01c10c00,
+		.end	= 0x01c10c00 + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_CCINT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= IRQ_CCERRINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	/* not using TC*_ERR */
+};
+
+static struct platform_device dm646x_edma_device = {
+	.name			= "edma",
+	.id			= -1,
+	.dev.platform_data	= &dm646x_edma_info,
+	.num_resources		= ARRAY_SIZE(edma_resources),
+	.resource		= edma_resources,
+};
+
+/*----------------------------------------------------------------------*/
+
+static struct map_desc dm646x_io_desc[] = {
+	{
+		.virtual	= IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= SRAM_VIRT,
+		.pfn		= __phys_to_pfn(0x00010000),
+		.length		= SZ_32K,
+		/* MT_MEMORY_NONCACHED requires supersection alignment */
+		.type		= MT_DEVICE,
+	},
+};
+
+/* Contents of JTAG ID register used to identify exact cpu type */
+static struct davinci_id dm646x_ids[] = {
+	{
+		.variant	= 0x0,
+		.part_no	= 0xb770,
+		.manufacturer	= 0x017,
+		.cpu_id		= DAVINCI_CPU_ID_DM6467,
+		.name		= "dm6467",
+	},
+};
+
+static void __iomem *dm646x_psc_bases[] = {
+	IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
+};
+
+/*
+ * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
+ * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
+ * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
+ * T1_TOP: Timer 1, top   :  <unused>
+ */
+struct davinci_timer_info dm646x_timer_info = {
+	.timers		= davinci_timer_instance,
+	.clockevent_id	= T0_BOT,
+	.clocksource_id	= T0_TOP,
+};
+
+static struct plat_serial8250_port dm646x_serial_platform_data[] = {
+	{
+		.mapbase	= DAVINCI_UART0_BASE,
+		.irq		= IRQ_UARTINT0,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+	},
+	{
+		.mapbase	= DAVINCI_UART1_BASE,
+		.irq		= IRQ_UARTINT1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+	},
+	{
+		.mapbase	= DAVINCI_UART2_BASE,
+		.irq		= IRQ_DM646X_UARTINT2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_IOREMAP,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+	},
+	{
+		.flags		= 0
+	},
+};
+
+static struct platform_device dm646x_serial_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= dm646x_serial_platform_data,
+	},
+};
+
+static struct davinci_soc_info davinci_soc_info_dm646x = {
+	.io_desc		= dm646x_io_desc,
+	.io_desc_num		= ARRAY_SIZE(dm646x_io_desc),
+	.jtag_id_base		= IO_ADDRESS(0x01c40028),
+	.ids			= dm646x_ids,
+	.ids_num		= ARRAY_SIZE(dm646x_ids),
+	.cpu_clks		= dm646x_clks,
+	.psc_bases		= dm646x_psc_bases,
+	.psc_bases_num		= ARRAY_SIZE(dm646x_psc_bases),
+	.pinmux_base		= IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE),
+	.pinmux_pins		= dm646x_pins,
+	.pinmux_pins_num	= ARRAY_SIZE(dm646x_pins),
+	.intc_base		= IO_ADDRESS(DAVINCI_ARM_INTC_BASE),
+	.intc_type		= DAVINCI_INTC_TYPE_AINTC,
+	.intc_irq_prios		= dm646x_default_priorities,
+	.intc_irq_num		= DAVINCI_N_AINTC_IRQ,
+	.timer_info		= &dm646x_timer_info,
+	.wdt_base		= IO_ADDRESS(DAVINCI_WDOG_BASE),
+	.gpio_base		= IO_ADDRESS(DAVINCI_GPIO_BASE),
+	.gpio_num		= 43, /* Only 33 usable */
+	.gpio_irq		= IRQ_DM646X_GPIOBNK0,
+	.serial_dev		= &dm646x_serial_device,
+	.emac_pdata		= &dm646x_emac_pdata,
+	.sram_dma		= 0x10010000,
+	.sram_len		= SZ_32K,
+};
+
+void __init dm646x_init(void)
+{
+	davinci_common_init(&davinci_soc_info_dm646x);
+}
+
+static int __init dm646x_init_devices(void)
+{
+	if (!cpu_is_davinci_dm646x())
+		return 0;
+
+	platform_device_register(&dm646x_edma_device);
+	platform_device_register(&dm646x_emac_device);
+	return 0;
+}
+postcore_initcall(dm646x_init_devices);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/gpio.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,7 @@
 #include <mach/cputype.h>
 #include <mach/irqs.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
 #include <mach/gpio.h>
 
 #include <asm/mach/irq.h>
@@ -37,14 +38,13 @@
 
 static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
 
-static unsigned __initdata ngpio;
-
 /* create a non-inlined version */
 static struct gpio_controller __iomem * __init gpio2controller(unsigned gpio)
 {
 	return __gpio_to_controller(gpio);
 }
 
+static int __init davinci_gpio_irq_setup(void);
 
 /*--------------------------------------------------------------------------*/
 
@@ -115,23 +115,16 @@
 static int __init davinci_gpio_setup(void)
 {
 	int i, base;
+	unsigned ngpio;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
-	/* The gpio banks conceptually expose a segmented bitmap,
+	/*
+	 * The gpio banks conceptually expose a segmented bitmap,
 	 * and "ngpio" is one more than the largest zero-based
 	 * bit index that's valid.
 	 */
-	if (cpu_is_davinci_dm355()) {		/* or dm335() */
-		ngpio = 104;
-	} else if (cpu_is_davinci_dm644x()) {	/* or dm337() */
-		ngpio = 71;
-	} else if (cpu_is_davinci_dm646x()) {
-		/* NOTE:  each bank has several "reserved" bits,
-		 * unusable as GPIOs.  Only 33 of the GPIO numbers
-		 * are usable, and we're not rejecting the others.
-		 */
-		ngpio = 43;
-	} else {
-		/* if cpu_is_davinci_dm643x() ngpio = 111 */
+	ngpio = soc_info->gpio_num;
+	if (ngpio == 0) {
 		pr_err("GPIO setup:  how many GPIOs?\n");
 		return -EINVAL;
 	}
@@ -157,6 +150,7 @@
 		gpiochip_add(&chips[i].chip);
 	}
 
+	davinci_gpio_irq_setup();
 	return 0;
 }
 pure_initcall(davinci_gpio_setup);
@@ -187,10 +181,15 @@
 {
 	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
 	u32 mask = __gpio_mask(irq_to_gpio(irq));
+	unsigned status = irq_desc[irq].status;
 
-	if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
+	status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+	if (!status)
+		status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+
+	if (status & IRQ_TYPE_EDGE_FALLING)
 		__raw_writel(mask, &g->set_falling);
-	if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
+	if (status & IRQ_TYPE_EDGE_RISING)
 		__raw_writel(mask, &g->set_rising);
 }
 
@@ -205,10 +204,13 @@
 	irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
 	irq_desc[irq].status |= trigger;
 
-	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
-		     ? &g->set_falling : &g->clr_falling);
-	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
-		     ? &g->set_rising : &g->clr_rising);
+	/* don't enable the IRQ if it's currently disabled */
+	if (irq_desc[irq].depth == 0) {
+		__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+			     ? &g->set_falling : &g->clr_falling);
+		__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
+			     ? &g->set_rising : &g->clr_rising);
+	}
 	return 0;
 }
 
@@ -230,6 +232,7 @@
 		mask <<= 16;
 
 	/* temporarily mask (level sensitive) parent IRQ */
+	desc->chip->mask(irq);
 	desc->chip->ack(irq);
 	while (1) {
 		u32		status;
@@ -268,17 +271,15 @@
 static int __init davinci_gpio_irq_setup(void)
 {
 	unsigned	gpio, irq, bank;
-	unsigned	bank_irq;
 	struct clk	*clk;
 	u32		binten = 0;
+	unsigned	ngpio, bank_irq;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
-	if (cpu_is_davinci_dm355()) {		/* or dm335() */
-		bank_irq = IRQ_DM355_GPIOBNK0;
-	} else if (cpu_is_davinci_dm644x()) {
-		bank_irq = IRQ_GPIOBNK0;
-	} else if (cpu_is_davinci_dm646x()) {
-		bank_irq = IRQ_DM646X_GPIOBNK0;
-	} else {
+	ngpio = soc_info->gpio_num;
+
+	bank_irq = soc_info->gpio_irq;
+	if (bank_irq == 0) {
 		printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
 		return -EINVAL;
 	}
@@ -318,11 +319,9 @@
 	/* BINTEN -- per-bank interrupt enable. genirq would also let these
 	 * bits be set/cleared dynamically.
 	 */
-	__raw_writel(binten, (void *__iomem)
-		     IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
+	__raw_writel(binten, soc_info->gpio_base + 0x08);
 
 	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
 
 	return 0;
 }
-arch_initcall(davinci_gpio_irq_setup);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/id.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/id.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/id.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/id.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,116 +0,0 @@
-/*
- * Davinci CPU identification code
- *
- * Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.com>
- *
- * Derived from OMAP1 CPU identification code.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#define JTAG_ID_BASE		IO_ADDRESS(0x01c40028)
-
-static unsigned int davinci_revision;
-
-struct davinci_id {
-	u8	variant;	/* JTAG ID bits 31:28 */
-	u16	part_no;	/* JTAG ID bits 27:12 */
-	u32	manufacturer;	/* JTAG ID bits 11:1 */
-	u32	type;		/* Cpu id bits [31:8], cpu class bits [7:0] */
-};
-
-/* Register values to detect the DaVinci version */
-static struct davinci_id davinci_ids[] __initdata = {
-	{
-		/* DM6446 */
-		.part_no      = 0xb700,
-		.variant      = 0x0,
-		.manufacturer = 0x017,
-		.type	      = 0x64460000,
-	},
-	{
-		/* DM646X */
-		.part_no      = 0xb770,
-		.variant      = 0x0,
-		.manufacturer = 0x017,
-		.type         = 0x64670000,
-	},
-	{
-		/* DM355 */
-		.part_no	= 0xb73b,
-		.variant	= 0x0,
-		.manufacturer	= 0x00f,
-		.type		= 0x03550000,
-	},
-};
-
-/*
- * Get Device Part No. from JTAG ID register
- */
-static u16 __init davinci_get_part_no(void)
-{
-	u32 dev_id, part_no;
-
-	dev_id = __raw_readl(JTAG_ID_BASE);
-
-	part_no = ((dev_id >> 12) & 0xffff);
-
-	return part_no;
-}
-
-/*
- * Get Device Revision from JTAG ID register
- */
-static u8 __init davinci_get_variant(void)
-{
-	u32 variant;
-
-	variant = __raw_readl(JTAG_ID_BASE);
-
-	variant = (variant >> 28) & 0xf;
-
-	return variant;
-}
-
-unsigned int davinci_rev(void)
-{
-	return davinci_revision >> 16;
-}
-EXPORT_SYMBOL(davinci_rev);
-
-void __init davinci_check_revision(void)
-{
-	int i;
-	u16 part_no;
-	u8 variant;
-
-	part_no = davinci_get_part_no();
-	variant = davinci_get_variant();
-
-	/* First check only the major version in a safe way */
-	for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
-		if (part_no == (davinci_ids[i].part_no)) {
-			davinci_revision = davinci_ids[i].type;
-			break;
-		}
-	}
-
-	/* Check if we can find the dev revision */
-	for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
-		if (part_no == davinci_ids[i].part_no &&
-		    variant == davinci_ids[i].variant) {
-			davinci_revision = davinci_ids[i].type;
-			break;
-		}
-	}
-
-	printk(KERN_INFO "DaVinci DM%04x variant 0x%x\n",
-	       davinci_rev(), variant);
-}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/board-dm6446evm.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/board-dm6446evm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/board-dm6446evm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/board-dm6446evm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * DaVinci DM6446 EVM board specific headers
- *
- * Author: Kevin Hilman, Deep Root Systems, LLC
- *
- * 2007 (c) Deep Root Systems, LLC. 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 ifndef.
- */
-
-#ifndef _MACH_DAVINCI_DM6446EVM_H
-#define _MACH_DAVINCI_DM6446EVM_H
-
-#include <linux/types.h>
-
-int dm6446evm_eeprom_read(char *buf, off_t off, size_t count);
-int dm6446evm_eeprom_write(char *buf, off_t off, size_t count);
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/common.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/common.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/common.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,8 @@
 extern struct sys_timer davinci_timer;
 
 extern void davinci_irq_init(void);
-extern void davinci_map_common_io(void);
+extern void __iomem *davinci_intc_base;
+extern int davinci_intc_type;
 
 /* parameters describe VBUS sourcing for host mode */
 extern void setup_usb(unsigned mA, unsigned potpgt_msec);
@@ -25,4 +26,56 @@
 /* parameters describe VBUS sourcing for host mode */
 extern void setup_usb(unsigned mA, unsigned potpgt_msec);
 
+struct davinci_timer_instance {
+	void __iomem	*base;
+	u32		bottom_irq;
+	u32		top_irq;
+	unsigned long	cmp_off;
+	unsigned int	cmp_irq;
+};
+
+struct davinci_timer_info {
+	struct davinci_timer_instance	*timers;
+	unsigned int			clockevent_id;
+	unsigned int			clocksource_id;
+};
+
+/* SoC specific init support */
+struct davinci_soc_info {
+	struct map_desc			*io_desc;
+	unsigned long			io_desc_num;
+	u32				cpu_id;
+	u32				jtag_id;
+	void __iomem			*jtag_id_base;
+	struct davinci_id		*ids;
+	unsigned long			ids_num;
+	struct davinci_clk		*cpu_clks;
+	void __iomem			**psc_bases;
+	unsigned long			psc_bases_num;
+	void __iomem			*pinmux_base;
+	const struct mux_config		*pinmux_pins;
+	unsigned long			pinmux_pins_num;
+	void __iomem			*intc_base;
+	int				intc_type;
+	u8				*intc_irq_prios;
+	unsigned long			intc_irq_num;
+	struct davinci_timer_info	*timer_info;
+	void __iomem			*wdt_base;
+	void __iomem			*gpio_base;
+	unsigned			gpio_num;
+	unsigned			gpio_irq;
+	struct platform_device		*serial_dev;
+	struct emac_platform_data	*emac_pdata;
+	dma_addr_t			sram_dma;
+	unsigned			sram_len;
+};
+
+extern struct davinci_soc_info davinci_soc_info;
+
+extern void davinci_common_init(struct davinci_soc_info *soc_info);
+
+/* standard place to map on-chip SRAMs; they *may* support DMA */
+#define SRAM_VIRT	0xfffe0000
+#define SRAM_SIZE	SZ_128K
+
 #endif /* __ARCH_ARM_MACH_DAVINCI_COMMON_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/cp_intc.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/cp_intc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/cp_intc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/cp_intc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * TI Common Platform Interrupt Controller (cp_intc) definitions
+ *
+ * Author: Steve Chen <schen@mvista.com>
+ * Copyright (C) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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.
+ */
+#ifndef __ASM_HARDWARE_CP_INTC_H
+#define __ASM_HARDWARE_CP_INTC_H
+
+#define CP_INTC_REV			0x00
+#define CP_INTC_CTRL			0x04
+#define CP_INTC_HOST_CTRL		0x0C
+#define CP_INTC_GLOBAL_ENABLE		0x10
+#define CP_INTC_GLOBAL_NESTING_LEVEL	0x1C
+#define CP_INTC_SYS_STAT_IDX_SET	0x20
+#define CP_INTC_SYS_STAT_IDX_CLR	0x24
+#define CP_INTC_SYS_ENABLE_IDX_SET	0x28
+#define CP_INTC_SYS_ENABLE_IDX_CLR	0x2C
+#define CP_INTC_GLOBAL_WAKEUP_ENABLE	0x30
+#define CP_INTC_HOST_ENABLE_IDX_SET	0x34
+#define CP_INTC_HOST_ENABLE_IDX_CLR	0x38
+#define CP_INTC_PACING_PRESCALE 	0x40
+#define CP_INTC_VECTOR_BASE		0x50
+#define CP_INTC_VECTOR_SIZE		0x54
+#define CP_INTC_VECTOR_NULL		0x58
+#define CP_INTC_PRIO_IDX		0x80
+#define CP_INTC_PRIO_VECTOR		0x84
+#define CP_INTC_SECURE_ENABLE		0x90
+#define CP_INTC_SECURE_PRIO_IDX 	0x94
+#define CP_INTC_PACING_PARAM(n) 	(0x0100 + (n << 4))
+#define CP_INTC_PACING_DEC(n)		(0x0104 + (n << 4))
+#define CP_INTC_PACING_MAP(n)		(0x0108 + (n << 4))
+#define CP_INTC_SYS_RAW_STAT(n) 	(0x0200 + (n << 2))
+#define CP_INTC_SYS_STAT_CLR(n) 	(0x0280 + (n << 2))
+#define CP_INTC_SYS_ENABLE_SET(n)	(0x0300 + (n << 2))
+#define CP_INTC_SYS_ENABLE_CLR(n)	(0x0380 + (n << 2))
+#define CP_INTC_CHAN_MAP(n)		(0x0400 + (n << 2))
+#define CP_INTC_HOST_MAP(n)		(0x0800 + (n << 2))
+#define CP_INTC_HOST_PRIO_IDX(n)	(0x0900 + (n << 2))
+#define CP_INTC_SYS_POLARITY(n) 	(0x0D00 + (n << 2))
+#define CP_INTC_SYS_TYPE(n)		(0x0D80 + (n << 2))
+#define CP_INTC_WAKEUP_ENABLE(n)	(0x0E00 + (n << 2))
+#define CP_INTC_DEBUG_SELECT(n) 	(0x0F00 + (n << 2))
+#define CP_INTC_SYS_SECURE_ENABLE(n)	(0x1000 + (n << 2))
+#define CP_INTC_HOST_NESTING_LEVEL(n)	(0x1100 + (n << 2))
+#define CP_INTC_HOST_ENABLE(n)		(0x1500 + (n << 2))
+#define CP_INTC_HOST_PRIO_VECTOR(n)	(0x1600 + (n << 2))
+#define CP_INTC_VECTOR_ADDR(n)		(0x2000 + (n << 2))
+
+void __init cp_intc_init(void __iomem *base, unsigned short num_irq,
+			 u8 *irq_prio);
+
+#endif	/* __ASM_HARDWARE_CP_INTC_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/cputype.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/cputype.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/cputype.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/cputype.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,17 +16,30 @@
 #ifndef _ASM_ARCH_CPU_H
 #define _ASM_ARCH_CPU_H
 
-extern unsigned int davinci_rev(void);
+#include <mach/common.h>
 
-#define IS_DAVINCI_CPU(type, id)			\
-static inline int is_davinci_dm ##type(void)	        \
-{							\
-	return (davinci_rev() == (id)) ? 1 : 0;	        \
+struct davinci_id {
+	u8	variant;	/* JTAG ID bits 31:28 */
+	u16	part_no;	/* JTAG ID bits 27:12 */
+	u16	manufacturer;	/* JTAG ID bits 11:1 */
+	u32	cpu_id;
+	char	*name;
+};
+
+/* Can use lower 16 bits of cpu id  for a variant when required */
+#define	DAVINCI_CPU_ID_DM6446		0x64460000
+#define	DAVINCI_CPU_ID_DM6467		0x64670000
+#define	DAVINCI_CPU_ID_DM355		0x03550000
+
+#define IS_DAVINCI_CPU(type, id)					\
+static inline int is_davinci_ ##type(void)				\
+{									\
+	return (davinci_soc_info.cpu_id == (id));			\
 }
 
-IS_DAVINCI_CPU(644x, 0x6446)
-IS_DAVINCI_CPU(646x, 0x6467)
-IS_DAVINCI_CPU(355, 0x355)
+IS_DAVINCI_CPU(dm644x, DAVINCI_CPU_ID_DM6446)
+IS_DAVINCI_CPU(dm646x, DAVINCI_CPU_ID_DM6467)
+IS_DAVINCI_CPU(dm355, DAVINCI_CPU_ID_DM355)
 
 #ifdef CONFIG_ARCH_DAVINCI_DM644x
 #define cpu_is_davinci_dm644x() is_davinci_dm644x()
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,16 @@
  * or implied.
  */
 
+/* Modifications
+ * Jan 2009	Chaithrika U S	Added senduart, busyuart, waituart
+ *				macros, based on debug-8250.S file
+ *				but using 32-bit accesses required for
+ *                              some davinci devices.
+ */
+
+#include <linux/serial_reg.h>
+#define UART_SHIFT	2
+
 		.macro addruart, rx
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
@@ -17,5 +27,22 @@
 		orr	\rx, \rx, #0x00c20000   @ UART 0
 		.endm
 
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_TX << UART_SHIFT]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
+		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
+		bne	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+#ifdef FLOW_CONTROL
+1001:		ldr	\rd, [\rx, #UART_MSR << UART_SHIFT]
+		tst	\rd, #UART_MSR_CTS
+		beq	1001b
+#endif
+		.endm
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/dm355.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/dm355.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/dm355.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/dm355.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Chip specific defines for DM355 SoC
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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.
+ */
+#ifndef __ASM_ARCH_DM355_H
+#define __ASM_ARCH_DM355_H
+
+#include <mach/hardware.h>
+
+struct spi_board_info;
+
+void __init dm355_init(void);
+void dm355_init_spi0(unsigned chipselect_mask,
+		struct spi_board_info *info, unsigned len);
+
+#endif /* __ASM_ARCH_DM355_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/dm644x.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/dm644x.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/dm644x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/dm644x.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 
 #include <linux/platform_device.h>
 #include <mach/hardware.h>
+#include <mach/emac.h>
 
 #define DM644X_EMAC_BASE		(0x01C80000)
 #define DM644X_EMAC_CNTRL_OFFSET	(0x0000)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/dm646x.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/dm646x.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/dm646x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/dm646x.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * Chip specific defines for DM646x SoC
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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.
+ */
+#ifndef __ASM_ARCH_DM646X_H
+#define __ASM_ARCH_DM646X_H
+
+#include <mach/hardware.h>
+#include <mach/emac.h>
+
+#define DM646X_EMAC_BASE		(0x01C80000)
+#define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
+#define DM646X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
+#define DM646X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
+#define DM646X_EMAC_MDIO_OFFSET		(0x4000)
+#define DM646X_EMAC_CNTRL_RAM_SIZE	(0x2000)
+
+void __init dm646x_init(void);
+
+#endif /* __ASM_ARCH_DM646X_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/edma.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/edma.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/edma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/edma.h	2009-09-09 18:13:59.000000000 -0400
@@ -208,10 +208,6 @@
 void edma_pause(unsigned channel);
 void edma_resume(unsigned channel);
 
-/* UNRELATED TO DMA */
-int davinci_alloc_iram(unsigned size);
-void davinci_free_iram(unsigned addr, unsigned size);
-
 /* platform_data for EDMA driver */
 struct edma_soc_info {
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/emac.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/emac.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/emac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/emac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * TI DaVinci EMAC platform support
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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.
+ */
+#ifndef _MACH_DAVINCI_EMAC_H
+#define _MACH_DAVINCI_EMAC_H
+
+#include <linux/if_ether.h>
+#include <linux/memory.h>
+
+struct emac_platform_data {
+	char mac_addr[ETH_ALEN];
+	u32 ctrl_reg_offset;
+	u32 ctrl_mod_reg_offset;
+	u32 ctrl_ram_offset;
+	u32 mdio_reg_offset;
+	u32 ctrl_ram_size;
+	u32 phy_mask;
+	u32 mdio_max_freq;
+	u8 rmii_en;
+	u8 version;
+};
+
+enum {
+	EMAC_VERSION_1,	/* DM644x */
+	EMAC_VERSION_2,	/* DM646x */
+};
+
+void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context);
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/entry-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/entry-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/entry-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/entry-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -15,17 +15,36 @@
 		.endm
 
 		.macro  get_irqnr_preamble, base, tmp
-		ldr \base, =IO_ADDRESS(DAVINCI_ARM_INTC_BASE)
+		ldr \base, =davinci_intc_base
+		ldr \base, [\base]
 		.endm
 
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
 
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+#if defined(CONFIG_AINTC) && defined(CONFIG_CP_INTC)
+		ldr \tmp, =davinci_intc_type
+		ldr \tmp, [\tmp]
+		cmp \tmp, #DAVINCI_INTC_TYPE_CP_INTC
+		beq 1001f
+#endif
+#if defined(CONFIG_AINTC)
 		ldr \tmp, [\base, #0x14]
-		mov \tmp, \tmp, lsr #2
+		movs \tmp, \tmp, lsr #2
 		sub \irqnr, \tmp, #1
-		cmp \tmp, #0
+		b 1002f
+#endif
+#if defined(CONFIG_CP_INTC)
+1001:		ldr \irqnr, [\base, #0x80] /* get irq number */
+		and \irqnr, \irqnr, #0xff  /* irq is in bits 0-9 */
+		mov \tmp, \irqnr, lsr #3
+		and \tmp, \tmp, #0xfc
+		add \tmp, \tmp, #0x280 /* get the register offset */
+		ldr \irqstat, [\base, \tmp] /* get the intc status */
+		cmp \irqstat, #0x0
+#endif
+1002:
 		.endm
 
 		.macro	irq_prio_table
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/gpio.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <asm-generic/gpio.h>
 
 #include <mach/irqs.h>
+#include <mach/common.h>
 
 #define DAVINCI_GPIO_BASE 0x01C67000
 
@@ -67,15 +68,16 @@
 __gpio_to_controller(unsigned gpio)
 {
 	void *__iomem ptr;
+	void __iomem *base = davinci_soc_info.gpio_base;
 
 	if (gpio < 32 * 1)
-		ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+		ptr = base + 0x10;
 	else if (gpio < 32 * 2)
-		ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+		ptr = base + 0x38;
 	else if (gpio < 32 * 3)
-		ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+		ptr = base + 0x60;
 	else if (gpio < 32 * 4)
-		ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);
+		ptr = base + 0x88;
 	else
 		ptr = NULL;
 	return ptr;
@@ -142,13 +144,13 @@
 {
 	if (gpio >= DAVINCI_N_GPIO)
 		return -EINVAL;
-	return DAVINCI_N_AINTC_IRQ + gpio;
+	return davinci_soc_info.intc_irq_num + gpio;
 }
 
 static inline int irq_to_gpio(unsigned irq)
 {
 	/* caller guarantees gpio_to_irq() succeeded */
-	return irq - DAVINCI_N_AINTC_IRQ;
+	return irq - davinci_soc_info.intc_irq_num;
 }
 
 #endif				/* __DAVINCI_GPIO_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,9 @@
 /* Base address */
 #define DAVINCI_ARM_INTC_BASE 0x01C48000
 
+#define DAVINCI_INTC_TYPE_AINTC		0
+#define DAVINCI_INTC_TYPE_CP_INTC	1
+
 /* Interrupt lines */
 #define IRQ_VDINT0       0
 #define IRQ_VDINT1       1
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/memory.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/memory.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/memory.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/memory.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,6 @@
  * Definitions
  **************************************************************************/
 #define DAVINCI_DDR_BASE    0x80000000
-#define DAVINCI_IRAM_BASE   0x00008000 /* ARM Internal RAM */
 
 #define PHYS_OFFSET DAVINCI_DDR_BASE
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/mmc.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/mmc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/mmc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,33 @@
+/*
+ *  Board-specific MMC configuration
+ */
+
+#ifndef _DAVINCI_MMC_H
+#define _DAVINCI_MMC_H
+
+#include <linux/types.h>
+#include <linux/mmc/host.h>
+
+struct davinci_mmc_config {
+	/* get_cd()/get_wp() may sleep */
+	int	(*get_cd)(int module);
+	int	(*get_ro)(int module);
+	/* wires == 0 is equivalent to wires == 4 (4-bit parallel) */
+	u8	wires;
+
+	u32     max_freq;
+
+	/* any additional host capabilities: OR'd in to mmc->f_caps */
+	u32     caps;
+
+	/* Version of the MMC/SD controller */
+	u8	version;
+};
+void davinci_setup_mmc(int module, struct davinci_mmc_config *config);
+
+enum {
+	MMC_CTLR_VERSION_1 = 0,	/* DM644x and DM355 */
+	MMC_CTLR_VERSION_2,	/* DA830 */
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/mux.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/mux.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/mux.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/mux.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,16 +19,6 @@
 #ifndef __INC_MACH_MUX_H
 #define __INC_MACH_MUX_H
 
-/* System module registers */
-#define PINMUX0			0x00
-#define PINMUX1			0x04
-/* dm355 only */
-#define PINMUX2			0x08
-#define PINMUX3			0x0c
-#define PINMUX4			0x10
-#define INTMUX			0x18
-#define EVTMUX			0x1c
-
 struct mux_config {
 	const char *name;
 	const char *mux_reg_name;
@@ -168,15 +158,9 @@
 
 #ifdef CONFIG_DAVINCI_MUX
 /* setup pin muxing */
-extern void davinci_mux_init(void);
-extern int davinci_mux_register(const struct mux_config *pins,
-				unsigned long size);
 extern int davinci_cfg_reg(unsigned long reg_cfg);
 #else
 /* boot loader does it all (no warnings from CONFIG_DAVINCI_MUX_WARNINGS) */
-static inline void davinci_mux_init(void) {}
-static inline int davinci_mux_register(const struct mux_config *pins,
-				       unsigned long size) { return 0; }
 static inline int davinci_cfg_reg(unsigned long reg_cfg) { return 0; }
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/nand.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/nand.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/nand.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/nand.h	2009-09-09 18:13:59.000000000 -0400
@@ -68,10 +68,14 @@
 
 	/* none  == NAND_ECC_NONE (strongly *not* advised!!)
 	 * soft  == NAND_ECC_SOFT
-	 * 1-bit == NAND_ECC_HW
-	 * 4-bit == NAND_ECC_HW_SYNDROME (not on all chips)
+	 * else  == NAND_ECC_HW, according to ecc_bits
+	 *
+	 * All DaVinci-family chips support 1-bit hardware ECC.
+	 * Newer ones also support 4-bit ECC, but are awkward
+	 * using it with large page chips.
 	 */
 	nand_ecc_modes_t	ecc_mode;
+	u8			ecc_bits;
 
 	/* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
 	unsigned		options;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/psc.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/psc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/psc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/psc.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,8 @@
 #ifndef __ASM_ARCH_PSC_H
 #define __ASM_ARCH_PSC_H
 
+#define	DAVINCI_PWR_SLEEP_CNTRL_BASE	0x01C41000
+
 /* Power and Sleep Controller (PSC) Domains */
 #define DAVINCI_GPSC_ARMDOMAIN      0
 #define DAVINCI_GPSC_DSPDOMAIN      1
@@ -116,8 +118,8 @@
 #define DM646X_LPSC_TIMER1         35
 #define DM646X_LPSC_ARM_INTC       45
 
-extern int davinci_psc_is_clk_active(unsigned int id);
-extern void davinci_psc_config(unsigned int domain, unsigned int id,
-			       char enable);
+extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
+extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
+		unsigned int id, char enable);
 
 #endif /* __ASM_ARCH_PSC_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/serial.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/serial.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/serial.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/serial.h	2009-09-09 18:13:59.000000000 -0400
@@ -18,8 +18,6 @@
 #define DAVINCI_UART1_BASE	(IO_PHYS + 0x20400)
 #define DAVINCI_UART2_BASE	(IO_PHYS + 0x20800)
 
-#define DM355_UART2_BASE	(IO_PHYS + 0x206000)
-
 /* DaVinci UART register offsets */
 #define UART_DAVINCI_PWREMU		0x0c
 #define UART_DM646X_SCR			0x10
@@ -30,6 +28,6 @@
 	unsigned int enabled_uarts;
 };
 
-extern void davinci_serial_init(struct davinci_uart_config *);
+extern int davinci_serial_init(struct davinci_uart_config *);
 
 #endif /* __ASM_ARCH_SERIAL_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/sram.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/sram.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/sram.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/sram.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * mach/sram.h - DaVinci simple SRAM allocator
+ *
+ * Copyright (C) 2009 David Brownell
+ *
+ * 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.
+ */
+#ifndef __MACH_SRAM_H
+#define __MACH_SRAM_H
+
+/* ARBITRARY:  SRAM allocations are multiples of this 2^N size */
+#define SRAM_GRANULARITY	512
+
+/*
+ * SRAM allocations return a CPU virtual address, or NULL on error.
+ * If a DMA address is requested and the SRAM supports DMA, its
+ * mapped address is also returned.
+ *
+ * Errors include SRAM memory not being available, and requesting
+ * DMA mapped SRAM on systems which don't allow that.
+ */
+extern void *sram_alloc(size_t len, dma_addr_t *dma);
+extern void sram_free(void *addr, size_t len);
+
+#endif /* __MACH_SRAM_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/time.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/time.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/time.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/time.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,35 @@
+/*
+ * Local header file for DaVinci time code.
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. 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.
+ */
+#ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H
+#define __ARCH_ARM_MACH_DAVINCI_TIME_H
+
+#define DAVINCI_TIMER0_BASE		(IO_PHYS + 0x21400)
+#define DAVINCI_TIMER1_BASE		(IO_PHYS + 0x21800)
+#define DAVINCI_WDOG_BASE		(IO_PHYS + 0x21C00)
+
+enum {
+	T0_BOT,
+	T0_TOP,
+	T1_BOT,
+	T1_TOP,
+	NUM_TIMERS
+};
+
+#define IS_TIMER1(id)		(id & 0x2)
+#define IS_TIMER0(id)		(!IS_TIMER1(id))
+#define IS_TIMER_TOP(id)	((id & 0x1))
+#define IS_TIMER_BOT(id)	(!IS_TIMER_TOP(id))
+
+#define ID_TO_TIMER(id)		(IS_TIMER1(id) != 0)
+
+extern struct davinci_timer_instance davinci_timer_instance[];
+
+#endif /* __ARCH_ARM_MACH_DAVINCI_TIME_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/uncompress.h linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/uncompress.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/include/mach/uncompress.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/include/mach/uncompress.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,11 +13,24 @@
 #include <linux/serial_reg.h>
 #include <mach/serial.h>
 
+#include <asm/mach-types.h>
+
+extern unsigned int __machine_arch_type;
+
+static u32 *uart;
+
+static u32 *get_uart_base(void)
+{
+	/* Add logic here for new platforms, using __macine_arch_type */
+	return (u32 *)DAVINCI_UART0_BASE;
+}
+
 /* PORT_16C550A, in polled non-fifo mode */
 
 static void putc(char c)
 {
-	volatile u32 *uart = (volatile void *) DAVINCI_UART0_BASE;
+	if (!uart)
+		uart = get_uart_base();
 
 	while (!(uart[UART_LSR] & UART_LSR_THRE))
 		barrier();
@@ -26,7 +39,9 @@
 
 static inline void flush(void)
 {
-	volatile u32 *uart = (volatile void *) DAVINCI_UART0_BASE;
+	if (!uart)
+		uart = get_uart_base();
+
 	while (!(uart[UART_LSR] & UART_LSR_THRE))
 		barrier();
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/io.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/io.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,47 +9,9 @@
  */
 
 #include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/io.h>
 
 #include <asm/tlb.h>
-#include <asm/memory.h>
-
-#include <asm/mach/map.h>
-#include <mach/clock.h>
-
-extern void davinci_check_revision(void);
-
-/*
- * The machine specific code may provide the extra mapping besides the
- * default mapping provided here.
- */
-static struct map_desc davinci_io_desc[] __initdata = {
-	{
-		.virtual	= IO_VIRT,
-		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= IO_SIZE,
-		.type		= MT_DEVICE
-	},
-};
-
-void __init davinci_map_common_io(void)
-{
-	iotable_init(davinci_io_desc, ARRAY_SIZE(davinci_io_desc));
-
-	/* Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but we must also do it here because of the CPU
-	 * revision check below.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-
-	/* We want to check CPU revision early for cpu_is_xxxx() macros.
-	 * IO space mapping must be initialized before we can do that.
-	 */
-	davinci_check_revision();
-}
 
 #define BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
 #define XLATE(p, pst, vst)	((void __iomem *)((p) - (pst) + (vst)))
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/irq.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 
 #include <mach/hardware.h>
 #include <mach/cputype.h>
+#include <mach/common.h>
 #include <asm/mach/irq.h>
 
 #define IRQ_BIT(irq)		((irq) & 0x1f)
@@ -41,18 +42,14 @@
 #define IRQ_INTPRI0_REG_OFFSET	0x0030
 #define IRQ_INTPRI7_REG_OFFSET	0x004C
 
-const u8 *davinci_def_priorities;
-
-#define INTC_BASE IO_ADDRESS(DAVINCI_ARM_INTC_BASE)
-
 static inline unsigned int davinci_irq_readl(int offset)
 {
-	return __raw_readl(INTC_BASE + offset);
+	return __raw_readl(davinci_intc_base + offset);
 }
 
 static inline void davinci_irq_writel(unsigned long value, int offset)
 {
-	__raw_writel(value, INTC_BASE + offset);
+	__raw_writel(value, davinci_intc_base + offset);
 }
 
 /* Disable interrupt */
@@ -113,217 +110,11 @@
 	.unmask = davinci_unmask_irq,
 };
 
-/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
-static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
-	[IRQ_VDINT0]		= 2,
-	[IRQ_VDINT1]		= 6,
-	[IRQ_VDINT2]		= 6,
-	[IRQ_HISTINT]		= 6,
-	[IRQ_H3AINT]		= 6,
-	[IRQ_PRVUINT]		= 6,
-	[IRQ_RSZINT]		= 6,
-	[7]			= 7,
-	[IRQ_VENCINT]		= 6,
-	[IRQ_ASQINT]		= 6,
-	[IRQ_IMXINT]		= 6,
-	[IRQ_VLCDINT]		= 6,
-	[IRQ_USBINT]		= 4,
-	[IRQ_EMACINT]		= 4,
-	[14]			= 7,
-	[15]			= 7,
-	[IRQ_CCINT0]		= 5,	/* dma */
-	[IRQ_CCERRINT]		= 5,	/* dma */
-	[IRQ_TCERRINT0]		= 5,	/* dma */
-	[IRQ_TCERRINT]		= 5,	/* dma */
-	[IRQ_PSCIN]		= 7,
-	[21]			= 7,
-	[IRQ_IDE]		= 4,
-	[23]			= 7,
-	[IRQ_MBXINT]		= 7,
-	[IRQ_MBRINT]		= 7,
-	[IRQ_MMCINT]		= 7,
-	[IRQ_SDIOINT]		= 7,
-	[28]			= 7,
-	[IRQ_DDRINT]		= 7,
-	[IRQ_AEMIFINT]		= 7,
-	[IRQ_VLQINT]		= 4,
-	[IRQ_TINT0_TINT12]	= 2,	/* clockevent */
-	[IRQ_TINT0_TINT34]	= 2,	/* clocksource */
-	[IRQ_TINT1_TINT12]	= 7,	/* DSP timer */
-	[IRQ_TINT1_TINT34]	= 7,	/* system tick */
-	[IRQ_PWMINT0]		= 7,
-	[IRQ_PWMINT1]		= 7,
-	[IRQ_PWMINT2]		= 7,
-	[IRQ_I2C]		= 3,
-	[IRQ_UARTINT0]		= 3,
-	[IRQ_UARTINT1]		= 3,
-	[IRQ_UARTINT2]		= 3,
-	[IRQ_SPINT0]		= 3,
-	[IRQ_SPINT1]		= 3,
-	[45]			= 7,
-	[IRQ_DSP2ARM0]		= 4,
-	[IRQ_DSP2ARM1]		= 4,
-	[IRQ_GPIO0]		= 7,
-	[IRQ_GPIO1]		= 7,
-	[IRQ_GPIO2]		= 7,
-	[IRQ_GPIO3]		= 7,
-	[IRQ_GPIO4]		= 7,
-	[IRQ_GPIO5]		= 7,
-	[IRQ_GPIO6]		= 7,
-	[IRQ_GPIO7]		= 7,
-	[IRQ_GPIOBNK0]		= 7,
-	[IRQ_GPIOBNK1]		= 7,
-	[IRQ_GPIOBNK2]		= 7,
-	[IRQ_GPIOBNK3]		= 7,
-	[IRQ_GPIOBNK4]		= 7,
-	[IRQ_COMMTX]		= 7,
-	[IRQ_COMMRX]		= 7,
-	[IRQ_EMUINT]		= 7,
-};
-
-static const u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
-	[IRQ_DM646X_VP_VERTINT0]        = 7,
-	[IRQ_DM646X_VP_VERTINT1]        = 7,
-	[IRQ_DM646X_VP_VERTINT2]        = 7,
-	[IRQ_DM646X_VP_VERTINT3]        = 7,
-	[IRQ_DM646X_VP_ERRINT]          = 7,
-	[IRQ_DM646X_RESERVED_1]         = 7,
-	[IRQ_DM646X_RESERVED_2]         = 7,
-	[IRQ_DM646X_WDINT]              = 7,
-	[IRQ_DM646X_CRGENINT0]          = 7,
-	[IRQ_DM646X_CRGENINT1]          = 7,
-	[IRQ_DM646X_TSIFINT0]           = 7,
-	[IRQ_DM646X_TSIFINT1]           = 7,
-	[IRQ_DM646X_VDCEINT]            = 7,
-	[IRQ_DM646X_USBINT]             = 7,
-	[IRQ_DM646X_USBDMAINT]          = 7,
-	[IRQ_DM646X_PCIINT]             = 7,
-	[IRQ_CCINT0]                    = 7,    /* dma */
-	[IRQ_CCERRINT]                  = 7,    /* dma */
-	[IRQ_TCERRINT0]                 = 7,    /* dma */
-	[IRQ_TCERRINT]                  = 7,    /* dma */
-	[IRQ_DM646X_TCERRINT2]          = 7,
-	[IRQ_DM646X_TCERRINT3]          = 7,
-	[IRQ_DM646X_IDE]                = 7,
-	[IRQ_DM646X_HPIINT]             = 7,
-	[IRQ_DM646X_EMACRXTHINT]        = 7,
-	[IRQ_DM646X_EMACRXINT]          = 7,
-	[IRQ_DM646X_EMACTXINT]          = 7,
-	[IRQ_DM646X_EMACMISCINT]        = 7,
-	[IRQ_DM646X_MCASP0TXINT]        = 7,
-	[IRQ_DM646X_MCASP0RXINT]        = 7,
-	[IRQ_AEMIFINT]                  = 7,
-	[IRQ_DM646X_RESERVED_3]         = 7,
-	[IRQ_DM646X_MCASP1TXINT]        = 7,    /* clockevent */
-	[IRQ_TINT0_TINT34]              = 7,    /* clocksource */
-	[IRQ_TINT1_TINT12]              = 7,    /* DSP timer */
-	[IRQ_TINT1_TINT34]              = 7,    /* system tick */
-	[IRQ_PWMINT0]                   = 7,
-	[IRQ_PWMINT1]                   = 7,
-	[IRQ_DM646X_VLQINT]             = 7,
-	[IRQ_I2C]                       = 7,
-	[IRQ_UARTINT0]                  = 7,
-	[IRQ_UARTINT1]                  = 7,
-	[IRQ_DM646X_UARTINT2]           = 7,
-	[IRQ_DM646X_SPINT0]             = 7,
-	[IRQ_DM646X_SPINT1]             = 7,
-	[IRQ_DM646X_DSP2ARMINT]         = 7,
-	[IRQ_DM646X_RESERVED_4]         = 7,
-	[IRQ_DM646X_PSCINT]             = 7,
-	[IRQ_DM646X_GPIO0]              = 7,
-	[IRQ_DM646X_GPIO1]              = 7,
-	[IRQ_DM646X_GPIO2]              = 7,
-	[IRQ_DM646X_GPIO3]              = 7,
-	[IRQ_DM646X_GPIO4]              = 7,
-	[IRQ_DM646X_GPIO5]              = 7,
-	[IRQ_DM646X_GPIO6]              = 7,
-	[IRQ_DM646X_GPIO7]              = 7,
-	[IRQ_DM646X_GPIOBNK0]           = 7,
-	[IRQ_DM646X_GPIOBNK1]           = 7,
-	[IRQ_DM646X_GPIOBNK2]           = 7,
-	[IRQ_DM646X_DDRINT]             = 7,
-	[IRQ_DM646X_AEMIFINT]           = 7,
-	[IRQ_COMMTX]                    = 7,
-	[IRQ_COMMRX]                    = 7,
-	[IRQ_EMUINT]                    = 7,
-};
-
-static const u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
-	[IRQ_DM355_CCDC_VDINT0]		= 2,
-	[IRQ_DM355_CCDC_VDINT1]		= 6,
-	[IRQ_DM355_CCDC_VDINT2]		= 6,
-	[IRQ_DM355_IPIPE_HST]		= 6,
-	[IRQ_DM355_H3AINT]		= 6,
-	[IRQ_DM355_IPIPE_SDR]		= 6,
-	[IRQ_DM355_IPIPEIFINT]		= 6,
-	[IRQ_DM355_OSDINT]		= 7,
-	[IRQ_DM355_VENCINT]		= 6,
-	[IRQ_ASQINT]			= 6,
-	[IRQ_IMXINT]			= 6,
-	[IRQ_USBINT]			= 4,
-	[IRQ_DM355_RTOINT]		= 4,
-	[IRQ_DM355_UARTINT2]		= 7,
-	[IRQ_DM355_TINT6]		= 7,
-	[IRQ_CCINT0]			= 5,	/* dma */
-	[IRQ_CCERRINT]			= 5,	/* dma */
-	[IRQ_TCERRINT0]			= 5,	/* dma */
-	[IRQ_TCERRINT]			= 5,	/* dma */
-	[IRQ_DM355_SPINT2_1]		= 7,
-	[IRQ_DM355_TINT7]		= 4,
-	[IRQ_DM355_SDIOINT0]		= 7,
-	[IRQ_MBXINT]			= 7,
-	[IRQ_MBRINT]			= 7,
-	[IRQ_MMCINT]			= 7,
-	[IRQ_DM355_MMCINT1]		= 7,
-	[IRQ_DM355_PWMINT3]		= 7,
-	[IRQ_DDRINT]			= 7,
-	[IRQ_AEMIFINT]			= 7,
-	[IRQ_DM355_SDIOINT1]		= 4,
-	[IRQ_TINT0_TINT12]		= 2,	/* clockevent */
-	[IRQ_TINT0_TINT34]		= 2,	/* clocksource */
-	[IRQ_TINT1_TINT12]		= 7,	/* DSP timer */
-	[IRQ_TINT1_TINT34]		= 7,	/* system tick */
-	[IRQ_PWMINT0]			= 7,
-	[IRQ_PWMINT1]			= 7,
-	[IRQ_PWMINT2]			= 7,
-	[IRQ_I2C]			= 3,
-	[IRQ_UARTINT0]			= 3,
-	[IRQ_UARTINT1]			= 3,
-	[IRQ_DM355_SPINT0_0]		= 3,
-	[IRQ_DM355_SPINT0_1]		= 3,
-	[IRQ_DM355_GPIO0]		= 3,
-	[IRQ_DM355_GPIO1]		= 7,
-	[IRQ_DM355_GPIO2]		= 4,
-	[IRQ_DM355_GPIO3]		= 4,
-	[IRQ_DM355_GPIO4]		= 7,
-	[IRQ_DM355_GPIO5]		= 7,
-	[IRQ_DM355_GPIO6]		= 7,
-	[IRQ_DM355_GPIO7]		= 7,
-	[IRQ_DM355_GPIO8]		= 7,
-	[IRQ_DM355_GPIO9]		= 7,
-	[IRQ_DM355_GPIOBNK0]		= 7,
-	[IRQ_DM355_GPIOBNK1]		= 7,
-	[IRQ_DM355_GPIOBNK2]		= 7,
-	[IRQ_DM355_GPIOBNK3]		= 7,
-	[IRQ_DM355_GPIOBNK4]		= 7,
-	[IRQ_DM355_GPIOBNK5]		= 7,
-	[IRQ_DM355_GPIOBNK6]		= 7,
-	[IRQ_COMMTX]			= 7,
-	[IRQ_COMMRX]			= 7,
-	[IRQ_EMUINT]			= 7,
-};
-
 /* ARM Interrupt Controller Initialization */
 void __init davinci_irq_init(void)
 {
 	unsigned i;
-
-	if (cpu_is_davinci_dm644x())
-		davinci_def_priorities = dm644x_default_priorities;
-	else if (cpu_is_davinci_dm646x())
-		davinci_def_priorities = dm646x_default_priorities;
-	else if (cpu_is_davinci_dm355())
-		davinci_def_priorities = dm355_default_priorities;
+	const u8 *davinci_def_priorities = davinci_soc_info.intc_irq_prios;
 
 	/* Clear all interrupt requests */
 	davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-davinci/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,11 +1,26 @@
 if ARCH_DAVINCI
 
+config AINTC
+	bool
+
+config CP_INTC
+	bool
+
 menu "TI DaVinci Implementations"
 
 comment "DaVinci Core Type"
 
 config ARCH_DAVINCI_DM644x
 	bool "DaVinci 644x based system"
+	select AINTC
+
+config ARCH_DAVINCI_DM355
+        bool "DaVinci 355 based system"
+	select AINTC
+
+config ARCH_DAVINCI_DM646x
+        bool "DaVinci 646x based system"
+	select AINTC
 
 comment "DaVinci Board Type"
 
@@ -17,6 +32,34 @@
 	  Configure this option to specify the whether the board used
 	  for development is a DM644x EVM
 
+config MACH_SFFSDR
+	bool "Lyrtech SFFSDR"
+	depends on ARCH_DAVINCI_DM644x
+	help
+	  Say Y here to select the Lyrtech Small Form Factor
+	  Software Defined Radio (SFFSDR) board.
+
+config MACH_DAVINCI_DM355_EVM
+	bool "TI DM355 EVM"
+	depends on ARCH_DAVINCI_DM355
+	help
+	  Configure this option to specify the whether the board used
+	  for development is a DM355 EVM
+
+config MACH_DM355_LEOPARD
+	bool "DM355 Leopard board"
+	depends on ARCH_DAVINCI_DM355
+	help
+	  Configure this option to specify the whether the board used
+	  for development is a DM355 Leopard board.
+
+config MACH_DAVINCI_DM6467_EVM
+	bool "TI DM6467 EVM"
+	depends on ARCH_DAVINCI_DM646x
+	help
+	  Configure this option to specify the whether the board used
+	  for development is a DM6467 EVM
+
 
 config DAVINCI_MUX
 	bool "DAVINCI multiplexing support"
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-davinci/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,13 +4,22 @@
 #
 
 # Common objects
-obj-y 			:= time.o irq.o clock.o serial.o io.o id.o psc.o \
-			   gpio.o devices.o dma.o usb.o
+obj-y 			:= time.o clock.o serial.o io.o psc.o \
+			   gpio.o devices.o dma.o usb.o common.o sram.o
 
 obj-$(CONFIG_DAVINCI_MUX)		+= mux.o
 
 # Chip specific
 obj-$(CONFIG_ARCH_DAVINCI_DM644x)       += dm644x.o
+obj-$(CONFIG_ARCH_DAVINCI_DM355)        += dm355.o
+obj-$(CONFIG_ARCH_DAVINCI_DM646x)       += dm646x.o
+
+obj-$(CONFIG_AINTC)			+= irq.o
+obj-$(CONFIG_CP_INTC)			+= cp_intc.o
 
 # Board specific
 obj-$(CONFIG_MACH_DAVINCI_EVM)  	+= board-dm644x-evm.o
+obj-$(CONFIG_MACH_SFFSDR)		+= board-sffsdr.o
+obj-$(CONFIG_MACH_DAVINCI_DM355_EVM)	+= board-dm355-evm.o
+obj-$(CONFIG_MACH_DM355_LEOPARD)	+= board-dm355-leopard.o
+obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM)	+= board-dm646x-evm.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/mux.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/mux.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/mux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/mux.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,18 +21,7 @@
 
 #include <mach/hardware.h>
 #include <mach/mux.h>
-
-static const struct mux_config *mux_table;
-static unsigned long pin_table_sz;
-
-int __init davinci_mux_register(const struct mux_config *pins,
-				unsigned long size)
-{
-	mux_table = pins;
-	pin_table_sz = size;
-
-	return 0;
-}
+#include <mach/common.h>
 
 /*
  * Sets the DAVINCI MUX register based on the table
@@ -40,23 +29,24 @@
 int __init_or_module davinci_cfg_reg(const unsigned long index)
 {
 	static DEFINE_SPINLOCK(mux_spin_lock);
-	void __iomem *base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE);
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	void __iomem *base = soc_info->pinmux_base;
 	unsigned long flags;
 	const struct mux_config *cfg;
 	unsigned int reg_orig = 0, reg = 0;
 	unsigned int mask, warn = 0;
 
-	if (!mux_table)
+	if (!soc_info->pinmux_pins)
 		BUG();
 
-	if (index >= pin_table_sz) {
+	if (index >= soc_info->pinmux_pins_num) {
 		printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
-		       index, pin_table_sz);
+		       index, soc_info->pinmux_pins_num);
 		dump_stack();
 		return -ENODEV;
 	}
 
-	cfg = &mux_table[index];
+	cfg = &soc_info->pinmux_pins[index];
 
 	if (cfg->name == NULL) {
 		printk(KERN_ERR "No entry for the specified index\n");
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/psc.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/psc.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/psc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/psc.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,8 +28,6 @@
 #include <mach/psc.h>
 #include <mach/mux.h>
 
-#define DAVINCI_PWR_SLEEP_CNTRL_BASE 0x01C41000
-
 /* PSC register offsets */
 #define EPCPR		0x070
 #define PTCMD		0x120
@@ -42,22 +40,42 @@
 #define MDSTAT_STATE_MASK 0x1f
 
 /* Return nonzero iff the domain's clock is active */
-int __init davinci_psc_is_clk_active(unsigned int id)
+int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
 {
-	void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
-	u32 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
+	void __iomem *psc_base;
+	u32 mdstat;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
+		pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
+				(int)soc_info->psc_bases, ctlr);
+		return 0;
+	}
+
+	psc_base = soc_info->psc_bases[ctlr];
+	mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
 
 	/* if clocked, state can be "Enable" or "SyncReset" */
 	return mdstat & BIT(12);
 }
 
 /* Enable or disable a PSC domain */
-void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
+void davinci_psc_config(unsigned int domain, unsigned int ctlr,
+		unsigned int id, char enable)
 {
 	u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
-	void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
+	void __iomem *psc_base;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */
 
+	if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
+		pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
+				(int)soc_info->psc_bases, ctlr);
+		return;
+	}
+
+	psc_base = soc_info->psc_bases[ctlr];
+
 	mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
 	mdctl &= ~MDSTAT_STATE_MASK;
 	mdctl |= next_state;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/serial.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/serial.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/serial.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/serial.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,8 @@
 #include <mach/serial.h>
 #include <mach/irqs.h>
 #include <mach/cputype.h>
+#include <mach/common.h>
+
 #include "clock.h"
 
 static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
@@ -49,44 +51,6 @@
 	__raw_writel(value, IO_ADDRESS(p->mapbase) + offset);
 }
 
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.mapbase	= DAVINCI_UART0_BASE,
-		.irq		= IRQ_UARTINT0,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
-				  UPF_IOREMAP,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-	},
-	{
-		.mapbase	= DAVINCI_UART1_BASE,
-		.irq		= IRQ_UARTINT1,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
-				  UPF_IOREMAP,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-	},
-	{
-		.mapbase	= DAVINCI_UART2_BASE,
-		.irq		= IRQ_UARTINT2,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
-				  UPF_IOREMAP,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-	},
-	{
-		.flags		= 0
-	},
-};
-
-static struct platform_device serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
-};
-
 static void __init davinci_serial_reset(struct plat_serial8250_port *p)
 {
 	unsigned int pwremu = 0;
@@ -106,35 +70,22 @@
 				 UART_DM646X_SCR_TX_WATERMARK);
 }
 
-void __init davinci_serial_init(struct davinci_uart_config *info)
+int __init davinci_serial_init(struct davinci_uart_config *info)
 {
 	int i;
 	char name[16];
 	struct clk *uart_clk;
-	struct device *dev = &serial_device.dev;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct device *dev = &soc_info->serial_dev->dev;
+	struct plat_serial8250_port *p = dev->platform_data;
 
 	/*
 	 * Make sure the serial ports are muxed on at this point.
-	 * You have to mux them off in device drivers later on
-	 * if not needed.
+	 * You have to mux them off in device drivers later on if not needed.
 	 */
-	for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++) {
-		struct plat_serial8250_port *p = serial_platform_data + i;
-
-		if (!(info->enabled_uarts & (1 << i))) {
-			p->flags = 0;
+	for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++, p++) {
+		if (!(info->enabled_uarts & (1 << i)))
 			continue;
-		}
-
-		if (cpu_is_davinci_dm646x())
-			p->iotype = UPIO_MEM32;
-
-		if (cpu_is_davinci_dm355()) {
-			if (i == 2) {
-				p->mapbase = (unsigned long)DM355_UART2_BASE;
-				p->irq = IRQ_DM355_UARTINT2;
-			}
-		}
 
 		sprintf(name, "uart%d", i);
 		uart_clk = clk_get(dev, name);
@@ -147,11 +98,6 @@
 			davinci_serial_reset(p);
 		}
 	}
-}
 
-static int __init davinci_init(void)
-{
-	return platform_device_register(&serial_device);
+	return platform_device_register(soc_info->serial_dev);
 }
-
-arch_initcall(davinci_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/sram.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/sram.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/sram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/sram.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ * mach-davinci/sram.c - DaVinci simple SRAM allocator
+ *
+ * Copyright (C) 2009 David Brownell
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/genalloc.h>
+
+#include <mach/common.h>
+#include <mach/memory.h>
+#include <mach/sram.h>
+
+
+static struct gen_pool *sram_pool;
+
+void *sram_alloc(size_t len, dma_addr_t *dma)
+{
+	unsigned long vaddr;
+	dma_addr_t dma_base = davinci_soc_info.sram_dma;
+
+	if (dma)
+		*dma = 0;
+	if (!sram_pool || (dma && !dma_base))
+		return NULL;
+
+	vaddr = gen_pool_alloc(sram_pool, len);
+	if (!vaddr)
+		return NULL;
+
+	if (dma)
+		*dma = dma_base + (vaddr - SRAM_VIRT);
+	return (void *)vaddr;
+
+}
+EXPORT_SYMBOL(sram_alloc);
+
+void sram_free(void *addr, size_t len)
+{
+	gen_pool_free(sram_pool, (unsigned long) addr, len);
+}
+EXPORT_SYMBOL(sram_free);
+
+
+/*
+ * REVISIT This supports CPU and DMA access to/from SRAM, but it
+ * doesn't (yet?) support some other notable uses of SRAM:  as TCM
+ * for data and/or instructions; and holding code needed to enter
+ * and exit suspend states (while DRAM can't be used).
+ */
+static int __init sram_init(void)
+{
+	unsigned len = davinci_soc_info.sram_len;
+	int status = 0;
+
+	if (len) {
+		len = min(len, SRAM_SIZE);
+		sram_pool = gen_pool_create(ilog2(SRAM_GRANULARITY), -1);
+		if (!sram_pool)
+			status = -ENOMEM;
+	}
+	if (sram_pool)
+		status = gen_pool_add(sram_pool, SRAM_VIRT, len, -1);
+	WARN_ON(status < 0);
+	return status;
+}
+core_initcall(sram_init);
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-davinci/time.c linux-libre-2.6.31-gnu/arch/arm/mach-davinci/time.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-davinci/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-davinci/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/platform_device.h>
 
 #include <mach/hardware.h>
 #include <asm/system.h>
@@ -28,52 +29,41 @@
 #include <asm/errno.h>
 #include <mach/io.h>
 #include <mach/cputype.h>
+#include <mach/time.h>
 #include "clock.h"
 
 static struct clock_event_device clockevent_davinci;
 static unsigned int davinci_clock_tick_rate;
 
-#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
-#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
-#define DAVINCI_WDOG_BASE   (IO_PHYS + 0x21C00)
-
-enum {
-	T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS,
-};
-
-#define IS_TIMER1(id)    (id & 0x2)
-#define IS_TIMER0(id)    (!IS_TIMER1(id))
-#define IS_TIMER_TOP(id) ((id & 0x1))
-#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id))
-
-static int timer_irqs[NUM_TIMERS] = {
-	IRQ_TINT0_TINT12,
-	IRQ_TINT0_TINT34,
-	IRQ_TINT1_TINT12,
-	IRQ_TINT1_TINT34,
-};
-
 /*
  * This driver configures the 2 64-bit count-up timers as 4 independent
  * 32-bit count-up timers used as follows:
- *
- * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
- * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top   :  <unused>
  */
-#define TID_CLOCKEVENT  T0_BOT
-#define TID_CLOCKSOURCE T0_TOP
+
+enum {
+	TID_CLOCKEVENT,
+	TID_CLOCKSOURCE,
+};
 
 /* Timer register offsets */
-#define PID12                        0x0
-#define TIM12                        0x10
-#define TIM34                        0x14
-#define PRD12                        0x18
-#define PRD34                        0x1c
-#define TCR                          0x20
-#define TGCR                         0x24
-#define WDTCR                        0x28
+#define PID12			0x0
+#define TIM12			0x10
+#define TIM34			0x14
+#define PRD12			0x18
+#define PRD34			0x1c
+#define TCR			0x20
+#define TGCR			0x24
+#define WDTCR			0x28
+
+/* Offsets of the 8 compare registers */
+#define	CMP12_0			0x60
+#define	CMP12_1			0x64
+#define	CMP12_2			0x68
+#define	CMP12_3			0x6c
+#define	CMP12_4			0x70
+#define	CMP12_5			0x74
+#define	CMP12_6			0x78
+#define	CMP12_7			0x7c
 
 /* Timer register bitfields */
 #define TCR_ENAMODE_DISABLE          0x0
@@ -105,6 +95,7 @@
 	unsigned int id;
 	unsigned long period;
 	unsigned long opts;
+	unsigned long flags;
 	void __iomem *base;
 	unsigned long tim_off;
 	unsigned long prd_off;
@@ -114,30 +105,58 @@
 static struct timer_s timers[];
 
 /* values for 'opts' field of struct timer_s */
-#define TIMER_OPTS_DISABLED   0x00
-#define TIMER_OPTS_ONESHOT    0x01
-#define TIMER_OPTS_PERIODIC   0x02
+#define TIMER_OPTS_DISABLED		0x01
+#define TIMER_OPTS_ONESHOT		0x02
+#define TIMER_OPTS_PERIODIC		0x04
+#define TIMER_OPTS_STATE_MASK		0x07
+
+#define TIMER_OPTS_USE_COMPARE		0x80000000
+#define USING_COMPARE(t)		((t)->opts & TIMER_OPTS_USE_COMPARE)
+
+static char *id_to_name[] = {
+	[T0_BOT]	= "timer0_0",
+	[T0_TOP]	= "timer0_1",
+	[T1_BOT]	= "timer1_0",
+	[T1_TOP]	= "timer1_1",
+};
 
 static int timer32_config(struct timer_s *t)
 {
-	u32 tcr = __raw_readl(t->base + TCR);
+	u32 tcr;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
-	/* disable timer */
-	tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
-	__raw_writel(tcr, t->base + TCR);
+	if (USING_COMPARE(t)) {
+		struct davinci_timer_instance *dtip =
+				soc_info->timer_info->timers;
+		int event_timer = ID_TO_TIMER(timers[TID_CLOCKEVENT].id);
 
-	/* reset counter to zero, set new period */
-	__raw_writel(0, t->base + t->tim_off);
-	__raw_writel(t->period, t->base + t->prd_off);
+		/*
+		 * Next interrupt should be the current time reg value plus
+		 * the new period (using 32-bit unsigned addition/wrapping
+		 * to 0 on overflow).  This assumes that the clocksource
+		 * is setup to count to 2^32-1 before wrapping around to 0.
+		 */
+		__raw_writel(__raw_readl(t->base + t->tim_off) + t->period,
+			t->base + dtip[event_timer].cmp_off);
+	} else {
+		tcr = __raw_readl(t->base + TCR);
 
-	/* Set enable mode */
-	if (t->opts & TIMER_OPTS_ONESHOT) {
-		tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift;
-	} else if (t->opts & TIMER_OPTS_PERIODIC) {
-		tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
-	}
+		/* disable timer */
+		tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
+		__raw_writel(tcr, t->base + TCR);
 
-	__raw_writel(tcr, t->base + TCR);
+		/* reset counter to zero, set new period */
+		__raw_writel(0, t->base + t->tim_off);
+		__raw_writel(t->period, t->base + t->prd_off);
+
+		/* Set enable mode */
+		if (t->opts & TIMER_OPTS_ONESHOT)
+			tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift;
+		else if (t->opts & TIMER_OPTS_PERIODIC)
+			tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
+
+		__raw_writel(tcr, t->base + TCR);
+	}
 	return 0;
 }
 
@@ -182,13 +201,14 @@
 
 static void __init timer_init(void)
 {
-	u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct davinci_timer_instance *dtip = soc_info->timer_info->timers;
 	int i;
 
 	/* Global init of each 64-bit timer as a whole */
 	for(i=0; i<2; i++) {
 		u32 tgcr;
-		void __iomem *base = IO_ADDRESS(phys_bases[i]);
+		void __iomem *base = dtip[i].base;
 
 		/* Disabled, Internal clock source */
 		__raw_writel(0, base + TCR);
@@ -214,33 +234,33 @@
 	/* Init of each timer as a 32-bit timer */
 	for (i=0; i< ARRAY_SIZE(timers); i++) {
 		struct timer_s *t = &timers[i];
-		u32 phys_base;
+		int timer = ID_TO_TIMER(t->id);
+		u32 irq;
 
-		if (t->name) {
-			t->id = i;
-			phys_base = (IS_TIMER1(t->id) ?
-			       DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE);
-			t->base = IO_ADDRESS(phys_base);
+		t->base = dtip[timer].base;
 
-			if (IS_TIMER_BOT(t->id)) {
-				t->enamode_shift = 6;
-				t->tim_off = TIM12;
-				t->prd_off = PRD12;
-			} else {
-				t->enamode_shift = 22;
-				t->tim_off = TIM34;
-				t->prd_off = PRD34;
-			}
+		if (IS_TIMER_BOT(t->id)) {
+			t->enamode_shift = 6;
+			t->tim_off = TIM12;
+			t->prd_off = PRD12;
+			irq = dtip[timer].bottom_irq;
+		} else {
+			t->enamode_shift = 22;
+			t->tim_off = TIM34;
+			t->prd_off = PRD34;
+			irq = dtip[timer].top_irq;
+		}
 
-			/* Register interrupt */
-			t->irqaction.name = t->name;
-			t->irqaction.dev_id = (void *)t;
-			if (t->irqaction.handler != NULL) {
-				setup_irq(timer_irqs[t->id], &t->irqaction);
-			}
+		/* Register interrupt */
+		t->irqaction.name = t->name;
+		t->irqaction.dev_id = (void *)t;
 
-			timer32_config(&timers[i]);
+		if (t->irqaction.handler != NULL) {
+			irq = USING_COMPARE(t) ? dtip[i].cmp_irq : irq;
+			setup_irq(irq, &t->irqaction);
 		}
+
+		timer32_config(&timers[i]);
 	}
 }
 
@@ -255,7 +275,6 @@
 }
 
 static struct clocksource clocksource_davinci = {
-	.name		= "timer0_1",
 	.rating		= 300,
 	.read		= read_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
@@ -284,15 +303,18 @@
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		t->period = davinci_clock_tick_rate / (HZ);
-		t->opts = TIMER_OPTS_PERIODIC;
+		t->opts &= ~TIMER_OPTS_STATE_MASK;
+		t->opts |= TIMER_OPTS_PERIODIC;
 		timer32_config(t);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
-		t->opts = TIMER_OPTS_ONESHOT;
+		t->opts &= ~TIMER_OPTS_STATE_MASK;
+		t->opts |= TIMER_OPTS_ONESHOT;
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
-		t->opts = TIMER_OPTS_DISABLED;
+		t->opts &= ~TIMER_OPTS_STATE_MASK;
+		t->opts |= TIMER_OPTS_DISABLED;
 		break;
 	case CLOCK_EVT_MODE_RESUME:
 		break;
@@ -300,7 +322,6 @@
 }
 
 static struct clock_event_device clockevent_davinci = {
-	.name		= "timer0_0",
 	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 	.shift		= 32,
 	.set_next_event	= davinci_set_next_event,
@@ -311,10 +332,42 @@
 static void __init davinci_timer_init(void)
 {
 	struct clk *timer_clk;
-
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	unsigned int clockevent_id;
+	unsigned int clocksource_id;
 	static char err[] __initdata = KERN_ERR
 		"%s: can't register clocksource!\n";
 
+	clockevent_id = soc_info->timer_info->clockevent_id;
+	clocksource_id = soc_info->timer_info->clocksource_id;
+
+	timers[TID_CLOCKEVENT].id = clockevent_id;
+	timers[TID_CLOCKSOURCE].id = clocksource_id;
+
+	/*
+	 * If using same timer for both clock events & clocksource,
+	 * a compare register must be used to generate an event interrupt.
+	 * This is equivalent to a oneshot timer only (not periodic).
+	 */
+	if (clockevent_id == clocksource_id) {
+		struct davinci_timer_instance *dtip =
+				soc_info->timer_info->timers;
+		int event_timer = ID_TO_TIMER(clockevent_id);
+
+		/* Only bottom timers can use compare regs */
+		if (IS_TIMER_TOP(clockevent_id))
+			pr_warning("davinci_timer_init: Invalid use"
+				" of system timers.  Results unpredictable.\n");
+		else if ((dtip[event_timer].cmp_off == 0)
+				|| (dtip[event_timer].cmp_irq == 0))
+			pr_warning("davinci_timer_init:  Invalid timer instance"
+				" setup.  Results unpredictable.\n");
+		else {
+			timers[TID_CLOCKEVENT].opts |= TIMER_OPTS_USE_COMPARE;
+			clockevent_davinci.features = CLOCK_EVT_FEAT_ONESHOT;
+		}
+	}
+
 	/* init timer hw */
 	timer_init();
 
@@ -325,6 +378,7 @@
 	davinci_clock_tick_rate = clk_get_rate(timer_clk);
 
 	/* setup clocksource */
+	clocksource_davinci.name = id_to_name[clocksource_id];
 	clocksource_davinci.mult =
 		clocksource_khz2mult(davinci_clock_tick_rate/1000,
 				     clocksource_davinci.shift);
@@ -332,12 +386,12 @@
 		printk(err, clocksource_davinci.name);
 
 	/* setup clockevent */
+	clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
 	clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
 					 clockevent_davinci.shift);
 	clockevent_davinci.max_delta_ns =
 		clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
-	clockevent_davinci.min_delta_ns =
-		clockevent_delta2ns(1, &clockevent_davinci);
+	clockevent_davinci.min_delta_ns = 50000; /* 50 usec */
 
 	clockevent_davinci.cpumask = cpumask_of(0);
 	clockevents_register_device(&clockevent_davinci);
@@ -349,15 +403,14 @@
 
 
 /* reset board using watchdog timer */
-void davinci_watchdog_reset(void) {
+void davinci_watchdog_reset(void)
+{
 	u32 tgcr, wdtcr;
-	void __iomem *base = IO_ADDRESS(DAVINCI_WDOG_BASE);
-	struct device dev;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	void __iomem *base = soc_info->wdt_base;
 	struct clk *wd_clk;
-	char *name = "watchdog";
 
-	dev_set_name(&dev, name);
-	wd_clk = clk_get(&dev, NULL);
+	wd_clk = clk_get(&davinci_wdt_device.dev, NULL);
 	if (WARN_ON(IS_ERR(wd_clk)))
 		return;
 	clk_enable(wd_clk);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,58 +72,58 @@
 static struct clk clk_p;
 static struct clk clk_pll2;
 static struct clk clk_usb_host = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= EP93XX_SYSCON_CLOCK_USH_EN,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_USH_EN,
 };
 
 /* DMA Clocks */
 static struct clk clk_m2p0 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00020000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P0,
 };
 static struct clk clk_m2p1 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00010000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P1,
 };
 static struct clk clk_m2p2 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00080000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P2,
 };
 static struct clk clk_m2p3 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00040000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P3,
 };
 static struct clk clk_m2p4 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00200000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P4,
 };
 static struct clk clk_m2p5 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00100000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P5,
 };
 static struct clk clk_m2p6 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00800000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P6,
 };
 static struct clk clk_m2p7 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x00400000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P7,
 };
 static struct clk clk_m2p8 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x02000000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P8,
 };
 static struct clk clk_m2p9 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x01000000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P9,
 };
 static struct clk clk_m2m0 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x04000000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2M0,
 };
 static struct clk clk_m2m1 = {
-	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
-	.enable_mask	= 0x08000000,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2M1,
 };
 
 #define INIT_CK(dev,con,ck)					\
@@ -138,7 +138,7 @@
 	INIT_CK(NULL, "hclk", &clk_h),
 	INIT_CK(NULL, "pclk", &clk_p),
 	INIT_CK(NULL, "pll2", &clk_pll2),
-	INIT_CK(NULL, "usb_host", &clk_usb_host),
+	INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
 	INIT_CK(NULL, "m2p0", &clk_m2p0),
 	INIT_CK(NULL, "m2p1", &clk_m2p1),
 	INIT_CK(NULL, "m2p2", &clk_m2p2),
@@ -186,8 +186,8 @@
 {
 	u32 value;
 
-	value = __raw_readl(EP93XX_SYSCON_CLOCK_CONTROL);
-	if (value & EP93XX_SYSCON_CLOCK_UARTBAUD)
+	value = __raw_readl(EP93XX_SYSCON_PWRCNT);
+	if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
 		return EP93XX_EXT_CLK_RATE;
 	else
 		return EP93XX_EXT_CLK_RATE / 2;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/core.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/core.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -155,7 +155,7 @@
 static unsigned char gpio_int_enabled[3];
 static unsigned char gpio_int_type1[3];
 static unsigned char gpio_int_type2[3];
-static unsigned char gpio_int_debouce[3];
+static unsigned char gpio_int_debounce[3];
 
 /* Port ordering is: A B F */
 static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c };
@@ -192,11 +192,11 @@
 	int port_mask = 1 << (line & 7);
 
 	if (enable)
-		gpio_int_debouce[port] |= port_mask;
+		gpio_int_debounce[port] |= port_mask;
 	else
-		gpio_int_debouce[port] &= ~port_mask;
+		gpio_int_debounce[port] &= ~port_mask;
 
-	__raw_writeb(gpio_int_debouce[port],
+	__raw_writeb(gpio_int_debounce[port],
 		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
 }
 EXPORT_SYMBOL(ep93xx_gpio_int_debounce);
@@ -362,8 +362,8 @@
 {
 	int gpio_irq;
 
-	vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
-	vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
+	vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
+	vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
 
 	for (gpio_irq = gpio_to_irq(0);
 	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
@@ -450,10 +450,19 @@
 };
 
 
+static struct resource ep93xx_rtc_resource[] = {
+	{
+		.start		= EP93XX_RTC_PHYS_BASE,
+		.end		= EP93XX_RTC_PHYS_BASE + 0x10c - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
 static struct platform_device ep93xx_rtc_device = {
-       .name           = "ep93xx-rtc",
-       .id             = -1,
-       .num_resources  = 0,
+	.name		= "ep93xx-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_rtc_resource),
+	.resource	= ep93xx_rtc_resource,
 };
 
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/dma-m2p.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/dma-m2p.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/dma-m2p.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/dma-m2p.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <mach/dma.h>
 #include <mach/hardware.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9302a.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9302a.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9302a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9302a.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9302a.c
- * Cirrus Logic EDB9302A support.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9302a_flash_data = {
-	.width		= 2,
-};
-
-static struct resource edb9302a_flash_resource = {
-	.start		= EP93XX_CS6_PHYS_BASE,
-	.end		= EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device edb9302a_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &edb9302a_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &edb9302a_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9302a_eth_data = {
-	.phy_id		= 1,
-};
-
-static void __init edb9302a_init_machine(void)
-{
-	ep93xx_init_devices();
-	platform_device_register(&edb9302a_flash);
-
-	ep93xx_register_eth(&edb9302a_eth_data, 1);
-}
-
-MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
-	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
-	.map_io		= ep93xx_map_io,
-	.init_irq	= ep93xx_init_irq,
-	.timer		= &ep93xx_timer,
-	.init_machine	= edb9302a_init_machine,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9302.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9302.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9302.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9302.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9302.c
- * Cirrus Logic EDB9302 support.
- *
- * Copyright (C) 2006 George Kashperko <george@chas.com.ua>
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9302_flash_data = {
-	.width		= 2,
-};
-
-static struct resource edb9302_flash_resource = {
-	.start		= EP93XX_CS6_PHYS_BASE,
-	.end		= EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device edb9302_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &edb9302_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &edb9302_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9302_eth_data = {
-	.phy_id		= 1,
-};
-
-static void __init edb9302_init_machine(void)
-{
-	ep93xx_init_devices();
-	platform_device_register(&edb9302_flash);
-
-	ep93xx_register_eth(&edb9302_eth_data, 1);
-}
-
-MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
-	/* Maintainer: George Kashperko <george@chas.com.ua> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
-	.map_io		= ep93xx_map_io,
-	.init_irq	= ep93xx_init_irq,
-	.timer		= &ep93xx_timer,
-	.init_machine	= edb9302_init_machine,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9307a.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9307a.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9307a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9307a.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9307a.c
- * Cirrus Logic EDB9307A support.
- *
- * Copyright (C) 2008 H Hartley Sweeten <hsweeten@visionengravers.com>
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9307a_flash_data = {
-	.width		= 2,
-};
-
-static struct resource edb9307a_flash_resource = {
-	.start		= EP93XX_CS6_PHYS_BASE,
-	.end		= EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device edb9307a_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &edb9307a_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &edb9307a_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9307a_eth_data = {
-	.phy_id		= 1,
-};
-
-static struct i2c_board_info __initdata edb9307a_i2c_data[] = {
-	{
-		/* On-board battery backed RTC */
-		I2C_BOARD_INFO("isl1208", 0x6f),
-	},
-	/*
-	 * The I2C signals are also routed to the Expansion Connector (J4)
-	 */
-};
-
-static void __init edb9307a_init_machine(void)
-{
-	ep93xx_init_devices();
-	platform_device_register(&edb9307a_flash);
-
-	ep93xx_register_eth(&edb9307a_eth_data, 1);
-
-	ep93xx_init_i2c(edb9307a_i2c_data, ARRAY_SIZE(edb9307a_i2c_data));
-}
-
-MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
-	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
-	.map_io		= ep93xx_map_io,
-	.init_irq	= ep93xx_init_irq,
-	.timer		= &ep93xx_timer,
-	.init_machine	= edb9307a_init_machine,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9307.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9307.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9307.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9307.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9307.c
- * Cirrus Logic EDB9307 support.
- *
- * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9307_flash_data = {
-	.width		= 4,
-};
-
-static struct resource edb9307_flash_resource = {
-	.start		= EP93XX_CS6_PHYS_BASE,
-	.end		= EP93XX_CS6_PHYS_BASE + SZ_32M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device edb9307_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &edb9307_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &edb9307_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9307_eth_data = {
-	.phy_id		= 1,
-};
-
-static void __init edb9307_init_machine(void)
-{
-	ep93xx_init_devices();
-	platform_device_register(&edb9307_flash);
-
-	ep93xx_register_eth(&edb9307_eth_data, 1);
-}
-
-MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
-	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
-	.map_io		= ep93xx_map_io,
-	.init_irq	= ep93xx_init_irq,
-	.timer		= &ep93xx_timer,
-	.init_machine	= edb9307_init_machine,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9312.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9312.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9312.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9312.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9312.c
- * Cirrus Logic EDB9312 support.
- *
- * Copyright (C) 2006 Infosys Technologies Limited
- * 	Toufeeq Hussain	<toufeeq_hussain@infosys.com>
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9312_flash_data = {
-	.width		= 4,
-};
-
-static struct resource edb9312_flash_resource = {
-	.start		= EP93XX_CS6_PHYS_BASE,
-	.end		= EP93XX_CS6_PHYS_BASE + SZ_32M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device edb9312_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &edb9312_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &edb9312_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9312_eth_data = {
-	.phy_id		= 1,
-};
-
-static void __init edb9312_init_machine(void)
-{
-	ep93xx_init_devices();
-	platform_device_register(&edb9312_flash);
-
-	ep93xx_register_eth(&edb9312_eth_data, 1);
-}
-
-MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
-	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
-	.map_io		= ep93xx_map_io,
-	.init_irq	= ep93xx_init_irq,
-	.timer		= &ep93xx_timer,
-	.init_machine	= edb9312_init_machine,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9315a.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9315a.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9315a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9315a.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9315a.c
- * Cirrus Logic EDB9315A support.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9315a_flash_data = {
-	.width		= 2,
-};
-
-static struct resource edb9315a_flash_resource = {
-	.start		= EP93XX_CS6_PHYS_BASE,
-	.end		= EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device edb9315a_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &edb9315a_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &edb9315a_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9315a_eth_data = {
-	.phy_id		= 1,
-};
-
-static void __init edb9315a_init_machine(void)
-{
-	ep93xx_init_devices();
-	platform_device_register(&edb9315a_flash);
-
-	ep93xx_register_eth(&edb9315a_eth_data, 1);
-}
-
-MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
-	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
-	.map_io		= ep93xx_map_io,
-	.init_irq	= ep93xx_init_irq,
-	.timer		= &ep93xx_timer,
-	.init_machine	= edb9315a_init_machine,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9315.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9315.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb9315.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb9315.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/edb9315.c
- * Cirrus Logic EDB9315 support.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-static struct physmap_flash_data edb9315_flash_data = {
-	.width		= 4,
-};
-
-static struct resource edb9315_flash_resource = {
-	.start		= EP93XX_CS6_PHYS_BASE,
-	.end		= EP93XX_CS6_PHYS_BASE + SZ_32M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device edb9315_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &edb9315_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &edb9315_flash_resource,
-};
-
-static struct ep93xx_eth_data edb9315_eth_data = {
-	.phy_id		= 1,
-};
-
-static void __init edb9315_init_machine(void)
-{
-	ep93xx_init_devices();
-	platform_device_register(&edb9315_flash);
-
-	ep93xx_register_eth(&edb9315_eth_data, 1);
-}
-
-MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
-	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.phys_io	= EP93XX_APB_PHYS_BASE,
-	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
-	.map_io		= ep93xx_map_io,
-	.init_irq	= ep93xx_init_irq,
-	.timer		= &ep93xx_timer,
-	.init_machine	= edb9315_init_machine,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb93xx.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb93xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/edb93xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/edb93xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,217 @@
+/*
+ * arch/arm/mach-ep93xx/edb93xx.c
+ * Cirrus Logic EDB93xx Development Board support.
+ *
+ * EDB93XX, EDB9301, EDB9307A
+ * Copyright (C) 2008-2009 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * EDB9302
+ * Copyright (C) 2006 George Kashperko <george@chas.com.ua>
+ *
+ * EDB9302A, EDB9315, EDB9315A
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * EDB9307
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * EDB9312
+ * Copyright (C) 2006 Infosys Technologies Limited
+ *                    Toufeeq Hussain <toufeeq_hussain@infosys.com>
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb93xx_flash_data;
+
+static struct resource edb93xx_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device edb93xx_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &edb93xx_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &edb93xx_flash_resource,
+};
+
+static void __init __edb93xx_register_flash(unsigned int width,
+			resource_size_t start, resource_size_t size)
+{
+	edb93xx_flash_data.width	= width;
+	edb93xx_flash_resource.start	= start;
+	edb93xx_flash_resource.end	= start + size - 1;
+
+	platform_device_register(&edb93xx_flash);
+}
+
+static void __init edb93xx_register_flash(void)
+{
+	if (machine_is_edb9307() || machine_is_edb9312() ||
+	    machine_is_edb9315()) {
+		__edb93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
+	} else {
+		__edb93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
+	}
+}
+
+static struct ep93xx_eth_data edb93xx_eth_data = {
+	.phy_id		= 1,
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_data[] = {
+	{
+		I2C_BOARD_INFO("isl1208", 0x6f),
+	},
+};
+
+static struct i2c_board_info __initdata edb93xx_i2c_data[] = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68),
+	},
+};
+
+static void __init edb93xx_register_i2c(void)
+{
+	if (machine_is_edb9302a() || machine_is_edb9307a() ||
+	    machine_is_edb9315a()) {
+		ep93xx_register_i2c(edb93xxa_i2c_data,
+				ARRAY_SIZE(edb93xxa_i2c_data));
+	} else if (machine_is_edb9307() || machine_is_edb9312() ||
+		   machine_is_edb9315()) {
+		ep93xx_register_i2c(edb93xx_i2c_data,
+				ARRAY_SIZE(edb93xx_i2c_data));
+	}
+}
+
+static void __init edb93xx_init_machine(void)
+{
+	ep93xx_init_devices();
+	edb93xx_register_flash();
+	ep93xx_register_eth(&edb93xx_eth_data, 1);
+	edb93xx_register_i2c();
+}
+
+
+#ifdef CONFIG_MACH_EDB9301
+MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9302
+MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
+	/* Maintainer: George Kashperko <george@chas.com.ua> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9302A
+MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9307
+MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
+	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9307A
+MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9312
+MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
+	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9315
+MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9315A
+MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= edb93xx_init_machine,
+MACHINE_END
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
+ */
+
+#ifndef __ASM_ARCH_EP93XX_KEYPAD_H
+#define __ASM_ARCH_EP93XX_KEYPAD_H
+
+#define MAX_MATRIX_KEY_ROWS		(8)
+#define MAX_MATRIX_KEY_COLS		(8)
+
+/* flags for the ep93xx_keypad driver */
+#define EP93XX_KEYPAD_DISABLE_3_KEY	(1<<0)	/* disable 3-key reset */
+#define EP93XX_KEYPAD_DIAG_MODE		(1<<1)	/* diagnostic mode */
+#define EP93XX_KEYPAD_BACK_DRIVE	(1<<2)	/* back driving mode */
+#define EP93XX_KEYPAD_TEST_MODE		(1<<3)	/* scan only column 0 */
+#define EP93XX_KEYPAD_KDIV		(1<<4)	/* 1/4 clock or 1/16 clock */
+#define EP93XX_KEYPAD_AUTOREPEAT	(1<<5)	/* enable key autorepeat */
+
+/**
+ * struct ep93xx_keypad_platform_data - platform specific device structure
+ * @matrix_key_rows:		number of rows in the keypad matrix
+ * @matrix_key_cols:		number of columns in the keypad matrix
+ * @matrix_key_map:		array of keycodes defining the keypad matrix
+ * @matrix_key_map_size:	ARRAY_SIZE(matrix_key_map)
+ * @debounce:			debounce start count; terminal count is 0xff
+ * @prescale:			row/column counter pre-scaler load value
+ * @flags:			see above
+ */
+struct ep93xx_keypad_platform_data {
+	unsigned int	matrix_key_rows;
+	unsigned int	matrix_key_cols;
+	unsigned int	*matrix_key_map;
+	int		matrix_key_map_size;
+	unsigned int	debounce;
+	unsigned int	prescale;
+	unsigned int	flags;
+};
+
+/* macro for creating the matrix_key_map table */
+#define KEY(row, col, val)	(((row) << 28) | ((col) << 24) | (val))
+
+#endif	/* __ASM_ARCH_EP93XX_KEYPAD_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -147,13 +147,27 @@
 #define EP93XX_PWM_BASE			(EP93XX_APB_VIRT_BASE + 0x00110000)
 
 #define EP93XX_RTC_BASE			(EP93XX_APB_VIRT_BASE + 0x00120000)
+#define EP93XX_RTC_PHYS_BASE		(EP93XX_APB_PHYS_BASE + 0x00120000)
 
 #define EP93XX_SYSCON_BASE		(EP93XX_APB_VIRT_BASE + 0x00130000)
 #define EP93XX_SYSCON_REG(x)		(EP93XX_SYSCON_BASE + (x))
 #define EP93XX_SYSCON_POWER_STATE	EP93XX_SYSCON_REG(0x00)
-#define EP93XX_SYSCON_CLOCK_CONTROL	EP93XX_SYSCON_REG(0x04)
-#define EP93XX_SYSCON_CLOCK_UARTBAUD	0x20000000
-#define EP93XX_SYSCON_CLOCK_USH_EN	0x10000000
+#define EP93XX_SYSCON_PWRCNT		EP93XX_SYSCON_REG(0x04)
+#define EP93XX_SYSCON_PWRCNT_FIR_EN	(1<<31)
+#define EP93XX_SYSCON_PWRCNT_UARTBAUD	(1<<29)
+#define EP93XX_SYSCON_PWRCNT_USH_EN	(1<<28)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2M1	(1<<27)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2M0	(1<<26)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P8	(1<<25)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P9	(1<<24)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P6	(1<<23)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P7	(1<<22)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P4	(1<<21)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P5	(1<<20)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P2	(1<<19)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P3	(1<<18)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P0	(1<<17)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P1	(1<<16)
 #define EP93XX_SYSCON_HALT		EP93XX_SYSCON_REG(0x08)
 #define EP93XX_SYSCON_STANDBY		EP93XX_SYSCON_REG(0x0c)
 #define EP93XX_SYSCON_CLOCK_SET1	EP93XX_SYSCON_REG(0x20)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/memory.h linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/memory.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/memory.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/memory.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,6 +5,12 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
+#if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)
 #define PHYS_OFFSET		UL(0x00000000)
+#elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)
+#define PHYS_OFFSET		UL(0xc0000000)
+#else
+#error "Kconfig bug: No EP93xx PHYS_OFFSET set"
+#endif
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/ts72xx.h linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/ts72xx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/include/mach/ts72xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/include/mach/ts72xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,9 +41,6 @@
 #define TS72XX_OPTIONS2_TS9420_BOOT	0x02
 
 
-#define TS72XX_NOR_PHYS_BASE		0x60000000
-#define TS72XX_NOR2_PHYS_BASE		0x62000000
-
 #define TS72XX_NAND1_DATA_PHYS_BASE	0x60000000
 #define TS72XX_NAND2_DATA_PHYS_BASE	0x70000000
 #define TS72XX_NAND_DATA_VIRT_BASE	0xfebfc000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -9,87 +9,135 @@
 
 comment "EP93xx Platforms"
 
+choice
+	prompt "EP93xx first SDRAM bank selection"
+	default EP93XX_SDCE3_SYNC_PHYS_OFFSET
+
+config EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	bool "0x00000000 - SDCE3/SyncBoot"
+	help
+	  Select this option if you want support for EP93xx boards with the
+	  first SDRAM bank at 0x00000000
+
+config EP93XX_SDCE0_PHYS_OFFSET
+	bool "0xc0000000 - SDCEO"
+	help
+	  Select this option if you want support for EP93xx boards with the
+	  first SDRAM bank at 0xc0000000
+
+endchoice
+
 config MACH_ADSSPHERE
 	bool "Support ADS Sphere"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
 	help
 	  Say 'Y' here if you want your kernel to support the ADS
 	  Sphere board.
 
+config MACH_EDB93XX
+	bool
+
+config MACH_EDB9301
+	bool "Support Cirrus Logic EDB9301"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9301 Evaluation Board.
+
 config MACH_EDB9302
 	bool "Support Cirrus Logic EDB9302"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_EDB93XX
 	help
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9302 Evaluation Board.
 
 config MACH_EDB9302A
 	bool "Support Cirrus Logic EDB9302A"
+	depends on EP93XX_SDCE0_PHYS_OFFSET
+	select MACH_EDB93XX
 	help
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9302A Evaluation Board.
 
 config MACH_EDB9307
 	bool "Support Cirrus Logic EDB9307"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_EDB93XX
 	help
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9307 Evaluation Board.
 
 config MACH_EDB9307A
 	bool "Support Cirrus Logic EDB9307A"
+	depends on EP93XX_SDCE0_PHYS_OFFSET
+	select MACH_EDB93XX
 	help
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9307A Evaluation Board.
 
 config MACH_EDB9312
 	bool "Support Cirrus Logic EDB9312"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_EDB93XX
 	help
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9312 Evaluation Board.
 
 config MACH_EDB9315
 	bool "Support Cirrus Logic EDB9315"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_EDB93XX
 	help
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9315 Evaluation Board.
 
 config MACH_EDB9315A
 	bool "Support Cirrus Logic EDB9315A"
+	depends on EP93XX_SDCE0_PHYS_OFFSET
+	select MACH_EDB93XX
 	help
 	  Say 'Y' here if you want your kernel to support the Cirrus
 	  Logic EDB9315A Evaluation Board.
 
 config MACH_GESBC9312
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
 	bool "Support Glomation GESBC-9312-sx"
 	help
 	  Say 'Y' here if you want your kernel to support the Glomation
 	  GESBC-9312-sx board.
 
 config MACH_MICRO9
-        bool
-        default n
+	bool
 
 config MACH_MICRO9H
-       bool "Support Contec Hypercontrol Micro9-H"
-       select MACH_MICRO9
-       help
-         Say 'Y' here if you want your kernel to support the
-         Contec Hypercontrol Micro9-H board.
+	bool "Support Contec Hypercontrol Micro9-H"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_MICRO9
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Contec Hypercontrol Micro9-H board.
 
 config MACH_MICRO9M
-       bool "Support Contec Hypercontrol Micro9-M"
-       select MACH_MICRO9
-       help
-         Say 'Y' here if you want your kernel to support the
-         Contec Hypercontrol Micro9-M board.
+	bool "Support Contec Hypercontrol Micro9-M"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_MICRO9
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Contec Hypercontrol Micro9-M board.
 
 config MACH_MICRO9L
-       bool "Support Contec Hypercontrol Micro9-L"
-       select MACH_MICRO9
-       help
-         Say 'Y' here if you want your kernel to support the
-         Contec Hypercontrol Micro9-L board.
+	bool "Support Contec Hypercontrol Micro9-L"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+	select MACH_MICRO9
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Contec Hypercontrol Micro9-L board.
 
 config MACH_TS72XX
 	bool "Support Technologic Systems TS-72xx SBC"
+	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Technologic Systems TS-72xx board.
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,13 +7,7 @@
 obj-			:=
 
 obj-$(CONFIG_MACH_ADSSPHERE)	+= adssphere.o
-obj-$(CONFIG_MACH_EDB9302)	+= edb9302.o
-obj-$(CONFIG_MACH_EDB9302A)	+= edb9302a.o
-obj-$(CONFIG_MACH_EDB9307)	+= edb9307.o
-obj-$(CONFIG_MACH_EDB9307A)	+= edb9307a.o
-obj-$(CONFIG_MACH_EDB9312)	+= edb9312.o
-obj-$(CONFIG_MACH_EDB9315)	+= edb9315.o
-obj-$(CONFIG_MACH_EDB9315A)	+= edb9315a.o
+obj-$(CONFIG_MACH_EDB93XX)	+= edb93xx.o
 obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o
 obj-$(CONFIG_MACH_MICRO9)	+= micro9.o
 obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/Makefile.boot linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/Makefile.boot
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/Makefile.boot	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/Makefile.boot	2009-09-09 18:13:59.000000000 -0400
@@ -1,2 +1,5 @@
-   zreladdr-y	:= 0x00008000
-params_phys-y	:= 0x00000100
+   zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	:= 0x00008000
+params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)	:= 0x00000100
+
+   zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		:= 0xc0008000
+params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)		:= 0xc0000100
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/ts72xx.c linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/ts72xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ep93xx/ts72xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ep93xx/ts72xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -112,13 +112,16 @@
 	}
 }
 
+/*************************************************************************
+ * NOR flash (TS-7200 only)
+ *************************************************************************/
 static struct physmap_flash_data ts72xx_flash_data = {
-	.width		= 1,
+	.width		= 2,
 };
 
 static struct resource ts72xx_flash_resource = {
-	.start		= TS72XX_NOR_PHYS_BASE,
-	.end		= TS72XX_NOR_PHYS_BASE + SZ_16M - 1,
+	.start		= EP93XX_CS6_PHYS_BASE,
+	.end		= EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
 	.flags		= IORESOURCE_MEM,
 };
 
@@ -132,6 +135,12 @@
 	.resource	= &ts72xx_flash_resource,
 };
 
+static void __init ts72xx_register_flash(void)
+{
+	if (board_is_ts7200())
+		platform_device_register(&ts72xx_flash);
+}
+
 static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
 {
 	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
@@ -165,8 +174,7 @@
 static void __init ts72xx_init_machine(void)
 {
 	ep93xx_init_devices();
-	if (board_is_ts7200())
-		platform_device_register(&ts72xx_flash);
+	ts72xx_register_flash();
 	platform_device_register(&ts72xx_rtc_device);
 
 	ep93xx_register_eth(&ts72xx_eth_data, 1);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,210 +0,0 @@
-/*
- *  Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * 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/device.h>
-#include <linux/list.h>
-#include <linux/math64.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-/*
- * Very simple approach: We can't disable clocks, so we do
- * not need refcounting
- */
-
-struct clk {
-	struct list_head node;
-	const char *name;
-	unsigned long (*get_rate)(void);
-};
-
-/*
- *  get the system pll clock in Hz
- *
- *                  mfi + mfn / (mfd +1)
- *  f = 2 * f_ref * --------------------
- *                        pd + 1
- */
-static unsigned long imx_decode_pll(unsigned int pll, u32 f_ref)
-{
-	unsigned long long ll;
-	unsigned long quot;
-
-	u32 mfi = (pll >> 10) & 0xf;
-	u32 mfn = pll & 0x3ff;
-	u32 mfd = (pll >> 16) & 0x3ff;
-	u32 pd =  (pll >> 26) & 0xf;
-
-	mfi = mfi <= 5 ? 5 : mfi;
-
-	ll = 2 * (unsigned long long)f_ref *
-		((mfi << 16) + (mfn << 16) / (mfd + 1));
-	quot = (pd + 1) * (1 << 16);
-	ll += quot / 2;
-	do_div(ll, quot);
-	return (unsigned long)ll;
-}
-
-static unsigned long imx_get_system_clk(void)
-{
-	u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
-
-	return imx_decode_pll(SPCTL0, f_ref);
-}
-
-static unsigned long imx_get_mcu_clk(void)
-{
-	return imx_decode_pll(MPCTL0, CLK32 * 512);
-}
-
-/*
- *  get peripheral clock 1 ( UART[12], Timer[12], PWM )
- */
-static unsigned long imx_get_perclk1(void)
-{
-	return imx_get_system_clk() / (((PCDR) & 0xf)+1);
-}
-
-/*
- *  get peripheral clock 2 ( LCD, SD, SPI[12] )
- */
-static unsigned long imx_get_perclk2(void)
-{
-	return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
-}
-
-/*
- *  get peripheral clock 3 ( SSI )
- */
-static unsigned long imx_get_perclk3(void)
-{
-	return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
-}
-
-/*
- *  get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
- */
-static unsigned long imx_get_hclk(void)
-{
-	return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
-}
-
-static struct clk clk_system_clk = {
-	.name = "system_clk",
-	.get_rate = imx_get_system_clk,
-};
-
-static struct clk clk_hclk = {
-	.name = "hclk",
-	.get_rate = imx_get_hclk,
-};
-
-static struct clk clk_mcu_clk = {
-	.name = "mcu_clk",
-	.get_rate = imx_get_mcu_clk,
-};
-
-static struct clk clk_perclk1 = {
-	.name = "perclk1",
-	.get_rate = imx_get_perclk1,
-};
-
-static struct clk clk_uart_clk = {
-	.name = "uart_clk",
-	.get_rate = imx_get_perclk1,
-};
-
-static struct clk clk_perclk2 = {
-	.name = "perclk2",
-	.get_rate = imx_get_perclk2,
-};
-
-static struct clk clk_perclk3 = {
-	.name = "perclk3",
-	.get_rate = imx_get_perclk3,
-};
-
-static struct clk *clks[] = {
-	&clk_perclk1,
-	&clk_perclk2,
-	&clk_perclk3,
-	&clk_system_clk,
-	&clk_hclk,
-	&clk_mcu_clk,
-	&clk_uart_clk,
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		if (!strcmp(p->name, id)) {
-			clk = p;
-			goto found;
-		}
-	}
-
-found:
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-int clk_enable(struct clk *clk)
-{
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return clk->get_rate();
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-int imx_clocks_init(void)
-{
-	int i;
-
-	mutex_lock(&clocks_mutex);
-	for (i = 0; i < ARRAY_SIZE(clks); i++)
-		list_add(&clks[i]->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-
-	return 0;
-}
-
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/cpufreq.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/cpufreq.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/cpufreq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,315 +0,0 @@
-/*
- * cpu.c: clock scaling for the iMX
- *
- * Copyright (C) 2000 2001, The Delft University of Technology
- * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
- * Copyright (C) 2006 Inky Lung <ilung@cwlinux.com>
- * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
- *
- * Based on SA1100 version written by:
- * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version
- * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
- *
- * 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
- *
- */
-
-/*#define DEBUG*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <asm/system.h>
-
-#include <mach/hardware.h>
-
-#include "generic.h"
-
-#ifndef __val2mfld
-#define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask))
-#endif
-#ifndef __mfld2val
-#define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1)))
-#endif
-
-#define CR_920T_CLOCK_MODE	0xC0000000
-#define CR_920T_FASTBUS_MODE	0x00000000
-#define CR_920T_ASYNC_MODE	0xC0000000
-
-static u32 mpctl0_at_boot;
-static u32 bclk_div_at_boot;
-
-static struct clk *system_clk, *mcu_clk;
-
-static void imx_set_async_mode(void)
-{
-	adjust_cr(CR_920T_CLOCK_MODE, CR_920T_ASYNC_MODE);
-}
-
-static void imx_set_fastbus_mode(void)
-{
-	adjust_cr(CR_920T_CLOCK_MODE, CR_920T_FASTBUS_MODE);
-}
-
-static void imx_set_mpctl0(u32 mpctl0)
-{
-	unsigned long flags;
-
-	if (mpctl0 == 0) {
-		local_irq_save(flags);
-		CSCR &= ~CSCR_MPEN;
-		local_irq_restore(flags);
-		return;
-	}
-
-	local_irq_save(flags);
-	MPCTL0 = mpctl0;
-	CSCR |= CSCR_MPEN;
-	local_irq_restore(flags);
-}
-
-/**
- * imx_compute_mpctl - compute new PLL parameters
- * @new_mpctl:	pointer to location assigned by new PLL control register value
- * @cur_mpctl:	current PLL control register parameters
- * @f_ref:	reference source frequency Hz
- * @freq:	required frequency in Hz
- * @relation:	is one of %CPUFREQ_RELATION_L (supremum)
- *		and %CPUFREQ_RELATION_H (infimum)
- */
-long imx_compute_mpctl(u32 *new_mpctl, u32 cur_mpctl, u32 f_ref, unsigned long freq, int relation)
-{
-        u32 mfi;
-        u32 mfn;
-        u32 mfd;
-        u32 pd;
-	unsigned long long ll;
-	long l;
-	long quot;
-
-	/* Fdppl=2*Fref*(MFI+MFN/(MFD+1))/(PD+1) */
-	/*  PD=<0,15>, MFD=<1,1023>, MFI=<5,15> MFN=<0,1022> */
-
-	if (cur_mpctl) {
-		mfd = ((cur_mpctl >> 16) & 0x3ff) + 1;
-		pd =  ((cur_mpctl >> 26) & 0xf) + 1;
-	} else {
-		pd=2; mfd=313;
-	}
-
-	/* pd=2; mfd=313; mfi=8; mfn=183; */
-	/* (MFI+MFN/(MFD)) = Fdppl / (2*Fref) * (PD); */
-
-	quot = (f_ref + (1 << 9)) >> 10;
-	l = (freq * pd + quot) / (2 * quot);
-	mfi = l >> 10;
-	mfn = ((l & ((1 << 10) - 1)) * mfd + (1 << 9)) >> 10;
-
-	mfd -= 1;
-	pd -= 1;
-
-	*new_mpctl = ((mfi & 0xf) << 10) | (mfn & 0x3ff) | ((mfd & 0x3ff) << 16)
-		| ((pd & 0xf) << 26);
-
-	ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) );
-	quot = (pd+1) * (1<<16);
-	ll += quot / 2;
-	do_div(ll, quot);
-	freq = ll;
-
-	pr_debug(KERN_DEBUG "imx: new PLL parameters pd=%d mfd=%d mfi=%d mfn=%d, freq=%ld\n",
-		pd, mfd, mfi, mfn, freq);
-
-	return freq;
-}
-
-
-static int imx_verify_speed(struct cpufreq_policy *policy)
-{
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
-
-	return 0;
-}
-
-static unsigned int imx_get_speed(unsigned int cpu)
-{
-	unsigned int freq;
-	unsigned int cr;
-	unsigned int cscr;
-	unsigned int bclk_div;
-
-	if (cpu)
-		return 0;
-
-	cscr = CSCR;
-	bclk_div = __mfld2val(CSCR_BCLK_DIV, cscr) + 1;
-	cr = get_cr();
-
-	if((cr & CR_920T_CLOCK_MODE) == CR_920T_FASTBUS_MODE) {
-		freq = clk_get_rate(system_clk);
-		freq = (freq + bclk_div/2) / bclk_div;
-	} else {
-		freq = clk_get_rate(mcu_clk);
-		if (cscr & CSCR_MPU_PRESC)
-			freq /= 2;
-	}
-
-	freq = (freq + 500) / 1000;
-
-	return freq;
-}
-
-static int imx_set_target(struct cpufreq_policy *policy,
-			  unsigned int target_freq,
-			  unsigned int relation)
-{
-	struct cpufreq_freqs freqs;
-	u32 mpctl0 = 0;
-	u32 cscr;
-	unsigned long flags;
-	long freq;
-	long sysclk;
-	unsigned int bclk_div = bclk_div_at_boot;
-
-	/*
-	 * Some governors do not respects CPU and policy lower limits
-	 * which leads to bad things (division by zero etc), ensure
-	 * that such things do not happen.
-	 */
-	if(target_freq < policy->cpuinfo.min_freq)
-		target_freq = policy->cpuinfo.min_freq;
-
-	if(target_freq < policy->min)
-		target_freq = policy->min;
-
-	freq = target_freq * 1000;
-
-	pr_debug(KERN_DEBUG "imx: requested frequency %ld Hz, mpctl0 at boot 0x%08x\n",
-			freq, mpctl0_at_boot);
-
-	sysclk = clk_get_rate(system_clk);
-
-	if (freq > sysclk / bclk_div_at_boot + 1000000) {
-		freq = imx_compute_mpctl(&mpctl0, mpctl0_at_boot, CLK32 * 512, freq, relation);
-		if (freq < 0) {
-			printk(KERN_WARNING "imx: target frequency %ld Hz cannot be set\n", freq);
-			return -EINVAL;
-		}
-	} else {
-		if(freq + 1000 < sysclk) {
-			if (relation == CPUFREQ_RELATION_L)
-				bclk_div = (sysclk - 1000) / freq;
-			else
-				bclk_div = (sysclk + freq + 1000) / freq;
-
-			if(bclk_div > 16)
-				bclk_div = 16;
-			if(bclk_div < bclk_div_at_boot)
-				bclk_div = bclk_div_at_boot;
-		}
-		freq = (sysclk + bclk_div / 2) / bclk_div;
-	}
-
-	freqs.old = imx_get_speed(0);
-	freqs.new = (freq + 500) / 1000;
-	freqs.cpu = 0;
-	freqs.flags = 0;
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	local_irq_save(flags);
-
-	imx_set_fastbus_mode();
-
-	imx_set_mpctl0(mpctl0);
-
-	cscr = CSCR;
-	cscr &= ~CSCR_BCLK_DIV;
-	cscr |= __val2mfld(CSCR_BCLK_DIV, bclk_div - 1);
-	CSCR = cscr;
-
-	if(mpctl0) {
-		CSCR |= CSCR_MPLL_RESTART;
-
-		/* Wait until MPLL is stabilized */
-		while( CSCR & CSCR_MPLL_RESTART );
-
-		imx_set_async_mode();
-	}
-
-	local_irq_restore(flags);
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	pr_debug(KERN_INFO "imx: set frequency %ld Hz, running from %s\n",
-			freq, mpctl0? "MPLL": "SPLL");
-
-	return 0;
-}
-
-static int __init imx_cpufreq_driver_init(struct cpufreq_policy *policy)
-{
-	printk(KERN_INFO "i.MX cpu freq change driver v1.0\n");
-
-	if (policy->cpu != 0)
-		return -EINVAL;
-
-	policy->cur = policy->min = policy->max = imx_get_speed(0);
-	policy->cpuinfo.min_freq = 8000;
-	policy->cpuinfo.max_freq = 200000;
-	 /* Manual states, that PLL stabilizes in two CLK32 periods */
-	policy->cpuinfo.transition_latency = 4 * 1000000000LL / CLK32;
-	return 0;
-}
-
-static struct cpufreq_driver imx_driver = {
-	.flags		= CPUFREQ_STICKY,
-	.verify		= imx_verify_speed,
-	.target		= imx_set_target,
-	.get		= imx_get_speed,
-	.init		= imx_cpufreq_driver_init,
-	.name		= "imx",
-};
-
-static int __init imx_cpufreq_init(void)
-{
-	bclk_div_at_boot = __mfld2val(CSCR_BCLK_DIV, CSCR) + 1;
-	mpctl0_at_boot = 0;
-
-	system_clk = clk_get(NULL, "system_clk");
-	if (IS_ERR(system_clk))
-		return PTR_ERR(system_clk);
-
-	mcu_clk = clk_get(NULL, "mcu_clk");
-	if (IS_ERR(mcu_clk)) {
-		clk_put(system_clk);
-		return PTR_ERR(mcu_clk);
-	}
-
-	if((CSCR & CSCR_MPEN) &&
-	   ((get_cr() & CR_920T_CLOCK_MODE) != CR_920T_FASTBUS_MODE))
-		mpctl0_at_boot = MPCTL0;
-
-	return cpufreq_register_driver(&imx_driver);
-}
-
-arch_initcall(imx_cpufreq_init);
-
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/dma.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,597 +0,0 @@
-/*
- *  linux/arch/arm/mach-imx/dma.c
- *
- *  imx DMA registration and IRQ dispatching
- *
- *  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.
- *
- *  2004-03-03 Sascha Hauer <sascha@saschahauer.de>
- *             initial version heavily inspired by
- *             linux/arch/arm/mach-pxa/dma.c
- *
- *  2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
- *             Changed to support scatter gather DMA
- *             by taking Russell's code from RiscPC
- *
- *  2006-05-31 Pavel Pisa <pisa@cmp.felk.cvut.cz>
- *             Corrected error handling code.
- *
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-
-#include <asm/scatterlist.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-#include <mach/imx-dma.h>
-
-struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
-
-/*
- * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
- * @dma_ch: i.MX DMA channel number
- * @lastcount: number of bytes transferred during last transfer
- *
- * Functions prepares DMA controller for next sg data chunk transfer.
- * The @lastcount argument informs function about number of bytes transferred
- * during last block. Zero value can be used for @lastcount to setup DMA
- * for the first chunk.
- */
-static inline int imx_dma_sg_next(imx_dmach_t dma_ch, unsigned int lastcount)
-{
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-	unsigned int nextcount;
-	unsigned int nextaddr;
-
-	if (!imxdma->name) {
-		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
-		       __func__, dma_ch);
-		return 0;
-	}
-
-	imxdma->resbytes -= lastcount;
-
-	if (!imxdma->sg) {
-		pr_debug("imxdma%d: no sg data\n", dma_ch);
-		return 0;
-	}
-
-	imxdma->sgbc += lastcount;
-	if ((imxdma->sgbc >= imxdma->sg->length) || !imxdma->resbytes) {
-		if ((imxdma->sgcount <= 1) || !imxdma->resbytes) {
-			pr_debug("imxdma%d: sg transfer limit reached\n",
-				 dma_ch);
-			imxdma->sgcount=0;
-			imxdma->sg = NULL;
-			return 0;
-		} else {
-			imxdma->sgcount--;
-			imxdma->sg++;
-			imxdma->sgbc = 0;
-		}
-	}
-	nextcount = imxdma->sg->length - imxdma->sgbc;
-	nextaddr = imxdma->sg->dma_address + imxdma->sgbc;
-
-	if(imxdma->resbytes < nextcount)
-		nextcount = imxdma->resbytes;
-
-	if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
-		DAR(dma_ch) = nextaddr;
-	else
-		SAR(dma_ch) = nextaddr;
-
-	CNTR(dma_ch) = nextcount;
-	pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, size 0x%08x\n",
-		 dma_ch, DAR(dma_ch), SAR(dma_ch), CNTR(dma_ch));
-
-	return nextcount;
-}
-
-/*
- * imx_dma_setup_sg_base - scatter-gather DMA emulation
- * @dma_ch: i.MX DMA channel number
- * @sg: pointer to the scatter-gather list/vector
- * @sgcount: scatter-gather list hungs count
- *
- * Functions sets up i.MX DMA state for emulated scatter-gather transfer
- * and sets up channel registers to be ready for the first chunk
- */
-static int
-imx_dma_setup_sg_base(imx_dmach_t dma_ch,
-		      struct scatterlist *sg, unsigned int sgcount)
-{
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-
-	imxdma->sg = sg;
-	imxdma->sgcount = sgcount;
-	imxdma->sgbc = 0;
-	return imx_dma_sg_next(dma_ch, 0);
-}
-
-/**
- * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from device transfer
- * @dma_ch: i.MX DMA channel number
- * @dma_address: the DMA/physical memory address of the linear data block
- *		to transfer
- * @dma_length: length of the data block in bytes
- * @dev_addr: physical device port address
- * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
- *           or %DMA_MODE_WRITE from memory to the device
- *
- * The function setups DMA channel source and destination addresses for transfer
- * specified by provided parameters. The scatter-gather emulation is disabled,
- * because linear data block
- * form the physical address range is transferred.
- * Return value: if incorrect parameters are provided -%EINVAL.
- *		Zero indicates success.
- */
-int
-imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
-		     unsigned int dma_length, unsigned int dev_addr,
-		     unsigned int dmamode)
-{
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-
-	imxdma->sg = NULL;
-	imxdma->sgcount = 0;
-	imxdma->dma_mode = dmamode;
-	imxdma->resbytes = dma_length;
-
-	if (!dma_address) {
-		printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n",
-		       dma_ch);
-		return -EINVAL;
-	}
-
-	if (!dma_length) {
-		printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n",
-		       dma_ch);
-		return -EINVAL;
-	}
-
-	if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
-		pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for read\n",
-			dma_ch, (unsigned int)dma_address, dma_length,
-			dev_addr);
-		SAR(dma_ch) = dev_addr;
-		DAR(dma_ch) = (unsigned int)dma_address;
-	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
-		pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for write\n",
-			dma_ch, (unsigned int)dma_address, dma_length,
-			dev_addr);
-		SAR(dma_ch) = (unsigned int)dma_address;
-		DAR(dma_ch) = dev_addr;
-	} else {
-		printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
-		       dma_ch);
-		return -EINVAL;
-	}
-
-	CNTR(dma_ch) = dma_length;
-
-	return 0;
-}
-
-/**
- * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer
- * @dma_ch: i.MX DMA channel number
- * @sg: pointer to the scatter-gather list/vector
- * @sgcount: scatter-gather list hungs count
- * @dma_length: total length of the transfer request in bytes
- * @dev_addr: physical device port address
- * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
- *           or %DMA_MODE_WRITE from memory to the device
- *
- * The function sets up DMA channel state and registers to be ready for transfer
- * specified by provided parameters. The scatter-gather emulation is set up
- * according to the parameters.
- *
- * The full preparation of the transfer requires setup of more register
- * by the caller before imx_dma_enable() can be called.
- *
- * %BLR(dma_ch) holds transfer burst length in bytes, 0 means 64 bytes
- *
- * %RSSR(dma_ch) has to be set to the DMA request line source %DMA_REQ_xxx
- *
- * %CCR(dma_ch) has to specify transfer parameters, the next settings is typical
- * for linear or simple scatter-gather transfers if %DMA_MODE_READ is specified
- *
- * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x
- *
- * The typical setup for %DMA_MODE_WRITE is specified by next options combination
- *
- * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
- *
- * Be careful here and do not mistakenly mix source and target device
- * port sizes constants, they are really different:
- * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
- * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
- *
- * Return value: if incorrect parameters are provided -%EINVAL.
- * Zero indicates success.
- */
-int
-imx_dma_setup_sg(imx_dmach_t dma_ch,
-		 struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
-		 unsigned int dev_addr, unsigned int dmamode)
-{
-	int res;
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-
-	imxdma->sg = NULL;
-	imxdma->sgcount = 0;
-	imxdma->dma_mode = dmamode;
-	imxdma->resbytes = dma_length;
-
-	if (!sg || !sgcount) {
-		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n",
-		       dma_ch);
-		return -EINVAL;
-	}
-
-	if (!sg->length) {
-		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n",
-		       dma_ch);
-		return -EINVAL;
-	}
-
-	if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
-		pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for read\n",
-			dma_ch, sg, sgcount, dma_length, dev_addr);
-		SAR(dma_ch) = dev_addr;
-	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
-		pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for write\n",
-			dma_ch, sg, sgcount, dma_length, dev_addr);
-		DAR(dma_ch) = dev_addr;
-	} else {
-		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
-		       dma_ch);
-		return -EINVAL;
-	}
-
-	res = imx_dma_setup_sg_base(dma_ch, sg, sgcount);
-	if (res <= 0) {
-		printk(KERN_ERR "imxdma%d: no sg chunk ready\n", dma_ch);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification handlers
- * @dma_ch: i.MX DMA channel number
- * @irq_handler: the pointer to the function called if the transfer
- *		ends successfully
- * @err_handler: the pointer to the function called if the premature
- *		end caused by error occurs
- * @data: user specified value to be passed to the handlers
- */
-int
-imx_dma_setup_handlers(imx_dmach_t dma_ch,
-		       void (*irq_handler) (int, void *),
-		       void (*err_handler) (int, void *, int),
-		       void *data)
-{
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-	unsigned long flags;
-
-	if (!imxdma->name) {
-		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
-		       __func__, dma_ch);
-		return -ENODEV;
-	}
-
-	local_irq_save(flags);
-	DISR = (1 << dma_ch);
-	imxdma->irq_handler = irq_handler;
-	imxdma->err_handler = err_handler;
-	imxdma->data = data;
-	local_irq_restore(flags);
-	return 0;
-}
-
-/**
- * imx_dma_enable - function to start i.MX DMA channel operation
- * @dma_ch: i.MX DMA channel number
- *
- * The channel has to be allocated by driver through imx_dma_request()
- * or imx_dma_request_by_prio() function.
- * The transfer parameters has to be set to the channel registers through
- * call of the imx_dma_setup_single() or imx_dma_setup_sg() function
- * and registers %BLR(dma_ch), %RSSR(dma_ch) and %CCR(dma_ch) has to
- * be set prior this function call by the channel user.
- */
-void imx_dma_enable(imx_dmach_t dma_ch)
-{
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-	unsigned long flags;
-
-	pr_debug("imxdma%d: imx_dma_enable\n", dma_ch);
-
-	if (!imxdma->name) {
-		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
-		       __func__, dma_ch);
-		return;
-	}
-
-	local_irq_save(flags);
-	DISR = (1 << dma_ch);
-	DIMR &= ~(1 << dma_ch);
-	CCR(dma_ch) |= CCR_CEN;
-	local_irq_restore(flags);
-}
-
-/**
- * imx_dma_disable - stop, finish i.MX DMA channel operatin
- * @dma_ch: i.MX DMA channel number
- */
-void imx_dma_disable(imx_dmach_t dma_ch)
-{
-	unsigned long flags;
-
-	pr_debug("imxdma%d: imx_dma_disable\n", dma_ch);
-
-	local_irq_save(flags);
-	DIMR |= (1 << dma_ch);
-	CCR(dma_ch) &= ~CCR_CEN;
-	DISR = (1 << dma_ch);
-	local_irq_restore(flags);
-}
-
-/**
- * imx_dma_request - request/allocate specified channel number
- * @dma_ch: i.MX DMA channel number
- * @name: the driver/caller own non-%NULL identification
- */
-int imx_dma_request(imx_dmach_t dma_ch, const char *name)
-{
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-	unsigned long flags;
-
-	/* basic sanity checks */
-	if (!name)
-		return -EINVAL;
-
-	if (dma_ch >= IMX_DMA_CHANNELS) {
-		printk(KERN_CRIT "%s: called for  non-existed channel %d\n",
-		       __func__, dma_ch);
-		return -EINVAL;
-	}
-
-	local_irq_save(flags);
-	if (imxdma->name) {
-		local_irq_restore(flags);
-		return -ENODEV;
-	}
-
-	imxdma->name = name;
-	imxdma->irq_handler = NULL;
-	imxdma->err_handler = NULL;
-	imxdma->data = NULL;
-	imxdma->sg = NULL;
-	local_irq_restore(flags);
-	return 0;
-}
-
-/**
- * imx_dma_free - release previously acquired channel
- * @dma_ch: i.MX DMA channel number
- */
-void imx_dma_free(imx_dmach_t dma_ch)
-{
-	unsigned long flags;
-	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
-
-	if (!imxdma->name) {
-		printk(KERN_CRIT
-		       "%s: trying to free channel %d which is already freed\n",
-		       __func__, dma_ch);
-		return;
-	}
-
-	local_irq_save(flags);
-	/* Disable interrupts */
-	DIMR |= (1 << dma_ch);
-	CCR(dma_ch) &= ~CCR_CEN;
-	imxdma->name = NULL;
-	local_irq_restore(flags);
-}
-
-/**
- * imx_dma_request_by_prio - find and request some of free channels best suiting requested priority
- * @name: the driver/caller own non-%NULL identification
- * @prio: one of the hardware distinguished priority level:
- *        %DMA_PRIO_HIGH, %DMA_PRIO_MEDIUM, %DMA_PRIO_LOW
- *
- * This function tries to find free channel in the specified priority group
- * if the priority cannot be achieved it tries to look for free channel
- * in the higher and then even lower priority groups.
- *
- * Return value: If there is no free channel to allocate, -%ENODEV is returned.
- *               On successful allocation channel is returned.
- */
-imx_dmach_t imx_dma_request_by_prio(const char *name, imx_dma_prio prio)
-{
-	int i;
-	int best;
-
-	switch (prio) {
-	case (DMA_PRIO_HIGH):
-		best = 8;
-		break;
-	case (DMA_PRIO_MEDIUM):
-		best = 4;
-		break;
-	case (DMA_PRIO_LOW):
-	default:
-		best = 0;
-		break;
-	}
-
-	for (i = best; i < IMX_DMA_CHANNELS; i++) {
-		if (!imx_dma_request(i, name)) {
-			return i;
-		}
-	}
-
-	for (i = best - 1; i >= 0; i--) {
-		if (!imx_dma_request(i, name)) {
-			return i;
-		}
-	}
-
-	printk(KERN_ERR "%s: no free DMA channel found\n", __func__);
-
-	return -ENODEV;
-}
-
-static irqreturn_t dma_err_handler(int irq, void *dev_id)
-{
-	int i, disr = DISR;
-	struct imx_dma_channel *channel;
-	unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
-	int errcode;
-
-	DISR = disr & err_mask;
-	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
-		if(!(err_mask & (1 << i)))
-			continue;
-		channel = &imx_dma_channels[i];
-		errcode = 0;
-
-		if (DBTOSR & (1 << i)) {
-			DBTOSR = (1 << i);
-			errcode |= IMX_DMA_ERR_BURST;
-		}
-		if (DRTOSR & (1 << i)) {
-			DRTOSR = (1 << i);
-			errcode |= IMX_DMA_ERR_REQUEST;
-		}
-		if (DSESR & (1 << i)) {
-			DSESR = (1 << i);
-			errcode |= IMX_DMA_ERR_TRANSFER;
-		}
-		if (DBOSR & (1 << i)) {
-			DBOSR = (1 << i);
-			errcode |= IMX_DMA_ERR_BUFFER;
-		}
-
-		/*
-		 * The cleaning of @sg field would be questionable
-		 * there, because its value can help to compute
-		 * remaining/transferred bytes count in the handler
-		 */
-		/*imx_dma_channels[i].sg = NULL;*/
-
-		if (channel->name && channel->err_handler) {
-			channel->err_handler(i, channel->data, errcode);
-			continue;
-		}
-
-		imx_dma_channels[i].sg = NULL;
-
-		printk(KERN_WARNING
-		       "DMA timeout on channel %d (%s) -%s%s%s%s\n",
-		       i, channel->name,
-		       errcode&IMX_DMA_ERR_BURST?    " burst":"",
-		       errcode&IMX_DMA_ERR_REQUEST?  " request":"",
-		       errcode&IMX_DMA_ERR_TRANSFER? " transfer":"",
-		       errcode&IMX_DMA_ERR_BUFFER?   " buffer":"");
-	}
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t dma_irq_handler(int irq, void *dev_id)
-{
-	int i, disr = DISR;
-
-	pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
-		     disr);
-
-	DISR = disr;
-	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
-		if (disr & (1 << i)) {
-			struct imx_dma_channel *channel = &imx_dma_channels[i];
-			if (channel->name) {
-				if (imx_dma_sg_next(i, CNTR(i))) {
-					CCR(i) &= ~CCR_CEN;
-					mb();
-					CCR(i) |= CCR_CEN;
-				} else {
-					if (channel->irq_handler)
-						channel->irq_handler(i,
-							channel->data);
-				}
-			} else {
-				/*
-				 * IRQ for an unregistered DMA channel:
-				 * let's clear the interrupts and disable it.
-				 */
-				printk(KERN_WARNING
-				       "spurious IRQ for DMA channel %d\n", i);
-			}
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-static int __init imx_dma_init(void)
-{
-	int ret;
-	int i;
-
-	/* reset DMA module */
-	DCR = DCR_DRST;
-
-	ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
-	if (ret) {
-		printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-		return ret;
-	}
-
-	ret = request_irq(DMA_ERR, dma_err_handler, 0, "DMA", NULL);
-	if (ret) {
-		printk(KERN_CRIT "Wow!  Can't register ERRIRQ for DMA\n");
-		free_irq(DMA_INT, NULL);
-	}
-
-	/* enable DMA module */
-	DCR = DCR_DEN;
-
-	/* clear all interrupts */
-	DISR = (1 << IMX_DMA_CHANNELS) - 1;
-
-	/* enable interrupts */
-	DIMR = (1 << IMX_DMA_CHANNELS) - 1;
-
-	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
-		imx_dma_channels[i].sg = NULL;
-		imx_dma_channels[i].dma_num = i;
-	}
-
-	return ret;
-}
-
-arch_initcall(imx_dma_init);
-
-EXPORT_SYMBOL(imx_dma_setup_single);
-EXPORT_SYMBOL(imx_dma_setup_sg);
-EXPORT_SYMBOL(imx_dma_setup_handlers);
-EXPORT_SYMBOL(imx_dma_enable);
-EXPORT_SYMBOL(imx_dma_disable);
-EXPORT_SYMBOL(imx_dma_request);
-EXPORT_SYMBOL(imx_dma_free);
-EXPORT_SYMBOL(imx_dma_request_by_prio);
-EXPORT_SYMBOL(imx_dma_channels);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/generic.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/generic.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/generic.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,271 +0,0 @@
-/*
- *  arch/arm/mach-imx/generic.c
- *
- *  author: Sascha Hauer
- *  Created: april 20th, 2004
- *  Copyright: Synertronixx GmbH
- *
- *  Common code for i.MX machines
- *
- * 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/platform_device.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/errno.h>
-#include <mach/hardware.h>
-#include <mach/imx-regs.h>
-
-#include <asm/mach/map.h>
-#include <mach/mmc.h>
-#include <mach/gpio.h>
-
-unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
-
-void imx_gpio_mode(int gpio_mode)
-{
-	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
-	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
-	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
-	unsigned int tmp;
-
-	/* Pullup enable */
-	if(gpio_mode & GPIO_PUEN)
-		PUEN(port) |= (1<<pin);
-	else
-		PUEN(port) &= ~(1<<pin);
-
-	/* Data direction */
-	if(gpio_mode & GPIO_OUT)
-		DDIR(port) |= 1<<pin;
-	else
-		DDIR(port) &= ~(1<<pin);
-
-	/* Primary / alternate function */
-	if(gpio_mode & GPIO_AF)
-		GPR(port) |= (1<<pin);
-	else
-		GPR(port) &= ~(1<<pin);
-
-	/* use as gpio? */
-	if(gpio_mode &  GPIO_GIUS)
-		GIUS(port) |= (1<<pin);
-	else
-		GIUS(port) &= ~(1<<pin);
-
-	/* Output / input configuration */
-	/* FIXME: I'm not very sure about OCR and ICONF, someone
-	 * should have a look over it
-	 */
-	if(pin<16) {
-		tmp = OCR1(port);
-		tmp &= ~( 3<<(pin*2));
-		tmp |= (ocr << (pin*2));
-		OCR1(port) = tmp;
-
-		ICONFA1(port) &= ~( 3<<(pin*2));
-		ICONFA1(port) |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << (pin * 2);
-		ICONFB1(port) &= ~( 3<<(pin*2));
-		ICONFB1(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << (pin * 2);
-	} else {
-		tmp = OCR2(port);
-		tmp &= ~( 3<<((pin-16)*2));
-		tmp |= (ocr << ((pin-16)*2));
-		OCR2(port) = tmp;
-
-		ICONFA2(port) &= ~( 3<<((pin-16)*2));
-		ICONFA2(port) |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << ((pin-16) * 2);
-		ICONFB2(port) &= ~( 3<<((pin-16)*2));
-		ICONFB2(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << ((pin-16) * 2);
-	}
-}
-
-EXPORT_SYMBOL(imx_gpio_mode);
-
-int imx_gpio_request(unsigned gpio, const char *label)
-{
-	if(gpio >= (GPIO_PORT_MAX + 1) * 32) {
-		printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
-			gpio, label ? label : "?");
-		return -EINVAL;
-	}
-
-	if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
-		printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
-			gpio, label ? label : "?");
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-EXPORT_SYMBOL(imx_gpio_request);
-
-void imx_gpio_free(unsigned gpio)
-{
-	if(gpio >= (GPIO_PORT_MAX + 1) * 32)
-		return;
-
-	clear_bit(gpio, imx_gpio_alloc_map);
-}
-
-EXPORT_SYMBOL(imx_gpio_free);
-
-int imx_gpio_direction_input(unsigned gpio)
-{
-	imx_gpio_mode(gpio | GPIO_IN | GPIO_GIUS | GPIO_DR);
-	return 0;
-}
-
-EXPORT_SYMBOL(imx_gpio_direction_input);
-
-int imx_gpio_direction_output(unsigned gpio, int value)
-{
-	imx_gpio_set_value(gpio, value);
-	imx_gpio_mode(gpio | GPIO_OUT | GPIO_GIUS | GPIO_DR);
-	return 0;
-}
-
-EXPORT_SYMBOL(imx_gpio_direction_output);
-
-int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
-				int alloc_mode, const char *label)
-{
-	const int *p = pin_list;
-	int i;
-	unsigned gpio;
-	unsigned mode;
-
-	for (i = 0; i < count; i++) {
-		gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-		mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
-
-		if (gpio >= (GPIO_PORT_MAX + 1) * 32)
-			goto setup_error;
-
-		if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
-			imx_gpio_free(gpio);
-		else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
-			if (imx_gpio_request(gpio, label))
-				if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
-					goto setup_error;
-
-		if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
-				    IMX_GPIO_ALLOC_MODE_RELEASE)))
-			imx_gpio_mode(gpio | mode);
-
-		p++;
-	}
-	return 0;
-
-setup_error:
-	if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
-		         IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
-		return -EINVAL;
-
-	while (p != pin_list) {
-		p--;
-		gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-		imx_gpio_free(gpio);
-	}
-
-	return -EINVAL;
-}
-
-EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
-
-void __imx_gpio_set_value(unsigned gpio, int value)
-{
-	imx_gpio_set_value_inline(gpio, value);
-}
-
-EXPORT_SYMBOL(__imx_gpio_set_value);
-
-int imx_gpio_to_irq(unsigned gpio)
-{
-	return IRQ_GPIOA(0) + gpio;
-}
-
-EXPORT_SYMBOL(imx_gpio_to_irq);
-
-int imx_irq_to_gpio(unsigned irq)
-{
-	if (irq < IRQ_GPIOA(0))
-		return -EINVAL;
-	return irq - IRQ_GPIOA(0);
-}
-
-EXPORT_SYMBOL(imx_irq_to_gpio);
-
-static struct resource imx_mmc_resources[] = {
-	[0] = {
-		.start	= 0x00214000,
-		.end	= 0x002140FF,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= (SDHC_INT),
-		.end	= (SDHC_INT),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 imxmmmc_dmamask = 0xffffffffUL;
-
-static struct platform_device imx_mmc_device = {
-	.name		= "imx-mmc",
-	.id		= 0,
-	.dev		= {
-		.dma_mask = &imxmmmc_dmamask,
-		.coherent_dma_mask = 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(imx_mmc_resources),
-	.resource	= imx_mmc_resources,
-};
-
-void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
-{
-	imx_mmc_device.dev.platform_data = info;
-}
-
-static struct platform_device *devices[] __initdata = {
-	&imx_mmc_device,
-};
-
-static struct map_desc imx_io_desc[] __initdata = {
-	{
-		.virtual	= IMX_IO_BASE,
-		.pfn		= __phys_to_pfn(IMX_IO_PHYS),
-		.length		= IMX_IO_SIZE,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init
-imx_map_io(void)
-{
-	iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
-}
-
-static int __init imx_init(void)
-{
-	return platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-subsys_initcall(imx_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/generic.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/generic.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/generic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/generic.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- *  linux/arch/arm/mach-imx/generic.h
- *
- * Author:	Sascha Hauer <sascha@saschahauer.de>
- * Copyright:	Synertronixx GmbH
- *
- * 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.
- */
-
-extern void __init imx_map_io(void);
-extern void __init imx_init_irq(void);
-
-struct sys_timer;
-extern struct sys_timer imx_timer;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/debug-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/debug-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/debug-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/* arch/arm/mach-imx/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * 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.
- *
-*/
-
-		.macro	addruart,rx
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1			@ MMU enabled?
-		moveq	\rx, #0x00000000	@ physical
-		movne	\rx, #0xe0000000	@ virtual
-		orreq	\rx, \rx, #0x00200000	@ physical
-		orr	\rx, \rx, #0x00006000	@ UART1 offset
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0x40]	@ TXDATA
-		.endm
-
-		.macro	waituart,rd,rx
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #0x98]	@ SR2
-		tst	\rd, #1 << 3		@ TXDC
-		beq	1002b			@ wait until transmit done
-		.endm
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/dma.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/dma.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- *  linux/include/asm-arm/imxads/dma.h
- *
- *  Copyright (C) 1997,1998 Russell King
- *
- * 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 __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-typedef enum {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 1,
-	DMA_PRIO_LOW = 2
-} imx_dma_prio;
-
-#define DMA_REQ_UART3_T        2
-#define DMA_REQ_UART3_R        3
-#define DMA_REQ_SSI2_T         4
-#define DMA_REQ_SSI2_R         5
-#define DMA_REQ_CSI_STAT       6
-#define DMA_REQ_CSI_R          7
-#define DMA_REQ_MSHC           8
-#define DMA_REQ_DSPA_DCT_DOUT  9
-#define DMA_REQ_DSPA_DCT_DIN  10
-#define DMA_REQ_DSPA_MAC      11
-#define DMA_REQ_EXT           12
-#define DMA_REQ_SDHC          13
-#define DMA_REQ_SPI1_R        14
-#define DMA_REQ_SPI1_T        15
-#define DMA_REQ_SSI_T         16
-#define DMA_REQ_SSI_R         17
-#define DMA_REQ_ASP_DAC       18
-#define DMA_REQ_ASP_ADC       19
-#define DMA_REQ_USP_EP(x)    (20+(x))
-#define DMA_REQ_SPI2_R        26
-#define DMA_REQ_SPI2_T        27
-#define DMA_REQ_UART2_T       28
-#define DMA_REQ_UART2_R       29
-#define DMA_REQ_UART1_T       30
-#define DMA_REQ_UART1_R       31
-
-#endif				/* _ASM_ARCH_DMA_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/entry-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/entry-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/entry-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-imx/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for iMX-based platforms
- *
- * 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 <mach/hardware.h>
-
-		.macro	disable_fiq
-		.endm
-
-		.macro	get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro	arch_ret_to_user, tmp1, tmp2
-		.endm
-
-#define AITC_NIVECSR   0x40
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr	\base, =IO_ADDRESS(IMX_AITC_BASE)
-		@ Load offset & priority of the highest priority
-		@ interrupt pending.
-		ldr	\irqstat, [\base, #AITC_NIVECSR]
-		@ Shift off the priority leaving the offset or
-		@ "interrupt number", use arithmetic shift to
-		@ transform illegal source (0xffff) as -1
-		mov	\irqnr, \irqstat, asr #16
-		adds	\tmp, \irqnr, #1
-		.endm
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/gpio.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,106 +0,0 @@
-#ifndef _IMX_GPIO_H
-
-#include <linux/kernel.h>
-#include <mach/hardware.h>
-#include <mach/imx-regs.h>
-
-#define IMX_GPIO_ALLOC_MODE_NORMAL	0
-#define IMX_GPIO_ALLOC_MODE_NO_ALLOC	1
-#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC	2
-#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY	4
-#define IMX_GPIO_ALLOC_MODE_RELEASE	8
-
-extern int imx_gpio_request(unsigned gpio, const char *label);
-
-extern void imx_gpio_free(unsigned gpio);
-
-extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
-					int alloc_mode, const char *label);
-
-extern int imx_gpio_direction_input(unsigned gpio);
-
-extern int imx_gpio_direction_output(unsigned gpio, int value);
-
-extern void __imx_gpio_set_value(unsigned gpio, int value);
-
-static inline int imx_gpio_get_value(unsigned gpio)
-{
-	return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK));
-}
-
-static inline void imx_gpio_set_value_inline(unsigned gpio, int value)
-{
-	unsigned long flags;
-
-	raw_local_irq_save(flags);
-	if(value)
-		DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK));
-	else
-		DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK));
-	raw_local_irq_restore(flags);
-}
-
-static inline void imx_gpio_set_value(unsigned gpio, int value)
-{
-	if(__builtin_constant_p(gpio))
-		imx_gpio_set_value_inline(gpio, value);
-	else
-		__imx_gpio_set_value(gpio, value);
-}
-
-extern int imx_gpio_to_irq(unsigned gpio);
-
-extern int imx_irq_to_gpio(unsigned irq);
-
-/*-------------------------------------------------------------------------*/
-
-/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions
- * to allow future extension of GPIO logic.
- */
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-	return imx_gpio_request(gpio, label);
-}
-
-static inline void gpio_free(unsigned gpio)
-{
-	might_sleep();
-
-	imx_gpio_free(gpio);
-}
-
-static inline  int gpio_direction_input(unsigned gpio)
-{
-	return imx_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
-	return imx_gpio_direction_output(gpio, value);
-}
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return imx_gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	imx_gpio_set_value(gpio, value);
-}
-
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return imx_gpio_to_irq(gpio);
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	return imx_irq_to_gpio(irq);
-}
-
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/hardware.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/hardware.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/hardware.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- *  arch/arm/mach-imx/include/mach/hardware.h
- *
- *  Copyright (C) 1999 ARM Limited.
- *
- * 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 __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include "imx-regs.h"
-
-#ifndef __ASSEMBLY__
-# define __REG(x)	(*((volatile u32 *)IO_ADDRESS(x)))
-
-# define __REG2(x,y)        (*(volatile u32 *)((u32)&__REG(x) + (y)))
-#endif
-
-/*
- * Memory map
- */
-
-#define IMX_IO_PHYS		0x00200000
-#define IMX_IO_SIZE		0x00100000
-#define IMX_IO_BASE		0xe0000000
-
-#define IMX_CS0_PHYS		0x10000000
-#define IMX_CS0_SIZE		0x02000000
-#define IMX_CS0_VIRT		0xe8000000
-
-#define IMX_CS1_PHYS		0x12000000
-#define IMX_CS1_SIZE		0x01000000
-#define IMX_CS1_VIRT		0xea000000
-
-#define IMX_CS2_PHYS		0x13000000
-#define IMX_CS2_SIZE		0x01000000
-#define IMX_CS2_VIRT		0xeb000000
-
-#define IMX_CS3_PHYS		0x14000000
-#define IMX_CS3_SIZE		0x01000000
-#define IMX_CS3_VIRT		0xec000000
-
-#define IMX_CS4_PHYS		0x15000000
-#define IMX_CS4_SIZE		0x01000000
-#define IMX_CS4_VIRT		0xed000000
-
-#define IMX_CS5_PHYS		0x16000000
-#define IMX_CS5_SIZE		0x01000000
-#define IMX_CS5_VIRT		0xee000000
-
-#define IMX_FB_VIRT		0xF1000000
-#define IMX_FB_SIZE		(256*1024)
-
-/* macro to get at IO space when running virtually */
-#define IO_ADDRESS(x) ((x) | IMX_IO_BASE)
-
-#ifndef __ASSEMBLY__
-/*
- * Handy routine to set GPIO functions
- */
-extern void imx_gpio_mode( int gpio_mode );
-
-#endif
-
-#define MAXIRQNUM                       62
-#define MAXFIQNUM                       62
-#define MAXSWINUM                       62
-
-/*
- * Use SDRAM for memory
- */
-#define MEM_SIZE		0x01000000
-
-#ifdef CONFIG_ARCH_MX1ADS
-#include "mx1ads.h"
-#endif
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/imx-dma.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/imx-dma.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/imx-dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/imx-dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- *  linux/include/asm-arm/imxads/dma.h
- *
- *  Copyright (C) 1997,1998 Russell King
- *
- * 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 <mach/dma.h>
-
-#ifndef __ASM_ARCH_IMX_DMA_H
-#define __ASM_ARCH_IMX_DMA_H
-
-#define IMX_DMA_CHANNELS  11
-
-/*
- * struct imx_dma_channel - i.MX specific DMA extension
- * @name: name specified by DMA client
- * @irq_handler: client callback for end of transfer
- * @err_handler: client callback for error condition
- * @data: clients context data for callbacks
- * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE
- * @sg: pointer to the actual read/written chunk for scatter-gather emulation
- * @sgbc: counter of processed bytes in the actual read/written chunk
- * @resbytes: total residual number of bytes to transfer
- *            (it can be lower or same as sum of SG mapped chunk sizes)
- * @sgcount: number of chunks to be read/written
- *
- * Structure is used for IMX DMA processing. It would be probably good
- * @struct dma_struct in the future for external interfacing and use
- * @struct imx_dma_channel only as extension to it.
- */
-
-struct imx_dma_channel {
-	const char *name;
-	void (*irq_handler) (int, void *);
-	void (*err_handler) (int, void *, int errcode);
-	void *data;
-	unsigned int  dma_mode;
-	struct scatterlist *sg;
-	unsigned int sgbc;
-	unsigned int sgcount;
-	unsigned int resbytes;
-	int dma_num;
-};
-
-extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
-
-#define IMX_DMA_ERR_BURST     1
-#define IMX_DMA_ERR_REQUEST   2
-#define IMX_DMA_ERR_TRANSFER  4
-#define IMX_DMA_ERR_BUFFER    8
-
-/* The type to distinguish channel numbers parameter from ordinal int type */
-typedef int imx_dmach_t;
-
-#define DMA_MODE_READ		0
-#define DMA_MODE_WRITE		1
-#define DMA_MODE_MASK		1
-
-int
-imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
-		unsigned int dma_length, unsigned int dev_addr, unsigned int dmamode);
-
-int
-imx_dma_setup_sg(imx_dmach_t dma_ch,
-		 struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
-		 unsigned int dev_addr, unsigned int dmamode);
-
-int
-imx_dma_setup_handlers(imx_dmach_t dma_ch,
-		void (*irq_handler) (int, void *),
-		void (*err_handler) (int, void *, int), void *data);
-
-void imx_dma_enable(imx_dmach_t dma_ch);
-
-void imx_dma_disable(imx_dmach_t dma_ch);
-
-int imx_dma_request(imx_dmach_t dma_ch, const char *name);
-
-void imx_dma_free(imx_dmach_t dma_ch);
-
-imx_dmach_t imx_dma_request_by_prio(const char *name, imx_dma_prio prio);
-
-
-#endif	/* _ASM_ARCH_IMX_DMA_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/imx-regs.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/imx-regs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/imx-regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/imx-regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,376 +0,0 @@
-#ifndef _IMX_REGS_H
-#define _IMX_REGS_H
-/* ------------------------------------------------------------------------
- *  Motorola IMX system registers
- * ------------------------------------------------------------------------
- *
- */
-
-/*
- *  Register BASEs, based on OFFSETs
- *
- */
-#define IMX_AIPI1_BASE             (0x00000 + IMX_IO_BASE)
-#define IMX_WDT_BASE               (0x01000 + IMX_IO_BASE)
-#define IMX_TIM1_BASE              (0x02000 + IMX_IO_BASE)
-#define IMX_TIM2_BASE              (0x03000 + IMX_IO_BASE)
-#define IMX_RTC_BASE               (0x04000 + IMX_IO_BASE)
-#define IMX_LCDC_BASE              (0x05000 + IMX_IO_BASE)
-#define IMX_UART1_BASE             (0x06000 + IMX_IO_BASE)
-#define IMX_UART2_BASE             (0x07000 + IMX_IO_BASE)
-#define IMX_PWM_BASE               (0x08000 + IMX_IO_BASE)
-#define IMX_DMAC_BASE              (0x09000 + IMX_IO_BASE)
-#define IMX_AIPI2_BASE             (0x10000 + IMX_IO_BASE)
-#define IMX_SIM_BASE               (0x11000 + IMX_IO_BASE)
-#define IMX_USBD_BASE              (0x12000 + IMX_IO_BASE)
-#define IMX_SPI1_BASE              (0x13000 + IMX_IO_BASE)
-#define IMX_MMC_BASE               (0x14000 + IMX_IO_BASE)
-#define IMX_ASP_BASE               (0x15000 + IMX_IO_BASE)
-#define IMX_BTA_BASE               (0x16000 + IMX_IO_BASE)
-#define IMX_I2C_BASE               (0x17000 + IMX_IO_BASE)
-#define IMX_SSI_BASE               (0x18000 + IMX_IO_BASE)
-#define IMX_SPI2_BASE              (0x19000 + IMX_IO_BASE)
-#define IMX_MSHC_BASE              (0x1A000 + IMX_IO_BASE)
-#define IMX_PLL_BASE               (0x1B000 + IMX_IO_BASE)
-#define IMX_GPIO_BASE              (0x1C000 + IMX_IO_BASE)
-#define IMX_EIM_BASE               (0x20000 + IMX_IO_BASE)
-#define IMX_SDRAMC_BASE            (0x21000 + IMX_IO_BASE)
-#define IMX_MMA_BASE               (0x22000 + IMX_IO_BASE)
-#define IMX_AITC_BASE              (0x23000 + IMX_IO_BASE)
-#define IMX_CSI_BASE               (0x24000 + IMX_IO_BASE)
-
-/* PLL registers */
-#define CSCR   __REG(IMX_PLL_BASE)        /* Clock Source Control Register */
-#define CSCR_SPLL_RESTART	(1<<22)
-#define CSCR_MPLL_RESTART	(1<<21)
-#define CSCR_SYSTEM_SEL		(1<<16)
-#define CSCR_BCLK_DIV		(0xf<<10)
-#define CSCR_MPU_PRESC		(1<<15)
-#define CSCR_SPEN		(1<<1)
-#define CSCR_MPEN		(1<<0)
-
-#define MPCTL0 __REG(IMX_PLL_BASE + 0x4)  /* MCU PLL Control Register 0 */
-#define MPCTL1 __REG(IMX_PLL_BASE + 0x8)  /* MCU PLL and System Clock Register 1 */
-#define SPCTL0 __REG(IMX_PLL_BASE + 0xc)  /* System PLL Control Register 0 */
-#define SPCTL1 __REG(IMX_PLL_BASE + 0x10) /* System PLL Control Register 1 */
-#define PCDR   __REG(IMX_PLL_BASE + 0x20) /* Peripheral Clock Divider Register */
-
-/*
- *  GPIO Module and I/O Multiplexer
- *  x = 0..3 for reg_A, reg_B, reg_C, reg_D
- */
-#define DDIR(x)    __REG2(IMX_GPIO_BASE + 0x00, ((x) & 3) << 8)
-#define OCR1(x)    __REG2(IMX_GPIO_BASE + 0x04, ((x) & 3) << 8)
-#define OCR2(x)    __REG2(IMX_GPIO_BASE + 0x08, ((x) & 3) << 8)
-#define ICONFA1(x) __REG2(IMX_GPIO_BASE + 0x0c, ((x) & 3) << 8)
-#define ICONFA2(x) __REG2(IMX_GPIO_BASE + 0x10, ((x) & 3) << 8)
-#define ICONFB1(x) __REG2(IMX_GPIO_BASE + 0x14, ((x) & 3) << 8)
-#define ICONFB2(x) __REG2(IMX_GPIO_BASE + 0x18, ((x) & 3) << 8)
-#define DR(x)      __REG2(IMX_GPIO_BASE + 0x1c, ((x) & 3) << 8)
-#define GIUS(x)    __REG2(IMX_GPIO_BASE + 0x20, ((x) & 3) << 8)
-#define SSR(x)     __REG2(IMX_GPIO_BASE + 0x24, ((x) & 3) << 8)
-#define ICR1(x)    __REG2(IMX_GPIO_BASE + 0x28, ((x) & 3) << 8)
-#define ICR2(x)    __REG2(IMX_GPIO_BASE + 0x2c, ((x) & 3) << 8)
-#define IMR(x)     __REG2(IMX_GPIO_BASE + 0x30, ((x) & 3) << 8)
-#define ISR(x)     __REG2(IMX_GPIO_BASE + 0x34, ((x) & 3) << 8)
-#define GPR(x)     __REG2(IMX_GPIO_BASE + 0x38, ((x) & 3) << 8)
-#define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
-#define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
-
-#define GPIO_PORT_MAX  3
-
-#define GPIO_PIN_MASK 0x1f
-#define GPIO_PORT_MASK (0x3 << 5)
-
-#define GPIO_PORT_SHIFT 5
-#define GPIO_PORTA (0<<5)
-#define GPIO_PORTB (1<<5)
-#define GPIO_PORTC (2<<5)
-#define GPIO_PORTD (3<<5)
-
-#define GPIO_OUT   (1<<7)
-#define GPIO_IN    (0<<7)
-#define GPIO_PUEN  (1<<8)
-
-#define GPIO_PF    (0<<9)
-#define GPIO_AF    (1<<9)
-
-#define GPIO_OCR_SHIFT 10
-#define GPIO_OCR_MASK (3<<10)
-#define GPIO_AIN   (0<<10)
-#define GPIO_BIN   (1<<10)
-#define GPIO_CIN   (2<<10)
-#define GPIO_DR    (3<<10)
-
-#define GPIO_AOUT_SHIFT 12
-#define GPIO_AOUT_MASK (3<<12)
-#define GPIO_AOUT     (0<<12)
-#define GPIO_AOUT_ISR (1<<12)
-#define GPIO_AOUT_0   (2<<12)
-#define GPIO_AOUT_1   (3<<12)
-
-#define GPIO_BOUT_SHIFT 14
-#define GPIO_BOUT_MASK (3<<14)
-#define GPIO_BOUT      (0<<14)
-#define GPIO_BOUT_ISR  (1<<14)
-#define GPIO_BOUT_0    (2<<14)
-#define GPIO_BOUT_1    (3<<14)
-
-#define GPIO_GIUS      (1<<16)
-
-/* assignements for GPIO alternate/primary functions */
-
-/* FIXME: This list is not completed. The correct directions are
- * missing on some (many) pins
- */
-#define PA0_AIN_SPI2_CLK     ( GPIO_GIUS | GPIO_PORTA | GPIO_OUT | 0 )
-#define PA0_AF_ETMTRACESYNC  ( GPIO_PORTA | GPIO_AF | 0 )
-#define PA1_AOUT_SPI2_RXD    ( GPIO_GIUS | GPIO_PORTA | GPIO_IN | 1 )
-#define PA1_PF_TIN           ( GPIO_PORTA | GPIO_PF | 1 )
-#define PA2_PF_PWM0          ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 2 )
-#define PA3_PF_CSI_MCLK      ( GPIO_PORTA | GPIO_PF | 3 )
-#define PA4_PF_CSI_D0        ( GPIO_PORTA | GPIO_PF | 4 )
-#define PA5_PF_CSI_D1        ( GPIO_PORTA | GPIO_PF | 5 )
-#define PA6_PF_CSI_D2        ( GPIO_PORTA | GPIO_PF | 6 )
-#define PA7_PF_CSI_D3        ( GPIO_PORTA | GPIO_PF | 7 )
-#define PA8_PF_CSI_D4        ( GPIO_PORTA | GPIO_PF | 8 )
-#define PA9_PF_CSI_D5        ( GPIO_PORTA | GPIO_PF | 9 )
-#define PA10_PF_CSI_D6       ( GPIO_PORTA | GPIO_PF | 10 )
-#define PA11_PF_CSI_D7       ( GPIO_PORTA | GPIO_PF | 11 )
-#define PA12_PF_CSI_VSYNC    ( GPIO_PORTA | GPIO_PF | 12 )
-#define PA13_PF_CSI_HSYNC    ( GPIO_PORTA | GPIO_PF | 13 )
-#define PA14_PF_CSI_PIXCLK   ( GPIO_PORTA | GPIO_PF | 14 )
-#define PA15_PF_I2C_SDA      ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 15 )
-#define PA16_PF_I2C_SCL      ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 16 )
-#define PA17_AF_ETMTRACEPKT4 ( GPIO_PORTA | GPIO_AF | 17 )
-#define PA17_AIN_SPI2_SS     ( GPIO_GIUS | GPIO_PORTA | GPIO_OUT | 17 )
-#define PA18_AF_ETMTRACEPKT5 ( GPIO_PORTA | GPIO_AF | 18 )
-#define PA19_AF_ETMTRACEPKT6 ( GPIO_PORTA | GPIO_AF | 19 )
-#define PA20_AF_ETMTRACEPKT7 ( GPIO_PORTA | GPIO_AF | 20 )
-#define PA21_PF_A0           ( GPIO_PORTA | GPIO_PF | 21 )
-#define PA22_PF_CS4          ( GPIO_PORTA | GPIO_PF | 22 )
-#define PA23_PF_CS5          ( GPIO_PORTA | GPIO_PF | 23 )
-#define PA24_PF_A16          ( GPIO_PORTA | GPIO_PF | 24 )
-#define PA24_AF_ETMTRACEPKT0 ( GPIO_PORTA | GPIO_AF | 24 )
-#define PA25_PF_A17          ( GPIO_PORTA | GPIO_PF | 25 )
-#define PA25_AF_ETMTRACEPKT1 ( GPIO_PORTA | GPIO_AF | 25 )
-#define PA26_PF_A18          ( GPIO_PORTA | GPIO_PF | 26 )
-#define PA26_AF_ETMTRACEPKT2 ( GPIO_PORTA | GPIO_AF | 26 )
-#define PA27_PF_A19          ( GPIO_PORTA | GPIO_PF | 27 )
-#define PA27_AF_ETMTRACEPKT3 ( GPIO_PORTA | GPIO_AF | 27 )
-#define PA28_PF_A20          ( GPIO_PORTA | GPIO_PF | 28 )
-#define PA28_AF_ETMPIPESTAT0 ( GPIO_PORTA | GPIO_AF | 28 )
-#define PA29_PF_A21          ( GPIO_PORTA | GPIO_PF | 29 )
-#define PA29_AF_ETMPIPESTAT1 ( GPIO_PORTA | GPIO_AF | 29 )
-#define PA30_PF_A22          ( GPIO_PORTA | GPIO_PF | 30 )
-#define PA30_AF_ETMPIPESTAT2 ( GPIO_PORTA | GPIO_AF | 30 )
-#define PA31_PF_A23          ( GPIO_PORTA | GPIO_PF | 31 )
-#define PA31_AF_ETMTRACECLK  ( GPIO_PORTA | GPIO_AF | 31 )
-#define PB8_PF_SD_DAT0       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8 )
-#define PB8_AF_MS_PIO        ( GPIO_PORTB | GPIO_AF | 8 )
-#define PB9_PF_SD_DAT1       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 9 )
-#define PB9_AF_MS_PI1        ( GPIO_PORTB | GPIO_AF | 9 )
-#define PB10_PF_SD_DAT2      ( GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 10 )
-#define PB10_AF_MS_SCLKI     ( GPIO_PORTB | GPIO_AF | 10 )
-#define PB11_PF_SD_DAT3      ( GPIO_PORTB | GPIO_PF | 11 )
-#define PB11_AF_MS_SDIO      ( GPIO_PORTB | GPIO_AF | 11 )
-#define PB12_PF_SD_CLK       ( GPIO_PORTB | GPIO_PF | 12 )
-#define PB12_AF_MS_SCLK0     ( GPIO_PORTB | GPIO_AF | 12 )
-#define PB13_PF_SD_CMD       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13 )
-#define PB13_AF_MS_BS        ( GPIO_PORTB | GPIO_AF | 13 )
-#define PB14_AF_SSI_RXFS     ( GPIO_PORTB | GPIO_AF | 14 )
-#define PB15_AF_SSI_RXCLK    ( GPIO_PORTB | GPIO_AF | 15 )
-#define PB16_AF_SSI_RXDAT    ( GPIO_PORTB | GPIO_IN | GPIO_AF | 16 )
-#define PB17_AF_SSI_TXDAT    ( GPIO_PORTB | GPIO_OUT | GPIO_AF | 17 )
-#define PB18_AF_SSI_TXFS     ( GPIO_PORTB | GPIO_AF | 18 )
-#define PB19_AF_SSI_TXCLK    ( GPIO_PORTB | GPIO_AF | 19 )
-#define PB20_PF_USBD_AFE     ( GPIO_PORTB | GPIO_PF | 20 )
-#define PB21_PF_USBD_OE      ( GPIO_PORTB | GPIO_PF | 21 )
-#define PB22_PFUSBD_RCV      ( GPIO_PORTB | GPIO_PF | 22 )
-#define PB23_PF_USBD_SUSPND  ( GPIO_PORTB | GPIO_PF | 23 )
-#define PB24_PF_USBD_VP      ( GPIO_PORTB | GPIO_PF | 24 )
-#define PB25_PF_USBD_VM      ( GPIO_PORTB | GPIO_PF | 25 )
-#define PB26_PF_USBD_VPO     ( GPIO_PORTB | GPIO_PF | 26 )
-#define PB27_PF_USBD_VMO     ( GPIO_PORTB | GPIO_PF | 27 )
-#define PB28_PF_UART2_CTS    ( GPIO_PORTB | GPIO_OUT | GPIO_PF | 28 )
-#define PB29_PF_UART2_RTS    ( GPIO_PORTB | GPIO_IN | GPIO_PF | 29 )
-#define PB30_PF_UART2_TXD    ( GPIO_PORTB | GPIO_OUT | GPIO_PF | 30 )
-#define PB31_PF_UART2_RXD    ( GPIO_PORTB | GPIO_IN | GPIO_PF | 31 )
-#define PC3_PF_SSI_RXFS      ( GPIO_PORTC | GPIO_PF | 3 )
-#define PC4_PF_SSI_RXCLK     ( GPIO_PORTC | GPIO_PF | 4 )
-#define PC5_PF_SSI_RXDAT     ( GPIO_PORTC | GPIO_IN | GPIO_PF | 5 )
-#define PC6_PF_SSI_TXDAT     ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 6 )
-#define PC7_PF_SSI_TXFS      ( GPIO_PORTC | GPIO_PF | 7 )
-#define PC8_PF_SSI_TXCLK     ( GPIO_PORTC | GPIO_PF | 8 )
-#define PC9_PF_UART1_CTS     ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 9 )
-#define PC10_PF_UART1_RTS    ( GPIO_PORTC | GPIO_IN | GPIO_PF | 10 )
-#define PC11_PF_UART1_TXD    ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 11 )
-#define PC12_PF_UART1_RXD    ( GPIO_PORTC | GPIO_IN | GPIO_PF | 12 )
-#define PC13_PF_SPI1_SPI_RDY ( GPIO_PORTC | GPIO_PF | 13 )
-#define PC14_PF_SPI1_SCLK    ( GPIO_PORTC | GPIO_PF | 14 )
-#define PC15_PF_SPI1_SS      ( GPIO_PORTC | GPIO_PF | 15 )
-#define PC16_PF_SPI1_MISO    ( GPIO_PORTC | GPIO_PF | 16 )
-#define PC17_PF_SPI1_MOSI    ( GPIO_PORTC | GPIO_PF | 17 )
-#define PC24_BIN_UART3_RI    ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 24 )
-#define PC25_BIN_UART3_DSR   ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 25 )
-#define PC26_AOUT_UART3_DTR  ( GPIO_GIUS | GPIO_PORTC | GPIO_IN | 26 )
-#define PC27_BIN_UART3_DCD   ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 27 )
-#define PC28_BIN_UART3_CTS   ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 28 )
-#define PC29_AOUT_UART3_RTS  ( GPIO_GIUS | GPIO_PORTC | GPIO_IN | 29 )
-#define PC30_BIN_UART3_TX    ( GPIO_GIUS | GPIO_PORTC | GPIO_BIN | 30 )
-#define PC31_AOUT_UART3_RX   ( GPIO_GIUS | GPIO_PORTC | GPIO_IN | 31)
-#define PD6_PF_LSCLK         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 6 )
-#define PD7_PF_REV           ( GPIO_PORTD | GPIO_PF | 7 )
-#define PD7_AF_UART2_DTR     ( GPIO_GIUS | GPIO_PORTD | GPIO_IN | GPIO_AF | 7 )
-#define PD7_AIN_SPI2_SCLK    ( GPIO_GIUS | GPIO_PORTD | GPIO_AIN | 7 )
-#define PD8_PF_CLS           ( GPIO_PORTD | GPIO_PF | 8 )
-#define PD8_AF_UART2_DCD     ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 8 )
-#define PD8_AIN_SPI2_SS      ( GPIO_GIUS | GPIO_PORTD | GPIO_AIN | 8 )
-#define PD9_PF_PS            ( GPIO_PORTD | GPIO_PF | 9 )
-#define PD9_AF_UART2_RI      ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 9 )
-#define PD9_AOUT_SPI2_RXD    ( GPIO_GIUS | GPIO_PORTD | GPIO_IN | 9 )
-#define PD10_PF_SPL_SPR      ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 10 )
-#define PD10_AF_UART2_DSR    ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 10 )
-#define PD10_AIN_SPI2_TXD    ( GPIO_GIUS | GPIO_PORTD | GPIO_OUT | 10 )
-#define PD11_PF_CONTRAST     ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 11 )
-#define PD12_PF_ACD_OE       ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 12 )
-#define PD13_PF_LP_HSYNC     ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 13 )
-#define PD14_PF_FLM_VSYNC    ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 14 )
-#define PD15_PF_LD0          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 15 )
-#define PD16_PF_LD1          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 16 )
-#define PD17_PF_LD2          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 17 )
-#define PD18_PF_LD3          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 18 )
-#define PD19_PF_LD4          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 19 )
-#define PD20_PF_LD5          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 20 )
-#define PD21_PF_LD6          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 21 )
-#define PD22_PF_LD7          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 22 )
-#define PD23_PF_LD8          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 23 )
-#define PD24_PF_LD9          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 24 )
-#define PD25_PF_LD10         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 25 )
-#define PD26_PF_LD11         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 26 )
-#define PD27_PF_LD12         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 27 )
-#define PD28_PF_LD13         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 28 )
-#define PD29_PF_LD14         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 29 )
-#define PD30_PF_LD15         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 30 )
-#define PD31_PF_TMR2OUT      ( GPIO_PORTD | GPIO_PF | 31 )
-#define PD31_BIN_SPI2_TXD    ( GPIO_GIUS | GPIO_PORTD | GPIO_BIN | 31 )
-
-/*
- * PWM controller
- */
-#define PWMC	__REG(IMX_PWM_BASE + 0x00)	/* PWM Control Register		*/
-#define PWMS	__REG(IMX_PWM_BASE + 0x04)	/* PWM Sample Register		*/
-#define PWMP	__REG(IMX_PWM_BASE + 0x08)	/* PWM Period Register		*/
-#define PWMCNT	__REG(IMX_PWM_BASE + 0x0C)	/* PWM Counter Register		*/
-
-#define PWMC_HCTR		(0x01<<18)		/* Halfword FIFO Data Swapping	*/
-#define PWMC_BCTR		(0x01<<17)		/* Byte FIFO Data Swapping	*/
-#define PWMC_SWR		(0x01<<16)		/* Software Reset		*/
-#define PWMC_CLKSRC		(0x01<<15)		/* Clock Source			*/
-#define PWMC_PRESCALER(x)	(((x-1) & 0x7F) << 8)	/* PRESCALER			*/
-#define PWMC_IRQ		(0x01<< 7)		/* Interrupt Request		*/
-#define PWMC_IRQEN		(0x01<< 6)		/* Interrupt Request Enable	*/
-#define PWMC_FIFOAV		(0x01<< 5)		/* FIFO Available		*/
-#define PWMC_EN			(0x01<< 4)		/* Enables/Disables the PWM	*/
-#define PWMC_REPEAT(x)		(((x) & 0x03) << 2)	/* Sample Repeats		*/
-#define PWMC_CLKSEL(x)		(((x) & 0x03) << 0)	/* Clock Selection		*/
-
-#define PWMS_SAMPLE(x)		((x) & 0xFFFF)		/* Contains a two-sample word	*/
-#define PWMP_PERIOD(x)		((x) & 0xFFFF)		/* Represents the PWM's period	*/
-#define PWMC_COUNTER(x)		((x) & 0xFFFF)		/* Represents the current count value	*/
-
-/*
- *  DMA Controller
- */
-#define DCR     __REG(IMX_DMAC_BASE +0x00)	/* DMA Control Register */
-#define DISR    __REG(IMX_DMAC_BASE +0x04)	/* DMA Interrupt status Register */
-#define DIMR    __REG(IMX_DMAC_BASE +0x08)	/* DMA Interrupt mask Register */
-#define DBTOSR  __REG(IMX_DMAC_BASE +0x0c)	/* DMA Burst timeout status Register */
-#define DRTOSR  __REG(IMX_DMAC_BASE +0x10)	/* DMA Request timeout Register */
-#define DSESR   __REG(IMX_DMAC_BASE +0x14)	/* DMA Transfer Error Status Register */
-#define DBOSR   __REG(IMX_DMAC_BASE +0x18)	/* DMA Buffer overflow status Register */
-#define DBTOCR  __REG(IMX_DMAC_BASE +0x1c)	/* DMA Burst timeout control Register */
-#define WSRA    __REG(IMX_DMAC_BASE +0x40)	/* W-Size Register A */
-#define XSRA    __REG(IMX_DMAC_BASE +0x44)	/* X-Size Register A */
-#define YSRA    __REG(IMX_DMAC_BASE +0x48)	/* Y-Size Register A */
-#define WSRB    __REG(IMX_DMAC_BASE +0x4c)	/* W-Size Register B */
-#define XSRB    __REG(IMX_DMAC_BASE +0x50)	/* X-Size Register B */
-#define YSRB    __REG(IMX_DMAC_BASE +0x54)	/* Y-Size Register B */
-#define SAR(x)  __REG2( IMX_DMAC_BASE + 0x80, (x) << 6)	/* Source Address Registers */
-#define DAR(x)  __REG2( IMX_DMAC_BASE + 0x84, (x) << 6)	/* Destination Address Registers */
-#define CNTR(x) __REG2( IMX_DMAC_BASE + 0x88, (x) << 6)	/* Count Registers */
-#define CCR(x)  __REG2( IMX_DMAC_BASE + 0x8c, (x) << 6)	/* Control Registers */
-#define RSSR(x) __REG2( IMX_DMAC_BASE + 0x90, (x) << 6)	/* Request source select Registers */
-#define BLR(x)  __REG2( IMX_DMAC_BASE + 0x94, (x) << 6)	/* Burst length Registers */
-#define RTOR(x) __REG2( IMX_DMAC_BASE + 0x98, (x) << 6)	/* Request timeout Registers */
-#define BUCR(x) __REG2( IMX_DMAC_BASE + 0x98, (x) << 6)	/* Bus Utilization Registers */
-
-#define DCR_DRST           (1<<1)
-#define DCR_DEN            (1<<0)
-#define DBTOCR_EN          (1<<15)
-#define DBTOCR_CNT(x)      ((x) & 0x7fff )
-#define CNTR_CNT(x)        ((x) & 0xffffff )
-#define CCR_DMOD_LINEAR    ( 0x0 << 12 )
-#define CCR_DMOD_2D        ( 0x1 << 12 )
-#define CCR_DMOD_FIFO      ( 0x2 << 12 )
-#define CCR_DMOD_EOBFIFO   ( 0x3 << 12 )
-#define CCR_SMOD_LINEAR    ( 0x0 << 10 )
-#define CCR_SMOD_2D        ( 0x1 << 10 )
-#define CCR_SMOD_FIFO      ( 0x2 << 10 )
-#define CCR_SMOD_EOBFIFO   ( 0x3 << 10 )
-#define CCR_MDIR_DEC       (1<<9)
-#define CCR_MSEL_B         (1<<8)
-#define CCR_DSIZ_32        ( 0x0 << 6 )
-#define CCR_DSIZ_8         ( 0x1 << 6 )
-#define CCR_DSIZ_16        ( 0x2 << 6 )
-#define CCR_SSIZ_32        ( 0x0 << 4 )
-#define CCR_SSIZ_8         ( 0x1 << 4 )
-#define CCR_SSIZ_16        ( 0x2 << 4 )
-#define CCR_REN            (1<<3)
-#define CCR_RPT            (1<<2)
-#define CCR_FRC            (1<<1)
-#define CCR_CEN            (1<<0)
-#define RTOR_EN            (1<<15)
-#define RTOR_CLK           (1<<14)
-#define RTOR_PSC           (1<<13)
-
-/*
- *  Interrupt controller
- */
-
-#define IMX_INTCNTL        __REG(IMX_AITC_BASE+0x00)
-#define INTCNTL_FIAD       (1<<19)
-#define INTCNTL_NIAD       (1<<20)
-
-#define IMX_NIMASK         __REG(IMX_AITC_BASE+0x04)
-#define IMX_INTENNUM       __REG(IMX_AITC_BASE+0x08)
-#define IMX_INTDISNUM      __REG(IMX_AITC_BASE+0x0c)
-#define IMX_INTENABLEH     __REG(IMX_AITC_BASE+0x10)
-#define IMX_INTENABLEL     __REG(IMX_AITC_BASE+0x14)
-
-/*
- *  General purpose timers
- */
-#define IMX_TCTL(x)        __REG( 0x00 + (x))
-#define TCTL_SWR           (1<<15)
-#define TCTL_FRR           (1<<8)
-#define TCTL_CAP_RIS       (1<<6)
-#define TCTL_CAP_FAL       (2<<6)
-#define TCTL_CAP_RIS_FAL   (3<<6)
-#define TCTL_OM            (1<<5)
-#define TCTL_IRQEN         (1<<4)
-#define TCTL_CLK_PCLK1     (1<<1)
-#define TCTL_CLK_PCLK1_16  (2<<1)
-#define TCTL_CLK_TIN       (3<<1)
-#define TCTL_CLK_32        (4<<1)
-#define TCTL_TEN           (1<<0)
-
-#define IMX_TPRER(x)       __REG( 0x04 + (x))
-#define IMX_TCMP(x)        __REG( 0x08 + (x))
-#define IMX_TCR(x)         __REG( 0x0C + (x))
-#define IMX_TCN(x)         __REG( 0x10 + (x))
-#define IMX_TSTAT(x)       __REG( 0x14 + (x))
-#define TSTAT_CAPT         (1<<1)
-#define TSTAT_COMP         (1<<0)
-
-#endif				// _IMX_REGS_H
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/imx-uart.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/imx-uart.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/imx-uart.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/imx-uart.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-#ifndef ASMARM_ARCH_UART_H
-#define ASMARM_ARCH_UART_H
-
-#define IMXUART_HAVE_RTSCTS (1<<0)
-
-struct imxuart_platform_data {
-	int (*init)(struct platform_device *pdev);
-	void (*exit)(struct platform_device *pdev);
-	unsigned int flags;
-};
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/io.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/io.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  arch/arm/mach-imxads/include/mach/io.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * 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 __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-/*
- *  arch/arm/mach-imxads/include/mach/irqs.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * 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 __ARM_IRQS_H__
-#define __ARM_IRQS_H__
-
-/* Use the imx definitions */
-#include <mach/hardware.h>
-
-/*
- *  IMX Interrupt numbers
- *
- */
-#define INT_SOFTINT                 0
-#define CSI_INT                     6
-#define DSPA_MAC_INT                7
-#define DSPA_INT                    8
-#define COMP_INT                    9
-#define MSHC_XINT                   10
-#define GPIO_INT_PORTA              11
-#define GPIO_INT_PORTB              12
-#define GPIO_INT_PORTC              13
-#define LCDC_INT                    14
-#define SIM_INT                     15
-#define SIM_DATA_INT                16
-#define RTC_INT                     17
-#define RTC_SAMINT                  18
-#define UART2_MINT_PFERR            19
-#define UART2_MINT_RTS              20
-#define UART2_MINT_DTR              21
-#define UART2_MINT_UARTC            22
-#define UART2_MINT_TX               23
-#define UART2_MINT_RX               24
-#define UART1_MINT_PFERR            25
-#define UART1_MINT_RTS              26
-#define UART1_MINT_DTR              27
-#define UART1_MINT_UARTC            28
-#define UART1_MINT_TX               29
-#define UART1_MINT_RX               30
-#define VOICE_DAC_INT               31
-#define VOICE_ADC_INT               32
-#define PEN_DATA_INT                33
-#define PWM_INT                     34
-#define SDHC_INT                    35
-#define I2C_INT                     39
-#define CSPI_INT                    41
-#define SSI_TX_INT                  42
-#define SSI_TX_ERR_INT              43
-#define SSI_RX_INT                  44
-#define SSI_RX_ERR_INT              45
-#define TOUCH_INT                   46
-#define USBD_INT0                   47
-#define USBD_INT1                   48
-#define USBD_INT2                   49
-#define USBD_INT3                   50
-#define USBD_INT4                   51
-#define USBD_INT5                   52
-#define USBD_INT6                   53
-#define BTSYS_INT                   55
-#define BTTIM_INT                   56
-#define BTWUI_INT                   57
-#define TIM2_INT                    58
-#define TIM1_INT                    59
-#define DMA_ERR                     60
-#define DMA_INT                     61
-#define GPIO_INT_PORTD              62
-
-#define IMX_IRQS                         (64)
-
-/* note: the IMX has four gpio ports (A-D), but only
- *       the following pins are connected to the outside
- *       world:
- *
- * PORT A: bits 0-31
- * PORT B: bits 8-31
- * PORT C: bits 3-17
- * PORT D: bits 6-31
- *
- * We map these interrupts straight on. As a result we have
- * several holes in the interrupt mapping. We do this for two
- * reasons:
- *   - mapping the interrupts without holes would get
- *     far more complicated
- *   - Motorola could well decide to bring some processor
- *     with more pins connected
- */
-
-#define IRQ_GPIOA(x)  (IMX_IRQS + x)
-#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
-#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
-#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
-
-/* decode irq number to use with IMR(x), ISR(x) and friends */
-#define IRQ_TO_REG(irq) ((irq - IMX_IRQS) >> 5)
-
-/* all normal IRQs can be FIQs */
-#define FIQ_START	0
-/* switch betwean IRQ and FIQ */
-extern int imx_set_irq_fiq(unsigned int irq, unsigned int type);
-
-#define NR_IRQS (IRQ_GPIOD(32) + 1)
-#define IRQ_GPIO(x)
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/memory.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/memory.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/memory.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- *  arch/arm/mach-imx/include/mach/memory.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *
- * 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 __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-#define PHYS_OFFSET	UL(0x08000000)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/mmc.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/mmc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/mmc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/mmc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-#ifndef ASMARM_ARCH_MMC_H
-#define ASMARM_ARCH_MMC_H
-
-#include <linux/mmc/host.h>
-
-struct device;
-
-struct imxmmc_platform_data {
-	int (*card_present)(struct device *);
-	int (*get_ro)(struct device *);
-};
-
-extern void imx_set_mmc_info(struct imxmmc_platform_data *info);
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/mx1ads.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/mx1ads.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/mx1ads.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/mx1ads.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-imx/include/mach/mx1ads.h
- *
- * Copyright (C) 2004 Robert Schwebel, Pengutronix
- *
- * 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 __ASM_ARCH_MX1ADS_H
-#define __ASM_ARCH_MX1ADS_H
-
-/* ------------------------------------------------------------------------ */
-/* Memory Map for the M9328MX1ADS (MX1ADS) Board                            */
-/* ------------------------------------------------------------------------ */
-
-#define MX1ADS_FLASH_PHYS		0x10000000
-#define MX1ADS_FLASH_SIZE		(16*1024*1024)
-
-#define IMX_FB_PHYS			(0x0C000000 - 0x40000)
-
-#define CLK32 32000
-
-#endif /* __ASM_ARCH_MX1ADS_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/spi_imx.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/spi_imx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/spi_imx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/spi_imx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/*
- * arch/arm/mach-imx/include/mach/spi_imx.h
- *
- * Copyright (C) 2006 SWAPP
- *	Andrea Paterniani <a.paterniani@swapp-eng.it>
- *
- * Initial version inspired by:
- *	linux-2.6.17-rc3-mm1/arch/arm/mach-pxa/include/mach/pxa2xx_spi.h
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef SPI_IMX_H_
-#define SPI_IMX_H_
-
-
-/*-------------------------------------------------------------------------*/
-/**
- * struct spi_imx_master - device.platform_data for SPI controller devices.
- * @num_chipselect: chipselects are used to distinguish individual
- *	SPI slaves, and are numbered from zero to num_chipselects - 1.
- *	each slave has a chipselect signal, but it's common that not
- *	every chipselect is connected to a slave.
- * @enable_dma: if true enables DMA driven transfers.
-*/
-struct spi_imx_master {
-	u8 num_chipselect;
-	u8 enable_dma:1;
-};
-/*-------------------------------------------------------------------------*/
-
-
-/*-------------------------------------------------------------------------*/
-/**
- * struct spi_imx_chip - spi_board_info.controller_data for SPI
- * slave devices, copied to spi_device.controller_data.
- * @enable_loopback : used for test purpouse to internally connect RX and TX
- *	sections.
- * @enable_dma : enables dma transfer (provided that controller driver has
- *	dma enabled too).
- * @ins_ss_pulse : enable /SS pulse insertion between SPI burst.
- * @bclk_wait : number of bclk waits between each bits_per_word SPI burst.
- * @cs_control : function pointer to board-specific function to assert/deassert
- *	I/O port to control HW generation of devices chip-select.
-*/
-struct spi_imx_chip {
-	u8	enable_loopback:1;
-	u8	enable_dma:1;
-	u8	ins_ss_pulse:1;
-	u16	bclk_wait:15;
-	void (*cs_control)(u32 control);
-};
-
-/* Chip-select state */
-#define SPI_CS_ASSERT			(1 << 0)
-#define SPI_CS_DEASSERT			(1 << 1)
-/*-------------------------------------------------------------------------*/
-
-
-#endif /* SPI_IMX_H_*/
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/system.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/system.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- *  arch/arm/mach-imxads/include/mach/system.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *
- * 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 __ASM_ARCH_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-static void
-arch_idle(void)
-{
-	/*
-	 * This should do all the clock switching
-	 * and wait for interrupt tricks
-	 */
-	cpu_do_idle();
-}
-
-static inline void
-arch_reset(char mode, const char *cmd)
-{
-	cpu_reset(0);
-}
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/timex.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/timex.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/timex.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- *  linux/include/asm-arm/imx/timex.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * 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 __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE		(16000000)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/uncompress.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/uncompress.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/uncompress.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-/*
- *  arch/arm/mach-imxads/include/mach/uncompress.h
- *
- *
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) Shane Nay (shane@minirl.com)
- *
- * 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
- */
-
-#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
-
-#define UART1_BASE 0x206000
-#define UART2_BASE 0x207000
-#define USR2 0x98
-#define USR2_TXFE (1<<14)
-#define TXR  0x40
-#define UCR1 0x80
-#define UCR1_UARTEN 1
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader.  We search for the first enabled
- * port in the most probable order.  If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- *
- * This does not append a newline
- */
-static void putc(int c)
-{
-	unsigned long serial_port;
-
-	do {
-		serial_port = UART1_BASE;
-		if ( UART(UCR1) & UCR1_UARTEN )
-			break;
-		serial_port = UART2_BASE;
-		if ( UART(UCR1) & UCR1_UARTEN )
-			break;
-		return;
-	} while(0);
-
-	while (!(UART(USR2) & USR2_TXFE))
-		barrier();
-
-	UART(TXR) = c;
-}
-
-static inline void flush(void)
-{
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-
-#define arch_decomp_wdog()
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/vmalloc.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/vmalloc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/include/mach/vmalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- *  arch/arm/mach-imx/include/mach/vmalloc.h
- *
- *  Copyright (C) 2000 Russell King.
- *
- * 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
- */
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/irq.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,311 +0,0 @@
-/*
- *  linux/arch/arm/mach-imx/irq.c
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *
- * 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
- *
- *  03/03/2004   Sascha Hauer <sascha@saschahauer.de>
- *               Copied from the motorola bsp package and added gpio demux
- *               interrupt handler
- */
-
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-/*
- *
- * We simply use the ENABLE DISABLE registers inside of the IMX
- * to turn on/off specific interrupts.
- *
- */
-
-#define INTCNTL_OFF               0x00
-#define NIMASK_OFF                0x04
-#define INTENNUM_OFF              0x08
-#define INTDISNUM_OFF             0x0C
-#define INTENABLEH_OFF            0x10
-#define INTENABLEL_OFF            0x14
-#define INTTYPEH_OFF              0x18
-#define INTTYPEL_OFF              0x1C
-#define NIPRIORITY_OFF(x)         (0x20+4*(7-(x)))
-#define NIVECSR_OFF               0x40
-#define FIVECSR_OFF               0x44
-#define INTSRCH_OFF               0x48
-#define INTSRCL_OFF               0x4C
-#define INTFRCH_OFF               0x50
-#define INTFRCL_OFF               0x54
-#define NIPNDH_OFF                0x58
-#define NIPNDL_OFF                0x5C
-#define FIPNDH_OFF                0x60
-#define FIPNDL_OFF                0x64
-
-#define VA_AITC_BASE              IO_ADDRESS(IMX_AITC_BASE)
-#define IMX_AITC_INTCNTL         (VA_AITC_BASE + INTCNTL_OFF)
-#define IMX_AITC_NIMASK          (VA_AITC_BASE + NIMASK_OFF)
-#define IMX_AITC_INTENNUM        (VA_AITC_BASE + INTENNUM_OFF)
-#define IMX_AITC_INTDISNUM       (VA_AITC_BASE + INTDISNUM_OFF)
-#define IMX_AITC_INTENABLEH      (VA_AITC_BASE + INTENABLEH_OFF)
-#define IMX_AITC_INTENABLEL      (VA_AITC_BASE + INTENABLEL_OFF)
-#define IMX_AITC_INTTYPEH        (VA_AITC_BASE + INTTYPEH_OFF)
-#define IMX_AITC_INTTYPEL        (VA_AITC_BASE + INTTYPEL_OFF)
-#define IMX_AITC_NIPRIORITY(x)   (VA_AITC_BASE + NIPRIORITY_OFF(x))
-#define IMX_AITC_NIVECSR         (VA_AITC_BASE + NIVECSR_OFF)
-#define IMX_AITC_FIVECSR         (VA_AITC_BASE + FIVECSR_OFF)
-#define IMX_AITC_INTSRCH         (VA_AITC_BASE + INTSRCH_OFF)
-#define IMX_AITC_INTSRCL         (VA_AITC_BASE + INTSRCL_OFF)
-#define IMX_AITC_INTFRCH         (VA_AITC_BASE + INTFRCH_OFF)
-#define IMX_AITC_INTFRCL         (VA_AITC_BASE + INTFRCL_OFF)
-#define IMX_AITC_NIPNDH          (VA_AITC_BASE + NIPNDH_OFF)
-#define IMX_AITC_NIPNDL          (VA_AITC_BASE + NIPNDL_OFF)
-#define IMX_AITC_FIPNDH          (VA_AITC_BASE + FIPNDH_OFF)
-#define IMX_AITC_FIPNDL          (VA_AITC_BASE + FIPNDL_OFF)
-
-#if 0
-#define DEBUG_IRQ(fmt...)	printk(fmt)
-#else
-#define DEBUG_IRQ(fmt...)	do { } while (0)
-#endif
-
-static void
-imx_mask_irq(unsigned int irq)
-{
-	__raw_writel(irq, IMX_AITC_INTDISNUM);
-}
-
-static void
-imx_unmask_irq(unsigned int irq)
-{
-	__raw_writel(irq, IMX_AITC_INTENNUM);
-}
-
-#ifdef CONFIG_FIQ
-int imx_set_irq_fiq(unsigned int irq, unsigned int type)
-{
-	unsigned int irqt;
-
-	if (irq >= IMX_IRQS)
-		return -EINVAL;
-
-	if (irq < IMX_IRQS / 2) {
-		irqt = __raw_readl(IMX_AITC_INTTYPEL) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), IMX_AITC_INTTYPEL);
-	} else {
-		irq -= IMX_IRQS / 2;
-		irqt = __raw_readl(IMX_AITC_INTTYPEH) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), IMX_AITC_INTTYPEH);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(imx_set_irq_fiq);
-#endif /* CONFIG_FIQ */
-
-static int
-imx_gpio_irq_type(unsigned int _irq, unsigned int type)
-{
-	unsigned int irq_type = 0, irq, reg, bit;
-
-	irq = _irq - IRQ_GPIOA(0);
-	reg = irq >> 5;
-	bit = 1 << (irq % 32);
-
-	if (type == IRQ_TYPE_PROBE) {
-		/* Don't mess with enabled GPIOs using preconfigured edges or
-		   GPIOs set to alternate function during probe */
-		/* TODO: support probe */
-//              if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
-//                  GPIO_bit(gpio))
-//                      return 0;
-//              if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
-//                      return 0;
-//              type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	GIUS(reg) |= bit;
-	DDIR(reg) &= ~(bit);
-
-	DEBUG_IRQ("setting type of irq %d to ", _irq);
-
-	if (type & IRQ_TYPE_EDGE_RISING) {
-		DEBUG_IRQ("rising edges\n");
-		irq_type = 0x0;
-	}
-	if (type & IRQ_TYPE_EDGE_FALLING) {
-		DEBUG_IRQ("falling edges\n");
-		irq_type = 0x1;
-	}
-	if (type & IRQ_TYPE_LEVEL_LOW) {
-		DEBUG_IRQ("low level\n");
-		irq_type = 0x3;
-	}
-	if (type & IRQ_TYPE_LEVEL_HIGH) {
-		DEBUG_IRQ("high level\n");
-		irq_type = 0x2;
-	}
-
-	if (irq % 32 < 16) {
-		ICR1(reg) = (ICR1(reg) & ~(0x3 << ((irq % 16) * 2))) |
-		    (irq_type << ((irq % 16) * 2));
-	} else {
-		ICR2(reg) = (ICR2(reg) & ~(0x3 << ((irq % 16) * 2))) |
-		    (irq_type << ((irq % 16) * 2));
-	}
-
-	return 0;
-
-}
-
-static void
-imx_gpio_ack_irq(unsigned int irq)
-{
-	DEBUG_IRQ("%s: irq %d\n", __func__, irq);
-	ISR(IRQ_TO_REG(irq)) = 1 << ((irq - IRQ_GPIOA(0)) % 32);
-}
-
-static void
-imx_gpio_mask_irq(unsigned int irq)
-{
-	DEBUG_IRQ("%s: irq %d\n", __func__, irq);
-	IMR(IRQ_TO_REG(irq)) &= ~( 1 << ((irq - IRQ_GPIOA(0)) % 32));
-}
-
-static void
-imx_gpio_unmask_irq(unsigned int irq)
-{
-	DEBUG_IRQ("%s: irq %d\n", __func__, irq);
-	IMR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
-}
-
-static void
-imx_gpio_handler(unsigned int mask, unsigned int irq,
-                 struct irq_desc *desc)
-{
-	while (mask) {
-		if (mask & 1) {
-			DEBUG_IRQ("handling irq %d\n", irq);
-			generic_handle_irq(irq);
-		}
-		irq++;
-		mask >>= 1;
-	}
-}
-
-static void
-imx_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = ISR(0);
-	irq = IRQ_GPIOA(0);
-	imx_gpio_handler(mask, irq, desc);
-}
-
-static void
-imx_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = ISR(1);
-	irq = IRQ_GPIOB(0);
-	imx_gpio_handler(mask, irq, desc);
-}
-
-static void
-imx_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = ISR(2);
-	irq = IRQ_GPIOC(0);
-	imx_gpio_handler(mask, irq, desc);
-}
-
-static void
-imx_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
-{
-	unsigned int mask, irq;
-
-	mask = ISR(3);
-	irq = IRQ_GPIOD(0);
-	imx_gpio_handler(mask, irq, desc);
-}
-
-static struct irq_chip imx_internal_chip = {
-	.name = "MPU",
-	.ack = imx_mask_irq,
-	.mask = imx_mask_irq,
-	.unmask = imx_unmask_irq,
-};
-
-static struct irq_chip imx_gpio_chip = {
-	.name = "GPIO",
-	.ack = imx_gpio_ack_irq,
-	.mask = imx_gpio_mask_irq,
-	.unmask = imx_gpio_unmask_irq,
-	.set_type = imx_gpio_irq_type,
-};
-
-void __init
-imx_init_irq(void)
-{
-	unsigned int irq;
-
-	DEBUG_IRQ("Initializing imx interrupts\n");
-
-	/* Disable all interrupts initially. */
-	/* Do not rely on the bootloader. */
-	__raw_writel(0, IMX_AITC_INTENABLEH);
-	__raw_writel(0, IMX_AITC_INTENABLEL);
-
-	/* Mask all GPIO interrupts as well */
-	IMR(0) = 0;
-	IMR(1) = 0;
-	IMR(2) = 0;
-	IMR(3) = 0;
-
-	for (irq = 0; irq < IMX_IRQS; irq++) {
-		set_irq_chip(irq, &imx_internal_chip);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) {
-		set_irq_chip(irq, &imx_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler(GPIO_INT_PORTA, imx_gpioa_demux_handler);
-	set_irq_chained_handler(GPIO_INT_PORTB, imx_gpiob_demux_handler);
-	set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler);
-	set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler);
-
-	/* Release masking of interrupts according to priority */
-	__raw_writel(-1, IMX_AITC_NIMASK);
-
-#ifdef CONFIG_FIQ
-	/* Initialize FIQ */
-	init_FIQ();
-#endif
-}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-imx/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-menu "IMX Implementations"
-	depends on ARCH_IMX
-
-config ARCH_MX1ADS
-	bool "mx1ads"
-	depends on ARCH_IMX
-	select ISA
-	help
-	  Say Y here if you are using the Motorola MX1ADS board
-
-endmenu
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/leds.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/leds.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/leds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/leds.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-/*
- * linux/arch/arm/mach-imx/leds.c
- *
- * Copyright (C) 2004 Sascha Hauer <sascha@saschahauer.de>
- *
- *
- * 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include "leds.h"
-
-static int __init
-leds_init(void)
-{
-	if (machine_is_mx1ads()) {
-		leds_event = mx1ads_leds_event;
-	}
-
-	return 0;
-}
-
-__initcall(leds_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/leds.h linux-libre-2.6.31-gnu/arch/arm/mach-imx/leds.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/leds.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/leds.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * arch/arm/mach-imx/leds.h
- *
- * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
- *
- * blinky lights for IMX-based systems
- *
- */
-extern void mx1ads_leds_event(led_event_t evt);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/leds-mx1ads.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/leds-mx1ads.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/leds-mx1ads.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/leds-mx1ads.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * linux/arch/arm/mach-imx/leds-mx1ads.c
- *
- * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
- *
- * Original (leds-footbridge.c) by Russell King
- *
- * 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/system.h>
-#include <asm/leds.h>
-#include "leds.h"
-
-/*
- * The MX1ADS Board has only one usable LED,
- * so select only the timer led or the
- * cpu usage led
- */
-void
-mx1ads_leds_event(led_event_t ledevt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch (ledevt) {
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		DR(0) &= ~(1<<2);
-		break;
-
-	case led_idle_end:
-		DR(0) |= 1<<2;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		DR(0) ^= 1<<2;
-#endif
-	default:
-		break;
-	}
-	local_irq_restore(flags);
-}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-imx/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y			+= irq.o time.o dma.o generic.o clock.o
-
-obj-$(CONFIG_CPU_FREQ_IMX)	+= cpufreq.o
-
-# Specific board support
-obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
-
-# Support for blinky lights
-led-y := leds.o
-
-obj-$(CONFIG_LEDS)	+=  $(led-y)
-led-$(CONFIG_ARCH_MX1ADS) += leds-mx1ads.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/Makefile.boot linux-libre-2.6.31-gnu/arch/arm/mach-imx/Makefile.boot
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/Makefile.boot	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-    zreladdr-$(CONFIG_ARCH_MX1ADS)	:= 0x08008000
-
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/mx1ads.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/mx1ads.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/mx1ads.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/mx1ads.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,180 +0,0 @@
-/*
- * arch/arm/mach-imx/mx1ads.c
- *
- * Initially based on:
- *	linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
- *	Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
- *
- * 2004 (c) MontaVista Software, Inc.
- *
- * 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/device.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <asm/system.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <mach/mmc.h>
-#include <mach/imx-uart.h>
-#include <linux/interrupt.h>
-#include "generic.h"
-
-static struct resource cs89x0_resources[] = {
-	[0] = {
-		.start	= IMX_CS4_PHYS + 0x300,
-		.end	= IMX_CS4_PHYS + 0x300 + 16,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_GPIOC(17),
-		.end	= IRQ_GPIOC(17),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cs89x0_device = {
-	.name		= "cirrus-cs89x0",
-	.num_resources	= ARRAY_SIZE(cs89x0_resources),
-	.resource	= cs89x0_resources,
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct resource imx_uart1_resources[] = {
-	[0] = {
-		.start	= 0x00206000,
-		.end	= 0x002060FF,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= (UART1_MINT_RX),
-		.end	= (UART1_MINT_RX),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= (UART1_MINT_TX),
-		.end	= (UART1_MINT_TX),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= UART1_MINT_RTS,
-		.end	= UART1_MINT_RTS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device imx_uart1_device = {
-	.name		= "imx-uart",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(imx_uart1_resources),
-	.resource	= imx_uart1_resources,
-	.dev = {
-		.platform_data = &uart_pdata,
-	}
-};
-
-static struct resource imx_uart2_resources[] = {
-	[0] = {
-		.start	= 0x00207000,
-		.end	= 0x002070FF,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= (UART2_MINT_RX),
-		.end	= (UART2_MINT_RX),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= (UART2_MINT_TX),
-		.end	= (UART2_MINT_TX),
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= UART2_MINT_RTS,
-		.end	= UART2_MINT_RTS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device imx_uart2_device = {
-	.name		= "imx-uart",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(imx_uart2_resources),
-	.resource	= imx_uart2_resources,
-	.dev = {
-		.platform_data = &uart_pdata,
-	}
-};
-
-static struct platform_device *devices[] __initdata = {
-	&cs89x0_device,
-	&imx_uart1_device,
-	&imx_uart2_device,
-};
-
-#if defined(CONFIG_MMC_IMX) || defined(CONFIG_MMC_IMX_MODULE)
-static int mx1ads_mmc_card_present(struct device *dev)
-{
-	/* MMC/SD Card Detect is PB 20 on MX1ADS V1.0.7 */
-	return (SSR(1) & (1 << 20) ? 0 : 1);
-}
-
-static struct imxmmc_platform_data mx1ads_mmc_info = {
-       .card_present = mx1ads_mmc_card_present,
-};
-#endif
-
-static void __init
-mx1ads_init(void)
-{
-#ifdef CONFIG_LEDS
-	imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2);
-#endif
-#if defined(CONFIG_MMC_IMX) || defined(CONFIG_MMC_IMX_MODULE)
-	/* SD/MMC card detect */
-	imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
-	imx_set_mmc_info(&mx1ads_mmc_info);
-#endif
-
-	imx_gpio_mode(PC9_PF_UART1_CTS);
-	imx_gpio_mode(PC10_PF_UART1_RTS);
-	imx_gpio_mode(PC11_PF_UART1_TXD);
-	imx_gpio_mode(PC12_PF_UART1_RXD);
-
-	imx_gpio_mode(PB28_PF_UART2_CTS);
-	imx_gpio_mode(PB29_PF_UART2_RTS);
-	imx_gpio_mode(PB30_PF_UART2_TXD);
-	imx_gpio_mode(PB31_PF_UART2_RXD);
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-static void __init
-mx1ads_map_io(void)
-{
-	imx_map_io();
-}
-
-MACHINE_START(MX1ADS, "Motorola MX1ADS")
-	/* Maintainer: Sascha Hauer, Pengutronix */
-	.phys_io	= 0x00200000,
-	.io_pg_offst	= ((0xe0000000) >> 18) & 0xfffc,
-	.boot_params	= 0x08000100,
-	.map_io		= mx1ads_map_io,
-	.init_irq	= imx_init_irq,
-	.timer		= &imx_timer,
-	.init_machine	= mx1ads_init,
-MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-imx/time.c linux-libre-2.6.31-gnu/arch/arm/mach-imx/time.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-imx/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-imx/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,220 +0,0 @@
-/*
- *  linux/arch/arm/mach-imx/time.c
- *
- *  Copyright (C) 2000-2001 Deep Blue Solutions
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/time.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/irq.h>
-#include <asm/mach/time.h>
-
-/* Use timer 1 as system timer */
-#define TIMER_BASE IMX_TIM1_BASE
-
-static struct clock_event_device clockevent_imx;
-static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-imx_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &clockevent_imx;
-	uint32_t tstat;
-	irqreturn_t ret = IRQ_NONE;
-
-	/* clear the interrupt */
-	tstat = IMX_TSTAT(TIMER_BASE);
-	IMX_TSTAT(TIMER_BASE) = 0;
-
-	if (tstat & TSTAT_COMP) {
-		evt->event_handler(evt);
-		ret = IRQ_HANDLED;
-	}
-
-	return ret;
-}
-
-static struct irqaction imx_timer_irq = {
-	.name		= "i.MX Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= imx_timer_interrupt,
-};
-
-/*
- * Set up timer hardware into expected mode and state.
- */
-static void __init imx_timer_hardware_init(void)
-{
-	/*
-	 * Initialise to a known state (all timers off, and timing reset)
-	 */
-	IMX_TCTL(TIMER_BASE) = 0;
-	IMX_TPRER(TIMER_BASE) = 0;
-
-	IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
-}
-
-cycle_t imx_get_cycles(struct clocksource *cs)
-{
-	return IMX_TCN(TIMER_BASE);
-}
-
-static struct clocksource clocksource_imx = {
-	.name 		= "imx_timer1",
-	.rating		= 200,
-	.read		= imx_get_cycles,
-	.mask		= 0xFFFFFFFF,
-	.shift 		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init imx_clocksource_init(unsigned long rate)
-{
-	clocksource_imx.mult =
-		clocksource_hz2mult(rate, clocksource_imx.shift);
-	clocksource_register(&clocksource_imx);
-
-	return 0;
-}
-
-static int imx_set_next_event(unsigned long evt,
-				  struct clock_event_device *unused)
-{
-	unsigned long tcmp;
-
-	tcmp = IMX_TCN(TIMER_BASE) + evt;
-	IMX_TCMP(TIMER_BASE) = tcmp;
-
-	return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0;
-}
-
-#ifdef DEBUG
-static const char *clock_event_mode_label[]={
-	[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
-	[CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
-	[CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
-	[CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
-};
-#endif /*DEBUG*/
-
-static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
-{
-	unsigned long flags;
-
-	/*
-	 * The timer interrupt generation is disabled at least
-	 * for enough time to call imx_set_next_event()
-	 */
-	local_irq_save(flags);
-	/* Disable interrupt in GPT module */
-	IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
-	if (mode != clockevent_mode) {
-		/* Set event time into far-far future */
-		IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
-		/* Clear pending interrupt */
-		IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
-	}
-
-#ifdef DEBUG
-	printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
-		clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
-#endif /*DEBUG*/
-
-	/* Remember timer mode */
-	clockevent_mode = mode;
-	local_irq_restore(flags);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		/*
-		 * Do not put overhead of interrupt enable/disable into
-		 * imx_set_next_event(), the core has about 4 minutes
-		 * to call imx_set_next_event() or shutdown clock after
-		 * mode switching
-		 */
-		local_irq_save(flags);
-		IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
-		local_irq_restore(flags);
-		break;
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_RESUME:
-		/* Left event sources disabled, no more interrupts appears */
-		break;
-	}
-}
-
-static struct clock_event_device clockevent_imx = {
-	.name		= "imx_timer1",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
-	.set_mode	= imx_set_mode,
-	.set_next_event	= imx_set_next_event,
-	.rating		= 200,
-};
-
-static int __init imx_clockevent_init(unsigned long rate)
-{
-	clockevent_imx.mult = div_sc(rate, NSEC_PER_SEC,
-					clockevent_imx.shift);
-	clockevent_imx.max_delta_ns =
-		clockevent_delta2ns(0xfffffffe, &clockevent_imx);
-	clockevent_imx.min_delta_ns =
-		clockevent_delta2ns(0xf, &clockevent_imx);
-
-	clockevent_imx.cpumask = cpumask_of(0);
-
-	clockevents_register_device(&clockevent_imx);
-
-	return 0;
-}
-
-extern int imx_clocks_init(void);
-
-static void __init imx_timer_init(void)
-{
-	struct clk *clk;
-	unsigned long rate;
-
-	imx_clocks_init();
-
-	clk = clk_get(NULL, "perclk1");
-	clk_enable(clk);
-	rate = clk_get_rate(clk);
-
-	imx_timer_hardware_init();
-	imx_clocksource_init(rate);
-
-	imx_clockevent_init(rate);
-
-	/*
-	 * Make irqs happen for the system timer
-	 */
-	setup_irq(TIM1_INT, &imx_timer_irq);
-}
-
-struct sys_timer imx_timer = {
-	.init		= imx_timer_init,
-};
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,507 @@
+/*
+ * Goramo MultiLink router platform code
+ * Copyright (C) 2006-2009 Krzysztof Halasa <khc@pm.waw.pl>
+ */
+
+#include <linux/delay.h>
+#include <linux/hdlc.h>
+#include <linux/i2c-gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <asm/mach-types.h>
+#include <asm/system.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/pci.h>
+
+#define xgpio_irq(n)		(IRQ_IXP4XX_GPIO ## n)
+#define gpio_irq(n)		xgpio_irq(n)
+
+#define SLOT_ETHA		0x0B	/* IDSEL = AD21 */
+#define SLOT_ETHB		0x0C	/* IDSEL = AD20 */
+#define SLOT_MPCI		0x0D	/* IDSEL = AD19 */
+#define SLOT_NEC		0x0E	/* IDSEL = AD18 */
+
+#define IRQ_ETHA		IRQ_IXP4XX_GPIO4
+#define IRQ_ETHB		IRQ_IXP4XX_GPIO5
+#define IRQ_NEC			IRQ_IXP4XX_GPIO3
+#define IRQ_MPCI		IRQ_IXP4XX_GPIO12
+
+/* GPIO lines */
+#define GPIO_SCL		0
+#define GPIO_SDA		1
+#define GPIO_STR		2
+#define GPIO_HSS0_DCD_N		6
+#define GPIO_HSS1_DCD_N		7
+#define GPIO_HSS0_CTS_N		10
+#define GPIO_HSS1_CTS_N		11
+#define GPIO_HSS1_RTS_N		13
+#define GPIO_HSS0_RTS_N		14
+
+/* Control outputs from 74HC4094 */
+#define CONTROL_HSS0_CLK_INT	0
+#define CONTROL_HSS1_CLK_INT	1
+#define CONTROL_HSS0_DTR_N	2
+#define CONTROL_HSS1_DTR_N	3
+#define CONTROL_EXT		4
+#define CONTROL_AUTO_RESET	5
+#define CONTROL_PCI_RESET_N	6
+#define CONTROL_EEPROM_WC_N	7
+
+/* offsets from start of flash ROM = 0x50000000 */
+#define CFG_ETH0_ADDRESS	0x40 /* 6 bytes */
+#define CFG_ETH1_ADDRESS	0x46 /* 6 bytes */
+#define CFG_REV			0x4C /* u32 */
+#define CFG_SDRAM_SIZE		0x50 /* u32 */
+#define CFG_SDRAM_CONF		0x54 /* u32 */
+#define CFG_SDRAM_MODE		0x58 /* u32 */
+#define CFG_SDRAM_REFRESH	0x5C /* u32 */
+
+#define CFG_HW_BITS		0x60 /* u32 */
+#define  CFG_HW_USB_PORTS	0x00000007 /* 0 = no NEC chip, 1-5 = ports # */
+#define  CFG_HW_HAS_PCI_SLOT	0x00000008
+#define  CFG_HW_HAS_ETH0	0x00000010
+#define  CFG_HW_HAS_ETH1	0x00000020
+#define  CFG_HW_HAS_HSS0	0x00000040
+#define  CFG_HW_HAS_HSS1	0x00000080
+#define  CFG_HW_HAS_UART0	0x00000100
+#define  CFG_HW_HAS_UART1	0x00000200
+#define  CFG_HW_HAS_EEPROM	0x00000400
+
+#define FLASH_CMD_READ_ARRAY	0xFF
+#define FLASH_CMD_READ_ID	0x90
+#define FLASH_SER_OFF		0x102 /* 0x81 in 16-bit mode */
+
+static u32 hw_bits = 0xFFFFFFFD;    /* assume all hardware present */;
+static u8 control_value;
+
+static void set_scl(u8 value)
+{
+	gpio_line_set(GPIO_SCL, !!value);
+	udelay(3);
+}
+
+static void set_sda(u8 value)
+{
+	gpio_line_set(GPIO_SDA, !!value);
+	udelay(3);
+}
+
+static void set_str(u8 value)
+{
+	gpio_line_set(GPIO_STR, !!value);
+	udelay(3);
+}
+
+static inline void set_control(int line, int value)
+{
+	if (value)
+		control_value |=  (1 << line);
+	else
+		control_value &= ~(1 << line);
+}
+
+
+static void output_control(void)
+{
+	int i;
+
+	gpio_line_config(GPIO_SCL, IXP4XX_GPIO_OUT);
+	gpio_line_config(GPIO_SDA, IXP4XX_GPIO_OUT);
+
+	for (i = 0; i < 8; i++) {
+		set_scl(0);
+		set_sda(control_value & (0x80 >> i)); /* MSB first */
+		set_scl(1);	/* active edge */
+	}
+
+	set_str(1);
+	set_str(0);
+
+	set_scl(0);
+	set_sda(1);		/* Be ready for START */
+	set_scl(1);
+}
+
+
+static void (*set_carrier_cb_tab[2])(void *pdev, int carrier);
+
+static int hss_set_clock(int port, unsigned int clock_type)
+{
+	int ctrl_int = port ? CONTROL_HSS1_CLK_INT : CONTROL_HSS0_CLK_INT;
+
+	switch (clock_type) {
+	case CLOCK_DEFAULT:
+	case CLOCK_EXT:
+		set_control(ctrl_int, 0);
+		output_control();
+		return CLOCK_EXT;
+
+	case CLOCK_INT:
+		set_control(ctrl_int, 1);
+		output_control();
+		return CLOCK_INT;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t hss_dcd_irq(int irq, void *pdev)
+{
+	int i, port = (irq == gpio_irq(GPIO_HSS1_DCD_N));
+	gpio_line_get(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N, &i);
+	set_carrier_cb_tab[port](pdev, !i);
+	return IRQ_HANDLED;
+}
+
+
+static int hss_open(int port, void *pdev,
+		    void (*set_carrier_cb)(void *pdev, int carrier))
+{
+	int i, irq;
+
+	if (!port)
+		irq = gpio_irq(GPIO_HSS0_DCD_N);
+	else
+		irq = gpio_irq(GPIO_HSS1_DCD_N);
+
+	gpio_line_get(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N, &i);
+	set_carrier_cb(pdev, !i);
+
+	set_carrier_cb_tab[!!port] = set_carrier_cb;
+
+	if ((i = request_irq(irq, hss_dcd_irq, 0, "IXP4xx HSS", pdev)) != 0) {
+		printk(KERN_ERR "ixp4xx_hss: failed to request IRQ%i (%i)\n",
+		       irq, i);
+		return i;
+	}
+
+	set_control(port ? CONTROL_HSS1_DTR_N : CONTROL_HSS0_DTR_N, 0);
+	output_control();
+	gpio_line_set(port ? GPIO_HSS1_RTS_N : GPIO_HSS0_RTS_N, 0);
+	return 0;
+}
+
+static void hss_close(int port, void *pdev)
+{
+	free_irq(port ? gpio_irq(GPIO_HSS1_DCD_N) : gpio_irq(GPIO_HSS0_DCD_N),
+		 pdev);
+	set_carrier_cb_tab[!!port] = NULL; /* catch bugs */
+
+	set_control(port ? CONTROL_HSS1_DTR_N : CONTROL_HSS0_DTR_N, 1);
+	output_control();
+	gpio_line_set(port ? GPIO_HSS1_RTS_N : GPIO_HSS0_RTS_N, 1);
+}
+
+
+/* Flash memory */
+static struct flash_platform_data flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device device_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= { .platform_data = &flash_data },
+	.num_resources	= 1,
+	.resource	= &flash_resource,
+};
+
+
+/* I^2C interface */
+static struct i2c_gpio_platform_data i2c_data = {
+	.sda_pin	= GPIO_SDA,
+	.scl_pin	= GPIO_SCL,
+};
+
+static struct platform_device device_i2c = {
+	.name		= "i2c-gpio",
+	.id		= 0,
+	.dev		= { .platform_data = &i2c_data },
+};
+
+
+/* IXP425 2 UART ports */
+static struct resource uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct plat_serial8250_port uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char __iomem *)IXP4XX_UART1_BASE_VIRT +
+			REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char __iomem *)IXP4XX_UART2_BASE_VIRT +
+			REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device device_uarts = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= uart_data,
+	.num_resources		= 2,
+	.resource		= uart_resources,
+};
+
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info eth_plat[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 32,
+	}, {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 33,
+	}
+};
+
+static struct platform_device device_eth_tab[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= eth_plat,
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev.platform_data	= eth_plat + 1,
+	}
+};
+
+
+/* IXP425 2 synchronous serial ports */
+static struct hss_plat_info hss_plat[] = {
+	{
+		.set_clock	= hss_set_clock,
+		.open		= hss_open,
+		.close		= hss_close,
+		.txreadyq	= 34,
+	}, {
+		.set_clock	= hss_set_clock,
+		.open		= hss_open,
+		.close		= hss_close,
+		.txreadyq	= 35,
+	}
+};
+
+static struct platform_device device_hss_tab[] = {
+	{
+		.name			= "ixp4xx_hss",
+		.id			= 0,
+		.dev.platform_data	= hss_plat,
+	}, {
+		.name			= "ixp4xx_hss",
+		.id			= 1,
+		.dev.platform_data	= hss_plat + 1,
+	}
+};
+
+
+static struct platform_device *device_tab[6] __initdata = {
+	&device_flash,		/* index 0 */
+};
+
+static inline u8 __init flash_readb(u8 __iomem *flash, u32 addr)
+{
+#ifdef __ARMEB__
+	return __raw_readb(flash + addr);
+#else
+	return __raw_readb(flash + (addr ^ 3));
+#endif
+}
+
+static inline u16 __init flash_readw(u8 __iomem *flash, u32 addr)
+{
+#ifdef __ARMEB__
+	return __raw_readw(flash + addr);
+#else
+	return __raw_readw(flash + (addr ^ 2));
+#endif
+}
+
+static void __init gmlr_init(void)
+{
+	u8 __iomem *flash;
+	int i, devices = 1; /* flash */
+
+	ixp4xx_sys_init();
+
+	if ((flash = ioremap(IXP4XX_EXP_BUS_BASE_PHYS, 0x80)) == NULL)
+		printk(KERN_ERR "goramo-mlr: unable to access system"
+		       " configuration data\n");
+	else {
+		system_rev = __raw_readl(flash + CFG_REV);
+		hw_bits = __raw_readl(flash + CFG_HW_BITS);
+
+		for (i = 0; i < ETH_ALEN; i++) {
+			eth_plat[0].hwaddr[i] =
+				flash_readb(flash, CFG_ETH0_ADDRESS + i);
+			eth_plat[1].hwaddr[i] =
+				flash_readb(flash, CFG_ETH1_ADDRESS + i);
+		}
+
+		__raw_writew(FLASH_CMD_READ_ID, flash);
+		system_serial_high = flash_readw(flash, FLASH_SER_OFF);
+		system_serial_high <<= 16;
+		system_serial_high |= flash_readw(flash, FLASH_SER_OFF + 2);
+		system_serial_low = flash_readw(flash, FLASH_SER_OFF + 4);
+		system_serial_low <<= 16;
+		system_serial_low |= flash_readw(flash, FLASH_SER_OFF + 6);
+		__raw_writew(FLASH_CMD_READ_ARRAY, flash);
+
+		iounmap(flash);
+	}
+
+	switch (hw_bits & (CFG_HW_HAS_UART0 | CFG_HW_HAS_UART1)) {
+	case CFG_HW_HAS_UART0:
+		memset(&uart_data[1], 0, sizeof(uart_data[1]));
+		device_uarts.num_resources = 1;
+		break;
+
+	case CFG_HW_HAS_UART1:
+		device_uarts.dev.platform_data = &uart_data[1];
+		device_uarts.resource = &uart_resources[1];
+		device_uarts.num_resources = 1;
+		break;
+	}
+	if (hw_bits & (CFG_HW_HAS_UART0 | CFG_HW_HAS_UART1))
+		device_tab[devices++] = &device_uarts; /* max index 1 */
+
+	if (hw_bits & CFG_HW_HAS_ETH0)
+		device_tab[devices++] = &device_eth_tab[0]; /* max index 2 */
+	if (hw_bits & CFG_HW_HAS_ETH1)
+		device_tab[devices++] = &device_eth_tab[1]; /* max index 3 */
+
+	if (hw_bits & CFG_HW_HAS_HSS0)
+		device_tab[devices++] = &device_hss_tab[0]; /* max index 4 */
+	if (hw_bits & CFG_HW_HAS_HSS1)
+		device_tab[devices++] = &device_hss_tab[1]; /* max index 5 */
+
+	if (hw_bits & CFG_HW_HAS_EEPROM)
+		device_tab[devices++] = &device_i2c; /* max index 6 */
+
+	gpio_line_config(GPIO_SCL, IXP4XX_GPIO_OUT);
+	gpio_line_config(GPIO_SDA, IXP4XX_GPIO_OUT);
+	gpio_line_config(GPIO_STR, IXP4XX_GPIO_OUT);
+	gpio_line_config(GPIO_HSS0_RTS_N, IXP4XX_GPIO_OUT);
+	gpio_line_config(GPIO_HSS1_RTS_N, IXP4XX_GPIO_OUT);
+	gpio_line_config(GPIO_HSS0_DCD_N, IXP4XX_GPIO_IN);
+	gpio_line_config(GPIO_HSS1_DCD_N, IXP4XX_GPIO_IN);
+	set_irq_type(gpio_irq(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH);
+	set_irq_type(gpio_irq(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH);
+
+	set_control(CONTROL_HSS0_DTR_N, 1);
+	set_control(CONTROL_HSS1_DTR_N, 1);
+	set_control(CONTROL_EEPROM_WC_N, 1);
+	set_control(CONTROL_PCI_RESET_N, 1);
+	output_control();
+
+	msleep(1);	      /* Wait for PCI devices to initialize */
+
+	flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	platform_add_devices(device_tab, devices);
+}
+
+
+#ifdef CONFIG_PCI
+static void __init gmlr_pci_preinit(void)
+{
+	set_irq_type(IRQ_ETHA, IRQ_TYPE_LEVEL_LOW);
+	set_irq_type(IRQ_ETHB, IRQ_TYPE_LEVEL_LOW);
+	set_irq_type(IRQ_NEC, IRQ_TYPE_LEVEL_LOW);
+	set_irq_type(IRQ_MPCI, IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static void __init gmlr_pci_postinit(void)
+{
+	if ((hw_bits & CFG_HW_USB_PORTS) >= 2 &&
+	    (hw_bits & CFG_HW_USB_PORTS) < 5) {
+		/* need to adjust number of USB ports on NEC chip */
+		u32 value, addr = BIT(32 - SLOT_NEC) | 0xE0;
+		if (!ixp4xx_pci_read(addr, NP_CMD_CONFIGREAD, &value)) {
+			value &= ~7;
+			value |= (hw_bits & CFG_HW_USB_PORTS);
+			ixp4xx_pci_write(addr, NP_CMD_CONFIGWRITE, value);
+		}
+	}
+}
+
+static int __init gmlr_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	switch(slot) {
+	case SLOT_ETHA:	return IRQ_ETHA;
+	case SLOT_ETHB:	return IRQ_ETHB;
+	case SLOT_NEC:	return IRQ_NEC;
+	default:	return IRQ_MPCI;
+	}
+}
+
+static struct hw_pci gmlr_hw_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit	= gmlr_pci_preinit,
+	.postinit	= gmlr_pci_postinit,
+	.swizzle	= pci_std_swizzle,
+	.setup		= ixp4xx_setup,
+	.scan		= ixp4xx_scan_bus,
+	.map_irq	= gmlr_map_irq,
+};
+
+static int __init gmlr_pci_init(void)
+{
+	if (machine_is_goramo_mlr() &&
+	    (hw_bits & (CFG_HW_USB_PORTS | CFG_HW_HAS_PCI_SLOT)))
+		pci_common_init(&gmlr_hw_pci);
+	return 0;
+}
+
+subsys_initcall(gmlr_pci_init);
+#endif /* CONFIG_PCI */
+
+
+MACHINE_START(GORAMO_MLR, "MultiLink")
+	/* Maintainer: Krzysztof Halasa */
+	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+	.io_pg_offst	= ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer		= &ixp4xx_timer,
+	.boot_params	= 0x0100,
+	.init_machine	= gmlr_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/include/mach/cpu.h linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/include/mach/cpu.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/include/mach/cpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/include/mach/cpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,8 @@
 #define IXP46X_PROCESSOR_ID_VALUE	0x69054200 /* including IXP455 */
 #define IXP46X_PROCESSOR_ID_MASK	0xfffffff0
 
+#define cpu_is_ixp42x_rev_a0() ((read_cpuid_id() & (IXP42X_PROCESSOR_ID_MASK | 0xF)) == \
+				IXP42X_PROCESSOR_ID_VALUE)
 #define cpu_is_ixp42x()	((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \
 			 IXP42X_PROCESSOR_ID_VALUE)
 #define cpu_is_ixp43x()	((read_cpuid_id() & IXP43X_PROCESSOR_ID_MASK) == \
@@ -35,8 +37,11 @@
 
 static inline u32 ixp4xx_read_feature_bits(void)
 {
-	unsigned int val = ~*IXP4XX_EXP_CFG2;
+	u32 val = ~*IXP4XX_EXP_CFG2;
 
+	if (cpu_is_ixp42x_rev_a0())
+		return IXP42X_FEATURE_MASK & ~(IXP4XX_FEATURE_RCOMP |
+					       IXP4XX_FEATURE_AES);
 	if (cpu_is_ixp42x())
 		return val & IXP42X_FEATURE_MASK;
 	if (cpu_is_ixp43x())
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/include/mach/io.h linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/include/mach/io.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/include/mach/io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/include/mach/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 
 #include <mach/hardware.h>
 
-#define IO_SPACE_LIMIT 0xffff0000
+#define IO_SPACE_LIMIT 0x0000ffff
 
 extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
 extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/include/mach/qmgr.h linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/include/mach/qmgr.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/include/mach/qmgr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/include/mach/qmgr.h	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,7 @@
 #define DEBUG_QMGR	0
 
 #define HALF_QUEUES	32
-#define QUEUES		64	/* only 32 lower queues currently supported */
+#define QUEUES		64
 #define MAX_QUEUE_LENGTH 4	/* in dwords */
 
 #define QUEUE_STAT1_EMPTY		1 /* queue status bits */
@@ -110,48 +110,95 @@
 	return val;
 }
 
-static inline int qmgr_get_stat1(unsigned int queue)
+static inline int __qmgr_get_stat1(unsigned int queue)
 {
 	extern struct qmgr_regs __iomem *qmgr_regs;
 	return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
 		>> ((queue & 7) << 2)) & 0xF;
 }
 
-static inline int qmgr_get_stat2(unsigned int queue)
+static inline int __qmgr_get_stat2(unsigned int queue)
 {
 	extern struct qmgr_regs __iomem *qmgr_regs;
+	BUG_ON(queue >= HALF_QUEUES);
 	return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
 		>> ((queue & 0xF) << 1)) & 0x3;
 }
 
+/**
+ * qmgr_stat_empty() - checks if a hardware queue is empty
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is empty.
+ */
 static inline int qmgr_stat_empty(unsigned int queue)
 {
-	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY);
+	BUG_ON(queue >= HALF_QUEUES);
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY;
 }
 
-static inline int qmgr_stat_nearly_empty(unsigned int queue)
+/**
+ * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is below low watermark.
+ */
+static inline int qmgr_stat_below_low_watermark(unsigned int queue)
 {
-	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY);
+	extern struct qmgr_regs __iomem *qmgr_regs;
+	if (queue >= HALF_QUEUES)
+		return (__raw_readl(&qmgr_regs->statne_h) >>
+			(queue - HALF_QUEUES)) & 0x01;
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY;
 }
 
-static inline int qmgr_stat_nearly_full(unsigned int queue)
+/**
+ * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is above high watermark
+ */
+static inline int qmgr_stat_above_high_watermark(unsigned int queue)
 {
-	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL);
+	BUG_ON(queue >= HALF_QUEUES);
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL;
 }
 
+/**
+ * qmgr_stat_full() - checks if a hardware queue is full
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is full.
+ */
 static inline int qmgr_stat_full(unsigned int queue)
 {
-	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_FULL);
+	extern struct qmgr_regs __iomem *qmgr_regs;
+	if (queue >= HALF_QUEUES)
+		return (__raw_readl(&qmgr_regs->statf_h) >>
+			(queue - HALF_QUEUES)) & 0x01;
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL;
 }
 
+/**
+ * qmgr_stat_underflow() - checks if a hardware queue experienced underflow
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue experienced underflow.
+ */
 static inline int qmgr_stat_underflow(unsigned int queue)
 {
-	return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW);
+	return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW;
 }
 
+/**
+ * qmgr_stat_overflow() - checks if a hardware queue experienced overflow
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue experienced overflow.
+ */
 static inline int qmgr_stat_overflow(unsigned int queue)
 {
-	return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW);
+	return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW;
 }
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/ixp4xx_npe.c linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/ixp4xx_npe.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/ixp4xx_npe.c	2012-03-22 19:10:36.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/ixp4xx_npe.c	2012-03-22 20:07:10.000000000 -0400
@@ -386,15 +386,6 @@
 	/* reset the NPE */
 	ixp4xx_write_feature_bits(val &
 				  ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
-	for (i = 0; i < MAX_RETRIES; i++) {
-		if (!(ixp4xx_read_feature_bits() &
-		      (IXP4XX_FEATURE_RESET_NPEA << npe->id)))
-			break;	/* reset completed */
-		udelay(1);
-	}
-	if (i == MAX_RETRIES)
-		return -ETIMEDOUT;
-
 	/* deassert reset */
 	ixp4xx_write_feature_bits(val |
 				  (IXP4XX_FEATURE_RESET_NPEA << npe->id));
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,8 +18,8 @@
 static struct resource *mem_res;
 static spinlock_t qmgr_lock;
 static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
-static void (*irq_handlers[HALF_QUEUES])(void *pdev);
-static void *irq_pdevs[HALF_QUEUES];
+static void (*irq_handlers[QUEUES])(void *pdev);
+static void *irq_pdevs[QUEUES];
 
 #if DEBUG_QMGR
 char qmgr_queue_descs[QUEUES][32];
@@ -28,51 +28,112 @@
 void qmgr_set_irq(unsigned int queue, int src,
 		  void (*handler)(void *pdev), void *pdev)
 {
-	u32 __iomem *reg = &qmgr_regs->irqsrc[queue / 8]; /* 8 queues / u32 */
-	int bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
 	unsigned long flags;
 
-	src &= 7;
 	spin_lock_irqsave(&qmgr_lock, flags);
-	__raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg);
+	if (queue < HALF_QUEUES) {
+		u32 __iomem *reg;
+		int bit;
+		BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
+		reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
+		bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
+		__raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit),
+			     reg);
+	} else
+		/* IRQ source for queues 32-63 is fixed */
+		BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY);
+
 	irq_handlers[queue] = handler;
 	irq_pdevs[queue] = pdev;
 	spin_unlock_irqrestore(&qmgr_lock, flags);
 }
 
 
-static irqreturn_t qmgr_irq1(int irq, void *pdev)
+static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
 {
-	int i;
-	u32 val = __raw_readl(&qmgr_regs->irqstat[0]);
-	__raw_writel(val, &qmgr_regs->irqstat[0]); /* ACK */
+	int i, ret = 0;
+	u32 en_bitmap, src, stat;
 
-	for (i = 0; i < HALF_QUEUES; i++)
-		if (val & (1 << i))
+	/* ACK - it may clear any bits so don't rely on it */
+	__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
+
+	en_bitmap = qmgr_regs->irqen[0];
+	while (en_bitmap) {
+		i = __fls(en_bitmap); /* number of the last "low" queue */
+		en_bitmap &= ~BIT(i);
+		src = qmgr_regs->irqsrc[i >> 3];
+		stat = qmgr_regs->stat1[i >> 3];
+		if (src & 4) /* the IRQ condition is inverted */
+			stat = ~stat;
+		if (stat & BIT(src & 3)) {
 			irq_handlers[i](irq_pdevs[i]);
+			ret = IRQ_HANDLED;
+		}
+	}
+	return ret;
+}
 
-	return val ? IRQ_HANDLED : 0;
+
+static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
+{
+	int i, ret = 0;
+	u32 req_bitmap;
+
+	/* ACK - it may clear any bits so don't rely on it */
+	__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);
+
+	req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h;
+	while (req_bitmap) {
+		i = __fls(req_bitmap); /* number of the last "high" queue */
+		req_bitmap &= ~BIT(i);
+		irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]);
+		ret = IRQ_HANDLED;
+	}
+	return ret;
+}
+
+
+static irqreturn_t qmgr_irq(int irq, void *pdev)
+{
+	int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1);
+	u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);
+
+	if (!req_bitmap)
+		return 0;
+	__raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */
+
+	while (req_bitmap) {
+		i = __fls(req_bitmap); /* number of the last queue */
+		req_bitmap &= ~BIT(i);
+		i += half * HALF_QUEUES;
+		irq_handlers[i](irq_pdevs[i]);
+	}
+	return IRQ_HANDLED;
 }
 
 
 void qmgr_enable_irq(unsigned int queue)
 {
 	unsigned long flags;
+	int half = queue / 32;
+	u32 mask = 1 << (queue & (HALF_QUEUES - 1));
 
 	spin_lock_irqsave(&qmgr_lock, flags);
-	__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue),
-		     &qmgr_regs->irqen[0]);
+	__raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
+		     &qmgr_regs->irqen[half]);
 	spin_unlock_irqrestore(&qmgr_lock, flags);
 }
 
 void qmgr_disable_irq(unsigned int queue)
 {
 	unsigned long flags;
+	int half = queue / 32;
+	u32 mask = 1 << (queue & (HALF_QUEUES - 1));
 
 	spin_lock_irqsave(&qmgr_lock, flags);
-	__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue),
-		     &qmgr_regs->irqen[0]);
-	__raw_writel(1 << queue, &qmgr_regs->irqstat[0]); /* clear */
+	__raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
+		     &qmgr_regs->irqen[half]);
+	__raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
 	spin_unlock_irqrestore(&qmgr_lock, flags);
 }
 
@@ -98,8 +159,7 @@
 	u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
 	int err;
 
-	if (queue >= HALF_QUEUES)
-		return -ERANGE;
+	BUG_ON(queue >= QUEUES);
 
 	if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
 		return -EINVAL;
@@ -180,7 +240,7 @@
 {
 	u32 cfg, addr, mask[4];
 
-	BUG_ON(queue >= HALF_QUEUES); /* not in valid range */
+	BUG_ON(queue >= QUEUES); /* not in valid range */
 
 	spin_lock_irq(&qmgr_lock);
 	cfg = __raw_readl(&qmgr_regs->sram[queue]);
@@ -224,6 +284,8 @@
 static int qmgr_init(void)
 {
 	int i, err;
+	irq_handler_t handler1, handler2;
+
 	mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
 				     IXP4XX_QMGR_REGION_SIZE,
 				     "IXP4xx Queue Manager");
@@ -247,23 +309,42 @@
 		__raw_writel(0, &qmgr_regs->irqen[i]);
 	}
 
+	__raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
+	__raw_writel(0, &qmgr_regs->statf_h);
+
 	for (i = 0; i < QUEUES; i++)
 		__raw_writel(0, &qmgr_regs->sram[i]);
 
-	err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0,
-			  "IXP4xx Queue Manager", NULL);
+	if (cpu_is_ixp42x_rev_a0()) {
+		handler1 = qmgr_irq1_a0;
+		handler2 = qmgr_irq2_a0;
+	} else
+		handler1 = handler2 = qmgr_irq;
+
+	err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager",
+			  NULL);
 	if (err) {
-		printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
-		       IRQ_IXP4XX_QM1);
+		printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
+		       IRQ_IXP4XX_QM1, err);
 		goto error_irq;
 	}
 
+	err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager",
+			  NULL);
+	if (err) {
+		printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
+		       IRQ_IXP4XX_QM2, err);
+		goto error_irq2;
+	}
+
 	used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
 	spin_lock_init(&qmgr_lock);
 
 	printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
 	return 0;
 
+error_irq2:
+	free_irq(IRQ_IXP4XX_QM1, NULL);
 error_irq:
 	iounmap(qmgr_regs);
 error_map:
@@ -274,7 +355,9 @@
 static void qmgr_remove(void)
 {
 	free_irq(IRQ_IXP4XX_QM1, NULL);
+	free_irq(IRQ_IXP4XX_QM2, NULL);
 	synchronize_irq(IRQ_IXP4XX_QM1);
+	synchronize_irq(IRQ_IXP4XX_QM2);
 	iounmap(qmgr_regs);
 	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -78,6 +78,12 @@
 	  IXDP465 Development Platform (Also known as BMP).
 	  For more information on this platform, see <file:Documentation/arm/IXP4xx>.
 
+config MACH_GORAMO_MLR
+	bool "GORAMO Multi Link Router"
+	help
+	  Say 'Y' here if you want your kernel to support GORAMO
+	  MultiLink router.
+
 config MACH_KIXRP435
 	bool "KIXRP435"
 	help
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-ixp4xx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ixp4xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 obj-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-setup.o
 obj-$(CONFIG_MACH_WG302V2)	+= wg302v2-setup.o
 obj-$(CONFIG_MACH_FSG)		+= fsg-setup.o
+obj-$(CONFIG_MACH_GORAMO_MLR)	+= goramo_mlr.o
 
 obj-$(CONFIG_PCI)		+= $(obj-pci-$(CONFIG_PCI)) common-pci.o
 obj-$(CONFIG_IXP4XX_QMGR)	+= ixp4xx_qmgr.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/addr-map.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/addr-map.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/addr-map.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/addr-map.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
  */
 #define TARGET_DDR		0
 #define TARGET_DEV_BUS		1
+#define TARGET_SRAM		3
 #define TARGET_PCIE		4
 #define ATTR_DEV_SPI_ROM	0x1e
 #define ATTR_DEV_BOOT		0x1d
@@ -30,6 +31,7 @@
 #define ATTR_DEV_CS0		0x3e
 #define ATTR_PCIE_IO		0xe0
 #define ATTR_PCIE_MEM		0xe8
+#define ATTR_SRAM		0x01
 
 /*
  * Helpers to get DDR bank info
@@ -48,7 +50,6 @@
 
 
 struct mbus_dram_target_info kirkwood_mbus_dram_info;
-static int __initdata win_alloc_count;
 
 static int __init cpu_win_can_remap(int win)
 {
@@ -112,7 +113,11 @@
 	setup_cpu_win(2, KIRKWOOD_NAND_MEM_PHYS_BASE, KIRKWOOD_NAND_MEM_SIZE,
 		      TARGET_DEV_BUS, ATTR_DEV_NAND, -1);
 
-	win_alloc_count = 3;
+	/*
+	 * Setup window for SRAM.
+	 */
+	setup_cpu_win(3, KIRKWOOD_SRAM_PHYS_BASE, KIRKWOOD_SRAM_SIZE,
+		      TARGET_SRAM, ATTR_SRAM, -1);
 
 	/*
 	 * Setup MBUS dram target info.
@@ -140,8 +145,3 @@
 	}
 	kirkwood_mbus_dram_info.num_cs = cs;
 }
-
-void __init kirkwood_setup_sram_win(u32 base, u32 size)
-{
-	setup_cpu_win(win_alloc_count++, base, size, 0x03, 0x00, -1);
-}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/common.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/common.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/common.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/mv643xx_i2c.h>
 #include <linux/ata_platform.h>
+#include <linux/mtd/nand.h>
 #include <linux/spi/orion_spi.h>
 #include <net/dsa.h>
 #include <asm/page.h>
@@ -29,6 +30,7 @@
 #include <plat/mvsdio.h>
 #include <plat/mv_xor.h>
 #include <plat/orion_nand.h>
+#include <plat/orion_wdt.h>
 #include <plat/time.h>
 #include "common.h"
 
@@ -54,6 +56,13 @@
 	iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
 }
 
+/*
+ * Default clock control bits.  Any bit _not_ set in this variable
+ * will be cleared from the hardware after platform devices have been
+ * registered.  Some reserved bits must be set to 1.
+ */
+unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED;
+	
 
 /*****************************************************************************
  * EHCI
@@ -95,6 +104,7 @@
 
 void __init kirkwood_ehci_init(void)
 {
+	kirkwood_clk_ctrl |= CGC_USB0;
 	platform_device_register(&kirkwood_ehci);
 }
 
@@ -151,6 +161,7 @@
 
 void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
 {
+	kirkwood_clk_ctrl |= CGC_GE0;
 	eth_data->shared = &kirkwood_ge00_shared;
 	kirkwood_ge00.dev.platform_data = eth_data;
 
@@ -212,6 +223,7 @@
 
 void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
 {
+	kirkwood_clk_ctrl |= CGC_GE1;
 	eth_data->shared = &kirkwood_ge01_shared;
 	kirkwood_ge01.dev.platform_data = eth_data;
 
@@ -258,6 +270,43 @@
 
 
 /*****************************************************************************
+ * NAND flash
+ ****************************************************************************/
+static struct resource kirkwood_nand_resource = {
+	.flags		= IORESOURCE_MEM,
+	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
+	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
+				KIRKWOOD_NAND_MEM_SIZE - 1,
+};
+
+static struct orion_nand_data kirkwood_nand_data = {
+	.cle		= 0,
+	.ale		= 1,
+	.width		= 8,
+};
+
+static struct platform_device kirkwood_nand_flash = {
+	.name		= "orion_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &kirkwood_nand_data,
+	},
+	.resource	= &kirkwood_nand_resource,
+	.num_resources	= 1,
+};
+
+void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
+			       int chip_delay)
+{
+	kirkwood_clk_ctrl |= CGC_RUNIT;
+	kirkwood_nand_data.parts = parts;
+	kirkwood_nand_data.nr_parts = nr_parts;
+	kirkwood_nand_data.chip_delay = chip_delay;
+	platform_device_register(&kirkwood_nand_flash);
+}
+
+
+/*****************************************************************************
  * SoC RTC
  ****************************************************************************/
 static struct resource kirkwood_rtc_resource = {
@@ -301,6 +350,9 @@
 
 void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data)
 {
+	kirkwood_clk_ctrl |= CGC_SATA0;
+	if (sata_data->n_ports > 1)
+		kirkwood_clk_ctrl |= CGC_SATA1;
 	sata_data->dram = &kirkwood_mbus_dram_info;
 	kirkwood_sata.dev.platform_data = sata_data;
 	platform_device_register(&kirkwood_sata);
@@ -346,6 +398,7 @@
 	else
 		mvsdio_data->clock = 200000000;
 	mvsdio_data->dram = &kirkwood_mbus_dram_info;
+	kirkwood_clk_ctrl |= CGC_SDIO;
 	kirkwood_sdio.dev.platform_data = mvsdio_data;
 	platform_device_register(&kirkwood_sdio);
 }
@@ -377,6 +430,7 @@
 
 void __init kirkwood_spi_init()
 {
+	kirkwood_clk_ctrl |= CGC_RUNIT;
 	platform_device_register(&kirkwood_spi);
 }
 
@@ -507,6 +561,43 @@
 
 
 /*****************************************************************************
+ * Cryptographic Engines and Security Accelerator (CESA)
+ ****************************************************************************/
+
+static struct resource kirkwood_crypto_res[] = {
+	{
+		.name   = "regs",
+		.start  = CRYPTO_PHYS_BASE,
+		.end    = CRYPTO_PHYS_BASE + 0xffff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.name   = "sram",
+		.start  = KIRKWOOD_SRAM_PHYS_BASE,
+		.end    = KIRKWOOD_SRAM_PHYS_BASE + KIRKWOOD_SRAM_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.name   = "crypto interrupt",
+		.start  = IRQ_KIRKWOOD_CRYPTO,
+		.end    = IRQ_KIRKWOOD_CRYPTO,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device kirkwood_crypto_device = {
+	.name           = "mv_crypto",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(kirkwood_crypto_res),
+	.resource       = kirkwood_crypto_res,
+};
+
+void __init kirkwood_crypto_init(void)
+{
+	kirkwood_clk_ctrl |= CGC_CRYPTO;
+	platform_device_register(&kirkwood_crypto_device);
+}
+
+
+/*****************************************************************************
  * XOR
  ****************************************************************************/
 static struct mv_xor_platform_shared_data kirkwood_xor_shared_data = {
@@ -597,6 +688,7 @@
 
 static void __init kirkwood_xor0_init(void)
 {
+	kirkwood_clk_ctrl |= CGC_XOR0;
 	platform_device_register(&kirkwood_xor0_shared);
 
 	/*
@@ -695,6 +787,7 @@
 
 static void __init kirkwood_xor1_init(void)
 {
+	kirkwood_clk_ctrl |= CGC_XOR1;
 	platform_device_register(&kirkwood_xor1_shared);
 
 	/*
@@ -713,6 +806,29 @@
 
 
 /*****************************************************************************
+ * Watchdog
+ ****************************************************************************/
+static struct orion_wdt_platform_data kirkwood_wdt_data = {
+	.tclk		= 0,
+};
+
+static struct platform_device kirkwood_wdt_device = {
+	.name		= "orion_wdt",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &kirkwood_wdt_data,
+	},
+	.num_resources	= 0,
+};
+
+static void __init kirkwood_wdt_init(void)
+{
+	kirkwood_wdt_data.tclk = kirkwood_tclk;
+	platform_device_register(&kirkwood_wdt_device);
+}
+
+
+/*****************************************************************************
  * Time handling
  ****************************************************************************/
 int kirkwood_tclk;
@@ -804,6 +920,49 @@
 
 	/* internal devices that every board has */
 	kirkwood_rtc_init();
+	kirkwood_wdt_init();
 	kirkwood_xor0_init();
 	kirkwood_xor1_init();
+	kirkwood_crypto_init();
 }
+
+static int __init kirkwood_clock_gate(void)
+{
+	unsigned int curr = readl(CLOCK_GATING_CTRL);
+
+	printk(KERN_DEBUG "Gating clock of unused units\n");
+	printk(KERN_DEBUG "before: 0x%08x\n", curr);
+
+	/* Make sure those units are accessible */
+	writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0, CLOCK_GATING_CTRL);
+
+	/* For SATA: first shutdown the phy */
+	if (!(kirkwood_clk_ctrl & CGC_SATA0)) {
+		/* Disable PLL and IVREF */
+		writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
+		/* Disable PHY */
+		writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
+	}
+	if (!(kirkwood_clk_ctrl & CGC_SATA1)) {
+		/* Disable PLL and IVREF */
+		writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
+		/* Disable PHY */
+		writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
+	}
+	
+	/* For PCIe: first shutdown the phy */
+	if (!(kirkwood_clk_ctrl & CGC_PEX0)) {
+		writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
+		while (1)
+			if (readl(PCIE_STATUS) & 0x1)
+				break;
+		writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
+	}
+
+	/* Now gate clock the required units */
+	writel(kirkwood_clk_ctrl, CLOCK_GATING_CTRL);
+	printk(KERN_DEBUG " after: 0x%08x\n", readl(CLOCK_GATING_CTRL));
+
+	return 0;
+}
+late_initcall(kirkwood_clock_gate);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/common.h linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/common.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/common.h	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 struct mv643xx_eth_platform_data;
 struct mv_sata_platform_data;
 struct mvsdio_platform_data;
+struct mtd_partition;
 
 /*
  * Basic Kirkwood init functions used early by machine-setup.
@@ -25,7 +26,6 @@
 
 extern struct mbus_dram_target_info kirkwood_mbus_dram_info;
 void kirkwood_setup_cpu_mbus(void);
-void kirkwood_setup_sram_win(u32 base, u32 size);
 
 void kirkwood_pcie_id(u32 *dev, u32 *rev);
 
@@ -40,9 +40,11 @@
 void kirkwood_i2c_init(void);
 void kirkwood_uart0_init(void);
 void kirkwood_uart1_init(void);
+void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
 
 extern int kirkwood_tclk;
 extern struct sys_timer kirkwood_timer;
 
+#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/cpuidle.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/cpuidle.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/cpuidle.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/cpuidle.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,96 @@
+/*
+ * arch/arm/mach-kirkwood/cpuidle.c
+ *
+ * CPU idle Marvell Kirkwood SoCs
+ *
+ * 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.
+ *
+ * The cpu idle uses wait-for-interrupt and DDR self refresh in order
+ * to implement two idle states -
+ * #1 wait-for-interrupt
+ * #2 wait-for-interrupt and DDR self refresh
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <asm/proc-fns.h>
+#include <mach/kirkwood.h>
+
+#define KIRKWOOD_MAX_STATES	2
+
+static struct cpuidle_driver kirkwood_idle_driver = {
+	.name =         "kirkwood_idle",
+	.owner =        THIS_MODULE,
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
+
+/* Actual code that puts the SoC in different idle states */
+static int kirkwood_enter_idle(struct cpuidle_device *dev,
+			       struct cpuidle_state *state)
+{
+	struct timeval before, after;
+	int idle_time;
+
+	local_irq_disable();
+	do_gettimeofday(&before);
+	if (state == &dev->states[0])
+		/* Wait for interrupt state */
+		cpu_do_idle();
+	else if (state == &dev->states[1]) {
+		/*
+		 * Following write will put DDR in self refresh.
+		 * Note that we have 256 cycles before DDR puts it
+		 * self in self-refresh, so the wait-for-interrupt
+		 * call afterwards won't get the DDR from self refresh
+		 * mode.
+		 */
+		writel(0x7, DDR_OPERATION_BASE);
+		cpu_do_idle();
+	}
+	do_gettimeofday(&after);
+	local_irq_enable();
+	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+			(after.tv_usec - before.tv_usec);
+	return idle_time;
+}
+
+/* Initialize CPU idle by registering the idle states */
+static int kirkwood_init_cpuidle(void)
+{
+	struct cpuidle_device *device;
+
+	cpuidle_register_driver(&kirkwood_idle_driver);
+
+	device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
+	device->state_count = KIRKWOOD_MAX_STATES;
+
+	/* Wait for interrupt state */
+	device->states[0].enter = kirkwood_enter_idle;
+	device->states[0].exit_latency = 1;
+	device->states[0].target_residency = 10000;
+	device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(device->states[0].name, "WFI");
+	strcpy(device->states[0].desc, "Wait for interrupt");
+
+	/* Wait for interrupt and DDR self refresh state */
+	device->states[1].enter = kirkwood_enter_idle;
+	device->states[1].exit_latency = 10;
+	device->states[1].target_residency = 10000;
+	device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+	strcpy(device->states[1].name, "DDR SR");
+	strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
+
+	if (cpuidle_register_device(device)) {
+		printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+device_initcall(kirkwood_init_cpuidle);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,14 +11,12 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <plat/orion_nand.h>
 #include <plat/mvsdio.h>
 #include "common.h"
 #include "mpp.h"
@@ -39,32 +37,6 @@
 	},
 };
 
-static struct resource db88f6281_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
-	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
-			  KIRKWOOD_NAND_MEM_SIZE - 1,
-};
-
-static struct orion_nand_data db88f6281_nand_data = {
-	.parts		= db88f6281_nand_parts,
-	.nr_parts	= ARRAY_SIZE(db88f6281_nand_parts),
-	.cle		= 0,
-	.ale		= 1,
-	.width		= 8,
-	.chip_delay	= 25,
-};
-
-static struct platform_device db88f6281_nand_flash = {
-	.name		= "orion_nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &db88f6281_nand_data,
-	},
-	.resource	= &db88f6281_nand_resource,
-	.num_resources	= 1,
-};
-
 static struct mv643xx_eth_platform_data db88f6281_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
@@ -92,13 +64,12 @@
 	kirkwood_init();
 	kirkwood_mpp_conf(db88f6281_mpp_config);
 
+	kirkwood_nand_init(ARRAY_AND_SIZE(db88f6281_nand_parts), 25);
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&db88f6281_ge00_data);
 	kirkwood_sata_init(&db88f6281_sata_data);
 	kirkwood_uart0_init();
 	kirkwood_sdio_init(&db88f6281_mvsdio_data);
-	
-	platform_device_register(&db88f6281_nand_flash);
 }
 
 static int __init db88f6281_pci_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,12 +17,15 @@
 #define CPU_RESET		0x00000002
 
 #define RSTOUTn_MASK		(BRIDGE_VIRT_BASE | 0x0108)
+#define WDT_RESET_OUT_EN	0x00000002
 #define SOFT_RESET_OUT_EN	0x00000004
 
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define SOFT_RESET		0x00000001
 
 #define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
+#define WDT_INT_REQ		0x0008
+
 #define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
 #define BRIDGE_INT_TIMER0	0x0002
 #define BRIDGE_INT_TIMER1	0x0004
@@ -39,4 +42,22 @@
 #define L2_CONFIG_REG		(BRIDGE_VIRT_BASE | 0x0128)
 #define L2_WRITETHROUGH		0x00000010
 
+#define CLOCK_GATING_CTRL	(BRIDGE_VIRT_BASE | 0x11c)
+#define CGC_GE0			(1 << 0)
+#define CGC_PEX0		(1 << 2)
+#define CGC_USB0		(1 << 3)
+#define CGC_SDIO		(1 << 4)
+#define CGC_TSU			(1 << 5)
+#define CGC_DUNIT		(1 << 6)
+#define CGC_RUNIT		(1 << 7)
+#define CGC_XOR0		(1 << 8)
+#define CGC_AUDIO		(1 << 9)
+#define CGC_SATA0		(1 << 14)
+#define CGC_SATA1		(1 << 15)
+#define CGC_XOR1		(1 << 16)
+#define CGC_CRYPTO		(1 << 17)
+#define CGC_GE1			(1 << 19)
+#define CGC_TDM			(1 << 20)
+#define CGC_RESERVED		((1 << 18) | (0x6 << 21))
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/include/mach/io.h linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/include/mach/io.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/include/mach/io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/include/mach/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,31 @@
 					+ KIRKWOOD_PCIE_IO_VIRT_BASE);
 }
 
+static inline void __iomem *
+__arch_ioremap(unsigned long paddr, size_t size, unsigned int mtype)
+{
+	void __iomem *retval;
+	unsigned long offs = paddr - KIRKWOOD_REGS_PHYS_BASE;
+	if (mtype == MT_DEVICE && size && offs < KIRKWOOD_REGS_SIZE &&
+	    size <= KIRKWOOD_REGS_SIZE && offs + size <= KIRKWOOD_REGS_SIZE) {
+		retval = (void __iomem *)KIRKWOOD_REGS_VIRT_BASE + offs;
+	} else {
+		retval = __arm_ioremap(paddr, size, mtype);
+	}
+
+	return retval;
+}
+
+static inline void
+__arch_iounmap(void __iomem *addr)
+{
+	if (addr < (void __iomem *)KIRKWOOD_REGS_VIRT_BASE ||
+	    addr >= (void __iomem *)(KIRKWOOD_REGS_VIRT_BASE + KIRKWOOD_REGS_SIZE))
+		__iounmap(addr);
+}
+
+#define __arch_ioremap(p, s, m)	__arch_ioremap(p, s, m)
+#define __arch_iounmap(a)	__arch_iounmap(a)
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,16 +20,18 @@
  * f1000000	on-chip peripheral registers
  * f2000000	PCIe I/O space
  * f3000000	NAND controller address window
+ * f4000000	Security Accelerator SRAM
  *
  * virt		phys		size
  * fee00000	f1000000	1M	on-chip peripheral registers
  * fef00000	f2000000	1M	PCIe I/O space
  */
 
+#define KIRKWOOD_SRAM_PHYS_BASE		0xf4000000
+#define KIRKWOOD_SRAM_SIZE		SZ_2K
+
 #define KIRKWOOD_NAND_MEM_PHYS_BASE	0xf3000000
-#define KIRKWOOD_NAND_MEM_SIZE		SZ_64K /* 1K is sufficient, but 64K
-						* is the minimal window size
-						*/
+#define KIRKWOOD_NAND_MEM_SIZE		SZ_1K
 
 #define KIRKWOOD_PCIE_IO_PHYS_BASE	0xf2000000
 #define KIRKWOOD_PCIE_IO_VIRT_BASE	0xfef00000
@@ -48,6 +50,7 @@
  */
 #define DDR_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x00000)
 #define  DDR_WINDOW_CPU_BASE	(DDR_VIRT_BASE | 0x1500)
+#define DDR_OPERATION_BASE	(DDR_VIRT_BASE | 0x1418)
 
 #define DEV_BUS_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE | 0x10000)
 #define DEV_BUS_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x10000)
@@ -63,7 +66,11 @@
 
 #define BRIDGE_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x20000)
 
+#define CRYPTO_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE | 0x30000)
+
 #define PCIE_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x40000)
+#define PCIE_LINK_CTRL		(PCIE_VIRT_BASE | 0x70)
+#define PCIE_STATUS		(PCIE_VIRT_BASE | 0x1a04)
 
 #define USB_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x50000)
 
@@ -80,6 +87,11 @@
 #define GE01_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x74000)
 
 #define SATA_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x80000)
+#define SATA_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x80000)
+#define SATA0_IF_CTRL		(SATA_VIRT_BASE | 0x2050)
+#define SATA0_PHY_MODE_2	(SATA_VIRT_BASE | 0x2330)
+#define SATA1_IF_CTRL		(SATA_VIRT_BASE | 0x4050)
+#define SATA1_PHY_MODE_2	(SATA_VIRT_BASE | 0x4330)
 
 #define SDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x90000)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,12 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell RD-88F6281 Reference Board.
 
+config MACH_MV88F6281GTW_GE
+	bool "Marvell 88F6281 GTW GE Board"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Marvell 88F6281 GTW GE Board.
+
 config MACH_SHEEVAPLUG
 	bool "Marvell SheevaPlug Reference Board"
 	help
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,5 +3,8 @@
 obj-$(CONFIG_MACH_DB88F6281_BP)		+= db88f6281-bp-setup.o
 obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
 obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
+obj-$(CONFIG_MACH_MV88F6281GTW_GE)	+= mv88f6281gtw_ge-setup.o
 obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
 obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o
+
+obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/mpp.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/mpp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/mpp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/mpp.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,9 @@
 	if (!variant_mask)
 		return;
 
+	/* Initialize gpiolib. */
+	orion_gpio_init();
+
 	printk(KERN_DEBUG "initial MPP regs:");
 	for (i = 0; i < MPP_NR_REGS; i++) {
 		mpp_ctrl[i] = readl(MPP_CTRL(i));
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/mpp.h linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/mpp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/mpp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/mpp.h	2009-09-09 18:13:59.000000000 -0400
@@ -289,7 +289,7 @@
 
 #define MPP48_GPIO		MPP( 48, 0x0, 1, 1, 0,   0,   0,   1    )
 #define MPP48_TSMP12		MPP( 48, 0x1, 1, 1, 0,   0,   0,   1    )
-#define MPP48_TDM_DTX		MPP( 48. 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP48_TDM_DTX		MPP( 48, 0x2, 0, 1, 0,   0,   0,   1    )
 
 #define MPP49_GPIO		MPP( 49, 0x0, 1, 1, 0,   0,   0,   1    )
 #define MPP49_TSMP9		MPP( 49, 0x1, 1, 1, 0,   0,   0,   1    )
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,173 @@
+/*
+ * arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+ *
+ * Marvell 88F6281 GTW GE Board Setup
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/mtd/physmap.h>
+#include <linux/timer.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/ethtool.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/orion_spi.h>
+#include <net/dsa.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/pci.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data mv88f6281gtw_ge_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_NONE,
+	.speed		= SPEED_1000,
+	.duplex		= DUPLEX_FULL,
+};
+
+static struct dsa_chip_data mv88f6281gtw_ge_switch_chip_data = {
+	.port_names[0]	= "lan1",
+	.port_names[1]	= "lan2",
+	.port_names[2]	= "lan3",
+	.port_names[3]	= "lan4",
+	.port_names[4]	= "wan",
+	.port_names[5]	= "cpu",
+};
+
+static struct dsa_platform_data mv88f6281gtw_ge_switch_plat_data = {
+	.nr_chips	= 1,
+	.chip		= &mv88f6281gtw_ge_switch_chip_data,
+};
+
+static const struct flash_platform_data mv88f6281gtw_ge_spi_slave_data = {
+	.type		= "mx25l12805d",
+};
+
+static struct spi_board_info __initdata mv88f6281gtw_ge_spi_slave_info[] = {
+	{
+		.modalias	= "m25p80",
+		.platform_data	= &mv88f6281gtw_ge_spi_slave_data,
+		.irq		= -1,
+		.max_speed_hz	= 50000000,
+		.bus_num	= 0,
+		.chip_select	= 0,
+	},
+};
+
+static struct gpio_keys_button mv88f6281gtw_ge_button_pins[] = {
+	{
+		.code		= KEY_RESTART,
+		.gpio		= 47,
+		.desc		= "SWR Button",
+		.active_low	= 1,
+	}, {
+		.code		= KEY_F1,
+		.gpio		= 46,
+		.desc		= "WPS Button(F1)",
+		.active_low	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data mv88f6281gtw_ge_button_data = {
+	.buttons	= mv88f6281gtw_ge_button_pins,
+	.nbuttons	= ARRAY_SIZE(mv88f6281gtw_ge_button_pins),
+};
+
+static struct platform_device mv88f6281gtw_ge_buttons = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &mv88f6281gtw_ge_button_data,
+	},
+};
+
+static struct gpio_led mv88f6281gtw_ge_led_pins[] = {
+	{
+		.name		= "gtw:green:Status",
+		.gpio		= 20,
+		.active_low	= 0,
+	}, {
+		.name		= "gtw:red:Status",
+		.gpio		= 21,
+		.active_low	= 0,
+	}, {
+		.name		= "gtw:green:USB",
+		.gpio		= 12,
+		.active_low	= 0,
+	},
+};
+
+static struct gpio_led_platform_data mv88f6281gtw_ge_led_data = {
+	.leds		= mv88f6281gtw_ge_led_pins,
+	.num_leds	= ARRAY_SIZE(mv88f6281gtw_ge_led_pins),
+};
+
+static struct platform_device mv88f6281gtw_ge_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &mv88f6281gtw_ge_led_data,
+	},
+};
+
+static unsigned int mv88f6281gtw_ge_mpp_config[] __initdata = {
+	MPP12_GPO,	/* Status#_USB pin  */
+	MPP20_GPIO,	/* Status#_GLED pin */
+	MPP21_GPIO,	/* Status#_RLED pin */
+	MPP46_GPIO,	/* WPS_Switch pin   */
+	MPP47_GPIO,	/* SW_Init pin      */
+	0
+};
+
+static void __init mv88f6281gtw_ge_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+	kirkwood_mpp_conf(mv88f6281gtw_ge_mpp_config);
+
+	kirkwood_ehci_init();
+	kirkwood_ge00_init(&mv88f6281gtw_ge_ge00_data);
+	kirkwood_ge00_switch_init(&mv88f6281gtw_ge_switch_plat_data, NO_IRQ);
+	spi_register_board_info(mv88f6281gtw_ge_spi_slave_info,
+				ARRAY_SIZE(mv88f6281gtw_ge_spi_slave_info));
+	kirkwood_spi_init();
+	kirkwood_uart0_init();
+	platform_device_register(&mv88f6281gtw_ge_leds);
+	platform_device_register(&mv88f6281gtw_ge_buttons);
+}
+
+static int __init mv88f6281gtw_ge_pci_init(void)
+{
+	if (machine_is_mv88f6281gtw_ge())
+		kirkwood_pcie_init();
+
+	return 0;
+}
+subsys_initcall(mv88f6281gtw_ge_pci_init);
+
+MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= mv88f6281gtw_ge_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &kirkwood_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/pcie.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/pcie.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/pcie.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/pcie.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
+#include <mach/bridge-regs.h>
 #include "common.h"
 
 
@@ -95,6 +96,7 @@
 static int kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct resource *res;
+	extern unsigned int kirkwood_clk_ctrl;
 
 	/*
 	 * Generic PCIe unit setup.
@@ -133,6 +135,8 @@
 	sys->resource[2] = NULL;
 	sys->io_offset = 0;
 
+	kirkwood_clk_ctrl |= CGC_PEX0;
+
 	return 1;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,8 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/spi/flash.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
-#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
@@ -22,7 +21,6 @@
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
 #include <plat/mvsdio.h>
-#include <plat/orion_nand.h>
 #include "common.h"
 #include "mpp.h"
 
@@ -42,32 +40,6 @@
 	},
 };
 
-static struct resource rd88f6281_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
-	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
-			  KIRKWOOD_NAND_MEM_SIZE - 1,
-};
-
-static struct orion_nand_data rd88f6281_nand_data = {
-	.parts		= rd88f6281_nand_parts,
-	.nr_parts	= ARRAY_SIZE(rd88f6281_nand_parts),
-	.cle		= 0,
-	.ale		= 1,
-	.width		= 8,
-	.chip_delay	= 25,
-};
-
-static struct platform_device rd88f6281_nand_flash = {
-	.name		= "orion_nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &rd88f6281_nand_data,
-	},
-	.resource	= &rd88f6281_nand_resource,
-	.num_resources	= 1,
-};
-
 static struct mv643xx_eth_platform_data rd88f6281_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_NONE,
 	.speed		= SPEED_1000,
@@ -114,6 +86,7 @@
 	kirkwood_init();
 	kirkwood_mpp_conf(rd88f6281_mpp_config);
 
+	kirkwood_nand_init(ARRAY_AND_SIZE(rd88f6281_nand_parts), 25);
 	kirkwood_ehci_init();
 
 	kirkwood_ge00_init(&rd88f6281_ge00_data);
@@ -129,8 +102,6 @@
 	kirkwood_sata_init(&rd88f6281_sata_data);
 	kirkwood_sdio_init(&rd88f6281_mvsdio_data);
 	kirkwood_uart0_init();
-
-	platform_device_register(&rd88f6281_nand_flash);
 }
 
 static int __init rd88f6281_pci_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/gpio.h>
@@ -20,7 +19,6 @@
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
 #include <plat/mvsdio.h>
-#include <plat/orion_nand.h>
 #include "common.h"
 #include "mpp.h"
 
@@ -40,38 +38,12 @@
 	},
 };
 
-static struct resource sheevaplug_nand_resource = {
-	.flags		= IORESOURCE_MEM,
-	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
-	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
-			  KIRKWOOD_NAND_MEM_SIZE - 1,
-};
-
-static struct orion_nand_data sheevaplug_nand_data = {
-	.parts		= sheevaplug_nand_parts,
-	.nr_parts	= ARRAY_SIZE(sheevaplug_nand_parts),
-	.cle		= 0,
-	.ale		= 1,
-	.width		= 8,
-	.chip_delay	= 25,
-};
-
-static struct platform_device sheevaplug_nand_flash = {
-	.name		= "orion_nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &sheevaplug_nand_data,
-	},
-	.resource	= &sheevaplug_nand_resource,
-	.num_resources	= 1,
-};
-
 static struct mv643xx_eth_platform_data sheevaplug_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
 };
 
 static struct mvsdio_platform_data sheevaplug_mvsdio_data = {
-	// unfortunately the CD signal has not been connected */
+	/* unfortunately the CD signal has not been connected */
 };
 
 static struct gpio_led sheevaplug_led_pins[] = {
@@ -111,6 +83,7 @@
 	kirkwood_mpp_conf(sheevaplug_mpp_config);
 
 	kirkwood_uart0_init();
+	kirkwood_nand_init(ARRAY_AND_SIZE(sheevaplug_nand_parts), 25);
 
 	if (gpio_request(29, "USB Power Enable") != 0 ||
 	    gpio_direction_output(29, 1) != 0)
@@ -120,7 +93,6 @@
 	kirkwood_ge00_init(&sheevaplug_ge00_data);
 	kirkwood_sdio_init(&sheevaplug_mvsdio_data);
 
-	platform_device_register(&sheevaplug_nand_flash);
 	platform_device_register(&sheevaplug_leds);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/ts219-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/ts219-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-kirkwood/ts219-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-kirkwood/ts219-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -206,6 +206,15 @@
 
 }
 
+static int __init ts219_pci_init(void)
+{
+   if (machine_is_ts219())
+           kirkwood_pcie_init();
+
+   return 0;
+}
+subsys_initcall(ts219_pci_init);
+
 MACHINE_START(TS219, "QNAP TS-119/TS-219")
 	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
 	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ks8695/include/mach/hardware.h linux-libre-2.6.31-gnu/arch/arm/mach-ks8695/include/mach/hardware.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ks8695/include/mach/hardware.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ks8695/include/mach/hardware.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,11 @@
 #include <asm/sizes.h>
 
 /*
+ * Clocks are derived from MCLK, which is 25Mhz
+ */
+#define KS8695_CLOCK_RATE	25000000
+
+/*
  * Physical RAM address.
  */
 #define KS8695_SDRAM_PA		0x00000000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ks8695/include/mach/timex.h linux-libre-2.6.31-gnu/arch/arm/mach-ks8695/include/mach/timex.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-ks8695/include/mach/timex.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ks8695/include/mach/timex.h	2009-09-09 18:13:59.000000000 -0400
@@ -14,7 +14,8 @@
 #ifndef __ASM_ARCH_TIMEX_H
 #define __ASM_ARCH_TIMEX_H
 
-/* timers are derived from MCLK, which is 25MHz */
-#define CLOCK_TICK_RATE 25000000
+#include <mach/hardware.h>
+
+#define CLOCK_TICK_RATE 	KS8695_CLOCK_RATE
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-ks8695/pci.c linux-libre-2.6.31-gnu/arch/arm/mach-ks8695/pci.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-ks8695/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-ks8695/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -245,6 +245,9 @@
 
 static void __init ks8695_pci_preinit(void)
 {
+	/* make software reset to avoid freeze if PCI bus was messed up */
+	__raw_writel(0x80000000, KS8695_PCI_VA + KS8695_PBCS);
+
 	/* stage 1 initialization, subid, subdevice = 0x0001 */
 	__raw_writel(0x00010001, KS8695_PCI_VA + KS8695_CRCSID);
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -52,6 +52,7 @@
 /*
  * Interrupt numbers for PXA910
  */
+#define IRQ_PXA910_NONE			(-1)
 #define IRQ_PXA910_AIRQ			0
 #define IRQ_PXA910_SSP3			1
 #define IRQ_PXA910_SSP2			2
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h	2009-09-09 18:13:59.000000000 -0400
@@ -253,6 +253,10 @@
 #define GPIO58_LCD_PCLK_WR	MFP_CFG(GPIO58, AF1)
 #define GPIO85_LCD_VSYNC	MFP_CFG(GPIO85, AF1)
 
+/* I2C */
+#define GPIO105_CI2C_SDA	MFP_CFG(GPIO105, AF1)
+#define GPIO106_CI2C_SCL	MFP_CFG(GPIO106, AF1)
+
 /* I2S */
 #define GPIO113_I2S_MCLK	MFP_CFG(GPIO113,AF6)
 #define GPIO114_I2S_FRM		MFP_CFG(GPIO114,AF1)
@@ -260,4 +264,27 @@
 #define GPIO116_I2S_RXD		MFP_CFG(GPIO116,AF2)
 #define GPIO117_I2S_TXD		MFP_CFG(GPIO117,AF2)
 
+/* PWM */
+#define GPIO96_PWM3_OUT		MFP_CFG(GPIO96, AF1)
+#define GPIO97_PWM2_OUT		MFP_CFG(GPIO97, AF1)
+#define GPIO98_PWM1_OUT		MFP_CFG(GPIO98, AF1)
+#define GPIO104_PWM4_OUT	MFP_CFG(GPIO104, AF1)
+#define GPIO106_PWM2_OUT	MFP_CFG(GPIO106, AF2)
+#define GPIO74_PWM4_OUT		MFP_CFG(GPIO74, AF2)
+#define GPIO75_PWM3_OUT		MFP_CFG(GPIO75, AF2)
+#define GPIO76_PWM2_OUT		MFP_CFG(GPIO76, AF2)
+#define GPIO77_PWM1_OUT		MFP_CFG(GPIO77, AF2)
+#define GPIO82_PWM4_OUT		MFP_CFG(GPIO82, AF2)
+#define GPIO83_PWM3_OUT		MFP_CFG(GPIO83, AF2)
+#define GPIO84_PWM2_OUT		MFP_CFG(GPIO84, AF2)
+#define GPIO85_PWM1_OUT		MFP_CFG(GPIO85, AF2)
+#define GPIO84_PWM1_OUT		MFP_CFG(GPIO84, AF4)
+#define GPIO122_PWM3_OUT	MFP_CFG(GPIO122, AF3)
+#define GPIO123_PWM1_OUT	MFP_CFG(GPIO123, AF1)
+#define GPIO124_PWM2_OUT	MFP_CFG(GPIO124, AF1)
+#define GPIO125_PWM3_OUT	MFP_CFG(GPIO125, AF1)
+#define GPIO126_PWM4_OUT	MFP_CFG(GPIO126, AF1)
+#define GPIO86_PWM1_OUT		MFP_CFG(GPIO86, AF2)
+#define GPIO86_PWM2_OUT		MFP_CFG(GPIO86, AF3)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa910.h	2009-09-09 18:13:59.000000000 -0400
@@ -159,4 +159,12 @@
 #define MMC1_CD_MMC1_CD		MFP_CFG_DRV(MMC1_CD, AF0, MEDIUM)
 #define MMC1_WP_MMC1_WP		MFP_CFG_DRV(MMC1_WP, AF0, MEDIUM)
 
+/* PWM */
+#define GPIO27 PWM3 AF2		MFP_CFG(GPIO27, AF2)
+#define GPIO51_PWM2_OUT		MFP_CFG(GPIO51, AF2)
+#define GPIO117_PWM1_OUT	MFP_CFG(GPIO117, AF2)
+#define GPIO118_PWM2_OUT	MFP_CFG(GPIO118, AF2)
+#define GPIO119_PWM3_OUT	MFP_CFG(GPIO119, AF2)
+#define GPIO120_PWM4_OUT	MFP_CFG(GPIO120, AF2)
+
 #endif /* __ASM_MACH MFP_PXA910_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/pxa168.h linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/pxa168.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/pxa168.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/pxa168.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,18 @@
 #ifndef __ASM_MACH_PXA168_H
 #define __ASM_MACH_PXA168_H
 
+#include <linux/i2c.h>
 #include <mach/devices.h>
+#include <plat/i2c.h>
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
+extern struct pxa_device_desc pxa168_device_twsi0;
+extern struct pxa_device_desc pxa168_device_twsi1;
+extern struct pxa_device_desc pxa168_device_pwm1;
+extern struct pxa_device_desc pxa168_device_pwm2;
+extern struct pxa_device_desc pxa168_device_pwm3;
+extern struct pxa_device_desc pxa168_device_pwm4;
 
 static inline int pxa168_add_uart(int id)
 {
@@ -20,4 +28,40 @@
 
 	return pxa_register_device(d, NULL, 0);
 }
+
+static inline int pxa168_add_twsi(int id, struct i2c_pxa_platform_data *data,
+				  struct i2c_board_info *info, unsigned size)
+{
+	struct pxa_device_desc *d = NULL;
+	int ret;
+
+	switch (id) {
+	case 0: d = &pxa168_device_twsi0; break;
+	case 1: d = &pxa168_device_twsi1; break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = i2c_register_board_info(id, info, size);
+	if (ret)
+		return ret;
+
+	return pxa_register_device(d, data, sizeof(*data));
+}
+
+static inline int pxa168_add_pwm(int id)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 1: d = &pxa168_device_pwm1; break;
+	case 2: d = &pxa168_device_pwm2; break;
+	case 3: d = &pxa168_device_pwm3; break;
+	case 4: d = &pxa168_device_pwm4; break;
+	default:
+		return -EINVAL;
+	}
+
+	return pxa_register_device(d, NULL, 0);
+}
 #endif /* __ASM_MACH_PXA168_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/pxa910.h linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/pxa910.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/pxa910.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/pxa910.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,18 @@
 #ifndef __ASM_MACH_PXA910_H
 #define __ASM_MACH_PXA910_H
 
+#include <linux/i2c.h>
 #include <mach/devices.h>
+#include <plat/i2c.h>
 
 extern struct pxa_device_desc pxa910_device_uart1;
 extern struct pxa_device_desc pxa910_device_uart2;
+extern struct pxa_device_desc pxa910_device_twsi0;
+extern struct pxa_device_desc pxa910_device_twsi1;
+extern struct pxa_device_desc pxa910_device_pwm1;
+extern struct pxa_device_desc pxa910_device_pwm2;
+extern struct pxa_device_desc pxa910_device_pwm3;
+extern struct pxa_device_desc pxa910_device_pwm4;
 
 static inline int pxa910_add_uart(int id)
 {
@@ -20,4 +28,40 @@
 
 	return pxa_register_device(d, NULL, 0);
 }
+
+static inline int pxa910_add_twsi(int id, struct i2c_pxa_platform_data *data,
+				  struct i2c_board_info *info, unsigned size)
+{
+	struct pxa_device_desc *d = NULL;
+	int ret;
+
+	switch (id) {
+	case 0: d = &pxa910_device_twsi0; break;
+	case 1: d = &pxa910_device_twsi1; break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = i2c_register_board_info(id, info, size);
+	if (ret)
+		return ret;
+
+	return pxa_register_device(d, data, sizeof(*data));
+}
+
+static inline int pxa910_add_pwm(int id)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 1: d = &pxa910_device_pwm1; break;
+	case 2: d = &pxa910_device_pwm2; break;
+	case 3: d = &pxa910_device_pwm3; break;
+	case 4: d = &pxa910_device_pwm4; break;
+	default:
+		return -EINVAL;
+	}
+
+	return pxa_register_device(d, NULL, 0);
+}
 #endif /* __ASM_MACH_PXA910_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/regs-apbc.h linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/regs-apbc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/include/mach/regs-apbc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/include/mach/regs-apbc.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,8 +22,10 @@
 #define APBC_PXA168_UART1	APBC_REG(0x000)
 #define APBC_PXA168_UART2	APBC_REG(0x004)
 #define APBC_PXA168_GPIO	APBC_REG(0x008)
-#define APBC_PXA168_PWM0	APBC_REG(0x00c)
-#define APBC_PXA168_PWM1	APBC_REG(0x010)
+#define APBC_PXA168_PWM1	APBC_REG(0x00c)
+#define APBC_PXA168_PWM2	APBC_REG(0x010)
+#define APBC_PXA168_PWM3	APBC_REG(0x014)
+#define APBC_PXA168_PWM4	APBC_REG(0x018)
 #define APBC_PXA168_SSP1	APBC_REG(0x01c)
 #define APBC_PXA168_SSP2	APBC_REG(0x020)
 #define APBC_PXA168_RTC		APBC_REG(0x028)
@@ -48,10 +50,10 @@
 #define APBC_PXA910_UART0	APBC_REG(0x000)
 #define APBC_PXA910_UART1	APBC_REG(0x004)
 #define APBC_PXA910_GPIO	APBC_REG(0x008)
-#define APBC_PXA910_PWM0	APBC_REG(0x00c)
-#define APBC_PXA910_PWM1	APBC_REG(0x010)
-#define APBC_PXA910_PWM2	APBC_REG(0x014)
-#define APBC_PXA910_PWM3	APBC_REG(0x018)
+#define APBC_PXA910_PWM1	APBC_REG(0x00c)
+#define APBC_PXA910_PWM2	APBC_REG(0x010)
+#define APBC_PXA910_PWM3	APBC_REG(0x014)
+#define APBC_PXA910_PWM4	APBC_REG(0x018)
 #define APBC_PXA910_SSP1	APBC_REG(0x01c)
 #define APBC_PXA910_SSP2	APBC_REG(0x020)
 #define APBC_PXA910_IPC		APBC_REG(0x024)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/pxa168.c linux-libre-2.6.31-gnu/arch/arm/mach-mmp/pxa168.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/pxa168.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/pxa168.c	2009-09-09 18:13:59.000000000 -0400
@@ -65,11 +65,23 @@
 /* APB peripheral clocks */
 static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
 static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
+static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PXA168_PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PXA168_PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PXA168_PWM4, 1, 13000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
 	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
 	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
+	INIT_CLKREG(&clk_pwm2, "pxa168-pwm.1", NULL),
+	INIT_CLKREG(&clk_pwm3, "pxa168-pwm.2", NULL),
+	INIT_CLKREG(&clk_pwm4, "pxa168-pwm.3", NULL),
 };
 
 static int __init pxa168_init(void)
@@ -109,3 +121,9 @@
 /* on-chip devices */
 PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
 PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
+PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
+PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
+PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
+PXA168_DEVICE(pwm2, "pxa168-pwm", 1, NONE, 0xd401a400, 0x10);
+PXA168_DEVICE(pwm3, "pxa168-pwm", 2, NONE, 0xd401a800, 0x10);
+PXA168_DEVICE(pwm4, "pxa168-pwm", 3, NONE, 0xd401ac00, 0x10);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mmp/pxa910.c linux-libre-2.6.31-gnu/arch/arm/mach-mmp/pxa910.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mmp/pxa910.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mmp/pxa910.c	2009-09-09 18:13:59.000000000 -0400
@@ -103,11 +103,23 @@
 /* APB peripheral clocks */
 static APBC_CLK(uart1, PXA910_UART0, 1, 14745600);
 static APBC_CLK(uart2, PXA910_UART1, 1, 14745600);
+static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PXA910_PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa910_clkregs[] = {
 	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
 	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_pwm1, "pxa910-pwm.0", NULL),
+	INIT_CLKREG(&clk_pwm2, "pxa910-pwm.1", NULL),
+	INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL),
+	INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
 };
 
 static int __init pxa910_init(void)
@@ -156,3 +168,9 @@
  */
 PXA910_DEVICE(uart1, "pxa2xx-uart", 0, UART2, 0xd4017000, 0x30, 21, 22);
 PXA910_DEVICE(uart2, "pxa2xx-uart", 1, UART3, 0xd4018000, 0x30, 23, 24);
+PXA910_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
+PXA910_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
+PXA910_DEVICE(pwm1, "pxa910-pwm", 0, NONE, 0xd401a000, 0x10);
+PXA910_DEVICE(pwm2, "pxa910-pwm", 1, NONE, 0xd401a400, 0x10);
+PXA910_DEVICE(pwm3, "pxa910-pwm", 2, NONE, 0xd401a800, 0x10);
+PXA910_DEVICE(pwm4, "pxa910-pwm", 3, NONE, 0xd401ac00, 0x10);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mv78xx0/irq.c linux-libre-2.6.31-gnu/arch/arm/mach-mv78xx0/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mv78xx0/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mv78xx0/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,9 @@
 {
 	int i;
 
+	/* Initialize gpiolib. */
+	orion_gpio_init();
+
 	orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
 	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
 	orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF));
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx1/generic.c linux-libre-2.6.31-gnu/arch/arm/mach-mx1/generic.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx1/generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx1/generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 
 #include <asm/mach/map.h>
 
+#include <mach/common.h>
 #include <mach/hardware.h>
 
 static struct map_desc imx_io_desc[] __initdata = {
@@ -37,7 +38,9 @@
 	}
 };
 
-void __init mxc_map_io(void)
+void __init mx1_map_io(void)
 {
+	mxc_set_cpu_type(MXC_CPU_MX1);
+
 	iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx1/mx1ads.c linux-libre-2.6.31-gnu/arch/arm/mach-mx1/mx1ads.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx1/mx1ads.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx1/mx1ads.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,77 +12,56 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pcf857x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include <mach/irqs.h>
-#include <mach/hardware.h>
 #include <mach/common.h>
-#include <mach/imx-uart.h>
-#include <mach/irqs.h>
+#include <mach/hardware.h>
 #include <mach/i2c.h>
+#include <mach/imx-uart.h>
 #include <mach/iomux.h>
+#include <mach/irqs.h>
+
 #include "devices.h"
 
-/*
- * UARTs platform data
- */
-static int mxc_uart1_pins[] = {
+static int mx1ads_pins[] = {
+	/* UART1 */
 	PC9_PF_UART1_CTS,
 	PC10_PF_UART1_RTS,
 	PC11_PF_UART1_TXD,
 	PC12_PF_UART1_RXD,
-};
-
-static int uart1_mxc_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins), "UART1");
-}
-
-static int uart1_mxc_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins));
-	return 0;
-}
-
-static int mxc_uart2_pins[] = {
+	/* UART2 */
 	PB28_PF_UART2_CTS,
 	PB29_PF_UART2_RTS,
 	PB30_PF_UART2_TXD,
 	PB31_PF_UART2_RXD,
+	/* I2C */
+	PA15_PF_I2C_SDA,
+	PA16_PF_I2C_SCL,
+	/* SPI */
+	PC13_PF_SPI1_SPI_RDY,
+	PC14_PF_SPI1_SCLK,
+	PC15_PF_SPI1_SS,
+	PC16_PF_SPI1_MISO,
+	PC17_PF_SPI1_MOSI,
 };
 
-static int uart2_mxc_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
-			ARRAY_SIZE(mxc_uart2_pins), "UART2");
-}
-
-static int uart2_mxc_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart2_pins,
-			ARRAY_SIZE(mxc_uart2_pins));
-	return 0;
-}
+/*
+ * UARTs platform data
+ */
 
 static struct imxuart_platform_data uart_pdata[] = {
 	{
-		.init = uart1_mxc_init,
-		.exit = uart1_mxc_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart2_mxc_init,
-		.exit = uart2_mxc_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	},
 };
@@ -111,24 +90,6 @@
 /*
  * I2C
  */
-
-static int i2c_pins[] = {
-	PA15_PF_I2C_SDA,
-	PA16_PF_I2C_SCL,
-};
-
-static int i2c_init(struct device *dev)
-{
-	return mxc_gpio_setup_multiple_pins(i2c_pins,
-			ARRAY_SIZE(i2c_pins), "I2C");
-}
-
-static void i2c_exit(struct device *dev)
-{
-	mxc_gpio_release_multiple_pins(i2c_pins,
-			ARRAY_SIZE(i2c_pins));
-}
-
 static struct pcf857x_platform_data pcf857x_data[] = {
 	{
 		.gpio_base = 4 * 32,
@@ -139,8 +100,6 @@
 
 static struct imxi2c_platform_data mx1ads_i2c_data = {
 	.bitrate = 100000,
-	.init = i2c_init,
-	.exit = i2c_exit,
 };
 
 static struct i2c_board_info mx1ads_i2c_devices[] = {
@@ -160,6 +119,9 @@
  */
 static void __init mx1ads_init(void)
 {
+	mxc_gpio_setup_multiple_pins(mx1ads_pins,
+		ARRAY_SIZE(mx1ads_pins), "mx1ads");
+
 	/* UART */
 	mxc_register_device(&imx_uart1_device, &uart_pdata[0]);
 	mxc_register_device(&imx_uart2_device, &uart_pdata[1]);
@@ -188,7 +150,7 @@
 	.phys_io	= IMX_IO_PHYS,
 	.io_pg_offst	= (IMX_IO_BASE >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x100,
-	.map_io		= mxc_map_io,
+	.map_io		= mx1_map_io,
 	.init_irq	= mxc_init_irq,
 	.timer		= &mx1ads_timer,
 	.init_machine	= mx1ads_init,
@@ -198,7 +160,7 @@
 	.phys_io	= IMX_IO_PHYS,
 	.io_pg_offst	= (IMX_IO_BASE >> 18) & 0xfffc,
 	.boot_params	= PHYS_OFFSET + 0x100,
-	.map_io		= mxc_map_io,
+	.map_io		= mx1_map_io,
 	.init_irq	= mxc_init_irq,
 	.timer		= &mx1ads_timer,
 	.init_machine	= mx1ads_init,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx1/scb9328.c linux-libre-2.6.31-gnu/arch/arm/mach-mx1/scb9328.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx1/scb9328.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx1/scb9328.c	2009-09-09 18:13:59.000000000 -0400
@@ -153,7 +153,7 @@
 	.phys_io	= 0x00200000,
 	.io_pg_offst	= ((0xe0200000) >> 18) & 0xfffc,
 	.boot_params	= 0x08000100,
-	.map_io		= mxc_map_io,
+	.map_io		= mx1_map_io,
 	.init_irq	= mxc_init_irq,
 	.timer		= &scb9328_timer,
 	.init_machine	= scb9328_init,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/clock_imx21.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/clock_imx21.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/clock_imx21.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/clock_imx21.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,25 @@
 	__raw_writel(reg, clk->enable_reg);
 }
 
+static unsigned long _clk_generic_round_rate(struct clk *clk,
+			unsigned long rate,
+			u32 max_divisor)
+{
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+	if (parent_rate % rate)
+		div++;
+
+	if (div > max_divisor)
+		div = max_divisor;
+
+	return parent_rate / div;
+}
+
 static int _clk_spll_enable(struct clk *clk)
 {
 	u32 reg;
@@ -78,19 +97,7 @@
 static unsigned long _clk_perclkx_round_rate(struct clk *clk,
 					     unsigned long rate)
 {
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-	if (parent_rate % rate)
-		div++;
-
-	if (div > 64)
-		div = 64;
-
-	return parent_rate / div;
+	return _clk_generic_round_rate(clk, rate, 64);
 }
 
 static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
@@ -130,6 +137,32 @@
 	return parent_rate / (usb_pdf + 1U);
 }
 
+static unsigned long _clk_usb_round_rate(struct clk *clk,
+					     unsigned long rate)
+{
+	return _clk_generic_round_rate(clk, rate, 8);
+}
+
+static int _clk_usb_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
+		return -EINVAL;
+	div--;
+
+	reg = CSCR() & ~CCM_CSCR_USB_MASK;
+	reg |= div << CCM_CSCR_USB_OFFSET;
+	__raw_writel(reg, CCM_CSCR);
+
+	return 0;
+}
+
 static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf)
 {
 	unsigned long parent_rate;
@@ -595,11 +628,14 @@
 static struct clk usb_clk[] = {
 	{
 		.parent = &spll_clk,
+		.secondary = &usb_clk[1],
 		.get_rate = _clk_usb_recalc,
 		.enable = _clk_enable,
 		.enable_reg = CCM_PCCR_USBOTG_REG,
 		.enable_shift = CCM_PCCR_USBOTG_OFFSET,
 		.disable = _clk_disable,
+		.round_rate = _clk_usb_round_rate,
+		.set_rate = _clk_usb_set_rate,
 	}, {
 		.parent = &hclk_clk,
 		.enable = _clk_enable,
@@ -768,18 +804,7 @@
 
 static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
 {
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	div = parent_rate / rate;
-	if (parent_rate % rate)
-		div++;
-
-	if (div > 8)
-		div = 8;
-
-	return parent_rate / div;
+	return _clk_generic_round_rate(clk, rate, 8);
 }
 
 static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
@@ -921,7 +946,7 @@
 	_REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
 	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
 	_REGISTER_CLOCK(NULL, "csi", csi_clk[0])
-	_REGISTER_CLOCK(NULL, "usb", usb_clk[0])
+	_REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0])
 	_REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0])
 	_REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1])
 	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/generic.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/generic.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -69,7 +69,17 @@
  * system startup to create static physical to virtual
  * memory map for the IO modules.
  */
-void __init mxc_map_io(void)
+void __init mx21_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX21);
+
+	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+}
+
+void __init mx27_map_io(void)
 {
+	mxc_set_cpu_type(MXC_CPU_MX27);
+
 	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
 }
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-mx2/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,13 @@
 
 comment "MX2 platforms:"
 
+config MACH_MX21ADS
+	bool "MX21ADS platform"
+	depends on MACH_MX21
+	help
+	  Include support for MX21ADS platform. This includes specific
+	  configurations for the board and its peripherals.
+
 config MACH_MX27ADS
 	bool "MX27ADS platform"
 	depends on MACH_MX27
@@ -46,4 +53,18 @@
 
 endchoice
 
+config MACH_MX27_3DS
+	bool "MX27PDK platform"
+	depends on MACH_MX27
+	help
+	  Include support for MX27PDK platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX27LITE
+	bool "LogicPD MX27 LITEKIT platform"
+	depends on MACH_MX27
+	help
+	  Include support for MX27 LITEKIT platform. This includes specific
+	  configurations for the board and its peripherals.
+
 endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-mx2/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,10 @@
 obj-$(CONFIG_MACH_MX27) += cpu_imx27.o
 obj-$(CONFIG_MACH_MX27) += clock_imx27.o
 
+obj-$(CONFIG_MACH_MX21ADS) += mx21ads.o
 obj-$(CONFIG_MACH_MX27ADS) += mx27ads.o
 obj-$(CONFIG_MACH_PCM038) += pcm038.o
 obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
+obj-$(CONFIG_MACH_MX27_3DS) += mx27pdk.o
+obj-$(CONFIG_MACH_MX27LITE) += mx27lite.o
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx21ads.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx21ads.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx21ads.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx21ads.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,286 @@
+/*
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/physmap.h>
+#include <linux/gpio.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/imx-uart.h>
+#include <mach/imxfb.h>
+#include <mach/iomux.h>
+#include <mach/mxc_nand.h>
+#include <mach/mmc.h>
+#include <mach/board-mx21ads.h>
+
+#include "devices.h"
+
+static unsigned int mx21ads_pins[] = {
+
+	/* CS8900A */
+	(GPIO_PORTE | GPIO_GPIO | GPIO_IN | 11),
+
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+
+	/* UART3 (IrDA) - only TXD and RXD */
+	PE8_PF_UART3_TXD,
+	PE9_PF_UART3_RXD,
+
+	/* UART4 */
+	PB26_AF_UART4_RTS,
+	PB28_AF_UART4_TXD,
+	PB29_AF_UART4_CTS,
+	PB31_AF_UART4_RXD,
+
+	/* LCDC */
+	PA5_PF_LSCLK,
+	PA6_PF_LD0,
+	PA7_PF_LD1,
+	PA8_PF_LD2,
+	PA9_PF_LD3,
+	PA10_PF_LD4,
+	PA11_PF_LD5,
+	PA12_PF_LD6,
+	PA13_PF_LD7,
+	PA14_PF_LD8,
+	PA15_PF_LD9,
+	PA16_PF_LD10,
+	PA17_PF_LD11,
+	PA18_PF_LD12,
+	PA19_PF_LD13,
+	PA20_PF_LD14,
+	PA21_PF_LD15,
+	PA22_PF_LD16,
+	PA24_PF_REV,     /* Sharp panel dedicated signal */
+	PA25_PF_CLS,     /* Sharp panel dedicated signal */
+	PA26_PF_PS,      /* Sharp panel dedicated signal */
+	PA27_PF_SPL_SPR, /* Sharp panel dedicated signal */
+	PA28_PF_HSYNC,
+	PA29_PF_VSYNC,
+	PA30_PF_CONTRAST,
+	PA31_PF_OE_ACD,
+
+	/* MMC/SDHC */
+	PE18_PF_SD1_D0,
+	PE19_PF_SD1_D1,
+	PE20_PF_SD1_D2,
+	PE21_PF_SD1_D3,
+	PE22_PF_SD1_CMD,
+	PE23_PF_SD1_CLK,
+
+	/* NFC */
+	PF0_PF_NRFB,
+	PF1_PF_NFCE,
+	PF2_PF_NFWP,
+	PF3_PF_NFCLE,
+	PF4_PF_NFALE,
+	PF5_PF_NFRE,
+	PF6_PF_NFWE,
+	PF7_PF_NFIO0,
+	PF8_PF_NFIO1,
+	PF9_PF_NFIO2,
+	PF10_PF_NFIO3,
+	PF11_PF_NFIO4,
+	PF12_PF_NFIO5,
+	PF13_PF_NFIO6,
+	PF14_PF_NFIO7,
+};
+
+/* ADS's NOR flash: 2x AM29BDS128HE9VKI on 32-bit bus */
+static struct physmap_flash_data mx21ads_flash_data = {
+	.width = 4,
+};
+
+static struct resource mx21ads_flash_resource = {
+	.start = CS0_BASE_ADDR,
+	.end = CS0_BASE_ADDR + 0x02000000 - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device mx21ads_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &mx21ads_flash_data,
+	},
+	.num_resources = 1,
+	.resource = &mx21ads_flash_resource,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct imxuart_platform_data uart_norts_pdata = {
+};
+
+
+static int mx21ads_fb_init(struct platform_device *pdev)
+{
+	u16 tmp;
+
+	tmp = __raw_readw(MX21ADS_IO_REG);
+	tmp |= MX21ADS_IO_LCDON;
+	__raw_writew(tmp, MX21ADS_IO_REG);
+	return 0;
+}
+
+static void mx21ads_fb_exit(struct platform_device *pdev)
+{
+	u16 tmp;
+
+	tmp = __raw_readw(MX21ADS_IO_REG);
+	tmp &= ~MX21ADS_IO_LCDON;
+	__raw_writew(tmp, MX21ADS_IO_REG);
+}
+
+/*
+ * Connected is a portrait Sharp-QVGA display
+ * of type: LQ035Q7DB02
+ */
+static struct imx_fb_platform_data mx21ads_fb_data = {
+	.pixclock       = 188679, /* in ps */
+	.xres           = 240,
+	.yres           = 320,
+
+	.bpp            = 16,
+	.hsync_len      = 2,
+	.left_margin    = 6,
+	.right_margin   = 16,
+
+	.vsync_len      = 1,
+	.upper_margin   = 8,
+	.lower_margin   = 10,
+	.fixed_screen_cpu = 0,
+
+	.pcr            = 0xFB108BC7,
+	.pwmr           = 0x00A901ff,
+	.lscr1          = 0x00120300,
+	.dmacr          = 0x00020008,
+
+	.init = mx21ads_fb_init,
+	.exit = mx21ads_fb_exit,
+};
+
+static int mx21ads_sdhc_get_ro(struct device *dev)
+{
+	return (__raw_readw(MX21ADS_IO_REG) & MX21ADS_IO_SD_WP) ? 1 : 0;
+}
+
+static int mx21ads_sdhc_init(struct device *dev, irq_handler_t detect_irq,
+	void *data)
+{
+	int ret;
+
+	ret = request_irq(IRQ_GPIOD(25), detect_irq,
+		IRQF_TRIGGER_FALLING, "mmc-detect", data);
+	if (ret)
+		goto out;
+	return 0;
+out:
+	return ret;
+}
+
+static void mx21ads_sdhc_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIOD(25), data);
+}
+
+static struct imxmmc_platform_data mx21ads_sdhc_pdata = {
+	.ocr_avail = MMC_VDD_29_30 | MMC_VDD_30_31, /* 3.0V */
+	.get_ro = mx21ads_sdhc_get_ro,
+	.init = mx21ads_sdhc_init,
+	.exit = mx21ads_sdhc_exit,
+};
+
+static struct mxc_nand_platform_data mx21ads_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct map_desc mx21ads_io_desc[] __initdata = {
+	/*
+	 * Memory-mapped I/O on MX21ADS Base board:
+	 *   - CS8900A Ethernet controller
+	 *   - ST16C2552CJ UART
+	 *   - CPU and Base board version
+	 *   - Base board I/O register
+	 */
+	{
+		.virtual = MX21ADS_MMIO_BASE_ADDR,
+		.pfn = __phys_to_pfn(CS1_BASE_ADDR),
+		.length = MX21ADS_MMIO_SIZE,
+		.type = MT_DEVICE,
+	},
+};
+
+static void __init mx21ads_map_io(void)
+{
+	mx21_map_io();
+	iotable_init(mx21ads_io_desc, ARRAY_SIZE(mx21ads_io_desc));
+}
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mx21ads_nor_mtd_device,
+};
+
+static void __init mx21ads_board_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins),
+			"mx21ads");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_uart_device2, &uart_norts_pdata);
+	mxc_register_device(&mxc_uart_device3, &uart_pdata);
+	mxc_register_device(&mxc_fb_device, &mx21ads_fb_data);
+	mxc_register_device(&mxc_sdhc_device0, &mx21ads_sdhc_pdata);
+	mxc_register_device(&mxc_nand_device, &mx21ads_nand_board_info);
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mx21ads_timer_init(void)
+{
+	mx21_clocks_init(32768, 26000000);
+}
+
+static struct sys_timer mx21ads_timer = {
+	.init	= mx21ads_timer_init,
+};
+
+MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
+	/* maintainer: Freescale Semiconductor, Inc. */
+	.phys_io        = AIPI_BASE_ADDR,
+	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = mx21ads_map_io,
+	.init_irq       = mxc_init_irq,
+	.init_machine   = mx21ads_board_init,
+	.timer          = &mx21ads_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx27ads.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx27ads.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx27ads.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx27ads.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,8 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -33,9 +35,117 @@
 #include <mach/imx-uart.h>
 #include <mach/iomux.h>
 #include <mach/board-mx27ads.h>
+#include <mach/mxc_nand.h>
+#include <mach/i2c.h>
+#include <mach/imxfb.h>
+#include <mach/mmc.h>
 
 #include "devices.h"
 
+static unsigned int mx27ads_pins[] = {
+	/* UART0 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* UART1 */
+	PE3_PF_UART2_CTS,
+	PE4_PF_UART2_RTS,
+	PE6_PF_UART2_TXD,
+	PE7_PF_UART2_RXD,
+	/* UART2 */
+	PE8_PF_UART3_TXD,
+	PE9_PF_UART3_RXD,
+	PE10_PF_UART3_CTS,
+	PE11_PF_UART3_RTS,
+	/* UART3 */
+	PB26_AF_UART4_RTS,
+	PB28_AF_UART4_TXD,
+	PB29_AF_UART4_CTS,
+	PB31_AF_UART4_RXD,
+	/* UART4 */
+	PB18_AF_UART5_TXD,
+	PB19_AF_UART5_RXD,
+	PB20_AF_UART5_CTS,
+	PB21_AF_UART5_RTS,
+	/* UART5 */
+	PB10_AF_UART6_TXD,
+	PB12_AF_UART6_CTS,
+	PB11_AF_UART6_RXD,
+	PB13_AF_UART6_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+	/* I2C2 */
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL,
+	/* FB */
+	PA5_PF_LSCLK,
+	PA6_PF_LD0,
+	PA7_PF_LD1,
+	PA8_PF_LD2,
+	PA9_PF_LD3,
+	PA10_PF_LD4,
+	PA11_PF_LD5,
+	PA12_PF_LD6,
+	PA13_PF_LD7,
+	PA14_PF_LD8,
+	PA15_PF_LD9,
+	PA16_PF_LD10,
+	PA17_PF_LD11,
+	PA18_PF_LD12,
+	PA19_PF_LD13,
+	PA20_PF_LD14,
+	PA21_PF_LD15,
+	PA22_PF_LD16,
+	PA23_PF_LD17,
+	PA24_PF_REV,
+	PA25_PF_CLS,
+	PA26_PF_PS,
+	PA27_PF_SPL_SPR,
+	PA28_PF_HSYNC,
+	PA29_PF_VSYNC,
+	PA30_PF_CONTRAST,
+	PA31_PF_OE_ACD,
+	/* OWIRE */
+	PE16_AF_OWIRE,
+	/* SDHC1*/
+	PE18_PF_SD1_D0,
+	PE19_PF_SD1_D1,
+	PE20_PF_SD1_D2,
+	PE21_PF_SD1_D3,
+	PE22_PF_SD1_CMD,
+	PE23_PF_SD1_CLK,
+	/* SDHC2*/
+	PB4_PF_SD2_D0,
+	PB5_PF_SD2_D1,
+	PB6_PF_SD2_D2,
+	PB7_PF_SD2_D3,
+	PB8_PF_SD2_CMD,
+	PB9_PF_SD2_CLK,
+};
+
+static struct mxc_nand_platform_data mx27ads_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
 /* ADS's NOR flash */
 static struct physmap_flash_data mx27ads_flash_data = {
 	.width = 2,
@@ -58,189 +168,113 @@
 	.resource = &mx27ads_flash_resource,
 };
 
-static int mxc_uart0_pins[] = {
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS
+static struct imxi2c_platform_data mx27ads_i2c_data = {
+	.bitrate = 100000,
 };
 
-static int uart_mxc_port0_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart0_pins,
-			ARRAY_SIZE(mxc_uart0_pins), "UART0");
-}
-
-static int uart_mxc_port0_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart0_pins,
-			ARRAY_SIZE(mxc_uart0_pins));
-	return 0;
-}
-
-static int mxc_uart1_pins[] = {
-	PE3_PF_UART2_CTS,
-	PE4_PF_UART2_RTS,
-	PE6_PF_UART2_TXD,
-	PE7_PF_UART2_RXD
+static struct i2c_board_info mx27ads_i2c_devices[] = {
 };
 
-static int uart_mxc_port1_init(struct platform_device *pdev)
+void lcd_power(int on)
 {
-	return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins), "UART1");
+	if (on)
+		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG);
+	else
+		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG);
 }
 
-static int uart_mxc_port1_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins));
-	return 0;
-}
+static struct imx_fb_platform_data mx27ads_fb_data = {
+	.pixclock	= 188679,
+	.xres		= 240,
+	.yres		= 320,
 
-static int mxc_uart2_pins[] = {
-	PE8_PF_UART3_TXD,
-	PE9_PF_UART3_RXD,
-	PE10_PF_UART3_CTS,
-	PE11_PF_UART3_RTS
-};
+	.bpp		= 16,
+	.hsync_len	= 1,
+	.left_margin	= 9,
+	.right_margin	= 16,
 
-static int uart_mxc_port2_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
-			ARRAY_SIZE(mxc_uart2_pins), "UART2");
-}
+	.vsync_len	= 1,
+	.upper_margin	= 7,
+	.lower_margin	= 9,
+	.fixed_screen_cpu = 0,
 
-static int uart_mxc_port2_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart2_pins,
-			ARRAY_SIZE(mxc_uart2_pins));
-	return 0;
-}
+	/*
+	 * - HSYNC active high
+	 * - VSYNC active high
+	 * - clk notenabled while idle
+	 * - clock inverted
+	 * - data not inverted
+	 * - data enable low active
+	 * - enable sharp mode
+	 */
+	.pcr		= 0xFB008BC0,
+	.pwmr		= 0x00A903FF,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00020010,
 
-static int mxc_uart3_pins[] = {
-	PB26_AF_UART4_RTS,
-	PB28_AF_UART4_TXD,
-	PB29_AF_UART4_CTS,
-	PB31_AF_UART4_RXD
+	.lcd_power	= lcd_power,
 };
 
-static int uart_mxc_port3_init(struct platform_device *pdev)
+static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
+			      void *data)
 {
-	return mxc_gpio_setup_multiple_pins(mxc_uart3_pins,
-			ARRAY_SIZE(mxc_uart3_pins), "UART3");
+	return request_irq(IRQ_GPIOE(21), detect_irq, IRQF_TRIGGER_RISING,
+			   "sdhc1-card-detect", data);
 }
 
-static int uart_mxc_port3_exit(struct platform_device *pdev)
+static int mx27ads_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
+			      void *data)
 {
-	mxc_gpio_release_multiple_pins(mxc_uart3_pins,
-			ARRAY_SIZE(mxc_uart3_pins));
-	return 0;
+	return request_irq(IRQ_GPIOB(7), detect_irq, IRQF_TRIGGER_RISING,
+			   "sdhc2-card-detect", data);
 }
 
-static int mxc_uart4_pins[] = {
-	PB18_AF_UART5_TXD,
-	PB19_AF_UART5_RXD,
-	PB20_AF_UART5_CTS,
-	PB21_AF_UART5_RTS
-};
-
-static int uart_mxc_port4_init(struct platform_device *pdev)
+static void mx27ads_sdhc1_exit(struct device *dev, void *data)
 {
-	return mxc_gpio_setup_multiple_pins(mxc_uart4_pins,
-			ARRAY_SIZE(mxc_uart4_pins), "UART4");
+	free_irq(IRQ_GPIOE(21), data);
 }
 
-static int uart_mxc_port4_exit(struct platform_device *pdev)
+static void mx27ads_sdhc2_exit(struct device *dev, void *data)
 {
-	mxc_gpio_release_multiple_pins(mxc_uart4_pins,
-			ARRAY_SIZE(mxc_uart4_pins));
-	return 0;
+	free_irq(IRQ_GPIOB(7), data);
 }
 
-static int mxc_uart5_pins[] = {
-	PB10_AF_UART6_TXD,
-	PB12_AF_UART6_CTS,
-	PB11_AF_UART6_RXD,
-	PB13_AF_UART6_RTS
+static struct imxmmc_platform_data sdhc1_pdata = {
+	.init = mx27ads_sdhc1_init,
+	.exit = mx27ads_sdhc1_exit,
 };
 
-static int uart_mxc_port5_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart5_pins,
-			ARRAY_SIZE(mxc_uart5_pins), "UART5");
-}
-
-static int uart_mxc_port5_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart5_pins,
-			ARRAY_SIZE(mxc_uart5_pins));
-	return 0;
-}
+static struct imxmmc_platform_data sdhc2_pdata = {
+	.init = mx27ads_sdhc2_init,
+	.exit = mx27ads_sdhc2_exit,
+};
 
 static struct platform_device *platform_devices[] __initdata = {
 	&mx27ads_nor_mtd_device,
 	&mxc_fec_device,
+	&mxc_w1_master_device,
 };
 
-static int mxc_fec_pins[] = {
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN
-};
-
-static void gpio_fec_active(void)
-{
-	mxc_gpio_setup_multiple_pins(mxc_fec_pins,
-			ARRAY_SIZE(mxc_fec_pins), "FEC");
-}
-
 static struct imxuart_platform_data uart_pdata[] = {
 	{
-		.init = uart_mxc_port0_init,
-		.exit = uart_mxc_port0_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart_mxc_port1_init,
-		.exit = uart_mxc_port1_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart_mxc_port2_init,
-		.exit = uart_mxc_port2_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart_mxc_port3_init,
-		.exit = uart_mxc_port3_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart_mxc_port4_init,
-		.exit = uart_mxc_port4_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart_mxc_port5_init,
-		.exit = uart_mxc_port5_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	},
 };
 
 static void __init mx27ads_board_init(void)
 {
-	gpio_fec_active();
+	mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins),
+			"mx27ads");
 
 	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
 	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
@@ -248,6 +282,15 @@
 	mxc_register_device(&mxc_uart_device3, &uart_pdata[3]);
 	mxc_register_device(&mxc_uart_device4, &uart_pdata[4]);
 	mxc_register_device(&mxc_uart_device5, &uart_pdata[5]);
+	mxc_register_device(&mxc_nand_device, &mx27ads_nand_board_info);
+
+	/* only the i2c master 1 is used on this CPU card */
+	i2c_register_board_info(1, mx27ads_i2c_devices,
+				ARRAY_SIZE(mx27ads_i2c_devices));
+	mxc_register_device(&mxc_i2c_device1, &mx27ads_i2c_data);
+	mxc_register_device(&mxc_fb_device, &mx27ads_fb_data);
+	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
+	mxc_register_device(&mxc_sdhc_device1, &sdhc2_pdata);
 
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
@@ -277,7 +320,7 @@
 
 static void __init mx27ads_map_io(void)
 {
-	mxc_map_io();
+	mx27_map_io();
 	iotable_init(mx27ads_io_desc, ARRAY_SIZE(mx27ads_io_desc));
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx27lite.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx27lite.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx27lite.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx27lite.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ * Copyright 2009 Daniel Schaeffer (daniel.schaeffer@timesys.com)
+ *
+ * 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/platform_device.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux.h>
+#include <mach/board-mx27lite.h>
+
+#include "devices.h"
+
+static unsigned int mx27lite_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static void __init mx27lite_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
+		"imx27lite");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mx27lite_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer mx27lite_timer = {
+	.init	= mx27lite_timer_init,
+};
+
+MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
+	.phys_io        = AIPI_BASE_ADDR,
+	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = mx27_map_io,
+	.init_irq       = mxc_init_irq,
+	.init_machine   = mx27lite_init,
+	.timer          = &mx27lite_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx27pdk.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx27pdk.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/mx27pdk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/mx27pdk.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * 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/platform_device.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux.h>
+#include <mach/board-mx27pdk.h>
+
+#include "devices.h"
+
+static unsigned int mx27pdk_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static void __init mx27pdk_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
+		"mx27pdk");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mx27pdk_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer mx27pdk_timer = {
+	.init	= mx27pdk_timer_init,
+};
+
+MACHINE_START(MX27_3DS, "Freescale MX27PDK")
+	/* maintainer: Freescale Semiconductor, Inc. */
+	.phys_io        = AIPI_BASE_ADDR,
+	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = mx27_map_io,
+	.init_irq       = mxc_init_irq,
+	.init_machine   = mx27pdk_init,
+	.timer          = &mx27pdk_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/pcm038.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/pcm038.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/pcm038.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/pcm038.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,28 +17,84 @@
  * MA 02110-1301, USA.
  */
 
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
+#include <linux/io.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
 
-#include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/board-pcm038.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/iomux.h>
-#ifdef CONFIG_I2C_IMX
 #include <mach/i2c.h>
-#endif
-#include <asm/mach/time.h>
+#include <mach/iomux.h>
 #include <mach/imx-uart.h>
-#include <mach/board-pcm038.h>
 #include <mach/mxc_nand.h>
 
 #include "devices.h"
 
+static int pcm038_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* UART2 */
+	PE3_PF_UART2_CTS,
+	PE4_PF_UART2_RTS,
+	PE6_PF_UART2_TXD,
+	PE7_PF_UART2_RXD,
+	/* UART3 */
+	PE8_PF_UART3_TXD,
+	PE9_PF_UART3_RXD,
+	PE10_PF_UART3_CTS,
+	PE11_PF_UART3_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+	/* I2C2 */
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL,
+	/* SPI1 */
+	PD25_PF_CSPI1_RDY,
+	PD27_PF_CSPI1_SS1,
+	PD28_PF_CSPI1_SS0,
+	PD29_PF_CSPI1_SCLK,
+	PD30_PF_CSPI1_MISO,
+	PD31_PF_CSPI1_MOSI,
+	/* SSI1 */
+	PC20_PF_SSI1_FS,
+	PC21_PF_SSI1_RXD,
+	PC22_PF_SSI1_TXD,
+	PC23_PF_SSI1_CLK,
+	/* SSI4 */
+	PC16_PF_SSI4_FS,
+	PC17_PF_SSI4_RXD,
+	PC18_PF_SSI4_TXD,
+	PC19_PF_SSI4_CLK,
+};
+
 /*
  * Phytec's PCM038 comes with 2MiB battery buffered SRAM,
  * 16 bit width
@@ -88,107 +144,16 @@
 	.resource = &pcm038_flash_resource,
 };
 
-static int mxc_uart0_pins[] = {
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS
-};
-
-static int uart_mxc_port0_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart0_pins,
-			ARRAY_SIZE(mxc_uart0_pins), "UART0");
-}
-
-static int uart_mxc_port0_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart0_pins,
-			ARRAY_SIZE(mxc_uart0_pins));
-	return 0;
-}
-
-static int mxc_uart1_pins[] = {
-	PE3_PF_UART2_CTS,
-	PE4_PF_UART2_RTS,
-	PE6_PF_UART2_TXD,
-	PE7_PF_UART2_RXD
-};
-
-static int uart_mxc_port1_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins), "UART1");
-}
-
-static int uart_mxc_port1_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins));
-	return 0;
-}
-
-static int mxc_uart2_pins[] = { PE8_PF_UART3_TXD,
-				PE9_PF_UART3_RXD,
-				PE10_PF_UART3_CTS,
-				PE11_PF_UART3_RTS };
-
-static int uart_mxc_port2_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
-			ARRAY_SIZE(mxc_uart2_pins), "UART2");
-}
-
-static int uart_mxc_port2_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart2_pins,
-			ARRAY_SIZE(mxc_uart2_pins));
-	return 0;
-}
-
 static struct imxuart_platform_data uart_pdata[] = {
 	{
-		.init = uart_mxc_port0_init,
-		.exit = uart_mxc_port0_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart_mxc_port1_init,
-		.exit = uart_mxc_port1_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	}, {
-		.init = uart_mxc_port2_init,
-		.exit = uart_mxc_port2_exit,
 		.flags = IMXUART_HAVE_RTSCTS,
 	},
 };
 
-static int mxc_fec_pins[] = {
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN
-};
-
-static void gpio_fec_active(void)
-{
-	mxc_gpio_setup_multiple_pins(mxc_fec_pins,
-			ARRAY_SIZE(mxc_fec_pins), "FEC");
-}
-
 static struct mxc_nand_platform_data pcm038_nand_board_info = {
 	.width = 1,
 	.hw_ecc = 1,
@@ -210,27 +175,8 @@
 	__raw_writel(0x22220a00, CSCR_A(1));
 }
 
-#ifdef CONFIG_I2C_IMX
-static int mxc_i2c1_pins[] = {
-	PC5_PF_I2C2_SDA,
-	PC6_PF_I2C2_SCL
-};
-
-static int pcm038_i2c_1_init(struct device *dev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_i2c1_pins, ARRAY_SIZE(mxc_i2c1_pins),
-			"I2C1");
-}
-
-static void pcm038_i2c_1_exit(struct device *dev)
-{
-	mxc_gpio_release_multiple_pins(mxc_i2c1_pins, ARRAY_SIZE(mxc_i2c1_pins));
-}
-
 static struct imxi2c_platform_data pcm038_i2c_1_data = {
 	.bitrate = 100000,
-	.init = pcm038_i2c_1_init,
-	.exit = pcm038_i2c_1_exit,
 };
 
 static struct at24_platform_data board_eeprom = {
@@ -253,11 +199,12 @@
 		.type = "lm75"
 	}
 };
-#endif
 
 static void __init pcm038_init(void)
 {
-	gpio_fec_active();
+	mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),
+			"PCM038");
+
 	pcm038_init_sram();
 
 	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
@@ -267,13 +214,11 @@
 	mxc_gpio_mode(PE16_AF_OWIRE);
 	mxc_register_device(&mxc_nand_device, &pcm038_nand_board_info);
 
-#ifdef CONFIG_I2C_IMX
 	/* only the i2c master 1 is used on this CPU card */
 	i2c_register_board_info(1, pcm038_i2c_devices,
 				ARRAY_SIZE(pcm038_i2c_devices));
 
 	mxc_register_device(&mxc_i2c_device1, &pcm038_i2c_1_data);
-#endif
 
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
@@ -295,7 +240,7 @@
 	.phys_io        = AIPI_BASE_ADDR,
 	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mxc_map_io,
+	.map_io         = mx27_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = pcm038_init,
 	.timer          = &pcm038_timer,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx2/pcm970-baseboard.c linux-libre-2.6.31-gnu/arch/arm/mach-mx2/pcm970-baseboard.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx2/pcm970-baseboard.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx2/pcm970-baseboard.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,71 +16,107 @@
  * MA 02110-1301, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
+#include <linux/platform_device.h>
 
 #include <asm/mach/arch.h>
 
-#include <mach/hardware.h>
 #include <mach/common.h>
-#include <mach/mmc.h>
-#include <mach/imxfb.h>
 #include <mach/iomux.h>
+#include <mach/imxfb.h>
+#include <mach/hardware.h>
+#include <mach/mmc.h>
 
 #include "devices.h"
 
-static int pcm970_sdhc2_get_ro(struct device *dev)
-{
-	return gpio_get_value(GPIO_PORTC + 28);
-}
-
-static int pcm970_sdhc2_pins[] = {
+static int pcm970_pins[] = {
+	/* SDHC */
 	PB4_PF_SD2_D0,
 	PB5_PF_SD2_D1,
 	PB6_PF_SD2_D2,
 	PB7_PF_SD2_D3,
 	PB8_PF_SD2_CMD,
 	PB9_PF_SD2_CLK,
+	GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN, /* card detect */
+	/* display */
+	PA5_PF_LSCLK,
+	PA6_PF_LD0,
+	PA7_PF_LD1,
+	PA8_PF_LD2,
+	PA9_PF_LD3,
+	PA10_PF_LD4,
+	PA11_PF_LD5,
+	PA12_PF_LD6,
+	PA13_PF_LD7,
+	PA14_PF_LD8,
+	PA15_PF_LD9,
+	PA16_PF_LD10,
+	PA17_PF_LD11,
+	PA18_PF_LD12,
+	PA19_PF_LD13,
+	PA20_PF_LD14,
+	PA21_PF_LD15,
+	PA22_PF_LD16,
+	PA23_PF_LD17,
+	PA24_PF_REV,
+	PA25_PF_CLS,
+	PA26_PF_PS,
+	PA27_PF_SPL_SPR,
+	PA28_PF_HSYNC,
+	PA29_PF_VSYNC,
+	PA30_PF_CONTRAST,
+	PA31_PF_OE_ACD,
+	/*
+	 * it seems the data line misses a pullup, so we must enable
+	 * the internal pullup as a local workaround
+	 */
+	PD17_PF_I2C_DATA | GPIO_PUEN,
+	PD18_PF_I2C_CLK,
+	/* Camera */
+	PB10_PF_CSI_D0,
+	PB11_PF_CSI_D1,
+	PB12_PF_CSI_D2,
+	PB13_PF_CSI_D3,
+	PB14_PF_CSI_D4,
+	PB15_PF_CSI_MCLK,
+	PB16_PF_CSI_PIXCLK,
+	PB17_PF_CSI_D5,
+	PB18_PF_CSI_D6,
+	PB19_PF_CSI_D7,
+	PB20_PF_CSI_VSYNC,
+	PB21_PF_CSI_HSYNC,
 };
 
+static int pcm970_sdhc2_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO_PORTC + 28);
+}
+
 static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void *data)
 {
 	int ret;
 
-	ret = mxc_gpio_setup_multiple_pins(pcm970_sdhc2_pins,
-		ARRAY_SIZE(pcm970_sdhc2_pins), "sdhc2");
-	if(ret)
-		return ret;
-
-	ret = request_irq(IRQ_GPIOC(29), detect_irq, 0,
+	ret = request_irq(IRQ_GPIOC(29), detect_irq, IRQF_TRIGGER_FALLING,
 				"imx-mmc-detect", data);
 	if (ret)
-		goto out_release_gpio;
-
-	set_irq_type(IRQ_GPIOC(29), IRQF_TRIGGER_FALLING);
+		return ret;
 
 	ret = gpio_request(GPIO_PORTC + 28, "imx-mmc-ro");
-	if (ret)
-		goto out_release_gpio;
+	if (ret) {
+		free_irq(IRQ_GPIOC(29), data);
+		return ret;
+	}
 
-	mxc_gpio_mode((GPIO_PORTC | 28) | GPIO_GPIO | GPIO_IN);
 	gpio_direction_input(GPIO_PORTC + 28);
 
 	return 0;
-
-out_release_gpio:
-	mxc_gpio_release_multiple_pins(pcm970_sdhc2_pins,
-			ARRAY_SIZE(pcm970_sdhc2_pins));
-	return ret;
 }
 
 static void pcm970_sdhc2_exit(struct device *dev, void *data)
 {
 	free_irq(IRQ_GPIOC(29), data);
 	gpio_free(GPIO_PORTC + 28);
-	mxc_gpio_release_multiple_pins(pcm970_sdhc2_pins,
-			ARRAY_SIZE(pcm970_sdhc2_pins));
 }
 
 static struct imxmmc_platform_data sdhc_pdata = {
@@ -89,29 +125,6 @@
 	.exit = pcm970_sdhc2_exit,
 };
 
-static int mxc_fb_pins[] = {
-	PA5_PF_LSCLK,	PA6_PF_LD0,	PA7_PF_LD1,	PA8_PF_LD2,
-	PA9_PF_LD3,	PA10_PF_LD4,	PA11_PF_LD5,	PA12_PF_LD6,
-	PA13_PF_LD7,	PA14_PF_LD8,	PA15_PF_LD9,	PA16_PF_LD10,
-	PA17_PF_LD11,	PA18_PF_LD12,	PA19_PF_LD13,	PA20_PF_LD14,
-	PA21_PF_LD15,	PA22_PF_LD16,	PA23_PF_LD17,	PA24_PF_REV,
-	PA25_PF_CLS,	PA26_PF_PS,	PA27_PF_SPL_SPR, PA28_PF_HSYNC,
-	PA29_PF_VSYNC,	PA30_PF_CONTRAST, PA31_PF_OE_ACD
-};
-
-static int pcm038_fb_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_fb_pins,
-			ARRAY_SIZE(mxc_fb_pins), "FB");
-}
-
-static int pcm038_fb_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_fb_pins, ARRAY_SIZE(mxc_fb_pins));
-
-	return 0;
-}
-
 /*
  * Connected is a portrait Sharp-QVGA display
  * of type: LQ035Q7DH06
@@ -144,9 +157,6 @@
 	.pwmr		= 0x00A903FF,
 	.lscr1		= 0x00120300,
 	.dmacr		= 0x00020010,
-
-	.init = pcm038_fb_init,
-	.exit = pcm038_fb_exit,
 };
 
 /*
@@ -157,6 +167,9 @@
  */
 void __init pcm970_baseboard_init(void)
 {
+	mxc_gpio_setup_multiple_pins(pcm970_pins, ARRAY_SIZE(pcm970_pins),
+			"PCM970");
+
 	mxc_register_device(&mxc_fb_device, &pcm038_fb_data);
 	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/armadillo5x0.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/armadillo5x0.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/armadillo5x0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/armadillo5x0.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,358 @@
+/*
+ * armadillo5x0.c
+ *
+ * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ * updates in http://alberdroid.blogspot.com/
+ *
+ * Based on Atmark Techno, Inc. armadillo 500 BSP 2008
+ * Based on mx31ads.c and pcm037.c Great Work!
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/memory.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include <mach/board-armadillo5x0.h>
+#include <mach/mmc.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+#include <mach/mxc_nand.h>
+
+#include "devices.h"
+#include "crm_regs.h"
+
+static int armadillo5x0_pins[] = {
+	/* UART1 */
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+	/* UART2 */
+	MX31_PIN_CTS2__CTS2,
+	MX31_PIN_RTS2__RTS2,
+	MX31_PIN_TXD2__TXD2,
+	MX31_PIN_RXD2__RXD2,
+	/* LAN9118_IRQ */
+	IOMUX_MODE(MX31_PIN_GPIO1_0, IOMUX_CONFIG_GPIO),
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
+	/* Framebuffer */
+	MX31_PIN_LD0__LD0,
+	MX31_PIN_LD1__LD1,
+	MX31_PIN_LD2__LD2,
+	MX31_PIN_LD3__LD3,
+	MX31_PIN_LD4__LD4,
+	MX31_PIN_LD5__LD5,
+	MX31_PIN_LD6__LD6,
+	MX31_PIN_LD7__LD7,
+	MX31_PIN_LD8__LD8,
+	MX31_PIN_LD9__LD9,
+	MX31_PIN_LD10__LD10,
+	MX31_PIN_LD11__LD11,
+	MX31_PIN_LD12__LD12,
+	MX31_PIN_LD13__LD13,
+	MX31_PIN_LD14__LD14,
+	MX31_PIN_LD15__LD15,
+	MX31_PIN_LD16__LD16,
+	MX31_PIN_LD17__LD17,
+	MX31_PIN_VSYNC3__VSYNC3,
+	MX31_PIN_HSYNC__HSYNC,
+	MX31_PIN_FPSHIFT__FPSHIFT,
+	MX31_PIN_DRDY0__DRDY0,
+	IOMUX_MODE(MX31_PIN_LCS1, IOMUX_CONFIG_GPIO), /*ADV7125_PSAVE*/
+};
+
+/*
+ * NAND Flash
+ */
+static struct mxc_nand_platform_data armadillo5x0_nand_flash_pdata = {
+	.width		= 1,
+	.hw_ecc		= 1,
+};
+
+/*
+ * MTD NOR Flash
+ */
+static struct mtd_partition armadillo5x0_nor_flash_partitions[] = {
+	{
+		.name		= "nor.bootloader",
+		.offset		= 0x00000000,
+		.size		= 4*32*1024,
+	}, {
+		.name		= "nor.kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 16*128*1024,
+	}, {
+		.name		= "nor.userland",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 110*128*1024,
+	}, {
+		.name		= "nor.config",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 1*128*1024,
+	},
+};
+
+static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+	.width		= 2,
+	.parts		= armadillo5x0_nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
+};
+
+static struct resource armadillo5x0_nor_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+	.start		= CS0_BASE_ADDR,
+	.end		= CS0_BASE_ADDR + SZ_64M - 1,
+};
+
+static struct platform_device armadillo5x0_nor_flash = {
+	.name			= "physmap-flash",
+	.id			= -1,
+	.num_resources		= 1,
+	.resource		= &armadillo5x0_nor_flash_resource,
+};
+
+/*
+ * FB support
+ */
+static const struct fb_videomode fb_modedb[] = {
+	{	/* 640x480 @ 60 Hz */
+		.name		= "CRT-VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 35,
+		.right_margin	= 115,
+		.upper_margin	= 43,
+		.lower_margin	= 1,
+		.hsync_len	= 10,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {/* 800x600 @ 56 Hz */
+		.name		= "CRT-SVGA",
+		.refresh	= 56,
+		.xres		= 800,
+		.yres		= 600,
+		.pixclock	= 30000,
+		.left_margin	= 30,
+		.right_margin	= 108,
+		.upper_margin	= 13,
+		.lower_margin	= 10,
+		.hsync_len	= 10,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_HOR_HIGH_ACT |
+				  FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "CRT-VGA",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+/*
+ * SDHC 1
+ * MMC support
+ */
+static int armadillo5x0_sdhc1_get_ro(struct device *dev)
+{
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
+}
+
+static int armadillo5x0_sdhc1_init(struct device *dev,
+				   irq_handler_t detect_irq, void *data)
+{
+	int ret;
+	int gpio_det, gpio_wp;
+
+	gpio_det = IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK);
+	gpio_wp = IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B);
+
+	ret = gpio_request(gpio_det, "sdhc-card-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(gpio_det);
+
+	ret = gpio_request(gpio_wp, "sdhc-write-protect");
+	if (ret)
+		goto err_gpio_free;
+
+	gpio_direction_input(gpio_wp);
+
+	/* When supported the trigger type have to be BOTH */
+	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), detect_irq,
+			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  "sdhc-detect", data);
+
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+	gpio_free(gpio_wp);
+
+err_gpio_free:
+	gpio_free(gpio_det);
+
+	return ret;
+
+}
+
+static void armadillo5x0_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), data);
+	gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK));
+	gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
+}
+
+static struct imxmmc_platform_data sdhc_pdata = {
+	.get_ro = armadillo5x0_sdhc1_get_ro,
+	.init = armadillo5x0_sdhc1_init,
+	.exit = armadillo5x0_sdhc1_exit,
+};
+
+/*
+ * SMSC 9118
+ * Network support
+ */
+static struct resource armadillo5x0_smc911x_resources[] = {
+	{
+		.start	= CS3_BASE_ADDR,
+		.end	= CS3_BASE_ADDR + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_info = {
+	.flags		= SMSC911X_USE_32BIT,
+	.irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device armadillo5x0_smc911x_device = {
+	.name           = "smsc911x",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(armadillo5x0_smc911x_resources),
+	.resource       = armadillo5x0_smc911x_resources,
+	.dev            = {
+		.platform_data = &smsc911x_info,
+	},
+};
+
+/* UART device data */
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&armadillo5x0_smc911x_device,
+};
+
+/*
+ * Perform board specific initializations
+ */
+static void __init armadillo5x0_init(void)
+{
+	mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
+			ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	/* Register UART */
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+
+	/* SMSC9118 IRQ pin */
+	gpio_direction_input(MX31_PIN_GPIO1_0);
+
+	/* Register SDHC */
+	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
+
+	/* Register FB */
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+	/* Register NOR Flash */
+	mxc_register_device(&armadillo5x0_nor_flash,
+			    &armadillo5x0_nor_flash_pdata);
+
+	/* Register NAND Flash */
+	mxc_register_device(&mxc_nand_device, &armadillo5x0_nand_flash_pdata);
+
+	/* set NAND page size to 2k if not configured via boot mode pins */
+	__raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR);
+}
+
+static void __init armadillo5x0_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer armadillo5x0_timer = {
+	.init	= armadillo5x0_timer_init,
+};
+
+MACHINE_START(ARMADILLO5X0, "Armadillo-500")
+	/* Maintainer: Alberto Panizzo  */
+	.phys_io	= AIPS1_BASE_ADDR,
+	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.map_io		= mx31_map_io,
+	.init_irq	= mxc_init_irq,
+	.timer		= &armadillo5x0_timer,
+	.init_machine	= armadillo5x0_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -483,7 +483,7 @@
 DEFINE_CLOCK(mpeg4_clk,   0, MXC_CCM_CGR1,  0, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1,  2, mstick1_get_rate, NULL, &usb_pll_clk);
 DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1,  4, mstick2_get_rate, NULL, &usb_pll_clk);
-DEFINE_CLOCK1(csi_clk,    0, MXC_CCM_CGR1,  6, csi, NULL, &ahb_clk);
+DEFINE_CLOCK1(csi_clk,    0, MXC_CCM_CGR1,  6, csi, NULL, &serial_pll_clk);
 DEFINE_CLOCK(rtc_clk,     0, MXC_CCM_CGR1,  8, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(wdog_clk,    0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(pwm_clk,     0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
@@ -566,13 +566,18 @@
 	u32 reg;
 	int i;
 
-	mxc_set_cpu_type(MXC_CPU_MX31);
-
 	ckih_rate = fref;
 
 	for (i = 0; i < ARRAY_SIZE(lookups); i++)
 		clkdev_add(&lookups[i]);
 
+	/* change the csi_clk parent if necessary */
+	reg = __raw_readl(MXC_CCM_CCMR);
+	if (!(reg & MXC_CCM_CCMR_CSCS))
+		if (clk_set_parent(&csi_clk, &usb_pll_clk))
+			pr_err("%s: error changing csi_clk parent\n", __func__);
+
+
 	/* Turn off all possible clocks */
 	__raw_writel((3 << 4), MXC_CCM_CGR0);
 	__raw_writel(0, MXC_CCM_CGR1);
@@ -581,6 +586,12 @@
 					   MX32, but still required to be set */
 		     MXC_CCM_CGR2);
 
+	/*
+	 * Before turning off usb_pll make sure ipg_per_clk is generated
+	 * by ipg_clk and not usb_pll.
+	 */
+	__raw_writel(__raw_readl(MXC_CCM_CCMR) | (1 << 24), MXC_CCM_CCMR);
+
 	usb_pll_disable(&usb_pll_clk);
 
 	pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/clock-imx35.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/clock-imx35.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/clock-imx35.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/clock-imx35.c	2009-09-09 18:13:59.000000000 -0400
@@ -147,34 +147,16 @@
 	{ .arm = 0, .ahb = 0, .sel = 0},
 };
 
-static struct arm_ahb_div clk_automotive[] = {
-	{ .arm = 1, .ahb = 3, .sel = 0},
-	{ .arm = 1, .ahb = 2, .sel = 1},
-	{ .arm = 2, .ahb = 1, .sel = 1},
-	{ .arm = 0, .ahb = 0, .sel = 0},
-	{ .arm = 1, .ahb = 6, .sel = 0},
-	{ .arm = 1, .ahb = 4, .sel = 1},
-	{ .arm = 2, .ahb = 2, .sel = 1},
-	{ .arm = 0, .ahb = 0, .sel = 0},
-};
-
 static unsigned long get_rate_arm(void)
 {
 	unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
 	struct arm_ahb_div *aad;
 	unsigned long fref = get_rate_mpll();
 
-	if (pdr0 & 1) {
-		/* consumer path */
-		aad = &clk_consumer[(pdr0 >> 16) & 0xf];
-		if (aad->sel)
-			fref = fref * 2 / 3;
-	} else {
-		/* auto path */
-		aad = &clk_automotive[(pdr0 >> 9) & 0x7];
-		if (aad->sel)
-			fref = fref * 3 / 4;
-	}
+	aad = &clk_consumer[(pdr0 >> 16) & 0xf];
+	if (aad->sel)
+		fref = fref * 2 / 3;
+
 	return fref / aad->arm;
 }
 
@@ -184,12 +166,7 @@
 	struct arm_ahb_div *aad;
 	unsigned long fref = get_rate_mpll();
 
-	if (pdr0 & 1)
-		/* consumer path */
-		aad = &clk_consumer[(pdr0 >> 16) & 0xf];
-	else
-		/* auto path */
-		aad = &clk_automotive[(pdr0 >> 9) & 0x7];
+	aad = &clk_consumer[(pdr0 >> 16) & 0xf];
 
 	return fref / aad->ahb;
 }
@@ -430,7 +407,8 @@
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
 	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
 	_REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk)
-	_REGISTER_CLOCK(NULL, "ipu", ipu_clk)
+	_REGISTER_CLOCK("ipu-core", NULL, ipu_clk)
+	_REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk)
 	_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
 	_REGISTER_CLOCK(NULL, "mlb", mlb_clk)
 	_REGISTER_CLOCK(NULL, "mshc", mshc_clk)
@@ -462,8 +440,6 @@
 	int i;
 	unsigned int ll = 0;
 
-	mxc_set_cpu_type(MXC_CPU_MX35);
-
 #ifdef CONFIG_DEBUG_LL_CONSOLE
 	ll = (3 << 16);
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/devices.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/devices.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/devices.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/devices.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,13 +17,16 @@
  * Boston, MA  02110-1301, USA.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/gpio.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/common.h>
 #include <mach/imx-uart.h>
+#include <mach/mx3_camera.h>
 
 #include "devices.h"
 
@@ -283,6 +286,21 @@
 	.num_resources = ARRAY_SIZE(mxcsdhc1_resources),
 	.resource = mxcsdhc1_resources,
 };
+
+static struct resource rnga_resources[] = {
+	{
+		.start = RNGA_BASE_ADDR,
+		.end = RNGA_BASE_ADDR + 0x28,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device mxc_rnga_device = {
+	.name = "mxc_rnga",
+	.id = -1,
+	.num_resources = 1,
+	.resource = rnga_resources,
+};
 #endif /* CONFIG_ARCH_MX31 */
 
 /* i.MX31 Image Processing Unit */
@@ -329,10 +347,54 @@
 	.num_resources	= ARRAY_SIZE(fb_resources),
 	.resource	= fb_resources,
 	.dev		= {
-		.coherent_dma_mask = 0xffffffff,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
+static struct resource camera_resources[] = {
+	{
+		.start	= IPU_CTRL_BASE_ADDR + 0x60,
+		.end	= IPU_CTRL_BASE_ADDR + 0x87,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device mx3_camera = {
+	.name		= "mx3-camera",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(camera_resources),
+	.resource	= camera_resources,
+	.dev		= {
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource otg_resources[] = {
+	{
+		.start	= OTG_BASE_ADDR,
+		.end	= OTG_BASE_ADDR + 0x1ff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= MXC_INT_USB3,
+		.end	= MXC_INT_USB3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 otg_dmamask = DMA_BIT_MASK(32);
+
+/* OTG gadget device */
+struct platform_device mxc_otg_udc_device = {
+	.name		= "fsl-usb2-udc",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &otg_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= otg_resources,
+	.num_resources	= ARRAY_SIZE(otg_resources),
+};
+
 #ifdef CONFIG_ARCH_MX35
 static struct resource mxc_fec_resources[] = {
 	{
@@ -359,6 +421,7 @@
 	if (cpu_is_mx31()) {
 		mxc_nand_resources[0].start = MX31_NFC_BASE_ADDR;
 		mxc_nand_resources[0].end = MX31_NFC_BASE_ADDR + 0xfff;
+		mxc_register_device(&mxc_rnga_device, NULL);
 	}
 	if (cpu_is_mx35()) {
 		mxc_nand_resources[0].start = MX35_NFC_BASE_ADDR;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/devices.h linux-libre-2.6.31-gnu/arch/arm/mach-mx3/devices.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/devices.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/devices.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,10 @@
 extern struct platform_device mxc_i2c_device2;
 extern struct platform_device mx3_ipu;
 extern struct platform_device mx3_fb;
+extern struct platform_device mx3_camera;
 extern struct platform_device mxc_fec_device;
 extern struct platform_device mxcsdhc_device0;
 extern struct platform_device mxcsdhc_device1;
+extern struct platform_device mxc_otg_udc_device;
+extern struct platform_device mxc_rnga_device;
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/iomux.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/iomux.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/iomux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/iomux.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
@@ -94,15 +93,13 @@
 EXPORT_SYMBOL(mxc_iomux_set_pad);
 
 /*
- * setups a single pin:
+ * allocs a single pin:
  * 	- reserves the pin so that it is not claimed by another driver
  * 	- setups the iomux according to the configuration
- * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
  */
-int mxc_iomux_setup_pin(const unsigned int pin, const char *label)
+int mxc_iomux_alloc_pin(const unsigned int pin, const char *label)
 {
 	unsigned pad = pin & IOMUX_PADNUM_MASK;
-	unsigned gpio;
 
 	if (pad >= (PIN_MAX + 1)) {
 		printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n",
@@ -113,19 +110,13 @@
 	if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
 		printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
 			pad, label ? label : "?");
-		return -EINVAL;
+		return -EBUSY;
 	}
 	mxc_iomux_mode(pin);
 
-	/* if we have a gpio, we can allocate it */
-	gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
-	if (gpio < (GPIO_PORT_MAX + 1) * 32)
-		if (gpio_request(gpio, label))
-			return -EINVAL;
-
 	return 0;
 }
-EXPORT_SYMBOL(mxc_iomux_setup_pin);
+EXPORT_SYMBOL(mxc_iomux_alloc_pin);
 
 int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
 		const char *label)
@@ -135,7 +126,8 @@
 	int ret = -EINVAL;
 
 	for (i = 0; i < count; i++) {
-		if (mxc_iomux_setup_pin(*p, label))
+		ret = mxc_iomux_alloc_pin(*p, label);
+		if (ret)
 			goto setup_error;
 		p++;
 	}
@@ -150,14 +142,9 @@
 void mxc_iomux_release_pin(const unsigned int pin)
 {
 	unsigned pad = pin & IOMUX_PADNUM_MASK;
-	unsigned gpio;
 
 	if (pad < (PIN_MAX + 1))
 		clear_bit(pad, mxc_pin_alloc_map);
-
-	gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
-	if (gpio < (GPIO_PORT_MAX + 1) * 32)
-		gpio_free(gpio);
 }
 EXPORT_SYMBOL(mxc_iomux_release_pin);
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-mx3/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,12 @@
 if ARCH_MX3
 
 config ARCH_MX31
+	select ARCH_HAS_RNGA
 	bool
 
 config ARCH_MX35
 	bool
+	select ARCH_MXC_IOMUX_V3
 
 comment "MX3 platforms:"
 
@@ -34,10 +36,17 @@
 	  Include support for Phytec pcm037 platform. This includes
 	  specific configurations for the board and its peripherals.
 
+config MACH_PCM037_EET
+	bool "Support pcm037 EET board extensions"
+	depends on MACH_PCM037
+	help
+	  Add support for PCM037 EET baseboard extensions. If you are using the
+	  OLED display with EET, use "video=mx3fb:CMEL-OLED" kernel
+	  command-line parameter.
+
 config MACH_MX31LITE
 	bool "Support MX31 LITEKIT (LogicPD)"
 	select ARCH_MX31
-	default n
 	help
 	  Include support for MX31 LITEKIT platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -45,7 +54,6 @@
 config MACH_MX31_3DS
 	bool "Support MX31PDK (3DS)"
 	select ARCH_MX31
-	default n
 	help
 	  Include support for MX31PDK (3DS) platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -53,17 +61,43 @@
 config MACH_MX31MOBOARD
 	bool "Support mx31moboard platforms (EPFL Mobots group)"
 	select ARCH_MX31
-	default n
 	help
 	  Include support for mx31moboard platform. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_MX31LILLY
+	bool "Support MX31 LILLY-1131 platforms (INCO startec)"
+	select ARCH_MX31
+	help
+	  Include support for mx31 based LILLY1131 modules. This includes
+	  specific configurations for the board and its peripherals.
+
 config MACH_QONG
 	bool "Support Dave/DENX QongEVB-LITE platform"
 	select ARCH_MX31
-	default n
 	help
 	  Include support for Dave/DENX QongEVB-LITE platform. This includes
 	  specific configurations for the board and its peripherals.
 
+config MACH_PCM043
+	bool "Support Phytec pcm043 (i.MX35) platforms"
+	select ARCH_MX35
+	help
+	  Include support for Phytec pcm043 platform. This includes
+	  specific configurations for the board and its peripherals.
+
+config MACH_ARMADILLO5X0
+	bool "Support Atmark Armadillo-500 Development Base Board"
+	select ARCH_MX31
+	help
+	  Include support for Atmark Armadillo-500 platform. This includes
+	  specific configurations for the board and its peripherals.
+
+config MACH_MX35_3DS
+	bool "Support MX35PDK platform"
+	select ARCH_MX35
+	default n
+	help
+	  Include support for MX35PDK platform. This includes specific
+	  configurations for the board and its peripherals.
 endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-mx3/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,9 +8,14 @@
 obj-$(CONFIG_ARCH_MX31)		+= clock.o iomux.o
 obj-$(CONFIG_ARCH_MX35)		+= clock-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)	+= mx31ads.o
+obj-$(CONFIG_MACH_MX31LILLY)	+= mx31lilly.o mx31lilly-db.o
 obj-$(CONFIG_MACH_MX31LITE)	+= mx31lite.o
 obj-$(CONFIG_MACH_PCM037)	+= pcm037.o
+obj-$(CONFIG_MACH_PCM037_EET)	+= pcm037_eet.o
 obj-$(CONFIG_MACH_MX31_3DS)	+= mx31pdk.o
 obj-$(CONFIG_MACH_MX31MOBOARD)	+= mx31moboard.o mx31moboard-devboard.o \
 				   mx31moboard-marxbot.o
 obj-$(CONFIG_MACH_QONG)		+= qong.o
+obj-$(CONFIG_MACH_PCM043)	+= pcm043.o
+obj-$(CONFIG_MACH_ARMADILLO5X0) += armadillo5x0.o
+obj-$(CONFIG_MACH_MX35_3DS)	+= mx35pdk.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mm.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mm.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,8 +72,17 @@
  * system startup to create static physical to virtual memory mappings
  * for the IO modules.
  */
-void __init mxc_map_io(void)
+void __init mx31_map_io(void)
 {
+	mxc_set_cpu_type(MXC_CPU_MX31);
+
+	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+}
+
+void __init mx35_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX35);
+
 	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31ads.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31ads.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31ads.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31ads.c	2009-09-09 18:13:59.000000000 -0400
@@ -187,7 +187,7 @@
 	/*
 	 * Configure INT line as GPIO input
 	 */
-	mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO), "expio");
+	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO), "expio");
 
 	/* disable the interrupt and clear the status */
 	__raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
@@ -511,7 +511,7 @@
  */
 static void __init mx31ads_map_io(void)
 {
-	mxc_map_io();
+	mx31_map_io();
 	iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc));
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31lilly.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31lilly.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31lilly.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31lilly.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,155 @@
+/*
+ *  LILLY-1131 module support
+ *
+ *    Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ *  based on code for other MX31 boards,
+ *
+ *    Copyright 2005-2007 Freescale Semiconductor
+ *    Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ *    Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/smsc911x.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx3.h>
+#include <mach/board-mx31lilly.h>
+
+#include "devices.h"
+
+/*
+ * This file contains module-specific initialization routines for LILLY-1131.
+ * Initialization of peripherals found on the baseboard is implemented in the
+ * appropriate baseboard support code.
+ */
+
+/* SMSC ethernet support */
+
+static struct resource smsc91x_resources[] = {
+	{
+		.start	= CS4_BASE_ADDR,
+		.end	= CS4_BASE_ADDR + 0xffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
+	}
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_32BIT |
+			  SMSC911X_SAVE_MAC_ADDRESS |
+			  SMSC911X_FORCE_INTERNAL_PHY,
+};
+
+static struct platform_device smsc91x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc91x_resources),
+	.resource	= smsc91x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_config,
+	}
+};
+
+/* NOR flash */
+static struct physmap_flash_data nor_flash_data = {
+	.width  = 2,
+};
+
+static struct resource nor_flash_resource = {
+	.start	= 0xa0000000,
+	.end	= 0xa1ffffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device physmap_flash_device = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &nor_flash_data,
+	},
+	.resource = &nor_flash_resource,
+	.num_resources = 1,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&smsc91x_device,
+	&physmap_flash_device,
+	&mxc_i2c_device1,
+};
+
+static int mx31lilly_baseboard;
+core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
+
+static void __init mx31lilly_board_init(void)
+{
+	switch (mx31lilly_baseboard) {
+	case MX31LILLY_NOBOARD:
+		break;
+	case MX31LILLY_DB:
+		mx31lilly_db_init();
+		break;
+	default:
+		printk(KERN_ERR "Illegal mx31lilly_baseboard type %d\n",
+			mx31lilly_baseboard);
+	}
+
+	mxc_iomux_alloc_pin(MX31_PIN_CS4__CS4, "Ethernet CS");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_MOSI__SCL, "I2C SCL");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_MISO__SDA, "I2C SDA");
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init mx31lilly_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer mx31lilly_timer = {
+	.init	= mx31lilly_timer_init,
+};
+
+MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
+	.phys_io	= AIPS1_BASE_ADDR,
+	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params	= PHYS_OFFSET + 0x100,
+	.map_io		= mx31_map_io,
+	.init_irq	= mxc_init_irq,
+	.init_machine	= mx31lilly_board_init,
+	.timer		= &mx31lilly_timer,
+MACHINE_END
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31lilly-db.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31lilly-db.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31lilly-db.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31lilly-db.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,216 @@
+/*
+ *  LILLY-1131 development board support
+ *
+ *    Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ *  based on code for other MX31 boards,
+ *
+ *    Copyright 2005-2007 Freescale Semiconductor
+ *    Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ *    Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include <mach/board-mx31lilly.h>
+#include <mach/mmc.h>
+#include <mach/mx3fb.h>
+#include <mach/ipu.h>
+
+#include "devices.h"
+
+/*
+ * This file contains board-specific initialization routines for the
+ * LILLY-1131 development board. If you design an own baseboard for the
+ * module, use this file as base for support code.
+ */
+
+static unsigned int lilly_db_board_pins[] __initdata = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+	MX31_PIN_CTS2__CTS2,
+	MX31_PIN_RTS2__RTS2,
+	MX31_PIN_TXD2__TXD2,
+	MX31_PIN_RXD2__RXD2,
+	MX31_PIN_CSPI3_MOSI__RXD3,
+	MX31_PIN_CSPI3_MISO__TXD3,
+	MX31_PIN_CSPI3_SCLK__RTS3,
+	MX31_PIN_CSPI3_SPI_RDY__CTS3,
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
+	MX31_PIN_LD0__LD0,
+	MX31_PIN_LD1__LD1,
+	MX31_PIN_LD2__LD2,
+	MX31_PIN_LD3__LD3,
+	MX31_PIN_LD4__LD4,
+	MX31_PIN_LD5__LD5,
+	MX31_PIN_LD6__LD6,
+	MX31_PIN_LD7__LD7,
+	MX31_PIN_LD8__LD8,
+	MX31_PIN_LD9__LD9,
+	MX31_PIN_LD10__LD10,
+	MX31_PIN_LD11__LD11,
+	MX31_PIN_LD12__LD12,
+	MX31_PIN_LD13__LD13,
+	MX31_PIN_LD14__LD14,
+	MX31_PIN_LD15__LD15,
+	MX31_PIN_LD16__LD16,
+	MX31_PIN_LD17__LD17,
+	MX31_PIN_VSYNC3__VSYNC3,
+	MX31_PIN_HSYNC__HSYNC,
+	MX31_PIN_FPSHIFT__FPSHIFT,
+	MX31_PIN_DRDY0__DRDY0,
+	MX31_PIN_CONTRAST__CONTRAST,
+};
+
+/* UART */
+static struct imxuart_platform_data uart_pdata __initdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* MMC support */
+
+static int mxc_mmc1_get_ro(struct device *dev)
+{
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_LCS0));
+}
+
+static int gpio_det, gpio_wp;
+
+static int mxc_mmc1_init(struct device *dev,
+			 irq_handler_t detect_irq, void *data)
+{
+	int ret;
+
+	gpio_det = IOMUX_TO_GPIO(MX31_PIN_GPIO1_1);
+	gpio_wp = IOMUX_TO_GPIO(MX31_PIN_LCS0);
+
+	ret = gpio_request(gpio_det, "MMC detect");
+	if (ret)
+		return ret;
+
+	ret = gpio_request(gpio_wp, "MMC w/p");
+	if (ret)
+		goto exit_free_det;
+
+	gpio_direction_input(gpio_det);
+	gpio_direction_input(gpio_wp);
+
+	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), detect_irq,
+			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  "MMC detect", data);
+	if (ret)
+		goto exit_free_wp;
+
+	return 0;
+
+exit_free_wp:
+	gpio_free(gpio_wp);
+
+exit_free_det:
+	gpio_free(gpio_det);
+
+	return ret;
+}
+
+static void mxc_mmc1_exit(struct device *dev, void *data)
+{
+	gpio_free(gpio_det);
+	gpio_free(gpio_wp);
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), data);
+}
+
+static struct imxmmc_platform_data mmc_pdata = {
+	.get_ro	= mxc_mmc1_get_ro,
+	.init	= mxc_mmc1_init,
+	.exit	= mxc_mmc1_exit,
+};
+
+/* Framebuffer support */
+static struct ipu_platform_data ipu_data __initdata = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static const struct fb_videomode fb_modedb = {
+	/* 640x480 TFT panel (IPS-056T) */
+	.name	   	= "CRT-VGA",
+	.refresh	= 64,
+	.xres		= 640,
+	.yres		= 480,
+	.pixclock	= 30000,
+	.left_margin	= 200,
+	.right_margin	= 2,
+	.upper_margin	= 2,
+	.lower_margin	= 2,
+	.hsync_len	= 3,
+	.vsync_len	= 1,
+	.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
+	.vmode		= FB_VMODE_NONINTERLACED,
+	.flag		= 0,
+};
+
+static struct mx3fb_platform_data fb_pdata __initdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "CRT-VGA",
+	.mode		= &fb_modedb,
+	.num_modes	= 1,
+};
+
+#define LCD_VCC_EN_GPIO	 (7)
+
+static void __init mx31lilly_init_fb(void)
+{
+	if (gpio_request(LCD_VCC_EN_GPIO, "LCD enable") != 0) {
+		printk(KERN_WARNING "unable to request LCD_VCC_EN pin.\n");
+		return;
+	}
+
+	mxc_register_device(&mx3_ipu, &ipu_data);
+	mxc_register_device(&mx3_fb, &fb_pdata);
+	gpio_direction_output(LCD_VCC_EN_GPIO, 1);
+}
+
+void __init mx31lilly_db_init(void)
+{
+	mxc_iomux_setup_multiple_pins(lilly_db_board_pins,
+					ARRAY_SIZE(lilly_db_board_pins),
+					"development board pins");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+	mxc_register_device(&mxc_uart_device2, &uart_pdata);
+	mxc_register_device(&mxcsdhc_device0, &mmc_pdata);
+	mx31lilly_init_fb();
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31lite.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31lite.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31lite.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31lite.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,9 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/memory.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -32,11 +35,64 @@
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <mach/board-mx31lite.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include <mach/irqs.h>
+#include <mach/mxc_nand.h>
+#include "devices.h"
 
 /*
  * This file contains the board-specific initialization routines.
  */
 
+static unsigned int mx31lite_pins[] = {
+	/* UART1 */
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+	/* LAN9117 IRQ pin */
+	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_GPIO),
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct mxc_nand_platform_data mx31lite_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT,
+};
+
+static struct resource smsc911x_resources[] = {
+	[0] = {
+		.start		= CS4_BASE_ADDR,
+		.end		= CS4_BASE_ADDR + 0x100,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= IOMUX_TO_IRQ(MX31_PIN_SFS6),
+		.end		= IOMUX_TO_IRQ(MX31_PIN_SFS6),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_config,
+	},
+};
+
 /*
  * This structure defines the MX31 memory map.
  */
@@ -59,7 +115,7 @@
  */
 void __init mx31lite_map_io(void)
 {
-	mxc_map_io();
+	mx31_map_io();
 	iotable_init(mx31lite_io_desc, ARRAY_SIZE(mx31lite_io_desc));
 }
 
@@ -68,6 +124,22 @@
  */
 static void __init mxc_board_init(void)
 {
+	int ret;
+
+	mxc_iomux_setup_multiple_pins(mx31lite_pins, ARRAY_SIZE(mx31lite_pins),
+				      "mx31lite");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_nand_device, &mx31lite_nand_board_info);
+
+	/* SMSC9117 IRQ pin */
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
+	if (ret)
+		pr_warning("could not get LAN irq gpio\n");
+	else {
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+		platform_device_register(&smsc911x_device);
+	}
 }
 
 static void __init mx31lite_timer_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31moboard.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31moboard.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31moboard.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31moboard.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,26 +16,47 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
-
-#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/memory.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
-#include <linux/memory.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <mach/board-mx31moboard.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
-#include <mach/board-mx31moboard.h>
+#include <mach/i2c.h>
+#include <mach/mmc.h>
 
 #include "devices.h"
 
+static unsigned int moboard_pins[] = {
+	/* UART0 */
+	MX31_PIN_CTS1__CTS1, MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1, MX31_PIN_RXD1__RXD1,
+	/* UART4 */
+	MX31_PIN_PC_RST__CTS5, MX31_PIN_PC_VS2__RTS5,
+	MX31_PIN_PC_BVD2__TXD5, MX31_PIN_PC_BVD1__RXD5,
+	/* I2C0 */
+	MX31_PIN_I2C_DAT__I2C1_SDA, MX31_PIN_I2C_CLK__I2C1_SCL,
+	/* I2C1 */
+	MX31_PIN_DCD_DTE1__I2C2_SDA, MX31_PIN_RI_DTE1__I2C2_SCL,
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA3__SD1_DATA3, MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1, MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK, MX31_PIN_SD1_CMD__SD1_CMD,
+	MX31_PIN_ATA_CS0__GPIO3_26, MX31_PIN_ATA_CS1__GPIO3_27,
+};
+
 static struct physmap_flash_data mx31moboard_flash_data = {
 	.width  	= 2,
 };
@@ -60,17 +81,69 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static struct platform_device *devices[] __initdata = {
-	&mx31moboard_flash,
+static struct imxi2c_platform_data moboard_i2c0_pdata = {
+	.bitrate = 400000,
 };
 
-static int mxc_uart0_pins[] = {
-	MX31_PIN_CTS1__CTS1, MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1, MX31_PIN_RXD1__RXD1,
+static struct imxi2c_platform_data moboard_i2c1_pdata = {
+	.bitrate = 100000,
 };
-static int mxc_uart4_pins[] = {
-	MX31_PIN_PC_RST__CTS5, MX31_PIN_PC_VS2__RTS5,
-	MX31_PIN_PC_BVD2__TXD5, MX31_PIN_PC_BVD1__RXD5,
+
+#define SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_ATA_CS0)
+#define SDHC1_WP IOMUX_TO_GPIO(MX31_PIN_ATA_CS1)
+
+static int moboard_sdhc1_get_ro(struct device *dev)
+{
+	return !gpio_get_value(SDHC1_WP);
+}
+
+static int moboard_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
+		void *data)
+{
+	int ret;
+
+	ret = gpio_request(SDHC1_CD, "sdhc-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(SDHC1_CD);
+
+	ret = gpio_request(SDHC1_WP, "sdhc-wp");
+	if (ret)
+		goto err_gpio_free;
+	gpio_direction_input(SDHC1_WP);
+
+	ret = request_irq(gpio_to_irq(SDHC1_CD), detect_irq,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"sdhc1-card-detect", data);
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+	gpio_free(SDHC1_WP);
+err_gpio_free:
+	gpio_free(SDHC1_CD);
+
+	return ret;
+}
+
+static void moboard_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(SDHC1_CD), data);
+	gpio_free(SDHC1_WP);
+	gpio_free(SDHC1_CD);
+}
+
+static struct imxmmc_platform_data sdhc1_pdata = {
+	.get_ro	= moboard_sdhc1_get_ro,
+	.init	= moboard_sdhc1_init,
+	.exit	= moboard_sdhc1_exit,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&mx31moboard_flash,
 };
 
 static int mx31moboard_baseboard;
@@ -81,14 +154,19 @@
  */
 static void __init mxc_board_init(void)
 {
+	mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
+		"moboard");
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
-	mxc_iomux_setup_multiple_pins(mxc_uart0_pins, ARRAY_SIZE(mxc_uart0_pins), "uart0");
 	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-
-	mxc_iomux_setup_multiple_pins(mxc_uart4_pins, ARRAY_SIZE(mxc_uart4_pins), "uart4");
 	mxc_register_device(&mxc_uart_device4, &uart_pdata);
 
+	mxc_register_device(&mxc_i2c_device0, &moboard_i2c0_pdata);
+	mxc_register_device(&mxc_i2c_device1, &moboard_i2c1_pdata);
+
+	mxc_register_device(&mxcsdhc_device0, &sdhc1_pdata);
+
 	switch (mx31moboard_baseboard) {
 	case MX31NOBOARD:
 		break;
@@ -99,7 +177,8 @@
 		mx31moboard_marxbot_init();
 		break;
 	default:
-		printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n", mx31moboard_baseboard);
+		printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n",
+			mx31moboard_baseboard);
 	}
 }
 
@@ -117,7 +196,7 @@
 	.phys_io	= AIPS1_BASE_ADDR,
 	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mxc_map_io,
+	.map_io         = mx31_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = mxc_board_init,
 	.timer          = &mx31moboard_timer,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,33 +16,142 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/types.h>
+#include <linux/fsl_devices.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
-
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/types.h>
 
-#include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
+#include <mach/hardware.h>
+#include <mach/mmc.h>
 
 #include "devices.h"
 
+static unsigned int devboard_pins[] = {
+	/* UART1 */
+	MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2,
+	MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2,
+	/* SDHC2 */
+	MX31_PIN_PC_PWRON__SD2_DATA3, MX31_PIN_PC_VS1__SD2_DATA2,
+	MX31_PIN_PC_READY__SD2_DATA1, MX31_PIN_PC_WAIT_B__SD2_DATA0,
+	MX31_PIN_PC_CD2_B__SD2_CLK, MX31_PIN_PC_CD1_B__SD2_CMD,
+	MX31_PIN_ATA_DIOR__GPIO3_28, MX31_PIN_ATA_DIOW__GPIO3_29,
+	/* USB OTG */
+	MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
+	MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
+	MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
+	MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
+	MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
+	MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
+	MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
+	MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
+	MX31_PIN_USBOTG_CLK__USBOTG_CLK, MX31_PIN_USBOTG_DIR__USBOTG_DIR,
+	MX31_PIN_USBOTG_NXT__USBOTG_NXT, MX31_PIN_USBOTG_STP__USBOTG_STP,
+	MX31_PIN_USB_OC__GPIO1_30,
+};
+
 static struct imxuart_platform_data uart_pdata = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static int mxc_uart1_pins[] = {
-	MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2,
-	MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2,
+#define SDHC2_CD IOMUX_TO_GPIO(MX31_PIN_ATA_DIOR)
+#define SDHC2_WP IOMUX_TO_GPIO(MX31_PIN_ATA_DIOW)
+
+static int devboard_sdhc2_get_ro(struct device *dev)
+{
+	return !gpio_get_value(SDHC2_WP);
+}
+
+static int devboard_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
+		void *data)
+{
+	int ret;
+
+	ret = gpio_request(SDHC2_CD, "sdhc-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(SDHC2_CD);
+
+	ret = gpio_request(SDHC2_WP, "sdhc-wp");
+	if (ret)
+		goto err_gpio_free;
+	gpio_direction_input(SDHC2_WP);
+
+	ret = request_irq(gpio_to_irq(SDHC2_CD), detect_irq,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"sdhc2-card-detect", data);
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+	gpio_free(SDHC2_WP);
+err_gpio_free:
+	gpio_free(SDHC2_CD);
+
+	return ret;
+}
+
+static void devboard_sdhc2_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(SDHC2_CD), data);
+	gpio_free(SDHC2_WP);
+	gpio_free(SDHC2_CD);
+}
+
+static struct imxmmc_platform_data sdhc2_pdata = {
+	.get_ro	= devboard_sdhc2_get_ro,
+	.init	= devboard_sdhc2_init,
+	.exit	= devboard_sdhc2_exit,
 };
 
+static struct fsl_usb2_platform_data usb_pdata = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_ULPI,
+};
+
+#define OTG_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST)
+#define OTG_EN_B IOMUX_TO_GPIO(MX31_PIN_USB_OC)
+
+static void devboard_usbotg_init(void)
+{
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, OTG_PAD_CFG);
+
+	gpio_request(OTG_EN_B, "usb-udc-en");
+	gpio_direction_output(OTG_EN_B, 0);
+}
+
 /*
  * system init for baseboard usage. Will be called by mx31moboard init.
  */
 void __init mx31moboard_devboard_init(void)
 {
 	printk(KERN_INFO "Initializing mx31devboard peripherals\n");
-	mxc_iomux_setup_multiple_pins(mxc_uart1_pins, ARRAY_SIZE(mxc_uart1_pins), "uart1");
+
+	mxc_iomux_setup_multiple_pins(devboard_pins, ARRAY_SIZE(devboard_pins),
+		"devboard");
+
 	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+
+	mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata);
+
+	devboard_usbotg_init();
+	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,22 +16,144 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/types.h>
+#include <linux/fsl_devices.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
-
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/types.h>
 
-#include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
+#include <mach/mmc.h>
 
 #include "devices.h"
 
+static unsigned int marxbot_pins[] = {
+	/* SDHC2 */
+	MX31_PIN_PC_PWRON__SD2_DATA3, MX31_PIN_PC_VS1__SD2_DATA2,
+	MX31_PIN_PC_READY__SD2_DATA1, MX31_PIN_PC_WAIT_B__SD2_DATA0,
+	MX31_PIN_PC_CD2_B__SD2_CLK, MX31_PIN_PC_CD1_B__SD2_CMD,
+	MX31_PIN_ATA_DIOR__GPIO3_28, MX31_PIN_ATA_DIOW__GPIO3_29,
+	/* CSI */
+	MX31_PIN_CSI_D4__CSI_D4, MX31_PIN_CSI_D5__CSI_D5,
+	MX31_PIN_CSI_D6__CSI_D6, MX31_PIN_CSI_D7__CSI_D7,
+	MX31_PIN_CSI_D8__CSI_D8, MX31_PIN_CSI_D9__CSI_D9,
+	MX31_PIN_CSI_D10__CSI_D10, MX31_PIN_CSI_D11__CSI_D11,
+	MX31_PIN_CSI_D12__CSI_D12, MX31_PIN_CSI_D13__CSI_D13,
+	MX31_PIN_CSI_D14__CSI_D14, MX31_PIN_CSI_D15__CSI_D15,
+	MX31_PIN_CSI_HSYNC__CSI_HSYNC, MX31_PIN_CSI_MCLK__CSI_MCLK,
+	MX31_PIN_CSI_PIXCLK__CSI_PIXCLK, MX31_PIN_CSI_VSYNC__CSI_VSYNC,
+	MX31_PIN_GPIO3_0__GPIO3_0, MX31_PIN_GPIO3_1__GPIO3_1,
+	MX31_PIN_TXD2__GPIO1_28,
+	/* USB OTG */
+	MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
+	MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
+	MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
+	MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
+	MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
+	MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
+	MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
+	MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
+	MX31_PIN_USBOTG_CLK__USBOTG_CLK, MX31_PIN_USBOTG_DIR__USBOTG_DIR,
+	MX31_PIN_USBOTG_NXT__USBOTG_NXT, MX31_PIN_USBOTG_STP__USBOTG_STP,
+	MX31_PIN_USB_OC__GPIO1_30,
+};
+
+#define SDHC2_CD IOMUX_TO_GPIO(MX31_PIN_ATA_DIOR)
+#define SDHC2_WP IOMUX_TO_GPIO(MX31_PIN_ATA_DIOW)
+
+static int marxbot_sdhc2_get_ro(struct device *dev)
+{
+	return !gpio_get_value(SDHC2_WP);
+}
+
+static int marxbot_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
+		void *data)
+{
+	int ret;
+
+	ret = gpio_request(SDHC2_CD, "sdhc-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(SDHC2_CD);
+
+	ret = gpio_request(SDHC2_WP, "sdhc-wp");
+	if (ret)
+		goto err_gpio_free;
+	gpio_direction_input(SDHC2_WP);
+
+	ret = request_irq(gpio_to_irq(SDHC2_CD), detect_irq,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"sdhc2-card-detect", data);
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+	gpio_free(SDHC2_WP);
+err_gpio_free:
+	gpio_free(SDHC2_CD);
+
+	return ret;
+}
+
+static void marxbot_sdhc2_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(SDHC2_CD), data);
+	gpio_free(SDHC2_WP);
+	gpio_free(SDHC2_CD);
+}
+
+static struct imxmmc_platform_data sdhc2_pdata = {
+	.get_ro	= marxbot_sdhc2_get_ro,
+	.init	= marxbot_sdhc2_init,
+	.exit	= marxbot_sdhc2_exit,
+};
+
+static struct fsl_usb2_platform_data usb_pdata = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_ULPI,
+};
+
+#define OTG_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST)
+#define OTG_EN_B IOMUX_TO_GPIO(MX31_PIN_USB_OC)
+
+static void marxbot_usbotg_init(void)
+{
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, OTG_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, OTG_PAD_CFG);
+
+	gpio_request(OTG_EN_B, "usb-udc-en");
+	gpio_direction_output(OTG_EN_B, 0);
+}
+
 /*
  * system init for baseboard usage. Will be called by mx31moboard init.
  */
 void __init mx31moboard_marxbot_init(void)
 {
 	printk(KERN_INFO "Initializing mx31marxbot peripherals\n");
+
+	mxc_iomux_setup_multiple_pins(marxbot_pins, ARRAY_SIZE(marxbot_pins),
+		"marxbot");
+
+	mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata);
+
+	marxbot_usbotg_init();
+	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31pdk.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31pdk.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx31pdk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx31pdk.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,9 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+#include <linux/platform_device.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -41,21 +44,192 @@
  * @ingroup System
  */
 
+static int mx31pdk_pins[] = {
+	/* UART1 */
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+	IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
+};
+
 static struct imxuart_platform_data uart_pdata = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static int uart_pins[] = {
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1
+/*
+ * Support for the SMSC9217 on the Debug board.
+ */
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
 };
 
-static inline void mxc_init_imx_uart(void)
+static struct resource smsc911x_resources[] = {
+	{
+		.start		= LAN9217_BASE_ADDR,
+		.end		= LAN9217_BASE_ADDR + 0xff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= EXPIO_INT_ENET,
+		.end		= EXPIO_INT_ENET,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_config,
+	},
+};
+
+/*
+ * Routines for the CPLD on the debug board. It contains a CPLD handling
+ * LEDs, switches, interrupts for Ethernet.
+ */
+
+static void mx31pdk_expio_irq_handler(uint32_t irq, struct irq_desc *desc)
 {
-	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	uint32_t imr_val;
+	uint32_t int_valid;
+	uint32_t expio_irq;
+
+	imr_val = __raw_readw(CPLD_INT_MASK_REG);
+	int_valid = __raw_readw(CPLD_INT_STATUS_REG) & ~imr_val;
+
+	expio_irq = MXC_EXP_IO_BASE;
+	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
+		if ((int_valid & 1) == 0)
+			continue;
+		generic_handle_irq(expio_irq);
+	}
+}
+
+/*
+ * Disable an expio pin's interrupt by setting the bit in the imr.
+ * @param irq           an expio virtual irq number
+ */
+static void expio_mask_irq(uint32_t irq)
+{
+	uint16_t reg;
+	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
+
+	/* mask the interrupt */
+	reg = __raw_readw(CPLD_INT_MASK_REG);
+	reg |= 1 << expio;
+	__raw_writew(reg, CPLD_INT_MASK_REG);
+}
+
+/*
+ * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
+ * @param irq           an expanded io virtual irq number
+ */
+static void expio_ack_irq(uint32_t irq)
+{
+	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
+
+	/* clear the interrupt status */
+	__raw_writew(1 << expio, CPLD_INT_RESET_REG);
+	__raw_writew(0, CPLD_INT_RESET_REG);
+	/* mask the interrupt */
+	expio_mask_irq(irq);
+}
+
+/*
+ * Enable a expio pin's interrupt by clearing the bit in the imr.
+ * @param irq           a expio virtual irq number
+ */
+static void expio_unmask_irq(uint32_t irq)
+{
+	uint16_t reg;
+	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
+
+	/* unmask the interrupt */
+	reg = __raw_readw(CPLD_INT_MASK_REG);
+	reg &= ~(1 << expio);
+	__raw_writew(reg, CPLD_INT_MASK_REG);
+}
+
+static struct irq_chip expio_irq_chip = {
+	.ack = expio_ack_irq,
+	.mask = expio_mask_irq,
+	.unmask = expio_unmask_irq,
+};
+
+static int __init mx31pdk_init_expio(void)
+{
+	int i;
+	int ret;
+
+	/* Check if there's a debug board connected */
+	if ((__raw_readw(CPLD_MAGIC_NUMBER1_REG) != 0xAAAA) ||
+	    (__raw_readw(CPLD_MAGIC_NUMBER2_REG) != 0x5555) ||
+	    (__raw_readw(CPLD_MAGIC_NUMBER3_REG) != 0xCAFE)) {
+		/* No Debug board found */
+		return -ENODEV;
+	}
+
+	pr_info("i.MX31PDK Debug board detected, rev = 0x%04X\n",
+		__raw_readw(CPLD_CODE_VER_REG));
+
+	/*
+	 * Configure INT line as GPIO input
+	 */
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1), "sms9217-irq");
+	if (ret)
+		pr_warning("could not get LAN irq gpio\n");
+	else
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+
+	/* Disable the interrupts and clear the status */
+	__raw_writew(0, CPLD_INT_MASK_REG);
+	__raw_writew(0xFFFF, CPLD_INT_RESET_REG);
+	__raw_writew(0, CPLD_INT_RESET_REG);
+	__raw_writew(0x1F, CPLD_INT_MASK_REG);
+	for (i = MXC_EXP_IO_BASE;
+	     i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
+	     i++) {
+		set_irq_chip(i, &expio_irq_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+	set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_LOW);
+	set_irq_chained_handler(EXPIO_PARENT_INT, mx31pdk_expio_irq_handler);
+
+	return 0;
+}
+
+/*
+ * This structure defines the MX31 memory map.
+ */
+static struct map_desc mx31pdk_io_desc[] __initdata = {
+	{
+		.virtual = SPBA0_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
+		.length = SPBA0_SIZE,
+		.type = MT_DEVICE_NONSHARED,
+	}, {
+		.virtual = CS5_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(CS5_BASE_ADDR),
+		.length = CS5_SIZE,
+		.type = MT_DEVICE,
+	},
+};
+
+/*
+ * Set up static virtual mappings.
+ */
+static void __init mx31pdk_map_io(void)
+{
+	mx31_map_io();
+	iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc));
 }
 
 /*!
@@ -63,7 +237,13 @@
  */
 static void __init mxc_board_init(void)
 {
-	mxc_init_imx_uart();
+	mxc_iomux_setup_multiple_pins(mx31pdk_pins, ARRAY_SIZE(mx31pdk_pins),
+				      "mx31pdk");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+
+	if (!mx31pdk_init_expio())
+		platform_device_register(&smsc911x_device);
 }
 
 static void __init mx31pdk_timer_init(void)
@@ -84,7 +264,7 @@
 	.phys_io	= AIPS1_BASE_ADDR,
 	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mxc_map_io,
+	.map_io         = mx31pdk_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = mxc_board_init,
 	.timer          = &mx31pdk_timer,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx35pdk.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx35pdk.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/mx35pdk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/mx35pdk.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx35.h>
+
+#include "devices.h"
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static struct pad_desc mx35pdk_pads[] = {
+	/* UART1 */
+	MX35_PAD_CTS1__UART1_CTS,
+	MX35_PAD_RTS1__UART1_RTS,
+	MX35_PAD_TXD1__UART1_TXD_MUX,
+	MX35_PAD_RXD1__UART1_RXD_MUX,
+	/* FEC */
+	MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
+	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX35_PAD_FEC_COL__FEC_COL,
+	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
+	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
+	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX35_PAD_FEC_MDC__FEC_MDC,
+	MX35_PAD_FEC_MDIO__FEC_MDIO,
+	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
+	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
+	MX35_PAD_FEC_CRS__FEC_CRS,
+	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
+	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
+	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
+	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
+	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
+	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+}
+
+static void __init mx35pdk_timer_init(void)
+{
+	mx35_clocks_init();
+}
+
+struct sys_timer mx35pdk_timer = {
+	.init	= mx35pdk_timer_init,
+};
+
+MACHINE_START(MX35_3DS, "Freescale MX35PDK")
+	/* Maintainer: Freescale Semiconductor, Inc */
+	.phys_io	= AIPS1_BASE_ADDR,
+	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = mx35_map_io,
+	.init_irq       = mxc_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &mx35pdk_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm037.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm037.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm037.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm037.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
-
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/plat-ram.h>
@@ -28,23 +28,148 @@
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/irq.h>
+#include <linux/fsl_devices.h>
+
+#include <media/soc_camera.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <mach/board-pcm037.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/i2c.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
-#include <mach/board-pcm037.h>
-#include <mach/mxc_nand.h>
+#include <mach/ipu.h>
 #include <mach/mmc.h>
-#ifdef CONFIG_I2C_IMX
-#include <mach/i2c.h>
-#endif
+#include <mach/mx3_camera.h>
+#include <mach/mx3fb.h>
+#include <mach/mxc_nand.h>
 
 #include "devices.h"
+#include "pcm037.h"
+
+static enum pcm037_board_variant pcm037_instance = PCM037_PCM970;
+
+static int __init pcm037_variant_setup(char *str)
+{
+	if (!strcmp("eet", str))
+		pcm037_instance = PCM037_EET;
+	else if (strcmp("pcm970", str))
+		pr_warning("Unknown pcm037 baseboard variant %s\n", str);
+
+	return 1;
+}
+
+/* Supported values: "pcm970" (default) and "eet" */
+__setup("pcm037_variant=", pcm037_variant_setup);
+
+enum pcm037_board_variant pcm037_variant(void)
+{
+	return pcm037_instance;
+}
+
+/* UART1 with RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_handshake_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+};
+
+/* UART1 without RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_pins[] = {
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+};
+
+static unsigned int pcm037_pins[] = {
+	/* I2C */
+	MX31_PIN_CSPI2_MOSI__SCL,
+	MX31_PIN_CSPI2_MISO__SDA,
+	MX31_PIN_CSPI2_SS2__I2C3_SDA,
+	MX31_PIN_CSPI2_SCLK__I2C3_SCL,
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
+	IOMUX_MODE(MX31_PIN_SCK6, IOMUX_CONFIG_GPIO), /* card detect */
+	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_GPIO), /* write protect */
+	/* SPI1 */
+	MX31_PIN_CSPI1_MOSI__MOSI,
+	MX31_PIN_CSPI1_MISO__MISO,
+	MX31_PIN_CSPI1_SCLK__SCLK,
+	MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
+	MX31_PIN_CSPI1_SS0__SS0,
+	MX31_PIN_CSPI1_SS1__SS1,
+	MX31_PIN_CSPI1_SS2__SS2,
+	/* UART2 */
+	MX31_PIN_TXD2__TXD2,
+	MX31_PIN_RXD2__RXD2,
+	MX31_PIN_CTS2__CTS2,
+	MX31_PIN_RTS2__RTS2,
+	/* UART3 */
+	MX31_PIN_CSPI3_MOSI__RXD3,
+	MX31_PIN_CSPI3_MISO__TXD3,
+	MX31_PIN_CSPI3_SCLK__RTS3,
+	MX31_PIN_CSPI3_SPI_RDY__CTS3,
+	/* LAN9217 irq pin */
+	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO),
+	/* Onewire */
+	MX31_PIN_BATT_LINE__OWIRE,
+	/* Framebuffer */
+	MX31_PIN_LD0__LD0,
+	MX31_PIN_LD1__LD1,
+	MX31_PIN_LD2__LD2,
+	MX31_PIN_LD3__LD3,
+	MX31_PIN_LD4__LD4,
+	MX31_PIN_LD5__LD5,
+	MX31_PIN_LD6__LD6,
+	MX31_PIN_LD7__LD7,
+	MX31_PIN_LD8__LD8,
+	MX31_PIN_LD9__LD9,
+	MX31_PIN_LD10__LD10,
+	MX31_PIN_LD11__LD11,
+	MX31_PIN_LD12__LD12,
+	MX31_PIN_LD13__LD13,
+	MX31_PIN_LD14__LD14,
+	MX31_PIN_LD15__LD15,
+	MX31_PIN_LD16__LD16,
+	MX31_PIN_LD17__LD17,
+	MX31_PIN_VSYNC3__VSYNC3,
+	MX31_PIN_HSYNC__HSYNC,
+	MX31_PIN_FPSHIFT__FPSHIFT,
+	MX31_PIN_DRDY0__DRDY0,
+	MX31_PIN_D3_REV__D3_REV,
+	MX31_PIN_CONTRAST__CONTRAST,
+	MX31_PIN_D3_SPL__D3_SPL,
+	MX31_PIN_D3_CLS__D3_CLS,
+	MX31_PIN_LCS0__GPI03_23,
+	/* CSI */
+	IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO),
+	MX31_PIN_CSI_D6__CSI_D6,
+	MX31_PIN_CSI_D7__CSI_D7,
+	MX31_PIN_CSI_D8__CSI_D8,
+	MX31_PIN_CSI_D9__CSI_D9,
+	MX31_PIN_CSI_D10__CSI_D10,
+	MX31_PIN_CSI_D11__CSI_D11,
+	MX31_PIN_CSI_D12__CSI_D12,
+	MX31_PIN_CSI_D13__CSI_D13,
+	MX31_PIN_CSI_D14__CSI_D14,
+	MX31_PIN_CSI_D15__CSI_D15,
+	MX31_PIN_CSI_HSYNC__CSI_HSYNC,
+	MX31_PIN_CSI_MCLK__CSI_MCLK,
+	MX31_PIN_CSI_PIXCLK__CSI_PIXCLK,
+	MX31_PIN_CSI_VSYNC__CSI_VSYNC,
+};
 
 static struct physmap_flash_data pcm037_flash_data = {
 	.width  = 2,
@@ -56,6 +181,54 @@
 	.flags	= IORESOURCE_MEM,
 };
 
+static int usbotg_pins[] = {
+	MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
+	MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
+	MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
+	MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
+	MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
+	MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
+	MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
+	MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
+	MX31_PIN_USBOTG_CLK__USBOTG_CLK,
+	MX31_PIN_USBOTG_DIR__USBOTG_DIR,
+	MX31_PIN_USBOTG_NXT__USBOTG_NXT,
+	MX31_PIN_USBOTG_STP__USBOTG_STP,
+};
+
+/* USB OTG HS port */
+static int __init gpio_usbotg_hs_activate(void)
+{
+	int ret = mxc_iomux_setup_multiple_pins(usbotg_pins,
+					ARRAY_SIZE(usbotg_pins), "usbotg");
+
+	if (ret < 0) {
+		printk(KERN_ERR "Cannot set up OTG pins\n");
+		return ret;
+	}
+
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
+
+	return 0;
+}
+
+/* OTG config */
+static struct fsl_usb2_platform_data usb_pdata = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_ULPI,
+};
+
 static struct platform_device pcm037_flash = {
 	.name	= "physmap-flash",
 	.id	= 0,
@@ -126,27 +299,12 @@
 	.hw_ecc = 1,
 };
 
-#ifdef CONFIG_I2C_IMX
-static int i2c_1_pins[] = {
-	MX31_PIN_CSPI2_MOSI__SCL,
-	MX31_PIN_CSPI2_MISO__SDA,
-};
-
-static int pcm037_i2c_1_init(struct device *dev)
-{
-	return mxc_iomux_setup_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins),
-			"i2c-1");
-}
-
-static void pcm037_i2c_1_exit(struct device *dev)
-{
-	mxc_iomux_release_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins));
-}
-
 static struct imxi2c_platform_data pcm037_i2c_1_data = {
 	.bitrate = 100000,
-	.init = pcm037_i2c_1_init,
-	.exit = pcm037_i2c_1_exit,
+};
+
+static struct imxi2c_platform_data pcm037_i2c_2_data = {
+	.bitrate = 20000,
 };
 
 static struct at24_platform_data board_eeprom = {
@@ -155,8 +313,29 @@
 	.flags = AT24_FLAG_ADDR16,
 };
 
+static int pcm037_camera_power(struct device *dev, int on)
+{
+	/* disable or enable the camera in X7 or X8 PCM970 connector */
+	gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), !on);
+	return 0;
+}
+
+static struct i2c_board_info pcm037_i2c_2_devices[] = {
+	{
+		I2C_BOARD_INFO("mt9t031", 0x5d),
+	},
+};
+
+static struct soc_camera_link iclink = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.power		= pcm037_camera_power,
+	.board_info	= &pcm037_i2c_2_devices[0],
+	.i2c_adapter_id	= 2,
+	.module_name	= "mt9t031",
+};
+
 static struct i2c_board_info pcm037_i2c_devices[] = {
-       {
+	{
 		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
 		.platform_data = &board_eeprom,
 	}, {
@@ -164,50 +343,176 @@
 		.type = "pcf8563",
 	}
 };
-#endif
 
-static int sdhc1_pins[] = {
-	MX31_PIN_SD1_DATA3__SD1_DATA3,
-	MX31_PIN_SD1_DATA2__SD1_DATA2,
-	MX31_PIN_SD1_DATA1__SD1_DATA1,
-	MX31_PIN_SD1_DATA0__SD1_DATA0,
-	MX31_PIN_SD1_CLK__SD1_CLK,
-	MX31_PIN_SD1_CMD__SD1_CMD,
+static struct platform_device pcm037_camera = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink,
+	},
 };
 
-static int pcm970_sdhc1_init(struct device *dev, irq_handler_t h, void *data)
+/* Not connected by default */
+#ifdef PCM970_SDHC_RW_SWITCH
+static int pcm970_sdhc1_get_ro(struct device *dev)
 {
-	return mxc_iomux_setup_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins),
-				"sdhc-1");
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+}
+#endif
+
+#define SDHC1_GPIO_WP	IOMUX_TO_GPIO(MX31_PIN_SFS6)
+#define SDHC1_GPIO_DET	IOMUX_TO_GPIO(MX31_PIN_SCK6)
+
+static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
+		void *data)
+{
+	int ret;
+
+	ret = gpio_request(SDHC1_GPIO_DET, "sdhc-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(SDHC1_GPIO_DET);
+
+#ifdef PCM970_SDHC_RW_SWITCH
+	ret = gpio_request(SDHC1_GPIO_WP, "sdhc-wp");
+	if (ret)
+		goto err_gpio_free;
+	gpio_direction_input(SDHC1_GPIO_WP);
+#endif
+
+	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), detect_irq,
+			IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+				"sdhc-detect", data);
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+#ifdef PCM970_SDHC_RW_SWITCH
+	gpio_free(SDHC1_GPIO_WP);
+err_gpio_free:
+#endif
+	gpio_free(SDHC1_GPIO_DET);
+
+	return ret;
 }
 
 static void pcm970_sdhc1_exit(struct device *dev, void *data)
 {
-	mxc_iomux_release_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins));
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), data);
+	gpio_free(SDHC1_GPIO_DET);
+	gpio_free(SDHC1_GPIO_WP);
 }
 
-/* No card and rw detection at the moment */
 static struct imxmmc_platform_data sdhc_pdata = {
+#ifdef PCM970_SDHC_RW_SWITCH
+	.get_ro = pcm970_sdhc1_get_ro,
+#endif
 	.init = pcm970_sdhc1_init,
 	.exit = pcm970_sdhc1_exit,
 };
 
+struct mx3_camera_pdata camera_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.flags		= MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10,
+	.mclk_10khz	= 2000,
+};
+
+static int __init pcm037_camera_alloc_dma(const size_t buf_size)
+{
+	dma_addr_t dma_handle;
+	void *buf;
+	int dma;
+
+	if (buf_size < 2 * 1024 * 1024)
+		return -EINVAL;
+
+	buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL);
+	if (!buf) {
+		pr_err("%s: cannot allocate camera buffer-memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, buf_size);
+
+	dma = dma_declare_coherent_memory(&mx3_camera.dev,
+					dma_handle, dma_handle, buf_size,
+					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+
+	/* The way we call dma_declare_coherent_memory only a malloc can fail */
+	return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM;
+}
+
 static struct platform_device *devices[] __initdata = {
 	&pcm037_flash,
-	&pcm037_eth,
 	&pcm037_sram_device,
+	&pcm037_camera,
 };
 
-static int uart0_pins[] = {
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
 };
 
-static int uart2_pins[] = {
-	MX31_PIN_CSPI3_MOSI__RXD3,
-	MX31_PIN_CSPI3_MISO__TXD3
+static const struct fb_videomode fb_modedb[] = {
+	{
+		/* 240x320 @ 60 Hz Sharp */
+		.name		= "Sharp-LQ035Q7DH06-QVGA",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
+				  FB_SYNC_CLK_INVERT | FB_SYNC_CLK_IDLE_EN,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 240x320 @ 60 Hz */
+		.name		= "TX090",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 38255,
+		.left_margin	= 144,
+		.right_margin	= 0,
+		.upper_margin	= 7,
+		.lower_margin	= 40,
+		.hsync_len	= 96,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 240x320 @ 60 Hz */
+		.name		= "CMEL-OLED",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "Sharp-LQ035Q7DH06-QVGA",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
 };
 
 /*
@@ -215,30 +520,61 @@
  */
 static void __init mxc_board_init(void)
 {
+	int ret;
+
+	mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),
+			"pcm037");
+
+	if (pcm037_variant() == PCM037_EET)
+		mxc_iomux_setup_multiple_pins(pcm037_uart1_pins,
+			ARRAY_SIZE(pcm037_uart1_pins), "pcm037_uart1");
+	else
+		mxc_iomux_setup_multiple_pins(pcm037_uart1_handshake_pins,
+			ARRAY_SIZE(pcm037_uart1_handshake_pins),
+			"pcm037_uart1");
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
-	mxc_iomux_setup_multiple_pins(uart0_pins, ARRAY_SIZE(uart0_pins), "uart-0");
 	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-
-	mxc_iomux_setup_multiple_pins(uart2_pins, ARRAY_SIZE(uart2_pins), "uart-2");
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
 	mxc_register_device(&mxc_uart_device2, &uart_pdata);
 
-	mxc_iomux_setup_pin(MX31_PIN_BATT_LINE__OWIRE, "batt-0wire");
 	mxc_register_device(&mxc_w1_master_device, NULL);
 
 	/* LAN9217 IRQ pin */
-	if (!mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO),
-				"pcm037-eth"))
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1), "lan9217-irq");
+	if (ret)
+		pr_warning("could not get LAN irq gpio\n");
+	else {
 		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
+		platform_device_register(&pcm037_eth);
+	}
 
-#ifdef CONFIG_I2C_IMX
+
+	/* I2C adapters and devices */
 	i2c_register_board_info(1, pcm037_i2c_devices,
 			ARRAY_SIZE(pcm037_i2c_devices));
 
 	mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
-#endif
+	mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
+
 	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
 	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+	if (!gpio_usbotg_hs_activate())
+		mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+
+	/* CSI */
+	/* Camera power: default - off */
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), "mt9t031-power");
+	if (!ret)
+		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1);
+	else
+		iclink.power = NULL;
+
+	if (!pcm037_camera_alloc_dma(4 * 1024 * 1024))
+		mxc_register_device(&mx3_camera, &camera_pdata);
 }
 
 static void __init pcm037_timer_init(void)
@@ -255,9 +591,8 @@
 	.phys_io	= AIPS1_BASE_ADDR,
 	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mxc_map_io,
+	.map_io         = mx31_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = mxc_board_init,
 	.timer          = &pcm037_timer,
 MACHINE_END
-
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm037_eet.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm037_eet.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm037_eet.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm037_eet.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2009
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * 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.
+ */
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <mach/common.h>
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+#include <mach/spi.h>
+#endif
+#include <mach/iomux-mx3.h>
+
+#include <asm/mach-types.h>
+
+#include "pcm037.h"
+#include "devices.h"
+
+static unsigned int pcm037_eet_pins[] = {
+	/* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
+	IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_GPIO),
+	/* GPIO keys */
+	IOMUX_MODE(MX31_PIN_GPIO1_0,	IOMUX_CONFIG_GPIO), /* 0 */
+	IOMUX_MODE(MX31_PIN_GPIO1_1,	IOMUX_CONFIG_GPIO), /* 1 */
+	IOMUX_MODE(MX31_PIN_GPIO1_2,	IOMUX_CONFIG_GPIO), /* 2 */
+	IOMUX_MODE(MX31_PIN_GPIO1_3,	IOMUX_CONFIG_GPIO), /* 3 */
+	IOMUX_MODE(MX31_PIN_SVEN0,	IOMUX_CONFIG_GPIO), /* 32 */
+	IOMUX_MODE(MX31_PIN_STX0,	IOMUX_CONFIG_GPIO), /* 33 */
+	IOMUX_MODE(MX31_PIN_SRX0,	IOMUX_CONFIG_GPIO), /* 34 */
+	IOMUX_MODE(MX31_PIN_SIMPD0,	IOMUX_CONFIG_GPIO), /* 35 */
+	IOMUX_MODE(MX31_PIN_RTS1,	IOMUX_CONFIG_GPIO), /* 38 */
+	IOMUX_MODE(MX31_PIN_CTS1,	IOMUX_CONFIG_GPIO), /* 39 */
+	IOMUX_MODE(MX31_PIN_KEY_ROW4,	IOMUX_CONFIG_GPIO), /* 50 */
+	IOMUX_MODE(MX31_PIN_KEY_ROW5,	IOMUX_CONFIG_GPIO), /* 51 */
+	IOMUX_MODE(MX31_PIN_KEY_ROW6,	IOMUX_CONFIG_GPIO), /* 52 */
+	IOMUX_MODE(MX31_PIN_KEY_ROW7,	IOMUX_CONFIG_GPIO), /* 53 */
+
+	/* LEDs */
+	IOMUX_MODE(MX31_PIN_DTR_DTE1,	IOMUX_CONFIG_GPIO), /* 44 */
+	IOMUX_MODE(MX31_PIN_DSR_DTE1,	IOMUX_CONFIG_GPIO), /* 45 */
+	IOMUX_MODE(MX31_PIN_KEY_COL5,	IOMUX_CONFIG_GPIO), /* 55 */
+	IOMUX_MODE(MX31_PIN_KEY_COL6,	IOMUX_CONFIG_GPIO), /* 56 */
+};
+
+/* SPI */
+static struct spi_board_info pcm037_spi_dev[] = {
+	{
+		.modalias	= "dac124s085",
+		.max_speed_hz	= 400000,
+		.bus_num	= 0,
+		.chip_select	= 0,		/* Index in pcm037_spi1_cs[] */
+		.mode		= SPI_CPHA,
+	},
+};
+
+/* Platform Data for MXC CSPI */
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+static int pcm037_spi1_cs[] = {MXC_SPI_CS(1), IOMUX_TO_GPIO(MX31_PIN_KEY_COL7)};
+
+struct spi_imx_master pcm037_spi1_master = {
+	.chipselect = pcm037_spi1_cs,
+	.num_chipselect = ARRAY_SIZE(pcm037_spi1_cs),
+};
+#endif
+
+/* GPIO-keys input device */
+static struct gpio_keys_button pcm037_gpio_keys[] = {
+	{
+		.type	= EV_KEY,
+		.code	= KEY_L,
+		.gpio	= 0,
+		.desc	= "Wheel Manual",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_A,
+		.gpio	= 1,
+		.desc	= "Wheel AF",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_V,
+		.gpio	= 2,
+		.desc	= "Wheel View",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_M,
+		.gpio	= 3,
+		.desc	= "Wheel Menu",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_UP,
+		.gpio	= 32,
+		.desc	= "Nav Pad Up",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_RIGHT,
+		.gpio	= 33,
+		.desc	= "Nav Pad Right",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_DOWN,
+		.gpio	= 34,
+		.desc	= "Nav Pad Down",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_LEFT,
+		.gpio	= 35,
+		.desc	= "Nav Pad Left",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_ENTER,
+		.gpio	= 38,
+		.desc	= "Nav Pad Ok",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= KEY_O,
+		.gpio	= 39,
+		.desc	= "Wheel Off",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= BTN_FORWARD,
+		.gpio	= 50,
+		.desc	= "Focus Forward",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= BTN_BACK,
+		.gpio	= 51,
+		.desc	= "Focus Backward",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= BTN_MIDDLE,
+		.gpio	= 52,
+		.desc	= "Release Half",
+		.wakeup	= 0,
+	}, {
+		.type	= EV_KEY,
+		.code	= BTN_EXTRA,
+		.gpio	= 53,
+		.desc	= "Release Full",
+		.wakeup	= 0,
+	},
+};
+
+static struct gpio_keys_platform_data pcm037_gpio_keys_platform_data = {
+	.buttons	= pcm037_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(pcm037_gpio_keys),
+	.rep		= 0, /* No auto-repeat */
+};
+
+static struct platform_device pcm037_gpio_keys_device = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &pcm037_gpio_keys_platform_data,
+	},
+};
+
+static int eet_init_devices(void)
+{
+	if (!machine_is_pcm037() || pcm037_variant() != PCM037_EET)
+		return 0;
+
+	mxc_iomux_setup_multiple_pins(pcm037_eet_pins,
+				ARRAY_SIZE(pcm037_eet_pins), "pcm037_eet");
+
+	/* SPI */
+	spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+	mxc_register_device(&mxc_spi_device0, &pcm037_spi1_master);
+#endif
+
+	platform_device_register(&pcm037_gpio_keys_device);
+
+	return 0;
+}
+
+late_initcall(eet_init_devices);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm037.h linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm037.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm037.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm037.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,11 @@
+#ifndef __PCM037_H__
+#define __PCM037_H__
+
+enum pcm037_board_variant {
+	PCM037_PCM970,
+	PCM037_EET,
+};
+
+extern enum pcm037_board_variant pcm037_variant(void);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm043.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm043.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/pcm043.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/pcm043.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,252 @@
+/*
+ *  Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * 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/types.h>
+#include <linux/init.h>
+
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/memory.h>
+#include <linux/gpio.h>
+#include <linux/smc911x.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
+#include <mach/i2c.h>
+#endif
+#include <mach/iomux-mx35.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+
+#include "devices.h"
+
+static const struct fb_videomode fb_modedb[] = {
+	{
+		/* 240x320 @ 60 Hz */
+		.name		= "Sharp-LQ035Q7",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | FB_SYNC_CLK_INVERT | FB_SYNC_CLK_IDLE_EN,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 240x320 @ 60 Hz */
+		.name		= "TX090",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 38255,
+		.left_margin	= 144,
+		.right_margin	= 0,
+		.upper_margin	= 7,
+		.lower_margin	= 40,
+		.hsync_len	= 96,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "Sharp-LQ035Q7",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+static struct physmap_flash_data pcm043_flash_data = {
+	.width  = 2,
+};
+
+static struct resource pcm043_flash_resource = {
+	.start	= 0xa0000000,
+	.end	= 0xa1ffffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device pcm043_flash = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &pcm043_flash_data,
+	},
+	.resource = &pcm043_flash_resource,
+	.num_resources = 1,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
+static struct imxi2c_platform_data pcm043_i2c_1_data = {
+	.bitrate = 50000,
+};
+
+static struct at24_platform_data board_eeprom = {
+	.byte_len = 4096,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info pcm043_i2c_devices[] = {
+       {
+		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+		.platform_data = &board_eeprom,
+	}, {
+		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+		.type = "pcf8563",
+	}
+};
+#endif
+
+static struct platform_device *devices[] __initdata = {
+	&pcm043_flash,
+	&mxc_fec_device,
+};
+
+static struct pad_desc pcm043_pads[] = {
+	/* UART1 */
+	MX35_PAD_CTS1__UART1_CTS,
+	MX35_PAD_RTS1__UART1_RTS,
+	MX35_PAD_TXD1__UART1_TXD_MUX,
+	MX35_PAD_RXD1__UART1_RXD_MUX,
+	/* UART2 */
+	MX35_PAD_CTS2__UART2_CTS,
+	MX35_PAD_RTS2__UART2_RTS,
+	MX35_PAD_TXD2__UART2_TXD_MUX,
+	MX35_PAD_RXD2__UART2_RXD_MUX,
+	/* FEC */
+	MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
+	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX35_PAD_FEC_COL__FEC_COL,
+	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
+	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
+	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX35_PAD_FEC_MDC__FEC_MDC,
+	MX35_PAD_FEC_MDIO__FEC_MDIO,
+	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
+	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
+	MX35_PAD_FEC_CRS__FEC_CRS,
+	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
+	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
+	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
+	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
+	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
+	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
+	/* I2C1 */
+	MX35_PAD_I2C1_CLK__I2C1_SCL,
+	MX35_PAD_I2C1_DAT__I2C1_SDA,
+	/* Display */
+	MX35_PAD_LD0__IPU_DISPB_DAT_0,
+	MX35_PAD_LD1__IPU_DISPB_DAT_1,
+	MX35_PAD_LD2__IPU_DISPB_DAT_2,
+	MX35_PAD_LD3__IPU_DISPB_DAT_3,
+	MX35_PAD_LD4__IPU_DISPB_DAT_4,
+	MX35_PAD_LD5__IPU_DISPB_DAT_5,
+	MX35_PAD_LD6__IPU_DISPB_DAT_6,
+	MX35_PAD_LD7__IPU_DISPB_DAT_7,
+	MX35_PAD_LD8__IPU_DISPB_DAT_8,
+	MX35_PAD_LD9__IPU_DISPB_DAT_9,
+	MX35_PAD_LD10__IPU_DISPB_DAT_10,
+	MX35_PAD_LD11__IPU_DISPB_DAT_11,
+	MX35_PAD_LD12__IPU_DISPB_DAT_12,
+	MX35_PAD_LD13__IPU_DISPB_DAT_13,
+	MX35_PAD_LD14__IPU_DISPB_DAT_14,
+	MX35_PAD_LD15__IPU_DISPB_DAT_15,
+	MX35_PAD_LD16__IPU_DISPB_DAT_16,
+	MX35_PAD_LD17__IPU_DISPB_DAT_17,
+	MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC,
+	MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK,
+	MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY,
+	MX35_PAD_CONTRAST__IPU_DISPB_CONTR,
+	MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC,
+	MX35_PAD_D3_REV__IPU_DISPB_D3_REV,
+	MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS,
+	MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+
+#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
+	i2c_register_board_info(0, pcm043_i2c_devices,
+			ARRAY_SIZE(pcm043_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device0, &pcm043_i2c_1_data);
+#endif
+
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+}
+
+static void __init pcm043_timer_init(void)
+{
+	mx35_clocks_init();
+}
+
+struct sys_timer pcm043_timer = {
+	.init	= pcm043_timer_init,
+};
+
+MACHINE_START(PCM043, "Phytec Phycore pcm043")
+	/* Maintainer: Pengutronix */
+	.phys_io	= AIPS1_BASE_ADDR,
+	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = mx35_map_io,
+	.init_irq       = mxc_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &pcm043_timer,
+MACHINE_END
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-mx3/qong.c linux-libre-2.6.31-gnu/arch/arm/mach-mx3/qong.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-mx3/qong.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-mx3/qong.c	2009-09-09 18:13:59.000000000 -0400
@@ -279,7 +279,7 @@
 	.phys_io        = AIPS1_BASE_ADDR,
 	.io_pg_offst    = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mxc_map_io,
+	.map_io         = mx31_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = mxc_board_init,
 	.timer          = &qong_timer,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-netx/generic.c linux-libre-2.6.31-gnu/arch/arm/mach-netx/generic.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-netx/generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-netx/generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -168,7 +168,7 @@
 {
 	int irq;
 
-	vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0);
+	vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0, 0);
 
 	for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
 		set_irq_chip(irq, &netx_hif_chip);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/board-nokia770.c linux-libre-2.6.31-gnu/arch/arm/mach-omap1/board-nokia770.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/board-nokia770.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/board-nokia770.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,8 +33,10 @@
 #include <mach/common.h>
 #include <mach/dsp_common.h>
 #include <mach/omapfb.h>
+#include <mach/hwa742.h>
 #include <mach/lcd_mipid.h>
 #include <mach/mmc.h>
+#include <mach/clock.h>
 
 #define ADS7846_PENDOWN_GPIO	15
 
@@ -162,6 +164,15 @@
 	},
 };
 
+static struct hwa742_platform_data nokia770_hwa742_platform_data = {
+	.te_connected		= 1,
+};
+
+static void hwa742_dev_init(void)
+{
+	clk_add_alias("hwa_sys_ck", NULL, "bclk", NULL);
+	omapfb_set_ctrl_platform_data(&nokia770_hwa742_platform_data);
+}
 
 /* assume no Mini-AB port */
 
@@ -193,9 +204,11 @@
 static struct omap_mmc_platform_data nokia770_mmc2_data = {
 	.nr_slots                       = 1,
 	.dma_mask			= 0xffffffff,
+	.max_freq                       = 12000000,
 	.slots[0]       = {
 		.set_power		= nokia770_mmc_set_power,
 		.get_cover_state	= nokia770_mmc_get_cover_state,
+		.ocr_mask               = MMC_VDD_32_33|MMC_VDD_33_34,
 		.name                   = "mmcblk",
 	},
 };
@@ -370,6 +383,7 @@
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
 	omap_dsp_init();
+	hwa742_dev_init();
 	ads7846_dev_init();
 	mipid_dev_init();
 	omap_usb_init(&nokia770_usb_config);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-omap1/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -776,7 +776,7 @@
 	arm_idlect1_mask = ~0;
 
 	for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
-		clk_init_one(c->lk.clk);
+		clk_preinit(c->lk.clk);
 
 	cpu_mask = 0;
 	if (cpu_is_omap16xx())
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-omap1/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,6 @@
 config MACH_OMAP_H3
 	bool "TI H3 Support"
 	depends on ARCH_OMAP1 && ARCH_OMAP16XX
-#	select GPIOEXPANDER_OMAP
     	help
 	  TI OMAP 1710 H3 board support. Say Y here if you have such
 	  a board.
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/mailbox.c linux-libre-2.6.31-gnu/arch/arm/mach-omap1/mailbox.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/mailbox.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/mailbox.c	2009-09-09 18:13:59.000000000 -0400
@@ -203,5 +203,5 @@
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU" <Hiroshi.DOYU@nokia.com>);
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
 MODULE_ALIAS("platform:omap1-mailbox");
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-omap1/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,10 @@
 # Power Management
 obj-$(CONFIG_PM) += pm.o sleep.o
 
+# DSP
+obj-$(CONFIG_OMAP_MBOX_FWK)	+= mailbox_mach.o
+mailbox_mach-objs		:= mailbox.o
+
 led-y := leds.o
 
 # Specific board support
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/mcbsp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap1/mcbsp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/mcbsp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/mcbsp.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,6 @@
 
 #include <mach/irqs.h>
 #include <mach/dma.h>
-#include <mach/irqs.h>
 #include <mach/mux.h>
 #include <mach/cpu.h>
 #include <mach/mcbsp.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/pm.c linux-libre-2.6.31-gnu/arch/arm/mach-omap1/pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,11 +53,12 @@
 #include <mach/clock.h>
 #include <mach/sram.h>
 #include <mach/tc.h>
-#include <mach/pm.h>
 #include <mach/mux.h>
 #include <mach/dma.h>
 #include <mach/dmtimer.h>
 
+#include "pm.h"
+
 static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
 static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE];
 static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
@@ -101,7 +102,7 @@
  * going idle we continue to do idle even if we get
  * a clock tick interrupt . .
  */
-void omap_pm_idle(void)
+void omap1_pm_idle(void)
 {
 	extern __u32 arm_idlect1_mask;
 	__u32 use_idlect1 = arm_idlect1_mask;
@@ -222,7 +223,7 @@
 #define EN_APICK	6	/* ARM_IDLECT2 */
 #define DSP_EN		1	/* ARM_RSTCT1 */
 
-void omap_pm_suspend(void)
+void omap1_pm_suspend(void)
 {
 	unsigned long arg0 = 0, arg1 = 0;
 
@@ -610,7 +611,7 @@
 	{
 	case PM_SUSPEND_STANDBY:
 	case PM_SUSPEND_MEM:
-		omap_pm_suspend();
+		omap1_pm_suspend();
 		break;
 	default:
 		return -EINVAL;
@@ -683,7 +684,7 @@
 		return -ENODEV;
 	}
 
-	pm_idle = omap_pm_idle;
+	pm_idle = omap1_pm_idle;
 
 	if (cpu_is_omap730())
 		setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/pm.h linux-libre-2.6.31-gnu/arch/arm/mach-omap1/pm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/pm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,280 @@
+/*
+ * arch/arm/mach-omap1/pm.h
+ *
+ * Header file for OMAP1 Power Management Routines
+ *
+ * Author: MontaVista Software, Inc.
+ *	   support@mvista.com
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ * Cleanup 2004 for Linux 2.6 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * 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 __ARCH_ARM_MACH_OMAP1_PM_H
+#define __ARCH_ARM_MACH_OMAP1_PM_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Register and offset definitions to be used in PM assembler code
+ * ----------------------------------------------------------------------------
+ */
+#define CLKGEN_REG_ASM_BASE		IO_ADDRESS(0xfffece00)
+#define ARM_IDLECT1_ASM_OFFSET		0x04
+#define ARM_IDLECT2_ASM_OFFSET		0x08
+
+#define TCMIF_ASM_BASE			IO_ADDRESS(0xfffecc00)
+#define EMIFS_CONFIG_ASM_OFFSET		0x0c
+#define EMIFF_SDRAM_CONFIG_ASM_OFFSET	0x20
+
+/*
+ * ----------------------------------------------------------------------------
+ * Power management bitmasks
+ * ----------------------------------------------------------------------------
+ */
+#define IDLE_WAIT_CYCLES		0x00000fff
+#define PERIPHERAL_ENABLE		0x2
+
+#define SELF_REFRESH_MODE		0x0c000001
+#define IDLE_EMIFS_REQUEST		0xc
+#define MODEM_32K_EN			0x1
+#define PER_EN				0x1
+
+#define CPU_SUSPEND_SIZE		200
+#define ULPD_LOW_PWR_EN			0x0001
+#define ULPD_DEEP_SLEEP_TRANSITION_EN	0x0010
+#define ULPD_SETUP_ANALOG_CELL_3_VAL	0
+#define ULPD_POWER_CTRL_REG_VAL		0x0219
+
+#define DSP_IDLE_DELAY			10
+#define DSP_IDLE			0x0040
+#define DSP_RST				0x0004
+#define DSP_ENABLE			0x0002
+#define SUFFICIENT_DSP_RESET_TIME	1000
+#define DEFAULT_MPUI_CONFIG		0x05cf
+#define ENABLE_XORCLK			0x2
+#define DSP_CLOCK_ENABLE		0x2000
+#define DSP_IDLE_MODE			0x2
+#define TC_IDLE_REQUEST			(0x0000000c)
+
+#define IRQ_LEVEL2			(1<<0)
+#define IRQ_KEYBOARD			(1<<1)
+#define IRQ_UART2			(1<<15)
+
+#define PDE_BIT				0x08
+#define PWD_EN_BIT			0x04
+#define EN_PERCK_BIT			0x04
+
+#define OMAP1510_DEEP_SLEEP_REQUEST	0x0ec7
+#define OMAP1510_BIG_SLEEP_REQUEST	0x0cc5
+#define OMAP1510_IDLE_LOOP_REQUEST	0x0c00
+#define OMAP1510_IDLE_CLOCK_DOMAINS	0x2
+
+/* Both big sleep and deep sleep use same values. Difference is in ULPD. */
+#define OMAP1610_IDLECT1_SLEEP_VAL	0x13c7
+#define OMAP1610_IDLECT2_SLEEP_VAL	0x09c7
+#define OMAP1610_IDLECT3_VAL		0x3f
+#define OMAP1610_IDLECT3_SLEEP_ORMASK	0x2c
+#define OMAP1610_IDLECT3		0xfffece24
+#define OMAP1610_IDLE_LOOP_REQUEST	0x0400
+
+#define OMAP730_IDLECT1_SLEEP_VAL	0x16c7
+#define OMAP730_IDLECT2_SLEEP_VAL	0x09c7
+#define OMAP730_IDLECT3_VAL		0x3f
+#define OMAP730_IDLECT3		0xfffece24
+#define OMAP730_IDLE_LOOP_REQUEST	0x0C00
+
+#if     !defined(CONFIG_ARCH_OMAP730) && \
+	!defined(CONFIG_ARCH_OMAP15XX) && \
+	!defined(CONFIG_ARCH_OMAP16XX)
+#warning "Power management for this processor not implemented yet"
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <linux/clk.h>
+
+extern struct kset power_subsys;
+
+extern void prevent_idle_sleep(void);
+extern void allow_idle_sleep(void);
+
+extern void omap1_pm_idle(void);
+extern void omap1_pm_suspend(void);
+
+extern void omap730_cpu_suspend(unsigned short, unsigned short);
+extern void omap1510_cpu_suspend(unsigned short, unsigned short);
+extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap730_idle_loop_suspend(void);
+extern void omap1510_idle_loop_suspend(void);
+extern void omap1610_idle_loop_suspend(void);
+
+extern unsigned int omap730_cpu_suspend_sz;
+extern unsigned int omap1510_cpu_suspend_sz;
+extern unsigned int omap1610_cpu_suspend_sz;
+extern unsigned int omap730_idle_loop_suspend_sz;
+extern unsigned int omap1510_idle_loop_suspend_sz;
+extern unsigned int omap1610_idle_loop_suspend_sz;
+
+#ifdef CONFIG_OMAP_SERIAL_WAKE
+extern void omap_serial_wake_trigger(int enable);
+#else
+#define omap_serial_wakeup_init()	{}
+#define omap_serial_wake_trigger(x)	{}
+#endif	/* CONFIG_OMAP_SERIAL_WAKE */
+
+#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
+#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
+#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
+
+#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x)
+#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x))
+#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x]
+
+#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
+#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
+#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
+
+#define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x))
+#define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]
+
+#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x))
+#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]
+
+#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
+#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
+
+/*
+ * List of global OMAP registers to preserve.
+ * More ones like CP and general purpose register values are preserved
+ * with the stack pointer in sleep.S.
+ */
+
+enum arm_save_state {
+	ARM_SLEEP_SAVE_START = 0,
+	/*
+	 * MPU control registers 32 bits
+	 */
+	ARM_SLEEP_SAVE_ARM_CKCTL,
+	ARM_SLEEP_SAVE_ARM_IDLECT1,
+	ARM_SLEEP_SAVE_ARM_IDLECT2,
+	ARM_SLEEP_SAVE_ARM_IDLECT3,
+	ARM_SLEEP_SAVE_ARM_EWUPCT,
+	ARM_SLEEP_SAVE_ARM_RSTCT1,
+	ARM_SLEEP_SAVE_ARM_RSTCT2,
+	ARM_SLEEP_SAVE_ARM_SYSST,
+	ARM_SLEEP_SAVE_SIZE
+};
+
+enum dsp_save_state {
+	DSP_SLEEP_SAVE_START = 0,
+	/*
+	 * DSP registers 16 bits
+	 */
+	DSP_SLEEP_SAVE_DSP_IDLECT2,
+	DSP_SLEEP_SAVE_SIZE
+};
+
+enum ulpd_save_state {
+	ULPD_SLEEP_SAVE_START = 0,
+	/*
+	 * ULPD registers 16 bits
+	 */
+	ULPD_SLEEP_SAVE_ULPD_IT_STATUS,
+	ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL,
+	ULPD_SLEEP_SAVE_ULPD_SOFT_REQ,
+	ULPD_SLEEP_SAVE_ULPD_STATUS_REQ,
+	ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL,
+	ULPD_SLEEP_SAVE_ULPD_POWER_CTRL,
+	ULPD_SLEEP_SAVE_SIZE
+};
+
+enum mpui1510_save_state {
+	MPUI1510_SLEEP_SAVE_START = 0,
+	/*
+	 * MPUI registers 32 bits
+	 */
+	MPUI1510_SLEEP_SAVE_MPUI_CTRL,
+	MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+	MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+	MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS,
+	MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+	MPUI1510_SLEEP_SAVE_EMIFS_CONFIG,
+	MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR,
+	MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR,
+#if defined(CONFIG_ARCH_OMAP15XX)
+	MPUI1510_SLEEP_SAVE_SIZE
+#else
+	MPUI1510_SLEEP_SAVE_SIZE = 0
+#endif
+};
+
+enum mpui730_save_state {
+	MPUI730_SLEEP_SAVE_START = 0,
+	/*
+	 * MPUI registers 32 bits
+	 */
+	MPUI730_SLEEP_SAVE_MPUI_CTRL,
+	MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+	MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+	MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS,
+	MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+	MPUI730_SLEEP_SAVE_EMIFS_CONFIG,
+	MPUI730_SLEEP_SAVE_OMAP_IH1_MIR,
+	MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR,
+	MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR,
+#if defined(CONFIG_ARCH_OMAP730)
+	MPUI730_SLEEP_SAVE_SIZE
+#else
+	MPUI730_SLEEP_SAVE_SIZE = 0
+#endif
+};
+
+enum mpui1610_save_state {
+	MPUI1610_SLEEP_SAVE_START = 0,
+	/*
+	 * MPUI registers 32 bits
+	 */
+	MPUI1610_SLEEP_SAVE_MPUI_CTRL,
+	MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+	MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+	MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS,
+	MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+	MPUI1610_SLEEP_SAVE_EMIFS_CONFIG,
+	MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR,
+#if defined(CONFIG_ARCH_OMAP16XX)
+	MPUI1610_SLEEP_SAVE_SIZE
+#else
+	MPUI1610_SLEEP_SAVE_SIZE = 0
+#endif
+};
+
+#endif /* ASSEMBLER */
+#endif /* __ASM_ARCH_OMAP_PM_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/serial.c linux-libre-2.6.31-gnu/arch/arm/mach-omap1/serial.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/serial.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/serial.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,9 +26,6 @@
 #include <mach/mux.h>
 #include <mach/gpio.h>
 #include <mach/fpga.h>
-#ifdef CONFIG_PM
-#include <mach/pm.h>
-#endif
 
 static struct clk * uart1_ck;
 static struct clk * uart2_ck;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap1/sleep.S linux-libre-2.6.31-gnu/arch/arm/mach-omap1/sleep.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap1/sleep.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap1/sleep.S	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
-#include <mach/pm.h>
+#include "pm.h"
 
 		.text
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-2430sdp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-2430sdp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-2430sdp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-2430sdp.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,14 +36,12 @@
 #include <mach/common.h>
 #include <mach/gpmc.h>
 #include <mach/usb.h>
+#include <mach/gpmc-smc91x.h>
 
 #include "mmc-twl4030.h"
 
 #define SDP2430_CS0_BASE	0x04000000
-#define	SDP2430_FLASH_CS	0
-#define	SDP2430_SMC91X_CS	5
-
-#define SDP2430_ETHR_GPIO_IRQ		149
+#define SECONDARY_LCD_GPIO		147
 
 static struct mtd_partition sdp2430_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
@@ -99,100 +97,53 @@
 	.resource	= &sdp2430_flash_resource,
 };
 
-static struct resource sdp2430_smc91x_resources[] = {
-	[0] = {
-		.start	= SDP2430_CS0_BASE,
-		.end	= SDP2430_CS0_BASE + SZ_64M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ),
-		.end	= OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ),
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
-};
-
-static struct platform_device sdp2430_smc91x_device = {
-	.name		= "smc91x",
+static struct platform_device sdp2430_lcd_device = {
+	.name		= "sdp2430_lcd",
 	.id		= -1,
-	.num_resources	= ARRAY_SIZE(sdp2430_smc91x_resources),
-	.resource	= sdp2430_smc91x_resources,
 };
 
 static struct platform_device *sdp2430_devices[] __initdata = {
-	&sdp2430_smc91x_device,
 	&sdp2430_flash_device,
+	&sdp2430_lcd_device,
 };
 
-static inline void __init sdp2430_init_smc91x(void)
-{
-	int eth_cs;
-	unsigned long cs_mem_base;
-	unsigned int rate;
-	struct clk *gpmc_fck;
-
-	eth_cs = SDP2430_SMC91X_CS;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
+static struct omap_lcd_config sdp2430_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
 
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
 
-	/* Make sure CS1 timings are correct, for 2430 always muxed */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
+static struct omap_smc91x_platform_data board_smc91x_data = {
+	.cs		= 5,
+	.gpio_irq	= 149,
+	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
+				IORESOURCE_IRQ_LOWLEVEL,
 
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else { /* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
+};
 
-	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		goto out;
-	}
+static void __init board_smc91x_init(void)
+{
+	if (omap_rev() > OMAP3430_REV_ES1_0)
+		board_smc91x_data.gpio_irq = 6;
+	else
+		board_smc91x_data.gpio_irq = 29;
 
-	sdp2430_smc91x_resources[0].start = cs_mem_base + 0x300;
-	sdp2430_smc91x_resources[0].end = cs_mem_base + 0x30f;
-	udelay(100);
+	gpmc_smc91x_init(&board_smc91x_data);
+}
 
-	if (gpio_request(SDP2430_ETHR_GPIO_IRQ, "SMC91x irq") < 0) {
-		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
-			SDP2430_ETHR_GPIO_IRQ);
-		gpmc_cs_free(eth_cs);
-		goto out;
-	}
-	gpio_direction_input(SDP2430_ETHR_GPIO_IRQ);
+#else
 
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
+static inline void board_smc91x_init(void)
+{
 }
 
+#endif
+
 static void __init omap_2430sdp_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(NULL, NULL);
 	omap_init_irq();
 	omap_gpio_init();
-	sdp2430_init_smc91x();
 }
 
 static struct omap_uart_config sdp2430_uart_config __initdata = {
@@ -201,6 +152,7 @@
 
 static struct omap_board_config_kernel sdp2430_config[] = {
 	{OMAP_TAG_UART, &sdp2430_uart_config},
+	{OMAP_TAG_LCD, &sdp2430_lcd_config},
 };
 
 
@@ -248,6 +200,8 @@
 
 static void __init omap_2430sdp_init(void)
 {
+	int ret;
+
 	omap2430_i2c_init();
 
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
@@ -256,6 +210,12 @@
 	omap_serial_init();
 	twl4030_mmc_init(mmc);
 	usb_musb_init();
+	board_smc91x_init();
+
+	/* Turn off secondary LCD backlight */
+	ret = gpio_request(SECONDARY_LCD_GPIO, "Secondary LCD backlight");
+	if (ret == 0)
+		gpio_direction_output(SECONDARY_LCD_GPIO, 0);
 }
 
 static void __init omap_2430sdp_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-3430sdp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-3430sdp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-3430sdp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-3430sdp.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,15 +39,13 @@
 
 #include <mach/control.h>
 #include <mach/keypad.h>
+#include <mach/gpmc-smc91x.h>
 
+#include "sdram-qimonda-hyb18m512160af-6.h"
 #include "mmc-twl4030.h"
 
 #define CONFIG_DISABLE_HFCLK 1
 
-#define SDP3430_ETHR_GPIO_IRQ_SDPV1	29
-#define SDP3430_ETHR_GPIO_IRQ_SDPV2	6
-#define SDP3430_SMC91X_CS		3
-
 #define SDP3430_TS_GPIO_IRQ_SDPV1	3
 #define SDP3430_TS_GPIO_IRQ_SDPV2	2
 
@@ -56,24 +54,6 @@
 
 #define TWL4030_MSECURE_GPIO 22
 
-static struct resource sdp3430_smc91x_resources[] = {
-	[0] = {
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 0,
-		.end	= 0,
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
-};
-
-static struct platform_device sdp3430_smc91x_device = {
-	.name		= "smc91x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(sdp3430_smc91x_resources),
-	.resource	= sdp3430_smc91x_resources,
-};
-
 static int sdp3430_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -184,48 +164,14 @@
 };
 
 static struct platform_device *sdp3430_devices[] __initdata = {
-	&sdp3430_smc91x_device,
 	&sdp3430_lcd_device,
 };
 
-static inline void __init sdp3430_init_smc91x(void)
-{
-	int eth_cs;
-	unsigned long cs_mem_base;
-	int eth_gpio = 0;
-
-	eth_cs = SDP3430_SMC91X_CS;
-
-	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		return;
-	}
-
-	sdp3430_smc91x_resources[0].start = cs_mem_base + 0x300;
-	sdp3430_smc91x_resources[0].end = cs_mem_base + 0x30f;
-	udelay(100);
-
-	if (omap_rev() > OMAP3430_REV_ES1_0)
-		eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV2;
-	else
-		eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV1;
-
-	sdp3430_smc91x_resources[1].start = gpio_to_irq(eth_gpio);
-
-	if (gpio_request(eth_gpio, "SMC91x irq") < 0) {
-		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
-			eth_gpio);
-		return;
-	}
-	gpio_direction_input(eth_gpio);
-}
-
 static void __init omap_3430sdp_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL);
 	omap_init_irq();
 	omap_gpio_init();
-	sdp3430_init_smc91x();
 }
 
 static struct omap_uart_config sdp3430_uart_config __initdata = {
@@ -506,6 +452,32 @@
 	return 0;
 }
 
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+
+static struct omap_smc91x_platform_data board_smc91x_data = {
+	.cs		= 3,
+	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
+				IORESOURCE_IRQ_LOWLEVEL,
+};
+
+static void __init board_smc91x_init(void)
+{
+	if (omap_rev() > OMAP3430_REV_ES1_0)
+		board_smc91x_data.gpio_irq = 6;
+	else
+		board_smc91x_data.gpio_irq = 29;
+
+	gpmc_smc91x_init(&board_smc91x_data);
+}
+
+#else
+
+static inline void board_smc91x_init(void)
+{
+}
+
+#endif
+
 static void __init omap_3430sdp_init(void)
 {
 	omap3430_i2c_init();
@@ -522,6 +494,7 @@
 	ads7846_dev_init();
 	omap_serial_init();
 	usb_musb_init();
+	board_smc91x_init();
 }
 
 static void __init omap_3430sdp_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-4430sdp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-4430sdp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-4430sdp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-4430sdp.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * Board support file for OMAP4430 SDP.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Author: Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Based on mach-omap2/board-3430sdp.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/board.h>
+#include <mach/common.h>
+#include <mach/control.h>
+#include <mach/timer-gp.h>
+#include <asm/hardware/gic.h>
+
+static struct platform_device sdp4430_lcd_device = {
+	.name		= "sdp4430_lcd",
+	.id		= -1,
+};
+
+static struct platform_device *sdp4430_devices[] __initdata = {
+	&sdp4430_lcd_device,
+};
+
+static struct omap_uart_config sdp4430_uart_config __initdata = {
+	.enabled_uarts	= (1 << 0) | (1 << 1) | (1 << 2),
+};
+
+static struct omap_lcd_config sdp4430_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
+static struct omap_board_config_kernel sdp4430_config[] __initdata = {
+	{ OMAP_TAG_UART,	&sdp4430_uart_config },
+	{ OMAP_TAG_LCD,		&sdp4430_lcd_config },
+};
+
+static void __init gic_init_irq(void)
+{
+	gic_dist_init(0, IO_ADDRESS(OMAP44XX_GIC_DIST_BASE), 29);
+	gic_cpu_init(0, IO_ADDRESS(OMAP44XX_GIC_CPU_BASE));
+}
+
+static void __init omap_4430sdp_init_irq(void)
+{
+	omap2_init_common_hw(NULL, NULL);
+#ifdef CONFIG_OMAP_32K_TIMER
+	omap2_gp_clockevent_set_gptimer(1);
+#endif
+	gic_init_irq();
+	omap_gpio_init();
+}
+
+
+static void __init omap_4430sdp_init(void)
+{
+	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
+	omap_board_config = sdp4430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp4430_config);
+	omap_serial_init();
+}
+
+static void __init omap_4430sdp_map_io(void)
+{
+	omap2_set_globals_443x();
+	omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
+	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= omap_4430sdp_map_io,
+	.init_irq	= omap_4430sdp_init_irq,
+	.init_machine	= omap_4430sdp_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-apollon.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-apollon.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-apollon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-apollon.c	2009-09-09 18:13:59.000000000 -0400
@@ -250,7 +250,7 @@
 
 static void __init omap_apollon_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(NULL, NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	apollon_init_smc91x();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-generic.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-generic.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,7 @@
 
 static void __init omap_generic_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(NULL, NULL);
 	omap_init_irq();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-h4.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-h4.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-h4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-h4.c	2009-09-09 18:13:59.000000000 -0400
@@ -270,7 +270,7 @@
 
 static void __init omap_h4_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(NULL, NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	h4_init_flash();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-ldp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-ldp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-ldp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-ldp.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,11 +16,13 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/gpio_keys.h>
 #include <linux/workqueue.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/regulator/machine.h>
 #include <linux/i2c/twl4030.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
@@ -39,6 +41,7 @@
 #include <asm/delay.h>
 #include <mach/control.h>
 #include <mach/usb.h>
+#include <mach/keypad.h>
 
 #include "mmc-twl4030.h"
 
@@ -77,8 +80,163 @@
 	},
 };
 
-static struct platform_device *ldp_devices[] __initdata = {
-	&ldp_smsc911x_device,
+static int ldp_twl4030_keymap[] = {
+	KEY(0, 0, KEY_1),
+	KEY(1, 0, KEY_2),
+	KEY(2, 0, KEY_3),
+	KEY(0, 1, KEY_4),
+	KEY(1, 1, KEY_5),
+	KEY(2, 1, KEY_6),
+	KEY(3, 1, KEY_F5),
+	KEY(0, 2, KEY_7),
+	KEY(1, 2, KEY_8),
+	KEY(2, 2, KEY_9),
+	KEY(3, 2, KEY_F6),
+	KEY(0, 3, KEY_F7),
+	KEY(1, 3, KEY_0),
+	KEY(2, 3, KEY_F8),
+	PERSISTENT_KEY(4, 5),
+	KEY(4, 4, KEY_VOLUMEUP),
+	KEY(5, 5, KEY_VOLUMEDOWN),
+	0
+};
+
+static struct twl4030_keypad_data ldp_kp_twl4030_data = {
+	.rows		= 6,
+	.cols		= 6,
+	.keymap		= ldp_twl4030_keymap,
+	.keymapsize	= ARRAY_SIZE(ldp_twl4030_keymap),
+	.rep		= 1,
+};
+
+static struct gpio_keys_button ldp_gpio_keys_buttons[] = {
+	[0] = {
+		.code			= KEY_ENTER,
+		.gpio			= 101,
+		.desc			= "enter sw",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+	[1] = {
+		.code			= KEY_F1,
+		.gpio			= 102,
+		.desc			= "func 1",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+	[2] = {
+		.code			= KEY_F2,
+		.gpio			= 103,
+		.desc			= "func 2",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+	[3] = {
+		.code			= KEY_F3,
+		.gpio			= 104,
+		.desc			= "func 3",
+		.active_low		= 1,
+		.debounce_interval 	= 30,
+	},
+	[4] = {
+		.code			= KEY_F4,
+		.gpio			= 105,
+		.desc			= "func 4",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+	[5] = {
+		.code			= KEY_LEFT,
+		.gpio			= 106,
+		.desc			= "left sw",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+	[6] = {
+		.code			= KEY_RIGHT,
+		.gpio			= 107,
+		.desc			= "right sw",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+	[7] = {
+		.code			= KEY_UP,
+		.gpio			= 108,
+		.desc			= "up sw",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+	[8] = {
+		.code			= KEY_DOWN,
+		.gpio			= 109,
+		.desc			= "down sw",
+		.active_low		= 1,
+		.debounce_interval	= 30,
+	},
+};
+
+static struct gpio_keys_platform_data ldp_gpio_keys = {
+	.buttons		= ldp_gpio_keys_buttons,
+	.nbuttons		= ARRAY_SIZE(ldp_gpio_keys_buttons),
+	.rep			= 1,
+};
+
+static struct platform_device ldp_gpio_keys_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &ldp_gpio_keys,
+	},
+};
+
+static int ts_gpio;
+
+/**
+ * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq
+ *
+ * @return - void. If request gpio fails then Flag KERN_ERR.
+ */
+static void ads7846_dev_init(void)
+{
+	if (gpio_request(ts_gpio, "ads7846 irq") < 0) {
+		printk(KERN_ERR "can't get ads746 pen down GPIO\n");
+		return;
+	}
+
+	gpio_direction_input(ts_gpio);
+	omap_set_gpio_debounce(ts_gpio, 1);
+	omap_set_gpio_debounce_time(ts_gpio, 0xa);
+}
+
+static int ads7846_get_pendown_state(void)
+{
+	return !gpio_get_value(ts_gpio);
+}
+
+static struct ads7846_platform_data tsc2046_config __initdata = {
+	.get_pendown_state	= ads7846_get_pendown_state,
+	.keep_vref_on		= 1,
+};
+
+static struct omap2_mcspi_device_config tsc2046_mcspi_config = {
+	.turbo_mode	= 0,
+	.single_channel	= 1,	/* 0: slave, 1: master */
+};
+
+static struct spi_board_info ldp_spi_board_info[] __initdata = {
+	[0] = {
+		/*
+		 * TSC2046 operates at a max freqency of 2MHz, so
+		 * operate slightly below at 1.5MHz
+		 */
+		.modalias		= "ads7846",
+		.bus_num		= 1,
+		.chip_select		= 0,
+		.max_speed_hz		= 1500000,
+		.controller_data	= &tsc2046_mcspi_config,
+		.irq			= 0,
+		.platform_data		= &tsc2046_config,
+	},
 };
 
 static inline void __init ldp_init_smsc911x(void)
@@ -112,7 +270,7 @@
 
 static void __init omap_ldp_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(NULL, NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	ldp_init_smsc911x();
@@ -122,8 +280,22 @@
 	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
+static struct platform_device ldp_lcd_device = {
+	.name		= "ldp_lcd",
+	.id		= -1,
+};
+
+static struct omap_lcd_config ldp_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
 static struct omap_board_config_kernel ldp_config[] __initdata = {
 	{ OMAP_TAG_UART,	&ldp_uart_config },
+	{ OMAP_TAG_LCD,		&ldp_lcd_config },
+};
+
+static struct twl4030_usb_data ldp_usb_data = {
+	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
 static struct twl4030_gpio_platform_data ldp_gpio_data = {
@@ -132,12 +304,39 @@
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 };
 
+static struct twl4030_madc_platform_data ldp_madc_data = {
+	.irq_line	= 1,
+};
+
+static struct regulator_consumer_supply ldp_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data ldp_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &ldp_vmmc1_supply,
+};
+
 static struct twl4030_platform_data ldp_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
 
 	/* platform_data for children goes here */
+	.madc		= &ldp_madc_data,
+	.usb		= &ldp_usb_data,
+	.vmmc1		= &ldp_vmmc1,
 	.gpio		= &ldp_gpio_data,
+	.keypad		= &ldp_kp_twl4030_data,
 };
 
 static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = {
@@ -168,15 +367,29 @@
 	{}	/* Terminator */
 };
 
+static struct platform_device *ldp_devices[] __initdata = {
+	&ldp_smsc911x_device,
+	&ldp_lcd_device,
+	&ldp_gpio_keys_device,
+};
+
 static void __init omap_ldp_init(void)
 {
 	omap_i2c_init();
 	platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
 	omap_board_config = ldp_config;
 	omap_board_config_size = ARRAY_SIZE(ldp_config);
+	ts_gpio = 54;
+	ldp_spi_board_info[0].irq = gpio_to_irq(ts_gpio);
+	spi_register_board_info(ldp_spi_board_info,
+				ARRAY_SIZE(ldp_spi_board_info));
+	ads7846_dev_init();
 	omap_serial_init();
-	twl4030_mmc_init(mmc);
 	usb_musb_init();
+
+	twl4030_mmc_init(mmc);
+	/* link regulators to MMC adapters */
+	ldp_vmmc1_supply.dev = mmc[0].dev;
 }
 
 static void __init omap_ldp_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-omap3beagle.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-omap3beagle.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-omap3beagle.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-omap3beagle.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 
+#include <linux/regulator/machine.h>
 #include <linux/i2c/twl4030.h>
 
 #include <mach/hardware.h>
@@ -105,6 +106,8 @@
 	.resource	= &omap3beagle_nand_resource,
 };
 
+#include "sdram-micron-mt46h32m32lf-6.h"
+
 static struct omap_uart_config omap3_beagle_uart_config __initdata = {
 	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
 };
@@ -118,6 +121,23 @@
 	{}	/* Terminator */
 };
 
+static struct platform_device omap3_beagle_lcd_device = {
+	.name		= "omap3beagle_lcd",
+	.id		= -1,
+};
+
+static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
+static struct regulator_consumer_supply beagle_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+static struct regulator_consumer_supply beagle_vsim_supply = {
+	.supply			= "vmmc_aux",
+};
+
 static struct gpio_led gpio_leds[];
 
 static int beagle_twl_gpio_setup(struct device *dev,
@@ -128,6 +148,10 @@
 	mmc[0].gpio_cd = gpio + 0;
 	twl4030_mmc_init(mmc);
 
+	/* link regulators to MMC adapters */
+	beagle_vmmc1_supply.dev = mmc[0].dev;
+	beagle_vsim_supply.dev = mmc[0].dev;
+
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
 	 */
@@ -156,12 +180,85 @@
 	.setup		= beagle_twl_gpio_setup,
 };
 
+static struct regulator_consumer_supply beagle_vdac_supply = {
+	.supply		= "vdac",
+	.dev		= &omap3_beagle_lcd_device.dev,
+};
+
+static struct regulator_consumer_supply beagle_vdvi_supply = {
+	.supply		= "vdvi",
+	.dev		= &omap3_beagle_lcd_device.dev,
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data beagle_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vmmc1_supply,
+};
+
+/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+static struct regulator_init_data beagle_vsim = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 3000000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vsim_supply,
+};
+
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data beagle_vdac = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vdac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data beagle_vpll2 = {
+	.constraints = {
+		.name			= "VDVI",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vdvi_supply,
+};
+
 static struct twl4030_platform_data beagle_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
 
 	/* platform_data for children goes here */
 	.gpio		= &beagle_gpio_data,
+	.vmmc1		= &beagle_vmmc1,
+	.vsim		= &beagle_vsim,
+	.vdac		= &beagle_vdac,
+	.vpll2		= &beagle_vpll2,
 };
 
 static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
@@ -185,7 +282,8 @@
 
 static void __init omap3_beagle_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+			     mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -193,15 +291,6 @@
 	omap_gpio_init();
 }
 
-static struct platform_device omap3_beagle_lcd_device = {
-	.name		= "omap3beagle_lcd",
-	.id		= -1,
-};
-
-static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
-
 static struct gpio_led gpio_leds[] = {
 	{
 		.name			= "beagleboard::usr0",
@@ -320,6 +409,10 @@
 
 	usb_musb_init();
 	omap3beagle_flash_init();
+
+	/* Ensure SDRC pins are mux'd for self-refresh */
+	omap_cfg_reg(H16_34XX_SDRC_CKE0);
+	omap_cfg_reg(H17_34XX_SDRC_CKE1);
 }
 
 static void __init omap3_beagle_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-omap3evm.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-omap3evm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-omap3evm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-omap3evm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,334 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3evm.c
+ *
+ * Copyright (C) 2008 Texas Instruments
+ *
+ * Modified from mach-omap2/board-3430sdp.c
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/i2c/twl4030.h>
+#include <linux/usb/otg.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/board.h>
+#include <mach/mux.h>
+#include <mach/usb.h>
+#include <mach/common.h>
+#include <mach/mcspi.h>
+#include <mach/keypad.h>
+
+#include "sdram-micron-mt46h32m32lf-6.h"
+#include "mmc-twl4030.h"
+
+#define OMAP3_EVM_TS_GPIO	175
+
+#define OMAP3EVM_ETHR_START	0x2c000000
+#define OMAP3EVM_ETHR_SIZE	1024
+#define OMAP3EVM_ETHR_GPIO_IRQ	176
+#define OMAP3EVM_SMC911X_CS	5
+
+static struct resource omap3evm_smc911x_resources[] = {
+	[0] =	{
+		.start	= OMAP3EVM_ETHR_START,
+		.end	= (OMAP3EVM_ETHR_START + OMAP3EVM_ETHR_SIZE - 1),
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] =	{
+		.start	= OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ),
+		.end	= OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device omap3evm_smc911x_device = {
+	.name		= "smc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(omap3evm_smc911x_resources),
+	.resource	= &omap3evm_smc911x_resources[0],
+};
+
+static inline void __init omap3evm_init_smc911x(void)
+{
+	int eth_cs;
+	struct clk *l3ck;
+	unsigned int rate;
+
+	eth_cs = OMAP3EVM_SMC911X_CS;
+
+	l3ck = clk_get(NULL, "l3_ck");
+	if (IS_ERR(l3ck))
+		rate = 100000000;
+	else
+		rate = clk_get_rate(l3ck);
+
+	if (gpio_request(OMAP3EVM_ETHR_GPIO_IRQ, "SMC911x irq") < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for smc911x IRQ\n",
+			OMAP3EVM_ETHR_GPIO_IRQ);
+		return;
+	}
+
+	gpio_direction_input(OMAP3EVM_ETHR_GPIO_IRQ);
+}
+
+static struct omap_uart_config omap3_evm_uart_config __initdata = {
+	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct twl4030_hsmmc_info mmc[] = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= 63,
+	},
+	{}	/* Terminator */
+};
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "omap3evm::ledb",
+		/* normally not visible (board underside) */
+		.default_trigger	= "default-on",
+		.gpio			= -EINVAL,	/* gets replaced */
+		.active_low		= true,
+	},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gpio_led_info,
+	},
+};
+
+
+static int omap3evm_twl_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+	omap_cfg_reg(L8_34XX_GPIO63);
+	mmc[0].gpio_cd = gpio + 0;
+	twl4030_mmc_init(mmc);
+
+	/*
+	 * Most GPIOs are for USB OTG.  Some are mostly sent to
+	 * the P2 connector; notably LEDA for the LCD backlight.
+	 */
+
+	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+
+	platform_device_register(&leds_gpio);
+
+	return 0;
+}
+
+static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.use_leds	= true,
+	.setup		= omap3evm_twl_gpio_setup,
+};
+
+static struct twl4030_usb_data omap3evm_usb_data = {
+	.usb_mode	= T2_USB_MODE_ULPI,
+};
+
+static int omap3evm_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_A),
+	KEY(0, 3, KEY_B),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_E),
+	KEY(1, 3, KEY_F),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_I),
+	KEY(2, 2, KEY_J),
+	KEY(2, 3, KEY_K),
+	KEY(3, 0, KEY_M),
+	KEY(3, 1, KEY_N),
+	KEY(3, 2, KEY_O),
+	KEY(3, 3, KEY_P)
+};
+
+static struct twl4030_keypad_data omap3evm_kp_data = {
+	.rows		= 4,
+	.cols		= 4,
+	.keymap		= omap3evm_keymap,
+	.keymapsize	= ARRAY_SIZE(omap3evm_keymap),
+	.rep		= 1,
+};
+
+static struct twl4030_madc_platform_data omap3evm_madc_data = {
+	.irq_line	= 1,
+};
+
+static struct twl4030_platform_data omap3evm_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.keypad		= &omap3evm_kp_data,
+	.madc		= &omap3evm_madc_data,
+	.usb		= &omap3evm_usb_data,
+	.gpio		= &omap3evm_gpio_data,
+};
+
+static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &omap3evm_twldata,
+	},
+};
+
+static int __init omap3_evm_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, omap3evm_i2c_boardinfo,
+			ARRAY_SIZE(omap3evm_i2c_boardinfo));
+	omap_register_i2c_bus(2, 400, NULL, 0);
+	omap_register_i2c_bus(3, 400, NULL, 0);
+	return 0;
+}
+
+static struct platform_device omap3_evm_lcd_device = {
+	.name		= "omap3evm_lcd",
+	.id		= -1,
+};
+
+static struct omap_lcd_config omap3_evm_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
+static void ads7846_dev_init(void)
+{
+	if (gpio_request(OMAP3_EVM_TS_GPIO, "ADS7846 pendown") < 0)
+		printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
+
+	gpio_direction_input(OMAP3_EVM_TS_GPIO);
+
+	omap_set_gpio_debounce(OMAP3_EVM_TS_GPIO, 1);
+	omap_set_gpio_debounce_time(OMAP3_EVM_TS_GPIO, 0xa);
+}
+
+static int ads7846_get_pendown_state(void)
+{
+	return !gpio_get_value(OMAP3_EVM_TS_GPIO);
+}
+
+struct ads7846_platform_data ads7846_config = {
+	.x_max			= 0x0fff,
+	.y_max			= 0x0fff,
+	.x_plate_ohms		= 180,
+	.pressure_max		= 255,
+	.debounce_max		= 10,
+	.debounce_tol		= 3,
+	.debounce_rep		= 1,
+	.get_pendown_state	= ads7846_get_pendown_state,
+	.keep_vref_on		= 1,
+	.settle_delay_usecs	= 150,
+};
+
+static struct omap2_mcspi_device_config ads7846_mcspi_config = {
+	.turbo_mode	= 0,
+	.single_channel	= 1,	/* 0: slave, 1: master */
+};
+
+struct spi_board_info omap3evm_spi_board_info[] = {
+	[0] = {
+		.modalias		= "ads7846",
+		.bus_num		= 1,
+		.chip_select		= 0,
+		.max_speed_hz		= 1500000,
+		.controller_data	= &ads7846_mcspi_config,
+		.irq			= OMAP_GPIO_IRQ(OMAP3_EVM_TS_GPIO),
+		.platform_data		= &ads7846_config,
+	},
+};
+
+static void __init omap3_evm_init_irq(void)
+{
+	omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL);
+	omap_init_irq();
+	omap_gpio_init();
+	omap3evm_init_smc911x();
+}
+
+static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
+	{ OMAP_TAG_UART,	&omap3_evm_uart_config },
+	{ OMAP_TAG_LCD,		&omap3_evm_lcd_config },
+};
+
+static struct platform_device *omap3_evm_devices[] __initdata = {
+	&omap3_evm_lcd_device,
+	&omap3evm_smc911x_device,
+};
+
+static void __init omap3_evm_init(void)
+{
+	omap3_evm_i2c_init();
+
+	platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices));
+	omap_board_config = omap3_evm_config;
+	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
+
+	spi_register_board_info(omap3evm_spi_board_info,
+				ARRAY_SIZE(omap3evm_spi_board_info));
+
+	omap_serial_init();
+#ifdef CONFIG_NOP_USB_XCEIV
+	/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
+	usb_nop_xceiv_register();
+#endif
+	usb_musb_init();
+	ads7846_dev_init();
+}
+
+static void __init omap3_evm_map_io(void)
+{
+	omap2_set_globals_343x();
+	omap2_map_common_io();
+}
+
+MACHINE_START(OMAP3EVM, "OMAP3 EVM")
+	/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_evm_map_io,
+	.init_irq	= omap3_evm_init_irq,
+	.init_machine	= omap3_evm_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-omap3pandora.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-omap3pandora.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-omap3pandora.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-omap3pandora.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,7 +23,11 @@
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/regulator/machine.h>
 #include <linux/i2c/twl4030.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,11 +39,155 @@
 #include <mach/hardware.h>
 #include <mach/mcspi.h>
 #include <mach/usb.h>
+#include <mach/keypad.h>
+#include <mach/mux.h>
 
+#include "sdram-micron-mt46h32m32lf-6.h"
 #include "mmc-twl4030.h"
 
 #define OMAP3_PANDORA_TS_GPIO		94
 
+/* hardware debounce: (value + 1) * 31us */
+#define GPIO_DEBOUNCE_TIME		127
+
+static struct gpio_led pandora_gpio_leds[] = {
+	{
+		.name			= "pandora::sd1",
+		.default_trigger	= "mmc0",
+		.gpio			= 128,
+	}, {
+		.name			= "pandora::sd2",
+		.default_trigger	= "mmc1",
+		.gpio			= 129,
+	}, {
+		.name			= "pandora::bluetooth",
+		.gpio			= 158,
+	}, {
+		.name			= "pandora::wifi",
+		.gpio			= 159,
+	},
+};
+
+static struct gpio_led_platform_data pandora_gpio_led_data = {
+	.leds		= pandora_gpio_leds,
+	.num_leds	= ARRAY_SIZE(pandora_gpio_leds),
+};
+
+static struct platform_device pandora_leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &pandora_gpio_led_data,
+	},
+};
+
+#define GPIO_BUTTON(gpio_num, ev_type, ev_code, act_low, descr)	\
+{								\
+	.gpio		= gpio_num,				\
+	.type		= ev_type,				\
+	.code		= ev_code,				\
+	.active_low	= act_low,				\
+	.desc		= "btn " descr,				\
+}
+
+#define GPIO_BUTTON_LOW(gpio_num, event_code, description)	\
+	GPIO_BUTTON(gpio_num, EV_KEY, event_code, 1, description)
+
+static struct gpio_keys_button pandora_gpio_keys[] = {
+	GPIO_BUTTON_LOW(110,	KEY_UP,		"up"),
+	GPIO_BUTTON_LOW(103,	KEY_DOWN,	"down"),
+	GPIO_BUTTON_LOW(96,	KEY_LEFT,	"left"),
+	GPIO_BUTTON_LOW(98,	KEY_RIGHT,	"right"),
+	GPIO_BUTTON_LOW(111,	BTN_A,		"a"),
+	GPIO_BUTTON_LOW(106,	BTN_B,		"b"),
+	GPIO_BUTTON_LOW(109,	BTN_X,		"x"),
+	GPIO_BUTTON_LOW(101,	BTN_Y,		"y"),
+	GPIO_BUTTON_LOW(102,	BTN_TL,		"l"),
+	GPIO_BUTTON_LOW(97,	BTN_TL2,	"l2"),
+	GPIO_BUTTON_LOW(105,	BTN_TR,		"r"),
+	GPIO_BUTTON_LOW(107,	BTN_TR2,	"r2"),
+	GPIO_BUTTON_LOW(104,	KEY_LEFTCTRL,	"ctrl"),
+	GPIO_BUTTON_LOW(99,	KEY_MENU,	"menu"),
+	GPIO_BUTTON_LOW(176,	KEY_COFFEE,	"hold"),
+	GPIO_BUTTON(100, EV_KEY, KEY_LEFTALT, 0, "alt"),
+	GPIO_BUTTON(108, EV_SW, SW_LID, 1, "lid"),
+};
+
+static struct gpio_keys_platform_data pandora_gpio_key_info = {
+	.buttons	= pandora_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(pandora_gpio_keys),
+};
+
+static struct platform_device pandora_keys_gpio = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &pandora_gpio_key_info,
+	},
+};
+
+static void __init pandora_keys_gpio_init(void)
+{
+	/* set debounce time for GPIO banks 4 and 6 */
+	omap_set_gpio_debounce_time(32 * 3, GPIO_DEBOUNCE_TIME);
+	omap_set_gpio_debounce_time(32 * 5, GPIO_DEBOUNCE_TIME);
+}
+
+static int pandora_keypad_map[] = {
+	/* col, row, code */
+	KEY(0, 0, KEY_9),
+	KEY(0, 1, KEY_0),
+	KEY(0, 2, KEY_BACKSPACE),
+	KEY(0, 3, KEY_O),
+	KEY(0, 4, KEY_P),
+	KEY(0, 5, KEY_K),
+	KEY(0, 6, KEY_L),
+	KEY(0, 7, KEY_ENTER),
+	KEY(1, 0, KEY_8),
+	KEY(1, 1, KEY_7),
+	KEY(1, 2, KEY_6),
+	KEY(1, 3, KEY_5),
+	KEY(1, 4, KEY_4),
+	KEY(1, 5, KEY_3),
+	KEY(1, 6, KEY_2),
+	KEY(1, 7, KEY_1),
+	KEY(2, 0, KEY_I),
+	KEY(2, 1, KEY_U),
+	KEY(2, 2, KEY_Y),
+	KEY(2, 3, KEY_T),
+	KEY(2, 4, KEY_R),
+	KEY(2, 5, KEY_E),
+	KEY(2, 6, KEY_W),
+	KEY(2, 7, KEY_Q),
+	KEY(3, 0, KEY_J),
+	KEY(3, 1, KEY_H),
+	KEY(3, 2, KEY_G),
+	KEY(3, 3, KEY_F),
+	KEY(3, 4, KEY_D),
+	KEY(3, 5, KEY_S),
+	KEY(3, 6, KEY_A),
+	KEY(3, 7, KEY_LEFTSHIFT),
+	KEY(4, 0, KEY_N),
+	KEY(4, 1, KEY_B),
+	KEY(4, 2, KEY_V),
+	KEY(4, 3, KEY_C),
+	KEY(4, 4, KEY_X),
+	KEY(4, 5, KEY_Z),
+	KEY(4, 6, KEY_DOT),
+	KEY(4, 7, KEY_COMMA),
+	KEY(5, 0, KEY_M),
+	KEY(5, 1, KEY_SPACE),
+	KEY(5, 2, KEY_FN),
+};
+
+static struct twl4030_keypad_data pandora_kp_data = {
+	.rows		= 8,
+	.cols		= 6,
+	.keymap		= pandora_keypad_map,
+	.keymapsize	= ARRAY_SIZE(pandora_keypad_map),
+	.rep		= 1,
+};
+
 static struct twl4030_hsmmc_info omap3pandora_mmc[] = {
 	{
 		.mmc		= 1,
@@ -69,6 +217,14 @@
 	.enabled_uarts	= (1 << 2), /* UART3 */
 };
 
+static struct regulator_consumer_supply pandora_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+static struct regulator_consumer_supply pandora_vmmc2_supply = {
+	.supply			= "vmmc",
+};
+
 static int omap3pandora_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
@@ -77,6 +233,10 @@
 	omap3pandora_mmc[1].gpio_cd = gpio + 1;
 	twl4030_mmc_init(omap3pandora_mmc);
 
+	/* link regulators to MMC adapters */
+	pandora_vmmc1_supply.dev = omap3pandora_mmc[0].dev;
+	pandora_vmmc2_supply.dev = omap3pandora_mmc[1].dev;
+
 	return 0;
 }
 
@@ -87,6 +247,36 @@
 	.setup		= omap3pandora_twl_gpio_setup,
 };
 
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data pandora_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &pandora_vmmc1_supply,
+};
+
+/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
+static struct regulator_init_data pandora_vmmc2 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &pandora_vmmc2_supply,
+};
+
 static struct twl4030_usb_data omap3pandora_usb_data = {
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
@@ -96,6 +286,9 @@
 	.irq_end	= TWL4030_IRQ_END,
 	.gpio		= &omap3pandora_gpio_data,
 	.usb		= &omap3pandora_usb_data,
+	.vmmc1		= &pandora_vmmc1,
+	.vmmc2		= &pandora_vmmc2,
+	.keypad		= &pandora_kp_data,
 };
 
 static struct i2c_board_info __initdata omap3pandora_i2c_boardinfo[] = {
@@ -118,7 +311,8 @@
 
 static void __init omap3pandora_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+			     mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -188,6 +382,8 @@
 
 static struct platform_device *omap3pandora_devices[] __initdata = {
 	&omap3pandora_lcd_device,
+	&pandora_leds_gpio,
+	&pandora_keys_gpio,
 };
 
 static void __init omap3pandora_init(void)
@@ -201,7 +397,12 @@
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap3pandora_ads7846_init();
+	pandora_keys_gpio_init();
 	usb_musb_init();
+
+	/* Ensure SDRC pins are mux'd for self-refresh */
+	omap_cfg_reg(H16_34XX_SDRC_CKE0);
+	omap_cfg_reg(H17_34XX_SDRC_CKE1);
 }
 
 static void __init omap3pandora_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-overo.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-overo.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-overo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-overo.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/i2c/twl4030.h>
+#include <linux/regulator/machine.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -43,12 +44,15 @@
 #include <mach/gpmc.h>
 #include <mach/hardware.h>
 #include <mach/nand.h>
+#include <mach/mux.h>
 #include <mach/usb.h>
 
+#include "sdram-micron-mt46h32m32lf-6.h"
 #include "mmc-twl4030.h"
 
 #define OVERO_GPIO_BT_XGATE	15
 #define OVERO_GPIO_W2W_NRESET	16
+#define OVERO_GPIO_PENDOWN	114
 #define OVERO_GPIO_BT_NRESET	164
 #define OVERO_GPIO_USBH_CPEN	168
 #define OVERO_GPIO_USBH_NRESET	183
@@ -144,7 +148,7 @@
 	.name		= "smsc911x",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(overo_smsc911x_resources),
-	.resource	= &overo_smsc911x_resources,
+	.resource	= overo_smsc911x_resources,
 	.dev		= {
 		.platform_data = &overo_smsc911x_config,
 	},
@@ -271,21 +275,76 @@
 	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
 };
 
+static struct twl4030_hsmmc_info mmc[] = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{
+		.mmc		= 2,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+		.transceiver	= true,
+		.ocr_mask	= 0x00100000,	/* 3.3V */
+	},
+	{}	/* Terminator */
+};
+
+static struct regulator_consumer_supply overo_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+static int overo_twl_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	twl4030_mmc_init(mmc);
+
+	overo_vmmc1_supply.dev = mmc[0].dev;
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data overo_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.setup		= overo_twl_gpio_setup,
+};
+
+static struct twl4030_usb_data overo_usb_data = {
+	.usb_mode	= T2_USB_MODE_ULPI,
+};
+
+static struct regulator_init_data overo_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &overo_vmmc1_supply,
 };
 
+/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
+
 static struct twl4030_platform_data overo_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
 	.gpio		= &overo_gpio_data,
+	.usb		= &overo_usb_data,
+	.vmmc1		= &overo_vmmc1,
 };
 
 static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
 	{
-		I2C_BOARD_INFO("twl4030", 0x48),
+		I2C_BOARD_INFO("tps65950", 0x48),
 		.flags = I2C_CLIENT_WAKE,
 		.irq = INT_34XX_SYS_NIRQ,
 		.platform_data = &overo_twldata,
@@ -303,7 +362,8 @@
 
 static void __init overo_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+			     mt46h32m32lf6_sdrc_params);
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -326,23 +386,6 @@
 	&overo_lcd_device,
 };
 
-static struct twl4030_hsmmc_info mmc[] __initdata = {
-	{
-		.mmc		= 1,
-		.wires		= 4,
-		.gpio_cd	= -EINVAL,
-		.gpio_wp	= -EINVAL,
-	},
-	{
-		.mmc		= 2,
-		.wires		= 4,
-		.gpio_cd	= -EINVAL,
-		.gpio_wp	= -EINVAL,
-		.transceiver	= true,
-	},
-	{}	/* Terminator */
-};
-
 static void __init overo_init(void)
 {
 	overo_i2c_init();
@@ -350,12 +393,15 @@
 	omap_board_config = overo_config;
 	omap_board_config_size = ARRAY_SIZE(overo_config);
 	omap_serial_init();
-	twl4030_mmc_init(mmc);
 	overo_flash_init();
 	usb_musb_init();
 	overo_ads7846_init();
 	overo_init_smsc911x();
 
+	/* Ensure SDRC pins are mux'd for self-refresh */
+	omap_cfg_reg(H16_34XX_SDRC_CKE0);
+	omap_cfg_reg(H17_34XX_SDRC_CKE1);
+
 	if ((gpio_request(OVERO_GPIO_W2W_NRESET,
 			  "OVERO_GPIO_W2W_NRESET") == 0) &&
 	    (gpio_direction_output(OVERO_GPIO_W2W_NRESET, 1) == 0)) {
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-rx51.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-rx51.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-rx51.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-rx51.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,7 +61,7 @@
 
 static void __init rx51_init_irq(void)
 {
-	omap2_init_common_hw(NULL);
+	omap2_init_common_hw(NULL, NULL);
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -75,6 +75,10 @@
 	omap_serial_init();
 	usb_musb_init();
 	rx51_peripherals_init();
+
+	/* Ensure SDRC pins are mux'd for self-refresh */
+	omap_cfg_reg(H16_34XX_SDRC_CKE0);
+	omap_cfg_reg(H17_34XX_SDRC_CKE1);
 }
 
 static void __init rx51_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,30 +27,13 @@
 #include <mach/dma.h>
 #include <mach/gpmc.h>
 #include <mach/keypad.h>
+#include <mach/onenand.h>
+#include <mach/gpmc-smc91x.h>
 
 #include "mmc-twl4030.h"
 
-
-#define SMC91X_CS			1
-#define SMC91X_GPIO_IRQ			54
-#define SMC91X_GPIO_RESET		164
-#define SMC91X_GPIO_PWRDWN		86
-
-static struct resource rx51_smc91x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
-	},
-};
-
-static struct platform_device rx51_smc91x_device = {
-	.name		= "smc91x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(rx51_smc91x_resources),
-	.resource	= rx51_smc91x_resources,
-};
+#define SYSTEM_REV_B_USES_VAUX3	0x1699
+#define SYSTEM_REV_S_USES_VAUX3 0x8
 
 static int rx51_keymap[] = {
 	KEY(0, 0, KEY_Q),
@@ -107,98 +90,6 @@
 	.rep		= 1,
 };
 
-static struct platform_device *rx51_peripherals_devices[] = {
-	&rx51_smc91x_device,
-};
-
-/*
- * Timings are taken from smsc-lan91c96-ms.pdf
- */
-static int smc91x_init_gpmc(int cs)
-{
-	struct gpmc_timings t;
-	const int t2_r = 45;		/* t2 in Figure 12.10 */
-	const int t2_w = 30;		/* t2 in Figure 12.11 */
-	const int t3 = 15;		/* t3 in Figure 12.10 */
-	const int t5_r = 0;		/* t5 in Figure 12.10 */
-	const int t6_r = 45;		/* t6 in Figure 12.10 */
-	const int t6_w = 0;		/* t6 in Figure 12.11 */
-	const int t7_w = 15;		/* t7 in Figure 12.11 */
-	const int t15 = 12;		/* t15 in Figure 12.2 */
-	const int t20 = 185;		/* t20 in Figure 12.2 */
-
-	memset(&t, 0, sizeof(t));
-
-	t.cs_on = t15;
-	t.cs_rd_off = t3 + t2_r + t5_r;	/* Figure 12.10 */
-	t.cs_wr_off = t3 + t2_w + t6_w;	/* Figure 12.11 */
-	t.adv_on = t3;			/* Figure 12.10 */
-	t.adv_rd_off = t3 + t2_r;	/* Figure 12.10 */
-	t.adv_wr_off = t3 + t2_w;	/* Figure 12.11 */
-	t.oe_off = t3 + t2_r + t5_r;	/* Figure 12.10 */
-	t.oe_on = t.oe_off - t6_r;	/* Figure 12.10 */
-	t.we_off = t3 + t2_w + t6_w;	/* Figure 12.11 */
-	t.we_on = t.we_off - t7_w;	/* Figure 12.11 */
-	t.rd_cycle = t20;		/* Figure 12.2 */
-	t.wr_cycle = t20;		/* Figure 12.4 */
-	t.access = t3 + t2_r + t5_r;	/* Figure 12.10 */
-	t.wr_access = t3 + t2_w + t6_w;	/* Figure 12.11 */
-
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16);
-
-	return gpmc_cs_set_timings(cs, &t);
-}
-
-static void __init rx51_init_smc91x(void)
-{
-	unsigned long cs_mem_base;
-	int ret;
-
-	omap_cfg_reg(U8_34XX_GPIO54_DOWN);
-	omap_cfg_reg(G25_34XX_GPIO86_OUT);
-	omap_cfg_reg(H19_34XX_GPIO164_OUT);
-
-	if (gpmc_cs_request(SMC91X_CS, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		return;
-	}
-
-	rx51_smc91x_resources[0].start = cs_mem_base + 0x300;
-	rx51_smc91x_resources[0].end = cs_mem_base + 0x30f;
-
-	smc91x_init_gpmc(SMC91X_CS);
-
-	if (gpio_request(SMC91X_GPIO_IRQ, "SMC91X irq") < 0)
-		goto free1;
-
-	gpio_direction_input(SMC91X_GPIO_IRQ);
-	rx51_smc91x_resources[1].start = gpio_to_irq(SMC91X_GPIO_IRQ);
-
-	ret = gpio_request(SMC91X_GPIO_PWRDWN, "SMC91X powerdown");
-	if (ret)
-		goto free2;
-	gpio_direction_output(SMC91X_GPIO_PWRDWN, 0);
-
-	ret = gpio_request(SMC91X_GPIO_RESET, "SMC91X reset");
-	if (ret)
-		goto free3;
-	gpio_direction_output(SMC91X_GPIO_RESET, 0);
-	gpio_set_value(SMC91X_GPIO_RESET, 1);
-	msleep(100);
-	gpio_set_value(SMC91X_GPIO_RESET, 0);
-
-	return;
-
-free3:
-	gpio_free(SMC91X_GPIO_PWRDWN);
-free2:
-	gpio_free(SMC91X_GPIO_IRQ);
-free1:
-	gpmc_cs_free(SMC91X_CS);
-
-	printk(KERN_ERR "Could not initialize smc91x\n");
-}
-
 static struct twl4030_madc_platform_data rx51_madc_data = {
 	.irq_line		= 1,
 };
@@ -259,7 +150,7 @@
 };
 
 /* VAUX3 - adds more power to VIO_18 rail */
-static struct regulator_init_data rx51_vaux3 = {
+static struct regulator_init_data rx51_vaux3_cam = {
 	.constraints = {
 		.name			= "VCAM_DIG_18",
 		.min_uV			= 1800000,
@@ -272,6 +163,22 @@
 	},
 };
 
+static struct regulator_init_data rx51_vaux3_mmc = {
+	.constraints = {
+		.name			= "VMMC2_30",
+		.min_uV			= 2800000,
+		.max_uV			= 3000000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &rx51_vmmc2_supply,
+};
+
 static struct regulator_init_data rx51_vaux4 = {
 	.constraints = {
 		.name			= "VCAM_ANA_28",
@@ -371,6 +278,10 @@
 	.setup			= rx51_twlgpio_setup,
 };
 
+static struct twl4030_usb_data rx51_usb_data = {
+	.usb_mode		= T2_USB_MODE_ULPI,
+};
+
 static struct twl4030_platform_data rx51_twldata = {
 	.irq_base		= TWL4030_IRQ_BASE,
 	.irq_end		= TWL4030_IRQ_END,
@@ -379,13 +290,12 @@
 	.gpio			= &rx51_gpio_data,
 	.keypad			= &rx51_kp_data,
 	.madc			= &rx51_madc_data,
+	.usb			= &rx51_usb_data,
 
 	.vaux1			= &rx51_vaux1,
 	.vaux2			= &rx51_vaux2,
-	.vaux3			= &rx51_vaux3,
 	.vaux4			= &rx51_vaux4,
 	.vmmc1			= &rx51_vmmc1,
-	.vmmc2			= &rx51_vmmc2,
 	.vsim			= &rx51_vsim,
 	.vdac			= &rx51_vdac,
 };
@@ -401,6 +311,13 @@
 
 static int __init rx51_i2c_init(void)
 {
+	if ((system_rev >= SYSTEM_REV_S_USES_VAUX3 && system_rev < 0x100) ||
+	    system_rev >= SYSTEM_REV_B_USES_VAUX3)
+		rx51_twldata.vaux3 = &rx51_vaux3_mmc;
+	else {
+		rx51_twldata.vaux3 = &rx51_vaux3_cam;
+		rx51_twldata.vmmc2 = &rx51_vmmc2;
+	}
 	omap_register_i2c_bus(1, 2600, rx51_peripherals_i2c_board_info_1,
 			ARRAY_SIZE(rx51_peripherals_i2c_board_info_1));
 	omap_register_i2c_bus(2, 100, NULL, 0);
@@ -408,12 +325,95 @@
 	return 0;
 }
 
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+
+static struct mtd_partition onenand_partitions[] = {
+	{
+		.name           = "bootloader",
+		.offset         = 0,
+		.size           = 0x20000,
+		.mask_flags     = MTD_WRITEABLE,	/* Force read-only */
+	},
+	{
+		.name           = "config",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 0x60000,
+	},
+	{
+		.name           = "log",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 0x40000,
+	},
+	{
+		.name           = "kernel",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 0x200000,
+	},
+	{
+		.name           = "initfs",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 0x200000,
+	},
+	{
+		.name           = "rootfs",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = MTDPART_SIZ_FULL,
+	},
+};
+
+static struct omap_onenand_platform_data board_onenand_data = {
+	.cs		= 0,
+	.gpio_irq	= 65,
+	.parts		= onenand_partitions,
+	.nr_parts	= ARRAY_SIZE(onenand_partitions),
+	.flags		= ONENAND_SYNC_READWRITE,
+};
+
+static void __init board_onenand_init(void)
+{
+	gpmc_onenand_init(&board_onenand_data);
+}
+
+#else
+
+static inline void board_onenand_init(void)
+{
+}
+
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+
+static struct omap_smc91x_platform_data board_smc91x_data = {
+	.cs		= 1,
+	.gpio_irq	= 54,
+	.gpio_pwrdwn	= 86,
+	.gpio_reset	= 164,
+	.flags		= GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHLEVEL,
+};
+
+static void __init board_smc91x_init(void)
+{
+	omap_cfg_reg(U8_34XX_GPIO54_DOWN);
+	omap_cfg_reg(G25_34XX_GPIO86_OUT);
+	omap_cfg_reg(H19_34XX_GPIO164_OUT);
+
+	gpmc_smc91x_init(&board_smc91x_data);
+}
+
+#else
+
+static inline void board_smc91x_init(void)
+{
+}
+
+#endif
 
 void __init rx51_peripherals_init(void)
 {
-	platform_add_devices(rx51_peripherals_devices,
-				ARRAY_SIZE(rx51_peripherals_devices));
 	rx51_i2c_init();
-	rx51_init_smc91x();
+	board_onenand_init();
+	board_smc91x_init();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-zoom2.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-zoom2.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-zoom2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-zoom2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2009 Texas Instruments Inc.
+ * Mikkel Christensen <mlc@ti.com>
+ *
+ * Modified from mach-omap2/board-ldp.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/i2c/twl4030.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/common.h>
+#include <mach/usb.h>
+
+#include "mmc-twl4030.h"
+
+static void __init omap_zoom2_init_irq(void)
+{
+	omap2_init_common_hw(NULL, NULL);
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+static struct omap_uart_config zoom2_uart_config __initdata = {
+	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_board_config_kernel zoom2_config[] __initdata = {
+	{ OMAP_TAG_UART,	&zoom2_uart_config },
+};
+
+static struct twl4030_gpio_platform_data zoom2_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+};
+
+static struct twl4030_platform_data zoom2_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.gpio		= &zoom2_gpio_data,
+};
+
+static struct i2c_board_info __initdata zoom2_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags		= I2C_CLIENT_WAKE,
+		.irq		= INT_34XX_SYS_NIRQ,
+		.platform_data	= &zoom2_twldata,
+	},
+};
+
+static int __init omap_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, zoom2_i2c_boardinfo,
+			ARRAY_SIZE(zoom2_i2c_boardinfo));
+	omap_register_i2c_bus(2, 400, NULL, 0);
+	omap_register_i2c_bus(3, 400, NULL, 0);
+	return 0;
+}
+
+static struct twl4030_hsmmc_info mmc[] __initdata = {
+	{
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{}	/* Terminator */
+};
+
+extern int __init omap_zoom2_debugboard_init(void);
+
+static void __init omap_zoom2_init(void)
+{
+	omap_i2c_init();
+	omap_board_config = zoom2_config;
+	omap_board_config_size = ARRAY_SIZE(zoom2_config);
+	omap_serial_init();
+	omap_zoom2_debugboard_init();
+	twl4030_mmc_init(mmc);
+	usb_musb_init();
+}
+
+static void __init omap_zoom2_map_io(void)
+{
+	omap2_set_globals_343x();
+	omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= omap_zoom2_map_io,
+	.init_irq	= omap_zoom2_init_irq,
+	.init_machine	= omap_zoom2_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-zoom-debugboard.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-zoom-debugboard.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/board-zoom-debugboard.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/board-zoom-debugboard.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 Texas Instruments Inc.
+ * Mikkel Christensen <mlc@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/serial_8250.h>
+#include <linux/smsc911x.h>
+
+#include <mach/gpmc.h>
+
+#define ZOOM2_SMSC911X_CS	7
+#define ZOOM2_SMSC911X_GPIO	158
+#define ZOOM2_QUADUART_CS	3
+#define ZOOM2_QUADUART_GPIO	102
+#define QUART_CLK		1843200
+#define DEBUG_BASE		0x08000000
+#define ZOOM2_ETHR_START	DEBUG_BASE
+
+static struct resource zoom2_smsc911x_resources[] = {
+	[0] = {
+		.start	= ZOOM2_ETHR_START,
+		.end	= ZOOM2_ETHR_START + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	},
+};
+
+static struct smsc911x_platform_config zoom2_smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_32BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device zoom2_smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(zoom2_smsc911x_resources),
+	.resource	= zoom2_smsc911x_resources,
+	.dev		= {
+		.platform_data = &zoom2_smsc911x_config,
+	},
+};
+
+static inline void __init zoom2_init_smsc911x(void)
+{
+	int eth_cs;
+	unsigned long cs_mem_base;
+	int eth_gpio = 0;
+
+	eth_cs = ZOOM2_SMSC911X_CS;
+
+	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
+		printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n");
+		return;
+	}
+
+	zoom2_smsc911x_resources[0].start = cs_mem_base + 0x0;
+	zoom2_smsc911x_resources[0].end   = cs_mem_base + 0xff;
+
+	eth_gpio = ZOOM2_SMSC911X_GPIO;
+
+	zoom2_smsc911x_resources[1].start = OMAP_GPIO_IRQ(eth_gpio);
+
+	if (gpio_request(eth_gpio, "smsc911x irq") < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n",
+				eth_gpio);
+		return;
+	}
+	gpio_direction_input(eth_gpio);
+}
+
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.mapbase	= 0x10000000,
+		.irq		= OMAP_GPIO_IRQ(102),
+		.flags		= UPF_BOOT_AUTOCONF|UPF_IOREMAP|UPF_SHARE_IRQ,
+		.iotype		= UPIO_MEM,
+		.regshift	= 1,
+		.uartclk	= QUART_CLK,
+	}, {
+		.flags		= 0
+	}
+};
+
+static struct platform_device zoom2_debugboard_serial_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM1,
+	.dev			= {
+		.platform_data	= serial_platform_data,
+	},
+};
+
+static inline void __init zoom2_init_quaduart(void)
+{
+	int quart_cs;
+	unsigned long cs_mem_base;
+	int quart_gpio = 0;
+
+	quart_cs = ZOOM2_QUADUART_CS;
+
+	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
+		printk(KERN_ERR "Failed to request GPMC mem"
+				"for Quad UART(TL16CP754C)\n");
+		return;
+	}
+
+	quart_gpio = ZOOM2_QUADUART_GPIO;
+
+	if (gpio_request(quart_gpio, "TL16CP754C GPIO") < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for TL16CP754C\n",
+								quart_gpio);
+		return;
+	}
+	gpio_direction_input(quart_gpio);
+}
+
+static inline int omap_zoom2_debugboard_detect(void)
+{
+	int debug_board_detect = 0;
+
+	debug_board_detect = ZOOM2_SMSC911X_GPIO;
+
+	if (gpio_request(debug_board_detect, "Zoom2 debug board detect") < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for Zoom2 debug"
+		"board detect\n", debug_board_detect);
+		return 0;
+	}
+	gpio_direction_input(debug_board_detect);
+
+	if (!gpio_get_value(debug_board_detect)) {
+		gpio_free(debug_board_detect);
+		return 0;
+	}
+	return 1;
+}
+
+static struct platform_device *zoom2_devices[] __initdata = {
+	&zoom2_smsc911x_device,
+	&zoom2_debugboard_serial_device,
+};
+
+int __init omap_zoom2_debugboard_init(void)
+{
+	if (!omap_zoom2_debugboard_detect())
+		return 0;
+
+	zoom2_init_smsc911x();
+	zoom2_init_quaduart();
+	return platform_add_devices(zoom2_devices, ARRAY_SIZE(zoom2_devices));
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock24xx.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock24xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock24xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock24xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 
 #include <mach/clock.h>
 #include <mach/sram.h>
+#include <mach/prcm.h>
 #include <asm/div64.h>
 #include <asm/clkdev.h>
 
@@ -43,6 +44,18 @@
 static const struct clkops clkops_oscck;
 static const struct clkops clkops_fixed;
 
+static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
+					   void __iomem **idlest_reg,
+					   u8 *idlest_bit);
+
+/* 2430 I2CHS has non-standard IDLEST register */
+static const struct clkops clkops_omap2430_i2chs_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap2430_clk_i2chs_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+};
+
 #include "clock24xx.h"
 
 struct omap_clk {
@@ -233,11 +246,33 @@
 static struct clk *vclk;
 static struct clk *sclk;
 
+static void __iomem *prcm_clksrc_ctrl;
+
 /*-------------------------------------------------------------------------
  * Omap24xx specific clock functions
  *-------------------------------------------------------------------------*/
 
 /**
+ * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
+ * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE.  This custom function
+ * passes back the correct CM_IDLEST register address for I2CHS
+ * modules.  No return value.
+ */
+static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
+					   void __iomem **idlest_reg,
+					   u8 *idlest_bit)
+{
+	*idlest_reg = OMAP_CM_REGADDR(CORE_MOD, CM_IDLEST);
+	*idlest_bit = clk->enable_bit;
+}
+
+
+/**
  * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
  * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
  *
@@ -269,10 +304,9 @@
 {
 	u32 pcc;
 
-	pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
+	pcc = __raw_readl(prcm_clksrc_ctrl);
 
-	__raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
-		      OMAP24XX_PRCM_CLKSRC_CTRL);
+	__raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
 
 	return 0;
 }
@@ -281,10 +315,9 @@
 {
 	u32 pcc;
 
-	pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
+	pcc = __raw_readl(prcm_clksrc_ctrl);
 
-	__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK,
-		      OMAP24XX_PRCM_CLKSRC_CTRL);
+	__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
 }
 
 static const struct clkops clkops_oscck = {
@@ -325,8 +358,8 @@
 	else if (clk == &apll54_ck)
 		cval = OMAP24XX_ST_54M_APLL;
 
-	omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
-			    clk->name);
+	omap2_cm_wait_idlest(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
+			     clk->name);
 
 	/*
 	 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
@@ -654,7 +687,7 @@
 {
 	u32 div;
 
-	div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
+	div = __raw_readl(prcm_clksrc_ctrl);
 	div &= OMAP_SYSCLKDIV_MASK;
 	div >>= OMAP_SYSCLKDIV_SHIFT;
 
@@ -714,15 +747,18 @@
 	struct omap_clk *c;
 	u32 clkrate;
 
-	if (cpu_is_omap242x())
+	if (cpu_is_omap242x()) {
+		prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL;
 		cpu_mask = RATE_IN_242X;
-	else if (cpu_is_omap2430())
+	} else if (cpu_is_omap2430()) {
+		prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL;
 		cpu_mask = RATE_IN_243X;
+	}
 
 	clk_init(&omap2_clk_functions);
 
 	for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
-		clk_init_one(c->lk.clk);
+		clk_preinit(c->lk.clk);
 
 	osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
 	propagate_rate(&osc_ck);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock24xx.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock24xx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock24xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock24xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,17 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 
+/* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */
+#ifdef CONFIG_ARCH_OMAP2420
+#define OMAP_CM_REGADDR			OMAP2420_CM_REGADDR
+#define OMAP24XX_PRCM_CLKOUT_CTRL	OMAP2420_PRCM_CLKOUT_CTRL
+#define OMAP24XX_PRCM_CLKEMUL_CTRL	OMAP2420_PRCM_CLKEMUL_CTRL
+#else
+#define OMAP_CM_REGADDR			OMAP2430_CM_REGADDR
+#define OMAP24XX_PRCM_CLKOUT_CTRL	OMAP2430_PRCM_CLKOUT_CTRL
+#define OMAP24XX_PRCM_CLKEMUL_CTRL	OMAP2430_PRCM_CLKEMUL_CTRL
+#endif
+
 static unsigned long omap2_table_mpu_recalc(struct clk *clk);
 static int omap2_select_table_rate(struct clk *clk, unsigned long rate);
 static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
@@ -2326,7 +2337,7 @@
 
 static struct clk i2chs2_fck = {
 	.name		= "i2c_fck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2430_i2chs_wait,
 	.id		= 2,
 	.parent		= &func_96m_ck,
 	.clkdm_name	= "core_l4_clkdm",
@@ -2359,7 +2370,7 @@
 
 static struct clk i2chs1_fck = {
 	.name		= "i2c_fck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2430_i2chs_wait,
 	.id		= 1,
 	.parent		= &func_96m_ck,
 	.clkdm_name	= "core_l4_clkdm",
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock34xx.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock34xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock34xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock34xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP3-specific clock framework functions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Testing and integration fixes by Jouni Högander
@@ -41,6 +41,37 @@
 
 static const struct clkops clkops_noncore_dpll_ops;
 
+static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
+					    void __iomem **idlest_reg,
+					    u8 *idlest_bit);
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
+					    void __iomem **idlest_reg,
+					    u8 *idlest_bit);
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
+						    void __iomem **idlest_reg,
+						    u8 *idlest_bit);
+
+static const struct clkops clkops_omap3430es2_ssi_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_ssi_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+};
+
+static const struct clkops clkops_omap3430es2_hsotgusb_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+};
+
+static const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+};
+
 #include "clock34xx.h"
 
 struct omap_clk {
@@ -129,6 +160,9 @@
 	CLK(NULL,	"sgx_fck",	&sgx_fck,	CK_3430ES2),
 	CLK(NULL,	"sgx_ick",	&sgx_ick,	CK_3430ES2),
 	CLK(NULL,	"d2d_26m_fck",	&d2d_26m_fck,	CK_3430ES1),
+	CLK(NULL,	"modem_fck",	&modem_fck,	CK_343X),
+	CLK(NULL,	"sad2d_ick",	&sad2d_ick,	CK_343X),
+	CLK(NULL,	"mad2d_ick",	&mad2d_ick,	CK_343X),
 	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_343X),
 	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_343X),
 	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2),
@@ -154,10 +188,13 @@
 	CLK(NULL,	"fshostusb_fck", &fshostusb_fck, CK_3430ES1),
 	CLK(NULL,	"core_12m_fck",	&core_12m_fck,	CK_343X),
 	CLK("omap_hdq.0", "fck",	&hdq_fck,	CK_343X),
-	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck,	CK_343X),
-	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck,	CK_343X),
+	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es1,	CK_3430ES1),
+	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck_3430es2,	CK_3430ES2),
+	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es1,	CK_3430ES1),
+	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck_3430es2,	CK_3430ES2),
 	CLK(NULL,	"core_l3_ick",	&core_l3_ick,	CK_343X),
-	CLK("musb_hdrc",	"ick",	&hsotgusb_ick,	CK_343X),
+	CLK("musb_hdrc",	"ick",	&hsotgusb_ick_3430es1,	CK_3430ES1),
+	CLK("musb_hdrc",	"ick",	&hsotgusb_ick_3430es2,	CK_3430ES2),
 	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_343X),
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_343X),
 	CLK(NULL,	"security_l3_ick", &security_l3_ick, CK_343X),
@@ -190,18 +227,21 @@
 	CLK(NULL,	"mailboxes_ick", &mailboxes_ick, CK_343X),
 	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_343X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_343X),
-	CLK(NULL,	"ssi_ick",	&ssi_ick,	CK_343X),
+	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es1,	CK_3430ES1),
+	CLK(NULL,	"ssi_ick",	&ssi_ick_3430es2,	CK_3430ES2),
 	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_3430ES1),
 	CLK(NULL,	"security_l4_ick2", &security_l4_ick2, CK_343X),
 	CLK(NULL,	"aes1_ick",	&aes1_ick,	CK_343X),
 	CLK("omap_rng",	"ick",		&rng_ick,	CK_343X),
 	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_343X),
 	CLK(NULL,	"des1_ick",	&des1_ick,	CK_343X),
-	CLK("omapfb",	"dss1_fck",	&dss1_alwon_fck, CK_343X),
+	CLK("omapfb",	"dss1_fck",	&dss1_alwon_fck_3430es1, CK_3430ES1),
+	CLK("omapfb",	"dss1_fck",	&dss1_alwon_fck_3430es2, CK_3430ES2),
 	CLK("omapfb",	"tv_fck",	&dss_tv_fck,	CK_343X),
 	CLK("omapfb",	"video_fck",	&dss_96m_fck,	CK_343X),
 	CLK("omapfb",	"dss2_fck",	&dss2_alwon_fck, CK_343X),
-	CLK("omapfb",	"ick",		&dss_ick,	CK_343X),
+	CLK("omapfb",	"ick",		&dss_ick_3430es1,	CK_3430ES1),
+	CLK("omapfb",	"ick",		&dss_ick_3430es2,	CK_3430ES2),
 	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_343X),
 	CLK(NULL,	"cam_ick",	&cam_ick,	CK_343X),
 	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_343X),
@@ -281,6 +321,89 @@
 
 #define MAX_DPLL_WAIT_TRIES		1000000
 
+#define MIN_SDRC_DLL_LOCK_FREQ		83000000
+
+#define CYCLES_PER_MHZ			1000000
+
+/* Scale factor for fixed-point arith in omap3_core_dpll_m2_set_rate() */
+#define SDRC_MPURATE_SCALE		8
+
+/* 2^SDRC_MPURATE_BASE_SHIFT: MPU MHz that SDRC_MPURATE_LOOPS is defined for */
+#define SDRC_MPURATE_BASE_SHIFT		9
+
+/*
+ * SDRC_MPURATE_LOOPS: Number of MPU loops to execute at
+ * 2^MPURATE_BASE_SHIFT MHz for SDRC to stabilize
+ */
+#define SDRC_MPURATE_LOOPS		96
+
+/**
+ * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
+ * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
+					    void __iomem **idlest_reg,
+					    u8 *idlest_bit)
+{
+	u32 r;
+
+	r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+	*idlest_reg = (__force void __iomem *)r;
+	*idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
+}
+
+/**
+ * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
+ * target IDLEST bits.  For our purposes, we are concerned with the
+ * target IDLEST bits, which exist at a different bit position than
+ * the *CLKEN bit position for these modules (DSS and USBHOST) (The
+ * default find_idlest code assumes that they are at the same
+ * position.)  No return value.
+ */
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
+						    void __iomem **idlest_reg,
+						    u8 *idlest_bit)
+{
+	u32 r;
+
+	r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+	*idlest_reg = (__force void __iomem *)r;
+	/* USBHOST_IDLE has same shift */
+	*idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
+}
+
+/**
+ * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
+ * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
+						 void __iomem **idlest_reg,
+						 u8 *idlest_bit)
+{
+	u32 r;
+
+	r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+	*idlest_reg = (__force void __iomem *)r;
+	*idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
+}
+
 /**
  * omap3_dpll_recalc - recalculate DPLL rate
  * @clk: DPLL struct clk
@@ -703,8 +826,12 @@
 static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 {
 	u32 new_div = 0;
-	unsigned long validrate, sdrcrate;
-	struct omap_sdrc_params *sp;
+	u32 unlock_dll = 0;
+	u32 c;
+	unsigned long validrate, sdrcrate, mpurate;
+	struct omap_sdrc_params *sdrc_cs0;
+	struct omap_sdrc_params *sdrc_cs1;
+	int ret;
 
 	if (!clk || !rate)
 		return -EINVAL;
@@ -712,34 +839,61 @@
 	if (clk != &dpll3_m2_ck)
 		return -EINVAL;
 
-	if (rate == clk->rate)
-		return 0;
-
 	validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
 	if (validrate != rate)
 		return -EINVAL;
 
 	sdrcrate = sdrc_ick.rate;
 	if (rate > clk->rate)
-		sdrcrate <<= ((rate / clk->rate) - 1);
+		sdrcrate <<= ((rate / clk->rate) >> 1);
 	else
-		sdrcrate >>= ((clk->rate / rate) - 1);
+		sdrcrate >>= ((clk->rate / rate) >> 1);
 
-	sp = omap2_sdrc_get_params(sdrcrate);
-	if (!sp)
+	ret = omap2_sdrc_get_params(sdrcrate, &sdrc_cs0, &sdrc_cs1);
+	if (ret)
 		return -EINVAL;
 
-	pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
-		validrate);
-	pr_info("clock: SDRC timing params used: %08x %08x %08x\n",
-		sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb);
+	if (sdrcrate < MIN_SDRC_DLL_LOCK_FREQ) {
+		pr_debug("clock: will unlock SDRC DLL\n");
+		unlock_dll = 1;
+	}
 
-	/* REVISIT: SRAM code doesn't support other M2 divisors yet */
-	WARN_ON(new_div != 1 && new_div != 2);
+	/*
+	 * XXX This only needs to be done when the CPU frequency changes
+	 */
+	mpurate = arm_fck.rate / CYCLES_PER_MHZ;
+	c = (mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
+	c += 1;  /* for safety */
+	c *= SDRC_MPURATE_LOOPS;
+	c >>= SDRC_MPURATE_SCALE;
+	if (c == 0)
+		c = 1;
 
-	/* REVISIT: Add SDRC_MR changing to this code also */
-	omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
-				  sp->actim_ctrlb, new_div);
+	pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
+		 validrate);
+	pr_debug("clock: SDRC CS0 timing params used:"
+		 " RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
+		 sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
+		 sdrc_cs0->actim_ctrlb, sdrc_cs0->mr);
+	if (sdrc_cs1)
+		pr_debug("clock: SDRC CS1 timing params used: "
+		 " RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
+		 sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
+		 sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
+
+	if (sdrc_cs1)
+		omap3_configure_core_dpll(
+				  new_div, unlock_dll, c, rate > clk->rate,
+				  sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
+				  sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
+				  sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
+				  sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
+	else
+		omap3_configure_core_dpll(
+				  new_div, unlock_dll, c, rate > clk->rate,
+				  sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
+				  sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
+				  0, 0, 0, 0);
 
 	return 0;
 }
@@ -956,7 +1110,7 @@
 	clk_init(&omap2_clk_functions);
 
 	for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
-		clk_init_one(c->lk.clk);
+		clk_preinit(c->lk.clk);
 
 	for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
 		if (c->cpu & cpu_clkflg) {
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock34xx.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock34xx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock34xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock34xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,8 @@
 #include "prm.h"
 #include "prm-regbits-34xx.h"
 
+#define OMAP_CM_REGADDR		OMAP34XX_CM_REGADDR
+
 static unsigned long omap3_dpll_recalc(struct clk *clk);
 static unsigned long omap3_clkoutx2_recalc(struct clk *clk);
 static void omap3_dpll_allow_idle(struct clk *clk);
@@ -1228,6 +1230,37 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk modem_fck = {
+	.name		= "modem_fck",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &sys_ck,
+	.init		= &omap2_init_clk_clkdm,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_MODEM_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk sad2d_ick = {
+	.name		= "sad2d_ick",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &l3_ick,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SAD2D_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk mad2d_ick = {
+	.name		= "mad2d_ick",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &l3_ick,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP3430_EN_MAD2D_SHIFT,
+	.clkdm_name	= "d2d_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 static const struct clksel omap343x_gpt_clksel[] = {
 	{ .parent = &omap_32k_fck, .rates = gpt_32k_rates },
 	{ .parent = &sys_ck,	   .rates = gpt_sys_rates },
@@ -1535,7 +1568,7 @@
 	{ .parent = NULL }
 };
 
-static struct clk ssi_ssr_fck = {
+static struct clk ssi_ssr_fck_3430es1 = {
 	.name		= "ssi_ssr_fck",
 	.ops		= &clkops_omap2_dflt,
 	.init		= &omap2_init_clksel_parent,
@@ -1548,10 +1581,31 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
-static struct clk ssi_sst_fck = {
+static struct clk ssi_ssr_fck_3430es2 = {
+	.name		= "ssi_ssr_fck",
+	.ops		= &clkops_omap3430es2_ssi_wait,
+	.init		= &omap2_init_clksel_parent,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
+	.clksel		= ssi_ssr_clksel,
+	.clkdm_name	= "core_l4_clkdm",
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk ssi_sst_fck_3430es1 = {
 	.name		= "ssi_sst_fck",
 	.ops		= &clkops_null,
-	.parent		= &ssi_ssr_fck,
+	.parent		= &ssi_ssr_fck_3430es1,
+	.fixed_div	= 2,
+	.recalc		= &omap2_fixed_divisor_recalc,
+};
+
+static struct clk ssi_sst_fck_3430es2 = {
+	.name		= "ssi_sst_fck",
+	.ops		= &clkops_null,
+	.parent		= &ssi_ssr_fck_3430es2,
 	.fixed_div	= 2,
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
@@ -1573,9 +1627,19 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk hsotgusb_ick = {
+static struct clk hsotgusb_ick_3430es1 = {
 	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_dflt,
+	.parent		= &core_l3_ick,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
+	.clkdm_name	= "core_l3_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk hsotgusb_ick_3430es2 = {
+	.name		= "hsotgusb_ick",
+	.ops		= &clkops_omap3430es2_hsotgusb_wait,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1914,7 +1978,7 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk ssi_ick = {
+static struct clk ssi_ick_3430es1 = {
 	.name		= "ssi_ick",
 	.ops		= &clkops_omap2_dflt,
 	.parent		= &ssi_l4_ick,
@@ -1924,6 +1988,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk ssi_ick_3430es2 = {
+	.name		= "ssi_ick",
+	.ops		= &clkops_omap3430es2_ssi_wait,
+	.parent		= &ssi_l4_ick,
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
+	.clkdm_name	= "core_l4_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /* REVISIT: Technically the TRM claims that this is CORE_CLK based,
  * but l4_ick makes more sense to me */
 
@@ -1945,8 +2019,6 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* XXX MDM_INTC_ICK, SAD2D_ICK ?? */
-
 /* SECURITY_L4_ICK2 based clocks */
 
 static struct clk security_l4_ick2 = {
@@ -1993,7 +2065,7 @@
 };
 
 /* DSS */
-static struct clk dss1_alwon_fck = {
+static struct clk dss1_alwon_fck_3430es1 = {
 	.name		= "dss1_alwon_fck",
 	.ops		= &clkops_omap2_dflt,
 	.parent		= &dpll4_m4x2_ck,
@@ -2003,6 +2075,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk dss1_alwon_fck_3430es2 = {
+	.name		= "dss1_alwon_fck",
+	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.parent		= &dpll4_m4x2_ck,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_DSS1_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk dss_tv_fck = {
 	.name		= "dss_tv_fck",
 	.ops		= &clkops_omap2_dflt,
@@ -2036,7 +2118,7 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk dss_ick = {
+static struct clk dss_ick_3430es1 = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
 	.ops		= &clkops_omap2_dflt,
@@ -2048,6 +2130,18 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk dss_ick_3430es2 = {
+	/* Handles both L3 and L4 clocks */
+	.name		= "dss_ick",
+	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.parent		= &l4_ick,
+	.init		= &omap2_init_clk_clkdm,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
+	.clkdm_name	= "dss_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /* CAM */
 
 static struct clk cam_mclk = {
@@ -2087,7 +2181,7 @@
 
 static struct clk usbhost_120m_fck = {
 	.name		= "usbhost_120m_fck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &dpll5_m2_ck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
@@ -2098,7 +2192,7 @@
 
 static struct clk usbhost_48m_fck = {
 	.name		= "usbhost_48m_fck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
 	.parent		= &omap_48m_fck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
@@ -2110,7 +2204,7 @@
 static struct clk usbhost_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "usbhost_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <mach/clock.h>
 #include <mach/clockdomain.h>
 #include <mach/cpu.h>
+#include <mach/prcm.h>
 #include <asm/div64.h>
 
 #include <mach/sdrc.h>
@@ -38,8 +39,6 @@
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
-#define MAX_CLOCK_ENABLE_WAIT		100000
-
 /* DPLL rate rounding: minimum DPLL multiplier, divider values */
 #define DPLL_MIN_MULTIPLIER		1
 #define DPLL_MIN_DIVIDER		1
@@ -91,9 +90,9 @@
 		return;
 
 	prm_write_mod_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_GR_MOD,
-		OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
+		OMAP2_PRCM_CLKCFG_CTRL_OFFSET);
 	/* OCP barrier */
-	prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
+	prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP2_PRCM_CLKCFG_CTRL_OFFSET);
 }
 
 /*
@@ -274,83 +273,97 @@
 }
 
 /**
- * omap2_wait_clock_ready - wait for clock to enable
- * @reg: physical address of clock IDLEST register
- * @mask: value to mask against to determine if the clock is active
- * @name: name of the clock (for printk)
+ * omap2_clk_dflt_find_companion - find companion clock to @clk
+ * @clk: struct clk * to find the companion clock of
+ * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
+ * @other_bit: u8 ** to return the companion clock bit shift in
  *
- * Returns 1 if the clock enabled in time, or 0 if it failed to enable
- * in roughly MAX_CLOCK_ENABLE_WAIT microseconds.
+ * Note: We don't need special code here for INVERT_ENABLE for the
+ * time being since INVERT_ENABLE only applies to clocks enabled by
+ * CM_CLKEN_PLL
+ *
+ * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes it's
+ * just a matter of XORing the bits.
+ *
+ * Some clocks don't have companion clocks.  For example, modules with
+ * only an interface clock (such as MAILBOXES) don't have a companion
+ * clock.  Right now, this code relies on the hardware exporting a bit
+ * in the correct companion register that indicates that the
+ * nonexistent 'companion clock' is active.  Future patches will
+ * associate this type of code with per-module data structures to
+ * avoid this issue, and remove the casts.  No return value.
  */
-int omap2_wait_clock_ready(void __iomem *reg, u32 mask, const char *name)
+void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
+				   u8 *other_bit)
 {
-	int i = 0;
-	int ena = 0;
+	u32 r;
 
 	/*
-	 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
-	 * 34xx reverses this, just to keep us on our toes
+	 * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
+	 * it's just a matter of XORing the bits.
 	 */
-	if (cpu_mask & (RATE_IN_242X | RATE_IN_243X))
-		ena = mask;
-	else if (cpu_mask & RATE_IN_343X)
-		ena = 0;
-
-	/* Wait for lock */
-	while (((__raw_readl(reg) & mask) != ena) &&
-	       (i++ < MAX_CLOCK_ENABLE_WAIT)) {
-		udelay(1);
-	}
-
-	if (i < MAX_CLOCK_ENABLE_WAIT)
-		pr_debug("Clock %s stable after %d loops\n", name, i);
-	else
-		printk(KERN_ERR "Clock %s didn't enable in %d tries\n",
-		       name, MAX_CLOCK_ENABLE_WAIT);
+	r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
 
+	*other_reg = (__force void __iomem *)r;
+	*other_bit = clk->enable_bit;
+}
 
-	return (i < MAX_CLOCK_ENABLE_WAIT) ? 1 : 0;
-};
+/**
+ * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
+ * @clk: struct clk * to find IDLEST info for
+ * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
+ * @idlest_bit: u8 ** to return the CM_IDLEST bit shift in
+ *
+ * Return the CM_IDLEST register address and bit shift corresponding
+ * to the module that "owns" this clock.  This default code assumes
+ * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
+ * the IDLEST register address ID corresponds to the CM_*CLKEN
+ * register address ID (e.g., that CM_FCLKEN2 corresponds to
+ * CM_IDLEST2).  This is not true for all modules.  No return value.
+ */
+void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
+				u8 *idlest_bit)
+{
+	u32 r;
 
+	r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+	*idlest_reg = (__force void __iomem *)r;
+	*idlest_bit = clk->enable_bit;
+}
 
-/*
- * Note: We don't need special code here for INVERT_ENABLE
- * for the time being since INVERT_ENABLE only applies to clocks enabled by
- * CM_CLKEN_PLL
+/**
+ * omap2_module_wait_ready - wait for an OMAP module to leave IDLE
+ * @clk: struct clk * belonging to the module
+ *
+ * If the necessary clocks for the OMAP hardware IP block that
+ * corresponds to clock @clk are enabled, then wait for the module to
+ * indicate readiness (i.e., to leave IDLE).  This code does not
+ * belong in the clock code and will be moved in the medium term to
+ * module-dependent code.  No return value.
  */
-static void omap2_clk_wait_ready(struct clk *clk)
+static void omap2_module_wait_ready(struct clk *clk)
 {
-	void __iomem *reg, *other_reg, *st_reg;
-	u32 bit;
-
-	/*
-	 * REVISIT: This code is pretty ugly.  It would be nice to generalize
-	 * it and pull it into struct clk itself somehow.
-	 */
-	reg = clk->enable_reg;
+	void __iomem *companion_reg, *idlest_reg;
+	u8 other_bit, idlest_bit;
 
-	/*
-	 * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
-	 * it's just a matter of XORing the bits.
-	 */
-	other_reg = (void __iomem *)((u32)reg ^ (CM_FCLKEN ^ CM_ICLKEN));
+	/* Not all modules have multiple clocks that their IDLEST depends on */
+	if (clk->ops->find_companion) {
+		clk->ops->find_companion(clk, &companion_reg, &other_bit);
+		if (!(__raw_readl(companion_reg) & (1 << other_bit)))
+			return;
+	}
 
-	/* Check if both functional and interface clocks
-	 * are running. */
-	bit = 1 << clk->enable_bit;
-	if (!(__raw_readl(other_reg) & bit))
-		return;
-	st_reg = (void __iomem *)(((u32)other_reg & ~0xf0) | 0x20); /* CM_IDLEST* */
+	clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit);
 
-	omap2_wait_clock_ready(st_reg, bit, clk->name);
+	omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), clk->name);
 }
 
-static int omap2_dflt_clk_enable(struct clk *clk)
+int omap2_dflt_clk_enable(struct clk *clk)
 {
 	u32 v;
 
 	if (unlikely(clk->enable_reg == NULL)) {
-		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+		pr_err("clock.c: Enable for %s without enable code\n",
 		       clk->name);
 		return 0; /* REVISIT: -EINVAL */
 	}
@@ -363,26 +376,13 @@
 	__raw_writel(v, clk->enable_reg);
 	v = __raw_readl(clk->enable_reg); /* OCP barrier */
 
-	return 0;
-}
-
-static int omap2_dflt_clk_enable_wait(struct clk *clk)
-{
-	int ret;
-
-	if (!clk->enable_reg) {
-		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
-		       clk->name);
-		return 0; /* REVISIT: -EINVAL */
-	}
+	if (clk->ops->find_idlest)
+		omap2_module_wait_ready(clk);
 
-	ret = omap2_dflt_clk_enable(clk);
-	if (ret == 0)
-		omap2_clk_wait_ready(clk);
-	return ret;
+	return 0;
 }
 
-static void omap2_dflt_clk_disable(struct clk *clk)
+void omap2_dflt_clk_disable(struct clk *clk)
 {
 	u32 v;
 
@@ -406,8 +406,10 @@
 }
 
 const struct clkops clkops_omap2_dflt_wait = {
-	.enable		= omap2_dflt_clk_enable_wait,
+	.enable		= omap2_dflt_clk_enable,
 	.disable	= omap2_dflt_clk_disable,
+	.find_companion	= omap2_clk_dflt_find_companion,
+	.find_idlest	= omap2_clk_dflt_find_idlest,
 };
 
 const struct clkops clkops_omap2_dflt = {
@@ -547,8 +549,8 @@
 	const struct clksel_rate *clkr;
 	u32 last_div = 0;
 
-	printk(KERN_INFO "clock: clksel_round_rate_div: %s target_rate %ld\n",
-	       clk->name, target_rate);
+	pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
+		 clk->name, target_rate);
 
 	*new_div = 1;
 
@@ -562,7 +564,7 @@
 
 		/* Sanity check */
 		if (clkr->div <= last_div)
-			printk(KERN_ERR "clock: clksel_rate table not sorted "
+			pr_err("clock: clksel_rate table not sorted "
 			       "for clock %s", clk->name);
 
 		last_div = clkr->div;
@@ -574,7 +576,7 @@
 	}
 
 	if (!clkr->div) {
-		printk(KERN_ERR "clock: Could not find divisor for target "
+		pr_err("clock: Could not find divisor for target "
 		       "rate %ld for clock %s parent %s\n", target_rate,
 		       clk->name, clk->parent->name);
 		return ~0;
@@ -582,8 +584,8 @@
 
 	*new_div = clkr->div;
 
-	printk(KERN_INFO "clock: new_div = %d, new_rate = %ld\n", *new_div,
-	       (clk->parent->rate / clkr->div));
+	pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
+		 (clk->parent->rate / clkr->div));
 
 	return (clk->parent->rate / clkr->div);
 }
@@ -1035,7 +1037,7 @@
 	if ((regval32 & (1 << clk->enable_bit)) == v)
 		return;
 
-	printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
+	printk(KERN_DEBUG "Disabling unused clock \"%s\"\n", clk->name);
 	if (cpu_is_omap34xx()) {
 		omap2_clk_enable(clk);
 		omap2_clk_disable(clk);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clockdomains.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clockdomains.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clockdomains.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clockdomains.h	2009-09-09 18:13:59.000000000 -0400
@@ -195,7 +195,7 @@
 static struct clockdomain d2d_clkdm = {
 	.name		= "d2d_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/clock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -65,6 +65,12 @@
 u32 omap2_get_dpll_rate(struct clk *clk);
 int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
 void omap2_clk_prepare_for_reboot(void);
+int omap2_dflt_clk_enable(struct clk *clk);
+void omap2_dflt_clk_disable(struct clk *clk);
+void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
+				   u8 *other_bit);
+void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
+				u8 *idlest_bit);
 
 extern const struct clkops clkops_omap2_dflt_wait;
 extern const struct clkops clkops_omap2_dflt;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/cm.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/cm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/cm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/cm.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,17 +16,12 @@
 
 #include "prcm-common.h"
 
-#ifndef __ASSEMBLER__
-#define OMAP_CM_REGADDR(module, reg)					\
-			IO_ADDRESS(OMAP2_CM_BASE + (module) + (reg))
-#else
 #define OMAP2420_CM_REGADDR(module, reg)				\
 			IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
 #define OMAP2430_CM_REGADDR(module, reg)				\
 			IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
 #define OMAP34XX_CM_REGADDR(module, reg)				\
 			IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
-#endif
 
 /*
  * Architecture-specific global CM registers
@@ -34,10 +29,11 @@
  * These registers appear once per CM module.
  */
 
-#define OMAP3430_CM_REVISION		OMAP_CM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP3430_CM_SYSCONFIG		OMAP_CM_REGADDR(OCP_MOD, 0x0010)
-#define OMAP3430_CM_POLCTRL		OMAP_CM_REGADDR(OCP_MOD, 0x009c)
+#define OMAP3430_CM_REVISION		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP3430_CM_SYSCONFIG		OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
+#define OMAP3430_CM_POLCTRL		OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
 
+#define OMAP3_CM_CLKOUT_CTRL_OFFSET	0x0070
 #define OMAP3430_CM_CLKOUT_CTRL		OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/cm-regbits-34xx.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/cm-regbits-34xx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/cm-regbits-34xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/cm-regbits-34xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -145,6 +145,8 @@
 #define OMAP3430_CLKACTIVITY_MPU_MASK			(1 << 0)
 
 /* CM_FCLKEN1_CORE specific bits */
+#define OMAP3430_EN_MODEM				(1 << 31)
+#define OMAP3430_EN_MODEM_SHIFT				31
 
 /* CM_ICLKEN1_CORE specific bits */
 #define OMAP3430_EN_ICR					(1 << 29)
@@ -161,6 +163,8 @@
 #define OMAP3430_EN_MAILBOXES_SHIFT			7
 #define OMAP3430_EN_OMAPCTRL				(1 << 6)
 #define OMAP3430_EN_OMAPCTRL_SHIFT			6
+#define OMAP3430_EN_SAD2D				(1 << 3)
+#define OMAP3430_EN_SAD2D_SHIFT				3
 #define OMAP3430_EN_SDRC				(1 << 1)
 #define OMAP3430_EN_SDRC_SHIFT				1
 
@@ -176,6 +180,10 @@
 #define OMAP3430_EN_DES1				(1 << 0)
 #define OMAP3430_EN_DES1_SHIFT				0
 
+/* CM_ICLKEN3_CORE */
+#define OMAP3430_EN_MAD2D_SHIFT				3
+#define OMAP3430_EN_MAD2D				(1 << 3)
+
 /* CM_FCLKEN3_CORE specific bits */
 #define OMAP3430ES2_EN_TS_SHIFT				1
 #define OMAP3430ES2_EN_TS_MASK				(1 << 1)
@@ -231,6 +239,8 @@
 #define OMAP3430ES2_ST_CPEFUSE_MASK			(1 << 0)
 
 /* CM_AUTOIDLE1_CORE */
+#define OMAP3430_AUTO_MODEM				(1 << 31)
+#define OMAP3430_AUTO_MODEM_SHIFT			31
 #define OMAP3430ES2_AUTO_MMC3				(1 << 30)
 #define OMAP3430ES2_AUTO_MMC3_SHIFT			30
 #define OMAP3430ES2_AUTO_ICR				(1 << 29)
@@ -287,6 +297,8 @@
 #define OMAP3430_AUTO_HSOTGUSB_SHIFT			4
 #define OMAP3430ES1_AUTO_D2D				(1 << 3)
 #define OMAP3430ES1_AUTO_D2D_SHIFT			3
+#define OMAP3430_AUTO_SAD2D				(1 << 3)
+#define OMAP3430_AUTO_SAD2D_SHIFT			3
 #define OMAP3430_AUTO_SSI				(1 << 0)
 #define OMAP3430_AUTO_SSI_SHIFT				0
 
@@ -308,6 +320,8 @@
 #define	OMAP3430ES2_AUTO_USBTLL				(1 << 2)
 #define OMAP3430ES2_AUTO_USBTLL_SHIFT			2
 #define OMAP3430ES2_AUTO_USBTLL_MASK			(1 << 2)
+#define OMAP3430_AUTO_MAD2D_SHIFT			3
+#define OMAP3430_AUTO_MAD2D				(1 << 3)
 
 /* CM_CLKSEL_CORE */
 #define OMAP3430_CLKSEL_SSI_SHIFT			8
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/gpmc.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/gpmc.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/gpmc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/gpmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,6 +5,9 @@
  *
  * Author: Juha Yrjola
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -424,6 +427,9 @@
 	} else if (cpu_is_omap34xx()) {
 		ck = "gpmc_fck";
 		l = OMAP34XX_GPMC_BASE;
+	} else if (cpu_is_omap44xx()) {
+		ck = "gpmc_fck";
+		l = OMAP44XX_GPMC_BASE;
 	}
 
 	gpmc_l3_clk = clk_get(NULL, ck);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/gpmc-onenand.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/gpmc-onenand.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/gpmc-onenand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/gpmc-onenand.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,347 @@
+/*
+ * linux/arch/arm/mach-omap2/gpmc-onenand.c
+ *
+ * Copyright (C) 2006 - 2009 Nokia Corporation
+ * Contacts:	Juha Yrjola
+ *		Tony Lindgren
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/onenand_regs.h>
+#include <linux/io.h>
+
+#include <asm/mach/flash.h>
+
+#include <mach/onenand.h>
+#include <mach/board.h>
+#include <mach/gpmc.h>
+
+static struct omap_onenand_platform_data *gpmc_onenand_data;
+
+static struct platform_device gpmc_onenand_device = {
+	.name		= "omap2-onenand",
+	.id		= -1,
+};
+
+static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
+{
+	struct gpmc_timings t;
+	u32 reg;
+	int err;
+
+	const int t_cer = 15;
+	const int t_avdp = 12;
+	const int t_aavdh = 7;
+	const int t_ce = 76;
+	const int t_aa = 76;
+	const int t_oe = 20;
+	const int t_cez = 20; /* max of t_cez, t_oez */
+	const int t_ds = 30;
+	const int t_wpl = 40;
+	const int t_wph = 30;
+
+	/* Ensure sync read and sync write are disabled */
+	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
+	reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
+	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+
+	memset(&t, 0, sizeof(t));
+	t.sync_clk = 0;
+	t.cs_on = 0;
+	t.adv_on = 0;
+
+	/* Read */
+	t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
+	t.oe_on  = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh);
+	t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa);
+	t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce));
+	t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe));
+	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
+	t.cs_rd_off = t.oe_off;
+	t.rd_cycle  = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez);
+
+	/* Write */
+	t.adv_wr_off = t.adv_rd_off;
+	t.we_on  = t.oe_on;
+	if (cpu_is_omap34xx()) {
+		t.wr_data_mux_bus = t.we_on;
+		t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
+	}
+	t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
+	t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
+	t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
+
+	/* Configure GPMC for asynchronous read */
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+			  GPMC_CONFIG1_DEVICESIZE_16 |
+			  GPMC_CONFIG1_MUXADDDATA);
+
+	err = gpmc_cs_set_timings(cs, &t);
+	if (err)
+		return err;
+
+	/* Ensure sync read and sync write are disabled */
+	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
+	reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
+	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+
+	return 0;
+}
+
+static void set_onenand_cfg(void __iomem *onenand_base, int latency,
+				int sync_read, int sync_write, int hf)
+{
+	u32 reg;
+
+	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
+	reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
+	reg |=	(latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
+		ONENAND_SYS_CFG1_BL_16;
+	if (sync_read)
+		reg |= ONENAND_SYS_CFG1_SYNC_READ;
+	else
+		reg &= ~ONENAND_SYS_CFG1_SYNC_READ;
+	if (sync_write)
+		reg |= ONENAND_SYS_CFG1_SYNC_WRITE;
+	else
+		reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE;
+	if (hf)
+		reg |= ONENAND_SYS_CFG1_HF;
+	else
+		reg &= ~ONENAND_SYS_CFG1_HF;
+	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+}
+
+static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
+					void __iomem *onenand_base,
+					int freq)
+{
+	struct gpmc_timings t;
+	const int t_cer  = 15;
+	const int t_avdp = 12;
+	const int t_cez  = 20; /* max of t_cez, t_oez */
+	const int t_ds   = 30;
+	const int t_wpl  = 40;
+	const int t_wph  = 30;
+	int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
+	int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
+	int first_time = 0, hf = 0, sync_read = 0, sync_write = 0;
+	int err, ticks_cez;
+	int cs = cfg->cs;
+	u32 reg;
+
+	if (cfg->flags & ONENAND_SYNC_READ) {
+		sync_read = 1;
+	} else if (cfg->flags & ONENAND_SYNC_READWRITE) {
+		sync_read = 1;
+		sync_write = 1;
+	} else
+		return omap2_onenand_set_async_mode(cs, onenand_base);
+
+	if (!freq) {
+		/* Very first call freq is not known */
+		err = omap2_onenand_set_async_mode(cs, onenand_base);
+		if (err)
+			return err;
+		reg = readw(onenand_base + ONENAND_REG_VERSION_ID);
+		switch ((reg >> 4) & 0xf) {
+		case 0:
+			freq = 40;
+			break;
+		case 1:
+			freq = 54;
+			break;
+		case 2:
+			freq = 66;
+			break;
+		case 3:
+			freq = 83;
+			break;
+		case 4:
+			freq = 104;
+			break;
+		default:
+			freq = 54;
+			break;
+		}
+		first_time = 1;
+	}
+
+	switch (freq) {
+	case 83:
+		min_gpmc_clk_period = 12; /* 83 MHz */
+		t_ces   = 5;
+		t_avds  = 4;
+		t_avdh  = 2;
+		t_ach   = 6;
+		t_aavdh = 6;
+		t_rdyo  = 9;
+		break;
+	case 66:
+		min_gpmc_clk_period = 15; /* 66 MHz */
+		t_ces   = 6;
+		t_avds  = 5;
+		t_avdh  = 2;
+		t_ach   = 6;
+		t_aavdh = 6;
+		t_rdyo  = 11;
+		break;
+	default:
+		min_gpmc_clk_period = 18; /* 54 MHz */
+		t_ces   = 7;
+		t_avds  = 7;
+		t_avdh  = 7;
+		t_ach   = 9;
+		t_aavdh = 7;
+		t_rdyo  = 15;
+		sync_write = 0;
+		break;
+	}
+
+	tick_ns = gpmc_ticks_to_ns(1);
+	div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
+	gpmc_clk_ns = gpmc_ticks_to_ns(div);
+	if (gpmc_clk_ns < 15) /* >66Mhz */
+		hf = 1;
+	if (hf)
+		latency = 6;
+	else if (gpmc_clk_ns >= 25) /* 40 MHz*/
+		latency = 3;
+	else
+		latency = 4;
+
+	if (first_time)
+		set_onenand_cfg(onenand_base, latency,
+					sync_read, sync_write, hf);
+
+	if (div == 1) {
+		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
+		reg |= (1 << 7);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
+		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
+		reg |= (1 << 7);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
+		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
+		reg |= (1 << 7);
+		reg |= (1 << 23);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+	} else {
+		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
+		reg &= ~(1 << 7);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
+		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
+		reg &= ~(1 << 7);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
+		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
+		reg &= ~(1 << 7);
+		reg &= ~(1 << 23);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+	}
+
+	/* Set synchronous read timings */
+	memset(&t, 0, sizeof(t));
+	t.sync_clk = min_gpmc_clk_period;
+	t.cs_on = 0;
+	t.adv_on = 0;
+	fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
+	fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
+	t.page_burst_access = gpmc_clk_ns;
+
+	/* Read */
+	t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
+	t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
+	t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
+	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
+	t.cs_rd_off = t.oe_off;
+	ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
+	t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
+		     ticks_cez);
+
+	/* Write */
+	if (sync_write) {
+		t.adv_wr_off = t.adv_rd_off;
+		t.we_on  = 0;
+		t.we_off = t.cs_rd_off;
+		t.cs_wr_off = t.cs_rd_off;
+		t.wr_cycle  = t.rd_cycle;
+		if (cpu_is_omap34xx()) {
+			t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
+					gpmc_ns_to_ticks(min_gpmc_clk_period +
+					t_rdyo));
+			t.wr_access = t.access;
+		}
+	} else {
+		t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int,
+							t_avdp, t_cer));
+		t.we_on  = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
+		t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
+		t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
+		t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
+		if (cpu_is_omap34xx()) {
+			t.wr_data_mux_bus = t.we_on;
+			t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
+		}
+	}
+
+	/* Configure GPMC for synchronous read */
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+			  GPMC_CONFIG1_WRAPBURST_SUPP |
+			  GPMC_CONFIG1_READMULTIPLE_SUPP |
+			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
+			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
+			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
+			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
+			  GPMC_CONFIG1_PAGE_LEN(2) |
+			  (cpu_is_omap34xx() ? 0 :
+				(GPMC_CONFIG1_WAIT_READ_MON |
+				 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
+			  GPMC_CONFIG1_DEVICESIZE_16 |
+			  GPMC_CONFIG1_DEVICETYPE_NOR |
+			  GPMC_CONFIG1_MUXADDDATA);
+
+	err = gpmc_cs_set_timings(cs, &t);
+	if (err)
+		return err;
+
+	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf);
+
+	return 0;
+}
+
+static int gpmc_onenand_setup(void __iomem *onenand_base, int freq)
+{
+	struct device *dev = &gpmc_onenand_device.dev;
+
+	/* Set sync timings in GPMC */
+	if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
+			freq) < 0) {
+		dev_err(dev, "Unable to set synchronous mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+{
+	gpmc_onenand_data = _onenand_data;
+	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
+	gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
+
+	if (cpu_is_omap24xx() &&
+			(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
+		printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
+		gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
+		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
+	}
+
+	if (platform_device_register(&gpmc_onenand_device) < 0) {
+		printk(KERN_ERR "Unable to register OneNAND device\n");
+		return;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/gpmc-smc91x.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/gpmc-smc91x.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/gpmc-smc91x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/gpmc-smc91x.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,189 @@
+/*
+ * linux/arch/arm/mach-omap2/gpmc-smc91x.c
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Contact:	Tony Lindgren
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/smc91x.h>
+
+#include <mach/board.h>
+#include <mach/gpmc.h>
+#include <mach/gpmc-smc91x.h>
+
+static struct omap_smc91x_platform_data *gpmc_cfg;
+
+static struct resource gpmc_smc91x_resources[] = {
+	[0] = {
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smc91x_platdata gpmc_smc91x_info = {
+	.flags  = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0,
+};
+
+static struct platform_device gpmc_smc91x_device = {
+	.name		= "smc91x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(gpmc_smc91x_resources),
+	.resource	= gpmc_smc91x_resources,
+	.dev		= {
+		.platform_data = &gpmc_smc91x_info,
+	},
+};
+
+/*
+ * Set the gpmc timings for smc91c96. The timings are taken
+ * from the data sheet available at:
+ * http://www.smsc.com/main/catalog/lan91c96.html
+ * REVISIT: Level shifters can add at least to the access latency.
+ */
+static int smc91c96_gpmc_retime(void)
+{
+	struct gpmc_timings t;
+	const int t3 = 10;	/* Figure 12.2 read and 12.4 write */
+	const int t4_r = 20;	/* Figure 12.2 read */
+	const int t4_w = 5;	/* Figure 12.4 write */
+	const int t5 = 25;	/* Figure 12.2 read */
+	const int t6 = 15;	/* Figure 12.2 read */
+	const int t7 = 5;	/* Figure 12.4 write */
+	const int t8 = 5;	/* Figure 12.4 write */
+	const int t20 = 185;	/* Figure 12.2 read and 12.4 write */
+	u32 l;
+
+	memset(&t, 0, sizeof(t));
+
+	/* Read timings */
+	t.cs_on = 0;
+	t.adv_on = t.cs_on;
+	t.oe_on = t.adv_on + t3;
+	t.access = t.oe_on + t5;
+	t.oe_off = t.access;
+	t.adv_rd_off = t.oe_off + max(t4_r, t6);
+	t.cs_rd_off = t.oe_off;
+	t.rd_cycle = t20 - t.oe_on;
+
+	/* Write timings */
+	t.we_on = t.adv_on + t3;
+
+	if (cpu_is_omap34xx() && (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)) {
+		t.wr_data_mux_bus = t.we_on;
+		t.we_off = t.wr_data_mux_bus + t7;
+	} else
+		t.we_off = t.we_on + t7;
+	if (cpu_is_omap34xx())
+		t.wr_access = t.we_off;
+	t.adv_wr_off = t.we_off + max(t4_w, t8);
+	t.cs_wr_off = t.we_off + t4_w;
+	t.wr_cycle = t20 - t.we_on;
+
+	l = GPMC_CONFIG1_DEVICESIZE_16;
+	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
+		l |= GPMC_CONFIG1_MUXADDDATA;
+	if (gpmc_cfg->flags & GPMC_READ_MON)
+		l |= GPMC_CONFIG1_WAIT_READ_MON;
+	if (gpmc_cfg->flags & GPMC_WRITE_MON)
+		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+	if (gpmc_cfg->wait_pin)
+		l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
+	gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
+
+	/*
+	 * FIXME: Calculate the address and data bus muxed timings.
+	 * Note that at least adv_rd_off needs to be changed according
+	 * to omap3430 TRM Figure 11-11. Are the sdp boards using the
+	 * FPGA in between smc91x and omap as the timings are different
+	 * from above?
+	 */
+	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
+		return 0;
+
+	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
+}
+
+/*
+ * Initialize smc91x device connected to the GPMC. Note that we
+ * assume that pin multiplexing is done in the board-*.c file,
+ * or in the bootloader.
+ */
+void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
+{
+	unsigned long cs_mem_base;
+	int ret;
+
+	gpmc_cfg = board_data;
+
+	if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96)
+		gpmc_cfg->retime = smc91c96_gpmc_retime;
+
+	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
+		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
+		return;
+	}
+
+	gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
+	gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
+	gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+
+	if (gpmc_cfg->retime) {
+		ret = gpmc_cfg->retime();
+		if (ret != 0)
+			goto free1;
+	}
+
+	if (gpio_request(gpmc_cfg->gpio_irq, "SMC91X irq") < 0)
+		goto free1;
+
+	gpio_direction_input(gpmc_cfg->gpio_irq);
+	gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+
+	if (gpmc_cfg->gpio_pwrdwn) {
+		ret = gpio_request(gpmc_cfg->gpio_pwrdwn, "SMC91X powerdown");
+		if (ret)
+			goto free2;
+		gpio_direction_output(gpmc_cfg->gpio_pwrdwn, 0);
+	}
+
+	if (gpmc_cfg->gpio_reset) {
+		ret = gpio_request(gpmc_cfg->gpio_reset, "SMC91X reset");
+		if (ret)
+			goto free3;
+
+		gpio_direction_output(gpmc_cfg->gpio_reset, 0);
+		gpio_set_value(gpmc_cfg->gpio_reset, 1);
+		msleep(100);
+		gpio_set_value(gpmc_cfg->gpio_reset, 0);
+	}
+
+	if (platform_device_register(&gpmc_smc91x_device) < 0) {
+		printk(KERN_ERR "Unable to register smc91x device\n");
+		gpio_free(gpmc_cfg->gpio_reset);
+		goto free3;
+	}
+
+	return;
+
+free3:
+	if (gpmc_cfg->gpio_pwrdwn)
+		gpio_free(gpmc_cfg->gpio_pwrdwn);
+free2:
+	gpio_free(gpmc_cfg->gpio_irq);
+free1:
+	gpmc_cs_free(gpmc_cfg->cs);
+
+	printk(KERN_ERR "Could not initialize smc91x\n");
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/id.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/id.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/id.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/id.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,9 @@
  * Copyright (C) 2005 Nokia Corporation
  * Written by Tony Lindgren <tony@atomide.com>
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -45,6 +48,28 @@
 }
 EXPORT_SYMBOL(omap_chip_is);
 
+int omap_type(void)
+{
+	u32 val = 0;
+
+	if (cpu_is_omap24xx())
+		val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
+	else if (cpu_is_omap34xx())
+		val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
+	else {
+		pr_err("Cannot detect omap type!\n");
+		goto out;
+	}
+
+	val &= OMAP2_DEVICETYPE_MASK;
+	val >>= 8;
+
+out:
+	return val;
+}
+EXPORT_SYMBOL(omap_type);
+
+
 /*----------------------------------------------------------------------------*/
 
 #define OMAP_TAP_IDCODE		0x0204
@@ -200,7 +225,10 @@
 		omap24xx_check_revision();
 	else if (cpu_is_omap34xx())
 		omap34xx_check_revision();
-	else
+	else if (cpu_is_omap44xx()) {
+		printk(KERN_INFO "FIXME: CPU revision = OMAP4430\n");
+		return;
+	} else
 		pr_err("OMAP revision unknown, please fix!\n");
 
 	/*
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/io.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/io.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -4,12 +4,14 @@
  * OMAP2 I/O mapping code
  *
  * Copyright (C) 2005 Nokia Corporation
- * Copyright (C) 2007 Texas Instruments
+ * Copyright (C) 2007-2009 Texas Instruments
  *
  * Author:
  *	Juha Yrjola <juha.yrjola@nokia.com>
  *	Syed Khasim <x0khasim@ti.com>
  *
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -19,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <asm/tlb.h>
 
@@ -30,6 +33,7 @@
 #include <mach/sdrc.h>
 #include <mach/gpmc.h>
 
+#ifndef CONFIG_ARCH_OMAP4	/* FIXME: Remove this once clkdev is ready */
 #include "clock.h"
 
 #include <mach/powerdomain.h>
@@ -38,7 +42,7 @@
 
 #include <mach/clockdomain.h>
 #include "clockdomains.h"
-
+#endif
 /*
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
@@ -166,6 +170,46 @@
 	},
 };
 #endif
+#ifdef	CONFIG_ARCH_OMAP4
+static struct map_desc omap44xx_io_desc[] __initdata = {
+	{
+		.virtual	= L3_44XX_VIRT,
+		.pfn		= __phys_to_pfn(L3_44XX_PHYS),
+		.length		= L3_44XX_SIZE,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= L4_44XX_VIRT,
+		.pfn		= __phys_to_pfn(L4_44XX_PHYS),
+		.length		= L4_44XX_SIZE,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= L4_WK_44XX_VIRT,
+		.pfn		= __phys_to_pfn(L4_WK_44XX_PHYS),
+		.length		= L4_WK_44XX_SIZE,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= OMAP44XX_GPMC_VIRT,
+		.pfn		= __phys_to_pfn(OMAP44XX_GPMC_PHYS),
+		.length		= OMAP44XX_GPMC_SIZE,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= L4_PER_44XX_VIRT,
+		.pfn		= __phys_to_pfn(L4_PER_44XX_PHYS),
+		.length		= L4_PER_44XX_SIZE,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= L4_EMU_44XX_VIRT,
+		.pfn		= __phys_to_pfn(L4_EMU_44XX_PHYS),
+		.length		= L4_EMU_44XX_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+#endif
 
 void __init omap2_map_common_io(void)
 {
@@ -183,6 +227,9 @@
 	iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
 #endif
 
+#if defined(CONFIG_ARCH_OMAP4)
+	iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
+#endif
 	/* Normally devicemaps_init() would flush caches and tlb after
 	 * mdesc->map_io(), but we must also do it here because of the CPU
 	 * revision check below.
@@ -195,12 +242,50 @@
 	omapfb_reserve_sdram();
 }
 
-void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+/*
+ * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters
+ *
+ * Sets the CORE DPLL3 M2 divider to the same value that it's at
+ * currently.  This has the effect of setting the SDRC SDRAM AC timing
+ * registers to the values currently defined by the kernel.  Currently
+ * only defined for OMAP3; will return 0 if called on OMAP2.  Returns
+ * -EINVAL if the dpll3_m2_ck cannot be found, 0 if called on OMAP2,
+ * or passes along the return value of clk_set_rate().
+ */
+static int __init _omap2_init_reprogram_sdrc(void)
+{
+	struct clk *dpll3_m2_ck;
+	int v = -EINVAL;
+	long rate;
+
+	if (!cpu_is_omap34xx())
+		return 0;
+
+	dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
+	if (!dpll3_m2_ck)
+		return -EINVAL;
+
+	rate = clk_get_rate(dpll3_m2_ck);
+	pr_info("Reprogramming SDRC clock to %ld Hz\n", rate);
+	v = clk_set_rate(dpll3_m2_ck, rate);
+	if (v)
+		pr_err("dpll3_m2_clk rate change failed: %d\n", v);
+
+	clk_put(dpll3_m2_ck);
+
+	return v;
+}
+
+void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
+				 struct omap_sdrc_params *sdrc_cs1)
 {
 	omap2_mux_init();
+#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */
 	pwrdm_init(powerdomains_omap);
 	clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
 	omap2_clk_init();
-	omap2_sdrc_init(sp);
+	omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
+	_omap2_init_reprogram_sdrc();
+#endif
 	gpmc_init();
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/iommu2.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/iommu2.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/iommu2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/iommu2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,323 @@
+/*
+ * omap iommu: omap2/3 architecture specific functions
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
+ *		Paul Mundt and Toshihiro Kobayashi
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/stringify.h>
+
+#include <mach/iommu.h>
+
+/*
+ * omap2 architecture specific register bit definitions
+ */
+#define IOMMU_ARCH_VERSION	0x00000011
+
+/* SYSCONF */
+#define MMU_SYS_IDLE_SHIFT	3
+#define MMU_SYS_IDLE_FORCE	(0 << MMU_SYS_IDLE_SHIFT)
+#define MMU_SYS_IDLE_NONE	(1 << MMU_SYS_IDLE_SHIFT)
+#define MMU_SYS_IDLE_SMART	(2 << MMU_SYS_IDLE_SHIFT)
+#define MMU_SYS_IDLE_MASK	(3 << MMU_SYS_IDLE_SHIFT)
+
+#define MMU_SYS_SOFTRESET	(1 << 1)
+#define MMU_SYS_AUTOIDLE	1
+
+/* SYSSTATUS */
+#define MMU_SYS_RESETDONE	1
+
+/* IRQSTATUS & IRQENABLE */
+#define MMU_IRQ_MULTIHITFAULT	(1 << 4)
+#define MMU_IRQ_TABLEWALKFAULT	(1 << 3)
+#define MMU_IRQ_EMUMISS		(1 << 2)
+#define MMU_IRQ_TRANSLATIONFAULT	(1 << 1)
+#define MMU_IRQ_TLBMISS		(1 << 0)
+#define MMU_IRQ_MASK	\
+	(MMU_IRQ_MULTIHITFAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_EMUMISS | \
+	 MMU_IRQ_TRANSLATIONFAULT)
+
+/* MMU_CNTL */
+#define MMU_CNTL_SHIFT		1
+#define MMU_CNTL_MASK		(7 << MMU_CNTL_SHIFT)
+#define MMU_CNTL_EML_TLB	(1 << 3)
+#define MMU_CNTL_TWL_EN		(1 << 2)
+#define MMU_CNTL_MMU_EN		(1 << 1)
+
+#define get_cam_va_mask(pgsz)				\
+	(((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 :	\
+	 ((pgsz) == MMU_CAM_PGSZ_1M)  ? 0xfff00000 :	\
+	 ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 :	\
+	 ((pgsz) == MMU_CAM_PGSZ_4K)  ? 0xfffff000 : 0)
+
+static int omap2_iommu_enable(struct iommu *obj)
+{
+	u32 l, pa;
+	unsigned long timeout;
+
+	if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd,  SZ_16K))
+		return -EINVAL;
+
+	pa = virt_to_phys(obj->iopgd);
+	if (!IS_ALIGNED(pa, SZ_16K))
+		return -EINVAL;
+
+	iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
+
+	timeout = jiffies + msecs_to_jiffies(20);
+	do {
+		l = iommu_read_reg(obj, MMU_SYSSTATUS);
+		if (l & MMU_SYS_RESETDONE)
+			break;
+	} while (time_after(jiffies, timeout));
+
+	if (!(l & MMU_SYS_RESETDONE)) {
+		dev_err(obj->dev, "can't take mmu out of reset\n");
+		return -ENODEV;
+	}
+
+	l = iommu_read_reg(obj, MMU_REVISION);
+	dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
+		 (l >> 4) & 0xf, l & 0xf);
+
+	l = iommu_read_reg(obj, MMU_SYSCONFIG);
+	l &= ~MMU_SYS_IDLE_MASK;
+	l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
+	iommu_write_reg(obj, l, MMU_SYSCONFIG);
+
+	iommu_write_reg(obj, MMU_IRQ_MASK, MMU_IRQENABLE);
+	iommu_write_reg(obj, pa, MMU_TTB);
+
+	l = iommu_read_reg(obj, MMU_CNTL);
+	l &= ~MMU_CNTL_MASK;
+	l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
+	iommu_write_reg(obj, l, MMU_CNTL);
+
+	return 0;
+}
+
+static void omap2_iommu_disable(struct iommu *obj)
+{
+	u32 l = iommu_read_reg(obj, MMU_CNTL);
+
+	l &= ~MMU_CNTL_MASK;
+	iommu_write_reg(obj, l, MMU_CNTL);
+	iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
+
+	dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
+}
+
+static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
+{
+	int i;
+	u32 stat, da;
+	const char *err_msg[] =	{
+		"tlb miss",
+		"translation fault",
+		"emulation miss",
+		"table walk fault",
+		"multi hit fault",
+	};
+
+	stat = iommu_read_reg(obj, MMU_IRQSTATUS);
+	stat &= MMU_IRQ_MASK;
+	if (!stat)
+		return 0;
+
+	da = iommu_read_reg(obj, MMU_FAULT_AD);
+	*ra = da;
+
+	dev_err(obj->dev, "%s:\tda:%08x ", __func__, da);
+
+	for (i = 0; i < ARRAY_SIZE(err_msg); i++) {
+		if (stat & (1 << i))
+			printk("%s ", err_msg[i]);
+	}
+	printk("\n");
+
+	iommu_write_reg(obj, stat, MMU_IRQSTATUS);
+	return stat;
+}
+
+static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
+{
+	cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
+	cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
+}
+
+static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr)
+{
+	iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
+	iommu_write_reg(obj, cr->ram, MMU_RAM);
+}
+
+static u32 omap2_cr_to_virt(struct cr_regs *cr)
+{
+	u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK;
+	u32 mask = get_cam_va_mask(cr->cam & page_size);
+
+	return cr->cam & mask;
+}
+
+static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
+{
+	struct cr_regs *cr;
+
+	if (e->da & ~(get_cam_va_mask(e->pgsz))) {
+		dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__,
+			e->da);
+		return ERR_PTR(-EINVAL);
+	}
+
+	cr = kmalloc(sizeof(*cr), GFP_KERNEL);
+	if (!cr)
+		return ERR_PTR(-ENOMEM);
+
+	cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz;
+	cr->ram = e->pa | e->endian | e->elsz | e->mixed;
+
+	return cr;
+}
+
+static inline int omap2_cr_valid(struct cr_regs *cr)
+{
+	return cr->cam & MMU_CAM_V;
+}
+
+static u32 omap2_get_pte_attr(struct iotlb_entry *e)
+{
+	u32 attr;
+
+	attr = e->mixed << 5;
+	attr |= e->endian;
+	attr |= e->elsz >> 3;
+	attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6);
+
+	return attr;
+}
+
+static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
+{
+	char *p = buf;
+
+	/* FIXME: Need more detail analysis of cam/ram */
+	p += sprintf(p, "%08x %08x\n", cr->cam, cr->ram);
+
+	return p - buf;
+}
+
+#define pr_reg(name)							\
+	p += sprintf(p, "%20s: %08x\n",					\
+		     __stringify(name), iommu_read_reg(obj, MMU_##name));
+
+static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf)
+{
+	char *p = buf;
+
+	pr_reg(REVISION);
+	pr_reg(SYSCONFIG);
+	pr_reg(SYSSTATUS);
+	pr_reg(IRQSTATUS);
+	pr_reg(IRQENABLE);
+	pr_reg(WALKING_ST);
+	pr_reg(CNTL);
+	pr_reg(FAULT_AD);
+	pr_reg(TTB);
+	pr_reg(LOCK);
+	pr_reg(LD_TLB);
+	pr_reg(CAM);
+	pr_reg(RAM);
+	pr_reg(GFLUSH);
+	pr_reg(FLUSH_ENTRY);
+	pr_reg(READ_CAM);
+	pr_reg(READ_RAM);
+	pr_reg(EMU_FAULT_AD);
+
+	return p - buf;
+}
+
+static void omap2_iommu_save_ctx(struct iommu *obj)
+{
+	int i;
+	u32 *p = obj->ctx;
+
+	for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
+		p[i] = iommu_read_reg(obj, i * sizeof(u32));
+		dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
+	}
+
+	BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+}
+
+static void omap2_iommu_restore_ctx(struct iommu *obj)
+{
+	int i;
+	u32 *p = obj->ctx;
+
+	for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
+		iommu_write_reg(obj, p[i], i * sizeof(u32));
+		dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
+	}
+
+	BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+}
+
+static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
+{
+	e->da		= cr->cam & MMU_CAM_VATAG_MASK;
+	e->pa		= cr->ram & MMU_RAM_PADDR_MASK;
+	e->valid	= cr->cam & MMU_CAM_V;
+	e->pgsz		= cr->cam & MMU_CAM_PGSZ_MASK;
+	e->endian	= cr->ram & MMU_RAM_ENDIAN_MASK;
+	e->elsz		= cr->ram & MMU_RAM_ELSZ_MASK;
+	e->mixed	= cr->ram & MMU_RAM_MIXED;
+}
+
+static const struct iommu_functions omap2_iommu_ops = {
+	.version	= IOMMU_ARCH_VERSION,
+
+	.enable		= omap2_iommu_enable,
+	.disable	= omap2_iommu_disable,
+	.fault_isr	= omap2_iommu_fault_isr,
+
+	.tlb_read_cr	= omap2_tlb_read_cr,
+	.tlb_load_cr	= omap2_tlb_load_cr,
+
+	.cr_to_e	= omap2_cr_to_e,
+	.cr_to_virt	= omap2_cr_to_virt,
+	.alloc_cr	= omap2_alloc_cr,
+	.cr_valid	= omap2_cr_valid,
+	.dump_cr	= omap2_dump_cr,
+
+	.get_pte_attr	= omap2_get_pte_attr,
+
+	.save_ctx	= omap2_iommu_save_ctx,
+	.restore_ctx	= omap2_iommu_restore_ctx,
+	.dump_ctx	= omap2_iommu_dump_ctx,
+};
+
+static int __init omap2_iommu_init(void)
+{
+	return install_iommu_arch(&omap2_iommu_ops);
+}
+module_init(omap2_iommu_init);
+
+static void __exit omap2_iommu_exit(void)
+{
+	uninstall_iommu_arch(&omap2_iommu_ops);
+}
+module_exit(omap2_iommu_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
+MODULE_DESCRIPTION("omap iommu: omap2/3 architecture specific functions");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/irq.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,6 @@
 #define INTC_MIR_CLEAR0		0x0088
 #define INTC_MIR_SET0		0x008c
 #define INTC_PENDING_IRQ0	0x0098
-
 /* Number of IRQ state bits in each MIR register */
 #define IRQ_BITS_PER_REG	32
 
@@ -134,7 +133,6 @@
 	.ack	= omap_mask_ack_irq,
 	.mask	= omap_mask_irq,
 	.unmask	= omap_unmask_irq,
-	.disable = omap_mask_irq,
 };
 
 static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
@@ -157,6 +155,22 @@
 	intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG);
 }
 
+int omap_irq_pending(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
+		struct omap_irq_bank *bank = irq_banks + i;
+		int irq;
+
+		for (irq = 0; irq < bank->nr_irqs; irq += 32)
+			if (intc_bank_read_reg(bank, INTC_PENDING_IRQ0 +
+					       ((irq >> 5) << 5)))
+				return 1;
+	}
+	return 0;
+}
+
 void __init omap_init_irq(void)
 {
 	unsigned long nr_of_irqs = 0;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-omap2/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,7 @@
 	select ARCH_OMAP_OTG
 
 comment "OMAP Board Type"
-	depends on ARCH_OMAP2 || ARCH_OMAP3
+	depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4
 
 config MACH_OMAP_GENERIC
 	bool "Generic OMAP board"
@@ -56,6 +56,10 @@
 	bool "Gumstix Overo board"
 	depends on ARCH_OMAP3 && ARCH_OMAP34XX
 
+config MACH_OMAP3EVM
+	bool "OMAP 3530 EVM board"
+	depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
 config MACH_OMAP3_PANDORA
 	bool "OMAP3 Pandora"
 	depends on ARCH_OMAP3 && ARCH_OMAP34XX
@@ -67,3 +71,11 @@
 config MACH_NOKIA_RX51
 	bool "Nokia RX-51 board"
 	depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
+config MACH_OMAP_ZOOM2
+	bool "OMAP3 Zoom2 board"
+	depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
+config MACH_OMAP_4430SDP
+	bool "OMAP 4430 SDP board"
+	depends on ARCH_OMAP4
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mailbox.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mailbox.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mailbox.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mailbox.c	2009-09-09 18:13:59.000000000 -0400
@@ -282,12 +282,12 @@
 		return -ENOMEM;
 
 	/* DSP or IVA2 IRQ */
-	mbox_dsp_info.irq = platform_get_irq(pdev, 0);
-	if (mbox_dsp_info.irq < 0) {
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
 		dev_err(&pdev->dev, "invalid irq resource\n");
-		ret = -ENODEV;
 		goto err_dsp;
 	}
+	mbox_dsp_info.irq = ret;
 
 	ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info);
 	if (ret)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-omap2/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,12 +3,21 @@
 #
 
 # Common support
-obj-y := irq.o id.o io.o sdrc.o control.o prcm.o clock.o mux.o \
-		devices.o serial.o gpmc.o timer-gp.o powerdomain.o \
-		clockdomain.o
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
+
+omap-2-3-common				= irq.o sdrc.o
+prcm-common				= prcm.o powerdomain.o
+clock-common				= clock.o clockdomain.o
+
+obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(clock-common)
+obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
+# SMP support ONLY available for OMAP4
+obj-$(CONFIG_SMP)			+= omap-smp.o omap-headsmp.o
+obj-$(CONFIG_LOCAL_TIMERS)		+= timer-mpu.o
+
 # Functions loaded to SRAM
 obj-$(CONFIG_ARCH_OMAP2420)		+= sram242x.o
 obj-$(CONFIG_ARCH_OMAP2430)		+= sram243x.o
@@ -20,14 +29,21 @@
 
 # Power Management
 ifeq ($(CONFIG_PM),y)
-obj-y					+= pm.o
+obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP24XX)		+= sleep24xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o
+obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 endif
 
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)		+= clock24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o
 
+iommu-y					+= iommu2.o
+iommu-$(CONFIG_ARCH_OMAP3)		+= omap3-iommu.o
+
+obj-$(CONFIG_OMAP_IOMMU)		+= $(iommu-y)
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
@@ -40,6 +56,8 @@
 					   mmc-twl4030.o
 obj-$(CONFIG_MACH_OVERO)		+= board-overo.o \
 					   mmc-twl4030.o
+obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o \
+					   mmc-twl4030.o
 obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o \
 					   mmc-twl4030.o
 obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o \
@@ -48,8 +66,17 @@
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o \
 					   board-rx51-peripherals.o \
 					   mmc-twl4030.o
+obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom2.o \
+					   mmc-twl4030.o \
+					   board-zoom-debugboard.o
+
+obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o
 
 # Platform specific device init code
-ifeq ($(CONFIG_USB_MUSB_SOC),y)
 obj-y					+= usb-musb.o
-endif
+
+onenand-$(CONFIG_MTD_ONENAND_OMAP2)	:= gpmc-onenand.o
+obj-y					+= $(onenand-m) $(onenand-y)
+
+smc91x-$(CONFIG_SMC91X)			:= gpmc-smc91x.o
+obj-y					+= $(smc91x-m) $(smc91x-y)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mcbsp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mcbsp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mcbsp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mcbsp.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,6 @@
 
 #include <mach/irqs.h>
 #include <mach/dma.h>
-#include <mach/irqs.h>
 #include <mach/mux.h>
 #include <mach/cpu.h>
 #include <mach/mcbsp.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mmc-twl4030.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mmc-twl4030.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mmc-twl4030.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mmc-twl4030.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,8 +16,8 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
-#include <linux/i2c/twl4030.h>
-#include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/hardware.h>
 #include <mach/control.h>
@@ -26,31 +26,9 @@
 
 #include "mmc-twl4030.h"
 
-#if defined(CONFIG_TWL4030_CORE) && \
-	(defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
-
-#define LDO_CLR			0x00
-#define VSEL_S2_CLR		0x40
-
-#define VMMC1_DEV_GRP		0x27
-#define VMMC1_CLR		0x00
-#define VMMC1_315V		0x03
-#define VMMC1_300V		0x02
-#define VMMC1_285V		0x01
-#define VMMC1_185V		0x00
-#define VMMC1_DEDICATED		0x2A
-
-#define VMMC2_DEV_GRP		0x2B
-#define VMMC2_CLR		0x40
-#define VMMC2_315V		0x0c
-#define VMMC2_300V		0x0b
-#define VMMC2_285V		0x0a
-#define VMMC2_280V		0x09
-#define VMMC2_260V		0x08
-#define VMMC2_185V		0x06
-#define VMMC2_DEDICATED		0x2E
 
-#define VMMC_DEV_GRP_P1		0x20
+#if defined(CONFIG_REGULATOR) && \
+	(defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
 
 static u16 control_pbias_offset;
 static u16 control_devconf1_offset;
@@ -59,19 +37,16 @@
 
 static struct twl_mmc_controller {
 	struct omap_mmc_platform_data	*mmc;
-	u8		twl_vmmc_dev_grp;
-	u8		twl_mmc_dedicated;
-	char		name[HSMMC_NAME_LEN + 1];
-} hsmmc[OMAP34XX_NR_MMC] = {
-	{
-		.twl_vmmc_dev_grp		= VMMC1_DEV_GRP,
-		.twl_mmc_dedicated		= VMMC1_DEDICATED,
-	},
-	{
-		.twl_vmmc_dev_grp		= VMMC2_DEV_GRP,
-		.twl_mmc_dedicated		= VMMC2_DEDICATED,
-	},
-};
+	/* Vcc == configured supply
+	 * Vcc_alt == optional
+	 *   -	MMC1, supply for DAT4..DAT7
+	 *   -	MMC2/MMC2, external level shifter voltage supply, for
+	 *	chip (SDIO, eMMC, etc) or transceiver (MMC2 only)
+	 */
+	struct regulator		*vcc;
+	struct regulator		*vcc_aux;
+	char				name[HSMMC_NAME_LEN + 1];
+} hsmmc[OMAP34XX_NR_MMC];
 
 static int twl_mmc_card_detect(int irq)
 {
@@ -117,16 +92,61 @@
 	int ret = 0;
 	int i;
 
-	ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd");
-	if (ret)
-		goto done;
-	ret = gpio_direction_input(mmc->slots[0].switch_pin);
-	if (ret)
-		goto err;
+	/* MMC/SD/SDIO doesn't require a card detect switch */
+	if (gpio_is_valid(mmc->slots[0].switch_pin)) {
+		ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd");
+		if (ret)
+			goto done;
+		ret = gpio_direction_input(mmc->slots[0].switch_pin);
+		if (ret)
+			goto err;
+	}
 
+	/* require at least main regulator */
 	for (i = 0; i < ARRAY_SIZE(hsmmc); i++) {
 		if (hsmmc[i].name == mmc->slots[0].name) {
+			struct regulator *reg;
+
 			hsmmc[i].mmc = mmc;
+
+			reg = regulator_get(dev, "vmmc");
+			if (IS_ERR(reg)) {
+				dev_dbg(dev, "vmmc regulator missing\n");
+				/* HACK: until fixed.c regulator is usable,
+				 * we don't require a main regulator
+				 * for MMC2 or MMC3
+				 */
+				if (i != 0)
+					break;
+				ret = PTR_ERR(reg);
+				hsmmc[i].vcc = NULL;
+				goto err;
+			}
+			hsmmc[i].vcc = reg;
+			mmc->slots[0].ocr_mask = mmc_regulator_get_ocrmask(reg);
+
+			/* allow an aux regulator */
+			reg = regulator_get(dev, "vmmc_aux");
+			hsmmc[i].vcc_aux = IS_ERR(reg) ? NULL : reg;
+
+			/* UGLY HACK:  workaround regulator framework bugs.
+			 * When the bootloader leaves a supply active, it's
+			 * initialized with zero usecount ... and we can't
+			 * disable it without first enabling it.  Until the
+			 * framework is fixed, we need a workaround like this
+			 * (which is safe for MMC, but not in general).
+			 */
+			if (regulator_is_enabled(hsmmc[i].vcc) > 0) {
+				regulator_enable(hsmmc[i].vcc);
+				regulator_disable(hsmmc[i].vcc);
+			}
+			if (hsmmc[i].vcc_aux) {
+				if (regulator_is_enabled(reg) > 0) {
+					regulator_enable(reg);
+					regulator_disable(reg);
+				}
+			}
+
 			break;
 		}
 	}
@@ -146,8 +166,13 @@
 static void twl_mmc_cleanup(struct device *dev)
 {
 	struct omap_mmc_platform_data *mmc = dev->platform_data;
+	int i;
 
 	gpio_free(mmc->slots[0].switch_pin);
+	for(i = 0; i < ARRAY_SIZE(hsmmc); i++) {
+		regulator_put(hsmmc[i].vcc);
+		regulator_put(hsmmc[i].vcc_aux);
+	}
 }
 
 #ifdef CONFIG_PM
@@ -173,96 +198,6 @@
 #define twl_mmc_resume	NULL
 #endif
 
-/*
- * Sets the MMC voltage in twl4030
- */
-
-#define MMC1_OCR	(MMC_VDD_165_195 \
-		|MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
-#define MMC2_OCR	(MMC_VDD_165_195 \
-		|MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28 \
-		|MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
-
-static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
-{
-	int ret;
-	u8 vmmc = 0, dev_grp_val;
-
-	if (!vdd)
-		goto doit;
-
-	if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) {
-		/* VMMC1:  max 220 mA.  And for 8-bit mode,
-		 * VSIM:  max 50 mA
-		 */
-		switch (1 << vdd) {
-		case MMC_VDD_165_195:
-			vmmc = VMMC1_185V;
-			/* and VSIM_180V */
-			break;
-		case MMC_VDD_28_29:
-			vmmc = VMMC1_285V;
-			/* and VSIM_280V */
-			break;
-		case MMC_VDD_29_30:
-		case MMC_VDD_30_31:
-			vmmc = VMMC1_300V;
-			/* and VSIM_300V */
-			break;
-		case MMC_VDD_31_32:
-			vmmc = VMMC1_315V;
-			/* error if VSIM needed */
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) {
-		/* VMMC2:  max 100 mA */
-		switch (1 << vdd) {
-		case MMC_VDD_165_195:
-			vmmc = VMMC2_185V;
-			break;
-		case MMC_VDD_25_26:
-		case MMC_VDD_26_27:
-			vmmc = VMMC2_260V;
-			break;
-		case MMC_VDD_27_28:
-			vmmc = VMMC2_280V;
-			break;
-		case MMC_VDD_28_29:
-			vmmc = VMMC2_285V;
-			break;
-		case MMC_VDD_29_30:
-		case MMC_VDD_30_31:
-			vmmc = VMMC2_300V;
-			break;
-		case MMC_VDD_31_32:
-			vmmc = VMMC2_315V;
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
-		return -EINVAL;
-	}
-
-doit:
-	if (vdd)
-		dev_grp_val = VMMC_DEV_GRP_P1;	/* Power up */
-	else
-		dev_grp_val = LDO_CLR;		/* Power down */
-
-	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
-					dev_grp_val, c->twl_vmmc_dev_grp);
-	if (ret || !vdd)
-		return ret;
-
-	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
-					vmmc, c->twl_mmc_dedicated);
-
-	return ret;
-}
-
 static int twl_mmc1_set_power(struct device *dev, int slot, int power_on,
 				int vdd)
 {
@@ -273,11 +208,13 @@
 
 	/*
 	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
-	 * card using the same TWL VMMC1 supply (hsmmc[0]); OMAP has both
+	 * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
 	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
 	 *
 	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
 	 * is most naturally TWL VSIM; those pins also use PBIAS.
+	 *
+	 * FIXME handle VMMC1A as needed ...
 	 */
 	if (power_on) {
 		if (cpu_is_omap2430()) {
@@ -300,7 +237,7 @@
 		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
 		omap_ctrl_writel(reg, control_pbias_offset);
 
-		ret = twl_mmc_set_voltage(c, vdd);
+		ret = mmc_regulator_set_ocr(c->vcc, vdd);
 
 		/* 100ms delay required for PBIAS configuration */
 		msleep(100);
@@ -316,7 +253,7 @@
 		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
 		omap_ctrl_writel(reg, control_pbias_offset);
 
-		ret = twl_mmc_set_voltage(c, 0);
+		ret = mmc_regulator_set_ocr(c->vcc, 0);
 
 		/* 100ms delay required for PBIAS configuration */
 		msleep(100);
@@ -329,19 +266,44 @@
 	return ret;
 }
 
-static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vdd)
+static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd)
 {
-	int ret;
-	struct twl_mmc_controller *c = &hsmmc[1];
+	int ret = 0;
+	struct twl_mmc_controller *c = NULL;
 	struct omap_mmc_platform_data *mmc = dev->platform_data;
+	int i;
+
+	for (i = 1; i < ARRAY_SIZE(hsmmc); i++) {
+		if (mmc == hsmmc[i].mmc) {
+			c = &hsmmc[i];
+			break;
+		}
+	}
+
+	if (c == NULL)
+		return -ENODEV;
+
+	/* If we don't see a Vcc regulator, assume it's a fixed
+	 * voltage always-on regulator.
+	 */
+	if (!c->vcc)
+		return 0;
 
 	/*
-	 * Assume TWL VMMC2 (hsmmc[1]) is used only to power the card ... OMAP
+	 * Assume Vcc regulator is used only to power the card ... OMAP
 	 * VDDS is used to power the pins, optionally with a transceiver to
 	 * support cards using voltages other than VDDS (1.8V nominal).  When a
 	 * transceiver is used, DAT3..7 are muxed as transceiver control pins.
+	 *
+	 * In some cases this regulator won't support enable/disable;
+	 * e.g. it's a fixed rail for a WLAN chip.
+	 *
+	 * In other cases vcc_aux switches interface power.  Example, for
+	 * eMMC cards it represents VccQ.  Sometimes transceivers or SDIO
+	 * chips/cards need an interface voltage rail too.
 	 */
 	if (power_on) {
+		/* only MMC2 supports a CLKIN */
 		if (mmc->slots[0].internal_clock) {
 			u32 reg;
 
@@ -349,24 +311,23 @@
 			reg |= OMAP2_MMCSDIO2ADPCLKISEL;
 			omap_ctrl_writel(reg, control_devconf1_offset);
 		}
-		ret = twl_mmc_set_voltage(c, vdd);
+		ret = mmc_regulator_set_ocr(c->vcc, vdd);
+		/* enable interface voltage rail, if needed */
+		if (ret == 0 && c->vcc_aux) {
+			ret = regulator_enable(c->vcc_aux);
+			if (ret < 0)
+				ret = mmc_regulator_set_ocr(c->vcc, 0);
+		}
 	} else {
-		ret = twl_mmc_set_voltage(c, 0);
+		if (c->vcc_aux && (ret = regulator_is_enabled(c->vcc_aux)) > 0)
+			ret = regulator_disable(c->vcc_aux);
+		if (ret == 0)
+			ret = mmc_regulator_set_ocr(c->vcc, 0);
 	}
 
 	return ret;
 }
 
-static int twl_mmc3_set_power(struct device *dev, int slot, int power_on,
-		int vdd)
-{
-	/*
-	 * Assume MMC3 has self-powered device connected, for example on-board
-	 * chip with external power source.
-	 */
-	return 0;
-}
-
 static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
 
 void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
@@ -412,10 +373,10 @@
 		mmc->slots[0].wires = c->wires;
 		mmc->slots[0].internal_clock = !c->ext_clock;
 		mmc->dma_mask = 0xffffffff;
+		mmc->init = twl_mmc_late_init;
 
-		/* note: twl4030 card detect GPIOs normally switch VMMCx ... */
+		/* note: twl4030 card detect GPIOs can disable VMMCx ... */
 		if (gpio_is_valid(c->gpio_cd)) {
-			mmc->init = twl_mmc_late_init;
 			mmc->cleanup = twl_mmc_cleanup;
 			mmc->suspend = twl_mmc_suspend;
 			mmc->resume = twl_mmc_resume;
@@ -439,26 +400,28 @@
 		} else
 			mmc->slots[0].gpio_wp = -EINVAL;
 
-		/* NOTE:  we assume OMAP's MMC1 and MMC2 use
-		 * the TWL4030's VMMC1 and VMMC2, respectively;
-		 * and that MMC3 device has it's own power source.
+		/* NOTE:  MMC slots should have a Vcc regulator set up.
+		 * This may be from a TWL4030-family chip, another
+		 * controllable regulator, or a fixed supply.
+		 *
+		 * temporary HACK: ocr_mask instead of fixed supply
 		 */
+		mmc->slots[0].ocr_mask = c->ocr_mask;
 
 		switch (c->mmc) {
 		case 1:
+			/* on-chip level shifting via PBIAS0/PBIAS1 */
 			mmc->slots[0].set_power = twl_mmc1_set_power;
-			mmc->slots[0].ocr_mask = MMC1_OCR;
 			break;
 		case 2:
-			mmc->slots[0].set_power = twl_mmc2_set_power;
-			if (c->transceiver)
-				mmc->slots[0].ocr_mask = MMC2_OCR;
-			else
-				mmc->slots[0].ocr_mask = MMC_VDD_165_195;
-			break;
+			if (c->ext_clock)
+				c->transceiver = 1;
+			if (c->transceiver && c->wires > 4)
+				c->wires = 4;
+			/* FALLTHROUGH */
 		case 3:
-			mmc->slots[0].set_power = twl_mmc3_set_power;
-			mmc->slots[0].ocr_mask = MMC_VDD_165_195;
+			/* off-chip level shifting, or none */
+			mmc->slots[0].set_power = twl_mmc23_set_power;
 			break;
 		default:
 			pr_err("MMC%d configuration not supported!\n", c->mmc);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mmc-twl4030.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mmc-twl4030.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mmc-twl4030.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mmc-twl4030.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,9 +16,10 @@
 	int	gpio_wp;	/* or -EINVAL */
 	char	*name;		/* or NULL for default */
 	struct device *dev;	/* returned: pointer to mmc adapter */
+	int	ocr_mask;	/* temporary HACK */
 };
 
-#if	defined(CONFIG_TWL4030_CORE) && \
+#if defined(CONFIG_REGULATOR) && \
 	(defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
 	 defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE))
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mux.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mux.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/mux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/mux.c	2009-09-09 18:13:59.000000000 -0400
@@ -486,6 +486,12 @@
 		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
 MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6,
 		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+
+/* OMAP3 SDRC CKE signals to SDR/DDR ram chips */
+MUX_CFG_34XX("H16_34XX_SDRC_CKE0", 0x262,
+		OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("H17_34XX_SDRC_CKE1", 0x264,
+		OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
 };
 
 #define OMAP34XX_PINS_SZ	ARRAY_SIZE(omap34xx_pins)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/omap3-iommu.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/omap3-iommu.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/omap3-iommu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/omap3-iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * omap iommu: omap3 device registration
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+
+#include <mach/iommu.h>
+
+#define OMAP3_MMU1_BASE	0x480bd400
+#define OMAP3_MMU2_BASE	0x5d000000
+#define OMAP3_MMU1_IRQ	24
+#define OMAP3_MMU2_IRQ	28
+
+
+static unsigned long iommu_base[] __initdata = {
+	OMAP3_MMU1_BASE,
+	OMAP3_MMU2_BASE,
+};
+
+static int iommu_irq[] __initdata = {
+	OMAP3_MMU1_IRQ,
+	OMAP3_MMU2_IRQ,
+};
+
+static const struct iommu_platform_data omap3_iommu_pdata[] __initconst = {
+	{
+		.name = "isp",
+		.nr_tlb_entries = 8,
+		.clk_name = "cam_ick",
+	},
+#if defined(CONFIG_MPU_BRIDGE_IOMMU)
+	{
+		.name = "iva2",
+		.nr_tlb_entries = 32,
+		.clk_name = "iva2_ck",
+	},
+#endif
+};
+#define NR_IOMMU_DEVICES ARRAY_SIZE(omap3_iommu_pdata)
+
+static struct platform_device *omap3_iommu_pdev[NR_IOMMU_DEVICES];
+
+static int __init omap3_iommu_init(void)
+{
+	int i, err;
+
+	for (i = 0; i < NR_IOMMU_DEVICES; i++) {
+		struct platform_device *pdev;
+		struct resource res[2];
+
+		pdev = platform_device_alloc("omap-iommu", i);
+		if (!pdev) {
+			err = -ENOMEM;
+			goto err_out;
+		}
+
+		memset(res, 0,  sizeof(res));
+		res[0].start = iommu_base[i];
+		res[0].end = iommu_base[i] + MMU_REG_SIZE - 1;
+		res[0].flags = IORESOURCE_MEM;
+		res[1].start = res[1].end = iommu_irq[i];
+		res[1].flags = IORESOURCE_IRQ;
+
+		err = platform_device_add_resources(pdev, res,
+						    ARRAY_SIZE(res));
+		if (err)
+			goto err_out;
+		err = platform_device_add_data(pdev, &omap3_iommu_pdata[i],
+					       sizeof(omap3_iommu_pdata[0]));
+		if (err)
+			goto err_out;
+		err = platform_device_add(pdev);
+		if (err)
+			goto err_out;
+		omap3_iommu_pdev[i] = pdev;
+	}
+	return 0;
+
+err_out:
+	while (i--)
+		platform_device_put(omap3_iommu_pdev[i]);
+	return err;
+}
+module_init(omap3_iommu_init);
+
+static void __exit omap3_iommu_exit(void)
+{
+	int i;
+
+	for (i = 0; i < NR_IOMMU_DEVICES; i++)
+		platform_device_unregister(omap3_iommu_pdev[i]);
+}
+module_exit(omap3_iommu_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU");
+MODULE_DESCRIPTION("omap iommu: omap3 device registration");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/omap-headsmp.S linux-libre-2.6.31-gnu/arch/arm/mach-omap2/omap-headsmp.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/omap-headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/omap-headsmp.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * Secondary CPU startup routine source file.
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author:
+ *      Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Interface functions needed for the SMP. This file is based on arm
+ * realview smp platform.
+ * Copyright (c) 2003 ARM Limited.
+ *
+ * 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.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+/* Physical address needed since MMU not enabled yet on secondary core */
+#define OMAP4_AUX_CORE_BOOT1_PA			0x48281804
+
+	__INIT
+
+/*
+ * OMAP4 specific entry point for secondary CPU to jump from ROM
+ * code.  This routine also provides a holding flag into which
+ * secondary core is held until we're ready for it to initialise.
+ * The primary core will update the this flag using a hardware
+ * register AuxCoreBoot1.
+ */
+ENTRY(omap_secondary_startup)
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #0x0f
+hold:	ldr	r1, =OMAP4_AUX_CORE_BOOT1_PA	@ read from AuxCoreBoot1
+	ldr	r2, [r1]
+	cmp	r2, r0
+	bne	hold
+
+	/*
+	 * we've been released from the cpu_release,secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/omap-smp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/omap-smp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/omap-smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/omap-smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,178 @@
+/*
+ * OMAP4 SMP source file. It contains platform specific fucntions
+ * needed for the linux smp kernel.
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author:
+ *      Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Platform file needed for the OMAP4 SMP. This file is based on arm
+ * realview smp platform.
+ * * Copyright (c) 2002 ARM Limited.
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/localtimer.h>
+#include <asm/smp_scu.h>
+#include <mach/hardware.h>
+
+/* Registers used for communicating startup information */
+#define OMAP4_AUXCOREBOOT_REG0		(OMAP44XX_VA_WKUPGEN_BASE + 0x800)
+#define OMAP4_AUXCOREBOOT_REG1		(OMAP44XX_VA_WKUPGEN_BASE + 0x804)
+
+/* SCU base address */
+static void __iomem *scu_base = OMAP44XX_VA_SCU_BASE;
+
+/*
+ * Use SCU config register to count number of cores
+ */
+static inline unsigned int get_core_count(void)
+{
+	if (scu_base)
+		return scu_get_core_count(scu_base);
+	return 1;
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	trace_hardirqs_off();
+
+	/*
+	 * If any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+
+	gic_cpu_init(0, IO_ADDRESS(OMAP44XX_GIC_CPU_BASE));
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * Update the AuxCoreBoot1 with boot state for secondary core.
+	 * omap_secondary_startup() routine will hold the secondary core till
+	 * the AuxCoreBoot1 register is updated with cpu state
+	 * A barrier is added to ensure that write buffer is drained
+	 */
+	__raw_writel(cpu, OMAP4_AUXCOREBOOT_REG1);
+	smp_wmb();
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout))
+		;
+
+	/*
+	 * Now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return 0;
+}
+
+static void __init wakeup_secondary(void)
+{
+	/*
+	 * Write the address of secondary startup routine into the
+	 * AuxCoreBoot0 where ROM code will jump and start executing
+	 * on secondary core once out of WFE
+	 * A barrier is added to ensure that write buffer is drained
+	 */
+	__raw_writel(virt_to_phys(omap_secondary_startup),	   \
+					OMAP4_AUXCOREBOOT_REG0);
+	smp_wmb();
+
+	/*
+	 * Send a 'sev' to wake the secondary core from WFE.
+	 */
+	set_event();
+	mb();
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	unsigned int i, ncores = get_core_count();
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned int ncores = get_core_count();
+	unsigned int cpu = smp_processor_id();
+	int i;
+
+	/* sanity check */
+	if (ncores == 0) {
+		printk(KERN_ERR
+		       "OMAP4: strange core count of 0? Default to 1\n");
+		ncores = 1;
+	}
+
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "OMAP4: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+	smp_store_cpu_info(cpu);
+
+	/*
+	 * are we trying to boot more cores than exist?
+	 */
+	if (max_cpus > ncores)
+		max_cpus = ncores;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	if (max_cpus > 1) {
+		/*
+		 * Enable the local timer or broadcast device for the
+		 * boot CPU, but only if we have more than one CPU.
+		 */
+		percpu_timer_setup();
+
+		/*
+		 * Initialise the SCU and wake up the secondary core using
+		 * wakeup_secondary().
+		 */
+		scu_enable(scu_base);
+		wakeup_secondary();
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm24xx.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm24xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm24xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm24xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,549 @@
+/*
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * Written by:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Tony Lindgren
+ * Juha Yrjola
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Igor Stoppa <igor.stoppa@nokia.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * 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.
+ */
+
+#include <linux/suspend.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/time.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/irqs.h>
+#include <mach/clock.h>
+#include <mach/sram.h>
+#include <mach/control.h>
+#include <mach/mux.h>
+#include <mach/dma.h>
+#include <mach/board.h>
+
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "cm.h"
+#include "cm-regbits-24xx.h"
+#include "sdrc.h"
+#include "pm.h"
+
+#include <mach/powerdomain.h>
+#include <mach/clockdomain.h>
+
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
+				  void __iomem *sdrc_power);
+
+static struct powerdomain *mpu_pwrdm;
+static struct powerdomain *core_pwrdm;
+
+static struct clockdomain *dsp_clkdm;
+static struct clockdomain *gfx_clkdm;
+
+static struct clk *osc_ck, *emul_ck;
+
+static int omap2_fclks_active(void)
+{
+	u32 f1, f2;
+
+	f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+
+	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
+	f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2);
+	f2 &= ~OMAP24XX_EN_UART3;
+
+	if (f1 | f2)
+		return 1;
+	return 0;
+}
+
+static void omap2_enter_full_retention(void)
+{
+	u32 l;
+	struct timespec ts_preidle, ts_postidle, ts_idle;
+
+	/* There is 1 reference hold for all children of the oscillator
+	 * clock, the following will remove it. If no one else uses the
+	 * oscillator itself it will be disabled if/when we enter retention
+	 * mode.
+	 */
+	clk_disable(osc_ck);
+
+	/* Clear old wake-up events */
+	/* REVISIT: These write to reserved bits? */
+	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+	prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+
+	/*
+	 * Set MPU powerdomain's next power state to RETENTION;
+	 * preserve logic state during retention
+	 */
+	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+
+	/* Workaround to kill USB */
+	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
+	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
+
+	omap2_gpio_prepare_for_retention();
+
+	if (omap2_pm_debug) {
+		omap2_pm_dump(0, 0, 0);
+		getnstimeofday(&ts_preidle);
+	}
+
+	/* One last check for pending IRQs to avoid extra latency due
+	 * to sleeping unnecessarily. */
+	if (omap_irq_pending())
+		goto no_sleep;
+
+	omap_uart_prepare_idle(0);
+	omap_uart_prepare_idle(1);
+	omap_uart_prepare_idle(2);
+
+	/* Jump to SRAM suspend code */
+	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
+			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
+			   OMAP_SDRC_REGADDR(SDRC_POWER));
+
+	omap_uart_resume_idle(2);
+	omap_uart_resume_idle(1);
+	omap_uart_resume_idle(0);
+
+no_sleep:
+	if (omap2_pm_debug) {
+		unsigned long long tmp;
+
+		getnstimeofday(&ts_postidle);
+		ts_idle = timespec_sub(ts_postidle, ts_preidle);
+		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
+		omap2_pm_dump(0, 1, tmp);
+	}
+	omap2_gpio_resume_after_retention();
+
+	clk_enable(osc_ck);
+
+	/* clear CORE wake-up events */
+	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+
+	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
+	prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
+
+	/* MPU domain wake events */
+	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	if (l & 0x01)
+		prm_write_mod_reg(0x01, OCP_MOD,
+				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+	if (l & 0x20)
+		prm_write_mod_reg(0x20, OCP_MOD,
+				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+
+	/* Mask future PRCM-to-MPU interrupts */
+	prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+}
+
+static int omap2_i2c_active(void)
+{
+	u32 l;
+
+	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	return l & (OMAP2420_EN_I2C2 | OMAP2420_EN_I2C1);
+}
+
+static int sti_console_enabled;
+
+static int omap2_allow_mpu_retention(void)
+{
+	u32 l;
+
+	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
+	l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	if (l & (OMAP2420_EN_MMC | OMAP24XX_EN_UART2 |
+		 OMAP24XX_EN_UART1 | OMAP24XX_EN_MCSPI2 |
+		 OMAP24XX_EN_MCSPI1 | OMAP24XX_EN_DSS1))
+		return 0;
+	/* Check for UART3. */
+	l = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+	if (l & OMAP24XX_EN_UART3)
+		return 0;
+	if (sti_console_enabled)
+		return 0;
+
+	return 1;
+}
+
+static void omap2_enter_mpu_retention(void)
+{
+	int only_idle = 0;
+	struct timespec ts_preidle, ts_postidle, ts_idle;
+
+	/* Putting MPU into the WFI state while a transfer is active
+	 * seems to cause the I2C block to timeout. Why? Good question. */
+	if (omap2_i2c_active())
+		return;
+
+	/* The peripherals seem not to be able to wake up the MPU when
+	 * it is in retention mode. */
+	if (omap2_allow_mpu_retention()) {
+		/* REVISIT: These write to reserved bits? */
+		prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
+		prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+		prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+
+		/* Try to enter MPU retention */
+		prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
+				  OMAP_LOGICRETSTATE,
+				  MPU_MOD, PM_PWSTCTRL);
+	} else {
+		/* Block MPU retention */
+
+		prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL);
+		only_idle = 1;
+	}
+
+	if (omap2_pm_debug) {
+		omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
+		getnstimeofday(&ts_preidle);
+	}
+
+	omap2_sram_idle();
+
+	if (omap2_pm_debug) {
+		unsigned long long tmp;
+
+		getnstimeofday(&ts_postidle);
+		ts_idle = timespec_sub(ts_postidle, ts_preidle);
+		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
+		omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
+	}
+}
+
+static int omap2_can_sleep(void)
+{
+	if (omap2_fclks_active())
+		return 0;
+	if (osc_ck->usecount > 1)
+		return 0;
+	if (omap_dma_running())
+		return 0;
+
+	return 1;
+}
+
+static void omap2_pm_idle(void)
+{
+	local_irq_disable();
+	local_fiq_disable();
+
+	if (!omap2_can_sleep()) {
+		if (omap_irq_pending())
+			goto out;
+		omap2_enter_mpu_retention();
+		goto out;
+	}
+
+	if (omap_irq_pending())
+		goto out;
+
+	omap2_enter_full_retention();
+
+out:
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static int omap2_pm_prepare(void)
+{
+	/* We cannot sleep in idle until we have resumed */
+	disable_hlt();
+	return 0;
+}
+
+static int omap2_pm_suspend(void)
+{
+	u32 wken_wkup, mir1;
+
+	wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+	prm_write_mod_reg(wken_wkup & ~OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN);
+
+	/* Mask GPT1 */
+	mir1 = omap_readl(0x480fe0a4);
+	omap_writel(1 << 5, 0x480fe0ac);
+
+	omap_uart_prepare_suspend();
+	omap2_enter_full_retention();
+
+	omap_writel(mir1, 0x480fe0a4);
+	prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN);
+
+	return 0;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = omap2_pm_suspend();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void omap2_pm_finish(void)
+{
+	enable_hlt();
+}
+
+static struct platform_suspend_ops omap_pm_ops = {
+	.prepare	= omap2_pm_prepare,
+	.enter		= omap2_pm_enter,
+	.finish		= omap2_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm)
+{
+	omap2_clkdm_allow_idle(clkdm);
+	return 0;
+}
+
+static void __init prcm_setup_regs(void)
+{
+	int i, num_mem_banks;
+	struct powerdomain *pwrdm;
+
+	/* Enable autoidle */
+	prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD,
+			  OMAP2_PRCM_SYSCONFIG_OFFSET);
+
+	/* Set all domain wakeup dependencies */
+	prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, CORE_MOD, PM_WKDEP);
+	if (cpu_is_omap2430())
+		prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP);
+
+	/*
+	 * Set CORE powerdomain memory banks to retain their contents
+	 * during RETENTION
+	 */
+	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
+	for (i = 0; i < num_mem_banks; i++)
+		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
+
+	/* Set CORE powerdomain's next power state to RETENTION */
+	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
+
+	/*
+	 * Set MPU powerdomain's next power state to RETENTION;
+	 * preserve logic state during retention
+	 */
+	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+
+	/* Force-power down DSP, GFX powerdomains */
+
+	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
+	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap2_clkdm_sleep(dsp_clkdm);
+
+	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
+	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap2_clkdm_sleep(gfx_clkdm);
+
+	/* Enable clockdomain hardware-supervised control for all clkdms */
+	clkdm_for_each(_pm_clkdm_enable_hwsup);
+
+	/* Enable clock autoidle for all domains */
+	cm_write_mod_reg(OMAP24XX_AUTO_CAM |
+			 OMAP24XX_AUTO_MAILBOXES |
+			 OMAP24XX_AUTO_WDT4 |
+			 OMAP2420_AUTO_WDT3 |
+			 OMAP24XX_AUTO_MSPRO |
+			 OMAP2420_AUTO_MMC |
+			 OMAP24XX_AUTO_FAC |
+			 OMAP2420_AUTO_EAC |
+			 OMAP24XX_AUTO_HDQ |
+			 OMAP24XX_AUTO_UART2 |
+			 OMAP24XX_AUTO_UART1 |
+			 OMAP24XX_AUTO_I2C2 |
+			 OMAP24XX_AUTO_I2C1 |
+			 OMAP24XX_AUTO_MCSPI2 |
+			 OMAP24XX_AUTO_MCSPI1 |
+			 OMAP24XX_AUTO_MCBSP2 |
+			 OMAP24XX_AUTO_MCBSP1 |
+			 OMAP24XX_AUTO_GPT12 |
+			 OMAP24XX_AUTO_GPT11 |
+			 OMAP24XX_AUTO_GPT10 |
+			 OMAP24XX_AUTO_GPT9 |
+			 OMAP24XX_AUTO_GPT8 |
+			 OMAP24XX_AUTO_GPT7 |
+			 OMAP24XX_AUTO_GPT6 |
+			 OMAP24XX_AUTO_GPT5 |
+			 OMAP24XX_AUTO_GPT4 |
+			 OMAP24XX_AUTO_GPT3 |
+			 OMAP24XX_AUTO_GPT2 |
+			 OMAP2420_AUTO_VLYNQ |
+			 OMAP24XX_AUTO_DSS,
+			 CORE_MOD, CM_AUTOIDLE1);
+	cm_write_mod_reg(OMAP24XX_AUTO_UART3 |
+			 OMAP24XX_AUTO_SSI |
+			 OMAP24XX_AUTO_USB,
+			 CORE_MOD, CM_AUTOIDLE2);
+	cm_write_mod_reg(OMAP24XX_AUTO_SDRC |
+			 OMAP24XX_AUTO_GPMC |
+			 OMAP24XX_AUTO_SDMA,
+			 CORE_MOD, CM_AUTOIDLE3);
+	cm_write_mod_reg(OMAP24XX_AUTO_PKA |
+			 OMAP24XX_AUTO_AES |
+			 OMAP24XX_AUTO_RNG |
+			 OMAP24XX_AUTO_SHA |
+			 OMAP24XX_AUTO_DES,
+			 CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
+
+	cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+
+	/* Put DPLL and both APLLs into autoidle mode */
+	cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
+			 (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
+			 (0x03 << OMAP24XX_AUTO_54M_SHIFT),
+			 PLL_MOD, CM_AUTOIDLE);
+
+	cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL |
+			 OMAP24XX_AUTO_WDT1 |
+			 OMAP24XX_AUTO_MPU_WDT |
+			 OMAP24XX_AUTO_GPIOS |
+			 OMAP24XX_AUTO_32KSYNC |
+			 OMAP24XX_AUTO_GPT1,
+			 WKUP_MOD, CM_AUTOIDLE);
+
+	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
+	 * stabilisation */
+	prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+			  OMAP2_PRCM_CLKSSETUP_OFFSET);
+
+	/* Configure automatic voltage transition */
+	prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+			  OMAP2_PRCM_VOLTSETUP_OFFSET);
+	prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT |
+			  (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
+			  OMAP24XX_MEMRETCTRL |
+			  (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
+			  (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
+			  OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);
+
+	/* Enable wake-up events */
+	prm_write_mod_reg(OMAP24XX_EN_GPIOS | OMAP24XX_EN_GPT1,
+			  WKUP_MOD, PM_WKEN);
+}
+
+static int __init omap2_pm_init(void)
+{
+	u32 l;
+
+	if (!cpu_is_omap24xx())
+		return -ENODEV;
+
+	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
+	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
+	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
+
+	/* Look up important powerdomains, clockdomains */
+
+	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+	if (!mpu_pwrdm)
+		pr_err("PM: mpu_pwrdm not found\n");
+
+	core_pwrdm = pwrdm_lookup("core_pwrdm");
+	if (!core_pwrdm)
+		pr_err("PM: core_pwrdm not found\n");
+
+	dsp_clkdm = clkdm_lookup("dsp_clkdm");
+	if (!dsp_clkdm)
+		pr_err("PM: mpu_clkdm not found\n");
+
+	gfx_clkdm = clkdm_lookup("gfx_clkdm");
+	if (!gfx_clkdm)
+		pr_err("PM: gfx_clkdm not found\n");
+
+
+	osc_ck = clk_get(NULL, "osc_ck");
+	if (IS_ERR(osc_ck)) {
+		printk(KERN_ERR "could not get osc_ck\n");
+		return -ENODEV;
+	}
+
+	if (cpu_is_omap242x()) {
+		emul_ck = clk_get(NULL, "emul_ck");
+		if (IS_ERR(emul_ck)) {
+			printk(KERN_ERR "could not get emul_ck\n");
+			clk_put(osc_ck);
+			return -ENODEV;
+		}
+	}
+
+	prcm_setup_regs();
+
+	/* Hack to prevent MPU retention when STI console is enabled. */
+	{
+		const struct omap_sti_console_config *sti;
+
+		sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
+				      struct omap_sti_console_config);
+		if (sti != NULL && sti->enable)
+			sti_console_enabled = 1;
+	}
+
+	/*
+	 * We copy the assembler sleep/wakeup routines to SRAM.
+	 * These routines need to be in SRAM as that's the only
+	 * memory the MPU can see when it wakes up.
+	 */
+	if (cpu_is_omap24xx()) {
+		omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+						 omap24xx_idle_loop_suspend_sz);
+
+		omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+						    omap24xx_cpu_suspend_sz);
+	}
+
+	suspend_set_ops(&omap_pm_ops);
+	pm_idle = omap2_pm_idle;
+
+	return 0;
+}
+
+late_initcall(omap2_pm_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm34xx.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm34xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm34xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm34xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,753 @@
+/*
+ * OMAP3 Power Management Routines
+ *
+ * Copyright (C) 2006-2008 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Jouni Hogander
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * 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.
+ */
+
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+
+#include <mach/sram.h>
+#include <mach/clockdomain.h>
+#include <mach/powerdomain.h>
+#include <mach/control.h>
+#include <mach/serial.h>
+
+#include "cm.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+
+#include "prm.h"
+#include "pm.h"
+
+struct power_state {
+	struct powerdomain *pwrdm;
+	u32 next_state;
+#ifdef CONFIG_SUSPEND
+	u32 saved_state;
+#endif
+	struct list_head node;
+};
+
+static LIST_HEAD(pwrst_list);
+
+static void (*_omap_sram_idle)(u32 *addr, int save_state);
+
+static struct powerdomain *mpu_pwrdm;
+
+/* PRCM Interrupt Handler for wakeups */
+static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
+{
+	u32 wkst, irqstatus_mpu;
+	u32 fclk, iclk;
+
+	/* WKUP */
+	wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST);
+	if (wkst) {
+		iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
+		fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
+		cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN);
+		cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN);
+		prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST);
+		while (prm_read_mod_reg(WKUP_MOD, PM_WKST))
+			cpu_relax();
+		cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN);
+		cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN);
+	}
+
+	/* CORE */
+	wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1);
+	if (wkst) {
+		iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
+		fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1);
+		prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1);
+		while (prm_read_mod_reg(CORE_MOD, PM_WKST1))
+			cpu_relax();
+		cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1);
+		cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1);
+	}
+	wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3);
+	if (wkst) {
+		iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
+		fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3);
+		cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+		prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3);
+		while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3))
+			cpu_relax();
+		cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3);
+		cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
+	}
+
+	/* PER */
+	wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST);
+	if (wkst) {
+		iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
+		fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
+		cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN);
+		cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN);
+		prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST);
+		while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST))
+			cpu_relax();
+		cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN);
+		cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN);
+	}
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		/* USBHOST */
+		wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST);
+		if (wkst) {
+			iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+					       CM_ICLKEN);
+			fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+					       CM_FCLKEN);
+			cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
+					    CM_ICLKEN);
+			cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD,
+					    CM_FCLKEN);
+			prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD,
+					  PM_WKST);
+			while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+						PM_WKST))
+				cpu_relax();
+			cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD,
+					 CM_ICLKEN);
+			cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD,
+					 CM_FCLKEN);
+		}
+	}
+
+	irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
+					 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
+			  OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+	while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET))
+		cpu_relax();
+
+	return IRQ_HANDLED;
+}
+
+static void omap_sram_idle(void)
+{
+	/* Variable to tell what needs to be saved and restored
+	 * in omap_sram_idle*/
+	/* save_state = 0 => Nothing to save and restored */
+	/* save_state = 1 => Only L1 and logic lost */
+	/* save_state = 2 => Only L2 lost */
+	/* save_state = 3 => L1, L2 and logic lost */
+	int save_state = 0, mpu_next_state;
+
+	if (!_omap_sram_idle)
+		return;
+
+	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+	switch (mpu_next_state) {
+	case PWRDM_POWER_RET:
+		/* No need to save context */
+		save_state = 0;
+		break;
+	default:
+		/* Invalid state */
+		printk(KERN_ERR "Invalid mpu state in sram_idle\n");
+		return;
+	}
+	omap2_gpio_prepare_for_retention();
+	omap_uart_prepare_idle(0);
+	omap_uart_prepare_idle(1);
+	omap_uart_prepare_idle(2);
+
+	_omap_sram_idle(NULL, save_state);
+	cpu_init();
+
+	omap_uart_resume_idle(2);
+	omap_uart_resume_idle(1);
+	omap_uart_resume_idle(0);
+	omap2_gpio_resume_after_retention();
+}
+
+/*
+ * Check if functional clocks are enabled before entering
+ * sleep. This function could be behind CONFIG_PM_DEBUG
+ * when all drivers are configuring their sysconfig registers
+ * properly and using their clocks properly.
+ */
+static int omap3_fclks_active(void)
+{
+	u32 fck_core1 = 0, fck_core3 = 0, fck_sgx = 0, fck_dss = 0,
+		fck_cam = 0, fck_per = 0, fck_usbhost = 0;
+
+	fck_core1 = cm_read_mod_reg(CORE_MOD,
+				    CM_FCLKEN1);
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		fck_core3 = cm_read_mod_reg(CORE_MOD,
+					    OMAP3430ES2_CM_FCLKEN3);
+		fck_sgx = cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
+					  CM_FCLKEN);
+		fck_usbhost = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
+					      CM_FCLKEN);
+	} else
+		fck_sgx = cm_read_mod_reg(GFX_MOD,
+					  OMAP3430ES2_CM_FCLKEN3);
+	fck_dss = cm_read_mod_reg(OMAP3430_DSS_MOD,
+				  CM_FCLKEN);
+	fck_cam = cm_read_mod_reg(OMAP3430_CAM_MOD,
+				  CM_FCLKEN);
+	fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
+				  CM_FCLKEN);
+
+	/* Ignore UART clocks.  These are handled by UART core (serial.c) */
+	fck_core1 &= ~(OMAP3430_EN_UART1 | OMAP3430_EN_UART2);
+	fck_per &= ~OMAP3430_EN_UART3;
+
+	if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
+	    fck_cam | fck_per | fck_usbhost)
+		return 1;
+	return 0;
+}
+
+static int omap3_can_sleep(void)
+{
+	if (!omap_uart_can_sleep())
+		return 0;
+	if (omap3_fclks_active())
+		return 0;
+	return 1;
+}
+
+/* This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported. Function is assuming that clkdm doesn't have
+ * hw_sup mode enabled. */
+static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
+{
+	u32 cur_state;
+	int sleep_switch = 0;
+	int ret = 0;
+
+	if (pwrdm == NULL || IS_ERR(pwrdm))
+		return -EINVAL;
+
+	while (!(pwrdm->pwrsts & (1 << state))) {
+		if (state == PWRDM_POWER_OFF)
+			return ret;
+		state--;
+	}
+
+	cur_state = pwrdm_read_next_pwrst(pwrdm);
+	if (cur_state == state)
+		return ret;
+
+	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
+		omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+		sleep_switch = 1;
+		pwrdm_wait_transition(pwrdm);
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, state);
+	if (ret) {
+		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
+		       pwrdm->name);
+		goto err;
+	}
+
+	if (sleep_switch) {
+		omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		pwrdm_wait_transition(pwrdm);
+	}
+
+err:
+	return ret;
+}
+
+static void omap3_pm_idle(void)
+{
+	local_irq_disable();
+	local_fiq_disable();
+
+	if (!omap3_can_sleep())
+		goto out;
+
+	if (omap_irq_pending())
+		goto out;
+
+	omap_sram_idle();
+
+out:
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state;
+
+static int omap3_pm_prepare(void)
+{
+	disable_hlt();
+	return 0;
+}
+
+static int omap3_pm_suspend(void)
+{
+	struct power_state *pwrst;
+	int state, ret = 0;
+
+	/* Read current next_pwrsts */
+	list_for_each_entry(pwrst, &pwrst_list, node)
+		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+	/* Set ones wanted by suspend */
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
+			goto restore;
+		if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
+			goto restore;
+	}
+
+	omap_uart_prepare_suspend();
+	omap_sram_idle();
+
+restore:
+	/* Restore next_pwrsts */
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+		if (state > pwrst->next_state) {
+			printk(KERN_INFO "Powerdomain (%s) didn't enter "
+			       "target state %d\n",
+			       pwrst->pwrdm->name, pwrst->next_state);
+			ret = -1;
+		}
+		set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+	}
+	if (ret)
+		printk(KERN_ERR "Could not enter target state in pm_suspend\n");
+	else
+		printk(KERN_INFO "Successfully put all powerdomains "
+		       "to target state\n");
+
+	return ret;
+}
+
+static int omap3_pm_enter(suspend_state_t unused)
+{
+	int ret = 0;
+
+	switch (suspend_state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = omap3_pm_suspend();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void omap3_pm_finish(void)
+{
+	enable_hlt();
+}
+
+/* Hooks to enable / disable UART interrupts during suspend */
+static int omap3_pm_begin(suspend_state_t state)
+{
+	suspend_state = state;
+	omap_uart_enable_irqs(0);
+	return 0;
+}
+
+static void omap3_pm_end(void)
+{
+	suspend_state = PM_SUSPEND_ON;
+	omap_uart_enable_irqs(1);
+	return;
+}
+
+static struct platform_suspend_ops omap_pm_ops = {
+	.begin		= omap3_pm_begin,
+	.end		= omap3_pm_end,
+	.prepare	= omap3_pm_prepare,
+	.enter		= omap3_pm_enter,
+	.finish		= omap3_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+#endif /* CONFIG_SUSPEND */
+
+
+/**
+ * omap3_iva_idle(): ensure IVA is in idle so it can be put into
+ *                   retention
+ *
+ * In cases where IVA2 is activated by bootcode, it may prevent
+ * full-chip retention or off-mode because it is not idle.  This
+ * function forces the IVA2 into idle state so it can go
+ * into retention/off and thus allow full-chip retention/off.
+ *
+ **/
+static void __init omap3_iva_idle(void)
+{
+	/* ensure IVA2 clock is disabled */
+	cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* if no clock activity, nothing else to do */
+	if (!(cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
+	      OMAP3430_CLKACTIVITY_IVA2_MASK))
+		return;
+
+	/* Reset IVA2 */
+	prm_write_mod_reg(OMAP3430_RST1_IVA2 |
+			  OMAP3430_RST2_IVA2 |
+			  OMAP3430_RST3_IVA2,
+			  OMAP3430_IVA2_MOD, RM_RSTCTRL);
+
+	/* Enable IVA2 clock */
+	cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2,
+			 OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* Set IVA2 boot mode to 'idle' */
+	omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
+			 OMAP343X_CONTROL_IVA2_BOOTMOD);
+
+	/* Un-reset IVA2 */
+	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, RM_RSTCTRL);
+
+	/* Disable IVA2 clock */
+	cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+	/* Reset IVA2 */
+	prm_write_mod_reg(OMAP3430_RST1_IVA2 |
+			  OMAP3430_RST2_IVA2 |
+			  OMAP3430_RST3_IVA2,
+			  OMAP3430_IVA2_MOD, RM_RSTCTRL);
+}
+
+static void __init omap3_d2d_idle(void)
+{
+	u16 mask, padconf;
+
+	/* In a stand alone OMAP3430 where there is not a stacked
+	 * modem for the D2D Idle Ack and D2D MStandby must be pulled
+	 * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
+	 * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. */
+	mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
+
+	padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
+	padconf |= mask;
+	omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
+
+	/* reset modem */
+	prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON |
+			  OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST,
+			  CORE_MOD, RM_RSTCTRL);
+	prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL);
+}
+
+static void __init prcm_setup_regs(void)
+{
+	/* XXX Reset all wkdeps. This should be done when initializing
+	 * powerdomains */
+	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
+	prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
+		prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
+	} else
+		prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
+
+	/*
+	 * Enable interface clock autoidle for all modules.
+	 * Note that in the long run this should be done by clockfw
+	 */
+	cm_write_mod_reg(
+		OMAP3430_AUTO_MODEM |
+		OMAP3430ES2_AUTO_MMC3 |
+		OMAP3430ES2_AUTO_ICR |
+		OMAP3430_AUTO_AES2 |
+		OMAP3430_AUTO_SHA12 |
+		OMAP3430_AUTO_DES2 |
+		OMAP3430_AUTO_MMC2 |
+		OMAP3430_AUTO_MMC1 |
+		OMAP3430_AUTO_MSPRO |
+		OMAP3430_AUTO_HDQ |
+		OMAP3430_AUTO_MCSPI4 |
+		OMAP3430_AUTO_MCSPI3 |
+		OMAP3430_AUTO_MCSPI2 |
+		OMAP3430_AUTO_MCSPI1 |
+		OMAP3430_AUTO_I2C3 |
+		OMAP3430_AUTO_I2C2 |
+		OMAP3430_AUTO_I2C1 |
+		OMAP3430_AUTO_UART2 |
+		OMAP3430_AUTO_UART1 |
+		OMAP3430_AUTO_GPT11 |
+		OMAP3430_AUTO_GPT10 |
+		OMAP3430_AUTO_MCBSP5 |
+		OMAP3430_AUTO_MCBSP1 |
+		OMAP3430ES1_AUTO_FAC | /* This is es1 only */
+		OMAP3430_AUTO_MAILBOXES |
+		OMAP3430_AUTO_OMAPCTRL |
+		OMAP3430ES1_AUTO_FSHOSTUSB |
+		OMAP3430_AUTO_HSOTGUSB |
+		OMAP3430_AUTO_SAD2D |
+		OMAP3430_AUTO_SSI,
+		CORE_MOD, CM_AUTOIDLE1);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_PKA |
+		OMAP3430_AUTO_AES1 |
+		OMAP3430_AUTO_RNG |
+		OMAP3430_AUTO_SHA11 |
+		OMAP3430_AUTO_DES1,
+		CORE_MOD, CM_AUTOIDLE2);
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		cm_write_mod_reg(
+			OMAP3430_AUTO_MAD2D |
+			OMAP3430ES2_AUTO_USBTLL,
+			CORE_MOD, CM_AUTOIDLE3);
+	}
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_WDT2 |
+		OMAP3430_AUTO_WDT1 |
+		OMAP3430_AUTO_GPIO1 |
+		OMAP3430_AUTO_32KSYNC |
+		OMAP3430_AUTO_GPT12 |
+		OMAP3430_AUTO_GPT1 ,
+		WKUP_MOD, CM_AUTOIDLE);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_DSS,
+		OMAP3430_DSS_MOD,
+		CM_AUTOIDLE);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_CAM,
+		OMAP3430_CAM_MOD,
+		CM_AUTOIDLE);
+
+	cm_write_mod_reg(
+		OMAP3430_AUTO_GPIO6 |
+		OMAP3430_AUTO_GPIO5 |
+		OMAP3430_AUTO_GPIO4 |
+		OMAP3430_AUTO_GPIO3 |
+		OMAP3430_AUTO_GPIO2 |
+		OMAP3430_AUTO_WDT3 |
+		OMAP3430_AUTO_UART3 |
+		OMAP3430_AUTO_GPT9 |
+		OMAP3430_AUTO_GPT8 |
+		OMAP3430_AUTO_GPT7 |
+		OMAP3430_AUTO_GPT6 |
+		OMAP3430_AUTO_GPT5 |
+		OMAP3430_AUTO_GPT4 |
+		OMAP3430_AUTO_GPT3 |
+		OMAP3430_AUTO_GPT2 |
+		OMAP3430_AUTO_MCBSP4 |
+		OMAP3430_AUTO_MCBSP3 |
+		OMAP3430_AUTO_MCBSP2,
+		OMAP3430_PER_MOD,
+		CM_AUTOIDLE);
+
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		cm_write_mod_reg(
+			OMAP3430ES2_AUTO_USBHOST,
+			OMAP3430ES2_USBHOST_MOD,
+			CM_AUTOIDLE);
+	}
+
+	/*
+	 * Set all plls to autoidle. This is needed until autoidle is
+	 * enabled by clockfw
+	 */
+	cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
+			 OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
+	cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
+			 MPU_MOD,
+			 CM_AUTOIDLE2);
+	cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
+			 (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
+			 PLL_MOD,
+			 CM_AUTOIDLE);
+	cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT,
+			 PLL_MOD,
+			 CM_AUTOIDLE2);
+
+	/*
+	 * Enable control of expternal oscillator through
+	 * sys_clkreq. In the long run clock framework should
+	 * take care of this.
+	 */
+	prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
+			     1 << OMAP_AUTOEXTCLKMODE_SHIFT,
+			     OMAP3430_GR_MOD,
+			     OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+
+	/* setup wakup source */
+	prm_write_mod_reg(OMAP3430_EN_IO | OMAP3430_EN_GPIO1 |
+			  OMAP3430_EN_GPT1 | OMAP3430_EN_GPT12,
+			  WKUP_MOD, PM_WKEN);
+	/* No need to write EN_IO, that is always enabled */
+	prm_write_mod_reg(OMAP3430_EN_GPIO1 | OMAP3430_EN_GPT1 |
+			  OMAP3430_EN_GPT12,
+			  WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
+	/* For some reason IO doesn't generate wakeup event even if
+	 * it is selected to mpu wakeup goup */
+	prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
+			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
+
+	/* Don't attach IVA interrupts */
+	prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+	prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+	prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+	prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+
+	/* Clear any pending 'reset' flags */
+	prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
+
+	/* Clear any pending PRCM interrupts */
+	prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+	/* Don't attach IVA interrupts */
+	prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+	prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+	prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+	prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+
+	/* Clear any pending 'reset' flags */
+	prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
+	prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
+
+	/* Clear any pending PRCM interrupts */
+	prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+	omap3_iva_idle();
+	omap3_d2d_idle();
+}
+
+static int __init pwrdms_setup(struct powerdomain *pwrdm)
+{
+	struct power_state *pwrst;
+
+	if (!pwrdm->pwrsts)
+		return 0;
+
+	pwrst = kmalloc(sizeof(struct power_state), GFP_KERNEL);
+	if (!pwrst)
+		return -ENOMEM;
+	pwrst->pwrdm = pwrdm;
+	pwrst->next_state = PWRDM_POWER_RET;
+	list_add(&pwrst->node, &pwrst_list);
+
+	if (pwrdm_has_hdwr_sar(pwrdm))
+		pwrdm_enable_hdwr_sar(pwrdm);
+
+	return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+}
+
+/*
+ * Enable hw supervised mode for all clockdomains if it's
+ * supported. Initiate sleep transition for other clockdomains, if
+ * they are not used
+ */
+static int __init clkdms_setup(struct clockdomain *clkdm)
+{
+	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
+		omap2_clkdm_allow_idle(clkdm);
+	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
+		 atomic_read(&clkdm->usecount) == 0)
+		omap2_clkdm_sleep(clkdm);
+	return 0;
+}
+
+static int __init omap3_pm_init(void)
+{
+	struct power_state *pwrst, *tmp;
+	int ret;
+
+	if (!cpu_is_omap34xx())
+		return -ENODEV;
+
+	printk(KERN_ERR "Power Management for TI OMAP3.\n");
+
+	/* XXX prcm_setup_regs needs to be before enabling hw
+	 * supervised mode for powerdomains */
+	prcm_setup_regs();
+
+	ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
+			  (irq_handler_t)prcm_interrupt_handler,
+			  IRQF_DISABLED, "prcm", NULL);
+	if (ret) {
+		printk(KERN_ERR "request_irq failed to register for 0x%x\n",
+		       INT_34XX_PRCM_MPU_IRQ);
+		goto err1;
+	}
+
+	ret = pwrdm_for_each(pwrdms_setup);
+	if (ret) {
+		printk(KERN_ERR "Failed to setup powerdomains\n");
+		goto err2;
+	}
+
+	(void) clkdm_for_each(clkdms_setup);
+
+	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+	if (mpu_pwrdm == NULL) {
+		printk(KERN_ERR "Failed to get mpu_pwrdm\n");
+		goto err2;
+	}
+
+	_omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
+					 omap34xx_cpu_suspend_sz);
+
+#ifdef CONFIG_SUSPEND
+	suspend_set_ops(&omap_pm_ops);
+#endif /* CONFIG_SUSPEND */
+
+	pm_idle = omap3_pm_idle;
+
+err1:
+	return ret;
+err2:
+	free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
+	list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) {
+		list_del(&pwrst->node);
+		kfree(pwrst);
+	}
+	return ret;
+}
+
+late_initcall(omap3_pm_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/pm.c
- *
- * OMAP2 Power Management Routines
- *
- * Copyright (C) 2006 Nokia Corporation
- * Tony Lindgren <tony@atomide.com>
- *
- * Copyright (C) 2005 Texas Instruments, Inc.
- * Richard Woodruff <r-woodruff2@ti.com>
- *
- * Based on pm.c for omap1
- *
- * 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.
- */
-
-#include <linux/suspend.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/atomic.h>
-#include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-
-#include <mach/irqs.h>
-#include <mach/clock.h>
-#include <mach/sram.h>
-#include <mach/pm.h>
-
-static struct clk *vclk;
-static void (*omap2_sram_idle)(void);
-static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
-static void (*saved_idle)(void);
-
-extern void __init pmdomain_init(void);
-extern void pmdomain_set_autoidle(void);
-
-static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
-
-void omap2_pm_idle(void)
-{
-	local_irq_disable();
-	local_fiq_disable();
-	if (need_resched()) {
-		local_fiq_enable();
-		local_irq_enable();
-		return;
-	}
-
-	omap2_sram_idle();
-	local_fiq_enable();
-	local_irq_enable();
-}
-
-static int omap2_pm_prepare(void)
-{
-	/* We cannot sleep in idle until we have resumed */
-	saved_idle = pm_idle;
-	pm_idle = NULL;
-	return 0;
-}
-
-static int omap2_pm_suspend(void)
-{
-	return 0;
-}
-
-static int omap2_pm_enter(suspend_state_t state)
-{
-	int ret = 0;
-
-	switch (state)
-	{
-	case PM_SUSPEND_STANDBY:
-	case PM_SUSPEND_MEM:
-		ret = omap2_pm_suspend();
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static void omap2_pm_finish(void)
-{
-	pm_idle = saved_idle;
-}
-
-static struct platform_suspend_ops omap_pm_ops = {
-	.prepare	= omap2_pm_prepare,
-	.enter		= omap2_pm_enter,
-	.finish		= omap2_pm_finish,
-	.valid		= suspend_valid_only_mem,
-};
-
-static int __init omap2_pm_init(void)
-{
-	return 0;
-}
-
-__initcall(omap2_pm_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm-debug.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm-debug.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm-debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm-debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,152 @@
+/*
+ * OMAP Power Management debug routines
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * Written by:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Tony Lindgren
+ * Juha Yrjola
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Igor Stoppa <igor.stoppa@nokia.com>
+ * Jouni Hogander
+ *
+ * Based on pm.c for omap2
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/clock.h>
+#include <mach/board.h>
+
+#include "prm.h"
+#include "cm.h"
+#include "pm.h"
+
+int omap2_pm_debug;
+
+#define DUMP_PRM_MOD_REG(mod, reg)    \
+	regs[reg_count].name = #mod "." #reg; \
+	regs[reg_count++].val = prm_read_mod_reg(mod, reg)
+#define DUMP_CM_MOD_REG(mod, reg)     \
+	regs[reg_count].name = #mod "." #reg; \
+	regs[reg_count++].val = cm_read_mod_reg(mod, reg)
+#define DUMP_PRM_REG(reg) \
+	regs[reg_count].name = #reg; \
+	regs[reg_count++].val = __raw_readl(reg)
+#define DUMP_CM_REG(reg) \
+	regs[reg_count].name = #reg; \
+	regs[reg_count++].val = __raw_readl(reg)
+#define DUMP_INTC_REG(reg, off) \
+	regs[reg_count].name = #reg; \
+	regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
+
+void omap2_pm_dump(int mode, int resume, unsigned int us)
+{
+	struct reg {
+		const char *name;
+		u32 val;
+	} regs[32];
+	int reg_count = 0, i;
+	const char *s1 = NULL, *s2 = NULL;
+
+	if (!resume) {
+#if 0
+		/* MPU */
+		DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
+		DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL);
+		DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL);
+		DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST);
+		DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
+#endif
+#if 0
+		/* INTC */
+		DUMP_INTC_REG(INTC_MIR0, 0x0084);
+		DUMP_INTC_REG(INTC_MIR1, 0x00a4);
+		DUMP_INTC_REG(INTC_MIR2, 0x00c4);
+#endif
+#if 0
+		DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
+		if (cpu_is_omap24xx()) {
+			DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+			DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
+					OMAP2_PRCM_CLKEMUL_CTRL_OFFSET);
+			DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
+					OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
+		}
+		DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
+		DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
+		DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
+		DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
+		DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
+		DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
+		DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST);
+#endif
+#if 0
+		/* DSP */
+		if (cpu_is_omap24xx()) {
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
+			DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL);
+			DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST);
+		}
+#endif
+	} else {
+		DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
+		if (cpu_is_omap24xx())
+			DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
+		DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
+		DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+#if 1
+		DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
+		DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
+		DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
+#endif
+	}
+
+	switch (mode) {
+	case 0:
+		s1 = "full";
+		s2 = "retention";
+		break;
+	case 1:
+		s1 = "MPU";
+		s2 = "retention";
+		break;
+	case 2:
+		s1 = "MPU";
+		s2 = "idle";
+		break;
+	}
+
+	if (!resume)
+#ifdef CONFIG_NO_HZ
+		printk(KERN_INFO
+		       "--- Going to %s %s (next timer after %u ms)\n", s1, s2,
+		       jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
+					jiffies));
+#else
+		printk(KERN_INFO "--- Going to %s %s\n", s1, s2);
+#endif
+	else
+		printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n",
+			us / 1000, us % 1000);
+
+	for (i = 0; i < reg_count; i++)
+		printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/pm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,35 @@
+/*
+ * OMAP2/3 Power Management Routines
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Jouni Hogander
+ *
+ * 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.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_PM_H
+#define __ARCH_ARM_MACH_OMAP2_PM_H
+
+#ifdef CONFIG_PM_DEBUG
+extern void omap2_pm_dump(int mode, int resume, unsigned int us);
+extern int omap2_pm_debug;
+#else
+#define omap2_pm_dump(mode, resume, us)		do {} while (0);
+#define omap2_pm_debug				0
+#endif /* CONFIG_PM_DEBUG */
+
+extern void omap24xx_idle_loop_suspend(void);
+
+extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
+					void __iomem *sdrc_power);
+extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
+extern void save_secure_ram_context(u32 *addr);
+
+extern unsigned int omap24xx_idle_loop_suspend_sz;
+extern unsigned int omap34xx_suspend_sz;
+extern unsigned int save_secure_ram_context_sz;
+extern unsigned int omap24xx_cpu_suspend_sz;
+extern unsigned int omap34xx_cpu_suspend_sz;
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/powerdomain.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/powerdomain.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/powerdomain.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/powerdomain.c	2009-09-09 18:13:59.000000000 -0400
@@ -1099,7 +1099,7 @@
 	       (c++ < PWRDM_TRANSITION_BAILOUT))
 		udelay(1);
 
-	if (c >= PWRDM_TRANSITION_BAILOUT) {
+	if (c > PWRDM_TRANSITION_BAILOUT) {
 		printk(KERN_ERR "powerdomain: waited too long for "
 		       "powerdomain %s to complete transition\n", pwrdm->name);
 		return -EAGAIN;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/prcm.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/prcm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/prcm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/prcm.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 
 #include <mach/common.h>
 #include <mach/prcm.h>
@@ -28,6 +29,8 @@
 static void __iomem *prm_base;
 static void __iomem *cm_base;
 
+#define MAX_MODULE_ENABLE_WAIT		100000
+
 u32 omap_prcm_get_reset_sources(void)
 {
 	/* XXX This presumably needs modification for 34XX */
@@ -120,6 +123,46 @@
 }
 EXPORT_SYMBOL(cm_rmw_mod_reg_bits);
 
+/**
+ * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness
+ * @reg: physical address of module IDLEST register
+ * @mask: value to mask against to determine if the module is active
+ * @name: name of the clock (for printk)
+ *
+ * Returns 1 if the module indicated readiness in time, or 0 if it
+ * failed to enable in roughly MAX_MODULE_ENABLE_WAIT microseconds.
+ */
+int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name)
+{
+	int i = 0;
+	int ena = 0;
+
+	/*
+	 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+	 * 34xx reverses this, just to keep us on our toes
+	 */
+	if (cpu_is_omap24xx())
+		ena = mask;
+	else if (cpu_is_omap34xx())
+		ena = 0;
+	else
+		BUG();
+
+	/* Wait for lock */
+	while (((__raw_readl(reg) & mask) != ena) &&
+	       (i++ < MAX_MODULE_ENABLE_WAIT))
+		udelay(1);
+
+	if (i < MAX_MODULE_ENABLE_WAIT)
+		pr_debug("cm: Module associated with clock %s ready after %d "
+			 "loops\n", name, i);
+	else
+		pr_err("cm: Module associated with clock %s didn't enable in "
+		       "%d tries\n", name, MAX_MODULE_ENABLE_WAIT);
+
+	return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
+};
+
 void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
 {
 	prm_base = omap2_globals->prm;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/prcm-common.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/prcm-common.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/prcm-common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/prcm-common.h	2009-09-09 18:13:59.000000000 -0400
@@ -276,6 +276,8 @@
 /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
 #define OMAP3430_EN_GPIO1				(1 << 3)
 #define OMAP3430_EN_GPIO1_SHIFT				3
+#define OMAP3430_EN_GPT12				(1 << 1)
+#define OMAP3430_EN_GPT12_SHIFT				1
 #define OMAP3430_EN_GPT1				(1 << 0)
 #define OMAP3430_EN_GPT1_SHIFT				0
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/prm.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/prm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/prm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/prm.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,17 +16,12 @@
 
 #include "prcm-common.h"
 
-#ifndef __ASSEMBLER__
-#define OMAP_PRM_REGADDR(module, reg)					\
-			IO_ADDRESS(OMAP2_PRM_BASE + (module) + (reg))
-#else
 #define OMAP2420_PRM_REGADDR(module, reg)				\
 			IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
 #define OMAP2430_PRM_REGADDR(module, reg)				\
 			IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
 #define OMAP34XX_PRM_REGADDR(module, reg)				\
 			IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
-#endif
 
 /*
  * Architecture-specific global PRM registers
@@ -38,80 +33,132 @@
  *
  */
 
-/* Global 24xx registers in GR_MOD (Same as OCP_MOD for 24xx) */
-#define OMAP24XX_PRCM_VOLTCTRL_OFFSET		0x0050
-#define OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET	0x0080
+#define OMAP2_PRCM_REVISION_OFFSET	0x0000
+#define OMAP2420_PRCM_REVISION		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP2_PRCM_SYSCONFIG_OFFSET	0x0010
+#define OMAP2420_PRCM_SYSCONFIG		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010)
 
-/* 242x GR_MOD registers, use these only for assembly code */
-#define OMAP242X_PRCM_VOLTCTRL		OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD,	\
-						OMAP24XX_PRCM_VOLTCTRL_OFFSET)
-#define OMAP242X_PRCM_CLKCFG_CTRL	OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD,	\
-						OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET)
+#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET	0x0018
+#define OMAP2420_PRCM_IRQSTATUS_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET	0x001c
+#define OMAP2420_PRCM_IRQENABLE_MPU	OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c)
 
-/* 243x GR_MOD registers, use these only for assembly code */
-#define OMAP243X_PRCM_VOLTCTRL		OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD,	\
-						OMAP24XX_PRCM_VOLTCTRL_OFFSET)
-#define OMAP243X_PRCM_CLKCFG_CTRL	OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD,	\
-						OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET)
+#define OMAP2_PRCM_VOLTCTRL_OFFSET	0x0050
+#define OMAP2420_PRCM_VOLTCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050)
+#define OMAP2_PRCM_VOLTST_OFFSET	0x0054
+#define OMAP2420_PRCM_VOLTST		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054)
+#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET	0x0060
+#define OMAP2420_PRCM_CLKSRC_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060)
+#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP2420_PRCM_CLKOUT_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070)
+#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET	0x0078
+#define OMAP2420_PRCM_CLKEMUL_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078)
+#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET	0x0080
+#define OMAP2420_PRCM_CLKCFG_CTRL	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080)
+#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET	0x0084
+#define OMAP2420_PRCM_CLKCFG_STATUS	OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084)
+#define OMAP2_PRCM_VOLTSETUP_OFFSET	0x0090
+#define OMAP2420_PRCM_VOLTSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090)
+#define OMAP2_PRCM_CLKSSETUP_OFFSET	0x0094
+#define OMAP2420_PRCM_CLKSSETUP		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094)
+#define OMAP2_PRCM_POLCTRL_OFFSET	0x0098
+#define OMAP2420_PRCM_POLCTRL		OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098)
 
-/* These will disappear */
-#define OMAP24XX_PRCM_REVISION		OMAP_PRM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP24XX_PRCM_SYSCONFIG		OMAP_PRM_REGADDR(OCP_MOD, 0x0010)
+#define OMAP2430_PRCM_REVISION		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP2430_PRCM_SYSCONFIG		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010)
 
-#define OMAP24XX_PRCM_IRQSTATUS_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP24XX_PRCM_IRQENABLE_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x001c)
+#define OMAP2430_PRCM_IRQSTATUS_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP2430_PRCM_IRQENABLE_MPU	OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c)
 
-#define OMAP24XX_PRCM_VOLTST		OMAP_PRM_REGADDR(OCP_MOD, 0x0054)
-#define OMAP24XX_PRCM_CLKSRC_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0060)
-#define OMAP24XX_PRCM_CLKOUT_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0070)
-#define OMAP24XX_PRCM_CLKEMUL_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0078)
-#define OMAP24XX_PRCM_CLKCFG_CTRL	OMAP_PRM_REGADDR(OCP_MOD, 0x0080)
-#define OMAP24XX_PRCM_CLKCFG_STATUS	OMAP_PRM_REGADDR(OCP_MOD, 0x0084)
-#define OMAP24XX_PRCM_VOLTSETUP		OMAP_PRM_REGADDR(OCP_MOD, 0x0090)
-#define OMAP24XX_PRCM_CLKSSETUP		OMAP_PRM_REGADDR(OCP_MOD, 0x0094)
-#define OMAP24XX_PRCM_POLCTRL		OMAP_PRM_REGADDR(OCP_MOD, 0x0098)
+#define OMAP2430_PRCM_VOLTCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050)
+#define OMAP2430_PRCM_VOLTST		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054)
+#define OMAP2430_PRCM_CLKSRC_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060)
+#define OMAP2430_PRCM_CLKOUT_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070)
+#define OMAP2430_PRCM_CLKEMUL_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078)
+#define OMAP2430_PRCM_CLKCFG_CTRL	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080)
+#define OMAP2430_PRCM_CLKCFG_STATUS	OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084)
+#define OMAP2430_PRCM_VOLTSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090)
+#define OMAP2430_PRCM_CLKSSETUP		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094)
+#define OMAP2430_PRCM_POLCTRL		OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098)
 
-#define OMAP3430_PRM_REVISION		OMAP_PRM_REGADDR(OCP_MOD, 0x0004)
-#define OMAP3430_PRM_SYSCONFIG		OMAP_PRM_REGADDR(OCP_MOD, 0x0014)
+#define OMAP3_PRM_REVISION_OFFSET	0x0004
+#define OMAP3430_PRM_REVISION		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004)
+#define OMAP3_PRM_SYSCONFIG_OFFSET	0x0014
+#define OMAP3430_PRM_SYSCONFIG		OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014)
 
-#define OMAP3430_PRM_IRQSTATUS_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x0018)
-#define OMAP3430_PRM_IRQENABLE_MPU	OMAP_PRM_REGADDR(OCP_MOD, 0x001c)
+#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET	0x0018
+#define OMAP3430_PRM_IRQSTATUS_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018)
+#define OMAP3_PRM_IRQENABLE_MPU_OFFSET	0x001c
+#define OMAP3430_PRM_IRQENABLE_MPU	OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c)
 
 
-#define OMAP3430_PRM_VC_SMPS_SA		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
-#define OMAP3430_PRM_VC_SMPS_VOL_RA	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
-#define OMAP3430_PRM_VC_SMPS_CMD_RA	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
-#define OMAP3430_PRM_VC_CMD_VAL_0	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
-#define OMAP3430_PRM_VC_CMD_VAL_1	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
-#define OMAP3430_PRM_VC_CH_CONF		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
-#define OMAP3430_PRM_VC_I2C_CFG		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
-#define OMAP3430_PRM_VC_BYPASS_VAL	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
-#define OMAP3430_PRM_RSTCTRL		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
-#define OMAP3430_PRM_RSTTIME		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
-#define OMAP3430_PRM_RSTST		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
-#define OMAP3430_PRM_VOLTCTRL		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
-#define OMAP3430_PRM_SRAM_PCHARGE	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
-#define OMAP3430_PRM_CLKSRC_CTRL	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
-#define OMAP3430_PRM_VOLTSETUP1		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
-#define OMAP3430_PRM_VOLTOFFSET		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
-#define OMAP3430_PRM_CLKSETUP		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
-#define OMAP3430_PRM_POLCTRL		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
-#define OMAP3430_PRM_VOLTSETUP2		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
-#define OMAP3430_PRM_VP1_CONFIG		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
-#define OMAP3430_PRM_VP1_VSTEPMIN	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
-#define OMAP3430_PRM_VP1_VSTEPMAX	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
-#define OMAP3430_PRM_VP1_VLIMITTO	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
-#define OMAP3430_PRM_VP1_VOLTAGE	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
-#define OMAP3430_PRM_VP1_STATUS		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
-#define OMAP3430_PRM_VP2_CONFIG		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
-#define OMAP3430_PRM_VP2_VSTEPMIN	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
-#define OMAP3430_PRM_VP2_VSTEPMAX	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
-#define OMAP3430_PRM_VP2_VLIMITTO	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
-#define OMAP3430_PRM_VP2_VOLTAGE	OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
-#define OMAP3430_PRM_VP2_STATUS		OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
+#define OMAP3_PRM_VC_SMPS_SA_OFFSET	0x0020
+#define OMAP3430_PRM_VC_SMPS_SA		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
+#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET	0x0024
+#define OMAP3430_PRM_VC_SMPS_VOL_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
+#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET	0x0028
+#define OMAP3430_PRM_VC_SMPS_CMD_RA	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
+#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET	0x002c
+#define OMAP3430_PRM_VC_CMD_VAL_0	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
+#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET	0x0030
+#define OMAP3430_PRM_VC_CMD_VAL_1	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
+#define OMAP3_PRM_VC_CH_CONF_OFFSET	0x0034
+#define OMAP3430_PRM_VC_CH_CONF		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
+#define OMAP3_PRM_VC_I2C_CFG_OFFSET	0x0038
+#define OMAP3430_PRM_VC_I2C_CFG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
+#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET	0x003c
+#define OMAP3430_PRM_VC_BYPASS_VAL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
+#define OMAP3_PRM_RSTCTRL_OFFSET	0x0050
+#define OMAP3430_PRM_RSTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
+#define OMAP3_PRM_RSTTIME_OFFSET	0x0054
+#define OMAP3430_PRM_RSTTIME		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
+#define OMAP3_PRM_RSTST_OFFSET	0x0058
+#define OMAP3430_PRM_RSTST		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
+#define OMAP3_PRM_VOLTCTRL_OFFSET	0x0060
+#define OMAP3430_PRM_VOLTCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
+#define OMAP3_PRM_SRAM_PCHARGE_OFFSET	0x0064
+#define OMAP3430_PRM_SRAM_PCHARGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
+#define OMAP3_PRM_CLKSRC_CTRL_OFFSET	0x0070
+#define OMAP3430_PRM_CLKSRC_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
+#define OMAP3_PRM_VOLTSETUP1_OFFSET	0x0090
+#define OMAP3430_PRM_VOLTSETUP1		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
+#define OMAP3_PRM_VOLTOFFSET_OFFSET	0x0094
+#define OMAP3430_PRM_VOLTOFFSET		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
+#define OMAP3_PRM_CLKSETUP_OFFSET	0x0098
+#define OMAP3430_PRM_CLKSETUP		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
+#define OMAP3_PRM_POLCTRL_OFFSET	0x009c
+#define OMAP3430_PRM_POLCTRL		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
+#define OMAP3_PRM_VOLTSETUP2_OFFSET	0x00a0
+#define OMAP3430_PRM_VOLTSETUP2		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
+#define OMAP3_PRM_VP1_CONFIG_OFFSET	0x00b0
+#define OMAP3430_PRM_VP1_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
+#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET	0x00b4
+#define OMAP3430_PRM_VP1_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
+#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET	0x00b8
+#define OMAP3430_PRM_VP1_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
+#define OMAP3_PRM_VP1_VLIMITTO_OFFSET	0x00bc
+#define OMAP3430_PRM_VP1_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
+#define OMAP3_PRM_VP1_VOLTAGE_OFFSET	0x00c0
+#define OMAP3430_PRM_VP1_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
+#define OMAP3_PRM_VP1_STATUS_OFFSET	0x00c4
+#define OMAP3430_PRM_VP1_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
+#define OMAP3_PRM_VP2_CONFIG_OFFSET	0x00d0
+#define OMAP3430_PRM_VP2_CONFIG		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
+#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET	0x00d4
+#define OMAP3430_PRM_VP2_VSTEPMIN	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
+#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET	0x00d8
+#define OMAP3430_PRM_VP2_VSTEPMAX	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
+#define OMAP3_PRM_VP2_VLIMITTO_OFFSET	0x00dc
+#define OMAP3430_PRM_VP2_VLIMITTO	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
+#define OMAP3_PRM_VP2_VOLTAGE_OFFSET	0x00e0
+#define OMAP3430_PRM_VP2_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
+#define OMAP3_PRM_VP2_STATUS_OFFSET	0x00e4
+#define OMAP3430_PRM_VP2_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
 
-#define OMAP3430_PRM_CLKSEL		OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
-#define OMAP3430_PRM_CLKOUT_CTRL	OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
+#define OMAP3_PRM_CLKSEL_OFFSET	0x0040
+#define OMAP3430_PRM_CLKSEL		OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
+#define OMAP3_PRM_CLKOUT_CTRL_OFFSET	0x0070
+#define OMAP3430_PRM_CLKOUT_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
 
 /*
  * Module specific PRM registers from PRM_BASE + domain offset
@@ -156,9 +203,11 @@
 
 #define OMAP3430_PM_MPUGRPSEL				0x00a4
 #define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
+#define OMAP3430ES2_PM_MPUGRPSEL3			0x00f8
 
 #define OMAP3430_PM_IVAGRPSEL				0x00a8
 #define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL
+#define OMAP3430ES2_PM_IVAGRPSEL3			0x00f4
 
 #define OMAP3430_PM_PREPWSTST				0x00e8
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * SDRC register values for the Micron MT46H32M32LF-6
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Paul Walmsley
+ *
+ * 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.
+ */
+
+#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
+#define ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
+
+#include <mach/sdrc.h>
+
+/* Micron MT46H32M32LF-6 */
+/* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */
+static struct omap_sdrc_params mt46h32m32lf6_sdrc_params[] = {
+	[0] = {
+		.rate	     = 166000000,
+		.actim_ctrla = 0x9a9db4c6,
+		.actim_ctrlb = 0x00011217,
+		.rfr_ctrl    = 0x0004dc01,
+		.mr	     = 0x00000032,
+	},
+	[1] = {
+		.rate	     = 165941176,
+		.actim_ctrla = 0x9a9db4c6,
+		.actim_ctrlb = 0x00011217,
+		.rfr_ctrl    = 0x0004dc01,
+		.mr	     = 0x00000032,
+	},
+	[2] = {
+		.rate	     = 83000000,
+		.actim_ctrla = 0x51512283,
+		.actim_ctrlb = 0x0001120c,
+		.rfr_ctrl    = 0x00025501,
+		.mr	     = 0x00000032,
+	},
+	[3] = {
+		.rate	     = 82970588,
+		.actim_ctrla = 0x51512283,
+		.actim_ctrlb = 0x0001120c,
+		.rfr_ctrl    = 0x00025501,
+		.mr	     = 0x00000032,
+	},
+	[4] = {
+		.rate	     = 0
+	},
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * SDRC register values for the Qimonda HYB18M512160AF-6
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Paul Walmsley
+ *
+ * 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.
+ */
+
+#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
+#define ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
+
+#include <mach/sdrc.h>
+
+/* Qimonda HYB18M512160AF-6 */
+static struct omap_sdrc_params hyb18m512160af6_sdrc_params[] = {
+	[0] = {
+		.rate	     = 166000000,
+		.actim_ctrla = 0x629db4c6,
+		.actim_ctrlb = 0x00012214,
+		.rfr_ctrl    = 0x0004dc01,
+		.mr	     = 0x00000032,
+	},
+	[1] = {
+		.rate	     = 165941176,
+		.actim_ctrla = 0x629db4c6,
+		.actim_ctrlb = 0x00012214,
+		.rfr_ctrl    = 0x0004dc01,
+		.mr	     = 0x00000032,
+	},
+	[2] = {
+		.rate	     = 83000000,
+		.actim_ctrla = 0x31512283,
+		.actim_ctrlb = 0x0001220a,
+		.rfr_ctrl    = 0x00025501,
+		.mr	     = 0x00000022,
+	},
+	[3] = {
+		.rate	     = 82970588,
+		.actim_ctrla = 0x31512283,
+		.actim_ctrlb = 0x0001220a,
+		.rfr_ctrl    = 0x00025501,
+		.mr	     = 0x00000022,
+	},
+	[4] = {
+		.rate	     = 0
+	},
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdrc2xxx.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdrc2xxx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdrc2xxx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdrc2xxx.c	2009-09-09 18:13:59.000000000 -0400
@@ -99,7 +99,10 @@
 	m_type = omap2xxx_sdrc_get_type();
 
 	local_irq_save(flags);
-	__raw_writel(0xffff, OMAP24XX_PRCM_VOLTSETUP);
+	if (cpu_is_omap2420())
+		__raw_writel(0xffff, OMAP2420_PRCM_VOLTSETUP);
+	else
+		__raw_writel(0xffff, OMAP2430_PRCM_VOLTSETUP);
 	omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type);
 	curr_perf_level = level;
 	local_irq_restore(flags);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdrc.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdrc.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sdrc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sdrc.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,39 +32,62 @@
 #include <mach/sdrc.h>
 #include "sdrc.h"
 
-static struct omap_sdrc_params *sdrc_init_params;
+static struct omap_sdrc_params *sdrc_init_params_cs0, *sdrc_init_params_cs1;
 
 void __iomem *omap2_sdrc_base;
 void __iomem *omap2_sms_base;
 
+/* SDRC_POWER register bits */
+#define SDRC_POWER_EXTCLKDIS_SHIFT		3
+#define SDRC_POWER_PWDENA_SHIFT			2
+#define SDRC_POWER_PAGEPOLICY_SHIFT		0
 
 /**
  * omap2_sdrc_get_params - return SDRC register values for a given clock rate
  * @r: SDRC clock rate (in Hz)
+ * @sdrc_cs0: chip select 0 ram timings **
+ * @sdrc_cs1: chip select 1 ram timings **
  *
  * Return pre-calculated values for the SDRC_ACTIM_CTRLA,
- * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL, and SDRC_MR registers, for a given
- * SDRC clock rate 'r'.  These parameters control various timing
- * delays in the SDRAM controller that are expressed in terms of the
- * number of SDRC clock cycles to wait; hence the clock rate
- * dependency. Note that sdrc_init_params must be sorted rate
- * descending.  Also assumes that both chip-selects use the same
- * timing parameters.  Returns a struct omap_sdrc_params * upon
- * success, or NULL upon failure.
+ *  SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL and SDRC_MR registers in sdrc_cs[01]
+ *  structs,for a given SDRC clock rate 'r'.
+ * These parameters control various timing delays in the SDRAM controller
+ *  that are expressed in terms of the number of SDRC clock cycles to
+ *  wait; hence the clock rate dependency.
+ *
+ * Supports 2 different timing parameters for both chip selects.
+ *
+ * Note 1: the sdrc_init_params_cs[01] must be sorted rate descending.
+ * Note 2: If sdrc_init_params_cs_1 is not NULL it must be of same size
+ *  as sdrc_init_params_cs_0.
+ *
+ * Fills in the struct omap_sdrc_params * for each chip select.
+ * Returns 0 upon success or -1 upon failure.
  */
-struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r)
+int omap2_sdrc_get_params(unsigned long r,
+			  struct omap_sdrc_params **sdrc_cs0,
+			  struct omap_sdrc_params **sdrc_cs1)
 {
-	struct omap_sdrc_params *sp;
+	struct omap_sdrc_params *sp0, *sp1;
 
-	sp = sdrc_init_params;
+	if (!sdrc_init_params_cs0)
+		return -1;
 
-	while (sp->rate != r)
-		sp++;
+	sp0 = sdrc_init_params_cs0;
+	sp1 = sdrc_init_params_cs1;
 
-	if (!sp->rate)
-		return NULL;
+	while (sp0->rate && sp0->rate != r) {
+		sp0++;
+		if (sdrc_init_params_cs1)
+			sp1++;
+	}
 
-	return sp;
+	if (!sp0->rate)
+		return -1;
+
+	*sdrc_cs0 = sp0;
+	*sdrc_cs1 = sp1;
+	return 0;
 }
 
 
@@ -74,8 +97,17 @@
 	omap2_sms_base = omap2_globals->sms;
 }
 
-/* turn on smart idle modes for SDRAM scheduler and controller */
-void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
+/**
+ * omap2_sdrc_init - initialize SMS, SDRC devices on boot
+ * @sdrc_cs[01]: pointers to a null-terminated list of struct omap_sdrc_params
+ *  Support for 2 chip selects timings
+ *
+ * Turn on smart idle modes for SDRAM scheduler and controller.
+ * Program a known-good configuration for the SDRC to deal with buggy
+ * bootloaders.
+ */
+void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+			    struct omap_sdrc_params *sdrc_cs1)
 {
 	u32 l;
 
@@ -89,5 +121,15 @@
 	l |= (0x2 << 3);
 	sdrc_write_reg(l, SDRC_SYSCONFIG);
 
-	sdrc_init_params = sp;
+	sdrc_init_params_cs0 = sdrc_cs0;
+	sdrc_init_params_cs1 = sdrc_cs1;
+
+	/* XXX Enable SRFRONIDLEREQ here also? */
+	/*
+	 * PWDENA should not be set due to 34xx erratum 1.150 - PWDENA
+	 * can cause random memory corruption
+	 */
+	l = (1 << SDRC_POWER_EXTCLKDIS_SHIFT) |
+		(1 << SDRC_POWER_PAGEPOLICY_SHIFT);
+	sdrc_write_reg(l, SDRC_POWER);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/serial.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/serial.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/serial.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/serial.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,8 +6,13 @@
  * Copyright (C) 2005-2008 Nokia Corporation
  * Author: Paul Mundt <paul.mundt@nokia.com>
  *
+ * Major rework for PM support by Kevin Hilman
+ *
  * Based off of arch/arm/mach-omap/omap1/serial.c
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.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.
@@ -21,11 +26,52 @@
 
 #include <mach/common.h>
 #include <mach/board.h>
+#include <mach/clock.h>
+#include <mach/control.h>
 
-static struct clk *uart_ick[OMAP_MAX_NR_PORTS];
-static struct clk *uart_fck[OMAP_MAX_NR_PORTS];
+#include "prm.h"
+#include "pm.h"
+#include "prm-regbits-34xx.h"
 
-static struct plat_serial8250_port serial_platform_data[] = {
+#define UART_OMAP_WER		0x17	/* Wake-up enable register */
+
+#define DEFAULT_TIMEOUT (5 * HZ)
+
+struct omap_uart_state {
+	int num;
+	int can_sleep;
+	struct timer_list timer;
+	u32 timeout;
+
+	void __iomem *wk_st;
+	void __iomem *wk_en;
+	u32 wk_mask;
+	u32 padconf;
+
+	struct clk *ick;
+	struct clk *fck;
+	int clocked;
+
+	struct plat_serial8250_port *p;
+	struct list_head node;
+	struct platform_device pdev;
+
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+	int context_valid;
+
+	/* Registers to be saved/restored for OFF-mode */
+	u16 dll;
+	u16 dlh;
+	u16 ier;
+	u16 sysc;
+	u16 scr;
+	u16 wer;
+#endif
+};
+
+static LIST_HEAD(uart_list);
+
+static struct plat_serial8250_port serial_platform_data0[] = {
 	{
 		.membase	= IO_ADDRESS(OMAP_UART1_BASE),
 		.mapbase	= OMAP_UART1_BASE,
@@ -35,6 +81,12 @@
 		.regshift	= 2,
 		.uartclk	= OMAP24XX_BASE_BAUD * 16,
 	}, {
+		.flags		= 0
+	}
+};
+
+static struct plat_serial8250_port serial_platform_data1[] = {
+	{
 		.membase	= IO_ADDRESS(OMAP_UART2_BASE),
 		.mapbase	= OMAP_UART2_BASE,
 		.irq		= 73,
@@ -43,6 +95,12 @@
 		.regshift	= 2,
 		.uartclk	= OMAP24XX_BASE_BAUD * 16,
 	}, {
+		.flags		= 0
+	}
+};
+
+static struct plat_serial8250_port serial_platform_data2[] = {
+	{
 		.membase	= IO_ADDRESS(OMAP_UART3_BASE),
 		.mapbase	= OMAP_UART3_BASE,
 		.irq		= 74,
@@ -74,30 +132,426 @@
  * properly. Note that the TX watermark initialization may not be needed
  * once the 8250.c watermark handling code is merged.
  */
-static inline void __init omap_serial_reset(struct plat_serial8250_port *p)
+static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 {
+	struct plat_serial8250_port *p = uart->p;
+
 	serial_write_reg(p, UART_OMAP_MDR1, 0x07);
 	serial_write_reg(p, UART_OMAP_SCR, 0x08);
 	serial_write_reg(p, UART_OMAP_MDR1, 0x00);
 	serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
 }
 
-void omap_serial_enable_clocks(int enable)
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+
+static int enable_off_mode; /* to be removed by full off-mode patches */
+
+static void omap_uart_save_context(struct omap_uart_state *uart)
 {
-	int i;
-	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
-		if (uart_ick[i] && uart_fck[i]) {
-			if (enable) {
-				clk_enable(uart_ick[i]);
-				clk_enable(uart_fck[i]);
-			} else {
-				clk_disable(uart_ick[i]);
-				clk_disable(uart_fck[i]);
+	u16 lcr = 0;
+	struct plat_serial8250_port *p = uart->p;
+
+	if (!enable_off_mode)
+		return;
+
+	lcr = serial_read_reg(p, UART_LCR);
+	serial_write_reg(p, UART_LCR, 0xBF);
+	uart->dll = serial_read_reg(p, UART_DLL);
+	uart->dlh = serial_read_reg(p, UART_DLM);
+	serial_write_reg(p, UART_LCR, lcr);
+	uart->ier = serial_read_reg(p, UART_IER);
+	uart->sysc = serial_read_reg(p, UART_OMAP_SYSC);
+	uart->scr = serial_read_reg(p, UART_OMAP_SCR);
+	uart->wer = serial_read_reg(p, UART_OMAP_WER);
+
+	uart->context_valid = 1;
+}
+
+static void omap_uart_restore_context(struct omap_uart_state *uart)
+{
+	u16 efr = 0;
+	struct plat_serial8250_port *p = uart->p;
+
+	if (!enable_off_mode)
+		return;
+
+	if (!uart->context_valid)
+		return;
+
+	uart->context_valid = 0;
+
+	serial_write_reg(p, UART_OMAP_MDR1, 0x7);
+	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+	efr = serial_read_reg(p, UART_EFR);
+	serial_write_reg(p, UART_EFR, UART_EFR_ECB);
+	serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
+	serial_write_reg(p, UART_IER, 0x0);
+	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(p, UART_DLL, uart->dll);
+	serial_write_reg(p, UART_DLM, uart->dlh);
+	serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
+	serial_write_reg(p, UART_IER, uart->ier);
+	serial_write_reg(p, UART_FCR, 0xA1);
+	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(p, UART_EFR, efr);
+	serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
+	serial_write_reg(p, UART_OMAP_SCR, uart->scr);
+	serial_write_reg(p, UART_OMAP_WER, uart->wer);
+	serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
+	serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+}
+#else
+static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
+static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
+#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
+
+static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
+{
+	if (uart->clocked)
+		return;
+
+	clk_enable(uart->ick);
+	clk_enable(uart->fck);
+	uart->clocked = 1;
+	omap_uart_restore_context(uart);
+}
+
+#ifdef CONFIG_PM
+
+static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
+{
+	if (!uart->clocked)
+		return;
+
+	omap_uart_save_context(uart);
+	uart->clocked = 0;
+	clk_disable(uart->ick);
+	clk_disable(uart->fck);
+}
+
+static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
+{
+	/* Set wake-enable bit */
+	if (uart->wk_en && uart->wk_mask) {
+		u32 v = __raw_readl(uart->wk_en);
+		v |= uart->wk_mask;
+		__raw_writel(v, uart->wk_en);
+	}
+
+	/* Ensure IOPAD wake-enables are set */
+	if (cpu_is_omap34xx() && uart->padconf) {
+		u16 v = omap_ctrl_readw(uart->padconf);
+		v |= OMAP3_PADCONF_WAKEUPENABLE0;
+		omap_ctrl_writew(v, uart->padconf);
+	}
+}
+
+static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
+{
+	/* Clear wake-enable bit */
+	if (uart->wk_en && uart->wk_mask) {
+		u32 v = __raw_readl(uart->wk_en);
+		v &= ~uart->wk_mask;
+		__raw_writel(v, uart->wk_en);
+	}
+
+	/* Ensure IOPAD wake-enables are cleared */
+	if (cpu_is_omap34xx() && uart->padconf) {
+		u16 v = omap_ctrl_readw(uart->padconf);
+		v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
+		omap_ctrl_writew(v, uart->padconf);
+	}
+}
+
+static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
+					  int enable)
+{
+	struct plat_serial8250_port *p = uart->p;
+	u16 sysc;
+
+	sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
+	if (enable)
+		sysc |= 0x2 << 3;
+	else
+		sysc |= 0x1 << 3;
+
+	serial_write_reg(p, UART_OMAP_SYSC, sysc);
+}
+
+static void omap_uart_block_sleep(struct omap_uart_state *uart)
+{
+	omap_uart_enable_clocks(uart);
+
+	omap_uart_smart_idle_enable(uart, 0);
+	uart->can_sleep = 0;
+	if (uart->timeout)
+		mod_timer(&uart->timer, jiffies + uart->timeout);
+	else
+		del_timer(&uart->timer);
+}
+
+static void omap_uart_allow_sleep(struct omap_uart_state *uart)
+{
+	if (device_may_wakeup(&uart->pdev.dev))
+		omap_uart_enable_wakeup(uart);
+	else
+		omap_uart_disable_wakeup(uart);
+
+	if (!uart->clocked)
+		return;
+
+	omap_uart_smart_idle_enable(uart, 1);
+	uart->can_sleep = 1;
+	del_timer(&uart->timer);
+}
+
+static void omap_uart_idle_timer(unsigned long data)
+{
+	struct omap_uart_state *uart = (struct omap_uart_state *)data;
+
+	omap_uart_allow_sleep(uart);
+}
+
+void omap_uart_prepare_idle(int num)
+{
+	struct omap_uart_state *uart;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		if (num == uart->num && uart->can_sleep) {
+			omap_uart_disable_clocks(uart);
+			return;
+		}
+	}
+}
+
+void omap_uart_resume_idle(int num)
+{
+	struct omap_uart_state *uart;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		if (num == uart->num) {
+			omap_uart_enable_clocks(uart);
+
+			/* Check for IO pad wakeup */
+			if (cpu_is_omap34xx() && uart->padconf) {
+				u16 p = omap_ctrl_readw(uart->padconf);
+
+				if (p & OMAP3_PADCONF_WAKEUPEVENT0)
+					omap_uart_block_sleep(uart);
 			}
+
+			/* Check for normal UART wakeup */
+			if (__raw_readl(uart->wk_st) & uart->wk_mask)
+				omap_uart_block_sleep(uart);
+			return;
+		}
+	}
+}
+
+void omap_uart_prepare_suspend(void)
+{
+	struct omap_uart_state *uart;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		omap_uart_allow_sleep(uart);
+	}
+}
+
+int omap_uart_can_sleep(void)
+{
+	struct omap_uart_state *uart;
+	int can_sleep = 1;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		if (!uart->clocked)
+			continue;
+
+		if (!uart->can_sleep) {
+			can_sleep = 0;
+			continue;
 		}
+
+		/* This UART can now safely sleep. */
+		omap_uart_allow_sleep(uart);
+	}
+
+	return can_sleep;
+}
+
+/**
+ * omap_uart_interrupt()
+ *
+ * This handler is used only to detect that *any* UART interrupt has
+ * occurred.  It does _nothing_ to handle the interrupt.  Rather,
+ * any UART interrupt will trigger the inactivity timer so the
+ * UART will not idle or sleep for its timeout period.
+ *
+ **/
+static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
+{
+	struct omap_uart_state *uart = dev_id;
+
+	omap_uart_block_sleep(uart);
+
+	return IRQ_NONE;
+}
+
+static void omap_uart_idle_init(struct omap_uart_state *uart)
+{
+	struct plat_serial8250_port *p = uart->p;
+	int ret;
+
+	uart->can_sleep = 0;
+	uart->timeout = DEFAULT_TIMEOUT;
+	setup_timer(&uart->timer, omap_uart_idle_timer,
+		    (unsigned long) uart);
+	mod_timer(&uart->timer, jiffies + uart->timeout);
+	omap_uart_smart_idle_enable(uart, 0);
+
+	if (cpu_is_omap34xx()) {
+		u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
+		u32 wk_mask = 0;
+		u32 padconf = 0;
+
+		uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
+		uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
+		switch (uart->num) {
+		case 0:
+			wk_mask = OMAP3430_ST_UART1_MASK;
+			padconf = 0x182;
+			break;
+		case 1:
+			wk_mask = OMAP3430_ST_UART2_MASK;
+			padconf = 0x17a;
+			break;
+		case 2:
+			wk_mask = OMAP3430_ST_UART3_MASK;
+			padconf = 0x19e;
+			break;
+		}
+		uart->wk_mask = wk_mask;
+		uart->padconf = padconf;
+	} else if (cpu_is_omap24xx()) {
+		u32 wk_mask = 0;
+
+		if (cpu_is_omap2430()) {
+			uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
+			uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
+		} else if (cpu_is_omap2420()) {
+			uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
+			uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
+		}
+		switch (uart->num) {
+		case 0:
+			wk_mask = OMAP24XX_ST_UART1_MASK;
+			break;
+		case 1:
+			wk_mask = OMAP24XX_ST_UART2_MASK;
+			break;
+		case 2:
+			wk_mask = OMAP24XX_ST_UART3_MASK;
+			break;
+		}
+		uart->wk_mask = wk_mask;
+	} else {
+		uart->wk_en = 0;
+		uart->wk_st = 0;
+		uart->wk_mask = 0;
+		uart->padconf = 0;
+	}
+
+	p->flags |= UPF_SHARE_IRQ;
+	ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
+			  "serial idle", (void *)uart);
+	WARN_ON(ret);
+}
+
+void omap_uart_enable_irqs(int enable)
+{
+	int ret;
+	struct omap_uart_state *uart;
+
+	list_for_each_entry(uart, &uart_list, node) {
+		if (enable)
+			ret = request_irq(uart->p->irq, omap_uart_interrupt,
+				IRQF_SHARED, "serial idle", (void *)uart);
+		else
+			free_irq(uart->p->irq, (void *)uart);
+	}
+}
+
+static ssize_t sleep_timeout_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct platform_device *pdev = container_of(dev,
+					struct platform_device, dev);
+	struct omap_uart_state *uart = container_of(pdev,
+					struct omap_uart_state, pdev);
+
+	return sprintf(buf, "%u\n", uart->timeout / HZ);
+}
+
+static ssize_t sleep_timeout_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t n)
+{
+	struct platform_device *pdev = container_of(dev,
+					struct platform_device, dev);
+	struct omap_uart_state *uart = container_of(pdev,
+					struct omap_uart_state, pdev);
+	unsigned int value;
+
+	if (sscanf(buf, "%u", &value) != 1) {
+		printk(KERN_ERR "sleep_timeout_store: Invalid value\n");
+		return -EINVAL;
 	}
+
+	uart->timeout = value * HZ;
+	if (uart->timeout)
+		mod_timer(&uart->timer, jiffies + uart->timeout);
+	else
+		/* A zero value means disable timeout feature */
+		omap_uart_block_sleep(uart);
+
+	return n;
 }
 
+DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
+#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
+#else
+static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
+#define DEV_CREATE_FILE(dev, attr)
+#endif /* CONFIG_PM */
+
+static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
+	{
+		.pdev = {
+			.name			= "serial8250",
+			.id			= PLAT8250_DEV_PLATFORM,
+			.dev			= {
+				.platform_data	= serial_platform_data0,
+			},
+		},
+	}, {
+		.pdev = {
+			.name			= "serial8250",
+			.id			= PLAT8250_DEV_PLATFORM1,
+			.dev			= {
+				.platform_data	= serial_platform_data1,
+			},
+		},
+	}, {
+		.pdev = {
+			.name			= "serial8250",
+			.id			= PLAT8250_DEV_PLATFORM2,
+			.dev			= {
+				.platform_data	= serial_platform_data2,
+			},
+		},
+	},
+};
+
 void __init omap_serial_init(void)
 {
 	int i;
@@ -116,7 +570,10 @@
 		return;
 
 	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
-		struct plat_serial8250_port *p = serial_platform_data + i;
+		struct omap_uart_state *uart = &omap_uart[i];
+		struct platform_device *pdev = &uart->pdev;
+		struct device *dev = &pdev->dev;
+		struct plat_serial8250_port *p = dev->platform_data;
 
 		if (!(info->enabled_uarts & (1 << i))) {
 			p->membase = NULL;
@@ -125,35 +582,40 @@
 		}
 
 		sprintf(name, "uart%d_ick", i+1);
-		uart_ick[i] = clk_get(NULL, name);
-		if (IS_ERR(uart_ick[i])) {
+		uart->ick = clk_get(NULL, name);
+		if (IS_ERR(uart->ick)) {
 			printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
-			uart_ick[i] = NULL;
-		} else
-			clk_enable(uart_ick[i]);
+			uart->ick = NULL;
+		}
 
 		sprintf(name, "uart%d_fck", i+1);
-		uart_fck[i] = clk_get(NULL, name);
-		if (IS_ERR(uart_fck[i])) {
+		uart->fck = clk_get(NULL, name);
+		if (IS_ERR(uart->fck)) {
 			printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
-			uart_fck[i] = NULL;
-		} else
-			clk_enable(uart_fck[i]);
+			uart->fck = NULL;
+		}
 
-		omap_serial_reset(p);
-	}
-}
+		if (!uart->ick || !uart->fck)
+			continue;
 
-static struct platform_device serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
-};
+		uart->num = i;
+		p->private_data = uart;
+		uart->p = p;
+		list_add_tail(&uart->node, &uart_list);
 
-static int __init omap_init(void)
-{
-	return platform_device_register(&serial_device);
+		if (cpu_is_omap44xx())
+			p->irq += 32;
+
+		omap_uart_enable_clocks(uart);
+		omap_uart_reset(uart);
+		omap_uart_idle_init(uart);
+
+		if (WARN_ON(platform_device_register(pdev)))
+			continue;
+		if ((cpu_is_omap34xx() && uart->padconf) ||
+		    (uart->wk_en && uart->wk_mask)) {
+			device_init_wakeup(dev, true);
+			DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
+		}
+	}
 }
-arch_initcall(omap_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sleep24xx.S linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sleep24xx.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sleep24xx.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sleep24xx.S	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,6 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
-#include <mach/pm.h>
 
 #include <mach/omap24xx.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sleep34xx.S linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sleep34xx.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sleep34xx.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sleep34xx.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,436 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2007
+ * Texas Instruments
+ * Karthik Dasu <karthik-dp@ti.com>
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/io.h>
+#include <mach/control.h>
+
+#include "prm.h"
+#include "sdrc.h"
+
+#define PM_PREPWSTST_CORE_V	OMAP34XX_PRM_REGADDR(CORE_MOD, \
+				OMAP3430_PM_PREPWSTST)
+#define PM_PREPWSTST_MPU_V	OMAP34XX_PRM_REGADDR(MPU_MOD, \
+				OMAP3430_PM_PREPWSTST)
+#define PM_PWSTCTRL_MPU_P	OMAP34XX_PRM_REGADDR(MPU_MOD, PM_PWSTCTRL)
+#define SCRATCHPAD_MEM_OFFS	0x310 /* Move this as correct place is
+				       * available */
+#define SCRATCHPAD_BASE_P	OMAP343X_CTRL_REGADDR(\
+				OMAP343X_CONTROL_MEM_WKUP +\
+				SCRATCHPAD_MEM_OFFS)
+#define SDRC_POWER_V		OMAP34XX_SDRC_REGADDR(SDRC_POWER)
+
+	.text
+/* Function call to get the restore pointer for resume from OFF */
+ENTRY(get_restore_pointer)
+        stmfd   sp!, {lr}     @ save registers on stack
+	adr	r0, restore
+        ldmfd   sp!, {pc}     @ restore regs and return
+ENTRY(get_restore_pointer_sz)
+        .word   . - get_restore_pointer_sz
+/*
+ * Forces OMAP into idle state
+ *
+ * omap34xx_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *	 wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap34xx_cpu_suspend)
+	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
+loop:
+	/*b	loop*/	@Enable to debug by stepping through code
+	/* r0 contains restore pointer in sdram */
+	/* r1 contains information about saving context */
+	ldr     r4, sdrc_power          @ read the SDRC_POWER register
+	ldr     r5, [r4]                @ read the contents of SDRC_POWER
+	orr     r5, r5, #0x40           @ enable self refresh on idle req
+	str     r5, [r4]                @ write back to SDRC_POWER register
+
+	cmp	r1, #0x0
+	/* If context save is required, do that and execute wfi */
+	bne	save_context_wfi
+	/* Data memory barrier and Data sync barrier */
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4
+	mcr	p15, 0, r1, c7, c10, 5
+
+	wfi				@ wait for interrupt
+
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	bl i_dll_wait
+
+	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+restore:
+	/* b restore*/ 	@ Enable to debug restore code
+        /* Check what was the reason for mpu reset and store the reason in r9*/
+        /* 1 - Only L1 and logic lost */
+        /* 2 - Only L2 lost - In this case, we wont be here */
+        /* 3 - Both L1 and L2 lost */
+	ldr     r1, pm_pwstctrl_mpu
+	ldr	r2, [r1]
+	and     r2, r2, #0x3
+	cmp     r2, #0x0	@ Check if target power state was OFF or RET
+        moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
+	movne	r9, #0x1	@ Only L1 and L2 lost => avoid L2 invalidation
+	bne	logic_l1_restore
+	/* Execute smi to invalidate L2 cache */
+	mov r12, #0x1                         @ set up to invalide L2
+smi:    .word 0xE1600070                @ Call SMI monitor (smieq)
+logic_l1_restore:
+	mov	r1, #0
+	/* Invalidate all instruction caches to PoU
+	 * and flush branch target cache */
+	mcr	p15, 0, r1, c7, c5, 0
+
+	ldr	r4, scratchpad_base
+	ldr	r3, [r4,#0xBC]
+	ldmia	r3!, {r4-r6}
+	mov	sp, r4
+	msr	spsr_cxsf, r5
+	mov	lr, r6
+
+	ldmia	r3!, {r4-r9}
+	/* Coprocessor access Control Register */
+	mcr p15, 0, r4, c1, c0, 2
+
+	/* TTBR0 */
+	MCR p15, 0, r5, c2, c0, 0
+	/* TTBR1 */
+	MCR p15, 0, r6, c2, c0, 1
+	/* Translation table base control register */
+	MCR p15, 0, r7, c2, c0, 2
+	/*domain access Control Register */
+	MCR p15, 0, r8, c3, c0, 0
+	/* data fault status Register */
+	MCR p15, 0, r9, c5, c0, 0
+
+	ldmia  r3!,{r4-r8}
+	/* instruction fault status Register */
+	MCR p15, 0, r4, c5, c0, 1
+	/*Data Auxiliary Fault Status Register */
+	MCR p15, 0, r5, c5, c1, 0
+	/*Instruction Auxiliary Fault Status Register*/
+	MCR p15, 0, r6, c5, c1, 1
+	/*Data Fault Address Register */
+	MCR p15, 0, r7, c6, c0, 0
+	/*Instruction Fault Address Register*/
+	MCR p15, 0, r8, c6, c0, 2
+	ldmia  r3!,{r4-r7}
+
+	/* user r/w thread and process ID */
+	MCR p15, 0, r4, c13, c0, 2
+	/* user ro thread and process ID */
+	MCR p15, 0, r5, c13, c0, 3
+	/*Privileged only thread and process ID */
+	MCR p15, 0, r6, c13, c0, 4
+	/* cache size selection */
+	MCR p15, 2, r7, c0, c0, 0
+	ldmia  r3!,{r4-r8}
+	/* Data TLB lockdown registers */
+	MCR p15, 0, r4, c10, c0, 0
+	/* Instruction TLB lockdown registers */
+	MCR p15, 0, r5, c10, c0, 1
+	/* Secure or Nonsecure Vector Base Address */
+	MCR p15, 0, r6, c12, c0, 0
+	/* FCSE PID */
+	MCR p15, 0, r7, c13, c0, 0
+	/* Context PID */
+	MCR p15, 0, r8, c13, c0, 1
+
+	ldmia  r3!,{r4-r5}
+	/* primary memory remap register */
+	MCR p15, 0, r4, c10, c2, 0
+	/*normal memory remap register */
+	MCR p15, 0, r5, c10, c2, 1
+
+	/* Restore cpsr */
+	ldmia	r3!,{r4}	/*load CPSR from SDRAM*/
+	msr	cpsr, r4	/*store cpsr */
+
+	/* Enabling MMU here */
+	mrc	p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
+	/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
+	and	r7, #0x7
+	cmp	r7, #0x0
+	beq	usettbr0
+ttbr_error:
+	/* More work needs to be done to support N[0:2] value other than 0
+	* So looping here so that the error can be detected
+	*/
+	b	ttbr_error
+usettbr0:
+	mrc	p15, 0, r2, c2, c0, 0
+	ldr	r5, ttbrbit_mask
+	and	r2, r5
+	mov	r4, pc
+	ldr	r5, table_index_mask
+	and	r4, r5 /* r4 = 31 to 20 bits of pc */
+	/* Extract the value to be written to table entry */
+	ldr	r1, table_entry
+	add	r1, r1, r4 /* r1 has value to be written to table entry*/
+	/* Getting the address of table entry to modify */
+	lsr	r4, #18
+	add	r2, r4 /* r2 has the location which needs to be modified */
+	/* Storing previous entry of location being modified */
+	ldr	r5, scratchpad_base
+	ldr	r4, [r2]
+	str	r4, [r5, #0xC0]
+	/* Modify the table entry */
+	str	r1, [r2]
+	/* Storing address of entry being modified
+	 * - will be restored after enabling MMU */
+	ldr	r5, scratchpad_base
+	str	r2, [r5, #0xC4]
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
+	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
+	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
+	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
+	/* Restore control register  but dont enable caches here*/
+	/* Caches will be enabled after restoring MMU table entry */
+	ldmia	r3!, {r4}
+	/* Store previous value of control register in scratchpad */
+	str	r4, [r5, #0xC8]
+	ldr	r2, cache_pred_disable_mask
+	and	r4, r2
+	mcr	p15, 0, r4, c1, c0, 0
+
+	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+save_context_wfi:
+	/*b	save_context_wfi*/	@ enable to debug save code
+	mov	r8, r0 /* Store SDRAM address in r8 */
+        /* Check what that target sleep state is:stored in r1*/
+        /* 1 - Only L1 and logic lost */
+        /* 2 - Only L2 lost */
+        /* 3 - Both L1 and L2 lost */
+	cmp	r1, #0x2 /* Only L2 lost */
+	beq	clean_l2
+	cmp	r1, #0x1 /* L2 retained */
+	/* r9 stores whether to clean L2 or not*/
+	moveq	r9, #0x0 /* Dont Clean L2 */
+	movne	r9, #0x1 /* Clean L2 */
+l1_logic_lost:
+	/* Store sp and spsr to SDRAM */
+	mov	r4, sp
+	mrs	r5, spsr
+	mov	r6, lr
+	stmia	r8!, {r4-r6}
+	/* Save all ARM registers */
+	/* Coprocessor access control register */
+	mrc	p15, 0, r6, c1, c0, 2
+	stmia	r8!, {r6}
+	/* TTBR0, TTBR1 and Translation table base control */
+	mrc	p15, 0, r4, c2, c0, 0
+	mrc	p15, 0, r5, c2, c0, 1
+	mrc	p15, 0, r6, c2, c0, 2
+	stmia	r8!, {r4-r6}
+	/* Domain access control register, data fault status register,
+	and instruction fault status register */
+	mrc	p15, 0, r4, c3, c0, 0
+	mrc	p15, 0, r5, c5, c0, 0
+	mrc	p15, 0, r6, c5, c0, 1
+	stmia	r8!, {r4-r6}
+	/* Data aux fault status register, instruction aux fault status,
+	datat fault address register and instruction fault address register*/
+	mrc	p15, 0, r4, c5, c1, 0
+	mrc	p15, 0, r5, c5, c1, 1
+	mrc	p15, 0, r6, c6, c0, 0
+	mrc	p15, 0, r7, c6, c0, 2
+	stmia	r8!, {r4-r7}
+	/* user r/w thread and process ID, user r/o thread and process ID,
+	priv only thread and process ID, cache size selection */
+	mrc	p15, 0, r4, c13, c0, 2
+	mrc	p15, 0, r5, c13, c0, 3
+	mrc	p15, 0, r6, c13, c0, 4
+	mrc	p15, 2, r7, c0, c0, 0
+	stmia	r8!, {r4-r7}
+	/* Data TLB lockdown, instruction TLB lockdown registers */
+	mrc	p15, 0, r5, c10, c0, 0
+	mrc	p15, 0, r6, c10, c0, 1
+	stmia	r8!, {r5-r6}
+	/* Secure or non secure vector base address, FCSE PID, Context PID*/
+	mrc	p15, 0, r4, c12, c0, 0
+	mrc	p15, 0, r5, c13, c0, 0
+	mrc	p15, 0, r6, c13, c0, 1
+	stmia	r8!, {r4-r6}
+	/* Primary remap, normal remap registers */
+	mrc	p15, 0, r4, c10, c2, 0
+	mrc	p15, 0, r5, c10, c2, 1
+	stmia	r8!,{r4-r5}
+
+	/* Store current cpsr*/
+	mrs	r2, cpsr
+	stmia	r8!, {r2}
+
+	mrc	p15, 0, r4, c1, c0, 0
+	/* save control register */
+	stmia	r8!, {r4}
+clean_caches:
+	/* Clean Data or unified cache to POU*/
+	/* How to invalidate only L1 cache???? - #FIX_ME# */
+	/* mcr	p15, 0, r11, c7, c11, 1 */
+	cmp	r9, #1 /* Check whether L2 inval is required or not*/
+	bne	skip_l2_inval
+clean_l2:
+	/* read clidr */
+	mrc     p15, 1, r0, c0, c0, 1
+	/* extract loc from clidr */
+	ands    r3, r0, #0x7000000
+	/* left align loc bit field */
+	mov     r3, r3, lsr #23
+	/* if loc is 0, then no need to clean */
+	beq     finished
+	/* start clean at cache level 0 */
+	mov     r10, #0
+loop1:
+	/* work out 3x current cache level */
+	add     r2, r10, r10, lsr #1
+	/* extract cache type bits from clidr*/
+	mov     r1, r0, lsr r2
+	/* mask of the bits for current cache only */
+	and     r1, r1, #7
+	/* see what cache we have at this level */
+	cmp     r1, #2
+	/* skip if no cache, or just i-cache */
+	blt     skip
+	/* select current cache level in cssr */
+	mcr     p15, 2, r10, c0, c0, 0
+	/* isb to sych the new cssr&csidr */
+	isb
+	/* read the new csidr */
+	mrc     p15, 1, r1, c0, c0, 0
+	/* extract the length of the cache lines */
+	and     r2, r1, #7
+	/* add 4 (line length offset) */
+	add     r2, r2, #4
+	ldr     r4, assoc_mask
+	/* find maximum number on the way size */
+	ands    r4, r4, r1, lsr #3
+	/* find bit position of way size increment */
+	clz     r5, r4
+	ldr     r7, numset_mask
+	/* extract max number of the index size*/
+	ands    r7, r7, r1, lsr #13
+loop2:
+	mov     r9, r4
+	/* create working copy of max way size*/
+loop3:
+	/* factor way and cache number into r11 */
+	orr     r11, r10, r9, lsl r5
+	/* factor index number into r11 */
+	orr     r11, r11, r7, lsl r2
+	/*clean & invalidate by set/way */
+	mcr     p15, 0, r11, c7, c10, 2
+	/* decrement the way*/
+	subs    r9, r9, #1
+	bge     loop3
+	/*decrement the index */
+	subs    r7, r7, #1
+	bge     loop2
+skip:
+	add     r10, r10, #2
+	/* increment cache number */
+	cmp     r3, r10
+	bgt     loop1
+finished:
+	/*swith back to cache level 0 */
+	mov     r10, #0
+	/* select current cache level in cssr */
+	mcr     p15, 2, r10, c0, c0, 0
+	isb
+skip_l2_inval:
+	/* Data memory barrier and Data sync barrier */
+	mov     r1, #0
+	mcr     p15, 0, r1, c7, c10, 4
+	mcr     p15, 0, r1, c7, c10, 5
+
+	wfi                             @ wait for interrupt
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	bl i_dll_wait
+	/* restore regs and return */
+	ldmfd   sp!, {r0-r12, pc}
+
+i_dll_wait:
+	ldr     r4, clk_stabilize_delay
+
+i_dll_delay:
+	subs    r4, r4, #0x1
+	bne     i_dll_delay
+	ldr     r4, sdrc_power
+	ldr     r5, [r4]
+	bic     r5, r5, #0x40
+	str     r5, [r4]
+	bx	lr
+pm_prepwstst_core:
+	.word	PM_PREPWSTST_CORE_V
+pm_prepwstst_mpu:
+	.word	PM_PREPWSTST_MPU_V
+pm_pwstctrl_mpu:
+	.word	PM_PWSTCTRL_MPU_P
+scratchpad_base:
+	.word	SCRATCHPAD_BASE_P
+sdrc_power:
+	.word SDRC_POWER_V
+context_mem:
+	.word	0x803E3E14
+clk_stabilize_delay:
+	.word 0x000001FF
+assoc_mask:
+	.word	0x3ff
+numset_mask:
+	.word	0x7fff
+ttbrbit_mask:
+	.word	0xFFFFC000
+table_index_mask:
+	.word	0xFFF00000
+table_entry:
+	.word	0x00000C02
+cache_pred_disable_mask:
+	.word	0xFFFFE7FB
+ENTRY(omap34xx_cpu_suspend_sz)
+	.word	. - omap34xx_cpu_suspend
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sram242x.S linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sram242x.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sram242x.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sram242x.S	2009-09-09 18:13:59.000000000 -0400
@@ -124,11 +124,11 @@
 omap242x_sdi_sdrc_dlla_ctrl:
 	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
 omap242x_sdi_prcm_voltctrl:
-	.word OMAP242X_PRCM_VOLTCTRL
+	.word OMAP2420_PRCM_VOLTCTRL
 prcm_mask_val:
 	.word 0xFFFF3FFC
 omap242x_sdi_timer_32ksynct_cr:
-	.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
+	.word IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010)
 ENTRY(omap242x_sram_ddr_init_sz)
 	.word	. - omap242x_sram_ddr_init
 
@@ -220,11 +220,11 @@
 omap242x_srs_sdrc_rfr_ctrl:
 	.word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
 omap242x_srs_prcm_voltctrl:
-	.word OMAP242X_PRCM_VOLTCTRL
+	.word OMAP2420_PRCM_VOLTCTRL
 ddr_prcm_mask_val:
 	.word 0xFFFF3FFC
 omap242x_srs_timer_32ksynct:
-	.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
+	.word IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010)
 
 ENTRY(omap242x_sram_reprogram_sdrc_sz)
 	.word	. - omap242x_sram_reprogram_sdrc
@@ -305,7 +305,7 @@
 	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
 
 omap242x_ssp_set_config:
-	.word OMAP242X_PRCM_CLKCFG_CTRL
+	.word OMAP2420_PRCM_CLKCFG_CTRL
 omap242x_ssp_pll_ctl:
 	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKEN)
 omap242x_ssp_pll_stat:
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sram243x.S linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sram243x.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sram243x.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sram243x.S	2009-09-09 18:13:59.000000000 -0400
@@ -124,11 +124,11 @@
 omap243x_sdi_sdrc_dlla_ctrl:
 	.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
 omap243x_sdi_prcm_voltctrl:
-	.word OMAP243X_PRCM_VOLTCTRL
+	.word OMAP2430_PRCM_VOLTCTRL
 prcm_mask_val:
 	.word 0xFFFF3FFC
 omap243x_sdi_timer_32ksynct_cr:
-	.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
+	.word IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010)
 ENTRY(omap243x_sram_ddr_init_sz)
 	.word	. - omap243x_sram_ddr_init
 
@@ -220,11 +220,11 @@
 omap243x_srs_sdrc_rfr_ctrl:
 	.word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
 omap243x_srs_prcm_voltctrl:
-	.word OMAP243X_PRCM_VOLTCTRL
+	.word OMAP2430_PRCM_VOLTCTRL
 ddr_prcm_mask_val:
 	.word 0xFFFF3FFC
 omap243x_srs_timer_32ksynct:
-	.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
+	.word IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010)
 
 ENTRY(omap243x_sram_reprogram_sdrc_sz)
 	.word	. - omap243x_sram_reprogram_sdrc
@@ -305,7 +305,7 @@
 	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
 
 omap243x_ssp_set_config:
-	.word OMAP243X_PRCM_CLKCFG_CTRL
+	.word OMAP2430_PRCM_CLKCFG_CTRL
 omap243x_ssp_pll_ctl:
 	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN)
 omap243x_ssp_pll_stat:
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sram34xx.S linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sram34xx.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/sram34xx.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/sram34xx.S	2009-09-09 18:13:59.000000000 -0400
@@ -3,13 +3,12 @@
  *
  * Omap3 specific functions that need to be run in internal SRAM
  *
- * (C) Copyright 2007
- * Texas Instruments Inc.
- * Rajendra Nayak <rnayak@ti.com>
+ * Copyright (C) 2004, 2007, 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008 Nokia Corporation
  *
- * (C) Copyright 2004
- * Texas Instruments, <www.ti.com>
+ * Rajendra Nayak <rnayak@ti.com>
  * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -37,121 +36,214 @@
 
 	.text
 
+/* r1 parameters */
+#define SDRC_NO_UNLOCK_DLL		0x0
+#define SDRC_UNLOCK_DLL			0x1
+
+/* SDRC_DLLA_CTRL bit settings */
+#define FIXEDDELAY_SHIFT		24
+#define FIXEDDELAY_MASK			(0xff << FIXEDDELAY_SHIFT)
+#define DLLIDLE_MASK			0x4
+
 /*
- * Change frequency of core dpll
- * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2
+ * SDRC_DLLA_CTRL default values: TI hardware team indicates that
+ * FIXEDDELAY should be initialized to 0xf.  This apparently was
+ * empirically determined during process testing, so no derivation
+ * was provided.
+ */
+#define FIXEDDELAY_DEFAULT		(0x0f << FIXEDDELAY_SHIFT)
+
+/* SDRC_DLLA_STATUS bit settings */
+#define LOCKSTATUS_MASK			0x4
+
+/* SDRC_POWER bit settings */
+#define SRFRONIDLEREQ_MASK		0x40
+
+/* CM_IDLEST1_CORE bit settings */
+#define ST_SDRC_MASK			0x2
+
+/* CM_ICLKEN1_CORE bit settings */
+#define EN_SDRC_MASK			0x2
+
+/* CM_CLKSEL1_PLL bit settings */
+#define CORE_DPLL_CLKOUT_DIV_SHIFT	0x1b
+
+/*
+ * omap3_sram_configure_core_dpll - change DPLL3 M2 divider
+ *
+ * Params passed in registers:
+ *  r0 = new M2 divider setting (only 1 and 2 supported right now)
+ *  r1 = unlock SDRC DLL? (1 = yes, 0 = no).  Only unlock DLL for
+ *      SDRC rates < 83MHz
+ *  r2 = number of MPU cycles to wait for SDRC to stabilize after
+ *      reprogramming the SDRC when switching to a slower MPU speed
+ *  r3 = increasing SDRC rate? (1 = yes, 0 = no)
+ *
+ * Params passed via the stack. The needed params will be copied in SRAM
+ *  before use by the code in SRAM (SDRAM is not accessible during SDRC
+ *  reconfiguration):
+ *  new SDRC_RFR_CTRL_0 register contents
+ *  new SDRC_ACTIM_CTRL_A_0 register contents
+ *  new SDRC_ACTIM_CTRL_B_0 register contents
+ *  new SDRC_MR_0 register value
+ *  new SDRC_RFR_CTRL_1 register contents
+ *  new SDRC_ACTIM_CTRL_A_1 register contents
+ *  new SDRC_ACTIM_CTRL_B_1 register contents
+ *  new SDRC_MR_1 register value
+ *
+ * If the param SDRC_RFR_CTRL_1 is 0, the parameters
+ *  are not programmed into the SDRC CS1 registers
  */
 ENTRY(omap3_sram_configure_core_dpll)
 	stmfd	sp!, {r1-r12, lr}	@ store regs to stack
-	cmp	r3, #0x2
-	blne	configure_sdrc
-	cmp	r3, #0x2
+
+					@ pull the extra args off the stack
+					@  and store them in SRAM
+	ldr	r4, [sp, #52]
+	str     r4, omap_sdrc_rfr_ctrl_0_val
+	ldr	r4, [sp, #56]
+	str     r4, omap_sdrc_actim_ctrl_a_0_val
+	ldr	r4, [sp, #60]
+	str     r4, omap_sdrc_actim_ctrl_b_0_val
+	ldr	r4, [sp, #64]
+	str     r4, omap_sdrc_mr_0_val
+	ldr	r4, [sp, #68]
+	str     r4, omap_sdrc_rfr_ctrl_1_val
+	cmp	r4, #0			@ if SDRC_RFR_CTRL_1 is 0,
+	beq	skip_cs1_params		@  do not use cs1 params
+	ldr	r4, [sp, #72]
+	str     r4, omap_sdrc_actim_ctrl_a_1_val
+	ldr	r4, [sp, #76]
+	str     r4, omap_sdrc_actim_ctrl_b_1_val
+	ldr	r4, [sp, #80]
+	str     r4, omap_sdrc_mr_1_val
+skip_cs1_params:
+	dsb				@ flush buffered writes to interconnect
+
+	cmp	r3, #1			@ if increasing SDRC clk rate,
+	bleq	configure_sdrc		@ program the SDRC regs early (for RFR)
+	cmp	r1, #SDRC_UNLOCK_DLL	@ set the intended DLL state
+	bleq	unlock_dll
 	blne	lock_dll
-	cmp	r3, #0x1
-	blne	unlock_dll
-	bl	sdram_in_selfrefresh	@ put the SDRAM in self refresh
-	bl 	configure_core_dpll
-	bl	enable_sdrc
-	cmp	r3, #0x1
-	blne	wait_dll_unlock
-	cmp	r3, #0x2
+	bl	sdram_in_selfrefresh	@ put SDRAM in self refresh, idle SDRC
+	bl 	configure_core_dpll	@ change the DPLL3 M2 divider
+	mov	r12, r2
+	bl	wait_clk_stable		@ wait for SDRC to stabilize
+	bl	enable_sdrc		@ take SDRC out of idle
+	cmp	r1, #SDRC_UNLOCK_DLL	@ wait for DLL status to change
+	bleq	wait_dll_unlock
 	blne	wait_dll_lock
-	cmp	r3, #0x1
-	blne	configure_sdrc
+	cmp	r3, #1			@ if increasing SDRC clk rate,
+	beq	return_to_sdram		@ return to SDRAM code, otherwise,
+	bl	configure_sdrc		@ reprogram SDRC regs now
+return_to_sdram:
+	isb				@ prevent speculative exec past here
 	mov 	r0, #0 			@ return value
 	ldmfd	sp!, {r1-r12, pc}	@ restore regs and return
 unlock_dll:
-	ldr	r4, omap3_sdrc_dlla_ctrl
-	ldr	r5, [r4]
-	orr	r5, r5, #0x4
-	str	r5, [r4]
+	ldr	r11, omap3_sdrc_dlla_ctrl
+	ldr	r12, [r11]
+	bic	r12, r12, #FIXEDDELAY_MASK
+	orr	r12, r12, #FIXEDDELAY_DEFAULT
+	orr	r12, r12, #DLLIDLE_MASK
+	str	r12, [r11]		@ (no OCP barrier needed)
 	bx	lr
 lock_dll:
-	ldr	r4, omap3_sdrc_dlla_ctrl
-	ldr	r5, [r4]
-	bic	r5, r5, #0x4
-	str	r5, [r4]
+	ldr	r11, omap3_sdrc_dlla_ctrl
+	ldr	r12, [r11]
+	bic	r12, r12, #DLLIDLE_MASK
+	str	r12, [r11]		@ (no OCP barrier needed)
 	bx	lr
 sdram_in_selfrefresh:
-	mov	r5, #0x0		@ Move 0 to R5
-	mcr	p15, 0, r5, c7, c10, 5	@ memory barrier
-	ldr	r4, omap3_sdrc_power	@ read the SDRC_POWER register
-	ldr	r5, [r4]		@ read the contents of SDRC_POWER
-	orr 	r5, r5, #0x40		@ enable self refresh on idle req
-	str 	r5, [r4]		@ write back to SDRC_POWER register
-	ldr	r4, omap3_cm_iclken1_core	@ read the CM_ICLKEN1_CORE reg
-	ldr	r5, [r4]
-	bic	r5, r5, #0x2		@ disable iclk bit for SRDC
-	str 	r5, [r4]
+	ldr	r11, omap3_sdrc_power	@ read the SDRC_POWER register
+	ldr	r12, [r11]		@ read the contents of SDRC_POWER
+	mov	r9, r12			@ keep a copy of SDRC_POWER bits
+	orr 	r12, r12, #SRFRONIDLEREQ_MASK	@ enable self refresh on idle
+	str 	r12, [r11]		@ write back to SDRC_POWER register
+	ldr	r12, [r11]		@ posted-write barrier for SDRC
+idle_sdrc:
+	ldr	r11, omap3_cm_iclken1_core	@ read the CM_ICLKEN1_CORE reg
+	ldr	r12, [r11]
+	bic	r12, r12, #EN_SDRC_MASK		@ disable iclk bit for SDRC
+	str 	r12, [r11]
 wait_sdrc_idle:
-	ldr 	r4, omap3_cm_idlest1_core
-	ldr 	r5, [r4]
-	and 	r5, r5, #0x2		@ check for SDRC idle
-	cmp 	r5, #2
+	ldr 	r11, omap3_cm_idlest1_core
+	ldr 	r12, [r11]
+	and 	r12, r12, #ST_SDRC_MASK		@ check for SDRC idle
+	cmp 	r12, #ST_SDRC_MASK
 	bne 	wait_sdrc_idle
 	bx 	lr
 configure_core_dpll:
-	ldr 	r4, omap3_cm_clksel1_pll
-	ldr	r5, [r4]
-	ldr	r6, core_m2_mask_val	@ modify m2 for core dpll
-	and	r5, r5, r6
-	orr	r5, r5, r3, lsl #0x1B	@ r3 contains the M2 val
-	str	r5, [r4]
-	mov 	r5, #0x800		@ wait for the clock to stabilise
-	cmp	r3, #2
-	bne	wait_clk_stable
+	ldr 	r11, omap3_cm_clksel1_pll
+	ldr	r12, [r11]
+	ldr	r10, core_m2_mask_val	@ modify m2 for core dpll
+	and	r12, r12, r10
+	orr	r12, r12, r0, lsl #CORE_DPLL_CLKOUT_DIV_SHIFT
+	str	r12, [r11]
+	ldr	r12, [r11]		@ posted-write barrier for CM
 	bx	lr
 wait_clk_stable:
-	subs 	r5, r5, #1
+	subs 	r12, r12, #1
 	bne	wait_clk_stable
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
 	bx	lr
 enable_sdrc:
-	ldr 	r4, omap3_cm_iclken1_core
-	ldr	r5, [r4]
-	orr 	r5, r5, #0x2		@ enable iclk bit for SDRC
-	str 	r5, [r4]
+	ldr 	r11, omap3_cm_iclken1_core
+	ldr	r12, [r11]
+	orr 	r12, r12, #EN_SDRC_MASK		@ enable iclk bit for SDRC
+	str 	r12, [r11]
 wait_sdrc_idle1:
-	ldr 	r4, omap3_cm_idlest1_core
-	ldr	r5, [r4]
-	and 	r5, r5, #0x2
-	cmp	r5, #0
+	ldr 	r11, omap3_cm_idlest1_core
+	ldr	r12, [r11]
+	and 	r12, r12, #ST_SDRC_MASK
+	cmp	r12, #0
 	bne	wait_sdrc_idle1
-	ldr	r4, omap3_sdrc_power
-	ldr	r5, [r4]
-	bic 	r5, r5, #0x40
-	str 	r5, [r4]
+restore_sdrc_power_val:
+	ldr	r11, omap3_sdrc_power
+	str	r9, [r11]		@ restore SDRC_POWER, no barrier needed
 	bx	lr
 wait_dll_lock:
-	ldr	r4, omap3_sdrc_dlla_status
-	ldr	r5, [r4]
-	and 	r5, r5, #0x4
-	cmp	r5, #0x4
+	ldr	r11, omap3_sdrc_dlla_status
+	ldr	r12, [r11]
+	and 	r12, r12, #LOCKSTATUS_MASK
+	cmp	r12, #LOCKSTATUS_MASK
 	bne	wait_dll_lock
 	bx	lr
 wait_dll_unlock:
-	ldr	r4, omap3_sdrc_dlla_status
-	ldr	r5, [r4]
-	and	r5, r5, #0x4
-	cmp	r5, #0x0
+	ldr	r11, omap3_sdrc_dlla_status
+	ldr	r12, [r11]
+	and	r12, r12, #LOCKSTATUS_MASK
+	cmp	r12, #0x0
 	bne	wait_dll_unlock
 	bx	lr
 configure_sdrc:
-	ldr	r4, omap3_sdrc_rfr_ctrl
-	str	r0, [r4]
-	ldr	r4, omap3_sdrc_actim_ctrla
-	str	r1, [r4]
-	ldr	r4, omap3_sdrc_actim_ctrlb
-	str	r2, [r4]
+	ldr	r12, omap_sdrc_rfr_ctrl_0_val	@ fetch value from SRAM
+	ldr	r11, omap3_sdrc_rfr_ctrl_0	@ fetch addr from SRAM
+	str	r12, [r11]			@ store
+	ldr	r12, omap_sdrc_actim_ctrl_a_0_val
+	ldr	r11, omap3_sdrc_actim_ctrl_a_0
+	str	r12, [r11]
+	ldr	r12, omap_sdrc_actim_ctrl_b_0_val
+	ldr	r11, omap3_sdrc_actim_ctrl_b_0
+	str	r12, [r11]
+	ldr	r12, omap_sdrc_mr_0_val
+	ldr	r11, omap3_sdrc_mr_0
+	str	r12, [r11]
+	ldr	r12, omap_sdrc_rfr_ctrl_1_val
+	cmp	r12, #0			@ if SDRC_RFR_CTRL_1 is 0,
+	beq	skip_cs1_prog		@  do not program cs1 params
+	ldr	r11, omap3_sdrc_rfr_ctrl_1
+	str	r12, [r11]
+	ldr	r12, omap_sdrc_actim_ctrl_a_1_val
+	ldr	r11, omap3_sdrc_actim_ctrl_a_1
+	str	r12, [r11]
+	ldr	r12, omap_sdrc_actim_ctrl_b_1_val
+	ldr	r11, omap3_sdrc_actim_ctrl_b_1
+	str	r12, [r11]
+	ldr	r12, omap_sdrc_mr_1_val
+	ldr	r11, omap3_sdrc_mr_1
+	str	r12, [r11]
+skip_cs1_prog:
+	ldr	r12, [r11]		@ posted-write barrier for SDRC
 	bx	lr
 
 omap3_sdrc_power:
@@ -162,12 +254,40 @@
 	.word OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST)
 omap3_cm_iclken1_core:
 	.word OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)
-omap3_sdrc_rfr_ctrl:
+
+omap3_sdrc_rfr_ctrl_0:
 	.word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_0)
-omap3_sdrc_actim_ctrla:
+omap3_sdrc_rfr_ctrl_1:
+	.word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_1)
+omap3_sdrc_actim_ctrl_a_0:
 	.word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A_0)
-omap3_sdrc_actim_ctrlb:
+omap3_sdrc_actim_ctrl_a_1:
+	.word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A_1)
+omap3_sdrc_actim_ctrl_b_0:
 	.word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B_0)
+omap3_sdrc_actim_ctrl_b_1:
+	.word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B_1)
+omap3_sdrc_mr_0:
+	.word OMAP34XX_SDRC_REGADDR(SDRC_MR_0)
+omap3_sdrc_mr_1:
+	.word OMAP34XX_SDRC_REGADDR(SDRC_MR_1)
+omap_sdrc_rfr_ctrl_0_val:
+	.word 0xDEADBEEF
+omap_sdrc_rfr_ctrl_1_val:
+	.word 0xDEADBEEF
+omap_sdrc_actim_ctrl_a_0_val:
+	.word 0xDEADBEEF
+omap_sdrc_actim_ctrl_a_1_val:
+	.word 0xDEADBEEF
+omap_sdrc_actim_ctrl_b_0_val:
+	.word 0xDEADBEEF
+omap_sdrc_actim_ctrl_b_1_val:
+	.word 0xDEADBEEF
+omap_sdrc_mr_0_val:
+	.word 0xDEADBEEF
+omap_sdrc_mr_1_val:
+	.word 0xDEADBEEF
+
 omap3_sdrc_dlla_status:
 	.word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
 omap3_sdrc_dlla_ctrl:
@@ -177,3 +297,4 @@
 
 ENTRY(omap3_sram_configure_core_dpll_sz)
 	.word	. - omap3_sram_configure_core_dpll
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/timer-gp.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/timer-gp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/timer-gp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/timer-gp.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,9 +17,10 @@
  *
  * Some parts based off of TI's 24xx code:
  *
- *   Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2004-2009 Texas Instruments, Inc.
  *
  * Roughly modelled after the OMAP1 MPU timer code.
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.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
@@ -37,6 +38,7 @@
 
 #include <asm/mach/time.h>
 #include <mach/dmtimer.h>
+#include <asm/localtimer.h>
 
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
@@ -82,7 +84,8 @@
 	case CLOCK_EVT_MODE_PERIODIC:
 		period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
 		period -= 1;
-
+		if (cpu_is_omap44xx())
+			period = 0xff;	/* FIXME: */
 		omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -145,6 +148,9 @@
 		     "timer-gp: omap_dm_timer_set_source() failed\n");
 
 	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
+	if (cpu_is_omap44xx())
+		/* Assuming 32kHz clk is driving GPT1 */
+		tick_rate = 32768;	/* FIXME: */
 
 	pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n",
 		gptimer_id, tick_rate);
@@ -224,6 +230,9 @@
 
 static void __init omap2_gp_timer_init(void)
 {
+#ifdef CONFIG_LOCAL_TIMERS
+	twd_base = IO_ADDRESS(OMAP44XX_LOCAL_TWD_BASE);
+#endif
 	omap_dm_timer_init();
 
 	omap2_gp_clockevent_init();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/timer-mpu.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/timer-mpu.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/timer-mpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/timer-mpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * The MPU local timer source file. In OMAP4, both cortex-a9 cores have
+ * own timer in it's MPU domain. These timers will be driving the
+ * linux kernel SMP tick framework when active. These timers are not
+ * part of the wake up domain.
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author:
+ *      Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This file is based on arm realview smp platform file.
+ * Copyright (C) 2002 ARM Ltd.
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/clockchips.h>
+#include <asm/irq.h>
+#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	evt->irq = INT_44XX_LOCALTIMER_IRQ;
+	twd_timer_setup(evt);
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-omap2/usb-musb.c linux-libre-2.6.31-gnu/arch/arm/mach-omap2/usb-musb.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-omap2/usb-musb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-omap2/usb-musb.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,10 +28,20 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/pm.h>
 #include <mach/mux.h>
 #include <mach/usb.h>
 
+#define OTG_SYSCONFIG	(OMAP34XX_HSUSB_OTG_BASE + 0x404)
+
+static void __init usb_musb_pm_init(void)
+{
+	/* Ensure force-idle mode for OTG controller */
+	if (cpu_is_omap34xx())
+		omap_writel(0, OTG_SYSCONFIG);
+}
+
+#ifdef CONFIG_USB_MUSB_SOC
+
 static struct resource musb_resources[] = {
 	[0] = { /* start and end set dynamically */
 		.flags	= IORESOURCE_MEM,
@@ -145,20 +155,6 @@
 	.resource	= musb_resources,
 };
 
-#ifdef CONFIG_NOP_USB_XCEIV
-static u64 nop_xceiv_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device nop_xceiv_device = {
-	.name		= "nop_usb_xceiv",
-	.id		= -1,
-	.dev = {
-		.dma_mask		= &nop_xceiv_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data		= NULL,
-	},
-};
-#endif
-
 void __init usb_musb_init(void)
 {
 	if (cpu_is_omap243x())
@@ -173,15 +169,17 @@
 	 */
 	musb_plat.clock = "ick";
 
-#ifdef CONFIG_NOP_USB_XCEIV
-	if (platform_device_register(&nop_xceiv_device) < 0) {
-		printk(KERN_ERR "Unable to register NOP-XCEIV device\n");
-		return;
-	}
-#endif
-
 	if (platform_device_register(&musb_device) < 0) {
 		printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
 		return;
 	}
+
+	usb_musb_pm_init();
+}
+
+#else
+void __init usb_musb_init(void)
+{
+	usb_musb_pm_init();
 }
+#endif /* CONFIG_USB_MUSB_SOC */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/addr-map.c linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/addr-map.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/addr-map.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/addr-map.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/mbus.h>
 #include <linux/io.h>
+#include <linux/errno.h>
 #include <mach/hardware.h>
 #include "common.h"
 
@@ -44,6 +45,7 @@
 #define TARGET_DEV_BUS		1
 #define TARGET_PCI		3
 #define TARGET_PCIE		4
+#define TARGET_SRAM		9
 #define ATTR_PCIE_MEM		0x59
 #define ATTR_PCIE_IO		0x51
 #define ATTR_PCIE_WA		0x79
@@ -53,6 +55,7 @@
 #define ATTR_DEV_CS1		0x1d
 #define ATTR_DEV_CS2		0x1b
 #define ATTR_DEV_BOOT		0xf
+#define ATTR_SRAM		0x0
 
 /*
  * Helpers to get DDR bank info
@@ -87,13 +90,13 @@
 	return 0;
 }
 
-static void __init setup_cpu_win(int win, u32 base, u32 size,
+static int __init setup_cpu_win(int win, u32 base, u32 size,
 				 u8 target, u8 attr, int remap)
 {
 	if (win >= 8) {
 		printk(KERN_ERR "setup_cpu_win: trying to allocate "
 				"window %d\n", win);
-		return;
+		return -ENOSPC;
 	}
 
 	writel(base & 0xffff0000, CPU_WIN_BASE(win));
@@ -107,6 +110,7 @@
 		writel(remap & 0xffff0000, CPU_WIN_REMAP_LO(win));
 		writel(0, CPU_WIN_REMAP_HI(win));
 	}
+	return 0;
 }
 
 void __init orion5x_setup_cpu_mbus_bridge(void)
@@ -193,3 +197,9 @@
 	setup_cpu_win(win_alloc_count++, base, size,
 		      TARGET_PCIE, ATTR_PCIE_WA, -1);
 }
+
+int __init orion5x_setup_sram_win(void)
+{
+	return setup_cpu_win(win_alloc_count++, ORION5X_SRAM_PHYS_BASE,
+			ORION5X_SRAM_SIZE, TARGET_SRAM, ATTR_SRAM, -1);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/common.c linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/common.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/common.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,7 +31,7 @@
 #include <plat/ehci-orion.h>
 #include <plat/mv_xor.h>
 #include <plat/orion_nand.h>
-#include <plat/orion5x_wdt.h>
+#include <plat/orion_wdt.h>
 #include <plat/time.h>
 #include "common.h"
 
@@ -536,16 +536,52 @@
 	platform_device_register(&orion5x_xor1_channel);
 }
 
+static struct resource orion5x_crypto_res[] = {
+	{
+		.name   = "regs",
+		.start  = ORION5X_CRYPTO_PHYS_BASE,
+		.end    = ORION5X_CRYPTO_PHYS_BASE + 0xffff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.name   = "sram",
+		.start  = ORION5X_SRAM_PHYS_BASE,
+		.end    = ORION5X_SRAM_PHYS_BASE + SZ_8K - 1,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.name   = "crypto interrupt",
+		.start  = IRQ_ORION5X_CESA,
+		.end    = IRQ_ORION5X_CESA,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device orion5x_crypto_device = {
+	.name           = "mv_crypto",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(orion5x_crypto_res),
+	.resource       = orion5x_crypto_res,
+};
+
+static int __init orion5x_crypto_init(void)
+{
+	int ret;
+
+	ret = orion5x_setup_sram_win();
+	if (ret)
+		return ret;
+
+	return platform_device_register(&orion5x_crypto_device);
+}
 
 /*****************************************************************************
  * Watchdog
  ****************************************************************************/
-static struct orion5x_wdt_platform_data orion5x_wdt_data = {
+static struct orion_wdt_platform_data orion5x_wdt_data = {
 	.tclk			= 0,
 };
 
 static struct platform_device orion5x_wdt_device = {
-	.name		= "orion5x_wdt",
+	.name		= "orion_wdt",
 	.id		= -1,
 	.dev		= {
 		.platform_data	= &orion5x_wdt_data,
@@ -661,6 +697,14 @@
 	}
 
 	/*
+	 * The 5082/5181l/5182/6082/6082l/6183 have crypto
+	 * while 5180n/5181/5281 don't have crypto.
+	 */
+	if ((dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0) ||
+	    dev == MV88F5182_DEV_ID || dev == MV88F6183_DEV_ID)
+		orion5x_crypto_init();
+
+	/*
 	 * Register watchdog driver
 	 */
 	orion5x_wdt_init();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/common.h linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/common.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/common.h	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 void orion5x_setup_dev1_win(u32 base, u32 size);
 void orion5x_setup_dev2_win(u32 base, u32 size);
 void orion5x_setup_pcie_wa_win(u32 base, u32 size);
+int orion5x_setup_sram_win(void);
 
 void orion5x_ehci0_init(void);
 void orion5x_ehci1_init(void);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,8 +17,8 @@
 
 #define CPU_CTRL		(ORION5X_BRIDGE_VIRT_BASE | 0x104)
 
-#define CPU_RESET_MASK		(ORION5X_BRIDGE_VIRT_BASE | 0x108)
-#define WDT_RESET		0x0002
+#define RSTOUTn_MASK		(ORION5X_BRIDGE_VIRT_BASE | 0x108)
+#define WDT_RESET_OUT_EN	0x0002
 
 #define CPU_SOFT_RESET		(ORION5X_BRIDGE_VIRT_BASE | 0x10c)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
  * f1000000	on-chip peripheral registers
  * f2000000	PCIe I/O space
  * f2100000	PCI I/O space
+ * f2200000	SRAM dedicated for the crypto unit
  * f4000000	device bus mappings (boot)
  * fa000000	device bus mappings (cs0)
  * fa800000	device bus mappings (cs2)
@@ -49,6 +50,9 @@
 #define ORION5X_PCI_IO_BUS_BASE		0x00100000
 #define ORION5X_PCI_IO_SIZE		SZ_1M
 
+#define ORION5X_SRAM_PHYS_BASE		(0xf2200000)
+#define ORION5X_SRAM_SIZE		SZ_8K
+
 /* Relevant only for Orion-1/Orion-NAS */
 #define ORION5X_PCIE_WA_PHYS_BASE	0xf0000000
 #define ORION5X_PCIE_WA_VIRT_BASE	0xfe000000
@@ -94,6 +98,8 @@
 #define ORION5X_SATA_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x80000)
 #define ORION5X_SATA_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x80000)
 
+#define ORION5X_CRYPTO_PHYS_BASE	(ORION5X_REGS_PHYS_BASE | 0x90000)
+
 #define ORION5X_USB1_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0xa0000)
 #define ORION5X_USB1_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0xa0000)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/include/mach/system.h linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/include/mach/system.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/include/mach/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/include/mach/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -23,7 +23,7 @@
 	/*
 	 * Enable and issue soft reset
 	 */
-	orion5x_setbits(CPU_RESET_MASK, (1 << 2));
+	orion5x_setbits(RSTOUTn_MASK, (1 << 2));
 	orion5x_setbits(CPU_SOFT_RESET, 1);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/mpp.c linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/mpp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/mpp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/mpp.c	2009-09-09 18:13:59.000000000 -0400
@@ -124,6 +124,9 @@
 	u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL);
 	u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL);
 
+	/* Initialize gpiolib. */
+	orion_gpio_init();
+
 	while (mode->mpp >= 0) {
 		u32 *reg;
 		int num_type;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/mss2-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/mss2-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/mss2-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/mss2-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -181,9 +181,9 @@
 	/*
 	 * Enable and issue soft reset
 	 */
-	reg = readl(CPU_RESET_MASK);
+	reg = readl(RSTOUTn_MASK);
 	reg |= 1 << 2;
-	writel(reg, CPU_RESET_MASK);
+	writel(reg, RSTOUTn_MASK);
 
 	reg = readl(CPU_SOFT_RESET);
 	reg |= 1;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 	/* Technologic Systems */
 	struct fpga_device 	ts_rtc;
 	struct fpga_device 	ts_nand;
+	struct fpga_device 	ts_rng;
 };
 
 struct ts78xx_fpga_data {
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/ts78xx-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/ts78xx-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/ts78xx-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/ts78xx-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/m48t86.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/timeriomem-rng.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -270,12 +271,57 @@
 }
 
 /*****************************************************************************
+ * HW RNG
+ ****************************************************************************/
+#define TS_RNG_DATA	(TS78XX_FPGA_REGS_PHYS_BASE | 0x044)
+
+static struct resource ts78xx_ts_rng_resource = {
+	.flags		= IORESOURCE_MEM,
+	.start		= TS_RNG_DATA,
+	.end		= TS_RNG_DATA + 4 - 1,
+};
+
+static struct timeriomem_rng_data ts78xx_ts_rng_data = {
+	.period		= 1000000, /* one second */
+};
+
+static struct platform_device ts78xx_ts_rng_device = {
+	.name		= "timeriomem_rng",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &ts78xx_ts_rng_data,
+	},
+	.resource	= &ts78xx_ts_rng_resource,
+	.num_resources	= 1,
+};
+
+static int ts78xx_ts_rng_load(void)
+{
+	int rc;
+
+	if (ts78xx_fpga.supports.ts_rng.init == 0) {
+		rc = platform_device_register(&ts78xx_ts_rng_device);
+		if (!rc)
+			ts78xx_fpga.supports.ts_rng.init = 1;
+	} else
+		rc = platform_device_add(&ts78xx_ts_rng_device);
+
+	return rc;
+};
+
+static void ts78xx_ts_rng_unload(void)
+{
+	platform_device_del(&ts78xx_ts_rng_device);
+}
+
+/*****************************************************************************
  * FPGA 'hotplug' support code
  ****************************************************************************/
 static void ts78xx_fpga_devices_zero_init(void)
 {
 	ts78xx_fpga.supports.ts_rtc.init = 0;
 	ts78xx_fpga.supports.ts_nand.init = 0;
+	ts78xx_fpga.supports.ts_rng.init = 0;
 }
 
 static void ts78xx_fpga_supports(void)
@@ -289,10 +335,12 @@
 	case TS7800_REV_5:
 		ts78xx_fpga.supports.ts_rtc.present = 1;
 		ts78xx_fpga.supports.ts_nand.present = 1;
+		ts78xx_fpga.supports.ts_rng.present = 1;
 		break;
 	default:
 		ts78xx_fpga.supports.ts_rtc.present = 0;
 		ts78xx_fpga.supports.ts_nand.present = 0;
+		ts78xx_fpga.supports.ts_rng.present = 0;
 	}
 }
 
@@ -316,6 +364,14 @@
 		}
 		ret |= tmp;
 	}
+	if (ts78xx_fpga.supports.ts_rng.present == 1) {
+		tmp = ts78xx_ts_rng_load();
+		if (tmp) {
+			printk(KERN_INFO "TS-78xx: RNG not registered\n");
+			ts78xx_fpga.supports.ts_rng.present = 0;
+		}
+		ret |= tmp;
+	}
 
 	return ret;
 }
@@ -328,6 +384,8 @@
 		ts78xx_ts_rtc_unload();
 	if (ts78xx_fpga.supports.ts_nand.present == 1)
 		ts78xx_ts_nand_unload();
+	if (ts78xx_fpga.supports.ts_rng.present == 1)
+		ts78xx_ts_rng_unload();
 
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/wnr854t-setup.c linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/wnr854t-setup.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-orion5x/wnr854t-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-orion5x/wnr854t-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/ethtool.h>
+#include <net/dsa.h>
 #include <asm/mach-types.h>
 #include <asm/gpio.h>
 #include <asm/mach/arch.h>
@@ -97,6 +98,20 @@
 	.duplex		= DUPLEX_FULL,
 };
 
+static struct dsa_chip_data wnr854t_switch_chip_data = {
+	.port_names[0] = "lan3",
+	.port_names[1] = "lan4",
+	.port_names[2] = "wan",
+	.port_names[3] = "cpu",
+	.port_names[5] = "lan1",
+	.port_names[7] = "lan2",
+};
+
+static struct dsa_platform_data wnr854t_switch_plat_data = {
+	.nr_chips	= 1,
+	.chip		= &wnr854t_switch_chip_data,
+};
+
 static void __init wnr854t_init(void)
 {
 	/*
@@ -110,6 +125,7 @@
 	 * Configure peripherals.
 	 */
 	orion5x_eth_init(&wnr854t_eth_data);
+	orion5x_eth_switch_init(&wnr854t_switch_plat_data, NO_IRQ);
 	orion5x_uart0_init();
 
 	orion5x_setup_dev_boot_win(WNR854T_NOR_BOOT_BASE,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,20 +86,3 @@
 	for (i = 0; i < num; i++)
 		clkdev_add(&clks[i]);
 }
-
-int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
-	struct device *dev)
-{
-	struct clk *r = clk_get(dev, id);
-	struct clk_lookup *l;
-
-	if (!r)
-		return -ENODEV;
-
-	l = clkdev_alloc(r, alias, alias_dev_name);
-	clk_put(r);
-	if (!l)
-		return -ENODEV;
-	clkdev_add(l);
-	return 0;
-}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/cm-x270.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/cm-x270.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/cm-x270.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/cm-x270.c	2009-09-09 18:13:59.000000000 -0400
@@ -335,6 +335,10 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config));
 
+#ifdef CONFIG_PM
+	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+#endif
+
 	cmx270_init_rtc();
 	cmx270_init_mmc();
 	cmx270_init_ohci();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/cm-x300.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/cm-x300.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/cm-x300.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/cm-x300.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,18 +21,20 @@
 #include <linux/gpio.h>
 #include <linux/dm9000.h>
 #include <linux/leds.h>
+#include <linux/rtc-v3020.h>
 
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/setup.h>
 
 #include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/pxa3xx_nand.h>
 
 #include <asm/mach/map.h>
@@ -46,6 +48,11 @@
 
 #define	CM_X300_MMC2_IRQ	IRQ_GPIO(GPIO82_MMC2_IRQ)
 
+#define GPIO95_RTC_CS		(95)
+#define GPIO96_RTC_WR		(96)
+#define GPIO97_RTC_RD		(97)
+#define GPIO98_RTC_IO		(98)
+
 static mfp_cfg_t cm_x300_mfp_cfg[] __initdata = {
 	/* LCD */
 	GPIO54_LCD_LDD_0,
@@ -135,6 +142,12 @@
 	GPIO85_GPIO,			/* MMC WP */
 	GPIO99_GPIO,			/* Ethernet IRQ */
 
+	/* RTC GPIOs */
+	GPIO95_GPIO,			/* RTC CS */
+	GPIO96_GPIO,			/* RTC WR */
+	GPIO97_GPIO,			/* RTC RD */
+	GPIO98_GPIO,			/* RTC IO */
+
 	/* Standard I2C */
 	GPIO21_I2C_SCL,
 	GPIO22_I2C_SDA,
@@ -265,6 +278,7 @@
 
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 	.enable_arbiter	= 1,
+	.keep_config	= 1,
 	.parts		= cm_x300_nand_partitions,
 	.nr_parts	= ARRAY_SIZE(cm_x300_nand_partitions),
 };
@@ -441,6 +455,31 @@
 static inline void cm_x300_init_i2c(void) {}
 #endif
 
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
+struct v3020_platform_data cm_x300_v3020_pdata = {
+	.use_gpio	= 1,
+	.gpio_cs	= GPIO95_RTC_CS,
+	.gpio_wr	= GPIO96_RTC_WR,
+	.gpio_rd	= GPIO97_RTC_RD,
+	.gpio_io	= GPIO98_RTC_IO,
+};
+
+static struct platform_device cm_x300_rtc_device = {
+	.name		= "v3020",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &cm_x300_v3020_pdata,
+	}
+};
+
+static void __init cm_x300_init_rtc(void)
+{
+	platform_device_register(&cm_x300_rtc_device);
+}
+#else
+static inline void cm_x300_init_rtc(void) {}
+#endif
+
 static void __init cm_x300_init(void)
 {
 	/* board-processor specific GPIO initialization */
@@ -453,6 +492,19 @@
 	cm_x300_init_nand();
 	cm_x300_init_leds();
 	cm_x300_init_i2c();
+	cm_x300_init_rtc();
+}
+
+static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
+				 char **cmdline, struct meminfo *mi)
+{
+	mi->nr_banks = 2;
+	mi->bank[0].start = 0xa0000000;
+	mi->bank[0].node = 0;
+	mi->bank[0].size = (64*1024*1024);
+	mi->bank[1].start = 0xc0000000;
+	mi->bank[1].node = 0;
+	mi->bank[1].size = (64*1024*1024);
 }
 
 MACHINE_START(CM_X300, "CM-X300 module")
@@ -463,4 +515,5 @@
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= cm_x300_init,
+	.fixup		= cm_x300_fixup,
 MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/corgi.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/corgi.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/corgi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/corgi.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/pm.h>
 #include <linux/gpio.h>
 #include <linux/backlight.h>
+#include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -42,7 +43,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/pxa25x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
@@ -445,13 +446,8 @@
 	.wait_for_sync		= corgi_wait_for_hsync,
 };
 
-static void corgi_ads7846_cs(u32 command)
-{
-	gpio_set_value(CORGI_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip corgi_ads7846_chip = {
-	.cs_control	= corgi_ads7846_cs,
+	.gpio_cs	= CORGI_GPIO_ADS7846_CS,
 };
 
 static void corgi_bl_kick_battery(void)
@@ -475,22 +471,12 @@
 	.kick_battery		= corgi_bl_kick_battery,
 };
 
-static void corgi_lcdcon_cs(u32 command)
-{
-	gpio_set_value(CORGI_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip corgi_lcdcon_chip = {
-	.cs_control	= corgi_lcdcon_cs,
+	.gpio_cs	= CORGI_GPIO_LCDCON_CS,
 };
 
-static void corgi_max1111_cs(u32 command)
-{
-	gpio_set_value(CORGI_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip corgi_max1111_chip = {
-	.cs_control	= corgi_max1111_cs,
+	.gpio_cs	= CORGI_GPIO_MAX1111_CS,
 };
 
 static struct spi_board_info corgi_spi_devices[] = {
@@ -520,32 +506,8 @@
 
 static void __init corgi_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(CORGI_GPIO_ADS7846_CS, "ADS7846_CS");
-	if (err)
-		return;
-
-	err = gpio_request(CORGI_GPIO_LCDCON_CS, "LCDCON_CS");
-	if (err)
-		goto err_free_1;
-
-	err = gpio_request(CORGI_GPIO_MAX1111_CS, "MAX1111_CS");
-	if (err)
-		goto err_free_2;
-
-	gpio_direction_output(CORGI_GPIO_ADS7846_CS, 1);
-	gpio_direction_output(CORGI_GPIO_LCDCON_CS, 1);
-	gpio_direction_output(CORGI_GPIO_MAX1111_CS, 1);
-
 	pxa2xx_set_spi_info(1, &corgi_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(corgi_spi_devices));
-	return;
-
-err_free_2:
-	gpio_free(CORGI_GPIO_LCDCON_CS);
-err_free_1:
-	gpio_free(CORGI_GPIO_ADS7846_CS);
 }
 #else
 static inline void corgi_init_spi(void) {}
@@ -639,6 +601,10 @@
 	&sharpsl_rom_device,
 };
 
+static struct i2c_board_info __initdata corgi_i2c_devices[] = {
+	{ I2C_BOARD_INFO("wm8731", 0x1b) },
+};
+
 static void corgi_poweroff(void)
 {
 	if (!machine_is_corgi())
@@ -673,6 +639,7 @@
 	pxa_set_mci_info(&corgi_mci_platform_data);
 	pxa_set_ficp_info(&corgi_ficp_platform_data);
 	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(corgi_i2c_devices));
 
 	platform_scoop_config = &corgi_pcmcia_config;
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/corgi_pm.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/corgi_pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/corgi_pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/corgi_pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,6 @@
 	pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT);
 	pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT);
 	pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN);
-	sharpsl_pm_pxa_init();
 }
 
 static void corgi_measure_temp(int on)
@@ -191,7 +190,7 @@
 
 static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
 	.init            = corgi_charger_init,
-	.exit            = sharpsl_pm_pxa_remove,
+	.exit            = NULL,
 	.gpio_batlock    = CORGI_GPIO_BAT_COVER,
 	.gpio_acin       = CORGI_GPIO_AC_IN,
 	.gpio_batfull    = CORGI_GPIO_CHRG_FULL,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/cpufreq-pxa2xx.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/cpufreq-pxa2xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/cpufreq-pxa2xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/cpufreq-pxa2xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,8 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/pxa2xx-regs.h>
 
@@ -47,6 +49,8 @@
 #define freq_debug  0
 #endif
 
+static struct regulator *vcc_core;
+
 static unsigned int pxa27x_maxfreq;
 module_param(pxa27x_maxfreq, uint, 0);
 MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz"
@@ -58,6 +62,8 @@
 	unsigned int cccr;
 	unsigned int div2;
 	unsigned int cclkcfg;
+	int vmin;
+	int vmax;
 } pxa_freqs_t;
 
 /* Define the refresh period in mSec for the SDRAM and the number of rows */
@@ -82,24 +88,24 @@
 
 static pxa_freqs_t pxa255_run_freqs[] =
 {
-	/* CPU   MEMBUS  CCCR  DIV2 CCLKCFG	   run  turbo PXbus SDRAM */
-	{ 99500,  99500, 0x121, 1,  CCLKCFG},	/*  99,   99,   50,   50  */
-	{132700, 132700, 0x123, 1,  CCLKCFG},	/* 133,  133,   66,   66  */
-	{199100,  99500, 0x141, 0,  CCLKCFG},	/* 199,  199,   99,   99  */
-	{265400, 132700, 0x143, 1,  CCLKCFG},	/* 265,  265,  133,   66  */
-	{331800, 165900, 0x145, 1,  CCLKCFG},	/* 331,  331,  166,   83  */
-	{398100,  99500, 0x161, 0,  CCLKCFG},	/* 398,  398,  196,   99  */
+	/* CPU   MEMBUS  CCCR  DIV2 CCLKCFG	           run  turbo PXbus SDRAM */
+	{ 99500,  99500, 0x121, 1,  CCLKCFG, -1, -1},	/*  99,   99,   50,   50  */
+	{132700, 132700, 0x123, 1,  CCLKCFG, -1, -1},	/* 133,  133,   66,   66  */
+	{199100,  99500, 0x141, 0,  CCLKCFG, -1, -1},	/* 199,  199,   99,   99  */
+	{265400, 132700, 0x143, 1,  CCLKCFG, -1, -1},	/* 265,  265,  133,   66  */
+	{331800, 165900, 0x145, 1,  CCLKCFG, -1, -1},	/* 331,  331,  166,   83  */
+	{398100,  99500, 0x161, 0,  CCLKCFG, -1, -1},	/* 398,  398,  196,   99  */
 };
 
 /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
 static pxa_freqs_t pxa255_turbo_freqs[] =
 {
 	/* CPU   MEMBUS  CCCR  DIV2 CCLKCFG	   run  turbo PXbus SDRAM */
-	{ 99500, 99500,  0x121, 1,  CCLKCFG},	/*  99,   99,   50,   50  */
-	{199100, 99500,  0x221, 0,  CCLKCFG},	/*  99,  199,   50,   99  */
-	{298500, 99500,  0x321, 0,  CCLKCFG},	/*  99,  287,   50,   99  */
-	{298600, 99500,  0x1c1, 0,  CCLKCFG},	/* 199,  287,   99,   99  */
-	{398100, 99500,  0x241, 0,  CCLKCFG},	/* 199,  398,   99,   99  */
+	{ 99500, 99500,  0x121, 1,  CCLKCFG, -1, -1},	/*  99,   99,   50,   50  */
+	{199100, 99500,  0x221, 0,  CCLKCFG, -1, -1},	/*  99,  199,   50,   99  */
+	{298500, 99500,  0x321, 0,  CCLKCFG, -1, -1},	/*  99,  287,   50,   99  */
+	{298600, 99500,  0x1c1, 0,  CCLKCFG, -1, -1},	/* 199,  287,   99,   99  */
+	{398100, 99500,  0x241, 0,  CCLKCFG, -1, -1},	/* 199,  398,   99,   99  */
 };
 
 #define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs)
@@ -148,13 +154,13 @@
    ((T)  ? CCLKCFG_TURBO : 0))
 
 static pxa_freqs_t pxa27x_freqs[] = {
-	{104000, 104000, PXA27x_CCCR(1,	 8, 2), 0, CCLKCFG2(1, 0, 1)},
-	{156000, 104000, PXA27x_CCCR(1,	 8, 6), 0, CCLKCFG2(1, 1, 1)},
-	{208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1)},
-	{312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1)},
-	{416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1)},
-	{520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1)},
-	{624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1)}
+	{104000, 104000, PXA27x_CCCR(1,	 8, 2), 0, CCLKCFG2(1, 0, 1),  900000, 1705000 },
+	{156000, 104000, PXA27x_CCCR(1,	 8, 6), 0, CCLKCFG2(1, 1, 1), 1000000, 1705000 },
+	{208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 },
+	{312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 },
+	{416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 },
+	{520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1), 1450000, 1705000 },
+	{624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1), 1550000, 1705000 }
 };
 
 #define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs)
@@ -163,6 +169,47 @@
 
 extern unsigned get_clk_frequency_khz(int info);
 
+#ifdef CONFIG_REGULATOR
+
+static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq)
+{
+	int ret = 0;
+	int vmin, vmax;
+
+	if (!cpu_is_pxa27x())
+		return 0;
+
+	vmin = pxa_freq->vmin;
+	vmax = pxa_freq->vmax;
+	if ((vmin == -1) || (vmax == -1))
+		return 0;
+
+	ret = regulator_set_voltage(vcc_core, vmin, vmax);
+	if (ret)
+		pr_err("cpufreq: Failed to set vcc_core in [%dmV..%dmV]\n",
+		       vmin, vmax);
+	return ret;
+}
+
+static __init void pxa_cpufreq_init_voltages(void)
+{
+	vcc_core = regulator_get(NULL, "vcc_core");
+	if (IS_ERR(vcc_core)) {
+		pr_info("cpufreq: Didn't find vcc_core regulator\n");
+		vcc_core = NULL;
+	} else {
+		pr_info("cpufreq: Found vcc_core regulator\n");
+	}
+}
+#else
+static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq)
+{
+	return 0;
+}
+
+static __init void pxa_cpufreq_init_voltages(void) { }
+#endif
+
 static void find_freq_tables(struct cpufreq_frequency_table **freq_table,
 			     pxa_freqs_t **pxa_freqs)
 {
@@ -251,6 +298,7 @@
 	unsigned long flags;
 	unsigned int new_freq_cpu, new_freq_mem;
 	unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg;
+	int ret = 0;
 
 	/* Get the current policy */
 	find_freq_tables(&pxa_freqs_table, &pxa_freq_settings);
@@ -273,6 +321,10 @@
 			 freqs.new / 1000, (pxa_freq_settings[idx].div2) ?
 			 (new_freq_mem / 2000) : (new_freq_mem / 1000));
 
+	if (vcc_core && freqs.new > freqs.old)
+		ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
+	if (ret)
+		return ret;
 	/*
 	 * Tell everyone what we're about to do...
 	 * you should add a notify client with any platform specific
@@ -335,6 +387,18 @@
 	 */
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
+	/*
+	 * Even if voltage setting fails, we don't report it, as the frequency
+	 * change succeeded. The voltage reduction is not a critical failure,
+	 * only power savings will suffer from this.
+	 *
+	 * Note: if the voltage change fails, and a return value is returned, a
+	 * bug is triggered (seems a deadlock). Should anybody find out where,
+	 * the "return 0" should become a "return ret".
+	 */
+	if (vcc_core && freqs.new < freqs.old)
+		ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
+
 	return 0;
 }
 
@@ -349,6 +413,8 @@
 	if (cpu_is_pxa27x())
 		pxa27x_guess_max_freq();
 
+	pxa_cpufreq_init_voltages();
+
 	init_sdram_rows();
 
 	/* set default policy and cpuinfo */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/csb726.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/csb726.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/csb726.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/csb726.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,15 +16,17 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
 #include <linux/sm501.h>
+#include <linux/smsc911x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/csb726.h>
 #include <mach/mfp-pxa27x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
+#include <mach/audio.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -275,15 +277,26 @@
 	{
 		.start	= CSB726_IRQ_LAN,
 		.end	= CSB726_IRQ_LAN,
-		.flags	= IORESOURCE_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
+struct smsc911x_platform_config csb726_lan_config = {
+	.irq_type	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_32BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+
 static struct platform_device csb726_lan = {
-	.name		= "smc911x",
+	.name		= "smsc911x",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(csb726_lan_resources),
 	.resource	= csb726_lan_resources,
+	.dev		= {
+		.platform_data	= &csb726_lan_config,
+	},
 };
 
 static struct platform_device *devices[] __initdata = {
@@ -303,6 +316,7 @@
 	pxa27x_set_i2c_power_info(NULL);
 	pxa_set_mci_info(&csb726_mci);
 	pxa_set_ohci_info(&csb726_ohci_platform_data);
+	pxa_set_ac97_info(NULL);
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/devices.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/devices.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/devices.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/devices.c	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/ohci.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/pxa2xx_spi.h>
@@ -290,7 +290,7 @@
 };
 
 struct platform_device pxa3xx_device_i2c_power = {
-	.name		= "pxa2xx-i2c",
+	.name		= "pxa3xx-pwri2c",
 	.id		= 1,
 	.resource	= pxa3xx_resources_i2c_power,
 	.num_resources	= ARRAY_SIZE(pxa3xx_resources_i2c_power),
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/em-x270.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/em-x270.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/em-x270.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/em-x270.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,9 @@
 #include <linux/spi/libertas_spi.h>
 #include <linux/power_supply.h>
 #include <linux/apm-emulation.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/regulator/userspace-consumer.h>
 
 #include <media/soc_camera.h>
 
@@ -41,7 +44,7 @@
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <mach/pxa27x_keypad.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/pxa2xx_spi.h>
 
@@ -52,23 +55,31 @@
 #define GPIO13_MMC_CD		(13)
 #define GPIO95_MMC_WP		(95)
 #define GPIO56_NAND_RB		(56)
+#define GPIO93_CAM_RESET	(93)
+#define GPIO16_USB_HUB_RESET	(16)
 
 /* eXeda specific GPIOs */
 #define GPIO114_MMC_CD		(114)
 #define GPIO20_NAND_RB		(20)
 #define GPIO38_SD_PWEN		(38)
+#define GPIO37_WLAN_RST		(37)
+#define GPIO95_TOUCHPAD_INT	(95)
+#define GPIO130_CAM_RESET	(130)
+#define GPIO10_USB_HUB_RESET	(10)
 
 /* common  GPIOs */
 #define GPIO11_NAND_CS		(11)
-#define GPIO93_CAM_RESET	(93)
 #define GPIO41_ETHIRQ		(41)
 #define EM_X270_ETHIRQ		IRQ_GPIO(GPIO41_ETHIRQ)
 #define GPIO115_WLAN_PWEN	(115)
 #define GPIO19_WLAN_STRAP	(19)
+#define GPIO9_USB_VBUS_EN	(9)
 
 static int mmc_cd;
 static int nand_rb;
 static int dm9000_flags;
+static int cam_reset;
+static int usb_hub_reset;
 
 static unsigned long common_pin_config[] = {
 	/* AC'97 */
@@ -180,7 +191,6 @@
 
 	/* power controls */
 	GPIO20_GPIO	| MFP_LPM_DRIVE_LOW,	/* GPRS_PWEN */
-	GPIO93_GPIO	| MFP_LPM_DRIVE_LOW,	/* Camera reset */
 	GPIO115_GPIO	| MFP_LPM_DRIVE_LOW,	/* WLAN_PWEN */
 
 	/* NAND controls */
@@ -191,14 +201,18 @@
 };
 
 static unsigned long em_x270_pin_config[] = {
-	GPIO13_GPIO,	/* MMC card detect */
-	GPIO56_GPIO,	/* NAND Ready/Busy */
-	GPIO95_GPIO,	/* MMC Write protect */
+	GPIO13_GPIO,				/* MMC card detect */
+	GPIO16_GPIO,				/* USB hub reset */
+	GPIO56_GPIO,				/* NAND Ready/Busy */
+	GPIO93_GPIO	| MFP_LPM_DRIVE_LOW,	/* Camera reset */
+	GPIO95_GPIO,				/* MMC Write protect */
 };
 
 static unsigned long exeda_pin_config[] = {
+	GPIO10_GPIO,				/* USB hub reset */
 	GPIO20_GPIO,				/* NAND Ready/Busy */
 	GPIO38_GPIO	| MFP_LPM_DRIVE_LOW,	/* SD slot power */
+	GPIO95_GPIO,				/* touchpad IRQ */
 	GPIO114_GPIO,				/* MMC card detect */
 };
 
@@ -464,18 +478,79 @@
 
 /* PXA27x OHCI controller setup */
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static struct regulator *em_x270_usb_ldo;
+
+static int em_x270_usb_hub_init(void)
+{
+	int err;
+
+	em_x270_usb_ldo = regulator_get(NULL, "vcc usb");
+	if (IS_ERR(em_x270_usb_ldo))
+		return PTR_ERR(em_x270_usb_ldo);
+
+	err = gpio_request(GPIO9_USB_VBUS_EN, "vbus en");
+	if (err)
+		goto err_free_usb_ldo;
+
+	err = gpio_request(usb_hub_reset, "hub rst");
+	if (err)
+		goto err_free_vbus_gpio;
+
+	/* USB Hub power-on and reset */
+	gpio_direction_output(usb_hub_reset, 0);
+	regulator_enable(em_x270_usb_ldo);
+	gpio_set_value(usb_hub_reset, 1);
+	gpio_set_value(usb_hub_reset, 0);
+	regulator_disable(em_x270_usb_ldo);
+	regulator_enable(em_x270_usb_ldo);
+	gpio_set_value(usb_hub_reset, 1);
+
+	/* enable VBUS */
+	gpio_direction_output(GPIO9_USB_VBUS_EN, 1);
+
+	return 0;
+
+err_free_vbus_gpio:
+	gpio_free(GPIO9_USB_VBUS_EN);
+err_free_usb_ldo:
+	regulator_put(em_x270_usb_ldo);
+
+	return err;
+}
+
 static int em_x270_ohci_init(struct device *dev)
 {
+	int err;
+
+	/* we don't want to entirely disable USB if the HUB init failed */
+	err = em_x270_usb_hub_init();
+	if (err)
+		pr_err("USB Hub initialization failed: %d\n", err);
+
 	/* enable port 2 transiever */
 	UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
 
 	return 0;
 }
 
+static void em_x270_ohci_exit(struct device *dev)
+{
+	gpio_free(usb_hub_reset);
+	gpio_free(GPIO9_USB_VBUS_EN);
+
+	if (!IS_ERR(em_x270_usb_ldo)) {
+		if (regulator_is_enabled(em_x270_usb_ldo))
+			regulator_disable(em_x270_usb_ldo);
+
+		regulator_put(em_x270_usb_ldo);
+	}
+}
+
 static struct pxaohci_platform_data em_x270_ohci_platform_data = {
 	.port_mode	= PMM_PERPORT_MODE,
 	.flags		= ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
 	.init		= em_x270_ohci_init,
+	.exit		= em_x270_ohci_exit,
 };
 
 static void __init em_x270_init_ohci(void)
@@ -661,6 +736,7 @@
 	.rx_threshold	= 1,
 	.tx_threshold	= 1,
 	.timeout	= 1000,
+	.gpio_cs	= 14,
 };
 
 static unsigned long em_x270_libertas_pin_config[] = {
@@ -677,33 +753,58 @@
 	if (err)
 		return err;
 
+	err = gpio_request(GPIO19_WLAN_STRAP, "WLAN STRAP");
+	if (err)
+		goto err_free_pwen;
+
+	if (machine_is_exeda()) {
+		err = gpio_request(GPIO37_WLAN_RST, "WLAN RST");
+		if (err)
+			goto err_free_strap;
+
+		gpio_direction_output(GPIO37_WLAN_RST, 1);
+		msleep(100);
+	}
+
 	gpio_direction_output(GPIO19_WLAN_STRAP, 1);
-	mdelay(100);
+	msleep(100);
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_libertas_pin_config));
 
 	gpio_direction_output(GPIO115_WLAN_PWEN, 0);
-	mdelay(100);
+	msleep(100);
 	gpio_set_value(GPIO115_WLAN_PWEN, 1);
-	mdelay(100);
+	msleep(100);
 
 	spi->bits_per_word = 16;
 	spi_setup(spi);
 
 	return 0;
+
+err_free_strap:
+	gpio_free(GPIO19_WLAN_STRAP);
+err_free_pwen:
+	gpio_free(GPIO115_WLAN_PWEN);
+
+	return err;
 }
 
 static int em_x270_libertas_teardown(struct spi_device *spi)
 {
 	gpio_set_value(GPIO115_WLAN_PWEN, 0);
 	gpio_free(GPIO115_WLAN_PWEN);
+	gpio_free(GPIO19_WLAN_STRAP);
+
+	if (machine_is_exeda()) {
+		gpio_set_value(GPIO37_WLAN_RST, 0);
+		gpio_free(GPIO37_WLAN_RST);
+	}
 
 	return 0;
 }
 
 struct libertas_spi_platform_data em_x270_libertas_pdata = {
 	.use_dummy_writes	= 1,
-	.gpio_cs		= 14,
 	.setup			= em_x270_libertas_setup,
 	.teardown		= em_x270_libertas_teardown,
 };
@@ -738,10 +839,14 @@
 static inline void em_x270_init_spi(void) {}
 #endif
 
-#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
+#if defined(CONFIG_SND_PXA2XX_LIB_AC97)
+static pxa2xx_audio_ops_t em_x270_ac97_info = {
+	.reset_gpio = 113,
+};
+
 static void __init em_x270_init_ac97(void)
 {
-	pxa_set_ac97_info(NULL);
+	pxa_set_ac97_info(&em_x270_ac97_info);
 }
 #else
 static inline void em_x270_init_ac97(void) {}
@@ -863,26 +968,26 @@
 {
 	int ret;
 
-	ret = gpio_request(GPIO93_CAM_RESET, "camera reset");
+	ret = gpio_request(cam_reset, "camera reset");
 	if (ret)
 		return ret;
 
-	gpio_direction_output(GPIO93_CAM_RESET, 0);
+	gpio_direction_output(cam_reset, 0);
 
 	em_x270_camera_ldo = regulator_get(NULL, "vcc cam");
 	if (em_x270_camera_ldo == NULL) {
-		gpio_free(GPIO93_CAM_RESET);
+		gpio_free(cam_reset);
 		return -ENODEV;
 	}
 
 	ret = regulator_enable(em_x270_camera_ldo);
 	if (ret) {
 		regulator_put(em_x270_camera_ldo);
-		gpio_free(GPIO93_CAM_RESET);
+		gpio_free(cam_reset);
 		return ret;
 	}
 
-	gpio_set_value(GPIO93_CAM_RESET, 1);
+	gpio_set_value(cam_reset, 1);
 
 	return 0;
 }
@@ -902,7 +1007,7 @@
 	if (on == is_on)
 		return 0;
 
-	gpio_set_value(GPIO93_CAM_RESET, !on);
+	gpio_set_value(cam_reset, !on);
 
 	if (on)
 		ret = regulator_enable(em_x270_camera_ldo);
@@ -912,7 +1017,7 @@
 	if (ret)
 		return ret;
 
-	gpio_set_value(GPIO93_CAM_RESET, on);
+	gpio_set_value(cam_reset, on);
 
 	return 0;
 }
@@ -929,13 +1034,8 @@
 	},
 };
 
-static struct i2c_pxa_platform_data em_x270_i2c_info = {
-	.fast_mode = 1,
-};
-
 static void  __init em_x270_init_camera(void)
 {
-	pxa_set_i2c_info(&em_x270_i2c_info);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
 	pxa_set_camera_info(&em_x270_camera_platform_data);
 }
@@ -943,6 +1043,52 @@
 static inline void em_x270_init_camera(void) {}
 #endif
 
+static struct regulator_bulk_data em_x270_gps_consumer_supply = {
+	.supply		= "vcc gps",
+};
+
+static struct regulator_userspace_consumer_data em_x270_gps_consumer_data = {
+	.name		= "vcc gps",
+	.num_supplies	= 1,
+	.supplies	= &em_x270_gps_consumer_supply,
+};
+
+static struct platform_device em_x270_gps_userspace_consumer = {
+	.name		= "reg-userspace-consumer",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &em_x270_gps_consumer_data,
+	},
+};
+
+static struct regulator_bulk_data em_x270_gprs_consumer_supply = {
+	.supply		= "vcc gprs",
+};
+
+static struct regulator_userspace_consumer_data em_x270_gprs_consumer_data = {
+	.name		= "vcc gprs",
+	.num_supplies	= 1,
+	.supplies	= &em_x270_gprs_consumer_supply
+};
+
+static struct platform_device em_x270_gprs_userspace_consumer = {
+	.name		= "reg-userspace-consumer",
+	.id		= 1,
+	.dev		= {
+		.platform_data = &em_x270_gprs_consumer_data,
+	}
+};
+
+static struct platform_device *em_x270_userspace_consumers[] = {
+	&em_x270_gps_userspace_consumer,
+	&em_x270_gprs_userspace_consumer,
+};
+
+static void __init em_x270_userspace_consumers_init(void)
+{
+	platform_add_devices(ARRAY_AND_SIZE(em_x270_userspace_consumers));
+}
+
 /* DA9030 related initializations */
 #define REGULATOR_CONSUMER(_name, _dev, _supply)			       \
 	static struct regulator_consumer_supply _name##_consumers[] = {	\
@@ -952,11 +1098,11 @@
 		},							\
 	}
 
-REGULATOR_CONSUMER(ldo3, NULL, "vcc gps");
+REGULATOR_CONSUMER(ldo3, &em_x270_gps_userspace_consumer.dev, "vcc gps");
 REGULATOR_CONSUMER(ldo5, NULL, "vcc cam");
 REGULATOR_CONSUMER(ldo10, &pxa_device_mci.dev, "vcc sdio");
 REGULATOR_CONSUMER(ldo12, NULL, "vcc usb");
-REGULATOR_CONSUMER(ldo19, NULL, "vcc gprs");
+REGULATOR_CONSUMER(ldo19, &em_x270_gprs_userspace_consumer.dev, "vcc gprs");
 
 #define REGULATOR_INIT(_ldo, _min_uV, _max_uV, _ops_mask)		\
 	static struct regulator_init_data _ldo##_data = {		\
@@ -967,6 +1113,7 @@
 				.enabled = 0,				\
 			},						\
 			.valid_ops_mask = _ops_mask,			\
+			.apply_uV = 1,					\
 		},							\
 		.num_consumer_supplies = ARRAY_SIZE(_ldo##_consumers),	\
 		.consumer_supplies = _ldo##_consumers,			\
@@ -985,7 +1132,7 @@
 };
 
 struct power_supply_info em_x270_psy_info = {
-	.name = "LP555597P6H-FPS",
+	.name = "battery",
 	.technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
 	.voltage_max_design = 4200000,
 	.voltage_min_design = 3000000,
@@ -994,12 +1141,16 @@
 
 static void em_x270_battery_low(void)
 {
+#if defined(CONFIG_APM_EMULATION)
 	apm_queue_event(APM_LOW_BATTERY);
+#endif
 }
 
 static void em_x270_battery_critical(void)
 {
+#if defined(CONFIG_APM_EMULATION)
 	apm_queue_event(APM_CRITICAL_SUSPEND);
+#endif
 }
 
 struct da9030_battery_info em_x270_batterty_info = {
@@ -1069,6 +1220,29 @@
 	i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1);
 }
 
+static struct pca953x_platform_data exeda_gpio_ext_pdata = {
+	.gpio_base = 128,
+};
+
+static struct i2c_board_info exeda_i2c_info[] = {
+	{
+		I2C_BOARD_INFO("pca9555", 0x21),
+		.platform_data = &exeda_gpio_ext_pdata,
+	},
+};
+
+static struct i2c_pxa_platform_data em_x270_i2c_info = {
+	.fast_mode = 1,
+};
+
+static void __init em_x270_init_i2c(void)
+{
+	pxa_set_i2c_info(&em_x270_i2c_info);
+
+	if (machine_is_exeda())
+		i2c_register_board_info(0, ARRAY_AND_SIZE(exeda_i2c_info));
+}
+
 static void __init em_x270_module_init(void)
 {
 	pr_info("%s\n", __func__);
@@ -1077,6 +1251,8 @@
 	mmc_cd = GPIO13_MMC_CD;
 	nand_rb = GPIO56_NAND_RB;
 	dm9000_flags = DM9000_PLATF_32BITONLY;
+	cam_reset = GPIO93_CAM_RESET;
+	usb_hub_reset = GPIO16_USB_HUB_RESET;
 }
 
 static void __init em_x270_exeda_init(void)
@@ -1087,12 +1263,18 @@
 	mmc_cd = GPIO114_MMC_CD;
 	nand_rb = GPIO20_NAND_RB;
 	dm9000_flags = DM9000_PLATF_16BITONLY;
+	cam_reset = GPIO130_CAM_RESET;
+	usb_hub_reset = GPIO10_USB_HUB_RESET;
 }
 
 static void __init em_x270_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config));
 
+#ifdef CONFIG_PM
+	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+#endif
+
 	if (machine_is_em_x270())
 		em_x270_module_init();
 	else if (machine_is_exeda())
@@ -1111,8 +1293,10 @@
 	em_x270_init_keypad();
 	em_x270_init_gpio_keys();
 	em_x270_init_ac97();
-	em_x270_init_camera();
 	em_x270_init_spi();
+	em_x270_init_i2c();
+	em_x270_init_camera();
+	em_x270_userspace_consumers_init();
 }
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/ezx.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/ezx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/ezx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/ezx.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/pwm_backlight.h>
 #include <linux/input.h>
+#include <linux/gpio_keys.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -25,13 +26,19 @@
 #include <mach/pxa27x.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/hardware.h>
 #include <mach/pxa27x_keypad.h>
 
 #include "devices.h"
 #include "generic.h"
 
+#define GPIO12_A780_FLIP_LID 		12
+#define GPIO15_A1200_FLIP_LID 		15
+#define GPIO15_A910_FLIP_LID 		15
+#define GPIO12_E680_LOCK_SWITCH 	12
+#define GPIO15_E6_LOCK_SWITCH 		15
+
 static struct platform_pwm_backlight_data ezx_backlight_data = {
 	.pwm_id		= 0,
 	.max_brightness	= 1023,
@@ -88,7 +95,7 @@
 	.lcd_conn	= LCD_COLOR_TFT_18BPP,
 };
 
-static struct platform_device *devices[] __initdata = {
+static struct platform_device *ezx_devices[] __initdata = {
 	&ezx_backlight_device,
 };
 
@@ -651,6 +658,35 @@
 #endif /* CONFIG_MACH_EZX_E2 */
 
 #ifdef CONFIG_MACH_EZX_A780
+/* gpio_keys */
+static struct gpio_keys_button a780_buttons[] = {
+	[0] = {
+		.code       = SW_LID,
+		.gpio       = GPIO12_A780_FLIP_LID,
+		.active_low = 0,
+		.desc       = "A780 flip lid",
+		.type       = EV_SW,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data a780_gpio_keys_platform_data = {
+	.buttons  = a780_buttons,
+	.nbuttons = ARRAY_SIZE(a780_buttons),
+};
+
+static struct platform_device a780_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &a780_gpio_keys_platform_data,
+	},
+};
+
+static struct platform_device *a780_devices[] __initdata = {
+	&a780_gpio_keys,
+};
+
 static void __init a780_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -663,7 +699,8 @@
 
 	pxa_set_keypad_info(&a780_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(a780_devices));
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
@@ -678,10 +715,39 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_E680
+/* gpio_keys */
+static struct gpio_keys_button e680_buttons[] = {
+	[0] = {
+		.code       = KEY_SCREENLOCK,
+		.gpio       = GPIO12_E680_LOCK_SWITCH,
+		.active_low = 0,
+		.desc       = "E680 lock switch",
+		.type       = EV_KEY,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data e680_gpio_keys_platform_data = {
+	.buttons  = e680_buttons,
+	.nbuttons = ARRAY_SIZE(e680_buttons),
+};
+
+static struct platform_device e680_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &e680_gpio_keys_platform_data,
+	},
+};
+
 static struct i2c_board_info __initdata e680_i2c_board_info[] = {
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *e680_devices[] __initdata = {
+	&e680_gpio_keys,
+};
+
 static void __init e680_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -695,7 +761,8 @@
 
 	pxa_set_keypad_info(&e680_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(e680_devices));
 }
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
@@ -710,10 +777,39 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_A1200
+/* gpio_keys */
+static struct gpio_keys_button a1200_buttons[] = {
+	[0] = {
+		.code       = SW_LID,
+		.gpio       = GPIO15_A1200_FLIP_LID,
+		.active_low = 0,
+		.desc       = "A1200 flip lid",
+		.type       = EV_SW,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data a1200_gpio_keys_platform_data = {
+	.buttons  = a1200_buttons,
+	.nbuttons = ARRAY_SIZE(a1200_buttons),
+};
+
+static struct platform_device a1200_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &a1200_gpio_keys_platform_data,
+	},
+};
+
 static struct i2c_board_info __initdata a1200_i2c_board_info[] = {
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *a1200_devices[] __initdata = {
+	&a1200_gpio_keys,
+};
+
 static void __init a1200_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -727,7 +823,8 @@
 
 	pxa_set_keypad_info(&a1200_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(a1200_devices));
 }
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
@@ -742,6 +839,35 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_A910
+/* gpio_keys */
+static struct gpio_keys_button a910_buttons[] = {
+	[0] = {
+		.code       = SW_LID,
+		.gpio       = GPIO15_A910_FLIP_LID,
+		.active_low = 0,
+		.desc       = "A910 flip lid",
+		.type       = EV_SW,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data a910_gpio_keys_platform_data = {
+	.buttons  = a910_buttons,
+	.nbuttons = ARRAY_SIZE(a910_buttons),
+};
+
+static struct platform_device a910_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &a910_gpio_keys_platform_data,
+	},
+};
+
+static struct platform_device *a910_devices[] __initdata = {
+	&a910_gpio_keys,
+};
+
 static void __init a910_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -754,7 +880,8 @@
 
 	pxa_set_keypad_info(&a910_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(a910_devices));
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
@@ -769,10 +896,39 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_E6
+/* gpio_keys */
+static struct gpio_keys_button e6_buttons[] = {
+	[0] = {
+		.code       = KEY_SCREENLOCK,
+		.gpio       = GPIO15_E6_LOCK_SWITCH,
+		.active_low = 0,
+		.desc       = "E6 lock switch",
+		.type       = EV_KEY,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data e6_gpio_keys_platform_data = {
+	.buttons  = e6_buttons,
+	.nbuttons = ARRAY_SIZE(e6_buttons),
+};
+
+static struct platform_device e6_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &e6_gpio_keys_platform_data,
+	},
+};
+
 static struct i2c_board_info __initdata e6_i2c_board_info[] = {
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *e6_devices[] __initdata = {
+	&e6_gpio_keys,
+};
+
 static void __init e6_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -786,7 +942,8 @@
 
 	pxa_set_keypad_info(&e6_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(e6_devices));
 }
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
@@ -805,6 +962,9 @@
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *e2_devices[] __initdata = {
+};
+
 static void __init e2_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -818,7 +978,8 @@
 
 	pxa_set_keypad_info(&e2_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(e2_devices));
 }
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/hx4700.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/hx4700.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/hx4700.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/hx4700.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,892 @@
+/*
+ * Support for HP iPAQ hx4700 PDAs.
+ *
+ * Copyright (c) 2008-2009 Philipp Zabel
+ *
+ * Based on code:
+ *    Copyright (c) 2004 Hewlett-Packard Company.
+ *    Copyright (c) 2005 SDG Systems, LLC
+ *    Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/lcd.h>
+#include <linux/mfd/htc-egpio.h>
+#include <linux/mfd/asic3.h>
+#include <linux/mtd/physmap.h>
+#include <linux/pda_power.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/bq24022.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/max1586.h>
+#include <linux/spi/ads7846.h>
+#include <linux/spi/spi.h>
+#include <linux/usb/gpio_vbus.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa27x.h>
+#include <mach/hx4700.h>
+#include <plat/i2c.h>
+#include <mach/irda.h>
+#include <mach/pxa2xx_spi.h>
+
+#include <video/w100fb.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* Physical address space information */
+
+#define ATI_W3220_PHYS  PXA_CS2_PHYS /* ATI Imageon 3220 Graphics */
+#define ASIC3_PHYS      PXA_CS3_PHYS
+#define ASIC3_SD_PHYS   (PXA_CS3_PHYS + 0x02000000)
+
+static unsigned long hx4700_pin_config[] __initdata = {
+
+	/* SDRAM and Static Memory I/O Signals */
+	GPIO20_nSDCS_2,
+	GPIO21_nSDCS_3,
+	GPIO15_nCS_1,
+	GPIO78_nCS_2,   /* W3220 */
+	GPIO79_nCS_3,   /* ASIC3 */
+	GPIO80_nCS_4,
+	GPIO33_nCS_5,	/* EGPIO, WLAN */
+
+	/* PC CARD */
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO54_nPCE_2,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+	GPIO85_nPCE_1,
+	GPIO104_PSKTSEL,
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* FFUART (RS-232) */
+	GPIO34_FFUART_RXD,
+	GPIO35_FFUART_CTS,
+	GPIO36_FFUART_DCD,
+	GPIO37_FFUART_DSR,
+	GPIO38_FFUART_RI,
+	GPIO39_FFUART_TXD,
+	GPIO40_FFUART_DTR,
+	GPIO41_FFUART_RTS,
+
+	/* BTUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	/* PWM 1 (Backlight) */
+	GPIO17_PWM1_OUT,
+
+	/* I2S */
+	GPIO28_I2S_BITCLK_OUT,
+	GPIO29_I2S_SDATA_IN,
+	GPIO30_I2S_SDATA_OUT,
+	GPIO31_I2S_SYNC,
+	GPIO113_I2S_SYSCLK,
+
+	/* SSP 1 (NavPoint) */
+	GPIO23_SSP1_SCLK,
+	GPIO24_SSP1_SFRM,
+	GPIO25_SSP1_TXD,
+	GPIO26_SSP1_RXD,
+
+	/* SSP 2 (TSC2046) */
+	GPIO19_SSP2_SCLK,
+	GPIO86_SSP2_RXD,
+	GPIO87_SSP2_TXD,
+	GPIO88_GPIO,
+
+	/* HX4700 specific input GPIOs */
+	GPIO12_GPIO,	/* ASIC3_IRQ */
+	GPIO13_GPIO,	/* W3220_IRQ */
+	GPIO14_GPIO,	/* nWLAN_IRQ */
+
+	GPIO10_GPIO,	/* GSM_IRQ */
+	GPIO13_GPIO,	/* CPLD_IRQ */
+	GPIO107_GPIO,	/* DS1WM_IRQ */
+	GPIO108_GPIO,	/* GSM_READY */
+	GPIO58_GPIO,	/* TSC2046_nPENIRQ */
+	GPIO66_GPIO,	/* nSDIO_IRQ */
+};
+
+#define HX4700_GPIO_IN(num, _desc) \
+	{ .gpio = (num), .dir = 0, .desc = (_desc) }
+#define HX4700_GPIO_OUT(num, _init, _desc) \
+	{ .gpio = (num), .dir = 1, .init = (_init), .desc = (_desc) }
+struct gpio_ress {
+	unsigned gpio : 8;
+	unsigned dir : 1;
+	unsigned init : 1;
+	char *desc;
+};
+
+static int hx4700_gpio_request(struct gpio_ress *gpios, int size)
+{
+	int i, rc = 0;
+	int gpio;
+	int dir;
+
+	for (i = 0; (!rc) && (i < size); i++) {
+		gpio = gpios[i].gpio;
+		dir = gpios[i].dir;
+		rc = gpio_request(gpio, gpios[i].desc);
+		if (rc) {
+			pr_err("Error requesting GPIO %d(%s) : %d\n",
+			       gpio, gpios[i].desc, rc);
+			continue;
+		}
+		if (dir)
+			gpio_direction_output(gpio, gpios[i].init);
+		else
+			gpio_direction_input(gpio);
+	}
+	while ((rc) && (--i >= 0))
+		gpio_free(gpios[i].gpio);
+	return rc;
+}
+
+/*
+ * IRDA
+ */
+
+static void irda_transceiver_mode(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO105_HX4700_nIR_ON, mode & IR_OFF);
+}
+
+static struct pxaficp_platform_data ficp_info = {
+	.transceiver_cap  = IR_SIRMODE | IR_OFF,
+	.transceiver_mode = irda_transceiver_mode,
+};
+
+/*
+ * GPIO Keys
+ */
+
+#define INIT_KEY(_code, _gpio, _active_low, _desc)	\
+	{						\
+		.code       = KEY_##_code,		\
+		.gpio       = _gpio,			\
+		.active_low = _active_low,		\
+		.desc       = _desc,			\
+		.type       = EV_KEY,			\
+		.wakeup     = 1,			\
+	}
+
+static struct gpio_keys_button gpio_keys_buttons[] = {
+	INIT_KEY(POWER,       GPIO0_HX4700_nKEY_POWER,   1, "Power button"),
+	INIT_KEY(MAIL,        GPIO94_HX4700_KEY_MAIL,    0, "Mail button"),
+	INIT_KEY(ADDRESSBOOK, GPIO99_HX4700_KEY_CONTACTS,0, "Contacts button"),
+	INIT_KEY(RECORD,      GPIOD6_nKEY_RECORD,        1, "Record button"),
+	INIT_KEY(CALENDAR,    GPIOD1_nKEY_CALENDAR,      1, "Calendar button"),
+	INIT_KEY(HOMEPAGE,    GPIOD3_nKEY_HOME,          1, "Home button"),
+};
+
+static struct gpio_keys_platform_data gpio_keys_data = {
+	.buttons = gpio_keys_buttons,
+	.nbuttons = ARRAY_SIZE(gpio_keys_buttons),
+};
+
+static struct platform_device gpio_keys = {
+	.name = "gpio-keys",
+	.dev  = {
+		.platform_data = &gpio_keys_data,
+	},
+	.id   = -1,
+};
+
+/*
+ * ASIC3
+ */
+
+static u16 asic3_gpio_config[] = {
+	/* ASIC3 GPIO banks A and B along with some of C and D
+	   implement the buffering for the CF slot. */
+	ASIC3_CONFIG_GPIO(0, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(1, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(2, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(3, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(4, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(5, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(6, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(7, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(8, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(9, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(10, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(11, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(12, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(13, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(14, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(15, 1, 1, 0),
+
+	ASIC3_CONFIG_GPIO(16, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(17, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(18, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(19, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(20, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(21, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(22, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(23, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(24, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(25, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(26, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(27, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(28, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(29, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(30, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(31, 1, 1, 0),
+
+	/* GPIOC - CF, LEDs, SD */
+	ASIC3_GPIOC0_LED0,		/* red */
+	ASIC3_GPIOC1_LED1,		/* green */
+	ASIC3_GPIOC2_LED2,		/* blue */
+	ASIC3_GPIOC4_CF_nCD,
+	ASIC3_GPIOC5_nCIOW,
+	ASIC3_GPIOC6_nCIOR,
+	ASIC3_GPIOC7_nPCE_1,
+	ASIC3_GPIOC8_nPCE_2,
+	ASIC3_GPIOC9_nPOE,
+	ASIC3_GPIOC10_nPWE,
+	ASIC3_GPIOC11_PSKTSEL,
+	ASIC3_GPIOC12_nPREG,
+	ASIC3_GPIOC13_nPWAIT,
+	ASIC3_GPIOC14_nPIOIS16,
+	ASIC3_GPIOC15_nPIOR,
+
+	/* GPIOD: input GPIOs, CF */
+	ASIC3_GPIOD11_nCIOIS16,
+	ASIC3_GPIOD12_nCWAIT,
+	ASIC3_GPIOD15_nPIOW,
+};
+
+static struct resource asic3_resources[] = {
+	/* GPIO part */
+	[0] = {
+		.start	= ASIC3_PHYS,
+		.end	= ASIC3_PHYS + ASIC3_MAP_SIZE_16BIT - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ),
+		.end	= gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
+	/* SD part */
+	[2] = {
+		.start	= ASIC3_SD_PHYS,
+		.end	= ASIC3_SD_PHYS + ASIC3_MAP_SIZE_16BIT - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		.start	= gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ),
+		.end	= gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct asic3_platform_data asic3_platform_data = {
+	.gpio_config     = asic3_gpio_config,
+	.gpio_config_num = ARRAY_SIZE(asic3_gpio_config),
+	.irq_base        = IRQ_BOARD_START,
+	.gpio_base       = HX4700_ASIC3_GPIO_BASE,
+};
+
+static struct platform_device asic3 = {
+	.name          = "asic3",
+	.id            = -1,
+	.resource      = asic3_resources,
+	.num_resources = ARRAY_SIZE(asic3_resources),
+	.dev = {
+		.platform_data = &asic3_platform_data,
+	},
+};
+
+/*
+ * EGPIO
+ */
+
+static struct resource egpio_resources[] = {
+	[0] = {
+		.start = PXA_CS5_PHYS,
+		.end   = PXA_CS5_PHYS + 0x4 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct htc_egpio_chip egpio_chips[] = {
+	[0] = {
+		.reg_start = 0,
+		.gpio_base = HX4700_EGPIO_BASE,
+		.num_gpios = 8,
+		.direction = HTC_EGPIO_OUTPUT,
+	},
+};
+
+static struct htc_egpio_platform_data egpio_info = {
+	.reg_width = 16,
+	.bus_width = 16,
+	.chip      = egpio_chips,
+	.num_chips = ARRAY_SIZE(egpio_chips),
+};
+
+static struct platform_device egpio = {
+	.name          = "htc-egpio",
+	.id            = -1,
+	.resource      = egpio_resources,
+	.num_resources = ARRAY_SIZE(egpio_resources),
+	.dev = {
+		.platform_data = &egpio_info,
+	},
+};
+
+/*
+ * LCD - Sony display connected to ATI Imageon w3220
+ */
+
+static int lcd_power;
+
+static void sony_lcd_init(void)
+{
+	gpio_set_value(GPIO84_HX4700_LCD_SQN, 1);
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0);
+	gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 0);
+	gpio_set_value(GPIO70_HX4700_LCD_SLIN1, 0);
+	gpio_set_value(GPIO62_HX4700_LCD_nRESET, 0);
+	mdelay(10);
+	gpio_set_value(GPIO59_HX4700_LCD_PC1, 0);
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0);
+	mdelay(20);
+
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1);
+	mdelay(5);
+	gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1);
+
+	/* FIXME: init w3220 registers here */
+
+	mdelay(5);
+	gpio_set_value(GPIO70_HX4700_LCD_SLIN1, 1);
+	mdelay(10);
+	gpio_set_value(GPIO62_HX4700_LCD_nRESET, 1);
+	mdelay(10);
+	gpio_set_value(GPIO59_HX4700_LCD_PC1, 1);
+	mdelay(10);
+	gpio_set_value(GPIO112_HX4700_LCD_N2V7_7V3_ON, 1);
+}
+
+static void sony_lcd_off(void)
+{
+	gpio_set_value(GPIO59_HX4700_LCD_PC1, 0);
+	gpio_set_value(GPIO62_HX4700_LCD_nRESET, 0);
+	mdelay(10);
+	gpio_set_value(GPIO112_HX4700_LCD_N2V7_7V3_ON, 0);
+	mdelay(10);
+	gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 0);
+	mdelay(10);
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0);
+}
+
+static int hx4700_lcd_set_power(struct lcd_device *ldev, int level)
+{
+	switch (level) {
+	case FB_BLANK_UNBLANK:
+		sony_lcd_init();
+		break;
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		sony_lcd_off();
+		break;
+	}
+	lcd_power = level;
+	return 0;
+}
+
+static int hx4700_lcd_get_power(struct lcd_device *lm)
+{
+	return lcd_power;
+}
+
+static struct lcd_ops hx4700_lcd_ops = {
+	.get_power = hx4700_lcd_get_power,
+	.set_power = hx4700_lcd_set_power,
+};
+
+static struct lcd_device *hx4700_lcd_device;
+
+#ifdef CONFIG_PM
+static void w3220_lcd_suspend(struct w100fb_par *wfb)
+{
+	sony_lcd_off();
+}
+
+static void w3220_lcd_resume(struct w100fb_par *wfb)
+{
+	sony_lcd_init();
+}
+#else
+#define w3220_lcd_resume	NULL
+#define w3220_lcd_suspend	NULL
+#endif
+
+static struct w100_tg_info w3220_tg_info = {
+	.suspend	= w3220_lcd_suspend,
+	.resume		= w3220_lcd_resume,
+};
+
+/*  				 W3220_VGA		QVGA */
+static struct w100_gen_regs w3220_regs = {
+	.lcd_format =        0x00000003,
+	.lcdd_cntl1 =        0x00000000,
+	.lcdd_cntl2 =        0x0003ffff,
+	.genlcd_cntl1 =      0x00abf003,	/* 0x00fff003 */
+	.genlcd_cntl2 =      0x00000003,
+	.genlcd_cntl3 =      0x000102aa,
+};
+
+static struct w100_mode w3220_modes[] = {
+{
+	.xres 		= 480,
+	.yres 		= 640,
+	.left_margin 	= 15,
+	.right_margin 	= 16,
+	.upper_margin 	= 8,
+	.lower_margin 	= 7,
+	.crtc_ss	= 0x00000000,
+	.crtc_ls	= 0xa1ff01f9,	/* 0x21ff01f9 */
+	.crtc_gs	= 0xc0000000,	/* 0x40000000 */
+	.crtc_vpos_gs	= 0x0000028f,
+	.crtc_ps1_active = 0x00000000,	/* 0x41060010 */
+	.crtc_rev	= 0,
+	.crtc_dclk	= 0x80000000,
+	.crtc_gclk	= 0x040a0104,
+	.crtc_goe	= 0,
+	.pll_freq 	= 95,
+	.pixclk_divider = 4,
+	.pixclk_divider_rotated = 4,
+	.pixclk_src     = CLK_SRC_PLL,
+	.sysclk_divider = 0,
+	.sysclk_src     = CLK_SRC_PLL,
+},
+{
+	.xres 		= 240,
+	.yres 		= 320,
+	.left_margin 	= 9,
+	.right_margin 	= 8,
+	.upper_margin 	= 5,
+	.lower_margin 	= 4,
+	.crtc_ss	= 0x80150014,
+	.crtc_ls        = 0xa0fb00f7,
+	.crtc_gs	= 0xc0080007,
+	.crtc_vpos_gs	= 0x00080007,
+	.crtc_rev	= 0x0000000a,
+	.crtc_dclk	= 0x81700030,
+	.crtc_gclk	= 0x8015010f,
+	.crtc_goe	= 0x00000000,
+	.pll_freq 	= 95,
+	.pixclk_divider = 4,
+	.pixclk_divider_rotated = 4,
+	.pixclk_src     = CLK_SRC_PLL,
+	.sysclk_divider = 0,
+	.sysclk_src     = CLK_SRC_PLL,
+},
+};
+
+struct w100_mem_info w3220_mem_info = {
+	.ext_cntl        = 0x09640011,
+	.sdram_mode_reg  = 0x00600021,
+	.ext_timing_cntl = 0x1a001545,	/* 0x15001545 */
+	.io_cntl         = 0x7ddd7333,
+	.size            = 0x1fffff,
+};
+
+struct w100_bm_mem_info w3220_bm_mem_info = {
+	.ext_mem_bw = 0x50413e01,
+	.offset = 0,
+	.ext_timing_ctl = 0x00043f7f,
+	.ext_cntl = 0x00000010,
+	.mode_reg = 0x00250000,
+	.io_cntl = 0x0fff0000,
+	.config = 0x08301480,
+};
+
+static struct w100_gpio_regs w3220_gpio_info = {
+	.init_data1 = 0xdfe00100,	/* GPIO_DATA */
+	.gpio_dir1  = 0xffff0000,	/* GPIO_CNTL1 */
+	.gpio_oe1   = 0x00000000,	/* GPIO_CNTL2 */
+	.init_data2 = 0x00000000,	/* GPIO_DATA2 */
+	.gpio_dir2  = 0x00000000,	/* GPIO_CNTL3 */
+	.gpio_oe2   = 0x00000000,	/* GPIO_CNTL4 */
+};
+
+static struct w100fb_mach_info w3220_info = {
+	.tg        = &w3220_tg_info,
+	.mem       = &w3220_mem_info,
+	.bm_mem    = &w3220_bm_mem_info,
+	.gpio      = &w3220_gpio_info,
+	.regs      = &w3220_regs,
+	.modelist  = w3220_modes,
+	.num_modes = 2,
+	.xtal_freq = 16000000,
+};
+
+static struct resource w3220_resources[] = {
+	[0] = {
+		.start	= ATI_W3220_PHYS,
+		.end	= ATI_W3220_PHYS + 0x00ffffff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device w3220 = {
+	.name	= "w100fb",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &w3220_info,
+	},
+	.num_resources = ARRAY_SIZE(w3220_resources),
+	.resource      = w3220_resources,
+};
+
+/*
+ * Backlight
+ */
+
+static struct platform_pwm_backlight_data backlight_data = {
+	.pwm_id         = 1,
+	.max_brightness = 200,
+	.dft_brightness = 100,
+	.pwm_period_ns  = 30923,
+};
+
+static struct platform_device backlight = {
+	.name = "pwm-backlight",
+	.id   = -1,
+	.dev  = {
+		.parent        = &pxa27x_device_pwm1.dev,
+		.platform_data = &backlight_data,
+	},
+};
+
+/*
+ * USB "Transceiver"
+ */
+
+static struct gpio_vbus_mach_info gpio_vbus_info = {
+	.gpio_pullup        = GPIO76_HX4700_USBC_PUEN,
+	.gpio_vbus          = GPIOD14_nUSBC_DETECT,
+	.gpio_vbus_inverted = 1,
+};
+
+static struct platform_device gpio_vbus = {
+	.name          = "gpio-vbus",
+	.id            = -1,
+	.dev = {
+		.platform_data = &gpio_vbus_info,
+	},
+};
+
+/*
+ * Touchscreen - TSC2046 connected to SSP2
+ */
+
+static const struct ads7846_platform_data tsc2046_info = {
+	.model            = 7846,
+	.vref_delay_usecs = 100,
+	.pressure_max     = 512,
+	.debounce_max     = 10,
+	.debounce_tol     = 3,
+	.debounce_rep     = 1,
+	.gpio_pendown     = GPIO58_HX4700_TSC2046_nPENIRQ,
+};
+
+static struct pxa2xx_spi_chip tsc2046_chip = {
+	.tx_threshold = 1,
+	.rx_threshold = 2,
+	.timeout      = 64,
+	.gpio_cs      = GPIO88_HX4700_TSC2046_CS,
+};
+
+static struct spi_board_info tsc2046_board_info[] __initdata = {
+	{
+		.modalias        = "ads7846",
+		.bus_num         = 2,
+		.max_speed_hz    = 2600000, /* 100 kHz sample rate */
+		.irq             = gpio_to_irq(GPIO58_HX4700_TSC2046_nPENIRQ),
+		.platform_data   = &tsc2046_info,
+		.controller_data = &tsc2046_chip,
+	},
+};
+
+static struct pxa2xx_spi_master pxa_ssp2_master_info = {
+	.num_chipselect = 1,
+	.clock_enable   = CKEN_SSP2,
+	.enable_dma     = 1,
+};
+
+/*
+ * External power
+ */
+
+static int power_supply_init(struct device *dev)
+{
+	return gpio_request(GPIOD9_nAC_IN, "AC charger detect");
+}
+
+static int hx4700_is_ac_online(void)
+{
+	return !gpio_get_value(GPIOD9_nAC_IN);
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(GPIOD9_nAC_IN);
+}
+
+static char *hx4700_supplicants[] = {
+	"ds2760-battery.0", "backup-battery"
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init            = power_supply_init,
+	.is_ac_online    = hx4700_is_ac_online,
+	.exit            = power_supply_exit,
+	.supplied_to     = hx4700_supplicants,
+	.num_supplicants = ARRAY_SIZE(hx4700_supplicants),
+};
+
+static struct resource power_supply_resources[] = {
+	[0] = {
+		.name  = "ac",
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		         IORESOURCE_IRQ_LOWEDGE,
+		.start = gpio_to_irq(GPIOD9_nAC_IN),
+		.end   = gpio_to_irq(GPIOD9_nAC_IN),
+	},
+	[1] = {
+		.name  = "usb",
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		         IORESOURCE_IRQ_LOWEDGE,
+		.start = gpio_to_irq(GPIOD14_nUSBC_DETECT),
+		.end   = gpio_to_irq(GPIOD14_nUSBC_DETECT),
+	},
+};
+
+static struct platform_device power_supply = {
+	.name = "pda-power",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &power_supply_info,
+	},
+	.resource      = power_supply_resources,
+	.num_resources = ARRAY_SIZE(power_supply_resources),
+};
+
+/*
+ * Battery charger
+ */
+
+static struct regulator_consumer_supply bq24022_consumers[] = {
+	{
+		.dev = &gpio_vbus.dev,
+		.supply = "vbus_draw",
+	},
+	{
+		.dev = &power_supply.dev,
+		.supply = "ac_draw",
+	},
+};
+
+static struct regulator_init_data bq24022_init_data = {
+	.constraints = {
+		.max_uA         = 500000,
+		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
+	.consumer_supplies      = bq24022_consumers,
+};
+
+static struct bq24022_mach_info bq24022_info = {
+	.gpio_nce   = GPIO72_HX4700_BQ24022_nCHARGE_EN,
+	.gpio_iset2 = GPIO96_HX4700_BQ24022_ISET2,
+	.init_data  = &bq24022_init_data,
+};
+
+static struct platform_device bq24022 = {
+	.name = "bq24022",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &bq24022_info,
+	},
+};
+
+/*
+ * StrataFlash
+ */
+
+static void hx4700_set_vpp(struct map_info *map, int vpp)
+{
+	gpio_set_value(GPIO91_HX4700_FLASH_VPEN, vpp);
+}
+
+static struct resource strataflash_resource = {
+	.start = PXA_CS0_PHYS,
+	.end   = PXA_CS0_PHYS + SZ_128M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data strataflash_data = {
+	.width = 4,
+	.set_vpp = hx4700_set_vpp,
+};
+
+static struct platform_device strataflash = {
+	.name          = "physmap-flash",
+	.id            = -1,
+	.resource      = &strataflash_resource,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &strataflash_data,
+	},
+};
+
+/*
+ * Maxim MAX1587A on PI2C
+ */
+
+static struct regulator_consumer_supply max1587a_consumer = {
+	.supply = "vcc_core",
+};
+
+static struct regulator_init_data max1587a_v3_info = {
+	.constraints = {
+		.name = "vcc_core range",
+		.min_uV =  900000,
+		.max_uV = 1705000,
+		.always_on = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies     = &max1587a_consumer,
+};
+
+static struct max1586_subdev_data max1587a_subdev = {
+	.name = "vcc_core",
+	.id   = MAX1586_V3,
+	.platform_data = &max1587a_v3_info,
+};
+
+static struct max1586_platform_data max1587a_info = {
+	.num_subdevs = 1,
+	.subdevs     = &max1587a_subdev,
+	.v3_gain     = MAX1586_GAIN_R24_3k32, /* 730..1550 mV */
+};
+
+static struct i2c_board_info __initdata pi2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("max1586", 0x14),
+		.platform_data = &max1587a_info,
+	},
+};
+
+/*
+ * PCMCIA
+ */
+
+static struct platform_device pcmcia = {
+	.name = "hx4700-pcmcia",
+	.dev  = {
+		.parent = &asic3.dev,
+	},
+};
+
+/*
+ * Platform devices
+ */
+
+static struct platform_device *devices[] __initdata = {
+	&asic3,
+	&gpio_keys,
+	&backlight,
+	&w3220,
+	&egpio,
+	&bq24022,
+	&gpio_vbus,
+	&power_supply,
+	&strataflash,
+	&pcmcia,
+};
+
+static struct gpio_ress global_gpios[] = {
+	HX4700_GPIO_IN(GPIO12_HX4700_ASIC3_IRQ, "ASIC3_IRQ"),
+	HX4700_GPIO_IN(GPIO13_HX4700_W3220_IRQ, "W3220_IRQ"),
+	HX4700_GPIO_IN(GPIO14_HX4700_nWLAN_IRQ, "WLAN_IRQ"),
+	HX4700_GPIO_OUT(GPIO59_HX4700_LCD_PC1,          1, "LCD_PC1"),
+	HX4700_GPIO_OUT(GPIO62_HX4700_LCD_nRESET,       1, "LCD_RESET"),
+	HX4700_GPIO_OUT(GPIO70_HX4700_LCD_SLIN1,        1, "LCD_SLIN1"),
+	HX4700_GPIO_OUT(GPIO84_HX4700_LCD_SQN,          1, "LCD_SQN"),
+	HX4700_GPIO_OUT(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1, "LCD_LVDD"),
+	HX4700_GPIO_OUT(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1, "LCD_AVDD"),
+	HX4700_GPIO_OUT(GPIO32_HX4700_RS232_ON,         1, "RS232_ON"),
+	HX4700_GPIO_OUT(GPIO71_HX4700_ASIC3_nRESET,     1, "ASIC3_nRESET"),
+	HX4700_GPIO_OUT(GPIO82_HX4700_EUART_RESET,      1, "EUART_RESET"),
+	HX4700_GPIO_OUT(GPIO105_HX4700_nIR_ON,          1, "nIR_EN"),
+};
+
+static void __init hx4700_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(hx4700_pin_config));
+	hx4700_gpio_request(ARRAY_AND_SIZE(global_gpios));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	pxa_set_ficp_info(&ficp_info);
+	pxa27x_set_i2c_power_info(NULL);
+	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(1, ARRAY_AND_SIZE(pi2c_board_info));
+	pxa2xx_set_spi_info(2, &pxa_ssp2_master_info);
+	spi_register_board_info(ARRAY_AND_SIZE(tsc2046_board_info));
+
+	hx4700_lcd_device = lcd_device_register("w100fb", NULL,
+					(void *)&w3220_info, &hx4700_lcd_ops);
+
+	gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 0);
+	mdelay(10);
+	gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1);
+	mdelay(10);
+}
+
+MACHINE_START(H4700, "HP iPAQ HX4700")
+	.phys_io      = 0x40000000,
+	.io_pg_offst  = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params  = 0xa0000100,
+	.map_io       = pxa_map_io,
+	.init_irq     = pxa27x_init_irq,
+	.init_machine = hx4700_init,
+	.timer        = &pxa_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/imote2.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/imote2.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/imote2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/imote2.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/spi/spi.h>
 #include <linux/i2c.h>
 #include <linux/mfd/da903x.h>
+#include <linux/sht15.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -29,7 +30,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/udc.h>
 #include <mach/mmc.h>
 #include <mach/pxa2xx_spi.h>
@@ -102,6 +103,10 @@
 	GPIO96_GPIO,	/* accelerometer interrupt */
 	GPIO99_GPIO,	/* ADC interrupt */
 
+	/* SHT15 */
+	GPIO100_GPIO,
+	GPIO98_GPIO,
+
 	/* Connector pins specified as gpios */
 	GPIO94_GPIO, /* large basic connector pin 14 */
 	GPIO10_GPIO, /* large basic connector pin 23 */
@@ -112,6 +117,26 @@
 	GPIO105_GPIO, /* blue led */
 };
 
+static struct sht15_platform_data platform_data_sht15 = {
+	.gpio_data =  100,
+	.gpio_sck  =  98,
+};
+
+static struct platform_device sht15 = {
+	.name = "sht15",
+	.id = -1,
+	.dev = {
+		.platform_data = &platform_data_sht15,
+	},
+};
+
+static struct regulator_consumer_supply imote2_sensor_3_con[] = {
+	{
+		.dev = &sht15.dev,
+		.supply = "vcc",
+	},
+};
+
 static struct gpio_led imote2_led_pins[] = {
 	{
 		.name       =  "imote2:red",
@@ -257,6 +282,8 @@
 			.min_uV = 2800000,
 			.max_uV = 3000000,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(imote2_sensor_3_con),
+		.consumer_supplies = imote2_sensor_3_con,
 	},
 	[vcc_pxa_pll] = { /* 1.17V - 1.43V, default 1.3V*/
 		.constraints = {
@@ -432,6 +459,9 @@
 		.type = "tmp175",
 		.addr = 0x4A,
 		.irq = IRQ_GPIO(96),
+	}, { /* IMB400 Multimedia board */
+		.type = "wm8940",
+		.addr = 0x1A,
 	},
 };
 
@@ -456,25 +486,12 @@
 	.num_chipselect = 1,
 };
 
-/* Patch posted by Eric Miao <eric.miao@marvell.com> will remove
- * the need for these functions.
- */
-static void spi1control(u32 command)
-{
-	gpio_set_value(24, command & PXA2XX_CS_ASSERT ? 0 : 1);
-};
-
-static void spi3control(u32 command)
-{
-	gpio_set_value(39, command & PXA2XX_CS_ASSERT ? 0 : 1);
-};
-
 static struct pxa2xx_spi_chip staccel_chip_info = {
 	.tx_threshold = 8,
 	.rx_threshold = 8,
 	.dma_burst_size = 8,
 	.timeout = 235,
-	.cs_control = spi1control,
+	.gpio_cs = 24,
 };
 
 static struct pxa2xx_spi_chip cc2420_info = {
@@ -482,7 +499,7 @@
 	.rx_threshold = 8,
 	.dma_burst_size = 8,
 	.timeout = 235,
-	.cs_control = spi3control,
+	.gpio_cs = 39,
 };
 
 static struct spi_board_info spi_board_info[] __initdata = {
@@ -521,6 +538,7 @@
 static struct platform_device *imote2_devices[] = {
 	&imote2_flash_device,
 	&imote2_leds,
+	&sht15,
 };
 
 static struct i2c_pxa_platform_data i2c_pwr_pdata = {
@@ -538,8 +556,6 @@
 	/* SPI chip select directions - all other directions should
 	 * be handled by drivers.*/
 	gpio_direction_output(37, 0);
-	gpio_direction_output(24, 0);
-	gpio_direction_output(39, 0);
 
 	platform_add_devices(imote2_devices, ARRAY_SIZE(imote2_devices));
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/hx4700.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/hx4700.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/hx4700.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/hx4700.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ * GPIO and IRQ definitions for HP iPAQ hx4700
+ *
+ * Copyright (c) 2008 Philipp Zabel
+ *
+ * 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.
+ *
+ */
+
+#ifndef _HX4700_H_
+#define _HX4700_H_
+
+#include <linux/gpio.h>
+#include <linux/mfd/asic3.h>
+
+#define HX4700_ASIC3_GPIO_BASE	NR_BUILTIN_GPIO
+#define HX4700_EGPIO_BASE	(HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS)
+
+/*
+ * PXA GPIOs
+ */
+
+#define GPIO0_HX4700_nKEY_POWER			0
+#define GPIO12_HX4700_ASIC3_IRQ			12
+#define GPIO13_HX4700_W3220_IRQ			13
+#define GPIO14_HX4700_nWLAN_IRQ			14
+#define GPIO18_HX4700_RDY			18
+#define GPIO22_HX4700_LCD_RL			22
+#define GPIO27_HX4700_CODEC_ON			27
+#define GPIO32_HX4700_RS232_ON			32
+#define GPIO52_HX4700_CPU_nBATT_FAULT		52
+#define GPIO58_HX4700_TSC2046_nPENIRQ		58
+#define GPIO59_HX4700_LCD_PC1			59
+#define GPIO60_HX4700_CF_RNB			60
+#define GPIO61_HX4700_W3220_nRESET		61
+#define GPIO62_HX4700_LCD_nRESET		62
+#define GPIO63_HX4700_CPU_SS_nRESET		63
+#define GPIO65_HX4700_TSC2046_PEN_PU		65
+#define GPIO66_HX4700_ASIC3_nSDIO_IRQ		66
+#define GPIO67_HX4700_EUART_PS			67
+#define GPIO70_HX4700_LCD_SLIN1			70
+#define GPIO71_HX4700_ASIC3_nRESET		71
+#define GPIO72_HX4700_BQ24022_nCHARGE_EN	72
+#define GPIO73_HX4700_LCD_UD_1			73
+#define GPIO75_HX4700_EARPHONE_nDET		75
+#define GPIO76_HX4700_USBC_PUEN			76
+#define GPIO81_HX4700_CPU_GP_nRESET		81
+#define GPIO82_HX4700_EUART_RESET		82
+#define GPIO83_HX4700_WLAN_nRESET		83
+#define GPIO84_HX4700_LCD_SQN			84
+#define GPIO85_HX4700_nPCE1			85
+#define GPIO88_HX4700_TSC2046_CS		88
+#define GPIO91_HX4700_FLASH_VPEN		91
+#define GPIO92_HX4700_HP_DRIVER			92
+#define GPIO93_HX4700_EUART_INT			93
+#define GPIO94_HX4700_KEY_MAIL			94
+#define GPIO95_HX4700_BATT_OFF			95
+#define GPIO96_HX4700_BQ24022_ISET2		96
+#define GPIO97_HX4700_nBL_DETECT		97
+#define GPIO99_HX4700_KEY_CONTACTS		99
+#define GPIO100_HX4700_AUTO_SENSE		100 /* BL auto brightness */
+#define GPIO102_HX4700_SYNAPTICS_POWER_ON	102
+#define GPIO103_HX4700_SYNAPTICS_INT		103
+#define GPIO105_HX4700_nIR_ON			105
+#define GPIO106_HX4700_CPU_BT_nRESET		106
+#define GPIO107_HX4700_SPK_nSD			107
+#define GPIO109_HX4700_CODEC_nPDN		109
+#define GPIO110_HX4700_LCD_LVDD_3V3_ON		110
+#define GPIO111_HX4700_LCD_AVDD_3V3_ON		111
+#define GPIO112_HX4700_LCD_N2V7_7V3_ON		112
+#define GPIO114_HX4700_CF_RESET			114
+#define GPIO116_HX4700_CPU_HW_nRESET		116
+
+/*
+ * ASIC3 GPIOs
+ */
+
+#define GPIOC_BASE		(HX4700_ASIC3_GPIO_BASE + 32)
+#define GPIOD_BASE		(HX4700_ASIC3_GPIO_BASE + 48)
+
+#define GPIOC0_LED_RED		(GPIOC_BASE + 0)
+#define GPIOC1_LED_GREEN	(GPIOC_BASE + 1)
+#define GPIOC2_LED_BLUE		(GPIOC_BASE + 2)
+#define GPIOC3_nSD_CS		(GPIOC_BASE + 3)
+#define GPIOC4_CF_nCD		(GPIOC_BASE + 4)	/* Input */
+#define GPIOC5_nCIOW		(GPIOC_BASE + 5)	/* Output, to CF */
+#define GPIOC6_nCIOR		(GPIOC_BASE + 6)	/* Output, to CF */
+#define GPIOC7_nPCE1		(GPIOC_BASE + 7)	/* Input, from CPU */
+#define GPIOC8_nPCE2		(GPIOC_BASE + 8)	/* Input, from CPU */
+#define GPIOC9_nPOE		(GPIOC_BASE + 9)	/* Input, from CPU */
+#define GPIOC10_CF_nPWE		(GPIOC_BASE + 10)	/* Input */
+#define GPIOC11_PSKTSEL		(GPIOC_BASE + 11)	/* Input, from CPU */
+#define GPIOC12_nPREG		(GPIOC_BASE + 12)	/* Input, from CPU */
+#define GPIOC13_nPWAIT		(GPIOC_BASE + 13)	/* Output, to CPU */
+#define GPIOC14_nPIOIS16	(GPIOC_BASE + 14)	/* Output, to CPU */
+#define GPIOC15_nPIOR		(GPIOC_BASE + 15)	/* Input, from CPU */
+
+#define GPIOD0_CPU_SS_INT	(GPIOD_BASE + 0)	/* Input */
+#define GPIOD1_nKEY_CALENDAR	(GPIOD_BASE + 1)
+#define GPIOD2_BLUETOOTH_WAKEUP	(GPIOD_BASE + 2)
+#define GPIOD3_nKEY_HOME	(GPIOD_BASE + 3)
+#define GPIOD4_CF_nCD		(GPIOD_BASE + 4)	/* Input, from CF */
+#define GPIOD5_nPIO		(GPIOD_BASE + 5)	/* Input */
+#define GPIOD6_nKEY_RECORD	(GPIOD_BASE + 6)
+#define GPIOD7_nSDIO_DETECT	(GPIOD_BASE + 7)
+#define GPIOD8_COM_DCD		(GPIOD_BASE + 8)	/* Input */
+#define GPIOD9_nAC_IN		(GPIOD_BASE + 9)
+#define GPIOD10_nSDIO_IRQ	(GPIOD_BASE + 10)	/* Input */
+#define GPIOD11_nCIOIS16	(GPIOD_BASE + 11)	/* Input, from CF */
+#define GPIOD12_nCWAIT		(GPIOD_BASE + 12)	/* Input, from CF */
+#define GPIOD13_CF_RNB		(GPIOD_BASE + 13)	/* Input */
+#define GPIOD14_nUSBC_DETECT	(GPIOD_BASE + 14)
+#define GPIOD15_nPIOW		(GPIOD_BASE + 15)	/* Input, from CPU */
+
+/*
+ * EGPIOs
+ */
+
+#define EGPIO0_VCC_3V3_EN	(HX4700_EGPIO_BASE + 0)	/* WLAN support chip */
+#define EGPIO1_WL_VREG_EN	(HX4700_EGPIO_BASE + 1)	/* WLAN power */
+#define EGPIO2_VCC_2V1_WL_EN	(HX4700_EGPIO_BASE + 2)	/* unused */
+#define EGPIO3_SS_PWR_ON	(HX4700_EGPIO_BASE + 3)	/* smart slot power */
+#define EGPIO4_CF_3V3_ON	(HX4700_EGPIO_BASE + 4)	/* CF 3.3V enable */
+#define EGPIO5_BT_3V3_ON	(HX4700_EGPIO_BASE + 5)	/* BT 3.3V enable */
+#define EGPIO6_WL1V8_EN		(HX4700_EGPIO_BASE + 6)	/* WLAN 1.8V enable */
+#define EGPIO7_VCC_3V3_WL_EN	(HX4700_EGPIO_BASE + 7)	/* WLAN 3.3V enable */
+#define EGPIO8_USB_3V3_ON	(HX4700_EGPIO_BASE + 8)	/* unused */
+
+#endif /* _HX4700_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/i2c.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/i2c.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/i2c.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/i2c.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- *  i2c_pxa.h
- *
- *  Copyright (C) 2002 Intrinsyc Software Inc.
- *
- *  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.
- *
- */
-#ifndef _I2C_PXA_H_
-#define _I2C_PXA_H_
-
-#if 0
-#define DEF_TIMEOUT             3
-#else
-/* need a longer timeout if we're dealing with the fact we may well be
- * looking at a multi-master environment
-*/
-#define DEF_TIMEOUT             32
-#endif
-
-#define BUS_ERROR               (-EREMOTEIO)
-#define XFER_NAKED              (-ECONNREFUSED)
-#define I2C_RETRY               (-2000) /* an error has occurred retry transmit */
-
-/* ICR initialize bit values
-*
-*  15. FM       0 (100 Khz operation)
-*  14. UR       0 (No unit reset)
-*  13. SADIE    0 (Disables the unit from interrupting on slave addresses
-*                                       matching its slave address)
-*  12. ALDIE    0 (Disables the unit from interrupt when it loses arbitration
-*                                       in master mode)
-*  11. SSDIE    0 (Disables interrupts from a slave stop detected, in slave mode)
-*  10. BEIE     1 (Enable interrupts from detected bus errors, no ACK sent)
-*  9.  IRFIE    1 (Enable interrupts from full buffer received)
-*  8.  ITEIE    1 (Enables the I2C unit to interrupt when transmit buffer empty)
-*  7.  GCD      1 (Disables i2c unit response to general call messages as a slave)
-*  6.  IUE      0 (Disable unit until we change settings)
-*  5.  SCLE     1 (Enables the i2c clock output for master mode (drives SCL)
-*  4.  MA       0 (Only send stop with the ICR stop bit)
-*  3.  TB       0 (We are not transmitting a byte initially)
-*  2.  ACKNAK   0 (Send an ACK after the unit receives a byte)
-*  1.  STOP     0 (Do not send a STOP)
-*  0.  START    0 (Do not send a START)
-*
-*/
-#define I2C_ICR_INIT	(ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
-
-/* I2C status register init values
- *
- * 10. BED      1 (Clear bus error detected)
- * 9.  SAD      1 (Clear slave address detected)
- * 7.  IRF      1 (Clear IDBR Receive Full)
- * 6.  ITE      1 (Clear IDBR Transmit Empty)
- * 5.  ALD      1 (Clear Arbitration Loss Detected)
- * 4.  SSD      1 (Clear Slave Stop Detected)
- */
-#define I2C_ISR_INIT	0x7FF  /* status register init */
-
-struct i2c_slave_client;
-
-struct i2c_pxa_platform_data {
-	unsigned int		slave_addr;
-	struct i2c_slave_client	*slave;
-	unsigned int		class;
-	unsigned int		use_pio :1;
-	unsigned int		fast_mode :1;
-};
-
-extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
-
-#ifdef CONFIG_PXA27x
-extern void pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info);
-#endif
-
-#ifdef CONFIG_PXA3xx
-extern void pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info);
-#endif
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -91,13 +91,23 @@
 #define IRQ_TO_GPIO(i)	(((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
 
 /*
- * The next 16 interrupts are for board specific purposes.  Since
+ * The following interrupts are for board specific purposes. Since
  * the kernel can only run on one machine at a time, we can re-use
- * these.  If you need more, increase IRQ_BOARD_END, but keep it
- * within sensible limits.
+ * these.  There will be 16 IRQs by default.  If it is not enough,
+ * IRQ_BOARD_END is allowed be customized for each board, but keep
+ * the numbers within sensible limits and in descending order, so
+ * when multiple config options are selected, the maximum will be
+ * used.
  */
 #define IRQ_BOARD_START		(PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
+
+#if defined(CONFIG_MACH_H4700)
+#define IRQ_BOARD_END		(IRQ_BOARD_START + 70)
+#elif defined(CONFIG_MACH_ZYLONITE)
+#define IRQ_BOARD_END		(IRQ_BOARD_START + 32)
+#else
 #define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
+#endif
 
 #define IRQ_SA1111_START	(IRQ_BOARD_END)
 #define IRQ_GPAIN0		(IRQ_BOARD_END + 0)
@@ -188,8 +198,6 @@
 #define NR_IRQS			(IRQ_LOCOMO_SPI_TEND + 1)
 #elif defined(CONFIG_PXA_HAVE_BOARD_IRQS)
 #define NR_IRQS			(IRQ_BOARD_END)
-#elif defined(CONFIG_MACH_ZYLONITE)
-#define NR_IRQS			(IRQ_BOARD_START + 32)
 #else
 #define NR_IRQS			(IRQ_BOARD_START)
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa300.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa300.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa300.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa300.h	2009-09-09 18:13:59.000000000 -0400
@@ -567,9 +567,9 @@
 #define GPIO37_ULPI_DATA_OUT_7	MFP_CFG(GPIO37, AF3)
 #define GPIO33_ULPI_OTG_INTR	MFP_CFG(GPIO33, AF1)
 
-#define ULPI_DIR	MFP_CFG_DRV(ULPI_DIR, MFP_AF0, MFP_DS01X)
-#define ULPI_NXT	MFP_CFG_DRV(ULPI_NXT, MFP_AF0, MFP_DS01X)
-#define ULPI_STP	MFP_CFG_DRV(ULPI_STP, MFP_AF0, MFP_DS01X)
+#define ULPI_DIR	MFP_CFG_DRV(ULPI_DIR, AF0, DS01X)
+#define ULPI_NXT	MFP_CFG_DRV(ULPI_NXT, AF0, DS01X)
+#define ULPI_STP	MFP_CFG_DRV(ULPI_STP, AF0, DS01X)
 #endif /* CONFIG_CPU_PXA310 */
 
 #endif /* __ASM_ARCH_MFP_PXA300_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa320.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa320.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa320.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/mfp-pxa320.h	2009-09-09 18:13:59.000000000 -0400
@@ -283,6 +283,9 @@
 #define GPIO41_UART1_TXD	MFP_CFG_LPM(GPIO41, AF4, FLOAT)
 #define GPIO42_UART1_RXD	MFP_CFG_LPM(GPIO42, AF4, FLOAT)
 #define GPIO42_UART1_TXD	MFP_CFG_LPM(GPIO42, AF2, FLOAT)
+#define GPIO75_UART1_RXD	MFP_CFG_LPM(GPIO75, AF1, FLOAT)
+#define GPIO76_UART1_RXD	MFP_CFG_LPM(GPIO76, AF3, FLOAT)
+#define GPIO76_UART1_TXD	MFP_CFG_LPM(GPIO76, AF1, FLOAT)
 #define GPIO97_UART1_RXD	MFP_CFG_LPM(GPIO97, AF1, FLOAT)
 #define GPIO97_UART1_TXD	MFP_CFG_LPM(GPIO97, AF6, FLOAT)
 #define GPIO98_UART1_RXD	MFP_CFG_LPM(GPIO98, AF6, FLOAT)
@@ -291,6 +294,9 @@
 #define GPIO43_UART1_RTS	MFP_CFG_LPM(GPIO43, AF4, FLOAT)
 #define GPIO48_UART1_CTS	MFP_CFG_LPM(GPIO48, AF4, FLOAT)
 #define GPIO48_UART1_RTS	MFP_CFG_LPM(GPIO48, AF2, FLOAT)
+#define GPIO77_UART1_CTS	MFP_CFG_LPM(GPIO77, AF1, FLOAT)
+#define GPIO82_UART1_RTS	MFP_CFG_LPM(GPIO82, AF1, FLOAT)
+#define GPIO82_UART1_CTS	MFP_CFG_LPM(GPIO82, AF3, FLOAT)
 #define GPIO99_UART1_CTS	MFP_CFG_LPM(GPIO99, AF1, FLOAT)
 #define GPIO99_UART1_RTS	MFP_CFG_LPM(GPIO99, AF6, FLOAT)
 #define GPIO104_UART1_CTS	MFP_CFG_LPM(GPIO104, AF6, FLOAT)
@@ -299,13 +305,18 @@
 #define GPIO45_UART1_DSR	MFP_CFG_LPM(GPIO45, AF2, FLOAT)
 #define GPIO47_UART1_DTR	MFP_CFG_LPM(GPIO47, AF2, FLOAT)
 #define GPIO47_UART1_DSR	MFP_CFG_LPM(GPIO47, AF4, FLOAT)
+#define GPIO79_UART1_DSR	MFP_CFG_LPM(GPIO79, AF1, FLOAT)
+#define GPIO81_UART1_DTR	MFP_CFG_LPM(GPIO81, AF1, FLOAT)
+#define GPIO81_UART1_DSR	MFP_CFG_LPM(GPIO81, AF3, FLOAT)
 #define GPIO101_UART1_DTR	MFP_CFG_LPM(GPIO101, AF6, FLOAT)
 #define GPIO101_UART1_DSR	MFP_CFG_LPM(GPIO101, AF1, FLOAT)
 #define GPIO103_UART1_DTR	MFP_CFG_LPM(GPIO103, AF1, FLOAT)
 #define GPIO103_UART1_DSR	MFP_CFG_LPM(GPIO103, AF6, FLOAT)
 #define GPIO44_UART1_DCD	MFP_CFG_LPM(GPIO44, AF2, FLOAT)
+#define GPIO78_UART1_DCD	MFP_CFG_LPM(GPIO78, AF1, FLOAT)
 #define GPIO100_UART1_DCD	MFP_CFG_LPM(GPIO100, AF1, FLOAT)
 #define GPIO46_UART1_RI		MFP_CFG_LPM(GPIO46, AF2, FLOAT)
+#define GPIO80_UART1_RI		MFP_CFG_LPM(GPIO80, AF1, FLOAT)
 #define GPIO102_UART1_RI	MFP_CFG_LPM(GPIO102, AF1, FLOAT)
 
 /* UART2 */
@@ -438,6 +449,9 @@
 
 #define GPIO2_RDY		MFP_CFG(GPIO2, AF1)
 #define GPIO5_NPIOR		MFP_CFG(GPIO5, AF3)
+#define GPIO6_NPIOW		MFP_CFG(GPIO6, AF3)
+#define GPIO7_NPIOS16		MFP_CFG(GPIO7, AF3)
+#define GPIO8_NPWAIT		MFP_CFG(GPIO8, AF3)
 
 #define GPIO11_PWM0_OUT		MFP_CFG(GPIO11, AF1)
 #define GPIO12_PWM1_OUT		MFP_CFG(GPIO12, AF1)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/palmld.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/palmld.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/palmld.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/palmld.h	2009-09-09 18:13:59.000000000 -0400
@@ -56,7 +56,6 @@
 #define GPIO_NR_PALMLD_LED_AMBER	94
 
 /* IDE */
-#define GPIO_NR_PALMLD_IDE_IRQ		95
 #define GPIO_NR_PALMLD_IDE_RESET	98
 #define GPIO_NR_PALMLD_IDE_PWEN		115
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/palmz72.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/palmz72.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/palmz72.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/palmz72.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,7 @@
 /* SD/MMC */
 #define GPIO_NR_PALMZ72_SD_DETECT_N		14
 #define GPIO_NR_PALMZ72_SD_POWER_N		98
-#define GPIO_NR_PALMZ72_SD_RO 115
+#define GPIO_NR_PALMZ72_SD_RO			115
 
 /* Touchscreen */
 #define GPIO_NR_PALMZ72_WM9712_IRQ		27
@@ -31,8 +31,7 @@
 
 /* USB */
 #define GPIO_NR_PALMZ72_USB_DETECT_N		15
-#define GPIO_NR_PALMZ72_USB_POWER		95
-#define GPIO_NR_PALMZ72_USB_PULLUP		12
+#define GPIO_NR_PALMZ72_USB_PULLUP		95
 
 /* LCD/Backlight */
 #define GPIO_NR_PALMZ72_BL_POWER		20
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/pm.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/pm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/pm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/pm.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,8 @@
 extern void pxa_cpu_resume(void);
 
 extern int pxa_pm_enter(suspend_state_t state);
+extern int pxa_pm_prepare(void);
+extern void pxa_pm_finish(void);
 
 /* NOTE: this is for PM debugging on Lubbock,  it's really a big
  * ugly, but let's keep the crap minimum here, instead of direct
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/pxa27x.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,4 +16,7 @@
 #define ARB_DMA_PARK		(1<<25)	   /* Be parked with DMA when idle */
 #define ARB_CORE_PARK		(1<<24)	   /* Be parked with core when idle */
 #define ARB_LOCK_FLAG		(1<<23)	   /* Only Locking masters gain access to the bus */
+
+extern int __init pxa27x_set_pwrmode(unsigned int mode);
+
 #endif /* __MACH_PXA27x_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/sharpsl_pm.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/sharpsl_pm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/sharpsl_pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/sharpsl_pm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * SharpSL Battery/PM Driver
+ *
+ * Copyright (c) 2004-2005 Richard Purdie
+ *
+ * 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.
+ *
+ */
+#ifndef _MACH_SHARPSL_PM
+#define _MACH_SHARPSL_PM
+
+struct sharpsl_charger_machinfo {
+	void (*init)(void);
+	void (*exit)(void);
+	int gpio_acin;
+	int gpio_batfull;
+	int batfull_irq;
+	int gpio_batlock;
+	int gpio_fatal;
+	void (*discharge)(int);
+	void (*discharge1)(int);
+	void (*charge)(int);
+	void (*measure_temp)(int);
+	void (*presuspend)(void);
+	void (*postsuspend)(void);
+	void (*earlyresume)(void);
+	unsigned long (*read_devdata)(int);
+#define SHARPSL_BATT_VOLT       1
+#define SHARPSL_BATT_TEMP       2
+#define SHARPSL_ACIN_VOLT       3
+#define SHARPSL_STATUS_ACIN     4
+#define SHARPSL_STATUS_LOCK     5
+#define SHARPSL_STATUS_CHRGFULL 6
+#define SHARPSL_STATUS_FATAL    7
+	unsigned long (*charger_wakeup)(void);
+	int (*should_wakeup)(unsigned int resume_on_alarm);
+	void (*backlight_limit)(int);
+	int (*backlight_get_status) (void);
+	int charge_on_volt;
+	int charge_on_temp;
+	int charge_acin_high;
+	int charge_acin_low;
+	int fatal_acin_volt;
+	int fatal_noacin_volt;
+	int bat_levels;
+	struct battery_thresh *bat_levels_noac;
+	struct battery_thresh *bat_levels_acin;
+	struct battery_thresh *bat_levels_noac_bl;
+	struct battery_thresh *bat_levels_acin_bl;
+	int status_high_acin;
+	int status_low_acin;
+	int status_high_noac;
+	int status_low_noac;
+};
+
+struct battery_thresh {
+	int voltage;
+	int percentage;
+};
+
+struct battery_stat {
+	int ac_status;         /* APM AC Present/Not Present */
+	int mainbat_status;    /* APM Main Battery Status */
+	int mainbat_percent;   /* Main Battery Percentage Charge */
+	int mainbat_voltage;   /* Main Battery Voltage */
+};
+
+struct sharpsl_pm_status {
+	struct device *dev;
+	struct timer_list ac_timer;
+	struct timer_list chrg_full_timer;
+
+	int charge_mode;
+#define CHRG_ERROR    (-1)
+#define CHRG_OFF      (0)
+#define CHRG_ON       (1)
+#define CHRG_DONE     (2)
+
+	unsigned int flags;
+#define SHARPSL_SUSPENDED       (1 << 0)  /* Device is Suspended */
+#define SHARPSL_ALARM_ACTIVE    (1 << 1)  /* Alarm is for charging event (not user) */
+#define SHARPSL_BL_LIMIT        (1 << 2)  /* Backlight Intensity Limited */
+#define SHARPSL_APM_QUEUED      (1 << 3)  /* APM Event Queued */
+#define SHARPSL_DO_OFFLINE_CHRG (1 << 4)  /* Trigger the offline charger */
+
+	int full_count;
+	unsigned long charge_start_time;
+	struct sharpsl_charger_machinfo *machinfo;
+	struct battery_stat battstat;
+};
+
+extern struct sharpsl_pm_status sharpsl_pm;
+
+
+#define SHARPSL_LED_ERROR  2
+#define SHARPSL_LED_ON     1
+#define SHARPSL_LED_OFF    0
+
+void sharpsl_battery_kick(void);
+void sharpsl_pm_led(int val);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/treo680.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/treo680.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/treo680.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/treo680.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * GPIOs and interrupts for Palm Treo 680 smartphone
+ *
+ * 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.
+ *
+ */
+
+#ifndef _INCLUDE_TREO680_H_
+#define _INCLUDE_TREO680_H_
+
+/* GPIOs */
+#define GPIO_NR_TREO680_POWER_DETECT	0
+#define GPIO_NR_TREO680_AMP_EN		27
+#define GPIO_NR_TREO680_KEYB_BL		24
+#define GPIO_NR_TREO680_VIBRATE_EN	44
+#define GPIO_NR_TREO680_GREEN_LED	20
+#define GPIO_NR_TREO680_RED_LED		79
+#define GPIO_NR_TREO680_SD_DETECT_N	113
+#define GPIO_NR_TREO680_SD_READONLY	33
+#define GPIO_NR_TREO680_EP_DETECT_N	116
+#define GPIO_NR_TREO680_SD_POWER	42
+#define GPIO_NR_TREO680_USB_DETECT	1
+#define GPIO_NR_TREO680_USB_PULLUP	114
+#define GPIO_NR_TREO680_GSM_POWER	40
+#define GPIO_NR_TREO680_GSM_RESET	87
+#define GPIO_NR_TREO680_GSM_WAKE	57
+#define GPIO_NR_TREO680_GSM_HOST_WAKE	14
+#define GPIO_NR_TREO680_GSM_TRIGGER	10
+#define GPIO_NR_TREO680_BT_EN		43
+#define GPIO_NR_TREO680_IR_EN		115
+#define GPIO_NR_TREO680_IR_TXD		47
+#define GPIO_NR_TREO680_BL_POWER	38
+#define GPIO_NR_TREO680_LCD_POWER	25
+
+/* Various addresses  */
+#define TREO680_PHYS_RAM_START	0xa0000000
+#define TREO680_PHYS_IO_START	0x40000000
+#define TREO680_STR_BASE	0xa2000000
+
+/* BACKLIGHT */
+#define TREO680_MAX_INTENSITY		254
+#define TREO680_DEFAULT_INTENSITY	160
+#define TREO680_LIMIT_MASK		0x7F
+#define TREO680_PRESCALER		63
+#define TREO680_PERIOD_NS		3500
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/uncompress.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/uncompress.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/include/mach/uncompress.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/include/mach/uncompress.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,8 @@
 static inline void arch_decomp_setup(void)
 {
 	if (machine_is_littleton() || machine_is_intelmote2()
-			|| machine_is_csb726())
+	    || machine_is_csb726() || machine_is_stargate2()
+	    || machine_is_cm_x300())
 		UART = STUART;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-pxa/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -51,6 +51,12 @@
 	select IWMMXT
 	select PXA_HAVE_BOARD_IRQS
 
+config MACH_STARGATE2
+	bool "Intel Stargate 2 Platform"
+	select PXA27x
+	select IWMMXT
+	select PXA_HAVE_BOARD_IRQS
+
 config ARCH_LUBBOCK
 	bool "Intel DBPXA250 Development Platform"
 	select PXA25x
@@ -88,6 +94,10 @@
 	  SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
 	  handheld computer.
 
+config SHARPSL_PM
+	bool
+	select APM_EMULATION
+
 config CORGI_SSP_DEPRECATED
 	bool
 	select PXA_SSP
@@ -280,6 +290,7 @@
 	select PXA3xx
 	select PXA_SSP
 	select HAVE_PWM
+	select PXA_HAVE_BOARD_IRQS
 
 config MACH_LITTLETON
 	bool "PXA3xx Form Factor Platform (aka Littleton)"
@@ -308,6 +319,14 @@
 	select PXA3xx
 	select CPU_PXA300
 
+config MACH_H4700
+	bool "HP iPAQ hx4700"
+	select PXA27x
+	select IWMMXT
+	select PXA_SSP
+	select HAVE_PWM
+	select PXA_HAVE_BOARD_IRQS
+
 config MACH_MAGICIAN
 	bool "Enable HTC Magician Support"
 	select PXA27x
@@ -382,6 +401,16 @@
 	  Say Y here if you intend to run this kernel on Palm Zire 72
 	  handheld computer.
 
+config MACH_TREO680
+	bool "Palm Treo 680"
+	default y
+	depends on ARCH_PXA_PALM
+	select PXA27x
+	select IWMMXT
+	help
+	  Say Y here if you intend to run this kernel on Palm Treo 680
+	  smartphone.
+
 config MACH_PALMLD
 	bool "Palm LifeDrive"
 	default y
@@ -505,12 +534,6 @@
 	help
 	  Enable support for PXA2xx SSP ports
 
-config PXA_PWM
-	tristate
-	default BACKLIGHT_PWM
-	help
-	  Enable support for PXA2xx/PXA3xx PWM controllers
-
 config TOSA_BT
 	tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
 	depends on MACH_TOSA
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/littleton.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/littleton.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/littleton.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/littleton.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,14 +42,17 @@
 #include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/ssp.h>
+#include <mach/mmc.h>
 #include <mach/pxa2xx_spi.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/pxa3xx_nand.h>
 #include <mach/littleton.h>
 
 #include "generic.h"
 
+#define GPIO_MMC1_CARD_DETECT	mfp_to_gpio(MFP_PIN_GPIO15)
+
 /* Littleton MFP configurations */
 static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
 	/* LCD */
@@ -98,6 +101,15 @@
 	GPIO123_KP_MKOUT_2,
 	GPIO124_KP_MKOUT_3,
 	GPIO125_KP_MKOUT_4,
+
+	/* MMC1 */
+	GPIO3_MMC1_DAT0,
+	GPIO4_MMC1_DAT1,
+	GPIO5_MMC1_DAT2,
+	GPIO6_MMC1_DAT3,
+	GPIO7_MMC1_CLK,
+	GPIO8_MMC1_CMD,
+	GPIO15_GPIO, /* card detect */
 };
 
 static struct resource smc91x_resources[] = {
@@ -179,15 +191,10 @@
 	.num_chipselect		= 1,
 };
 
-static void littleton_tdo24m_cs(u32 cmd)
-{
-	gpio_set_value(LITTLETON_GPIO_LCD_CS, !(cmd == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip littleton_tdo24m_chip = {
 	.rx_threshold	= 1,
 	.tx_threshold	= 1,
-	.cs_control	= littleton_tdo24m_cs,
+	.gpio_cs	= LITTLETON_GPIO_LCD_CS,
 };
 
 static struct spi_board_info littleton_spi_devices[] __initdata = {
@@ -202,16 +209,6 @@
 
 static void __init littleton_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(LITTLETON_GPIO_LCD_CS, "LCD_CS");
-	if (err) {
-		pr_warning("failed to request GPIO for LCS CS\n");
-		return;
-	}
-
-	gpio_direction_output(LITTLETON_GPIO_LCD_CS, 1);
-
 	pxa2xx_set_spi_info(2, &littleton_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(littleton_spi_devices));
 }
@@ -267,6 +264,56 @@
 static inline void littleton_init_keypad(void) {}
 #endif
 
+#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+static int littleton_mci_init(struct device *dev,
+			      irq_handler_t littleton_detect_int, void *data)
+{
+	int err, gpio_cd = GPIO_MMC1_CARD_DETECT;
+
+	err = gpio_request(gpio_cd, "mmc card detect");
+	if (err)
+		goto err_request_cd;
+
+	gpio_direction_input(gpio_cd);
+
+	err = request_irq(gpio_to_irq(gpio_cd), littleton_detect_int,
+			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+			  "mmc card detect", data);
+	if (err) {
+		dev_err(dev, "failed to request card detect IRQ\n");
+		goto err_request_irq;
+	}
+	return 0;
+
+err_request_irq:
+	gpio_free(gpio_cd);
+err_request_cd:
+	return err;
+}
+
+static void littleton_mci_exit(struct device *dev, void *data)
+{
+	int gpio_cd = GPIO_MMC1_CARD_DETECT;
+
+	free_irq(gpio_to_irq(gpio_cd), data);
+	gpio_free(gpio_cd);
+}
+
+static struct pxamci_platform_data littleton_mci_platform_data = {
+	.detect_delay	= 20,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.init 		= littleton_mci_init,
+	.exit		= littleton_mci_exit,
+};
+
+static void __init littleton_init_mmc(void)
+{
+	pxa_set_mci_info(&littleton_mci_platform_data);
+}
+#else
+static inline void littleton_init_mmc(void) {}
+#endif
+
 #if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
 static struct mtd_partition littleton_nand_partitions[] = {
 	[0] = {
@@ -407,6 +454,7 @@
 
 	littleton_init_spi();
 	littleton_init_i2c();
+	littleton_init_mmc();
 	littleton_init_lcd();
 	littleton_init_keypad();
 	littleton_init_nand();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/magician.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/magician.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/magician.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/magician.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,7 @@
 #include <mach/pxa27x.h>
 #include <mach/magician.h>
 #include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
@@ -745,6 +745,14 @@
 };
 
 /*
+ * I2C
+ */
+
+static struct i2c_pxa_platform_data i2c_info = {
+	.fast_mode = 1,
+};
+
+/*
  * Platform devices
  */
 
@@ -771,7 +779,7 @@
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(devices));
 
 	err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN");
 	if (!err) {
@@ -779,7 +787,7 @@
 		pxa_set_ficp_info(&magician_ficp_info);
 	}
 	pxa27x_set_i2c_power_info(NULL);
-	pxa_set_i2c_info(NULL);
+	pxa_set_i2c_info(&i2c_info);
 	pxa_set_mci_info(&magician_mci_info);
 	pxa_set_ohci_info(&magician_ohci_info);
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/mainstone.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/mainstone.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/mainstone.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/mainstone.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 #include <mach/mainstone.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-pxa/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,6 @@
 
 # Generic drivers that other drivers may depend upon
 obj-$(CONFIG_PXA_SSP)		+= ssp.o
-obj-$(CONFIG_PXA_PWM)		+= pwm.o
 
 # SoC-specific code
 obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o pxa2xx.o pxa25x.o
@@ -47,6 +46,7 @@
 obj-$(CONFIG_MACH_PCM990_BASEBOARD)	+= pcm990-baseboard.o
 obj-$(CONFIG_MACH_TOSA)		+= tosa.o
 obj-$(CONFIG_MACH_EM_X270)	+= em-x270.o
+obj-$(CONFIG_MACH_H4700)	+= hx4700.o
 obj-$(CONFIG_MACH_MAGICIAN)	+= magician.o
 obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
 obj-$(CONFIG_MACH_MIOA701)	+= mioa701.o mioa701_bootresume.o
@@ -62,6 +62,7 @@
 obj-$(CONFIG_MACH_PALMTX)	+= palmtx.o
 obj-$(CONFIG_MACH_PALMLD)	+= palmld.o
 obj-$(CONFIG_MACH_PALMZ72)	+= palmz72.o
+obj-$(CONFIG_MACH_TREO680)	+= treo680.o
 obj-$(CONFIG_ARCH_VIPER)	+= viper.o
 
 ifeq ($(CONFIG_MACH_ZYLONITE),y)
@@ -78,6 +79,7 @@
 obj-$(CONFIG_PXA_EZX)           += ezx.o
 
 obj-$(CONFIG_MACH_INTELMOTE2)   += imote2.o
+obj-$(CONFIG_MACH_STARGATE2)	+= stargate2.o
 obj-$(CONFIG_MACH_CSB726)	+= csb726.o
 obj-$(CONFIG_CSB726_CSB701)	+= csb701.o
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/mioa701.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/mioa701.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/mioa701.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/mioa701.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,7 @@
 #include <linux/wm97xx_batt.h>
 #include <linux/mtd/physmap.h>
 #include <linux/usb/gpio_vbus.h>
+#include <linux/regulator/max1586.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -48,7 +49,7 @@
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <media/soc_camera.h>
@@ -717,6 +718,38 @@
 };
 
 /*
+ * Voltage regulation
+ */
+static struct regulator_consumer_supply max1586_consumers[] = {
+	{
+		.supply = "vcc_core",
+	}
+};
+
+static struct regulator_init_data max1586_v3_info = {
+	.constraints = {
+		.name = "vcc_core range",
+		.min_uV = 1000000,
+		.max_uV = 1705000,
+		.always_on = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(max1586_consumers),
+	.consumer_supplies = max1586_consumers,
+};
+
+static struct max1586_subdev_data max1586_subdevs[] = {
+	{ .name = "vcc_core", .id = MAX1586_V3,
+	  .platform_data = &max1586_v3_info },
+};
+
+static struct max1586_platform_data max1586_info = {
+	.subdevs = max1586_subdevs,
+	.num_subdevs = ARRAY_SIZE(max1586_subdevs),
+	.v3_gain = MAX1586_GAIN_NO_R24, /* 700..1475 mV */
+};
+
+/*
  * Camera interface
  */
 struct pxacamera_platform_data mioa701_pxacamera_platform_data = {
@@ -725,6 +758,13 @@
 	.mclk_10khz = 5000,
 };
 
+static struct i2c_board_info __initdata mioa701_pi2c_devices[] = {
+	{
+		I2C_BOARD_INFO("max1586", 0x14),
+		.platform_data = &max1586_info,
+	},
+};
+
 static struct soc_camera_link iclink = {
 	.bus_id	= 0, /* Must match id in pxa27x_device_camera in device.c */
 };
@@ -798,7 +838,7 @@
 	arm_machine_restart('s', cmd);
 }
 
-struct gpio_ress global_gpios[] = {
+static struct gpio_ress global_gpios[] = {
 	MIO_GPIO_OUT(GPIO9_CHARGE_EN, 1, "Charger enable"),
 	MIO_GPIO_OUT(GPIO18_POWEROFF, 0, "Power Off"),
 	MIO_GPIO_OUT(GPIO87_LCD_POWER, 0, "LCD Power")
@@ -825,7 +865,9 @@
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 	gsm_init();
 
+	i2c_register_board_info(1, ARRAY_AND_SIZE(mioa701_pi2c_devices));
 	pxa_set_i2c_info(&i2c_pdata);
+	pxa27x_set_i2c_power_info(NULL);
 	pxa_set_camera_info(&mioa701_pxacamera_platform_data);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices));
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmld.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmld.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmld.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmld.c	2009-09-09 18:13:59.000000000 -0400
@@ -128,8 +128,12 @@
 	GPIO38_GPIO,	/* wifi ready */
 	GPIO81_GPIO,	/* wifi reset */
 
+	/* FFUART */
+	GPIO34_FFUART_RXD,
+	GPIO39_FFUART_TXD,
+
 	/* HDD */
-	GPIO95_GPIO,	/* HDD irq */
+	GPIO98_GPIO,	/* HDD reset */
 	GPIO115_GPIO,	/* HDD power */
 
 	/* MISC */
@@ -496,6 +500,14 @@
 };
 
 /******************************************************************************
+ * HDD
+ ******************************************************************************/
+static struct platform_device palmld_hdd = {
+	.name	= "pata_palmld",
+	.id	= -1,
+};
+
+/******************************************************************************
  * Framebuffer
  ******************************************************************************/
 static struct pxafb_mode_info palmld_lcd_modes[] = {
@@ -524,30 +536,18 @@
 /******************************************************************************
  * Power management - standby
  ******************************************************************************/
-#ifdef CONFIG_PM
-static u32 *addr __initdata;
-static u32 resume[3] __initdata = {
-	0xe3a00101,	/* mov	r0,	#0x40000000 */
-	0xe380060f,	/* orr	r0, r0, #0x00f00000 */
-	0xe590f008,	/* ldr	pc, [r0, #0x08] */
-};
-
-static int __init palmld_pm_init(void)
+static void __init palmld_pm_init(void)
 {
-	int i;
-
-	/* this is where the bootloader jumps */
-	addr = phys_to_virt(PALMLD_STR_BASE);
-
-	for (i = 0; i < 3; i++)
-		addr[i] = resume[i];
+	static u32 resume[] = {
+		0xe3a00101,	/* mov	r0,	#0x40000000 */
+		0xe380060f,	/* orr	r0, r0, #0x00f00000 */
+		0xe590f008,	/* ldr	pc, [r0, #0x08] */
+	};
 
-	return 0;
+	/* copy the bootloader */
+	memcpy(phys_to_virt(PALMLD_STR_BASE), resume, sizeof(resume));
 }
 
-device_initcall(palmld_pm_init);
-#endif
-
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -559,6 +559,7 @@
 	&palmld_leds,
 	&power_supply,
 	&palmld_asoc,
+	&palmld_hdd,
 };
 
 static struct map_desc palmld_io_desc[] __initdata = {
@@ -586,6 +587,7 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmld_pin_config));
 
+	palmld_pm_init();
 	set_pxa_fb_info(&palmld_lcd_screen);
 	pxa_set_mci_info(&palmld_mci_platform_data);
 	pxa_set_ac97_info(&palmld_ac97_pdata);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmt5.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmt5.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmt5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmt5.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/gpio.h>
 #include <linux/wm97xx_batt.h>
 #include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -110,6 +111,10 @@
 	/* PWM */
 	GPIO16_PWM0_OUT,
 
+	/* FFUART */
+	GPIO34_FFUART_RXD,
+	GPIO39_FFUART_TXD,
+
 	/* MISC */
 	GPIO10_GPIO,	/* hotsync button */
 	GPIO90_GPIO,	/* power detect */
@@ -343,11 +348,18 @@
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmt5_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmt5_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMT5_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
 	.gpio_pullup		= GPIO_NR_PALMT5_USB_PULLUP,
-	.gpio_pullup_inverted	= 0,
+};
+
+static struct platform_device palmt5_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmt5_udc_info,
+	},
 };
 
 /******************************************************************************
@@ -466,30 +478,18 @@
 /******************************************************************************
  * Power management - standby
  ******************************************************************************/
-#ifdef CONFIG_PM
-static u32 *addr __initdata;
-static u32 resume[3] __initdata = {
-	0xe3a00101,	/* mov	r0,	#0x40000000 */
-	0xe380060f,	/* orr	r0, r0, #0x00f00000 */
-	0xe590f008,	/* ldr	pc, [r0, #0x08] */
-};
-
-static int __init palmt5_pm_init(void)
+static void __init palmt5_pm_init(void)
 {
-	int i;
-
-	/* this is where the bootloader jumps */
-	addr = phys_to_virt(PALMT5_STR_BASE);
-
-	for (i = 0; i < 3; i++)
-		addr[i] = resume[i];
+	static u32 resume[] = {
+		0xe3a00101,	/* mov	r0,	#0x40000000 */
+		0xe380060f,	/* orr	r0, r0, #0x00f00000 */
+		0xe590f008,	/* ldr	pc, [r0, #0x08] */
+	};
 
-	return 0;
+	/* copy the bootloader */
+	memcpy(phys_to_virt(PALMT5_STR_BASE), resume, sizeof(resume));
 }
 
-device_initcall(palmt5_pm_init);
-#endif
-
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -500,6 +500,7 @@
 	&palmt5_backlight,
 	&power_supply,
 	&palmt5_asoc,
+	&palmt5_gpio_vbus,
 };
 
 /* setup udc GPIOs initial state */
@@ -515,14 +516,15 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config));
 
+	palmt5_pm_init();
 	set_pxa_fb_info(&palmt5_lcd_screen);
 	pxa_set_mci_info(&palmt5_mci_platform_data);
 	palmt5_udc_init();
 	pxa_set_ac97_info(&palmt5_ac97_pdata);
-	pxa_set_udc_info(&palmt5_udc_info);
 	pxa_set_ficp_info(&palmt5_ficp_platform_data);
 	pxa_set_keypad_info(&palmt5_keypad_platform_data);
 	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmte2.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmte2.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmte2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmte2.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/wm97xx_batt.h>
 #include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -37,6 +38,7 @@
 #include <mach/mfp-pxa25x.h>
 #include <mach/irda.h>
 #include <mach/udc.h>
+#include <mach/palmasoc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -107,6 +109,7 @@
 	GPIO1_RST,	/* reset */
 	GPIO4_GPIO,	/* Hotsync button */
 	GPIO9_GPIO,	/* power detect */
+	GPIO15_GPIO,	/* earphone detect */
 	GPIO37_GPIO,	/* LCD power */
 	GPIO56_GPIO,	/* Backlight power */
 };
@@ -318,11 +321,18 @@
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmte2_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmte2_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMTE2_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
 	.gpio_pullup		= GPIO_NR_PALMTE2_USB_PULLUP,
-	.gpio_pullup_inverted	= 0,
+};
+
+static struct platform_device palmte2_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmte2_udc_info,
+	},
 };
 
 /******************************************************************************
@@ -395,6 +405,21 @@
 };
 
 /******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+static struct palm27x_asoc_info palmte2_asoc_pdata = {
+	.jack_gpio	= GPIO_NR_PALMTE2_EARPHONE_DETECT,
+};
+
+static struct platform_device palmte2_asoc = {
+	.name = "palm27x-asoc",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &palmte2_asoc_pdata,
+	},
+};
+
+/******************************************************************************
  * Framebuffer
  ******************************************************************************/
 static struct pxafb_mode_info palmte2_lcd_modes[] = {
@@ -429,6 +454,8 @@
 #endif
 	&palmte2_backlight,
 	&power_supply,
+	&palmte2_asoc,
+	&palmte2_gpio_vbus,
 };
 
 /* setup udc GPIOs initial state */
@@ -447,7 +474,6 @@
 	set_pxa_fb_info(&palmte2_lcd_screen);
 	pxa_set_mci_info(&palmte2_mci_platform_data);
 	palmte2_udc_init();
-	pxa_set_udc_info(&palmte2_udc_info);
 	pxa_set_ac97_info(NULL);
 	pxa_set_ficp_info(&palmte2_ficp_platform_data);
 	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmtx.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmtx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmtx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmtx.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/gpio.h>
 #include <linux/wm97xx_batt.h>
 #include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -126,6 +127,10 @@
 	GPIO76_LCD_PCLK,
 	GPIO77_LCD_BIAS,
 
+	/* FFUART */
+	GPIO34_FFUART_RXD,
+	GPIO39_FFUART_TXD,
+
 	/* MISC. */
 	GPIO10_GPIO,	/* hotsync button */
 	GPIO12_GPIO,	/* power detect */
@@ -359,11 +364,18 @@
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmtx_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMTX_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
 	.gpio_pullup		= GPIO_NR_PALMTX_USB_PULLUP,
-	.gpio_pullup_inverted	= 0,
+};
+
+static struct platform_device palmtx_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmtx_udc_info,
+	},
 };
 
 /******************************************************************************
@@ -483,30 +495,18 @@
 /******************************************************************************
  * Power management - standby
  ******************************************************************************/
-#ifdef CONFIG_PM
-static u32 *addr __initdata;
-static u32 resume[3] __initdata = {
-	0xe3a00101,	/* mov	r0,	#0x40000000 */
-	0xe380060f,	/* orr	r0, r0, #0x00f00000 */
-	0xe590f008,	/* ldr	pc, [r0, #0x08] */
-};
-
-static int __init palmtx_pm_init(void)
+static void __init palmtx_pm_init(void)
 {
-	int i;
-
-	/* this is where the bootloader jumps */
-	addr = phys_to_virt(PALMTX_STR_BASE);
-
-	for (i = 0; i < 3; i++)
-		addr[i] = resume[i];
+	static u32 resume[] = {
+		0xe3a00101,	/* mov	r0,	#0x40000000 */
+		0xe380060f,	/* orr	r0, r0, #0x00f00000 */
+		0xe590f008,	/* ldr	pc, [r0, #0x08] */
+	};
 
-	return 0;
+	/* copy the bootloader */
+	memcpy(phys_to_virt(PALMTX_STR_BASE), resume, sizeof(resume));
 }
 
-device_initcall(palmtx_pm_init);
-#endif
-
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -517,6 +517,7 @@
 	&palmtx_backlight,
 	&power_supply,
 	&palmtx_asoc,
+	&palmtx_gpio_vbus,
 };
 
 static struct map_desc palmtx_io_desc[] __initdata = {
@@ -548,11 +549,11 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
 
+	palmtx_pm_init();
 	set_pxa_fb_info(&palmtx_lcd_screen);
 	pxa_set_mci_info(&palmtx_mci_platform_data);
 	palmtx_udc_init();
 	pxa_set_ac97_info(&palmtx_ac97_pdata);
-	pxa_set_udc_info(&palmtx_udc_info);
 	pxa_set_ficp_info(&palmtx_ficp_platform_data);
 	pxa_set_keypad_info(&palmtx_keypad_platform_data);
 	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmz72.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmz72.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/palmz72.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/palmz72.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,9 @@
 #include <linux/pda_power.h>
 #include <linux/pwm_backlight.h>
 #include <linux/gpio.h>
+#include <linux/wm97xx_batt.h>
 #include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -41,6 +43,8 @@
 #include <mach/irda.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/udc.h>
+#include <mach/palmasoc.h>
+
 #include <mach/pm.h>
 
 #include "generic.h"
@@ -66,6 +70,8 @@
 	GPIO29_AC97_SDATA_IN_0,
 	GPIO30_AC97_SDATA_OUT,
 	GPIO31_AC97_SYNC,
+	GPIO89_AC97_SYSCLK,
+	GPIO113_AC97_nRESET,
 
 	/* IrDA */
 	GPIO49_GPIO,	/* ir disable */
@@ -77,8 +83,7 @@
 
 	/* USB */
 	GPIO15_GPIO,	/* usb detect */
-	GPIO12_GPIO,	/* usb pullup */
-	GPIO95_GPIO,	/* usb power */
+	GPIO95_GPIO,	/* usb pullup */
 
 	/* Matrix keypad */
 	GPIO100_KP_MKIN_0	| WAKEUP_ON_LEVEL_HIGH,
@@ -355,6 +360,22 @@
 };
 
 /******************************************************************************
+ * UDC
+ ******************************************************************************/
+static struct gpio_vbus_mach_info palmz72_udc_info = {
+	.gpio_vbus		= GPIO_NR_PALMZ72_USB_DETECT_N,
+	.gpio_pullup		= GPIO_NR_PALMZ72_USB_PULLUP,
+};
+
+static struct platform_device palmz72_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmz72_udc_info,
+	},
+};
+
+/******************************************************************************
  * Power supply
  ******************************************************************************/
 static int power_supply_init(struct device *dev)
@@ -422,6 +443,31 @@
 };
 
 /******************************************************************************
+ * WM97xx battery
+ ******************************************************************************/
+static struct wm97xx_batt_info wm97xx_batt_pdata = {
+	.batt_aux	= WM97XX_AUX_ID3,
+	.temp_aux	= WM97XX_AUX_ID2,
+	.charge_gpio	= -1,
+	.max_voltage	= PALMZ72_BAT_MAX_VOLTAGE,
+	.min_voltage	= PALMZ72_BAT_MIN_VOLTAGE,
+	.batt_mult	= 1000,
+	.batt_div	= 414,
+	.temp_mult	= 1,
+	.temp_div	= 1,
+	.batt_tech	= POWER_SUPPLY_TECHNOLOGY_LIPO,
+	.batt_name	= "main-batt",
+};
+
+/******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+static struct platform_device palmz72_asoc = {
+	.name = "palm27x-asoc",
+	.id   = -1,
+};
+
+/******************************************************************************
  * Framebuffer
  ******************************************************************************/
 static struct pxafb_mode_info palmz72_lcd_modes[] = {
@@ -527,17 +573,32 @@
 static struct platform_device *devices[] __initdata = {
 	&palmz72_backlight,
 	&palmz72_leds,
+	&palmz72_asoc,
 	&power_supply,
+	&palmz72_gpio_vbus,
 };
 
+/* setup udc GPIOs initial state */
+static void __init palmz72_udc_init(void)
+{
+	if (!gpio_request(GPIO_NR_PALMZ72_USB_PULLUP, "USB Pullup")) {
+		gpio_direction_output(GPIO_NR_PALMZ72_USB_PULLUP, 0);
+		gpio_free(GPIO_NR_PALMZ72_USB_PULLUP);
+	}
+}
+
 static void __init palmz72_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmz72_pin_config));
+
 	set_pxa_fb_info(&palmz72_lcd_screen);
 	pxa_set_mci_info(&palmz72_mci_platform_data);
+	palmz72_udc_init();
 	pxa_set_ac97_info(NULL);
 	pxa_set_ficp_info(&palmz72_ficp_platform_data);
 	pxa_set_keypad_info(&palmz72_keypad_platform_data);
+	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pcm990-baseboard.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pcm990-baseboard.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pcm990-baseboard.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pcm990-baseboard.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,7 @@
 #include <media/soc_camera.h>
 
 #include <asm/gpio.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <asm/mach/map.h>
 #include <mach/pxa27x.h>
@@ -380,12 +380,12 @@
 	.gpio_base	= NR_BUILTIN_GPIO,
 };
 
-static int gpio_bus_switch;
+static int gpio_bus_switch = -EINVAL;
 
 static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
-		unsigned long flags)
+				       unsigned long flags)
 {
-	if (gpio_bus_switch <= 0) {
+	if (gpio_bus_switch < 0) {
 		if (flags == SOCAM_DATAWIDTH_10)
 			return 0;
 		else
@@ -404,25 +404,34 @@
 {
 	int ret;
 
-	if (!gpio_bus_switch) {
+	if (gpio_bus_switch < 0) {
 		ret = gpio_request(NR_BUILTIN_GPIO, "camera");
 		if (!ret) {
 			gpio_bus_switch = NR_BUILTIN_GPIO;
 			gpio_direction_output(gpio_bus_switch, 0);
-		} else
-			gpio_bus_switch = -EINVAL;
+		}
 	}
 
-	if (gpio_bus_switch > 0)
+	if (gpio_bus_switch >= 0)
 		return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
 	else
 		return SOCAM_DATAWIDTH_10;
 }
 
+static void pcm990_camera_free_bus(struct soc_camera_link *link)
+{
+	if (gpio_bus_switch < 0)
+		return;
+
+	gpio_free(gpio_bus_switch);
+	gpio_bus_switch = -EINVAL;
+}
+
 static struct soc_camera_link iclink = {
 	.bus_id	= 0, /* Must match with the camera ID above */
 	.query_bus_param = pcm990_camera_query_bus_param,
 	.set_bus_param = pcm990_camera_set_bus_param,
+	.free_bus = pcm990_camera_free_bus,
 };
 
 /* Board I2C devices. */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pm.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,7 +79,7 @@
 	return -EINVAL;
 }
 
-static int pxa_pm_prepare(void)
+int pxa_pm_prepare(void)
 {
 	int ret = 0;
 
@@ -89,7 +89,7 @@
 	return ret;
 }
 
-static void pxa_pm_finish(void)
+void pxa_pm_finish(void)
 {
 	if (pxa_cpu_pm_fns && pxa_cpu_pm_fns->finish)
 		pxa_cpu_pm_fns->finish();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/poodle.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/poodle.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/poodle.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/poodle.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
+#include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/mtd/sharpsl.h>
@@ -39,7 +40,7 @@
 #include <mach/pxa25x.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/poodle.h>
 #include <mach/pxafb.h>
@@ -214,13 +215,8 @@
 	.gpio_pendown		= POODLE_GPIO_TP_INT,
 };
 
-static void ads7846_cs(u32 command)
-{
-	gpio_set_value(POODLE_GPIO_TP_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip poodle_ads7846_chip = {
-	.cs_control		= ads7846_cs,
+	.gpio_cs		= POODLE_GPIO_TP_CS,
 };
 
 static struct spi_board_info poodle_spi_devices[] = {
@@ -236,14 +232,6 @@
 
 static void __init poodle_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(POODLE_GPIO_TP_CS, "ADS7846_CS");
-	if (err)
-		return;
-
-	gpio_direction_output(POODLE_GPIO_TP_CS, 1);
-
 	pxa2xx_set_spi_info(1, &poodle_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(poodle_spi_devices));
 }
@@ -499,6 +487,10 @@
 	&sharpsl_rom_device,
 };
 
+static struct i2c_board_info __initdata poodle_i2c_devices[] = {
+	{ I2C_BOARD_INFO("wm8731", 0x1b) },
+};
+
 static void poodle_poweroff(void)
 {
 	arm_machine_restart('h', NULL);
@@ -532,6 +524,7 @@
 	pxa_set_mci_info(&poodle_mci_platform_data);
 	pxa_set_ficp_info(&poodle_ficp_platform_data);
 	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(poodle_i2c_devices));
 	poodle_init_spi();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pwm.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pwm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pwm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pwm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,318 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/pwm.c
- *
- * simple driver for PWM (Pulse Width Modulator) controller
- *
- * 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.
- *
- * 2008-02-13	initial version
- * 		eric miao <eric.miao@marvell.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/pwm.h>
-
-#include <asm/div64.h>
-
-/* PWM registers and bits definitions */
-#define PWMCR		(0x00)
-#define PWMDCR		(0x04)
-#define PWMPCR		(0x08)
-
-#define PWMCR_SD	(1 << 6)
-#define PWMDCR_FD	(1 << 10)
-
-struct pwm_device {
-	struct list_head	node;
-	struct platform_device *pdev;
-
-	const char	*label;
-	struct clk	*clk;
-	int		clk_enabled;
-	void __iomem	*mmio_base;
-
-	unsigned int	use_count;
-	unsigned int	pwm_id;
-};
-
-/*
- * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
- * duty_ns   = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
- */
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
-{
-	unsigned long long c;
-	unsigned long period_cycles, prescale, pv, dc;
-
-	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
-		return -EINVAL;
-
-	c = clk_get_rate(pwm->clk);
-	c = c * period_ns;
-	do_div(c, 1000000000);
-	period_cycles = c;
-
-	if (period_cycles < 1)
-		period_cycles = 1;
-	prescale = (period_cycles - 1) / 1024;
-	pv = period_cycles / (prescale + 1) - 1;
-
-	if (prescale > 63)
-		return -EINVAL;
-
-	if (duty_ns == period_ns)
-		dc = PWMDCR_FD;
-	else
-		dc = (pv + 1) * duty_ns / period_ns;
-
-	/* NOTE: the clock to PWM has to be enabled first
-	 * before writing to the registers
-	 */
-	clk_enable(pwm->clk);
-	__raw_writel(prescale, pwm->mmio_base + PWMCR);
-	__raw_writel(dc, pwm->mmio_base + PWMDCR);
-	__raw_writel(pv, pwm->mmio_base + PWMPCR);
-	clk_disable(pwm->clk);
-
-	return 0;
-}
-EXPORT_SYMBOL(pwm_config);
-
-int pwm_enable(struct pwm_device *pwm)
-{
-	int rc = 0;
-
-	if (!pwm->clk_enabled) {
-		rc = clk_enable(pwm->clk);
-		if (!rc)
-			pwm->clk_enabled = 1;
-	}
-	return rc;
-}
-EXPORT_SYMBOL(pwm_enable);
-
-void pwm_disable(struct pwm_device *pwm)
-{
-	if (pwm->clk_enabled) {
-		clk_disable(pwm->clk);
-		pwm->clk_enabled = 0;
-	}
-}
-EXPORT_SYMBOL(pwm_disable);
-
-static DEFINE_MUTEX(pwm_lock);
-static LIST_HEAD(pwm_list);
-
-struct pwm_device *pwm_request(int pwm_id, const char *label)
-{
-	struct pwm_device *pwm;
-	int found = 0;
-
-	mutex_lock(&pwm_lock);
-
-	list_for_each_entry(pwm, &pwm_list, node) {
-		if (pwm->pwm_id == pwm_id) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (found) {
-		if (pwm->use_count == 0) {
-			pwm->use_count++;
-			pwm->label = label;
-		} else
-			pwm = ERR_PTR(-EBUSY);
-	} else
-		pwm = ERR_PTR(-ENOENT);
-
-	mutex_unlock(&pwm_lock);
-	return pwm;
-}
-EXPORT_SYMBOL(pwm_request);
-
-void pwm_free(struct pwm_device *pwm)
-{
-	mutex_lock(&pwm_lock);
-
-	if (pwm->use_count) {
-		pwm->use_count--;
-		pwm->label = NULL;
-	} else
-		pr_warning("PWM device already freed\n");
-
-	mutex_unlock(&pwm_lock);
-}
-EXPORT_SYMBOL(pwm_free);
-
-static inline void __add_pwm(struct pwm_device *pwm)
-{
-	mutex_lock(&pwm_lock);
-	list_add_tail(&pwm->node, &pwm_list);
-	mutex_unlock(&pwm_lock);
-}
-
-static struct pwm_device *pwm_probe(struct platform_device *pdev,
-		unsigned int pwm_id, struct pwm_device *parent_pwm)
-{
-	struct pwm_device *pwm;
-	struct resource *r;
-	int ret = 0;
-
-	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
-	if (pwm == NULL) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	pwm->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(pwm->clk)) {
-		ret = PTR_ERR(pwm->clk);
-		goto err_free;
-	}
-	pwm->clk_enabled = 0;
-
-	pwm->use_count = 0;
-	pwm->pwm_id = pwm_id;
-	pwm->pdev = pdev;
-
-	if (parent_pwm != NULL) {
-		/* registers for the second PWM has offset of 0x10 */
-		pwm->mmio_base = parent_pwm->mmio_base + 0x10;
-		__add_pwm(pwm);
-		return pwm;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (r == NULL) {
-		dev_err(&pdev->dev, "no memory resource defined\n");
-		ret = -ENODEV;
-		goto err_free_clk;
-	}
-
-	r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
-	if (r == NULL) {
-		dev_err(&pdev->dev, "failed to request memory resource\n");
-		ret = -EBUSY;
-		goto err_free_clk;
-	}
-
-	pwm->mmio_base = ioremap(r->start, r->end - r->start + 1);
-	if (pwm->mmio_base == NULL) {
-		dev_err(&pdev->dev, "failed to ioremap() registers\n");
-		ret = -ENODEV;
-		goto err_free_mem;
-	}
-
-	__add_pwm(pwm);
-	platform_set_drvdata(pdev, pwm);
-	return pwm;
-
-err_free_mem:
-	release_mem_region(r->start, r->end - r->start + 1);
-err_free_clk:
-	clk_put(pwm->clk);
-err_free:
-	kfree(pwm);
-	return ERR_PTR(ret);
-}
-
-static int __devinit pxa25x_pwm_probe(struct platform_device *pdev)
-{
-	struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
-
-	if (IS_ERR(pwm))
-		return PTR_ERR(pwm);
-
-	return 0;
-}
-
-static int __devinit pxa27x_pwm_probe(struct platform_device *pdev)
-{
-	struct pwm_device *pwm;
-
-	pwm = pwm_probe(pdev, pdev->id, NULL);
-	if (IS_ERR(pwm))
-		return PTR_ERR(pwm);
-
-	pwm = pwm_probe(pdev, pdev->id + 2, pwm);
-	if (IS_ERR(pwm))
-		return PTR_ERR(pwm);
-
-	return 0;
-}
-
-static int __devexit pwm_remove(struct platform_device *pdev)
-{
-	struct pwm_device *pwm;
-	struct resource *r;
-
-	pwm = platform_get_drvdata(pdev);
-	if (pwm == NULL)
-		return -ENODEV;
-
-	mutex_lock(&pwm_lock);
-	list_del(&pwm->node);
-	mutex_unlock(&pwm_lock);
-
-	iounmap(pwm->mmio_base);
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(r->start, r->end - r->start + 1);
-
-	clk_put(pwm->clk);
-	kfree(pwm);
-	return 0;
-}
-
-static struct platform_driver pxa25x_pwm_driver = {
-	.driver		= {
-		.name	= "pxa25x-pwm",
-	},
-	.probe		= pxa25x_pwm_probe,
-	.remove		= __devexit_p(pwm_remove),
-};
-
-static struct platform_driver pxa27x_pwm_driver = {
-	.driver		= {
-		.name	= "pxa27x-pwm",
-	},
-	.probe		= pxa27x_pwm_probe,
-	.remove		= __devexit_p(pwm_remove),
-};
-
-static int __init pwm_init(void)
-{
-	int ret = 0;
-
-	ret = platform_driver_register(&pxa25x_pwm_driver);
-	if (ret) {
-		printk(KERN_ERR "failed to register pxa25x_pwm_driver\n");
-		return ret;
-	}
-
-	ret = platform_driver_register(&pxa27x_pwm_driver);
-	if (ret) {
-		printk(KERN_ERR "failed to register pxa27x_pwm_driver\n");
-		return ret;
-	}
-
-	return ret;
-}
-arch_initcall(pwm_init);
-
-static void __exit pwm_exit(void)
-{
-	platform_driver_unregister(&pxa25x_pwm_driver);
-	platform_driver_unregister(&pxa27x_pwm_driver);
-}
-module_exit(pwm_exit);
-
-MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pxa27x.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pxa27x.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pxa27x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pxa27x.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,7 @@
 #include <mach/ohci.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -204,6 +204,23 @@
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
 
 /*
+ * allow platforms to override default PWRMODE setting used for PM_SUSPEND_MEM
+ */
+static unsigned int pwrmode = PWRMODE_SLEEP;
+
+int __init pxa27x_set_pwrmode(unsigned int mode)
+{
+	switch (mode) {
+	case PWRMODE_SLEEP:
+	case PWRMODE_DEEPSLEEP:
+		pwrmode = mode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/*
  * List of global PXA peripheral registers to preserve.
  * More ones like CP and general purpose register values are preserved
  * with the stack pointer in sleep.S.
@@ -254,7 +271,7 @@
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		pxa27x_cpu_suspend(PWRMODE_SLEEP);
+		pxa27x_cpu_suspend(pwrmode);
 		break;
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pxa3xx.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pxa3xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/pxa3xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/pxa3xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,7 @@
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/ssp.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -250,7 +250,7 @@
 static struct clk_lookup pxa3xx_clkregs[] = {
 	INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
 	/* Power I2C clock is always on */
-	INIT_CLKREG(&clk_dummy, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
 	INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL),
 	INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"),
 	INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"),
@@ -552,7 +552,7 @@
 }
 
 static struct platform_device *devices[] __initdata = {
-/*	&pxa_device_udc,	The UDC driver is PXA25x only */
+	&pxa27x_device_udc,
 	&pxa_device_ffuart,
 	&pxa_device_btuart,
 	&pxa_device_stuart,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/saar.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/saar.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/saar.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/saar.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/pxa930.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/pxafb.h>
 
 #include "devices.h"
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/sharpsl.h linux-libre-2.6.31-gnu/arch/arm/mach-pxa/sharpsl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/sharpsl.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/sharpsl.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
  *
  */
 
-#include <asm/hardware/sharpsl_pm.h>
+#include <mach/sharpsl_pm.h>
 
 /*
  * SharpSL SSP Driver
@@ -44,8 +44,6 @@
 
 extern struct battery_thresh spitz_battery_levels_acin[];
 extern struct battery_thresh spitz_battery_levels_noac[];
-void sharpsl_pm_pxa_init(void);
-void sharpsl_pm_pxa_remove(void);
 int sharpsl_pm_pxa_read_max1111(int channel);
 
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/sharpsl_pm.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/sharpsl_pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/sharpsl_pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/sharpsl_pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,20 +15,69 @@
 #undef DEBUG
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/apm-emulation.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/suspend.h>
+#include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/pm.h>
+#include <mach/pxa2xx-regs.h>
 #include <mach/pxa2xx-gpio.h>
+#include <mach/regs-rtc.h>
 #include <mach/sharpsl.h>
+#include <mach/sharpsl_pm.h>
+
 #include "sharpsl.h"
 
+/*
+ * Constants
+ */
+#define SHARPSL_CHARGE_ON_TIME_INTERVAL        (msecs_to_jiffies(1*60*1000))  /* 1 min */
+#define SHARPSL_CHARGE_FINISH_TIME             (msecs_to_jiffies(10*60*1000)) /* 10 min */
+#define SHARPSL_BATCHK_TIME                    (msecs_to_jiffies(15*1000))    /* 15 sec */
+#define SHARPSL_BATCHK_TIME_SUSPEND            (60*10)                        /* 10 min */
+
+#define SHARPSL_WAIT_CO_TIME                   15  /* 15 sec */
+#define SHARPSL_WAIT_DISCHARGE_ON              100 /* 100 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP   10  /* 10 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT   10  /* 10 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN   10  /* 10 msec */
+#define SHARPSL_CHARGE_WAIT_TIME               15  /* 15 msec */
+#define SHARPSL_CHARGE_CO_CHECK_TIME           5   /* 5 msec */
+#define SHARPSL_CHARGE_RETRY_CNT               1   /* eqv. 10 min */
+
+/*
+ * Prototypes
+ */
+#ifdef CONFIG_PM
+static int sharpsl_off_charge_battery(void);
+static int sharpsl_check_battery_voltage(void);
+static int sharpsl_fatal_check(void);
+#endif
+static int sharpsl_check_battery_temp(void);
+static int sharpsl_ac_check(void);
+static int sharpsl_average_value(int ad);
+static void sharpsl_average_clear(void);
+static void sharpsl_charge_toggle(struct work_struct *private_);
+static void sharpsl_battery_thread(struct work_struct *private_);
+
+
+/*
+ * Variables
+ */
+struct sharpsl_pm_status sharpsl_pm;
+static DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
+static DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
+DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
+
+
+
 struct battery_thresh spitz_battery_levels_acin[] = {
 	{ 213, 100},
 	{ 212,  98},
@@ -144,42 +193,789 @@
 #endif
 }
 
-void sharpsl_pm_pxa_init(void)
+static int get_percentage(int voltage)
 {
-	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN);
-	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN);
-	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN);
+	int i = sharpsl_pm.machinfo->bat_levels - 1;
+	int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
+	struct battery_thresh *thresh;
+
+	if (sharpsl_pm.charge_mode == CHRG_ON)
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
+	else
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
+
+	while (i > 0 && (voltage > thresh[i].voltage))
+		i--;
+
+	return thresh[i].percentage;
+}
+
+static int get_apm_status(int voltage)
+{
+	int low_thresh, high_thresh;
+
+	if (sharpsl_pm.charge_mode == CHRG_ON) {
+		high_thresh = sharpsl_pm.machinfo->status_high_acin;
+		low_thresh = sharpsl_pm.machinfo->status_low_acin;
+	} else {
+		high_thresh = sharpsl_pm.machinfo->status_high_noac;
+		low_thresh = sharpsl_pm.machinfo->status_low_noac;
+	}
+
+	if (voltage >= high_thresh)
+		return APM_BATTERY_STATUS_HIGH;
+	if (voltage >= low_thresh)
+		return APM_BATTERY_STATUS_LOW;
+	return APM_BATTERY_STATUS_CRITICAL;
+}
+
+void sharpsl_battery_kick(void)
+{
+	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
+}
+EXPORT_SYMBOL(sharpsl_battery_kick);
+
+
+static void sharpsl_battery_thread(struct work_struct *private_)
+{
+	int voltage, percent, apm_status, i = 0;
+
+	if (!sharpsl_pm.machinfo)
+		return;
+
+	sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
+
+	/* Corgi cannot confirm when battery fully charged so periodically kick! */
+	if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
+			&& time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
+		schedule_delayed_work(&toggle_charger, 0);
+
+	while(1) {
+		voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+
+		if (voltage > 0) break;
+		if (i++ > 5) {
+			voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
+			dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
+			break;
+		}
+	}
+
+	voltage = sharpsl_average_value(voltage);
+	apm_status = get_apm_status(voltage);
+	percent = get_percentage(voltage);
+
+	/* At low battery voltages, the voltage has a tendency to start
+           creeping back up so we try to avoid this here */
+	if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) ||  percent <= sharpsl_pm.battstat.mainbat_percent) {
+		sharpsl_pm.battstat.mainbat_voltage = voltage;
+		sharpsl_pm.battstat.mainbat_status = apm_status;
+		sharpsl_pm.battstat.mainbat_percent = percent;
+	}
+
+	dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage,
+			sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
+
+#ifdef CONFIG_BACKLIGHT_CORGI
+	/* If battery is low. limit backlight intensity to save power. */
+	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
+			&& ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
+			(sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
+		if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
+			sharpsl_pm.machinfo->backlight_limit(1);
+			sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
+		}
+	} else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
+		sharpsl_pm.machinfo->backlight_limit(0);
+		sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
+	}
+#endif
+
+	/* Suspend if critical battery level */
+	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
+			&& (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
+			&& !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
+		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
+		dev_err(sharpsl_pm.dev, "Fatal Off\n");
+		apm_queue_event(APM_CRITICAL_SUSPEND);
+	}
+
+	schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
+}
+
+void sharpsl_pm_led(int val)
+{
+	if (val == SHARPSL_LED_ERROR) {
+		dev_err(sharpsl_pm.dev, "Charging Error!\n");
+	} else if (val == SHARPSL_LED_ON) {
+		dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
+		led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
+	} else {
+		dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
+		led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
+	}
+}
+
+static void sharpsl_charge_on(void)
+{
+	dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
+
+	sharpsl_pm.full_count = 0;
+	sharpsl_pm.charge_mode = CHRG_ON;
+	schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
+	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
+}
+
+static void sharpsl_charge_off(void)
+{
+	dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
+
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm_led(SHARPSL_LED_OFF);
+	sharpsl_pm.charge_mode = CHRG_OFF;
+
+	schedule_delayed_work(&sharpsl_bat, 0);
+}
+
+static void sharpsl_charge_error(void)
+{
+	sharpsl_pm_led(SHARPSL_LED_ERROR);
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm.charge_mode = CHRG_ERROR;
+}
+
+static void sharpsl_charge_toggle(struct work_struct *private_)
+{
+	dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies);
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
+		sharpsl_charge_off();
+		return;
+	} else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
+		sharpsl_charge_error();
+		return;
+	}
+
+	sharpsl_pm_led(SHARPSL_LED_ON);
+	sharpsl_pm.machinfo->charge(0);
+	mdelay(SHARPSL_CHARGE_WAIT_TIME);
+	sharpsl_pm.machinfo->charge(1);
+
+	sharpsl_pm.charge_start_time = jiffies;
+}
+
+static void sharpsl_ac_timer(unsigned long data)
+{
+	int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
+
+	dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin);
+
+	sharpsl_average_clear();
+	if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
+		sharpsl_charge_on();
+	else if (sharpsl_pm.charge_mode == CHRG_ON)
+		sharpsl_charge_off();
+
+	schedule_delayed_work(&sharpsl_bat, 0);
+}
+
+
+static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id)
+{
+	/* Delay the event slightly to debounce */
+	/* Must be a smaller delay than the chrg_full_isr below */
+	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
+
+	return IRQ_HANDLED;
+}
+
+static void sharpsl_chrg_full_timer(unsigned long data)
+{
+	dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
+
+	sharpsl_pm.full_count++;
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
+		dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
+		if (sharpsl_pm.charge_mode == CHRG_ON)
+			sharpsl_charge_off();
+	} else if (sharpsl_pm.full_count < 2) {
+		dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
+		schedule_delayed_work(&toggle_charger, 0);
+	} else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
+		dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
+		schedule_delayed_work(&toggle_charger, 0);
+	} else {
+		sharpsl_charge_off();
+		sharpsl_pm.charge_mode = CHRG_DONE;
+		dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
+	}
+}
+
+/* Charging Finished Interrupt (Not present on Corgi) */
+/* Can trigger at the same time as an AC status change so
+   delay until after that has been processed */
+static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
+{
+	if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
+		return IRQ_HANDLED;
+
+	/* delay until after any ac interrupt */
+	mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id)
+{
+	int is_fatal = 0;
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) {
+		dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
+		is_fatal = 1;
+	}
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) {
+		dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
+		is_fatal = 1;
+	}
+
+	if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
+		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
+		apm_queue_event(APM_CRITICAL_SUSPEND);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Maintain an average of the last 10 readings
+ */
+#define SHARPSL_CNV_VALUE_NUM    10
+static int sharpsl_ad_index;
+
+static void sharpsl_average_clear(void)
+{
+	sharpsl_ad_index = 0;
+}
+
+static int sharpsl_average_value(int ad)
+{
+	int i, ad_val = 0;
+	static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
+
+	if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
+		sharpsl_ad_index = 0;
+		return ad;
+	}
+
+	sharpsl_ad[sharpsl_ad_index] = ad;
+	sharpsl_ad_index++;
+	if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
+		for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
+			sharpsl_ad[i] = sharpsl_ad[i+1];
+		sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
+	}
+	for (i=0; i < sharpsl_ad_index; i++)
+		ad_val += sharpsl_ad[i];
+
+	return (ad_val / sharpsl_ad_index);
+}
+
+/*
+ * Take an array of 5 integers, remove the maximum and minimum values
+ * and return the average.
+ */
+static int get_select_val(int *val)
+{
+	int i, j, k, temp, sum = 0;
+
+	/* Find MAX val */
+	temp = val[0];
+	j=0;
+	for (i=1; i<5; i++) {
+		if (temp < val[i]) {
+			temp = val[i];
+			j = i;
+		}
+	}
+
+	/* Find MIN val */
+	temp = val[4];
+	k=4;
+	for (i=3; i>=0; i--) {
+		if (temp > val[i]) {
+			temp = val[i];
+			k = i;
+		}
+	}
+
+	for (i=0; i<5; i++)
+		if (i != j && i != k )
+			sum += val[i];
+
+	dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]);
+
+	return (sum/3);
+}
+
+static int sharpsl_check_battery_temp(void)
+{
+	int val, i, buff[5];
+
+	/* Check battery temperature */
+	for (i=0; i<5; i++) {
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
+		sharpsl_pm.machinfo->measure_temp(1);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP);
+		sharpsl_pm.machinfo->measure_temp(0);
+	}
+
+	val = get_select_val(buff);
+
+	dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
+	if (val > sharpsl_pm.machinfo->charge_on_temp) {
+		printk(KERN_WARNING "Not charging: temperature out of limits.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int sharpsl_check_battery_voltage(void)
+{
+	int val, i, buff[5];
+
+	/* disable charge, enable discharge */
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm.machinfo->discharge(1);
+	mdelay(SHARPSL_WAIT_DISCHARGE_ON);
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(1);
+
+	/* Check battery voltage */
+	for (i=0; i<5; i++) {
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
+	}
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(0);
+
+	sharpsl_pm.machinfo->discharge(0);
+
+	val = get_select_val(buff);
+	dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
+
+	if (val < sharpsl_pm.machinfo->charge_on_volt)
+		return -1;
+
+	return 0;
+}
+#endif
+
+static int sharpsl_ac_check(void)
+{
+	int temp, i, buff[5];
+
+	for (i=0; i<5; i++) {
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
+	}
+
+	temp = get_select_val(buff);
+	dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
+
+	if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
+		dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	sharpsl_pm.flags |= SHARPSL_SUSPENDED;
+	flush_scheduled_work();
+
+	if (sharpsl_pm.charge_mode == CHRG_ON)
+		sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
+	else
+		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
+
+	return 0;
+}
+
+static int sharpsl_pm_resume(struct platform_device *pdev)
+{
+	/* Clear the reset source indicators as they break the bootloader upon reboot */
+	RCSR = 0x0f;
+	sharpsl_average_clear();
+	sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
+	sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
+
+	return 0;
+}
+
+static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
+{
+	dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR);
+
+	dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
+	/* not charging and AC-IN! */
+
+	if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
+		dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
+		sharpsl_pm.charge_mode = CHRG_OFF;
+		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
+		sharpsl_off_charge_battery();
+	}
+
+	sharpsl_pm.machinfo->presuspend();
+
+	PEDR = 0xffffffff; /* clear it */
+
+	sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
+	if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
+		RTSR &= RTSR_ALE;
+		RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
+		dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR);
+		sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
+	} else if (alarm_enable) {
+		RTSR &= RTSR_ALE;
+		RTAR = alarm_time;
+		dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR);
+	} else {
+		dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
+	}
+
+	pxa_pm_enter(state);
+
+	sharpsl_pm.machinfo->postsuspend();
+
+	dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR);
+}
+
+static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
+{
+	if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) )
+	{
+		if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
+			dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
+			corgi_goto_sleep(alarm_time, alarm_enable, state);
+			return 1;
+		}
+		if(sharpsl_off_charge_battery()) {
+			dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
+			corgi_goto_sleep(alarm_time, alarm_enable, state);
+			return 1;
+		}
+		dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
+	}
+
+	if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) )
+	{
+		dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
+		corgi_goto_sleep(alarm_time, alarm_enable, state);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int corgi_pxa_pm_enter(suspend_state_t state)
+{
+	unsigned long alarm_time = RTAR;
+	unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
+
+	dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
+
+	corgi_goto_sleep(alarm_time, alarm_status, state);
+
+	while (corgi_enter_suspend(alarm_time,alarm_status,state))
+		{}
+
+	if (sharpsl_pm.machinfo->earlyresume)
+		sharpsl_pm.machinfo->earlyresume();
+
+	dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
+
+	return 0;
+}
+
+/*
+ * Check for fatal battery errors
+ * Fatal returns -1
+ */
+static int sharpsl_fatal_check(void)
+{
+	int buff[5], temp, i, acin;
+
+	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
+
+	/* Check AC-Adapter */
+	acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
+
+	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
+		sharpsl_pm.machinfo->charge(0);
+		udelay(100);
+		sharpsl_pm.machinfo->discharge(1);	/* enable discharge */
+		mdelay(SHARPSL_WAIT_DISCHARGE_ON);
+	}
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(1);
+
+	/* Check battery : check inserting battery ? */
+	for (i=0; i<5; i++) {
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
+	}
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(0);
+
+	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
+		udelay(100);
+		sharpsl_pm.machinfo->charge(1);
+		sharpsl_pm.machinfo->discharge(0);
+	}
+
+	temp = get_select_val(buff);
+	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
+
+	if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
+			(!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
+		return -1;
+	return 0;
+}
+
+static int sharpsl_off_charge_error(void)
+{
+	dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm_led(SHARPSL_LED_ERROR);
+	sharpsl_pm.charge_mode = CHRG_ERROR;
+	return 1;
+}
+
+/*
+ * Charging Control while suspended
+ * Return 1 - go straight to sleep
+ * Return 0 - sleep or wakeup depending on other factors
+ */
+static int sharpsl_off_charge_battery(void)
+{
+	int time;
+
+	dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
+
+	if (sharpsl_pm.charge_mode == CHRG_OFF) {
+		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
+
+		/* AC Check */
+		if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
+			return sharpsl_off_charge_error();
+
+		/* Start Charging */
+		sharpsl_pm_led(SHARPSL_LED_ON);
+		sharpsl_pm.machinfo->charge(0);
+		mdelay(SHARPSL_CHARGE_WAIT_TIME);
+		sharpsl_pm.machinfo->charge(1);
+
+		sharpsl_pm.charge_mode = CHRG_ON;
+		sharpsl_pm.full_count = 0;
+
+		return 1;
+	} else if (sharpsl_pm.charge_mode != CHRG_ON) {
+		return 1;
+	}
+
+	if (sharpsl_pm.full_count == 0) {
+		int time;
+
+		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
+
+		if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
+			return sharpsl_off_charge_error();
+
+		sharpsl_pm.machinfo->charge(0);
+		mdelay(SHARPSL_CHARGE_WAIT_TIME);
+		sharpsl_pm.machinfo->charge(1);
+		sharpsl_pm.charge_mode = CHRG_ON;
+
+		mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
+
+		time = RCNR;
+		while(1) {
+			/* Check if any wakeup event had occurred */
+			if (sharpsl_pm.machinfo->charger_wakeup() != 0)
+				return 0;
+			/* Check for timeout */
+			if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
+				return 1;
+			if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
+				dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n");
+				sharpsl_pm.full_count++;
+				sharpsl_pm.machinfo->charge(0);
+				mdelay(SHARPSL_CHARGE_WAIT_TIME);
+				sharpsl_pm.machinfo->charge(1);
+				return 1;
+			}
+		}
+	}
+
+	dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
+
+	mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
+
+	time = RCNR;
+	while(1) {
+		/* Check if any wakeup event had occurred */
+		if (sharpsl_pm.machinfo->charger_wakeup() != 0)
+			return 0;
+		/* Check for timeout */
+		if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
+			if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
+				dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
+				sharpsl_pm.full_count = 0;
+			}
+			sharpsl_pm.full_count++;
+			return 1;
+		}
+		if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
+			dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
+			sharpsl_pm_led(SHARPSL_LED_OFF);
+			sharpsl_pm.machinfo->charge(0);
+			sharpsl_pm.charge_mode = CHRG_DONE;
+			return 1;
+		}
+	}
+}
+#else
+#define sharpsl_pm_suspend	NULL
+#define sharpsl_pm_resume	NULL
+#endif
+
+static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent);
+}
+
+static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage);
+}
+
+static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL);
+static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL);
+
+extern void (*apm_get_power_status)(struct apm_power_info *);
+
+static void sharpsl_apm_get_power_status(struct apm_power_info *info)
+{
+	info->ac_line_status = sharpsl_pm.battstat.ac_status;
+
+	if (sharpsl_pm.charge_mode == CHRG_ON)
+		info->battery_status = APM_BATTERY_STATUS_CHARGING;
+	else
+		info->battery_status = sharpsl_pm.battstat.mainbat_status;
+
+	info->battery_flag = (1 << info->battery_status);
+	info->battery_life = sharpsl_pm.battstat.mainbat_percent;
+}
+
+#ifdef CONFIG_PM
+static struct platform_suspend_ops sharpsl_pm_ops = {
+	.prepare	= pxa_pm_prepare,
+	.finish		= pxa_pm_finish,
+	.enter		= corgi_pxa_pm_enter,
+	.valid		= suspend_valid_only_mem,
+};
+#endif
+
+static int __init sharpsl_pm_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	sharpsl_pm.dev = &pdev->dev;
+	sharpsl_pm.machinfo = pdev->dev.platform_data;
+	sharpsl_pm.charge_mode = CHRG_OFF;
+	sharpsl_pm.flags = 0;
+
+	init_timer(&sharpsl_pm.ac_timer);
+	sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
+
+	init_timer(&sharpsl_pm.chrg_full_timer);
+	sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
+
+	led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
+
+	sharpsl_pm.machinfo->init();
+
+	gpio_request(sharpsl_pm.machinfo->gpio_acin, "AC IN");
+	gpio_direction_input(sharpsl_pm.machinfo->gpio_acin);
+	gpio_request(sharpsl_pm.machinfo->gpio_batfull, "Battery Full");
+	gpio_direction_input(sharpsl_pm.machinfo->gpio_batfull);
+	gpio_request(sharpsl_pm.machinfo->gpio_batlock, "Battery Lock");
+	gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock);
 
 	/* Register interrupt handlers */
-	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) {
+	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) {
 		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
 	}
-	else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH);
 
-	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) {
+	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) {
 		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
 	}
-	else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING);
 
 	if (sharpsl_pm.machinfo->gpio_fatal) {
-		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) {
+		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) {
 			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
 		}
-		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING);
 	}
 
 	if (sharpsl_pm.machinfo->batfull_irq)
 	{
 		/* Register interrupt handler. */
-		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) {
+		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) {
 			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
 		}
-		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING);
 	}
+
+	ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage);
+	ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage);
+	if (ret != 0)
+		dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret);
+
+	apm_get_power_status = sharpsl_apm_get_power_status;
+
+#ifdef CONFIG_PM
+	suspend_set_ops(&sharpsl_pm_ops);
+#endif
+
+	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
+
+	return 0;
 }
 
-void sharpsl_pm_pxa_remove(void)
+static int sharpsl_pm_remove(struct platform_device *pdev)
 {
+	suspend_set_ops(NULL);
+
+	device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
+	device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
+
+	led_trigger_unregister_simple(sharpsl_charge_led_trigger);
+
 	free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
 	free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
 
@@ -188,4 +984,39 @@
 
 	if (sharpsl_pm.machinfo->batfull_irq)
 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
+
+	gpio_free(sharpsl_pm.machinfo->gpio_batlock);
+	gpio_free(sharpsl_pm.machinfo->gpio_batfull);
+	gpio_free(sharpsl_pm.machinfo->gpio_acin);
+
+	if (sharpsl_pm.machinfo->exit)
+		sharpsl_pm.machinfo->exit();
+
+	del_timer_sync(&sharpsl_pm.chrg_full_timer);
+	del_timer_sync(&sharpsl_pm.ac_timer);
+
+	return 0;
+}
+
+static struct platform_driver sharpsl_pm_driver = {
+	.probe		= sharpsl_pm_probe,
+	.remove		= sharpsl_pm_remove,
+	.suspend	= sharpsl_pm_suspend,
+	.resume		= sharpsl_pm_resume,
+	.driver		= {
+		.name		= "sharpsl-pm",
+	},
+};
+
+static int __devinit sharpsl_pm_init(void)
+{
+	return platform_driver_register(&sharpsl_pm_driver);
 }
+
+static void sharpsl_pm_exit(void)
+{
+	platform_driver_unregister(&sharpsl_pm_driver);
+}
+
+late_initcall(sharpsl_pm_init);
+module_exit(sharpsl_pm_exit);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/spitz.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/spitz.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/spitz.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/spitz.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,19 +13,11 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
-#include <linux/mmc/host.h>
 #include <linux/mtd/physmap.h>
-#include <linux/pm.h>
-#include <linux/backlight.h>
-#include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/spi/spi.h>
@@ -34,31 +26,22 @@
 #include <linux/mtd/sharpsl.h>
 
 #include <asm/setup.h>
-#include <asm/memory.h>
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
+#include <asm/mach/sharpsl_param.h>
+#include <asm/hardware/scoop.h>
+
 
 #include <mach/pxa27x.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/reset.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/udc.h>
 #include <mach/pxafb.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/spitz.h>
-#include <mach/sharpsl.h>
-
-#include <asm/mach/sharpsl_param.h>
-#include <asm/hardware/scoop.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -317,13 +300,8 @@
 	.wait_for_sync		= spitz_wait_for_hsync,
 };
 
-static void spitz_ads7846_cs(u32 command)
-{
-	gpio_set_value(SPITZ_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip spitz_ads7846_chip = {
-	.cs_control		= spitz_ads7846_cs,
+	.gpio_cs		= SPITZ_GPIO_ADS7846_CS,
 };
 
 static void spitz_bl_kick_battery(void)
@@ -347,22 +325,12 @@
 	.kick_battery		= spitz_bl_kick_battery,
 };
 
-static void spitz_lcdcon_cs(u32 command)
-{
-	gpio_set_value(SPITZ_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip spitz_lcdcon_chip = {
-	.cs_control	= spitz_lcdcon_cs,
+	.gpio_cs	= SPITZ_GPIO_LCDCON_CS,
 };
 
-static void spitz_max1111_cs(u32 command)
-{
-	gpio_set_value(SPITZ_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip spitz_max1111_chip = {
-	.cs_control	= spitz_max1111_cs,
+	.gpio_cs	= SPITZ_GPIO_MAX1111_CS,
 };
 
 static struct spi_board_info spitz_spi_devices[] = {
@@ -392,30 +360,6 @@
 
 static void __init spitz_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(SPITZ_GPIO_ADS7846_CS, "ADS7846_CS");
-	if (err)
-		return;
-
-	err = gpio_request(SPITZ_GPIO_LCDCON_CS, "LCDCON_CS");
-	if (err)
-		goto err_free_1;
-
-	err = gpio_request(SPITZ_GPIO_MAX1111_CS, "MAX1111_CS");
-	if (err)
-		goto err_free_2;
-
-	err = gpio_direction_output(SPITZ_GPIO_ADS7846_CS, 1);
-	if (err)
-		goto err_free_3;
-	err = gpio_direction_output(SPITZ_GPIO_LCDCON_CS, 1);
-	if (err)
-		goto err_free_3;
-	err = gpio_direction_output(SPITZ_GPIO_MAX1111_CS, 1);
-	if (err)
-		goto err_free_3;
-
 	if (machine_is_akita()) {
 		spitz_lcdcon_info.gpio_backlight_cont = AKITA_GPIO_BACKLIGHT_CONT;
 		spitz_lcdcon_info.gpio_backlight_on = AKITA_GPIO_BACKLIGHT_ON;
@@ -423,14 +367,6 @@
 
 	pxa2xx_set_spi_info(2, &spitz_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices));
-	return;
-
-err_free_3:
-	gpio_free(SPITZ_GPIO_MAX1111_CS);
-err_free_2:
-	gpio_free(SPITZ_GPIO_LCDCON_CS);
-err_free_1:
-	gpio_free(SPITZ_GPIO_ADS7846_CS);
 }
 #else
 static inline void spitz_init_spi(void) {}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/spitz_pm.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/spitz_pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/spitz_pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/spitz_pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,6 @@
 {
 	pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN);
 	pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
-	sharpsl_pm_pxa_init();
 }
 
 static void spitz_measure_temp(int on)
@@ -182,7 +181,7 @@
 
 struct sharpsl_charger_machinfo spitz_pm_machinfo = {
 	.init             = spitz_charger_init,
-	.exit             = sharpsl_pm_pxa_remove,
+	.exit             = NULL,
 	.gpio_batlock     = SPITZ_GPIO_BAT_COVER,
 	.gpio_acin        = SPITZ_GPIO_AC_IN,
 	.gpio_batfull     = SPITZ_GPIO_CHRG_FULL,
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/stargate2.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/stargate2.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/stargate2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/stargate2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,796 @@
+/*
+ *  linux/arch/arm/mach-pxa/stargate2.c
+ *
+ *  Author:	Ed C. Epp
+ *  Created:	Nov 05, 2002
+ *  Copyright:	Intel Corp.
+ *
+ *  Modified 2009:  Jonathan Cameron <jic23@cam.ac.uk>
+ *
+ *  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.
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/i2c/pcf857x.h>
+#include <linux/i2c/at24.h>
+#include <linux/smc91x.h>
+#include <linux/gpio.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <mach/pxa27x.h>
+#include <plat/i2c.h>
+#include <mach/mmc.h>
+#include <mach/udc.h>
+#include <mach/pxa2xx_spi.h>
+#include <mach/pxa27x-udc.h>
+
+#include <linux/spi/spi.h>
+#include <linux/mfd/da903x.h>
+#include <linux/sht15.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* Bluetooth */
+#define SG2_BT_RESET		81
+
+/* SD */
+#define SG2_GPIO_nSD_DETECT	90
+#define SG2_SD_POWER_ENABLE	89
+
+static unsigned long stargate2_pin_config[] __initdata = {
+
+	GPIO15_nCS_1, /* SRAM */
+	/* SMC91x */
+	GPIO80_nCS_4,
+	GPIO40_GPIO, /*cable detect?*/
+	/* Device Identification for wakeup*/
+	GPIO102_GPIO,
+
+	/* Button */
+	GPIO91_GPIO | WAKEUP_ON_LEVEL_HIGH,
+
+	/* DA9030 */
+	GPIO1_GPIO,
+
+	/* Compact Flash */
+	GPIO79_PSKTSEL,
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO85_nPCE_1,
+	GPIO54_nPCE_2,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+	GPIO120_GPIO, /* Buff ctrl */
+	GPIO108_GPIO, /* Power ctrl */
+	GPIO82_GPIO, /* Reset */
+	GPIO53_GPIO, /* SG2_S0_GPIO_DETECT */
+
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO90_GPIO, /* nSD detect */
+	GPIO89_GPIO, /* SD_POWER_ENABLE */
+
+	/* Bluetooth */
+	GPIO81_GPIO, /* reset */
+
+	/* cc2420 802.15.4 radio */
+	GPIO22_GPIO,		/* CC_RSTN  (out)*/
+	GPIO114_GPIO,		/* CC_FIFO (in) */
+	GPIO116_GPIO, 		/* CC_CCA (in) */
+	GPIO0_GPIO,		/* CC_FIFOP (in) */
+	GPIO16_GPIO,		/* CCSFD (in) */
+	GPIO39_GPIO,		/* CSn (out) */
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* SSP 3 - 802.15.4 radio */
+	GPIO39_GPIO, /* chip select */
+	GPIO34_SSP3_SCLK,
+	GPIO35_SSP3_TXD,
+	GPIO41_SSP3_RXD,
+
+	/* SSP 2 */
+	GPIO11_SSP2_RXD,
+	GPIO38_SSP2_TXD,
+	GPIO36_SSP2_SCLK,
+	GPIO37_GPIO, /* chip select */
+
+	/* SSP 1 */
+	GPIO26_SSP1_RXD,
+	GPIO25_SSP1_TXD,
+	GPIO23_SSP1_SCLK,
+	GPIO24_GPIO, /* chip select */
+
+	/* BTUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	/* STUART */
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+
+	/* Basic sensor board */
+	GPIO96_GPIO,	/* accelerometer interrupt */
+	GPIO99_GPIO,	/* ADC interrupt */
+
+	/* Connector pins specified as gpios */
+	GPIO94_GPIO, /* large basic connector pin 14 */
+	GPIO10_GPIO, /* large basic connector pin 23 */
+
+	/* SHT15 */
+	GPIO100_GPIO,
+	GPIO98_GPIO,
+};
+
+/**
+ * stargate2_reset_bluetooth() reset the bluecore to ensure consistent state
+ **/
+static int stargate2_reset_bluetooth(void)
+{
+	int err;
+	err = gpio_request(SG2_BT_RESET, "SG2_BT_RESET");
+	if (err) {
+		printk(KERN_ERR "Could not get gpio for bluetooth reset \n");
+		return err;
+	}
+	gpio_direction_output(SG2_BT_RESET, 1);
+	mdelay(5);
+	/* now reset it - 5 msec minimum */
+	gpio_set_value(SG2_BT_RESET, 0);
+	mdelay(10);
+	gpio_set_value(SG2_BT_RESET, 1);
+	gpio_free(SG2_BT_RESET);
+	return 0;
+}
+
+static struct led_info stargate2_leds[] = {
+	{
+		.name = "sg2:red",
+		.flags = DA9030_LED_RATE_ON,
+	}, {
+		.name = "sg2:blue",
+		.flags = DA9030_LED_RATE_ON,
+	}, {
+		.name = "sg2:green",
+		.flags = DA9030_LED_RATE_ON,
+	},
+};
+
+static struct sht15_platform_data platform_data_sht15 = {
+	.gpio_data =  100,
+	.gpio_sck  =  98,
+};
+
+static struct platform_device sht15 = {
+	.name = "sht15",
+	.id = -1,
+	.dev = {
+		.platform_data = &platform_data_sht15,
+	},
+};
+
+static struct regulator_consumer_supply stargate2_sensor_3_con[] = {
+	{
+		.dev = &sht15.dev,
+		.supply = "vcc",
+	},
+};
+
+enum stargate2_ldos{
+	vcc_vref,
+	vcc_cc2420,
+	/* a mote connector? */
+	vcc_mica,
+	/* the CSR bluecore chip */
+	vcc_bt,
+	/* The two voltages available to sensor boards */
+	vcc_sensor_1_8,
+	vcc_sensor_3,
+	/* directly connected to the pxa27x */
+	vcc_sram_ext,
+	vcc_pxa_pll,
+	vcc_pxa_usim, /* Reference voltage for certain gpios */
+	vcc_pxa_mem,
+	vcc_pxa_flash,
+	vcc_pxa_core, /*Dc-Dc buck not yet supported */
+	vcc_lcd,
+	vcc_bb,
+	vcc_bbio, /*not sure!*/
+	vcc_io, /* cc2420 802.15.4 radio and pxa vcc_io ?*/
+};
+
+/* The values of the various regulator constraints are obviously dependent
+ * on exactly what is wired to each ldo.  Unfortunately this information is
+ * not generally available.  More information has been requested from Xbow.
+ */
+static struct regulator_init_data stargate2_ldo_init_data[] = {
+	[vcc_bbio] = {
+		.constraints = { /* board default 1.8V */
+			.name = "vcc_bbio",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_bb] = {
+		.constraints = { /* board default 2.8V */
+			.name = "vcc_bb",
+			.min_uV = 2700000,
+			.max_uV = 3000000,
+		},
+	},
+	[vcc_pxa_flash] = {
+		.constraints = {/* default is 1.8V */
+			.name = "vcc_pxa_flash",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_cc2420] = { /* also vcc_io */
+		.constraints = {
+			/* board default is 2.8V */
+			.name = "vcc_cc2420",
+			.min_uV = 2700000,
+			.max_uV = 3300000,
+		},
+	},
+	[vcc_vref] = { /* Reference for what? */
+		.constraints = { /* default 1.8V */
+			.name = "vcc_vref",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_sram_ext] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_sram_ext",
+			.min_uV = 2800000,
+			.max_uV = 2800000,
+		},
+	},
+	[vcc_mica] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_mica",
+			.min_uV = 2800000,
+			.max_uV = 2800000,
+		},
+	},
+	[vcc_bt] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_bt",
+			.min_uV = 2800000,
+			.max_uV = 2800000,
+		},
+	},
+	[vcc_lcd] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_lcd",
+			.min_uV = 2700000,
+			.max_uV = 3300000,
+		},
+	},
+	[vcc_io] = { /* Same or higher than everything
+			  * bar vccbat and vccusb */
+		.constraints = { /* default 2.8V */
+			.name = "vcc_io",
+			.min_uV = 2692000,
+			.max_uV = 3300000,
+		},
+	},
+	[vcc_sensor_1_8] = {
+		.constraints = { /* default 1.8V */
+			.name = "vcc_sensor_1_8",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_sensor_3] = { /* curiously default 2.8V */
+		.constraints = {
+			.name = "vcc_sensor_3",
+			.min_uV = 2800000,
+			.max_uV = 3000000,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(stargate2_sensor_3_con),
+		.consumer_supplies = stargate2_sensor_3_con,
+	},
+	[vcc_pxa_pll] = { /* 1.17V - 1.43V, default 1.3V*/
+		.constraints = {
+			.name = "vcc_pxa_pll",
+			.min_uV = 1170000,
+			.max_uV = 1430000,
+		},
+	},
+	[vcc_pxa_usim] = {
+		.constraints = { /* default 1.8V */
+			.name = "vcc_pxa_usim",
+			.min_uV = 1710000,
+			.max_uV = 2160000,
+		},
+	},
+	[vcc_pxa_mem] = {
+		.constraints = { /* default 1.8V */
+			.name = "vcc_pxa_mem",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+};
+
+static struct da903x_subdev_info stargate2_da9030_subdevs[] = {
+	{
+		.name = "da903x-led",
+		.id = DA9030_ID_LED_2,
+		.platform_data = &stargate2_leds[0],
+	}, {
+		.name = "da903x-led",
+		.id = DA9030_ID_LED_3,
+		.platform_data = &stargate2_leds[2],
+	}, {
+		.name = "da903x-led",
+		.id = DA9030_ID_LED_4,
+		.platform_data = &stargate2_leds[1],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO2,
+		.platform_data = &stargate2_ldo_init_data[vcc_bbio],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO3,
+		.platform_data = &stargate2_ldo_init_data[vcc_bb],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO4,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_flash],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO5,
+		.platform_data = &stargate2_ldo_init_data[vcc_cc2420],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO6,
+		.platform_data = &stargate2_ldo_init_data[vcc_vref],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO7,
+		.platform_data = &stargate2_ldo_init_data[vcc_sram_ext],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO8,
+		.platform_data = &stargate2_ldo_init_data[vcc_mica],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO9,
+		.platform_data = &stargate2_ldo_init_data[vcc_bt],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO10,
+		.platform_data = &stargate2_ldo_init_data[vcc_sensor_1_8],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO11,
+		.platform_data = &stargate2_ldo_init_data[vcc_sensor_3],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO12,
+		.platform_data = &stargate2_ldo_init_data[vcc_lcd],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO15,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_pll],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO17,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_usim],
+	}, {
+		.name = "da903x-regulator", /*pxa vcc i/o and cc2420 vcc i/o */
+		.id = DA9030_ID_LDO18,
+		.platform_data = &stargate2_ldo_init_data[vcc_io],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO19,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_mem],
+	},
+};
+
+static struct da903x_platform_data stargate2_da9030_pdata = {
+	.num_subdevs = ARRAY_SIZE(stargate2_da9030_subdevs),
+	.subdevs = stargate2_da9030_subdevs,
+};
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.name = "smc91x-regs",
+		.start = (PXA_CS4_PHYS + 0x300),
+		.end = (PXA_CS4_PHYS + 0xfffff),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_GPIO(40),
+		.end = IRQ_GPIO(40),
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+static struct smc91x_platdata stargate2_smc91x_info = {
+	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT
+	| SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
+static struct platform_device smc91x_device = {
+	.name = "smc91x",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(smc91x_resources),
+	.resource = smc91x_resources,
+	.dev = {
+		.platform_data = &stargate2_smc91x_info,
+	},
+};
+
+
+
+static struct pxamci_platform_data stargate2_mci_platform_data;
+
+/*
+ * The card detect interrupt isn't debounced so we delay it by 250ms
+ * to give the card a chance to fully insert / eject.
+ */
+static int stargate2_mci_init(struct device *dev,
+			      irq_handler_t stargate2_detect_int,
+			      void *data)
+{
+	int err;
+
+	err = gpio_request(SG2_SD_POWER_ENABLE, "SG2_sd_power_enable");
+	if (err) {
+		printk(KERN_ERR "Can't get the gpio for SD power control");
+		goto return_err;
+	}
+	gpio_direction_output(SG2_SD_POWER_ENABLE, 0);
+
+	err = gpio_request(SG2_GPIO_nSD_DETECT, "SG2_sd_detect");
+	if (err) {
+		printk(KERN_ERR "Can't get the sd detect gpio");
+		goto free_power_en;
+	}
+	gpio_direction_input(SG2_GPIO_nSD_DETECT);
+	/* Delay to allow for full insertion */
+	stargate2_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+	err = request_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT),
+			  stargate2_detect_int,
+			  IRQ_TYPE_EDGE_BOTH,
+			  "MMC card detect",
+			  data);
+	if (err) {
+		printk(KERN_ERR "can't request MMC card detect IRQ\n");
+		goto free_nsd_detect;
+	}
+	return 0;
+
+ free_nsd_detect:
+	gpio_free(SG2_GPIO_nSD_DETECT);
+ free_power_en:
+	gpio_free(SG2_SD_POWER_ENABLE);
+ return_err:
+	return err;
+}
+
+/**
+ * stargate2_mci_setpower() - set state of mmc power supply
+ *
+ * Very simple control. Either it is on or off and is controlled by
+ * a gpio pin */
+static void stargate2_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	gpio_set_value(SG2_SD_POWER_ENABLE, !!vdd);
+}
+
+static void stargate2_mci_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT), data);
+	gpio_free(SG2_SD_POWER_ENABLE);
+	gpio_free(SG2_GPIO_nSD_DETECT);
+}
+
+static struct pxamci_platform_data stargate2_mci_platform_data = {
+	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+	.init = stargate2_mci_init,
+	.setpower = stargate2_mci_setpower,
+	.exit = stargate2_mci_exit,
+};
+
+static struct mtd_partition stargate2flash_partitions[] = {
+	{
+		.name = "Bootloader",
+		.size = 0x00040000,
+		.offset = 0,
+		.mask_flags = 0,
+	}, {
+		.name = "Kernel",
+		.size = 0x00200000,
+		.offset = 0x00040000,
+		.mask_flags = 0
+	}, {
+		.name = "Filesystem",
+		.size = 0x01DC0000,
+		.offset = 0x00240000,
+		.mask_flags = 0
+	},
+};
+
+static struct resource flash_resources = {
+	.start = PXA_CS0_PHYS,
+	.end = PXA_CS0_PHYS + SZ_32M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct flash_platform_data stargate2_flash_data = {
+	.map_name = "cfi_probe",
+	.parts = stargate2flash_partitions,
+	.nr_parts = ARRAY_SIZE(stargate2flash_partitions),
+	.name = "PXA27xOnChipROM",
+	.width = 2,
+};
+
+static struct platform_device stargate2_flash_device = {
+	.name = "pxa2xx-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &stargate2_flash_data,
+	},
+	.resource = &flash_resources,
+	.num_resources = 1,
+};
+
+/*
+ * SRAM - The Stargate 2 has 32MB of SRAM.
+ *
+ * Here it is made available as an MTD. This will then
+ * typically have a cifs filesystem created on it to provide
+ * fast temporary storage.
+ */
+static struct resource sram_resources = {
+	.start = PXA_CS1_PHYS,
+	.end = PXA_CS1_PHYS + SZ_32M-1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platdata_mtd_ram stargate2_sram_pdata = {
+	.mapname = "Stargate2 SRAM",
+	.bankwidth = 2,
+};
+
+static struct platform_device stargate2_sram = {
+	.name = "mtd-ram",
+	.id = 0,
+	.resource = &sram_resources,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &stargate2_sram_pdata,
+	},
+};
+
+static struct pcf857x_platform_data platform_data_pcf857x = {
+	.gpio_base = 128,
+	.n_latch = 0,
+	.setup = NULL,
+	.teardown = NULL,
+	.context = NULL,
+};
+
+static struct at24_platform_data pca9500_eeprom_pdata = {
+	.byte_len = 256,
+	.page_size = 4,
+};
+
+
+static struct i2c_board_info __initdata stargate2_i2c_board_info[] = {
+	/* Techically this a pca9500 - but it's compatible with the 8574
+	 * for gpio expansion and the 24c02 for eeprom access.
+	 */
+	{
+		.type = "pcf8574",
+		.addr =  0x27,
+		.platform_data = &platform_data_pcf857x,
+	}, {
+		.type = "24c02",
+		.addr = 0x57,
+		.platform_data = &pca9500_eeprom_pdata,
+	}, {
+		.type = "max1238",
+		.addr = 0x35,
+	}, { /* ITS400 Sensor board only */
+		.type = "max1363",
+		.addr = 0x34,
+		/* Through a nand gate - Also beware, on V2 sensor board the
+		 * pull up resistors are missing.
+		 */
+		.irq = IRQ_GPIO(99),
+	}, { /* ITS400 Sensor board only */
+		.type = "tsl2561",
+		.addr = 0x49,
+		/* Through a nand gate - Also beware, on V2 sensor board the
+		 * pull up resistors are missing.
+		 */
+		.irq = IRQ_GPIO(99),
+	}, { /* ITS400 Sensor board only */
+		.type = "tmp175",
+		.addr = 0x4A,
+		.irq = IRQ_GPIO(96),
+	},
+};
+
+static struct i2c_board_info __initdata stargate2_pwr_i2c_board_info[] = {
+	{
+		.type = "da9030",
+		.addr = 0x49,
+		.platform_data = &stargate2_da9030_pdata,
+		.irq = gpio_to_irq(1),
+	},
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_0_info = {
+	.num_chipselect = 1,
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_1_info = {
+	.num_chipselect = 1,
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_2_info = {
+	.num_chipselect = 1,
+};
+
+/* An upcoming kernel change will scrap SFRM usage so these
+ * drivers have been moved to use gpio's via cs_control */
+static struct pxa2xx_spi_chip staccel_chip_info = {
+	.tx_threshold = 8,
+	.rx_threshold = 8,
+	.dma_burst_size = 8,
+	.timeout = 235,
+	.gpio_cs = 24,
+};
+
+static struct pxa2xx_spi_chip cc2420_info = {
+	.tx_threshold = 8,
+	.rx_threshold = 8,
+	.dma_burst_size = 8,
+	.timeout = 235,
+	.gpio_cs = 39,
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+	{
+		.modalias = "lis3l02dq",
+		.max_speed_hz = 8000000,/* 8MHz max spi frequency at 3V */
+		.bus_num = 1,
+		.chip_select = 0,
+		.controller_data = &staccel_chip_info,
+		.irq = IRQ_GPIO(96),
+	}, {
+		.modalias = "cc2420",
+		.max_speed_hz = 6500000,
+		.bus_num = 3,
+		.chip_select = 0,
+		.controller_data = &cc2420_info,
+	},
+};
+
+static void sg2_udc_command(int cmd)
+{
+	switch (cmd) {
+	case PXA2XX_UDC_CMD_CONNECT:
+		UP2OCR |=  UP2OCR_HXOE  | UP2OCR_DPPUE | UP2OCR_DPPUBE;
+		break;
+	case PXA2XX_UDC_CMD_DISCONNECT:
+		UP2OCR &= ~(UP2OCR_HXOE  | UP2OCR_DPPUE | UP2OCR_DPPUBE);
+		break;
+	}
+}
+
+/* Board doesn't support cable detection - so always lie and say
+ * something is there.
+ */
+static int sg2_udc_detect(void)
+{
+	return 1;
+}
+
+static struct pxa2xx_udc_mach_info stargate2_udc_info __initdata = {
+	.udc_is_connected	= sg2_udc_detect,
+	.udc_command		= sg2_udc_command,
+};
+
+static struct platform_device *stargate2_devices[] = {
+	&stargate2_flash_device,
+	&stargate2_sram,
+	&smc91x_device,
+	&sht15,
+};
+
+static struct i2c_pxa_platform_data i2c_pwr_pdata = {
+	.fast_mode = 1,
+};
+
+static struct i2c_pxa_platform_data i2c_pdata = {
+	.fast_mode = 1,
+};
+
+static void __init stargate2_init(void)
+{
+	/* This is probably a board specific hack as this must be set
+	   prior to connecting the MFP stuff up. */
+	MECR &= ~MECR_NOS;
+
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(stargate2_pin_config));
+
+	/* spi chip selects */
+	gpio_direction_output(37, 0);
+	gpio_direction_output(24, 0);
+	gpio_direction_output(39, 0);
+
+	platform_add_devices(ARRAY_AND_SIZE(stargate2_devices));
+
+	pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info);
+	pxa2xx_set_spi_info(2, &pxa_ssp_master_1_info);
+	pxa2xx_set_spi_info(3, &pxa_ssp_master_2_info);
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+	i2c_register_board_info(0, ARRAY_AND_SIZE(stargate2_i2c_board_info));
+	i2c_register_board_info(1,
+				ARRAY_AND_SIZE(stargate2_pwr_i2c_board_info));
+	pxa27x_set_i2c_power_info(&i2c_pwr_pdata);
+	pxa_set_i2c_info(&i2c_pdata);
+
+	pxa_set_mci_info(&stargate2_mci_platform_data);
+
+	pxa_set_udc_info(&stargate2_udc_info);
+
+	stargate2_reset_bluetooth();
+}
+
+MACHINE_START(STARGATE2, "Stargate 2")
+	.phys_io = 0x40000000,
+	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io = pxa_map_io,
+	.init_irq = pxa27x_init_irq,
+	.timer = &pxa_timer,
+	.init_machine = stargate2_init,
+	.boot_params = 0xA0000100,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/tosa-bt.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/tosa-bt.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/tosa-bt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/tosa-bt.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,21 +35,25 @@
 	gpio_set_value(data->gpio_reset, 0);
 }
 
-static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
+static int tosa_bt_set_block(void *data, bool blocked)
 {
-	pr_info("BT_RADIO going: %s\n",
-			state == RFKILL_STATE_ON ? "on" : "off");
+	pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
 
-	if (state == RFKILL_STATE_ON) {
+	if (!blocked) {
 		pr_info("TOSA_BT: going ON\n");
 		tosa_bt_on(data);
 	} else {
 		pr_info("TOSA_BT: going OFF\n");
 		tosa_bt_off(data);
 	}
+
 	return 0;
 }
 
+static const struct rfkill_ops tosa_bt_rfkill_ops = {
+	.set_block = tosa_bt_set_block,
+};
+
 static int tosa_bt_probe(struct platform_device *dev)
 {
 	int rc;
@@ -70,18 +74,14 @@
 	if (rc)
 		goto err_pwr_dir;
 
-	rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
+	rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
+			   &tosa_bt_rfkill_ops, data);
 	if (!rfk) {
 		rc = -ENOMEM;
 		goto err_rfk_alloc;
 	}
 
-	rfk->name = "tosa-bt";
-	rfk->toggle_radio = tosa_bt_toggle_radio;
-	rfk->data = data;
-#ifdef CONFIG_RFKILL_LEDS
-	rfk->led_trigger.name = "tosa-bt";
-#endif
+	rfkill_set_led_trigger_name(rfk, "tosa-bt");
 
 	rc = rfkill_register(rfk);
 	if (rc)
@@ -92,9 +92,7 @@
 	return 0;
 
 err_rfkill:
-	if (rfk)
-		rfkill_free(rfk);
-	rfk = NULL;
+	rfkill_destroy(rfk);
 err_rfk_alloc:
 	tosa_bt_off(data);
 err_pwr_dir:
@@ -113,8 +111,10 @@
 
 	platform_set_drvdata(dev, NULL);
 
-	if (rfk)
+	if (rfk) {
 		rfkill_unregister(rfk);
+		rfkill_destroy(rfk);
+	}
 	rfk = NULL;
 
 	tosa_bt_off(data);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/tosa.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/tosa.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/tosa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/tosa.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,7 +31,6 @@
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/pda_power.h>
-#include <linux/rfkill.h>
 #include <linux/spi/spi.h>
 
 #include <asm/setup.h>
@@ -40,7 +39,7 @@
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/irda.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/tosa_bt.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/treo680.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/treo680.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/treo680.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/treo680.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,612 @@
+/*
+ * Hardware definitions for Palm Treo 680
+ *
+ * Author:     Tomas Cech <sleep_walker@suse.cz>
+ *
+ * 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.
+ *
+ * (find more info at www.hackndev.com)
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/pda_power.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+#include <linux/wm97xx_batt.h>
+#include <linux/power_supply.h>
+#include <linux/sysdev.h>
+#include <linux/w1-gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/pxa27x.h>
+#include <mach/pxa27x-udc.h>
+#include <mach/audio.h>
+#include <mach/treo680.h>
+#include <mach/mmc.h>
+#include <mach/pxafb.h>
+#include <mach/irda.h>
+#include <mach/pxa27x_keypad.h>
+#include <mach/udc.h>
+#include <mach/ohci.h>
+#include <mach/pxa2xx-regs.h>
+#include <mach/palmasoc.h>
+#include <mach/camera.h>
+
+#include <sound/pxa2xx-lib.h>
+
+#include "generic.h"
+#include "devices.h"
+
+/******************************************************************************
+ * Pin configuration
+ ******************************************************************************/
+static unsigned long treo680_pin_config[] __initdata = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+	GPIO33_GPIO,				/* SD read only */
+	GPIO113_GPIO,				/* SD detect */
+
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+	GPIO89_AC97_SYSCLK,
+	GPIO95_AC97_nRESET,
+
+	/* IrDA */
+	GPIO46_FICP_RXD,
+	GPIO47_FICP_TXD,
+
+	/* PWM */
+	GPIO16_PWM0_OUT,
+
+	/* USB */
+	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,	/* usb detect */
+
+	/* MATRIX KEYPAD */
+	GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
+	GPIO101_KP_MKIN_1,
+	GPIO102_KP_MKIN_2,
+	GPIO97_KP_MKIN_3,
+	GPIO98_KP_MKIN_4,
+	GPIO99_KP_MKIN_5,
+	GPIO91_KP_MKIN_6,
+	GPIO13_KP_MKIN_7,
+	GPIO103_KP_MKOUT_0 | MFP_LPM_DRIVE_HIGH,
+	GPIO104_KP_MKOUT_1,
+	GPIO105_KP_MKOUT_2,
+	GPIO106_KP_MKOUT_3,
+	GPIO107_KP_MKOUT_4,
+	GPIO108_KP_MKOUT_5,
+	GPIO96_KP_MKOUT_6,
+	GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH,	/* Hotsync button */
+
+	/* LCD */
+	GPIO58_LCD_LDD_0,
+	GPIO59_LCD_LDD_1,
+	GPIO60_LCD_LDD_2,
+	GPIO61_LCD_LDD_3,
+	GPIO62_LCD_LDD_4,
+	GPIO63_LCD_LDD_5,
+	GPIO64_LCD_LDD_6,
+	GPIO65_LCD_LDD_7,
+	GPIO66_LCD_LDD_8,
+	GPIO67_LCD_LDD_9,
+	GPIO68_LCD_LDD_10,
+	GPIO69_LCD_LDD_11,
+	GPIO70_LCD_LDD_12,
+	GPIO71_LCD_LDD_13,
+	GPIO72_LCD_LDD_14,
+	GPIO73_LCD_LDD_15,
+	GPIO74_LCD_FCLK,
+	GPIO75_LCD_LCLK,
+	GPIO76_LCD_PCLK,
+
+	/* Quick Capture Interface */
+	GPIO84_CIF_FV,
+	GPIO85_CIF_LV,
+	GPIO53_CIF_MCLK,
+	GPIO54_CIF_PCLK,
+	GPIO81_CIF_DD_0,
+	GPIO55_CIF_DD_1,
+	GPIO51_CIF_DD_2,
+	GPIO50_CIF_DD_3,
+	GPIO52_CIF_DD_4,
+	GPIO48_CIF_DD_5,
+	GPIO17_CIF_DD_6,
+	GPIO12_CIF_DD_7,
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* GSM */
+	GPIO14_GPIO | WAKEUP_ON_EDGE_BOTH,	/* GSM host wake up */
+	GPIO34_FFUART_RXD,
+	GPIO35_FFUART_CTS,
+	GPIO39_FFUART_TXD,
+	GPIO41_FFUART_RTS,
+
+	/* MISC. */
+	GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH,	/* external power detect */
+	GPIO15_GPIO | WAKEUP_ON_EDGE_BOTH,	/* silent switch */
+	GPIO116_GPIO,				/* headphone detect */
+	GPIO11_GPIO | WAKEUP_ON_EDGE_BOTH,	/* bluetooth host wake up */
+};
+
+/******************************************************************************
+ * SD/MMC card controller
+ ******************************************************************************/
+static int treo680_mci_init(struct device *dev,
+		irq_handler_t treo680_detect_int, void *data)
+{
+	int err = 0;
+
+	/* Setup an interrupt for detecting card insert/remove events */
+	err = gpio_request(GPIO_NR_TREO680_SD_DETECT_N, "SD IRQ");
+
+	if (err)
+		goto err;
+
+	err = gpio_direction_input(GPIO_NR_TREO680_SD_DETECT_N);
+	if (err)
+		goto err2;
+
+	err = request_irq(gpio_to_irq(GPIO_NR_TREO680_SD_DETECT_N),
+			treo680_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"SD/MMC card detect", data);
+
+	if (err) {
+		dev_err(dev, "%s: cannot request SD/MMC card detect IRQ\n",
+			     __func__);
+		goto err2;
+	}
+
+	err = gpio_request(GPIO_NR_TREO680_SD_POWER, "SD_POWER");
+	if (err)
+		goto err3;
+
+	err = gpio_direction_output(GPIO_NR_TREO680_SD_POWER, 1);
+	if (err)
+		goto err4;
+
+	err = gpio_request(GPIO_NR_TREO680_SD_READONLY, "SD_READONLY");
+	if (err)
+		goto err4;
+
+	err = gpio_direction_input(GPIO_NR_TREO680_SD_READONLY);
+	if (err)
+		goto err5;
+
+	return 0;
+
+err5:
+	gpio_free(GPIO_NR_TREO680_SD_READONLY);
+err4:
+	gpio_free(GPIO_NR_TREO680_SD_POWER);
+err3:
+	free_irq(gpio_to_irq(GPIO_NR_TREO680_SD_DETECT_N), data);
+err2:
+	gpio_free(GPIO_NR_TREO680_SD_DETECT_N);
+err:
+	return err;
+}
+
+static void treo680_mci_exit(struct device *dev, void *data)
+{
+	gpio_free(GPIO_NR_TREO680_SD_READONLY);
+	gpio_free(GPIO_NR_TREO680_SD_POWER);
+	free_irq(gpio_to_irq(GPIO_NR_TREO680_SD_DETECT_N), data);
+	gpio_free(GPIO_NR_TREO680_SD_DETECT_N);
+}
+
+static void treo680_mci_power(struct device *dev, unsigned int vdd)
+{
+	struct pxamci_platform_data *p_d = dev->platform_data;
+	gpio_set_value(GPIO_NR_TREO680_SD_POWER, p_d->ocr_mask & (1 << vdd));
+}
+
+static int treo680_mci_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO_NR_TREO680_SD_READONLY);
+}
+
+static struct pxamci_platform_data treo680_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.setpower	= treo680_mci_power,
+	.get_ro		= treo680_mci_get_ro,
+	.init 		= treo680_mci_init,
+	.exit		= treo680_mci_exit,
+};
+
+/******************************************************************************
+ * GPIO keyboard
+ ******************************************************************************/
+static unsigned int treo680_matrix_keys[] = {
+	KEY(0, 0, KEY_F8),		/* Red/Off/Power */
+	KEY(0, 1, KEY_LEFT),
+	KEY(0, 2, KEY_LEFTCTRL),	/* Alternate */
+	KEY(0, 3, KEY_L),
+	KEY(0, 4, KEY_A),
+	KEY(0, 5, KEY_Q),
+	KEY(0, 6, KEY_P),
+
+	KEY(1, 0, KEY_RIGHTCTRL),	/* Menu */
+	KEY(1, 1, KEY_RIGHT),
+	KEY(1, 2, KEY_LEFTSHIFT),	/* Left shift */
+	KEY(1, 3, KEY_Z),
+	KEY(1, 4, KEY_S),
+	KEY(1, 5, KEY_W),
+
+	KEY(2, 0, KEY_F1),		/* Phone */
+	KEY(2, 1, KEY_UP),
+	KEY(2, 2, KEY_0),
+	KEY(2, 3, KEY_X),
+	KEY(2, 4, KEY_D),
+	KEY(2, 5, KEY_E),
+
+	KEY(3, 0, KEY_F10),		/* Calendar */
+	KEY(3, 1, KEY_DOWN),
+	KEY(3, 2, KEY_SPACE),
+	KEY(3, 3, KEY_C),
+	KEY(3, 4, KEY_F),
+	KEY(3, 5, KEY_R),
+
+	KEY(4, 0, KEY_F12),		/* Mail */
+	KEY(4, 1, KEY_KPENTER),
+	KEY(4, 2, KEY_RIGHTALT),	/* Alt */
+	KEY(4, 3, KEY_V),
+	KEY(4, 4, KEY_G),
+	KEY(4, 5, KEY_T),
+
+	KEY(5, 0, KEY_F9),		/* Home */
+	KEY(5, 1, KEY_PAGEUP),		/* Side up */
+	KEY(5, 2, KEY_DOT),
+	KEY(5, 3, KEY_B),
+	KEY(5, 4, KEY_H),
+	KEY(5, 5, KEY_Y),
+
+	KEY(6, 0, KEY_TAB),		/* Side Activate */
+	KEY(6, 1, KEY_PAGEDOWN),	/* Side down */
+	KEY(6, 2, KEY_ENTER),
+	KEY(6, 3, KEY_N),
+	KEY(6, 4, KEY_J),
+	KEY(6, 5, KEY_U),
+
+	KEY(7, 0, KEY_F6),		/* Green/Call */
+	KEY(7, 1, KEY_O),
+	KEY(7, 2, KEY_BACKSPACE),
+	KEY(7, 3, KEY_M),
+	KEY(7, 4, KEY_K),
+	KEY(7, 5, KEY_I),
+};
+
+static struct pxa27x_keypad_platform_data treo680_keypad_platform_data = {
+	.matrix_key_rows	= 8,
+	.matrix_key_cols	= 7,
+	.matrix_key_map		= treo680_matrix_keys,
+	.matrix_key_map_size	= ARRAY_SIZE(treo680_matrix_keys),
+	.direct_key_map		= { KEY_CONNECT },
+	.direct_key_num		= 1,
+
+	.debounce_interval	= 30,
+};
+
+/******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+
+static pxa2xx_audio_ops_t treo680_ac97_pdata = {
+	.reset_gpio	= 95,
+};
+
+/******************************************************************************
+ * Backlight
+ ******************************************************************************/
+static int treo680_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_TREO680_BL_POWER, "BL POWER");
+	if (ret)
+		goto err;
+	ret = gpio_direction_output(GPIO_NR_TREO680_BL_POWER, 0);
+	if (ret)
+		goto err2;
+	ret = gpio_request(GPIO_NR_TREO680_LCD_POWER, "LCD POWER");
+	if (ret)
+		goto err2;
+	ret = gpio_direction_output(GPIO_NR_TREO680_LCD_POWER, 0);
+	if (ret)
+		goto err3;
+
+	return 0;
+err3:
+	gpio_free(GPIO_NR_TREO680_LCD_POWER);
+err2:
+	gpio_free(GPIO_NR_TREO680_BL_POWER);
+err:
+	return ret;
+}
+
+static int treo680_backlight_notify(int brightness)
+{
+	gpio_set_value(GPIO_NR_TREO680_BL_POWER, brightness);
+	return TREO680_MAX_INTENSITY - brightness;
+};
+
+static void treo680_backlight_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_TREO680_BL_POWER);
+	gpio_free(GPIO_NR_TREO680_LCD_POWER);
+}
+
+static struct platform_pwm_backlight_data treo680_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= TREO680_MAX_INTENSITY,
+	.dft_brightness	= TREO680_DEFAULT_INTENSITY,
+	.pwm_period_ns	= TREO680_PERIOD_NS,
+	.init		= treo680_backlight_init,
+	.notify		= treo680_backlight_notify,
+	.exit		= treo680_backlight_exit,
+};
+
+static struct platform_device treo680_backlight = {
+	.name	= "pwm-backlight",
+	.dev	= {
+		.parent		= &pxa27x_device_pwm0.dev,
+		.platform_data	= &treo680_backlight_data,
+	},
+};
+
+/******************************************************************************
+ * IrDA
+ ******************************************************************************/
+static void treo680_transceiver_mode(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO_NR_TREO680_IR_EN, mode & IR_OFF);
+	pxa2xx_transceiver_mode(dev, mode);
+}
+
+static int treo680_irda_startup(struct device *dev)
+{
+	int err;
+
+	err = gpio_request(GPIO_NR_TREO680_IR_EN, "Ir port disable");
+	if (err)
+		goto err1;
+
+	err = gpio_direction_output(GPIO_NR_TREO680_IR_EN, 1);
+	if (err)
+		goto err2;
+
+	return 0;
+
+err2:
+	dev_err(dev, "treo680_irda: cannot change IR gpio direction\n");
+	gpio_free(GPIO_NR_TREO680_IR_EN);
+err1:
+	dev_err(dev, "treo680_irda: cannot allocate IR gpio\n");
+	return err;
+}
+
+static void treo680_irda_shutdown(struct device *dev)
+{
+	gpio_free(GPIO_NR_TREO680_IR_EN);
+}
+
+static struct pxaficp_platform_data treo680_ficp_info = {
+	.transceiver_cap  = IR_FIRMODE | IR_SIRMODE | IR_OFF,
+	.startup          = treo680_irda_startup,
+	.shutdown         = treo680_irda_shutdown,
+	.transceiver_mode = treo680_transceiver_mode,
+};
+
+/******************************************************************************
+ * UDC
+ ******************************************************************************/
+static struct pxa2xx_udc_mach_info treo680_udc_info __initdata = {
+	.gpio_vbus		= GPIO_NR_TREO680_USB_DETECT,
+	.gpio_vbus_inverted	= 1,
+	.gpio_pullup		= GPIO_NR_TREO680_USB_PULLUP,
+};
+
+
+/******************************************************************************
+ * USB host
+ ******************************************************************************/
+static struct pxaohci_platform_data treo680_ohci_info = {
+	.port_mode    = PMM_PERPORT_MODE,
+	.flags        = ENABLE_PORT1 | ENABLE_PORT3,
+	.power_budget = 0,
+};
+
+/******************************************************************************
+ * Power supply
+ ******************************************************************************/
+static int power_supply_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_TREO680_POWER_DETECT, "CABLE_STATE_AC");
+	if (ret)
+		goto err1;
+	ret = gpio_direction_input(GPIO_NR_TREO680_POWER_DETECT);
+	if (ret)
+		goto err2;
+
+	return 0;
+
+err2:
+	gpio_free(GPIO_NR_TREO680_POWER_DETECT);
+err1:
+	return ret;
+}
+
+static int treo680_is_ac_online(void)
+{
+	return gpio_get_value(GPIO_NR_TREO680_POWER_DETECT);
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_TREO680_POWER_DETECT);
+}
+
+static char *treo680_supplicants[] = {
+	"main-battery",
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init		 = power_supply_init,
+	.is_ac_online    = treo680_is_ac_online,
+	.exit		 = power_supply_exit,
+	.supplied_to     = treo680_supplicants,
+	.num_supplicants = ARRAY_SIZE(treo680_supplicants),
+};
+
+static struct platform_device power_supply = {
+	.name = "pda-power",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &power_supply_info,
+	},
+};
+
+/******************************************************************************
+ * Vibra and LEDs
+ ******************************************************************************/
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "treo680:vibra:vibra",
+		.default_trigger	= "none",
+		.gpio			= GPIO_NR_TREO680_VIBRATE_EN,
+	},
+	{
+		.name			= "treo680:green:led",
+		.default_trigger	= "mmc0",
+		.gpio			= GPIO_NR_TREO680_GREEN_LED,
+	},
+	{
+		.name			= "treo680:keybbl:keybbl",
+		.default_trigger	= "none",
+		.gpio			= GPIO_NR_TREO680_KEYB_BL,
+	},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device treo680_leds = {
+	.name   = "leds-gpio",
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &gpio_led_info,
+	}
+};
+
+
+/******************************************************************************
+ * Framebuffer
+ ******************************************************************************/
+/* TODO: add support for 324x324 */
+static struct pxafb_mode_info treo680_lcd_modes[] = {
+{
+	.pixclock		= 86538,
+	.xres			= 320,
+	.yres			= 320,
+	.bpp			= 16,
+
+	.left_margin		= 20,
+	.right_margin		= 8,
+	.upper_margin		= 8,
+	.lower_margin		= 5,
+
+	.hsync_len		= 4,
+	.vsync_len		= 1,
+},
+};
+
+static struct pxafb_mach_info treo680_lcd_screen = {
+	.modes		= treo680_lcd_modes,
+	.num_modes	= ARRAY_SIZE(treo680_lcd_modes),
+	.lcd_conn	= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+};
+
+/******************************************************************************
+ * Power management - standby
+ ******************************************************************************/
+static void __init treo680_pm_init(void)
+{
+	static u32 resume[] = {
+		0xe3a00101,	/* mov	r0,	#0x40000000 */
+		0xe380060f,	/* orr	r0, r0, #0x00f00000 */
+		0xe590f008,	/* ldr	pc, [r0, #0x08] */
+	};
+
+	/* this is where the bootloader jumps */
+	memcpy(phys_to_virt(TREO680_STR_BASE), resume, sizeof(resume));
+}
+
+/******************************************************************************
+ * Machine init
+ ******************************************************************************/
+static struct platform_device *devices[] __initdata = {
+	&treo680_backlight,
+	&treo680_leds,
+	&power_supply,
+};
+
+/* setup udc GPIOs initial state */
+static void __init treo680_udc_init(void)
+{
+	if (!gpio_request(GPIO_NR_TREO680_USB_PULLUP, "UDC Vbus")) {
+		gpio_direction_output(GPIO_NR_TREO680_USB_PULLUP, 1);
+		gpio_free(GPIO_NR_TREO680_USB_PULLUP);
+	}
+}
+
+static void __init treo680_init(void)
+{
+	treo680_pm_init();
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(treo680_pin_config));
+	pxa_set_keypad_info(&treo680_keypad_platform_data);
+	set_pxa_fb_info(&treo680_lcd_screen);
+	pxa_set_mci_info(&treo680_mci_platform_data);
+	treo680_udc_init();
+	pxa_set_udc_info(&treo680_udc_info);
+	pxa_set_ac97_info(&treo680_ac97_pdata);
+	pxa_set_ficp_info(&treo680_ficp_info);
+	pxa_set_ohci_info(&treo680_ohci_info);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(TREO680, "Palm Treo 680")
+	.phys_io	= TREO680_PHYS_IO_START,
+	.io_pg_offst	= io_p2v(0x40000000),
+	.boot_params	= 0xa0000100,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa27x_init_irq,
+	.timer		= &pxa_timer,
+	.init_machine	= treo680_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/trizeps4.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/trizeps4.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/trizeps4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/trizeps4.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,7 @@
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/viper.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/viper.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/viper.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/viper.c	2009-09-09 18:13:59.000000000 -0400
@@ -45,7 +45,7 @@
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/regs-uart.h>
 #include <mach/viper.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/zylonite_pxa300.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/zylonite_pxa300.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/zylonite_pxa300.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/zylonite_pxa300.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,7 @@
 #include <linux/gpio.h>
 
 #include <mach/pxa300.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/zylonite.h>
 
 #include "generic.h"
@@ -197,10 +197,12 @@
 	for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
 		id = id << 1;
 		gpio = mfp_to_gpio(lcd_detect_pins[i]);
+		gpio_request(gpio, "LCD_ID_PINS");
 		gpio_direction_input(gpio);
 
 		if (gpio_get_value(gpio))
 			id = id | 0x1;
+		gpio_free(gpio);
 	}
 
 	/* lcd id, flush out bit 1 */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-pxa/zylonite_pxa320.c linux-libre-2.6.31-gnu/arch/arm/mach-pxa/zylonite_pxa320.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-pxa/zylonite_pxa320.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-pxa/zylonite_pxa320.c	2009-09-09 18:13:59.000000000 -0400
@@ -176,10 +176,12 @@
 	for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
 		id = id << 1;
 		gpio = mfp_to_gpio(lcd_detect_pins[i]);
+		gpio_request(gpio, "LCD_ID_PINS");
 		gpio_direction_input(gpio);
 
 		if (gpio_get_value(gpio))
 			id = id | 0x1;
+		gpio_free(gpio);
 	}
 
 	/* lcd id, flush out bit 1 */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/core.c linux-libre-2.6.31-gnu/arch/arm/mach-realview/core.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,9 @@
 
 #include <asm/hardware/gic.h>
 
+#include <mach/platform.h>
+#include <mach/irqs.h>
+
 #include "core.h"
 #include "clock.h"
 
@@ -205,8 +208,7 @@
 
 static struct i2c_board_info realview_i2c_board_info[] = {
 	{
-		I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
-		.type = "ds1338",
+		I2C_BOARD_INFO("ds1338", 0xd0 >> 1),
 	},
 };
 
@@ -578,21 +580,22 @@
 {
 	unsigned long flags;
 	u32 val;
+	u32 led = 1 << smp_processor_id();
 
 	local_irq_save(flags);
 	val = readl(VA_LEDS_BASE);
 
 	switch (ledevt) {
 	case led_idle_start:
-		val = val & ~REALVIEW_SYS_LED0;
+		val = val & ~led;
 		break;
 
 	case led_idle_end:
-		val = val | REALVIEW_SYS_LED0;
+		val = val | led;
 		break;
 
 	case led_timer:
-		val = val ^ REALVIEW_SYS_LED1;
+		val = val ^ REALVIEW_SYS_LED7;
 		break;
 
 	case led_halted:
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/core.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/core.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/core.h	2009-09-09 18:13:59.000000000 -0400
@@ -51,9 +51,6 @@
 extern struct mmc_platform_data realview_mmc1_plat_data;
 extern struct clcd_board clcd_plat_data;
 extern void __iomem *gic_cpu_base_addr;
-#ifdef CONFIG_LOCAL_TIMERS
-extern void __iomem *twd_base;
-#endif
 extern void __iomem *timer0_va_base;
 extern void __iomem *timer1_va_base;
 extern void __iomem *timer2_va_base;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-eb.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-eb.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-eb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-eb.h	2009-09-09 18:13:59.000000000 -0400
@@ -62,111 +62,6 @@
 #define REALVIEW_EB11MP_SYS_PLD_CTRL1	0x74		/* Register offset for MPCore sysctl */
 #endif
 
-#define IRQ_EB_GIC_START	32
-
-/*
- * RealView EB interrupt sources
- */
-#define IRQ_EB_WDOG		(IRQ_EB_GIC_START + 0)		/* Watchdog timer */
-#define IRQ_EB_SOFT		(IRQ_EB_GIC_START + 1)		/* Software interrupt */
-#define IRQ_EB_COMMRx		(IRQ_EB_GIC_START + 2)		/* Debug Comm Rx interrupt */
-#define IRQ_EB_COMMTx		(IRQ_EB_GIC_START + 3)		/* Debug Comm Tx interrupt */
-#define IRQ_EB_TIMER0_1		(IRQ_EB_GIC_START + 4)		/* Timer 0 and 1 */
-#define IRQ_EB_TIMER2_3		(IRQ_EB_GIC_START + 5)		/* Timer 2 and 3 */
-#define IRQ_EB_GPIO0		(IRQ_EB_GIC_START + 6)		/* GPIO 0 */
-#define IRQ_EB_GPIO1		(IRQ_EB_GIC_START + 7)		/* GPIO 1 */
-#define IRQ_EB_GPIO2		(IRQ_EB_GIC_START + 8)		/* GPIO 2 */
-								/* 9 reserved */
-#define IRQ_EB_RTC		(IRQ_EB_GIC_START + 10)		/* Real Time Clock */
-#define IRQ_EB_SSP		(IRQ_EB_GIC_START + 11)		/* Synchronous Serial Port */
-#define IRQ_EB_UART0		(IRQ_EB_GIC_START + 12)		/* UART 0 on development chip */
-#define IRQ_EB_UART1		(IRQ_EB_GIC_START + 13)		/* UART 1 on development chip */
-#define IRQ_EB_UART2		(IRQ_EB_GIC_START + 14)		/* UART 2 on development chip */
-#define IRQ_EB_UART3		(IRQ_EB_GIC_START + 15)		/* UART 3 on development chip */
-#define IRQ_EB_SCI		(IRQ_EB_GIC_START + 16)		/* Smart Card Interface */
-#define IRQ_EB_MMCI0A		(IRQ_EB_GIC_START + 17)		/* Multimedia Card 0A */
-#define IRQ_EB_MMCI0B		(IRQ_EB_GIC_START + 18)		/* Multimedia Card 0B */
-#define IRQ_EB_AACI		(IRQ_EB_GIC_START + 19)		/* Audio Codec */
-#define IRQ_EB_KMI0		(IRQ_EB_GIC_START + 20)		/* Keyboard/Mouse port 0 */
-#define IRQ_EB_KMI1		(IRQ_EB_GIC_START + 21)		/* Keyboard/Mouse port 1 */
-#define IRQ_EB_CHARLCD		(IRQ_EB_GIC_START + 22)		/* Character LCD */
-#define IRQ_EB_CLCD		(IRQ_EB_GIC_START + 23)		/* CLCD controller */
-#define IRQ_EB_DMA		(IRQ_EB_GIC_START + 24)		/* DMA controller */
-#define IRQ_EB_PWRFAIL		(IRQ_EB_GIC_START + 25)		/* Power failure */
-#define IRQ_EB_PISMO		(IRQ_EB_GIC_START + 26)		/* PISMO interface */
-#define IRQ_EB_DoC		(IRQ_EB_GIC_START + 27)		/* Disk on Chip memory controller */
-#define IRQ_EB_ETH		(IRQ_EB_GIC_START + 28)		/* Ethernet controller */
-#define IRQ_EB_USB		(IRQ_EB_GIC_START + 29)		/* USB controller */
-#define IRQ_EB_TSPEN		(IRQ_EB_GIC_START + 30)		/* Touchscreen pen */
-#define IRQ_EB_TSKPAD		(IRQ_EB_GIC_START + 31)		/* Touchscreen keypad */
-
-/*
- * RealView EB + ARM11MPCore interrupt sources (primary GIC on the core tile)
- */
-#define IRQ_EB11MP_AACI		(IRQ_EB_GIC_START + 0)
-#define IRQ_EB11MP_TIMER0_1	(IRQ_EB_GIC_START + 1)
-#define IRQ_EB11MP_TIMER2_3	(IRQ_EB_GIC_START + 2)
-#define IRQ_EB11MP_USB		(IRQ_EB_GIC_START + 3)
-#define IRQ_EB11MP_UART0	(IRQ_EB_GIC_START + 4)
-#define IRQ_EB11MP_UART1	(IRQ_EB_GIC_START + 5)
-#define IRQ_EB11MP_RTC		(IRQ_EB_GIC_START + 6)
-#define IRQ_EB11MP_KMI0		(IRQ_EB_GIC_START + 7)
-#define IRQ_EB11MP_KMI1		(IRQ_EB_GIC_START + 8)
-#define IRQ_EB11MP_ETH		(IRQ_EB_GIC_START + 9)
-#define IRQ_EB11MP_EB_IRQ1	(IRQ_EB_GIC_START + 10)		/* main GIC */
-#define IRQ_EB11MP_EB_IRQ2	(IRQ_EB_GIC_START + 11)		/* tile GIC */
-#define IRQ_EB11MP_EB_FIQ1	(IRQ_EB_GIC_START + 12)		/* main GIC */
-#define IRQ_EB11MP_EB_FIQ2	(IRQ_EB_GIC_START + 13)		/* tile GIC */
-#define IRQ_EB11MP_MMCI0A	(IRQ_EB_GIC_START + 14)
-#define IRQ_EB11MP_MMCI0B	(IRQ_EB_GIC_START + 15)
-
-#define IRQ_EB11MP_PMU_CPU0	(IRQ_EB_GIC_START + 17)
-#define IRQ_EB11MP_PMU_CPU1	(IRQ_EB_GIC_START + 18)
-#define IRQ_EB11MP_PMU_CPU2	(IRQ_EB_GIC_START + 19)
-#define IRQ_EB11MP_PMU_CPU3	(IRQ_EB_GIC_START + 20)
-#define IRQ_EB11MP_PMU_SCU0	(IRQ_EB_GIC_START + 21)
-#define IRQ_EB11MP_PMU_SCU1	(IRQ_EB_GIC_START + 22)
-#define IRQ_EB11MP_PMU_SCU2	(IRQ_EB_GIC_START + 23)
-#define IRQ_EB11MP_PMU_SCU3	(IRQ_EB_GIC_START + 24)
-#define IRQ_EB11MP_PMU_SCU4	(IRQ_EB_GIC_START + 25)
-#define IRQ_EB11MP_PMU_SCU5	(IRQ_EB_GIC_START + 26)
-#define IRQ_EB11MP_PMU_SCU6	(IRQ_EB_GIC_START + 27)
-#define IRQ_EB11MP_PMU_SCU7	(IRQ_EB_GIC_START + 28)
-
-#define IRQ_EB11MP_L220_EVENT	(IRQ_EB_GIC_START + 29)
-#define IRQ_EB11MP_L220_SLAVE	(IRQ_EB_GIC_START + 30)
-#define IRQ_EB11MP_L220_DECODE	(IRQ_EB_GIC_START + 31)
-
-#define IRQ_EB11MP_UART2	-1
-#define IRQ_EB11MP_UART3	-1
-#define IRQ_EB11MP_CLCD		-1
-#define IRQ_EB11MP_DMA		-1
-#define IRQ_EB11MP_WDOG		-1
-#define IRQ_EB11MP_GPIO0	-1
-#define IRQ_EB11MP_GPIO1	-1
-#define IRQ_EB11MP_GPIO2	-1
-#define IRQ_EB11MP_SCI		-1
-#define IRQ_EB11MP_SSP		-1
-
-#define NR_GIC_EB11MP		2
-
-/*
- * Only define NR_IRQS if less than NR_IRQS_EB
- */
-#define NR_IRQS_EB		(IRQ_EB_GIC_START + 96)
-
-#if defined(CONFIG_MACH_REALVIEW_EB) \
-	&& (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB))
-#undef NR_IRQS
-#define NR_IRQS			NR_IRQS_EB
-#endif
-
-#if defined(CONFIG_REALVIEW_EB_ARM11MP) || defined(CONFIG_REALVIEW_EB_A9MP) \
-	&& (!defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_EB11MP))
-#undef MAX_GIC_NR
-#define MAX_GIC_NR		NR_GIC_EB11MP
-#endif
-
 /*
  * Core tile identification (REALVIEW_SYS_PROCID)
  */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pb1176.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,8 @@
 #define REALVIEW_PB1176_SDRAM67_BASE		0x70000000 /* SDRAM banks 6 and 7 */
 #define REALVIEW_PB1176_FLASH_BASE		0x30000000
 #define REALVIEW_PB1176_FLASH_SIZE		SZ_64M
+#define REALVIEW_PB1176_SEC_FLASH_BASE		0x3C000000 /* Secure flash */
+#define REALVIEW_PB1176_SEC_FLASH_SIZE		SZ_64M
 
 #define REALVIEW_PB1176_TIMER0_1_BASE		0x10104000 /* Timer 0 and 1 */
 #define REALVIEW_PB1176_TIMER2_3_BASE		0x10105000 /* Timer 2 and 3 */
@@ -71,82 +73,4 @@
 #define REALVIEW_PB1176_GIC_DIST_BASE		0x10041000 /* GIC distributor, on FPGA */
 #define REALVIEW_PB1176_L220_BASE		0x10110000 /* L220 registers */
 
-/*
- * Irqs
- */
-#define IRQ_DC1176_GIC_START			32
-#define IRQ_PB1176_GIC_START			64
-
-/*
- * ARM1176 DevChip interrupt sources (primary GIC)
- */
-#define IRQ_DC1176_WATCHDOG	(IRQ_DC1176_GIC_START + 0)	/* Watchdog timer */
-#define IRQ_DC1176_SOFTINT	(IRQ_DC1176_GIC_START + 1)	/* Software interrupt */
-#define IRQ_DC1176_COMMRx	(IRQ_DC1176_GIC_START + 2)	/* Debug Comm Rx interrupt */
-#define IRQ_DC1176_COMMTx	(IRQ_DC1176_GIC_START + 3)	/* Debug Comm Tx interrupt */
-#define IRQ_DC1176_TIMER0	(IRQ_DC1176_GIC_START + 8)	/* Timer 0 */
-#define IRQ_DC1176_TIMER1	(IRQ_DC1176_GIC_START + 9)	/* Timer 1 */
-#define IRQ_DC1176_TIMER2	(IRQ_DC1176_GIC_START + 10)	/* Timer 2 */
-#define IRQ_DC1176_APC		(IRQ_DC1176_GIC_START + 11)
-#define IRQ_DC1176_IEC		(IRQ_DC1176_GIC_START + 12)
-#define IRQ_DC1176_L2CC		(IRQ_DC1176_GIC_START + 13)
-#define IRQ_DC1176_RTC		(IRQ_DC1176_GIC_START + 14)
-#define IRQ_DC1176_CLCD		(IRQ_DC1176_GIC_START + 15)	/* CLCD controller */
-#define IRQ_DC1176_UART0	(IRQ_DC1176_GIC_START + 18)	/* UART 0 on development chip */
-#define IRQ_DC1176_UART1	(IRQ_DC1176_GIC_START + 19)	/* UART 1 on development chip */
-#define IRQ_DC1176_UART2	(IRQ_DC1176_GIC_START + 20)	/* UART 2 on development chip */
-#define IRQ_DC1176_UART3	(IRQ_DC1176_GIC_START + 21)	/* UART 3 on development chip */
-
-#define IRQ_DC1176_PB_IRQ2	(IRQ_DC1176_GIC_START + 30)	/* tile GIC */
-#define IRQ_DC1176_PB_IRQ1	(IRQ_DC1176_GIC_START + 31)	/* main GIC */
-
-/*
- * RealView PB1176 interrupt sources (secondary GIC)
- */
-#define IRQ_PB1176_MMCI0A	(IRQ_PB1176_GIC_START + 1)	/* Multimedia Card 0A */
-#define IRQ_PB1176_MMCI0B	(IRQ_PB1176_GIC_START + 2)	/* Multimedia Card 0A */
-#define IRQ_PB1176_KMI0		(IRQ_PB1176_GIC_START + 3)	/* Keyboard/Mouse port 0 */
-#define IRQ_PB1176_KMI1		(IRQ_PB1176_GIC_START + 4)	/* Keyboard/Mouse port 1 */
-#define IRQ_PB1176_SCI		(IRQ_PB1176_GIC_START + 5)
-#define IRQ_PB1176_UART4	(IRQ_PB1176_GIC_START + 6)	/* UART 4 on baseboard */
-#define IRQ_PB1176_CHARLCD	(IRQ_PB1176_GIC_START + 7)	/* Character LCD */
-#define IRQ_PB1176_GPIO1	(IRQ_PB1176_GIC_START + 8)
-#define IRQ_PB1176_GPIO2	(IRQ_PB1176_GIC_START + 9)
-#define IRQ_PB1176_ETH		(IRQ_PB1176_GIC_START + 10)	/* Ethernet controller */
-#define IRQ_PB1176_USB		(IRQ_PB1176_GIC_START + 11)	/* USB controller */
-
-#define IRQ_PB1176_PISMO	(IRQ_PB1176_GIC_START + 16)
-
-#define IRQ_PB1176_AACI		(IRQ_PB1176_GIC_START + 19)	/* Audio Codec */
-
-#define IRQ_PB1176_TIMER0_1	(IRQ_PB1176_GIC_START + 22)
-#define IRQ_PB1176_TIMER2_3	(IRQ_PB1176_GIC_START + 23)
-#define IRQ_PB1176_DMAC		(IRQ_PB1176_GIC_START + 24)	/* DMA controller */
-#define IRQ_PB1176_RTC		(IRQ_PB1176_GIC_START + 25)	/* Real Time Clock */
-
-#define IRQ_PB1176_GPIO0	-1
-#define IRQ_PB1176_SSP		-1
-#define IRQ_PB1176_SCTL		-1
-
-#define NR_GIC_PB1176		2
-
-/*
- * Only define NR_IRQS if less than NR_IRQS_PB1176
- */
-#define NR_IRQS_PB1176		(IRQ_DC1176_GIC_START + 96)
-
-#if defined(CONFIG_MACH_REALVIEW_PB1176)
-
-#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB1176)
-#undef NR_IRQS
-#define NR_IRQS			NR_IRQS_PB1176
-#endif
-
-#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB1176)
-#undef MAX_GIC_NR
-#define MAX_GIC_NR		NR_GIC_PB1176
-#endif
-
-#endif	/* CONFIG_MACH_REALVIEW_PB1176 */
-
 #endif	/* __ASM_ARCH_BOARD_PB1176_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pb11mp.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pb11mp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pb11mp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pb11mp.h	2009-09-09 18:13:59.000000000 -0400
@@ -81,105 +81,4 @@
 #define REALVIEW_TC11MP_GIC_DIST_BASE		0x1F001000	/* Test chip interrupt controller distributor */
 #define REALVIEW_TC11MP_L220_BASE		0x1F002000	/* L220 registers */
 
-/*
- * Irqs
- */
-#define IRQ_TC11MP_GIC_START			32
-#define IRQ_PB11MP_GIC_START			64
-
-/*
- * ARM11MPCore test chip interrupt sources (primary GIC on the test chip)
- */
-#define IRQ_TC11MP_AACI		(IRQ_TC11MP_GIC_START + 0)
-#define IRQ_TC11MP_TIMER0_1	(IRQ_TC11MP_GIC_START + 1)
-#define IRQ_TC11MP_TIMER2_3	(IRQ_TC11MP_GIC_START + 2)
-#define IRQ_TC11MP_USB		(IRQ_TC11MP_GIC_START + 3)
-#define IRQ_TC11MP_UART0	(IRQ_TC11MP_GIC_START + 4)
-#define IRQ_TC11MP_UART1	(IRQ_TC11MP_GIC_START + 5)
-#define IRQ_TC11MP_RTC		(IRQ_TC11MP_GIC_START + 6)
-#define IRQ_TC11MP_KMI0		(IRQ_TC11MP_GIC_START + 7)
-#define IRQ_TC11MP_KMI1		(IRQ_TC11MP_GIC_START + 8)
-#define IRQ_TC11MP_ETH		(IRQ_TC11MP_GIC_START + 9)
-#define IRQ_TC11MP_PB_IRQ1	(IRQ_TC11MP_GIC_START + 10)		/* main GIC */
-#define IRQ_TC11MP_PB_IRQ2	(IRQ_TC11MP_GIC_START + 11)		/* tile GIC */
-#define IRQ_TC11MP_PB_FIQ1	(IRQ_TC11MP_GIC_START + 12)		/* main GIC */
-#define IRQ_TC11MP_PB_FIQ2	(IRQ_TC11MP_GIC_START + 13)		/* tile GIC */
-#define IRQ_TC11MP_MMCI0A	(IRQ_TC11MP_GIC_START + 14)
-#define IRQ_TC11MP_MMCI0B	(IRQ_TC11MP_GIC_START + 15)
-
-#define IRQ_TC11MP_PMU_CPU0	(IRQ_TC11MP_GIC_START + 17)
-#define IRQ_TC11MP_PMU_CPU1	(IRQ_TC11MP_GIC_START + 18)
-#define IRQ_TC11MP_PMU_CPU2	(IRQ_TC11MP_GIC_START + 19)
-#define IRQ_TC11MP_PMU_CPU3	(IRQ_TC11MP_GIC_START + 20)
-#define IRQ_TC11MP_PMU_SCU0	(IRQ_TC11MP_GIC_START + 21)
-#define IRQ_TC11MP_PMU_SCU1	(IRQ_TC11MP_GIC_START + 22)
-#define IRQ_TC11MP_PMU_SCU2	(IRQ_TC11MP_GIC_START + 23)
-#define IRQ_TC11MP_PMU_SCU3	(IRQ_TC11MP_GIC_START + 24)
-#define IRQ_TC11MP_PMU_SCU4	(IRQ_TC11MP_GIC_START + 25)
-#define IRQ_TC11MP_PMU_SCU5	(IRQ_TC11MP_GIC_START + 26)
-#define IRQ_TC11MP_PMU_SCU6	(IRQ_TC11MP_GIC_START + 27)
-#define IRQ_TC11MP_PMU_SCU7	(IRQ_TC11MP_GIC_START + 28)
-
-#define IRQ_TC11MP_L220_EVENT	(IRQ_TC11MP_GIC_START + 29)
-#define IRQ_TC11MP_L220_SLAVE	(IRQ_TC11MP_GIC_START + 30)
-#define IRQ_TC11MP_L220_DECODE	(IRQ_TC11MP_GIC_START + 31)
-
-/*
- * RealView PB11MPCore GIC interrupt sources (secondary GIC on the board)
- */
-#define IRQ_PB11MP_WATCHDOG	(IRQ_PB11MP_GIC_START + 0)	/* Watchdog timer */
-#define IRQ_PB11MP_SOFT		(IRQ_PB11MP_GIC_START + 1)	/* Software interrupt */
-#define IRQ_PB11MP_COMMRx	(IRQ_PB11MP_GIC_START + 2)	/* Debug Comm Rx interrupt */
-#define IRQ_PB11MP_COMMTx	(IRQ_PB11MP_GIC_START + 3)	/* Debug Comm Tx interrupt */
-#define IRQ_PB11MP_GPIO0	(IRQ_PB11MP_GIC_START + 6)	/* GPIO 0 */
-#define IRQ_PB11MP_GPIO1	(IRQ_PB11MP_GIC_START + 7)	/* GPIO 1 */
-#define IRQ_PB11MP_GPIO2	(IRQ_PB11MP_GIC_START + 8)	/* GPIO 2 */
-								/* 9 reserved */
-#define IRQ_PB11MP_RTC_GIC1	(IRQ_PB11MP_GIC_START + 10)	/* Real Time Clock */
-#define IRQ_PB11MP_SSP		(IRQ_PB11MP_GIC_START + 11)	/* Synchronous Serial Port */
-#define IRQ_PB11MP_UART0_GIC1	(IRQ_PB11MP_GIC_START + 12)	/* UART 0 on development chip */
-#define IRQ_PB11MP_UART1_GIC1	(IRQ_PB11MP_GIC_START + 13)	/* UART 1 on development chip */
-#define IRQ_PB11MP_UART2	(IRQ_PB11MP_GIC_START + 14)	/* UART 2 on development chip */
-#define IRQ_PB11MP_UART3	(IRQ_PB11MP_GIC_START + 15)	/* UART 3 on development chip */
-#define IRQ_PB11MP_SCI		(IRQ_PB11MP_GIC_START + 16)	/* Smart Card Interface */
-#define IRQ_PB11MP_MMCI0A_GIC1	(IRQ_PB11MP_GIC_START + 17)	/* Multimedia Card 0A */
-#define IRQ_PB11MP_MMCI0B_GIC1	(IRQ_PB11MP_GIC_START + 18)	/* Multimedia Card 0B */
-#define IRQ_PB11MP_AACI_GIC1	(IRQ_PB11MP_GIC_START + 19)	/* Audio Codec */
-#define IRQ_PB11MP_KMI0_GIC1	(IRQ_PB11MP_GIC_START + 20)	/* Keyboard/Mouse port 0 */
-#define IRQ_PB11MP_KMI1_GIC1	(IRQ_PB11MP_GIC_START + 21)	/* Keyboard/Mouse port 1 */
-#define IRQ_PB11MP_CHARLCD	(IRQ_PB11MP_GIC_START + 22)	/* Character LCD */
-#define IRQ_PB11MP_CLCD		(IRQ_PB11MP_GIC_START + 23)	/* CLCD controller */
-#define IRQ_PB11MP_DMAC		(IRQ_PB11MP_GIC_START + 24)	/* DMA controller */
-#define IRQ_PB11MP_PWRFAIL	(IRQ_PB11MP_GIC_START + 25)	/* Power failure */
-#define IRQ_PB11MP_PISMO	(IRQ_PB11MP_GIC_START + 26)	/* PISMO interface */
-#define IRQ_PB11MP_DoC		(IRQ_PB11MP_GIC_START + 27)	/* Disk on Chip memory controller */
-#define IRQ_PB11MP_ETH_GIC1	(IRQ_PB11MP_GIC_START + 28)	/* Ethernet controller */
-#define IRQ_PB11MP_USB_GIC1	(IRQ_PB11MP_GIC_START + 29)	/* USB controller */
-#define IRQ_PB11MP_TSPEN	(IRQ_PB11MP_GIC_START + 30)	/* Touchscreen pen */
-#define IRQ_PB11MP_TSKPAD	(IRQ_PB11MP_GIC_START + 31)	/* Touchscreen keypad */
-
-#define IRQ_PB11MP_SMC		-1
-#define IRQ_PB11MP_SCTL		-1
-
-#define NR_GIC_PB11MP		2
-
-/*
- * Only define NR_IRQS if less than NR_IRQS_PB11MP
- */
-#define NR_IRQS_PB11MP		(IRQ_TC11MP_GIC_START + 96)
-
-#if defined(CONFIG_MACH_REALVIEW_PB11MP)
-
-#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB11MP)
-#undef NR_IRQS
-#define NR_IRQS			NR_IRQS_PB11MP
-#endif
-
-#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB11MP)
-#undef MAX_GIC_NR
-#define MAX_GIC_NR		NR_GIC_PB11MP
-#endif
-
-#endif	/* CONFIG_MACH_REALVIEW_PB11MP */
-
 #endif	/* __ASM_ARCH_BOARD_PB11MP_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pba8.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pba8.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pba8.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pba8.h	2009-09-09 18:13:59.000000000 -0400
@@ -70,81 +70,4 @@
 #define REALVIEW_PBA8_PCI_IO_SIZE		0x1000		/* 4 Kb */
 #define REALVIEW_PBA8_PCI_MEM_SIZE		0x20000000	/* 512 MB */
 
-/*
- * Irqs
- */
-#define IRQ_PBA8_GIC_START			32
-
-/* L220
-#define IRQ_PBA8_L220_EVENT	(IRQ_PBA8_GIC_START + 29)
-#define IRQ_PBA8_L220_SLAVE	(IRQ_PBA8_GIC_START + 30)
-#define IRQ_PBA8_L220_DECODE	(IRQ_PBA8_GIC_START + 31)
-*/
-
-/*
- * PB-A8 on-board gic irq sources
- */
-#define IRQ_PBA8_WATCHDOG	(IRQ_PBA8_GIC_START + 0)	/* Watchdog timer */
-#define IRQ_PBA8_SOFT		(IRQ_PBA8_GIC_START + 1)	/* Software interrupt */
-#define IRQ_PBA8_COMMRx		(IRQ_PBA8_GIC_START + 2)	/* Debug Comm Rx interrupt */
-#define IRQ_PBA8_COMMTx		(IRQ_PBA8_GIC_START + 3)	/* Debug Comm Tx interrupt */
-#define IRQ_PBA8_TIMER0_1	(IRQ_PBA8_GIC_START + 4)	/* Timer 0/1 (default timer) */
-#define IRQ_PBA8_TIMER2_3	(IRQ_PBA8_GIC_START + 5)	/* Timer 2/3 */
-#define IRQ_PBA8_GPIO0		(IRQ_PBA8_GIC_START + 6)	/* GPIO 0 */
-#define IRQ_PBA8_GPIO1		(IRQ_PBA8_GIC_START + 7)	/* GPIO 1 */
-#define IRQ_PBA8_GPIO2		(IRQ_PBA8_GIC_START + 8)	/* GPIO 2 */
-								/* 9 reserved */
-#define IRQ_PBA8_RTC		(IRQ_PBA8_GIC_START + 10)	/* Real Time Clock */
-#define IRQ_PBA8_SSP		(IRQ_PBA8_GIC_START + 11)	/* Synchronous Serial Port */
-#define IRQ_PBA8_UART0		(IRQ_PBA8_GIC_START + 12)	/* UART 0 on development chip */
-#define IRQ_PBA8_UART1		(IRQ_PBA8_GIC_START + 13)	/* UART 1 on development chip */
-#define IRQ_PBA8_UART2		(IRQ_PBA8_GIC_START + 14)	/* UART 2 on development chip */
-#define IRQ_PBA8_UART3		(IRQ_PBA8_GIC_START + 15)	/* UART 3 on development chip */
-#define IRQ_PBA8_SCI		(IRQ_PBA8_GIC_START + 16)	/* Smart Card Interface */
-#define IRQ_PBA8_MMCI0A		(IRQ_PBA8_GIC_START + 17)	/* Multimedia Card 0A */
-#define IRQ_PBA8_MMCI0B		(IRQ_PBA8_GIC_START + 18)	/* Multimedia Card 0B */
-#define IRQ_PBA8_AACI		(IRQ_PBA8_GIC_START + 19)	/* Audio Codec */
-#define IRQ_PBA8_KMI0		(IRQ_PBA8_GIC_START + 20)	/* Keyboard/Mouse port 0 */
-#define IRQ_PBA8_KMI1		(IRQ_PBA8_GIC_START + 21)	/* Keyboard/Mouse port 1 */
-#define IRQ_PBA8_CHARLCD	(IRQ_PBA8_GIC_START + 22)	/* Character LCD */
-#define IRQ_PBA8_CLCD		(IRQ_PBA8_GIC_START + 23)	/* CLCD controller */
-#define IRQ_PBA8_DMAC		(IRQ_PBA8_GIC_START + 24)	/* DMA controller */
-#define IRQ_PBA8_PWRFAIL	(IRQ_PBA8_GIC_START + 25)	/* Power failure */
-#define IRQ_PBA8_PISMO		(IRQ_PBA8_GIC_START + 26)	/* PISMO interface */
-#define IRQ_PBA8_DoC		(IRQ_PBA8_GIC_START + 27)	/* Disk on Chip memory controller */
-#define IRQ_PBA8_ETH		(IRQ_PBA8_GIC_START + 28)	/* Ethernet controller */
-#define IRQ_PBA8_USB		(IRQ_PBA8_GIC_START + 29)	/* USB controller */
-#define IRQ_PBA8_TSPEN		(IRQ_PBA8_GIC_START + 30)	/* Touchscreen pen */
-#define IRQ_PBA8_TSKPAD		(IRQ_PBA8_GIC_START + 31)	/* Touchscreen keypad */
-
-/* ... */
-#define IRQ_PBA8_PCI0		(IRQ_PBA8_GIC_START + 50)
-#define IRQ_PBA8_PCI1		(IRQ_PBA8_GIC_START + 51)
-#define IRQ_PBA8_PCI2		(IRQ_PBA8_GIC_START + 52)
-#define IRQ_PBA8_PCI3		(IRQ_PBA8_GIC_START + 53)
-
-#define IRQ_PBA8_SMC		-1
-#define IRQ_PBA8_SCTL		-1
-
-#define NR_GIC_PBA8		1
-
-/*
- * Only define NR_IRQS if less than NR_IRQS_PBA8
- */
-#define NR_IRQS_PBA8		(IRQ_PBA8_GIC_START + 64)
-
-#if defined(CONFIG_MACH_REALVIEW_PBA8)
-
-#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PBA8)
-#undef NR_IRQS
-#define NR_IRQS			NR_IRQS_PBA8
-#endif
-
-#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PBA8)
-#undef MAX_GIC_NR
-#define MAX_GIC_NR		NR_GIC_PBA8
-#endif
-
-#endif	/* CONFIG_MACH_REALVIEW_PBA8 */
-
 #endif	/* __ASM_ARCH_BOARD_PBA8_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pbx.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pbx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/board-pbx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/board-pbx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-realview/include/mach/board-pbx.h
+ *
+ * Copyright (C) 2009 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARCH_BOARD_PBX_H
+#define __ASM_ARCH_BOARD_PBX_H
+
+#include <mach/platform.h>
+
+/*
+ * Peripheral addresses
+ */
+#define REALVIEW_PBX_UART0_BASE			0x10009000	/* UART 0 */
+#define REALVIEW_PBX_UART1_BASE			0x1000A000	/* UART 1 */
+#define REALVIEW_PBX_UART2_BASE			0x1000B000	/* UART 2 */
+#define REALVIEW_PBX_UART3_BASE			0x1000C000	/* UART 3 */
+#define REALVIEW_PBX_SSP_BASE			0x1000D000	/* Synchronous Serial Port */
+#define REALVIEW_PBX_WATCHDOG0_BASE		0x1000F000	/* Watchdog 0 */
+#define REALVIEW_PBX_WATCHDOG_BASE		0x10010000	/* watchdog interface */
+#define REALVIEW_PBX_TIMER0_1_BASE		0x10011000	/* Timer 0 and 1 */
+#define REALVIEW_PBX_TIMER2_3_BASE		0x10012000	/* Timer 2 and 3 */
+#define REALVIEW_PBX_GPIO0_BASE			0x10013000	/* GPIO port 0 */
+#define REALVIEW_PBX_RTC_BASE			0x10017000	/* Real Time Clock */
+#define REALVIEW_PBX_TIMER4_5_BASE		0x10018000	/* Timer 4/5 */
+#define REALVIEW_PBX_TIMER6_7_BASE		0x10019000	/* Timer 6/7 */
+#define REALVIEW_PBX_SCTL_BASE			0x1001A000	/* System Controller */
+#define REALVIEW_PBX_CLCD_BASE			0x10020000	/* CLCD */
+#define REALVIEW_PBX_ONB_SRAM_BASE		0x10060000	/* On-board SRAM */
+#define REALVIEW_PBX_DMC_BASE			0x100E0000	/* DMC configuration */
+#define REALVIEW_PBX_SMC_BASE			0x100E1000	/* SMC configuration */
+#define REALVIEW_PBX_CAN_BASE			0x100E2000	/* CAN bus */
+#define REALVIEW_PBX_GIC_CPU_BASE		0x1E000000	/* Generic interrupt controller CPU interface */
+#define REALVIEW_PBX_FLASH0_BASE		0x40000000
+#define REALVIEW_PBX_FLASH0_SIZE		SZ_64M
+#define REALVIEW_PBX_FLASH1_BASE		0x44000000
+#define REALVIEW_PBX_FLASH1_SIZE		SZ_64M
+#define REALVIEW_PBX_ETH_BASE			0x4E000000	/* Ethernet */
+#define REALVIEW_PBX_USB_BASE			0x4F000000	/* USB */
+#define REALVIEW_PBX_GIC_DIST_BASE		0x1E001000	/* Generic interrupt controller distributor */
+#define REALVIEW_PBX_LT_BASE			0xC0000000	/* Logic Tile expansion */
+#define REALVIEW_PBX_SDRAM6_BASE		0x70000000	/* SDRAM bank 6 256MB */
+#define REALVIEW_PBX_SDRAM7_BASE		0x80000000	/* SDRAM bank 7 256MB */
+
+/*
+ * Tile-specific addresses
+ */
+#define REALVIEW_PBX_TILE_SCU_BASE		0x1F000000      /* SCU registers */
+#define REALVIEW_PBX_TILE_GIC_CPU_BASE		0x1F000100      /* Private Generic interrupt controller CPU interface */
+#define REALVIEW_PBX_TILE_TWD_BASE		0x1F000600
+#define REALVIEW_PBX_TILE_TWD_PERCPU_BASE	0x1F000700
+#define REALVIEW_PBX_TILE_TWD_SIZE		0x00000100
+#define REALVIEW_PBX_TILE_GIC_DIST_BASE		0x1F001000      /* Private Generic interrupt controller distributor */
+#define REALVIEW_PBX_TILE_L220_BASE		0x1F002000      /* L220 registers */
+
+#define REALVIEW_PBX_SYS_PLD_CTRL1		0x74
+
+/*
+ * PBX PCI regions
+ */
+#define REALVIEW_PBX_PCI_BASE			0x90040000	/* PCI-X Unit base */
+#define REALVIEW_PBX_PCI_IO_BASE		0x90050000	/* IO Region on AHB */
+#define REALVIEW_PBX_PCI_MEM_BASE		0xA0000000	/* MEM Region on AHB */
+
+#define REALVIEW_PBX_PCI_BASE_SIZE		0x10000		/* 16 Kb */
+#define REALVIEW_PBX_PCI_IO_SIZE		0x1000		/* 4 Kb */
+#define REALVIEW_PBX_PCI_MEM_SIZE		0x20000000	/* 512 MB */
+
+/*
+ * Core tile identification (REALVIEW_SYS_PROCID)
+ */
+#define REALVIEW_PBX_PROC_MASK          0xFF000000
+#define REALVIEW_PBX_PROC_ARM7TDMI      0x00000000
+#define REALVIEW_PBX_PROC_ARM9          0x02000000
+#define REALVIEW_PBX_PROC_ARM11         0x04000000
+#define REALVIEW_PBX_PROC_ARM11MP       0x06000000
+#define REALVIEW_PBX_PROC_A9MP          0x0C000000
+#define REALVIEW_PBX_PROC_A8            0x0E000000
+
+#define check_pbx_proc(proc_type)                                            \
+	((readl(__io_address(REALVIEW_SYS_PROCID)) & REALVIEW_PBX_PROC_MASK) \
+	== proc_type)
+
+#ifdef CONFIG_MACH_REALVIEW_PBX
+#define core_tile_pbx11mp()     check_pbx_proc(REALVIEW_PBX_PROC_ARM11MP)
+#define core_tile_pbxa9mp()     check_pbx_proc(REALVIEW_PBX_PROC_A9MP)
+#define core_tile_pbxa8()       check_pbx_proc(REALVIEW_PBX_PROC_A8)
+#else
+#define core_tile_pbx11mp()     0
+#define core_tile_pbxa9mp()     0
+#define core_tile_pbxa8()       0
+#endif
+
+#endif	/* __ASM_ARCH_BOARD_PBX_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/debug-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/debug-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/debug-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/debug-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,8 @@
 
 #if defined(CONFIG_MACH_REALVIEW_EB) || \
     defined(CONFIG_MACH_REALVIEW_PB11MP) || \
-    defined(CONFIG_MACH_REALVIEW_PBA8)
+    defined(CONFIG_MACH_REALVIEW_PBA8) || \
+    defined(CONFIG_MACH_REALVIEW_PBX)
 #ifndef DEBUG_LL_UART_OFFSET
 #define DEBUG_LL_UART_OFFSET	0x00009000
 #elif DEBUG_LL_UART_OFFSET != 0x00009000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-eb.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-eb.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-eb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-eb.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,129 @@
+/*
+ * arch/arm/mach-realview/include/mach/irqs-eb.h
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_IRQS_EB_H
+#define __MACH_IRQS_EB_H
+
+#define IRQ_EB_GIC_START	32
+
+/*
+ * RealView EB interrupt sources
+ */
+#define IRQ_EB_WDOG		(IRQ_EB_GIC_START + 0)		/* Watchdog timer */
+#define IRQ_EB_SOFT		(IRQ_EB_GIC_START + 1)		/* Software interrupt */
+#define IRQ_EB_COMMRx		(IRQ_EB_GIC_START + 2)		/* Debug Comm Rx interrupt */
+#define IRQ_EB_COMMTx		(IRQ_EB_GIC_START + 3)		/* Debug Comm Tx interrupt */
+#define IRQ_EB_TIMER0_1		(IRQ_EB_GIC_START + 4)		/* Timer 0 and 1 */
+#define IRQ_EB_TIMER2_3		(IRQ_EB_GIC_START + 5)		/* Timer 2 and 3 */
+#define IRQ_EB_GPIO0		(IRQ_EB_GIC_START + 6)		/* GPIO 0 */
+#define IRQ_EB_GPIO1		(IRQ_EB_GIC_START + 7)		/* GPIO 1 */
+#define IRQ_EB_GPIO2		(IRQ_EB_GIC_START + 8)		/* GPIO 2 */
+								/* 9 reserved */
+#define IRQ_EB_RTC		(IRQ_EB_GIC_START + 10)		/* Real Time Clock */
+#define IRQ_EB_SSP		(IRQ_EB_GIC_START + 11)		/* Synchronous Serial Port */
+#define IRQ_EB_UART0		(IRQ_EB_GIC_START + 12)		/* UART 0 on development chip */
+#define IRQ_EB_UART1		(IRQ_EB_GIC_START + 13)		/* UART 1 on development chip */
+#define IRQ_EB_UART2		(IRQ_EB_GIC_START + 14)		/* UART 2 on development chip */
+#define IRQ_EB_UART3		(IRQ_EB_GIC_START + 15)		/* UART 3 on development chip */
+#define IRQ_EB_SCI		(IRQ_EB_GIC_START + 16)		/* Smart Card Interface */
+#define IRQ_EB_MMCI0A		(IRQ_EB_GIC_START + 17)		/* Multimedia Card 0A */
+#define IRQ_EB_MMCI0B		(IRQ_EB_GIC_START + 18)		/* Multimedia Card 0B */
+#define IRQ_EB_AACI		(IRQ_EB_GIC_START + 19)		/* Audio Codec */
+#define IRQ_EB_KMI0		(IRQ_EB_GIC_START + 20)		/* Keyboard/Mouse port 0 */
+#define IRQ_EB_KMI1		(IRQ_EB_GIC_START + 21)		/* Keyboard/Mouse port 1 */
+#define IRQ_EB_CHARLCD		(IRQ_EB_GIC_START + 22)		/* Character LCD */
+#define IRQ_EB_CLCD		(IRQ_EB_GIC_START + 23)		/* CLCD controller */
+#define IRQ_EB_DMA		(IRQ_EB_GIC_START + 24)		/* DMA controller */
+#define IRQ_EB_PWRFAIL		(IRQ_EB_GIC_START + 25)		/* Power failure */
+#define IRQ_EB_PISMO		(IRQ_EB_GIC_START + 26)		/* PISMO interface */
+#define IRQ_EB_DoC		(IRQ_EB_GIC_START + 27)		/* Disk on Chip memory controller */
+#define IRQ_EB_ETH		(IRQ_EB_GIC_START + 28)		/* Ethernet controller */
+#define IRQ_EB_USB		(IRQ_EB_GIC_START + 29)		/* USB controller */
+#define IRQ_EB_TSPEN		(IRQ_EB_GIC_START + 30)		/* Touchscreen pen */
+#define IRQ_EB_TSKPAD		(IRQ_EB_GIC_START + 31)		/* Touchscreen keypad */
+
+/*
+ * RealView EB + ARM11MPCore interrupt sources (primary GIC on the core tile)
+ */
+#define IRQ_EB11MP_AACI		(IRQ_EB_GIC_START + 0)
+#define IRQ_EB11MP_TIMER0_1	(IRQ_EB_GIC_START + 1)
+#define IRQ_EB11MP_TIMER2_3	(IRQ_EB_GIC_START + 2)
+#define IRQ_EB11MP_USB		(IRQ_EB_GIC_START + 3)
+#define IRQ_EB11MP_UART0	(IRQ_EB_GIC_START + 4)
+#define IRQ_EB11MP_UART1	(IRQ_EB_GIC_START + 5)
+#define IRQ_EB11MP_RTC		(IRQ_EB_GIC_START + 6)
+#define IRQ_EB11MP_KMI0		(IRQ_EB_GIC_START + 7)
+#define IRQ_EB11MP_KMI1		(IRQ_EB_GIC_START + 8)
+#define IRQ_EB11MP_ETH		(IRQ_EB_GIC_START + 9)
+#define IRQ_EB11MP_EB_IRQ1	(IRQ_EB_GIC_START + 10)		/* main GIC */
+#define IRQ_EB11MP_EB_IRQ2	(IRQ_EB_GIC_START + 11)		/* tile GIC */
+#define IRQ_EB11MP_EB_FIQ1	(IRQ_EB_GIC_START + 12)		/* main GIC */
+#define IRQ_EB11MP_EB_FIQ2	(IRQ_EB_GIC_START + 13)		/* tile GIC */
+#define IRQ_EB11MP_MMCI0A	(IRQ_EB_GIC_START + 14)
+#define IRQ_EB11MP_MMCI0B	(IRQ_EB_GIC_START + 15)
+
+#define IRQ_EB11MP_PMU_CPU0	(IRQ_EB_GIC_START + 17)
+#define IRQ_EB11MP_PMU_CPU1	(IRQ_EB_GIC_START + 18)
+#define IRQ_EB11MP_PMU_CPU2	(IRQ_EB_GIC_START + 19)
+#define IRQ_EB11MP_PMU_CPU3	(IRQ_EB_GIC_START + 20)
+#define IRQ_EB11MP_PMU_SCU0	(IRQ_EB_GIC_START + 21)
+#define IRQ_EB11MP_PMU_SCU1	(IRQ_EB_GIC_START + 22)
+#define IRQ_EB11MP_PMU_SCU2	(IRQ_EB_GIC_START + 23)
+#define IRQ_EB11MP_PMU_SCU3	(IRQ_EB_GIC_START + 24)
+#define IRQ_EB11MP_PMU_SCU4	(IRQ_EB_GIC_START + 25)
+#define IRQ_EB11MP_PMU_SCU5	(IRQ_EB_GIC_START + 26)
+#define IRQ_EB11MP_PMU_SCU6	(IRQ_EB_GIC_START + 27)
+#define IRQ_EB11MP_PMU_SCU7	(IRQ_EB_GIC_START + 28)
+
+#define IRQ_EB11MP_L220_EVENT	(IRQ_EB_GIC_START + 29)
+#define IRQ_EB11MP_L220_SLAVE	(IRQ_EB_GIC_START + 30)
+#define IRQ_EB11MP_L220_DECODE	(IRQ_EB_GIC_START + 31)
+
+#define IRQ_EB11MP_UART2	-1
+#define IRQ_EB11MP_UART3	-1
+#define IRQ_EB11MP_CLCD		-1
+#define IRQ_EB11MP_DMA		-1
+#define IRQ_EB11MP_WDOG		-1
+#define IRQ_EB11MP_GPIO0	-1
+#define IRQ_EB11MP_GPIO1	-1
+#define IRQ_EB11MP_GPIO2	-1
+#define IRQ_EB11MP_SCI		-1
+#define IRQ_EB11MP_SSP		-1
+
+#define NR_GIC_EB11MP		2
+
+/*
+ * Only define NR_IRQS if less than NR_IRQS_EB
+ */
+#define NR_IRQS_EB		(IRQ_EB_GIC_START + 96)
+
+#if defined(CONFIG_MACH_REALVIEW_EB) \
+	&& (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB))
+#undef NR_IRQS
+#define NR_IRQS			NR_IRQS_EB
+#endif
+
+#if defined(CONFIG_REALVIEW_EB_ARM11MP) || defined(CONFIG_REALVIEW_EB_A9MP) \
+	&& (!defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_EB11MP))
+#undef MAX_GIC_NR
+#define MAX_GIC_NR		NR_GIC_EB11MP
+#endif
+
+#endif	/* __MACH_IRQS_EB_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,10 +22,11 @@
 #ifndef __ASM_ARCH_IRQS_H
 #define __ASM_ARCH_IRQS_H
 
-#include <mach/board-eb.h>
-#include <mach/board-pb11mp.h>
-#include <mach/board-pb1176.h>
-#include <mach/board-pba8.h>
+#include <mach/irqs-eb.h>
+#include <mach/irqs-pb11mp.h>
+#include <mach/irqs-pb1176.h>
+#include <mach/irqs-pba8.h>
+#include <mach/irqs-pbx.h>
 
 #define IRQ_LOCALTIMER		29
 #define IRQ_LOCALWDOG		30
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pb1176.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pb1176.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pb1176.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pb1176.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * arch/arm/mach-realview/include/mach/irqs-pb1176.h
+ *
+ * Copyright (C) 2008 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_IRQS_PB1176_H
+#define __MACH_IRQS_PB1176_H
+
+#define IRQ_DC1176_GIC_START			32
+#define IRQ_PB1176_GIC_START			64
+
+/*
+ * ARM1176 DevChip interrupt sources (primary GIC)
+ */
+#define IRQ_DC1176_WATCHDOG	(IRQ_DC1176_GIC_START + 0)	/* Watchdog timer */
+#define IRQ_DC1176_SOFTINT	(IRQ_DC1176_GIC_START + 1)	/* Software interrupt */
+#define IRQ_DC1176_COMMRx	(IRQ_DC1176_GIC_START + 2)	/* Debug Comm Rx interrupt */
+#define IRQ_DC1176_COMMTx	(IRQ_DC1176_GIC_START + 3)	/* Debug Comm Tx interrupt */
+#define IRQ_DC1176_TIMER0	(IRQ_DC1176_GIC_START + 8)	/* Timer 0 */
+#define IRQ_DC1176_TIMER1	(IRQ_DC1176_GIC_START + 9)	/* Timer 1 */
+#define IRQ_DC1176_TIMER2	(IRQ_DC1176_GIC_START + 10)	/* Timer 2 */
+#define IRQ_DC1176_APC		(IRQ_DC1176_GIC_START + 11)
+#define IRQ_DC1176_IEC		(IRQ_DC1176_GIC_START + 12)
+#define IRQ_DC1176_L2CC		(IRQ_DC1176_GIC_START + 13)
+#define IRQ_DC1176_RTC		(IRQ_DC1176_GIC_START + 14)
+#define IRQ_DC1176_CLCD		(IRQ_DC1176_GIC_START + 15)	/* CLCD controller */
+#define IRQ_DC1176_UART0	(IRQ_DC1176_GIC_START + 18)	/* UART 0 on development chip */
+#define IRQ_DC1176_UART1	(IRQ_DC1176_GIC_START + 19)	/* UART 1 on development chip */
+#define IRQ_DC1176_UART2	(IRQ_DC1176_GIC_START + 20)	/* UART 2 on development chip */
+#define IRQ_DC1176_UART3	(IRQ_DC1176_GIC_START + 21)	/* UART 3 on development chip */
+
+#define IRQ_DC1176_PB_IRQ2	(IRQ_DC1176_GIC_START + 30)	/* tile GIC */
+#define IRQ_DC1176_PB_IRQ1	(IRQ_DC1176_GIC_START + 31)	/* main GIC */
+
+/*
+ * RealView PB1176 interrupt sources (secondary GIC)
+ */
+#define IRQ_PB1176_MMCI0A	(IRQ_PB1176_GIC_START + 1)	/* Multimedia Card 0A */
+#define IRQ_PB1176_MMCI0B	(IRQ_PB1176_GIC_START + 2)	/* Multimedia Card 0A */
+#define IRQ_PB1176_KMI0		(IRQ_PB1176_GIC_START + 3)	/* Keyboard/Mouse port 0 */
+#define IRQ_PB1176_KMI1		(IRQ_PB1176_GIC_START + 4)	/* Keyboard/Mouse port 1 */
+#define IRQ_PB1176_SCI		(IRQ_PB1176_GIC_START + 5)
+#define IRQ_PB1176_UART4	(IRQ_PB1176_GIC_START + 6)	/* UART 4 on baseboard */
+#define IRQ_PB1176_CHARLCD	(IRQ_PB1176_GIC_START + 7)	/* Character LCD */
+#define IRQ_PB1176_GPIO1	(IRQ_PB1176_GIC_START + 8)
+#define IRQ_PB1176_GPIO2	(IRQ_PB1176_GIC_START + 9)
+#define IRQ_PB1176_ETH		(IRQ_PB1176_GIC_START + 10)	/* Ethernet controller */
+#define IRQ_PB1176_USB		(IRQ_PB1176_GIC_START + 11)	/* USB controller */
+
+#define IRQ_PB1176_PISMO	(IRQ_PB1176_GIC_START + 16)
+
+#define IRQ_PB1176_AACI		(IRQ_PB1176_GIC_START + 19)	/* Audio Codec */
+
+#define IRQ_PB1176_TIMER0_1	(IRQ_PB1176_GIC_START + 22)
+#define IRQ_PB1176_TIMER2_3	(IRQ_PB1176_GIC_START + 23)
+#define IRQ_PB1176_DMAC		(IRQ_PB1176_GIC_START + 24)	/* DMA controller */
+#define IRQ_PB1176_RTC		(IRQ_PB1176_GIC_START + 25)	/* Real Time Clock */
+
+#define IRQ_PB1176_GPIO0	-1
+#define IRQ_PB1176_SSP		-1
+#define IRQ_PB1176_SCTL		-1
+
+#define NR_GIC_PB1176		2
+
+/*
+ * Only define NR_IRQS if less than NR_IRQS_PB1176
+ */
+#define NR_IRQS_PB1176		(IRQ_DC1176_GIC_START + 96)
+
+#if defined(CONFIG_MACH_REALVIEW_PB1176)
+
+#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB1176)
+#undef NR_IRQS
+#define NR_IRQS			NR_IRQS_PB1176
+#endif
+
+#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB1176)
+#undef MAX_GIC_NR
+#define MAX_GIC_NR		NR_GIC_PB1176
+#endif
+
+#endif	/* CONFIG_MACH_REALVIEW_PB1176 */
+
+#endif	/* __MACH_IRQS_PB1176_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pb11mp.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pb11mp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pb11mp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pb11mp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,122 @@
+/*
+ * arch/arm/mach-realview/include/mach/irqs-pb11mp.h
+ *
+ * Copyright (C) 2008 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_IRQS_PB11MP_H
+#define __MACH_IRQS_PB11MP_H
+
+#define IRQ_TC11MP_GIC_START			32
+#define IRQ_PB11MP_GIC_START			64
+
+/*
+ * ARM11MPCore test chip interrupt sources (primary GIC on the test chip)
+ */
+#define IRQ_TC11MP_AACI		(IRQ_TC11MP_GIC_START + 0)
+#define IRQ_TC11MP_TIMER0_1	(IRQ_TC11MP_GIC_START + 1)
+#define IRQ_TC11MP_TIMER2_3	(IRQ_TC11MP_GIC_START + 2)
+#define IRQ_TC11MP_USB		(IRQ_TC11MP_GIC_START + 3)
+#define IRQ_TC11MP_UART0	(IRQ_TC11MP_GIC_START + 4)
+#define IRQ_TC11MP_UART1	(IRQ_TC11MP_GIC_START + 5)
+#define IRQ_TC11MP_RTC		(IRQ_TC11MP_GIC_START + 6)
+#define IRQ_TC11MP_KMI0		(IRQ_TC11MP_GIC_START + 7)
+#define IRQ_TC11MP_KMI1		(IRQ_TC11MP_GIC_START + 8)
+#define IRQ_TC11MP_ETH		(IRQ_TC11MP_GIC_START + 9)
+#define IRQ_TC11MP_PB_IRQ1	(IRQ_TC11MP_GIC_START + 10)		/* main GIC */
+#define IRQ_TC11MP_PB_IRQ2	(IRQ_TC11MP_GIC_START + 11)		/* tile GIC */
+#define IRQ_TC11MP_PB_FIQ1	(IRQ_TC11MP_GIC_START + 12)		/* main GIC */
+#define IRQ_TC11MP_PB_FIQ2	(IRQ_TC11MP_GIC_START + 13)		/* tile GIC */
+#define IRQ_TC11MP_MMCI0A	(IRQ_TC11MP_GIC_START + 14)
+#define IRQ_TC11MP_MMCI0B	(IRQ_TC11MP_GIC_START + 15)
+
+#define IRQ_TC11MP_PMU_CPU0	(IRQ_TC11MP_GIC_START + 17)
+#define IRQ_TC11MP_PMU_CPU1	(IRQ_TC11MP_GIC_START + 18)
+#define IRQ_TC11MP_PMU_CPU2	(IRQ_TC11MP_GIC_START + 19)
+#define IRQ_TC11MP_PMU_CPU3	(IRQ_TC11MP_GIC_START + 20)
+#define IRQ_TC11MP_PMU_SCU0	(IRQ_TC11MP_GIC_START + 21)
+#define IRQ_TC11MP_PMU_SCU1	(IRQ_TC11MP_GIC_START + 22)
+#define IRQ_TC11MP_PMU_SCU2	(IRQ_TC11MP_GIC_START + 23)
+#define IRQ_TC11MP_PMU_SCU3	(IRQ_TC11MP_GIC_START + 24)
+#define IRQ_TC11MP_PMU_SCU4	(IRQ_TC11MP_GIC_START + 25)
+#define IRQ_TC11MP_PMU_SCU5	(IRQ_TC11MP_GIC_START + 26)
+#define IRQ_TC11MP_PMU_SCU6	(IRQ_TC11MP_GIC_START + 27)
+#define IRQ_TC11MP_PMU_SCU7	(IRQ_TC11MP_GIC_START + 28)
+
+#define IRQ_TC11MP_L220_EVENT	(IRQ_TC11MP_GIC_START + 29)
+#define IRQ_TC11MP_L220_SLAVE	(IRQ_TC11MP_GIC_START + 30)
+#define IRQ_TC11MP_L220_DECODE	(IRQ_TC11MP_GIC_START + 31)
+
+/*
+ * RealView PB11MPCore GIC interrupt sources (secondary GIC on the board)
+ */
+#define IRQ_PB11MP_WATCHDOG	(IRQ_PB11MP_GIC_START + 0)	/* Watchdog timer */
+#define IRQ_PB11MP_SOFT		(IRQ_PB11MP_GIC_START + 1)	/* Software interrupt */
+#define IRQ_PB11MP_COMMRx	(IRQ_PB11MP_GIC_START + 2)	/* Debug Comm Rx interrupt */
+#define IRQ_PB11MP_COMMTx	(IRQ_PB11MP_GIC_START + 3)	/* Debug Comm Tx interrupt */
+#define IRQ_PB11MP_GPIO0	(IRQ_PB11MP_GIC_START + 6)	/* GPIO 0 */
+#define IRQ_PB11MP_GPIO1	(IRQ_PB11MP_GIC_START + 7)	/* GPIO 1 */
+#define IRQ_PB11MP_GPIO2	(IRQ_PB11MP_GIC_START + 8)	/* GPIO 2 */
+								/* 9 reserved */
+#define IRQ_PB11MP_RTC_GIC1	(IRQ_PB11MP_GIC_START + 10)	/* Real Time Clock */
+#define IRQ_PB11MP_SSP		(IRQ_PB11MP_GIC_START + 11)	/* Synchronous Serial Port */
+#define IRQ_PB11MP_UART0_GIC1	(IRQ_PB11MP_GIC_START + 12)	/* UART 0 on development chip */
+#define IRQ_PB11MP_UART1_GIC1	(IRQ_PB11MP_GIC_START + 13)	/* UART 1 on development chip */
+#define IRQ_PB11MP_UART2	(IRQ_PB11MP_GIC_START + 14)	/* UART 2 on development chip */
+#define IRQ_PB11MP_UART3	(IRQ_PB11MP_GIC_START + 15)	/* UART 3 on development chip */
+#define IRQ_PB11MP_SCI		(IRQ_PB11MP_GIC_START + 16)	/* Smart Card Interface */
+#define IRQ_PB11MP_MMCI0A_GIC1	(IRQ_PB11MP_GIC_START + 17)	/* Multimedia Card 0A */
+#define IRQ_PB11MP_MMCI0B_GIC1	(IRQ_PB11MP_GIC_START + 18)	/* Multimedia Card 0B */
+#define IRQ_PB11MP_AACI_GIC1	(IRQ_PB11MP_GIC_START + 19)	/* Audio Codec */
+#define IRQ_PB11MP_KMI0_GIC1	(IRQ_PB11MP_GIC_START + 20)	/* Keyboard/Mouse port 0 */
+#define IRQ_PB11MP_KMI1_GIC1	(IRQ_PB11MP_GIC_START + 21)	/* Keyboard/Mouse port 1 */
+#define IRQ_PB11MP_CHARLCD	(IRQ_PB11MP_GIC_START + 22)	/* Character LCD */
+#define IRQ_PB11MP_CLCD		(IRQ_PB11MP_GIC_START + 23)	/* CLCD controller */
+#define IRQ_PB11MP_DMAC		(IRQ_PB11MP_GIC_START + 24)	/* DMA controller */
+#define IRQ_PB11MP_PWRFAIL	(IRQ_PB11MP_GIC_START + 25)	/* Power failure */
+#define IRQ_PB11MP_PISMO	(IRQ_PB11MP_GIC_START + 26)	/* PISMO interface */
+#define IRQ_PB11MP_DoC		(IRQ_PB11MP_GIC_START + 27)	/* Disk on Chip memory controller */
+#define IRQ_PB11MP_ETH_GIC1	(IRQ_PB11MP_GIC_START + 28)	/* Ethernet controller */
+#define IRQ_PB11MP_USB_GIC1	(IRQ_PB11MP_GIC_START + 29)	/* USB controller */
+#define IRQ_PB11MP_TSPEN	(IRQ_PB11MP_GIC_START + 30)	/* Touchscreen pen */
+#define IRQ_PB11MP_TSKPAD	(IRQ_PB11MP_GIC_START + 31)	/* Touchscreen keypad */
+
+#define IRQ_PB11MP_SMC		-1
+#define IRQ_PB11MP_SCTL		-1
+
+#define NR_GIC_PB11MP		2
+
+/*
+ * Only define NR_IRQS if less than NR_IRQS_PB11MP
+ */
+#define NR_IRQS_PB11MP		(IRQ_TC11MP_GIC_START + 96)
+
+#if defined(CONFIG_MACH_REALVIEW_PB11MP)
+
+#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB11MP)
+#undef NR_IRQS
+#define NR_IRQS			NR_IRQS_PB11MP
+#endif
+
+#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB11MP)
+#undef MAX_GIC_NR
+#define MAX_GIC_NR		NR_GIC_PB11MP
+#endif
+
+#endif	/* CONFIG_MACH_REALVIEW_PB11MP */
+
+#endif	/* __MACH_IRQS_PB11MP_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pba8.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pba8.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pba8.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pba8.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * arch/arm/mach-realview/include/mach/irqs-pba8.h
+ *
+ * Copyright (C) 2008 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __MACH_IRQS_PBA8_H
+#define __MACH_IRQS_PBA8_H
+
+#define IRQ_PBA8_GIC_START			32
+
+/* L220
+#define IRQ_PBA8_L220_EVENT	(IRQ_PBA8_GIC_START + 29)
+#define IRQ_PBA8_L220_SLAVE	(IRQ_PBA8_GIC_START + 30)
+#define IRQ_PBA8_L220_DECODE	(IRQ_PBA8_GIC_START + 31)
+*/
+
+/*
+ * PB-A8 on-board gic irq sources
+ */
+#define IRQ_PBA8_WATCHDOG	(IRQ_PBA8_GIC_START + 0)	/* Watchdog timer */
+#define IRQ_PBA8_SOFT		(IRQ_PBA8_GIC_START + 1)	/* Software interrupt */
+#define IRQ_PBA8_COMMRx		(IRQ_PBA8_GIC_START + 2)	/* Debug Comm Rx interrupt */
+#define IRQ_PBA8_COMMTx		(IRQ_PBA8_GIC_START + 3)	/* Debug Comm Tx interrupt */
+#define IRQ_PBA8_TIMER0_1	(IRQ_PBA8_GIC_START + 4)	/* Timer 0/1 (default timer) */
+#define IRQ_PBA8_TIMER2_3	(IRQ_PBA8_GIC_START + 5)	/* Timer 2/3 */
+#define IRQ_PBA8_GPIO0		(IRQ_PBA8_GIC_START + 6)	/* GPIO 0 */
+#define IRQ_PBA8_GPIO1		(IRQ_PBA8_GIC_START + 7)	/* GPIO 1 */
+#define IRQ_PBA8_GPIO2		(IRQ_PBA8_GIC_START + 8)	/* GPIO 2 */
+								/* 9 reserved */
+#define IRQ_PBA8_RTC		(IRQ_PBA8_GIC_START + 10)	/* Real Time Clock */
+#define IRQ_PBA8_SSP		(IRQ_PBA8_GIC_START + 11)	/* Synchronous Serial Port */
+#define IRQ_PBA8_UART0		(IRQ_PBA8_GIC_START + 12)	/* UART 0 on development chip */
+#define IRQ_PBA8_UART1		(IRQ_PBA8_GIC_START + 13)	/* UART 1 on development chip */
+#define IRQ_PBA8_UART2		(IRQ_PBA8_GIC_START + 14)	/* UART 2 on development chip */
+#define IRQ_PBA8_UART3		(IRQ_PBA8_GIC_START + 15)	/* UART 3 on development chip */
+#define IRQ_PBA8_SCI		(IRQ_PBA8_GIC_START + 16)	/* Smart Card Interface */
+#define IRQ_PBA8_MMCI0A		(IRQ_PBA8_GIC_START + 17)	/* Multimedia Card 0A */
+#define IRQ_PBA8_MMCI0B		(IRQ_PBA8_GIC_START + 18)	/* Multimedia Card 0B */
+#define IRQ_PBA8_AACI		(IRQ_PBA8_GIC_START + 19)	/* Audio Codec */
+#define IRQ_PBA8_KMI0		(IRQ_PBA8_GIC_START + 20)	/* Keyboard/Mouse port 0 */
+#define IRQ_PBA8_KMI1		(IRQ_PBA8_GIC_START + 21)	/* Keyboard/Mouse port 1 */
+#define IRQ_PBA8_CHARLCD	(IRQ_PBA8_GIC_START + 22)	/* Character LCD */
+#define IRQ_PBA8_CLCD		(IRQ_PBA8_GIC_START + 23)	/* CLCD controller */
+#define IRQ_PBA8_DMAC		(IRQ_PBA8_GIC_START + 24)	/* DMA controller */
+#define IRQ_PBA8_PWRFAIL	(IRQ_PBA8_GIC_START + 25)	/* Power failure */
+#define IRQ_PBA8_PISMO		(IRQ_PBA8_GIC_START + 26)	/* PISMO interface */
+#define IRQ_PBA8_DoC		(IRQ_PBA8_GIC_START + 27)	/* Disk on Chip memory controller */
+#define IRQ_PBA8_ETH		(IRQ_PBA8_GIC_START + 28)	/* Ethernet controller */
+#define IRQ_PBA8_USB		(IRQ_PBA8_GIC_START + 29)	/* USB controller */
+#define IRQ_PBA8_TSPEN		(IRQ_PBA8_GIC_START + 30)	/* Touchscreen pen */
+#define IRQ_PBA8_TSKPAD		(IRQ_PBA8_GIC_START + 31)	/* Touchscreen keypad */
+
+/* ... */
+#define IRQ_PBA8_PCI0		(IRQ_PBA8_GIC_START + 50)
+#define IRQ_PBA8_PCI1		(IRQ_PBA8_GIC_START + 51)
+#define IRQ_PBA8_PCI2		(IRQ_PBA8_GIC_START + 52)
+#define IRQ_PBA8_PCI3		(IRQ_PBA8_GIC_START + 53)
+
+#define IRQ_PBA8_SMC		-1
+#define IRQ_PBA8_SCTL		-1
+
+#define NR_GIC_PBA8		1
+
+/*
+ * Only define NR_IRQS if less than NR_IRQS_PBA8
+ */
+#define NR_IRQS_PBA8		(IRQ_PBA8_GIC_START + 64)
+
+#if defined(CONFIG_MACH_REALVIEW_PBA8)
+
+#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PBA8)
+#undef NR_IRQS
+#define NR_IRQS			NR_IRQS_PBA8
+#endif
+
+#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PBA8)
+#undef MAX_GIC_NR
+#define MAX_GIC_NR		NR_GIC_PBA8
+#endif
+
+#endif	/* CONFIG_MACH_REALVIEW_PBA8 */
+
+#endif	/* __MACH_IRQS_PBA8_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pbx.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pbx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/irqs-pbx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/irqs-pbx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ * arch/arm/mach-realview/include/mach/irqs-pbx.h
+ *
+ * Copyright (C) 2009 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __MACH_IRQS_PBX_H
+#define __MACH_IRQS_PBX_H
+
+#define IRQ_PBX_GIC_START			32
+
+/* L220
+#define IRQ_PBX_L220_EVENT	(IRQ_PBX_GIC_START + 29)
+#define IRQ_PBX_L220_SLAVE	(IRQ_PBX_GIC_START + 30)
+#define IRQ_PBX_L220_DECODE	(IRQ_PBX_GIC_START + 31)
+*/
+
+/*
+ * PBX on-board gic irq sources
+ */
+#define IRQ_PBX_WATCHDOG	(IRQ_PBX_GIC_START + 0)	/* Watchdog timer */
+#define IRQ_PBX_SOFT		(IRQ_PBX_GIC_START + 1)	/* Software interrupt */
+#define IRQ_PBX_COMMRx		(IRQ_PBX_GIC_START + 2)	/* Debug Comm Rx interrupt */
+#define IRQ_PBX_COMMTx		(IRQ_PBX_GIC_START + 3)	/* Debug Comm Tx interrupt */
+#define IRQ_PBX_TIMER0_1	(IRQ_PBX_GIC_START + 4)	/* Timer 0/1 (default timer) */
+#define IRQ_PBX_TIMER2_3	(IRQ_PBX_GIC_START + 5)	/* Timer 2/3 */
+#define IRQ_PBX_GPIO0		(IRQ_PBX_GIC_START + 6)	/* GPIO 0 */
+#define IRQ_PBX_GPIO1		(IRQ_PBX_GIC_START + 7)	/* GPIO 1 */
+#define IRQ_PBX_GPIO2		(IRQ_PBX_GIC_START + 8)	/* GPIO 2 */
+								/* 9 reserved */
+#define IRQ_PBX_RTC		(IRQ_PBX_GIC_START + 10)	/* Real Time Clock */
+#define IRQ_PBX_SSP		(IRQ_PBX_GIC_START + 11)	/* Synchronous Serial Port */
+#define IRQ_PBX_UART0		(IRQ_PBX_GIC_START + 12)	/* UART 0 on development chip */
+#define IRQ_PBX_UART1		(IRQ_PBX_GIC_START + 13)	/* UART 1 on development chip */
+#define IRQ_PBX_UART2		(IRQ_PBX_GIC_START + 14)	/* UART 2 on development chip */
+#define IRQ_PBX_UART3		(IRQ_PBX_GIC_START + 15)	/* UART 3 on development chip */
+#define IRQ_PBX_SCI		(IRQ_PBX_GIC_START + 16)	/* Smart Card Interface */
+#define IRQ_PBX_MMCI0A		(IRQ_PBX_GIC_START + 17)	/* Multimedia Card 0A */
+#define IRQ_PBX_MMCI0B		(IRQ_PBX_GIC_START + 18)	/* Multimedia Card 0B */
+#define IRQ_PBX_AACI		(IRQ_PBX_GIC_START + 19)	/* Audio Codec */
+#define IRQ_PBX_KMI0		(IRQ_PBX_GIC_START + 20)	/* Keyboard/Mouse port 0 */
+#define IRQ_PBX_KMI1		(IRQ_PBX_GIC_START + 21)	/* Keyboard/Mouse port 1 */
+#define IRQ_PBX_CHARLCD		(IRQ_PBX_GIC_START + 22)	/* Character LCD */
+#define IRQ_PBX_CLCD		(IRQ_PBX_GIC_START + 23)	/* CLCD controller */
+#define IRQ_PBX_DMAC		(IRQ_PBX_GIC_START + 24)	/* DMA controller */
+#define IRQ_PBX_PWRFAIL		(IRQ_PBX_GIC_START + 25)	/* Power failure */
+#define IRQ_PBX_PISMO		(IRQ_PBX_GIC_START + 26)	/* PISMO interface */
+#define IRQ_PBX_DoC		(IRQ_PBX_GIC_START + 27)	/* Disk on Chip memory controller */
+#define IRQ_PBX_ETH		(IRQ_PBX_GIC_START + 28)	/* Ethernet controller */
+#define IRQ_PBX_USB		(IRQ_PBX_GIC_START + 29)	/* USB controller */
+#define IRQ_PBX_TSPEN		(IRQ_PBX_GIC_START + 30)	/* Touchscreen pen */
+#define IRQ_PBX_TSKPAD		(IRQ_PBX_GIC_START + 31)	/* Touchscreen keypad */
+
+#define IRQ_PBX_PMU_SCU0        (IRQ_PBX_GIC_START + 32)        /* SCU PMU Interrupts (11mp) */
+#define IRQ_PBX_PMU_SCU1        (IRQ_PBX_GIC_START + 33)
+#define IRQ_PBX_PMU_SCU2        (IRQ_PBX_GIC_START + 34)
+#define IRQ_PBX_PMU_SCU3        (IRQ_PBX_GIC_START + 35)
+#define IRQ_PBX_PMU_SCU4        (IRQ_PBX_GIC_START + 36)
+#define IRQ_PBX_PMU_SCU5        (IRQ_PBX_GIC_START + 37)
+#define IRQ_PBX_PMU_SCU6        (IRQ_PBX_GIC_START + 38)
+#define IRQ_PBX_PMU_SCU7        (IRQ_PBX_GIC_START + 39)
+
+#define IRQ_PBX_WATCHDOG1       (IRQ_PBX_GIC_START + 40)        /* Watchdog1 timer */
+#define IRQ_PBX_TIMER4_5        (IRQ_PBX_GIC_START + 41)        /* Timer 0/1 (default timer) */
+#define IRQ_PBX_TIMER6_7        (IRQ_PBX_GIC_START + 42)        /* Timer 2/3 */
+/* ... */
+#define IRQ_PBX_PMU_CPU3        (IRQ_PBX_GIC_START + 44)        /* CPU PMU Interrupts */
+#define IRQ_PBX_PMU_CPU2        (IRQ_PBX_GIC_START + 45)
+#define IRQ_PBX_PMU_CPU1        (IRQ_PBX_GIC_START + 46)
+#define IRQ_PBX_PMU_CPU0        (IRQ_PBX_GIC_START + 47)
+
+/* ... */
+#define IRQ_PBX_PCI0		(IRQ_PBX_GIC_START + 50)
+#define IRQ_PBX_PCI1		(IRQ_PBX_GIC_START + 51)
+#define IRQ_PBX_PCI2		(IRQ_PBX_GIC_START + 52)
+#define IRQ_PBX_PCI3		(IRQ_PBX_GIC_START + 53)
+
+#define IRQ_PBX_SMC		-1
+#define IRQ_PBX_SCTL		-1
+
+#define NR_GIC_PBX		1
+
+/*
+ * Only define NR_IRQS if less than NR_IRQS_PBX
+ */
+#define NR_IRQS_PBX		(IRQ_PBX_GIC_START + 96)
+
+#if defined(CONFIG_MACH_REALVIEW_PBX)
+
+#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PBX)
+#undef NR_IRQS
+#define NR_IRQS			NR_IRQS_PBX
+#endif
+
+#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PBX)
+#undef MAX_GIC_NR
+#define MAX_GIC_NR		NR_GIC_PBX
+#endif
+
+#endif	/* CONFIG_MACH_REALVIEW_PBX */
+
+#endif	/* __MACH_IRQS_PBX_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/scu.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/scu.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/scu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/scu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-#ifndef __ASMARM_ARCH_SCU_H
-#define __ASMARM_ARCH_SCU_H
-
-/*
- * SCU registers
- */
-#define SCU_CTRL		0x00
-#define SCU_CONFIG		0x04
-#define SCU_CPU_STATUS		0x08
-#define SCU_INVALIDATE		0x0c
-#define SCU_FPGA_REVISION	0x10
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/uncompress.h linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/uncompress.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/include/mach/uncompress.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/include/mach/uncompress.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 #include <mach/board-pb11mp.h>
 #include <mach/board-pb1176.h>
 #include <mach/board-pba8.h>
+#include <mach/board-pbx.h>
 
 #define AMBA_UART_DR(base)	(*(volatile unsigned char *)((base) + 0x00))
 #define AMBA_UART_LCRH(base)	(*(volatile unsigned char *)((base) + 0x2c))
@@ -43,6 +44,8 @@
 		return REALVIEW_PB1176_UART0_BASE;
 	else if (machine_is_realview_pba8())
 		return REALVIEW_PBA8_UART0_BASE;
+	else if (machine_is_realview_pbx())
+		return REALVIEW_PBX_UART0_BASE;
 	else
 		return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-realview/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -24,7 +24,6 @@
 config REALVIEW_EB_ARM11MP_REVB
 	bool "Support ARM11MPCore RevB tile"
 	depends on REALVIEW_EB_ARM11MP
-	default n
 	help
 	  Enable support for the ARM11MPCore RevB tile on the Realview
 	  platform. Since there are device address differences, a
@@ -48,6 +47,15 @@
 	help
 	  Include support for the ARM(R) RealView ARM1176 Platform Baseboard.
 
+config REALVIEW_PB1176_SECURE_FLASH
+	bool "Allow access to the secure flash memory block"
+	depends on MACH_REALVIEW_PB1176
+	default n
+	help
+	  Select this option if Linux will only run in secure mode on the
+	  RealView PB1176 platform and access to the secure flash memory
+	  block (64MB @ 0x3c000000) is required.
+
 config MACH_REALVIEW_PBA8
 	bool "Support RealView/PB-A8 platform"
 	select CPU_V7
@@ -58,6 +66,13 @@
 	  PB-A8 is a platform with an on-board Cortex-A8 and has support for
 	  PCI-E and Compact Flash.
 
+config MACH_REALVIEW_PBX
+	bool "Support RealView/PBX platform"
+	select ARM_GIC
+	select HAVE_PATA_PLATFORM
+	help
+	  Include support for the ARM(R) RealView PBX platform.
+
 config REALVIEW_HIGH_PHYS_OFFSET
 	bool "High physical base address for the RealView platform"
 	depends on !MACH_REALVIEW_PB1176
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/localtimer.c linux-libre-2.6.31-gnu/arch/arm/mach-realview/localtimer.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/localtimer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/localtimer.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,196 +9,18 @@
  * published by the Free Software Foundation.
  */
 #include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/device.h>
 #include <linux/smp.h>
-#include <linux/jiffies.h>
-#include <linux/percpu.h>
 #include <linux/clockchips.h>
-#include <linux/irq.h>
-#include <linux/io.h>
 
-#include <asm/hardware/arm_twd.h>
-#include <asm/hardware/gic.h>
-#include <mach/hardware.h>
 #include <asm/irq.h>
-
-static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
-
-/*
- * Used on SMP for either the local timer or IPI_TIMER
- */
-void local_timer_interrupt(void)
-{
-	struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
-
-	clk->event_handler(clk);
-}
-
-#ifdef CONFIG_LOCAL_TIMERS
-
-/* set up by the platform code */
-void __iomem *twd_base;
-
-static unsigned long mpcore_timer_rate;
-
-static void local_timer_set_mode(enum clock_event_mode mode,
-				 struct clock_event_device *clk)
-{
-	unsigned long ctrl;
-
-	switch(mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		/* timer load already set up */
-		ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
-			| TWD_TIMER_CONTROL_PERIODIC;
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		/* period set, and timer enabled in 'next_event' hook */
-		ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	default:
-		ctrl = 0;
-	}
-
-	__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
-}
-
-static int local_timer_set_next_event(unsigned long evt,
-				      struct clock_event_device *unused)
-{
-	unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
-
-	__raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
-	__raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, twd_base + TWD_TIMER_CONTROL);
-
-	return 0;
-}
-
-/*
- * local_timer_ack: checks for a local timer interrupt.
- *
- * If a local timer interrupt has occurred, acknowledge and return 1.
- * Otherwise, return 0.
- */
-int local_timer_ack(void)
-{
-	if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
-		__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
-		return 1;
-	}
-
-	return 0;
-}
-
-static void __cpuinit twd_calibrate_rate(void)
-{
-	unsigned long load, count;
-	u64 waitjiffies;
-
-	/*
-	 * If this is the first time round, we need to work out how fast
-	 * the timer ticks
-	 */
-	if (mpcore_timer_rate == 0) {
-		printk("Calibrating local timer... ");
-
-		/* Wait for a tick to start */
-		waitjiffies = get_jiffies_64() + 1;
-
-		while (get_jiffies_64() < waitjiffies)
-			udelay(10);
-
-		/* OK, now the tick has started, let's get the timer going */
-		waitjiffies += 5;
-
-				 /* enable, no interrupt or reload */
-		__raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
-
-				 /* maximum value */
-		__raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
-
-		while (get_jiffies_64() < waitjiffies)
-			udelay(10);
-
-		count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
-
-		mpcore_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
-
-		printk("%lu.%02luMHz.\n", mpcore_timer_rate / 1000000,
-			(mpcore_timer_rate / 100000) % 100);
-	}
-
-	load = mpcore_timer_rate / HZ;
-
-	__raw_writel(load, twd_base + TWD_TIMER_LOAD);
-}
+#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
 
 /*
  * Setup the local clock events for a CPU.
  */
-void __cpuinit local_timer_setup(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
-	unsigned long flags;
-
-	twd_calibrate_rate();
-
-	clk->name		= "local_timer";
-	clk->features		= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-	clk->rating		= 350;
-	clk->set_mode		= local_timer_set_mode;
-	clk->set_next_event	= local_timer_set_next_event;
-	clk->irq		= IRQ_LOCALTIMER;
-	clk->cpumask		= cpumask_of(cpu);
-	clk->shift		= 20;
-	clk->mult		= div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift);
-	clk->max_delta_ns	= clockevent_delta2ns(0xffffffff, clk);
-	clk->min_delta_ns	= clockevent_delta2ns(0xf, clk);
-
-	/* Make sure our local interrupt controller has this enabled */
-	local_irq_save(flags);
-	get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER);
-	local_irq_restore(flags);
-
-	clockevents_register_device(clk);
-}
-
-/*
- * take a local timer down
- */
-void __cpuexit local_timer_stop(void)
-{
-	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-}
-
-#else	/* CONFIG_LOCAL_TIMERS */
-
-static void dummy_timer_set_mode(enum clock_event_mode mode,
-				 struct clock_event_device *clk)
-{
-}
-
-void __cpuinit local_timer_setup(void)
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
-	unsigned int cpu = smp_processor_id();
-	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
-
-	clk->name		= "dummy_timer";
-	clk->features		= CLOCK_EVT_FEAT_ONESHOT |
-				  CLOCK_EVT_FEAT_PERIODIC |
-				  CLOCK_EVT_FEAT_DUMMY;
-	clk->rating		= 400;
-	clk->mult               = 1;
-	clk->set_mode		= dummy_timer_set_mode;
-	clk->broadcast		= smp_timer_broadcast;
-	clk->cpumask		= cpumask_of(cpu);
-
-	clockevents_register_device(clk);
+	evt->irq = IRQ_LOCALTIMER;
+	twd_timer_setup(evt);
 }
-
-#endif	/* !CONFIG_LOCAL_TIMERS */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-realview/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,5 +7,7 @@
 obj-$(CONFIG_MACH_REALVIEW_PB11MP)	+= realview_pb11mp.o
 obj-$(CONFIG_MACH_REALVIEW_PB1176)	+= realview_pb1176.o
 obj-$(CONFIG_MACH_REALVIEW_PBA8)	+= realview_pba8.o
-obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o localtimer.o
+obj-$(CONFIG_MACH_REALVIEW_PBX)		+= realview_pbx.o
+obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/platsmp.c linux-libre-2.6.31-gnu/arch/arm/mach-realview/platsmp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/platsmp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/platsmp.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,10 +19,12 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
+#include <asm/localtimer.h>
 
 #include <mach/board-eb.h>
 #include <mach/board-pb11mp.h>
-#include <mach/scu.h>
+#include <mach/board-pbx.h>
+#include <asm/smp_scu.h>
 
 #include "core.h"
 
@@ -40,35 +42,19 @@
 		return __io_address(REALVIEW_EB11MP_SCU_BASE);
 	else if (machine_is_realview_pb11mp())
 		return __io_address(REALVIEW_TC11MP_SCU_BASE);
+	else if (machine_is_realview_pbx() &&
+		 (core_tile_pbx11mp() || core_tile_pbxa9mp()))
+		return __io_address(REALVIEW_PBX_TILE_SCU_BASE);
 	else
 		return (void __iomem *)0;
 }
 
-static unsigned int __init get_core_count(void)
-{
-	unsigned int ncores;
-	void __iomem *scu_base = scu_base_addr();
-
-	if (scu_base) {
-		ncores = __raw_readl(scu_base + SCU_CONFIG);
-		ncores = (ncores & 0x03) + 1;
-	} else
-		ncores = 1;
-
-	return ncores;
-}
-
-/*
- * Setup the SCU
- */
-static void scu_enable(void)
+static inline unsigned int get_core_count(void)
 {
-	u32 scu_ctrl;
 	void __iomem *scu_base = scu_base_addr();
-
-	scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
-	scu_ctrl |= 1;
-	__raw_writel(scu_ctrl, scu_base + SCU_CTRL);
+	if (scu_base)
+		return scu_get_core_count(scu_base);
+	return 1;
 }
 
 static DEFINE_SPINLOCK(boot_lock);
@@ -184,7 +170,7 @@
 	unsigned int i, ncores = get_core_count();
 
 	for (i = 0; i < ncores; i++)
-		cpu_set(i, cpu_possible_map);
+		set_cpu_possible(i, true);
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -217,19 +203,12 @@
 	if (max_cpus > ncores)
 		max_cpus = ncores;
 
-#if defined(CONFIG_LOCAL_TIMERS) || defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
-	/*
-	 * Enable the local timer or broadcast device for the boot CPU.
-	 */
-	local_timer_setup();
-#endif
-
 	/*
 	 * Initialise the present map, which describes the set of CPUs
 	 * actually populated at the present time.
 	 */
 	for (i = 0; i < max_cpus; i++)
-		cpu_set(i, cpu_present_map);
+		set_cpu_present(i, true);
 
 	/*
 	 * Initialise the SCU if there are more than one CPU and let
@@ -239,7 +218,13 @@
 	 * WFI
 	 */
 	if (max_cpus > 1) {
-		scu_enable();
+		/*
+		 * Enable the local timer or broadcast device for the
+		 * boot CPU, but only if we have more than one CPU.
+		 */
+		percpu_timer_setup();
+
+		scu_enable(scu_base_addr());
 		poke_milo();
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_eb.c linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_eb.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_eb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_eb.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/localtimer.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_pb1176.c linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_pb1176.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_pb1176.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_pb1176.c	2009-09-09 18:13:59.000000000 -0400
@@ -203,11 +203,23 @@
 /*
  * RealView PB1176 platform devices
  */
-static struct resource realview_pb1176_flash_resource = {
-	.start			= REALVIEW_PB1176_FLASH_BASE,
-	.end			= REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1,
-	.flags			= IORESOURCE_MEM,
+static struct resource realview_pb1176_flash_resources[] = {
+	[0] = {
+		.start		= REALVIEW_PB1176_FLASH_BASE,
+		.end		= REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= REALVIEW_PB1176_SEC_FLASH_BASE,
+		.end		= REALVIEW_PB1176_SEC_FLASH_BASE + REALVIEW_PB1176_SEC_FLASH_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
 };
+#ifdef CONFIG_REALVIEW_PB1176_SECURE_FLASH
+#define PB1176_FLASH_BLOCKS	2
+#else
+#define PB1176_FLASH_BLOCKS	1
+#endif
 
 static struct resource realview_pb1176_smsc911x_resources[] = {
 	[0] = {
@@ -271,7 +283,8 @@
 	l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff);
 #endif
 
-	realview_flash_register(&realview_pb1176_flash_resource, 1);
+	realview_flash_register(realview_pb1176_flash_resources,
+				PB1176_FLASH_BLOCKS);
 	realview_eth_register(NULL, realview_pb1176_smsc911x_resources);
 	platform_device_register(&realview_i2c_device);
 	realview_usb_register(realview_pb1176_isp1761_resources);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_pb11mp.c linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_pb11mp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_pb11mp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_pb11mp.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/localtimer.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_pbx.c linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_pbx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-realview/realview_pbx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-realview/realview_pbx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,336 @@
+/*
+ *  arch/arm/mach-realview/realview_pbx.c
+ *
+ *  Copyright (C) 2009 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include <asm/smp_twd.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/mmc.h>
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+#include <mach/board-pbx.h>
+#include <mach/irqs.h>
+
+#include "core.h"
+
+static struct map_desc realview_pbx_io_desc[] __initdata = {
+	{
+		.virtual	= IO_ADDRESS(REALVIEW_SYS_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_SYS_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_PBX_GIC_CPU_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_PBX_GIC_CPU_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_PBX_GIC_DIST_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_PBX_GIC_DIST_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_SCTL_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_SCTL_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_PBX_TIMER0_1_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_PBX_TIMER0_1_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(REALVIEW_PBX_TIMER2_3_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_PBX_TIMER2_3_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+#ifdef CONFIG_PCI
+	{
+		.virtual	= PCIX_UNIT_BASE,
+		.pfn		= __phys_to_pfn(REALVIEW_PBX_PCI_BASE),
+		.length		= REALVIEW_PBX_PCI_BASE_SIZE,
+		.type		= MT_DEVICE,
+	},
+#endif
+#ifdef CONFIG_DEBUG_LL
+	{
+		.virtual	= IO_ADDRESS(REALVIEW_PBX_UART0_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_PBX_UART0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+#endif
+};
+
+static struct map_desc realview_local_io_desc[] __initdata = {
+	{
+		.virtual        = IO_ADDRESS(REALVIEW_PBX_TILE_GIC_CPU_BASE),
+		.pfn            = __phys_to_pfn(REALVIEW_PBX_TILE_GIC_CPU_BASE),
+		.length         = SZ_4K,
+		.type           = MT_DEVICE,
+	}, {
+		.virtual        = IO_ADDRESS(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+		.pfn            = __phys_to_pfn(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+		.length         = SZ_4K,
+		.type           = MT_DEVICE,
+	}, {
+		.virtual        = IO_ADDRESS(REALVIEW_PBX_TILE_L220_BASE),
+		.pfn            = __phys_to_pfn(REALVIEW_PBX_TILE_L220_BASE),
+		.length         = SZ_8K,
+		.type           = MT_DEVICE,
+	}
+};
+
+static void __init realview_pbx_map_io(void)
+{
+	iotable_init(realview_pbx_io_desc, ARRAY_SIZE(realview_pbx_io_desc));
+	if (core_tile_pbx11mp() || core_tile_pbxa9mp())
+		iotable_init(realview_local_io_desc, ARRAY_SIZE(realview_local_io_desc));
+}
+
+/*
+ * RealView PBXCore AMBA devices
+ */
+
+#define GPIO2_IRQ		{ IRQ_PBX_GPIO2, NO_IRQ }
+#define GPIO2_DMA		{ 0, 0 }
+#define GPIO3_IRQ		{ IRQ_PBX_GPIO3, NO_IRQ }
+#define GPIO3_DMA		{ 0, 0 }
+#define AACI_IRQ		{ IRQ_PBX_AACI, NO_IRQ }
+#define AACI_DMA		{ 0x80, 0x81 }
+#define MMCI0_IRQ		{ IRQ_PBX_MMCI0A, IRQ_PBX_MMCI0B }
+#define MMCI0_DMA		{ 0x84, 0 }
+#define KMI0_IRQ		{ IRQ_PBX_KMI0, NO_IRQ }
+#define KMI0_DMA		{ 0, 0 }
+#define KMI1_IRQ		{ IRQ_PBX_KMI1, NO_IRQ }
+#define KMI1_DMA		{ 0, 0 }
+#define PBX_SMC_IRQ		{ NO_IRQ, NO_IRQ }
+#define PBX_SMC_DMA		{ 0, 0 }
+#define MPMC_IRQ		{ NO_IRQ, NO_IRQ }
+#define MPMC_DMA		{ 0, 0 }
+#define PBX_CLCD_IRQ		{ IRQ_PBX_CLCD, NO_IRQ }
+#define PBX_CLCD_DMA		{ 0, 0 }
+#define DMAC_IRQ		{ IRQ_PBX_DMAC, NO_IRQ }
+#define DMAC_DMA		{ 0, 0 }
+#define SCTL_IRQ		{ NO_IRQ, NO_IRQ }
+#define SCTL_DMA		{ 0, 0 }
+#define PBX_WATCHDOG_IRQ	{ IRQ_PBX_WATCHDOG, NO_IRQ }
+#define PBX_WATCHDOG_DMA	{ 0, 0 }
+#define PBX_GPIO0_IRQ		{ IRQ_PBX_GPIO0, NO_IRQ }
+#define PBX_GPIO0_DMA		{ 0, 0 }
+#define GPIO1_IRQ		{ IRQ_PBX_GPIO1, NO_IRQ }
+#define GPIO1_DMA		{ 0, 0 }
+#define PBX_RTC_IRQ		{ IRQ_PBX_RTC, NO_IRQ }
+#define PBX_RTC_DMA		{ 0, 0 }
+#define SCI_IRQ			{ IRQ_PBX_SCI, NO_IRQ }
+#define SCI_DMA			{ 7, 6 }
+#define PBX_UART0_IRQ		{ IRQ_PBX_UART0, NO_IRQ }
+#define PBX_UART0_DMA		{ 15, 14 }
+#define PBX_UART1_IRQ		{ IRQ_PBX_UART1, NO_IRQ }
+#define PBX_UART1_DMA		{ 13, 12 }
+#define PBX_UART2_IRQ		{ IRQ_PBX_UART2, NO_IRQ }
+#define PBX_UART2_DMA		{ 11, 10 }
+#define PBX_UART3_IRQ		{ IRQ_PBX_UART3, NO_IRQ }
+#define PBX_UART3_DMA		{ 0x86, 0x87 }
+#define PBX_SSP_IRQ		{ IRQ_PBX_SSP, NO_IRQ }
+#define PBX_SSP_DMA		{ 9, 8 }
+
+/* FPGA Primecells */
+AMBA_DEVICE(aaci,	"fpga:04",	AACI,		NULL);
+AMBA_DEVICE(mmc0,	"fpga:05",	MMCI0,		&realview_mmc0_plat_data);
+AMBA_DEVICE(kmi0,	"fpga:06",	KMI0,		NULL);
+AMBA_DEVICE(kmi1,	"fpga:07",	KMI1,		NULL);
+AMBA_DEVICE(uart3,	"fpga:09",	PBX_UART3,	NULL);
+
+/* DevChip Primecells */
+AMBA_DEVICE(smc,	"dev:00",	PBX_SMC,	NULL);
+AMBA_DEVICE(sctl,	"dev:e0",	SCTL,		NULL);
+AMBA_DEVICE(wdog,	"dev:e1",	PBX_WATCHDOG, 	NULL);
+AMBA_DEVICE(gpio0,	"dev:e4",	PBX_GPIO0,	NULL);
+AMBA_DEVICE(gpio1,	"dev:e5",	GPIO1,		NULL);
+AMBA_DEVICE(gpio2,	"dev:e6",	GPIO2,		NULL);
+AMBA_DEVICE(rtc,	"dev:e8",	PBX_RTC,	NULL);
+AMBA_DEVICE(sci0,	"dev:f0",	SCI,		NULL);
+AMBA_DEVICE(uart0,	"dev:f1",	PBX_UART0,	NULL);
+AMBA_DEVICE(uart1,	"dev:f2",	PBX_UART1,	NULL);
+AMBA_DEVICE(uart2,	"dev:f3",	PBX_UART2,	NULL);
+AMBA_DEVICE(ssp0,	"dev:f4",	PBX_SSP,	NULL);
+
+/* Primecells on the NEC ISSP chip */
+AMBA_DEVICE(clcd,	"issp:20",	PBX_CLCD,	&clcd_plat_data);
+AMBA_DEVICE(dmac,	"issp:30",	DMAC,		NULL);
+
+static struct amba_device *amba_devs[] __initdata = {
+	&dmac_device,
+	&uart0_device,
+	&uart1_device,
+	&uart2_device,
+	&uart3_device,
+	&smc_device,
+	&clcd_device,
+	&sctl_device,
+	&wdog_device,
+	&gpio0_device,
+	&gpio1_device,
+	&gpio2_device,
+	&rtc_device,
+	&sci0_device,
+	&ssp0_device,
+	&aaci_device,
+	&mmc0_device,
+	&kmi0_device,
+	&kmi1_device,
+};
+
+/*
+ * RealView PB-X platform devices
+ */
+static struct resource realview_pbx_flash_resources[] = {
+	[0] = {
+		.start          = REALVIEW_PBX_FLASH0_BASE,
+		.end            = REALVIEW_PBX_FLASH0_BASE + REALVIEW_PBX_FLASH0_SIZE - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start          = REALVIEW_PBX_FLASH1_BASE,
+		.end            = REALVIEW_PBX_FLASH1_BASE + REALVIEW_PBX_FLASH1_SIZE - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+};
+
+static struct resource realview_pbx_smsc911x_resources[] = {
+	[0] = {
+		.start		= REALVIEW_PBX_ETH_BASE,
+		.end		= REALVIEW_PBX_ETH_BASE + SZ_64K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= IRQ_PBX_ETH,
+		.end		= IRQ_PBX_ETH,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource realview_pbx_isp1761_resources[] = {
+	[0] = {
+		.start		= REALVIEW_PBX_USB_BASE,
+		.end		= REALVIEW_PBX_USB_BASE + SZ_128K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= IRQ_PBX_USB,
+		.end		= IRQ_PBX_USB,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static void __init gic_init_irq(void)
+{
+	/* ARM PBX on-board GIC */
+	if (core_tile_pbx11mp() || core_tile_pbxa9mp()) {
+		gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE);
+		gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+			      29);
+		gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
+	} else {
+		gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE);
+		gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE),
+			      IRQ_PBX_GIC_START);
+		gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE));
+	}
+}
+
+static void __init realview_pbx_timer_init(void)
+{
+	timer0_va_base = __io_address(REALVIEW_PBX_TIMER0_1_BASE);
+	timer1_va_base = __io_address(REALVIEW_PBX_TIMER0_1_BASE) + 0x20;
+	timer2_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE);
+	timer3_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE) + 0x20;
+
+#ifdef CONFIG_LOCAL_TIMERS
+	if (core_tile_pbx11mp() || core_tile_pbxa9mp())
+		twd_base = __io_address(REALVIEW_PBX_TILE_TWD_BASE);
+#endif
+	realview_timer_init(IRQ_PBX_TIMER0_1);
+}
+
+static struct sys_timer realview_pbx_timer = {
+	.init		= realview_pbx_timer_init,
+};
+
+static void __init realview_pbx_init(void)
+{
+	int i;
+
+#ifdef CONFIG_CACHE_L2X0
+	if (core_tile_pbxa9mp()) {
+		void __iomem *l2x0_base =
+			__io_address(REALVIEW_PBX_TILE_L220_BASE);
+
+		/* set RAM latencies to 1 cycle for eASIC */
+		writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
+		writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
+
+		/* 16KB way size, 8-way associativity, parity disabled
+		 * Bits:  .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */
+		l2x0_init(l2x0_base, 0x02520000, 0xc0000fff);
+	}
+#endif
+
+	realview_flash_register(realview_pbx_flash_resources,
+				ARRAY_SIZE(realview_pbx_flash_resources));
+	realview_eth_register(NULL, realview_pbx_smsc911x_resources);
+	platform_device_register(&realview_i2c_device);
+	platform_device_register(&realview_cf_device);
+	realview_usb_register(realview_pbx_isp1761_resources);
+
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		amba_device_register(d, &iomem_resource);
+	}
+
+#ifdef CONFIG_LEDS
+	leds_event = realview_leds_event;
+#endif
+}
+
+MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
+	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+	.phys_io	= REALVIEW_PBX_UART0_BASE,
+	.io_pg_offst	= (IO_ADDRESS(REALVIEW_PBX_UART0_BASE) >> 18) & 0xfffc,
+	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.map_io		= realview_pbx_map_io,
+	.init_irq	= gic_init_irq,
+	.timer		= &realview_pbx_timer,
+	.init_machine	= realview_pbx_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2400/gpio.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2400/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2400/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2400/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,10 +33,10 @@
 
 int s3c2400_gpio_getirq(unsigned int pin)
 {
-	if (pin < S3C2410_GPE0 || pin > S3C2400_GPE7_EINT7)
-		return -1;  /* not valid interrupts */
+	if (pin < S3C2410_GPE(0) || pin > S3C2400_GPE(7))
+		return -EINVAL;  /* not valid interrupts */
 
-	return (pin - S3C2410_GPE0) + IRQ_EINT0;
+	return (pin - S3C2410_GPE(0)) + IRQ_EINT0;
 }
 
 EXPORT_SYMBOL(s3c2400_gpio_getirq);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/dma.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,14 +17,16 @@
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 
+#include <mach/map.h>
 #include <mach/dma.h>
 
 #include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat/dma-plat.h>
 
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-ac97.h>
+#include <plat/regs-dma.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/gpio.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,12 +39,12 @@
 	unsigned long flags;
 	unsigned long val;
 
-	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
-		return -1;
+	if (pin < S3C2410_GPG(8) || pin > S3C2410_GPG(15))
+		return -EINVAL;
 
 	config &= 0xff;
 
-	pin -= S3C2410_GPG8;
+	pin -= S3C2410_GPG(8);
 	reg += pin & ~3;
 
 	local_irq_save(flags);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,8 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/leds.h>
+#include <linux/gpio.h>
+
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
 #include <mach/h1940-latch.h>
@@ -41,9 +43,9 @@
 		h1940_latch_control(0, H1940_LATCH_BLUETOOTH_POWER);
 		/* Reset the chip */
 		mdelay(10);
-		s3c2410_gpio_setpin(S3C2410_GPH1, 1);
+		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
 		mdelay(10);
-		s3c2410_gpio_setpin(S3C2410_GPH1, 0);
+		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
 
 		state = 1;
 	}
@@ -52,9 +54,9 @@
 		led_trigger_event(bt_led_trigger, 0);
 #endif
 
-		s3c2410_gpio_setpin(S3C2410_GPH1, 1);
+		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
 		mdelay(10);
-		s3c2410_gpio_setpin(S3C2410_GPH1, 0);
+		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
 		mdelay(10);
 		h1940_latch_control(H1940_LATCH_BLUETOOTH_POWER, 0);
 
@@ -87,14 +89,14 @@
 static int __init h1940bt_probe(struct platform_device *pdev)
 {
 	/* Configures BT serial port GPIOs */
-	s3c2410_gpio_cfgpin(S3C2410_GPH0, S3C2410_GPH0_nCTS0);
-	s3c2410_gpio_pullup(S3C2410_GPH0, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_OUTP);
-	s3c2410_gpio_pullup(S3C2410_GPH1, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH2, S3C2410_GPH2_TXD0);
-	s3c2410_gpio_pullup(S3C2410_GPH2, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH3, S3C2410_GPH3_RXD0);
-	s3c2410_gpio_pullup(S3C2410_GPH3, 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0);
+	s3c2410_gpio_pullup(S3C2410_GPH(0), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_pullup(S3C2410_GPH(1), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0);
+	s3c2410_gpio_pullup(S3C2410_GPH(2), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
+	s3c2410_gpio_pullup(S3C2410_GPH(3), 1);
 
 #ifdef CONFIG_LEDS_H1940
 	led_trigger_register_simple("h1940-bluetooth", &bt_led_trigger);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/dma.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/dma.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,7 @@
  * Copyright (C) 2003,2004,2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * Samsung S3C241XX DMA support
+ * Samsung S3C24XX DMA support
  *
  * 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
@@ -13,8 +13,8 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
+#include <plat/dma.h>
 #include <linux/sysdev.h>
-#include <mach/hardware.h>
 
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
@@ -55,9 +55,9 @@
 
 /* we have 4 dma channels */
 #ifndef CONFIG_CPU_S3C2443
-#define S3C2410_DMA_CHANNELS		(4)
+#define S3C_DMA_CHANNELS		(4)
 #else
-#define S3C2410_DMA_CHANNELS		(6)
+#define S3C_DMA_CHANNELS		(6)
 #endif
 
 /* types */
@@ -68,7 +68,6 @@
 	S3C2410_DMA_PAUSED
 };
 
-
 /* enum s3c2410_dma_loadst
  *
  * This represents the state of the DMA engine, wrt to the loaded / running
@@ -104,32 +103,6 @@
 	S3C2410_DMALOAD_1LOADED_1RUNNING,
 };
 
-enum s3c2410_dma_buffresult {
-	S3C2410_RES_OK,
-	S3C2410_RES_ERR,
-	S3C2410_RES_ABORT
-};
-
-enum s3c2410_dmasrc {
-	S3C2410_DMASRC_HW,		/* source is memory */
-	S3C2410_DMASRC_MEM		/* source is hardware */
-};
-
-/* enum s3c2410_chan_op
- *
- * operation codes passed to the DMA code by the user, and also used
- * to inform the current channel owner of any changes to the system state
-*/
-
-enum s3c2410_chan_op {
-	S3C2410_DMAOP_START,
-	S3C2410_DMAOP_STOP,
-	S3C2410_DMAOP_PAUSE,
-	S3C2410_DMAOP_RESUME,
-	S3C2410_DMAOP_FLUSH,
-	S3C2410_DMAOP_TIMEOUT,		/* internal signal to handler */
-	S3C2410_DMAOP_STARTED,		/* indicate channel started */
-};
 
 /* flags */
 
@@ -139,17 +112,14 @@
 
 /* dma buffer */
 
-struct s3c2410_dma_client {
-	char                *name;
-};
+struct s3c2410_dma_buf;
 
-/* s3c2410_dma_buf_s
+/* s3c2410_dma_buf
  *
  * internally used buffer structure to describe a queued or running
  * buffer.
 */
 
-struct s3c2410_dma_buf;
 struct s3c2410_dma_buf {
 	struct s3c2410_dma_buf	*next;
 	int			 magic;		/* magic */
@@ -161,20 +131,6 @@
 
 /* [1] is this updated for both recv/send modes? */
 
-struct s3c2410_dma_chan;
-
-/* s3c2410_dma_cbfn_t
- *
- * buffer callback routine type
-*/
-
-typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
-				   void *buf, int size,
-				   enum s3c2410_dma_buffresult result);
-
-typedef int  (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
-				   enum s3c2410_chan_op );
-
 struct s3c2410_dma_stats {
 	unsigned long		loads;
 	unsigned long		timeout_longest;
@@ -206,10 +162,10 @@
 
 	/* channel configuration */
 	enum s3c2410_dmasrc	 source;
+	enum dma_ch		 req_ch;
 	unsigned long		 dev_addr;
 	unsigned long		 load_timeout;
 	unsigned int		 flags;		/* channel flags */
-	unsigned int		 hw_cfg;	/* last hw config */
 
 	struct s3c24xx_dma_map	*map;		/* channel hw maps */
 
@@ -236,213 +192,6 @@
 	struct sys_device	dev;
 };
 
-/* the currently allocated channel information */
-extern struct s3c2410_dma_chan s3c2410_chans[];
-
-/* note, we don't really use dma_device_t at the moment */
 typedef unsigned long dma_device_t;
 
-/* functions --------------------------------------------------------------- */
-
-/* s3c2410_dma_request
- *
- * request a dma channel exclusivley
-*/
-
-extern int s3c2410_dma_request(unsigned int channel,
-			       struct s3c2410_dma_client *, void *dev);
-
-
-/* s3c2410_dma_ctrl
- *
- * change the state of the dma channel
-*/
-
-extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
-
-/* s3c2410_dma_setflags
- *
- * set the channel's flags to a given state
-*/
-
-extern int s3c2410_dma_setflags(unsigned int channel,
-				unsigned int flags);
-
-/* s3c2410_dma_free
- *
- * free the dma channel (will also abort any outstanding operations)
-*/
-
-extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
-
-/* s3c2410_dma_enqueue
- *
- * place the given buffer onto the queue of operations for the channel.
- * The buffer must be allocated from dma coherent memory, or the Dcache/WB
- * drained before the buffer is given to the DMA system.
-*/
-
-extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
-			       dma_addr_t data, int size);
-
-/* s3c2410_dma_config
- *
- * configure the dma channel
-*/
-
-extern int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon);
-
-/* s3c2410_dma_devconfig
- *
- * configure the device we're talking to
-*/
-
-extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
-				 int hwcfg, unsigned long devaddr);
-
-/* s3c2410_dma_getposition
- *
- * get the position that the dma transfer is currently at
-*/
-
-extern int s3c2410_dma_getposition(unsigned int channel,
-				   dma_addr_t *src, dma_addr_t *dest);
-
-extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
-extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
-
-/* DMA Register definitions */
-
-#define S3C2410_DMA_DISRC       (0x00)
-#define S3C2410_DMA_DISRCC      (0x04)
-#define S3C2410_DMA_DIDST       (0x08)
-#define S3C2410_DMA_DIDSTC      (0x0C)
-#define S3C2410_DMA_DCON        (0x10)
-#define S3C2410_DMA_DSTAT       (0x14)
-#define S3C2410_DMA_DCSRC       (0x18)
-#define S3C2410_DMA_DCDST       (0x1C)
-#define S3C2410_DMA_DMASKTRIG   (0x20)
-#define S3C2412_DMA_DMAREQSEL	(0x24)
-#define S3C2443_DMA_DMAREQSEL	(0x24)
-
-#define S3C2410_DISRCC_INC	(1<<0)
-#define S3C2410_DISRCC_APB	(1<<1)
-
-#define S3C2410_DMASKTRIG_STOP   (1<<2)
-#define S3C2410_DMASKTRIG_ON     (1<<1)
-#define S3C2410_DMASKTRIG_SWTRIG (1<<0)
-
-#define S3C2410_DCON_DEMAND     (0<<31)
-#define S3C2410_DCON_HANDSHAKE  (1<<31)
-#define S3C2410_DCON_SYNC_PCLK  (0<<30)
-#define S3C2410_DCON_SYNC_HCLK  (1<<30)
-
-#define S3C2410_DCON_INTREQ     (1<<29)
-
-#define S3C2410_DCON_CH0_XDREQ0	(0<<24)
-#define S3C2410_DCON_CH0_UART0	(1<<24)
-#define S3C2410_DCON_CH0_SDI	(2<<24)
-#define S3C2410_DCON_CH0_TIMER	(3<<24)
-#define S3C2410_DCON_CH0_USBEP1	(4<<24)
-
-#define S3C2410_DCON_CH1_XDREQ1	(0<<24)
-#define S3C2410_DCON_CH1_UART1	(1<<24)
-#define S3C2410_DCON_CH1_I2SSDI	(2<<24)
-#define S3C2410_DCON_CH1_SPI	(3<<24)
-#define S3C2410_DCON_CH1_USBEP2	(4<<24)
-
-#define S3C2410_DCON_CH2_I2SSDO	(0<<24)
-#define S3C2410_DCON_CH2_I2SSDI	(1<<24)
-#define S3C2410_DCON_CH2_SDI	(2<<24)
-#define S3C2410_DCON_CH2_TIMER	(3<<24)
-#define S3C2410_DCON_CH2_USBEP3	(4<<24)
-
-#define S3C2410_DCON_CH3_UART2	(0<<24)
-#define S3C2410_DCON_CH3_SDI	(1<<24)
-#define S3C2410_DCON_CH3_SPI	(2<<24)
-#define S3C2410_DCON_CH3_TIMER	(3<<24)
-#define S3C2410_DCON_CH3_USBEP4	(4<<24)
-
-#define S3C2410_DCON_SRCSHIFT   (24)
-#define S3C2410_DCON_SRCMASK	(7<<24)
-
-#define S3C2410_DCON_BYTE       (0<<20)
-#define S3C2410_DCON_HALFWORD   (1<<20)
-#define S3C2410_DCON_WORD       (2<<20)
-
-#define S3C2410_DCON_AUTORELOAD (0<<22)
-#define S3C2410_DCON_NORELOAD   (1<<22)
-#define S3C2410_DCON_HWTRIG     (1<<23)
-
-#ifdef CONFIG_CPU_S3C2440
-#define S3C2440_DIDSTC_CHKINT	(1<<2)
-
-#define S3C2440_DCON_CH0_I2SSDO	(5<<24)
-#define S3C2440_DCON_CH0_PCMIN	(6<<24)
-
-#define S3C2440_DCON_CH1_PCMOUT	(5<<24)
-#define S3C2440_DCON_CH1_SDI	(6<<24)
-
-#define S3C2440_DCON_CH2_PCMIN	(5<<24)
-#define S3C2440_DCON_CH2_MICIN	(6<<24)
-
-#define S3C2440_DCON_CH3_MICIN	(5<<24)
-#define S3C2440_DCON_CH3_PCMOUT	(6<<24)
-#endif
-
-#ifdef CONFIG_CPU_S3C2412
-
-#define S3C2412_DMAREQSEL_SRC(x)	((x)<<1)
-
-#define S3C2412_DMAREQSEL_HW		(1)
-
-#define S3C2412_DMAREQSEL_SPI0TX	S3C2412_DMAREQSEL_SRC(0)
-#define S3C2412_DMAREQSEL_SPI0RX	S3C2412_DMAREQSEL_SRC(1)
-#define S3C2412_DMAREQSEL_SPI1TX	S3C2412_DMAREQSEL_SRC(2)
-#define S3C2412_DMAREQSEL_SPI1RX	S3C2412_DMAREQSEL_SRC(3)
-#define S3C2412_DMAREQSEL_I2STX		S3C2412_DMAREQSEL_SRC(4)
-#define S3C2412_DMAREQSEL_I2SRX		S3C2412_DMAREQSEL_SRC(5)
-#define S3C2412_DMAREQSEL_TIMER		S3C2412_DMAREQSEL_SRC(9)
-#define S3C2412_DMAREQSEL_SDI		S3C2412_DMAREQSEL_SRC(10)
-#define S3C2412_DMAREQSEL_USBEP1	S3C2412_DMAREQSEL_SRC(13)
-#define S3C2412_DMAREQSEL_USBEP2	S3C2412_DMAREQSEL_SRC(14)
-#define S3C2412_DMAREQSEL_USBEP3	S3C2412_DMAREQSEL_SRC(15)
-#define S3C2412_DMAREQSEL_USBEP4	S3C2412_DMAREQSEL_SRC(16)
-#define S3C2412_DMAREQSEL_XDREQ0	S3C2412_DMAREQSEL_SRC(17)
-#define S3C2412_DMAREQSEL_XDREQ1	S3C2412_DMAREQSEL_SRC(18)
-#define S3C2412_DMAREQSEL_UART0_0	S3C2412_DMAREQSEL_SRC(19)
-#define S3C2412_DMAREQSEL_UART0_1	S3C2412_DMAREQSEL_SRC(20)
-#define S3C2412_DMAREQSEL_UART1_0	S3C2412_DMAREQSEL_SRC(21)
-#define S3C2412_DMAREQSEL_UART1_1	S3C2412_DMAREQSEL_SRC(22)
-#define S3C2412_DMAREQSEL_UART2_0	S3C2412_DMAREQSEL_SRC(23)
-#define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
-
-#endif
-
-#define S3C2443_DMAREQSEL_SRC(x)	((x)<<1)
-
-#define S3C2443_DMAREQSEL_HW		(1)
-
-#define S3C2443_DMAREQSEL_SPI0TX	S3C2443_DMAREQSEL_SRC(0)
-#define S3C2443_DMAREQSEL_SPI0RX	S3C2443_DMAREQSEL_SRC(1)
-#define S3C2443_DMAREQSEL_SPI1TX	S3C2443_DMAREQSEL_SRC(2)
-#define S3C2443_DMAREQSEL_SPI1RX	S3C2443_DMAREQSEL_SRC(3)
-#define S3C2443_DMAREQSEL_I2STX		S3C2443_DMAREQSEL_SRC(4)
-#define S3C2443_DMAREQSEL_I2SRX		S3C2443_DMAREQSEL_SRC(5)
-#define S3C2443_DMAREQSEL_TIMER		S3C2443_DMAREQSEL_SRC(9)
-#define S3C2443_DMAREQSEL_SDI		S3C2443_DMAREQSEL_SRC(10)
-#define S3C2443_DMAREQSEL_XDREQ0	S3C2443_DMAREQSEL_SRC(17)
-#define S3C2443_DMAREQSEL_XDREQ1	S3C2443_DMAREQSEL_SRC(18)
-#define S3C2443_DMAREQSEL_UART0_0	S3C2443_DMAREQSEL_SRC(19)
-#define S3C2443_DMAREQSEL_UART0_1	S3C2443_DMAREQSEL_SRC(20)
-#define S3C2443_DMAREQSEL_UART1_0	S3C2443_DMAREQSEL_SRC(21)
-#define S3C2443_DMAREQSEL_UART1_1	S3C2443_DMAREQSEL_SRC(22)
-#define S3C2443_DMAREQSEL_UART2_0	S3C2443_DMAREQSEL_SRC(23)
-#define S3C2443_DMAREQSEL_UART2_1	S3C2443_DMAREQSEL_SRC(24)
-#define S3C2443_DMAREQSEL_UART3_0	S3C2443_DMAREQSEL_SRC(25)
-#define S3C2443_DMAREQSEL_UART3_1	S3C2443_DMAREQSEL_SRC(26)
-#define S3C2443_DMAREQSEL_PCMOUT	S3C2443_DMAREQSEL_SRC(27)
-#define S3C2443_DMAREQSEL_PCMIN 	S3C2443_DMAREQSEL_SRC(28)
-#define S3C2443_DMAREQSEL_MICIN		S3C2443_DMAREQSEL_SRC(29)
-
 #endif /* __ASM_ARCH_DMA_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio-core.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio-core.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio-core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio-core.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,11 +24,11 @@
 {
 	struct s3c_gpio_chip *chip;
 
-	if (pin > S3C2410_GPG10)
+	if (pin > S3C2410_GPG(10))
 		return NULL;
 
 	chip = &s3c24xx_gpios[pin/32];
-	return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL;
+	return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL;
 }
 
 #endif /* __ASM_ARCH_GPIO_CORE_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio-fns.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,103 @@
+/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+ *
+ * Copyright (c) 2003,2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - hardware
+ *
+ * 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.
+*/
+
+/* These functions are in the to-be-removed category and it is strongly
+ * encouraged not to use these in new code. They will be marked deprecated
+ * very soon.
+ *
+ * Most of the functionality can be either replaced by the gpiocfg calls
+ * for the s3c platform or by the generic GPIOlib API.
+*/
+
+/* external functions for GPIO support
+ *
+ * These allow various different clients to access the same GPIO
+ * registers without conflicting. If your driver only owns the entire
+ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
+*/
+
+/* s3c2410_gpio_cfgpin
+ *
+ * set the configuration of the given pin to the value passed.
+ *
+ * eg:
+ *    s3c2410_gpio_cfgpin(S3C2410_GPA(0), S3C2410_GPA0_ADDR0);
+ *    s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
+*/
+
+extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
+
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *	< 0 = no interrupt for this pin
+ *	>=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+#ifdef CONFIG_CPU_S3C2400
+
+extern int s3c2400_gpio_getirq(unsigned int pin);
+
+#endif /* CONFIG_CPU_S3C2400 */
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+				  unsigned int config);
+
+/* s3c2410_gpio_pullup
+ *
+ * configure the pull-up control on the given pin
+ *
+ * to = 1 => disable the pull-up
+ *      0 => enable the pull-up
+ *
+ * eg;
+ *
+ *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
+ *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
+*/
+
+extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+/* s3c2410_gpio_getpull
+ *
+ * Read the state of the pull-up on a given pin
+ *
+ * return:
+ *	< 0 => error code
+ *	  0 => enabled
+ *	  1 => disabled
+*/
+
+extern int s3c2410_gpio_getpull(unsigned int pin);
+
+extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,5 +24,6 @@
 
 #include <asm-generic/gpio.h>
 #include <mach/gpio-nrs.h>
+#include <mach/gpio-fns.h>
 
 #define S3C_GPIO_END	(S3C2410_GPIO_BANKH + 32)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,9 @@
  * published by the Free Software Foundation.
 */
 
+#ifndef __MACH_GPIONRS_H
+#define __MACH_GPIONRS_H
+
 #define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
 
 #define S3C2410_GPIO_BANKA   (32*0)
@@ -21,3 +24,70 @@
 #define S3C2410_GPIO_BANKF   (32*5)
 #define S3C2410_GPIO_BANKG   (32*6)
 #define S3C2410_GPIO_BANKH   (32*7)
+
+/* GPIO bank sizes */
+#define S3C2410_GPIO_A_NR	(32)
+#define S3C2410_GPIO_B_NR	(32)
+#define S3C2410_GPIO_C_NR	(32)
+#define S3C2410_GPIO_D_NR	(32)
+#define S3C2410_GPIO_E_NR	(32)
+#define S3C2410_GPIO_F_NR	(32)
+#define S3C2410_GPIO_G_NR	(32)
+#define S3C2410_GPIO_H_NR	(32)
+
+#if CONFIG_S3C_GPIO_SPACE != 0
+#error CONFIG_S3C_GPIO_SPACE cannot be zero at the moment
+#endif
+
+#define S3C2410_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 0)
+
+#ifndef __ASSEMBLY__
+
+enum s3c_gpio_number {
+	S3C2410_GPIO_A_START = 0,
+	S3C2410_GPIO_B_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_A),
+	S3C2410_GPIO_C_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_B),
+	S3C2410_GPIO_D_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_C),
+	S3C2410_GPIO_E_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_D),
+	S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E),
+	S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F),
+	S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G),
+};
+
+#endif /* __ASSEMBLY__ */
+
+/* S3C2410 GPIO number definitions. */
+
+#define S3C2410_GPA(_nr)	(S3C2410_GPIO_A_START + (_nr))
+#define S3C2410_GPB(_nr)	(S3C2410_GPIO_B_START + (_nr))
+#define S3C2410_GPC(_nr)	(S3C2410_GPIO_C_START + (_nr))
+#define S3C2410_GPD(_nr)	(S3C2410_GPIO_D_START + (_nr))
+#define S3C2410_GPE(_nr)	(S3C2410_GPIO_E_START + (_nr))
+#define S3C2410_GPF(_nr)	(S3C2410_GPIO_F_START + (_nr))
+#define S3C2410_GPG(_nr)	(S3C2410_GPIO_G_START + (_nr))
+#define S3C2410_GPH(_nr)	(S3C2410_GPIO_H_START + (_nr))
+
+/* compatibility until drivers can be modified */
+
+#define S3C2410_GPA0	S3C2410_GPA(0)
+#define S3C2410_GPA1	S3C2410_GPA(1)
+#define S3C2410_GPA3	S3C2410_GPA(3)
+#define S3C2410_GPA7	S3C2410_GPA(7)
+
+#define S3C2410_GPE0	S3C2410_GPE(0)
+#define S3C2410_GPE1	S3C2410_GPE(1)
+#define S3C2410_GPE2	S3C2410_GPE(2)
+#define S3C2410_GPE3	S3C2410_GPE(3)
+#define S3C2410_GPE4	S3C2410_GPE(4)
+#define S3C2410_GPE5	S3C2410_GPE(5)
+#define S3C2410_GPE6	S3C2410_GPE(6)
+#define S3C2410_GPE7	S3C2410_GPE(7)
+#define S3C2410_GPE8	S3C2410_GPE(8)
+#define S3C2410_GPE9	S3C2410_GPE(9)
+#define S3C2410_GPE10	S3C2410_GPE(10)
+
+#define S3C2410_GPH10	S3C2410_GPH(10)
+
+#endif /* __MACH_GPIONRS_H */
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/hardware.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/hardware.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/hardware.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/hardware.h	2009-09-09 18:13:59.000000000 -0400
@@ -15,101 +15,6 @@
 
 #ifndef __ASSEMBLY__
 
-/* external functions for GPIO support
- *
- * These allow various different clients to access the same GPIO
- * registers without conflicting. If your driver only owns the entire
- * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
-*/
-
-/* s3c2410_gpio_cfgpin
- *
- * set the configuration of the given pin to the value passed.
- *
- * eg:
- *    s3c2410_gpio_cfgpin(S3C2410_GPA0, S3C2410_GPA0_ADDR0);
- *    s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
-*/
-
-extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
-
-extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
-
-/* s3c2410_gpio_getirq
- *
- * turn the given pin number into the corresponding IRQ number
- *
- * returns:
- *	< 0 = no interrupt for this pin
- *	>=0 = interrupt number for the pin
-*/
-
-extern int s3c2410_gpio_getirq(unsigned int pin);
-
-/* s3c2410_gpio_irq2pin
- *
- * turn the given irq number into the corresponding GPIO number
- *
- * returns:
- *	< 0 = no pin
- *	>=0 = gpio pin number
-*/
-
-extern int s3c2410_gpio_irq2pin(unsigned int irq);
-
-#ifdef CONFIG_CPU_S3C2400
-
-extern int s3c2400_gpio_getirq(unsigned int pin);
-
-#endif /* CONFIG_CPU_S3C2400 */
-
-/* s3c2410_gpio_irqfilter
- *
- * set the irq filtering on the given pin
- *
- * on = 0 => disable filtering
- *      1 => enable filtering
- *
- * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
- *          width of filter (0 through 63)
- *
- *
-*/
-
-extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-				  unsigned int config);
-
-/* s3c2410_gpio_pullup
- *
- * configure the pull-up control on the given pin
- *
- * to = 1 => disable the pull-up
- *      0 => enable the pull-up
- *
- * eg;
- *
- *   s3c2410_gpio_pullup(S3C2410_GPB0, 0);
- *   s3c2410_gpio_pullup(S3C2410_GPE8, 0);
-*/
-
-extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
-
-/* s3c2410_gpio_getpull
- *
- * Read the state of the pull-up on a given pin
- *
- * return:
- *	< 0 => error code
- *	  0 => enabled
- *	  1 => disabled
-*/
-
-extern int s3c2410_gpio_getpull(unsigned int pin);
-
-extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
-
-extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
-
 extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg);
 
 #ifdef CONFIG_CPU_S3C2440
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/map.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/map.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/map.h	2009-09-09 18:13:59.000000000 -0400
@@ -84,7 +84,6 @@
 
 #define S3C24XX_PA_IRQ      S3C2410_PA_IRQ
 #define S3C24XX_PA_MEMCTRL  S3C2410_PA_MEMCTRL
-#define S3C24XX_PA_USBHOST  S3C2410_PA_USBHOST
 #define S3C24XX_PA_DMA      S3C2410_PA_DMA
 #define S3C24XX_PA_CLKPWR   S3C2410_PA_CLKPWR
 #define S3C24XX_PA_LCD      S3C2410_PA_LCD
@@ -102,6 +101,7 @@
 
 #define S3C_PA_IIC          S3C2410_PA_IIC
 #define S3C_PA_UART	    S3C24XX_PA_UART
+#define S3C_PA_USBHOST	S3C2410_PA_USBHOST
 #define S3C_PA_HSMMC0	    S3C2443_PA_HSMMC
 
 #endif /* __ASM_ARCH_MAP_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/regs-gpio.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/regs-gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/regs-gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -69,104 +69,58 @@
 #define S3C2400_GPACON	   S3C2410_GPIOREG(0x00)
 #define S3C2400_GPADAT	   S3C2410_GPIOREG(0x04)
 
-#define S3C2410_GPA0         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 0)
-#define S3C2410_GPA0_OUT     (0<<0)
 #define S3C2410_GPA0_ADDR0   (1<<0)
 
-#define S3C2410_GPA1         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 1)
-#define S3C2410_GPA1_OUT     (0<<1)
 #define S3C2410_GPA1_ADDR16  (1<<1)
 
-#define S3C2410_GPA2         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 2)
-#define S3C2410_GPA2_OUT     (0<<2)
 #define S3C2410_GPA2_ADDR17  (1<<2)
 
-#define S3C2410_GPA3         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 3)
-#define S3C2410_GPA3_OUT     (0<<3)
 #define S3C2410_GPA3_ADDR18  (1<<3)
 
-#define S3C2410_GPA4         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 4)
-#define S3C2410_GPA4_OUT     (0<<4)
 #define S3C2410_GPA4_ADDR19  (1<<4)
 
-#define S3C2410_GPA5         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 5)
-#define S3C2410_GPA5_OUT     (0<<5)
 #define S3C2410_GPA5_ADDR20  (1<<5)
 
-#define S3C2410_GPA6         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 6)
-#define S3C2410_GPA6_OUT     (0<<6)
 #define S3C2410_GPA6_ADDR21  (1<<6)
 
-#define S3C2410_GPA7         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 7)
-#define S3C2410_GPA7_OUT     (0<<7)
 #define S3C2410_GPA7_ADDR22  (1<<7)
 
-#define S3C2410_GPA8         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 8)
-#define S3C2410_GPA8_OUT     (0<<8)
 #define S3C2410_GPA8_ADDR23  (1<<8)
 
-#define S3C2410_GPA9         S3C2410_GPIONO(S3C2410_GPIO_BANKA, 9)
-#define S3C2410_GPA9_OUT     (0<<9)
 #define S3C2410_GPA9_ADDR24  (1<<9)
 
-#define S3C2410_GPA10        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 10)
-#define S3C2410_GPA10_OUT    (0<<10)
 #define S3C2410_GPA10_ADDR25 (1<<10)
 #define S3C2400_GPA10_SCKE   (1<<10)
 
-#define S3C2410_GPA11        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 11)
-#define S3C2410_GPA11_OUT    (0<<11)
 #define S3C2410_GPA11_ADDR26 (1<<11)
 #define S3C2400_GPA11_nCAS0  (1<<11)
 
-#define S3C2410_GPA12        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 12)
-#define S3C2410_GPA12_OUT    (0<<12)
 #define S3C2410_GPA12_nGCS1  (1<<12)
 #define S3C2400_GPA12_nCAS1  (1<<12)
 
-#define S3C2410_GPA13        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 13)
-#define S3C2410_GPA13_OUT    (0<<13)
 #define S3C2410_GPA13_nGCS2  (1<<13)
 #define S3C2400_GPA13_nGCS1  (1<<13)
 
-#define S3C2410_GPA14        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 14)
-#define S3C2410_GPA14_OUT    (0<<14)
 #define S3C2410_GPA14_nGCS3  (1<<14)
 #define S3C2400_GPA14_nGCS2  (1<<14)
 
-#define S3C2410_GPA15        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 15)
-#define S3C2410_GPA15_OUT    (0<<15)
 #define S3C2410_GPA15_nGCS4  (1<<15)
 #define S3C2400_GPA15_nGCS3  (1<<15)
 
-#define S3C2410_GPA16        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 16)
-#define S3C2410_GPA16_OUT    (0<<16)
 #define S3C2410_GPA16_nGCS5  (1<<16)
 #define S3C2400_GPA16_nGCS4  (1<<16)
 
-#define S3C2410_GPA17        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 17)
-#define S3C2410_GPA17_OUT    (0<<17)
 #define S3C2410_GPA17_CLE    (1<<17)
 #define S3C2400_GPA17_nGCS5  (1<<17)
 
-#define S3C2410_GPA18        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 18)
-#define S3C2410_GPA18_OUT    (0<<18)
 #define S3C2410_GPA18_ALE    (1<<18)
 
-#define S3C2410_GPA19        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 19)
-#define S3C2410_GPA19_OUT    (0<<19)
 #define S3C2410_GPA19_nFWE   (1<<19)
 
-#define S3C2410_GPA20        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 20)
-#define S3C2410_GPA20_OUT    (0<<20)
 #define S3C2410_GPA20_nFRE   (1<<20)
 
-#define S3C2410_GPA21        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 21)
-#define S3C2410_GPA21_OUT    (0<<21)
 #define S3C2410_GPA21_nRSTOUT (1<<21)
 
-#define S3C2410_GPA22        S3C2410_GPIONO(S3C2410_GPIO_BANKA, 22)
-#define S3C2410_GPA22_OUT    (0<<22)
 #define S3C2410_GPA22_nFCE   (1<<22)
 
 /* 0x08 and 0x0c are reserved on S3C2410 */
@@ -194,107 +148,69 @@
 
 /* no i/o pin in port b can have value 3 (unless it is a s3c2443) ! */
 
-#define S3C2410_GPB0         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0)
-#define S3C2410_GPB0_INP     (0x00 << 0)
-#define S3C2410_GPB0_OUTP    (0x01 << 0)
 #define S3C2410_GPB0_TOUT0   (0x02 << 0)
 #define S3C2400_GPB0_DATA16  (0x02 << 0)
 
-#define S3C2410_GPB1         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 1)
-#define S3C2410_GPB1_INP     (0x00 << 2)
-#define S3C2410_GPB1_OUTP    (0x01 << 2)
 #define S3C2410_GPB1_TOUT1   (0x02 << 2)
 #define S3C2400_GPB1_DATA17  (0x02 << 2)
 
-#define S3C2410_GPB2         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 2)
-#define S3C2410_GPB2_INP     (0x00 << 4)
-#define S3C2410_GPB2_OUTP    (0x01 << 4)
 #define S3C2410_GPB2_TOUT2   (0x02 << 4)
 #define S3C2400_GPB2_DATA18  (0x02 << 4)
 #define S3C2400_GPB2_TCLK1   (0x03 << 4)
 
-#define S3C2410_GPB3         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 3)
-#define S3C2410_GPB3_INP     (0x00 << 6)
-#define S3C2410_GPB3_OUTP    (0x01 << 6)
 #define S3C2410_GPB3_TOUT3   (0x02 << 6)
 #define S3C2400_GPB3_DATA19  (0x02 << 6)
 #define S3C2400_GPB3_TXD1    (0x03 << 6)
 
-#define S3C2410_GPB4         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 4)
-#define S3C2410_GPB4_INP     (0x00 << 8)
-#define S3C2410_GPB4_OUTP    (0x01 << 8)
 #define S3C2410_GPB4_TCLK0   (0x02 << 8)
 #define S3C2400_GPB4_DATA20  (0x02 << 8)
 #define S3C2410_GPB4_MASK    (0x03 << 8)
 #define S3C2400_GPB4_RXD1    (0x03 << 8)
 #define S3C2400_GPB4_MASK    (0x03 << 8)
 
-#define S3C2410_GPB5         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)
-#define S3C2410_GPB5_INP     (0x00 << 10)
-#define S3C2410_GPB5_OUTP    (0x01 << 10)
 #define S3C2410_GPB5_nXBACK  (0x02 << 10)
 #define S3C2443_GPB5_XBACK   (0x03 << 10)
 #define S3C2400_GPB5_DATA21  (0x02 << 10)
 #define S3C2400_GPB5_nCTS1   (0x03 << 10)
 
-#define S3C2410_GPB6         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 6)
-#define S3C2410_GPB6_INP     (0x00 << 12)
-#define S3C2410_GPB6_OUTP    (0x01 << 12)
 #define S3C2410_GPB6_nXBREQ  (0x02 << 12)
 #define S3C2443_GPB6_XBREQ   (0x03 << 12)
 #define S3C2400_GPB6_DATA22  (0x02 << 12)
 #define S3C2400_GPB6_nRTS1   (0x03 << 12)
 
-#define S3C2410_GPB7         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 7)
-#define S3C2410_GPB7_INP     (0x00 << 14)
-#define S3C2410_GPB7_OUTP    (0x01 << 14)
 #define S3C2410_GPB7_nXDACK1 (0x02 << 14)
 #define S3C2443_GPB7_XDACK1  (0x03 << 14)
 #define S3C2400_GPB7_DATA23  (0x02 << 14)
 
-#define S3C2410_GPB8         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 8)
-#define S3C2410_GPB8_INP     (0x00 << 16)
-#define S3C2410_GPB8_OUTP    (0x01 << 16)
 #define S3C2410_GPB8_nXDREQ1 (0x02 << 16)
 #define S3C2400_GPB8_DATA24  (0x02 << 16)
 
-#define S3C2410_GPB9         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 9)
-#define S3C2410_GPB9_INP     (0x00 << 18)
-#define S3C2410_GPB9_OUTP    (0x01 << 18)
 #define S3C2410_GPB9_nXDACK0 (0x02 << 18)
 #define S3C2443_GPB9_XDACK0  (0x03 << 18)
 #define S3C2400_GPB9_DATA25  (0x02 << 18)
 #define S3C2400_GPB9_I2SSDI  (0x03 << 18)
 
-#define S3C2410_GPB10        S3C2410_GPIONO(S3C2410_GPIO_BANKB, 10)
-#define S3C2410_GPB10_INP    (0x00 << 20)
-#define S3C2410_GPB10_OUTP   (0x01 << 20)
 #define S3C2410_GPB10_nXDRE0 (0x02 << 20)
 #define S3C2443_GPB10_XDREQ0 (0x03 << 20)
 #define S3C2400_GPB10_DATA26 (0x02 << 20)
 #define S3C2400_GPB10_nSS    (0x03 << 20)
 
-#define S3C2400_GPB11        S3C2410_GPIONO(S3C2410_GPIO_BANKB, 11)
 #define S3C2400_GPB11_INP    (0x00 << 22)
 #define S3C2400_GPB11_OUTP   (0x01 << 22)
 #define S3C2400_GPB11_DATA27 (0x02 << 22)
 
-#define S3C2400_GPB12        S3C2410_GPIONO(S3C2410_GPIO_BANKB, 12)
 #define S3C2400_GPB12_INP    (0x00 << 24)
 #define S3C2400_GPB12_OUTP   (0x01 << 24)
 #define S3C2400_GPB12_DATA28 (0x02 << 24)
 
-#define S3C2400_GPB13        S3C2410_GPIONO(S3C2410_GPIO_BANKB, 13)
 #define S3C2400_GPB13_INP    (0x00 << 26)
 #define S3C2400_GPB13_OUTP   (0x01 << 26)
 #define S3C2400_GPB13_DATA29 (0x02 << 26)
 
-#define S3C2400_GPB14        S3C2410_GPIONO(S3C2410_GPIO_BANKB, 14)
 #define S3C2400_GPB14_INP    (0x00 << 28)
 #define S3C2400_GPB14_OUTP   (0x01 << 28)
 #define S3C2400_GPB14_DATA30 (0x02 << 28)
 
-#define S3C2400_GPB15        S3C2410_GPIONO(S3C2410_GPIO_BANKB, 15)
 #define S3C2400_GPB15_INP    (0x00 << 30)
 #define S3C2400_GPB15_OUTP   (0x01 << 30)
 #define S3C2400_GPB15_DATA31 (0x02 << 30)
@@ -315,99 +231,51 @@
 #define S3C2400_GPCDAT	   S3C2410_GPIOREG(0x18)
 #define S3C2400_GPCUP	   S3C2410_GPIOREG(0x1C)
 
-#define S3C2410_GPC0            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 0)
-#define S3C2410_GPC0_INP	(0x00 << 0)
-#define S3C2410_GPC0_OUTP	(0x01 << 0)
 #define S3C2410_GPC0_LEND	(0x02 << 0)
 #define S3C2400_GPC0_VD0 	(0x02 << 0)
 
-#define S3C2410_GPC1            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 1)
-#define S3C2410_GPC1_INP	(0x00 << 2)
-#define S3C2410_GPC1_OUTP	(0x01 << 2)
 #define S3C2410_GPC1_VCLK	(0x02 << 2)
 #define S3C2400_GPC1_VD1 	(0x02 << 2)
 
-#define S3C2410_GPC2            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 2)
-#define S3C2410_GPC2_INP	(0x00 << 4)
-#define S3C2410_GPC2_OUTP	(0x01 << 4)
 #define S3C2410_GPC2_VLINE	(0x02 << 4)
 #define S3C2400_GPC2_VD2  	(0x02 << 4)
 
-#define S3C2410_GPC3            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 3)
-#define S3C2410_GPC3_INP	(0x00 << 6)
-#define S3C2410_GPC3_OUTP	(0x01 << 6)
 #define S3C2410_GPC3_VFRAME	(0x02 << 6)
 #define S3C2400_GPC3_VD3   	(0x02 << 6)
 
-#define S3C2410_GPC4            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 4)
-#define S3C2410_GPC4_INP	(0x00 << 8)
-#define S3C2410_GPC4_OUTP	(0x01 << 8)
 #define S3C2410_GPC4_VM		(0x02 << 8)
 #define S3C2400_GPC4_VD4	(0x02 << 8)
 
-#define S3C2410_GPC5            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 5)
-#define S3C2410_GPC5_INP	(0x00 << 10)
-#define S3C2410_GPC5_OUTP	(0x01 << 10)
 #define S3C2410_GPC5_LCDVF0	(0x02 << 10)
 #define S3C2400_GPC5_VD5   	(0x02 << 10)
 
-#define S3C2410_GPC6            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 6)
-#define S3C2410_GPC6_INP	(0x00 << 12)
-#define S3C2410_GPC6_OUTP	(0x01 << 12)
 #define S3C2410_GPC6_LCDVF1	(0x02 << 12)
 #define S3C2400_GPC6_VD6   	(0x02 << 12)
 
-#define S3C2410_GPC7            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 7)
-#define S3C2410_GPC7_INP	(0x00 << 14)
-#define S3C2410_GPC7_OUTP	(0x01 << 14)
 #define S3C2410_GPC7_LCDVF2	(0x02 << 14)
 #define S3C2400_GPC7_VD7   	(0x02 << 14)
 
-#define S3C2410_GPC8            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 8)
-#define S3C2410_GPC8_INP	(0x00 << 16)
-#define S3C2410_GPC8_OUTP	(0x01 << 16)
 #define S3C2410_GPC8_VD0	(0x02 << 16)
 #define S3C2400_GPC8_VD8	(0x02 << 16)
 
-#define S3C2410_GPC9            S3C2410_GPIONO(S3C2410_GPIO_BANKC, 9)
-#define S3C2410_GPC9_INP	(0x00 << 18)
-#define S3C2410_GPC9_OUTP	(0x01 << 18)
 #define S3C2410_GPC9_VD1	(0x02 << 18)
 #define S3C2400_GPC9_VD9	(0x02 << 18)
 
-#define S3C2410_GPC10           S3C2410_GPIONO(S3C2410_GPIO_BANKC, 10)
-#define S3C2410_GPC10_INP	(0x00 << 20)
-#define S3C2410_GPC10_OUTP	(0x01 << 20)
 #define S3C2410_GPC10_VD2	(0x02 << 20)
 #define S3C2400_GPC10_VD10	(0x02 << 20)
 
-#define S3C2410_GPC11           S3C2410_GPIONO(S3C2410_GPIO_BANKC, 11)
-#define S3C2410_GPC11_INP	(0x00 << 22)
-#define S3C2410_GPC11_OUTP	(0x01 << 22)
 #define S3C2410_GPC11_VD3	(0x02 << 22)
 #define S3C2400_GPC11_VD11	(0x02 << 22)
 
-#define S3C2410_GPC12           S3C2410_GPIONO(S3C2410_GPIO_BANKC, 12)
-#define S3C2410_GPC12_INP	(0x00 << 24)
-#define S3C2410_GPC12_OUTP	(0x01 << 24)
 #define S3C2410_GPC12_VD4	(0x02 << 24)
 #define S3C2400_GPC12_VD12	(0x02 << 24)
 
-#define S3C2410_GPC13           S3C2410_GPIONO(S3C2410_GPIO_BANKC, 13)
-#define S3C2410_GPC13_INP	(0x00 << 26)
-#define S3C2410_GPC13_OUTP	(0x01 << 26)
 #define S3C2410_GPC13_VD5	(0x02 << 26)
 #define S3C2400_GPC13_VD13	(0x02 << 26)
 
-#define S3C2410_GPC14           S3C2410_GPIONO(S3C2410_GPIO_BANKC, 14)
-#define S3C2410_GPC14_INP	(0x00 << 28)
-#define S3C2410_GPC14_OUTP	(0x01 << 28)
 #define S3C2410_GPC14_VD6	(0x02 << 28)
 #define S3C2400_GPC14_VD14	(0x02 << 28)
 
-#define S3C2410_GPC15           S3C2410_GPIONO(S3C2410_GPIO_BANKC, 15)
-#define S3C2410_GPC15_INP	(0x00 << 30)
-#define S3C2410_GPC15_OUTP	(0x01 << 30)
 #define S3C2410_GPC15_VD7	(0x02 << 30)
 #define S3C2400_GPC15_VD15	(0x02 << 30)
 
@@ -432,99 +300,51 @@
 #define S3C2400_GPDDAT	   S3C2410_GPIOREG(0x24)
 #define S3C2400_GPDUP	   S3C2410_GPIOREG(0x28)
 
-#define S3C2410_GPD0            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 0)
-#define S3C2410_GPD0_INP	(0x00 << 0)
-#define S3C2410_GPD0_OUTP	(0x01 << 0)
 #define S3C2410_GPD0_VD8	(0x02 << 0)
 #define S3C2400_GPD0_VFRAME	(0x02 << 0)
 #define S3C2442_GPD0_nSPICS1	(0x03 << 0)
 
-#define S3C2410_GPD1            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 1)
-#define S3C2410_GPD1_INP	(0x00 << 2)
-#define S3C2410_GPD1_OUTP	(0x01 << 2)
 #define S3C2410_GPD1_VD9	(0x02 << 2)
 #define S3C2400_GPD1_VM		(0x02 << 2)
 #define S3C2442_GPD1_SPICLK1	(0x03 << 2)
 
-#define S3C2410_GPD2            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 2)
-#define S3C2410_GPD2_INP	(0x00 << 4)
-#define S3C2410_GPD2_OUTP	(0x01 << 4)
 #define S3C2410_GPD2_VD10	(0x02 << 4)
 #define S3C2400_GPD2_VLINE	(0x02 << 4)
 
-#define S3C2410_GPD3            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 3)
-#define S3C2410_GPD3_INP	(0x00 << 6)
-#define S3C2410_GPD3_OUTP	(0x01 << 6)
 #define S3C2410_GPD3_VD11	(0x02 << 6)
 #define S3C2400_GPD3_VCLK	(0x02 << 6)
 
-#define S3C2410_GPD4            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 4)
-#define S3C2410_GPD4_INP	(0x00 << 8)
-#define S3C2410_GPD4_OUTP	(0x01 << 8)
 #define S3C2410_GPD4_VD12	(0x02 << 8)
 #define S3C2400_GPD4_LEND	(0x02 << 8)
 
-#define S3C2410_GPD5            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 5)
-#define S3C2410_GPD5_INP	(0x00 << 10)
-#define S3C2410_GPD5_OUTP	(0x01 << 10)
 #define S3C2410_GPD5_VD13	(0x02 << 10)
 #define S3C2400_GPD5_TOUT0	(0x02 << 10)
 
-#define S3C2410_GPD6            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 6)
-#define S3C2410_GPD6_INP	(0x00 << 12)
-#define S3C2410_GPD6_OUTP	(0x01 << 12)
 #define S3C2410_GPD6_VD14	(0x02 << 12)
 #define S3C2400_GPD6_TOUT1	(0x02 << 12)
 
-#define S3C2410_GPD7            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 7)
-#define S3C2410_GPD7_INP	(0x00 << 14)
-#define S3C2410_GPD7_OUTP	(0x01 << 14)
 #define S3C2410_GPD7_VD15	(0x02 << 14)
 #define S3C2400_GPD7_TOUT2	(0x02 << 14)
 
-#define S3C2410_GPD8            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 8)
-#define S3C2410_GPD8_INP	(0x00 << 16)
-#define S3C2410_GPD8_OUTP	(0x01 << 16)
 #define S3C2410_GPD8_VD16	(0x02 << 16)
 #define S3C2400_GPD8_TOUT3	(0x02 << 16)
 
-#define S3C2410_GPD9            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 9)
-#define S3C2410_GPD9_INP	(0x00 << 18)
-#define S3C2410_GPD9_OUTP	(0x01 << 18)
 #define S3C2410_GPD9_VD17	(0x02 << 18)
 #define S3C2400_GPD9_TCLK0	(0x02 << 18)
 #define S3C2410_GPD9_MASK       (0x03 << 18)
 
-#define S3C2410_GPD10           S3C2410_GPIONO(S3C2410_GPIO_BANKD, 10)
-#define S3C2410_GPD10_INP	(0x00 << 20)
-#define S3C2410_GPD10_OUTP	(0x01 << 20)
 #define S3C2410_GPD10_VD18	(0x02 << 20)
 #define S3C2400_GPD10_nWAIT	(0x02 << 20)
 
-#define S3C2410_GPD11           S3C2410_GPIONO(S3C2410_GPIO_BANKD, 11)
-#define S3C2410_GPD11_INP	(0x00 << 22)
-#define S3C2410_GPD11_OUTP	(0x01 << 22)
 #define S3C2410_GPD11_VD19	(0x02 << 22)
 
-#define S3C2410_GPD12           S3C2410_GPIONO(S3C2410_GPIO_BANKD, 12)
-#define S3C2410_GPD12_INP	(0x00 << 24)
-#define S3C2410_GPD12_OUTP	(0x01 << 24)
 #define S3C2410_GPD12_VD20	(0x02 << 24)
 
-#define S3C2410_GPD13           S3C2410_GPIONO(S3C2410_GPIO_BANKD, 13)
-#define S3C2410_GPD13_INP	(0x00 << 26)
-#define S3C2410_GPD13_OUTP	(0x01 << 26)
 #define S3C2410_GPD13_VD21	(0x02 << 26)
 
-#define S3C2410_GPD14           S3C2410_GPIONO(S3C2410_GPIO_BANKD, 14)
-#define S3C2410_GPD14_INP	(0x00 << 28)
-#define S3C2410_GPD14_OUTP	(0x01 << 28)
 #define S3C2410_GPD14_VD22	(0x02 << 28)
 #define S3C2410_GPD14_nSS1	(0x03 << 28)
 
-#define S3C2410_GPD15           S3C2410_GPIONO(S3C2410_GPIO_BANKD, 15)
-#define S3C2410_GPD15_INP	(0x00 << 30)
-#define S3C2410_GPD15_OUTP	(0x01 << 30)
 #define S3C2410_GPD15_VD23	(0x02 << 30)
 #define S3C2410_GPD15_nSS0	(0x03 << 30)
 
@@ -550,34 +370,22 @@
 #define S3C2400_GPEDAT	   S3C2410_GPIOREG(0x30)
 #define S3C2400_GPEUP	   S3C2410_GPIOREG(0x34)
 
-#define S3C2410_GPE0           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 0)
-#define S3C2410_GPE0_INP       (0x00 << 0)
-#define S3C2410_GPE0_OUTP      (0x01 << 0)
 #define S3C2410_GPE0_I2SLRCK   (0x02 << 0)
 #define S3C2443_GPE0_AC_nRESET (0x03 << 0)
 #define S3C2400_GPE0_EINT0     (0x02 << 0)
 #define S3C2410_GPE0_MASK      (0x03 << 0)
 
-#define S3C2410_GPE1           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 1)
-#define S3C2410_GPE1_INP       (0x00 << 2)
-#define S3C2410_GPE1_OUTP      (0x01 << 2)
 #define S3C2410_GPE1_I2SSCLK   (0x02 << 2)
 #define S3C2443_GPE1_AC_SYNC   (0x03 << 2)
 #define S3C2400_GPE1_EINT1     (0x02 << 2)
 #define S3C2400_GPE1_nSS       (0x03 << 2)
 #define S3C2410_GPE1_MASK      (0x03 << 2)
 
-#define S3C2410_GPE2           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 2)
-#define S3C2410_GPE2_INP       (0x00 << 4)
-#define S3C2410_GPE2_OUTP      (0x01 << 4)
 #define S3C2410_GPE2_CDCLK     (0x02 << 4)
 #define S3C2443_GPE2_AC_BITCLK (0x03 << 4)
 #define S3C2400_GPE2_EINT2     (0x02 << 4)
 #define S3C2400_GPE2_I2SSDI    (0x03 << 4)
 
-#define S3C2410_GPE3           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 3)
-#define S3C2410_GPE3_INP       (0x00 << 6)
-#define S3C2410_GPE3_OUTP      (0x01 << 6)
 #define S3C2410_GPE3_I2SSDI    (0x02 << 6)
 #define S3C2443_GPE3_AC_SDI    (0x03 << 6)
 #define S3C2400_GPE3_EINT3     (0x02 << 6)
@@ -585,9 +393,6 @@
 #define S3C2410_GPE3_nSS0      (0x03 << 6)
 #define S3C2410_GPE3_MASK      (0x03 << 6)
 
-#define S3C2410_GPE4           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 4)
-#define S3C2410_GPE4_INP       (0x00 << 8)
-#define S3C2410_GPE4_OUTP      (0x01 << 8)
 #define S3C2410_GPE4_I2SSDO    (0x02 << 8)
 #define S3C2443_GPE4_AC_SDO    (0x03 << 8)
 #define S3C2400_GPE4_EINT4     (0x02 << 8)
@@ -595,81 +400,48 @@
 #define S3C2410_GPE4_I2SSDI    (0x03 << 8)
 #define S3C2410_GPE4_MASK      (0x03 << 8)
 
-#define S3C2410_GPE5           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 5)
-#define S3C2410_GPE5_INP       (0x00 << 10)
-#define S3C2410_GPE5_OUTP      (0x01 << 10)
 #define S3C2410_GPE5_SDCLK     (0x02 << 10)
 #define S3C2443_GPE5_SD1_CLK   (0x02 << 10)
 #define S3C2400_GPE5_EINT5     (0x02 << 10)
 #define S3C2400_GPE5_TCLK1     (0x03 << 10)
 
-#define S3C2410_GPE6           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 6)
-#define S3C2410_GPE6_INP       (0x00 << 12)
-#define S3C2410_GPE6_OUTP      (0x01 << 12)
 #define S3C2410_GPE6_SDCMD     (0x02 << 12)
 #define S3C2443_GPE6_SD1_CMD   (0x02 << 12)
 #define S3C2443_GPE6_AC_BITCLK (0x03 << 12)
 #define S3C2400_GPE6_EINT6     (0x02 << 12)
 
-#define S3C2410_GPE7           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 7)
-#define S3C2410_GPE7_INP       (0x00 << 14)
-#define S3C2410_GPE7_OUTP      (0x01 << 14)
 #define S3C2410_GPE7_SDDAT0    (0x02 << 14)
 #define S3C2443_GPE5_SD1_DAT0  (0x02 << 14)
 #define S3C2443_GPE7_AC_SDI    (0x03 << 14)
 #define S3C2400_GPE7_EINT7     (0x02 << 14)
 
-#define S3C2410_GPE8           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 8)
-#define S3C2410_GPE8_INP       (0x00 << 16)
-#define S3C2410_GPE8_OUTP      (0x01 << 16)
 #define S3C2410_GPE8_SDDAT1    (0x02 << 16)
 #define S3C2443_GPE8_SD1_DAT1  (0x02 << 16)
 #define S3C2443_GPE8_AC_SDO    (0x03 << 16)
 #define S3C2400_GPE8_nXDACK0   (0x02 << 16)
 
-#define S3C2410_GPE9           S3C2410_GPIONO(S3C2410_GPIO_BANKE, 9)
-#define S3C2410_GPE9_INP       (0x00 << 18)
-#define S3C2410_GPE9_OUTP      (0x01 << 18)
 #define S3C2410_GPE9_SDDAT2    (0x02 << 18)
 #define S3C2443_GPE9_SD1_DAT2  (0x02 << 18)
 #define S3C2443_GPE9_AC_SYNC   (0x03 << 18)
 #define S3C2400_GPE9_nXDACK1   (0x02 << 18)
 #define S3C2400_GPE9_nXBACK    (0x03 << 18)
 
-#define S3C2410_GPE10          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 10)
-#define S3C2410_GPE10_INP      (0x00 << 20)
-#define S3C2410_GPE10_OUTP     (0x01 << 20)
 #define S3C2410_GPE10_SDDAT3   (0x02 << 20)
 #define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
 #define S3C2443_GPE10_AC_nRESET (0x03 << 20)
 #define S3C2400_GPE10_nXDREQ0  (0x02 << 20)
 
-#define S3C2410_GPE11          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 11)
-#define S3C2410_GPE11_INP      (0x00 << 22)
-#define S3C2410_GPE11_OUTP     (0x01 << 22)
 #define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
 #define S3C2400_GPE11_nXDREQ1  (0x02 << 22)
 #define S3C2400_GPE11_nXBREQ   (0x03 << 22)
 
-#define S3C2410_GPE12          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 12)
-#define S3C2410_GPE12_INP      (0x00 << 24)
-#define S3C2410_GPE12_OUTP     (0x01 << 24)
 #define S3C2410_GPE12_SPIMOSI0 (0x02 << 24)
 
-#define S3C2410_GPE13          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 13)
-#define S3C2410_GPE13_INP      (0x00 << 26)
-#define S3C2410_GPE13_OUTP     (0x01 << 26)
 #define S3C2410_GPE13_SPICLK0  (0x02 << 26)
 
-#define S3C2410_GPE14          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 14)
-#define S3C2410_GPE14_INP      (0x00 << 28)
-#define S3C2410_GPE14_OUTP     (0x01 << 28)
 #define S3C2410_GPE14_IICSCL   (0x02 << 28)
 #define S3C2410_GPE14_MASK     (0x03 << 28)
 
-#define S3C2410_GPE15          S3C2410_GPIONO(S3C2410_GPIO_BANKE, 15)
-#define S3C2410_GPE15_INP      (0x00 << 30)
-#define S3C2410_GPE15_OUTP     (0x01 << 30)
 #define S3C2410_GPE15_IICSDA   (0x02 << 30)
 #define S3C2410_GPE15_MASK     (0x03 << 30)
 
@@ -705,55 +477,31 @@
 #define S3C2400_GPFDAT	   S3C2410_GPIOREG(0x3C)
 #define S3C2400_GPFUP	   S3C2410_GPIOREG(0x40)
 
-#define S3C2410_GPF0        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 0)
-#define S3C2410_GPF0_INP    (0x00 << 0)
-#define S3C2410_GPF0_OUTP   (0x01 << 0)
 #define S3C2410_GPF0_EINT0  (0x02 << 0)
 #define S3C2400_GPF0_RXD0   (0x02 << 0)
 
-#define S3C2410_GPF1        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 1)
-#define S3C2410_GPF1_INP    (0x00 << 2)
-#define S3C2410_GPF1_OUTP   (0x01 << 2)
 #define S3C2410_GPF1_EINT1  (0x02 << 2)
 #define S3C2400_GPF1_RXD1   (0x02 << 2)
 #define S3C2400_GPF1_IICSDA (0x03 << 2)
 
-#define S3C2410_GPF2        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 2)
-#define S3C2410_GPF2_INP    (0x00 << 4)
-#define S3C2410_GPF2_OUTP   (0x01 << 4)
 #define S3C2410_GPF2_EINT2  (0x02 << 4)
 #define S3C2400_GPF2_TXD0   (0x02 << 4)
 
-#define S3C2410_GPF3        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 3)
-#define S3C2410_GPF3_INP    (0x00 << 6)
-#define S3C2410_GPF3_OUTP   (0x01 << 6)
 #define S3C2410_GPF3_EINT3  (0x02 << 6)
 #define S3C2400_GPF3_TXD1   (0x02 << 6)
 #define S3C2400_GPF3_IICSCL (0x03 << 6)
 
-#define S3C2410_GPF4        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 4)
-#define S3C2410_GPF4_INP    (0x00 << 8)
-#define S3C2410_GPF4_OUTP   (0x01 << 8)
 #define S3C2410_GPF4_EINT4  (0x02 << 8)
 #define S3C2400_GPF4_nRTS0  (0x02 << 8)
 #define S3C2400_GPF4_nXBACK (0x03 << 8)
 
-#define S3C2410_GPF5        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 5)
-#define S3C2410_GPF5_INP    (0x00 << 10)
-#define S3C2410_GPF5_OUTP   (0x01 << 10)
 #define S3C2410_GPF5_EINT5  (0x02 << 10)
 #define S3C2400_GPF5_nCTS0  (0x02 << 10)
 #define S3C2400_GPF5_nXBREQ (0x03 << 10)
 
-#define S3C2410_GPF6        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 6)
-#define S3C2410_GPF6_INP    (0x00 << 12)
-#define S3C2410_GPF6_OUTP   (0x01 << 12)
 #define S3C2410_GPF6_EINT6  (0x02 << 12)
 #define S3C2400_GPF6_CLKOUT (0x02 << 12)
 
-#define S3C2410_GPF7        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 7)
-#define S3C2410_GPF7_INP    (0x00 << 14)
-#define S3C2410_GPF7_OUTP   (0x01 << 14)
 #define S3C2410_GPF7_EINT7  (0x02 << 14)
 
 #define S3C2410_GPF_PUPDIS(x)  (1<<(x))
@@ -778,117 +526,69 @@
 #define S3C2400_GPGDAT	   S3C2410_GPIOREG(0x48)
 #define S3C2400_GPGUP	   S3C2410_GPIOREG(0x4C)
 
-#define S3C2410_GPG0          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 0)
-#define S3C2410_GPG0_INP      (0x00 << 0)
-#define S3C2410_GPG0_OUTP     (0x01 << 0)
 #define S3C2410_GPG0_EINT8    (0x02 << 0)
 #define S3C2400_GPG0_I2SLRCK  (0x02 << 0)
 
-#define S3C2410_GPG1          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 1)
-#define S3C2410_GPG1_INP      (0x00 << 2)
-#define S3C2410_GPG1_OUTP     (0x01 << 2)
 #define S3C2410_GPG1_EINT9    (0x02 << 2)
 #define S3C2400_GPG1_I2SSCLK  (0x02 << 2)
 
-#define S3C2410_GPG2          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 2)
-#define S3C2410_GPG2_INP      (0x00 << 4)
-#define S3C2410_GPG2_OUTP     (0x01 << 4)
 #define S3C2410_GPG2_EINT10   (0x02 << 4)
 #define S3C2410_GPG2_nSS0     (0x03 << 4)
 #define S3C2400_GPG2_CDCLK    (0x02 << 4)
 
-#define S3C2410_GPG3          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 3)
-#define S3C2410_GPG3_INP      (0x00 << 6)
-#define S3C2410_GPG3_OUTP     (0x01 << 6)
 #define S3C2410_GPG3_EINT11   (0x02 << 6)
 #define S3C2410_GPG3_nSS1     (0x03 << 6)
 #define S3C2400_GPG3_I2SSDO   (0x02 << 6)
 #define S3C2400_GPG3_I2SSDI   (0x03 << 6)
 
-#define S3C2410_GPG4          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 4)
-#define S3C2410_GPG4_INP      (0x00 << 8)
-#define S3C2410_GPG4_OUTP     (0x01 << 8)
 #define S3C2410_GPG4_EINT12   (0x02 << 8)
 #define S3C2400_GPG4_MMCCLK   (0x02 << 8)
 #define S3C2400_GPG4_I2SSDI   (0x03 << 8)
 #define S3C2410_GPG4_LCDPWREN (0x03 << 8)
 #define S3C2443_GPG4_LCDPWRDN (0x03 << 8)
 
-#define S3C2410_GPG5          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 5)
-#define S3C2410_GPG5_INP      (0x00 << 10)
-#define S3C2410_GPG5_OUTP     (0x01 << 10)
 #define S3C2410_GPG5_EINT13   (0x02 << 10)
 #define S3C2400_GPG5_MMCCMD   (0x02 << 10)
 #define S3C2400_GPG5_IICSDA   (0x03 << 10)
 #define S3C2410_GPG5_SPIMISO1 (0x03 << 10)	/* not s3c2443 */
 
-#define S3C2410_GPG6          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 6)
-#define S3C2410_GPG6_INP      (0x00 << 12)
-#define S3C2410_GPG6_OUTP     (0x01 << 12)
 #define S3C2410_GPG6_EINT14   (0x02 << 12)
 #define S3C2400_GPG6_MMCDAT   (0x02 << 12)
 #define S3C2400_GPG6_IICSCL   (0x03 << 12)
 #define S3C2410_GPG6_SPIMOSI1 (0x03 << 12)
 
-#define S3C2410_GPG7          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 7)
-#define S3C2410_GPG7_INP      (0x00 << 14)
-#define S3C2410_GPG7_OUTP     (0x01 << 14)
 #define S3C2410_GPG7_EINT15   (0x02 << 14)
 #define S3C2410_GPG7_SPICLK1  (0x03 << 14)
 #define S3C2400_GPG7_SPIMISO  (0x02 << 14)
 #define S3C2400_GPG7_IICSDA   (0x03 << 14)
 
-#define S3C2410_GPG8          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 8)
-#define S3C2410_GPG8_INP      (0x00 << 16)
-#define S3C2410_GPG8_OUTP     (0x01 << 16)
 #define S3C2410_GPG8_EINT16   (0x02 << 16)
 #define S3C2400_GPG8_SPIMOSI  (0x02 << 16)
 #define S3C2400_GPG8_IICSCL   (0x03 << 16)
 
-#define S3C2410_GPG9          S3C2410_GPIONO(S3C2410_GPIO_BANKG, 9)
-#define S3C2410_GPG9_INP      (0x00 << 18)
-#define S3C2410_GPG9_OUTP     (0x01 << 18)
 #define S3C2410_GPG9_EINT17   (0x02 << 18)
 #define S3C2400_GPG9_SPICLK   (0x02 << 18)
 #define S3C2400_GPG9_MMCCLK   (0x03 << 18)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
-#define S3C2410_GPG10_INP     (0x00 << 20)
-#define S3C2410_GPG10_OUTP    (0x01 << 20)
 #define S3C2410_GPG10_EINT18  (0x02 << 20)
 
-#define S3C2410_GPG11         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 11)
-#define S3C2410_GPG11_INP     (0x00 << 22)
-#define S3C2410_GPG11_OUTP    (0x01 << 22)
 #define S3C2410_GPG11_EINT19  (0x02 << 22)
 #define S3C2410_GPG11_TCLK1   (0x03 << 22)
 #define S3C2443_GPG11_CF_nIREQ (0x03 << 22)
 
-#define S3C2410_GPG12         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
-#define S3C2410_GPG12_INP     (0x00 << 24)
-#define S3C2410_GPG12_OUTP    (0x01 << 24)
 #define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
 #define S3C2442_GPG12_nSPICS0 (0x03 << 24)
 #define S3C2443_GPG12_nINPACK (0x03 << 24)
 
-#define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
-#define S3C2410_GPG13_INP     (0x00 << 26)
-#define S3C2410_GPG13_OUTP    (0x01 << 26)
 #define S3C2410_GPG13_EINT21  (0x02 << 26)
 #define S3C2410_GPG13_nXPON   (0x03 << 26)
 #define S3C2443_GPG13_CF_nREG (0x03 << 26)
 
-#define S3C2410_GPG14         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
-#define S3C2410_GPG14_INP     (0x00 << 28)
-#define S3C2410_GPG14_OUTP    (0x01 << 28)
 #define S3C2410_GPG14_EINT22  (0x02 << 28)
 #define S3C2410_GPG14_YMON    (0x03 << 28)
 #define S3C2443_GPG14_CF_RESET (0x03 << 28)
 
-#define S3C2410_GPG15         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
-#define S3C2410_GPG15_INP     (0x00 << 30)
-#define S3C2410_GPG15_OUTP    (0x01 << 30)
 #define S3C2410_GPG15_EINT23  (0x02 << 30)
 #define S3C2410_GPG15_nYPON   (0x03 << 30)
 #define S3C2443_GPG15_CF_PWR  (0x03 << 30)
@@ -907,62 +607,29 @@
 #define S3C2410_GPHDAT	   S3C2410_GPIOREG(0x74)
 #define S3C2410_GPHUP	   S3C2410_GPIOREG(0x78)
 
-#define S3C2410_GPH0        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 0)
-#define S3C2410_GPH0_INP    (0x00 << 0)
-#define S3C2410_GPH0_OUTP   (0x01 << 0)
 #define S3C2410_GPH0_nCTS0  (0x02 << 0)
 
-#define S3C2410_GPH1        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 1)
-#define S3C2410_GPH1_INP    (0x00 << 2)
-#define S3C2410_GPH1_OUTP   (0x01 << 2)
 #define S3C2410_GPH1_nRTS0  (0x02 << 2)
 
-#define S3C2410_GPH2        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 2)
-#define S3C2410_GPH2_INP    (0x00 << 4)
-#define S3C2410_GPH2_OUTP   (0x01 << 4)
 #define S3C2410_GPH2_TXD0   (0x02 << 4)
 
-#define S3C2410_GPH3        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 3)
-#define S3C2410_GPH3_INP    (0x00 << 6)
-#define S3C2410_GPH3_OUTP   (0x01 << 6)
 #define S3C2410_GPH3_RXD0   (0x02 << 6)
 
-#define S3C2410_GPH4        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 4)
-#define S3C2410_GPH4_INP    (0x00 << 8)
-#define S3C2410_GPH4_OUTP   (0x01 << 8)
 #define S3C2410_GPH4_TXD1   (0x02 << 8)
 
-#define S3C2410_GPH5        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 5)
-#define S3C2410_GPH5_INP    (0x00 << 10)
-#define S3C2410_GPH5_OUTP   (0x01 << 10)
 #define S3C2410_GPH5_RXD1   (0x02 << 10)
 
-#define S3C2410_GPH6        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 6)
-#define S3C2410_GPH6_INP    (0x00 << 12)
-#define S3C2410_GPH6_OUTP   (0x01 << 12)
 #define S3C2410_GPH6_TXD2   (0x02 << 12)
 #define S3C2410_GPH6_nRTS1  (0x03 << 12)
 
-#define S3C2410_GPH7        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 7)
-#define S3C2410_GPH7_INP    (0x00 << 14)
-#define S3C2410_GPH7_OUTP   (0x01 << 14)
 #define S3C2410_GPH7_RXD2   (0x02 << 14)
 #define S3C2410_GPH7_nCTS1  (0x03 << 14)
 
-#define S3C2410_GPH8        S3C2410_GPIONO(S3C2410_GPIO_BANKH, 8)
-#define S3C2410_GPH8_INP    (0x00 << 16)
-#define S3C2410_GPH8_OUTP   (0x01 << 16)
 #define S3C2410_GPH8_UCLK   (0x02 << 16)
 
-#define S3C2410_GPH9          S3C2410_GPIONO(S3C2410_GPIO_BANKH, 9)
-#define S3C2410_GPH9_INP      (0x00 << 18)
-#define S3C2410_GPH9_OUTP     (0x01 << 18)
 #define S3C2410_GPH9_CLKOUT0  (0x02 << 18)
 #define S3C2442_GPH9_nSPICS0  (0x03 << 18)
 
-#define S3C2410_GPH10         S3C2410_GPIONO(S3C2410_GPIO_BANKH, 10)
-#define S3C2410_GPH10_INP     (0x00 << 20)
-#define S3C2410_GPH10_OUTP    (0x01 << 20)
 #define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
 
 /* The S3C2412 and S3C2413 move the GPJ register set to after
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/system-reset.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/system-reset.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/include/mach/system-reset.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/include/mach/system-reset.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,21 +11,13 @@
 */
 
 #include <mach/hardware.h>
-#include <linux/io.h>
-
-#include <plat/regs-watchdog.h>
-#include <mach/regs-clock.h>
-
-#include <linux/clk.h>
-#include <linux/err.h>
+#include <plat/watchdog-reset.h>
 
 extern void (*s3c24xx_reset_hook)(void);
 
 static void
 arch_reset(char mode, const char *cmd)
 {
-	struct clk *wdtclk;
-
 	if (mode == 's') {
 		cpu_reset(0);
 	}
@@ -33,31 +25,7 @@
 	if (s3c24xx_reset_hook)
 		s3c24xx_reset_hook();
 
-	printk("arch_reset: attempting watchdog reset\n");
-
-	__raw_writel(0, S3C2410_WTCON);	  /* disable watchdog, to be safe  */
-
-	wdtclk = clk_get(NULL, "watchdog");
-	if (!IS_ERR(wdtclk)) {
-		clk_enable(wdtclk);
-	} else
-		printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
-
-	/* put initial values into count and data */
-	__raw_writel(0x80, S3C2410_WTCNT);
-	__raw_writel(0x80, S3C2410_WTDAT);
-
-	/* set the watchdog to go and reset... */
-	__raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
-		     S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
-
-	/* wait for reset to assert... */
-	mdelay(500);
-
-	printk(KERN_ERR "Watchdog reset failed to assert reset\n");
-
-	/* delay to allow the serial port to show the message */
-	mdelay(50);
+	arch_wdt_reset();
 
 	/* we'll take a jump through zero as a poor second */
 	cpu_reset(0);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -59,6 +59,7 @@
 	bool "IPAQ H1940"
 	select CPU_S3C2410
 	select PM_H1940 if PM
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the HP IPAQ H1940
 
@@ -70,6 +71,7 @@
 config MACH_N30
 	bool "Acer N30 family"
 	select CPU_S3C2410
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you want suppt for the Acer N30, Acer N35,
 	  Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
@@ -82,6 +84,7 @@
 	select MACH_BAST_IDE
 	select S3C24XX_DCLK
 	select ISA
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the Simtec Electronics EB2410ITX
 	  development board (also known as BAST)
@@ -89,6 +92,7 @@
 config MACH_OTOM
  	bool "NexVision OTOM Board"
  	select CPU_S3C2410
+	select S3C_DEV_USB_HOST
 	help
  	  Say Y here if you are using the Nex Vision OTOM board
 
@@ -96,6 +100,7 @@
 	bool "AML M5900 Series"
 	select CPU_S3C2410
 	select PM_SIMTEC if PM
+	select S3C_DEV_USB_HOST
 	help
 	   Say Y here if you are using the American Microsystems M5900 Series
            <http://www.amltd.com>
@@ -111,6 +116,7 @@
 config MACH_TCT_HAMMER
 	bool "TCT Hammer Board"
 	select CPU_S3C2410
+	select S3C_DEV_USB_HOST
 	help
 	   Say Y here if you are using the TinCanTools Hammer Board
            <http://www.tincantools.com>
@@ -122,12 +128,14 @@
 	select SIMTEC_NOR
 	select MACH_BAST_IDE
 	select CPU_S3C2410
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the Thorcom VR1000 board.
 
 config MACH_QT2410
 	bool "QT2410"
 	select CPU_S3C2410
+	select S3C_DEV_USB_HOST
 	help
 	   Say Y here if you are using the Armzone QT2410
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-amlm5900.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/proc_fs.h>
@@ -224,8 +225,8 @@
 	} else {
 		enable_irq_wake(IRQ_EINT9);
 		/* configure the suspend/resume status pin */
-		s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP);
-		s3c2410_gpio_pullup(S3C2410_GPF2, 0);
+		s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT);
+		s3c2410_gpio_pullup(S3C2410_GPF(2), 0);
 	}
 }
 static void __init amlm5900_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-bast.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-bast.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-bast.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-bast.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
@@ -212,15 +213,15 @@
 static int bast_pm_suspend(struct sys_device *sd, pm_message_t state)
 {
 	/* ensure that an nRESET is not generated on resume. */
-	s3c2410_gpio_setpin(S3C2410_GPA21, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_OUT);
+	s3c2410_gpio_setpin(S3C2410_GPA(21), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT);
 
 	return 0;
 }
 
 static int bast_pm_resume(struct sys_device *sd)
 {
-	s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_nRSTOUT);
+	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
 	return 0;
 }
 
@@ -591,8 +592,6 @@
 	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
-
-	usb_simtec_init();
 }
 
 static void __init bast_init(void)
@@ -607,6 +606,7 @@
 	i2c_register_board_info(0, bast_i2c_devs,
 				ARRAY_SIZE(bast_i2c_devs));
 
+	usb_simtec_init();
 	nor_simtec_init();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-h1940.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-h1940.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-h1940.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-h1940.c	2009-09-09 18:13:59.000000000 -0400
@@ -127,7 +127,7 @@
 
 static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
 	.udc_command		= h1940_udc_pullup,
-	.vbus_pin		= S3C2410_GPG5,
+	.vbus_pin		= S3C2410_GPG(5),
 	.vbus_pin_inverted	= 1,
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-n30.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-n30.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-n30.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-n30.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 
 #include <linux/gpio_keys.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -85,10 +86,10 @@
 {
 	switch (cmd) {
 	case S3C2410_UDC_P_ENABLE :
-		s3c2410_gpio_setpin(S3C2410_GPB3, 1);
+		s3c2410_gpio_setpin(S3C2410_GPB(3), 1);
 		break;
 	case S3C2410_UDC_P_DISABLE :
-		s3c2410_gpio_setpin(S3C2410_GPB3, 0);
+		s3c2410_gpio_setpin(S3C2410_GPB(3), 0);
 		break;
 	case S3C2410_UDC_P_RESET :
 		break;
@@ -99,55 +100,55 @@
 
 static struct s3c2410_udc_mach_info n30_udc_cfg __initdata = {
 	.udc_command		= n30_udc_pullup,
-	.vbus_pin		= S3C2410_GPG1,
+	.vbus_pin		= S3C2410_GPG(1),
 	.vbus_pin_inverted	= 0,
 };
 
 static struct gpio_keys_button n30_buttons[] = {
 	{
-		.gpio		= S3C2410_GPF0,
+		.gpio		= S3C2410_GPF(0),
 		.code		= KEY_POWER,
 		.desc		= "Power",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG9,
+		.gpio		= S3C2410_GPG(9),
 		.code		= KEY_UP,
 		.desc		= "Thumbwheel Up",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG8,
+		.gpio		= S3C2410_GPG(8),
 		.code		= KEY_DOWN,
 		.desc		= "Thumbwheel Down",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG7,
+		.gpio		= S3C2410_GPG(7),
 		.code		= KEY_ENTER,
 		.desc		= "Thumbwheel Press",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF7,
+		.gpio		= S3C2410_GPF(7),
 		.code		= KEY_HOMEPAGE,
 		.desc		= "Home",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF6,
+		.gpio		= S3C2410_GPF(6),
 		.code		= KEY_CALENDAR,
 		.desc		= "Calendar",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF5,
+		.gpio		= S3C2410_GPF(5),
 		.code		= KEY_ADDRESSBOOK,
 		.desc		= "Contacts",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF4,
+		.gpio		= S3C2410_GPF(4),
 		.code		= KEY_MAIL,
 		.desc		= "Mail",
 		.active_low	= 0,
@@ -169,73 +170,73 @@
 
 static struct gpio_keys_button n35_buttons[] = {
 	{
-		.gpio		= S3C2410_GPF0,
+		.gpio		= S3C2410_GPF(0),
 		.code		= KEY_POWER,
 		.desc		= "Power",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG9,
+		.gpio		= S3C2410_GPG(9),
 		.code		= KEY_UP,
 		.desc		= "Joystick Up",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG8,
+		.gpio		= S3C2410_GPG(8),
 		.code		= KEY_DOWN,
 		.desc		= "Joystick Down",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG6,
+		.gpio		= S3C2410_GPG(6),
 		.code		= KEY_DOWN,
 		.desc		= "Joystick Left",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG5,
+		.gpio		= S3C2410_GPG(5),
 		.code		= KEY_DOWN,
 		.desc		= "Joystick Right",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG7,
+		.gpio		= S3C2410_GPG(7),
 		.code		= KEY_ENTER,
 		.desc		= "Joystick Press",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF7,
+		.gpio		= S3C2410_GPF(7),
 		.code		= KEY_HOMEPAGE,
 		.desc		= "Home",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF6,
+		.gpio		= S3C2410_GPF(6),
 		.code		= KEY_CALENDAR,
 		.desc		= "Calendar",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF5,
+		.gpio		= S3C2410_GPF(5),
 		.code		= KEY_ADDRESSBOOK,
 		.desc		= "Contacts",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF4,
+		.gpio		= S3C2410_GPF(4),
 		.code		= KEY_MAIL,
 		.desc		= "Mail",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPF3,
+		.gpio		= S3C2410_GPF(3),
 		.code		= SW_RADIO,
 		.desc		= "GPS Antenna",
 		.active_low	= 0,
 	},
 	{
-		.gpio		= S3C2410_GPG2,
+		.gpio		= S3C2410_GPG(2),
 		.code		= SW_HEADPHONE_INSERT,
 		.desc		= "Headphone",
 		.active_low	= 0,
@@ -259,7 +260,7 @@
 /* This is the bluetooth LED on the device. */
 static struct s3c24xx_led_platdata n30_blue_led_pdata = {
 	.name		= "blue_led",
-	.gpio		= S3C2410_GPG6,
+	.gpio		= S3C2410_GPG(6),
 	.def_trigger	= "",
 };
 
@@ -270,7 +271,7 @@
 static struct s3c24xx_led_platdata n30_warning_led_pdata = {
 	.name		= "warning_led",
 	.flags          = S3C24XX_LEDF_ACTLOW,
-	.gpio		= S3C2410_GPD9,
+	.gpio		= S3C2410_GPD(9),
 	.def_trigger	= "",
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-qt2410.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-qt2410.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-qt2410.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-qt2410.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
@@ -198,7 +199,7 @@
 /* LED */
 
 static struct s3c24xx_led_platdata qt2410_pdata_led = {
-	.gpio		= S3C2410_GPB0,
+	.gpio		= S3C2410_GPB(0),
 	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
 	.name		= "led",
 	.def_trigger	= "timer",
@@ -218,18 +219,18 @@
 {
 	switch (cs) {
 	case BITBANG_CS_ACTIVE:
-		s3c2410_gpio_setpin(S3C2410_GPB5, 0);
+		s3c2410_gpio_setpin(S3C2410_GPB(5), 0);
 		break;
 	case BITBANG_CS_INACTIVE:
-		s3c2410_gpio_setpin(S3C2410_GPB5, 1);
+		s3c2410_gpio_setpin(S3C2410_GPB(5), 1);
 		break;
 	}
 }
 
 static struct s3c2410_spigpio_info spi_gpio_cfg = {
-	.pin_clk	= S3C2410_GPG7,
-	.pin_mosi	= S3C2410_GPG6,
-	.pin_miso	= S3C2410_GPG5,
+	.pin_clk	= S3C2410_GPG(7),
+	.pin_mosi	= S3C2410_GPG(6),
+	.pin_miso	= S3C2410_GPG(5),
 	.chip_select	= &spi_gpio_cs,
 };
 
@@ -346,13 +347,13 @@
 	}
 	s3c24xx_fb_set_platdata(&qt2410_fb_info);
 
-	s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_setpin(S3C2410_GPB0, 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
 
 	s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
 	s3c_i2c0_set_platdata(NULL);
 
-	s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPIO_OUTPUT);
 
 	platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
 	s3c_pm_init();
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-vr1000.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-vr1000.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/mach-vr1000.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/mach-vr1000.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/dm9000.h>
 #include <linux/i2c.h>
 
@@ -277,19 +278,19 @@
 
 static struct s3c24xx_led_platdata vr1000_led1_pdata = {
 	.name		= "led1",
-	.gpio		= S3C2410_GPB0,
+	.gpio		= S3C2410_GPB(0),
 	.def_trigger	= "",
 };
 
 static struct s3c24xx_led_platdata vr1000_led2_pdata = {
 	.name		= "led2",
-	.gpio		= S3C2410_GPB1,
+	.gpio		= S3C2410_GPB(1),
 	.def_trigger	= "",
 };
 
 static struct s3c24xx_led_platdata vr1000_led3_pdata = {
 	.name		= "led3",
-	.gpio		= S3C2410_GPB2,
+	.gpio		= S3C2410_GPB(2),
 	.def_trigger	= "",
 };
 
@@ -355,8 +356,8 @@
 
 static void vr1000_power_off(void)
 {
-	s3c2410_gpio_cfgpin(S3C2410_GPB9, S3C2410_GPB9_OUTP);
-	s3c2410_gpio_setpin(S3C2410_GPB9, 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPB(9), S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPB(9), 1);
 }
 
 static void __init vr1000_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/pm.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/time.h>
 #include <linux/sysdev.h>
+#include <linux/gpio.h>
 #include <linux/io.h>
 
 #include <mach/hardware.h>
@@ -76,7 +77,7 @@
 	}
 
 	if ( machine_is_aml_m5900() )
-		s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+		s3c2410_gpio_setpin(S3C2410_GPF(2), 1);
 
 }
 
@@ -91,7 +92,7 @@
 	__raw_writel(tmp, S3C2410_GSTATUS2);
 
 	if ( machine_is_aml_m5900() )
-		s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+		s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/usb-simtec.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/usb-simtec.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2410/usb-simtec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2410/usb-simtec.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
+#include <linux/gpio.h>
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -29,7 +30,6 @@
 
 #include <mach/bast-map.h>
 #include <mach/bast-irq.h>
-#include <mach/regs-gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -53,9 +53,9 @@
 	power_state[port] = to;
 
 	if (power_state[0] && power_state[1])
-		s3c2410_gpio_setpin(S3C2410_GPB4, 0);
+		gpio_set_value(S3C2410_GPB(4), 0);
 	else
-		s3c2410_gpio_setpin(S3C2410_GPB4, 1);
+		gpio_set_value(S3C2410_GPB(4), 1);
 }
 
 static irqreturn_t
@@ -63,7 +63,7 @@
 {
 	struct s3c2410_hcd_info *info = pw;
 
-	if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
+	if (gpio_get_value(S3C2410_GPG(10)) == 0) {
 		pr_debug("usb_simtec: over-current irq (oc detected)\n");
 		s3c2410_usb_report_oc(info, 3);
 	} else {
@@ -106,10 +106,27 @@
 
 int usb_simtec_init(void)
 {
+	int ret;
+
 	printk("USB Power Control, (c) 2004 Simtec Electronics\n");
-	s3c_device_usb.dev.platform_data = &usb_simtec_info;
 
-	s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
-	s3c2410_gpio_setpin(S3C2410_GPB4, 1);
+	ret = gpio_request(S3C2410_GPB(4), "USB power control");
+	if (ret < 0) {
+		pr_err("%s: failed to get GPB4\n", __func__);
+		return ret;
+	}
+
+	ret = gpio_request(S3C2410_GPG(10), "USB overcurrent");
+	if (ret < 0) {
+		pr_err("%s: failed to get GPG10\n", __func__);
+		gpio_free(S3C2410_GPB(4));
+		return ret;
+	}
+
+	/* turn power on */
+	gpio_direction_output(S3C2410_GPB(4), 1);
+	gpio_direction_input(S3C2410_GPG(10));
+
+	s3c_device_usb.dev.platform_data = &usb_simtec_info;
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/dma.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,12 +20,13 @@
 
 #include <mach/dma.h>
 
-#include <plat/dma.h>
+#include <plat/dma-plat.h>
 #include <plat/cpu.h>
 
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-ac97.h>
+#include <plat/regs-dma.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,7 @@
 config MACH_JIVE
 	bool "Logitech Jive"
 	select CPU_S3C2412
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the Logitech Jive.
 
@@ -50,6 +51,7 @@
 	select CPU_S3C2412
 	select MACH_S3C2413
 	select MACH_SMDK
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using an SMDK2413
 
@@ -72,6 +74,7 @@
 config MACH_VSTMS
 	bool "VMSTMS"
 	select CPU_S3C2412
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using an VSTMS board
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/mach-jive.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/mach-jive.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/mach-jive.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/mach-jive.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
@@ -356,8 +357,8 @@
 {
 	printk(KERN_DEBUG "%s(%d)\n", __func__, set);
 
-	s3c2410_gpio_setpin(S3C2410_GPG13, set);
-	s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPG(13), set);
+	s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_OUTPUT);
 }
 
 #undef LCD_UPPER_MARGIN
@@ -390,13 +391,13 @@
 
 static void jive_lcd_spi_chipselect(struct s3c2410_spigpio_info *spi, int cs)
 {
-	s3c2410_gpio_setpin(S3C2410_GPB7, cs ? 0 : 1);
+	s3c2410_gpio_setpin(S3C2410_GPB(7), cs ? 0 : 1);
 }
 
 static struct s3c2410_spigpio_info jive_lcd_spi = {
 	.bus_num	= 1,
-	.pin_clk	= S3C2410_GPG8,
-	.pin_mosi	= S3C2410_GPB8,
+	.pin_clk	= S3C2410_GPG(8),
+	.pin_mosi	= S3C2410_GPB(8),
 	.num_chipselect	= 1,
 	.chip_select	= jive_lcd_spi_chipselect,
 };
@@ -412,13 +413,13 @@
 
 static void jive_wm8750_chipselect(struct s3c2410_spigpio_info *spi, int cs)
 {
-	s3c2410_gpio_setpin(S3C2410_GPH10, cs ? 0 : 1);
+	s3c2410_gpio_setpin(S3C2410_GPH(10), cs ? 0 : 1);
 }
 
 static struct s3c2410_spigpio_info jive_wm8750_spi = {
 	.bus_num	= 2,
-	.pin_clk	= S3C2410_GPB4,
-	.pin_mosi	= S3C2410_GPB9,
+	.pin_clk	= S3C2410_GPB(4),
+	.pin_mosi	= S3C2410_GPB(9),
 	.num_chipselect	= 1,
 	.chip_select	= jive_wm8750_chipselect,
 };
@@ -479,7 +480,7 @@
 };
 
 static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
-	.vbus_pin	= S3C2410_GPG1,		/* detect is on GPG1 */
+	.vbus_pin	= S3C2410_GPG(1),		/* detect is on GPG1 */
 };
 
 /* Jive power management device */
@@ -529,8 +530,8 @@
 {
 	printk(KERN_INFO "powering system down...\n");
 
-	s3c2410_gpio_setpin(S3C2410_GPC5, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPC5, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPC(5), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT);
 }
 
 static void __init jive_machine_init(void)
@@ -634,22 +635,22 @@
 
 	/* initialise the spi */
 
-	s3c2410_gpio_setpin(S3C2410_GPG13, 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPG(13), 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_OUTPUT);
 
-	s3c2410_gpio_setpin(S3C2410_GPB7, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPB7, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPB(7), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPB(7), S3C2410_GPIO_OUTPUT);
 
-	s3c2410_gpio_setpin(S3C2410_GPB6, 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPB6, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPB(6), 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT);
 
-	s3c2410_gpio_setpin(S3C2410_GPG8, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPG8, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPG(8), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPG(8), S3C2410_GPIO_OUTPUT);
 
 	/* initialise the WM8750 spi */
 
-	s3c2410_gpio_setpin(S3C2410_GPH10, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH10, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPH(10), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPH(10), S3C2410_GPIO_OUTPUT);
 
 	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -84,10 +85,10 @@
 	switch (cmd)
 	{
 		case S3C2410_UDC_P_ENABLE :
-			s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+			s3c2410_gpio_setpin(S3C2410_GPF(2), 1);
 			break;
 		case S3C2410_UDC_P_DISABLE :
-			s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+			s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
 			break;
 		case S3C2410_UDC_P_RESET :
 			break;
@@ -134,8 +135,8 @@
 {	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
 
-	s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT);
 
 	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
 			      S3C2410_MISCCR_USBSUSPND0 |
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/dma.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,14 +17,16 @@
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
 
+#include <mach/map.h>
 #include <mach/dma.h>
 
-#include <plat/dma.h>
+#include <plat/dma-plat.h>
 #include <plat/cpu.h>
 
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-ac97.h>
+#include <plat/regs-dma.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,7 @@
 	select PM_SIMTEC if PM
 	select HAVE_PATA_PLATFORM
 	select S3C24XX_GPIO_EXTRA64
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the Simtec Electronics ANUBIS
 	  development system
@@ -43,6 +44,7 @@
 	select S3C24XX_DCLK
 	select PM_SIMTEC if PM
 	select S3C24XX_GPIO_EXTRA128
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the Simtec IM2440D20 module, also
 	  known as the Osiris.
@@ -58,12 +60,14 @@
 	bool "SMDK2440"
 	select CPU_S3C2440
 	select MACH_SMDK
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the SMDK2440.
 
 config MACH_NEXCODER_2440
  	bool "NexVision NEXCODER 2440 Light Board"
  	select CPU_S3C2440
+	select S3C_DEV_USB_HOST
 	help
  	  Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
 
@@ -76,8 +80,19 @@
 config MACH_AT2440EVB
 	bool "Avantech AT2440EVB development board"
 	select CPU_S3C2440
+	select S3C_DEV_USB_HOST
 	help
 	  Say Y here if you are using the AT2440EVB development board
 
+config MACH_MINI2440
+	bool "MINI2440 development board"
+	select CPU_S3C2440
+	select EEPROM_AT24
+	select LEDS_TRIGGER_BACKLIGHT
+	select SND_S3C24XX_SOC_S3C24XX_UDA134X
+	help
+	  Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
+	  available via various sources. It can come with a 3.5" or 7" touch LCD.
+
 endmenu
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-anubis.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-anubis.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-anubis.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-anubis.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
@@ -468,7 +469,7 @@
 		anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
 	} else {
 		/* ensure that the GPIO is setup */
-		s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+		s3c2410_gpio_setpin(S3C2410_GPA(0), 1);
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-at2440evb.c	2009-09-09 18:13:59.000000000 -0400
@@ -166,7 +166,7 @@
 };
 
 static struct s3c24xx_mci_pdata at2440evb_mci_pdata = {
-	.gpio_detect	= S3C2410_GPG10,
+	.gpio_detect	= S3C2410_GPG(10),
 };
 
 /* 7" LCD panel */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-mini2440.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-mini2440.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,702 @@
+/* linux/arch/arm/mach-s3c2440/mach-mini2440.c
+ *
+ * Copyright (c) 2008 Ramax Lo <ramaxlo@gmail.com>
+ *      Based on mach-anubis.c by Ben Dooks <ben@simtec.co.uk>
+ *      and modifications by SBZ <sbz@spgui.org> and
+ *      Weibing <http://weibing.blogbus.com> and
+ *      Michel Pollet <buserror@gmail.com>
+ *
+ * For product information, visit http://code.google.com/p/mini2440/
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/serial_core.h>
+#include <linux/dm9000.h>
+#include <linux/i2c/at24.h>
+#include <linux/platform_device.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/mmc/host.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-gpio.h>
+#include <mach/leds-gpio.h>
+#include <mach/regs-mem.h>
+#include <mach/regs-lcd.h>
+#include <mach/irqs.h>
+#include <plat/nand.h>
+#include <plat/iic.h>
+#include <plat/mci.h>
+#include <plat/udc.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+#include <sound/s3c24xx_uda134x.h>
+
+#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)
+
+static struct map_desc mini2440_iodesc[] __initdata = {
+	/* nothing to declare, move along */
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+
+static struct s3c2410_uartcfg mini2440_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+};
+
+/* USB device UDC support */
+
+static void mini2440_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+	pr_debug("udc: pullup(%d)\n", cmd);
+
+	switch (cmd) {
+		case S3C2410_UDC_P_ENABLE :
+			s3c2410_gpio_setpin(S3C2410_GPC(5), 1);
+			break;
+		case S3C2410_UDC_P_DISABLE :
+			s3c2410_gpio_setpin(S3C2410_GPC(5), 0);
+			break;
+		case S3C2410_UDC_P_RESET :
+			break;
+		default:
+			break;
+	}
+}
+
+static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = {
+	.udc_command		= mini2440_udc_pullup,
+};
+
+
+/* LCD timing and setup */
+
+/*
+ * This macro simplifies the table bellow
+ */
+#define _LCD_DECLARE(_clock,_xres,margin_left,margin_right,hsync, \
+			_yres,margin_top,margin_bottom,vsync, refresh) \
+	.width = _xres, \
+	.xres = _xres, \
+	.height = _yres, \
+	.yres = _yres, \
+	.left_margin	= margin_left,	\
+	.right_margin	= margin_right,	\
+	.upper_margin	= margin_top,	\
+	.lower_margin	= margin_bottom,	\
+	.hsync_len	= hsync,	\
+	.vsync_len	= vsync,	\
+	.pixclock	= ((_clock*100000000000LL) /	\
+			   ((refresh) * \
+			   (hsync + margin_left + _xres + margin_right) * \
+			   (vsync + margin_top + _yres + margin_bottom))), \
+	.bpp		= 16,\
+	.type		= (S3C2410_LCDCON1_TFT16BPP |\
+			   S3C2410_LCDCON1_TFT)
+
+struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
+	[0] = {	/* mini2440 + 3.5" TFT + touchscreen */
+		_LCD_DECLARE(
+			7,			/* The 3.5 is quite fast */
+			240, 21, 38, 6, 	/* x timing */
+			320, 4, 4, 2,		/* y timing */
+			60),			/* refresh rate */
+		.lcdcon5	= (S3C2410_LCDCON5_FRM565 |
+				   S3C2410_LCDCON5_INVVLINE |
+				   S3C2410_LCDCON5_INVVFRAME |
+				   S3C2410_LCDCON5_INVVDEN |
+				   S3C2410_LCDCON5_PWREN),
+	},
+	[1] = { /* mini2440 + 7" TFT + touchscreen */
+		_LCD_DECLARE(
+			10,			/* the 7" runs slower */
+			800, 40, 40, 48, 	/* x timing */
+			480, 29, 3, 3,		/* y timing */
+			50),			/* refresh rate */
+		.lcdcon5	= (S3C2410_LCDCON5_FRM565 |
+				   S3C2410_LCDCON5_INVVLINE |
+				   S3C2410_LCDCON5_INVVFRAME |
+				   S3C2410_LCDCON5_PWREN),
+	},
+	/* The VGA shield can outout at several resolutions. All share 
+	 * the same timings, however, anything smaller than 1024x768
+	 * will only be displayed in the top left corner of a 1024x768
+	 * XGA output unless you add optional dip switches to the shield.
+	 * Therefore timings for other resolutions have been ommited here.
+	 */
+	[2] = {
+		_LCD_DECLARE(
+			10,
+			1024, 1, 2, 2,		/* y timing */
+			768, 200, 16, 16, 	/* x timing */
+			24),	/* refresh rate, maximum stable,
+				 tested with the FPGA shield */
+		.lcdcon5	= (S3C2410_LCDCON5_FRM565 |
+				   S3C2410_LCDCON5_HWSWP),
+	},
+};
+
+/* todo - put into gpio header */
+
+#define S3C2410_GPCCON_MASK(x)	(3 << ((x) * 2))
+#define S3C2410_GPDCON_MASK(x)	(3 << ((x) * 2))
+
+struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
+	.displays	 = &mini2440_lcd_cfg[0], /* not constant! see init */
+	.num_displays	 = 1,
+	.default_display = 0,
+
+	/* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN
+	 * and disable the pull down resistors on pins we are using for LCD
+	 * data. */
+
+	.gpcup		= (0xf << 1) | (0x3f << 10),
+
+	.gpccon		= (S3C2410_GPC1_VCLK   | S3C2410_GPC2_VLINE |
+			   S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM |
+			   S3C2410_GPC10_VD2   | S3C2410_GPC11_VD3 |
+			   S3C2410_GPC12_VD4   | S3C2410_GPC13_VD5 |
+			   S3C2410_GPC14_VD6   | S3C2410_GPC15_VD7),
+
+	.gpccon_mask	= (S3C2410_GPCCON_MASK(1)  | S3C2410_GPCCON_MASK(2)  |
+			   S3C2410_GPCCON_MASK(3)  | S3C2410_GPCCON_MASK(4)  |
+			   S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) |
+			   S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) |
+			   S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)),
+
+	.gpdup		= (0x3f << 2) | (0x3f << 10),
+
+	.gpdcon		= (S3C2410_GPD2_VD10  | S3C2410_GPD3_VD11 |
+			   S3C2410_GPD4_VD12  | S3C2410_GPD5_VD13 |
+			   S3C2410_GPD6_VD14  | S3C2410_GPD7_VD15 |
+			   S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 |
+			   S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 |
+			   S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23),
+
+	.gpdcon_mask	= (S3C2410_GPDCON_MASK(2)  | S3C2410_GPDCON_MASK(3) |
+			   S3C2410_GPDCON_MASK(4)  | S3C2410_GPDCON_MASK(5) |
+			   S3C2410_GPDCON_MASK(6)  | S3C2410_GPDCON_MASK(7) |
+			   S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)|
+			   S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)|
+			   S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)),
+};
+
+/* MMC/SD  */
+
+static struct s3c24xx_mci_pdata mini2440_mmc_cfg __initdata = {
+   .gpio_detect   = S3C2410_GPG(8),
+   .gpio_wprotect = S3C2410_GPH(8),
+   .set_power     = NULL,
+   .ocr_avail     = MMC_VDD_32_33|MMC_VDD_33_34,
+};
+
+/* NAND Flash on MINI2440 board */
+
+static struct mtd_partition mini2440_default_nand_part[] __initdata = {
+	[0] = {
+		.name	= "u-boot",
+		.size	= SZ_256K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "u-boot-env",
+		.size	= SZ_128K,
+		.offset	= SZ_256K,
+	},
+	[2] = {
+		.name	= "kernel",
+		/* 5 megabytes, for a kernel with no modules
+		 * or a uImage with a ramdisk attached */
+		.size	= 0x00500000,
+		.offset	= SZ_256K + SZ_128K,
+	},
+	[3] = {
+		.name	= "root",
+		.offset	= SZ_256K + SZ_128K + 0x00500000,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = {
+	[0] = {
+		.name		= "nand",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(mini2440_default_nand_part),
+		.partitions	= mini2440_default_nand_part,
+		.flash_bbt 	= 1, /* we use u-boot to create a BBT */
+	},
+};
+
+static struct s3c2410_platform_nand mini2440_nand_info __initdata = {
+	.tacls		= 0,
+	.twrph0		= 25,
+	.twrph1		= 15,
+	.nr_sets	= ARRAY_SIZE(mini2440_nand_sets),
+	.sets		= mini2440_nand_sets,
+	.ignore_unset_ecc = 1,
+};
+
+/* DM9000AEP 10/100 ethernet controller */
+
+static struct resource mini2440_dm9k_resource[] __initdata = {
+	[0] = {
+		.start = MACH_MINI2440_DM9K_BASE,
+		.end   = MACH_MINI2440_DM9K_BASE + 3,
+		.flags = IORESOURCE_MEM
+	},
+	[1] = {
+		.start = MACH_MINI2440_DM9K_BASE + 4,
+		.end   = MACH_MINI2440_DM9K_BASE + 7,
+		.flags = IORESOURCE_MEM
+	},
+	[2] = {
+		.start = IRQ_EINT7,
+		.end   = IRQ_EINT7,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+/*
+ * The DM9000 has no eeprom, and it's MAC address is set by
+ * the bootloader before starting the kernel.
+ */
+static struct dm9000_plat_data mini2440_dm9k_pdata __initdata = {
+	.flags		= (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+};
+
+static struct platform_device mini2440_device_eth __initdata = {
+	.name		= "dm9000",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(mini2440_dm9k_resource),
+	.resource	= mini2440_dm9k_resource,
+	.dev		= {
+		.platform_data	= &mini2440_dm9k_pdata,
+	},
+};
+
+/*  CON5
+ *	+--+	 /-----\
+ *	|  |    |	|
+ *	|  |	|  BAT	|
+ *	|  |	 \_____/
+ *	|  |
+ *	|  |  +----+  +----+
+ *	|  |  | K5 |  | K1 |
+ *	|  |  +----+  +----+
+ *	|  |  +----+  +----+
+ *	|  |  | K4 |  | K2 |
+ *	|  |  +----+  +----+
+ *	|  |  +----+  +----+
+ *	|  |  | K6 |  | K3 |
+ *	|  |  +----+  +----+
+ *	  .....
+ */
+static struct gpio_keys_button mini2440_buttons[] __initdata = {
+	{
+		.gpio		= S3C2410_GPG(0),		/* K1 */
+		.code		= KEY_F1,
+		.desc		= "Button 1",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= S3C2410_GPG(3),		/* K2 */
+		.code		= KEY_F2,
+		.desc		= "Button 2",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= S3C2410_GPG(5),		/* K3 */
+		.code		= KEY_F3,
+		.desc		= "Button 3",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= S3C2410_GPG(6),		/* K4 */
+		.code		= KEY_POWER,
+		.desc		= "Power",
+		.active_low	= 1,
+	},
+	{
+		.gpio		= S3C2410_GPG(7),		/* K5 */
+		.code		= KEY_F5,
+		.desc		= "Button 5",
+		.active_low	= 1,
+	},
+#if 0
+	/* this pin is also known as TCLK1 and seems to already
+	 * marked as "in use" somehow in the kernel -- possibly wrongly */
+	{
+		.gpio		= S3C2410_GPG(11),	/* K6 */
+		.code		= KEY_F6,
+		.desc		= "Button 6",
+		.active_low	= 1,
+	},
+#endif
+};
+
+static struct gpio_keys_platform_data mini2440_button_data __initdata = {
+	.buttons	= mini2440_buttons,
+	.nbuttons	= ARRAY_SIZE(mini2440_buttons),
+};
+
+static struct platform_device mini2440_button_device __initdata = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &mini2440_button_data,
+	}
+};
+
+/* LEDS */
+
+static struct s3c24xx_led_platdata mini2440_led1_pdata __initdata = {
+	.name		= "led1",
+	.gpio		= S3C2410_GPB(5),
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.def_trigger	= "heartbeat",
+};
+
+static struct s3c24xx_led_platdata mini2440_led2_pdata __initdata = {
+	.name		= "led2",
+	.gpio		= S3C2410_GPB(6),
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.def_trigger	= "nand-disk",
+};
+
+static struct s3c24xx_led_platdata mini2440_led3_pdata __initdata = {
+	.name		= "led3",
+	.gpio		= S3C2410_GPB(7),
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.def_trigger	= "mmc0",
+};
+
+static struct s3c24xx_led_platdata mini2440_led4_pdata __initdata = {
+	.name		= "led4",
+	.gpio		= S3C2410_GPB(8),
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.def_trigger	= "",
+};
+
+static struct s3c24xx_led_platdata mini2440_led_backlight_pdata __initdata = {
+	.name		= "backlight",
+	.gpio		= S3C2410_GPG(4),
+	.def_trigger	= "backlight",
+};
+
+static struct platform_device mini2440_led1 __initdata = {
+	.name		= "s3c24xx_led",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &mini2440_led1_pdata,
+	},
+};
+
+static struct platform_device mini2440_led2 __initdata = {
+	.name		= "s3c24xx_led",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &mini2440_led2_pdata,
+	},
+};
+
+static struct platform_device mini2440_led3 __initdata = {
+	.name		= "s3c24xx_led",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &mini2440_led3_pdata,
+	},
+};
+
+static struct platform_device mini2440_led4 __initdata = {
+	.name		= "s3c24xx_led",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &mini2440_led4_pdata,
+	},
+};
+
+static struct platform_device mini2440_led_backlight __initdata = {
+	.name		= "s3c24xx_led",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &mini2440_led_backlight_pdata,
+	},
+};
+
+/* AUDIO */
+
+static struct s3c24xx_uda134x_platform_data mini2440_audio_pins __initdata = {
+	.l3_clk = S3C2410_GPB(4),
+	.l3_mode = S3C2410_GPB(2),
+	.l3_data = S3C2410_GPB(3),
+	.model = UDA134X_UDA1341
+};
+
+static struct platform_device mini2440_audio __initdata = {
+	.name		= "s3c24xx_uda134x",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &mini2440_audio_pins,
+	},
+};
+
+/*
+ * I2C devices
+ */
+static struct at24_platform_data at24c08 = {
+	.byte_len	= SZ_8K / 8,
+	.page_size	= 16,
+};
+
+static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("24c08", 0x50),
+		.platform_data = &at24c08,
+	},
+};
+
+static struct platform_device *mini2440_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_wdt,
+/*	&s3c_device_adc,*/ /* ADC doesn't like living with touchscreen ! */
+	&s3c_device_i2c0,
+	&s3c_device_rtc,
+	&s3c_device_usbgadget,
+	&mini2440_device_eth,
+	&mini2440_led1,
+	&mini2440_led2,
+	&mini2440_led3,
+	&mini2440_led4,
+	&mini2440_button_device,
+	&s3c_device_nand,
+	&s3c_device_sdi,
+	&s3c_device_iis,
+	&mini2440_audio,
+/*	&s3c_device_timer[0],*/	/* buzzer pwm, no API for it */
+	/* remaining devices are optional */
+};
+
+static void __init mini2440_map_io(void)
+{
+	s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
+
+	s3c_device_nand.dev.platform_data = &mini2440_nand_info;
+	s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;
+}
+
+/*
+ * mini2440_features string
+ *
+ * t = Touchscreen present
+ * b = backlight control
+ * c = camera [TODO]
+ * 0-9 LCD configuration
+ *
+ */
+static char mini2440_features_str[12] __initdata = "0tb";
+
+static int __init mini2440_features_setup(char *str)
+{
+	if (str)
+		strlcpy(mini2440_features_str, str, sizeof(mini2440_features_str));
+	return 1;
+}
+
+__setup("mini2440=", mini2440_features_setup);
+
+#define FEATURE_SCREEN (1 << 0)
+#define FEATURE_BACKLIGHT (1 << 1)
+#define FEATURE_TOUCH (1 << 2)
+#define FEATURE_CAMERA (1 << 3)
+
+struct mini2440_features_t {
+	int count;
+	int done;
+	int lcd_index;
+	struct platform_device *optional[8];
+};
+
+static void mini2440_parse_features(
+		struct mini2440_features_t * features,
+		const char * features_str )
+{
+	const char * fp = features_str;
+
+	features->count = 0;
+	features->done = 0;
+	features->lcd_index = -1;
+
+	while (*fp) {
+		char f = *fp++;
+
+		switch (f) {
+		case '0'...'9':	/* tft screen */
+			if (features->done & FEATURE_SCREEN) {
+				printk(KERN_INFO "MINI2440: '%c' ignored, "
+					"screen type already set\n", f);
+			} else {
+				int li = f - '0';
+				if (li >= ARRAY_SIZE(mini2440_lcd_cfg))
+					printk(KERN_INFO "MINI2440: "
+						"'%c' out of range LCD mode\n", f);
+				else {
+					features->optional[features->count++] =
+							&s3c_device_lcd;
+					features->lcd_index = li;
+				}
+			}
+			features->done |= FEATURE_SCREEN;
+			break;
+		case 'b':
+			if (features->done & FEATURE_BACKLIGHT)
+				printk(KERN_INFO "MINI2440: '%c' ignored, "
+					"backlight already set\n", f);
+			else {
+				features->optional[features->count++] =
+						&mini2440_led_backlight;
+			}
+			features->done |= FEATURE_BACKLIGHT;
+			break;
+		case 't':
+			printk(KERN_INFO "MINI2440: '%c' ignored, "
+				"touchscreen not compiled in\n", f);
+			break;
+		case 'c':
+			if (features->done & FEATURE_CAMERA)
+				printk(KERN_INFO "MINI2440: '%c' ignored, "
+					"camera already registered\n", f);
+			else
+				features->optional[features->count++] =
+					&s3c_device_camif;
+			features->done |= FEATURE_CAMERA;
+			break;
+		}
+	}
+}
+
+static void __init mini2440_init(void)
+{
+	struct mini2440_features_t features = { 0 };
+	int i;
+
+	printk(KERN_INFO "MINI2440: Option string mini2440=%s\n",
+			mini2440_features_str);
+
+	/* Parse the feature string */
+	mini2440_parse_features(&features, mini2440_features_str);
+
+	/* turn LCD on */
+	s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
+
+	/* Turn the backlight early on */
+	s3c2410_gpio_setpin(S3C2410_GPG(4), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT);
+
+	/* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
+	s3c2410_gpio_pullup(S3C2410_GPB(1), 0);
+	s3c2410_gpio_setpin(S3C2410_GPB(1), 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT);
+
+	/* Make sure the D+ pullup pin is output */
+	s3c2410_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT);
+
+	/* mark the key as input, without pullups (there is one on the board) */
+	for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
+		s3c2410_gpio_pullup(mini2440_buttons[i].gpio, 0);
+		s3c2410_gpio_cfgpin(mini2440_buttons[i].gpio,
+					S3C2410_GPIO_INPUT);
+	}
+	if (features.lcd_index != -1) {
+		int li;
+
+		mini2440_fb_info.displays =
+			&mini2440_lcd_cfg[features.lcd_index];
+
+		printk(KERN_INFO "MINI2440: LCD");
+		for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++)
+			if (li == features.lcd_index)
+				printk(" [%d:%dx%d]", li,
+					mini2440_lcd_cfg[li].width,
+					mini2440_lcd_cfg[li].height);
+			else
+				printk(" %d:%dx%d", li,
+					mini2440_lcd_cfg[li].width,
+					mini2440_lcd_cfg[li].height);
+		printk("\n");
+		s3c24xx_fb_set_platdata(&mini2440_fb_info);
+	}
+	s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
+	s3c_i2c0_set_platdata(NULL);
+	i2c_register_board_info(0, mini2440_i2c_devs,
+				ARRAY_SIZE(mini2440_i2c_devs));
+
+	platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
+
+	if (features.count)	/* the optional features */
+		platform_add_devices(features.optional, features.count);
+
+}
+
+
+MACHINE_START(MINI2440, "MINI2440")
+	/* Maintainer: Michel Pollet <buserror@gmail.com> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= mini2440_map_io,
+	.init_machine	= mini2440_init,
+	.init_irq	= s3c24xx_init_irq,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-nexcoder.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/string.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
@@ -120,16 +121,16 @@
 static void __init nexcoder_sensorboard_init(void)
 {
 	// Initialize SCCB bus
-	s3c2410_gpio_setpin(S3C2410_GPE14, 1); // IICSCL
-	s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_OUTP);
-	s3c2410_gpio_setpin(S3C2410_GPE15, 1); // IICSDA
-	s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_OUTP);
+	s3c2410_gpio_setpin(S3C2410_GPE(14), 1); // IICSCL
+	s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_setpin(S3C2410_GPE(15), 1); // IICSDA
+	s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT);
 
 	// Power up the sensor board
-	s3c2410_gpio_setpin(S3C2410_GPF1, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPF1, S3C2410_GPF1_OUTP); // CAM_GPIO7 => nLDO_PWRDN
-	s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN
+	s3c2410_gpio_setpin(S3C2410_GPF(1), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPF(1), S3C2410_GPIO_OUTPUT); // CAM_GPIO7 => nLDO_PWRDN
+	s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
+	s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); // CAM_GPIO6 => CAM_PWRDN
 }
 
 static void __init nexcoder_map_io(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-osiris.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-osiris.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/mach-osiris.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/mach-osiris.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
@@ -291,8 +292,8 @@
 	__raw_writeb(tmp, OSIRIS_VA_CTRL0);
 
 	/* ensure that an nRESET is not generated on resume. */
-	s3c2410_gpio_setpin(S3C2410_GPA21, 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_OUT);
+	s3c2410_gpio_setpin(S3C2410_GPA(21), 1);
+	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT);
 
 	return 0;
 }
@@ -304,7 +305,7 @@
 
 	__raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);
 
-	s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_nRSTOUT);
+	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
 
 	return 0;
 }
@@ -384,7 +385,7 @@
 		osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
 	} else {
 		/* write-protect line to the NAND */
-		s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+		s3c2410_gpio_setpin(S3C2410_GPA(0), 1);
 	}
 
 	/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2440/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2440/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -22,3 +22,4 @@
 obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
 obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
+obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/include/mach/gta02.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/include/mach/gta02.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/include/mach/gta02.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/include/mach/gta02.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,84 @@
+#ifndef _GTA02_H
+#define _GTA02_H
+
+#include <mach/regs-gpio.h>
+
+/* Different hardware revisions, passed in ATAG_REVISION by u-boot */
+#define GTA02v1_SYSTEM_REV	0x00000310
+#define GTA02v2_SYSTEM_REV	0x00000320
+#define GTA02v3_SYSTEM_REV	0x00000330
+#define GTA02v4_SYSTEM_REV	0x00000340
+#define GTA02v5_SYSTEM_REV	0x00000350
+/* since A7 is basically same as A6, we use A6 PCB ID */
+#define GTA02v6_SYSTEM_REV	0x00000360
+
+#define GTA02_GPIO_n3DL_GSM	S3C2410_GPA(13)	/* v1 + v2 + v3 only */
+
+#define GTA02_GPIO_PWR_LED1	S3C2410_GPB(0)
+#define GTA02_GPIO_PWR_LED2	S3C2410_GPB(1)
+#define GTA02_GPIO_AUX_LED	S3C2410_GPB(2)
+#define GTA02_GPIO_VIBRATOR_ON	S3C2410_GPB(3)
+#define GTA02_GPIO_MODEM_RST	S3C2410_GPB(5)
+#define GTA02_GPIO_BT_EN	S3C2410_GPB(6)
+#define GTA02_GPIO_MODEM_ON	S3C2410_GPB(7)
+#define GTA02_GPIO_EXTINT8	S3C2410_GPB(8)
+#define GTA02_GPIO_USB_PULLUP	S3C2410_GPB(9)
+
+#define GTA02_GPIO_PIO5		S3C2410_GPC(5)	/* v3 + v4 only */
+
+#define GTA02v3_GPIO_nG1_CS	S3C2410_GPD(12)	/* v3 + v4 only */
+#define GTA02v3_GPIO_nG2_CS	S3C2410_GPD(13)	/* v3 + v4 only */
+#define GTA02v5_GPIO_HDQ	S3C2410_GPD(14)   /* v5 + */
+
+#define GTA02_GPIO_nG1_INT	S3C2410_GPF(0)
+#define GTA02_GPIO_IO1		S3C2410_GPF(1)
+#define GTA02_GPIO_PIO_2	S3C2410_GPF(2)	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_JACK_INSERT	S3C2410_GPF(4)
+#define GTA02_GPIO_WLAN_GPIO1	S3C2410_GPF(5)	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_AUX_KEY	S3C2410_GPF(6)
+#define GTA02_GPIO_HOLD_KEY	S3C2410_GPF(7)
+
+#define GTA02_GPIO_3D_IRQ	S3C2410_GPG(4)
+#define GTA02v2_GPIO_nG2_INT	S3C2410_GPG(8)	/* v2 + v3 + v4 only */
+#define GTA02v3_GPIO_nUSB_OC	S3C2410_GPG(9)	/* v3 + v4 only */
+#define GTA02v3_GPIO_nUSB_FLT	S3C2410_GPG(10)	/* v3 + v4 only */
+#define GTA02v3_GPIO_nGSM_OC	S3C2410_GPG(11)	/* v3 + v4 only */
+
+#define GTA02_GPIO_AMP_SHUT	S3C2440_GPJ1	/* v2 + v3 + v4 only */
+#define GTA02v1_GPIO_WLAN_GPIO10	S3C2440_GPJ2
+#define GTA02_GPIO_HP_IN	S3C2440_GPJ2	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_INT0		S3C2440_GPJ3	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_nGSM_EN	S3C2440_GPJ4
+#define GTA02_GPIO_3D_RESET	S3C2440_GPJ5
+#define GTA02_GPIO_nDL_GSM	S3C2440_GPJ6	/* v4 + v5 only */
+#define GTA02_GPIO_WLAN_GPIO0	S3C2440_GPJ7
+#define GTA02v1_GPIO_BAT_ID	S3C2440_GPJ8
+#define GTA02_GPIO_KEEPACT	S3C2440_GPJ8
+#define GTA02v1_GPIO_HP_IN	S3C2440_GPJ10
+#define GTA02_CHIP_PWD		S3C2440_GPJ11	/* v2 + v3 + v4 only */
+#define GTA02_GPIO_nWLAN_RESET	S3C2440_GPJ12	/* v2 + v3 + v4 only */
+
+#define GTA02_IRQ_GSENSOR_1	IRQ_EINT0
+#define GTA02_IRQ_MODEM		IRQ_EINT1
+#define GTA02_IRQ_PIO_2		IRQ_EINT2	/* v2 + v3 + v4 only */
+#define GTA02_IRQ_nJACK_INSERT	IRQ_EINT4
+#define GTA02_IRQ_WLAN_GPIO1	IRQ_EINT5
+#define GTA02_IRQ_AUX		IRQ_EINT6
+#define GTA02_IRQ_nHOLD		IRQ_EINT7
+#define GTA02_IRQ_PCF50633	IRQ_EINT9
+#define GTA02_IRQ_3D		IRQ_EINT12
+#define GTA02_IRQ_GSENSOR_2	IRQ_EINT16	/* v2 + v3 + v4 only */
+#define GTA02v3_IRQ_nUSB_OC	IRQ_EINT17	/* v3 + v4 only */
+#define GTA02v3_IRQ_nUSB_FLT	IRQ_EINT18	/* v3 + v4 only */
+#define GTA02v3_IRQ_nGSM_OC	IRQ_EINT19	/* v3 + v4 only */
+
+/* returns 00 000 on GTA02 A5 and earlier, A6 returns 01 001 */
+#define GTA02_PCB_ID1_0		S3C2410_GPC(13)
+#define GTA02_PCB_ID1_1		S3C2410_GPC(15)
+#define GTA02_PCB_ID1_2		S3C2410_GPD(0)
+#define GTA02_PCB_ID2_0		S3C2410_GPD(3)
+#define GTA02_PCB_ID2_1		S3C2410_GPD(4)
+
+int gta02_get_pcb_revision(void);
+
+#endif /* _GTA02_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,18 @@
 	depends on ARCH_S3C2440
 	select CPU_S3C2442
 
+config MACH_NEO1973_GTA02
+	bool "Openmoko GTA02 / Freerunner phone"
+	select CPU_S3C2442
+	select MFD_PCF50633
+	select PCF50633_GPIO
+	select I2C
+	select POWER_SUPPLY
+	select MACH_NEO1973
+	select S3C2410_PWM
+	help
+	   Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone
+
 
 endmenu
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/mach-gta02.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/mach-gta02.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/mach-gta02.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/mach-gta02.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,645 @@
+/*
+ * linux/arch/arm/mach-s3c2442/mach-gta02.c
+ *
+ * S3C2442 Machine Support for Openmoko GTA02 / FreeRunner.
+ *
+ * Copyright (C) 2006-2009 by Openmoko, Inc.
+ * Authors: Harald Welte <laforge@openmoko.org>
+ *          Andy Green <andy@openmoko.org>
+ *          Werner Almesberger <werner@openmoko.org>
+ * All rights reserved.
+ *
+ * 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/spi/spi.h>
+
+#include <linux/mmc/host.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/mbc.h>
+#include <linux/mfd/pcf50633/adc.h>
+#include <linux/mfd/pcf50633/gpio.h>
+#include <linux/mfd/pcf50633/pmic.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-gpioj.h>
+#include <mach/fb.h>
+
+#include <mach/spi.h>
+#include <mach/spi-gpio.h>
+#include <plat/usb-control.h>
+#include <mach/regs-mem.h>
+#include <mach/hardware.h>
+
+#include <mach/gta02.h>
+
+#include <plat/regs-serial.h>
+#include <plat/nand.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/udc.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+
+static struct pcf50633 *gta02_pcf;
+
+/*
+ * This gets called every 1ms when we paniced.
+ */
+
+static long gta02_panic_blink(long count)
+{
+	long delay = 0;
+	static long last_blink;
+	static char led;
+
+	/* Fast blink: 200ms period. */
+	if (count - last_blink < 100)
+		return 0;
+
+	led ^= 1;
+	gpio_direction_output(GTA02_GPIO_AUX_LED, led);
+
+	last_blink = count;
+
+	return delay;
+}
+
+
+static struct map_desc gta02_iodesc[] __initdata = {
+	{
+		.virtual	= 0xe0000000,
+		.pfn		= __phys_to_pfn(S3C2410_CS3 + 0x01000000),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	},
+};
+
+#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg gta02_uartcfgs[] = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+};
+
+#ifdef CONFIG_CHARGER_PCF50633
+/*
+ * On GTA02 the 1A charger features a 48K resistor to 0V on the ID pin.
+ * We use this to recognize that we can pull 1A from the USB socket.
+ *
+ * These constants are the measured pcf50633 ADC levels with the 1A
+ * charger / 48K resistor, and with no pulldown resistor.
+ */
+
+#define ADC_NOM_CHG_DETECT_1A 6
+#define ADC_NOM_CHG_DETECT_USB 43
+
+static void
+gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
+{
+	int  ma;
+
+	/* Interpret charger type */
+	if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {
+
+		/*
+		 * Sanity - stop GPO driving out now that we have a 1A charger
+		 * GPO controls USB Host power generation on GTA02
+		 */
+		pcf50633_gpio_set(pcf, PCF50633_GPO, 0);
+
+		ma = 1000;
+	} else
+		ma = 100;
+
+	pcf50633_mbc_usb_curlim_set(pcf, ma);
+}
+
+static struct delayed_work gta02_charger_work;
+static int gta02_usb_vbus_draw;
+
+static void gta02_charger_worker(struct work_struct *work)
+{
+	if (gta02_usb_vbus_draw) {
+		pcf50633_mbc_usb_curlim_set(gta02_pcf, gta02_usb_vbus_draw);
+		return;
+	}
+
+#ifdef CONFIG_PCF50633_ADC
+	pcf50633_adc_async_read(gta02_pcf,
+				PCF50633_ADCC1_MUX_ADCIN1,
+				PCF50633_ADCC1_AVERAGE_16,
+				gta02_configure_pmu_for_charger,
+				NULL);
+#else
+	/*
+	 * If the PCF50633 ADC is disabled we fallback to a
+	 * 100mA limit for safety.
+	 */
+	pcf50633_mbc_usb_curlim_set(pcf, 100);
+#endif
+}
+
+#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)
+
+static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
+{
+	if (irq == PCF50633_IRQ_USBINS) {
+		schedule_delayed_work(&gta02_charger_work,
+				      GTA02_CHARGER_CONFIGURE_TIMEOUT);
+
+		return;
+	}
+
+	if (irq == PCF50633_IRQ_USBREM) {
+		cancel_delayed_work_sync(&gta02_charger_work);
+		gta02_usb_vbus_draw = 0;
+	}
+}
+
+static void gta02_udc_vbus_draw(unsigned int ma)
+{
+	if (!gta02_pcf)
+		return;
+
+	gta02_usb_vbus_draw = ma;
+
+	schedule_delayed_work(&gta02_charger_work,
+			      GTA02_CHARGER_CONFIGURE_TIMEOUT);
+}
+#else /* !CONFIG_CHARGER_PCF50633 */
+#define gta02_pmu_event_callback	NULL
+#define gta02_udc_vbus_draw		NULL
+#endif
+
+/*
+ * This is called when pc50633 is probed, unfortunately quite late in the
+ * day since it is an I2C bus device. Here we can belatedly define some
+ * platform devices with the advantage that we can mark the pcf50633 as the
+ * parent. This makes them get suspended and resumed with their parent
+ * the pcf50633 still around.
+ */
+
+static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf);
+
+
+static char *gta02_batteries[] = {
+	"battery",
+};
+
+struct pcf50633_platform_data gta02_pcf_pdata = {
+	.resumers = {
+		[0] =	PCF50633_INT1_USBINS |
+			PCF50633_INT1_USBREM |
+			PCF50633_INT1_ALARM,
+		[1] =	PCF50633_INT2_ONKEYF,
+		[2] =	PCF50633_INT3_ONKEY1S,
+		[3] =	PCF50633_INT4_LOWSYS |
+			PCF50633_INT4_LOWBAT |
+			PCF50633_INT4_HIGHTMP,
+	},
+
+	.batteries = gta02_batteries,
+	.num_batteries = ARRAY_SIZE(gta02_batteries),
+	.reg_init_data = {
+		[PCF50633_REGULATOR_AUTO] = {
+			.constraints = {
+				.min_uV = 3300000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.always_on = 1,
+				.apply_uV = 1,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_DOWN1] = {
+			.constraints = {
+				.min_uV = 1300000,
+				.max_uV = 1600000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.always_on = 1,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_DOWN2] = {
+			.constraints = {
+				.min_uV = 1800000,
+				.max_uV = 1800000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+				.always_on = 1,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_HCLDO] = {
+			.constraints = {
+				.min_uV = 2000000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+				.always_on = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO1] = {
+			.constraints = {
+				.min_uV = 3300000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+				.state_mem = {
+					.enabled = 0,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_LDO2] = {
+			.constraints = {
+				.min_uV = 3300000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO3] = {
+			.constraints = {
+				.min_uV = 3000000,
+				.max_uV = 3000000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO4] = {
+			.constraints = {
+				.min_uV = 3200000,
+				.max_uV = 3200000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO5] = {
+			.constraints = {
+				.min_uV = 3000000,
+				.max_uV = 3000000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_LDO6] = {
+			.constraints = {
+				.min_uV = 3000000,
+				.max_uV = 3000000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+			},
+		},
+		[PCF50633_REGULATOR_MEMLDO] = {
+			.constraints = {
+				.min_uV = 1800000,
+				.max_uV = 1800000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+
+	},
+	.probe_done = gta02_pmu_attach_child_devices,
+	.mbc_event_callback = gta02_pmu_event_callback,
+};
+
+
+/* NOR Flash. */
+
+#define GTA02_FLASH_BASE	0x18000000 /* GCS3 */
+#define GTA02_FLASH_SIZE	0x200000 /* 2MBytes */
+
+static struct physmap_flash_data gta02_nor_flash_data = {
+	.width		= 2,
+};
+
+static struct resource gta02_nor_flash_resource = {
+	.start		= GTA02_FLASH_BASE,
+	.end		= GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gta02_nor_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &gta02_nor_flash_data,
+	},
+	.resource	= &gta02_nor_flash_resource,
+	.num_resources	= 1,
+};
+
+
+struct platform_device s3c24xx_pwm_device = {
+	.name		= "s3c24xx_pwm",
+	.num_resources	= 0,
+};
+
+static struct i2c_board_info gta02_i2c_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("pcf50633", 0x73),
+		.irq = GTA02_IRQ_PCF50633,
+		.platform_data = &gta02_pcf_pdata,
+	},
+	{
+		I2C_BOARD_INFO("wm8753", 0x1a),
+	},
+};
+
+static struct s3c2410_nand_set gta02_nand_sets[] = {
+	[0] = {
+		/*
+		 * This name is also hard-coded in the boot loaders, so
+		 * changing it would would require all users to upgrade
+		 * their boot loaders, some of which are stored in a NOR
+		 * that is considered to be immutable.
+		 */
+		.name		= "neo1973-nand",
+		.nr_chips	= 1,
+		.flash_bbt	= 1,
+	},
+};
+
+/*
+ * Choose a set of timings derived from S3C@2442B MCP54
+ * data sheet (K5D2G13ACM-D075 MCP Memory).
+ */
+
+static struct s3c2410_platform_nand gta02_nand_info = {
+	.tacls		= 0,
+	.twrph0		= 25,
+	.twrph1		= 15,
+	.nr_sets	= ARRAY_SIZE(gta02_nand_sets),
+	.sets		= gta02_nand_sets,
+};
+
+
+static void gta02_udc_command(enum s3c2410_udc_cmd_e cmd)
+{
+	switch (cmd) {
+	case S3C2410_UDC_P_ENABLE:
+		pr_debug("%s S3C2410_UDC_P_ENABLE\n", __func__);
+		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 1);
+		break;
+	case S3C2410_UDC_P_DISABLE:
+		pr_debug("%s S3C2410_UDC_P_DISABLE\n", __func__);
+		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 0);
+		break;
+	case S3C2410_UDC_P_RESET:
+		pr_debug("%s S3C2410_UDC_P_RESET\n", __func__);
+		/* FIXME: Do something here. */
+	}
+}
+
+/* Get PMU to set USB current limit accordingly. */
+static struct s3c2410_udc_mach_info gta02_udc_cfg = {
+	.vbus_draw	= gta02_udc_vbus_draw,
+	.udc_command	= gta02_udc_command,
+
+};
+
+
+
+static void gta02_bl_set_intensity(int intensity)
+{
+	struct pcf50633 *pcf = gta02_pcf;
+	int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
+
+	/* We map 8-bit intensity to 6-bit intensity in hardware. */
+	intensity >>= 2;
+
+	/*
+	 * This can happen during, eg, print of panic on blanked console,
+	 * but we can't service i2c without interrupts active, so abort.
+	 */
+	if (in_atomic()) {
+		printk(KERN_ERR "gta02_bl_set_intensity called while atomic\n");
+		return;
+	}
+
+	old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
+	if (intensity == old_intensity)
+		return;
+
+	/* We can't do this anywhere else. */
+	pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5);
+
+	if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3))
+		old_intensity = 0;
+
+	/*
+	 * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
+	 * if seen, you have to re-enable the LED unit.
+	 */
+	if (!intensity || !old_intensity)
+		pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0);
+
+	/* Illegal to set LEDOUT to 0. */
+	if (!intensity)
+		pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 2);
+	else
+		pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
+					  intensity);
+
+	if (intensity)
+		pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2);
+
+}
+
+static struct generic_bl_info gta02_bl_info = {
+	.name			= "gta02-bl",
+	.max_intensity		= 0xff,
+	.default_intensity	= 0xff,
+	.set_bl_intensity	= gta02_bl_set_intensity,
+};
+
+static struct platform_device gta02_bl_dev = {
+	.name			= "generic-bl",
+	.id			= 1,
+	.dev = {
+		.platform_data = &gta02_bl_info,
+	},
+};
+
+
+
+/* USB */
+static struct s3c2410_hcd_info gta02_usb_info = {
+	.port[0]	= {
+		.flags	= S3C_HCDFLG_USED,
+	},
+	.port[1]	= {
+		.flags	= 0,
+	},
+};
+
+
+static void __init gta02_map_io(void)
+{
+	s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
+}
+
+
+/* These are the guys that don't need to be children of PMU. */
+
+static struct platform_device *gta02_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_wdt,
+	&s3c_device_sdi,
+	&s3c_device_usbgadget,
+	&s3c_device_nand,
+	&gta02_nor_flash,
+	&s3c24xx_pwm_device,
+	&s3c_device_iis,
+	&s3c_device_i2c0,
+};
+
+/* These guys DO need to be children of PMU. */
+
+static struct platform_device *gta02_devices_pmu_children[] = {
+	&gta02_bl_dev,
+};
+
+
+/*
+ * This is called when pc50633 is probed, quite late in the day since it is an
+ * I2C bus device.  Here we can define platform devices with the advantage that
+ * we can mark the pcf50633 as the parent.  This makes them get suspended and
+ * resumed with their parent the pcf50633 still around.  All devices whose
+ * operation depends on something from pcf50633 must have this relationship
+ * made explicit like this, or suspend and resume will become an unreliable
+ * hellworld.
+ */
+
+static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf)
+{
+	int n;
+
+	/* Grab a copy of the now probed PMU pointer. */
+	gta02_pcf = pcf;
+
+	for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++)
+		gta02_devices_pmu_children[n]->dev.parent = pcf->dev;
+
+	platform_add_devices(gta02_devices_pmu_children,
+			     ARRAY_SIZE(gta02_devices_pmu_children));
+}
+
+static void gta02_poweroff(void)
+{
+	pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1);
+}
+
+static void __init gta02_machine_init(void)
+{
+	/* Set the panic callback to make AUX LED blink at ~5Hz. */
+	panic_blink = gta02_panic_blink;
+
+	s3c_pm_init();
+
+#ifdef CONFIG_CHARGER_PCF50633
+	INIT_DELAYED_WORK(&gta02_charger_work, gta02_charger_worker);
+#endif
+
+	s3c_device_usb.dev.platform_data = &gta02_usb_info;
+	s3c_device_nand.dev.platform_data = &gta02_nand_info;
+
+	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
+	s3c_i2c0_set_platdata(NULL);
+
+	i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
+
+	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
+	pm_power_off = gta02_poweroff;
+}
+
+
+MACHINE_START(NEO1973_GTA02, "GTA02")
+	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= gta02_map_io,
+	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= gta02_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2442/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2442/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -12,5 +12,7 @@
 obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
 obj-$(CONFIG_CPU_S3C2442)	+= clock.o
 
+obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
+
 # Machine support
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c2443/dma.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c2443/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c2443/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c2443/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,12 +20,13 @@
 
 #include <mach/dma.h>
 
-#include <plat/dma.h>
+#include <plat/dma-plat.h>
 #include <plat/cpu.h>
 
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-ac97.h>
+#include <plat/regs-dma.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/dma.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/dma.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,63 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-/* currently nothing here, placeholder */
+#define S3C_DMA_CHANNELS	(16)
+
+/* see mach-s3c2410/dma.h for notes on dma channel numbers */
+
+/* Note, for the S3C64XX architecture we keep the DMACH_
+ * defines in the order they are allocated to [S]DMA0/[S]DMA1
+ * so that is easy to do DHACH_ -> DMA controller conversion
+ */
+enum dma_ch {
+	/* DMA0/SDMA0 */
+	DMACH_UART0 = 0,
+	DMACH_UART0_SRC2,
+	DMACH_UART1,
+	DMACH_UART1_SRC2,
+	DMACH_UART2,
+	DMACH_UART2_SRC2,
+	DMACH_UART3,
+	DMACH_UART3_SRC2,
+	DMACH_PCM0_TX,
+	DMACH_PCM0_RX,
+	DMACH_I2S0_OUT,
+	DMACH_I2S0_IN,
+	DMACH_SPI0_TX,
+	DMACH_SPI0_RX,
+	DMACH_HSI_I2SV40_TX,
+	DMACH_HSI_I2SV40_RX,
+
+	/* DMA1/SDMA1 */
+	DMACH_PCM1_TX = 16,
+	DMACH_PCM1_RX,
+	DMACH_I2S1_OUT,
+	DMACH_I2S1_IN,
+	DMACH_SPI1_TX,
+	DMACH_SPI1_RX,
+	DMACH_AC97_PCMOUT,
+	DMACH_AC97_PCMIN,
+	DMACH_AC97_MICIN,
+	DMACH_PWM,
+	DMACH_IRDA,
+	DMACH_EXTERNAL,
+	DMACH_RES1,
+	DMACH_RES2,
+	DMACH_SECURITY_RX,	/* SDMA1 only */
+	DMACH_SECURITY_TX,	/* SDMA1 only */
+	DMACH_MAX		/* the end */
+};
+
+static __inline__ int s3c_dma_has_circular(void)
+{
+	/* we will be supporting ciruclar buffers as soon as we have DMA
+	 * engine support.
+	 */
+	return 1;
+}
+
+#define S3C2410_DMAF_CIRCULAR		(1 << 0)
+
+#include <plat/dma.h>
 
 #endif /* __ASM_ARCH_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/map.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/map.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/map.h	2009-09-09 18:13:59.000000000 -0400
@@ -39,6 +39,8 @@
 #define S3C_VA_UART3		S3C_VA_UARTx(3)
 
 #define S3C64XX_PA_FB		(0x77100000)
+#define S3C64XX_PA_USB_HSOTG	(0x7C000000)
+#define S3C64XX_PA_WATCHDOG	(0x7E004000)
 #define S3C64XX_PA_SYSCON	(0x7E00F000)
 #define S3C64XX_PA_IIS0		(0x7F002000)
 #define S3C64XX_PA_IIS1		(0x7F003000)
@@ -57,6 +59,8 @@
 #define S3C64XX_PA_MODEM	(0x74108000)
 #define S3C64XX_VA_MODEM	S3C_ADDR(0x00600000)
 
+#define S3C64XX_PA_USBHOST	(0x74300000)
+
 /* place VICs close together */
 #define S3C_VA_VIC0		(S3C_VA_IRQ + 0x00)
 #define S3C_VA_VIC1		(S3C_VA_IRQ + 0x10000)
@@ -69,5 +73,7 @@
 #define S3C_PA_IIC		S3C64XX_PA_IIC0
 #define S3C_PA_IIC1		S3C64XX_PA_IIC1
 #define S3C_PA_FB		S3C64XX_PA_FB
+#define S3C_PA_USBHOST		S3C64XX_PA_USBHOST
+#define S3C_PA_USB_HSOTG	S3C64XX_PA_USB_HSOTG
 
 #endif /* __ASM_ARCH_6400_MAP_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/regs-clock.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/regs-clock.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/regs-clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,16 @@
+/* linux/arch/arm/mach-s3c6400/include/mach/regs-clock.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - clock register compatibility with s3c24xx
+ *
+ * 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.
+*/
+
+#include <plat/regs-clock.h>
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/system.h linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/system.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/include/mach/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/include/mach/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H __FILE__
 
+#include <plat/watchdog-reset.h>
+
 static void arch_idle(void)
 {
 	/* nothing here yet */
@@ -18,7 +20,11 @@
 
 static void arch_reset(char mode, const char *cmd)
 {
-	/* nothing here yet */
+	if (mode != 's')
+		arch_wdt_reset();
+
+	/* if all else fails, or mode was for soft, jump to 0 */
+	cpu_reset(0);
 }
 
 #endif /* __ASM_ARCH_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -5,4 +5,27 @@
 #
 # Licensed under GPLv2
 
-# Currently nothing here, this will be added later
+# Configuration options for the S3C6410 CPU
+
+config CPU_S3C6400
+	bool
+	select CPU_S3C6400_INIT
+	select CPU_S3C6400_CLOCK
+	help
+	  Enable S3C6400 CPU support
+
+config S3C6400_SETUP_SDHCI
+	bool
+	help
+	  Internal configuration for default SDHCI
+	  setup for S3C6400.
+
+# S36400 Macchine support
+
+config MACH_SMDK6400
+       bool "SMDK6400"
+	select CPU_S3C6400
+	select S3C_DEV_HSMMC
+	select S3C6400_SETUP_SDHCI
+	help
+	  Machine support for the Samsung SMDK6400
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/mach-smdk6400.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/mach-smdk6400.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/mach-smdk6400.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/mach-smdk6400.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,96 @@
+/* linux/arch/arm/mach-s3c6400/mach-smdk6400.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+
+#include <plat/s3c6400.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk6400_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+};
+
+static struct map_desc smdk6400_iodesc[] = {};
+
+static void __init smdk6400_map_io(void)
+{
+	s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
+}
+
+static struct platform_device *smdk6400_devices[] __initdata = {
+	&s3c_device_hsmmc1,
+	&s3c_device_i2c0,
+};
+
+static struct i2c_board_info i2c_devs[] __initdata = {
+	{ I2C_BOARD_INFO("wm8753", 0x1A), },
+	{ I2C_BOARD_INFO("24c08", 0x50), },
+};
+
+static void __init smdk6400_machine_init(void)
+{
+	i2c_register_board_info(0, i2c_devs, ARRAY_SIZE(i2c_devs));
+	platform_add_devices(smdk6400_devices, ARRAY_SIZE(smdk6400_devices));
+}
+
+MACHINE_START(SMDK6400, "SMDK6400")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+
+	.init_irq	= s3c6400_init_irq,
+	.map_io		= smdk6400_map_io,
+	.init_machine	= smdk6400_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -12,4 +12,12 @@
 
 # Core support for S3C6400 system
 
-obj-n				+= blank.o
+obj-$(CONFIG_CPU_S3C6400)	+= s3c6400.o
+
+# setup support
+
+obj-$(CONFIG_S3C6400_SETUP_SDHCI) += setup-sdhci.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK6400)	+= mach-smdk6400.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/s3c6400.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/s3c6400.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/s3c6400.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/s3c6400.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,89 @@
+/* linux/arch/arm/mach-s3c6410/cpu.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/sdhci.h>
+#include <plat/iic-core.h>
+#include <plat/s3c6400.h>
+
+void __init s3c6400_map_io(void)
+{
+	/* setup SDHCI */
+
+	s3c6400_default_sdhci0();
+	s3c6400_default_sdhci1();
+
+	/* the i2c devices are directly compatible with s3c2440 */
+	s3c_i2c0_setname("s3c2440-i2c");
+}
+
+void __init s3c6400_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
+	s3c24xx_register_baseclocks(xtal);
+	s3c64xx_register_clocks();
+	s3c6400_register_clocks(S3C6400_CLKDIV0_ARM_MASK);
+	s3c6400_setup_clocks();
+}
+
+void __init s3c6400_init_irq(void)
+{
+	/* VIC0 does not have IRQS 5..7,
+	 * VIC1 is fully populated. */
+	s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
+}
+
+struct sysdev_class s3c6400_sysclass = {
+	.name	= "s3c6400-core",
+};
+
+static struct sys_device s3c6400_sysdev = {
+	.cls	= &s3c6400_sysclass,
+};
+
+static int __init s3c6400_core_init(void)
+{
+	return sysdev_class_register(&s3c6400_sysclass);
+}
+
+core_initcall(s3c6400_core_init);
+
+int __init s3c6400_init(void)
+{
+	printk("S3C6400: Initialising architecture\n");
+
+	return sysdev_register(&s3c6400_sysdev);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/setup-sdhci.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/setup-sdhci.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6400/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6400/setup-sdhci.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,63 @@
+/* linux/arch/arm/mach-s3c6410/setup-sdhci.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC)
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
+
+/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
+
+char *s3c6400_hsmmc_clksrcs[4] = {
+	[0] = "hsmmc",
+	[1] = "hsmmc",
+	[2] = "mmc_bus",
+	/* [3] = "48m", - note not succesfully used yet */
+};
+
+void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
+				  void __iomem *r,
+				  struct mmc_ios *ios,
+				  struct mmc_card *card)
+{
+	u32 ctrl2, ctrl3;
+
+	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
+	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
+		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
+		  S3C_SDHCI_CTRL2_ENFBCLKRX |
+		  S3C_SDHCI_CTRL2_DFCNT_NONE |
+		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
+
+	if (ios->clock < 25 * 1000000)
+		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
+			 S3C_SDHCI_CTRL3_FCSEL2 |
+			 S3C_SDHCI_CTRL3_FCSEL1 |
+			 S3C_SDHCI_CTRL3_FCSEL0);
+	else
+		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
+
+	printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
+	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
+	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/cpu.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/cpu.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/cpu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/cpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,7 @@
 
 #include <plat/cpu-freq.h>
 #include <plat/regs-serial.h>
+#include <plat/regs-clock.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -68,7 +69,7 @@
 	printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
 	s3c24xx_register_baseclocks(xtal);
 	s3c64xx_register_clocks();
-	s3c6400_register_clocks();
+	s3c6400_register_clocks(S3C6410_CLKDIV0_ARM_MASK);
 	s3c6400_setup_clocks();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -16,9 +16,18 @@
 
 config S3C6410_SETUP_SDHCI
 	bool
+	select S3C64XX_SETUP_SDHCI_GPIO
 	help
 	  Internal helper functions for S3C6410 based SDHCI systems
 
+config MACH_ANW6410
+	bool "A&W6410"
+	select CPU_S3C6410
+	select S3C_DEV_FB
+	select S3C64XX_SETUP_FB_24BPP
+	help
+	  Machine support for the A&W6410
+
 config MACH_SMDK6410
 	bool "SMDK6410"
 	select CPU_S3C6410
@@ -26,6 +35,8 @@
 	select S3C_DEV_HSMMC1
 	select S3C_DEV_I2C1
 	select S3C_DEV_FB
+	select S3C_DEV_USB_HOST
+	select S3C_DEV_USB_HSOTG
 	select S3C6410_SETUP_SDHCI
 	select S3C64XX_SETUP_I2C1
 	select S3C64XX_SETUP_FB_24BPP
@@ -60,3 +71,29 @@
 	  channels 0 and 1 are the same.
 
 endchoice
+
+config SMDK6410_WM1190_EV1
+	bool "Support Wolfson Microelectronics 1190-EV1 PMIC card"
+	depends on MACH_SMDK6410
+	select REGULATOR
+	select REGULATOR_WM8350
+	select MFD_WM8350_I2C
+	select MFD_WM8350_CONFIG_MODE_0
+	select MFD_WM8350_CONFIG_MODE_3
+	select MFD_WM8352_CONFIG_MODE_0
+	help
+	  The Wolfson Microelectronics 1190-EV1 is a WM835x based PMIC
+	  and audio daughtercard for the Samsung SMDK6410 reference
+	  platform.  Enabling this option will build support for this
+	  module into the kernel.  The presence of the module will be
+	  detected at runtime so the the resulting kernel can be used
+	  with or without the 1190-EV1 fitted.
+
+config MACH_NCP
+	bool "NCP"
+	select CPU_S3C6410
+	select S3C_DEV_I2C1
+	select S3C_DEV_HSMMC1
+	select S3C64XX_SETUP_I2C1
+	help
+          Machine support for the Samsung NCP
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/mach-anw6410.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/mach-anw6410.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/mach-anw6410.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/mach-anw6410.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,245 @@
+/* linux/arch/arm/mach-s3c6410/mach-anw6410.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ * Copyright 2009 Kwangwoo Lee
+ * 	Kwangwoo Lee <kwangwoo.lee@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/dm9000.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+
+#include <plat/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/regs-gpio.h>
+#include <plat/regs-modem.h>
+
+/* DM9000 */
+#define ANW6410_PA_DM9000	(0x18000000)
+
+/* A hardware buffer to control external devices is mapped at 0x30000000.
+ * It can not be read. So current status must be kept in anw6410_extdev_status.
+ */
+#define ANW6410_VA_EXTDEV	S3C_ADDR(0x02000000)
+#define ANW6410_PA_EXTDEV	(0x30000000)
+
+#define ANW6410_EN_DM9000	(1<<11)
+#define ANW6410_EN_LCD		(1<<14)
+
+static __u32 anw6410_extdev_status;
+
+static struct s3c2410_uartcfg anw6410_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+};
+
+/* framebuffer and LCD setup. */
+static void __init anw6410_lcd_mode_set(void)
+{
+	u32 tmp;
+
+	/* set the LCD type */
+	tmp = __raw_readl(S3C64XX_SPCON);
+	tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
+	tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
+	__raw_writel(tmp, S3C64XX_SPCON);
+
+	/* remove the LCD bypass */
+	tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
+	tmp &= ~MIFPCON_LCD_BYPASS;
+	__raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
+}
+
+/* GPF1 = LCD panel power
+ * GPF4 = LCD backlight control
+ */
+static void anw6410_lcd_power_set(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+		anw6410_extdev_status |= (ANW6410_EN_LCD << 16);
+		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+
+		gpio_direction_output(S3C64XX_GPF(1), 1);
+		gpio_direction_output(S3C64XX_GPF(4), 1);
+	} else {
+		anw6410_extdev_status &= ~(ANW6410_EN_LCD << 16);
+		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+
+		gpio_direction_output(S3C64XX_GPF(1), 0);
+		gpio_direction_output(S3C64XX_GPF(4), 0);
+	}
+}
+
+static struct plat_lcd_data anw6410_lcd_power_data = {
+	.set_power	= anw6410_lcd_power_set,
+};
+
+static struct platform_device anw6410_lcd_powerdev = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &anw6410_lcd_power_data,
+};
+
+static struct s3c_fb_pd_win anw6410_fb_win0 = {
+	/* this is to ensure we use win0 */
+	.win_mode	= {
+		.pixclock	= 41094,
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 16,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = {
+	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
+	.win[0]		= &anw6410_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/* DM9000AEP 10/100 ethernet controller */
+static void __init anw6410_dm9000_enable(void)
+{
+	anw6410_extdev_status |= (ANW6410_EN_DM9000 << 16);
+	__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+}
+
+static struct resource anw6410_dm9000_resource[] = {
+	[0] = {
+		.start = ANW6410_PA_DM9000,
+		.end   = ANW6410_PA_DM9000 + 3,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = ANW6410_PA_DM9000 + 4,
+		.end   = ANW6410_PA_DM9000 + 4 + 500,
+		.flags = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start = IRQ_EINT(15),
+		.end   = IRQ_EINT(15),
+		.flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+	},
+};
+
+static struct dm9000_plat_data anw6410_dm9000_pdata = {
+	.flags	  = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+	/* dev_addr can be set to provide hwaddr. */
+};
+
+static struct platform_device anw6410_device_eth = {
+	.name	= "dm9000",
+	.id	= -1,
+	.num_resources	= ARRAY_SIZE(anw6410_dm9000_resource),
+	.resource	= anw6410_dm9000_resource,
+	.dev	= {
+		.platform_data  = &anw6410_dm9000_pdata,
+	},
+};
+
+static struct map_desc anw6410_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)ANW6410_VA_EXTDEV,
+		.pfn		= __phys_to_pfn(ANW6410_PA_EXTDEV),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct platform_device *anw6410_devices[] __initdata = {
+	&s3c_device_fb,
+	&anw6410_lcd_powerdev,
+	&anw6410_device_eth,
+};
+
+static void __init anw6410_map_io(void)
+{
+	s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
+
+	anw6410_lcd_mode_set();
+}
+
+static void __init anw6410_machine_init(void)
+{
+	s3c_fb_set_platdata(&anw6410_lcd_pdata);
+
+	gpio_request(S3C64XX_GPF(1), "panel power");
+	gpio_request(S3C64XX_GPF(4), "LCD backlight");
+
+	anw6410_dm9000_enable();
+
+	platform_add_devices(anw6410_devices, ARRAY_SIZE(anw6410_devices));
+}
+
+MACHINE_START(ANW6410, "A&W6410")
+	/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+
+	.init_irq	= s3c6410_init_irq,
+	.map_io		= anw6410_map_io,
+	.init_machine	= anw6410_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/mach-ncp.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/mach-ncp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/mach-ncp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/mach-ncp.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,107 @@
+/*
+ * linux/arch/arm/mach-s3c6410/mach-ncp.c
+ *
+ * Copyright (C) 2008-2009 Samsung Electronics
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+
+#include <plat/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg ncp_uartcfgs[] __initdata = {
+	/* REVISIT: NCP uses only serial 1, 2 */
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+};
+
+static struct platform_device *ncp_devices[] __initdata = {
+	&s3c_device_hsmmc1,
+	&s3c_device_i2c0,
+};
+
+struct map_desc ncp_iodesc[] = {};
+
+static void __init ncp_map_io(void)
+{
+	s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
+}
+
+static void __init ncp_machine_init(void)
+{
+	s3c_i2c0_set_platdata(NULL);
+
+	platform_add_devices(ncp_devices, ARRAY_SIZE(ncp_devices));
+}
+
+MACHINE_START(NCP, "NCP")
+	/* Maintainer: Samsung Electronics */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.init_irq	= s3c6410_init_irq,
+	.map_io		= ncp_map_io,
+	.init_machine	= ncp_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/mach-smdk6410.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/mach-smdk6410.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/mach-smdk6410.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/mach-smdk6410.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,12 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/smsc911x.h>
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#endif
 
 #include <video/platform_lcd.h>
 
@@ -39,8 +45,12 @@
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
+#include <plat/regs-modem.h>
+#include <plat/regs-gpio.h>
+#include <plat/regs-sys.h>
 #include <plat/iic.h>
 #include <plat/fb.h>
+#include <plat/gpio-cfg.h>
 
 #include <plat/s3c6410.h>
 #include <plat/clock.h>
@@ -129,6 +139,37 @@
 	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
 };
 
+static struct resource smdk6410_smsc911x_resources[] = {
+	[0] = {
+		.start = 0x18000000,
+		.end   = 0x18000000 + SZ_64K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = S3C_EINT(10),
+		.end   = S3C_EINT(10),
+		.flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_LOW,
+	},
+};
+
+static struct smsc911x_platform_config smdk6410_smsc911x_pdata = {
+	.irq_polarity  = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type      = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags         = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+
+static struct platform_device smdk6410_smsc911x = {
+	.name          = "smsc911x",
+	.id            = -1,
+	.num_resources = ARRAY_SIZE(smdk6410_smsc911x_resources),
+	.resource      = &smdk6410_smsc911x_resources[0],
+	.dev = {
+		.platform_data = &smdk6410_smsc911x_pdata,
+	},
+};
+
 static struct map_desc smdk6410_iodesc[] = {};
 
 static struct platform_device *smdk6410_devices[] __initdata = {
@@ -141,12 +182,155 @@
 	&s3c_device_i2c0,
 	&s3c_device_i2c1,
 	&s3c_device_fb,
+	&s3c_device_usb,
+	&s3c_device_usb_hsotg,
 	&smdk6410_lcd_powerdev,
+
+	&smdk6410_smsc911x,
+};
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+/* S3C64xx internal logic & PLL */
+static struct regulator_init_data wm8350_dcdc1_data = {
+	.constraints = {
+		.name = "PVDD_INT/PVDD_PLL",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.always_on = 1,
+		.apply_uV = 1,
+	},
+};
+
+/* Memory */
+static struct regulator_init_data wm8350_dcdc3_data = {
+	.constraints = {
+		.name = "PVDD_MEM",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.always_on = 1,
+		.state_mem = {
+			 .uV = 1800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.initial_state = PM_SUSPEND_MEM,
+	},
+};
+
+/* USB, EXT, PCM, ADC/DAC, USB, MMC */
+static struct regulator_init_data wm8350_dcdc4_data = {
+	.constraints = {
+		.name = "PVDD_HI/PVDD_EXT/PVDD_SYS/PVCCM2MTV",
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.always_on = 1,
+	},
+};
+
+/* ARM core */
+static struct regulator_consumer_supply dcdc6_consumers[] = {
+	{
+		.supply = "vddarm",
+	}
+};
+
+static struct regulator_init_data wm8350_dcdc6_data = {
+	.constraints = {
+		.name = "PVDD_ARM",
+		.min_uV = 1000000,
+		.max_uV = 1300000,
+		.always_on = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(dcdc6_consumers),
+	.consumer_supplies = dcdc6_consumers,
+};
+
+/* Alive */
+static struct regulator_init_data wm8350_ldo1_data = {
+	.constraints = {
+		.name = "PVDD_ALIVE",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.always_on = 1,
+		.apply_uV = 1,
+	},
+};
+
+/* OTG */
+static struct regulator_init_data wm8350_ldo2_data = {
+	.constraints = {
+		.name = "PVDD_OTG",
+		.min_uV = 3300000,
+		.max_uV = 3300000,
+		.always_on = 1,
+	},
+};
+
+/* LCD */
+static struct regulator_init_data wm8350_ldo3_data = {
+	.constraints = {
+		.name = "PVDD_LCD",
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.always_on = 1,
+	},
 };
 
+/* OTGi/1190-EV1 HPVDD & AVDD */
+static struct regulator_init_data wm8350_ldo4_data = {
+	.constraints = {
+		.name = "PVDD_OTGI/HPVDD/AVDD",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.apply_uV = 1,
+		.always_on = 1,
+	},
+};
+
+static struct {
+	int regulator;
+	struct regulator_init_data *initdata;
+} wm1190_regulators[] = {
+	{ WM8350_DCDC_1, &wm8350_dcdc1_data },
+	{ WM8350_DCDC_3, &wm8350_dcdc3_data },
+	{ WM8350_DCDC_4, &wm8350_dcdc4_data },
+	{ WM8350_DCDC_6, &wm8350_dcdc6_data },
+	{ WM8350_LDO_1, &wm8350_ldo1_data },
+	{ WM8350_LDO_2, &wm8350_ldo2_data },
+	{ WM8350_LDO_3, &wm8350_ldo3_data },
+	{ WM8350_LDO_4, &wm8350_ldo4_data },
+};
+
+static int __init smdk6410_wm8350_init(struct wm8350 *wm8350)
+{
+	int i;
+
+	/* Instantiate the regulators */
+	for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
+		wm8350_register_regulator(wm8350,
+					  wm1190_regulators[i].regulator,
+					  wm1190_regulators[i].initdata);
+
+	return 0;
+}
+
+static struct wm8350_platform_data __initdata smdk6410_wm8350_pdata = {
+	.init = smdk6410_wm8350_init,
+	.irq_high = 1,
+};
+#endif
+
 static struct i2c_board_info i2c_devs0[] __initdata = {
 	{ I2C_BOARD_INFO("24c08", 0x50), },
 	{ I2C_BOARD_INFO("wm8580", 0x1b), },
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+	{ I2C_BOARD_INFO("wm8350", 0x1a),
+	  .platform_data = &smdk6410_wm8350_pdata,
+	  .irq = S3C_EINT(12),
+	},
+#endif
 };
 
 static struct i2c_board_info i2c_devs1[] __initdata = {
@@ -155,9 +339,23 @@
 
 static void __init smdk6410_map_io(void)
 {
+	u32 tmp;
+
 	s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
+
+	/* set the LCD type */
+
+	tmp = __raw_readl(S3C64XX_SPCON);
+	tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
+	tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
+	__raw_writel(tmp, S3C64XX_SPCON);
+
+	/* remove the lcd bypass */
+	tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
+	tmp &= ~MIFPCON_LCD_BYPASS;
+	__raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
 }
 
 static void __init smdk6410_machine_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -20,4 +20,8 @@
 
 # machine support
 
+obj-$(CONFIG_MACH_ANW6410)	+= mach-anw6410.o
 obj-$(CONFIG_MACH_SMDK6410)	+= mach-smdk6410.o
+obj-$(CONFIG_MACH_NCP)		+= mach-ncp.o
+
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/setup-sdhci.c linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/setup-sdhci.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-s3c6410/setup-sdhci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-s3c6410/setup-sdhci.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,8 +21,6 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
-#include <mach/gpio.h>
-#include <plat/gpio-cfg.h>
 #include <plat/regs-sdhci.h>
 #include <plat/sdhci.h>
 
@@ -35,22 +33,6 @@
 	/* [3] = "48m", - note not succesfully used yet */
 };
 
-void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-	unsigned int gpio;
-	unsigned int end;
-
-	end = S3C64XX_GPG(2 + width);
-
-	/* Set all the necessary GPG pins to special-function 0 */
-	for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-	}
-
-	s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
-	s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
-}
 
 void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
 				    void __iomem *r,
@@ -84,19 +66,3 @@
 	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
 }
 
-void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-	unsigned int gpio;
-	unsigned int end;
-
-	end = S3C64XX_GPH(2 + width);
-
-	/* Set all the necessary GPG pins to special-function 0 */
-	for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-	}
-
-	s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
-	s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
-}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-sa1100/collie_pm.c linux-libre-2.6.31-gnu/arch/arm/mach-sa1100/collie_pm.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-sa1100/collie_pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-sa1100/collie_pm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,296 +0,0 @@
-/*
- * Based on spitz_pm.c and sharp code.
- *
- * Copyright (C) 2001  SHARP
- * Copyright 2005 Pavel Machek <pavel@suse.cz>
- *
- * Distribute under GPLv2.
- *
- * Li-ion batteries are angry beasts, and they like to explode. This driver is not finished,
- * and sometimes charges them when it should not. If it makes angry lithium to come your way...
- * ...well, you have been warned.
- *
- * Actually, this should be quite safe, it seems sharp leaves charger enabled by default,
- * and my collie did not explode (yet).
- */
-
-#include <linux/module.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/hardware/scoop.h>
-#include <mach/dma.h>
-#include <mach/collie.h>
-#include <asm/mach/sharpsl_param.h>
-#include <asm/hardware/sharpsl_pm.h>
-
-#include "../drivers/mfd/ucb1x00.h"
-
-static struct ucb1x00 *ucb;
-static int ad_revise;
-
-#define ADCtoPower(x)	       ((330 * x * 2) / 1024)
-
-static void collie_charger_init(void)
-{
-	int err;
-
-	if (sharpsl_param.adadj != -1)
-		ad_revise = sharpsl_param.adadj;
-
-	/* Register interrupt handler. */
-	if ((err = request_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr, IRQF_DISABLED,
-			       "ACIN", sharpsl_ac_isr))) {
-		printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_AC_IN);
-		return;
-	}
-	if ((err = request_irq(COLLIE_IRQ_GPIO_CO, sharpsl_chrg_full_isr, IRQF_DISABLED,
-			       "CO", sharpsl_chrg_full_isr))) {
-		free_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr);
-		printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_CO);
-		return;
-	}
-
-	gpio_request(COLLIE_GPIO_CHARGE_ON, "charge on");
-	gpio_direction_output(COLLIE_GPIO_CHARGE_ON, 1);
-
-	ucb1x00_io_set_dir(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON | COLLIE_TC35143_GPIO_TMP_ON |
-			           COLLIE_TC35143_GPIO_BBAT_ON);
-	return;
-}
-
-static void collie_measure_temp(int on)
-{
-	if (on)
-		ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
-	else
-		ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
-}
-
-static void collie_charge(int on)
-{
-	/* Zaurus seems to contain LTC1731; it should know when to
-	 * stop charging itself, so setting charge on should be
-	 * relatively harmless (as long as it is not done too often).
-	 */
-	gpio_set_value(COLLIE_GPIO_CHARGE_ON, on);
-}
-
-static void collie_discharge(int on)
-{
-}
-
-static void collie_discharge1(int on)
-{
-}
-
-static void collie_presuspend(void)
-{
-}
-
-static void collie_postsuspend(void)
-{
-}
-
-static int collie_should_wakeup(unsigned int resume_on_alarm)
-{
-	return 0;
-}
-
-static unsigned long collie_charger_wakeup(void)
-{
-	return 0;
-}
-
-int collie_read_backup_battery(void)
-{
-	int voltage;
-
-	ucb1x00_adc_enable(ucb);
-
-	ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_BBAT_ON, 0);
-	voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
-
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
-	ucb1x00_adc_disable(ucb);
-
-	printk("Backup battery = %d(%d)\n", ADCtoPower(voltage), voltage);
-
-	return ADCtoPower(voltage);
-}
-
-int collie_read_main_battery(void)
-{
-	int voltage, voltage_rev, voltage_volts;
-
-	ucb1x00_adc_enable(ucb);
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
-	ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_MBAT_ON, 0);
-
-	mdelay(1);
-	voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
-
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON);
-	ucb1x00_adc_disable(ucb);
-
-	voltage_rev = voltage + ((ad_revise * voltage) / 652);
-	voltage_volts = ADCtoPower(voltage_rev);
-
-	printk("Main battery = %d(%d)\n", voltage_volts, voltage);
-
-	if (voltage != -1)
-		return voltage_volts;
-	else
-		return voltage;
-}
-
-int collie_read_temp(void)
-{
-	int voltage;
-
-	/* According to Sharp, temp must be > 973, main battery must be < 465,
-	   FIXME: sharpsl_pm.c has both conditions negated? FIXME: values
-	   are way out of range? */
-
-	ucb1x00_adc_enable(ucb);
-	ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
-	/* >1010 = battery removed, 460 = 22C ?, higher = lower temp ? */
-	voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD0, UCB_SYNC);
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
-	ucb1x00_adc_disable(ucb);
-
-	printk("Battery temp = %d\n", voltage);
-	return voltage;
-}
-
-static unsigned long read_devdata(int which)
-{
-	switch (which) {
-	case SHARPSL_BATT_VOLT:
-		return collie_read_main_battery();
-	case SHARPSL_BATT_TEMP:
-		return collie_read_temp();
-	case SHARPSL_ACIN_VOLT:
-		return 500;
-	case SHARPSL_STATUS_ACIN: {
-		int ret = GPLR & COLLIE_GPIO_AC_IN;
-		printk("AC status = %d\n", ret);
-		return ret;
-	}
-	case SHARPSL_STATUS_FATAL: {
-		int ret = GPLR & COLLIE_GPIO_MAIN_BAT_LOW;
-		printk("Fatal bat = %d\n", ret);
-		return ret;
-	}
-	default:
-		return ~0;
-	}
-}
-
-struct battery_thresh collie_battery_levels_acin[] = {
-	{ 420, 100},
-	{ 417,  95},
-	{ 415,  90},
-	{ 413,  80},
-	{ 411,  75},
-	{ 408,  70},
-	{ 406,  60},
-	{ 403,  50},
-	{ 398,  40},
-	{ 391,  25},
-	{  10,   5},
-	{   0,   0},
-};
-
-struct battery_thresh collie_battery_levels[] = {
-	{ 394, 100},
-	{ 390,  95},
-	{ 380,  90},
-	{ 370,  80},
-	{ 368,  75},	/* From sharp code: battery high with frontlight */
-	{ 366,  70},	/* 60..90 -- fake values invented by me for testing */
-	{ 364,  60},
-	{ 362,  50},
-	{ 360,  40},
-	{ 358,  25},	/* From sharp code: battery low with frontlight */
-	{ 356,   5},	/* From sharp code: battery verylow with frontlight */
-	{   0,   0},
-};
-
-struct sharpsl_charger_machinfo collie_pm_machinfo = {
-	.init             = collie_charger_init,
-	.read_devdata	  = read_devdata,
-	.discharge        = collie_discharge,
-	.discharge1       = collie_discharge1,
-	.charge           = collie_charge,
-	.measure_temp     = collie_measure_temp,
-	.presuspend       = collie_presuspend,
-	.postsuspend      = collie_postsuspend,
-	.charger_wakeup   = collie_charger_wakeup,
-	.should_wakeup    = collie_should_wakeup,
-	.bat_levels       = 12,
-	.bat_levels_noac  = collie_battery_levels,
-	.bat_levels_acin  = collie_battery_levels_acin,
-	.status_high_acin = 368,
-	.status_low_acin  = 358,
-	.status_high_noac = 368,
-	.status_low_noac  = 358,
-	.charge_on_volt	  = 350,	/* spitz uses 2.90V, but lets play it safe. */
-	.charge_on_temp   = 550,
-	.charge_acin_high = 550,	/* collie does not seem to have sensor for this, anyway */
-	.charge_acin_low  = 450,	/* ignored, too */
-	.fatal_acin_volt  = 356,
-	.fatal_noacin_volt = 356,
-
-	.batfull_irq = 1,		/* We do not want periodical charge restarts */
-};
-
-static int __init collie_pm_ucb_add(struct ucb1x00_dev *pdev)
-{
-	sharpsl_pm.machinfo = &collie_pm_machinfo;
-	ucb = pdev->ucb;
-	return 0;
-}
-
-static struct ucb1x00_driver collie_pm_ucb_driver = {
-	.add	= collie_pm_ucb_add,
-};
-
-static struct platform_device *collie_pm_device;
-
-static int __init collie_pm_init(void)
-{
-	int ret;
-
-	collie_pm_device = platform_device_alloc("sharpsl-pm", -1);
-	if (!collie_pm_device)
-		return -ENOMEM;
-
-	collie_pm_device->dev.platform_data = &collie_pm_machinfo;
-	ret = platform_device_add(collie_pm_device);
-
-	if (ret)
-		platform_device_put(collie_pm_device);
-
-	if (!ret)
-		ret = ucb1x00_register_driver(&collie_pm_ucb_driver);
-
-	return ret;
-}
-
-static void __exit collie_pm_exit(void)
-{
-	ucb1x00_unregister_driver(&collie_pm_ucb_driver);
-	platform_device_unregister(collie_pm_device);
-}
-
-module_init(collie_pm_init);
-module_exit(collie_pm_exit);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-sa1100/jornada720_ssp.c linux-libre-2.6.31-gnu/arch/arm/mach-sa1100/jornada720_ssp.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-sa1100/jornada720_ssp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-sa1100/jornada720_ssp.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,7 +54,7 @@
  * timeout after <timeout> rounds. Needs mcu running before its called.
  *
  * returns : %mcu output on success
- *	   : %-ETIMEOUT on timeout
+ *	   : %-ETIMEDOUT on timeout
  */
 int jornada_ssp_byte(u8 byte)
 {
@@ -82,7 +82,7 @@
  * jornada_ssp_inout - decide if input is command or trading byte
  *
  * returns : (jornada_ssp_byte(byte)) on success
- *         : %-ETIMEOUT on timeout failure
+ *         : %-ETIMEDOUT on timeout failure
  */
 int jornada_ssp_inout(u8 byte)
 {
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/entry-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/entry-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/entry-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,35 @@
+/*
+ * Low-level IRQ helper macros for Freescale STMP378X
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	        mov	\base, #0xf0000000	@ vm address of IRQ controller
+		ldr	\irqnr, [\base, #0x70]	@ HW_ICOLL_STAT
+		cmp	\irqnr, #0x7f
+		moveqs	\irqnr, #0		@ Zero flag set for no IRQ
+
+		.endm
+
+                .macro  get_irqnr_preamble, base, tmp
+                .endm
+
+                .macro  arch_ret_to_user, tmp1, tmp2
+                .endm
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * Freescale STMP378X interrupts
+ *
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#define IRQ_DEBUG_UART			0
+#define IRQ_COMMS_RX			1
+#define IRQ_COMMS_TX			1
+#define IRQ_SSP2_ERROR			2
+#define IRQ_VDD5V			3
+#define IRQ_HEADPHONE_SHORT		4
+#define IRQ_DAC_DMA			5
+#define IRQ_DAC_ERROR			6
+#define IRQ_ADC_DMA			7
+#define IRQ_ADC_ERROR			8
+#define IRQ_SPDIF_DMA			9
+#define IRQ_SAIF2_DMA			9
+#define IRQ_SPDIF_ERROR			10
+#define IRQ_SAIF1_IRQ			10
+#define IRQ_SAIF2_IRQ			10
+#define IRQ_USB_CTRL			11
+#define IRQ_USB_WAKEUP			12
+#define IRQ_GPMI_DMA			13
+#define IRQ_SSP1_DMA			14
+#define IRQ_SSP_ERROR			15
+#define IRQ_GPIO0			16
+#define IRQ_GPIO1			17
+#define IRQ_GPIO2			18
+#define IRQ_SAIF1_DMA			19
+#define IRQ_SSP2_DMA			20
+#define IRQ_ECC8_IRQ			21
+#define IRQ_RTC_ALARM			22
+#define IRQ_UARTAPP_TX_DMA		23
+#define IRQ_UARTAPP_INTERNAL		24
+#define IRQ_UARTAPP_RX_DMA		25
+#define IRQ_I2C_DMA			26
+#define IRQ_I2C_ERROR			27
+#define IRQ_TIMER0			28
+#define IRQ_TIMER1			29
+#define IRQ_TIMER2			30
+#define IRQ_TIMER3			31
+#define IRQ_BATT_BRNOUT			32
+#define IRQ_VDDD_BRNOUT			33
+#define IRQ_VDDIO_BRNOUT		34
+#define IRQ_VDD18_BRNOUT		35
+#define IRQ_TOUCH_DETECT		36
+#define IRQ_LRADC_CH0			37
+#define IRQ_LRADC_CH1			38
+#define IRQ_LRADC_CH2			39
+#define IRQ_LRADC_CH3			40
+#define IRQ_LRADC_CH4			41
+#define IRQ_LRADC_CH5			42
+#define IRQ_LRADC_CH6			43
+#define IRQ_LRADC_CH7			44
+#define IRQ_LCDIF_DMA			45
+#define IRQ_LCDIF_ERROR			46
+#define IRQ_DIGCTL_DEBUG_TRAP		47
+#define IRQ_RTC_1MSEC			48
+#define IRQ_DRI_DMA			49
+#define IRQ_DRI_ATTENTION		50
+#define IRQ_GPMI_ATTENTION		51
+#define IRQ_IR				52
+#define IRQ_DCP_VMI			53
+#define IRQ_DCP				54
+#define IRQ_BCH				56
+#define IRQ_PXP				57
+#define IRQ_UARTAPP2_TX_DMA		58
+#define IRQ_UARTAPP2_INTERNAL		59
+#define IRQ_UARTAPP2_RX_DMA		60
+#define IRQ_VDAC_DETECT			61
+#define IRQ_VDD5V_DROOP			64
+#define IRQ_DCDC4P2_BO			65
+
+
+#define NR_REAL_IRQS	128
+#define NR_IRQS		(NR_REAL_IRQS + 32 * 3)
+
+/* All interrupts are FIQ capable */
+#define FIQ_START		IRQ_DEBUG_UART
+
+/* Hard disk IRQ is a GPMI attention IRQ */
+#define IRQ_HARDDISK		IRQ_GPMI_ATTENTION
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/pins.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/pins.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/pins.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/pins.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,151 @@
+/*
+ * Freescale STMP378X SoC pin multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_PINS_H
+#define __ASM_ARCH_PINS_H
+
+/*
+ * Define all STMP378x pins, a pin name corresponds to a STMP378x hardware
+ * interface  this pin belongs to.
+ */
+
+/* Bank 0 */
+#define PINID_GPMI_D00		STMP3XXX_PINID(0, 0)
+#define PINID_GPMI_D01		STMP3XXX_PINID(0, 1)
+#define PINID_GPMI_D02		STMP3XXX_PINID(0, 2)
+#define PINID_GPMI_D03		STMP3XXX_PINID(0, 3)
+#define PINID_GPMI_D04		STMP3XXX_PINID(0, 4)
+#define PINID_GPMI_D05		STMP3XXX_PINID(0, 5)
+#define PINID_GPMI_D06		STMP3XXX_PINID(0, 6)
+#define PINID_GPMI_D07		STMP3XXX_PINID(0, 7)
+#define PINID_GPMI_D08		STMP3XXX_PINID(0, 8)
+#define PINID_GPMI_D09		STMP3XXX_PINID(0, 9)
+#define PINID_GPMI_D10		STMP3XXX_PINID(0, 10)
+#define PINID_GPMI_D11		STMP3XXX_PINID(0, 11)
+#define PINID_GPMI_D12		STMP3XXX_PINID(0, 12)
+#define PINID_GPMI_D13		STMP3XXX_PINID(0, 13)
+#define PINID_GPMI_D14		STMP3XXX_PINID(0, 14)
+#define PINID_GPMI_D15		STMP3XXX_PINID(0, 15)
+#define PINID_GPMI_CLE		STMP3XXX_PINID(0, 16)
+#define PINID_GPMI_ALE		STMP3XXX_PINID(0, 17)
+#define PINID_GMPI_CE2N		STMP3XXX_PINID(0, 18)
+#define PINID_GPMI_RDY0		STMP3XXX_PINID(0, 19)
+#define PINID_GPMI_RDY1		STMP3XXX_PINID(0, 20)
+#define PINID_GPMI_RDY2		STMP3XXX_PINID(0, 21)
+#define PINID_GPMI_RDY3		STMP3XXX_PINID(0, 22)
+#define PINID_GPMI_WPN		STMP3XXX_PINID(0, 23)
+#define PINID_GPMI_WRN		STMP3XXX_PINID(0, 24)
+#define PINID_GPMI_RDN		STMP3XXX_PINID(0, 25)
+#define PINID_AUART1_CTS	STMP3XXX_PINID(0, 26)
+#define PINID_AUART1_RTS	STMP3XXX_PINID(0, 27)
+#define PINID_AUART1_RX		STMP3XXX_PINID(0, 28)
+#define PINID_AUART1_TX		STMP3XXX_PINID(0, 29)
+#define PINID_I2C_SCL		STMP3XXX_PINID(0, 30)
+#define PINID_I2C_SDA		STMP3XXX_PINID(0, 31)
+
+/* Bank 1 */
+#define PINID_LCD_D00		STMP3XXX_PINID(1, 0)
+#define PINID_LCD_D01		STMP3XXX_PINID(1, 1)
+#define PINID_LCD_D02		STMP3XXX_PINID(1, 2)
+#define PINID_LCD_D03		STMP3XXX_PINID(1, 3)
+#define PINID_LCD_D04		STMP3XXX_PINID(1, 4)
+#define PINID_LCD_D05		STMP3XXX_PINID(1, 5)
+#define PINID_LCD_D06		STMP3XXX_PINID(1, 6)
+#define PINID_LCD_D07		STMP3XXX_PINID(1, 7)
+#define PINID_LCD_D08		STMP3XXX_PINID(1, 8)
+#define PINID_LCD_D09		STMP3XXX_PINID(1, 9)
+#define PINID_LCD_D10		STMP3XXX_PINID(1, 10)
+#define PINID_LCD_D11		STMP3XXX_PINID(1, 11)
+#define PINID_LCD_D12		STMP3XXX_PINID(1, 12)
+#define PINID_LCD_D13		STMP3XXX_PINID(1, 13)
+#define PINID_LCD_D14		STMP3XXX_PINID(1, 14)
+#define PINID_LCD_D15		STMP3XXX_PINID(1, 15)
+#define PINID_LCD_D16		STMP3XXX_PINID(1, 16)
+#define PINID_LCD_D17		STMP3XXX_PINID(1, 17)
+#define PINID_LCD_RESET		STMP3XXX_PINID(1, 18)
+#define PINID_LCD_RS		STMP3XXX_PINID(1, 19)
+#define PINID_LCD_WR		STMP3XXX_PINID(1, 20)
+#define PINID_LCD_CS		STMP3XXX_PINID(1, 21)
+#define PINID_LCD_DOTCK		STMP3XXX_PINID(1, 22)
+#define PINID_LCD_ENABLE	STMP3XXX_PINID(1, 23)
+#define PINID_LCD_HSYNC		STMP3XXX_PINID(1, 24)
+#define PINID_LCD_VSYNC		STMP3XXX_PINID(1, 25)
+#define PINID_PWM0		STMP3XXX_PINID(1, 26)
+#define PINID_PWM1		STMP3XXX_PINID(1, 27)
+#define PINID_PWM2		STMP3XXX_PINID(1, 28)
+#define PINID_PWM3		STMP3XXX_PINID(1, 29)
+#define PINID_PWM4		STMP3XXX_PINID(1, 30)
+
+/* Bank 2 */
+#define PINID_SSP1_CMD		STMP3XXX_PINID(2, 0)
+#define PINID_SSP1_DETECT	STMP3XXX_PINID(2, 1)
+#define PINID_SSP1_DATA0	STMP3XXX_PINID(2, 2)
+#define PINID_SSP1_DATA1	STMP3XXX_PINID(2, 3)
+#define PINID_SSP1_DATA2	STMP3XXX_PINID(2, 4)
+#define PINID_SSP1_DATA3	STMP3XXX_PINID(2, 5)
+#define PINID_SSP1_SCK		STMP3XXX_PINID(2, 6)
+#define PINID_ROTARYA		STMP3XXX_PINID(2, 7)
+#define PINID_ROTARYB		STMP3XXX_PINID(2, 8)
+#define PINID_EMI_A00		STMP3XXX_PINID(2, 9)
+#define PINID_EMI_A01		STMP3XXX_PINID(2, 10)
+#define PINID_EMI_A02		STMP3XXX_PINID(2, 11)
+#define PINID_EMI_A03		STMP3XXX_PINID(2, 12)
+#define PINID_EMI_A04		STMP3XXX_PINID(2, 13)
+#define PINID_EMI_A05		STMP3XXX_PINID(2, 14)
+#define PINID_EMI_A06		STMP3XXX_PINID(2, 15)
+#define PINID_EMI_A07		STMP3XXX_PINID(2, 16)
+#define PINID_EMI_A08		STMP3XXX_PINID(2, 17)
+#define PINID_EMI_A09		STMP3XXX_PINID(2, 18)
+#define PINID_EMI_A10		STMP3XXX_PINID(2, 19)
+#define PINID_EMI_A11		STMP3XXX_PINID(2, 20)
+#define PINID_EMI_A12		STMP3XXX_PINID(2, 21)
+#define PINID_EMI_BA0		STMP3XXX_PINID(2, 22)
+#define PINID_EMI_BA1		STMP3XXX_PINID(2, 23)
+#define PINID_EMI_CASN		STMP3XXX_PINID(2, 24)
+#define PINID_EMI_CE0N		STMP3XXX_PINID(2, 25)
+#define PINID_EMI_CE1N		STMP3XXX_PINID(2, 26)
+#define PINID_GPMI_CE1N		STMP3XXX_PINID(2, 27)
+#define PINID_GPMI_CE0N		STMP3XXX_PINID(2, 28)
+#define PINID_EMI_CKE		STMP3XXX_PINID(2, 29)
+#define PINID_EMI_RASN		STMP3XXX_PINID(2, 30)
+#define PINID_EMI_WEN		STMP3XXX_PINID(2, 31)
+
+/* Bank 3 */
+#define PINID_EMI_D00		STMP3XXX_PINID(3, 0)
+#define PINID_EMI_D01		STMP3XXX_PINID(3, 1)
+#define PINID_EMI_D02		STMP3XXX_PINID(3, 2)
+#define PINID_EMI_D03		STMP3XXX_PINID(3, 3)
+#define PINID_EMI_D04		STMP3XXX_PINID(3, 4)
+#define PINID_EMI_D05		STMP3XXX_PINID(3, 5)
+#define PINID_EMI_D06		STMP3XXX_PINID(3, 6)
+#define PINID_EMI_D07		STMP3XXX_PINID(3, 7)
+#define PINID_EMI_D08		STMP3XXX_PINID(3, 8)
+#define PINID_EMI_D09		STMP3XXX_PINID(3, 9)
+#define PINID_EMI_D10		STMP3XXX_PINID(3, 10)
+#define PINID_EMI_D11		STMP3XXX_PINID(3, 11)
+#define PINID_EMI_D12		STMP3XXX_PINID(3, 12)
+#define PINID_EMI_D13		STMP3XXX_PINID(3, 13)
+#define PINID_EMI_D14		STMP3XXX_PINID(3, 14)
+#define PINID_EMI_D15		STMP3XXX_PINID(3, 15)
+#define PINID_EMI_DQM0		STMP3XXX_PINID(3, 16)
+#define PINID_EMI_DQM1		STMP3XXX_PINID(3, 17)
+#define PINID_EMI_DQS0		STMP3XXX_PINID(3, 18)
+#define PINID_EMI_DQS1		STMP3XXX_PINID(3, 19)
+#define PINID_EMI_CLK		STMP3XXX_PINID(3, 20)
+#define PINID_EMI_CLKN		STMP3XXX_PINID(3, 21)
+
+#endif /* __ASM_ARCH_PINS_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbh.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbh.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbh.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbh.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,101 @@
+/*
+ * stmp378x: APBH register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_APBH
+#define _MACH_REGS_APBH
+
+#define REGS_APBH_BASE	(STMP3XXX_REGS_BASE + 0x4000)
+#define REGS_APBH_PHYS	0x80004000
+#define REGS_APBH_SIZE	0x2000
+
+#define HW_APBH_CTRL0		0x0
+#define BM_APBH_CTRL0_RESET_CHANNEL	0x00FF0000
+#define BP_APBH_CTRL0_RESET_CHANNEL	16
+#define BM_APBH_CTRL0_CLKGATE	0x40000000
+#define BM_APBH_CTRL0_SFTRST	0x80000000
+
+#define HW_APBH_CTRL1		0x10
+#define BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ	0x00000001
+#define BP_APBH_CTRL1_CH0_CMDCMPLT_IRQ	0
+
+#define HW_APBH_CTRL2		0x20
+
+#define HW_APBH_DEVSEL		0x30
+
+#define HW_APBH_CH0_NXTCMDAR	(0x50 + 0 * 0x70)
+#define HW_APBH_CH1_NXTCMDAR	(0x50 + 1 * 0x70)
+#define HW_APBH_CH2_NXTCMDAR	(0x50 + 2 * 0x70)
+#define HW_APBH_CH3_NXTCMDAR	(0x50 + 3 * 0x70)
+#define HW_APBH_CH4_NXTCMDAR	(0x50 + 4 * 0x70)
+#define HW_APBH_CH5_NXTCMDAR	(0x50 + 5 * 0x70)
+#define HW_APBH_CH6_NXTCMDAR	(0x50 + 6 * 0x70)
+#define HW_APBH_CH7_NXTCMDAR	(0x50 + 7 * 0x70)
+#define HW_APBH_CH8_NXTCMDAR	(0x50 + 8 * 0x70)
+#define HW_APBH_CH9_NXTCMDAR	(0x50 + 9 * 0x70)
+#define HW_APBH_CH10_NXTCMDAR	(0x50 + 10 * 0x70)
+#define HW_APBH_CH11_NXTCMDAR	(0x50 + 11 * 0x70)
+#define HW_APBH_CH12_NXTCMDAR	(0x50 + 12 * 0x70)
+#define HW_APBH_CH13_NXTCMDAR	(0x50 + 13 * 0x70)
+#define HW_APBH_CH14_NXTCMDAR	(0x50 + 14 * 0x70)
+#define HW_APBH_CH15_NXTCMDAR	(0x50 + 15 * 0x70)
+
+#define HW_APBH_CHn_NXTCMDAR	0x50
+
+#define BV_APBH_CHn_CMD_COMMAND__NO_DMA_XFER	 0
+#define BV_APBH_CHn_CMD_COMMAND__DMA_WRITE	 1
+#define BV_APBH_CHn_CMD_COMMAND__DMA_READ	 2
+#define BV_APBH_CHn_CMD_COMMAND__DMA_SENSE	 3
+#define BM_APBH_CHn_CMD_COMMAND	0x00000003
+#define BP_APBH_CHn_CMD_COMMAND	0
+#define BM_APBH_CHn_CMD_CHAIN	0x00000004
+#define BM_APBH_CHn_CMD_IRQONCMPLT	0x00000008
+#define BM_APBH_CHn_CMD_NANDLOCK	0x00000010
+#define BM_APBH_CHn_CMD_NANDWAIT4READY	0x00000020
+#define BM_APBH_CHn_CMD_SEMAPHORE	0x00000040
+#define BM_APBH_CHn_CMD_WAIT4ENDCMD	0x00000080
+#define BM_APBH_CHn_CMD_CMDWORDS	0x0000F000
+#define BP_APBH_CHn_CMD_CMDWORDS	12
+#define BM_APBH_CHn_CMD_XFER_COUNT	0xFFFF0000
+#define BP_APBH_CHn_CMD_XFER_COUNT	16
+
+#define HW_APBH_CH0_SEMA	(0x80 + 0 * 0x70)
+#define HW_APBH_CH1_SEMA	(0x80 + 1 * 0x70)
+#define HW_APBH_CH2_SEMA	(0x80 + 2 * 0x70)
+#define HW_APBH_CH3_SEMA	(0x80 + 3 * 0x70)
+#define HW_APBH_CH4_SEMA	(0x80 + 4 * 0x70)
+#define HW_APBH_CH5_SEMA	(0x80 + 5 * 0x70)
+#define HW_APBH_CH6_SEMA	(0x80 + 6 * 0x70)
+#define HW_APBH_CH7_SEMA	(0x80 + 7 * 0x70)
+#define HW_APBH_CH8_SEMA	(0x80 + 8 * 0x70)
+#define HW_APBH_CH9_SEMA	(0x80 + 9 * 0x70)
+#define HW_APBH_CH10_SEMA	(0x80 + 10 * 0x70)
+#define HW_APBH_CH11_SEMA	(0x80 + 11 * 0x70)
+#define HW_APBH_CH12_SEMA	(0x80 + 12 * 0x70)
+#define HW_APBH_CH13_SEMA	(0x80 + 13 * 0x70)
+#define HW_APBH_CH14_SEMA	(0x80 + 14 * 0x70)
+#define HW_APBH_CH15_SEMA	(0x80 + 15 * 0x70)
+
+#define HW_APBH_CHn_SEMA	0x80
+#define BM_APBH_CHn_SEMA_INCREMENT_SEMA	0x000000FF
+#define BP_APBH_CHn_SEMA_INCREMENT_SEMA	0
+#define BM_APBH_CHn_SEMA_PHORE	0x00FF0000
+#define BP_APBH_CHn_SEMA_PHORE	16
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbx.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-apbx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,119 @@
+/*
+ * stmp378x: APBX register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_APBX
+#define _MACH_REGS_APBX
+
+#define REGS_APBX_BASE	(STMP3XXX_REGS_BASE + 0x24000)
+#define REGS_APBX_PHYS	0x80024000
+#define REGS_APBX_SIZE	0x2000
+
+#define HW_APBX_CTRL0		0x0
+#define BM_APBX_CTRL0_CLKGATE	0x40000000
+#define BM_APBX_CTRL0_SFTRST	0x80000000
+
+#define HW_APBX_CTRL1		0x10
+
+#define HW_APBX_CTRL2		0x20
+
+#define HW_APBX_CHANNEL_CTRL	0x30
+#define BM_APBX_CHANNEL_CTRL_RESET_CHANNEL	0xFFFF0000
+#define BP_APBX_CHANNEL_CTRL_RESET_CHANNEL	16
+
+#define HW_APBX_DEVSEL		0x40
+
+#define HW_APBX_CH0_NXTCMDAR	(0x110 + 0 * 0x70)
+#define HW_APBX_CH1_NXTCMDAR	(0x110 + 1 * 0x70)
+#define HW_APBX_CH2_NXTCMDAR	(0x110 + 2 * 0x70)
+#define HW_APBX_CH3_NXTCMDAR	(0x110 + 3 * 0x70)
+#define HW_APBX_CH4_NXTCMDAR	(0x110 + 4 * 0x70)
+#define HW_APBX_CH5_NXTCMDAR	(0x110 + 5 * 0x70)
+#define HW_APBX_CH6_NXTCMDAR	(0x110 + 6 * 0x70)
+#define HW_APBX_CH7_NXTCMDAR	(0x110 + 7 * 0x70)
+#define HW_APBX_CH8_NXTCMDAR	(0x110 + 8 * 0x70)
+#define HW_APBX_CH9_NXTCMDAR	(0x110 + 9 * 0x70)
+#define HW_APBX_CH10_NXTCMDAR	(0x110 + 10 * 0x70)
+#define HW_APBX_CH11_NXTCMDAR	(0x110 + 11 * 0x70)
+#define HW_APBX_CH12_NXTCMDAR	(0x110 + 12 * 0x70)
+#define HW_APBX_CH13_NXTCMDAR	(0x110 + 13 * 0x70)
+#define HW_APBX_CH14_NXTCMDAR	(0x110 + 14 * 0x70)
+#define HW_APBX_CH15_NXTCMDAR	(0x110 + 15 * 0x70)
+
+#define HW_APBX_CHn_NXTCMDAR	0x110
+#define BM_APBX_CHn_CMD_COMMAND	0x00000003
+#define BP_APBX_CHn_CMD_COMMAND	0
+#define BV_APBX_CHn_CMD_COMMAND__NO_DMA_XFER	 0
+#define BV_APBX_CHn_CMD_COMMAND__DMA_WRITE	 1
+#define BV_APBX_CHn_CMD_COMMAND__DMA_READ	 2
+#define BV_APBX_CHn_CMD_COMMAND__DMA_SENSE	 3
+#define BM_APBX_CHn_CMD_CHAIN	0x00000004
+#define BM_APBX_CHn_CMD_IRQONCMPLT	0x00000008
+#define BM_APBX_CHn_CMD_SEMAPHORE	0x00000040
+#define BM_APBX_CHn_CMD_WAIT4ENDCMD	0x00000080
+#define BM_APBX_CHn_CMD_HALTONTERMINATE	0x00000100
+#define BM_APBX_CHn_CMD_CMDWORDS	0x0000F000
+#define BP_APBX_CHn_CMD_CMDWORDS	12
+#define BM_APBX_CHn_CMD_XFER_COUNT	0xFFFF0000
+#define BP_APBX_CHn_CMD_XFER_COUNT	16
+
+#define HW_APBX_CH0_BAR		(0x130 + 0 * 0x70)
+#define HW_APBX_CH1_BAR		(0x130 + 1 * 0x70)
+#define HW_APBX_CH2_BAR		(0x130 + 2 * 0x70)
+#define HW_APBX_CH3_BAR		(0x130 + 3 * 0x70)
+#define HW_APBX_CH4_BAR		(0x130 + 4 * 0x70)
+#define HW_APBX_CH5_BAR		(0x130 + 5 * 0x70)
+#define HW_APBX_CH6_BAR		(0x130 + 6 * 0x70)
+#define HW_APBX_CH7_BAR		(0x130 + 7 * 0x70)
+#define HW_APBX_CH8_BAR		(0x130 + 8 * 0x70)
+#define HW_APBX_CH9_BAR		(0x130 + 9 * 0x70)
+#define HW_APBX_CH10_BAR		(0x130 + 10 * 0x70)
+#define HW_APBX_CH11_BAR		(0x130 + 11 * 0x70)
+#define HW_APBX_CH12_BAR		(0x130 + 12 * 0x70)
+#define HW_APBX_CH13_BAR		(0x130 + 13 * 0x70)
+#define HW_APBX_CH14_BAR		(0x130 + 14 * 0x70)
+#define HW_APBX_CH15_BAR		(0x130 + 15 * 0x70)
+
+#define HW_APBX_CHn_BAR		0x130
+
+#define HW_APBX_CH0_SEMA	(0x140 + 0 * 0x70)
+#define HW_APBX_CH1_SEMA	(0x140 + 1 * 0x70)
+#define HW_APBX_CH2_SEMA	(0x140 + 2 * 0x70)
+#define HW_APBX_CH3_SEMA	(0x140 + 3 * 0x70)
+#define HW_APBX_CH4_SEMA	(0x140 + 4 * 0x70)
+#define HW_APBX_CH5_SEMA	(0x140 + 5 * 0x70)
+#define HW_APBX_CH6_SEMA	(0x140 + 6 * 0x70)
+#define HW_APBX_CH7_SEMA	(0x140 + 7 * 0x70)
+#define HW_APBX_CH8_SEMA	(0x140 + 8 * 0x70)
+#define HW_APBX_CH9_SEMA	(0x140 + 9 * 0x70)
+#define HW_APBX_CH10_SEMA	(0x140 + 10 * 0x70)
+#define HW_APBX_CH11_SEMA	(0x140 + 11 * 0x70)
+#define HW_APBX_CH12_SEMA	(0x140 + 12 * 0x70)
+#define HW_APBX_CH13_SEMA	(0x140 + 13 * 0x70)
+#define HW_APBX_CH14_SEMA	(0x140 + 14 * 0x70)
+#define HW_APBX_CH15_SEMA	(0x140 + 15 * 0x70)
+
+#define HW_APBX_CHn_SEMA	0x140
+#define BM_APBX_CHn_SEMA_INCREMENT_SEMA	0x000000FF
+#define BP_APBX_CHn_SEMA_INCREMENT_SEMA	0
+#define BM_APBX_CHn_SEMA_PHORE	0x00FF0000
+#define BP_APBX_CHn_SEMA_PHORE	16
+
+#endif
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioin.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioin.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioin.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioin.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * stmp378x: AUDIOIN register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_AUDIOIN_BASE	(STMP3XXX_REGS_BASE + 0x4C000)
+#define REGS_AUDIOIN_PHYS	0x8004C000
+#define REGS_AUDIOIN_SIZE	0x2000
+
+#define HW_AUDIOIN_CTRL		0x0
+#define BM_AUDIOIN_CTRL_RUN	0x00000001
+#define BP_AUDIOIN_CTRL_RUN	0
+#define BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN	0x00000002
+#define BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ	0x00000004
+#define BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ	0x00000008
+#define BM_AUDIOIN_CTRL_WORD_LENGTH	0x00000020
+#define BM_AUDIOIN_CTRL_CLKGATE	0x40000000
+#define BM_AUDIOIN_CTRL_SFTRST	0x80000000
+
+#define HW_AUDIOIN_STAT		0x10
+
+#define HW_AUDIOIN_ADCSRR	0x20
+
+#define HW_AUDIOIN_ADCVOLUME	0x30
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT	0x000000FF
+#define BP_AUDIOIN_ADCVOLUME_VOLUME_RIGHT	0
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT	0x00FF0000
+#define BP_AUDIOIN_ADCVOLUME_VOLUME_LEFT	16
+
+#define HW_AUDIOIN_ADCDEBUG	0x40
+
+#define HW_AUDIOIN_ADCVOL	0x50
+#define BM_AUDIOIN_ADCVOL_GAIN_RIGHT	0x0000000F
+#define BP_AUDIOIN_ADCVOL_GAIN_RIGHT	0
+#define BM_AUDIOIN_ADCVOL_SELECT_RIGHT	0x00000030
+#define BP_AUDIOIN_ADCVOL_SELECT_RIGHT	4
+#define BM_AUDIOIN_ADCVOL_GAIN_LEFT	0x00000F00
+#define BP_AUDIOIN_ADCVOL_GAIN_LEFT	8
+#define BM_AUDIOIN_ADCVOL_SELECT_LEFT	0x00003000
+#define BP_AUDIOIN_ADCVOL_SELECT_LEFT	12
+#define BM_AUDIOIN_ADCVOL_MUTE	0x01000000
+
+#define HW_AUDIOIN_MICLINE	0x60
+
+#define HW_AUDIOIN_ANACLKCTRL	0x70
+#define BM_AUDIOIN_ANACLKCTRL_CLKGATE	0x80000000
+
+#define HW_AUDIOIN_DATA		0x80
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioout.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioout.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioout.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-audioout.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * stmp378x: AUDIOOUT register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_AUDIOOUT_BASE	(STMP3XXX_REGS_BASE + 0x48000)
+#define REGS_AUDIOOUT_PHYS	0x80048000
+#define REGS_AUDIOOUT_SIZE	0x2000
+
+#define HW_AUDIOOUT_CTRL	0x0
+#define BM_AUDIOOUT_CTRL_RUN	0x00000001
+#define BP_AUDIOOUT_CTRL_RUN	0
+#define BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN	0x00000002
+#define BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ	0x00000004
+#define BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ	0x00000008
+#define BM_AUDIOOUT_CTRL_WORD_LENGTH	0x00000040
+#define BM_AUDIOOUT_CTRL_CLKGATE	0x40000000
+#define BM_AUDIOOUT_CTRL_SFTRST	0x80000000
+
+#define HW_AUDIOOUT_STAT	0x10
+
+#define HW_AUDIOOUT_DACSRR	0x20
+#define BM_AUDIOOUT_DACSRR_SRC_FRAC	0x00001FFF
+#define BP_AUDIOOUT_DACSRR_SRC_FRAC	0
+#define BM_AUDIOOUT_DACSRR_SRC_INT	0x001F0000
+#define BP_AUDIOOUT_DACSRR_SRC_INT	16
+#define BM_AUDIOOUT_DACSRR_SRC_HOLD	0x07000000
+#define BP_AUDIOOUT_DACSRR_SRC_HOLD	24
+#define BM_AUDIOOUT_DACSRR_BASEMULT	0x70000000
+#define BP_AUDIOOUT_DACSRR_BASEMULT	28
+
+#define HW_AUDIOOUT_DACVOLUME	0x30
+#define BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT	0x00000100
+#define BM_AUDIOOUT_DACVOLUME_MUTE_LEFT	0x01000000
+#define BM_AUDIOOUT_DACVOLUME_EN_ZCD	0x02000000
+
+#define HW_AUDIOOUT_DACDEBUG	0x40
+
+#define HW_AUDIOOUT_HPVOL	0x50
+#define BM_AUDIOOUT_HPVOL_MUTE	0x01000000
+#define BM_AUDIOOUT_HPVOL_EN_MSTR_ZCD	0x02000000
+
+#define HW_AUDIOOUT_PWRDN	0x70
+#define BM_AUDIOOUT_PWRDN_HEADPHONE	0x00000001
+#define BP_AUDIOOUT_PWRDN_HEADPHONE	0
+#define BM_AUDIOOUT_PWRDN_CAPLESS	0x00000010
+#define BM_AUDIOOUT_PWRDN_ADC	0x00000100
+#define BM_AUDIOOUT_PWRDN_DAC	0x00001000
+#define BM_AUDIOOUT_PWRDN_RIGHT_ADC	0x00010000
+#define BM_AUDIOOUT_PWRDN_SPEAKER	0x01000000
+
+#define HW_AUDIOOUT_REFCTRL	0x80
+#define BM_AUDIOOUT_REFCTRL_VAG_VAL	0x000000F0
+#define BP_AUDIOOUT_REFCTRL_VAG_VAL	4
+#define BM_AUDIOOUT_REFCTRL_ADC_REFVAL	0x00000F00
+#define BP_AUDIOOUT_REFCTRL_ADC_REFVAL	8
+#define BM_AUDIOOUT_REFCTRL_ADJ_VAG	0x00001000
+#define BM_AUDIOOUT_REFCTRL_ADJ_ADC	0x00002000
+#define BM_AUDIOOUT_REFCTRL_BIAS_CTRL	0x00030000
+#define BP_AUDIOOUT_REFCTRL_BIAS_CTRL	16
+#define BM_AUDIOOUT_REFCTRL_LOW_PWR	0x00080000
+#define BM_AUDIOOUT_REFCTRL_VBG_ADJ	0x00700000
+#define BP_AUDIOOUT_REFCTRL_VBG_ADJ	20
+#define BM_AUDIOOUT_REFCTRL_XTAL_BGR_BIAS	0x01000000
+#define BM_AUDIOOUT_REFCTRL_RAISE_REF	0x02000000
+
+#define HW_AUDIOOUT_ANACTRL	0x90
+#define BM_AUDIOOUT_ANACTRL_HP_CLASSAB	0x00000010
+#define BM_AUDIOOUT_ANACTRL_HP_HOLD_GND	0x00000020
+
+#define HW_AUDIOOUT_TEST	0xA0
+#define BM_AUDIOOUT_TEST_HP_I1_ADJ	0x00C00000
+#define BP_AUDIOOUT_TEST_HP_I1_ADJ	22
+
+#define HW_AUDIOOUT_BISTCTRL	0xB0
+
+#define HW_AUDIOOUT_BISTSTAT0	0xC0
+
+#define HW_AUDIOOUT_BISTSTAT1	0xD0
+
+#define HW_AUDIOOUT_ANACLKCTRL	0xE0
+#define BM_AUDIOOUT_ANACLKCTRL_CLKGATE	0x80000000
+
+#define HW_AUDIOOUT_DATA	0xF0
+
+#define HW_AUDIOOUT_SPEAKERCTRL	0x100
+#define BM_AUDIOOUT_SPEAKERCTRL_MUTE	0x01000000
+
+#define HW_AUDIOOUT_VERSION	0x200
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-bch.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-bch.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-bch.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-bch.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * stmp378x: BCH register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_BCH_BASE	(STMP3XXX_REGS_BASE + 0xA000)
+#define REGS_BCH_PHYS	0x8000A000
+#define REGS_BCH_SIZE	0x2000
+
+#define HW_BCH_CTRL		0x0
+#define BM_BCH_CTRL_COMPLETE_IRQ	0x00000001
+#define BP_BCH_CTRL_COMPLETE_IRQ	0
+#define BM_BCH_CTRL_COMPLETE_IRQ_EN	0x00000100
+
+#define HW_BCH_STATUS0		0x10
+#define BM_BCH_STATUS0_UNCORRECTABLE	0x00000004
+#define BM_BCH_STATUS0_CORRECTED	0x00000008
+#define BM_BCH_STATUS0_STATUS_BLK0	0x0000FF00
+#define BP_BCH_STATUS0_STATUS_BLK0	8
+#define BM_BCH_STATUS0_COMPLETED_CE	0x000F0000
+#define BP_BCH_STATUS0_COMPLETED_CE	16
+
+#define HW_BCH_LAYOUTSELECT	0x70
+
+#define HW_BCH_FLASH0LAYOUT0	0x80
+#define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE	0x00000FFF
+#define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE	0
+#define BM_BCH_FLASH0LAYOUT0_ECC0	0x0000F000
+#define BP_BCH_FLASH0LAYOUT0_ECC0	12
+#define BM_BCH_FLASH0LAYOUT0_META_SIZE	0x00FF0000
+#define BP_BCH_FLASH0LAYOUT0_META_SIZE	16
+#define BM_BCH_FLASH0LAYOUT0_NBLOCKS	0xFF000000
+#define BP_BCH_FLASH0LAYOUT0_NBLOCKS	24
+#define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE	0x00000FFF
+#define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE	0
+#define BM_BCH_FLASH0LAYOUT1_ECCN	0x0000F000
+#define BP_BCH_FLASH0LAYOUT1_ECCN	12
+#define BM_BCH_FLASH0LAYOUT1_PAGE_SIZE	0xFFFF0000
+#define BP_BCH_FLASH0LAYOUT1_PAGE_SIZE	16
+
+#define HW_BCH_BLOCKNAME	0x150
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-clkctrl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,88 @@
+/*
+ * stmp378x: CLKCTRL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_CLKCTRL
+#define _MACH_REGS_CLKCTRL
+
+#define REGS_CLKCTRL_BASE	(STMP3XXX_REGS_BASE + 0x40000)
+#define REGS_CLKCTRL_PHYS	0x80040000
+#define REGS_CLKCTRL_SIZE	0x2000
+
+#define HW_CLKCTRL_PLLCTRL0	0x0
+#define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS	0x00040000
+
+#define HW_CLKCTRL_CPU		0x20
+#define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
+#define BP_CLKCTRL_CPU_DIV_CPU	0
+
+#define HW_CLKCTRL_HBUS		0x30
+#define BM_CLKCTRL_HBUS_DIV	0x0000001F
+#define BP_CLKCTRL_HBUS_DIV	0
+#define BM_CLKCTRL_HBUS_DIV_FRAC_EN	0x00000020
+
+#define HW_CLKCTRL_XBUS		0x40
+
+#define HW_CLKCTRL_XTAL		0x50
+#define BM_CLKCTRL_XTAL_DRI_CLK24M_GATE	0x10000000
+
+#define HW_CLKCTRL_PIX		0x60
+#define BM_CLKCTRL_PIX_DIV	0x00000FFF
+#define BP_CLKCTRL_PIX_DIV	0
+#define BM_CLKCTRL_PIX_CLKGATE	0x80000000
+
+#define HW_CLKCTRL_SSP		0x70
+
+#define HW_CLKCTRL_GPMI		0x80
+
+#define HW_CLKCTRL_SPDIF	0x90
+
+#define HW_CLKCTRL_EMI		0xA0
+#define BM_CLKCTRL_EMI_DIV_EMI	0x0000003F
+#define BP_CLKCTRL_EMI_DIV_EMI	0
+#define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE	0x00010000
+#define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC	0x00020000
+#define BM_CLKCTRL_EMI_BUSY_REF_EMI	0x10000000
+#define BM_CLKCTRL_EMI_BUSY_REF_XTAL	0x20000000
+
+#define HW_CLKCTRL_IR		0xB0
+
+#define HW_CLKCTRL_SAIF		0xC0
+
+#define HW_CLKCTRL_TV		0xD0
+
+#define HW_CLKCTRL_ETM		0xE0
+
+#define HW_CLKCTRL_FRAC		0xF0
+#define BM_CLKCTRL_FRAC_EMIFRAC	0x00003F00
+#define BP_CLKCTRL_FRAC_EMIFRAC	8
+#define BM_CLKCTRL_FRAC_PIXFRAC	0x003F0000
+#define BP_CLKCTRL_FRAC_PIXFRAC	16
+#define BM_CLKCTRL_FRAC_CLKGATEPIX	0x00800000
+
+#define HW_CLKCTRL_FRAC1	0x100
+
+#define HW_CLKCTRL_CLKSEQ	0x110
+#define BM_CLKCTRL_CLKSEQ_BYPASS_PIX	0x00000002
+
+#define HW_CLKCTRL_RESET	0x120
+#define BM_CLKCTRL_RESET_DIG	0x00000001
+#define BP_CLKCTRL_RESET_DIG	0
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-dcp.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-dcp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-dcp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-dcp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+ * stmp378x: DCP register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_DCP_BASE	(STMP3XXX_REGS_BASE + 0x28000)
+#define REGS_DCP_PHYS	0x80028000
+#define REGS_DCP_SIZE	0x2000
+
+#define HW_DCP_CTRL		0x0
+#define BM_DCP_CTRL_CHANNEL_INTERRUPT_ENABLE	0x000000FF
+#define BP_DCP_CTRL_CHANNEL_INTERRUPT_ENABLE	0
+#define BM_DCP_CTRL_ENABLE_CONTEXT_CACHING	0x00400000
+#define BM_DCP_CTRL_GATHER_RESIDUAL_WRITES	0x00800000
+#define BM_DCP_CTRL_CLKGATE	0x40000000
+#define BM_DCP_CTRL_SFTRST	0x80000000
+
+#define HW_DCP_STAT		0x10
+#define BM_DCP_STAT_IRQ		0x0000000F
+#define BP_DCP_STAT_IRQ		0
+
+#define HW_DCP_CHANNELCTRL	0x20
+#define BM_DCP_CHANNELCTRL_ENABLE_CHANNEL	0x000000FF
+#define BP_DCP_CHANNELCTRL_ENABLE_CHANNEL	0
+
+#define HW_DCP_CONTEXT		0x50
+#define BM_DCP_PACKET1_INTERRUPT	0x00000001
+#define BP_DCP_PACKET1_INTERRUPT	0
+#define BM_DCP_PACKET1_DECR_SEMAPHORE	0x00000002
+#define BM_DCP_PACKET1_CHAIN	0x00000004
+#define BM_DCP_PACKET1_CHAIN_CONTIGUOUS	0x00000008
+#define BM_DCP_PACKET1_ENABLE_CIPHER	0x00000020
+#define BM_DCP_PACKET1_ENABLE_HASH	0x00000040
+#define BM_DCP_PACKET1_CIPHER_ENCRYPT	0x00000100
+#define BM_DCP_PACKET1_CIPHER_INIT	0x00000200
+#define BM_DCP_PACKET1_OTP_KEY	0x00000400
+#define BM_DCP_PACKET1_PAYLOAD_KEY	0x00000800
+#define BM_DCP_PACKET1_HASH_INIT	0x00001000
+#define BM_DCP_PACKET1_HASH_TERM	0x00002000
+#define BM_DCP_PACKET2_CIPHER_SELECT	0x0000000F
+#define BP_DCP_PACKET2_CIPHER_SELECT	0
+#define BM_DCP_PACKET2_CIPHER_MODE	0x000000F0
+#define BP_DCP_PACKET2_CIPHER_MODE	4
+#define BM_DCP_PACKET2_KEY_SELECT	0x0000FF00
+#define BP_DCP_PACKET2_KEY_SELECT	8
+#define BM_DCP_PACKET2_HASH_SELECT	0x000F0000
+#define BP_DCP_PACKET2_HASH_SELECT	16
+#define BM_DCP_PACKET2_CIPHER_CFG	0xFF000000
+#define BP_DCP_PACKET2_CIPHER_CFG	24
+
+#define HW_DCP_CH0CMDPTR	(0x100 + 0 * 0x40)
+#define HW_DCP_CH1CMDPTR	(0x100 + 1 * 0x40)
+#define HW_DCP_CH2CMDPTR	(0x100 + 2 * 0x40)
+#define HW_DCP_CH3CMDPTR	(0x100 + 3 * 0x40)
+
+#define HW_DCP_CHnCMDPTR	0x100
+
+#define HW_DCP_CH0SEMA		(0x110 + 0 * 0x40)
+#define HW_DCP_CH1SEMA		(0x110 + 1 * 0x40)
+#define HW_DCP_CH2SEMA		(0x110 + 2 * 0x40)
+#define HW_DCP_CH3SEMA		(0x110 + 3 * 0x40)
+
+#define HW_DCP_CHnSEMA		0x110
+#define BM_DCP_CHnSEMA_INCREMENT	0x000000FF
+#define BP_DCP_CHnSEMA_INCREMENT	0
+
+#define HW_DCP_CH0STAT		(0x120 + 0 * 0x40)
+#define HW_DCP_CH1STAT		(0x120 + 1 * 0x40)
+#define HW_DCP_CH2STAT		(0x120 + 2 * 0x40)
+#define HW_DCP_CH3STAT		(0x120 + 3 * 0x40)
+
+#define HW_DCP_CHnSTAT		0x120
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-digctl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-digctl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-digctl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-digctl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * stmp378x: DIGCTL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_DIGCTL_BASE	(STMP3XXX_REGS_BASE + 0x1C000)
+#define REGS_DIGCTL_PHYS	0x8001C000
+#define REGS_DIGCTL_SIZE	0x2000
+
+#define HW_DIGCTL_CTRL		0x0
+#define BM_DIGCTL_CTRL_USB_CLKGATE	0x00000004
+
+#define HW_DIGCTL_ARMCACHE	0x2B0
+#define BM_DIGCTL_ARMCACHE_ITAG_SS	0x00000003
+#define BP_DIGCTL_ARMCACHE_ITAG_SS	0
+#define BM_DIGCTL_ARMCACHE_DTAG_SS	0x00000030
+#define BP_DIGCTL_ARMCACHE_DTAG_SS	4
+#define BM_DIGCTL_ARMCACHE_CACHE_SS	0x00000300
+#define BP_DIGCTL_ARMCACHE_CACHE_SS	8
+#define BM_DIGCTL_ARMCACHE_DRTY_SS	0x00003000
+#define BP_DIGCTL_ARMCACHE_DRTY_SS	12
+#define BM_DIGCTL_ARMCACHE_VALID_SS	0x00030000
+#define BP_DIGCTL_ARMCACHE_VALID_SS	16
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-dram.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-dram.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-dram.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-dram.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * stmp378x: DRAM register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_DRAM_BASE	(STMP3XXX_REGS_BASE + 0xE0000)
+#define REGS_DRAM_PHYS	0x800E0000
+#define REGS_DRAM_SIZE	0x2000
+
+#define HW_DRAM_CTL06		0x18
+
+#define HW_DRAM_CTL08		0x20
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-dri.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-dri.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-dri.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-dri.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * stmp378x: DRI register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_DRI_BASE	(STMP3XXX_REGS_BASE + 0x74000)
+#define REGS_DRI_PHYS	0x80074000
+#define REGS_DRI_SIZE	0x2000
+
+#define HW_DRI_CTRL		0x0
+#define BM_DRI_CTRL_RUN		0x00000001
+#define BP_DRI_CTRL_RUN		0
+#define BM_DRI_CTRL_ATTENTION_IRQ	0x00000002
+#define BM_DRI_CTRL_PILOT_SYNC_LOSS_IRQ	0x00000004
+#define BM_DRI_CTRL_OVERFLOW_IRQ	0x00000008
+#define BM_DRI_CTRL_ATTENTION_IRQ_EN	0x00000200
+#define BM_DRI_CTRL_PILOT_SYNC_LOSS_IRQ_EN	0x00000400
+#define BM_DRI_CTRL_OVERFLOW_IRQ_EN	0x00000800
+#define BM_DRI_CTRL_REACQUIRE_PHASE	0x00008000
+#define BM_DRI_CTRL_STOP_ON_PILOT_ERROR	0x02000000
+#define BM_DRI_CTRL_STOP_ON_OFLOW_ERROR	0x04000000
+#define BM_DRI_CTRL_ENABLE_INPUTS	0x20000000
+#define BM_DRI_CTRL_CLKGATE	0x40000000
+#define BM_DRI_CTRL_SFTRST	0x80000000
+
+#define HW_DRI_TIMING		0x10
+#define BM_DRI_TIMING_GAP_DETECTION_INTERVAL	0x000000FF
+#define BP_DRI_TIMING_GAP_DETECTION_INTERVAL	0
+#define BM_DRI_TIMING_PILOT_REP_RATE	0x000F0000
+#define BP_DRI_TIMING_PILOT_REP_RATE	16
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ecc8.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ecc8.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ecc8.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ecc8.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,39 @@
+/*
+ * stmp378x: ECC8 register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_ECC8_BASE	(STMP3XXX_REGS_BASE + 0x8000)
+#define REGS_ECC8_PHYS	0x80008000
+#define REGS_ECC8_SIZE	0x2000
+
+#define HW_ECC8_CTRL		0x0
+#define BM_ECC8_CTRL_COMPLETE_IRQ	0x00000001
+#define BP_ECC8_CTRL_COMPLETE_IRQ	0
+#define BM_ECC8_CTRL_COMPLETE_IRQ_EN	0x00000100
+#define BM_ECC8_CTRL_AHBM_SFTRST	0x20000000
+
+#define HW_ECC8_STATUS0		0x10
+#define BM_ECC8_STATUS0_UNCORRECTABLE	0x00000004
+#define BM_ECC8_STATUS0_CORRECTED	0x00000008
+#define BM_ECC8_STATUS0_STATUS_AUX	0x00000F00
+#define BP_ECC8_STATUS0_STATUS_AUX	8
+#define BM_ECC8_STATUS0_COMPLETED_CE	0x000F0000
+#define BP_ECC8_STATUS0_COMPLETED_CE	16
+
+#define HW_ECC8_STATUS1		0x20
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-emi.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-emi.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-emi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-emi.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * stmp378x: EMI register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_EMI_BASE	(STMP3XXX_REGS_BASE + 0x20000)
+#define REGS_EMI_PHYS	0x80020000
+#define REGS_EMI_SIZE	0x2000
+
+#define HW_EMI_STAT		0x10
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-gpmi.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-gpmi.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-gpmi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-gpmi.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * stmp378x: GPMI register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_GPMI_BASE	(STMP3XXX_REGS_BASE + 0xC000)
+#define REGS_GPMI_PHYS	0x8000C000
+#define REGS_GPMI_SIZE	0x2000
+
+#define HW_GPMI_CTRL0		0x0
+#define BM_GPMI_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_GPMI_CTRL0_XFER_COUNT	0
+#define BM_GPMI_CTRL0_CS	0x00300000
+#define BP_GPMI_CTRL0_CS	20
+#define BM_GPMI_CTRL0_LOCK_CS	0x00400000
+#define BM_GPMI_CTRL0_WORD_LENGTH	0x00800000
+#define BM_GPMI_CTRL0_ADDRESS      0x000E0000
+#define BP_GPMI_CTRL0_ADDRESS      17
+#define BV_GPMI_CTRL0_ADDRESS__NAND_DATA  0x0
+#define BV_GPMI_CTRL0_ADDRESS__NAND_CLE   0x1
+#define BV_GPMI_CTRL0_ADDRESS__NAND_ALE   0x2
+#define BM_GPMI_CTRL0_ADDRESS_INCREMENT      0x00010000
+#define BM_GPMI_CTRL0_COMMAND_MODE	0x03000000
+#define BP_GPMI_CTRL0_COMMAND_MODE	24
+#define BV_GPMI_CTRL0_COMMAND_MODE__WRITE	    0x0
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ	     0x1
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ_AND_COMPARE 0x2
+#define BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY   0x3
+#define BM_GPMI_CTRL0_RUN	0x20000000
+#define BM_GPMI_CTRL0_CLKGATE	0x40000000
+#define BM_GPMI_CTRL0_SFTRST	0x80000000
+#define BM_GPMI_ECCCTRL_BUFFER_MASK	0x000001FF
+#define BP_GPMI_ECCCTRL_BUFFER_MASK	0
+#define BM_GPMI_ECCCTRL_ENABLE_ECC	0x00001000
+#define BM_GPMI_ECCCTRL_ECC_CMD	0x00006000
+#define BP_GPMI_ECCCTRL_ECC_CMD	13
+#define BV_GPMI_ECCCTRL_ECC_CMD__DECODE_4_BIT			0
+#define BV_GPMI_ECCCTRL_ECC_CMD__ENCODE_4_BIT			1
+#define BV_GPMI_ECCCTRL_ECC_CMD__DECODE_8_BIT			2
+#define BV_GPMI_ECCCTRL_ECC_CMD__ENCODE_8_BIT			3
+
+#define HW_GPMI_CTRL1		0x60
+#define BM_GPMI_CTRL1_GPMI_MODE	0x00000001
+#define BP_GPMI_CTRL1_GPMI_MODE	0
+#define BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY	0x00000004
+#define BM_GPMI_CTRL1_DEV_RESET	0x00000008
+#define BM_GPMI_CTRL1_TIMEOUT_IRQ	0x00000200
+#define BM_GPMI_CTRL1_DEV_IRQ	0x00000400
+#define BM_GPMI_CTRL1_RDN_DELAY	0x0000F000
+#define BP_GPMI_CTRL1_RDN_DELAY	12
+#define BM_GPMI_CTRL1_BCH_MODE	0x00040000
+
+#define HW_GPMI_TIMING0		0x70
+#define BM_GPMI_TIMING0_DATA_SETUP	0x000000FF
+#define BP_GPMI_TIMING0_DATA_SETUP	0
+#define BM_GPMI_TIMING0_DATA_HOLD	0x0000FF00
+#define BP_GPMI_TIMING0_DATA_HOLD	8
+#define BM_GPMI_TIMING0_ADDRESS_SETUP	0x00FF0000
+#define BP_GPMI_TIMING0_ADDRESS_SETUP	16
+
+#define HW_GPMI_TIMING1		0x80
+#define BM_GPMI_TIMING1_DEVICE_BUSY_TIMEOUT	0xFFFF0000
+#define BP_GPMI_TIMING1_DEVICE_BUSY_TIMEOUT	16
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-i2c.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-i2c.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-i2c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-i2c.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * stmp378x: I2C register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_I2C_BASE	(STMP3XXX_REGS_BASE + 0x58000)
+#define REGS_I2C_PHYS	0x80058000
+#define REGS_I2C_SIZE	0x2000
+
+#define HW_I2C_CTRL0		0x0
+#define BM_I2C_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_I2C_CTRL0_XFER_COUNT	0
+#define BM_I2C_CTRL0_DIRECTION	0x00010000
+#define BM_I2C_CTRL0_MASTER_MODE	0x00020000
+#define BM_I2C_CTRL0_PRE_SEND_START	0x00080000
+#define BM_I2C_CTRL0_POST_SEND_STOP	0x00100000
+#define BM_I2C_CTRL0_RETAIN_CLOCK	0x00200000
+#define BM_I2C_CTRL0_SEND_NAK_ON_LAST	0x02000000
+#define BM_I2C_CTRL0_CLKGATE	0x40000000
+#define BM_I2C_CTRL0_SFTRST	0x80000000
+
+#define HW_I2C_TIMING0		0x10
+
+#define HW_I2C_TIMING1		0x20
+
+#define HW_I2C_TIMING2		0x30
+
+#define HW_I2C_CTRL1		0x40
+#define BM_I2C_CTRL1_SLAVE_IRQ	0x00000001
+#define BP_I2C_CTRL1_SLAVE_IRQ	0
+#define BM_I2C_CTRL1_SLAVE_STOP_IRQ	0x00000002
+#define BM_I2C_CTRL1_MASTER_LOSS_IRQ	0x00000004
+#define BM_I2C_CTRL1_EARLY_TERM_IRQ	0x00000008
+#define BM_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	0x00000010
+#define BM_I2C_CTRL1_NO_SLAVE_ACK_IRQ	0x00000020
+#define BM_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ	0x00000040
+#define BM_I2C_CTRL1_BUS_FREE_IRQ	0x00000080
+#define BM_I2C_CTRL1_CLR_GOT_A_NAK	0x10000000
+
+#define HW_I2C_VERSION		0x90
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-icoll.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-icoll.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-icoll.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-icoll.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * stmp378x: ICOLL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_ICOLL
+#define _MACH_REGS_ICOLL
+
+#define REGS_ICOLL_BASE	(STMP3XXX_REGS_BASE + 0x0)
+#define REGS_ICOLL_PHYS	0x80000000
+#define REGS_ICOLL_SIZE	0x2000
+
+#define HW_ICOLL_VECTOR		0x0
+
+#define HW_ICOLL_LEVELACK	0x10
+#define BM_ICOLL_LEVELACK_IRQLEVELACK	0x0000000F
+#define BP_ICOLL_LEVELACK_IRQLEVELACK	0
+
+#define HW_ICOLL_CTRL		0x20
+#define BM_ICOLL_CTRL_CLKGATE	0x40000000
+#define BM_ICOLL_CTRL_SFTRST	0x80000000
+
+#define HW_ICOLL_STAT		0x70
+
+#define HW_ICOLL_INTERRUPTn	0x120
+
+#define HW_ICOLL_INTERRUPTn	0x120
+#define BM_ICOLL_INTERRUPTn_ENABLE	0x00000004
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ir.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ir.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ir.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ir.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * stmp378x: IR register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_IR_BASE	(STMP3XXX_REGS_BASE + 0x78000)
+#define REGS_IR_PHYS	0x80078000
+#define REGS_IR_SIZE	0x2000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-lcdif.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-lcdif.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-lcdif.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-lcdif.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * stmp378x: LCDIF register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_LCDIF_BASE	(STMP3XXX_REGS_BASE + 0x30000)
+#define REGS_LCDIF_PHYS	0x80030000
+#define REGS_LCDIF_SIZE	0x2000
+
+#define HW_LCDIF_CTRL		0x0
+#define BM_LCDIF_CTRL_RUN	0x00000001
+#define BP_LCDIF_CTRL_RUN	0
+#define BM_LCDIF_CTRL_LCDIF_MASTER	0x00000020
+#define BM_LCDIF_CTRL_RGB_TO_YCBCR422_CSC	0x00000080
+#define BM_LCDIF_CTRL_WORD_LENGTH	0x00000300
+#define BP_LCDIF_CTRL_WORD_LENGTH	8
+#define BM_LCDIF_CTRL_LCD_DATABUS_WIDTH	0x00000C00
+#define BP_LCDIF_CTRL_LCD_DATABUS_WIDTH	10
+#define BM_LCDIF_CTRL_INPUT_DATA_SWIZZLE	0x0000C000
+#define BP_LCDIF_CTRL_INPUT_DATA_SWIZZLE	14
+#define BM_LCDIF_CTRL_DATA_SELECT	0x00010000
+#define BM_LCDIF_CTRL_DOTCLK_MODE	0x00020000
+#define BM_LCDIF_CTRL_VSYNC_MODE	0x00040000
+#define BM_LCDIF_CTRL_BYPASS_COUNT	0x00080000
+#define BM_LCDIF_CTRL_DVI_MODE	0x00100000
+#define BM_LCDIF_CTRL_SHIFT_NUM_BITS	0x03E00000
+#define BP_LCDIF_CTRL_SHIFT_NUM_BITS	21
+#define BM_LCDIF_CTRL_DATA_SHIFT_DIR	0x04000000
+#define BM_LCDIF_CTRL_WAIT_FOR_VSYNC_EDGE	0x08000000
+#define BM_LCDIF_CTRL_CLKGATE	0x40000000
+#define BM_LCDIF_CTRL_SFTRST	0x80000000
+
+#define HW_LCDIF_CTRL1		0x10
+#define BM_LCDIF_CTRL1_RESET	0x00000001
+#define BP_LCDIF_CTRL1_RESET	0
+#define BM_LCDIF_CTRL1_MODE86	0x00000002
+#define BM_LCDIF_CTRL1_BUSY_ENABLE	0x00000004
+#define BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ	0x00000100
+#define BM_LCDIF_CTRL1_CUR_FRAME_DONE_IRQ	0x00000200
+#define BM_LCDIF_CTRL1_UNDERFLOW_IRQ	0x00000400
+#define BM_LCDIF_CTRL1_OVERFLOW_IRQ	0x00000800
+#define BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN	0x00001000
+#define BM_LCDIF_CTRL1_BYTE_PACKING_FORMAT	0x000F0000
+#define BP_LCDIF_CTRL1_BYTE_PACKING_FORMAT	16
+#define BM_LCDIF_CTRL1_INTERLACE_FIELDS	0x00800000
+#define BM_LCDIF_CTRL1_RECOVER_ON_UNDERFLOW	0x01000000
+
+#define HW_LCDIF_TRANSFER_COUNT	0x20
+#define BM_LCDIF_TRANSFER_COUNT_H_COUNT	0x0000FFFF
+#define BP_LCDIF_TRANSFER_COUNT_H_COUNT	0
+#define BM_LCDIF_TRANSFER_COUNT_V_COUNT	0xFFFF0000
+#define BP_LCDIF_TRANSFER_COUNT_V_COUNT	16
+
+#define HW_LCDIF_CUR_BUF	0x30
+
+#define HW_LCDIF_NEXT_BUF	0x40
+
+#define HW_LCDIF_TIMING		0x60
+
+#define HW_LCDIF_VDCTRL0	0x70
+#define BM_LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH	0x0003FFFF
+#define BP_LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH	0
+#define BM_LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	0x00100000
+#define BM_LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT	0x00200000
+#define BM_LCDIF_VDCTRL0_ENABLE_POL	0x01000000
+#define BM_LCDIF_VDCTRL0_DOTCLK_POL	0x02000000
+#define BM_LCDIF_VDCTRL0_HSYNC_POL	0x04000000
+#define BM_LCDIF_VDCTRL0_VSYNC_POL	0x08000000
+#define BM_LCDIF_VDCTRL0_ENABLE_PRESENT	0x10000000
+#define BM_LCDIF_VDCTRL0_VSYNC_OEB	0x20000000
+
+#define HW_LCDIF_VDCTRL1	0x80
+#define BM_LCDIF_VDCTRL1_VSYNC_PERIOD	0xFFFFFFFF
+#define BP_LCDIF_VDCTRL1_VSYNC_PERIOD	0
+
+#define HW_LCDIF_VDCTRL2	0x90
+#define BM_LCDIF_VDCTRL2_HSYNC_PERIOD	0x0003FFFF
+#define BP_LCDIF_VDCTRL2_HSYNC_PERIOD	0
+#define BM_LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH	0xFF000000
+#define BP_LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH	24
+
+#define HW_LCDIF_VDCTRL3	0xA0
+#define BM_LCDIF_VDCTRL3_VERTICAL_WAIT_CNT	0x0000FFFF
+#define BP_LCDIF_VDCTRL3_VERTICAL_WAIT_CNT	0
+#define BM_LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT	0x0FFF0000
+#define BP_LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT	16
+
+#define HW_LCDIF_VDCTRL4	0xB0
+#define BM_LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT	0x0003FFFF
+#define BP_LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT	0
+#define BM_LCDIF_VDCTRL4_SYNC_SIGNALS_ON	0x00040000
+
+#define HW_LCDIF_DVICTRL0	0xC0
+#define BM_LCDIF_DVICTRL0_V_LINES_CNT	0x000003FF
+#define BP_LCDIF_DVICTRL0_V_LINES_CNT	0
+#define BM_LCDIF_DVICTRL0_H_BLANKING_CNT	0x000FFC00
+#define BP_LCDIF_DVICTRL0_H_BLANKING_CNT	10
+#define BM_LCDIF_DVICTRL0_H_ACTIVE_CNT	0x7FF00000
+#define BP_LCDIF_DVICTRL0_H_ACTIVE_CNT	20
+
+#define HW_LCDIF_DVICTRL1	0xD0
+#define BM_LCDIF_DVICTRL1_F2_START_LINE	0x000003FF
+#define BP_LCDIF_DVICTRL1_F2_START_LINE	0
+#define BM_LCDIF_DVICTRL1_F1_END_LINE	0x000FFC00
+#define BP_LCDIF_DVICTRL1_F1_END_LINE	10
+#define BM_LCDIF_DVICTRL1_F1_START_LINE	0x3FF00000
+#define BP_LCDIF_DVICTRL1_F1_START_LINE	20
+
+#define HW_LCDIF_DVICTRL2	0xE0
+#define BM_LCDIF_DVICTRL2_V1_BLANK_END_LINE	0x000003FF
+#define BP_LCDIF_DVICTRL2_V1_BLANK_END_LINE	0
+#define BM_LCDIF_DVICTRL2_V1_BLANK_START_LINE	0x000FFC00
+#define BP_LCDIF_DVICTRL2_V1_BLANK_START_LINE	10
+#define BM_LCDIF_DVICTRL2_F2_END_LINE	0x3FF00000
+#define BP_LCDIF_DVICTRL2_F2_END_LINE	20
+
+#define HW_LCDIF_DVICTRL3	0xF0
+#define BM_LCDIF_DVICTRL3_V2_BLANK_END_LINE	0x000003FF
+#define BP_LCDIF_DVICTRL3_V2_BLANK_END_LINE	0
+#define BM_LCDIF_DVICTRL3_V2_BLANK_START_LINE	0x03FF0000
+#define BP_LCDIF_DVICTRL3_V2_BLANK_START_LINE	16
+
+#define HW_LCDIF_DVICTRL4	0x100
+#define BM_LCDIF_DVICTRL4_H_FILL_CNT	0x000000FF
+#define BP_LCDIF_DVICTRL4_H_FILL_CNT	0
+#define BM_LCDIF_DVICTRL4_CR_FILL_VALUE	0x0000FF00
+#define BP_LCDIF_DVICTRL4_CR_FILL_VALUE	8
+#define BM_LCDIF_DVICTRL4_CB_FILL_VALUE	0x00FF0000
+#define BP_LCDIF_DVICTRL4_CB_FILL_VALUE	16
+#define BM_LCDIF_DVICTRL4_Y_FILL_VALUE	0xFF000000
+#define BP_LCDIF_DVICTRL4_Y_FILL_VALUE	24
+
+#define HW_LCDIF_CSC_COEFF0	0x110
+#define BM_LCDIF_CSC_COEFF0_CSC_SUBSAMPLE_FILTER	0x00000003
+#define BP_LCDIF_CSC_COEFF0_CSC_SUBSAMPLE_FILTER	0
+#define BM_LCDIF_CSC_COEFF0_C0	0x03FF0000
+#define BP_LCDIF_CSC_COEFF0_C0	16
+
+#define HW_LCDIF_CSC_COEFF1	0x120
+#define BM_LCDIF_CSC_COEFF1_C1	0x000003FF
+#define BP_LCDIF_CSC_COEFF1_C1	0
+#define BM_LCDIF_CSC_COEFF1_C2	0x03FF0000
+#define BP_LCDIF_CSC_COEFF1_C2	16
+
+#define HW_LCDIF_CSC_COEFF2	0x130
+#define BM_LCDIF_CSC_COEFF2_C3	0x000003FF
+#define BP_LCDIF_CSC_COEFF2_C3	0
+#define BM_LCDIF_CSC_COEFF2_C4	0x03FF0000
+#define BP_LCDIF_CSC_COEFF2_C4	16
+
+#define HW_LCDIF_CSC_COEFF3	0x140
+#define BM_LCDIF_CSC_COEFF3_C5	0x000003FF
+#define BP_LCDIF_CSC_COEFF3_C5	0
+#define BM_LCDIF_CSC_COEFF3_C6	0x03FF0000
+#define BP_LCDIF_CSC_COEFF3_C6	16
+
+#define HW_LCDIF_CSC_COEFF4	0x150
+#define BM_LCDIF_CSC_COEFF4_C7	0x000003FF
+#define BP_LCDIF_CSC_COEFF4_C7	0
+#define BM_LCDIF_CSC_COEFF4_C8	0x03FF0000
+#define BP_LCDIF_CSC_COEFF4_C8	16
+
+#define HW_LCDIF_CSC_OFFSET	0x160
+#define BM_LCDIF_CSC_OFFSET_Y_OFFSET	0x000001FF
+#define BP_LCDIF_CSC_OFFSET_Y_OFFSET	0
+#define BM_LCDIF_CSC_OFFSET_CBCR_OFFSET	0x01FF0000
+#define BP_LCDIF_CSC_OFFSET_CBCR_OFFSET	16
+
+#define HW_LCDIF_CSC_LIMIT	0x170
+#define BM_LCDIF_CSC_LIMIT_Y_MAX	0x000000FF
+#define BP_LCDIF_CSC_LIMIT_Y_MAX	0
+#define BM_LCDIF_CSC_LIMIT_Y_MIN	0x0000FF00
+#define BP_LCDIF_CSC_LIMIT_Y_MIN	8
+#define BM_LCDIF_CSC_LIMIT_CBCR_MAX	0x00FF0000
+#define BP_LCDIF_CSC_LIMIT_CBCR_MAX	16
+#define BM_LCDIF_CSC_LIMIT_CBCR_MIN	0xFF000000
+#define BP_LCDIF_CSC_LIMIT_CBCR_MIN	24
+
+#define HW_LCDIF_STAT		0x1D0
+#define BM_LCDIF_STAT_TXFIFO_EMPTY	0x04000000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-lradc.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-lradc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-lradc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-lradc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * stmp378x: LRADC register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_LRADC_BASE	(STMP3XXX_REGS_BASE + 0x50000)
+#define REGS_LRADC_PHYS	0x80050000
+#define REGS_LRADC_SIZE	0x2000
+
+#define HW_LRADC_CTRL0		0x0
+#define BM_LRADC_CTRL0_SCHEDULE	0x000000FF
+#define BP_LRADC_CTRL0_SCHEDULE	0
+#define BM_LRADC_CTRL0_XPLUS_ENABLE	0x00010000
+#define BM_LRADC_CTRL0_YPLUS_ENABLE	0x00020000
+#define BM_LRADC_CTRL0_XMINUS_ENABLE	0x00040000
+#define BM_LRADC_CTRL0_YMINUS_ENABLE	0x00080000
+#define BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE	0x00100000
+#define BM_LRADC_CTRL0_ONCHIP_GROUNDREF	0x00200000
+#define BM_LRADC_CTRL0_CLKGATE	0x40000000
+#define BM_LRADC_CTRL0_SFTRST	0x80000000
+
+#define HW_LRADC_CTRL1		0x10
+#define BM_LRADC_CTRL1_LRADC0_IRQ	0x00000001
+#define BP_LRADC_CTRL1_LRADC0_IRQ	0
+#define BM_LRADC_CTRL1_LRADC5_IRQ	0x00000020
+#define BM_LRADC_CTRL1_LRADC6_IRQ	0x00000040
+#define BM_LRADC_CTRL1_TOUCH_DETECT_IRQ	0x00000100
+#define BM_LRADC_CTRL1_LRADC0_IRQ_EN	0x00010000
+#define BM_LRADC_CTRL1_LRADC5_IRQ_EN	0x00200000
+#define BM_LRADC_CTRL1_TOUCH_DETECT_IRQ_EN	0x01000000
+
+#define HW_LRADC_CTRL2		0x20
+#define BM_LRADC_CTRL2_BL_BRIGHTNESS	0x001F0000
+#define BP_LRADC_CTRL2_BL_BRIGHTNESS	16
+#define BM_LRADC_CTRL2_BL_MUX_SELECT	0x00200000
+#define BM_LRADC_CTRL2_BL_ENABLE	0x00400000
+#define BM_LRADC_CTRL2_DIVIDE_BY_TWO	0xFF000000
+#define BP_LRADC_CTRL2_DIVIDE_BY_TWO	24
+
+#define HW_LRADC_CTRL3		0x30
+#define BM_LRADC_CTRL3_CYCLE_TIME	0x00000300
+#define BP_LRADC_CTRL3_CYCLE_TIME	8
+
+#define HW_LRADC_STATUS		0x40
+#define BM_LRADC_STATUS_TOUCH_DETECT_RAW	0x00000001
+#define BP_LRADC_STATUS_TOUCH_DETECT_RAW	0
+
+#define HW_LRADC_CH0		(0x50 + 0 * 0x10)
+#define HW_LRADC_CH1		(0x50 + 1 * 0x10)
+#define HW_LRADC_CH2		(0x50 + 2 * 0x10)
+#define HW_LRADC_CH3		(0x50 + 3 * 0x10)
+#define HW_LRADC_CH4		(0x50 + 4 * 0x10)
+#define HW_LRADC_CH5		(0x50 + 5 * 0x10)
+#define HW_LRADC_CH6		(0x50 + 6 * 0x10)
+#define HW_LRADC_CH7		(0x50 + 7 * 0x10)
+
+#define HW_LRADC_CHn		0x50
+#define BM_LRADC_CHn_VALUE	0x0003FFFF
+#define BP_LRADC_CHn_VALUE	0
+#define BM_LRADC_CHn_NUM_SAMPLES	0x1F000000
+#define BP_LRADC_CHn_NUM_SAMPLES	24
+#define BM_LRADC_CHn_ACCUMULATE	0x20000000
+
+#define HW_LRADC_DELAY0		(0xD0 + 0 * 0x10)
+#define HW_LRADC_DELAY1		(0xD0 + 1 * 0x10)
+#define HW_LRADC_DELAY2		(0xD0 + 2 * 0x10)
+#define HW_LRADC_DELAY3		(0xD0 + 3 * 0x10)
+
+#define HW_LRADC_DELAYn		0xD0
+#define BM_LRADC_DELAYn_DELAY	0x000007FF
+#define BP_LRADC_DELAYn_DELAY	0
+#define BM_LRADC_DELAYn_LOOP_COUNT	0x0000F800
+#define BP_LRADC_DELAYn_LOOP_COUNT	11
+#define BM_LRADC_DELAYn_TRIGGER_DELAYS	0x000F0000
+#define BP_LRADC_DELAYn_TRIGGER_DELAYS	16
+#define BM_LRADC_DELAYn_KICK	0x00100000
+#define BM_LRADC_DELAYn_TRIGGER_LRADCS	0xFF000000
+#define BP_LRADC_DELAYn_TRIGGER_LRADCS	24
+
+#define HW_LRADC_CTRL4		0x140
+#define BM_LRADC_CTRL4_LRADC6SELECT	0x0F000000
+#define BP_LRADC_CTRL4_LRADC6SELECT	24
+#define BM_LRADC_CTRL4_LRADC7SELECT	0xF0000000
+#define BP_LRADC_CTRL4_LRADC7SELECT	28
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ocotp.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ocotp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ocotp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ocotp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * stmp378x: OCOTP register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_OCOTP_BASE	(STMP3XXX_REGS_BASE + 0x2C000)
+#define REGS_OCOTP_PHYS	0x8002C000
+#define REGS_OCOTP_SIZE	0x2000
+
+#define HW_OCOTP_CTRL		0x0
+#define BM_OCOTP_CTRL_BUSY	0x00000100
+#define BM_OCOTP_CTRL_ERROR	0x00000200
+#define BM_OCOTP_CTRL_RD_BANK_OPEN	0x00001000
+#define BM_OCOTP_CTRL_RELOAD_SHADOWS	0x00002000
+#define BM_OCOTP_CTRL_WR_UNLOCK	0xFFFF0000
+#define BP_OCOTP_CTRL_WR_UNLOCK	16
+
+#define HW_OCOTP_DATA		0x10
+
+#define HW_OCOTP_CUST0		(0x20 + 0 * 0x10)
+#define HW_OCOTP_CUST1		(0x20 + 1 * 0x10)
+#define HW_OCOTP_CUST2		(0x20 + 2 * 0x10)
+#define HW_OCOTP_CUST3		(0x20 + 3 * 0x10)
+
+#define HW_OCOTP_CUSTn		0x20
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-pinctrl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,90 @@
+/*
+ * stmp378x: PINCTRL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_PINCTRL
+#define _MACH_REGS_PINCTRL
+
+#define REGS_PINCTRL_BASE	(STMP3XXX_REGS_BASE + 0x18000)
+#define REGS_PINCTRL_PHYS	0x80018000
+#define REGS_PINCTRL_SIZE	0x2000
+
+#define HW_PINCTRL_MUXSEL0	0x100
+#define HW_PINCTRL_MUXSEL1	0x110
+#define HW_PINCTRL_MUXSEL2	0x120
+#define HW_PINCTRL_MUXSEL3	0x130
+#define HW_PINCTRL_MUXSEL4	0x140
+#define HW_PINCTRL_MUXSEL5	0x150
+#define HW_PINCTRL_MUXSEL6	0x160
+#define HW_PINCTRL_MUXSEL7	0x170
+
+#define HW_PINCTRL_DRIVE0	0x200
+#define HW_PINCTRL_DRIVE1	0x210
+#define HW_PINCTRL_DRIVE2	0x220
+#define HW_PINCTRL_DRIVE3	0x230
+#define HW_PINCTRL_DRIVE4	0x240
+#define HW_PINCTRL_DRIVE5	0x250
+#define HW_PINCTRL_DRIVE6	0x260
+#define HW_PINCTRL_DRIVE7	0x270
+#define HW_PINCTRL_DRIVE8	0x280
+#define HW_PINCTRL_DRIVE9	0x290
+#define HW_PINCTRL_DRIVE10	0x2A0
+#define HW_PINCTRL_DRIVE11	0x2B0
+#define HW_PINCTRL_DRIVE12	0x2C0
+#define HW_PINCTRL_DRIVE13	0x2D0
+#define HW_PINCTRL_DRIVE14	0x2E0
+
+#define HW_PINCTRL_PULL0	0x400
+#define HW_PINCTRL_PULL1	0x410
+#define HW_PINCTRL_PULL2	0x420
+#define HW_PINCTRL_PULL3	0x430
+
+#define HW_PINCTRL_DOUT0	0x500
+#define HW_PINCTRL_DOUT1	0x510
+#define HW_PINCTRL_DOUT2	0x520
+
+#define HW_PINCTRL_DIN0		0x600
+#define HW_PINCTRL_DIN1		0x610
+#define HW_PINCTRL_DIN2		0x620
+
+#define HW_PINCTRL_DOE0		0x700
+#define HW_PINCTRL_DOE1		0x710
+#define HW_PINCTRL_DOE2		0x720
+
+#define HW_PINCTRL_PIN2IRQ0	0x800
+#define HW_PINCTRL_PIN2IRQ1	0x810
+#define HW_PINCTRL_PIN2IRQ2	0x820
+
+#define HW_PINCTRL_IRQEN0	0x900
+#define HW_PINCTRL_IRQEN1	0x910
+#define HW_PINCTRL_IRQEN2	0x920
+
+#define HW_PINCTRL_IRQLEVEL0	0xA00
+#define HW_PINCTRL_IRQLEVEL1	0xA10
+#define HW_PINCTRL_IRQLEVEL2	0xA20
+
+#define HW_PINCTRL_IRQPOL0	0xB00
+#define HW_PINCTRL_IRQPOL1	0xB10
+#define HW_PINCTRL_IRQPOL2	0xB20
+
+#define HW_PINCTRL_IRQSTAT0	0xC00
+#define HW_PINCTRL_IRQSTAT1	0xC10
+#define HW_PINCTRL_IRQSTAT2	0xC20
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-power.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-power.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-power.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-power.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * stmp378x: POWER register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_POWER
+#define _MACH_REGS_POWER
+
+#define REGS_POWER_BASE	(STMP3XXX_REGS_BASE + 0x44000)
+#define REGS_POWER_PHYS	0x80044000
+#define REGS_POWER_SIZE	0x2000
+
+#define HW_POWER_CTRL		0x0
+#define BM_POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO	0x00000001
+#define BP_POWER_CTRL_ENIRQ_VDD5V_GT_VDDIO	0
+#define BM_POWER_CTRL_ENIRQ_PSWITCH	0x00020000
+#define BM_POWER_CTRL_PSWITCH_IRQ	0x00100000
+#define BM_POWER_CTRL_CLKGATE	0x40000000
+
+#define HW_POWER_5VCTRL		0x10
+#define BM_POWER_5VCTRL_ENABLE_LINREG_ILIMIT	0x00000040
+
+#define HW_POWER_MINPWR		0x20
+
+#define HW_POWER_CHARGE		0x30
+
+#define HW_POWER_VDDDCTRL	0x40
+
+#define HW_POWER_VDDACTRL	0x50
+
+#define HW_POWER_VDDIOCTRL	0x60
+#define BM_POWER_VDDIOCTRL_TRG	0x0000001F
+#define BP_POWER_VDDIOCTRL_TRG	0
+
+#define HW_POWER_STS		0xC0
+#define BM_POWER_STS_VBUSVALID	0x00000002
+#define BM_POWER_STS_BVALID	0x00000004
+#define BM_POWER_STS_AVALID	0x00000008
+#define BM_POWER_STS_DC_OK	0x00000200
+
+#define HW_POWER_RESET		0x100
+
+#define HW_POWER_DEBUG		0x110
+#define BM_POWER_DEBUG_BVALIDPIOLOCK	0x00000002
+#define BM_POWER_DEBUG_AVALIDPIOLOCK	0x00000004
+#define BM_POWER_DEBUG_VBUSVALIDPIOLOCK	0x00000008
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-pwm.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-pwm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-pwm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-pwm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * stmp378x: PWM register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_PWM_BASE	(STMP3XXX_REGS_BASE + 0x64000)
+#define REGS_PWM_PHYS	0x80064000
+#define REGS_PWM_SIZE	0x2000
+
+#define HW_PWM_CTRL		0x0
+#define BM_PWM_CTRL_PWM2_ENABLE	0x00000004
+#define BM_PWM_CTRL_PWM2_ANA_CTRL_ENABLE	0x00000020
+
+#define HW_PWM_ACTIVE0		(0x10 + 0 * 0x20)
+#define HW_PWM_ACTIVE1		(0x10 + 1 * 0x20)
+#define HW_PWM_ACTIVE2		(0x10 + 2 * 0x20)
+#define HW_PWM_ACTIVE3		(0x10 + 3 * 0x20)
+
+#define HW_PWM_ACTIVEn		0x10
+#define BM_PWM_ACTIVEn_ACTIVE	0x0000FFFF
+#define BP_PWM_ACTIVEn_ACTIVE	0
+#define BM_PWM_ACTIVEn_INACTIVE	0xFFFF0000
+#define BP_PWM_ACTIVEn_INACTIVE	16
+
+#define HW_PWM_PERIOD0		(0x20 + 0 * 0x20)
+#define HW_PWM_PERIOD1		(0x20 + 1 * 0x20)
+#define HW_PWM_PERIOD2		(0x20 + 2 * 0x20)
+#define HW_PWM_PERIOD3		(0x20 + 3 * 0x20)
+
+#define HW_PWM_PERIODn		0x20
+#define BM_PWM_PERIODn_PERIOD	0x0000FFFF
+#define BP_PWM_PERIODn_PERIOD	0
+#define BM_PWM_PERIODn_ACTIVE_STATE	0x00030000
+#define BP_PWM_PERIODn_ACTIVE_STATE	16
+#define BM_PWM_PERIODn_INACTIVE_STATE	0x000C0000
+#define BP_PWM_PERIODn_INACTIVE_STATE	18
+#define BM_PWM_PERIODn_CDIV	0x00700000
+#define BP_PWM_PERIODn_CDIV	20
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-pxp.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-pxp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-pxp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-pxp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,140 @@
+/*
+ * stmp378x: PXP register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_PXP_BASE	(STMP3XXX_REGS_BASE + 0x2A000)
+#define REGS_PXP_PHYS	0x8002A000
+#define REGS_PXP_SIZE	0x2000
+
+#define HW_PXP_CTRL		0x0
+#define BM_PXP_CTRL_ENABLE	0x00000001
+#define BP_PXP_CTRL_ENABLE	0
+#define BM_PXP_CTRL_IRQ_ENABLE	0x00000002
+#define BM_PXP_CTRL_OUTPUT_RGB_FORMAT	0x000000F0
+#define BP_PXP_CTRL_OUTPUT_RGB_FORMAT	4
+#define BM_PXP_CTRL_ROTATE	0x00000300
+#define BP_PXP_CTRL_ROTATE	8
+#define BM_PXP_CTRL_HFLIP	0x00000400
+#define BM_PXP_CTRL_VFLIP	0x00000800
+#define BM_PXP_CTRL_S0_FORMAT	0x0000F000
+#define BP_PXP_CTRL_S0_FORMAT	12
+#define BM_PXP_CTRL_SCALE	0x00040000
+#define BM_PXP_CTRL_CROP	0x00080000
+
+#define HW_PXP_STAT		0x10
+#define BM_PXP_STAT_IRQ		0x00000001
+#define BP_PXP_STAT_IRQ		0
+
+#define HW_PXP_RGBBUF		0x20
+
+#define HW_PXP_RGBSIZE		0x40
+#define BM_PXP_RGBSIZE_HEIGHT	0x00000FFF
+#define BP_PXP_RGBSIZE_HEIGHT	0
+#define BM_PXP_RGBSIZE_WIDTH	0x00FFF000
+#define BP_PXP_RGBSIZE_WIDTH	12
+
+#define HW_PXP_S0BUF		0x50
+
+#define HW_PXP_S0UBUF		0x60
+
+#define HW_PXP_S0VBUF		0x70
+
+#define HW_PXP_S0PARAM		0x80
+#define BM_PXP_S0PARAM_HEIGHT	0x000000FF
+#define BP_PXP_S0PARAM_HEIGHT	0
+#define BM_PXP_S0PARAM_WIDTH	0x0000FF00
+#define BP_PXP_S0PARAM_WIDTH	8
+#define BM_PXP_S0PARAM_YBASE	0x00FF0000
+#define BP_PXP_S0PARAM_YBASE	16
+#define BM_PXP_S0PARAM_XBASE	0xFF000000
+#define BP_PXP_S0PARAM_XBASE	24
+
+#define HW_PXP_S0BACKGROUND	0x90
+
+#define HW_PXP_S0CROP		0xA0
+#define BM_PXP_S0CROP_HEIGHT	0x000000FF
+#define BP_PXP_S0CROP_HEIGHT	0
+#define BM_PXP_S0CROP_WIDTH	0x0000FF00
+#define BP_PXP_S0CROP_WIDTH	8
+#define BM_PXP_S0CROP_YBASE	0x00FF0000
+#define BP_PXP_S0CROP_YBASE	16
+#define BM_PXP_S0CROP_XBASE	0xFF000000
+#define BP_PXP_S0CROP_XBASE	24
+
+#define HW_PXP_S0SCALE		0xB0
+#define BM_PXP_S0SCALE_XSCALE	0x00003FFF
+#define BP_PXP_S0SCALE_XSCALE	0
+#define BM_PXP_S0SCALE_YSCALE	0x3FFF0000
+#define BP_PXP_S0SCALE_YSCALE	16
+
+#define HW_PXP_CSCCOEFF0	0xD0
+
+#define HW_PXP_CSCCOEFF1	0xE0
+
+#define HW_PXP_CSCCOEFF2	0xF0
+
+#define HW_PXP_S0COLORKEYLOW	0x180
+
+#define HW_PXP_S0COLORKEYHIGH	0x190
+
+#define HW_PXP_OL0		(0x200 + 0 * 0x40)
+#define HW_PXP_OL1		(0x200 + 1 * 0x40)
+#define HW_PXP_OL2		(0x200 + 2 * 0x40)
+#define HW_PXP_OL3		(0x200 + 3 * 0x40)
+#define HW_PXP_OL4		(0x200 + 4 * 0x40)
+#define HW_PXP_OL5		(0x200 + 5 * 0x40)
+#define HW_PXP_OL6		(0x200 + 6 * 0x40)
+#define HW_PXP_OL7		(0x200 + 7 * 0x40)
+
+#define HW_PXP_OLn		0x200
+
+#define HW_PXP_OL0SIZE		(0x210 + 0 * 0x40)
+#define HW_PXP_OL1SIZE		(0x210 + 1 * 0x40)
+#define HW_PXP_OL2SIZE		(0x210 + 2 * 0x40)
+#define HW_PXP_OL3SIZE		(0x210 + 3 * 0x40)
+#define HW_PXP_OL4SIZE		(0x210 + 4 * 0x40)
+#define HW_PXP_OL5SIZE		(0x210 + 5 * 0x40)
+#define HW_PXP_OL6SIZE		(0x210 + 6 * 0x40)
+#define HW_PXP_OL7SIZE		(0x210 + 7 * 0x40)
+
+#define HW_PXP_OLnSIZE		0x210
+#define BM_PXP_OLnSIZE_HEIGHT	0x000000FF
+#define BP_PXP_OLnSIZE_HEIGHT	0
+#define BM_PXP_OLnSIZE_WIDTH	0x0000FF00
+#define BP_PXP_OLnSIZE_WIDTH	8
+
+#define HW_PXP_OL0PARAM		(0x220 + 0 * 0x40)
+#define HW_PXP_OL1PARAM		(0x220 + 1 * 0x40)
+#define HW_PXP_OL2PARAM		(0x220 + 2 * 0x40)
+#define HW_PXP_OL3PARAM		(0x220 + 3 * 0x40)
+#define HW_PXP_OL4PARAM		(0x220 + 4 * 0x40)
+#define HW_PXP_OL5PARAM		(0x220 + 5 * 0x40)
+#define HW_PXP_OL6PARAM		(0x220 + 6 * 0x40)
+#define HW_PXP_OL7PARAM		(0x220 + 7 * 0x40)
+
+#define HW_PXP_OLnPARAM		0x220
+#define BM_PXP_OLnPARAM_ENABLE	0x00000001
+#define BP_PXP_OLnPARAM_ENABLE	0
+#define BM_PXP_OLnPARAM_ALPHA_CNTL	0x00000006
+#define BP_PXP_OLnPARAM_ALPHA_CNTL	1
+#define BM_PXP_OLnPARAM_ENABLE_COLORKEY	0x00000008
+#define BM_PXP_OLnPARAM_FORMAT	0x000000F0
+#define BP_PXP_OLnPARAM_FORMAT	4
+#define BM_PXP_OLnPARAM_ALPHA	0x0000FF00
+#define BP_PXP_OLnPARAM_ALPHA	8
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-rtc.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-rtc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-rtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-rtc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * stmp378x: RTC register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_RTC_BASE	(STMP3XXX_REGS_BASE + 0x5C000)
+#define REGS_RTC_PHYS	0x8005C000
+#define REGS_RTC_SIZE	0x2000
+
+#define HW_RTC_CTRL		0x0
+#define BM_RTC_CTRL_ALARM_IRQ_EN	0x00000001
+#define BP_RTC_CTRL_ALARM_IRQ_EN	0
+#define BM_RTC_CTRL_ONEMSEC_IRQ_EN	0x00000002
+#define BM_RTC_CTRL_ALARM_IRQ	0x00000004
+#define BM_RTC_CTRL_ONEMSEC_IRQ	0x00000008
+#define BM_RTC_CTRL_WATCHDOGEN	0x00000010
+
+#define HW_RTC_STAT		0x10
+#define BM_RTC_STAT_NEW_REGS	0x0000FF00
+#define BP_RTC_STAT_NEW_REGS	8
+#define BM_RTC_STAT_STALE_REGS	0x00FF0000
+#define BP_RTC_STAT_STALE_REGS	16
+#define BM_RTC_STAT_RTC_PRESENT	0x80000000
+
+#define HW_RTC_SECONDS		0x30
+
+#define HW_RTC_ALARM		0x40
+
+#define HW_RTC_WATCHDOG		0x50
+
+#define HW_RTC_PERSISTENT0	0x60
+#define BM_RTC_PERSISTENT0_ALARM_WAKE_EN	0x00000002
+#define BM_RTC_PERSISTENT0_ALARM_EN	0x00000004
+#define BM_RTC_PERSISTENT0_XTAL24MHZ_PWRUP	0x00000010
+#define BM_RTC_PERSISTENT0_XTAL32KHZ_PWRUP	0x00000020
+#define BM_RTC_PERSISTENT0_ALARM_WAKE	0x00000080
+#define BM_RTC_PERSISTENT0_SPARE_ANALOG	0xFFFC0000
+#define BP_RTC_PERSISTENT0_SPARE_ANALOG	18
+
+#define HW_RTC_PERSISTENT1	0x70
+#define BM_RTC_PERSISTENT1_GENERAL	0xFFFFFFFF
+#define BP_RTC_PERSISTENT1_GENERAL	0
+
+#define HW_RTC_VERSION		0xD0
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-saif.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-saif.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-saif.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-saif.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ * stmp378x: SAIF register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_SAIF_SIZE	0x2000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-spdif.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-spdif.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-spdif.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-spdif.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * stmp378x: SPDIF register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_SPDIF_BASE	(STMP3XXX_REGS_BASE + 0x54000)
+#define REGS_SPDIF_PHYS	0x80054000
+#define REGS_SPDIF_SIZE	0x2000
+
+#define HW_SPDIF_CTRL		0x0
+#define BM_SPDIF_CTRL_RUN	0x00000001
+#define BP_SPDIF_CTRL_RUN	0
+#define BM_SPDIF_CTRL_FIFO_ERROR_IRQ_EN	0x00000002
+#define BM_SPDIF_CTRL_FIFO_OVERFLOW_IRQ	0x00000004
+#define BM_SPDIF_CTRL_FIFO_UNDERFLOW_IRQ	0x00000008
+#define BM_SPDIF_CTRL_WORD_LENGTH	0x00000010
+#define BM_SPDIF_CTRL_CLKGATE	0x40000000
+#define BM_SPDIF_CTRL_SFTRST	0x80000000
+
+#define HW_SPDIF_STAT		0x10
+
+#define HW_SPDIF_FRAMECTRL	0x20
+
+#define HW_SPDIF_SRR		0x30
+#define BM_SPDIF_SRR_RATE	0x000FFFFF
+#define BP_SPDIF_SRR_RATE	0
+#define BM_SPDIF_SRR_BASEMULT	0x70000000
+#define BP_SPDIF_SRR_BASEMULT	28
+
+#define HW_SPDIF_DEBUG		0x40
+
+#define HW_SPDIF_DATA		0x50
+
+#define HW_SPDIF_VERSION	0x60
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ssp.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ssp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-ssp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-ssp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * stmp378x: SSP register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_SSP1_BASE	(STMP3XXX_REGS_BASE + 0x10000)
+#define REGS_SSP1_PHYS	0x80010000
+#define REGS_SSP2_BASE	(STMP3XXX_REGS_BASE + 0x34000)
+#define REGS_SSP2_PHYS	0x80034000
+#define REGS_SSP_SIZE	0x2000
+
+#define HW_SSP_CTRL0		0x0
+#define BM_SSP_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_SSP_CTRL0_XFER_COUNT	0
+#define BM_SSP_CTRL0_ENABLE	0x00010000
+#define BM_SSP_CTRL0_GET_RESP	0x00020000
+#define BM_SSP_CTRL0_LONG_RESP	0x00080000
+#define BM_SSP_CTRL0_WAIT_FOR_CMD	0x00100000
+#define BM_SSP_CTRL0_WAIT_FOR_IRQ	0x00200000
+#define BM_SSP_CTRL0_BUS_WIDTH	0x00C00000
+#define BP_SSP_CTRL0_BUS_WIDTH	22
+#define BM_SSP_CTRL0_DATA_XFER	0x01000000
+#define BM_SSP_CTRL0_READ	0x02000000
+#define BM_SSP_CTRL0_IGNORE_CRC	0x04000000
+#define BM_SSP_CTRL0_LOCK_CS	0x08000000
+#define BM_SSP_CTRL0_RUN	0x20000000
+#define BM_SSP_CTRL0_CLKGATE	0x40000000
+#define BM_SSP_CTRL0_SFTRST	0x80000000
+
+#define HW_SSP_CMD0		0x10
+#define BM_SSP_CMD0_CMD		0x000000FF
+#define BP_SSP_CMD0_CMD		0
+#define BM_SSP_CMD0_BLOCK_COUNT	0x0000FF00
+#define BP_SSP_CMD0_BLOCK_COUNT	8
+#define BM_SSP_CMD0_BLOCK_SIZE	0x000F0000
+#define BP_SSP_CMD0_BLOCK_SIZE	16
+#define BM_SSP_CMD0_APPEND_8CYC	0x00100000
+#define BM_SSP_CMD1_CMD_ARG	0xFFFFFFFF
+#define BP_SSP_CMD1_CMD_ARG	0
+
+#define HW_SSP_TIMING		0x50
+#define BM_SSP_TIMING_CLOCK_RATE	0x000000FF
+#define BP_SSP_TIMING_CLOCK_RATE	0
+#define BM_SSP_TIMING_CLOCK_DIVIDE	0x0000FF00
+#define BP_SSP_TIMING_CLOCK_DIVIDE	8
+#define BM_SSP_TIMING_TIMEOUT	0xFFFF0000
+#define BP_SSP_TIMING_TIMEOUT	16
+
+#define HW_SSP_CTRL1		0x60
+#define BM_SSP_CTRL1_SSP_MODE	0x0000000F
+#define BP_SSP_CTRL1_SSP_MODE	0
+#define BM_SSP_CTRL1_WORD_LENGTH	0x000000F0
+#define BP_SSP_CTRL1_WORD_LENGTH	4
+#define BM_SSP_CTRL1_POLARITY	0x00000200
+#define BM_SSP_CTRL1_PHASE	0x00000400
+#define BM_SSP_CTRL1_DMA_ENABLE	0x00002000
+#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ	0x00008000
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN	0x00010000
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ	0x00020000
+#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ	0x00200000
+#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN	0x00400000
+#define BM_SSP_CTRL1_DATA_CRC_IRQ	0x00800000
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN	0x01000000
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ	0x02000000
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN	0x04000000
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	0x08000000
+#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN	0x10000000
+#define BM_SSP_CTRL1_RESP_ERR_IRQ	0x20000000
+#define BM_SSP_CTRL1_SDIO_IRQ	0x80000000
+
+#define HW_SSP_DATA		0x70
+
+#define HW_SSP_SDRESP0		0x80
+
+#define HW_SSP_SDRESP1		0x90
+
+#define HW_SSP_SDRESP2		0xA0
+
+#define HW_SSP_SDRESP3		0xB0
+
+#define HW_SSP_STATUS		0xC0
+#define BM_SSP_STATUS_FIFO_EMPTY	0x00000020
+#define BM_SSP_STATUS_TIMEOUT	0x00001000
+#define BM_SSP_STATUS_RESP_TIMEOUT	0x00004000
+#define BM_SSP_STATUS_RESP_ERR	0x00008000
+#define BM_SSP_STATUS_RESP_CRC_ERR	0x00010000
+#define BM_SSP_STATUS_CARD_DETECT	0x10000000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-sydma.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-sydma.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-sydma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-sydma.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * stmp378x: SYDMA register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_SYDMA_BASE	(STMP3XXX_REGS_BASE + 0x26000)
+#define REGS_SYDMA_PHYS	0x80026000
+#define REGS_SYDMA_SIZE	0x2000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-timrot.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-timrot.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-timrot.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-timrot.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * stmp378x: TIMROT register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_TIMROT
+#define _MACH_REGS_TIMROT
+
+#define REGS_TIMROT_BASE	(STMP3XXX_REGS_BASE + 0x68000)
+#define REGS_TIMROT_PHYS	0x80068000
+#define REGS_TIMROT_SIZE	0x2000
+
+#define HW_TIMROT_ROTCTRL	0x0
+#define BM_TIMROT_ROTCTRL_SELECT_A	0x00000007
+#define BP_TIMROT_ROTCTRL_SELECT_A	0
+#define BM_TIMROT_ROTCTRL_SELECT_B	0x00000070
+#define BP_TIMROT_ROTCTRL_SELECT_B	4
+#define BM_TIMROT_ROTCTRL_POLARITY_A	0x00000100
+#define BM_TIMROT_ROTCTRL_POLARITY_B	0x00000200
+#define BM_TIMROT_ROTCTRL_OVERSAMPLE	0x00000C00
+#define BP_TIMROT_ROTCTRL_OVERSAMPLE	10
+#define BM_TIMROT_ROTCTRL_RELATIVE	0x00001000
+#define BM_TIMROT_ROTCTRL_DIVIDER	0x003F0000
+#define BP_TIMROT_ROTCTRL_DIVIDER	16
+#define BM_TIMROT_ROTCTRL_ROTARY_PRESENT	0x20000000
+#define BM_TIMROT_ROTCTRL_CLKGATE	0x40000000
+#define BM_TIMROT_ROTCTRL_SFTRST	0x80000000
+
+#define HW_TIMROT_ROTCOUNT	0x10
+#define BM_TIMROT_ROTCOUNT_UPDOWN	0x0000FFFF
+#define BP_TIMROT_ROTCOUNT_UPDOWN	0
+
+#define HW_TIMROT_TIMCTRL0	(0x20 + 0 * 0x20)
+#define HW_TIMROT_TIMCTRL1	(0x20 + 1 * 0x20)
+#define HW_TIMROT_TIMCTRL2	(0x20 + 2 * 0x20)
+
+#define HW_TIMROT_TIMCTRLn	0x20
+#define BM_TIMROT_TIMCTRLn_SELECT	0x0000000F
+#define BP_TIMROT_TIMCTRLn_SELECT	0
+#define BM_TIMROT_TIMCTRLn_PRESCALE	0x00000030
+#define BP_TIMROT_TIMCTRLn_PRESCALE	4
+#define BM_TIMROT_TIMCTRLn_RELOAD	0x00000040
+#define BM_TIMROT_TIMCTRLn_UPDATE	0x00000080
+#define BM_TIMROT_TIMCTRLn_IRQ_EN	0x00004000
+#define BM_TIMROT_TIMCTRLn_IRQ	0x00008000
+
+#define HW_TIMROT_TIMCOUNT0	(0x30 + 0 * 0x20)
+#define HW_TIMROT_TIMCOUNT1	(0x30 + 1 * 0x20)
+#define HW_TIMROT_TIMCOUNT2	(0x30 + 2 * 0x20)
+
+#define HW_TIMROT_TIMCOUNTn	0x30
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-tvenc.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-tvenc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-tvenc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-tvenc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+ * stmp378x: TVENC register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_TVENC_BASE	(STMP3XXX_REGS_BASE + 0x38000)
+#define REGS_TVENC_PHYS	0x80038000
+#define REGS_TVENC_SIZE	0x2000
+
+#define HW_TVENC_CTRL		0x0
+#define BM_TVENC_CTRL_CLKGATE	0x40000000
+#define BM_TVENC_CTRL_SFTRST	0x80000000
+
+#define HW_TVENC_CONFIG		0x10
+#define BM_TVENC_CONFIG_ENCD_MODE	0x00000007
+#define BP_TVENC_CONFIG_ENCD_MODE	0
+#define BM_TVENC_CONFIG_SYNC_MODE	0x00000070
+#define BP_TVENC_CONFIG_SYNC_MODE	4
+#define BM_TVENC_CONFIG_FSYNC_PHS	0x00000200
+#define BM_TVENC_CONFIG_CGAIN	0x0000C000
+#define BP_TVENC_CONFIG_CGAIN	14
+#define BM_TVENC_CONFIG_YGAIN_SEL	0x00030000
+#define BP_TVENC_CONFIG_YGAIN_SEL	16
+#define BM_TVENC_CONFIG_PAL_SHAPE	0x00100000
+
+#define HW_TVENC_SYNCOFFSET	0x30
+
+#define HW_TVENC_COLORSUB0	0xC0
+
+#define HW_TVENC_COLORBURST	0x140
+#define BM_TVENC_COLORBURST_PBA	0x00FF0000
+#define BP_TVENC_COLORBURST_PBA	16
+#define BM_TVENC_COLORBURST_NBA	0xFF000000
+#define BP_TVENC_COLORBURST_NBA	24
+
+#define HW_TVENC_MACROVISION0	0x150
+
+#define HW_TVENC_MACROVISION1	0x160
+
+#define HW_TVENC_MACROVISION2	0x170
+
+#define HW_TVENC_MACROVISION3	0x180
+
+#define HW_TVENC_MACROVISION4	0x190
+
+#define HW_TVENC_DACCTRL	0x1A0
+#define BM_TVENC_DACCTRL_RVAL	0x00000070
+#define BP_TVENC_DACCTRL_RVAL	4
+#define BM_TVENC_DACCTRL_DUMP_TOVDD1	0x00000100
+#define BM_TVENC_DACCTRL_PWRUP1	0x00001000
+#define BM_TVENC_DACCTRL_GAINUP	0x00040000
+#define BM_TVENC_DACCTRL_GAINDN	0x00080000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartapp.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartapp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartapp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartapp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+ * stmp378x: UARTAPP register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_UARTAPP1_BASE	(STMP3XXX_REGS_BASE + 0x6C000)
+#define REGS_UARTAPP1_PHYS	0x8006C000
+#define REGS_UARTAPP2_BASE	(STMP3XXX_REGS_BASE + 0x6E000)
+#define REGS_UARTAPP2_PHYS	0x8006E000
+#define REGS_UARTAPP_SIZE	0x2000
+
+#define HW_UARTAPP_CTRL0	0x0
+#define BM_UARTAPP_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_UARTAPP_CTRL0_XFER_COUNT	0
+#define BM_UARTAPP_CTRL0_RXTIMEOUT	0x07FF0000
+#define BP_UARTAPP_CTRL0_RXTIMEOUT	16
+#define BM_UARTAPP_CTRL0_RXTO_ENABLE	0x08000000
+#define BM_UARTAPP_CTRL0_RUN	0x20000000
+#define BM_UARTAPP_CTRL0_SFTRST	0x80000000
+#define BM_UARTAPP_CTRL1_XFER_COUNT	0x0000FFFF
+#define BP_UARTAPP_CTRL1_XFER_COUNT	0
+#define BM_UARTAPP_CTRL1_RUN	0x10000000
+
+#define HW_UARTAPP_CTRL2	0x20
+#define BM_UARTAPP_CTRL2_UARTEN	0x00000001
+#define BP_UARTAPP_CTRL2_UARTEN	0
+#define BM_UARTAPP_CTRL2_TXE	0x00000100
+#define BM_UARTAPP_CTRL2_RXE	0x00000200
+#define BM_UARTAPP_CTRL2_RTS	0x00000800
+#define BM_UARTAPP_CTRL2_RTSEN	0x00004000
+#define BM_UARTAPP_CTRL2_CTSEN	0x00008000
+#define BM_UARTAPP_CTRL2_RXDMAE	0x01000000
+#define BM_UARTAPP_CTRL2_TXDMAE	0x02000000
+#define BM_UARTAPP_CTRL2_DMAONERR	0x04000000
+
+#define HW_UARTAPP_LINECTRL	0x30
+#define BM_UARTAPP_LINECTRL_BRK	0x00000001
+#define BP_UARTAPP_LINECTRL_BRK	0
+#define BM_UARTAPP_LINECTRL_PEN	0x00000002
+#define BM_UARTAPP_LINECTRL_EPS	0x00000004
+#define BM_UARTAPP_LINECTRL_STP2	0x00000008
+#define BM_UARTAPP_LINECTRL_FEN	0x00000010
+#define BM_UARTAPP_LINECTRL_WLEN	0x00000060
+#define BP_UARTAPP_LINECTRL_WLEN	5
+#define BM_UARTAPP_LINECTRL_SPS	0x00000080
+#define BM_UARTAPP_LINECTRL_BAUD_DIVFRAC	0x00003F00
+#define BP_UARTAPP_LINECTRL_BAUD_DIVFRAC	8
+#define BM_UARTAPP_LINECTRL_BAUD_DIVINT	0xFFFF0000
+#define BP_UARTAPP_LINECTRL_BAUD_DIVINT	16
+
+#define HW_UARTAPP_INTR		0x50
+#define BM_UARTAPP_INTR_CTSMIS	0x00000002
+#define BM_UARTAPP_INTR_RTIS	0x00000040
+#define BM_UARTAPP_INTR_CTSMIEN	0x00020000
+#define BM_UARTAPP_INTR_RXIEN	0x00100000
+#define BM_UARTAPP_INTR_RTIEN	0x00400000
+
+#define HW_UARTAPP_DATA		0x60
+
+#define HW_UARTAPP_STAT		0x70
+#define BM_UARTAPP_STAT_RXCOUNT	0x0000FFFF
+#define BP_UARTAPP_STAT_RXCOUNT	0
+#define BM_UARTAPP_STAT_FERR	0x00010000
+#define BM_UARTAPP_STAT_PERR	0x00020000
+#define BM_UARTAPP_STAT_BERR	0x00040000
+#define BM_UARTAPP_STAT_OERR	0x00080000
+#define BM_UARTAPP_STAT_RXFE	0x01000000
+#define BM_UARTAPP_STAT_TXFF	0x02000000
+#define BM_UARTAPP_STAT_TXFE	0x08000000
+#define BM_UARTAPP_STAT_CTS	0x10000000
+
+#define HW_UARTAPP_VERSION	0x90
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartdbg.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartdbg.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartdbg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-uartdbg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,268 @@
+/*
+ * stmp378x: UARTDBG register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_UARTDBG_BASE	(STMP3XXX_REGS_BASE + 0x70000)
+#define REGS_UARTDBG_PHYS	0x80070000
+#define REGS_UARTDBG_SIZE	0x2000
+
+#define HW_UARTDBGDR 0x00000000
+#define BP_UARTDBGDR_UNAVAILABLE      16
+#define BM_UARTDBGDR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGDR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGDR_UNAVAILABLE)
+#define BP_UARTDBGDR_RESERVED      12
+#define BM_UARTDBGDR_RESERVED 0x0000F000
+#define BF_UARTDBGDR_RESERVED(v)  \
+	(((v) << 12) & BM_UARTDBGDR_RESERVED)
+#define BM_UARTDBGDR_OE 0x00000800
+#define BM_UARTDBGDR_BE 0x00000400
+#define BM_UARTDBGDR_PE 0x00000200
+#define BM_UARTDBGDR_FE 0x00000100
+#define BP_UARTDBGDR_DATA      0
+#define BM_UARTDBGDR_DATA 0x000000FF
+#define BF_UARTDBGDR_DATA(v)  \
+	(((v) << 0) & BM_UARTDBGDR_DATA)
+#define HW_UARTDBGRSR_ECR 0x00000004
+#define BP_UARTDBGRSR_ECR_UNAVAILABLE      8
+#define BM_UARTDBGRSR_ECR_UNAVAILABLE 0xFFFFFF00
+#define BF_UARTDBGRSR_ECR_UNAVAILABLE(v) \
+	(((v) << 8) & BM_UARTDBGRSR_ECR_UNAVAILABLE)
+#define BP_UARTDBGRSR_ECR_EC      4
+#define BM_UARTDBGRSR_ECR_EC 0x000000F0
+#define BF_UARTDBGRSR_ECR_EC(v)  \
+	(((v) << 4) & BM_UARTDBGRSR_ECR_EC)
+#define BM_UARTDBGRSR_ECR_OE 0x00000008
+#define BM_UARTDBGRSR_ECR_BE 0x00000004
+#define BM_UARTDBGRSR_ECR_PE 0x00000002
+#define BM_UARTDBGRSR_ECR_FE 0x00000001
+#define HW_UARTDBGFR 0x00000018
+#define BP_UARTDBGFR_UNAVAILABLE      16
+#define BM_UARTDBGFR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGFR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGFR_UNAVAILABLE)
+#define BP_UARTDBGFR_RESERVED      9
+#define BM_UARTDBGFR_RESERVED 0x0000FE00
+#define BF_UARTDBGFR_RESERVED(v)  \
+	(((v) << 9) & BM_UARTDBGFR_RESERVED)
+#define BM_UARTDBGFR_RI 0x00000100
+#define BM_UARTDBGFR_TXFE 0x00000080
+#define BM_UARTDBGFR_RXFF 0x00000040
+#define BM_UARTDBGFR_TXFF 0x00000020
+#define BM_UARTDBGFR_RXFE 0x00000010
+#define BM_UARTDBGFR_BUSY 0x00000008
+#define BM_UARTDBGFR_DCD 0x00000004
+#define BM_UARTDBGFR_DSR 0x00000002
+#define BM_UARTDBGFR_CTS 0x00000001
+#define HW_UARTDBGILPR 0x00000020
+#define BP_UARTDBGILPR_UNAVAILABLE      8
+#define BM_UARTDBGILPR_UNAVAILABLE 0xFFFFFF00
+#define BF_UARTDBGILPR_UNAVAILABLE(v) \
+	(((v) << 8) & BM_UARTDBGILPR_UNAVAILABLE)
+#define BP_UARTDBGILPR_ILPDVSR      0
+#define BM_UARTDBGILPR_ILPDVSR 0x000000FF
+#define BF_UARTDBGILPR_ILPDVSR(v)  \
+	(((v) << 0) & BM_UARTDBGILPR_ILPDVSR)
+#define HW_UARTDBGIBRD 0x00000024
+#define BP_UARTDBGIBRD_UNAVAILABLE      16
+#define BM_UARTDBGIBRD_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGIBRD_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGIBRD_UNAVAILABLE)
+#define BP_UARTDBGIBRD_BAUD_DIVINT      0
+#define BM_UARTDBGIBRD_BAUD_DIVINT 0x0000FFFF
+#define BF_UARTDBGIBRD_BAUD_DIVINT(v)  \
+	(((v) << 0) & BM_UARTDBGIBRD_BAUD_DIVINT)
+#define HW_UARTDBGFBRD 0x00000028
+#define BP_UARTDBGFBRD_UNAVAILABLE      8
+#define BM_UARTDBGFBRD_UNAVAILABLE 0xFFFFFF00
+#define BF_UARTDBGFBRD_UNAVAILABLE(v) \
+	(((v) << 8) & BM_UARTDBGFBRD_UNAVAILABLE)
+#define BP_UARTDBGFBRD_RESERVED      6
+#define BM_UARTDBGFBRD_RESERVED 0x000000C0
+#define BF_UARTDBGFBRD_RESERVED(v)  \
+	(((v) << 6) & BM_UARTDBGFBRD_RESERVED)
+#define BP_UARTDBGFBRD_BAUD_DIVFRAC      0
+#define BM_UARTDBGFBRD_BAUD_DIVFRAC 0x0000003F
+#define BF_UARTDBGFBRD_BAUD_DIVFRAC(v)  \
+	(((v) << 0) & BM_UARTDBGFBRD_BAUD_DIVFRAC)
+#define HW_UARTDBGLCR_H 0x0000002c
+#define BP_UARTDBGLCR_H_UNAVAILABLE      16
+#define BM_UARTDBGLCR_H_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGLCR_H_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGLCR_H_UNAVAILABLE)
+#define BP_UARTDBGLCR_H_RESERVED      8
+#define BM_UARTDBGLCR_H_RESERVED 0x0000FF00
+#define BF_UARTDBGLCR_H_RESERVED(v)  \
+	(((v) << 8) & BM_UARTDBGLCR_H_RESERVED)
+#define BM_UARTDBGLCR_H_SPS 0x00000080
+#define BP_UARTDBGLCR_H_WLEN      5
+#define BM_UARTDBGLCR_H_WLEN 0x00000060
+#define BF_UARTDBGLCR_H_WLEN(v)  \
+	(((v) << 5) & BM_UARTDBGLCR_H_WLEN)
+#define BM_UARTDBGLCR_H_FEN 0x00000010
+#define BM_UARTDBGLCR_H_STP2 0x00000008
+#define BM_UARTDBGLCR_H_EPS 0x00000004
+#define BM_UARTDBGLCR_H_PEN 0x00000002
+#define BM_UARTDBGLCR_H_BRK 0x00000001
+#define HW_UARTDBGCR 0x00000030
+#define BP_UARTDBGCR_UNAVAILABLE      16
+#define BM_UARTDBGCR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGCR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGCR_UNAVAILABLE)
+#define BM_UARTDBGCR_CTSEN 0x00008000
+#define BM_UARTDBGCR_RTSEN 0x00004000
+#define BM_UARTDBGCR_OUT2 0x00002000
+#define BM_UARTDBGCR_OUT1 0x00001000
+#define BM_UARTDBGCR_RTS 0x00000800
+#define BM_UARTDBGCR_DTR 0x00000400
+#define BM_UARTDBGCR_RXE 0x00000200
+#define BM_UARTDBGCR_TXE 0x00000100
+#define BM_UARTDBGCR_LBE 0x00000080
+#define BP_UARTDBGCR_RESERVED      3
+#define BM_UARTDBGCR_RESERVED 0x00000078
+#define BF_UARTDBGCR_RESERVED(v)  \
+	(((v) << 3) & BM_UARTDBGCR_RESERVED)
+#define BM_UARTDBGCR_SIRLP 0x00000004
+#define BM_UARTDBGCR_SIREN 0x00000002
+#define BM_UARTDBGCR_UARTEN 0x00000001
+#define HW_UARTDBGIFLS 0x00000034
+#define BP_UARTDBGIFLS_UNAVAILABLE      16
+#define BM_UARTDBGIFLS_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGIFLS_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGIFLS_UNAVAILABLE)
+#define BP_UARTDBGIFLS_RESERVED      6
+#define BM_UARTDBGIFLS_RESERVED 0x0000FFC0
+#define BF_UARTDBGIFLS_RESERVED(v)  \
+	(((v) << 6) & BM_UARTDBGIFLS_RESERVED)
+#define BP_UARTDBGIFLS_RXIFLSEL      3
+#define BM_UARTDBGIFLS_RXIFLSEL 0x00000038
+#define BF_UARTDBGIFLS_RXIFLSEL(v)  \
+	(((v) << 3) & BM_UARTDBGIFLS_RXIFLSEL)
+#define BV_UARTDBGIFLS_RXIFLSEL__NOT_EMPTY      0x0
+#define BV_UARTDBGIFLS_RXIFLSEL__ONE_QUARTER    0x1
+#define BV_UARTDBGIFLS_RXIFLSEL__ONE_HALF       0x2
+#define BV_UARTDBGIFLS_RXIFLSEL__THREE_QUARTERS 0x3
+#define BV_UARTDBGIFLS_RXIFLSEL__SEVEN_EIGHTHS  0x4
+#define BV_UARTDBGIFLS_RXIFLSEL__INVALID5       0x5
+#define BV_UARTDBGIFLS_RXIFLSEL__INVALID6       0x6
+#define BV_UARTDBGIFLS_RXIFLSEL__INVALID7       0x7
+#define BP_UARTDBGIFLS_TXIFLSEL      0
+#define BM_UARTDBGIFLS_TXIFLSEL 0x00000007
+#define BF_UARTDBGIFLS_TXIFLSEL(v)  \
+	(((v) << 0) & BM_UARTDBGIFLS_TXIFLSEL)
+#define BV_UARTDBGIFLS_TXIFLSEL__EMPTY	  0x0
+#define BV_UARTDBGIFLS_TXIFLSEL__ONE_QUARTER    0x1
+#define BV_UARTDBGIFLS_TXIFLSEL__ONE_HALF       0x2
+#define BV_UARTDBGIFLS_TXIFLSEL__THREE_QUARTERS 0x3
+#define BV_UARTDBGIFLS_TXIFLSEL__SEVEN_EIGHTHS  0x4
+#define BV_UARTDBGIFLS_TXIFLSEL__INVALID5       0x5
+#define BV_UARTDBGIFLS_TXIFLSEL__INVALID6       0x6
+#define BV_UARTDBGIFLS_TXIFLSEL__INVALID7       0x7
+#define HW_UARTDBGIMSC 0x00000038
+#define BP_UARTDBGIMSC_UNAVAILABLE      16
+#define BM_UARTDBGIMSC_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGIMSC_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGIMSC_UNAVAILABLE)
+#define BP_UARTDBGIMSC_RESERVED      11
+#define BM_UARTDBGIMSC_RESERVED 0x0000F800
+#define BF_UARTDBGIMSC_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGIMSC_RESERVED)
+#define BM_UARTDBGIMSC_OEIM 0x00000400
+#define BM_UARTDBGIMSC_BEIM 0x00000200
+#define BM_UARTDBGIMSC_PEIM 0x00000100
+#define BM_UARTDBGIMSC_FEIM 0x00000080
+#define BM_UARTDBGIMSC_RTIM 0x00000040
+#define BM_UARTDBGIMSC_TXIM 0x00000020
+#define BM_UARTDBGIMSC_RXIM 0x00000010
+#define BM_UARTDBGIMSC_DSRMIM 0x00000008
+#define BM_UARTDBGIMSC_DCDMIM 0x00000004
+#define BM_UARTDBGIMSC_CTSMIM 0x00000002
+#define BM_UARTDBGIMSC_RIMIM 0x00000001
+#define HW_UARTDBGRIS 0x0000003c
+#define BP_UARTDBGRIS_UNAVAILABLE      16
+#define BM_UARTDBGRIS_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGRIS_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGRIS_UNAVAILABLE)
+#define BP_UARTDBGRIS_RESERVED      11
+#define BM_UARTDBGRIS_RESERVED 0x0000F800
+#define BF_UARTDBGRIS_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGRIS_RESERVED)
+#define BM_UARTDBGRIS_OERIS 0x00000400
+#define BM_UARTDBGRIS_BERIS 0x00000200
+#define BM_UARTDBGRIS_PERIS 0x00000100
+#define BM_UARTDBGRIS_FERIS 0x00000080
+#define BM_UARTDBGRIS_RTRIS 0x00000040
+#define BM_UARTDBGRIS_TXRIS 0x00000020
+#define BM_UARTDBGRIS_RXRIS 0x00000010
+#define BM_UARTDBGRIS_DSRRMIS 0x00000008
+#define BM_UARTDBGRIS_DCDRMIS 0x00000004
+#define BM_UARTDBGRIS_CTSRMIS 0x00000002
+#define BM_UARTDBGRIS_RIRMIS 0x00000001
+#define HW_UARTDBGMIS 0x00000040
+#define BP_UARTDBGMIS_UNAVAILABLE      16
+#define BM_UARTDBGMIS_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGMIS_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGMIS_UNAVAILABLE)
+#define BP_UARTDBGMIS_RESERVED      11
+#define BM_UARTDBGMIS_RESERVED 0x0000F800
+#define BF_UARTDBGMIS_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGMIS_RESERVED)
+#define BM_UARTDBGMIS_OEMIS 0x00000400
+#define BM_UARTDBGMIS_BEMIS 0x00000200
+#define BM_UARTDBGMIS_PEMIS 0x00000100
+#define BM_UARTDBGMIS_FEMIS 0x00000080
+#define BM_UARTDBGMIS_RTMIS 0x00000040
+#define BM_UARTDBGMIS_TXMIS 0x00000020
+#define BM_UARTDBGMIS_RXMIS 0x00000010
+#define BM_UARTDBGMIS_DSRMMIS 0x00000008
+#define BM_UARTDBGMIS_DCDMMIS 0x00000004
+#define BM_UARTDBGMIS_CTSMMIS 0x00000002
+#define BM_UARTDBGMIS_RIMMIS 0x00000001
+#define HW_UARTDBGICR 0x00000044
+#define BP_UARTDBGICR_UNAVAILABLE      16
+#define BM_UARTDBGICR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGICR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGICR_UNAVAILABLE)
+#define BP_UARTDBGICR_RESERVED      11
+#define BM_UARTDBGICR_RESERVED 0x0000F800
+#define BF_UARTDBGICR_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGICR_RESERVED)
+#define BM_UARTDBGICR_OEIC 0x00000400
+#define BM_UARTDBGICR_BEIC 0x00000200
+#define BM_UARTDBGICR_PEIC 0x00000100
+#define BM_UARTDBGICR_FEIC 0x00000080
+#define BM_UARTDBGICR_RTIC 0x00000040
+#define BM_UARTDBGICR_TXIC 0x00000020
+#define BM_UARTDBGICR_RXIC 0x00000010
+#define BM_UARTDBGICR_DSRMIC 0x00000008
+#define BM_UARTDBGICR_DCDMIC 0x00000004
+#define BM_UARTDBGICR_CTSMIC 0x00000002
+#define BM_UARTDBGICR_RIMIC 0x00000001
+#define HW_UARTDBGDMACR 0x00000048
+#define BP_UARTDBGDMACR_UNAVAILABLE      16
+#define BM_UARTDBGDMACR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGDMACR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGDMACR_UNAVAILABLE)
+#define BP_UARTDBGDMACR_RESERVED      3
+#define BM_UARTDBGDMACR_RESERVED 0x0000FFF8
+#define BF_UARTDBGDMACR_RESERVED(v)  \
+	(((v) << 3) & BM_UARTDBGDMACR_RESERVED)
+#define BM_UARTDBGDMACR_DMAONERR 0x00000004
+#define BM_UARTDBGDMACR_TXDMAE 0x00000002
+#define BM_UARTDBGDMACR_RXDMAE 0x00000001
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbctrl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbctrl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbctrl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbctrl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * stmp378x: USBCTRL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_USBCTRL_BASE	(STMP3XXX_REGS_BASE + 0x80000)
+#define REGS_USBCTRL_PHYS	0x80080000
+#define REGS_USBCTRL_SIZE	0x2000
+
+#define HW_USBCTRL_USBCMD	0x140
+#define BM_USBCTRL_USBCMD_RS	0x00000001
+#define BP_USBCTRL_USBCMD_RS	0
+#define BM_USBCTRL_USBCMD_RST	0x00000002
+
+#define HW_USBCTRL_USBINTR	0x148
+#define BM_USBCTRL_USBINTR_UE	0x00000001
+#define BP_USBCTRL_USBINTR_UE	0
+
+#define HW_USBCTRL_PORTSC1	0x184
+#define BM_USBCTRL_PORTSC1_PHCD	0x00800000
+
+#define HW_USBCTRL_OTGSC	0x1A4
+#define BM_USBCTRL_OTGSC_ID	0x00000100
+#define BM_USBCTRL_OTGSC_IDIS	0x00010000
+#define BM_USBCTRL_OTGSC_IDIE	0x01000000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbphy.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbphy.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbphy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/include/mach/regs-usbphy.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ * stmp378x: USBPHY register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_USBPHY_BASE	(STMP3XXX_REGS_BASE + 0x7C000)
+#define REGS_USBPHY_PHYS	0x8007C000
+#define REGS_USBPHY_SIZE	0x2000
+
+#define HW_USBPHY_PWD		0x0
+
+#define HW_USBPHY_CTRL		0x30
+#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	0x00000002
+#define BM_USBPHY_CTRL_ENDEVPLUGINDETECT	0x00000010
+#define BM_USBPHY_CTRL_ENOTGIDDETECT	0x00000080
+#define BM_USBPHY_CTRL_ENIRQDEVPLUGIN	0x00000800
+#define BM_USBPHY_CTRL_CLKGATE	0x40000000
+#define BM_USBPHY_CTRL_SFTRST	0x80000000
+
+#define HW_USBPHY_STATUS	0x40
+#define BM_USBPHY_STATUS_DEVPLUGIN_STATUS	0x00000040
+#define BM_USBPHY_STATUS_OTGID_STATUS	0x00000100
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARCH_STMP378X) += stmp378x.o
+obj-$(CONFIG_MACH_STMP378X) += stmp378x_devb.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/Makefile.boot linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/Makefile.boot
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/Makefile.boot	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x40008000
+params_phys-y	:= 0x40000100
+initrd_phys-y	:= 0x40800000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/stmp378x.c linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/stmp378x.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/stmp378x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/stmp378x.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,299 @@
+/*
+ * Freescale STMP378X platform support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/dma.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include <mach/platform.h>
+#include <mach/stmp3xxx.h>
+#include <mach/regs-icoll.h>
+#include <mach/regs-apbh.h>
+#include <mach/regs-apbx.h>
+#include <mach/regs-pxp.h>
+#include <mach/regs-i2c.h>
+
+#include "stmp378x.h"
+/*
+ * IRQ handling
+ */
+static void stmp378x_ack_irq(unsigned int irq)
+{
+	/* Tell ICOLL to release IRQ line */
+	__raw_writel(0, REGS_ICOLL_BASE + HW_ICOLL_VECTOR);
+
+	/* ACK current interrupt */
+	__raw_writel(0x01 /* BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 */,
+			REGS_ICOLL_BASE + HW_ICOLL_LEVELACK);
+
+	/* Barrier */
+	(void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT);
+}
+
+static void stmp378x_mask_irq(unsigned int irq)
+{
+	/* IRQ disable */
+	stmp3xxx_clearl(BM_ICOLL_INTERRUPTn_ENABLE,
+			REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10);
+}
+
+static void stmp378x_unmask_irq(unsigned int irq)
+{
+	/* IRQ enable */
+	stmp3xxx_setl(BM_ICOLL_INTERRUPTn_ENABLE,
+		      REGS_ICOLL_BASE + HW_ICOLL_INTERRUPTn + irq * 0x10);
+}
+
+static struct irq_chip stmp378x_chip = {
+	.ack	= stmp378x_ack_irq,
+	.mask	= stmp378x_mask_irq,
+	.unmask = stmp378x_unmask_irq,
+};
+
+void __init stmp378x_init_irq(void)
+{
+	stmp3xxx_init_irq(&stmp378x_chip);
+}
+
+/*
+ * DMA interrupt handling
+ */
+void stmp3xxx_arch_dma_enable_interrupt(int channel)
+{
+	void __iomem *c1, *c2;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		c1 = REGS_APBH_BASE + HW_APBH_CTRL1;
+		c2 = REGS_APBH_BASE + HW_APBH_CTRL2;
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		c1 = REGS_APBX_BASE + HW_APBX_CTRL1;
+		c2 = REGS_APBX_BASE + HW_APBX_CTRL2;
+		break;
+
+	default:
+		return;
+	}
+	stmp3xxx_setl(1 << (16 + STMP3XXX_DMA_CHANNEL(channel)), c1);
+	stmp3xxx_setl(1 << (16 + STMP3XXX_DMA_CHANNEL(channel)), c2);
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt);
+
+void stmp3xxx_arch_dma_clear_interrupt(int channel)
+{
+	void __iomem *c1, *c2;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		c1 = REGS_APBH_BASE + HW_APBH_CTRL1;
+		c2 = REGS_APBH_BASE + HW_APBH_CTRL2;
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		c1 = REGS_APBX_BASE + HW_APBX_CTRL1;
+		c2 = REGS_APBX_BASE + HW_APBX_CTRL2;
+		break;
+
+	default:
+		return;
+	}
+	stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), c1);
+	stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), c2);
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt);
+
+int stmp3xxx_arch_dma_is_interrupt(int channel)
+{
+	int r = 0;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) &
+			(1 << STMP3XXX_DMA_CHANNEL(channel));
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		r = __raw_readl(REGS_APBX_BASE + HW_APBX_CTRL1) &
+			(1 << STMP3XXX_DMA_CHANNEL(channel));
+		break;
+	}
+	return r;
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt);
+
+void stmp3xxx_arch_dma_reset_channel(int channel)
+{
+	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
+	void __iomem *c0;
+	u32 mask;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		c0 = REGS_APBH_BASE + HW_APBH_CTRL0;
+		mask = chbit << BP_APBH_CTRL0_RESET_CHANNEL;
+		break;
+	case STMP3XXX_BUS_APBX:
+		c0 = REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL;
+		mask = chbit << BP_APBX_CHANNEL_CTRL_RESET_CHANNEL;
+		break;
+	default:
+		return;
+	}
+
+	/* Reset channel and wait for it to complete */
+	stmp3xxx_setl(mask, c0);
+	while (__raw_readl(c0) & mask)
+		cpu_relax();
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel);
+
+void stmp3xxx_arch_dma_freeze(int channel)
+{
+	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
+	u32 mask = 1 << chbit;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		stmp3xxx_setl(mask, REGS_APBH_BASE + HW_APBH_CTRL0);
+		break;
+	case STMP3XXX_BUS_APBX:
+		stmp3xxx_setl(mask, REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL);
+		break;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze);
+
+void stmp3xxx_arch_dma_unfreeze(int channel)
+{
+	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
+	u32 mask = 1 << chbit;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		stmp3xxx_clearl(mask, REGS_APBH_BASE + HW_APBH_CTRL0);
+		break;
+	case STMP3XXX_BUS_APBX:
+		stmp3xxx_clearl(mask, REGS_APBX_BASE + HW_APBX_CHANNEL_CTRL);
+		break;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze);
+
+/*
+ * The registers are all very closely mapped, so we might as well map them all
+ * with a single mapping
+ *
+ * Logical      Physical
+ * f0000000	80000000	On-chip registers
+ * f1000000	00000000	32k on-chip SRAM
+ */
+
+static struct map_desc stmp378x_io_desc[] __initdata = {
+	{
+		.virtual	= (u32)STMP3XXX_REGS_BASE,
+		.pfn		= __phys_to_pfn(STMP3XXX_REGS_PHBASE),
+		.length		= STMP3XXX_REGS_SIZE,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= (u32)STMP3XXX_OCRAM_BASE,
+		.pfn		= __phys_to_pfn(STMP3XXX_OCRAM_PHBASE),
+		.length		= STMP3XXX_OCRAM_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+
+static u64 common_dmamask = DMA_BIT_MASK(32);
+
+/*
+ * devices that are present only on stmp378x, not on all 3xxx boards:
+ * 	PxP
+ * 	I2C
+ */
+static struct resource pxp_resource[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+		.start	= REGS_PXP_PHYS,
+		.end	= REGS_PXP_PHYS + REGS_PXP_SIZE,
+	}, {
+		.flags	= IORESOURCE_IRQ,
+		.start	= IRQ_PXP,
+		.end	= IRQ_PXP,
+	},
+};
+
+struct platform_device stmp378x_pxp = {
+	.name		= "stmp3xxx-pxp",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &common_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(pxp_resource),
+	.resource	= pxp_resource,
+};
+
+static struct resource i2c_resources[] = {
+	{
+		.flags = IORESOURCE_IRQ,
+		.start = IRQ_I2C_ERROR,
+		.end = IRQ_I2C_ERROR,
+	}, {
+		.flags = IORESOURCE_MEM,
+		.start = REGS_I2C_PHYS,
+		.end = REGS_I2C_PHYS + REGS_I2C_SIZE,
+	}, {
+		.flags = IORESOURCE_DMA,
+		.start = STMP3XXX_DMA(3, STMP3XXX_BUS_APBX),
+		.end = STMP3XXX_DMA(3, STMP3XXX_BUS_APBX),
+	},
+};
+
+struct platform_device stmp378x_i2c = {
+	.name = "i2c_stmp3xxx",
+	.id = 0,
+	.dev	= {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = i2c_resources,
+	.num_resources = ARRAY_SIZE(i2c_resources),
+};
+
+void __init stmp378x_map_io(void)
+{
+	iotable_init(stmp378x_io_desc, ARRAY_SIZE(stmp378x_io_desc));
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/stmp378x_devb.c linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/stmp378x_devb.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/stmp378x_devb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/stmp378x_devb.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,334 @@
+/*
+ * Freescale STMP378X development board support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/spi/spi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+#include <mach/platform.h>
+#include <mach/stmp3xxx.h>
+#include <mach/mmc.h>
+#include <mach/gpmi.h>
+
+#include "stmp378x.h"
+
+static struct platform_device *devices[] = {
+	&stmp3xxx_dbguart,
+	&stmp3xxx_appuart,
+	&stmp3xxx_watchdog,
+	&stmp3xxx_touchscreen,
+	&stmp3xxx_rtc,
+	&stmp3xxx_keyboard,
+	&stmp3xxx_framebuffer,
+	&stmp3xxx_backlight,
+	&stmp3xxx_rotdec,
+	&stmp3xxx_persistent,
+	&stmp3xxx_dcp_bootstream,
+	&stmp3xxx_dcp,
+	&stmp3xxx_battery,
+	&stmp378x_pxp,
+	&stmp378x_i2c,
+};
+
+static struct pin_desc i2c_pins_desc[] = {
+	{ PINID_I2C_SCL, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_I2C_SDA, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+};
+
+static struct pin_group i2c_pins = {
+	.pins		= i2c_pins_desc,
+	.nr_pins	= ARRAY_SIZE(i2c_pins_desc),
+};
+
+static struct pin_desc dbguart_pins_0[] = {
+	{ PINID_PWM0, PIN_FUN3, },
+	{ PINID_PWM1, PIN_FUN3, },
+};
+
+static struct pin_group dbguart_pins[] = {
+	[0] = {
+		.pins		= dbguart_pins_0,
+		.nr_pins	= ARRAY_SIZE(dbguart_pins_0),
+	},
+};
+
+static int dbguart_pins_control(int id, int request)
+{
+	int r = 0;
+
+	if (request)
+		r = stmp3xxx_request_pin_group(&dbguart_pins[id], "debug uart");
+	else
+		stmp3xxx_release_pin_group(&dbguart_pins[id], "debug uart");
+	return r;
+}
+
+static struct pin_desc appuart_pins_0[] = {
+	{ PINID_AUART1_CTS, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_AUART1_RTS, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_AUART1_RX, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_AUART1_TX, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+};
+
+static struct pin_desc appuart_pins_1[] = {
+#if 0 /* enable these when second appuart will be connected */
+	{ PINID_AUART2_CTS, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_AUART2_RTS, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_AUART2_RX, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_AUART2_TX, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+#endif
+};
+
+static struct pin_desc mmc_pins_desc[] = {
+	{ PINID_SSP1_DATA0, PIN_FUN1, PIN_8MA, PIN_3_3V, 1 },
+	{ PINID_SSP1_DATA1, PIN_FUN1, PIN_8MA, PIN_3_3V, 1 },
+	{ PINID_SSP1_DATA2, PIN_FUN1, PIN_8MA, PIN_3_3V, 1 },
+	{ PINID_SSP1_DATA3, PIN_FUN1, PIN_8MA, PIN_3_3V, 1 },
+	{ PINID_SSP1_CMD, PIN_FUN1, PIN_8MA, PIN_3_3V, 1 },
+	{ PINID_SSP1_SCK, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
+	{ PINID_SSP1_DETECT, PIN_FUN1, PIN_8MA, PIN_3_3V, 0 },
+};
+
+static struct pin_group mmc_pins = {
+	.pins		= mmc_pins_desc,
+	.nr_pins	= ARRAY_SIZE(mmc_pins_desc),
+};
+
+static int stmp3xxxmmc_get_wp(void)
+{
+	return gpio_get_value(PINID_PWM4);
+}
+
+static int stmp3xxxmmc_hw_init_ssp1(void)
+{
+	int ret;
+
+	ret = stmp3xxx_request_pin_group(&mmc_pins, "mmc");
+	if (ret)
+		goto out;
+
+	/* Configure write protect GPIO pin */
+	ret = gpio_request(PINID_PWM4, "mmc wp");
+	if (ret)
+		goto out_wp;
+
+	gpio_direction_input(PINID_PWM4);
+
+	/* Configure POWER pin as gpio to drive power to MMC slot */
+	ret = gpio_request(PINID_PWM3, "mmc power");
+	if (ret)
+		goto out_power;
+
+	gpio_direction_output(PINID_PWM3, 0);
+	mdelay(100);
+
+	return 0;
+
+out_power:
+	gpio_free(PINID_PWM4);
+out_wp:
+	stmp3xxx_release_pin_group(&mmc_pins, "mmc");
+out:
+	return ret;
+}
+
+static void stmp3xxxmmc_hw_release_ssp1(void)
+{
+	gpio_free(PINID_PWM3);
+	gpio_free(PINID_PWM4);
+	stmp3xxx_release_pin_group(&mmc_pins, "mmc");
+}
+
+static void stmp3xxxmmc_cmd_pullup_ssp1(int enable)
+{
+	stmp3xxx_pin_pullup(PINID_SSP1_CMD, enable, "mmc");
+}
+
+static unsigned long
+stmp3xxxmmc_setclock_ssp1(void __iomem *base, unsigned long hz)
+{
+	struct clk *ssp, *parent;
+	char *p;
+	long r;
+
+	ssp = clk_get(NULL, "ssp");
+
+	/* using SSP1, no timeout, clock rate 1 */
+	writel(BF(2, SSP_TIMING_CLOCK_DIVIDE) |
+	       BF(0xFFFF, SSP_TIMING_TIMEOUT),
+	       base + HW_SSP_TIMING);
+
+	p = (hz > 1000000) ? "io" : "osc_24M";
+	parent = clk_get(NULL, p);
+	clk_set_parent(ssp, parent);
+	r = clk_set_rate(ssp, 2 * hz / 1000);
+	clk_put(parent);
+	clk_put(ssp);
+
+	return hz;
+}
+
+static struct stmp3xxxmmc_platform_data mmc_data = {
+	.hw_init	= stmp3xxxmmc_hw_init_ssp1,
+	.hw_release	= stmp3xxxmmc_hw_release_ssp1,
+	.get_wp		= stmp3xxxmmc_get_wp,
+	.cmd_pullup	= stmp3xxxmmc_cmd_pullup_ssp1,
+	.setclock	= stmp3xxxmmc_setclock_ssp1,
+};
+
+
+static struct pin_group appuart_pins[] = {
+	[0] = {
+		.pins		= appuart_pins_0,
+		.nr_pins	= ARRAY_SIZE(appuart_pins_0),
+	},
+	[1] = {
+		.pins		= appuart_pins_1,
+		.nr_pins	= ARRAY_SIZE(appuart_pins_1),
+	},
+};
+
+static struct pin_desc ssp1_pins_desc[] = {
+	{ PINID_SSP1_SCK,	PIN_FUN1, PIN_8MA, PIN_3_3V, 0, },
+	{ PINID_SSP1_CMD,	PIN_FUN1, PIN_4MA, PIN_3_3V, 0, },
+	{ PINID_SSP1_DATA0,	PIN_FUN1, PIN_4MA, PIN_3_3V, 0, },
+	{ PINID_SSP1_DATA3,	PIN_FUN1, PIN_4MA, PIN_3_3V, 0, },
+};
+
+static struct pin_desc ssp2_pins_desc[] = {
+	{ PINID_GPMI_WRN,	PIN_FUN3, PIN_8MA, PIN_3_3V, 0, },
+	{ PINID_GPMI_RDY1,	PIN_FUN3, PIN_4MA, PIN_3_3V, 0, },
+	{ PINID_GPMI_D00,	PIN_FUN3, PIN_4MA, PIN_3_3V, 0, },
+	{ PINID_GPMI_D03,	PIN_FUN3, PIN_4MA, PIN_3_3V, 0, },
+};
+
+static struct pin_group ssp1_pins = {
+	.pins = ssp1_pins_desc,
+	.nr_pins = ARRAY_SIZE(ssp1_pins_desc),
+};
+
+static struct pin_group ssp2_pins = {
+	.pins = ssp1_pins_desc,
+	.nr_pins = ARRAY_SIZE(ssp2_pins_desc),
+};
+
+static struct pin_desc gpmi_pins_desc[] = {
+	{ PINID_GPMI_CE0N, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_CE1N, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GMPI_CE2N, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_CLE, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_ALE, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_WPN, PIN_FUN1, PIN_12MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_RDY1, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D00, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D01, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D02, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D03, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D04, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D05, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D06, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_D07, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_RDY0, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_RDY2, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_RDY3, PIN_FUN1, PIN_4MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_WRN, PIN_FUN1, PIN_12MA, PIN_3_3V, 0 },
+	{ PINID_GPMI_RDN, PIN_FUN1, PIN_12MA, PIN_3_3V, 0 },
+};
+
+static struct pin_group gpmi_pins = {
+	.pins		= gpmi_pins_desc,
+	.nr_pins	= ARRAY_SIZE(gpmi_pins_desc),
+};
+
+static struct mtd_partition gpmi_partitions[] = {
+	[0] = {
+		.name	= "boot",
+		.size	= 10 * SZ_1M,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "data",
+		.size	= MTDPART_SIZ_FULL,
+		.offset	= MTDPART_OFS_APPEND,
+	},
+};
+
+static struct gpmi_platform_data gpmi_data = {
+	.pins = &gpmi_pins,
+	.nr_parts = ARRAY_SIZE(gpmi_partitions),
+	.parts = gpmi_partitions,
+	.part_types = { "cmdline", NULL },
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
+	{
+		.modalias       = "enc28j60",
+		.max_speed_hz   = 6 * 1000 * 1000,
+		.bus_num	= 1,
+		.chip_select    = 0,
+		.platform_data  = NULL,
+	},
+#endif
+};
+
+static void __init stmp378x_devb_init(void)
+{
+	stmp3xxx_pinmux_init(NR_REAL_IRQS);
+
+	/* init stmp3xxx platform */
+	stmp3xxx_init();
+
+	stmp3xxx_dbguart.dev.platform_data = dbguart_pins_control;
+	stmp3xxx_appuart.dev.platform_data = appuart_pins;
+	stmp3xxx_mmc.dev.platform_data = &mmc_data;
+	stmp3xxx_gpmi.dev.platform_data = &gpmi_data;
+	stmp3xxx_spi1.dev.platform_data = &ssp1_pins;
+	stmp3xxx_spi2.dev.platform_data = &ssp2_pins;
+	stmp378x_i2c.dev.platform_data = &i2c_pins;
+
+	/* register spi devices */
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+	/* add board's devices */
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	/* add devices selected by command line ssp1= and ssp2= options */
+	stmp3xxx_ssp1_device_register();
+	stmp3xxx_ssp2_device_register();
+}
+
+MACHINE_START(STMP378X, "STMP378X")
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xf0000000) >> 18) & 0xfffc,
+	.boot_params	= 0x40000100,
+	.map_io		= stmp378x_map_io,
+	.init_irq	= stmp378x_init_irq,
+	.timer		= &stmp3xxx_timer,
+	.init_machine	= stmp378x_devb_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/stmp378x.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/stmp378x.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp378x/stmp378x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp378x/stmp378x.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Freescale STMP37XX/STMP378X internal functions and data declarations
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __MACH_STMP378X_H
+#define __MACH_STMP378X_H
+
+void stmp378x_map_io(void);
+void stmp378x_init_irq(void);
+
+extern struct platform_device stmp378x_pxp, stmp378x_i2c;
+#endif /* __MACH_STMP378X_COMMON_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/entry-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/entry-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/entry-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ * Low-level IRQ helper macros for Freescale STMP37XX
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	        mov	\base, #0xf0000000	@ vm address of IRQ controller
+		ldr	\irqnr, [\base, #0x30]	@ HW_ICOLL_STAT
+		cmp	\irqnr, #0x3f
+		movne	\irqstat, #0		@ Ack this IRQ
+		strne	\irqstat, [\base, #0x00]@ HW_ICOLL_VECTOR
+		moveqs	\irqnr, #0		@ Zero flag set for no IRQ
+
+		.endm
+
+                .macro  get_irqnr_preamble, base, tmp
+                .endm
+
+                .macro  arch_ret_to_user, tmp1, tmp2
+                .endm
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * Freescale STMP37XX interrupts
+ *
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef _ASM_ARCH_IRQS_H
+#define _ASM_ARCH_IRQS_H
+
+#define IRQ_DEBUG_UART	         0
+#define IRQ_COMMS_RX	           1
+#define IRQ_COMMS_TX	           1
+#define IRQ_SSP2_ERROR	         2
+#define IRQ_VDD5V	              3
+#define IRQ_HEADPHONE_SHORT	    4
+#define IRQ_DAC_DMA	            5
+#define IRQ_DAC_ERROR	          6
+#define IRQ_ADC_DMA	            7
+#define IRQ_ADC_ERROR	          8
+#define IRQ_SPDIF_DMA	          9
+#define IRQ_SAIF2_DMA	          9
+#define IRQ_SPDIF_ERROR	        10
+#define IRQ_SAIF1_IRQ	          10
+#define IRQ_SAIF2_IRQ	          10
+#define IRQ_USB_CTRL	           11
+#define IRQ_USB_WAKEUP	         12
+#define IRQ_GPMI_DMA	           13
+#define IRQ_SSP1_DMA	           14
+#define IRQ_SSP_ERROR	          15
+#define IRQ_GPIO0	              16
+#define IRQ_GPIO1	              17
+#define IRQ_GPIO2	              18
+#define IRQ_SAIF1_DMA	          19
+#define IRQ_SSP2_DMA	           20
+#define IRQ_ECC8_IRQ	           21
+#define IRQ_RTC_ALARM	          22
+#define IRQ_UARTAPP_TX_DMA	     23
+#define IRQ_UARTAPP_INTERNAL	   24
+#define IRQ_UARTAPP_RX_DMA	     25
+#define IRQ_I2C_DMA	            26
+#define IRQ_I2C_ERROR	          27
+#define IRQ_TIMER0	             28
+#define IRQ_TIMER1	             29
+#define IRQ_TIMER2	             30
+#define IRQ_TIMER3	             31
+#define IRQ_BATT_BRNOUT	        32
+#define IRQ_VDDD_BRNOUT	        33
+#define IRQ_VDDIO_BRNOUT	       34
+#define IRQ_VDD18_BRNOUT	       35
+#define IRQ_TOUCH_DETECT	       36
+#define IRQ_LRADC_CH0	          37
+#define IRQ_LRADC_CH1	          38
+#define IRQ_LRADC_CH2	          39
+#define IRQ_LRADC_CH3	          40
+#define IRQ_LRADC_CH4	          41
+#define IRQ_LRADC_CH5	          42
+#define IRQ_LRADC_CH6	          43
+#define IRQ_LRADC_CH7	          44
+#define IRQ_LCDIF_DMA	          45
+#define IRQ_LCDIF_ERROR	        46
+#define IRQ_DIGCTL_DEBUG_TRAP	  47
+#define IRQ_RTC_1MSEC	          48
+#define IRQ_DRI_DMA	            49
+#define IRQ_DRI_ATTENTION	      50
+#define IRQ_GPMI_ATTENTION	     51
+#define IRQ_IR	                 52
+#define IRQ_DCP_VMI	            53
+#define IRQ_DCP	                54
+#define IRQ_RESERVED_55	        55
+#define IRQ_RESERVED_56	        56
+#define IRQ_RESERVED_57	        57
+#define IRQ_RESERVED_58	        58
+#define IRQ_RESERVED_59	        59
+#define SW_IRQ_60	              60
+#define SW_IRQ_61	              61
+#define SW_IRQ_62	              62
+#define SW_IRQ_63	              63
+
+#define NR_REAL_IRQS		64
+#define NR_IRQS			(NR_REAL_IRQS + 32 * 3)
+
+/* TIMER and BRNOUT are FIQ capable */
+#define FIQ_START			IRQ_TIMER0
+
+/* Hard disk IRQ is a GPMI attention IRQ */
+#define IRQ_HARDDISK		IRQ_GPMI_ATTENTION
+
+#endif /* _ASM_ARCH_IRQS_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/pins.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/pins.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/pins.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/pins.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,147 @@
+/*
+ * Freescale STMP37XX SoC pin multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_PINS_H
+#define __ASM_ARCH_PINS_H
+
+/*
+ * Define all STMP37XX pins, a pin name corresponds to a STMP37xx hardware
+ * interface  this pin belongs to.
+ */
+
+/* Bank 0 */
+#define PINID_GPMI_D00		STMP3XXX_PINID(0, 0)
+#define PINID_GPMI_D01		STMP3XXX_PINID(0, 1)
+#define PINID_GPMI_D02		STMP3XXX_PINID(0, 2)
+#define PINID_GPMI_D03		STMP3XXX_PINID(0, 3)
+#define PINID_GPMI_D04		STMP3XXX_PINID(0, 4)
+#define PINID_GPMI_D05		STMP3XXX_PINID(0, 5)
+#define PINID_GPMI_D06		STMP3XXX_PINID(0, 6)
+#define PINID_GPMI_D07		STMP3XXX_PINID(0, 7)
+#define PINID_GPMI_D08		STMP3XXX_PINID(0, 8)
+#define PINID_GPMI_D09		STMP3XXX_PINID(0, 9)
+#define PINID_GPMI_D10		STMP3XXX_PINID(0, 10)
+#define PINID_GPMI_D11		STMP3XXX_PINID(0, 11)
+#define PINID_GPMI_D12		STMP3XXX_PINID(0, 12)
+#define PINID_GPMI_D13		STMP3XXX_PINID(0, 13)
+#define PINID_GPMI_D14		STMP3XXX_PINID(0, 14)
+#define PINID_GPMI_D15		STMP3XXX_PINID(0, 15)
+#define PINID_GPMI_A0		STMP3XXX_PINID(0, 16)
+#define PINID_GPMI_A1		STMP3XXX_PINID(0, 17)
+#define PINID_GPMI_A2		STMP3XXX_PINID(0, 18)
+#define PINID_GPMI_RDY0		STMP3XXX_PINID(0, 19)
+#define PINID_GPMI_RDY2		STMP3XXX_PINID(0, 20)
+#define PINID_GPMI_RDY3		STMP3XXX_PINID(0, 21)
+#define PINID_GPMI_RESETN	STMP3XXX_PINID(0, 22)
+#define PINID_GPMI_IRQ		STMP3XXX_PINID(0, 23)
+#define PINID_GPMI_WRN		STMP3XXX_PINID(0, 24)
+#define PINID_GPMI_RDN		STMP3XXX_PINID(0, 25)
+#define PINID_UART2_CTS		STMP3XXX_PINID(0, 26)
+#define PINID_UART2_RTS		STMP3XXX_PINID(0, 27)
+#define PINID_UART2_RX		STMP3XXX_PINID(0, 28)
+#define PINID_UART2_TX		STMP3XXX_PINID(0, 29)
+
+/* Bank 1 */
+#define PINID_LCD_D00		STMP3XXX_PINID(1, 0)
+#define PINID_LCD_D01		STMP3XXX_PINID(1, 1)
+#define PINID_LCD_D02		STMP3XXX_PINID(1, 2)
+#define PINID_LCD_D03		STMP3XXX_PINID(1, 3)
+#define PINID_LCD_D04		STMP3XXX_PINID(1, 4)
+#define PINID_LCD_D05		STMP3XXX_PINID(1, 5)
+#define PINID_LCD_D06		STMP3XXX_PINID(1, 6)
+#define PINID_LCD_D07		STMP3XXX_PINID(1, 7)
+#define PINID_LCD_D08		STMP3XXX_PINID(1, 8)
+#define PINID_LCD_D09		STMP3XXX_PINID(1, 9)
+#define PINID_LCD_D10		STMP3XXX_PINID(1, 10)
+#define PINID_LCD_D11		STMP3XXX_PINID(1, 11)
+#define PINID_LCD_D12		STMP3XXX_PINID(1, 12)
+#define PINID_LCD_D13		STMP3XXX_PINID(1, 13)
+#define PINID_LCD_D14		STMP3XXX_PINID(1, 14)
+#define PINID_LCD_D15		STMP3XXX_PINID(1, 15)
+#define PINID_LCD_RESET 	STMP3XXX_PINID(1, 16)
+#define PINID_LCD_RS		STMP3XXX_PINID(1, 17)
+#define PINID_LCD_WR_RWN	STMP3XXX_PINID(1, 18)
+#define PINID_LCD_RD_E		STMP3XXX_PINID(1, 19)
+#define PINID_LCD_CS		STMP3XXX_PINID(1, 20)
+#define PINID_LCD_BUSY		STMP3XXX_PINID(1, 21)
+#define PINID_SSP1_CMD		STMP3XXX_PINID(1, 22)
+#define PINID_SSP1_SCK		STMP3XXX_PINID(1, 23)
+#define PINID_SSP1_DATA0	STMP3XXX_PINID(1, 24)
+#define PINID_SSP1_DATA1	STMP3XXX_PINID(1, 25)
+#define PINID_SSP1_DATA2	STMP3XXX_PINID(1, 26)
+#define PINID_SSP1_DATA3	STMP3XXX_PINID(1, 27)
+#define PINID_SSP1_DETECT	STMP3XXX_PINID(1, 28)
+
+/* Bank 2 */
+#define PINID_PWM0		STMP3XXX_PINID(2, 0)
+#define PINID_PWM1		STMP3XXX_PINID(2, 1)
+#define PINID_PWM2		STMP3XXX_PINID(2, 2)
+#define PINID_PWM3		STMP3XXX_PINID(2, 3)
+#define PINID_PWM4		STMP3XXX_PINID(2, 4)
+#define PINID_I2C_SCL		STMP3XXX_PINID(2, 5)
+#define PINID_I2C_SDA		STMP3XXX_PINID(2, 6)
+#define PINID_ROTTARYA		STMP3XXX_PINID(2, 7)
+#define PINID_ROTTARYB		STMP3XXX_PINID(2, 8)
+#define PINID_EMI_CKE		STMP3XXX_PINID(2, 9)
+#define PINID_EMI_RASN		STMP3XXX_PINID(2, 10)
+#define PINID_EMI_CASN		STMP3XXX_PINID(2, 11)
+#define PINID_EMI_CE0N		STMP3XXX_PINID(2, 12)
+#define PINID_EMI_CE1N		STMP3XXX_PINID(2, 13)
+#define PINID_EMI_CE2N		STMP3XXX_PINID(2, 14)
+#define PINID_EMI_CE3N		STMP3XXX_PINID(2, 15)
+#define PINID_EMI_A00		STMP3XXX_PINID(2, 16)
+#define PINID_EMI_A01		STMP3XXX_PINID(2, 17)
+#define PINID_EMI_A02		STMP3XXX_PINID(2, 18)
+#define PINID_EMI_A03		STMP3XXX_PINID(2, 19)
+#define PINID_EMI_A04		STMP3XXX_PINID(2, 20)
+#define PINID_EMI_A05		STMP3XXX_PINID(2, 21)
+#define PINID_EMI_A06		STMP3XXX_PINID(2, 22)
+#define PINID_EMI_A07		STMP3XXX_PINID(2, 23)
+#define PINID_EMI_A08		STMP3XXX_PINID(2, 24)
+#define PINID_EMI_A09		STMP3XXX_PINID(2, 25)
+#define PINID_EMI_A10		STMP3XXX_PINID(2, 26)
+#define PINID_EMI_A11		STMP3XXX_PINID(2, 27)
+#define PINID_EMI_A12		STMP3XXX_PINID(2, 28)
+#define PINID_EMI_A13		STMP3XXX_PINID(2, 29)
+#define PINID_EMI_A14		STMP3XXX_PINID(2, 30)
+#define PINID_EMI_WEN		STMP3XXX_PINID(2, 31)
+
+/* Bank 3 */
+#define PINID_EMI_D00		STMP3XXX_PINID(3, 0)
+#define PINID_EMI_D01		STMP3XXX_PINID(3, 1)
+#define PINID_EMI_D02		STMP3XXX_PINID(3, 2)
+#define PINID_EMI_D03		STMP3XXX_PINID(3, 3)
+#define PINID_EMI_D04		STMP3XXX_PINID(3, 4)
+#define PINID_EMI_D05		STMP3XXX_PINID(3, 5)
+#define PINID_EMI_D06		STMP3XXX_PINID(3, 6)
+#define PINID_EMI_D07		STMP3XXX_PINID(3, 7)
+#define PINID_EMI_D08		STMP3XXX_PINID(3, 8)
+#define PINID_EMI_D09		STMP3XXX_PINID(3, 9)
+#define PINID_EMI_D10		STMP3XXX_PINID(3, 10)
+#define PINID_EMI_D11		STMP3XXX_PINID(3, 11)
+#define PINID_EMI_D12		STMP3XXX_PINID(3, 12)
+#define PINID_EMI_D13		STMP3XXX_PINID(3, 13)
+#define PINID_EMI_D14		STMP3XXX_PINID(3, 14)
+#define PINID_EMI_D15		STMP3XXX_PINID(3, 15)
+#define PINID_EMI_DQS0		STMP3XXX_PINID(3, 16)
+#define PINID_EMI_DQS1		STMP3XXX_PINID(3, 17)
+#define PINID_EMI_DQM0		STMP3XXX_PINID(3, 18)
+#define PINID_EMI_DQM1		STMP3XXX_PINID(3, 19)
+#define PINID_EMI_CLK		STMP3XXX_PINID(3, 20)
+#define PINID_EMI_CLKN		STMP3XXX_PINID(3, 21)
+
+#endif /* __ASM_ARCH_PINS_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbh.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbh.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbh.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbh.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,97 @@
+/*
+ * stmp37xx: APBH register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_APBH
+#define _MACH_REGS_APBH
+
+#define REGS_APBH_BASE	(STMP3XXX_REGS_BASE + 0x4000)
+
+#define HW_APBH_CTRL0		0x0
+#define BM_APBH_CTRL0_RESET_CHANNEL	0x00FF0000
+#define BP_APBH_CTRL0_RESET_CHANNEL	16
+#define BM_APBH_CTRL0_CLKGATE	0x40000000
+#define BM_APBH_CTRL0_SFTRST	0x80000000
+
+#define HW_APBH_CTRL1		0x10
+#define BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ	0x00000001
+#define BP_APBH_CTRL1_CH0_CMDCMPLT_IRQ	0
+
+#define HW_APBH_DEVSEL		0x20
+
+#define HW_APBH_CH0_NXTCMDAR	(0x50 + 0 * 0x70)
+#define HW_APBH_CH1_NXTCMDAR	(0x50 + 1 * 0x70)
+#define HW_APBH_CH2_NXTCMDAR	(0x50 + 2 * 0x70)
+#define HW_APBH_CH3_NXTCMDAR	(0x50 + 3 * 0x70)
+#define HW_APBH_CH4_NXTCMDAR	(0x50 + 4 * 0x70)
+#define HW_APBH_CH5_NXTCMDAR	(0x50 + 5 * 0x70)
+#define HW_APBH_CH6_NXTCMDAR	(0x50 + 6 * 0x70)
+#define HW_APBH_CH7_NXTCMDAR	(0x50 + 7 * 0x70)
+#define HW_APBH_CH8_NXTCMDAR	(0x50 + 8 * 0x70)
+#define HW_APBH_CH9_NXTCMDAR	(0x50 + 9 * 0x70)
+#define HW_APBH_CH10_NXTCMDAR	(0x50 + 10 * 0x70)
+#define HW_APBH_CH11_NXTCMDAR	(0x50 + 11 * 0x70)
+#define HW_APBH_CH12_NXTCMDAR	(0x50 + 12 * 0x70)
+#define HW_APBH_CH13_NXTCMDAR	(0x50 + 13 * 0x70)
+#define HW_APBH_CH14_NXTCMDAR	(0x50 + 14 * 0x70)
+#define HW_APBH_CH15_NXTCMDAR	(0x50 + 15 * 0x70)
+
+#define HW_APBH_CHn_NXTCMDAR	0x50
+
+#define BM_APBH_CHn_CMD_MODE		0x00000003
+#define BP_APBH_CHn_CMD_MODE		0x00000001
+#define BV_APBH_CHn_CMD_MODE_NOOP		 0
+#define BV_APBH_CHn_CMD_MODE_WRITE		 1
+#define BV_APBH_CHn_CMD_MODE_READ		 2
+#define BV_APBH_CHn_CMD_MODE_SENSE		 3
+#define BM_APBH_CHn_CMD_CHAIN		0x00000004
+#define BM_APBH_CHn_CMD_IRQONCMPLT	0x00000008
+#define BM_APBH_CHn_CMD_NANDLOCK	0x00000010
+#define BM_APBH_CHn_CMD_NANDWAIT4READY	0x00000020
+#define BM_APBH_CHn_CMD_SEMAPHORE	0x00000040
+#define BM_APBH_CHn_CMD_WAIT4ENDCMD	0x00000080
+#define BM_APBH_CHn_CMD_CMDWORDS	0x0000F000
+#define BP_APBH_CHn_CMD_CMDWORDS	12
+#define BM_APBH_CHn_CMD_XFER_COUNT	0xFFFF0000
+#define BP_APBH_CHn_CMD_XFER_COUNT	16
+
+#define HW_APBH_CH0_SEMA	(0x80 + 0 * 0x70)
+#define HW_APBH_CH1_SEMA	(0x80 + 1 * 0x70)
+#define HW_APBH_CH2_SEMA	(0x80 + 2 * 0x70)
+#define HW_APBH_CH3_SEMA	(0x80 + 3 * 0x70)
+#define HW_APBH_CH4_SEMA	(0x80 + 4 * 0x70)
+#define HW_APBH_CH5_SEMA	(0x80 + 5 * 0x70)
+#define HW_APBH_CH6_SEMA	(0x80 + 6 * 0x70)
+#define HW_APBH_CH7_SEMA	(0x80 + 7 * 0x70)
+#define HW_APBH_CH8_SEMA	(0x80 + 8 * 0x70)
+#define HW_APBH_CH9_SEMA	(0x80 + 9 * 0x70)
+#define HW_APBH_CH10_SEMA	(0x80 + 10 * 0x70)
+#define HW_APBH_CH11_SEMA	(0x80 + 11 * 0x70)
+#define HW_APBH_CH12_SEMA	(0x80 + 12 * 0x70)
+#define HW_APBH_CH13_SEMA	(0x80 + 13 * 0x70)
+#define HW_APBH_CH14_SEMA	(0x80 + 14 * 0x70)
+#define HW_APBH_CH15_SEMA	(0x80 + 15 * 0x70)
+
+#define HW_APBH_CHn_SEMA	0x80
+#define BM_APBH_CHn_SEMA_INCREMENT_SEMA	0x000000FF
+#define BP_APBH_CHn_SEMA_INCREMENT_SEMA	0
+#define BM_APBH_CHn_SEMA_PHORE	0x00FF0000
+#define BP_APBH_CHn_SEMA_PHORE	16
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbx.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-apbx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * stmp37xx: APBX register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_APBX
+#define _MACH_REGS_APBX
+
+#define REGS_APBX_BASE	(STMP3XXX_REGS_BASE + 0x24000)
+
+#define HW_APBX_CTRL0		0x0
+#define BM_APBX_CTRL0_RESET_CHANNEL	0x00FF0000
+#define BP_APBX_CTRL0_RESET_CHANNEL	16
+#define BM_APBX_CTRL0_CLKGATE	0x40000000
+#define BM_APBX_CTRL0_SFTRST	0x80000000
+
+#define HW_APBX_CTRL1		0x10
+
+#define HW_APBX_DEVSEL		0x20
+
+#define HW_APBX_CH0_NXTCMDAR	(0x50 + 0 * 0x70)
+#define HW_APBX_CH1_NXTCMDAR	(0x50 + 1 * 0x70)
+#define HW_APBX_CH2_NXTCMDAR	(0x50 + 2 * 0x70)
+#define HW_APBX_CH3_NXTCMDAR	(0x50 + 3 * 0x70)
+#define HW_APBX_CH4_NXTCMDAR	(0x50 + 4 * 0x70)
+#define HW_APBX_CH5_NXTCMDAR	(0x50 + 5 * 0x70)
+#define HW_APBX_CH6_NXTCMDAR	(0x50 + 6 * 0x70)
+#define HW_APBX_CH7_NXTCMDAR	(0x50 + 7 * 0x70)
+#define HW_APBX_CH8_NXTCMDAR	(0x50 + 8 * 0x70)
+#define HW_APBX_CH9_NXTCMDAR	(0x50 + 9 * 0x70)
+#define HW_APBX_CH10_NXTCMDAR	(0x50 + 10 * 0x70)
+#define HW_APBX_CH11_NXTCMDAR	(0x50 + 11 * 0x70)
+#define HW_APBX_CH12_NXTCMDAR	(0x50 + 12 * 0x70)
+#define HW_APBX_CH13_NXTCMDAR	(0x50 + 13 * 0x70)
+#define HW_APBX_CH14_NXTCMDAR	(0x50 + 14 * 0x70)
+#define HW_APBX_CH15_NXTCMDAR	(0x50 + 15 * 0x70)
+
+#define HW_APBX_CHn_NXTCMDAR	0x50
+#define BM_APBX_CHn_CMD_MODE		0x00000003
+#define BP_APBX_CHn_CMD_MODE		0x00000001
+#define BV_APBX_CHn_CMD_MODE_NOOP		 0
+#define BV_APBX_CHn_CMD_MODE_WRITE		 1
+#define BV_APBX_CHn_CMD_MODE_READ		 2
+#define BV_APBX_CHn_CMD_MODE_SENSE		 3
+#define BM_APBX_CHn_CMD_COMMAND	0x00000003
+#define BP_APBX_CHn_CMD_COMMAND	0
+#define BM_APBX_CHn_CMD_CHAIN	0x00000004
+#define BM_APBX_CHn_CMD_IRQONCMPLT	0x00000008
+#define BM_APBX_CHn_CMD_SEMAPHORE	0x00000040
+#define BM_APBX_CHn_CMD_WAIT4ENDCMD	0x00000080
+#define BM_APBX_CHn_CMD_CMDWORDS	0x0000F000
+#define BP_APBX_CHn_CMD_CMDWORDS	12
+#define BM_APBX_CHn_CMD_XFER_COUNT	0xFFFF0000
+#define BP_APBX_CHn_CMD_XFER_COUNT	16
+
+#define HW_APBX_CH0_BAR		(0x70 + 0 * 0x70)
+#define HW_APBX_CH1_BAR		(0x70 + 1 * 0x70)
+#define HW_APBX_CH2_BAR		(0x70 + 2 * 0x70)
+#define HW_APBX_CH3_BAR		(0x70 + 3 * 0x70)
+#define HW_APBX_CH4_BAR		(0x70 + 4 * 0x70)
+#define HW_APBX_CH5_BAR		(0x70 + 5 * 0x70)
+#define HW_APBX_CH6_BAR		(0x70 + 6 * 0x70)
+#define HW_APBX_CH7_BAR		(0x70 + 7 * 0x70)
+#define HW_APBX_CH8_BAR		(0x70 + 8 * 0x70)
+#define HW_APBX_CH9_BAR		(0x70 + 9 * 0x70)
+#define HW_APBX_CH10_BAR		(0x70 + 10 * 0x70)
+#define HW_APBX_CH11_BAR		(0x70 + 11 * 0x70)
+#define HW_APBX_CH12_BAR		(0x70 + 12 * 0x70)
+#define HW_APBX_CH13_BAR		(0x70 + 13 * 0x70)
+#define HW_APBX_CH14_BAR		(0x70 + 14 * 0x70)
+#define HW_APBX_CH15_BAR		(0x70 + 15 * 0x70)
+
+#define HW_APBX_CHn_BAR		0x70
+
+#define HW_APBX_CH0_SEMA	(0x80 + 0 * 0x70)
+#define HW_APBX_CH1_SEMA	(0x80 + 1 * 0x70)
+#define HW_APBX_CH2_SEMA	(0x80 + 2 * 0x70)
+#define HW_APBX_CH3_SEMA	(0x80 + 3 * 0x70)
+#define HW_APBX_CH4_SEMA	(0x80 + 4 * 0x70)
+#define HW_APBX_CH5_SEMA	(0x80 + 5 * 0x70)
+#define HW_APBX_CH6_SEMA	(0x80 + 6 * 0x70)
+#define HW_APBX_CH7_SEMA	(0x80 + 7 * 0x70)
+#define HW_APBX_CH8_SEMA	(0x80 + 8 * 0x70)
+#define HW_APBX_CH9_SEMA	(0x80 + 9 * 0x70)
+#define HW_APBX_CH10_SEMA	(0x80 + 10 * 0x70)
+#define HW_APBX_CH11_SEMA	(0x80 + 11 * 0x70)
+#define HW_APBX_CH12_SEMA	(0x80 + 12 * 0x70)
+#define HW_APBX_CH13_SEMA	(0x80 + 13 * 0x70)
+#define HW_APBX_CH14_SEMA	(0x80 + 14 * 0x70)
+#define HW_APBX_CH15_SEMA	(0x80 + 15 * 0x70)
+
+#define HW_APBX_CHn_SEMA	0x80
+#define BM_APBX_CHn_SEMA_INCREMENT_SEMA	0x000000FF
+#define BP_APBX_CHn_SEMA_INCREMENT_SEMA	0
+#define BM_APBX_CHn_SEMA_PHORE	0x00FF0000
+#define BP_APBX_CHn_SEMA_PHORE	16
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioin.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioin.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioin.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioin.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * stmp37xx: AUDIOIN register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_AUDIOIN_BASE	(STMP3XXX_REGS_BASE + 0x4C000)
+
+#define HW_AUDIOIN_CTRL		0x0
+#define BM_AUDIOIN_CTRL_RUN	0x00000001
+#define BP_AUDIOIN_CTRL_RUN	0
+#define BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN	0x00000002
+#define BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ	0x00000004
+#define BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ	0x00000008
+#define BM_AUDIOIN_CTRL_WORD_LENGTH	0x00000020
+#define BM_AUDIOIN_CTRL_CLKGATE	0x40000000
+#define BM_AUDIOIN_CTRL_SFTRST	0x80000000
+
+#define HW_AUDIOIN_STAT		0x10
+
+#define HW_AUDIOIN_ADCSRR	0x20
+
+#define HW_AUDIOIN_ADCVOLUME	0x30
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT	0x000000FF
+#define BP_AUDIOIN_ADCVOLUME_VOLUME_RIGHT	0
+#define BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT	0x00FF0000
+#define BP_AUDIOIN_ADCVOLUME_VOLUME_LEFT	16
+
+#define HW_AUDIOIN_ADCDEBUG	0x40
+
+#define HW_AUDIOIN_ADCVOL	0x50
+#define BM_AUDIOIN_ADCVOL_GAIN_RIGHT	0x0000000F
+#define BP_AUDIOIN_ADCVOL_GAIN_RIGHT	0
+#define BM_AUDIOIN_ADCVOL_SELECT_RIGHT	0x00000030
+#define BP_AUDIOIN_ADCVOL_SELECT_RIGHT	4
+#define BM_AUDIOIN_ADCVOL_GAIN_LEFT	0x00000F00
+#define BP_AUDIOIN_ADCVOL_GAIN_LEFT	8
+#define BM_AUDIOIN_ADCVOL_SELECT_LEFT	0x00003000
+#define BP_AUDIOIN_ADCVOL_SELECT_LEFT	12
+#define BM_AUDIOIN_ADCVOL_MUTE	0x01000000
+
+#define HW_AUDIOIN_MICLINE	0x60
+
+#define HW_AUDIOIN_ANACLKCTRL	0x70
+#define BM_AUDIOIN_ANACLKCTRL_CLKGATE	0x80000000
+
+#define HW_AUDIOIN_DATA		0x80
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioout.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioout.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioout.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-audioout.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,111 @@
+/*
+ * stmp37xx: AUDIOOUT register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_AUDIOOUT_BASE	(STMP3XXX_REGS_BASE + 0x48000)
+
+#define HW_AUDIOOUT_CTRL	0x0
+#define BM_AUDIOOUT_CTRL_RUN	0x00000001
+#define BP_AUDIOOUT_CTRL_RUN	0
+#define BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN	0x00000002
+#define BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ	0x00000004
+#define BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ	0x00000008
+#define BM_AUDIOOUT_CTRL_WORD_LENGTH	0x00000040
+#define BM_AUDIOOUT_CTRL_CLKGATE	0x40000000
+#define BM_AUDIOOUT_CTRL_SFTRST	0x80000000
+
+#define HW_AUDIOOUT_STAT	0x10
+
+#define HW_AUDIOOUT_DACSRR	0x20
+#define BM_AUDIOOUT_DACSRR_SRC_FRAC	0x00001FFF
+#define BP_AUDIOOUT_DACSRR_SRC_FRAC	0
+#define BM_AUDIOOUT_DACSRR_SRC_INT	0x001F0000
+#define BP_AUDIOOUT_DACSRR_SRC_INT	16
+#define BM_AUDIOOUT_DACSRR_SRC_HOLD	0x07000000
+#define BP_AUDIOOUT_DACSRR_SRC_HOLD	24
+#define BM_AUDIOOUT_DACSRR_BASEMULT	0x70000000
+#define BP_AUDIOOUT_DACSRR_BASEMULT	28
+
+#define HW_AUDIOOUT_DACVOLUME	0x30
+#define BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT	0x00000100
+#define BM_AUDIOOUT_DACVOLUME_MUTE_LEFT	0x01000000
+#define BM_AUDIOOUT_DACVOLUME_EN_ZCD	0x02000000
+
+#define HW_AUDIOOUT_DACDEBUG	0x40
+
+#define HW_AUDIOOUT_HPVOL	0x50
+#define BM_AUDIOOUT_HPVOL_MUTE	0x01000000
+#define BM_AUDIOOUT_HPVOL_EN_MSTR_ZCD	0x02000000
+
+#define HW_AUDIOOUT_PWRDN	0x70
+#define BM_AUDIOOUT_PWRDN_HEADPHONE	0x00000001
+#define BP_AUDIOOUT_PWRDN_HEADPHONE	0
+#define BM_AUDIOOUT_PWRDN_CAPLESS	0x00000010
+#define BM_AUDIOOUT_PWRDN_ADC	0x00000100
+#define BM_AUDIOOUT_PWRDN_DAC	0x00001000
+#define BM_AUDIOOUT_PWRDN_RIGHT_ADC	0x00010000
+#define BM_AUDIOOUT_PWRDN_LINEOUT	0x01000000
+
+#define HW_AUDIOOUT_REFCTRL	0x80
+#define BM_AUDIOOUT_REFCTRL_VAG_VAL	0x000000F0
+#define BP_AUDIOOUT_REFCTRL_VAG_VAL	4
+#define BM_AUDIOOUT_REFCTRL_ADC_REFVAL	0x00000F00
+#define BP_AUDIOOUT_REFCTRL_ADC_REFVAL	8
+#define BM_AUDIOOUT_REFCTRL_ADJ_VAG	0x00001000
+#define BM_AUDIOOUT_REFCTRL_ADJ_ADC	0x00002000
+#define BM_AUDIOOUT_REFCTRL_BIAS_CTRL	0x00030000
+#define BP_AUDIOOUT_REFCTRL_BIAS_CTRL	16
+#define BM_AUDIOOUT_REFCTRL_LOW_PWR	0x00080000
+#define BM_AUDIOOUT_REFCTRL_VBG_ADJ	0x00700000
+#define BP_AUDIOOUT_REFCTRL_VBG_ADJ	20
+#define BM_AUDIOOUT_REFCTRL_XTAL_BGR_BIAS	0x01000000
+#define BM_AUDIOOUT_REFCTRL_RAISE_REF	0x02000000
+
+#define HW_AUDIOOUT_ANACTRL	0x90
+#define BM_AUDIOOUT_ANACTRL_HP_CLASSAB	0x00000010
+#define BM_AUDIOOUT_ANACTRL_HP_HOLD_GND	0x00000020
+
+#define HW_AUDIOOUT_TEST	0xA0
+#define BM_AUDIOOUT_TEST_HP_I1_ADJ	0x00C00000
+#define BP_AUDIOOUT_TEST_HP_I1_ADJ	22
+
+#define HW_AUDIOOUT_BISTCTRL	0xB0
+
+#define HW_AUDIOOUT_BISTSTAT0	0xC0
+
+#define HW_AUDIOOUT_BISTSTAT1	0xD0
+
+#define HW_AUDIOOUT_ANACLKCTRL	0xE0
+#define BM_AUDIOOUT_ANACLKCTRL_CLKGATE	0x80000000
+
+#define HW_AUDIOOUT_DATA	0xF0
+
+#define HW_AUDIOOUT_LINEOUTCTRL	0x100
+#define BM_AUDIOOUT_LINEOUTCTRL_VOL_RIGHT	0x0000001F
+#define BP_AUDIOOUT_LINEOUTCTRL_VOL_RIGHT	0
+#define BM_AUDIOOUT_LINEOUTCTRL_VOL_LEFT	0x00001F00
+#define BP_AUDIOOUT_LINEOUTCTRL_VOL_LEFT	8
+#define BM_AUDIOOUT_LINEOUTCTRL_CHARGE_CAP	0x00007000
+#define BP_AUDIOOUT_LINEOUTCTRL_CHARGE_CAP	12
+#define BM_AUDIOOUT_LINEOUTCTRL_VAG_CTRL	0x00F00000
+#define BP_AUDIOOUT_LINEOUTCTRL_VAG_CTRL	20
+#define BM_AUDIOOUT_LINEOUTCTRL_MUTE	0x01000000
+#define BM_AUDIOOUT_LINEOUTCTRL_EN_ZCD	0x02000000
+
+#define HW_AUDIOOUT_VERSION	0x200
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-clkctrl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * stmp37xx: CLKCTRL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_CLKCTRL
+#define _MACH_REGS_CLKCTRL
+
+#define REGS_CLKCTRL_BASE	(STMP3XXX_REGS_BASE + 0x40000)
+
+#define HW_CLKCTRL_PLLCTRL0	0x0
+#define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS	0x00040000
+
+#define HW_CLKCTRL_CPU		0x20
+#define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
+#define BP_CLKCTRL_CPU_DIV_CPU	0
+
+#define HW_CLKCTRL_HBUS		0x30
+#define BM_CLKCTRL_HBUS_DIV	0x0000001F
+#define BP_CLKCTRL_HBUS_DIV	0
+
+#define HW_CLKCTRL_XBUS		0x40
+
+#define HW_CLKCTRL_XTAL		0x50
+
+#define HW_CLKCTRL_PIX		0x60
+#define BM_CLKCTRL_PIX_DIV	0x00007FFF
+#define BP_CLKCTRL_PIX_DIV	0
+#define BM_CLKCTRL_PIX_CLKGATE	0x80000000
+
+#define HW_CLKCTRL_SSP		0x70
+
+#define HW_CLKCTRL_GPMI		0x80
+
+#define HW_CLKCTRL_SPDIF	0x90
+
+#define HW_CLKCTRL_EMI		0xA0
+
+#define HW_CLKCTRL_IR		0xB0
+
+#define HW_CLKCTRL_SAIF		0xC0
+
+#define HW_CLKCTRL_FRAC		0xD0
+#define BM_CLKCTRL_FRAC_EMIFRAC	0x00003F00
+#define BP_CLKCTRL_FRAC_EMIFRAC	8
+#define BM_CLKCTRL_FRAC_PIXFRAC	0x003F0000
+#define BP_CLKCTRL_FRAC_PIXFRAC	16
+#define BM_CLKCTRL_FRAC_CLKGATEPIX	0x00800000
+
+#define HW_CLKCTRL_CLKSEQ	0xE0
+#define BM_CLKCTRL_CLKSEQ_BYPASS_PIX	0x00000002
+
+#define HW_CLKCTRL_RESET	0xF0
+#define BM_CLKCTRL_RESET_DIG	0x00000001
+#define BP_CLKCTRL_RESET_DIG	0
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-digctl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-digctl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-digctl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-digctl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * stmp37xx: DIGCTL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_DIGCTL_BASE	(STMP3XXX_REGS_BASE + 0x1C000)
+
+#define HW_DIGCTL_CTRL		0x0
+#define BM_DIGCTL_CTRL_USB_CLKGATE	0x00000004
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ecc8.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ecc8.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ecc8.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ecc8.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ * stmp37xx: ECC8 register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_ECC8_BASE	(STMP3XXX_REGS_BASE + 0x8000)
+
+#define HW_ECC8_CTRL		0x0
+#define BM_ECC8_CTRL_COMPLETE_IRQ	0x00000001
+#define BP_ECC8_CTRL_COMPLETE_IRQ	0
+#define BM_ECC8_CTRL_COMPLETE_IRQ_EN	0x00000100
+#define BM_ECC8_CTRL_AHBM_SFTRST	0x20000000
+
+#define HW_ECC8_STATUS0		0x10
+#define BM_ECC8_STATUS0_UNCORRECTABLE	0x00000004
+#define BM_ECC8_STATUS0_CORRECTED	0x00000008
+#define BM_ECC8_STATUS0_STATUS_AUX	0x00000F00
+#define BP_ECC8_STATUS0_STATUS_AUX	8
+#define BM_ECC8_STATUS0_COMPLETED_CE	0x000F0000
+#define BP_ECC8_STATUS0_COMPLETED_CE	16
+
+#define HW_ECC8_STATUS1		0x20
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-gpmi.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-gpmi.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-gpmi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-gpmi.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * stmp37xx: GPMI register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_GPMI_BASE	(STMP3XXX_REGS_BASE + 0xC000)
+#define REGS_GPMI_PHYS	0x8000C000
+#define REGS_GPMI_SIZE	0x2000
+
+#define HW_GPMI_CTRL0		0x0
+#define BM_GPMI_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_GPMI_CTRL0_XFER_COUNT	0
+#define BM_GPMI_CTRL0_CS	0x00300000
+#define BP_GPMI_CTRL0_CS	20
+#define BM_GPMI_CTRL0_LOCK_CS	0x00400000
+#define BM_GPMI_CTRL0_WORD_LENGTH	0x00800000
+#define BM_GPMI_CTRL0_COMMAND_MODE	0x03000000
+#define BP_GPMI_CTRL0_COMMAND_MODE	24
+#define BV_GPMI_CTRL0_COMMAND_MODE__WRITE	    0x0
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ	     0x1
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ_AND_COMPARE 0x2
+#define BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY   0x3
+#define BM_GPMI_CTRL0_RUN	0x20000000
+#define BM_GPMI_CTRL0_CLKGATE	0x40000000
+#define BM_GPMI_CTRL0_SFTRST	0x80000000
+#define BM_GPMI_ECCCTRL_ENABLE_ECC	0x00001000
+#define BM_GPMI_ECCCTRL_ECC_CMD	0x00006000
+#define BP_GPMI_ECCCTRL_ECC_CMD	13
+
+#define HW_GPMI_CTRL1		0x60
+#define BM_GPMI_CTRL1_GPMI_MODE	0x00000003
+#define BP_GPMI_CTRL1_GPMI_MODE	0
+#define BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY	0x00000004
+#define BM_GPMI_CTRL1_DEV_RESET	0x00000008
+#define BM_GPMI_CTRL1_TIMEOUT_IRQ	0x00000200
+#define BM_GPMI_CTRL1_DEV_IRQ	0x00000400
+#define BM_GPMI_CTRL1_DSAMPLE_TIME	0x00007000
+#define BP_GPMI_CTRL1_DSAMPLE_TIME	12
+
+#define HW_GPMI_TIMING0		0x70
+#define BM_GPMI_TIMING0_DATA_SETUP	0x000000FF
+#define BP_GPMI_TIMING0_DATA_SETUP	0
+#define BM_GPMI_TIMING0_DATA_HOLD	0x0000FF00
+#define BP_GPMI_TIMING0_DATA_HOLD	8
+
+#define HW_GPMI_TIMING1		0x80
+#define BM_GPMI_TIMING1_DEVICE_BUSY_TIMEOUT	0xFFFF0000
+#define BP_GPMI_TIMING1_DEVICE_BUSY_TIMEOUT	16
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-i2c.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-i2c.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-i2c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-i2c.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * stmp37xx: I2C register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_I2C_BASE	(STMP3XXX_REGS_BASE + 0x58000)
+#define REGS_I2C_PHYS	0x80058000
+#define REGS_I2C_SIZE	0x2000
+
+#define HW_I2C_CTRL0		0x0
+#define BM_I2C_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_I2C_CTRL0_XFER_COUNT	0
+#define BM_I2C_CTRL0_DIRECTION	0x00010000
+#define BM_I2C_CTRL0_MASTER_MODE	0x00020000
+#define BM_I2C_CTRL0_PRE_SEND_START	0x00080000
+#define BM_I2C_CTRL0_POST_SEND_STOP	0x00100000
+#define BM_I2C_CTRL0_RETAIN_CLOCK	0x00200000
+#define BM_I2C_CTRL0_SEND_NAK_ON_LAST	0x02000000
+#define BM_I2C_CTRL0_CLKGATE	0x40000000
+#define BM_I2C_CTRL0_SFTRST	0x80000000
+
+#define HW_I2C_TIMING0		0x10
+
+#define HW_I2C_TIMING1		0x20
+
+#define HW_I2C_TIMING2		0x30
+
+#define HW_I2C_CTRL1		0x40
+#define BM_I2C_CTRL1_SLAVE_IRQ	0x00000001
+#define BP_I2C_CTRL1_SLAVE_IRQ	0
+#define BM_I2C_CTRL1_SLAVE_STOP_IRQ	0x00000002
+#define BM_I2C_CTRL1_MASTER_LOSS_IRQ	0x00000004
+#define BM_I2C_CTRL1_EARLY_TERM_IRQ	0x00000008
+#define BM_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	0x00000010
+#define BM_I2C_CTRL1_NO_SLAVE_ACK_IRQ	0x00000020
+#define BM_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ	0x00000040
+#define BM_I2C_CTRL1_BUS_FREE_IRQ	0x00000080
+#define BM_I2C_CTRL1_CLR_GOT_A_NAK	0x10000000
+
+#define HW_I2C_VERSION		0x90
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-icoll.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-icoll.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-icoll.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-icoll.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * stmp37xx: ICOLL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_ICOLL
+#define _MACH_REGS_ICOLL
+
+#define REGS_ICOLL_BASE	(STMP3XXX_REGS_BASE + 0x0)
+
+#define HW_ICOLL_VECTOR		0x0
+
+#define HW_ICOLL_LEVELACK	0x10
+
+#define HW_ICOLL_CTRL		0x20
+#define BM_ICOLL_CTRL_CLKGATE	0x40000000
+#define BM_ICOLL_CTRL_SFTRST	0x80000000
+
+#define HW_ICOLL_STAT		0x30
+
+#define HW_ICOLL_PRIORITY0	(0x60 + 0 * 0x10)
+#define HW_ICOLL_PRIORITY1	(0x60 + 1 * 0x10)
+#define HW_ICOLL_PRIORITY2	(0x60 + 2 * 0x10)
+#define HW_ICOLL_PRIORITY3	(0x60 + 3 * 0x10)
+
+#define HW_ICOLL_PRIORITYn	0x60
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lcdif.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lcdif.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lcdif.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lcdif.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,89 @@
+/*
+ * stmp37xx: LCDIF register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_LCDIF_BASE	(STMP3XXX_REGS_BASE + 0x30000)
+#define REGS_LCDIF_PHYS	0x80030000
+#define REGS_LCDIF_SIZE	0x2000
+
+#define HW_LCDIF_CTRL		0x0
+#define BM_LCDIF_CTRL_COUNT	0x0000FFFF
+#define BP_LCDIF_CTRL_COUNT	0
+#define BM_LCDIF_CTRL_RUN	0x00010000
+#define BM_LCDIF_CTRL_WORD_LENGTH	0x00020000
+#define BM_LCDIF_CTRL_DATA_SELECT	0x00040000
+#define BM_LCDIF_CTRL_DOTCLK_MODE	0x00080000
+#define BM_LCDIF_CTRL_VSYNC_MODE	0x00100000
+#define BM_LCDIF_CTRL_DATA_SWIZZLE	0x00600000
+#define BP_LCDIF_CTRL_DATA_SWIZZLE	21
+#define BM_LCDIF_CTRL_BYPASS_COUNT	0x00800000
+#define BM_LCDIF_CTRL_SHIFT_NUM_BITS	0x06000000
+#define BP_LCDIF_CTRL_SHIFT_NUM_BITS	25
+#define BM_LCDIF_CTRL_DATA_SHIFT_DIR	0x08000000
+#define BM_LCDIF_CTRL_WAIT_FOR_VSYNC_EDGE	0x10000000
+#define BM_LCDIF_CTRL_CLKGATE	0x40000000
+#define BM_LCDIF_CTRL_SFTRST	0x80000000
+
+#define HW_LCDIF_CTRL1		0x10
+#define BM_LCDIF_CTRL1_RESET	0x00000001
+#define BP_LCDIF_CTRL1_RESET	0
+#define BM_LCDIF_CTRL1_MODE86	0x00000002
+#define BM_LCDIF_CTRL1_BUSY_ENABLE	0x00000004
+#define BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ	0x00000100
+#define BM_LCDIF_CTRL1_CUR_FRAME_DONE_IRQ	0x00000200
+#define BM_LCDIF_CTRL1_UNDERFLOW_IRQ	0x00000400
+#define BM_LCDIF_CTRL1_OVERFLOW_IRQ	0x00000800
+#define BM_LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN	0x00001000
+#define BM_LCDIF_CTRL1_BYTE_PACKING_FORMAT	0x000F0000
+#define BP_LCDIF_CTRL1_BYTE_PACKING_FORMAT	16
+
+#define HW_LCDIF_TIMING		0x20
+
+#define HW_LCDIF_VDCTRL0	0x30
+#define BM_LCDIF_VDCTRL0_VALID_DATA_CNT	0x000003FF
+#define BP_LCDIF_VDCTRL0_VALID_DATA_CNT	0
+#define BM_LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	0x00100000
+#define BM_LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT	0x00200000
+#define BM_LCDIF_VDCTRL0_ENABLE_POL	0x01000000
+#define BM_LCDIF_VDCTRL0_DOTCLK_POL	0x02000000
+#define BM_LCDIF_VDCTRL0_HSYNC_POL	0x04000000
+#define BM_LCDIF_VDCTRL0_VSYNC_POL	0x08000000
+#define BM_LCDIF_VDCTRL0_ENABLE_PRESENT	0x10000000
+#define BM_LCDIF_VDCTRL0_VSYNC_OEB	0x20000000
+
+#define HW_LCDIF_VDCTRL1	0x40
+#define BM_LCDIF_VDCTRL1_VSYNC_PERIOD	0x000FFFFF
+#define BP_LCDIF_VDCTRL1_VSYNC_PERIOD	0
+#define BM_LCDIF_VDCTRL1_VSYNC_PULSE_WIDTH	0xFFF00000
+#define BP_LCDIF_VDCTRL1_VSYNC_PULSE_WIDTH	20
+
+#define HW_LCDIF_VDCTRL2	0x50
+#define BM_LCDIF_VDCTRL2_VALID_DATA_CNT	0x000007FF
+#define BP_LCDIF_VDCTRL2_VALID_DATA_CNT	0
+#define BM_LCDIF_VDCTRL2_HSYNC_PERIOD	0x007FF800
+#define BP_LCDIF_VDCTRL2_HSYNC_PERIOD	11
+#define BM_LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH	0xFF800000
+#define BP_LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH	23
+
+#define HW_LCDIF_VDCTRL3	0x60
+#define BM_LCDIF_VDCTRL3_VERTICAL_WAIT_CNT	0x000001FF
+#define BP_LCDIF_VDCTRL3_VERTICAL_WAIT_CNT	0
+#define BM_LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT	0x00FFF000
+#define BP_LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT	12
+#define BM_LCDIF_VDCTRL3_SYNC_SIGNALS_ON	0x01000000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lradc.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lradc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lradc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-lradc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,97 @@
+/*
+ * stmp37xx: LRADC register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_LRADC_BASE	(STMP3XXX_REGS_BASE + 0x50000)
+
+#define HW_LRADC_CTRL0		0x0
+#define BM_LRADC_CTRL0_SCHEDULE	0x000000FF
+#define BP_LRADC_CTRL0_SCHEDULE	0
+#define BM_LRADC_CTRL0_XPLUS_ENABLE	0x00010000
+#define BM_LRADC_CTRL0_YPLUS_ENABLE	0x00020000
+#define BM_LRADC_CTRL0_XMINUS_ENABLE	0x00040000
+#define BM_LRADC_CTRL0_YMINUS_ENABLE	0x00080000
+#define BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE	0x00100000
+#define BM_LRADC_CTRL0_ONCHIP_GROUNDREF	0x00200000
+#define BM_LRADC_CTRL0_CLKGATE	0x40000000
+#define BM_LRADC_CTRL0_SFTRST	0x80000000
+
+#define HW_LRADC_CTRL1		0x10
+#define BM_LRADC_CTRL1_LRADC0_IRQ	0x00000001
+#define BP_LRADC_CTRL1_LRADC0_IRQ	0
+#define BM_LRADC_CTRL1_LRADC5_IRQ	0x00000020
+#define BM_LRADC_CTRL1_LRADC6_IRQ	0x00000040
+#define BM_LRADC_CTRL1_TOUCH_DETECT_IRQ	0x00000100
+#define BM_LRADC_CTRL1_LRADC0_IRQ_EN	0x00010000
+#define BM_LRADC_CTRL1_LRADC5_IRQ_EN	0x00200000
+#define BM_LRADC_CTRL1_TOUCH_DETECT_IRQ_EN	0x01000000
+
+#define HW_LRADC_CTRL2		0x20
+#define BM_LRADC_CTRL2_BL_BRIGHTNESS	0x001F0000
+#define BP_LRADC_CTRL2_BL_BRIGHTNESS	16
+#define BM_LRADC_CTRL2_BL_MUX_SELECT	0x00200000
+#define BM_LRADC_CTRL2_BL_ENABLE	0x00400000
+#define BM_LRADC_CTRL2_DIVIDE_BY_TWO	0xFF000000
+#define BP_LRADC_CTRL2_DIVIDE_BY_TWO	24
+
+#define HW_LRADC_CTRL3		0x30
+#define BM_LRADC_CTRL3_CYCLE_TIME	0x00000300
+#define BP_LRADC_CTRL3_CYCLE_TIME	8
+
+#define HW_LRADC_STATUS		0x40
+#define BM_LRADC_STATUS_TOUCH_DETECT_RAW	0x00000001
+#define BP_LRADC_STATUS_TOUCH_DETECT_RAW	0
+
+#define HW_LRADC_CH0		(0x50 + 0 * 0x10)
+#define HW_LRADC_CH1		(0x50 + 1 * 0x10)
+#define HW_LRADC_CH2		(0x50 + 2 * 0x10)
+#define HW_LRADC_CH3		(0x50 + 3 * 0x10)
+#define HW_LRADC_CH4		(0x50 + 4 * 0x10)
+#define HW_LRADC_CH5		(0x50 + 5 * 0x10)
+#define HW_LRADC_CH6		(0x50 + 6 * 0x10)
+#define HW_LRADC_CH7		(0x50 + 7 * 0x10)
+
+#define HW_LRADC_CHn		0x50
+#define BM_LRADC_CHn_VALUE	0x0003FFFF
+#define BP_LRADC_CHn_VALUE	0
+#define BM_LRADC_CHn_NUM_SAMPLES	0x1F000000
+#define BP_LRADC_CHn_NUM_SAMPLES	24
+#define BM_LRADC_CHn_ACCUMULATE	0x20000000
+
+#define HW_LRADC_DELAY0		(0xD0 + 0 * 0x10)
+#define HW_LRADC_DELAY1		(0xD0 + 1 * 0x10)
+#define HW_LRADC_DELAY2		(0xD0 + 2 * 0x10)
+#define HW_LRADC_DELAY3		(0xD0 + 3 * 0x10)
+
+#define HW_LRADC_DELAYn		0xD0
+#define BM_LRADC_DELAYn_DELAY	0x000007FF
+#define BP_LRADC_DELAYn_DELAY	0
+#define BM_LRADC_DELAYn_LOOP_COUNT	0x0000F800
+#define BP_LRADC_DELAYn_LOOP_COUNT	11
+#define BM_LRADC_DELAYn_TRIGGER_DELAYS	0x000F0000
+#define BP_LRADC_DELAYn_TRIGGER_DELAYS	16
+#define BM_LRADC_DELAYn_KICK	0x00100000
+#define BM_LRADC_DELAYn_TRIGGER_LRADCS	0xFF000000
+#define BP_LRADC_DELAYn_TRIGGER_LRADCS	24
+
+#define HW_LRADC_CTRL4		0x140
+#define BM_LRADC_CTRL4_LRADC6SELECT	0x0F000000
+#define BP_LRADC_CTRL4_LRADC6SELECT	24
+#define BM_LRADC_CTRL4_LRADC7SELECT	0xF0000000
+#define BP_LRADC_CTRL4_LRADC7SELECT	28
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pinctrl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,88 @@
+/*
+ * stmp37xx: PINCTRL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_PINCTRL
+#define _MACH_REGS_PINCTRL
+
+#define REGS_PINCTRL_BASE	(STMP3XXX_REGS_BASE + 0x18000)
+
+#define HW_PINCTRL_MUXSEL0	0x100
+#define HW_PINCTRL_MUXSEL1	0x110
+#define HW_PINCTRL_MUXSEL2	0x120
+#define HW_PINCTRL_MUXSEL3	0x130
+#define HW_PINCTRL_MUXSEL4	0x140
+#define HW_PINCTRL_MUXSEL5	0x150
+#define HW_PINCTRL_MUXSEL6	0x160
+#define HW_PINCTRL_MUXSEL7	0x170
+
+#define HW_PINCTRL_DRIVE0	0x200
+#define HW_PINCTRL_DRIVE1	0x210
+#define HW_PINCTRL_DRIVE2	0x220
+#define HW_PINCTRL_DRIVE3	0x230
+#define HW_PINCTRL_DRIVE4	0x240
+#define HW_PINCTRL_DRIVE5	0x250
+#define HW_PINCTRL_DRIVE6	0x260
+#define HW_PINCTRL_DRIVE7	0x270
+#define HW_PINCTRL_DRIVE8	0x280
+#define HW_PINCTRL_DRIVE9	0x290
+#define HW_PINCTRL_DRIVE10	0x2A0
+#define HW_PINCTRL_DRIVE11	0x2B0
+#define HW_PINCTRL_DRIVE12	0x2C0
+#define HW_PINCTRL_DRIVE13	0x2D0
+#define HW_PINCTRL_DRIVE14	0x2E0
+
+#define HW_PINCTRL_PULL0	0x300
+#define HW_PINCTRL_PULL1	0x310
+#define HW_PINCTRL_PULL2	0x320
+#define HW_PINCTRL_PULL3	0x330
+
+#define HW_PINCTRL_DOUT0	0x400
+#define HW_PINCTRL_DOUT1	0x410
+#define HW_PINCTRL_DOUT2	0x420
+
+#define HW_PINCTRL_DIN0		0x500
+#define HW_PINCTRL_DIN1		0x510
+#define HW_PINCTRL_DIN2		0x520
+
+#define HW_PINCTRL_DOE0		0x600
+#define HW_PINCTRL_DOE1		0x610
+#define HW_PINCTRL_DOE2		0x620
+
+#define HW_PINCTRL_PIN2IRQ0	0x700
+#define HW_PINCTRL_PIN2IRQ1	0x710
+#define HW_PINCTRL_PIN2IRQ2	0x720
+
+#define HW_PINCTRL_IRQEN0	0x800
+#define HW_PINCTRL_IRQEN1	0x810
+#define HW_PINCTRL_IRQEN2	0x820
+
+#define HW_PINCTRL_IRQLEVEL0	0x900
+#define HW_PINCTRL_IRQLEVEL1	0x910
+#define HW_PINCTRL_IRQLEVEL2	0x920
+
+#define HW_PINCTRL_IRQPOL0	0xA00
+#define HW_PINCTRL_IRQPOL1	0xA10
+#define HW_PINCTRL_IRQPOL2	0xA20
+
+#define HW_PINCTRL_IRQSTAT0	0xB00
+#define HW_PINCTRL_IRQSTAT1	0xB10
+#define HW_PINCTRL_IRQSTAT2	0xB20
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-power.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-power.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-power.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-power.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * stmp37xx: POWER register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_POWER
+#define _MACH_REGS_POWER
+
+#define REGS_POWER_BASE	(STMP3XXX_REGS_BASE + 0x44000)
+
+#define HW_POWER_CTRL		0x0
+#define BM_POWER_CTRL_CLKGATE	0x40000000
+
+#define HW_POWER_5VCTRL		0x10
+
+#define HW_POWER_MINPWR		0x20
+
+#define HW_POWER_CHARGE		0x30
+
+#define HW_POWER_VDDDCTRL	0x40
+
+#define HW_POWER_VDDACTRL	0x50
+
+#define HW_POWER_VDDIOCTRL	0x60
+#define BM_POWER_VDDIOCTRL_TRG	0x0000001F
+#define BP_POWER_VDDIOCTRL_TRG	0
+
+#define HW_POWER_STS		0xB0
+#define BM_POWER_STS_VBUSVALID	0x00000002
+#define BM_POWER_STS_BVALID	0x00000004
+#define BM_POWER_STS_AVALID	0x00000008
+#define BM_POWER_STS_DC_OK	0x00000100
+
+#define HW_POWER_RESET		0xE0
+
+#define HW_POWER_DEBUG		0xF0
+#define BM_POWER_DEBUG_BVALIDPIOLOCK	0x00000002
+#define BM_POWER_DEBUG_AVALIDPIOLOCK	0x00000004
+#define BM_POWER_DEBUG_VBUSVALIDPIOLOCK	0x00000008
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pwm.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pwm.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pwm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-pwm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * stmp37xx: PWM register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_PWM_BASE	(STMP3XXX_REGS_BASE + 0x64000)
+
+#define HW_PWM_CTRL		0x0
+#define BM_PWM_CTRL_PWM2_ENABLE	0x00000004
+#define BM_PWM_CTRL_PWM2_ANA_CTRL_ENABLE	0x00000020
+
+#define HW_PWM_ACTIVE0		(0x10 + 0 * 0x20)
+#define HW_PWM_ACTIVE1		(0x10 + 1 * 0x20)
+#define HW_PWM_ACTIVE2		(0x10 + 2 * 0x20)
+#define HW_PWM_ACTIVE3		(0x10 + 3 * 0x20)
+
+#define HW_PWM_ACTIVEn		0x10
+#define BM_PWM_ACTIVEn_ACTIVE	0x0000FFFF
+#define BP_PWM_ACTIVEn_ACTIVE	0
+#define BM_PWM_ACTIVEn_INACTIVE	0xFFFF0000
+#define BP_PWM_ACTIVEn_INACTIVE	16
+
+#define HW_PWM_PERIOD0		(0x20 + 0 * 0x20)
+#define HW_PWM_PERIOD1		(0x20 + 1 * 0x20)
+#define HW_PWM_PERIOD2		(0x20 + 2 * 0x20)
+#define HW_PWM_PERIOD3		(0x20 + 3 * 0x20)
+
+#define HW_PWM_PERIODn		0x20
+#define BM_PWM_PERIODn_PERIOD	0x0000FFFF
+#define BP_PWM_PERIODn_PERIOD	0
+#define BM_PWM_PERIODn_ACTIVE_STATE	0x00030000
+#define BP_PWM_PERIODn_ACTIVE_STATE	16
+#define BM_PWM_PERIODn_INACTIVE_STATE	0x000C0000
+#define BP_PWM_PERIODn_INACTIVE_STATE	18
+#define BM_PWM_PERIODn_CDIV	0x00700000
+#define BP_PWM_PERIODn_CDIV	20
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-rtc.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-rtc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-rtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-rtc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * stmp37xx: RTC register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_RTC_BASE	(STMP3XXX_REGS_BASE + 0x5C000)
+#define REGS_RTC_PHYS   0x8005C000
+#define REGS_RTC_SIZE   0x2000
+
+#define HW_RTC_CTRL		0x0
+#define BM_RTC_CTRL_ALARM_IRQ_EN	0x00000001
+#define BP_RTC_CTRL_ALARM_IRQ_EN	0
+#define BM_RTC_CTRL_ONEMSEC_IRQ_EN	0x00000002
+#define BM_RTC_CTRL_ALARM_IRQ	0x00000004
+#define BM_RTC_CTRL_ONEMSEC_IRQ	0x00000008
+#define BM_RTC_CTRL_WATCHDOGEN	0x00000010
+
+#define HW_RTC_STAT		0x10
+#define BM_RTC_STAT_NEW_REGS	0x0000FF00
+#define BP_RTC_STAT_NEW_REGS	8
+#define BM_RTC_STAT_STALE_REGS	0x00FF0000
+#define BP_RTC_STAT_STALE_REGS	16
+#define BM_RTC_STAT_RTC_PRESENT	0x80000000
+
+#define HW_RTC_SECONDS		0x30
+
+#define HW_RTC_ALARM		0x40
+
+#define HW_RTC_WATCHDOG		0x50
+
+#define HW_RTC_PERSISTENT0	0x60
+#define BM_RTC_PERSISTENT0_ALARM_WAKE_EN	0x00000002
+#define BM_RTC_PERSISTENT0_ALARM_EN	0x00000004
+#define BM_RTC_PERSISTENT0_XTAL24MHZ_PWRUP	0x00000010
+#define BM_RTC_PERSISTENT0_XTAL32KHZ_PWRUP	0x00000020
+#define BM_RTC_PERSISTENT0_ALARM_WAKE	0x00000080
+#define BM_RTC_PERSISTENT0_SPARE_ANALOG	0xFFFC0000
+#define BP_RTC_PERSISTENT0_SPARE_ANALOG	18
+
+#define HW_RTC_PERSISTENT1	0x70
+
+#define HW_RTC_VERSION		0xD0
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ssp.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ssp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ssp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-ssp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,101 @@
+/*
+ * stmp37xx: SSP register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_SSP_BASE	(STMP3XXX_REGS_BASE + 0x10000)
+#define REGS_SSP1_PHYS	0x80010000
+#define REGS_SSP2_PHYS	0x80034000
+#define REGS_SSP_SIZE	0x2000
+
+#define HW_SSP_CTRL0		0x0
+#define BM_SSP_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_SSP_CTRL0_XFER_COUNT	0
+#define BM_SSP_CTRL0_ENABLE	0x00010000
+#define BM_SSP_CTRL0_GET_RESP	0x00020000
+#define BM_SSP_CTRL0_LONG_RESP	0x00080000
+#define BM_SSP_CTRL0_WAIT_FOR_CMD	0x00100000
+#define BM_SSP_CTRL0_WAIT_FOR_IRQ	0x00200000
+#define BM_SSP_CTRL0_BUS_WIDTH	0x00C00000
+#define BP_SSP_CTRL0_BUS_WIDTH	22
+#define BM_SSP_CTRL0_DATA_XFER	0x01000000
+#define BM_SSP_CTRL0_READ	0x02000000
+#define BM_SSP_CTRL0_IGNORE_CRC	0x04000000
+#define BM_SSP_CTRL0_LOCK_CS	0x08000000
+#define BM_SSP_CTRL0_RUN	0x20000000
+#define BM_SSP_CTRL0_CLKGATE	0x40000000
+#define BM_SSP_CTRL0_SFTRST	0x80000000
+
+#define HW_SSP_CMD0		0x10
+#define BM_SSP_CMD0_CMD		0x000000FF
+#define BP_SSP_CMD0_CMD		0
+#define BM_SSP_CMD0_BLOCK_COUNT	0x0000FF00
+#define BP_SSP_CMD0_BLOCK_COUNT	8
+#define BM_SSP_CMD0_BLOCK_SIZE	0x000F0000
+#define BP_SSP_CMD0_BLOCK_SIZE	16
+#define BM_SSP_CMD0_APPEND_8CYC	0x00100000
+#define BM_SSP_CMD1_CMD_ARG	0xFFFFFFFF
+#define BP_SSP_CMD1_CMD_ARG	0
+
+#define HW_SSP_TIMING		0x50
+#define BM_SSP_TIMING_CLOCK_RATE	0x000000FF
+#define BP_SSP_TIMING_CLOCK_RATE	0
+#define BM_SSP_TIMING_CLOCK_DIVIDE	0x0000FF00
+#define BP_SSP_TIMING_CLOCK_DIVIDE	8
+#define BM_SSP_TIMING_TIMEOUT	0xFFFF0000
+#define BP_SSP_TIMING_TIMEOUT	16
+
+#define HW_SSP_CTRL1		0x60
+#define BM_SSP_CTRL1_SSP_MODE	0x0000000F
+#define BP_SSP_CTRL1_SSP_MODE	0
+#define BM_SSP_CTRL1_WORD_LENGTH	0x000000F0
+#define BP_SSP_CTRL1_WORD_LENGTH	4
+#define BM_SSP_CTRL1_POLARITY	0x00000200
+#define BM_SSP_CTRL1_PHASE	0x00000400
+#define BM_SSP_CTRL1_DMA_ENABLE	0x00002000
+#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ	0x00008000
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN	0x00010000
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ	0x00020000
+#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ	0x00200000
+#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN	0x00400000
+#define BM_SSP_CTRL1_DATA_CRC_IRQ	0x00800000
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN	0x01000000
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ	0x02000000
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN	0x04000000
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	0x08000000
+#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN	0x10000000
+#define BM_SSP_CTRL1_RESP_ERR_IRQ	0x20000000
+#define BM_SSP_CTRL1_SDIO_IRQ	0x80000000
+
+#define HW_SSP_DATA		0x70
+
+#define HW_SSP_SDRESP0		0x80
+
+#define HW_SSP_SDRESP1		0x90
+
+#define HW_SSP_SDRESP2		0xA0
+
+#define HW_SSP_SDRESP3		0xB0
+
+#define HW_SSP_STATUS		0xC0
+#define BM_SSP_STATUS_FIFO_EMPTY	0x00000020
+#define BM_SSP_STATUS_TIMEOUT	0x00001000
+#define BM_SSP_STATUS_RESP_TIMEOUT	0x00004000
+#define BM_SSP_STATUS_RESP_ERR	0x00008000
+#define BM_SSP_STATUS_RESP_CRC_ERR	0x00010000
+#define BM_SSP_STATUS_CARD_DETECT	0x10000000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-timrot.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-timrot.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-timrot.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-timrot.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * stmp37xx: TIMROT register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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 _MACH_REGS_TIMROT
+#define _MACH_REGS_TIMROT
+
+#define REGS_TIMROT_BASE	(STMP3XXX_REGS_BASE + 0x68000)
+
+#define HW_TIMROT_ROTCTRL	0x0
+#define BM_TIMROT_ROTCTRL_CLKGATE	0x40000000
+#define BM_TIMROT_ROTCTRL_SFTRST	0x80000000
+
+#define HW_TIMROT_TIMCTRL0	(0x20 + 0 * 0x20)
+#define HW_TIMROT_TIMCTRL1	(0x20 + 1 * 0x20)
+#define HW_TIMROT_TIMCTRL2	(0x20 + 2 * 0x20)
+
+#define HW_TIMROT_TIMCTRLn	0x20
+#define BM_TIMROT_TIMCTRLn_SELECT	0x0000000F
+#define BP_TIMROT_TIMCTRLn_SELECT	0
+#define BM_TIMROT_TIMCTRLn_PRESCALE	0x00000030
+#define BP_TIMROT_TIMCTRLn_PRESCALE	4
+#define BM_TIMROT_TIMCTRLn_RELOAD	0x00000040
+#define BM_TIMROT_TIMCTRLn_UPDATE	0x00000080
+#define BM_TIMROT_TIMCTRLn_IRQ_EN	0x00004000
+#define BM_TIMROT_TIMCTRLn_IRQ	0x00008000
+
+#define HW_TIMROT_TIMCOUNT0	(0x30 + 0 * 0x20)
+#define HW_TIMROT_TIMCOUNT1	(0x30 + 1 * 0x20)
+#define HW_TIMROT_TIMCOUNT2	(0x30 + 2 * 0x20)
+
+#define HW_TIMROT_TIMCOUNTn	0x30
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartapp.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartapp.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartapp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartapp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * stmp37xx: UARTAPP register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_UARTAPP_BASE	(STMP3XXX_REGS_BASE + 0x6C000)
+#define REGS_UARTAPP1_PHYS	0x8006C000
+#define REGS_UARTAPP_SIZE	0x2000
+
+#define HW_UARTAPP_CTRL0	0x0
+#define BM_UARTAPP_CTRL0_XFER_COUNT	0x0000FFFF
+#define BP_UARTAPP_CTRL0_XFER_COUNT	0
+#define BM_UARTAPP_CTRL0_RXTIMEOUT	0x07FF0000
+#define BP_UARTAPP_CTRL0_RXTIMEOUT	16
+#define BM_UARTAPP_CTRL0_RXTO_ENABLE	0x08000000
+#define BM_UARTAPP_CTRL0_RUN	0x20000000
+#define BM_UARTAPP_CTRL0_SFTRST	0x80000000
+#define BM_UARTAPP_CTRL1_XFER_COUNT	0x0000FFFF
+#define BP_UARTAPP_CTRL1_XFER_COUNT	0
+#define BM_UARTAPP_CTRL1_RUN	0x10000000
+
+#define HW_UARTAPP_CTRL2	0x20
+#define BM_UARTAPP_CTRL2_UARTEN	0x00000001
+#define BP_UARTAPP_CTRL2_UARTEN	0
+#define BM_UARTAPP_CTRL2_TXE	0x00000100
+#define BM_UARTAPP_CTRL2_RXE	0x00000200
+#define BM_UARTAPP_CTRL2_RTS	0x00000800
+#define BM_UARTAPP_CTRL2_RTSEN	0x00004000
+#define BM_UARTAPP_CTRL2_CTSEN	0x00008000
+#define BM_UARTAPP_CTRL2_RXDMAE	0x01000000
+#define BM_UARTAPP_CTRL2_TXDMAE	0x02000000
+#define BM_UARTAPP_CTRL2_DMAONERR	0x04000000
+
+#define HW_UARTAPP_LINECTRL	0x30
+#define BM_UARTAPP_LINECTRL_BRK	0x00000001
+#define BP_UARTAPP_LINECTRL_BRK	0
+#define BM_UARTAPP_LINECTRL_PEN	0x00000002
+#define BM_UARTAPP_LINECTRL_EPS	0x00000004
+#define BM_UARTAPP_LINECTRL_STP2	0x00000008
+#define BM_UARTAPP_LINECTRL_FEN	0x00000010
+#define BM_UARTAPP_LINECTRL_WLEN	0x00000060
+#define BP_UARTAPP_LINECTRL_WLEN	5
+#define BM_UARTAPP_LINECTRL_SPS	0x00000080
+#define BM_UARTAPP_LINECTRL_BAUD_DIVFRAC	0x00003F00
+#define BP_UARTAPP_LINECTRL_BAUD_DIVFRAC	8
+#define BM_UARTAPP_LINECTRL_BAUD_DIVINT	0xFFFF0000
+#define BP_UARTAPP_LINECTRL_BAUD_DIVINT	16
+
+#define HW_UARTAPP_INTR		0x50
+#define BM_UARTAPP_INTR_CTSMIS	0x00000002
+#define BM_UARTAPP_INTR_RTIS	0x00000040
+#define BM_UARTAPP_INTR_CTSMIEN	0x00020000
+#define BM_UARTAPP_INTR_RXIEN	0x00100000
+#define BM_UARTAPP_INTR_RTIEN	0x00400000
+
+#define HW_UARTAPP_DATA		0x60
+
+#define HW_UARTAPP_STAT		0x70
+#define BM_UARTAPP_STAT_RXCOUNT	0x0000FFFF
+#define BP_UARTAPP_STAT_RXCOUNT	0
+#define BM_UARTAPP_STAT_FERR	0x00010000
+#define BM_UARTAPP_STAT_PERR	0x00020000
+#define BM_UARTAPP_STAT_BERR	0x00040000
+#define BM_UARTAPP_STAT_OERR	0x00080000
+#define BM_UARTAPP_STAT_RXFE	0x01000000
+#define BM_UARTAPP_STAT_TXFF	0x02000000
+#define BM_UARTAPP_STAT_TXFE	0x08000000
+#define BM_UARTAPP_STAT_CTS	0x10000000
+
+#define HW_UARTAPP_VERSION	0x90
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartdbg.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartdbg.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartdbg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-uartdbg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,268 @@
+/*
+ * stmp378x: UARTDBG register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_UARTDBG_BASE	(STMP3XXX_REGS_BASE + 0x70000)
+#define REGS_UARTDBG_PHYS	0x80070000
+#define REGS_UARTDBG_SIZE	0x2000
+
+#define HW_UARTDBGDR 0x00000000
+#define BP_UARTDBGDR_UNAVAILABLE      16
+#define BM_UARTDBGDR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGDR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGDR_UNAVAILABLE)
+#define BP_UARTDBGDR_RESERVED      12
+#define BM_UARTDBGDR_RESERVED 0x0000F000
+#define BF_UARTDBGDR_RESERVED(v)  \
+	(((v) << 12) & BM_UARTDBGDR_RESERVED)
+#define BM_UARTDBGDR_OE 0x00000800
+#define BM_UARTDBGDR_BE 0x00000400
+#define BM_UARTDBGDR_PE 0x00000200
+#define BM_UARTDBGDR_FE 0x00000100
+#define BP_UARTDBGDR_DATA      0
+#define BM_UARTDBGDR_DATA 0x000000FF
+#define BF_UARTDBGDR_DATA(v)  \
+	(((v) << 0) & BM_UARTDBGDR_DATA)
+#define HW_UARTDBGRSR_ECR 0x00000004
+#define BP_UARTDBGRSR_ECR_UNAVAILABLE      8
+#define BM_UARTDBGRSR_ECR_UNAVAILABLE 0xFFFFFF00
+#define BF_UARTDBGRSR_ECR_UNAVAILABLE(v) \
+	(((v) << 8) & BM_UARTDBGRSR_ECR_UNAVAILABLE)
+#define BP_UARTDBGRSR_ECR_EC      4
+#define BM_UARTDBGRSR_ECR_EC 0x000000F0
+#define BF_UARTDBGRSR_ECR_EC(v)  \
+	(((v) << 4) & BM_UARTDBGRSR_ECR_EC)
+#define BM_UARTDBGRSR_ECR_OE 0x00000008
+#define BM_UARTDBGRSR_ECR_BE 0x00000004
+#define BM_UARTDBGRSR_ECR_PE 0x00000002
+#define BM_UARTDBGRSR_ECR_FE 0x00000001
+#define HW_UARTDBGFR 0x00000018
+#define BP_UARTDBGFR_UNAVAILABLE      16
+#define BM_UARTDBGFR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGFR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGFR_UNAVAILABLE)
+#define BP_UARTDBGFR_RESERVED      9
+#define BM_UARTDBGFR_RESERVED 0x0000FE00
+#define BF_UARTDBGFR_RESERVED(v)  \
+	(((v) << 9) & BM_UARTDBGFR_RESERVED)
+#define BM_UARTDBGFR_RI 0x00000100
+#define BM_UARTDBGFR_TXFE 0x00000080
+#define BM_UARTDBGFR_RXFF 0x00000040
+#define BM_UARTDBGFR_TXFF 0x00000020
+#define BM_UARTDBGFR_RXFE 0x00000010
+#define BM_UARTDBGFR_BUSY 0x00000008
+#define BM_UARTDBGFR_DCD 0x00000004
+#define BM_UARTDBGFR_DSR 0x00000002
+#define BM_UARTDBGFR_CTS 0x00000001
+#define HW_UARTDBGILPR 0x00000020
+#define BP_UARTDBGILPR_UNAVAILABLE      8
+#define BM_UARTDBGILPR_UNAVAILABLE 0xFFFFFF00
+#define BF_UARTDBGILPR_UNAVAILABLE(v) \
+	(((v) << 8) & BM_UARTDBGILPR_UNAVAILABLE)
+#define BP_UARTDBGILPR_ILPDVSR      0
+#define BM_UARTDBGILPR_ILPDVSR 0x000000FF
+#define BF_UARTDBGILPR_ILPDVSR(v)  \
+	(((v) << 0) & BM_UARTDBGILPR_ILPDVSR)
+#define HW_UARTDBGIBRD 0x00000024
+#define BP_UARTDBGIBRD_UNAVAILABLE      16
+#define BM_UARTDBGIBRD_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGIBRD_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGIBRD_UNAVAILABLE)
+#define BP_UARTDBGIBRD_BAUD_DIVINT      0
+#define BM_UARTDBGIBRD_BAUD_DIVINT 0x0000FFFF
+#define BF_UARTDBGIBRD_BAUD_DIVINT(v)  \
+	(((v) << 0) & BM_UARTDBGIBRD_BAUD_DIVINT)
+#define HW_UARTDBGFBRD 0x00000028
+#define BP_UARTDBGFBRD_UNAVAILABLE      8
+#define BM_UARTDBGFBRD_UNAVAILABLE 0xFFFFFF00
+#define BF_UARTDBGFBRD_UNAVAILABLE(v) \
+	(((v) << 8) & BM_UARTDBGFBRD_UNAVAILABLE)
+#define BP_UARTDBGFBRD_RESERVED      6
+#define BM_UARTDBGFBRD_RESERVED 0x000000C0
+#define BF_UARTDBGFBRD_RESERVED(v)  \
+	(((v) << 6) & BM_UARTDBGFBRD_RESERVED)
+#define BP_UARTDBGFBRD_BAUD_DIVFRAC      0
+#define BM_UARTDBGFBRD_BAUD_DIVFRAC 0x0000003F
+#define BF_UARTDBGFBRD_BAUD_DIVFRAC(v)  \
+	(((v) << 0) & BM_UARTDBGFBRD_BAUD_DIVFRAC)
+#define HW_UARTDBGLCR_H 0x0000002c
+#define BP_UARTDBGLCR_H_UNAVAILABLE      16
+#define BM_UARTDBGLCR_H_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGLCR_H_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGLCR_H_UNAVAILABLE)
+#define BP_UARTDBGLCR_H_RESERVED      8
+#define BM_UARTDBGLCR_H_RESERVED 0x0000FF00
+#define BF_UARTDBGLCR_H_RESERVED(v)  \
+	(((v) << 8) & BM_UARTDBGLCR_H_RESERVED)
+#define BM_UARTDBGLCR_H_SPS 0x00000080
+#define BP_UARTDBGLCR_H_WLEN      5
+#define BM_UARTDBGLCR_H_WLEN 0x00000060
+#define BF_UARTDBGLCR_H_WLEN(v)  \
+	(((v) << 5) & BM_UARTDBGLCR_H_WLEN)
+#define BM_UARTDBGLCR_H_FEN 0x00000010
+#define BM_UARTDBGLCR_H_STP2 0x00000008
+#define BM_UARTDBGLCR_H_EPS 0x00000004
+#define BM_UARTDBGLCR_H_PEN 0x00000002
+#define BM_UARTDBGLCR_H_BRK 0x00000001
+#define HW_UARTDBGCR 0x00000030
+#define BP_UARTDBGCR_UNAVAILABLE      16
+#define BM_UARTDBGCR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGCR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGCR_UNAVAILABLE)
+#define BM_UARTDBGCR_CTSEN 0x00008000
+#define BM_UARTDBGCR_RTSEN 0x00004000
+#define BM_UARTDBGCR_OUT2 0x00002000
+#define BM_UARTDBGCR_OUT1 0x00001000
+#define BM_UARTDBGCR_RTS 0x00000800
+#define BM_UARTDBGCR_DTR 0x00000400
+#define BM_UARTDBGCR_RXE 0x00000200
+#define BM_UARTDBGCR_TXE 0x00000100
+#define BM_UARTDBGCR_LBE 0x00000080
+#define BP_UARTDBGCR_RESERVED      3
+#define BM_UARTDBGCR_RESERVED 0x00000078
+#define BF_UARTDBGCR_RESERVED(v)  \
+	(((v) << 3) & BM_UARTDBGCR_RESERVED)
+#define BM_UARTDBGCR_SIRLP 0x00000004
+#define BM_UARTDBGCR_SIREN 0x00000002
+#define BM_UARTDBGCR_UARTEN 0x00000001
+#define HW_UARTDBGIFLS 0x00000034
+#define BP_UARTDBGIFLS_UNAVAILABLE      16
+#define BM_UARTDBGIFLS_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGIFLS_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGIFLS_UNAVAILABLE)
+#define BP_UARTDBGIFLS_RESERVED      6
+#define BM_UARTDBGIFLS_RESERVED 0x0000FFC0
+#define BF_UARTDBGIFLS_RESERVED(v)  \
+	(((v) << 6) & BM_UARTDBGIFLS_RESERVED)
+#define BP_UARTDBGIFLS_RXIFLSEL      3
+#define BM_UARTDBGIFLS_RXIFLSEL 0x00000038
+#define BF_UARTDBGIFLS_RXIFLSEL(v)  \
+	(((v) << 3) & BM_UARTDBGIFLS_RXIFLSEL)
+#define BV_UARTDBGIFLS_RXIFLSEL__NOT_EMPTY      0x0
+#define BV_UARTDBGIFLS_RXIFLSEL__ONE_QUARTER    0x1
+#define BV_UARTDBGIFLS_RXIFLSEL__ONE_HALF       0x2
+#define BV_UARTDBGIFLS_RXIFLSEL__THREE_QUARTERS 0x3
+#define BV_UARTDBGIFLS_RXIFLSEL__SEVEN_EIGHTHS  0x4
+#define BV_UARTDBGIFLS_RXIFLSEL__INVALID5       0x5
+#define BV_UARTDBGIFLS_RXIFLSEL__INVALID6       0x6
+#define BV_UARTDBGIFLS_RXIFLSEL__INVALID7       0x7
+#define BP_UARTDBGIFLS_TXIFLSEL      0
+#define BM_UARTDBGIFLS_TXIFLSEL 0x00000007
+#define BF_UARTDBGIFLS_TXIFLSEL(v)  \
+	(((v) << 0) & BM_UARTDBGIFLS_TXIFLSEL)
+#define BV_UARTDBGIFLS_TXIFLSEL__EMPTY	  0x0
+#define BV_UARTDBGIFLS_TXIFLSEL__ONE_QUARTER    0x1
+#define BV_UARTDBGIFLS_TXIFLSEL__ONE_HALF       0x2
+#define BV_UARTDBGIFLS_TXIFLSEL__THREE_QUARTERS 0x3
+#define BV_UARTDBGIFLS_TXIFLSEL__SEVEN_EIGHTHS  0x4
+#define BV_UARTDBGIFLS_TXIFLSEL__INVALID5       0x5
+#define BV_UARTDBGIFLS_TXIFLSEL__INVALID6       0x6
+#define BV_UARTDBGIFLS_TXIFLSEL__INVALID7       0x7
+#define HW_UARTDBGIMSC 0x00000038
+#define BP_UARTDBGIMSC_UNAVAILABLE      16
+#define BM_UARTDBGIMSC_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGIMSC_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGIMSC_UNAVAILABLE)
+#define BP_UARTDBGIMSC_RESERVED      11
+#define BM_UARTDBGIMSC_RESERVED 0x0000F800
+#define BF_UARTDBGIMSC_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGIMSC_RESERVED)
+#define BM_UARTDBGIMSC_OEIM 0x00000400
+#define BM_UARTDBGIMSC_BEIM 0x00000200
+#define BM_UARTDBGIMSC_PEIM 0x00000100
+#define BM_UARTDBGIMSC_FEIM 0x00000080
+#define BM_UARTDBGIMSC_RTIM 0x00000040
+#define BM_UARTDBGIMSC_TXIM 0x00000020
+#define BM_UARTDBGIMSC_RXIM 0x00000010
+#define BM_UARTDBGIMSC_DSRMIM 0x00000008
+#define BM_UARTDBGIMSC_DCDMIM 0x00000004
+#define BM_UARTDBGIMSC_CTSMIM 0x00000002
+#define BM_UARTDBGIMSC_RIMIM 0x00000001
+#define HW_UARTDBGRIS 0x0000003c
+#define BP_UARTDBGRIS_UNAVAILABLE      16
+#define BM_UARTDBGRIS_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGRIS_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGRIS_UNAVAILABLE)
+#define BP_UARTDBGRIS_RESERVED      11
+#define BM_UARTDBGRIS_RESERVED 0x0000F800
+#define BF_UARTDBGRIS_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGRIS_RESERVED)
+#define BM_UARTDBGRIS_OERIS 0x00000400
+#define BM_UARTDBGRIS_BERIS 0x00000200
+#define BM_UARTDBGRIS_PERIS 0x00000100
+#define BM_UARTDBGRIS_FERIS 0x00000080
+#define BM_UARTDBGRIS_RTRIS 0x00000040
+#define BM_UARTDBGRIS_TXRIS 0x00000020
+#define BM_UARTDBGRIS_RXRIS 0x00000010
+#define BM_UARTDBGRIS_DSRRMIS 0x00000008
+#define BM_UARTDBGRIS_DCDRMIS 0x00000004
+#define BM_UARTDBGRIS_CTSRMIS 0x00000002
+#define BM_UARTDBGRIS_RIRMIS 0x00000001
+#define HW_UARTDBGMIS 0x00000040
+#define BP_UARTDBGMIS_UNAVAILABLE      16
+#define BM_UARTDBGMIS_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGMIS_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGMIS_UNAVAILABLE)
+#define BP_UARTDBGMIS_RESERVED      11
+#define BM_UARTDBGMIS_RESERVED 0x0000F800
+#define BF_UARTDBGMIS_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGMIS_RESERVED)
+#define BM_UARTDBGMIS_OEMIS 0x00000400
+#define BM_UARTDBGMIS_BEMIS 0x00000200
+#define BM_UARTDBGMIS_PEMIS 0x00000100
+#define BM_UARTDBGMIS_FEMIS 0x00000080
+#define BM_UARTDBGMIS_RTMIS 0x00000040
+#define BM_UARTDBGMIS_TXMIS 0x00000020
+#define BM_UARTDBGMIS_RXMIS 0x00000010
+#define BM_UARTDBGMIS_DSRMMIS 0x00000008
+#define BM_UARTDBGMIS_DCDMMIS 0x00000004
+#define BM_UARTDBGMIS_CTSMMIS 0x00000002
+#define BM_UARTDBGMIS_RIMMIS 0x00000001
+#define HW_UARTDBGICR 0x00000044
+#define BP_UARTDBGICR_UNAVAILABLE      16
+#define BM_UARTDBGICR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGICR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGICR_UNAVAILABLE)
+#define BP_UARTDBGICR_RESERVED      11
+#define BM_UARTDBGICR_RESERVED 0x0000F800
+#define BF_UARTDBGICR_RESERVED(v)  \
+	(((v) << 11) & BM_UARTDBGICR_RESERVED)
+#define BM_UARTDBGICR_OEIC 0x00000400
+#define BM_UARTDBGICR_BEIC 0x00000200
+#define BM_UARTDBGICR_PEIC 0x00000100
+#define BM_UARTDBGICR_FEIC 0x00000080
+#define BM_UARTDBGICR_RTIC 0x00000040
+#define BM_UARTDBGICR_TXIC 0x00000020
+#define BM_UARTDBGICR_RXIC 0x00000010
+#define BM_UARTDBGICR_DSRMIC 0x00000008
+#define BM_UARTDBGICR_DCDMIC 0x00000004
+#define BM_UARTDBGICR_CTSMIC 0x00000002
+#define BM_UARTDBGICR_RIMIC 0x00000001
+#define HW_UARTDBGDMACR 0x00000048
+#define BP_UARTDBGDMACR_UNAVAILABLE      16
+#define BM_UARTDBGDMACR_UNAVAILABLE 0xFFFF0000
+#define BF_UARTDBGDMACR_UNAVAILABLE(v) \
+	(((v) << 16) & BM_UARTDBGDMACR_UNAVAILABLE)
+#define BP_UARTDBGDMACR_RESERVED      3
+#define BM_UARTDBGDMACR_RESERVED 0x0000FFF8
+#define BF_UARTDBGDMACR_RESERVED(v)  \
+	(((v) << 3) & BM_UARTDBGDMACR_RESERVED)
+#define BM_UARTDBGDMACR_DMAONERR 0x00000004
+#define BM_UARTDBGDMACR_TXDMAE 0x00000002
+#define BM_UARTDBGDMACR_RXDMAE 0x00000001
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * stmp37xx: USBCTL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_USBCTL_BASE	(STMP3XXX_REGS_BASE + 0x80000)
+#define REGS_USBCTL_PHYS	0x80000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctrl.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctrl.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctrl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbctrl.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * stmp37xx: USBCTRL register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_USBCTRL_BASE	(STMP3XXX_REGS_BASE + 0x80000)
+#define REGS_USBCTRL_PHYS	0x80080000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbphy.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbphy.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbphy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/include/mach/regs-usbphy.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ * stmp37xx: USBPHY register definitions
+ *
+ * Copyright (c) 2008 Freescale Semiconductor
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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
+ */
+#define REGS_USBPHY_BASE	(STMP3XXX_REGS_BASE + 0x7C000)
+
+#define HW_USBPHY_PWD		0x0
+
+#define HW_USBPHY_CTRL		0x30
+#define BM_USBPHY_CTRL_ENHSPRECHARGEXMIT	0x00000001
+#define BP_USBPHY_CTRL_ENHSPRECHARGEXMIT	0
+#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	0x00000002
+#define BM_USBPHY_CTRL_ENDEVPLUGINDETECT	0x00000010
+#define BM_USBPHY_CTRL_ENOTGIDDETECT	0x00000080
+#define BM_USBPHY_CTRL_ENIRQDEVPLUGIN	0x00000800
+#define BM_USBPHY_CTRL_CLKGATE	0x40000000
+#define BM_USBPHY_CTRL_SFTRST	0x80000000
+
+#define HW_USBPHY_STATUS	0x40
+#define BM_USBPHY_STATUS_DEVPLUGIN_STATUS	0x00000040
+#define BM_USBPHY_STATUS_OTGID_STATUS	0x00000100
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARCH_STMP37XX) += stmp37xx.o
+obj-$(CONFIG_MACH_STMP37XX) += stmp37xx_devb.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/Makefile.boot linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/Makefile.boot
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/Makefile.boot	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x40008000
+params_phys-y	:= 0x40000100
+initrd_phys-y	:= 0x40800000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/stmp37xx.c linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/stmp37xx.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/stmp37xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/stmp37xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,219 @@
+/*
+ * Freescale STMP37XX platform support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/dma.h>
+
+#include <mach/platform.h>
+#include <mach/regs-icoll.h>
+#include <mach/regs-apbh.h>
+#include <mach/regs-apbx.h>
+#include "stmp37xx.h"
+
+/*
+ * IRQ handling
+ */
+static void stmp37xx_ack_irq(unsigned int irq)
+{
+	/* Disable IRQ */
+	stmp3xxx_clearl(0x04 << ((irq % 4) * 8),
+		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10);
+
+	/* ACK current interrupt */
+	__raw_writel(1, REGS_ICOLL_BASE + HW_ICOLL_LEVELACK);
+
+	/* Barrier */
+	(void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT);
+}
+
+static void stmp37xx_mask_irq(unsigned int irq)
+{
+	/* IRQ disable */
+	stmp3xxx_clearl(0x04 << ((irq % 4) * 8),
+		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10);
+}
+
+static void stmp37xx_unmask_irq(unsigned int irq)
+{
+	/* IRQ enable */
+	stmp3xxx_setl(0x04 << ((irq % 4) * 8),
+		REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10);
+}
+
+static struct irq_chip stmp37xx_chip = {
+	.ack	= stmp37xx_ack_irq,
+	.mask	= stmp37xx_mask_irq,
+	.unmask = stmp37xx_unmask_irq,
+};
+
+void __init stmp37xx_init_irq(void)
+{
+	stmp3xxx_init_irq(&stmp37xx_chip);
+}
+
+/*
+ * DMA interrupt handling
+ */
+void stmp3xxx_arch_dma_enable_interrupt(int channel)
+{
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)),
+			REGS_APBH_BASE + HW_APBH_CTRL1);
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)),
+			REGS_APBX_BASE + HW_APBX_CTRL1);
+		break;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt);
+
+void stmp3xxx_arch_dma_clear_interrupt(int channel)
+{
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel),
+				REGS_APBH_BASE + HW_APBH_CTRL1);
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel),
+				REGS_APBX_BASE + HW_APBX_CTRL1);
+		break;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt);
+
+int stmp3xxx_arch_dma_is_interrupt(int channel)
+{
+	int r = 0;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) &
+			(1 << STMP3XXX_DMA_CHANNEL(channel));
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) &
+			(1 << STMP3XXX_DMA_CHANNEL(channel));
+		break;
+	}
+	return r;
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt);
+
+void stmp3xxx_arch_dma_reset_channel(int channel)
+{
+	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		/* Reset channel and wait for it to complete */
+		stmp3xxx_setl(chbit << BP_APBH_CTRL0_RESET_CHANNEL,
+			REGS_APBH_BASE + HW_APBH_CTRL0);
+		while (__raw_readl(REGS_APBH_BASE + HW_APBH_CTRL0) &
+		       (chbit << BP_APBH_CTRL0_RESET_CHANNEL))
+				cpu_relax();
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		stmp3xxx_setl(chbit << BP_APBX_CTRL0_RESET_CHANNEL,
+			REGS_APBX_BASE + HW_APBX_CTRL0);
+		while (__raw_readl(REGS_APBX_BASE + HW_APBX_CTRL0) &
+		       (chbit << BP_APBX_CTRL0_RESET_CHANNEL))
+				cpu_relax();
+		break;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel);
+
+void stmp3xxx_arch_dma_freeze(int channel)
+{
+	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0);
+		break;
+	case STMP3XXX_BUS_APBX:
+		stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0);
+		break;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze);
+
+void stmp3xxx_arch_dma_unfreeze(int channel)
+{
+	unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel);
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0);
+		break;
+	case STMP3XXX_BUS_APBX:
+		stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0);
+		break;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze);
+
+/*
+ * The registers are all very closely mapped, so we might as well map them all
+ * with a single mapping
+ *
+ * Logical      Physical
+ * f0000000	80000000	On-chip registers
+ * f1000000	00000000	32k on-chip SRAM
+ */
+static struct map_desc stmp37xx_io_desc[] __initdata = {
+	{
+		.virtual	= (u32)STMP3XXX_REGS_BASE,
+		.pfn		= __phys_to_pfn(STMP3XXX_REGS_PHBASE),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= (u32)STMP3XXX_OCRAM_BASE,
+		.pfn		= __phys_to_pfn(STMP3XXX_OCRAM_PHBASE),
+		.length		= STMP3XXX_OCRAM_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init stmp37xx_map_io(void)
+{
+	iotable_init(stmp37xx_io_desc, ARRAY_SIZE(stmp37xx_io_desc));
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/stmp37xx_devb.c linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/stmp37xx_devb.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/stmp37xx_devb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/stmp37xx_devb.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,101 @@
+/*
+ * Freescale STMP37XX development board support
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+#include "stmp37xx.h"
+
+/*
+ * List of STMP37xx development board specific devices
+ */
+static struct platform_device *stmp37xx_devb_devices[] = {
+	&stmp3xxx_dbguart,
+	&stmp3xxx_appuart,
+};
+
+static struct pin_desc dbguart_pins_0[] = {
+	{ PINID_PWM0, PIN_FUN3, },
+	{ PINID_PWM1, PIN_FUN3, },
+};
+
+struct pin_desc appuart_pins_0[] = {
+	{ PINID_UART2_CTS, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_UART2_RTS, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_UART2_RX, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+	{ PINID_UART2_TX, PIN_FUN1, PIN_4MA, PIN_1_8V, 0, },
+};
+
+static struct pin_group appuart_pins[] = {
+	[0] = {
+		.pins		= appuart_pins_0,
+		.nr_pins	= ARRAY_SIZE(appuart_pins_0),
+	},
+	/* 37xx has the only app uart */
+};
+
+static struct pin_group dbguart_pins[] = {
+	[0] = {
+		.pins		= dbguart_pins_0,
+		.nr_pins	= ARRAY_SIZE(dbguart_pins_0),
+	},
+};
+
+static int dbguart_pins_control(int id, int request)
+{
+	int r = 0;
+
+	if (request)
+		r = stmp3xxx_request_pin_group(&dbguart_pins[id], "debug uart");
+	else
+		stmp3xxx_release_pin_group(&dbguart_pins[id], "debug uart");
+	return r;
+}
+
+
+static void __init stmp37xx_devb_init(void)
+{
+	stmp3xxx_pinmux_init(NR_REAL_IRQS);
+
+	/* Init STMP3xxx platform */
+	stmp3xxx_init();
+
+	stmp3xxx_dbguart.dev.platform_data = dbguart_pins_control;
+	stmp3xxx_appuart.dev.platform_data = appuart_pins;
+
+	/* Add STMP37xx development board devices */
+	platform_add_devices(stmp37xx_devb_devices,
+			ARRAY_SIZE(stmp37xx_devb_devices));
+}
+
+MACHINE_START(STMP37XX, "STMP37XX")
+	.phys_io	= 0x80000000,
+	.io_pg_offst	= ((0xf0000000) >> 18) & 0xfffc,
+	.boot_params	= 0x40000100,
+	.map_io		= stmp37xx_map_io,
+	.init_irq	= stmp37xx_init_irq,
+	.timer		= &stmp3xxx_timer,
+	.init_machine	= stmp37xx_devb_init,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/stmp37xx.h linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/stmp37xx.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-stmp37xx/stmp37xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-stmp37xx/stmp37xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * Freescale STMP37XX/STMP378X internal functions and data declarations
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __MACH_STMP37XX_H
+#define __MACH_STMP37XX_H
+
+void stmp37xx_map_io(void);
+void stmp37xx_init_irq(void);
+
+#endif /* __MACH_STMP37XX_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-u300/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1526 @@
+/*
+ *
+ * arch/arm/mach-u300/clock.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Define clocks in the app platform.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+
+#include <asm/clkdev.h>
+#include <mach/hardware.h>
+#include <mach/syscon.h>
+
+#include "clock.h"
+
+/*
+ * TODO:
+ * - move all handling of the CCR register into this file and create
+ *   a spinlock for the CCR register
+ * - switch to the clkdevice lookup mechanism that maps clocks to
+ *   device ID:s instead when it becomes available in kernel 2.6.29.
+ * - implement rate get/set for all clocks that need it.
+ */
+
+/*
+ * Syscon clock I/O registers lock so clock requests don't collide
+ * NOTE: this is a local lock only used to lock access to clock and
+ * reset registers in syscon.
+ */
+static DEFINE_SPINLOCK(syscon_clkreg_lock);
+static DEFINE_SPINLOCK(syscon_resetreg_lock);
+
+/*
+ * The clocking hierarchy currently looks like this.
+ * NOTE: the idea is NOT to show how the clocks are routed on the chip!
+ * The ideas is to show dependencies, so a clock higher up in the
+ * hierarchy has to be on in order for another clock to be on. Now,
+ * both CPU and DMA can actually be on top of the hierarchy, and that
+ * is not modeled currently. Instead we have the backbone AMBA bus on
+ * top. This bus cannot be programmed in any way but conceptually it
+ * needs to be active for the bridges and devices to transport data.
+ *
+ * Please be aware that a few clocks are hw controlled, which mean that
+ * the hw itself can turn on/off or change the rate of the clock when
+ * needed!
+ *
+ *  AMBA bus
+ *  |
+ *  +- CPU
+ *  +- NANDIF NAND Flash interface
+ *  +- SEMI Shared Memory interface
+ *  +- ISP Image Signal Processor (U335 only)
+ *  +- CDS (U335 only)
+ *  +- DMA Direct Memory Access Controller
+ *  +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL)
+ *  +- APEX
+ *  +- VIDEO_ENC AVE2/3 Video Encoder
+ *  +- XGAM Graphics Accelerator Controller
+ *  +- AHB
+ *  |
+ *  +- ahb:0 AHB Bridge
+ *  |  |
+ *  |  +- ahb:1 INTCON Interrupt controller
+ *  |  +- ahb:3 MSPRO  Memory Stick Pro controller
+ *  |  +- ahb:4 EMIF   External Memory interface
+ *  |
+ *  +- fast:0 FAST bridge
+ *  |  |
+ *  |  +- fast:1 MMCSD MMC/SD card reader controller
+ *  |  +- fast:2 I2S0  PCM I2S channel 0 controller
+ *  |  +- fast:3 I2S1  PCM I2S channel 1 controller
+ *  |  +- fast:4 I2C0  I2C channel 0 controller
+ *  |  +- fast:5 I2C1  I2C channel 1 controller
+ *  |  +- fast:6 SPI   SPI controller
+ *  |  +- fast:7 UART1 Secondary UART (U335 only)
+ *  |
+ *  +- slow:0 SLOW bridge
+ *     |
+ *     +- slow:1 SYSCON (not possible to control)
+ *     +- slow:2 WDOG Watchdog
+ *     +- slow:3 UART0 primary UART
+ *     +- slow:4 TIMER_APP Application timer - used in Linux
+ *     +- slow:5 KEYPAD controller
+ *     +- slow:6 GPIO controller
+ *     +- slow:7 RTC controller
+ *     +- slow:8 BT Bus Tracer (not used currently)
+ *     +- slow:9 EH Event Handler (not used currently)
+ *     +- slow:a TIMER_ACC Access style timer (not used currently)
+ *     +- slow:b PPM (U335 only, what is that?)
+ */
+
+/*
+ * Reset control functions. We remember if a block has been
+ * taken out of reset and don't remove the reset assertion again
+ * and vice versa. Currently we only remove resets so the
+ * enablement function is defined out.
+ */
+static void syscon_block_reset_enable(struct clk *clk)
+{
+	u16 val;
+	unsigned long iflags;
+
+	/* Not all blocks support resetting */
+	if (!clk->res_reg || !clk->res_mask)
+		return;
+	spin_lock_irqsave(&syscon_resetreg_lock, iflags);
+	val = readw(clk->res_reg);
+	val |= clk->res_mask;
+	writew(val, clk->res_reg);
+	spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
+	clk->reset = true;
+}
+
+static void syscon_block_reset_disable(struct clk *clk)
+{
+	u16 val;
+	unsigned long iflags;
+
+	/* Not all blocks support resetting */
+	if (!clk->res_reg || !clk->res_mask)
+		return;
+	spin_lock_irqsave(&syscon_resetreg_lock, iflags);
+	val = readw(clk->res_reg);
+	val &= ~clk->res_mask;
+	writew(val, clk->res_reg);
+	spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
+	clk->reset = false;
+}
+
+int __clk_get(struct clk *clk)
+{
+	u16 val;
+
+	/* The MMC and MSPRO clocks need some special set-up */
+	if (!strcmp(clk->name, "MCLK")) {
+		/* Set default MMC clock divisor to 18.9 MHz */
+		writew(0x0054U, U300_SYSCON_VBASE + U300_SYSCON_MMF0R);
+		val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+		/* Disable the MMC feedback clock */
+		val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
+		/* Disable MSPRO frequency */
+		val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
+		writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+	}
+	if (!strcmp(clk->name, "MSPRO")) {
+		val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+		/* Disable the MMC feedback clock */
+		val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
+		/* Enable MSPRO frequency */
+		val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
+		writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR);
+	}
+	return 1;
+}
+EXPORT_SYMBOL(__clk_get);
+
+void __clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(__clk_put);
+
+static void syscon_clk_disable(struct clk *clk)
+{
+	unsigned long iflags;
+
+	/* Don't touch the hardware controlled clocks */
+	if (clk->hw_ctrld)
+		return;
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCDR);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void syscon_clk_enable(struct clk *clk)
+{
+	unsigned long iflags;
+
+	/* Don't touch the hardware controlled clocks */
+	if (clk->hw_ctrld)
+		return;
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCER);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static u16 syscon_clk_get_rate(void)
+{
+	u16 val;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+	return val;
+}
+
+#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
+static void enable_i2s0_vcxo(void)
+{
+	u16 val;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	/* Set I2S0 to use the VCXO 26 MHz clock */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val |= U300_SYSCON_CCR_TURN_VCXO_ON;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val |= U300_SYSCON_CCR_I2S0_USE_VCXO;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	val |= U300_SYSCON_CEFR_I2S0_CLK_EN;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void enable_i2s1_vcxo(void)
+{
+	u16 val;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	/* Set I2S1 to use the VCXO 26 MHz clock */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val |= U300_SYSCON_CCR_TURN_VCXO_ON;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val |= U300_SYSCON_CCR_I2S1_USE_VCXO;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	val |= U300_SYSCON_CEFR_I2S1_CLK_EN;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void disable_i2s0_vcxo(void)
+{
+	u16 val;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	/* Disable I2S0 use of the VCXO 26 MHz clock */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	/* Deactivate VCXO if noone else is using VCXO */
+	if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO))
+		val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+static void disable_i2s1_vcxo(void)
+{
+	u16 val;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	/* Disable I2S1 use of the VCXO 26 MHz clock */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	/* Deactivate VCXO if noone else is using VCXO */
+	if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO))
+		val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+#endif /* CONFIG_MACH_U300_USE_I2S_AS_MASTER */
+
+
+static void syscon_clk_rate_set_mclk(unsigned long rate)
+{
+	u16 val;
+	u32 reg;
+	unsigned long iflags;
+
+	switch (rate) {
+	case 18900000:
+		val = 0x0054;
+		break;
+	case 20800000:
+		val = 0x0044;
+		break;
+	case 23100000:
+		val = 0x0043;
+		break;
+	case 26000000:
+		val = 0x0033;
+		break;
+	case 29700000:
+		val = 0x0032;
+		break;
+	case 34700000:
+		val = 0x0022;
+		break;
+	case 41600000:
+		val = 0x0021;
+		break;
+	case 52000000:
+		val = 0x0011;
+		break;
+	case 104000000:
+		val = 0x0000;
+		break;
+	default:
+		printk(KERN_ERR "Trying to set MCLK to unknown speed! %ld\n",
+		       rate);
+		return;
+	}
+
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	reg = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) &
+		~U300_SYSCON_MMF0R_MASK;
+	writew(reg | val, U300_SYSCON_VBASE + U300_SYSCON_MMF0R);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+
+void syscon_clk_rate_set_cpuclk(unsigned long rate)
+{
+	u16 val;
+	unsigned long iflags;
+
+	switch (rate) {
+	case 13000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER;
+		break;
+	case 52000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE;
+		break;
+	case 104000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH;
+		break;
+	case 208000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST;
+		break;
+	default:
+		return;
+	}
+	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
+	val |= readw(U300_SYSCON_VBASE + U300_SYSCON_CCR) &
+		~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
+}
+EXPORT_SYMBOL(syscon_clk_rate_set_cpuclk);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long iflags;
+
+	spin_lock_irqsave(&clk->lock, iflags);
+	if (clk->usecount > 0 && !(--clk->usecount)) {
+		/* some blocks lack clocking registers and cannot be disabled */
+		if (clk->disable)
+			clk->disable(clk);
+		if (likely((u32)clk->parent))
+			clk_disable(clk->parent);
+	}
+#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
+	if (unlikely(!strcmp(clk->name, "I2S0")))
+		disable_i2s0_vcxo();
+	if (unlikely(!strcmp(clk->name, "I2S1")))
+		disable_i2s1_vcxo();
+#endif
+	spin_unlock_irqrestore(&clk->lock, iflags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&clk->lock, iflags);
+	if (clk->usecount++ == 0) {
+		if (likely((u32)clk->parent))
+			ret = clk_enable(clk->parent);
+
+		if (unlikely(ret != 0))
+			clk->usecount--;
+		else {
+			/* remove reset line (we never enable reset again) */
+			syscon_block_reset_disable(clk);
+			/* clocks without enable function are always on */
+			if (clk->enable)
+				clk->enable(clk);
+#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
+			if (unlikely(!strcmp(clk->name, "I2S0")))
+				enable_i2s0_vcxo();
+			if (unlikely(!strcmp(clk->name, "I2S1")))
+				enable_i2s1_vcxo();
+#endif
+		}
+	}
+	spin_unlock_irqrestore(&clk->lock, iflags);
+	return ret;
+
+}
+EXPORT_SYMBOL(clk_enable);
+
+/* Returns the clock rate in Hz */
+static unsigned long clk_get_rate_cpuclk(struct clk *clk)
+{
+	u16 val;
+
+	val = syscon_clk_get_rate();
+
+	switch (val) {
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+		return 13000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+		return 52000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+		return 104000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+		return 208000000;
+	default:
+		break;
+	}
+	return clk->rate;
+}
+
+static unsigned long clk_get_rate_ahb_clk(struct clk *clk)
+{
+	u16 val;
+
+	val = syscon_clk_get_rate();
+
+	switch (val) {
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+		return 6500000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+		return 26000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+		return 52000000;
+	default:
+		break;
+	}
+	return clk->rate;
+
+}
+
+static unsigned long clk_get_rate_emif_clk(struct clk *clk)
+{
+	u16 val;
+
+	val = syscon_clk_get_rate();
+
+	switch (val) {
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+		return 13000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+		return 52000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+		return 104000000;
+	default:
+		break;
+	}
+	return clk->rate;
+
+}
+
+static unsigned long clk_get_rate_xgamclk(struct clk *clk)
+{
+	u16 val;
+
+	val = syscon_clk_get_rate();
+
+	switch (val) {
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+		return 6500000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+		return 26000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+		return 52000000;
+	default:
+		break;
+	}
+
+	return clk->rate;
+}
+
+static unsigned long clk_get_rate_mclk(struct clk *clk)
+{
+	u16 val;
+
+	val = syscon_clk_get_rate();
+
+	switch (val) {
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+		/*
+		 * Here, the 208 MHz PLL gets shut down and the always
+		 * on 13 MHz PLL used for RTC etc kicks into use
+		 * instead.
+		 */
+		return 13000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+	{
+		/*
+		 * This clock is under program control. The register is
+		 * divided in two nybbles, bit 7-4 gives cycles-1 to count
+		 * high, bit 3-0 gives cycles-1 to count low. Distribute
+		 * these with no more than 1 cycle difference between
+		 * low and high and add low and high to get the actual
+		 * divisor. The base PLL is 208 MHz. Writing 0x00 will
+		 * divide by 1 and 1 so the highest frequency possible
+		 * is 104 MHz.
+		 *
+		 * e.g. 0x54 =>
+		 * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz
+		 */
+		u16 val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) &
+			U300_SYSCON_MMF0R_MASK;
+		switch (val) {
+		case 0x0054:
+			return 18900000;
+		case 0x0044:
+			return 20800000;
+		case 0x0043:
+			return 23100000;
+		case 0x0033:
+			return 26000000;
+		case 0x0032:
+			return 29700000;
+		case 0x0022:
+			return 34700000;
+		case 0x0021:
+			return 41600000;
+		case 0x0011:
+			return 52000000;
+		case 0x0000:
+			return 104000000;
+		default:
+			break;
+		}
+	}
+	default:
+		break;
+	}
+
+	return clk->rate;
+}
+
+static unsigned long clk_get_rate_i2s_i2c_spi(struct clk *clk)
+{
+	u16 val;
+
+	val = syscon_clk_get_rate();
+
+	switch (val) {
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+		return 13000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+		return 26000000;
+	default:
+		break;
+	}
+
+	return clk->rate;
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->get_rate)
+		return clk->get_rate(clk);
+	else
+		return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static unsigned long clk_round_rate_mclk(struct clk *clk, unsigned long rate)
+{
+	if (rate >= 18900000)
+		return 18900000;
+	if (rate >= 20800000)
+		return 20800000;
+	if (rate >= 23100000)
+		return 23100000;
+	if (rate >= 26000000)
+		return 26000000;
+	if (rate >= 29700000)
+		return 29700000;
+	if (rate >= 34700000)
+		return 34700000;
+	if (rate >= 41600000)
+		return 41600000;
+	if (rate >= 52000000)
+		return 52000000;
+	return -EINVAL;
+}
+
+static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate)
+{
+	if (rate >= 13000000)
+		return 13000000;
+	if (rate >= 52000000)
+		return 52000000;
+	if (rate >= 104000000)
+		return 104000000;
+	if (rate >= 208000000)
+		return 208000000;
+	return -EINVAL;
+}
+
+/*
+ * This adjusts a requested rate to the closest exact rate
+ * a certain clock can provide. For a fixed clock it's
+ * mostly clk->rate.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	/* TODO: get apropriate switches for EMIFCLK, AHBCLK and MCLK */
+	/* Else default to fixed value */
+
+	if (clk->round_rate) {
+		return (long) clk->round_rate(clk, rate);
+	} else {
+		printk(KERN_ERR "clock: Failed to round rate of %s\n",
+		       clk->name);
+	}
+	return (long) clk->rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+static int clk_set_rate_mclk(struct clk *clk, unsigned long rate)
+{
+	syscon_clk_rate_set_mclk(clk_round_rate(clk, rate));
+	return 0;
+}
+
+static int clk_set_rate_cpuclk(struct clk *clk, unsigned long rate)
+{
+	syscon_clk_rate_set_cpuclk(clk_round_rate(clk, rate));
+	return 0;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	/* TODO: set for EMIFCLK and AHBCLK */
+	/* Else assume the clock is fixed and fail */
+	if (clk->set_rate) {
+		return clk->set_rate(clk, rate);
+	} else {
+		printk(KERN_ERR "clock: Failed to set %s to %ld hz\n",
+		       clk->name, rate);
+		return -EINVAL;
+	}
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+/*
+ * Clock definitions. The clock parents are set to respective
+ * bridge and the clock framework makes sure that the clocks have
+ * parents activated and are brought out of reset when in use.
+ *
+ * Clocks that have hw_ctrld = true are hw controlled, and the hw
+ * can by itself turn these clocks on and off.
+ * So in other words, we don't really have to care about them.
+ */
+
+static struct clk amba_clk = {
+	.name	    = "AMBA",
+	.rate	    = 52000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = false,
+	.lock       = __SPIN_LOCK_UNLOCKED(amba_clk.lock),
+};
+
+/*
+ * These blocks are connected directly to the AMBA bus
+ * with no bridge.
+ */
+
+static struct clk cpu_clk = {
+	.name	    = "CPU",
+	.parent	    = &amba_clk,
+	.rate	    = 208000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_CPU_RESET_EN,
+	.set_rate   = clk_set_rate_cpuclk,
+	.get_rate   = clk_get_rate_cpuclk,
+	.round_rate = clk_round_rate_cpuclk,
+	.lock       = __SPIN_LOCK_UNLOCKED(cpu_clk.lock),
+};
+
+static struct clk nandif_clk = {
+	.name       = "NANDIF",
+	.parent	    = &amba_clk,
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_NANDIF_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_NANDIF_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(nandif_clk.lock),
+};
+
+static struct clk semi_clk = {
+	.name       = "SEMI",
+	.parent	    = &amba_clk,
+	.rate       = 0, /* FIXME */
+	/* It is not possible to reset SEMI */
+	.hw_ctrld   = false,
+	.reset	    = false,
+	.clk_val    = U300_SYSCON_SBCER_SEMI_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(semi_clk.lock),
+};
+
+#ifdef CONFIG_MACH_U300_BS335
+static struct clk isp_clk = {
+	.name	    = "ISP",
+	.parent	    = &amba_clk,
+	.rate	    = 0, /* FIXME */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_ISP_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_ISP_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(isp_clk.lock),
+};
+
+static struct clk cds_clk = {
+	.name	    = "CDS",
+	.parent	    = &amba_clk,
+	.rate	    = 0, /* FIXME */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_CDS_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_CDS_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(cds_clk.lock),
+};
+#endif
+
+static struct clk dma_clk = {
+	.name       = "DMA",
+	.parent	    = &amba_clk,
+	.rate       = 52000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_DMAC_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_DMAC_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(dma_clk.lock),
+};
+
+static struct clk aaif_clk = {
+	.name       = "AAIF",
+	.parent	    = &amba_clk,
+	.rate       = 52000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_AAIF_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_AAIF_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(aaif_clk.lock),
+};
+
+static struct clk apex_clk = {
+	.name       = "APEX",
+	.parent	    = &amba_clk,
+	.rate       = 0, /* FIXME */
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_APEX_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_APEX_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(apex_clk.lock),
+};
+
+static struct clk video_enc_clk = {
+	.name       = "VIDEO_ENC",
+	.parent	    = &amba_clk,
+	.rate       = 208000000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = false,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	/* This has XGAM in the name but refers to the video encoder */
+	.res_mask   = U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(video_enc_clk.lock),
+};
+
+static struct clk xgam_clk = {
+	.name       = "XGAMCLK",
+	.parent	    = &amba_clk,
+	.rate       = 52000000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_XGAM_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_XGAM_CLK_EN,
+	.get_rate   = clk_get_rate_xgamclk,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(xgam_clk.lock),
+};
+
+/* This clock is used to activate the video encoder */
+static struct clk ahb_clk = {
+	.name	    = "AHB",
+	.parent	    = &amba_clk,
+	.rate	    = 52000000, /* this varies! */
+	.hw_ctrld   = false, /* This one is set to false due to HW bug */
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_AHB_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_AHB_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_ahb_clk,
+	.lock       = __SPIN_LOCK_UNLOCKED(ahb_clk.lock),
+};
+
+
+/*
+ * Clocks on the AHB bridge
+ */
+
+static struct clk ahb_subsys_clk = {
+	.name	    = "AHB_SUBSYS",
+	.parent	    = &amba_clk,
+	.rate	    = 52000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = false,
+	.clk_val    = U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_ahb_clk,
+	.lock       = __SPIN_LOCK_UNLOCKED(ahb_subsys_clk.lock),
+};
+
+static struct clk intcon_clk = {
+	.name	    = "INTCON",
+	.parent	    = &ahb_subsys_clk,
+	.rate	    = 52000000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_INTCON_RESET_EN,
+	/* INTCON can be reset but not clock-gated */
+	.lock       = __SPIN_LOCK_UNLOCKED(intcon_clk.lock),
+
+};
+
+static struct clk mspro_clk = {
+	.name       = "MSPRO",
+	.parent	    = &ahb_subsys_clk,
+	.rate       = 0, /* FIXME */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_MSPRO_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_MSPRO_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(mspro_clk.lock),
+};
+
+static struct clk emif_clk = {
+	.name	    = "EMIF",
+	.parent	    = &ahb_subsys_clk,
+	.rate	    = 104000000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
+	.res_mask   = U300_SYSCON_RRR_EMIF_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_EMIF_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_emif_clk,
+	.lock       = __SPIN_LOCK_UNLOCKED(emif_clk.lock),
+};
+
+
+/*
+ * Clocks on the FAST bridge
+ */
+static struct clk fast_clk = {
+	.name	    = "FAST_BRIDGE",
+	.parent	    = &amba_clk,
+	.rate	    = 13000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(fast_clk.lock),
+};
+
+static struct clk mmcsd_clk = {
+	.name       = "MCLK",
+	.parent	    = &fast_clk,
+	.rate       = 18900000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_MMC_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_MMC_CLK_EN,
+	.get_rate   = clk_get_rate_mclk,
+	.set_rate   = clk_set_rate_mclk,
+	.round_rate = clk_round_rate_mclk,
+	.disable    = syscon_clk_disable,
+	.enable     = syscon_clk_enable,
+	.lock       = __SPIN_LOCK_UNLOCKED(mmcsd_clk.lock),
+};
+
+static struct clk i2s0_clk = {
+	.name       = "i2s0",
+	.parent	    = &fast_clk,
+	.rate       = 26000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_I2S0_CORE_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_i2s_i2c_spi,
+	.lock       = __SPIN_LOCK_UNLOCKED(i2s0_clk.lock),
+};
+
+static struct clk i2s1_clk = {
+	.name       = "i2s1",
+	.parent	    = &fast_clk,
+	.rate       = 26000000, /* this varies! */
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_I2S1_CORE_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_i2s_i2c_spi,
+	.lock       = __SPIN_LOCK_UNLOCKED(i2s1_clk.lock),
+};
+
+static struct clk i2c0_clk = {
+	.name       = "I2C0",
+	.parent	    = &fast_clk,
+	.rate       = 26000000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_I2C0_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_I2C0_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_i2s_i2c_spi,
+	.lock       = __SPIN_LOCK_UNLOCKED(i2c0_clk.lock),
+};
+
+static struct clk i2c1_clk = {
+	.name       = "I2C1",
+	.parent	    = &fast_clk,
+	.rate       = 26000000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_I2C1_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_I2C1_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_i2s_i2c_spi,
+	.lock       = __SPIN_LOCK_UNLOCKED(i2c1_clk.lock),
+};
+
+static struct clk spi_clk = {
+	.name       = "SPI",
+	.parent	    = &fast_clk,
+	.rate       = 26000000, /* this varies! */
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_SPI_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_SPI_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.get_rate   = clk_get_rate_i2s_i2c_spi,
+	.lock       = __SPIN_LOCK_UNLOCKED(spi_clk.lock),
+};
+
+#ifdef CONFIG_MACH_U300_BS335
+static struct clk uart1_clk = {
+	.name	    = "UART1",
+	.parent	    = &fast_clk,
+	.rate	    = 13000000,
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
+	.res_mask   = U300_SYSCON_RFR_UART1_RESET_ENABLE,
+	.clk_val    = U300_SYSCON_SBCER_UART1_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(uart1_clk.lock),
+};
+#endif
+
+
+/*
+ * Clocks on the SLOW bridge
+ */
+static struct clk slow_clk = {
+	.name	    = "SLOW_BRIDGE",
+	.parent	    = &amba_clk,
+	.rate	    = 13000000,
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(slow_clk.lock),
+};
+
+/* TODO: implement SYSCON clock? */
+
+static struct clk wdog_clk = {
+	.name	    = "WDOG",
+	.parent	    = &slow_clk,
+	.hw_ctrld   = false,
+	.rate	    = 32768,
+	.reset	    = false,
+	/* This is always on, cannot be enabled/disabled or reset */
+	.lock       = __SPIN_LOCK_UNLOCKED(wdog_clk.lock),
+};
+
+/* This one is hardwired to PLL13 */
+static struct clk uart_clk = {
+	.name	    = "UARTCLK",
+	.parent	    = &slow_clk,
+	.rate	    = 13000000,
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_UART_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_UART_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(uart_clk.lock),
+};
+
+static struct clk keypad_clk = {
+	.name       = "KEYPAD",
+	.parent	    = &slow_clk,
+	.rate       = 32768,
+	.hw_ctrld   = false,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_KEYPAD_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_KEYPAD_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(keypad_clk.lock),
+};
+
+static struct clk gpio_clk = {
+	.name       = "GPIO",
+	.parent	    = &slow_clk,
+	.rate       = 13000000,
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_GPIO_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_GPIO_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(gpio_clk.lock),
+};
+
+static struct clk rtc_clk = {
+	.name	    = "RTC",
+	.parent	    = &slow_clk,
+	.rate	    = 32768,
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_RTC_RESET_EN,
+	/* This clock is always on, cannot be enabled/disabled */
+	.lock       = __SPIN_LOCK_UNLOCKED(rtc_clk.lock),
+};
+
+static struct clk bustr_clk = {
+	.name       = "BUSTR",
+	.parent	    = &slow_clk,
+	.rate       = 13000000,
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_BTR_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_BTR_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(bustr_clk.lock),
+};
+
+static struct clk evhist_clk = {
+	.name       = "EVHIST",
+	.parent	    = &slow_clk,
+	.rate       = 13000000,
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_EH_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_EH_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(evhist_clk.lock),
+};
+
+static struct clk timer_clk = {
+	.name       = "TIMER",
+	.parent	    = &slow_clk,
+	.rate       = 13000000,
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_ACC_TMR_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_ACC_TMR_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(timer_clk.lock),
+};
+
+static struct clk app_timer_clk = {
+	.name       = "TIMER_APP",
+	.parent	    = &slow_clk,
+	.rate       = 13000000,
+	.hw_ctrld   = true,
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_APP_TMR_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_APP_TMR_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(app_timer_clk.lock),
+};
+
+#ifdef CONFIG_MACH_U300_BS335
+static struct clk ppm_clk = {
+	.name	    = "PPM",
+	.parent	    = &slow_clk,
+	.rate	    = 0, /* FIXME */
+	.hw_ctrld   = true, /* TODO: Look up if it is hw ctrld or not */
+	.reset	    = true,
+	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
+	.res_mask   = U300_SYSCON_RSR_PPM_RESET_EN,
+	.clk_val    = U300_SYSCON_SBCER_PPM_CLK_EN,
+	.enable     = syscon_clk_enable,
+	.disable    = syscon_clk_disable,
+	.lock       = __SPIN_LOCK_UNLOCKED(ppm_clk.lock),
+};
+#endif
+
+#define DEF_LOOKUP(devid, clkref)		\
+	{					\
+	.dev_id = devid,			\
+	.clk = clkref,				\
+	}
+
+/*
+ * Here we only define clocks that are meaningful to
+ * look up through clockdevice.
+ */
+static struct clk_lookup lookups[] = {
+	/* Connected directly to the AMBA bus */
+	DEF_LOOKUP("amba",      &amba_clk),
+	DEF_LOOKUP("cpu",       &cpu_clk),
+	DEF_LOOKUP("fsmc",      &nandif_clk),
+	DEF_LOOKUP("semi",      &semi_clk),
+#ifdef CONFIG_MACH_U300_BS335
+	DEF_LOOKUP("isp",       &isp_clk),
+	DEF_LOOKUP("cds",       &cds_clk),
+#endif
+	DEF_LOOKUP("dma",       &dma_clk),
+	DEF_LOOKUP("msl",       &aaif_clk),
+	DEF_LOOKUP("apex",      &apex_clk),
+	DEF_LOOKUP("video_enc", &video_enc_clk),
+	DEF_LOOKUP("xgam",      &xgam_clk),
+	DEF_LOOKUP("ahb",       &ahb_clk),
+	/* AHB bridge clocks */
+	DEF_LOOKUP("ahb_subsys", &ahb_subsys_clk),
+	DEF_LOOKUP("intcon",    &intcon_clk),
+	DEF_LOOKUP("mspro",     &mspro_clk),
+	DEF_LOOKUP("pl172",     &emif_clk),
+	/* FAST bridge clocks */
+	DEF_LOOKUP("fast",      &fast_clk),
+	DEF_LOOKUP("mmci",      &mmcsd_clk),
+	/*
+	 * The .0 and .1 identifiers on these comes from the platform device
+	 * .id field and are assigned when the platform devices are registered.
+	 */
+	DEF_LOOKUP("i2s.0",     &i2s0_clk),
+	DEF_LOOKUP("i2s.1",     &i2s1_clk),
+	DEF_LOOKUP("stu300.0",  &i2c0_clk),
+	DEF_LOOKUP("stu300.1",  &i2c1_clk),
+	DEF_LOOKUP("pl022",     &spi_clk),
+#ifdef CONFIG_MACH_U300_BS335
+	DEF_LOOKUP("uart1",     &uart1_clk),
+#endif
+	/* SLOW bridge clocks */
+	DEF_LOOKUP("slow",      &slow_clk),
+	DEF_LOOKUP("coh901327_wdog",      &wdog_clk),
+	DEF_LOOKUP("uart0",     &uart_clk),
+	DEF_LOOKUP("apptimer",  &app_timer_clk),
+	DEF_LOOKUP("coh901461-keypad",    &keypad_clk),
+	DEF_LOOKUP("u300-gpio", &gpio_clk),
+	DEF_LOOKUP("rtc-coh901331",      &rtc_clk),
+	DEF_LOOKUP("bustr",     &bustr_clk),
+	DEF_LOOKUP("evhist",    &evhist_clk),
+	DEF_LOOKUP("timer",     &timer_clk),
+#ifdef CONFIG_MACH_U300_BS335
+	DEF_LOOKUP("ppm",       &ppm_clk),
+#endif
+};
+
+static void __init clk_register(void)
+{
+	int i;
+
+	/* Register the lookups */
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+}
+
+/*
+ * These are the clocks for cells registered as primecell drivers
+ * on the AMBA bus. These must be on during AMBA device registration
+ * since the bus probe will attempt to read magic configuration
+ * registers for these devices. If they are deactivated these probes
+ * will fail.
+ *
+ *
+ * Please note that on emif, both RAM and NAND is connected in dual
+ * RAM phones. On single RAM phones, ram is on semi and NAND on emif.
+ *
+ */
+void u300_clock_primecells(void)
+{
+	clk_enable(&intcon_clk);
+	clk_enable(&uart_clk);
+#ifdef CONFIG_MACH_U300_BS335
+	clk_enable(&uart1_clk);
+#endif
+	clk_enable(&spi_clk);
+
+	clk_enable(&mmcsd_clk);
+
+}
+EXPORT_SYMBOL(u300_clock_primecells);
+
+void u300_unclock_primecells(void)
+{
+
+	clk_disable(&intcon_clk);
+	clk_disable(&uart_clk);
+#ifdef CONFIG_MACH_U300_BS335
+	clk_disable(&uart1_clk);
+#endif
+	clk_disable(&spi_clk);
+	clk_disable(&mmcsd_clk);
+
+}
+EXPORT_SYMBOL(u300_unclock_primecells);
+
+/*
+ * The interrupt controller is enabled before the clock API is registered.
+ */
+void u300_enable_intcon_clock(void)
+{
+	clk_enable(&intcon_clk);
+}
+EXPORT_SYMBOL(u300_enable_intcon_clock);
+
+/*
+ * The timer is enabled before the clock API is registered.
+ */
+void u300_enable_timer_clock(void)
+{
+	clk_enable(&app_timer_clk);
+}
+EXPORT_SYMBOL(u300_enable_timer_clock);
+
+#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
+/*
+ * The following makes it possible to view the status (especially
+ * reference count and reset status) for the clocks in the platform
+ * by looking into the special file <debugfs>/u300_clocks
+ */
+
+/* A list of all clocks in the platform */
+static struct clk *clks[] = {
+	/* Top node clock for the AMBA bus */
+	&amba_clk,
+	/* Connected directly to the AMBA bus */
+	&cpu_clk,
+	&nandif_clk,
+	&semi_clk,
+#ifdef CONFIG_MACH_U300_BS335
+	&isp_clk,
+	&cds_clk,
+#endif
+	&dma_clk,
+	&aaif_clk,
+	&apex_clk,
+	&video_enc_clk,
+	&xgam_clk,
+	&ahb_clk,
+
+	/* AHB bridge clocks */
+	&ahb_subsys_clk,
+	&intcon_clk,
+	&mspro_clk,
+	&emif_clk,
+	/* FAST bridge clocks */
+	&fast_clk,
+	&mmcsd_clk,
+	&i2s0_clk,
+	&i2s1_clk,
+	&i2c0_clk,
+	&i2c1_clk,
+	&spi_clk,
+#ifdef CONFIG_MACH_U300_BS335
+	&uart1_clk,
+#endif
+	/* SLOW bridge clocks */
+	&slow_clk,
+	&wdog_clk,
+	&uart_clk,
+	&app_timer_clk,
+	&keypad_clk,
+	&gpio_clk,
+	&rtc_clk,
+	&bustr_clk,
+	&evhist_clk,
+	&timer_clk,
+#ifdef CONFIG_MACH_U300_BS335
+	&ppm_clk,
+#endif
+};
+
+static int u300_clocks_show(struct seq_file *s, void *data)
+{
+	struct clk *clk;
+	int i;
+
+	seq_printf(s, "CLOCK           DEVICE          RESET STATE\t" \
+		   "ACTIVE\tUSERS\tHW CTRL FREQ\n");
+	seq_printf(s, "---------------------------------------------" \
+		   "-----------------------------------------\n");
+	for (i = 0; i < ARRAY_SIZE(clks); i++) {
+		clk = clks[i];
+		if (clk != ERR_PTR(-ENOENT)) {
+			/* Format clock and device name nicely */
+			char cdp[33];
+			int chars;
+
+			chars = snprintf(&cdp[0], 17, "%s", clk->name);
+			while (chars < 16) {
+				cdp[chars] = ' ';
+				chars++;
+			}
+			chars = snprintf(&cdp[16], 17, "%s", clk->dev ?
+					 dev_name(clk->dev) : "N/A");
+			while (chars < 16) {
+				cdp[chars+16] = ' ';
+				chars++;
+			}
+			cdp[32] = '\0';
+			if (clk->get_rate)
+				seq_printf(s,
+					   "%s%s\t%s\t%d\t%s\t%lu Hz\n",
+					   &cdp[0],
+					   clk->reset ?
+					   "ASSERTED" : "RELEASED",
+					   clk->usecount ? "ON" : "OFF",
+					   clk->usecount,
+					   clk->hw_ctrld  ? "YES" : "NO ",
+					   clk->get_rate(clk));
+			else
+				seq_printf(s,
+					   "%s%s\t%s\t%d\t%s\t" \
+					   "(unknown rate)\n",
+					   &cdp[0],
+					   clk->reset ?
+					   "ASSERTED" : "RELEASED",
+					   clk->usecount ? "ON" : "OFF",
+					   clk->usecount,
+					   clk->hw_ctrld  ? "YES" : "NO ");
+		}
+	}
+	return 0;
+}
+
+static int u300_clocks_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, u300_clocks_show, NULL);
+}
+
+static const struct file_operations u300_clocks_operations = {
+	.open		= u300_clocks_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init init_clk_read_debugfs(void)
+{
+	/* Expose a simple debugfs interface to view all clocks */
+	(void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO,
+				   NULL, NULL,
+				   &u300_clocks_operations);
+	return 0;
+}
+/*
+ * This needs to come in after the core_initcall() for the
+ * overall clocks, because debugfs is not available until
+ * the subsystems come up.
+ */
+module_init(init_clk_read_debugfs);
+#endif
+
+static int __init u300_clock_init(void)
+{
+	u16 val;
+
+	/*
+	 * FIXME: shall all this powermanagement stuff really live here???
+	 */
+
+	/* Set system to run at PLL208, max performance, a known state. */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	/* Wait for the PLL208 to lock if not locked in yet */
+	while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) &
+		 U300_SYSCON_CSR_PLL208_LOCK_IND));
+
+	/* Power management enable */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMCR);
+	val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMCR);
+
+	clk_register();
+
+	/*
+	 * Some of these may be on when we boot the system so make sure they
+	 * are turned OFF.
+	 */
+	syscon_block_reset_enable(&timer_clk);
+	timer_clk.disable(&timer_clk);
+
+	/*
+	 * These shall be turned on by default when we boot the system
+	 * so make sure they are ON. (Adding CPU here is a bit too much.)
+	 * These clocks will be claimed by drivers later.
+	 */
+	syscon_block_reset_disable(&semi_clk);
+	syscon_block_reset_disable(&emif_clk);
+	semi_clk.enable(&semi_clk);
+	emif_clk.enable(&emif_clk);
+
+	return 0;
+}
+/* initialize clocking early to be available later in the boot */
+core_initcall(u300_clock_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/clock.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/clock.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * arch/arm/mach-u300/include/mach/clock.h
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * Adopted to ST-Ericsson U300 platforms by
+ * Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __MACH_CLOCK_H
+#define __MACH_CLOCK_H
+
+#include <linux/clk.h>
+
+struct clk {
+	struct list_head node;
+	struct module *owner;
+	struct device *dev;
+	const char *name;
+	struct clk *parent;
+
+	spinlock_t lock;
+	unsigned long rate;
+	bool reset;
+	__u16 clk_val;
+	__s8 usecount;
+	__u32 res_reg;
+	__u16 res_mask;
+
+	bool hw_ctrld;
+
+	void (*recalc) (struct clk *);
+	int (*set_rate) (struct clk *, unsigned long);
+	unsigned long (*get_rate) (struct clk *);
+	unsigned long (*round_rate) (struct clk *, unsigned long);
+	void (*init) (struct clk *);
+	void (*enable) (struct clk *);
+	void (*disable) (struct clk *);
+};
+
+void u300_clock_primecells(void);
+void u300_unclock_primecells(void);
+void u300_enable_intcon_clock(void);
+void u300_enable_timer_clock(void);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/core.c linux-libre-2.6.31-gnu/arch/arm/mach-u300/core.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,649 @@
+/*
+ *
+ * arch/arm/mach-u300/core.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Core platform support, IRQ handling and device definitions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/termios.h>
+#include <linux/amba/bus.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware/vic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/syscon.h>
+
+#include "clock.h"
+#include "mmc.h"
+
+/*
+ * Static I/O mappings that are needed for booting the U300 platforms. The
+ * only things we need are the areas where we find the timer, syscon and
+ * intcon, since the remaining device drivers will map their own memory
+ * physical to virtual as the need arise.
+ */
+static struct map_desc u300_io_desc[] __initdata = {
+	{
+		.virtual	= U300_SLOW_PER_VIRT_BASE,
+		.pfn		= __phys_to_pfn(U300_SLOW_PER_PHYS_BASE),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= U300_AHB_PER_VIRT_BASE,
+		.pfn		= __phys_to_pfn(U300_AHB_PER_PHYS_BASE),
+		.length		= SZ_32K,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= U300_FAST_PER_VIRT_BASE,
+		.pfn		= __phys_to_pfn(U300_FAST_PER_PHYS_BASE),
+		.length		= SZ_32K,
+		.type		= MT_DEVICE,
+	},
+	{
+		.virtual	= 0xffff2000, /* TCM memory */
+		.pfn		= __phys_to_pfn(0xffff2000),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	},
+
+	/*
+	 * This overlaps with the IRQ vectors etc at 0xffff0000, so these
+	 * may have to be moved to 0x00000000 in order to use the ROM.
+	 */
+	/*
+	{
+		.virtual	= U300_BOOTROM_VIRT_BASE,
+		.pfn		= __phys_to_pfn(U300_BOOTROM_PHYS_BASE),
+		.length		= SZ_64K,
+		.type		= MT_ROM,
+	},
+	*/
+};
+
+void __init u300_map_io(void)
+{
+	iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
+}
+
+/*
+ * Declaration of devices found on the U300 board and
+ * their respective memory locations.
+ */
+static struct amba_device uart0_device = {
+	.dev = {
+		.init_name = "uart0", /* Slow device at 0x3000 offset */
+		.platform_data = NULL,
+	},
+	.res = {
+		.start = U300_UART0_BASE,
+		.end   = U300_UART0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = { IRQ_U300_UART0, NO_IRQ },
+};
+
+/* The U335 have an additional UART1 on the APP CPU */
+#ifdef CONFIG_MACH_U300_BS335
+static struct amba_device uart1_device = {
+	.dev = {
+		.init_name = "uart1", /* Fast device at 0x7000 offset */
+		.platform_data = NULL,
+	},
+	.res = {
+		.start = U300_UART1_BASE,
+		.end   = U300_UART1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = { IRQ_U300_UART1, NO_IRQ },
+};
+#endif
+
+static struct amba_device pl172_device = {
+	.dev = {
+		.init_name = "pl172", /* AHB device at 0x4000 offset */
+		.platform_data = NULL,
+	},
+	.res = {
+		.start = U300_EMIF_CFG_BASE,
+		.end   = U300_EMIF_CFG_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+
+/*
+ * Everything within this next ifdef deals with external devices connected to
+ * the APP SPI bus.
+ */
+static struct amba_device pl022_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.init_name = "pl022", /* Fast device at 0x6000 offset */
+	},
+	.res = {
+		.start = U300_SPI_BASE,
+		.end   = U300_SPI_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_U300_SPI, NO_IRQ },
+	/*
+	 * This device has a DMA channel but the Linux driver does not use
+	 * it currently.
+	 */
+};
+
+static struct amba_device mmcsd_device = {
+	.dev = {
+		.init_name = "mmci", /* Fast device at 0x1000 offset */
+		.platform_data = NULL, /* Added later */
+	},
+	.res = {
+		.start = U300_MMCSD_BASE,
+		.end   = U300_MMCSD_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_U300_MMCSD_MCIINTR0, IRQ_U300_MMCSD_MCIINTR1 },
+	/*
+	 * This device has a DMA channel but the Linux driver does not use
+	 * it currently.
+	 */
+};
+
+/*
+ * The order of device declaration may be important, since some devices
+ * have dependencies on other devices being initialized first.
+ */
+static struct amba_device *amba_devs[] __initdata = {
+	&uart0_device,
+#ifdef CONFIG_MACH_U300_BS335
+	&uart1_device,
+#endif
+	&pl022_device,
+	&pl172_device,
+	&mmcsd_device,
+};
+
+/* Here follows a list of all hw resources that the platform devices
+ * allocate. Note, clock dependencies are not included
+ */
+
+static struct resource gpio_resources[] = {
+	{
+		.start = U300_GPIO_BASE,
+		.end   = (U300_GPIO_BASE + SZ_4K - 1),
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name  = "gpio0",
+		.start = IRQ_U300_GPIO_PORT0,
+		.end   = IRQ_U300_GPIO_PORT0,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name  = "gpio1",
+		.start = IRQ_U300_GPIO_PORT1,
+		.end   = IRQ_U300_GPIO_PORT1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name  = "gpio2",
+		.start = IRQ_U300_GPIO_PORT2,
+		.end   = IRQ_U300_GPIO_PORT2,
+		.flags = IORESOURCE_IRQ,
+	},
+#ifdef U300_COH901571_3
+	{
+		.name  = "gpio3",
+		.start = IRQ_U300_GPIO_PORT3,
+		.end   = IRQ_U300_GPIO_PORT3,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name  = "gpio4",
+		.start = IRQ_U300_GPIO_PORT4,
+		.end   = IRQ_U300_GPIO_PORT4,
+		.flags = IORESOURCE_IRQ,
+	},
+#ifdef CONFIG_MACH_U300_BS335
+	{
+		.name  = "gpio5",
+		.start = IRQ_U300_GPIO_PORT5,
+		.end   = IRQ_U300_GPIO_PORT5,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name  = "gpio6",
+		.start = IRQ_U300_GPIO_PORT6,
+		.end   = IRQ_U300_GPIO_PORT6,
+		.flags = IORESOURCE_IRQ,
+	},
+#endif /* CONFIG_MACH_U300_BS335 */
+#endif /* U300_COH901571_3 */
+};
+
+static struct resource keypad_resources[] = {
+	{
+		.start = U300_KEYPAD_BASE,
+		.end   = U300_KEYPAD_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name  = "coh901461-press",
+		.start = IRQ_U300_KEYPAD_KEYBF,
+		.end   = IRQ_U300_KEYPAD_KEYBF,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name  = "coh901461-release",
+		.start = IRQ_U300_KEYPAD_KEYBR,
+		.end   = IRQ_U300_KEYPAD_KEYBR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource rtc_resources[] = {
+	{
+		.start = U300_RTC_BASE,
+		.end   = U300_RTC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_U300_RTC,
+		.end   = IRQ_U300_RTC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/*
+ * Fsmc does have IRQs: #43 and #44 (NFIF and NFIF2)
+ * but these are not yet used by the driver.
+ */
+static struct resource fsmc_resources[] = {
+	{
+		.start = U300_NAND_IF_PHYS_BASE,
+		.end   = U300_NAND_IF_PHYS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct resource i2c0_resources[] = {
+	{
+		.start = U300_I2C0_BASE,
+		.end   = U300_I2C0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_U300_I2C0,
+		.end   = IRQ_U300_I2C0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource i2c1_resources[] = {
+	{
+		.start = U300_I2C1_BASE,
+		.end   = U300_I2C1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_U300_I2C1,
+		.end   = IRQ_U300_I2C1,
+		.flags = IORESOURCE_IRQ,
+	},
+
+};
+
+static struct resource wdog_resources[] = {
+	{
+		.start = U300_WDOG_BASE,
+		.end   = U300_WDOG_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_U300_WDOG,
+		.end   = IRQ_U300_WDOG,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+/* TODO: These should be protected by suitable #ifdef's */
+static struct resource ave_resources[] = {
+	{
+		.name  = "AVE3e I/O Area",
+		.start = U300_VIDEOENC_BASE,
+		.end   = U300_VIDEOENC_BASE + SZ_512K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name  = "AVE3e IRQ0",
+		.start = IRQ_U300_VIDEO_ENC_0,
+		.end   = IRQ_U300_VIDEO_ENC_0,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name  = "AVE3e IRQ1",
+		.start = IRQ_U300_VIDEO_ENC_1,
+		.end   = IRQ_U300_VIDEO_ENC_1,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name  = "AVE3e Physmem Area",
+		.start = 0, /* 0 will be remapped to reserved memory */
+		.end   = SZ_1M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	/*
+	 * The AVE3e requires two regions of 256MB that it considers
+	 * "invisible". The hardware will not be able to access these
+	 * adresses, so they should never point to system RAM.
+	 */
+	{
+		.name  = "AVE3e Reserved 0",
+		.start = 0xd0000000,
+		.end   = 0xd0000000 + SZ_256M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name  = "AVE3e Reserved 1",
+		.start = 0xe0000000,
+		.end   = 0xe0000000 + SZ_256M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device wdog_device = {
+	.name = "wdog",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(wdog_resources),
+	.resource = wdog_resources,
+};
+
+static struct platform_device i2c0_device = {
+	.name = "stddci2c",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(i2c0_resources),
+	.resource = i2c0_resources,
+};
+
+static struct platform_device i2c1_device = {
+	.name = "stddci2c",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(i2c1_resources),
+	.resource = i2c1_resources,
+};
+
+static struct platform_device gpio_device = {
+	.name = "u300-gpio",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(gpio_resources),
+	.resource = gpio_resources,
+};
+
+static struct platform_device keypad_device = {
+	.name = "keypad",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(keypad_resources),
+	.resource = keypad_resources,
+};
+
+static struct platform_device rtc_device = {
+	.name = "rtc0",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(rtc_resources),
+	.resource = rtc_resources,
+};
+
+static struct platform_device fsmc_device = {
+	.name = "nandif",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(fsmc_resources),
+	.resource = fsmc_resources,
+};
+
+static struct platform_device ave_device = {
+	.name = "video_enc",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(ave_resources),
+	.resource = ave_resources,
+};
+
+/*
+ * Notice that AMBA devices are initialized before platform devices.
+ *
+ */
+static struct platform_device *platform_devs[] __initdata = {
+	&i2c0_device,
+	&i2c1_device,
+	&keypad_device,
+	&rtc_device,
+	&gpio_device,
+	&fsmc_device,
+	&wdog_device,
+	&ave_device
+};
+
+
+/*
+ * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected
+ * together so some interrupts are connected to the first one and some
+ * to the second one.
+ */
+void __init u300_init_irq(void)
+{
+	u32 mask[2] = {0, 0};
+	int i;
+
+	for (i = 0; i < NR_IRQS; i++)
+		set_bit(i, (unsigned long *) &mask[0]);
+	u300_enable_intcon_clock();
+	vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
+	vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
+}
+
+
+/*
+ * U300 platforms peripheral handling
+ */
+struct db_chip {
+	u16 chipid;
+	const char *name;
+};
+
+/*
+ * This is a list of the Digital Baseband chips used in the U300 platform.
+ */
+static struct db_chip db_chips[] __initdata = {
+	{
+		.chipid = 0xb800,
+		.name = "DB3000",
+	},
+	{
+		.chipid = 0xc000,
+		.name = "DB3100",
+	},
+	{
+		.chipid = 0xc800,
+		.name = "DB3150",
+	},
+	{
+		.chipid = 0xd800,
+		.name = "DB3200",
+	},
+	{
+		.chipid = 0xe000,
+		.name = "DB3250",
+	},
+	{
+		.chipid = 0xe800,
+		.name = "DB3210",
+	},
+	{
+		.chipid = 0xf000,
+		.name = "DB3350 P1x",
+	},
+	{
+		.chipid = 0xf100,
+		.name = "DB3350 P2x",
+	},
+	{
+		.chipid = 0x0000, /* List terminator */
+		.name = NULL,
+	}
+};
+
+static void __init u300_init_check_chip(void)
+{
+
+	u16 val;
+	struct db_chip *chip;
+	const char *chipname;
+	const char unknown[] = "UNKNOWN";
+
+	/* Read out and print chip ID */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CIDR);
+	/* This is in funky bigendian order... */
+	val = (val & 0xFFU) << 8 | (val >> 8);
+	chip = db_chips;
+	chipname = unknown;
+
+	for ( ; chip->chipid; chip++) {
+		if (chip->chipid == (val & 0xFF00U)) {
+			chipname = chip->name;
+			break;
+		}
+	}
+	printk(KERN_INFO "Initializing U300 system on %s baseband chip " \
+	       "(chip ID 0x%04x)\n", chipname, val);
+
+#ifdef CONFIG_MACH_U300_BS26
+	if ((val & 0xFF00U) != 0xc800) {
+		printk(KERN_ERR "Platform configured for BS25/BS26 " \
+		       "with DB3150 but %s detected, expect problems!",
+		       chipname);
+	}
+#endif
+#ifdef CONFIG_MACH_U300_BS330
+	if ((val & 0xFF00U) != 0xd800) {
+		printk(KERN_ERR "Platform configured for BS330 " \
+		       "with DB3200 but %s detected, expect problems!",
+		       chipname);
+	}
+#endif
+#ifdef CONFIG_MACH_U300_BS335
+	if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
+		printk(KERN_ERR "Platform configured for BS365 " \
+		       " with DB3350 but %s detected, expect problems!",
+		       chipname);
+	}
+#endif
+#ifdef CONFIG_MACH_U300_BS365
+	if ((val & 0xFF00U) != 0xe800) {
+		printk(KERN_ERR "Platform configured for BS365 " \
+		       "with DB3210 but %s detected, expect problems!",
+		       chipname);
+	}
+#endif
+
+
+}
+
+/*
+ * Some devices and their resources require reserved physical memory from
+ * the end of the available RAM. This function traverses the list of devices
+ * and assigns actual adresses to these.
+ */
+static void __init u300_assign_physmem(void)
+{
+	unsigned long curr_start = __pa(high_memory);
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(platform_devs); i++) {
+		for (j = 0; j < platform_devs[i]->num_resources; j++) {
+			struct resource *const res =
+			  &platform_devs[i]->resource[j];
+
+			if (IORESOURCE_MEM == res->flags &&
+				     0 == res->start) {
+				res->start  = curr_start;
+				res->end   += curr_start;
+				curr_start += (res->end - res->start + 1);
+
+				printk(KERN_INFO "core.c: Mapping RAM " \
+				       "%#x-%#x to device %s:%s\n",
+					res->start, res->end,
+				       platform_devs[i]->name, res->name);
+			}
+		}
+	}
+}
+
+void __init u300_init_devices(void)
+{
+	int i;
+	u16 val;
+
+	/* Check what platform we run and print some status information */
+	u300_init_check_chip();
+
+	/* Set system to run at PLL208, max performance, a known state. */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
+	/* Wait for the PLL208 to lock if not locked in yet */
+	while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) &
+		 U300_SYSCON_CSR_PLL208_LOCK_IND));
+
+	/* Register the AMBA devices in the AMBA bus abstraction layer */
+	u300_clock_primecells();
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		amba_device_register(d, &iomem_resource);
+	}
+	u300_unclock_primecells();
+
+	u300_assign_physmem();
+
+	/* Register the platform devices */
+	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+
+#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
+	/*
+	 * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
+	 * both subsystems are requesting this mode.
+	 * If we not share the Acc SDRAM, this is never the case. Therefore
+	 * enable it here from the App side.
+	 */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) |
+		U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR);
+#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */
+}
+
+static int core_module_init(void)
+{
+	/*
+	 * This needs to be initialized later: it needs the input framework
+	 * to be initialized first.
+	 */
+	return mmc_init(&mmcsd_device);
+}
+module_init(core_module_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/gpio.c linux-libre-2.6.31-gnu/arch/arm/mach-u300/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,703 @@
+/*
+ *
+ * arch/arm/mach-u300/gpio.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * U300 GPIO module.
+ * This can driver either of the two basic GPIO cores
+ * available in the U300 platforms:
+ * COH 901 335   - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
+ * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
+ * Notice that you also have inline macros in <asm-arch/gpio.h>
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+/* Need access to SYSCON registers for PADmuxing */
+#include <mach/syscon.h>
+
+#include "padmux.h"
+
+/* Reference to GPIO block clock */
+static struct clk *clk;
+
+/* Memory resource */
+static struct resource *memres;
+static void __iomem *virtbase;
+static struct device *gpiodev;
+
+struct u300_gpio_port {
+	const char *name;
+	int irq;
+	int number;
+};
+
+
+static struct u300_gpio_port gpio_ports[] = {
+	{
+		.name = "gpio0",
+		.number = 0,
+	},
+	{
+		.name = "gpio1",
+		.number = 1,
+	},
+	{
+		.name = "gpio2",
+		.number = 2,
+	},
+#ifdef U300_COH901571_3
+	{
+		.name = "gpio3",
+		.number = 3,
+	},
+	{
+		.name = "gpio4",
+		.number = 4,
+	},
+#ifdef CONFIG_MACH_U300_BS335
+	{
+		.name = "gpio5",
+		.number = 5,
+	},
+	{
+		.name = "gpio6",
+		.number = 6,
+	},
+#endif
+#endif
+
+};
+
+
+#ifdef U300_COH901571_3
+
+/* Default input value */
+#define DEFAULT_OUTPUT_LOW   0
+#define DEFAULT_OUTPUT_HIGH  1
+
+/* GPIO Pull-Up status */
+#define DISABLE_PULL_UP  0
+#define ENABLE_PULL_UP  1
+
+#define GPIO_NOT_USED 0
+#define GPIO_IN       1
+#define GPIO_OUT      2
+
+struct u300_gpio_configuration_data {
+	unsigned char pin_usage;
+	unsigned char default_output_value;
+	unsigned char pull_up;
+};
+
+/* Initial configuration */
+const struct u300_gpio_configuration_data
+u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
+#ifdef CONFIG_MACH_U300_BS335
+	/* Port 0, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	},
+	/* Port 1, pins 0-7 */
+	{
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	},
+	/* Port 2, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+	},
+	/* Port 3, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	},
+	/* Port 4, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	},
+	/* Port 5, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	},
+	/* Port 6, pind 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	}
+#endif
+
+#ifdef CONFIG_MACH_U300_BS365
+	/* Port 0, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	},
+	/* Port 1, pins 0-7 */
+	{
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+	},
+	/* Port 2, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+	},
+	/* Port 3, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+	},
+	/* Port 4, pins 0-7 */
+	{
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		/* These 4 pins doesn't exist on DB3210 */
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+		{GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+	}
+#endif
+};
+#endif
+
+
+/* No users == we can power down GPIO */
+static int gpio_users;
+
+struct gpio_struct {
+	int (*callback)(void *);
+	void *data;
+	int users;
+};
+
+static struct gpio_struct gpio_pin[U300_GPIO_MAX];
+
+/*
+ * Let drivers register callback in order to get notified when there is
+ * an interrupt on the gpio pin
+ */
+int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
+{
+	if (gpio_pin[gpio].callback)
+		dev_warn(gpiodev, "%s: WARNING: callback already "
+			 "registered for gpio pin#%d\n", __func__, gpio);
+	gpio_pin[gpio].callback = func;
+	gpio_pin[gpio].data = data;
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_register_callback);
+
+int gpio_unregister_callback(unsigned gpio)
+{
+	if (!gpio_pin[gpio].callback)
+		dev_warn(gpiodev, "%s: WARNING: callback already "
+			 "unregistered for gpio pin#%d\n", __func__, gpio);
+	gpio_pin[gpio].callback = NULL;
+	gpio_pin[gpio].data = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_unregister_callback);
+
+int gpio_request(unsigned gpio, const char *label)
+{
+	if (gpio_pin[gpio].users)
+		return -EINVAL;
+	else
+		gpio_pin[gpio].users++;
+
+	gpio_users++;
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+	gpio_users--;
+	gpio_pin[gpio].users--;
+	if (unlikely(gpio_pin[gpio].users < 0)) {
+		dev_warn(gpiodev, "warning: gpio#%d release mismatch\n",
+			 gpio);
+		gpio_pin[gpio].users = 0;
+	}
+
+	return;
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* This returns zero or nonzero */
+int gpio_get_value(unsigned gpio)
+{
+	return readl(virtbase + U300_GPIO_PXPDIR +
+	  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+/*
+ * We hope that the compiler will optimize away the unused branch
+ * in case "value" is a constant
+ */
+void gpio_set_value(unsigned gpio, int value)
+{
+	u32 val;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (value) {
+		/* set */
+		val = readl(virtbase + U300_GPIO_PXPDOR +
+		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
+		  & (1 << (gpio & 0x07));
+		writel(val | (1 << (gpio & 0x07)), virtbase +
+		  U300_GPIO_PXPDOR +
+		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+	} else {
+		/* clear */
+		val = readl(virtbase + U300_GPIO_PXPDOR +
+		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
+		  & (1 << (gpio & 0x07));
+		writel(val & ~(1 << (gpio & 0x07)), virtbase +
+		  U300_GPIO_PXPDOR +
+		  PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+	}
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+int gpio_direction_input(unsigned gpio)
+{
+	unsigned long flags;
+	u32 val;
+
+	if (gpio > U300_GPIO_MAX)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	/* Mask out this pin*/
+	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
+	/* This is not needed since it sets the bits to zero.*/
+	/* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
+	writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	local_irq_restore(flags);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+	unsigned long flags;
+	u32 val;
+
+	if (gpio > U300_GPIO_MAX)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	/* Mask out this pin */
+	val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
+	/*
+	 * FIXME: configure for push/pull, open drain or open source per pin
+	 * in setup. The current driver will only support push/pull.
+	 */
+	val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+			<< ((gpio & 0x07) << 1));
+	writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	gpio_set_value(gpio, value);
+	local_irq_restore(flags);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
+ */
+void enable_irq_on_gpio_pin(unsigned gpio, int edge)
+{
+	u32 val;
+	unsigned long flags;
+	local_irq_save(flags);
+
+	val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	val |= (1 << (gpio & 0x07));
+	writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	if (edge)
+		val |= (1 << (gpio & 0x07));
+	else
+		val &= ~(1 << (gpio & 0x07));
+	writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(enable_irq_on_gpio_pin);
+
+void disable_irq_on_gpio_pin(unsigned gpio)
+{
+	u32 val;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	val &= ~(1 << (gpio & 0x07));
+	writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+				U300_GPIO_PORTX_SPACING);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(disable_irq_on_gpio_pin);
+
+/* Enable (value == 0) or disable (value == 1) internal pullup */
+void gpio_pullup(unsigned gpio, int value)
+{
+	u32 val;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (value) {
+		val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
+					U300_GPIO_PORTX_SPACING);
+		writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
+				PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+	} else {
+		val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
+					U300_GPIO_PORTX_SPACING);
+		writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
+				PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+	}
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_pullup);
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+	struct u300_gpio_port *port = dev_id;
+	u32 val;
+	int pin;
+
+	/* Read event register */
+	val = readl(virtbase + U300_GPIO_PXIEV + port->number *
+				U300_GPIO_PORTX_SPACING);
+	/* Mask with enable register */
+	val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
+				U300_GPIO_PORTX_SPACING);
+	/* Mask relevant bits */
+	val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
+	/* ACK IRQ (clear event) */
+	writel(val, virtbase + U300_GPIO_PXIEV + port->number *
+				U300_GPIO_PORTX_SPACING);
+	/* Print message */
+	while (val != 0) {
+		unsigned gpio;
+
+		pin = __ffs(val);
+		/* mask off this pin */
+		val &= ~(1 << pin);
+		gpio = (port->number << 3) + pin;
+
+		if (gpio_pin[gpio].callback)
+			(void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
+		else
+			dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n",
+			       gpio);
+	}
+	return IRQ_HANDLED;
+}
+
+static void gpio_set_initial_values(void)
+{
+#ifdef U300_COH901571_3
+	int i, j;
+	unsigned long flags;
+	u32 val;
+
+	/* Write default values to all pins */
+	for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
+		val = 0;
+		for (j = 0; j < 8; j++)
+			val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
+		local_irq_save(flags);
+		writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
+		local_irq_restore(flags);
+	}
+
+	/*
+	 * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
+	 * to output and 'GPIO_IN' to input for each port. And initalize
+	 * default value on outputs.
+	 */
+	for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
+		for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
+			local_irq_save(flags);
+			val = readl(virtbase + U300_GPIO_PXPCR +
+					 i * U300_GPIO_PORTX_SPACING);
+			/* Mask out this pin */
+			val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
+
+			if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
+				val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
+			writel(val, virtbase + U300_GPIO_PXPCR +
+					 i * U300_GPIO_PORTX_SPACING);
+			local_irq_restore(flags);
+		}
+	}
+
+	/* Enable or disable the internal pull-ups in the GPIO ASIC block */
+	for (i = 0; i < U300_GPIO_MAX; i++) {
+		val = 0;
+		for (j = 0; j < 8; j++)
+			val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP)) << j;
+		local_irq_save(flags);
+		writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
+		local_irq_restore(flags);
+	}
+#endif
+}
+
+static int __init gpio_probe(struct platform_device *pdev)
+{
+	u32 val;
+	int err = 0;
+	int i;
+	int num_irqs;
+
+	gpiodev = &pdev->dev;
+	memset(gpio_pin, 0, sizeof(gpio_pin));
+
+	/* Get GPIO clock */
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		err = PTR_ERR(clk);
+		dev_err(gpiodev, "could not get GPIO clock\n");
+		goto err_no_clk;
+	}
+	err = clk_enable(clk);
+	if (err) {
+		dev_err(gpiodev, "could not enable GPIO clock\n");
+		goto err_no_clk_enable;
+	}
+
+	memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!memres)
+		goto err_no_resource;
+
+	if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller")
+	    == NULL) {
+		err = -ENODEV;
+		goto err_no_ioregion;
+	}
+
+	virtbase = ioremap(memres->start, resource_size(memres));
+	if (!virtbase) {
+		err = -ENOMEM;
+		goto err_no_ioremap;
+	}
+	dev_info(gpiodev, "remapped 0x%08x to %p\n",
+		 memres->start, virtbase);
+
+#ifdef U300_COH901335
+	dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n");
+	/* Turn on the GPIO block */
+	writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
+#endif
+
+#ifdef U300_COH901571_3
+	dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n");
+	val = readl(virtbase + U300_GPIO_CR);
+	dev_info(gpiodev, "COH901571/3 block version: %d, " \
+	       "number of cores: %d\n",
+	       ((val & 0x0000FE00) >> 9),
+	       ((val & 0x000001FC) >> 2));
+	writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
+#endif
+
+	/* Set up some padmuxing here */
+#ifdef CONFIG_MMC
+	pmx_set_mission_mode_mmc();
+#endif
+#ifdef CONFIG_SPI_PL022
+	pmx_set_mission_mode_spi();
+#endif
+
+	gpio_set_initial_values();
+
+	for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
+
+		gpio_ports[num_irqs].irq =
+			platform_get_irq_byname(pdev,
+						gpio_ports[num_irqs].name);
+
+		err = request_irq(gpio_ports[num_irqs].irq,
+				  gpio_irq_handler, IRQF_DISABLED,
+				  gpio_ports[num_irqs].name,
+				  &gpio_ports[num_irqs]);
+		if (err) {
+			dev_err(gpiodev, "cannot allocate IRQ for %s!\n",
+				gpio_ports[num_irqs].name);
+			goto err_no_irq;
+		}
+		/* Turns off PortX_irq_force */
+		writel(0x0, virtbase + U300_GPIO_PXIFR +
+				 num_irqs * U300_GPIO_PORTX_SPACING);
+	}
+
+	return 0;
+
+ err_no_irq:
+	for (i = 0; i < num_irqs; i++)
+		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
+	iounmap(virtbase);
+ err_no_ioremap:
+	release_mem_region(memres->start, memres->end - memres->start);
+ err_no_ioregion:
+ err_no_resource:
+	clk_disable(clk);
+ err_no_clk_enable:
+	clk_put(clk);
+ err_no_clk:
+	dev_info(gpiodev, "module ERROR:%d\n", err);
+	return err;
+}
+
+static int __exit gpio_remove(struct platform_device *pdev)
+{
+	int i;
+
+	/* Turn off the GPIO block */
+	writel(0x00000000U, virtbase + U300_GPIO_CR);
+	for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
+		free_irq(gpio_ports[i].irq, &gpio_ports[i]);
+	iounmap(virtbase);
+	release_mem_region(memres->start, memres->end - memres->start);
+	clk_disable(clk);
+	clk_put(clk);
+	return 0;
+}
+
+static struct platform_driver gpio_driver = {
+	.driver		= {
+		.name	= "u300-gpio",
+	},
+	.remove		= __exit_p(gpio_remove),
+};
+
+
+static int __init u300_gpio_init(void)
+{
+	return platform_driver_probe(&gpio_driver, gpio_probe);
+}
+
+static void __exit u300_gpio_exit(void)
+{
+	platform_driver_unregister(&gpio_driver);
+}
+
+arch_initcall(u300_gpio_init);
+module_exit(u300_gpio_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
+
+#ifdef U300_COH901571_3
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
+#endif
+
+#ifdef U300_COH901335
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
+#endif
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/clkdev.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/clkdev.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/clkdev.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+int __clk_get(struct clk *clk);
+void __clk_put(struct clk *clk);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/debug-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/debug-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/debug-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ *
+ * arch-arm/mach-u300/include/mach/debug-macro.S
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Debugging macro include header.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <mach/hardware.h>
+
+	.macro	addruart,rx
+	/* If we move the adress using MMU, use this. */
+	mrc	p15, 0, \rx, c1, c0
+	tst	\rx, #1			@ MMU enabled?
+	ldreq	\rx,	  = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
+	ldrne	\rx,	  = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
+	orr	\rx, \rx, #0x00003000
+	.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/entry-macro.S linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/entry-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/entry-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ *
+ * arch-arm/mach-u300/include/mach/entry-macro.S
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Low-level IRQ helper macros for ST-Ericsson U300
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <mach/hardware.h>
+#include <asm/hardware/vic.h>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON0_BASE
+	ldr	\irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
+	mov	\irqnr, #0
+	teq	\irqstat, #0
+	bne	1002f
+1001:	ldr	\base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON1_BASE
+	ldr	\irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
+	mov	\irqnr, #32
+	teq	\irqstat, #0
+	beq	1003f
+1002:	tst	\irqstat, #1
+	bne	1003f
+	add	\irqnr, \irqnr, #1
+	movs	\irqstat, \irqstat, lsr #1
+	bne	1002b
+1003:		/* EQ will be set if no irqs pending */
+	.endm
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/gpio.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,290 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/gpio.h
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * GPIO block resgister definitions and inline macros for
+ * U300 GPIO COH 901 335 or COH 901 571/3
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_GPIO_H
+#define __MACH_U300_GPIO_H
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+/* Switch type depending on platform/chip variant */
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+#define U300_COH901335
+#endif
+#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
+#define U300_COH901571_3
+#endif
+
+/* Get base address for regs here */
+#include "u300-regs.h"
+/* IRQ numbers */
+#include "irqs.h"
+
+/*
+ * This is the GPIO block definitions. GPIO (General Purpose I/O) can be
+ * used for anything, and often is. The event/enable etc figures are for
+ * the lowermost pin (pin 0 on each port), shift this left to match your
+ * pin if you're gonna use these values.
+ */
+#ifdef U300_COH901335
+#define U300_GPIO_PORTX_SPACING				(0x1C)
+/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
+#define U300_GPIO_PXPDIR				(0x00)
+#define U300_GPIO_PXPDOR				(0x00)
+/* Port X Pin Config Register 32bit (R/W) */
+#define U300_GPIO_PXPCR					(0x04)
+#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
+#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
+#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
+/* Port X Interrupt Event Register 32bit (R/W) */
+#define U300_GPIO_PXIEV					(0x08)
+#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK		(0x000000FFUL)
+#define U300_GPIO_PXIEV_IRQ_EVENT			(0x00000001UL)
+/* Port X Interrupt Enable Register 32bit (R/W) */
+#define U300_GPIO_PXIEN					(0x0C)
+#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK		(0x000000FFUL)
+#define U300_GPIO_PXIEN_IRQ_ENABLE			(0x00000001UL)
+/* Port X Interrupt Force Register 32bit (R/W) */
+#define U300_GPIO_PXIFR					(0x10)
+#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK		(0x000000FFUL)
+#define U300_GPIO_PXIFR_IRQ_FORCE			(0x00000001UL)
+/* Port X Interrupt Config Register 32bit (R/W) */
+#define U300_GPIO_PXICR					(0x14)
+#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
+/* Port X Pull-up Enable Register 32bit (R/W) */
+#define U300_GPIO_PXPER					(0x18)
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
+/* Control Register 32bit (R/W) */
+#define U300_GPIO_CR					(0x54)
+#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE			(0x00000001UL)
+/* three ports of 8 bits each = GPIO pins 0..23 */
+#define U300_GPIO_NUM_PORTS 3
+#define U300_GPIO_PINS_PER_PORT 8
+#define U300_GPIO_MAX	(U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
+#endif
+
+#ifdef U300_COH901571_3
+/*
+ * Control Register 32bit (R/W)
+ * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
+ * gives the number of GPIO pins.
+ * bit 8-2  (mask 0x000001FC) contains the core version ID.
+ */
+#define U300_GPIO_CR					(0x00)
+#define U300_GPIO_CR_SYNC_SEL_ENABLE			(0x00000002UL)
+#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE			(0x00000001UL)
+#define U300_GPIO_PORTX_SPACING				(0x30)
+/* Port X Pin Data INPUT Register 32bit (R/W) */
+#define U300_GPIO_PXPDIR				(0x04)
+/* Port X Pin Data OUTPUT Register 32bit (R/W) */
+#define U300_GPIO_PXPDOR				(0x08)
+/* Port X Pin Config Register 32bit (R/W) */
+#define U300_GPIO_PXPCR					(0x0C)
+#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK		(0x0000FFFFUL)
+#define U300_GPIO_PXPCR_PIN_MODE_MASK			(0x00000003UL)
+#define U300_GPIO_PXPCR_PIN_MODE_SHIFT			(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_INPUT			(0x00000000UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL	(0x00000001UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN	(0x00000002UL)
+#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE	(0x00000003UL)
+/* Port X Pull-up Enable Register 32bit (R/W) */
+#define U300_GPIO_PXPER					(0x10)
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK	(0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE			(0x00000001UL)
+/* Port X Interrupt Event Register 32bit (R/W) */
+#define U300_GPIO_PXIEV					(0x14)
+#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK		(0x000000FFUL)
+#define U300_GPIO_PXIEV_IRQ_EVENT			(0x00000001UL)
+/* Port X Interrupt Enable Register 32bit (R/W) */
+#define U300_GPIO_PXIEN					(0x18)
+#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK		(0x000000FFUL)
+#define U300_GPIO_PXIEN_IRQ_ENABLE			(0x00000001UL)
+/* Port X Interrupt Force Register 32bit (R/W) */
+#define U300_GPIO_PXIFR					(0x1C)
+#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK		(0x000000FFUL)
+#define U300_GPIO_PXIFR_IRQ_FORCE			(0x00000001UL)
+/* Port X Interrupt Config Register 32bit (R/W) */
+#define U300_GPIO_PXICR					(0x20)
+#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK		(0x000000FFUL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_MASK			(0x00000001UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE		(0x00000000UL)
+#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE		(0x00000001UL)
+#ifdef CONFIG_MACH_U300_BS335
+/* seven ports of 8 bits each = GPIO pins 0..55 */
+#define U300_GPIO_NUM_PORTS 7
+#else
+/* five ports of 8 bits each = GPIO pins 0..39 */
+#define U300_GPIO_NUM_PORTS 5
+#endif
+#define U300_GPIO_PINS_PER_PORT 8
+#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1)
+#endif
+
+/*
+ * Individual pin assignments for the B26/S26. Notice that the
+ * actual usage of these pins depends on the PAD MUX settings, that
+ * is why the same number can potentially appear several times.
+ * In the reference design each pin is only used for one purpose.
+ * These were determined by inspecting the B26/S26 schematic:
+ * 2/1911-ROA 128 1603
+ */
+#ifdef CONFIG_MACH_U300_BS2X
+#define U300_GPIO_PIN_UART_RX		0
+#define U300_GPIO_PIN_UART_TX		1
+#define U300_GPIO_PIN_GPIO02		2  /* Unrouted */
+#define U300_GPIO_PIN_GPIO03		3  /* Unrouted */
+#define U300_GPIO_PIN_CAM_SLEEP		4
+#define U300_GPIO_PIN_CAM_REG_EN	5
+#define U300_GPIO_PIN_GPIO06		6  /* Unrouted */
+#define U300_GPIO_PIN_GPIO07		7  /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO08		8  /* Service point SP2321 */
+#define U300_GPIO_PIN_GPIO09		9  /* Service point SP2322 */
+#define U300_GPIO_PIN_PHFSENSE		10 /* Headphone jack sensing */
+#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_FLIPSENSE		13 /* Mechanical flip sensing */
+#define U300_GPIO_PIN_GPIO14		14 /* DSP JTAG Port RTCK */
+#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16		16 /* Unrouted */
+#define U300_GPIO_PIN_GPIO17		17 /* Unrouted */
+#define U300_GPIO_PIN_GPIO18		18 /* Unrouted */
+#define U300_GPIO_PIN_GPIO19		19 /* Unrouted */
+#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
+#endif
+
+/*
+ * Individual pin assignments for the B330/S330 and B365/S365.
+ * Notice that the actual usage of these pins depends on the
+ * PAD MUX settings, that is why the same number can potentially
+ * appear several times. In the reference design each pin is only
+ * used for one purpose. These were determined by inspecting the
+ * S365 schematic.
+ */
+#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
+    defined(CONFIG_MACH_U300_BS335)
+#define U300_GPIO_PIN_UART_RX		0
+#define U300_GPIO_PIN_UART_TX		1
+#define U300_GPIO_PIN_UART_CTS		2
+#define U300_GPIO_PIN_UART_RTS		3
+#define U300_GPIO_PIN_CAM_MAIN_STANDBY	4 /* Camera MAIN standby */
+#define U300_GPIO_PIN_GPIO05		5 /* Unrouted */
+#define U300_GPIO_PIN_MS_CD		6 /* Memory Stick Card insertion */
+#define U300_GPIO_PIN_GPIO07		7 /* Test point TP2430 */
+
+#define U300_GPIO_PIN_GPIO08		8 /* Test point TP2437 */
+#define U300_GPIO_PIN_GPIO09		9 /* Test point TP2431 */
+#define U300_GPIO_PIN_GPIO10		10 /* Test point TP2432 */
+#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
+#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
+#define U300_GPIO_PIN_CAM_SUB_STANDBY	13 /* Camera SUB standby */
+#define U300_GPIO_PIN_GPIO14		14 /* Test point TP2436 */
+#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO16		16 /* Test point TP2438 */
+#define U300_GPIO_PIN_PHFSENSE		17 /* Headphone jack sensing */
+#define U300_GPIO_PIN_GPIO18		18 /* Test point TP2439 */
+#define U300_GPIO_PIN_GPIO19		19 /* Routed somewhere */
+#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
+#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
+#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
+#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO24		24 /* Unrouted */
+#define U300_GPIO_PIN_GPIO25		25 /* Unrouted */
+#define U300_GPIO_PIN_GPIO26		26 /* Unrouted */
+#define U300_GPIO_PIN_GPIO27		27 /* Unrouted */
+#define U300_GPIO_PIN_GPIO28		28 /* Unrouted */
+#define U300_GPIO_PIN_GPIO29		29 /* Unrouted */
+#define U300_GPIO_PIN_GPIO30		30 /* Unrouted */
+#define U300_GPIO_PIN_GPIO31		31 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO32		32 /* Unrouted */
+#define U300_GPIO_PIN_GPIO33		33 /* Unrouted */
+#define U300_GPIO_PIN_GPIO34		34 /* Unrouted */
+#define U300_GPIO_PIN_GPIO35		35 /* Unrouted */
+#define U300_GPIO_PIN_GPIO36		36 /* Unrouted */
+#define U300_GPIO_PIN_GPIO37		37 /* Unrouted */
+#define U300_GPIO_PIN_GPIO38		38 /* Unrouted */
+#define U300_GPIO_PIN_GPIO39		39 /* Unrouted */
+
+#ifdef CONFIG_MACH_U300_BS335
+
+#define U300_GPIO_PIN_GPIO40		40 /* Unrouted */
+#define U300_GPIO_PIN_GPIO41		41 /* Unrouted */
+#define U300_GPIO_PIN_GPIO42		42 /* Unrouted */
+#define U300_GPIO_PIN_GPIO43		43 /* Unrouted */
+#define U300_GPIO_PIN_GPIO44		44 /* Unrouted */
+#define U300_GPIO_PIN_GPIO45		45 /* Unrouted */
+#define U300_GPIO_PIN_GPIO46		46 /* Unrouted */
+#define U300_GPIO_PIN_GPIO47		47 /* Unrouted */
+
+#define U300_GPIO_PIN_GPIO48		48 /* Unrouted */
+#define U300_GPIO_PIN_GPIO49		49 /* Unrouted */
+#define U300_GPIO_PIN_GPIO50		50 /* Unrouted */
+#define U300_GPIO_PIN_GPIO51		51 /* Unrouted */
+#define U300_GPIO_PIN_GPIO52		52 /* Unrouted */
+#define U300_GPIO_PIN_GPIO53		53 /* Unrouted */
+#define U300_GPIO_PIN_GPIO54		54 /* Unrouted */
+#define U300_GPIO_PIN_GPIO55		55 /* Unrouted */
+#endif
+
+#endif
+
+/* translates a pin number to a port number */
+#define PIN_TO_PORT(val) (val >> 3)
+
+/* These can be found in arch/arm/mach-u300/gpio.c */
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
+extern int gpio_register_callback(unsigned gpio,
+				  int (*func)(void *arg),
+				  void *);
+extern int gpio_unregister_callback(unsigned gpio);
+extern void enable_irq_on_gpio_pin(unsigned gpio, int edge);
+extern void disable_irq_on_gpio_pin(unsigned gpio);
+extern void gpio_pullup(unsigned gpio, int value);
+extern int gpio_get_value(unsigned gpio);
+extern void gpio_set_value(unsigned gpio, int value);
+
+/* wrappers to sleep-enable the previous two functions */
+static inline unsigned gpio_to_irq(unsigned gpio)
+{
+	return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0;
+}
+
+static inline unsigned irq_to_gpio(unsigned irq)
+{
+	/*
+	 * FIXME: This is no 1-1 mapping at all, it points to the
+	 * whole block of 8 pins.
+	 */
+	return (irq - IRQ_U300_GPIO_PORT0) << 3;
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/hardware.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/hardware.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/hardware.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-u300/include/mach/hardware.h
+ */
+#include <asm/sizes.h>
+#include <mach/u300-regs.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/io.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/io.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/io.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Dummy IO map for being able to use writew()/readw(),
+ * writel()/readw() and similar accessor functions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/irqs.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * IRQ channel definitions for the U300 platforms.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define IRQ_U300_INTCON0_START		0
+#define IRQ_U300_INTCON1_START		32
+/* These are on INTCON0 - 30 lines */
+#define IRQ_U300_IRQ0_EXT		0
+#define IRQ_U300_IRQ1_EXT		1
+#define IRQ_U300_DMA			2
+#define IRQ_U300_VIDEO_ENC_0		3
+#define IRQ_U300_VIDEO_ENC_1		4
+#define IRQ_U300_AAIF_RX		5
+#define IRQ_U300_AAIF_TX		6
+#define IRQ_U300_AAIF_VGPIO		7
+#define IRQ_U300_AAIF_WAKEUP		8
+#define IRQ_U300_PCM_I2S0_FRAME		9
+#define IRQ_U300_PCM_I2S0_FIFO		10
+#define IRQ_U300_PCM_I2S1_FRAME		11
+#define IRQ_U300_PCM_I2S1_FIFO		12
+#define IRQ_U300_XGAM_GAMCON		13
+#define IRQ_U300_XGAM_CDI		14
+#define IRQ_U300_XGAM_CDICON		15
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+/* MMIACC not used on the DB3210 or DB3350 chips */
+#define IRQ_U300_XGAM_MMIACC		16
+#endif
+#define IRQ_U300_XGAM_PDI		17
+#define IRQ_U300_XGAM_PDICON		18
+#define IRQ_U300_XGAM_GAMEACC		19
+#define IRQ_U300_XGAM_MCIDCT		20
+#define IRQ_U300_APEX			21
+#define IRQ_U300_UART0			22
+#define IRQ_U300_SPI			23
+#define IRQ_U300_TIMER_APP_OS		24
+#define IRQ_U300_TIMER_APP_DD		25
+#define IRQ_U300_TIMER_APP_GP1		26
+#define IRQ_U300_TIMER_APP_GP2		27
+#define IRQ_U300_TIMER_OS		28
+#define IRQ_U300_TIMER_MS		29
+#define IRQ_U300_KEYPAD_KEYBF		30
+#define IRQ_U300_KEYPAD_KEYBR		31
+/* These are on INTCON1 - 32 lines */
+#define IRQ_U300_GPIO_PORT0		32
+#define IRQ_U300_GPIO_PORT1		33
+#define IRQ_U300_GPIO_PORT2		34
+
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) || \
+    defined(CONFIG_MACH_U300_BS335)
+/* These are for DB3150, DB3200 and DB3350 */
+#define IRQ_U300_WDOG			35
+#define IRQ_U300_EVHIST			36
+#define IRQ_U300_MSPRO			37
+#define IRQ_U300_MMCSD_MCIINTR0		38
+#define IRQ_U300_MMCSD_MCIINTR1		39
+#define IRQ_U300_I2C0			40
+#define IRQ_U300_I2C1			41
+#define IRQ_U300_RTC			42
+#define IRQ_U300_NFIF			43
+#define IRQ_U300_NFIF2			44
+#endif
+
+/* DB3150 and DB3200 have only 45 IRQs */
+#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
+#define U300_NR_IRQS			45
+#endif
+
+/* The DB3350-specific interrupt lines */
+#ifdef CONFIG_MACH_U300_BS335
+#define IRQ_U300_ISP_F0			45
+#define IRQ_U300_ISP_F1			46
+#define IRQ_U300_ISP_F2			47
+#define IRQ_U300_ISP_F3			48
+#define IRQ_U300_ISP_F4			49
+#define IRQ_U300_GPIO_PORT3		50
+#define IRQ_U300_SYSCON_PLL_LOCK	51
+#define IRQ_U300_UART1			52
+#define IRQ_U300_GPIO_PORT4		53
+#define IRQ_U300_GPIO_PORT5		54
+#define IRQ_U300_GPIO_PORT6		55
+#define U300_NR_IRQS			56
+#endif
+
+/* The DB3210-specific interrupt lines */
+#ifdef CONFIG_MACH_U300_BS365
+#define IRQ_U300_GPIO_PORT3		35
+#define IRQ_U300_GPIO_PORT4		36
+#define IRQ_U300_WDOG			37
+#define IRQ_U300_EVHIST			38
+#define IRQ_U300_MSPRO			39
+#define IRQ_U300_MMCSD_MCIINTR0		40
+#define IRQ_U300_MMCSD_MCIINTR1		41
+#define IRQ_U300_I2C0			42
+#define IRQ_U300_I2C1			43
+#define IRQ_U300_RTC			44
+#define IRQ_U300_NFIF			45
+#define IRQ_U300_NFIF2			46
+#define IRQ_U300_SYSCON_PLL_LOCK	47
+#define U300_NR_IRQS			48
+#endif
+
+#define NR_IRQS U300_NR_IRQS
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/memory.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/memory.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/memory.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/memory.h
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Memory virtual/physical mapping constants.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+
+#ifndef __MACH_MEMORY_H
+#define __MACH_MEMORY_H
+
+#ifdef CONFIG_MACH_U300_DUAL_RAM
+
+#define PHYS_OFFSET		UL(0x48000000)
+#define BOOT_PARAMS_OFFSET	(PHYS_OFFSET + 0x100)
+
+#else
+
+#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
+#define PHYS_OFFSET (0x28000000 + \
+	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
+	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
+#else
+#define PHYS_OFFSET (0x28000000 + \
+	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE +	\
+	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
+#endif
+#define BOOT_PARAMS_OFFSET (0x28000000 + \
+	    (CONFIG_MACH_U300_ACCESS_MEM_SIZE +		\
+	    (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100)
+#endif
+
+/*
+ * We enable a real big DMA buffer if need be.
+ */
+#define CONSISTENT_DMA_SIZE SZ_4M
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/platform.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/platform.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/platform.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/platform.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/platform.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Basic platform init and mapping functions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __ASSEMBLY__
+
+void u300_map_io(void);
+void u300_init_irq(void);
+void u300_init_devices(void);
+extern struct sys_timer u300_timer;
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/syscon.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/syscon.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/syscon.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/syscon.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,644 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/syscon.h
+ *
+ *
+ * Copyright (C) 2008 ST-Ericsson AB
+ *
+ * Author: Rickard Andersson <rickard.andersson@stericsson.com>
+ */
+
+#ifndef __MACH_SYSCON_H
+#define __MACH_SYSCON_H
+
+/*
+ * All register defines for SYSCON registers that concerns individual
+ * block clocks and reset lines are registered here. This is because
+ * we don't want any other file to try to fool around with this stuff.
+ */
+
+/* APP side SYSCON registers */
+/* TODO: this is incomplete. Add all from asic_syscon_map.h eventually. */
+/* CLK Control Register 16bit (R/W) */
+#define U300_SYSCON_CCR						(0x0000)
+#define U300_SYSCON_CCR_I2S1_USE_VCXO				(0x0040)
+#define U300_SYSCON_CCR_I2S0_USE_VCXO				(0x0020)
+#define U300_SYSCON_CCR_TURN_VCXO_ON				(0x0008)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK			(0x0007)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER		(0x04)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW			(0x03)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE		(0x02)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH			(0x01)
+#define U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST			(0x00)
+/* CLK Status Register 16bit (R/W) */
+#define U300_SYSCON_CSR						(0x0004)
+#define U300_SYSCON_CSR_PLL208_LOCK_IND				(0x0002)
+#define U300_SYSCON_CSR_PLL13_LOCK_IND				(0x0001)
+/* Reset lines for SLOW devices 16bit (R/W) */
+#define U300_SYSCON_RSR						(0x0014)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_RSR_PPM_RESET_EN				(0x0200)
+#endif
+#define U300_SYSCON_RSR_ACC_TMR_RESET_EN			(0x0100)
+#define U300_SYSCON_RSR_APP_TMR_RESET_EN			(0x0080)
+#define U300_SYSCON_RSR_RTC_RESET_EN				(0x0040)
+#define U300_SYSCON_RSR_KEYPAD_RESET_EN				(0x0020)
+#define U300_SYSCON_RSR_GPIO_RESET_EN				(0x0010)
+#define U300_SYSCON_RSR_EH_RESET_EN				(0x0008)
+#define U300_SYSCON_RSR_BTR_RESET_EN				(0x0004)
+#define U300_SYSCON_RSR_UART_RESET_EN				(0x0002)
+#define U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN			(0x0001)
+/* Reset lines for FAST devices 16bit (R/W) */
+#define U300_SYSCON_RFR						(0x0018)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_RFR_UART1_RESET_ENABLE			(0x0080)
+#endif
+#define U300_SYSCON_RFR_SPI_RESET_ENABLE			(0x0040)
+#define U300_SYSCON_RFR_MMC_RESET_ENABLE			(0x0020)
+#define U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE			(0x0010)
+#define U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE			(0x0008)
+#define U300_SYSCON_RFR_I2C1_RESET_ENABLE			(0x0004)
+#define U300_SYSCON_RFR_I2C0_RESET_ENABLE			(0x0002)
+#define U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE		(0x0001)
+/* Reset lines for the rest of the peripherals 16bit (R/W) */
+#define U300_SYSCON_RRR						(0x001c)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_RRR_CDS_RESET_EN				(0x4000)
+#define U300_SYSCON_RRR_ISP_RESET_EN				(0x2000)
+#endif
+#define U300_SYSCON_RRR_INTCON_RESET_EN				(0x1000)
+#define U300_SYSCON_RRR_MSPRO_RESET_EN				(0x0800)
+#define U300_SYSCON_RRR_XGAM_RESET_EN				(0x0100)
+#define U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN			(0x0080)
+#define U300_SYSCON_RRR_NANDIF_RESET_EN				(0x0040)
+#define U300_SYSCON_RRR_EMIF_RESET_EN				(0x0020)
+#define U300_SYSCON_RRR_DMAC_RESET_EN				(0x0010)
+#define U300_SYSCON_RRR_CPU_RESET_EN				(0x0008)
+#define U300_SYSCON_RRR_APEX_RESET_EN				(0x0004)
+#define U300_SYSCON_RRR_AHB_RESET_EN				(0x0002)
+#define U300_SYSCON_RRR_AAIF_RESET_EN				(0x0001)
+/* Clock enable for SLOW peripherals 16bit (R/W) */
+#define U300_SYSCON_CESR					(0x0020)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CESR_PPM_CLK_EN				(0x0200)
+#endif
+#define U300_SYSCON_CESR_ACC_TMR_CLK_EN				(0x0100)
+#define U300_SYSCON_CESR_APP_TMR_CLK_EN				(0x0080)
+#define U300_SYSCON_CESR_KEYPAD_CLK_EN				(0x0040)
+#define U300_SYSCON_CESR_GPIO_CLK_EN				(0x0010)
+#define U300_SYSCON_CESR_EH_CLK_EN				(0x0008)
+#define U300_SYSCON_CESR_BTR_CLK_EN				(0x0004)
+#define U300_SYSCON_CESR_UART_CLK_EN				(0x0002)
+#define U300_SYSCON_CESR_SLOW_BRIDGE_CLK_EN			(0x0001)
+/* Clock enable for FAST peripherals 16bit (R/W) */
+#define U300_SYSCON_CEFR					(0x0024)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CEFR_UART1_CLK_EN				(0x0200)
+#endif
+#define U300_SYSCON_CEFR_I2S1_CORE_CLK_EN			(0x0100)
+#define U300_SYSCON_CEFR_I2S0_CORE_CLK_EN			(0x0080)
+#define U300_SYSCON_CEFR_SPI_CLK_EN				(0x0040)
+#define U300_SYSCON_CEFR_MMC_CLK_EN				(0x0020)
+#define U300_SYSCON_CEFR_I2S1_CLK_EN    			(0x0010)
+#define U300_SYSCON_CEFR_I2S0_CLK_EN     			(0x0008)
+#define U300_SYSCON_CEFR_I2C1_CLK_EN     			(0x0004)
+#define U300_SYSCON_CEFR_I2C0_CLK_EN     			(0x0002)
+#define U300_SYSCON_CEFR_FAST_BRIDGE_CLK_EN			(0x0001)
+/* Clock enable for the rest of the peripherals 16bit (R/W) */
+#define U300_SYSCON_CERR					(0x0028)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CERR_CDS_CLK_EN				(0x2000)
+#define U300_SYSCON_CERR_ISP_CLK_EN				(0x1000)
+#endif
+#define U300_SYSCON_CERR_MSPRO_CLK_EN				(0x0800)
+#define U300_SYSCON_CERR_AHB_SUBSYS_BRIDGE_CLK_EN		(0x0400)
+#define U300_SYSCON_CERR_SEMI_CLK_EN				(0x0200)
+#define U300_SYSCON_CERR_XGAM_CLK_EN				(0x0100)
+#define U300_SYSCON_CERR_VIDEO_ENC_CLK_EN			(0x0080)
+#define U300_SYSCON_CERR_NANDIF_CLK_EN				(0x0040)
+#define U300_SYSCON_CERR_EMIF_CLK_EN				(0x0020)
+#define U300_SYSCON_CERR_DMAC_CLK_EN				(0x0010)
+#define U300_SYSCON_CERR_CPU_CLK_EN				(0x0008)
+#define U300_SYSCON_CERR_APEX_CLK_EN				(0x0004)
+#define U300_SYSCON_CERR_AHB_CLK_EN				(0x0002)
+#define U300_SYSCON_CERR_AAIF_CLK_EN				(0x0001)
+/* Single block clock enable 16bit (-/W) */
+#define U300_SYSCON_SBCER					(0x002c)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_SBCER_PPM_CLK_EN				(0x0009)
+#endif
+#define U300_SYSCON_SBCER_ACC_TMR_CLK_EN			(0x0008)
+#define U300_SYSCON_SBCER_APP_TMR_CLK_EN			(0x0007)
+#define U300_SYSCON_SBCER_KEYPAD_CLK_EN				(0x0006)
+#define U300_SYSCON_SBCER_GPIO_CLK_EN				(0x0004)
+#define U300_SYSCON_SBCER_EH_CLK_EN				(0x0003)
+#define U300_SYSCON_SBCER_BTR_CLK_EN				(0x0002)
+#define U300_SYSCON_SBCER_UART_CLK_EN				(0x0001)
+#define U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN			(0x0000)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_SBCER_UART1_CLK_EN				(0x0019)
+#endif
+#define U300_SYSCON_SBCER_I2S1_CORE_CLK_EN			(0x0018)
+#define U300_SYSCON_SBCER_I2S0_CORE_CLK_EN			(0x0017)
+#define U300_SYSCON_SBCER_SPI_CLK_EN				(0x0016)
+#define U300_SYSCON_SBCER_MMC_CLK_EN				(0x0015)
+#define U300_SYSCON_SBCER_I2S1_CLK_EN				(0x0014)
+#define U300_SYSCON_SBCER_I2S0_CLK_EN				(0x0013)
+#define U300_SYSCON_SBCER_I2C1_CLK_EN				(0x0012)
+#define U300_SYSCON_SBCER_I2C0_CLK_EN				(0x0011)
+#define U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN			(0x0010)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_SBCER_CDS_CLK_EN				(0x002D)
+#define U300_SYSCON_SBCER_ISP_CLK_EN				(0x002C)
+#endif
+#define U300_SYSCON_SBCER_MSPRO_CLK_EN				(0x002B)
+#define U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN		(0x002A)
+#define U300_SYSCON_SBCER_SEMI_CLK_EN				(0x0029)
+#define U300_SYSCON_SBCER_XGAM_CLK_EN				(0x0028)
+#define U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN			(0x0027)
+#define U300_SYSCON_SBCER_NANDIF_CLK_EN				(0x0026)
+#define U300_SYSCON_SBCER_EMIF_CLK_EN				(0x0025)
+#define U300_SYSCON_SBCER_DMAC_CLK_EN				(0x0024)
+#define U300_SYSCON_SBCER_CPU_CLK_EN				(0x0023)
+#define U300_SYSCON_SBCER_APEX_CLK_EN				(0x0022)
+#define U300_SYSCON_SBCER_AHB_CLK_EN				(0x0021)
+#define U300_SYSCON_SBCER_AAIF_CLK_EN				(0x0020)
+/* Single block clock disable 16bit (-/W) */
+#define U300_SYSCON_SBCDR					(0x0030)
+/* Same values as above for SBCER */
+/* Clock force SLOW peripherals 16bit (R/W) */
+#define U300_SYSCON_CFSR					(0x003c)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CFSR_PPM_CLK_FORCE_EN			(0x0200)
+#endif
+#define U300_SYSCON_CFSR_ACC_TMR_CLK_FORCE_EN			(0x0100)
+#define U300_SYSCON_CFSR_APP_TMR_CLK_FORCE_EN			(0x0080)
+#define U300_SYSCON_CFSR_KEYPAD_CLK_FORCE_EN			(0x0020)
+#define U300_SYSCON_CFSR_GPIO_CLK_FORCE_EN			(0x0010)
+#define U300_SYSCON_CFSR_EH_CLK_FORCE_EN			(0x0008)
+#define U300_SYSCON_CFSR_BTR_CLK_FORCE_EN			(0x0004)
+#define U300_SYSCON_CFSR_UART_CLK_FORCE_EN			(0x0002)
+#define U300_SYSCON_CFSR_SLOW_BRIDGE_CLK_FORCE_EN		(0x0001)
+/* Clock force FAST peripherals 16bit (R/W) */
+#define U300_SYSCON_CFFR					(0x40)
+/* Values not defined. Define if you want to use them. */
+/* Clock force the rest of the peripherals 16bit (R/W) */
+#define U300_SYSCON_CFRR					(0x44)
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SYSCON_CFRR_CDS_CLK_FORCE_EN			(0x2000)
+#define U300_SYSCON_CFRR_ISP_CLK_FORCE_EN			(0x1000)
+#endif
+#define U300_SYSCON_CFRR_MSPRO_CLK_FORCE_EN			(0x0800)
+#define U300_SYSCON_CFRR_AHB_SUBSYS_BRIDGE_CLK_FORCE_EN		(0x0400)
+#define U300_SYSCON_CFRR_SEMI_CLK_FORCE_EN			(0x0200)
+#define U300_SYSCON_CFRR_XGAM_CLK_FORCE_EN			(0x0100)
+#define U300_SYSCON_CFRR_VIDEO_ENC_CLK_FORCE_EN			(0x0080)
+#define U300_SYSCON_CFRR_NANDIF_CLK_FORCE_EN			(0x0040)
+#define U300_SYSCON_CFRR_EMIF_CLK_FORCE_EN			(0x0020)
+#define U300_SYSCON_CFRR_DMAC_CLK_FORCE_EN			(0x0010)
+#define U300_SYSCON_CFRR_CPU_CLK_FORCE_EN			(0x0008)
+#define U300_SYSCON_CFRR_APEX_CLK_FORCE_EN			(0x0004)
+#define U300_SYSCON_CFRR_AHB_CLK_FORCE_EN			(0x0002)
+#define U300_SYSCON_CFRR_AAIF_CLK_FORCE_EN			(0x0001)
+/* PLL208 Frequency Control 16bit (R/W) */
+#define U300_SYSCON_PFCR					(0x48)
+#define U300_SYSCON_PFCR_DPLL_MULT_NUM				(0x000F)
+/* Power Management Control 16bit (R/W) */
+#define U300_SYSCON_PMCR					(0x50)
+#define U300_SYSCON_PMCR_DCON_ENABLE				(0x0002)
+#define U300_SYSCON_PMCR_PWR_MGNT_ENABLE			(0x0001)
+/*
+ * All other clocking registers moved to clock.c!
+ */
+/* Reset Out 16bit (R/W) */
+#define U300_SYSCON_RCR						(0x6c)
+#define U300_SYSCON_RCR_RESOUT0_RST_N_DISABLE			(0x0001)
+/* EMIF Slew Rate Control 16bit (R/W) */
+#define U300_SYSCON_SRCLR					(0x70)
+#define U300_SYSCON_SRCLR_MASK					(0x03FF)
+#define U300_SYSCON_SRCLR_VALUE					(0x03FF)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_B			(0x0200)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_A			(0x0100)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_B			(0x0080)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_A			(0x0040)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_B			(0x0020)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_A			(0x0010)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_B			(0x0008)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_A			(0x0004)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_B			(0x0002)
+#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_A			(0x0001)
+/* EMIF Clock Control Register 16bit (R/W) */
+#define U300_SYSCON_ECCR					(0x0078)
+#define U300_SYSCON_ECCR_MASK					(0x000F)
+#define U300_SYSCON_ECCR_EMIF_1_STATIC_CLK_EN_N_DISABLE		(0x0008)
+#define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE	(0x0004)
+#define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE		(0x0002)
+#define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE		(0x0001)
+/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
+#define U300_SYSCON_PMC1LR					(0x007C)
+#define U300_SYSCON_PMC1LR_MASK					(0xFFFF)
+#define U300_SYSCON_PMC1LR_CDI_MASK				(0xC000)
+#define U300_SYSCON_PMC1LR_CDI_CDI				(0x0000)
+#define U300_SYSCON_PMC1LR_CDI_EMIF				(0x4000)
+#define U300_SYSCON_PMC1LR_CDI_GPIO				(0x8000)
+#define U300_SYSCON_PMC1LR_CDI_WCDMA				(0xC000)
+#define U300_SYSCON_PMC1LR_PDI_MASK				(0x3000)
+#define U300_SYSCON_PMC1LR_PDI_PDI				(0x0000)
+#define U300_SYSCON_PMC1LR_PDI_EGG				(0x1000)
+#define U300_SYSCON_PMC1LR_PDI_WCDMA				(0x3000)
+#define U300_SYSCON_PMC1LR_MMCSD_MASK				(0x0C00)
+#define U300_SYSCON_PMC1LR_MMCSD_MMCSD				(0x0000)
+#define U300_SYSCON_PMC1LR_MMCSD_MSPRO				(0x0400)
+#define U300_SYSCON_PMC1LR_MMCSD_DSP				(0x0800)
+#define U300_SYSCON_PMC1LR_MMCSD_WCDMA				(0x0C00)
+#define U300_SYSCON_PMC1LR_ETM_MASK				(0x0300)
+#define U300_SYSCON_PMC1LR_ETM_ACC				(0x0000)
+#define U300_SYSCON_PMC1LR_ETM_APP				(0x0100)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK			(0x00C0)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC			(0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF			(0x0040)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM			(0x0080)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB		(0x00C0)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK			(0x0030)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC			(0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF			(0x0010)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM			(0x0020)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI			(0x0030)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK			(0x000C)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC			(0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF			(0x0004)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM			(0x0008)
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI			(0x000C)
+#define U300_SYSCON_PMC1LR_EMIF_1_MASK				(0x0003)
+#define U300_SYSCON_PMC1LR_EMIF_1_STATIC			(0x0000)
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0			(0x0001)
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1			(0x0002)
+#define U300_SYSCON_PMC1LR_EMIF_1				(0x0003)
+/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
+#define U300_SYSCON_PMC1HR					(0x007E)
+#define U300_SYSCON_PMC1HR_MASK					(0xFFFF)
+#define U300_SYSCON_PMC1HR_MISC_2_MASK				(0xC000)
+#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO			(0x0000)
+#define U300_SYSCON_PMC1HR_MISC_2_MSPRO				(0x4000)
+#define U300_SYSCON_PMC1HR_MISC_2_DSP				(0x8000)
+#define U300_SYSCON_PMC1HR_MISC_2_AAIF				(0xC000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK			(0x3000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO			(0x0000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF			(0x1000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP			(0x2000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF			(0x3000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK			(0x0C00)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO			(0x0000)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC			(0x0400)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP			(0x0800)
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF			(0x0C00)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK			(0x0300)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO		(0x0000)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI			(0x0100)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF			(0x0300)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK			(0x00C0)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO		(0x0000)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI			(0x0040)
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF			(0x00C0)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK			(0x0030)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO			(0x0000)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI			(0x0010)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP			(0x0020)
+#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF			(0x0030)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK			(0x000C)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO			(0x0000)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0			(0x0004)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS			(0x0008)
+#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF			(0x000C)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK			(0x0003)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO			(0x0000)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0			(0x0001)
+#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF			(0x0003)
+/* Step one for killing the applications system 16bit (-/W) */
+#define U300_SYSCON_KA1R					(0x0080)
+#define U300_SYSCON_KA1R_MASK					(0xFFFF)
+#define U300_SYSCON_KA1R_VALUE					(0xFFFF)
+/* Step two for killing the application system 16bit (-/W) */
+#define U300_SYSCON_KA2R					(0x0084)
+#define U300_SYSCON_KA2R_MASK					(0xFFFF)
+#define U300_SYSCON_KA2R_VALUE					(0xFFFF)
+/* MMC/MSPRO frequency divider register 0 16bit (R/W) */
+#define U300_SYSCON_MMF0R					(0x90)
+#define U300_SYSCON_MMF0R_MASK					(0x00FF)
+#define U300_SYSCON_MMF0R_FREQ_0_HIGH_MASK			(0x00F0)
+#define U300_SYSCON_MMF0R_FREQ_0_LOW_MASK			(0x000F)
+/* MMC/MSPRO frequency divider register 1 16bit (R/W) */
+#define U300_SYSCON_MMF1R					(0x94)
+#define U300_SYSCON_MMF1R_MASK					(0x00FF)
+#define U300_SYSCON_MMF1R_FREQ_1_HIGH_MASK			(0x00F0)
+#define U300_SYSCON_MMF1R_FREQ_1_LOW_MASK			(0x000F)
+/* AAIF control register 16 bit (R/W) */
+#define U300_SYSCON_AAIFCR					(0x98)
+#define U300_SYSCON_AAIFCR_MASK					(0x0003)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_MASK			(0x0003)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_FUNCTIONAL			(0x0000)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_MONITORING			(0x0001)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_ACC_TO_EXT			(0x0002)
+#define U300_SYSCON_AAIFCR_AASW_CTRL_APP_TO_EXT			(0x0003)
+/* Clock control for the MMC and MSPRO blocks 16bit (R/W) */
+#define U300_SYSCON_MMCR					(0x9C)
+#define U300_SYSCON_MMCR_MASK					(0x0003)
+#define U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE			(0x0002)
+#define U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE			(0x0001)
+
+/* TODO: More SYSCON registers missing */
+#define U300_SYSCON_PMC3R					(0x10c)
+#define U300_SYSCON_PMC3R_APP_MISC_11_MASK			(0xc000)
+#define U300_SYSCON_PMC3R_APP_MISC_11_SPI			(0x4000)
+#define U300_SYSCON_PMC3R_APP_MISC_10_MASK			(0x3000)
+#define U300_SYSCON_PMC3R_APP_MISC_10_SPI			(0x1000)
+/* TODO: Missing other configs, I just added the SPI stuff */
+
+/* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */
+#define U300_SYSCON_S0CCR					(0x120)
+#define U300_SYSCON_S0CCR_FIELD_MASK				(0x43FF)
+#define U300_SYSCON_S0CCR_CLOCK_REQ				(0x4000)
+#define U300_SYSCON_S0CCR_CLOCK_INV				(0x0200)
+#define U300_SYSCON_S0CCR_CLOCK_FREQ_MASK			(0x01E0)
+#define U300_SYSCON_S0CCR_CLOCK_SELECT_MASK			(0x001E)
+#define U300_SYSCON_S0CCR_CLOCK_ENABLE				(0x0001)
+#define U300_SYSCON_S0CCR_SEL_MCLK				(0x8<<1)
+#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK			(0xA<<1)
+#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK			(0xC<<1)
+#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK			(0xD<<1)
+#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK			(0xE<<1)
+#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK			(0x0<<1)
+#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK			(0x2<<1)
+#define U300_SYSCON_S0CCR_SEL_RTC_CLK				(0x4<<1)
+#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK			(0x6<<1)
+/* SYS_1_CLK_CONTROL second clock control 16 bit (R/W) */
+#define U300_SYSCON_S1CCR					(0x124)
+#define U300_SYSCON_S1CCR_FIELD_MASK				(0x43FF)
+#define U300_SYSCON_S1CCR_CLOCK_REQ				(0x4000)
+#define U300_SYSCON_S1CCR_CLOCK_INV				(0x0200)
+#define U300_SYSCON_S1CCR_CLOCK_FREQ_MASK			(0x01E0)
+#define U300_SYSCON_S1CCR_CLOCK_SELECT_MASK			(0x001E)
+#define U300_SYSCON_S1CCR_CLOCK_ENABLE				(0x0001)
+#define U300_SYSCON_S1CCR_SEL_MCLK				(0x8<<1)
+#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK			(0xA<<1)
+#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK			(0xC<<1)
+#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK			(0xD<<1)
+#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK			(0xE<<1)
+#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK			(0x0<<1)
+#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK			(0x2<<1)
+#define U300_SYSCON_S1CCR_SEL_RTC_CLK				(0x4<<1)
+#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK			(0x6<<1)
+/* SYS_2_CLK_CONTROL third clock contol 16 bit (R/W) */
+#define U300_SYSCON_S2CCR					(0x128)
+#define U300_SYSCON_S2CCR_FIELD_MASK				(0xC3FF)
+#define U300_SYSCON_S2CCR_CLK_STEAL				(0x8000)
+#define U300_SYSCON_S2CCR_CLOCK_REQ				(0x4000)
+#define U300_SYSCON_S2CCR_CLOCK_INV				(0x0200)
+#define U300_SYSCON_S2CCR_CLOCK_FREQ_MASK			(0x01E0)
+#define U300_SYSCON_S2CCR_CLOCK_SELECT_MASK			(0x001E)
+#define U300_SYSCON_S2CCR_CLOCK_ENABLE				(0x0001)
+#define U300_SYSCON_S2CCR_SEL_MCLK				(0x8<<1)
+#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK			(0xA<<1)
+#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK			(0xC<<1)
+#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK			(0xD<<1)
+#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK			(0xE<<1)
+#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK			(0x0<<1)
+#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK			(0x2<<1)
+#define U300_SYSCON_S2CCR_SEL_RTC_CLK				(0x4<<1)
+#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK			(0x6<<1)
+/* SYS_MISC_CONTROL, miscellaneous 16bit (R/W) */
+#define U300_SYSCON_MCR						(0x12c)
+#define U300_SYSCON_MCR_FIELD_MASK				(0x00FF)
+#define U300_SYSCON_MCR_PMGEN_CR_4_MASK				(0x00C0)
+#define U300_SYSCON_MCR_PMGEN_CR_4_GPIO				(0x0000)
+#define U300_SYSCON_MCR_PMGEN_CR_4_SPI				(0x0040)
+#define U300_SYSCON_MCR_PMGEN_CR_4_AAIF				(0x00C0)
+#define U300_SYSCON_MCR_PMGEN_CR_2_MASK				(0x0030)
+#define U300_SYSCON_MCR_PMGEN_CR_2_GPIO				(0x0000)
+#define U300_SYSCON_MCR_PMGEN_CR_2_EMIF_1_STATIC		(0x0010)
+#define U300_SYSCON_MCR_PMGEN_CR_2_DSP				(0x0020)
+#define U300_SYSCON_MCR_PMGEN_CR_2_AAIF				(0x0030)
+#define U300_SYSCON_MCR_PMGEN_CR_0_MASK				(0x000C)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M1		(0x0000)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M2		(0x0004)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M3		(0x0008)
+#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_0_SDRAM			(0x000C)
+#define U300_SYSCON_MCR_PM1G_MODE_ENABLE			(0x0002)
+#define U300_SYSCON_MCR_PMTG5_MODE_ENABLE			(0x0001)
+/* Clock activity observability register 0 */
+#define U300_SYSCON_C0OAR					(0x140)
+#define U300_SYSCON_C0OAR_MASK					(0xFFFF)
+#define U300_SYSCON_C0OAR_VALUE					(0xFFFF)
+#define U300_SYSCON_C0OAR_BT_H_CLK				(0x8000)
+#define U300_SYSCON_C0OAR_ASPB_P_CLK				(0x4000)
+#define U300_SYSCON_C0OAR_APP_SEMI_H_CLK			(0x2000)
+#define U300_SYSCON_C0OAR_APP_SEMI_CLK				(0x1000)
+#define U300_SYSCON_C0OAR_APP_MMC_MSPRO_CLK			(0x0800)
+#define U300_SYSCON_C0OAR_APP_I2S1_CLK				(0x0400)
+#define U300_SYSCON_C0OAR_APP_I2S0_CLK				(0x0200)
+#define U300_SYSCON_C0OAR_APP_CPU_CLK				(0x0100)
+#define U300_SYSCON_C0OAR_APP_52_CLK				(0x0080)
+#define U300_SYSCON_C0OAR_APP_208_CLK				(0x0040)
+#define U300_SYSCON_C0OAR_APP_104_CLK				(0x0020)
+#define U300_SYSCON_C0OAR_APEX_CLK				(0x0010)
+#define U300_SYSCON_C0OAR_AHPB_M_H_CLK				(0x0008)
+#define U300_SYSCON_C0OAR_AHB_CLK				(0x0004)
+#define U300_SYSCON_C0OAR_AFPB_P_CLK				(0x0002)
+#define U300_SYSCON_C0OAR_AAIF_CLK				(0x0001)
+/* Clock activity observability register 1 */
+#define U300_SYSCON_C1OAR					(0x144)
+#define U300_SYSCON_C1OAR_MASK					(0x3FFE)
+#define U300_SYSCON_C1OAR_VALUE					(0x3FFE)
+#define U300_SYSCON_C1OAR_NFIF_F_CLK				(0x2000)
+#define U300_SYSCON_C1OAR_MSPRO_CLK				(0x1000)
+#define U300_SYSCON_C1OAR_MMC_P_CLK				(0x0800)
+#define U300_SYSCON_C1OAR_MMC_CLK				(0x0400)
+#define U300_SYSCON_C1OAR_KP_P_CLK				(0x0200)
+#define U300_SYSCON_C1OAR_I2C1_P_CLK				(0x0100)
+#define U300_SYSCON_C1OAR_I2C0_P_CLK				(0x0080)
+#define U300_SYSCON_C1OAR_GPIO_CLK				(0x0040)
+#define U300_SYSCON_C1OAR_EMIF_MPMC_CLK				(0x0020)
+#define U300_SYSCON_C1OAR_EMIF_H_CLK				(0x0010)
+#define U300_SYSCON_C1OAR_EVHIST_CLK				(0x0008)
+#define U300_SYSCON_C1OAR_PPM_CLK				(0x0004)
+#define U300_SYSCON_C1OAR_DMA_CLK				(0x0002)
+/* Clock activity observability register 2 */
+#define U300_SYSCON_C2OAR					(0x148)
+#define U300_SYSCON_C2OAR_MASK					(0x0FFF)
+#define U300_SYSCON_C2OAR_VALUE					(0x0FFF)
+#define U300_SYSCON_C2OAR_XGAM_CDI_CLK				(0x0800)
+#define U300_SYSCON_C2OAR_XGAM_CLK				(0x0400)
+#define U300_SYSCON_C2OAR_VC_H_CLK				(0x0200)
+#define U300_SYSCON_C2OAR_VC_CLK				(0x0100)
+#define U300_SYSCON_C2OAR_UA_P_CLK				(0x0080)
+#define U300_SYSCON_C2OAR_TMR1_CLK				(0x0040)
+#define U300_SYSCON_C2OAR_TMR0_CLK				(0x0020)
+#define U300_SYSCON_C2OAR_SPI_P_CLK				(0x0010)
+#define U300_SYSCON_C2OAR_PCM_I2S1_CORE_CLK			(0x0008)
+#define U300_SYSCON_C2OAR_PCM_I2S1_CLK				(0x0004)
+#define U300_SYSCON_C2OAR_PCM_I2S0_CORE_CLK			(0x0002)
+#define U300_SYSCON_C2OAR_PCM_I2S0_CLK				(0x0001)
+
+/* Chip ID register 16bit (R/-) */
+#define U300_SYSCON_CIDR					(0x400)
+/* Video IRQ clear 16bit (R/W) */
+#define U300_SYSCON_VICR					(0x404)
+#define U300_SYSCON_VICR_VIDEO1_IRQ_CLEAR_ENABLE		(0x0002)
+#define U300_SYSCON_VICR_VIDEO0_IRQ_CLEAR_ENABLE		(0x0001)
+/* SMCR */
+#define U300_SYSCON_SMCR					(0x4d0)
+#define U300_SYSCON_SMCR_FIELD_MASK				(0x000e)
+#define U300_SYSCON_SMCR_SEMI_SREFACK_IND			(0x0008)
+#define U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE			(0x0004)
+#define U300_SYSCON_SMCR_SEMI_EXT_BOOT_MODE_ENABLE		(0x0002)
+/* CPU_SW_DBGEN Software Debug Enable 16bit (R/W) */
+#define U300_SYSCON_CSDR					(0x4f0)
+#define U300_SYSCON_CSDR_SW_DEBUG_ENABLE			(0x0001)
+/* PRINT_CONTROL Print Control 16bit (R/-) */
+#define U300_SYSCON_PCR						(0x4f8)
+#define U300_SYSCON_PCR_SERV_IND				(0x0001)
+/* BOOT_CONTROL 16bit (R/-) */
+#define U300_SYSCON_BCR						(0x4fc)
+#define U300_SYSCON_BCR_ACC_CPU_SUBSYS_VINITHI_IND		(0x0400)
+#define U300_SYSCON_BCR_APP_CPU_SUBSYS_VINITHI_IND		(0x0200)
+#define U300_SYSCON_BCR_EXTRA_BOOT_OPTION_MASK			(0x01FC)
+#define U300_SYSCON_BCR_APP_BOOT_SERV_MASK			(0x0003)
+
+
+/* CPU clock defines */
+/**
+ * CPU high frequency in MHz
+ */
+#define SYSCON_CPU_CLOCK_HIGH    208
+/**
+ * CPU medium frequency in MHz
+ */
+#define SYSCON_CPU_CLOCK_MEDIUM  104
+/**
+ * CPU low frequency in MHz
+ */
+#define SYSCON_CPU_CLOCK_LOW      13
+
+/* EMIF clock defines */
+/**
+ * EMIF high frequency in MHz
+ */
+#define SYSCON_EMIF_CLOCK_HIGH   104
+/**
+ * EMIF medium frequency in MHz
+ */
+#define SYSCON_EMIF_CLOCK_MEDIUM 104
+/**
+ * EMIF low frequency in MHz
+ */
+#define SYSCON_EMIF_CLOCK_LOW     13
+
+/* AHB clock defines */
+/**
+ * AHB high frequency in MHz
+ */
+#define SYSCON_AHB_CLOCK_HIGH     52
+/**
+ * AHB medium frequency in MHz
+ */
+#define SYSCON_AHB_CLOCK_MEDIUM   52
+/**
+ * AHB low frequency in MHz
+ */
+#define SYSCON_AHB_CLOCK_LOW       7  /* i.e 13/2=6.5MHz */
+
+enum syscon_busmaster {
+  SYSCON_BM_DMAC,
+  SYSCON_BM_XGAM,
+  SYSCON_BM_VIDEO_ENC
+};
+
+/*
+ * Note that this array must match the order of the array "clk_reg"
+ * in syscon.c
+ */
+enum syscon_clk {
+  SYSCON_CLKCONTROL_SLOW_BRIDGE,
+  SYSCON_CLKCONTROL_UART,
+  SYSCON_CLKCONTROL_BTR,
+  SYSCON_CLKCONTROL_EH,
+  SYSCON_CLKCONTROL_GPIO,
+  SYSCON_CLKCONTROL_KEYPAD,
+  SYSCON_CLKCONTROL_APP_TIMER,
+  SYSCON_CLKCONTROL_ACC_TIMER,
+  SYSCON_CLKCONTROL_FAST_BRIDGE,
+  SYSCON_CLKCONTROL_I2C0,
+  SYSCON_CLKCONTROL_I2C1,
+  SYSCON_CLKCONTROL_I2S0,
+  SYSCON_CLKCONTROL_I2S1,
+  SYSCON_CLKCONTROL_MMC,
+  SYSCON_CLKCONTROL_SPI,
+  SYSCON_CLKCONTROL_I2S0_CORE,
+  SYSCON_CLKCONTROL_I2S1_CORE,
+  SYSCON_CLKCONTROL_AAIF,
+  SYSCON_CLKCONTROL_AHB,
+  SYSCON_CLKCONTROL_APEX,
+  SYSCON_CLKCONTROL_CPU,
+  SYSCON_CLKCONTROL_DMA,
+  SYSCON_CLKCONTROL_EMIF,
+  SYSCON_CLKCONTROL_NAND_IF,
+  SYSCON_CLKCONTROL_VIDEO_ENC,
+  SYSCON_CLKCONTROL_XGAM,
+  SYSCON_CLKCONTROL_SEMI,
+  SYSCON_CLKCONTROL_AHB_SUBSYS,
+  SYSCON_CLKCONTROL_MSPRO
+};
+
+enum syscon_sysclk_mode {
+  SYSCON_SYSCLK_DISABLED,
+  SYSCON_SYSCLK_M_CLK,
+  SYSCON_SYSCLK_ACC_FSM,
+  SYSCON_SYSCLK_PLL60_48,
+  SYSCON_SYSCLK_PLL60_60,
+  SYSCON_SYSCLK_ACC_PLL208,
+  SYSCON_SYSCLK_APP_PLL13,
+  SYSCON_SYSCLK_APP_FSM,
+  SYSCON_SYSCLK_RTC,
+  SYSCON_SYSCLK_APP_PLL208
+};
+
+enum syscon_sysclk_req {
+  SYSCON_SYSCLKREQ_DISABLED,
+  SYSCON_SYSCLKREQ_ACTIVE_LOW
+};
+
+enum syscon_clk_mode {
+  SYSCON_CLKMODE_OFF,
+  SYSCON_CLKMODE_DEFAULT,
+  SYSCON_CLKMODE_LOW,
+  SYSCON_CLKMODE_MEDIUM,
+  SYSCON_CLKMODE_HIGH,
+  SYSCON_CLKMODE_PERMANENT,
+  SYSCON_CLKMODE_ON,
+};
+
+enum syscon_call_mode {
+  SYSCON_CLKCALL_NOWAIT,
+  SYSCON_CLKCALL_WAIT,
+};
+
+int syscon_dc_on(bool keep_power_on);
+int syscon_set_busmaster_active_state(enum syscon_busmaster busmaster,
+				      bool active);
+bool syscon_get_busmaster_active_state(void);
+int syscon_set_sleep_mask(enum syscon_clk,
+			  bool sleep_ctrl);
+int syscon_config_sysclk(u32 sysclk,
+			 enum syscon_sysclk_mode sysclkmode,
+			 bool inverse,
+			 u32 divisor,
+			 enum syscon_sysclk_req sysclkreq);
+bool syscon_can_turn_off_semi_clock(void);
+
+/* This function is restricted to core.c */
+int syscon_request_normal_power(bool req);
+
+/* This function is restricted to be used by platform_speed.c */
+int syscon_speed_request(enum syscon_call_mode wait_mode,
+			 enum syscon_clk_mode req_clk_mode);
+#endif /* __MACH_SYSCON_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/system.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/system.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/system.h
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * System shutdown and reset functions.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/hardware/vic.h>
+#include <asm/irq.h>
+
+/* Forward declare this function from the watchdog */
+void coh901327_watchdog_reset(void);
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static void arch_reset(char mode, const char *cmd)
+{
+	switch (mode) {
+	case 's':
+	case 'h':
+		printk(KERN_CRIT "RESET: shutting down/rebooting system\n");
+		/* Disable interrupts */
+		local_irq_disable();
+#ifdef CONFIG_COH901327_WATCHDOG
+		coh901327_watchdog_reset();
+#endif
+		break;
+	default:
+		/* Do nothing */
+		break;
+	}
+	/* Wait for system do die/reset. */
+	while (1);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/timex.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/timex.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/timex.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,17 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/timex.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Platform tick rate definition.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#ifndef __MACH_TIMEX_H
+#define __MACH_TIMEX_H
+
+/* This is for the APP OS GP1 (General Purpose 1) timer */
+#define CLOCK_TICK_RATE		1000000
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/u300-regs.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/u300-regs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/u300-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/u300-regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/u300-regs.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Basic register address definitions in physical memory and
+ * some block defintions for core devices like the timer.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#ifndef __MACH_U300_REGS_H
+#define __MACH_U300_REGS_H
+
+/*
+ * These are the large blocks of memory allocated for I/O.
+ * the defines are used for setting up the I/O memory mapping.
+ */
+
+/* NAND Flash CS0 */
+#define U300_NAND_CS0_PHYS_BASE		0x80000000
+#define U300_NAND_CS0_VIRT_BASE		0xff040000
+
+/* NFIF */
+#define U300_NAND_IF_PHYS_BASE		0x9f800000
+#define U300_NAND_IF_VIRT_BASE		0xff030000
+
+/* AHB Peripherals */
+#define U300_AHB_PER_PHYS_BASE		0xa0000000
+#define U300_AHB_PER_VIRT_BASE		0xff010000
+
+/* FAST Peripherals */
+#define U300_FAST_PER_PHYS_BASE		0xc0000000
+#define U300_FAST_PER_VIRT_BASE		0xff020000
+
+/* SLOW Peripherals */
+#define U300_SLOW_PER_PHYS_BASE		0xc0010000
+#define U300_SLOW_PER_VIRT_BASE		0xff000000
+
+/* Boot ROM */
+#define U300_BOOTROM_PHYS_BASE		0xffff0000
+#define U300_BOOTROM_VIRT_BASE		0xffff0000
+
+/* SEMI config base */
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_SEMI_CONFIG_BASE		0x2FFE0000
+#else
+#define U300_SEMI_CONFIG_BASE		0x30000000
+#endif
+
+/*
+ * All the following peripherals are specified at their PHYSICAL address,
+ * so if you need to access them (in the kernel), you MUST use the macros
+ * defined in <asm/io.h> to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST()
+ * etc.
+ */
+
+/*
+ * AHB peripherals
+ */
+
+/* AHB Peripherals Bridge Controller */
+#define U300_AHB_BRIDGE_BASE		(U300_AHB_PER_PHYS_BASE+0x0000)
+
+/* Vectored Interrupt Controller 0, servicing 32 interrupts */
+#define U300_INTCON0_BASE		(U300_AHB_PER_PHYS_BASE+0x1000)
+#define U300_INTCON0_VBASE		(U300_AHB_PER_VIRT_BASE+0x1000)
+
+/* Vectored Interrupt Controller 1, servicing 32 interrupts */
+#define U300_INTCON1_BASE		(U300_AHB_PER_PHYS_BASE+0x2000)
+#define U300_INTCON1_VBASE		(U300_AHB_PER_VIRT_BASE+0x2000)
+
+/* Memory Stick Pro (MSPRO) controller */
+#define U300_MSPRO_BASE			(U300_AHB_PER_PHYS_BASE+0x3000)
+
+/* EMIF Configuration Area */
+#define U300_EMIF_CFG_BASE		(U300_AHB_PER_PHYS_BASE+0x4000)
+
+
+/*
+ * FAST peripherals
+ */
+
+/* FAST bridge control */
+#define U300_FAST_BRIDGE_BASE		(U300_FAST_PER_PHYS_BASE+0x0000)
+
+/* MMC/SD controller */
+#define U300_MMCSD_BASE			(U300_FAST_PER_PHYS_BASE+0x1000)
+
+/* PCM I2S0 controller */
+#define U300_PCM_I2S0_BASE		(U300_FAST_PER_PHYS_BASE+0x2000)
+
+/* PCM I2S1 controller */
+#define U300_PCM_I2S1_BASE		(U300_FAST_PER_PHYS_BASE+0x3000)
+
+/* I2C0 controller */
+#define U300_I2C0_BASE			(U300_FAST_PER_PHYS_BASE+0x4000)
+
+/* I2C1 controller */
+#define U300_I2C1_BASE			(U300_FAST_PER_PHYS_BASE+0x5000)
+
+/* SPI controller */
+#define U300_SPI_BASE			(U300_FAST_PER_PHYS_BASE+0x6000)
+
+#ifdef CONFIG_MACH_U300_BS335
+/* Fast UART1 on U335 only */
+#define U300_UART1_BASE			(U300_SLOW_PER_PHYS_BASE+0x7000)
+#endif
+
+/*
+ * SLOW peripherals
+ */
+
+/* SLOW bridge control */
+#define U300_SLOW_BRIDGE_BASE		(U300_SLOW_PER_PHYS_BASE)
+
+/* SYSCON */
+#define U300_SYSCON_BASE		(U300_SLOW_PER_PHYS_BASE+0x1000)
+#define U300_SYSCON_VBASE		(U300_SLOW_PER_VIRT_BASE+0x1000)
+
+/* Watchdog */
+#define U300_WDOG_BASE			(U300_SLOW_PER_PHYS_BASE+0x2000)
+
+/* UART0 */
+#define U300_UART0_BASE			(U300_SLOW_PER_PHYS_BASE+0x3000)
+
+/* APP side special timer */
+#define U300_TIMER_APP_BASE		(U300_SLOW_PER_PHYS_BASE+0x4000)
+#define U300_TIMER_APP_VBASE		(U300_SLOW_PER_VIRT_BASE+0x4000)
+
+/* Keypad */
+#define U300_KEYPAD_BASE		(U300_SLOW_PER_PHYS_BASE+0x5000)
+
+/* GPIO */
+#define U300_GPIO_BASE			(U300_SLOW_PER_PHYS_BASE+0x6000)
+
+/* RTC */
+#define U300_RTC_BASE			(U300_SLOW_PER_PHYS_BASE+0x7000)
+
+/* Bus tracer */
+#define U300_BUSTR_BASE			(U300_SLOW_PER_PHYS_BASE+0x8000)
+
+/* Event handler (hardware queue) */
+#define U300_EVHIST_BASE		(U300_SLOW_PER_PHYS_BASE+0x9000)
+
+/* Genric Timer */
+#define U300_TIMER_BASE			(U300_SLOW_PER_PHYS_BASE+0xa000)
+
+/* PPM */
+#define U300_PPM_BASE			(U300_SLOW_PER_PHYS_BASE+0xb000)
+
+
+/*
+ * REST peripherals
+ */
+
+/* ISP (image signal processor) is only available in U335 */
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_ISP_BASE			(0xA0008000)
+#endif
+
+/* DMA Controller base */
+#define U300_DMAC_BASE			(0xC0020000)
+
+/* MSL Base */
+#define U300_MSL_BASE			(0xc0022000)
+
+/* APEX Base */
+#define U300_APEX_BASE			(0xc0030000)
+
+/* Video Encoder Base */
+#ifdef CONFIG_MACH_U300_BS335
+#define U300_VIDEOENC_BASE		(0xc0080000)
+#else
+#define U300_VIDEOENC_BASE		(0xc0040000)
+#endif
+
+/* XGAM Base */
+#define U300_XGAM_BASE			(0xd0000000)
+
+/*
+ * Virtual accessor macros for static devices
+ */
+
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/uncompress.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/uncompress.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/uncompress.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * arch/arm/mach-u300/include/mach/uncompress.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * 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
+ */
+#define AMBA_UART_DR	(*(volatile unsigned char *)0xc0013000)
+#define AMBA_UART_LCRH	(*(volatile unsigned char *)0xc001302C)
+#define AMBA_UART_CR	(*(volatile unsigned char *)0xc0013030)
+#define AMBA_UART_FR	(*(volatile unsigned char *)0xc0013018)
+
+/*
+ * This does not append a newline
+ */
+static inline void putc(int c)
+{
+	while (AMBA_UART_FR & (1 << 5))
+		barrier();
+
+	AMBA_UART_DR = c;
+}
+
+static inline void flush(void)
+{
+	while (AMBA_UART_FR & (1 << 3))
+		barrier();
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/vmalloc.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/vmalloc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/include/mach/vmalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,12 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/vmalloc.h
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Virtual memory allocations
+ * End must be above the I/O registers and on an even 2MiB boundary.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#define VMALLOC_END	0xfe800000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/Kconfig linux-libre-2.6.31-gnu/arch/arm/mach-u300/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,105 @@
+if ARCH_U300
+
+menu "ST-Ericsson AB U300/U330/U335/U365 Platform"
+
+comment "ST-Ericsson Mobile Platform Products"
+
+config MACH_U300
+	bool "U300"
+
+comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
+
+choice
+	prompt "U300/U330/U335/U365 system type"
+	default MACH_U300_BS2X
+	---help---
+	You need to select the target system, i.e. the
+	U300/U330/U335/U365 board that you want to compile your kernel
+	for.
+
+config MACH_U300_BS2X
+	bool "S26/S26/B25/B26 Test Products"
+	depends on MACH_U300
+	help
+		Select this if you're developing on the
+		S26/S25 test products. (Also works on
+		B26/B25 big boards.)
+
+config MACH_U300_BS330
+	bool "S330/B330 Test Products"
+	depends on MACH_U300
+	help
+		Select this if you're developing on the
+		S330/B330 test products.
+
+config MACH_U300_BS335
+	bool "S335/B335 Test Products"
+	depends on MACH_U300
+	help
+		Select this if you're developing on the
+		S335/B335 test products.
+
+config MACH_U300_BS365
+	bool "S365/B365 Test Products"
+	depends on MACH_U300
+	help
+		Select this if you're developing on the
+		S365/B365 test products.
+
+endchoice
+
+choice
+	prompt "Memory configuration"
+	default MACH_U300_SINGLE_RAM
+	---help---
+	You have to config the kernel according to the physical memory
+	configuration.
+
+config MACH_U300_SINGLE_RAM
+	bool "Single RAM"
+	help
+		Select this if you want support for Single RAM phones.
+
+config MACH_U300_DUAL_RAM
+	bool "Dual RAM"
+	help
+		Select this if you want support for Dual RAM phones.
+		This is two RAM memorys on different EMIFs.
+endchoice
+
+config U300_DEBUG
+	bool "Debug support for U300"
+	depends on PM
+	help
+		Debug support for U300 in sysfs, procfs etc.
+
+config MACH_U300_SEMI_IS_SHARED
+	bool "The SEMI is used by both the access and application side"
+	depends on MACH_U300
+	help
+		This makes it possible to use the SEMI (Shared External
+		Memory Interface) from both from access and application
+		side.
+
+comment "All the settings below must match the bootloader's settings"
+
+config MACH_U300_ACCESS_MEM_SIZE
+       int "Access CPU memory allocation"
+       range 7 25
+       depends on MACH_U300_SINGLE_RAM
+       default 13
+       help
+		How much memory in MiB that the Access side CPU has allocated
+
+config MACH_U300_2MB_ALIGNMENT_FIX
+       bool "2MiB alignment fix"
+       depends on MACH_U300_SINGLE_RAM
+       default y
+       help
+		If yes and the Access side CPU has allocated an odd size in
+		MiB, this fix gives you one MiB extra that would otherwise be
+		lost due to Linux 2 MiB alignment policy.
+
+endmenu
+
+endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-u300/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel, U300 machine.
+#
+
+obj-y		:= core.o clock.o timer.o gpio.o padmux.o
+obj-m		:=
+obj-n		:=
+obj-		:=
+
+obj-$(CONFIG_ARCH_U300)	          += u300.o
+obj-$(CONFIG_MMC)                 += mmc.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/Makefile.boot linux-libre-2.6.31-gnu/arch/arm/mach-u300/Makefile.boot
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/Makefile.boot	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,15 @@
+# Note: the following conditions must always be true:
+#   ZRELADDR == virt_to_phys(TEXTADDR)
+#   PARAMS_PHYS must be within 4MB of ZRELADDR
+#   INITRD_PHYS must be in RAM
+
+ifdef CONFIG_MACH_U300_SINGLE_RAM
+     zreladdr-y	:= 0x28E08000
+  params_phys-y	:= 0x28E00100
+else
+     zreladdr-y	:= 0x48008000
+  params_phys-y	:= 0x48000100
+endif
+
+# This isn't used.
+#initrd_phys-y	:= 0x29800000
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/mmc.c linux-libre-2.6.31-gnu/arch/arm/mach-u300/mmc.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/mmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/mmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,216 @@
+/*
+ *
+ * arch/arm/mach-u300/mmc.c
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Johan Lundin <johan.lundin@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+#include <linux/device.h>
+#include <linux/amba/bus.h>
+#include <linux/mmc/host.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/mmc.h>
+#include "mmc.h"
+
+struct mmci_card_event {
+	struct input_dev *mmc_input;
+	int mmc_inserted;
+	struct work_struct workq;
+	struct mmc_platform_data mmc0_plat_data;
+};
+
+static unsigned int mmc_status(struct device *dev)
+{
+	struct mmci_card_event *mmci_card = container_of(
+		dev->platform_data,
+		struct mmci_card_event, mmc0_plat_data);
+
+	return mmci_card->mmc_inserted;
+}
+
+/*
+ * Here follows a large chunk of code which will only be enabled if you
+ * have both the AB3100 chip mounted and the MMC subsystem activated.
+ */
+
+static u32 mmc_translate_vdd(struct device *dev, unsigned int voltage)
+{
+	int v;
+
+	/*
+	 * MMC Spec:
+	 * bit 7:	1.70 - 1.95V
+	 * bit 8 - 14:	2.0 - 2.6V
+	 * bit 15 - 23:	2.7 - 3.6V
+	 *
+	 * ab3100 voltages:
+	 * 000 - 2.85V
+	 * 001 - 2.75V
+	 * 010 - 1.8V
+	 * 011 - 1.5V
+	 */
+	switch (voltage) {
+	case 8:
+		v = 3;
+		break;
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+	case 14:
+	case 15:
+		v = 1;
+		break;
+	case 16:
+		v = 1;
+		break;
+	case 17:
+	case 18:
+	case 19:
+	case 20:
+	case 21:
+	case 22:
+	case 23:
+	case 24:
+		v = 0;
+		break;
+	default:
+		v = 0;
+		break;
+	}
+
+	/* PL180 voltage register bits */
+	return v << 2;
+}
+
+
+
+static int mmci_callback(void *data)
+{
+	struct mmci_card_event *mmci_card = data;
+
+	disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD);
+	schedule_work(&mmci_card->workq);
+
+	return 0;
+}
+
+
+static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
+		  char *buf)
+{
+	struct mmci_card_event *mmci_card = container_of(
+		dev->platform_data,
+		struct mmci_card_event, mmc0_plat_data);
+
+
+	return sprintf(buf, "%d\n", !mmci_card->mmc_inserted);
+}
+
+static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL);
+
+static void _mmci_callback(struct work_struct *ws)
+{
+
+	struct mmci_card_event *mmci_card = container_of(
+		ws,
+		struct mmci_card_event, workq);
+
+	mdelay(20);
+
+	mmci_card->mmc_inserted = !!gpio_get_value(U300_GPIO_PIN_MMC_CD);
+
+	input_report_switch(mmci_card->mmc_input, KEY_INSERT,
+			    !mmci_card->mmc_inserted);
+	input_sync(mmci_card->mmc_input);
+
+	pr_debug("MMC/SD card was %s\n",
+		 mmci_card->mmc_inserted ? "removed" : "inserted");
+
+	enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, !mmci_card->mmc_inserted);
+}
+
+int __devinit mmc_init(struct amba_device *adev)
+{
+	struct mmci_card_event *mmci_card;
+	struct device *mmcsd_device = &adev->dev;
+	int ret = 0;
+
+	mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
+	if (!mmci_card)
+		return -ENOMEM;
+
+	/* Nominally 2.85V on our platform */
+	mmci_card->mmc0_plat_data.ocr_mask = MMC_VDD_28_29;
+	mmci_card->mmc0_plat_data.translate_vdd = mmc_translate_vdd;
+	mmci_card->mmc0_plat_data.status = mmc_status;
+
+	mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
+
+	INIT_WORK(&mmci_card->workq, _mmci_callback);
+
+	ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection");
+	if (ret) {
+		printk(KERN_CRIT "Could not allocate MMC card detection " \
+		       "GPIO pin\n");
+		goto out;
+	}
+
+	ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD);
+	if (ret) {
+		printk(KERN_CRIT "Invalid GPIO pin requested\n");
+		goto out;
+	}
+
+	ret = sysfs_create_file(&mmcsd_device->kobj,
+			       &dev_attr_mmc_inserted.attr);
+	if (ret)
+		goto out;
+
+	mmci_card->mmc_input = input_allocate_device();
+	if (!mmci_card->mmc_input) {
+		printk(KERN_CRIT "Could not allocate MMC input device\n");
+		return -ENOMEM;
+	}
+
+	mmci_card->mmc_input->name = "MMC insert notification";
+	mmci_card->mmc_input->id.bustype = BUS_HOST;
+	mmci_card->mmc_input->id.vendor = 0;
+	mmci_card->mmc_input->id.product = 0;
+	mmci_card->mmc_input->id.version = 0x0100;
+	mmci_card->mmc_input->dev.parent = mmcsd_device;
+	input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT);
+
+	/*
+	 * Since this must always be compiled into the kernel, this input
+	 * is never unregistered or free:ed.
+	 */
+	ret = input_register_device(mmci_card->mmc_input);
+	if (ret) {
+		input_free_device(mmci_card->mmc_input);
+		goto out;
+	}
+
+	input_set_drvdata(mmci_card->mmc_input, mmci_card);
+
+	ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback,
+				     mmci_card);
+
+	schedule_work(&mmci_card->workq);
+
+	printk(KERN_INFO "Registered MMC insert/remove notification\n");
+out:
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/mmc.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/mmc.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/mmc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ *
+ * arch/arm/mach-u300/mmc.h
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+#ifndef MMC_H
+#define MMC_H
+
+#include <linux/amba/bus.h>
+
+int __devinit mmc_init(struct amba_device *adev);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/padmux.c linux-libre-2.6.31-gnu/arch/arm/mach-u300/padmux.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/padmux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/padmux.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,58 @@
+/*
+ *
+ * arch/arm/mach-u300/padmux.c
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * U300 PADMUX functions
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <mach/u300-regs.h>
+#include <mach/syscon.h>
+
+#include "padmux.h"
+
+/* Set the PAD MUX to route the MMC reader correctly to GPIO0. */
+void pmx_set_mission_mode_mmc(void)
+{
+	u16 val;
+
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1LR);
+	val &= ~U300_SYSCON_PMC1LR_MMCSD_MASK;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1LR);
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+	val &= ~U300_SYSCON_PMC1HR_APP_GPIO_1_MASK;
+	val |= U300_SYSCON_PMC1HR_APP_GPIO_1_MMC;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+}
+
+void pmx_set_mission_mode_spi(void)
+{
+	u16 val;
+
+	/* Set up padmuxing so the SPI port and its chipselects are active */
+	val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+	/*
+	 * Activate the SPI port (disable the use of these pins for generic
+	 * GPIO, DSP, AAIF
+	 */
+	val &= ~U300_SYSCON_PMC1HR_APP_SPI_2_MASK;
+	val |= U300_SYSCON_PMC1HR_APP_SPI_2_SPI;
+	/*
+	 * Use GPIO pin SPI CS1 for CS1 actually (it can be used for other
+	 * things also)
+	 */
+	val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK;
+	val |= U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI;
+	/*
+	 * Use GPIO pin SPI CS2 for CS2 actually (it can be used for other
+	 * things also)
+	 */
+	val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK;
+	val |= U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI;
+	writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/padmux.h linux-libre-2.6.31-gnu/arch/arm/mach-u300/padmux.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/padmux.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/padmux.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ *
+ * arch/arm/mach-u300/padmux.h
+ *
+ *
+ * Copyright (C) 2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * U300 PADMUX API
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ */
+
+#ifndef __MACH_U300_PADMUX_H
+#define __MACH_U300_PADMUX_H
+
+void pmx_set_mission_mode_mmc(void);
+void pmx_set_mission_mode_spi(void);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/timer.c linux-libre-2.6.31-gnu/arch/arm/mach-u300/timer.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/timer.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,422 @@
+/*
+ *
+ * arch/arm/mach-u300/timer.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Timer COH 901 328, runs the OS timer interrupt.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+/* Generic stuff */
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+
+#include "clock.h"
+
+/*
+ * APP side special timer registers
+ * This timer contains four timers which can fire an interrupt each.
+ * OS (operating system) timer @ 32768 Hz
+ * DD (device driver) timer @ 1 kHz
+ * GP1 (general purpose 1) timer @ 1MHz
+ * GP2 (general purpose 2) timer @ 1MHz
+ */
+
+/* Reset OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_ROST					(0x0000)
+#define U300_TIMER_APP_ROST_TIMER_RESET				(0x00000000)
+/* Enable OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_EOST					(0x0004)
+#define U300_TIMER_APP_EOST_TIMER_ENABLE			(0x00000000)
+/* Disable OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_DOST					(0x0008)
+#define U300_TIMER_APP_DOST_TIMER_DISABLE			(0x00000000)
+/* OS Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SOSTM					(0x000c)
+#define U300_TIMER_APP_SOSTM_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_SOSTM_MODE_ONE_SHOT			(0x00000001)
+/* OS Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_OSTS					(0x0010)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_MASK			(0x0000000F)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_IDLE			(0x00000001)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_ACTIVE			(0x00000002)
+#define U300_TIMER_APP_OSTS_ENABLE_IND				(0x00000010)
+#define U300_TIMER_APP_OSTS_MODE_MASK				(0x00000020)
+#define U300_TIMER_APP_OSTS_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_OSTS_MODE_ONE_SHOT			(0x00000020)
+#define U300_TIMER_APP_OSTS_IRQ_ENABLED_IND			(0x00000040)
+#define U300_TIMER_APP_OSTS_IRQ_PENDING_IND			(0x00000080)
+/* OS Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_OSTCC					(0x0014)
+/* OS Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_OSTTC					(0x0018)
+/* OS Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_OSTIE					(0x001c)
+#define U300_TIMER_APP_OSTIE_IRQ_DISABLE			(0x00000000)
+#define U300_TIMER_APP_OSTIE_IRQ_ENABLE				(0x00000001)
+/* OS Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_OSTIA					(0x0020)
+#define U300_TIMER_APP_OSTIA_IRQ_ACK				(0x00000080)
+
+/* Reset DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_RDDT					(0x0040)
+#define U300_TIMER_APP_RDDT_TIMER_RESET				(0x00000000)
+/* Enable DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_EDDT					(0x0044)
+#define U300_TIMER_APP_EDDT_TIMER_ENABLE			(0x00000000)
+/* Disable DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_DDDT					(0x0048)
+#define U300_TIMER_APP_DDDT_TIMER_DISABLE			(0x00000000)
+/* DD Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SDDTM					(0x004c)
+#define U300_TIMER_APP_SDDTM_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_SDDTM_MODE_ONE_SHOT			(0x00000001)
+/* DD Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_DDTS					(0x0050)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_MASK			(0x0000000F)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_IDLE			(0x00000001)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_ACTIVE			(0x00000002)
+#define U300_TIMER_APP_DDTS_ENABLE_IND				(0x00000010)
+#define U300_TIMER_APP_DDTS_MODE_MASK				(0x00000020)
+#define U300_TIMER_APP_DDTS_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_DDTS_MODE_ONE_SHOT			(0x00000020)
+#define U300_TIMER_APP_DDTS_IRQ_ENABLED_IND			(0x00000040)
+#define U300_TIMER_APP_DDTS_IRQ_PENDING_IND			(0x00000080)
+/* DD Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_DDTCC					(0x0054)
+/* DD Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_DDTTC					(0x0058)
+/* DD Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_DDTIE					(0x005c)
+#define U300_TIMER_APP_DDTIE_IRQ_DISABLE			(0x00000000)
+#define U300_TIMER_APP_DDTIE_IRQ_ENABLE				(0x00000001)
+/* DD Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_DDTIA					(0x0060)
+#define U300_TIMER_APP_DDTIA_IRQ_ACK				(0x00000080)
+
+/* Reset GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_RGPT1					(0x0080)
+#define U300_TIMER_APP_RGPT1_TIMER_RESET			(0x00000000)
+/* Enable GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_EGPT1					(0x0084)
+#define U300_TIMER_APP_EGPT1_TIMER_ENABLE			(0x00000000)
+/* Disable GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_DGPT1					(0x0088)
+#define U300_TIMER_APP_DGPT1_TIMER_DISABLE			(0x00000000)
+/* GP1 Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SGPT1M					(0x008c)
+#define U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT			(0x00000001)
+/* GP1 Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT1S					(0x0090)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_MASK			(0x0000000F)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_IDLE			(0x00000001)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_ACTIVE			(0x00000002)
+#define U300_TIMER_APP_GPT1S_ENABLE_IND				(0x00000010)
+#define U300_TIMER_APP_GPT1S_MODE_MASK				(0x00000020)
+#define U300_TIMER_APP_GPT1S_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_GPT1S_MODE_ONE_SHOT			(0x00000020)
+#define U300_TIMER_APP_GPT1S_IRQ_ENABLED_IND			(0x00000040)
+#define U300_TIMER_APP_GPT1S_IRQ_PENDING_IND			(0x00000080)
+/* GP1 Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT1CC					(0x0094)
+/* GP1 Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_GPT1TC					(0x0098)
+/* GP1 Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT1IE					(0x009c)
+#define U300_TIMER_APP_GPT1IE_IRQ_DISABLE			(0x00000000)
+#define U300_TIMER_APP_GPT1IE_IRQ_ENABLE			(0x00000001)
+/* GP1 Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT1IA					(0x00a0)
+#define U300_TIMER_APP_GPT1IA_IRQ_ACK				(0x00000080)
+
+/* Reset GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_RGPT2					(0x00c0)
+#define U300_TIMER_APP_RGPT2_TIMER_RESET			(0x00000000)
+/* Enable GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_EGPT2					(0x00c4)
+#define U300_TIMER_APP_EGPT2_TIMER_ENABLE			(0x00000000)
+/* Disable GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_DGPT2					(0x00c8)
+#define U300_TIMER_APP_DGPT2_TIMER_DISABLE			(0x00000000)
+/* GP2 Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SGPT2M					(0x00cc)
+#define U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_SGPT2M_MODE_ONE_SHOT			(0x00000001)
+/* GP2 Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT2S					(0x00d0)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_MASK			(0x0000000F)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_IDLE			(0x00000001)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_ACTIVE			(0x00000002)
+#define U300_TIMER_APP_GPT2S_ENABLE_IND				(0x00000010)
+#define U300_TIMER_APP_GPT2S_MODE_MASK				(0x00000020)
+#define U300_TIMER_APP_GPT2S_MODE_CONTINUOUS			(0x00000000)
+#define U300_TIMER_APP_GPT2S_MODE_ONE_SHOT			(0x00000020)
+#define U300_TIMER_APP_GPT2S_IRQ_ENABLED_IND			(0x00000040)
+#define U300_TIMER_APP_GPT2S_IRQ_PENDING_IND			(0x00000080)
+/* GP2 Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT2CC					(0x00d4)
+/* GP2 Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_GPT2TC					(0x00d8)
+/* GP2 Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT2IE					(0x00dc)
+#define U300_TIMER_APP_GPT2IE_IRQ_DISABLE			(0x00000000)
+#define U300_TIMER_APP_GPT2IE_IRQ_ENABLE			(0x00000001)
+/* GP2 Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT2IA					(0x00e0)
+#define U300_TIMER_APP_GPT2IA_IRQ_ACK				(0x00000080)
+
+/* Clock request control register - all four timers */
+#define U300_TIMER_APP_CRC					(0x100)
+#define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE			(0x00000001)
+
+#define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
+#define US_PER_TICK ((1000000 + (HZ/2)) / HZ)
+
+/*
+ * The u300_set_mode() function is always called first, if we
+ * have oneshot timer active, the oneshot scheduling function
+ * u300_set_next_event() is called immediately after.
+ */
+static void u300_set_mode(enum clock_event_mode mode,
+			  struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		/* Disable interrupts on GPT1 */
+		writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+		/* Disable GP1 while we're reprogramming it. */
+		writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+		/*
+		 * Set the periodic mode to a certain number of ticks per
+		 * jiffy.
+		 */
+		writel(TICKS_PER_JIFFY,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC);
+		/*
+		 * Set continuous mode, so the timer keeps triggering
+		 * interrupts.
+		 */
+		writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M);
+		/* Enable timer interrupts */
+		writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+		/* Then enable the OS timer again */
+		writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* Just break; here? */
+		/*
+		 * The actual event will be programmed by the next event hook,
+		 * so we just set a dummy value somewhere at the end of the
+		 * universe here.
+		 */
+		/* Disable interrupts on GPT1 */
+		writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+		/* Disable GP1 while we're reprogramming it. */
+		writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+		/*
+		 * Expire far in the future, u300_set_next_event() will be
+		 * called soon...
+		 */
+		writel(0xFFFFFFFF, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC);
+		/* We run one shot per tick here! */
+		writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M);
+		/* Enable interrupts for this timer */
+		writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+		/* Enable timer */
+		writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/* Disable interrupts on GP1 */
+		writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+		/* Disable GP1 */
+		writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+		       U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		/* Ignore this call */
+		break;
+	}
+}
+
+/*
+ * The app timer in one shot mode obviously has to be reprogrammed
+ * in EXACTLY this sequence to work properly. Do NOT try to e.g. replace
+ * the interrupt disable + timer disable commands with a reset command,
+ * it will fail miserably. Apparently (and I found this the hard way)
+ * the timer is very sensitive to the instruction order, though you don't
+ * get that impression from the data sheet.
+ */
+static int u300_set_next_event(unsigned long cycles,
+			       struct clock_event_device *evt)
+
+{
+	/* Disable interrupts on GPT1 */
+	writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+	       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+	/* Disable GP1 while we're reprogramming it. */
+	writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+	       U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1);
+	/* Reset the General Purpose timer 1. */
+	writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
+	       U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1);
+	/* IRQ in n * cycles */
+	writel(cycles, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC);
+	/*
+	 * We run one shot per tick here! (This is necessary to reconfigure,
+	 * the timer will tilt if you don't!)
+	 */
+	writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
+	       U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M);
+	/* Enable timer interrupts */
+	writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+	       U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE);
+	/* Then enable the OS timer again */
+	writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+	       U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1);
+	return 0;
+}
+
+
+/* Use general purpose timer 1 as clock event */
+static struct clock_event_device clockevent_u300_1mhz = {
+	.name           = "GPT1",
+	.rating         = 300, /* Reasonably fast and accurate clock event */
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	/* 22 calculated using the algorithm in arch/mips/kernel/time.c */
+	.shift          = 22,
+	.set_next_event = u300_set_next_event,
+	.set_mode       = u300_set_mode,
+};
+
+/* Clock event timer interrupt handler */
+static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &clockevent_u300_1mhz;
+	/* ACK/Clear timer IRQ for the APP GPT1 Timer */
+	writel(U300_TIMER_APP_GPT1IA_IRQ_ACK,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IA);
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction u300_timer_irq = {
+	.name           = "U300 Timer Tick",
+	.flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler        = u300_timer_interrupt,
+};
+
+/* Use general purpose timer 2 as clock source */
+static cycle_t u300_get_cycles(struct clocksource *cs)
+{
+	return (cycles_t) readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
+}
+
+static struct clocksource clocksource_u300_1mhz = {
+	.name           = "GPT2",
+	.rating         = 300, /* Reasonably fast and accurate clock source */
+	.read           = u300_get_cycles,
+	.mask           = CLOCKSOURCE_MASK(32), /* 32 bits */
+	/* 22 calculated using the algorithm in arch/mips/kernel/time.c */
+	.shift          = 22,
+	.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/*
+ * This sets up the system timers, clock source and clock event.
+ */
+static void __init u300_timer_init(void)
+{
+	u300_enable_timer_clock();
+	/*
+	 * Disable the "OS" and "DD" timers - these are designed for Symbian!
+	 * Example usage in cnh1601578 cpu subsystem pd_timer_app.c
+	 */
+	writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_CRC);
+	writel(U300_TIMER_APP_ROST_TIMER_RESET,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_ROST);
+	writel(U300_TIMER_APP_DOST_TIMER_DISABLE,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_DOST);
+	writel(U300_TIMER_APP_RDDT_TIMER_RESET,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_RDDT);
+	writel(U300_TIMER_APP_DDDT_TIMER_DISABLE,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_DDDT);
+
+	/* Reset the General Purpose timer 1. */
+	writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1);
+
+	/* Set up the IRQ handler */
+	setup_irq(IRQ_U300_TIMER_APP_GP1, &u300_timer_irq);
+
+	/* Reset the General Purpose timer 2 */
+	writel(U300_TIMER_APP_RGPT2_TIMER_RESET,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT2);
+	/* Set this timer to run around forever */
+	writel(0xFFFFFFFFU, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2TC);
+	/* Set continuous mode so it wraps around */
+	writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS,
+	       U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT2M);
+	/* Disable timer interrupts */
+	writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2IE);
+	/* Then enable the GP2 timer to use as a free running us counter */
+	writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
+		U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2);
+
+	/* This is a pure microsecond clock source */
+	clocksource_u300_1mhz.mult =
+		clocksource_khz2mult(1000, clocksource_u300_1mhz.shift);
+	if (clocksource_register(&clocksource_u300_1mhz))
+		printk(KERN_ERR "timer: failed to initialize clock "
+		       "source %s\n", clocksource_u300_1mhz.name);
+
+	clockevent_u300_1mhz.mult =
+		div_sc(1000000, NSEC_PER_SEC, clockevent_u300_1mhz.shift);
+	/* 32bit counter, so 32bits delta is max */
+	clockevent_u300_1mhz.max_delta_ns =
+		clockevent_delta2ns(0xffffffff, &clockevent_u300_1mhz);
+	/* This timer is slow enough to set for 1 cycle == 1 MHz */
+	clockevent_u300_1mhz.min_delta_ns =
+		clockevent_delta2ns(1, &clockevent_u300_1mhz);
+	clockevent_u300_1mhz.cpumask = cpumask_of(0);
+	clockevents_register_device(&clockevent_u300_1mhz);
+	/*
+	 * TODO: init and register the rest of the timers too, they can be
+	 * used by hrtimers!
+	 */
+}
+
+/*
+ * Very simple system timer that only register the clock event and
+ * clock source.
+ */
+struct sys_timer u300_timer = {
+	.init		= u300_timer_init,
+};
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-u300/u300.c linux-libre-2.6.31-gnu/arch/arm/mach-u300/u300.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-u300/u300.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-u300/u300.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ *
+ * arch/arm/mach-u300/u300.c
+ *
+ *
+ * Copyright (C) 2006-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Platform machine definition.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init u300_init_machine(void)
+{
+	u300_init_devices();
+}
+
+#ifdef CONFIG_MACH_U300_BS2X
+#define MACH_U300_STRING "Ericsson AB U300 S25/S26/B25/B26 Prototype Board"
+#endif
+
+#ifdef CONFIG_MACH_U300_BS330
+#define MACH_U300_STRING "Ericsson AB U330 S330/B330 Prototype Board"
+#endif
+
+#ifdef CONFIG_MACH_U300_BS335
+#define MACH_U300_STRING "Ericsson AB U335 S335/B335 Prototype Board"
+#endif
+
+#ifdef CONFIG_MACH_U300_BS365
+#define MACH_U300_STRING "Ericsson AB U365 S365/B365 Prototype Board"
+#endif
+
+MACHINE_START(U300, MACH_U300_STRING)
+	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
+	.phys_io	= U300_AHB_PER_PHYS_BASE,
+	.io_pg_offst	= ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= BOOT_PARAMS_OFFSET,
+	.map_io		= u300_map_io,
+	.init_irq	= u300_init_irq,
+	.timer		= &u300_timer,
+	.init_machine	= u300_init_machine,
+MACHINE_END
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-versatile/core.c linux-libre-2.6.31-gnu/arch/arm/mach-versatile/core.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-versatile/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-versatile/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -116,7 +116,7 @@
 {
 	unsigned int i;
 
-	vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0);
+	vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
 
 	set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
 
@@ -342,8 +342,7 @@
 
 static struct i2c_board_info versatile_i2c_board_info[] = {
 	{
-		I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
-		.type = "ds1338",
+		I2C_BOARD_INFO("ds1338", 0xd0 >> 1),
 	},
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/clock.c linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/arm/mach-w90x900/clock.c
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#include "clock.h"
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	if (clk->enabled++ == 0)
+		(clk->enable)(clk, 1);
+	spin_unlock_irqrestore(&clocks_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	WARN_ON(clk->enabled == 0);
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	if (--clk->enabled == 0)
+		(clk->enable)(clk, 0);
+	spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+void w90x900_clk_enable(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->cken;
+	unsigned long clken;
+
+	clken = __raw_readl(W90X900_VA_CLKPWR);
+
+	if (enable)
+		clken |= clocks;
+	else
+		clken &= ~clocks;
+
+	__raw_writel(clken, W90X900_VA_CLKPWR);
+}
+
+void clks_register(struct clk_lookup *clks, size_t num)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		clkdev_add(&clks[i]);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/clock.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/clock.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/mach-w90x900/clock.h
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * 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.
+ */
+
+#include <asm/clkdev.h>
+
+void w90x900_clk_enable(struct clk *clk, int enable);
+void clks_register(struct clk_lookup *clks, size_t num);
+
+struct clk {
+	unsigned long		cken;
+	unsigned int		enabled;
+	void			(*enable)(struct clk *, int enable);
+};
+
+#define DEFINE_CLK(_name, _ctrlbit)			\
+struct clk clk_##_name = {				\
+		.enable	= w90x900_clk_enable,		\
+		.cken	= (1 << _ctrlbit),		\
+	}
+
+#define DEF_CLKLOOK(_clk, _devname, _conname)		\
+	{						\
+		.clk		= _clk,			\
+		.dev_id		= _devname,		\
+		.con_id		= _conname,		\
+	}
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/cpu.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/cpu.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/cpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/cpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,7 @@
 extern void w90x900_init_irq(void);
 extern void w90p910_init_io(struct map_desc *mach_desc, int size);
 extern void w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no);
-extern void w90p910_init_clocks(int xtal);
+extern void w90p910_init_clocks(void);
 extern void w90p910_map_io(struct map_desc *mach_desc, int size);
 extern struct platform_device w90p910_serial_device;
 extern struct sys_timer w90x900_timer;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/gpio.c linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,154 @@
+/*
+ * linux/arch/arm/mach-w90p910/gpio.c
+ *
+ * Generic w90p910 GPIO handling
+ *
+ *  Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+
+#define GPIO_BASE 		(W90X900_VA_GPIO)
+#define GPIO_DIR		(0x04)
+#define GPIO_OUT		(0x08)
+#define GPIO_IN			(0x0C)
+#define GROUPINERV		(0x10)
+#define GPIO_GPIO(Nb)		(0x00000001 << (Nb))
+#define to_w90p910_gpio_chip(c) container_of(c, struct w90p910_gpio_chip, chip)
+
+#define W90P910_GPIO_CHIP(name, base_gpio, nr_gpio)			\
+	{								\
+		.chip = {						\
+			.label		  = name,			\
+			.direction_input  = w90p910_dir_input,		\
+			.direction_output = w90p910_dir_output,		\
+			.get		  = w90p910_gpio_get,		\
+			.set		  = w90p910_gpio_set,		\
+			.base		  = base_gpio,			\
+			.ngpio		  = nr_gpio,			\
+		}							\
+	}
+
+struct w90p910_gpio_chip {
+	struct gpio_chip	chip;
+	void __iomem		*regbase;	/* Base of group register*/
+	spinlock_t 		gpio_lock;
+};
+
+static int w90p910_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
+	void __iomem *pio = w90p910_gpio->regbase + GPIO_IN;
+	unsigned int regval;
+
+	regval = __raw_readl(pio);
+	regval &= GPIO_GPIO(offset);
+
+	return (regval != 0);
+}
+
+static void w90p910_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
+	void __iomem *pio = w90p910_gpio->regbase + GPIO_OUT;
+	unsigned int regval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags);
+
+	regval = __raw_readl(pio);
+
+	if (val)
+		regval |= GPIO_GPIO(offset);
+	else
+		regval &= ~GPIO_GPIO(offset);
+
+	__raw_writel(regval, pio);
+
+	spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags);
+}
+
+static int w90p910_dir_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
+	void __iomem *pio = w90p910_gpio->regbase + GPIO_DIR;
+	unsigned int regval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags);
+
+	regval = __raw_readl(pio);
+	regval &= ~GPIO_GPIO(offset);
+	__raw_writel(regval, pio);
+
+	spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags);
+
+	return 0;
+}
+
+static int w90p910_dir_output(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
+	void __iomem *outreg = w90p910_gpio->regbase + GPIO_OUT;
+	void __iomem *pio = w90p910_gpio->regbase + GPIO_DIR;
+	unsigned int regval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags);
+
+	regval = __raw_readl(pio);
+	regval |= GPIO_GPIO(offset);
+	__raw_writel(regval, pio);
+
+	regval = __raw_readl(outreg);
+
+	if (val)
+		regval |= GPIO_GPIO(offset);
+	else
+		regval &= ~GPIO_GPIO(offset);
+
+	__raw_writel(regval, outreg);
+
+	spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags);
+
+	return 0;
+}
+
+static struct w90p910_gpio_chip w90p910_gpio[] = {
+	W90P910_GPIO_CHIP("GROUPC", 0, 16),
+	W90P910_GPIO_CHIP("GROUPD", 16, 10),
+	W90P910_GPIO_CHIP("GROUPE", 26, 14),
+	W90P910_GPIO_CHIP("GROUPF", 40, 10),
+	W90P910_GPIO_CHIP("GROUPG", 50, 17),
+	W90P910_GPIO_CHIP("GROUPH", 67, 8),
+	W90P910_GPIO_CHIP("GROUPI", 75, 17),
+};
+
+void __init w90p910_init_gpio(int nr_group)
+{
+	unsigned	i;
+	struct w90p910_gpio_chip *gpio_chip;
+
+	for (i = 0; i < nr_group; i++) {
+		gpio_chip = &w90p910_gpio[i];
+		spin_lock_init(&gpio_chip->gpio_lock);
+		gpio_chip->regbase = GPIO_BASE + i * GROUPINERV;
+		gpiochip_add(&gpio_chip->chip);
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/clkdev.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/clkdev.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/clkdev.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/gpio.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/mach-w90p910/include/mach/gpio.h
+ *
+ * Generic w90p910 GPIO handling
+ *
+ *  Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_W90P910_GPIO_H
+#define __ASM_ARCH_W90P910_GPIO_H
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq;
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,7 @@
 /*
  * arch/arm/mach-w90x900/include/mach/irqs.h
  *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (c) 2008 Nuvoton technology corporation.
  *
  * Wan ZongShun <mcuos.com@gmail.com>
  *
@@ -10,8 +9,7 @@
  *
  * 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.
+ * the Free Software Foundation;version 2 of the License.
  *
  */
 
@@ -31,6 +29,11 @@
 /* Main cpu interrupts */
 
 #define IRQ_WDT		W90X900_IRQ(1)
+#define IRQ_GROUP0	W90X900_IRQ(2)
+#define IRQ_GROUP1	W90X900_IRQ(3)
+#define IRQ_ACTL	W90X900_IRQ(4)
+#define IRQ_LCD		W90X900_IRQ(5)
+#define IRQ_RTC		W90X900_IRQ(6)
 #define IRQ_UART0	W90X900_IRQ(7)
 #define IRQ_UART1	W90X900_IRQ(8)
 #define IRQ_UART2	W90X900_IRQ(9)
@@ -39,7 +42,45 @@
 #define IRQ_TIMER0	W90X900_IRQ(12)
 #define IRQ_TIMER1	W90X900_IRQ(13)
 #define IRQ_T_INT_GROUP	W90X900_IRQ(14)
+#define IRQ_USBH	W90X900_IRQ(15)
+#define IRQ_EMCTX	W90X900_IRQ(16)
+#define IRQ_EMCRX	W90X900_IRQ(17)
+#define IRQ_GDMAGROUP	W90X900_IRQ(18)
+#define IRQ_DMAC	W90X900_IRQ(19)
+#define IRQ_FMI		W90X900_IRQ(20)
+#define IRQ_USBD	W90X900_IRQ(21)
+#define IRQ_ATAPI	W90X900_IRQ(22)
+#define IRQ_G2D		W90X900_IRQ(23)
+#define IRQ_PCI		W90X900_IRQ(24)
+#define IRQ_SCGROUP	W90X900_IRQ(25)
+#define IRQ_I2CGROUP	W90X900_IRQ(26)
+#define IRQ_SSP		W90X900_IRQ(27)
+#define IRQ_PWM		W90X900_IRQ(28)
+#define IRQ_KPI		W90X900_IRQ(29)
+#define IRQ_P2SGROUP	W90X900_IRQ(30)
 #define IRQ_ADC		W90X900_IRQ(31)
 #define NR_IRQS		(IRQ_ADC+1)
 
+/*for irq group*/
+
+#define	IRQ_PS2_PORT0	0x10000000
+#define	IRQ_PS2_PORT1	0x20000000
+#define	IRQ_I2C_LINE0	0x04000000
+#define	IRQ_I2C_LINE1	0x08000000
+#define	IRQ_SC_CARD0	0x01000000
+#define	IRQ_SC_CARD1	0x02000000
+#define	IRQ_GDMA_CH0	0x00100000
+#define	IRQ_GDMA_CH1	0x00200000
+#define	IRQ_TIMER2	0x00010000
+#define	IRQ_TIMER3	0x00020000
+#define	IRQ_TIMER4	0x00040000
+#define	IRQ_GROUP0_IRQ0	0x00000001
+#define	IRQ_GROUP0_IRQ1	0x00000002
+#define	IRQ_GROUP0_IRQ2	0x00000004
+#define	IRQ_GROUP0_IRQ3	0x00000008
+#define	IRQ_GROUP1_IRQ4	0x00000010
+#define	IRQ_GROUP1_IRQ5	0x00000020
+#define	IRQ_GROUP1_IRQ6	0x00000040
+#define	IRQ_GROUP1_IRQ7	0x00000080
+
 #endif /* __ASM_ARCH_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/map.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/map.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,7 @@
 /*
  * arch/arm/mach-w90x900/include/mach/map.h
  *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (c) 2008 Nuvoton technology corporation.
  *
  * Wan ZongShun <mcuos.com@gmail.com>
  *
@@ -10,8 +9,7 @@
  *
  * 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.
+ * the Free Software Foundation;version 2 of the License.
  *
  */
 
@@ -34,7 +32,6 @@
  * interrupt controller is the first thing we put in, to make
  * the assembly code for the irq detection easier
  */
-
 #define W90X900_VA_IRQ		W90X900_ADDR(0x00000000)
 #define W90X900_PA_IRQ		(0xB8002000)
 #define W90X900_SZ_IRQ		SZ_4K
@@ -44,33 +41,117 @@
 #define W90X900_SZ_GCR		SZ_4K
 
 /* Clock and Power management */
-
 #define W90X900_VA_CLKPWR	(W90X900_VA_GCR+0x200)
 #define W90X900_PA_CLKPWR	(0xB0000200)
 #define W90X900_SZ_CLKPWR	SZ_4K
 
 /* EBI management */
-
 #define W90X900_VA_EBI		W90X900_ADDR(0x00001000)
 #define W90X900_PA_EBI		(0xB0001000)
 #define W90X900_SZ_EBI		SZ_4K
 
 /* UARTs */
-
 #define W90X900_VA_UART		W90X900_ADDR(0x08000000)
 #define W90X900_PA_UART		(0xB8000000)
 #define W90X900_SZ_UART		SZ_4K
 
 /* Timers */
-
 #define W90X900_VA_TIMER	W90X900_ADDR(0x08001000)
 #define W90X900_PA_TIMER	(0xB8001000)
 #define W90X900_SZ_TIMER	SZ_4K
 
 /* GPIO ports */
-
 #define W90X900_VA_GPIO		W90X900_ADDR(0x08003000)
 #define W90X900_PA_GPIO		(0xB8003000)
 #define W90X900_SZ_GPIO		SZ_4K
 
+/* GDMA control */
+#define W90X900_VA_GDMA		W90X900_ADDR(0x00004000)
+#define W90X900_PA_GDMA		(0xB0004000)
+#define W90X900_SZ_GDMA		SZ_4K
+
+/* USB host controller*/
+#define W90X900_VA_USBEHCIHOST	W90X900_ADDR(0x00005000)
+#define W90X900_PA_USBEHCIHOST	(0xB0005000)
+#define W90X900_SZ_USBEHCIHOST	SZ_4K
+
+#define W90X900_VA_USBOHCIHOST	W90X900_ADDR(0x00007000)
+#define W90X900_PA_USBOHCIHOST	(0xB0007000)
+#define W90X900_SZ_USBOHCIHOST	SZ_4K
+
+/* I2C hardware controller */
+#define W90X900_VA_I2C		W90X900_ADDR(0x08006000)
+#define W90X900_PA_I2C		(0xB8006000)
+#define W90X900_SZ_I2C		SZ_4K
+
+/* Keypad Interface*/
+#define W90X900_VA_KPI		W90X900_ADDR(0x08008000)
+#define W90X900_PA_KPI		(0xB8008000)
+#define W90X900_SZ_KPI		SZ_4K
+
+/* Smart card host*/
+#define W90X900_VA_SC		W90X900_ADDR(0x08005000)
+#define W90X900_PA_SC		(0xB8005000)
+#define W90X900_SZ_SC		SZ_4K
+
+/* LCD controller*/
+#define W90X900_VA_LCD		W90X900_ADDR(0x00008000)
+#define W90X900_PA_LCD		(0xB0008000)
+#define W90X900_SZ_LCD		SZ_4K
+
+/* 2D controller*/
+#define W90X900_VA_GE		W90X900_ADDR(0x0000B000)
+#define W90X900_PA_GE		(0xB000B000)
+#define W90X900_SZ_GE		SZ_4K
+
+/* ATAPI */
+#define W90X900_VA_ATAPI	W90X900_ADDR(0x0000A000)
+#define W90X900_PA_ATAPI	(0xB000A000)
+#define W90X900_SZ_ATAPI	SZ_4K
+
+/* ADC */
+#define W90X900_VA_ADC		W90X900_ADDR(0x0800A000)
+#define W90X900_PA_ADC		(0xB800A000)
+#define W90X900_SZ_ADC		SZ_4K
+
+/* PS2 Interface*/
+#define W90X900_VA_PS2		W90X900_ADDR(0x08009000)
+#define W90X900_PA_PS2		(0xB8009000)
+#define W90X900_SZ_PS2		SZ_4K
+
+/* RTC */
+#define W90X900_VA_RTC		W90X900_ADDR(0x08004000)
+#define W90X900_PA_RTC		(0xB8004000)
+#define W90X900_SZ_RTC		SZ_4K
+
+/* Pulse Width Modulation(PWM) Registers */
+#define W90X900_VA_PWM		W90X900_ADDR(0x08007000)
+#define W90X900_PA_PWM		(0xB8007000)
+#define W90X900_SZ_PWM		SZ_4K
+
+/* Audio Controller controller */
+#define W90X900_VA_ACTL		W90X900_ADDR(0x00009000)
+#define W90X900_PA_ACTL		(0xB0009000)
+#define W90X900_SZ_ACTL		SZ_4K
+
+/* DMA controller */
+#define W90X900_VA_DMA		W90X900_ADDR(0x0000c000)
+#define W90X900_PA_DMA		(0xB000c000)
+#define W90X900_SZ_DMA		SZ_4K
+
+/* FMI controller */
+#define W90X900_VA_FMI		W90X900_ADDR(0x0000d000)
+#define W90X900_PA_FMI		(0xB000d000)
+#define W90X900_SZ_FMI		SZ_4K
+
+/* USB Device port */
+#define W90X900_VA_USBDEV	W90X900_ADDR(0x00006000)
+#define W90X900_PA_USBDEV	(0xB0006000)
+#define W90X900_SZ_USBDEV	SZ_4K
+
+/* External MAC control*/
+#define W90X900_VA_EMC		W90X900_ADDR(0x00003000)
+#define W90X900_PA_EMC		(0xB0003000)
+#define W90X900_SZ_EMC		SZ_4K
+
 #endif /* __ASM_ARCH_MAP_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/regs-clock.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/regs-clock.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/regs-clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-w90x900/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H
+
+/* Clock Control Registers  */
+#define CLK_BA		W90X900_VA_CLKPWR
+#define REG_CLKEN	(CLK_BA + 0x00)
+#define REG_CLKSEL	(CLK_BA + 0x04)
+#define REG_CLKDIV	(CLK_BA + 0x08)
+#define REG_PLLCON0	(CLK_BA + 0x0C)
+#define REG_PLLCON1	(CLK_BA + 0x10)
+#define REG_PMCON	(CLK_BA + 0x14)
+#define REG_IRQWAKECON	(CLK_BA + 0x18)
+#define REG_IRQWAKEFLAG	(CLK_BA + 0x1C)
+#define REG_IPSRST	(CLK_BA + 0x20)
+#define REG_CLKEN1	(CLK_BA + 0x24)
+#define REG_CLKDIV1	(CLK_BA + 0x28)
+
+#endif /*  __ASM_ARCH_REGS_CLOCK_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/regs-usb.h linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/regs-usb.h
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/include/mach/regs-usb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/include/mach/regs-usb.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-w90x900/include/mach/regs-usb.h
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#ifndef __ASM_ARCH_REGS_USB_H
+#define __ASM_ARCH_REGS_USB_H
+
+/* usb Control Registers  */
+#define USBH_BA		W90X900_VA_USBEHCIHOST
+#define USBD_BA		W90X900_VA_USBDEV
+#define USBO_BA		W90X900_VA_USBOHCIHOST
+
+/* USB Host Control Registers */
+#define REG_UPSCR0	(USBH_BA+0x064)
+#define REG_UPSCR1	(USBH_BA+0x068)
+#define REG_USBPCR0	(USBH_BA+0x0C4)
+#define REG_USBPCR1	(USBH_BA+0x0C8)
+
+/* USBH OHCI Control Registers */
+#define REG_OpModEn	(USBO_BA+0x204)
+/*This bit controls the polarity of over
+*current flag from external power IC.
+*/
+#define OCALow		0x08
+
+#endif /*  __ASM_ARCH_REGS_USB_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/mach-w90p910evb.c linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/mach-w90p910evb.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/mach-w90p910evb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/mach-w90p910evb.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,15 +3,13 @@
  *
  * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
  *
- * Copyright (C) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (C) 2008 Nuvoton technology corporation.
  *
  * Wan ZongShun <mcuos.com@gmail.com>
  *
  * 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.
+ * published by the Free Software Foundation;version 2 of the License.
  *
  */
 
@@ -80,6 +78,156 @@
 	.num_resources	=	ARRAY_SIZE(w90p910_flash_resources),
 };
 
+/* USB EHCI Host Controller */
+
+static struct resource w90x900_usb_ehci_resource[] = {
+	[0] = {
+		.start = W90X900_PA_USBEHCIHOST,
+		.end   = W90X900_PA_USBEHCIHOST + W90X900_SZ_USBEHCIHOST - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH,
+		.end   = IRQ_USBH,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 w90x900_device_usb_ehci_dmamask = 0xffffffffUL;
+
+struct platform_device w90x900_device_usb_ehci = {
+	.name		  = "w90x900-ehci",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(w90x900_usb_ehci_resource),
+	.resource	  = w90x900_usb_ehci_resource,
+	.dev              = {
+		.dma_mask = &w90x900_device_usb_ehci_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+EXPORT_SYMBOL(w90x900_device_usb_ehci);
+
+/* USB OHCI Host Controller */
+
+static struct resource w90x900_usb_ohci_resource[] = {
+	[0] = {
+		.start = W90X900_PA_USBOHCIHOST,
+		.end   = W90X900_PA_USBOHCIHOST + W90X900_SZ_USBOHCIHOST - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH,
+		.end   = IRQ_USBH,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 w90x900_device_usb_ohci_dmamask = 0xffffffffUL;
+struct platform_device w90x900_device_usb_ohci = {
+	.name		  = "w90x900-ohci",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(w90x900_usb_ohci_resource),
+	.resource	  = w90x900_usb_ohci_resource,
+	.dev              = {
+		.dma_mask = &w90x900_device_usb_ohci_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+EXPORT_SYMBOL(w90x900_device_usb_ohci);
+
+/*TouchScreen controller*/
+
+static struct resource w90x900_ts_resource[] = {
+	[0] = {
+		.start = W90X900_PA_ADC,
+		.end   = W90X900_PA_ADC + W90X900_SZ_ADC-1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_ADC,
+		.end   = IRQ_ADC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device w90x900_device_ts = {
+	.name		= "w90x900-ts",
+	.id		= -1,
+	.resource	= w90x900_ts_resource,
+	.num_resources	= ARRAY_SIZE(w90x900_ts_resource),
+};
+EXPORT_SYMBOL(w90x900_device_ts);
+
+/* RTC controller*/
+
+static struct resource w90x900_rtc_resource[] = {
+	[0] = {
+		.start = W90X900_PA_RTC,
+		.end   = W90X900_PA_RTC + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_RTC,
+		.end   = IRQ_RTC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device w90x900_device_rtc = {
+	.name		= "w90x900-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(w90x900_rtc_resource),
+	.resource	= w90x900_rtc_resource,
+};
+EXPORT_SYMBOL(w90x900_device_rtc);
+
+/* KPI controller*/
+
+static struct resource w90x900_kpi_resource[] = {
+	[0] = {
+		.start = W90X900_PA_KPI,
+		.end   = W90X900_PA_KPI + W90X900_SZ_KPI - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_KPI,
+		.end   = IRQ_KPI,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device w90x900_device_kpi = {
+	.name		= "w90x900-kpi",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(w90x900_kpi_resource),
+	.resource	= w90x900_kpi_resource,
+};
+EXPORT_SYMBOL(w90x900_device_kpi);
+
+/* USB Device (Gadget)*/
+
+static struct resource w90x900_usbgadget_resource[] = {
+	[0] = {
+		.start = W90X900_PA_USBDEV,
+		.end   = W90X900_PA_USBDEV + W90X900_SZ_USBDEV - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBD,
+		.end   = IRQ_USBD,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device w90x900_device_usbgadget = {
+	.name		= "w90x900-usbgadget",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(w90x900_usbgadget_resource),
+	.resource	= w90x900_usbgadget_resource,
+};
+EXPORT_SYMBOL(w90x900_device_usbgadget);
+
 static struct map_desc w90p910_iodesc[] __initdata = {
 };
 
@@ -88,12 +236,18 @@
 static struct platform_device *w90p910evb_dev[] __initdata = {
 	&w90p910_serial_device,
 	&w90p910_flash_device,
+	&w90x900_device_usb_ehci,
+	&w90x900_device_usb_ohci,
+	&w90x900_device_ts,
+	&w90x900_device_rtc,
+	&w90x900_device_kpi,
+	&w90x900_device_usbgadget,
 };
 
 static void __init w90p910evb_map_io(void)
 {
 	w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc));
-	w90p910_init_clocks(0);
+	w90p910_init_clocks();
 }
 
 static void __init w90p910evb_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/Makefile linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y				:= irq.o time.o
+obj-y				:= irq.o time.o mfp-w90p910.o gpio.o clock.o
 
 # W90X900 CPU support files
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/mfp-w90p910.c linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/mfp-w90p910.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/mfp-w90p910.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/mfp-w90p910.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-w90x900/mfp-w90p910.c
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#define REG_MFSEL	(W90X900_VA_GCR + 0xC)
+
+#define GPSELF		(0x01 << 1)
+
+#define GPSELC		(0x03 << 2)
+#define ENKPI		(0x02 << 2)
+#define ENNAND		(0x01 << 2)
+
+#define GPSELEI0	(0x01 << 26)
+#define GPSELEI1	(0x01 << 27)
+
+static DECLARE_MUTEX(mfp_sem);
+
+void mfp_set_groupf(struct device *dev)
+{
+	unsigned long mfpen;
+	const char *dev_id;
+
+	BUG_ON(!dev);
+
+	down(&mfp_sem);
+
+	dev_id = dev_name(dev);
+
+	mfpen = __raw_readl(REG_MFSEL);
+
+	if (strcmp(dev_id, "w90p910-emc") == 0)
+		mfpen |= GPSELF;/*enable mac*/
+	else
+		mfpen &= ~GPSELF;/*GPIOF[9:0]*/
+
+	__raw_writel(mfpen, REG_MFSEL);
+
+	up(&mfp_sem);
+}
+EXPORT_SYMBOL(mfp_set_groupf);
+
+void mfp_set_groupc(struct device *dev)
+{
+	unsigned long mfpen;
+	const char *dev_id;
+
+	BUG_ON(!dev);
+
+	down(&mfp_sem);
+
+	dev_id = dev_name(dev);
+
+	mfpen = __raw_readl(REG_MFSEL);
+
+	if (strcmp(dev_id, "w90p910-lcd") == 0)
+		mfpen |= GPSELC;/*enable lcd*/
+	else if (strcmp(dev_id, "w90p910-kpi") == 0) {
+			mfpen &= (~GPSELC);/*enable kpi*/
+			mfpen |= ENKPI;
+		} else if (strcmp(dev_id, "w90p910-nand") == 0) {
+				mfpen &= (~GPSELC);/*enable nand*/
+				mfpen |= ENNAND;
+			} else
+				mfpen &= (~GPSELC);/*GPIOC[14:0]*/
+
+	__raw_writel(mfpen, REG_MFSEL);
+
+	up(&mfp_sem);
+}
+EXPORT_SYMBOL(mfp_set_groupc);
+
+void mfp_set_groupi(struct device *dev, int gpio)
+{
+	unsigned long mfpen;
+	const char *dev_id;
+
+	BUG_ON(!dev);
+
+	down(&mfp_sem);
+
+	dev_id = dev_name(dev);
+
+	mfpen = __raw_readl(REG_MFSEL);
+
+	if (strcmp(dev_id, "w90p910-wdog") == 0)
+		mfpen |= GPSELEI1;/*enable wdog*/
+		else if (strcmp(dev_id, "w90p910-atapi") == 0)
+			mfpen |= GPSELEI0;/*enable atapi*/
+
+	__raw_writel(mfpen, REG_MFSEL);
+
+	up(&mfp_sem);
+}
+EXPORT_SYMBOL(mfp_set_groupi);
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/w90p910.c linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/w90p910.c
--- linux-libre-2.6.30-gnu/arch/arm/mach-w90x900/w90p910.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mach-w90x900/w90p910.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,8 +3,7 @@
  *
  * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks
  *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
+ * Copyright (c) 2008 Nuvoton technology corporation.
  *
  * Wan ZongShun <mcuos.com@gmail.com>
  *
@@ -12,8 +11,7 @@
  *
  * 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.
+ * the Free Software Foundation;version 2 of the License.
  *
  */
 
@@ -36,6 +34,7 @@
 #include <mach/regs-serial.h>
 
 #include "cpu.h"
+#include "clock.h"
 
 /* Initial IO mappings */
 
@@ -45,9 +44,52 @@
 	IODESC_ENT(UART),
 	IODESC_ENT(TIMER),
 	IODESC_ENT(EBI),
+	IODESC_ENT(USBEHCIHOST),
+	IODESC_ENT(USBOHCIHOST),
+	IODESC_ENT(ADC),
+	IODESC_ENT(RTC),
+	IODESC_ENT(KPI),
+	IODESC_ENT(USBDEV),
 	/*IODESC_ENT(LCD),*/
 };
 
+/* Initial clock declarations. */
+static DEFINE_CLK(lcd, 0);
+static DEFINE_CLK(audio, 1);
+static DEFINE_CLK(fmi, 4);
+static DEFINE_CLK(dmac, 5);
+static DEFINE_CLK(atapi, 6);
+static DEFINE_CLK(emc, 7);
+static DEFINE_CLK(usbd, 8);
+static DEFINE_CLK(usbh, 9);
+static DEFINE_CLK(g2d, 10);;
+static DEFINE_CLK(pwm, 18);
+static DEFINE_CLK(ps2, 24);
+static DEFINE_CLK(kpi, 25);
+static DEFINE_CLK(wdt, 26);
+static DEFINE_CLK(gdma, 27);
+static DEFINE_CLK(adc, 28);
+static DEFINE_CLK(usi, 29);
+
+static struct clk_lookup w90p910_clkregs[] = {
+	DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL),
+	DEF_CLKLOOK(&clk_audio, "w90p910-audio", NULL),
+	DEF_CLKLOOK(&clk_fmi, "w90p910-fmi", NULL),
+	DEF_CLKLOOK(&clk_dmac, "w90p910-dmac", NULL),
+	DEF_CLKLOOK(&clk_atapi, "w90p910-atapi", NULL),
+	DEF_CLKLOOK(&clk_emc, "w90p910-emc", NULL),
+	DEF_CLKLOOK(&clk_usbd, "w90p910-usbd", NULL),
+	DEF_CLKLOOK(&clk_usbh, "w90p910-usbh", NULL),
+	DEF_CLKLOOK(&clk_g2d, "w90p910-g2d", NULL),
+	DEF_CLKLOOK(&clk_pwm, "w90p910-pwm", NULL),
+	DEF_CLKLOOK(&clk_ps2, "w90p910-ps2", NULL),
+	DEF_CLKLOOK(&clk_kpi, "w90p910-kpi", NULL),
+	DEF_CLKLOOK(&clk_wdt, "w90p910-wdt", NULL),
+	DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL),
+	DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL),
+	DEF_CLKLOOK(&clk_usi, "w90p910-usi", NULL),
+};
+
 /* Initial serial platform data */
 
 struct plat_serial8250_port w90p910_uart_data[] = {
@@ -77,8 +119,9 @@
 
 /*Init W90P910 clock*/
 
-void __init w90p910_init_clocks(int xtal)
+void __init w90p910_init_clocks(void)
 {
+	clks_register(w90p910_clkregs, ARRAY_SIZE(w90p910_clkregs));
 }
 
 static int __init w90p910_init_cpu(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/Makefile linux-libre-2.6.31-gnu/arch/arm/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,9 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p --no-undefined -X
+ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
+LDFLAGS_vmlinux	+= --be8
+endif
 CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
 OBJCOPYFLAGS	:=-O binary -R .note -R .note.gnu.build-id -R .comment -S
 GZFLAGS		:=-9
@@ -99,64 +102,73 @@
 #Default value
 head-y		:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
 textofs-y	:= 0x00008000
-
- machine-$(CONFIG_ARCH_RPC)	   := rpc
- machine-$(CONFIG_ARCH_EBSA110)	   := ebsa110
- machine-$(CONFIG_FOOTBRIDGE)	   := footbridge
- machine-$(CONFIG_ARCH_SHARK)	   := shark
- machine-$(CONFIG_ARCH_SA1100)	   := sa1100
-ifeq ($(CONFIG_ARCH_SA1100),y)
+textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
 # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
- textofs-$(CONFIG_SA1111)	   := 0x00208000
+ifeq ($(CONFIG_ARCH_SA1100),y)
+textofs-$(CONFIG_SA1111) := 0x00208000
 endif
- machine-$(CONFIG_ARCH_PXA)	   := pxa
- machine-$(CONFIG_ARCH_MMP)	   := mmp
-    plat-$(CONFIG_PLAT_PXA)	   := pxa
- machine-$(CONFIG_ARCH_L7200)	   := l7200
- machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
- machine-$(CONFIG_ARCH_GEMINI)     := gemini
- textofs-$(CONFIG_ARCH_CLPS711X)   := 0x00028000
- machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
- machine-$(CONFIG_ARCH_IOP32X)	   := iop32x
- machine-$(CONFIG_ARCH_IOP33X)	   := iop33x
- machine-$(CONFIG_ARCH_IOP13XX)	   := iop13xx
-    plat-$(CONFIG_PLAT_IOP)	   := iop
- machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
- machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
- machine-$(CONFIG_ARCH_IXP23XX)    := ixp23xx
- machine-$(CONFIG_ARCH_OMAP1)	   := omap1
- machine-$(CONFIG_ARCH_OMAP2)	   := omap2
- machine-$(CONFIG_ARCH_OMAP3)	   := omap2
-    plat-$(CONFIG_ARCH_OMAP)	   := omap
- machine-$(CONFIG_ARCH_S3C2410)	   := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
- machine-$(CONFIG_ARCH_S3C24A0)	   := s3c24a0
-    plat-$(CONFIG_PLAT_S3C24XX)	   := s3c24xx s3c
- machine-$(CONFIG_ARCH_S3C64XX)	   := s3c6400 s3c6410
-    plat-$(CONFIG_PLAT_S3C64XX)	   := s3c64xx s3c
- machine-$(CONFIG_ARCH_LH7A40X)	   := lh7a40x
- machine-$(CONFIG_ARCH_VERSATILE)  := versatile
- machine-$(CONFIG_ARCH_IMX)	   := imx
- machine-$(CONFIG_ARCH_H720X)	   := h720x
- machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
- machine-$(CONFIG_ARCH_REALVIEW)   := realview
- machine-$(CONFIG_ARCH_AT91)	   := at91
- machine-$(CONFIG_ARCH_EP93XX)	   := ep93xx
- machine-$(CONFIG_ARCH_PNX4008)	   := pnx4008
- machine-$(CONFIG_ARCH_NETX)	   := netx
- machine-$(CONFIG_ARCH_NS9XXX)	   := ns9xxx
- machine-$(CONFIG_ARCH_DAVINCI)	   := davinci
- machine-$(CONFIG_ARCH_KIRKWOOD)   := kirkwood
- machine-$(CONFIG_ARCH_KS8695)     := ks8695
-    plat-$(CONFIG_ARCH_MXC)	   := mxc
- machine-$(CONFIG_ARCH_MX2)	   := mx2
- machine-$(CONFIG_ARCH_MX3)	   := mx3
- machine-$(CONFIG_ARCH_MX1)	   := mx1
- machine-$(CONFIG_ARCH_ORION5X)	   := orion5x
-    plat-$(CONFIG_PLAT_ORION)	   := orion
- machine-$(CONFIG_ARCH_MSM)	   := msm
- machine-$(CONFIG_ARCH_LOKI)       := loki
- machine-$(CONFIG_ARCH_MV78XX0)    := mv78xx0
- machine-$(CONFIG_ARCH_W90X900)    := w90x900
+
+# Machine directory name.  This list is sorted alphanumerically
+# by CONFIG_* macro name.
+machine-$(CONFIG_ARCH_AAEC2000)		:= aaec2000
+machine-$(CONFIG_ARCH_AT91)		:= at91
+machine-$(CONFIG_ARCH_CLPS711X)		:= clps711x
+machine-$(CONFIG_ARCH_DAVINCI)		:= davinci
+machine-$(CONFIG_ARCH_EBSA110)		:= ebsa110
+machine-$(CONFIG_ARCH_EP93XX)		:= ep93xx
+machine-$(CONFIG_ARCH_GEMINI)		:= gemini
+machine-$(CONFIG_ARCH_H720X)		:= h720x
+machine-$(CONFIG_ARCH_INTEGRATOR)	:= integrator
+machine-$(CONFIG_ARCH_IOP13XX)		:= iop13xx
+machine-$(CONFIG_ARCH_IOP32X)		:= iop32x
+machine-$(CONFIG_ARCH_IOP33X)		:= iop33x
+machine-$(CONFIG_ARCH_IXP2000)		:= ixp2000
+machine-$(CONFIG_ARCH_IXP23XX)		:= ixp23xx
+machine-$(CONFIG_ARCH_IXP4XX)		:= ixp4xx
+machine-$(CONFIG_ARCH_KIRKWOOD)		:= kirkwood
+machine-$(CONFIG_ARCH_KS8695)		:= ks8695
+machine-$(CONFIG_ARCH_L7200)		:= l7200
+machine-$(CONFIG_ARCH_LH7A40X)		:= lh7a40x
+machine-$(CONFIG_ARCH_LOKI) 		:= loki
+machine-$(CONFIG_ARCH_MMP)		:= mmp
+machine-$(CONFIG_ARCH_MSM)		:= msm
+machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
+machine-$(CONFIG_ARCH_MX1)		:= mx1
+machine-$(CONFIG_ARCH_MX2)		:= mx2
+machine-$(CONFIG_ARCH_MX3)		:= mx3
+machine-$(CONFIG_ARCH_NETX)		:= netx
+machine-$(CONFIG_ARCH_NS9XXX)		:= ns9xxx
+machine-$(CONFIG_ARCH_OMAP1)		:= omap1
+machine-$(CONFIG_ARCH_OMAP2)		:= omap2
+machine-$(CONFIG_ARCH_OMAP3)		:= omap2
+machine-$(CONFIG_ARCH_OMAP4)		:= omap2
+machine-$(CONFIG_ARCH_ORION5X)		:= orion5x
+machine-$(CONFIG_ARCH_PNX4008)		:= pnx4008
+machine-$(CONFIG_ARCH_PXA)		:= pxa
+machine-$(CONFIG_ARCH_REALVIEW)		:= realview
+machine-$(CONFIG_ARCH_RPC)		:= rpc
+machine-$(CONFIG_ARCH_S3C2410)		:= s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
+machine-$(CONFIG_ARCH_S3C24A0)		:= s3c24a0
+machine-$(CONFIG_ARCH_S3C64XX)		:= s3c6400 s3c6410
+machine-$(CONFIG_ARCH_SA1100)		:= sa1100
+machine-$(CONFIG_ARCH_SHARK)		:= shark
+machine-$(CONFIG_ARCH_STMP378X)		:= stmp378x
+machine-$(CONFIG_ARCH_STMP37XX)		:= stmp37xx
+machine-$(CONFIG_ARCH_U300)		:= u300
+machine-$(CONFIG_ARCH_VERSATILE)	:= versatile
+machine-$(CONFIG_ARCH_W90X900)		:= w90x900
+machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
+
+# Platform directory name.  This list is sorted alphanumerically
+# by CONFIG_* macro name.
+plat-$(CONFIG_ARCH_MXC)		:= mxc
+plat-$(CONFIG_ARCH_OMAP)	:= omap
+plat-$(CONFIG_PLAT_IOP)		:= iop
+plat-$(CONFIG_PLAT_ORION)	:= orion
+plat-$(CONFIG_PLAT_PXA)		:= pxa
+plat-$(CONFIG_PLAT_S3C24XX)	:= s3c24xx s3c
+plat-$(CONFIG_PLAT_S3C64XX)	:= s3c64xx s3c
+plat-$(CONFIG_ARCH_STMP3XXX)	:= stmp3xxx
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/abort-ev6.S linux-libre-2.6.31-gnu/arch/arm/mm/abort-ev6.S
--- linux-libre-2.6.30-gnu/arch/arm/mm/abort-ev6.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/abort-ev6.S	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,9 @@
 	movne	pc, lr
 	do_thumb_abort
 	ldreq	r3, [r2]			@ read aborted ARM instruction
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	reveq	r3, r3
+#endif
 	do_ldrd_abort
 	tst	r3, #1 << 20			@ L = 0 -> write
 	orreq	r1, r1, #1 << 11		@ yes.
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/alignment.c linux-libre-2.6.31-gnu/arch/arm/mm/alignment.c
--- linux-libre-2.6.30-gnu/arch/arm/mm/alignment.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/alignment.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,12 @@
 #define SHIFT_ASR	0x40
 #define SHIFT_RORRRX	0x60
 
+#define BAD_INSTR 	0xdeadc0de
+
+/* Thumb-2 32 bit format per ARMv7 DDI0406A A6.3, either f800h,e800h,f800h */
+#define IS_T32(hi16) \
+	(((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800))
+
 static unsigned long ai_user;
 static unsigned long ai_sys;
 static unsigned long ai_skipped;
@@ -332,38 +338,48 @@
 		      struct pt_regs *regs)
 {
 	unsigned int rd = RD_BITS(instr);
+	unsigned int rd2;
+	int load;
 
-	if (((rd & 1) == 1) || (rd == 14))
+	if ((instr & 0xfe000000) == 0xe8000000) {
+		/* ARMv7 Thumb-2 32-bit LDRD/STRD */
+		rd2 = (instr >> 8) & 0xf;
+		load = !!(LDST_L_BIT(instr));
+	} else if (((rd & 1) == 1) || (rd == 14))
 		goto bad;
+	else {
+		load = ((instr & 0xf0) == 0xd0);
+		rd2 = rd + 1;
+	}
 
 	ai_dword += 1;
 
 	if (user_mode(regs))
 		goto user;
 
-	if ((instr & 0xf0) == 0xd0) {
+	if (load) {
 		unsigned long val;
 		get32_unaligned_check(val, addr);
 		regs->uregs[rd] = val;
 		get32_unaligned_check(val, addr + 4);
-		regs->uregs[rd + 1] = val;
+		regs->uregs[rd2] = val;
 	} else {
 		put32_unaligned_check(regs->uregs[rd], addr);
-		put32_unaligned_check(regs->uregs[rd + 1], addr + 4);
+		put32_unaligned_check(regs->uregs[rd2], addr + 4);
 	}
 
 	return TYPE_LDST;
 
  user:
-	if ((instr & 0xf0) == 0xd0) {
+	if (load) {
 		unsigned long val;
 		get32t_unaligned_check(val, addr);
 		regs->uregs[rd] = val;
 		get32t_unaligned_check(val, addr + 4);
-		regs->uregs[rd + 1] = val;
+		regs->uregs[rd2] = val;
 	} else {
 		put32t_unaligned_check(regs->uregs[rd], addr);
-		put32t_unaligned_check(regs->uregs[rd + 1], addr + 4);
+		put32t_unaligned_check(regs->uregs[rd2], addr + 4);
 	}
 
 	return TYPE_LDST;
@@ -616,10 +632,74 @@
 		/* Else fall through for illegal instruction case */
 
 	default:
-		return 0xdeadc0de;
+		return BAD_INSTR;
 	}
 }
 
+/*
+ * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction
+ * handlable by ARM alignment handler, also find the corresponding handler,
+ * so that we can reuse ARM userland alignment fault fixups for Thumb.
+ *
+ * @pinstr: original Thumb-2 instruction; returns new handlable instruction
+ * @regs: register context.
+ * @poffset: return offset from faulted addr for later writeback
+ *
+ * NOTES:
+ * 1. Comments below refer to ARMv7 DDI0406A Thumb Instruction sections.
+ * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt)
+ */
+static void *
+do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
+			    union offset_union *poffset)
+{
+	unsigned long instr = *pinstr;
+	u16 tinst1 = (instr >> 16) & 0xffff;
+	u16 tinst2 = instr & 0xffff;
+	poffset->un = 0;
+
+	switch (tinst1 & 0xffe0) {
+	/* A6.3.5 Load/Store multiple */
+	case 0xe880:		/* STM/STMIA/STMEA,LDM/LDMIA, PUSH/POP T2 */
+	case 0xe8a0:		/* ...above writeback version */
+	case 0xe900:		/* STMDB/STMFD, LDMDB/LDMEA */
+	case 0xe920:		/* ...above writeback version */
+		/* no need offset decision since handler calculates it */
+		return do_alignment_ldmstm;
+
+	case 0xf840:		/* POP/PUSH T3 (single register) */
+		if (RN_BITS(instr) == 13 && (tinst2 & 0x09ff) == 0x0904) {
+			u32 L = !!(LDST_L_BIT(instr));
+			const u32 subset[2] = {
+				0xe92d0000,	/* STMDB sp!,{registers} */
+				0xe8bd0000,	/* LDMIA sp!,{registers} */
+			};
+			*pinstr = subset[L] | (1<<RD_BITS(instr));
+			return do_alignment_ldmstm;
+		}
+		/* Else fall through for illegal instruction case */
+		break;
+
+	/* A6.3.6 Load/store double, STRD/LDRD(immed, lit, reg) */
+	case 0xe860:
+	case 0xe960:
+	case 0xe8e0:
+	case 0xe9e0:
+		poffset->un = (tinst2 & 0xff) << 2;
+	case 0xe940:
+	case 0xe9c0:
+		return do_alignment_ldrdstrd;
+
+	/*
+	 * No need to handle load/store instructions up to word size
+	 * since ARMv6 and later CPUs can perform unaligned accesses.
+	 */
+	default:
+		break;
+	}
+	return NULL;
+}
+
 static int
 do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
@@ -630,6 +710,8 @@
 	mm_segment_t fs;
 	unsigned int fault;
 	u16 tinstr = 0;
+	int isize = 4;
+	int thumb2_32b = 0;
 
 	instrptr = instruction_pointer(regs);
 
@@ -637,8 +719,19 @@
 	set_fs(KERNEL_DS);
 	if (thumb_mode(regs)) {
 		fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
-		if (!(fault))
-			instr = thumb2arm(tinstr);
+		if (!fault) {
+			if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
+			    IS_T32(tinstr)) {
+				/* Thumb-2 32-bit */
+				u16 tinst2 = 0;
+				fault = __get_user(tinst2, (u16 *)(instrptr+2));
+				instr = (tinstr << 16) | tinst2;
+				thumb2_32b = 1;
+			} else {
+				isize = 2;
+				instr = thumb2arm(tinstr);
+			}
+		}
 	} else
 		fault = __get_user(instr, (u32 *)instrptr);
 	set_fs(fs);
@@ -655,7 +748,7 @@
 
  fixup:
 
-	regs->ARM_pc += thumb_mode(regs) ? 2 : 4;
+	regs->ARM_pc += isize;
 
 	switch (CODING_BITS(instr)) {
 	case 0x00000000:	/* 3.13.4 load/store instruction extensions */
@@ -714,18 +807,25 @@
 		handler = do_alignment_ldrstr;
 		break;
 
-	case 0x08000000:	/* ldm or stm */
-		handler = do_alignment_ldmstm;
+	case 0x08000000:	/* ldm or stm, or thumb-2 32bit instruction */
+		if (thumb2_32b)
+			handler = do_alignment_t32_to_handler(&instr, regs, &offset);
+		else
+			handler = do_alignment_ldmstm;
 		break;
 
 	default:
 		goto bad;
 	}
 
+	if (!handler)
+		goto bad;
 	type = handler(addr, instr, regs);
 
-	if (type == TYPE_ERROR || type == TYPE_FAULT)
+	if (type == TYPE_ERROR || type == TYPE_FAULT) {
+		regs->ARM_pc -= isize;
 		goto bad_or_fault;
+	}
 
 	if (type == TYPE_LDST)
 		do_alignment_finish_ldst(addr, instr, regs, offset);
@@ -735,7 +835,6 @@
  bad_or_fault:
 	if (type == TYPE_ERROR)
 		goto bad;
-	regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
 	/*
 	 * We got a fault - fix it up, or die.
 	 */
@@ -751,8 +850,8 @@
 	 */
 	printk(KERN_ERR "Alignment trap: not handling instruction "
 		"%0*lx at [<%08lx>]\n",
-		thumb_mode(regs) ? 4 : 8,
-		thumb_mode(regs) ? tinstr : instr, instrptr);
+		isize << 1,
+		isize == 2 ? tinstr : instr, instrptr);
 	ai_skipped += 1;
 	return 1;
 
@@ -763,8 +862,8 @@
 		printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
 		       "Address=0x%08lx FSR 0x%03x\n", current->comm,
 			task_pid_nr(current), instrptr,
-		        thumb_mode(regs) ? 4 : 8,
-		        thumb_mode(regs) ? tinstr : instr,
+			isize << 1,
+			isize == 2 ? tinstr : instr,
 		        addr, fsr);
 
 	if (ai_usermode & UM_FIXUP)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/fault.c linux-libre-2.6.31-gnu/arch/arm/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/arm/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -208,7 +208,7 @@
 	 * than endlessly redo the fault.
 	 */
 survive:
-	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, fsr & (1 << 11));
+	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, (fsr & (1 << 11)) ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/init.c linux-libre-2.6.31-gnu/arch/arm/mm/init.c
--- linux-libre-2.6.30-gnu/arch/arm/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -120,6 +120,32 @@
 	printk("%d pages swap cached\n", cached);
 }
 
+static void __init find_node_limits(int node, struct meminfo *mi,
+	unsigned long *min, unsigned long *max_low, unsigned long *max_high)
+{
+	int i;
+
+	*min = -1UL;
+	*max_low = *max_high = 0;
+
+	for_each_nodebank(i, mi, node) {
+		struct membank *bank = &mi->bank[i];
+		unsigned long start, end;
+
+		start = bank_pfn_start(bank);
+		end = bank_pfn_end(bank);
+
+		if (*min > start)
+			*min = start;
+		if (*max_high < end)
+			*max_high = end;
+		if (bank->highmem)
+			continue;
+		if (*max_low < end)
+			*max_low = end;
+	}
+}
+
 /*
  * FIXME: We really want to avoid allocating the bootmap bitmap
  * over the top of the initrd.  Hopefully, this is located towards
@@ -210,41 +236,25 @@
 #endif
 }
 
-static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
+static void __init bootmem_init_node(int node, struct meminfo *mi,
+	unsigned long start_pfn, unsigned long end_pfn)
 {
-	unsigned long start_pfn, end_pfn, boot_pfn;
+	unsigned long boot_pfn;
 	unsigned int boot_pages;
 	pg_data_t *pgdat;
 	int i;
 
-	start_pfn = -1UL;
-	end_pfn = 0;
-
 	/*
-	 * Calculate the pfn range, and map the memory banks for this node.
+	 * Map the memory banks for this node.
 	 */
 	for_each_nodebank(i, mi, node) {
 		struct membank *bank = &mi->bank[i];
-		unsigned long start, end;
-
-		start = bank_pfn_start(bank);
-		end = bank_pfn_end(bank);
-
-		if (start_pfn > start)
-			start_pfn = start;
-		if (end_pfn < end)
-			end_pfn = end;
 
-		map_memory_bank(bank);
+		if (!bank->highmem)
+			map_memory_bank(bank);
 	}
 
 	/*
-	 * If there is no memory in this node, ignore it.
-	 */
-	if (end_pfn == 0)
-		return end_pfn;
-
-	/*
 	 * Allocate the bootmem bitmap page.
 	 */
 	boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
@@ -260,7 +270,8 @@
 
 	for_each_nodebank(i, mi, node) {
 		struct membank *bank = &mi->bank[i];
-		free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
+		if (!bank->highmem)
+			free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
 		memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
 	}
 
@@ -269,8 +280,6 @@
 	 */
 	reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
 			     boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
-
-	return end_pfn;
 }
 
 static void __init bootmem_reserve_initrd(int node)
@@ -297,33 +306,39 @@
 static void __init bootmem_free_node(int node, struct meminfo *mi)
 {
 	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
-	unsigned long start_pfn, end_pfn;
-	pg_data_t *pgdat = NODE_DATA(node);
+	unsigned long min, max_low, max_high;
 	int i;
 
-	start_pfn = pgdat->bdata->node_min_pfn;
-	end_pfn = pgdat->bdata->node_low_pfn;
+	find_node_limits(node, mi, &min, &max_low, &max_high);
 
 	/*
 	 * initialise the zones within this node.
 	 */
 	memset(zone_size, 0, sizeof(zone_size));
-	memset(zhole_size, 0, sizeof(zhole_size));
 
 	/*
 	 * The size of this node has already been determined.  If we need
 	 * to do anything fancy with the allocation of this memory to the
 	 * zones, now is the time to do it.
 	 */
-	zone_size[0] = end_pfn - start_pfn;
+	zone_size[0] = max_low - min;
+#ifdef CONFIG_HIGHMEM
+	zone_size[ZONE_HIGHMEM] = max_high - max_low;
+#endif
 
 	/*
 	 * For each bank in this node, calculate the size of the holes.
 	 *  holes = node_size - sum(bank_sizes_in_node)
 	 */
-	zhole_size[0] = zone_size[0];
-	for_each_nodebank(i, mi, node)
-		zhole_size[0] -= bank_pfn_size(&mi->bank[i]);
+	memcpy(zhole_size, zone_size, sizeof(zhole_size));
+	for_each_nodebank(i, mi, node) {
+		int idx = 0;
+#ifdef CONFIG_HIGHMEM
+		if (mi->bank[i].highmem)
+			idx = ZONE_HIGHMEM;
+#endif
+		zhole_size[idx] -= bank_pfn_size(&mi->bank[i]);
+	}
 
 	/*
 	 * Adjust the sizes according to any special requirements for
@@ -331,13 +346,13 @@
 	 */
 	arch_adjust_zones(node, zone_size, zhole_size);
 
-	free_area_init_node(node, zone_size, start_pfn, zhole_size);
+	free_area_init_node(node, zone_size, min, zhole_size);
 }
 
 void __init bootmem_init(void)
 {
 	struct meminfo *mi = &meminfo;
-	unsigned long memend_pfn = 0;
+	unsigned long min, max_low, max_high;
 	int node, initrd_node;
 
 	/*
@@ -345,11 +360,29 @@
 	 */
 	initrd_node = check_initrd(mi);
 
+	max_low = max_high = 0;
+
 	/*
 	 * Run through each node initialising the bootmem allocator.
 	 */
 	for_each_node(node) {
-		unsigned long end_pfn = bootmem_init_node(node, mi);
+		unsigned long node_low, node_high;
+
+		find_node_limits(node, mi, &min, &node_low, &node_high);
+
+		if (node_low > max_low)
+			max_low = node_low;
+		if (node_high > max_high)
+			max_high = node_high;
+
+		/*
+		 * If there is no memory in this node, ignore it.
+		 * (We can't have nodes which have no lowmem)
+		 */
+		if (node_low == 0)
+			continue;
+
+		bootmem_init_node(node, mi, min, node_low);
 
 		/*
 		 * Reserve any special node zero regions.
@@ -362,12 +395,6 @@
 		 */
 		if (node == initrd_node)
 			bootmem_reserve_initrd(node);
-
-		/*
-		 * Remember the highest memory PFN.
-		 */
-		if (end_pfn > memend_pfn)
-			memend_pfn = end_pfn;
 	}
 
 	/*
@@ -383,7 +410,7 @@
 	for_each_node(node)
 		bootmem_free_node(node, mi);
 
-	high_memory = __va((memend_pfn << PAGE_SHIFT) - 1) + 1;
+	high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
 
 	/*
 	 * This doesn't seem to be used by the Linux memory manager any
@@ -393,7 +420,8 @@
 	 * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
 	 * the system, not the maximum PFN.
 	 */
-	max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET;
+	max_low_pfn = max_low - PHYS_PFN_OFFSET;
+	max_pfn = max_high - PHYS_PFN_OFFSET;
 }
 
 static inline int free_area(unsigned long pfn, unsigned long end, char *s)
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/ioremap.c linux-libre-2.6.31-gnu/arch/arm/mm/ioremap.c
--- linux-libre-2.6.30-gnu/arch/arm/mm/ioremap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/ioremap.c	2009-09-09 18:13:59.000000000 -0400
@@ -110,6 +110,12 @@
 	return err;
 }
 
+int ioremap_page(unsigned long virt, unsigned long phys,
+		 const struct mem_type *mtype)
+{
+	return remap_area_pages(virt, __phys_to_pfn(phys), PAGE_SIZE, mtype);
+}
+EXPORT_SYMBOL(ioremap_page);
 
 void __check_kvm_seq(struct mm_struct *mm)
 {
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/Kconfig linux-libre-2.6.31-gnu/arch/arm/mm/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/mm/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -391,7 +391,7 @@
 
 # ARMv6
 config CPU_V6
-	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB
+	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
 	select CPU_32v6
 	select CPU_ABRT_EV6
 	select CPU_PABRT_NOIFAR
@@ -416,7 +416,7 @@
 
 # ARMv7
 config CPU_V7
-	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB
+	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
 	select CPU_32v6K
 	select CPU_32v7
 	select CPU_ABRT_EV7
@@ -639,10 +639,23 @@
 	  port must properly enable any big-endian related features
 	  of your chipset/board/processor.
 
+config CPU_ENDIAN_BE8
+	bool
+	depends on CPU_BIG_ENDIAN
+	default CPU_V6 || CPU_V7
+	help
+	  Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors.
+
+config CPU_ENDIAN_BE32
+	bool
+	depends on CPU_BIG_ENDIAN
+	default !CPU_ENDIAN_BE8
+	help
+	  Support for the BE-32 (big-endian) mode on pre-ARMv6 processors.
+
 config CPU_HIGH_VECTOR
 	depends on !MMU && CPU_CP15 && !CPU_ARM740T
 	bool "Select the High exception vector"
-	default n
 	help
 	  Say Y here to select high exception vector(0xFFFF0000~).
 	  The exception vector can be vary depending on the platform
@@ -726,7 +739,6 @@
 
 config OUTER_CACHE
 	bool
-	default n
 
 config CACHE_FEROCEON_L2
 	bool "Enable the Feroceon L2 cache controller"
@@ -739,7 +751,6 @@
 config CACHE_FEROCEON_L2_WRITETHROUGH
 	bool "Force Feroceon L2 cache write through"
 	depends on CACHE_FEROCEON_L2
-	default n
 	help
 	  Say Y here to use the Feroceon L2 cache in writethrough mode.
 	  Unless you specifically require this, say N for writeback mode.
@@ -747,7 +758,7 @@
 config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
-		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31
+		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX
 	default y
 	select OUTER_CACHE
 	help
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/mmu.c linux-libre-2.6.31-gnu/arch/arm/mm/mmu.c
--- linux-libre-2.6.30-gnu/arch/arm/mm/mmu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/mmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -255,6 +255,7 @@
 {
 	return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL;
 }
+EXPORT_SYMBOL(get_mem_type);
 
 /*
  * Adjust the PMD section entries according to the CPU in use.
@@ -686,13 +687,19 @@
 
 static void __init sanity_check_meminfo(void)
 {
-	int i, j;
+	int i, j, highmem = 0;
 
 	for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
 		struct membank *bank = &meminfo.bank[j];
 		*bank = meminfo.bank[i];
 
 #ifdef CONFIG_HIGHMEM
+		if (__va(bank->start) > VMALLOC_MIN ||
+		    __va(bank->start) < (void *)PAGE_OFFSET)
+			highmem = 1;
+
+		bank->highmem = highmem;
+
 		/*
 		 * Split those memory banks which are partially overlapping
 		 * the vmalloc area greatly simplifying things later.
@@ -713,6 +720,7 @@
 				i++;
 				bank[1].size -= VMALLOC_MIN - __va(bank->start);
 				bank[1].start = __pa(VMALLOC_MIN - 1) + 1;
+				bank[1].highmem = highmem = 1;
 				j++;
 			}
 			bank->size = VMALLOC_MIN - __va(bank->start);
@@ -835,10 +843,31 @@
 				BOOTMEM_EXCLUSIVE);
 	}
 
+	if (machine_is_treo680()) {
+		reserve_bootmem_node(pgdat, 0xa0000000, 0x1000,
+				BOOTMEM_EXCLUSIVE);
+		reserve_bootmem_node(pgdat, 0xa2000000, 0x1000,
+				BOOTMEM_EXCLUSIVE);
+	}
+
 	if (machine_is_palmt5())
 		reserve_bootmem_node(pgdat, 0xa0200000, 0x1000,
 				BOOTMEM_EXCLUSIVE);
 
+	/*
+	 * U300 - This platform family can share physical memory
+	 * between two ARM cpus, one running Linux and the other
+	 * running another OS.
+	 */
+	if (machine_is_u300()) {
+#ifdef CONFIG_MACH_U300_SINGLE_RAM
+#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) &&	\
+	CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
+		res_size = 0x00100000;
+#endif
+#endif
+	}
+
 #ifdef CONFIG_SA1111
 	/*
 	 * Because of the SA1111 DMA bug, we want to preserve our
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/proc-syms.c linux-libre-2.6.31-gnu/arch/arm/mm/proc-syms.c
--- linux-libre-2.6.30-gnu/arch/arm/mm/proc-syms.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/proc-syms.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 EXPORT_SYMBOL(__cpuc_flush_user_all);
 EXPORT_SYMBOL(__cpuc_flush_user_range);
 EXPORT_SYMBOL(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL(__cpuc_flush_dcache_page);
 EXPORT_SYMBOL(dmac_inv_range);  /* because of flush_ioremap_region() */
 #else
 EXPORT_SYMBOL(cpu_cache);
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/proc-v6.S linux-libre-2.6.31-gnu/arch/arm/mm/proc-v6.S
--- linux-libre-2.6.30-gnu/arch/arm/mm/proc-v6.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/proc-v6.S	2009-09-09 18:13:59.000000000 -0400
@@ -170,6 +170,9 @@
 #endif /* CONFIG_MMU */
 	adr	r5, v6_crval
 	ldmia	r5, {r5, r6}
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	orr	r6, r6, #1 << 25		@ big-endian page tables
+#endif
 	mrc	p15, 0, r0, c1, c0, 0		@ read control register
 	bic	r0, r0, r5			@ clear bits them
 	orr	r0, r0, r6			@ set them
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/proc-v7.S linux-libre-2.6.31-gnu/arch/arm/mm/proc-v7.S
--- linux-libre-2.6.30-gnu/arch/arm/mm/proc-v7.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/proc-v7.S	2009-09-09 18:13:59.000000000 -0400
@@ -19,17 +19,23 @@
 
 #include "proc-macros.S"
 
-#define TTB_C		(1 << 0)
 #define TTB_S		(1 << 1)
 #define TTB_RGN_NC	(0 << 3)
 #define TTB_RGN_OC_WBWA	(1 << 3)
 #define TTB_RGN_OC_WT	(2 << 3)
 #define TTB_RGN_OC_WB	(3 << 3)
+#define TTB_NOS		(1 << 5)
+#define TTB_IRGN_NC	((0 << 0) | (0 << 6))
+#define TTB_IRGN_WBWA	((0 << 0) | (1 << 6))
+#define TTB_IRGN_WT	((1 << 0) | (0 << 6))
+#define TTB_IRGN_WB	((1 << 0) | (1 << 6))
 
 #ifndef CONFIG_SMP
-#define TTB_FLAGS	TTB_C|TTB_RGN_OC_WB		@ mark PTWs cacheable, outer WB
+/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
+#define TTB_FLAGS	TTB_IRGN_WB|TTB_RGN_OC_WB
 #else
-#define TTB_FLAGS	TTB_C|TTB_S|TTB_RGN_OC_WBWA	@ mark PTWs cacheable and shared, outer WBWA
+/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
+#define TTB_FLAGS	TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
 #endif
 
 ENTRY(cpu_v7_proc_init)
@@ -176,8 +182,8 @@
  */
 __v7_setup:
 #ifdef CONFIG_SMP
-	mrc	p15, 0, r0, c1, c0, 1		@ Enable SMP/nAMP mode
-	orr	r0, r0, #(0x1 << 6)
+	mrc	p15, 0, r0, c1, c0, 1		@ Enable SMP/nAMP mode and
+	orr	r0, r0, #(1 << 6) | (1 << 0)	@ TLB ops broadcasting
 	mcr	p15, 0, r0, c1, c0, 1
 #endif
 	adr	r12, __v7_setup_stack		@ the local stack
@@ -227,12 +233,43 @@
 	mov	r10, #0x1f			@ domains 0, 1 = manager
 	mcr	p15, 0, r10, c3, c0, 0		@ load domain access register
 #endif
-	ldr	r5, =0xff0aa1a8
-	ldr	r6, =0x40e040e0
+	/*
+	 * Memory region attributes with SCTLR.TRE=1
+	 *
+	 *   n = TEX[0],C,B
+	 *   TR = PRRR[2n+1:2n]		- memory type
+	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
+	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
+	 *
+	 *			n	TR	IR	OR
+	 *   UNCACHED		000	00
+	 *   BUFFERABLE		001	10	00	00
+	 *   WRITETHROUGH	010	10	10	10
+	 *   WRITEBACK		011	10	11	11
+	 *   reserved		110
+	 *   WRITEALLOC		111	10	01	01
+	 *   DEV_SHARED		100	01
+	 *   DEV_NONSHARED	100	01
+	 *   DEV_WC		001	10
+	 *   DEV_CACHED		011	10
+	 *
+	 * Other attributes:
+	 *
+	 *   DS0 = PRRR[16] = 0		- device shareable property
+	 *   DS1 = PRRR[17] = 1		- device shareable property
+	 *   NS0 = PRRR[18] = 0		- normal shareable property
+	 *   NS1 = PRRR[19] = 1		- normal shareable property
+	 *   NOS = PRRR[24+n] = 1	- not outer shareable
+	 */
+	ldr	r5, =0xff0a81a8			@ PRRR
+	ldr	r6, =0x40e040e0			@ NMRR
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 	adr	r5, v7_crval
 	ldmia	r5, {r5, r6}
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	orr	r6, r6, #1 << 25		@ big-endian page tables
+#endif
    	mrc	p15, 0, r0, c1, c0, 0		@ read control register
 	bic	r0, r0, r5			@ clear bits them
 	orr	r0, r0, r6			@ set them
@@ -240,14 +277,14 @@
 ENDPROC(__v7_setup)
 
 	/*   AT
-	 *  TFR   EV X F   I D LR
-	 * .EEE ..EE PUI. .T.T 4RVI ZFRS BLDP WCAM
+	 *  TFR   EV X F   I D LR    S
+	 * .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM
 	 * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
-	 *    1    0 110       0011 1.00 .111 1101 < we want
+	 *    1    0 110       0011 1100 .111 1101 < we want
 	 */
 	.type	v7_crval, #object
 v7_crval:
-	crval	clear=0x0120c302, mmuset=0x10c0387d, ucset=0x00c0187c
+	crval	clear=0x0120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c
 
 __v7_setup_stack:
 	.space	4 * 11				@ 11 registers
diff -druN linux-libre-2.6.30-gnu/arch/arm/mm/tlb-v7.S linux-libre-2.6.31-gnu/arch/arm/mm/tlb-v7.S
--- linux-libre-2.6.30-gnu/arch/arm/mm/tlb-v7.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/mm/tlb-v7.S	2009-09-09 18:13:59.000000000 -0400
@@ -42,9 +42,11 @@
 	mov	r1, r1, lsl #PAGE_SHIFT
 	vma_vm_flags r2, r2			@ get vma->vm_flags
 1:
-	mcr	p15, 0, r0, c8, c6, 1		@ TLB invalidate D MVA (was 1)
-	tst	r2, #VM_EXEC			@ Executable area ?
-	mcrne	p15, 0, r0, c8, c5, 1		@ TLB invalidate I MVA (was 1)
+#ifdef CONFIG_SMP
+	mcr	p15, 0, r0, c8, c3, 1		@ TLB invalidate U MVA (shareable) 
+#else
+	mcr	p15, 0, r0, c8, c7, 1		@ TLB invalidate U MVA
+#endif
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
@@ -69,8 +71,11 @@
 	mov	r0, r0, lsl #PAGE_SHIFT
 	mov	r1, r1, lsl #PAGE_SHIFT
 1:
-	mcr	p15, 0, r0, c8, c6, 1		@ TLB invalidate D MVA
-	mcr	p15, 0, r0, c8, c5, 1		@ TLB invalidate I MVA
+#ifdef CONFIG_SMP
+	mcr	p15, 0, r0, c8, c3, 1		@ TLB invalidate U MVA (shareable)
+#else
+	mcr	p15, 0, r0, c8, c7, 1		@ TLB invalidate U MVA
+#endif
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
 	blo	1b
@@ -87,5 +92,5 @@
 ENTRY(v7wbi_tlb_fns)
 	.long	v7wbi_flush_user_tlb_range
 	.long	v7wbi_flush_kern_tlb_range
-	.long	v6wbi_tlb_flags
+	.long	v7wbi_tlb_flags
 	.size	v7wbi_tlb_fns, . - v7wbi_tlb_fns
diff -druN linux-libre-2.6.30-gnu/arch/arm/oprofile/op_model_mpcore.c linux-libre-2.6.31-gnu/arch/arm/oprofile/op_model_mpcore.c
--- linux-libre-2.6.30-gnu/arch/arm/oprofile/op_model_mpcore.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/oprofile/op_model_mpcore.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <mach/hardware.h>
+#include <mach/board-eb.h>
 #include <asm/system.h>
 
 #include "op_counter.h"
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-mxc/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,6 +64,8 @@
 	_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
 }
 
+static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
+
 static int gpio_set_irq_type(u32 irq, u32 type)
 {
 	u32 gpio = irq_to_gpio(irq);
@@ -72,6 +74,7 @@
 	int edge;
 	void __iomem *reg = port->base;
 
+	port->both_edges &= ~(1 << (gpio & 31));
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
 		edge = GPIO_INT_RISE_EDGE;
@@ -79,13 +82,24 @@
 	case IRQ_TYPE_EDGE_FALLING:
 		edge = GPIO_INT_FALL_EDGE;
 		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		val = mxc_gpio_get(&port->chip, gpio & 31);
+		if (val) {
+			edge = GPIO_INT_LOW_LEV;
+			pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
+		} else {
+			edge = GPIO_INT_HIGH_LEV;
+			pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
+		}
+		port->both_edges |= 1 << (gpio & 31);
+		break;
 	case IRQ_TYPE_LEVEL_LOW:
 		edge = GPIO_INT_LOW_LEV;
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
 		edge = GPIO_INT_HIGH_LEV;
 		break;
-	default:	/* this includes IRQ_TYPE_EDGE_BOTH */
+	default:
 		return -EINVAL;
 	}
 
@@ -98,6 +112,34 @@
 	return 0;
 }
 
+static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
+{
+	void __iomem *reg = port->base;
+	u32 bit, val;
+	int edge;
+
+	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+	bit = gpio & 0xf;
+	val = __raw_readl(reg);
+	edge = (val >> (bit << 1)) & 3;
+	val &= ~(0x3 << (bit << 1));
+	switch (edge) {
+	case GPIO_INT_HIGH_LEV:
+		edge = GPIO_INT_LOW_LEV;
+		pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
+		break;
+	case GPIO_INT_LOW_LEV:
+		edge = GPIO_INT_HIGH_LEV;
+		pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
+		break;
+	default:
+		pr_err("mxc: invalid configuration for GPIO %d: %x\n",
+		       gpio, edge);
+		return;
+	}
+	__raw_writel(val | (edge << (bit << 1)), reg);
+}
+
 /* handle n interrupts in one status register */
 static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 {
@@ -105,11 +147,16 @@
 
 	gpio_irq_no = port->virtual_irq_start;
 	for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
+		u32 gpio = irq_to_gpio(gpio_irq_no);
 
 		if ((irq_stat & 1) == 0)
 			continue;
 
 		BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
+
+		if (port->both_edges & (1 << (gpio & 31)))
+			mxc_flip_edge(port, gpio);
+
 		irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
 				&irq_desc[gpio_irq_no]);
 	}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>.
+ * All Rights Reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_ARMADILLO5X0_H__
+#define __ASM_ARCH_MXC_BOARD_ARMADILLO5X0_H__
+
+#include <mach/hardware.h>
+
+/* mandatory for CONFIG_DEBUG_LL */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx21ads.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx21ads.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx21ads.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx21ads.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX21ADS_H__
+#define __ASM_ARCH_MXC_BOARD_MX21ADS_H__
+
+/*
+ * MXC UART EVB board level configurations
+ */
+#define MXC_LL_UART_PADDR       UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR       AIPI_IO_ADDRESS(UART1_BASE_ADDR)
+
+/*
+ * Memory-mapped I/O on MX21ADS base board
+ */
+#define MX21ADS_MMIO_BASE_ADDR   0xF5000000
+#define MX21ADS_MMIO_SIZE        SZ_16M
+
+#define MX21ADS_REG_ADDR(offset)    (void __force __iomem *) \
+		(MX21ADS_MMIO_BASE_ADDR + (offset))
+
+#define MX21ADS_CS8900A_IRQ         IRQ_GPIOE(11)
+#define MX21ADS_CS8900A_IOBASE_REG  MX21ADS_REG_ADDR(0x000000)
+#define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000)
+#define MX21ADS_VERSION_REG         MX21ADS_REG_ADDR(0x400000)
+#define MX21ADS_IO_REG              MX21ADS_REG_ADDR(0x800000)
+
+/* MX21ADS_IO_REG bit definitions */
+#define MX21ADS_IO_SD_WP        0x0001 /* read */
+#define MX21ADS_IO_TP6          0x0001 /* write */
+#define MX21ADS_IO_SW_SEL       0x0002 /* read */
+#define MX21ADS_IO_TP7          0x0002 /* write */
+#define MX21ADS_IO_RESET_E_UART 0x0004
+#define MX21ADS_IO_RESET_BASE   0x0008
+#define MX21ADS_IO_CSI_CTL2     0x0010
+#define MX21ADS_IO_CSI_CTL1     0x0020
+#define MX21ADS_IO_CSI_CTL0     0x0040
+#define MX21ADS_IO_UART1_EN     0x0080
+#define MX21ADS_IO_UART4_EN     0x0100
+#define MX21ADS_IO_LCDON        0x0200
+#define MX21ADS_IO_IRDA_EN      0x0400
+#define MX21ADS_IO_IRDA_FIR_SEL 0x0800
+#define MX21ADS_IO_IRDA_MD0_B   0x1000
+#define MX21ADS_IO_IRDA_MD1     0x2000
+#define MX21ADS_IO_LED4_ON      0x4000
+#define MX21ADS_IO_LED3_ON      0x8000
+
+#endif				/* __ASM_ARCH_MXC_BOARD_MX21ADS_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx27lite.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx27lite.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx27lite.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx27lite.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX27LITE_H__
+#define __ASM_ARCH_MXC_BOARD_MX27LITE_H__
+
+/* mandatory for CONFIG_DEBUG_LL */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX27LITE_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx27pdk.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx27pdk.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx27pdk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx27pdk.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX27PDK_H__
+#define __ASM_ARCH_MXC_BOARD_MX27PDK_H__
+
+/* mandatory for CONFIG_DEBUG_LL */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX27PDK_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31ads.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31ads.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31ads.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31ads.h	2009-09-09 18:13:59.000000000 -0400
@@ -114,7 +114,7 @@
 
 #define MXC_MAX_EXP_IO_LINES	16
 
-/* mandatory for CONFIG_LL_DEBUG */
+/* mandatory for CONFIG_DEBUG_LL */
 
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31lilly.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31lilly.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31lilly.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31lilly.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * Based on code for mobots boards,
+ *   Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX31LILLY_H__
+#define __ASM_ARCH_MXC_BOARD_MX31LILLY_H__
+
+/* mandatory for CONFIG_LL_DEBUG */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	(AIPI_BASE_ADDR_VIRT + 0x0A000)
+
+#ifndef __ASSEMBLY__
+
+enum mx31lilly_boards {
+	MX31LILLY_NOBOARD	= 0,
+	MX31LILLY_DB		= 1,
+};
+
+/*
+ * This CPU module needs a baseboard to work. After basic initializing
+ * its own devices, it calls baseboard's init function.
+ */
+
+extern void mx31lilly_db_init(void);
+
+#endif
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31LILLY_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31lite.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31lite.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31lite.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31lite.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,28 +11,8 @@
 #ifndef __ASM_ARCH_MXC_BOARD_MX31LITE_H__
 #define __ASM_ARCH_MXC_BOARD_MX31LITE_H__
 
-#define MXC_MAX_EXP_IO_LINES	16
-
-
-/*
- * Memory Size parameters
- */
-
-/*
- * Size of SDRAM memory
- */
-#define SDRAM_MEM_SIZE		SZ_128M
-/*
- * Size of MBX buffer memory
- */
-#define MXC_MBX_MEM_SIZE	SZ_16M
-/*
- * Size of memory available to kernel
- */
-#define MEM_SIZE		(SDRAM_MEM_SIZE - MXC_MBX_MEM_SIZE)
-
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
 
-#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
+#endif /* __ASM_ARCH_MXC_BOARD_MX31LITE_H__ */
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31moboard.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31moboard.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31moboard.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,7 @@
 #ifndef __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
 #define __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
 
-/* mandatory for CONFIG_LL_DEBUG */
+/* mandatory for CONFIG_DEBUG_LL */
 
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	(AIPI_BASE_ADDR_VIRT + 0x0A000)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31pdk.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31pdk.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx31pdk.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx31pdk.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,9 +11,54 @@
 #ifndef __ASM_ARCH_MXC_BOARD_MX31PDK_H__
 #define __ASM_ARCH_MXC_BOARD_MX31PDK_H__
 
-/* mandatory for CONFIG_LL_DEBUG */
+/* mandatory for CONFIG_DEBUG_LL */
 
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
 
+/* Definitions for components on the Debug board */
+
+/* Base address of CPLD controller on the Debug board */
+#define DEBUG_BASE_ADDRESS		CS5_IO_ADDRESS(CS5_BASE_ADDR)
+
+/* LAN9217 ethernet base address */
+#define LAN9217_BASE_ADDR		CS5_BASE_ADDR
+
+/* CPLD config and interrupt base address */
+#define CPLD_ADDR			(DEBUG_BASE_ADDRESS + 0x20000)
+
+/* LED switchs */
+#define CPLD_LED_REG			(CPLD_ADDR + 0x00)
+/* buttons */
+#define CPLD_SWITCH_BUTTONS_REG	(EXPIO_ADDR + 0x08)
+/* status, interrupt */
+#define CPLD_INT_STATUS_REG		(CPLD_ADDR + 0x10)
+#define CPLD_INT_MASK_REG		(CPLD_ADDR + 0x38)
+#define CPLD_INT_RESET_REG		(CPLD_ADDR + 0x20)
+/* magic word for debug CPLD */
+#define CPLD_MAGIC_NUMBER1_REG		(CPLD_ADDR + 0x40)
+#define CPLD_MAGIC_NUMBER2_REG		(CPLD_ADDR + 0x48)
+/* CPLD code version */
+#define CPLD_CODE_VER_REG		(CPLD_ADDR + 0x50)
+/* magic word for debug CPLD */
+#define CPLD_MAGIC_NUMBER3_REG		(CPLD_ADDR + 0x58)
+/* module reset register */
+#define CPLD_MODULE_RESET_REG		(CPLD_ADDR + 0x60)
+/* CPU ID and Personality ID */
+#define CPLD_MCU_BOARD_ID_REG		(CPLD_ADDR + 0x68)
+
+/* CPLD IRQ line for external uart, external ethernet etc */
+#define EXPIO_PARENT_INT	IOMUX_TO_IRQ(MX31_PIN_GPIO1_1)
+
+#define MXC_EXP_IO_BASE		(MXC_BOARD_IRQ_START)
+#define MXC_IRQ_TO_EXPIO(irq)	((irq) - MXC_EXP_IO_BASE)
+
+#define EXPIO_INT_ENET		(MXC_EXP_IO_BASE + 0)
+#define EXPIO_INT_XUART_A	(MXC_EXP_IO_BASE + 1)
+#define EXPIO_INT_XUART_B	(MXC_EXP_IO_BASE + 2)
+#define EXPIO_INT_BUTTON_A	(MXC_EXP_IO_BASE + 3)
+#define EXPIO_INT_BUTTON_B	(MXC_EXP_IO_BASE + 4)
+
+#define MXC_MAX_EXP_IO_LINES	16
+
 #endif /* __ASM_ARCH_MXC_BOARD_MX31PDK_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx35pdk.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx35pdk.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-mx35pdk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-mx35pdk.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ *  Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved
+ *
+ * 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 __ASM_ARCH_MXC_BOARD_MX35PDK_H__
+#define __ASM_ARCH_MXC_BOARD_MX35PDK_H__
+
+/* mandatory for CONFIG_DEBUG_LL */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX35PDK_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-pcm037.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-pcm037.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-pcm037.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-pcm037.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,7 @@
 #ifndef __ASM_ARCH_MXC_BOARD_PCM037_H__
 #define __ASM_ARCH_MXC_BOARD_PCM037_H__
 
-/* mandatory for CONFIG_LL_DEBUG */
+/* mandatory for CONFIG_DEBUG_LL */
 
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-pcm038.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-pcm038.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-pcm038.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-pcm038.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,7 @@
 #ifndef __ASM_ARCH_MXC_BOARD_PCM038_H__
 #define __ASM_ARCH_MXC_BOARD_PCM038_H__
 
-/* mandatory for CONFIG_LL_DEBUG */
+/* mandatory for CONFIG_DEBUG_LL */
 
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	(AIPI_BASE_ADDR_VIRT + 0x0A000)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-pcm043.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-pcm043.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-pcm043.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-pcm043.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (C) 2008 Sascha Hauer, Pengutronix
+ *
+ * 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 __ASM_ARCH_MXC_BOARD_PCM043_H__
+#define __ASM_ARCH_MXC_BOARD_PCM043_H__
+
+/* mandatory for CONFIG_LL_DEBUG */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+
+#endif /* __ASM_ARCH_MXC_BOARD_PCM043_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-qong.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-qong.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/board-qong.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/board-qong.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,7 @@
 #ifndef __ASM_ARCH_MXC_BOARD_QONG_H__
 #define __ASM_ARCH_MXC_BOARD_QONG_H__
 
-/* mandatory for CONFIG_LL_DEBUG */
+/* mandatory for CONFIG_DEBUG_LL */
 
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/common.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/common.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/common.h	2009-09-09 18:13:59.000000000 -0400
@@ -14,7 +14,11 @@
 struct platform_device;
 struct clk;
 
-extern void mxc_map_io(void);
+extern void mx1_map_io(void);
+extern void mx21_map_io(void);
+extern void mx27_map_io(void);
+extern void mx31_map_io(void);
+extern void mx35_map_io(void);
 extern void mxc_init_irq(void);
 extern void mxc_timer_init(struct clk *timer_clk);
 extern int mx1_clocks_init(unsigned long fref);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/debug-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,9 @@
 #ifdef CONFIG_MACH_MX27ADS
 #include <mach/board-mx27ads.h>
 #endif
+#ifdef CONFIG_MACH_MX21ADS
+#include <mach/board-mx21ads.h>
+#endif
 #ifdef CONFIG_MACH_PCM038
 #include <mach/board-pcm038.h>
 #endif
@@ -34,6 +37,21 @@
 #ifdef CONFIG_MACH_QONG
 #include <mach/board-qong.h>
 #endif
+#ifdef CONFIG_MACH_PCM043
+#include <mach/board-pcm043.h>
+#endif
+#ifdef CONFIG_MACH_MX27_3DS
+#include <mach/board-mx27pdk.h>
+#endif
+#ifdef CONFIG_MACH_ARMADILLO5X0
+#include <mach/board-armadillo5x0.h>
+#endif
+#ifdef CONFIG_MACH_MX35_3DS
+#include <mach/board-mx35pdk.h>
+#endif
+#ifdef CONFIG_MACH_MX27LITE
+#include <mach/board-mx27lite.h>
+#endif
 		.macro	addruart,rx
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/gpio.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,6 +35,7 @@
 	int irq;
 	int virtual_irq_start;
 	struct gpio_chip chip;
+	u32 both_edges;
 };
 
 int mxc_gpio_init(struct mxc_gpio_port*, int);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/imxfb.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/imxfb.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/imxfb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/imxfb.h	2009-09-09 18:13:59.000000000 -0400
@@ -76,8 +76,8 @@
 	u_char * fixed_screen_cpu;
 	dma_addr_t fixed_screen_dma;
 
-	int (*init)(struct platform_device*);
-	int (*exit)(struct platform_device*);
+	int (*init)(struct platform_device *);
+	void (*exit)(struct platform_device *);
 
 	void (*lcd_power)(int);
 	void (*backlight_power)(int);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/imx-uart.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/imx-uart.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/imx-uart.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/imx-uart.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,11 +20,16 @@
 #define ASMARM_ARCH_UART_H
 
 #define IMXUART_HAVE_RTSCTS (1<<0)
+#define IMXUART_IRDA        (1<<1)
 
 struct imxuart_platform_data {
 	int (*init)(struct platform_device *pdev);
-	int (*exit)(struct platform_device *pdev);
+	void (*exit)(struct platform_device *pdev);
 	unsigned int flags;
+	void (*irda_enable)(int enable);
+	unsigned int irda_inv_rx:1;
+	unsigned int irda_inv_tx:1;
+	unsigned short transceiver_delay;
 };
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1267 @@
+/*
+ * Copyright (C, NO_PAD_CTRL) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.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, NO_PAD_CTRL) 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.
+ */
+
+#ifndef __MACH_IOMUX_MX35_H__
+#define __MACH_IOMUX_MX35_H__
+
+#include <mach/iomux-v3.h>
+
+/*
+ * The naming convention for the pad modes is MX35_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named
+ * GPIO_<unit>_<num> see also iomux-v3.h
+ */
+
+/*									  PAD    MUX   ALT INPSE PATH */
+#define MX35_PAD_CAPTURE__GPT_CAPIN1				IOMUX_PAD(0x328, 0x004, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__GPT_CMPOUT2				IOMUX_PAD(0x328, 0x004, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__CSPI2_SS1				IOMUX_PAD(0x328, 0x004, 2, 0x7f4, 0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__EPIT1_EPITO				IOMUX_PAD(0x328, 0x004, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__CCM_CLK32K				IOMUX_PAD(0x328, 0x004, 4, 0x7d0, 0, NO_PAD_CTRL)
+#define MX35_PAD_CAPTURE__GPIO1_4				IOMUX_PAD(0x328, 0x004, 5, 0x850, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_COMPARE__GPT_CMPOUT1				IOMUX_PAD(0x32c, 0x008, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__GPT_CAPIN2				IOMUX_PAD(0x32c, 0x008, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__GPT_CMPOUT3				IOMUX_PAD(0x32c, 0x008, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__EPIT2_EPITO				IOMUX_PAD(0x32c, 0x008, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__GPIO1_5				IOMUX_PAD(0x32c, 0x008, 5, 0x854, 0, NO_PAD_CTRL)
+#define MX35_PAD_COMPARE__SDMA_EXTDMA_2				IOMUX_PAD(0x32c, 0x008, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_WDOG_RST__WDOG_WDOG_B				IOMUX_PAD(0x330, 0x00c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_WDOG_RST__IPU_FLASH_STROBE			IOMUX_PAD(0x330, 0x00c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_WDOG_RST__GPIO1_6				IOMUX_PAD(0x330, 0x00c, 5, 0x858, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO1_0__GPIO1_0				IOMUX_PAD(0x334, 0x010, 0, 0x82c, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_0__CCM_PMIC_RDY				IOMUX_PAD(0x334, 0x010, 1, 0x7d4, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_0__OWIRE_LINE				IOMUX_PAD(0x334, 0x010, 2, 0x990, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_0__SDMA_EXTDMA_0				IOMUX_PAD(0x334, 0x010, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO1_1__GPIO1_1				IOMUX_PAD(0x338, 0x014, 0, 0x838, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__PWM_PWMO				IOMUX_PAD(0x338, 0x014, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__CSPI1_SS2				IOMUX_PAD(0x338, 0x014, 3, 0x7d8, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__SCC_TAMPER_DETECT			IOMUX_PAD(0x338, 0x014, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO1_1__SDMA_EXTDMA_1				IOMUX_PAD(0x338, 0x014, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO2_0__GPIO2_0				IOMUX_PAD(0x33c, 0x018, 0, 0x868, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO2_0__USB_TOP_USBOTG_CLK			IOMUX_PAD(0x33c, 0x018, 1, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_GPIO3_0__GPIO3_0				IOMUX_PAD(0x340, 0x01c, 0, 0x8e8, 0, NO_PAD_CTRL)
+#define MX35_PAD_GPIO3_0__USB_TOP_USBH2_CLK			IOMUX_PAD(0x340, 0x01c, 1, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RESET_IN_B__CCM_RESET_IN_B			IOMUX_PAD(0x344, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_POR_B__CCM_POR_B				IOMUX_PAD(0x348, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CLKO__CCM_CLKO					IOMUX_PAD(0x34c, 0x020, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CLKO__GPIO1_8					IOMUX_PAD(0x34c, 0x020, 5, 0x860, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_BOOT_MODE0__CCM_BOOT_MODE_0			IOMUX_PAD(0x350, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_BOOT_MODE1__CCM_BOOT_MODE_1			IOMUX_PAD(0x354, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CLK_MODE0__CCM_CLK_MODE_0			IOMUX_PAD(0x358, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CLK_MODE1__CCM_CLK_MODE_1			IOMUX_PAD(0x35c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_POWER_FAIL__CCM_DSM_WAKEUP_INT_26		IOMUX_PAD(0x360, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_VSTBY__CCM_VSTBY				IOMUX_PAD(0x364, 0x024, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_VSTBY__GPIO1_7					IOMUX_PAD(0x364, 0x024, 5, 0x85c, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_A0__EMI_EIM_DA_L_0				IOMUX_PAD(0x368, 0x028, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A1__EMI_EIM_DA_L_1				IOMUX_PAD(0x36c, 0x02c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A2__EMI_EIM_DA_L_2				IOMUX_PAD(0x370, 0x030, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A3__EMI_EIM_DA_L_3				IOMUX_PAD(0x374, 0x034, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A4__EMI_EIM_DA_L_4				IOMUX_PAD(0x378, 0x038, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A5__EMI_EIM_DA_L_5				IOMUX_PAD(0x37c, 0x03c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A6__EMI_EIM_DA_L_6				IOMUX_PAD(0x380, 0x040, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A7__EMI_EIM_DA_L_7				IOMUX_PAD(0x384, 0x044, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A8__EMI_EIM_DA_H_8				IOMUX_PAD(0x388, 0x048, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A9__EMI_EIM_DA_H_9				IOMUX_PAD(0x38c, 0x04c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A10__EMI_EIM_DA_H_10				IOMUX_PAD(0x390, 0x050, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_MA10__EMI_MA10					IOMUX_PAD(0x394, 0x054, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A11__EMI_EIM_DA_H_11				IOMUX_PAD(0x398, 0x058, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A12__EMI_EIM_DA_H_12				IOMUX_PAD(0x39c, 0x05c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A13__EMI_EIM_DA_H_13				IOMUX_PAD(0x3a0, 0x060, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A14__EMI_EIM_DA_H2_14				IOMUX_PAD(0x3a4, 0x064, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A15__EMI_EIM_DA_H2_15				IOMUX_PAD(0x3a8, 0x068, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A16__EMI_EIM_A_16				IOMUX_PAD(0x3ac, 0x06c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A17__EMI_EIM_A_17				IOMUX_PAD(0x3b0, 0x070, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A18__EMI_EIM_A_18				IOMUX_PAD(0x3b4, 0x074, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A19__EMI_EIM_A_19				IOMUX_PAD(0x3b8, 0x078, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A20__EMI_EIM_A_20				IOMUX_PAD(0x3bc, 0x07c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A21__EMI_EIM_A_21				IOMUX_PAD(0x3c0, 0x080, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A22__EMI_EIM_A_22				IOMUX_PAD(0x3c4, 0x084, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A23__EMI_EIM_A_23				IOMUX_PAD(0x3c8, 0x088, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A24__EMI_EIM_A_24				IOMUX_PAD(0x3cc, 0x08c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_A25__EMI_EIM_A_25				IOMUX_PAD(0x3d0, 0x090, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDBA1__EMI_EIM_SDBA1				IOMUX_PAD(0x3d4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDBA0__EMI_EIM_SDBA0				IOMUX_PAD(0x3d8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD0__EMI_DRAM_D_0				IOMUX_PAD(0x3dc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1__EMI_DRAM_D_1				IOMUX_PAD(0x3e0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2__EMI_DRAM_D_2				IOMUX_PAD(0x3e4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD3__EMI_DRAM_D_3				IOMUX_PAD(0x3e8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD4__EMI_DRAM_D_4				IOMUX_PAD(0x3ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD5__EMI_DRAM_D_5				IOMUX_PAD(0x3f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD6__EMI_DRAM_D_6				IOMUX_PAD(0x3f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD7__EMI_DRAM_D_7				IOMUX_PAD(0x3f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD8__EMI_DRAM_D_8				IOMUX_PAD(0x3fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD9__EMI_DRAM_D_9				IOMUX_PAD(0x400, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD10__EMI_DRAM_D_10				IOMUX_PAD(0x404, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD11__EMI_DRAM_D_11				IOMUX_PAD(0x408, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD12__EMI_DRAM_D_12				IOMUX_PAD(0x40c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD13__EMI_DRAM_D_13				IOMUX_PAD(0x410, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD14__EMI_DRAM_D_14				IOMUX_PAD(0x414, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD15__EMI_DRAM_D_15				IOMUX_PAD(0x418, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD16__EMI_DRAM_D_16				IOMUX_PAD(0x41c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD17__EMI_DRAM_D_17				IOMUX_PAD(0x420, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD18__EMI_DRAM_D_18				IOMUX_PAD(0x424, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD19__EMI_DRAM_D_19				IOMUX_PAD(0x428, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD20__EMI_DRAM_D_20				IOMUX_PAD(0x42c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD21__EMI_DRAM_D_21				IOMUX_PAD(0x430, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD22__EMI_DRAM_D_22				IOMUX_PAD(0x434, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD23__EMI_DRAM_D_23				IOMUX_PAD(0x438, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD24__EMI_DRAM_D_24				IOMUX_PAD(0x43c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD25__EMI_DRAM_D_25				IOMUX_PAD(0x440, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD26__EMI_DRAM_D_26				IOMUX_PAD(0x444, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD27__EMI_DRAM_D_27				IOMUX_PAD(0x448, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD28__EMI_DRAM_D_28				IOMUX_PAD(0x44c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD29__EMI_DRAM_D_29				IOMUX_PAD(0x450, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD30__EMI_DRAM_D_30				IOMUX_PAD(0x454, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD31__EMI_DRAM_D_31				IOMUX_PAD(0x458, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM0__EMI_DRAM_DQM_0				IOMUX_PAD(0x45c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM1__EMI_DRAM_DQM_1				IOMUX_PAD(0x460, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM2__EMI_DRAM_DQM_2				IOMUX_PAD(0x464, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DQM3__EMI_DRAM_DQM_3				IOMUX_PAD(0x468, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_EB0__EMI_EIM_EB0_B				IOMUX_PAD(0x46c, 0x094, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_EB1__EMI_EIM_EB1_B				IOMUX_PAD(0x470, 0x098, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_OE__EMI_EIM_OE					IOMUX_PAD(0x474, 0x09c, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS0__EMI_EIM_CS0				IOMUX_PAD(0x478, 0x0a0, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS1__EMI_EIM_CS1				IOMUX_PAD(0x47c, 0x0a4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS1__EMI_NANDF_CE3				IOMUX_PAD(0x47c, 0x0a4, 3, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS2__EMI_EIM_CS2				IOMUX_PAD(0x480, 0x0a8, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS3__EMI_EIM_CS3				IOMUX_PAD(0x484, 0x0ac, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS4__EMI_EIM_CS4				IOMUX_PAD(0x488, 0x0b0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS4__EMI_DTACK_B				IOMUX_PAD(0x488, 0x0b0, 1, 0x800, 0, NO_PAD_CTRL)
+#define MX35_PAD_CS4__EMI_NANDF_CE1				IOMUX_PAD(0x488, 0x0b0, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS4__GPIO1_20					IOMUX_PAD(0x488, 0x0b0, 5, 0x83c, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_CS5__EMI_EIM_CS5				IOMUX_PAD(0x48c, 0x0b4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS5__CSPI2_SS2					IOMUX_PAD(0x48c, 0x0b4, 1, 0x7f8, 0, NO_PAD_CTRL)
+#define MX35_PAD_CS5__CSPI1_SS2					IOMUX_PAD(0x48c, 0x0b4, 2, 0x7d8, 1, NO_PAD_CTRL)
+#define MX35_PAD_CS5__EMI_NANDF_CE2				IOMUX_PAD(0x48c, 0x0b4, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CS5__GPIO1_21					IOMUX_PAD(0x48c, 0x0b4, 5, 0x840, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_NF_CE0__EMI_NANDF_CE0				IOMUX_PAD(0x490, 0x0b8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NF_CE0__GPIO1_22				IOMUX_PAD(0x490, 0x0b8, 5, 0x844, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_ECB__EMI_EIM_ECB				IOMUX_PAD(0x494, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LBA__EMI_EIM_LBA				IOMUX_PAD(0x498, 0x0bc, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_BCLK__EMI_EIM_BCLK				IOMUX_PAD(0x49c, 0x0c0, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RW__EMI_EIM_RW					IOMUX_PAD(0x4a0, 0x0c4, 0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RAS__EMI_DRAM_RAS				IOMUX_PAD(0x4a4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CAS__EMI_DRAM_CAS				IOMUX_PAD(0x4a8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDWE__EMI_DRAM_SDWE				IOMUX_PAD(0x4ac, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDCKE0__EMI_DRAM_SDCKE_0			IOMUX_PAD(0x4b0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDCKE1__EMI_DRAM_SDCKE_1			IOMUX_PAD(0x4b4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDCLK__EMI_DRAM_SDCLK				IOMUX_PAD(0x4b8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS0__EMI_DRAM_SDQS_0				IOMUX_PAD(0x4bc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS1__EMI_DRAM_SDQS_1				IOMUX_PAD(0x4c0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS2__EMI_DRAM_SDQS_2				IOMUX_PAD(0x4c4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SDQS3__EMI_DRAM_SDQS_3				IOMUX_PAD(0x4c8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFWE_B__EMI_NANDF_WE_B				IOMUX_PAD(0x4cc, 0x0c8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__USB_TOP_USBH2_DATA_3			IOMUX_PAD(0x4cc, 0x0c8, 1, 0x9d8, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x4cc, 0x0c8, 2, 0x924, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__GPIO2_18				IOMUX_PAD(0x4cc, 0x0c8, 5, 0x88c, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWE_B__ARM11P_TOP_TRACE_0			IOMUX_PAD(0x4cc, 0x0c8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFRE_B__EMI_NANDF_RE_B				IOMUX_PAD(0x4d0, 0x0cc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__USB_TOP_USBH2_DIR			IOMUX_PAD(0x4d0, 0x0cc, 1, 0x9ec, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__IPU_DISPB_BCLK				IOMUX_PAD(0x4d0, 0x0cc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__GPIO2_19				IOMUX_PAD(0x4d0, 0x0cc, 5, 0x890, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFRE_B__ARM11P_TOP_TRACE_1			IOMUX_PAD(0x4d0, 0x0cc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFALE__EMI_NANDF_ALE				IOMUX_PAD(0x4d4, 0x0d0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__USB_TOP_USBH2_STP			IOMUX_PAD(0x4d4, 0x0d0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__IPU_DISPB_CS0				IOMUX_PAD(0x4d4, 0x0d0, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__GPIO2_20				IOMUX_PAD(0x4d4, 0x0d0, 5, 0x898, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFALE__ARM11P_TOP_TRACE_2			IOMUX_PAD(0x4d4, 0x0d0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFCLE__EMI_NANDF_CLE				IOMUX_PAD(0x4d8, 0x0d4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__USB_TOP_USBH2_NXT			IOMUX_PAD(0x4d8, 0x0d4, 1, 0x9f0, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__IPU_DISPB_PAR_RS			IOMUX_PAD(0x4d8, 0x0d4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__GPIO2_21				IOMUX_PAD(0x4d8, 0x0d4, 5, 0x89c, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFCLE__ARM11P_TOP_TRACE_3			IOMUX_PAD(0x4d8, 0x0d4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFWP_B__EMI_NANDF_WP_B				IOMUX_PAD(0x4dc, 0x0d8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__USB_TOP_USBH2_DATA_7			IOMUX_PAD(0x4dc, 0x0d8, 1, 0x9e8, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__IPU_DISPB_WR				IOMUX_PAD(0x4dc, 0x0d8, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__GPIO2_22				IOMUX_PAD(0x4dc, 0x0d8, 5, 0x8a0, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFWP_B__ARM11P_TOP_TRCTL			IOMUX_PAD(0x4dc, 0x0d8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_NFRB__EMI_NANDF_RB				IOMUX_PAD(0x4e0, 0x0dc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRB__IPU_DISPB_RD				IOMUX_PAD(0x4e0, 0x0dc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_NFRB__GPIO2_23					IOMUX_PAD(0x4e0, 0x0dc, 5, 0x8a4, 0, NO_PAD_CTRL)
+#define MX35_PAD_NFRB__ARM11P_TOP_TRCLK				IOMUX_PAD(0x4e0, 0x0dc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D15__EMI_EIM_D_15				IOMUX_PAD(0x4e4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D14__EMI_EIM_D_14				IOMUX_PAD(0x4e8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D13__EMI_EIM_D_13				IOMUX_PAD(0x4ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D12__EMI_EIM_D_12				IOMUX_PAD(0x4f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D11__EMI_EIM_D_11				IOMUX_PAD(0x4f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D10__EMI_EIM_D_10				IOMUX_PAD(0x4f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D9__EMI_EIM_D_9				IOMUX_PAD(0x4fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D8__EMI_EIM_D_8				IOMUX_PAD(0x500, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D7__EMI_EIM_D_7				IOMUX_PAD(0x504, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D6__EMI_EIM_D_6				IOMUX_PAD(0x508, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D5__EMI_EIM_D_5				IOMUX_PAD(0x50c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D4__EMI_EIM_D_4				IOMUX_PAD(0x510, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3__EMI_EIM_D_3				IOMUX_PAD(0x514, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D2__EMI_EIM_D_2				IOMUX_PAD(0x518, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D1__EMI_EIM_D_1				IOMUX_PAD(0x51c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D0__EMI_EIM_D_0				IOMUX_PAD(0x520, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D8__IPU_CSI_D_8				IOMUX_PAD(0x524, 0x0e0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D8__KPP_COL_0				IOMUX_PAD(0x524, 0x0e0, 1, 0x950, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D8__GPIO1_20				IOMUX_PAD(0x524, 0x0e0, 5, 0x83c, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D8__ARM11P_TOP_EVNTBUS_13			IOMUX_PAD(0x524, 0x0e0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D9__IPU_CSI_D_9				IOMUX_PAD(0x528, 0x0e4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D9__KPP_COL_1				IOMUX_PAD(0x528, 0x0e4, 1, 0x954, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D9__GPIO1_21				IOMUX_PAD(0x528, 0x0e4, 5, 0x840, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D9__ARM11P_TOP_EVNTBUS_14			IOMUX_PAD(0x528, 0x0e4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D10__IPU_CSI_D_10				IOMUX_PAD(0x52c, 0x0e8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D10__KPP_COL_2				IOMUX_PAD(0x52c, 0x0e8, 1, 0x958, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D10__GPIO1_22				IOMUX_PAD(0x52c, 0x0e8, 5, 0x844, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D10__ARM11P_TOP_EVNTBUS_15			IOMUX_PAD(0x52c, 0x0e8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D11__IPU_CSI_D_11				IOMUX_PAD(0x530, 0x0ec, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D11__KPP_COL_3				IOMUX_PAD(0x530, 0x0ec, 1, 0x95c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D11__GPIO1_23				IOMUX_PAD(0x530, 0x0ec, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D12__IPU_CSI_D_12				IOMUX_PAD(0x534, 0x0f0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D12__KPP_ROW_0				IOMUX_PAD(0x534, 0x0f0, 1, 0x970, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D12__GPIO1_24				IOMUX_PAD(0x534, 0x0f0, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D13__IPU_CSI_D_13				IOMUX_PAD(0x538, 0x0f4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D13__KPP_ROW_1				IOMUX_PAD(0x538, 0x0f4, 1, 0x974, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D13__GPIO1_25				IOMUX_PAD(0x538, 0x0f4, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D14__IPU_CSI_D_14				IOMUX_PAD(0x53c, 0x0f8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D14__KPP_ROW_2				IOMUX_PAD(0x53c, 0x0f8, 1, 0x978, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D14__GPIO1_26				IOMUX_PAD(0x53c, 0x0f8, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_D15__IPU_CSI_D_15				IOMUX_PAD(0x540, 0x0fc, 0, 0x97c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D15__KPP_ROW_3				IOMUX_PAD(0x540, 0x0fc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_D15__GPIO1_27				IOMUX_PAD(0x540, 0x0fc, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_MCLK__IPU_CSI_MCLK				IOMUX_PAD(0x544, 0x100, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_MCLK__GPIO1_28				IOMUX_PAD(0x544, 0x100, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC			IOMUX_PAD(0x548, 0x104, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_VSYNC__GPIO1_29				IOMUX_PAD(0x548, 0x104, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_HSYNC__IPU_CSI_HSYNC			IOMUX_PAD(0x54c, 0x108, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_HSYNC__GPIO1_30				IOMUX_PAD(0x54c, 0x108, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK			IOMUX_PAD(0x550, 0x10c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSI_PIXCLK__GPIO1_31				IOMUX_PAD(0x550, 0x10c, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C1_CLK__I2C1_SCL				IOMUX_PAD(0x554, 0x110, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C1_CLK__GPIO2_24				IOMUX_PAD(0x554, 0x110, 5, 0x8a8, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C1_CLK__CCM_USB_BYP_CLK			IOMUX_PAD(0x554, 0x110, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C1_DAT__I2C1_SDA				IOMUX_PAD(0x558, 0x114, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C1_DAT__GPIO2_25				IOMUX_PAD(0x558, 0x114, 5, 0x8ac, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C2_CLK__I2C2_SCL				IOMUX_PAD(0x55c, 0x118, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__CAN1_TXCAN				IOMUX_PAD(0x55c, 0x118, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR			IOMUX_PAD(0x55c, 0x118, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__GPIO2_26				IOMUX_PAD(0x55c, 0x118, 5, 0x8b0, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_CLK__SDMA_DEBUG_BUS_DEVICE_2		IOMUX_PAD(0x55c, 0x118, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_I2C2_DAT__I2C2_SDA				IOMUX_PAD(0x560, 0x11c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__CAN1_RXCAN				IOMUX_PAD(0x560, 0x11c, 1, 0x7c8, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC			IOMUX_PAD(0x560, 0x11c, 2, 0x9f4, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__GPIO2_27				IOMUX_PAD(0x560, 0x11c, 5, 0x8b4, 0, NO_PAD_CTRL)
+#define MX35_PAD_I2C2_DAT__SDMA_DEBUG_BUS_DEVICE_3		IOMUX_PAD(0x560, 0x11c, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXD4__AUDMUX_AUD4_TXD				IOMUX_PAD(0x564, 0x120, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXD4__GPIO2_28				IOMUX_PAD(0x564, 0x120, 5, 0x8b8, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXD4__ARM11P_TOP_ARM_COREASID0		IOMUX_PAD(0x564, 0x120, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SRXD4__AUDMUX_AUD4_RXD				IOMUX_PAD(0x568, 0x124, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD4__GPIO2_29				IOMUX_PAD(0x568, 0x124, 5, 0x8bc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD4__ARM11P_TOP_ARM_COREASID1		IOMUX_PAD(0x568, 0x124, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCK4__AUDMUX_AUD4_TXC				IOMUX_PAD(0x56c, 0x128, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCK4__GPIO2_30					IOMUX_PAD(0x56c, 0x128, 5, 0x8c4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK4__ARM11P_TOP_ARM_COREASID2			IOMUX_PAD(0x56c, 0x128, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS			IOMUX_PAD(0x570, 0x12c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS4__GPIO2_31				IOMUX_PAD(0x570, 0x12c, 5, 0x8c8, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS4__ARM11P_TOP_ARM_COREASID3		IOMUX_PAD(0x570, 0x12c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXD5__AUDMUX_AUD5_TXD				IOMUX_PAD(0x574, 0x130, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x574, 0x130, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__CSPI2_MOSI				IOMUX_PAD(0x574, 0x130, 2, 0x7ec, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__GPIO1_0					IOMUX_PAD(0x574, 0x130, 5, 0x82c, 1, NO_PAD_CTRL)
+#define MX35_PAD_STXD5__ARM11P_TOP_ARM_COREASID4		IOMUX_PAD(0x574, 0x130, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SRXD5__AUDMUX_AUD5_RXD				IOMUX_PAD(0x578, 0x134, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__SPDIF_SPDIF_IN1				IOMUX_PAD(0x578, 0x134, 1, 0x998, 0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__CSPI2_MISO				IOMUX_PAD(0x578, 0x134, 2, 0x7e8, 0, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__GPIO1_1					IOMUX_PAD(0x578, 0x134, 5, 0x838, 1, NO_PAD_CTRL)
+#define MX35_PAD_SRXD5__ARM11P_TOP_ARM_COREASID5		IOMUX_PAD(0x578, 0x134, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCK5__AUDMUX_AUD5_TXC				IOMUX_PAD(0x57c, 0x138, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x57c, 0x138, 1, 0x994, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__CSPI2_SCLK				IOMUX_PAD(0x57c, 0x138, 2, 0x7e0, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__GPIO1_2					IOMUX_PAD(0x57c, 0x138, 5, 0x848, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCK5__ARM11P_TOP_ARM_COREASID6			IOMUX_PAD(0x57c, 0x138, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_STXFS5__AUDMUX_AUD5_TXFS			IOMUX_PAD(0x580, 0x13c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS5__CSPI2_RDY				IOMUX_PAD(0x580, 0x13c, 2, 0x7e4, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS5__GPIO1_3				IOMUX_PAD(0x580, 0x13c, 5, 0x84c, 0, NO_PAD_CTRL)
+#define MX35_PAD_STXFS5__ARM11P_TOP_ARM_COREASID7		IOMUX_PAD(0x580, 0x13c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCKR__ESAI_SCKR				IOMUX_PAD(0x584, 0x140, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCKR__GPIO1_4					IOMUX_PAD(0x584, 0x140, 5, 0x850, 1, NO_PAD_CTRL)
+#define MX35_PAD_SCKR__ARM11P_TOP_EVNTBUS_10			IOMUX_PAD(0x584, 0x140, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FSR__ESAI_FSR					IOMUX_PAD(0x588, 0x144, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FSR__GPIO1_5					IOMUX_PAD(0x588, 0x144, 5, 0x854, 1, NO_PAD_CTRL)
+#define MX35_PAD_FSR__ARM11P_TOP_EVNTBUS_11			IOMUX_PAD(0x588, 0x144, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_HCKR__ESAI_HCKR				IOMUX_PAD(0x58c, 0x148, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__AUDMUX_AUD5_RXFS				IOMUX_PAD(0x58c, 0x148, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__CSPI2_SS0				IOMUX_PAD(0x58c, 0x148, 2, 0x7f0, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__IPU_FLASH_STROBE				IOMUX_PAD(0x58c, 0x148, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__GPIO1_6					IOMUX_PAD(0x58c, 0x148, 5, 0x858, 1, NO_PAD_CTRL)
+#define MX35_PAD_HCKR__ARM11P_TOP_EVNTBUS_12			IOMUX_PAD(0x58c, 0x148, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SCKT__ESAI_SCKT				IOMUX_PAD(0x590, 0x14c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SCKT__GPIO1_7					IOMUX_PAD(0x590, 0x14c, 5, 0x85c, 1, NO_PAD_CTRL)
+#define MX35_PAD_SCKT__IPU_CSI_D_0				IOMUX_PAD(0x590, 0x14c, 6, 0x930, 0, NO_PAD_CTRL)
+#define MX35_PAD_SCKT__KPP_ROW_2				IOMUX_PAD(0x590, 0x14c, 7, 0x978, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_FST__ESAI_FST					IOMUX_PAD(0x594, 0x150, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FST__GPIO1_8					IOMUX_PAD(0x594, 0x150, 5, 0x860, 1, NO_PAD_CTRL)
+#define MX35_PAD_FST__IPU_CSI_D_1				IOMUX_PAD(0x594, 0x150, 6, 0x934, 0, NO_PAD_CTRL)
+#define MX35_PAD_FST__KPP_ROW_3					IOMUX_PAD(0x594, 0x150, 7, 0x97c, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_HCKT__ESAI_HCKT				IOMUX_PAD(0x598, 0x154, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__AUDMUX_AUD5_RXC				IOMUX_PAD(0x598, 0x154, 1, 0x7a8, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__GPIO1_9					IOMUX_PAD(0x598, 0x154, 5, 0x864, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__IPU_CSI_D_2				IOMUX_PAD(0x598, 0x154, 6, 0x938, 0, NO_PAD_CTRL)
+#define MX35_PAD_HCKT__KPP_COL_3				IOMUX_PAD(0x598, 0x154, 7, 0x95c, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX5_RX0__ESAI_TX5_RX0				IOMUX_PAD(0x59c, 0x158, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__AUDMUX_AUD4_RXC			IOMUX_PAD(0x59c, 0x158, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__CSPI2_SS2				IOMUX_PAD(0x59c, 0x158, 2, 0x7f8, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__CAN2_TXCAN				IOMUX_PAD(0x59c, 0x158, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__UART2_DTR				IOMUX_PAD(0x59c, 0x158, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__GPIO1_10				IOMUX_PAD(0x59c, 0x158, 5, 0x830, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX5_RX0__EMI_M3IF_CHOSEN_MASTER_0		IOMUX_PAD(0x59c, 0x158, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TX4_RX1__ESAI_TX4_RX1				IOMUX_PAD(0x5a0, 0x15c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__AUDMUX_AUD4_RXFS			IOMUX_PAD(0x5a0, 0x15c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__CSPI2_SS3				IOMUX_PAD(0x5a0, 0x15c, 2, 0x7fc, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__CAN2_RXCAN				IOMUX_PAD(0x5a0, 0x15c, 3, 0x7cc, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__UART2_DSR				IOMUX_PAD(0x5a0, 0x15c, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__GPIO1_11				IOMUX_PAD(0x5a0, 0x15c, 5, 0x834, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__IPU_CSI_D_3				IOMUX_PAD(0x5a0, 0x15c, 6, 0x93c, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX4_RX1__KPP_ROW_0				IOMUX_PAD(0x5a0, 0x15c, 7, 0x970, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX3_RX2__ESAI_TX3_RX2				IOMUX_PAD(0x5a4, 0x160, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__I2C3_SCL				IOMUX_PAD(0x5a4, 0x160, 1, 0x91c, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__EMI_NANDF_CE1				IOMUX_PAD(0x5a4, 0x160, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__GPIO1_12				IOMUX_PAD(0x5a4, 0x160, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__IPU_CSI_D_4				IOMUX_PAD(0x5a4, 0x160, 6, 0x940, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX3_RX2__KPP_ROW_1				IOMUX_PAD(0x5a4, 0x160, 7, 0x974, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX2_RX3__ESAI_TX2_RX3				IOMUX_PAD(0x5a8, 0x164, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__I2C3_SDA				IOMUX_PAD(0x5a8, 0x164, 1, 0x920, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__EMI_NANDF_CE2				IOMUX_PAD(0x5a8, 0x164, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__GPIO1_13				IOMUX_PAD(0x5a8, 0x164, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__IPU_CSI_D_5				IOMUX_PAD(0x5a8, 0x164, 6, 0x944, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX2_RX3__KPP_COL_0				IOMUX_PAD(0x5a8, 0x164, 7, 0x950, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX1__ESAI_TX1					IOMUX_PAD(0x5ac, 0x168, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__CCM_PMIC_RDY				IOMUX_PAD(0x5ac, 0x168, 1, 0x7d4, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX1__CSPI1_SS2					IOMUX_PAD(0x5ac, 0x168, 2, 0x7d8, 2, NO_PAD_CTRL)
+#define MX35_PAD_TX1__EMI_NANDF_CE3				IOMUX_PAD(0x5ac, 0x168, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__UART2_RI					IOMUX_PAD(0x5ac, 0x168, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__GPIO1_14					IOMUX_PAD(0x5ac, 0x168, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__IPU_CSI_D_6				IOMUX_PAD(0x5ac, 0x168, 6, 0x948, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX1__KPP_COL_1					IOMUX_PAD(0x5ac, 0x168, 7, 0x954, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_TX0__ESAI_TX0					IOMUX_PAD(0x5b0, 0x16c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x5b0, 0x16c, 1, 0x994, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX0__CSPI1_SS3					IOMUX_PAD(0x5b0, 0x16c, 2, 0x7dc, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__EMI_DTACK_B				IOMUX_PAD(0x5b0, 0x16c, 3, 0x800, 1, NO_PAD_CTRL)
+#define MX35_PAD_TX0__UART2_DCD					IOMUX_PAD(0x5b0, 0x16c, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__GPIO1_15					IOMUX_PAD(0x5b0, 0x16c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__IPU_CSI_D_7				IOMUX_PAD(0x5b0, 0x16c, 6, 0x94c, 0, NO_PAD_CTRL)
+#define MX35_PAD_TX0__KPP_COL_2					IOMUX_PAD(0x5b0, 0x16c, 7, 0x958, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_MOSI__CSPI1_MOSI				IOMUX_PAD(0x5b4, 0x170, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MOSI__GPIO1_16				IOMUX_PAD(0x5b4, 0x170, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MOSI__ECT_CTI_TRIG_OUT1_2		IOMUX_PAD(0x5b4, 0x170, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_MISO__CSPI1_MISO				IOMUX_PAD(0x5b8, 0x174, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MISO__GPIO1_17				IOMUX_PAD(0x5b8, 0x174, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_MISO__ECT_CTI_TRIG_OUT1_3		IOMUX_PAD(0x5b8, 0x174, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SS0__CSPI1_SS0				IOMUX_PAD(0x5bc, 0x178, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__OWIRE_LINE				IOMUX_PAD(0x5bc, 0x178, 1, 0x990, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__CSPI2_SS3				IOMUX_PAD(0x5bc, 0x178, 2, 0x7fc, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__GPIO1_18				IOMUX_PAD(0x5bc, 0x178, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS0__ECT_CTI_TRIG_OUT1_4			IOMUX_PAD(0x5bc, 0x178, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SS1__CSPI1_SS1				IOMUX_PAD(0x5c0, 0x17c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__PWM_PWMO				IOMUX_PAD(0x5c0, 0x17c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__CCM_CLK32K				IOMUX_PAD(0x5c0, 0x17c, 2, 0x7d0, 1, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__GPIO1_19				IOMUX_PAD(0x5c0, 0x17c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__IPU_DIAGB_29			IOMUX_PAD(0x5c0, 0x17c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SS1__ECT_CTI_TRIG_OUT1_5			IOMUX_PAD(0x5c0, 0x17c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SCLK__CSPI1_SCLK				IOMUX_PAD(0x5c4, 0x180, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SCLK__GPIO3_4				IOMUX_PAD(0x5c4, 0x180, 5, 0x904, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SCLK__IPU_DIAGB_30			IOMUX_PAD(0x5c4, 0x180, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SCLK__EMI_M3IF_CHOSEN_MASTER_1		IOMUX_PAD(0x5c4, 0x180, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CSPI1_SPI_RDY__CSPI1_RDY			IOMUX_PAD(0x5c8, 0x184, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SPI_RDY__GPIO3_5				IOMUX_PAD(0x5c8, 0x184, 5, 0x908, 0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SPI_RDY__IPU_DIAGB_31			IOMUX_PAD(0x5c8, 0x184, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CSPI1_SPI_RDY__EMI_M3IF_CHOSEN_MASTER_2	IOMUX_PAD(0x5c8, 0x184, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RXD1__UART1_RXD_MUX				IOMUX_PAD(0x5cc, 0x188, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__CSPI2_MOSI				IOMUX_PAD(0x5cc, 0x188, 1, 0x7ec, 1, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__KPP_COL_4				IOMUX_PAD(0x5cc, 0x188, 4, 0x960, 0, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__GPIO3_6					IOMUX_PAD(0x5cc, 0x188, 5, 0x90c, 0, NO_PAD_CTRL)
+#define MX35_PAD_RXD1__ARM11P_TOP_EVNTBUS_16			IOMUX_PAD(0x5cc, 0x188, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TXD1__UART1_TXD_MUX				IOMUX_PAD(0x5d0, 0x18c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__CSPI2_MISO				IOMUX_PAD(0x5d0, 0x18c, 1, 0x7e8, 1, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__KPP_COL_5				IOMUX_PAD(0x5d0, 0x18c, 4, 0x964, 0, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__GPIO3_7					IOMUX_PAD(0x5d0, 0x18c, 5, 0x910, 0, NO_PAD_CTRL)
+#define MX35_PAD_TXD1__ARM11P_TOP_EVNTBUS_17			IOMUX_PAD(0x5d0, 0x18c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RTS1__UART1_RTS				IOMUX_PAD(0x5d4, 0x190, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__CSPI2_SCLK				IOMUX_PAD(0x5d4, 0x190, 1, 0x7e0, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__I2C3_SCL					IOMUX_PAD(0x5d4, 0x190, 2, 0x91c, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__IPU_CSI_D_0				IOMUX_PAD(0x5d4, 0x190, 3, 0x930, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__KPP_COL_6				IOMUX_PAD(0x5d4, 0x190, 4, 0x968, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__GPIO3_8					IOMUX_PAD(0x5d4, 0x190, 5, 0x914, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__EMI_NANDF_CE1				IOMUX_PAD(0x5d4, 0x190, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS1__ARM11P_TOP_EVNTBUS_18			IOMUX_PAD(0x5d4, 0x190, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CTS1__UART1_CTS				IOMUX_PAD(0x5d8, 0x194, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__CSPI2_RDY				IOMUX_PAD(0x5d8, 0x194, 1, 0x7e4, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__I2C3_SDA					IOMUX_PAD(0x5d8, 0x194, 2, 0x920, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__IPU_CSI_D_1				IOMUX_PAD(0x5d8, 0x194, 3, 0x934, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__KPP_COL_7				IOMUX_PAD(0x5d8, 0x194, 4, 0x96c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__GPIO3_9					IOMUX_PAD(0x5d8, 0x194, 5, 0x918, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__EMI_NANDF_CE2				IOMUX_PAD(0x5d8, 0x194, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS1__ARM11P_TOP_EVNTBUS_19			IOMUX_PAD(0x5d8, 0x194, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RXD2__UART2_RXD_MUX				IOMUX_PAD(0x5dc, 0x198, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RXD2__KPP_ROW_4				IOMUX_PAD(0x5dc, 0x198, 4, 0x980, 0, NO_PAD_CTRL)
+#define MX35_PAD_RXD2__GPIO3_10					IOMUX_PAD(0x5dc, 0x198, 5, 0x8ec, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_TXD2__UART2_TXD_MUX				IOMUX_PAD(0x5e0, 0x19c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_TXD2__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x5e0, 0x19c, 1, 0x994, 2, NO_PAD_CTRL)
+#define MX35_PAD_TXD2__KPP_ROW_5				IOMUX_PAD(0x5e0, 0x19c, 4, 0x984, 0, NO_PAD_CTRL)
+#define MX35_PAD_TXD2__GPIO3_11					IOMUX_PAD(0x5e0, 0x19c, 5, 0x8f0, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_RTS2__UART2_RTS				IOMUX_PAD(0x5e4, 0x1a0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__SPDIF_SPDIF_IN1				IOMUX_PAD(0x5e4, 0x1a0, 1, 0x998, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__CAN2_RXCAN				IOMUX_PAD(0x5e4, 0x1a0, 2, 0x7cc, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__IPU_CSI_D_2				IOMUX_PAD(0x5e4, 0x1a0, 3, 0x938, 1, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__KPP_ROW_6				IOMUX_PAD(0x5e4, 0x1a0, 4, 0x988, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__GPIO3_12					IOMUX_PAD(0x5e4, 0x1a0, 5, 0x8f4, 0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__AUDMUX_AUD5_RXC				IOMUX_PAD(0x5e4, 0x1a0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_RTS2__UART3_RXD_MUX				IOMUX_PAD(0x5e4, 0x1a0, 7, 0x9a0, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_CTS2__UART2_CTS				IOMUX_PAD(0x5e8, 0x1a4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__SPDIF_SPDIF_OUT1				IOMUX_PAD(0x5e8, 0x1a4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__CAN2_TXCAN				IOMUX_PAD(0x5e8, 0x1a4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__IPU_CSI_D_3				IOMUX_PAD(0x5e8, 0x1a4, 3, 0x93c, 1, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__KPP_ROW_7				IOMUX_PAD(0x5e8, 0x1a4, 4, 0x98c, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__GPIO3_13					IOMUX_PAD(0x5e8, 0x1a4, 5, 0x8f8, 0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__AUDMUX_AUD5_RXFS				IOMUX_PAD(0x5e8, 0x1a4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CTS2__UART3_TXD_MUX				IOMUX_PAD(0x5e8, 0x1a4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_RTCK__ARM11P_TOP_RTCK				IOMUX_PAD(0x5ec, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TCK__SJC_TCK					IOMUX_PAD(0x5f0, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TMS__SJC_TMS					IOMUX_PAD(0x5f4, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TDI__SJC_TDI					IOMUX_PAD(0x5f8, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TDO__SJC_TDO					IOMUX_PAD(0x5fc, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TRSTB__SJC_TRSTB				IOMUX_PAD(0x600, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_DE_B__SJC_DE_B					IOMUX_PAD(0x604, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SJC_MOD__SJC_MOD				IOMUX_PAD(0x608, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR			IOMUX_PAD(0x60c, 0x1a8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_PWR__USB_TOP_USBH2_PWR			IOMUX_PAD(0x60c, 0x1a8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_PWR__GPIO3_14				IOMUX_PAD(0x60c, 0x1a8, 5, 0x8fc, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC			IOMUX_PAD(0x610, 0x1ac, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_OC__USB_TOP_USBH2_OC			IOMUX_PAD(0x610, 0x1ac, 1, 0x9f4, 1, NO_PAD_CTRL)
+#define MX35_PAD_USBOTG_OC__GPIO3_15				IOMUX_PAD(0x610, 0x1ac, 5, 0x900, 0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD0__IPU_DISPB_DAT_0				IOMUX_PAD(0x614, 0x1b0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD0__GPIO2_0					IOMUX_PAD(0x614, 0x1b0, 5, 0x868, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD0__SDMA_SDMA_DEBUG_PC_0			IOMUX_PAD(0x614, 0x1b0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD1__IPU_DISPB_DAT_1				IOMUX_PAD(0x618, 0x1b4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD1__GPIO2_1					IOMUX_PAD(0x618, 0x1b4, 5, 0x894, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD1__SDMA_SDMA_DEBUG_PC_1			IOMUX_PAD(0x618, 0x1b4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD2__IPU_DISPB_DAT_2				IOMUX_PAD(0x61c, 0x1b8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD2__GPIO2_2					IOMUX_PAD(0x61c, 0x1b8, 5, 0x8c0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD2__SDMA_SDMA_DEBUG_PC_2			IOMUX_PAD(0x61c, 0x1b8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD3__IPU_DISPB_DAT_3				IOMUX_PAD(0x620, 0x1bc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD3__GPIO2_3					IOMUX_PAD(0x620, 0x1bc, 5, 0x8cc, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD3__SDMA_SDMA_DEBUG_PC_3			IOMUX_PAD(0x620, 0x1bc, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD4__IPU_DISPB_DAT_4				IOMUX_PAD(0x624, 0x1c0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD4__GPIO2_4					IOMUX_PAD(0x624, 0x1c0, 5, 0x8d0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD4__SDMA_SDMA_DEBUG_PC_4			IOMUX_PAD(0x624, 0x1c0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD5__IPU_DISPB_DAT_5				IOMUX_PAD(0x628, 0x1c4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD5__GPIO2_5					IOMUX_PAD(0x628, 0x1c4, 5, 0x8d4, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD5__SDMA_SDMA_DEBUG_PC_5			IOMUX_PAD(0x628, 0x1c4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD6__IPU_DISPB_DAT_6				IOMUX_PAD(0x62c, 0x1c8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD6__GPIO2_6					IOMUX_PAD(0x62c, 0x1c8, 5, 0x8d8, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD6__SDMA_SDMA_DEBUG_PC_6			IOMUX_PAD(0x62c, 0x1c8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD7__IPU_DISPB_DAT_7				IOMUX_PAD(0x630, 0x1cc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD7__GPIO2_7					IOMUX_PAD(0x630, 0x1cc, 5, 0x8dc, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD7__SDMA_SDMA_DEBUG_PC_7			IOMUX_PAD(0x630, 0x1cc, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD8__IPU_DISPB_DAT_8				IOMUX_PAD(0x634, 0x1d0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD8__GPIO2_8					IOMUX_PAD(0x634, 0x1d0, 5, 0x8e0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD8__SDMA_SDMA_DEBUG_PC_8			IOMUX_PAD(0x634, 0x1d0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD9__IPU_DISPB_DAT_9				IOMUX_PAD(0x638, 0x1d4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD9__GPIO2_9					IOMUX_PAD(0x638, 0x1d4, 5, 0x8e4  0, NO_PAD_CTRL)
+#define MX35_PAD_LD9__SDMA_SDMA_DEBUG_PC_9			IOMUX_PAD(0x638, 0x1d4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD10__IPU_DISPB_DAT_10				IOMUX_PAD(0x63c, 0x1d8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD10__GPIO2_10					IOMUX_PAD(0x63c, 0x1d8, 5, 0x86c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD10__SDMA_SDMA_DEBUG_PC_10			IOMUX_PAD(0x63c, 0x1d8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD11__IPU_DISPB_DAT_11				IOMUX_PAD(0x640, 0x1dc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD11__GPIO2_11					IOMUX_PAD(0x640, 0x1dc, 5, 0x870, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD11__SDMA_SDMA_DEBUG_PC_11			IOMUX_PAD(0x640, 0x1dc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD11__ARM11P_TOP_TRACE_4			IOMUX_PAD(0x640, 0x1dc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD12__IPU_DISPB_DAT_12				IOMUX_PAD(0x644, 0x1e0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD12__GPIO2_12					IOMUX_PAD(0x644, 0x1e0, 5, 0x874, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD12__SDMA_SDMA_DEBUG_PC_12			IOMUX_PAD(0x644, 0x1e0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD12__ARM11P_TOP_TRACE_5			IOMUX_PAD(0x644, 0x1e0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD13__IPU_DISPB_DAT_13				IOMUX_PAD(0x648, 0x1e4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD13__GPIO2_13					IOMUX_PAD(0x648, 0x1e4, 5, 0x878, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD13__SDMA_SDMA_DEBUG_PC_13			IOMUX_PAD(0x648, 0x1e4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD13__ARM11P_TOP_TRACE_6			IOMUX_PAD(0x648, 0x1e4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD14__IPU_DISPB_DAT_14				IOMUX_PAD(0x64c, 0x1e8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD14__GPIO2_14					IOMUX_PAD(0x64c, 0x1e8, 5, 0x87c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD14__SDMA_SDMA_DEBUG_EVENT_CHANNEL_0		IOMUX_PAD(0x64c, 0x1e8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD14__ARM11P_TOP_TRACE_7			IOMUX_PAD(0x64c, 0x1e8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD15__IPU_DISPB_DAT_15				IOMUX_PAD(0x650, 0x1ec, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD15__GPIO2_15					IOMUX_PAD(0x650, 0x1ec, 5, 0x880, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD15__SDMA_SDMA_DEBUG_EVENT_CHANNEL_1		IOMUX_PAD(0x650, 0x1ec, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD15__ARM11P_TOP_TRACE_8			IOMUX_PAD(0x650, 0x1ec, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD16__IPU_DISPB_DAT_16				IOMUX_PAD(0x654, 0x1f0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x654, 0x1f0, 2, 0x928, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__GPIO2_16					IOMUX_PAD(0x654, 0x1f0, 5, 0x884, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__SDMA_SDMA_DEBUG_EVENT_CHANNEL_2		IOMUX_PAD(0x654, 0x1f0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD16__ARM11P_TOP_TRACE_9			IOMUX_PAD(0x654, 0x1f0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD17__IPU_DISPB_DAT_17				IOMUX_PAD(0x658, 0x1f4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__IPU_DISPB_CS2				IOMUX_PAD(0x658, 0x1f4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__GPIO2_17					IOMUX_PAD(0x658, 0x1f4, 5, 0x888, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__SDMA_SDMA_DEBUG_EVENT_CHANNEL_3		IOMUX_PAD(0x658, 0x1f4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD17__ARM11P_TOP_TRACE_10			IOMUX_PAD(0x658, 0x1f4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD18__IPU_DISPB_DAT_18				IOMUX_PAD(0x65c, 0x1f8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x65c, 0x1f8, 1, 0x924, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD18__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x65c, 0x1f8, 2, 0x928, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD18__ESDHC3_CMD				IOMUX_PAD(0x65c, 0x1f8, 3, 0x818, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__USB_TOP_USBOTG_DATA_3			IOMUX_PAD(0x65c, 0x1f8, 4, 0x9b0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__GPIO3_24					IOMUX_PAD(0x65c, 0x1f8, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__SDMA_SDMA_DEBUG_EVENT_CHANNEL_4		IOMUX_PAD(0x65c, 0x1f8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD18__ARM11P_TOP_TRACE_11			IOMUX_PAD(0x65c, 0x1f8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD19__IPU_DISPB_DAT_19				IOMUX_PAD(0x660, 0x1fc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__IPU_DISPB_BCLK				IOMUX_PAD(0x660, 0x1fc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__IPU_DISPB_CS1				IOMUX_PAD(0x660, 0x1fc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__ESDHC3_CLK				IOMUX_PAD(0x660, 0x1fc, 3, 0x814, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__USB_TOP_USBOTG_DIR			IOMUX_PAD(0x660, 0x1fc, 4, 0x9c4, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__GPIO3_25					IOMUX_PAD(0x660, 0x1fc, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__SDMA_SDMA_DEBUG_EVENT_CHANNEL_5		IOMUX_PAD(0x660, 0x1fc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD19__ARM11P_TOP_TRACE_12			IOMUX_PAD(0x660, 0x1fc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD20__IPU_DISPB_DAT_20				IOMUX_PAD(0x664, 0x200, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__IPU_DISPB_CS0				IOMUX_PAD(0x664, 0x200, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__IPU_DISPB_SD_CLK				IOMUX_PAD(0x664, 0x200, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__ESDHC3_DAT0				IOMUX_PAD(0x664, 0x200, 3, 0x81c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__GPIO3_26					IOMUX_PAD(0x664, 0x200, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__SDMA_SDMA_DEBUG_CORE_STATUS_3		IOMUX_PAD(0x664, 0x200, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD20__ARM11P_TOP_TRACE_13			IOMUX_PAD(0x664, 0x200, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD21__IPU_DISPB_DAT_21				IOMUX_PAD(0x668, 0x204, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__IPU_DISPB_PAR_RS				IOMUX_PAD(0x668, 0x204, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__IPU_DISPB_SER_RS				IOMUX_PAD(0x668, 0x204, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__ESDHC3_DAT1				IOMUX_PAD(0x668, 0x204, 3, 0x820, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__USB_TOP_USBOTG_STP			IOMUX_PAD(0x668, 0x204, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__GPIO3_27					IOMUX_PAD(0x668, 0x204, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__SDMA_DEBUG_EVENT_CHANNEL_SEL		IOMUX_PAD(0x668, 0x204, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD21__ARM11P_TOP_TRACE_14			IOMUX_PAD(0x668, 0x204, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD22__IPU_DISPB_DAT_22				IOMUX_PAD(0x66c, 0x208, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__IPU_DISPB_WR				IOMUX_PAD(0x66c, 0x208, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__IPU_DISPB_SD_D_I				IOMUX_PAD(0x66c, 0x208, 2, 0x92c, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__ESDHC3_DAT2				IOMUX_PAD(0x66c, 0x208, 3, 0x824, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__USB_TOP_USBOTG_NXT			IOMUX_PAD(0x66c, 0x208, 4, 0x9c8, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__GPIO3_28					IOMUX_PAD(0x66c, 0x208, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__SDMA_DEBUG_BUS_ERROR			IOMUX_PAD(0x66c, 0x208, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD22__ARM11P_TOP_TRCTL				IOMUX_PAD(0x66c, 0x208, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_LD23__IPU_DISPB_DAT_23				IOMUX_PAD(0x670, 0x20c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__IPU_DISPB_RD				IOMUX_PAD(0x670, 0x20c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x670, 0x20c, 2, 0x92c, 1, NO_PAD_CTRL)
+#define MX35_PAD_LD23__ESDHC3_DAT3				IOMUX_PAD(0x670, 0x20c, 3, 0x828, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__USB_TOP_USBOTG_DATA_7			IOMUX_PAD(0x670, 0x20c, 4, 0x9c0, 0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__GPIO3_29					IOMUX_PAD(0x670, 0x20c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__SDMA_DEBUG_MATCHED_DMBUS			IOMUX_PAD(0x670, 0x20c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_LD23__ARM11P_TOP_TRCLK				IOMUX_PAD(0x670, 0x20c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC			IOMUX_PAD(0x674, 0x210, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x674, 0x210, 2, 0x92c, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__GPIO3_30				IOMUX_PAD(0x674, 0x210, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__SDMA_DEBUG_RTBUFFER_WRITE		IOMUX_PAD(0x674, 0x210, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_HSYNC__ARM11P_TOP_TRACE_15			IOMUX_PAD(0x674, 0x210, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK			IOMUX_PAD(0x678, 0x214, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__IPU_DISPB_SD_CLK			IOMUX_PAD(0x678, 0x214, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__GPIO3_31				IOMUX_PAD(0x678, 0x214, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__SDMA_SDMA_DEBUG_CORE_STATUS_0	IOMUX_PAD(0x678, 0x214, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_FPSHIFT__ARM11P_TOP_TRACE_16		IOMUX_PAD(0x678, 0x214, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY			IOMUX_PAD(0x67c, 0x218, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__IPU_DISPB_SD_D_O			IOMUX_PAD(0x67c, 0x218, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__GPIO1_0				IOMUX_PAD(0x67c, 0x218, 5, 0x82c, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__SDMA_SDMA_DEBUG_CORE_STATUS_1		IOMUX_PAD(0x67c, 0x218, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_DRDY__ARM11P_TOP_TRACE_17			IOMUX_PAD(0x67c, 0x218, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_CONTRAST__IPU_DISPB_CONTR			IOMUX_PAD(0x680, 0x21c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CONTRAST__GPIO1_1				IOMUX_PAD(0x680, 0x21c, 5, 0x838, 2, NO_PAD_CTRL)
+#define MX35_PAD_CONTRAST__SDMA_SDMA_DEBUG_CORE_STATUS_2	IOMUX_PAD(0x680, 0x21c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_CONTRAST__ARM11P_TOP_TRACE_18			IOMUX_PAD(0x680, 0x21c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC			IOMUX_PAD(0x684, 0x220, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__IPU_DISPB_CS1			IOMUX_PAD(0x684, 0x220, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__GPIO1_2				IOMUX_PAD(0x684, 0x220, 5, 0x848, 1, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__SDMA_DEBUG_YIELD			IOMUX_PAD(0x684, 0x220, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_VSYNC__ARM11P_TOP_TRACE_19			IOMUX_PAD(0x684, 0x220, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_REV__IPU_DISPB_D3_REV			IOMUX_PAD(0x688, 0x224, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__IPU_DISPB_SER_RS			IOMUX_PAD(0x688, 0x224, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__GPIO1_3				IOMUX_PAD(0x688, 0x224, 5, 0x84c, 1, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__SDMA_DEBUG_BUS_RWB			IOMUX_PAD(0x688, 0x224, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_REV__ARM11P_TOP_TRACE_20			IOMUX_PAD(0x688, 0x224, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS			IOMUX_PAD(0x68c, 0x228, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__IPU_DISPB_CS2				IOMUX_PAD(0x68c, 0x228, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__GPIO1_4				IOMUX_PAD(0x68c, 0x228, 5, 0x850, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__SDMA_DEBUG_BUS_DEVICE_0		IOMUX_PAD(0x68c, 0x228, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_CLS__ARM11P_TOP_TRACE_21			IOMUX_PAD(0x68c, 0x228, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL			IOMUX_PAD(0x690, 0x22c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x690, 0x22c, 2, 0x928, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__GPIO1_5				IOMUX_PAD(0x690, 0x22c, 5, 0x854, 2, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__SDMA_DEBUG_BUS_DEVICE_1		IOMUX_PAD(0x690, 0x22c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_D3_SPL__ARM11P_TOP_TRACE_22			IOMUX_PAD(0x690, 0x22c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_CMD__ESDHC1_CMD				IOMUX_PAD(0x694, 0x230, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__MSHC_SCLK				IOMUX_PAD(0x694, 0x230, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x694, 0x230, 3, 0x924, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__USB_TOP_USBOTG_DATA_4			IOMUX_PAD(0x694, 0x230, 4, 0x9b4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__GPIO1_6				IOMUX_PAD(0x694, 0x230, 5, 0x858, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CMD__ARM11P_TOP_TRCTL			IOMUX_PAD(0x694, 0x230, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_CLK__ESDHC1_CLK				IOMUX_PAD(0x698, 0x234, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__MSHC_BS				IOMUX_PAD(0x698, 0x234, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__IPU_DISPB_BCLK			IOMUX_PAD(0x698, 0x234, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__USB_TOP_USBOTG_DATA_5			IOMUX_PAD(0x698, 0x234, 4, 0x9b8, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__GPIO1_7				IOMUX_PAD(0x698, 0x234, 5, 0x85c, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_CLK__ARM11P_TOP_TRCLK			IOMUX_PAD(0x698, 0x234, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA0__ESDHC1_DAT0				IOMUX_PAD(0x69c, 0x238, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__MSHC_DATA_0				IOMUX_PAD(0x69c, 0x238, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__IPU_DISPB_CS0			IOMUX_PAD(0x69c, 0x238, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__USB_TOP_USBOTG_DATA_6		IOMUX_PAD(0x69c, 0x238, 4, 0x9bc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__GPIO1_8				IOMUX_PAD(0x69c, 0x238, 5, 0x860, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA0__ARM11P_TOP_TRACE_23			IOMUX_PAD(0x69c, 0x238, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA1__ESDHC1_DAT1				IOMUX_PAD(0x6a0, 0x23c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__MSHC_DATA_1				IOMUX_PAD(0x6a0, 0x23c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__IPU_DISPB_PAR_RS			IOMUX_PAD(0x6a0, 0x23c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__USB_TOP_USBOTG_DATA_0		IOMUX_PAD(0x6a0, 0x23c, 4, 0x9a4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__GPIO1_9				IOMUX_PAD(0x6a0, 0x23c, 5, 0x864, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA1__ARM11P_TOP_TRACE_24			IOMUX_PAD(0x6a0, 0x23c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA2__ESDHC1_DAT2				IOMUX_PAD(0x6a4, 0x240, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__MSHC_DATA_2				IOMUX_PAD(0x6a4, 0x240, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__IPU_DISPB_WR			IOMUX_PAD(0x6a4, 0x240, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__USB_TOP_USBOTG_DATA_1		IOMUX_PAD(0x6a4, 0x240, 4, 0x9a8, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__GPIO1_10				IOMUX_PAD(0x6a4, 0x240, 5, 0x830, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA2__ARM11P_TOP_TRACE_25			IOMUX_PAD(0x6a4, 0x240, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD1_DATA3__ESDHC1_DAT3				IOMUX_PAD(0x6a8, 0x244, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__MSHC_DATA_3				IOMUX_PAD(0x6a8, 0x244, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__IPU_DISPB_RD			IOMUX_PAD(0x6a8, 0x244, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__USB_TOP_USBOTG_DATA_2		IOMUX_PAD(0x6a8, 0x244, 4, 0x9ac, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__GPIO1_11				IOMUX_PAD(0x6a8, 0x244, 5, 0x834, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD1_DATA3__ARM11P_TOP_TRACE_26			IOMUX_PAD(0x6a8, 0x244, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_CMD__ESDHC2_CMD				IOMUX_PAD(0x6ac, 0x248, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__I2C3_SCL				IOMUX_PAD(0x6ac, 0x248, 1, 0x91c, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__ESDHC1_DAT4				IOMUX_PAD(0x6ac, 0x248, 2, 0x804, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__IPU_CSI_D_2				IOMUX_PAD(0x6ac, 0x248, 3, 0x938, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__USB_TOP_USBH2_DATA_4			IOMUX_PAD(0x6ac, 0x248, 4, 0x9dc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__GPIO2_0				IOMUX_PAD(0x6ac, 0x248, 5, 0x868, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x6ac, 0x248, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CMD__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x6ac, 0x248, 7, 0x928, 3, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_CLK__ESDHC2_CLK				IOMUX_PAD(0x6b0, 0x24c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__I2C3_SDA				IOMUX_PAD(0x6b0, 0x24c, 1, 0x920, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__ESDHC1_DAT5				IOMUX_PAD(0x6b0, 0x24c, 2, 0x808, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__IPU_CSI_D_3				IOMUX_PAD(0x6b0, 0x24c, 3, 0x93c, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__USB_TOP_USBH2_DATA_5			IOMUX_PAD(0x6b0, 0x24c, 4, 0x9e0, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__GPIO2_1				IOMUX_PAD(0x6b0, 0x24c, 5, 0x894, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__SPDIF_SPDIF_IN1			IOMUX_PAD(0x6b0, 0x24c, 6, 0x998, 2, NO_PAD_CTRL)
+#define MX35_PAD_SD2_CLK__IPU_DISPB_CS2				IOMUX_PAD(0x6b0, 0x24c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA0__ESDHC2_DAT0				IOMUX_PAD(0x6b4, 0x250, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__UART3_RXD_MUX			IOMUX_PAD(0x6b4, 0x250, 1, 0x9a0, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__ESDHC1_DAT6				IOMUX_PAD(0x6b4, 0x250, 2, 0x80c, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__IPU_CSI_D_4				IOMUX_PAD(0x6b4, 0x250, 3, 0x940, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__USB_TOP_USBH2_DATA_6		IOMUX_PAD(0x6b4, 0x250, 4, 0x9e4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__GPIO2_2				IOMUX_PAD(0x6b4, 0x250, 5, 0x8c0, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA0__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x6b4, 0x250, 6, 0x994, 3, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA1__ESDHC2_DAT1				IOMUX_PAD(0x6b8, 0x254, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__UART3_TXD_MUX			IOMUX_PAD(0x6b8, 0x254, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__ESDHC1_DAT7				IOMUX_PAD(0x6b8, 0x254, 2, 0x810, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__IPU_CSI_D_5				IOMUX_PAD(0x6b8, 0x254, 3, 0x944, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__USB_TOP_USBH2_DATA_0		IOMUX_PAD(0x6b8, 0x254, 4, 0x9cc, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA1__GPIO2_3				IOMUX_PAD(0x6b8, 0x254, 5, 0x8cc, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA2__ESDHC2_DAT2				IOMUX_PAD(0x6bc, 0x258, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__UART3_RTS				IOMUX_PAD(0x6bc, 0x258, 1, 0x99c, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__CAN1_RXCAN				IOMUX_PAD(0x6bc, 0x258, 2, 0x7c8, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__IPU_CSI_D_6				IOMUX_PAD(0x6bc, 0x258, 3, 0x948, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__USB_TOP_USBH2_DATA_1		IOMUX_PAD(0x6bc, 0x258, 4, 0x9d0, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA2__GPIO2_4				IOMUX_PAD(0x6bc, 0x258, 5, 0x8d0, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_SD2_DATA3__ESDHC2_DAT3				IOMUX_PAD(0x6c0, 0x25c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__UART3_CTS				IOMUX_PAD(0x6c0, 0x25c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__CAN1_TXCAN				IOMUX_PAD(0x6c0, 0x25c, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__IPU_CSI_D_7				IOMUX_PAD(0x6c0, 0x25c, 3, 0x94c, 1, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__USB_TOP_USBH2_DATA_2		IOMUX_PAD(0x6c0, 0x25c, 4, 0x9d4, 0, NO_PAD_CTRL)
+#define MX35_PAD_SD2_DATA3__GPIO2_5				IOMUX_PAD(0x6c0, 0x25c, 5, 0x8d4, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_CS0__ATA_CS0				IOMUX_PAD(0x6c4, 0x260, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__CSPI1_SS3				IOMUX_PAD(0x6c4, 0x260, 1, 0x7dc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__IPU_DISPB_CS1				IOMUX_PAD(0x6c4, 0x260, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__GPIO2_6				IOMUX_PAD(0x6c4, 0x260, 5, 0x8d8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__IPU_DIAGB_0				IOMUX_PAD(0x6c4, 0x260, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS0__ARM11P_TOP_MAX1_HMASTER_0		IOMUX_PAD(0x6c4, 0x260, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_CS1__ATA_CS1				IOMUX_PAD(0x6c8, 0x264, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__IPU_DISPB_CS2				IOMUX_PAD(0x6c8, 0x264, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__CSPI2_SS0				IOMUX_PAD(0x6c8, 0x264, 4, 0x7f0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__GPIO2_7				IOMUX_PAD(0x6c8, 0x264, 5, 0x8dc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__IPU_DIAGB_1				IOMUX_PAD(0x6c8, 0x264, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_CS1__ARM11P_TOP_MAX1_HMASTER_1		IOMUX_PAD(0x6c8, 0x264, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DIOR__ATA_DIOR				IOMUX_PAD(0x6cc, 0x268, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__ESDHC3_DAT0				IOMUX_PAD(0x6cc, 0x268, 1, 0x81c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__USB_TOP_USBOTG_DIR			IOMUX_PAD(0x6cc, 0x268, 2, 0x9c4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__IPU_DISPB_BE0			IOMUX_PAD(0x6cc, 0x268, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__CSPI2_SS1				IOMUX_PAD(0x6cc, 0x268, 4, 0x7f4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__GPIO2_8				IOMUX_PAD(0x6cc, 0x268, 5, 0x8e0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__IPU_DIAGB_2				IOMUX_PAD(0x6cc, 0x268, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOR__ARM11P_TOP_MAX1_HMASTER_2		IOMUX_PAD(0x6cc, 0x268, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DIOW__ATA_DIOW				IOMUX_PAD(0x6d0, 0x26c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__ESDHC3_DAT1				IOMUX_PAD(0x6d0, 0x26c, 1, 0x820, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__USB_TOP_USBOTG_STP			IOMUX_PAD(0x6d0, 0x26c, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__IPU_DISPB_BE1			IOMUX_PAD(0x6d0, 0x26c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__CSPI2_MOSI				IOMUX_PAD(0x6d0, 0x26c, 4, 0x7ec, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__GPIO2_9				IOMUX_PAD(0x6d0, 0x26c, 5, 0x8e4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__IPU_DIAGB_3				IOMUX_PAD(0x6d0, 0x26c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DIOW__ARM11P_TOP_MAX1_HMASTER_3		IOMUX_PAD(0x6d0, 0x26c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DMACK__ATA_DMACK				IOMUX_PAD(0x6d4, 0x270, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__ESDHC3_DAT2				IOMUX_PAD(0x6d4, 0x270, 1, 0x824, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__USB_TOP_USBOTG_NXT			IOMUX_PAD(0x6d4, 0x270, 2, 0x9c8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__CSPI2_MISO				IOMUX_PAD(0x6d4, 0x270, 4, 0x7e8, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__GPIO2_10				IOMUX_PAD(0x6d4, 0x270, 5, 0x86c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__IPU_DIAGB_4				IOMUX_PAD(0x6d4, 0x270, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMACK__ARM11P_TOP_MAX0_HMASTER_0		IOMUX_PAD(0x6d4, 0x270, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_RESET_B__ATA_RESET_B			IOMUX_PAD(0x6d8, 0x274, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__ESDHC3_DAT3			IOMUX_PAD(0x6d8, 0x274, 1, 0x828, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__USB_TOP_USBOTG_DATA_0		IOMUX_PAD(0x6d8, 0x274, 2, 0x9a4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__IPU_DISPB_SD_D_O			IOMUX_PAD(0x6d8, 0x274, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__CSPI2_RDY				IOMUX_PAD(0x6d8, 0x274, 4, 0x7e4, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__GPIO2_11				IOMUX_PAD(0x6d8, 0x274, 5, 0x870, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__IPU_DIAGB_5			IOMUX_PAD(0x6d8, 0x274, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_RESET_B__ARM11P_TOP_MAX0_HMASTER_1		IOMUX_PAD(0x6d8, 0x274, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_IORDY__ATA_IORDY				IOMUX_PAD(0x6dc, 0x278, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__ESDHC3_DAT4				IOMUX_PAD(0x6dc, 0x278, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__USB_TOP_USBOTG_DATA_1		IOMUX_PAD(0x6dc, 0x278, 2, 0x9a8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x6dc, 0x278, 3, 0x92c, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__ESDHC2_DAT4				IOMUX_PAD(0x6dc, 0x278, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__GPIO2_12				IOMUX_PAD(0x6dc, 0x278, 5, 0x874, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__IPU_DIAGB_6				IOMUX_PAD(0x6dc, 0x278, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_IORDY__ARM11P_TOP_MAX0_HMASTER_2		IOMUX_PAD(0x6dc, 0x278, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA0__ATA_DATA_0				IOMUX_PAD(0x6e0, 0x27c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__ESDHC3_DAT5				IOMUX_PAD(0x6e0, 0x27c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__USB_TOP_USBOTG_DATA_2		IOMUX_PAD(0x6e0, 0x27c, 2, 0x9ac, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__IPU_DISPB_D12_VSYNC			IOMUX_PAD(0x6e0, 0x27c, 3, 0x928, 4, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__ESDHC2_DAT5				IOMUX_PAD(0x6e0, 0x27c, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__GPIO2_13				IOMUX_PAD(0x6e0, 0x27c, 5, 0x878, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__IPU_DIAGB_7				IOMUX_PAD(0x6e0, 0x27c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA0__ARM11P_TOP_MAX0_HMASTER_3		IOMUX_PAD(0x6e0, 0x27c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA1__ATA_DATA_1				IOMUX_PAD(0x6e4, 0x280, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__ESDHC3_DAT6				IOMUX_PAD(0x6e4, 0x280, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__USB_TOP_USBOTG_DATA_3		IOMUX_PAD(0x6e4, 0x280, 2, 0x9b0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__IPU_DISPB_SD_CLK			IOMUX_PAD(0x6e4, 0x280, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__ESDHC2_DAT6				IOMUX_PAD(0x6e4, 0x280, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__GPIO2_14				IOMUX_PAD(0x6e4, 0x280, 5, 0x87c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__IPU_DIAGB_8				IOMUX_PAD(0x6e4, 0x280, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA1__ARM11P_TOP_TRACE_27			IOMUX_PAD(0x6e4, 0x280, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA2__ATA_DATA_2				IOMUX_PAD(0x6e8, 0x284, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__ESDHC3_DAT7				IOMUX_PAD(0x6e8, 0x284, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__USB_TOP_USBOTG_DATA_4		IOMUX_PAD(0x6e8, 0x284, 2, 0x9b4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__IPU_DISPB_SER_RS			IOMUX_PAD(0x6e8, 0x284, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__ESDHC2_DAT7				IOMUX_PAD(0x6e8, 0x284, 4, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__GPIO2_15				IOMUX_PAD(0x6e8, 0x284, 5, 0x880, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__IPU_DIAGB_9				IOMUX_PAD(0x6e8, 0x284, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28			IOMUX_PAD(0x6e8, 0x284, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA3__ATA_DATA_3				IOMUX_PAD(0x6e8, 0x288, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ESDHC3_CLK				IOMUX_PAD(0x6e8, 0x288, 1, 0x814, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5		IOMUX_PAD(0x6e8, 0x288, 2, 0x9b8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__CSPI2_SCLK				IOMUX_PAD(0x6e8, 0x288, 4, 0x7e0, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__GPIO2_16				IOMUX_PAD(0x6e8, 0x288, 5, 0x884, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__IPU_DIAGB_10			IOMUX_PAD(0x6e8, 0x288, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29			IOMUX_PAD(0x6e8, 0x288, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA4__ATA_DATA_4				IOMUX_PAD(0x6f0, 0x28c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__ESDHC3_CMD				IOMUX_PAD(0x6f0, 0x28c, 1, 0x818, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__USB_TOP_USBOTG_DATA_6		IOMUX_PAD(0x6f0, 0x28c, 2, 0x9bc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__GPIO2_17				IOMUX_PAD(0x6f0, 0x28c, 5, 0x888, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__IPU_DIAGB_11			IOMUX_PAD(0x6f0, 0x28c, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA4__ARM11P_TOP_TRACE_30			IOMUX_PAD(0x6f0, 0x28c, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA5__ATA_DATA_5				IOMUX_PAD(0x6f4, 0x290, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__USB_TOP_USBOTG_DATA_7		IOMUX_PAD(0x6f4, 0x290, 2, 0x9c0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__GPIO2_18				IOMUX_PAD(0x6f4, 0x290, 5, 0x88c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__IPU_DIAGB_12			IOMUX_PAD(0x6f4, 0x290, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA5__ARM11P_TOP_TRACE_31			IOMUX_PAD(0x6f4, 0x290, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA6__ATA_DATA_6				IOMUX_PAD(0x6f8, 0x294, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__CAN1_TXCAN				IOMUX_PAD(0x6f8, 0x294, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__UART1_DTR				IOMUX_PAD(0x6f8, 0x294, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__AUDMUX_AUD6_TXD			IOMUX_PAD(0x6f8, 0x294, 3, 0x7b4, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__GPIO2_19				IOMUX_PAD(0x6f8, 0x294, 5, 0x890, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA6__IPU_DIAGB_13			IOMUX_PAD(0x6f8, 0x294, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA7__ATA_DATA_7				IOMUX_PAD(0x6fc, 0x298, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__CAN1_RXCAN				IOMUX_PAD(0x6fc, 0x298, 1, 0x7c8, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__UART1_DSR				IOMUX_PAD(0x6fc, 0x298, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__AUDMUX_AUD6_RXD			IOMUX_PAD(0x6fc, 0x298, 3, 0x7b0, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__GPIO2_20				IOMUX_PAD(0x6fc, 0x298, 5, 0x898, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA7__IPU_DIAGB_14			IOMUX_PAD(0x6fc, 0x298, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA8__ATA_DATA_8				IOMUX_PAD(0x700, 0x29c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__UART3_RTS				IOMUX_PAD(0x700, 0x29c, 1, 0x99c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__UART1_RI				IOMUX_PAD(0x700, 0x29c, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__AUDMUX_AUD6_TXC			IOMUX_PAD(0x700, 0x29c, 3, 0x7c0, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__GPIO2_21				IOMUX_PAD(0x700, 0x29c, 5, 0x89c, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA8__IPU_DIAGB_15			IOMUX_PAD(0x700, 0x29c, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA9__ATA_DATA_9				IOMUX_PAD(0x704, 0x2a0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__UART3_CTS				IOMUX_PAD(0x704, 0x2a0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__UART1_DCD				IOMUX_PAD(0x704, 0x2a0, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__AUDMUX_AUD6_TXFS			IOMUX_PAD(0x704, 0x2a0, 3, 0x7c4, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__GPIO2_22				IOMUX_PAD(0x704, 0x2a0, 5, 0x8a0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA9__IPU_DIAGB_16			IOMUX_PAD(0x704, 0x2a0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA10__ATA_DATA_10			IOMUX_PAD(0x708, 0x2a4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__UART3_RXD_MUX			IOMUX_PAD(0x708, 0x2a4, 1, 0x9a0, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__AUDMUX_AUD6_RXC			IOMUX_PAD(0x708, 0x2a4, 3, 0x7b8, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__GPIO2_23				IOMUX_PAD(0x708, 0x2a4, 5, 0x8a4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA10__IPU_DIAGB_17			IOMUX_PAD(0x708, 0x2a4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA11__ATA_DATA_11			IOMUX_PAD(0x70c, 0x2a8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__UART3_TXD_MUX			IOMUX_PAD(0x70c, 0x2a8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__AUDMUX_AUD6_RXFS			IOMUX_PAD(0x70c, 0x2a8, 3, 0x7bc, 0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__GPIO2_24				IOMUX_PAD(0x70c, 0x2a8, 5, 0x8a8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA11__IPU_DIAGB_18			IOMUX_PAD(0x70c, 0x2a8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA12__ATA_DATA_12			IOMUX_PAD(0x710, 0x2ac, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA12__I2C3_SCL				IOMUX_PAD(0x710, 0x2ac, 1, 0x91c, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA12__GPIO2_25				IOMUX_PAD(0x710, 0x2ac, 5, 0x8ac, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA12__IPU_DIAGB_19			IOMUX_PAD(0x710, 0x2ac, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA13__ATA_DATA_13			IOMUX_PAD(0x714, 0x2b0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA13__I2C3_SDA				IOMUX_PAD(0x714, 0x2b0, 1, 0x920, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA13__GPIO2_26				IOMUX_PAD(0x714, 0x2b0, 5, 0x8b0, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA13__IPU_DIAGB_20			IOMUX_PAD(0x714, 0x2b0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA14__ATA_DATA_14			IOMUX_PAD(0x718, 0x2b4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__IPU_CSI_D_0			IOMUX_PAD(0x718, 0x2b4, 1, 0x930, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__KPP_ROW_0				IOMUX_PAD(0x718, 0x2b4, 3, 0x970, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__GPIO2_27				IOMUX_PAD(0x718, 0x2b4, 5, 0x8b4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA14__IPU_DIAGB_21			IOMUX_PAD(0x718, 0x2b4, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DATA15__ATA_DATA_15			IOMUX_PAD(0x71c, 0x2b8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__IPU_CSI_D_1			IOMUX_PAD(0x71c, 0x2b8, 1, 0x934, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__KPP_ROW_1				IOMUX_PAD(0x71c, 0x2b8, 3, 0x974, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__GPIO2_28				IOMUX_PAD(0x71c, 0x2b8, 5, 0x8b8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA15__IPU_DIAGB_22			IOMUX_PAD(0x71c, 0x2b8, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_INTRQ__ATA_INTRQ				IOMUX_PAD(0x720, 0x2bc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__IPU_CSI_D_2				IOMUX_PAD(0x720, 0x2bc, 1, 0x938, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__KPP_ROW_2				IOMUX_PAD(0x720, 0x2bc, 3, 0x978, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__GPIO2_29				IOMUX_PAD(0x720, 0x2bc, 5, 0x8bc, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_INTRQ__IPU_DIAGB_23			IOMUX_PAD(0x720, 0x2bc, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_BUFF_EN__ATA_BUFFER_EN			IOMUX_PAD(0x724, 0x2c0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__IPU_CSI_D_3			IOMUX_PAD(0x724, 0x2c0, 1, 0x93c, 3, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__KPP_ROW_3				IOMUX_PAD(0x724, 0x2c0, 3, 0x97c, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__GPIO2_30				IOMUX_PAD(0x724, 0x2c0, 5, 0x8c4, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_BUFF_EN__IPU_DIAGB_24			IOMUX_PAD(0x724, 0x2c0, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DMARQ__ATA_DMARQ				IOMUX_PAD(0x728, 0x2c4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__IPU_CSI_D_4				IOMUX_PAD(0x728, 0x2c4, 1, 0x940, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__KPP_COL_0				IOMUX_PAD(0x728, 0x2c4, 3, 0x950, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__GPIO2_31				IOMUX_PAD(0x728, 0x2c4, 5, 0x8c8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__IPU_DIAGB_25			IOMUX_PAD(0x728, 0x2c4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DMARQ__ECT_CTI_TRIG_IN1_4			IOMUX_PAD(0x728, 0x2c4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DA0__ATA_DA_0				IOMUX_PAD(0x72c, 0x2c8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__IPU_CSI_D_5				IOMUX_PAD(0x72c, 0x2c8, 1, 0x944, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__KPP_COL_1				IOMUX_PAD(0x72c, 0x2c8, 3, 0x954, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__GPIO3_0				IOMUX_PAD(0x72c, 0x2c8, 5, 0x8e8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__IPU_DIAGB_26				IOMUX_PAD(0x72c, 0x2c8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA0__ECT_CTI_TRIG_IN1_5			IOMUX_PAD(0x72c, 0x2c8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DA1__ATA_DA_1				IOMUX_PAD(0x730, 0x2cc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__IPU_CSI_D_6				IOMUX_PAD(0x730, 0x2cc, 1, 0x948, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__KPP_COL_2				IOMUX_PAD(0x730, 0x2cc, 3, 0x958, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__GPIO3_1				IOMUX_PAD(0x730, 0x2cc, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__IPU_DIAGB_27				IOMUX_PAD(0x730, 0x2cc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA1__ECT_CTI_TRIG_IN1_6			IOMUX_PAD(0x730, 0x2cc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_ATA_DA2__ATA_DA_2				IOMUX_PAD(0x734, 0x2d0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__IPU_CSI_D_7				IOMUX_PAD(0x734, 0x2d0, 1, 0x94c, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__KPP_COL_3				IOMUX_PAD(0x734, 0x2d0, 3, 0x95c, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__GPIO3_2				IOMUX_PAD(0x734, 0x2d0, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__IPU_DIAGB_28				IOMUX_PAD(0x734, 0x2d0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DA2__ECT_CTI_TRIG_IN1_7			IOMUX_PAD(0x734, 0x2d0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_MLB_CLK__MLB_MLBCLK				IOMUX_PAD(0x738, 0x2d4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_MLB_CLK__GPIO3_3				IOMUX_PAD(0x738, 0x2d4, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_MLB_DAT__MLB_MLBDAT				IOMUX_PAD(0x73c, 0x2d8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_MLB_DAT__GPIO3_4				IOMUX_PAD(0x73c, 0x2d8, 5, 0x904, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_MLB_SIG__MLB_MLBSIG				IOMUX_PAD(0x740, 0x2dc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_MLB_SIG__GPIO3_5				IOMUX_PAD(0x740, 0x2dc, 5, 0x908, 1, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TX_CLK__FEC_TX_CLK				IOMUX_PAD(0x744, 0x2e0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__ESDHC1_DAT4			IOMUX_PAD(0x744, 0x2e0, 1, 0x804, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__UART3_RXD_MUX			IOMUX_PAD(0x744, 0x2e0, 2, 0x9a0, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__USB_TOP_USBH2_DIR			IOMUX_PAD(0x744, 0x2e0, 3, 0x9ec, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__CSPI2_MOSI				IOMUX_PAD(0x744, 0x2e0, 4, 0x7ec, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__GPIO3_6				IOMUX_PAD(0x744, 0x2e0, 5, 0x90c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__IPU_DISPB_D12_VSYNC		IOMUX_PAD(0x744, 0x2e0, 6, 0x928, 5, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_CLK__ARM11P_TOP_EVNTBUS_0		IOMUX_PAD(0x744, 0x2e0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RX_CLK__FEC_RX_CLK				IOMUX_PAD(0x748, 0x2e4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__ESDHC1_DAT5			IOMUX_PAD(0x748, 0x2e4, 1, 0x808, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__UART3_TXD_MUX			IOMUX_PAD(0x748, 0x2e4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__USB_TOP_USBH2_STP			IOMUX_PAD(0x748, 0x2e4, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__CSPI2_MISO				IOMUX_PAD(0x748, 0x2e4, 4, 0x7e8, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__GPIO3_7				IOMUX_PAD(0x748, 0x2e4, 5, 0x910, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__IPU_DISPB_SD_D_I			IOMUX_PAD(0x748, 0x2e4, 6, 0x92c, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_CLK__ARM11P_TOP_EVNTBUS_1		IOMUX_PAD(0x748, 0x2e4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RX_DV__FEC_RX_DV				IOMUX_PAD(0x74c, 0x2e8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__ESDHC1_DAT6				IOMUX_PAD(0x74c, 0x2e8, 1, 0x80c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__UART3_RTS				IOMUX_PAD(0x74c, 0x2e8, 2, 0x99c, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__USB_TOP_USBH2_NXT			IOMUX_PAD(0x74c, 0x2e8, 3, 0x9f0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__CSPI2_SCLK				IOMUX_PAD(0x74c, 0x2e8, 4, 0x7e0, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__GPIO3_8				IOMUX_PAD(0x74c, 0x2e8, 5, 0x914, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__IPU_DISPB_SD_CLK			IOMUX_PAD(0x74c, 0x2e8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_DV__ARM11P_TOP_EVNTBUS_2		IOMUX_PAD(0x74c, 0x2e8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_COL__FEC_COL				IOMUX_PAD(0x750, 0x2ec, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__ESDHC1_DAT7				IOMUX_PAD(0x750, 0x2ec, 1, 0x810, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__UART3_CTS				IOMUX_PAD(0x750, 0x2ec, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__USB_TOP_USBH2_DATA_0			IOMUX_PAD(0x750, 0x2ec, 3, 0x9cc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__CSPI2_RDY				IOMUX_PAD(0x750, 0x2ec, 4, 0x7e4, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__GPIO3_9				IOMUX_PAD(0x750, 0x2ec, 5, 0x918, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__IPU_DISPB_SER_RS			IOMUX_PAD(0x750, 0x2ec, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_COL__ARM11P_TOP_EVNTBUS_3			IOMUX_PAD(0x750, 0x2ec, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA0__FEC_RDATA_0			IOMUX_PAD(0x754, 0x2f0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__PWM_PWMO				IOMUX_PAD(0x754, 0x2f0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__UART3_DTR				IOMUX_PAD(0x754, 0x2f0, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__USB_TOP_USBH2_DATA_1		IOMUX_PAD(0x754, 0x2f0, 3, 0x9d0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__CSPI2_SS0				IOMUX_PAD(0x754, 0x2f0, 4, 0x7f0, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__GPIO3_10				IOMUX_PAD(0x754, 0x2f0, 5, 0x8ec, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__IPU_DISPB_CS1			IOMUX_PAD(0x754, 0x2f0, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA0__ARM11P_TOP_EVNTBUS_4		IOMUX_PAD(0x754, 0x2f0, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA0__FEC_TDATA_0			IOMUX_PAD(0x758, 0x2f4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__SPDIF_SPDIF_OUT1			IOMUX_PAD(0x758, 0x2f4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__UART3_DSR				IOMUX_PAD(0x758, 0x2f4, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__USB_TOP_USBH2_DATA_2		IOMUX_PAD(0x758, 0x2f4, 3, 0x9d4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__CSPI2_SS1				IOMUX_PAD(0x758, 0x2f4, 4, 0x7f4, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__GPIO3_11				IOMUX_PAD(0x758, 0x2f4, 5, 0x8f0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__IPU_DISPB_CS0			IOMUX_PAD(0x758, 0x2f4, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA0__ARM11P_TOP_EVNTBUS_5		IOMUX_PAD(0x758, 0x2f4, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TX_EN__FEC_TX_EN				IOMUX_PAD(0x75c, 0x2f8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__SPDIF_SPDIF_IN1			IOMUX_PAD(0x75c, 0x2f8, 1, 0x998, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__UART3_RI				IOMUX_PAD(0x75c, 0x2f8, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__USB_TOP_USBH2_DATA_3		IOMUX_PAD(0x75c, 0x2f8, 3, 0x9d8, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__GPIO3_12				IOMUX_PAD(0x75c, 0x2f8, 5, 0x8f4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__IPU_DISPB_PAR_RS			IOMUX_PAD(0x75c, 0x2f8, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_EN__ARM11P_TOP_EVNTBUS_6		IOMUX_PAD(0x75c, 0x2f8, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_MDC__FEC_MDC				IOMUX_PAD(0x760, 0x2fc, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__CAN2_TXCAN				IOMUX_PAD(0x760, 0x2fc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__UART3_DCD				IOMUX_PAD(0x760, 0x2fc, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__USB_TOP_USBH2_DATA_4			IOMUX_PAD(0x760, 0x2fc, 3, 0x9dc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__GPIO3_13				IOMUX_PAD(0x760, 0x2fc, 5, 0x8f8, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__IPU_DISPB_WR				IOMUX_PAD(0x760, 0x2fc, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDC__ARM11P_TOP_EVNTBUS_7			IOMUX_PAD(0x760, 0x2fc, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_MDIO__FEC_MDIO				IOMUX_PAD(0x764, 0x300, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__CAN2_RXCAN				IOMUX_PAD(0x764, 0x300, 1, 0x7cc, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__USB_TOP_USBH2_DATA_5			IOMUX_PAD(0x764, 0x300, 3, 0x9e0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__GPIO3_14				IOMUX_PAD(0x764, 0x300, 5, 0x8fc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__IPU_DISPB_RD				IOMUX_PAD(0x764, 0x300, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_MDIO__ARM11P_TOP_EVNTBUS_8			IOMUX_PAD(0x764, 0x300, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TX_ERR__FEC_TX_ERR				IOMUX_PAD(0x768, 0x304, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__OWIRE_LINE				IOMUX_PAD(0x768, 0x304, 1, 0x990, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__SPDIF_SPDIF_EXTCLK			IOMUX_PAD(0x768, 0x304, 2, 0x994, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__USB_TOP_USBH2_DATA_6		IOMUX_PAD(0x768, 0x304, 3, 0x9e4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__GPIO3_15				IOMUX_PAD(0x768, 0x304, 5, 0x900, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__IPU_DISPB_D0_VSYNC			IOMUX_PAD(0x768, 0x304, 6, 0x924, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TX_ERR__ARM11P_TOP_EVNTBUS_9		IOMUX_PAD(0x768, 0x304, 7, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RX_ERR__FEC_RX_ERR				IOMUX_PAD(0x76c, 0x308, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__IPU_CSI_D_0			IOMUX_PAD(0x76c, 0x308, 1, 0x930, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__USB_TOP_USBH2_DATA_7		IOMUX_PAD(0x76c, 0x308, 3, 0x9e8, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__KPP_COL_4				IOMUX_PAD(0x76c, 0x308, 4, 0x960, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__GPIO3_16				IOMUX_PAD(0x76c, 0x308, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RX_ERR__IPU_DISPB_SD_D_IO			IOMUX_PAD(0x76c, 0x308, 6, 0x92c, 5, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_CRS__FEC_CRS				IOMUX_PAD(0x770, 0x30c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__IPU_CSI_D_1				IOMUX_PAD(0x770, 0x30c, 1, 0x934, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__USB_TOP_USBH2_PWR			IOMUX_PAD(0x770, 0x30c, 3, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__KPP_COL_5				IOMUX_PAD(0x770, 0x30c, 4, 0x964, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__GPIO3_17				IOMUX_PAD(0x770, 0x30c, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_CRS__IPU_FLASH_STROBE			IOMUX_PAD(0x770, 0x30c, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA1__FEC_RDATA_1			IOMUX_PAD(0x774, 0x310, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__IPU_CSI_D_2			IOMUX_PAD(0x774, 0x310, 1, 0x938, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__AUDMUX_AUD6_RXC			IOMUX_PAD(0x774, 0x310, 2, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__USB_TOP_USBH2_OC			IOMUX_PAD(0x774, 0x310, 3, 0x9f4, 2, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__KPP_COL_6				IOMUX_PAD(0x774, 0x310, 4, 0x968, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__GPIO3_18				IOMUX_PAD(0x774, 0x310, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA1__IPU_DISPB_BE0			IOMUX_PAD(0x774, 0x310, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA1__FEC_TDATA_1			IOMUX_PAD(0x778, 0x314, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__IPU_CSI_D_3			IOMUX_PAD(0x778, 0x314, 1, 0x93c, 4, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__AUDMUX_AUD6_RXFS			IOMUX_PAD(0x778, 0x314, 2, 0x7bc, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__KPP_COL_7				IOMUX_PAD(0x778, 0x314, 4, 0x96c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__GPIO3_19				IOMUX_PAD(0x778, 0x314, 5, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA1__IPU_DISPB_BE1			IOMUX_PAD(0x778, 0x314, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA2__FEC_RDATA_2			IOMUX_PAD(0x77c, 0x318, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__IPU_CSI_D_4			IOMUX_PAD(0x77c, 0x318, 1, 0x940, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__AUDMUX_AUD6_TXD			IOMUX_PAD(0x77c, 0x318, 2, 0x7b4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__KPP_ROW_4				IOMUX_PAD(0x77c, 0x318, 4, 0x980, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA2__GPIO3_20				IOMUX_PAD(0x77c, 0x318, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA2__FEC_TDATA_2			IOMUX_PAD(0x780, 0x31c, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__IPU_CSI_D_5			IOMUX_PAD(0x780, 0x31c, 1, 0x944, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__AUDMUX_AUD6_RXD			IOMUX_PAD(0x780, 0x31c, 2, 0x7b0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__KPP_ROW_5				IOMUX_PAD(0x780, 0x31c, 4, 0x984, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA2__GPIO3_21				IOMUX_PAD(0x780, 0x31c, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_RDATA3__FEC_RDATA_3			IOMUX_PAD(0x784, 0x320, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__IPU_CSI_D_6			IOMUX_PAD(0x784, 0x320, 1, 0x948, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__AUDMUX_AUD6_TXC			IOMUX_PAD(0x784, 0x320, 2, 0x7c0, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__KPP_ROW_6				IOMUX_PAD(0x784, 0x320, 4, 0x988, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_RDATA3__GPIO3_22				IOMUX_PAD(0x784, 0x320, 6, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_FEC_TDATA3__FEC_TDATA_3			IOMUX_PAD(0x788, 0x324, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__IPU_CSI_D_7			IOMUX_PAD(0x788, 0x324, 1, 0x94c, 3, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__AUDMUX_AUD6_TXFS			IOMUX_PAD(0x788, 0x324, 2, 0x7c4, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__KPP_ROW_7				IOMUX_PAD(0x788, 0x324, 4, 0x98c, 1, NO_PAD_CTRL)
+#define MX35_PAD_FEC_TDATA3__GPIO3_23				IOMUX_PAD(0x788, 0x324, 5, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_EXT_ARMCLK__CCM_EXT_ARMCLK			IOMUX_PAD(0x78c, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+#define MX35_PAD_TEST_MODE__TCU_TEST_MODE			IOMUX_PAD(0x790, 0x0,   0, 0x0,   0, NO_PAD_CTRL)
+
+
+#endif /* __MACH_IOMUX_MX35_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2009-09-09 18:13:59.000000000 -0400
@@ -114,7 +114,7 @@
  * 	- setups the iomux according to the configuration
  * 	- if the pin is configured as a GPIO, we claim it throug kernel gpiolib
  */
-int mxc_iomux_setup_pin(const unsigned int pin, const char *label);
+int mxc_iomux_alloc_pin(const unsigned int pin, const char *label);
 /*
  * setups mutliple pins
  * convenient way to call the above function with tables
@@ -602,6 +602,8 @@
 #define MX31_PIN_I2C_DAT__SDA		IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_DCD_DTE1__I2C2_SDA	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
 #define MX31_PIN_RI_DTE1__I2C2_SCL	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_CSPI2_SS2__I2C3_SDA	IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI2_SCLK__I2C3_SCL	IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_CSI_D4__CSI_D4		IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSI_D5__CSI_D5		IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSI_D6__CSI_D6		IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
@@ -633,6 +635,40 @@
 #define MX31_PIN_USBOTG_DIR__USBOTG_DIR        IOMUX_MODE(MX31_PIN_USBOTG_DIR, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_USBOTG_NXT__USBOTG_NXT        IOMUX_MODE(MX31_PIN_USBOTG_NXT, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_USBOTG_STP__USBOTG_STP        IOMUX_MODE(MX31_PIN_USBOTG_STP, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USB_OC__GPIO1_30	IOMUX_MODE(MX31_PIN_USB_OC, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_I2C_DAT__I2C1_SDA	IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_I2C_CLK__I2C1_SCL	IOMUX_MODE(MX31_PIN_I2C_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DCD_DTE1__I2C2_SDA	IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_RI_DTE1__I2C2_SCL	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_ATA_CS0__GPIO3_26	IOMUX_MODE(MX31_PIN_ATA_CS0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_CS1__GPIO3_27	IOMUX_MODE(MX31_PIN_ATA_CS1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_PC_PWRON__SD2_DATA3	IOMUX_MODE(MX31_PIN_PC_PWRON, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_VS1__SD2_DATA2	IOMUX_MODE(MX31_PIN_PC_VS1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_READY__SD2_DATA1	IOMUX_MODE(MX31_PIN_PC_READY, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_WAIT_B__SD2_DATA0	IOMUX_MODE(MX31_PIN_PC_WAIT_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD2_B__SD2_CLK	IOMUX_MODE(MX31_PIN_PC_CD2_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_PC_CD1_B__SD2_CMD	IOMUX_MODE(MX31_PIN_PC_CD1_B, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_ATA_DIOR__GPIO3_28	IOMUX_MODE(MX31_PIN_ATA_DIOR, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_ATA_DIOW__GPIO3_29	IOMUX_MODE(MX31_PIN_ATA_DIOW, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_CSI_D4__CSI_D4		IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D5__CSI_D5		IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D6__CSI_D6		IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D7__CSI_D7		IOMUX_MODE(MX31_PIN_CSI_D7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D8__CSI_D8		IOMUX_MODE(MX31_PIN_CSI_D8, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D9__CSI_D9		IOMUX_MODE(MX31_PIN_CSI_D9, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D10__CSI_D10	IOMUX_MODE(MX31_PIN_CSI_D10, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D11__CSI_D11	IOMUX_MODE(MX31_PIN_CSI_D11, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D12__CSI_D12	IOMUX_MODE(MX31_PIN_CSI_D12, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D13__CSI_D13	IOMUX_MODE(MX31_PIN_CSI_D13, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D14__CSI_D14	IOMUX_MODE(MX31_PIN_CSI_D14, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_D15__CSI_D15	IOMUX_MODE(MX31_PIN_CSI_D15, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_HSYNC__CSI_HSYNC	IOMUX_MODE(MX31_PIN_CSI_HSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_MCLK__CSI_MCLK	IOMUX_MODE(MX31_PIN_CSI_MCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_PIXCLK__CSI_PIXCLK	IOMUX_MODE(MX31_PIN_CSI_PIXCLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSI_VSYNC__CSI_VSYNC	IOMUX_MODE(MX31_PIN_CSI_VSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_GPIO3_0__GPIO3_0	IOMUX_MODE(MX31_PIN_GPIO3_0, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_GPIO3_1__GPIO3_1	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_TXD2__GPIO1_28		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO)
 
 /*XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed by cspi2_ss0, cspi2_ss1, cspi1_ss0
  * cspi1_ss1*/
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/iomux-v3.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *			<armlinux@phytec.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.
+ * 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.
+ */
+
+#ifndef __MACH_IOMUX_V3_H__
+#define __MACH_IOMUX_V3_H__
+
+/*
+ *	build IOMUX_PAD structure
+ *
+ * This iomux scheme is based around pads, which are the physical balls
+ * on the processor.
+ *
+ * - Each pad has a pad control register (IOMUXC_SW_PAD_CTRL_x) which controls
+ *   things like driving strength and pullup/pulldown.
+ * - Each pad can have but not necessarily does have an output routing register
+ *   (IOMUXC_SW_MUX_CTL_PAD_x).
+ * - Each pad can have but not necessarily does have an input routing register
+ *   (IOMUXC_x_SELECT_INPUT)
+ *
+ * The three register sets do not have a fixed offset to each other,
+ * hence we order this table by pad control registers (which all pads
+ * have) and put the optional i/o routing registers into additional
+ * fields.
+ *
+ * The naming convention for the pad modes is MX35_PAD_<padname>__<padmode>
+ * If <padname> or <padmode> refers to a GPIO, it is named
+ * GPIO_<unit>_<num>
+ *
+ */
+
+struct pad_desc {
+	unsigned mux_ctrl_ofs:12; /* IOMUXC_SW_MUX_CTL_PAD offset */
+	unsigned mux_mode:8;
+	unsigned pad_ctrl_ofs:12; /* IOMUXC_SW_PAD_CTRL offset */
+#define	NO_PAD_CTRL	(1 << 16)
+	unsigned pad_ctrl:17;
+	unsigned select_input_ofs:12; /* IOMUXC_SELECT_INPUT offset */
+	unsigned select_input:3;
+};
+
+#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _select_input_ofs, \
+		_select_input, _pad_ctrl)				\
+		{							\
+			.mux_ctrl_ofs     = _mux_ctrl_ofs,		\
+			.mux_mode         = _mux_mode,			\
+			.pad_ctrl_ofs     = _pad_ctrl_ofs,		\
+			.pad_ctrl         = _pad_ctrl,			\
+			.select_input_ofs = _select_input_ofs,		\
+			.select_input     = _select_input,		\
+		}
+
+/*
+ * Use to set PAD control
+ */
+#define PAD_CTL_DRIVE_VOLTAGE_3_3_V	0
+#define PAD_CTL_DRIVE_VOLTAGE_1_8_V	1
+
+#define PAD_CTL_NO_HYSTERESIS		0
+#define PAD_CTL_HYSTERESIS		1
+
+#define PAD_CTL_PULL_DISABLED		0x0
+#define PAD_CTL_PULL_KEEPER		0xa
+#define PAD_CTL_PULL_DOWN_100K		0xc
+#define PAD_CTL_PULL_UP_47K		0xd
+#define PAD_CTL_PULL_UP_100K		0xe
+#define PAD_CTL_PULL_UP_22K		0xf
+
+#define PAD_CTL_OUTPUT_CMOS		0
+#define PAD_CTL_OUTPUT_OPEN_DRAIN	1
+
+#define PAD_CTL_DRIVE_STRENGTH_NORM	0
+#define PAD_CTL_DRIVE_STRENGTH_HIGH	1
+#define PAD_CTL_DRIVE_STRENGTH_MAX	2
+
+#define PAD_CTL_SLEW_RATE_SLOW		0
+#define PAD_CTL_SLEW_RATE_FAST		1
+
+/*
+ * setups a single pad:
+ * 	- reserves the pad so that it is not claimed by another driver
+ * 	- setups the iomux according to the configuration
+ */
+int mxc_iomux_v3_setup_pad(struct pad_desc *pad);
+
+/*
+ * setups mutliple pads
+ * convenient way to call the above function with tables
+ */
+int mxc_iomux_v3_setup_multiple_pads(struct pad_desc *pad_list, unsigned count);
+
+/*
+ * releases a single pad:
+ * 	- make it available for a future use by another driver
+ * 	- DOES NOT reconfigure the IOMUX in its reset state
+ */
+void mxc_iomux_v3_release_pad(struct pad_desc *pad);
+
+/*
+ * releases multiple pads
+ * convenvient way to call the above function with tables
+ */
+void mxc_iomux_v3_release_multiple_pads(struct pad_desc *pad_list, int count);
+
+#endif /* __MACH_IOMUX_V3_H__*/
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/memory.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/memory.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/memory.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/memory.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,4 +32,12 @@
 #define CONSISTENT_DMA_SIZE SZ_4M
 #endif /* CONFIG_MX1_VIDEO */
 
+#if defined(CONFIG_MX3_VIDEO)
+/*
+ * Increase size of DMA-consistent memory region.
+ * This is required for mx3 camera driver to capture at least two QXGA frames.
+ */
+#define CONSISTENT_DMA_SIZE SZ_8M
+#endif /* CONFIG_MX3_VIDEO */
+
 #endif /* __ASM_ARCH_MXC_MEMORY_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/mx1.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/mx1.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/mx1.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/mx1.h	2009-09-09 18:13:59.000000000 -0400
@@ -179,7 +179,7 @@
 #define DMA_REQ_UART1_T		30
 #define DMA_REQ_UART1_R		31
 
-/* mandatory for CONFIG_LL_DEBUG */
+/* mandatory for CONFIG_DEBUG_LL */
 #define MXC_LL_UART_PADDR	UART1_BASE_ADDR
 #define MXC_LL_UART_VADDR	IO_ADDRESS(UART1_BASE_ADDR)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/mx3x.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/mx3x.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/mx3x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/mx3x.h	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,9 @@
 #define CS4_SIZE		SZ_32M
 
 #define CS5_BASE_ADDR		0xB6000000
+#define CS5_BASE_ADDR_VIRT	0xF6000000
+#define CS5_SIZE		SZ_32M
+
 #define PCMCIA_MEM_BASE_ADDR	0xBC000000
 
 /*
@@ -191,6 +194,9 @@
 #define CS4_IO_ADDRESS(x)  \
 	(((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
 
+#define CS5_IO_ADDRESS(x)  \
+	(((x) - CS5_BASE_ADDR) + CS5_BASE_ADDR_VIRT)
+
 #define X_MEMC_IO_ADDRESS(x)  \
 	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/mxc_timer.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/mxc_timer.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/mxc_timer.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/mxc_timer.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,158 +0,0 @@
-/*
- * mxc_timer.h
- *
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * Platform independent (i.MX1, i.MX2, i.MX3) definition for timer handling.
- *
- * 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.
- */
-
-#ifndef __PLAT_MXC_TIMER_H
-#define __PLAT_MXC_TIMER_H
-
-#include <linux/clk.h>
-#include <mach/hardware.h>
-
-#ifdef CONFIG_ARCH_MX1
-#define TIMER_BASE		IO_ADDRESS(TIM1_BASE_ADDR)
-#define TIMER_INTERRUPT		TIM1_INT
-
-#define TCTL_VAL		TCTL_CLK_PCLK1
-#define TCTL_IRQEN		(1<<4)
-#define TCTL_FRR		(1<<8)
-#define TCTL_CLK_PCLK1		(1<<1)
-#define TCTL_CLK_PCLK1_4	(2<<1)
-#define TCTL_CLK_TIN		(3<<1)
-#define TCTL_CLK_32		(4<<1)
-
-#define MXC_TCTL   0x00
-#define MXC_TPRER  0x04
-#define MXC_TCMP   0x08
-#define MXC_TCR    0x0c
-#define MXC_TCN    0x10
-#define MXC_TSTAT  0x14
-#define TSTAT_CAPT		(1<<1)
-#define TSTAT_COMP		(1<<0)
-
-static inline void gpt_irq_disable(void)
-{
-	unsigned int tmp;
-
-	tmp = __raw_readl(TIMER_BASE + MXC_TCTL);
-	__raw_writel(tmp & ~TCTL_IRQEN, TIMER_BASE + MXC_TCTL);
-}
-
-static inline void gpt_irq_enable(void)
-{
-	__raw_writel(__raw_readl(TIMER_BASE + MXC_TCTL) | TCTL_IRQEN,
-				TIMER_BASE + MXC_TCTL);
-}
-
-static void gpt_irq_acknowledge(void)
-{
-	__raw_writel(0, TIMER_BASE + MXC_TSTAT);
-}
-#endif /* CONFIG_ARCH_MX1 */
-
-#ifdef CONFIG_ARCH_MX2
-#define TIMER_BASE		IO_ADDRESS(GPT1_BASE_ADDR)
-#define TIMER_INTERRUPT		MXC_INT_GPT1
-
-#define MXC_TCTL   0x00
-#define TCTL_VAL		TCTL_CLK_PCLK1
-#define TCTL_CLK_PCLK1		(1<<1)
-#define TCTL_CLK_PCLK1_4	(2<<1)
-#define TCTL_IRQEN		(1<<4)
-#define TCTL_FRR		(1<<8)
-#define MXC_TPRER  0x04
-#define MXC_TCMP   0x08
-#define MXC_TCR    0x0c
-#define MXC_TCN    0x10
-#define MXC_TSTAT  0x14
-#define TSTAT_CAPT		(1<<1)
-#define TSTAT_COMP		(1<<0)
-
-static inline void gpt_irq_disable(void)
-{
-	unsigned int tmp;
-
-	tmp = __raw_readl(TIMER_BASE + MXC_TCTL);
-	__raw_writel(tmp & ~TCTL_IRQEN, TIMER_BASE + MXC_TCTL);
-}
-
-static inline void gpt_irq_enable(void)
-{
-	__raw_writel(__raw_readl(TIMER_BASE + MXC_TCTL) | TCTL_IRQEN,
-				TIMER_BASE + MXC_TCTL);
-}
-
-static void gpt_irq_acknowledge(void)
-{
-	__raw_writel(TSTAT_CAPT | TSTAT_COMP, TIMER_BASE + MXC_TSTAT);
-}
-#endif /* CONFIG_ARCH_MX2 */
-
-#ifdef CONFIG_ARCH_MX3
-#define TIMER_BASE		IO_ADDRESS(GPT1_BASE_ADDR)
-#define TIMER_INTERRUPT		MXC_INT_GPT
-
-#define MXC_TCTL   0x00
-#define TCTL_VAL		(TCTL_CLK_IPG | TCTL_WAITEN)
-#define TCTL_CLK_IPG		(1<<6)
-#define TCTL_FRR		(1<<9)
-#define TCTL_WAITEN		(1<<3)
-
-#define MXC_TPRER  0x04
-#define MXC_TSTAT  0x08
-#define TSTAT_OF1		(1<<0)
-#define TSTAT_OF2		(1<<1)
-#define TSTAT_OF3		(1<<2)
-#define TSTAT_IF1		(1<<3)
-#define TSTAT_IF2		(1<<4)
-#define TSTAT_ROV		(1<<5)
-#define MXC_IR     0x0c
-#define MXC_TCMP   0x10
-#define MXC_TCMP2  0x14
-#define MXC_TCMP3  0x18
-#define MXC_TCR    0x1c
-#define MXC_TCN    0x24
-
-static inline void gpt_irq_disable(void)
-{
-	__raw_writel(0, TIMER_BASE + MXC_IR);
-}
-
-static inline void gpt_irq_enable(void)
-{
-	__raw_writel(1<<0, TIMER_BASE + MXC_IR);
-}
-
-static inline void gpt_irq_acknowledge(void)
-{
-	__raw_writel(TSTAT_OF1, TIMER_BASE + MXC_TSTAT);
-}
-#endif /* CONFIG_ARCH_MX3 */
-
-#define TCTL_SWR		(1<<15)
-#define TCTL_CC			(1<<10)
-#define TCTL_OM			(1<<9)
-#define TCTL_CAP_RIS		(1<<6)
-#define TCTL_CAP_FAL		(2<<6)
-#define TCTL_CAP_RIS_FAL	(3<<6)
-#define TCTL_CAP_ENA		(1<<5)
-#define TCTL_TEN		(1<<0)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/usb.h linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/usb.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/include/mach/usb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/include/mach/usb.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 
 struct imxusb_platform_data {
 	int (*init)(struct device *);
-	int (*exit)(struct device *);
+	void (*exit)(struct device *);
 };
 
 #endif /* __ASM_ARCH_MXC_USB */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/iomux-v3.c linux-libre-2.6.31-gnu/arch/arm/plat-mxc/iomux-v3.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/iomux-v3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/iomux-v3.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ *                       <armlinux@phytec.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.
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/map.h>
+#include <mach/iomux-v3.h>
+
+#define IOMUX_BASE	IO_ADDRESS(IOMUXC_BASE_ADDR)
+
+static unsigned long iomux_v3_pad_alloc_map[0x200 / BITS_PER_LONG];
+
+/*
+ * setups a single pin:
+ * 	- reserves the pin so that it is not claimed by another driver
+ * 	- setups the iomux according to the configuration
+ */
+int mxc_iomux_v3_setup_pad(struct pad_desc *pad)
+{
+	unsigned int pad_ofs = pad->pad_ctrl_ofs;
+
+	if (test_and_set_bit(pad_ofs >> 2, iomux_v3_pad_alloc_map))
+		return -EBUSY;
+	if (pad->mux_ctrl_ofs)
+		__raw_writel(pad->mux_mode, IOMUX_BASE + pad->mux_ctrl_ofs);
+
+	if (pad->select_input_ofs)
+		__raw_writel(pad->select_input,
+				IOMUX_BASE + pad->select_input_ofs);
+
+	if (!(pad->pad_ctrl & NO_PAD_CTRL))
+		__raw_writel(pad->pad_ctrl, IOMUX_BASE + pad->pad_ctrl_ofs);
+	return 0;
+}
+EXPORT_SYMBOL(mxc_iomux_v3_setup_pad);
+
+int mxc_iomux_v3_setup_multiple_pads(struct pad_desc *pad_list, unsigned count)
+{
+	struct pad_desc *p = pad_list;
+	int i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		ret = mxc_iomux_v3_setup_pad(p);
+		if (ret)
+			goto setup_error;
+		p++;
+	}
+	return 0;
+
+setup_error:
+	mxc_iomux_v3_release_multiple_pads(pad_list, i);
+	return ret;
+}
+EXPORT_SYMBOL(mxc_iomux_v3_setup_multiple_pads);
+
+void mxc_iomux_v3_release_pad(struct pad_desc *pad)
+{
+	unsigned int pad_ofs = pad->pad_ctrl_ofs;
+
+	clear_bit(pad_ofs >> 2, iomux_v3_pad_alloc_map);
+}
+EXPORT_SYMBOL(mxc_iomux_v3_release_pad);
+
+void mxc_iomux_v3_release_multiple_pads(struct pad_desc *pad_list, int count)
+{
+	struct pad_desc *p = pad_list;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		mxc_iomux_v3_release_pad(p);
+		p++;
+	}
+}
+EXPORT_SYMBOL(mxc_iomux_v3_release_multiple_pads);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/irq.c linux-libre-2.6.31-gnu/arch/arm/plat-mxc/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,31 +24,27 @@
 #include <asm/mach/irq.h>
 #include <mach/hardware.h>
 
-#define AVIC_BASE		IO_ADDRESS(AVIC_BASE_ADDR)
-#define AVIC_INTCNTL		(AVIC_BASE + 0x00)	/* int control reg */
-#define AVIC_NIMASK		(AVIC_BASE + 0x04)	/* int mask reg */
-#define AVIC_INTENNUM		(AVIC_BASE + 0x08)	/* int enable number reg */
-#define AVIC_INTDISNUM		(AVIC_BASE + 0x0C)	/* int disable number reg */
-#define AVIC_INTENABLEH		(AVIC_BASE + 0x10)	/* int enable reg high */
-#define AVIC_INTENABLEL		(AVIC_BASE + 0x14)	/* int enable reg low */
-#define AVIC_INTTYPEH		(AVIC_BASE + 0x18)	/* int type reg high */
-#define AVIC_INTTYPEL		(AVIC_BASE + 0x1C)	/* int type reg low */
-#define AVIC_NIPRIORITY(x)	(AVIC_BASE + (0x20 + 4 * (7 - (x)))) /* int priority */
-#define AVIC_NIVECSR		(AVIC_BASE + 0x40)	/* norm int vector/status */
-#define AVIC_FIVECSR		(AVIC_BASE + 0x44)	/* fast int vector/status */
-#define AVIC_INTSRCH		(AVIC_BASE + 0x48)	/* int source reg high */
-#define AVIC_INTSRCL		(AVIC_BASE + 0x4C)	/* int source reg low */
-#define AVIC_INTFRCH		(AVIC_BASE + 0x50)	/* int force reg high */
-#define AVIC_INTFRCL		(AVIC_BASE + 0x54)	/* int force reg low */
-#define AVIC_NIPNDH		(AVIC_BASE + 0x58)	/* norm int pending high */
-#define AVIC_NIPNDL		(AVIC_BASE + 0x5C)	/* norm int pending low */
-#define AVIC_FIPNDH		(AVIC_BASE + 0x60)	/* fast int pending high */
-#define AVIC_FIPNDL		(AVIC_BASE + 0x64)	/* fast int pending low */
+#define AVIC_INTCNTL		0x00	/* int control reg */
+#define AVIC_NIMASK		0x04	/* int mask reg */
+#define AVIC_INTENNUM		0x08	/* int enable number reg */
+#define AVIC_INTDISNUM		0x0C	/* int disable number reg */
+#define AVIC_INTENABLEH		0x10	/* int enable reg high */
+#define AVIC_INTENABLEL		0x14	/* int enable reg low */
+#define AVIC_INTTYPEH		0x18	/* int type reg high */
+#define AVIC_INTTYPEL		0x1C	/* int type reg low */
+#define AVIC_NIPRIORITY(x)	(0x20 + 4 * (7 - (x))) /* int priority */
+#define AVIC_NIVECSR		0x40	/* norm int vector/status */
+#define AVIC_FIVECSR		0x44	/* fast int vector/status */
+#define AVIC_INTSRCH		0x48	/* int source reg high */
+#define AVIC_INTSRCL		0x4C	/* int source reg low */
+#define AVIC_INTFRCH		0x50	/* int force reg high */
+#define AVIC_INTFRCL		0x54	/* int force reg low */
+#define AVIC_NIPNDH		0x58	/* norm int pending high */
+#define AVIC_NIPNDL		0x5C	/* norm int pending low */
+#define AVIC_FIPNDH		0x60	/* fast int pending high */
+#define AVIC_FIPNDL		0x64	/* fast int pending low */
 
-#define SYSTEM_PREV_REG		IO_ADDRESS(IIM_BASE_ADDR + 0x20)
-#define SYSTEM_SREV_REG		IO_ADDRESS(IIM_BASE_ADDR + 0x24)
-#define IIM_PROD_REV_SH		3
-#define IIM_PROD_REV_LEN	5
+static void __iomem *avic_base;
 
 int imx_irq_set_priority(unsigned char irq, unsigned char prio)
 {
@@ -59,11 +55,11 @@
 	if (irq >= MXC_INTERNAL_IRQS)
 		return -EINVAL;;
 
-	temp = __raw_readl(AVIC_NIPRIORITY(irq / 8));
+	temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
 	temp &= ~mask;
 	temp |= prio & mask;
 
-	__raw_writel(temp, AVIC_NIPRIORITY(irq / 8));
+	__raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));
 
 	return 0;
 #else
@@ -81,12 +77,12 @@
 		return -EINVAL;
 
 	if (irq < MXC_INTERNAL_IRQS / 2) {
-		irqt = __raw_readl(AVIC_INTTYPEL) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), AVIC_INTTYPEL);
+		irqt = __raw_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
+		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
 	} else {
 		irq -= MXC_INTERNAL_IRQS / 2;
-		irqt = __raw_readl(AVIC_INTTYPEH) & ~(1 << irq);
-		__raw_writel(irqt | (!!type << irq), AVIC_INTTYPEH);
+		irqt = __raw_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
+		__raw_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
 	}
 
 	return 0;
@@ -97,13 +93,13 @@
 /* Disable interrupt number "irq" in the AVIC */
 static void mxc_mask_irq(unsigned int irq)
 {
-	__raw_writel(irq, AVIC_INTDISNUM);
+	__raw_writel(irq, avic_base + AVIC_INTDISNUM);
 }
 
 /* Enable interrupt number "irq" in the AVIC */
 static void mxc_unmask_irq(unsigned int irq)
 {
-	__raw_writel(irq, AVIC_INTENNUM);
+	__raw_writel(irq, avic_base + AVIC_INTENNUM);
 }
 
 static struct irq_chip mxc_avic_chip = {
@@ -121,19 +117,21 @@
 {
 	int i;
 
+	avic_base = IO_ADDRESS(AVIC_BASE_ADDR);
+
 	/* put the AVIC into the reset value with
 	 * all interrupts disabled
 	 */
-	__raw_writel(0, AVIC_INTCNTL);
-	__raw_writel(0x1f, AVIC_NIMASK);
+	__raw_writel(0, avic_base + AVIC_INTCNTL);
+	__raw_writel(0x1f, avic_base + AVIC_NIMASK);
 
 	/* disable all interrupts */
-	__raw_writel(0, AVIC_INTENABLEH);
-	__raw_writel(0, AVIC_INTENABLEL);
+	__raw_writel(0, avic_base + AVIC_INTENABLEH);
+	__raw_writel(0, avic_base + AVIC_INTENABLEL);
 
 	/* all IRQ no FIQ */
-	__raw_writel(0, AVIC_INTTYPEH);
-	__raw_writel(0, AVIC_INTTYPEL);
+	__raw_writel(0, avic_base + AVIC_INTTYPEH);
+	__raw_writel(0, avic_base + AVIC_INTTYPEL);
 	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
 		set_irq_chip(i, &mxc_avic_chip);
 		set_irq_handler(i, handle_level_irq);
@@ -142,7 +140,7 @@
 
 	/* Set default priority value (0) for all IRQ's */
 	for (i = 0; i < 8; i++)
-		__raw_writel(0, AVIC_NIPRIORITY(i));
+		__raw_writel(0, avic_base + AVIC_NIPRIORITY(i));
 
 	/* init architectures chained interrupt handler */
 	mxc_register_gpios();
@@ -154,3 +152,4 @@
 
 	printk(KERN_INFO "MXC IRQ initialized\n");
 }
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/Kconfig linux-libre-2.6.31-gnu/arch/arm/plat-mxc/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,14 @@
 config MXC_PWM
 	tristate "Enable PWM driver"
 	depends on ARCH_MXC
+	select HAVE_PWM
 	help
 	  Enable support for the i.MX PWM controller(s).
 
+config ARCH_HAS_RNGA
+	bool
+	depends on ARCH_MXC
+
+config ARCH_MXC_IOMUX_V3
+	bool
 endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/Makefile linux-libre-2.6.31-gnu/arch/arm/plat-mxc/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,4 +7,5 @@
 
 obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o
 obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
+obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/pwm.c linux-libre-2.6.31-gnu/arch/arm/plat-mxc/pwm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/pwm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/pwm.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,65 +15,26 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/pwm.h>
+#include <mach/hardware.h>
 
-#if defined CONFIG_ARCH_MX1 || defined CONFIG_ARCH_MX21
-#define PWM_VER_1
-
-#define PWMCR	0x00	/* PWM Control Register		*/
-#define PWMSR	0x04	/* PWM Sample Register		*/
-#define PWMPR	0x08	/* PWM Period Register		*/
-#define PWMCNR	0x0C	/* PWM Counter Register		*/
 
-#define PWMCR_HCTR		(1 << 18)		/* Halfword FIFO Data Swapping	*/
-#define PWMCR_BCTR		(1 << 17)		/* Byte FIFO Data Swapping	*/
-#define PWMCR_SWR		(1 << 16)		/* Software Reset		*/
-#define PWMCR_CLKSRC_PERCLK	(0 << 15)		/* PERCLK Clock Source		*/
-#define PWMCR_CLKSRC_CLK32	(1 << 15)		/* 32KHz Clock Source		*/
-#define PWMCR_PRESCALER(x)	(((x - 1) & 0x7F) << 8)	/* PRESCALER			*/
-#define PWMCR_IRQ		(1 << 7)		/* Interrupt Request		*/
-#define PWMCR_IRQEN		(1 << 6)		/* Interrupt Request Enable	*/
-#define PWMCR_FIFOAV		(1 << 5)		/* FIFO Available		*/
-#define PWMCR_EN		(1 << 4)		/* Enables/Disables the PWM	*/
-#define PWMCR_REPEAT(x)		(((x) & 0x03) << 2)	/* Sample Repeats		*/
-#define PWMCR_DIV(x)		(((x) & 0x03) << 0)	/* Clock divider 2/4/8/16	*/
+/* i.MX1 and i.MX21 share the same PWM function block: */
 
-#define MAX_DIV			(128 * 16)
-#endif
+#define MX1_PWMC    0x00   /* PWM Control Register */
+#define MX1_PWMS    0x04   /* PWM Sample Register */
+#define MX1_PWMP    0x08   /* PWM Period Register */
 
-#if defined CONFIG_MACH_MX27 || defined CONFIG_ARCH_MX31
-#define PWM_VER_2
 
-#define PWMCR	0x00	/* PWM Control Register		*/
-#define PWMSR	0x04	/* PWM Status Register		*/
-#define PWMIR	0x08	/* PWM Interrupt Register	*/
-#define PWMSAR	0x0C	/* PWM Sample Register		*/
-#define PWMPR	0x10	/* PWM Period Register		*/
-#define PWMCNR	0x14	/* PWM Counter Register		*/
+/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
 
-#define PWMCR_EN		(1 << 0)		/* Enables/Disables the PWM	*/
-#define PWMCR_REPEAT(x)		(((x) & 0x03) << 1)	/* Sample Repeats		*/
-#define PWMCR_SWR		(1 << 3)		/* Software Reset		*/
-#define PWMCR_PRESCALER(x)	(((x - 1) & 0xFFF) << 4)/* PRESCALER			*/
-#define PWMCR_CLKSRC(x)		(((x) & 0x3) << 16)
-#define PWMCR_CLKSRC_OFF	(0 << 16)
-#define PWMCR_CLKSRC_IPG	(1 << 16)
-#define PWMCR_CLKSRC_IPG_HIGH	(2 << 16)
-#define PWMCR_CLKSRC_CLK32	(3 << 16)
-#define PWMCR_POUTC
-#define PWMCR_HCTR		(1 << 20)		/* Halfword FIFO Data Swapping	*/
-#define PWMCR_BCTR		(1 << 21)		/* Byte FIFO Data Swapping	*/
-#define PWMCR_DBGEN		(1 << 22)		/* Debug Mode			*/
-#define PWMCR_WAITEN		(1 << 23)		/* Wait Mode			*/
-#define PWMCR_DOZEN		(1 << 24)		/* Doze Mode			*/
-#define PWMCR_STOPEN		(1 << 25)		/* Stop Mode			*/
-#define PWMCR_FWM(x)		(((x) & 0x3) << 26)	/* FIFO Water Mark		*/
+#define MX3_PWMCR                 0x00    /* PWM Control Register */
+#define MX3_PWMSAR                0x0C    /* PWM Sample Register */
+#define MX3_PWMPR                 0x10    /* PWM Period Register */
+#define MX3_PWMCR_PRESCALER(x)    (((x - 1) & 0xFFF) << 4)
+#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
+#define MX3_PWMCR_EN              (1 << 0)
 
-#define MAX_DIV 4096
-#endif
 
-#define PWMS_SAMPLE(x)		((x) & 0xFFFF)		/* Contains a two-sample word	*/
-#define PWMP_PERIOD(x)		((x) & 0xFFFF)		/* Represents the PWM's period	*/
-#define PWMC_COUNTER(x)		((x) & 0xFFFF)		/* Represents the current count value	*/
 
 struct pwm_device {
 	struct list_head	node;
@@ -91,32 +52,52 @@
 
 int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 {
-	unsigned long long c;
-	unsigned long period_cycles, duty_cycles, prescale;
-
 	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
 		return -EINVAL;
 
-	c = clk_get_rate(pwm->clk);
-	c = c * period_ns;
-	do_div(c, 1000000000);
-	period_cycles = c;
+	if (cpu_is_mx27() || cpu_is_mx3()) {
+		unsigned long long c;
+		unsigned long period_cycles, duty_cycles, prescale;
+		c = clk_get_rate(pwm->clk);
+		c = c * period_ns;
+		do_div(c, 1000000000);
+		period_cycles = c;
 
-	prescale = period_cycles / 0x10000 + 1;
+		prescale = period_cycles / 0x10000 + 1;
 
-	period_cycles /= prescale;
-	c = (unsigned long long)period_cycles * duty_ns;
-	do_div(c, period_ns);
-	duty_cycles = c;
+		period_cycles /= prescale;
+		c = (unsigned long long)period_cycles * duty_ns;
+		do_div(c, period_ns);
+		duty_cycles = c;
 
-#ifdef PWM_VER_2
-	writel(duty_cycles, pwm->mmio_base + PWMSAR);
-	writel(period_cycles, pwm->mmio_base + PWMPR);
-	writel(PWMCR_PRESCALER(prescale - 1) | PWMCR_CLKSRC_IPG_HIGH | PWMCR_EN,
-			pwm->mmio_base + PWMCR);
-#elif defined PWM_VER_1
-#error PWM not yet working on MX1 / MX21
-#endif
+		writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR);
+		writel(period_cycles, pwm->mmio_base + MX3_PWMPR);
+		writel(MX3_PWMCR_PRESCALER(prescale - 1) |
+			MX3_PWMCR_CLKSRC_IPG_HIGH | MX3_PWMCR_EN,
+			pwm->mmio_base + MX3_PWMCR);
+	} else if (cpu_is_mx1() || cpu_is_mx21()) {
+		/* The PWM subsystem allows for exact frequencies. However,
+		 * I cannot connect a scope on my device to the PWM line and
+		 * thus cannot provide the program the PWM controller
+		 * exactly. Instead, I'm relying on the fact that the
+		 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
+		 * function group already. So I'll just modify the PWM sample
+		 * register to follow the ratio of duty_ns vs. period_ns
+		 * accordingly.
+		 *
+		 * This is good enought for programming the brightness of
+		 * the LCD backlight.
+		 *
+		 * The real implementation would divide PERCLK[0] first by
+		 * both the prescaler (/1 .. /128) and then by CLKSEL
+		 * (/2 .. /16).
+		 */
+		u32 max = readl(pwm->mmio_base + MX1_PWMP);
+		u32 p = max * duty_ns / period_ns;
+		writel(max - p, pwm->mmio_base + MX1_PWMS);
+	} else {
+		BUG();
+	}
 
 	return 0;
 }
@@ -297,4 +278,3 @@
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
-
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-mxc/time.c linux-libre-2.6.31-gnu/arch/arm/plat-mxc/time.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-mxc/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-mxc/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,22 +29,85 @@
 #include <mach/hardware.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
-#include <mach/mxc_timer.h>
+
+/* defines common for all i.MX */
+#define MXC_TCTL		0x00
+#define MXC_TCTL_TEN		(1 << 0)
+#define MXC_TPRER		0x04
+
+/* MX1, MX21, MX27 */
+#define MX1_2_TCTL_CLK_PCLK1	(1 << 1)
+#define MX1_2_TCTL_IRQEN	(1 << 4)
+#define MX1_2_TCTL_FRR		(1 << 8)
+#define MX1_2_TCMP		0x08
+#define MX1_2_TCN		0x10
+#define MX1_2_TSTAT		0x14
+
+/* MX21, MX27 */
+#define MX2_TSTAT_CAPT		(1 << 1)
+#define MX2_TSTAT_COMP		(1 << 0)
+
+/* MX31, MX35 */
+#define MX3_TCTL_WAITEN		(1 << 3)
+#define MX3_TCTL_CLK_IPG	(1 << 6)
+#define MX3_TCTL_FRR		(1 << 9)
+#define MX3_IR			0x0c
+#define MX3_TSTAT		0x08
+#define MX3_TSTAT_OF1		(1 << 0)
+#define MX3_TCN			0x24
+#define MX3_TCMP		0x10
 
 static struct clock_event_device clockevent_mxc;
 static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
-/* clock source */
+static void __iomem *timer_base;
 
-static cycle_t mxc_get_cycles(struct clocksource *cs)
+static inline void gpt_irq_disable(void)
 {
-	return __raw_readl(TIMER_BASE + MXC_TCN);
+	unsigned int tmp;
+
+	if (cpu_is_mx3())
+		__raw_writel(0, timer_base + MX3_IR);
+	else {
+		tmp = __raw_readl(timer_base + MXC_TCTL);
+		__raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
+	}
+}
+
+static inline void gpt_irq_enable(void)
+{
+	if (cpu_is_mx3())
+		__raw_writel(1<<0, timer_base + MX3_IR);
+	else {
+		__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
+			timer_base + MXC_TCTL);
+	}
+}
+
+static void gpt_irq_acknowledge(void)
+{
+	if (cpu_is_mx1())
+		__raw_writel(0, timer_base + MX1_2_TSTAT);
+	if (cpu_is_mx2())
+		__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT);
+	if (cpu_is_mx3())
+		__raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT);
+}
+
+static cycle_t mx1_2_get_cycles(struct clocksource *cs)
+{
+	return __raw_readl(timer_base + MX1_2_TCN);
+}
+
+static cycle_t mx3_get_cycles(struct clocksource *cs)
+{
+	return __raw_readl(timer_base + MX3_TCN);
 }
 
 static struct clocksource clocksource_mxc = {
 	.name 		= "mxc_timer1",
 	.rating		= 200,
-	.read		= mxc_get_cycles,
+	.read		= mx1_2_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
@@ -54,6 +117,9 @@
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
+	if (cpu_is_mx3())
+		clocksource_mxc.read = mx3_get_cycles;
+
 	clocksource_mxc.mult = clocksource_hz2mult(c,
 					clocksource_mxc.shift);
 	clocksource_register(&clocksource_mxc);
@@ -63,15 +129,29 @@
 
 /* clock event */
 
-static int mxc_set_next_event(unsigned long evt,
+static int mx1_2_set_next_event(unsigned long evt,
 			      struct clock_event_device *unused)
 {
 	unsigned long tcmp;
 
-	tcmp = __raw_readl(TIMER_BASE + MXC_TCN) + evt;
-	__raw_writel(tcmp, TIMER_BASE + MXC_TCMP);
+	tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
 
-	return (int)(tcmp - __raw_readl(TIMER_BASE + MXC_TCN)) < 0 ?
+	__raw_writel(tcmp, timer_base + MX1_2_TCMP);
+
+	return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
+				-ETIME : 0;
+}
+
+static int mx3_set_next_event(unsigned long evt,
+			      struct clock_event_device *unused)
+{
+	unsigned long tcmp;
+
+	tcmp = __raw_readl(timer_base + MX3_TCN) + evt;
+
+	__raw_writel(tcmp, timer_base + MX3_TCMP);
+
+	return (int)(tcmp - __raw_readl(timer_base + MX3_TCN)) < 0 ?
 				-ETIME : 0;
 }
 
@@ -100,8 +180,13 @@
 
 	if (mode != clockevent_mode) {
 		/* Set event time into far-far future */
-		__raw_writel(__raw_readl(TIMER_BASE + MXC_TCN) - 3,
-				TIMER_BASE + MXC_TCMP);
+		if (cpu_is_mx3())
+			__raw_writel(__raw_readl(timer_base + MX3_TCN) - 3,
+					timer_base + MX3_TCMP);
+		else
+			__raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
+					timer_base + MX1_2_TCMP);
+
 		/* Clear pending interrupt */
 		gpt_irq_acknowledge();
 	}
@@ -148,7 +233,10 @@
 	struct clock_event_device *evt = &clockevent_mxc;
 	uint32_t tstat;
 
-	tstat = __raw_readl(TIMER_BASE + MXC_TSTAT);
+	if (cpu_is_mx3())
+		tstat = __raw_readl(timer_base + MX3_TSTAT);
+	else
+		tstat = __raw_readl(timer_base + MX1_2_TSTAT);
 
 	gpt_irq_acknowledge();
 
@@ -168,7 +256,7 @@
 	.features	= CLOCK_EVT_FEAT_ONESHOT,
 	.shift		= 32,
 	.set_mode	= mxc_set_mode,
-	.set_next_event	= mxc_set_next_event,
+	.set_next_event	= mx1_2_set_next_event,
 	.rating		= 200,
 };
 
@@ -176,6 +264,9 @@
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
+	if (cpu_is_mx3())
+		clockevent_mxc.set_next_event = mx3_set_next_event;
+
 	clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
 					clockevent_mxc.shift);
 	clockevent_mxc.max_delta_ns =
@@ -192,23 +283,47 @@
 
 void __init mxc_timer_init(struct clk *timer_clk)
 {
+	uint32_t tctl_val;
+	int irq;
+
 	clk_enable(timer_clk);
 
+	if (cpu_is_mx1()) {
+#ifdef CONFIG_ARCH_MX1
+		timer_base = IO_ADDRESS(TIM1_BASE_ADDR);
+		irq = TIM1_INT;
+#endif
+	} else if (cpu_is_mx2()) {
+#ifdef CONFIG_ARCH_MX2
+		timer_base = IO_ADDRESS(GPT1_BASE_ADDR);
+		irq = MXC_INT_GPT1;
+#endif
+	} else if (cpu_is_mx3()) {
+#ifdef CONFIG_ARCH_MX3
+		timer_base = IO_ADDRESS(GPT1_BASE_ADDR);
+		irq = MXC_INT_GPT;
+#endif
+	} else
+		BUG();
+
 	/*
 	 * Initialise to a known state (all timers off, and timing reset)
 	 */
-	__raw_writel(0, TIMER_BASE + MXC_TCTL);
-	__raw_writel(0, TIMER_BASE + MXC_TPRER); /* see datasheet note */
 
-	__raw_writel(TCTL_FRR |	/* free running */
-		     TCTL_VAL |	/* set clocksource and arch specific bits */
-		     TCTL_TEN,	/* start the timer */
-		     TIMER_BASE + MXC_TCTL);
+	__raw_writel(0, timer_base + MXC_TCTL);
+	__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
+
+	if (cpu_is_mx3())
+		tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
+	else
+		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
+
+	__raw_writel(tctl_val, timer_base + MXC_TCTL);
 
 	/* init and register the timer to the framework */
 	mxc_clocksource_init(timer_clk);
 	mxc_clockevent_init(timer_clk);
 
 	/* Make irqs happen */
-	setup_irq(TIMER_INTERRUPT, &mxc_timer_irq);
+	setup_irq(irq, &mxc_timer_irq);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/clock.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,10 +36,40 @@
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
 
+/* This functions is moved to arch/arm/common/clkdev.c. For OMAP4 since
+ * clock framework is not up , it is defined here to avoid rework in
+ * every driver. Also dummy prcm reset function is added */
+
+/* Dummy hooks only for OMAP4.For rest OMAPs, common clkdev is used */
+#if defined(CONFIG_ARCH_OMAP4)
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	return NULL;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+void omap2_clk_prepare_for_reboot(void)
+{
+}
+EXPORT_SYMBOL(omap2_clk_prepare_for_reboot);
+
+void omap_prcm_arch_reset(char mode)
+{
+}
+EXPORT_SYMBOL(omap_prcm_arch_reset);
+#endif
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
 	int ret = 0;
+	if (cpu_is_omap44xx())
+		/* OMAP4 clk framework not supported yet */
+		return 0;
 
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
@@ -140,6 +170,9 @@
 	unsigned long flags;
 	int ret = -EINVAL;
 
+	if (cpu_is_omap44xx())
+	/* OMAP4 clk framework not supported yet */
+		return 0;
 	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
 		return ret;
 
@@ -240,13 +273,13 @@
 }
 
 /**
- * clk_init_one - initialize any fields in the struct clk before clk init
+ * clk_preinit - initialize any fields in the struct clk before clk init
  * @clk: struct clk * to initialize
  *
  * Initialize any struct clk fields needed before normal clk initialization
  * can run.  No return value.
  */
-void clk_init_one(struct clk *clk)
+void clk_preinit(struct clk *clk)
 {
 	INIT_LIST_HEAD(&clk->children);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/common.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/common.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/common.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,10 @@
  * linux/arch/arm/plat-omap/common.c
  *
  * Code common to all OMAP machines.
+ * The file is created by Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/pm.h>
 #include <linux/console.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
@@ -175,25 +178,70 @@
  * but systems won't necessarily want to spend resources that way.
  */
 
-#if defined(CONFIG_ARCH_OMAP16XX)
-#define TIMER_32K_SYNCHRONIZED		0xfffbc410
-#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
-#define TIMER_32K_SYNCHRONIZED		(OMAP2_32KSYNCT_BASE + 0x10)
-#endif
+#define OMAP16XX_TIMER_32K_SYNCHRONIZED		0xfffbc410
 
-#ifdef	TIMER_32K_SYNCHRONIZED
+#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
 
 #include <linux/clocksource.h>
 
-static cycle_t omap_32k_read(struct clocksource *cs)
+#ifdef CONFIG_ARCH_OMAP16XX
+static cycle_t omap16xx_32k_read(struct clocksource *cs)
 {
-	return omap_readl(TIMER_32K_SYNCHRONIZED);
+	return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED);
+}
+#else
+#define omap16xx_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2420
+static cycle_t omap2420_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10);
+}
+#else
+#define omap2420_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+static cycle_t omap2430_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10);
+}
+#else
+#define omap2430_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+static cycle_t omap34xx_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10);
+}
+#else
+#define omap34xx_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static cycle_t omap44xx_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10);
+}
+#else
+#define omap44xx_32k_read	NULL
+#endif
+
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t omap_32k_read_dummy(struct clocksource *cs)
+{
+	return 0;
 }
 
 static struct clocksource clocksource_32k = {
 	.name		= "32k_counter",
 	.rating		= 250,
-	.read		= omap_32k_read,
+	.read		= omap_32k_read_dummy,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift		= 10,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
@@ -207,7 +255,7 @@
 {
 	unsigned long long ret;
 
-	ret = (unsigned long long)omap_32k_read(&clocksource_32k);
+	ret = (unsigned long long)clocksource_32k.read(&clocksource_32k);
 	ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift;
 	return ret;
 }
@@ -220,6 +268,19 @@
 	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
 		struct clk *sync_32k_ick;
 
+		if (cpu_is_omap16xx())
+			clocksource_32k.read = omap16xx_32k_read;
+		else if (cpu_is_omap2420())
+			clocksource_32k.read = omap2420_32k_read;
+		else if (cpu_is_omap2430())
+			clocksource_32k.read = omap2430_32k_read;
+		else if (cpu_is_omap34xx())
+			clocksource_32k.read = omap34xx_32k_read;
+		else if (cpu_is_omap44xx())
+			clocksource_32k.read = omap44xx_32k_read;
+		else
+			return -ENODEV;
+
 		sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
 		if (sync_32k_ick)
 			clk_enable(sync_32k_ick);
@@ -234,15 +295,13 @@
 }
 arch_initcall(omap_init_clocksource_32k);
 
-#endif	/* TIMER_32K_SYNCHRONIZED */
+#endif	/* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
 
 /* Global address base setup code */
 
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 
-static struct omap_globals *omap2_globals;
-
-static void __init __omap2_set_globals(void)
+static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
 {
 	omap2_set_globals_tap(omap2_globals);
 	omap2_set_globals_sdrc(omap2_globals);
@@ -266,8 +325,7 @@
 
 void __init omap2_set_globals_242x(void)
 {
-	omap2_globals = &omap242x_globals;
-	__omap2_set_globals();
+	__omap2_set_globals(&omap242x_globals);
 }
 #endif
 
@@ -285,8 +343,7 @@
 
 void __init omap2_set_globals_243x(void)
 {
-	omap2_globals = &omap243x_globals;
-	__omap2_set_globals();
+	__omap2_set_globals(&omap243x_globals);
 }
 #endif
 
@@ -304,8 +361,23 @@
 
 void __init omap2_set_globals_343x(void)
 {
-	omap2_globals = &omap343x_globals;
-	__omap2_set_globals();
+	__omap2_set_globals(&omap343x_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static struct omap_globals omap4_globals = {
+	.class	= OMAP443X_CLASS,
+	.tap	= OMAP2_IO_ADDRESS(0x4830a000),
+	.ctrl	= OMAP2_IO_ADDRESS(OMAP443X_CTRL_BASE),
+	.prm	= OMAP2_IO_ADDRESS(OMAP4430_PRM_BASE),
+	.cm	= OMAP2_IO_ADDRESS(OMAP4430_CM_BASE),
+};
+
+void __init omap2_set_globals_443x(void)
+{
+	omap2_set_globals_tap(&omap4_globals);
+	omap2_set_globals_control(&omap4_globals);
 }
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/cpu-omap.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/cpu-omap.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/cpu-omap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/cpu-omap.c	2009-09-09 18:13:59.000000000 -0400
@@ -78,10 +78,10 @@
 
 	/* Ensure desired rate is within allowed range.  Some govenors
 	 * (ondemand) will just pass target_freq=0 to get the minimum. */
-	if (target_freq < policy->cpuinfo.min_freq)
-		target_freq = policy->cpuinfo.min_freq;
-	if (target_freq > policy->cpuinfo.max_freq)
-		target_freq = policy->cpuinfo.max_freq;
+	if (target_freq < policy->min)
+		target_freq = policy->min;
+	if (target_freq > policy->max)
+		target_freq = policy->max;
 
 	freqs.old = omap_getspeed(0);
 	freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/devices.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/devices.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/devices.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/devices.c	2009-09-09 18:13:59.000000000 -0400
@@ -311,6 +311,8 @@
 		wdt_resources[0].start = 0x49016000; /* WDT2 */
 	else if (cpu_is_omap343x())
 		wdt_resources[0].start = 0x48314000; /* WDT2 */
+	else if (cpu_is_omap44xx())
+		wdt_resources[0].start = 0x4a314000;
 	else
 		return;
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/dma.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,9 @@
  * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
  * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * Support functions for the OMAP internal DMA channels.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -310,41 +313,62 @@
 
 void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 {
-	u16 w;
-
 	BUG_ON(omap_dma_in_1510_mode());
 
-	if (cpu_class_is_omap2()) {
-		REVISIT_24XX();
-		return;
-	}
+	if (cpu_class_is_omap1()) {
+		u16 w;
 
-	w = dma_read(CCR2(lch));
-	w &= ~0x03;
+		w = dma_read(CCR2(lch));
+		w &= ~0x03;
 
-	switch (mode) {
-	case OMAP_DMA_CONSTANT_FILL:
-		w |= 0x01;
-		break;
-	case OMAP_DMA_TRANSPARENT_COPY:
-		w |= 0x02;
-		break;
-	case OMAP_DMA_COLOR_DIS:
-		break;
-	default:
-		BUG();
+		switch (mode) {
+		case OMAP_DMA_CONSTANT_FILL:
+			w |= 0x01;
+			break;
+		case OMAP_DMA_TRANSPARENT_COPY:
+			w |= 0x02;
+			break;
+		case OMAP_DMA_COLOR_DIS:
+			break;
+		default:
+			BUG();
+		}
+		dma_write(w, CCR2(lch));
+
+		w = dma_read(LCH_CTRL(lch));
+		w &= ~0x0f;
+		/* Default is channel type 2D */
+		if (mode) {
+			dma_write((u16)color, COLOR_L(lch));
+			dma_write((u16)(color >> 16), COLOR_U(lch));
+			w |= 1;		/* Channel type G */
+		}
+		dma_write(w, LCH_CTRL(lch));
 	}
-	dma_write(w, CCR2(lch));
 
-	w = dma_read(LCH_CTRL(lch));
-	w &= ~0x0f;
-	/* Default is channel type 2D */
-	if (mode) {
-		dma_write((u16)color, COLOR_L(lch));
-		dma_write((u16)(color >> 16), COLOR_U(lch));
-		w |= 1;		/* Channel type G */
+	if (cpu_class_is_omap2()) {
+		u32 val;
+
+		val = dma_read(CCR(lch));
+		val &= ~((1 << 17) | (1 << 16));
+
+		switch (mode) {
+		case OMAP_DMA_CONSTANT_FILL:
+			val |= 1 << 16;
+			break;
+		case OMAP_DMA_TRANSPARENT_COPY:
+			val |= 1 << 17;
+			break;
+		case OMAP_DMA_COLOR_DIS:
+			break;
+		default:
+			BUG();
+		}
+		dma_write(val, CCR(lch));
+
+		color &= 0xffffff;
+		dma_write(color, COLOR(lch));
 	}
-	dma_write(w, LCH_CTRL(lch));
 }
 EXPORT_SYMBOL(omap_set_dma_color_mode);
 
@@ -851,7 +875,7 @@
 	}
 	l = dma_read(CCR(lch));
 	l &= ~((1 << 6) | (1 << 26));
-	if (cpu_is_omap2430() || cpu_is_omap34xx())
+	if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
 		l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
 	else
 		l |= ((read_prio & 0x1) << 6);
@@ -922,7 +946,9 @@
 
 			cur_lch = next_lch;
 		} while (next_lch != -1);
-	} else if (cpu_class_is_omap2()) {
+	} else if (cpu_is_omap242x() ||
+		(cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) {
+
 		/* Errata: Need to write lch even if not using chaining */
 		dma_write(lch, CLNK_CTRL(lch));
 	}
@@ -1199,7 +1225,7 @@
  * 	     Failure: -EINVAL/-ENOMEM
  */
 int omap_request_dma_chain(int dev_id, const char *dev_name,
-			   void (*callback) (int chain_id, u16 ch_status,
+			   void (*callback) (int lch, u16 ch_status,
 					     void *data),
 			   int *chain_id, int no_of_chans, int chain_mode,
 			   struct omap_dma_channel_params params)
@@ -1823,7 +1849,8 @@
 #define omap1_dma_irq_handler	NULL
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+			defined(CONFIG_ARCH_OMAP4)
 
 static int omap2_dma_handle_ch(int ch)
 {
@@ -2318,6 +2345,9 @@
 	} else if (cpu_is_omap34xx()) {
 		omap_dma_base = IO_ADDRESS(OMAP34XX_DMA4_BASE);
 		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
+	} else if (cpu_is_omap44xx()) {
+		omap_dma_base = IO_ADDRESS(OMAP44XX_DMA4_BASE);
+		dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
 	} else {
 		pr_err("DMA init failed for unsupported omap\n");
 		return -ENODEV;
@@ -2416,12 +2446,31 @@
 		}
 	}
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx())
+	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())
 		omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
 				DMA_DEFAULT_FIFO_DEPTH, 0);
 
-	if (cpu_class_is_omap2())
-		setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq);
+	if (cpu_class_is_omap2()) {
+		int irq;
+		if (cpu_is_omap44xx())
+			irq = INT_44XX_SDMA_IRQ0;
+		else
+			irq = INT_24XX_SDMA_IRQ0;
+		setup_irq(irq, &omap24xx_dma_irq);
+	}
+
+	/* Enable smartidle idlemodes and autoidle */
+	if (cpu_is_omap34xx()) {
+		u32 v = dma_read(OCP_SYSCONFIG);
+		v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
+				DMA_SYSCONFIG_SIDLEMODE_MASK |
+				DMA_SYSCONFIG_AUTOIDLE);
+		v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
+			DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
+			DMA_SYSCONFIG_AUTOIDLE);
+		dma_write(v , OCP_SYSCONFIG);
+	}
+
 
 	/* FIXME: Update LCD DMA to work on 24xx */
 	if (cpu_class_is_omap1()) {
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/dmtimer.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/dmtimer.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/dmtimer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/dmtimer.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,6 +7,9 @@
  * OMAP2 support by Juha Yrjola
  * API improvements and OMAP2 clock framework support by Timo Teras
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * 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
@@ -150,7 +153,8 @@
 struct omap_dm_timer {
 	unsigned long phys_base;
 	int irq;
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+			defined(CONFIG_ARCH_OMAP4)
 	struct clk *iclk, *fclk;
 #endif
 	void __iomem *io_base;
@@ -169,6 +173,9 @@
 #define omap3_dm_timers			NULL
 #define omap3_dm_source_names		NULL
 #define omap3_dm_source_clocks		NULL
+#define omap4_dm_timers			NULL
+#define omap4_dm_source_names		NULL
+#define omap4_dm_source_clocks		NULL
 
 static struct omap_dm_timer omap1_dm_timers[] = {
 	{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
@@ -191,6 +198,9 @@
 #define omap3_dm_timers			NULL
 #define omap3_dm_source_names		NULL
 #define omap3_dm_source_clocks		NULL
+#define omap4_dm_timers			NULL
+#define omap4_dm_source_names		NULL
+#define omap4_dm_source_clocks		NULL
 
 static struct omap_dm_timer omap2_dm_timers[] = {
 	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
@@ -214,7 +224,7 @@
 	NULL
 };
 
-static struct clk **omap2_dm_source_clocks[3];
+static struct clk *omap2_dm_source_clocks[3];
 static const int dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
 
 #elif defined(CONFIG_ARCH_OMAP3)
@@ -225,6 +235,9 @@
 #define omap2_dm_timers			NULL
 #define omap2_dm_source_names		NULL
 #define omap2_dm_source_clocks		NULL
+#define omap4_dm_timers			NULL
+#define omap4_dm_source_names		NULL
+#define omap4_dm_source_clocks		NULL
 
 static struct omap_dm_timer omap3_dm_timers[] = {
 	{ .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
@@ -247,9 +260,43 @@
 	NULL
 };
 
-static struct clk **omap3_dm_source_clocks[2];
+static struct clk *omap3_dm_source_clocks[2];
 static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
 
+#elif defined(CONFIG_ARCH_OMAP4)
+
+#define omap_dm_clk_enable(x)		clk_enable(x)
+#define omap_dm_clk_disable(x)		clk_disable(x)
+#define omap1_dm_timers			NULL
+#define omap2_dm_timers			NULL
+#define omap2_dm_source_names		NULL
+#define omap2_dm_source_clocks		NULL
+#define omap3_dm_timers			NULL
+#define omap3_dm_source_names		NULL
+#define omap3_dm_source_clocks		NULL
+
+static struct omap_dm_timer omap4_dm_timers[] = {
+	{ .phys_base = 0x4a318000, .irq = INT_44XX_GPTIMER1 },
+	{ .phys_base = 0x48032000, .irq = INT_44XX_GPTIMER2 },
+	{ .phys_base = 0x48034000, .irq = INT_44XX_GPTIMER3 },
+	{ .phys_base = 0x48036000, .irq = INT_44XX_GPTIMER4 },
+	{ .phys_base = 0x40138000, .irq = INT_44XX_GPTIMER5 },
+	{ .phys_base = 0x4013a000, .irq = INT_44XX_GPTIMER6 },
+	{ .phys_base = 0x4013a000, .irq = INT_44XX_GPTIMER7 },
+	{ .phys_base = 0x4013e000, .irq = INT_44XX_GPTIMER8 },
+	{ .phys_base = 0x4803e000, .irq = INT_44XX_GPTIMER9 },
+	{ .phys_base = 0x48086000, .irq = INT_44XX_GPTIMER10 },
+	{ .phys_base = 0x48088000, .irq = INT_44XX_GPTIMER11 },
+	{ .phys_base = 0x4a320000, .irq = INT_44XX_GPTIMER12 },
+};
+static const char *omap4_dm_source_names[] __initdata = {
+	"sys_ck",
+	"omap_32k_fck",
+	NULL
+};
+static struct clk *omap4_dm_source_clocks[2];
+static const int dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
+
 #else
 
 #error OMAP architecture not supported!
@@ -257,7 +304,7 @@
 #endif
 
 static struct omap_dm_timer *dm_timers;
-static char **dm_source_names;
+static const char **dm_source_names;
 static struct clk **dm_source_clocks;
 
 static spinlock_t dm_timer_lock;
@@ -459,7 +506,8 @@
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 
-#elif defined(CONFIG_ARCH_OMAP2) || defined (CONFIG_ARCH_OMAP3)
+#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+				defined(CONFIG_ARCH_OMAP4)
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
@@ -705,12 +753,16 @@
 		dm_timers = omap1_dm_timers;
 	else if (cpu_is_omap24xx()) {
 		dm_timers = omap2_dm_timers;
-		dm_source_names = (char **)omap2_dm_source_names;
-		dm_source_clocks = (struct clk **)omap2_dm_source_clocks;
+		dm_source_names = omap2_dm_source_names;
+		dm_source_clocks = omap2_dm_source_clocks;
 	} else if (cpu_is_omap34xx()) {
 		dm_timers = omap3_dm_timers;
-		dm_source_names = (char **)omap3_dm_source_names;
-		dm_source_clocks = (struct clk **)omap3_dm_source_clocks;
+		dm_source_names = omap3_dm_source_names;
+		dm_source_clocks = omap3_dm_source_clocks;
+	} else if (cpu_is_omap44xx()) {
+		dm_timers = omap4_dm_timers;
+		dm_source_names = omap4_dm_source_names;
+		dm_source_clocks = omap4_dm_source_clocks;
 	}
 
 	if (cpu_class_is_omap2())
@@ -723,7 +775,8 @@
 	for (i = 0; i < dm_timer_count; i++) {
 		timer = &dm_timers[i];
 		timer->io_base = IO_ADDRESS(timer->phys_base);
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+					defined(CONFIG_ARCH_OMAP4)
 		if (cpu_class_is_omap2()) {
 			char clk_name[16];
 			sprintf(clk_name, "gpt%d_ick", i + 1);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,9 @@
  * Copyright (C) 2003-2005 Nokia Corporation
  * Written by Juha Yrjölä <juha.yrjola@nokia.com>
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -146,6 +149,16 @@
 #define OMAP34XX_GPIO5_BASE		IO_ADDRESS(0x49056000)
 #define OMAP34XX_GPIO6_BASE		IO_ADDRESS(0x49058000)
 
+/*
+ * OMAP44XX  specific GPIO registers
+ */
+#define OMAP44XX_GPIO1_BASE             IO_ADDRESS(0x4a310000)
+#define OMAP44XX_GPIO2_BASE             IO_ADDRESS(0x48055000)
+#define OMAP44XX_GPIO3_BASE             IO_ADDRESS(0x48057000)
+#define OMAP44XX_GPIO4_BASE             IO_ADDRESS(0x48059000)
+#define OMAP44XX_GPIO5_BASE             IO_ADDRESS(0x4805B000)
+#define OMAP44XX_GPIO6_BASE             IO_ADDRESS(0x4805D000)
+
 #define OMAP_MPUIO_VBASE		IO_ADDRESS(OMAP_MPUIO_BASE)
 
 struct gpio_bank {
@@ -153,11 +166,13 @@
 	u16 irq;
 	u16 virtual_irq_start;
 	int method;
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) ||  \
+		defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
 	u32 suspend_wakeup;
 	u32 saved_wakeup;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 	u32 non_wakeup_gpios;
 	u32 enabled_non_wakeup_gpios;
 
@@ -251,6 +266,24 @@
 
 #endif
 
+#ifdef CONFIG_ARCH_OMAP4
+static struct gpio_bank gpio_bank_44xx[6] = {
+	{ OMAP44XX_GPIO1_BASE, INT_44XX_GPIO_BANK1, IH_GPIO_BASE,	\
+		METHOD_GPIO_24XX },
+	{ OMAP44XX_GPIO2_BASE, INT_44XX_GPIO_BANK2, IH_GPIO_BASE + 32,	\
+		METHOD_GPIO_24XX },
+	{ OMAP44XX_GPIO3_BASE, INT_44XX_GPIO_BANK3, IH_GPIO_BASE + 64,	\
+		METHOD_GPIO_24XX },
+	{ OMAP44XX_GPIO4_BASE, INT_44XX_GPIO_BANK4, IH_GPIO_BASE + 96,	\
+		METHOD_GPIO_24XX },
+	{ OMAP44XX_GPIO5_BASE, INT_44XX_GPIO_BANK5, IH_GPIO_BASE + 128, \
+		METHOD_GPIO_24XX },
+	{ OMAP44XX_GPIO6_BASE, INT_44XX_GPIO_BANK6, IH_GPIO_BASE + 160, \
+		METHOD_GPIO_24XX },
+};
+
+#endif
+
 static struct gpio_bank *gpio_bank;
 static int gpio_bank_count;
 
@@ -273,7 +306,7 @@
 	}
 	if (cpu_is_omap24xx())
 		return &gpio_bank[gpio >> 5];
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx() || cpu_is_omap44xx())
 		return &gpio_bank[gpio >> 5];
 	BUG();
 	return NULL;
@@ -285,7 +318,7 @@
 		return gpio & 0x1f;
 	if (cpu_is_omap24xx())
 		return gpio & 0x1f;
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx() || cpu_is_omap44xx())
 		return gpio & 0x1f;
 	return gpio & 0x0f;
 }
@@ -307,7 +340,7 @@
 		return 0;
 	if (cpu_is_omap24xx() && gpio < 128)
 		return 0;
-	if (cpu_is_omap34xx() && gpio < 192)
+	if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
 		return 0;
 	return -1;
 }
@@ -353,7 +386,8 @@
 		reg += OMAP850_GPIO_DIR_CONTROL;
 		break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_OE;
 		break;
@@ -425,7 +459,8 @@
 			l &= ~(1 << gpio);
 		break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		if (enable)
 			reg += OMAP24XX_GPIO_SETDATAOUT;
@@ -441,14 +476,12 @@
 	__raw_writel(l, reg);
 }
 
-static int __omap_get_gpio_datain(int gpio)
+static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
 {
-	struct gpio_bank *bank;
 	void __iomem *reg;
 
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
-	bank = get_gpio_bank(gpio);
 	reg = bank->base;
 	switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
@@ -476,7 +509,8 @@
 		reg += OMAP850_GPIO_DATA_INPUT;
 		break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_DATAIN;
 		break;
@@ -488,6 +522,53 @@
 			& (1 << get_gpio_index(gpio))) != 0;
 }
 
+static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+{
+	void __iomem *reg;
+
+	if (check_gpio(gpio) < 0)
+		return -EINVAL;
+	reg = bank->base;
+
+	switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+	case METHOD_MPUIO:
+		reg += OMAP_MPUIO_OUTPUT;
+		break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+	case METHOD_GPIO_1510:
+		reg += OMAP1510_GPIO_DATA_OUTPUT;
+		break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+	case METHOD_GPIO_1610:
+		reg += OMAP1610_GPIO_DATAOUT;
+		break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
+	case METHOD_GPIO_730:
+		reg += OMAP730_GPIO_DATA_OUTPUT;
+		break;
+#endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_DATA_OUTPUT;
+		break;
+#endif
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+		defined(CONFIG_ARCH_OMAP4)
+	case METHOD_GPIO_24XX:
+		reg += OMAP24XX_GPIO_DATAOUT;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
+}
+
 #define MOD_REG_BIT(reg, bit_mask, set)	\
 do {	\
 	int l = __raw_readl(base + reg); \
@@ -520,7 +601,7 @@
 	else
 		goto done;
 
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
 		if (enable)
 			clk_enable(bank->dbck);
 		else
@@ -550,7 +631,8 @@
 }
 EXPORT_SYMBOL(omap_set_gpio_debounce_time);
 
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
 						int trigger)
 {
@@ -660,7 +742,8 @@
 			goto bad;
 		break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		set_24xx_gpio_triggering(bank, gpio, trigger);
 		break;
@@ -745,7 +828,8 @@
 		reg += OMAP850_GPIO_INT_STATUS;
 		break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_IRQSTATUS1;
 		break;
@@ -814,7 +898,8 @@
 		inv = 1;
 		break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_IRQENABLE1;
 		mask = 0xffffffff;
@@ -887,7 +972,8 @@
 			l |= gpio_mask;
 		break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+		defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		if (enable)
 			reg += OMAP24XX_GPIO_SETIRQENABLE1;
@@ -932,7 +1018,8 @@
 		spin_unlock_irqrestore(&bank->lock, flags);
 		return 0;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 	case METHOD_GPIO_24XX:
 		if (bank->non_wakeup_gpios & (1 << gpio)) {
 			printk(KERN_ERR "Unable to modify wakeup on "
@@ -1017,7 +1104,8 @@
 		__raw_writel(1 << offset, reg);
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 	if (bank->method == METHOD_GPIO_24XX) {
 		/* Disable wake-up during idle for dynamic tick */
 		void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
@@ -1069,7 +1157,8 @@
 	if (bank->method == METHOD_GPIO_850)
 		isr_reg = bank->base + OMAP850_GPIO_INT_STATUS;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 	if (bank->method == METHOD_GPIO_24XX)
 		isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
 #endif
@@ -1145,6 +1234,7 @@
 	struct gpio_bank *bank = get_irq_chip_data(irq);
 
 	_set_gpio_irqenable(bank, gpio, 0);
+	_set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
 }
 
 static void gpio_unmask_irq(unsigned int irq)
@@ -1152,6 +1242,11 @@
 	unsigned int gpio = irq - IH_GPIO_BASE;
 	struct gpio_bank *bank = get_irq_chip_data(irq);
 	unsigned int irq_mask = 1 << get_gpio_index(gpio);
+	struct irq_desc *desc = irq_to_desc(irq);
+	u32 trigger = desc->status & IRQ_TYPE_SENSE_MASK;
+
+	if (trigger)
+		_set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
 
 	/* For level-triggered GPIOs, the clearing must be done after
 	 * the HW source is cleared, thus after the handler has run */
@@ -1306,9 +1401,49 @@
 	return 0;
 }
 
+static int gpio_is_input(struct gpio_bank *bank, int mask)
+{
+	void __iomem *reg = bank->base;
+
+	switch (bank->method) {
+	case METHOD_MPUIO:
+		reg += OMAP_MPUIO_IO_CNTL;
+		break;
+	case METHOD_GPIO_1510:
+		reg += OMAP1510_GPIO_DIR_CONTROL;
+		break;
+	case METHOD_GPIO_1610:
+		reg += OMAP1610_GPIO_DIRECTION;
+		break;
+	case METHOD_GPIO_730:
+		reg += OMAP730_GPIO_DIR_CONTROL;
+		break;
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_DIR_CONTROL;
+		break;
+	case METHOD_GPIO_24XX:
+		reg += OMAP24XX_GPIO_OE;
+		break;
+	}
+	return __raw_readl(reg) & mask;
+}
+
 static int gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	return __omap_get_gpio_datain(chip->base + offset);
+	struct gpio_bank *bank;
+	void __iomem *reg;
+	int gpio;
+	u32 mask;
+
+	gpio = chip->base + offset;
+	bank = get_gpio_bank(gpio);
+	reg = bank->base;
+	mask = 1 << get_gpio_index(gpio);
+
+	if (gpio_is_input(bank, mask))
+		return _get_gpio_datain(bank, gpio);
+	else
+		return _get_gpio_dataout(bank, gpio);
 }
 
 static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
@@ -1346,7 +1481,7 @@
 /*---------------------------------------------------------------------*/
 
 static int initialized;
-#if !defined(CONFIG_ARCH_OMAP3)
+#if !(defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4))
 static struct clk * gpio_ick;
 #endif
 
@@ -1359,7 +1494,7 @@
 static struct clk * gpio5_fck;
 #endif
 
-#if defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS];
 #endif
 
@@ -1419,8 +1554,8 @@
 	}
 #endif
 
-#if defined(CONFIG_ARCH_OMAP3)
-	if (cpu_is_omap34xx()) {
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
+	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
 		for (i = 0; i < OMAP34XX_NR_GPIOS; i++) {
 			sprintf(clk_name, "gpio%d_ick", i + 1);
 			gpio_iclks[i] = clk_get(NULL, clk_name);
@@ -1497,6 +1632,17 @@
 			(rev >> 4) & 0x0f, rev & 0x0f);
 	}
 #endif
+#ifdef CONFIG_ARCH_OMAP4
+	if (cpu_is_omap44xx()) {
+		int rev;
+
+		gpio_bank_count = OMAP34XX_NR_GPIOS;
+		gpio_bank = gpio_bank_44xx;
+		rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+		printk(KERN_INFO "OMAP44xx GPIO hardware version %d.%d\n",
+			(rev >> 4) & 0x0f, rev & 0x0f);
+	}
+#endif
 	for (i = 0; i < gpio_bank_count; i++) {
 		int j, gpio_count = 16;
 
@@ -1520,7 +1666,8 @@
 			gpio_count = 32; /* 730 has 32-bit GPIOs */
 		}
 
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 		if (bank->method == METHOD_GPIO_24XX) {
 			static const u32 non_wakeup_gpios[] = {
 				0xe203ffc0, 0x08700040
@@ -1529,6 +1676,7 @@
 			__raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
 			__raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
 			__raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG);
+			__raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_DEBOUNCE_EN);
 
 			/* Initialize interface clock ungated, module enabled */
 			__raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
@@ -1577,7 +1725,7 @@
 		set_irq_chained_handler(bank->irq, gpio_irq_handler);
 		set_irq_data(bank->irq, bank);
 
-		if (cpu_is_omap34xx()) {
+		if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
 			sprintf(clk_name, "gpio%d_dbck", i + 1);
 			bank->dbck = clk_get(NULL, clk_name);
 			if (IS_ERR(bank->dbck))
@@ -1599,7 +1747,8 @@
 	return 0;
 }
 
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \
+		defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
 static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
 {
 	int i;
@@ -1622,7 +1771,8 @@
 			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
 			break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 		case METHOD_GPIO_24XX:
 			wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
 			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
@@ -1663,7 +1813,8 @@
 			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
 			break;
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 		case METHOD_GPIO_24XX:
 			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
 			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
@@ -1695,7 +1846,8 @@
 
 #endif
 
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 
 static int workaround_enabled;
 
@@ -1711,7 +1863,8 @@
 
 		if (!(bank->enabled_non_wakeup_gpios))
 			continue;
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+				defined(CONFIG_ARCH_OMAP4)
 		bank->saved_datain = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
 		l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
 		l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
@@ -1720,7 +1873,8 @@
 		bank->saved_risingdetect = l2;
 		l1 &= ~bank->enabled_non_wakeup_gpios;
 		l2 &= ~bank->enabled_non_wakeup_gpios;
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 		__raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT);
 		__raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT);
 #endif
@@ -1745,7 +1899,8 @@
 
 		if (!(bank->enabled_non_wakeup_gpios))
 			continue;
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 		__raw_writel(bank->saved_fallingdetect,
 				 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
 		__raw_writel(bank->saved_risingdetect,
@@ -1755,14 +1910,16 @@
 		 * state.  If so, generate an IRQ by software.  This is
 		 * horribly racy, but it's the best we can do to work around
 		 * this silicon bug. */
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 		l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
 #endif
 		l ^= bank->saved_datain;
 		l &= bank->non_wakeup_gpios;
 		if (l) {
 			u32 old0, old1;
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 			old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
 			old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
 			__raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
@@ -1798,7 +1955,8 @@
 
 	mpuio_init();
 
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \
+		defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
 	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
 		if (ret == 0) {
 			ret = sysdev_class_register(&omap_gpio_sysclass);
@@ -1819,34 +1977,6 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
-static int gpio_is_input(struct gpio_bank *bank, int mask)
-{
-	void __iomem *reg = bank->base;
-
-	switch (bank->method) {
-	case METHOD_MPUIO:
-		reg += OMAP_MPUIO_IO_CNTL;
-		break;
-	case METHOD_GPIO_1510:
-		reg += OMAP1510_GPIO_DIR_CONTROL;
-		break;
-	case METHOD_GPIO_1610:
-		reg += OMAP1610_GPIO_DIRECTION;
-		break;
-	case METHOD_GPIO_730:
-		reg += OMAP730_GPIO_DIR_CONTROL;
-		break;
-	case METHOD_GPIO_850:
-		reg += OMAP850_GPIO_DIR_CONTROL;
-		break;
-	case METHOD_GPIO_24XX:
-		reg += OMAP24XX_GPIO_OE;
-		break;
-	}
-	return __raw_readl(reg) & mask;
-}
-
-
 static int dbg_gpio_show(struct seq_file *s, void *unused)
 {
 	unsigned	i, j, gpio;
@@ -1887,7 +2017,7 @@
 
 			irqstat = irq_desc[irq].status;
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) ||	\
-		defined(CONFIG_ARCH_OMAP34XX)
+		defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4)
 			if (is_in && ((bank->suspend_wakeup & mask)
 					|| irqstat & IRQ_TYPE_SENSE_MASK)) {
 				char	*trigger = NULL;
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/i2c.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/i2c.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2007 Nokia Corporation.
  *
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Contact: Jarkko Nikula <jhnikula@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/clock.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/clock.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/clock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,9 +20,12 @@
 struct clkops {
 	int			(*enable)(struct clk *);
 	void			(*disable)(struct clk *);
+	void			(*find_idlest)(struct clk *, void __iomem **, u8 *);
+	void			(*find_companion)(struct clk *, void __iomem **, u8 *);
 };
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+		defined(CONFIG_ARCH_OMAP4)
 
 struct clksel_rate {
 	u32			val;
@@ -51,7 +54,7 @@
 	u8			max_divider;
 	u32			max_tolerance;
 	u16			max_multiplier;
-#  if defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 	u8			modes;
 	void __iomem		*autoidle_reg;
 	void __iomem		*idlest_reg;
@@ -83,7 +86,8 @@
 	void			(*init)(struct clk *);
 	__u8			enable_bit;
 	__s8			usecount;
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+		defined(CONFIG_ARCH_OMAP4)
 	u8			fixed_div;
 	void __iomem		*clksel_reg;
 	u32			clksel_mask;
@@ -119,7 +123,7 @@
 extern unsigned int mpurate;
 
 extern int clk_init(struct clk_functions *custom_clocks);
-extern void clk_init_one(struct clk *clk);
+extern void clk_preinit(struct clk *clk);
 extern int clk_register(struct clk *clk);
 extern void clk_reparent(struct clk *child, struct clk *parent);
 extern void clk_unregister(struct clk *clk);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/common.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/common.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/common.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,8 +33,6 @@
 
 extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
-extern void omap_serial_init(void);
-extern void omap_serial_enable_clocks(int enable);
 #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
 				 struct i2c_board_info const *info,
@@ -62,6 +60,7 @@
 void omap2_set_globals_242x(void);
 void omap2_set_globals_243x(void);
 void omap2_set_globals_343x(void);
+void omap2_set_globals_443x(void);
 
 /* These get called from omap2_set_globals_xxxx(), do not call these */
 void omap2_set_globals_tap(struct omap_globals *);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/control.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/control.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/control.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/control.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,9 +1,9 @@
 /*
  * arch/arm/plat-omap/include/mach/control.h
  *
- * OMAP2/3 System Control Module definitions
+ * OMAP2/3/4 System Control Module definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
  * Copyright (C) 2007-2008 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -144,6 +144,10 @@
 #define OMAP343X_CONTROL_PBIAS_LITE	(OMAP2_CONTROL_GENERAL + 0x02b0)
 #define OMAP343X_CONTROL_TEMP_SENSOR	(OMAP2_CONTROL_GENERAL + 0x02b4)
 
+/* 34xx D2D idle-related pins, handled by PM core */
+#define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
+#define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
+
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
@@ -189,8 +193,18 @@
 #define OMAP2_PBIASLITEPWRDNZ0		(1 << 1)
 #define OMAP2_PBIASLITEVMODE0		(1 << 0)
 
+/* CONTROL_IVA2_BOOTMOD bits */
+#define OMAP3_IVA2_BOOTMOD_SHIFT	0
+#define OMAP3_IVA2_BOOTMOD_MASK		(0xf << 0)
+#define OMAP3_IVA2_BOOTMOD_IDLE		(0x1 << 0)
+
+/* CONTROL_PADCONF_X bits */
+#define OMAP3_PADCONF_WAKEUPEVENT0	(1 << 15)
+#define OMAP3_PADCONF_WAKEUPENABLE0	(1 << 14)
+
 #ifndef __ASSEMBLY__
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+		defined(CONFIG_ARCH_OMAP4)
 extern void __iomem *omap_ctrl_base_get(void);
 extern u8 omap_ctrl_readb(u16 offset);
 extern u16 omap_ctrl_readw(u16 offset);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/cpu.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/cpu.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/cpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/cpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,8 +5,12 @@
  *
  * Copyright (C) 2004, 2008 Nokia Corporation
  *
+ * Copyright (C) 2009 Texas Instruments.
+ *
  * Written by Tony Lindgren <tony.lindgren@nokia.com>
  *
+ * Added OMAP4 specific defines - Santosh Shilimkar<santosh.shilimkar@ti.com>
+ *
  * 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
@@ -26,6 +30,17 @@
 #ifndef __ASM_ARCH_OMAP_CPU_H
 #define __ASM_ARCH_OMAP_CPU_H
 
+/*
+ * Omap device type i.e. EMU/HS/TST/GP/BAD
+ */
+#define OMAP2_DEVICE_TYPE_TEST		0
+#define OMAP2_DEVICE_TYPE_EMU		1
+#define OMAP2_DEVICE_TYPE_SEC		2
+#define OMAP2_DEVICE_TYPE_GP		3
+#define OMAP2_DEVICE_TYPE_BAD		4
+
+int omap_type(void);
+
 struct omap_chip_id {
 	u8 oc;
 	u8 type;
@@ -155,6 +170,8 @@
 #define cpu_is_omap243x()		0
 #define cpu_is_omap34xx()		0
 #define cpu_is_omap343x()		0
+#define cpu_is_omap44xx()		0
+#define cpu_is_omap443x()		0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
@@ -348,12 +365,18 @@
 # define cpu_is_omap3430()		is_omap3430()
 #endif
 
+# if defined(CONFIG_ARCH_OMAP4)
+# undef cpu_is_omap44xx
+# undef cpu_is_omap443x
+# define cpu_is_omap44xx()		1
+# define cpu_is_omap443x()		1
+# endif
+
 /* Macros to detect if we have OMAP1 or OMAP2 */
 #define cpu_class_is_omap1()	(cpu_is_omap7xx() || cpu_is_omap15xx() || \
 				cpu_is_omap16xx())
-#define cpu_class_is_omap2()	(cpu_is_omap24xx() || cpu_is_omap34xx())
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#define cpu_class_is_omap2()	(cpu_is_omap24xx() || cpu_is_omap34xx() || \
+				cpu_is_omap44xx())
 
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS		0x24200024
@@ -370,6 +393,8 @@
 #define OMAP3430_REV_ES3_0	0x34303034
 #define OMAP3430_REV_ES3_1	0x34304034
 
+#define OMAP443X_CLASS		0x44300034
+
 /*
  * omap_chip bits
  *
@@ -407,17 +432,4 @@
 
 
 int omap_chip_is(struct omap_chip_id oci);
-int omap_type(void);
-
-/*
- * Macro to detect device type i.e. EMU/HS/TST/GP/BAD
- */
-#define OMAP2_DEVICE_TYPE_TEST		0
-#define OMAP2_DEVICE_TYPE_EMU		1
-#define OMAP2_DEVICE_TYPE_SEC		2
-#define OMAP2_DEVICE_TYPE_GP		3
-#define OMAP2_DEVICE_TYPE_BAD		4
-
 void omap2_check_revision(void);
-
-#endif    /* defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/debug-macro.S linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/debug-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/debug-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/debug-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,7 @@
 		add	\rx, \rx, #0x00004000	@ UART 3
 #endif
 
-#elif	CONFIG_ARCH_OMAP3
+#elif defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 		moveq	\rx, #0x48000000	@ physical base address
 		movne	\rx, #0xd8000000	@ virtual base
 		orr	\rx, \rx, #0x0006a000
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/dma.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/dma.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,7 @@
 /* Hardware registers for omap2 and omap3 */
 #define OMAP24XX_DMA4_BASE		(L4_24XX_BASE + 0x56000)
 #define OMAP34XX_DMA4_BASE		(L4_34XX_BASE + 0x56000)
+#define OMAP44XX_DMA4_BASE		(L4_44XX_BASE + 0x56000)
 
 #define OMAP_DMA4_REVISION		0x00
 #define OMAP_DMA4_GCR			0x78
@@ -144,6 +145,7 @@
 #define OMAP_DMA4_CSSA_U(n)		0
 #define OMAP_DMA4_CDSA_L(n)		0
 #define OMAP_DMA4_CDSA_U(n)		0
+#define OMAP1_DMA_COLOR(n)		0
 
 /*----------------------------------------------------------------------------*/
 
@@ -387,6 +389,21 @@
 #define DMA_THREAD_FIFO_25		(0x02 << 14)
 #define DMA_THREAD_FIFO_50		(0x03 << 14)
 
+/* DMA4_OCP_SYSCONFIG bits */
+#define DMA_SYSCONFIG_MIDLEMODE_MASK		(3 << 12)
+#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK	(3 << 8)
+#define DMA_SYSCONFIG_EMUFREE			(1 << 5)
+#define DMA_SYSCONFIG_SIDLEMODE_MASK		(3 << 3)
+#define DMA_SYSCONFIG_SOFTRESET			(1 << 2)
+#define DMA_SYSCONFIG_AUTOIDLE			(1 << 0)
+
+#define DMA_SYSCONFIG_MIDLEMODE(n)		((n) << 12)
+#define DMA_SYSCONFIG_SIDLEMODE(n)		((n) << 3)
+
+#define DMA_IDLEMODE_SMARTIDLE			0x2
+#define DMA_IDLEMODE_NO_IDLE			0x1
+#define DMA_IDLEMODE_FORCE_IDLE			0x0
+
 /* Chaining modes*/
 #ifndef CONFIG_ARCH_OMAP1
 #define OMAP_DMA_STATIC_CHAIN		0x1
@@ -531,7 +548,7 @@
 /* Chaining APIs */
 #ifndef CONFIG_ARCH_OMAP1
 extern int omap_request_dma_chain(int dev_id, const char *dev_name,
-				  void (*callback) (int chain_id, u16 ch_status,
+				  void (*callback) (int lch, u16 ch_status,
 						    void *data),
 				  int *chain_id, int no_of_chans,
 				  int chain_mode,
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/entry-macro.S linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/entry-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/entry-macro.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/entry-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,9 @@
  *
  * Low-level IRQ helper macros for OMAP-based platforms
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * 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.
@@ -10,6 +13,7 @@
 #include <mach/hardware.h>
 #include <mach/io.h>
 #include <mach/irqs.h>
+#include <asm/hardware/gic.h>
 
 #if defined(CONFIG_ARCH_OMAP1)
 
@@ -56,15 +60,21 @@
 		.endm
 
 #endif
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+			defined(CONFIG_ARCH_OMAP4)
 
-#if defined(CONFIG_ARCH_OMAP24XX)
 #include <mach/omap24xx.h>
-#endif
-#if defined(CONFIG_ARCH_OMAP34XX)
 #include <mach/omap34xx.h>
-#endif
 
+/* REVISIT: This should be set dynamically if CONFIG_MULTI_OMAP2 is selected */
+#if defined(CONFIG_ARCH_OMAP2420) || defined(CONFIG_ARCH_OMAP2430)
+#define OMAP2_VA_IC_BASE		IO_ADDRESS(OMAP24XX_IC_BASE)
+#elif defined(CONFIG_ARCH_OMAP34XX)
+#define OMAP2_VA_IC_BASE		IO_ADDRESS(OMAP34XX_IC_BASE)
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+#include <mach/omap44xx.h>
+#endif
 #define INTCPS_SIR_IRQ_OFFSET	0x0040		/* Active interrupt offset */
 #define	ACTIVEIRQ_MASK		0x7f		/* Active interrupt bits */
 
@@ -77,6 +87,7 @@
 		.macro  arch_ret_to_user, tmp1, tmp2
 		.endm
 
+#ifndef CONFIG_ARCH_OMAP4
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		ldr	\base, =OMAP2_VA_IC_BASE
 		ldr	\irqnr, [\base, #0x98] /* IRQ pending reg 1 */
@@ -92,6 +103,68 @@
 		and	\irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
 
 		.endm
+#else
+		/*
+		 * The interrupt numbering scheme is defined in the
+		 * interrupt controller spec.  To wit:
+		 *
+		 * Interrupts 0-15 are IPI
+		 * 16-28 are reserved
+		 * 29-31 are local.  We allow 30 to be used for the watchdog.
+		 * 32-1020 are global
+		 * 1021-1022 are reserved
+		 * 1023 is "spurious" (no interrupt)
+		 *
+		 * For now, we ignore all local interrupts so only return an
+		 * interrupt if it's between 30 and 1020.  The test_for_ipi
+		 * routine below will pick up on IPIs.
+		 * A simple read from the controller will tell us the number
+		 * of the highest priority enabled interrupt.
+		 * We then just need to check whether it is in the
+		 * valid range for an IRQ (30-1020 inclusive).
+		 */
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr     \base, =OMAP44XX_VA_GIC_CPU_BASE
+		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+
+		ldr     \tmp, =1021
+
+		bic     \irqnr, \irqstat, #0x1c00
+
+		cmp     \irqnr, #29
+		cmpcc   \irqnr, \irqnr
+		cmpne   \irqnr, \tmp
+		cmpcs   \irqnr, \irqnr
+		.endm
+
+		/* We assume that irqstat (the raw value of the IRQ acknowledge
+		 * register) is preserved from the macro above.
+		 * If there is an IPI, we immediately signal end of interrupt
+		 * on the controller, since this requires the original irqstat
+		 * value which we won't easily be able to recreate later.
+		 */
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		it	cc
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		it	cs
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* As above, this assumes that irqstat and base are preserved */
+
+		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov 	\tmp, #0
+		cmp	\irqnr, #29
+		itt	eq
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
+#endif
 
 		.macro	irq_prio_table
 		.endm
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/gpmc-smc91x.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/gpmc-smc91x.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/gpmc-smc91x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/gpmc-smc91x.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/plat-omap/include/mach/gpmc-smc91x.h
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPMC_SMC91X_H__
+
+#define GPMC_TIMINGS_SMC91C96	(1 << 4)
+#define GPMC_MUX_ADD_DATA	(1 << 5) /* GPMC_CONFIG1_MUXADDDATA */
+#define GPMC_READ_MON		(1 << 6) /* GPMC_CONFIG1_WAIT_READ_MON */
+#define GPMC_WRITE_MON		(1 << 7) /* GPMC_CONFIG1_WAIT_WRITE_MON */
+
+struct omap_smc91x_platform_data {
+	int	cs;
+	int	gpio_irq;
+	int	gpio_pwrdwn;
+	int	gpio_reset;
+	int	wait_pin;	/* Optional GPMC_CONFIG1_WAITPINSELECT */
+	u32	flags;
+	int	(*retime)(void);
+};
+
+#if defined(CONFIG_SMC91X) || \
+	defined(CONFIG_SMC91X_MODULE)
+
+extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
+
+#else
+
+#define board_smc91x_data	NULL
+
+static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
+{
+}
+
+#endif
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/hardware.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/hardware.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/hardware.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/hardware.h	2009-09-09 18:13:59.000000000 -0400
@@ -285,5 +285,6 @@
 #include "omap16xx.h"
 #include "omap24xx.h"
 #include "omap34xx.h"
+#include "omap44xx.h"
 
 #endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/hwa742.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/hwa742.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/hwa742.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/hwa742.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,10 +2,6 @@
 #define _HWA742_H
 
 struct hwa742_platform_data {
-	void		(*power_up)(struct device *dev);
-	void		(*power_down)(struct device *dev);
-	unsigned long	(*get_clock_rate)(struct device *dev);
-
 	unsigned	te_connected:1;
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/io.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/io.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,9 @@
  * Copied from arch/arm/mach-sa1100/include/mach/io.h
  * Copyright (C) 1997-1999 Russell King
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * 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
@@ -157,6 +160,40 @@
 #define DSP_MMU_34XX_VIRT	0xe2000000
 #define DSP_MMU_34XX_SIZE	SZ_4K
 
+
+#elif defined(CONFIG_ARCH_OMAP4)
+/* We map both L3 and L4 on OMAP4 */
+#define L3_44XX_PHYS		L3_44XX_BASE
+#define L3_44XX_VIRT		0xd4000000
+#define L3_44XX_SIZE		SZ_1M
+
+#define L4_44XX_PHYS		L4_44XX_BASE
+#define L4_44XX_VIRT		0xda000000
+#define L4_44XX_SIZE		SZ_4M
+
+
+#define L4_WK_44XX_PHYS		L4_WK_44XX_BASE
+#define L4_WK_44XX_VIRT		0xda300000
+#define L4_WK_44XX_SIZE		SZ_1M
+
+#define L4_PER_44XX_PHYS	L4_PER_44XX_BASE
+#define L4_PER_44XX_VIRT	0xd8000000
+#define L4_PER_44XX_SIZE	SZ_4M
+
+#define L4_EMU_44XX_PHYS	L4_EMU_44XX_BASE
+#define L4_EMU_44XX_VIRT	0xe4000000
+#define L4_EMU_44XX_SIZE	SZ_64M
+
+#define OMAP44XX_GPMC_PHYS	OMAP44XX_GPMC_BASE
+#define OMAP44XX_GPMC_VIRT	0xe0000000
+#define OMAP44XX_GPMC_SIZE	SZ_1M
+
+
+#define IO_OFFSET		0x90000000
+#define __IO_ADDRESS(pa)	((pa) + IO_OFFSET)/* Works for L3 and L4 */
+#define __OMAP2_IO_ADDRESS(pa)	((pa) + IO_OFFSET)/* Works for L3 and L4 */
+#define io_v2p(va)		((va) - IO_OFFSET)/* Works for L3 and L4 */
+
 #endif
 
 #define IO_ADDRESS(pa)		IOMEM(__IO_ADDRESS(pa))
@@ -164,7 +201,7 @@
 #define OMAP2_IO_ADDRESS(pa)	IOMEM(__OMAP2_IO_ADDRESS(pa))
 
 #ifdef __ASSEMBLER__
-#define IOMEM(x)		x
+#define IOMEM(x)		(x)
 #else
 #define IOMEM(x)		((void __force __iomem *)(x))
 
@@ -191,7 +228,8 @@
 extern void omap1_init_common_hw(void);
 
 extern void omap2_map_common_io(void);
-extern void omap2_init_common_hw(struct omap_sdrc_params *sp);
+extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
+				 struct omap_sdrc_params *sdrc_cs1);
 
 #define __arch_ioremap(p,s,t)	omap_ioremap(p,s,t)
 #define __arch_iounmap(v)	omap_iounmap(v)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/iommu2.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/iommu2.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/iommu2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/iommu2.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,96 @@
+/*
+ * omap iommu: omap2 architecture specific definitions
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MACH_IOMMU2_H
+#define __MACH_IOMMU2_H
+
+#include <linux/io.h>
+
+/*
+ * MMU Register offsets
+ */
+#define MMU_REVISION		0x00
+#define MMU_SYSCONFIG		0x10
+#define MMU_SYSSTATUS		0x14
+#define MMU_IRQSTATUS		0x18
+#define MMU_IRQENABLE		0x1c
+#define MMU_WALKING_ST		0x40
+#define MMU_CNTL		0x44
+#define MMU_FAULT_AD		0x48
+#define MMU_TTB			0x4c
+#define MMU_LOCK		0x50
+#define MMU_LD_TLB		0x54
+#define MMU_CAM			0x58
+#define MMU_RAM			0x5c
+#define MMU_GFLUSH		0x60
+#define MMU_FLUSH_ENTRY		0x64
+#define MMU_READ_CAM		0x68
+#define MMU_READ_RAM		0x6c
+#define MMU_EMU_FAULT_AD	0x70
+
+#define MMU_REG_SIZE		256
+
+/*
+ * MMU Register bit definitions
+ */
+#define MMU_LOCK_BASE_SHIFT	10
+#define MMU_LOCK_BASE_MASK	(0x1f << MMU_LOCK_BASE_SHIFT)
+#define MMU_LOCK_BASE(x)	\
+	((x & MMU_LOCK_BASE_MASK) >> MMU_LOCK_BASE_SHIFT)
+
+#define MMU_LOCK_VICT_SHIFT	4
+#define MMU_LOCK_VICT_MASK	(0x1f << MMU_LOCK_VICT_SHIFT)
+#define MMU_LOCK_VICT(x)	\
+	((x & MMU_LOCK_VICT_MASK) >> MMU_LOCK_VICT_SHIFT)
+
+#define MMU_CAM_VATAG_SHIFT	12
+#define MMU_CAM_VATAG_MASK \
+	((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT)
+#define MMU_CAM_P		(1 << 3)
+#define MMU_CAM_V		(1 << 2)
+#define MMU_CAM_PGSZ_MASK	3
+#define MMU_CAM_PGSZ_1M		(0 << 0)
+#define MMU_CAM_PGSZ_64K	(1 << 0)
+#define MMU_CAM_PGSZ_4K		(2 << 0)
+#define MMU_CAM_PGSZ_16M	(3 << 0)
+
+#define MMU_RAM_PADDR_SHIFT	12
+#define MMU_RAM_PADDR_MASK \
+	((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
+#define MMU_RAM_ENDIAN_SHIFT	9
+#define MMU_RAM_ENDIAN_MASK	(1 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ENDIAN_BIG	(1 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ENDIAN_LITTLE	(0 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ELSZ_SHIFT	7
+#define MMU_RAM_ELSZ_MASK	(3 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_8		(0 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_16		(1 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_32		(2 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_NONE	(3 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_MIXED_SHIFT	6
+#define MMU_RAM_MIXED_MASK	(1 << MMU_RAM_MIXED_SHIFT)
+#define MMU_RAM_MIXED		MMU_RAM_MIXED_MASK
+
+/*
+ * register accessors
+ */
+static inline u32 iommu_read_reg(struct iommu *obj, size_t offs)
+{
+	return __raw_readl(obj->regbase + offs);
+}
+
+static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs)
+{
+	__raw_writel(val, obj->regbase + offs);
+}
+
+#endif /* __MACH_IOMMU2_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/iommu.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/iommu.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/iommu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/iommu.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * omap iommu: main structures
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __MACH_IOMMU_H
+#define __MACH_IOMMU_H
+
+struct iotlb_entry {
+	u32 da;
+	u32 pa;
+	u32 pgsz, prsvd, valid;
+	union {
+		u16 ap;
+		struct {
+			u32 endian, elsz, mixed;
+		};
+	};
+};
+
+struct iommu {
+	const char	*name;
+	struct module	*owner;
+	struct clk	*clk;
+	void __iomem	*regbase;
+	struct device	*dev;
+
+	unsigned int	refcount;
+	struct mutex	iommu_lock;	/* global for this whole object */
+
+	/*
+	 * We don't change iopgd for a situation like pgd for a task,
+	 * but share it globally for each iommu.
+	 */
+	u32		*iopgd;
+	spinlock_t	page_table_lock; /* protect iopgd */
+
+	int		nr_tlb_entries;
+
+	struct list_head	mmap;
+	struct mutex		mmap_lock; /* protect mmap */
+
+	int (*isr)(struct iommu *obj);
+
+	void *ctx; /* iommu context: registres saved area */
+};
+
+struct cr_regs {
+	union {
+		struct {
+			u16 cam_l;
+			u16 cam_h;
+		};
+		u32 cam;
+	};
+	union {
+		struct {
+			u16 ram_l;
+			u16 ram_h;
+		};
+		u32 ram;
+	};
+};
+
+struct iotlb_lock {
+	short base;
+	short vict;
+};
+
+/* architecture specific functions */
+struct iommu_functions {
+	unsigned long	version;
+
+	int (*enable)(struct iommu *obj);
+	void (*disable)(struct iommu *obj);
+	u32 (*fault_isr)(struct iommu *obj, u32 *ra);
+
+	void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
+	void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
+
+	struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e);
+	int (*cr_valid)(struct cr_regs *cr);
+	u32 (*cr_to_virt)(struct cr_regs *cr);
+	void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
+	ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf);
+
+	u32 (*get_pte_attr)(struct iotlb_entry *e);
+
+	void (*save_ctx)(struct iommu *obj);
+	void (*restore_ctx)(struct iommu *obj);
+	ssize_t (*dump_ctx)(struct iommu *obj, char *buf);
+};
+
+struct iommu_platform_data {
+	const char *name;
+	const char *clk_name;
+	const int nr_tlb_entries;
+};
+
+#if defined(CONFIG_ARCH_OMAP1)
+#error "iommu for this processor not implemented yet"
+#else
+#include <mach/iommu2.h>
+#endif
+
+/*
+ * utilities for super page(16MB, 1MB, 64KB and 4KB)
+ */
+
+#define iopgsz_max(bytes)			\
+	(((bytes) >= SZ_16M) ? SZ_16M :		\
+	 ((bytes) >= SZ_1M)  ? SZ_1M  :		\
+	 ((bytes) >= SZ_64K) ? SZ_64K :		\
+	 ((bytes) >= SZ_4K)  ? SZ_4K  :	0)
+
+#define bytes_to_iopgsz(bytes)				\
+	(((bytes) == SZ_16M) ? MMU_CAM_PGSZ_16M :	\
+	 ((bytes) == SZ_1M)  ? MMU_CAM_PGSZ_1M  :	\
+	 ((bytes) == SZ_64K) ? MMU_CAM_PGSZ_64K :	\
+	 ((bytes) == SZ_4K)  ? MMU_CAM_PGSZ_4K  : -1)
+
+#define iopgsz_to_bytes(iopgsz)				\
+	(((iopgsz) == MMU_CAM_PGSZ_16M)	? SZ_16M :	\
+	 ((iopgsz) == MMU_CAM_PGSZ_1M)	? SZ_1M  :	\
+	 ((iopgsz) == MMU_CAM_PGSZ_64K)	? SZ_64K :	\
+	 ((iopgsz) == MMU_CAM_PGSZ_4K)	? SZ_4K  : 0)
+
+#define iopgsz_ok(bytes) (bytes_to_iopgsz(bytes) >= 0)
+
+/*
+ * global functions
+ */
+extern u32 iommu_arch_version(void);
+
+extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
+extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
+
+extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
+extern void flush_iotlb_page(struct iommu *obj, u32 da);
+extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
+extern void flush_iotlb_all(struct iommu *obj);
+
+extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
+extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
+
+extern struct iommu *iommu_get(const char *name);
+extern void iommu_put(struct iommu *obj);
+
+extern void iommu_save_ctx(struct iommu *obj);
+extern void iommu_restore_ctx(struct iommu *obj);
+
+extern int install_iommu_arch(const struct iommu_functions *ops);
+extern void uninstall_iommu_arch(const struct iommu_functions *ops);
+
+extern int foreach_iommu_device(void *data,
+				int (*fn)(struct device *, void *));
+
+extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf);
+extern size_t dump_tlb_entries(struct iommu *obj, char *buf);
+
+#endif /* __MACH_IOMMU_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/iovmm.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/iovmm.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/iovmm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/iovmm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * omap iommu: simple virtual address space management
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __IOMMU_MMAP_H
+#define __IOMMU_MMAP_H
+
+struct iovm_struct {
+	struct iommu		*iommu;	/* iommu object which this belongs to */
+	u32			da_start; /* area definition */
+	u32			da_end;
+	u32			flags; /* IOVMF_: see below */
+	struct list_head	list; /* linked in ascending order */
+	const struct sg_table	*sgt; /* keep 'page' <-> 'da' mapping */
+	void			*va; /* mpu side mapped address */
+};
+
+/*
+ * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
+ *
+ * lower 16 bit is used for h/w and upper 16 bit is for s/w.
+ */
+#define IOVMF_SW_SHIFT		16
+#define IOVMF_HW_SIZE		(1 << IOVMF_SW_SHIFT)
+#define IOVMF_HW_MASK		(IOVMF_HW_SIZE - 1)
+#define IOVMF_SW_MASK		(~IOVMF_HW_MASK)UL
+
+/*
+ * iovma: h/w flags derived from cam and ram attribute
+ */
+#define IOVMF_CAM_MASK		(~((1 << 10) - 1))
+#define IOVMF_RAM_MASK		(~IOVMF_CAM_MASK)
+
+#define IOVMF_PGSZ_MASK		(3 << 0)
+#define IOVMF_PGSZ_1M		MMU_CAM_PGSZ_1M
+#define IOVMF_PGSZ_64K		MMU_CAM_PGSZ_64K
+#define IOVMF_PGSZ_4K		MMU_CAM_PGSZ_4K
+#define IOVMF_PGSZ_16M		MMU_CAM_PGSZ_16M
+
+#define IOVMF_ENDIAN_MASK	(1 << 9)
+#define IOVMF_ENDIAN_BIG	MMU_RAM_ENDIAN_BIG
+#define IOVMF_ENDIAN_LITTLE	MMU_RAM_ENDIAN_LITTLE
+
+#define IOVMF_ELSZ_MASK		(3 << 7)
+#define IOVMF_ELSZ_8		MMU_RAM_ELSZ_8
+#define IOVMF_ELSZ_16		MMU_RAM_ELSZ_16
+#define IOVMF_ELSZ_32		MMU_RAM_ELSZ_32
+#define IOVMF_ELSZ_NONE		MMU_RAM_ELSZ_NONE
+
+#define IOVMF_MIXED_MASK	(1 << 6)
+#define IOVMF_MIXED		MMU_RAM_MIXED
+
+/*
+ * iovma: s/w flags, used for mapping and umapping internally.
+ */
+#define IOVMF_MMIO		(1 << IOVMF_SW_SHIFT)
+#define IOVMF_ALLOC		(2 << IOVMF_SW_SHIFT)
+#define IOVMF_ALLOC_MASK	(3 << IOVMF_SW_SHIFT)
+
+/* "superpages" is supported just with physically linear pages */
+#define IOVMF_DISCONT		(1 << (2 + IOVMF_SW_SHIFT))
+#define IOVMF_LINEAR		(2 << (2 + IOVMF_SW_SHIFT))
+#define IOVMF_LINEAR_MASK	(3 << (2 + IOVMF_SW_SHIFT))
+
+#define IOVMF_DA_FIXED		(1 << (4 + IOVMF_SW_SHIFT))
+#define IOVMF_DA_ANON		(2 << (4 + IOVMF_SW_SHIFT))
+#define IOVMF_DA_MASK		(3 << (4 + IOVMF_SW_SHIFT))
+
+
+extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
+extern u32 iommu_vmap(struct iommu *obj, u32 da,
+			const struct sg_table *sgt, u32 flags);
+extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da);
+extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes,
+			   u32 flags);
+extern void iommu_vfree(struct iommu *obj, const u32 da);
+extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
+			u32 flags);
+extern void iommu_kunmap(struct iommu *obj, u32 da);
+extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes,
+			   u32 flags);
+extern void iommu_kfree(struct iommu *obj, u32 da);
+
+extern void *da_to_va(struct iommu *obj, u32 da);
+
+#endif /* __IOMMU_MMAP_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/irqs.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -4,6 +4,9 @@
  *  Copyright (C) Greg Lonnon 2001
  *  Updated for OMAP-1610 by Tony Lindgren <tony@atomide.com>
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * 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
@@ -422,6 +425,94 @@
 
 #define	INT_34XX_BENCH_MPU_EMUL	3
 
+
+#define IRQ_GIC_START		32
+#define INT_44XX_LOCALTIMER_IRQ	29
+#define INT_44XX_LOCALWDT_IRQ	30
+
+#define INT_44XX_BENCH_MPU_EMUL	(3 + IRQ_GIC_START)
+#define INT_44XX_SSM_ABORT_IRQ	(6 + IRQ_GIC_START)
+#define INT_44XX_SYS_NIRQ	(7 + IRQ_GIC_START)
+#define INT_44XX_D2D_FW_IRQ	(8 + IRQ_GIC_START)
+#define INT_44XX_PRCM_MPU_IRQ	(11 + IRQ_GIC_START)
+#define INT_44XX_SDMA_IRQ0	(12 + IRQ_GIC_START)
+#define INT_44XX_SDMA_IRQ1	(13 + IRQ_GIC_START)
+#define INT_44XX_SDMA_IRQ2	(14 + IRQ_GIC_START)
+#define INT_44XX_SDMA_IRQ3	(15 + IRQ_GIC_START)
+#define INT_44XX_ISS_IRQ	(24 + IRQ_GIC_START)
+#define INT_44XX_DSS_IRQ	(25 + IRQ_GIC_START)
+#define INT_44XX_MAIL_U0_MPU	(26 + IRQ_GIC_START)
+#define INT_44XX_DSP_MMU	(28 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER1	(37 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER2	(38 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER3	(39 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER4	(40 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER5	(41 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER6	(42 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER7	(43 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER8	(44 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER9	(45 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER10	(46 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER11	(47 + IRQ_GIC_START)
+#define INT_44XX_GPTIMER12	(95 + IRQ_GIC_START)
+#define INT_44XX_SHA1MD5	(51 + IRQ_GIC_START)
+#define INT_44XX_I2C1_IRQ	(56 + IRQ_GIC_START)
+#define INT_44XX_I2C2_IRQ	(57 + IRQ_GIC_START)
+#define INT_44XX_HDQ_IRQ	(58 + IRQ_GIC_START)
+#define INT_44XX_SPI1_IRQ	(65 + IRQ_GIC_START)
+#define INT_44XX_SPI2_IRQ	(66 + IRQ_GIC_START)
+#define INT_44XX_HSI_1_IRQ0	(67 + IRQ_GIC_START)
+#define INT_44XX_HSI_2_IRQ1	(68 + IRQ_GIC_START)
+#define INT_44XX_HSI_1_DMAIRQ	(71 + IRQ_GIC_START)
+#define INT_44XX_UART1_IRQ	(72 + IRQ_GIC_START)
+#define INT_44XX_UART2_IRQ	(73 + IRQ_GIC_START)
+#define INT_44XX_UART3_IRQ	(74 + IRQ_GIC_START)
+#define INT_44XX_UART4_IRQ	(70 + IRQ_GIC_START)
+#define INT_44XX_USB_IRQ_NISO	(76 + IRQ_GIC_START)
+#define INT_44XX_USB_IRQ_ISO	(77 + IRQ_GIC_START)
+#define INT_44XX_USB_IRQ_HGEN	(78 + IRQ_GIC_START)
+#define INT_44XX_USB_IRQ_HSOF	(79 + IRQ_GIC_START)
+#define INT_44XX_USB_IRQ_OTG	(80 + IRQ_GIC_START)
+#define INT_44XX_MCBSP4_IRQ_TX	(81 + IRQ_GIC_START)
+#define INT_44XX_MCBSP4_IRQ_RX	(82 + IRQ_GIC_START)
+#define INT_44XX_MMC_IRQ	(83 + IRQ_GIC_START)
+#define INT_44XX_MMC2_IRQ	(86 + IRQ_GIC_START)
+#define INT_44XX_MCBSP2_IRQ_TX	(89 + IRQ_GIC_START)
+#define INT_44XX_MCBSP2_IRQ_RX	(90 + IRQ_GIC_START)
+#define INT_44XX_SPI3_IRQ	(91 + IRQ_GIC_START)
+#define INT_44XX_SPI5_IRQ	(69 + IRQ_GIC_START)
+
+#define INT_44XX_MCBSP5_IRQ	(16 + IRQ_GIC_START)
+#define INT_44xX_MCBSP1_IRQ	(17 + IRQ_GIC_START)
+#define INT_44XX_MCBSP2_IRQ	(22 + IRQ_GIC_START)
+#define INT_44XX_MCBSP3_IRQ	(23 + IRQ_GIC_START)
+#define INT_44XX_MCBSP4_IRQ	(27 + IRQ_GIC_START)
+#define INT_44XX_HS_USB_MC	(92 + IRQ_GIC_START)
+#define INT_44XX_HS_USB_DMA	(93 + IRQ_GIC_START)
+
+#define INT_44XX_GPIO_BANK1	(29 + IRQ_GIC_START)
+#define INT_44XX_GPIO_BANK2	(30 + IRQ_GIC_START)
+#define INT_44XX_GPIO_BANK3	(31 + IRQ_GIC_START)
+#define INT_44XX_GPIO_BANK4	(32 + IRQ_GIC_START)
+#define INT_44XX_GPIO_BANK5	(33 + IRQ_GIC_START)
+#define INT_44XX_GPIO_BANK6	(34 + IRQ_GIC_START)
+#define INT_44XX_USIM_IRQ	(35 + IRQ_GIC_START)
+#define INT_44XX_WDT3_IRQ	(36 + IRQ_GIC_START)
+#define INT_44XX_SPI4_IRQ	(48 + IRQ_GIC_START)
+#define INT_44XX_SHA1MD52_IRQ	(49 + IRQ_GIC_START)
+#define INT_44XX_FPKA_READY_IRQ	(50 + IRQ_GIC_START)
+#define INT_44XX_SHA1MD51_IRQ	(51 + IRQ_GIC_START)
+#define INT_44XX_RNG_IRQ	(52 + IRQ_GIC_START)
+#define INT_44XX_I2C3_IRQ	(61 + IRQ_GIC_START)
+#define INT_44XX_FPKA_ERROR_IRQ	(64 + IRQ_GIC_START)
+#define INT_44XX_PBIAS_IRQ	(75 + IRQ_GIC_START)
+#define INT_44XX_OHCI_IRQ	(76 + IRQ_GIC_START)
+#define INT_44XX_EHCI_IRQ	(77 + IRQ_GIC_START)
+#define INT_44XX_TLL_IRQ	(78 + IRQ_GIC_START)
+#define INT_44XX_PARTHASH_IRQ	(79 + IRQ_GIC_START)
+#define INT_44XX_MMC3_IRQ	(94 + IRQ_GIC_START)
+
+
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and
  * 16 MPUIO lines */
 #define OMAP_MAX_GPIO_LINES	192
@@ -467,6 +558,7 @@
 
 #ifndef __ASSEMBLY__
 extern void omap_init_irq(void);
+extern int omap_irq_pending(void);
 #endif
 
 #include <mach/hardware.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/keypad.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/keypad.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/keypad.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/keypad.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,11 @@
 #define GROUP_3		(3 << 16)
 #define GROUP_MASK	GROUP_3
 
+#define KEY_PERSISTENT		0x00800000
+#define KEYNUM_MASK		0x00EFFFFF
 #define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+#define PERSISTENT_KEY(col, row) (((col) << 28) | ((row) << 24) | \
+						KEY_PERSISTENT)
 
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/memory.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/memory.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/memory.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/memory.h	2009-09-09 18:13:59.000000000 -0400
@@ -38,7 +38,8 @@
  */
 #if defined(CONFIG_ARCH_OMAP1)
 #define PHYS_OFFSET		UL(0x10000000)
-#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+			defined(CONFIG_ARCH_OMAP4)
 #define PHYS_OFFSET		UL(0x80000000)
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/mux.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/mux.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/mux.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/mux.h	2009-09-09 18:13:59.000000000 -0400
@@ -853,6 +853,10 @@
 	AE5_34XX_GPIO143,
 	H19_34XX_GPIO164_OUT,
 	J25_34XX_GPIO170,
+
+	/* OMAP3 SDRC CKE signals to SDR/DDR ram chips */
+	H16_34XX_SDRC_CKE0,
+	H17_34XX_SDRC_CKE1,
 };
 
 struct omap_mux_cfg {
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/omap24xx.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/omap24xx.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/omap24xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/omap24xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -85,23 +85,5 @@
 #define OMAP24XX_SEC_AES_BASE	(OMAP24XX_SEC_BASE + 0x6000)
 #define OMAP24XX_SEC_PKA_BASE	(OMAP24XX_SEC_BASE + 0x8000)
 
-#if defined(CONFIG_ARCH_OMAP2420)
-
-#define OMAP2_32KSYNCT_BASE	OMAP2420_32KSYNCT_BASE
-#define OMAP2_PRCM_BASE		OMAP2420_PRCM_BASE
-#define OMAP2_CM_BASE		OMAP2420_CM_BASE
-#define OMAP2_PRM_BASE		OMAP2420_PRM_BASE
-#define OMAP2_VA_IC_BASE	IO_ADDRESS(OMAP24XX_IC_BASE)
-
-#elif defined(CONFIG_ARCH_OMAP2430)
-
-#define OMAP2_32KSYNCT_BASE	OMAP2430_32KSYNCT_BASE
-#define OMAP2_PRCM_BASE		OMAP2430_PRCM_BASE
-#define OMAP2_CM_BASE		OMAP2430_CM_BASE
-#define OMAP2_PRM_BASE		OMAP2430_PRM_BASE
-#define OMAP2_VA_IC_BASE	IO_ADDRESS(OMAP24XX_IC_BASE)
-
-#endif
-
 #endif /* __ASM_ARCH_OMAP24XX_H */
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/omap34xx.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/omap34xx.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/omap34xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/omap34xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -31,13 +31,9 @@
 
 #define L4_34XX_BASE		0x48000000
 #define L4_WK_34XX_BASE		0x48300000
-#define L4_WK_OMAP_BASE		L4_WK_34XX_BASE
 #define L4_PER_34XX_BASE	0x49000000
-#define L4_PER_OMAP_BASE	L4_PER_34XX_BASE
 #define L4_EMU_34XX_BASE	0x54000000
-#define L4_EMU_BASE		L4_EMU_34XX_BASE
 #define L3_34XX_BASE		0x68000000
-#define L3_OMAP_BASE		L3_34XX_BASE
 
 #define OMAP3430_32KSYNCT_BASE	0x48320000
 #define OMAP3430_CM_BASE	0x48004800
@@ -83,15 +79,6 @@
 
 #define OMAP34XX_MAILBOX_BASE		(L4_34XX_BASE + 0x94000)
 
-#if defined(CONFIG_ARCH_OMAP3430)
-
-#define OMAP2_32KSYNCT_BASE		OMAP3430_32KSYNCT_BASE
-#define OMAP2_CM_BASE			OMAP3430_CM_BASE
-#define OMAP2_PRM_BASE			OMAP3430_PRM_BASE
-#define OMAP2_VA_IC_BASE		IO_ADDRESS(OMAP34XX_IC_BASE)
-
-#endif
-
 #define OMAP34XX_DSP_BASE	0x58000000
 #define OMAP34XX_DSP_MEM_BASE	(OMAP34XX_DSP_BASE + 0x0)
 #define OMAP34XX_DSP_IPI_BASE	(OMAP34XX_DSP_BASE + 0x1000000)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/omap44xx.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/omap44xx.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/omap44xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/omap44xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,46 @@
+/*:
+ * Address mappings and base address for OMAP4 interconnects
+ * and peripherals.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Author: Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_OMAP44XX_H
+#define __ASM_ARCH_OMAP44XX_H
+
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers.
+ */
+#define L4_44XX_BASE			0x4a000000
+#define L4_WK_44XX_BASE			0x4a300000
+#define L4_PER_44XX_BASE		0x48000000
+#define L4_EMU_44XX_BASE		0x54000000
+#define L3_44XX_BASE			0x44000000
+#define OMAP4430_32KSYNCT_BASE		0x4a304000
+#define OMAP4430_CM_BASE		0x4a004000
+#define OMAP4430_PRM_BASE		0x48306000
+#define OMAP44XX_GPMC_BASE		0x50000000
+#define OMAP443X_SCM_BASE		0x4a002000
+#define OMAP443X_CTRL_BASE		OMAP443X_SCM_BASE
+#define OMAP44XX_IC_BASE		0x48200000
+#define OMAP44XX_IVA_INTC_BASE		0x40000000
+#define IRQ_SIR_IRQ			0x0040
+#define OMAP44XX_GIC_DIST_BASE		0x48241000
+#define OMAP44XX_GIC_CPU_BASE		0x48240100
+#define OMAP44XX_VA_GIC_CPU_BASE	IO_ADDRESS(OMAP44XX_GIC_CPU_BASE)
+#define OMAP44XX_SCU_BASE		0x48240000
+#define OMAP44XX_VA_SCU_BASE		IO_ADDRESS(OMAP44XX_SCU_BASE)
+#define OMAP44XX_LOCAL_TWD_BASE		0x48240600
+#define OMAP44XX_VA_LOCAL_TWD_BASE	IO_ADDRESS(OMAP44XX_LOCAL_TWD_BASE)
+#define OMAP44XX_LOCAL_TWD_SIZE		0x00000100
+#define OMAP44XX_WKUPGEN_BASE		0x48281000
+#define OMAP44XX_VA_WKUPGEN_BASE	IO_ADDRESS(OMAP44XX_WKUPGEN_BASE)
+
+#endif /* __ASM_ARCH_OMAP44XX_H */
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/onenand.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/onenand.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/onenand.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/onenand.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,8 +9,12 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
+#define ONENAND_SYNC_READ	(1 << 0)
+#define ONENAND_SYNC_READWRITE	(1 << 1)
+
 struct omap_onenand_platform_data {
 	int			cs;
 	int			gpio_irq;
@@ -18,8 +22,22 @@
 	int			nr_parts;
 	int                     (*onenand_setup)(void __iomem *, int freq);
 	int			dma_channel;
+	u8			flags;
 };
 
-int omap2_onenand_rephase(void);
-
 #define ONENAND_MAX_PARTITIONS 8
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+
+extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+
+#else
+
+#define board_onenand_data	NULL
+
+static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+{
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/pm.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/pm.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/pm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/pm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,345 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/pm.h
- *
- * Header file for OMAP Power Management Routines
- *
- * Author: MontaVista Software, Inc.
- *	   support@mvista.com
- *
- * Copyright 2002 MontaVista Software Inc.
- *
- * Cleanup 2004 for Linux 2.6 by Dirk Behme <dirk.behme@de.bosch.com>
- *
- * 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 __ASM_ARCH_OMAP_PM_H
-#define __ASM_ARCH_OMAP_PM_H
-
-/*
- * ----------------------------------------------------------------------------
- * Register and offset definitions to be used in PM assembler code
- * ----------------------------------------------------------------------------
- */
-#define CLKGEN_REG_ASM_BASE		IO_ADDRESS(0xfffece00)
-#define ARM_IDLECT1_ASM_OFFSET		0x04
-#define ARM_IDLECT2_ASM_OFFSET		0x08
-
-#define TCMIF_ASM_BASE			IO_ADDRESS(0xfffecc00)
-#define EMIFS_CONFIG_ASM_OFFSET		0x0c
-#define EMIFF_SDRAM_CONFIG_ASM_OFFSET	0x20
-
-/*
- * ----------------------------------------------------------------------------
- * Power management bitmasks
- * ----------------------------------------------------------------------------
- */
-#define IDLE_WAIT_CYCLES		0x00000fff
-#define PERIPHERAL_ENABLE		0x2
-
-#define SELF_REFRESH_MODE		0x0c000001
-#define IDLE_EMIFS_REQUEST		0xc
-#define MODEM_32K_EN			0x1
-#define PER_EN				0x1
-
-#define CPU_SUSPEND_SIZE		200
-#define ULPD_LOW_PWR_EN			0x0001
-#define ULPD_DEEP_SLEEP_TRANSITION_EN	0x0010
-#define ULPD_SETUP_ANALOG_CELL_3_VAL	0
-#define ULPD_POWER_CTRL_REG_VAL		0x0219
-
-#define DSP_IDLE_DELAY			10
-#define DSP_IDLE			0x0040
-#define DSP_RST				0x0004
-#define DSP_ENABLE			0x0002
-#define SUFFICIENT_DSP_RESET_TIME	1000
-#define DEFAULT_MPUI_CONFIG		0x05cf
-#define ENABLE_XORCLK			0x2
-#define DSP_CLOCK_ENABLE		0x2000
-#define DSP_IDLE_MODE			0x2
-#define TC_IDLE_REQUEST			(0x0000000c)
-
-#define IRQ_LEVEL2			(1<<0)
-#define IRQ_KEYBOARD			(1<<1)
-#define IRQ_UART2			(1<<15)
-
-#define PDE_BIT				0x08
-#define PWD_EN_BIT			0x04
-#define EN_PERCK_BIT			0x04
-
-#define OMAP1510_DEEP_SLEEP_REQUEST	0x0ec7
-#define OMAP1510_BIG_SLEEP_REQUEST	0x0cc5
-#define OMAP1510_IDLE_LOOP_REQUEST	0x0c00
-#define OMAP1510_IDLE_CLOCK_DOMAINS	0x2
-
-/* Both big sleep and deep sleep use same values. Difference is in ULPD. */
-#define OMAP1610_IDLECT1_SLEEP_VAL	0x13c7
-#define OMAP1610_IDLECT2_SLEEP_VAL	0x09c7
-#define OMAP1610_IDLECT3_VAL		0x3f
-#define OMAP1610_IDLECT3_SLEEP_ORMASK	0x2c
-#define OMAP1610_IDLECT3		0xfffece24
-#define OMAP1610_IDLE_LOOP_REQUEST	0x0400
-
-#define OMAP730_IDLECT1_SLEEP_VAL	0x16c7
-#define OMAP730_IDLECT2_SLEEP_VAL	0x09c7
-#define OMAP730_IDLECT3_VAL		0x3f
-#define OMAP730_IDLECT3		0xfffece24
-#define OMAP730_IDLE_LOOP_REQUEST	0x0C00
-
-#if     !defined(CONFIG_ARCH_OMAP730) && \
-	!defined(CONFIG_ARCH_OMAP15XX) && \
-	!defined(CONFIG_ARCH_OMAP16XX) && \
-	!defined(CONFIG_ARCH_OMAP24XX)
-#warning "Power management for this processor not implemented yet"
-#endif
-
-#ifndef __ASSEMBLER__
-
-#include <linux/clk.h>
-
-extern void prevent_idle_sleep(void);
-extern void allow_idle_sleep(void);
-
-extern void omap_pm_idle(void);
-extern void omap_pm_suspend(void);
-extern void omap730_cpu_suspend(unsigned short, unsigned short);
-extern void omap1510_cpu_suspend(unsigned short, unsigned short);
-extern void omap1610_cpu_suspend(unsigned short, unsigned short);
-extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
-					void __iomem *sdrc_power);
-extern void omap730_idle_loop_suspend(void);
-extern void omap1510_idle_loop_suspend(void);
-extern void omap1610_idle_loop_suspend(void);
-extern void omap24xx_idle_loop_suspend(void);
-
-extern unsigned int omap730_cpu_suspend_sz;
-extern unsigned int omap1510_cpu_suspend_sz;
-extern unsigned int omap1610_cpu_suspend_sz;
-extern unsigned int omap24xx_cpu_suspend_sz;
-extern unsigned int omap730_idle_loop_suspend_sz;
-extern unsigned int omap1510_idle_loop_suspend_sz;
-extern unsigned int omap1610_idle_loop_suspend_sz;
-extern unsigned int omap24xx_idle_loop_suspend_sz;
-
-#ifdef CONFIG_OMAP_SERIAL_WAKE
-extern void omap_serial_wake_trigger(int enable);
-#else
-#define omap_serial_wakeup_init()	{}
-#define omap_serial_wake_trigger(x)	{}
-#endif	/* CONFIG_OMAP_SERIAL_WAKE */
-
-#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
-#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
-#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
-
-#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x)
-#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x))
-#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x]
-
-#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
-#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
-#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
-
-#define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x)
-#define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x))
-#define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]
-
-#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x)
-#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x))
-#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]
-
-#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x)
-#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
-#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
-
-#define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x
-#define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
-#define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
-
-/*
- * List of global OMAP registers to preserve.
- * More ones like CP and general purpose register values are preserved
- * with the stack pointer in sleep.S.
- */
-
-enum arm_save_state {
-	ARM_SLEEP_SAVE_START = 0,
-	/*
-	 * MPU control registers 32 bits
-	 */
-	ARM_SLEEP_SAVE_ARM_CKCTL,
-	ARM_SLEEP_SAVE_ARM_IDLECT1,
-	ARM_SLEEP_SAVE_ARM_IDLECT2,
-	ARM_SLEEP_SAVE_ARM_IDLECT3,
-	ARM_SLEEP_SAVE_ARM_EWUPCT,
-	ARM_SLEEP_SAVE_ARM_RSTCT1,
-	ARM_SLEEP_SAVE_ARM_RSTCT2,
-	ARM_SLEEP_SAVE_ARM_SYSST,
-	ARM_SLEEP_SAVE_SIZE
-};
-
-enum dsp_save_state {
-	DSP_SLEEP_SAVE_START = 0,
-	/*
-	 * DSP registers 16 bits
-	 */
-	DSP_SLEEP_SAVE_DSP_IDLECT2,
-	DSP_SLEEP_SAVE_SIZE
-};
-
-enum ulpd_save_state {
-	ULPD_SLEEP_SAVE_START = 0,
-	/*
-	 * ULPD registers 16 bits
-	 */
-	ULPD_SLEEP_SAVE_ULPD_IT_STATUS,
-	ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL,
-	ULPD_SLEEP_SAVE_ULPD_SOFT_REQ,
-	ULPD_SLEEP_SAVE_ULPD_STATUS_REQ,
-	ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL,
-	ULPD_SLEEP_SAVE_ULPD_POWER_CTRL,
-	ULPD_SLEEP_SAVE_SIZE
-};
-
-enum mpui1510_save_state {
-	MPUI1510_SLEEP_SAVE_START = 0,
-	/*
-	 * MPUI registers 32 bits
-	 */
-	MPUI1510_SLEEP_SAVE_MPUI_CTRL,
-	MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
-	MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
-	MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS,
-	MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
-	MPUI1510_SLEEP_SAVE_EMIFS_CONFIG,
-	MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR,
-	MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR,
-#if defined(CONFIG_ARCH_OMAP15XX)
-	MPUI1510_SLEEP_SAVE_SIZE
-#else
-	MPUI1510_SLEEP_SAVE_SIZE = 0
-#endif
-};
-
-enum mpui730_save_state {
-	MPUI730_SLEEP_SAVE_START = 0,
-	/*
-	 * MPUI registers 32 bits
-	 */
-	MPUI730_SLEEP_SAVE_MPUI_CTRL,
-	MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
-	MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
-	MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS,
-	MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
-	MPUI730_SLEEP_SAVE_EMIFS_CONFIG,
-	MPUI730_SLEEP_SAVE_OMAP_IH1_MIR,
-	MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR,
-	MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR,
-#if defined(CONFIG_ARCH_OMAP730)
-	MPUI730_SLEEP_SAVE_SIZE
-#else
-	MPUI730_SLEEP_SAVE_SIZE = 0
-#endif
-};
-
-enum mpui1610_save_state {
-	MPUI1610_SLEEP_SAVE_START = 0,
-	/*
-	 * MPUI registers 32 bits
-	 */
-	MPUI1610_SLEEP_SAVE_MPUI_CTRL,
-	MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
-	MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
-	MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS,
-	MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
-	MPUI1610_SLEEP_SAVE_EMIFS_CONFIG,
-	MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR,
-	MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR,
-#if defined(CONFIG_ARCH_OMAP16XX)
-	MPUI1610_SLEEP_SAVE_SIZE
-#else
-	MPUI1610_SLEEP_SAVE_SIZE = 0
-#endif
-};
-
-enum omap24xx_save_state {
-	OMAP24XX_SLEEP_SAVE_START = 0,
-	OMAP24XX_SLEEP_SAVE_INTC_MIR0,
-	OMAP24XX_SLEEP_SAVE_INTC_MIR1,
-	OMAP24XX_SLEEP_SAVE_INTC_MIR2,
-
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MPU,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_GFX,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_DSP,
-	OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MDM,
-
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MPU,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_CORE,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_GFX,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_DSP,
-	OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MDM,
-
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST1_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST2_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST3_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST4_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_GFX,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_WKUP,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_CKGEN,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_DSP,
-	OMAP24XX_SLEEP_SAVE_CM_IDLEST_MDM,
-
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE1_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE2_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE3_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE4_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_WKUP,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_PLL,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_DSP,
-	OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_MDM,
-
-	OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_ICLKEN3_CORE,
-	OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE,
-	OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1,
-	OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1,
-	OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1,
-	OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1,
-	OMAP24XX_SLEEP_SAVE_GPIO3_OE,
-	OMAP24XX_SLEEP_SAVE_GPIO4_OE,
-	OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT,
-	OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT,
-	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2,
-	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX,
-	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX,
-	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0,
-	OMAP24XX_SLEEP_SAVE_SIZE
-};
-
-#endif /* ASSEMBLER */
-#endif /* __ASM_ARCH_OMAP_PM_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/prcm.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/prcm.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/prcm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/prcm.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 
 u32 omap_prcm_get_reset_sources(void);
 void omap_prcm_arch_reset(char mode);
+int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name);
 
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/sdrc.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/sdrc.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/sdrc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/sdrc.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,10 @@
 #define SDRC_ACTIM_CTRL_A_0	0x09c
 #define SDRC_ACTIM_CTRL_B_0	0x0a0
 #define SDRC_RFR_CTRL_0		0x0a4
+#define SDRC_MR_1		0x0B4
+#define SDRC_ACTIM_CTRL_A_1	0x0C4
+#define SDRC_ACTIM_CTRL_B_1	0x0C8
+#define SDRC_RFR_CTRL_1		0x0D4
 
 /*
  * These values represent the number of memory clock cycles between
@@ -102,8 +106,11 @@
 	u32 mr;
 };
 
-void __init omap2_sdrc_init(struct omap_sdrc_params *sp);
-struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r);
+void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+			    struct omap_sdrc_params *sdrc_cs1);
+int omap2_sdrc_get_params(unsigned long r,
+			  struct omap_sdrc_params **sdrc_cs0,
+			  struct omap_sdrc_params **sdrc_cs1);
 
 #ifdef CONFIG_ARCH_OMAP2
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/serial.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/serial.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/serial.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/serial.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,8 @@
 /*
- *  arch/arm/plat-omap/include/mach/serial.h
+ * arch/arm/plat-omap/include/mach/serial.h
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Addded OMAP4 support- Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,19 +18,28 @@
 #define OMAP_UART1_BASE		0xfffb0000
 #define OMAP_UART2_BASE		0xfffb0800
 #define OMAP_UART3_BASE		0xfffb9800
+#define OMAP_MAX_NR_PORTS	3
 #elif defined(CONFIG_ARCH_OMAP2)
 /* OMAP2 serial ports */
 #define OMAP_UART1_BASE		0x4806a000
 #define OMAP_UART2_BASE		0x4806c000
 #define OMAP_UART3_BASE		0x4806e000
+#define OMAP_MAX_NR_PORTS	3
 #elif defined(CONFIG_ARCH_OMAP3)
 /* OMAP3 serial ports */
 #define OMAP_UART1_BASE		0x4806a000
 #define OMAP_UART2_BASE		0x4806c000
 #define OMAP_UART3_BASE		0x49020000
+#define OMAP_MAX_NR_PORTS	3
+#elif defined(CONFIG_ARCH_OMAP4)
+/* OMAP4 serial ports */
+#define OMAP_UART1_BASE		0x4806a000
+#define OMAP_UART2_BASE		0x4806c000
+#define OMAP_UART3_BASE		0x48020000
+#define OMAP_UART4_BASE		0x4806e000
+#define OMAP_MAX_NR_PORTS	4
 #endif
 
-#define OMAP_MAX_NR_PORTS	3
 #define OMAP1510_BASE_BAUD	(12000000/16)
 #define OMAP16XX_BASE_BAUD	(48000000/16)
 #define OMAP24XX_BASE_BAUD	(48000000/16)
@@ -40,4 +52,14 @@
 			__ret;						\
 			})
 
+#ifndef __ASSEMBLER__
+extern void omap_serial_init(void);
+extern int omap_uart_can_sleep(void);
+extern void omap_uart_check_wakeup(void);
+extern void omap_uart_prepare_suspend(void);
+extern void omap_uart_prepare_idle(int num);
+extern void omap_uart_resume_idle(int num);
+extern void omap_uart_enable_irqs(int enable);
+#endif
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/smp.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/smp.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/smp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/smp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * OMAP4 machine specific smp.h
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Author:
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Interface functions needed for the SMP. This file is based on arm
+ * realview smp platform.
+ * Copyright (c) 2003 ARM Limited.
+ *
+ * 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.
+ */
+#ifndef OMAP_ARCH_SMP_H
+#define OMAP_ARCH_SMP_H
+
+#include <asm/hardware/gic.h>
+
+/*
+ * set_event() is used to wake up secondary core from wfe using sev. ROM
+ * code puts the second core into wfe(standby).
+ *
+ */
+#define set_event()	__asm__ __volatile__ ("sev" : : : "memory")
+
+/* Needed for secondary core boot */
+extern void omap_secondary_startup(void);
+
+/*
+ * We use Soft IRQ1 as the IPI
+ */
+static inline void smp_cross_call(const struct cpumask *mask)
+{
+	gic_raise_softirq(mask, 1);
+}
+
+/*
+ * Read MPIDR: Multiprocessor affinity register
+ */
+#define hard_smp_processor_id()			\
+	({						\
+		unsigned int cpunum;			\
+		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
+			: "=r" (cpunum));		\
+		cpunum &= 0x0F;				\
+	})
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/sram.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/sram.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/sram.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/sram.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,9 +21,12 @@
 				      u32 mem_type);
 extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
 
-extern u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl,
-				     u32 sdrc_actim_ctrla,
-				     u32 sdrc_actim_ctrlb, u32 m2);
+extern u32 omap3_configure_core_dpll(
+			u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
 
 /* Do not use these */
 extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
@@ -57,10 +60,12 @@
 						u32 mem_type);
 extern unsigned long omap243x_sram_reprogram_sdrc_sz;
 
-
-extern u32 omap3_sram_configure_core_dpll(u32 sdrc_rfr_ctrl,
-					  u32 sdrc_actim_ctrla,
-					  u32 sdrc_actim_ctrlb, u32 m2);
+extern u32 omap3_sram_configure_core_dpll(
+			u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
 extern unsigned long omap3_sram_configure_core_dpll_sz;
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/usb.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/usb.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/usb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/usb.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,13 +27,7 @@
 #define UDC_BASE			OMAP2_UDC_BASE
 #define OMAP_OHCI_BASE			OMAP2_OHCI_BASE
 
-#ifdef CONFIG_USB_MUSB_SOC
 extern void usb_musb_init(void);
-#else
-static inline void usb_musb_init(void)
-{
-}
-#endif
 
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/vmalloc.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/vmalloc.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/include/mach/vmalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/include/mach/vmalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,5 +17,5 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-#define VMALLOC_END	  (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END	  (PAGE_OFFSET + 0x18000000)
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/io.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/io.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,14 @@
+/*
+ * Common io.c file
+ * This file is created by Russell King <rmk+kernel@arm.linux.org.uk>
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/mm.h>
@@ -7,6 +18,7 @@
 #include <mach/omap16xx.h>
 #include <mach/omap24xx.h>
 #include <mach/omap34xx.h>
+#include <mach/omap44xx.h>
 
 #define BETWEEN(p,st,sz)	((p) >= (st) && (p) < ((st) + (sz)))
 #define XLATE(p,pst,vst)	((void __iomem *)((p) - (pst) + (vst)))
@@ -92,7 +104,22 @@
 			return XLATE(p, L4_EMU_34XX_PHYS, L4_EMU_34XX_VIRT);
 	}
 #endif
-
+#ifdef CONFIG_ARCH_OMAP4
+	if (cpu_is_omap44xx()) {
+		if (BETWEEN(p, L3_44XX_PHYS, L3_44XX_SIZE))
+			return XLATE(p, L3_44XX_PHYS, L3_44XX_VIRT);
+		if (BETWEEN(p, L4_44XX_PHYS, L4_44XX_SIZE))
+			return XLATE(p, L4_44XX_PHYS, L4_44XX_VIRT);
+		if (BETWEEN(p, L4_WK_44XX_PHYS, L4_WK_44XX_SIZE))
+			return XLATE(p, L4_WK_44XX_PHYS, L4_WK_44XX_VIRT);
+		if (BETWEEN(p, OMAP44XX_GPMC_PHYS, OMAP44XX_GPMC_SIZE))
+			return XLATE(p, OMAP44XX_GPMC_PHYS, OMAP44XX_GPMC_VIRT);
+		if (BETWEEN(p, L4_PER_44XX_PHYS, L4_PER_44XX_SIZE))
+			return XLATE(p, L4_PER_44XX_PHYS, L4_PER_44XX_VIRT);
+		if (BETWEEN(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_SIZE))
+			return XLATE(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_VIRT);
+	}
+#endif
 	return __arm_ioremap(p, size, type);
 }
 EXPORT_SYMBOL(omap_ioremap);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/iommu.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/iommu.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/iommu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,996 @@
+/*
+ * omap iommu: tlb and pagetable primitives
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
+ *		Paul Mundt and Toshihiro Kobayashi
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <asm/cacheflush.h>
+
+#include <mach/iommu.h>
+
+#include "iopgtable.h"
+
+/* accommodate the difference between omap1 and omap2/3 */
+static const struct iommu_functions *arch_iommu;
+
+static struct platform_driver omap_iommu_driver;
+static struct kmem_cache *iopte_cachep;
+
+/**
+ * install_iommu_arch - Install archtecure specific iommu functions
+ * @ops:	a pointer to architecture specific iommu functions
+ *
+ * There are several kind of iommu algorithm(tlb, pagetable) among
+ * omap series. This interface installs such an iommu algorighm.
+ **/
+int install_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu)
+		return -EBUSY;
+
+	arch_iommu = ops;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(install_iommu_arch);
+
+/**
+ * uninstall_iommu_arch - Uninstall archtecure specific iommu functions
+ * @ops:	a pointer to architecture specific iommu functions
+ *
+ * This interface uninstalls the iommu algorighm installed previously.
+ **/
+void uninstall_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu != ops)
+		pr_err("%s: not your arch\n", __func__);
+
+	arch_iommu = NULL;
+}
+EXPORT_SYMBOL_GPL(uninstall_iommu_arch);
+
+/**
+ * iommu_save_ctx - Save registers for pm off-mode support
+ * @obj:	target iommu
+ **/
+void iommu_save_ctx(struct iommu *obj)
+{
+	arch_iommu->save_ctx(obj);
+}
+EXPORT_SYMBOL_GPL(iommu_save_ctx);
+
+/**
+ * iommu_restore_ctx - Restore registers for pm off-mode support
+ * @obj:	target iommu
+ **/
+void iommu_restore_ctx(struct iommu *obj)
+{
+	arch_iommu->restore_ctx(obj);
+}
+EXPORT_SYMBOL_GPL(iommu_restore_ctx);
+
+/**
+ * iommu_arch_version - Return running iommu arch version
+ **/
+u32 iommu_arch_version(void)
+{
+	return arch_iommu->version;
+}
+EXPORT_SYMBOL_GPL(iommu_arch_version);
+
+static int iommu_enable(struct iommu *obj)
+{
+	int err;
+
+	if (!obj)
+		return -EINVAL;
+
+	clk_enable(obj->clk);
+
+	err = arch_iommu->enable(obj);
+
+	clk_disable(obj->clk);
+	return err;
+}
+
+static void iommu_disable(struct iommu *obj)
+{
+	if (!obj)
+		return;
+
+	clk_enable(obj->clk);
+
+	arch_iommu->disable(obj);
+
+	clk_disable(obj->clk);
+}
+
+/*
+ *	TLB operations
+ */
+void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
+{
+	BUG_ON(!cr || !e);
+
+	arch_iommu->cr_to_e(cr, e);
+}
+EXPORT_SYMBOL_GPL(iotlb_cr_to_e);
+
+static inline int iotlb_cr_valid(struct cr_regs *cr)
+{
+	if (!cr)
+		return -EINVAL;
+
+	return arch_iommu->cr_valid(cr);
+}
+
+static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
+					     struct iotlb_entry *e)
+{
+	if (!e)
+		return NULL;
+
+	return arch_iommu->alloc_cr(obj, e);
+}
+
+u32 iotlb_cr_to_virt(struct cr_regs *cr)
+{
+	return arch_iommu->cr_to_virt(cr);
+}
+EXPORT_SYMBOL_GPL(iotlb_cr_to_virt);
+
+static u32 get_iopte_attr(struct iotlb_entry *e)
+{
+	return arch_iommu->get_pte_attr(e);
+}
+
+static u32 iommu_report_fault(struct iommu *obj, u32 *da)
+{
+	return arch_iommu->fault_isr(obj, da);
+}
+
+static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
+{
+	u32 val;
+
+	val = iommu_read_reg(obj, MMU_LOCK);
+
+	l->base = MMU_LOCK_BASE(val);
+	l->vict = MMU_LOCK_VICT(val);
+
+	BUG_ON(l->base != 0); /* Currently no preservation is used */
+}
+
+static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
+{
+	u32 val;
+
+	BUG_ON(l->base != 0); /* Currently no preservation is used */
+
+	val = (l->base << MMU_LOCK_BASE_SHIFT);
+	val |= (l->vict << MMU_LOCK_VICT_SHIFT);
+
+	iommu_write_reg(obj, val, MMU_LOCK);
+}
+
+static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr)
+{
+	arch_iommu->tlb_read_cr(obj, cr);
+}
+
+static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
+{
+	arch_iommu->tlb_load_cr(obj, cr);
+
+	iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
+	iommu_write_reg(obj, 1, MMU_LD_TLB);
+}
+
+/**
+ * iotlb_dump_cr - Dump an iommu tlb entry into buf
+ * @obj:	target iommu
+ * @cr:		contents of cam and ram register
+ * @buf:	output buffer
+ **/
+static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
+				    char *buf)
+{
+	BUG_ON(!cr || !buf);
+
+	return arch_iommu->dump_cr(obj, cr, buf);
+}
+
+/**
+ * load_iotlb_entry - Set an iommu tlb entry
+ * @obj:	target iommu
+ * @e:		an iommu tlb entry info
+ **/
+int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
+{
+	int i;
+	int err = 0;
+	struct iotlb_lock l;
+	struct cr_regs *cr;
+
+	if (!obj || !obj->nr_tlb_entries || !e)
+		return -EINVAL;
+
+	clk_enable(obj->clk);
+
+	for (i = 0; i < obj->nr_tlb_entries; i++) {
+		struct cr_regs tmp;
+
+		iotlb_lock_get(obj, &l);
+		l.vict = i;
+		iotlb_lock_set(obj, &l);
+		iotlb_read_cr(obj, &tmp);
+		if (!iotlb_cr_valid(&tmp))
+			break;
+	}
+
+	if (i == obj->nr_tlb_entries) {
+		dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
+		err = -EBUSY;
+		goto out;
+	}
+
+	cr = iotlb_alloc_cr(obj, e);
+	if (IS_ERR(cr)) {
+		clk_disable(obj->clk);
+		return PTR_ERR(cr);
+	}
+
+	iotlb_load_cr(obj, cr);
+	kfree(cr);
+
+	/* increment victim for next tlb load */
+	if (++l.vict == obj->nr_tlb_entries)
+		l.vict = 0;
+	iotlb_lock_set(obj, &l);
+out:
+	clk_disable(obj->clk);
+	return err;
+}
+EXPORT_SYMBOL_GPL(load_iotlb_entry);
+
+/**
+ * flush_iotlb_page - Clear an iommu tlb entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ *
+ * Clear an iommu tlb entry which includes 'da' address.
+ **/
+void flush_iotlb_page(struct iommu *obj, u32 da)
+{
+	struct iotlb_lock l;
+	int i;
+
+	clk_enable(obj->clk);
+
+	for (i = 0; i < obj->nr_tlb_entries; i++) {
+		struct cr_regs cr;
+		u32 start;
+		size_t bytes;
+
+		iotlb_lock_get(obj, &l);
+		l.vict = i;
+		iotlb_lock_set(obj, &l);
+		iotlb_read_cr(obj, &cr);
+		if (!iotlb_cr_valid(&cr))
+			continue;
+
+		start = iotlb_cr_to_virt(&cr);
+		bytes = iopgsz_to_bytes(cr.cam & 3);
+
+		if ((start <= da) && (da < start + bytes)) {
+			dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
+				__func__, start, da, bytes);
+			iotlb_load_cr(obj, &cr);
+			iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
+		}
+	}
+	clk_disable(obj->clk);
+
+	if (i == obj->nr_tlb_entries)
+		dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
+}
+EXPORT_SYMBOL_GPL(flush_iotlb_page);
+
+/**
+ * flush_iotlb_range - Clear an iommu tlb entries
+ * @obj:	target iommu
+ * @start:	iommu device virtual address(start)
+ * @end:	iommu device virtual address(end)
+ *
+ * Clear an iommu tlb entry which includes 'da' address.
+ **/
+void flush_iotlb_range(struct iommu *obj, u32 start, u32 end)
+{
+	u32 da = start;
+
+	while (da < end) {
+		flush_iotlb_page(obj, da);
+		/* FIXME: Optimize for multiple page size */
+		da += IOPTE_SIZE;
+	}
+}
+EXPORT_SYMBOL_GPL(flush_iotlb_range);
+
+/**
+ * flush_iotlb_all - Clear all iommu tlb entries
+ * @obj:	target iommu
+ **/
+void flush_iotlb_all(struct iommu *obj)
+{
+	struct iotlb_lock l;
+
+	clk_enable(obj->clk);
+
+	l.base = 0;
+	l.vict = 0;
+	iotlb_lock_set(obj, &l);
+
+	iommu_write_reg(obj, 1, MMU_GFLUSH);
+
+	clk_disable(obj->clk);
+}
+EXPORT_SYMBOL_GPL(flush_iotlb_all);
+
+#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
+
+ssize_t iommu_dump_ctx(struct iommu *obj, char *buf)
+{
+	ssize_t bytes;
+
+	if (!obj || !buf)
+		return -EINVAL;
+
+	clk_enable(obj->clk);
+
+	bytes = arch_iommu->dump_ctx(obj, buf);
+
+	clk_disable(obj->clk);
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(iommu_dump_ctx);
+
+static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs)
+{
+	int i;
+	struct iotlb_lock saved, l;
+	struct cr_regs *p = crs;
+
+	clk_enable(obj->clk);
+
+	iotlb_lock_get(obj, &saved);
+	memcpy(&l, &saved, sizeof(saved));
+
+	for (i = 0; i < obj->nr_tlb_entries; i++) {
+		struct cr_regs tmp;
+
+		iotlb_lock_get(obj, &l);
+		l.vict = i;
+		iotlb_lock_set(obj, &l);
+		iotlb_read_cr(obj, &tmp);
+		if (!iotlb_cr_valid(&tmp))
+			continue;
+
+		*p++ = tmp;
+	}
+	iotlb_lock_set(obj, &saved);
+	clk_disable(obj->clk);
+
+	return  p - crs;
+}
+
+/**
+ * dump_tlb_entries - dump cr arrays to given buffer
+ * @obj:	target iommu
+ * @buf:	output buffer
+ **/
+size_t dump_tlb_entries(struct iommu *obj, char *buf)
+{
+	int i, n;
+	struct cr_regs *cr;
+	char *p = buf;
+
+	cr = kcalloc(obj->nr_tlb_entries, sizeof(*cr), GFP_KERNEL);
+	if (!cr)
+		return 0;
+
+	n = __dump_tlb_entries(obj, cr);
+	for (i = 0; i < n; i++)
+		p += iotlb_dump_cr(obj, cr + i, p);
+	kfree(cr);
+
+	return p - buf;
+}
+EXPORT_SYMBOL_GPL(dump_tlb_entries);
+
+int foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
+{
+	return driver_for_each_device(&omap_iommu_driver.driver,
+				      NULL, data, fn);
+}
+EXPORT_SYMBOL_GPL(foreach_iommu_device);
+
+#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */
+
+/*
+ *	H/W pagetable operations
+ */
+static void flush_iopgd_range(u32 *first, u32 *last)
+{
+	/* FIXME: L2 cache should be taken care of if it exists */
+	do {
+		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pgd"
+		    : : "r" (first));
+		first += L1_CACHE_BYTES / sizeof(*first);
+	} while (first <= last);
+}
+
+static void flush_iopte_range(u32 *first, u32 *last)
+{
+	/* FIXME: L2 cache should be taken care of if it exists */
+	do {
+		asm("mcr	p15, 0, %0, c7, c10, 1 @ flush_pte"
+		    : : "r" (first));
+		first += L1_CACHE_BYTES / sizeof(*first);
+	} while (first <= last);
+}
+
+static void iopte_free(u32 *iopte)
+{
+	/* Note: freed iopte's must be clean ready for re-use */
+	kmem_cache_free(iopte_cachep, iopte);
+}
+
+static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
+{
+	u32 *iopte;
+
+	/* a table has already existed */
+	if (*iopgd)
+		goto pte_ready;
+
+	/*
+	 * do the allocation outside the page table lock
+	 */
+	spin_unlock(&obj->page_table_lock);
+	iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
+	spin_lock(&obj->page_table_lock);
+
+	if (!*iopgd) {
+		if (!iopte)
+			return ERR_PTR(-ENOMEM);
+
+		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
+		flush_iopgd_range(iopgd, iopgd);
+
+		dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
+	} else {
+		/* We raced, free the reduniovant table */
+		iopte_free(iopte);
+	}
+
+pte_ready:
+	iopte = iopte_offset(iopgd, da);
+
+	dev_vdbg(obj->dev,
+		 "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
+		 __func__, da, iopgd, *iopgd, iopte, *iopte);
+
+	return iopte;
+}
+
+static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+
+	*iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
+	flush_iopgd_range(iopgd, iopgd);
+	return 0;
+}
+
+static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	int i;
+
+	for (i = 0; i < 16; i++)
+		*(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
+	flush_iopgd_range(iopgd, iopgd + 15);
+	return 0;
+}
+
+static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	u32 *iopte = iopte_alloc(obj, iopgd, da);
+
+	if (IS_ERR(iopte))
+		return PTR_ERR(iopte);
+
+	*iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
+	flush_iopte_range(iopte, iopte);
+
+	dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
+		 __func__, da, pa, iopte, *iopte);
+
+	return 0;
+}
+
+static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
+{
+	u32 *iopgd = iopgd_offset(obj, da);
+	u32 *iopte = iopte_alloc(obj, iopgd, da);
+	int i;
+
+	if (IS_ERR(iopte))
+		return PTR_ERR(iopte);
+
+	for (i = 0; i < 16; i++)
+		*(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
+	flush_iopte_range(iopte, iopte + 15);
+	return 0;
+}
+
+static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
+{
+	int (*fn)(struct iommu *, u32, u32, u32);
+	u32 prot;
+	int err;
+
+	if (!obj || !e)
+		return -EINVAL;
+
+	switch (e->pgsz) {
+	case MMU_CAM_PGSZ_16M:
+		fn = iopgd_alloc_super;
+		break;
+	case MMU_CAM_PGSZ_1M:
+		fn = iopgd_alloc_section;
+		break;
+	case MMU_CAM_PGSZ_64K:
+		fn = iopte_alloc_large;
+		break;
+	case MMU_CAM_PGSZ_4K:
+		fn = iopte_alloc_page;
+		break;
+	default:
+		fn = NULL;
+		BUG();
+		break;
+	}
+
+	prot = get_iopte_attr(e);
+
+	spin_lock(&obj->page_table_lock);
+	err = fn(obj, e->da, e->pa, prot);
+	spin_unlock(&obj->page_table_lock);
+
+	return err;
+}
+
+/**
+ * iopgtable_store_entry - Make an iommu pte entry
+ * @obj:	target iommu
+ * @e:		an iommu tlb entry info
+ **/
+int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
+{
+	int err;
+
+	flush_iotlb_page(obj, e->da);
+	err = iopgtable_store_entry_core(obj, e);
+#ifdef PREFETCH_IOTLB
+	if (!err)
+		load_iotlb_entry(obj, e);
+#endif
+	return err;
+}
+EXPORT_SYMBOL_GPL(iopgtable_store_entry);
+
+/**
+ * iopgtable_lookup_entry - Lookup an iommu pte entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ * @ppgd:	iommu pgd entry pointer to be returned
+ * @ppte:	iommu pte entry pointer to be returned
+ **/
+void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
+{
+	u32 *iopgd, *iopte = NULL;
+
+	iopgd = iopgd_offset(obj, da);
+	if (!*iopgd)
+		goto out;
+
+	if (*iopgd & IOPGD_TABLE)
+		iopte = iopte_offset(iopgd, da);
+out:
+	*ppgd = iopgd;
+	*ppte = iopte;
+}
+EXPORT_SYMBOL_GPL(iopgtable_lookup_entry);
+
+static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
+{
+	size_t bytes;
+	u32 *iopgd = iopgd_offset(obj, da);
+	int nent = 1;
+
+	if (!*iopgd)
+		return 0;
+
+	if (*iopgd & IOPGD_TABLE) {
+		int i;
+		u32 *iopte = iopte_offset(iopgd, da);
+
+		bytes = IOPTE_SIZE;
+		if (*iopte & IOPTE_LARGE) {
+			nent *= 16;
+			/* rewind to the 1st entry */
+			iopte = (u32 *)((u32)iopte & IOLARGE_MASK);
+		}
+		bytes *= nent;
+		memset(iopte, 0, nent * sizeof(*iopte));
+		flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
+
+		/*
+		 * do table walk to check if this table is necessary or not
+		 */
+		iopte = iopte_offset(iopgd, 0);
+		for (i = 0; i < PTRS_PER_IOPTE; i++)
+			if (iopte[i])
+				goto out;
+
+		iopte_free(iopte);
+		nent = 1; /* for the next L1 entry */
+	} else {
+		bytes = IOPGD_SIZE;
+		if (*iopgd & IOPGD_SUPER) {
+			nent *= 16;
+			/* rewind to the 1st entry */
+			iopgd = (u32 *)((u32)iopgd & IOSUPER_MASK);
+		}
+		bytes *= nent;
+	}
+	memset(iopgd, 0, nent * sizeof(*iopgd));
+	flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
+out:
+	return bytes;
+}
+
+/**
+ * iopgtable_clear_entry - Remove an iommu pte entry
+ * @obj:	target iommu
+ * @da:		iommu device virtual address
+ **/
+size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
+{
+	size_t bytes;
+
+	spin_lock(&obj->page_table_lock);
+
+	bytes = iopgtable_clear_entry_core(obj, da);
+	flush_iotlb_page(obj, da);
+
+	spin_unlock(&obj->page_table_lock);
+
+	return bytes;
+}
+EXPORT_SYMBOL_GPL(iopgtable_clear_entry);
+
+static void iopgtable_clear_entry_all(struct iommu *obj)
+{
+	int i;
+
+	spin_lock(&obj->page_table_lock);
+
+	for (i = 0; i < PTRS_PER_IOPGD; i++) {
+		u32 da;
+		u32 *iopgd;
+
+		da = i << IOPGD_SHIFT;
+		iopgd = iopgd_offset(obj, da);
+
+		if (!*iopgd)
+			continue;
+
+		if (*iopgd & IOPGD_TABLE)
+			iopte_free(iopte_offset(iopgd, 0));
+
+		*iopgd = 0;
+		flush_iopgd_range(iopgd, iopgd);
+	}
+
+	flush_iotlb_all(obj);
+
+	spin_unlock(&obj->page_table_lock);
+}
+
+/*
+ *	Device IOMMU generic operations
+ */
+static irqreturn_t iommu_fault_handler(int irq, void *data)
+{
+	u32 stat, da;
+	u32 *iopgd, *iopte;
+	int err = -EIO;
+	struct iommu *obj = data;
+
+	if (!obj->refcount)
+		return IRQ_NONE;
+
+	/* Dynamic loading TLB or PTE */
+	if (obj->isr)
+		err = obj->isr(obj);
+
+	if (!err)
+		return IRQ_HANDLED;
+
+	clk_enable(obj->clk);
+	stat = iommu_report_fault(obj, &da);
+	clk_disable(obj->clk);
+	if (!stat)
+		return IRQ_HANDLED;
+
+	iopgd = iopgd_offset(obj, da);
+
+	if (!(*iopgd & IOPGD_TABLE)) {
+		dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__,
+			da, iopgd, *iopgd);
+		return IRQ_NONE;
+	}
+
+	iopte = iopte_offset(iopgd, da);
+
+	dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
+		__func__, da, iopgd, *iopgd, iopte, *iopte);
+
+	return IRQ_NONE;
+}
+
+static int device_match_by_alias(struct device *dev, void *data)
+{
+	struct iommu *obj = to_iommu(dev);
+	const char *name = data;
+
+	pr_debug("%s: %s %s\n", __func__, obj->name, name);
+
+	return strcmp(obj->name, name) == 0;
+}
+
+/**
+ * iommu_get - Get iommu handler
+ * @name:	target iommu name
+ **/
+struct iommu *iommu_get(const char *name)
+{
+	int err = -ENOMEM;
+	struct device *dev;
+	struct iommu *obj;
+
+	dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
+				 device_match_by_alias);
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	obj = to_iommu(dev);
+
+	mutex_lock(&obj->iommu_lock);
+
+	if (obj->refcount++ == 0) {
+		err = iommu_enable(obj);
+		if (err)
+			goto err_enable;
+		flush_iotlb_all(obj);
+	}
+
+	if (!try_module_get(obj->owner))
+		goto err_module;
+
+	mutex_unlock(&obj->iommu_lock);
+
+	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
+	return obj;
+
+err_module:
+	if (obj->refcount == 1)
+		iommu_disable(obj);
+err_enable:
+	obj->refcount--;
+	mutex_unlock(&obj->iommu_lock);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(iommu_get);
+
+/**
+ * iommu_put - Put back iommu handler
+ * @obj:	target iommu
+ **/
+void iommu_put(struct iommu *obj)
+{
+	if (!obj && IS_ERR(obj))
+		return;
+
+	mutex_lock(&obj->iommu_lock);
+
+	if (--obj->refcount == 0)
+		iommu_disable(obj);
+
+	module_put(obj->owner);
+
+	mutex_unlock(&obj->iommu_lock);
+
+	dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
+}
+EXPORT_SYMBOL_GPL(iommu_put);
+
+/*
+ *	OMAP Device MMU(IOMMU) detection
+ */
+static int __devinit omap_iommu_probe(struct platform_device *pdev)
+{
+	int err = -ENODEV;
+	void *p;
+	int irq;
+	struct iommu *obj;
+	struct resource *res;
+	struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+	if (pdev->num_resources != 2)
+		return -EINVAL;
+
+	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	obj->clk = clk_get(&pdev->dev, pdata->clk_name);
+	if (IS_ERR(obj->clk))
+		goto err_clk;
+
+	obj->nr_tlb_entries = pdata->nr_tlb_entries;
+	obj->name = pdata->name;
+	obj->dev = &pdev->dev;
+	obj->ctx = (void *)obj + sizeof(*obj);
+
+	mutex_init(&obj->iommu_lock);
+	mutex_init(&obj->mmap_lock);
+	spin_lock_init(&obj->page_table_lock);
+	INIT_LIST_HEAD(&obj->mmap);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto err_mem;
+	}
+	obj->regbase = ioremap(res->start, resource_size(res));
+	if (!obj->regbase) {
+		err = -ENOMEM;
+		goto err_mem;
+	}
+
+	res = request_mem_region(res->start, resource_size(res),
+				 dev_name(&pdev->dev));
+	if (!res) {
+		err = -EIO;
+		goto err_mem;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		err = -ENODEV;
+		goto err_irq;
+	}
+	err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
+			  dev_name(&pdev->dev), obj);
+	if (err < 0)
+		goto err_irq;
+	platform_set_drvdata(pdev, obj);
+
+	p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE));
+	if (!p) {
+		err = -ENOMEM;
+		goto err_pgd;
+	}
+	memset(p, 0, IOPGD_TABLE_SIZE);
+	clean_dcache_area(p, IOPGD_TABLE_SIZE);
+	obj->iopgd = p;
+
+	BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE));
+
+	dev_info(&pdev->dev, "%s registered\n", obj->name);
+	return 0;
+
+err_pgd:
+	free_irq(irq, obj);
+err_irq:
+	release_mem_region(res->start, resource_size(res));
+	iounmap(obj->regbase);
+err_mem:
+	clk_put(obj->clk);
+err_clk:
+	kfree(obj);
+	return err;
+}
+
+static int __devexit omap_iommu_remove(struct platform_device *pdev)
+{
+	int irq;
+	struct resource *res;
+	struct iommu *obj = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	iopgtable_clear_entry_all(obj);
+	free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, obj);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+	iounmap(obj->regbase);
+
+	clk_put(obj->clk);
+	dev_info(&pdev->dev, "%s removed\n", obj->name);
+	kfree(obj);
+	return 0;
+}
+
+static struct platform_driver omap_iommu_driver = {
+	.probe	= omap_iommu_probe,
+	.remove	= __devexit_p(omap_iommu_remove),
+	.driver	= {
+		.name	= "omap-iommu",
+	},
+};
+
+static void iopte_cachep_ctor(void *iopte)
+{
+	clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
+}
+
+static int __init omap_iommu_init(void)
+{
+	struct kmem_cache *p;
+	const unsigned long flags = SLAB_HWCACHE_ALIGN;
+	size_t align = 1 << 10; /* L2 pagetable alignement */
+
+	p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
+			      iopte_cachep_ctor);
+	if (!p)
+		return -ENOMEM;
+	iopte_cachep = p;
+
+	return platform_driver_register(&omap_iommu_driver);
+}
+module_init(omap_iommu_init);
+
+static void __exit omap_iommu_exit(void)
+{
+	kmem_cache_destroy(iopte_cachep);
+
+	platform_driver_unregister(&omap_iommu_driver);
+}
+module_exit(omap_iommu_exit);
+
+MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives");
+MODULE_ALIAS("platform:omap-iommu");
+MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/iopgtable.h linux-libre-2.6.31-gnu/arch/arm/plat-omap/iopgtable.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/iopgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/iopgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * omap iommu: pagetable definitions
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_OMAP_IOMMU_H
+#define __PLAT_OMAP_IOMMU_H
+
+#define IOPGD_SHIFT		20
+#define IOPGD_SIZE		(1 << IOPGD_SHIFT)
+#define IOPGD_MASK		(~(IOPGD_SIZE - 1))
+#define IOSECTION_MASK		IOPGD_MASK
+#define PTRS_PER_IOPGD		(1 << (32 - IOPGD_SHIFT))
+#define IOPGD_TABLE_SIZE	(PTRS_PER_IOPGD * sizeof(u32))
+
+#define IOSUPER_SIZE		(IOPGD_SIZE << 4)
+#define IOSUPER_MASK		(~(IOSUPER_SIZE - 1))
+
+#define IOPTE_SHIFT		12
+#define IOPTE_SIZE		(1 << IOPTE_SHIFT)
+#define IOPTE_MASK		(~(IOPTE_SIZE - 1))
+#define IOPAGE_MASK		IOPTE_MASK
+#define PTRS_PER_IOPTE		(1 << (IOPGD_SHIFT - IOPTE_SHIFT))
+#define IOPTE_TABLE_SIZE	(PTRS_PER_IOPTE * sizeof(u32))
+
+#define IOLARGE_SIZE		(IOPTE_SIZE << 4)
+#define IOLARGE_MASK		(~(IOLARGE_SIZE - 1))
+
+#define IOPGD_TABLE		(1 << 0)
+#define IOPGD_SECTION		(2 << 0)
+#define IOPGD_SUPER		(1 << 18 | 2 << 0)
+
+#define IOPTE_SMALL		(2 << 0)
+#define IOPTE_LARGE		(1 << 0)
+
+#define iopgd_index(da)		(((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
+#define iopgd_offset(obj, da)	((obj)->iopgd + iopgd_index(da))
+
+#define iopte_paddr(iopgd)	(*iopgd & ~((1 << 10) - 1))
+#define iopte_vaddr(iopgd)	((u32 *)phys_to_virt(iopte_paddr(iopgd)))
+
+#define iopte_index(da)		(((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
+#define iopte_offset(iopgd, da)	(iopte_vaddr(iopgd) + iopte_index(da))
+
+static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
+				   u32 flags)
+{
+	memset(e, 0, sizeof(*e));
+
+	e->da		= da;
+	e->pa		= pa;
+	e->valid	= 1;
+	/* FIXME: add OMAP1 support */
+	e->pgsz		= flags & MMU_CAM_PGSZ_MASK;
+	e->endian	= flags & MMU_RAM_ENDIAN_MASK;
+	e->elsz		= flags & MMU_RAM_ELSZ_MASK;
+	e->mixed	= flags & MMU_RAM_MIXED_MASK;
+
+	return iopgsz_to_bytes(e->pgsz);
+}
+
+#define to_iommu(dev)							\
+	(struct iommu *)platform_get_drvdata(to_platform_device(dev))
+
+#endif /* __PLAT_OMAP_IOMMU_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/iovmm.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/iovmm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/iovmm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/iovmm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,896 @@
+/*
+ * omap iommu: simple virtual address space management
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/scatterlist.h>
+
+#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
+#include <mach/iommu.h>
+#include <mach/iovmm.h>
+
+#include "iopgtable.h"
+
+/*
+ * A device driver needs to create address mappings between:
+ *
+ * - iommu/device address
+ * - physical address
+ * - mpu virtual address
+ *
+ * There are 4 possible patterns for them:
+ *
+ *    |iova/			  mapping		iommu_		page
+ *    | da	pa	va	(d)-(p)-(v)		function	type
+ *  ---------------------------------------------------------------------------
+ *  1 | c	c	c	 1 - 1 - 1	  _kmap() / _kunmap()	s
+ *  2 | c	c,a	c	 1 - 1 - 1	_kmalloc()/ _kfree()	s
+ *  3 | c	d	c	 1 - n - 1	  _vmap() / _vunmap()	s
+ *  4 | c	d,a	c	 1 - n - 1	_vmalloc()/ _vfree()	n*
+ *
+ *
+ *	'iova':	device iommu virtual address
+ *	'da':	alias of 'iova'
+ *	'pa':	physical address
+ *	'va':	mpu virtual address
+ *
+ *	'c':	contiguous memory area
+ *	'd':	dicontiguous memory area
+ *	'a':	anonymous memory allocation
+ *	'()':	optional feature
+ *
+ *	'n':	a normal page(4KB) size is used.
+ *	's':	multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
+ *
+ *	'*':	not yet, but feasible.
+ */
+
+static struct kmem_cache *iovm_area_cachep;
+
+/* return total bytes of sg buffers */
+static size_t sgtable_len(const struct sg_table *sgt)
+{
+	unsigned int i, total = 0;
+	struct scatterlist *sg;
+
+	if (!sgt)
+		return 0;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+
+		bytes = sg_dma_len(sg);
+
+		if (!iopgsz_ok(bytes)) {
+			pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
+			       __func__, i, bytes);
+			return 0;
+		}
+
+		total += bytes;
+	}
+
+	return total;
+}
+#define sgtable_ok(x)	(!!sgtable_len(x))
+
+/*
+ * calculate the optimal number sg elements from total bytes based on
+ * iommu superpages
+ */
+static unsigned int sgtable_nents(size_t bytes)
+{
+	int i;
+	unsigned int nr_entries;
+	const unsigned long pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
+
+	if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
+		pr_err("%s: wrong size %08x\n", __func__, bytes);
+		return 0;
+	}
+
+	nr_entries = 0;
+	for (i = 0; i < ARRAY_SIZE(pagesize); i++) {
+		if (bytes >= pagesize[i]) {
+			nr_entries += (bytes / pagesize[i]);
+			bytes %= pagesize[i];
+		}
+	}
+	BUG_ON(bytes);
+
+	return nr_entries;
+}
+
+/* allocate and initialize sg_table header(a kind of 'superblock') */
+static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags)
+{
+	unsigned int nr_entries;
+	int err;
+	struct sg_table *sgt;
+
+	if (!bytes)
+		return ERR_PTR(-EINVAL);
+
+	if (!IS_ALIGNED(bytes, PAGE_SIZE))
+		return ERR_PTR(-EINVAL);
+
+	/* FIXME: IOVMF_DA_FIXED should support 'superpages' */
+	if ((flags & IOVMF_LINEAR) && (flags & IOVMF_DA_ANON)) {
+		nr_entries = sgtable_nents(bytes);
+		if (!nr_entries)
+			return ERR_PTR(-EINVAL);
+	} else
+		nr_entries =  bytes / PAGE_SIZE;
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return ERR_PTR(-ENOMEM);
+
+	err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
+	if (err)
+		return ERR_PTR(err);
+
+	pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
+
+	return sgt;
+}
+
+/* free sg_table header(a kind of superblock) */
+static void sgtable_free(struct sg_table *sgt)
+{
+	if (!sgt)
+		return;
+
+	sg_free_table(sgt);
+	kfree(sgt);
+
+	pr_debug("%s: sgt:%p\n", __func__, sgt);
+}
+
+/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
+static void *vmap_sg(const struct sg_table *sgt)
+{
+	u32 va;
+	size_t total;
+	unsigned int i;
+	struct scatterlist *sg;
+	struct vm_struct *new;
+	const struct mem_type *mtype;
+
+	mtype = get_mem_type(MT_DEVICE);
+	if (!mtype)
+		return ERR_PTR(-EINVAL);
+
+	total = sgtable_len(sgt);
+	if (!total)
+		return ERR_PTR(-EINVAL);
+
+	new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+	va = (u32)new->addr;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+		u32 pa;
+		int err;
+
+		pa = sg_phys(sg);
+		bytes = sg_dma_len(sg);
+
+		BUG_ON(bytes != PAGE_SIZE);
+
+		err = ioremap_page(va,  pa, mtype);
+		if (err)
+			goto err_out;
+
+		va += bytes;
+	}
+
+	flush_cache_vmap(new->addr, total);
+	return new->addr;
+
+err_out:
+	WARN_ON(1); /* FIXME: cleanup some mpu mappings */
+	vunmap(new->addr);
+	return ERR_PTR(-EAGAIN);
+}
+
+static inline void vunmap_sg(const void *va)
+{
+	vunmap(va);
+}
+
+static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da)
+{
+	struct iovm_struct *tmp;
+
+	list_for_each_entry(tmp, &obj->mmap, list) {
+		if ((da >= tmp->da_start) && (da < tmp->da_end)) {
+			size_t len;
+
+			len = tmp->da_end - tmp->da_start;
+
+			dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
+				__func__, tmp->da_start, da, tmp->da_end, len,
+				tmp->flags);
+
+			return tmp;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * find_iovm_area  -  find iovma which includes @da
+ * @da:		iommu device virtual address
+ *
+ * Find the existing iovma starting at @da
+ */
+struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da)
+{
+	struct iovm_struct *area;
+
+	mutex_lock(&obj->mmap_lock);
+	area = __find_iovm_area(obj, da);
+	mutex_unlock(&obj->mmap_lock);
+
+	return area;
+}
+EXPORT_SYMBOL_GPL(find_iovm_area);
+
+/*
+ * This finds the hole(area) which fits the requested address and len
+ * in iovmas mmap, and returns the new allocated iovma.
+ */
+static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
+					   size_t bytes, u32 flags)
+{
+	struct iovm_struct *new, *tmp;
+	u32 start, prev_end, alignement;
+
+	if (!obj || !bytes)
+		return ERR_PTR(-EINVAL);
+
+	start = da;
+	alignement = PAGE_SIZE;
+
+	if (flags & IOVMF_DA_ANON) {
+		/*
+		 * Reserve the first page for NULL
+		 */
+		start = PAGE_SIZE;
+		if (flags & IOVMF_LINEAR)
+			alignement = iopgsz_max(bytes);
+		start = roundup(start, alignement);
+	}
+
+	tmp = NULL;
+	if (list_empty(&obj->mmap))
+		goto found;
+
+	prev_end = 0;
+	list_for_each_entry(tmp, &obj->mmap, list) {
+
+		if ((prev_end <= start) && (start + bytes < tmp->da_start))
+			goto found;
+
+		if (flags & IOVMF_DA_ANON)
+			start = roundup(tmp->da_end, alignement);
+
+		prev_end = tmp->da_end;
+	}
+
+	if ((start >= prev_end) && (ULONG_MAX - start >= bytes))
+		goto found;
+
+	dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
+		__func__, da, bytes, flags);
+
+	return ERR_PTR(-EINVAL);
+
+found:
+	new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
+	if (!new)
+		return ERR_PTR(-ENOMEM);
+
+	new->iommu = obj;
+	new->da_start = start;
+	new->da_end = start + bytes;
+	new->flags = flags;
+
+	/*
+	 * keep ascending order of iovmas
+	 */
+	if (tmp)
+		list_add_tail(&new->list, &tmp->list);
+	else
+		list_add(&new->list, &obj->mmap);
+
+	dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
+		__func__, new->da_start, start, new->da_end, bytes, flags);
+
+	return new;
+}
+
+static void free_iovm_area(struct iommu *obj, struct iovm_struct *area)
+{
+	size_t bytes;
+
+	BUG_ON(!obj || !area);
+
+	bytes = area->da_end - area->da_start;
+
+	dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
+		__func__, area->da_start, area->da_end, bytes, area->flags);
+
+	list_del(&area->list);
+	kmem_cache_free(iovm_area_cachep, area);
+}
+
+/**
+ * da_to_va - convert (d) to (v)
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ * @va:		mpu virtual address
+ *
+ * Returns mpu virtual addr which corresponds to a given device virtual addr
+ */
+void *da_to_va(struct iommu *obj, u32 da)
+{
+	void *va = NULL;
+	struct iovm_struct *area;
+
+	mutex_lock(&obj->mmap_lock);
+
+	area = __find_iovm_area(obj, da);
+	if (!area) {
+		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
+		goto out;
+	}
+	va = area->va;
+	mutex_unlock(&obj->mmap_lock);
+out:
+	return va;
+}
+EXPORT_SYMBOL_GPL(da_to_va);
+
+static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
+{
+	unsigned int i;
+	struct scatterlist *sg;
+	void *va = _va;
+	void *va_end;
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		struct page *pg;
+		const size_t bytes = PAGE_SIZE;
+
+		/*
+		 * iommu 'superpage' isn't supported with 'iommu_vmalloc()'
+		 */
+		pg = vmalloc_to_page(va);
+		BUG_ON(!pg);
+		sg_set_page(sg, pg, bytes, 0);
+
+		va += bytes;
+	}
+
+	va_end = _va + PAGE_SIZE * i;
+	flush_cache_vmap(_va, va_end);
+}
+
+static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
+{
+	/*
+	 * Actually this is not necessary at all, just exists for
+	 * consistency of the code readibility.
+	 */
+	BUG_ON(!sgt);
+}
+
+static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len)
+{
+	unsigned int i;
+	struct scatterlist *sg;
+	void *va;
+
+	va = phys_to_virt(pa);
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		size_t bytes;
+
+		bytes = iopgsz_max(len);
+
+		BUG_ON(!iopgsz_ok(bytes));
+
+		sg_set_buf(sg, phys_to_virt(pa), bytes);
+		/*
+		 * 'pa' is cotinuous(linear).
+		 */
+		pa += bytes;
+		len -= bytes;
+	}
+	BUG_ON(len);
+
+	clean_dcache_area(va, len);
+}
+
+static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
+{
+	/*
+	 * Actually this is not necessary at all, just exists for
+	 * consistency of the code readibility
+	 */
+	BUG_ON(!sgt);
+}
+
+/* create 'da' <-> 'pa' mapping from 'sgt' */
+static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
+			 const struct sg_table *sgt, u32 flags)
+{
+	int err;
+	unsigned int i, j;
+	struct scatterlist *sg;
+	u32 da = new->da_start;
+
+	if (!obj || !new || !sgt)
+		return -EINVAL;
+
+	BUG_ON(!sgtable_ok(sgt));
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		u32 pa;
+		int pgsz;
+		size_t bytes;
+		struct iotlb_entry e;
+
+		pa = sg_phys(sg);
+		bytes = sg_dma_len(sg);
+
+		flags &= ~IOVMF_PGSZ_MASK;
+		pgsz = bytes_to_iopgsz(bytes);
+		if (pgsz < 0)
+			goto err_out;
+		flags |= pgsz;
+
+		pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
+			 i, da, pa, bytes);
+
+		iotlb_init_entry(&e, da, pa, flags);
+		err = iopgtable_store_entry(obj, &e);
+		if (err)
+			goto err_out;
+
+		da += bytes;
+	}
+	return 0;
+
+err_out:
+	da = new->da_start;
+
+	for_each_sg(sgt->sgl, sg, i, j) {
+		size_t bytes;
+
+		bytes = iopgtable_clear_entry(obj, da);
+
+		BUG_ON(!iopgsz_ok(bytes));
+
+		da += bytes;
+	}
+	return err;
+}
+
+/* release 'da' <-> 'pa' mapping */
+static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
+{
+	u32 start;
+	size_t total = area->da_end - area->da_start;
+
+	BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
+
+	start = area->da_start;
+	while (total > 0) {
+		size_t bytes;
+
+		bytes = iopgtable_clear_entry(obj, start);
+		if (bytes == 0)
+			bytes = PAGE_SIZE;
+		else
+			dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
+				__func__, start, bytes, area->flags);
+
+		BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
+
+		total -= bytes;
+		start += bytes;
+	}
+	BUG_ON(total);
+}
+
+/* template function for all unmapping */
+static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
+				      void (*fn)(const void *), u32 flags)
+{
+	struct sg_table *sgt = NULL;
+	struct iovm_struct *area;
+
+	if (!IS_ALIGNED(da, PAGE_SIZE)) {
+		dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
+		return NULL;
+	}
+
+	mutex_lock(&obj->mmap_lock);
+
+	area = __find_iovm_area(obj, da);
+	if (!area) {
+		dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
+		goto out;
+	}
+
+	if ((area->flags & flags) != flags) {
+		dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
+			area->flags);
+		goto out;
+	}
+	sgt = (struct sg_table *)area->sgt;
+
+	unmap_iovm_area(obj, area);
+
+	fn(area->va);
+
+	dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
+		area->da_start, da, area->da_end,
+		area->da_end - area->da_start, area->flags);
+
+	free_iovm_area(obj, area);
+out:
+	mutex_unlock(&obj->mmap_lock);
+
+	return sgt;
+}
+
+static u32 map_iommu_region(struct iommu *obj, u32 da,
+	      const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
+{
+	int err = -ENOMEM;
+	struct iovm_struct *new;
+
+	mutex_lock(&obj->mmap_lock);
+
+	new = alloc_iovm_area(obj, da, bytes, flags);
+	if (IS_ERR(new)) {
+		err = PTR_ERR(new);
+		goto err_alloc_iovma;
+	}
+	new->va = va;
+	new->sgt = sgt;
+
+	if (map_iovm_area(obj, new, sgt, new->flags))
+		goto err_map;
+
+	mutex_unlock(&obj->mmap_lock);
+
+	dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
+		__func__, new->da_start, bytes, new->flags, va);
+
+	return new->da_start;
+
+err_map:
+	free_iovm_area(obj, new);
+err_alloc_iovma:
+	mutex_unlock(&obj->mmap_lock);
+	return err;
+}
+
+static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
+		 const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
+{
+	return map_iommu_region(obj, da, sgt, va, bytes, flags);
+}
+
+/**
+ * iommu_vmap  -  (d)-(p)-(v) address mapper
+ * @obj:	objective iommu
+ * @sgt:	address of scatter gather table
+ * @flags:	iovma and page property
+ *
+ * Creates 1-n-1 mapping with given @sgt and returns @da.
+ * All @sgt element must be io page size aligned.
+ */
+u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
+		 u32 flags)
+{
+	size_t bytes;
+	void *va;
+
+	if (!obj || !obj->dev || !sgt)
+		return -EINVAL;
+
+	bytes = sgtable_len(sgt);
+	if (!bytes)
+		return -EINVAL;
+	bytes = PAGE_ALIGN(bytes);
+
+	va = vmap_sg(sgt);
+	if (IS_ERR(va))
+		return PTR_ERR(va);
+
+	flags &= IOVMF_HW_MASK;
+	flags |= IOVMF_DISCONT;
+	flags |= IOVMF_MMIO;
+	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
+
+	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		vunmap_sg(va);
+
+	return da;
+}
+EXPORT_SYMBOL_GPL(iommu_vmap);
+
+/**
+ * iommu_vunmap  -  release virtual mapping obtained by 'iommu_vmap()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Free the iommu virtually contiguous memory area starting at
+ * @da, which was returned by 'iommu_vmap()'.
+ */
+struct sg_table *iommu_vunmap(struct iommu *obj, u32 da)
+{
+	struct sg_table *sgt;
+	/*
+	 * 'sgt' is allocated before 'iommu_vmalloc()' is called.
+	 * Just returns 'sgt' to the caller to free
+	 */
+	sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	return sgt;
+}
+EXPORT_SYMBOL_GPL(iommu_vunmap);
+
+/**
+ * iommu_vmalloc  -  (d)-(p)-(v) address allocator and mapper
+ * @obj:	objective iommu
+ * @da:		contiguous iommu virtual memory
+ * @bytes:	allocation size
+ * @flags:	iovma and page property
+ *
+ * Allocate @bytes linearly and creates 1-n-1 mapping and returns
+ * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
+ */
+u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
+{
+	void *va;
+	struct sg_table *sgt;
+
+	if (!obj || !obj->dev || !bytes)
+		return -EINVAL;
+
+	bytes = PAGE_ALIGN(bytes);
+
+	va = vmalloc(bytes);
+	if (!va)
+		return -ENOMEM;
+
+	sgt = sgtable_alloc(bytes, flags);
+	if (IS_ERR(sgt)) {
+		da = PTR_ERR(sgt);
+		goto err_sgt_alloc;
+	}
+	sgtable_fill_vmalloc(sgt, va);
+
+	flags &= IOVMF_HW_MASK;
+	flags |= IOVMF_DISCONT;
+	flags |= IOVMF_ALLOC;
+	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
+
+	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		goto err_iommu_vmap;
+
+	return da;
+
+err_iommu_vmap:
+	sgtable_drain_vmalloc(sgt);
+	sgtable_free(sgt);
+err_sgt_alloc:
+	vfree(va);
+	return da;
+}
+EXPORT_SYMBOL_GPL(iommu_vmalloc);
+
+/**
+ * iommu_vfree  -  release memory allocated by 'iommu_vmalloc()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Frees the iommu virtually continuous memory area starting at
+ * @da, as obtained from 'iommu_vmalloc()'.
+ */
+void iommu_vfree(struct iommu *obj, const u32 da)
+{
+	struct sg_table *sgt;
+
+	sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	sgtable_free(sgt);
+}
+EXPORT_SYMBOL_GPL(iommu_vfree);
+
+static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
+			  size_t bytes, u32 flags)
+{
+	struct sg_table *sgt;
+
+	sgt = sgtable_alloc(bytes, flags);
+	if (IS_ERR(sgt))
+		return PTR_ERR(sgt);
+
+	sgtable_fill_kmalloc(sgt, pa, bytes);
+
+	da = map_iommu_region(obj, da, sgt, va, bytes, flags);
+	if (IS_ERR_VALUE(da)) {
+		sgtable_drain_kmalloc(sgt);
+		sgtable_free(sgt);
+	}
+
+	return da;
+}
+
+/**
+ * iommu_kmap  -  (d)-(p)-(v) address mapper
+ * @obj:	objective iommu
+ * @da:		contiguous iommu virtual memory
+ * @pa:		contiguous physical memory
+ * @flags:	iovma and page property
+ *
+ * Creates 1-1-1 mapping and returns @da again, which can be
+ * adjusted if 'IOVMF_DA_ANON' is set.
+ */
+u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
+		 u32 flags)
+{
+	void *va;
+
+	if (!obj || !obj->dev || !bytes)
+		return -EINVAL;
+
+	bytes = PAGE_ALIGN(bytes);
+
+	va = ioremap(pa, bytes);
+	if (!va)
+		return -ENOMEM;
+
+	flags &= IOVMF_HW_MASK;
+	flags |= IOVMF_LINEAR;
+	flags |= IOVMF_MMIO;
+	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
+
+	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		iounmap(va);
+
+	return da;
+}
+EXPORT_SYMBOL_GPL(iommu_kmap);
+
+/**
+ * iommu_kunmap  -  release virtual mapping obtained by 'iommu_kmap()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Frees the iommu virtually contiguous memory area starting at
+ * @da, which was passed to and was returned by'iommu_kmap()'.
+ */
+void iommu_kunmap(struct iommu *obj, u32 da)
+{
+	struct sg_table *sgt;
+	typedef void (*func_t)(const void *);
+
+	sgt = unmap_vm_area(obj, da, (func_t)__iounmap,
+			    IOVMF_LINEAR | IOVMF_MMIO);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	sgtable_free(sgt);
+}
+EXPORT_SYMBOL_GPL(iommu_kunmap);
+
+/**
+ * iommu_kmalloc  -  (d)-(p)-(v) address allocator and mapper
+ * @obj:	objective iommu
+ * @da:		contiguous iommu virtual memory
+ * @bytes:	bytes for allocation
+ * @flags:	iovma and page property
+ *
+ * Allocate @bytes linearly and creates 1-1-1 mapping and returns
+ * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
+ */
+u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
+{
+	void *va;
+	u32 pa;
+
+	if (!obj || !obj->dev || !bytes)
+		return -EINVAL;
+
+	bytes = PAGE_ALIGN(bytes);
+
+	va = kmalloc(bytes, GFP_KERNEL | GFP_DMA);
+	if (!va)
+		return -ENOMEM;
+	pa = virt_to_phys(va);
+
+	flags &= IOVMF_HW_MASK;
+	flags |= IOVMF_LINEAR;
+	flags |= IOVMF_ALLOC;
+	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
+
+	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
+	if (IS_ERR_VALUE(da))
+		kfree(va);
+
+	return da;
+}
+EXPORT_SYMBOL_GPL(iommu_kmalloc);
+
+/**
+ * iommu_kfree  -  release virtual mapping obtained by 'iommu_kmalloc()'
+ * @obj:	objective iommu
+ * @da:		iommu device virtual address
+ *
+ * Frees the iommu virtually contiguous memory area starting at
+ * @da, which was passed to and was returned by'iommu_kmalloc()'.
+ */
+void iommu_kfree(struct iommu *obj, u32 da)
+{
+	struct sg_table *sgt;
+
+	sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC);
+	if (!sgt)
+		dev_dbg(obj->dev, "%s: No sgt\n", __func__);
+	sgtable_free(sgt);
+}
+EXPORT_SYMBOL_GPL(iommu_kfree);
+
+
+static int __init iovmm_init(void)
+{
+	const unsigned long flags = SLAB_HWCACHE_ALIGN;
+	struct kmem_cache *p;
+
+	p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
+			      flags, NULL);
+	if (!p)
+		return -ENOMEM;
+	iovm_area_cachep = p;
+
+	return 0;
+}
+module_init(iovmm_init);
+
+static void __exit iovmm_exit(void)
+{
+	kmem_cache_destroy(iovm_area_cachep);
+}
+module_exit(iovmm_exit);
+
+MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/Kconfig linux-libre-2.6.31-gnu/arch/arm/plat-omap/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,11 @@
 	select CPU_V7
 	select COMMON_CLKDEV
 
+config ARCH_OMAP4
+	bool "TI OMAP4"
+	select CPU_V7
+	select ARM_GIC
+
 endchoice
 
 comment "OMAP Feature Selections"
@@ -40,7 +45,6 @@
 config OMAP_DEBUG_POWERDOMAIN
 	bool "Emit debug messages from powerdomain layer"
 	depends on ARCH_OMAP2 || ARCH_OMAP3
-	default n
 	help
 	  Say Y here if you want to compile in powerdomain layer
 	  debugging messages for OMAP2/3.   These messages can
@@ -52,7 +56,6 @@
 config OMAP_DEBUG_CLOCKDOMAIN
 	bool "Emit debug messages from clockdomain layer"
 	depends on ARCH_OMAP2 || ARCH_OMAP3
-	default n
 	help
 	  Say Y here if you want to compile in clockdomain layer
 	  debugging messages for OMAP2/3.   These messages can
@@ -110,11 +113,13 @@
 config OMAP_MBOX_FWK
 	tristate "Mailbox framework support"
 	depends on ARCH_OMAP
-	default n
 	help
 	  Say Y here if you want to use OMAP Mailbox framework support for
 	  DSP, IVA1.0 and IVA2 in OMAP1/2/3.
 
+config OMAP_IOMMU
+	tristate
+
 choice
         prompt "System timer"
 	default OMAP_MPU_TIMER
@@ -128,13 +133,13 @@
 
 config OMAP_32K_TIMER
 	bool "Use 32KHz timer"
-	depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
+	depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX || ARCH_OMAP4
 	help
 	  Select this option if you want to enable the OMAP 32KHz timer.
 	  This timer saves power compared to the OMAP_MPU_TIMER, and has
 	  support for no tick during idle. The 32KHz timer provides less
 	  intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
-	  currently only available for OMAP16XX, 24XX and 34XX.
+	  currently only available for OMAP16XX, 24XX, 34XX and OMAP4.
 
 endchoice
 
@@ -149,7 +154,7 @@
 
 config OMAP_DM_TIMER
 	bool "Use dual-mode timer"
-	depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
+	depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX || ARCH_OMAP4
 	help
 	 Select this option if you want to use OMAP Dual-Mode timers.
 
@@ -171,7 +176,7 @@
 
 config OMAP_SERIAL_WAKE
 	bool "Enable wake-up events for serial ports"
-	depends on OMAP_MUX
+	depends on ARCH_OMAP1 && OMAP_MUX
 	default y
 	help
 	  Select this option if you want to have your system wake up
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/mailbox.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/mailbox.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/mailbox.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/mailbox.c	2009-09-09 18:13:59.000000000 -0400
@@ -147,24 +147,40 @@
 	return ret;
 }
 
+struct omap_msg_tx_data {
+	mbox_msg_t	msg;
+	void		*arg;
+};
+
+static void omap_msg_tx_end_io(struct request *rq, int error)
+{
+	kfree(rq->special);
+	__blk_put_request(rq->q, rq);
+}
+
 int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg)
 {
+	struct omap_msg_tx_data *tx_data;
 	struct request *rq;
 	struct request_queue *q = mbox->txq->queue;
-	int ret = 0;
+
+	tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
+	if (unlikely(!tx_data))
+		return -ENOMEM;
 
 	rq = blk_get_request(q, WRITE, GFP_ATOMIC);
 	if (unlikely(!rq)) {
-		ret = -ENOMEM;
-		goto fail;
+		kfree(tx_data);
+		return -ENOMEM;
 	}
 
-	rq->data = (void *)msg;
-	blk_insert_request(q, rq, 0, arg);
+	tx_data->msg = msg;
+	tx_data->arg = arg;
+	rq->end_io = omap_msg_tx_end_io;
+	blk_insert_request(q, rq, 0, tx_data);
 
 	schedule_work(&mbox->txq->work);
- fail:
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL(omap_mbox_msg_send);
 
@@ -178,22 +194,28 @@
 	struct request_queue *q = mbox->txq->queue;
 
 	while (1) {
+		struct omap_msg_tx_data *tx_data;
+
 		spin_lock(q->queue_lock);
-		rq = elv_next_request(q);
+		rq = blk_fetch_request(q);
 		spin_unlock(q->queue_lock);
 
 		if (!rq)
 			break;
 
-		ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special);
+		tx_data = rq->special;
+
+		ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg);
 		if (ret) {
 			enable_mbox_irq(mbox, IRQ_TX);
+			spin_lock(q->queue_lock);
+			blk_requeue_request(q, rq);
+			spin_unlock(q->queue_lock);
 			return;
 		}
 
 		spin_lock(q->queue_lock);
-		if (__blk_end_request(rq, 0, 0))
-			BUG();
+		__blk_end_request_all(rq, 0);
 		spin_unlock(q->queue_lock);
 	}
 }
@@ -218,16 +240,13 @@
 
 	while (1) {
 		spin_lock_irqsave(q->queue_lock, flags);
-		rq = elv_next_request(q);
+		rq = blk_fetch_request(q);
 		spin_unlock_irqrestore(q->queue_lock, flags);
 		if (!rq)
 			break;
 
-		msg = (mbox_msg_t) rq->data;
-
-		if (blk_end_request(rq, 0, 0))
-			BUG();
-
+		msg = (mbox_msg_t)rq->special;
+		blk_end_request_all(rq, 0);
 		mbox->rxq->callback((void *)msg);
 	}
 }
@@ -264,7 +283,6 @@
 			goto nomem;
 
 		msg = mbox_fifo_read(mbox);
-		rq->data = (void *)msg;
 
 		if (unlikely(mbox_seq_test(mbox, msg))) {
 			pr_info("mbox: Illegal seq bit!(%08x)\n", msg);
@@ -272,7 +290,7 @@
 				mbox->err_notify();
 		}
 
-		blk_insert_request(q, rq, 0, NULL);
+		blk_insert_request(q, rq, 0, (void *)msg);
 		if (mbox->ops->type == OMAP_MBOX_TYPE1)
 			break;
 	}
@@ -329,16 +347,15 @@
 
 	while (1) {
 		spin_lock_irqsave(q->queue_lock, flags);
-		rq = elv_next_request(q);
+		rq = blk_fetch_request(q);
 		spin_unlock_irqrestore(q->queue_lock, flags);
 
 		if (!rq)
 			break;
 
-		*p = (mbox_msg_t) rq->data;
+		*p = (mbox_msg_t)rq->special;
 
-		if (blk_end_request(rq, 0, 0))
-			BUG();
+		blk_end_request_all(rq, 0);
 
 		if (unlikely(mbox_seq_test(mbox, *p))) {
 			pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/Makefile linux-libre-2.6.31-gnu/arch/arm/plat-omap/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
+obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/mcbsp.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/mcbsp.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/mcbsp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/mcbsp.c	2009-09-09 18:13:59.000000000 -0400
@@ -91,11 +91,20 @@
 static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
 {
 	struct omap_mcbsp *mcbsp_tx = dev_id;
+	u16 irqst_spcr2;
 
-	dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n",
-		OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
+	irqst_spcr2 = OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2);
+	dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2);
 
-	complete(&mcbsp_tx->tx_irq_completion);
+	if (irqst_spcr2 & XSYNC_ERR) {
+		dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n",
+			irqst_spcr2);
+		/* Writing zero to XSYNC_ERR clears the IRQ */
+		OMAP_MCBSP_WRITE(mcbsp_tx->io_base, SPCR2,
+			irqst_spcr2 & ~(XSYNC_ERR));
+	} else {
+		complete(&mcbsp_tx->tx_irq_completion);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -103,11 +112,20 @@
 static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
 {
 	struct omap_mcbsp *mcbsp_rx = dev_id;
+	u16 irqst_spcr1;
 
-	dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n",
-		OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
+	irqst_spcr1 = OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR1);
+	dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1);
 
-	complete(&mcbsp_rx->rx_irq_completion);
+	if (irqst_spcr1 & RSYNC_ERR) {
+		dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n",
+			irqst_spcr1);
+		/* Writing zero to RSYNC_ERR clears the IRQ */
+		OMAP_MCBSP_WRITE(mcbsp_rx->io_base, SPCR1,
+			irqst_spcr1 & ~(RSYNC_ERR));
+	} else {
+		complete(&mcbsp_rx->tx_irq_completion);
+	}
 
 	return IRQ_HANDLED;
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/mux.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/mux.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/mux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/mux.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,6 +54,9 @@
 {
 	struct pin_config *reg;
 
+	if (cpu_is_omap44xx())
+		return 0;
+
 	if (mux_cfg == NULL) {
 		printk(KERN_ERR "Pin mux table not initialized\n");
 		return -ENODEV;
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-omap/sram.c linux-libre-2.6.31-gnu/arch/arm/plat-omap/sram.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-omap/sram.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-omap/sram.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,9 @@
  * Copyright (C) 2005 Nokia Corporation
  * Written by Tony Lindgren <tony@atomide.com>
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -38,12 +41,14 @@
 #define OMAP1_SRAM_VA		VMALLOC_END
 #define OMAP2_SRAM_PA		0x40200000
 #define OMAP2_SRAM_PUB_PA	0x4020f800
-#define OMAP2_SRAM_VA		VMALLOC_END
-#define OMAP2_SRAM_PUB_VA	(VMALLOC_END + 0x800)
+#define OMAP2_SRAM_VA		0xe3000000
+#define OMAP2_SRAM_PUB_VA	(OMAP2_SRAM_VA + 0x800)
 #define OMAP3_SRAM_PA           0x40200000
-#define OMAP3_SRAM_VA           0xd7000000
+#define OMAP3_SRAM_VA           0xe3000000
 #define OMAP3_SRAM_PUB_PA       0x40208000
-#define OMAP3_SRAM_PUB_VA       0xd7008000
+#define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000)
+#define OMAP4_SRAM_PA		0x40200000		/*0x402f0000*/
+#define OMAP4_SRAM_VA		0xd7000000		/*0xd70f0000*/
 
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 #define SRAM_BOOTLOADER_SZ	0x00
@@ -87,6 +92,10 @@
 {
 	int type = 0;
 
+	if (cpu_is_omap44xx())
+		/* Not yet supported */
+		return 0;
+
 	if (cpu_is_omap242x())
 		type = omap_rev() & OMAP2_DEVICETYPE_MASK;
 
@@ -124,7 +133,12 @@
 			if (cpu_is_omap34xx()) {
 				omap_sram_base = OMAP3_SRAM_PUB_VA;
 				omap_sram_start = OMAP3_SRAM_PUB_PA;
-				omap_sram_size = 0x8000; /* 32K */
+				if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
+				    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
+					omap_sram_size = 0x7000; /* 28K */
+				} else {
+					omap_sram_size = 0x8000; /* 32K */
+				}
 			} else {
 				omap_sram_base = OMAP2_SRAM_PUB_VA;
 				omap_sram_start = OMAP2_SRAM_PUB_PA;
@@ -135,6 +149,10 @@
 				omap_sram_base = OMAP3_SRAM_VA;
 				omap_sram_start = OMAP3_SRAM_PA;
 				omap_sram_size = 0x10000; /* 64K */
+			} else if (cpu_is_omap44xx()) {
+				omap_sram_base = OMAP4_SRAM_VA;
+				omap_sram_start = OMAP4_SRAM_PA;
+				omap_sram_size = 0x8000; /* 32K */
 			} else {
 				omap_sram_base = OMAP2_SRAM_VA;
 				omap_sram_start = OMAP2_SRAM_PA;
@@ -201,8 +219,23 @@
 		base = OMAP3_SRAM_PA;
 		base = ROUND_DOWN(base, PAGE_SIZE);
 		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
+
+		/*
+		 * SRAM must be marked as non-cached on OMAP3 since the
+		 * CORE DPLL M2 divider change code (in SRAM) runs with the
+		 * SDRAM controller disabled, and if it is marked cached,
+		 * the ARM may attempt to write cache lines back to SDRAM
+		 * which will cause the system to hang.
+		 */
+		omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
 	}
 
+	if (cpu_is_omap44xx()) {
+		omap_sram_io_desc[0].virtual = OMAP4_SRAM_VA;
+		base = OMAP4_SRAM_PA;
+		base = ROUND_DOWN(base, PAGE_SIZE);
+		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
+	}
 	omap_sram_io_desc[0].length = 1024 * 1024;	/* Use section desc */
 	iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
 
@@ -242,20 +275,13 @@
 	return (void *)omap_sram_ceil;
 }
 
-static void omap_sram_error(void)
-{
-	panic("Uninitialized SRAM function\n");
-}
-
 #ifdef CONFIG_ARCH_OMAP1
 
 static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl);
 
 void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
 {
-	if (!_omap_sram_reprogram_clock)
-		omap_sram_error();
-
+	BUG_ON(!_omap_sram_reprogram_clock);
 	_omap_sram_reprogram_clock(dpllctl, ckctl);
 }
 
@@ -280,9 +306,7 @@
 void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
 		   u32 base_cs, u32 force_unlock)
 {
-	if (!_omap2_sram_ddr_init)
-		omap_sram_error();
-
+	BUG_ON(!_omap2_sram_ddr_init);
 	_omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
 			     base_cs, force_unlock);
 }
@@ -292,9 +316,7 @@
 
 void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
 {
-	if (!_omap2_sram_reprogram_sdrc)
-		omap_sram_error();
-
+	BUG_ON(!_omap2_sram_reprogram_sdrc);
 	_omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
 }
 
@@ -302,9 +324,7 @@
 
 u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
 {
-	if (!_omap2_set_prcm)
-		omap_sram_error();
-
+	BUG_ON(!_omap2_set_prcm);
 	return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass);
 }
 #endif
@@ -353,19 +373,26 @@
 
 #ifdef CONFIG_ARCH_OMAP3
 
-static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl,
-					      u32 sdrc_actim_ctrla,
-					      u32 sdrc_actim_ctrlb,
-					      u32 m2);
-u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla,
-			      u32 sdrc_actim_ctrlb, u32 m2)
-{
-	if (!_omap3_sram_configure_core_dpll)
-		omap_sram_error();
+static u32 (*_omap3_sram_configure_core_dpll)(
+			u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
 
-	return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl,
-					       sdrc_actim_ctrla,
-					       sdrc_actim_ctrlb, m2);
+u32 omap3_configure_core_dpll(u32 m2, u32 unlock_dll, u32 f, u32 inc,
+			u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+			u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+			u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1)
+{
+	BUG_ON(!_omap3_sram_configure_core_dpll);
+	return _omap3_sram_configure_core_dpll(
+			m2, unlock_dll, f, inc,
+			sdrc_rfr_ctrl_0, sdrc_actim_ctrl_a_0,
+			sdrc_actim_ctrl_b_0, sdrc_mr_0,
+			sdrc_rfr_ctrl_1, sdrc_actim_ctrl_a_1,
+			sdrc_actim_ctrl_b_1, sdrc_mr_1);
 }
 
 /* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */
@@ -406,6 +433,8 @@
 		omap243x_sram_init();
 	else if (cpu_is_omap34xx())
 		omap34xx_sram_init();
+	else if (cpu_is_omap44xx())
+		omap34xx_sram_init(); /* FIXME: */
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-orion/gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-orion/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-orion/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-orion/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,10 +15,9 @@
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 static DEFINE_SPINLOCK(gpio_lock);
-static const char *gpio_label[GPIO_MAX];  /* non null for allocated GPIOs */
 static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
 static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
 
@@ -46,82 +45,54 @@
 	writel(u, GPIO_OUT(pin));
 }
 
-
-/*
- * GENERIC_GPIO primitives.
- */
-int gpio_direction_input(unsigned pin)
+static inline void __set_blinking(unsigned pin, int blink)
 {
-	unsigned long flags;
-
-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_input)) {
-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/*
-	 * Some callers might not have used gpio_request(),
-	 * so flag this pin as requested now.
-	 */
-	if (gpio_label[pin] == NULL)
-		gpio_label[pin] = "?";
+	u32 u;
 
-	/*
-	 * Configure GPIO direction.
-	 */
-	__set_direction(pin, 1);
+	u = readl(GPIO_BLINK_EN(pin));
+	if (blink)
+		u |= 1 << (pin & 31);
+	else
+		u &= ~(1 << (pin & 31));
+	writel(u, GPIO_BLINK_EN(pin));
+}
 
-	spin_unlock_irqrestore(&gpio_lock, flags);
+static inline int orion_gpio_is_valid(unsigned pin, int mode)
+{
+	if (pin < GPIO_MAX) {
+		if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input))
+			goto err_out;
+		if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output))
+			goto err_out;
+		return true;
+	}
 
-	return 0;
+err_out:
+	pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+	return false;
 }
-EXPORT_SYMBOL(gpio_direction_input);
 
-int gpio_direction_output(unsigned pin, int value)
+/*
+ * GENERIC_GPIO primitives.
+ */
+static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
 	unsigned long flags;
-	u32 u;
 
-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_output)) {
-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+	if (!orion_gpio_is_valid(pin, GPIO_INPUT_OK))
 		return -EINVAL;
-	}
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
-	/*
-	 * Some callers might not have used gpio_request(),
-	 * so flag this pin as requested now.
-	 */
-	if (gpio_label[pin] == NULL)
-		gpio_label[pin] = "?";
-
-	/*
-	 * Disable blinking.
-	 */
-	u = readl(GPIO_BLINK_EN(pin));
-	u &= ~(1 << (pin & 31));
-	writel(u, GPIO_BLINK_EN(pin));
-
-	/*
-	 * Configure GPIO output value.
-	 */
-	__set_level(pin, value);
-
-	/*
-	 * Configure GPIO direction.
-	 */
-	__set_direction(pin, 0);
+	/* Configure GPIO direction. */
+	__set_direction(pin, 1);
 
 	spin_unlock_irqrestore(&gpio_lock, flags);
 
 	return 0;
 }
-EXPORT_SYMBOL(gpio_direction_output);
 
-int gpio_get_value(unsigned pin)
+static int orion_gpio_get_value(struct gpio_chip *chip, unsigned pin)
 {
 	int val;
 
@@ -132,83 +103,75 @@
 
 	return (val >> (pin & 31)) & 1;
 }
-EXPORT_SYMBOL(gpio_get_value);
 
-void gpio_set_value(unsigned pin, int value)
+static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+	int value)
 {
 	unsigned long flags;
-	u32 u;
+
+	if (!orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+		return -EINVAL;
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
-	/*
-	 * Disable blinking.
-	 */
-	u = readl(GPIO_BLINK_EN(pin));
-	u &= ~(1 << (pin & 31));
-	writel(u, GPIO_BLINK_EN(pin));
+	/* Disable blinking. */
+	__set_blinking(pin, 0);
 
-	/*
-	 * Configure GPIO output value.
-	 */
+	/* Configure GPIO output value. */
 	__set_level(pin, value);
 
+	/* Configure GPIO direction. */
+	__set_direction(pin, 0);
+
 	spin_unlock_irqrestore(&gpio_lock, flags);
+
+	return 0;
 }
-EXPORT_SYMBOL(gpio_set_value);
 
-int gpio_request(unsigned pin, const char *label)
+static void orion_gpio_set_value(struct gpio_chip *chip, unsigned pin,
+	int value)
 {
 	unsigned long flags;
-	int ret;
-
-	if (pin >= GPIO_MAX ||
-	    !(test_bit(pin, gpio_valid_input) ||
-	      test_bit(pin, gpio_valid_output))) {
-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
-		return -EINVAL;
-	}
 
 	spin_lock_irqsave(&gpio_lock, flags);
-	if (gpio_label[pin] == NULL) {
-		gpio_label[pin] = label ? label : "?";
-		ret = 0;
-	} else {
-		pr_debug("%s: GPIO %d already used as %s\n",
-			 __func__, pin, gpio_label[pin]);
-		ret = -EBUSY;
-	}
-	spin_unlock_irqrestore(&gpio_lock, flags);
 
-	return ret;
+	/* Configure GPIO output value. */
+	__set_level(pin, value);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
 }
-EXPORT_SYMBOL(gpio_request);
 
-void gpio_free(unsigned pin)
+static int orion_gpio_request(struct gpio_chip *chip, unsigned pin)
 {
-	if (pin >= GPIO_MAX ||
-	    !(test_bit(pin, gpio_valid_input) ||
-	      test_bit(pin, gpio_valid_output))) {
-		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
-		return;
-	}
-
-	if (gpio_label[pin] == NULL)
-		pr_warning("%s: GPIO %d already freed\n", __func__, pin);
-	else
-		gpio_label[pin] = NULL;
+	if (orion_gpio_is_valid(pin, GPIO_INPUT_OK) ||
+	    orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+		return 0;
+	return -EINVAL;
 }
-EXPORT_SYMBOL(gpio_free);
 
+static struct gpio_chip orion_gpiochip = {
+	.label			= "orion_gpio",
+	.direction_input	= orion_gpio_direction_input,
+	.get			= orion_gpio_get_value,
+	.direction_output	= orion_gpio_direction_output,
+	.set			= orion_gpio_set_value,
+	.request		= orion_gpio_request,
+	.base			= 0,
+	.ngpio			= GPIO_MAX,
+	.can_sleep		= 0,
+};
+
+void __init orion_gpio_init(void)
+{
+	gpiochip_add(&orion_gpiochip);
+}
 
 /*
  * Orion-specific GPIO API extensions.
  */
 void __init orion_gpio_set_unused(unsigned pin)
 {
-	/*
-	 * Configure as output, drive low.
-	 */
+	/* Configure as output, drive low. */
 	__set_level(pin, 0);
 	__set_direction(pin, 0);
 }
@@ -230,21 +193,14 @@
 void orion_gpio_set_blink(unsigned pin, int blink)
 {
 	unsigned long flags;
-	u32 u;
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
-	/*
-	 * Set output value to zero.
-	 */
+	/* Set output value to zero. */
 	__set_level(pin, 0);
 
-	u = readl(GPIO_BLINK_EN(pin));
-	if (blink)
-		u |= 1 << (pin & 31);
-	else
-		u &= ~(1 << (pin & 31));
-	writel(u, GPIO_BLINK_EN(pin));
+	/* Set blinking. */
+	__set_blinking(pin, blink);
 
 	spin_unlock_irqrestore(&gpio_lock, flags);
 }
@@ -368,7 +324,7 @@
 }
 
 struct irq_chip orion_gpio_irq_chip = {
-	.name		= "orion_gpio",
+	.name		= "orion_gpio_irq",
 	.ack		= gpio_irq_ack,
 	.mask		= gpio_irq_mask,
 	.unmask		= gpio_irq_unmask,
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-orion/include/plat/gpio.h linux-libre-2.6.31-gnu/arch/arm/plat-orion/include/plat/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-orion/include/plat/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-orion/include/plat/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,15 +11,14 @@
 #ifndef __PLAT_GPIO_H
 #define __PLAT_GPIO_H
 
+#include <linux/init.h>
+
 /*
  * GENERIC_GPIO primitives.
  */
-int gpio_request(unsigned pin, const char *label);
-void gpio_free(unsigned pin);
-int gpio_direction_input(unsigned pin);
-int gpio_direction_output(unsigned pin, int value);
-int gpio_get_value(unsigned pin);
-void gpio_set_value(unsigned pin, int value);
+#define gpio_get_value  __gpio_get_value
+#define gpio_set_value  __gpio_set_value
+#define gpio_cansleep   __gpio_cansleep
 
 /*
  * Orion-specific GPIO API extensions.
@@ -27,11 +26,13 @@
 void orion_gpio_set_unused(unsigned pin);
 void orion_gpio_set_blink(unsigned pin, int blink);
 
-#define GPIO_BIDI_OK		(1 << 0)
-#define GPIO_INPUT_OK		(1 << 1)
-#define GPIO_OUTPUT_OK		(1 << 2)
+#define GPIO_INPUT_OK		(1 << 0)
+#define GPIO_OUTPUT_OK		(1 << 1)
 void orion_gpio_set_valid(unsigned pin, int mode);
 
+/* Initialize gpiolib. */
+void __init orion_gpio_init(void);
+
 /*
  * GPIO interrupt handling.
  */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-orion/include/plat/orion5x_wdt.h linux-libre-2.6.31-gnu/arch/arm/plat-orion/include/plat/orion5x_wdt.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-orion/include/plat/orion5x_wdt.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-orion/include/plat/orion5x_wdt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- * arch/arm/plat-orion/include/plat/orion5x_wdt.h
- *
- * 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.
- */
-
-#ifndef __PLAT_ORION5X_WDT_H
-#define __PLAT_ORION5X_WDT_H
-
-struct orion5x_wdt_platform_data {
-	u32	tclk;		/* no <linux/clk.h> support yet */
-};
-
-
-#endif
-
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-orion/include/plat/orion_wdt.h linux-libre-2.6.31-gnu/arch/arm/plat-orion/include/plat/orion_wdt.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-orion/include/plat/orion_wdt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-orion/include/plat/orion_wdt.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/plat-orion/include/plat/orion_wdt.h
+ *
+ * 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.
+ */
+
+#ifndef __PLAT_ORION_WDT_H
+#define __PLAT_ORION_WDT_H
+
+struct orion_wdt_platform_data {
+	u32	tclk;		/* no <linux/clk.h> support yet */
+};
+
+
+#endif
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-orion/time.c linux-libre-2.6.31-gnu/arch/arm/plat-orion/time.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-orion/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-orion/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,11 +12,15 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cnt32_to_63.h>
+#include <linux/timer.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/mach/time.h>
 #include <mach/bridge-regs.h>
+#include <mach/hardware.h>
 
 /*
  * Number of timer ticks per jiffy.
@@ -39,6 +43,56 @@
 
 
 /*
+ * Orion's sched_clock implementation. It has a resolution of
+ * at least 7.5ns (133MHz TCLK) and a maximum value of 834 days.
+ *
+ * Because the hardware timer period is quite short (21 secs if
+ * 200MHz TCLK) and because cnt32_to_63() needs to be called at
+ * least once per half period to work properly, a kernel timer is
+ * set up to ensure this requirement is always met.
+ */
+#define TCLK2NS_SCALE_FACTOR 8
+
+static unsigned long tclk2ns_scale;
+
+unsigned long long sched_clock(void)
+{
+	unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL));
+	return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR;
+}
+
+static struct timer_list cnt32_to_63_keepwarm_timer;
+
+static void cnt32_to_63_keepwarm(unsigned long data)
+{
+	mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
+	(void) sched_clock();
+}
+
+static void __init setup_sched_clock(unsigned long tclk)
+{
+	unsigned long long v;
+	unsigned long data;
+
+	v = NSEC_PER_SEC;
+	v <<= TCLK2NS_SCALE_FACTOR;
+	v += tclk/2;
+	do_div(v, tclk);
+	/*
+	 * We want an even value to automatically clear the top bit
+	 * returned by cnt32_to_63() without an additional run time
+	 * instruction. So if the LSB is 1 then round it up.
+	 */
+	if (v & 1)
+		v++;
+	tclk2ns_scale = v;
+
+	data = (0xffffffffUL / tclk / 2 - 2) * HZ;
+	setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, data);
+	mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
+}
+
+/*
  * Clocksource handling.
  */
 static cycle_t orion_clksrc_read(struct clocksource *cs)
@@ -176,6 +230,10 @@
 
 	ticks_per_jiffy = (tclk + HZ/2) / HZ;
 
+	/*
+	 * Set scale and timer for sched_clock
+	 */
+	setup_sched_clock(tclk);
 
 	/*
 	 * Setup free-running clocksource timer (interrupts
@@ -190,7 +248,6 @@
 	orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift);
 	clocksource_register(&orion_clksrc);
 
-
 	/*
 	 * Setup clockevent timer (interrupt-driven.)
 	 */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-pxa/gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-pxa/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-pxa/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-pxa/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
-#include <linux/bootmem.h>
+#include <linux/slab.h>
 
 #include <mach/gpio.h>
 
@@ -112,17 +112,12 @@
 	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
 	struct pxa_gpio_chip *chips;
 
-	/* this is early, we have to use bootmem allocator, and we really
-	 * want this to be allocated dynamically for different 'gpio_end'
-	 */
-	chips = alloc_bootmem_low(nbanks * sizeof(struct pxa_gpio_chip));
+	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
 	if (chips == NULL) {
 		pr_err("%s: failed to allocate GPIO chips\n", __func__);
 		return -ENOMEM;
 	}
 
-	memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip));
-
 	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
 		struct gpio_chip *c = &chips[i].chip;
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-pxa/include/plat/i2c.h linux-libre-2.6.31-gnu/arch/arm/plat-pxa/include/plat/i2c.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-pxa/include/plat/i2c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-pxa/include/plat/i2c.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+ *  i2c_pxa.h
+ *
+ *  Copyright (C) 2002 Intrinsyc Software Inc.
+ *
+ *  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.
+ *
+ */
+#ifndef _I2C_PXA_H_
+#define _I2C_PXA_H_
+
+#if 0
+#define DEF_TIMEOUT             3
+#else
+/* need a longer timeout if we're dealing with the fact we may well be
+ * looking at a multi-master environment
+*/
+#define DEF_TIMEOUT             32
+#endif
+
+#define BUS_ERROR               (-EREMOTEIO)
+#define XFER_NAKED              (-ECONNREFUSED)
+#define I2C_RETRY               (-2000) /* an error has occurred retry transmit */
+
+/* ICR initialize bit values
+*
+*  15. FM       0 (100 Khz operation)
+*  14. UR       0 (No unit reset)
+*  13. SADIE    0 (Disables the unit from interrupting on slave addresses
+*                                       matching its slave address)
+*  12. ALDIE    0 (Disables the unit from interrupt when it loses arbitration
+*                                       in master mode)
+*  11. SSDIE    0 (Disables interrupts from a slave stop detected, in slave mode)
+*  10. BEIE     1 (Enable interrupts from detected bus errors, no ACK sent)
+*  9.  IRFIE    1 (Enable interrupts from full buffer received)
+*  8.  ITEIE    1 (Enables the I2C unit to interrupt when transmit buffer empty)
+*  7.  GCD      1 (Disables i2c unit response to general call messages as a slave)
+*  6.  IUE      0 (Disable unit until we change settings)
+*  5.  SCLE     1 (Enables the i2c clock output for master mode (drives SCL)
+*  4.  MA       0 (Only send stop with the ICR stop bit)
+*  3.  TB       0 (We are not transmitting a byte initially)
+*  2.  ACKNAK   0 (Send an ACK after the unit receives a byte)
+*  1.  STOP     0 (Do not send a STOP)
+*  0.  START    0 (Do not send a START)
+*
+*/
+#define I2C_ICR_INIT	(ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
+
+/* I2C status register init values
+ *
+ * 10. BED      1 (Clear bus error detected)
+ * 9.  SAD      1 (Clear slave address detected)
+ * 7.  IRF      1 (Clear IDBR Receive Full)
+ * 6.  ITE      1 (Clear IDBR Transmit Empty)
+ * 5.  ALD      1 (Clear Arbitration Loss Detected)
+ * 4.  SSD      1 (Clear Slave Stop Detected)
+ */
+#define I2C_ISR_INIT	0x7FF  /* status register init */
+
+struct i2c_slave_client;
+
+struct i2c_pxa_platform_data {
+	unsigned int		slave_addr;
+	struct i2c_slave_client	*slave;
+	unsigned int		class;
+	unsigned int		use_pio :1;
+	unsigned int		fast_mode :1;
+};
+
+extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
+
+#ifdef CONFIG_PXA27x
+extern void pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info);
+#endif
+
+#ifdef CONFIG_PXA3xx
+extern void pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info);
+#endif
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-pxa/Makefile linux-libre-2.6.31-gnu/arch/arm/plat-pxa/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/plat-pxa/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-pxa/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,3 +7,5 @@
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
+
+obj-$(CONFIG_HAVE_PWM)		+= pwm.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-pxa/pwm.c linux-libre-2.6.31-gnu/arch/arm/plat-pxa/pwm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-pxa/pwm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-pxa/pwm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,303 @@
+/*
+ * linux/arch/arm/mach-pxa/pwm.c
+ *
+ * simple driver for PWM (Pulse Width Modulator) controller
+ *
+ * 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.
+ *
+ * 2008-02-13	initial version
+ * 		eric miao <eric.miao@marvell.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+
+#include <asm/div64.h>
+
+#define HAS_SECONDARY_PWM	0x10
+#define PWM_ID_BASE(d)		((d) & 0xf)
+
+static const struct platform_device_id pwm_id_table[] = {
+	/*   PWM    has_secondary_pwm? */
+	{ "pxa25x-pwm", 0 },
+	{ "pxa27x-pwm", 0 | HAS_SECONDARY_PWM },
+	{ "pxa168-pwm", 1 },
+	{ "pxa910-pwm", 1 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, pwm_id_table);
+
+/* PWM registers and bits definitions */
+#define PWMCR		(0x00)
+#define PWMDCR		(0x04)
+#define PWMPCR		(0x08)
+
+#define PWMCR_SD	(1 << 6)
+#define PWMDCR_FD	(1 << 10)
+
+struct pwm_device {
+	struct list_head	node;
+	struct pwm_device	*secondary;
+	struct platform_device	*pdev;
+
+	const char	*label;
+	struct clk	*clk;
+	int		clk_enabled;
+	void __iomem	*mmio_base;
+
+	unsigned int	use_count;
+	unsigned int	pwm_id;
+};
+
+/*
+ * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
+ * duty_ns   = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+ */
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned long long c;
+	unsigned long period_cycles, prescale, pv, dc;
+
+	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
+		return -EINVAL;
+
+	c = clk_get_rate(pwm->clk);
+	c = c * period_ns;
+	do_div(c, 1000000000);
+	period_cycles = c;
+
+	if (period_cycles < 1)
+		period_cycles = 1;
+	prescale = (period_cycles - 1) / 1024;
+	pv = period_cycles / (prescale + 1) - 1;
+
+	if (prescale > 63)
+		return -EINVAL;
+
+	if (duty_ns == period_ns)
+		dc = PWMDCR_FD;
+	else
+		dc = (pv + 1) * duty_ns / period_ns;
+
+	/* NOTE: the clock to PWM has to be enabled first
+	 * before writing to the registers
+	 */
+	clk_enable(pwm->clk);
+	__raw_writel(prescale, pwm->mmio_base + PWMCR);
+	__raw_writel(dc, pwm->mmio_base + PWMDCR);
+	__raw_writel(pv, pwm->mmio_base + PWMPCR);
+	clk_disable(pwm->clk);
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	int rc = 0;
+
+	if (!pwm->clk_enabled) {
+		rc = clk_enable(pwm->clk);
+		if (!rc)
+			pwm->clk_enabled = 1;
+	}
+	return rc;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	if (pwm->clk_enabled) {
+		clk_disable(pwm->clk);
+		pwm->clk_enabled = 0;
+	}
+}
+EXPORT_SYMBOL(pwm_disable);
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+	struct pwm_device *pwm;
+	int found = 0;
+
+	mutex_lock(&pwm_lock);
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (pwm->pwm_id == pwm_id) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		if (pwm->use_count == 0) {
+			pwm->use_count++;
+			pwm->label = label;
+		} else
+			pwm = ERR_PTR(-EBUSY);
+	} else
+		pwm = ERR_PTR(-ENOENT);
+
+	mutex_unlock(&pwm_lock);
+	return pwm;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+
+	if (pwm->use_count) {
+		pwm->use_count--;
+		pwm->label = NULL;
+	} else
+		pr_warning("PWM device already freed\n");
+
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_free);
+
+static inline void __add_pwm(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+	list_add_tail(&pwm->node, &pwm_list);
+	mutex_unlock(&pwm_lock);
+}
+
+static int __devinit pwm_probe(struct platform_device *pdev)
+{
+	struct platform_device_id *id = platform_get_device_id(pdev);
+	struct pwm_device *pwm, *secondary = NULL;
+	struct resource *r;
+	int ret = 0;
+
+	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
+	if (pwm == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	pwm->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pwm->clk)) {
+		ret = PTR_ERR(pwm->clk);
+		goto err_free;
+	}
+	pwm->clk_enabled = 0;
+
+	pwm->use_count = 0;
+	pwm->pwm_id = PWM_ID_BASE(id->driver_data) + pdev->id;
+	pwm->pdev = pdev;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		ret = -ENODEV;
+		goto err_free_clk;
+	}
+
+	r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto err_free_clk;
+	}
+
+	pwm->mmio_base = ioremap(r->start, r->end - r->start + 1);
+	if (pwm->mmio_base == NULL) {
+		dev_err(&pdev->dev, "failed to ioremap() registers\n");
+		ret = -ENODEV;
+		goto err_free_mem;
+	}
+
+	if (id->driver_data & HAS_SECONDARY_PWM) {
+		secondary = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
+		if (secondary == NULL) {
+			ret = -ENOMEM;
+			goto err_free_mem;
+		}
+
+		*secondary = *pwm;
+		pwm->secondary = secondary;
+
+		/* registers for the second PWM has offset of 0x10 */
+		secondary->mmio_base = pwm->mmio_base + 0x10;
+		secondary->pwm_id = pdev->id + 2;
+	}
+
+	__add_pwm(pwm);
+	if (secondary)
+		__add_pwm(secondary);
+
+	platform_set_drvdata(pdev, pwm);
+	return 0;
+
+err_free_mem:
+	release_mem_region(r->start, r->end - r->start + 1);
+err_free_clk:
+	clk_put(pwm->clk);
+err_free:
+	kfree(pwm);
+	return ret;
+}
+
+static int __devexit pwm_remove(struct platform_device *pdev)
+{
+	struct pwm_device *pwm;
+	struct resource *r;
+
+	pwm = platform_get_drvdata(pdev);
+	if (pwm == NULL)
+		return -ENODEV;
+
+	mutex_lock(&pwm_lock);
+
+	if (pwm->secondary) {
+		list_del(&pwm->secondary->node);
+		kfree(pwm->secondary);
+	}
+
+	list_del(&pwm->node);
+	mutex_unlock(&pwm_lock);
+
+	iounmap(pwm->mmio_base);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, r->end - r->start + 1);
+
+	clk_put(pwm->clk);
+	kfree(pwm);
+	return 0;
+}
+
+static struct platform_driver pwm_driver = {
+	.driver		= {
+		.name	= "pxa25x-pwm",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pwm_probe,
+	.remove		= __devexit_p(pwm_remove),
+	.id_table	= pwm_id_table,
+};
+
+static int __init pwm_init(void)
+{
+	return platform_driver_register(&pwm_driver);
+}
+arch_initcall(pwm_init);
+
+static void __exit pwm_exit(void)
+{
+	platform_driver_unregister(&pwm_driver);
+}
+module_exit(pwm_exit);
+
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dev-audio.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dev-audio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dev-audio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,68 @@
+/* linux/arch/arm/plat-s3c/dev-audio.c
+ *
+ * Copyright 2009 Wolfson Microelectronics
+ *      Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+
+static struct resource s3c64xx_iis0_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_IIS0,
+		.end   = S3C64XX_PA_IIS0 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device s3c64xx_device_iis0 = {
+	.name		  = "s3c64xx-iis",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_iis0_resource),
+	.resource	  = s3c64xx_iis0_resource,
+};
+EXPORT_SYMBOL(s3c64xx_device_iis0);
+
+static struct resource s3c64xx_iis1_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_IIS1,
+		.end   = S3C64XX_PA_IIS1 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device s3c64xx_device_iis1 = {
+	.name		  = "s3c64xx-iis",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_iis1_resource),
+	.resource	  = s3c64xx_iis1_resource,
+};
+EXPORT_SYMBOL(s3c64xx_device_iis1);
+
+static struct resource s3c64xx_iisv4_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_IISV4,
+		.end   = S3C64XX_PA_IISV4 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device s3c64xx_device_iisv4 = {
+	.name		  = "s3c64xx-iis-v4",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_iisv4_resource),
+	.resource	  = s3c64xx_iisv4_resource,
+};
+EXPORT_SYMBOL(s3c64xx_device_iisv4);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dev-usb.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dev-usb.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dev-usb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dev-usb.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,50 @@
+/* linux/arch/arm/plat-s3c/dev-usb.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB host
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+
+static struct resource s3c_usb_resource[] = {
+	[0] = {
+		.start = S3C_PA_USBHOST,
+		.end   = S3C_PA_USBHOST + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH,
+		.end   = IRQ_USBH,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+	.name		  = "s3c2410-ohci",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
+	.resource	  = s3c_usb_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_usb_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dev-usb-hsotg.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dev-usb-hsotg.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dev-usb-hsotg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dev-usb-hsotg.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,41 @@
+/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB high-speed UDC/OtG block
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+static struct resource s3c_usb_hsotg_resources[] = {
+	[0] = {
+		.start	= S3C_PA_USB_HSOTG,
+		.end	= S3C_PA_USB_HSOTG + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_OTG,
+		.end	= IRQ_OTG,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device s3c_device_usb_hsotg = {
+	.name		= "s3c-hsotg",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usb_hsotg_resources),
+	.resource	= s3c_usb_hsotg_resources,
+};
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dma.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,86 @@
+/* linux/arch/arm/plat-s3c/dma.c
+ *
+ * Copyright (c) 2003-2005,2006,2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C DMA core
+ *
+ * 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.
+*/
+
+struct s3c2410_dma_buf;
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+#include <plat/dma-plat.h>
+
+/* dma channel state information */
+struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
+struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX];
+
+/* s3c_dma_lookup_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)
+{
+	if (channel & DMACH_LOW_LEVEL)
+		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+	else
+		return s3c_dma_chan_map[channel];
+}
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
+
+	chan->op_fn = rtn;
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_set_opfn);
+
+int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
+
+	chan->callback_fn = rtn;
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
+
+int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	chan->flags = flags;
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_setflags);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#include <plat/gpio-core.h>
+#include <mach/gpio-core.h>
 
 #ifdef CONFIG_S3C_GPIO_TRACK
 struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
@@ -140,6 +140,15 @@
 	if (!gc->get)
 		gc->get = s3c_gpiolib_get;
 
+#ifdef CONFIG_PM
+	if (chip->pm != NULL) {
+		if (!chip->pm->save || !chip->pm->resume)
+			printk(KERN_ERR "gpio: %s has missing PM functions\n",
+			       gc->label);
+	} else
+		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
 	/* gpiochip_add() prints own failure message on error. */
 	ret = gpiochip_add(gc);
 	if (ret >= 0)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/gpio-config.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/gpio-config.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/gpio-config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/gpio-config.c	2009-09-09 18:13:59.000000000 -0400
@@ -119,7 +119,7 @@
 	unsigned int shift = (off & 7) * 4;
 	u32 con;
 
-	if (off < 8 && chip->chip.ngpio >= 8)
+	if (off < 8 && chip->chip.ngpio > 8)
 		reg -= 4;
 
 	if (s3c_gpio_is_cfg_special(cfg)) {
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/adc.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/adc.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/adc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/adc.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,10 +19,12 @@
 extern int s3c_adc_start(struct s3c_adc_client *client,
 			 unsigned int channel, unsigned int nr_samples);
 
-extern struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
-					       void (*select)(unsigned selected),
-					       void (*conv)(unsigned d0, unsigned d1),
-					       unsigned int is_ts);
+extern struct s3c_adc_client *
+	s3c_adc_register(struct platform_device *pdev,
+			 void (*select)(unsigned selected),
+			 void (*conv)(unsigned d0, unsigned d1,
+				      unsigned *samples_left),
+			 unsigned int is_ts);
 
 extern void s3c_adc_release(struct s3c_adc_client *client);
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/clock.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/clock.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/clock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,7 @@
 extern struct clk clk_ext;
 
 /* S3C64XX specific clocks */
+extern struct clk clk_h2;
 extern struct clk clk_27m;
 extern struct clk clk_48m;
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/cpu.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/cpu.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/cpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/cpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -69,3 +69,6 @@
 extern struct sysdev_class s3c2440_sysclass;
 extern struct sysdev_class s3c2442_sysclass;
 extern struct sysdev_class s3c2443_sysclass;
+extern struct sysdev_class s3c6410_sysclass;
+extern struct sysdev_class s3c64xx_sysclass;
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/devs.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/devs.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/devs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/devs.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,16 +24,20 @@
 
 extern struct platform_device s3c_device_timer[];
 
+extern struct platform_device s3c64xx_device_iis0;
+extern struct platform_device s3c64xx_device_iis1;
+extern struct platform_device s3c64xx_device_iisv4;
+
 extern struct platform_device s3c_device_fb;
 extern struct platform_device s3c_device_usb;
 extern struct platform_device s3c_device_lcd;
 extern struct platform_device s3c_device_wdt;
 extern struct platform_device s3c_device_i2c0;
 extern struct platform_device s3c_device_i2c1;
-extern struct platform_device s3c_device_iis;
 extern struct platform_device s3c_device_rtc;
 extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
+extern struct platform_device s3c_device_iis;
 extern struct platform_device s3c_device_hwmon;
 extern struct platform_device s3c_device_hsmmc0;
 extern struct platform_device s3c_device_hsmmc1;
@@ -45,6 +49,7 @@
 extern struct platform_device s3c_device_nand;
 
 extern struct platform_device s3c_device_usbgadget;
+extern struct platform_device s3c_device_usb_hsotg;
 
 /* s3c2440 specific devices */
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/dma-core.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/dma-core.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/dma-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/dma-core.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/* arch/arm/plat-s3c/include/plat/dma.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Samsung S3C DMA core support
+ *
+ * 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.
+*/
+
+extern struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel);
+
+extern struct s3c2410_dma_chan *s3c_dma_chan_map[];
+
+/* the currently allocated channel information */
+extern struct s3c2410_dma_chan s3c2410_chans[];
+
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/dma.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/dma.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,127 @@
+/* arch/arm/plat-s3c/include/plat/dma.h
+ *
+ * Copyright (C) 2003,2004,2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C DMA support
+ *
+ * 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.
+*/
+
+enum s3c2410_dma_buffresult {
+	S3C2410_RES_OK,
+	S3C2410_RES_ERR,
+	S3C2410_RES_ABORT
+};
+
+enum s3c2410_dmasrc {
+	S3C2410_DMASRC_HW,		/* source is memory */
+	S3C2410_DMASRC_MEM		/* source is hardware */
+};
+
+/* enum s3c2410_chan_op
+ *
+ * operation codes passed to the DMA code by the user, and also used
+ * to inform the current channel owner of any changes to the system state
+*/
+
+enum s3c2410_chan_op {
+	S3C2410_DMAOP_START,
+	S3C2410_DMAOP_STOP,
+	S3C2410_DMAOP_PAUSE,
+	S3C2410_DMAOP_RESUME,
+	S3C2410_DMAOP_FLUSH,
+	S3C2410_DMAOP_TIMEOUT,		/* internal signal to handler */
+	S3C2410_DMAOP_STARTED,		/* indicate channel started */
+};
+
+struct s3c2410_dma_client {
+	char                *name;
+};
+
+struct s3c2410_dma_chan;
+
+/* s3c2410_dma_cbfn_t
+ *
+ * buffer callback routine type
+*/
+
+typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
+				   void *buf, int size,
+				   enum s3c2410_dma_buffresult result);
+
+typedef int  (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
+				   enum s3c2410_chan_op );
+
+
+
+/* s3c2410_dma_request
+ *
+ * request a dma channel exclusivley
+*/
+
+extern int s3c2410_dma_request(unsigned int channel,
+			       struct s3c2410_dma_client *, void *dev);
+
+
+/* s3c2410_dma_ctrl
+ *
+ * change the state of the dma channel
+*/
+
+extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
+
+/* s3c2410_dma_setflags
+ *
+ * set the channel's flags to a given state
+*/
+
+extern int s3c2410_dma_setflags(unsigned int channel,
+				unsigned int flags);
+
+/* s3c2410_dma_free
+ *
+ * free the dma channel (will also abort any outstanding operations)
+*/
+
+extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
+
+/* s3c2410_dma_enqueue
+ *
+ * place the given buffer onto the queue of operations for the channel.
+ * The buffer must be allocated from dma coherent memory, or the Dcache/WB
+ * drained before the buffer is given to the DMA system.
+*/
+
+extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
+			       dma_addr_t data, int size);
+
+/* s3c2410_dma_config
+ *
+ * configure the dma channel
+*/
+
+extern int s3c2410_dma_config(unsigned int channel, int xferunit);
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the device we're talking to
+*/
+
+extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
+				 unsigned long devaddr);
+
+/* s3c2410_dma_getposition
+ *
+ * get the position that the dma transfer is currently at
+*/
+
+extern int s3c2410_dma_getposition(unsigned int channel,
+				   dma_addr_t *src, dma_addr_t *dest);
+
+extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
+extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
+
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/gpio-core.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/gpio-core.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/gpio-core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/gpio-core.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,18 @@
  * specific code.
 */
 
+struct s3c_gpio_chip;
+
+/**
+ * struct s3c_gpio_pm - power management (suspend/resume) information
+ * @save: Routine to save the state of the GPIO block
+ * @resume: Routine to resume the GPIO block.
+ */
+struct s3c_gpio_pm {
+	void (*save)(struct s3c_gpio_chip *chip);
+	void (*resume)(struct s3c_gpio_chip *chip);
+};
+
 struct s3c_gpio_cfg;
 
 /**
@@ -27,6 +39,7 @@
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @config: special function and pull-resistor control information.
+ * @pm_save: Save information for suspend/resume support.
  *
  * This wrapper provides the necessary information for the Samsung
  * specific gpios being registered with gpiolib.
@@ -34,7 +47,11 @@
 struct s3c_gpio_chip {
 	struct gpio_chip	chip;
 	struct s3c_gpio_cfg	*config;
+	struct s3c_gpio_pm	*pm;
 	void __iomem		*base;
+#ifdef CONFIG_PM
+	u32			pm_save[4];
+#endif
 };
 
 static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
@@ -75,3 +92,16 @@
 
 static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
 #endif
+
+#ifdef CONFIG_PM
+extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
+extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
+extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
+#define __gpio_pm(x) x
+#else
+#define s3c_gpio_pm_1bit NULL
+#define s3c_gpio_pm_2bit NULL
+#define s3c_gpio_pm_4bit NULL
+#define __gpio_pm(x) NULL
+
+#endif /* CONFIG_PM */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/nand.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/nand.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/nand.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/nand.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,19 +10,26 @@
  * published by the Free Software Foundation.
 */
 
-/* struct s3c2410_nand_set
- *
- * define an set of one or more nand chips registered with an unique mtd
+/**
+ * struct s3c2410_nand_set - define a set of one or more nand chips
+ * @disable_ecc:	Entirely disable ECC - Dangerous
+ * @flash_bbt: 		Openmoko u-boot can create a Bad Block Table
+ *			Setting this flag will allow the kernel to
+ *			look for it at boot time and also skip the NAND
+ *			scan.
+ * @nr_chips:		Number of chips in this set
+ * @nr_partitions:	Number of partitions pointed to by @partitions
+ * @name:		Name of set (optional)
+ * @nr_map:		Map for low-layer logical to physical chip numbers (option)
+ * @partitions:		The mtd partition list
  *
- * nr_chips	 = number of chips in this set
- * nr_partitions = number of partitions pointed to be partitoons (or zero)
- * name		 = name of set (optional)
- * nr_map	 = map for low-layer logical to physical chip numbers (option)
- * partitions	 = mtd partition list
-*/
-
+ * define a set of one or more nand chips registered with an unique mtd. Also
+ * allows to pass flag to the underlying NAND layer. 'disable_ecc' will trigger
+ * a warning at boot time.
+ */
 struct s3c2410_nand_set {
-	unsigned int		disable_ecc : 1;
+	unsigned int		disable_ecc:1;
+	unsigned int		flash_bbt:1;
 
 	int			nr_chips;
 	int			nr_partitions;
@@ -39,7 +46,7 @@
 	int	twrph0;	/* active time for nWE/nOE */
 	int	twrph1;	/* time for release CLE/ALE from nWE/nOE inactive */
 
-	unsigned int	ignore_unset_ecc : 1;
+	unsigned int	ignore_unset_ecc:1;
 
 	int			nr_sets;
 	struct s3c2410_nand_set *sets;
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/pm.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/pm.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/pm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/pm.h	2009-09-09 18:13:59.000000000 -0400
@@ -44,6 +44,8 @@
 
 extern unsigned long s3c_pm_flags;
 
+extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
+
 /* from sleep.S */
 
 extern int  s3c_cpu_save(unsigned long *saveblk);
@@ -88,6 +90,7 @@
 	u32	ufcon;
 	u32	umcon;
 	u32	ubrdiv;
+	u32	udivslot;
 };
 
 /* helper functions to save/restore lists of registers. */
@@ -124,6 +127,18 @@
 #define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
 #endif
 
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+/**
+ * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
+ * @set: set bits for the state of the LEDs
+ * @clear: clear bits for the state of the LEDs.
+ */
+extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
+
+#else
+static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
+#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
+
 /* suspend memory checking */
 
 #ifdef CONFIG_S3C2410_PM_CHECK
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/regs-serial.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/regs-serial.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/regs-serial.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/regs-serial.h	2009-09-09 18:13:59.000000000 -0400
@@ -189,6 +189,11 @@
 
 #define S3C2443_DIVSLOT		  (0x2C)
 
+/* S3C64XX interrupt registers. */
+#define S3C64XX_UINTP		0x30
+#define S3C64XX_UINTSP		0x34
+#define S3C64XX_UINTM		0x38
+
 #ifndef __ASSEMBLY__
 
 /* struct s3c24xx_uart_clksrc
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,377 @@
+/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - USB2.0 Highspeed/OtG device block registers
+ *
+ * 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.
+*/
+
+#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_H
+#define __PLAT_S3C64XX_REGS_USB_HSOTG_H __FILE__
+
+#define S3C_HSOTG_REG(x) (x)
+
+#define S3C_GOTGCTL				S3C_HSOTG_REG(0x000)
+#define S3C_GOTGCTL_BSESVLD			(1 << 19)
+#define S3C_GOTGCTL_ASESVLD			(1 << 18)
+#define S3C_GOTGCTL_DBNC_SHORT			(1 << 17)
+#define S3C_GOTGCTL_CONID_B			(1 << 16)
+#define S3C_GOTGCTL_DEVHNPEN			(1 << 11)
+#define S3C_GOTGCTL_HSSETHNPEN			(1 << 10)
+#define S3C_GOTGCTL_HNPREQ			(1 << 9)
+#define S3C_GOTGCTL_HSTNEGSCS			(1 << 8)
+#define S3C_GOTGCTL_SESREQ			(1 << 1)
+#define S3C_GOTGCTL_SESREQSCS			(1 << 0)
+
+#define S3C_GOTGINT				S3C_HSOTG_REG(0x004)
+#define S3C_GOTGINT_DbnceDone			(1 << 19)
+#define S3C_GOTGINT_ADevTOUTChg			(1 << 18)
+#define S3C_GOTGINT_HstNegDet			(1 << 17)
+#define S3C_GOTGINT_HstnegSucStsChng		(1 << 9)
+#define S3C_GOTGINT_SesReqSucStsChng		(1 << 8)
+#define S3C_GOTGINT_SesEndDet			(1 << 2)
+
+#define S3C_GAHBCFG				S3C_HSOTG_REG(0x008)
+#define S3C_GAHBCFG_PTxFEmpLvl			(1 << 8)
+#define S3C_GAHBCFG_NPTxFEmpLvl			(1 << 7)
+#define S3C_GAHBCFG_DMAEn			(1 << 5)
+#define S3C_GAHBCFG_HBstLen_MASK		(0xf << 1)
+#define S3C_GAHBCFG_HBstLen_SHIFT		(1)
+#define S3C_GAHBCFG_HBstLen_Single		(0x0 << 1)
+#define S3C_GAHBCFG_HBstLen_Incr		(0x1 << 1)
+#define S3C_GAHBCFG_HBstLen_Incr4		(0x3 << 1)
+#define S3C_GAHBCFG_HBstLen_Incr8		(0x5 << 1)
+#define S3C_GAHBCFG_HBstLen_Incr16		(0x7 << 1)
+#define S3C_GAHBCFG_GlblIntrEn			(1 << 0)
+
+#define S3C_GUSBCFG				S3C_HSOTG_REG(0x00C)
+#define S3C_GUSBCFG_PHYLPClkSel			(1 << 15)
+#define S3C_GUSBCFG_HNPCap			(1 << 9)
+#define S3C_GUSBCFG_SRPCap			(1 << 8)
+#define S3C_GUSBCFG_PHYIf16			(1 << 3)
+#define S3C_GUSBCFG_TOutCal_MASK		(0x7 << 0)
+#define S3C_GUSBCFG_TOutCal_SHIFT		(0)
+#define S3C_GUSBCFG_TOutCal_LIMIT		(0x7)
+#define S3C_GUSBCFG_TOutCal(_x)			((_x) << 0)
+
+#define S3C_GRSTCTL				S3C_HSOTG_REG(0x010)
+
+#define S3C_GRSTCTL_AHBIdle			(1 << 31)
+#define S3C_GRSTCTL_DMAReq			(1 << 30)
+#define S3C_GRSTCTL_TxFNum_MASK			(0x1f << 6)
+#define S3C_GRSTCTL_TxFNum_SHIFT		(6)
+#define S3C_GRSTCTL_TxFNum_LIMIT		(0x1f)
+#define S3C_GRSTCTL_TxFNum(_x)			((_x) << 6)
+#define S3C_GRSTCTL_TxFFlsh			(1 << 5)
+#define S3C_GRSTCTL_RxFFlsh			(1 << 4)
+#define S3C_GRSTCTL_INTknQFlsh			(1 << 3)
+#define S3C_GRSTCTL_FrmCntrRst			(1 << 2)
+#define S3C_GRSTCTL_HSftRst			(1 << 1)
+#define S3C_GRSTCTL_CSftRst			(1 << 0)
+
+#define S3C_GINTSTS				S3C_HSOTG_REG(0x014)
+#define S3C_GINTMSK				S3C_HSOTG_REG(0x018)
+
+#define S3C_GINTSTS_WkUpInt			(1 << 31)
+#define S3C_GINTSTS_SessReqInt			(1 << 30)
+#define S3C_GINTSTS_DisconnInt			(1 << 29)
+#define S3C_GINTSTS_ConIDStsChng		(1 << 28)
+#define S3C_GINTSTS_PTxFEmp			(1 << 26)
+#define S3C_GINTSTS_HChInt			(1 << 25)
+#define S3C_GINTSTS_PrtInt			(1 << 24)
+#define S3C_GINTSTS_FetSusp			(1 << 22)
+#define S3C_GINTSTS_incompIP			(1 << 21)
+#define S3C_GINTSTS_IncomplSOIN			(1 << 20)
+#define S3C_GINTSTS_OEPInt			(1 << 19)
+#define S3C_GINTSTS_IEPInt			(1 << 18)
+#define S3C_GINTSTS_EPMis			(1 << 17)
+#define S3C_GINTSTS_EOPF			(1 << 15)
+#define S3C_GINTSTS_ISOutDrop			(1 << 14)
+#define S3C_GINTSTS_EnumDone			(1 << 13)
+#define S3C_GINTSTS_USBRst			(1 << 12)
+#define S3C_GINTSTS_USBSusp			(1 << 11)
+#define S3C_GINTSTS_ErlySusp			(1 << 10)
+#define S3C_GINTSTS_GOUTNakEff			(1 << 7)
+#define S3C_GINTSTS_GINNakEff			(1 << 6)
+#define S3C_GINTSTS_NPTxFEmp			(1 << 5)
+#define S3C_GINTSTS_RxFLvl			(1 << 4)
+#define S3C_GINTSTS_SOF				(1 << 3)
+#define S3C_GINTSTS_OTGInt			(1 << 2)
+#define S3C_GINTSTS_ModeMis			(1 << 1)
+#define S3C_GINTSTS_CurMod_Host			(1 << 0)
+
+#define S3C_GRXSTSR				S3C_HSOTG_REG(0x01C)
+#define S3C_GRXSTSP				S3C_HSOTG_REG(0x020)
+
+#define S3C_GRXSTS_FN_MASK			(0x7f << 25)
+#define S3C_GRXSTS_FN_SHIFT			(25)
+
+#define S3C_GRXSTS_PktSts_MASK			(0xf << 17)
+#define S3C_GRXSTS_PktSts_SHIFT			(17)
+#define S3C_GRXSTS_PktSts_GlobalOutNAK		(0x1 << 17)
+#define S3C_GRXSTS_PktSts_OutRX			(0x2 << 17)
+#define S3C_GRXSTS_PktSts_OutDone		(0x3 << 17)
+#define S3C_GRXSTS_PktSts_SetupDone		(0x4 << 17)
+#define S3C_GRXSTS_PktSts_SetupRX		(0x6 << 17)
+
+#define S3C_GRXSTS_DPID_MASK			(0x3 << 15)
+#define S3C_GRXSTS_DPID_SHIFT			(15)
+#define S3C_GRXSTS_ByteCnt_MASK			(0x7ff << 4)
+#define S3C_GRXSTS_ByteCnt_SHIFT		(4)
+#define S3C_GRXSTS_EPNum_MASK			(0xf << 0)
+#define S3C_GRXSTS_EPNum_SHIFT			(0)
+
+#define S3C_GRXFSIZ				S3C_HSOTG_REG(0x024)
+
+#define S3C_GNPTXFSIZ				S3C_HSOTG_REG(0x028)
+
+#define S3C_GNPTXFSIZ_NPTxFDep_MASK		(0xffff << 16)
+#define S3C_GNPTXFSIZ_NPTxFDep_SHIFT		(16)
+#define S3C_GNPTXFSIZ_NPTxFDep_LIMIT		(0xffff)
+#define S3C_GNPTXFSIZ_NPTxFDep(_x)		((_x) << 16)
+#define S3C_GNPTXFSIZ_NPTxFStAddr_MASK		(0xffff << 0)
+#define S3C_GNPTXFSIZ_NPTxFStAddr_SHIFT		(0)
+#define S3C_GNPTXFSIZ_NPTxFStAddr_LIMIT		(0xffff)
+#define S3C_GNPTXFSIZ_NPTxFStAddr(_x)		((_x) << 0)
+
+#define S3C_GNPTXSTS				S3C_HSOTG_REG(0x02C)
+
+#define S3C_GNPTXSTS_NPtxQTop_MASK		(0x7f << 24)
+#define S3C_GNPTXSTS_NPtxQTop_SHIFT		(24)
+
+#define S3C_GNPTXSTS_NPTxQSpcAvail_MASK		(0xff << 16)
+#define S3C_GNPTXSTS_NPTxQSpcAvail_SHIFT	(16)
+#define S3C_GNPTXSTS_NPTxQSpcAvail_GET(_v)	(((_v) >> 16) & 0xff)
+
+#define S3C_GNPTXSTS_NPTxFSpcAvail_MASK		(0xffff << 0)
+#define S3C_GNPTXSTS_NPTxFSpcAvail_SHIFT	(0)
+#define S3C_GNPTXSTS_NPTxFSpcAvail_GET(_v)	(((_v) >> 0) & 0xffff)
+
+
+#define S3C_HPTXFSIZ				S3C_HSOTG_REG(0x100)
+
+#define S3C_DPTXFSIZn(_a)			S3C_HSOTG_REG(0x104 + (((_a) - 1) * 4))
+
+#define S3C_DPTXFSIZn_DPTxFSize_MASK		(0xffff << 16)
+#define S3C_DPTXFSIZn_DPTxFSize_SHIFT		(16)
+#define S3C_DPTXFSIZn_DPTxFSize_GET(_v)		(((_v) >> 16) & 0xffff)
+#define S3C_DPTXFSIZn_DPTxFSize_LIMIT		(0xffff)
+#define S3C_DPTXFSIZn_DPTxFSize(_x)		((_x) << 16)
+
+#define S3C_DPTXFSIZn_DPTxFStAddr_MASK		(0xffff << 0)
+#define S3C_DPTXFSIZn_DPTxFStAddr_SHIFT		(0)
+
+/* Device mode registers */
+#define S3C_DCFG				S3C_HSOTG_REG(0x800)
+
+#define S3C_DCFG_EPMisCnt_MASK			(0x1f << 18)
+#define S3C_DCFG_EPMisCnt_SHIFT			(18)
+#define S3C_DCFG_EPMisCnt_LIMIT			(0x1f)
+#define S3C_DCFG_EPMisCnt(_x)			((_x) << 18)
+
+#define S3C_DCFG_PerFrInt_MASK			(0x3 << 11)
+#define S3C_DCFG_PerFrInt_SHIFT			(11)
+#define S3C_DCFG_PerFrInt_LIMIT			(0x3)
+#define S3C_DCFG_PerFrInt(_x)			((_x) << 11)
+
+#define S3C_DCFG_DevAddr_MASK			(0x7f << 4)
+#define S3C_DCFG_DevAddr_SHIFT			(4)
+#define S3C_DCFG_DevAddr_LIMIT			(0x7f)
+#define S3C_DCFG_DevAddr(_x)			((_x) << 4)
+
+#define S3C_DCFG_NZStsOUTHShk			(1 << 2)
+
+#define S3C_DCFG_DevSpd_MASK			(0x3 << 0)
+#define S3C_DCFG_DevSpd_SHIFT			(0)
+#define S3C_DCFG_DevSpd_HS			(0x0 << 0)
+#define S3C_DCFG_DevSpd_FS			(0x1 << 0)
+#define S3C_DCFG_DevSpd_LS			(0x2 << 0)
+#define S3C_DCFG_DevSpd_FS48			(0x3 << 0)
+
+#define S3C_DCTL				S3C_HSOTG_REG(0x804)
+
+#define S3C_DCTL_PWROnPrgDone			(1 << 11)
+#define S3C_DCTL_CGOUTNak			(1 << 10)
+#define S3C_DCTL_SGOUTNak			(1 << 9)
+#define S3C_DCTL_CGNPInNAK			(1 << 8)
+#define S3C_DCTL_SGNPInNAK			(1 << 7)
+#define S3C_DCTL_TstCtl_MASK			(0x7 << 4)
+#define S3C_DCTL_TstCtl_SHIFT			(4)
+#define S3C_DCTL_GOUTNakSts			(1 << 3)
+#define S3C_DCTL_GNPINNakSts			(1 << 2)
+#define S3C_DCTL_SftDiscon			(1 << 1)
+#define S3C_DCTL_RmtWkUpSig			(1 << 0)
+
+#define S3C_DSTS				S3C_HSOTG_REG(0x808)
+
+#define S3C_DSTS_SOFFN_MASK			(0x3fff << 8)
+#define S3C_DSTS_SOFFN_SHIFT			(8)
+#define S3C_DSTS_SOFFN_LIMIT			(0x3fff)
+#define S3C_DSTS_SOFFN(_x)			((_x) << 8)
+#define S3C_DSTS_ErraticErr			(1 << 3)
+#define S3C_DSTS_EnumSpd_MASK			(0x3 << 1)
+#define S3C_DSTS_EnumSpd_SHIFT			(1)
+#define S3C_DSTS_EnumSpd_HS			(0x0 << 1)
+#define S3C_DSTS_EnumSpd_FS			(0x1 << 1)
+#define S3C_DSTS_EnumSpd_LS			(0x2 << 1)
+#define S3C_DSTS_EnumSpd_FS48			(0x3 << 1)
+
+#define S3C_DSTS_SuspSts			(1 << 0)
+
+#define S3C_DIEPMSK				S3C_HSOTG_REG(0x810)
+
+#define S3C_DIEPMSK_INEPNakEffMsk		(1 << 6)
+#define S3C_DIEPMSK_INTknEPMisMsk		(1 << 5)
+#define S3C_DIEPMSK_INTknTXFEmpMsk		(1 << 4)
+#define S3C_DIEPMSK_TimeOUTMsk			(1 << 3)
+#define S3C_DIEPMSK_AHBErrMsk			(1 << 2)
+#define S3C_DIEPMSK_EPDisbldMsk			(1 << 1)
+#define S3C_DIEPMSK_XferComplMsk		(1 << 0)
+
+#define S3C_DOEPMSK				S3C_HSOTG_REG(0x814)
+
+#define S3C_DOEPMSK_Back2BackSetup		(1 << 6)
+#define S3C_DOEPMSK_OUTTknEPdisMsk		(1 << 4)
+#define S3C_DOEPMSK_SetupMsk			(1 << 3)
+#define S3C_DOEPMSK_AHBErrMsk			(1 << 2)
+#define S3C_DOEPMSK_EPDisbldMsk			(1 << 1)
+#define S3C_DOEPMSK_XferComplMsk		(1 << 0)
+
+#define S3C_DAINT				S3C_HSOTG_REG(0x818)
+#define S3C_DAINTMSK				S3C_HSOTG_REG(0x81C)
+
+#define S3C_DAINT_OutEP_SHIFT			(16)
+#define S3C_DAINT_OutEP(x)			(1 << ((x) + 16))
+#define S3C_DAINT_InEP(x)			(1 << (x))
+
+#define S3C_DTKNQR1				S3C_HSOTG_REG(0x820)
+#define S3C_DTKNQR2				S3C_HSOTG_REG(0x824)
+#define S3C_DTKNQR3				S3C_HSOTG_REG(0x830)
+#define S3C_DTKNQR4				S3C_HSOTG_REG(0x834)
+
+#define S3C_DVBUSDIS				S3C_HSOTG_REG(0x828)
+#define S3C_DVBUSPULSE				S3C_HSOTG_REG(0x82C)
+
+#define S3C_DIEPCTL0				S3C_HSOTG_REG(0x900)
+#define S3C_DOEPCTL0				S3C_HSOTG_REG(0xB00)
+#define S3C_DIEPCTL(_a)				S3C_HSOTG_REG(0x900 + ((_a) * 0x20))
+#define S3C_DOEPCTL(_a)				S3C_HSOTG_REG(0xB00 + ((_a) * 0x20))
+
+/* EP0 specialness:
+ * bits[29..28] - reserved (no SetD0PID, SetD1PID)
+ * bits[25..22] - should always be zero, this isn't a periodic endpoint
+ * bits[10..0] - MPS setting differenct for EP0
+*/
+#define S3C_D0EPCTL_MPS_MASK			(0x3 << 0)
+#define S3C_D0EPCTL_MPS_SHIFT			(0)
+#define S3C_D0EPCTL_MPS_64			(0x0 << 0)
+#define S3C_D0EPCTL_MPS_32			(0x1 << 0)
+#define S3C_D0EPCTL_MPS_16			(0x2 << 0)
+#define S3C_D0EPCTL_MPS_8			(0x3 << 0)
+
+#define S3C_DxEPCTL_EPEna			(1 << 31)
+#define S3C_DxEPCTL_EPDis			(1 << 30)
+#define S3C_DxEPCTL_SetD1PID			(1 << 29)
+#define S3C_DxEPCTL_SetOddFr			(1 << 29)
+#define S3C_DxEPCTL_SetD0PID			(1 << 28)
+#define S3C_DxEPCTL_SetEvenFr			(1 << 28)
+#define S3C_DxEPCTL_SNAK			(1 << 27)
+#define S3C_DxEPCTL_CNAK			(1 << 26)
+#define S3C_DxEPCTL_TxFNum_MASK			(0xf << 22)
+#define S3C_DxEPCTL_TxFNum_SHIFT		(22)
+#define S3C_DxEPCTL_TxFNum_LIMIT		(0xf)
+#define S3C_DxEPCTL_TxFNum(_x)			((_x) << 22)
+
+#define S3C_DxEPCTL_Stall			(1 << 21)
+#define S3C_DxEPCTL_Snp				(1 << 20)
+#define S3C_DxEPCTL_EPType_MASK			(0x3 << 18)
+#define S3C_DxEPCTL_EPType_SHIFT		(18)
+#define S3C_DxEPCTL_EPType_Control		(0x0 << 18)
+#define S3C_DxEPCTL_EPType_Iso			(0x1 << 18)
+#define S3C_DxEPCTL_EPType_Bulk			(0x2 << 18)
+#define S3C_DxEPCTL_EPType_Intterupt		(0x3 << 18)
+
+#define S3C_DxEPCTL_NAKsts			(1 << 17)
+#define S3C_DxEPCTL_DPID			(1 << 16)
+#define S3C_DxEPCTL_EOFrNum			(1 << 16)
+#define S3C_DxEPCTL_USBActEp			(1 << 15)
+#define S3C_DxEPCTL_NextEp_MASK			(0xf << 11)
+#define S3C_DxEPCTL_NextEp_SHIFT		(11)
+#define S3C_DxEPCTL_NextEp_LIMIT		(0xf)
+#define S3C_DxEPCTL_NextEp(_x)			((_x) << 11)
+
+#define S3C_DxEPCTL_MPS_MASK			(0x7ff << 0)
+#define S3C_DxEPCTL_MPS_SHIFT			(0)
+#define S3C_DxEPCTL_MPS_LIMIT			(0x7ff)
+#define S3C_DxEPCTL_MPS(_x)			((_x) << 0)
+
+#define S3C_DIEPINT(_a)				S3C_HSOTG_REG(0x908 + ((_a) * 0x20))
+#define S3C_DOEPINT(_a)				S3C_HSOTG_REG(0xB08 + ((_a) * 0x20))
+
+#define S3C_DxEPINT_INEPNakEff			(1 << 6)
+#define S3C_DxEPINT_Back2BackSetup		(1 << 6)
+#define S3C_DxEPINT_INTknEPMis			(1 << 5)
+#define S3C_DxEPINT_INTknTXFEmp			(1 << 4)
+#define S3C_DxEPINT_OUTTknEPdis			(1 << 4)
+#define S3C_DxEPINT_Timeout			(1 << 3)
+#define S3C_DxEPINT_Setup			(1 << 3)
+#define S3C_DxEPINT_AHBErr			(1 << 2)
+#define S3C_DxEPINT_EPDisbld			(1 << 1)
+#define S3C_DxEPINT_XferCompl			(1 << 0)
+
+#define S3C_DIEPTSIZ0				S3C_HSOTG_REG(0x910)
+
+#define S3C_DIEPTSIZ0_PktCnt_MASK		(0x3 << 19)
+#define S3C_DIEPTSIZ0_PktCnt_SHIFT		(19)
+#define S3C_DIEPTSIZ0_PktCnt_LIMIT		(0x3)
+#define S3C_DIEPTSIZ0_PktCnt(_x)		((_x) << 19)
+
+#define S3C_DIEPTSIZ0_XferSize_MASK		(0x7f << 0)
+#define S3C_DIEPTSIZ0_XferSize_SHIFT		(0)
+#define S3C_DIEPTSIZ0_XferSize_LIMIT		(0x7f)
+#define S3C_DIEPTSIZ0_XferSize(_x)		((_x) << 0)
+
+
+#define DOEPTSIZ0				S3C_HSOTG_REG(0xB10)
+#define S3C_DOEPTSIZ0_SUPCnt_MASK		(0x3 << 29)
+#define S3C_DOEPTSIZ0_SUPCnt_SHIFT		(29)
+#define S3C_DOEPTSIZ0_SUPCnt_LIMIT		(0x3)
+#define S3C_DOEPTSIZ0_SUPCnt(_x)		((_x) << 29)
+
+#define S3C_DOEPTSIZ0_PktCnt			(1 << 19)
+#define S3C_DOEPTSIZ0_XferSize_MASK		(0x7f << 0)
+#define S3C_DOEPTSIZ0_XferSize_SHIFT		(0)
+
+#define S3C_DIEPTSIZ(_a)			S3C_HSOTG_REG(0x910 + ((_a) * 0x20))
+#define S3C_DOEPTSIZ(_a)			S3C_HSOTG_REG(0xB10 + ((_a) * 0x20))
+
+#define S3C_DxEPTSIZ_MC_MASK			(0x3 << 29)
+#define S3C_DxEPTSIZ_MC_SHIFT			(29)
+#define S3C_DxEPTSIZ_MC_LIMIT			(0x3)
+#define S3C_DxEPTSIZ_MC(_x)			((_x) << 29)
+
+#define S3C_DxEPTSIZ_PktCnt_MASK		(0x3ff << 19)
+#define S3C_DxEPTSIZ_PktCnt_SHIFT		(19)
+#define S3C_DxEPTSIZ_PktCnt_GET(_v)		(((_v) >> 19) & 0x3ff)
+#define S3C_DxEPTSIZ_PktCnt_LIMIT		(0x3ff)
+#define S3C_DxEPTSIZ_PktCnt(_x)			((_x) << 19)
+
+#define S3C_DxEPTSIZ_XferSize_MASK		(0x7ffff << 0)
+#define S3C_DxEPTSIZ_XferSize_SHIFT		(0)
+#define S3C_DxEPTSIZ_XferSize_GET(_v)		(((_v) >> 0) & 0x7ffff)
+#define S3C_DxEPTSIZ_XferSize_LIMIT		(0x7ffff)
+#define S3C_DxEPTSIZ_XferSize(_x)		((_x) << 0)
+
+
+#define S3C_DIEPDMA(_a)				S3C_HSOTG_REG(0x914 + ((_a) * 0x20))
+#define S3C_DOEPDMA(_a)				S3C_HSOTG_REG(0xB14 + ((_a) * 0x20))
+
+#define S3C_EPFIFO(_a)				S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000))
+
+#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,50 @@
+/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - USB2.0 Highspeed/OtG device PHY registers
+ *
+ * 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.
+*/
+
+/* Note, this is a seperate header file as some of the clock framework
+ * needs to touch this if the clk_48m is used as the USB OHCI or other
+ * peripheral source.
+*/
+
+#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H
+#define __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H __FILE__
+
+/* S3C64XX_PA_USB_HSPHY */
+
+#define S3C_HSOTG_PHYREG(x)	((x) + S3C_VA_USB_HSPHY)
+
+#define S3C_PHYPWR				S3C_HSOTG_PHYREG(0x00)
+#define SRC_PHYPWR_OTG_DISABLE			(1 << 4)
+#define SRC_PHYPWR_ANALOG_POWERDOWN		(1 << 3)
+#define SRC_PHYPWR_FORCE_SUSPEND		(1 << 1)
+
+#define S3C_PHYCLK				S3C_HSOTG_PHYREG(0x04)
+#define S3C_PHYCLK_MODE_USB11			(1 << 6)
+#define S3C_PHYCLK_EXT_OSC			(1 << 5)
+#define S3C_PHYCLK_CLK_FORCE			(1 << 4)
+#define S3C_PHYCLK_ID_PULL			(1 << 2)
+#define S3C_PHYCLK_CLKSEL_MASK			(0x3 << 0)
+#define S3C_PHYCLK_CLKSEL_SHIFT			(0)
+#define S3C_PHYCLK_CLKSEL_48M			(0x0 << 0)
+#define S3C_PHYCLK_CLKSEL_12M			(0x2 << 0)
+#define S3C_PHYCLK_CLKSEL_24M			(0x3 << 0)
+
+#define S3C_RSTCON				S3C_HSOTG_PHYREG(0x08)
+#define S3C_RSTCON_PHYCLK			(1 << 2)
+#define S3C_RSTCON_HCLK				(1 << 2)
+#define S3C_RSTCON_PHY				(1 << 0)
+
+#define S3C_PHYTUNE				S3C_HSOTG_PHYREG(0x20)
+
+#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/sdhci.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/sdhci.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/sdhci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/sdhci.h	2009-09-09 18:13:59.000000000 -0400
@@ -67,12 +67,52 @@
 
 /* Helper function availablity */
 
+extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
+extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
+
+/* S3C6400 SDHCI setup */
+
+#ifdef CONFIG_S3C6400_SETUP_SDHCI
+extern char *s3c6400_hsmmc_clksrcs[4];
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
+					 void __iomem *r,
+					 struct mmc_ios *ios,
+					 struct mmc_card *card);
+
+static inline void s3c6400_default_sdhci0(void)
+{
+	s3c_hsmmc0_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
+	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
+	s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
+}
+
+#else
+static inline void s3c6400_default_sdhci0(void) { }
+#endif  /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static inline void s3c6400_default_sdhci1(void)
+{
+	s3c_hsmmc1_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
+	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
+	s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
+}
+#else
+static inline void s3c6400_default_sdhci1(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+#else
+static inline void s3c6400_default_sdhci0(void) { }
+static inline void s3c6400_default_sdhci1(void) { }
+#endif /* CONFIG_S3C6400_SETUP_SDHCI */
+
+/* S3C6410 SDHCI setup */
+
 #ifdef CONFIG_S3C6410_SETUP_SDHCI
 extern char *s3c6410_hsmmc_clksrcs[4];
 
-extern void s3c6410_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s3c6410_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-
 extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
 					   void __iomem *r,
 					   struct mmc_ios *ios,
@@ -82,7 +122,7 @@
 static inline void s3c6410_default_sdhci0(void)
 {
 	s3c_hsmmc0_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
-	s3c_hsmmc0_def_platdata.cfg_gpio = s3c6410_setup_sdhci0_cfg_gpio;
+	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
 	s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
 }
 #else
@@ -93,7 +133,7 @@
 static inline void s3c6410_default_sdhci1(void)
 {
 	s3c_hsmmc1_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
-	s3c_hsmmc1_def_platdata.cfg_gpio = s3c6410_setup_sdhci1_cfg_gpio;
+	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
 	s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
 }
 #else
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/udc-hs.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/udc-hs.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/udc-hs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/udc-hs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,29 @@
+/* arch/arm/plat-s3c/include/plat/udc-hs.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C USB2.0 High-speed / OtG platform information
+ *
+ * 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.
+*/
+
+enum s3c_hostg_dmamode {
+	S3C_HSOTG_DMA_NONE,	/* do not use DMA at-all */
+	S3C_HSOTG_DMA_ONLY,	/* always use DMA */
+	S3C_HSOTG_DMA_DRV,	/* DMA is chosen by driver */
+};
+
+/**
+ * struct s3c_hsotg_plat - platform data for high-speed otg/udc
+ * @dma: Whether to use DMA or not.
+ * @is_osc: The clock source is an oscillator, not a crystal
+ */
+struct s3c_hsotg_plat {
+	enum s3c_hostg_dmamode	dma;
+	unsigned int		is_osc : 1;
+};
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/watchdog-reset.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/watchdog-reset.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/include/plat/watchdog-reset.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/include/plat/watchdog-reset.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,49 @@
+/* arch/arm/plat-s3c/include/plat/watchdog-reset.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - System define for arch_reset() function
+ *
+ * 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.
+*/
+
+#include <plat/regs-watchdog.h>
+#include <mach/map.h>
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+static inline void arch_wdt_reset(void)
+{
+	struct clk *wdtclk;
+
+	printk("arch_reset: attempting watchdog reset\n");
+
+	__raw_writel(0, S3C2410_WTCON);	  /* disable watchdog, to be safe  */
+
+	wdtclk = clk_get(NULL, "watchdog");
+	if (!IS_ERR(wdtclk)) {
+		clk_enable(wdtclk);
+	} else
+		printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
+
+	/* put initial values into count and data */
+	__raw_writel(0x80, S3C2410_WTCNT);
+	__raw_writel(0x80, S3C2410_WTDAT);
+
+	/* set the watchdog to go and reset... */
+	__raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
+		     S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
+
+	/* wait for reset to assert... */
+	mdelay(500);
+
+	printk(KERN_ERR "Watchdog reset failed to assert reset\n");
+
+	/* delay to allow the serial port to show the message */
+	mdelay(50);
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/Kconfig linux-libre-2.6.31-gnu/arch/arm/plat-s3c/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -71,6 +71,15 @@
 	  Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
 	  for more information.
 
+config S3C_PM_DEBUG_LED_SMDK
+       bool "SMDK LED suspend/resume debugging"
+       depends on PM && (MACH_SMDK6410)
+       help
+         Say Y here to enable the use of the SMDK LEDs on the baseboard
+	 for debugging of the state of the suspend and resume process.
+
+	 Note, this currently only works for S3C64XX based SMDK boards.
+
 config S3C2410_PM_CHECK
 	bool "S3C2410 PM Suspend Memory CRC"
 	depends on PM && CRC32
@@ -150,6 +159,13 @@
 	  Internal configuration to enable S3C64XX style GPIO configuration
 	  functions.
 
+# DMA
+
+config S3C_DMA
+	bool
+	help
+	  Internal configuration for S3C DMA core
+
 # device definitions to compile in
 
 config S3C_DEV_HSMMC
@@ -172,4 +188,14 @@
 	help
 	  Compile in platform device definition for framebuffer
 
+config S3C_DEV_USB_HOST
+	bool
+	help
+	  Compile in platform device definition for USB host.
+
+config S3C_DEV_USB_HSOTG
+	bool
+	help
+	  Compile in platform device definition for USB high-speed OtG
+
 endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/Makefile linux-libre-2.6.31-gnu/arch/arm/plat-s3c/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -18,9 +18,14 @@
 obj-y				+= gpio.o
 obj-y				+= gpio-config.o
 
+# DMA support
+
+obj-$(CONFIG_S3C_DMA)		+= dma.o
+
 # PM support
 
 obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= pm-gpio.o
 obj-$(CONFIG_S3C2410_PM_CHECK)	+= pm-check.o
 
 # devices
@@ -29,4 +34,7 @@
 obj-$(CONFIG_S3C_DEV_HSMMC1)	+= dev-hsmmc1.o
 obj-y				+= dev-i2c0.o
 obj-$(CONFIG_S3C_DEV_I2C1)	+= dev-i2c1.o
+obj-$(CONFIG_SND_S3C64XX_SOC_I2S)	+= dev-audio.o
 obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
+obj-$(CONFIG_S3C_DEV_USB_HOST)	+= dev-usb.o
+obj-$(CONFIG_S3C_DEV_USB_HSOTG)	+= dev-usb-hsotg.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/pm.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/pm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,11 +21,10 @@
 
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
+#include <mach/map.h>
 
 #include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-#include <mach/regs-mem.h>
 #include <mach/regs-irq.h>
 #include <asm/irq.h>
 
@@ -70,6 +69,8 @@
 
 /* Save the UART configurations if we are configured for debug. */
 
+unsigned char pm_uart_udivslot;
+
 #ifdef CONFIG_S3C2410_PM_DEBUG
 
 struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
@@ -83,6 +84,12 @@
 	save->ufcon = __raw_readl(regs + S3C2410_UFCON);
 	save->umcon = __raw_readl(regs + S3C2410_UMCON);
 	save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
+
+	if (pm_uart_udivslot)
+		save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
+
+	S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
+		  uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
 }
 
 static void s3c_pm_save_uarts(void)
@@ -98,11 +105,16 @@
 {
 	void __iomem *regs = S3C_VA_UARTx(uart);
 
+	s3c_pm_arch_update_uart(regs, save);
+
 	__raw_writel(save->ulcon, regs + S3C2410_ULCON);
 	__raw_writel(save->ucon,  regs + S3C2410_UCON);
 	__raw_writel(save->ufcon, regs + S3C2410_UFCON);
 	__raw_writel(save->umcon, regs + S3C2410_UMCON);
 	__raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
+
+	if (pm_uart_udivslot)
+		__raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
 }
 
 static void s3c_pm_restore_uarts(void)
@@ -313,6 +325,9 @@
 
 	S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
 
+	/* LEDs should now be 1110 */
+	s3c_pm_debug_smdkled(1 << 1, 0);
+
 	s3c_pm_check_restore();
 
 	/* ok, let's return from sleep */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c/pm-gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c/pm-gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c/pm-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c/pm-gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,380 @@
+
+/* linux/arch/arm/plat-s3c/pm-gpio.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series GPIO PM code
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/gpio-core.h>
+#include <plat/pm.h>
+
+/* PM GPIO helpers */
+
+#define OFFS_CON	(0x00)
+#define OFFS_DAT	(0x04)
+#define OFFS_UP		(0x08)
+
+static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
+{
+	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
+	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
+}
+
+static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
+{
+	void __iomem *base = chip->base;
+	u32 old_gpcon = __raw_readl(base + OFFS_CON);
+	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+	u32 gps_gpcon = chip->pm_save[0];
+	u32 gps_gpdat = chip->pm_save[1];
+	u32 gpcon;
+
+	/* GPACON only has one bit per control / data and no PULLUPs.
+	 * GPACON[x] = 0 => Output, 1 => SFN */
+
+	/* first set all SFN bits to SFN */
+
+	gpcon = old_gpcon | gps_gpcon;
+	__raw_writel(gpcon, base + OFFS_CON);
+
+	/* now set all the other bits */
+
+	__raw_writel(gps_gpdat, base + OFFS_DAT);
+	__raw_writel(gps_gpcon, base + OFFS_CON);
+
+	S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_1bit = {
+	.save	= s3c_gpio_pm_1bit_save,
+	.resume = s3c_gpio_pm_1bit_resume,
+};
+
+static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+{
+	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
+	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
+	chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
+}
+
+/* Test whether the given masked+shifted bits of an GPIO configuration
+ * are one of the SFN (special function) modes. */
+
+static inline int is_sfn(unsigned long con)
+{
+	return con >= 2;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an input */
+
+static inline int is_in(unsigned long con)
+{
+	return con == 0;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an output */
+
+static inline int is_out(unsigned long con)
+{
+	return con == 1;
+}
+
+/**
+ * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
+ * @chip: The chip information to resume.
+ *
+ * Restore one of the GPIO banks that was saved during suspend. This is
+ * not as simple as once thought, due to the possibility of glitches
+ * from the order that the CON and DAT registers are set in.
+ *
+ * The three states the pin can be are {IN,OUT,SFN} which gives us 9
+ * combinations of changes to check. Three of these, if the pin stays
+ * in the same configuration can be discounted. This leaves us with
+ * the following:
+ *
+ * { IN => OUT }  Change DAT first
+ * { IN => SFN }  Change CON first
+ * { OUT => SFN } Change CON first, so new data will not glitch
+ * { OUT => IN }  Change CON first, so new data will not glitch
+ * { SFN => IN }  Change CON first
+ * { SFN => OUT } Change DAT first, so new data will not glitch [1]
+ *
+ * We do not currently deal with the UP registers as these control
+ * weak resistors, so a small delay in change should not need to bring
+ * these into the calculations.
+ *
+ * [1] this assumes that writing to a pin DAT whilst in SFN will set the
+ *     state for when it is next output.
+ */
+static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
+{
+	void __iomem *base = chip->base;
+	u32 old_gpcon = __raw_readl(base + OFFS_CON);
+	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+	u32 gps_gpcon = chip->pm_save[0];
+	u32 gps_gpdat = chip->pm_save[1];
+	u32 gpcon, old, new, mask;
+	u32 change_mask = 0x0;
+	int nr;
+
+	/* restore GPIO pull-up settings */
+	__raw_writel(chip->pm_save[2], base + OFFS_UP);
+
+	/* Create a change_mask of all the items that need to have
+	 * their CON value changed before their DAT value, so that
+	 * we minimise the work between the two settings.
+	 */
+
+	for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
+		old = (old_gpcon & mask) >> nr;
+		new = (gps_gpcon & mask) >> nr;
+
+		/* If there is no change, then skip */
+
+		if (old == new)
+			continue;
+
+		/* If both are special function, then skip */
+
+		if (is_sfn(old) && is_sfn(new))
+			continue;
+
+		/* Change is IN => OUT, do not change now */
+
+		if (is_in(old) && is_out(new))
+			continue;
+
+		/* Change is SFN => OUT, do not change now */
+
+		if (is_sfn(old) && is_out(new))
+			continue;
+
+		/* We should now be at the case of IN=>SFN,
+		 * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+		change_mask |= mask;
+	}
+
+
+	/* Write the new CON settings */
+
+	gpcon = old_gpcon & ~change_mask;
+	gpcon |= gps_gpcon & change_mask;
+
+	__raw_writel(gpcon, base + OFFS_CON);
+
+	/* Now change any items that require DAT,CON */
+
+	__raw_writel(gps_gpdat, base + OFFS_DAT);
+	__raw_writel(gps_gpcon, base + OFFS_CON);
+
+	S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_2bit = {
+	.save	= s3c_gpio_pm_2bit_save,
+	.resume = s3c_gpio_pm_2bit_resume,
+};
+
+#ifdef CONFIG_ARCH_S3C64XX
+static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+{
+	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
+	chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
+	chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
+
+	if (chip->chip.ngpio > 8)
+		chip->pm_save[0] = __raw_readl(chip->base - 4);
+}
+
+static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+{
+	u32 old, new, mask;
+	u32 change_mask = 0x0;
+	int nr;
+
+	for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
+		old = (old_gpcon & mask) >> nr;
+		new = (gps_gpcon & mask) >> nr;
+
+		/* If there is no change, then skip */
+
+		if (old == new)
+			continue;
+
+		/* If both are special function, then skip */
+
+		if (is_sfn(old) && is_sfn(new))
+			continue;
+
+		/* Change is IN => OUT, do not change now */
+
+		if (is_in(old) && is_out(new))
+			continue;
+
+		/* Change is SFN => OUT, do not change now */
+
+		if (is_sfn(old) && is_out(new))
+			continue;
+
+		/* We should now be at the case of IN=>SFN,
+		 * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+		change_mask |= mask;
+	}
+
+	return change_mask;
+}
+
+static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
+{
+	void __iomem *con = chip->base + (index * 4);
+	u32 old_gpcon = __raw_readl(con);
+	u32 gps_gpcon = chip->pm_save[index + 1];
+	u32 gpcon, mask;
+
+	mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
+
+	gpcon = old_gpcon & ~mask;
+	gpcon |= gps_gpcon & mask;
+
+	__raw_writel(gpcon, con);
+}
+
+static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+{
+	void __iomem *base = chip->base;
+	u32 old_gpcon[2];
+	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+	u32 gps_gpdat = chip->pm_save[2];
+
+	/* First, modify the CON settings */
+
+	old_gpcon[0] = 0;
+	old_gpcon[1] = __raw_readl(base + OFFS_CON);
+
+	s3c_gpio_pm_4bit_con(chip, 0);
+	if (chip->chip.ngpio > 8) {
+		old_gpcon[0] = __raw_readl(base - 4);
+		s3c_gpio_pm_4bit_con(chip, -1);
+	}
+
+	/* Now change the configurations that require DAT,CON */
+
+	__raw_writel(chip->pm_save[2], base + OFFS_DAT);
+	__raw_writel(chip->pm_save[1], base + OFFS_CON);
+	if (chip->chip.ngpio > 8)
+		__raw_writel(chip->pm_save[0], base - 4);
+
+	__raw_writel(chip->pm_save[2], base + OFFS_DAT);
+	__raw_writel(chip->pm_save[3], base + OFFS_UP);
+
+	if (chip->chip.ngpio > 8) {
+		S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
+			  chip->chip.label, old_gpcon[0], old_gpcon[1],
+			  __raw_readl(base - 4),
+			  __raw_readl(base + OFFS_CON),
+			  old_gpdat, gps_gpdat);
+	} else
+		S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
+			  chip->chip.label, old_gpcon[1],
+			  __raw_readl(base + OFFS_CON),
+			  old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_4bit = {
+	.save	= s3c_gpio_pm_4bit_save,
+	.resume = s3c_gpio_pm_4bit_resume,
+};
+#endif /* CONFIG_ARCH_S3C64XX */
+
+/**
+ * s3c_pm_save_gpio() - save gpio chip data for suspend
+ * @ourchip: The chip for suspend.
+ */
+static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
+{
+	struct s3c_gpio_pm *pm = ourchip->pm;
+
+	if (pm == NULL || pm->save == NULL)
+		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+	else
+		pm->save(ourchip);
+}
+
+/**
+ * s3c_pm_save_gpios() - Save the state of the GPIO banks.
+ *
+ * For all the GPIO banks, save the state of each one ready for going
+ * into a suspend mode.
+ */
+void s3c_pm_save_gpios(void)
+{
+	struct s3c_gpio_chip *ourchip;
+	unsigned int gpio_nr;
+
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		if (!ourchip)
+			continue;
+
+		s3c_pm_save_gpio(ourchip);
+
+		S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
+			  ourchip->chip.label,
+			  ourchip->pm_save[0],
+			  ourchip->pm_save[1],
+			  ourchip->pm_save[2],
+			  ourchip->pm_save[3]);
+
+		gpio_nr += ourchip->chip.ngpio;
+		gpio_nr += CONFIG_S3C_GPIO_SPACE;
+	}
+}
+
+/**
+ * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * @ourchip: The suspended chip.
+ */
+static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+{
+	struct s3c_gpio_pm *pm = ourchip->pm;
+
+	if (pm == NULL || pm->resume == NULL)
+		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+	else
+		pm->resume(ourchip);
+}
+
+void s3c_pm_restore_gpios(void)
+{
+	struct s3c_gpio_chip *ourchip;
+	unsigned int gpio_nr;
+
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		if (!ourchip)
+			continue;
+
+		s3c_pm_resume_gpio(ourchip);
+
+		gpio_nr += ourchip->chip.ngpio;
+		gpio_nr += CONFIG_S3C_GPIO_SPACE;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/adc.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/adc.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/adc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/adc.c	2009-09-09 18:13:59.000000000 -0400
@@ -45,7 +45,8 @@
 	unsigned char		 channel;
 
 	void	(*select_cb)(unsigned selected);
-	void	(*convert_cb)(unsigned val1, unsigned val2);
+	void	(*convert_cb)(unsigned val1, unsigned val2,
+			      unsigned *samples_left);
 };
 
 struct adc_device {
@@ -158,7 +159,8 @@
 
 struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
 					void (*select)(unsigned int selected),
-					void (*conv)(unsigned d0, unsigned d1),
+					void (*conv)(unsigned d0, unsigned d1,
+						     unsigned *samples_left),
 					unsigned int is_ts)
 {
 	struct s3c_adc_client *client;
@@ -227,9 +229,10 @@
 	data1 = readl(adc->regs + S3C2410_ADCDAT1);
 	adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
 
-	(client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff);
+	client->nr_samples--;
+	(client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff, &client->nr_samples);
 
-	if (--client->nr_samples > 0) {
+	if (client->nr_samples > 0) {
 		/* fire another conversion for this */
 
 		client->select_cb(1);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/clock-dclk.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/clock-dclk.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/clock-dclk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/clock-dclk.c	2009-09-09 18:13:59.000000000 -0400
@@ -129,7 +129,7 @@
 
 	/* calculate the MISCCR setting for the clock */
 
-	if (parent == &clk_xtal)
+	if (parent == &clk_mpll)
 		source = S3C2410_MISCCR_CLK0_MPLL;
 	else if (parent == &clk_upll)
 		source = S3C2410_MISCCR_CLK0_UPLL;
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/common-smdk.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/common-smdk.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/common-smdk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/common-smdk.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/sysdev.h>
 #include <linux/platform_device.h>
 
@@ -47,27 +48,27 @@
 /* LED devices */
 
 static struct s3c24xx_led_platdata smdk_pdata_led4 = {
-	.gpio		= S3C2410_GPF4,
+	.gpio		= S3C2410_GPF(4),
 	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
 	.name		= "led4",
 	.def_trigger	= "timer",
 };
 
 static struct s3c24xx_led_platdata smdk_pdata_led5 = {
-	.gpio		= S3C2410_GPF5,
+	.gpio		= S3C2410_GPF(5),
 	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
 	.name		= "led5",
 	.def_trigger	= "nand-disk",
 };
 
 static struct s3c24xx_led_platdata smdk_pdata_led6 = {
-	.gpio		= S3C2410_GPF6,
+	.gpio		= S3C2410_GPF(6),
 	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
 	.name		= "led6",
 };
 
 static struct s3c24xx_led_platdata smdk_pdata_led7 = {
-	.gpio		= S3C2410_GPF7,
+	.gpio		= S3C2410_GPF(7),
 	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
 	.name		= "led7",
 };
@@ -184,15 +185,15 @@
 {
 	/* Configure the LEDs (even if we have no LED support)*/
 
-	s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT);
+	s3c2410_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT);
 
-	s3c2410_gpio_setpin(S3C2410_GPF4, 1);
-	s3c2410_gpio_setpin(S3C2410_GPF5, 1);
-	s3c2410_gpio_setpin(S3C2410_GPF6, 1);
-	s3c2410_gpio_setpin(S3C2410_GPF7, 1);
+	s3c2410_gpio_setpin(S3C2410_GPF(4), 1);
+	s3c2410_gpio_setpin(S3C2410_GPF(5), 1);
+	s3c2410_gpio_setpin(S3C2410_GPF(6), 1);
+	s3c2410_gpio_setpin(S3C2410_GPF(7), 1);
 
 	if (machine_is_smdk2443())
 		smdk_nand_info.twrph0 = 50;
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/devs.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/devs.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/devs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/devs.c	2009-09-09 18:13:59.000000000 -0400
@@ -136,36 +136,6 @@
 struct platform_device *s3c24xx_uart_devs[4] = {
 };
 
-/* USB Host Controller */
-
-static struct resource s3c_usb_resource[] = {
-	[0] = {
-		.start = S3C24XX_PA_USBHOST,
-		.end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBH,
-		.end   = IRQ_USBH,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_usb = {
-	.name		  = "s3c2410-ohci",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
-	.resource	  = s3c_usb_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_usb_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_usb);
-
 /* LCD Controller */
 
 static struct resource s3c_lcd_resource[] = {
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/dma.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,10 +31,10 @@
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
-
 #include <mach/map.h>
 
-#include <plat/dma.h>
+#include <plat/dma-plat.h>
+#include <plat/regs-dma.h>
 
 /* io map for dma */
 static void __iomem *dma_base;
@@ -44,8 +44,6 @@
 
 static struct s3c24xx_dma_selection dma_sel;
 
-/* dma channel state information */
-struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
 
 /* debugging functions */
 
@@ -135,21 +133,6 @@
 #define dbg_showchan(chan) do { } while(0)
 #endif /* CONFIG_S3C2410_DMA_DEBUG */
 
-static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
-
-/* lookup_dma_channel
- *
- * change the dma channel number given into a real dma channel id
-*/
-
-static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
-{
-	if (channel & DMACH_LOW_LEVEL)
-		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
-	else
-		return dma_chan_map[channel];
-}
-
 /* s3c2410_dma_stats_timeout
  *
  * Update DMA stats from timeout info
@@ -214,8 +197,6 @@
 	return 0;
 }
 
-
-
 /* s3c2410_dma_loadbuffer
  *
  * load a buffer, and update the channel state
@@ -453,7 +434,7 @@
 int s3c2410_dma_enqueue(unsigned int channel, void *id,
 			dma_addr_t data, int size)
 {
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
 	struct s3c2410_dma_buf *buf;
 	unsigned long flags;
 
@@ -804,7 +785,7 @@
 
 int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
 {
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
 	unsigned long flags;
 
 	if (chan == NULL)
@@ -836,7 +817,7 @@
 	chan->irq_claimed = 0;
 
 	if (!(channel & DMACH_LOW_LEVEL))
-		dma_chan_map[channel] = NULL;
+		s3c_dma_chan_map[channel] = NULL;
 
 	local_irq_restore(flags);
 
@@ -995,7 +976,7 @@
 int
 s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
 {
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
 
 	if (chan == NULL)
 		return -EINVAL;
@@ -1038,14 +1019,13 @@
 /* s3c2410_dma_config
  *
  * xfersize:     size of unit in bytes (1,2,4)
- * dcon:         base value of the DCONx register
 */
 
 int s3c2410_dma_config(unsigned int channel,
-		       int xferunit,
-		       int dcon)
+		       int xferunit)
 {
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	unsigned int dcon;
 
 	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
 		 __func__, channel, xferunit, dcon);
@@ -1055,10 +1035,33 @@
 
 	pr_debug("%s: Initial dcon is %08x\n", __func__, dcon);
 
-	dcon |= chan->dcon & dma_sel.dcon_mask;
+	dcon = chan->dcon & dma_sel.dcon_mask;
 
 	pr_debug("%s: New dcon is %08x\n", __func__, dcon);
 
+	switch (chan->req_ch) {
+	case DMACH_I2S_IN:
+	case DMACH_I2S_OUT:
+	case DMACH_PCM_IN:
+	case DMACH_PCM_OUT:
+	case DMACH_MIC_IN:
+	default:
+		dcon |= S3C2410_DCON_HANDSHAKE;
+		dcon |= S3C2410_DCON_SYNC_PCLK;
+		break;
+
+	case DMACH_SDI:
+		/* note, ensure if need HANDSHAKE or not */
+		dcon |= S3C2410_DCON_SYNC_PCLK;
+		break;
+
+	case DMACH_XD0:
+	case DMACH_XD1:
+		dcon |= S3C2410_DCON_HANDSHAKE;
+		dcon |= S3C2410_DCON_SYNC_HCLK;
+		break;
+	}
+
 	switch (xferunit) {
 	case 1:
 		dcon |= S3C2410_DCON_BYTE;
@@ -1090,58 +1093,6 @@
 
 EXPORT_SYMBOL(s3c2410_dma_config);
 
-int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, flags=%08x\n", __func__, chan, flags);
-
-	chan->flags = flags;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-
-/* do we need to protect the settings of the fields from
- * irq?
-*/
-
-int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
-
-	chan->op_fn = rtn;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_opfn);
-
-int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
-
-	chan->callback_fn = rtn;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
 
 /* s3c2410_dma_devconfig
  *
@@ -1150,29 +1101,38 @@
  * source:    S3C2410_DMASRC_HW: source is hardware
  *            S3C2410_DMASRC_MEM: source is memory
  *
- * hwcfg:     the value for xxxSTCn register,
- *            bit 0: 0=increment pointer, 1=leave pointer
- *            bit 1: 0=source is AHB, 1=source is APB
- *
  * devaddr:   physical address of the source
 */
 
 int s3c2410_dma_devconfig(int channel,
 			  enum s3c2410_dmasrc source,
-			  int hwcfg,
 			  unsigned long devaddr)
 {
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	unsigned int hwcfg;
 
 	if (chan == NULL)
 		return -EINVAL;
 
-	pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
-		 __func__, (int)source, hwcfg, devaddr);
+	pr_debug("%s: source=%d, devaddr=%08lx\n",
+		 __func__, (int)source, devaddr);
 
 	chan->source = source;
 	chan->dev_addr = devaddr;
-	chan->hw_cfg = hwcfg;
+
+	switch (chan->req_ch) {
+	case DMACH_XD0:
+	case DMACH_XD1:
+		hwcfg = 0; /* AHB */
+		break;
+
+	default:
+		hwcfg = S3C2410_DISRCC_APB;
+	}
+
+	/* always assume our peripheral desintation is a fixed
+	 * address in memory. */
+	 hwcfg |= S3C2410_DISRCC_INC;
 
 	switch (source) {
 	case S3C2410_DMASRC_HW:
@@ -1219,7 +1179,7 @@
 
 int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst)
 {
- 	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
 
 	if (chan == NULL)
 		return -EINVAL;
@@ -1278,8 +1238,8 @@
 
 	printk(KERN_INFO "dma%d: restoring configuration\n", cp->number);
 
-	s3c2410_dma_config(no, cp->xfer_unit, cp->dcon);
-	s3c2410_dma_devconfig(no, cp->source, cp->hw_cfg, cp->dev_addr);
+	s3c2410_dma_config(no, cp->xfer_unit);
+	s3c2410_dma_devconfig(no, cp->source, cp->dev_addr);
 
 	/* re-select the dma source for this channel */
 
@@ -1476,7 +1436,8 @@
  found:
 	dmach = &s3c2410_chans[ch];
 	dmach->map = ch_map;
-	dma_chan_map[channel] = dmach;
+	dmach->req_ch = channel;
+	s3c_dma_chan_map[channel] = dmach;
 
 	/* select the channel */
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -183,35 +183,19 @@
 
 int s3c2410_gpio_getirq(unsigned int pin)
 {
-	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
-		return -1;	/* not valid interrupts */
+	if (pin < S3C2410_GPF(0) || pin > S3C2410_GPG(15))
+		return -EINVAL;	/* not valid interrupts */
 
-	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
-		return -1;	/* not valid pin */
+	if (pin < S3C2410_GPG(0) && pin > S3C2410_GPF(7))
+		return -EINVAL;	/* not valid pin */
 
-	if (pin < S3C2410_GPF4)
-		return (pin - S3C2410_GPF0) + IRQ_EINT0;
+	if (pin < S3C2410_GPF(4))
+		return (pin - S3C2410_GPF(0)) + IRQ_EINT0;
 
-	if (pin < S3C2410_GPG0)
-		return (pin - S3C2410_GPF4) + IRQ_EINT4;
+	if (pin < S3C2410_GPG(0))
+		return (pin - S3C2410_GPF(4)) + IRQ_EINT4;
 
-	return (pin - S3C2410_GPG0) + IRQ_EINT8;
+	return (pin - S3C2410_GPG(0)) + IRQ_EINT8;
 }
 
 EXPORT_SYMBOL(s3c2410_gpio_getirq);
-
-int s3c2410_gpio_irq2pin(unsigned int irq)
-{
-	if (irq >= IRQ_EINT0 && irq <= IRQ_EINT3)
-		return S3C2410_GPF0 + (irq - IRQ_EINT0);
-
-	if (irq >= IRQ_EINT4 && irq <= IRQ_EINT7)
-		return S3C2410_GPF4 + (irq - IRQ_EINT4);
-
-	if (irq >= IRQ_EINT8 && irq <= IRQ_EINT23)
-		return S3C2410_GPG0 + (irq - IRQ_EINT8);
-
-	return -EINVAL;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irq2pin);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/gpiolib.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/gpiolib.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/gpiolib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/gpiolib.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/sysdev.h>
 #include <linux/ioport.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -22,6 +23,7 @@
 #include <mach/gpio-core.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <plat/pm.h>
 
 #include <mach/regs-gpio.h>
 
@@ -77,9 +79,10 @@
 
 struct s3c_gpio_chip s3c24xx_gpios[] = {
 	[0] = {
-		.base	= S3C24XX_GPIO_BASE(S3C2410_GPA0),
+		.base	= S3C2410_GPACON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_1bit),
 		.chip	= {
-			.base			= S3C2410_GPA0,
+			.base			= S3C2410_GPA(0),
 			.owner			= THIS_MODULE,
 			.label			= "GPIOA",
 			.ngpio			= 24,
@@ -88,45 +91,50 @@
 		},
 	},
 	[1] = {
-		.base	= S3C24XX_GPIO_BASE(S3C2410_GPB0),
+		.base	= S3C2410_GPBCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
 		.chip	= {
-			.base			= S3C2410_GPB0,
+			.base			= S3C2410_GPB(0),
 			.owner			= THIS_MODULE,
 			.label			= "GPIOB",
 			.ngpio			= 16,
 		},
 	},
 	[2] = {
-		.base	= S3C24XX_GPIO_BASE(S3C2410_GPC0),
+		.base	= S3C2410_GPCCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
 		.chip	= {
-			.base			= S3C2410_GPC0,
+			.base			= S3C2410_GPC(0),
 			.owner			= THIS_MODULE,
 			.label			= "GPIOC",
 			.ngpio			= 16,
 		},
 	},
 	[3] = {
-		.base	= S3C24XX_GPIO_BASE(S3C2410_GPD0),
+		.base	= S3C2410_GPDCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
 		.chip	= {
-			.base			= S3C2410_GPD0,
+			.base			= S3C2410_GPD(0),
 			.owner			= THIS_MODULE,
 			.label			= "GPIOD",
 			.ngpio			= 16,
 		},
 	},
 	[4] = {
-		.base	= S3C24XX_GPIO_BASE(S3C2410_GPE0),
+		.base	= S3C2410_GPECON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
 		.chip	= {
-			.base			= S3C2410_GPE0,
+			.base			= S3C2410_GPE(0),
 			.label			= "GPIOE",
 			.owner			= THIS_MODULE,
 			.ngpio			= 16,
 		},
 	},
 	[5] = {
-		.base	= S3C24XX_GPIO_BASE(S3C2410_GPF0),
+		.base	= S3C2410_GPFCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
 		.chip	= {
-			.base			= S3C2410_GPF0,
+			.base			= S3C2410_GPF(0),
 			.owner			= THIS_MODULE,
 			.label			= "GPIOF",
 			.ngpio			= 8,
@@ -134,14 +142,24 @@
 		},
 	},
 	[6] = {
-		.base	= S3C24XX_GPIO_BASE(S3C2410_GPG0),
+		.base	= S3C2410_GPGCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
 		.chip	= {
-			.base			= S3C2410_GPG0,
+			.base			= S3C2410_GPG(0),
 			.owner			= THIS_MODULE,
 			.label			= "GPIOG",
-			.ngpio			= 10,
+			.ngpio			= 16,
 			.to_irq			= s3c24xx_gpiolib_bankg_toirq,
 		},
+	}, {
+		.base	= S3C2410_GPHCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
+		.chip	= {
+			.base			= S3C2410_GPH(0),
+			.owner			= THIS_MODULE,
+			.label			= "GPIOH",
+			.ngpio			= 11,
+		},
 	},
 };
 
@@ -156,4 +174,4 @@
 	return 0;
 }
 
-arch_initcall(s3c24xx_gpiolib_init);
+core_initcall(s3c24xx_gpiolib_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/dma.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/dma.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/dma.h
- *
- * Copyright (C) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C24XX DMA support
- *
- * 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.
-*/
-
-extern struct sysdev_class dma_sysclass;
-extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
-
-#define DMA_CH_VALID		(1<<31)
-#define DMA_CH_NEVER		(1<<30)
-
-struct s3c24xx_dma_addr {
-	unsigned long		from;
-	unsigned long		to;
-};
-
-/* struct s3c24xx_dma_map
- *
- * this holds the mapping information for the channel selected
- * to be connected to the specified device
-*/
-
-struct s3c24xx_dma_map {
-	const char		*name;
-	struct s3c24xx_dma_addr  hw_addr;
-
-	unsigned long		 channels[S3C2410_DMA_CHANNELS];
-	unsigned long		 channels_rx[S3C2410_DMA_CHANNELS];
-};
-
-struct s3c24xx_dma_selection {
-	struct s3c24xx_dma_map	*map;
-	unsigned long		 map_size;
-	unsigned long		 dcon_mask;
-
-	void	(*select)(struct s3c2410_dma_chan *chan,
-			  struct s3c24xx_dma_map *map);
-
-	void	(*direction)(struct s3c2410_dma_chan *chan,
-			     struct s3c24xx_dma_map *map,
-			     enum s3c2410_dmasrc dir);
-};
-
-extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
-
-/* struct s3c24xx_dma_order_ch
- *
- * channel map for one of the `enum dma_ch` dma channels. the list
- * entry contains a set of low-level channel numbers, orred with
- * DMA_CH_VALID, which are checked in the order in the array.
-*/
-
-struct s3c24xx_dma_order_ch {
-	unsigned int	list[S3C2410_DMA_CHANNELS];	/* list of channels */
-	unsigned int	flags;				/* flags */
-};
-
-/* struct s3c24xx_dma_order
- *
- * information provided by either the core or the board to give the
- * dma system a hint on how to allocate channels
-*/
-
-struct s3c24xx_dma_order {
-	struct s3c24xx_dma_order_ch	channels[DMACH_MAX];
-};
-
-extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
-
-/* DMA init code, called from the cpu support code */
-
-extern int s3c2410_dma_init(void);
-
-extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
-			    unsigned int stride);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/dma-plat.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/dma-plat.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/dma-plat.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * 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.
+*/
+
+#include <plat/dma-core.h>
+
+extern struct sysdev_class dma_sysclass;
+extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
+
+#define DMA_CH_VALID		(1<<31)
+#define DMA_CH_NEVER		(1<<30)
+
+struct s3c24xx_dma_addr {
+	unsigned long		from;
+	unsigned long		to;
+};
+
+/* struct s3c24xx_dma_map
+ *
+ * this holds the mapping information for the channel selected
+ * to be connected to the specified device
+*/
+
+struct s3c24xx_dma_map {
+	const char		*name;
+	struct s3c24xx_dma_addr  hw_addr;
+
+	unsigned long		 channels[S3C_DMA_CHANNELS];
+	unsigned long		 channels_rx[S3C_DMA_CHANNELS];
+};
+
+struct s3c24xx_dma_selection {
+	struct s3c24xx_dma_map	*map;
+	unsigned long		 map_size;
+	unsigned long		 dcon_mask;
+
+	void	(*select)(struct s3c2410_dma_chan *chan,
+			  struct s3c24xx_dma_map *map);
+
+	void	(*direction)(struct s3c2410_dma_chan *chan,
+			     struct s3c24xx_dma_map *map,
+			     enum s3c2410_dmasrc dir);
+};
+
+extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
+
+/* struct s3c24xx_dma_order_ch
+ *
+ * channel map for one of the `enum dma_ch` dma channels. the list
+ * entry contains a set of low-level channel numbers, orred with
+ * DMA_CH_VALID, which are checked in the order in the array.
+*/
+
+struct s3c24xx_dma_order_ch {
+	unsigned int	list[S3C_DMA_CHANNELS];	/* list of channels */
+	unsigned int	flags;				/* flags */
+};
+
+/* struct s3c24xx_dma_order
+ *
+ * information provided by either the core or the board to give the
+ * dma system a hint on how to allocate channels
+*/
+
+struct s3c24xx_dma_order {
+	struct s3c24xx_dma_order_ch	channels[DMACH_MAX];
+};
+
+extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
+
+/* DMA init code, called from the cpu support code */
+
+extern int s3c2410_dma_init(void);
+
+extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+			    unsigned int stride);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/map.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/map.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/map.h	2009-09-09 18:13:59.000000000 -0400
@@ -58,7 +58,6 @@
 #define S3C24XX_SZ_SPI		SZ_1M
 #define S3C24XX_SZ_SDI		SZ_1M
 #define S3C24XX_SZ_NAND		SZ_1M
-#define S3C24XX_SZ_USBHOST	SZ_1M
 
 /* GPIO ports */
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/pm-core.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/pm-core.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/pm-core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/pm-core.h	2009-09-09 18:13:59.000000000 -0400
@@ -57,3 +57,8 @@
 	s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
 				s3c_irqwake_eintmask);
 }
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/include/plat/regs-dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,145 @@
+/* arch/arm/mach-s3c2410/include/mach/dma.h
+ *
+ * Copyright (C) 2003,2004,2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support
+ *
+ * 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.
+*/
+
+/* DMA Register definitions */
+
+#define S3C2410_DMA_DISRC		(0x00)
+#define S3C2410_DMA_DISRCC		(0x04)
+#define S3C2410_DMA_DIDST		(0x08)
+#define S3C2410_DMA_DIDSTC		(0x0C)
+#define S3C2410_DMA_DCON		(0x10)
+#define S3C2410_DMA_DSTAT		(0x14)
+#define S3C2410_DMA_DCSRC		(0x18)
+#define S3C2410_DMA_DCDST		(0x1C)
+#define S3C2410_DMA_DMASKTRIG		(0x20)
+#define S3C2412_DMA_DMAREQSEL		(0x24)
+#define S3C2443_DMA_DMAREQSEL		(0x24)
+
+#define S3C2410_DISRCC_INC		(1<<0)
+#define S3C2410_DISRCC_APB		(1<<1)
+
+#define S3C2410_DMASKTRIG_STOP		(1<<2)
+#define S3C2410_DMASKTRIG_ON		(1<<1)
+#define S3C2410_DMASKTRIG_SWTRIG	(1<<0)
+
+#define S3C2410_DCON_DEMAND		(0<<31)
+#define S3C2410_DCON_HANDSHAKE		(1<<31)
+#define S3C2410_DCON_SYNC_PCLK		(0<<30)
+#define S3C2410_DCON_SYNC_HCLK		(1<<30)
+
+#define S3C2410_DCON_INTREQ		(1<<29)
+
+#define S3C2410_DCON_CH0_XDREQ0		(0<<24)
+#define S3C2410_DCON_CH0_UART0		(1<<24)
+#define S3C2410_DCON_CH0_SDI		(2<<24)
+#define S3C2410_DCON_CH0_TIMER		(3<<24)
+#define S3C2410_DCON_CH0_USBEP1		(4<<24)
+
+#define S3C2410_DCON_CH1_XDREQ1		(0<<24)
+#define S3C2410_DCON_CH1_UART1		(1<<24)
+#define S3C2410_DCON_CH1_I2SSDI		(2<<24)
+#define S3C2410_DCON_CH1_SPI		(3<<24)
+#define S3C2410_DCON_CH1_USBEP2		(4<<24)
+
+#define S3C2410_DCON_CH2_I2SSDO		(0<<24)
+#define S3C2410_DCON_CH2_I2SSDI		(1<<24)
+#define S3C2410_DCON_CH2_SDI		(2<<24)
+#define S3C2410_DCON_CH2_TIMER		(3<<24)
+#define S3C2410_DCON_CH2_USBEP3		(4<<24)
+
+#define S3C2410_DCON_CH3_UART2		(0<<24)
+#define S3C2410_DCON_CH3_SDI		(1<<24)
+#define S3C2410_DCON_CH3_SPI		(2<<24)
+#define S3C2410_DCON_CH3_TIMER		(3<<24)
+#define S3C2410_DCON_CH3_USBEP4		(4<<24)
+
+#define S3C2410_DCON_SRCSHIFT		(24)
+#define S3C2410_DCON_SRCMASK		(7<<24)
+
+#define S3C2410_DCON_BYTE		(0<<20)
+#define S3C2410_DCON_HALFWORD		(1<<20)
+#define S3C2410_DCON_WORD		(2<<20)
+
+#define S3C2410_DCON_AUTORELOAD		(0<<22)
+#define S3C2410_DCON_NORELOAD		(1<<22)
+#define S3C2410_DCON_HWTRIG		(1<<23)
+
+#ifdef CONFIG_CPU_S3C2440
+#define S3C2440_DIDSTC_CHKINT		(1<<2)
+
+#define S3C2440_DCON_CH0_I2SSDO		(5<<24)
+#define S3C2440_DCON_CH0_PCMIN		(6<<24)
+
+#define S3C2440_DCON_CH1_PCMOUT		(5<<24)
+#define S3C2440_DCON_CH1_SDI		(6<<24)
+
+#define S3C2440_DCON_CH2_PCMIN		(5<<24)
+#define S3C2440_DCON_CH2_MICIN		(6<<24)
+
+#define S3C2440_DCON_CH3_MICIN		(5<<24)
+#define S3C2440_DCON_CH3_PCMOUT		(6<<24)
+#endif
+
+#ifdef CONFIG_CPU_S3C2412
+
+#define S3C2412_DMAREQSEL_SRC(x)	((x)<<1)
+
+#define S3C2412_DMAREQSEL_HW		(1)
+
+#define S3C2412_DMAREQSEL_SPI0TX	S3C2412_DMAREQSEL_SRC(0)
+#define S3C2412_DMAREQSEL_SPI0RX	S3C2412_DMAREQSEL_SRC(1)
+#define S3C2412_DMAREQSEL_SPI1TX	S3C2412_DMAREQSEL_SRC(2)
+#define S3C2412_DMAREQSEL_SPI1RX	S3C2412_DMAREQSEL_SRC(3)
+#define S3C2412_DMAREQSEL_I2STX		S3C2412_DMAREQSEL_SRC(4)
+#define S3C2412_DMAREQSEL_I2SRX		S3C2412_DMAREQSEL_SRC(5)
+#define S3C2412_DMAREQSEL_TIMER		S3C2412_DMAREQSEL_SRC(9)
+#define S3C2412_DMAREQSEL_SDI		S3C2412_DMAREQSEL_SRC(10)
+#define S3C2412_DMAREQSEL_USBEP1	S3C2412_DMAREQSEL_SRC(13)
+#define S3C2412_DMAREQSEL_USBEP2	S3C2412_DMAREQSEL_SRC(14)
+#define S3C2412_DMAREQSEL_USBEP3	S3C2412_DMAREQSEL_SRC(15)
+#define S3C2412_DMAREQSEL_USBEP4	S3C2412_DMAREQSEL_SRC(16)
+#define S3C2412_DMAREQSEL_XDREQ0	S3C2412_DMAREQSEL_SRC(17)
+#define S3C2412_DMAREQSEL_XDREQ1	S3C2412_DMAREQSEL_SRC(18)
+#define S3C2412_DMAREQSEL_UART0_0	S3C2412_DMAREQSEL_SRC(19)
+#define S3C2412_DMAREQSEL_UART0_1	S3C2412_DMAREQSEL_SRC(20)
+#define S3C2412_DMAREQSEL_UART1_0	S3C2412_DMAREQSEL_SRC(21)
+#define S3C2412_DMAREQSEL_UART1_1	S3C2412_DMAREQSEL_SRC(22)
+#define S3C2412_DMAREQSEL_UART2_0	S3C2412_DMAREQSEL_SRC(23)
+#define S3C2412_DMAREQSEL_UART2_1	S3C2412_DMAREQSEL_SRC(24)
+
+#endif
+
+#define S3C2443_DMAREQSEL_SRC(x)	((x)<<1)
+
+#define S3C2443_DMAREQSEL_HW		(1)
+
+#define S3C2443_DMAREQSEL_SPI0TX	S3C2443_DMAREQSEL_SRC(0)
+#define S3C2443_DMAREQSEL_SPI0RX	S3C2443_DMAREQSEL_SRC(1)
+#define S3C2443_DMAREQSEL_SPI1TX	S3C2443_DMAREQSEL_SRC(2)
+#define S3C2443_DMAREQSEL_SPI1RX	S3C2443_DMAREQSEL_SRC(3)
+#define S3C2443_DMAREQSEL_I2STX		S3C2443_DMAREQSEL_SRC(4)
+#define S3C2443_DMAREQSEL_I2SRX		S3C2443_DMAREQSEL_SRC(5)
+#define S3C2443_DMAREQSEL_TIMER		S3C2443_DMAREQSEL_SRC(9)
+#define S3C2443_DMAREQSEL_SDI		S3C2443_DMAREQSEL_SRC(10)
+#define S3C2443_DMAREQSEL_XDREQ0	S3C2443_DMAREQSEL_SRC(17)
+#define S3C2443_DMAREQSEL_XDREQ1	S3C2443_DMAREQSEL_SRC(18)
+#define S3C2443_DMAREQSEL_UART0_0	S3C2443_DMAREQSEL_SRC(19)
+#define S3C2443_DMAREQSEL_UART0_1	S3C2443_DMAREQSEL_SRC(20)
+#define S3C2443_DMAREQSEL_UART1_0	S3C2443_DMAREQSEL_SRC(21)
+#define S3C2443_DMAREQSEL_UART1_1	S3C2443_DMAREQSEL_SRC(22)
+#define S3C2443_DMAREQSEL_UART2_0	S3C2443_DMAREQSEL_SRC(23)
+#define S3C2443_DMAREQSEL_UART2_1	S3C2443_DMAREQSEL_SRC(24)
+#define S3C2443_DMAREQSEL_UART3_0	S3C2443_DMAREQSEL_SRC(25)
+#define S3C2443_DMAREQSEL_UART3_1	S3C2443_DMAREQSEL_SRC(26)
+#define S3C2443_DMAREQSEL_PCMOUT	S3C2443_DMAREQSEL_SRC(27)
+#define S3C2443_DMAREQSEL_PCMIN 	S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_MICIN		S3C2443_DMAREQSEL_SRC(29)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/Kconfig linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -71,6 +71,7 @@
 config S3C2410_DMA
 	bool "S3C2410 DMA support"
 	depends on ARCH_S3C2410
+	select S3C_DMA
 	help
 	  S3C2410 DMA support. This is needed for drivers like sound which
 	  use the S3C2410's DMA system to move data to and from the
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/Makefile linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,7 @@
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM)		+= irq-pm.o
 obj-$(CONFIG_PM)		+= sleep.o
-obj-$(CONFIG_HAVE_PWM)		+= pwm.o
+obj-$(CONFIG_S3C24XX_PWM)	+= pwm.o
 obj-$(CONFIG_S3C2410_CLOCK)	+= s3c2410-clock.o
 obj-$(CONFIG_S3C2410_DMA)	+= dma.o
 obj-$(CONFIG_S3C24XX_ADC)	+= adc.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/pm.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/pm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/suspend.h>
 #include <linux/errno.h>
 #include <linux/time.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/serial_core.h>
 #include <linux/io.h>
@@ -75,43 +76,10 @@
 	SAVE_ITEM(S3C2410_CLKSLOW),
 };
 
-static struct gpio_sleep {
-	void __iomem	*base;
-	unsigned int	 gpcon;
-	unsigned int	 gpdat;
-	unsigned int	 gpup;
-} gpio_save[] = {
-	[0] = {
-		.base	= S3C2410_GPACON,
-	},
-	[1] = {
-		.base	= S3C2410_GPBCON,
-	},
-	[2] = {
-		.base	= S3C2410_GPCCON,
-	},
-	[3] = {
-		.base	= S3C2410_GPDCON,
-	},
-	[4] = {
-		.base	= S3C2410_GPECON,
-	},
-	[5] = {
-		.base	= S3C2410_GPFCON,
-	},
-	[6] = {
-		.base	= S3C2410_GPGCON,
-	},
-	[7] = {
-		.base	= S3C2410_GPHCON,
-	},
-};
-
 static struct sleep_save misc_save[] = {
 	SAVE_ITEM(S3C2410_DCLKCON),
 };
 
-
 /* s3c_pm_check_resume_pin
  *
  * check to see if the pin is configured correctly for sleep mode, and
@@ -156,196 +124,16 @@
 	 * and then configure it as an input if it is not
 	*/
 
-	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
-		s3c_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
-	}
-
-	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
-		s3c_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
-	}
-}
-
-/* offsets for CON/DAT/UP registers */
-
-#define OFFS_CON	(S3C2410_GPACON - S3C2410_GPACON)
-#define OFFS_DAT	(S3C2410_GPADAT - S3C2410_GPACON)
-#define OFFS_UP		(S3C2410_GPBUP  - S3C2410_GPBCON)
-
-/* s3c_pm_save_gpios()
- *
- * Save the state of the GPIOs
- */
-
-void s3c_pm_save_gpios(void)
-{
-	struct gpio_sleep *gps = gpio_save;
-	unsigned int gpio;
-
-	for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
-		void __iomem *base = gps->base;
-
-		gps->gpcon = __raw_readl(base + OFFS_CON);
-		gps->gpdat = __raw_readl(base + OFFS_DAT);
-
-		if (gpio > 0)
-			gps->gpup = __raw_readl(base + OFFS_UP);
-
+	for (pin = S3C2410_GPF(0); pin <= S3C2410_GPF(7); pin++) {
+		s3c_pm_check_resume_pin(pin, pin - S3C2410_GPF(0));
 	}
-}
-
-/* Test whether the given masked+shifted bits of an GPIO configuration
- * are one of the SFN (special function) modes. */
-
-static inline int is_sfn(unsigned long con)
-{
-	return (con == 2 || con == 3);
-}
-
-/* Test if the given masked+shifted GPIO configuration is an input */
-
-static inline int is_in(unsigned long con)
-{
-	return con == 0;
-}
-
-/* Test if the given masked+shifted GPIO configuration is an output */
-
-static inline int is_out(unsigned long con)
-{
-	return con == 1;
-}
-
-/**
- * s3c2410_pm_restore_gpio() - restore the given GPIO bank
- * @index: The number of the GPIO bank being resumed.
- * @gps: The sleep confgiuration for the bank.
- *
- * Restore one of the GPIO banks that was saved during suspend. This is
- * not as simple as once thought, due to the possibility of glitches
- * from the order that the CON and DAT registers are set in.
- *
- * The three states the pin can be are {IN,OUT,SFN} which gives us 9
- * combinations of changes to check. Three of these, if the pin stays
- * in the same configuration can be discounted. This leaves us with
- * the following:
- *
- * { IN => OUT }  Change DAT first
- * { IN => SFN }  Change CON first
- * { OUT => SFN } Change CON first, so new data will not glitch
- * { OUT => IN }  Change CON first, so new data will not glitch
- * { SFN => IN }  Change CON first
- * { SFN => OUT } Change DAT first, so new data will not glitch [1]
- *
- * We do not currently deal with the UP registers as these control
- * weak resistors, so a small delay in change should not need to bring
- * these into the calculations.
- *
- * [1] this assumes that writing to a pin DAT whilst in SFN will set the
- *     state for when it is next output.
- */
-
-static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
-{
-	void __iomem *base = gps->base;
-	unsigned long gps_gpcon = gps->gpcon;
-	unsigned long gps_gpdat = gps->gpdat;
-	unsigned long old_gpcon;
-	unsigned long old_gpdat;
-	unsigned long old_gpup = 0x0;
-	unsigned long gpcon;
-	int nr;
-
-	old_gpcon = __raw_readl(base + OFFS_CON);
-	old_gpdat = __raw_readl(base + OFFS_DAT);
-
-	if (base == S3C2410_GPACON) {
-		/* GPACON only has one bit per control / data and no PULLUPs.
-		 * GPACON[x] = 0 => Output, 1 => SFN */
-
-		/* first set all SFN bits to SFN */
-
-		gpcon = old_gpcon | gps->gpcon;
-		__raw_writel(gpcon, base + OFFS_CON);
-
-		/* now set all the other bits */
-
-		__raw_writel(gps_gpdat, base + OFFS_DAT);
-		__raw_writel(gps_gpcon, base + OFFS_CON);
-	} else {
-		unsigned long old, new, mask;
-		unsigned long change_mask = 0x0;
 
-		old_gpup = __raw_readl(base + OFFS_UP);
-
-		/* Create a change_mask of all the items that need to have
-		 * their CON value changed before their DAT value, so that
-		 * we minimise the work between the two settings.
-		 */
-
-		for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
-			old = (old_gpcon & mask) >> nr;
-			new = (gps_gpcon & mask) >> nr;
-
-			/* If there is no change, then skip */
-
-			if (old == new)
-				continue;
-
-			/* If both are special function, then skip */
-
-			if (is_sfn(old) && is_sfn(new))
-				continue;
-
-			/* Change is IN => OUT, do not change now */
-
-			if (is_in(old) && is_out(new))
-				continue;
-
-			/* Change is SFN => OUT, do not change now */
-
-			if (is_sfn(old) && is_out(new))
-				continue;
-
-			/* We should now be at the case of IN=>SFN,
-			 * OUT=>SFN, OUT=>IN, SFN=>IN. */
-
-			change_mask |= mask;
-		}
-
-		/* Write the new CON settings */
-
-		gpcon = old_gpcon & ~change_mask;
-		gpcon |= gps_gpcon & change_mask;
-
-		__raw_writel(gpcon, base + OFFS_CON);
-
-		/* Now change any items that require DAT,CON */
-
-		__raw_writel(gps_gpdat, base + OFFS_DAT);
-		__raw_writel(gps_gpcon, base + OFFS_CON);
-		__raw_writel(gps->gpup, base + OFFS_UP);
+	for (pin = S3C2410_GPG(0); pin <= S3C2410_GPG(7); pin++) {
+		s3c_pm_check_resume_pin(pin, (pin - S3C2410_GPG(0))+8);
 	}
-
-	S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
-		  index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
 
-/** s3c2410_pm_restore_gpios()
- *
- * Restore the state of the GPIOs
- */
-
-void s3c_pm_restore_gpios(void)
-{
-	struct gpio_sleep *gps = gpio_save;
-	int gpio;
-
-	for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
-		s3c2410_pm_restore_gpio(gpio, gps);
-	}
-}
-
 void s3c_pm_restore_core(void)
 {
 	s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/pwm.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/pwm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/pwm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/pwm.c	2009-09-09 18:13:59.000000000 -0400
@@ -246,6 +246,10 @@
 
 	tcmp = duty_ns / tin_ns;
 	tcmp = tcnt - tcmp;
+	/* the pwm hw only checks the compare register after a decrement,
+	   so the pin never toggles if tcmp = tcnt */
+	if (tcmp == tcnt)
+		tcmp--;
 
 	pwm_dbg(pwm, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt);
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/setup-i2c.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/setup-i2c.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/setup-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/setup-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 */
 
 #include <linux/kernel.h>
+#include <linux/gpio.h>
 
 struct platform_device;
 
@@ -20,6 +21,6 @@
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
 {
-	s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA);
-	s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL);
+	s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);
+	s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,8 +12,7 @@
 */
 
 #include <linux/kernel.h>
-
-#include <mach/hardware.h>
+#include <linux/gpio.h>
 
 #include <mach/spi.h>
 #include <mach/regs-gpio.h>
@@ -22,16 +21,16 @@
 					  int enable)
 {
 	if (enable) {
-		s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_SPICLK0);
-		s3c2410_gpio_cfgpin(S3C2410_GPE12, S3C2410_GPE12_SPIMOSI0);
-		s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE11_SPIMISO0);
-		s3c2410_gpio_pullup(S3C2410_GPE11, 0);
-		s3c2410_gpio_pullup(S3C2410_GPE13, 0);
+		s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
+		s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
+		s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
+		s3c2410_gpio_pullup(S3C2410_GPE(11), 0);
+		s3c2410_gpio_pullup(S3C2410_GPE(13), 0);
 	} else {
-		s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPIO_INPUT);
-		s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPIO_INPUT);
-		s3c2410_gpio_pullup(S3C2410_GPE11, 1);
-		s3c2410_gpio_pullup(S3C2410_GPE12, 1);
-		s3c2410_gpio_pullup(S3C2410_GPE13, 1);
+		s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT);
+		s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT);
+		s3c2410_gpio_pullup(S3C2410_GPE(11), 1);
+		s3c2410_gpio_pullup(S3C2410_GPE(12), 1);
+		s3c2410_gpio_pullup(S3C2410_GPE(13), 1);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,8 +12,7 @@
 */
 
 #include <linux/kernel.h>
-
-#include <mach/hardware.h>
+#include <linux/gpio.h>
 
 #include <mach/spi.h>
 #include <mach/regs-gpio.h>
@@ -22,16 +21,16 @@
 				       int enable)
 {
 	if (enable) {
-		s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPG7_SPICLK1);
-		s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_SPIMOSI1);
-		s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPG5_SPIMISO1);
-		s3c2410_gpio_pullup(S3C2410_GPG5, 0);
-		s3c2410_gpio_pullup(S3C2410_GPG6, 0);
+		s3c2410_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPG7_SPICLK1);
+		s3c2410_gpio_cfgpin(S3C2410_GPG(6), S3C2410_GPG6_SPIMOSI1);
+		s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPG5_SPIMISO1);
+		s3c2410_gpio_pullup(S3C2410_GPG(5), 0);
+		s3c2410_gpio_pullup(S3C2410_GPG(6), 0);
 	} else {
-		s3c2410_gpio_cfgpin(S3C2410_GPG7, S3C2410_GPIO_INPUT);
-		s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPIO_INPUT);
-		s3c2410_gpio_pullup(S3C2410_GPG5, 1);
-		s3c2410_gpio_pullup(S3C2410_GPG6, 1);
-		s3c2410_gpio_pullup(S3C2410_GPG7, 1);
+		s3c2410_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT);
+		s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT);
+		s3c2410_gpio_pullup(S3C2410_GPG(5), 1);
+		s3c2410_gpio_pullup(S3C2410_GPG(6), 1);
+		s3c2410_gpio_pullup(S3C2410_GPG(7), 1);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/clock.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,12 @@
 #include <plat/devs.h>
 #include <plat/clock.h>
 
+struct clk clk_h2 = {
+	.name		= "hclk2",
+	.id		= -1,
+	.rate		= 0,
+};
+
 struct clk clk_27m = {
 	.name		= "clk_27m",
 	.id		= -1,
@@ -152,6 +158,18 @@
 		.parent		= &clk_48m,
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_MMC2_48,
+	}, {
+		.name		= "dma0",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_DMA0,
+	}, {
+		.name		= "dma1",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_DMA1,
 	},
 };
 
@@ -173,7 +191,7 @@
 		.id		= -1,
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_UHOST,
+		.ctrlbit	= S3C_CLKCON_HCLK_UHOST,
 	}, {
 		.name		= "hsmmc",
 		.id		= 0,
@@ -246,6 +264,7 @@
 	&clk_epll,
 	&clk_27m,
 	&clk_48m,
+	&clk_h2,
 };
 
 void __init s3c64xx_register_clocks(void)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/cpu.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/cpu.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/cpu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/cpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/sysdev.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -101,9 +102,24 @@
 		.pfn		= __phys_to_pfn(S3C64XX_PA_MODEM),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_WATCHDOG),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
 	},
 };
 
+
+struct sysdev_class s3c64xx_sysclass = {
+	.name	= "s3c64xx-core",
+};
+
+static struct sys_device s3c64xx_sysdev = {
+	.cls	= &s3c64xx_sysclass,
+};
+
+
 /* read cpu identification code */
 
 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
@@ -115,5 +131,21 @@
 	iotable_init(mach_desc, size);
 
 	idcode = __raw_readl(S3C_VA_SYS + 0x118);
+	if (!idcode) {
+		/* S3C6400 has the ID register in a different place,
+		 * and needs a write before it can be read. */
+
+		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
+		idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
+	}
+
 	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
+
+static __init int s3c64xx_sysdev_init(void)
+{
+	sysdev_class_register(&s3c64xx_sysclass);
+	return sysdev_register(&s3c64xx_sysdev);
+}
+
+core_initcall(s3c64xx_sysdev_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/cpufreq.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/cpufreq.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/cpufreq.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,262 @@
+/* linux/arch/arm/plat-s3c64xx/cpufreq.c
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * S3C64xx CPUfreq Support
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+
+static struct clk *armclk;
+static struct regulator *vddarm;
+
+#ifdef CONFIG_CPU_S3C6410
+struct s3c64xx_dvfs {
+	unsigned int vddarm_min;
+	unsigned int vddarm_max;
+};
+
+static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {
+	[0] = { 1000000, 1000000 },
+	[1] = { 1000000, 1050000 },
+	[2] = { 1050000, 1100000 },
+	[3] = { 1050000, 1150000 },
+	[4] = { 1250000, 1350000 },
+};
+
+static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
+	{ 0,  66000 },
+	{ 0, 133000 },
+	{ 1, 222000 },
+	{ 1, 266000 },
+	{ 2, 333000 },
+	{ 2, 400000 },
+	{ 3, 532000 },
+	{ 3, 533000 },
+	{ 4, 667000 },
+	{ 0, CPUFREQ_TABLE_END },
+};
+#endif
+
+static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table);
+}
+
+static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
+{
+	if (cpu != 0)
+		return 0;
+
+	return clk_get_rate(armclk) / 1000;
+}
+
+static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
+				      unsigned int target_freq,
+				      unsigned int relation)
+{
+	int ret;
+	unsigned int i;
+	struct cpufreq_freqs freqs;
+	struct s3c64xx_dvfs *dvfs;
+
+	ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table,
+					     target_freq, relation, &i);
+	if (ret != 0)
+		return ret;
+
+	freqs.cpu = 0;
+	freqs.old = clk_get_rate(armclk) / 1000;
+	freqs.new = s3c64xx_freq_table[i].frequency;
+	freqs.flags = 0;
+	dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index];
+
+	if (freqs.old == freqs.new)
+		return 0;
+
+	pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_REGULATOR
+	if (vddarm && freqs.new > freqs.old) {
+		ret = regulator_set_voltage(vddarm,
+					    dvfs->vddarm_min,
+					    dvfs->vddarm_max);
+		if (ret != 0) {
+			pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+			       freqs.new, ret);
+			goto err;
+		}
+	}
+#endif
+
+	ret = clk_set_rate(armclk, freqs.new * 1000);
+	if (ret < 0) {
+		pr_err("cpufreq: Failed to set rate %dkHz: %d\n",
+		       freqs.new, ret);
+		goto err;
+	}
+
+#ifdef CONFIG_REGULATOR
+	if (vddarm && freqs.new < freqs.old) {
+		ret = regulator_set_voltage(vddarm,
+					    dvfs->vddarm_min,
+					    dvfs->vddarm_max);
+		if (ret != 0) {
+			pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+			       freqs.new, ret);
+			goto err_clk;
+		}
+	}
+#endif
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	pr_debug("cpufreq: Set actual frequency %lukHz\n",
+		 clk_get_rate(armclk) / 1000);
+
+	return 0;
+
+err_clk:
+	if (clk_set_rate(armclk, freqs.old * 1000) < 0)
+		pr_err("Failed to restore original clock rate\n");
+err:
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return ret;
+}
+
+#ifdef CONFIG_REGULATOR
+static void __init s3c64xx_cpufreq_constrain_voltages(void)
+{
+	int count, v, i, found;
+	struct cpufreq_frequency_table *freq;
+	struct s3c64xx_dvfs *dvfs;
+
+	count = regulator_count_voltages(vddarm);
+	if (count < 0) {
+		pr_err("cpufreq: Unable to check supported voltages\n");
+		return;
+	}
+
+	freq = s3c64xx_freq_table;
+	while (freq->frequency != CPUFREQ_TABLE_END) {
+		if (freq->frequency == CPUFREQ_ENTRY_INVALID)
+			continue;
+
+		dvfs = &s3c64xx_dvfs_table[freq->index];
+		found = 0;
+
+		for (i = 0; i < count; i++) {
+			v = regulator_list_voltage(vddarm, i);
+			if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max)
+				found = 1;
+		}
+
+		if (!found) {
+			pr_debug("cpufreq: %dkHz unsupported by regulator\n",
+				 freq->frequency);
+			freq->frequency = CPUFREQ_ENTRY_INVALID;
+		}
+
+		freq++;
+	}
+}
+#endif
+
+static int __init s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+	int ret;
+	struct cpufreq_frequency_table *freq;
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	if (s3c64xx_freq_table == NULL) {
+		pr_err("cpufreq: No frequency information for this CPU\n");
+		return -ENODEV;
+	}
+
+	armclk = clk_get(NULL, "armclk");
+	if (IS_ERR(armclk)) {
+		pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n",
+		       PTR_ERR(armclk));
+		return PTR_ERR(armclk);
+	}
+
+#ifdef CONFIG_REGULATOR
+	vddarm = regulator_get(NULL, "vddarm");
+	if (IS_ERR(vddarm)) {
+		ret = PTR_ERR(vddarm);
+		pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
+		pr_err("cpufreq: Only frequency scaling available\n");
+		vddarm = NULL;
+	} else {
+		s3c64xx_cpufreq_constrain_voltages();
+	}
+#endif
+
+	freq = s3c64xx_freq_table;
+	while (freq->frequency != CPUFREQ_TABLE_END) {
+		unsigned long r;
+
+		/* Check for frequencies we can generate */
+		r = clk_round_rate(armclk, freq->frequency * 1000);
+		r /= 1000;
+		if (r != freq->frequency)
+			freq->frequency = CPUFREQ_ENTRY_INVALID;
+
+		/* If we have no regulator then assume startup
+		 * frequency is the maximum we can support. */
+		if (!vddarm && freq->frequency > s3c64xx_cpufreq_get_speed(0))
+			freq->frequency = CPUFREQ_ENTRY_INVALID;
+
+		freq++;
+	}
+
+	policy->cur = clk_get_rate(armclk) / 1000;
+
+	/* Pick a conservative guess in ns: we'll need ~1 I2C/SPI
+	 * write plus clock reprogramming. */
+	policy->cpuinfo.transition_latency = 2 * 1000 * 1000;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
+	if (ret != 0) {
+		pr_err("cpufreq: Failed to configure frequency table: %d\n",
+		       ret);
+		regulator_put(vddarm);
+		clk_put(armclk);
+	}
+
+	return ret;
+}
+
+static struct cpufreq_driver s3c64xx_cpufreq_driver = {
+	.owner		= THIS_MODULE,
+	.flags          = 0,
+	.verify		= s3c64xx_cpufreq_verify_speed,
+	.target		= s3c64xx_cpufreq_set_target,
+	.get		= s3c64xx_cpufreq_get_speed,
+	.init		= s3c64xx_cpufreq_driver_init,
+	.name		= "s3c",
+};
+
+static int __init s3c64xx_cpufreq_init(void)
+{
+	return cpufreq_register_driver(&s3c64xx_cpufreq_driver);
+}
+module_init(s3c64xx_cpufreq_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/dma.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,722 @@
+/* linux/arch/arm/plat-s3c64xx/dma.c
+ *
+ * Copyright 2009 Openmoko, Inc.
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX DMA core
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/dmapool.h>
+#include <linux/sysdev.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/dma.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#include <plat/dma-plat.h>
+#include <plat/regs-sys.h>
+
+#include <asm/hardware/pl080.h>
+
+/* dma channel state information */
+
+struct s3c64xx_dmac {
+	struct sys_device	 sysdev;
+	struct clk		*clk;
+	void __iomem		*regs;
+	struct s3c2410_dma_chan *channels;
+	enum dma_ch		 chanbase;
+};
+
+/* pool to provide LLI buffers */
+static struct dma_pool *dma_pool;
+
+/* Debug configuration and code */
+
+static unsigned char debug_show_buffs = 0;
+
+static void dbg_showchan(struct s3c2410_dma_chan *chan)
+{
+	pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
+		 chan->number,
+		 readl(chan->regs + PL080_CH_SRC_ADDR),
+		 readl(chan->regs + PL080_CH_DST_ADDR),
+		 readl(chan->regs + PL080_CH_LLI),
+		 readl(chan->regs + PL080_CH_CONTROL),
+		 readl(chan->regs + PL080S_CH_CONTROL2),
+		 readl(chan->regs + PL080S_CH_CONFIG));
+}
+
+static void show_lli(struct pl080s_lli *lli)
+{
+	pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
+		 lli, lli->src_addr, lli->dst_addr, lli->next_lli,
+		 lli->control0, lli->control1);
+}
+
+static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
+{
+	struct s3c64xx_dma_buff *ptr;
+	struct s3c64xx_dma_buff *end;
+
+	pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
+		 chan->number, chan->next, chan->curr, chan->end);
+
+	ptr = chan->next;
+	end = chan->end;
+
+	if (debug_show_buffs) {
+		for (; ptr != NULL; ptr = ptr->next) {
+			pr_debug("DMA%d: %08x ",
+				 chan->number, ptr->lli_dma);
+			show_lli(ptr->lli);
+		}
+	}
+}
+
+/* End of Debug */
+
+static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
+{
+	struct s3c2410_dma_chan *chan;
+	unsigned int start, offs;
+
+	start = 0;
+
+	if (channel >= DMACH_PCM1_TX)
+		start = 8;
+
+	for (offs = 0; offs < 8; offs++) {
+		chan = &s3c2410_chans[start + offs];
+		if (!chan->in_use)
+			goto found;
+	}
+
+	return NULL;
+
+found:
+	s3c_dma_chan_map[channel] = chan;
+	return chan;
+}
+
+int s3c2410_dma_config(unsigned int channel, int xferunit)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	switch (xferunit) {
+	case 1:
+		chan->hw_width = 0;
+		break;
+	case 2:
+		chan->hw_width = 1;
+		break;
+	case 4:
+		chan->hw_width = 2;
+		break;
+	default:
+		printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_config);
+
+static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
+				 struct pl080s_lli *lli,
+				 dma_addr_t data, int size)
+{
+	dma_addr_t src, dst;
+	u32 control0, control1;
+
+	switch (chan->source) {
+	case S3C2410_DMASRC_HW:
+		src = chan->dev_addr;
+		dst = data;
+		control0 = PL080_CONTROL_SRC_AHB2;
+		control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
+		control0 |= 2 << PL080_CONTROL_DWIDTH_SHIFT;
+		control0 |= PL080_CONTROL_DST_INCR;
+		break;
+
+	case S3C2410_DMASRC_MEM:
+		src = data;
+		dst = chan->dev_addr;
+		control0 = PL080_CONTROL_DST_AHB2;
+		control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
+		control0 |= 2 << PL080_CONTROL_SWIDTH_SHIFT;
+		control0 |= PL080_CONTROL_SRC_INCR;
+		break;
+	default:
+		BUG();
+	}
+
+	/* note, we do not currently setup any of the burst controls */
+
+	control1 = size >> chan->hw_width;	/* size in no of xfers */
+	control0 |= PL080_CONTROL_PROT_SYS;	/* always in priv. mode */
+	control0 |= PL080_CONTROL_TC_IRQ_EN;	/* always fire IRQ */
+
+	lli->src_addr = src;
+	lli->dst_addr = dst;
+	lli->next_lli = 0;
+	lli->control0 = control0;
+	lli->control1 = control1;
+}
+
+static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
+				struct pl080s_lli *lli)
+{
+	void __iomem *regs = chan->regs;
+
+	pr_debug("%s: LLI %p => regs\n", __func__, lli);
+	show_lli(lli);
+
+	writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
+	writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
+	writel(lli->next_lli, regs + PL080_CH_LLI);
+	writel(lli->control0, regs + PL080_CH_CONTROL);
+	writel(lli->control1, regs + PL080S_CH_CONTROL2);
+}
+
+static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
+{
+	struct s3c64xx_dmac *dmac = chan->dmac;
+	u32 config;
+	u32 bit = chan->bit;
+
+	dbg_showchan(chan);
+
+	pr_debug("%s: clearing interrupts\n", __func__);
+
+	/* clear interrupts */
+	writel(bit, dmac->regs + PL080_TC_CLEAR);
+	writel(bit, dmac->regs + PL080_ERR_CLEAR);
+
+	pr_debug("%s: starting channel\n", __func__);
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config |= PL080_CONFIG_ENABLE;
+
+	pr_debug("%s: writing config %08x\n", __func__, config);
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	return 0;
+}
+
+static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
+{
+	u32 config;
+	int timeout;
+
+	pr_debug("%s: stopping channel\n", __func__);
+
+	dbg_showchan(chan);
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config |= PL080_CONFIG_HALT;
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	timeout = 1000;
+	do {
+		config = readl(chan->regs + PL080S_CH_CONFIG);
+		pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
+		if (config & PL080_CONFIG_ACTIVE)
+			udelay(10);
+		else
+			break;
+		} while (--timeout > 0);
+
+	if (config & PL080_CONFIG_ACTIVE) {
+		printk(KERN_ERR "%s: channel still active\n", __func__);
+		return -EFAULT;
+	}
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config &= ~PL080_CONFIG_ENABLE;
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	return 0;
+}
+
+static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
+					 struct s3c64xx_dma_buff *buf,
+					 enum s3c2410_dma_buffresult result)
+{
+	if (chan->callback_fn != NULL)
+		(chan->callback_fn)(chan, buf->pw, 0, result);
+}
+
+static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
+{
+	dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
+	kfree(buff);
+}
+
+static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
+{
+	struct s3c64xx_dma_buff *buff, *next;
+	u32 config;
+
+	dbg_showchan(chan);
+
+	pr_debug("%s: flushing channel\n", __func__);
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config &= ~PL080_CONFIG_ENABLE;
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	/* dump all the buffers associated with this channel */
+
+	for (buff = chan->curr; buff != NULL; buff = next) {
+		next = buff->next;
+		pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
+
+		s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
+		s3c64xx_dma_freebuff(buff);
+	}
+
+	chan->curr = chan->next = chan->end = NULL;
+
+	return 0;
+}
+
+int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	switch (op) {
+	case S3C2410_DMAOP_START:
+		return s3c64xx_dma_start(chan);
+
+	case S3C2410_DMAOP_STOP:
+		return s3c64xx_dma_stop(chan);
+
+	case S3C2410_DMAOP_FLUSH:
+		return s3c64xx_dma_flush(chan);
+
+	/* belive PAUSE/RESUME are no-ops */
+	case S3C2410_DMAOP_PAUSE:
+	case S3C2410_DMAOP_RESUME:
+	case S3C2410_DMAOP_STARTED:
+	case S3C2410_DMAOP_TIMEOUT:
+		return 0;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(s3c2410_dma_ctrl);
+
+/* s3c2410_dma_enque
+ *
+ */
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+			dma_addr_t data, int size)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	struct s3c64xx_dma_buff *next;
+	struct s3c64xx_dma_buff *buff;
+	struct pl080s_lli *lli;
+	int ret;
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_KERNEL);
+	if (!buff) {
+		printk(KERN_ERR "%s: no memory for buffer\n", __func__);
+		return -ENOMEM;
+	}
+
+	lli = dma_pool_alloc(dma_pool, GFP_KERNEL, &buff->lli_dma);
+	if (!lli) {
+		printk(KERN_ERR "%s: no memory for lli\n", __func__);
+		ret = -ENOMEM;
+		goto err_buff;
+	}
+
+	pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
+		 __func__, buff, data, lli, (u32)buff->lli_dma, size);
+
+	buff->lli = lli;
+	buff->pw = id;
+
+	s3c64xx_dma_fill_lli(chan, lli, data, size);
+
+	if ((next = chan->next) != NULL) {
+		struct s3c64xx_dma_buff *end = chan->end;
+		struct pl080s_lli *endlli = end->lli;
+
+		pr_debug("enquing onto channel\n");
+
+		end->next = buff;
+		endlli->next_lli = buff->lli_dma;
+
+		if (chan->flags & S3C2410_DMAF_CIRCULAR) {
+			struct s3c64xx_dma_buff *curr = chan->curr;
+			lli->next_lli = curr->lli_dma;
+		}
+
+		if (next == chan->curr) {
+			writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
+			chan->next = buff;
+		}
+
+		show_lli(endlli);
+		chan->end = buff;
+	} else {
+		pr_debug("enquing onto empty channel\n");
+
+		chan->curr = buff;
+		chan->next = buff;
+		chan->end = buff;
+
+		s3c64xx_lli_to_regs(chan, lli);
+	}
+
+	show_lli(lli);
+
+	dbg_showchan(chan);
+	dbg_showbuffs(chan);
+	return 0;
+
+err_buff:
+	kfree(buff);
+	return ret;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_enqueue);
+
+
+int s3c2410_dma_devconfig(int channel,
+			  enum s3c2410_dmasrc source,
+			  unsigned long devaddr)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	u32 peripheral;
+	u32 config = 0;
+
+	pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n",
+		 __func__, channel, source, devaddr, chan);
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	peripheral = (chan->peripheral & 0xf);
+	chan->source = source;
+	chan->dev_addr = devaddr;
+
+	pr_debug("%s: peripheral %d\n", __func__, peripheral);
+
+	switch (source) {
+	case S3C2410_DMASRC_HW:
+		config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
+		break;
+	case S3C2410_DMASRC_MEM:
+		config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
+		break;
+	default:
+		printk(KERN_ERR "%s: bad source\n", __func__);
+		return -EINVAL;
+	}
+
+	/* allow TC and ERR interrupts */
+	config |= PL080_CONFIG_TC_IRQ_MASK;
+	config |= PL080_CONFIG_ERR_IRQ_MASK;
+
+	pr_debug("%s: config %08x\n", __func__, config);
+
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_devconfig);
+
+
+int s3c2410_dma_getposition(unsigned int channel,
+			    dma_addr_t *src, dma_addr_t *dst)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	if (src != NULL)
+		*src = readl(chan->regs + PL080_CH_SRC_ADDR);
+
+	if (dst != NULL)
+		*dst = readl(chan->regs + PL080_CH_DST_ADDR);
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_getposition);
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel,
+			struct s3c2410_dma_client *client,
+			void *dev)
+{
+	struct s3c2410_dma_chan *chan;
+	unsigned long flags;
+
+	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+		 channel, client->name, dev);
+
+	local_irq_save(flags);
+
+	chan = s3c64xx_dma_map_channel(channel);
+	if (chan == NULL) {
+		local_irq_restore(flags);
+		return -EBUSY;
+	}
+
+	dbg_showchan(chan);
+
+	chan->client = client;
+	chan->in_use = 1;
+	chan->peripheral = channel;
+
+	local_irq_restore(flags);
+
+	/* need to setup */
+
+	pr_debug("%s: channel initialised, %p\n", __func__, chan);
+
+	return chan->number | DMACH_LOW_LEVEL;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_request);
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	unsigned long flags;
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	if (chan->client != client) {
+		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+		       channel, chan->client, client);
+	}
+
+	/* sort out stopping and freeing the channel */
+
+
+	chan->client = NULL;
+	chan->in_use = 0;
+
+	if (!(channel & DMACH_LOW_LEVEL))
+		s3c_dma_chan_map[channel] = NULL;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_free);
+
+
+static void s3c64xx_dma_tcirq(struct s3c64xx_dmac *dmac, int offs)
+{
+	struct s3c2410_dma_chan *chan = dmac->channels + offs;
+
+	/* note, we currently do not bother to work out which buffer
+	 * or buffers have been completed since the last tc-irq. */
+
+	if (chan->callback_fn)
+		(chan->callback_fn)(chan, chan->curr->pw, 0, S3C2410_RES_OK);
+}
+
+static void s3c64xx_dma_errirq(struct s3c64xx_dmac *dmac, int offs)
+{
+	printk(KERN_DEBUG "%s: offs %d\n", __func__, offs);
+}
+
+static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
+{
+	struct s3c64xx_dmac *dmac = pw;
+	u32 tcstat, errstat;
+	u32 bit;
+	int offs;
+
+	tcstat = readl(dmac->regs + PL080_TC_STATUS);
+	errstat = readl(dmac->regs + PL080_ERR_STATUS);
+
+	for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
+		if (tcstat & bit) {
+			writel(bit, dmac->regs + PL080_TC_CLEAR);
+			s3c64xx_dma_tcirq(dmac, offs);
+		}
+
+		if (errstat & bit) {
+			s3c64xx_dma_errirq(dmac, offs);
+			writel(bit, dmac->regs + PL080_ERR_CLEAR);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct sysdev_class dma_sysclass = {
+	.name		= "s3c64xx-dma",
+};
+
+static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
+			     int irq, unsigned int base)
+{
+	struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
+	struct s3c64xx_dmac *dmac;
+	char clkname[16];
+	void __iomem *regs;
+	void __iomem *regptr;
+	int err, ch;
+
+	dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
+	if (!dmac) {
+		printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
+		return -ENOMEM;
+	}
+
+	dmac->sysdev.id = chno / 8;
+	dmac->sysdev.cls = &dma_sysclass;
+
+	err = sysdev_register(&dmac->sysdev);
+	if (err) {
+		printk(KERN_ERR "%s: failed to register sysdevice\n", __func__);
+		goto err_alloc;
+	}
+
+	regs = ioremap(base, 0x200);
+	if (!regs) {
+		printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
+		err = -ENXIO;
+		goto err_dev;
+	}
+
+	snprintf(clkname, sizeof(clkname), "dma%d", dmac->sysdev.id);
+
+	dmac->clk = clk_get(NULL, clkname);
+	if (IS_ERR(dmac->clk)) {
+		printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
+		err = PTR_ERR(dmac->clk);
+		goto err_map;
+	}
+
+	clk_enable(dmac->clk);
+
+	dmac->regs = regs;
+	dmac->chanbase = chbase;
+	dmac->channels = chptr;
+
+	err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
+	if (err < 0) {
+		printk(KERN_ERR "%s: failed to get irq\n", __func__);
+		goto err_clk;
+	}
+
+	regptr = regs + PL080_Cx_BASE(0);
+
+	for (ch = 0; ch < 8; ch++, chno++, chptr++) {
+		printk(KERN_INFO "%s: registering DMA %d (%p)\n",
+		       __func__, chno, regptr);
+
+		chptr->bit = 1 << ch;
+		chptr->number = chno;
+		chptr->dmac = dmac;
+		chptr->regs = regptr;
+		regptr += PL008_Cx_STRIDE;
+	}
+
+	/* for the moment, permanently enable the controller */
+	writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
+
+	printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs);
+
+	return 0;
+
+err_clk:
+	clk_disable(dmac->clk);
+	clk_put(dmac->clk);
+err_map:
+	iounmap(regs);
+err_dev:
+	sysdev_unregister(&dmac->sysdev);
+err_alloc:
+	kfree(dmac);
+	return err;
+}
+
+static int __init s3c64xx_dma_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
+
+	dma_pool = dma_pool_create("DMA-LLI", NULL, 32, 16, 0);
+	if (!dma_pool) {
+		printk(KERN_ERR "%s: failed to create pool\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = sysdev_class_register(&dma_sysclass);
+	if (ret) {
+		printk(KERN_ERR "%s: failed to create sysclass\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* Set all DMA configuration to be DMA, not SDMA */
+	writel(0xffffff, S3C_SYSREG(0x110));
+
+	/* Register standard DMA controlers */
+	s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
+	s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
+
+	return 0;
+}
+
+arch_initcall(s3c64xx_dma_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/gpiolib.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/gpiolib.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/gpiolib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/gpiolib.c	2009-09-09 18:13:59.000000000 -0400
@@ -321,6 +321,11 @@
 	.get_pull	= s3c_gpio_getpull_updown,
 };
 
+int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
+{
+	return IRQ_EINT(0) + pin;
+}
+
 static struct s3c_gpio_chip gpio_2bit[] = {
 	{
 		.base	= S3C64XX_GPF_BASE,
@@ -353,6 +358,7 @@
 			.base	= S3C64XX_GPN(0),
 			.ngpio	= S3C64XX_GPIO_N_NR,
 			.label	= "GPN",
+			.to_irq = s3c64xx_gpio2int_gpn,
 		},
 	}, {
 		.base	= S3C64XX_GPO_BASE,
@@ -385,12 +391,19 @@
 {
 	chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
 	chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
+	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
 }
 
 static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
 {
 	chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
 	chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
+	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
+}
+
+static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
+{
+	chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
 }
 
 static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
@@ -412,7 +425,8 @@
 	s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
 			    s3c64xx_gpiolib_add_4bit2);
 
-	s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL);
+	s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
+			    s3c64xx_gpiolib_add_2bit);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/dma-plat.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/dma-plat.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/dma-plat.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,70 @@
+/* linux/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
+ *
+ * Copyright 2009 Openmoko, Inc.
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX DMA core
+ *
+ * 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.
+*/
+
+#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
+
+struct s3c64xx_dma_buff;
+
+/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
+ * @next: Pointer to next buffer in queue or ring.
+ * @pw: Client provided identifier
+ * @lli: Pointer to hardware descriptor this buffer is associated with.
+ * @lli_dma: Hardare address of the descriptor.
+ */
+struct s3c64xx_dma_buff {
+	struct s3c64xx_dma_buff *next;
+
+	void			*pw;
+	struct pl080_lli	*lli;
+	dma_addr_t		 lli_dma;
+};
+
+struct s3c64xx_dmac;
+
+struct s3c2410_dma_chan {
+	unsigned char		 number;      /* number of this dma channel */
+	unsigned char		 in_use;      /* channel allocated */
+	unsigned char		 bit;	      /* bit for enable/disable/etc */
+	unsigned char		 hw_width;
+	unsigned char		 peripheral;
+
+	unsigned int		 flags;
+	enum s3c2410_dmasrc	 source;
+
+
+	dma_addr_t		dev_addr;
+
+	struct s3c2410_dma_client *client;
+	struct s3c64xx_dmac	*dmac;		/* pointer to controller */
+
+	void __iomem		*regs;
+
+	/* cdriver callbacks */
+	s3c2410_dma_cbfn_t	 callback_fn;	/* buffer done callback */
+	s3c2410_dma_opfn_t	 op_fn;		/* channel op callback */
+
+	/* buffer list and information */
+	struct s3c64xx_dma_buff	*curr;		/* current dma buffer */
+	struct s3c64xx_dma_buff	*next;		/* next buffer to load */
+	struct s3c64xx_dma_buff	*end;		/* end of queue */
+
+	/* note, when channel is running in circular mode, curr is the
+	 * first buffer enqueued, end is the last and curr is where the
+	 * last buffer-done event is set-at. The buffers are not freed
+	 * and the last buffer hardware descriptor points back to the
+	 * first.
+	 */
+};
+
+#include <plat/dma-core.h>
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/irqs.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/irqs.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/irqs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/irqs.h	2009-09-09 18:13:59.000000000 -0400
@@ -157,6 +157,7 @@
 
 #define S3C_EINT(x)		((x) + S3C_IRQ_EINT_BASE)
 #define IRQ_EINT(x)		S3C_EINT(x)
+#define IRQ_EINT_BIT(x)		((x) - S3C_EINT(0))
 
 /* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
  * that they are sourced from the GPIO pins but with a different scheme for
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/pm-core.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/pm-core.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/pm-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/pm-core.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,98 @@
+/* linux/arch/arm/plat-s3c64xx/include/plat/pm-core.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - PM core support for arch/arm/plat-s3c/pm.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.
+ */
+
+#include <plat/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	u32 tmp = __raw_readl(S3C_PCLK_GATE);
+
+	/* As a note, since the S3C64XX UARTs generally have multiple
+	 * clock sources, we simply enable PCLK at the moment and hope
+	 * that the resume settings for the UART are suitable for the
+	 * use with PCLK.
+	 */
+
+	tmp |= S3C_CLKCON_PCLK_UART0;
+	tmp |= S3C_CLKCON_PCLK_UART1;
+	tmp |= S3C_CLKCON_PCLK_UART2;
+	tmp |= S3C_CLKCON_PCLK_UART3;
+
+	__raw_writel(tmp, S3C_PCLK_GATE);
+	udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	/* VIC should have already been taken care of */
+
+	/* clear any pending EINT0 interrupts */
+	__raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+}
+
+/* make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on */
+
+#define s3c_irqwake_eintallow	((1 << 28) - 1)
+#define s3c_irqwake_intallow	(0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+	u32 ucon = __raw_readl(regs + S3C2410_UCON);
+	u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+	u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+	u32 new_ucon;
+	u32 delta;
+
+	/* S3C64XX UART blocks only support level interrupts, so ensure that
+	 * when we restore unused UART blocks we force the level interrupt
+	 * settigs. */
+	save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+	/* We have a constraint on changing the clock type of the UART
+	 * between UCLKx and PCLK, so ensure that when we restore UCON
+	 * that the CLK field is correctly modified if the bootloader
+	 * has changed anything.
+	 */
+	if (ucon_clk != save_clk) {
+		new_ucon = save->ucon;
+		delta = ucon_clk ^ save_clk;
+
+		/* change from UCLKx => wrong PCLK,
+		 * either UCLK can be tested for by a bit-test
+		 * with UCLK0 */
+		if (ucon_clk & S3C6400_UCON_UCLK0 &&
+		    !(save_clk & S3C6400_UCON_UCLK0) &&
+		    delta & S3C6400_UCON_PCLK2) {
+			new_ucon &= ~S3C6400_UCON_UCLK0;
+		} else if (delta == S3C6400_UCON_PCLK2) {
+			/* as an precaution, don't change from
+			 * PCLK2 => PCLK or vice-versa */
+			new_ucon ^= S3C6400_UCON_PCLK2;
+		}
+
+		S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+			  ucon, new_ucon, save->ucon);
+		save->ucon = new_ucon;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/regs-clock.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/regs-clock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/regs-clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #define S3C_HCLK_GATE		S3C_CLKREG(0x30)
 #define S3C_PCLK_GATE		S3C_CLKREG(0x34)
 #define S3C_SCLK_GATE		S3C_CLKREG(0x38)
+#define S3C_MEM0_GATE		S3C_CLKREG(0x3C)
 
 /* CLKDIV0 */
 #define S3C6400_CLKDIV0_MFC_MASK	(0xf << 28)
@@ -87,11 +88,11 @@
 #define S3C6400_CLKDIV2_SPI0_SHIFT	(0)
 
 /* HCLK GATE Registers */
-#define S3C_CLKCON_HCLK_BUS	(1<<30)
-#define S3C_CLKCON_HCLK_SECUR	(1<<29)
-#define S3C_CLKCON_HCLK_SDMA1	(1<<28)
-#define S3C_CLKCON_HCLK_SDMA2	(1<<27)
-#define S3C_CLKCON_HCLK_UHOST	(1<<26)
+#define S3C_CLKCON_HCLK_3DSE	(1<<31)
+#define S3C_CLKCON_HCLK_UHOST	(1<<29)
+#define S3C_CLKCON_HCLK_SECUR	(1<<28)
+#define S3C_CLKCON_HCLK_SDMA1	(1<<27)
+#define S3C_CLKCON_HCLK_SDMA0	(1<<26)
 #define S3C_CLKCON_HCLK_IROM	(1<<25)
 #define S3C_CLKCON_HCLK_DDR1	(1<<24)
 #define S3C_CLKCON_HCLK_DDR0	(1<<23)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/s3c6400.h linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/s3c6400.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/include/plat/s3c6400.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/include/plat/s3c6400.h	2009-09-09 18:13:59.000000000 -0400
@@ -15,12 +15,13 @@
 /* Common init code for S3C6400 related SoCs */
 
 extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s3c6400_register_clocks(void);
+extern void s3c6400_register_clocks(unsigned armclk_divlimit);
 extern void s3c6400_setup_clocks(void);
 
 #ifdef CONFIG_CPU_S3C6400
 
 extern  int s3c6400_init(void);
+extern void s3c6400_init_irq(void);
 extern void s3c6400_map_io(void);
 extern void s3c6400_init_clocks(int xtal);
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/irq.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,12 +14,14 @@
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/serial_core.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 
 #include <asm/hardware/vic.h>
 
 #include <mach/map.h>
+#include <plat/regs-serial.h>
 #include <plat/regs-timer.h>
 #include <plat/cpu.h>
 
@@ -135,9 +137,6 @@
 }
 
 /* UART interrupt registers, not worth adding to seperate include header */
-#define S3C64XX_UINTP	0x30
-#define S3C64XX_UINTSP	0x34
-#define S3C64XX_UINTM	0x38
 
 static void s3c_irq_uart_mask(unsigned int irq)
 {
@@ -233,8 +232,8 @@
 	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
 
 	/* initialise the pair of VICs */
-	vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid);
-	vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid);
+	vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid, 0);
+	vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid, 0);
 
 	/* add the timer sub-irqs */
 
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/irq-eint.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/irq-eint.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/irq-eint.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/irq-eint.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/sysdev.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/io.h>
@@ -26,6 +27,7 @@
 
 #include <mach/map.h>
 #include <plat/cpu.h>
+#include <plat/pm.h>
 
 #define eint_offset(irq)	((irq) - IRQ_EINT(0))
 #define eint_irq_to_bit(irq)	(1 << eint_offset(irq))
@@ -134,6 +136,7 @@
 	.mask_ack	= s3c_irq_eint_maskack,
 	.ack		= s3c_irq_eint_ack,
 	.set_type	= s3c_irq_eint_set_type,
+	.set_wake	= s3c_irqext_wake,
 };
 
 /* s3c_irq_demux_eint
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/irq-pm.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/irq-pm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/irq-pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/irq-pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,111 @@
+/* arch/arm/plat-s3c64xx/irq-pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Interrupt handling Power Management
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-timer.h>
+#include <plat/regs-gpio.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+/* We handled all the IRQ types in this code, to save having to make several
+ * small files to handle each different type separately. Having the EINT_GRP
+ * code here shouldn't be as much bloat as the IRQ table space needed when
+ * they are enabled. The added benefit is we ensure that these registers are
+ * in the same state as we suspended.
+ */
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S3C64XX_PRIORITY),
+	SAVE_ITEM(S3C64XX_EINT0CON0),
+	SAVE_ITEM(S3C64XX_EINT0CON1),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON0),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON1),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON2),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON3),
+	SAVE_ITEM(S3C64XX_EINT0MASK),
+	SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+static struct irq_grp_save {
+	u32	fltcon;
+	u32	con;
+	u32	mask;
+} eint_grp_save[5];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
+		grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
+		grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
+	}
+
+	return 0;
+}
+
+static int s3c64xx_irq_pm_resume(struct sys_device *dev)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		__raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		__raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
+		__raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
+		__raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
+	}
+
+	S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+	return 0;
+}
+
+static struct sysdev_driver s3c64xx_irq_driver = {
+	.suspend = s3c64xx_irq_pm_suspend,
+	.resume	 = s3c64xx_irq_pm_resume,
+};
+
+static int __init s3c64xx_irq_pm_init(void)
+{
+	return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
+}
+
+arch_initcall(s3c64xx_irq_pm_init);
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/Kconfig linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 	select S3C_GPIO_PULL_UPDOWN
 	select S3C_GPIO_CFG_S3C24XX
 	select S3C_GPIO_CFG_S3C64XX
+	select USB_ARCH_HAS_OHCI
 	help
 	  Base platform code for any Samsung S3C64XX device
 
@@ -38,6 +39,10 @@
 	  Common clock support code for the S3C6400 that is shared
 	  by other CPUs in the series, such as the S3C6410.
 
+config S3C64XX_DMA
+	bool "S3C64XX DMA"
+	select S3C_DMA
+
 # platform specific device setup
 
 config S3C64XX_SETUP_I2C0
@@ -59,4 +64,9 @@
 	help
 	  Common setup code for S3C64XX with an 24bpp RGB display helper.
 
+config S3C64XX_SETUP_SDHCI_GPIO
+	bool
+	help
+	  Common setup code for S3C64XX SDHCI GPIO configurations
+
 endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/Makefile linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -23,9 +23,21 @@
 
 obj-$(CONFIG_CPU_S3C6400_INIT)	+= s3c6400-init.o
 obj-$(CONFIG_CPU_S3C6400_CLOCK)	+= s3c6400-clock.o
+obj-$(CONFIG_CPU_FREQ_S3C64XX)  += cpufreq.o
+
+# PM support
+
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= sleep.o
+obj-$(CONFIG_PM)		+= irq-pm.o
+
+# DMA support
+
+obj-$(CONFIG_S3C64XX_DMA)	+= dma.o
 
 # Device setup
 
 obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
 obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
 obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
+obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
\ No newline at end of file
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/pm.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/pm.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,173 @@
+/* linux/arch/arm/plat-s3c64xx/pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU PM support.
+ *
+ * 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.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/pm.h>
+#include <plat/regs-sys.h>
+#include <plat/regs-gpio.h>
+#include <plat/regs-clock.h>
+#include <plat/regs-syscon-power.h>
+#include <plat/regs-gpio-memport.h>
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+#include <plat/gpio-bank-n.h>
+
+void s3c_pm_debug_smdkled(u32 set, u32 clear)
+{
+	unsigned long flags;
+	u32 reg;
+
+	local_irq_save(flags);
+	reg = __raw_readl(S3C64XX_GPNCON);
+	reg &= ~(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) |
+		 S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15));
+	reg |= S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) |
+	       S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15);
+	__raw_writel(reg, S3C64XX_GPNCON);
+
+	reg = __raw_readl(S3C64XX_GPNDAT);
+	reg &= ~(clear << 12);
+	reg |= set << 12;
+	__raw_writel(reg, S3C64XX_GPNDAT);
+
+	local_irq_restore(flags);
+}
+#endif
+
+static struct sleep_save core_save[] = {
+	SAVE_ITEM(S3C_APLL_LOCK),
+	SAVE_ITEM(S3C_MPLL_LOCK),
+	SAVE_ITEM(S3C_EPLL_LOCK),
+	SAVE_ITEM(S3C_CLK_SRC),
+	SAVE_ITEM(S3C_CLK_DIV0),
+	SAVE_ITEM(S3C_CLK_DIV1),
+	SAVE_ITEM(S3C_CLK_DIV2),
+	SAVE_ITEM(S3C_CLK_OUT),
+	SAVE_ITEM(S3C_HCLK_GATE),
+	SAVE_ITEM(S3C_PCLK_GATE),
+	SAVE_ITEM(S3C_SCLK_GATE),
+	SAVE_ITEM(S3C_MEM0_GATE),
+
+	SAVE_ITEM(S3C_EPLL_CON1),
+	SAVE_ITEM(S3C_EPLL_CON0),
+
+	SAVE_ITEM(S3C64XX_MEM0DRVCON),
+	SAVE_ITEM(S3C64XX_MEM1DRVCON),
+
+#ifndef CONFIG_CPU_FREQ
+	SAVE_ITEM(S3C_APLL_CON),
+	SAVE_ITEM(S3C_MPLL_CON),
+#endif
+};
+
+static struct sleep_save misc_save[] = {
+	SAVE_ITEM(S3C64XX_AHB_CON0),
+	SAVE_ITEM(S3C64XX_AHB_CON1),
+	SAVE_ITEM(S3C64XX_AHB_CON2),
+	
+	SAVE_ITEM(S3C64XX_SPCON),
+
+	SAVE_ITEM(S3C64XX_MEM0CONSTOP),
+	SAVE_ITEM(S3C64XX_MEM1CONSTOP),
+	SAVE_ITEM(S3C64XX_MEM0CONSLP0),
+	SAVE_ITEM(S3C64XX_MEM0CONSLP1),
+	SAVE_ITEM(S3C64XX_MEM1CONSLP),
+};
+
+void s3c_pm_configure_extint(void)
+{
+	__raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+	__raw_writel(0, S3C64XX_EINT_MASK);
+
+	s3c_pm_debug_smdkled(1 << 2, 0);
+
+	s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+	s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+	s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
+	s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
+}
+
+/* since both s3c6400 and s3c6410 share the same sleep pm calls, we
+ * put the per-cpu code in here until any new cpu comes along and changes
+ * this.
+ */
+
+static void s3c64xx_cpu_suspend(void)
+{
+	unsigned long tmp;
+
+	/* set our standby method to sleep */
+
+	tmp = __raw_readl(S3C64XX_PWR_CFG);
+	tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
+	tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
+	__raw_writel(tmp, S3C64XX_PWR_CFG);
+
+	/* clear any old wakeup */
+
+	__raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
+		     S3C64XX_WAKEUP_STAT);
+
+	/* set the LED state to 0110 over sleep */
+	s3c_pm_debug_smdkled(3 << 1, 0xf);
+
+	/* issue the standby signal into the pm unit. Note, we
+	 * issue a write-buffer drain just in case */
+
+	tmp = 0;
+
+	asm("b 1f\n\t"
+	    ".align 5\n\t"
+	    "1:\n\t"
+	    "mcr p15, 0, %0, c7, c10, 5\n\t"
+	    "mcr p15, 0, %0, c7, c10, 4\n\t"
+	    "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
+
+	/* we should never get past here */
+
+	panic("sleep resumed to originator?");
+}
+
+static void s3c64xx_pm_prepare(void)
+{
+	/* store address of resume. */
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
+
+	/* ensure previous wakeup state is cleared before sleeping */
+	__raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
+}
+
+static int s3c64xx_pm_init(void)
+{
+	pm_cpu_prep = s3c64xx_pm_prepare;
+	pm_cpu_sleep = s3c64xx_cpu_suspend;
+	pm_uart_udivslot = 1;
+	return 0;
+}
+
+arch_initcall(s3c64xx_pm_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/s3c6400-clock.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/s3c6400-clock.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/s3c6400-clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/s3c6400-clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,6 +133,65 @@
 	.sources	= &clk_src_mpll,
 };
 
+static unsigned int armclk_mask;
+
+static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+	u32 clkdiv;
+
+	/* divisor mask starts at bit0, so no need to shift */
+	clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
+
+	return rate / (clkdiv + 1);
+}
+
+static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
+						unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	u32 div;
+
+	if (parent < rate)
+		return parent;
+
+	div = (parent / rate) - 1;
+	if (div > armclk_mask)
+		div = armclk_mask;
+
+	return parent / (div + 1);
+}
+
+static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	u32 div;
+	u32 val;
+
+	if (rate < parent / (armclk_mask + 1))
+		return -EINVAL;
+
+	rate = clk_round_rate(clk, rate);
+	div = clk_get_rate(clk->parent) / rate;
+
+	val = __raw_readl(S3C_CLK_DIV0);
+	val &= ~armclk_mask;
+	val |= (div - 1);
+	__raw_writel(val, S3C_CLK_DIV0);
+
+	return 0;
+
+}
+
+static struct clk clk_arm = {
+	.name		= "armclk",
+	.id		= -1,
+	.parent		= &clk_mout_apll.clk,
+	.get_rate	= s3c64xx_clk_arm_get_rate,
+	.set_rate	= s3c64xx_clk_arm_set_rate,
+	.round_rate	= s3c64xx_clk_arm_round_rate,
+};
+
 static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
 {
 	unsigned long rate = clk_get_rate(clk->parent);
@@ -520,6 +579,33 @@
 	.reg_divider	= S3C_CLK_DIV2,
 };
 
+static struct clk *clkset_camif_list[] = {
+	&clk_h2,
+};
+
+static struct clk_sources clkset_camif = {
+	.sources	= clkset_camif_list,
+	.nr_sources	= ARRAY_SIZE(clkset_camif_list),
+};
+
+static struct clksrc_clk clk_camif = {
+	.clk	= {
+		.name		= "camera",
+		.id		= -1,
+		.ctrlbit        = S3C_CLKCON_SCLK_CAM,
+		.enable		= s3c64xx_sclk_ctrl,
+		.set_parent	= s3c64xx_setparent_clksrc,
+		.get_rate	= s3c64xx_getrate_clksrc,
+		.set_rate	= s3c64xx_setrate_clksrc,
+		.round_rate	= s3c64xx_roundrate_clksrc,
+	},
+	.shift		= 0,
+	.mask		= 0,
+	.sources	= &clkset_camif,
+	.divider_shift	= S3C6400_CLKDIV0_CAM_SHIFT,
+	.reg_divider	= S3C_CLK_DIV0,
+};
+
 /* Clock initialisation code */
 
 static struct clksrc_clk *init_parents[] = {
@@ -536,6 +622,7 @@
 	&clk_audio0,
 	&clk_audio1,
 	&clk_irda,
+	&clk_camif,
 };
 
 static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk)
@@ -608,6 +695,7 @@
 	clk_fout_epll.rate = epll;
 	clk_fout_apll.rate = apll;
 
+	clk_h2.rate = hclk2;
 	clk_h.rate = hclk;
 	clk_p.rate = pclk;
 	clk_f.rate = fclk;
@@ -635,14 +723,30 @@
 	&clk_audio0.clk,
 	&clk_audio1.clk,
 	&clk_irda.clk,
+	&clk_camif.clk,
+	&clk_arm,
 };
 
-void __init s3c6400_register_clocks(void)
+/**
+ * s3c6400_register_clocks - register clocks for s3c6400 and above
+ * @armclk_divlimit: Divisor mask for ARMCLK
+ *
+ * Register the clocks for the S3C6400 and above SoC range, such
+ * as ARMCLK and the clocks which have divider chains attached.
+ *
+ * This call does not setup the clocks, which is left to the
+ * s3c6400_setup_clocks() call which may be needed by the cpufreq
+ * or resume code to re-set the clocks if the bootloader has changed
+ * them.
+ */
+void __init s3c6400_register_clocks(unsigned armclk_divlimit)
 {
 	struct clk *clkp;
 	int ret;
 	int ptr;
 
+	armclk_mask = armclk_divlimit;
+
 	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
 		clkp = clks[ptr];
 		ret = s3c24xx_register_clock(clkp);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,55 @@
+/* linux/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+
+void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
+{
+	unsigned int gpio;
+	unsigned int end;
+
+	end = S3C64XX_GPG(2 + width);
+
+	/* Set all the necessary GPG pins to special-function 0 */
+	for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+	}
+
+	s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
+}
+
+void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
+{
+	unsigned int gpio;
+	unsigned int end;
+
+	end = S3C64XX_GPH(2 + width);
+
+	/* Set all the necessary GPG pins to special-function 0 */
+	for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+	}
+
+	s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
+	s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/sleep.S linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/sleep.S
--- linux-libre-2.6.30-gnu/arch/arm/plat-s3c64xx/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-s3c64xx/sleep.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,144 @@
+/* linux/0arch/arm/plat-s3c64xx/sleep.S
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU sleep code
+ *
+ * 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.
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/map.h>
+
+#undef S3C64XX_VA_GPIO
+#define S3C64XX_VA_GPIO (0x0)
+
+#include <plat/regs-gpio.h>
+#include <plat/gpio-bank-n.h>
+
+#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
+
+	.text
+
+	/* s3c_cpu_save
+	 *
+	 * Save enough processor state to allow the restart of the pm.c
+	 * code after resume.
+	 *
+	 * entry:
+	 *	r0 = pointer to the save block
+	*/
+
+ENTRY(s3c_cpu_save)
+	stmfd	sp!, { r4 - r12, lr }
+
+	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
+	mrc	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
+	mrc	p15, 0, r8, c2, c0, 2	@ Translation Table Control
+	mrc	p15, 0, r9, c1, c0, 0	@ Control register
+	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
+
+	stmia	r0, { r4 - r13 }	@ Save CP registers and SP
+
+	@@ save our state to ram
+	bl	s3c_pm_cb_flushcache
+
+	@@ call final suspend code
+	ldr	r0, =pm_cpu_sleep
+	ldr	pc, [r0]
+	
+	@@ return to the caller, after the MMU is turned on.
+	@@ restore the last bits of the stack and return.
+resume_with_mmu:
+	ldmfd	sp!, { r4 - r12, pc }	@ return, from sp from s3c_cpu_save
+
+	.data
+
+	/* the next bit is code, but it requires easy access to the
+	 * s3c_sleep_save_phys data before the MMU is switched on, so
+	 * we store the code that needs this variable in the .data where
+	 * the value can be written to (the .text segment is RO).
+	*/
+
+	.global	s3c_sleep_save_phys
+s3c_sleep_save_phys:
+	.word	0
+
+	/* Sleep magic, the word before the resume entry point so that the
+	 * bootloader can check for a resumeable image. */
+
+	.word	0x2bedf00d
+
+	/* s3c_cpu_reusme
+	 *
+	 * This is the entry point, stored by whatever method the bootloader
+	 * requires to get the kernel runnign again. This code expects to be
+	 * entered with no caches live and the MMU disabled. It will then
+	 * restore the MMU and other basic CP registers saved and restart
+	 * the kernel C code to finish the resume code.
+	*/
+
+ENTRY(s3c_cpu_resume)
+	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+	ldr	r2, =LL_UART		/* for debug */
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+	/* Initialise the GPIO state if we are debugging via the SMDK LEDs,
+	 * as the uboot version supplied resets these to inputs during the
+	 * resume checks.
+	*/
+
+	ldr	r3, =S3C64XX_PA_GPIO
+	ldr	r0, [ r3, #S3C64XX_GPNCON ]
+	bic	r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
+			  S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
+	orr	r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
+			  S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
+	str	r0, [ r3, #S3C64XX_GPNCON ]
+
+	ldr	r0, [ r3, #S3C64XX_GPNDAT ]
+	bic	r0, r0, #0xf << 12			@ GPN12..15
+	orr	r0, r0, #1 << 15			@ GPN15
+	str	r0, [ r3, #S3C64XX_GPNDAT ]
+#endif
+
+	/* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
+	 * are thoroughly cleaned just in case the bootloader didn't do it
+	 * for us. */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c14, 0		@ clean+invalidate D cache
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c15, 0		@ clean+invalidate cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	@@mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
+	@@mcr	p15, 0, r0, c7, c7, 0		@ Invalidate I + D caches
+
+	ldr	r0, s3c_sleep_save_phys
+	ldmia	r0, { r4 - r13 }
+
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
+	mcr	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
+	mcr	p15, 0, r8, c2, c0, 2	@ Translation Table Control
+	mcr	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
+
+	mov	r0, #0			@ restore copro access controls
+	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
+	mcr 	p15, 0, r0, c7, c5, 4
+
+	ldr	r2, =resume_with_mmu
+	mcr	p15, 0, r9, c1, c0, 0		/* turn mmu back on */
+	nop
+	mov	pc, r2				/* jump back */
+
+	.end
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/clock.c linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/clock.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1135 @@
+/*
+ * Clock manipulation routines for Freescale STMP37XX/STMP378X
+ *
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/clkdev.h>
+#include <mach/platform.h>
+#include <mach/regs-clkctrl.h>
+
+#include "clock.h"
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+static struct clk osc_24M;
+static struct clk pll_clk;
+static struct clk cpu_clk;
+static struct clk hclk;
+
+static int propagate_rate(struct clk *);
+
+static inline int clk_is_busy(struct clk *clk)
+{
+	return __raw_readl(clk->busy_reg) & (1 << clk->busy_bit);
+}
+
+static inline int clk_good(struct clk *clk)
+{
+	return clk && !IS_ERR(clk) && clk->ops;
+}
+
+static int std_clk_enable(struct clk *clk)
+{
+	if (clk->enable_reg) {
+		u32 clk_reg = __raw_readl(clk->enable_reg);
+		if (clk->enable_negate)
+			clk_reg &= ~(1 << clk->enable_shift);
+		else
+			clk_reg |= (1 << clk->enable_shift);
+		__raw_writel(clk_reg, clk->enable_reg);
+		if (clk->enable_wait)
+			udelay(clk->enable_wait);
+		return 0;
+	} else
+		return -EINVAL;
+}
+
+static int std_clk_disable(struct clk *clk)
+{
+	if (clk->enable_reg) {
+		u32 clk_reg = __raw_readl(clk->enable_reg);
+		if (clk->enable_negate)
+			clk_reg |= (1 << clk->enable_shift);
+		else
+			clk_reg &= ~(1 << clk->enable_shift);
+		__raw_writel(clk_reg, clk->enable_reg);
+		return 0;
+	} else
+		return -EINVAL;
+}
+
+static int io_set_rate(struct clk *clk, u32 rate)
+{
+	u32 reg_frac, clkctrl_frac;
+	int i, ret = 0, mask = 0x1f;
+
+	clkctrl_frac = (clk->parent->rate * 18 + rate - 1) / rate;
+
+	if (clkctrl_frac < 18 || clkctrl_frac > 35) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	reg_frac = __raw_readl(clk->scale_reg);
+	reg_frac &= ~(mask << clk->scale_shift);
+	__raw_writel(reg_frac | (clkctrl_frac << clk->scale_shift),
+				clk->scale_reg);
+	if (clk->busy_reg) {
+		for (i = 10000; i; i--)
+			if (!clk_is_busy(clk))
+				break;
+		if (!i)
+			ret = -ETIMEDOUT;
+		else
+			ret = 0;
+	}
+out:
+	return ret;
+}
+
+static long io_get_rate(struct clk *clk)
+{
+	long rate = clk->parent->rate * 18;
+	int mask = 0x1f;
+
+	rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask;
+	clk->rate = rate;
+
+	return rate;
+}
+
+static long per_get_rate(struct clk *clk)
+{
+	long rate = clk->parent->rate;
+	long div;
+	const int mask = 0xff;
+
+	if (clk->enable_reg &&
+			!(__raw_readl(clk->enable_reg) & clk->enable_shift))
+		clk->rate = 0;
+	else {
+		div = (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask;
+		if (div)
+			rate /= div;
+		clk->rate = rate;
+	}
+
+	return clk->rate;
+}
+
+static int per_set_rate(struct clk *clk, u32 rate)
+{
+	int ret = -EINVAL;
+	int div = (clk->parent->rate + rate - 1) / rate;
+	u32 reg_frac;
+	const int mask = 0xff;
+	int try = 10;
+	int i = -1;
+
+	if (div == 0 || div > mask)
+		goto out;
+
+	reg_frac = __raw_readl(clk->scale_reg);
+	reg_frac &= ~(mask << clk->scale_shift);
+
+	while (try--) {
+		__raw_writel(reg_frac | (div << clk->scale_shift),
+				clk->scale_reg);
+
+		if (clk->busy_reg) {
+			for (i = 10000; i; i--)
+				if (!clk_is_busy(clk))
+					break;
+		}
+		if (i)
+			break;
+	}
+
+	if (!i)
+		ret = -ETIMEDOUT;
+	else
+		ret = 0;
+
+out:
+	if (ret != 0)
+		printk(KERN_ERR "%s: error %d\n", __func__, ret);
+	return ret;
+}
+
+static long lcdif_get_rate(struct clk *clk)
+{
+	long rate = clk->parent->rate;
+	long div;
+	const int mask = 0xff;
+
+	div = (__raw_readl(clk->scale_reg) >> clk->scale_shift) & mask;
+	if (div) {
+		rate /= div;
+		div = (__raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC) &
+			BM_CLKCTRL_FRAC_PIXFRAC) >> BP_CLKCTRL_FRAC_PIXFRAC;
+		rate /= div;
+	}
+	clk->rate = rate;
+
+	return rate;
+}
+
+static int lcdif_set_rate(struct clk *clk, u32 rate)
+{
+	int ret = 0;
+	/*
+	 * On 3700, we can get most timings exact by modifying ref_pix
+	 * and the divider, but keeping the phase timings at 1 (2
+	 * phases per cycle).
+	 *
+	 * ref_pix can be between 480e6*18/35=246.9MHz and 480e6*18/18=480MHz,
+	 * which is between 18/(18*480e6)=2.084ns and 35/(18*480e6)=4.050ns.
+	 *
+	 * ns_cycle >= 2*18e3/(18*480) = 25/6
+	 * ns_cycle <= 2*35e3/(18*480) = 875/108
+	 *
+	 * Multiply the ns_cycle by 'div' to lengthen it until it fits the
+	 * bounds. This is the divider we'll use after ref_pix.
+	 *
+	 * 6 * ns_cycle >= 25 * div
+	 * 108 * ns_cycle <= 875 * div
+	 */
+	u32 ns_cycle = 1000000 / rate;
+	u32 div, reg_val;
+	u32 lowest_result = (u32) -1;
+	u32 lowest_div = 0, lowest_fracdiv = 0;
+
+	for (div = 1; div < 256; ++div) {
+		u32 fracdiv;
+		u32 ps_result;
+		int lower_bound = 6 * ns_cycle >= 25 * div;
+		int upper_bound = 108 * ns_cycle <= 875 * div;
+		if (!lower_bound)
+			break;
+		if (!upper_bound)
+			continue;
+		/*
+		 * Found a matching div. Calculate fractional divider needed,
+		 * rounded up.
+		 */
+		fracdiv = ((clk->parent->rate / 1000 * 18 / 2) *
+				ns_cycle + 1000 * div - 1) /
+				(1000 * div);
+		if (fracdiv < 18 || fracdiv > 35) {
+			ret = -EINVAL;
+			goto out;
+		}
+		/* Calculate the actual cycle time this results in */
+		ps_result = 6250 * div * fracdiv / 27;
+
+		/* Use the fastest result that doesn't break ns_cycle */
+		if (ps_result <= lowest_result) {
+			lowest_result = ps_result;
+			lowest_div = div;
+			lowest_fracdiv = fracdiv;
+		}
+	}
+
+	if (div >= 256 || lowest_result == (u32) -1) {
+		ret = -EINVAL;
+		goto out;
+	}
+	pr_debug("Programming PFD=%u,DIV=%u ref_pix=%uMHz "
+			"PIXCLK=%uMHz cycle=%u.%03uns\n",
+			lowest_fracdiv, lowest_div,
+			480*18/lowest_fracdiv, 480*18/lowest_fracdiv/lowest_div,
+			lowest_result / 1000, lowest_result % 1000);
+
+	/* Program ref_pix phase fractional divider */
+	reg_val = __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC);
+	reg_val &= ~BM_CLKCTRL_FRAC_PIXFRAC;
+	reg_val |= BF(lowest_fracdiv, CLKCTRL_FRAC_PIXFRAC);
+	__raw_writel(reg_val, REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC);
+
+	/* Ungate PFD */
+	stmp3xxx_clearl(BM_CLKCTRL_FRAC_CLKGATEPIX,
+			REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC);
+
+	/* Program pix divider */
+	reg_val = __raw_readl(clk->scale_reg);
+	reg_val &= ~(BM_CLKCTRL_PIX_DIV | BM_CLKCTRL_PIX_CLKGATE);
+	reg_val |= BF(lowest_div, CLKCTRL_PIX_DIV);
+	__raw_writel(reg_val, clk->scale_reg);
+
+	/* Wait for divider update */
+	if (clk->busy_reg) {
+		int i;
+		for (i = 10000; i; i--)
+			if (!clk_is_busy(clk))
+				break;
+		if (!i) {
+			ret = -ETIMEDOUT;
+			goto out;
+		}
+	}
+
+	/* Switch to ref_pix source */
+	reg_val = __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ);
+	reg_val &= ~BM_CLKCTRL_CLKSEQ_BYPASS_PIX;
+	__raw_writel(reg_val, REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ);
+
+out:
+	return ret;
+}
+
+
+static int cpu_set_rate(struct clk *clk, u32 rate)
+{
+	u32 reg_val;
+
+	if (rate < 24000)
+		return -EINVAL;
+	else if (rate == 24000) {
+		/* switch to the 24M source */
+		clk_set_parent(clk, &osc_24M);
+	} else {
+		int i;
+		u32 clkctrl_cpu = 1;
+		u32 c = clkctrl_cpu;
+		u32 clkctrl_frac = 1;
+		u32 val;
+		for ( ; c < 0x40; c++) {
+			u32 f = (pll_clk.rate*18/c + rate/2) / rate;
+			int s1, s2;
+
+			if (f < 18 || f > 35)
+				continue;
+			s1 = pll_clk.rate*18/clkctrl_frac/clkctrl_cpu - rate;
+			s2 = pll_clk.rate*18/c/f - rate;
+			pr_debug("%s: s1 %d, s2 %d\n", __func__, s1, s2);
+			if (abs(s1) > abs(s2)) {
+				clkctrl_cpu = c;
+				clkctrl_frac = f;
+			}
+			if (s2 == 0)
+				break;
+		};
+		pr_debug("%s: clkctrl_cpu %d, clkctrl_frac %d\n", __func__,
+				clkctrl_cpu, clkctrl_frac);
+		if (c == 0x40) {
+			int  d = pll_clk.rate*18/clkctrl_frac/clkctrl_cpu -
+				rate;
+			if (abs(d) > 100 ||
+			    clkctrl_frac < 18 || clkctrl_frac > 35)
+				return -EINVAL;
+		}
+
+		/* 4.6.2 */
+		val = __raw_readl(clk->scale_reg);
+		val &= ~(0x3f << clk->scale_shift);
+		val |= clkctrl_frac;
+		clk_set_parent(clk, &osc_24M);
+		udelay(10);
+		__raw_writel(val, clk->scale_reg);
+		/* ungate */
+		__raw_writel(1<<7, clk->scale_reg + 8);
+		/* write clkctrl_cpu */
+		clk->saved_div = clkctrl_cpu;
+
+		reg_val = __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU);
+		reg_val &= ~0x3F;
+		reg_val |= clkctrl_cpu;
+		__raw_writel(reg_val, REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU);
+
+		for (i = 10000; i; i--)
+			if (!clk_is_busy(clk))
+				break;
+		if (!i) {
+			printk(KERN_ERR "couldn't set up CPU divisor\n");
+			return -ETIMEDOUT;
+		}
+		clk_set_parent(clk, &pll_clk);
+		clk->saved_div = 0;
+		udelay(10);
+	}
+	return 0;
+}
+
+static long cpu_get_rate(struct clk *clk)
+{
+	long rate = clk->parent->rate * 18;
+
+	rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & 0x3f;
+	rate /= __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU) & 0x3f;
+	rate = ((rate + 9) / 10) * 10;
+	clk->rate = rate;
+
+	return rate;
+}
+
+static long cpu_round_rate(struct clk *clk, u32 rate)
+{
+	unsigned long r = 0;
+
+	if (rate <= 24000)
+		r = 24000;
+	else {
+		u32 clkctrl_cpu = 1;
+		u32 clkctrl_frac;
+		do {
+			clkctrl_frac =
+				(pll_clk.rate*18 / clkctrl_cpu + rate/2) / rate;
+			if (clkctrl_frac > 35)
+				continue;
+			if (pll_clk.rate*18 / clkctrl_frac / clkctrl_cpu/10 ==
+			    rate / 10)
+				break;
+		} while (pll_clk.rate / 2  >= clkctrl_cpu++ * rate);
+		if (pll_clk.rate / 2 < (clkctrl_cpu - 1) * rate)
+			clkctrl_cpu--;
+		pr_debug("%s: clkctrl_cpu %d, clkctrl_frac %d\n", __func__,
+				clkctrl_cpu, clkctrl_frac);
+		if (clkctrl_frac < 18)
+			clkctrl_frac = 18;
+		if (clkctrl_frac > 35)
+			clkctrl_frac = 35;
+
+		r = pll_clk.rate * 18;
+		r /= clkctrl_frac;
+		r /= clkctrl_cpu;
+		r = 10 * ((r + 9) / 10);
+	}
+	return r;
+}
+
+static long emi_get_rate(struct clk *clk)
+{
+	long rate = clk->parent->rate * 18;
+
+	rate /= (__raw_readl(clk->scale_reg) >> clk->scale_shift) & 0x3f;
+	rate /= __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI) & 0x3f;
+	clk->rate = rate;
+
+	return rate;
+}
+
+static int clkseq_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -EINVAL;
+	int shift = 8;
+
+	/* bypass? */
+	if (parent == &osc_24M)
+		shift = 4;
+
+	if (clk->bypass_reg) {
+#ifdef CONFIG_ARCH_STMP378X
+		u32 hbus_val, cpu_val;
+
+		if (clk == &cpu_clk && shift == 4) {
+			hbus_val = __raw_readl(REGS_CLKCTRL_BASE +
+					HW_CLKCTRL_HBUS);
+			cpu_val = __raw_readl(REGS_CLKCTRL_BASE +
+					HW_CLKCTRL_CPU);
+
+			hbus_val &= ~(BM_CLKCTRL_HBUS_DIV_FRAC_EN |
+				      BM_CLKCTRL_HBUS_DIV);
+			clk->saved_div = cpu_val & BM_CLKCTRL_CPU_DIV_CPU;
+			cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU;
+			cpu_val |= 1;
+
+			if (machine_is_stmp378x()) {
+				__raw_writel(hbus_val,
+					REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS);
+				__raw_writel(cpu_val,
+					REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU);
+				hclk.rate = 0;
+			}
+		} else if (clk == &cpu_clk && shift == 8) {
+			hbus_val = __raw_readl(REGS_CLKCTRL_BASE +
+							HW_CLKCTRL_HBUS);
+			cpu_val = __raw_readl(REGS_CLKCTRL_BASE +
+							HW_CLKCTRL_CPU);
+			hbus_val &= ~(BM_CLKCTRL_HBUS_DIV_FRAC_EN |
+				      BM_CLKCTRL_HBUS_DIV);
+			hbus_val |= 2;
+			cpu_val &= ~BM_CLKCTRL_CPU_DIV_CPU;
+			if (clk->saved_div)
+				cpu_val |= clk->saved_div;
+			else
+				cpu_val |= 2;
+
+			if (machine_is_stmp378x()) {
+				__raw_writel(hbus_val,
+					REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS);
+				__raw_writel(cpu_val,
+					REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU);
+				hclk.rate = 0;
+			}
+		}
+#endif
+		__raw_writel(1 << clk->bypass_shift, clk->bypass_reg + shift);
+
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int hbus_set_rate(struct clk *clk, u32 rate)
+{
+	u8 div = 0;
+	int is_frac = 0;
+	u32 clkctrl_hbus;
+	struct clk *parent = clk->parent;
+
+	pr_debug("%s: rate %d, parent rate %d\n", __func__, rate,
+			parent->rate);
+
+	if (rate > parent->rate)
+		return -EINVAL;
+
+	if (((parent->rate + rate/2) / rate) * rate != parent->rate &&
+	    parent->rate / rate < 32) {
+		pr_debug("%s: switching to fractional mode\n", __func__);
+		is_frac = 1;
+	}
+
+	if (is_frac)
+		div = (32 * rate + parent->rate / 2) / parent->rate;
+	else
+		div = (parent->rate + rate - 1) / rate;
+	pr_debug("%s: div calculated is %d\n", __func__, div);
+	if (!div || div > 0x1f)
+		return -EINVAL;
+
+	clk_set_parent(&cpu_clk, &osc_24M);
+	udelay(10);
+	clkctrl_hbus = __raw_readl(clk->scale_reg);
+	clkctrl_hbus &= ~0x3f;
+	clkctrl_hbus |= div;
+	clkctrl_hbus |= (is_frac << 5);
+
+	__raw_writel(clkctrl_hbus, clk->scale_reg);
+	if (clk->busy_reg) {
+		int i;
+		for (i = 10000; i; i--)
+			if (!clk_is_busy(clk))
+				break;
+		if (!i) {
+			printk(KERN_ERR "couldn't set up CPU divisor\n");
+			return -ETIMEDOUT;
+		}
+	}
+	clk_set_parent(&cpu_clk, &pll_clk);
+	__raw_writel(clkctrl_hbus, clk->scale_reg);
+	udelay(10);
+	return 0;
+}
+
+static long hbus_get_rate(struct clk *clk)
+{
+	long rate = clk->parent->rate;
+
+	if (__raw_readl(clk->scale_reg) & 0x20) {
+		rate *= __raw_readl(clk->scale_reg) & 0x1f;
+		rate /= 32;
+	} else
+		rate /= __raw_readl(clk->scale_reg) & 0x1f;
+	clk->rate = rate;
+
+	return rate;
+}
+
+static int xbus_set_rate(struct clk *clk, u32 rate)
+{
+	u16 div = 0;
+	u32 clkctrl_xbus;
+
+	pr_debug("%s: rate %d, parent rate %d\n", __func__, rate,
+			clk->parent->rate);
+
+	div = (clk->parent->rate + rate - 1) / rate;
+	pr_debug("%s: div calculated is %d\n", __func__, div);
+	if (!div || div > 0x3ff)
+		return -EINVAL;
+
+	clkctrl_xbus = __raw_readl(clk->scale_reg);
+	clkctrl_xbus &= ~0x3ff;
+	clkctrl_xbus |= div;
+	__raw_writel(clkctrl_xbus, clk->scale_reg);
+	if (clk->busy_reg) {
+		int i;
+		for (i = 10000; i; i--)
+			if (!clk_is_busy(clk))
+				break;
+		if (!i) {
+			printk(KERN_ERR "couldn't set up xbus divisor\n");
+			return -ETIMEDOUT;
+		}
+	}
+	return 0;
+}
+
+static long xbus_get_rate(struct clk *clk)
+{
+	long rate = clk->parent->rate;
+
+	rate /= __raw_readl(clk->scale_reg) & 0x3ff;
+	clk->rate = rate;
+
+	return rate;
+}
+
+
+/* Clock ops */
+
+static struct clk_ops std_ops = {
+	.enable		= std_clk_enable,
+	.disable	= std_clk_disable,
+	.get_rate	= per_get_rate,
+	.set_rate	= per_set_rate,
+	.set_parent	= clkseq_set_parent,
+};
+
+static struct clk_ops min_ops = {
+	.enable		= std_clk_enable,
+	.disable	= std_clk_disable,
+};
+
+static struct clk_ops cpu_ops = {
+	.enable		= std_clk_enable,
+	.disable	= std_clk_disable,
+	.get_rate	= cpu_get_rate,
+	.set_rate	= cpu_set_rate,
+	.round_rate	= cpu_round_rate,
+	.set_parent	= clkseq_set_parent,
+};
+
+static struct clk_ops io_ops = {
+	.enable		= std_clk_enable,
+	.disable	= std_clk_disable,
+	.get_rate	= io_get_rate,
+	.set_rate	= io_set_rate,
+};
+
+static struct clk_ops hbus_ops = {
+	.get_rate	= hbus_get_rate,
+	.set_rate	= hbus_set_rate,
+};
+
+static struct clk_ops xbus_ops = {
+	.get_rate	= xbus_get_rate,
+	.set_rate	= xbus_set_rate,
+};
+
+static struct clk_ops lcdif_ops = {
+	.enable		= std_clk_enable,
+	.disable	= std_clk_disable,
+	.get_rate	= lcdif_get_rate,
+	.set_rate	= lcdif_set_rate,
+	.set_parent	= clkseq_set_parent,
+};
+
+static struct clk_ops emi_ops = {
+	.get_rate	= emi_get_rate,
+};
+
+/* List of on-chip clocks */
+
+static struct clk osc_24M = {
+	.flags		= FIXED_RATE | ENABLED,
+	.rate		= 24000,
+};
+
+static struct clk pll_clk = {
+	.parent		= &osc_24M,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0,
+	.enable_shift	= 16,
+	.enable_wait	= 10,
+	.flags		= FIXED_RATE | ENABLED,
+	.rate		= 480000,
+	.ops		= &min_ops,
+};
+
+static struct clk cpu_clk = {
+	.parent		= &pll_clk,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC,
+	.scale_shift	= 0,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 7,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CPU,
+	.busy_bit	= 28,
+	.flags		= RATE_PROPAGATES | ENABLED,
+	.ops		= &cpu_ops,
+};
+
+static struct clk io_clk = {
+	.parent		= &pll_clk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC,
+	.scale_shift	= 24,
+	.flags		= RATE_PROPAGATES | ENABLED,
+	.ops		= &io_ops,
+};
+
+static struct clk hclk = {
+	.parent		= &cpu_clk,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 7,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS,
+	.busy_bit	= 29,
+	.flags		= RATE_PROPAGATES | ENABLED,
+	.ops		= &hbus_ops,
+};
+
+static struct clk xclk = {
+	.parent		= &osc_24M,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XBUS,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XBUS,
+	.busy_bit	= 31,
+	.flags		= RATE_PROPAGATES | ENABLED,
+	.ops		= &xbus_ops,
+};
+
+static struct clk uart_clk = {
+	.parent		= &xclk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.flags		= ENABLED,
+	.ops		= &min_ops,
+};
+
+static struct clk audio_clk = {
+	.parent		= &xclk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL,
+	.enable_shift	= 30,
+	.enable_negate	= 1,
+	.ops		= &min_ops,
+};
+
+static struct clk pwm_clk = {
+	.parent		= &xclk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL,
+	.enable_shift	= 29,
+	.enable_negate	= 1,
+	.ops		= &min_ops,
+};
+
+static struct clk dri_clk = {
+	.parent		= &xclk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL,
+	.enable_shift	= 28,
+	.enable_negate	= 1,
+	.ops		= &min_ops,
+};
+
+static struct clk digctl_clk = {
+	.parent		= &xclk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL,
+	.enable_shift	= 27,
+	.enable_negate	= 1,
+	.ops		= &min_ops,
+};
+
+static struct clk timer_clk = {
+	.parent		= &xclk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL,
+	.enable_shift	= 26,
+	.enable_negate	= 1,
+	.flags		= ENABLED,
+	.ops		= &min_ops,
+};
+
+static struct clk lcdif_clk = {
+	.parent		= &pll_clk,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_PIX,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_PIX,
+	.busy_bit	= 29,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_PIX,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 1,
+	.flags		= NEEDS_SET_PARENT,
+	.ops		= &lcdif_ops,
+};
+
+static struct clk ssp_clk = {
+	.parent		= &io_clk,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_SSP,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_SSP,
+	.busy_bit	= 29,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_SSP,
+	.enable_shift	= 31,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 5,
+	.enable_negate	= 1,
+	.flags		= NEEDS_SET_PARENT,
+	.ops		= &std_ops,
+};
+
+static struct clk gpmi_clk = {
+	.parent		= &io_clk,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI,
+	.busy_bit	= 29,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_GPMI,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 4,
+	.flags		= NEEDS_SET_PARENT,
+	.ops		= &std_ops,
+};
+
+static struct clk spdif_clk = {
+	.parent		= &pll_clk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_SPDIF,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.ops		= &min_ops,
+};
+
+static struct clk emi_clk = {
+	.parent		= &pll_clk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_FRAC,
+	.scale_shift	= 8,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_EMI,
+	.busy_bit	= 28,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 6,
+	.flags		= ENABLED,
+	.ops		= &emi_ops,
+};
+
+static struct clk ir_clk = {
+	.parent		= &io_clk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_IR,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 3,
+	.ops		= &min_ops,
+};
+
+static struct clk saif_clk = {
+	.parent		= &pll_clk,
+	.scale_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_SAIF,
+	.busy_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_SAIF,
+	.busy_bit	= 29,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_SAIF,
+	.enable_shift	= 31,
+	.enable_negate	= 1,
+	.bypass_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ,
+	.bypass_shift	= 0,
+	.ops		= &std_ops,
+};
+
+static struct clk usb_clk = {
+	.parent		= &pll_clk,
+	.enable_reg	= REGS_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0,
+	.enable_shift	= 18,
+	.enable_negate	= 1,
+	.ops		= &min_ops,
+};
+
+/* list of all the clocks */
+static struct clk_lookup onchip_clks[] = {
+	{
+		.con_id = "osc_24M",
+		.clk = &osc_24M,
+	}, {
+		.con_id = "pll",
+		.clk = &pll_clk,
+	}, {
+		.con_id = "cpu",
+		.clk = &cpu_clk,
+	}, {
+		.con_id = "hclk",
+		.clk = &hclk,
+	}, {
+		.con_id = "xclk",
+		.clk = &xclk,
+	}, {
+		.con_id = "io",
+		.clk = &io_clk,
+	}, {
+		.con_id = "uart",
+		.clk = &uart_clk,
+	}, {
+		.con_id = "audio",
+		.clk = &audio_clk,
+	}, {
+		.con_id = "pwm",
+		.clk = &pwm_clk,
+	}, {
+		.con_id = "dri",
+		.clk = &dri_clk,
+	}, {
+		.con_id = "digctl",
+		.clk = &digctl_clk,
+	}, {
+		.con_id = "timer",
+		.clk = &timer_clk,
+	}, {
+		.con_id = "lcdif",
+		.clk = &lcdif_clk,
+	}, {
+		.con_id = "ssp",
+		.clk = &ssp_clk,
+	}, {
+		.con_id = "gpmi",
+		.clk = &gpmi_clk,
+	}, {
+		.con_id = "spdif",
+		.clk = &spdif_clk,
+	}, {
+		.con_id = "emi",
+		.clk = &emi_clk,
+	}, {
+		.con_id = "ir",
+		.clk = &ir_clk,
+	}, {
+		.con_id = "saif",
+		.clk = &saif_clk,
+	}, {
+		.con_id = "usb",
+		.clk = &usb_clk,
+	},
+};
+
+static int __init propagate_rate(struct clk *clk)
+{
+	struct clk_lookup *cl;
+
+	for (cl = onchip_clks; cl < onchip_clks + ARRAY_SIZE(onchip_clks);
+	     cl++) {
+		if (unlikely(!clk_good(cl->clk)))
+			continue;
+		if (cl->clk->parent == clk && cl->clk->ops->get_rate) {
+			cl->clk->ops->get_rate(cl->clk);
+			if (cl->clk->flags & RATE_PROPAGATES)
+				propagate_rate(cl->clk);
+		}
+	}
+
+	return 0;
+}
+
+/* Exported API */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (unlikely(!clk_good(clk)))
+		return 0;
+
+	if (clk->rate != 0)
+		return clk->rate;
+
+	if (clk->ops->get_rate != NULL)
+		return clk->ops->get_rate(clk);
+
+	return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (unlikely(!clk_good(clk)))
+		return 0;
+
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+
+	return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+static inline int close_enough(long rate1, long rate2)
+{
+	return rate1 && !((rate2 - rate1) * 1000 / rate1);
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EINVAL;
+
+	if (unlikely(!clk_good(clk)))
+		goto out;
+
+	if (clk->flags & FIXED_RATE || !clk->ops->set_rate)
+		goto out;
+
+	else if (!close_enough(clk->rate, rate)) {
+		ret = clk->ops->set_rate(clk, rate);
+		if (ret < 0)
+			goto out;
+		clk->rate = rate;
+		if (clk->flags & RATE_PROPAGATES)
+			propagate_rate(clk);
+	} else
+		ret = 0;
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long clocks_flags;
+
+	if (unlikely(!clk_good(clk)))
+		return -EINVAL;
+
+	if (clk->parent)
+		clk_enable(clk->parent);
+
+	spin_lock_irqsave(&clocks_lock, clocks_flags);
+
+	clk->usage++;
+	if (clk->ops && clk->ops->enable)
+		clk->ops->enable(clk);
+
+	spin_unlock_irqrestore(&clocks_lock, clocks_flags);
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void local_clk_disable(struct clk *clk)
+{
+	if (unlikely(!clk_good(clk)))
+		return;
+
+	if (clk->usage == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	if (clk->parent)
+		local_clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long clocks_flags;
+
+	if (unlikely(!clk_good(clk)))
+		return;
+
+	spin_lock_irqsave(&clocks_lock, clocks_flags);
+
+	if ((--clk->usage) == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clocks_lock, clocks_flags);
+	if (clk->parent)
+		clk_disable(clk->parent);
+}
+EXPORT_SYMBOL(clk_disable);
+
+/* Some additional API */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -ENODEV;
+	unsigned long clocks_flags;
+
+	if (unlikely(!clk_good(clk)))
+		goto out;
+
+	if (!clk->ops->set_parent)
+		goto out;
+
+	spin_lock_irqsave(&clocks_lock, clocks_flags);
+
+	ret = clk->ops->set_parent(clk, parent);
+	if (!ret) {
+		/* disable if usage count is 0 */
+		local_clk_disable(parent);
+
+		parent->usage += clk->usage;
+		clk->parent->usage -= clk->usage;
+
+		/* disable if new usage count is 0 */
+		local_clk_disable(clk->parent);
+
+		clk->parent = parent;
+	}
+	spin_unlock_irqrestore(&clocks_lock, clocks_flags);
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (unlikely(!clk_good(clk)))
+		return NULL;
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+static int __init clk_init(void)
+{
+	struct clk_lookup *cl;
+	struct clk_ops *ops;
+
+	spin_lock_init(&clocks_lock);
+
+	for (cl = onchip_clks; cl < onchip_clks + ARRAY_SIZE(onchip_clks);
+	     cl++) {
+		if (cl->clk->flags & ENABLED)
+			clk_enable(cl->clk);
+		else
+			local_clk_disable(cl->clk);
+
+		ops = cl->clk->ops;
+
+		if ((cl->clk->flags & NEEDS_INITIALIZATION) &&
+				ops && ops->set_rate)
+			ops->set_rate(cl->clk, cl->clk->rate);
+
+		if (cl->clk->flags & FIXED_RATE) {
+			if (cl->clk->flags & RATE_PROPAGATES)
+				propagate_rate(cl->clk);
+		} else {
+			if (ops && ops->get_rate)
+				ops->get_rate(cl->clk);
+		}
+
+		if (cl->clk->flags & NEEDS_SET_PARENT) {
+			if (ops && ops->set_parent)
+				ops->set_parent(cl->clk, cl->clk->parent);
+		}
+
+		clkdev_add(cl);
+	}
+	return 0;
+}
+
+arch_initcall(clk_init);
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/clock.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/clock.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Clock control driver for Freescale STMP37XX/STMP378X - internal header file
+ *
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ARCH_ARM_STMX3XXX_CLOCK_H__
+#define __ARCH_ARM_STMX3XXX_CLOCK_H__
+
+#ifndef __ASSEMBLER__
+
+struct clk_ops {
+	int (*enable) (struct clk *);
+	int (*disable) (struct clk *);
+	long (*get_rate) (struct clk *);
+	long (*round_rate) (struct clk *, u32);
+	int (*set_rate) (struct clk *, u32);
+	int (*set_parent) (struct clk *, struct clk *);
+};
+
+struct clk {
+	struct clk *parent;
+	u32 rate;
+	u32 flags;
+	u8 scale_shift;
+	u8 enable_shift;
+	u8 bypass_shift;
+	u8 busy_bit;
+	s8 usage;
+	int enable_wait;
+	int enable_negate;
+	u32 saved_div;
+	void __iomem *enable_reg;
+	void __iomem *scale_reg;
+	void __iomem *bypass_reg;
+	void __iomem *busy_reg;
+	struct clk_ops *ops;
+};
+
+#endif /* __ASSEMBLER__ */
+
+/* Flags */
+#define RATE_PROPAGATES      (1<<0)
+#define NEEDS_INITIALIZATION (1<<1)
+#define PARENT_SET_RATE      (1<<2)
+#define FIXED_RATE           (1<<3)
+#define ENABLED	             (1<<4)
+#define NEEDS_SET_PARENT     (1<<5)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/core.c linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/core.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,128 @@
+/*
+ * Freescale STMP37XX/STMP378X core routines
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/platform.h>
+#include <mach/dma.h>
+#include <mach/regs-clkctrl.h>
+
+static int __stmp3xxx_reset_block(void __iomem *hwreg, int just_enable)
+{
+	u32 c;
+	int timeout;
+
+	/* the process of software reset of IP block is done
+	   in several steps:
+
+	   - clear SFTRST and wait for block is enabled;
+	   - clear clock gating (CLKGATE bit);
+	   - set the SFTRST again and wait for block is in reset;
+	   - clear SFTRST and wait for reset completion.
+	*/
+	c = __raw_readl(hwreg);
+	c &= ~(1<<31);		/* clear SFTRST */
+	__raw_writel(c, hwreg);
+	for (timeout = 1000000; timeout > 0; timeout--)
+		/* still in SFTRST state ? */
+		if ((__raw_readl(hwreg) & (1<<31)) == 0)
+			break;
+	if (timeout <= 0) {
+		printk(KERN_ERR"%s(%p): timeout when enabling\n",
+				__func__, hwreg);
+		return -ETIME;
+	}
+
+	c = __raw_readl(hwreg);
+	c &= ~(1<<30);		/* clear CLKGATE */
+	__raw_writel(c, hwreg);
+
+	if (!just_enable) {
+		c = __raw_readl(hwreg);
+		c |= (1<<31);		/* now again set SFTRST */
+		__raw_writel(c, hwreg);
+		for (timeout = 1000000; timeout > 0; timeout--)
+			/* poll until CLKGATE set */
+			if (__raw_readl(hwreg) & (1<<30))
+				break;
+		if (timeout <= 0) {
+			printk(KERN_ERR"%s(%p): timeout when resetting\n",
+					__func__, hwreg);
+			return -ETIME;
+		}
+
+		c = __raw_readl(hwreg);
+		c &= ~(1<<31);		/* clear SFTRST */
+		__raw_writel(c, hwreg);
+		for (timeout = 1000000; timeout > 0; timeout--)
+			/* still in SFTRST state ? */
+			if ((__raw_readl(hwreg) & (1<<31)) == 0)
+				break;
+		if (timeout <= 0) {
+			printk(KERN_ERR"%s(%p): timeout when enabling "
+					"after reset\n", __func__, hwreg);
+			return -ETIME;
+		}
+
+		c = __raw_readl(hwreg);
+		c &= ~(1<<30);		/* clear CLKGATE */
+		__raw_writel(c, hwreg);
+	}
+	for (timeout = 1000000; timeout > 0; timeout--)
+		/* still in SFTRST state ? */
+		if ((__raw_readl(hwreg) & (1<<30)) == 0)
+			break;
+
+	if (timeout <= 0) {
+		printk(KERN_ERR"%s(%p): timeout when unclockgating\n",
+				__func__, hwreg);
+		return -ETIME;
+	}
+
+	return 0;
+}
+
+int stmp3xxx_reset_block(void __iomem *hwreg, int just_enable)
+{
+	int try = 10;
+	int r;
+
+	while (try--) {
+		r = __stmp3xxx_reset_block(hwreg, just_enable);
+		if (!r)
+			break;
+		pr_debug("%s: try %d failed\n", __func__, 10 - try);
+	}
+	return r;
+}
+EXPORT_SYMBOL(stmp3xxx_reset_block);
+
+struct platform_device stmp3xxx_dbguart = {
+	.name = "stmp3xxx-dbguart",
+	.id = -1,
+};
+
+void __init stmp3xxx_init(void)
+{
+	/* Turn off auto-slow and other tricks */
+	stmp3xxx_clearl(0x7f00000, REGS_CLKCTRL_BASE + HW_CLKCTRL_HBUS);
+
+	stmp3xxx_dma_init();
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/devices.c linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/devices.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/devices.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/devices.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,389 @@
+/*
+* Freescale STMP37XX/STMP378X platform devices
+*
+* Embedded Alley Solutions, Inc <source@embeddedalley.com>
+*
+* Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+*/
+
+/*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/dma.h>
+#include <mach/platform.h>
+#include <mach/stmp3xxx.h>
+#include <mach/regs-lcdif.h>
+#include <mach/regs-uartapp.h>
+#include <mach/regs-gpmi.h>
+#include <mach/regs-usbctrl.h>
+#include <mach/regs-ssp.h>
+#include <mach/regs-rtc.h>
+
+static u64 common_dmamask = DMA_BIT_MASK(32);
+
+static struct resource appuart_resources[] = {
+	{
+		.start = IRQ_UARTAPP_INTERNAL,
+		.end = IRQ_UARTAPP_INTERNAL,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = IRQ_UARTAPP_RX_DMA,
+		.end = IRQ_UARTAPP_RX_DMA,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = IRQ_UARTAPP_TX_DMA,
+		.end = IRQ_UARTAPP_TX_DMA,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = REGS_UARTAPP1_PHYS,
+		.end = REGS_UARTAPP1_PHYS + REGS_UARTAPP_SIZE,
+		.flags = IORESOURCE_MEM,
+	}, {
+		/* Rx DMA channel */
+		.start = STMP3XXX_DMA(6, STMP3XXX_BUS_APBX),
+		.end = STMP3XXX_DMA(6, STMP3XXX_BUS_APBX),
+		.flags = IORESOURCE_DMA,
+	}, {
+		/* Tx DMA channel */
+		.start = STMP3XXX_DMA(7, STMP3XXX_BUS_APBX),
+		.end = STMP3XXX_DMA(7, STMP3XXX_BUS_APBX),
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+struct platform_device stmp3xxx_appuart = {
+	.name = "stmp3xxx-appuart",
+	.id = 0,
+	.resource = appuart_resources,
+	.num_resources = ARRAY_SIZE(appuart_resources),
+	.dev = {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device stmp3xxx_watchdog = {
+      .name   = "stmp3xxx_wdt",
+      .id     = -1,
+};
+
+static struct resource ts_resource[] = {
+	{
+		.flags  = IORESOURCE_IRQ,
+		.start  = IRQ_TOUCH_DETECT,
+		.end    = IRQ_TOUCH_DETECT,
+	}, {
+		.flags  = IORESOURCE_IRQ,
+		.start  = IRQ_LRADC_CH5,
+		.end    = IRQ_LRADC_CH5,
+	},
+};
+
+struct platform_device stmp3xxx_touchscreen = {
+	.name		= "stmp3xxx_ts",
+	.id		= -1,
+	.resource	= ts_resource,
+	.num_resources	= ARRAY_SIZE(ts_resource),
+};
+
+/*
+* Keypad device
+*/
+struct platform_device stmp3xxx_keyboard = {
+	.name		= "stmp3xxx-keyboard",
+	.id		= -1,
+};
+
+static struct resource gpmi_resources[] = {
+	{
+		.flags = IORESOURCE_MEM,
+		.start = REGS_GPMI_PHYS,
+		.end = REGS_GPMI_PHYS + REGS_GPMI_SIZE,
+	}, {
+		.flags = IORESOURCE_IRQ,
+		.start = IRQ_GPMI_DMA,
+		.end = IRQ_GPMI_DMA,
+	}, {
+		.flags = IORESOURCE_DMA,
+		.start = STMP3XXX_DMA(4, STMP3XXX_BUS_APBH),
+		.end = STMP3XXX_DMA(8, STMP3XXX_BUS_APBH),
+	},
+};
+
+struct platform_device stmp3xxx_gpmi = {
+	.name = "gpmi",
+	.id = -1,
+	.dev	= {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = gpmi_resources,
+	.num_resources = ARRAY_SIZE(gpmi_resources),
+};
+
+static struct resource mmc1_resource[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+		.start	= REGS_SSP1_PHYS,
+		.end	= REGS_SSP1_PHYS + REGS_SSP_SIZE,
+	}, {
+		.flags	= IORESOURCE_DMA,
+		.start	= STMP3XXX_DMA(1, STMP3XXX_BUS_APBH),
+		.end	= STMP3XXX_DMA(1, STMP3XXX_BUS_APBH),
+	}, {
+		.flags	= IORESOURCE_IRQ,
+		.start	= IRQ_SSP1_DMA,
+		.end	= IRQ_SSP1_DMA,
+	}, {
+		.flags	= IORESOURCE_IRQ,
+		.start	= IRQ_SSP_ERROR,
+		.end	= IRQ_SSP_ERROR,
+	},
+};
+
+struct platform_device stmp3xxx_mmc = {
+	.name	= "stmp3xxx-mmc",
+	.id	= 1,
+	.dev	= {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = mmc1_resource,
+	.num_resources = ARRAY_SIZE(mmc1_resource),
+};
+
+static struct resource usb_resources[] = {
+	{
+		.start	= REGS_USBCTRL_PHYS,
+		.end	= REGS_USBCTRL_PHYS + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_USB_CTRL,
+		.end	= IRQ_USB_CTRL,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device stmp3xxx_udc = {
+	.name		= "fsl-usb2-udc",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &common_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource = usb_resources,
+	.num_resources = ARRAY_SIZE(usb_resources),
+};
+
+struct platform_device stmp3xxx_ehci = {
+	.name		= "fsl-ehci",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &common_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= usb_resources,
+	.num_resources	= ARRAY_SIZE(usb_resources),
+};
+
+static struct resource rtc_resources[] = {
+	{
+		.start	= REGS_RTC_PHYS,
+		.end	= REGS_RTC_PHYS + REGS_RTC_SIZE,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_RTC_ALARM,
+		.end	= IRQ_RTC_ALARM,
+		.flags	= IORESOURCE_IRQ,
+	}, {
+		.start	= IRQ_RTC_1MSEC,
+		.end	= IRQ_RTC_1MSEC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device stmp3xxx_rtc = {
+	.name		= "stmp3xxx-rtc",
+	.id		= -1,
+	.resource	= rtc_resources,
+	.num_resources	= ARRAY_SIZE(rtc_resources),
+};
+
+static struct resource ssp1_resources[] = {
+	{
+		.start	= REGS_SSP1_PHYS,
+		.end	= REGS_SSP1_PHYS + REGS_SSP_SIZE,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_SSP1_DMA,
+		.end	= IRQ_SSP1_DMA,
+		.flags	= IORESOURCE_IRQ,
+	}, {
+		.start	= STMP3XXX_DMA(1, STMP3XXX_BUS_APBH),
+		.end	= STMP3XXX_DMA(1, STMP3XXX_BUS_APBH),
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource ssp2_resources[] = {
+	{
+		.start	= REGS_SSP2_PHYS,
+		.end	= REGS_SSP2_PHYS + REGS_SSP_SIZE,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_SSP2_DMA,
+		.end	= IRQ_SSP2_DMA,
+		.flags	= IORESOURCE_IRQ,
+	}, {
+		.start	= STMP3XXX_DMA(2, STMP3XXX_BUS_APBH),
+		.end	= STMP3XXX_DMA(2, STMP3XXX_BUS_APBH),
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device stmp3xxx_spi1 = {
+	.name	= "stmp3xxx_ssp",
+	.id	= 1,
+	.dev	= {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = ssp1_resources,
+	.num_resources = ARRAY_SIZE(ssp1_resources),
+};
+
+struct platform_device stmp3xxx_spi2 = {
+	.name	= "stmp3xxx_ssp",
+	.id	= 2,
+	.dev	= {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = ssp2_resources,
+	.num_resources = ARRAY_SIZE(ssp2_resources),
+};
+
+static struct resource fb_resource[] = {
+	{
+		.flags	= IORESOURCE_IRQ,
+		.start	= IRQ_LCDIF_DMA,
+		.end	= IRQ_LCDIF_DMA,
+	}, {
+		.flags	= IORESOURCE_IRQ,
+		.start	= IRQ_LCDIF_ERROR,
+		.end	= IRQ_LCDIF_ERROR,
+	}, {
+		.flags	= IORESOURCE_MEM,
+		.start	= REGS_LCDIF_PHYS,
+		.end	= REGS_LCDIF_PHYS + REGS_LCDIF_SIZE,
+	},
+};
+
+struct platform_device stmp3xxx_framebuffer = {
+	.name		= "stmp3xxx-fb",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &common_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(fb_resource),
+	.resource	= fb_resource,
+};
+
+#define CMDLINE_DEVICE_CHOOSE(name, dev1, dev2)			\
+	static char *cmdline_device_##name;			\
+	static int cmdline_device_##name##_setup(char *dev)	\
+	{							\
+		cmdline_device_##name = dev + 1;		\
+		return 0;					\
+	}							\
+	__setup(#name, cmdline_device_##name##_setup);		\
+	int stmp3xxx_##name##_device_register(void)		\
+	{							\
+		struct platform_device *d = NULL;		\
+		if (!cmdline_device_##name ||			\
+			!strcmp(cmdline_device_##name, #dev1))	\
+				d = &stmp3xxx_##dev1;		\
+		else if (!strcmp(cmdline_device_##name, #dev2))	\
+				d = &stmp3xxx_##dev2;		\
+		else						\
+			printk(KERN_ERR"Unknown %s assignment '%s'.\n",	\
+				#name, cmdline_device_##name);	\
+		return d ? platform_device_register(d) : -ENOENT;	\
+	}
+
+CMDLINE_DEVICE_CHOOSE(ssp1, mmc, spi1)
+CMDLINE_DEVICE_CHOOSE(ssp2, gpmi, spi2)
+
+struct platform_device stmp3xxx_backlight = {
+	.name		= "stmp3xxx-bl",
+	.id		= -1,
+};
+
+struct platform_device stmp3xxx_rotdec = {
+	.name	= "stmp3xxx-rotdec",
+	.id	= -1,
+};
+
+struct platform_device stmp3xxx_persistent = {
+	.name			= "stmp3xxx-persistent",
+	.id			= -1,
+};
+
+struct platform_device stmp3xxx_dcp_bootstream = {
+	.name			= "stmp3xxx-dcpboot",
+	.id			= -1,
+	.dev	= {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource dcp_resources[] = {
+	{
+		.start = IRQ_DCP_VMI,
+		.end = IRQ_DCP_VMI,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = IRQ_DCP,
+		.end = IRQ_DCP,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device stmp3xxx_dcp = {
+	.name			= "stmp3xxx-dcp",
+	.id			= -1,
+	.resource		= dcp_resources,
+	.num_resources		= ARRAY_SIZE(dcp_resources),
+	.dev	= {
+		.dma_mask	= &common_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource battery_resource[] = {
+	{
+		.flags  = IORESOURCE_IRQ,
+		.start  = IRQ_VDD5V,
+		.end    = IRQ_VDD5V,
+	},
+};
+
+struct platform_device stmp3xxx_battery = {
+	.name   = "stmp3xxx-battery",
+	.resource = battery_resource,
+	.num_resources = ARRAY_SIZE(battery_resource),
+};
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/dma.c linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/dma.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,463 @@
+/*
+ * DMA helper routines for Freescale STMP37XX/STMP378X
+ *
+ * Author: dmitry pervushin <dpervushin@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/sysdev.h>
+#include <linux/cpufreq.h>
+
+#include <asm/page.h>
+
+#include <mach/platform.h>
+#include <mach/dma.h>
+#include <mach/regs-apbx.h>
+#include <mach/regs-apbh.h>
+
+static const size_t pool_item_size = sizeof(struct stmp3xxx_dma_command);
+static const size_t pool_alignment = 8;
+static struct stmp3xxx_dma_user {
+	void *pool;
+	int inuse;
+	const char *name;
+} channels[MAX_DMA_CHANNELS];
+
+#define IS_VALID_CHANNEL(ch) ((ch) >= 0 && (ch) < MAX_DMA_CHANNELS)
+#define IS_USED(ch) (channels[ch].inuse)
+
+int stmp3xxx_dma_request(int ch, struct device *dev, const char *name)
+{
+	struct stmp3xxx_dma_user *user;
+	int err = 0;
+
+	user = channels + ch;
+	if (!IS_VALID_CHANNEL(ch)) {
+		err = -ENODEV;
+		goto out;
+	}
+	if (IS_USED(ch)) {
+		err = -EBUSY;
+		goto out;
+	}
+	/* Create a pool to allocate dma commands from */
+	user->pool = dma_pool_create(name, dev, pool_item_size,
+				     pool_alignment, PAGE_SIZE);
+	if (user->pool == NULL) {
+		err = -ENOMEM;
+		goto out;
+	}
+	user->name = name;
+	user->inuse++;
+out:
+	return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_request);
+
+int stmp3xxx_dma_release(int ch)
+{
+	struct stmp3xxx_dma_user *user = channels + ch;
+	int err = 0;
+
+	if (!IS_VALID_CHANNEL(ch)) {
+		err = -ENODEV;
+		goto out;
+	}
+	if (!IS_USED(ch)) {
+		err = -EBUSY;
+		goto out;
+	}
+	BUG_ON(user->pool == NULL);
+	dma_pool_destroy(user->pool);
+	user->inuse--;
+out:
+	return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_release);
+
+int stmp3xxx_dma_read_semaphore(int channel)
+{
+	int sem = -1;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		sem = __raw_readl(REGS_APBH_BASE + HW_APBH_CHn_SEMA +
+				STMP3XXX_DMA_CHANNEL(channel) * 0x70);
+		sem &= BM_APBH_CHn_SEMA_PHORE;
+		sem >>= BP_APBH_CHn_SEMA_PHORE;
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		sem = __raw_readl(REGS_APBX_BASE + HW_APBX_CHn_SEMA +
+				STMP3XXX_DMA_CHANNEL(channel) * 0x70);
+		sem &= BM_APBX_CHn_SEMA_PHORE;
+		sem >>= BP_APBX_CHn_SEMA_PHORE;
+		break;
+	default:
+		BUG();
+	}
+	return sem;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_read_semaphore);
+
+int stmp3xxx_dma_allocate_command(int channel,
+				  struct stmp3xxx_dma_descriptor *descriptor)
+{
+	struct stmp3xxx_dma_user *user = channels + channel;
+	int err = 0;
+
+	if (!IS_VALID_CHANNEL(channel)) {
+		err = -ENODEV;
+		goto out;
+	}
+	if (!IS_USED(channel)) {
+		err = -EBUSY;
+		goto out;
+	}
+	if (descriptor == NULL) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* Allocate memory for a command from the buffer */
+	descriptor->command =
+	    dma_pool_alloc(user->pool, GFP_KERNEL, &descriptor->handle);
+
+	/* Check it worked */
+	if (!descriptor->command) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	memset(descriptor->command, 0, pool_item_size);
+out:
+	WARN_ON(err);
+	return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_allocate_command);
+
+int stmp3xxx_dma_free_command(int channel,
+			      struct stmp3xxx_dma_descriptor *descriptor)
+{
+	int err = 0;
+
+	if (!IS_VALID_CHANNEL(channel)) {
+		err = -ENODEV;
+		goto out;
+	}
+	if (!IS_USED(channel)) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	/* Return the command memory to the pool */
+	dma_pool_free(channels[channel].pool, descriptor->command,
+		      descriptor->handle);
+
+	/* Initialise descriptor so we're not tempted to use it */
+	descriptor->command = NULL;
+	descriptor->handle = 0;
+	descriptor->virtual_buf_ptr = NULL;
+	descriptor->next_descr = NULL;
+
+	WARN_ON(err);
+out:
+	return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_free_command);
+
+void stmp3xxx_dma_go(int channel,
+		     struct stmp3xxx_dma_descriptor *head, u32 semaphore)
+{
+	int ch = STMP3XXX_DMA_CHANNEL(channel);
+	void __iomem *c, *s;
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		c = REGS_APBH_BASE + HW_APBH_CHn_NXTCMDAR + 0x70 * ch;
+		s = REGS_APBH_BASE + HW_APBH_CHn_SEMA + 0x70 * ch;
+		break;
+
+	case STMP3XXX_BUS_APBX:
+		c = REGS_APBX_BASE + HW_APBX_CHn_NXTCMDAR + 0x70 * ch;
+		s = REGS_APBX_BASE + HW_APBX_CHn_SEMA + 0x70 * ch;
+		break;
+
+	default:
+		return;
+	}
+
+	/* Set next command */
+	__raw_writel(head->handle, c);
+	/* Set counting semaphore (kicks off transfer). Assumes
+	   peripheral has been set up correctly */
+	__raw_writel(semaphore, s);
+}
+EXPORT_SYMBOL(stmp3xxx_dma_go);
+
+int stmp3xxx_dma_running(int channel)
+{
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		return (__raw_readl(REGS_APBH_BASE + HW_APBH_CHn_SEMA +
+			0x70 * STMP3XXX_DMA_CHANNEL(channel))) &
+			    BM_APBH_CHn_SEMA_PHORE;
+
+	case STMP3XXX_BUS_APBX:
+		return (__raw_readl(REGS_APBX_BASE + HW_APBX_CHn_SEMA +
+			0x70 * STMP3XXX_DMA_CHANNEL(channel))) &
+			    BM_APBX_CHn_SEMA_PHORE;
+	default:
+		BUG();
+		return 0;
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_dma_running);
+
+/*
+ * Circular dma chain management
+ */
+void stmp3xxx_dma_free_chain(struct stmp37xx_circ_dma_chain *chain)
+{
+	int i;
+
+	for (i = 0; i < chain->total_count; i++)
+		stmp3xxx_dma_free_command(
+			STMP3XXX_DMA(chain->channel, chain->bus),
+			&chain->chain[i]);
+}
+EXPORT_SYMBOL(stmp3xxx_dma_free_chain);
+
+int stmp3xxx_dma_make_chain(int ch, struct stmp37xx_circ_dma_chain *chain,
+			    struct stmp3xxx_dma_descriptor descriptors[],
+			    unsigned items)
+{
+	int i;
+	int err = 0;
+
+	if (items == 0)
+		return err;
+
+	for (i = 0; i < items; i++) {
+		err = stmp3xxx_dma_allocate_command(ch, &descriptors[i]);
+		if (err) {
+			WARN_ON(err);
+			/*
+			 * Couldn't allocate the whole chain.
+			 * deallocate what has been allocated
+			 */
+			if (i) {
+				do {
+					stmp3xxx_dma_free_command(ch,
+								  &descriptors
+								  [i]);
+				} while (i-- >= 0);
+			}
+			return err;
+		}
+
+		/* link them! */
+		if (i > 0) {
+			descriptors[i - 1].next_descr = &descriptors[i];
+			descriptors[i - 1].command->next =
+						descriptors[i].handle;
+		}
+	}
+
+	/* make list circular */
+	descriptors[items - 1].next_descr = &descriptors[0];
+	descriptors[items - 1].command->next = descriptors[0].handle;
+
+	chain->total_count = items;
+	chain->chain = descriptors;
+	chain->free_index = 0;
+	chain->active_index = 0;
+	chain->cooked_index = 0;
+	chain->free_count = items;
+	chain->active_count = 0;
+	chain->cooked_count = 0;
+	chain->bus = STMP3XXX_DMA_BUS(ch);
+	chain->channel = STMP3XXX_DMA_CHANNEL(ch);
+	return err;
+}
+EXPORT_SYMBOL(stmp3xxx_dma_make_chain);
+
+void stmp37xx_circ_clear_chain(struct stmp37xx_circ_dma_chain *chain)
+{
+	BUG_ON(stmp3xxx_dma_running(STMP3XXX_DMA(chain->channel, chain->bus)));
+	chain->free_index = 0;
+	chain->active_index = 0;
+	chain->cooked_index = 0;
+	chain->free_count = chain->total_count;
+	chain->active_count = 0;
+	chain->cooked_count = 0;
+}
+EXPORT_SYMBOL(stmp37xx_circ_clear_chain);
+
+void stmp37xx_circ_advance_free(struct stmp37xx_circ_dma_chain *chain,
+		unsigned count)
+{
+	BUG_ON(chain->cooked_count < count);
+
+	chain->cooked_count -= count;
+	chain->cooked_index += count;
+	chain->cooked_index %= chain->total_count;
+	chain->free_count += count;
+}
+EXPORT_SYMBOL(stmp37xx_circ_advance_free);
+
+void stmp37xx_circ_advance_active(struct stmp37xx_circ_dma_chain *chain,
+		unsigned count)
+{
+	void __iomem *c;
+	u32 mask_clr, mask;
+	BUG_ON(chain->free_count < count);
+
+	chain->free_count -= count;
+	chain->free_index += count;
+	chain->free_index %= chain->total_count;
+	chain->active_count += count;
+
+	switch (chain->bus) {
+	case STMP3XXX_BUS_APBH:
+		c = REGS_APBH_BASE + HW_APBH_CHn_SEMA + 0x70 * chain->channel;
+		mask_clr = BM_APBH_CHn_SEMA_INCREMENT_SEMA;
+		mask = BF(count, APBH_CHn_SEMA_INCREMENT_SEMA);
+		break;
+	case STMP3XXX_BUS_APBX:
+		c = REGS_APBX_BASE + HW_APBX_CHn_SEMA + 0x70 * chain->channel;
+		mask_clr = BM_APBX_CHn_SEMA_INCREMENT_SEMA;
+		mask = BF(count, APBX_CHn_SEMA_INCREMENT_SEMA);
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	/* Set counting semaphore (kicks off transfer). Assumes
+	   peripheral has been set up correctly */
+	stmp3xxx_clearl(mask_clr, c);
+	stmp3xxx_setl(mask, c);
+}
+EXPORT_SYMBOL(stmp37xx_circ_advance_active);
+
+unsigned stmp37xx_circ_advance_cooked(struct stmp37xx_circ_dma_chain *chain)
+{
+	unsigned cooked;
+
+	cooked = chain->active_count -
+	  stmp3xxx_dma_read_semaphore(STMP3XXX_DMA(chain->channel, chain->bus));
+
+	chain->active_count -= cooked;
+	chain->active_index += cooked;
+	chain->active_index %= chain->total_count;
+
+	chain->cooked_count += cooked;
+
+	return cooked;
+}
+EXPORT_SYMBOL(stmp37xx_circ_advance_cooked);
+
+void stmp3xxx_dma_set_alt_target(int channel, int function)
+{
+#if defined(CONFIG_ARCH_STMP37XX)
+	unsigned bits = 4;
+#elif defined(CONFIG_ARCH_STMP378X)
+	unsigned bits = 2;
+#else
+#error wrong arch
+#endif
+	int shift = STMP3XXX_DMA_CHANNEL(channel) * bits;
+	unsigned mask = (1<<bits) - 1;
+	void __iomem *c;
+
+	BUG_ON(function < 0 || function >= (1<<bits));
+	pr_debug("%s: channel = %d, using mask %x, "
+		 "shift = %d\n", __func__, channel, mask, shift);
+
+	switch (STMP3XXX_DMA_BUS(channel)) {
+	case STMP3XXX_BUS_APBH:
+		c = REGS_APBH_BASE + HW_APBH_DEVSEL;
+		break;
+	case STMP3XXX_BUS_APBX:
+		c = REGS_APBX_BASE + HW_APBX_DEVSEL;
+		break;
+	default:
+		BUG();
+	}
+	stmp3xxx_clearl(mask << shift, c);
+	stmp3xxx_setl(mask << shift, c);
+}
+EXPORT_SYMBOL(stmp3xxx_dma_set_alt_target);
+
+void stmp3xxx_dma_suspend(void)
+{
+	stmp3xxx_setl(BM_APBH_CTRL0_CLKGATE, REGS_APBH_BASE + HW_APBH_CTRL0);
+	stmp3xxx_setl(BM_APBX_CTRL0_CLKGATE, REGS_APBX_BASE + HW_APBX_CTRL0);
+}
+
+void stmp3xxx_dma_resume(void)
+{
+	stmp3xxx_clearl(BM_APBH_CTRL0_CLKGATE | BM_APBH_CTRL0_SFTRST,
+			REGS_APBH_BASE + HW_APBH_CTRL0);
+	stmp3xxx_clearl(BM_APBX_CTRL0_CLKGATE | BM_APBX_CTRL0_SFTRST,
+			REGS_APBX_BASE + HW_APBX_CTRL0);
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+struct dma_notifier_block {
+	struct notifier_block nb;
+	void *data;
+};
+
+static int dma_cpufreq_notifier(struct notifier_block *self,
+				unsigned long phase, void *p)
+{
+	switch (phase) {
+	case CPUFREQ_POSTCHANGE:
+		stmp3xxx_dma_resume();
+		break;
+
+	case CPUFREQ_PRECHANGE:
+		stmp3xxx_dma_suspend();
+		break;
+
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct dma_notifier_block dma_cpufreq_nb = {
+	.nb = {
+		.notifier_call = dma_cpufreq_notifier,
+	},
+};
+#endif /* CONFIG_CPU_FREQ */
+
+void __init stmp3xxx_dma_init(void)
+{
+	stmp3xxx_clearl(BM_APBH_CTRL0_CLKGATE | BM_APBH_CTRL0_SFTRST,
+			REGS_APBH_BASE + HW_APBH_CTRL0);
+	stmp3xxx_clearl(BM_APBX_CTRL0_CLKGATE | BM_APBX_CTRL0_SFTRST,
+			REGS_APBX_BASE + HW_APBX_CTRL0);
+#ifdef CONFIG_CPU_FREQ
+	cpufreq_register_notifier(&dma_cpufreq_nb.nb,
+				CPUFREQ_TRANSITION_NOTIFIER);
+#endif /* CONFIG_CPU_FREQ */
+}
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/clkdev.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/clkdev.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/clkdev.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/cputype.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/cputype.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/cputype.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/cputype.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,33 @@
+/*
+ * Freescale STMP37XX/STMP378X CPU type detection
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_CPU_H
+#define __ASM_PLAT_CPU_H
+
+#ifdef CONFIG_ARCH_STMP37XX
+#define cpu_is_stmp37xx()	(1)
+#else
+#define cpu_is_stmp37xx()	(0)
+#endif
+
+#ifdef CONFIG_ARCH_STMP378X
+#define cpu_is_stmp378x()	(1)
+#else
+#define cpu_is_stmp378x()	(0)
+#endif
+
+#endif /* __ASM_PLAT_CPU_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Debugging macro include header
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x80000000	@ physical base address
+		addeq	\rx, \rx, #0x00070000
+		movne	\rx, #0xf0000000	@ virtual base
+		addne	\rx, \rx, #0x00070000
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx, #0]		@ data register at 0
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
+		tst	\rd, #1 << 5		@ UARTFLGUTXFF - 1 when full
+		bne	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
+		tst	\rd, #1 << 3		@ UARTFLGUBUSY - 1 when busy
+		bne	1001b
+		.endm
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/dma.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/dma.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,153 @@
+/*
+ * Freescale STMP37XX/STMP378X DMA helper interface
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_STMP3XXX_DMA_H
+#define __ASM_PLAT_STMP3XXX_DMA_H
+
+#include <linux/platform_device.h>
+#include <linux/dmapool.h>
+
+#if !defined(MAX_PIO_WORDS)
+#define MAX_PIO_WORDS   (15)
+#endif
+
+#define STMP3XXX_BUS_APBH		0
+#define STMP3XXX_BUS_APBX		1
+#define STMP3XXX_DMA_MAX_CHANNEL	16
+#define STMP3XXX_DMA_BUS(dma)		((dma) / 16)
+#define STMP3XXX_DMA_CHANNEL(dma)	((dma) % 16)
+#define STMP3XXX_DMA(channel, bus)	((bus) * 16 + (channel))
+#define MAX_DMA_ADDRESS			0xffffffff
+#define MAX_DMA_CHANNELS		32
+
+struct stmp3xxx_dma_command {
+	u32 next;
+	u32 cmd;
+	union {
+		u32 buf_ptr;
+		u32 alternate;
+	};
+	u32 pio_words[MAX_PIO_WORDS];
+};
+
+struct stmp3xxx_dma_descriptor {
+	struct stmp3xxx_dma_command *command;
+	dma_addr_t handle;
+
+	/* The virtual address of the buffer pointer */
+	void *virtual_buf_ptr;
+	/* The next descriptor in a the DMA chain (optional) */
+	struct stmp3xxx_dma_descriptor *next_descr;
+};
+
+struct stmp37xx_circ_dma_chain {
+	unsigned total_count;
+	struct stmp3xxx_dma_descriptor *chain;
+
+	unsigned free_index;
+	unsigned free_count;
+	unsigned active_index;
+	unsigned active_count;
+	unsigned cooked_index;
+	unsigned cooked_count;
+
+	int bus;
+	unsigned channel;
+};
+
+static inline struct stmp3xxx_dma_descriptor
+    *stmp3xxx_dma_circ_get_free_head(struct stmp37xx_circ_dma_chain *chain)
+{
+	return &(chain->chain[chain->free_index]);
+}
+
+static inline struct stmp3xxx_dma_descriptor
+    *stmp3xxx_dma_circ_get_cooked_head(struct stmp37xx_circ_dma_chain *chain)
+{
+	return &(chain->chain[chain->cooked_index]);
+}
+
+int stmp3xxx_dma_request(int ch, struct device *dev, const char *name);
+int stmp3xxx_dma_release(int ch);
+int stmp3xxx_dma_allocate_command(int ch,
+				  struct stmp3xxx_dma_descriptor *descriptor);
+int stmp3xxx_dma_free_command(int ch,
+			      struct stmp3xxx_dma_descriptor *descriptor);
+void stmp3xxx_dma_continue(int channel, u32 semaphore);
+void stmp3xxx_dma_go(int ch, struct stmp3xxx_dma_descriptor *head,
+		     u32 semaphore);
+int stmp3xxx_dma_running(int ch);
+int stmp3xxx_dma_make_chain(int ch, struct stmp37xx_circ_dma_chain *chain,
+			    struct stmp3xxx_dma_descriptor descriptors[],
+			    unsigned items);
+void stmp3xxx_dma_free_chain(struct stmp37xx_circ_dma_chain *chain);
+void stmp37xx_circ_clear_chain(struct stmp37xx_circ_dma_chain *chain);
+void stmp37xx_circ_advance_free(struct stmp37xx_circ_dma_chain *chain,
+		unsigned count);
+void stmp37xx_circ_advance_active(struct stmp37xx_circ_dma_chain *chain,
+		unsigned count);
+unsigned stmp37xx_circ_advance_cooked(struct stmp37xx_circ_dma_chain *chain);
+int stmp3xxx_dma_read_semaphore(int ch);
+void stmp3xxx_dma_init(void);
+void stmp3xxx_dma_set_alt_target(int ch, int target);
+void stmp3xxx_dma_suspend(void);
+void stmp3xxx_dma_resume(void);
+
+/*
+ * STMP37xx and STMP378x have different DMA control
+ * registers layout
+ */
+
+void stmp3xxx_arch_dma_freeze(int ch);
+void stmp3xxx_arch_dma_unfreeze(int ch);
+void stmp3xxx_arch_dma_reset_channel(int ch);
+void stmp3xxx_arch_dma_enable_interrupt(int ch);
+void stmp3xxx_arch_dma_clear_interrupt(int ch);
+int stmp3xxx_arch_dma_is_interrupt(int ch);
+
+static inline void stmp3xxx_dma_reset_channel(int ch)
+{
+	stmp3xxx_arch_dma_reset_channel(ch);
+}
+
+
+static inline void stmp3xxx_dma_freeze(int ch)
+{
+	stmp3xxx_arch_dma_freeze(ch);
+}
+
+static inline void stmp3xxx_dma_unfreeze(int ch)
+{
+	stmp3xxx_arch_dma_unfreeze(ch);
+}
+
+static inline void stmp3xxx_dma_enable_interrupt(int ch)
+{
+	stmp3xxx_arch_dma_enable_interrupt(ch);
+}
+
+static inline void stmp3xxx_dma_clear_interrupt(int ch)
+{
+	stmp3xxx_arch_dma_clear_interrupt(ch);
+}
+
+static inline int stmp3xxx_dma_is_interrupt(int ch)
+{
+	return stmp3xxx_arch_dma_is_interrupt(ch);
+}
+
+#endif /* __ASM_PLAT_STMP3XXX_DMA_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/gpio.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/gpio.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * Freescale STMP37XX/STMP378X GPIO interface
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_GPIO_H
+#define __ASM_PLAT_GPIO_H
+
+#define ARCH_NR_GPIOS	(32 * 3)
+#define gpio_to_irq(gpio) __gpio_to_irq(gpio)
+#define gpio_get_value(gpio) __gpio_get_value(gpio)
+#define gpio_set_value(gpio, value) __gpio_set_value(gpio, value)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_PLAT_GPIO_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/gpmi.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/gpmi.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/gpmi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/gpmi.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef __MACH_GPMI_H
+
+#include <linux/mtd/partitions.h>
+#include <mach/regs-gpmi.h>
+
+struct gpmi_platform_data {
+	void *pins;
+	int nr_parts;
+	struct mtd_partition *parts;
+	const char *part_types[];
+};
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/hardware.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/hardware.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/hardware.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * This file contains the hardware definitions of the Freescale STMP3XXX
+ *
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ */
+#define IO_BASE			0xF0000000                 /* VA of IO  */
+#define IO_SIZE			0x00100000                 /* How much? */
+#define IO_START		0x80000000                 /* PA of IO  */
+
+/* macro to get at IO space when running virtually */
+#define IO_ADDRESS(x) (((x) & 0x000fffff) | IO_BASE)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/io.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/io.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) 	__typesafe_io(a)
+#define __mem_pci(a)	(a)
+#define __mem_isa(a)	(a)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	UL(0x40000000)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/mmc.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/mmc.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/mmc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,14 @@
+#ifndef _MACH_MMC_H
+#define _MACH_MMC_H
+
+#include <mach/regs-ssp.h>
+
+struct stmp3xxxmmc_platform_data {
+	int (*get_wp)(void);
+	unsigned long (*setclock)(void __iomem *base, unsigned long);
+	void (*cmd_pullup)(int);
+	int  (*hw_init)(void);
+	void (*hw_release)(void);
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/pinmux.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/pinmux.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/pinmux.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/pinmux.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,157 @@
+/*
+ * Freescale STMP37XX/STMP378X Pin Multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __PINMUX_H
+#define __PINMUX_H
+
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <asm-generic/gpio.h>
+
+/* Pin definitions */
+#include "pins.h"
+#include <mach/pins.h>
+
+/*
+ * Each pin may be routed up to four different HW interfaces
+ * including GPIO
+ */
+enum pin_fun {
+	PIN_FUN1 = 0,
+	PIN_FUN2,
+	PIN_FUN3,
+	PIN_GPIO,
+};
+
+/*
+ * Each pin may have different output drive strength in range from
+ * 4mA to 20mA. The most common case is 4, 8 and 12 mA strengths.
+ */
+enum pin_strength {
+	PIN_4MA = 0,
+	PIN_8MA,
+	PIN_12MA,
+	PIN_16MA,
+	PIN_20MA,
+};
+
+/*
+ * Each pin can be programmed for 1.8V or 3.3V
+ */
+enum pin_voltage {
+	PIN_1_8V = 0,
+	PIN_3_3V,
+};
+
+/*
+ * Structure to define a group of pins and their parameters
+ */
+struct pin_desc {
+	unsigned id;
+	enum pin_fun fun;
+	enum pin_strength strength;
+	enum pin_voltage voltage;
+	unsigned pullup:1;
+};
+
+struct pin_group {
+	struct pin_desc *pins;
+	int nr_pins;
+};
+
+/* Set pin drive strength */
+void stmp3xxx_pin_strength(unsigned id, enum pin_strength strength,
+			   const char *label);
+
+/* Set pin voltage */
+void stmp3xxx_pin_voltage(unsigned id, enum pin_voltage voltage,
+			   const char *label);
+
+/* Enable pull-up resistor for a pin */
+void stmp3xxx_pin_pullup(unsigned id, int enable, const char *label);
+
+/*
+ * Request a pin ownership, only one module (identified by @label)
+ * may own a pin.
+ */
+int stmp3xxx_request_pin(unsigned id, enum pin_fun fun, const char *label);
+
+/* Release pin */
+void stmp3xxx_release_pin(unsigned id, const char *label);
+
+void stmp3xxx_set_pin_type(unsigned id, enum pin_fun fun);
+
+/*
+ * Each bank is associated with a number of registers to control
+ * pin function, drive strength, voltage and pull-up reigster. The
+ * number of registers of a given type depends on the number of bits
+ * describin particular pin.
+ */
+#define HW_MUXSEL_NUM		2	/* registers per bank */
+#define HW_MUXSEL_PIN_LEN	2	/* bits per pin */
+#define HW_MUXSEL_PIN_NUM	16	/* pins per register */
+#define HW_MUXSEL_PINFUN_MASK	0x3	/* pin function mask */
+#define HW_MUXSEL_PINFUN_NUM	4	/* four options for a pin */
+
+#define HW_DRIVE_NUM		4	/* registers per bank */
+#define HW_DRIVE_PIN_LEN	4	/* bits per pin */
+#define HW_DRIVE_PIN_NUM	8	/* pins per register */
+#define HW_DRIVE_PINDRV_MASK	0x3	/* pin strength mask - 2 bits */
+#define HW_DRIVE_PINDRV_NUM	5	/* five possible strength values */
+#define HW_DRIVE_PINV_MASK	0x4	/* pin voltage mask - 1 bit */
+
+
+struct stmp3xxx_pinmux_bank {
+	struct gpio_chip chip;
+
+	/* Pins allocation map */
+	unsigned long pin_map;
+
+	/* Pin owner names */
+	const char *pin_labels[32];
+
+	/* Bank registers */
+	void __iomem *hw_muxsel[HW_MUXSEL_NUM];
+	void __iomem *hw_drive[HW_DRIVE_NUM];
+	void __iomem *hw_pull;
+
+	void __iomem *pin2irq,
+		*irqlevel,
+		*irqpolarity,
+		*irqen,
+		*irqstat;
+
+	/* HW MUXSEL register function bit values */
+	u8 functions[HW_MUXSEL_PINFUN_NUM];
+
+	/*
+	 * HW DRIVE register strength bit values:
+	 * 0xff - requested strength is not supported for this bank
+	 */
+	u8 strengths[HW_DRIVE_PINDRV_NUM];
+
+	/* GPIO things */
+	void __iomem *hw_gpio_in,
+		     *hw_gpio_out,
+		     *hw_gpio_doe;
+	int irq, virq;
+};
+
+int __init stmp3xxx_pinmux_init(int virtual_irq_start);
+
+#endif /* __PINMUX_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/pins.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/pins.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/pins.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/pins.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Freescale STMP37XX/STMP378X Pin multiplexing interface definitions
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_PINS_H
+#define __ASM_PLAT_PINS_H
+
+#define STMP3XXX_PINID(bank, pin)	(bank * 32 + pin)
+#define STMP3XXX_PINID_TO_BANK(pinid)	(pinid / 32)
+#define STMP3XXX_PINID_TO_PINNUM(pinid)	(pinid % 32)
+
+/*
+ * Special invalid pin identificator to show a pin doesn't exist
+ */
+#define PINID_NO_PIN	STMP3XXX_PINID(0xFF, 0xFF)
+
+#endif /* __ASM_PLAT_PINS_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/platform.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/platform.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/platform.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/platform.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_PLATFORM_H
+#define __ASM_PLAT_PLATFORM_H
+
+#ifndef __ASSEMBLER__
+#include <linux/io.h>
+#endif
+#include <asm/sizes.h>
+
+/* Virtual address where registers are mapped */
+#define STMP3XXX_REGS_PHBASE	0x80000000
+#ifdef __ASSEMBLER__
+#define STMP3XXX_REGS_BASE	0xF0000000
+#else
+#define STMP3XXX_REGS_BASE	(void __iomem *)0xF0000000
+#endif
+#define STMP3XXX_REGS_SIZE	SZ_1M
+
+/* Virtual address where OCRAM is mapped */
+#define STMP3XXX_OCRAM_PHBASE	0x00000000
+#ifdef __ASSEMBLER__
+#define STMP3XXX_OCRAM_BASE	0xf1000000
+#else
+#define STMP3XXX_OCRAM_BASE	(void __iomem *)0xf1000000
+#endif
+#define STMP3XXX_OCRAM_SIZE	(32 * SZ_1K)
+
+#ifdef CONFIG_ARCH_STMP37XX
+#define IRQ_PRIORITY_REG_RD	HW_ICOLL_PRIORITYn_RD
+#define IRQ_PRIORITY_REG_WR	HW_ICOLL_PRIORITYn_WR
+#endif
+
+#ifdef CONFIG_ARCH_STMP378X
+#define IRQ_PRIORITY_REG_RD	HW_ICOLL_INTERRUPTn_RD
+#define IRQ_PRIORITY_REG_WR	HW_ICOLL_INTERRUPTn_WR
+#endif
+
+#define HW_STMP3XXX_SET		0x04
+#define HW_STMP3XXX_CLR		0x08
+#define HW_STMP3XXX_TOG		0x0c
+
+#ifndef __ASSEMBLER__
+static inline void stmp3xxx_clearl(u32 v, void __iomem *r)
+{
+	__raw_writel(v, r + HW_STMP3XXX_CLR);
+}
+
+static inline void stmp3xxx_setl(u32 v, void __iomem *r)
+{
+	__raw_writel(v, r + HW_STMP3XXX_SET);
+}
+#endif
+
+#define BF(value, field) (((value) << BP_##field) & BM_##field)
+
+#endif /* __ASM_ARCH_PLATFORM_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/stmp3xxx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * Freescale STMP37XX/STMP378X core structure and function declarations
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_STMP3XXX_H
+#define __ASM_PLAT_STMP3XXX_H
+
+#include <linux/irq.h>
+
+extern struct sys_timer stmp3xxx_timer;
+
+void stmp3xxx_init_irq(struct irq_chip *chip);
+void stmp3xxx_init(void);
+int stmp3xxx_reset_block(void __iomem *hwreg, int just_enable);
+extern struct platform_device stmp3xxx_dbguart,
+			      stmp3xxx_appuart,
+			      stmp3xxx_watchdog,
+			      stmp3xxx_touchscreen,
+			      stmp3xxx_keyboard,
+			      stmp3xxx_gpmi,
+			      stmp3xxx_mmc,
+			      stmp3xxx_udc,
+			      stmp3xxx_ehci,
+			      stmp3xxx_rtc,
+			      stmp3xxx_spi1,
+			      stmp3xxx_spi2,
+			      stmp3xxx_backlight,
+			      stmp3xxx_rotdec,
+			      stmp3xxx_dcp,
+			      stmp3xxx_dcp_bootstream,
+			      stmp3xxx_persistent,
+			      stmp3xxx_framebuffer,
+			      stmp3xxx_battery;
+int stmp3xxx_ssp1_device_register(void);
+int stmp3xxx_ssp2_device_register(void);
+
+struct pin_group;
+void stmp3xxx_release_pin_group(struct pin_group *pin_group, const char *label);
+int stmp3xxx_request_pin_group(struct pin_group *pin_group, const char *label);
+
+#endif /* __ASM_PLAT_STMP3XXX_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/system.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/system.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005 Sigmatel Inc
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/proc-fns.h>
+#include <mach/platform.h>
+#include <mach/regs-clkctrl.h>
+#include <mach/regs-power.h>
+
+static inline void arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching
+	 * and wait for interrupt tricks
+	 */
+
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	/* Set BATTCHRG to default value */
+	__raw_writel(0x00010000, REGS_POWER_BASE + HW_POWER_CHARGE);
+
+	/* Set MINPWR to default value   */
+	__raw_writel(0, REGS_POWER_BASE + HW_POWER_MINPWR);
+
+	/* Reset digital side of chip (but not power or RTC) */
+	__raw_writel(BM_CLKCTRL_RESET_DIG,
+			REGS_CLKCTRL_BASE + HW_CLKCTRL_RESET);
+
+	/* Should not return */
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/timex.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/timex.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/timex.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * System time clock is sourced from the 32k clock
+ */
+#define CLOCK_TICK_RATE		(32768)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/uncompress.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/uncompress.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/uncompress.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_UNCOMPRESS_H
+#define __ASM_PLAT_UNCOMPRESS_H
+
+/*
+ * Register includes are for when the MMU enabled; we need to define our
+ * own stuff here for pre-MMU use
+ */
+#define UARTDBG_BASE		0x80070000
+#define UART(c)			(((volatile unsigned *)UARTDBG_BASE)[c])
+
+/*
+ * This does not append a newline
+ */
+static void putc(char c)
+{
+	/* Wait for TX fifo empty */
+	while ((UART(6) & (1<<7)) == 0)
+		continue;
+
+	/* Write byte */
+	UART(0) = c;
+
+	/* Wait for last bit to exit the UART */
+	while (UART(6) & (1<<3))
+		continue;
+}
+
+static void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
+
+#endif /* __ASM_PLAT_UNCOMPRESS_H */
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#define VMALLOC_END       (0xF0000000)
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/irq.c linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/irq.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * Freescale STMP37XX/STMP378X common interrupt handling code
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/sysdev.h>
+
+#include <mach/stmp3xxx.h>
+#include <mach/platform.h>
+#include <mach/regs-icoll.h>
+
+void __init stmp3xxx_init_irq(struct irq_chip *chip)
+{
+	unsigned int i, lv;
+
+	/* Reset the interrupt controller */
+	stmp3xxx_reset_block(REGS_ICOLL_BASE + HW_ICOLL_CTRL, true);
+
+	/* Disable all interrupts initially */
+	for (i = 0; i < NR_REAL_IRQS; i++) {
+		chip->mask(i);
+		set_irq_chip(i, chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Ensure vector is cleared */
+	for (lv = 0; lv < 4; lv++)
+		__raw_writel(1 << lv, REGS_ICOLL_BASE + HW_ICOLL_LEVELACK);
+	__raw_writel(0, REGS_ICOLL_BASE + HW_ICOLL_VECTOR);
+
+	/* Barrier */
+	(void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT);
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/Kconfig linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/Kconfig
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,37 @@
+if ARCH_STMP3XXX
+
+menu "Freescale STMP3xxx implementations"
+
+choice
+	prompt "Select STMP3xxx chip family"
+
+config ARCH_STMP37XX
+	bool "Freescale SMTP37xx"
+	select CPU_ARM926T
+	---help---
+	 STMP37xx refers to 3700 through 3769 chips
+
+config ARCH_STMP378X
+	bool "Freescale STMP378x"
+	select CPU_ARM926T
+	---help---
+	 STMP378x refers to 3780 through 3789 chips
+
+endchoice
+
+choice
+	prompt "Select STMP3xxx board type"
+
+config MACH_STMP37XX
+	depends on ARCH_STMP37XX
+	bool "Freescale STMP37xx development board"
+
+config MACH_STMP378X
+	depends on ARCH_STMP378X
+	bool "Freescale STMP378x development board"
+
+endchoice
+
+endmenu
+
+endif
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/Makefile linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/Makefile
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux kernel.
+#
+# Object file lists.
+obj-y += core.o timer.o irq.o dma.o clock.o pinmux.o devices.o
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/pinmux.c linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/pinmux.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/pinmux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/pinmux.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,551 @@
+/*
+ * Freescale STMP378X/STMP378X Pin Multiplexing
+ *
+ * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#define DEBUG
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sysdev.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/regs-pinctrl.h>
+#include <mach/pins.h>
+#include <mach/pinmux.h>
+
+#define NR_BANKS ARRAY_SIZE(pinmux_banks)
+static struct stmp3xxx_pinmux_bank pinmux_banks[] = {
+	[0] = {
+		.hw_muxsel = {
+			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL0,
+			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL1,
+		},
+		.hw_drive = {
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE0,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE1,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE2,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE3,
+		},
+		.hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL0,
+		.functions = { 0x0, 0x1, 0x2, 0x3 },
+		.strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
+
+		.hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN0,
+		.hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT0,
+		.hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE0,
+		.irq = IRQ_GPIO0,
+
+		.pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ0,
+		.irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT0,
+		.irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL0,
+		.irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL0,
+		.irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN0,
+	},
+	[1] = {
+		.hw_muxsel = {
+			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL2,
+			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL3,
+		},
+		.hw_drive = {
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE4,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE5,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE6,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE7,
+		},
+		.hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL1,
+		.functions = { 0x0, 0x1, 0x2, 0x3 },
+		.strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
+
+		.hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN1,
+		.hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT1,
+		.hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE1,
+		.irq = IRQ_GPIO1,
+
+		.pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ1,
+		.irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT1,
+		.irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL1,
+		.irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL1,
+		.irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN1,
+	},
+	[2] = {
+	       .hw_muxsel = {
+			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL4,
+			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL5,
+		},
+		.hw_drive = {
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE8,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE9,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE10,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE11,
+		},
+		.hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL2,
+		.functions = { 0x0, 0x1, 0x2, 0x3 },
+		.strengths = { 0x0, 0x1, 0x2, 0x1, 0x2 },
+
+		.hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN2,
+		.hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT2,
+		.hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE2,
+		.irq = IRQ_GPIO2,
+
+		.pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ2,
+		.irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT2,
+		.irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL2,
+		.irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL2,
+		.irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN2,
+	},
+	[3] = {
+	       .hw_muxsel = {
+		       REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL6,
+		       REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL7,
+	       },
+	       .hw_drive = {
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE12,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE13,
+			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE14,
+			NULL,
+	       },
+	       .hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL3,
+	       .functions = {0x0, 0x1, 0x2, 0x3},
+	       .strengths = {0x0, 0x1, 0x2, 0x3, 0xff},
+	},
+};
+
+static inline struct stmp3xxx_pinmux_bank *
+stmp3xxx_pinmux_bank(unsigned id, unsigned *bank, unsigned *pin)
+{
+	unsigned b, p;
+
+	b = STMP3XXX_PINID_TO_BANK(id);
+	p = STMP3XXX_PINID_TO_PINNUM(id);
+	BUG_ON(b >= NR_BANKS);
+	if (bank)
+		*bank = b;
+	if (pin)
+		*pin = p;
+	return &pinmux_banks[b];
+}
+
+/* Check if requested pin is owned by caller */
+static int stmp3xxx_check_pin(unsigned id, const char *label)
+{
+	unsigned pin;
+	struct stmp3xxx_pinmux_bank *pm = stmp3xxx_pinmux_bank(id, NULL, &pin);
+
+	if (!test_bit(pin, &pm->pin_map)) {
+		printk(KERN_WARNING
+		       "%s: Accessing free pin %x, caller %s\n",
+		       __func__, id, label);
+
+		return -EINVAL;
+	}
+
+	if (label && pm->pin_labels[pin] &&
+	    strcmp(label, pm->pin_labels[pin])) {
+		printk(KERN_WARNING
+		       "%s: Wrong pin owner %x, caller %s owner %s\n",
+		       __func__, id, label, pm->pin_labels[pin]);
+
+		return -EINVAL;
+	}
+	return 0;
+}
+
+void stmp3xxx_pin_strength(unsigned id, enum pin_strength strength,
+		const char *label)
+{
+	struct stmp3xxx_pinmux_bank *pbank;
+	void __iomem *hwdrive;
+	u32 shift, val;
+	u32 bank, pin;
+
+	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+	pr_debug("%s: label %s bank %d pin %d strength %d\n", __func__, label,
+		 bank, pin, strength);
+
+	hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
+	shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
+	val = pbank->strengths[strength];
+	if (val == 0xff) {
+		printk(KERN_WARNING
+		       "%s: strength is not supported for bank %d, caller %s",
+		       __func__, bank, label);
+		return;
+	}
+
+	if (stmp3xxx_check_pin(id, label))
+		return;
+
+	pr_debug("%s: writing 0x%x to 0x%p register\n", __func__,
+			val << shift, hwdrive);
+	stmp3xxx_clearl(HW_DRIVE_PINDRV_MASK << shift, hwdrive);
+	stmp3xxx_setl(val << shift, hwdrive);
+}
+
+void stmp3xxx_pin_voltage(unsigned id, enum pin_voltage voltage,
+			  const char *label)
+{
+	struct stmp3xxx_pinmux_bank *pbank;
+	void __iomem *hwdrive;
+	u32 shift;
+	u32 bank, pin;
+
+	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+	pr_debug("%s: label %s bank %d pin %d voltage %d\n", __func__, label,
+		 bank, pin, voltage);
+
+	hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
+	shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
+
+	if (stmp3xxx_check_pin(id, label))
+		return;
+
+	pr_debug("%s: changing 0x%x bit in 0x%p register\n",
+			__func__, HW_DRIVE_PINV_MASK << shift, hwdrive);
+	if (voltage == PIN_1_8V)
+		stmp3xxx_clearl(HW_DRIVE_PINV_MASK << shift, hwdrive);
+	else
+		stmp3xxx_setl(HW_DRIVE_PINV_MASK << shift, hwdrive);
+}
+
+void stmp3xxx_pin_pullup(unsigned id, int enable, const char *label)
+{
+	struct stmp3xxx_pinmux_bank *pbank;
+	void __iomem *hwpull;
+	u32 bank, pin;
+
+	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+	pr_debug("%s: label %s bank %d pin %d enable %d\n", __func__, label,
+		 bank, pin, enable);
+
+	hwpull = pbank->hw_pull;
+
+	if (stmp3xxx_check_pin(id, label))
+		return;
+
+	pr_debug("%s: changing 0x%x bit in 0x%p register\n",
+			__func__, 1 << pin, hwpull);
+	if (enable)
+		stmp3xxx_setl(1 << pin, hwpull);
+	else
+		stmp3xxx_clearl(1 << pin, hwpull);
+}
+
+int stmp3xxx_request_pin(unsigned id, enum pin_fun fun, const char *label)
+{
+	struct stmp3xxx_pinmux_bank *pbank;
+	u32 bank, pin;
+	int ret = 0;
+
+	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+	pr_debug("%s: label %s bank %d pin %d fun %d\n", __func__, label,
+		 bank, pin, fun);
+
+	if (test_bit(pin, &pbank->pin_map)) {
+		printk(KERN_WARNING
+		       "%s: CONFLICT DETECTED pin %d:%d caller %s owner %s\n",
+		       __func__, bank, pin, label, pbank->pin_labels[pin]);
+		return -EBUSY;
+	}
+
+	set_bit(pin, &pbank->pin_map);
+	pbank->pin_labels[pin] = label;
+
+	stmp3xxx_set_pin_type(id, fun);
+
+	return ret;
+}
+
+void stmp3xxx_set_pin_type(unsigned id, enum pin_fun fun)
+{
+	struct stmp3xxx_pinmux_bank *pbank;
+	void __iomem *hwmux;
+	u32 shift, val;
+	u32 bank, pin;
+
+	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+
+	hwmux = pbank->hw_muxsel[pin / HW_MUXSEL_PIN_NUM];
+	shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
+
+	val = pbank->functions[fun];
+	shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
+	pr_debug("%s: writing 0x%x to 0x%p register\n",
+			__func__, val << shift, hwmux);
+	stmp3xxx_clearl(HW_MUXSEL_PINFUN_MASK << shift, hwmux);
+	stmp3xxx_setl(val << shift, hwmux);
+}
+
+void stmp3xxx_release_pin(unsigned id, const char *label)
+{
+	struct stmp3xxx_pinmux_bank *pbank;
+	u32 bank, pin;
+
+	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
+	pr_debug("%s: label %s bank %d pin %d\n", __func__, label, bank, pin);
+
+	if (stmp3xxx_check_pin(id, label))
+		return;
+
+	clear_bit(pin, &pbank->pin_map);
+	pbank->pin_labels[pin] = NULL;
+}
+
+int stmp3xxx_request_pin_group(struct pin_group *pin_group, const char *label)
+{
+	struct pin_desc *pin;
+	int p;
+	int err = 0;
+
+	/* Allocate and configure pins */
+	for (p = 0; p < pin_group->nr_pins; p++) {
+		pr_debug("%s: #%d\n", __func__, p);
+		pin = &pin_group->pins[p];
+
+		err = stmp3xxx_request_pin(pin->id, pin->fun, label);
+		if (err)
+			goto out_err;
+
+		stmp3xxx_pin_strength(pin->id, pin->strength, label);
+		stmp3xxx_pin_voltage(pin->id, pin->voltage, label);
+		stmp3xxx_pin_pullup(pin->id, pin->pullup, label);
+	}
+
+	return 0;
+
+out_err:
+	/* Release allocated pins in case of error */
+	while (--p >= 0) {
+		pr_debug("%s: releasing #%d\n", __func__, p);
+		stmp3xxx_release_pin(pin_group->pins[p].id, label);
+	}
+	return err;
+}
+EXPORT_SYMBOL(stmp3xxx_request_pin_group);
+
+void stmp3xxx_release_pin_group(struct pin_group *pin_group, const char *label)
+{
+	struct pin_desc *pin;
+	int p;
+
+	for (p = 0; p < pin_group->nr_pins; p++) {
+		pin = &pin_group->pins[p];
+		stmp3xxx_release_pin(pin->id, label);
+	}
+}
+EXPORT_SYMBOL(stmp3xxx_release_pin_group);
+
+static int stmp3xxx_irq_to_gpio(int irq,
+	struct stmp3xxx_pinmux_bank **bank, unsigned *gpio)
+{
+	struct stmp3xxx_pinmux_bank *pm;
+
+	for (pm = pinmux_banks; pm < pinmux_banks + NR_BANKS; pm++)
+		if (pm->virq <= irq && irq < pm->virq + 32) {
+			*bank = pm;
+			*gpio = irq - pm->virq;
+			return 0;
+		}
+	return -ENOENT;
+}
+
+static int stmp3xxx_set_irqtype(unsigned irq, unsigned type)
+{
+	struct stmp3xxx_pinmux_bank *pm;
+	unsigned gpio;
+	int l, p;
+
+	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		l = 0; p = 1; break;
+	case IRQ_TYPE_EDGE_FALLING:
+		l = 0; p = 0; break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		l = 1; p = 1; break;
+	case IRQ_TYPE_LEVEL_LOW:
+		l = 1; p = 0; break;
+	default:
+		pr_debug("%s: Incorrect GPIO interrupt type 0x%x\n",
+				__func__, type);
+		return -ENXIO;
+	}
+
+	if (l)
+		stmp3xxx_setl(1 << gpio, pm->irqlevel);
+	else
+		stmp3xxx_clearl(1 << gpio, pm->irqlevel);
+	if (p)
+		stmp3xxx_setl(1 << gpio, pm->irqpolarity);
+	else
+		stmp3xxx_clearl(1 << gpio, pm->irqpolarity);
+	return 0;
+}
+
+static void stmp3xxx_pin_ack_irq(unsigned irq)
+{
+	u32 stat;
+	struct stmp3xxx_pinmux_bank *pm;
+	unsigned gpio;
+
+	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	stat = __raw_readl(pm->irqstat) & (1 << gpio);
+	stmp3xxx_clearl(stat, pm->irqstat);
+}
+
+static void stmp3xxx_pin_mask_irq(unsigned irq)
+{
+	struct stmp3xxx_pinmux_bank *pm;
+	unsigned gpio;
+
+	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	stmp3xxx_clearl(1 << gpio, pm->irqen);
+	stmp3xxx_clearl(1 << gpio, pm->pin2irq);
+}
+
+static void stmp3xxx_pin_unmask_irq(unsigned irq)
+{
+	struct stmp3xxx_pinmux_bank *pm;
+	unsigned gpio;
+
+	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
+	stmp3xxx_setl(1 << gpio, pm->irqen);
+	stmp3xxx_setl(1 << gpio, pm->pin2irq);
+}
+
+static inline
+struct stmp3xxx_pinmux_bank *to_pinmux_bank(struct gpio_chip *chip)
+{
+	return container_of(chip, struct stmp3xxx_pinmux_bank, chip);
+}
+
+static int stmp3xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+	return pm->virq + offset;
+}
+
+static int stmp3xxx_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+	unsigned v;
+
+	v = __raw_readl(pm->hw_gpio_in) & (1 << offset);
+	return v ? 1 : 0;
+}
+
+static void stmp3xxx_gpio_set(struct gpio_chip *chip, unsigned offset, int v)
+{
+	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+
+	if (v)
+		stmp3xxx_setl(1 << offset, pm->hw_gpio_out);
+	else
+		stmp3xxx_clearl(1 << offset, pm->hw_gpio_out);
+}
+
+static int stmp3xxx_gpio_output(struct gpio_chip *chip, unsigned offset, int v)
+{
+	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+
+	stmp3xxx_setl(1 << offset, pm->hw_gpio_doe);
+	stmp3xxx_gpio_set(chip, offset, v);
+	return 0;
+}
+
+static int stmp3xxx_gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
+
+	stmp3xxx_clearl(1 << offset, pm->hw_gpio_doe);
+	return 0;
+}
+
+static int stmp3xxx_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return stmp3xxx_request_pin(chip->base + offset, PIN_GPIO, "gpio");
+}
+
+static void stmp3xxx_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	stmp3xxx_release_pin(chip->base + offset, "gpio");
+}
+
+static void stmp3xxx_gpio_irq(u32 irq, struct irq_desc *desc)
+{
+	struct stmp3xxx_pinmux_bank *pm = get_irq_data(irq);
+	int gpio_irq = pm->virq;
+	u32 stat = __raw_readl(pm->irqstat);
+
+	while (stat) {
+		if (stat & 1)
+			irq_desc[gpio_irq].handle_irq(gpio_irq,
+				&irq_desc[gpio_irq]);
+		gpio_irq++;
+		stat >>= 1;
+	}
+}
+
+static struct irq_chip gpio_irq_chip = {
+	.ack	= stmp3xxx_pin_ack_irq,
+	.mask	= stmp3xxx_pin_mask_irq,
+	.unmask	= stmp3xxx_pin_unmask_irq,
+	.set_type = stmp3xxx_set_irqtype,
+};
+
+int __init stmp3xxx_pinmux_init(int virtual_irq_start)
+{
+	int b, r = 0;
+	struct stmp3xxx_pinmux_bank *pm;
+	int virq;
+
+	for (b = 0; b < 3; b++) {
+		/* only banks 0,1,2 are allowed to GPIO */
+		pm = pinmux_banks + b;
+		pm->chip.base = 32 * b;
+		pm->chip.ngpio = 32;
+		pm->chip.owner = THIS_MODULE;
+		pm->chip.can_sleep = 1;
+		pm->chip.exported = 1;
+		pm->chip.to_irq = stmp3xxx_gpio_to_irq;
+		pm->chip.direction_input = stmp3xxx_gpio_input;
+		pm->chip.direction_output = stmp3xxx_gpio_output;
+		pm->chip.get = stmp3xxx_gpio_get;
+		pm->chip.set = stmp3xxx_gpio_set;
+		pm->chip.request = stmp3xxx_gpio_request;
+		pm->chip.free = stmp3xxx_gpio_free;
+		pm->virq = virtual_irq_start + b * 32;
+
+		for (virq = pm->virq; virq < pm->virq; virq++) {
+			gpio_irq_chip.mask(virq);
+			set_irq_chip(virq, &gpio_irq_chip);
+			set_irq_handler(virq, handle_level_irq);
+			set_irq_flags(virq, IRQF_VALID);
+		}
+		r = gpiochip_add(&pm->chip);
+		if (r < 0)
+			break;
+		set_irq_chained_handler(pm->irq, stmp3xxx_gpio_irq);
+		set_irq_data(pm->irq, pm);
+	}
+	return r;
+}
+
+MODULE_AUTHOR("Vladislav Buzov");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/timer.c linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/timer.c
--- linux-libre-2.6.30-gnu/arch/arm/plat-stmp3xxx/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/arm/plat-stmp3xxx/timer.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,189 @@
+/*
+ * System timer for Freescale STMP37XX/STMP378X
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/time.h>
+#include <mach/stmp3xxx.h>
+#include <mach/platform.h>
+#include <mach/regs-timrot.h>
+
+static irqreturn_t
+stmp3xxx_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *c = dev_id;
+
+	/* timer 0 */
+	if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0) &
+			BM_TIMROT_TIMCTRLn_IRQ) {
+		stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ,
+				REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
+		c->event_handler(c);
+	}
+
+	/* timer 1 */
+	else if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1)
+			& BM_TIMROT_TIMCTRLn_IRQ) {
+		stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ,
+				REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
+		stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN,
+				REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
+		__raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static cycle_t stmp3xxx_clock_read(struct clocksource *cs)
+{
+	return ~((__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1)
+				& 0xFFFF0000) >> 16);
+}
+
+static int
+stmp3xxx_timrot_set_next_event(unsigned long delta,
+		struct clock_event_device *dev)
+{
+	/* reload the timer */
+	__raw_writel(delta, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
+	return 0;
+}
+
+static void
+stmp3xxx_timrot_set_mode(enum clock_event_mode mode,
+		struct clock_event_device *dev)
+{
+}
+
+static struct clock_event_device ckevt_timrot = {
+	.name		= "timrot",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_next_event	= stmp3xxx_timrot_set_next_event,
+	.set_mode	= stmp3xxx_timrot_set_mode,
+};
+
+static struct clocksource cksrc_stmp3xxx = {
+	.name           = "cksrc_stmp3xxx",
+	.rating         = 250,
+	.read           = stmp3xxx_clock_read,
+	.mask           = CLOCKSOURCE_MASK(16),
+	.shift          = 10,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static struct irqaction stmp3xxx_timer_irq = {
+	.name		= "stmp3xxx_timer",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= stmp3xxx_timer_interrupt,
+	.dev_id		= &ckevt_timrot,
+};
+
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+static void __init stmp3xxx_init_timer(void)
+{
+	cksrc_stmp3xxx.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
+				cksrc_stmp3xxx.shift);
+	ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+				ckevt_timrot.shift);
+	ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
+	ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot);
+	ckevt_timrot.cpumask = cpumask_of(0);
+
+	stmp3xxx_reset_block(REGS_TIMROT_BASE, false);
+
+	/* clear two timers */
+	__raw_writel(0, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
+	__raw_writel(0, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
+
+	/* configure them */
+	__raw_writel(
+		(8 << BP_TIMROT_TIMCTRLn_SELECT) |  /* 32 kHz */
+		BM_TIMROT_TIMCTRLn_RELOAD |
+		BM_TIMROT_TIMCTRLn_UPDATE |
+		BM_TIMROT_TIMCTRLn_IRQ_EN,
+			REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
+	__raw_writel(
+		(8 << BP_TIMROT_TIMCTRLn_SELECT) |  /* 32 kHz */
+		BM_TIMROT_TIMCTRLn_RELOAD |
+		BM_TIMROT_TIMCTRLn_UPDATE |
+		BM_TIMROT_TIMCTRLn_IRQ_EN,
+			REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
+
+	__raw_writel(CLOCK_TICK_RATE / HZ - 1,
+			REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
+	__raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
+
+	setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq);
+
+	clocksource_register(&cksrc_stmp3xxx);
+	clockevents_register_device(&ckevt_timrot);
+}
+
+#ifdef CONFIG_PM
+
+void stmp3xxx_suspend_timer(void)
+{
+	stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN | BM_TIMROT_TIMCTRLn_IRQ,
+			REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
+	stmp3xxx_setl(BM_TIMROT_ROTCTRL_CLKGATE,
+			REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL);
+}
+
+void stmp3xxx_resume_timer(void)
+{
+	stmp3xxx_clearl(BM_TIMROT_ROTCTRL_SFTRST | BM_TIMROT_ROTCTRL_CLKGATE,
+			REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL);
+	__raw_writel(
+		8 << BP_TIMROT_TIMCTRLn_SELECT |  /* 32 kHz */
+		BM_TIMROT_TIMCTRLn_RELOAD |
+		BM_TIMROT_TIMCTRLn_UPDATE |
+		BM_TIMROT_TIMCTRLn_IRQ_EN,
+			REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
+	__raw_writel(
+		8 << BP_TIMROT_TIMCTRLn_SELECT |  /* 32 kHz */
+		BM_TIMROT_TIMCTRLn_RELOAD |
+		BM_TIMROT_TIMCTRLn_UPDATE |
+		BM_TIMROT_TIMCTRLn_IRQ_EN,
+			REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
+	__raw_writel(CLOCK_TICK_RATE / HZ - 1,
+			REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
+	__raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
+}
+
+#else
+
+#define stmp3xxx_suspend_timer	NULL
+#define	stmp3xxx_resume_timer	NULL
+
+#endif	/* CONFIG_PM */
+
+struct sys_timer stmp3xxx_timer = {
+	.init		= stmp3xxx_init_timer,
+	.suspend	= stmp3xxx_suspend_timer,
+	.resume		= stmp3xxx_resume_timer,
+};
diff -druN linux-libre-2.6.30-gnu/arch/arm/tools/mach-types linux-libre-2.6.31-gnu/arch/arm/tools/mach-types
--- linux-libre-2.6.30-gnu/arch/arm/tools/mach-types	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/tools/mach-types	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Fri May 29 10:14:20 2009
+# Last update: Sat Jun 20 22:28:39 2009
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -1455,7 +1455,7 @@
 h6044			MACH_H6044		H6044			1458
 app			MACH_APP		APP			1459
 tct_hammer		MACH_TCT_HAMMER		TCT_HAMMER		1460
-herald			MACH_HERMES		HERMES			1461
+herald			MACH_HERALD		HERALD			1461
 artemis			MACH_ARTEMIS		ARTEMIS			1462
 htctitan		MACH_HTCTITAN		HTCTITAN		1463
 qranium			MACH_QRANIUM		QRANIUM			1464
@@ -2245,3 +2245,38 @@
 omap3_wl_ff		MACH_OMAP3_WL_FF	OMAP3_WL_FF		2258
 simcom			MACH_SIMCOM		SIMCOM			2259
 mcwebio			MACH_MCWEBIO		MCWEBIO			2260
+omap3_phrazer		MACH_OMAP3_PHRAZER	OMAP3_PHRAZER		2261
+darwin			MACH_DARWIN		DARWIN			2262
+oratiscomu		MACH_ORATISCOMU		ORATISCOMU		2263
+rtsbc20			MACH_RTSBC20		RTSBC20			2264
+i780			MACH_I780		I780			2265
+gemini324		MACH_GEMINI324		GEMINI324		2266
+oratislan		MACH_ORATISLAN		ORATISLAN		2267
+oratisalog		MACH_ORATISALOG		ORATISALOG		2268
+oratismadi		MACH_ORATISMADI		ORATISMADI		2269
+oratisot16		MACH_ORATISOT16		ORATISOT16		2270
+oratisdesk		MACH_ORATISDESK		ORATISDESK		2271
+v2p_ca9			MACH_V2P_CA9		V2P_CA9			2272
+sintexo			MACH_SINTEXO		SINTEXO			2273
+cm3389			MACH_CM3389		CM3389			2274
+omap3_cio		MACH_OMAP3_CIO		OMAP3_CIO		2275
+sgh_i900		MACH_SGH_I900		SGH_I900		2276
+bst100			MACH_BST100		BST100			2277
+passion			MACH_PASSION		PASSION			2278
+indesign_at91sam	MACH_INDESIGN_AT91SAM	INDESIGN_AT91SAM	2279
+c4_badger		MACH_C4_BADGER		C4_BADGER		2280
+c4_viper		MACH_C4_VIPER		C4_VIPER		2281
+d2net			MACH_D2NET		D2NET			2282
+bigdisk			MACH_BIGDISK		BIGDISK			2283
+notalvision		MACH_NOTALVISION	NOTALVISION		2284
+omap3_kboc		MACH_OMAP3_KBOC		OMAP3_KBOC		2285
+cyclone			MACH_CYCLONE		CYCLONE			2286
+ninja			MACH_NINJA		NINJA			2287
+at91sam9g20ek_2mmc	MACH_AT91SAM9G20EK_2MMC	AT91SAM9G20EK_2MMC	2288
+bcmring			MACH_BCMRING		BCMRING			2289
+resol_dl2		MACH_RESOL_DL2		RESOL_DL2		2290
+ifosw			MACH_IFOSW		IFOSW			2291
+htcrhodium		MACH_HTCRHODIUM		HTCRHODIUM		2292
+htctopaz		MACH_HTCTOPAZ		HTCTOPAZ		2293
+matrix504		MACH_MATRIX504		MATRIX504		2294
+mrfsa			MACH_MRFSA		MRFSA			2295
diff -druN linux-libre-2.6.30-gnu/arch/arm/vfp/vfphw.S linux-libre-2.6.31-gnu/arch/arm/vfp/vfphw.S
--- linux-libre-2.6.30-gnu/arch/arm/vfp/vfphw.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/vfp/vfphw.S	2009-09-09 18:13:59.000000000 -0400
@@ -100,6 +100,7 @@
 	beq	no_old_VFP_process
 	VFPFSTMIA r4, r5		@ save the working registers
 	VFPFMRX	r5, FPSCR		@ current status
+#ifndef CONFIG_CPU_FEROCEON
 	tst	r1, #FPEXC_EX		@ is there additional state to save?
 	beq	1f
 	VFPFMRX	r6, FPINST		@ FPINST (only if FPEXC.EX is set)
@@ -107,6 +108,7 @@
 	beq	1f
 	VFPFMRX	r8, FPINST2		@ FPINST2 if needed (and present)
 1:
+#endif
 	stmia	r4, {r1, r5, r6, r8}	@ save FPEXC, FPSCR, FPINST, FPINST2
 					@ and point r4 at the word at the
 					@ start of the register dump
@@ -119,6 +121,7 @@
 	VFPFLDMIA r10, r5		@ reload the working registers while
 					@ FPEXC is in a safe state
 	ldmia	r10, {r1, r5, r6, r8}	@ load FPEXC, FPSCR, FPINST, FPINST2
+#ifndef CONFIG_CPU_FEROCEON
 	tst	r1, #FPEXC_EX		@ is there additional state to restore?
 	beq	1f
 	VFPFMXR	FPINST, r6		@ restore FPINST (only if FPEXC.EX is set)
@@ -126,6 +129,7 @@
 	beq	1f
 	VFPFMXR	FPINST2, r8		@ FPINST2 if needed (and present)
 1:
+#endif
 	VFPFMXR	FPSCR, r5		@ restore status
 
 check_for_exception:
diff -druN linux-libre-2.6.30-gnu/arch/arm/vfp/vfpmodule.c linux-libre-2.6.31-gnu/arch/arm/vfp/vfpmodule.c
--- linux-libre-2.6.30-gnu/arch/arm/vfp/vfpmodule.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/arm/vfp/vfpmodule.c	2009-09-09 18:13:59.000000000 -0400
@@ -253,12 +253,14 @@
 	}
 
 	if (fpexc & FPEXC_EX) {
+#ifndef CONFIG_CPU_FEROCEON
 		/*
 		 * Asynchronous exception. The instruction is read from FPINST
 		 * and the interrupted instruction has to be restarted.
 		 */
 		trigger = fmrx(FPINST);
 		regs->ARM_pc -= 4;
+#endif
 	} else if (!(fpexc & FPEXC_DEX)) {
 		/*
 		 * Illegal combination of bits. It can be caused by an
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/Kconfig linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/Kconfig
--- linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,15 @@
 
 if BOARD_ATNGW100
 
+choice
+	prompt "Select an NGW100 add-on board to support"
+	default BOARD_ATNGW100_ADDON_NONE
+
+config BOARD_ATNGW100_ADDON_NONE
+	bool "None"
+
 config BOARD_ATNGW100_EVKLCD10X
-	bool "Add support for EVKLCD10X addon board"
+	bool "EVKLCD10X addon board"
 	help
 	  This enables support for the EVKLCD100 (QVGA) or EVKLCD101 (VGA)
 	  addon board for the NGW100. By enabling this the LCD controller and
@@ -14,7 +21,19 @@
 	  The MCI pins can be reenabled by editing the "add device function" but
 	  this may break the setup for other displays that use these pins.
 
-	  Choose 'Y' here if you have a EVKLCD100/101 connected to the NGW100.
+config BOARD_ATNGW100_MRMT
+	bool "Mediama RMT1/2 add-on board"
+	help
+	  This enables support for the Mediama RMT1 or RMT2 board.
+	  RMT provides LCD support, AC97 codec and other
+	  optional peripherals to the Atmel NGW100.
+
+	  This choice disables the detect pin and the write-protect pin for the
+	  MCI platform device, since it conflicts with the LCD platform device.
+	  The MCI pins can be reenabled by editing the "add device function" but
+	  this may break the setup for other displays that use these pins.
+
+endchoice
 
 choice
 	prompt "LCD panel resolution on EVKLCD10X"
@@ -32,4 +51,8 @@
 
 endchoice
 
+if BOARD_ATNGW100_MRMT
+source	"arch/avr32/boards/atngw100/Kconfig_mrmt"
+endif
+
 endif	# BOARD_ATNGW100
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/Kconfig_mrmt linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/Kconfig_mrmt
--- linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/Kconfig_mrmt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/Kconfig_mrmt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,80 @@
+# RMT for NGW100 customization
+
+choice
+	prompt "RMT Version"
+	help
+	  Select the RMTx board version.
+
+config BOARD_MRMT_REV1
+	bool "RMT1"
+config BOARD_MRMT_REV2
+	bool "RMT2"
+
+endchoice
+
+config BOARD_MRMT_AC97
+	bool "Enable AC97 CODEC"
+	help
+	  Enable the UCB1400 AC97 CODEC driver.
+
+choice
+	prompt "Touchscreen Driver"
+	default BOARD_MRMT_ADS7846_TS
+
+config BOARD_MRMT_UCB1400_TS
+	bool "Use UCB1400 Touchscreen"
+
+config BOARD_MRMT_ADS7846_TS
+	bool "Use ADS7846 Touchscreen"
+
+endchoice
+
+choice
+	prompt "RMTx LCD Selection"
+	default BOARD_MRMT_LCD_DISABLE
+
+config BOARD_MRMT_LCD_DISABLE
+	bool "LCD Disabled"
+
+config BOARD_MRMT_LCD_LQ043T3DX0X
+	bool "Sharp LQ043T3DX0x or compatible"
+	help
+	  If using RMT2, be sure to load the resistor pack selectors accordingly
+
+if BOARD_MRMT_REV2
+config BOARD_MRMT_LCD_KWH043GM08
+	bool "Formike KWH043GM08 or compatible"
+	help
+	  Be sure to load the RMT2 resistor pack selectors accordingly
+endif
+
+endchoice
+
+if !BOARD_MRMT_LCD_DISABLE
+config BOARD_MRMT_BL_PWM
+	bool "Use PWM control for LCD Backlight"
+	help
+		Use PWM driver for controlling LCD Backlight.
+		Otherwise, LCD Backlight is always on.
+endif
+
+config BOARD_MRMT_RTC_I2C
+	bool "Use External RTC on I2C Bus"
+	help
+		RMT1 has an optional RTC device on the I2C bus.
+		It is a SII S35390A.  Be sure to select the
+		matching RTC driver.
+
+choice
+	prompt "Wireless Module on ttyS2"
+	default BOARD_MRMT_WIRELESS_ZB
+
+config BOARD_MRMT_WIRELESS_ZB
+	bool "Use ZigBee/802.15.4 Module"
+
+config BOARD_MRMT_WIRELESS_BT
+	bool "Use Bluetooth (HCI) Module"
+
+config BOARD_MRMT_WIRELESS_NONE
+	bool "Not Installed"
+endchoice
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/Makefile linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/Makefile
--- linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,2 +1,3 @@
 obj-y					+= setup.o flash.o
 obj-$(CONFIG_BOARD_ATNGW100_EVKLCD10X)	+= evklcd10x.o
+obj-$(CONFIG_BOARD_ATNGW100_MRMT)	+= mrmt.o
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/mrmt.c linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/mrmt.c
--- linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/mrmt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/mrmt.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,373 @@
+/*
+ * Board-specific setup code for Remote Media Terminal 1 (RMT1)
+ * add-on board for the ATNGW100 Network Gateway
+ *
+ * Copyright (C) 2008 Mediama Technologies
+ * Based on ATNGW100 Network Gateway (Copyright (C) Atmel)
+ *
+ * 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.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/linkage.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/atmel_serial.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <video/atmel_lcdc.h>
+#include <sound/atmel-ac97c.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+
+#include <mach/at32ap700x.h>
+#include <mach/board.h>
+#include <mach/init.h>
+#include <mach/portmux.h>
+
+/* Define board-specifoic GPIO assignments */
+#define PIN_LCD_BL	GPIO_PIN_PA(28)
+#define PWM_CH_BL	0	/* Must match with GPIO pin definition */
+#define PIN_LCD_DISP	GPIO_PIN_PA(31)
+#define	PIN_AC97_RST_N	GPIO_PIN_PA(30)
+#define PB_EXTINT_BASE	25
+#define TS_IRQ		0
+#define PIN_TS_EXTINT	GPIO_PIN_PB(PB_EXTINT_BASE+TS_IRQ)
+#define PIN_PB_LEFT	GPIO_PIN_PB(11)
+#define PIN_PB_RIGHT	GPIO_PIN_PB(12)
+#define PIN_PWR_SW_N	GPIO_PIN_PB(14)
+#define PIN_PWR_ON	GPIO_PIN_PB(13)
+#define PIN_ZB_RST_N	GPIO_PIN_PA(21)
+#define PIN_BT_RST	GPIO_PIN_PA(22)
+#define PIN_LED_SYS	GPIO_PIN_PA(16)
+#define PIN_LED_A	GPIO_PIN_PA(19)
+#define PIN_LED_B	GPIO_PIN_PE(19)
+
+#ifdef CONFIG_BOARD_MRMT_LCD_LQ043T3DX0X
+/* Sharp LQ043T3DX0x (or compatible) panel */
+static struct fb_videomode __initdata lcd_fb_modes[] = {
+	{
+		.name		= "480x272 @ 59.94Hz",
+		.refresh	= 59.94,
+		.xres		= 480,		.yres		= 272,
+		.pixclock	= KHZ2PICOS(9000),
+
+		.left_margin	= 2,		.right_margin	= 2,
+		.upper_margin	= 3,		.lower_margin	= 9,
+		.hsync_len	= 41,		.vsync_len	= 1,
+
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
+	.manufacturer		= "SHA",
+	.monitor		= "LQ043T3DX02",
+	.modedb			= lcd_fb_modes,
+	.modedb_len		= ARRAY_SIZE(lcd_fb_modes),
+	.hfmin			= 14915,
+	.hfmax			= 17638,
+	.vfmin			= 53,
+	.vfmax			= 61,
+	.dclkmax		= 9260000,
+};
+
+static struct atmel_lcdfb_info __initdata rmt_lcdc_data = {
+	.default_bpp		= 24,
+	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
+	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
+				   | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
+				   | ATMEL_LCDC_INVCLK_NORMAL
+				   | ATMEL_LCDC_MEMOR_BIG),
+	.lcd_wiring_mode	= ATMEL_LCDC_WIRING_RGB,
+	.default_monspecs	= &lcd_fb_default_monspecs,
+	.guard_time		= 2,
+};
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_LCD_KWH043GM08
+/* Sharp KWH043GM08-Fxx (or compatible) panel */
+static struct fb_videomode __initdata lcd_fb_modes[] = {
+	{
+		.name		= "480x272 @ 59.94Hz",
+		.refresh	= 59.94,
+		.xres		= 480,		.yres		= 272,
+		.pixclock	= KHZ2PICOS(9000),
+
+		.left_margin	= 2,		.right_margin	= 2,
+		.upper_margin	= 3,		.lower_margin	= 9,
+		.hsync_len	= 41,		.vsync_len	= 1,
+
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+
+static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
+	.manufacturer		= "FOR",
+	.monitor		= "KWH043GM08",
+	.modedb			= lcd_fb_modes,
+	.modedb_len		= ARRAY_SIZE(lcd_fb_modes),
+	.hfmin			= 14915,
+	.hfmax			= 17638,
+	.vfmin			= 53,
+	.vfmax			= 61,
+	.dclkmax		= 9260000,
+};
+
+static struct atmel_lcdfb_info __initdata rmt_lcdc_data = {
+	.default_bpp		= 24,
+	.default_dmacon		= ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
+	.default_lcdcon2	= (ATMEL_LCDC_DISTYPE_TFT
+				   | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
+				   | ATMEL_LCDC_INVCLK_INVERTED
+				   | ATMEL_LCDC_MEMOR_BIG),
+	.lcd_wiring_mode	= ATMEL_LCDC_WIRING_RGB,
+	.default_monspecs	= &lcd_fb_default_monspecs,
+	.guard_time		= 2,
+};
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_AC97
+static struct ac97c_platform_data __initdata ac97c0_data = {
+	.reset_pin		= PIN_AC97_RST_N,
+};
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_UCB1400_TS
+/* NOTE: IRQ assignment relies on kernel module parameter */
+static struct platform_device rmt_ts_device = {
+	.name	= "ucb1400_ts",
+	.id	= -1,
+	}
+};
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_BL_PWM
+/* PWM LEDs: LCD Backlight, etc */
+static struct gpio_led rmt_pwm_led[] = {
+	/* here the "gpio" is actually a PWM channel */
+	{ .name = "backlight",	.gpio = PWM_CH_BL, },
+};
+
+static struct gpio_led_platform_data rmt_pwm_led_data = {
+	.num_leds	= ARRAY_SIZE(rmt_pwm_led),
+	.leds		= rmt_pwm_led,
+};
+
+static struct platform_device rmt_pwm_led_dev = {
+	.name		= "leds-atmel-pwm",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &rmt_pwm_led_data,
+	},
+};
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_ADS7846_TS
+static int ads7846_pendown_state(void)
+{
+	return !gpio_get_value( PIN_TS_EXTINT );	/* PENIRQ.*/
+}
+
+static struct ads7846_platform_data ads_info = {
+	.model				= 7846,
+	.keep_vref_on			= 0,	/* Use external VREF pin */
+	.vref_delay_usecs		= 0,
+	.vref_mv			= 3300,	/* VREF = 3.3V */
+	.settle_delay_usecs		= 800,
+	.penirq_recheck_delay_usecs	= 800,
+	.x_plate_ohms			= 750,
+	.y_plate_ohms			= 300,
+	.pressure_max			= 4096,
+	.debounce_max			= 1,
+	.debounce_rep			= 0,
+	.debounce_tol			= (~0),
+	.get_pendown_state		= ads7846_pendown_state,
+	.filter				= NULL,
+	.filter_init			= NULL,
+};
+
+static struct spi_board_info spi01_board_info[] __initdata = {
+	{
+		.modalias	= "ads7846",
+		.max_speed_hz	= 31250*26,
+		.bus_num	= 0,
+		.chip_select	= 1,
+		.platform_data	= &ads_info,
+		.irq		= AT32_EXTINT(TS_IRQ),
+	},
+};
+#endif
+
+/* GPIO Keys: left, right, power, etc */
+static const struct gpio_keys_button rmt_gpio_keys_buttons[] = {
+	[0] = {
+		.type		= EV_KEY,
+		.code		= KEY_POWER,
+		.gpio		= PIN_PWR_SW_N,
+		.active_low	= 1,
+		.desc		= "power button",
+	},
+	[1] = {
+		.type		= EV_KEY,
+		.code		= KEY_LEFT,
+		.gpio		= PIN_PB_LEFT,
+		.active_low	= 1,
+		.desc		= "left button",
+	},
+	[2] = {
+		.type		= EV_KEY,
+		.code		= KEY_RIGHT,
+		.gpio		= PIN_PB_RIGHT,
+		.active_low	= 1,
+		.desc		= "right button",
+	},
+};
+
+static const struct gpio_keys_platform_data rmt_gpio_keys_data = {
+	.nbuttons =	ARRAY_SIZE(rmt_gpio_keys_buttons),
+	.buttons =	(void *) rmt_gpio_keys_buttons,
+};
+
+static struct platform_device rmt_gpio_keys = {
+	.name =		"gpio-keys",
+	.id =		-1,
+	.dev = {
+		.platform_data = (void *) &rmt_gpio_keys_data,
+	}
+};
+
+#ifdef CONFIG_BOARD_MRMT_RTC_I2C
+static struct i2c_board_info __initdata mrmt1_i2c_rtc = {
+	I2C_BOARD_INFO("s35390a", 0x30),
+	.irq		= 0,
+};
+#endif
+
+static void mrmt_power_off(void)
+{
+	/* PWR_ON=0 will force power off */
+	gpio_set_value( PIN_PWR_ON, 0 );
+}
+
+static int __init mrmt1_init(void)
+{
+	gpio_set_value( PIN_PWR_ON, 1 );	/* Ensure PWR_ON is enabled */
+
+	pm_power_off = mrmt_power_off;
+
+	/* Setup USARTS (other than console) */
+	at32_map_usart(2, 1, 0);	/* USART 2: /dev/ttyS1, RMT1:DB9M */
+	at32_map_usart(3, 2, ATMEL_USART_RTS | ATMEL_USART_CTS);
+			/* USART 3: /dev/ttyS2, RMT1:Wireless, w/ RTS/CTS */
+	at32_add_device_usart(1);
+	at32_add_device_usart(2);
+
+	/* Select GPIO Key pins */
+	at32_select_gpio( PIN_PWR_SW_N, AT32_GPIOF_DEGLITCH);
+	at32_select_gpio( PIN_PB_LEFT, AT32_GPIOF_DEGLITCH);
+	at32_select_gpio( PIN_PB_RIGHT, AT32_GPIOF_DEGLITCH);
+	platform_device_register(&rmt_gpio_keys);
+
+#ifdef CONFIG_BOARD_MRMT_RTC_I2C
+	i2c_register_board_info(0, &mrmt1_i2c_rtc, 1);
+#endif
+
+#ifndef CONFIG_BOARD_MRMT_LCD_DISABLE
+	/* User "alternate" LCDC inferface on Port E & D */
+	/* NB: exclude LCDC_CC pin, as NGW100 reserves it for other use */
+	at32_add_device_lcdc(0, &rmt_lcdc_data,
+		fbmem_start, fbmem_size,
+		(ATMEL_LCDC_ALT_24BIT | ATMEL_LCDC_PE_DVAL ) );
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_AC97
+	at32_add_device_ac97c(0, &ac97c0_data, AC97C_BOTH);
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_ADS7846_TS
+	/* Select the Touchscreen interrupt pin mode */
+	at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ),
+			GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
+	set_irq_type( AT32_EXTINT(TS_IRQ), IRQ_TYPE_EDGE_FALLING );
+	spi_register_board_info(spi01_board_info,ARRAY_SIZE(spi01_board_info));
+#endif
+
+#ifdef CONFIG_BOARD_MRMT_UCB1400_TS
+	/* Select the Touchscreen interrupt pin mode */
+	at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ),
+			GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
+	platform_device_register(&rmt_ts_device);
+#endif
+
+	at32_select_gpio( PIN_LCD_DISP, AT32_GPIOF_OUTPUT );
+	gpio_request( PIN_LCD_DISP, "LCD_DISP" );
+	gpio_direction_output( PIN_LCD_DISP, 0 );	/* LCD DISP */
+#ifdef CONFIG_BOARD_MRMT_LCD_DISABLE
+	/* Keep Backlight and DISP off */
+	at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT );
+	gpio_request( PIN_LCD_BL, "LCD_BL" );
+	gpio_direction_output( PIN_LCD_BL, 0 );		/* Backlight */
+#else
+	gpio_set_value( PIN_LCD_DISP, 1 );	/* DISP asserted first */
+#ifdef CONFIG_BOARD_MRMT_BL_PWM
+	/* Use PWM for Backlight controls */
+	at32_add_device_pwm(1 << PWM_CH_BL);
+	platform_device_register(&rmt_pwm_led_dev);
+#else
+	/* Backlight always on */
+	udelay( 1 );
+	at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT );
+	gpio_request( PIN_LCD_BL, "LCD_BL" );
+	gpio_direction_output( PIN_LCD_BL, 1 );
+#endif
+#endif
+
+	/* Make sure BT and Zigbee modules in reset */
+	at32_select_gpio( PIN_BT_RST, AT32_GPIOF_OUTPUT );
+	gpio_request( PIN_BT_RST, "BT_RST" );
+	gpio_direction_output( PIN_BT_RST, 1 );
+	/* BT Module in Reset */
+
+	at32_select_gpio( PIN_ZB_RST_N, AT32_GPIOF_OUTPUT );
+	gpio_request( PIN_ZB_RST_N, "ZB_RST_N" );
+	gpio_direction_output( PIN_ZB_RST_N, 0 );
+	/* XBee Module in Reset */
+
+#ifdef CONFIG_BOARD_MRMT_WIRELESS_ZB
+	udelay( 1000 );
+	/* Unreset the XBee Module */
+	gpio_set_value( PIN_ZB_RST_N, 1 );
+#endif
+#ifdef CONFIG_BOARD_MRMT_WIRELESS_BT
+	udelay( 1000 );
+	/* Unreset the BT Module */
+	gpio_set_value( PIN_BT_RST, 0 );
+#endif
+
+	return 0;
+}
+arch_initcall(mrmt1_init);
+
+static int __init mrmt1_early_init(void)
+{
+	/* To maintain power-on signal in case boot loader did not already */
+	at32_select_gpio( PIN_PWR_ON, AT32_GPIOF_OUTPUT );
+	gpio_request( PIN_PWR_ON, "PIN_PWR_ON" );
+	gpio_direction_output( PIN_PWR_ON, 1 );
+
+	return 0;
+}
+core_initcall(mrmt1_early_init);
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/setup.c linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/setup.c
--- linux-libre-2.6.30-gnu/arch/avr32/boards/atngw100/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/atngw100/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -56,8 +56,13 @@
 static struct mci_platform_data __initdata mci0_data = {
 	.slot[0] = {
 		.bus_width	= 4,
+#if defined(CONFIG_BOARD_ATNGW100_EVKLCD10X) || defined(CONFIG_BOARD_ATNGW100_MRMT1)
+		.detect_pin     = GPIO_PIN_NONE,
+		.wp_pin         = GPIO_PIN_NONE,
+#else
 		.detect_pin	= GPIO_PIN_PC(25),
 		.wp_pin		= GPIO_PIN_PE(0),
+#endif
 	},
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/favr-32/setup.c linux-libre-2.6.31-gnu/arch/avr32/boards/favr-32/setup.c
--- linux-libre-2.6.30-gnu/arch/avr32/boards/favr-32/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/favr-32/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,6 +72,10 @@
 	.debounce_max		= 20,
 	.debounce_rep		= 4,
 	.debounce_tol		= 5,
+
+	.keep_vref_on		= true,
+	.settle_delay_usecs	= 500,
+	.penirq_recheck_delay_usecs = 100,
 };
 
 static struct spi_board_info __initdata spi1_board_info[] = {
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/merisc/setup.c linux-libre-2.6.31-gnu/arch/avr32/boards/merisc/setup.c
--- linux-libre-2.6.30-gnu/arch/avr32/boards/merisc/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/merisc/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -94,9 +94,10 @@
 
 static struct mci_platform_data __initdata mci0_data = {
 	.slot[0] = {
-		.bus_width	= 4,
-		.detect_pin	= GPIO_PIN_PE(19),
-		.wp_pin		= GPIO_PIN_PE(20),
+		.bus_width		= 4,
+		.detect_pin		= GPIO_PIN_PE(19),
+		.wp_pin			= GPIO_PIN_PE(20),
+		.detect_is_active_high	= true,
 	},
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/avr32/boards/mimc200/setup.c linux-libre-2.6.31-gnu/arch/avr32/boards/mimc200/setup.c
--- linux-libre-2.6.30-gnu/arch/avr32/boards/mimc200/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/boards/mimc200/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,16 +43,16 @@
 /* Initialized by bootloader-specific startup code. */
 struct tag *bootloader_tags __initdata;
 
-static struct fb_videomode __initdata tx14d14_modes[] = {
+static struct fb_videomode __initdata pt0434827_modes[] = {
 	{
-		.name		= "640x480 @ 60",
-		.refresh	= 60,
-		.xres		= 640,		.yres		= 480,
-		.pixclock	= KHZ2PICOS(11666),
+		.name		= "480x272 @ 72",
+		.refresh	= 72,
+		.xres		= 480,		.yres		= 272,
+		.pixclock	= KHZ2PICOS(10000),
 
-		.left_margin	= 80,		.right_margin	= 1,
-		.upper_margin	= 13,		.lower_margin	= 2,
-		.hsync_len	= 64,		.vsync_len	= 1,
+		.left_margin	= 1,		.right_margin	= 1,
+		.upper_margin	= 12,		.lower_margin	= 1,
+		.hsync_len	= 42,		.vsync_len	= 1,
 
 		.sync		= 0,
 		.vmode		= FB_VMODE_NONINTERLACED,
@@ -60,14 +60,14 @@
 };
 
 static struct fb_monspecs __initdata mimc200_default_monspecs = {
-	.manufacturer		= "HIT",
-	.monitor		= "TX14D14VM1BAB",
-	.modedb			= tx14d14_modes,
-	.modedb_len		= ARRAY_SIZE(tx14d14_modes),
+	.manufacturer		= "PT",
+	.monitor		= "PT0434827-A401",
+	.modedb			= pt0434827_modes,
+	.modedb_len		= ARRAY_SIZE(pt0434827_modes),
 	.hfmin			= 14820,
 	.hfmax			= 22230,
 	.vfmin			= 60,
-	.vfmax			= 73.3,
+	.vfmax			= 85,
 	.dclkmax		= 25200000,
 };
 
@@ -228,7 +228,8 @@
 	i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info));
 
 	at32_add_device_lcdc(0, &mimc200_lcdc_data,
-			     fbmem_start, fbmem_size, 1);
+			     fbmem_start, fbmem_size,
+			     ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_CONTROL | ATMEL_LCDC_ALT_24B_DATA);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/avr32/configs/atngw100_mrmt_defconfig linux-libre-2.6.31-gnu/arch/avr32/configs/atngw100_mrmt_defconfig
--- linux-libre-2.6.30-gnu/arch/avr32/configs/atngw100_mrmt_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/avr32/configs/atngw100_mrmt_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1363 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc1
+# Wed Jun  3 00:24:53 2009
+#
+CONFIG_AVR32=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=1
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System Type and features
+#
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SUBARCH_AVR32B=y
+CONFIG_MMU=y
+CONFIG_PERFORMANCE_COUNTERS=y
+CONFIG_PLATFORM_AT32AP=y
+CONFIG_CPU_AT32AP700X=y
+CONFIG_CPU_AT32AP7000=y
+# CONFIG_BOARD_ATSTK1000 is not set
+CONFIG_BOARD_ATNGW100=y
+# CONFIG_BOARD_HAMMERHEAD is not set
+# CONFIG_BOARD_FAVR_32 is not set
+# CONFIG_BOARD_MERISC is not set
+# CONFIG_BOARD_MIMC200 is not set
+# CONFIG_BOARD_ATNGW100_ADDON_NONE is not set
+# CONFIG_BOARD_ATNGW100_EVKLCD10X is not set
+CONFIG_BOARD_ATNGW100_MRMT=y
+CONFIG_BOARD_MRMT_REV1=y
+# CONFIG_BOARD_MRMT_REV2 is not set
+CONFIG_BOARD_MRMT_AC97=y
+# CONFIG_BOARD_MRMT_UCB1400_TS is not set
+CONFIG_BOARD_MRMT_ADS7846_TS=y
+# CONFIG_BOARD_MRMT_LCD_DISABLE is not set
+CONFIG_BOARD_MRMT_LCD_LQ043T3DX0X=y
+# CONFIG_BOARD_MRMT_LCD_KWH043GM08 is not set
+CONFIG_BOARD_MRMT_BL_PWM=y
+CONFIG_BOARD_MRMT_RTC_I2C=y
+CONFIG_BOARD_MRMT_WIRELESS_ZB=y
+# CONFIG_BOARD_MRMT_WIRELESS_BT is not set
+# CONFIG_BOARD_MRMT_WIRELESS_NONE is not set
+CONFIG_LOADER_U_BOOT=y
+
+#
+# Atmel AVR32 AP options
+#
+# CONFIG_AP700X_32_BIT_SMC is not set
+CONFIG_AP700X_16_BIT_SMC=y
+# CONFIG_AP700X_8_BIT_SMC is not set
+CONFIG_LOAD_ADDRESS=0x10000000
+CONFIG_ENTRY_ADDRESS=0x90000000
+CONFIG_PHYS_OFFSET=0x10000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_QUICKLIST=y
+# CONFIG_HAVE_ARCH_BOOTMEM is not set
+# CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set
+# CONFIG_NEED_NODE_MEMMAP_SIZE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ARCH_SPARSEMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_OWNERSHIP_TRACE is not set
+# CONFIG_NMI_DEBUGGING is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_CMDLINE=""
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_AT32AP=y
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# 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=y
+# 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_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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 is not set
+# 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_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+# CONFIG_BT_SCO is not set
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+# CONFIG_BT_BNEP is not set
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_LL is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_DATAFLASH=y
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON 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_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_PWM=y
+# CONFIG_ATMEL_TCLIB is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ATMEL_SSC is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MACB=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_WM97XX is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_ATMEL_PDC=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=y
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT32AP700X_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_ATMEL=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_ATMEL_LCDC is not set
+# CONFIG_BACKLIGHT_ATMEL_PWM is not set
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+
+#
+# Atmel devices (AVR32 and AT91)
+#
+# CONFIG_SND_ATMEL_ABDAC is not set
+CONFIG_SND_ATMEL_AC97C=m
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_APPLE is not set
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+CONFIG_USB_GADGET_DEBUG_FILES=y
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_USB_ATMEL_USBA=m
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_ATMELMCI=y
+# CONFIG_MMC_ATMELMCI_DMA is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_ATMEL_PWM=y
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# 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
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_S35390A=m
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_AT32AP700X=m
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+CONFIG_DW_DMAC=y
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -196,6 +196,6 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 
 #endif /*  __ASM_AVR32_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/hw_irq.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/hw_irq.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/hw_irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/hw_irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __ASM_AVR32_HW_IRQ_H
 #define __ASM_AVR32_HW_IRQ_H
 
-static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+static inline void hw_resend_irq(struct irq_chip *h, unsigned int i)
 {
 	/* Nothing to do */
 }
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/mman.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __ASM_AVR32_MMAN_H__
 #define __ASM_AVR32_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -83,7 +83,7 @@
 	quicklist_free_page(QUICK_PT, NULL, pte);
 }
 
-#define __pte_free_tlb(tlb,pte)				\
+#define __pte_free_tlb(tlb,pte,addr)			\
 do {							\
 	pgtable_page_dtor(pte);				\
 	tlb_remove_page((tlb), pte);			\
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/signal.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -112,7 +112,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/termios.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,7 @@
 */
 #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
 
-#include <asm-generic/termios.h>
+#include <asm-generic/termios-base.h>
 
 #endif	/* __KERNEL__ */
 
diff -druN linux-libre-2.6.30-gnu/arch/avr32/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/avr32/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/avr32/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 	.exec_domain	= &default_exec_domain,				\
 	.flags		= 0,						\
 	.cpu		= 0,						\
-	.preempt_count	= 1,						\
+	.preempt_count	= INIT_PREEMPT_COUNT,				\
 	.restart_block	= {						\
 		.fn	= do_no_restart_syscall				\
 	}								\
diff -druN linux-libre-2.6.30-gnu/arch/avr32/kernel/init_task.c linux-libre-2.6.31-gnu/arch/avr32/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/avr32/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,10 +15,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure. Must be aligned on an 8192-byte boundary.
  */
diff -druN linux-libre-2.6.30-gnu/arch/avr32/kernel/module.c linux-libre-2.6.31-gnu/arch/avr32/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/avr32/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,8 +32,6 @@
 	mod->arch.syminfo = NULL;
 
 	vfree(module_region);
-	/* FIXME: if module_region == mod->init_region, trim exception
-	 * table entries. */
 }
 
 static inline int check_rela(Elf32_Rela *rela, struct module *module,
diff -druN linux-libre-2.6.30-gnu/arch/avr32/kernel/process.c linux-libre-2.6.31-gnu/arch/avr32/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/avr32/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -394,8 +394,6 @@
 		goto out;
 
 	error = do_execve(filename, uargv, uenvp, regs);
-	if (error == 0)
-		current->ptrace &= ~PT_DTRACE;
 	putname(filename);
 
 out:
diff -druN linux-libre-2.6.30-gnu/arch/avr32/kernel/signal.c linux-libre-2.6.31-gnu/arch/avr32/kernel/signal.c
--- linux-libre-2.6.30-gnu/arch/avr32/kernel/signal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/kernel/signal.c	2009-09-09 18:13:59.000000000 -0400
@@ -212,7 +212,7 @@
 	return err;
 }
 
-static inline void restart_syscall(struct pt_regs *regs)
+static inline void setup_syscall_restart(struct pt_regs *regs)
 {
 	if (regs->r12 == -ERESTART_RESTARTBLOCK)
 		regs->r8 = __NR_restart_syscall;
@@ -296,7 +296,7 @@
 			}
 			/* fall through */
 		case -ERESTARTNOINTR:
-			restart_syscall(regs);
+			setup_syscall_restart(regs);
 		}
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/avr32/kernel/traps.c linux-libre-2.6.31-gnu/arch/avr32/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/avr32/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,22 +32,25 @@
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 
-	printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG,
+	printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n",
 	       str, err, ++die_counter);
+
+	printk(KERN_EMERG);
+
 #ifdef CONFIG_PREEMPT
-	printk("PREEMPT ");
+	printk(KERN_CONT "PREEMPT ");
 #endif
 #ifdef CONFIG_FRAME_POINTER
-	printk("FRAME_POINTER ");
+	printk(KERN_CONT "FRAME_POINTER ");
 #endif
 	if (current_cpu_data.features & AVR32_FEATURE_OCD) {
 		unsigned long did = ocd_read(DID);
-		printk("chip: 0x%03lx:0x%04lx rev %lu\n",
+		printk(KERN_CONT "chip: 0x%03lx:0x%04lx rev %lu\n",
 		       (did >> 1) & 0x7ff,
 		       (did >> 12) & 0x7fff,
 		       (did >> 28) & 0xf);
 	} else {
-		printk("cpu: arch %u r%u / core %u r%u\n",
+		printk(KERN_CONT "cpu: arch %u r%u / core %u r%u\n",
 		       current_cpu_data.arch_type,
 		       current_cpu_data.arch_revision,
 		       current_cpu_data.cpu_type,
@@ -75,8 +78,17 @@
 {
 	siginfo_t info;
 
-	if (!user_mode(regs))
+	if (!user_mode(regs)) {
+		const struct exception_table_entry *fixup;
+
+		/* Are we prepared to handle this kernel fault? */
+		fixup = search_exception_tables(regs->pc);
+		if (fixup) {
+			regs->pc = fixup->fixup;
+			return;
+		}
 		die("Unhandled exception in kernel mode", regs, signr);
+	}
 
 	memset(&info, 0, sizeof(info));
 	info.si_signo = signr;
diff -druN linux-libre-2.6.30-gnu/arch/avr32/lib/memcpy.S linux-libre-2.6.31-gnu/arch/avr32/lib/memcpy.S
--- linux-libre-2.6.30-gnu/arch/avr32/lib/memcpy.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/lib/memcpy.S	2009-09-09 18:13:59.000000000 -0400
@@ -24,8 +24,8 @@
 	brne	1f
 
 	/* At this point, "from" is word-aligned */
-2:	sub	r10, 4
-	mov	r9, r12
+2:	mov	r9, r12
+5:	sub	r10, 4
 	brlt	4f
 
 3:	ld.w	r8, r11++
@@ -49,6 +49,7 @@
 
 	/* Handle unaligned "from" pointer */
 1:	sub	r10, 4
+	movlt	r9, r12
 	brlt	4b
 	add	r10, r9
 	lsl	r9, 2
@@ -59,4 +60,13 @@
 	st.b	r12++, r8
 	ld.ub	r8, r11++
 	st.b	r12++, r8
-	rjmp	2b
+	mov	r8, r12
+	add	pc, pc, r9
+	sub	r8, 1
+	nop
+	sub	r8, 1
+	nop
+	sub	r8, 1
+	nop
+	mov	r9, r8
+	rjmp	5b
diff -druN linux-libre-2.6.30-gnu/arch/avr32/mach-at32ap/include/mach/board.h linux-libre-2.6.31-gnu/arch/avr32/mach-at32ap/include/mach/board.h
--- linux-libre-2.6.30-gnu/arch/avr32/mach-at32ap/include/mach/board.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/mach-at32ap/include/mach/board.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,7 @@
 /* Flags for selecting USART extra pins */
 #define	ATMEL_USART_RTS		0x01
 #define	ATMEL_USART_CTS		0x02
-#define	ATMEL_USART_CLK		0x03
+#define	ATMEL_USART_CLK		0x04
 
 struct atmel_uart_data {
 	short		use_dma_tx;	/* use transmit DMA? */
diff -druN linux-libre-2.6.30-gnu/arch/avr32/mm/fault.c linux-libre-2.6.31-gnu/arch/avr32/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/avr32/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/avr32/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,7 +133,7 @@
 	 * fault.
 	 */
 survive:
-	fault = handle_mm_fault(mm, vma, address, writeaccess);
+	fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/boot/.gitignore linux-libre-2.6.31-gnu/arch/blackfin/boot/.gitignore
--- linux-libre-2.6.30-gnu/arch/blackfin/boot/.gitignore	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/boot/.gitignore	2009-09-09 18:13:59.000000000 -0400
@@ -1 +1,2 @@
-+vmImage
+vmImage*
+vmlinux*
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/boot/Makefile linux-libre-2.6.31-gnu/arch/blackfin/boot/Makefile
--- linux-libre-2.6.30-gnu/arch/blackfin/boot/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/boot/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,24 +8,41 @@
 
 MKIMAGE := $(srctree)/scripts/mkuboot.sh
 
-targets := vmImage
-extra-y += vmlinux.bin vmlinux.gz
+targets := vmImage vmImage.bz2 vmImage.gz vmImage.lzma
+extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
 
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
-                   -C gzip -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \
+                   -C $(2) -n '$(MACHINE)-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \
                    -e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \
                    -d $< $@
 
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
 
-$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,gzip)
 
-$(obj)/vmImage: $(obj)/vmlinux.gz
-	$(call if_changed,uimage)
-	@$(kecho) 'Kernel: $@ is ready'
+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,bzip2)
+
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,lzma)
+
+$(obj)/vmImage.bz2: $(obj)/vmlinux.bin.bz2
+	$(call if_changed,uimage,bzip2)
+
+$(obj)/vmImage.gz: $(obj)/vmlinux.bin.gz
+	$(call if_changed,uimage,gzip)
+
+$(obj)/vmImage.lzma: $(obj)/vmlinux.bin.lzma
+	$(call if_changed,uimage,lzma)
+
+suffix-$(CONFIG_KERNEL_GZIP)  := gz
+suffix-$(CONFIG_KERNEL_BZIP2) := bz2
+suffix-$(CONFIG_KERNEL_LZMA)  := lzma
+$(obj)/vmImage: $(obj)/vmImage.$(suffix-y)
+	@ln -sf $(notdir $<) $@
 
 install:
 	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -259,7 +259,10 @@
 # CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -323,11 +326,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -404,17 +413,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -688,14 +697,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 # CONFIG_BFIN_SPORT is not set
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 CONFIG_SIMPLE_GPIO=m
 CONFIG_VT=y
 CONFIG_CONSOLE_TRANSLATIONS=y
@@ -802,7 +811,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -831,6 +863,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_REGULATOR is not set
@@ -889,7 +922,7 @@
 # CONFIG_MMC_SDHCI is not set
 CONFIG_SDH_BFIN=m
 CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND=y
-CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ=y
+# CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ is not set
 # CONFIG_MMC_SPI is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -962,7 +995,8 @@
 #
 # File systems
 #
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -988,8 +1022,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
+CONFIG_FAT_FS=m
 # CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1012,8 +1049,8 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
+# CONFIG_YAFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1048,9 +1085,9 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
+CONFIG_NLS=m
 CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -1065,7 +1102,7 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
+CONFIG_NLS_CODEPAGE_936=m
 # CONFIG_NLS_CODEPAGE_950 is not set
 # CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_949 is not set
@@ -1074,7 +1111,7 @@
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1087,7 +1124,7 @@
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
 # CONFIG_DLM is not set
 
 #
@@ -1102,7 +1139,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1111,14 +1148,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1132,7 +1167,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 
 #
 # Tracers
@@ -1148,16 +1182,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1269,7 +1307,6 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -144,8 +144,8 @@
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=0
 CONFIG_BF_REV_MAX=2
-# CONFIG_BF_REV_0_0 is not set
-CONFIG_BF_REV_0_1=y
+CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_1 is not set
 # CONFIG_BF_REV_0_2 is not set
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
@@ -264,7 +264,10 @@
 # CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -328,16 +331,18 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-# CONFIG_MPU is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
 
 #
-# Asynchonous Memory Configuration
+# Memory Protection Unit
 #
+# CONFIG_MPU is not set
 
 #
 # EBIU_AMGCTL Global Control
@@ -409,17 +414,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -491,7 +496,7 @@
 #
 # User Modules And Translation Layers
 #
-CONFIG_MTD_CHAR=m
+CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
@@ -504,9 +509,9 @@
 #
 # RAM/ROM/Flash chip drivers
 #
-# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
 # CONFIG_MTD_CFI_ADV_OPTIONS is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
@@ -518,9 +523,10 @@
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_ROM=m
 # CONFIG_MTD_ABSENT is not set
@@ -529,7 +535,8 @@
 # Mapping drivers for chip access
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_GPIO_ADDR is not set
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
@@ -597,9 +604,42 @@
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
@@ -644,9 +684,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -715,14 +754,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 # CONFIG_BFIN_SPORT is not set
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 CONFIG_SIMPLE_GPIO=m
 CONFIG_VT=y
 CONFIG_CONSOLE_TRANSLATIONS=y
@@ -832,11 +871,35 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD5252 is not set
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADCXX is not set
@@ -920,6 +983,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_REGULATOR is not set
@@ -1008,8 +1072,8 @@
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 # CONFIG_USB_OTG_WHITELIST is not set
@@ -1037,10 +1101,10 @@
 CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_PERIPHERAL is not set
 # CONFIG_USB_MUSB_OTG is not set
-# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
-CONFIG_MUSB_PIO_ONLY=y
-CONFIG_MUSB_DMA_POLL=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
 # CONFIG_USB_MUSB_DEBUG is not set
 
 #
@@ -1058,7 +1122,7 @@
 #
 # see USB_STORAGE Help for more information
 #
-CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
@@ -1107,33 +1171,10 @@
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
-# CONFIG_USB_GADGET_AT91 is not set
-# CONFIG_USB_GADGET_ATMEL_USBA is not set
-# CONFIG_USB_GADGET_FSL_USB2 is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_PXA25X is not set
-# CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
-# CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_AMD5536UDC is not set
-# CONFIG_USB_GADGET_FSL_QE is not set
-# CONFIG_USB_GADGET_NET2272 is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_ZERO is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-# CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_USB_G_PRINTER is not set
-# CONFIG_USB_CDC_COMPOSITE is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -1206,7 +1247,8 @@
 #
 # File systems
 #
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -1226,14 +1268,19 @@
 #
 # CD-ROM/DVD Filesystems
 #
-# CONFIG_ISO9660_FS is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
 # CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
 #
+CONFIG_FAT_FS=m
 # CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1256,16 +1303,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1277,6 +1314,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1313,7 +1360,7 @@
 CONFIG_MSDOS_PARTITION=y
 CONFIG_NLS=m
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -1328,7 +1375,7 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
+CONFIG_NLS_CODEPAGE_936=m
 # CONFIG_NLS_CODEPAGE_950 is not set
 # CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_949 is not set
@@ -1337,7 +1384,7 @@
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1350,7 +1397,7 @@
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
 # CONFIG_DLM is not set
 
 #
@@ -1365,7 +1412,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1374,14 +1421,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1395,7 +1440,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 
 #
 # Tracers
@@ -1411,16 +1455,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1534,7 +1582,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -145,8 +145,8 @@
 CONFIG_BF_REV_MIN=0
 CONFIG_BF_REV_MAX=2
 # CONFIG_BF_REV_0_0 is not set
-CONFIG_BF_REV_0_1=y
-# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_1 is not set
+CONFIG_BF_REV_0_2=y
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
@@ -264,7 +264,10 @@
 # CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -318,7 +321,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-CONFIG_BFIN_GPTIMERS=m
+CONFIG_BFIN_GPTIMERS=y
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -328,11 +331,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -409,17 +418,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -639,9 +648,42 @@
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
@@ -687,9 +729,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -758,14 +799,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-CONFIG_BF5xx_PPI=m
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 CONFIG_SIMPLE_GPIO=m
 CONFIG_VT=y
 CONFIG_CONSOLE_TRANSLATIONS=y
@@ -875,7 +916,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -909,6 +973,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_REGULATOR is not set
@@ -1091,8 +1156,8 @@
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 # CONFIG_USB_OTG_WHITELIST is not set
@@ -1120,10 +1185,10 @@
 CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_PERIPHERAL is not set
 # CONFIG_USB_MUSB_OTG is not set
-# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
-CONFIG_MUSB_PIO_ONLY=y
-CONFIG_MUSB_DMA_POLL=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
 # CONFIG_USB_MUSB_DEBUG is not set
 
 #
@@ -1141,7 +1206,7 @@
 #
 # see USB_STORAGE Help for more information
 #
-CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
@@ -1190,33 +1255,10 @@
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
-# CONFIG_USB_GADGET_AT91 is not set
-# CONFIG_USB_GADGET_ATMEL_USBA is not set
-# CONFIG_USB_GADGET_FSL_USB2 is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_PXA25X is not set
-# CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
-# CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_AMD5536UDC is not set
-# CONFIG_USB_GADGET_FSL_QE is not set
-# CONFIG_USB_GADGET_NET2272 is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_ZERO is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-# CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_USB_G_PRINTER is not set
-# CONFIG_USB_CDC_COMPOSITE is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -1289,7 +1331,8 @@
 #
 # File systems
 #
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -1309,14 +1352,20 @@
 #
 # CD-ROM/DVD Filesystems
 #
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
 #
+CONFIG_FAT_FS=m
 # CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1339,16 +1388,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1360,6 +1399,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1396,7 +1445,7 @@
 CONFIG_MSDOS_PARTITION=y
 CONFIG_NLS=m
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -1411,7 +1460,7 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
+CONFIG_NLS_CODEPAGE_936=m
 # CONFIG_NLS_CODEPAGE_950 is not set
 # CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_949 is not set
@@ -1420,7 +1469,7 @@
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1433,7 +1482,7 @@
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
 # CONFIG_DLM is not set
 
 #
@@ -1448,7 +1497,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1457,14 +1506,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1478,7 +1525,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
 
 #
 # Tracers
@@ -1494,16 +1540,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1611,13 +1661,12 @@
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC_ITU_T=m
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -225,7 +225,10 @@
 CONFIG_SCHED_HRTICK=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -289,12 +292,21 @@
 #
 # Cache Support
 #
+#
+# Cache Support
+#
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -382,17 +394,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -613,9 +625,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -667,13 +678,13 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=y
 # CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
@@ -729,7 +740,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -904,16 +938,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -925,6 +949,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1013,7 +1047,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1022,14 +1056,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1043,7 +1075,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
 
 #
 # Tracers
@@ -1059,16 +1090,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1181,7 +1216,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF533-STAMP_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF533-STAMP_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF533-STAMP_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF533-STAMP_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -225,7 +225,10 @@
 CONFIG_SCHED_HRTICK=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -290,11 +293,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -382,17 +391,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -618,9 +627,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -674,14 +682,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-CONFIG_BF5xx_PPI=m
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
@@ -781,7 +789,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -1068,16 +1099,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1089,6 +1110,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1177,7 +1208,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1186,14 +1217,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1207,7 +1236,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
 
 #
 # Tracers
@@ -1223,16 +1251,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1345,7 +1377,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF537-STAMP_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF537-STAMP_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF537-STAMP_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF537-STAMP_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -232,7 +232,10 @@
 CONFIG_SCHED_HRTICK=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -297,11 +300,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -390,17 +399,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -548,9 +557,7 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=m
-CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -649,9 +656,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -708,14 +714,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-CONFIG_BF5xx_PPI=m
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
@@ -823,7 +829,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -1123,16 +1152,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1144,6 +1163,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1232,7 +1261,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1241,14 +1270,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1262,7 +1289,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
 
 #
 # Tracers
@@ -1278,16 +1304,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1400,7 +1430,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -243,7 +243,10 @@
 CONFIG_SCHED_HRTICK=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -308,11 +311,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -389,17 +398,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -546,9 +555,7 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=m
-CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -691,11 +698,11 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_AD7877 is not set
 # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
 CONFIG_TOUCHSCREEN_AD7879_SPI=y
 CONFIG_TOUCHSCREEN_AD7879=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -720,14 +727,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-CONFIG_BF5xx_PPI=m
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
@@ -833,7 +840,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -1056,16 +1086,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1077,6 +1097,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1165,7 +1195,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1174,14 +1204,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1195,7 +1223,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 
 #
 # Tracers
@@ -1211,16 +1238,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1333,7 +1364,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -196,6 +196,7 @@
 # BF548 Specific Configuration
 #
 # CONFIG_DEB_DMA_URGENT is not set
+# CONFIG_BF548_ATAPI_ALTERNATIVE_PORT is not set
 
 #
 # Interrupt Priority Assignment
@@ -298,7 +299,10 @@
 # CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -362,12 +366,19 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-# CONFIG_BFIN_L2_CACHEABLE is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+# CONFIG_BFIN_L2_ICACHEABLE is not set
+# CONFIG_BFIN_L2_DCACHEABLE is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -447,17 +458,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -616,9 +627,7 @@
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_GPIO_ADDR is not set
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
@@ -696,7 +705,7 @@
 CONFIG_BLK_DEV_SD=y
 # CONFIG_CHR_DEV_ST is not set
 # CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
@@ -718,9 +727,7 @@
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
 # CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_DH is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
@@ -752,9 +759,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -821,11 +827,11 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_ADS7846 is not set
 CONFIG_TOUCHSCREEN_AD7877=m
 # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
 # CONFIG_TOUCHSCREEN_AD7879_SPI is not set
 # CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -858,14 +864,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-CONFIG_BF5xx_PPI=m
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 CONFIG_SIMPLE_GPIO=m
 CONFIG_VT=y
 CONFIG_CONSOLE_TRANSLATIONS=y
@@ -977,7 +983,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -1011,6 +1040,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_REGULATOR is not set
@@ -1193,8 +1223,8 @@
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 # CONFIG_USB_OTG_WHITELIST is not set
@@ -1222,10 +1252,10 @@
 CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_PERIPHERAL is not set
 # CONFIG_USB_MUSB_OTG is not set
-# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
-CONFIG_MUSB_PIO_ONLY=y
-CONFIG_MUSB_DMA_POLL=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
 # CONFIG_USB_MUSB_DEBUG is not set
 
 #
@@ -1243,7 +1273,7 @@
 #
 # see USB_STORAGE Help for more information
 #
-CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
@@ -1292,33 +1322,10 @@
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
-# CONFIG_USB_GADGET_AT91 is not set
-# CONFIG_USB_GADGET_ATMEL_USBA is not set
-# CONFIG_USB_GADGET_FSL_USB2 is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_PXA25X is not set
-# CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
-# CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_AMD5536UDC is not set
-# CONFIG_USB_GADGET_FSL_QE is not set
-# CONFIG_USB_GADGET_NET2272 is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_ZERO is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-# CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_USB_G_PRINTER is not set
-# CONFIG_USB_CDC_COMPOSITE is not set
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
@@ -1414,13 +1421,8 @@
 CONFIG_EXT2_FS_XATTR=y
 # CONFIG_EXT2_FS_POSIX_ACL is not set
 # CONFIG_EXT2_FS_SECURITY is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
 # CONFIG_EXT4_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
@@ -1476,16 +1478,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1497,6 +1489,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1539,63 +1541,47 @@
 #
 # Partition Types
 #
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-# CONFIG_SYSV68_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
 CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=m
 # CONFIG_DLM is not set
 
@@ -1611,7 +1597,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1620,14 +1606,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1641,7 +1625,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
 
 #
 # Tracers
@@ -1657,16 +1640,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1780,7 +1767,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
+# Thu May 21 05:50:01 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,10 +43,11 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -53,16 +55,15 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -71,7 +72,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -148,9 +148,9 @@
 # CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
 # CONFIG_BF_REV_0_2 is not set
-CONFIG_BF_REV_0_3=y
+# CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
-# CONFIG_BF_REV_0_5 is not set
+CONFIG_BF_REV_0_5=y
 # CONFIG_BF_REV_0_6 is not set
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
@@ -179,7 +179,6 @@
 # Core B Support
 #
 CONFIG_BF561_COREB=y
-CONFIG_BF561_COREB_RESET=y
 
 #
 # Interrupt Priority Assignment
@@ -264,7 +263,10 @@
 CONFIG_SCHED_HRTICK=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -329,12 +331,19 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-# CONFIG_BFIN_L2_CACHEABLE is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+# CONFIG_BFIN_L2_ICACHEABLE is not set
+# CONFIG_BFIN_L2_DCACHEABLE is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -415,17 +424,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -570,9 +579,7 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=m
-CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -649,9 +656,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -703,13 +709,13 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 # CONFIG_BFIN_SPORT is not set
 # CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
@@ -765,7 +771,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -897,16 +926,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 CONFIG_JFFS2_FS=m
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -918,6 +937,16 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1006,7 +1035,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -1015,14 +1044,12 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS 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 is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
@@ -1036,7 +1063,6 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
 
 #
 # Tracers
@@ -1052,16 +1078,20 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
-# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_DOUBLEFAULT_PRINT=y
+# CONFIG_DEBUG_DOUBLEFAULT_RESET is not set
+# CONFIG_DEBUG_ICACHE_CHECK is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
-# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 # CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
-CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=1
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
-# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
@@ -1174,7 +1204,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/BlackStamp_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/BlackStamp_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/BlackStamp_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/BlackStamp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -285,11 +285,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -381,7 +387,7 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF527_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF527_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF527_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF527_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -329,11 +329,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -411,17 +417,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -783,7 +789,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
@@ -1223,7 +1252,7 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF533_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF533_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF533_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF533_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -262,12 +262,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -347,16 +352,16 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=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 is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -547,9 +552,9 @@
 CONFIG_SMC91X=y
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
-CONFIG_NETDEV_1000=y
+# CONFIG_NETDEV_1000 is not set
 # CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -641,6 +646,10 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
 #
 # SPI support
 #
@@ -869,7 +878,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF537E_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF537E_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF537E_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF537E_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.16
+# Linux kernel version: 2.6.28.10
+# Wed Jun  3 06:27:41 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -8,48 +9,44 @@
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
 CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=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
-# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -58,37 +55,36 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
-CONFIG_RT_MUTEXES=y
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 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
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -102,9 +98,11 @@
 # CONFIG_DEFAULT_CFQ is not set
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
 
 #
 # Blackfin Processor Options
@@ -113,6 +111,10 @@
 #
 # Processor and Board Settings
 #
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
 # CONFIG_BF522 is not set
 # CONFIG_BF523 is not set
 # CONFIG_BF524 is not set
@@ -125,22 +127,31 @@
 # CONFIG_BF534 is not set
 # CONFIG_BF536 is not set
 CONFIG_BF537=y
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=2
+CONFIG_BF_REV_MAX=3
 # CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
 CONFIG_BF_REV_0_2=y
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF53x=y
-CONFIG_BFIN_SINGLE_CORE=y
 CONFIG_MEM_MT48LC16M16A2TG_75=y
 CONFIG_IRQ_PLL_WAKEUP=7
 CONFIG_IRQ_RTC=8
@@ -150,7 +161,6 @@
 CONFIG_IRQ_SPORT1_RX=9
 CONFIG_IRQ_SPORT1_TX=9
 CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
 CONFIG_IRQ_UART0_RX=10
 CONFIG_IRQ_UART0_TX=10
 CONFIG_IRQ_UART1_RX=10
@@ -169,11 +179,12 @@
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
 CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_SPI=10
 # CONFIG_BFIN537_STAMP is not set
 CONFIG_BFIN537_BLUETECHNIX_CM=y
+# CONFIG_BFIN537_BLUETECHNIX_TCM is not set
 # CONFIG_PNAV10 is not set
 # CONFIG_CAMSIG_MINOTAUR is not set
-# CONFIG_GENERIC_BF537_BOARD is not set
 
 #
 # BF537 Specific Configuration
@@ -196,6 +207,7 @@
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
@@ -215,13 +227,20 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=32
-CONFIG_MEM_ADD_WIDTH=9
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -248,6 +267,12 @@
 CONFIG_CACHELINE_ALIGNED_L1=y
 CONFIG_SYSCALL_TAB_L1=y
 CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
 CONFIG_RAMKERNEL=y
 # CONFIG_ROMKERNEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -256,12 +281,14 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
+CONFIG_VIRT_TO_BUS=y
 # CONFIG_BFIN_GPTIMERS is not set
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -270,12 +297,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -304,36 +336,28 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 
 #
-# PCCARD (PCMCIA/CardBus) support
-#
-
-#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF_FDPIC=y
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
 CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 
 #
 # CPU Frequency scaling
 #
 # CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
@@ -346,6 +370,7 @@
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -358,24 +383,23 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=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_LRO is not set
+# CONFIG_INET_DIAG is not set
 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 is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -384,6 +408,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -393,10 +418,6 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
 # CONFIG_NET_SCHED is not set
 
 #
@@ -404,18 +425,14 @@
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN 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_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -427,10 +444,6 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
@@ -438,6 +451,7 @@
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -450,12 +464,15 @@
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
 #
-# CONFIG_MTD_CFI is not set
+CONFIG_MTD_CFI=y
 # CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
 CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -466,6 +483,10 @@
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
@@ -473,7 +494,8 @@
 #
 # Mapping drivers for chip access
 #
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_GPIO_ADDR=y
 CONFIG_MTD_UCLINUX=y
 # CONFIG_MTD_PLATRAM is not set
 
@@ -498,33 +520,23 @@
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
-
-#
-# Parallel port support
-#
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # 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_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -532,22 +544,17 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_VETH is not set
 CONFIG_PHYLIB=y
 
 #
@@ -561,46 +568,44 @@
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
 # CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
 # CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_SMC91X is not set
 CONFIG_BFIN_MAC=y
 CONFIG_BFIN_MAC_USE_L1=y
 CONFIG_BFIN_TX_DESC_NUM=10
 CONFIG_BFIN_RX_DESC_NUM=20
 # CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMC91X is not set
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE 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
 
 #
@@ -618,15 +623,17 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=y
 # CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_SIMPLE_GPIO is not set
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -655,138 +662,119 @@
 # CAN, the car bus and industrial fieldbus
 #
 # CONFIG_CAN4LINUX is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
 
 #
-# TPM devices
+# Memory mapped GPIO expanders:
 #
-# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
 
 #
-# SPI support
+# I2C GPIO expanders:
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
 
 #
-# Dallas's 1-wire bus
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
 #
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-# CONFIG_DAB is not set
+# CONFIG_VIDEO_MEDIA is not set
 
 #
-# Graphics support
+# Multimedia drivers
 #
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DAB is not set
 
 #
-# Display device support
+# Graphics support
 #
-# CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
-# Sound
+# Display device support
 #
+# CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_SOUND is not set
-
-#
-# USB support
-#
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
 
 #
 # Enable Host or Gadget support to see Inventra options
 #
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 # CONFIG_USB_GADGET is not set
 # CONFIG_MMC is not set
-
-#
-# LED devices
-#
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -796,20 +784,18 @@
 # CONFIG_EXT2_FS_POSIX_ACL is not set
 # CONFIG_EXT2_FS_SECURITY is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -835,7 +821,6 @@
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -848,60 +833,53 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
+# CONFIG_YAFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
 # CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
 # CONFIG_DLM is not set
 
 #
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_DOUBLEFAULT is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -919,13 +897,95 @@
 #
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
 
 #
-# Cryptographic options
+# Crypto core or helper
 #
-# CONFIG_CRYPTO is not set
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
 
 #
 # Library routines
@@ -933,11 +993,12 @@
 CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF537U_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF537U_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF537U_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF537U_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -270,12 +270,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -355,16 +360,16 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=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 is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -556,9 +561,9 @@
 # CONFIG_BFIN_MAC is not set
 # CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
-CONFIG_NETDEV_1000=y
+# CONFIG_NETDEV_1000 is not set
 # CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -652,6 +657,10 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
 #
 # SPI support
 #
@@ -897,7 +906,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF548_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF548_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF548_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF548_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -125,9 +125,9 @@
 CONFIG_BF548=y
 # CONFIG_BF549 is not set
 # CONFIG_BF561 is not set
-CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
-# CONFIG_BF_REV_0_2 is not set
+CONFIG_BF_REV_0_2=y
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
@@ -333,12 +333,19 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+# CONFIG_BFIN_L2_ICACHEABLE is not set
+# CONFIG_BFIN_L2_DCACHEABLE is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -422,17 +429,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -811,6 +818,10 @@
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
 #
 # SPI support
 #
@@ -1330,7 +1341,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_SAMPLES is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF561_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF561_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/CM-BF561_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/CM-BF561_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -308,12 +308,19 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+# CONFIG_BFIN_L2_ICACHEABLE is not set
+# CONFIG_BFIN_L2_DCACHEABLE is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -389,17 +396,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -569,9 +576,9 @@
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
+# CONFIG_NETDEV_1000 is not set
 # CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -646,6 +653,10 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
 #
 # SPI support
 #
@@ -833,7 +844,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_SAMPLES is not set
 CONFIG_DEBUG_MMRS=y
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/H8606_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/H8606_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/H8606_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/H8606_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
@@ -258,12 +258,18 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_ICACHE_LOCK=y
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
+# CONFIG_MPU is not set
 
 #
 # Asynchonous Memory Configuration
@@ -347,7 +353,7 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
@@ -594,8 +600,8 @@
 # CONFIG_SMC91X is not set
 # CONFIG_SMSC911X is not set
 CONFIG_DM9000=y
-CONFIG_NETDEV_1000=y
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 # CONFIG_AX88180 is not set
 
 #
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/IP0X_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/IP0X_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/IP0X_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/IP0X_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -355,7 +355,7 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
@@ -672,9 +672,9 @@
 # CONFIG_SMC91X is not set
 # CONFIG_SMSC911X is not set
 CONFIG_DM9000=y
-CONFIG_NETDEV_1000=y
+# CONFIG_NETDEV_1000 is not set
 # CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/PNAV-10_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/PNAV-10_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/PNAV-10_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/PNAV-10_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.7
+# Linux kernel version: 2.6.28.10
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -40,26 +40,26 @@
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -68,7 +68,6 @@
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
@@ -229,7 +228,10 @@
 # CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -293,11 +295,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -374,17 +382,17 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# 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 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_LRO is not set
-CONFIG_INET_DIAG=y
+# CONFIG_INET_DIAG is not set
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -598,9 +606,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_AX88180 is not set
-CONFIG_NETDEV_10000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Wireless LAN
@@ -640,11 +647,11 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_ADS7846 is not set
 CONFIG_TOUCHSCREEN_AD7877=y
 # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
 # CONFIG_TOUCHSCREEN_AD7879_SPI is not set
 # CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -676,14 +683,14 @@
 # Character devices
 #
 # CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=y
 # CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_TWI_LCD=m
-CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_TWI_LCD is not set
 # CONFIG_SIMPLE_GPIO is not set
 # CONFIG_VT is not set
 CONFIG_DEVKMEM=y
@@ -796,6 +803,7 @@
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD5252 is not set
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADCXX is not set
@@ -867,6 +875,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_REGULATOR is not set
@@ -1111,6 +1120,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 CONFIG_YAFFS_FS=y
 CONFIG_YAFFS_YAFFS1=y
 # CONFIG_YAFFS_9BYTE_TAGS is not set
@@ -1121,7 +1131,6 @@
 # CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
 # CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
 CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
-# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1213,7 +1222,6 @@
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
 
 #
 # Tracers
@@ -1343,7 +1351,6 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/SRV1_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/SRV1_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/SRV1_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/SRV1_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -52,7 +52,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -279,12 +279,18 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
+# CONFIG_MPU is not set
 
 #
 # Asynchonous Memory Configuration
@@ -373,7 +379,7 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
+# CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/configs/TCM-BF537_defconfig linux-libre-2.6.31-gnu/arch/blackfin/configs/TCM-BF537_defconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/configs/TCM-BF537_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/configs/TCM-BF537_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -42,7 +42,7 @@
 # CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 # CONFIG_HOTPLUG is not set
@@ -287,11 +287,17 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
+# CONFIG_BFIN_ICACHE_LOCK is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-# CONFIG_BFIN_ICACHE_LOCK is not set
-CONFIG_BFIN_WB=y
-# CONFIG_BFIN_WT is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+
+#
+# Memory Protection Unit
+#
 # CONFIG_MPU is not set
 
 #
@@ -537,7 +543,30 @@
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -686,7 +715,7 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,24 +1,21 @@
 #ifndef __ARCH_BLACKFIN_ATOMIC__
 #define __ARCH_BLACKFIN_ATOMIC__
 
+#ifndef CONFIG_SMP
+# include <asm-generic/atomic.h>
+#else
+
 #include <linux/types.h>
 #include <asm/system.h>	/* local_irq_XXX() */
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc..
- *
- * Generally we do not concern about SMP BFIN systems, so we don't have
- * to deal with that.
- *
- * Tony Kou (tonyko@lineo.ca)   Lineo Inc.   2001
  */
 
 #define ATOMIC_INIT(i)	{ (i) }
 #define atomic_set(v, i)	(((v)->counter) = i)
 
-#ifdef CONFIG_SMP
-
 #define atomic_read(v)	__raw_uncached_fetch_asm(&(v)->counter)
 
 asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
@@ -84,100 +81,6 @@
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc() barrier()
 
-#else /* !CONFIG_SMP */
-
-#define atomic_read(v)	((v)->counter)
-
-static inline void atomic_add(int i, atomic_t *v)
-{
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter += i;
-	local_irq_restore_hw(flags);
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter -= i;
-	local_irq_restore_hw(flags);
-
-}
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-	int __temp = 0;
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter += i;
-	__temp = v->counter;
-	local_irq_restore_hw(flags);
-
-
-	return __temp;
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	int __temp = 0;
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter -= i;
-	__temp = v->counter;
-	local_irq_restore_hw(flags);
-
-	return __temp;
-}
-
-static inline void atomic_inc(volatile atomic_t *v)
-{
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter++;
-	local_irq_restore_hw(flags);
-}
-
-static inline void atomic_dec(volatile atomic_t *v)
-{
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter--;
-	local_irq_restore_hw(flags);
-}
-
-static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
-{
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter &= ~mask;
-	local_irq_restore_hw(flags);
-}
-
-static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
-{
-	long flags;
-
-	local_irq_save_hw(flags);
-	v->counter |= mask;
-	local_irq_restore_hw(flags);
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#endif /* !CONFIG_SMP */
-
 #define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
 #define atomic_inc_return(v) atomic_add_return(1,(v))
@@ -208,6 +111,8 @@
 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 
-#endif				/* __ARCH_BLACKFIN_ATOMIC __ */
+#endif
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/auxvec.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/auxvec.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/auxvec.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/auxvec.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1 @@
-#ifndef __ASMBFIN_AUXVEC_H
-#define __ASMBFIN_AUXVEC_H
-
-#endif
+#include <asm-generic/auxvec.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bfin-global.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bfin-global.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bfin-global.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bfin-global.h	2009-09-09 18:13:59.000000000 -0400
@@ -31,7 +31,7 @@
 
 #ifndef __ASSEMBLY__
 
-#include <asm-generic/sections.h>
+#include <asm/sections.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 #include <linux/linkage.h>
@@ -99,15 +99,6 @@
 extern unsigned long bfin_sic_iwr[];
 extern unsigned vr_wakeup;
 extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
-extern unsigned long _ramstart, _ramend, _rambase;
-extern unsigned long memory_start, memory_end, physical_mem_end;
-extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
-	_ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
-	_stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
-	_ebss_l2[], _l2_lma_start[];
-
-/* only used when MTD_UCLINUX */
-extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
 
 #ifdef CONFIG_BFIN_ICACHE_LOCK
 extern void cache_grab_lock(int way);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bitops.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bitops.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bitops.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bitops.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,22 @@
 #ifndef _BLACKFIN_BITOPS_H
 #define _BLACKFIN_BITOPS_H
 
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-#include <linux/compiler.h>
-#include <asm/byteorder.h>	/* swab32 */
-
-#ifdef __KERNEL__
+#ifndef CONFIG_SMP
+# include <asm-generic/bitops.h>
+#else
 
 #ifndef _LINUX_BITOPS_H
 #error only <linux/bitops.h> can be included directly
 #endif
 
+#include <linux/compiler.h>
+#include <asm/byteorder.h>	/* swab32 */
+
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/__ffs.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ffz.h>
 
-#ifdef CONFIG_SMP
-
 #include <linux/linkage.h>
 
 asmlinkage int __raw_bit_set_asm(volatile unsigned long *addr, int nr);
@@ -79,188 +75,13 @@
 	return __raw_bit_test_toggle_asm(a, nr & 0x1f);
 }
 
-#else /* !CONFIG_SMP */
-
-#include <asm/system.h>		/* save_flags */
-
-static inline void set_bit(int nr, volatile unsigned long *addr)
-{
-	int *a = (int *)addr;
-	int mask;
-	unsigned long flags;
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	local_irq_save_hw(flags);
-	*a |= mask;
-	local_irq_restore_hw(flags);
-}
-
-static inline void clear_bit(int nr, volatile unsigned long *addr)
-{
-	int *a = (int *)addr;
-	int mask;
-	unsigned long flags;
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	local_irq_save_hw(flags);
-	*a &= ~mask;
-	local_irq_restore_hw(flags);
-}
-
-static inline void change_bit(int nr, volatile unsigned long *addr)
-{
-	int mask, flags;
-	unsigned long *ADDR = (unsigned long *)addr;
-
-	ADDR += nr >> 5;
-	mask = 1 << (nr & 31);
-	local_irq_save_hw(flags);
-	*ADDR ^= mask;
-	local_irq_restore_hw(flags);
-}
-
-static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
-{
-	int mask, retval;
-	volatile unsigned int *a = (volatile unsigned int *)addr;
-	unsigned long flags;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	local_irq_save_hw(flags);
-	retval = (mask & *a) != 0;
-	*a |= mask;
-	local_irq_restore_hw(flags);
-
-	return retval;
-}
-
-static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
-{
-	int mask, retval;
-	volatile unsigned int *a = (volatile unsigned int *)addr;
-	unsigned long flags;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	local_irq_save_hw(flags);
-	retval = (mask & *a) != 0;
-	*a &= ~mask;
-	local_irq_restore_hw(flags);
-
-	return retval;
-}
-
-static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
-{
-	int mask, retval;
-	volatile unsigned int *a = (volatile unsigned int *)addr;
-	unsigned long flags;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	local_irq_save_hw(flags);
-	retval = (mask & *a) != 0;
-	*a ^= mask;
-	local_irq_restore_hw(flags);
-	return retval;
-}
-
-#endif /* CONFIG_SMP */
-
 /*
  * clear_bit() doesn't provide any barrier for the compiler.
  */
 #define smp_mb__before_clear_bit()	barrier()
 #define smp_mb__after_clear_bit()	barrier()
 
-static inline void __set_bit(int nr, volatile unsigned long *addr)
-{
-	int *a = (int *)addr;
-	int mask;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	*a |= mask;
-}
-
-static inline void __clear_bit(int nr, volatile unsigned long *addr)
-{
-	int *a = (int *)addr;
-	int mask;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	*a &= ~mask;
-}
-
-static inline void __change_bit(int nr, volatile unsigned long *addr)
-{
-	int mask;
-	unsigned long *ADDR = (unsigned long *)addr;
-
-	ADDR += nr >> 5;
-	mask = 1 << (nr & 31);
-	*ADDR ^= mask;
-}
-
-static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
-{
-	int mask, retval;
-	volatile unsigned int *a = (volatile unsigned int *)addr;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	retval = (mask & *a) != 0;
-	*a |= mask;
-	return retval;
-}
-
-static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
-{
-	int mask, retval;
-	volatile unsigned int *a = (volatile unsigned int *)addr;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	retval = (mask & *a) != 0;
-	*a &= ~mask;
-	return retval;
-}
-
-static inline int __test_and_change_bit(int nr,
-					    volatile unsigned long *addr)
-{
-	int mask, retval;
-	volatile unsigned int *a = (volatile unsigned int *)addr;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	retval = (mask & *a) != 0;
-	*a ^= mask;
-	return retval;
-}
-
-static inline int __test_bit(int nr, const void *addr)
-{
-	int *a = (int *)addr;
-	int mask;
-
-	a += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	return ((mask & *a) != 0);
-}
-
-#ifndef CONFIG_SMP
-/*
- * This routine doesn't need irq save and restore ops in UP
- * context.
- */
-static inline int test_bit(int nr, const void *addr)
-{
-	return __test_bit(nr, addr);
-}
-#endif
+#include <asm-generic/bitops/non-atomic.h>
 
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/hweight.h>
@@ -271,10 +92,10 @@
 
 #include <asm-generic/bitops/minix.h>
 
-#endif				/* __KERNEL__ */
-
 #include <asm-generic/bitops/fls.h>
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
+#endif /* CONFIG_SMP */
+
 #endif				/* _BLACKFIN_BITOPS_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -86,6 +86,7 @@
 
 #endif /* __ASSEMBLY__ */
 
+#include <asm/mem_map.h>
 #include <mach/blackfin.h>
 #include <asm/bfin-global.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bug.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bug.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bug.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,13 +2,58 @@
 #define _BLACKFIN_BUG_H
 
 #ifdef CONFIG_BUG
-#define HAVE_ARCH_BUG
 
-#define BUG() do { \
-	dump_bfin_trace_buffer(); \
-	printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
-	panic("BUG!"); \
-} while (0)
+#define BFIN_BUG_OPCODE	0xefcd
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+
+#define _BUG_OR_WARN(flags)						\
+	asm volatile(							\
+		"1:	.hword	%0\n"					\
+		"	.section __bug_table,\"a\",@progbits\n"		\
+		"2:	.long	1b\n"					\
+		"	.long	%1\n"					\
+		"	.short	%2\n"					\
+		"	.short	%3\n"					\
+		"	.org	2b + %4\n"				\
+		"	.previous"					\
+		:							\
+		: "i"(BFIN_BUG_OPCODE), "i"(__FILE__),			\
+		  "i"(__LINE__), "i"(flags),				\
+		  "i"(sizeof(struct bug_entry)))
+
+#else
+
+#define _BUG_OR_WARN(flags)						\
+	asm volatile(							\
+		"1:	.hword	%0\n"					\
+		"	.section __bug_table,\"a\",@progbits\n"		\
+		"2:	.long	1b\n"					\
+		"	.short	%1\n"					\
+		"	.org	2b + %2\n"				\
+		"	.previous"					\
+		:							\
+		: "i"(BFIN_BUG_OPCODE), "i"(flags),			\
+		  "i"(sizeof(struct bug_entry)))
+
+#endif /* CONFIG_DEBUG_BUGVERBOSE */
+
+#define BUG()								\
+	do {								\
+		_BUG_OR_WARN(0);					\
+		for (;;);						\
+	} while (0)
+
+#define WARN_ON(condition)							\
+	({								\
+		int __ret_warn_on = !!(condition);			\
+		if (unlikely(__ret_warn_on))				\
+			_BUG_OR_WARN(BUGFLAG_WARNING);			\
+		unlikely(__ret_warn_on);				\
+	})
+
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_WARN_ON
 
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bugs.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bugs.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/bugs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/bugs.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,16 +1 @@
-/*
- *  include/asm-blackfin/bugs.h
- *
- *  Copyright (C) 1994  Linus Torvalds
- */
-
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- *	void check_bugs(void);
- */
-
-static void check_bugs(void)
-{
-}
+#include <asm-generic/bugs.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cacheflush.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cacheflush.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cacheflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cacheflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,12 +30,14 @@
 #ifndef _BLACKFIN_CACHEFLUSH_H
 #define _BLACKFIN_CACHEFLUSH_H
 
-extern void blackfin_icache_dcache_flush_range(unsigned long start_address, unsigned long end_address);
+#include <asm/blackfin.h>	/* for SSYNC() */
+
 extern void blackfin_icache_flush_range(unsigned long start_address, unsigned long end_address);
 extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address);
 extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address);
 extern void blackfin_dflush_page(void *page);
 extern void blackfin_invalidate_entire_dcache(void);
+extern void blackfin_invalidate_entire_icache(void);
 
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
@@ -54,32 +56,28 @@
 
 static inline void flush_icache_range(unsigned start, unsigned end)
 {
-#if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE)
-
-# if defined(CONFIG_BFIN_WT)
-	blackfin_icache_flush_range((start), (end));
-	flush_icache_range_others(start, end);
-# else
-	blackfin_icache_dcache_flush_range((start), (end));
-# endif
-
-#else
+#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
+	blackfin_dcache_flush_range(start, end);
+#endif
 
-# if defined(CONFIG_BFIN_ICACHE)
-	blackfin_icache_flush_range((start), (end));
+	/* Make sure all write buffers in the data side of the core
+	 * are flushed before trying to invalidate the icache.  This
+	 * needs to be after the data flush and before the icache
+	 * flush so that the SSYNC does the right thing in preventing
+	 * the instruction prefetcher from hitting things in cached
+	 * memory at the wrong time -- it runs much further ahead than
+	 * the pipeline.
+	 */
+	SSYNC();
+#if defined(CONFIG_BFIN_ICACHE)
+	blackfin_icache_flush_range(start, end);
 	flush_icache_range_others(start, end);
-# endif
-# if defined(CONFIG_BFIN_DCACHE)
-	blackfin_dcache_flush_range((start), (end));
-# endif
-
 #endif
 }
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
 do { memcpy(dst, src, len);						\
      flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len));	\
-     flush_icache_range_others((unsigned long) (dst), (unsigned long) (dst) + (len));\
 } while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len)	memcpy(dst, src, len)
@@ -89,9 +87,9 @@
 #else
 # define invalidate_dcache_range(start,end)	do { } while (0)
 #endif
-#if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_WB)
+#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
 # define flush_dcache_range(start,end)		blackfin_dcache_flush_range((start), (end))
-# define flush_dcache_page(page)			blackfin_dflush_page(page_address(page))
+# define flush_dcache_page(page)		blackfin_dflush_page(page_address(page))
 #else
 # define flush_dcache_range(start,end)		do { } while (0)
 # define flush_dcache_page(page)		do { } while (0)
@@ -100,9 +98,9 @@
 extern unsigned long reserved_mem_dcache_on;
 extern unsigned long reserved_mem_icache_on;
 
-static inline int bfin_addr_dcachable(unsigned long addr)
+static inline int bfin_addr_dcacheable(unsigned long addr)
 {
-#ifdef CONFIG_BFIN_DCACHE
+#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE
 	if (addr < (_ramend - DMA_UNCACHED_REGION))
 		return 1;
 #endif
@@ -111,6 +109,11 @@
 		addr >= _ramend && addr < physical_mem_end)
 		return 1;
 
+#ifdef CONFIG_BFIN_L2_DCACHEABLE
+	if (addr >= L2_START && addr < L2_START + L2_LENGTH)
+		return 1;
+#endif
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cache.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cache.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cache.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cache.h	2009-09-09 18:13:59.000000000 -0400
@@ -34,9 +34,13 @@
 #define L1_CACHE_SHIFT_MAX	5
 
 #if defined(CONFIG_SMP) && \
-    !defined(CONFIG_BFIN_CACHE_COHERENT) && \
-    defined(CONFIG_BFIN_DCACHE)
-#define __ARCH_SYNC_CORE_DCACHE
+    !defined(CONFIG_BFIN_CACHE_COHERENT)
+# if defined(CONFIG_BFIN_ICACHEABLE) || defined(CONFIG_BFIN_L2_ICACHEABLE)
+# define __ARCH_SYNC_CORE_ICACHE
+# endif
+# if defined(CONFIG_BFIN_DCACHEABLE) || defined(CONFIG_BFIN_L2_DCACHEABLE)
+# define __ARCH_SYNC_CORE_DCACHE
+# endif
 #ifndef __ASSEMBLY__
 asmlinkage void __raw_smp_mark_barrier_asm(void);
 asmlinkage void __raw_smp_check_barrier_asm(void);
@@ -51,6 +55,7 @@
 }
 
 void resync_core_dcache(void);
+void resync_core_icache(void);
 #endif
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/context.S linux-libre-2.6.31-gnu/arch/blackfin/include/asm/context.S
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/context.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/context.S	2009-09-09 18:13:59.000000000 -0400
@@ -223,9 +223,10 @@
 	[--sp] = RETN;
 	[--sp] = RETE;
 	[--sp] = SEQSTAT;
-#ifdef CONFIG_KGDB
-	r1.l = lo(IPEND);
-	r1.h = hi(IPEND);
+#ifdef CONFIG_DEBUG_KERNEL
+	p1.l = lo(IPEND);
+	p1.h = hi(IPEND);
+	r1 = [p1];
 	[--sp] = r1;
 #else
 	[--sp] = r0;	/* Skip IPEND as well. */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cplb.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cplb.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cplb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cplb.h	2009-09-09 18:13:59.000000000 -0400
@@ -37,8 +37,6 @@
 #define L1_IMEMORY        (               CPLB_USER_RD | CPLB_VALID | CPLB_LOCK)
 #define SDRAM_INON_CHBL   (               CPLB_USER_RD | CPLB_VALID)
 
-/*Use the menuconfig cache policy here - CONFIG_BFIN_WT/CONFIG_BFIN_WB*/
-
 #if ANOMALY_05000158
 #define ANOMALY_05000158_WORKAROUND             0x200
 #else
@@ -47,35 +45,42 @@
 
 #define CPLB_COMMON	(CPLB_DIRTY | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
 
-#ifdef CONFIG_BFIN_WB         /*Write Back Policy */
+#ifdef CONFIG_BFIN_EXTMEM_WRITEBACK
 #define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_COMMON)
-#else                           /*Write Through */
+#elif defined(CONFIG_BFIN_EXTMEM_WRITETHROUGH)
 #define SDRAM_DGENERIC   (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW  | CPLB_COMMON)
+#else
+#define SDRAM_DGENERIC   (CPLB_COMMON)
 #endif
 
+#define SDRAM_DNON_CHBL  (CPLB_COMMON)
+#define SDRAM_EBIU       (CPLB_COMMON)
+#define SDRAM_OOPS       (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
+
 #define L1_DMEMORY       (CPLB_LOCK | CPLB_COMMON)
 
 #ifdef CONFIG_SMP
-#define L2_ATTR           (INITIAL_T | I_CPLB | D_CPLB)
-#define L2_IMEMORY         (CPLB_COMMON | CPLB_LOCK)
-#define L2_DMEMORY         (CPLB_COMMON | CPLB_LOCK)
+#define L2_ATTR          (INITIAL_T | I_CPLB | D_CPLB)
+#define L2_IMEMORY       (CPLB_COMMON | PAGE_SIZE_1MB)
+#define L2_DMEMORY       (CPLB_LOCK | CPLB_COMMON | PAGE_SIZE_1MB)
 
 #else
-#ifdef CONFIG_BFIN_L2_CACHEABLE
-#define L2_IMEMORY        (SDRAM_IGENERIC)
-#define L2_DMEMORY        (SDRAM_DGENERIC)
-#else
-#define L2_IMEMORY        (CPLB_COMMON)
-#define L2_DMEMORY        (CPLB_COMMON)
-#endif /* CONFIG_BFIN_L2_CACHEABLE */
+#define L2_ATTR          (INITIAL_T | SWITCH_T | I_CPLB | D_CPLB)
+# if defined(CONFIG_BFIN_L2_ICACHEABLE)
+# define L2_IMEMORY      (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | PAGE_SIZE_1MB)
+# else
+# define L2_IMEMORY      (               CPLB_USER_RD | CPLB_VALID | PAGE_SIZE_1MB)
+# endif
 
-#define L2_ATTR           (INITIAL_T | SWITCH_T | I_CPLB | D_CPLB)
+# if defined(CONFIG_BFIN_L2_WRITEBACK)
+# define L2_DMEMORY      (CPLB_L1_CHBL | CPLB_COMMON | PAGE_SIZE_1MB)
+# elif defined(CONFIG_BFIN_L2_WRITETHROUGH)
+# define L2_DMEMORY      (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_COMMON | PAGE_SIZE_1MB)
+# else
+# define L2_DMEMORY      (CPLB_COMMON | PAGE_SIZE_1MB)
+# endif
 #endif /* CONFIG_SMP */
 
-#define SDRAM_DNON_CHBL  (CPLB_COMMON)
-#define SDRAM_EBIU       (CPLB_COMMON)
-#define SDRAM_OOPS       (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
-
 #define SIZE_1K 0x00000400      /* 1K */
 #define SIZE_4K 0x00001000      /* 4K */
 #define SIZE_1M 0x00100000      /* 1M */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cpu.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cpu.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,8 +32,8 @@
 	struct task_struct *idle;
 	unsigned int imemctl;
 	unsigned int dmemctl;
-	unsigned long loops_per_jiffy;
 	unsigned long dcache_invld_count;
+	unsigned long icache_invld_count;
 };
 
 DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cputime.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cputime.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/cputime.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/cputime.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef __BLACKFIN_CPUTIME_H
-#define __BLACKFIN_CPUTIME_H
-
 #include <asm-generic/cputime.h>
-
-#endif				/* __BLACKFIN_CPUTIME_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/current.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/current.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/current.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/current.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,23 +1 @@
-#ifndef _BLACKFIN_CURRENT_H
-#define _BLACKFIN_CURRENT_H
-/*
- *	current.h
- *	(C) Copyright 2000, Lineo, David McCullough <davidm@lineo.com>
- *
- *	rather than dedicate a register (as the m68k source does), we
- *	just keep a global,  we should probably just change it all to be
- *	current and lose _current_task.
- */
-#include <linux/thread_info.h>
-
-struct task_struct;
-
-static inline struct task_struct *get_current(void) __attribute__ ((__const__));
-static inline struct task_struct *get_current(void)
-{
-	return (current_thread_info()->task);
-}
-
-#define	current	(get_current())
-
-#endif				/* _BLACKFIN_CURRENT_H */
+#include <asm-generic/current.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/device.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/device.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/device.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/device.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
 #include <asm-generic/device.h>
-
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/dma.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/dma.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -206,10 +206,16 @@
 
 static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize)
 {
+	/* Make sure the internal data buffers in the core are drained
+	 * so that the DMA descriptors are completely written when the
+	 * DMA engine goes to fetch them below.
+	 */
+	SSYNC();
+
+	dma_ch[channel].regs->next_desc_ptr = sg;
 	dma_ch[channel].regs->cfg =
 		(dma_ch[channel].regs->cfg & ~(0xf << 8)) |
 		((ndsize & 0xf) << 8);
-	dma_ch[channel].regs->next_desc_ptr = sg;
 }
 
 static inline int dma_channel_active(unsigned int channel)
@@ -253,5 +259,7 @@
 void *dma_memcpy(void *dest, const void *src, size_t count);
 void *safe_dma_memcpy(void *dest, const void *src, size_t count);
 void blackfin_dma_early_init(void);
+void early_dma_memcpy(void *dest, const void *src, size_t count);
+void early_dma_memcpy_done(void);
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -95,4 +95,17 @@
 					enum dma_data_direction dir)
 {
 }
+
+static inline void dma_sync_sg_for_cpu(struct device *dev,
+					struct scatterlist *sg,
+					int nents, enum dma_data_direction dir)
+{
+}
+
+static inline void dma_sync_sg_for_device(struct device *dev,
+					struct scatterlist *sg,
+					int nents, enum dma_data_direction dir)
+{
+}
+
 #endif				/* _BLACKFIN_DMA_MAPPING_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/elf.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/elf.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/elf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/elf.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,7 +20,7 @@
 
 typedef unsigned long elf_greg_t;
 
-#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+#define ELF_NGREG 40 /* (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) */
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 typedef struct user_bfinfp_struct elf_fpregset_t;
@@ -55,50 +55,50 @@
 #define ELF_FDPIC_CORE_EFLAGS	EF_BFIN_FDPIC
 #define ELF_EXEC_PAGESIZE	4096
 
-#define	R_unused0	0	/* relocation type 0 is not defined */
-#define R_pcrel5m2	1	/*LSETUP part a */
-#define R_unused1	2	/* relocation type 2 is not defined */
-#define R_pcrel10	3	/* type 3, if cc jump <target>  */
-#define R_pcrel12_jump	4	/* type 4, jump <target> */
-#define R_rimm16	5	/* type 0x5, rN = <target> */
-#define R_luimm16	6	/* # 0x6, preg.l=<target> Load imm 16 to lower half */
-#define R_huimm16  	7	/* # 0x7, preg.h=<target> Load imm 16 to upper half */
-#define R_pcrel12_jump_s 8	/* # 0x8 jump.s <target> */
-#define R_pcrel24_jump_x 9	/* # 0x9 jump.x <target> */
-#define R_pcrel24       10	/* # 0xa call <target> , not expandable */
-#define R_unusedb       11	/* # 0xb not generated */
-#define R_unusedc       12	/* # 0xc  not used */
-#define R_pcrel24_jump_l 13	/*0xd jump.l <target> */
-#define R_pcrel24_call_x 14	/* 0xE, call.x <target> if <target> is above 24 bit limit call through P1 */
-#define R_var_eq_symb    15	/* 0xf, linker should treat it same as 0x12 */
-#define R_byte_data      16	/* 0x10, .byte var = symbol */
-#define R_byte2_data     17	/* 0x11, .byte2 var = symbol */
-#define R_byte4_data     18	/* 0x12, .byte4 var = symbol and .var var=symbol */
-#define R_pcrel11        19	/* 0x13, lsetup part b */
-#define R_unused14      20	/* 0x14, undefined */
-#define R_unused15       21	/* not generated by VDSP 3.5 */
+#define R_BFIN_UNUSED0         0   /* relocation type 0 is not defined */
+#define R_BFIN_PCREL5M2        1   /* LSETUP part a */
+#define R_BFIN_UNUSED1         2   /* relocation type 2 is not defined */
+#define R_BFIN_PCREL10         3   /* type 3, if cc jump <target> */
+#define R_BFIN_PCREL12_JUMP    4   /* type 4, jump <target> */
+#define R_BFIN_RIMM16          5   /* type 0x5, rN = <target> */
+#define R_BFIN_LUIMM16         6   /* # 0x6, preg.l=<target> Load imm 16 to lower half */
+#define R_BFIN_HUIMM16         7   /* # 0x7, preg.h=<target> Load imm 16 to upper half */
+#define R_BFIN_PCREL12_JUMP_S  8   /* # 0x8 jump.s <target> */
+#define R_BFIN_PCREL24_JUMP_X  9   /* # 0x9 jump.x <target> */
+#define R_BFIN_PCREL24         10  /* # 0xa call <target> , not expandable */
+#define R_BFIN_UNUSEDB         11  /* # 0xb not generated */
+#define R_BFIN_UNUSEDC         12  /* # 0xc  not used */
+#define R_BFIN_PCREL24_JUMP_L  13  /* 0xd jump.l <target> */
+#define R_BFIN_PCREL24_CALL_X  14  /* 0xE, call.x <target> if <target> is above 24 bit limit call through P1 */
+#define R_BFIN_VAR_EQ_SYMB     15  /* 0xf, linker should treat it same as 0x12 */
+#define R_BFIN_BYTE_DATA       16  /* 0x10, .byte var = symbol */
+#define R_BFIN_BYTE2_DATA      17  /* 0x11, .byte2 var = symbol */
+#define R_BFIN_BYTE4_DATA      18  /* 0x12, .byte4 var = symbol and .var var=symbol */
+#define R_BFIN_PCREL11         19  /* 0x13, lsetup part b */
+#define R_BFIN_UNUSED14        20  /* 0x14, undefined */
+#define R_BFIN_UNUSED15        21  /* not generated by VDSP 3.5 */
 
 /* arithmetic relocations */
-#define R_push		 0xE0
-#define R_const		 0xE1
-#define R_add		 0xE2
-#define R_sub		 0xE3
-#define R_mult		 0xE4
-#define R_div		 0xE5
-#define R_mod		 0xE6
-#define R_lshift	 0xE7
-#define R_rshift	 0xE8
-#define R_and		 0xE9
-#define R_or		 0xEA
-#define R_xor		 0xEB
-#define R_land		 0xEC
-#define R_lor		 0xED
-#define R_len		 0xEE
-#define R_neg		 0xEF
-#define R_comp		 0xF0
-#define R_page		 0xF1
-#define R_hwpage	 0xF2
-#define R_addr		 0xF3
+#define R_BFIN_PUSH            0xE0
+#define R_BFIN_CONST           0xE1
+#define R_BFIN_ADD             0xE2
+#define R_BFIN_SUB             0xE3
+#define R_BFIN_MULT            0xE4
+#define R_BFIN_DIV             0xE5
+#define R_BFIN_MOD             0xE6
+#define R_BFIN_LSHIFT          0xE7
+#define R_BFIN_RSHIFT          0xE8
+#define R_BFIN_AND             0xE9
+#define R_BFIN_OR              0xEA
+#define R_BFIN_XOR             0xEB
+#define R_BFIN_LAND            0xEC
+#define R_BFIN_LOR             0xED
+#define R_BFIN_LEN             0xEE
+#define R_BFIN_NEG             0xEF
+#define R_BFIN_COMP            0xF0
+#define R_BFIN_PAGE            0xF1
+#define R_BFIN_HWPAGE          0xF2
+#define R_BFIN_ADDR            0xF3
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
    use of this is to invoke "./ld.so someprog" to test out a new version of
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/emergency-restart.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/emergency-restart.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/emergency-restart.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/emergency-restart.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
 #include <asm-generic/emergency-restart.h>
-
-#endif				/* _ASM_EMERGENCY_RESTART_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/entry.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/entry.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/entry.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/entry.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,21 +35,39 @@
 #else
 # define LOAD_IPIPE_IPEND
 #endif
+
+#ifndef CONFIG_EXACT_HWERR
+/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
+ * otherwise it is a waste of cycles.
+ */
+# ifndef CONFIG_DEBUG_KERNEL
 #define INTERRUPT_ENTRY(N)						\
     [--sp] = SYSCFG;							\
-									\
     [--sp] = P0;	/*orig_p0*/					\
     [--sp] = R0;	/*orig_r0*/					\
     [--sp] = (R7:0,P5:0);						\
     R0 = (N);								\
     LOAD_IPIPE_IPEND							\
     jump __common_int_entry;
+# else /* CONFIG_DEBUG_KERNEL */
+#define INTERRUPT_ENTRY(N)						\
+    [--sp] = SYSCFG;							\
+    [--sp] = P0;	/*orig_p0*/					\
+    [--sp] = R0;	/*orig_r0*/					\
+    [--sp] = (R7:0,P5:0);						\
+    p0.l = lo(IPEND);							\
+    p0.h = hi(IPEND);							\
+    r1 = [p0];								\
+    R0 = (N);								\
+    LOAD_IPIPE_IPEND							\
+    jump __common_int_entry;
+# endif /* CONFIG_DEBUG_KERNEL */
 
 /* For timer interrupts, we need to save IPEND, since the user_mode
-	   macro accesses it to determine where to account time.  */
+ *macro accesses it to determine where to account time.
+ */
 #define TIMER_INTERRUPT_ENTRY(N)					\
     [--sp] = SYSCFG;							\
-									\
     [--sp] = P0;	/*orig_p0*/					\
     [--sp] = R0;	/*orig_r0*/					\
     [--sp] = (R7:0,P5:0);						\
@@ -58,6 +76,74 @@
     r1 = [p0];								\
     R0 = (N);								\
     jump __common_int_entry;
+#else /* CONFIG_EXACT_HWERR is defined */
+
+/* if we want hardware error to be exact, we need to do a SSYNC (which forces
+ * read/writes to complete to the memory controllers), and check to see that
+ * caused a pending HW error condition. If so, we assume it was caused by user
+ * space, by setting the same interrupt that we are in (so it goes off again)
+ * and context restore, and a RTI (without servicing anything). This should
+ * cause the pending HWERR to fire, and when that is done, this interrupt will
+ * be re-serviced properly.
+ * As you can see by the code - we actually need to do two SSYNCS - one to
+ * make sure the read/writes complete, and another to make sure the hardware
+ * error is recognized by the core.
+ */
+#define INTERRUPT_ENTRY(N)						\
+    SSYNC;								\
+    SSYNC;								\
+    [--sp] = SYSCFG;							\
+    [--sp] = P0;	/*orig_p0*/					\
+    [--sp] = R0;	/*orig_r0*/					\
+    [--sp] = (R7:0,P5:0);						\
+    R1 = ASTAT;								\
+    P0.L = LO(ILAT);							\
+    P0.H = HI(ILAT);							\
+    R0 = [P0];								\
+    CC = BITTST(R0, EVT_IVHW_P);					\
+    IF CC JUMP 1f;							\
+    ASTAT = R1;								\
+    p0.l = lo(IPEND);							\
+    p0.h = hi(IPEND);							\
+    r1 = [p0];								\
+    R0 = (N);								\
+    LOAD_IPIPE_IPEND							\
+    jump __common_int_entry;						\
+1:  ASTAT = R1;								\
+    RAISE N;								\
+    (R7:0, P5:0) = [SP++];						\
+    SP += 0x8;								\
+    SYSCFG = [SP++];							\
+    CSYNC;								\
+    RTI;
+
+#define TIMER_INTERRUPT_ENTRY(N)					\
+    SSYNC;								\
+    SSYNC;								\
+    [--sp] = SYSCFG;							\
+    [--sp] = P0;	/*orig_p0*/					\
+    [--sp] = R0;	/*orig_r0*/					\
+    [--sp] = (R7:0,P5:0);						\
+    R1 = ASTAT;								\
+    P0.L = LO(ILAT);							\
+    P0.H = HI(ILAT);							\
+    R0 = [P0];								\
+    CC = BITTST(R0, EVT_IVHW_P);					\
+    IF CC JUMP 1f;							\
+    ASTAT = R1;								\
+    p0.l = lo(IPEND);							\
+    p0.h = hi(IPEND);							\
+    r1 = [p0];								\
+    R0 = (N);								\
+    jump __common_int_entry;						\
+1:  ASTAT = R1;								\
+    RAISE N;								\
+    (R7:0, P5:0) = [SP++];						\
+    SP += 0x8;								\
+    SYSCFG = [SP++];							\
+    CSYNC;								\
+    RTI;
+#endif	/* CONFIG_EXACT_HWERR */
 
 /* This one pushes RETI without using CLI.  Interrupts are enabled.  */
 #define SAVE_CONTEXT_SYSCALL	save_context_syscall
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/errno.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/errno.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/errno.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/errno.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _BFIN_ERRNO_H
-#define _BFIN_ERRNO_H
-
-#include<asm-generic/errno.h>
-
-#endif				/* _BFIN_ERRNO_H */
+#include <asm-generic/errno.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/fb.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/fb.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/fb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/fb.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,12 +1 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-
-#define fb_pgprotect(...) do {} while (0)
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
-	return 0;
-}
-
-#endif /* _ASM_FB_H_ */
+#include <asm-generic/fb.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ftrace.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ftrace.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ftrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ftrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -1 +1,13 @@
-/* empty */
+/*
+ * Blackfin ftrace code
+ *
+ * Copyright 2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_FTRACE_H__
+#define __ASM_BFIN_FTRACE_H__
+
+#define MCOUNT_INSN_SIZE	8 /* sizeof mcount call: LINK + CALL */
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/futex.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/futex.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/futex.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/futex.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
 #include <asm-generic/futex.h>
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/gptimers.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/gptimers.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/gptimers.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/gptimers.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 # else
 #  define MAX_BLACKFIN_GPTIMERS 11
 #  define TIMER8_GROUP_REG      TIMER_ENABLE1
+#  define TIMER_GROUP2          1
 # endif
 # define TIMER0_GROUP_REG       TIMER_ENABLE0
 #endif
@@ -40,10 +41,12 @@
 # define MAX_BLACKFIN_GPTIMERS 12
 # define TIMER0_GROUP_REG      TMRS8_ENABLE
 # define TIMER8_GROUP_REG      TMRS4_ENABLE
+# define TIMER_GROUP2          1
 #endif
 /*
  * All others: 3 timers:
  */
+#define TIMER_GROUP1           0
 #if !defined(MAX_BLACKFIN_GPTIMERS)
 # define MAX_BLACKFIN_GPTIMERS 3
 # define TIMER0_GROUP_REG      TIMER_ENABLE
@@ -109,8 +112,8 @@
 #define TIMER_ERR_PROG_PER  0x8000
 #define TIMER_ERR_PROG_PW   0xC000
 #define TIMER_EMU_RUN       0x0200
-#define	TIMER_TOGGLE_HI     0x0100
-#define	TIMER_CLK_SEL       0x0080
+#define TIMER_TOGGLE_HI     0x0100
+#define TIMER_CLK_SEL       0x0080
 #define TIMER_OUT_DIS       0x0040
 #define TIMER_TIN_SEL       0x0020
 #define TIMER_IRQ_ENA       0x0010
@@ -169,23 +172,25 @@
 
 /* The actual gptimer API */
 
-void     set_gptimer_pwidth    (int timer_id, uint32_t width);
-uint32_t get_gptimer_pwidth    (int timer_id);
-void     set_gptimer_period    (int timer_id, uint32_t period);
-uint32_t get_gptimer_period    (int timer_id);
-uint32_t get_gptimer_count     (int timer_id);
-uint16_t get_gptimer_intr      (int timer_id);
-void     clear_gptimer_intr    (int timer_id);
-uint16_t get_gptimer_over      (int timer_id);
-void     clear_gptimer_over    (int timer_id);
-void     set_gptimer_config    (int timer_id, uint16_t config);
-uint16_t get_gptimer_config    (int timer_id);
-void     set_gptimer_pulse_hi  (int timer_id);
+void     set_gptimer_pwidth(int timer_id, uint32_t width);
+uint32_t get_gptimer_pwidth(int timer_id);
+void     set_gptimer_period(int timer_id, uint32_t period);
+uint32_t get_gptimer_period(int timer_id);
+uint32_t get_gptimer_count(int timer_id);
+int      get_gptimer_intr(int timer_id);
+void     clear_gptimer_intr(int timer_id);
+int      get_gptimer_over(int timer_id);
+void     clear_gptimer_over(int timer_id);
+void     set_gptimer_config(int timer_id, uint16_t config);
+uint16_t get_gptimer_config(int timer_id);
+int      get_gptimer_run(int timer_id);
+void     set_gptimer_pulse_hi(int timer_id);
 void     clear_gptimer_pulse_hi(int timer_id);
-void     enable_gptimers       (uint16_t mask);
-void     disable_gptimers      (uint16_t mask);
-uint16_t get_enabled_gptimers  (void);
-uint32_t get_gptimer_status    (int group);
-void     set_gptimer_status    (int group, uint32_t value);
+void     enable_gptimers(uint16_t mask);
+void     disable_gptimers(uint16_t mask);
+void     disable_gptimers_sync(uint16_t mask);
+uint16_t get_enabled_gptimers(void);
+uint32_t get_gptimer_status(int group);
+void     set_gptimer_status(int group, uint32_t value);
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/hardirq.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/hardirq.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/hardirq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/hardirq.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,47 +1,14 @@
 #ifndef __BFIN_HARDIRQ_H
 #define __BFIN_HARDIRQ_H
 
-#include <linux/cache.h>
-#include <linux/threads.h>
-#include <asm/irq.h>
-
-typedef struct {
-	unsigned int __softirq_pending;
-	unsigned int __syscall_count;
-	struct task_struct *__ksoftirqd_task;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
-
-/*
- * We put the hardirq and softirq counter into the preemption
- * counter. The bitmask has the following meaning:
- *
- * - bits 0-7 are the preemption count (max preemption depth: 256)
- * - bits 8-15 are the softirq count (max # of softirqs: 256)
- * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
- *
- * - ( bit 26 is the PREEMPT_ACTIVE flag. )
- *
- * PREEMPT_MASK: 0x000000ff
- * HARDIRQ_MASK: 0x0000ff00
- * SOFTIRQ_MASK: 0x00ff0000
- */
-
-#if NR_IRQS > 256
-#define HARDIRQ_BITS	9
-#else
-#define HARDIRQ_BITS	8
-#endif
-
-#ifdef NR_IRQS
-# if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-# endif
-#endif
-
 #define __ARCH_IRQ_EXIT_IRQS_DISABLED	1
 
 extern void ack_bad_irq(unsigned int irq);
+#define ack_bad_irq ack_bad_irq
+
+/* Define until common code gets sane defaults */
+#define HARDIRQ_BITS 9
+
+#include <asm-generic/hardirq.h>
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/hw_irq.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/hw_irq.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/hw_irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/hw_irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef __ASM_BFIN_HW_IRQ_H
-#define __ASM_BFIN_HW_IRQ_H
-
-/* Dummy include. */
-
-#endif
+#include <asm-generic/hw_irq.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ioctls.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ioctls.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ioctls.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ioctls.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,87 +1,7 @@
 #ifndef __ARCH_BFIN_IOCTLS_H__
 #define __ARCH_BFIN_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT	0x5426	/* For debugging only */
-#define TIOCSBRK	0x5427	/* BSD compatibility */
-#define TIOCCBRK	0x5428	/* BSD compatibility */
-#define TIOCGSID	0x5429	/* Return the session ID of FD */
-#define TCGETS2		_IOR('T', 0x2A, struct termios2)
-#define TCSETS2		_IOW('T', 0x2B, struct termios2)
-#define TCSETSW2	_IOW('T', 0x2C, struct termios2)
-#define TCSETSF2	_IOW('T', 0x2D, struct termios2)
-/* Get Pty Number (of pty-mux device) */
-#define TIOCGPTN	_IOR('T', 0x30, unsigned int)
-#define TIOCSPTLCK	_IOW('T', 0x31, int)	/* Lock/unlock Pty */
-
-#define FIONCLEX	0x5450	/* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458	/* For debugging only */
-#define TIOCSERGETLSR   0x5459	/* Get line status register */
-#define TIOCSERGETMULTI 0x545A	/* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B	/* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-
 #define FIOQSIZE	0x545E
+#include <asm-generic/ioctls.h>
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
-
-#endif				/* __ARCH_BFIN_IOCTLS_H__ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/io.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/io.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -80,19 +80,22 @@
 #define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
 #define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
 
-#define inb(addr)    readb(addr)
-#define inw(addr)    readw(addr)
-#define inl(addr)    readl(addr)
-#define outb(x,addr) ((void) writeb(x,addr))
-#define outw(x,addr) ((void) writew(x,addr))
-#define outl(x,addr) ((void) writel(x,addr))
+/* Convert "I/O port addresses" to actual addresses.  i.e. ugly casts. */
+#define __io(port) ((void *)(unsigned long)(port))
 
-#define inb_p(addr)    inb(addr)
-#define inw_p(addr)    inw(addr)
-#define inl_p(addr)    inl(addr)
-#define outb_p(x,addr) outb(x,addr)
-#define outw_p(x,addr) outw(x,addr)
-#define outl_p(x,addr) outl(x,addr)
+#define inb(port)    readb(__io(port))
+#define inw(port)    readw(__io(port))
+#define inl(port)    readl(__io(port))
+#define outb(x,port) writeb(x,__io(port))
+#define outw(x,port) writew(x,__io(port))
+#define outl(x,port) writel(x,__io(port))
+
+#define inb_p(port)    inb(__io(port))
+#define inw_p(port)    inw(__io(port))
+#define inl_p(port)    inl(__io(port))
+#define outb_p(x,port) outb(x,__io(port))
+#define outw_p(x,port) outw(x,__io(port))
+#define outl_p(x,port) outl(x,__io(port))
 
 #define ioread8_rep(a,d,c)	readsb(a,d,c)
 #define ioread16_rep(a,d,c)	readsw(a,d,c)
@@ -219,7 +222,6 @@
 #define	ioport_unmap(addr)
 
 /* Pages to physical address... */
-#define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
 #define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
 
 #define phys_to_virt(vaddr)	((void *) (vaddr))
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ipcbuf.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ipcbuf.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ipcbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ipcbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,30 +1 @@
-/* Changes origined from m68k version.    Lineo Inc.  May 2001   */
-
-#ifndef __BFIN_IPCBUF_H__
-#define __BFIN_IPCBUF_H__
-
-/*
- * The user_ipc_perm structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm {
-	__kernel_key_t key;
-	__kernel_uid32_t uid;
-	__kernel_gid32_t gid;
-	__kernel_uid32_t cuid;
-	__kernel_gid32_t cgid;
-	__kernel_mode_t mode;
-	unsigned short __pad1;
-	unsigned short seq;
-	unsigned short __pad2;
-	unsigned long __unused1;
-	unsigned long __unused2;
-};
-
-#endif				/* __BFIN_IPCBUF_H__ */
+#include <asm-generic/ipcbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ipipe_base.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ipipe_base.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ipipe_base.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ipipe_base.h	2009-09-09 18:13:59.000000000 -0400
@@ -51,23 +51,23 @@
 
 extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
 
-static inline void __ipipe_stall_root(void)
-{
-	volatile unsigned long *p = &__ipipe_root_status;
-	set_bit(0, p);
-}
+#define __ipipe_stall_root()						\
+	do {								\
+		volatile unsigned long *p = &__ipipe_root_status;	\
+		set_bit(0, p);						\
+	} while (0)
 
-static inline unsigned long __ipipe_test_and_stall_root(void)
-{
-	volatile unsigned long *p = &__ipipe_root_status;
-	return test_and_set_bit(0, p);
-}
+#define __ipipe_test_and_stall_root()					\
+	({								\
+		volatile unsigned long *p = &__ipipe_root_status;	\
+		test_and_set_bit(0, p);					\
+	})
 
-static inline unsigned long __ipipe_test_root(void)
-{
-	const unsigned long *p = &__ipipe_root_status;
-	return test_bit(0, p);
-}
+#define __ipipe_test_root()					\
+	({							\
+		const unsigned long *p = &__ipipe_root_status;	\
+		test_bit(0, p);					\
+	})
 
 #endif /* !__ASSEMBLY__ */
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ipipe.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ipipe.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ipipe.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ipipe.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,9 +35,9 @@
 #include <asm/atomic.h>
 #include <asm/traps.h>
 
-#define IPIPE_ARCH_STRING     "1.9-00"
+#define IPIPE_ARCH_STRING     "1.11-00"
 #define IPIPE_MAJOR_NUMBER    1
-#define IPIPE_MINOR_NUMBER    9
+#define IPIPE_MINOR_NUMBER    11
 #define IPIPE_PATCH_NUMBER    0
 
 #ifdef CONFIG_SMP
@@ -54,10 +54,11 @@
 
 #define task_hijacked(p)						\
 	({								\
-		int __x__ = ipipe_current_domain != ipipe_root_domain;	\
-		/* We would need to clear the SYNC flag for the root domain */ \
-		/* over the current processor in SMP mode. */		\
-		local_irq_enable_hw(); __x__;				\
+		int __x__ = __ipipe_root_domain_p;			\
+		__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
+		if (__x__)						\
+			local_irq_enable_hw();				\
+		!__x__;							\
 	})
 
 struct ipipe_domain;
@@ -179,23 +180,24 @@
 
 #define __ipipe_run_isr(ipd, irq)					\
 	do {								\
-		if (ipd == ipipe_root_domain) {				\
+		if (!__ipipe_pipeline_head_p(ipd))			\
 			local_irq_enable_hw();				\
-			if (ipipe_virtual_irq_p(irq))			\
+		if (ipd == ipipe_root_domain) {				\
+			if (unlikely(ipipe_virtual_irq_p(irq))) {	\
+				irq_enter();				\
 				ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-			else						\
+				irq_exit();				\
+			} else 						\
 				ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
-			local_irq_disable_hw();				\
 		} else {						\
 			__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
-			local_irq_enable_nohead(ipd);			\
 			ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
 			/* Attempt to exit the outer interrupt level before \
 			 * starting the deferred IRQ processing. */	\
-			local_irq_disable_nohead(ipd);			\
 			__ipipe_run_irqtail();				\
 			__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
 		}							\
+		local_irq_disable_hw();					\
 	} while (0)
 
 #define __ipipe_syscall_watched_p(p, sc)	\
@@ -205,7 +207,7 @@
 
 int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
+#ifdef CONFIG_TICKSOURCE_CORETMR
 #define IRQ_SYSTMR		IRQ_CORETMR
 #define IRQ_PRIOTMR		IRQ_CORETMR
 #else
@@ -238,8 +240,13 @@
 #define ipipe_init_irq_threads()		do { } while (0)
 #define ipipe_start_irq_thread(irq, desc)	0
 
+#ifndef CONFIG_TICKSOURCE_GPTMR0
 #define IRQ_SYSTMR		IRQ_CORETMR
 #define IRQ_PRIOTMR		IRQ_CORETMR
+#else
+#define IRQ_SYSTMR		IRQ_TIMER0
+#define IRQ_PRIOTMR		CONFIG_IRQ_TIMER0
+#endif
 
 #define __ipipe_root_tick_p(regs)	1
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/irqflags.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/irqflags.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/irqflags.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/irqflags.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,215 @@
+/*
+ * interface to Blackfin CEC
+ *
+ * Copyright 2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_IRQFLAGS_H__
+#define __ASM_BFIN_IRQFLAGS_H__
+
+#ifdef CONFIG_SMP
+# include <asm/pda.h>
+# include <asm/processor.h>
+/* Forward decl needed due to cdef inter dependencies */
+static inline uint32_t __pure bfin_dspid(void);
+# define blackfin_core_id() (bfin_dspid() & 0xff)
+# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
+#else
+extern unsigned long bfin_irq_flags;
+#endif
+
+static inline void bfin_sti(unsigned long flags)
+{
+	asm volatile("sti %0;" : : "d" (flags));
+}
+
+static inline unsigned long bfin_cli(void)
+{
+	unsigned long flags;
+	asm volatile("cli %0;" : "=d" (flags));
+	return flags;
+}
+
+#ifdef CONFIG_IPIPE
+
+#include <linux/ipipe_base.h>
+#include <linux/ipipe_trace.h>
+
+#ifdef CONFIG_DEBUG_HWERR
+# define bfin_no_irqs 0x3f
+#else
+# define bfin_no_irqs 0x1f
+#endif
+
+#define raw_local_irq_disable()				\
+	do {						\
+		ipipe_check_context(ipipe_root_domain);	\
+		__ipipe_stall_root();			\
+		barrier();				\
+	} while (0)
+
+static inline void raw_local_irq_enable(void)
+{
+	barrier();
+	ipipe_check_context(ipipe_root_domain);
+	__ipipe_unstall_root();
+}
+
+#define raw_local_save_flags_ptr(x)					\
+	do {								\
+		*(x) = __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; \
+	} while (0)
+
+#define raw_local_save_flags(x)		raw_local_save_flags_ptr(&(x))
+
+#define raw_irqs_disabled_flags(x)	((x) == bfin_no_irqs)
+
+#define raw_local_irq_save_ptr(x)					\
+	do {								\
+		*(x) = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; \
+		barrier();						\
+	} while (0)
+
+#define raw_local_irq_save(x)				\
+	do {						\
+		ipipe_check_context(ipipe_root_domain);	\
+		raw_local_irq_save_ptr(&(x));		\
+	} while (0)
+
+static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
+{
+	/*
+	 * Merge virtual and real interrupt mask bits into a single
+	 * 32bit word.
+	 */
+	return (real & ~(1 << 31)) | ((virt != 0) << 31);
+}
+
+static inline int raw_demangle_irq_bits(unsigned long *x)
+{
+	int virt = (*x & (1 << 31)) != 0;
+	*x &= ~(1L << 31);
+	return virt;
+}
+
+static inline void local_irq_disable_hw_notrace(void)
+{
+	bfin_cli();
+}
+
+static inline void local_irq_enable_hw_notrace(void)
+{
+	bfin_sti(bfin_irq_flags);
+}
+
+#define local_save_flags_hw(flags)			\
+	do {						\
+		(flags) = bfin_read_IMASK();		\
+	} while (0)
+
+#define irqs_disabled_flags_hw(flags) (((flags) & ~0x3f) == 0)
+
+#define irqs_disabled_hw()			\
+	({					\
+	unsigned long flags;			\
+	local_save_flags_hw(flags);		\
+	irqs_disabled_flags_hw(flags);		\
+	})
+
+static inline void local_irq_save_ptr_hw(unsigned long *flags)
+{
+	*flags = bfin_cli();
+#ifdef CONFIG_DEBUG_HWERR
+	bfin_sti(0x3f);
+#endif
+}
+
+#define local_irq_save_hw_notrace(flags)		\
+	do {						\
+		local_irq_save_ptr_hw(&(flags));	\
+	} while (0)
+
+static inline void local_irq_restore_hw_notrace(unsigned long flags)
+{
+	if (!irqs_disabled_flags_hw(flags))
+		local_irq_enable_hw_notrace();
+}
+
+#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
+# define local_irq_disable_hw()				\
+	do {						\
+		if (!irqs_disabled_hw()) {		\
+			local_irq_disable_hw_notrace();	\
+			ipipe_trace_begin(0x80000000);	\
+		}					\
+	} while (0)
+# define local_irq_enable_hw()				\
+	do {						\
+		if (irqs_disabled_hw()) {		\
+			ipipe_trace_end(0x80000000);	\
+			local_irq_enable_hw_notrace();	\
+		}					\
+	} while (0)
+# define local_irq_save_hw(flags)			\
+	do {						\
+		local_save_flags_hw(flags);		\
+		if (!irqs_disabled_flags_hw(flags)) {	\
+			local_irq_disable_hw_notrace();	\
+			ipipe_trace_begin(0x80000001);	\
+		}					\
+	} while (0)
+# define local_irq_restore_hw(flags)			\
+	do {						\
+		if (!irqs_disabled_flags_hw(flags)) {	\
+			ipipe_trace_end(0x80000001);	\
+			local_irq_enable_hw_notrace();	\
+		}					\
+	} while (0)
+#else /* !CONFIG_IPIPE_TRACE_IRQSOFF */
+# define local_irq_disable_hw()		local_irq_disable_hw_notrace()
+# define local_irq_enable_hw()		local_irq_enable_hw_notrace()
+# define local_irq_save_hw(flags)	local_irq_save_hw_notrace(flags)
+# define local_irq_restore_hw(flags)	local_irq_restore_hw_notrace(flags)
+#endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
+
+#else /* CONFIG_IPIPE */
+
+static inline void raw_local_irq_disable(void)
+{
+	bfin_cli();
+}
+static inline void raw_local_irq_enable(void)
+{
+	bfin_sti(bfin_irq_flags);
+}
+
+#define raw_local_save_flags(flags) do { (flags) = bfin_read_IMASK(); } while (0)
+
+#define raw_irqs_disabled_flags(flags) (((flags) & ~0x3f) == 0)
+
+static inline unsigned long __raw_local_irq_save(void)
+{
+	unsigned long flags = bfin_cli();
+#ifdef CONFIG_DEBUG_HWERR
+	bfin_sti(0x3f);
+#endif
+	return flags;
+}
+#define raw_local_irq_save(flags) do { (flags) = __raw_local_irq_save(); } while (0)
+
+#define local_irq_save_hw(flags)	raw_local_irq_save(flags)
+#define local_irq_restore_hw(flags)	raw_local_irq_restore(flags)
+#define local_irq_enable_hw()		raw_local_irq_enable()
+#define local_irq_disable_hw()		raw_local_irq_disable()
+#define irqs_disabled_hw()		irqs_disabled()
+
+#endif /* !CONFIG_IPIPE */
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+	if (!raw_irqs_disabled_flags(flags))
+		raw_local_irq_enable();
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/irq.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/irq.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,270 +17,10 @@
 #ifndef _BFIN_IRQ_H_
 #define _BFIN_IRQ_H_
 
-/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h>*/
-#include <mach/irq.h>
-#include <asm/pda.h>
-#include <asm/processor.h>
-
-#ifdef CONFIG_SMP
-/* Forward decl needed due to cdef inter dependencies */
-static inline uint32_t __pure bfin_dspid(void);
-# define blackfin_core_id() (bfin_dspid() & 0xff)
-# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
-#else
-extern unsigned long bfin_irq_flags;
-#endif
-
-#ifdef CONFIG_IPIPE
-
-#include <linux/ipipe_trace.h>
-
-void __ipipe_unstall_root(void);
-
-void __ipipe_restore_root(unsigned long flags);
-
-#ifdef CONFIG_DEBUG_HWERR
-# define __all_masked_irq_flags 0x3f
-# define __save_and_cli_hw(x) \
-	__asm__ __volatile__( \
-		"cli %0;" \
-		"sti %1;" \
-		: "=&d"(x) \
-		: "d" (0x3F) \
-	)
-#else
-# define __all_masked_irq_flags 0x1f
-# define __save_and_cli_hw(x) \
-	__asm__ __volatile__( \
-		"cli %0;" \
-		: "=&d"(x) \
-	)
-#endif
-
-#define irqs_enabled_from_flags_hw(x)	((x) != __all_masked_irq_flags)
-#define raw_irqs_disabled_flags(flags)	(!irqs_enabled_from_flags_hw(flags))
-#define local_test_iflag_hw(x)		irqs_enabled_from_flags_hw(x)
-
-#define local_save_flags(x)					 \
-	do {							 \
-		(x) = __ipipe_test_root() ?			 \
-			__all_masked_irq_flags : bfin_irq_flags; \
-		barrier();					 \
-	} while (0)
-
-#define local_irq_save(x)					 \
-	do {						 	 \
-		(x) = __ipipe_test_and_stall_root() ?		 \
-			__all_masked_irq_flags : bfin_irq_flags; \
-		barrier();					 \
-	} while (0)
-
-static inline void local_irq_restore(unsigned long x)
-{
-	barrier();
-	__ipipe_restore_root(x == __all_masked_irq_flags);
-}
-
-#define local_irq_disable()			\
-	do {					\
-		__ipipe_stall_root();		\
-		barrier();			\
-	} while (0)
-
-static inline void local_irq_enable(void)
-{
-	barrier();
-	__ipipe_unstall_root();
-}
-
-#define irqs_disabled()		__ipipe_test_root()
-
-#define local_save_flags_hw(x) \
-	__asm__ __volatile__( \
-		"cli %0;" \
-		"sti %0;" \
-		: "=d"(x) \
-	)
-
-#define	irqs_disabled_hw()				\
-	({						\
-		unsigned long flags;			\
-		local_save_flags_hw(flags);		\
-		!irqs_enabled_from_flags_hw(flags);	\
-	})
-
-static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
-{
-	/* Merge virtual and real interrupt mask bits into a single
-	   32bit word. */
-	return (real & ~(1 << 31)) | ((virt != 0) << 31);
-}
-
-static inline int raw_demangle_irq_bits(unsigned long *x)
-{
-	int virt = (*x & (1 << 31)) != 0;
-	*x &= ~(1L << 31);
-	return virt;
-}
-
-#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
-
-#define local_irq_disable_hw()						\
-	do {								\
-		int _tmp_dummy;						\
-		if (!irqs_disabled_hw())				\
-			ipipe_trace_begin(0x80000000);			\
-		__asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : );	\
-	} while (0)
-
-#define local_irq_enable_hw()						\
-	do {								\
-		if (irqs_disabled_hw())					\
-			ipipe_trace_end(0x80000000);			\
-		__asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags));	\
-	} while (0)
-
-#define local_irq_save_hw(x)				\
-	do {						\
-		__save_and_cli_hw(x);			\
-		if (local_test_iflag_hw(x))		\
-			ipipe_trace_begin(0x80000001);	\
-	} while (0)
-
-#define local_irq_restore_hw(x)				\
-	do {						\
-		if (local_test_iflag_hw(x)) {		\
-			ipipe_trace_end(0x80000001);	\
-			local_irq_enable_hw_notrace();	\
-		}					\
-	} while (0)
-
-#define local_irq_disable_hw_notrace()					\
-	do {								\
-		int _tmp_dummy;						\
-		__asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : );	\
-	} while (0)
-
-#define local_irq_enable_hw_notrace() \
-	__asm__ __volatile__( \
-		"sti %0;" \
-		: \
-		: "d"(bfin_irq_flags) \
-	)
-
-#define local_irq_save_hw_notrace(x) __save_and_cli_hw(x)
-
-#define local_irq_restore_hw_notrace(x)			\
-	do {						\
-		if (local_test_iflag_hw(x))		\
-			local_irq_enable_hw_notrace();	\
-	} while (0)
-
-#else /* CONFIG_IPIPE_TRACE_IRQSOFF */
-
-#define local_irq_enable_hw() \
-	__asm__ __volatile__( \
-		"sti %0;" \
-		: \
-		: "d"(bfin_irq_flags) \
-	)
-
-#define local_irq_disable_hw()			\
-	do {					\
-		int _tmp_dummy;			\
-		__asm__ __volatile__ (		\
-			"cli %0;"		\
-			: "=d" (_tmp_dummy));	\
-	} while (0)
-
-#define local_irq_restore_hw(x) \
-	do { \
-		if (irqs_enabled_from_flags_hw(x)) \
-			local_irq_enable_hw(); \
-	} while (0)
-
-#define local_irq_save_hw(x)		__save_and_cli_hw(x)
-
-#define local_irq_disable_hw_notrace()	local_irq_disable_hw()
-#define local_irq_enable_hw_notrace()	local_irq_enable_hw()
-#define local_irq_save_hw_notrace(x)	local_irq_save_hw(x)
-#define local_irq_restore_hw_notrace(x)	local_irq_restore_hw(x)
-
-#endif  /* CONFIG_IPIPE_TRACE_IRQSOFF */
-
-#else /* !CONFIG_IPIPE */
-
-/*
- * Interrupt configuring macros.
- */
-#define local_irq_disable() \
-	do { \
-		int __tmp_dummy; \
-		__asm__ __volatile__( \
-			"cli %0;" \
-			: "=d" (__tmp_dummy) \
-		); \
-	} while (0)
-
-#define local_irq_enable() \
-	__asm__ __volatile__( \
-		"sti %0;" \
-		: \
-		: "d" (bfin_irq_flags) \
-	)
-
-#ifdef CONFIG_DEBUG_HWERR
-# define __save_and_cli(x) \
-	__asm__ __volatile__( \
-		"cli %0;" \
-		"sti %1;" \
-		: "=&d" (x) \
-		: "d" (0x3F) \
-	)
-#else
-# define __save_and_cli(x) \
-	__asm__ __volatile__( \
-		"cli %0;" \
-		: "=&d" (x) \
-	)
-#endif
-
-#define local_save_flags(x) \
-	__asm__ __volatile__( \
-		"cli %0;" \
-		"sti %0;" \
-		: "=d" (x) \
-	)
-
-#ifdef CONFIG_DEBUG_HWERR
-#define irqs_enabled_from_flags(x) (((x) & ~0x3f) != 0)
-#else
-#define irqs_enabled_from_flags(x) ((x) != 0x1f)
-#endif
-
-#define local_irq_restore(x) \
-	do { \
-		if (irqs_enabled_from_flags(x)) \
-			local_irq_enable(); \
-	} while (0)
-
-/* For spinlocks etc */
-#define local_irq_save(x) __save_and_cli(x)
-
-#define irqs_disabled()				\
-({						\
-	unsigned long flags;			\
-	local_save_flags(flags);		\
-	!irqs_enabled_from_flags(flags);	\
-})
-
-#define local_irq_save_hw(x)		local_irq_save(x)
-#define local_irq_restore_hw(x)		local_irq_restore(x)
-#define local_irq_enable_hw()		local_irq_enable()
-#define local_irq_disable_hw()		local_irq_disable()
-#define irqs_disabled_hw()		irqs_disabled()
+#include <linux/irqflags.h>
 
-#endif /* !CONFIG_IPIPE */
+/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h> */
+#include <mach/irq.h>
 
 #if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
 # define NOP_PAD_ANOMALY_05000244 "nop; nop;"
@@ -298,9 +38,6 @@
 		: "d" (bfin_irq_flags) \
 	)
 
-static inline int irq_canonicalize(int irq)
-{
-	return irq;
-}
+#include <asm-generic/irq.h>
 
 #endif				/* _BFIN_IRQ_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,21 +1 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
-
-#endif
+#include <asm-generic/kmap_types.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/local.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/local.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/local.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/local.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef __BLACKFIN_LOCAL_H
-#define __BLACKFIN_LOCAL_H
-
 #include <asm-generic/local.h>
-
-#endif				/* __BLACKFIN_LOCAL_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mem_init.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mem_init.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mem_init.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mem_init.h	2009-09-09 18:13:59.000000000 -0400
@@ -59,7 +59,7 @@
 #define SDRAM_tRP       TRP_1
 #define SDRAM_tRP_num   1
 #define SDRAM_tRAS      TRAS_4
-#define SDRAM_tRAS_num  3
+#define SDRAM_tRAS_num  4
 #define SDRAM_tRCD      TRCD_1
 #define SDRAM_tWR       TWR_2
 #endif
@@ -89,6 +89,85 @@
 #endif
 #endif
 
+/*
+ * The BF526-EZ-Board changed SDRAM chips between revisions,
+ * so we use below timings to accommodate both.
+ */
+#if defined(CONFIG_MEM_MT48H32M16LFCJ_75)
+#if (CONFIG_SCLK_HZ > 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_8
+#define SDRAM_tRAS_num  8
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_7
+#define SDRAM_tRAS_num  7
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_6
+#define SDRAM_tRAS_num  6
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_5
+#define SDRAM_tRAS_num  5
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  4
+#define SDRAM_tRCD      TRCD_2
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_4
+#define SDRAM_tRAS_num  4
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
+#define SDRAM_tRP       TRP_2
+#define SDRAM_tRP_num   2
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_3
+#define SDRAM_tRAS_num  3
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#if (CONFIG_SCLK_HZ <= 29850746)
+#define SDRAM_tRP       TRP_1
+#define SDRAM_tRP_num   1
+#define SDRAM_tRAS      TRAS_2
+#define SDRAM_tRAS_num  2
+#define SDRAM_tRCD      TRCD_1
+#define SDRAM_tWR       TWR_2
+#endif
+#endif
+
 #if defined(CONFIG_MEM_MT48LC16M8A2TG_75) || \
     defined(CONFIG_MEM_MT48LC8M32B2B5_7)
   /*SDRAM INFORMATION: */
@@ -109,6 +188,13 @@
 #define SDRAM_CL    CL_3
 #endif
 
+#if defined(CONFIG_MEM_MT48H32M16LFCJ_75)
+  /*SDRAM INFORMATION: */
+#define SDRAM_Tref  64		/* Refresh period in milliseconds   */
+#define SDRAM_NRA   8192	/* Number of row addresses in SDRAM */
+#define SDRAM_CL    CL_2
+#endif
+
 
 #ifdef CONFIG_BFIN_KERNEL_CLOCK_MEMINIT_CALC
 /* Equation from section 17 (p17-46) of BF533 HRM */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,87 +1,84 @@
 /*
- * mem_map.h
- * Common header file for blackfin family of processors.
+ * Common Blackfin memory map
  *
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_H_
-#define _MEM_MAP_H_
+#ifndef __BFIN_MEM_MAP_H__
+#define __BFIN_MEM_MAP_H__
 
 #include <mach/mem_map.h>
 
-#ifndef __ASSEMBLY__
+/* Every Blackfin so far has MMRs like this */
+#ifndef COREMMR_BASE
+# define COREMMR_BASE 0xFFE00000
+#endif
+#ifndef SYSMMR_BASE
+# define SYSMMR_BASE  0xFFC00000
+#endif
 
-#ifdef CONFIG_SMP
-static inline ulong get_l1_scratch_start_cpu(int cpu)
-{
-	return (cpu) ? COREB_L1_SCRATCH_START : COREA_L1_SCRATCH_START;
-}
-static inline ulong get_l1_code_start_cpu(int cpu)
-{
-	return (cpu) ? COREB_L1_CODE_START : COREA_L1_CODE_START;
-}
-static inline ulong get_l1_data_a_start_cpu(int cpu)
-{
-	return (cpu) ? COREB_L1_DATA_A_START : COREA_L1_DATA_A_START;
-}
-static inline ulong get_l1_data_b_start_cpu(int cpu)
-{
-	return (cpu) ? COREB_L1_DATA_B_START : COREA_L1_DATA_B_START;
-}
+/* Every Blackfin so far has on-chip Scratch Pad SRAM like this */
+#ifndef L1_SCRATCH_START
+# define L1_SCRATCH_START  0xFFB00000
+# define L1_SCRATCH_LENGTH 0x1000
+#endif
 
-static inline ulong get_l1_scratch_start(void)
-{
-	return get_l1_scratch_start_cpu(blackfin_core_id());
-}
-static inline ulong get_l1_code_start(void)
-{
-	return get_l1_code_start_cpu(blackfin_core_id());
-}
-static inline ulong get_l1_data_a_start(void)
-{
-	return get_l1_data_a_start_cpu(blackfin_core_id());
-}
-static inline ulong get_l1_data_b_start(void)
-{
-	return get_l1_data_b_start_cpu(blackfin_core_id());
-}
+/* Most parts lack on-chip L2 SRAM */
+#ifndef L2_START
+# define L2_START  0
+# define L2_LENGTH 0
+#endif
 
-#else /* !CONFIG_SMP */
+/* Most parts lack on-chip L1 ROM */
+#ifndef L1_ROM_START
+# define L1_ROM_START  0
+# define L1_ROM_LENGTH 0
+#endif
 
-static inline ulong get_l1_scratch_start_cpu(int cpu)
+/* Allow wonky SMP ports to override this */
+#ifndef GET_PDA_SAFE
+# define GET_PDA_SAFE(preg) \
+	preg.l = _cpu_pda; \
+	preg.h = _cpu_pda;
+# define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+
+# ifndef __ASSEMBLY__
+
+static inline unsigned long get_l1_scratch_start_cpu(int cpu)
 {
 	return L1_SCRATCH_START;
 }
-static inline ulong get_l1_code_start_cpu(int cpu)
+static inline unsigned long get_l1_code_start_cpu(int cpu)
 {
 	return L1_CODE_START;
 }
-static inline ulong get_l1_data_a_start_cpu(int cpu)
+static inline unsigned long get_l1_data_a_start_cpu(int cpu)
 {
 	return L1_DATA_A_START;
 }
-static inline ulong get_l1_data_b_start_cpu(int cpu)
+static inline unsigned long get_l1_data_b_start_cpu(int cpu)
 {
 	return L1_DATA_B_START;
 }
-static inline ulong get_l1_scratch_start(void)
+static inline unsigned long get_l1_scratch_start(void)
 {
 	return get_l1_scratch_start_cpu(0);
 }
-static inline ulong get_l1_code_start(void)
+static inline unsigned long get_l1_code_start(void)
 {
 	return  get_l1_code_start_cpu(0);
 }
-static inline ulong get_l1_data_a_start(void)
+static inline unsigned long get_l1_data_a_start(void)
 {
 	return get_l1_data_a_start_cpu(0);
 }
-static inline ulong get_l1_data_b_start(void)
+static inline unsigned long get_l1_data_b_start(void)
 {
 	return get_l1_data_b_start_cpu(0);
 }
 
-#endif /* CONFIG_SMP */
-#endif /* __ASSEMBLY__ */
+# endif /* __ASSEMBLY__ */
+#endif /* !GET_PDA_SAFE */
 
-#endif				/* _MEM_MAP_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mman.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,43 +1 @@
-#ifndef __BFIN_MMAN_H__
-#define __BFIN_MMAN_H__
-
-#define PROT_READ	0x1	/* page can be read */
-#define PROT_WRITE	0x2	/* page can be written */
-#define PROT_EXEC	0x4	/* page can be executed */
-#define PROT_SEM	0x8	/* page may be used for atomic ops */
-#define PROT_NONE	0x0	/* page can not be accessed */
-#define PROT_GROWSDOWN	0x01000000	/* mprotect flag: extend change to start of growsdown vma */
-#define PROT_GROWSUP	0x02000000	/* mprotect flag: extend change to end of growsup vma */
-
-#define MAP_SHARED	0x01	/* Share changes */
-#define MAP_PRIVATE	0x02	/* Changes are private */
-#define MAP_TYPE	0x0f	/* Mask for type of mapping */
-#define MAP_FIXED	0x10	/* Interpret addr exactly */
-#define MAP_ANONYMOUS	0x20	/* don't use a file */
-
-#define MAP_GROWSDOWN	0x0100	/* stack-like segment */
-#define MAP_DENYWRITE	0x0800	/* ETXTBSY */
-#define MAP_EXECUTABLE	0x1000	/* mark it as an executable */
-#define MAP_LOCKED	0x2000	/* pages are locked */
-#define MAP_NORESERVE	0x4000	/* don't check for reservations */
-#define MAP_POPULATE	0x8000	/* populate (prefault) pagetables */
-#define MAP_NONBLOCK	0x10000	/* do not block on IO */
-
-#define MS_ASYNC	1	/* sync memory asynchronously */
-#define MS_INVALIDATE	2	/* invalidate the caches */
-#define MS_SYNC		4	/* synchronous memory sync */
-
-#define MCL_CURRENT	1	/* lock all current mappings */
-#define MCL_FUTURE	2	/* lock all future mappings */
-
-#define MADV_NORMAL	0x0	/* default page-in behavior */
-#define MADV_RANDOM	0x1	/* page-in minimum required */
-#define MADV_SEQUENTIAL	0x2	/* read-ahead aggressively */
-#define MADV_WILLNEED	0x3	/* pre-fault pages */
-#define MADV_DONTNEED	0x4	/* discard these pages */
-
-/* compatibility flags */
-#define MAP_ANON	MAP_ANONYMOUS
-#define MAP_FILE	0
-
-#endif				/* __BFIN_MMAN_H__ */
+#include <asm-generic/mman.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/msgbuf.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/msgbuf.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/msgbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/msgbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,31 +1 @@
-#ifndef _BFIN_MSGBUF_H
-#define _BFIN_MSGBUF_H
-
-/*
- * The msqid64_ds structure for bfin architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-	struct ipc64_perm msg_perm;
-	__kernel_time_t msg_stime;	/* last msgsnd time */
-	unsigned long __unused1;
-	__kernel_time_t msg_rtime;	/* last msgrcv time */
-	unsigned long __unused2;
-	__kernel_time_t msg_ctime;	/* last change time */
-	unsigned long __unused3;
-	unsigned long msg_cbytes;	/* current number of bytes on queue */
-	unsigned long msg_qnum;	/* number of messages in queue */
-	unsigned long msg_qbytes;	/* max number of bytes on queue */
-	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
-	__kernel_pid_t msg_lrpid;	/* last receive pid */
-	unsigned long __unused4;
-	unsigned long __unused5;
-};
-
-#endif				/* _BFIN_MSGBUF_H */
+#include <asm-generic/msgbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mutex-dec.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mutex-dec.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mutex-dec.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mutex-dec.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,112 +0,0 @@
-/*
- * include/asm-generic/mutex-dec.h
- *
- * Generic implementation of the mutex fastpath, based on atomic
- * decrement/increment.
- */
-#ifndef _ASM_GENERIC_MUTEX_DEC_H
-#define _ASM_GENERIC_MUTEX_DEC_H
-
-/**
- *  __mutex_fastpath_lock - try to take the lock by moving the count
- *                          from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if
- * it wasn't 1 originally. This function MUST leave the value lower than
- * 1 even when the "1" assertion wasn't true.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
-{
-	if (unlikely(atomic_dec_return(count) < 0))
-		fail_fn(count);
-	else
-		smp_mb();
-}
-
-/**
- *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
- *                                 from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if
- * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
- * or anything the slow path function returns.
- */
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
-{
-	if (unlikely(atomic_dec_return(count) < 0))
-		return fail_fn(count);
-	else {
-		smp_mb();
-		return 0;
-	}
-}
-
-/**
- *  __mutex_fastpath_unlock - try to promote the count from 0 to 1
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 0
- *
- * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value to
- * 1, or to set it to a value lower than 1.
- *
- * If the implementation sets it to a value of lower than 1, then the
- * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
- * to return 0 otherwise.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
-{
-	smp_mb();
-	if (unlikely(atomic_inc_return(count) <= 0))
-		fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock()		1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- *  @count: pointer of type atomic_t
- *  @fail_fn: fallback function
- *
- * Change the count from 1 to a value lower than 1, and return 0 (failure)
- * if it wasn't 1 originally, or return 1 (success) otherwise. This function
- * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
- * Additionally, if the value was < 0 originally, this function must not leave
- * it to 0 on failure.
- *
- * If the architecture has no effective trylock variant, it should call the
- * <fail_fn> spinlock-based trylock variant unconditionally.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
-	/*
-	 * We have two variants here. The cmpxchg based one is the best one
-	 * because it never induce a false contention state.  It is included
-	 * here because architectures using the inc/dec algorithms over the
-	 * xchg ones are much more likely to support cmpxchg natively.
-	 *
-	 * If not we fall back to the spinlock based variant - that is
-	 * just as efficient (and simpler) as a 'destructive' probing of
-	 * the mutex state would be.
-	 */
-#ifdef __HAVE_ARCH_CMPXCHG
-	if (likely(atomic_cmpxchg(count, 1, 0) == 1)) {
-		smp_mb();
-		return 1;
-	}
-	return 0;
-#else
-	return fail_fn(count);
-#endif
-}
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mutex.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mutex.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/mutex.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/mutex.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,7 @@
 #define _ASM_MUTEX_H
 
 #ifndef CONFIG_SMP
-#include <asm-generic/mutex-dec.h>
+#include <asm-generic/mutex.h>
 #else
 
 static inline void
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/page.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,88 +1,7 @@
 #ifndef _BLACKFIN_PAGE_H
 #define _BLACKFIN_PAGE_H
 
-/* PAGE_SHIFT determines the page size */
-
-#define PAGE_SHIFT	12
-#ifdef __ASSEMBLY__
-#define PAGE_SIZE	(1 << PAGE_SHIFT)
-#else
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
-#endif
-#define PAGE_MASK	(~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
-
-#ifndef __ASSEMBLY__
-
-#define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
-#define free_user_page(page, addr)	free_page(addr)
-
-#define clear_page(page)	memset((page), 0, PAGE_SIZE)
-#define copy_page(to,from)	memcpy((to), (from), PAGE_SIZE)
-
-#define clear_user_page(page, vaddr,pg)	clear_page(page)
-#define copy_user_page(to, from, vaddr,pg)	copy_page(to, from)
-
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct {
-	unsigned long pte;
-} pte_t;
-typedef struct {
-	unsigned long pmd[16];
-} pmd_t;
-typedef struct {
-	unsigned long pgd;
-} pgd_t;
-typedef struct {
-	unsigned long pgprot;
-} pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x)	((x).pte)
-#define pmd_val(x)	((&x)->pmd[0])
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-#endif				/* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-#include <asm/io.h>
-
-#define PAGE_OFFSET		(PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
-#define __pa(vaddr)		virt_to_phys((void *)(vaddr))
-#define __va(paddr)		phys_to_virt((unsigned long)(paddr))
-
-#define MAP_NR(addr)		(((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
-
-#define virt_to_pfn(kaddr)	(__pa(kaddr) >> PAGE_SHIFT)
-#define pfn_to_virt(pfn)	__va((pfn) << PAGE_SHIFT)
-#define virt_to_page(addr)	(mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
-#define page_to_virt(page)	((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-#define VALID_PAGE(page)	((page - mem_map) < max_mapnr)
-
-#define pfn_to_page(pfn)	virt_to_page(pfn_to_virt(pfn))
-#define page_to_pfn(page)	virt_to_pfn(page_to_virt(page))
-#define pfn_valid(pfn)	        ((pfn) < max_mapnr)
-
-#define	virt_addr_valid(kaddr)	(((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
-				((void *)(kaddr) < (void *)memory_end))
-
 #include <asm-generic/page.h>
+#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
 
-#endif				/* __ASSEMBLY__ */
-
-#endif				/* _BLACKFIN_PAGE_H */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/param.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/param.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/param.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/param.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,22 +1 @@
-#ifndef _BLACKFIN_PARAM_H
-#define _BLACKFIN_PARAM_H
-
-#ifdef __KERNEL__
-#define HZ 		CONFIG_HZ
-#define	USER_HZ		100
-#define	CLOCKS_PER_SEC	(USER_HZ)
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE	4096
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif				/* _BLACKFIN_PARAM_H */
+#include <asm-generic/param.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/pda.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/pda.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/pda.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/pda.h	2009-09-09 18:13:59.000000000 -0400
@@ -64,8 +64,6 @@
 
 extern struct blackfin_pda cpu_pda[];
 
-void reserve_pda(void);
-
 #endif	/* __ASSEMBLY__ */
 
 #endif /* _ASM_BLACKFIN_PDA_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/percpu.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/percpu.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/percpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/percpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef __ARCH_BLACKFIN_PERCPU__
-#define __ARCH_BLACKFIN_PERCPU__
-
 #include <asm-generic/percpu.h>
-
-#endif	/* __ARCH_BLACKFIN_PERCPU__ */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1 @@
-#ifndef _BLACKFIN_PGALLOC_H
-#define _BLACKFIN_PGALLOC_H
-
-#include <asm/setup.h>
-
-#define check_pgt_cache()	do { } while (0)
-
-#endif				/* _BLACKFIN_PGALLOC_H */
+#include <asm-generic/pgalloc.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/poll.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/poll.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/poll.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/poll.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,24 +1,9 @@
 #ifndef __BFIN_POLL_H
 #define __BFIN_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 POLLWRNORM	4 /* POLLOUT */
 #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				/* __BFIN_POLL_H */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/posix_types.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/posix_types.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/posix_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/posix_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,61 +1,27 @@
 #ifndef __ARCH_BFIN_POSIX_TYPES_H
 #define __ARCH_BFIN_POSIX_TYPES_H
 
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned int __kernel_ipc_pid_t;
-typedef unsigned int __kernel_uid_t;
-typedef unsigned int __kernel_gid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned long __kernel_size_t;
 typedef long __kernel_ssize_t;
 typedef int __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
-typedef long __kernel_suseconds_t;
-typedef long __kernel_clock_t;
-typedef int __kernel_timer_t;
-typedef int __kernel_clockid_t;
-typedef int __kernel_daddr_t;
-typedef char *__kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int __kernel_uid32_t;
-typedef unsigned int __kernel_gid32_t;
+#define __kernel_size_t __kernel_size_t
 
 typedef unsigned short __kernel_old_uid_t;
 typedef unsigned short __kernel_old_gid_t;
-typedef unsigned short __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
-	int val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef	__FD_SET
-#define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-
-#undef	__FD_CLR
-#define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-
-#undef	__FD_ISSET
-#define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define __kernel_old_uid_t __kernel_old_uid_t
 
-#undef	__FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#endif				/* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/processor.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,9 +7,8 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
+#include <asm/ptrace.h>
 #include <asm/blackfin.h>
-#include <asm/segment.h>
-#include <linux/compiler.h>
 
 static inline unsigned long rdusp(void)
 {
@@ -59,36 +58,8 @@
 	PS_S, 0, 0						\
 }
 
-/*
- * Do necessary setup to start up a newly executed thread.
- *
- * pass the data segment into user programs if it exists,
- * it can't hurt anything as far as I can tell
- */
-#ifndef CONFIG_SMP
-#define start_thread(_regs, _pc, _usp)					\
-do {									\
-	set_fs(USER_DS);						\
-	(_regs)->pc = (_pc);						\
-	if (current->mm)						\
-		(_regs)->p5 = current->mm->start_data;			\
-	task_thread_info(current)->l1_task_info.stack_start		\
-		= (void *)current->mm->context.stack_start;		\
-	task_thread_info(current)->l1_task_info.lowest_sp = (void *)(_usp); \
-	memcpy(L1_SCRATCH_TASK_INFO, &task_thread_info(current)->l1_task_info, \
-		sizeof(*L1_SCRATCH_TASK_INFO));				\
-	wrusp(_usp);							\
-} while(0)
-#else
-#define start_thread(_regs, _pc, _usp)					\
-do {									\
-	set_fs(USER_DS);						\
-	(_regs)->pc = (_pc);						\
-	if (current->mm)						\
-		(_regs)->p5 = current->mm->start_data;			\
-	wrusp(_usp);							\
-} while (0)
-#endif
+extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
+					       unsigned long new_sp);
 
 /* Forward declaration, a strange C thing */
 struct task_struct;
@@ -131,26 +102,19 @@
 /* Get the Silicon Revision of the chip */
 static inline uint32_t __pure bfin_revid(void)
 {
-	/* stored in the upper 4 bits */
-	uint32_t revid = bfin_read_CHIPID() >> 28;
+	/* Always use CHIPID, to work around ANOMALY_05000234 */
+	uint32_t revid = (bfin_read_CHIPID() & CHIPID_VERSION) >> 28;
 
-#ifdef CONFIG_BF52x
-	/* ANOMALY_05000357
+#ifdef _BOOTROM_GET_DXE_ADDRESS_TWI
+	/*
+	 * ANOMALY_05000364
 	 * Incorrect Revision Number in DSPID Register
 	 */
-	if (revid == 0)
-		switch (bfin_read16(_BOOTROM_GET_DXE_ADDRESS_TWI)) {
-		case 0x0010:
-			revid = 0;
-			break;
-		case 0x2796:
-			revid = 1;
-			break;
-		default:
-			revid = 0xFFFF;
-			break;
-		}
+	if (ANOMALY_05000364 &&
+	    bfin_read16(_BOOTROM_GET_DXE_ADDRESS_TWI) == 0x2796)
+		revid = 1;
 #endif
+
 	return revid;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/resource.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/resource.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/resource.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/resource.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _BFIN_RESOURCE_H
-#define _BFIN_RESOURCE_H
-
 #include <asm-generic/resource.h>
-
-#endif				/* _BFIN_RESOURCE_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/sections.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/sections.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/sections.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/sections.h	2009-09-09 18:13:59.000000000 -0400
@@ -4,4 +4,15 @@
 /* nothing to see, move along */
 #include <asm-generic/sections.h>
 
+/* only used when MTD_UCLINUX */
+extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
+
+extern unsigned long _ramstart, _ramend, _rambase;
+extern unsigned long memory_start, memory_end, physical_mem_end;
+
+extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
+	_ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
+	_stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
+	_ebss_l2[], _l2_lma_start[];
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/sembuf.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/sembuf.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/sembuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/sembuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1 @@
-#ifndef _BFIN_SEMBUF_H
-#define _BFIN_SEMBUF_H
-
-/*
- * The semid64_ds structure for bfin architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-	struct ipc64_perm sem_perm;	/* permissions .. see ipc.h */
-	__kernel_time_t sem_otime;	/* last semop time */
-	unsigned long __unused1;
-	__kernel_time_t sem_ctime;	/* last change time */
-	unsigned long __unused2;
-	unsigned long sem_nsems;	/* no. of semaphores in array */
-	unsigned long __unused3;
-	unsigned long __unused4;
-};
-
-#endif				/* _BFIN_SEMBUF_H */
+#include <asm-generic/sembuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/serial.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/serial.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/serial.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/serial.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,2 @@
-/*
- * include/asm-blackfin/serial.h
- */
-
+#include <asm-generic/serial.h>
 #define SERIAL_EXTRA_IRQ_FLAGS IRQF_TRIGGER_HIGH
-#define BASE_BAUD (1843200 / 16)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/setup.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/setup.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/setup.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/setup.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,17 +1 @@
-/*
-** asm/setup.h -- Definition of the Linux/bfin setup information
-**
-** 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 Lineo, Inc 2001          Tony Kou
-**
-*/
-
-#ifndef _BFIN_SETUP_H
-#define _BFIN_SETUP_H
-
-#define COMMAND_LINE_SIZE	512
-
-#endif				/* _BFIN_SETUP_H */
+#include <asm-generic/setup.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/shmbuf.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/shmbuf.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/shmbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/shmbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,42 +1 @@
-#ifndef _BFIN_SHMBUF_H
-#define _BFIN_SHMBUF_H
-
-/*
- * The shmid64_ds structure for bfin architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-	struct ipc64_perm shm_perm;	/* operation perms */
-	size_t shm_segsz;	/* size of segment (bytes) */
-	__kernel_time_t shm_atime;	/* last attach time */
-	unsigned long __unused1;
-	__kernel_time_t shm_dtime;	/* last detach time */
-	unsigned long __unused2;
-	__kernel_time_t shm_ctime;	/* last change time */
-	unsigned long __unused3;
-	__kernel_pid_t shm_cpid;	/* pid of creator */
-	__kernel_pid_t shm_lpid;	/* pid of last operator */
-	unsigned long shm_nattch;	/* no. of current attaches */
-	unsigned long __unused4;
-	unsigned long __unused5;
-};
-
-struct shminfo64 {
-	unsigned long shmmax;
-	unsigned long shmmin;
-	unsigned long shmmni;
-	unsigned long shmseg;
-	unsigned long shmall;
-	unsigned long __unused1;
-	unsigned long __unused2;
-	unsigned long __unused3;
-	unsigned long __unused4;
-};
-
-#endif				/* _BFIN_SHMBUF_H */
+#include <asm-generic/shmbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/shmparam.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/shmparam.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/shmparam.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/shmparam.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _BFIN_SHMPARAM_H
-#define _BFIN_SHMPARAM_H
-
-#define	SHMLBA PAGE_SIZE	/* attach addr a multiple of this */
-
-#endif				/* _BFIN_SHMPARAM_H */
+#include <asm-generic/shmparam.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/signal.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,160 +1,7 @@
 #ifndef _BLACKFIN_SIGNAL_H
 #define _BLACKFIN_SIGNAL_H
 
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define _NSIG		64
-#define _NSIG_BPW	32
-#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t;	/* at least 32 bits */
-
-typedef struct {
-	unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG		32
-typedef unsigned long sigset_t;
-
-#endif				/* __KERNEL__ */
-
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-#define SIGBUS		 7
-#define SIGFPE		 8
-#define SIGKILL		 9
-#define SIGUSR1		10
-#define SIGSEGV		11
-#define SIGUSR2		12
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGSTKFLT	16
-#define SIGCHLD		17
-#define SIGCONT		18
-#define SIGSTOP		19
-#define SIGTSTP		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGURG		23
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGIO		29
-#define SIGPOLL		SIGIO
-/*
-#define SIGLOST		29
-*/
-#define SIGPWR		30
-#define SIGSYS		31
-#define	SIGUNUSED	31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN	32
-#define SIGRTMAX	_NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002	/* not supported yet */
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
-
+#define SA_RESTORER 0x04000000
 #include <asm-generic/signal.h>
 
-#ifdef __KERNEL__
-struct old_sigaction {
-	__sighandler_t sa_handler;
-	old_sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer) (void);
-};
-
-struct sigaction {
-	__sighandler_t sa_handler;
-	unsigned long sa_flags;
-	void (*sa_restorer) (void);
-	sigset_t sa_mask;	/* mask last for extensibility */
-};
-
-struct k_sigaction {
-	struct sigaction sa;
-};
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-	union {
-		__sighandler_t _sa_handler;
-		void (*_sa_sigaction) (int, struct siginfo *, void *);
-	} _u;
-	sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer) (void);
-};
-
-#define sa_handler	_u._sa_handler
-#define sa_sigaction	_u._sa_sigaction
-
-#endif				/* __KERNEL__ */
-
-typedef struct sigaltstack {
-	void __user *ss_sp;
-	int ss_flags;
-	size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
-#include <asm/sigcontext.h>
-#undef __HAVE_ARCH_SIG_BITOPS
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif				/* __KERNEL__ */
-
-#endif				/* _BLACKFIN_SIGNAL_H */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/socket.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/socket.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/socket.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/socket.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,59 +1 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET	1
-
-#define SO_DEBUG	1
-#define SO_REUSEADDR	2
-#define SO_TYPE		3
-#define SO_ERROR	4
-#define SO_DONTROUTE	5
-#define SO_BROADCAST	6
-#define SO_SNDBUF	7
-#define SO_RCVBUF	8
-#define SO_SNDBUFFORCE	32
-#define SO_RCVBUFFORCE	33
-#define SO_KEEPALIVE	9
-#define SO_OOBINLINE	10
-#define SO_NO_CHECK	11
-#define SO_PRIORITY	12
-#define SO_LINGER	13
-#define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED	16
-#define SO_PEERCRED	17
-#define SO_RCVLOWAT	18
-#define SO_SNDLOWAT	19
-#define SO_RCVTIMEO	20
-#define SO_SNDTIMEO	21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION		22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
-#define SO_SECURITY_ENCRYPTION_NETWORK		24
-
-#define SO_BINDTODEVICE	25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER	26
-#define SO_DETACH_FILTER	27
-
-#define SO_PEERNAME		28
-#define SO_TIMESTAMP		29
-#define SCM_TIMESTAMP		SO_TIMESTAMP
-
-#define SO_ACCEPTCONN		30
-#define SO_PEERSEC		31
-#define SO_PASSSEC		34
-#define SO_TIMESTAMPNS		35
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
-
-#define SO_MARK			36
-
-#define SO_TIMESTAMPING		37
-#define SCM_TIMESTAMPING	SO_TIMESTAMPING
-
-#endif				/* _ASM_SOCKET_H */
+#include <asm-generic/socket.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/sockios.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/sockios.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/sockios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/sockios.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,13 +1 @@
-#ifndef __ARCH_BFIN_SOCKIOS__
-#define __ARCH_BFIN_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 	0x8901
-#define SIOCSPGRP	0x8902
-#define FIOGETOWN	0x8903
-#define SIOCGPGRP	0x8904
-#define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906	/* Get stamp (timeval) */
-#define SIOCGSTAMPNS	0x8907	/* Get stamp (timespec) */
-
-#endif				/* __ARCH_BFIN_SOCKIOS__ */
+#include <asm-generic/sockios.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/spinlock.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/spinlock.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/spinlock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/spinlock.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,10 @@
 #ifndef __BFIN_SPINLOCK_H
 #define __BFIN_SPINLOCK_H
 
+#ifndef CONFIG_SMP
+# include <asm-generic/spinlock.h>
+#else
+
 #include <asm/atomic.h>
 
 asmlinkage int __raw_spin_is_locked_asm(volatile int *ptr);
@@ -86,4 +90,6 @@
 #define _raw_read_relax(lock)	cpu_relax()
 #define _raw_write_relax(lock)	cpu_relax()
 
+#endif
+
 #endif /*  !__BFIN_SPINLOCK_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/statfs.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/statfs.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/statfs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/statfs.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _BFIN_STATFS_H
-#define _BFIN_STATFS_H
-
 #include <asm-generic/statfs.h>
-
-#endif				/* _BFIN_STATFS_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/swab.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/swab.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/swab.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/swab.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,11 +2,7 @@
 #define _BLACKFIN_SWAB_H
 
 #include <linux/types.h>
-#include <linux/compiler.h>
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#  define __SWAB_64_THRU_32__
-#endif
+#include <asm-generic/swab.h>
 
 #ifdef __GNUC__
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/system.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/system.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,10 +35,10 @@
 #define _BLACKFIN_SYSTEM_H
 
 #include <linux/linkage.h>
-#include <linux/compiler.h>
+#include <linux/irqflags.h>
 #include <mach/anomaly.h>
+#include <asm/cache.h>
 #include <asm/pda.h>
-#include <asm/processor.h>
 #include <asm/irq.h>
 
 /*
@@ -135,11 +135,13 @@
 };
 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
 
+#include <mach/blackfin.h>
+
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
 				   int size)
 {
 	unsigned long tmp = 0;
-	unsigned long flags = 0;
+	unsigned long flags;
 
 	local_irq_save_hw(flags);
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/termbits.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/termbits.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/termbits.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/termbits.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,198 +1 @@
-#ifndef __ARCH_BFIN_TERMBITS_H__
-#define __ARCH_BFIN_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
-
-#define NCCS 19
-struct termios {
-	tcflag_t c_iflag;	/* input mode flags */
-	tcflag_t c_oflag;	/* output mode flags */
-	tcflag_t c_cflag;	/* control mode flags */
-	tcflag_t c_lflag;	/* local mode flags */
-	cc_t c_line;		/* line discipline */
-	cc_t c_cc[NCCS];	/* control characters */
-};
-
-struct termios2 {
-	tcflag_t c_iflag;               /* input mode flags */
-	tcflag_t c_oflag;               /* output mode flags */
-	tcflag_t c_cflag;               /* control mode flags */
-	tcflag_t c_lflag;               /* local mode flags */
-	cc_t c_line;                    /* line discipline */
-	cc_t c_cc[NCCS];                /* control characters */
-	speed_t c_ispeed;               /* input speed */
-	speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-	tcflag_t c_iflag;               /* input mode flags */
-	tcflag_t c_oflag;               /* output mode flags */
-	tcflag_t c_cflag;               /* control mode flags */
-	tcflag_t c_lflag;               /* local mode flags */
-	cc_t c_line;                    /* line discipline */
-	cc_t c_cc[NCCS];                /* control characters */
-	speed_t c_ispeed;               /* input speed */
-	speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-#define IGNBRK	0000001
-#define BRKINT	0000002
-#define IGNPAR	0000004
-#define PARMRK	0000010
-#define INPCK	0000020
-#define ISTRIP	0000040
-#define INLCR	0000100
-#define IGNCR	0000200
-#define ICRNL	0000400
-#define IUCLC	0001000
-#define IXON	0002000
-#define IXANY	0004000
-#define IXOFF	0010000
-#define IMAXBEL	0020000
-#define IUTF8	0040000
-
-/* c_oflag bits */
-#define OPOST	0000001
-#define OLCUC	0000002
-#define ONLCR	0000004
-#define OCRNL	0000010
-#define ONOCR	0000020
-#define ONLRET	0000040
-#define OFILL	0000100
-#define OFDEL	0000200
-#define NLDLY	0000400
-#define   NL0	0000000
-#define   NL1	0000400
-#define CRDLY	0003000
-#define   CR0	0000000
-#define   CR1	0001000
-#define   CR2	0002000
-#define   CR3	0003000
-#define TABDLY	0014000
-#define   TAB0	0000000
-#define   TAB1	0004000
-#define   TAB2	0010000
-#define   TAB3	0014000
-#define   XTABS	0014000
-#define BSDLY	0020000
-#define   BS0	0000000
-#define   BS1	0020000
-#define VTDLY	0040000
-#define   VT0	0000000
-#define   VT1	0040000
-#define FFDLY	0100000
-#define   FF0	0000000
-#define   FF1	0100000
-
-/* c_cflag bit meaning */
-#define CBAUD	0010017
-#define  B0	0000000		/* hang up */
-#define  B50	0000001
-#define  B75	0000002
-#define  B110	0000003
-#define  B134	0000004
-#define  B150	0000005
-#define  B200	0000006
-#define  B300	0000007
-#define  B600	0000010
-#define  B1200	0000011
-#define  B1800	0000012
-#define  B2400	0000013
-#define  B4800	0000014
-#define  B9600	0000015
-#define  B19200	0000016
-#define  B38400	0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE	0000060
-#define   CS5	0000000
-#define   CS6	0000020
-#define   CS7	0000040
-#define   CS8	0000060
-#define CSTOPB	0000100
-#define CREAD	0000200
-#define PARENB	0000400
-#define PARODD	0001000
-#define HUPCL	0002000
-#define CLOCAL	0004000
-#define CBAUDEX 0010000
-#define BOTHER	0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD	  002003600000	/* input baud rate */
-#define CMSPAR	  010000000000	/* mark or space (stick) parity */
-#define CRTSCTS	  020000000000	/* flow control */
-
-#define IBSHIFT	16	/* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG	0000001
-#define ICANON	0000002
-#define XCASE	0000004
-#define ECHO	0000010
-#define ECHOE	0000020
-#define ECHOK	0000040
-#define ECHONL	0000100
-#define NOFLSH	0000200
-#define TOSTOP	0000400
-#define ECHOCTL	0001000
-#define ECHOPRT	0002000
-#define ECHOKE	0004000
-#define FLUSHO	0010000
-#define PENDIN	0040000
-#define IEXTEN	0100000
-
-/* tcflow() and TCXONC use these */
-#define	TCOOFF		0
-#define	TCOON		1
-#define	TCIOFF		2
-#define	TCION		3
-
-/* tcflush() and TCFLSH use these */
-#define	TCIFLUSH	0
-#define	TCOFLUSH	1
-#define	TCIOFLUSH	2
-
-/* tcsetattr uses these */
-#define	TCSANOW		0
-#define	TCSADRAIN	1
-#define	TCSAFLUSH	2
-
-#endif				/* __ARCH_BFIN_TERMBITS_H__ */
+#include <asm-generic/termbits.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/termios.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,94 +1 @@
-#ifndef __BFIN_TERMIOS_H__
-#define __BFIN_TERMIOS_H__
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-	unsigned short ws_row;
-	unsigned short ws_col;
-	unsigned short ws_xpixel;
-	unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-	unsigned short c_iflag;	/* input mode flags */
-	unsigned short c_oflag;	/* output mode flags */
-	unsigned short c_cflag;	/* control mode flags */
-	unsigned short c_lflag;	/* local mode flags */
-	unsigned char c_line;	/* line discipline */
-	unsigned char c_cc[NCC];	/* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE	0x001
-#define TIOCM_DTR	0x002
-#define TIOCM_RTS	0x004
-#define TIOCM_ST	0x008
-#define TIOCM_SR	0x010
-#define TIOCM_CTS	0x020
-#define TIOCM_CAR	0x040
-#define TIOCM_RNG	0x080
-#define TIOCM_DSR	0x100
-#define TIOCM_CD	TIOCM_CAR
-#define TIOCM_RI	TIOCM_RNG
-#define TIOCM_OUT1	0x2000
-#define TIOCM_OUT2	0x4000
-#define TIOCM_LOOP	0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/*	intr=^C		quit=^\		erase=del	kill=^U
-	eof=^D		vtime=\0	vmin=\1		sxtc=\0
-	start=^Q	stop=^S		susp=^Z		eol=\0
-	reprint=^R	discard=^U	werase=^W	lnext=^V
-	eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
-	unsigned short __tmp; \
-	get_user(__tmp,&(termio)->x); \
-	*(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
-	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-	put_user((termios)->c_iflag, &(termio)->c_iflag); \
-	put_user((termios)->c_oflag, &(termio)->c_oflag); \
-	put_user((termios)->c_cflag, &(termio)->c_cflag); \
-	put_user((termios)->c_lflag, &(termio)->c_lflag); \
-	put_user((termios)->c_line,  &(termio)->c_line); \
-	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) \
-	copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) \
-	copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) \
-	copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) \
-	copy_to_user(u, k, sizeof(struct termios))
-
-#endif				/* __KERNEL__ */
-
-#endif				/* __BFIN_TERMIOS_H__ */
+#include <asm-generic/termios.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -77,7 +77,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count  = 1,                    \
+	.preempt_count  = INIT_PREEMPT_COUNT,   \
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/time.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/time.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/time.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/time.h	2009-09-09 18:13:59.000000000 -0400
@@ -37,4 +37,5 @@
 extern unsigned int __bfin_cycles_mod;
 #endif
 
+extern void __init setup_core_timer(void);
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/tlbflush.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/tlbflush.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/tlbflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/tlbflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,56 +1 @@
-#ifndef _BLACKFIN_TLBFLUSH_H
-#define _BLACKFIN_TLBFLUSH_H
-
-/*
- * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
- * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
- */
-
-#include <asm/setup.h>
-
-/*
- * flush all user-space atc entries.
- */
-static inline void __flush_tlb(void)
-{
-	BUG();
-}
-
-static inline void __flush_tlb_one(unsigned long addr)
-{
-	BUG();
-}
-
-#define flush_tlb() __flush_tlb()
-
-/*
- * flush all atc entries (both kernel and user-space entries).
- */
-static inline void flush_tlb_all(void)
-{
-	BUG();
-}
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
-	BUG();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma,
-				  unsigned long addr)
-{
-	BUG();
-}
-
-static inline void flush_tlb_range(struct mm_struct *mm,
-				   unsigned long start, unsigned long end)
-{
-	BUG();
-}
-
-static inline void flush_tlb_kernel_page(unsigned long addr)
-{
-	BUG();
-}
-
-#endif
+#include <asm-generic/tlbflush.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/topology.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/topology.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/topology.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/topology.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _ASM_BLACKFIN_TOPOLOGY_H
-#define _ASM_BLACKFIN_TOPOLOGY_H
-
 #include <asm-generic/topology.h>
-
-#endif				/* _ASM_BLACKFIN_TOPOLOGY_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/traps.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/traps.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/traps.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/traps.h	2009-09-09 18:13:59.000000000 -0400
@@ -111,9 +111,7 @@
 	level "   bits in the Watchpoint Instruction Address Control register (WPIACTL) is set.\n"
 #define EXC_0x2A(level) \
 	"Instruction fetch misaligned address violation\n" \
-	level " - Attempted misaligned instruction cache fetch. On a misaligned instruction fetch\n" \
-	level "   exception, the return address provided in RETX is the destination address which is\n" \
-	level "   misaligned, rather than the address of the offending instruction.\n"
+	level " - Attempted misaligned instruction cache fetch.\n"
 #define EXC_0x2B(level) \
 	"CPLB protection violation\n" \
 	level " - Illegal instruction fetch access (memory protection violation).\n"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/types.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,36 +1 @@
-#ifndef _BFIN_TYPES_H
-#define _BFIN_TYPES_H
-
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-#include <asm-generic/int-ll64.h>
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned short umode_t;
-
-#endif				/* __ASSEMBLY__ */
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-#define BITS_PER_LONG 32
-
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-typedef u64 dma64_addr_t;
-
-#endif				/* __ASSEMBLY__ */
-
-#endif				/* __KERNEL__ */
-
-#endif				/* _BFIN_TYPES_H */
+#include <asm-generic/types.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/uaccess.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/uaccess.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/uaccess.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/uaccess.h	2009-09-09 18:13:59.000000000 -0400
@@ -59,12 +59,8 @@
 #ifndef CONFIG_ACCESS_CHECK
 static inline int _access_ok(unsigned long addr, unsigned long size) { return 1; }
 #else
-#ifdef CONFIG_ACCESS_OK_L1
-extern int _access_ok(unsigned long addr, unsigned long size)__attribute__((l1_text));
-#else
 extern int _access_ok(unsigned long addr, unsigned long size);
 #endif
-#endif
 
 /*
  * The exception table consists of pairs of addresses: the first is the
@@ -83,9 +79,6 @@
 	unsigned long insn, fixup;
 };
 
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long);
-
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
@@ -233,16 +226,29 @@
 }
 
 /*
- * Return the size of a string (including the ending 0)
+ * Get the size of a string in user space.
+ *   src: The string to measure
+ *     n: The maximum valid length
  *
- * Return 0 on exception, a value greater than N if too long
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than n.
  */
-static inline long strnlen_user(const char *src, long n)
+static inline long __must_check strnlen_user(const char *src, long n)
 {
-	return (strlen(src) + 1);
+	if (!access_ok(VERIFY_READ, src, 1))
+		return 0;
+	return strnlen(src, n) + 1;
 }
 
-#define strlen_user(str) strnlen_user(str, 32767)
+static inline long __must_check strlen_user(const char *src)
+{
+	if (!access_ok(VERIFY_READ, src, 1))
+		return 0;
+	return strlen(src) + 1;
+}
 
 /*
  * Zero Userspace
@@ -251,10 +257,34 @@
 static inline unsigned long __must_check
 __clear_user(void *to, unsigned long n)
 {
+	if (!access_ok(VERIFY_WRITE, to, n))
+		return n;
 	memset(to, 0, n);
 	return 0;
 }
 
 #define clear_user(to, n) __clear_user(to, n)
 
+/* How to interpret these return values:
+ *	CORE:      can be accessed by core load or dma memcpy
+ *	CORE_ONLY: can only be accessed by core load
+ *	DMA:       can only be accessed by dma memcpy
+ *	IDMA:      can only be accessed by interprocessor dma memcpy (BF561)
+ *	ITEST:     can be accessed by isram memcpy or dma memcpy
+ */
+enum {
+	BFIN_MEM_ACCESS_CORE = 0,
+	BFIN_MEM_ACCESS_CORE_ONLY,
+	BFIN_MEM_ACCESS_DMA,
+	BFIN_MEM_ACCESS_IDMA,
+	BFIN_MEM_ACCESS_ITEST,
+};
+/**
+ *	bfin_mem_access_type() - what kind of memory access is required
+ *	@addr:   the address to check
+ *	@size:   number of bytes needed
+ *	@return: <0 is error, >=0 is BFIN_MEM_ACCESS_xxx enum (see above)
+ */
+int bfin_mem_access_type(unsigned long addr, unsigned long size);
+
 #endif				/* _BLACKFIN_UACCESS_H */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ucontext.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ucontext.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/ucontext.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/ucontext.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,17 +1 @@
-/** Changes made by Tony Kou   Lineo Inc.    May 2001
- *
- *  Based on: include/m68knommu/ucontext.h
- */
-
-#ifndef _BLACKFIN_UCONTEXT_H
-#define _BLACKFIN_UCONTEXT_H
-
-struct ucontext {
-	unsigned long uc_flags;	/* the others are necessary */
-	struct ucontext *uc_link;
-	stack_t uc_stack;
-	struct sigcontext uc_mcontext;
-	sigset_t uc_sigmask;	/* mask last for extensibility */
-};
-
-#endif				/* _BLACKFIN_UCONTEXT_H */
+#include <asm-generic/ucontext.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/unaligned.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/unaligned.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/unaligned.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/unaligned.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,11 +1 @@
-#ifndef _ASM_BLACKFIN_UNALIGNED_H
-#define _ASM_BLACKFIN_UNALIGNED_H
-
-#include <linux/unaligned/le_struct.h>
-#include <linux/unaligned/be_byteshift.h>
-#include <linux/unaligned/generic.h>
-
-#define get_unaligned	__get_unaligned_le
-#define put_unaligned	__put_unaligned_le
-
-#endif /* _ASM_BLACKFIN_UNALIGNED_H */
+#include <asm-generic/unaligned.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -380,8 +380,10 @@
 #define __NR_inotify_init1	365
 #define __NR_preadv		366
 #define __NR_pwritev		367
+#define __NR_rt_tgsigqueueinfo	368
+#define __NR_perf_counter_open	369
 
-#define __NR_syscall		368
+#define __NR_syscall		370
 #define NR_syscalls		__NR_syscall
 
 /* Old optional stuff no one actually uses */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/include/asm/user.h linux-libre-2.6.31-gnu/arch/blackfin/include/asm/user.h
--- linux-libre-2.6.30-gnu/arch/blackfin/include/asm/user.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/include/asm/user.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,89 +1 @@
-#ifndef _BFIN_USER_H
-#define _BFIN_USER_H
-
-/* Changes by Tony Kou   Lineo, Inc.  July, 2001
- *
- * Based include/asm-m68knommu/user.h
- *
- */
-
-/* Core file format: The core file is written in such a way that gdb
-   can understand it and provide useful information to the user (under
-   linux we use the 'trad-core' bfd).  There are quite a number of
-   obstacles to being able to view the contents of the floating point
-   registers, and until these are solved you will not be able to view the
-   contents of them.  Actually, you can read in the core file and look at
-   the contents of the user struct to find out what the floating point
-   registers contain.
-   The actual file contents are as follows:
-   UPAGE: 1 page consisting of a user struct that tells gdb what is present
-   in the file.  Directly after this is a copy of the task_struct, which
-   is currently not used by gdb, but it may come in useful at some point.
-   All of the registers are stored as part of the upage.  The upage should
-   always be only one page.
-   DATA: The data area is stored.  We use current->end_text to
-   current->brk to pick up all of the user variables, plus any memory
-   that may have been malloced.  No attempt is made to determine if a page
-   is demand-zero or if a page is totally unused, we just cover the entire
-   range.  All of the addresses are rounded in such a way that an integral
-   number of pages is written.
-   STACK: We need the stack information in order to get a meaningful
-   backtrace.  We need to write the data from (esp) to
-   current->start_stack, so we round each of these off in order to be able
-   to write an integer number of pages.
-   The minimum core file size is 3 pages, or 12288 bytes.
-*/
-struct user_bfinfp_struct {
-};
-
-/* This is the old layout of "struct pt_regs" as of Linux 1.x, and
-   is still the layout used by user (the new pt_regs doesn't have
-   all registers). */
-struct user_regs_struct {
-	long r0, r1, r2, r3, r4, r5, r6, r7;
-	long p0, p1, p2, p3, p4, p5, usp, fp;
-	long i0, i1, i2, i3;
-	long l0, l1, l2, l3;
-	long b0, b1, b2, b3;
-	long m0, m1, m2, m3;
-	long a0w, a1w;
-	long a0x, a1x;
-	unsigned long rets;
-	unsigned long astat;
-	unsigned long pc;
-	unsigned long orig_p0;
-};
-
-/* When the kernel dumps core, it starts by dumping the user struct -
-   this will be used by gdb to figure out where the data and stack segments
-   are within the file, and what virtual addresses to use. */
-
-struct user {
-/* We start with the registers, to mimic the way that "memory" is returned
-   from the ptrace(3,...) function.  */
-
-	struct user_regs_struct regs;	/* Where the registers are actually stored */
-
-/* The rest of this junk is to help gdb figure out what goes where */
-	unsigned long int u_tsize;	/* Text segment size (pages). */
-	unsigned long int u_dsize;	/* Data segment size (pages). */
-	unsigned long int u_ssize;	/* Stack segment size (pages). */
-	unsigned long start_code;	/* Starting virtual address of text. */
-	unsigned long start_stack;	/* Starting virtual address of stack area.
-					   This is actually the bottom of the stack,
-					   the top of the stack is always found in the
-					   esp register.  */
-	long int signal;	/* Signal that caused the core dump. */
-	int reserved;		/* No longer used */
-	unsigned long u_ar0;
-	/* Used by gdb to help find the values for */
-	/* the registers. */
-	unsigned long magic;	/* To uniquely identify a core file */
-	char u_comm[32];	/* User command that was responsible */
-};
-#define NBPG PAGE_SIZE
-#define UPAGES 1
-#define HOST_TEXT_START_ADDR (u.start_code)
-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
-
-#endif
+#include <asm-generic/user.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -6,59 +6,65 @@
 mainmenu "Blackfin Kernel Configuration"
 
 config MMU
-	bool
-	default n
+	def_bool n
 
 config FPU
-	bool
-	default n
+	def_bool n
 
 config RWSEM_GENERIC_SPINLOCK
-	bool
-	default y
+	def_bool y
 
 config RWSEM_XCHGADD_ALGORITHM
-	bool
-	default n
+	def_bool n
 
 config BLACKFIN
-	bool
-	default y
+	def_bool y
+	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_FUNCTION_TRACER
 	select HAVE_IDE
+	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_BZIP2
+	select HAVE_KERNEL_LZMA
 	select HAVE_OPROFILE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
+
 config ZONE_DMA
-	bool
-	default y
+	def_bool y
 
 config GENERIC_FIND_NEXT_BIT
-	bool
-	default y
+	def_bool y
 
 config GENERIC_HWEIGHT
-	bool
-	default y
+	def_bool y
 
 config GENERIC_HARDIRQS
-	bool
-	default y
+	def_bool y
 
 config GENERIC_IRQ_PROBE
-	bool
-	default y
+	def_bool y
 
 config GENERIC_GPIO
-	bool
-	default y
+	def_bool y
 
 config FORCE_MAX_ZONEORDER
 	int
 	default "14"
 
 config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
+config STACKTRACE_SUPPORT
+	def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
 
 source "init/Kconfig"
 
@@ -223,6 +229,7 @@
 
 config SMP
 	depends on BF561
+	select GENERIC_TIME
 	bool "Symmetric multi-processing support"
 	---help---
 	  This enables support for systems with more than one CPU,
@@ -241,12 +248,6 @@
 	depends on SMP
 	default y
 
-config TICK_SOURCE_SYSTMR0
-	bool
-	select BFIN_GPTIMERS
-	depends on SMP
-	default y
-
 config BF_REV_MIN
 	int
 	default 0 if (BF51x || BF52x || (BF54x && !BF54xM))
@@ -263,8 +264,8 @@
 
 choice
 	prompt "Silicon Rev"
-	default BF_REV_0_1 if (BF51x || BF52x || (BF54x && !BF54xM))
-	default BF_REV_0_2 if (BF534 || BF536 || BF537)
+	default BF_REV_0_0 if (BF51x || BF52x)
+	default BF_REV_0_2 if (BF534 || BF536 || BF537 || (BF54x && !BF54xM))
 	default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF54xM || BF561)
 
 config BF_REV_0_0
@@ -273,7 +274,7 @@
 
 config BF_REV_0_1
 	bool "0.1"
-	depends on (BF52x || (BF54x && !BF54xM))
+	depends on (BF51x || BF52x || (BF54x && !BF54xM))
 
 config BF_REV_0_2
 	bool "0.2"
@@ -357,7 +358,7 @@
 
 config MEM_MT48LC32M16A2TG_75
 	bool
-	depends on (BFIN527_EZKIT || BFIN532_IP0X || BLACKSTAMP || BFIN526_EZBRD)
+	depends on (BFIN527_EZKIT || BFIN532_IP0X || BLACKSTAMP)
 	default y
 
 config MEM_MT48LC32M8A2_75
@@ -365,6 +366,11 @@
 	depends on (BFIN518F_EZBRD)
 	default y
 
+config MEM_MT48H32M16LFCJ_75
+	bool
+	depends on (BFIN526_EZBRD)
+	default y
+
 source "arch/blackfin/mach-bf518/Kconfig"
 source "arch/blackfin/mach-bf527/Kconfig"
 source "arch/blackfin/mach-bf533/Kconfig"
@@ -413,12 +419,12 @@
 
 config CLKIN_HZ
 	int "Frequency of the crystal on the board in Hz"
+	default "10000000" if BFIN532_IP0X
 	default "11059200" if BFIN533_STAMP
+	default "24576000" if PNAV10
+	default "25000000" # most people use this
 	default "27000000" if BFIN533_EZKIT
-	default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN538_EZKIT || BFIN518F-EZBRD)
 	default "30000000" if BFIN561_EZKIT
-	default "24576000" if PNAV10
-	default "10000000" if BFIN532_IP0X
 	help
 	  The frequency of CLKIN crystal oscillator on the board in Hz.
 	  Warning: This value should match the crystal on the board. Otherwise,
@@ -607,7 +613,6 @@
 
 config GENERIC_TIME
 	bool "Generic time"
-	depends on !SMP
 	default y
 
 config GENERIC_CLOCKEVENTS
@@ -615,12 +620,25 @@
 	depends on GENERIC_TIME
 	default y
 
+choice
+	prompt "Kernel Tick Source"
+	depends on GENERIC_CLOCKEVENTS
+	default TICKSOURCE_CORETMR
+
+config TICKSOURCE_GPTMR0
+	bool "Gptimer0 (SCLK domain)"
+	select BFIN_GPTIMERS
+
+config TICKSOURCE_CORETMR
+	bool "Core timer (CCLK domain)"
+
+endchoice
+
 config CYCLES_CLOCKSOURCE
-	bool "Use 'CYCLES' as a clocksource (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "Use 'CYCLES' as a clocksource"
 	depends on GENERIC_CLOCKEVENTS
 	depends on !BFIN_SCRATCH_REG_CYCLES
-	default n
+	depends on !SMP
 	help
 	  If you say Y here, you will enable support for using the 'cycles'
 	  registers as a clock source.  Doing so means you will be unable to
@@ -628,6 +646,12 @@
 	  still be able to read it (such as for performance monitoring), but
 	  writing the registers will most likely crash the kernel.
 
+config GPTMR0_CLOCKSOURCE
+	bool "Use GPTimer0 as a clocksource (higher rating)"
+	select BFIN_GPTIMERS
+	depends on GENERIC_CLOCKEVENTS
+	depends on !TICKSOURCE_GPTMR0
+
 source kernel/time/Kconfig
 
 comment "Misc"
@@ -808,7 +832,7 @@
 config EXCEPTION_L1_SCRATCH
 	bool "Locate exception stack in L1 Scratch Memory"
 	default n
-	depends on !APP_STACK_L1 && !SYSCALL_TAB_L1
+	depends on !APP_STACK_L1
 	help
 	  Whenever an exception occurs, use the L1 Scratch memory for
 	  stack storage.  You cannot place the stacks of FLAT binaries
@@ -872,7 +896,7 @@
 	  are unsure, say N.
 
 	  To compile this driver as a module, choose M here: the module
-	  will be called gptimers.ko.
+	  will be called gptimers.
 
 choice
 	prompt "Uncached DMA region"
@@ -889,23 +913,41 @@
 
 
 comment "Cache Support"
+
 config BFIN_ICACHE
 	bool "Enable ICACHE"
+	default y
+config BFIN_ICACHE_LOCK
+	bool "Enable Instruction Cache Locking"
+	depends on BFIN_ICACHE
+	default n
+config BFIN_EXTMEM_ICACHEABLE
+	bool "Enable ICACHE for external memory"
+	depends on BFIN_ICACHE
+	default y
+config BFIN_L2_ICACHEABLE
+	bool "Enable ICACHE for L2 SRAM"
+	depends on BFIN_ICACHE
+	depends on BF54x || BF561
+	default n
+
 config BFIN_DCACHE
 	bool "Enable DCACHE"
+	default y
 config BFIN_DCACHE_BANKA
 	bool "Enable only 16k BankA DCACHE - BankB is SRAM"
 	depends on BFIN_DCACHE && !BF531
 	default n
-config BFIN_ICACHE_LOCK
-	bool "Enable Instruction Cache Locking"
-
-choice
-	prompt "Policy"
+config BFIN_EXTMEM_DCACHEABLE
+	bool "Enable DCACHE for external memory"
 	depends on BFIN_DCACHE
-	default BFIN_WB if !SMP
-	default BFIN_WT if SMP
-config BFIN_WB
+	default y
+choice
+	prompt "External memory DCACHE policy"
+	depends on BFIN_EXTMEM_DCACHEABLE
+	default BFIN_EXTMEM_WRITEBACK if !SMP
+	default BFIN_EXTMEM_WRITETHROUGH if SMP
+config BFIN_EXTMEM_WRITEBACK
 	bool "Write back"
 	depends on !SMP
 	help
@@ -923,7 +965,7 @@
 	  If you are unsure of the options and you want to be safe,
 	  then go with Write Through.
 
-config BFIN_WT
+config BFIN_EXTMEM_WRITETHROUGH
 	bool "Write through"
 	help
 	  Write Back Policy:
@@ -942,13 +984,26 @@
 
 endchoice
 
-config BFIN_L2_CACHEABLE
-	bool "Cache L2 SRAM"
-	depends on (BFIN_DCACHE || BFIN_ICACHE) && (BF54x || (BF561 && !SMP))
+config BFIN_L2_DCACHEABLE
+	bool "Enable DCACHE for L2 SRAM"
+	depends on BFIN_DCACHE
+	depends on BF54x || BF561
 	default n
-	help
-	  Select to make L2 SRAM cacheable in L1 data and instruction cache.
+choice
+	prompt "L2 SRAM DCACHE policy"
+	depends on BFIN_L2_DCACHEABLE
+	default BFIN_L2_WRITEBACK
+config BFIN_L2_WRITEBACK
+	bool "Write back"
+	depends on !SMP
+
+config BFIN_L2_WRITETHROUGH
+	bool "Write through"
+	depends on !SMP
+endchoice
 
+
+comment "Memory Protection Unit"
 config MPU
 	bool "Enable the memory protection unit (EXPERIMENTAL)"
 	default n
@@ -1011,21 +1066,34 @@
 
 menu "EBIU_AMBCTL Control"
 config BANK_0
-	hex "Bank 0"
+	hex "Bank 0 (AMBCTL0.L)"
 	default 0x7BB0
+	help
+	  These are the low 16 bits of the EBIU_AMBCTL0 MMR which are
+	  used to control the Asynchronous Memory Bank 0 settings.
 
 config BANK_1
-	hex "Bank 1"
+	hex "Bank 1 (AMBCTL0.H)"
 	default 0x7BB0
 	default 0x5558 if BF54x
+	help
+	  These are the high 16 bits of the EBIU_AMBCTL0 MMR which are
+	  used to control the Asynchronous Memory Bank 1 settings.
 
 config BANK_2
-	hex "Bank 2"
+	hex "Bank 2 (AMBCTL1.L)"
 	default 0x7BB0
+	help
+	  These are the low 16 bits of the EBIU_AMBCTL1 MMR which are
+	  used to control the Asynchronous Memory Bank 2 settings.
 
 config BANK_3
-	hex "Bank 3"
+	hex "Bank 3 (AMBCTL1.H)"
 	default 0x99B3
+	help
+	  These are the high 16 bits of the EBIU_AMBCTL1 MMR which are
+	  used to control the Asynchronous Memory Bank 3 settings.
+
 endmenu
 
 config EBIU_MBSCTLVAL
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/Kconfig.debug linux-libre-2.6.31-gnu/arch/blackfin/Kconfig.debug
--- linux-libre-2.6.30-gnu/arch/blackfin/Kconfig.debug	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/Kconfig.debug	2009-09-09 18:13:59.000000000 -0400
@@ -54,6 +54,19 @@
 	  hardware error interrupts and need to know where they are coming
 	  from.
 
+config EXACT_HWERR
+	bool "Try to make Hardware errors exact"
+	depends on DEBUG_HWERR
+	help
+	  By default, the Blackfin hardware errors are not exact - the error
+          be reported multiple cycles after the error happens. This delay
+	  can cause the wrong application, or even the kernel to receive a
+	  signal to be killed. If you are getting HW errors in your system,
+	  try turning this on to ensure they are at least comming from the
+	  proper thread.
+
+	  On production systems, it is safe (and a small optimization) to say N.
+
 config DEBUG_DOUBLEFAULT
 	bool "Debug Double Faults"
 	default n
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/bfin_dma_5xx.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/bfin_dma_5xx.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/bfin_dma_5xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/bfin_dma_5xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,11 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 
+/*
+ * To make sure we work around 05000119 - we always check DMA_DONE bit,
+ * never the DMA_RUN bit
+ */
+
 struct dma_channel dma_ch[MAX_DMA_CHANNELS];
 EXPORT_SYMBOL(dma_ch);
 
@@ -232,6 +237,86 @@
 void __init blackfin_dma_early_init(void)
 {
 	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_S1_CONFIG(0);
+}
+
+void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
+{
+	unsigned long dst = (unsigned long)pdst;
+	unsigned long src = (unsigned long)psrc;
+	struct dma_register *dst_ch, *src_ch;
+
+	/* We assume that everything is 4 byte aligned, so include
+	 * a basic sanity check
+	 */
+	BUG_ON(dst % 4);
+	BUG_ON(src % 4);
+	BUG_ON(size % 4);
+
+	src_ch = 0;
+	/* Find an avalible memDMA channel */
+	while (1) {
+		if (src_ch == (struct dma_register *)MDMA_S0_NEXT_DESC_PTR) {
+			dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR;
+			src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR;
+		} else {
+			dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
+			src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
+		}
+
+		if (!bfin_read16(&src_ch->cfg))
+			break;
+		else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) {
+			bfin_write16(&src_ch->cfg, 0);
+			break;
+		}
+	}
+
+	/* Force a sync in case a previous config reset on this channel
+	 * occurred.  This is needed so subsequent writes to DMA registers
+	 * are not spuriously lost/corrupted.
+	 */
+	__builtin_bfin_ssync();
+
+	/* Destination */
+	bfin_write32(&dst_ch->start_addr, dst);
+	bfin_write16(&dst_ch->x_count, size >> 2);
+	bfin_write16(&dst_ch->x_modify, 1 << 2);
+	bfin_write16(&dst_ch->irq_status, DMA_DONE | DMA_ERR);
+
+	/* Source */
+	bfin_write32(&src_ch->start_addr, src);
+	bfin_write16(&src_ch->x_count, size >> 2);
+	bfin_write16(&src_ch->x_modify, 1 << 2);
+	bfin_write16(&src_ch->irq_status, DMA_DONE | DMA_ERR);
+
+	/* Enable */
+	bfin_write16(&src_ch->cfg, DMAEN | WDSIZE_32);
+	bfin_write16(&dst_ch->cfg, WNR | DI_EN | DMAEN | WDSIZE_32);
+
+	/* Since we are atomic now, don't use the workaround ssync */
+	__builtin_bfin_ssync();
+}
+
+void __init early_dma_memcpy_done(void)
+{
+	while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) ||
+	       (bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE)))
+		continue;
+
+	bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+	bfin_write_MDMA_D1_IRQ_STATUS(DMA_DONE | DMA_ERR);
+	/*
+	 * Now that DMA is done, we would normally flush cache, but
+	 * i/d cache isn't running this early, so we don't bother,
+	 * and just clear out the DMA channel for next time
+	 */
+	bfin_write_MDMA_S0_CONFIG(0);
+	bfin_write_MDMA_S1_CONFIG(0);
+	bfin_write_MDMA_D0_CONFIG(0);
+	bfin_write_MDMA_D1_CONFIG(0);
+
+	__builtin_bfin_ssync();
 }
 
 /**
@@ -367,10 +452,10 @@
 	unsigned long src = (unsigned long)psrc;
 	size_t bulk, rest;
 
-	if (bfin_addr_dcachable(src))
+	if (bfin_addr_dcacheable(src))
 		blackfin_dcache_flush_range(src, src + size);
 
-	if (bfin_addr_dcachable(dst))
+	if (bfin_addr_dcacheable(dst))
 		blackfin_dcache_invalidate_range(dst, dst + size);
 
 	bulk = size & ~0xffff;
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/bfin_gpio.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/bfin_gpio.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/bfin_gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/bfin_gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -313,15 +313,6 @@
 # define portmux_setup(...)  do { } while (0)
 #endif
 
-static int __init bfin_gpio_init(void)
-{
-	printk(KERN_INFO "Blackfin GPIO Controller\n");
-
-	return 0;
-}
-arch_initcall(bfin_gpio_init);
-
-
 #ifndef CONFIG_BF54x
 /***********************************************************
 *
@@ -695,14 +686,12 @@
 		*port_fer[bank] = gpio_bank_saved[bank].fer;
 #endif
 		gpio_array[bank]->inen  = gpio_bank_saved[bank].inen;
+		gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+						& gpio_bank_saved[bank].dir;
 		gpio_array[bank]->dir   = gpio_bank_saved[bank].dir;
 		gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
 		gpio_array[bank]->edge  = gpio_bank_saved[bank].edge;
 		gpio_array[bank]->both  = gpio_bank_saved[bank].both;
-
-		gpio_array[bank]->data_set = gpio_bank_saved[bank].data
-						| gpio_bank_saved[bank].dir;
-
 		gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
 	}
 	AWA_DUMMY_READ(maska);
@@ -1021,15 +1010,6 @@
 
 	local_irq_save_hw(flags);
 
-	if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-		if (system_state == SYSTEM_BOOTING)
-			dump_stack();
-		printk(KERN_ERR
-		       "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n",
-		       gpio);
-		local_irq_restore_hw(flags);
-		return -EBUSY;
-	}
 	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
 		if (system_state == SYSTEM_BOOTING)
 			dump_stack();
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/bfin_ksyms.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/bfin_ksyms.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/bfin_ksyms.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/bfin_ksyms.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,13 +10,13 @@
 #include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
+#include <asm/io.h>
 
 /* Allow people to have their own Blackfin exception handler in a module */
 EXPORT_SYMBOL(bfin_return_from_exception);
 
 /* All the Blackfin cache functions: mach-common/cache.S */
 EXPORT_SYMBOL(blackfin_dcache_invalidate_range);
-EXPORT_SYMBOL(blackfin_icache_dcache_flush_range);
 EXPORT_SYMBOL(blackfin_icache_flush_range);
 EXPORT_SYMBOL(blackfin_dcache_flush_range);
 EXPORT_SYMBOL(blackfin_dflush_page);
@@ -104,3 +104,8 @@
 EXPORT_SYMBOL(__raw_smp_check_barrier_asm);
 #endif
 #endif
+
+#ifdef CONFIG_FUNCTION_TRACER
+extern void _mcount(void);
+EXPORT_SYMBOL(_mcount);
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-mpu/cacheinit.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-mpu/cacheinit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-mpu/cacheinit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-mpu/cacheinit.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,14 @@
 	}
 
 	ctrl = bfin_read_DMEM_CONTROL();
-	ctrl |= DMEM_CNTR;
+
+	/*
+	 *  Anomaly notes:
+	 *  05000287 - We implement workaround #2 - Change the DMEM_CONTROL
+	 *  register, so that the port preferences for DAG0 and DAG1 are set
+	 *  to port B
+	 */
+	ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0);
 	bfin_write_DMEM_CONTROL(ctrl);
 	SSYNC();
 }
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-mpu/cplbinit.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-mpu/cplbinit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-mpu/cplbinit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-mpu/cplbinit.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,13 +46,13 @@
 
 	printk(KERN_INFO "MPU: setting up cplb tables with memory protection\n");
 
-#ifdef CONFIG_BFIN_ICACHE
+#ifdef CONFIG_BFIN_EXTMEM_ICACHEABLE
 	i_cache = CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
 #endif
 
-#ifdef CONFIG_BFIN_DCACHE
+#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE
 	d_cache = CPLB_L1_CHBL;
-#ifdef CONFIG_BFIN_WT
+#ifdef CONFIG_BFIN_EXTMEM_WRITETROUGH
 	d_cache |= CPLB_L1_AOW | CPLB_WT;
 #endif
 #endif
@@ -64,7 +64,7 @@
 	dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
 
 	icplb_tbl[cpu][i_i].addr = 0;
-	icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_1KB;
+	icplb_tbl[cpu][i_i++].data = CPLB_VALID | i_cache | CPLB_USER_RD | PAGE_SIZE_1KB;
 
 	/* Cover kernel memory with 4M pages.  */
 	addr = 0;
@@ -91,9 +91,9 @@
 	/* Cover L2 memory */
 #if L2_LENGTH > 0
 	dcplb_tbl[cpu][i_d].addr = L2_START;
-	dcplb_tbl[cpu][i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
+	dcplb_tbl[cpu][i_d++].data = L2_DMEMORY;
 	icplb_tbl[cpu][i_i].addr = L2_START;
-	icplb_tbl[cpu][i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
+	icplb_tbl[cpu][i_i++].data = L2_IMEMORY;
 #endif
 
 	first_mask_dcplb = i_d;
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-mpu/cplbmgr.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-mpu/cplbmgr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-mpu/cplbmgr.c	2009-09-09 18:13:59.000000000 -0400
@@ -150,15 +150,19 @@
 	nr_dcplb_miss[cpu]++;
 
 	d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
-#ifdef CONFIG_BFIN_DCACHE
-	if (bfin_addr_dcachable(addr)) {
+#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE
+	if (bfin_addr_dcacheable(addr)) {
 		d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
-#ifdef CONFIG_BFIN_WT
+# ifdef CONFIG_BFIN_EXTMEM_WRITETHROUGH
 		d_data |= CPLB_L1_AOW | CPLB_WT;
-#endif
+# endif
 	}
 #endif
-	if (addr >= physical_mem_end) {
+
+	if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) {
+		addr = L2_START;
+		d_data = L2_DMEMORY;
+	} else if (addr >= physical_mem_end) {
 		if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE
 		    && (status & FAULT_USERSUPV)) {
 			addr &= ~0x3fffff;
@@ -235,7 +239,7 @@
 
 	i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB;
 
-#ifdef CONFIG_BFIN_ICACHE
+#ifdef CONFIG_BFIN_EXTMEM_ICACHEABLE
 	/*
 	 * Normal RAM, and possibly the reserved memory area, are
 	 * cacheable.
@@ -245,7 +249,10 @@
 		i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
 #endif
 
-	if (addr >= physical_mem_end) {
+	if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) {
+		addr = L2_START;
+		i_data = L2_IMEMORY;
+	} else if (addr >= physical_mem_end) {
 		if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
 		    && (status & FAULT_USERSUPV)) {
 			addr &= ~(1 * 1024 * 1024 - 1);
@@ -365,13 +372,18 @@
 	local_irq_save_hw(flags);
 	current_rwx_mask[cpu] = masks;
 
-	d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
-#ifdef CONFIG_BFIN_DCACHE
-	d_data |= CPLB_L1_CHBL;
-#ifdef CONFIG_BFIN_WT
-	d_data |= CPLB_L1_AOW | CPLB_WT;
-#endif
+	if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) {
+		addr = L2_START;
+		d_data = L2_DMEMORY;
+	} else {
+		d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
+#ifdef CONFIG_BFIN_EXTMEM_DCACHEABLE
+		d_data |= CPLB_L1_CHBL;
+# ifdef CONFIG_BFIN_EXTMEM_WRITETHROUGH
+		d_data |= CPLB_L1_AOW | CPLB_WT;
+# endif
 #endif
+	}
 
 	disable_dcplb();
 	for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-nompu/cacheinit.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-nompu/cacheinit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-nompu/cacheinit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-nompu/cacheinit.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,14 @@
 	}
 
 	ctrl = bfin_read_DMEM_CONTROL();
-	ctrl |= DMEM_CNTR;
+
+	/*
+	 *  Anomaly notes:
+	 *  05000287 - We implement workaround #2 - Change the DMEM_CONTROL
+	 *  register, so that the port preferences for DAG0 and DAG1 are set
+	 *  to port B
+	 */
+	ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0);
 	bfin_write_DMEM_CONTROL(ctrl);
 	SSYNC();
 }
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-nompu/cplbinit.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-nompu/cplbinit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-nompu/cplbinit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-nompu/cplbinit.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,13 +72,24 @@
 	}
 
 	/* Cover L1 memory.  One 4M area for code and data each is enough.  */
-	if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
-		d_tbl[i_d].addr = L1_DATA_A_START;
-		d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+	if (cpu == 0) {
+		if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
+			d_tbl[i_d].addr = L1_DATA_A_START;
+			d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+		}
+		i_tbl[i_i].addr = L1_CODE_START;
+		i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
 	}
-	i_tbl[i_i].addr = L1_CODE_START;
-	i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
-
+#ifdef CONFIG_SMP
+	else {
+		if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
+			d_tbl[i_d].addr = COREB_L1_DATA_A_START;
+			d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+		}
+		i_tbl[i_i].addr = COREB_L1_CODE_START;
+		i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
+	}
+#endif
 	first_switched_dcplb = i_d;
 	first_switched_icplb = i_i;
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-nompu/cplbmgr.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/cplb-nompu/cplbmgr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/cplb-nompu/cplbmgr.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
 #include <asm/cplbinit.h>
 #include <asm/cplb.h>
 #include <asm/mmu_context.h>
+#include <asm/traps.h>
 
 /*
  * WARNING
@@ -100,28 +101,6 @@
 #endif
 }
 
-/*
- * Given the contents of the status register, return the index of the
- * CPLB that caused the fault.
- */
-static inline int faulting_cplb_index(int status)
-{
-	int signbits = __builtin_bfin_norm_fr1x32(status & 0xFFFF);
-	return 30 - signbits;
-}
-
-/*
- * Given the contents of the status register and the DCPLB_DATA contents,
- * return true if a write access should be permitted.
- */
-static inline int write_permitted(int status, unsigned long data)
-{
-	if (status & FAULT_USERSUPV)
-		return !!(data & CPLB_SUPV_WR);
-	else
-		return !!(data & CPLB_USER_WR);
-}
-
 /* Counters to implement round-robin replacement.  */
 static int icplb_rr_index[NR_CPUS] PDT_ATTR;
 static int dcplb_rr_index[NR_CPUS] PDT_ATTR;
@@ -245,43 +224,16 @@
 	return CPLB_RELOADED;
 }
 
-MGR_ATTR static noinline int dcplb_protection_fault(int cpu)
-{
-	int status = bfin_read_DCPLB_STATUS();
-
-	nr_dcplb_prot[cpu]++;
-
-	if (likely(status & FAULT_RW)) {
-		int idx = faulting_cplb_index(status);
-		unsigned long regaddr = DCPLB_DATA0 + idx * 4;
-		unsigned long data = bfin_read32(regaddr);
-
-		/* Check if fault is to dirty a clean page */
-		if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
-		    write_permitted(status, data)) {
-
-			dcplb_tbl[cpu][idx].data = data;
-			bfin_write32(regaddr, data);
-			return CPLB_RELOADED;
-		}
-	}
-
-	return CPLB_PROT_VIOL;
-}
-
 MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
 {
 	int cause = seqstat & 0x3f;
 	unsigned int cpu = smp_processor_id();
 	switch (cause) {
-	case 0x2C:
+	case VEC_CPLB_I_M:
 		return icplb_miss(cpu);
-	case 0x26:
+	case VEC_CPLB_M:
 		return dcplb_miss(cpu);
 	default:
-		if (unlikely(cause == 0x23))
-			return dcplb_protection_fault(cpu);
-
 		return CPLB_UNKNOWN_ERR;
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/early_printk.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/early_printk.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/early_printk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/early_printk.c	2009-09-09 18:13:59.000000000 -0400
@@ -178,25 +178,15 @@
 
 asmlinkage void __init init_early_exception_vectors(void)
 {
+	u32 evt;
 	SSYNC();
 
 	/* cannot program in software:
 	 * evt0 - emulation (jtag)
 	 * evt1 - reset
 	 */
-	bfin_write_EVT2(early_trap);
-	bfin_write_EVT3(early_trap);
-	bfin_write_EVT5(early_trap);
-	bfin_write_EVT6(early_trap);
-	bfin_write_EVT7(early_trap);
-	bfin_write_EVT8(early_trap);
-	bfin_write_EVT9(early_trap);
-	bfin_write_EVT10(early_trap);
-	bfin_write_EVT11(early_trap);
-	bfin_write_EVT12(early_trap);
-	bfin_write_EVT13(early_trap);
-	bfin_write_EVT14(early_trap);
-	bfin_write_EVT15(early_trap);
+	for (evt = EVT2; evt <= EVT15; evt += 4)
+		bfin_write32(evt, early_trap);
 	CSYNC();
 
 	/* Set all the return from interrupt, exception, NMI to a known place
@@ -212,11 +202,15 @@
 asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
 {
 	/* This can happen before the uart is initialized, so initialize
-	 * the UART now
+	 * the UART now (but only if we are running on the processor we think
+	 * we are compiled for - otherwise we write to MMRs that don't exist,
+	 * and cause other problems. Nothing comes out the UART, but it does
+	 * end up in the __buf_log.
 	 */
-	if (likely(early_console == NULL))
+	if (likely(early_console == NULL) && CPUID == bfin_cpuid())
 		setup_early_printk(DEFAULT_EARLY_PORT);
 
+	printk(KERN_EMERG "Early panic\n");
 	dump_bfin_mem(fp);
 	show_regs(fp);
 	dump_bfin_trace_buffer();
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/ftrace.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/ftrace.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/ftrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/ftrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * ftrace graph code
+ *
+ * Copyright (C) 2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/ftrace.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+{
+	struct ftrace_graph_ent trace;
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY)
+		return;
+
+	trace.func = self_addr;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		return;
+	}
+
+	/* all is well in the world !  hijack RETS ... */
+	*parent = return_hooker;
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/ftrace-entry.S linux-libre-2.6.31-gnu/arch/blackfin/kernel/ftrace-entry.S
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/ftrace-entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/ftrace-entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,140 @@
+/*
+ * mcount and friends -- ftrace stuff
+ *
+ * Copyright (C) 2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ftrace.h>
+
+.text
+
+/* GCC will have called us before setting up the function prologue, so we
+ * can clobber the normal scratch registers, but we need to make sure to
+ * save/restore the registers used for argument passing (R0-R2) in case
+ * the profiled function is using them.  With data registers, R3 is the
+ * only one we can blow away.  With pointer registers, we have P0-P2.
+ *
+ * Upon entry, the RETS will point to the top of the current profiled
+ * function.  And since GCC setup the frame for us, the previous function
+ * will be waiting there.  mmmm pie.
+ */
+ENTRY(__mcount)
+	/* save third function arg early so we can do testing below */
+	[--sp] = r2;
+
+	/* load the function pointer to the tracer */
+	p0.l = _ftrace_trace_function;
+	p0.h = _ftrace_trace_function;
+	r3 = [p0];
+
+	/* optional micro optimization: don't call the stub tracer */
+	r2.l = _ftrace_stub;
+	r2.h = _ftrace_stub;
+	cc = r2 == r3;
+	if ! cc jump .Ldo_trace;
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	/* if the ftrace_graph_return function pointer is not set to
+	 * the ftrace_stub entry, call prepare_ftrace_return().
+	 */
+	p0.l = _ftrace_graph_return;
+	p0.h = _ftrace_graph_return;
+	r3 = [p0];
+	cc = r2 == r3;
+	if ! cc jump _ftrace_graph_caller;
+
+	/* similarly, if the ftrace_graph_entry function pointer is not
+	 * set to the ftrace_graph_entry_stub entry, ...
+	 */
+	p0.l = _ftrace_graph_entry;
+	p0.h = _ftrace_graph_entry;
+	r2.l = _ftrace_graph_entry_stub;
+	r2.h = _ftrace_graph_entry_stub;
+	r3 = [p0];
+	cc = r2 == r3;
+	if ! cc jump _ftrace_graph_caller;
+#endif
+
+	r2 = [sp++];
+	rts;
+
+.Ldo_trace:
+
+	/* save first/second function arg and the return register */
+	[--sp] = r0;
+	[--sp] = r1;
+	[--sp] = rets;
+
+	/* setup the tracer function */
+	p0 = r3;
+
+	/* tracer(ulong frompc, ulong selfpc):
+	 *  frompc: the pc that did the call to ...
+	 *  selfpc: ... this location
+	 * the selfpc itself will need adjusting for the mcount call
+	 */
+	r1 = rets;
+	r0 = [fp + 4];
+	r1 += -MCOUNT_INSN_SIZE;
+
+	/* call the tracer */
+	call (p0);
+
+	/* restore state and get out of dodge */
+.Lfinish_trace:
+	rets = [sp++];
+	r1 = [sp++];
+	r0 = [sp++];
+	r2 = [sp++];
+
+.globl _ftrace_stub
+_ftrace_stub:
+	rts;
+ENDPROC(__mcount)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/* The prepare_ftrace_return() function is similar to the trace function
+ * except it takes a pointer to the location of the frompc.  This is so
+ * the prepare_ftrace_return() can hijack it temporarily for probing
+ * purposes.
+ */
+ENTRY(_ftrace_graph_caller)
+	/* save first/second function arg and the return register */
+	[--sp] = r0;
+	[--sp] = r1;
+	[--sp] = rets;
+
+	r0 = fp;
+	r1 = rets;
+	r0 += 4;
+	r1 += -MCOUNT_INSN_SIZE;
+	call _prepare_ftrace_return;
+
+	jump .Lfinish_trace;
+ENDPROC(_ftrace_graph_caller)
+
+/* Undo the rewrite caused by ftrace_graph_caller().  The common function
+ * ftrace_return_to_handler() will return the original rets so we can
+ * restore it and be on our way.
+ */
+ENTRY(_return_to_handler)
+	/* make sure original return values are saved */
+	[--sp] = p0;
+	[--sp] = r0;
+	[--sp] = r1;
+
+	/* get original return address */
+	call _ftrace_return_to_handler;
+	rets = r0;
+
+	/* anomaly 05000371 - make sure we have at least three instructions
+	 * between rets setting and the return
+	 */
+	r1 = [sp++];
+	r0 = [sp++];
+	p0 = [sp++];
+	rts;
+ENDPROC(_return_to_handler)
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/gptimers.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/gptimers.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/gptimers.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/gptimers.c	2009-09-09 18:13:59.000000000 -0400
@@ -189,10 +189,10 @@
 }
 EXPORT_SYMBOL(set_gptimer_status);
 
-uint16_t get_gptimer_intr(int timer_id)
+int get_gptimer_intr(int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]) ? 1 : 0;
+	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_intr);
 
@@ -203,10 +203,10 @@
 }
 EXPORT_SYMBOL(clear_gptimer_intr);
 
-uint16_t get_gptimer_over(int timer_id)
+int get_gptimer_over(int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
-	return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]) ? 1 : 0;
+	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_over);
 
@@ -217,6 +217,13 @@
 }
 EXPORT_SYMBOL(clear_gptimer_over);
 
+int get_gptimer_run(int timer_id)
+{
+	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
+	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]);
+}
+EXPORT_SYMBOL(get_gptimer_run);
+
 void set_gptimer_config(int timer_id, uint16_t config)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
@@ -244,7 +251,7 @@
 }
 EXPORT_SYMBOL(enable_gptimers);
 
-void disable_gptimers(uint16_t mask)
+static void _disable_gptimers(uint16_t mask)
 {
 	int i;
 	uint16_t m = mask;
@@ -253,6 +260,12 @@
 		group_regs[i]->disable = m & 0xFF;
 		m >>= 8;
 	}
+}
+
+void disable_gptimers(uint16_t mask)
+{
+	int i;
+	_disable_gptimers(mask);
 	for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
 		if (mask & (1 << i))
 			group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i];
@@ -260,6 +273,13 @@
 }
 EXPORT_SYMBOL(disable_gptimers);
 
+void disable_gptimers_sync(uint16_t mask)
+{
+	_disable_gptimers(mask);
+	SSYNC();
+}
+EXPORT_SYMBOL(disable_gptimers_sync);
+
 void set_gptimer_pulse_hi(int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/init_task.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,10 +35,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-
-struct mm_struct init_mm = INIT_MM(init_mm);
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial task structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/ipipe.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/ipipe.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/ipipe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/ipipe.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,7 +52,7 @@
 
 atomic_t __ipipe_irq_lvdepth[IVG15 + 1];
 
-unsigned long __ipipe_irq_lvmask = __all_masked_irq_flags;
+unsigned long __ipipe_irq_lvmask = bfin_no_irqs;
 EXPORT_SYMBOL(__ipipe_irq_lvmask);
 
 static void __ipipe_ack_irq(unsigned irq, struct irq_desc *desc)
@@ -99,7 +99,7 @@
 	 * interrupt.
 	 */
 	m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
-	this_domain = ipipe_current_domain;
+	this_domain = __ipipe_current_domain;
 
 	if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
 		head = &this_domain->p_link;
@@ -167,7 +167,7 @@
 void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
-	int prio = desc->ic_prio;
+	int prio = __ipipe_get_irq_priority(irq);
 
 	desc->depth = 0;
 	if (ipd != &ipipe_root &&
@@ -178,8 +178,7 @@
 
 void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	int prio = desc->ic_prio;
+	int prio = __ipipe_get_irq_priority(irq);
 
 	if (ipd != &ipipe_root &&
 	    atomic_dec_and_test(&__ipipe_irq_lvdepth[prio]))
@@ -213,7 +212,9 @@
 
 int __ipipe_syscall_root(struct pt_regs *regs)
 {
+	struct ipipe_percpu_domain_data *p;
 	unsigned long flags;
+	int ret;
 
 	/*
 	 * We need to run the IRQ tail hook whenever we don't
@@ -232,29 +233,31 @@
 	/*
 	 * This routine either returns:
 	 * 0 -- if the syscall is to be passed to Linux;
-	 * 1 -- if the syscall should not be passed to Linux, and no
+	 * >0 -- if the syscall should not be passed to Linux, and no
 	 * tail work should be performed;
-	 * -1 -- if the syscall should not be passed to Linux but the
+	 * <0 -- if the syscall should not be passed to Linux but the
 	 * tail work has to be performed (for handling signals etc).
 	 */
 
-	if (__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL) &&
-	    __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs) > 0) {
-		if (ipipe_root_domain_p && !in_atomic()) {
-			/*
-			 * Sync pending VIRQs before _TIF_NEED_RESCHED
-			 * is tested.
-			 */
-			local_irq_save_hw(flags);
-			if ((ipipe_root_cpudom_var(irqpend_himask) & IPIPE_IRQMASK_VIRT) != 0)
-				__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
-			local_irq_restore_hw(flags);
-			return -1;
-		}
+	if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
+		return 0;
+
+	ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
+
+	local_irq_save_hw(flags);
+
+	if (!__ipipe_root_domain_p) {
+		local_irq_restore_hw(flags);
 		return 1;
 	}
 
-	return 0;
+	p = ipipe_root_cpudom_ptr();
+	if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
+		__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
+
+	local_irq_restore_hw(flags);
+
+	return -ret;
 }
 
 unsigned long ipipe_critical_enter(void (*syncfn) (void))
@@ -310,12 +313,16 @@
 
 asmlinkage void __ipipe_sync_root(void)
 {
+	void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
 	unsigned long flags;
 
 	BUG_ON(irqs_disabled());
 
 	local_irq_save_hw(flags);
 
+	if (irq_tail_hook)
+		irq_tail_hook();
+
 	clear_thread_flag(TIF_IRQ_SYNC);
 
 	if (ipipe_root_cpudom_var(irqpend_himask) != 0)
@@ -326,9 +333,7 @@
 
 void ___ipipe_sync_pipeline(unsigned long syncmask)
 {
-	struct ipipe_domain *ipd = ipipe_current_domain;
-
-	if (ipd == ipipe_root_domain) {
+	if (__ipipe_root_domain_p) {
 		if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
 			return;
 	}
@@ -337,8 +342,3 @@
 }
 
 EXPORT_SYMBOL(show_stack);
-
-#ifdef CONFIG_IPIPE_TRACE_MCOUNT
-void notrace _mcount(void);
-EXPORT_SYMBOL(_mcount);
-#endif /* CONFIG_IPIPE_TRACE_MCOUNT */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/irqchip.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/irqchip.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/irqchip.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/irqchip.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,36 +38,15 @@
 #include <asm/pda.h>
 
 static atomic_t irq_err_count;
-static spinlock_t irq_controller_lock;
-
-/*
- * Dummy mask/unmask handler
- */
-void dummy_mask_unmask_irq(unsigned int irq)
-{
-}
-
 void ack_bad_irq(unsigned int irq)
 {
 	atomic_inc(&irq_err_count);
 	printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
 }
 
-static struct irq_chip bad_chip = {
-	.ack = dummy_mask_unmask_irq,
-	.mask = dummy_mask_unmask_irq,
-	.unmask = dummy_mask_unmask_irq,
-};
-
 static struct irq_desc bad_irq_desc = {
-	.status = IRQ_DISABLED,
-	.chip = &bad_chip,
 	.handle_irq = handle_bad_irq,
-	.depth = 1,
 	.lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
-#ifdef CONFIG_SMP
-	.affinity = CPU_MASK_ALL
-#endif
 };
 
 #ifdef CONFIG_CPUMASK_OFFSTACK
@@ -75,6 +54,7 @@
 #error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK."
 #endif
 
+#ifdef CONFIG_PROC_FS
 int show_interrupts(struct seq_file *p, void *v)
 {
 	int i = *(loff_t *) v, j;
@@ -106,50 +86,29 @@
 	}
 	return 0;
 }
-
-/*
- * do_IRQ handles all hardware IRQs.  Decoded IRQs should not
- * come via this function.  Instead, they should provide their
- * own 'handler'
- */
-#ifdef CONFIG_DO_IRQ_L1
-__attribute__((l1_text))
-#endif
-asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
-{
-	struct pt_regs *old_regs;
-	struct irq_desc *desc = irq_desc + irq;
-#ifndef CONFIG_IPIPE
-	unsigned short pending, other_ints;
 #endif
-	old_regs = set_irq_regs(regs);
-
-	/*
-	 * Some hardware gives randomly wrong interrupts.  Rather
-	 * than crashing, do something sensible.
-	 */
-	if (irq >= NR_IRQS)
-		desc = &bad_irq_desc;
 
-	irq_enter();
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
+static void check_stack_overflow(int irq)
+{
 	/* Debugging check for stack overflow: is there less than STACK_WARN free? */
-	{
-		long sp;
-
-		sp = __get_SP() & (THREAD_SIZE-1);
+	long sp = __get_SP() & (THREAD_SIZE - 1);
 
-		if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
-			dump_stack();
-			printk(KERN_EMERG "%s: possible stack overflow while handling irq %i "
-					" only %ld bytes free\n",
-				__func__, irq, sp - sizeof(struct thread_info));
-		}
+	if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
+		dump_stack();
+		pr_emerg("irq%i: possible stack overflow only %ld bytes free\n",
+			irq, sp - sizeof(struct thread_info));
 	}
+}
+#else
+static inline void check_stack_overflow(int irq) { }
 #endif
-	generic_handle_irq(irq);
 
 #ifndef CONFIG_IPIPE
+static void maybe_lower_to_irq14(void)
+{
+	unsigned short pending, other_ints;
+
 	/*
 	 * If we're the only interrupt running (ignoring IRQ15 which
 	 * is for syscalls), lower our priority to IRQ14 so that
@@ -163,7 +122,38 @@
 	other_ints = pending & (pending - 1);
 	if (other_ints == 0)
 		lower_to_irq14();
-#endif /* !CONFIG_IPIPE */
+}
+#else
+static inline void maybe_lower_to_irq14(void) { }
+#endif
+
+/*
+ * do_IRQ handles all hardware IRQs.  Decoded IRQs should not
+ * come via this function.  Instead, they should provide their
+ * own 'handler'
+ */
+#ifdef CONFIG_DO_IRQ_L1
+__attribute__((l1_text))
+#endif
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+
+	check_stack_overflow(irq);
+
+	/*
+	 * Some hardware gives randomly wrong interrupts.  Rather
+	 * than crashing, do something sensible.
+	 */
+	if (irq >= NR_IRQS)
+		handle_bad_irq(irq, &bad_irq_desc);
+	else
+		generic_handle_irq(irq);
+
+	maybe_lower_to_irq14();
+
 	irq_exit();
 
 	set_irq_regs(old_regs);
@@ -171,14 +161,6 @@
 
 void __init init_IRQ(void)
 {
-	struct irq_desc *desc;
-	int irq;
-
-	spin_lock_init(&irq_controller_lock);
-	for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
-		*desc = bad_irq_desc;
-	}
-
 	init_arch_irq();
 
 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/kgdb.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/kgdb.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/kgdb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/kgdb.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,15 +34,6 @@
 #error change the definition of slavecpulocks
 #endif
 
-#define IN_MEM(addr, size, l1_addr, l1_size) \
-({ \
-	unsigned long __addr = (unsigned long)(addr); \
-	(l1_size && __addr >= l1_addr && __addr + (size) <= l1_addr + l1_size); \
-})
-#define ASYNC_BANK_SIZE \
-	(ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
-	 ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE)
-
 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
 	gdb_regs[BFIN_R0] = regs->r0;
@@ -463,42 +454,89 @@
 
 static int validate_memory_access_address(unsigned long addr, int size)
 {
-	int cpu = raw_smp_processor_id();
+	if (size < 0 || addr == 0)
+		return -EFAULT;
+	return bfin_mem_access_type(addr, size);
+}
 
-	if (size < 0)
-		return EFAULT;
-	if (addr >= 0x1000 && (addr + size) <= physical_mem_end)
-		return 0;
-	if (addr >= SYSMMR_BASE)
-		return 0;
-	if (IN_MEM(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK_SIZE))
-		return 0;
-	if (cpu == 0) {
-		if (IN_MEM(addr, size, L1_SCRATCH_START, L1_SCRATCH_LENGTH))
-			return 0;
-		if (IN_MEM(addr, size, L1_CODE_START, L1_CODE_LENGTH))
-			return 0;
-		if (IN_MEM(addr, size, L1_DATA_A_START, L1_DATA_A_LENGTH))
-			return 0;
-		if (IN_MEM(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH))
-			return 0;
-#ifdef CONFIG_SMP
-	} else if (cpu == 1) {
-		if (IN_MEM(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
+static int bfin_probe_kernel_read(char *dst, char *src, int size)
+{
+	unsigned long lsrc = (unsigned long)src;
+	int mem_type;
+
+	mem_type = validate_memory_access_address(lsrc, size);
+	if (mem_type < 0)
+		return mem_type;
+
+	if (lsrc >= SYSMMR_BASE) {
+		if (size == 2 && lsrc % 2 == 0) {
+			u16 mmr = bfin_read16(src);
+			memcpy(dst, &mmr, sizeof(mmr));
 			return 0;
-		if (IN_MEM(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
+		} else if (size == 4 && lsrc % 4 == 0) {
+			u32 mmr = bfin_read32(src);
+			memcpy(dst, &mmr, sizeof(mmr));
 			return 0;
-		if (IN_MEM(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
+		}
+	} else {
+		switch (mem_type) {
+			case BFIN_MEM_ACCESS_CORE:
+			case BFIN_MEM_ACCESS_CORE_ONLY:
+				return probe_kernel_read(dst, src, size);
+			/* XXX: should support IDMA here with SMP */
+			case BFIN_MEM_ACCESS_DMA:
+				if (dma_memcpy(dst, src, size))
+					return 0;
+				break;
+			case BFIN_MEM_ACCESS_ITEST:
+				if (isram_memcpy(dst, src, size))
+					return 0;
+				break;
+		}
+	}
+
+	return -EFAULT;
+}
+
+static int bfin_probe_kernel_write(char *dst, char *src, int size)
+{
+	unsigned long ldst = (unsigned long)dst;
+	int mem_type;
+
+	mem_type = validate_memory_access_address(ldst, size);
+	if (mem_type < 0)
+		return mem_type;
+
+	if (ldst >= SYSMMR_BASE) {
+		if (size == 2 && ldst % 2 == 0) {
+			u16 mmr;
+			memcpy(&mmr, src, sizeof(mmr));
+			bfin_write16(dst, mmr);
 			return 0;
-		if (IN_MEM(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
+		} else if (size == 4 && ldst % 4 == 0) {
+			u32 mmr;
+			memcpy(&mmr, src, sizeof(mmr));
+			bfin_write32(dst, mmr);
 			return 0;
-#endif
+		}
+	} else {
+		switch (mem_type) {
+			case BFIN_MEM_ACCESS_CORE:
+			case BFIN_MEM_ACCESS_CORE_ONLY:
+				return probe_kernel_write(dst, src, size);
+			/* XXX: should support IDMA here with SMP */
+			case BFIN_MEM_ACCESS_DMA:
+				if (dma_memcpy(dst, src, size))
+					return 0;
+				break;
+			case BFIN_MEM_ACCESS_ITEST:
+				if (isram_memcpy(dst, src, size))
+					return 0;
+				break;
+		}
 	}
 
-	if (IN_MEM(addr, size, L2_START, L2_LENGTH))
-		return 0;
-
-	return EFAULT;
+	return -EFAULT;
 }
 
 /*
@@ -508,14 +546,7 @@
 int kgdb_mem2hex(char *mem, char *buf, int count)
 {
 	char *tmp;
-	int err = 0;
-	unsigned char *pch;
-	unsigned short mmr16;
-	unsigned long mmr32;
-	int cpu = raw_smp_processor_id();
-
-	if (validate_memory_access_address((unsigned long)mem, count))
-		return EFAULT;
+	int err;
 
 	/*
 	 * We use the upper half of buf as an intermediate buffer for the
@@ -523,44 +554,7 @@
 	 */
 	tmp = buf + count;
 
-	if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
-		switch (count) {
-		case 2:
-			if ((unsigned int)mem % 2 == 0) {
-				mmr16 = *(unsigned short *)mem;
-				pch = (unsigned char *)&mmr16;
-				*tmp++ = *pch++;
-				*tmp++ = *pch++;
-				tmp -= 2;
-			} else
-				err = EFAULT;
-			break;
-		case 4:
-			if ((unsigned int)mem % 4 == 0) {
-				mmr32 = *(unsigned long *)mem;
-				pch = (unsigned char *)&mmr32;
-				*tmp++ = *pch++;
-				*tmp++ = *pch++;
-				*tmp++ = *pch++;
-				*tmp++ = *pch++;
-				tmp -= 4;
-			} else
-				err = EFAULT;
-			break;
-		default:
-			err = EFAULT;
-		}
-	} else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH))
-#ifdef CONFIG_SMP
-		|| (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH))
-#endif
-		) {
-		/* access L1 instruction SRAM*/
-		if (dma_memcpy(tmp, mem, count) == NULL)
-			err = EFAULT;
-	} else
-		err = probe_kernel_read(tmp, mem, count);
-
+	err = bfin_probe_kernel_read(tmp, mem, count);
 	if (!err) {
 		while (count > 0) {
 			buf = pack_hex_byte(buf, *tmp);
@@ -581,60 +575,21 @@
  */
 int kgdb_ebin2mem(char *buf, char *mem, int count)
 {
-	char *tmp_old;
-	char *tmp_new;
-	unsigned short *mmr16;
-	unsigned long *mmr32;
-	int err = 0;
-	int size = 0;
-	int cpu = raw_smp_processor_id();
+	char *tmp_old, *tmp_new;
+	int size;
 
 	tmp_old = tmp_new = buf;
 
-	while (count-- > 0) {
+	for (size = 0; size < count; ++size) {
 		if (*tmp_old == 0x7d)
 			*tmp_new = *(++tmp_old) ^ 0x20;
 		else
 			*tmp_new = *tmp_old;
 		tmp_new++;
 		tmp_old++;
-		size++;
 	}
 
-	if (validate_memory_access_address((unsigned long)mem, size))
-		return EFAULT;
-
-	if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
-		switch (size) {
-		case 2:
-			if ((unsigned int)mem % 2 == 0) {
-				mmr16 = (unsigned short *)buf;
-				*(unsigned short *)mem = *mmr16;
-			} else
-				return EFAULT;
-			break;
-		case 4:
-			if ((unsigned int)mem % 4 == 0) {
-				mmr32 = (unsigned long *)buf;
-				*(unsigned long *)mem = *mmr32;
-			} else
-				return EFAULT;
-			break;
-		default:
-			return EFAULT;
-		}
-	} else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH))
-#ifdef CONFIG_SMP
-		|| (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH))
-#endif
-		) {
-		/* access L1 instruction SRAM */
-		if (dma_memcpy(mem, buf, size) == NULL)
-			err = EFAULT;
-	} else
-		err = probe_kernel_write(mem, buf, size);
-
-	return err;
+	return bfin_probe_kernel_write(mem, buf, count);
 }
 
 /*
@@ -644,14 +599,7 @@
  */
 int kgdb_hex2mem(char *buf, char *mem, int count)
 {
-	char *tmp_raw;
-	char *tmp_hex;
-	unsigned short *mmr16;
-	unsigned long *mmr32;
-	int cpu = raw_smp_processor_id();
-
-	if (validate_memory_access_address((unsigned long)mem, count))
-		return EFAULT;
+	char *tmp_raw, *tmp_hex;
 
 	/*
 	 * We use the upper half of buf as an intermediate buffer for the
@@ -666,38 +614,18 @@
 		*tmp_raw |= hex(*tmp_hex--) << 4;
 	}
 
-	if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
-		switch (count) {
-		case 2:
-			if ((unsigned int)mem % 2 == 0) {
-				mmr16 = (unsigned short *)tmp_raw;
-				*(unsigned short *)mem = *mmr16;
-			} else
-				return EFAULT;
-			break;
-		case 4:
-			if ((unsigned int)mem % 4 == 0) {
-				mmr32 = (unsigned long *)tmp_raw;
-				*(unsigned long *)mem = *mmr32;
-			} else
-				return EFAULT;
-			break;
-		default:
-			return EFAULT;
-		}
-	} else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH))
-#ifdef CONFIG_SMP
-		|| (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH))
-#endif
-		) {
-		/* access L1 instruction SRAM */
-		if (dma_memcpy(mem, tmp_raw, count) == NULL)
-			return EFAULT;
-	} else
-		return probe_kernel_write(mem, tmp_raw, count);
-	return 0;
+	return bfin_probe_kernel_write(mem, tmp_raw, count);
 }
 
+#define IN_MEM(addr, size, l1_addr, l1_size) \
+({ \
+	unsigned long __addr = (unsigned long)(addr); \
+	(l1_size && __addr >= l1_addr && __addr + (size) <= l1_addr + l1_size); \
+})
+#define ASYNC_BANK_SIZE \
+	(ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
+	 ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE)
+
 int kgdb_validate_break_address(unsigned long addr)
 {
 	int cpu = raw_smp_processor_id();
@@ -715,51 +643,22 @@
 	if (IN_MEM(addr, BREAK_INSTR_SIZE, L2_START, L2_LENGTH))
 		return 0;
 
-	return EFAULT;
+	return -EFAULT;
 }
 
 int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
 {
-	int err;
-	int cpu = raw_smp_processor_id();
-
-	if ((cpu == 0 && IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH))
-#ifdef CONFIG_SMP
-		|| (cpu == 1 && IN_MEM(addr, BREAK_INSTR_SIZE, COREB_L1_CODE_START, L1_CODE_LENGTH))
-#endif
-		) {
-		/* access L1 instruction SRAM */
-		if (dma_memcpy(saved_instr, (void *)addr, BREAK_INSTR_SIZE)
-			== NULL)
-			return -EFAULT;
-
-		if (dma_memcpy((void *)addr, arch_kgdb_ops.gdb_bpt_instr,
-			BREAK_INSTR_SIZE) == NULL)
-			return -EFAULT;
-
-		return 0;
-	} else {
-		err = probe_kernel_read(saved_instr, (char *)addr,
-			BREAK_INSTR_SIZE);
-		if (err)
-			return err;
-
-		return probe_kernel_write((char *)addr,
-			arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
-	}
+	int err = bfin_probe_kernel_read(saved_instr, (char *)addr,
+	                                 BREAK_INSTR_SIZE);
+	if (err)
+		return err;
+	return bfin_probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
+	                               BREAK_INSTR_SIZE);
 }
 
 int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
 {
-	if (IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH)) {
-		/* access L1 instruction SRAM */
-		if (dma_memcpy((void *)addr, bundle, BREAK_INSTR_SIZE) == NULL)
-			return -EFAULT;
-
-		return 0;
-	} else
-		return probe_kernel_write((char *)addr,
-				(char *)bundle, BREAK_INSTR_SIZE);
+	return bfin_probe_kernel_write((char *)addr, bundle, BREAK_INSTR_SIZE);
 }
 
 int kgdb_arch_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/Makefile linux-libre-2.6.31-gnu/arch/blackfin/kernel/Makefile
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -15,14 +15,18 @@
     obj-y += time.o
 endif
 
+obj-$(CONFIG_FUNCTION_TRACER)        += ftrace-entry.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER)  += ftrace.o
+CFLAGS_REMOVE_ftrace.o = -pg
+
 obj-$(CONFIG_IPIPE)                  += ipipe.o
-obj-$(CONFIG_IPIPE_TRACE_MCOUNT)     += mcount.o
 obj-$(CONFIG_BFIN_GPTIMERS)          += gptimers.o
 obj-$(CONFIG_CPLB_INFO)              += cplbinfo.o
 obj-$(CONFIG_MODULES)                += module.o
 obj-$(CONFIG_KGDB)                   += kgdb.o
 obj-$(CONFIG_KGDB_TESTS)             += kgdb_test.o
 obj-$(CONFIG_EARLY_PRINTK)           += early_printk.o
+obj-$(CONFIG_STACKTRACE)             += stacktrace.o
 
 # the kgdb test puts code into L2 and without linker
 # relaxation, we need to force long calls to/from it
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/mcount.S linux-libre-2.6.31-gnu/arch/blackfin/kernel/mcount.S
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/mcount.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/mcount.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/*
- * linux/arch/blackfin/mcount.S
- *
- * Copyright (C) 2006 Analog Devices Inc.
- *
- * 2007/04/12 Save index, length, modify and base registers. --rpm
- */
-
-#include <linux/linkage.h>
-#include <asm/blackfin.h>
-
-.text
-
-.align 4 	/* just in case */
-
-ENTRY(__mcount)
-	[--sp] = i0;
-	[--sp] = i1;
-	[--sp] = i2;
-	[--sp] = i3;
-	[--sp] = l0;
-	[--sp] = l1;
-	[--sp] = l2;
-	[--sp] = l3;
-	[--sp] = m0;
-	[--sp] = m1;
-	[--sp] = m2;
-	[--sp] = m3;
-	[--sp] = b0;
-	[--sp] = b1;
-	[--sp] = b2;
-	[--sp] = b3;
-	[--sp] = ( r7:0, p5:0 );
-	[--sp] = ASTAT;
-
-	p1.L = _ipipe_trace_enable;
-	p1.H = _ipipe_trace_enable;
-	r7 = [p1];
-	CC = r7 == 0;
-	if CC jump out;
-	link 0x10;
-	r0 = 0x0;
-	[sp + 0xc] = r0; /* v */
-	r0 = 0x0;	/* type: IPIPE_TRACE_FN */
-	r1 = rets;
-	p0 = [fp];	/* p0: Prior FP */
-	r2 = [p0 + 4];	/* r2: Prior RETS */
-	call ___ipipe_trace;
-	unlink;
-out:
-	ASTAT = [sp++];
-	( r7:0, p5:0 ) = [sp++];
-	b3 = [sp++];
-	b2 = [sp++];
-	b1 = [sp++];
-	b0 = [sp++];
-	m3 = [sp++];
-	m2 = [sp++];
-	m1 = [sp++];
-	m0 = [sp++];
-	l3 = [sp++];
-	l2 = [sp++];
-	l1 = [sp++];
-	l0 = [sp++];
-	i3 = [sp++];
-	i2 = [sp++];
-	i1 = [sp++];
-	i0 = [sp++];
-	rts;
-ENDPROC(__mcount)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/module.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -201,8 +201,8 @@
 /*            Arithmetic relocations are handled.                        */
 /*            We do not expect LSETUP to be split and hence is not       */
 /*            handled.                                                   */
-/*            R_byte and R_byte2 are also not handled as the gas         */
-/*            does not generate it.                                      */
+/*            R_BFIN_BYTE and R_BFIN_BYTE2 are also not handled as the   */
+/*            gas does not generate it.                                  */
 /*************************************************************************/
 int
 apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
@@ -243,8 +243,8 @@
 #endif
 		switch (ELF32_R_TYPE(rel[i].r_info)) {
 
-		case R_pcrel24:
-		case R_pcrel24_jump_l:
+		case R_BFIN_PCREL24:
+		case R_BFIN_PCREL24_JUMP_L:
 			/* Add the value, subtract its postition */
 			location16 =
 			    (uint16_t *) (sechdrs[sechdrs[relsec].sh_info].
@@ -266,18 +266,18 @@
 			    (*location16 & 0xff00) | (value >> 16 & 0x00ff);
 			*(location16 + 1) = value & 0xffff;
 			break;
-		case R_pcrel12_jump:
-		case R_pcrel12_jump_s:
+		case R_BFIN_PCREL12_JUMP:
+		case R_BFIN_PCREL12_JUMP_S:
 			value -= (uint32_t) location32;
 			value >>= 1;
 			*location16 = (value & 0xfff);
 			break;
-		case R_pcrel10:
+		case R_BFIN_PCREL10:
 			value -= (uint32_t) location32;
 			value >>= 1;
 			*location16 = (value & 0x3ff);
 			break;
-		case R_luimm16:
+		case R_BFIN_LUIMM16:
 			pr_debug("before %x after %x\n", *location16,
 				       (value & 0xffff));
 			tmp = (value & 0xffff);
@@ -286,7 +286,7 @@
 			} else
 				*location16 = tmp;
 			break;
-		case R_huimm16:
+		case R_BFIN_HUIMM16:
 			pr_debug("before %x after %x\n", *location16,
 				       ((value >> 16) & 0xffff));
 			tmp = ((value >> 16) & 0xffff);
@@ -295,10 +295,10 @@
 			} else
 				*location16 = tmp;
 			break;
-		case R_rimm16:
+		case R_BFIN_RIMM16:
 			*location16 = (value & 0xffff);
 			break;
-		case R_byte4_data:
+		case R_BFIN_BYTE4_DATA:
 			pr_debug("before %x after %x\n", *location32, value);
 			*location32 = value;
 			break;
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/process.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -160,6 +160,29 @@
 }
 EXPORT_SYMBOL(kernel_thread);
 
+/*
+ * Do necessary setup to start up a newly executed thread.
+ *
+ * pass the data segment into user programs if it exists,
+ * it can't hurt anything as far as I can tell
+ */
+void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+{
+	set_fs(USER_DS);
+	regs->pc = new_ip;
+	if (current->mm)
+		regs->p5 = current->mm->start_data;
+#ifdef CONFIG_SMP
+	task_thread_info(current)->l1_task_info.stack_start =
+		(void *)current->mm->context.stack_start;
+	task_thread_info(current)->l1_task_info.lowest_sp = (void *)new_sp;
+	memcpy(L1_SCRATCH_TASK_INFO, &task_thread_info(current)->l1_task_info,
+	       sizeof(*L1_SCRATCH_TASK_INFO));
+#endif
+	wrusp(new_sp);
+}
+EXPORT_SYMBOL_GPL(start_thread);
+
 void flush_thread(void)
 {
 }
@@ -321,57 +344,151 @@
 	}
 }
 
+static inline
+int in_mem(unsigned long addr, unsigned long size,
+           unsigned long start, unsigned long end)
+{
+	return addr >= start && addr + size <= end;
+}
+static inline
+int in_mem_const_off(unsigned long addr, unsigned long size, unsigned long off,
+                     unsigned long const_addr, unsigned long const_size)
+{
+	return const_size &&
+	       in_mem(addr, size, const_addr + off, const_addr + const_size);
+}
+static inline
+int in_mem_const(unsigned long addr, unsigned long size,
+                 unsigned long const_addr, unsigned long const_size)
+{
+	return in_mem_const_off(addr, size, 0, const_addr, const_size);
+}
+#define IN_ASYNC(bnum, bctlnum) \
+({ \
+	(bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? -EFAULT : \
+	bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? -EFAULT : \
+	BFIN_MEM_ACCESS_CORE; \
+})
+
+int bfin_mem_access_type(unsigned long addr, unsigned long size)
+{
+	int cpu = raw_smp_processor_id();
+
+	/* Check that things do not wrap around */
+	if (addr > ULONG_MAX - size)
+		return -EFAULT;
+
+	if (in_mem(addr, size, FIXED_CODE_START, physical_mem_end))
+		return BFIN_MEM_ACCESS_CORE;
+
+	if (in_mem_const(addr, size, L1_CODE_START, L1_CODE_LENGTH))
+		return cpu == 0 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA;
+	if (in_mem_const(addr, size, L1_SCRATCH_START, L1_SCRATCH_LENGTH))
+		return cpu == 0 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT;
+	if (in_mem_const(addr, size, L1_DATA_A_START, L1_DATA_A_LENGTH))
+		return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
+	if (in_mem_const(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH))
+		return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
+#ifdef COREB_L1_CODE_START
+	if (in_mem_const(addr, size, COREB_L1_CODE_START, COREB_L1_CODE_LENGTH))
+		return cpu == 1 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA;
+	if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
+		return cpu == 1 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT;
+	if (in_mem_const(addr, size, COREB_L1_DATA_A_START, COREB_L1_DATA_A_LENGTH))
+		return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
+	if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
+		return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
+#endif
+	if (in_mem_const(addr, size, L2_START, L2_LENGTH))
+		return BFIN_MEM_ACCESS_CORE;
+
+	if (addr >= SYSMMR_BASE)
+		return BFIN_MEM_ACCESS_CORE_ONLY;
+
+	/* We can't read EBIU banks that aren't enabled or we end up hanging
+	 * on the access to the async space.
+	 */
+	if (in_mem_const(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE))
+		return IN_ASYNC(0, 0);
+	if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE))
+		return IN_ASYNC(1, 0);
+	if (in_mem_const(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE))
+		return IN_ASYNC(2, 1);
+	if (in_mem_const(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE))
+		return IN_ASYNC(3, 1);
+
+	if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH))
+		return BFIN_MEM_ACCESS_CORE;
+	if (in_mem_const(addr, size, L1_ROM_START, L1_ROM_LENGTH))
+		return BFIN_MEM_ACCESS_DMA;
+
+	return -EFAULT;
+}
+
 #if defined(CONFIG_ACCESS_CHECK)
+#ifdef CONFIG_ACCESS_OK_L1
+__attribute__((l1_text))
+#endif
 /* Return 1 if access to memory range is OK, 0 otherwise */
 int _access_ok(unsigned long addr, unsigned long size)
 {
 	if (size == 0)
 		return 1;
-	if (addr > (addr + size))
+	/* Check that things do not wrap around */
+	if (addr > ULONG_MAX - size)
 		return 0;
 	if (segment_eq(get_fs(), KERNEL_DS))
 		return 1;
 #ifdef CONFIG_MTD_UCLINUX
-	if (addr >= memory_start && (addr + size) <= memory_end)
-		return 1;
-	if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end)
+	if (1)
+#else
+	if (0)
+#endif
+	{
+		if (in_mem(addr, size, memory_start, memory_end))
+			return 1;
+		if (in_mem(addr, size, memory_mtd_end, physical_mem_end))
+			return 1;
+# ifndef CONFIG_ROMFS_ON_MTD
+		if (0)
+# endif
+			/* For XIP, allow user space to use pointers within the ROMFS.  */
+			if (in_mem(addr, size, memory_mtd_start, memory_mtd_end))
+				return 1;
+	} else {
+		if (in_mem(addr, size, memory_start, physical_mem_end))
+			return 1;
+	}
+
+	if (in_mem(addr, size, (unsigned long)__init_begin, (unsigned long)__init_end))
 		return 1;
 
-#ifdef CONFIG_ROMFS_ON_MTD
-	/* For XIP, allow user space to use pointers within the ROMFS.  */
-	if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end)
+	if (in_mem_const(addr, size, L1_CODE_START, L1_CODE_LENGTH))
 		return 1;
-#endif
-#else
-	if (addr >= memory_start && (addr + size) <= physical_mem_end)
+	if (in_mem_const_off(addr, size, _etext_l1 - _stext_l1, L1_CODE_START, L1_CODE_LENGTH))
 		return 1;
-#endif
-	if (addr >= (unsigned long)__init_begin &&
-	    addr + size <= (unsigned long)__init_end)
+	if (in_mem_const_off(addr, size, _ebss_l1 - _sdata_l1, L1_DATA_A_START, L1_DATA_A_LENGTH))
 		return 1;
-	if (addr >= get_l1_scratch_start()
-	    && addr + size <= get_l1_scratch_start() + L1_SCRATCH_LENGTH)
+	if (in_mem_const_off(addr, size, _ebss_b_l1 - _sdata_b_l1, L1_DATA_B_START, L1_DATA_B_LENGTH))
 		return 1;
-#if L1_CODE_LENGTH != 0
-	if (addr >= get_l1_code_start() + (_etext_l1 - _stext_l1)
-	    && addr + size <= get_l1_code_start() + L1_CODE_LENGTH)
+#ifdef COREB_L1_CODE_START
+	if (in_mem_const(addr, size, COREB_L1_CODE_START, COREB_L1_CODE_LENGTH))
 		return 1;
-#endif
-#if L1_DATA_A_LENGTH != 0
-	if (addr >= get_l1_data_a_start() + (_ebss_l1 - _sdata_l1)
-	    && addr + size <= get_l1_data_a_start() + L1_DATA_A_LENGTH)
+	if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
 		return 1;
-#endif
-#if L1_DATA_B_LENGTH != 0
-	if (addr >= get_l1_data_b_start() + (_ebss_b_l1 - _sdata_b_l1)
-	    && addr + size <= get_l1_data_b_start() + L1_DATA_B_LENGTH)
+	if (in_mem_const(addr, size, COREB_L1_DATA_A_START, COREB_L1_DATA_A_LENGTH))
 		return 1;
-#endif
-#if L2_LENGTH != 0
-	if (addr >= L2_START + (_ebss_l2 - _stext_l2)
-	    && addr + size <= L2_START + L2_LENGTH)
+	if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
 		return 1;
 #endif
+	if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH))
+		return 1;
+
+	if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH))
+		return 1;
+	if (in_mem_const(addr, size, L1_ROM_START, L1_ROM_LENGTH))
+		return 1;
+
 	return 0;
 }
 EXPORT_SYMBOL(_access_ok);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,7 +31,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/setup.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,9 +18,12 @@
 #include <linux/tty.h>
 #include <linux/pfn.h>
 
+#ifdef CONFIG_MTD_UCLINUX
+#include <linux/mtd/map.h>
 #include <linux/ext2_fs.h>
 #include <linux/cramfs_fs.h>
 #include <linux/romfs_fs.h>
+#endif
 
 #include <asm/cplb.h>
 #include <asm/cacheflush.h>
@@ -45,6 +48,7 @@
 EXPORT_SYMBOL(reserved_mem_dcache_on);
 
 #ifdef CONFIG_MTD_UCLINUX
+extern struct map_info uclinux_ram_map;
 unsigned long memory_mtd_end, memory_mtd_start, mtd_size;
 unsigned long _ebss;
 EXPORT_SYMBOL(memory_mtd_end);
@@ -113,15 +117,49 @@
 	 */
 #ifdef CONFIG_BFIN_ICACHE
 	printk(KERN_INFO "Instruction Cache Enabled for CPU%u\n", cpu);
+	printk(KERN_INFO "  External memory:"
+# ifdef CONFIG_BFIN_EXTMEM_ICACHEABLE
+	       " cacheable"
+# else
+	       " uncacheable"
+# endif
+	       " in instruction cache\n");
+	if (L2_LENGTH)
+		printk(KERN_INFO "  L2 SRAM        :"
+# ifdef CONFIG_BFIN_L2_ICACHEABLE
+		       " cacheable"
+# else
+		       " uncacheable"
+# endif
+		       " in instruction cache\n");
+
+#else
+	printk(KERN_INFO "Instruction Cache Disabled for CPU%u\n", cpu);
 #endif
+
 #ifdef CONFIG_BFIN_DCACHE
-	printk(KERN_INFO "Data Cache Enabled for CPU%u"
-# if defined CONFIG_BFIN_WB
-		" (write-back)"
-# elif defined CONFIG_BFIN_WT
-		" (write-through)"
+	printk(KERN_INFO "Data Cache Enabled for CPU%u\n", cpu);
+	printk(KERN_INFO "  External memory:"
+# if defined CONFIG_BFIN_EXTMEM_WRITEBACK
+	       " cacheable (write-back)"
+# elif defined CONFIG_BFIN_EXTMEM_WRITETHROUGH
+	       " cacheable (write-through)"
+# else
+	       " uncacheable"
 # endif
-		"\n", cpu);
+	       " in data cache\n");
+	if (L2_LENGTH)
+		printk(KERN_INFO "  L2 SRAM        :"
+# if defined CONFIG_BFIN_L2_WRITEBACK
+		       " cacheable (write-back)"
+# elif defined CONFIG_BFIN_L2_WRITETHROUGH
+		       " cacheable (write-through)"
+# else
+		       " uncacheable"
+# endif
+		       " in data cache\n");
+#else
+	printk(KERN_INFO "Data Cache Disabled for CPU%u\n", cpu);
 #endif
 }
 
@@ -130,7 +168,6 @@
 	struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu);
 
 	cpudata->idle = current;
-	cpudata->loops_per_jiffy = loops_per_jiffy;
 	cpudata->imemctl = bfin_read_IMEM_CONTROL();
 	cpudata->dmemctl = bfin_read_DMEM_CONTROL();
 }
@@ -150,40 +187,45 @@
 	unsigned long l1_data_b_length;
 	unsigned long l2_length;
 
+	/*
+	 * due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S
+	 * we know that everything about l1 text/data is nice and aligned,
+	 * so copy by 4 byte chunks, and don't worry about overlapping
+	 * src/dest.
+	 *
+	 * We can't use the dma_memcpy functions, since they can call
+	 * scheduler functions which might be in L1 :( and core writes
+	 * into L1 instruction cause bad access errors, so we are stuck,
+	 * we are required to use DMA, but can't use the common dma
+	 * functions. We can't use memcpy either - since that might be
+	 * going to be in the relocated L1
+	 */
+
 	blackfin_dma_early_init();
 
+	/* if necessary, copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
 	l1_code_length = _etext_l1 - _stext_l1;
-	if (l1_code_length > L1_CODE_LENGTH)
-		panic("L1 Instruction SRAM Overflow\n");
-	/* cannot complain as printk is not available as yet.
-	 * But we can continue booting and complain later!
-	 */
-
-	/* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
-	dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
+	if (l1_code_length)
+		early_dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
 
+	/* if necessary, copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */
 	l1_data_a_length = _sbss_l1 - _sdata_l1;
-	if (l1_data_a_length > L1_DATA_A_LENGTH)
-		panic("L1 Data SRAM Bank A Overflow\n");
-
-	/* Copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */
-	dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
+	if (l1_data_a_length)
+		early_dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
 
+	/* if necessary, copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */
 	l1_data_b_length = _sbss_b_l1 - _sdata_b_l1;
-	if (l1_data_b_length > L1_DATA_B_LENGTH)
-		panic("L1 Data SRAM Bank B Overflow\n");
-
-	/* Copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */
-	dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
+	if (l1_data_b_length)
+		early_dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
 			l1_data_a_length, l1_data_b_length);
 
+	early_dma_memcpy_done();
+
+	/* if necessary, copy _stext_l2 to _edata_l2 to L2 SRAM */
 	if (L2_LENGTH != 0) {
 		l2_length = _sbss_l2 - _stext_l2;
-		if (l2_length > L2_LENGTH)
-			panic("L2 SRAM Overflow\n");
-
-		/* Copy _stext_l2 to _edata_l2 to L2 SRAM */
-		dma_memcpy(_stext_l2, _l2_lma_start, l2_length);
+		if (l2_length)
+			memcpy(_stext_l2, _l2_lma_start, l2_length);
 	}
 }
 
@@ -365,13 +407,14 @@
 			bfin_memmap.map[i].addr + bfin_memmap.map[i].size);
 		switch (bfin_memmap.map[i].type) {
 		case BFIN_MEMMAP_RAM:
-				printk("(usable)\n");
-				break;
+			printk(KERN_CONT "(usable)\n");
+			break;
 		case BFIN_MEMMAP_RESERVED:
-				printk("(reserved)\n");
-				break;
-		default:	printk("type %lu\n", bfin_memmap.map[i].type);
-				break;
+			printk(KERN_CONT "(reserved)\n");
+			break;
+		default:
+			printk(KERN_CONT "type %lu\n", bfin_memmap.map[i].type);
+			break;
 		}
 	}
 }
@@ -434,9 +477,11 @@
 			} else if (!memcmp(to, "clkin_hz=", 9)) {
 				to += 9;
 				early_init_clkin_hz(to);
+#ifdef CONFIG_EARLY_PRINTK
 			} else if (!memcmp(to, "earlyprintk=", 12)) {
 				to += 12;
 				setup_early_printk(to);
+#endif
 			} else if (!memcmp(to, "memmap=", 7)) {
 				to += 7;
 				parse_memmap(to);
@@ -472,7 +517,7 @@
 
 	if (DMA_UNCACHED_REGION > (_ramend - _ramstart)) {
 		console_init();
-		panic("DMA region exceeds memory limit: %lu.\n",
+		panic("DMA region exceeds memory limit: %lu.",
 			_ramend - _ramstart);
 	}
 	memory_end = _ramend - DMA_UNCACHED_REGION;
@@ -507,7 +552,7 @@
 	    && ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1)
 		mtd_size =
 		    PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2]));
-#  if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263)
+#  if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
 	/* Due to a Hardware Anomaly we need to limit the size of usable
 	 * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
 	 * 05000263 - Hardware loop corrupted when taking an ICPLB exception
@@ -522,21 +567,26 @@
 #  endif				/* ANOMALY_05000263 */
 # endif				/* CONFIG_ROMFS_FS */
 
-	memory_end -= mtd_size;
+	/* Since the default MTD_UCLINUX has no magic number, we just blindly
+	 * read 8 past the end of the kernel's image, and look at it.
+	 * When no image is attached, mtd_size is set to a random number
+	 * Do some basic sanity checks before operating on things
+	 */
+	if (mtd_size == 0 || memory_end <= mtd_size) {
+		pr_emerg("Could not find valid ram mtd attached.\n");
+	} else {
+		memory_end -= mtd_size;
 
-	if (mtd_size == 0) {
-		console_init();
-		panic("Don't boot kernel without rootfs attached.\n");
+		/* Relocate MTD image to the top of memory after the uncached memory area */
+		uclinux_ram_map.phys = memory_mtd_start = memory_end;
+		uclinux_ram_map.size = mtd_size;
+		pr_info("Found mtd parition at 0x%p, (len=0x%lx), moving to 0x%p\n",
+			_end, mtd_size, (void *)memory_mtd_start);
+		dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size);
 	}
-
-	/* Relocate MTD image to the top of memory after the uncached memory area */
-	dma_memcpy((char *)memory_end, _end, mtd_size);
-
-	memory_mtd_start = memory_end;
-	_ebss = memory_mtd_start;	/* define _ebss for compatible */
 #endif				/* CONFIG_MTD_UCLINUX */
 
-#if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263)
+#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
 	/* Due to a Hardware Anomaly we need to limit the size of usable
 	 * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
 	 * 05000263 - Hardware loop corrupted when taking an ICPLB exception
@@ -570,19 +620,19 @@
 	printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
 
 	printk(KERN_INFO "Memory map:\n"
-		KERN_INFO "  fixedcode = 0x%p-0x%p\n"
-		KERN_INFO "  text      = 0x%p-0x%p\n"
-		KERN_INFO "  rodata    = 0x%p-0x%p\n"
-		KERN_INFO "  bss       = 0x%p-0x%p\n"
-		KERN_INFO "  data      = 0x%p-0x%p\n"
-		KERN_INFO "    stack   = 0x%p-0x%p\n"
-		KERN_INFO "  init      = 0x%p-0x%p\n"
-		KERN_INFO "  available = 0x%p-0x%p\n"
+	       "  fixedcode = 0x%p-0x%p\n"
+	       "  text      = 0x%p-0x%p\n"
+	       "  rodata    = 0x%p-0x%p\n"
+	       "  bss       = 0x%p-0x%p\n"
+	       "  data      = 0x%p-0x%p\n"
+	       "    stack   = 0x%p-0x%p\n"
+	       "  init      = 0x%p-0x%p\n"
+	       "  available = 0x%p-0x%p\n"
 #ifdef CONFIG_MTD_UCLINUX
-		KERN_INFO "  rootfs    = 0x%p-0x%p\n"
+	       "  rootfs    = 0x%p-0x%p\n"
 #endif
 #if DMA_UNCACHED_REGION > 0
-		KERN_INFO "  DMA Zone  = 0x%p-0x%p\n"
+	       "  DMA Zone  = 0x%p-0x%p\n"
 #endif
 		, (void *)FIXED_CODE_START, (void *)FIXED_CODE_END,
 		_stext, _etext,
@@ -756,6 +806,11 @@
 {
 	unsigned long sclk, cclk;
 
+	/* Check to make sure we are running on the right processor */
+	if (unlikely(CPUID != bfin_cpuid()))
+		printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
+			CPU, bfin_cpuid(), bfin_revid());
+
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
@@ -770,14 +825,17 @@
 	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
 
-	/* setup memory defaults from the user config */
-	physical_mem_end = 0;
-	_ramend = get_mem_size() * 1024 * 1024;
-
 	memset(&bfin_memmap, 0, sizeof(bfin_memmap));
 
+	/* If the user does not specify things on the command line, use
+	 * what the bootloader set things up as
+	 */
+	physical_mem_end = 0;
 	parse_cmdline_early(&command_line[0]);
 
+	if (_ramend == 0)
+		_ramend = get_mem_size() * 1024 * 1024;
+
 	if (physical_mem_end == 0)
 		physical_mem_end = _ramend;
 
@@ -796,10 +854,8 @@
 	cclk = get_cclk();
 	sclk = get_sclk();
 
-#if !defined(CONFIG_BFIN_KERNEL_CLOCK)
-	if (ANOMALY_05000273 && cclk == sclk)
-		panic("ANOMALY 05000273, SCLK can not be same as CCLK");
-#endif
+	if ((ANOMALY_05000273 || ANOMALY_05000274) && (cclk >> 1) < sclk)
+		panic("ANOMALY 05000273 or 05000274: CCLK must be >= 2*SCLK");
 
 #ifdef BF561_FAMILY
 	if (ANOMALY_05000266) {
@@ -809,20 +865,13 @@
 #endif
 	printk(KERN_INFO "Hardware Trace ");
 	if (bfin_read_TBUFCTL() & 0x1)
-		printk("Active ");
+		printk(KERN_CONT "Active ");
 	else
-		printk("Off ");
+		printk(KERN_CONT "Off ");
 	if (bfin_read_TBUFCTL() & 0x2)
-		printk("and Enabled\n");
+		printk(KERN_CONT "and Enabled\n");
 	else
-	printk("and Disabled\n");
-
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
-	/* we need to initialize the Flashrom device here since we might
-	 * do things with flash early on in the boot
-	 */
-	flash_probe();
-#endif
+		printk(KERN_CONT "and Disabled\n");
 
 	printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF);
 
@@ -831,7 +880,8 @@
     defined(CONFIG_BF538) || defined(CONFIG_BF539)
 	_bfin_swrst = bfin_read_SWRST();
 #else
-	_bfin_swrst = bfin_read_SYSCR();
+	/* Clear boot mode field */
+	_bfin_swrst = bfin_read_SYSCR() & ~0xf;
 #endif
 
 #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
@@ -869,10 +919,7 @@
 	else
 		printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
 
-	if (unlikely(CPUID != bfin_cpuid()))
-		printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
-			CPU, bfin_cpuid(), bfin_revid());
-	else {
+	if (likely(CPUID == bfin_cpuid())) {
 		if (bfin_revid() != bfin_compiled_revid()) {
 			if (bfin_compiled_revid() == -1)
 				printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n",
@@ -881,7 +928,7 @@
 				printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
 				       bfin_compiled_revid(), bfin_revid());
 				if (bfin_compiled_revid() > bfin_revid())
-					panic("Error: you are missing anomaly workarounds for this rev\n");
+					panic("Error: you are missing anomaly workarounds for this rev");
 			}
 		}
 		if (bfin_revid() < CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX)
@@ -889,18 +936,11 @@
 			       CPU, bfin_revid());
 	}
 
-	/* We can't run on BF548-0.1 due to ANOMALY 05000448 */
-	if (bfin_cpuid() == 0x27de && bfin_revid() == 1)
-		panic("You can't run on this processor due to 05000448\n");
-
 	printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
 
 	printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
 	       cclk / 1000000, sclk / 1000000);
 
-	if (ANOMALY_05000273 && (cclk >> 1) <= sclk)
-		printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n");
-
 	setup_bootmem_allocator();
 
 	paging_init();
@@ -1095,7 +1135,7 @@
 			CPUID, bfin_cpuid());
 
 	seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
-		"stepping\t: %d\n",
+		"stepping\t: %d ",
 		cpu, cclk/1000000, sclk/1000000,
 #ifdef CONFIG_MPU
 		"mpu on",
@@ -1104,14 +1144,23 @@
 #endif
 		revid);
 
-	seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
+	if (bfin_revid() != bfin_compiled_revid()) {
+		if (bfin_compiled_revid() == -1)
+			seq_printf(m, "(Compiled for Rev none)");
+		else if (bfin_compiled_revid() == 0xffff)
+			seq_printf(m, "(Compiled for Rev any)");
+		else
+			seq_printf(m, "(Compiled for Rev %d)", bfin_compiled_revid());
+	}
+
+	seq_printf(m, "\ncpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
 		cclk/1000000, cclk%1000000,
 		sclk/1000000, sclk%1000000);
 	seq_printf(m, "bogomips\t: %lu.%02lu\n"
 		"Calibration\t: %lu loops\n",
-		(cpudata->loops_per_jiffy * HZ) / 500000,
-		((cpudata->loops_per_jiffy * HZ) / 5000) % 100,
-		(cpudata->loops_per_jiffy * HZ));
+		(loops_per_jiffy * HZ) / 500000,
+		((loops_per_jiffy * HZ) / 5000) % 100,
+		(loops_per_jiffy * HZ));
 
 	/* Check Cache configutation */
 	switch (cpudata->dmemctl & (1 << DMC0_P | 1 << DMC1_P)) {
@@ -1145,16 +1194,25 @@
 		icache_size = 0;
 
 	seq_printf(m, "cache size\t: %d KB(L1 icache) "
-		"%d KB(L1 dcache%s) %d KB(L2 cache)\n",
-		icache_size, dcache_size,
-#if defined CONFIG_BFIN_WB
-		"-wb"
-#elif defined CONFIG_BFIN_WT
-		"-wt"
-#endif
-		"", 0);
-
+		"%d KB(L1 dcache) %d KB(L2 cache)\n",
+		icache_size, dcache_size, 0);
 	seq_printf(m, "%s\n", cache);
+	seq_printf(m, "external memory\t: "
+#if defined(CONFIG_BFIN_EXTMEM_ICACHEABLE)
+		   "cacheable"
+#else
+		   "uncacheable"
+#endif
+		   " in instruction cache\n");
+	seq_printf(m, "external memory\t: "
+#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK)
+		      "cacheable (write-back)"
+#elif defined(CONFIG_BFIN_EXTMEM_WRITETHROUGH)
+		      "cacheable (write-through)"
+#else
+		      "uncacheable"
+#endif
+		      " in data cache\n");
 
 	if (icache_size)
 		seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n",
@@ -1169,6 +1227,9 @@
 #ifdef __ARCH_SYNC_CORE_DCACHE
 	seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count);
 #endif
+#ifdef __ARCH_SYNC_CORE_ICACHE
+	seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count);
+#endif
 #ifdef CONFIG_BFIN_ICACHE_LOCK
 	switch ((cpudata->imemctl >> 3) & WAYALL_L) {
 	case WAY0_L:
@@ -1224,8 +1285,25 @@
 	if (cpu_num != num_possible_cpus() - 1)
 		return 0;
 
-	if (L2_LENGTH)
+	if (L2_LENGTH) {
 		seq_printf(m, "L2 SRAM\t\t: %dKB\n", L2_LENGTH/0x400);
+		seq_printf(m, "L2 SRAM\t\t: "
+#if defined(CONFIG_BFIN_L2_ICACHEABLE)
+			      "cacheable"
+#else
+			      "uncacheable"
+#endif
+			      " in instruction cache\n");
+		seq_printf(m, "L2 SRAM\t\t: "
+#if defined(CONFIG_BFIN_L2_WRITEBACK)
+			      "cacheable (write-back)"
+#elif defined(CONFIG_BFIN_L2_WRITETHROUGH)
+			      "cacheable (write-through)"
+#else
+			      "uncacheable"
+#endif
+			      " in data cache\n");
+	}
 	seq_printf(m, "board name\t: %s\n", bfin_board_name);
 	seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
 		 physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/stacktrace.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/stacktrace.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/stacktrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/stacktrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * Blackfin stacktrace code (mostly copied from avr32)
+ *
+ * Copyright 2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <linux/module.h>
+
+register unsigned long current_frame_pointer asm("FP");
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long rets;
+};
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+	unsigned long low, high;
+	unsigned long fp;
+	struct stackframe *frame;
+	int skip = trace->skip;
+
+	low = (unsigned long)task_stack_page(current);
+	high = low + THREAD_SIZE;
+	fp = current_frame_pointer;
+
+	while (fp >= low && fp <= (high - sizeof(*frame))) {
+		frame = (struct stackframe *)fp;
+
+		if (skip) {
+			skip--;
+		} else {
+			trace->entries[trace->nr_entries++] = frame->rets;
+			if (trace->nr_entries >= trace->max_entries)
+				break;
+		}
+
+		/*
+		 * The next frame must be at a higher address than the
+		 * current frame.
+		 */
+		low = fp + sizeof(*frame);
+		fp = frame->fp;
+	}
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/sys_bfin.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/sys_bfin.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/sys_bfin.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/sys_bfin.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,6 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
@@ -78,11 +77,6 @@
 	return do_mmap2(addr, len, prot, flags, fd, pgoff);
 }
 
-asmlinkage int sys_getpagesize(void)
-{
-	return PAGE_SIZE;
-}
-
 asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
 {
 	return sram_alloc_with_lsl(size, flags);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/time.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/time.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,14 +24,10 @@
 
 static struct irqaction bfin_timer_irq = {
 	.name = "Blackfin Timer Tick",
-#ifdef CONFIG_IRQ_PER_CPU
-	.flags = IRQF_DISABLED | IRQF_PERCPU,
-#else
 	.flags = IRQF_DISABLED
-#endif
 };
 
-#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+#if defined(CONFIG_IPIPE)
 void __init setup_system_timer0(void)
 {
 	/* Power down the core timer, just to play safe. */
@@ -74,7 +70,7 @@
 static void __init
 time_sched_init(irqreturn_t(*timer_routine) (int, void *))
 {
-#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+#if defined(CONFIG_IPIPE)
 	setup_system_timer0();
 	bfin_timer_irq.handler = timer_routine;
 	setup_irq(IRQ_TIMER0, &bfin_timer_irq);
@@ -94,7 +90,7 @@
 	unsigned long offset;
 	unsigned long clocks_per_jiffy;
 
-#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+#if defined(CONFIG_IPIPE)
 	clocks_per_jiffy = bfin_read_TIMER0_PERIOD();
 	offset = bfin_read_TIMER0_COUNTER() / \
 		(((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
@@ -133,36 +129,25 @@
 	static long last_rtc_update;
 
 	write_seqlock(&xtime_lock);
-#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
+	do_timer(1);
+
 	/*
-	 * TIMIL0 is latched in __ipipe_grab_irq() when the I-Pipe is
-	 * enabled.
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
 	 */
-	if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) {
-#endif
-		do_timer(1);
-
-		/*
-		 * If we have an externally synchronized Linux clock, then update
-		 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-		 * called as close as possible to 500 ms before the new second starts.
-		 */
-		if (ntp_synced() &&
-		    xtime.tv_sec > last_rtc_update + 660 &&
-		    (xtime.tv_nsec / NSEC_PER_USEC) >=
-		    500000 - ((unsigned)TICK_SIZE) / 2
-		    && (xtime.tv_nsec / NSEC_PER_USEC) <=
-		    500000 + ((unsigned)TICK_SIZE) / 2) {
-			if (set_rtc_mmss(xtime.tv_sec) == 0)
-				last_rtc_update = xtime.tv_sec;
-			else
-				/* Do it again in 60s. */
-				last_rtc_update = xtime.tv_sec - 600;
-		}
-#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
-		set_gptimer_status(0, TIMER_STATUS_TIMIL0);
+	if (ntp_synced() &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    (xtime.tv_nsec / NSEC_PER_USEC) >=
+	    500000 - ((unsigned)TICK_SIZE) / 2
+	    && (xtime.tv_nsec / NSEC_PER_USEC) <=
+	    500000 + ((unsigned)TICK_SIZE) / 2) {
+		if (set_rtc_mmss(xtime.tv_sec) == 0)
+			last_rtc_update = xtime.tv_sec;
+		else
+			/* Do it again in 60s. */
+			last_rtc_update = xtime.tv_sec - 600;
 	}
-#endif
 	write_sequnlock(&xtime_lock);
 
 #ifdef CONFIG_IPIPE
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/time-ts.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/time-ts.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/time-ts.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/time-ts.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,8 +20,9 @@
 
 #include <asm/blackfin.h>
 #include <asm/time.h>
+#include <asm/gptimers.h>
 
-#ifdef CONFIG_CYCLES_CLOCKSOURCE
+#if defined(CONFIG_CYCLES_CLOCKSOURCE)
 
 /* Accelerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
@@ -58,15 +59,15 @@
 	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
 }
 
-static cycle_t read_cycles(struct clocksource *cs)
+static cycle_t bfin_read_cycles(struct clocksource *cs)
 {
 	return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
 }
 
-static struct clocksource clocksource_bfin = {
-	.name		= "bfin_cycles",
+static struct clocksource bfin_cs_cycles = {
+	.name		= "bfin_cs_cycles",
 	.rating		= 350,
-	.read		= read_cycles,
+	.read		= bfin_read_cycles,
 	.mask		= CLOCKSOURCE_MASK(64),
 	.shift		= 22,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
@@ -74,53 +75,198 @@
 
 unsigned long long sched_clock(void)
 {
-	return cycles_2_ns(read_cycles(&clocksource_bfin));
+	return cycles_2_ns(bfin_read_cycles(&bfin_cs_cycles));
 }
 
-static int __init bfin_clocksource_init(void)
+static int __init bfin_cs_cycles_init(void)
 {
 	set_cyc2ns_scale(get_cclk() / 1000);
 
-	clocksource_bfin.mult = clocksource_hz2mult(get_cclk(), clocksource_bfin.shift);
+	bfin_cs_cycles.mult = \
+		clocksource_hz2mult(get_cclk(), bfin_cs_cycles.shift);
 
-	if (clocksource_register(&clocksource_bfin))
+	if (clocksource_register(&bfin_cs_cycles))
 		panic("failed to register clocksource");
 
 	return 0;
 }
+#else
+# define bfin_cs_cycles_init()
+#endif
+
+#ifdef CONFIG_GPTMR0_CLOCKSOURCE
+
+void __init setup_gptimer0(void)
+{
+	disable_gptimers(TIMER0bit);
+
+	set_gptimer_config(TIMER0_id, \
+		TIMER_OUT_DIS | TIMER_PERIOD_CNT | TIMER_MODE_PWM);
+	set_gptimer_period(TIMER0_id, -1);
+	set_gptimer_pwidth(TIMER0_id, -2);
+	SSYNC();
+	enable_gptimers(TIMER0bit);
+}
+
+static cycle_t bfin_read_gptimer0(void)
+{
+	return bfin_read_TIMER0_COUNTER();
+}
 
+static struct clocksource bfin_cs_gptimer0 = {
+	.name		= "bfin_cs_gptimer0",
+	.rating		= 400,
+	.read		= bfin_read_gptimer0,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift		= 22,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init bfin_cs_gptimer0_init(void)
+{
+	setup_gptimer0();
+
+	bfin_cs_gptimer0.mult = \
+		clocksource_hz2mult(get_sclk(), bfin_cs_gptimer0.shift);
+
+	if (clocksource_register(&bfin_cs_gptimer0))
+		panic("failed to register clocksource");
+
+	return 0;
+}
 #else
-# define bfin_clocksource_init()
+# define bfin_cs_gptimer0_init()
 #endif
 
+#ifdef CONFIG_CORE_TIMER_IRQ_L1
+__attribute__((l1_text))
+#endif
+irqreturn_t timer_interrupt(int irq, void *dev_id);
+
+static int bfin_timer_set_next_event(unsigned long, \
+		struct clock_event_device *);
+
+static void bfin_timer_set_mode(enum clock_event_mode, \
+		struct clock_event_device *);
+
+static struct clock_event_device clockevent_bfin = {
+#if defined(CONFIG_TICKSOURCE_GPTMR0)
+	.name		= "bfin_gptimer0",
+	.rating		= 300,
+	.irq		= IRQ_TIMER0,
+#else
+	.name		= "bfin_core_timer",
+	.rating		= 350,
+	.irq		= IRQ_CORETMR,
+#endif
+	.shift		= 32,
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_next_event = bfin_timer_set_next_event,
+	.set_mode	= bfin_timer_set_mode,
+};
+
+static struct irqaction bfin_timer_irq = {
+#if defined(CONFIG_TICKSOURCE_GPTMR0)
+	.name		= "Blackfin GPTimer0",
+#else
+	.name		= "Blackfin CoreTimer",
+#endif
+	.flags		= IRQF_DISABLED | IRQF_TIMER | \
+			  IRQF_IRQPOLL | IRQF_PERCPU,
+	.handler	= timer_interrupt,
+	.dev_id		= &clockevent_bfin,
+};
+
+#if defined(CONFIG_TICKSOURCE_GPTMR0)
 static int bfin_timer_set_next_event(unsigned long cycles,
                                      struct clock_event_device *evt)
 {
+	disable_gptimers(TIMER0bit);
+
+	/* it starts counting three SCLK cycles after the TIMENx bit is set */
+	set_gptimer_pwidth(TIMER0_id, cycles - 3);
+	enable_gptimers(TIMER0bit);
+	return 0;
+}
+
+static void bfin_timer_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC: {
+		set_gptimer_config(TIMER0_id, \
+			TIMER_OUT_DIS | TIMER_IRQ_ENA | \
+			TIMER_PERIOD_CNT | TIMER_MODE_PWM);
+		set_gptimer_period(TIMER0_id, get_sclk() / HZ);
+		set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1);
+		enable_gptimers(TIMER0bit);
+		break;
+	}
+	case CLOCK_EVT_MODE_ONESHOT:
+		disable_gptimers(TIMER0bit);
+		set_gptimer_config(TIMER0_id, \
+			TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM);
+		set_gptimer_period(TIMER0_id, 0);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		disable_gptimers(TIMER0bit);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static void bfin_timer_ack(void)
+{
+	set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0);
+}
+
+static void __init bfin_timer_init(void)
+{
+	disable_gptimers(TIMER0bit);
+}
+
+static unsigned long  __init bfin_clockevent_check(void)
+{
+	setup_irq(IRQ_TIMER0, &bfin_timer_irq);
+	return get_sclk();
+}
+
+#else /* CONFIG_TICKSOURCE_CORETMR */
+
+static int bfin_timer_set_next_event(unsigned long cycles,
+				struct clock_event_device *evt)
+{
+	bfin_write_TCNTL(TMPWR);
+	CSYNC();
 	bfin_write_TCOUNT(cycles);
 	CSYNC();
+	bfin_write_TCNTL(TMPWR | TMREN);
 	return 0;
 }
 
 static void bfin_timer_set_mode(enum clock_event_mode mode,
-                                struct clock_event_device *evt)
+				struct clock_event_device *evt)
 {
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC: {
 		unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
 		bfin_write_TCNTL(TMPWR);
-		bfin_write_TSCALE(TIME_SCALE - 1);
 		CSYNC();
+		bfin_write_TSCALE(TIME_SCALE - 1);
 		bfin_write_TPERIOD(tcount);
 		bfin_write_TCOUNT(tcount);
-		bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
 		CSYNC();
+		bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
 		break;
 	}
 	case CLOCK_EVT_MODE_ONESHOT:
+		bfin_write_TCNTL(TMPWR);
+		CSYNC();
 		bfin_write_TSCALE(TIME_SCALE - 1);
+		bfin_write_TPERIOD(0);
 		bfin_write_TCOUNT(0);
-		bfin_write_TCNTL(TMPWR | TMREN);
-		CSYNC();
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
@@ -132,6 +278,10 @@
 	}
 }
 
+static void bfin_timer_ack(void)
+{
+}
+
 static void __init bfin_timer_init(void)
 {
 	/* power up the timer, but don't enable it just yet */
@@ -145,38 +295,32 @@
 	bfin_write_TPERIOD(0);
 	bfin_write_TCOUNT(0);
 
-	/* now enable the timer */
 	CSYNC();
 }
 
+static unsigned long  __init bfin_clockevent_check(void)
+{
+	setup_irq(IRQ_CORETMR, &bfin_timer_irq);
+	return get_cclk() / TIME_SCALE;
+}
+
+void __init setup_core_timer(void)
+{
+	bfin_timer_init();
+	bfin_timer_set_mode(CLOCK_EVT_MODE_PERIODIC, NULL);
+}
+#endif /* CONFIG_TICKSOURCE_GPTMR0 */
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-#ifdef CONFIG_CORE_TIMER_IRQ_L1
-__attribute__((l1_text))
-#endif
-irqreturn_t timer_interrupt(int irq, void *dev_id);
-
-static struct clock_event_device clockevent_bfin = {
-	.name		= "bfin_core_timer",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
-	.set_next_event = bfin_timer_set_next_event,
-	.set_mode	= bfin_timer_set_mode,
-};
-
-static struct irqaction bfin_timer_irq = {
-	.name		= "Blackfin Core Timer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= timer_interrupt,
-	.dev_id		= &clockevent_bfin,
-};
-
 irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = dev_id;
+	smp_mb();
 	evt->event_handler(evt);
+	bfin_timer_ack();
 	return IRQ_HANDLED;
 }
 
@@ -184,9 +328,8 @@
 {
 	unsigned long timer_clk;
 
-	timer_clk = get_cclk() / TIME_SCALE;
+	timer_clk = bfin_clockevent_check();
 
-	setup_irq(IRQ_CORETMR, &bfin_timer_irq);
 	bfin_timer_init();
 
 	clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift);
@@ -218,6 +361,7 @@
 	xtime.tv_nsec = 0;
 	set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
 
-	bfin_clocksource_init();
+	bfin_cs_cycles_init();
+	bfin_cs_gptimer0_init();
 	bfin_clockevent_init();
 }
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/traps.c linux-libre-2.6.31-gnu/arch/blackfin/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/bug.h>
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -36,6 +37,7 @@
 #include <asm/traps.h>
 #include <asm/cacheflush.h>
 #include <asm/cplb.h>
+#include <asm/dma.h>
 #include <asm/blackfin.h>
 #include <asm/irq_handler.h>
 #include <linux/irq.h>
@@ -68,6 +70,13 @@
 	({ if (0) printk(fmt, ##arg); 0; })
 #endif
 
+#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE)
+u32 last_seqstat;
+#ifdef CONFIG_DEBUG_MMRS_MODULE
+EXPORT_SYMBOL(last_seqstat);
+#endif
+#endif
+
 /* Initiate the event table handler */
 void __init trap_init(void)
 {
@@ -79,7 +88,6 @@
 static void decode_address(char *buf, unsigned long address)
 {
 #ifdef CONFIG_DEBUG_VERBOSE
-	struct vm_list_struct *vml;
 	struct task_struct *p;
 	struct mm_struct *mm;
 	unsigned long flags, offset;
@@ -196,10 +204,15 @@
 
 asmlinkage void double_fault_c(struct pt_regs *fp)
 {
+#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
+	int j;
+	trace_buffer_save(j);
+#endif
+
 	console_verbose();
 	oops_in_progress = 1;
 #ifdef CONFIG_DEBUG_VERBOSE
-	printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
+	printk(KERN_EMERG "Double Fault\n");
 #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
 	if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
 		unsigned int cpu = smp_processor_id();
@@ -220,12 +233,18 @@
 		dump_bfin_process(fp);
 		dump_bfin_mem(fp);
 		show_regs(fp);
+		dump_bfin_trace_buffer();
 	}
 #endif
-	panic("Double Fault - unrecoverable event\n");
+	panic("Double Fault - unrecoverable event");
 
 }
 
+static int kernel_mode_regs(struct pt_regs *regs)
+{
+	return regs->ipend & 0xffc0;
+}
+
 asmlinkage void trap_c(struct pt_regs *fp)
 {
 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
@@ -234,37 +253,24 @@
 #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
 	unsigned int cpu = smp_processor_id();
 #endif
+	const char *strerror = NULL;
 	int sig = 0;
 	siginfo_t info;
 	unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
 
 	trace_buffer_save(j);
+#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE)
+	last_seqstat = (u32)fp->seqstat;
+#endif
 
 	/* Important - be very careful dereferncing pointers - will lead to
 	 * double faults if the stack has become corrupt
 	 */
 
-	/* If the fault was caused by a kernel thread, or interrupt handler
-	 * we will kernel panic, so the system reboots.
-	 * If KGDB is enabled, don't set this for kernel breakpoints
-	*/
-
-	/* TODO: check to see if we are in some sort of deferred HWERR
-	 * that we should be able to recover from, not kernel panic
-	 */
-	if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
-#ifdef CONFIG_KGDB
-		&& (trapnr != VEC_EXCPT02)
+#ifndef CONFIG_KGDB
+	/* IPEND is skipped if KGDB isn't enabled (see entry code) */
+	fp->ipend = bfin_read_IPEND();
 #endif
-	){
-		console_verbose();
-		oops_in_progress = 1;
-	} else if (current) {
-		if (current->mm == NULL) {
-			console_verbose();
-			oops_in_progress = 1;
-		}
-	}
 
 	/* trap_c() will be called for exceptions. During exceptions
 	 * processing, the pc value should be set with retx value.
@@ -292,15 +298,15 @@
 		sig = SIGTRAP;
 		CHK_DEBUGGER_TRAP_MAYBE();
 		/* Check if this is a breakpoint in kernel space */
-		if (fp->ipend & 0xffc0)
-			return;
+		if (kernel_mode_regs(fp))
+			goto traps_done;
 		else
 			break;
 	/* 0x03 - User Defined, userspace stack overflow */
 	case VEC_EXCPT03:
 		info.si_code = SEGV_STACKFLOW;
 		sig = SIGSEGV;
-		verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x02 - KGDB initial connection and break signal trap */
@@ -309,7 +315,7 @@
 		info.si_code = TRAP_ILLTRAP;
 		sig = SIGTRAP;
 		CHK_DEBUGGER_TRAP();
-		return;
+		goto traps_done;
 #endif
 	/* 0x04 - User Defined */
 	/* 0x05 - User Defined */
@@ -329,7 +335,7 @@
 	case VEC_EXCPT04 ... VEC_EXCPT15:
 		info.si_code = ILL_ILLPARAOP;
 		sig = SIGILL;
-		verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x10 HW Single step, handled here */
@@ -338,15 +344,15 @@
 		sig = SIGTRAP;
 		CHK_DEBUGGER_TRAP_MAYBE();
 		/* Check if this is a single step in kernel space */
-		if (fp->ipend & 0xffc0)
-			return;
+		if (kernel_mode_regs(fp))
+			goto traps_done;
 		else
 			break;
 	/* 0x11 - Trace Buffer Full, handled here */
 	case VEC_OVFLOW:
 		info.si_code = TRAP_TRACEFLOW;
 		sig = SIGTRAP;
-		verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x12 - Reserved, Caught by default */
@@ -366,37 +372,54 @@
 	/* 0x20 - Reserved, Caught by default */
 	/* 0x21 - Undefined Instruction, handled here */
 	case VEC_UNDEF_I:
+#ifdef CONFIG_BUG
+		if (kernel_mode_regs(fp)) {
+			switch (report_bug(fp->pc, fp)) {
+			case BUG_TRAP_TYPE_NONE:
+				break;
+			case BUG_TRAP_TYPE_WARN:
+				dump_bfin_trace_buffer();
+				fp->pc += 2;
+				goto traps_done;
+			case BUG_TRAP_TYPE_BUG:
+				/* call to panic() will dump trace, and it is
+				 * off at this point, so it won't be clobbered
+				 */
+				panic("BUG()");
+			}
+		}
+#endif
 		info.si_code = ILL_ILLOPC;
 		sig = SIGILL;
-		verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x22 - Illegal Instruction Combination, handled here */
 	case VEC_ILGAL_I:
 		info.si_code = ILL_ILLPARAOP;
 		sig = SIGILL;
-		verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x23 - Data CPLB protection violation, handled here */
 	case VEC_CPLB_VL:
 		info.si_code = ILL_CPLB_VI;
 		sig = SIGBUS;
-		verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x24 - Data access misaligned, handled here */
 	case VEC_MISALI_D:
 		info.si_code = BUS_ADRALN;
 		sig = SIGBUS;
-		verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x25 - Unrecoverable Event, handled here */
 	case VEC_UNCOV:
 		info.si_code = ILL_ILLEXCPT;
 		sig = SIGILL;
-		verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
@@ -404,7 +427,7 @@
 	case VEC_CPLB_M:
 		info.si_code = BUS_ADRALN;
 		sig = SIGBUS;
-		verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE);
 		break;
 	/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
 	case VEC_CPLB_MHIT:
@@ -412,10 +435,10 @@
 		sig = SIGSEGV;
 #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
 		if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
-			verbose_printk(KERN_NOTICE "NULL pointer access\n");
+			strerror = KERN_NOTICE "NULL pointer access\n";
 		else
 #endif
-			verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
+			strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x28 - Emulation Watchpoint, handled here */
@@ -425,8 +448,8 @@
 		pr_debug(EXC_0x28(KERN_DEBUG));
 		CHK_DEBUGGER_TRAP_MAYBE();
 		/* Check if this is a watchpoint in kernel space */
-		if (fp->ipend & 0xffc0)
-			return;
+		if (kernel_mode_regs(fp))
+			goto traps_done;
 		else
 			break;
 #ifdef CONFIG_BF535
@@ -434,7 +457,7 @@
 	case VEC_ISTRU_VL:      /* ADSP-BF535 only (MH) */
 		info.si_code = BUS_OPFETCH;
 		sig = SIGBUS;
-		verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
+		strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n";
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 #else
@@ -444,21 +467,21 @@
 	case VEC_MISALI_I:
 		info.si_code = BUS_ADRALN;
 		sig = SIGBUS;
-		verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x2B - Instruction CPLB protection violation, handled here */
 	case VEC_CPLB_I_VL:
 		info.si_code = ILL_CPLB_VI;
 		sig = SIGBUS;
-		verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
 	case VEC_CPLB_I_M:
 		info.si_code = ILL_CPLB_MISS;
 		sig = SIGBUS;
-		verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE);
 		break;
 	/* 0x2D - Instruction CPLB Multiple Hits, handled here */
 	case VEC_CPLB_I_MHIT:
@@ -466,17 +489,17 @@
 		sig = SIGSEGV;
 #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
 		if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
-			verbose_printk(KERN_NOTICE "Jump to NULL address\n");
+			strerror = KERN_NOTICE "Jump to NULL address\n";
 		else
 #endif
-			verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
+			strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x2E - Illegal use of Supervisor Resource, handled here */
 	case VEC_ILL_RES:
 		info.si_code = ILL_PRVOPC;
 		sig = SIGILL;
-		verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
+		strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE);
 		CHK_DEBUGGER_TRAP_MAYBE();
 		break;
 	/* 0x2F - Reserved, Caught by default */
@@ -504,17 +527,17 @@
 		case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
 			info.si_code = BUS_ADRALN;
 			sig = SIGBUS;
-			verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
+			strerror = KERN_NOTICE HWC_x2(KERN_NOTICE);
 			break;
 		/* External Memory Addressing Error */
 		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
 			info.si_code = BUS_ADRERR;
 			sig = SIGBUS;
-			verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
+			strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
 			break;
 		/* Performance Monitor Overflow */
 		case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
-			verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
+			strerror = KERN_NOTICE HWC_x12(KERN_NOTICE);
 			break;
 		/* RAISE 5 instruction */
 		case (SEQSTAT_HWERRCAUSE_RAISE_5):
@@ -531,7 +554,6 @@
 	 * if we get here we hit a reserved one, so panic
 	 */
 	default:
-		oops_in_progress = 1;
 		info.si_code = ILL_ILLPARAOP;
 		sig = SIGILL;
 		verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
@@ -542,7 +564,18 @@
 
 	BUG_ON(sig == 0);
 
+	/* If the fault was caused by a kernel thread, or interrupt handler
+	 * we will kernel panic, so the system reboots.
+	 */
+	if (kernel_mode_regs(fp) || (current && !current->mm)) {
+		console_verbose();
+		oops_in_progress = 1;
+	}
+
 	if (sig != SIGTRAP) {
+		if (strerror)
+			verbose_printk(strerror);
+
 		dump_bfin_process(fp);
 		dump_bfin_mem(fp);
 		show_regs(fp);
@@ -551,15 +584,14 @@
 #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
 		if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
 			verbose_printk(KERN_NOTICE "No trace since you do not have "
-				"CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
-				KERN_NOTICE "\n");
+			       "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n");
 		else
 #endif
 			dump_bfin_trace_buffer();
 
 		if (oops_in_progress) {
 			/* Dump the current kernel stack */
-			verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
+			verbose_printk(KERN_NOTICE "Kernel Stack\n");
 			show_stack(current, NULL);
 			print_modules();
 #ifndef CONFIG_ACCESS_CHECK
@@ -588,8 +620,13 @@
 		force_sig_info(sig, &info, current);
 	}
 
+	if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) ||
+	    (ANOMALY_05000281 && trapnr == VEC_HWERR) ||
+	    (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL)))
+		fp->pc = SAFE_USER_INSTRUCTION;
+
+ traps_done:
 	trace_buffer_restore(j);
-	return;
 }
 
 /* Typical exception handling routines	*/
@@ -602,57 +639,30 @@
  */
 static bool get_instruction(unsigned short *val, unsigned short *address)
 {
-
-	unsigned long addr;
-
-	addr = (unsigned long)address;
+	unsigned long addr = (unsigned long)address;
 
 	/* Check for odd addresses */
 	if (addr & 0x1)
 		return false;
 
-	/* Check that things do not wrap around */
-	if (addr > (addr + 2))
+	/* MMR region will never have instructions */
+	if (addr >= SYSMMR_BASE)
 		return false;
 
-	/*
-	 * Since we are in exception context, we need to do a little address checking
-	 * We need to make sure we are only accessing valid memory, and
-	 * we don't read something in the async space that can hang forever
-	 */
-	if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) ||
-#if L2_LENGTH != 0
-	    (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) ||
-#endif
-	    (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) ||
-#if L1_DATA_A_LENGTH != 0
-	    (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) ||
-#endif
-#if L1_DATA_B_LENGTH != 0
-	    (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
-#endif
-	    (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
-	    (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
-	       addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
-	    (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
-	       addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
-	    (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
-	       addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
-	    (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
-	      addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
-		*val = *address;
-		return true;
-	}
-
-#if L1_CODE_LENGTH != 0
-	if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
-		isram_memcpy(val, address, 2);
-		return true;
+	switch (bfin_mem_access_type(addr, 2)) {
+		case BFIN_MEM_ACCESS_CORE:
+		case BFIN_MEM_ACCESS_CORE_ONLY:
+			*val = *address;
+			return true;
+		case BFIN_MEM_ACCESS_DMA:
+			dma_memcpy(val, address, 2);
+			return true;
+		case BFIN_MEM_ACCESS_ITEST:
+			isram_memcpy(val, address, 2);
+			return true;
+		default: /* invalid access */
+			return false;
 	}
-#endif
-
-
-	return false;
 }
 
 /*
@@ -774,6 +784,18 @@
 }
 EXPORT_SYMBOL(dump_bfin_trace_buffer);
 
+#ifdef CONFIG_BUG
+int is_valid_bugaddr(unsigned long addr)
+{
+	unsigned short opcode;
+
+	if (!get_instruction(&opcode, (unsigned short *)addr))
+		return 0;
+
+	return opcode == BFIN_BUG_OPCODE;
+}
+#endif
+
 /*
  * Checks to see if the address pointed to is either a
  * 16-bit CALL instruction, or a 32-bit CALL instruction
@@ -832,6 +854,11 @@
 	decode_address(buf, (unsigned int)stack);
 	printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
 
+	if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) {
+		printk(KERN_NOTICE "Invalid stack pointer\n");
+		return;
+	}
+
 	/* First thing is to look for a frame pointer */
 	for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
 		if (*addr & 0x1)
@@ -881,7 +908,7 @@
 
 			ret_addr = 0;
 			if (!j && i % 8 == 0)
-				printk("\n" KERN_NOTICE "%p:",addr);
+				printk(KERN_NOTICE "%p:",addr);
 
 			/* if it is an odd address, or zero, just skip it */
 			if (*addr & 0x1 || !*addr)
@@ -971,9 +998,9 @@
 
 		printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
 		if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
-			verbose_printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
-				KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
-				KERN_NOTICE "\n",
+			verbose_printk(KERN_NOTICE
+				"TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
+				" BSS = 0x%p-0x%p  USER-STACK = 0x%p\n\n",
 				(void *)current->mm->start_code,
 				(void *)current->mm->end_code,
 				(void *)current->mm->start_data,
@@ -984,8 +1011,8 @@
 		else
 			verbose_printk(KERN_NOTICE "invalid mm\n");
 	} else
-		verbose_printk(KERN_NOTICE "\n" KERN_NOTICE
-		     "No Valid process in current context\n");
+		verbose_printk(KERN_NOTICE
+			       "No Valid process in current context\n");
 #endif
 }
 
@@ -1003,7 +1030,7 @@
 	     addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
 	     addr++) {
 		if (!((unsigned long)addr & 0xF))
-			verbose_printk("\n" KERN_NOTICE "0x%p: ", addr);
+			verbose_printk(KERN_NOTICE "0x%p: ", addr);
 
 		if (!get_instruction(&val, addr)) {
 				val = 0;
@@ -1031,9 +1058,9 @@
 	    oops_in_progress)){
 		verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
 #ifndef CONFIG_DEBUG_HWERR
-		verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n"
-			KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
-			 " better idea where it came from\n");
+		verbose_printk(KERN_NOTICE
+"The remaining message may be meaningless\n"
+"You should enable CONFIG_DEBUG_HWERR to get a better idea where it came from\n");
 #else
 		/* If we are handling only one peripheral interrupt
 		 * and current mm and pid are valid, and the last error
@@ -1066,9 +1093,33 @@
 	unsigned int cpu = smp_processor_id();
 	unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
 
-	verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
+	verbose_printk(KERN_NOTICE "\n");
+	if (CPUID != bfin_cpuid())
+		verbose_printk(KERN_NOTICE "Compiled for cpu family 0x%04x (Rev %d), "
+			"but running on:0x%04x (Rev %d)\n",
+			CPUID, bfin_compiled_revid(), bfin_cpuid(), bfin_revid());
+
+	verbose_printk(KERN_NOTICE "ADSP-%s-0.%d",
+		CPU, bfin_compiled_revid());
+
+	if (bfin_compiled_revid() !=  bfin_revid())
+		verbose_printk("(Detected 0.%d)", bfin_revid());
+
+	verbose_printk(" %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n",
+		get_cclk()/1000000, get_sclk()/1000000,
+#ifdef CONFIG_MPU
+		"mpu on"
+#else
+		"mpu off"
+#endif
+		);
+
+	verbose_printk(KERN_NOTICE "%s", linux_banner);
+
+	verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n",
+		       print_tainted());
 	verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
-		(long)fp->seqstat, fp->ipend, fp->syscfg);
+		       (long)fp->seqstat, fp->ipend, fp->syscfg);
 	if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
 		verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
 			(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
@@ -1136,7 +1187,7 @@
 		verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
 	}
 
-	verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
+	verbose_printk(KERN_NOTICE "PROCESSOR STATE:\n");
 	verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
 		fp->r0, fp->r1, fp->r2, fp->r3);
 	verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
@@ -1246,5 +1297,5 @@
 	dump_bfin_mem(fp);
 	show_regs(fp);
 	dump_stack();
-	panic("Unrecoverable event\n");
+	panic("Unrecoverable event");
 }
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/kernel/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/blackfin/kernel/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/blackfin/kernel/vmlinux.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/kernel/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -50,8 +50,11 @@
 		_text = .;
 		__stext = .;
 		TEXT_TEXT
+#ifndef CONFIG_SCHEDULE_L1
 		SCHED_TEXT
+#endif
 		LOCK_TEXT
+		IRQENTRY_TEXT
 		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
@@ -164,6 +167,20 @@
 	}
 	PERCPU(4)
 	SECURITY_INIT
+
+	/* we have to discard exit text and such at runtime, not link time, to
+	 * handle embedded cross-section references (alt instructions, bug
+	 * table, eh_frame, etc...)
+	 */
+	.exit.text :
+	{
+		EXIT_TEXT
+	}
+	.exit.data :
+	{
+		EXIT_DATA
+	}
+
 	.init.ramfs :
 	{
 		. = ALIGN(4);
@@ -180,6 +197,9 @@
 		. = ALIGN(4);
 		__stext_l1 = .;
 		*(.l1.text)
+#ifdef CONFIG_SCHEDULE_L1
+		SCHED_TEXT
+#endif
 		. = ALIGN(4);
 		__etext_l1 = .;
 	}
@@ -259,8 +279,6 @@
 
 	/DISCARD/ :
 	{
-		EXIT_TEXT
-		EXIT_DATA
 		*(.exitcall.exit)
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/lib/checksum.c linux-libre-2.6.31-gnu/arch/blackfin/lib/checksum.c
--- linux-libre-2.6.30-gnu/arch/blackfin/lib/checksum.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/lib/checksum.c	2009-09-09 18:13:59.000000000 -0400
@@ -116,6 +116,7 @@
 {
 	return (__force __sum16)~do_csum(buff, len);
 }
+EXPORT_SYMBOL(ip_compute_csum);
 
 /*
  * copy from fs while checksumming, otherwise like csum_partial
@@ -130,6 +131,7 @@
 	memcpy(dst, (__force void *)src, len);
 	return csum_partial(dst, len, sum);
 }
+EXPORT_SYMBOL(csum_partial_copy_from_user);
 
 /*
  * copy from ds while checksumming, otherwise like csum_partial
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/lib/lshrdi3.c linux-libre-2.6.31-gnu/arch/blackfin/lib/lshrdi3.c
--- linux-libre-2.6.30-gnu/arch/blackfin/lib/lshrdi3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/lib/lshrdi3.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,21 +27,7 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#define BITS_PER_UNIT 8
-
-typedef int SItype __attribute__ ((mode(SI)));
-typedef unsigned int USItype __attribute__ ((mode(SI)));
-typedef int DItype __attribute__ ((mode(DI)));
-typedef int word_type __attribute__ ((mode(__word__)));
-
-struct DIstruct {
-	SItype high, low;
-};
-
-typedef union {
-	struct DIstruct s;
-	DItype ll;
-} DIunion;
+#include "gcclib.h"
 
 #ifdef CONFIG_ARITHMETIC_OPS_L1
 DItype __lshrdi3(DItype u, word_type b)__attribute__((l1_text));
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/boards/ezbrd.c	2009-09-09 18:13:59.000000000 -0400
@@ -82,7 +82,11 @@
 
 static struct resource ezbrd_flash_resource = {
 	.start = 0x20000000,
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+	.end   = 0x202fffff,
+#else
 	.end   = 0x203fffff,
+#endif
 	.flags = IORESOURCE_MEM,
 };
 
@@ -115,13 +119,19 @@
 };
 
 #if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
-static struct dsa_platform_data ksz8893m_switch_data = {
+static struct dsa_chip_data ksz8893m_switch_chip_data = {
 	.mii_bus = &bfin_mii_bus.dev,
+	.port_names = {
+		NULL,
+		"eth%d",
+		"eth%d",
+		"cpu",
+	},
+};
+static struct dsa_platform_data ksz8893m_switch_data = {
+	.nr_chips = 1,
 	.netdev = &bfin_mac_device.dev,
-	.port_names[0]	= NULL,
-	.port_names[1]	= "eth%d",
-	.port_names[2]	= "eth%d",
-	.port_names[3]	= "cpu",
+	.chip = &ksz8893m_switch_chip_data,
 };
 
 static struct platform_device ksz8893m_switch_device = {
@@ -162,8 +172,8 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -242,15 +252,15 @@
 		.modalias = "m25p80", /* Name of spi_driver for this device */
 		.max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
 		.bus_num = 0, /* Framework bus number */
-		.chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+		.chip_select = 2, /* On BF518F-EZBRD it's SPI0_SSEL2 */
 		.platform_data = &bfin_spi_flash_data,
 		.controller_data = &spi_flash_chip_info,
 		.mode = SPI_MODE_3,
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -365,6 +375,11 @@
 	[1] = {
 		.start = CH_SPI0,
 		.end   = CH_SPI0,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI0,
+		.end   = IRQ_SPI0,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -395,6 +410,11 @@
 	[1] = {
 		.start = CH_SPI1,
 		.end   = CH_SPI1,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI1,
+		.end   = IRQ_SPI1,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -514,7 +534,7 @@
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
 	},
@@ -678,6 +698,11 @@
 				ARRAY_SIZE(bfin_i2c_board_info));
 	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+	/* setup BF518-EZBRD GPIO pin PG11 to AMS2, PG15 to AMS3. */
+	peripheral_request(P_AMS2, "ParaFlash");
+#if !defined(CONFIG_SPI_BFIN) && !defined(CONFIG_SPI_BFIN_MODULE)
+	peripheral_request(P_AMS3, "ParaFlash");
+#endif
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/anomaly.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/anomaly.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/anomaly.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/anomaly.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,10 +6,15 @@
  * Licensed under the GPL-2 or later.
  */
 
-/* This file shoule be up to date with:
- *  - Revision B, 02/03/2009; ADSP-BF512/BF514/BF516/BF518 Blackfin Processor Anomaly List
+/* This file should be up to date with:
+ *  - Revision C, 06/12/2009; ADSP-BF512/BF514/BF516/BF518 Blackfin Processor Anomaly List
  */
 
+/* We plan on not supporting 0.0 silicon, but 0.1 isn't out yet - sorry */
+#if __SILICON_REVISION__ < 0
+# error will not work on BF518 silicon version
+#endif
+
 #ifndef _MACH_ANOMALY_H_
 #define _MACH_ANOMALY_H_
 
@@ -40,53 +45,92 @@
 /* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
 #define ANOMALY_05000426 (1)
 /* Software System Reset Corrupts PLL_LOCKCNT Register */
-#define ANOMALY_05000430 (1)
+#define ANOMALY_05000430 (__SILICON_REVISION__ < 1)
 /* Incorrect Use of Stack in Lockbox Firmware During Authentication */
 #define ANOMALY_05000431 (1)
 /* Certain SIC Registers are not Reset After Soft or Core Double Fault Reset */
-#define ANOMALY_05000435 (1)
+#define ANOMALY_05000435 (__SILICON_REVISION__ < 1)
 /* PORTx_DRIVE and PORTx_HYSTERESIS Registers Read Back Incorrect Values */
-#define ANOMALY_05000438 (1)
-/* Preboot Cannot be Used to Program the PLL_DIV Register */
-#define ANOMALY_05000439 (1)
+#define ANOMALY_05000438 (__SILICON_REVISION__ < 1)
+/* Preboot Cannot be Used to Alter the PLL_DIV Register */
+#define ANOMALY_05000439 (__SILICON_REVISION__ < 1)
 /* bfrom_SysControl() Cannot be Used to Write the PLL_DIV Register */
-#define ANOMALY_05000440 (1)
+#define ANOMALY_05000440 (__SILICON_REVISION__ < 1)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
 /* Incorrect L1 Instruction Bank B Memory Map Location */
-#define ANOMALY_05000444 (1)
+#define ANOMALY_05000444 (__SILICON_REVISION__ < 1)
 /* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
-#define ANOMALY_05000452 (1)
+#define ANOMALY_05000452 (__SILICON_REVISION__ < 1)
 /* PWM_TRIPB Signal Not Available on PG10 */
-#define ANOMALY_05000453 (1)
+#define ANOMALY_05000453 (__SILICON_REVISION__ < 1)
 /* PPI_FS3 is Driven One Half Cycle Later Than PPI Data */
-#define ANOMALY_05000455 (1)
+#define ANOMALY_05000455 (__SILICON_REVISION__ < 1)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
+/* Synchronization Problem at Startup May Cause SPORT Transmit Channels to Misalign */
+#define ANOMALY_05000462 (1)
 
 /* Anomalies that don't exist on this proc */
+#define ANOMALY_05000099 (0)
+#define ANOMALY_05000119 (0)
+#define ANOMALY_05000120 (0)
 #define ANOMALY_05000125 (0)
+#define ANOMALY_05000149 (0)
 #define ANOMALY_05000158 (0)
+#define ANOMALY_05000171 (0)
+#define ANOMALY_05000179 (0)
+#define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
+#define ANOMALY_05000202 (0)
+#define ANOMALY_05000215 (0)
+#define ANOMALY_05000220 (0)
+#define ANOMALY_05000227 (0)
 #define ANOMALY_05000230 (0)
+#define ANOMALY_05000231 (0)
+#define ANOMALY_05000233 (0)
+#define ANOMALY_05000234 (0)
+#define ANOMALY_05000242 (0)
 #define ANOMALY_05000244 (0)
+#define ANOMALY_05000248 (0)
+#define ANOMALY_05000250 (0)
+#define ANOMALY_05000257 (0)
 #define ANOMALY_05000261 (0)
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000274 (0)
 #define ANOMALY_05000278 (0)
+#define ANOMALY_05000281 (0)
+#define ANOMALY_05000283 (0)
 #define ANOMALY_05000285 (0)
+#define ANOMALY_05000287 (0)
+#define ANOMALY_05000301 (0)
 #define ANOMALY_05000305 (0)
 #define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000312 (0)
+#define ANOMALY_05000315 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (0)
+#define ANOMALY_05000357 (0)
+#define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
+#define ANOMALY_05000371 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (0)
+#define ANOMALY_05000389 (0)
+#define ANOMALY_05000400 (0)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
+#define ANOMALY_05000456 (0)
+#define ANOMALY_05000450 (0)
+#define ANOMALY_05000465 (0)
+#define ANOMALY_05000467 (0)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,6 @@
 #define _MACH_BLACKFIN_H_
 
 #include "bf518.h"
-#include "mem_map.h"
 #include "defBF512.h"
 #include "anomaly.h"
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,38 +1,16 @@
 /*
- * file:         include/asm-blackfin/mach-bf518/mem_map.h
- * based on:	include/asm-blackfin/mach-bf527/mem_map.h
- * author:	Bryan Wu <cooloney@kernel.org>
- *
- * created:
- * description:
- *	Memory MAP Common header file for blackfin BF518/6/4/2 of processors.
- * rev:
- *
- * modified:
- *
- * bugs:         enter bugs at http://blackfin.uclinux.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, 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.
+ * BF51x memory map
  *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_518_H_
-#define _MEM_MAP_518_H_
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
 
-#define COREMMR_BASE           0xFFE00000	/* Core MMRs */
-#define SYSMMR_BASE            0xFFC00000	/* System MMRs */
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
 
 /* Async Memory Banks */
 #define ASYNC_BANK3_BASE	0x20300000	/* Async Bank 3 */
@@ -89,20 +67,4 @@
 #define BFIN_DSUPBANKS		0
 #endif				/*CONFIG_BFIN_DCACHE */
 
-/* Level 2 Memory - none */
-
-#define L2_START	0
-#define L2_LENGTH	0
-
-/* Scratch Pad Memory */
-
-#define L1_SCRATCH_START	0xFFB00000
-#define L1_SCRATCH_LENGTH	0x1000
-
-#define GET_PDA_SAFE(preg)		\
-	preg.l = _cpu_pda;		\
-	preg.h = _cpu_pda;
-
-#define GET_PDA(preg, dreg)	GET_PDA_SAFE(preg)
-
-#endif				/* _MEM_MAP_518_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/portmux.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/portmux.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/include/mach/portmux.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/include/mach/portmux.h	2009-09-09 18:13:59.000000000 -0400
@@ -185,6 +185,10 @@
 #define P_PTP_PPS		(P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(2))
 #define P_PTP_CLKOUT		(P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(2))
 
-#define P_HWAIT		(P_DEFINED | P_IDENT(GPIO_PG000000000) | P_FUNCT(1))
+/* AMS */
+#define P_AMS2			(P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_AMS3			(P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(2))
+
+#define P_HWAIT			(P_DEFINED | P_IDENT(GPIO_PG000000000) | P_FUNCT(1))
 
 #endif				/* _MACH_PORTMUX_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf518/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf518/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -156,6 +156,7 @@
 	default 11
 config IRQ_TIMER0
 	int "IRQ_TIMER0"
+	default 7 if TICKSOURCE_GPTMR0
 	default 8
 config IRQ_TIMER1
 	int "IRQ_TIMER1"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/boards/cm_bf527.c	2009-09-09 18:13:59.000000000 -0400
@@ -78,7 +78,6 @@
 
 static struct isp1760_platform_data isp1760_priv = {
 	.is_isp1761 = 0,
-	.port1_disable = 0,
 	.bus_width_16 = 1,
 	.port1_otg = 0,
 	.analog_oc = 0,
@@ -463,8 +462,8 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -554,8 +553,8 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -664,6 +663,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -789,7 +793,7 @@
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
 		.type = "pcf8574_lcd",
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/boards/ezbrd.c	2009-09-09 18:13:59.000000000 -0400
@@ -237,18 +237,18 @@
 	.name = "m25p80",
 	.parts = bfin_spi_flash_partitions,
 	.nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
-	.type = "m25p16",
+	.type = "sst25wf040",
 };
 
-/* SPI flash chip (m25p64) */
+/* SPI flash chip (sst25wf040) */
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
 	.enable_dma = 0,         /* use dma transfer with this chip*/
 	.bits_per_word = 8,
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -354,8 +354,8 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -467,6 +467,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -586,7 +591,7 @@
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
 	},
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/boards/ezkit.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/boards/ezkit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/boards/ezkit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/boards/ezkit.c	2009-09-09 18:13:59.000000000 -0400
@@ -77,7 +77,6 @@
 
 static struct isp1760_platform_data isp1760_priv = {
 	.is_isp1761 = 0,
-	.port1_disable = 0,
 	.bus_width_16 = 1,
 	.port1_otg = 0,
 	.analog_oc = 0,
@@ -485,8 +484,8 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -509,6 +508,13 @@
 };
 #endif
 
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip  mmc_spi_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
 #if defined(CONFIG_PBX)
 static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
 	.ctl_reg	= 0x4, /* send zero */
@@ -593,8 +599,8 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -624,6 +630,17 @@
 		.controller_data = &ad9960_spi_chip_info,
 	},
 #endif
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+	{
+		.modalias = "mmc_spi",
+		.max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 3,
+		.controller_data = &mmc_spi_chip_info,
+		.mode = SPI_MODE_0,
+	},
+#endif
+
 #if defined(CONFIG_PBX)
 	{
 		.modalias = "fxs-spi",
@@ -705,6 +722,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -836,7 +858,7 @@
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
 	},
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/anomaly.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/anomaly.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/anomaly.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/anomaly.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,14 +6,19 @@
  * Licensed under the GPL-2 or later.
  */
 
-/* This file shoule be up to date with:
- *  - Revision B, 08/12/2008; ADSP-BF526 Blackfin Processor Anomaly List
- *  - Revision E, 08/18/2008; ADSP-BF527 Blackfin Processor Anomaly List
+/* This file should be up to date with:
+ *  - Revision C, 03/13/2009; ADSP-BF526 Blackfin Processor Anomaly List
+ *  - Revision F, 03/03/2009; ADSP-BF527 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 #define _MACH_ANOMALY_H_
 
+/* We do not support old silicon - sorry */
+#if __SILICON_REVISION__ < 0
+# error will not work on BF526/BF527 silicon version
+#endif
+
 #if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
 # define ANOMALY_BF526 1
 #else
@@ -25,156 +30,214 @@
 # define ANOMALY_BF527 0
 #endif
 
+#define _ANOMALY_BF526(rev526) (ANOMALY_BF526 && __SILICON_REVISION__ rev526)
+#define _ANOMALY_BF527(rev527) (ANOMALY_BF527 && __SILICON_REVISION__ rev527)
+#define _ANOMALY_BF526_BF527(rev526, rev527) (_ANOMALY_BF526(rev526) || _ANOMALY_BF527(rev527))
+
 /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
 /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
 #define ANOMALY_05000119 (1)	/* note: brokenness is noted in documentation, not anomaly sheet */
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
-/* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
+/* Incorrect Timer Pulse Width in Single-Shot PWM_OUT Mode with External Clock */
+#define ANOMALY_05000254 (1)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
 /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
 #define ANOMALY_05000310 (1)
 /* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */
-#define ANOMALY_05000313 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000313 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Incorrect Access of OTP_STATUS During otp_write() Function */
-#define ANOMALY_05000328 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000328 (_ANOMALY_BF527(< 2))
+/* Host DMA Boot Modes Are Not Functional */
+#define ANOMALY_05000330 (__SILICON_REVISION__ < 2)
 /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
-#define ANOMALY_05000337 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000337 (_ANOMALY_BF527(< 2))
 /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
-#define ANOMALY_05000341 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000341 (_ANOMALY_BF527(< 2))
 /* TWI May Not Operate Correctly Under Certain Signal Termination Conditions */
-#define ANOMALY_05000342 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000342 (_ANOMALY_BF527(< 2))
 /* USB Calibration Value Is Not Initialized */
-#define ANOMALY_05000346 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000346 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* USB Calibration Value to use */
 #define ANOMALY_05000346_value 0xE510
 /* Preboot Routine Incorrectly Alters Reset Value of USB Register */
-#define ANOMALY_05000347 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000347 (_ANOMALY_BF527(< 2))
 /* Security Features Are Not Functional */
-#define ANOMALY_05000348 (ANOMALY_BF527 && __SILICON_REVISION__ < 1)
+#define ANOMALY_05000348 (_ANOMALY_BF527(< 1))
 /* bfrom_SysControl() Firmware Function Performs Improper System Reset */
-#define ANOMALY_05000353 (ANOMALY_BF526)
+#define ANOMALY_05000353 (_ANOMALY_BF526(< 1))
 /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
-#define ANOMALY_05000355 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000355 (_ANOMALY_BF527(< 2))
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
-#define ANOMALY_05000357 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000357 (_ANOMALY_BF527(< 2))
 /* Incorrect Revision Number in DSPID Register */
-#define ANOMALY_05000364 (ANOMALY_BF527 && __SILICON_REVISION__ == 1)
+#define ANOMALY_05000364 (_ANOMALY_BF527(== 1))
 /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
 #define ANOMALY_05000366 (1)
 /* Incorrect Default CSEL Value in PLL_DIV */
-#define ANOMALY_05000368 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000368 (_ANOMALY_BF527(< 2))
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
-#define ANOMALY_05000371 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000371 (_ANOMALY_BF527(< 2))
 /* Authentication Fails To Initiate */
-#define ANOMALY_05000376 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000376 (_ANOMALY_BF527(< 2))
 /* Data Read From L3 Memory by USB DMA May be Corrupted */
-#define ANOMALY_05000380 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000380 (_ANOMALY_BF527(< 2))
 /* 8-Bit NAND Flash Boot Mode Not Functional */
-#define ANOMALY_05000382 (__SILICON_REVISION__ < 2)
-/* Host Must Not Read Back During Host DMA Boot */
-#define ANOMALY_05000384 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000382 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Boot from OTP Memory Not Functional */
-#define ANOMALY_05000385 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000385 (_ANOMALY_BF527(< 2))
 /* bfrom_SysControl() Firmware Routine Not Functional */
-#define ANOMALY_05000386 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000386 (_ANOMALY_BF527(< 2))
 /* Programmable Preboot Settings Not Functional */
-#define ANOMALY_05000387 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000387 (_ANOMALY_BF527(< 2))
 /* CRC32 Checksum Support Not Functional */
-#define ANOMALY_05000388 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000388 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Reset Vector Must Not Be in SDRAM Memory Space */
-#define ANOMALY_05000389 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000389 (_ANOMALY_BF527(< 2))
 /* pTempCurrent Not Present in ADI_BOOT_DATA Structure */
-#define ANOMALY_05000392 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000392 (_ANOMALY_BF527(< 2))
 /* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */
-#define ANOMALY_05000393 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000393 (_ANOMALY_BF527(< 2))
 /* Log Buffer Not Functional */
-#define ANOMALY_05000394 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000394 (_ANOMALY_BF527(< 2))
 /* Hook Routine Not Functional */
-#define ANOMALY_05000395 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000395 (_ANOMALY_BF527(< 2))
 /* Header Indirect Bit Not Functional */
-#define ANOMALY_05000396 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000396 (_ANOMALY_BF527(< 2))
 /* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */
-#define ANOMALY_05000397 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000397 (_ANOMALY_BF527(< 2))
 /* SWRESET, DFRESET and WDRESET Bits in the SYSCR Register Not Functional */
-#define ANOMALY_05000398 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000398 (_ANOMALY_BF527(< 2))
 /* BCODE_NOBOOT in BCODE Field of SYSCR Register Not Functional */
-#define ANOMALY_05000399 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000399 (_ANOMALY_BF527(< 2))
 /* PPI Data Signals D0 and D8 do not Tristate After Disabling PPI */
-#define ANOMALY_05000401 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000401 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
-#define ANOMALY_05000403 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000403 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Lockbox SESR Disallows Certain User Interrupts */
-#define ANOMALY_05000404 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000404 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Lockbox SESR Firmware Does Not Save/Restore Full Context */
 #define ANOMALY_05000405 (1)
 /* Lockbox SESR Firmware Arguments Are Not Retained After First Initialization */
-#define ANOMALY_05000407 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000407 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */
 #define ANOMALY_05000408 (1)
 /* Lockbox firmware leaves MDMA0 channel enabled */
-#define ANOMALY_05000409 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000409 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Incorrect Default Internal Voltage Regulator Setting */
-#define ANOMALY_05000410 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000410 (_ANOMALY_BF527(< 2))
 /* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */
-#define ANOMALY_05000411 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000411 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */
-#define ANOMALY_05000414 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000414 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* DEB2_URGENT Bit Not Functional */
-#define ANOMALY_05000415 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000415 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Speculative Fetches Can Cause Undesired External FIFO Operations */
 #define ANOMALY_05000416 (1)
 /* SPORT0 Ignores External TSCLK0 on PG14 When TMR6 is an Output */
-#define ANOMALY_05000417 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
-/* tSFSPE and tHFSPE Do Not Meet Data Sheet Specifications */
-#define ANOMALY_05000418 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000417 (_ANOMALY_BF527(< 2))
+/* PPI Timing Requirements tSFSPE and tHFSPE Do Not Meet Data Sheet Specifications */
+#define ANOMALY_05000418 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* USB PLL_STABLE Bit May Not Accurately Reflect the USB PLL's Status */
-#define ANOMALY_05000420 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000420 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* TWI Fall Time (Tof) May Violate the Minimum I2C Specification */
 #define ANOMALY_05000421 (1)
 /* TWI Input Capacitance (Ci) May Violate the Maximum I2C Specification */
-#define ANOMALY_05000422 (ANOMALY_BF527 && __SILICON_REVISION__ > 1)
+#define ANOMALY_05000422 (_ANOMALY_BF526_BF527(> 0, > 1))
 /* Certain Ethernet Frames With Errors are Misclassified in RMII Mode */
-#define ANOMALY_05000423 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000423 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Internal Voltage Regulator Not Trimmed */
-#define ANOMALY_05000424 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+#define ANOMALY_05000424 (_ANOMALY_BF527(< 2))
 /* Multichannel SPORT Channel Misalignment Under Specific Configuration */
-#define ANOMALY_05000425 (__SILICON_REVISION__ < 2)
-/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */
+#define ANOMALY_05000425 (_ANOMALY_BF526_BF527(< 1, < 2))
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
 #define ANOMALY_05000426 (1)
 /* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Reflects Buffer Status Instead of IRQ Status */
-#define ANOMALY_05000429 (__SILICON_REVISION__ < 2)
+#define ANOMALY_05000429 (_ANOMALY_BF526_BF527(< 1, < 2))
 /* Software System Reset Corrupts PLL_LOCKCNT Register */
-#define ANOMALY_05000430 (ANOMALY_BF527 && __SILICON_REVISION__ > 1)
+#define ANOMALY_05000430 (_ANOMALY_BF527(> 1))
+/* Incorrect Use of Stack in Lockbox Firmware During Authentication */
+#define ANOMALY_05000431 (1)
 /* bfrom_SysControl() Does Not Clear SIC_IWR1 Before Executing PLL Programming Sequence */
-#define ANOMALY_05000432 (ANOMALY_BF526)
+#define ANOMALY_05000432 (_ANOMALY_BF526(< 1))
 /* Certain SIC Registers are not Reset After Soft or Core Double Fault Reset */
-#define ANOMALY_05000435 ((ANOMALY_BF526 && __SILICON_REVISION__ < 1) || ANOMALY_BF527)
+#define ANOMALY_05000435 (_ANOMALY_BF526_BF527(< 1, >= 0))
+/* Preboot Cannot be Used to Alter the PLL_DIV Register */
+#define ANOMALY_05000439 (_ANOMALY_BF526_BF527(< 1, >= 0))
+/* bfrom_SysControl() Cannot be Used to Write the PLL_DIV Register */
+#define ANOMALY_05000440 (_ANOMALY_BF526_BF527(< 1, >= 0))
+/* OTP Write Accesses Not Supported */
+#define ANOMALY_05000442 (_ANOMALY_BF527(< 1))
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
+/* The WURESET Bit in the SYSCR Register is not Functional */
+#define ANOMALY_05000445 (1)
+/* USB DMA Short Packet Data Corruption */
+#define ANOMALY_05000450 (1)
+/* BCODE_QUICKBOOT, BCODE_ALLBOOT, and BCODE_FULLBOOT Settings in SYSCR Register Not Functional */
+#define ANOMALY_05000451 (1)
+/* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
+#define ANOMALY_05000452 (_ANOMALY_BF526_BF527(< 1, >= 0))
+/* USB Receive Interrupt Is Not Generated in DMA Mode 1 */
+#define ANOMALY_05000456 (1)
+/* Host DMA Port Responds to Certain Bus Activity Without HOST_CE Assertion */
+#define ANOMALY_05000457 (1)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
+/* USB Rx DMA hang */
+#define ANOMALY_05000465 (1)
+/* Possible RX data corruption when control & data EP FIFOs are accessed via the core */
+#define ANOMALY_05000467 (1)
 
 /* Anomalies that don't exist on this proc */
+#define ANOMALY_05000099 (0)
+#define ANOMALY_05000120 (0)
 #define ANOMALY_05000125 (0)
+#define ANOMALY_05000149 (0)
 #define ANOMALY_05000158 (0)
+#define ANOMALY_05000171 (0)
+#define ANOMALY_05000179 (0)
+#define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
+#define ANOMALY_05000202 (0)
+#define ANOMALY_05000215 (0)
+#define ANOMALY_05000220 (0)
+#define ANOMALY_05000227 (0)
 #define ANOMALY_05000230 (0)
+#define ANOMALY_05000231 (0)
+#define ANOMALY_05000233 (0)
+#define ANOMALY_05000234 (0)
+#define ANOMALY_05000242 (0)
 #define ANOMALY_05000244 (0)
+#define ANOMALY_05000248 (0)
+#define ANOMALY_05000250 (0)
+#define ANOMALY_05000257 (0)
 #define ANOMALY_05000261 (0)
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000274 (0)
 #define ANOMALY_05000278 (0)
+#define ANOMALY_05000281 (0)
+#define ANOMALY_05000283 (0)
 #define ANOMALY_05000285 (0)
+#define ANOMALY_05000287 (0)
+#define ANOMALY_05000301 (0)
 #define ANOMALY_05000305 (0)
 #define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000312 (0)
+#define ANOMALY_05000315 (0)
 #define ANOMALY_05000323 (0)
+#define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000400 (0)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,6 @@
 #define _MACH_BLACKFIN_H_
 
 #include "bf527.h"
-#include "mem_map.h"
 #include "defBF522.h"
 #include "anomaly.h"
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/include/mach/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/include/mach/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,38 +1,16 @@
 /*
- * file:         include/asm-blackfin/mach-bf527/mem_map.h
- * based on:	include/asm-blackfin/mach-bf537/mem_map.h
- * author:	Michael Hennerich (michael.hennerich@analog.com)
- *
- * created:
- * description:
- *	Memory MAP Common header file for blackfin BF527/5/2 of processors.
- * rev:
- *
- * modified:
- *
- * bugs:         enter bugs at http://blackfin.uclinux.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, 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.
+ * BF52x memory map
  *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_527_H_
-#define _MEM_MAP_527_H_
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
 
-#define COREMMR_BASE           0xFFE00000	/* Core MMRs */
-#define SYSMMR_BASE            0xFFC00000	/* System MMRs */
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
 
 /* Async Memory Banks */
 #define ASYNC_BANK3_BASE	0x20300000	/* Async Bank 3 */
@@ -89,20 +67,4 @@
 #define BFIN_DSUPBANKS	0
 #endif				/*CONFIG_BFIN_DCACHE */
 
-/* Level 2 Memory - none */
-
-#define L2_START	0
-#define L2_LENGTH	0
-
-/* Scratch Pad Memory */
-
-#define L1_SCRATCH_START	0xFFB00000
-#define L1_SCRATCH_LENGTH	0x1000
-
-#define GET_PDA_SAFE(preg)		\
-	preg.l = _cpu_pda;		\
-	preg.h = _cpu_pda;
-
-#define GET_PDA(preg, dreg)	GET_PDA_SAFE(preg)
-
-#endif				/* _MEM_MAP_527_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf527/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf527/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -170,6 +170,7 @@
 	default 11
 config IRQ_TIMER0
 	int "IRQ_TIMER0"
+	default 7 if TICKSOURCE_GPTMR0
 	default 8
 config IRQ_TIMER1
 	int "IRQ_TIMER1"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/blackstamp.c	2009-09-09 18:13:59.000000000 -0400
@@ -162,6 +162,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	}
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/cm_bf533.c	2009-09-09 18:13:59.000000000 -0400
@@ -82,7 +82,7 @@
 #endif
 
 /* SPI ADC chip */
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
 	.bits_per_word = 16,
@@ -117,7 +117,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -160,6 +160,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	}
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/ezkit.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/ezkit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/ezkit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/ezkit.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/plat-ram.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
@@ -86,6 +87,101 @@
 };
 #endif
 
+#if defined(CONFIG_MTD_PSD4256G) || defined(CONFIG_MTD_PSD4256G_MODULE)
+static const char *map_probes[] = {
+	"stm_flash",
+	NULL,
+};
+
+static struct platdata_mtd_ram stm_pri_data_a = {
+	.mapname    = "Flash A Primary",
+	.map_probes = map_probes,
+	.bankwidth  = 2,
+};
+
+static struct resource stm_pri_resource_a = {
+	.start = 0x20000000,
+	.end   = 0x200fffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device stm_pri_device_a = {
+	.name          = "mtd-ram",
+	.id            = 0,
+	.dev = {
+		.platform_data = &stm_pri_data_a,
+	},
+	.num_resources = 1,
+	.resource      = &stm_pri_resource_a,
+};
+
+static struct platdata_mtd_ram stm_pri_data_b = {
+	.mapname    = "Flash B Primary",
+	.map_probes = map_probes,
+	.bankwidth  = 2,
+};
+
+static struct resource stm_pri_resource_b = {
+	.start = 0x20100000,
+	.end   = 0x201fffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device stm_pri_device_b = {
+	.name          = "mtd-ram",
+	.id            = 4,
+	.dev = {
+		.platform_data = &stm_pri_data_b,
+	},
+	.num_resources = 1,
+	.resource      = &stm_pri_resource_b,
+};
+#endif
+
+#if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
+static struct platdata_mtd_ram sram_data_a = {
+	.mapname   = "Flash A SRAM",
+	.bankwidth = 2,
+};
+
+static struct resource sram_resource_a = {
+	.start = 0x20240000,
+	.end   = 0x2024ffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device sram_device_a = {
+	.name          = "mtd-ram",
+	.id            = 8,
+	.dev = {
+		.platform_data = &sram_data_a,
+	},
+	.num_resources = 1,
+	.resource      = &sram_resource_a,
+};
+
+static struct platdata_mtd_ram sram_data_b = {
+	.mapname   = "Flash B SRAM",
+	.bankwidth = 2,
+};
+
+static struct resource sram_resource_b = {
+	.start = 0x202c0000,
+	.end   = 0x202cffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device sram_device_b = {
+	.name          = "mtd-ram",
+	.id            = 9,
+	.dev = {
+		.platform_data = &sram_data_b,
+	},
+	.num_resources = 1,
+	.resource      = &sram_resource_b,
+};
+#endif
+
 #if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
 static struct mtd_partition bfin_spi_flash_partitions[] = {
 	{
@@ -118,7 +214,7 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -154,7 +250,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -196,6 +292,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	}
 };
@@ -352,6 +453,16 @@
 
 	&bfin_dpmc,
 
+#if defined(CONFIG_MTD_PSD4256G) || defined(CONFIG_MTD_PSD4256G_MODULE)
+	&stm_pri_device_a,
+	&stm_pri_device_b,
+#endif
+
+#if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
+	&sram_device_a,
+	&sram_device_b,
+#endif
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 	&smc91x_device,
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/H8606.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/H8606.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/H8606.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/H8606.c	2009-09-09 18:13:59.000000000 -0400
@@ -173,7 +173,7 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.ctl_reg = 0x1000,
@@ -216,7 +216,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 4,     /* actual baudrate is SCLK/(2xspeed_hz) */
@@ -266,6 +266,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	}
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/stamp.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/stamp.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/boards/stamp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/boards/stamp.c	2009-09-09 18:13:59.000000000 -0400
@@ -192,7 +192,7 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -237,7 +237,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -299,6 +299,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	}
 };
@@ -448,7 +453,7 @@
 		.irq = 39,
 	},
 #endif
-#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
 	},
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/anomaly.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/anomaly.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/anomaly.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/anomaly.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,7 +6,7 @@
  * Licensed under the GPL-2 or later.
  */
 
-/* This file shoule be up to date with:
+/* This file should be up to date with:
  *  - Revision E, 09/18/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
  */
 
@@ -34,21 +34,21 @@
 # define ANOMALY_BF533 0
 #endif
 
-/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot 2 Not Supported */
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
 /* UART Line Status Register (UART_LSR) Bits Are Not Updated at the Same Time */
 #define ANOMALY_05000099 (__SILICON_REVISION__ < 5)
 /* Watchpoint Status Register (WPSTAT) Bits Are Set on Every Corresponding Match */
-#define ANOMALY_05000105 (1)
+#define ANOMALY_05000105 (__SILICON_REVISION__ > 2)
 /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
 #define ANOMALY_05000119 (1)
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
 /* Instruction DMA Can Cause Data Cache Fills to Fail (Boot Implications) */
 #define ANOMALY_05000158 (__SILICON_REVISION__ < 5)
-/* PPI Data Lengths Between 8 and 16 Do Not Zero Out Upper Bits */
+/* PPI Data Lengths between 8 and 16 Do Not Zero Out Upper Bits */
 #define ANOMALY_05000166 (1)
-/* Turning Serial Ports on with External Frame Syncs */
+/* Turning SPORTs on while External Frame Sync Is Active May Corrupt Data */
 #define ANOMALY_05000167 (1)
 /* PPI_COUNT Cannot Be Programmed to 0 in General Purpose TX or RX Modes */
 #define ANOMALY_05000179 (__SILICON_REVISION__ < 5)
@@ -56,25 +56,25 @@
 #define ANOMALY_05000180 (1)
 /* Timer Pin Limitations for PPI TX Modes with External Frame Syncs */
 #define ANOMALY_05000183 (__SILICON_REVISION__ < 4)
-/* False Protection Exceptions */
+/* False Protection Exceptions when Speculative Fetch Is Cancelled */
 #define ANOMALY_05000189 (__SILICON_REVISION__ < 4)
 /* False I/O Pin Interrupts on Edge-Sensitive Inputs When Polarity Setting Is Changed */
 #define ANOMALY_05000193 (__SILICON_REVISION__ < 4)
 /* Restarting SPORT in Specific Modes May Cause Data Corruption */
 #define ANOMALY_05000194 (__SILICON_REVISION__ < 4)
-/* Failing MMR Accesses When Stalled by Preceding Memory Read */
+/* Failing MMR Accesses when Preceding Memory Read Stalls */
 #define ANOMALY_05000198 (__SILICON_REVISION__ < 5)
 /* Current DMA Address Shows Wrong Value During Carry Fix */
 #define ANOMALY_05000199 (__SILICON_REVISION__ < 4)
 /* SPORT TFS and DT Are Incorrectly Driven During Inactive Channels in Certain Conditions */
-#define ANOMALY_05000200 (__SILICON_REVISION__ < 5)
+#define ANOMALY_05000200 (__SILICON_REVISION__ == 3 || __SILICON_REVISION__ == 4)
 /* Receive Frame Sync Not Ignored During Active Frames in SPORT Multi-Channel Mode */
-#define ANOMALY_05000201 (__SILICON_REVISION__ < 4)
+#define ANOMALY_05000201 (__SILICON_REVISION__ == 3)
 /* Possible Infinite Stall with Specific Dual-DAG Situation */
 #define ANOMALY_05000202 (__SILICON_REVISION__ < 5)
 /* Specific Sequence That Can Cause DMA Error or DMA Stopping */
 #define ANOMALY_05000203 (__SILICON_REVISION__ < 4)
-/* Incorrect data read with write-through cache and allocate cache lines on reads only mode */
+/* Incorrect Data Read with Writethrough "Allocate Cache Lines on Reads Only" Cache Mode */
 #define ANOMALY_05000204 (__SILICON_REVISION__ < 4 && ANOMALY_BF533)
 /* Recovery from "Brown-Out" Condition */
 #define ANOMALY_05000207 (__SILICON_REVISION__ < 4)
@@ -104,9 +104,9 @@
 #define ANOMALY_05000242 (__SILICON_REVISION__ < 5)
 /* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
 #define ANOMALY_05000244 (__SILICON_REVISION__ < 5)
-/* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
-/* Data CPLBs Should Prevent Spurious Hardware Errors */
+/* Data CPLBs Should Prevent False Hardware Errors */
 #define ANOMALY_05000246 (__SILICON_REVISION__ < 5)
 /* Incorrect Bit Shift of Data Word in Multichannel (TDM) Mode in Certain Conditions */
 #define ANOMALY_05000250 (__SILICON_REVISION__ == 4)
@@ -137,7 +137,7 @@
 /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */
 #define ANOMALY_05000270 (__SILICON_REVISION__ < 5)
 /* Spontaneous Reset of Internal Voltage Regulator */
-#define ANOMALY_05000271 (__SILICON_REVISION__ < 4)
+#define ANOMALY_05000271 (__SILICON_REVISION__ == 3)
 /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
 #define ANOMALY_05000272 (1)
 /* Writes to Synchronous SDRAM Memory May Be Lost */
@@ -148,33 +148,33 @@
 #define ANOMALY_05000277 (__SILICON_REVISION__ < 6)
 /* Disabling Peripherals with DMA Running May Cause DMA System Instability */
 #define ANOMALY_05000278 (__SILICON_REVISION__ < 6)
-/* False Hardware Error Exception When ISR Context Is Not Restored */
+/* False Hardware Error Exception when ISR Context Is Not Restored */
 #define ANOMALY_05000281 (__SILICON_REVISION__ < 6)
 /* Memory DMA Corruption with 32-Bit Data and Traffic Control */
 #define ANOMALY_05000282 (__SILICON_REVISION__ < 6)
-/* System MMR Write Is Stalled Indefinitely When Killed in a Particular Stage */
+/* System MMR Write Is Stalled Indefinitely when Killed in a Particular Stage */
 #define ANOMALY_05000283 (__SILICON_REVISION__ < 6)
 /* SPORTs May Receive Bad Data If FIFOs Fill Up */
 #define ANOMALY_05000288 (__SILICON_REVISION__ < 6)
 /* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
 #define ANOMALY_05000301 (__SILICON_REVISION__ < 6)
-/* SSYNCs After Writes To DMA MMR Registers May Not Be Handled Correctly */
+/* SSYNCs after Writes to DMA MMR Registers May Not Be Handled Correctly */
 #define ANOMALY_05000302 (__SILICON_REVISION__ < 5)
 /* SPORT_HYS Bit in PLL_CTL Register Is Not Functional */
 #define ANOMALY_05000305 (__SILICON_REVISION__ < 5)
-/* New Feature: Additional PPI Frame Sync Sampling Options (Not Available On Older Silicon) */
+/* ALT_TIMING Bit in PPI_CONTROL Register Is Not Functional */
 #define ANOMALY_05000306 (__SILICON_REVISION__ < 5)
 /* SCKELOW Bit Does Not Maintain State Through Hibernate */
-#define ANOMALY_05000307 (1)
+#define ANOMALY_05000307 (1)	/* note: brokenness is noted in documentation, not anomaly sheet */
 /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
 #define ANOMALY_05000310 (1)
 /* Erroneous Flag (GPIO) Pin Operations under Specific Sequences */
 #define ANOMALY_05000311 (__SILICON_REVISION__ < 6)
-/* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
 #define ANOMALY_05000312 (__SILICON_REVISION__ < 6)
-/* PPI Is Level-Sensitive on First Transfer */
+/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */
 #define ANOMALY_05000313 (__SILICON_REVISION__ < 6)
-/* Killed System MMR Write Completes Erroneously On Next System MMR Access */
+/* Killed System MMR Write Completes Erroneously on Next System MMR Access */
 #define ANOMALY_05000315 (__SILICON_REVISION__ < 6)
 /* Internal Voltage Regulator Values of 1.05V, 1.10V and 1.15V Not Allowed for LQFP Packages */
 #define ANOMALY_05000319 ((ANOMALY_BF531 || ANOMALY_BF532) && __SILICON_REVISION__ < 6)
@@ -200,32 +200,80 @@
 #define ANOMALY_05000426 (1)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
 
 /* These anomalies have been "phased" out of analog.com anomaly sheets and are
  * here to show running on older silicon just isn't feasible.
  */
 
+/* Internal voltage regulator can't be modified via register writes */
+#define ANOMALY_05000066 (__SILICON_REVISION__ < 2)
 /* Watchpoints (Hardware Breakpoints) are not supported */
 #define ANOMALY_05000067 (__SILICON_REVISION__ < 3)
-/* Reserved bits in SYSCFG register not set at power on */
+/* SDRAM PSSE bit cannot be set again after SDRAM Powerup */
+#define ANOMALY_05000070 (__SILICON_REVISION__ < 2)
+/* Writing FIO_DIR can corrupt a programmable flag's data */
+#define ANOMALY_05000079 (__SILICON_REVISION__ < 2)
+/* Timer Auto-Baud Mode requires the UART clock to be enabled. */
+#define ANOMALY_05000086 (__SILICON_REVISION__ < 2)
+/* Internal Clocking Modes on SPORT0 not supported */
+#define ANOMALY_05000088 (__SILICON_REVISION__ < 2)
+/* Internal voltage regulator does not wake up from an RTC wakeup */
+#define ANOMALY_05000092 (__SILICON_REVISION__ < 2)
+/* The IFLUSH Instruction Must Be Preceded by a CSYNC Instruction */
+#define ANOMALY_05000093 (__SILICON_REVISION__ < 2)
+/* Vectoring to instruction that is being filled into the i-cache may cause erroneous behavior */
+#define ANOMALY_05000095 (__SILICON_REVISION__ < 2)
+/* PREFETCH, FLUSH, and FLUSHINV Instructions Must Be Followed by a CSYNC Instruction */
+#define ANOMALY_05000096 (__SILICON_REVISION__ < 2)
+/* Performance Monitor 0 and 1 are swapped when monitoring memory events */
+#define ANOMALY_05000097 (__SILICON_REVISION__ < 2)
+/* 32-bit SPORT DMA will be word reversed */
+#define ANOMALY_05000098 (__SILICON_REVISION__ < 2)
+/* Incorrect status in the UART_IIR register */
+#define ANOMALY_05000100 (__SILICON_REVISION__ < 2)
+/* Reading X_MODIFY or Y_MODIFY while DMA channel is active */
+#define ANOMALY_05000101 (__SILICON_REVISION__ < 2)
+/* Descriptor MemDMA may lock up with 32-bit transfers or if transfers span 64KB buffers */
+#define ANOMALY_05000102 (__SILICON_REVISION__ < 2)
+/* Incorrect Value Written to the Cycle Counters */
+#define ANOMALY_05000103 (__SILICON_REVISION__ < 2)
+/* Stores to L1 Data Memory Incorrect when a Specific Sequence Is Followed */
+#define ANOMALY_05000104 (__SILICON_REVISION__ < 2)
+/* Programmable Flag (PF3) functionality not supported in all PPI modes */
+#define ANOMALY_05000106 (__SILICON_REVISION__ < 2)
+/* Data store can be lost when targeting a cache line fill */
+#define ANOMALY_05000107 (__SILICON_REVISION__ < 2)
+/* Reserved Bits in SYSCFG Register Not Set at Power-On */
 #define ANOMALY_05000109 (__SILICON_REVISION__ < 3)
-/* Trace Buffers may record discontinuities into emulation mode and/or exception, NMI, reset handlers */
+/* Infinite Core Stall */
+#define ANOMALY_05000114 (__SILICON_REVISION__ < 2)
+/* PPI_FSx may glitch when generated by the on chip Timers. */
+#define ANOMALY_05000115 (__SILICON_REVISION__ < 2)
+/* Trace Buffers May Contain Errors in Emulation Mode and/or Exception, NMI, Reset Handlers */
 #define ANOMALY_05000116 (__SILICON_REVISION__ < 3)
-/* DTEST_COMMAND initiated memory access may be incorrect if data cache or DMA is active */
+/* DTEST registers allow access to Data Cache when DTEST_COMMAND< 14 >= 0 */
+#define ANOMALY_05000117 (__SILICON_REVISION__ < 2)
+/* Booting from an 8-bit or 24-bit Addressable SPI device is not supported */
+#define ANOMALY_05000118 (__SILICON_REVISION__ < 2)
+/* DTEST_COMMAND Initiated Memory Access May Be Incorrect If Data Cache or DMA Is Active */
 #define ANOMALY_05000123 (__SILICON_REVISION__ < 3)
 /* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1, or 1:1 */
 #define ANOMALY_05000124 (__SILICON_REVISION__ < 3)
-/* Erroneous exception when enabling cache */
+/* Erroneous Exception when Enabling Cache */
 #define ANOMALY_05000125 (__SILICON_REVISION__ < 3)
 /* SPI clock polarity and phase bits incorrect during booting */
 #define ANOMALY_05000126 (__SILICON_REVISION__ < 3)
-/* DMEM_CONTROL is not set on Reset */
+/* DMEM_CONTROL<12> Is Not Set on Reset */
 #define ANOMALY_05000137 (__SILICON_REVISION__ < 3)
 /* SPI boot will not complete if there is a zero fill block in the loader file */
-#define ANOMALY_05000138 (__SILICON_REVISION__ < 3)
+#define ANOMALY_05000138 (__SILICON_REVISION__ == 2)
+/* TIMERx_CONFIG[5] must be set for PPI in GP output mode with internal Frame Syncs */
+#define ANOMALY_05000139 (__SILICON_REVISION__ < 2)
 /* Allowing the SPORT RX FIFO to fill will cause an overflow */
 #define ANOMALY_05000140 (__SILICON_REVISION__ < 3)
-/* An Infinite Stall occurs with a particular sequence of consecutive dual dag events */
+/* Infinite Stall may occur with a particular sequence of consecutive dual dag events */
 #define ANOMALY_05000141 (__SILICON_REVISION__ < 3)
 /* Interrupts may be lost when a programmable input flag is configured to be edge sensitive */
 #define ANOMALY_05000142 (__SILICON_REVISION__ < 3)
@@ -237,23 +285,23 @@
 #define ANOMALY_05000145 (__SILICON_REVISION__ < 3)
 /* MDMA may lose the first few words of a descriptor chain */
 #define ANOMALY_05000146 (__SILICON_REVISION__ < 3)
-/* The source MDMA descriptor may stop with a DMA Error */
+/* Source MDMA descriptor may stop with a DMA Error near beginning of descriptor fetch */
 #define ANOMALY_05000147 (__SILICON_REVISION__ < 3)
-/* When booting from a 16-bit asynchronous memory device, the upper 8-bits of each word must be 0x00 */
+/* When booting from 16-bit asynchronous memory, the upper 8 bits of each word must be 0x00 */
 #define ANOMALY_05000148 (__SILICON_REVISION__ < 3)
 /* Frame Delay in SPORT Multichannel Mode */
 #define ANOMALY_05000153 (__SILICON_REVISION__ < 3)
-/* SPORT TFS signal is active in Multi-channel mode outside of valid channels */
+/* SPORT TFS signal stays active in multichannel mode outside of valid channels */
 #define ANOMALY_05000154 (__SILICON_REVISION__ < 3)
 /* Timer1 can not be used for PWMOUT mode when a certain PPI mode is in use */
 #define ANOMALY_05000155 (__SILICON_REVISION__ < 3)
-/* A killed 32-bit System MMR write will lead to the next system MMR access thinking it should be 32-bit. */
+/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
 #define ANOMALY_05000157 (__SILICON_REVISION__ < 3)
-/* SPORT transmit data is not gated by external frame sync in certain conditions */
+/* SPORT Transmit Data Is Not Gated by External Frame Sync in Certain Conditions */
 #define ANOMALY_05000163 (__SILICON_REVISION__ < 3)
-/* SDRAM auto-refresh and subsequent Power Ups */
+/* Undefined Behavior when Power-Up Sequence Is Issued to SDRAM during Auto-Refresh */
 #define ANOMALY_05000168 (__SILICON_REVISION__ < 3)
-/* DATA CPLB page miss can result in lost write-through cache data writes */
+/* DATA CPLB Page Miss Can Result in Lost Write-Through Data Cache Writes */
 #define ANOMALY_05000169 (__SILICON_REVISION__ < 3)
 /* DMA vs Core accesses to external memory */
 #define ANOMALY_05000173 (__SILICON_REVISION__ < 3)
@@ -261,29 +309,45 @@
 #define ANOMALY_05000174 (__SILICON_REVISION__ < 3)
 /* Overlapping Sequencer and Memory Stalls */
 #define ANOMALY_05000175 (__SILICON_REVISION__ < 3)
-/* Multiplication of (-1) by (-1) followed by an accumulator saturation */
+/* Overflow Bit Asserted when Multiplication of -1 by -1 Followed by Accumulator Saturation */
 #define ANOMALY_05000176 (__SILICON_REVISION__ < 3)
-/* Disabling the PPI resets the PPI configuration registers */
+/* Disabling the PPI Resets the PPI Configuration Registers */
 #define ANOMALY_05000181 (__SILICON_REVISION__ < 3)
-/* PPI TX Mode with 2 External Frame Syncs */
+/* Early PPI Transmit when FS1 Asserts before FS2 in TX Mode with 2 External Frame Syncs */
 #define ANOMALY_05000185 (__SILICON_REVISION__ < 3)
 /* PPI does not invert the Driving PPICLK edge in Transmit Modes */
 #define ANOMALY_05000191 (__SILICON_REVISION__ < 3)
-/* In PPI Transmit Modes with External Frame Syncs POLC */
+/* In PPI Transmit Modes with External Frame Syncs POLC bit must be set to 1 */
 #define ANOMALY_05000192 (__SILICON_REVISION__ < 3)
 /* Internal Voltage Regulator may not start up */
 #define ANOMALY_05000206 (__SILICON_REVISION__ < 3)
 
 /* Anomalies that don't exist on this proc */
+#define ANOMALY_05000120 (0)
+#define ANOMALY_05000149 (0)
+#define ANOMALY_05000171 (0)
+#define ANOMALY_05000182 (0)
+#define ANOMALY_05000220 (0)
+#define ANOMALY_05000248 (0)
 #define ANOMALY_05000266 (0)
+#define ANOMALY_05000274 (0)
+#define ANOMALY_05000287 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000362 (1)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
+#define ANOMALY_05000389 (0)
 #define ANOMALY_05000412 (0)
+#define ANOMALY_05000430 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
+#define ANOMALY_05000456 (0)
+#define ANOMALY_05000450 (0)
+#define ANOMALY_05000465 (0)
+#define ANOMALY_05000467 (0)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -34,7 +34,6 @@
 #define BF533_FAMILY
 
 #include "bf533.h"
-#include "mem_map.h"
 #include "defBF532.h"
 #include "anomaly.h"
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/include/mach/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/include/mach/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,38 +1,16 @@
 /*
- * File:         include/asm-blackfin/mach-bf533/mem_map.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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, 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.
+ * BF533 memory map
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_533_H_
-#define _MEM_MAP_533_H_
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
 
-#define COREMMR_BASE           0xFFE00000	 /* Core MMRs */
-#define SYSMMR_BASE            0xFFC00000	 /* System MMRs */
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
 
 /* Async Memory Banks */
 #define ASYNC_BANK3_BASE	0x20300000	 /* Async Bank 3 */
@@ -158,20 +136,4 @@
 
 #endif
 
-/* Level 2 Memory - none */
-
-#define L2_START	0
-#define L2_LENGTH	0
-
-/* Scratch Pad Memory */
-
-#define L1_SCRATCH_START	0xFFB00000
-#define L1_SCRATCH_LENGTH	0x1000
-
-#define GET_PDA_SAFE(preg)		\
-	preg.l = _cpu_pda;		\
-	preg.h = _cpu_pda;
-
-#define GET_PDA(preg, dreg)	GET_PDA_SAFE(preg)
-
-#endif				/* _MEM_MAP_533_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf533/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf533/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -59,6 +59,7 @@
 	default 10
 config TIMER0
 	int "TIMER0"
+	default 7 if TICKSOURCE_GPTMR0
 	default 8
 config TIMER1
 	int "TIMER1"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/cm_bf537.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/cm_bf537.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/cm_bf537.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/cm_bf537.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,7 +86,7 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -129,7 +129,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -182,8 +182,13 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
-	}
+	},
 };
 
 /* SPI controller data */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/minotaur.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/minotaur.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/minotaur.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/minotaur.c	2009-09-09 18:13:59.000000000 -0400
@@ -184,6 +184,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	},
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/pnav10.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/pnav10.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/pnav10.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/pnav10.c	2009-09-09 18:13:59.000000000 -0400
@@ -265,8 +265,8 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -333,8 +333,8 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -398,8 +398,13 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
-	}
+	},
 };
 
 /* SPI controller data */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/stamp.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/stamp.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/stamp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/stamp.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,7 +79,6 @@
 
 static struct isp1760_platform_data isp1760_priv = {
 	.is_isp1761 = 0,
-	.port1_disable = 0,
 	.bus_width_16 = 1,
 	.port1_otg = 0,
 	.analog_oc = 0,
@@ -508,8 +507,8 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -607,6 +606,43 @@
 };
 #endif
 
+#if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
+#include <linux/input.h>
+#include <linux/spi/adxl34x.h>
+static const struct adxl34x_platform_data adxl34x_info = {
+	.x_axis_offset = 0,
+	.y_axis_offset = 0,
+	.z_axis_offset = 0,
+	.tap_threshold = 0x31,
+	.tap_duration = 0x10,
+	.tap_latency = 0x60,
+	.tap_window = 0xF0,
+	.tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN,
+	.act_axis_control = 0xFF,
+	.activity_threshold = 5,
+	.inactivity_threshold = 3,
+	.inactivity_time = 4,
+	.free_fall_threshold = 0x7,
+	.free_fall_time = 0x20,
+	.data_rate = 0x8,
+	.data_range = ADXL_FULL_RES,
+
+	.ev_type = EV_ABS,
+	.ev_code_x = ABS_X,		/* EV_REL */
+	.ev_code_y = ABS_Y,		/* EV_REL */
+	.ev_code_z = ABS_Z,		/* EV_REL */
+
+	.ev_code_tap_x = BTN_TOUCH,		/* EV_KEY */
+	.ev_code_tap_y = BTN_TOUCH,		/* EV_KEY */
+	.ev_code_tap_z = BTN_TOUCH,		/* EV_KEY */
+
+/*	.ev_code_ff = KEY_F,*/		/* EV_KEY */
+/*	.ev_code_act_inactivity = KEY_A,*/	/* EV_KEY */
+	.power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
+	.fifo_mode = ADXL_FIFO_STREAM,
+};
+#endif
+
 #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
 static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
 	.enable_dma = 0,
@@ -695,8 +731,8 @@
 		.mode = SPI_MODE_3,
 	},
 #endif
-#if defined(CONFIG_SPI_ADC_BF533) \
-	|| defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) \
+	|| defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -1277,10 +1313,10 @@
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
 	{
 		I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-		.irq = IRQ_PF5,
+		.irq = IRQ_PG5,
 	},
 #endif
-#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
 	},
@@ -1308,10 +1344,17 @@
 #if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE)
 	{
 		I2C_BOARD_INFO("pmic-adp5520", 0x32),
-		.irq = IRQ_PF7,
+		.irq = IRQ_PG0,
 		.platform_data = (void *)&adp5520_pdev_data,
 	},
 #endif
+#if defined(CONFIG_INPUT_ADXL34X_I2C) || defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
+	{
+		I2C_BOARD_INFO("adxl34x", 0x53),
+		.irq = IRQ_PG3,
+		.platform_data = (void *)&adxl34x_info,
+	},
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -1358,16 +1401,18 @@
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 0,
 };
-
+/* CompactFlash Storage Card Memory Mapped Adressing
+ * /REG = A11 = 1
+ */
 static struct resource bfin_pata_resources[] = {
 	{
-		.start = 0x20211820,
-		.end = 0x2021183F,
+		.start = 0x20211800,
+		.end = 0x20211807,
 		.flags = IORESOURCE_MEM,
 	},
 	{
-		.start = 0x2021181C,
-		.end = 0x2021181F,
+		.start = 0x2021180E,	/* Device Ctl */
+		.end = 0x2021180E,
 		.flags = IORESOURCE_MEM,
 	},
 };
@@ -1527,7 +1572,8 @@
 	platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
-#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+#if (defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)) \
+	 && defined(PATA_INT)
 	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,7 +86,7 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -129,7 +129,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -182,6 +182,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	}
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/anomaly.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/anomaly.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/anomaly.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/anomaly.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,7 +6,7 @@
  * Licensed under the GPL-2 or later.
  */
 
-/* This file shoule be up to date with:
+/* This file should be up to date with:
  *  - Revision D, 09/18/2008; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
  */
 
@@ -34,79 +34,77 @@
 # define ANOMALY_BF537 0
 #endif
 
-/* Multi-issue instruction with dsp32shiftimm in slot1 and P-reg store in slot 2 not supported */
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
-/* DMA_RUN bit is not valid after a Peripheral Receive Channel DMA stops */
+/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
 #define ANOMALY_05000119 (1)
-/* Rx.H cannot be used to access 16-bit System MMR registers */
+/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
-/* Killed 32-bit MMR write leads to next system MMR access thinking it should be 32-bit */
+/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
 #define ANOMALY_05000157 (__SILICON_REVISION__ < 2)
-/* Turning SPORTs on while External Frame Sync Is Active May Corrupt Data */
-#define ANOMALY_05000167 (1)
-/* PPI_DELAY not functional in PPI modes with 0 frame syncs */
+/* PPI_DELAY Not Functional in PPI Modes with 0 Frame Syncs */
 #define ANOMALY_05000180 (1)
 /* Instruction Cache Is Not Functional */
 #define ANOMALY_05000237 (__SILICON_REVISION__ < 2)
-/* If i-cache is on, CSYNC/SSYNC/IDLE around Change of Control causes failures */
+/* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
 #define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
-/* Spurious Hardware Error from an access in the shadow of a conditional branch */
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
-/* CLKIN Buffer Output Enable Reset Behavior Is Changed */
+/* Buffered CLKIN Output Is Disabled by Default */
 #define ANOMALY_05000247 (1)
-/* Incorrect Bit-Shift of Data Word in Multichannel (TDM) mode in certain conditions */
+/* Incorrect Bit Shift of Data Word in Multichannel (TDM) Mode in Certain Conditions */
 #define ANOMALY_05000250 (__SILICON_REVISION__ < 3)
-/* EMAC Tx DMA error after an early frame abort */
+/* EMAC TX DMA Error After an Early Frame Abort */
 #define ANOMALY_05000252 (__SILICON_REVISION__ < 3)
-/* Maximum external clock speed for Timers */
+/* Maximum External Clock Speed for Timers */
 #define ANOMALY_05000253 (__SILICON_REVISION__ < 3)
-/* Incorrect Timer Pulse Width in Single-Shot PWM_OUT mode with external clock */
+/* Incorrect Timer Pulse Width in Single-Shot PWM_OUT Mode with External Clock */
 #define ANOMALY_05000254 (__SILICON_REVISION__ > 2)
-/* Entering Hibernate Mode with RTC Seconds event interrupt not functional */
+/* Entering Hibernate State with RTC Seconds Interrupt Not Functional */
 #define ANOMALY_05000255 (__SILICON_REVISION__ < 3)
-/* EMAC MDIO input latched on wrong MDC edge */
+/* EMAC MDIO Input Latched on Wrong MDC Edge */
 #define ANOMALY_05000256 (__SILICON_REVISION__ < 3)
-/* Interrupt/Exception during short hardware loop may cause bad instruction fetches */
+/* Interrupt/Exception During Short Hardware Loop May Cause Bad Instruction Fetches */
 #define ANOMALY_05000257 (__SILICON_REVISION__ < 3)
-/* Instruction Cache is corrupted when bits 9 and 12 of the ICPLB Data registers differ */
+/* Instruction Cache Is Corrupted When Bits 9 and 12 of the ICPLB Data Registers Differ */
 #define ANOMALY_05000258 (((ANOMALY_BF536 || ANOMALY_BF537) && __SILICON_REVISION__ == 1) || __SILICON_REVISION__ == 2)
-/* ICPLB_STATUS MMR register may be corrupted */
+/* ICPLB_STATUS MMR Register May Be Corrupted */
 #define ANOMALY_05000260 (__SILICON_REVISION__ == 2)
-/* DCPLB_FAULT_ADDR MMR register may be corrupted */
+/* DCPLB_FAULT_ADDR MMR Register May Be Corrupted */
 #define ANOMALY_05000261 (__SILICON_REVISION__ < 3)
-/* Stores to data cache may be lost */
+/* Stores To Data Cache May Be Lost */
 #define ANOMALY_05000262 (__SILICON_REVISION__ < 3)
-/* Hardware loop corrupted when taking an ICPLB exception */
+/* Hardware Loop Corrupted When Taking an ICPLB Exception */
 #define ANOMALY_05000263 (__SILICON_REVISION__ == 2)
-/* CSYNC/SSYNC/IDLE causes infinite stall in second to last instruction in hardware loop */
+/* CSYNC/SSYNC/IDLE Causes Infinite Stall in Penultimate Instruction in Hardware Loop */
 #define ANOMALY_05000264 (__SILICON_REVISION__ < 3)
-/* Sensitivity to noise with slow input edge rates on external SPORT TX and RX clocks */
+/* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
-/* Memory DMA error when peripheral DMA is running with non-zero DEB_TRAFFIC_PERIOD */
+/* Memory DMA Error when Peripheral DMA Is Running with Non-Zero DEB_TRAFFIC_PERIOD */
 #define ANOMALY_05000268 (__SILICON_REVISION__ < 3)
-/* High I/O activity causes output voltage of internal voltage regulator (VDDint) to decrease */
+/* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */
 #define ANOMALY_05000270 (__SILICON_REVISION__ < 3)
-/* Certain data cache write through modes fail for VDDint <=0.9V */
+/* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
 #define ANOMALY_05000272 (1)
-/* Writes to Synchronous SDRAM memory may be lost */
+/* Writes to Synchronous SDRAM Memory May Be Lost */
 #define ANOMALY_05000273 (__SILICON_REVISION__ < 3)
-/* Writes to an I/O data register one SCLK cycle after an edge is detected may clear interrupt */
+/* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
 #define ANOMALY_05000277 (__SILICON_REVISION__ < 3)
-/* Disabling Peripherals with DMA running may cause DMA system instability */
+/* Disabling Peripherals with DMA Running May Cause DMA System Instability */
 #define ANOMALY_05000278 (((ANOMALY_BF536 || ANOMALY_BF537) && __SILICON_REVISION__ < 3) || (ANOMALY_BF534 && __SILICON_REVISION__ < 2))
-/* SPI Master boot mode does not work well with Atmel Data flash devices */
+/* SPI Master Boot Mode Does Not Work Well with Atmel Data Flash Devices */
 #define ANOMALY_05000280 (1)
-/* False Hardware Error Exception when ISR context is not restored */
+/* False Hardware Error Exception when ISR Context Is Not Restored */
 #define ANOMALY_05000281 (__SILICON_REVISION__ < 3)
-/* Memory DMA corruption with 32-bit data and traffic control */
+/* Memory DMA Corruption with 32-Bit Data and Traffic Control */
 #define ANOMALY_05000282 (__SILICON_REVISION__ < 3)
-/* System MMR Write Is Stalled Indefinitely When Killed in a Particular Stage */
+/* System MMR Write Is Stalled Indefinitely when Killed in a Particular Stage */
 #define ANOMALY_05000283 (__SILICON_REVISION__ < 3)
-/* New Feature: EMAC TX DMA Word Alignment (Not Available On Older Silicon) */
+/* TXDWA Bit in EMAC_SYSCTL Register Is Not Functional */
 #define ANOMALY_05000285 (__SILICON_REVISION__ < 3)
-/* SPORTs may receive bad data if FIFOs fill up */
+/* SPORTs May Receive Bad Data If FIFOs Fill Up */
 #define ANOMALY_05000288 (__SILICON_REVISION__ < 3)
-/* Memory to memory DMA source/destination descriptors must be in same memory space */
+/* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
 #define ANOMALY_05000301 (1)
 /* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
 #define ANOMALY_05000304 (__SILICON_REVISION__ < 3)
@@ -114,25 +112,25 @@
 #define ANOMALY_05000305 (__SILICON_REVISION__ < 3)
 /* SCKELOW Bit Does Not Maintain State Through Hibernate */
 #define ANOMALY_05000307 (__SILICON_REVISION__ < 3)
-/* Writing UART_THR while UART clock is disabled sends erroneous start bit */
+/* Writing UART_THR While UART Clock Is Disabled Sends Erroneous Start Bit */
 #define ANOMALY_05000309 (__SILICON_REVISION__ < 3)
-/* False hardware errors caused by fetches at the boundary of reserved memory */
+/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
 #define ANOMALY_05000310 (1)
-/* Errors when SSYNC, CSYNC, or loads to LT, LB and LC registers are interrupted */
+/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
 #define ANOMALY_05000312 (1)
-/* PPI is level sensitive on first transfer */
+/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */
 #define ANOMALY_05000313 (1)
-/* Killed System MMR Write Completes Erroneously On Next System MMR Access */
+/* Killed System MMR Write Completes Erroneously on Next System MMR Access */
 #define ANOMALY_05000315 (__SILICON_REVISION__ < 3)
-/* EMAC RMII mode: collisions occur in Full Duplex mode */
+/* EMAC RMII Mode: Collisions Occur in Full Duplex Mode */
 #define ANOMALY_05000316 (__SILICON_REVISION__ < 3)
-/* EMAC RMII mode: TX frames in half duplex fail with status No Carrier */
+/* EMAC RMII Mode: TX Frames in Half Duplex Fail with Status "No Carrier" */
 #define ANOMALY_05000321 (__SILICON_REVISION__ < 3)
-/* EMAC RMII mode at 10-Base-T speed: RX frames not received properly */
+/* EMAC RMII Mode at 10-Base-T Speed: RX Frames Not Received Properly */
 #define ANOMALY_05000322 (1)
 /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
 #define ANOMALY_05000341 (__SILICON_REVISION__ >= 3)
-/* New Feature: UART Remains Enabled after UART Boot */
+/* UART Gets Disabled after UART Boot */
 #define ANOMALY_05000350 (__SILICON_REVISION__ >= 3)
 /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
 #define ANOMALY_05000355 (1)
@@ -156,24 +154,53 @@
 #define ANOMALY_05000426 (1)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
 
 /* Anomalies that don't exist on this proc */
+#define ANOMALY_05000099 (0)
+#define ANOMALY_05000120 (0)
 #define ANOMALY_05000125 (0)
+#define ANOMALY_05000149 (0)
 #define ANOMALY_05000158 (0)
+#define ANOMALY_05000171 (0)
+#define ANOMALY_05000179 (0)
+#define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
+#define ANOMALY_05000202 (0)
+#define ANOMALY_05000215 (0)
+#define ANOMALY_05000220 (0)
+#define ANOMALY_05000227 (0)
 #define ANOMALY_05000230 (0)
+#define ANOMALY_05000231 (0)
+#define ANOMALY_05000233 (0)
+#define ANOMALY_05000234 (0)
+#define ANOMALY_05000242 (0)
+#define ANOMALY_05000248 (0)
 #define ANOMALY_05000266 (0)
+#define ANOMALY_05000274 (0)
+#define ANOMALY_05000287 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
+#define ANOMALY_05000389 (0)
+#define ANOMALY_05000400 (0)
 #define ANOMALY_05000412 (0)
+#define ANOMALY_05000430 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
+#define ANOMALY_05000456 (0)
+#define ANOMALY_05000450 (0)
+#define ANOMALY_05000465 (0)
+#define ANOMALY_05000467 (0)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,6 @@
 #define BF537_FAMILY
 
 #include "bf537.h"
-#include "mem_map.h"
 #include "defBF534.h"
 #include "anomaly.h"
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/include/mach/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/include/mach/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,38 +1,16 @@
 /*
- * file:         include/asm-blackfin/mach-bf537/mem_map.h
- * based on:
- * author:
- *
- * created:
- * description:
- *	Memory MAP Common header file for blackfin BF537/6/4 of processors.
- * rev:
- *
- * modified:
- *
- * bugs:         enter bugs at http://blackfin.uclinux.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, 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.
+ * BF537 memory map
  *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_537_H_
-#define _MEM_MAP_537_H_
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
 
-#define COREMMR_BASE           0xFFE00000	 /* Core MMRs */
-#define SYSMMR_BASE            0xFFC00000	 /* System MMRs */
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
 
 /* Async Memory Banks */
 #define ASYNC_BANK3_BASE	0x20300000	 /* Async Bank 3 */
@@ -166,20 +144,4 @@
 
 #endif
 
-/* Level 2 Memory - none */
-
-#define L2_START	0
-#define L2_LENGTH	0
-
-/* Scratch Pad Memory */
-
-#define L1_SCRATCH_START	0xFFB00000
-#define L1_SCRATCH_LENGTH	0x1000
-
-#define GET_PDA_SAFE(preg)		\
-	preg.l = _cpu_pda;		\
-	preg.h = _cpu_pda;
-
-#define GET_PDA(preg, dreg)	GET_PDA_SAFE(preg)
-
-#endif				/* _MEM_MAP_537_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf537/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf537/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -66,6 +66,7 @@
 	default 11
 config IRQ_TIMER0
 	int "IRQ_TIMER0"
+	default 7 if TICKSOURCE_GPTMR0
 	default 8
 config IRQ_TIMER1
 	int "IRQ_TIMER1"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/boards/ezkit.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/boards/ezkit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/boards/ezkit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/boards/ezkit.c	2009-09-09 18:13:59.000000000 -0400
@@ -352,6 +352,11 @@
 	[1] = {
 		.start = CH_SPI0,
 		.end   = CH_SPI0,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI0,
+		.end   = IRQ_SPI0,
 		.flags = IORESOURCE_IRQ,
 	}
 };
@@ -366,6 +371,11 @@
 	[1] = {
 		.start = CH_SPI1,
 		.end   = CH_SPI1,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI1,
+		.end   = IRQ_SPI1,
 		.flags = IORESOURCE_IRQ,
 	}
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/anomaly.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/anomaly.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/anomaly.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/anomaly.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,7 +6,7 @@
  * Licensed under the GPL-2 or later.
  */
 
-/* This file shoule be up to date with:
+/* This file should be up to date with:
  *  - Revision G, 09/18/2008; ADSP-BF538/BF538F Blackfin Processor Anomaly List
  *  - Revision L, 09/18/2008; ADSP-BF539/BF539F Blackfin Processor Anomaly List
  */
@@ -14,8 +14,20 @@
 #ifndef _MACH_ANOMALY_H_
 #define _MACH_ANOMALY_H_
 
+/* We do not support old silicon - sorry */
 #if __SILICON_REVISION__ < 4
-# error will not work on BF538 silicon version 0.0, 0.1, 0.2, or 0.3
+# error will not work on BF538/BF539 silicon version 0.0, 0.1, 0.2, or 0.3
+#endif
+
+#if defined(__ADSPBF538__)
+# define ANOMALY_BF538 1
+#else
+# define ANOMALY_BF538 0
+#endif
+#if defined(__ADSPBF539__)
+# define ANOMALY_BF539 1
+#else
+# define ANOMALY_BF539 0
 #endif
 
 /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
@@ -40,13 +52,13 @@
 #define ANOMALY_05000229 (1)
 /* PPI_FS3 Is Not Driven in 2 or 3 Internal Frame Sync Transmit Modes */
 #define ANOMALY_05000233 (1)
-/* If i-cache is on, CSYNC/SSYNC/IDLE around Change of Control causes failures */
+/* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
 #define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
-/* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
 /* Maximum External Clock Speed for Timers */
 #define ANOMALY_05000253 (1)
-/* DCPLB_FAULT_ADDR MMR register may be corrupted */
+/* DCPLB_FAULT_ADDR MMR Register May Be Corrupted */
 #define ANOMALY_05000261 (__SILICON_REVISION__ < 3)
 /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */
 #define ANOMALY_05000270 (__SILICON_REVISION__ < 4)
@@ -82,12 +94,12 @@
 #define ANOMALY_05000310 (1)
 /* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
 #define ANOMALY_05000312 (__SILICON_REVISION__ < 5)
-/* PPI Is Level-Sensitive on First Transfer */
+/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */
 #define ANOMALY_05000313 (__SILICON_REVISION__ < 4)
 /* Killed System MMR Write Completes Erroneously on Next System MMR Access */
 #define ANOMALY_05000315 (__SILICON_REVISION__ < 4)
 /* PFx Glitch on Write to FIO_FLAG_D or FIO_FLAG_T */
-#define ANOMALY_05000318 (__SILICON_REVISION__ < 4)
+#define ANOMALY_05000318 (ANOMALY_BF539 && __SILICON_REVISION__ < 4)
 /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
 #define ANOMALY_05000355 (__SILICON_REVISION__ < 5)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
@@ -98,7 +110,7 @@
 #define ANOMALY_05000371 (__SILICON_REVISION__ < 5)
 /* Entering Hibernate State with Peripheral Wakeups Enabled Draws Excess Current */
 #define ANOMALY_05000374 (__SILICON_REVISION__ == 4)
-/* New Feature: Open-Drain GPIO Outputs on PC1 and PC4 (Not Available on Older Silicon) */
+/* GPIO Pins PC1 and PC4 Can Function as Normal Outputs */
 #define ANOMALY_05000375 (__SILICON_REVISION__ < 4)
 /* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
 #define ANOMALY_05000402 (__SILICON_REVISION__ < 4)
@@ -114,23 +126,55 @@
 #define ANOMALY_05000436 (__SILICON_REVISION__ > 3)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
 
 /* Anomalies that don't exist on this proc */
+#define ANOMALY_05000099 (0)
+#define ANOMALY_05000120 (0)
+#define ANOMALY_05000125 (0)
+#define ANOMALY_05000149 (0)
 #define ANOMALY_05000158 (0)
+#define ANOMALY_05000171 (0)
+#define ANOMALY_05000182 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
+#define ANOMALY_05000202 (0)
+#define ANOMALY_05000215 (0)
+#define ANOMALY_05000220 (0)
+#define ANOMALY_05000227 (0)
 #define ANOMALY_05000230 (0)
+#define ANOMALY_05000231 (0)
+#define ANOMALY_05000234 (0)
+#define ANOMALY_05000242 (0)
+#define ANOMALY_05000248 (0)
+#define ANOMALY_05000250 (0)
+#define ANOMALY_05000254 (0)
+#define ANOMALY_05000257 (0)
 #define ANOMALY_05000263 (0)
+#define ANOMALY_05000266 (0)
+#define ANOMALY_05000274 (0)
+#define ANOMALY_05000287 (0)
 #define ANOMALY_05000305 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
+#define ANOMALY_05000389 (0)
+#define ANOMALY_05000400 (0)
 #define ANOMALY_05000412 (0)
+#define ANOMALY_05000430 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
+#define ANOMALY_05000456 (0)
+#define ANOMALY_05000450 (0)
+#define ANOMALY_05000465 (0)
+#define ANOMALY_05000467 (0)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,6 @@
 #define BF538_FAMILY
 
 #include "bf538.h"
-#include "mem_map.h"
 #include "defBF539.h"
 #include "anomaly.h"
 
@@ -68,25 +67,6 @@
 #define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
 #define OFFSET_GCTL             0x24	/* Global Control Register              */
 
-
-#define bfin_write_MDMA_D0_IRQ_STATUS	bfin_write_MDMA0_D0_IRQ_STATUS
-#define bfin_write_MDMA_D0_START_ADDR   bfin_write_MDMA0_D0_START_ADDR
-#define bfin_write_MDMA_S0_START_ADDR   bfin_write_MDMA0_S0_START_ADDR
-#define bfin_write_MDMA_D0_X_COUNT      bfin_write_MDMA0_D0_X_COUNT
-#define bfin_write_MDMA_S0_X_COUNT      bfin_write_MDMA0_S0_X_COUNT
-#define bfin_write_MDMA_D0_Y_COUNT      bfin_write_MDMA0_D0_Y_COUNT
-#define bfin_write_MDMA_S0_Y_COUNT      bfin_write_MDMA0_S0_Y_COUNT
-#define bfin_write_MDMA_D0_X_MODIFY     bfin_write_MDMA0_D0_X_MODIFY
-#define bfin_write_MDMA_S0_X_MODIFY     bfin_write_MDMA0_S0_X_MODIFY
-#define bfin_write_MDMA_D0_Y_MODIFY     bfin_write_MDMA0_D0_Y_MODIFY
-#define bfin_write_MDMA_S0_Y_MODIFY     bfin_write_MDMA0_S0_Y_MODIFY
-#define bfin_write_MDMA_S0_CONFIG       bfin_write_MDMA0_S0_CONFIG
-#define bfin_write_MDMA_D0_CONFIG       bfin_write_MDMA0_D0_CONFIG
-#define bfin_read_MDMA_S0_CONFIG        bfin_read_MDMA0_S0_CONFIG
-#define bfin_read_MDMA_D0_IRQ_STATUS    bfin_read_MDMA0_D0_IRQ_STATUS
-#define bfin_write_MDMA_S0_IRQ_STATUS   bfin_write_MDMA0_S0_IRQ_STATUS
-
-
 /* DPMC*/
 #define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
 #define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/cdefBF538.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/cdefBF538.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/cdefBF538.h	2009-09-09 18:13:59.000000000 -0400
@@ -67,14 +67,14 @@
 #define bfin_write_SIC_ISR0(val)       bfin_write32(SIC_ISR0, val)
 #define bfin_read_SIC_ISR1()           bfin_read32(SIC_ISR1)
 #define bfin_write_SIC_ISR1(val)       bfin_write32(SIC_ISR1, val)
-#define bfin_read_SIC_ISR(x)	       bfin_read32(SIC_ISR0 + x * (SIC_ISR1 - SIC_ISR0))
+#define bfin_read_SIC_ISR(x)           bfin_read32(SIC_ISR0 + x * (SIC_ISR1 - SIC_ISR0))
 #define bfin_write_SIC_ISR(x, val)     bfin_write32(SIC_ISR0 + x * (SIC_ISR1 - SIC_ISR0), val)
 #define bfin_read_SIC_IWR0()           bfin_read32(SIC_IWR0)
 #define bfin_write_SIC_IWR0(val)       bfin_write32(SIC_IWR0, val)
 #define bfin_read_SIC_IWR1()           bfin_read32(SIC_IWR1)
 #define bfin_write_SIC_IWR1(val)       bfin_write32(SIC_IWR1, val)
-#define bfin_read_SIC_IWR(x)	       bfin_read32(SIC_IWR0 + x * (SIC_IWR1 - SIC_IWR0))
-#define bfin_write_SIC_IWR(x, val)     bfin_write32((SIC_IWR0 + x * (SIC_IWR1 - SIC_IWR0), val)
+#define bfin_read_SIC_IWR(x)           bfin_read32(SIC_IWR0 + x * (SIC_IWR1 - SIC_IWR0))
+#define bfin_write_SIC_IWR(x, val)     bfin_write32(SIC_IWR0 + x * (SIC_IWR1 - SIC_IWR0), val)
 #define bfin_read_SIC_IAR0()           bfin_read32(SIC_IAR0)
 #define bfin_write_SIC_IAR0(val)       bfin_write32(SIC_IAR0, val)
 #define bfin_read_SIC_IAR1()           bfin_read32(SIC_IAR1)
@@ -1247,6 +1247,65 @@
 #define bfin_write_MDMA1_S1_CURR_X_COUNT(val) bfin_write16(MDMA1_S1_CURR_X_COUNT, val)
 #define bfin_read_MDMA1_S1_CURR_Y_COUNT() bfin_read16(MDMA1_S1_CURR_Y_COUNT)
 #define bfin_write_MDMA1_S1_CURR_Y_COUNT(val) bfin_write16(MDMA1_S1_CURR_Y_COUNT, val)
+
+#define bfin_read_MDMA_S0_CONFIG()  bfin_read_MDMA0_S0_CONFIG()
+#define bfin_write_MDMA_S0_CONFIG(val) bfin_write_MDMA0_S0_CONFIG(val)
+#define bfin_read_MDMA_S0_IRQ_STATUS()  bfin_read_MDMA0_S0_IRQ_STATUS()
+#define bfin_write_MDMA_S0_IRQ_STATUS(val) bfin_write_MDMA0_S0_IRQ_STATUS(val)
+#define bfin_read_MDMA_S0_X_MODIFY()  bfin_read_MDMA0_S0_X_MODIFY()
+#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write_MDMA0_S0_X_MODIFY(val)
+#define bfin_read_MDMA_S0_Y_MODIFY()  bfin_read_MDMA0_S0_Y_MODIFY()
+#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write_MDMA0_S0_Y_MODIFY(val)
+#define bfin_read_MDMA_S0_X_COUNT()  bfin_read_MDMA0_S0_X_COUNT()
+#define bfin_write_MDMA_S0_X_COUNT(val) bfin_write_MDMA0_S0_X_COUNT(val)
+#define bfin_read_MDMA_S0_Y_COUNT()  bfin_read_MDMA0_S0_Y_COUNT()
+#define bfin_write_MDMA_S0_Y_COUNT(val) bfin_write_MDMA0_S0_Y_COUNT(val)
+#define bfin_read_MDMA_S0_START_ADDR()  bfin_read_MDMA0_S0_START_ADDR()
+#define bfin_write_MDMA_S0_START_ADDR(val) bfin_write_MDMA0_S0_START_ADDR(val)
+#define bfin_read_MDMA_D0_CONFIG()  bfin_read_MDMA0_D0_CONFIG()
+#define bfin_write_MDMA_D0_CONFIG(val) bfin_write_MDMA0_D0_CONFIG(val)
+#define bfin_read_MDMA_D0_IRQ_STATUS()  bfin_read_MDMA0_D0_IRQ_STATUS()
+#define bfin_write_MDMA_D0_IRQ_STATUS(val) bfin_write_MDMA0_D0_IRQ_STATUS(val)
+#define bfin_read_MDMA_D0_X_MODIFY()  bfin_read_MDMA0_D0_X_MODIFY()
+#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write_MDMA0_D0_X_MODIFY(val)
+#define bfin_read_MDMA_D0_Y_MODIFY()  bfin_read_MDMA0_D0_Y_MODIFY()
+#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write_MDMA0_D0_Y_MODIFY(val)
+#define bfin_read_MDMA_D0_X_COUNT()  bfin_read_MDMA0_D0_X_COUNT()
+#define bfin_write_MDMA_D0_X_COUNT(val) bfin_write_MDMA0_D0_X_COUNT(val)
+#define bfin_read_MDMA_D0_Y_COUNT()  bfin_read_MDMA0_D0_Y_COUNT()
+#define bfin_write_MDMA_D0_Y_COUNT(val) bfin_write_MDMA0_D0_Y_COUNT(val)
+#define bfin_read_MDMA_D0_START_ADDR()  bfin_read_MDMA0_D0_START_ADDR()
+#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write_MDMA0_D0_START_ADDR(val)
+
+#define bfin_read_MDMA_S1_CONFIG()  bfin_read_MDMA0_S1_CONFIG()
+#define bfin_write_MDMA_S1_CONFIG(val) bfin_write_MDMA0_S1_CONFIG(val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()  bfin_read_MDMA0_S1_IRQ_STATUS()
+#define bfin_write_MDMA_S1_IRQ_STATUS(val) bfin_write_MDMA0_S1_IRQ_STATUS(val)
+#define bfin_read_MDMA_S1_X_MODIFY()  bfin_read_MDMA0_S1_X_MODIFY()
+#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write_MDMA0_S1_X_MODIFY(val)
+#define bfin_read_MDMA_S1_Y_MODIFY()  bfin_read_MDMA0_S1_Y_MODIFY()
+#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write_MDMA0_S1_Y_MODIFY(val)
+#define bfin_read_MDMA_S1_X_COUNT()  bfin_read_MDMA0_S1_X_COUNT()
+#define bfin_write_MDMA_S1_X_COUNT(val) bfin_write_MDMA0_S1_X_COUNT(val)
+#define bfin_read_MDMA_S1_Y_COUNT()  bfin_read_MDMA0_S1_Y_COUNT()
+#define bfin_write_MDMA_S1_Y_COUNT(val) bfin_write_MDMA0_S1_Y_COUNT(val)
+#define bfin_read_MDMA_S1_START_ADDR()  bfin_read_MDMA0_S1_START_ADDR()
+#define bfin_write_MDMA_S1_START_ADDR(val) bfin_write_MDMA0_S1_START_ADDR(val)
+#define bfin_read_MDMA_D1_CONFIG()  bfin_read_MDMA0_D1_CONFIG()
+#define bfin_write_MDMA_D1_CONFIG(val) bfin_write_MDMA0_D1_CONFIG(val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()  bfin_read_MDMA0_D1_IRQ_STATUS()
+#define bfin_write_MDMA_D1_IRQ_STATUS(val) bfin_write_MDMA0_D1_IRQ_STATUS(val)
+#define bfin_read_MDMA_D1_X_MODIFY()  bfin_read_MDMA0_D1_X_MODIFY()
+#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write_MDMA0_D1_X_MODIFY(val)
+#define bfin_read_MDMA_D1_Y_MODIFY()  bfin_read_MDMA0_D1_Y_MODIFY()
+#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write_MDMA0_D1_Y_MODIFY(val)
+#define bfin_read_MDMA_D1_X_COUNT()  bfin_read_MDMA0_D1_X_COUNT()
+#define bfin_write_MDMA_D1_X_COUNT(val) bfin_write_MDMA0_D1_X_COUNT(val)
+#define bfin_read_MDMA_D1_Y_COUNT()  bfin_read_MDMA0_D1_Y_COUNT()
+#define bfin_write_MDMA_D1_Y_COUNT(val) bfin_write_MDMA0_D1_Y_COUNT(val)
+#define bfin_read_MDMA_D1_START_ADDR()  bfin_read_MDMA0_D1_START_ADDR()
+#define bfin_write_MDMA_D1_START_ADDR(val) bfin_write_MDMA0_D1_START_ADDR(val)
+
 #define bfin_read_PPI_CONTROL()        bfin_read16(PPI_CONTROL)
 #define bfin_write_PPI_CONTROL(val)    bfin_write16(PPI_CONTROL, val)
 #define bfin_read_PPI_STATUS()         bfin_read16(PPI_STATUS)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/defBF539.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/defBF539.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/defBF539.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/defBF539.h	2009-09-09 18:13:59.000000000 -0400
@@ -412,6 +412,62 @@
 #define	MDMA0_S1_CURR_X_COUNT	0xFFC00EF0	/* MemDMA0 Stream 1 Source Current X Count Register */
 #define	MDMA0_S1_CURR_Y_COUNT	0xFFC00EF8	/* MemDMA0 Stream 1 Source Current Y Count Register */
 
+#define MDMA_D0_NEXT_DESC_PTR MDMA0_D0_NEXT_DESC_PTR
+#define MDMA_D0_START_ADDR MDMA0_D0_START_ADDR
+#define MDMA_D0_CONFIG MDMA0_D0_CONFIG
+#define MDMA_D0_X_COUNT MDMA0_D0_X_COUNT
+#define MDMA_D0_X_MODIFY MDMA0_D0_X_MODIFY
+#define MDMA_D0_Y_COUNT MDMA0_D0_Y_COUNT
+#define MDMA_D0_Y_MODIFY MDMA0_D0_Y_MODIFY
+#define MDMA_D0_CURR_DESC_PTR MDMA0_D0_CURR_DESC_PTR
+#define MDMA_D0_CURR_ADDR MDMA0_D0_CURR_ADDR
+#define MDMA_D0_IRQ_STATUS MDMA0_D0_IRQ_STATUS
+#define MDMA_D0_PERIPHERAL_MAP MDMA0_D0_PERIPHERAL_MAP
+#define MDMA_D0_CURR_X_COUNT MDMA0_D0_CURR_X_COUNT
+#define MDMA_D0_CURR_Y_COUNT MDMA0_D0_CURR_Y_COUNT
+
+#define MDMA_S0_NEXT_DESC_PTR MDMA0_S0_NEXT_DESC_PTR
+#define MDMA_S0_START_ADDR MDMA0_S0_START_ADDR
+#define MDMA_S0_CONFIG MDMA0_S0_CONFIG
+#define MDMA_S0_X_COUNT MDMA0_S0_X_COUNT
+#define MDMA_S0_X_MODIFY MDMA0_S0_X_MODIFY
+#define MDMA_S0_Y_COUNT MDMA0_S0_Y_COUNT
+#define MDMA_S0_Y_MODIFY MDMA0_S0_Y_MODIFY
+#define MDMA_S0_CURR_DESC_PTR MDMA0_S0_CURR_DESC_PTR
+#define MDMA_S0_CURR_ADDR MDMA0_S0_CURR_ADDR
+#define MDMA_S0_IRQ_STATUS MDMA0_S0_IRQ_STATUS
+#define MDMA_S0_PERIPHERAL_MAP MDMA0_S0_PERIPHERAL_MAP
+#define MDMA_S0_CURR_X_COUNT MDMA0_S0_CURR_X_COUNT
+#define MDMA_S0_CURR_Y_COUNT MDMA0_S0_CURR_Y_COUNT
+
+#define MDMA_D1_NEXT_DESC_PTR MDMA0_D1_NEXT_DESC_PTR
+#define MDMA_D1_START_ADDR MDMA0_D1_START_ADDR
+#define MDMA_D1_CONFIG MDMA0_D1_CONFIG
+#define MDMA_D1_X_COUNT MDMA0_D1_X_COUNT
+#define MDMA_D1_X_MODIFY MDMA0_D1_X_MODIFY
+#define MDMA_D1_Y_COUNT MDMA0_D1_Y_COUNT
+#define MDMA_D1_Y_MODIFY MDMA0_D1_Y_MODIFY
+#define MDMA_D1_CURR_DESC_PTR MDMA0_D1_CURR_DESC_PTR
+#define MDMA_D1_CURR_ADDR MDMA0_D1_CURR_ADDR
+#define MDMA_D1_IRQ_STATUS MDMA0_D1_IRQ_STATUS
+#define MDMA_D1_PERIPHERAL_MAP MDMA0_D1_PERIPHERAL_MAP
+#define MDMA_D1_CURR_X_COUNT MDMA0_D1_CURR_X_COUNT
+#define MDMA_D1_CURR_Y_COUNT MDMA0_D1_CURR_Y_COUNT
+
+#define MDMA_S1_NEXT_DESC_PTR MDMA0_S1_NEXT_DESC_PTR
+#define MDMA_S1_START_ADDR MDMA0_S1_START_ADDR
+#define MDMA_S1_CONFIG MDMA0_S1_CONFIG
+#define MDMA_S1_X_COUNT MDMA0_S1_X_COUNT
+#define MDMA_S1_X_MODIFY MDMA0_S1_X_MODIFY
+#define MDMA_S1_Y_COUNT MDMA0_S1_Y_COUNT
+#define MDMA_S1_Y_MODIFY MDMA0_S1_Y_MODIFY
+#define MDMA_S1_CURR_DESC_PTR MDMA0_S1_CURR_DESC_PTR
+#define MDMA_S1_CURR_ADDR MDMA0_S1_CURR_ADDR
+#define MDMA_S1_IRQ_STATUS MDMA0_S1_IRQ_STATUS
+#define MDMA_S1_PERIPHERAL_MAP MDMA0_S1_PERIPHERAL_MAP
+#define MDMA_S1_CURR_X_COUNT MDMA0_S1_CURR_X_COUNT
+#define MDMA_S1_CURR_Y_COUNT MDMA0_S1_CURR_Y_COUNT
+
 
 /* Parallel Peripheral Interface (PPI) (0xFFC01000 - 0xFFC010FF) */
 #define	PPI_CONTROL			0xFFC01000	/* PPI Control Register */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/include/mach/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/include/mach/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,38 +1,16 @@
 /*
- * File:         include/asm-blackfin/mach-bf538/mem_map.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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, 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.
+ * BF538 memory map
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_538_H_
-#define _MEM_MAP_538_H_
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
 
-#define COREMMR_BASE           0xFFE00000	 /* Core MMRs */
-#define SYSMMR_BASE            0xFFC00000	 /* System MMRs */
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
 
 /* Async Memory Banks */
 #define ASYNC_BANK3_BASE	0x20300000	 /* Async Bank 3 */
@@ -93,21 +71,4 @@
 #define BFIN_DSUPBANKS	0
 #endif /*CONFIG_BFIN_DCACHE*/
 
-
-/* Level 2 Memory - none */
-
-#define L2_START	0
-#define L2_LENGTH	0
-
-/* Scratch Pad Memory */
-
-#define L1_SCRATCH_START	0xFFB00000
-#define L1_SCRATCH_LENGTH	0x1000
-
-#define GET_PDA_SAFE(preg)		\
-	preg.l = _cpu_pda;		\
-	preg.h = _cpu_pda;
-
-#define GET_PDA(preg, dreg)	GET_PDA_SAFE(preg)
-
-#endif				/* _MEM_MAP_538_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf538/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf538/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -57,6 +57,7 @@
 	default 10
 config IRQ_TIMER0
 	int "IRQ_TIMER0"
+	default 7 if TICKSOURCE_GPTMR0
 	default 8
 config IRQ_TIMER1
 	int "IRQ_TIMER1"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/boards/cm_bf548.c	2009-09-09 18:13:59.000000000 -0400
@@ -612,6 +612,11 @@
 	[1] = {
 		.start = CH_SPI0,
 		.end   = CH_SPI0,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI0,
+		.end   = IRQ_SPI0,
 		.flags = IORESOURCE_IRQ,
 	}
 };
@@ -626,6 +631,11 @@
 	[1] = {
 		.start = CH_SPI1,
 		.end   = CH_SPI1,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI1,
+		.end   = IRQ_SPI1,
 		.flags = IORESOURCE_IRQ,
 	}
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/boards/ezkit.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/boards/ezkit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/boards/ezkit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/boards/ezkit.c	2009-09-09 18:13:59.000000000 -0400
@@ -76,7 +76,6 @@
 
 static struct isp1760_platform_data isp1760_priv = {
 	.is_isp1761 = 0,
-	.port1_disable = 0,
 	.bus_width_16 = 1,
 	.port1_otg = 0,
 	.analog_oc = 0,
@@ -208,6 +207,43 @@
 };
 #endif
 
+#if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
+#include <linux/input.h>
+#include <linux/spi/adxl34x.h>
+static const struct adxl34x_platform_data adxl34x_info = {
+	.x_axis_offset = 0,
+	.y_axis_offset = 0,
+	.z_axis_offset = 0,
+	.tap_threshold = 0x31,
+	.tap_duration = 0x10,
+	.tap_latency = 0x60,
+	.tap_window = 0xF0,
+	.tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN,
+	.act_axis_control = 0xFF,
+	.activity_threshold = 5,
+	.inactivity_threshold = 3,
+	.inactivity_time = 4,
+	.free_fall_threshold = 0x7,
+	.free_fall_time = 0x20,
+	.data_rate = 0x8,
+	.data_range = ADXL_FULL_RES,
+
+	.ev_type = EV_ABS,
+	.ev_code_x = ABS_X,		/* EV_REL */
+	.ev_code_y = ABS_Y,		/* EV_REL */
+	.ev_code_z = ABS_Z,		/* EV_REL */
+
+	.ev_code_tap_x = BTN_TOUCH,		/* EV_KEY */
+	.ev_code_tap_y = BTN_TOUCH,		/* EV_KEY */
+	.ev_code_tap_z = BTN_TOUCH,		/* EV_KEY */
+
+/*	.ev_code_ff = KEY_F,*/		/* EV_KEY */
+/*	.ev_code_act_inactivity = KEY_A,*/	/* EV_KEY */
+	.power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
+	.fifo_mode = ADXL_FIFO_STREAM,
+};
+#endif
+
 #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
 static struct platform_device rtc_device = {
 	.name = "rtc-bfin",
@@ -359,6 +395,8 @@
 #endif
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+#include <linux/smsc911x.h>
+
 static struct resource smsc911x_resources[] = {
 	{
 		.name = "smsc911x-memory",
@@ -372,11 +410,22 @@
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
 	},
 };
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.flags = SMSC911X_USE_32BIT,
+	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
 static struct platform_device smsc911x_device = {
 	.name = "smsc911x",
 	.id = 0,
 	.num_resources = ARRAY_SIZE(smsc911x_resources),
 	.resource = smsc911x_resources,
+	.dev = {
+		.platform_data = &smsc911x_config,
+	},
 };
 #endif
 
@@ -628,6 +677,14 @@
 };
 #endif
 
+#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
+	.enable_dma = 0,         /* use dma transfer with this chip*/
+	.bits_per_word = 8,
+	.cs_change_per_word = 0,
+};
+#endif
+
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -653,15 +710,15 @@
 	},
 #endif
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
-{
-	.modalias		= "ad7877",
-	.platform_data		= &bfin_ad7877_ts_info,
-	.irq			= IRQ_PB4,	/* old boards (<=Rev 1.3) use IRQ_PJ11 */
-	.max_speed_hz		= 12500000,     /* max spi clock (SCK) speed in HZ */
-	.bus_num		= 0,
-	.chip_select  		= 2,
-	.controller_data = &spi_ad7877_chip_info,
-},
+	{
+		.modalias		= "ad7877",
+		.platform_data		= &bfin_ad7877_ts_info,
+		.irq			= IRQ_PB4,	/* old boards (<=Rev 1.3) use IRQ_PJ11 */
+		.max_speed_hz		= 12500000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num		= 0,
+		.chip_select  		= 2,
+		.controller_data = &spi_ad7877_chip_info,
+	},
 #endif
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
 	{
@@ -672,8 +729,19 @@
 		.controller_data = &spidev_chip_info,
 	},
 #endif
+#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
+	{
+		.modalias		= "adxl34x",
+		.platform_data		= &adxl34x_info,
+		.irq			= IRQ_PC5,
+		.max_speed_hz		= 5000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num		= 1,
+		.chip_select  		= 2,
+		.controller_data = &spi_adxl34x_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
 };
-
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
 /* SPI (0) */
 static struct resource bfin_spi0_resource[] = {
@@ -685,6 +753,11 @@
 	[1] = {
 		.start = CH_SPI0,
 		.end   = CH_SPI0,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI0,
+		.end   = IRQ_SPI0,
 		.flags = IORESOURCE_IRQ,
 	}
 };
@@ -699,6 +772,11 @@
 	[1] = {
 		.start = CH_SPI1,
 		.end   = CH_SPI1,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI1,
+		.end   = IRQ_SPI1,
 		.flags = IORESOURCE_IRQ,
 	}
 };
@@ -786,7 +864,7 @@
 
 #if !defined(CONFIG_BF542)	/* The BF542 only has 1 TWI */
 static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
-#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
 	{
 		I2C_BOARD_INFO("pcf8574_lcd", 0x22),
 	},
@@ -797,6 +875,13 @@
 		.irq = 212,
 	},
 #endif
+#if defined(CONFIG_INPUT_ADXL34X_I2C) || defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
+	{
+		I2C_BOARD_INFO("adxl34x", 0x53),
+		.irq = IRQ_PC5,
+		.platform_data = (void *)&adxl34x_info,
+	},
+#endif
 };
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,36 +6,41 @@
  * Licensed under the GPL-2 or later.
  */
 
-/* This file shoule be up to date with:
+/* This file should be up to date with:
  *  - Revision H, 01/16/2009; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 #define _MACH_ANOMALY_H_
 
+/* We do not support 0.0 or 0.1 silicon - sorry */
+#if __SILICON_REVISION__ < 2
+# error will not work on BF548 silicon version 0.0, or 0.1
+#endif
+
 /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
 /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
 #define ANOMALY_05000119 (1)
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
-/* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (1)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
 /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
 #define ANOMALY_05000272 (1)
-/* False Hardware Error Exception when ISR context is not restored */
+/* False Hardware Error Exception when ISR Context Is Not Restored */
 #define ANOMALY_05000281 (__SILICON_REVISION__ < 1)
 /* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
 #define ANOMALY_05000304 (__SILICON_REVISION__ < 1)
 /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
 #define ANOMALY_05000310 (1)
-/* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
 #define ANOMALY_05000312 (__SILICON_REVISION__ < 1)
 /* TWI Slave Boot Mode Is Not Functional */
 #define ANOMALY_05000324 (__SILICON_REVISION__ < 1)
-/* External FIFO Boot Mode Is Not Functional */
+/* FIFO Boot Mode Not Functional */
 #define ANOMALY_05000325 (__SILICON_REVISION__ < 2)
 /* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */
 #define ANOMALY_05000327 (__SILICON_REVISION__ < 1)
@@ -59,7 +64,7 @@
 #define ANOMALY_05000340 (__SILICON_REVISION__ < 1)
 /* Boot Host Wait (HWAIT) and Boot Host Wait Alternate (HWAITA) Signals Are Swapped */
 #define ANOMALY_05000344 (__SILICON_REVISION__ < 1)
-/* USB Calibration Value Is Not Intialized */
+/* USB Calibration Value Is Not Initialized */
 #define ANOMALY_05000346 (__SILICON_REVISION__ < 1)
 /* USB Calibration Value to use */
 #define ANOMALY_05000346_value 0x5411
@@ -147,11 +152,11 @@
 #define ANOMALY_05000416 (1)
 /* Multichannel SPORT Channel Misalignment Under Specific Configuration */
 #define ANOMALY_05000425 (1)
-/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
 #define ANOMALY_05000426 (1)
 /* CORE_EPPI_PRIO bit and SYS_EPPI_PRIO bit in the HMDMA1_CONTROL register are not functional */
 #define ANOMALY_05000427 (__SILICON_REVISION__ < 2)
-/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Behaves as a Buffer Status Bit Instead of an IRQ Status Bit */
+/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Reflects Buffer Status Instead of IRQ Status */
 #define ANOMALY_05000429 (__SILICON_REVISION__ < 2)
 /* Software System Reset Corrupts PLL_LOCKCNT Register */
 #define ANOMALY_05000430 (__SILICON_REVISION__ >= 2)
@@ -170,26 +175,61 @@
 /* Reduced Timing Margins on DDR Output Setup and Hold (tDS and tDH) */
 #define ANOMALY_05000449 (__SILICON_REVISION__ == 1)
 /* USB DMA Mode 1 Short Packet Data Corruption */
-#define ANOMALY_05000450 (1
+#define ANOMALY_05000450 (1)
+/* USB Receive Interrupt Is Not Generated in DMA Mode 1 */
+#define ANOMALY_05000456 (__SILICON_REVISION__ < 3)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
+/* USB Rx DMA hang */
+#define ANOMALY_05000465 (1)
+/* Possible RX data corruption when control & data EP FIFOs are accessed via the core */
+#define ANOMALY_05000467 (1)
 
 /* Anomalies that don't exist on this proc */
+#define ANOMALY_05000099 (0)
+#define ANOMALY_05000120 (0)
 #define ANOMALY_05000125 (0)
+#define ANOMALY_05000149 (0)
 #define ANOMALY_05000158 (0)
+#define ANOMALY_05000171 (0)
+#define ANOMALY_05000179 (0)
+#define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
+#define ANOMALY_05000202 (0)
+#define ANOMALY_05000215 (0)
+#define ANOMALY_05000220 (0)
+#define ANOMALY_05000227 (0)
 #define ANOMALY_05000230 (0)
+#define ANOMALY_05000231 (0)
+#define ANOMALY_05000233 (0)
+#define ANOMALY_05000234 (0)
+#define ANOMALY_05000242 (0)
 #define ANOMALY_05000244 (0)
+#define ANOMALY_05000248 (0)
+#define ANOMALY_05000250 (0)
+#define ANOMALY_05000254 (0)
+#define ANOMALY_05000257 (0)
 #define ANOMALY_05000261 (0)
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000274 (0)
 #define ANOMALY_05000278 (0)
+#define ANOMALY_05000283 (0)
+#define ANOMALY_05000287 (0)
+#define ANOMALY_05000301 (0)
 #define ANOMALY_05000305 (0)
 #define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
+#define ANOMALY_05000315 (0)
 #define ANOMALY_05000323 (0)
+#define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
+#define ANOMALY_05000400 (0)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,6 @@
 #define _MACH_BLACKFIN_H_
 
 #include "bf548.h"
-#include "mem_map.h"
 #include "anomaly.h"
 
 #ifdef CONFIG_BF542
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,38 +1,16 @@
 /*
- * file:         include/asm-blackfin/mach-bf548/mem_map.h
- * based on:
- * author:
- *
- * created:
- * description:
- *	Memory MAP Common header file for blackfin BF537/6/4 of processors.
- * rev:
- *
- * modified:
- *
- * bugs:         enter bugs at http://blackfin.uclinux.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, 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.
+ * BF548 memory map
  *
- * you should have received a copy of the gnu general public license
- * along with this program; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_548_H_
-#define _MEM_MAP_548_H_
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
 
-#define COREMMR_BASE           0xFFE00000	 /* Core MMRs */
-#define SYSMMR_BASE            0xFFC00000	 /* System MMRs */
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
 
 /* Async Memory Banks */
 #define ASYNC_BANK3_BASE	0x2C000000	 /* Async Bank 3 */
@@ -103,15 +81,4 @@
 # define L2_LENGTH          0x20000
 #endif
 
-/* Scratch Pad Memory */
-
-#define L1_SCRATCH_START	0xFFB00000
-#define L1_SCRATCH_LENGTH	0x1000
-
-#define GET_PDA_SAFE(preg)		\
-	preg.l = _cpu_pda;		\
-	preg.h = _cpu_pda;
-
-#define GET_PDA(preg, dreg)	GET_PDA_SAFE(preg)
-
-#endif/* _MEM_MAP_548_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/portmux.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/portmux.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/include/mach/portmux.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/include/mach/portmux.h	2009-09-09 18:13:59.000000000 -0400
@@ -167,22 +167,42 @@
 #define P_PPI0_D13	(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
 #define P_PPI0_D14	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
 #define P_PPI0_D15	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
-#define P_ATAPI_D0A	(P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
-#define P_ATAPI_D1A	(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
-#define P_ATAPI_D2A	(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
-#define P_ATAPI_D3A	(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
-#define P_ATAPI_D4A	(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
-#define P_ATAPI_D5A	(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
-#define P_ATAPI_D6A	(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
-#define P_ATAPI_D7A	(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
-#define P_ATAPI_D8A	(P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
-#define P_ATAPI_D9A	(P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
-#define P_ATAPI_D10A	(P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
-#define P_ATAPI_D11A	(P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
-#define P_ATAPI_D12A	(P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
-#define P_ATAPI_D13A	(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
-#define P_ATAPI_D14A	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
-#define P_ATAPI_D15A	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#ifdef CONFIG_BF548_ATAPI_ALTERNATIVE_PORT
+# define P_ATAPI_D0A	(P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+# define P_ATAPI_D1A	(P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+# define P_ATAPI_D2A	(P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+# define P_ATAPI_D3A	(P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+# define P_ATAPI_D4A	(P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+# define P_ATAPI_D5A	(P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+# define P_ATAPI_D6A	(P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+# define P_ATAPI_D7A	(P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+# define P_ATAPI_D8A	(P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+# define P_ATAPI_D9A	(P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+# define P_ATAPI_D10A	(P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
+# define P_ATAPI_D11A	(P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
+# define P_ATAPI_D12A	(P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
+# define P_ATAPI_D13A	(P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
+# define P_ATAPI_D14A	(P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+# define P_ATAPI_D15A	(P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+#else
+# define P_ATAPI_D0A	(P_DONTCARE)
+# define P_ATAPI_D1A	(P_DONTCARE)
+# define P_ATAPI_D2A	(P_DONTCARE)
+# define P_ATAPI_D3A	(P_DONTCARE)
+# define P_ATAPI_D4A	(P_DONTCARE)
+# define P_ATAPI_D5A	(P_DONTCARE)
+# define P_ATAPI_D6A	(P_DONTCARE)
+# define P_ATAPI_D7A	(P_DONTCARE)
+# define P_ATAPI_D8A	(P_DONTCARE)
+# define P_ATAPI_D9A	(P_DONTCARE)
+# define P_ATAPI_D10A	(P_DONTCARE)
+# define P_ATAPI_D11A	(P_DONTCARE)
+# define P_ATAPI_D12A	(P_DONTCARE)
+# define P_ATAPI_D13A	(P_DONTCARE)
+# define P_ATAPI_D14A	(P_DONTCARE)
+# define P_ATAPI_D15A	(P_DONTCARE)
+#endif
 
 #define P_PPI0_CLK	(P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
 #define P_PPI0_FS1	(P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
@@ -200,9 +220,15 @@
 #define P_CAN0_RX	(P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
 #define P_CAN1_TX	(P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
 #define P_CAN1_RX	(P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
-#define P_ATAPI_A0A	(P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(1))
-#define P_ATAPI_A1A	(P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
-#define P_ATAPI_A2A	(P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#ifdef CONFIG_BF548_ATAPI_ALTERNATIVE_PORT
+# define P_ATAPI_A0A	(P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(1))
+# define P_ATAPI_A1A	(P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
+# define P_ATAPI_A2A	(P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#else
+# define P_ATAPI_A0A	(P_DONTCARE)
+# define P_ATAPI_A1A	(P_DONTCARE)
+# define P_ATAPI_A2A	(P_DONTCARE)
+#endif
 #define P_HOST_CE	(P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
 #define P_HOST_RD	(P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
 #define P_HOST_WR	(P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf548/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf548/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,13 @@
 	help
 	  Treat any DEB1, DEB2 and DEB3 request as Urgent
 
+config BF548_ATAPI_ALTERNATIVE_PORT
+	bool "BF548 ATAPI alternative port via GPIO"
+	help
+	  BF548 ATAPI data and address PINs can be routed through
+	  async address or GPIO port F and G. Select y to route it
+	  to GPIO.
+
 comment "Interrupt Priority Assignment"
 menu "Priority"
 
@@ -250,6 +257,7 @@
 	default 11
 config IRQ_TIMER0
 	int "IRQ_TIMER0"
+	default 7 if TICKSOURCE_GPTMR0
 	default 8
 config IRQ_TIMER1
 	int "IRQ_TIMER1"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c	2009-09-09 18:13:59.000000000 -0400
@@ -83,7 +83,7 @@
 };
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
 	.enable_dma = 1,         /* use dma transfer with this chip*/
@@ -126,7 +126,7 @@
 	},
 #endif
 
-#if defined(CONFIG_SPI_ADC_BF533) || defined(CONFIG_SPI_ADC_BF533_MODULE)
+#if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 	{
 		.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
 		.max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
@@ -177,8 +177,13 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
-	}
+	},
 };
 
 /* SPI controller data */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/boards/ezkit.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/boards/ezkit.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/boards/ezkit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/boards/ezkit.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,7 +62,6 @@
 
 static struct isp1760_platform_data isp1760_priv = {
 	.is_isp1761 = 0,
-	.port1_disable = 0,
 	.bus_width_16 = 1,
 	.port1_otg = 0,
 	.analog_oc = 0,
@@ -304,6 +303,11 @@
 	[1] = {
 		.start = CH_SPI,
 		.end   = CH_SPI,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = IRQ_SPI,
+		.end   = IRQ_SPI,
 		.flags = IORESOURCE_IRQ,
 	}
 };
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/coreb.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/coreb.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/coreb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/coreb.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,406 +1,74 @@
-/*
- * File:         arch/blackfin/mach-bf561/coreb.c
- * Based on:
- * Author:
- *
- * Created:
- * Description:  Handle CoreB on a BF561
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.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 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.
+/* Load firmware into Core B on a BF561
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+/* The Core B reset func requires code in the application that is loaded into
+ * Core B.  In order to reset, the application needs to install an interrupt
+ * handler for Supplemental Interrupt 0, that sets RETI to 0xff600000 and
+ * writes bit 11 of SICB_SYSCR when bit 5 of SICA_SYSCR is 0.  This causes Core
+ * B to stall when Supplemental Interrupt 0 is set, and will reset PC to
+ * 0xff600000 when COREB_SRAM_INIT is cleared.
  */
 
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
 #include <linux/device.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <asm/dma.h>
-#include <asm/cacheflush.h>
-
-#define MODULE_VER		"v0.1"
-
-static spinlock_t coreb_lock;
-static wait_queue_head_t coreb_dma_wait;
-
-#define COREB_IS_OPEN		0x00000001
-#define COREB_IS_RUNNING	0x00000010
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
 
-#define CMD_COREB_INDEX		1
 #define CMD_COREB_START		2
 #define CMD_COREB_STOP		3
 #define CMD_COREB_RESET		4
 
-#define COREB_MINOR		229
-
-static unsigned long coreb_status = 0;
-static unsigned long coreb_base = 0xff600000;
-static unsigned long coreb_size = 0x4000;
-int coreb_dma_done;
-
-static loff_t coreb_lseek(struct file *file, loff_t offset, int origin);
-static ssize_t coreb_read(struct file *file, char *buf, size_t count,
-			  loff_t * ppos);
-static ssize_t coreb_write(struct file *file, const char *buf, size_t count,
-			   loff_t * ppos);
-static int coreb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-		       unsigned long arg);
-static int coreb_open(struct inode *inode, struct file *file);
-static int coreb_release(struct inode *inode, struct file *file);
-
-static irqreturn_t coreb_dma_interrupt(int irq, void *dev_id)
-{
-	clear_dma_irqstat(CH_MEM_STREAM2_DEST);
-	coreb_dma_done = 1;
-	wake_up_interruptible(&coreb_dma_wait);
-	return IRQ_HANDLED;
-}
-
-static ssize_t coreb_write(struct file *file, const char *buf, size_t count,
-			   loff_t * ppos)
-{
-	unsigned long p = *ppos;
-	ssize_t wrote = 0;
-
-	if (p + count > coreb_size)
-		return -EFAULT;
-
-	while (count > 0) {
-		int len = count;
-
-		if (len > PAGE_SIZE)
-			len = PAGE_SIZE;
-
-		coreb_dma_done = 0;
-
-		flush_dcache_range((unsigned long)buf, (unsigned long)(buf+len));
-		/* Source Channel */
-		set_dma_start_addr(CH_MEM_STREAM2_SRC, (unsigned long)buf);
-		set_dma_x_count(CH_MEM_STREAM2_SRC, len);
-		set_dma_x_modify(CH_MEM_STREAM2_SRC, sizeof(char));
-		set_dma_config(CH_MEM_STREAM2_SRC, 0);
-		/* Destination Channel */
-		set_dma_start_addr(CH_MEM_STREAM2_DEST, coreb_base + p);
-		set_dma_x_count(CH_MEM_STREAM2_DEST, len);
-		set_dma_x_modify(CH_MEM_STREAM2_DEST, sizeof(char));
-		set_dma_config(CH_MEM_STREAM2_DEST, WNR | RESTART | DI_EN);
-
-		enable_dma(CH_MEM_STREAM2_SRC);
-		enable_dma(CH_MEM_STREAM2_DEST);
-
-		wait_event_interruptible(coreb_dma_wait, coreb_dma_done);
-
-		disable_dma(CH_MEM_STREAM2_SRC);
-		disable_dma(CH_MEM_STREAM2_DEST);
-
-		count -= len;
-		wrote += len;
-		buf += len;
-		p += len;
-	}
-	*ppos = p;
-	return wrote;
-}
-
-static ssize_t coreb_read(struct file *file, char *buf, size_t count,
-			  loff_t * ppos)
-{
-	unsigned long p = *ppos;
-	ssize_t read = 0;
-
-	if ((p + count) > coreb_size)
-		return -EFAULT;
-
-	while (count > 0) {
-		int len = count;
-
-		if (len > PAGE_SIZE)
-			len = PAGE_SIZE;
-
-		coreb_dma_done = 0;
-
-		invalidate_dcache_range((unsigned long)buf, (unsigned long)(buf+len));
-		/* Source Channel */
-		set_dma_start_addr(CH_MEM_STREAM2_SRC, coreb_base + p);
-		set_dma_x_count(CH_MEM_STREAM2_SRC, len);
-		set_dma_x_modify(CH_MEM_STREAM2_SRC, sizeof(char));
-		set_dma_config(CH_MEM_STREAM2_SRC, 0);
-		/* Destination Channel */
-		set_dma_start_addr(CH_MEM_STREAM2_DEST, (unsigned long)buf);
-		set_dma_x_count(CH_MEM_STREAM2_DEST, len);
-		set_dma_x_modify(CH_MEM_STREAM2_DEST, sizeof(char));
-		set_dma_config(CH_MEM_STREAM2_DEST, WNR | RESTART | DI_EN);
-
-		enable_dma(CH_MEM_STREAM2_SRC);
-		enable_dma(CH_MEM_STREAM2_DEST);
-
-		wait_event_interruptible(coreb_dma_wait, coreb_dma_done);
-
-		disable_dma(CH_MEM_STREAM2_SRC);
-		disable_dma(CH_MEM_STREAM2_DEST);
-
-		count -= len;
-		read += len;
-		buf += len;
-		p += len;
-	}
-
-	return read;
-}
-
-static loff_t coreb_lseek(struct file *file, loff_t offset, int origin)
-{
-	loff_t ret;
-
-	mutex_lock(&file->f_dentry->d_inode->i_mutex);
-
-	switch (origin) {
-	case 0 /* SEEK_SET */ :
-		if (offset < coreb_size) {
-			file->f_pos = offset;
-			ret = file->f_pos;
-		} else
-			ret = -EINVAL;
-		break;
-	case 1 /* SEEK_CUR */ :
-		if ((offset + file->f_pos) < coreb_size) {
-			file->f_pos += offset;
-			ret = file->f_pos;
-		} else
-			ret = -EINVAL;
-	default:
-		ret = -EINVAL;
-	}
-	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
-	return ret;
-}
-
-/* No BKL needed here */
-static int coreb_open(struct inode *inode, struct file *file)
-{
-	spin_lock_irq(&coreb_lock);
-
-	if (coreb_status & COREB_IS_OPEN)
-		goto out_busy;
-
-	coreb_status |= COREB_IS_OPEN;
-
-	spin_unlock_irq(&coreb_lock);
-	return 0;
-
- out_busy:
-	spin_unlock_irq(&coreb_lock);
-	return -EBUSY;
-}
-
-static int coreb_release(struct inode *inode, struct file *file)
-{
-	spin_lock_irq(&coreb_lock);
-	coreb_status &= ~COREB_IS_OPEN;
-	spin_unlock_irq(&coreb_lock);
-	return 0;
-}
-
-static int coreb_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg)
+static int
+coreb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	int retval = 0;
-	int coreb_index = 0;
+	int ret = 0;
 
 	switch (cmd) {
-	case CMD_COREB_INDEX:
-		if (copy_from_user(&coreb_index, (int *)arg, sizeof(int))) {
-			retval = -EFAULT;
-			break;
-		}
-
-		spin_lock_irq(&coreb_lock);
-		switch (coreb_index) {
-		case 0:
-			coreb_base = 0xff600000;
-			coreb_size = 0x4000;
-			break;
-		case 1:
-			coreb_base = 0xff610000;
-			coreb_size = 0x4000;
-			break;
-		case 2:
-			coreb_base = 0xff500000;
-			coreb_size = 0x8000;
-			break;
-		case 3:
-			coreb_base = 0xff400000;
-			coreb_size = 0x8000;
-			break;
-		default:
-			retval = -EINVAL;
-			break;
-		}
-		spin_unlock_irq(&coreb_lock);
-
-		mutex_lock(&file->f_dentry->d_inode->i_mutex);
-		file->f_pos = 0;
-		mutex_unlock(&file->f_dentry->d_inode->i_mutex);
-		break;
 	case CMD_COREB_START:
-		spin_lock_irq(&coreb_lock);
-		if (coreb_status & COREB_IS_RUNNING) {
-			retval = -EBUSY;
-			break;
-		}
-		printk(KERN_INFO "Starting Core B\n");
-		coreb_status |= COREB_IS_RUNNING;
 		bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~0x0020);
-		SSYNC();
-		spin_unlock_irq(&coreb_lock);
 		break;
-#if defined(CONFIG_BF561_COREB_RESET)
 	case CMD_COREB_STOP:
-		spin_lock_irq(&coreb_lock);
-		printk(KERN_INFO "Stopping Core B\n");
 		bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() | 0x0020);
 		bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080);
-		coreb_status &= ~COREB_IS_RUNNING;
-		spin_unlock_irq(&coreb_lock);
 		break;
 	case CMD_COREB_RESET:
-		printk(KERN_INFO "Resetting Core B\n");
 		bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080);
 		break;
-#endif
+	default:
+		ret = -EINVAL;
+		break;
 	}
 
-	return retval;
+	CSYNC();
+
+	return ret;
 }
 
 static struct file_operations coreb_fops = {
-	.owner = THIS_MODULE,
-	.llseek = coreb_lseek,
-	.read = coreb_read,
-	.write = coreb_write,
-	.ioctl = coreb_ioctl,
-	.open = coreb_open,
-	.release = coreb_release
+	.owner   = THIS_MODULE,
+	.ioctl   = coreb_ioctl,
 };
 
 static struct miscdevice coreb_dev = {
-	COREB_MINOR,
-	"coreb",
-	&coreb_fops
+	.minor = MISC_DYNAMIC_MINOR,
+	.name  = "coreb",
+	.fops  = &coreb_fops,
 };
 
-static ssize_t coreb_show_status(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf,
-		       "Base Address:\t0x%08lx\n"
-		       "Core B is %s\n"
-		       "SICA_SYSCR:\t%04x\n"
-		       "SICB_SYSCR:\t%04x\n"
-		       "\n"
-		       "IRQ Status:\tCore A\t\tCore B\n"
-		       "ISR0:\t\t%08x\t\t%08x\n"
-		       "ISR1:\t\t%08x\t\t%08x\n"
-		       "IMASK0:\t\t%08x\t\t%08x\n"
-		       "IMASK1:\t\t%08x\t\t%08x\n",
-		       coreb_base,
-		       coreb_status & COREB_IS_RUNNING ? "running" : "stalled",
-		       bfin_read_SICA_SYSCR(), bfin_read_SICB_SYSCR(),
-		       bfin_read_SICA_ISR0(), bfin_read_SICB_ISR0(),
-		       bfin_read_SICA_ISR1(), bfin_read_SICB_ISR0(),
-		       bfin_read_SICA_IMASK0(), bfin_read_SICB_IMASK0(),
-		       bfin_read_SICA_IMASK1(), bfin_read_SICB_IMASK1());
-}
-
-static DEVICE_ATTR(coreb_status, S_IRUGO, coreb_show_status, NULL);
-
-int __init bf561_coreb_init(void)
+static int __init bf561_coreb_init(void)
 {
-	init_waitqueue_head(&coreb_dma_wait);
-
-	spin_lock_init(&coreb_lock);
-	/* Request the core memory regions for Core B */
-	if (request_mem_region(0xff600000, 0x4000,
-			       "Core B - Instruction SRAM") == NULL)
-		goto exit;
-
-	if (request_mem_region(0xFF610000, 0x4000,
-			       "Core B - Instruction SRAM") == NULL)
-		goto release_instruction_a_sram;
-
-	if (request_mem_region(0xFF500000, 0x8000,
-			       "Core B - Data Bank B SRAM") == NULL)
-		goto release_instruction_b_sram;
-
-	if (request_mem_region(0xff400000, 0x8000,
-			       "Core B - Data Bank A SRAM") == NULL)
-		goto release_data_b_sram;
-
-	if (request_dma(CH_MEM_STREAM2_DEST, "Core B - DMA Destination") < 0)
-		goto release_data_a_sram;
-
-	if (request_dma(CH_MEM_STREAM2_SRC, "Core B - DMA Source") < 0)
-		goto release_dma_dest;
-
-	set_dma_callback(CH_MEM_STREAM2_DEST, coreb_dma_interrupt, NULL);
-
-	misc_register(&coreb_dev);
-
-	if (device_create_file(coreb_dev.this_device, &dev_attr_coreb_status))
-		goto release_dma_src;
-
-	printk(KERN_INFO "BF561 Core B driver %s initialized.\n", MODULE_VER);
-	return 0;
-
- release_dma_src:
-	free_dma(CH_MEM_STREAM2_SRC);
- release_dma_dest:
-	free_dma(CH_MEM_STREAM2_DEST);
- release_data_a_sram:
-	release_mem_region(0xff400000, 0x8000);
- release_data_b_sram:
-	release_mem_region(0xff500000, 0x8000);
- release_instruction_b_sram:
-	release_mem_region(0xff610000, 0x4000);
- release_instruction_a_sram:
-	release_mem_region(0xff600000, 0x4000);
- exit:
-	return -ENOMEM;
+	return misc_register(&coreb_dev);
 }
+module_init(bf561_coreb_init);
 
-void __exit bf561_coreb_exit(void)
+static void __exit bf561_coreb_exit(void)
 {
-	device_remove_file(coreb_dev.this_device, &dev_attr_coreb_status);
 	misc_deregister(&coreb_dev);
-
-	release_mem_region(0xff610000, 0x4000);
-	release_mem_region(0xff600000, 0x4000);
-	release_mem_region(0xff500000, 0x8000);
-	release_mem_region(0xff400000, 0x8000);
-
-	free_dma(CH_MEM_STREAM2_DEST);
-	free_dma(CH_MEM_STREAM2_SRC);
 }
-
-module_init(bf561_coreb_init);
 module_exit(bf561_coreb_exit);
 
 MODULE_AUTHOR("Bas Vermeulen <bvermeul@blackstar.xs4all.nl>");
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/anomaly.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/anomaly.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/anomaly.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/anomaly.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,7 +6,7 @@
  * Licensed under the GPL-2 or later.
  */
 
-/* This file shoule be up to date with:
+/* This file should be up to date with:
  *  - Revision Q, 11/07/2008; ADSP-BF561 Blackfin Processor Anomaly List
  */
 
@@ -18,19 +18,19 @@
 # error will not work on BF561 silicon version 0.0, 0.1, 0.2, or 0.4
 #endif
 
-/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot 2 Not Supported */
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
 /* UART Line Status Register (UART_LSR) Bits Are Not Updated at the Same Time */
 #define ANOMALY_05000099 (__SILICON_REVISION__ < 5)
-/* Trace Buffers may contain errors in emulation mode and/or exception, NMI, reset handlers */
+/* Trace Buffers May Contain Errors in Emulation Mode and/or Exception, NMI, Reset Handlers */
 #define ANOMALY_05000116 (__SILICON_REVISION__ < 3)
-/* Testset instructions restricted to 32-bit aligned memory locations */
+/* TESTSET Instructions Restricted to 32-Bit Aligned Memory Locations */
 #define ANOMALY_05000120 (1)
 /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
 #define ANOMALY_05000122 (1)
-/* Erroneous exception when enabling cache */
+/* Erroneous Exception when Enabling Cache */
 #define ANOMALY_05000125 (__SILICON_REVISION__ < 3)
-/* Signbits instruction not functional under certain conditions */
+/* SIGNBITS Instruction Not Functional under Certain Conditions */
 #define ANOMALY_05000127 (1)
 /* Two bits in the Watchpoint Status Register (WPSTAT) are swapped */
 #define ANOMALY_05000134 (__SILICON_REVISION__ < 3)
@@ -52,7 +52,7 @@
 #define ANOMALY_05000146 (__SILICON_REVISION__ < 3)
 /* Source MDMA descriptor may stop with a DMA Error near beginning of descriptor fetch */
 #define ANOMALY_05000147 (__SILICON_REVISION__ < 3)
-/* IMDMA S1/D1 channel may stall */
+/* IMDMA S1/D1 Channel May Stall */
 #define ANOMALY_05000149 (1)
 /* DMA engine may lose data due to incorrect handshaking */
 #define ANOMALY_05000150 (__SILICON_REVISION__ < 3)
@@ -66,7 +66,7 @@
 #define ANOMALY_05000154 (__SILICON_REVISION__ < 3)
 /* Timers in PWM-Out Mode with PPI GP Receive (Input) Mode with 0 Frame Syncs */
 #define ANOMALY_05000156 (__SILICON_REVISION__ < 4)
-/* Killed 32-bit MMR write leads to next system MMR access thinking it should be 32-bit */
+/* Killed 32-Bit MMR Write Leads to Next System MMR Access Thinking It Should Be 32-Bit */
 #define ANOMALY_05000157 (__SILICON_REVISION__ < 3)
 /* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1, or 1:1 */
 #define ANOMALY_05000159 (__SILICON_REVISION__ < 3)
@@ -76,17 +76,17 @@
 #define ANOMALY_05000161 (__SILICON_REVISION__ < 3)
 /* DMEM_CONTROL<12> is not set on Reset */
 #define ANOMALY_05000162 (__SILICON_REVISION__ < 3)
-/* SPORT transmit data is not gated by external frame sync in certain conditions */
+/* SPORT Transmit Data Is Not Gated by External Frame Sync in Certain Conditions */
 #define ANOMALY_05000163 (__SILICON_REVISION__ < 3)
-/* PPI Data Lengths Between 8 and 16 Do Not Zero Out Upper Bits */
+/* PPI Data Lengths between 8 and 16 Do Not Zero Out Upper Bits */
 #define ANOMALY_05000166 (1)
-/* Turning Serial Ports on with External Frame Syncs */
+/* Turning SPORTs on while External Frame Sync Is Active May Corrupt Data */
 #define ANOMALY_05000167 (1)
-/* SDRAM auto-refresh and subsequent Power Ups */
+/* Undefined Behavior when Power-Up Sequence Is Issued to SDRAM during Auto-Refresh */
 #define ANOMALY_05000168 (__SILICON_REVISION__ < 5)
-/* DATA CPLB page miss can result in lost write-through cache data writes */
+/* DATA CPLB Page Miss Can Result in Lost Write-Through Data Cache Writes */
 #define ANOMALY_05000169 (__SILICON_REVISION__ < 5)
-/* Boot-ROM code modifies SICA_IWRx wakeup registers */
+/* Boot-ROM Modifies SICA_IWRx Wakeup Registers */
 #define ANOMALY_05000171 (__SILICON_REVISION__ < 5)
 /* DSPID register values incorrect */
 #define ANOMALY_05000172 (__SILICON_REVISION__ < 3)
@@ -96,29 +96,29 @@
 #define ANOMALY_05000174 (__SILICON_REVISION__ < 5)
 /* Overlapping Sequencer and Memory Stalls */
 #define ANOMALY_05000175 (__SILICON_REVISION__ < 5)
-/* Multiplication of (-1) by (-1) followed by an accumulator saturation */
+/* Overflow Bit Asserted when Multiplication of -1 by -1 Followed by Accumulator Saturation */
 #define ANOMALY_05000176 (__SILICON_REVISION__ < 5)
 /* PPI_COUNT Cannot Be Programmed to 0 in General Purpose TX or RX Modes */
 #define ANOMALY_05000179 (__SILICON_REVISION__ < 5)
 /* PPI_DELAY Not Functional in PPI Modes with 0 Frame Syncs */
 #define ANOMALY_05000180 (1)
-/* Disabling the PPI resets the PPI configuration registers */
+/* Disabling the PPI Resets the PPI Configuration Registers */
 #define ANOMALY_05000181 (__SILICON_REVISION__ < 5)
-/* IMDMA does not operate to full speed for 600MHz and higher devices */
+/* Internal Memory DMA Does Not Operate at Full Speed */
 #define ANOMALY_05000182 (1)
-/* Timer Pin limitations for PPI TX Modes with External Frame Syncs */
+/* Timer Pin Limitations for PPI TX Modes with External Frame Syncs */
 #define ANOMALY_05000184 (__SILICON_REVISION__ < 5)
-/* PPI TX Mode with 2 External Frame Syncs */
+/* Early PPI Transmit when FS1 Asserts before FS2 in TX Mode with 2 External Frame Syncs */
 #define ANOMALY_05000185 (__SILICON_REVISION__ < 5)
-/* PPI packing with Data Length greater than 8 bits (not a meaningful mode) */
+/* Upper PPI Pins Driven when PPI Packing Enabled and Data Length >8 Bits */
 #define ANOMALY_05000186 (__SILICON_REVISION__ < 5)
 /* IMDMA Corrupted Data after a Halt */
 #define ANOMALY_05000187 (1)
 /* IMDMA Restrictions on Descriptor and Buffer Placement in Memory */
 #define ANOMALY_05000188 (__SILICON_REVISION__ < 5)
-/* False Protection Exceptions */
+/* False Protection Exceptions when Speculative Fetch Is Cancelled */
 #define ANOMALY_05000189 (__SILICON_REVISION__ < 5)
-/* PPI not functional at core voltage < 1Volt */
+/* PPI Not Functional at Core Voltage < 1Volt */
 #define ANOMALY_05000190 (1)
 /* PPI does not invert the Driving PPICLK edge in Transmit Modes */
 #define ANOMALY_05000191 (__SILICON_REVISION__ < 3)
@@ -126,7 +126,7 @@
 #define ANOMALY_05000193 (__SILICON_REVISION__ < 5)
 /* Restarting SPORT in Specific Modes May Cause Data Corruption */
 #define ANOMALY_05000194 (__SILICON_REVISION__ < 5)
-/* Failing MMR Accesses When Stalled by Preceding Memory Read */
+/* Failing MMR Accesses when Preceding Memory Read Stalls */
 #define ANOMALY_05000198 (__SILICON_REVISION__ < 5)
 /* Current DMA Address Shows Wrong Value During Carry Fix */
 #define ANOMALY_05000199 (__SILICON_REVISION__ < 5)
@@ -134,9 +134,9 @@
 #define ANOMALY_05000200 (__SILICON_REVISION__ < 5)
 /* Possible Infinite Stall with Specific Dual-DAG Situation */
 #define ANOMALY_05000202 (__SILICON_REVISION__ < 5)
-/* Incorrect data read with write-through cache and allocate cache lines on reads only mode */
+/* Incorrect Data Read with Writethrough "Allocate Cache Lines on Reads Only" Cache Mode */
 #define ANOMALY_05000204 (__SILICON_REVISION__ < 5)
-/* Specific sequence that can cause DMA error or DMA stopping */
+/* Specific Sequence that Can Cause DMA Error or DMA Stopping */
 #define ANOMALY_05000205 (__SILICON_REVISION__ < 5)
 /* Recovery from "Brown-Out" Condition */
 #define ANOMALY_05000207 (__SILICON_REVISION__ < 5)
@@ -158,15 +158,15 @@
 #define ANOMALY_05000230 (__SILICON_REVISION__ < 5)
 /* UART STB Bit Incorrectly Affects Receiver Setting */
 #define ANOMALY_05000231 (__SILICON_REVISION__ < 5)
-/* SPORT data transmit lines are incorrectly driven in multichannel mode */
+/* SPORT Data Transmit Lines Are Incorrectly Driven in Multichannel Mode */
 #define ANOMALY_05000232 (__SILICON_REVISION__ < 5)
 /* DF Bit in PLL_CTL Register Does Not Respond to Hardware Reset */
 #define ANOMALY_05000242 (__SILICON_REVISION__ < 5)
 /* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
 #define ANOMALY_05000244 (__SILICON_REVISION__ < 5)
-/* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
 #define ANOMALY_05000245 (__SILICON_REVISION__ < 5)
-/* TESTSET operation forces stall on the other core */
+/* TESTSET Operation Forces Stall on the Other Core */
 #define ANOMALY_05000248 (__SILICON_REVISION__ < 5)
 /* Incorrect Bit Shift of Data Word in Multichannel (TDM) Mode in Certain Conditions */
 #define ANOMALY_05000250 (__SILICON_REVISION__ > 2 && __SILICON_REVISION__ < 5)
@@ -192,9 +192,9 @@
 #define ANOMALY_05000264 (__SILICON_REVISION__ < 5)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (__SILICON_REVISION__ < 5)
-/* IMDMA destination IRQ status must be read prior to using IMDMA */
+/* IMDMA Destination IRQ Status Must Be Read Prior to Using IMDMA */
 #define ANOMALY_05000266 (__SILICON_REVISION__ > 3)
-/* IMDMA may corrupt data under certain conditions */
+/* IMDMA May Corrupt Data under Certain Conditions */
 #define ANOMALY_05000267 (1)
 /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Increase */
 #define ANOMALY_05000269 (1)
@@ -202,27 +202,27 @@
 #define ANOMALY_05000270 (1)
 /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
 #define ANOMALY_05000272 (1)
-/* Data cache write back to external synchronous memory may be lost */
+/* Data Cache Write Back to External Synchronous Memory May Be Lost */
 #define ANOMALY_05000274 (1)
 /* PPI Timing and Sampling Information Updates */
 #define ANOMALY_05000275 (__SILICON_REVISION__ > 2)
 /* Timing Requirements Change for External Frame Sync PPI Modes with Non-Zero PPI_DELAY */
 #define ANOMALY_05000276 (__SILICON_REVISION__ < 5)
-/* Writes to an I/O data register one SCLK cycle after an edge is detected may clear interrupt */
+/* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
 #define ANOMALY_05000277 (__SILICON_REVISION__ < 3)
 /* Disabling Peripherals with DMA Running May Cause DMA System Instability */
 #define ANOMALY_05000278 (__SILICON_REVISION__ < 5)
-/* False Hardware Error Exception When ISR Context Is Not Restored */
+/* False Hardware Error Exception when ISR Context Is Not Restored */
 #define ANOMALY_05000281 (__SILICON_REVISION__ < 5)
-/* System MMR Write Is Stalled Indefinitely When Killed in a Particular Stage */
+/* System MMR Write Is Stalled Indefinitely when Killed in a Particular Stage */
 #define ANOMALY_05000283 (1)
-/* A read will receive incorrect data under certain conditions */
+/* Reads Will Receive Incorrect Data under Certain Conditions */
 #define ANOMALY_05000287 (__SILICON_REVISION__ < 5)
 /* SPORTs May Receive Bad Data If FIFOs Fill Up */
 #define ANOMALY_05000288 (__SILICON_REVISION__ < 5)
 /* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
 #define ANOMALY_05000301 (1)
-/* SSYNCs After Writes To DMA MMR Registers May Not Be Handled Correctly */
+/* SSYNCs after Writes to DMA MMR Registers May Not Be Handled Correctly */
 #define ANOMALY_05000302 (1)
 /* SPORT_HYS Bit in PLL_CTL Register Is Not Functional */
 #define ANOMALY_05000305 (__SILICON_REVISION__ < 5)
@@ -230,25 +230,25 @@
 #define ANOMALY_05000307 (__SILICON_REVISION__ < 5)
 /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
 #define ANOMALY_05000310 (1)
-/* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
 #define ANOMALY_05000312 (1)
-/* PPI Is Level-Sensitive on First Transfer */
+/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */
 #define ANOMALY_05000313 (1)
-/* Killed System MMR Write Completes Erroneously On Next System MMR Access */
+/* Killed System MMR Write Completes Erroneously on Next System MMR Access */
 #define ANOMALY_05000315 (1)
-/* PF2 Output Remains Asserted After SPI Master Boot */
+/* PF2 Output Remains Asserted after SPI Master Boot */
 #define ANOMALY_05000320 (__SILICON_REVISION__ > 3)
-/* Erroneous GPIO Flag Pin Operations Under Specific Sequences */
+/* Erroneous GPIO Flag Pin Operations under Specific Sequences */
 #define ANOMALY_05000323 (1)
-/* SPORT Secondary Receive Channel Not Functional When Word Length Exceeds 16 Bits */
+/* SPORT Secondary Receive Channel Not Functional when Word Length >16 Bits */
 #define ANOMALY_05000326 (__SILICON_REVISION__ > 3)
-/* New Feature: 24-Bit SPI Boot Mode Support (Not Available On Older Silicon) */
+/* 24-Bit SPI Boot Mode Is Not Functional */
 #define ANOMALY_05000331 (__SILICON_REVISION__ < 5)
-/* New Feature: Slave SPI Boot Mode Supported (Not Available On Older Silicon) */
+/* Slave SPI Boot Mode Is Not Functional */
 #define ANOMALY_05000332 (__SILICON_REVISION__ < 5)
-/* Flag Data Register Writes One SCLK Cycle After Edge Is Detected May Clear Interrupt Status */
+/* Flag Data Register Writes One SCLK Cycle after Edge Is Detected May Clear Interrupt Status */
 #define ANOMALY_05000333 (__SILICON_REVISION__ < 5)
-/* New Feature: Additional PPI Frame Sync Sampling Options (Not Available on Older Silicon) */
+/* ALT_TIMING Bit in PLL_CTL Register Is Not Functional */
 #define ANOMALY_05000339 (__SILICON_REVISION__ < 5)
 /* Memory DMA FIFO Causes Throughput Degradation on Writes to External Memory */
 #define ANOMALY_05000343 (__SILICON_REVISION__ < 5)
@@ -276,18 +276,31 @@
 #define ANOMALY_05000428 (__SILICON_REVISION__ > 3)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
 #define ANOMALY_05000443 (1)
+/* False Hardware Error when RETI Points to Invalid Memory */
+#define ANOMALY_05000461 (1)
 
 /* Anomalies that don't exist on this proc */
+#define ANOMALY_05000119 (0)
 #define ANOMALY_05000158 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000233 (0)
+#define ANOMALY_05000234 (0)
 #define ANOMALY_05000273 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
+#define ANOMALY_05000389 (0)
+#define ANOMALY_05000400 (0)
+#define ANOMALY_05000430 (0)
 #define ANOMALY_05000432 (0)
 #define ANOMALY_05000435 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
+#define ANOMALY_05000456 (0)
+#define ANOMALY_05000450 (0)
+#define ANOMALY_05000465 (0)
+#define ANOMALY_05000467 (0)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/blackfin.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/blackfin.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/blackfin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/blackfin.h	2009-09-09 18:13:59.000000000 -0400
@@ -34,7 +34,6 @@
 #define BF561_FAMILY
 
 #include "bf561.h"
-#include "mem_map.h"
 #include "defBF561.h"
 #include "anomaly.h"
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/cdefBF561.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/cdefBF561.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/cdefBF561.h	2009-09-09 18:13:59.000000000 -0400
@@ -1526,6 +1526,35 @@
 #define bfin_read_MDMA_D0_START_ADDR()  bfin_read_MDMA1_D0_START_ADDR()
 #define bfin_write_MDMA_D0_START_ADDR(val) bfin_write_MDMA1_D0_START_ADDR(val)
 
+#define bfin_read_MDMA_S1_CONFIG()  bfin_read_MDMA1_S1_CONFIG()
+#define bfin_write_MDMA_S1_CONFIG(val) bfin_write_MDMA1_S1_CONFIG(val)
+#define bfin_read_MDMA_S1_IRQ_STATUS()  bfin_read_MDMA1_S1_IRQ_STATUS()
+#define bfin_write_MDMA_S1_IRQ_STATUS(val) bfin_write_MDMA1_S1_IRQ_STATUS(val)
+#define bfin_read_MDMA_S1_X_MODIFY()  bfin_read_MDMA1_S1_X_MODIFY()
+#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write_MDMA1_S1_X_MODIFY(val)
+#define bfin_read_MDMA_S1_Y_MODIFY()  bfin_read_MDMA1_S1_Y_MODIFY()
+#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write_MDMA1_S1_Y_MODIFY(val)
+#define bfin_read_MDMA_S1_X_COUNT()  bfin_read_MDMA1_S1_X_COUNT()
+#define bfin_write_MDMA_S1_X_COUNT(val) bfin_write_MDMA1_S1_X_COUNT(val)
+#define bfin_read_MDMA_S1_Y_COUNT()  bfin_read_MDMA1_S1_Y_COUNT()
+#define bfin_write_MDMA_S1_Y_COUNT(val) bfin_write_MDMA1_S1_Y_COUNT(val)
+#define bfin_read_MDMA_S1_START_ADDR()  bfin_read_MDMA1_S1_START_ADDR()
+#define bfin_write_MDMA_S1_START_ADDR(val) bfin_write_MDMA1_S1_START_ADDR(val)
+#define bfin_read_MDMA_D1_CONFIG()  bfin_read_MDMA1_D1_CONFIG()
+#define bfin_write_MDMA_D1_CONFIG(val) bfin_write_MDMA1_D1_CONFIG(val)
+#define bfin_read_MDMA_D1_IRQ_STATUS()  bfin_read_MDMA1_D1_IRQ_STATUS()
+#define bfin_write_MDMA_D1_IRQ_STATUS(val) bfin_write_MDMA1_D1_IRQ_STATUS(val)
+#define bfin_read_MDMA_D1_X_MODIFY()  bfin_read_MDMA1_D1_X_MODIFY()
+#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write_MDMA1_D1_X_MODIFY(val)
+#define bfin_read_MDMA_D1_Y_MODIFY()  bfin_read_MDMA1_D1_Y_MODIFY()
+#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write_MDMA1_D1_Y_MODIFY(val)
+#define bfin_read_MDMA_D1_X_COUNT()  bfin_read_MDMA1_D1_X_COUNT()
+#define bfin_write_MDMA_D1_X_COUNT(val) bfin_write_MDMA1_D1_X_COUNT(val)
+#define bfin_read_MDMA_D1_Y_COUNT()  bfin_read_MDMA1_D1_Y_COUNT()
+#define bfin_write_MDMA_D1_Y_COUNT(val) bfin_write_MDMA1_D1_Y_COUNT(val)
+#define bfin_read_MDMA_D1_START_ADDR()  bfin_read_MDMA1_D1_START_ADDR()
+#define bfin_write_MDMA_D1_START_ADDR(val) bfin_write_MDMA1_D1_START_ADDR(val)
+
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/defBF561.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/defBF561.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/defBF561.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/defBF561.h	2009-09-09 18:13:59.000000000 -0400
@@ -796,6 +796,62 @@
 #define MDMA2_S1_IRQ_STATUS 0xFFC00FE8	/*MemDMA2 Stream 1 Source Interrupt/Status Register */
 #define MDMA2_S1_PERIPHERAL_MAP 0xFFC00FEC	/*MemDMA2 Stream 1 Source Peripheral Map register */
 
+#define MDMA_D0_NEXT_DESC_PTR MDMA1_D0_NEXT_DESC_PTR
+#define MDMA_D0_START_ADDR MDMA1_D0_START_ADDR
+#define MDMA_D0_CONFIG MDMA1_D0_CONFIG
+#define MDMA_D0_X_COUNT MDMA1_D0_X_COUNT
+#define MDMA_D0_X_MODIFY MDMA1_D0_X_MODIFY
+#define MDMA_D0_Y_COUNT MDMA1_D0_Y_COUNT
+#define MDMA_D0_Y_MODIFY MDMA1_D0_Y_MODIFY
+#define MDMA_D0_CURR_DESC_PTR MDMA1_D0_CURR_DESC_PTR
+#define MDMA_D0_CURR_ADDR MDMA1_D0_CURR_ADDR
+#define MDMA_D0_IRQ_STATUS MDMA1_D0_IRQ_STATUS
+#define MDMA_D0_PERIPHERAL_MAP MDMA1_D0_PERIPHERAL_MAP
+#define MDMA_D0_CURR_X_COUNT MDMA1_D0_CURR_X_COUNT
+#define MDMA_D0_CURR_Y_COUNT MDMA1_D0_CURR_Y_COUNT
+
+#define MDMA_S0_NEXT_DESC_PTR MDMA1_S0_NEXT_DESC_PTR
+#define MDMA_S0_START_ADDR MDMA1_S0_START_ADDR
+#define MDMA_S0_CONFIG MDMA1_S0_CONFIG
+#define MDMA_S0_X_COUNT MDMA1_S0_X_COUNT
+#define MDMA_S0_X_MODIFY MDMA1_S0_X_MODIFY
+#define MDMA_S0_Y_COUNT MDMA1_S0_Y_COUNT
+#define MDMA_S0_Y_MODIFY MDMA1_S0_Y_MODIFY
+#define MDMA_S0_CURR_DESC_PTR MDMA1_S0_CURR_DESC_PTR
+#define MDMA_S0_CURR_ADDR MDMA1_S0_CURR_ADDR
+#define MDMA_S0_IRQ_STATUS MDMA1_S0_IRQ_STATUS
+#define MDMA_S0_PERIPHERAL_MAP MDMA1_S0_PERIPHERAL_MAP
+#define MDMA_S0_CURR_X_COUNT MDMA1_S0_CURR_X_COUNT
+#define MDMA_S0_CURR_Y_COUNT MDMA1_S0_CURR_Y_COUNT
+
+#define MDMA_D1_NEXT_DESC_PTR MDMA1_D1_NEXT_DESC_PTR
+#define MDMA_D1_START_ADDR MDMA1_D1_START_ADDR
+#define MDMA_D1_CONFIG MDMA1_D1_CONFIG
+#define MDMA_D1_X_COUNT MDMA1_D1_X_COUNT
+#define MDMA_D1_X_MODIFY MDMA1_D1_X_MODIFY
+#define MDMA_D1_Y_COUNT MDMA1_D1_Y_COUNT
+#define MDMA_D1_Y_MODIFY MDMA1_D1_Y_MODIFY
+#define MDMA_D1_CURR_DESC_PTR MDMA1_D1_CURR_DESC_PTR
+#define MDMA_D1_CURR_ADDR MDMA1_D1_CURR_ADDR
+#define MDMA_D1_IRQ_STATUS MDMA1_D1_IRQ_STATUS
+#define MDMA_D1_PERIPHERAL_MAP MDMA1_D1_PERIPHERAL_MAP
+#define MDMA_D1_CURR_X_COUNT MDMA1_D1_CURR_X_COUNT
+#define MDMA_D1_CURR_Y_COUNT MDMA1_D1_CURR_Y_COUNT
+
+#define MDMA_S1_NEXT_DESC_PTR MDMA1_S1_NEXT_DESC_PTR
+#define MDMA_S1_START_ADDR MDMA1_S1_START_ADDR
+#define MDMA_S1_CONFIG MDMA1_S1_CONFIG
+#define MDMA_S1_X_COUNT MDMA1_S1_X_COUNT
+#define MDMA_S1_X_MODIFY MDMA1_S1_X_MODIFY
+#define MDMA_S1_Y_COUNT MDMA1_S1_Y_COUNT
+#define MDMA_S1_Y_MODIFY MDMA1_S1_Y_MODIFY
+#define MDMA_S1_CURR_DESC_PTR MDMA1_S1_CURR_DESC_PTR
+#define MDMA_S1_CURR_ADDR MDMA1_S1_CURR_ADDR
+#define MDMA_S1_IRQ_STATUS MDMA1_S1_IRQ_STATUS
+#define MDMA_S1_PERIPHERAL_MAP MDMA1_S1_PERIPHERAL_MAP
+#define MDMA_S1_CURR_X_COUNT MDMA1_S1_CURR_X_COUNT
+#define MDMA_S1_CURR_Y_COUNT MDMA1_S1_CURR_Y_COUNT
+
 /* Internal Memory DMA Registers (0xFFC0_1800 - 0xFFC0_19FF) */
 #define IMDMA_D0_CONFIG 0xFFC01808	/*IMDMA Stream 0 Destination Configuration */
 #define IMDMA_D0_NEXT_DESC_PTR 0xFFC01800	/*IMDMA Stream 0 Destination Next Descriptor Ptr Reg */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/mem_map.h linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/mem_map.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/include/mach/mem_map.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/include/mach/mem_map.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,13 +1,16 @@
 /*
- * Memory MAP
- * Common header file for blackfin BF561 of processors.
+ * BF561 memory map
+ *
+ * Copyright 2004-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
  */
 
-#ifndef _MEM_MAP_561_H_
-#define _MEM_MAP_561_H_
+#ifndef __BFIN_MACH_MEM_MAP_H__
+#define __BFIN_MACH_MEM_MAP_H__
 
-#define COREMMR_BASE           0xFFE00000	 /* Core MMRs */
-#define SYSMMR_BASE            0xFFC00000	 /* System MMRs */
+#ifndef __BFIN_MEM_MAP_H__
+# error "do not include mach/mem_map.h directly -- use asm/mem_map.h"
+#endif
 
 /* Async Memory Banks */
 #define ASYNC_BANK3_BASE	0x2C000000	 /* Async Bank 3 */
@@ -34,7 +37,6 @@
 
 /* Memory Map for ADSP-BF561 processors */
 
-#ifdef CONFIG_BF561
 #define COREA_L1_CODE_START       0xFFA00000
 #define COREA_L1_DATA_A_START     0xFF800000
 #define COREA_L1_DATA_B_START     0xFF900000
@@ -71,6 +73,28 @@
 #define BFIN_DCACHESIZE	(0*1024)
 #define BFIN_DSUPBANKS	0
 #endif /*CONFIG_BFIN_DCACHE*/
+
+/*
+ * If we are in SMP mode, then the cache settings of Core B will match
+ * the settings of Core A.  If we aren't, then we assume Core B is not
+ * using any cache.  This allows the rest of the kernel to work with
+ * the core in either mode as we are only loading user code into it and
+ * it is the user's problem to make sure they aren't doing something
+ * stupid there.
+ *
+ * Note that we treat the L1 code region as a contiguous blob to make
+ * the rest of the kernel simpler.  Easier to check one region than a
+ * bunch of small ones.  Again, possible misbehavior here is the fault
+ * of the user -- don't try to use memory that doesn't exist.
+ */
+#ifdef CONFIG_SMP
+# define COREB_L1_CODE_LENGTH     L1_CODE_LENGTH
+# define COREB_L1_DATA_A_LENGTH   L1_DATA_A_LENGTH
+# define COREB_L1_DATA_B_LENGTH   L1_DATA_B_LENGTH
+#else
+# define COREB_L1_CODE_LENGTH     0x14000
+# define COREB_L1_DATA_A_LENGTH   0x8000
+# define COREB_L1_DATA_B_LENGTH   0x8000
 #endif
 
 /* Level 2 Memory */
@@ -82,9 +106,6 @@
 #define COREA_L1_SCRATCH_START	0xFFB00000
 #define COREB_L1_SCRATCH_START	0xFF700000
 
-#define L1_SCRATCH_START	COREA_L1_SCRATCH_START
-#define L1_SCRATCH_LENGTH	0x1000
-
 #ifdef __ASSEMBLY__
 
 /*
@@ -155,14 +176,42 @@
 	dreg = ROT dreg BY -1;		\
 	dreg = CC;
 
-#else
-#define GET_PDA_SAFE(preg)		\
-	preg.l = _cpu_pda;		\
-	preg.h = _cpu_pda;
+static inline unsigned long get_l1_scratch_start_cpu(int cpu)
+{
+	return cpu ? COREB_L1_SCRATCH_START : COREA_L1_SCRATCH_START;
+}
+static inline unsigned long get_l1_code_start_cpu(int cpu)
+{
+	return cpu ? COREB_L1_CODE_START : COREA_L1_CODE_START;
+}
+static inline unsigned long get_l1_data_a_start_cpu(int cpu)
+{
+	return cpu ? COREB_L1_DATA_A_START : COREA_L1_DATA_A_START;
+}
+static inline unsigned long get_l1_data_b_start_cpu(int cpu)
+{
+	return cpu ? COREB_L1_DATA_B_START : COREA_L1_DATA_B_START;
+}
+
+static inline unsigned long get_l1_scratch_start(void)
+{
+	return get_l1_scratch_start_cpu(blackfin_core_id());
+}
+static inline unsigned long get_l1_code_start(void)
+{
+	return get_l1_code_start_cpu(blackfin_core_id());
+}
+static inline unsigned long get_l1_data_a_start(void)
+{
+	return get_l1_data_a_start_cpu(blackfin_core_id());
+}
+static inline unsigned long get_l1_data_b_start(void)
+{
+	return get_l1_data_b_start_cpu(blackfin_core_id());
+}
 
-#define GET_PDA(preg, dreg)	GET_PDA_SAFE(preg)
 #endif /* CONFIG_SMP */
 
 #endif /* __ASSEMBLY__ */
 
-#endif				/* _MEM_MAP_533_H_ */
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/Kconfig linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/Kconfig
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -9,22 +9,9 @@
 comment "Core B Support"
 
 config BF561_COREB
-	bool "Enable Core B support"
+	bool "Enable Core B loader"
 	default y
 
-config BF561_COREB_RESET
-	bool "Enable Core B reset support"
-	default n
-	help
-	  This requires code in the application that is loaded
-	  into Core B. In order to reset, the application needs
-	  to install an interrupt handler for Supplemental
-	  Interrupt 0, that sets RETI to 0xff600000 and writes
-	  bit 11 of SICB_SYSCR when bit 5 of SICA_SYSCR is 0.
-	  This causes Core B to stall when Supplemental Interrupt
-	  0 is set, and will reset PC to 0xff600000 when
-	  COREB_SRAM_INIT is cleared.
-
 endif
 
 comment "Interrupt Priority Assignment"
@@ -138,6 +125,7 @@
 	default 9
 config IRQ_TIMER0
 	int "TIMER 0  Interrupt"
+	default 7 if TICKSOURCE_GPTMR0
 	default 8
 config IRQ_TIMER1
 	int "TIMER 1  Interrupt"
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/smp.c linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/smp.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-bf561/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-bf561/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,9 +133,9 @@
 	int ret;
 
 	ret = request_irq(IRQ_SUPPLE_0, handler, IRQF_DISABLED,
-			  "SMP interrupt", handler);
+			  "Supplemental Interrupt0", handler);
 	if (ret)
-		panic("Cannot request supplemental interrupt 0 for IPI service\n");
+		panic("Cannot request supplemental interrupt 0 for IPI service");
 }
 
 void platform_send_ipi(cpumask_t callmap)
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/arch_checks.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/arch_checks.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/arch_checks.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/arch_checks.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,3 +71,10 @@
 #if ANOMALY_05000448
 # error You are using a part with anomaly 05000448, this issue causes random memory read/write failures - that means random crashes.
 #endif
+
+/* if 220 exists, can not set External Memory WB and L2 not_cached, either External Memory not_cached and L2 WB */
+#if ANOMALY_05000220 && \
+	((defined(CONFIG_BFIN_EXTMEM_WRITEBACK) && !defined(CONFIG_BFIN_L2_DCACHEABLE)) || \
+	 (!defined(CONFIG_BFIN_EXTMEM_DCACHEABLE) && defined(CONFIG_BFIN_L2_WRITEBACK)))
+# error You are exposing Anomaly 220 in this config, either config L2 as Write Through, or make External Memory WB.
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/cache-c.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/cache-c.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/cache-c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/cache-c.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,9 +16,21 @@
 void blackfin_invalidate_entire_dcache(void)
 {
 	u32 dmem = bfin_read_DMEM_CONTROL();
-	SSYNC();
 	bfin_write_DMEM_CONTROL(dmem & ~0xc);
 	SSYNC();
 	bfin_write_DMEM_CONTROL(dmem);
 	SSYNC();
 }
+
+/* Invalidate the Entire Instruction cache by
+ * clearing IMC bit
+ */
+void blackfin_invalidate_entire_icache(void)
+{
+	u32 imem = bfin_read_IMEM_CONTROL();
+	bfin_write_IMEM_CONTROL(imem & ~0x4);
+	SSYNC();
+	bfin_write_IMEM_CONTROL(imem);
+	SSYNC();
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/cache.S linux-libre-2.6.31-gnu/arch/blackfin/mach-common/cache.S
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/cache.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/cache.S	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,13 @@
 
 .text
 
+/* 05000443 - IFLUSH cannot be last instruction in hardware loop */
+#if ANOMALY_05000443
+# define BROK_FLUSH_INST "IFLUSH"
+#else
+# define BROK_FLUSH_INST "no anomaly! yeah!"
+#endif
+
 /* Since all L1 caches work the same way, we use the same method for flushing
  * them.  Only the actual flush instruction differs.  We write this in asm as
  * GCC can be hard to coax into writing nice hardware loops.
@@ -23,7 +30,7 @@
  * R0 = start address
  * R1 = end address
  */
-.macro do_flush flushins:req optflushins optnopins label
+.macro do_flush flushins:req label
 
 	R2 = -L1_CACHE_BYTES;
 
@@ -44,22 +51,15 @@
 \label :
 .endif
 	P0 = R0;
+
 	LSETUP (1f, 2f) LC1 = P1;
 1:
-.ifnb \optflushins
-	\optflushins [P0];
-.endif
-#if ANOMALY_05000443
-.ifb \optnopins
-2:
-.endif
+.ifeqs "\flushins", BROK_FLUSH_INST
 	\flushins [P0++];
-.ifnb \optnopins
-2:	\optnopins;
-.endif
-#else
+2:	nop;
+.else
 2:	\flushins [P0++];
-#endif
+.endif
 
 	RTS;
 .endm
@@ -77,25 +77,9 @@
  */
 	P0 = R0;
 	IFLUSH[P0];
-	do_flush IFLUSH, , nop
+	do_flush IFLUSH
 ENDPROC(_blackfin_icache_flush_range)
 
-/* Flush all cache lines assocoiated with this area of memory. */
-ENTRY(_blackfin_icache_dcache_flush_range)
-/*
- * Walkaround to avoid loading wrong instruction after invalidating icache
- * and following sequence is met.
- *
- * 1) One instruction address is cached in the instruction cache.
- * 2) This instruction in SDRAM is changed.
- * 3) IFLASH[P0] is executed only once in blackfin_icache_flush_range().
- * 4) This instruction is executed again, but the old one is loaded.
- */
-	P0 = R0;
-	IFLUSH[P0];
-	do_flush FLUSH, IFLUSH
-ENDPROC(_blackfin_icache_dcache_flush_range)
-
 /* Throw away all D-cached data in specified region without any obligation to
  * write them back.  Since the Blackfin ISA does not have an "invalidate"
  * instruction, we use flush/invalidate.  Perhaps as a speed optimization we
@@ -107,7 +91,7 @@
 
 /* Flush all data cache lines assocoiated with this memory area */
 ENTRY(_blackfin_dcache_flush_range)
-	do_flush FLUSH, , , .Ldfr
+	do_flush FLUSH, .Ldfr
 ENDPROC(_blackfin_dcache_flush_range)
 
 /* Our headers convert the page structure to an address, so just need to flush
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/clocks-init.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/clocks-init.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/clocks-init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/clocks-init.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,6 +72,7 @@
 #endif
 	bfin_write_PLL_LOCKCNT(0x300);
 	do_sync();
+	/* We always write PLL_CTL thus avoiding Anomaly 05000242 */
 	bfin_write16(PLL_CTL, PLL_CTL_VAL);
 	__asm__ __volatile__("IDLE;");
 	bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/cpufreq.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/cpufreq.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/cpufreq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/cpufreq.c	2009-09-09 18:13:59.000000000 -0400
@@ -140,7 +140,8 @@
 	cclk = get_cclk() / 1000;
 	sclk = get_sclk() / 1000;
 
-#if ANOMALY_05000273 || (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_DCACHE))
+#if ANOMALY_05000273 || ANOMALY_05000274 || \
+	(!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE))
 	min_cclk = sclk * 2;
 #else
 	min_cclk = sclk;
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/entry.S linux-libre-2.6.31-gnu/arch/blackfin/mach-common/entry.S
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -36,13 +36,13 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/unistd.h>
-#include <linux/threads.h>
 #include <asm/blackfin.h>
 #include <asm/errno.h>
 #include <asm/fixed_code.h>
 #include <asm/thread_info.h>  /* TIF_NEED_RESCHED */
 #include <asm/asm-offsets.h>
 #include <asm/trace.h>
+#include <asm/traps.h>
 
 #include <asm/context.S>
 
@@ -85,13 +85,15 @@
 	if !cc jump _bfin_return_from_exception;
 	/* fall through */
 	R7 = P4;
-	R6 = 0x26;	/* Data CPLB Miss */
+	R6 = VEC_CPLB_M;	/* Data CPLB Miss */
 	cc = R6 == R7;
 	if cc jump _ex_dcplb_miss (BP);
-	R6 = 0x23;	/* Data CPLB Miss */
+#ifdef CONFIG_MPU
+	R6 = VEC_CPLB_VL;	/* Data CPLB Violation */
 	cc = R6 == R7;
 	if cc jump _ex_dcplb_viol (BP);
-	/* Handle 0x23 Data CPLB Protection Violation
+#endif
+	/* Handle Data CPLB Protection Violation
 	 * and Data CPLB Multiple Hits - Linux Trap Zero
 	 */
 	jump _ex_trap_c;
@@ -201,11 +203,22 @@
 	cc = r7 == 0;
 	if !cc jump 1f;
 #endif
-
+#ifdef CONFIG_EXACT_HWERR
+	/* Read the ILAT, and to check to see if the process we are
+	 * single stepping caused a previous hardware error
+	 * If so, do not single step, (which lowers to IRQ5, and makes
+	 * us miss the error).
+	 */
+	p5.l = lo(ILAT);
+	p5.h = hi(ILAT);
+	r7 = [p5];
+	cc = bittst(r7, EVT_IVHW_P);
+	if cc jump 1f;
+#endif
 	/* Single stepping only a single instruction, so clear the trace
 	 * bit here.  */
 	r7 = syscfg;
-	bitclr (r7, 0);
+	bitclr (r7, SYSCFG_SSSTEP_P);
 	syscfg = R7;
 	jump _ex_trap_c;
 
@@ -238,7 +251,7 @@
 	if !cc jump _bfin_return_from_exception;
 
 	r7 = syscfg;
-	bitclr (r7, 0);
+	bitclr (r7, SYSCFG_SSSTEP_P);	/* Turn off single step */
 	syscfg = R7;
 
 	/* Fall through to _bfin_return_from_exception.  */
@@ -260,16 +273,7 @@
 	r6.l = lo(SEQSTAT_EXCAUSE);
 	r6.h = hi(SEQSTAT_EXCAUSE);
 	r7 = r7 & r6;
-	r6 = 0x25;
-	CC = R7 == R6;
-	if CC JUMP _double_fault;
-
-	/* Did we cause a HW error? */
-	p5.l = lo(ILAT);
-	p5.h = hi(ILAT);
-	r6 = [p5];
-	r7 = 0x20;		/* Did I just cause anther HW error? */
-	r6 = r7 & r6;
+	r6 = VEC_UNCOV;
 	CC = R7 == R6;
 	if CC JUMP _double_fault;
 #endif
@@ -338,9 +342,11 @@
 	r6 = retx;
 	[p5 + PDA_RETX] = r6;
 #endif
+	/* Save the state of single stepping */
 	r6 = SYSCFG;
 	[p5 + PDA_SYSCFG] = r6;
-	BITCLR(r6, 0);
+	/* Clear it while we handle the exception in IRQ5 mode */
+	BITCLR(r6, SYSCFG_SSSTEP_P);
 	SYSCFG = r6;
 
 	/* Disable all interrupts, but make sure level 5 is enabled so
@@ -363,7 +369,7 @@
  * exception. This is a unrecoverable event, so crash.
  * Note: this cannot be ENTRY() as we jump here with "if cc jump" ...
  */
-_double_fault:
+ENTRY(_double_fault)
 	/* Turn caches & protection off, to ensure we don't get any more
 	 * double exceptions
 	 */
@@ -473,6 +479,16 @@
 	[--sp] = ASTAT;
 	[--sp] = (R7:6,P5:4);
 
+#ifdef CONFIG_EXACT_HWERR
+	/* Make sure all pending read/writes complete. This will ensure any
+	 * accesses which could cause hardware errors completes, and signal
+	 * the the hardware before we do something silly, like crash the
+	 * kernel. We don't need to work around anomaly 05000312, since
+	 * we are already atomic
+	 */
+	ssync;
+#endif
+
 #if ANOMALY_05000283 || ANOMALY_05000315
 	cc = r7 == r7;
 	p5.h = HI(CHIPID);
@@ -855,10 +871,10 @@
 	p1.h = _schedule_and_signal;
 	[p0] = p1;
 	csync;
-	raise 15;		/* raise evt14 to do signal or reschedule */
+	raise 15;		/* raise evt15 to do signal or reschedule */
 4:
 	r0 = syscfg;
-	bitclr(r0, 0);
+	bitclr(r0, SYSCFG_SSSTEP_P);		/* Turn off single step */
 	syscfg = r0;
 5:
 	rts;
@@ -916,7 +932,7 @@
 	p1.h = _schedule_and_signal_from_int;
 	[p0] = p1;
 	csync;
-#if ANOMALY_05000281
+#if ANOMALY_05000281 || ANOMALY_05000461
 	r0.l = lo(SAFE_USER_INSTRUCTION);
 	r0.h = hi(SAFE_USER_INSTRUCTION);
 	reti = r0;
@@ -930,18 +946,27 @@
 ENDPROC(_return_from_int)
 
 ENTRY(_lower_to_irq14)
-#if ANOMALY_05000281
+#if ANOMALY_05000281 || ANOMALY_05000461
 	r0.l = lo(SAFE_USER_INSTRUCTION);
 	r0.h = hi(SAFE_USER_INSTRUCTION);
 	reti = r0;
 #endif
-	r0 = 0x401f;
+
+#ifdef CONFIG_DEBUG_HWERR
+	/* enable irq14 & hwerr interrupt, until we transition to _evt14_softirq */
+	r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#else
+	/* Only enable irq14 interrupt, until we transition to _evt14_softirq */
+	r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#endif
 	sti r0;
 	raise 14;
 	rti;
+ENDPROC(_lower_to_irq14)
+
 ENTRY(_evt14_softirq)
 #ifdef CONFIG_DEBUG_HWERR
-	r0 = 0x3f;
+	r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
 	sti r0;
 #else
 	cli r0;
@@ -949,8 +974,9 @@
 	[--sp] = RETI;
 	SP += 4;
 	rts;
+ENDPROC(_evt14_softirq)
 
-_schedule_and_signal_from_int:
+ENTRY(_schedule_and_signal_from_int)
 	/* To end up here, vector 15 was changed - so we have to change it
 	 * back.
 	 */
@@ -983,8 +1009,9 @@
 	call _finish_atomic_sections;
 	sp += 12;
 	jump.s .Lresume_userspace;
+ENDPROC(_schedule_and_signal_from_int)
 
-_schedule_and_signal:
+ENTRY(_schedule_and_signal)
 	SAVE_CONTEXT_SYSCALL
 	/* To end up here, vector 15 was changed - so we have to change it
 	 * back.
@@ -1002,7 +1029,7 @@
 1:
 	RESTORE_CONTEXT
 	rti;
-ENDPROC(_lower_to_irq14)
+ENDPROC(_schedule_and_signal)
 
 /* We handle this 100% in exception space - to reduce overhead
  * Only potiential problem is if the software buffer gets swapped out of the
@@ -1583,24 +1610,10 @@
 	.long _sys_inotify_init1	/* 365 */
 	.long _sys_preadv
 	.long _sys_pwritev
+	.long _sys_rt_tgsigqueueinfo
+	.long _sys_perf_counter_open
 
 	.rept NR_syscalls-(.-_sys_call_table)/4
 	.long _sys_ni_syscall
 	.endr
 END(_sys_call_table)
-
-#ifdef CONFIG_EXCEPTION_L1_SCRATCH
-/* .section .l1.bss.scratch */
-.set _exception_stack_top, L1_SCRATCH_START + L1_SCRATCH_LENGTH
-#else
-#ifdef CONFIG_SYSCALL_TAB_L1
-.section .l1.bss
-#else
-.bss
-#endif
-ENTRY(_exception_stack)
-	.rept 1024 * NR_CPUS
-	.long 0
-	.endr
-_exception_stack_top:
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/head.S linux-libre-2.6.31-gnu/arch/blackfin/mach-common/head.S
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/head.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/head.S	2009-09-09 18:13:59.000000000 -0400
@@ -30,8 +30,6 @@
 	rts;
 ENDPROC(__init_clear_bss)
 
-#define INITIAL_STACK	(L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
-
 ENTRY(__start)
 	/* R0: argument of command line string, passed from uboot, save it */
 	R7 = R0;
@@ -126,30 +124,30 @@
 	 * below
 	 */
 	GET_PDA(p0, r0);
-	r7 = [p0 + PDA_RETX];
+	r6 = [p0 + PDA_RETX];
 	p1.l = _init_saved_retx;
 	p1.h = _init_saved_retx;
-	[p1] = r7;
+	[p1] = r6;
 
-	r7 = [p0 + PDA_DCPLB];
+	r6 = [p0 + PDA_DCPLB];
 	p1.l = _init_saved_dcplb_fault_addr;
 	p1.h = _init_saved_dcplb_fault_addr;
-	[p1] = r7;
+	[p1] = r6;
 
-	r7 = [p0 + PDA_ICPLB];
+	r6 = [p0 + PDA_ICPLB];
 	p1.l = _init_saved_icplb_fault_addr;
 	p1.h = _init_saved_icplb_fault_addr;
-	[p1] = r7;
+	[p1] = r6;
 
-	r7 = [p0 + PDA_SEQSTAT];
+	r6 = [p0 + PDA_SEQSTAT];
 	p1.l = _init_saved_seqstat;
 	p1.h = _init_saved_seqstat;
-	[p1] = r7;
+	[p1] = r6;
 #endif
 
 	/* Initialize stack pointer */
-	sp.l = lo(INITIAL_STACK);
-	sp.h = hi(INITIAL_STACK);
+	sp.l = _init_thread_union;
+	sp.h = _init_thread_union;
 	fp = sp;
 	usp = sp;
 
@@ -189,7 +187,15 @@
 	/* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
 	call _bfin_relocate_l1_mem;
 #ifdef CONFIG_BFIN_KERNEL_CLOCK
+	/* Only use on-chip scratch space for stack when absolutely required
+	 * to avoid Anomaly 05000227 ... we know the init_clocks() func only
+	 * uses L1 text and stack space and no other memory region.
+	 */
+# define KERNEL_CLOCK_STACK (L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
+	sp.l = lo(KERNEL_CLOCK_STACK);
+	sp.h = hi(KERNEL_CLOCK_STACK);
 	call _init_clocks;
+	sp = usp;	/* usp hasnt been touched, so restore from there */
 #endif
 
 	/* This section keeps the processor in supervisor mode
@@ -243,9 +249,7 @@
 	call _cmdline_init;
 
 	/* Load the current thread pointer and stack */
-	sp.l = _init_thread_union;
-	sp.h = _init_thread_union;
-	p1 = THREAD_SIZE (z);
+	p1 = THREAD_SIZE + 4 (z);	/* +4 is for reti loading */
 	sp = sp + p1;
 	usp = sp;
 	fp = sp;
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/interrupt.S linux-libre-2.6.31-gnu/arch/blackfin/mach-common/interrupt.S
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/interrupt.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/interrupt.S	2009-09-09 18:13:59.000000000 -0400
@@ -145,6 +145,14 @@
 
 /* interrupt routine for ivhw - 5 */
 ENTRY(_evt_ivhw)
+	/* In case a single action kicks off multiple memory transactions, (like
+	 * a cache line fetch, - this can cause multiple hardware errors, let's
+	 * catch them all. First - make sure all the actions are complete, and
+	 * the core sees the hardware errors.
+	 */
+	SSYNC;
+	SSYNC;
+
 	SAVE_ALL_SYS
 #ifdef CONFIG_FRAME_POINTER
 	fp = 0;
@@ -159,6 +167,25 @@
 1:
 #endif
 
+	/* Handle all stacked hardware errors
+	 * To make sure we don't hang forever, only do it 10 times
+	 */
+	R0 = 0;
+	R2 = 10;
+1:
+	P0.L = LO(ILAT);
+	P0.H = HI(ILAT);
+	R1 = [P0];
+	CC = BITTST(R1, EVT_IVHW_P);
+	IF ! CC JUMP 2f;
+	/* OK a hardware error is pending - clear it */
+	R1 = EVT_IVHW_P;
+	[P0] = R1;
+	R0 += 1;
+	CC = R1 == R2;
+	if CC JUMP 2f;
+	JUMP 1b;
+2:
 	# We are going to dump something out, so make sure we print IPEND properly
 	p2.l = lo(IPEND);
 	p2.h = hi(IPEND);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/ints-priority.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/ints-priority.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/ints-priority.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/ints-priority.c	2009-09-09 18:13:59.000000000 -0400
@@ -472,7 +472,7 @@
 
 	if (type == IRQ_TYPE_PROBE) {
 		/* only probe unenabled GPIO interrupt lines */
-		if (__test_bit(gpionr, gpio_enabled))
+		if (test_bit(gpionr, gpio_enabled))
 			return 0;
 		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
 	}
@@ -782,7 +782,7 @@
 
 	if (type == IRQ_TYPE_PROBE) {
 		/* only probe unenabled GPIO interrupt lines */
-		if (__test_bit(gpionr, gpio_enabled))
+		if (test_bit(gpionr, gpio_enabled))
 			return 0;
 		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
 	}
@@ -1052,35 +1052,34 @@
 			set_irq_chained_handler(irq, bfin_demux_error_irq);
 			break;
 #endif
-#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
-		case IRQ_TIMER0:
-			set_irq_handler(irq, handle_percpu_irq);
-			break;
-#endif
 #ifdef CONFIG_SMP
 		case IRQ_SUPPLE_0:
 		case IRQ_SUPPLE_1:
 			set_irq_handler(irq, handle_percpu_irq);
 			break;
 #endif
-		default:
 #ifdef CONFIG_IPIPE
-			/*
-			 * We want internal interrupt sources to be
-			 * masked, because ISRs may trigger interrupts
-			 * recursively (e.g. DMA), but interrupts are
-			 * _not_ masked at CPU level. So let's handle
-			 * most of them as level interrupts, except
-			 * the timer interrupt which is special.
-			 */
-			if (irq == IRQ_SYSTMR || irq == IRQ_CORETMR)
-				set_irq_handler(irq, handle_simple_irq);
-			else
-				set_irq_handler(irq, handle_level_irq);
+#ifndef CONFIG_TICKSOURCE_CORETMR
+		case IRQ_TIMER0:
+			set_irq_handler(irq, handle_simple_irq);
+			break;
+#endif /* !CONFIG_TICKSOURCE_CORETMR */
+		case IRQ_CORETMR:
+			set_irq_handler(irq, handle_simple_irq);
+			break;
+		default:
+			set_irq_handler(irq, handle_level_irq);
+			break;
 #else /* !CONFIG_IPIPE */
+#ifdef CONFIG_TICKSOURCE_GPTMR0
+		case IRQ_TIMER0:
+			set_irq_handler(irq, handle_percpu_irq);
+			break;
+#endif /* CONFIG_TICKSOURCE_GPTMR0 */
+		default:
 			set_irq_handler(irq, handle_simple_irq);
-#endif /* !CONFIG_IPIPE */
 			break;
+#endif	/* !CONFIG_IPIPE */
 		}
 	}
 
@@ -1116,6 +1115,9 @@
 	    IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
 	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
 
+	/* This implicitly covers ANOMALY_05000171
+	 * Boot-ROM code modifies SICA_IWRx wakeup registers
+	 */
 #ifdef SIC_IWR0
 	bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
 # ifdef SIC_IWR1
@@ -1136,13 +1138,6 @@
 	bfin_write_SIC_IWR(IWR_DISABLE_ALL);
 #endif
 
-#ifdef CONFIG_IPIPE
-	for (irq = 0; irq < NR_IRQS; irq++) {
-		struct irq_desc *desc = irq_to_desc(irq);
-		desc->ic_prio = __ipipe_get_irq_priority(irq);
-	}
-#endif /* CONFIG_IPIPE */
-
 	return 0;
 }
 
@@ -1156,23 +1151,22 @@
 	} else {
 		struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
 		struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
-	|| defined(BF538_FAMILY) || defined(CONFIG_BF51x)
+#if defined(SIC_ISR0) || defined(SICA_ISR0)
 		unsigned long sic_status[3];
 
 		if (smp_processor_id()) {
-#ifdef CONFIG_SMP
+# ifdef SICB_ISR0
 			/* This will be optimized out in UP mode. */
 			sic_status[0] = bfin_read_SICB_ISR0() & bfin_read_SICB_IMASK0();
 			sic_status[1] = bfin_read_SICB_ISR1() & bfin_read_SICB_IMASK1();
-#endif
+# endif
 		} else {
 			sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
 			sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
 		}
-#ifdef CONFIG_BF54x
+# ifdef SIC_ISR2
 		sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
-#endif
+# endif
 		for (;; ivg++) {
 			if (ivg >= ivg_stop) {
 				atomic_inc(&num_spurious);
@@ -1229,27 +1223,22 @@
 asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
 {
 	struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
-	struct ipipe_domain *this_domain = ipipe_current_domain;
+	struct ipipe_domain *this_domain = __ipipe_current_domain;
 	struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
 	struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
 	int irq, s;
 
-	if (likely(vec == EVT_IVTMR_P)) {
+	if (likely(vec == EVT_IVTMR_P))
 		irq = IRQ_CORETMR;
-		goto core_tick;
-	}
-
-	SSYNC();
-
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
-	{
+	else {
+#if defined(SIC_ISR0) || defined(SICA_ISR0)
 		unsigned long sic_status[3];
 
 		sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
 		sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
-#ifdef CONFIG_BF54x
+# ifdef SIC_ISR2
 		sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
-#endif
+# endif
 		for (;; ivg++) {
 			if (ivg >= ivg_stop) {
 				atomic_inc(&num_spurious);
@@ -1258,9 +1247,7 @@
 			if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
 				break;
 		}
-	}
 #else
-	{
 		unsigned long sic_status;
 
 		sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
@@ -1272,15 +1259,12 @@
 			} else if (sic_status & ivg->isrflag)
 				break;
 		}
-	}
 #endif
-
-	irq = ivg->irqno;
+		irq = ivg->irqno;
+	}
 
 	if (irq == IRQ_SYSTMR) {
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
-core_tick:
-#else
+#if !defined(CONFIG_GENERIC_CLOCKEVENTS) || defined(CONFIG_TICKSOURCE_GPTMR0)
 		bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */
 #endif
 		/* This is basically what we need from the register frame. */
@@ -1292,9 +1276,6 @@
 			__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
 	}
 
-#ifndef CONFIG_GENERIC_CLOCKEVENTS
-core_tick:
-#endif
 	if (this_domain == ipipe_root_domain) {
 		s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
 		barrier();
@@ -1312,7 +1293,7 @@
 		}
 	}
 
-       return 0;
+	return 0;
 }
 
 #endif /* CONFIG_IPIPE */
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/irqpanic.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/irqpanic.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/irqpanic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/irqpanic.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,21 +30,17 @@
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
-#include <asm/traps.h>
 #include <asm/blackfin.h>
 
-#ifdef CONFIG_DEBUG_ICACHE_CHECK
 #define L1_ICACHE_START 0xffa10000
 #define L1_ICACHE_END   0xffa13fff
-void irq_panic(int reason, struct pt_regs *regs) __attribute__ ((l1_text));
-#endif
 
 /*
  * irq_panic - calls panic with string setup
  */
+__attribute__ ((l1_text))
 asmlinkage void irq_panic(int reason, struct pt_regs *regs)
 {
-#ifdef CONFIG_DEBUG_ICACHE_CHECK
 	unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
 	unsigned short i, j, die;
 	unsigned int bad[10][6];
@@ -126,9 +122,6 @@
 			     bad[j][3], bad[j][4], bad[j][5]);
 		}
 		panic("icache coherency error");
-	} else {
+	} else
 		printk(KERN_EMERG "icache checked, and OK\n");
-	}
-#endif
-
 }
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/Makefile linux-libre-2.6.31-gnu/arch/blackfin/mach-common/Makefile
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,7 +4,7 @@
 
 obj-y := \
 	cache.o cache-c.o entry.o head.o \
-	interrupt.o irqpanic.o arch_checks.o ints-priority.o
+	interrupt.o arch_checks.o ints-priority.o
 
 obj-$(CONFIG_BFIN_ICACHE_LOCK) += lock.o
 obj-$(CONFIG_PM)          += pm.o dpmc_modes.o
@@ -12,3 +12,4 @@
 obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
 obj-$(CONFIG_SMP)         += smp.o
 obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o
+obj-$(CONFIG_DEBUG_ICACHE_CHECK) += irqpanic.o
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/pm.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/pm.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -132,7 +132,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_BFIN_WB
+#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
 static void flushinv_all_dcache(void)
 {
 	u32 way, bank, subbank, set;
@@ -175,7 +175,7 @@
 #ifdef CONFIG_BFIN_DCACHE
 	unsigned long ctrl;
 
-#ifdef CONFIG_BFIN_WB
+#if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
 	flushinv_all_dcache();
 #endif
 	SSYNC();
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mach-common/smp.c linux-libre-2.6.31-gnu/arch/blackfin/mach-common/smp.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mach-common/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mach-common/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,8 +43,13 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/cpu.h>
+#include <asm/time.h>
 #include <linux/err.h>
 
+/*
+ * Anomaly notes:
+ * 05000120 - we always define corelock as 32-bit integer in L2
+ */
 struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
 
 void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
@@ -139,7 +144,7 @@
 
 static irqreturn_t ipi_handler(int irq, void *dev_instance)
 {
-	struct ipi_message *msg, *mg;
+	struct ipi_message *msg;
 	struct ipi_message_queue *msg_queue;
 	unsigned int cpu = smp_processor_id();
 
@@ -149,7 +154,8 @@
 	msg_queue->count++;
 
 	spin_lock(&msg_queue->lock);
-	list_for_each_entry_safe(msg, mg, &msg_queue->head, list) {
+	while (!list_empty(&msg_queue->head)) {
+		msg = list_entry(msg_queue->head.next, typeof(*msg), list);
 		list_del(&msg->list);
 		switch (msg->type) {
 		case BFIN_IPI_RESCHEDULE:
@@ -205,6 +211,8 @@
 		return 0;
 
 	msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+	if (!msg)
+		return -ENOMEM;
 	INIT_LIST_HEAD(&msg->list);
 	msg->call_struct.func = func;
 	msg->call_struct.info = info;
@@ -216,7 +224,7 @@
 	for_each_cpu_mask(cpu, callmap) {
 		msg_queue = &per_cpu(ipi_msg_queue, cpu);
 		spin_lock_irqsave(&msg_queue->lock, flags);
-		list_add(&msg->list, &msg_queue->head);
+		list_add_tail(&msg->list, &msg_queue->head);
 		spin_unlock_irqrestore(&msg_queue->lock, flags);
 		platform_send_ipi_cpu(cpu);
 	}
@@ -246,6 +254,8 @@
 	cpu_set(cpu, callmap);
 
 	msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+	if (!msg)
+		return -ENOMEM;
 	INIT_LIST_HEAD(&msg->list);
 	msg->call_struct.func = func;
 	msg->call_struct.info = info;
@@ -256,7 +266,7 @@
 
 	msg_queue = &per_cpu(ipi_msg_queue, cpu);
 	spin_lock_irqsave(&msg_queue->lock, flags);
-	list_add(&msg->list, &msg_queue->head);
+	list_add_tail(&msg->list, &msg_queue->head);
 	spin_unlock_irqrestore(&msg_queue->lock, flags);
 	platform_send_ipi_cpu(cpu);
 
@@ -281,13 +291,15 @@
 		return;
 
 	msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+	if (!msg)
+		return;
 	memset(msg, 0, sizeof(msg));
 	INIT_LIST_HEAD(&msg->list);
 	msg->type = BFIN_IPI_RESCHEDULE;
 
 	msg_queue = &per_cpu(ipi_msg_queue, cpu);
 	spin_lock_irqsave(&msg_queue->lock, flags);
-	list_add(&msg->list, &msg_queue->head);
+	list_add_tail(&msg->list, &msg_queue->head);
 	spin_unlock_irqrestore(&msg_queue->lock, flags);
 	platform_send_ipi_cpu(cpu);
 
@@ -308,6 +320,8 @@
 		return;
 
 	msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+	if (!msg)
+		return;
 	memset(msg, 0, sizeof(msg));
 	INIT_LIST_HEAD(&msg->list);
 	msg->type = BFIN_IPI_CPU_STOP;
@@ -315,7 +329,7 @@
 	for_each_cpu_mask(cpu, callmap) {
 		msg_queue = &per_cpu(ipi_msg_queue, cpu);
 		spin_lock_irqsave(&msg_queue->lock, flags);
-		list_add(&msg->list, &msg_queue->head);
+		list_add_tail(&msg->list, &msg_queue->head);
 		spin_unlock_irqrestore(&msg_queue->lock, flags);
 		platform_send_ipi_cpu(cpu);
 	}
@@ -352,7 +366,7 @@
 
 static void __cpuinit setup_secondary(unsigned int cpu)
 {
-#if !(defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE))
+#if !defined(CONFIG_TICKSOURCE_GPTMR0)
 	struct irq_desc *timer_desc;
 #endif
 	unsigned long ilat;
@@ -364,16 +378,13 @@
 	bfin_write_ILAT(ilat);
 	CSYNC();
 
-	/* Reserve the PDA space for the secondary CPU. */
-	reserve_pda();
-
 	/* Enable interrupt levels IVG7-15. IARs have been already
 	 * programmed by the boot CPU.  */
 	bfin_irq_flags |= IMASK_IVG15 |
 	    IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
 	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
 
-#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+#if defined(CONFIG_TICKSOURCE_GPTMR0)
 	/* Power down the core timer, just to play safe. */
 	bfin_write_TCNTL(0);
 
@@ -447,7 +458,7 @@
 	unsigned int cpu;
 
 	for_each_online_cpu(cpu)
-		bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy;
+		bogosum += loops_per_jiffy;
 
 	printk(KERN_INFO "SMP: Total of %d processors activated "
 	       "(%lu.%02lu BogoMIPS).\n",
@@ -466,6 +477,17 @@
 }
 EXPORT_SYMBOL_GPL(smp_icache_flush_range_others);
 
+#ifdef __ARCH_SYNC_CORE_ICACHE
+void resync_core_icache(void)
+{
+	unsigned int cpu = get_cpu();
+	blackfin_invalidate_entire_icache();
+	++per_cpu(cpu_data, cpu).icache_invld_count;
+	put_cpu();
+}
+EXPORT_SYMBOL(resync_core_icache);
+#endif
+
 #ifdef __ARCH_SYNC_CORE_DCACHE
 unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));
 
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/Makefile linux-libre-2.6.31-gnu/arch/blackfin/Makefile
--- linux-libre-2.6.30-gnu/arch/blackfin/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -137,7 +137,7 @@
 
 INSTALL_PATH ?= /tftpboot
 boot := arch/$(ARCH)/boot
-BOOT_TARGETS = vmImage
+BOOT_TARGETS = vmImage vmImage.bz2 vmImage.gz vmImage.lzma
 PHONY += $(BOOT_TARGETS) install
 KBUILD_IMAGE := $(boot)/vmImage
 
@@ -150,7 +150,10 @@
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
 
 define archhelp
-  echo  '* vmImage         - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage)'
+  echo  '* vmImage         - Alias to selected kernel format (vmImage.gz by default)'
+  echo  '  vmImage.bz2     - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.bz2)'
+  echo  '* vmImage.gz      - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.gz)'
+  echo  '  vmImage.lzma    - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.lzma)'
   echo  '  install         - Install kernel using'
   echo  '                     (your) ~/bin/$(CROSS_COMPILE)installkernel or'
   echo  '                     (distribution) PATH: $(CROSS_COMPILE)installkernel or'
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mm/blackfin_sram.h linux-libre-2.6.31-gnu/arch/blackfin/mm/blackfin_sram.h
--- linux-libre-2.6.30-gnu/arch/blackfin/mm/blackfin_sram.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mm/blackfin_sram.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,6 @@
 #ifndef __BLACKFIN_SRAM_H__
 #define __BLACKFIN_SRAM_H__
 
-extern void bfin_sram_init(void);
 extern void *l1sram_alloc(size_t);
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mm/init.c linux-libre-2.6.31-gnu/arch/blackfin/mm/init.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,9 +52,14 @@
 
 static unsigned long empty_bad_page;
 
-unsigned long empty_zero_page;
+static unsigned long empty_zero_page;
 
-extern unsigned long exception_stack[NR_CPUS][1024];
+#ifndef CONFIG_EXCEPTION_L1_SCRATCH
+#if defined CONFIG_SYSCALL_TAB_L1
+__attribute__((l1_data))
+#endif
+static unsigned long exception_stack[NR_CPUS][1024];
+#endif
 
 struct blackfin_pda cpu_pda[NR_CPUS];
 EXPORT_SYMBOL(cpu_pda);
@@ -117,19 +122,18 @@
 	cpu_pda[0].next = &cpu_pda[1];
 	cpu_pda[1].next = &cpu_pda[0];
 
+#ifdef CONFIG_EXCEPTION_L1_SCRATCH
+	cpu_pda[cpu].ex_stack = (unsigned long *)(L1_SCRATCH_START + \
+					L1_SCRATCH_LENGTH);
+#else
 	cpu_pda[cpu].ex_stack = exception_stack[cpu + 1];
+#endif
 
 #ifdef CONFIG_SMP
 	cpu_pda[cpu].imask = 0x1f;
 #endif
 }
 
-void __cpuinit reserve_pda(void)
-{
-	printk(KERN_INFO "PDA for CPU%u reserved at %p\n", smp_processor_id(),
-					&cpu_pda[smp_processor_id()]);
-}
-
 void __init mem_init(void)
 {
 	unsigned int codek = 0, datak = 0, initk = 0;
@@ -156,7 +160,7 @@
 
 	/* do not count in kernel image between _rambase and _ramstart */
 	reservedpages -= (_ramstart - _rambase) >> PAGE_SHIFT;
-#if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263)
+#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
 	reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >> PAGE_SHIFT;
 #endif
 
@@ -171,19 +175,6 @@
 		initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
 }
 
-static int __init sram_init(void)
-{
-	/* Initialize the blackfin L1 Memory. */
-	bfin_sram_init();
-
-	/* Reserve the PDA space for the boot CPU right after we
-	 * initialized the scratch memory allocator.
-	 */
-	reserve_pda();
-	return 0;
-}
-pure_initcall(sram_init);
-
 static void __init free_init_pages(const char *what, unsigned long begin, unsigned long end)
 {
 	unsigned long addr;
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mm/isram-driver.c linux-libre-2.6.31-gnu/arch/blackfin/mm/isram-driver.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mm/isram-driver.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mm/isram-driver.c	2009-09-09 18:13:59.000000000 -0400
@@ -125,7 +125,7 @@
 {
 	if ((addr >= (void *)L1_CODE_START) &&
 	    (addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))) {
-		if ((addr + n) >= (void *)(L1_CODE_START + L1_CODE_LENGTH)) {
+		if ((addr + n) > (void *)(L1_CODE_START + L1_CODE_LENGTH)) {
 			show_stack(NULL, NULL);
 			printk(KERN_ERR "isram_memcpy: copy involving %p length "
 					"(%zu) too long\n", addr, n);
diff -druN linux-libre-2.6.30-gnu/arch/blackfin/mm/sram-alloc.c linux-libre-2.6.31-gnu/arch/blackfin/mm/sram-alloc.c
--- linux-libre-2.6.30-gnu/arch/blackfin/mm/sram-alloc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/blackfin/mm/sram-alloc.c	2009-09-09 18:13:59.000000000 -0400
@@ -83,6 +83,14 @@
 static void __init l1sram_init(void)
 {
 	unsigned int cpu;
+	unsigned long reserve;
+
+#ifdef CONFIG_SMP
+	reserve = 0;
+#else
+	reserve = sizeof(struct l1_scratch_task_info);
+#endif
+
 	for (cpu = 0; cpu < num_possible_cpus(); ++cpu) {
 		per_cpu(free_l1_ssram_head, cpu).next =
 			kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
@@ -91,8 +99,8 @@
 			return;
 		}
 
-		per_cpu(free_l1_ssram_head, cpu).next->paddr = (void *)get_l1_scratch_start_cpu(cpu);
-		per_cpu(free_l1_ssram_head, cpu).next->size = L1_SCRATCH_LENGTH;
+		per_cpu(free_l1_ssram_head, cpu).next->paddr = (void *)get_l1_scratch_start_cpu(cpu) + reserve;
+		per_cpu(free_l1_ssram_head, cpu).next->size = L1_SCRATCH_LENGTH - reserve;
 		per_cpu(free_l1_ssram_head, cpu).next->pid = 0;
 		per_cpu(free_l1_ssram_head, cpu).next->next = NULL;
 
@@ -223,7 +231,7 @@
 	spin_lock_init(&l2_sram_lock);
 }
 
-void __init bfin_sram_init(void)
+static int __init bfin_sram_init(void)
 {
 	sram_piece_cache = kmem_cache_create("sram_piece_cache",
 				sizeof(struct sram_piece),
@@ -233,7 +241,10 @@
 	l1_data_sram_init();
 	l1_inst_sram_init();
 	l2_sram_init();
+
+	return 0;
 }
+pure_initcall(bfin_sram_init);
 
 /* SRAM allocate function */
 static void *_sram_alloc(size_t size, struct sram_piece *pfree_head,
@@ -732,6 +743,10 @@
 }
 EXPORT_SYMBOL(sram_free_with_lsl);
 
+/* Allocate memory and keep in L1 SRAM List (lsl) so that the resources are
+ * tracked.  These are designed for userspace so that when a process exits,
+ * we can safely reap their resources.
+ */
 void *sram_alloc_with_lsl(size_t size, unsigned long flags)
 {
 	void *addr = NULL;
diff -druN linux-libre-2.6.30-gnu/arch/cris/arch-v10/kernel/dma.c linux-libre-2.6.31-gnu/arch/cris/arch-v10/kernel/dma.c
--- linux-libre-2.6.30-gnu/arch/cris/arch-v10/kernel/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/arch-v10/kernel/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,7 +24,7 @@
 	unsigned long int gens;
 	int fail = -EINVAL;
 
-	if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
+	if (dmanr >= MAX_DMA_CHANNELS) {
 		printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr);
 		return -EINVAL;
 	}
@@ -213,7 +213,7 @@
 void cris_free_dma(unsigned int dmanr, const char * device_id)
 {
 	unsigned long flags;
-	if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) {
+	if (dmanr >= MAX_DMA_CHANNELS) {
 		printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr);
 		return;
 	}
diff -druN linux-libre-2.6.30-gnu/arch/cris/arch-v32/drivers/cryptocop.c linux-libre-2.6.31-gnu/arch/cris/arch-v32/drivers/cryptocop.c
--- linux-libre-2.6.30-gnu/arch/cris/arch-v32/drivers/cryptocop.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/arch-v32/drivers/cryptocop.c	2009-09-09 18:13:59.000000000 -0400
@@ -1395,7 +1395,7 @@
 	if (padlen < MD5_MIN_PAD_LENGTH) padlen += MD5_BLOCK_LENGTH;
 
 	p = kmalloc(padlen, alloc_flag);
-	if (!pad) return -ENOMEM;
+	if (!p) return -ENOMEM;
 
 	*p = 0x80;
 	memset(p+1, 0, padlen - 1);
@@ -1427,7 +1427,7 @@
 	if (padlen < SHA1_MIN_PAD_LENGTH) padlen += SHA1_BLOCK_LENGTH;
 
 	p = kmalloc(padlen, alloc_flag);
-	if (!pad) return -ENOMEM;
+	if (!p) return -ENOMEM;
 
 	*p = 0x80;
 	memset(p+1, 0, padlen - 1);
diff -druN linux-libre-2.6.30-gnu/arch/cris/arch-v32/kernel/irq.c linux-libre-2.6.31-gnu/arch/cris/arch-v32/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/cris/arch-v32/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/arch-v32/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -325,12 +325,14 @@
 {
 }
 
-void set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
+int set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&irq_lock, flags);
 	irq_allocations[irq - FIRST_IRQ].mask = *dest;
 	spin_unlock_irqrestore(&irq_lock, flags);
+
+	return 0;
 }
 
 static struct irq_chip crisv32_irq_type = {
@@ -428,8 +430,8 @@
 			 masked[i] &= ~TIMER_MASK;
 			 do_IRQ(TIMER0_INTR_VECT, regs);
 		}
-	}
 #endif
+	}
 
 #ifdef IGNORE_MASK
 	/* Remove IRQs that can't be handled as multiple. */
diff -druN linux-libre-2.6.30-gnu/arch/cris/arch-v32/lib/Makefile linux-libre-2.6.31-gnu/arch/cris/arch-v32/lib/Makefile
--- linux-libre-2.6.30-gnu/arch/cris/arch-v32/lib/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/arch-v32/lib/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,5 +3,5 @@
 #
 
 lib-y  = checksum.o checksumcopy.o string.o usercopy.o memset.o \
-	csumcpfruser.o spinlock.o delay.o
+	csumcpfruser.o spinlock.o delay.o strcmp.o
 
diff -druN linux-libre-2.6.30-gnu/arch/cris/arch-v32/lib/strcmp.S linux-libre-2.6.31-gnu/arch/cris/arch-v32/lib/strcmp.S
--- linux-libre-2.6.30-gnu/arch/cris/arch-v32/lib/strcmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/cris/arch-v32/lib/strcmp.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,21 @@
+; strcmp.S -- CRISv32 version.
+; Copyright (C) 2008 AXIS Communications AB
+; Written by Edgar E. Iglesias
+;
+; This source code is licensed under the GNU General Public License,
+; Version 2.  See the file COPYING for more details.
+
+	.global	strcmp
+	.type	strcmp,@function
+strcmp:
+1:
+	move.b	[$r10+], $r12
+	seq	$r13
+	sub.b	[$r11+], $r12
+	or.b	$r12, $r13
+	beq	1b
+	nop
+
+	ret
+	movs.b	$r12, $r10
+	.size	strcmp, . - strcmp
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/arch-v32/arch/spinlock.h linux-libre-2.6.31-gnu/arch/cris/include/arch-v32/arch/spinlock.h
--- linux-libre-2.6.30-gnu/arch/cris/include/arch-v32/arch/spinlock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/arch-v32/arch/spinlock.h	2009-09-09 18:13:59.000000000 -0400
@@ -78,7 +78,7 @@
 {
 	__raw_spin_lock(&rw->slock);
 	while (rw->lock != RW_LOCK_BIAS);
-	rw->lock == 0;
+	rw->lock = 0;
 	__raw_spin_unlock(&rw->slock);
 }
 
@@ -93,7 +93,7 @@
 {
 	__raw_spin_lock(&rw->slock);
 	while (rw->lock != RW_LOCK_BIAS);
-	rw->lock == RW_LOCK_BIAS;
+	rw->lock = RW_LOCK_BIAS;
 	__raw_spin_unlock(&rw->slock);
 }
 
@@ -114,7 +114,7 @@
 	int ret = 0;
 	__raw_spin_lock(&rw->slock);
 	if (rw->lock == RW_LOCK_BIAS) {
-		rw->lock == 0;
+		rw->lock = 0;
 		ret = 1;
 	}
 	__raw_spin_unlock(&rw->slock);
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/cris/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -158,5 +158,5 @@
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc()     barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/cris/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/cris/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,21 +5,6 @@
  * is actually used on cris. 
  */
 
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/mman.h linux-libre-2.6.31-gnu/arch/cris/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,7 @@
 
 /* verbatim copy of asm-i386/ version */
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/page.h linux-libre-2.6.31-gnu/arch/cris/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -68,7 +68,7 @@
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _CRIS_PAGE_H */
 
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/cris/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,7 @@
 	__free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte)				\
+#define __pte_free_tlb(tlb,pte,address)			\
 do {							\
 	pgtable_page_dtor(pte);				\
 	tlb_remove_page((tlb), pte);			\
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/signal.h linux-libre-2.6.31-gnu/arch/cris/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -106,7 +106,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/string.h linux-libre-2.6.31-gnu/arch/cris/include/asm/string.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/string.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/string.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,4 +11,10 @@
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *, int, size_t);
 
+#ifdef CONFIG_ETRAX_ARCH_V32
+/* For v32 we provide strcmp.  */
+#define __HAVE_ARCH_STRCMP
+extern int strcmp(const char *s1, const char *s2);
+#endif
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/cris/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/cris/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/cris/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -50,8 +50,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 #define INIT_THREAD_INFO(tsk)				\
@@ -60,7 +58,7 @@
 	.exec_domain	= &default_exec_domain,		\
 	.flags		= 0,				\
 	.cpu		= 0,				\
-	.preempt_count	= 1,				\
+	.preempt_count	= INIT_PREEMPT_COUNT,		\
 	.addr_limit	= KERNEL_DS,			\
 	.restart_block = {				\
 		       .fn = do_no_restart_syscall,	\
diff -druN linux-libre-2.6.30-gnu/arch/cris/kernel/module.c linux-libre-2.6.31-gnu/arch/cris/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/cris/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,8 +48,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	FREE_MODULE(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-	   table entries. */
 }
 
 /* We don't need anything special. */
diff -druN linux-libre-2.6.30-gnu/arch/cris/kernel/process.c linux-libre-2.6.31-gnu/arch/cris/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/cris/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,10 +38,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/cris/kernel/sys_cris.c linux-libre-2.6.31-gnu/arch/cris/kernel/sys_cris.c
--- linux-libre-2.6.30-gnu/arch/cris/kernel/sys_cris.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/kernel/sys_cris.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
diff -druN linux-libre-2.6.30-gnu/arch/cris/mm/fault.c linux-libre-2.6.31-gnu/arch/cris/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/cris/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/cris/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -163,7 +163,7 @@
 	 * the fault.
 	 */
 
-	fault = handle_mm_fault(mm, vma, address, writeaccess & 1);
+	fault = handle_mm_fault(mm, vma, address, (writeaccess & 1) ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/frv/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -121,10 +121,72 @@
 #define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) == 0)
 
+/*
+ * 64-bit atomic ops
+ */
+typedef struct {
+	volatile long long counter;
+} atomic64_t;
+
+#define ATOMIC64_INIT(i)	{ (i) }
+
+static inline long long atomic64_read(atomic64_t *v)
+{
+	long long counter;
+
+	asm("ldd%I1 %M1,%0"
+	    : "=e"(counter)
+	    : "m"(v->counter));
+	return counter;
+}
+
+static inline void atomic64_set(atomic64_t *v, long long i)
+{
+	asm volatile("std%I0 %1,%M0"
+		     : "=m"(v->counter)
+		     : "e"(i));
+}
+
+extern long long atomic64_inc_return(atomic64_t *v);
+extern long long atomic64_dec_return(atomic64_t *v);
+extern long long atomic64_add_return(long long i, atomic64_t *v);
+extern long long atomic64_sub_return(long long i, atomic64_t *v);
+
+static inline long long atomic64_add_negative(long long i, atomic64_t *v)
+{
+	return atomic64_add_return(i, v) < 0;
+}
+
+static inline void atomic64_add(long long i, atomic64_t *v)
+{
+	atomic64_add_return(i, v);
+}
+
+static inline void atomic64_sub(long long i, atomic64_t *v)
+{
+	atomic64_sub_return(i, v);
+}
+
+static inline void atomic64_inc(atomic64_t *v)
+{
+	atomic64_inc_return(v);
+}
+
+static inline void atomic64_dec(atomic64_t *v)
+{
+	atomic64_dec_return(v);
+}
+
+#define atomic64_sub_and_test(i,v)	(atomic64_sub_return((i), (v)) == 0)
+#define atomic64_dec_and_test(v)	(atomic64_dec_return((v)) == 0)
+#define atomic64_inc_and_test(v)	(atomic64_inc_return((v)) == 0)
+
 /*****************************************************************************/
 /*
  * exchange value with memory
  */
+extern uint64_t __xchg_64(uint64_t i, volatile void *v);
+
 #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
 
 #define xchg(ptr, x)								\
@@ -174,8 +236,10 @@
 
 #define tas(ptr) (xchg((ptr), 1))
 
-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+#define atomic_cmpxchg(v, old, new)	(cmpxchg(&(v)->counter, old, new))
+#define atomic_xchg(v, new)		(xchg(&(v)->counter, new))
+#define atomic64_cmpxchg(v, old, new)	(__cmpxchg_64(old, new, &(v)->counter))
+#define atomic64_xchg(v, new)		(__xchg_64(new, &(v)->counter))
 
 static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 {
@@ -194,5 +258,5 @@
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* _ASM_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/bitops.h linux-libre-2.6.31-gnu/arch/frv/include/asm/bitops.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/bitops.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/bitops.h	2009-09-09 18:13:59.000000000 -0400
@@ -112,7 +112,7 @@
 #define atomic_clear_mask(mask, v)	atomic_test_and_ANDNOT_mask((mask), (v))
 #define atomic_set_mask(mask, v)	atomic_test_and_OR_mask((mask), (v))
 
-static inline int test_and_clear_bit(int nr, volatile void *addr)
+static inline int test_and_clear_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *ptr = addr;
 	unsigned long mask = 1UL << (nr & 31);
@@ -120,7 +120,7 @@
 	return (atomic_test_and_ANDNOT_mask(mask, ptr) & mask) != 0;
 }
 
-static inline int test_and_set_bit(int nr, volatile void *addr)
+static inline int test_and_set_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *ptr = addr;
 	unsigned long mask = 1UL << (nr & 31);
@@ -128,7 +128,7 @@
 	return (atomic_test_and_OR_mask(mask, ptr) & mask) != 0;
 }
 
-static inline int test_and_change_bit(int nr, volatile void *addr)
+static inline int test_and_change_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *ptr = addr;
 	unsigned long mask = 1UL << (nr & 31);
@@ -136,22 +136,22 @@
 	return (atomic_test_and_XOR_mask(mask, ptr) & mask) != 0;
 }
 
-static inline void clear_bit(int nr, volatile void *addr)
+static inline void clear_bit(unsigned long nr, volatile void *addr)
 {
 	test_and_clear_bit(nr, addr);
 }
 
-static inline void set_bit(int nr, volatile void *addr)
+static inline void set_bit(unsigned long nr, volatile void *addr)
 {
 	test_and_set_bit(nr, addr);
 }
 
-static inline void change_bit(int nr, volatile void * addr)
+static inline void change_bit(unsigned long nr, volatile void *addr)
 {
 	test_and_change_bit(nr, addr);
 }
 
-static inline void __clear_bit(int nr, volatile void * addr)
+static inline void __clear_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *a = addr;
 	int mask;
@@ -161,7 +161,7 @@
 	*a &= ~mask;
 }
 
-static inline void __set_bit(int nr, volatile void * addr)
+static inline void __set_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *a = addr;
 	int mask;
@@ -171,7 +171,7 @@
 	*a |= mask;
 }
 
-static inline void __change_bit(int nr, volatile void *addr)
+static inline void __change_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *a = addr;
 	int mask;
@@ -181,7 +181,7 @@
 	*a ^= mask;
 }
 
-static inline int __test_and_clear_bit(int nr, volatile void * addr)
+static inline int __test_and_clear_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *a = addr;
 	int mask, retval;
@@ -193,7 +193,7 @@
 	return retval;
 }
 
-static inline int __test_and_set_bit(int nr, volatile void * addr)
+static inline int __test_and_set_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *a = addr;
 	int mask, retval;
@@ -205,7 +205,7 @@
 	return retval;
 }
 
-static inline int __test_and_change_bit(int nr, volatile void * addr)
+static inline int __test_and_change_bit(unsigned long nr, volatile void *addr)
 {
 	volatile unsigned long *a = addr;
 	int mask, retval;
@@ -220,12 +220,13 @@
 /*
  * This routine doesn't need to be atomic.
  */
-static inline int __constant_test_bit(int nr, const volatile void * addr)
+static inline int
+__constant_test_bit(unsigned long nr, const volatile void *addr)
 {
 	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
 }
 
-static inline int __test_bit(int nr, const volatile void * addr)
+static inline int __test_bit(unsigned long nr, const volatile void *addr)
 {
 	int 	* a = (int *) addr;
 	int	mask;
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/frv/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/elf.h linux-libre-2.6.31-gnu/arch/frv/include/asm/elf.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/elf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/elf.h	2009-09-09 18:13:59.000000000 -0400
@@ -116,6 +116,7 @@
 } while(0)
 
 #define USE_ELF_CORE_DUMP
+#define CORE_DUMP_USE_REGSET
 #define ELF_FDPIC_CORE_EFLAGS	EF_FRV_FDPIC
 #define ELF_EXEC_PAGESIZE	16384
 
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/mman.h linux-libre-2.6.31-gnu/arch/frv/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __ASM_MMAN_H__
 #define __ASM_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/page.h linux-libre-2.6.31-gnu/arch/frv/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -73,6 +73,6 @@
 #endif /* __ASSEMBLY__ */
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _ASM_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/pci.h linux-libre-2.6.31-gnu/arch/frv/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,8 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#ifndef ASM_PCI_H
-#define	ASM_PCI_H
+#ifndef _ASM_FRV_PCI_H
+#define _ASM_FRV_PCI_H
 
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
@@ -43,12 +43,6 @@
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)	(0)
 
-/* The PCI address space does equal the physical memory
- * address space.  The networking and block device layers use
- * this boolean for bounce buffer decisions.
- */
-#define PCI_DMA_BUS_IS_PHYS	(1)
-
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
@@ -87,8 +81,7 @@
 				       dma_addr_t dma_handle,
 				       size_t size, int direction)
 {
-	if (direction == PCI_DMA_NONE)
-                BUG();
+	BUG_ON(direction == PCI_DMA_NONE);
 
 	frv_cache_wback_inv((unsigned long)bus_to_virt(dma_handle),
 			    (unsigned long)bus_to_virt(dma_handle) + size);
@@ -105,14 +98,11 @@
 				   int nelems, int direction)
 {
 	int i;
-
-	if (direction == PCI_DMA_NONE)
-                BUG();
+	BUG_ON(direction == PCI_DMA_NONE);
 
 	for (i = 0; i < nelems; i++)
 		frv_cache_wback_inv(sg_dma_address(&sg[i]),
 				    sg_dma_address(&sg[i])+sg_dma_len(&sg[i]));
 }
 
-
-#endif
+#endif /* _ASM_FRV_PCI_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/perf_counter.h linux-libre-2.6.31-gnu/arch/frv/include/asm/perf_counter.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/perf_counter.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/perf_counter.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,17 @@
+/* FRV performance counter support
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_PERF_COUNTER_H
+#define _ASM_PERF_COUNTER_H
+
+#define PERF_COUNTER_INDEX_OFFSET	0
+
+#endif /* _ASM_PERF_COUNTER_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/frv/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 	__free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte)				\
+#define __pte_free_tlb(tlb,pte,address)			\
 do {							\
 	pgtable_page_dtor(pte);				\
 	tlb_remove_page((tlb),(pte));			\
@@ -62,7 +62,7 @@
  */
 #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *) 2); })
 #define pmd_free(mm, x)			do { } while (0)
-#define __pmd_free_tlb(tlb,x)		do { } while (0)
+#define __pmd_free_tlb(tlb,x,a)		do { } while (0)
 
 #endif /* CONFIG_MMU */
 
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/frv/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -225,7 +225,7 @@
  */
 #define pud_alloc_one(mm, address)		NULL
 #define pud_free(mm, x)				do { } while (0)
-#define __pud_free_tlb(tlb, x)			do { } while (0)
+#define __pud_free_tlb(tlb, x, address)		do { } while (0)
 
 /*
  * The "pud_xxx()" functions here are trivial for a folded two-level
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/ptrace.h linux-libre-2.6.31-gnu/arch/frv/include/asm/ptrace.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/ptrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/ptrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -65,6 +65,8 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
+struct task_struct;
+
 /*
  * we dedicate GR28 to keeping a pointer to the current exception frame
  * - gr28 is destroyed on entry to the kernel from userspace
@@ -73,11 +75,18 @@
 
 #define user_mode(regs)			(!((regs)->psr & PSR_S))
 #define instruction_pointer(regs)	((regs)->pc)
+#define user_stack_pointer(regs)	((regs)->sp)
 
 extern unsigned long user_stack(const struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) ((regs)->pc)
-#endif
+
+#define task_pt_regs(task) ((task)->thread.frame0)
+
+#define arch_has_single_step()	(1)
+extern void user_enable_single_step(struct task_struct *);
+extern void user_disable_single_step(struct task_struct *);
 
 #endif /* !__ASSEMBLY__ */
+#endif /* __KERNEL__ */
 #endif /* _ASM_PTRACE_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/signal.h linux-libre-2.6.31-gnu/arch/frv/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,107 +3,15 @@
 
 #include <linux/types.h>
 
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define _NSIG		64
-#define _NSIG_BPW	32
-#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t;		/* at least 32 bits */
-
-typedef struct {
-	unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else
+#ifndef __KERNEL__
 /* Here we must cater to libcs that poke about in kernel headers.  */
 
 #define NSIG		32
 typedef unsigned long sigset_t;
 
-#endif /* __KERNEL__ */
-
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-#define SIGBUS		 7
-#define SIGFPE		 8
-#define SIGKILL		 9
-#define SIGUSR1		10
-#define SIGSEGV		11
-#define SIGUSR2		12
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGSTKFLT	16
-#define SIGCHLD		17
-#define SIGCONT		18
-#define SIGSTOP		19
-#define SIGTSTP		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGURG		23
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGIO		29
-#define SIGPOLL		SIGIO
-/*
-#define SIGLOST		29
-*/
-#define SIGPWR		30
-#define SIGSYS		31
-#define	SIGUNUSED	31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN	32
-#define SIGRTMAX	(_NSIG-1)
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-#define SA_RESTORER	0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
+#endif /* !__KERNEL__ */
 
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
+#define SA_RESTORER	0x04000000 /* to get struct sigaction correct */
 
 #include <asm-generic/signal.h>
 
@@ -115,16 +23,6 @@
 	__sigrestore_t sa_restorer;
 };
 
-struct sigaction {
-	__sighandler_t sa_handler;
-	unsigned long sa_flags;
-	__sigrestore_t sa_restorer;
-	sigset_t sa_mask;		/* mask last for extensibility */
-};
-
-struct k_sigaction {
-	struct sigaction sa;
-};
 #else
 /* Here we must cater to libcs that poke about in kernel headers.  */
 
@@ -143,19 +41,4 @@
 
 #endif /* __KERNEL__ */
 
-typedef struct sigaltstack {
-	void __user *ss_sp;
-	int ss_flags;
-	size_t ss_size;
-} stack_t;
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#ifdef __KERNEL__
-
-#include <asm/sigcontext.h>
-#undef __HAVE_ARCH_SIG_BITOPS
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_SIGNAL_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/syscall.h linux-libre-2.6.31-gnu/arch/frv/include/asm/syscall.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/syscall.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/syscall.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,123 @@
+/* syscall parameter access functions
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_SYSCALL_H
+#define _ASM_SYSCALL_H
+
+#include <linux/err.h>
+#include <asm/ptrace.h>
+
+/*
+ * Get the system call number or -1
+ */
+static inline long syscall_get_nr(struct task_struct *task,
+				  struct pt_regs *regs)
+{
+	return regs->syscallno;
+}
+
+/*
+ * Restore the clobbered GR8 register
+ * (1st syscall arg was overwritten with syscall return or error)
+ */
+static inline void syscall_rollback(struct task_struct *task,
+				    struct pt_regs *regs)
+{
+	regs->gr8 = regs->orig_gr8;
+}
+
+/*
+ * See if the syscall return value is an error, returning it if it is and 0 if
+ * not
+ */
+static inline long syscall_get_error(struct task_struct *task,
+				     struct pt_regs *regs)
+{
+	return IS_ERR_VALUE(regs->gr8) ? regs->gr8 : 0;
+}
+
+/*
+ * Get the syscall return value
+ */
+static inline long syscall_get_return_value(struct task_struct *task,
+					    struct pt_regs *regs)
+{
+	return regs->gr8;
+}
+
+/*
+ * Set the syscall return value
+ */
+static inline void syscall_set_return_value(struct task_struct *task,
+					    struct pt_regs *regs,
+					    int error, long val)
+{
+	if (error)
+		regs->gr8 = -error;
+	else
+		regs->gr8 = val;
+}
+
+/*
+ * Retrieve the system call arguments
+ */
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	/*
+	 * Do this simply for now. If we need to start supporting
+	 * fetching arguments from arbitrary indices, this will need some
+	 * extra logic. Presently there are no in-tree users that depend
+	 * on this behaviour.
+	 */
+	BUG_ON(i);
+
+	/* Argument pattern is: GR8, GR9, GR10, GR11, GR12, GR13 */
+	switch (n) {
+	case 6: args[5] = regs->gr13;
+	case 5: args[4] = regs->gr12;
+	case 4: args[3] = regs->gr11;
+	case 3: args[2] = regs->gr10;
+	case 2: args[1] = regs->gr9;
+	case 1:	args[0] = regs->gr8;
+		break;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * Alter the system call arguments
+ */
+static inline void syscall_set_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 const unsigned long *args)
+{
+	/* Same note as above applies */
+	BUG_ON(i);
+
+	switch (n) {
+	case 6: regs->gr13 = args[5];
+	case 5: regs->gr12 = args[4];
+	case 4: regs->gr11 = args[3];
+	case 3: regs->gr10 = args[2];
+	case 2: regs->gr9  = args[1];
+	case 1: regs->gr8  = args[0];
+		break;
+	default:
+		BUG();
+	}
+}
+
+#endif /* _ASM_SYSCALL_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/system.h linux-libre-2.6.31-gnu/arch/frv/include/asm/system.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -208,6 +208,8 @@
  * - if (*ptr == test) then orig = *ptr; *ptr = test;
  * - if (*ptr != test) then orig = *ptr;
  */
+extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v);
+
 #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
 
 #define cmpxchg(ptr, test, new)							\
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/termios.h linux-libre-2.6.31-gnu/arch/frv/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -52,7 +52,7 @@
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
 #ifdef __KERNEL__
-#include <asm-generic/termios.h>
+#include <asm-generic/termios-base.h>
 #endif
 
 #endif /* _ASM_TERMIOS_H */
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/frv/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -56,8 +56,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -67,7 +65,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -109,20 +107,20 @@
  * - other flags in MSW
  */
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_SIGPENDING		1	/* signal pending */
-#define TIF_NEED_RESCHED	2	/* rescheduling necessary */
-#define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
-#define TIF_IRET		4	/* return with iret */
+#define TIF_NOTIFY_RESUME	1	/* callback before returning to user */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
 #define TIF_FREEZE		18	/* freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
-#define _TIF_IRET		(1 << TIF_IRET)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1 << TIF_FREEZE)
diff -druN linux-libre-2.6.30-gnu/arch/frv/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/frv/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/frv/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -341,10 +341,12 @@
 #define __NR_inotify_init1	332
 #define __NR_preadv		333
 #define __NR_pwritev		334
+#define __NR_rt_tgsigqueueinfo	335
+#define __NR_perf_counter_open	336
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 335
+#define NR_syscalls 337
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
diff -druN linux-libre-2.6.30-gnu/arch/frv/Kconfig linux-libre-2.6.31-gnu/arch/frv/Kconfig
--- linux-libre-2.6.30-gnu/arch/frv/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,8 @@
 	bool
 	default y
 	select HAVE_IDE
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_PERF_COUNTERS
 
 config ZONE_DMA
 	bool
diff -druN linux-libre-2.6.30-gnu/arch/frv/kernel/entry.S linux-libre-2.6.31-gnu/arch/frv/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/frv/kernel/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -886,7 +886,6 @@
 	bnc		icc0,#0,__syscall_badsys
 
 	ldi		@(gr15,#TI_FLAGS),gr4
-	ori		gr4,#_TIF_SYSCALL_TRACE,gr4
 	andicc		gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
 	bne		icc0,#0,__syscall_trace_entry
 
@@ -1150,11 +1149,10 @@
 	# perform syscall entry tracing
 __syscall_trace_entry:
 	LEDS		0x6320
-	setlos.p	#0,gr8
-	call		do_syscall_trace
+	call		syscall_trace_entry
 
-	ldi		@(gr28,#REG_SYSCALLNO),gr7
-	lddi		@(gr28,#REG_GR(8)) ,gr8
+	lddi.p		@(gr28,#REG_GR(8)) ,gr8
+	ori		gr8,#0,gr7		; syscall_trace_entry() returned new syscallno
 	lddi		@(gr28,#REG_GR(10)),gr10
 	lddi.p		@(gr28,#REG_GR(12)),gr12
 
@@ -1169,11 +1167,10 @@
 	beq		icc0,#1,__entry_work_pending
 
 	movsg		psr,gr23
-	andi		gr23,#~PSR_PIL,gr23	; could let do_syscall_trace() call schedule()
+	andi		gr23,#~PSR_PIL,gr23	; could let syscall_trace_exit() call schedule()
 	movgs		gr23,psr
 
-	setlos.p	#1,gr8
-	call		do_syscall_trace
+	call		syscall_trace_exit
 	bra		__entry_resume_userspace
 
 __syscall_badsys:
@@ -1527,5 +1524,7 @@
 	.long sys_inotify_init1
 	.long sys_preadv
 	.long sys_pwritev
+	.long sys_rt_tgsigqueueinfo	/* 335 */
+	.long sys_perf_counter_open
 
 syscall_table_size = (. - sys_call_table)
diff -druN linux-libre-2.6.30-gnu/arch/frv/kernel/frv_ksyms.c linux-libre-2.6.31-gnu/arch/frv/kernel/frv_ksyms.c
--- linux-libre-2.6.30-gnu/arch/frv/kernel/frv_ksyms.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/kernel/frv_ksyms.c	2009-09-09 18:13:59.000000000 -0400
@@ -67,6 +67,10 @@
 EXPORT_SYMBOL(__xchg_32);
 EXPORT_SYMBOL(__cmpxchg_32);
 #endif
+EXPORT_SYMBOL(atomic64_add_return);
+EXPORT_SYMBOL(atomic64_sub_return);
+EXPORT_SYMBOL(__xchg_64);
+EXPORT_SYMBOL(__cmpxchg_64);
 
 EXPORT_SYMBOL(__debug_bug_printk);
 EXPORT_SYMBOL(__delay_loops_MHz);
diff -druN linux-libre-2.6.30-gnu/arch/frv/kernel/init_task.c linux-libre-2.6.31-gnu/arch/frv/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/frv/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,10 +12,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/frv/kernel/module.c linux-libre-2.6.31-gnu/arch/frv/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/frv/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,8 +35,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* We don't need anything special. */
diff -druN linux-libre-2.6.30-gnu/arch/frv/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/frv/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/frv/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,9 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/regset.h>
+#include <linux/elf.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -33,6 +36,169 @@
  */
 
 /*
+ * retrieve the contents of FRV userspace general registers
+ */
+static int genregs_get(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       void *kbuf, void __user *ubuf)
+{
+	const struct user_int_regs *iregs = &target->thread.user->i;
+	int ret;
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  iregs, 0, sizeof(*iregs));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					sizeof(*iregs), -1);
+}
+
+/*
+ * update the contents of the FRV userspace general registers
+ */
+static int genregs_set(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       const void *kbuf, const void __user *ubuf)
+{
+	struct user_int_regs *iregs = &target->thread.user->i;
+	unsigned int offs_gr0, offs_gr1;
+	int ret;
+
+	/* not allowed to set PSR or __status */
+	if (pos < offsetof(struct user_int_regs, psr) + sizeof(long) &&
+	    pos + count > offsetof(struct user_int_regs, psr))
+		return -EIO;
+
+	if (pos < offsetof(struct user_int_regs, __status) + sizeof(long) &&
+	    pos + count > offsetof(struct user_int_regs, __status))
+		return -EIO;
+
+	/* set the control regs */
+	offs_gr0 = offsetof(struct user_int_regs, gr[0]);
+	offs_gr1 = offsetof(struct user_int_regs, gr[1]);
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 iregs, 0, offs_gr0);
+	if (ret < 0)
+		return ret;
+
+	/* skip GR0/TBR */
+	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					offs_gr0, offs_gr1);
+	if (ret < 0)
+		return ret;
+
+	/* set the general regs */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &iregs->gr[1], offs_gr1, sizeof(*iregs));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					sizeof(*iregs), -1);
+}
+
+/*
+ * retrieve the contents of FRV userspace FP/Media registers
+ */
+static int fpmregs_get(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       void *kbuf, void __user *ubuf)
+{
+	const struct user_fpmedia_regs *fpregs = &target->thread.user->f;
+	int ret;
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  fpregs, 0, sizeof(*fpregs));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					sizeof(*fpregs), -1);
+}
+
+/*
+ * update the contents of the FRV userspace FP/Media registers
+ */
+static int fpmregs_set(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       const void *kbuf, const void __user *ubuf)
+{
+	struct user_fpmedia_regs *fpregs = &target->thread.user->f;
+	int ret;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 fpregs, 0, sizeof(*fpregs));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					sizeof(*fpregs), -1);
+}
+
+/*
+ * determine if the FP/Media registers have actually been used
+ */
+static int fpmregs_active(struct task_struct *target,
+			  const struct user_regset *regset)
+{
+	return tsk_used_math(target) ? regset->n : 0;
+}
+
+/*
+ * Define the register sets available on the FRV under Linux
+ */
+enum frv_regset {
+	REGSET_GENERAL,
+	REGSET_FPMEDIA,
+};
+
+static const struct user_regset frv_regsets[] = {
+	/*
+	 * General register format is:
+	 *	PSR, ISR, CCR, CCCR, LR, LCR, PC, (STATUS), SYSCALLNO, ORIG_G8
+	 *	GNER0-1, IACC0, TBR, GR1-63
+	 */
+	[REGSET_GENERAL] = {
+		.core_note_type	= NT_PRSTATUS,
+		.n		= ELF_NGREG,
+		.size		= sizeof(long),
+		.align		= sizeof(long),
+		.get		= genregs_get,
+		.set		= genregs_set,
+	},
+	/*
+	 * FPU/Media register format is:
+	 *	FR0-63, FNER0-1, MSR0-1, ACC0-7, ACCG0-8, FSR
+	 */
+	[REGSET_FPMEDIA] = {
+		.core_note_type	= NT_PRFPREG,
+		.n		= sizeof(struct user_fpmedia_regs) / sizeof(long),
+		.size		= sizeof(long),
+		.align		= sizeof(long),
+		.get		= fpmregs_get,
+		.set		= fpmregs_set,
+		.active		= fpmregs_active,
+	},
+};
+
+static const struct user_regset_view user_frv_native_view = {
+	.name		= "frv",
+	.e_machine	= EM_FRV,
+	.regsets	= frv_regsets,
+	.n		= ARRAY_SIZE(frv_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &user_frv_native_view;
+}
+
+/*
  * Get contents of register REGNO in task TASK.
  */
 static inline long get_reg(struct task_struct *task, int regno)
@@ -69,40 +235,23 @@
 }
 
 /*
- * check that an address falls within the bounds of the target process's memory
- * mappings
- */
-static inline int is_user_addr_valid(struct task_struct *child,
-				     unsigned long start, unsigned long len)
-{
-#ifdef CONFIG_MMU
-	if (start >= PAGE_OFFSET || len > PAGE_OFFSET - start)
-		return -EIO;
-	return 0;
-#else
-	struct vm_area_struct *vma;
-
-	vma = find_vma(child->mm, start);
-	if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
-		return 0;
-
-	return -EIO;
-#endif
-}
-
-/*
  * Called by kernel/ptrace.c when detaching..
  *
  * Control h/w single stepping
  */
-void ptrace_disable(struct task_struct *child)
+void user_enable_single_step(struct task_struct *child)
+{
+	child->thread.frame0->__status |= REG__STATUS_STEP;
+}
+
+void user_disable_single_step(struct task_struct *child)
 {
 	child->thread.frame0->__status &= ~REG__STATUS_STEP;
 }
 
-void ptrace_enable(struct task_struct *child)
+void ptrace_disable(struct task_struct *child)
 {
-	child->thread.frame0->__status |= REG__STATUS_STEP;
+	user_disable_single_step(child);
 }
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -111,15 +260,6 @@
 	int ret;
 
 	switch (request) {
-		/* when I and D space are separate, these will need to be fixed. */
-	case PTRACE_PEEKTEXT: /* read word at location addr. */
-	case PTRACE_PEEKDATA:
-		ret = -EIO;
-		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
-			break;
-		ret = generic_ptrace_peekdata(child, addr, data);
-		break;
-
 		/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR: {
 		tmp = 0;
@@ -163,15 +303,6 @@
 		break;
 	}
 
-		/* when I and D space are separate, this will have to be fixed. */
-	case PTRACE_POKETEXT: /* write the word at location addr. */
-	case PTRACE_POKEDATA:
-		ret = -EIO;
-		if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
-			break;
-		ret = generic_ptrace_pokedata(child, addr, data);
-		break;
-
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
 		ret = -EIO;
 		if ((addr & 3) || addr < 0)
@@ -179,7 +310,7 @@
 
 		ret = 0;
 		switch (addr >> 2) {
-		case 0 ... PT__END-1:
+		case 0 ... PT__END - 1:
 			ret = put_reg(child, addr >> 2, data);
 			break;
 
@@ -189,95 +320,29 @@
 		}
 		break;
 
-	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-	case PTRACE_CONT: /* restart after signal. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		ptrace_disable(child);
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-		/* make the child exit.  Best I can do is send it a sigkill.
-		 * perhaps it should be put in the status that it wants to
-		 * exit.
-		 */
-	case PTRACE_KILL:
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
-		ptrace_disable(child);
-		wake_up_process(child);
-		break;
-
-	case PTRACE_SINGLESTEP:  /* set the trap flag. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		ptrace_enable(child);
-		child->exit_code = data;
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-	case PTRACE_DETACH:	/* detach a process that was attached. */
-		ret = ptrace_detach(child, data);
-		break;
-
-	case PTRACE_GETREGS: { /* Get all integer regs from the child. */
-		int i;
-		for (i = 0; i < PT__GPEND; i++) {
-			tmp = get_reg(child, i);
-			if (put_user(tmp, (unsigned long *) data)) {
-				ret = -EFAULT;
-				break;
-			}
-			data += sizeof(long);
-		}
-		ret = 0;
-		break;
-	}
+	case PTRACE_GETREGS:	/* Get all integer regs from the child. */
+		return copy_regset_to_user(child, &user_frv_native_view,
+					   REGSET_GENERAL,
+					   0, sizeof(child->thread.user->i),
+					   (void __user *)data);
 
-	case PTRACE_SETREGS: { /* Set all integer regs in the child. */
-		int i;
-		for (i = 0; i < PT__GPEND; i++) {
-			if (get_user(tmp, (unsigned long *) data)) {
-				ret = -EFAULT;
-				break;
-			}
-			put_reg(child, i, tmp);
-			data += sizeof(long);
-		}
-		ret = 0;
-		break;
-	}
+	case PTRACE_SETREGS:	/* Set all integer regs in the child. */
+		return copy_regset_from_user(child, &user_frv_native_view,
+					     REGSET_GENERAL,
+					     0, sizeof(child->thread.user->i),
+					     (const void __user *)data);
 
-	case PTRACE_GETFPREGS: { /* Get the child FP/Media state. */
-		ret = 0;
-		if (copy_to_user((void *) data,
-				 &child->thread.user->f,
-				 sizeof(child->thread.user->f)))
-			ret = -EFAULT;
-		break;
-	}
+	case PTRACE_GETFPREGS:	/* Get the child FP/Media state. */
+		return copy_regset_to_user(child, &user_frv_native_view,
+					   REGSET_FPMEDIA,
+					   0, sizeof(child->thread.user->f),
+					   (void __user *)data);
 
-	case PTRACE_SETFPREGS: { /* Set the child FP/Media state. */
-		ret = 0;
-		if (copy_from_user(&child->thread.user->f,
-				   (void *) data,
-				   sizeof(child->thread.user->f)))
-			ret = -EFAULT;
-		break;
-	}
+	case PTRACE_SETFPREGS:	/* Set the child FP/Media state. */
+		return copy_regset_from_user(child, &user_frv_native_view,
+					     REGSET_FPMEDIA,
+					     0, sizeof(child->thread.user->f),
+					     (const void __user *)data);
 
 	case PTRACE_GETFDPIC:
 		tmp = 0;
@@ -300,414 +365,36 @@
 		break;
 
 	default:
-		ret = -EIO;
+		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
 	return ret;
 }
 
-int __nongprelbss kstrace;
-
-static const struct {
-	const char	*name;
-	unsigned	argmask;
-} __syscall_name_table[NR_syscalls] = {
-	[0]	= { "restart_syscall"			},
-	[1]	= { "exit",		0x000001	},
-	[2]	= { "fork",		0xffffff	},
-	[3]	= { "read",		0x000141	},
-	[4]	= { "write",		0x000141	},
-	[5]	= { "open",		0x000235	},
-	[6]	= { "close",		0x000001	},
-	[7]	= { "waitpid",		0x000141	},
-	[8]	= { "creat",		0x000025	},
-	[9]	= { "link",		0x000055	},
-	[10]	= { "unlink",		0x000005	},
-	[11]	= { "execve",		0x000445	},
-	[12]	= { "chdir",		0x000005	},
-	[13]	= { "time",		0x000004	},
-	[14]	= { "mknod",		0x000325	},
-	[15]	= { "chmod",		0x000025	},
-	[16]	= { "lchown",		0x000025	},
-	[17]	= { "break" },
-	[18]	= { "oldstat",		0x000045	},
-	[19]	= { "lseek",		0x000131	},
-	[20]	= { "getpid",		0xffffff	},
-	[21]	= { "mount",		0x043555	},
-	[22]	= { "umount",		0x000005	},
-	[23]	= { "setuid",		0x000001	},
-	[24]	= { "getuid",		0xffffff	},
-	[25]	= { "stime",		0x000004	},
-	[26]	= { "ptrace",		0x004413	},
-	[27]	= { "alarm",		0x000001	},
-	[28]	= { "oldfstat",		0x000041	},
-	[29]	= { "pause",		0xffffff	},
-	[30]	= { "utime",		0x000045	},
-	[31]	= { "stty" },
-	[32]	= { "gtty" },
-	[33]	= { "access",		0x000025	},
-	[34]	= { "nice",		0x000001	},
-	[35]	= { "ftime" },
-	[36]	= { "sync",		0xffffff	},
-	[37]	= { "kill",		0x000011	},
-	[38]	= { "rename",		0x000055	},
-	[39]	= { "mkdir",		0x000025	},
-	[40]	= { "rmdir",		0x000005	},
-	[41]	= { "dup",		0x000001	},
-	[42]	= { "pipe",		0x000004	},
-	[43]	= { "times",		0x000004	},
-	[44]	= { "prof" },
-	[45]	= { "brk",		0x000004	},
-	[46]	= { "setgid",		0x000001	},
-	[47]	= { "getgid",		0xffffff	},
-	[48]	= { "signal",		0x000041	},
-	[49]	= { "geteuid",		0xffffff	},
-	[50]	= { "getegid",		0xffffff	},
-	[51]	= { "acct",		0x000005	},
-	[52]	= { "umount2",		0x000035	},
-	[53]	= { "lock" },
-	[54]	= { "ioctl",		0x000331	},
-	[55]	= { "fcntl",		0x000331	},
-	[56]	= { "mpx" },
-	[57]	= { "setpgid",		0x000011	},
-	[58]	= { "ulimit" },
-	[60]	= { "umask",		0x000002	},
-	[61]	= { "chroot",		0x000005	},
-	[62]	= { "ustat",		0x000043	},
-	[63]	= { "dup2",		0x000011	},
-	[64]	= { "getppid",		0xffffff	},
-	[65]	= { "getpgrp",		0xffffff	},
-	[66]	= { "setsid",		0xffffff	},
-	[67]	= { "sigaction" },
-	[68]	= { "sgetmask" },
-	[69]	= { "ssetmask" },
-	[70]	= { "setreuid" },
-	[71]	= { "setregid" },
-	[72]	= { "sigsuspend" },
-	[73]	= { "sigpending" },
-	[74]	= { "sethostname" },
-	[75]	= { "setrlimit" },
-	[76]	= { "getrlimit" },
-	[77]	= { "getrusage" },
-	[78]	= { "gettimeofday" },
-	[79]	= { "settimeofday" },
-	[80]	= { "getgroups" },
-	[81]	= { "setgroups" },
-	[82]	= { "select" },
-	[83]	= { "symlink" },
-	[84]	= { "oldlstat" },
-	[85]	= { "readlink" },
-	[86]	= { "uselib" },
-	[87]	= { "swapon" },
-	[88]	= { "reboot" },
-	[89]	= { "readdir" },
-	[91]	= { "munmap",		0x000034	},
-	[92]	= { "truncate" },
-	[93]	= { "ftruncate" },
-	[94]	= { "fchmod" },
-	[95]	= { "fchown" },
-	[96]	= { "getpriority" },
-	[97]	= { "setpriority" },
-	[99]	= { "statfs" },
-	[100]	= { "fstatfs" },
-	[102]	= { "socketcall" },
-	[103]	= { "syslog" },
-	[104]	= { "setitimer" },
-	[105]	= { "getitimer" },
-	[106]	= { "stat" },
-	[107]	= { "lstat" },
-	[108]	= { "fstat" },
-	[111]	= { "vhangup" },
-	[114]	= { "wait4" },
-	[115]	= { "swapoff" },
-	[116]	= { "sysinfo" },
-	[117]	= { "ipc" },
-	[118]	= { "fsync" },
-	[119]	= { "sigreturn" },
-	[120]	= { "clone" },
-	[121]	= { "setdomainname" },
-	[122]	= { "uname" },
-	[123]	= { "modify_ldt" },
-	[123]	= { "cacheflush" },
-	[124]	= { "adjtimex" },
-	[125]	= { "mprotect" },
-	[126]	= { "sigprocmask" },
-	[127]	= { "create_module" },
-	[128]	= { "init_module" },
-	[129]	= { "delete_module" },
-	[130]	= { "get_kernel_syms" },
-	[131]	= { "quotactl" },
-	[132]	= { "getpgid" },
-	[133]	= { "fchdir" },
-	[134]	= { "bdflush" },
-	[135]	= { "sysfs" },
-	[136]	= { "personality" },
-	[137]	= { "afs_syscall" },
-	[138]	= { "setfsuid" },
-	[139]	= { "setfsgid" },
-	[140]	= { "_llseek",			0x014331	},
-	[141]	= { "getdents" },
-	[142]	= { "_newselect",		0x000141	},
-	[143]	= { "flock" },
-	[144]	= { "msync" },
-	[145]	= { "readv" },
-	[146]	= { "writev" },
-	[147]	= { "getsid",			0x000001	},
-	[148]	= { "fdatasync",		0x000001	},
-	[149]	= { "_sysctl",			0x000004	},
-	[150]	= { "mlock" },
-	[151]	= { "munlock" },
-	[152]	= { "mlockall" },
-	[153]	= { "munlockall" },
-	[154]	= { "sched_setparam" },
-	[155]	= { "sched_getparam" },
-	[156]	= { "sched_setscheduler" },
-	[157]	= { "sched_getscheduler" },
-	[158]	= { "sched_yield" },
-	[159]	= { "sched_get_priority_max" },
-	[160]	= { "sched_get_priority_min" },
-	[161]	= { "sched_rr_get_interval" },
-	[162]	= { "nanosleep",		0x000044	},
-	[163]	= { "mremap" },
-	[164]	= { "setresuid" },
-	[165]	= { "getresuid" },
-	[166]	= { "vm86" },
-	[167]	= { "query_module" },
-	[168]	= { "poll" },
-	[169]	= { "nfsservctl" },
-	[170]	= { "setresgid" },
-	[171]	= { "getresgid" },
-	[172]	= { "prctl",			0x333331	},
-	[173]	= { "rt_sigreturn",		0xffffff	},
-	[174]	= { "rt_sigaction",		0x001441	},
-	[175]	= { "rt_sigprocmask",		0x001441	},
-	[176]	= { "rt_sigpending",		0x000014	},
-	[177]	= { "rt_sigtimedwait",		0x001444	},
-	[178]	= { "rt_sigqueueinfo",		0x000411	},
-	[179]	= { "rt_sigsuspend",		0x000014	},
-	[180]	= { "pread",			0x003341	},
-	[181]	= { "pwrite",			0x003341	},
-	[182]	= { "chown",			0x000115	},
-	[183]	= { "getcwd" },
-	[184]	= { "capget" },
-	[185]	= { "capset" },
-	[186]	= { "sigaltstack" },
-	[187]	= { "sendfile" },
-	[188]	= { "getpmsg" },
-	[189]	= { "putpmsg" },
-	[190]	= { "vfork",			0xffffff	},
-	[191]	= { "ugetrlimit" },
-	[192]	= { "mmap2",			0x313314	},
-	[193]	= { "truncate64" },
-	[194]	= { "ftruncate64" },
-	[195]	= { "stat64",			0x000045	},
-	[196]	= { "lstat64",			0x000045	},
-	[197]	= { "fstat64",			0x000041	},
-	[198]	= { "lchown32" },
-	[199]	= { "getuid32",			0xffffff	},
-	[200]	= { "getgid32",			0xffffff	},
-	[201]	= { "geteuid32",		0xffffff	},
-	[202]	= { "getegid32",		0xffffff	},
-	[203]	= { "setreuid32" },
-	[204]	= { "setregid32" },
-	[205]	= { "getgroups32" },
-	[206]	= { "setgroups32" },
-	[207]	= { "fchown32" },
-	[208]	= { "setresuid32" },
-	[209]	= { "getresuid32" },
-	[210]	= { "setresgid32" },
-	[211]	= { "getresgid32" },
-	[212]	= { "chown32" },
-	[213]	= { "setuid32" },
-	[214]	= { "setgid32" },
-	[215]	= { "setfsuid32" },
-	[216]	= { "setfsgid32" },
-	[217]	= { "pivot_root" },
-	[218]	= { "mincore" },
-	[219]	= { "madvise" },
-	[220]	= { "getdents64" },
-	[221]	= { "fcntl64" },
-	[223]	= { "security" },
-	[224]	= { "gettid" },
-	[225]	= { "readahead" },
-	[226]	= { "setxattr" },
-	[227]	= { "lsetxattr" },
-	[228]	= { "fsetxattr" },
-	[229]	= { "getxattr" },
-	[230]	= { "lgetxattr" },
-	[231]	= { "fgetxattr" },
-	[232]	= { "listxattr" },
-	[233]	= { "llistxattr" },
-	[234]	= { "flistxattr" },
-	[235]	= { "removexattr" },
-	[236]	= { "lremovexattr" },
-	[237]	= { "fremovexattr" },
-	[238]	= { "tkill" },
-	[239]	= { "sendfile64" },
-	[240]	= { "futex" },
-	[241]	= { "sched_setaffinity" },
-	[242]	= { "sched_getaffinity" },
-	[243]	= { "set_thread_area" },
-	[244]	= { "get_thread_area" },
-	[245]	= { "io_setup" },
-	[246]	= { "io_destroy" },
-	[247]	= { "io_getevents" },
-	[248]	= { "io_submit" },
-	[249]	= { "io_cancel" },
-	[250]	= { "fadvise64" },
-	[252]	= { "exit_group",		0x000001	},
-	[253]	= { "lookup_dcookie" },
-	[254]	= { "epoll_create" },
-	[255]	= { "epoll_ctl" },
-	[256]	= { "epoll_wait" },
-	[257]	= { "remap_file_pages" },
-	[258]	= { "set_tid_address" },
-	[259]	= { "timer_create" },
-	[260]	= { "timer_settime" },
-	[261]	= { "timer_gettime" },
-	[262]	= { "timer_getoverrun" },
-	[263]	= { "timer_delete" },
-	[264]	= { "clock_settime" },
-	[265]	= { "clock_gettime" },
-	[266]	= { "clock_getres" },
-	[267]	= { "clock_nanosleep" },
-	[268]	= { "statfs64" },
-	[269]	= { "fstatfs64" },
-	[270]	= { "tgkill" },
-	[271]	= { "utimes" },
-	[272]	= { "fadvise64_64" },
-	[273]	= { "vserver" },
-	[274]	= { "mbind" },
-	[275]	= { "get_mempolicy" },
-	[276]	= { "set_mempolicy" },
-	[277]	= { "mq_open" },
-	[278]	= { "mq_unlink" },
-	[279]	= { "mq_timedsend" },
-	[280]	= { "mq_timedreceive" },
-	[281]	= { "mq_notify" },
-	[282]	= { "mq_getsetattr" },
-	[283]	= { "sys_kexec_load" },
-};
-
-asmlinkage void do_syscall_trace(int leaving)
+/*
+ * handle tracing of system call entry
+ * - return the revised system call number or ULONG_MAX to cause ENOSYS
+ */
+asmlinkage unsigned long syscall_trace_entry(void)
 {
-#if 0
-	unsigned long *argp;
-	const char *name;
-	unsigned argmask;
-	char buffer[16];
-
-	if (!kstrace)
-		return;
-
-	if (!current->mm)
-		return;
-
-	if (__frame->gr7 == __NR_close)
-		return;
-
-#if 0
-	if (__frame->gr7 != __NR_mmap2 &&
-	    __frame->gr7 != __NR_vfork &&
-	    __frame->gr7 != __NR_execve &&
-	    __frame->gr7 != __NR_exit)
-		return;
-#endif
-
-	argmask = 0;
-	name = NULL;
-	if (__frame->gr7 < NR_syscalls) {
-		name = __syscall_name_table[__frame->gr7].name;
-		argmask = __syscall_name_table[__frame->gr7].argmask;
-	}
-	if (!name) {
-		sprintf(buffer, "sys_%lx", __frame->gr7);
-		name = buffer;
-	}
-
-	if (!leaving) {
-		if (!argmask) {
-			printk(KERN_CRIT "[%d] %s(%lx,%lx,%lx,%lx,%lx,%lx)\n",
-			       current->pid,
-			       name,
-			       __frame->gr8,
-			       __frame->gr9,
-			       __frame->gr10,
-			       __frame->gr11,
-			       __frame->gr12,
-			       __frame->gr13);
-		}
-		else if (argmask == 0xffffff) {
-			printk(KERN_CRIT "[%d] %s()\n",
-			       current->pid,
-			       name);
-		}
-		else {
-			printk(KERN_CRIT "[%d] %s(",
-			       current->pid,
-			       name);
-
-			argp = &__frame->gr8;
-
-			do {
-				switch (argmask & 0xf) {
-				case 1:
-					printk("%ld", (long) *argp);
-					break;
-				case 2:
-					printk("%lo", *argp);
-					break;
-				case 3:
-					printk("%lx", *argp);
-					break;
-				case 4:
-					printk("%p", (void *) *argp);
-					break;
-				case 5:
-					printk("\"%s\"", (char *) *argp);
-					break;
-				}
-
-				argp++;
-				argmask >>= 4;
-				if (argmask)
-					printk(",");
-
-			} while (argmask);
-
-			printk(")\n");
-		}
-	}
-	else {
-		if ((int)__frame->gr8 > -4096 && (int)__frame->gr8 < 4096)
-			printk(KERN_CRIT "[%d] %s() = %ld\n", current->pid, name, __frame->gr8);
-		else
-			printk(KERN_CRIT "[%d] %s() = %lx\n", current->pid, name, __frame->gr8);
+	__frame->__status |= REG__STATUS_SYSC_ENTRY;
+	if (tracehook_report_syscall_entry(__frame)) {
+		/* tracing decided this syscall should not happen, so
+		 * We'll return a bogus call number to get an ENOSYS
+		 * error, but leave the original number in
+		 * __frame->syscallno
+		 */
+		return ULONG_MAX;
 	}
-	return;
-#endif
-
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
-
-	if (!(current->ptrace & PT_PTRACED))
-		return;
-
-	/* we need to indicate entry or exit to strace */
-	if (leaving)
-		__frame->__status |= REG__STATUS_SYSC_EXIT;
-	else
-		__frame->__status |= REG__STATUS_SYSC_ENTRY;
 
-	ptrace_notify(SIGTRAP);
+	return __frame->syscallno;
+}
 
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
+/*
+ * handle tracing of system call exit
+ */
+asmlinkage void syscall_trace_exit(void)
+{
+	__frame->__status |= REG__STATUS_SYSC_EXIT;
+	tracehook_report_syscall_exit(__frame, 0);
 }
diff -druN linux-libre-2.6.30-gnu/arch/frv/kernel/signal.c linux-libre-2.6.31-gnu/arch/frv/kernel/signal.c
--- linux-libre-2.6.30-gnu/arch/frv/kernel/signal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/kernel/signal.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/unistd.h>
 #include <linux/personality.h>
 #include <linux/freezer.h>
+#include <linux/tracehook.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -516,6 +517,9 @@
 			 * clear the TIF_RESTORE_SIGMASK flag */
 			if (test_thread_flag(TIF_RESTORE_SIGMASK))
 				clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+			tracehook_signal_handler(signr, &info, &ka, __frame,
+						 test_thread_flag(TIF_SINGLESTEP));
 		}
 
 		return;
@@ -564,4 +568,10 @@
 	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
 		do_signal();
 
+	/* deal with notification on about to resume userspace execution */
+	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(__frame);
+	}
+
 } /* end do_notify_resume() */
diff -druN linux-libre-2.6.30-gnu/arch/frv/kernel/uaccess.c linux-libre-2.6.31-gnu/arch/frv/kernel/uaccess.c
--- linux-libre-2.6.30-gnu/arch/frv/kernel/uaccess.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/kernel/uaccess.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,7 @@
 	char *p, ch;
 	long err = -EFAULT;
 
-	if (count < 0)
-		BUG();
+	BUG_ON(count < 0);
 
 	p = dst;
 
@@ -76,8 +75,7 @@
 	long err = 0;
 	char ch;
 
-	if (count < 0)
-		BUG();
+	BUG_ON(count < 0);
 
 #ifndef CONFIG_MMU
 	if ((unsigned long) src < memory_start)
diff -druN linux-libre-2.6.30-gnu/arch/frv/lib/atomic64-ops.S linux-libre-2.6.31-gnu/arch/frv/lib/atomic64-ops.S
--- linux-libre-2.6.30-gnu/arch/frv/lib/atomic64-ops.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/frv/lib/atomic64-ops.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,162 @@
+/* kernel atomic64 operations
+ *
+ * For an explanation of how atomic ops work in this arch, see:
+ *   Documentation/frv/atomic-ops.txt
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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 <asm/spr-regs.h>
+
+	.text
+	.balign 4
+
+
+###############################################################################
+#
+# long long atomic64_inc_return(atomic64_t *v)
+#
+###############################################################################
+	.globl		atomic64_inc_return
+        .type		atomic64_inc_return,@function
+atomic64_inc_return:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ldd.p		@(gr10,gr0),gr8			/* LDD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	addicc		gr9,#1,gr9,icc0
+	addxi		gr8,#0,gr8,icc0
+	cstd.p		gr8,@(gr10,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic64_inc_return, .-atomic64_inc_return
+
+###############################################################################
+#
+# long long atomic64_dec_return(atomic64_t *v)
+#
+###############################################################################
+	.globl		atomic64_dec_return
+        .type		atomic64_dec_return,@function
+atomic64_dec_return:
+	or.p		gr8,gr8,gr10
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ldd.p		@(gr10,gr0),gr8			/* LDD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	subicc		gr9,#1,gr9,icc0
+	subxi		gr8,#0,gr8,icc0
+	cstd.p		gr8,@(gr10,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic64_dec_return, .-atomic64_dec_return
+
+###############################################################################
+#
+# long long atomic64_add_return(long long i, atomic64_t *v)
+#
+###############################################################################
+	.globl		atomic64_add_return
+        .type		atomic64_add_return,@function
+atomic64_add_return:
+	or.p		gr8,gr8,gr4
+	or		gr9,gr9,gr5
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ldd.p		@(gr10,gr0),gr8			/* LDD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	addcc		gr9,gr5,gr9,icc0
+	addx		gr8,gr4,gr8,icc0
+	cstd.p		gr8,@(gr10,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic64_add_return, .-atomic64_add_return
+
+###############################################################################
+#
+# long long atomic64_sub_return(long long i, atomic64_t *v)
+#
+###############################################################################
+	.globl		atomic64_sub_return
+        .type		atomic64_sub_return,@function
+atomic64_sub_return:
+	or.p		gr8,gr8,gr4
+	or		gr9,gr9,gr5
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ldd.p		@(gr10,gr0),gr8			/* LDD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	subcc		gr9,gr5,gr9,icc0
+	subx		gr8,gr4,gr8,icc0
+	cstd.p		gr8,@(gr10,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		atomic64_sub_return, .-atomic64_sub_return
+
+###############################################################################
+#
+# uint64_t __xchg_64(uint64_t i, uint64_t *v)
+#
+###############################################################################
+	.globl		__xchg_64
+        .type		__xchg_64,@function
+__xchg_64:
+	or.p		gr8,gr8,gr4
+	or		gr9,gr9,gr5
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ldd.p		@(gr10,gr0),gr8			/* LDD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3			/* set CC3 to true */
+	cstd.p		gr4,@(gr10,gr0)		,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		__xchg_64, .-__xchg_64
+
+###############################################################################
+#
+# uint64_t __cmpxchg_64(uint64_t test, uint64_t new, uint64_t *v)
+#
+###############################################################################
+	.globl		__cmpxchg_64
+        .type		__cmpxchg_64,@function
+__cmpxchg_64:
+	or.p		gr8,gr8,gr4
+	or		gr9,gr9,gr5
+0:
+	orcc		gr0,gr0,gr0,icc3		/* set ICC3.Z */
+	ckeq		icc3,cc7
+	ldd.p		@(gr12,gr0),gr8			/* LDD.P/ORCR must be atomic */
+	orcr		cc7,cc7,cc3
+	subcc		gr8,gr4,gr0,icc0
+	subcc.p		gr9,gr5,gr0,icc1
+	bnelr		icc0,#0
+	bnelr		icc1,#0
+	cstd.p		gr10,@(gr12,gr0)	,cc3,#1
+	corcc		gr29,gr29,gr0		,cc3,#1	/* clear ICC3.Z if store happens */
+	beq		icc3,#0,0b
+	bralr
+
+	.size		__cmpxchg_64, .-__cmpxchg_64
+
diff -druN linux-libre-2.6.30-gnu/arch/frv/lib/atomic-ops.S linux-libre-2.6.31-gnu/arch/frv/lib/atomic-ops.S
--- linux-libre-2.6.30-gnu/arch/frv/lib/atomic-ops.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/lib/atomic-ops.S	2009-09-09 18:13:59.000000000 -0400
@@ -163,11 +163,10 @@
 	ld.p		@(gr11,gr0),gr8
 	orcr		cc7,cc7,cc3
 	subcc		gr8,gr9,gr7,icc0
-	bne		icc0,#0,1f
+	bnelr		icc0,#0
 	cst.p		gr10,@(gr11,gr0)	,cc3,#1
 	corcc		gr29,gr29,gr0		,cc3,#1
 	beq		icc3,#0,0b
-1:
 	bralr
 
 	.size		__cmpxchg_32, .-__cmpxchg_32
diff -druN linux-libre-2.6.30-gnu/arch/frv/lib/Makefile linux-libre-2.6.31-gnu/arch/frv/lib/Makefile
--- linux-libre-2.6.30-gnu/arch/frv/lib/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/lib/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,5 +4,5 @@
 
 lib-y := \
 	__ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \
-	checksum.o memcpy.o memset.o atomic-ops.o \
-	outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
+	checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \
+	outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o perf_counter.o
diff -druN linux-libre-2.6.30-gnu/arch/frv/lib/perf_counter.c linux-libre-2.6.31-gnu/arch/frv/lib/perf_counter.c
--- linux-libre-2.6.30-gnu/arch/frv/lib/perf_counter.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/frv/lib/perf_counter.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,19 @@
+/* Performance counter handling
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/perf_counter.h>
+
+/*
+ * mark the performance counter as pending
+ */
+void set_perf_counter_pending(void)
+{
+}
diff -druN linux-libre-2.6.30-gnu/arch/frv/mb93090-mb00/pci-dma.c linux-libre-2.6.31-gnu/arch/frv/mb93090-mb00/pci-dma.c
--- linux-libre-2.6.30-gnu/arch/frv/mb93090-mb00/pci-dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/mb93090-mb00/pci-dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,8 +48,7 @@
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 			  enum dma_data_direction direction)
 {
-	if (direction == DMA_NONE)
-                BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	frv_cache_wback_inv((unsigned long) ptr, (unsigned long) ptr + size);
 
@@ -81,8 +80,7 @@
 	void *vaddr;
 	int i;
 
-	if (direction == DMA_NONE)
-                BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	dampr2 = __get_DAMPR(2);
 
diff -druN linux-libre-2.6.30-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c linux-libre-2.6.31-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c
--- linux-libre-2.6.30-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -116,8 +116,7 @@
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 			  enum dma_data_direction direction)
 {
-	if (direction == DMA_NONE)
-                BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	frv_cache_wback_inv((unsigned long) ptr, (unsigned long) ptr + size);
 
@@ -151,8 +150,7 @@
 		frv_cache_wback_inv(sg_dma_address(&sg[i]),
 				    sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]));
 
-	if (direction == DMA_NONE)
-                BUG();
+	BUG_ON(direction == DMA_NONE);
 
 	return nents;
 }
diff -druN linux-libre-2.6.30-gnu/arch/frv/mm/fault.c linux-libre-2.6.31-gnu/arch/frv/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/frv/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/frv/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -163,7 +163,7 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, ear0, write);
+	fault = handle_mm_fault(mm, vma, ear0, write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/h8300/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/h8300/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/h8300/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -141,5 +141,5 @@
 #define smp_mb__before_atomic_inc()    barrier()
 #define smp_mb__after_atomic_inc() barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* __ARCH_H8300_ATOMIC __ */
diff -druN linux-libre-2.6.30-gnu/arch/h8300/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/h8300/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/h8300/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/h8300/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/h8300/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/h8300/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/h8300/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,21 +1,6 @@
 #ifndef _ASM_H8300_KMAP_TYPES_H
 #define _ASM_H8300_KMAP_TYPES_H
 
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/h8300/include/asm/mman.h linux-libre-2.6.31-gnu/arch/h8300/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/h8300/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __H8300_MMAN_H__
 #define __H8300_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/h8300/include/asm/page.h linux-libre-2.6.31-gnu/arch/h8300/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/h8300/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -73,6 +73,6 @@
 #endif /* __ASSEMBLY__ */
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _H8300_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/h8300/include/asm/signal.h linux-libre-2.6.31-gnu/arch/h8300/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/h8300/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -105,7 +105,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/h8300/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/h8300/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/h8300/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,7 @@
 	.exec_domain =	&default_exec_domain,	\
 	.flags =	0,			\
 	.cpu =		0,			\
-	.preempt_count = 1,			\
+	.preempt_count = INIT_PREEMPT_COUNT,	\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
diff -druN linux-libre-2.6.30-gnu/arch/h8300/Kconfig.cpu linux-libre-2.6.31-gnu/arch/h8300/Kconfig.cpu
--- linux-libre-2.6.30-gnu/arch/h8300/Kconfig.cpu	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/Kconfig.cpu	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,7 @@
 
 config H8300H_AKI3068NET
 	bool "AE-3068/69"
-	select CONFIG_H83068
+	select H83068
 	help
 	  AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support
 	  More Information. (Japanese Only)
@@ -24,7 +24,7 @@
 
 config H8300H_H8MAX
 	bool "H8MAX"
-	select CONFIG_H83068
+	select H83068
 	help
 	  H8MAX Evaluation Board Support
 	  More Information. (Japanese Only)
@@ -32,7 +32,7 @@
 
 config H8300H_SIM
 	bool "H8/300H Simulator"
-	select CONFIG_H83007
+	select H83007
 	help
 	  GDB Simulator Support
 	  More Information.
@@ -45,7 +45,7 @@
 
 config H8S_EDOSK2674
 	bool "EDOSK-2674"
-	select CONFIG_H8S2768
+	select H8S2678
 	help
 	  Renesas EDOSK-2674 Evaluation Board Support
 	  More Information.
diff -druN linux-libre-2.6.30-gnu/arch/h8300/kernel/asm-offsets.c linux-libre-2.6.31-gnu/arch/h8300/kernel/asm-offsets.c
--- linux-libre-2.6.30-gnu/arch/h8300/kernel/asm-offsets.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/kernel/asm-offsets.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,6 @@
 	DEFINE(LRET,  offsetof(struct pt_regs, pc)       - sizeof(long));
 
 	DEFINE(PT_PTRACED, PT_PTRACED);
-	DEFINE(PT_DTRACE, PT_DTRACE);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/h8300/kernel/init_task.c linux-libre-2.6.31-gnu/arch/h8300/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/h8300/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,10 +14,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial task structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/h8300/kernel/module.c linux-libre-2.6.31-gnu/arch/h8300/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/h8300/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/h8300/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* We don't need anything special. */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/hp/common/sba_iommu.c linux-libre-2.6.31-gnu/arch/ia64/hp/common/sba_iommu.c
--- linux-libre-2.6.30-gnu/arch/ia64/hp/common/sba_iommu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/hp/common/sba_iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -1131,7 +1131,7 @@
 #ifdef CONFIG_NUMA
 	{
 		struct page *page;
-		page = alloc_pages_node(ioc->node == MAX_NUMNODES ?
+		page = alloc_pages_exact_node(ioc->node == MAX_NUMNODES ?
 		                        numa_node_id() : ioc->node, flags,
 		                        get_order(size));
 
@@ -1787,7 +1787,7 @@
 };
 
 static struct ioc * __init
-ioc_init(u64 hpa, void *handle)
+ioc_init(unsigned long hpa, void *handle)
 {
 	struct ioc *ioc;
 	struct ioc_iommu *info;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/hp/sim/hpsim_irq.c linux-libre-2.6.31-gnu/arch/ia64/hp/sim/hpsim_irq.c
--- linux-libre-2.6.30-gnu/arch/ia64/hp/sim/hpsim_irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/hp/sim/hpsim_irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,12 +21,13 @@
 {
 }
 
-static void
+static int
 hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
 {
+	return 0;
 }
 
-static struct hw_interrupt_type irq_type_hp_sim = {
+static struct irq_chip irq_type_hp_sim = {
 	.name =		"hpsim",
 	.startup =	hpsim_irq_startup,
 	.shutdown =	hpsim_irq_noop,
@@ -40,12 +41,12 @@
 void __init
 hpsim_irq_init (void)
 {
-	irq_desc_t *idesc;
+	struct irq_desc *idesc;
 	int i;
 
 	for (i = 0; i < NR_IRQS; ++i) {
 		idesc = irq_desc + i;
-		if (idesc->chip == &no_irq_type)
+		if (idesc->chip == &no_irq_chip)
 			idesc->chip = &irq_type_hp_sim;
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -216,5 +216,5 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* _ASM_IA64_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/bitops.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/bitops.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/bitops.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/bitops.h	2009-09-09 18:13:59.000000000 -0400
@@ -286,7 +286,7 @@
 {
 	__u32 *p = (__u32 *) addr + (nr >> 5);
 	__u32 m = 1 << (nr & 31);
-	int oldbitset = *p & m;
+	int oldbitset = (*p & m) != 0;
 
 	*p &= ~m;
 	return oldbitset;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,8 @@
+#ifndef __ASM_IA64_BITSPERLONG_H
+#define __ASM_IA64_BITSPERLONG_H
+
+#define __BITS_PER_LONG 64
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_IA64_BITSPERLONG_H */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,7 @@
 #include <asm/machvec.h>
 #include <linux/scatterlist.h>
 #include <asm/swiotlb.h>
+#include <linux/dma-debug.h>
 
 #define ARCH_HAS_DMA_GET_REQUIRED_MASK
 
@@ -24,95 +25,28 @@
 				       dma_addr_t *daddr, gfp_t gfp)
 {
 	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	return ops->alloc_coherent(dev, size, daddr, gfp);
+	void *caddr;
+
+	caddr = ops->alloc_coherent(dev, size, daddr, gfp);
+	debug_dma_alloc_coherent(dev, size, *daddr, caddr);
+	return caddr;
 }
 
 static inline void dma_free_coherent(struct device *dev, size_t size,
 				     void *caddr, dma_addr_t daddr)
 {
 	struct dma_map_ops *ops = platform_dma_get_ops(dev);
+	debug_dma_free_coherent(dev, size, caddr, daddr);
 	ops->free_coherent(dev, size, caddr, daddr);
 }
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
-static inline dma_addr_t dma_map_single_attrs(struct device *dev,
-					      void *caddr, size_t size,
-					      enum dma_data_direction dir,
-					      struct dma_attrs *attrs)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	return ops->map_page(dev, virt_to_page(caddr),
-			     (unsigned long)caddr & ~PAGE_MASK, size,
-			     dir, attrs);
-}
-
-static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t daddr,
-					  size_t size,
-					  enum dma_data_direction dir,
-					  struct dma_attrs *attrs)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	ops->unmap_page(dev, daddr, size, dir, attrs);
-}
-
-#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
-#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
-
-static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
-				   int nents, enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	return ops->map_sg(dev, sgl, nents, dir, attrs);
-}
-
-static inline void dma_unmap_sg_attrs(struct device *dev,
-				      struct scatterlist *sgl, int nents,
-				      enum dma_data_direction dir,
-				      struct dma_attrs *attrs)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	ops->unmap_sg(dev, sgl, nents, dir, attrs);
-}
-
-#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
-#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
-
-static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t daddr,
-					   size_t size,
-					   enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	ops->sync_single_for_cpu(dev, daddr, size, dir);
-}
-
-static inline void dma_sync_sg_for_cpu(struct device *dev,
-				       struct scatterlist *sgl,
-				       int nents, enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	ops->sync_sg_for_cpu(dev, sgl, nents, dir);
-}
-
-static inline void dma_sync_single_for_device(struct device *dev,
-					      dma_addr_t daddr,
-					      size_t size,
-					      enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	ops->sync_single_for_device(dev, daddr, size, dir);
-}
+#define get_dma_ops(dev) platform_dma_get_ops(dev)
+#define flush_write_buffers()
 
-static inline void dma_sync_sg_for_device(struct device *dev,
-					  struct scatterlist *sgl,
-					  int nents,
-					  enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	ops->sync_sg_for_device(dev, sgl, nents, dir);
-}
+#include <asm-generic/dma-mapping-common.h>
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t daddr)
 {
@@ -120,30 +54,6 @@
 	return ops->mapping_error(dev, daddr);
 }
 
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-				      size_t offset, size_t size,
-				      enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-	return ops->map_page(dev, page, offset, size, dir, NULL);
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
-				  size_t size, enum dma_data_direction dir)
-{
-	dma_unmap_single(dev, addr, size, dir);
-}
-
-/*
- * Rest of this file is part of the "Advanced DMA API".  Use at your own risk.
- * See Documentation/DMA-API.txt for details.
- */
-
-#define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir)	\
-	dma_sync_single_for_cpu(dev, dma_handle, size, dir)
-#define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir)	\
-	dma_sync_single_for_device(dev, dma_handle, size, dir)
-
 static inline int dma_supported(struct device *dev, u64 mask)
 {
 	struct dma_map_ops *ops = platform_dma_get_ops(dev);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/fpu.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/fpu.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/fpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/fpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,8 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
+#include <linux/types.h>
+
 /* floating point status register: */
 #define FPSR_TRAP_VD	(1 << 0)	/* invalid op trap disabled */
 #define FPSR_TRAP_DD	(1 << 1)	/* denormal trap disabled */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/gcc_intrin.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/gcc_intrin.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/gcc_intrin.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/gcc_intrin.h	2009-09-09 18:13:59.000000000 -0400
@@ -388,7 +388,7 @@
 
 #define ia64_native_thash(addr)							\
 ({										\
-	__u64 ia64_intri_res;							\
+	unsigned long ia64_intri_res;						\
 	asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr));	\
 	ia64_intri_res;								\
 })
@@ -419,7 +419,7 @@
 
 #define ia64_tpa(addr)								\
 ({										\
-	__u64 ia64_pa;								\
+	unsigned long ia64_pa;							\
 	asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory");	\
 	ia64_pa;								\
 })
@@ -444,35 +444,35 @@
 
 #define ia64_native_get_cpuid(index)							\
 ({											\
-	__u64 ia64_intri_res;								\
+	unsigned long ia64_intri_res;							\
 	asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index));	\
 	ia64_intri_res;									\
 })
 
 #define __ia64_get_dbr(index)							\
 ({										\
-	__u64 ia64_intri_res;							\
+	unsigned long ia64_intri_res;						\
 	asm volatile ("mov %0=dbr[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
 	ia64_intri_res;								\
 })
 
 #define ia64_get_ibr(index)							\
 ({										\
-	__u64 ia64_intri_res;							\
+	unsigned long ia64_intri_res;						\
 	asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
 	ia64_intri_res;								\
 })
 
 #define ia64_get_pkr(index)							\
 ({										\
-	__u64 ia64_intri_res;							\
+	unsigned long ia64_intri_res;						\
 	asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
 	ia64_intri_res;								\
 })
 
 #define ia64_get_pmc(index)							\
 ({										\
-	__u64 ia64_intri_res;							\
+	unsigned long ia64_intri_res;						\
 	asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
 	ia64_intri_res;								\
 })
@@ -480,14 +480,14 @@
 
 #define ia64_native_get_pmd(index)						\
 ({										\
-	__u64 ia64_intri_res;							\
+	unsigned long ia64_intri_res;						\
 	asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
 	ia64_intri_res;								\
 })
 
 #define ia64_native_get_rr(index)						\
 ({										\
-	__u64 ia64_intri_res;							\
+	unsigned long ia64_intri_res;						\
 	asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index));	\
 	ia64_intri_res;								\
 })
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/hw_irq.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/hw_irq.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/hw_irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/hw_irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -106,7 +106,7 @@
 #define irq_to_domain(x)	irq_cfg[(x)].domain
 DECLARE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq);
 
-extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
+extern struct irq_chip irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
 
 #ifdef CONFIG_PARAVIRT_GUEST
 #include <asm/paravirt.h>
@@ -146,7 +146,7 @@
  * Default implementations for the irq-descriptor API:
  */
 
-extern irq_desc_t irq_desc[NR_IRQS];
+extern struct irq_desc irq_desc[NR_IRQS];
 
 #ifndef CONFIG_IA64_GENERIC
 static inline ia64_vector __ia64_irq_to_vector(int irq)
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/iommu.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/iommu.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/iommu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/iommu.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,11 @@
 extern void no_iommu_init(void);
 extern int force_iommu, no_iommu;
 extern int iommu_detected;
+#ifdef	CONFIG_DMAR
+extern int iommu_pass_through;
+#else
+#define iommu_pass_through	(0)
+#endif
 extern void iommu_dma_init(void);
 extern void machvec_init(const char *name);
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/Kbuild linux-libre-2.6.31-gnu/arch/ia64/include/asm/Kbuild
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/Kbuild	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/Kbuild	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,6 @@
 
 header-y += break.h
 header-y += fpu.h
-header-y += fpswa.h
 header-y += ia64regs.h
 header-y += intel_intrin.h
 header-y += perfmon_default_smpl.h
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,30 +1,12 @@
 #ifndef _ASM_IA64_KMAP_TYPES_H
 #define _ASM_IA64_KMAP_TYPES_H
 
-
 #ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
+#define  __WITH_KM_FENCE
 #endif
 
-enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_IRQ0,
-D(10)	KM_IRQ1,
-D(11)	KM_SOFTIRQ0,
-D(12)	KM_SOFTIRQ1,
-D(13)	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
-#undef D
+#undef __WITH_KM_FENCE
 
 #endif /* _ASM_IA64_KMAP_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/kvm_host.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/kvm_host.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/kvm_host.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/kvm_host.h	2009-09-09 18:13:59.000000000 -0400
@@ -371,6 +371,7 @@
 	int last_run_cpu;
 	int vmm_tr_slot;
 	int vm_tr_slot;
+	int sn_rtc_tr_slot;
 
 #define KVM_MP_STATE_RUNNABLE          0
 #define KVM_MP_STATE_UNINITIALIZED     1
@@ -465,6 +466,7 @@
 	unsigned long	vmm_init_rr;
 
 	int		online_vcpus;
+	int		is_sn2;
 
 	struct kvm_ioapic *vioapic;
 	struct kvm_vm_stat stat;
@@ -472,6 +474,7 @@
 
 	struct list_head assigned_dev_head;
 	struct iommu_domain *iommu_domain;
+	int iommu_flags;
 	struct hlist_head irq_ack_notifier_list;
 
 	unsigned long irq_sources_bitmap;
@@ -578,6 +581,8 @@
 	kvm_vmm_entry 	*vmm_entry;
 	kvm_tramp_entry *tramp_entry;
 	unsigned long 	vmm_ivt;
+	unsigned long	patch_mov_ar;
+	unsigned long	patch_mov_ar_sn2;
 };
 
 int kvm_highest_pending_irq(struct kvm_vcpu *vcpu);
@@ -585,7 +590,6 @@
 int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
 void kvm_sal_emul(struct kvm_vcpu *vcpu);
 
-static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {}
 #endif /* __ASSEMBLY__*/
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/mca.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/mca.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/mca.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/mca.h	2009-09-09 18:13:59.000000000 -0400
@@ -72,39 +72,39 @@
 struct ia64_sal_os_state {
 
 	/* SAL to OS */
-	u64			os_gp;			/* GP of the os registered with the SAL, physical */
-	u64			pal_proc;		/* PAL_PROC entry point, physical */
-	u64			sal_proc;		/* SAL_PROC entry point, physical */
-	u64			rv_rc;			/* MCA - Rendezvous state, INIT - reason code */
-	u64			proc_state_param;	/* from R18 */
-	u64			monarch;		/* 1 for a monarch event, 0 for a slave */
+	unsigned long		os_gp;			/* GP of the os registered with the SAL, physical */
+	unsigned long		pal_proc;		/* PAL_PROC entry point, physical */
+	unsigned long		sal_proc;		/* SAL_PROC entry point, physical */
+	unsigned long		rv_rc;			/* MCA - Rendezvous state, INIT - reason code */
+	unsigned long		proc_state_param;	/* from R18 */
+	unsigned long		monarch;		/* 1 for a monarch event, 0 for a slave */
 
 	/* common */
-	u64			sal_ra;			/* Return address in SAL, physical */
-	u64			sal_gp;			/* GP of the SAL - physical */
+	unsigned long		sal_ra;			/* Return address in SAL, physical */
+	unsigned long		sal_gp;			/* GP of the SAL - physical */
 	pal_min_state_area_t	*pal_min_state;		/* from R17.  physical in asm, virtual in C */
 	/* Previous values of IA64_KR(CURRENT) and IA64_KR(CURRENT_STACK).
 	 * Note: if the MCA/INIT recovery code wants to resume to a new context
 	 * then it must change these values to reflect the new kernel stack.
 	 */
-	u64			prev_IA64_KR_CURRENT;	/* previous value of IA64_KR(CURRENT) */
-	u64			prev_IA64_KR_CURRENT_STACK;
+	unsigned long		prev_IA64_KR_CURRENT;	/* previous value of IA64_KR(CURRENT) */
+	unsigned long		prev_IA64_KR_CURRENT_STACK;
 	struct task_struct	*prev_task;		/* previous task, NULL if it is not useful */
 	/* Some interrupt registers are not saved in minstate, pt_regs or
 	 * switch_stack.  Because MCA/INIT can occur when interrupts are
 	 * disabled, we need to save the additional interrupt registers over
 	 * MCA/INIT and resume.
 	 */
-	u64			isr;
-	u64			ifa;
-	u64			itir;
-	u64			iipa;
-	u64			iim;
-	u64			iha;
+	unsigned long		isr;
+	unsigned long		ifa;
+	unsigned long		itir;
+	unsigned long		iipa;
+	unsigned long		iim;
+	unsigned long		iha;
 
 	/* OS to SAL */
-	u64			os_status;		/* OS status to SAL, enum below */
-	u64			context;		/* 0 if return to same context
+	unsigned long		os_status;		/* OS status to SAL, enum below */
+	unsigned long		context;		/* 0 if return to same context
 							   1 if return to new context */
 };
 
@@ -150,7 +150,7 @@
 extern void ia64_mca_cmc_vector_setup(void);
 extern int  ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *));
 extern void ia64_unreg_MCA_extension(void);
-extern u64 ia64_get_rnat(u64 *);
+extern unsigned long ia64_get_rnat(unsigned long *);
 extern void ia64_mca_printk(const char * fmt, ...)
 	 __attribute__ ((format (printf, 1, 2)));
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/meminit.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/meminit.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/meminit.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/meminit.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,8 +25,8 @@
 #define IA64_MAX_RSVD_REGIONS 9
 
 struct rsvd_region {
-	unsigned long start;	/* virtual address of beginning of element */
-	unsigned long end;	/* virtual address of end of element + 1 */
+	u64 start;	/* virtual address of beginning of element */
+	u64 end;	/* virtual address of end of element + 1 */
 };
 
 extern struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
@@ -35,13 +35,13 @@
 extern void find_memory (void);
 extern void reserve_memory (void);
 extern void find_initrd (void);
-extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
-extern int filter_memory (unsigned long start, unsigned long end, void *arg);
-extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e);
-extern int find_max_min_low_pfn (unsigned long , unsigned long, void *);
+extern int filter_rsvd_memory (u64 start, u64 end, void *arg);
+extern int filter_memory (u64 start, u64 end, void *arg);
+extern unsigned long efi_memmap_init(u64 *s, u64 *e);
+extern int find_max_min_low_pfn (u64, u64, void *);
 
 extern unsigned long vmcore_find_descriptor_size(unsigned long address);
-extern int reserve_elfcorehdr(unsigned long *start, unsigned long *end);
+extern int reserve_elfcorehdr(u64 *start, u64 *end);
 
 /*
  * For rounding an address to the next IA64_GRANULE_SIZE or order
@@ -63,8 +63,8 @@
 # define LARGE_GAP	0x40000000 /* Use virtual mem map if hole is > than this */
   extern unsigned long vmalloc_end;
   extern struct page *vmem_map;
-  extern int find_largest_hole (u64 start, u64 end, void *arg);
-  extern int create_mem_map_page_table (u64 start, u64 end, void *arg);
+  extern int find_largest_hole(u64 start, u64 end, void *arg);
+  extern int create_mem_map_page_table(u64 start, u64 end, void *arg);
   extern int vmemmap_find_next_valid_pfn(int, int);
 #else
 static inline int vmemmap_find_next_valid_pfn(int node, int i)
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/mman.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,7 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x00100		/* stack-like segment */
 #define MAP_GROWSUP	0x00200		/* register stack-like segment */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/pal.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/pal.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/pal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/pal.h	2009-09-09 18:13:59.000000000 -0400
@@ -989,8 +989,8 @@
 }
 
 /* Return summary information about the hierarchy of caches controlled by the processor */
-static inline s64
-ia64_pal_cache_summary (u64 *cache_levels, u64 *unique_caches)
+static inline long ia64_pal_cache_summary(unsigned long *cache_levels,
+						unsigned long *unique_caches)
 {
 	struct ia64_pal_retval iprv;
 	PAL_CALL(iprv, PAL_CACHE_SUMMARY, 0, 0, 0);
@@ -1038,8 +1038,8 @@
 }
 
 /* Return the number of instruction and data debug register pairs */
-static inline s64
-ia64_pal_debug_info (u64 *inst_regs,  u64 *data_regs)
+static inline long ia64_pal_debug_info(unsigned long *inst_regs,
+						unsigned long *data_regs)
 {
 	struct ia64_pal_retval iprv;
 	PAL_CALL(iprv, PAL_DEBUG_INFO, 0, 0, 0);
@@ -1074,8 +1074,7 @@
 }
 
 /* Get base frequency of the platform if generated by the processor */
-static inline s64
-ia64_pal_freq_base (u64 *platform_base_freq)
+static inline long ia64_pal_freq_base(unsigned long *platform_base_freq)
 {
 	struct ia64_pal_retval iprv;
 	PAL_CALL(iprv, PAL_FREQ_BASE, 0, 0, 0);
@@ -1437,7 +1436,7 @@
  * possible.
  */
 typedef struct ia64_ptce_info_s {
-	u64		base;
+	unsigned long	base;
 	u32		count[2];
 	u32		stride[2];
 } ia64_ptce_info_t;
@@ -1478,9 +1477,9 @@
 }
 
 typedef union pal_hints_u {
-	u64			ph_data;
+	unsigned long		ph_data;
 	struct {
-	       u64		si		: 1,
+	       unsigned long	si		: 1,
 				li		: 1,
 				reserved	: 62;
 	} pal_hints_s;
@@ -1489,8 +1488,8 @@
 /* Return information about the register stack and RSE for this processor
  * implementation.
  */
-static inline s64
-ia64_pal_rse_info (u64 *num_phys_stacked, pal_hints_u_t *hints)
+static inline long ia64_pal_rse_info(unsigned long *num_phys_stacked,
+							pal_hints_u_t *hints)
 {
 	struct ia64_pal_retval iprv;
 	PAL_CALL(iprv, PAL_RSE_INFO, 0, 0, 0);
@@ -1608,8 +1607,7 @@
 /* Get page size information about the virtual memory characteristics of the processor
  * implementation.
  */
-static inline s64
-ia64_pal_vm_page_size (u64 *tr_pages, u64 *vw_pages)
+static inline s64 ia64_pal_vm_page_size(u64 *tr_pages, u64 *vw_pages)
 {
 	struct ia64_pal_retval iprv;
 	PAL_CALL(iprv, PAL_VM_PAGE_SIZE, 0, 0, 0);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/pci.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -135,19 +135,6 @@
 extern void pcibios_bus_to_resource(struct pci_dev *dev,
 		struct resource *res, struct pci_bus_region *region);
 
-static inline struct resource *
-pcibios_select_root(struct pci_dev *pdev, struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 #define pcibios_scan_all_fns(a, b)	0
 
 #define HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,7 @@
 {
 	quicklist_free(0, NULL, pud);
 }
-#define __pud_free_tlb(tlb, pud)	pud_free((tlb)->mm, pud)
+#define __pud_free_tlb(tlb, pud, address)	pud_free((tlb)->mm, pud)
 #endif /* CONFIG_PGTABLE_4 */
 
 static inline void
@@ -67,7 +67,7 @@
 	quicklist_free(0, NULL, pmd);
 }
 
-#define __pmd_free_tlb(tlb, pmd)	pmd_free((tlb)->mm, pmd)
+#define __pmd_free_tlb(tlb, pmd, address)	pmd_free((tlb)->mm, pmd)
 
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, pgtable_t pte)
@@ -117,6 +117,6 @@
 	quicklist_trim(0, NULL, 25, 16);
 }
 
-#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
+#define __pte_free_tlb(tlb, pte, address)	pte_free((tlb)->mm, pte)
 
 #endif				/* _ASM_IA64_PGALLOC_H */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -146,6 +146,8 @@
 #define PAGE_GATE	__pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
 #define PAGE_KERNEL	__pgprot(__DIRTY_BITS  | _PAGE_PL_0 | _PAGE_AR_RWX)
 #define PAGE_KERNELRX	__pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
+#define PAGE_KERNEL_UC	__pgprot(__DIRTY_BITS  | _PAGE_PL_0 | _PAGE_AR_RWX | \
+				 _PAGE_MA_UC)
 
 # ifndef __ASSEMBLY__
 
@@ -153,7 +155,6 @@
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
 #include <asm/mmu_context.h>
-#include <asm/processor.h>
 
 /*
  * Next come the mappings that determine how mmap() protection bits
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/processor.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -187,40 +187,40 @@
  * state comes earlier:
  */
 struct cpuinfo_ia64 {
-	__u32 softirq_pending;
-	__u64 itm_delta;	/* # of clock cycles between clock ticks */
-	__u64 itm_next;		/* interval timer mask value to use for next clock tick */
-	__u64 nsec_per_cyc;	/* (1000000000<<IA64_NSEC_PER_CYC_SHIFT)/itc_freq */
-	__u64 unimpl_va_mask;	/* mask of unimplemented virtual address bits (from PAL) */
-	__u64 unimpl_pa_mask;	/* mask of unimplemented physical address bits (from PAL) */
-	__u64 itc_freq;		/* frequency of ITC counter */
-	__u64 proc_freq;	/* frequency of processor */
-	__u64 cyc_per_usec;	/* itc_freq/1000000 */
-	__u64 ptce_base;
-	__u32 ptce_count[2];
-	__u32 ptce_stride[2];
+	unsigned int softirq_pending;
+	unsigned long itm_delta;	/* # of clock cycles between clock ticks */
+	unsigned long itm_next;		/* interval timer mask value to use for next clock tick */
+	unsigned long nsec_per_cyc;	/* (1000000000<<IA64_NSEC_PER_CYC_SHIFT)/itc_freq */
+	unsigned long unimpl_va_mask;	/* mask of unimplemented virtual address bits (from PAL) */
+	unsigned long unimpl_pa_mask;	/* mask of unimplemented physical address bits (from PAL) */
+	unsigned long itc_freq;		/* frequency of ITC counter */
+	unsigned long proc_freq;	/* frequency of processor */
+	unsigned long cyc_per_usec;	/* itc_freq/1000000 */
+	unsigned long ptce_base;
+	unsigned int ptce_count[2];
+	unsigned int ptce_stride[2];
 	struct task_struct *ksoftirqd;	/* kernel softirq daemon for this CPU */
 
 #ifdef CONFIG_SMP
-	__u64 loops_per_jiffy;
+	unsigned long loops_per_jiffy;
 	int cpu;
-	__u32 socket_id;	/* physical processor socket id */
-	__u16 core_id;		/* core id */
-	__u16 thread_id;	/* thread id */
-	__u16 num_log;		/* Total number of logical processors on
+	unsigned int socket_id;	/* physical processor socket id */
+	unsigned short core_id;	/* core id */
+	unsigned short thread_id; /* thread id */
+	unsigned short num_log;	/* Total number of logical processors on
 				 * this socket that were successfully booted */
-	__u8  cores_per_socket;	/* Cores per processor socket */
-	__u8  threads_per_core;	/* Threads per core */
+	unsigned char cores_per_socket;	/* Cores per processor socket */
+	unsigned char threads_per_core;	/* Threads per core */
 #endif
 
 	/* CPUID-derived information: */
-	__u64 ppn;
-	__u64 features;
-	__u8 number;
-	__u8 revision;
-	__u8 model;
-	__u8 family;
-	__u8 archrev;
+	unsigned long ppn;
+	unsigned long features;
+	unsigned char number;
+	unsigned char revision;
+	unsigned char model;
+	unsigned char family;
+	unsigned char archrev;
 	char vendor[16];
 	char *model_name;
 
@@ -329,8 +329,8 @@
 #else
 # define INIT_THREAD_PM
 #endif
-	__u64 dbr[IA64_NUM_DBG_REGS];
-	__u64 ibr[IA64_NUM_DBG_REGS];
+	unsigned long dbr[IA64_NUM_DBG_REGS];
+	unsigned long ibr[IA64_NUM_DBG_REGS];
 	struct ia64_fpreg fph[96];	/* saved/loaded on demand */
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/sal.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/sal.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/sal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/sal.h	2009-09-09 18:13:59.000000000 -0400
@@ -106,10 +106,10 @@
 	 * informational value should be printed (e.g., "reboot for
 	 * change to take effect").
 	 */
-	s64 status;
-	u64 v0;
-	u64 v1;
-	u64 v2;
+	long status;
+	unsigned long v0;
+	unsigned long v1;
+	unsigned long v2;
 };
 
 typedef struct ia64_sal_retval (*ia64_sal_handler) (u64, ...);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/signal.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -114,7 +114,7 @@
 
 #endif /* __KERNEL__ */
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 # ifndef __ASSEMBLY__
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/sn/sn_sal.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/sn/sn_sal.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/sn/sn_sal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/sn/sn_sal.h	2009-09-09 18:13:59.000000000 -0400
@@ -929,7 +929,7 @@
 /*
  * Get the associated ioboard type for a given nasid.
  */
-static inline s64
+static inline long
 ia64_sn_sysctl_ioboard_get(nasid_t nasid, u16 *ioboard)
 {
 	struct ia64_sal_retval isrv;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/suspend.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/suspend.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/suspend.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-/* dummy (must be non-empty to prevent prejudicial removal...) */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
-	.preempt_count	= 0,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -236,22 +236,22 @@
 	__tlb_remove_tlb_entry(tlb, ptep, addr);	\
 } while (0)
 
-#define pte_free_tlb(tlb, ptep)				\
+#define pte_free_tlb(tlb, ptep, address)		\
 do {							\
 	tlb->need_flush = 1;				\
-	__pte_free_tlb(tlb, ptep);			\
+	__pte_free_tlb(tlb, ptep, address);		\
 } while (0)
 
-#define pmd_free_tlb(tlb, ptep)				\
+#define pmd_free_tlb(tlb, ptep, address)		\
 do {							\
 	tlb->need_flush = 1;				\
-	__pmd_free_tlb(tlb, ptep);			\
+	__pmd_free_tlb(tlb, ptep, address);		\
 } while (0)
 
-#define pud_free_tlb(tlb, pudp)				\
+#define pud_free_tlb(tlb, pudp, address)		\
 do {							\
 	tlb->need_flush = 1;				\
-	__pud_free_tlb(tlb, pudp);			\
+	__pud_free_tlb(tlb, pudp, address);		\
 } while (0)
 
 #endif /* _ASM_IA64_TLB_H */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/types.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,10 +2,11 @@
 #define _ASM_IA64_TYPES_H
 
 /*
- * This file is never included by application software unless explicitly requested (e.g.,
- * via linux/types.h) in which case the application is Linux specific so (user-) name
- * space pollution is not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
+ * This file is never included by application software unless explicitly
+ * requested (e.g., via linux/types.h) in which case the application is
+ * Linux specific so (user-) name space pollution is not a major issue.
+ * However, for interoperability, libraries still need to be careful to
+ * avoid naming clashes.
  *
  * Based on <asm-alpha/types.h>.
  *
@@ -13,16 +14,16 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
+#ifdef __KERNEL__
+#include <asm-generic/int-ll64.h>
+#else
 #include <asm-generic/int-l64.h>
+#endif
 
 #ifdef __ASSEMBLY__
 # define __IA64_UL(x)		(x)
 # define __IA64_UL_CONST(x)	x
 
-# ifdef __KERNEL__
-#  define BITS_PER_LONG 64
-# endif
-
 #else
 # define __IA64_UL(x)		((unsigned long)(x))
 # define __IA64_UL_CONST(x)	x##UL
@@ -34,10 +35,7 @@
  */
 # ifdef __KERNEL__
 
-#define BITS_PER_LONG 64
-
 /* DMA addresses are 64-bits wide, in general.  */
-
 typedef u64 dma_addr_t;
 
 # endif /* __KERNEL__ */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -310,11 +310,12 @@
 #define __NR_inotify_init1		1318
 #define __NR_preadv			1319
 #define __NR_pwritev			1320
+#define __NR_rt_tgsigqueueinfo		1321
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls			297 /* length of syscall table */
+#define NR_syscalls			298 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
@@ -328,6 +329,7 @@
 #define __IGNORE_utime		/* utimes() */
 #define __IGNORE_getpgrp	/* getpgid() */
 #define __IGNORE_vfork		/* clone() */
+#define __IGNORE_umount2	/* umount() */
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
diff -druN linux-libre-2.6.30-gnu/arch/ia64/include/asm/xen/hypervisor.h linux-libre-2.6.31-gnu/arch/ia64/include/asm/xen/hypervisor.h
--- linux-libre-2.6.30-gnu/arch/ia64/include/asm/xen/hypervisor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/include/asm/xen/hypervisor.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,7 @@
 #ifndef _ASM_IA64_XEN_HYPERVISOR_H
 #define _ASM_IA64_XEN_HYPERVISOR_H
 
+#include <linux/err.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>	/* to compile feature.c */
 #include <xen/features.h>		/* to comiple xen-netfront.c */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/Kconfig linux-libre-2.6.31-gnu/arch/ia64/Kconfig
--- linux-libre-2.6.30-gnu/arch/ia64/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
 	select HAVE_DMA_ATTRS
 	select HAVE_KVM
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_DMA_API_DEBUG
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/acpi.c linux-libre-2.6.31-gnu/arch/ia64/kernel/acpi.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/acpi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/acpi.c	2009-09-09 18:13:59.000000000 -0400
@@ -636,7 +636,7 @@
  * success: return IRQ number (>=0)
  * failure: return < 0
  */
-int acpi_register_gsi(u32 gsi, int triggering, int polarity)
+int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
 {
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
 		return gsi;
@@ -678,7 +678,8 @@
 
 	fadt = (struct acpi_table_fadt *)fadt_header;
 
-	acpi_register_gsi(fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
+	acpi_register_gsi(NULL, fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE,
+				 ACPI_ACTIVE_LOW);
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/acpi-processor.c linux-libre-2.6.31-gnu/arch/ia64/kernel/acpi-processor.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/acpi-processor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/acpi-processor.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,3 +71,15 @@
 }
 
 EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
+
+void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr)
+{
+	if (pr->pdc) {
+		kfree(pr->pdc->pointer->buffer.pointer);
+		kfree(pr->pdc->pointer);
+		kfree(pr->pdc);
+		pr->pdc = NULL;
+	}
+}
+
+EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/dma-mapping.c linux-libre-2.6.31-gnu/arch/ia64/kernel/dma-mapping.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/dma-mapping.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/dma-mapping.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,16 @@
 struct dma_map_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init dma_init(void)
+{
+	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+
+	return 0;
+}
+fs_initcall(dma_init);
+
 struct dma_map_ops *dma_get_ops(struct device *dev)
 {
 	return dma_ops;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/efi.c linux-libre-2.6.31-gnu/arch/ia64/kernel/efi.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/efi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/efi.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 struct efi efi;
 EXPORT_SYMBOL(efi);
 static efi_runtime_services_t *runtime;
-static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
+static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
 
 #define efi_call_virt(f, args...)	(*(f))(args)
 
@@ -356,7 +356,7 @@
 
 		if (++pal_code_count > 1) {
 			printk(KERN_ERR "Too many EFI Pal Code memory ranges, "
-			       "dropped @ %lx\n", md->phys_addr);
+			       "dropped @ %llx\n", md->phys_addr);
 			continue;
 		}
 		/*
@@ -490,10 +490,10 @@
 		}
 	}
 	if (min_addr != 0UL)
-		printk(KERN_INFO "Ignoring memory below %luMB\n",
+		printk(KERN_INFO "Ignoring memory below %lluMB\n",
 		       min_addr >> 20);
 	if (max_addr != ~0UL)
-		printk(KERN_INFO "Ignoring memory above %luMB\n",
+		printk(KERN_INFO "Ignoring memory above %lluMB\n",
 		       max_addr >> 20);
 
 	efi.systab = __va(ia64_boot_param->efi_systab);
@@ -1066,7 +1066,7 @@
  * parts exist, and are WB.
  */
 unsigned long
-efi_memmap_init(unsigned long *s, unsigned long *e)
+efi_memmap_init(u64 *s, u64 *e)
 {
 	struct kern_memdesc *k, *prev = NULL;
 	u64	contig_low=0, contig_high=0;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/entry.S linux-libre-2.6.31-gnu/arch/ia64/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -1805,6 +1805,7 @@
 	data8 sys_inotify_init1
 	data8 sys_preadv
 	data8 sys_pwritev			// 1320
+	data8 sys_rt_tgsigqueueinfo
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/esi.c linux-libre-2.6.31-gnu/arch/ia64/kernel/esi.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/esi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/esi.c	2009-09-09 18:13:59.000000000 -0400
@@ -65,7 +65,7 @@
 	}
 
 	if (!esi)
-		return -ENODEV;;
+		return -ENODEV;
 
 	systab = __va(esi);
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/ia64_ksyms.c linux-libre-2.6.31-gnu/arch/ia64/kernel/ia64_ksyms.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/ia64_ksyms.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/ia64_ksyms.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 
 #include <asm/page.h>
 EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 #include <linux/bootmem.h>
@@ -60,9 +61,6 @@
 EXPORT_SYMBOL(__moddi3);
 EXPORT_SYMBOL(__umoddi3);
 
-#include <asm/page.h>
-EXPORT_SYMBOL(copy_page);
-
 #if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
 extern void xor_ia64_2(void);
 extern void xor_ia64_3(void);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/init_task.c linux-libre-2.6.31-gnu/arch/ia64/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,10 +19,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial task structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/iosapic.c linux-libre-2.6.31-gnu/arch/ia64/kernel/iosapic.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/iosapic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/iosapic.c	2009-09-09 18:13:59.000000000 -0400
@@ -329,7 +329,7 @@
 }
 
 
-static void
+static int
 iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 #ifdef CONFIG_SMP
@@ -343,15 +343,15 @@
 
 	cpu = cpumask_first_and(cpu_online_mask, mask);
 	if (cpu >= nr_cpu_ids)
-		return;
+		return -1;
 
 	if (irq_prepare_move(irq, cpu))
-		return;
+		return -1;
 
 	dest = cpu_physical_id(cpu);
 
 	if (!iosapic_intr_info[irq].count)
-		return;			/* not an IOSAPIC interrupt */
+		return -1;			/* not an IOSAPIC interrupt */
 
 	set_irq_affinity_info(irq, dest, redir);
 
@@ -376,7 +376,9 @@
 		iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
 		iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
 	}
+
 #endif
+	return 0;
 }
 
 /*
@@ -449,7 +451,7 @@
 static void
 iosapic_ack_edge_irq (unsigned int irq)
 {
-	irq_desc_t *idesc = irq_desc + irq;
+	struct irq_desc *idesc = irq_desc + irq;
 
 	irq_complete_move(irq);
 	move_native_irq(irq);
@@ -598,8 +600,8 @@
 register_intr (unsigned int gsi, int irq, unsigned char delivery,
 	       unsigned long polarity, unsigned long trigger)
 {
-	irq_desc_t *idesc;
-	struct hw_interrupt_type *irq_type;
+	struct irq_desc *idesc;
+	struct irq_chip *irq_type;
 	int index;
 	struct iosapic_rte_info *rte;
 
@@ -648,7 +650,7 @@
 
 	idesc = irq_desc + irq;
 	if (irq_type != NULL && idesc->chip != irq_type) {
-		if (idesc->chip != &no_irq_type)
+		if (idesc->chip != &no_irq_chip)
 			printk(KERN_WARNING
 			       "%s: changing vector %d from %s to %s\n",
 			       __func__, irq_to_vector(irq),
@@ -826,7 +828,7 @@
 {
 	unsigned long flags;
 	int irq, index;
-	irq_desc_t *idesc;
+	struct irq_desc *idesc;
 	u32 low32;
 	unsigned long trigger, polarity;
 	unsigned int dest;
@@ -1070,6 +1072,10 @@
 	}
 
 	addr = ioremap(phys_addr, 0);
+	if (addr == NULL) {
+		spin_unlock_irqrestore(&iosapic_lock, flags);
+		return -ENOMEM;
+	}
 	ver = iosapic_version(addr);
 	if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
 		iounmap(addr);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/irq.c linux-libre-2.6.31-gnu/arch/ia64/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -130,7 +130,7 @@
  */
 static void migrate_irqs(void)
 {
-	irq_desc_t *desc;
+	struct irq_desc *desc;
 	int 		irq, new_cpu;
 
 	for (irq=0; irq < NR_IRQS; irq++) {
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/irq_ia64.c linux-libre-2.6.31-gnu/arch/ia64/kernel/irq_ia64.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/irq_ia64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/irq_ia64.c	2009-09-09 18:13:59.000000000 -0400
@@ -610,6 +610,9 @@
 	.name =		"IPI"
 };
 
+/*
+ * KVM uses this interrupt to force a cpu out of guest mode
+ */
 static struct irqaction resched_irqaction = {
 	.handler =	dummy_handler,
 	.flags =	IRQF_DISABLED,
@@ -627,7 +630,7 @@
 void
 ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action)
 {
-	irq_desc_t *desc;
+	struct irq_desc *desc;
 	unsigned int irq;
 
 	irq = vec;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/irq_lsapic.c linux-libre-2.6.31-gnu/arch/ia64/kernel/irq_lsapic.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/irq_lsapic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/irq_lsapic.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,7 @@
 	return 1;
 }
 
-struct hw_interrupt_type irq_type_ia64_lsapic = {
+struct irq_chip irq_type_ia64_lsapic = {
 	.name =		"LSAPIC",
 	.startup =	lsapic_noop_startup,
 	.shutdown =	lsapic_noop,
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/mca.c linux-libre-2.6.31-gnu/arch/ia64/kernel/mca.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/mca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/mca.c	2009-09-09 18:13:59.000000000 -0400
@@ -850,7 +850,7 @@
 
 
 static inline void
-copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)
+copy_reg(const u64 *fr, u64 fnat, unsigned long *tr, unsigned long *tnat)
 {
 	u64 fslot, tslot, nat;
 	*tr = *fr;
@@ -914,9 +914,9 @@
 	struct switch_stack *old_sw;
 	unsigned size = sizeof(struct pt_regs) +
 			sizeof(struct switch_stack) + 16;
-	u64 *old_bspstore, *old_bsp;
-	u64 *new_bspstore, *new_bsp;
-	u64 old_unat, old_rnat, new_rnat, nat;
+	unsigned long *old_bspstore, *old_bsp;
+	unsigned long *new_bspstore, *new_bsp;
+	unsigned long old_unat, old_rnat, new_rnat, nat;
 	u64 slots, loadrs = regs->loadrs;
 	u64 r12 = ms->pmsa_gr[12-1], r13 = ms->pmsa_gr[13-1];
 	u64 ar_bspstore = regs->ar_bspstore;
@@ -968,10 +968,10 @@
 	 * loadrs for the new stack and save it in the new pt_regs, where
 	 * ia64_old_stack() can get it.
 	 */
-	old_bspstore = (u64 *)ar_bspstore;
-	old_bsp = (u64 *)ar_bsp;
+	old_bspstore = (unsigned long *)ar_bspstore;
+	old_bsp = (unsigned long *)ar_bsp;
 	slots = ia64_rse_num_regs(old_bspstore, old_bsp);
-	new_bspstore = (u64 *)((u64)current + IA64_RBS_OFFSET);
+	new_bspstore = (unsigned long *)((u64)current + IA64_RBS_OFFSET);
 	new_bsp = ia64_rse_skip_regs(new_bspstore, slots);
 	regs->loadrs = (new_bsp - new_bspstore) * 8 << 16;
 
@@ -1829,8 +1829,7 @@
 			data = mca_bootmem();
 			first_time = 0;
 		} else
-			data = page_address(alloc_pages_node(numa_node_id(),
-					GFP_KERNEL, get_order(sz)));
+			data = __get_free_pages(GFP_KERNEL, get_order(sz));
 		if (!data)
 			panic("Could not allocate MCA memory for cpu %d\n",
 					cpu);
@@ -1918,9 +1917,9 @@
 	ia64_fptr_t *init_hldlr_ptr_slave = (ia64_fptr_t *)ia64_os_init_dispatch_slave;
 	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
 	int i;
-	s64 rc;
+	long rc;
 	struct ia64_sal_retval isrv;
-	u64 timeout = IA64_MCA_RENDEZ_TIMEOUT;	/* platform specific */
+	unsigned long timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */
 	static struct notifier_block default_init_monarch_nb = {
 		.notifier_call = default_monarch_init_process,
 		.priority = 0/* we need to notified last */
@@ -2093,7 +2092,7 @@
 	cpe_poll_timer.function = ia64_mca_cpe_poll;
 
 	{
-		irq_desc_t *desc;
+		struct irq_desc *desc;
 		unsigned int irq;
 
 		if (cpe_vector >= 0) {
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/module.c linux-libre-2.6.31-gnu/arch/ia64/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -171,7 +171,8 @@
 		return 0;
 	}
 	if (val + ((uint64_t) 1 << 59) >= (1UL << 60)) {
-		printk(KERN_ERR "%s: value %ld out of IMM60 range\n", mod->name, (int64_t) val);
+		printk(KERN_ERR "%s: value %ld out of IMM60 range\n",
+			mod->name, (long) val);
 		return 0;
 	}
 	ia64_patch_imm60((u64) insn, val);
@@ -182,7 +183,8 @@
 apply_imm22 (struct module *mod, struct insn *insn, uint64_t val)
 {
 	if (val + (1 << 21) >= (1 << 22)) {
-		printk(KERN_ERR "%s: value %li out of IMM22 range\n", mod->name, (int64_t)val);
+		printk(KERN_ERR "%s: value %li out of IMM22 range\n",
+			mod->name, (long)val);
 		return 0;
 	}
 	ia64_patch((u64) insn, 0x01fffcfe000UL, (  ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
@@ -196,7 +198,8 @@
 apply_imm21b (struct module *mod, struct insn *insn, uint64_t val)
 {
 	if (val + (1 << 20) >= (1 << 21)) {
-		printk(KERN_ERR "%s: value %li out of IMM21b range\n", mod->name, (int64_t)val);
+		printk(KERN_ERR "%s: value %li out of IMM21b range\n",
+			mod->name, (long)val);
 		return 0;
 	}
 	ia64_patch((u64) insn, 0x11ffffe000UL, (  ((val & 0x100000UL) << 16) /* bit 20 -> 36 */
@@ -701,8 +704,9 @@
 	      case RV_PCREL2:
 		if (r_type == R_IA64_PCREL21BI) {
 			if (!is_internal(mod, val)) {
-				printk(KERN_ERR "%s: %s reloc against non-local symbol (%lx)\n",
-				       __func__, reloc_name[r_type], val);
+				printk(KERN_ERR "%s: %s reloc against "
+					"non-local symbol (%lx)\n", __func__,
+					reloc_name[r_type], (unsigned long)val);
 				return -ENOEXEC;
 			}
 			format = RF_INSN21B;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/msi_ia64.c linux-libre-2.6.31-gnu/arch/ia64/kernel/msi_ia64.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/msi_ia64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/msi_ia64.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
 static struct irq_chip	ia64_msi_chip;
 
 #ifdef CONFIG_SMP
-static void ia64_set_msi_irq_affinity(unsigned int irq,
+static int ia64_set_msi_irq_affinity(unsigned int irq,
 				      const cpumask_t *cpu_mask)
 {
 	struct msi_msg msg;
@@ -20,10 +20,10 @@
 	int cpu = first_cpu(*cpu_mask);
 
 	if (!cpu_online(cpu))
-		return;
+		return -1;
 
 	if (irq_prepare_move(irq, cpu))
-		return;
+		return -1;
 
 	read_msi_msg(irq, &msg);
 
@@ -39,6 +39,8 @@
 
 	write_msi_msg(irq, &msg);
 	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+
+	return 0;
 }
 #endif /* CONFIG_SMP */
 
@@ -130,17 +132,17 @@
 
 #ifdef CONFIG_DMAR
 #ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	struct irq_cfg *cfg = irq_cfg + irq;
 	struct msi_msg msg;
 	int cpu = cpumask_first(mask);
 
 	if (!cpu_online(cpu))
-		return;
+		return -1;
 
 	if (irq_prepare_move(irq, cpu))
-		return;
+		return -1;
 
 	dmar_msi_read(irq, &msg);
 
@@ -151,10 +153,12 @@
 
 	dmar_msi_write(irq, &msg);
 	cpumask_copy(irq_desc[irq].affinity, mask);
+
+	return 0;
 }
 #endif /* CONFIG_SMP */
 
-struct irq_chip dmar_msi_type = {
+static struct irq_chip dmar_msi_type = {
 	.name = "DMAR_MSI",
 	.unmask = dmar_msi_unmask,
 	.mask = dmar_msi_mask,
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/palinfo.c linux-libre-2.6.31-gnu/arch/ia64/kernel/palinfo.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/palinfo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/palinfo.c	2009-09-09 18:13:59.000000000 -0400
@@ -218,10 +218,10 @@
 cache_info(char *page)
 {
 	char *p = page;
-	u64 i, levels, unique_caches;
+	unsigned long i, levels, unique_caches;
 	pal_cache_config_info_t cci;
 	int j, k;
-	s64 status;
+	long status;
 
 	if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
 		printk(KERN_ERR "ia64_pal_cache_summary=%ld\n", status);
@@ -303,7 +303,7 @@
 	ia64_ptce_info_t ptce;
 	const char *sep;
 	int i, j;
-	s64 status;
+	long status;
 
 	if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
 		printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
@@ -431,9 +431,9 @@
 	char *p = page;
 	u64 reg_info[2];
 	u64 info;
-	u64 phys_stacked;
+	unsigned long phys_stacked;
 	pal_hints_u_t hints;
-	u64 iregs, dregs;
+	unsigned long iregs, dregs;
 	char *info_type[]={
 		"Implemented AR(s)",
 		"AR(s) with read side-effects",
@@ -530,8 +530,8 @@
 	NULL, NULL, NULL, NULL,
 };
 
-static char *
-feature_set_info(char *page, u64 avail, u64 status, u64 control, u64 set)
+static char * feature_set_info(char *page, u64 avail, u64 status, u64 control,
+							unsigned long set)
 {
 	char *p = page;
 	char **vf, **v;
@@ -714,7 +714,7 @@
 {
 	char *p = page;
 	struct pal_freq_ratio proc, itc, bus;
-	u64 base;
+	unsigned long base;
 
 	if (ia64_pal_freq_base(&base) == -1)
 		p += sprintf(p, "Output clock            : not implemented\n");
@@ -736,43 +736,43 @@
 tr_info(char *page)
 {
 	char *p = page;
-	s64 status;
+	long status;
 	pal_tr_valid_u_t tr_valid;
 	u64 tr_buffer[4];
 	pal_vm_info_1_u_t vm_info_1;
 	pal_vm_info_2_u_t vm_info_2;
-	u64 i, j;
-	u64 max[3], pgm;
+	unsigned long i, j;
+	unsigned long max[3], pgm;
 	struct ifa_reg {
-		u64 valid:1;
-		u64 ig:11;
-		u64 vpn:52;
+		unsigned long valid:1;
+		unsigned long ig:11;
+		unsigned long vpn:52;
 	} *ifa_reg;
 	struct itir_reg {
-		u64 rv1:2;
-		u64 ps:6;
-		u64 key:24;
-		u64 rv2:32;
+		unsigned long rv1:2;
+		unsigned long ps:6;
+		unsigned long key:24;
+		unsigned long rv2:32;
 	} *itir_reg;
 	struct gr_reg {
-		u64 p:1;
-		u64 rv1:1;
-		u64 ma:3;
-		u64 a:1;
-		u64 d:1;
-		u64 pl:2;
-		u64 ar:3;
-		u64 ppn:38;
-		u64 rv2:2;
-		u64 ed:1;
-		u64 ig:11;
+		unsigned long p:1;
+		unsigned long rv1:1;
+		unsigned long ma:3;
+		unsigned long a:1;
+		unsigned long d:1;
+		unsigned long pl:2;
+		unsigned long ar:3;
+		unsigned long ppn:38;
+		unsigned long rv2:2;
+		unsigned long ed:1;
+		unsigned long ig:11;
 	} *gr_reg;
 	struct rid_reg {
-		u64 ig1:1;
-		u64 rv1:1;
-		u64 ig2:6;
-		u64 rid:24;
-		u64 rv2:32;
+		unsigned long ig1:1;
+		unsigned long rv1:1;
+		unsigned long ig2:6;
+		unsigned long rid:24;
+		unsigned long rv2:32;
 	} *rid_reg;
 
 	if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/paravirt_patchlist.c linux-libre-2.6.31-gnu/arch/ia64/kernel/paravirt_patchlist.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/paravirt_patchlist.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/paravirt_patchlist.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,8 @@
  */
 
 #include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <asm/paravirt.h>
 
 #define DECLARE(name)						\
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/pci-dma.c linux-libre-2.6.31-gnu/arch/ia64/kernel/pci-dma.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/pci-dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/pci-dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,8 @@
 int force_iommu __read_mostly;
 #endif
 
+int iommu_pass_through;
+
 /* Dummy device used for NULL arguments (normally ISA). Better would
    be probably a smaller DMA mask, but this is bug-to-bug compatible
    to i386. */
@@ -67,11 +69,6 @@
 
 int iommu_dma_supported(struct device *dev, u64 mask)
 {
-	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-
-	if (ops->dma_supported)
-		return ops->dma_supported(dev, mask);
-
 	/* Copied from i386. Doesn't make much sense, because it will
 	   only work for pci_alloc_coherent.
 	   The caller just has to use GFP_DMA in this case. */
@@ -91,7 +88,7 @@
 	   type. Normally this doesn't make any difference, but gives
 	   more gentle handling of IOMMU overflow. */
 	if (iommu_sac_force && (mask >= DMA_BIT_MASK(40))) {
-		dev_info(dev, "Force SAC with mask %lx\n", mask);
+		dev_info(dev, "Force SAC with mask %llx\n", mask);
 		return 0;
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/pci-swiotlb.c linux-libre-2.6.31-gnu/arch/ia64/kernel/pci-swiotlb.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/pci-swiotlb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/pci-swiotlb.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 
 void __init pci_swiotlb_init(void)
 {
-	if (!iommu_detected) {
+	if (!iommu_detected || iommu_pass_through) {
 #ifdef CONFIG_IA64_GENERIC
 		swiotlb = 1;
 		printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/perfmon.c linux-libre-2.6.31-gnu/arch/ia64/kernel/perfmon.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/perfmon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/perfmon.c	2009-09-09 18:13:59.000000000 -0400
@@ -312,7 +312,7 @@
 	unsigned long		th_pmcs[PFM_NUM_PMC_REGS];	/* PMC thread save state */
 	unsigned long		th_pmds[PFM_NUM_PMD_REGS];	/* PMD thread save state */
 
-	u64			ctx_saved_psr_up;	/* only contains psr.up value */
+	unsigned long		ctx_saved_psr_up;	/* only contains psr.up value */
 
 	unsigned long		ctx_last_activation;	/* context last activation number for last_cpu */
 	unsigned int		ctx_last_cpu;		/* CPU id of current or last CPU used (SMP only) */
@@ -5213,8 +5213,8 @@
  * main overflow processing routine.
  * it can be called from the interrupt path or explicitly during the context switch code
  */
-static void
-pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs)
+static void pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx,
+				unsigned long pmc0, struct pt_regs *regs)
 {
 	pfm_ovfl_arg_t *ovfl_arg;
 	unsigned long mask;
@@ -5595,7 +5595,7 @@
 		(*pfm_alt_intr_handler->handler)(irq, arg, regs);
 	}
 
-	put_cpu_no_resched();
+	put_cpu();
 	return IRQ_HANDLED;
 }
 
@@ -5603,7 +5603,7 @@
  * /proc/perfmon interface, for debug only
  */
 
-#define PFM_PROC_SHOW_HEADER	((void *)nr_cpu_ids+1)
+#define PFM_PROC_SHOW_HEADER	((void *)(long)nr_cpu_ids+1)
 
 static void *
 pfm_proc_start(struct seq_file *m, loff_t *pos)
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/ia64/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
-#include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/salinfo.c linux-libre-2.6.31-gnu/arch/ia64/kernel/salinfo.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/salinfo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/salinfo.c	2009-09-09 18:13:59.000000000 -0400
@@ -192,7 +192,7 @@
 static void
 salinfo_work_to_do(struct salinfo_data *data)
 {
-	down_trylock(&data->mutex);
+	(void)(down_trylock(&data->mutex) ?: 0);
 	up(&data->mutex);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/setup.c linux-libre-2.6.31-gnu/arch/ia64/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -151,9 +151,9 @@
  * This routine does not assume the incoming segments are sorted.
  */
 int __init
-filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
+filter_rsvd_memory (u64 start, u64 end, void *arg)
 {
-	unsigned long range_start, range_end, prev_start;
+	u64 range_start, range_end, prev_start;
 	void (*func)(unsigned long, unsigned long, int);
 	int i;
 
@@ -191,7 +191,7 @@
  * are not filtered out.
  */
 int __init
-filter_memory(unsigned long start, unsigned long end, void *arg)
+filter_memory(u64 start, u64 end, void *arg)
 {
 	void (*func)(unsigned long, unsigned long, int);
 
@@ -397,7 +397,7 @@
 		initrd_start = (unsigned long)__va(ia64_boot_param->initrd_start);
 		initrd_end   = initrd_start+ia64_boot_param->initrd_size;
 
-		printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
+		printk(KERN_INFO "Initial ramdisk at: 0x%lx (%llu bytes)\n",
 		       initrd_start, ia64_boot_param->initrd_size);
 	}
 #endif
@@ -505,9 +505,9 @@
 }
 early_param("elfcorehdr", parse_elfcorehdr);
 
-int __init reserve_elfcorehdr(unsigned long *start, unsigned long *end)
+int __init reserve_elfcorehdr(u64 *start, u64 *end)
 {
-	unsigned long length;
+	u64 length;
 
 	/* We get the address using the kernel command line,
 	 * but the size is extracted from the EFI tables.
@@ -588,7 +588,7 @@
 	ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist);
 #else
 	{
-		u64 num_phys_stacked;
+		unsigned long num_phys_stacked;
 
 		if (ia64_pal_rse_info(&num_phys_stacked, 0) == 0 && num_phys_stacked > 96)
 			ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist);
@@ -872,9 +872,9 @@
 get_cache_info(void)
 {
 	unsigned long line_size, max = 1;
-	u64 l, levels, unique_caches;
-        pal_cache_config_info_t cci;
-        s64 status;
+	unsigned long l, levels, unique_caches;
+	pal_cache_config_info_t cci;
+	long status;
 
         status = ia64_pal_cache_summary(&levels, &unique_caches);
         if (status != 0) {
@@ -892,9 +892,9 @@
 		/* cache_type (data_or_unified)=2 */
 		status = ia64_pal_cache_config_info(l, 2, &cci);
 		if (status != 0) {
-			printk(KERN_ERR
-			       "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n",
-			       __func__, l, status);
+			printk(KERN_ERR "%s: ia64_pal_cache_config_info"
+				"(l=%lu, 2) failed (status=%ld)\n",
+				__func__, l, status);
 			max = SMP_CACHE_BYTES;
 			/* The safest setup for "flush_icache_range()" */
 			cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
@@ -914,10 +914,10 @@
 			/* cache_type (instruction)=1*/
 			status = ia64_pal_cache_config_info(l, 1, &cci);
 			if (status != 0) {
-				printk(KERN_ERR
-				"%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n",
+				printk(KERN_ERR "%s: ia64_pal_cache_config_info"
+					"(l=%lu, 1) failed (status=%ld)\n",
 					__func__, l, status);
-				/* The safest setup for "flush_icache_range()" */
+				/* The safest setup for flush_icache_range() */
 				cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
 			}
 		}
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/smpboot.c linux-libre-2.6.31-gnu/arch/ia64/kernel/smpboot.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/smpboot.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/smpboot.c	2009-09-09 18:13:59.000000000 -0400
@@ -678,7 +678,7 @@
 int migrate_platform_irqs(unsigned int cpu)
 {
 	int new_cpei_cpu;
-	irq_desc_t *desc = NULL;
+	struct irq_desc *desc = NULL;
 	const struct cpumask *mask;
 	int 		retval = 0;
 
@@ -865,7 +865,7 @@
 void __devinit
 identify_siblings(struct cpuinfo_ia64 *c)
 {
-	s64 status;
+	long status;
 	u16 pltid;
 	pal_logical_to_physical_t info;
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/smp.c linux-libre-2.6.31-gnu/arch/ia64/kernel/smp.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -66,7 +66,7 @@
 #define IPI_KDUMP_CPU_STOP	3
 
 /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
-static DEFINE_PER_CPU_SHARED_ALIGNED(u64, ipi_operation);
+static DEFINE_PER_CPU_SHARED_ALIGNED(unsigned long, ipi_operation);
 
 extern void cpu_halt (void);
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/time.c linux-libre-2.6.31-gnu/arch/ia64/kernel/time.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -385,7 +385,7 @@
 
 static cycle_t itc_get_cycles(struct clocksource *cs)
 {
-	u64 lcycle, now, ret;
+	unsigned long lcycle, now, ret;
 
 	if (!itc_jitter_data.itc_jitter)
 		return get_cycles();
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/topology.c linux-libre-2.6.31-gnu/arch/ia64/kernel/topology.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/topology.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/topology.c	2009-09-09 18:13:59.000000000 -0400
@@ -306,10 +306,10 @@
 
 static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu)
 {
-	u64 i, levels, unique_caches;
+	unsigned long i, levels, unique_caches;
 	pal_cache_config_info_t cci;
 	int j;
-	s64 status;
+	long status;
 	struct cache_info *this_cache;
 	int num_cache_leaves = 0;
 
@@ -372,6 +372,10 @@
 	retval = kobject_init_and_add(&all_cpu_cache_info[cpu].kobj,
 				      &cache_ktype_percpu_entry, &sys_dev->kobj,
 				      "%s", "cache");
+	if (unlikely(retval < 0)) {
+		cpu_cache_sysfs_exit(cpu);
+		return retval;
+	}
 
 	for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) {
 		this_object = LEAF_KOBJECT_PTR(cpu,i);
@@ -385,7 +389,7 @@
 			}
 			kobject_put(&all_cpu_cache_info[cpu].kobj);
 			cpu_cache_sysfs_exit(cpu);
-			break;
+			return retval;
 		}
 		kobject_uevent(&(this_object->kobj), KOBJ_ADD);
 	}
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kernel/uncached.c linux-libre-2.6.31-gnu/arch/ia64/kernel/uncached.c
--- linux-libre-2.6.30-gnu/arch/ia64/kernel/uncached.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kernel/uncached.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,7 +98,8 @@
 
 	/* attempt to allocate a granule's worth of cached memory pages */
 
-	page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+	page = alloc_pages_exact_node(nid,
+				GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
 				IA64_GRANULE_SHIFT-PAGE_SHIFT);
 	if (!page) {
 		mutex_unlock(&uc_pool->add_chunk_mutex);
@@ -249,8 +250,7 @@
  * Called at boot time to build a map of pages that can be used for
  * memory special operations.
  */
-static int __init uncached_build_memmap(unsigned long uc_start,
-					unsigned long uc_end, void *arg)
+static int __init uncached_build_memmap(u64 uc_start, u64 uc_end, void *arg)
 {
 	int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET);
 	struct gen_pool *pool = uncached_pools[nid].pool;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/Kconfig linux-libre-2.6.31-gnu/arch/ia64/kvm/Kconfig
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -23,7 +23,7 @@
 
 config KVM
 	tristate "Kernel-based Virtual Machine (KVM) support"
-	depends on HAVE_KVM && EXPERIMENTAL
+	depends on HAVE_KVM && MODULES && EXPERIMENTAL
 	# for device assignment:
 	depends on PCI
 	select PREEMPT_NOTIFIERS
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/kvm_fw.c linux-libre-2.6.31-gnu/arch/ia64/kvm/kvm_fw.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/kvm_fw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/kvm_fw.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,9 @@
 
 #include <linux/kvm_host.h>
 #include <linux/smp.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/shub_mmr.h>
 
 #include "vti.h"
 #include "misc.h"
@@ -188,12 +191,35 @@
 	return result;
 }
 
-static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
+/*
+ * On the SGI SN2, the ITC isn't stable. Emulation backed by the SN2
+ * RTC is used instead. This function patches the ratios from SAL
+ * to match the RTC before providing them to the guest.
+ */
+static void sn2_patch_itc_freq_ratios(struct ia64_pal_retval *result)
 {
+	struct pal_freq_ratio *ratio;
+	unsigned long sal_freq, sal_drift, factor;
+
+	result->status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM,
+					    &sal_freq, &sal_drift);
+	ratio = (struct pal_freq_ratio *)&result->v2;
+	factor = ((sal_freq * 3) + (sn_rtc_cycles_per_second / 2)) /
+		sn_rtc_cycles_per_second;
+
+	ratio->num = 3;
+	ratio->den = factor;
+}
 
+static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
+{
 	struct ia64_pal_retval result;
 
 	PAL_CALL(result, PAL_FREQ_RATIOS, 0, 0, 0);
+
+	if (vcpu->kvm->arch.is_sn2)
+		sn2_patch_itc_freq_ratios(&result);
+
 	return result;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/kvm-ia64.c linux-libre-2.6.31-gnu/arch/ia64/kvm/kvm-ia64.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/kvm-ia64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/kvm-ia64.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,9 @@
 #include <asm/div64.h>
 #include <asm/tlb.h>
 #include <asm/elf.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/shub_mmr.h>
 
 #include "misc.h"
 #include "vti.h"
@@ -65,6 +68,16 @@
 	{ NULL }
 };
 
+static unsigned long kvm_get_itc(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+	if (vcpu->kvm->arch.is_sn2)
+		return rtc_time();
+	else
+#endif
+		return ia64_getreg(_IA64_REG_AR_ITC);
+}
+
 static void kvm_flush_icache(unsigned long start, unsigned long len)
 {
 	int l;
@@ -119,8 +132,7 @@
 	unsigned long saved_psr;
 	int slot;
 
-	pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
-				PAGE_KERNEL));
+	pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base), PAGE_KERNEL));
 	local_irq_save(saved_psr);
 	slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
 	local_irq_restore(saved_psr);
@@ -283,6 +295,18 @@
 
 }
 
+static int __apic_accept_irq(struct kvm_vcpu *vcpu, uint64_t vector)
+{
+	struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+	if (!test_and_set_bit(vector, &vpd->irr[0])) {
+		vcpu->arch.irq_new_pending = 1;
+		kvm_vcpu_kick(vcpu);
+		return 1;
+	}
+	return 0;
+}
+
 /*
  *  offset: address offset to IPI space.
  *  value:  deliver value.
@@ -292,20 +316,20 @@
 {
 	switch (dm) {
 	case SAPIC_FIXED:
-		kvm_apic_set_irq(vcpu, vector, 0);
 		break;
 	case SAPIC_NMI:
-		kvm_apic_set_irq(vcpu, 2, 0);
+		vector = 2;
 		break;
 	case SAPIC_EXTINT:
-		kvm_apic_set_irq(vcpu, 0, 0);
+		vector = 0;
 		break;
 	case SAPIC_INIT:
 	case SAPIC_PMI:
 	default:
 		printk(KERN_ERR"kvm: Unimplemented Deliver reserved IPI!\n");
-		break;
+		return;
 	}
+	__apic_accept_irq(vcpu, vector);
 }
 
 static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
@@ -413,6 +437,23 @@
 	return 1;
 }
 
+static int kvm_sn2_setup_mappings(struct kvm_vcpu *vcpu)
+{
+	unsigned long pte, rtc_phys_addr, map_addr;
+	int slot;
+
+	map_addr = KVM_VMM_BASE + (1UL << KVM_VMM_SHIFT);
+	rtc_phys_addr = LOCAL_MMR_OFFSET | SH_RTC;
+	pte = pte_val(mk_pte_phys(rtc_phys_addr, PAGE_KERNEL_UC));
+	slot = ia64_itr_entry(0x3, map_addr, pte, PAGE_SHIFT);
+	vcpu->arch.sn_rtc_tr_slot = slot;
+	if (slot < 0) {
+		printk(KERN_ERR "Mayday mayday! RTC mapping failed!\n");
+		slot = 0;
+	}
+	return slot;
+}
+
 int kvm_emulate_halt(struct kvm_vcpu *vcpu)
 {
 
@@ -426,7 +467,7 @@
 
 	if (irqchip_in_kernel(vcpu->kvm)) {
 
-		vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset;
+		vcpu_now_itc = kvm_get_itc(vcpu) + vcpu->arch.itc_offset;
 
 		if (time_after(vcpu_now_itc, vpd->itm)) {
 			vcpu->arch.timer_check = 1;
@@ -447,10 +488,10 @@
 		hrtimer_cancel(p_ht);
 		vcpu->arch.ht_active = 0;
 
-		if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
+		if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests) ||
+				kvm_cpu_has_pending_timer(vcpu))
 			if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
-				vcpu->arch.mp_state =
-					KVM_MP_STATE_RUNNABLE;
+				vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 
 		if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
 			return -EINTR;
@@ -551,22 +592,35 @@
 	if (r < 0)
 		goto out;
 	vcpu->arch.vm_tr_slot = r;
+
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+	if (kvm->arch.is_sn2) {
+		r = kvm_sn2_setup_mappings(vcpu);
+		if (r < 0)
+			goto out;
+	}
+#endif
+
 	r = 0;
 out:
 	return r;
-
 }
 
 static void kvm_purge_vmm_mapping(struct kvm_vcpu *vcpu)
 {
-
+	struct kvm *kvm = vcpu->kvm;
 	ia64_ptr_entry(0x3, vcpu->arch.vmm_tr_slot);
 	ia64_ptr_entry(0x3, vcpu->arch.vm_tr_slot);
-
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+	if (kvm->arch.is_sn2)
+		ia64_ptr_entry(0x3, vcpu->arch.sn_rtc_tr_slot);
+#endif
 }
 
 static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu)
 {
+	unsigned long psr;
+	int r;
 	int cpu = smp_processor_id();
 
 	if (vcpu->arch.last_run_cpu != cpu ||
@@ -578,36 +632,27 @@
 
 	vcpu->arch.host_rr6 = ia64_get_rr(RR6);
 	vti_set_rr6(vcpu->arch.vmm_rr);
-	return kvm_insert_vmm_mapping(vcpu);
+	local_irq_save(psr);
+	r = kvm_insert_vmm_mapping(vcpu);
+	local_irq_restore(psr);
+	return r;
 }
+
 static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu)
 {
 	kvm_purge_vmm_mapping(vcpu);
 	vti_set_rr6(vcpu->arch.host_rr6);
 }
 
-static int  vti_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	union context *host_ctx, *guest_ctx;
 	int r;
 
-	/*Get host and guest context with guest address space.*/
-	host_ctx = kvm_get_host_context(vcpu);
-	guest_ctx = kvm_get_guest_context(vcpu);
-
-	r = kvm_vcpu_pre_transition(vcpu);
-	if (r < 0)
-		goto out;
-	kvm_vmm_info->tramp_entry(host_ctx, guest_ctx);
-	kvm_vcpu_post_transition(vcpu);
-	r = 0;
-out:
-	return r;
-}
-
-static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
-{
-	int r;
+	/*
+	 * down_read() may sleep and return with interrupts enabled
+	 */
+	down_read(&vcpu->kvm->slots_lock);
 
 again:
 	if (signal_pending(current)) {
@@ -616,26 +661,31 @@
 		goto out;
 	}
 
-	/*
-	 * down_read() may sleep and return with interrupts enabled
-	 */
-	down_read(&vcpu->kvm->slots_lock);
-
 	preempt_disable();
 	local_irq_disable();
 
-	vcpu->guest_mode = 1;
+	/*Get host and guest context with guest address space.*/
+	host_ctx = kvm_get_host_context(vcpu);
+	guest_ctx = kvm_get_guest_context(vcpu);
+
+	clear_bit(KVM_REQ_KICK, &vcpu->requests);
+
+	r = kvm_vcpu_pre_transition(vcpu);
+	if (r < 0)
+		goto vcpu_run_fail;
+
+	up_read(&vcpu->kvm->slots_lock);
 	kvm_guest_enter();
-	r = vti_vcpu_run(vcpu, kvm_run);
-	if (r < 0) {
-		local_irq_enable();
-		preempt_enable();
-		kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
-		goto out;
-	}
+
+	/*
+	 * Transition to the guest
+	 */
+	kvm_vmm_info->tramp_entry(host_ctx, guest_ctx);
+
+	kvm_vcpu_post_transition(vcpu);
 
 	vcpu->arch.launched = 1;
-	vcpu->guest_mode = 0;
+	set_bit(KVM_REQ_KICK, &vcpu->requests);
 	local_irq_enable();
 
 	/*
@@ -646,9 +696,10 @@
 	 */
 	barrier();
 	kvm_guest_exit();
-	up_read(&vcpu->kvm->slots_lock);
 	preempt_enable();
 
+	down_read(&vcpu->kvm->slots_lock);
+
 	r = kvm_handle_exit(kvm_run, vcpu);
 
 	if (r > 0) {
@@ -657,12 +708,20 @@
 	}
 
 out:
+	up_read(&vcpu->kvm->slots_lock);
 	if (r > 0) {
 		kvm_resched(vcpu);
+		down_read(&vcpu->kvm->slots_lock);
 		goto again;
 	}
 
 	return r;
+
+vcpu_run_fail:
+	local_irq_enable();
+	preempt_enable();
+	kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+	goto out;
 }
 
 static void kvm_set_mmio_data(struct kvm_vcpu *vcpu)
@@ -788,6 +847,9 @@
 
 	if (IS_ERR(kvm))
 		return ERR_PTR(-ENOMEM);
+
+	kvm->arch.is_sn2 = ia64_platform_is("sn2");
+
 	kvm_init_vm(kvm);
 
 	kvm->arch.online_vcpus = 0;
@@ -884,7 +946,7 @@
 	RESTORE_REGS(saved_gp);
 
 	vcpu->arch.irq_new_pending = 1;
-	vcpu->arch.itc_offset = regs->saved_itc - ia64_getreg(_IA64_REG_AR_ITC);
+	vcpu->arch.itc_offset = regs->saved_itc - kvm_get_itc(vcpu);
 	set_bit(KVM_REQ_RESUME, &vcpu->requests);
 
 	vcpu_put(vcpu);
@@ -1043,10 +1105,6 @@
 	}
 }
 
-static void vti_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
-{
-}
-
 static int vti_init_vpd(struct kvm_vcpu *vcpu)
 {
 	int i;
@@ -1165,7 +1223,7 @@
 		regs->cr_iip = PALE_RESET_ENTRY;
 
 		/*Initialize itc offset for vcpus*/
-		itc_offset = 0UL - ia64_getreg(_IA64_REG_AR_ITC);
+		itc_offset = 0UL - kvm_get_itc(vcpu);
 		for (i = 0; i < kvm->arch.online_vcpus; i++) {
 			v = (struct kvm_vcpu *)((char *)vcpu +
 					sizeof(struct kvm_vcpu_data) * i);
@@ -1237,6 +1295,7 @@
 
 	local_irq_save(psr);
 	r = kvm_insert_vmm_mapping(vcpu);
+	local_irq_restore(psr);
 	if (r)
 		goto fail;
 	r = kvm_vcpu_init(vcpu, vcpu->kvm, id);
@@ -1254,13 +1313,11 @@
 		goto uninit;
 
 	kvm_purge_vmm_mapping(vcpu);
-	local_irq_restore(psr);
 
 	return 0;
 uninit:
 	kvm_vcpu_uninit(vcpu);
 fail:
-	local_irq_restore(psr);
 	return r;
 }
 
@@ -1291,7 +1348,6 @@
 	vcpu->kvm = kvm;
 
 	cpu = get_cpu();
-	vti_vcpu_load(vcpu, cpu);
 	r = vti_vcpu_setup(vcpu, id);
 	put_cpu();
 
@@ -1427,7 +1483,7 @@
 	}
 	for (i = 0; i < 4; i++)
 		regs->insvc[i] = vcpu->arch.insvc[i];
-	regs->saved_itc = vcpu->arch.itc_offset + ia64_getreg(_IA64_REG_AR_ITC);
+	regs->saved_itc = vcpu->arch.itc_offset + kvm_get_itc(vcpu);
 	SAVE_REGS(xtp);
 	SAVE_REGS(metaphysical_rr0);
 	SAVE_REGS(metaphysical_rr4);
@@ -1574,6 +1630,7 @@
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
 {
+	kvm_flush_remote_tlbs(kvm);
 }
 
 long kvm_arch_dev_ioctl(struct file *filp,
@@ -1616,8 +1673,37 @@
 	return 0;
 }
 
+
+/*
+ * On SN2, the ITC isn't stable, so copy in fast path code to use the
+ * SN2 RTC, replacing the ITC based default verion.
+ */
+static void kvm_patch_vmm(struct kvm_vmm_info *vmm_info,
+			  struct module *module)
+{
+	unsigned long new_ar, new_ar_sn2;
+	unsigned long module_base;
+
+	if (!ia64_platform_is("sn2"))
+		return;
+
+	module_base = (unsigned long)module->module_core;
+
+	new_ar = kvm_vmm_base + vmm_info->patch_mov_ar - module_base;
+	new_ar_sn2 = kvm_vmm_base + vmm_info->patch_mov_ar_sn2 - module_base;
+
+	printk(KERN_INFO "kvm: Patching ITC emulation to use SGI SN2 RTC "
+	       "as source\n");
+
+	/*
+	 * Copy the SN2 version of mov_ar into place. They are both
+	 * the same size, so 6 bundles is sufficient (6 * 0x10).
+	 */
+	memcpy((void *)new_ar, (void *)new_ar_sn2, 0x60);
+}
+
 static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
-						struct module *module)
+			    struct module *module)
 {
 	unsigned long module_base;
 	unsigned long vmm_size;
@@ -1639,6 +1725,7 @@
 		return -EFAULT;
 
 	memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size);
+	kvm_patch_vmm(vmm_info, module);
 	kvm_flush_icache(kvm_vmm_base, vmm_size);
 
 	/*Recalculate kvm_vmm_info based on new VMM*/
@@ -1792,38 +1879,24 @@
 {
 }
 
-static void vcpu_kick_intr(void *info)
-{
-#ifdef DEBUG
-	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info;
-	printk(KERN_DEBUG"vcpu_kick_intr %p \n", vcpu);
-#endif
-}
-
 void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 {
-	int ipi_pcpu = vcpu->cpu;
-	int cpu = get_cpu();
+	int me;
+	int cpu = vcpu->cpu;
 
 	if (waitqueue_active(&vcpu->wq))
 		wake_up_interruptible(&vcpu->wq);
 
-	if (vcpu->guest_mode && cpu != ipi_pcpu)
-		smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0);
+	me = get_cpu();
+	if (cpu != me && (unsigned) cpu < nr_cpu_ids && cpu_online(cpu))
+		if (!test_and_set_bit(KVM_REQ_KICK, &vcpu->requests))
+			smp_send_reschedule(cpu);
 	put_cpu();
 }
 
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq)
 {
-
-	struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
-
-	if (!test_and_set_bit(vec, &vpd->irr[0])) {
-		vcpu->arch.irq_new_pending = 1;
-		kvm_vcpu_kick(vcpu);
-		return 1;
-	}
-	return 0;
+	return __apic_accept_irq(vcpu, irq->vector);
 }
 
 int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
@@ -1836,20 +1909,18 @@
 	return 0;
 }
 
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
-				       unsigned long bitmap)
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
 {
-	struct kvm_vcpu *lvcpu = kvm->vcpus[0];
-	int i;
-
-	for (i = 1; i < kvm->arch.online_vcpus; i++) {
-		if (!kvm->vcpus[i])
-			continue;
-		if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp)
-			lvcpu = kvm->vcpus[i];
-	}
+	return vcpu1->arch.xtp - vcpu2->arch.xtp;
+}
 
-	return lvcpu;
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+		int short_hand, int dest, int dest_mode)
+{
+	struct kvm_lapic *target = vcpu->arch.apic;
+	return (dest_mode == 0) ?
+		kvm_apic_match_physical_addr(target, dest) :
+		kvm_apic_match_logical_addr(target, dest);
 }
 
 static int find_highest_bits(int *dat)
@@ -1888,6 +1959,12 @@
 	return 0;
 }
 
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+	/* do real check here */
+	return 1;
+}
+
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 {
 	return vcpu->arch.timer_fired;
@@ -1918,6 +1995,7 @@
 	long psr;
 	local_irq_save(psr);
 	r = kvm_insert_vmm_mapping(vcpu);
+	local_irq_restore(psr);
 	if (r)
 		goto fail;
 
@@ -1930,7 +2008,6 @@
 	kvm_purge_vmm_mapping(vcpu);
 	r = 0;
 fail:
-	local_irq_restore(psr);
 	return r;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/kvm_lib.c linux-libre-2.6.31-gnu/arch/ia64/kvm/kvm_lib.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/kvm_lib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/kvm_lib.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,5 +11,11 @@
  *
  */
 #undef CONFIG_MODULES
+#include <linux/module.h>
+#undef CONFIG_KALLSYMS
+#undef EXPORT_SYMBOL
+#undef EXPORT_SYMBOL_GPL
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
 #include "../../../lib/vsprintf.c"
 #include "../../../lib/ctype.c"
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/lapic.h linux-libre-2.6.31-gnu/arch/ia64/kvm/lapic.h
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/lapic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/lapic.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,10 @@
 
 int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
 int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+		int short_hand, int dest, int dest_mode);
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
+#define kvm_apic_present(x) (true)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/mmio.c linux-libre-2.6.31-gnu/arch/ia64/kvm/mmio.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/mmio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/mmio.c	2009-09-09 18:13:59.000000000 -0400
@@ -247,7 +247,8 @@
 		vcpu_get_fpreg(vcpu, inst.M9.f2, &v);
 		/* Write high word. FIXME: this is a kludge!  */
 		v.u.bits[1] &= 0x3ffff;
-		mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
+		mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1], 8,
+			    ma, IOREQ_WRITE);
 		data = v.u.bits[0];
 		size = 3;
 	} else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) {
@@ -265,7 +266,8 @@
 
 		/* Write high word.FIXME: this is a kludge!  */
 		v.u.bits[1] &= 0x3ffff;
-		mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
+		mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1],
+			    8, ma, IOREQ_WRITE);
 		data = v.u.bits[0];
 		size = 3;
 	} else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) {
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/optvfault.S linux-libre-2.6.31-gnu/arch/ia64/kvm/optvfault.S
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/optvfault.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/optvfault.S	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/processor.h>
+#include <asm/kvm_host.h>
 
 #include "vti.h"
 #include "asm-offsets.h"
@@ -140,6 +141,35 @@
 	;;
 END(kvm_asm_mov_from_ar)
 
+/*
+ * Special SGI SN2 optimized version of mov_from_ar using the SN2 RTC
+ * clock as it's source for emulating the ITC. This version will be
+ * copied on top of the original version if the host is determined to
+ * be an SN2.
+ */
+GLOBAL_ENTRY(kvm_asm_mov_from_ar_sn2)
+	add r18=VMM_VCPU_ITC_OFS_OFFSET, r21
+	movl r19 = (KVM_VMM_BASE+(1<<KVM_VMM_SHIFT))
+
+	add r16=VMM_VCPU_LAST_ITC_OFFSET,r21
+	extr.u r17=r25,6,7
+	mov r24=b0
+	;;
+	ld8 r18=[r18]
+	ld8 r19=[r19]
+	addl r20=@gprel(asm_mov_to_reg),gp
+	;;
+	add r19=r19,r18
+	shladd r17=r17,4,r20
+	;;
+	adds r30=kvm_resume_to_guest-asm_mov_to_reg,r20
+	st8 [r16] = r19
+	mov b0=r17
+	br.sptk.few b0
+	;;
+END(kvm_asm_mov_from_ar_sn2)
+
+
 
 // mov r1=rr[r3]
 GLOBAL_ENTRY(kvm_asm_mov_from_rr)
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/process.c linux-libre-2.6.31-gnu/arch/ia64/kvm/process.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -130,7 +130,7 @@
 	if (vdcr & IA64_DCR_PP) {
 		vpsr |= IA64_PSR_PP;
 	} else {
-		vpsr &= ~IA64_PSR_PP;;
+		vpsr &= ~IA64_PSR_PP;
 	}
 
 	vcpu_set_psr(vcpu, vpsr);
@@ -594,11 +594,11 @@
 		p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30);
 		break;
 	case PAL_BRAND_INFO:
-		p->u.pal_data.gr29 = gr29;;
+		p->u.pal_data.gr29 = gr29;
 		p->u.pal_data.gr30 = kvm_trans_pal_call_args(vcpu, gr30);
 		break;
 	default:
-		p->u.pal_data.gr29 = gr29;;
+		p->u.pal_data.gr29 = gr29;
 		p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30);
 	}
 	p->u.pal_data.gr28 = gr28;
@@ -652,20 +652,25 @@
 		unsigned long isr, unsigned long iim)
 {
 	struct kvm_vcpu *v = current_vcpu;
+	long psr;
 
 	if (ia64_psr(regs)->cpl == 0) {
 		/* Allow hypercalls only when cpl = 0.  */
 		if (iim == DOMN_PAL_REQUEST) {
+			local_irq_save(psr);
 			set_pal_call_data(v);
 			vmm_transition(v);
 			get_pal_call_result(v);
 			vcpu_increment_iip(v);
+			local_irq_restore(psr);
 			return;
 		} else if (iim == DOMN_SAL_REQUEST) {
+			local_irq_save(psr);
 			set_sal_call_data(v);
 			vmm_transition(v);
 			get_sal_call_result(v);
 			vcpu_increment_iip(v);
+			local_irq_restore(psr);
 			return;
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/vcpu.c linux-libre-2.6.31-gnu/arch/ia64/kvm/vcpu.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/vcpu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/vcpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -406,7 +406,7 @@
 	 * Now look at registers in [0-31] range and init correct UNAT
 	 */
 	addr = (unsigned long)regs;
-	unat = &regs->eml_unat;;
+	unat = &regs->eml_unat;
 
 	addr += gr_info[regnum];
 
@@ -461,7 +461,7 @@
 u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
 {
 	struct kvm_pt_regs *regs = vcpu_regs(vcpu);
-	u64 val;
+	unsigned long val;
 
 	if (!reg)
 		return 0;
@@ -469,7 +469,7 @@
 	return val;
 }
 
-void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 value, int nat)
+void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg, u64 value, int nat)
 {
 	struct kvm_pt_regs *regs = vcpu_regs(vcpu);
 	long sof = (regs->cr_ifs) & 0x7f;
@@ -788,13 +788,29 @@
 		setfpreg(reg, val, regs);   /* FIXME: handle NATs later*/
 }
 
+/*
+ * The Altix RTC is mapped specially here for the vmm module
+ */
+#define SN_RTC_BASE	(u64 *)(KVM_VMM_BASE+(1UL<<KVM_VMM_SHIFT))
+static long kvm_get_itc(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
+	struct kvm *kvm = (struct kvm *)KVM_VM_BASE;
+
+	if (kvm->arch.is_sn2)
+		return (*SN_RTC_BASE);
+	else
+#endif
+		return ia64_getreg(_IA64_REG_AR_ITC);
+}
+
 /************************************************************************
  * lsapic timer
  ***********************************************************************/
 u64 vcpu_get_itc(struct kvm_vcpu *vcpu)
 {
 	unsigned long guest_itc;
-	guest_itc = VMX(vcpu, itc_offset) + ia64_getreg(_IA64_REG_AR_ITC);
+	guest_itc = VMX(vcpu, itc_offset) + kvm_get_itc(vcpu);
 
 	if (guest_itc >= VMX(vcpu, last_itc)) {
 		VMX(vcpu, last_itc) = guest_itc;
@@ -809,7 +825,7 @@
 	struct kvm_vcpu *v;
 	struct kvm *kvm;
 	int i;
-	long itc_offset = val - ia64_getreg(_IA64_REG_AR_ITC);
+	long itc_offset = val - kvm_get_itc(vcpu);
 	unsigned long vitv = VCPU(vcpu, itv);
 
 	kvm = (struct kvm *)KVM_VM_BASE;
@@ -1056,7 +1072,7 @@
 	vcpu_set_gr(vcpu, inst.M46.r1, tag, 0);
 }
 
-int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, u64 *padr)
+int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, unsigned long *padr)
 {
 	struct thash_data *data;
 	union ia64_isr visr, pt_isr;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/vcpu.h linux-libre-2.6.31-gnu/arch/ia64/kvm/vcpu.h
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/vcpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/vcpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -686,14 +686,15 @@
 	return highest_bits((int *)&(VMX(vcpu, insvc[0])));
 }
 
-extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, u64 reg,
+extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
 					struct ia64_fpreg *val);
-extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, u64 reg,
+extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
 					struct ia64_fpreg *val);
-extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, u64 reg);
-extern void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 val, int nat);
-extern u64 vcpu_get_psr(struct kvm_vcpu *vcpu);
-extern void vcpu_set_psr(struct kvm_vcpu *vcpu, u64 val);
+extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg);
+extern void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg,
+			u64 val, int nat);
+extern unsigned long vcpu_get_psr(struct kvm_vcpu *vcpu);
+extern void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val);
 extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr);
 extern void vcpu_bsw0(struct kvm_vcpu *vcpu);
 extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte,
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/vmm.c linux-libre-2.6.31-gnu/arch/ia64/kvm/vmm.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/vmm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/vmm.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,15 +30,19 @@
 MODULE_LICENSE("GPL");
 
 extern char kvm_ia64_ivt;
+extern char kvm_asm_mov_from_ar;
+extern char kvm_asm_mov_from_ar_sn2;
 extern fpswa_interface_t *vmm_fpswa_interface;
 
 long vmm_sanity = 1;
 
 struct kvm_vmm_info vmm_info = {
-	.module	     = THIS_MODULE,
-	.vmm_entry   = vmm_entry,
-	.tramp_entry = vmm_trampoline,
-	.vmm_ivt     = (unsigned long)&kvm_ia64_ivt,
+	.module			= THIS_MODULE,
+	.vmm_entry		= vmm_entry,
+	.tramp_entry		= vmm_trampoline,
+	.vmm_ivt		= (unsigned long)&kvm_ia64_ivt,
+	.patch_mov_ar		= (unsigned long)&kvm_asm_mov_from_ar,
+	.patch_mov_ar_sn2	= (unsigned long)&kvm_asm_mov_from_ar_sn2,
 };
 
 static int __init  kvm_vmm_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/vmm_ivt.S linux-libre-2.6.31-gnu/arch/ia64/kvm/vmm_ivt.S
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/vmm_ivt.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/vmm_ivt.S	2009-09-09 18:13:59.000000000 -0400
@@ -95,7 +95,7 @@
 	;;
 	srlz.i    // guarantee that interruption collection is on
 	;;
-	//(p15) ssm psr.i               // restore psr.i
+	(p15) ssm psr.i               // restore psr.
 	addl r14=@gprel(ia64_leave_hypervisor),gp
 	;;
 	KVM_SAVE_REST
@@ -249,7 +249,7 @@
 	;;
 	srlz.i         // guarantee that interruption collection is on
 	;;
-	//(p15)ssm psr.i               // restore psr.i
+	(p15)ssm psr.i               // restore psr.i
 	addl r14=@gprel(ia64_leave_hypervisor),gp
 	;;
 	KVM_SAVE_REST
@@ -439,7 +439,7 @@
 	;;
 	srlz.i // guarantee that interruption collection is on
 	;;
-	//(p15) ssm psr.i               // restore psr.i
+	(p15) ssm psr.i               // restore psr.i
 	adds r3=8,r2                // set up second base pointer
 	;;
 	KVM_SAVE_REST
@@ -819,7 +819,7 @@
 	;;
 	srlz.i     // guarantee that interruption collection is on
 	;;
-	//(p15) ssm psr.i               // restore psr.i
+	(p15) ssm psr.i               // restore psr.i
 	addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
 	;;
 	KVM_SAVE_REST
@@ -842,7 +842,7 @@
 	;;
 	srlz.i   // guarantee that interruption collection is on
 	;;
-	//(p15) ssm psr.i               // restore psr.i
+	(p15) ssm psr.i               // restore psr.i
 	addl r14=@gprel(ia64_leave_hypervisor),gp
 	;;
 	KVM_SAVE_REST
@@ -871,7 +871,7 @@
 	;;
 	srlz.i   // guarantee that interruption collection is on
 	;;
-	//(p15) ssm psr.i               // restore psr.i
+	(p15) ssm psr.i               // restore psr.i
 	addl r14=@gprel(ia64_leave_hypervisor),gp
 	;;
 	KVM_SAVE_REST
@@ -898,7 +898,7 @@
 	;;
 	srlz.i    // guarantee that interruption collection is on
 	;;
-	//(p15) ssm psr.i               // restore psr.i
+	(p15) ssm psr.i               // restore psr.i
 	addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
 	;;
 	KVM_SAVE_REST
@@ -920,7 +920,7 @@
 	;;
 	srlz.i
 	;;
-	//(p15) ssm psr.i
+	(p15) ssm psr.i
 	addl r14=@gprel(ia64_leave_hypervisor),gp
 	;;
 	KVM_SAVE_REST
@@ -1333,7 +1333,7 @@
 	;;
 (p7)    srlz.i
 	;;
-//(p6)    ssm psr.i
+(p6)    ssm psr.i
 	;;
 	mov rp=rpsave
 	mov ar.pfs=pfssave
diff -druN linux-libre-2.6.30-gnu/arch/ia64/kvm/vtlb.c linux-libre-2.6.31-gnu/arch/ia64/kvm/vtlb.c
--- linux-libre-2.6.30-gnu/arch/ia64/kvm/vtlb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/kvm/vtlb.c	2009-09-09 18:13:59.000000000 -0400
@@ -135,7 +135,7 @@
 	u64 rid;
 
 	rid = vcpu_get_rr(vcpu, va);
-	rid = rid & RR_RID_MASK;;
+	rid = rid & RR_RID_MASK;
 	if (type == D_TLB) {
 		if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) {
 			for (trp = (struct thash_data *)&vcpu->arch.dtrs, i = 0;
@@ -254,7 +254,8 @@
 			"(p7) st8 [%2]=r9;;"
 			"ssm psr.ic;;"
 			"srlz.d;;"
-			/* "ssm psr.i;;" Once interrupts in vmm open, need fix*/
+			"ssm psr.i;;"
+			"srlz.d;;"
 			: "=r"(ret) : "r"(iha), "r"(pte):"memory");
 
 	return ret;
@@ -517,7 +518,7 @@
 
 	struct thash_cb *hcb = &v->arch.vtlb;
 
-	cch = __vtr_lookup(v, va, is_data);;
+	cch = __vtr_lookup(v, va, is_data);
 	if (cch)
 		return cch;
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/lib/ip_fast_csum.S linux-libre-2.6.31-gnu/arch/ia64/lib/ip_fast_csum.S
--- linux-libre-2.6.30-gnu/arch/ia64/lib/ip_fast_csum.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/lib/ip_fast_csum.S	2009-09-09 18:13:59.000000000 -0400
@@ -96,20 +96,22 @@
 GLOBAL_ENTRY(csum_ipv6_magic)
 	ld4	r20=[in0],4
 	ld4	r21=[in1],4
-	dep	r15=in3,in2,32,16
+	zxt4	in2=in2
 	;;
 	ld4	r22=[in0],4
 	ld4	r23=[in1],4
-	mux1	r15=r15,@rev
+	dep	r15=in3,in2,32,16
 	;;
 	ld4	r24=[in0],4
 	ld4	r25=[in1],4
-	shr.u	r15=r15,16
+	mux1	r15=r15,@rev
 	add	r16=r20,r21
 	add	r17=r22,r23
+	zxt4	in4=in4
 	;;
 	ld4	r26=[in0],4
 	ld4	r27=[in1],4
+	shr.u	r15=r15,16
 	add	r18=r24,r25
 	add	r8=r16,r17
 	;;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/Makefile linux-libre-2.6.31-gnu/arch/ia64/Makefile
--- linux-libre-2.6.30-gnu/arch/ia64/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -41,11 +41,6 @@
 		ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
 endif
 
-ifeq ($(call cc-version),0304)
-	cflags-$(CONFIG_ITANIUM)	+= -mtune=merced
-	cflags-$(CONFIG_MCKINLEY)	+= -mtune=mckinley
-endif
-
 KBUILD_CFLAGS += $(cflags-y)
 head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/mm/contig.c linux-libre-2.6.31-gnu/arch/ia64/mm/contig.c
--- linux-libre-2.6.30-gnu/arch/ia64/mm/contig.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/mm/contig.c	2009-09-09 18:13:59.000000000 -0400
@@ -107,10 +107,10 @@
  * bootmap_start.  This address must be page-aligned.
  */
 static int __init
-find_bootmap_location (unsigned long start, unsigned long end, void *arg)
+find_bootmap_location (u64 start, u64 end, void *arg)
 {
-	unsigned long needed = *(unsigned long *)arg;
-	unsigned long range_start, range_end, free_start;
+	u64 needed = *(unsigned long *)arg;
+	u64 range_start, range_end, free_start;
 	int i;
 
 #if IGNORE_PFN0
@@ -229,8 +229,7 @@
 	alloc_per_cpu_data();
 }
 
-static int
-count_pages (u64 start, u64 end, void *arg)
+static int count_pages(u64 start, u64 end, void *arg)
 {
 	unsigned long *count = arg;
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/mm/extable.c linux-libre-2.6.31-gnu/arch/ia64/mm/extable.c
--- linux-libre-2.6.30-gnu/arch/ia64/mm/extable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/mm/extable.c	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,7 @@
 #include <linux/sort.h>
 
 #include <asm/uaccess.h>
-#include <asm/module.h>
+#include <linux/module.h>
 
 static int cmp_ex(const void *a, const void *b)
 {
@@ -53,6 +53,32 @@
 	     cmp_ex, swap_ex);
 }
 
+static inline unsigned long ex_to_addr(const struct exception_table_entry *x)
+{
+	return (unsigned long)&x->addr + x->addr;
+}
+
+#ifdef CONFIG_MODULES
+/*
+ * Any entry referring to the module init will be at the beginning or
+ * the end.
+ */
+void trim_init_extable(struct module *m)
+{
+	/*trim the beginning*/
+	while (m->num_exentries &&
+	       within_module_init(ex_to_addr(&m->extable[0]), m)) {
+		m->extable++;
+		m->num_exentries--;
+	}
+	/*trim the end*/
+	while (m->num_exentries &&
+	       within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]),
+				  m))
+		m->num_exentries--;
+}
+#endif /* CONFIG_MODULES */
+
 const struct exception_table_entry *
 search_extable (const struct exception_table_entry *first,
 		const struct exception_table_entry *last,
diff -druN linux-libre-2.6.30-gnu/arch/ia64/mm/fault.c linux-libre-2.6.31-gnu/arch/ia64/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/ia64/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -154,7 +154,7 @@
 	 * sure we exit gracefully rather than endlessly redo the
 	 * fault.
 	 */
-	fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) != 0);
+	fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		/*
 		 * We ran out of memory, or some other thing happened
diff -druN linux-libre-2.6.30-gnu/arch/ia64/mm/init.c linux-libre-2.6.31-gnu/arch/ia64/mm/init.c
--- linux-libre-2.6.30-gnu/arch/ia64/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -422,8 +422,7 @@
 	return hole_next_pfn - pgdat->node_start_pfn;
 }
 
-int __init
-create_mem_map_page_table (u64 start, u64 end, void *arg)
+int __init create_mem_map_page_table(u64 start, u64 end, void *arg)
 {
 	unsigned long address, start_page, end_page;
 	struct page *map_start, *map_end;
@@ -469,7 +468,7 @@
 };
 
 static int __meminit
-virtual_memmap_init (u64 start, u64 end, void *arg)
+virtual_memmap_init(u64 start, u64 end, void *arg)
 {
 	struct memmap_init_callback_data *args;
 	struct page *map_start, *map_end;
@@ -531,8 +530,7 @@
 }
 EXPORT_SYMBOL(ia64_pfn_valid);
 
-int __init
-find_largest_hole (u64 start, u64 end, void *arg)
+int __init find_largest_hole(u64 start, u64 end, void *arg)
 {
 	u64 *max_gap = arg;
 
@@ -548,8 +546,7 @@
 
 #endif /* CONFIG_VIRTUAL_MEM_MAP */
 
-int __init
-register_active_ranges(u64 start, u64 len, int nid)
+int __init register_active_ranges(u64 start, u64 len, int nid)
 {
 	u64 end = start + len;
 
@@ -567,7 +564,7 @@
 }
 
 static int __init
-count_reserved_pages (u64 start, u64 end, void *arg)
+count_reserved_pages(u64 start, u64 end, void *arg)
 {
 	unsigned long num_reserved = 0;
 	unsigned long *count = arg;
@@ -580,7 +577,7 @@
 }
 
 int
-find_max_min_low_pfn (unsigned long start, unsigned long end, void *arg)
+find_max_min_low_pfn (u64 start, u64 end, void *arg)
 {
 	unsigned long pfn_start, pfn_end;
 #ifdef CONFIG_FLATMEM
diff -druN linux-libre-2.6.30-gnu/arch/ia64/mm/tlb.c linux-libre-2.6.31-gnu/arch/ia64/mm/tlb.c
--- linux-libre-2.6.30-gnu/arch/ia64/mm/tlb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/mm/tlb.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,7 +34,7 @@
 #include <asm/tlb.h>
 
 static struct {
-	unsigned long mask;	/* mask of supported purge page-sizes */
+	u64 mask;		/* mask of supported purge page-sizes */
 	unsigned long max_bits;	/* log2 of largest supported purge page-size */
 } purge;
 
@@ -328,7 +328,7 @@
 ia64_tlb_init (void)
 {
 	ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
-	unsigned long tr_pgbits;
+	u64 tr_pgbits;
 	long status;
 	pal_vm_info_1_u_t vm_info_1;
 	pal_vm_info_2_u_t vm_info_2;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/pci/pci.c linux-libre-2.6.31-gnu/arch/ia64/pci/pci.c
--- linux-libre-2.6.30-gnu/arch/ia64/pci/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/pci/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -163,7 +163,7 @@
 {
 	struct resource *resource;
 	char *name;
-	u64 base, min, max, base_port;
+	unsigned long base, min, max, base_port;
 	unsigned int sparse = 0, space_nr, len;
 
 	resource = kzalloc(sizeof(*resource), GFP_KERNEL);
@@ -292,7 +292,7 @@
 	window->offset = offset;
 
 	if (insert_resource(root, &window->resource)) {
-		printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n",
+		printk(KERN_ERR "alloc 0x%llx-0x%llx from %s for %s failed\n",
 			window->resource.start, window->resource.end,
 			root->name, info->name);
 	}
@@ -314,8 +314,8 @@
 		    (res->end - res->start < 16))
 			continue;
 		if (j >= PCI_BUS_NUM_RESOURCES) {
-			printk("Ignoring range [%lx-%lx] (%lx)\n", res->start,
-					res->end, res->flags);
+			printk("Ignoring range [%#llx-%#llx] (%lx)\n",
+					res->start, res->end, res->flags);
 			continue;
 		}
 		bus->resource[j++] = res;
@@ -371,8 +371,6 @@
 	 * such quirk. So we just ignore the case now.
 	 */
 	pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller);
-	if (pbus)
-		pcibios_setup_root_windows(pbus, controller);
 
 	return pbus;
 
@@ -490,6 +488,8 @@
 	if (b->self) {
 		pci_read_bridge_bases(b);
 		pcibios_fixup_bridge_resources(b->self);
+	} else {
+		pcibios_setup_root_windows(b, b->sysdata);
 	}
 	list_for_each_entry(dev, &b->devices, bus_list)
 		pcibios_fixup_device_resources(dev);
@@ -537,7 +537,7 @@
 /*
  * PCI BIOS setup, always defaults to SAL interface
  */
-char * __devinit
+char * __init
 pcibios_setup (char *str)
 {
 	return str;
@@ -728,8 +728,8 @@
  */
 static void __init set_pci_cacheline_size(void)
 {
-	u64 levels, unique_caches;
-	s64 status;
+	unsigned long levels, unique_caches;
+	long status;
 	pal_cache_config_info_t cci;
 
 	status = ia64_pal_cache_summary(&levels, &unique_caches);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/io_acpi_init.c linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/io_acpi_init.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/io_acpi_init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/io_acpi_init.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 /*
  * Perform the early IO init in PROM.
  */
-static s64
+static long
 sal_ioif_init(u64 *result)
 {
 	struct ia64_sal_retval isrv = {0,0,0,0};
@@ -492,7 +492,7 @@
 sn_io_acpi_init(void)
 {
 	u64 result;
-	s64 status;
+	long status;
 
 	/* SN Altix does not follow the IOSAPIC IRQ routing model */
 	acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/io_common.c linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/io_common.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/io_common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/io_common.c	2009-09-09 18:13:59.000000000 -0400
@@ -342,7 +342,7 @@
 		struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
 
 		printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u "
-		       "L_IO=%lx L_MEM=%lx BASE=%lx\n",
+		       "L_IO=%llx L_MEM=%llx BASE=%llx\n",
 		       b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
 		       b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
 		printk(KERN_WARNING "on node %d but only %d nodes online."
@@ -435,7 +435,8 @@
 	bricktype = MODULE_GET_BTYPE(moduleid);
 	if ((bricktype == L1_BRICKTYPE_191010) ||
 	    (bricktype == L1_BRICKTYPE_1932))
-			sprintf(address, "%s^%d", address, geo_slot(geoid));
+			sprintf(address + strlen(address), "^%d",
+						geo_slot(geoid));
 }
 
 void __devinit
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/irq.c linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -227,7 +227,7 @@
 	return new_irq_info;
 }
 
-static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
+static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
 {
 	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
 	nasid_t nasid;
@@ -239,6 +239,8 @@
 	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
 				 sn_irq_lh[irq], list)
 		(void)sn_retarget_vector(sn_irq_info, nasid, slice);
+
+	return 0;
 }
 
 #ifdef CONFIG_SMP
@@ -293,13 +295,13 @@
 void sn_irq_init(void)
 {
 	int i;
-	irq_desc_t *base_desc = irq_desc;
+	struct irq_desc *base_desc = irq_desc;
 
 	ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
 	ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
 
 	for (i = 0; i < NR_IRQS; i++) {
-		if (base_desc[i].chip == &no_irq_type) {
+		if (base_desc[i].chip == &no_irq_chip) {
 			base_desc[i].chip = &irq_type_sn;
 		}
 	}
@@ -375,7 +377,7 @@
 	int cpu = nasid_slice_to_cpuid(nasid, slice);
 #ifdef CONFIG_SMP
 	int cpuphys;
-	irq_desc_t *desc;
+	struct irq_desc *desc;
 #endif
 
 	pci_dev_get(pci_dev);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/msi_sn.c linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/msi_sn.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/msi_sn.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/msi_sn.c	2009-09-09 18:13:59.000000000 -0400
@@ -151,7 +151,7 @@
 }
 
 #ifdef CONFIG_SMP
-static void sn_set_msi_irq_affinity(unsigned int irq,
+static int sn_set_msi_irq_affinity(unsigned int irq,
 				    const struct cpumask *cpu_mask)
 {
 	struct msi_msg msg;
@@ -168,7 +168,7 @@
 	cpu = cpumask_first(cpu_mask);
 	sn_irq_info = sn_msi_info[irq].sn_irq_info;
 	if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
-		return;
+		return -1;
 
 	/*
 	 * Release XIO resources for the old MSI PCI address
@@ -189,7 +189,7 @@
 	new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
 	sn_msi_info[irq].sn_irq_info = new_irq_info;
 	if (new_irq_info == NULL)
-		return;
+		return -1;
 
 	/*
 	 * Map the xio address into bus space
@@ -206,6 +206,8 @@
 
 	write_msi_msg(irq, &msg);
 	cpumask_copy(irq_desc[irq].affinity, cpu_mask);
+
+	return 0;
 }
 #endif /* CONFIG_SMP */
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2009-09-09 18:13:59.000000000 -0400
@@ -414,7 +414,7 @@
 		}
 		seq_printf(s, "partition %u %s local "
 			"shubtype %s, "
-			"nasid_mask 0x%016lx, "
+			"nasid_mask 0x%016llx, "
 			"nasid_bits %d:%d, "
 			"system_size %d, "
 			"sharing_size %d, "
@@ -683,7 +683,7 @@
  * ioctl for "sn_hwperf" misc device
  */
 static int
-sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
+sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, unsigned long arg)
 {
 	struct sn_hwperf_ioctl_args a;
 	struct cpuinfo_ia64 *cdata;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,7 @@
 
 static int licenseID_show(struct seq_file *s, void *p)
 {
-	seq_printf(s, "0x%lx\n", sn_partition_serial_number_val());
+	seq_printf(s, "0x%llx\n", sn_partition_serial_number_val());
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/tiocx.c linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/tiocx.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/kernel/tiocx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/kernel/tiocx.c	2009-09-09 18:13:59.000000000 -0400
@@ -368,7 +368,7 @@
 static int is_fpga_tio(int nasid, int *bt)
 {
 	u16 uninitialized_var(ioboard_type);	/* GCC be quiet */
-	s64 rc;
+	long rc;
 
 	rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
 	if (rc) {
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c linux-libre-2.6.31-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,7 +79,7 @@
 
 u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
 {
-	s64 rc;
+	long rc;
 	u16 uninitialized_var(ioboard);		/* GCC be quiet */
 	nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
 
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/pci/pci_dma.c linux-libre-2.6.31-gnu/arch/ia64/sn/pci/pci_dma.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/pci/pci_dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/pci/pci_dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -90,7 +90,8 @@
 	 */
 	node = pcibus_to_node(pdev->bus);
 	if (likely(node >=0)) {
-		struct page *p = alloc_pages_node(node, flags, get_order(size));
+		struct page *p = alloc_pages_exact_node(node,
+						flags, get_order(size));
 
 		if (likely(p))
 			cpuaddr = page_address(p);
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/pci/tioca_provider.c linux-libre-2.6.31-gnu/arch/ia64/sn/pci/tioca_provider.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/pci/tioca_provider.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/pci/tioca_provider.c	2009-09-09 18:13:59.000000000 -0400
@@ -123,7 +123,7 @@
 
 	if (!tmp) {
 		printk(KERN_ERR "%s:  Could not allocate "
-		       "%lu bytes (order %d) for GART\n",
+		       "%llu bytes (order %d) for GART\n",
 		       __func__,
 		       tioca_kern->ca_gart_size,
 		       get_order(tioca_kern->ca_gart_size));
@@ -348,7 +348,7 @@
 	agp_dma_extn = __sn_readq_relaxed(&ca_base->ca_agp_dma_addr_extn);
 	if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
 		printk(KERN_ERR "%s:  coretalk upper node (%u) "
-		       "mismatch with ca_agp_dma_addr_extn (%lu)\n",
+		       "mismatch with ca_agp_dma_addr_extn (%llu)\n",
 		       __func__,
 		       node_upper, (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT));
 		return 0;
@@ -367,7 +367,7 @@
  * dma_addr_t is guaranteed to be contiguous in CA bus space.
  */
 static dma_addr_t
-tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size)
+tioca_dma_mapped(struct pci_dev *pdev, unsigned long paddr, size_t req_size)
 {
 	int i, ps, ps_shift, entry, entries, mapsize, last_entry;
 	u64 xio_addr, end_xio_addr;
diff -druN linux-libre-2.6.30-gnu/arch/ia64/sn/pci/tioce_provider.c linux-libre-2.6.31-gnu/arch/ia64/sn/pci/tioce_provider.c
--- linux-libre-2.6.30-gnu/arch/ia64/sn/pci/tioce_provider.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/sn/pci/tioce_provider.c	2009-09-09 18:13:59.000000000 -0400
@@ -493,7 +493,7 @@
 
 		if (&map->ce_dmamap_list == &ce_kern->ce_dmamap_list) {
 			printk(KERN_WARNING
-			       "%s:  %s - no map found for bus_addr 0x%lx\n",
+			       "%s:  %s - no map found for bus_addr 0x%llx\n",
 			       __func__, pci_name(pdev), bus_addr);
 		} else if (--map->refcnt == 0) {
 			for (i = 0; i < map->ate_count; i++) {
@@ -642,7 +642,7 @@
  * in the address.
  */
 static u64
-tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+tioce_dma(struct pci_dev *pdev, unsigned long  paddr, size_t byte_count, int dma_flags)
 {
 	return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags);
 }
@@ -657,7 +657,7 @@
  * in the address.
  */
 static u64
-tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+tioce_dma_consistent(struct pci_dev *pdev, unsigned long  paddr, size_t byte_count, int dma_flags)
 {
 	return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
 }
diff -druN linux-libre-2.6.30-gnu/arch/ia64/xen/irq_xen.c linux-libre-2.6.31-gnu/arch/ia64/xen/irq_xen.c
--- linux-libre-2.6.30-gnu/arch/ia64/xen/irq_xen.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/ia64/xen/irq_xen.c	2009-09-09 18:13:59.000000000 -0400
@@ -138,7 +138,7 @@
 __xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
 			struct irqaction *action, int save)
 {
-	irq_desc_t *desc;
+	struct irq_desc *desc;
 	int irq = 0;
 
 	if (xen_slab_ready) {
diff -druN linux-libre-2.6.30-gnu/arch/Kconfig linux-libre-2.6.31-gnu/arch/Kconfig
--- linux-libre-2.6.30-gnu/arch/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -112,3 +112,5 @@
 
 config HAVE_DEFAULT_NO_SPIN_MUTEXES
 	bool
+
+source "kernel/gcov/Kconfig"
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -314,5 +314,5 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif	/* _ASM_M32R_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,28 +2,11 @@
 #define __M32R_KMAP_TYPES_H
 
 #ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
+#define  __WITH_KM_FENCE
 #endif
 
-enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_IRQ0,
-D(10)	KM_IRQ1,
-D(11)	KM_SOFTIRQ0,
-D(12)	KM_SOFTIRQ1,
-D(13)	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
-#undef D
+#undef __WITH_KM_FENCE
 
 #endif /* __M32R_KMAP_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/mman.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __M32R_MMAN_H__
 #define __M32R_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/page.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -82,6 +82,6 @@
 #define devmem_is_allowed(x) 1
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _ASM_M32R_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/pci.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,4 @@
 
 #include <asm-generic/pci.h>
 
-#define PCI_DMA_BUS_IS_PHYS	(1)
-
 #endif /* _ASM_M32R_PCI_H */
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -58,7 +58,7 @@
 	__free_page(pte);
 }
 
-#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, (pte))
+#define __pte_free_tlb(tlb, pte, addr)	pte_free((tlb)->mm, (pte))
 
 /*
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
@@ -68,7 +68,7 @@
 
 #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
 #define pmd_free(mm, x)			do { } while (0)
-#define __pmd_free_tlb(tlb, x)		do { } while (0)
+#define __pmd_free_tlb(tlb, x, addr)	do { } while (0)
 #define pgd_populate(mm, pmd, pte)	BUG()
 
 #define check_pgt_cache()	do { } while (0)
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/signal.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -107,7 +107,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/m32r/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/m32r/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/m32r/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -57,8 +57,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -68,7 +66,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
diff -druN linux-libre-2.6.30-gnu/arch/m32r/kernel/init_task.c linux-libre-2.6.31-gnu/arch/m32r/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/m32r/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,10 +13,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/m32r/kernel/module.c linux-libre-2.6.31-gnu/arch/m32r/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/m32r/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,8 +44,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* We don't need anything special. */
diff -druN linux-libre-2.6.30-gnu/arch/m32r/kernel/process.c linux-libre-2.6.31-gnu/arch/m32r/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/m32r/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -302,11 +302,6 @@
 		goto out;
 
 	error = do_execve(filename, uargv, uenvp, &regs);
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
-		task_unlock(current);
-	}
 	putname(filename);
 out:
 	return error;
diff -druN linux-libre-2.6.30-gnu/arch/m32r/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/m32r/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/m32r/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,6 @@
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
@@ -676,10 +675,6 @@
 		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		if ((child->ptrace & PT_DTRACE) == 0) {
-			/* Spurious delayed TF traps may occur */
-			child->ptrace |= PT_DTRACE;
-		}
 
 		/* Compute next pc.  */
 		pc = get_stack_long(child, PT_BPC);
diff -druN linux-libre-2.6.30-gnu/arch/m32r/mm/discontig.c linux-libre-2.6.31-gnu/arch/m32r/mm/discontig.c
--- linux-libre-2.6.30-gnu/arch/m32r/mm/discontig.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/mm/discontig.c	2009-09-09 18:13:59.000000000 -0400
@@ -154,9 +154,9 @@
 	 *  Use all area of internal RAM.
 	 *  see __alloc_pages()
 	 */
-	NODE_DATA(1)->node_zones->pages_min = 0;
-	NODE_DATA(1)->node_zones->pages_low = 0;
-	NODE_DATA(1)->node_zones->pages_high = 0;
+	NODE_DATA(1)->node_zones->watermark[WMARK_MIN] = 0;
+	NODE_DATA(1)->node_zones->watermark[WMARK_LOW] = 0;
+	NODE_DATA(1)->node_zones->watermark[WMARK_HIGH] = 0;
 
 	return holes;
 }
diff -druN linux-libre-2.6.30-gnu/arch/m32r/mm/fault.c linux-libre-2.6.31-gnu/arch/m32r/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/m32r/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -196,7 +196,7 @@
 	 */
 	addr = (address & PAGE_MASK);
 	set_thread_fault_code(error_code);
-	fault = handle_mm_fault(mm, vma, addr, write);
+	fault = handle_mm_fault(mm, vma, addr, write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/m32104ut/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/m32104ut/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/m32104ut/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/m32104ut/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -63,7 +63,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type m32104ut_irq_type =
+static struct irq_chip m32104ut_irq_type =
 {
 	.typename = "M32104UT-IRQ",
 	.startup = startup_m32104ut_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/m32700ut/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/m32700ut/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/m32700ut/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/m32700ut/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -69,7 +69,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type m32700ut_irq_type =
+static struct irq_chip m32700ut_irq_type =
 {
 	.typename = "M32700UT-IRQ",
 	.startup = startup_m32700ut_irq,
@@ -146,7 +146,7 @@
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type m32700ut_pld_irq_type =
+static struct irq_chip m32700ut_pld_irq_type =
 {
 	.typename = "M32700UT-PLD-IRQ",
 	.startup = startup_m32700ut_pld_irq,
@@ -215,7 +215,7 @@
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type m32700ut_lanpld_irq_type =
+static struct irq_chip m32700ut_lanpld_irq_type =
 {
 	.typename = "M32700UT-PLD-LAN-IRQ",
 	.startup = startup_m32700ut_lanpld_irq,
@@ -284,7 +284,7 @@
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type m32700ut_lcdpld_irq_type =
+static struct irq_chip m32700ut_lcdpld_irq_type =
 {
 	.typename = "M32700UT-PLD-LCD-IRQ",
 	.startup = startup_m32700ut_lcdpld_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/mappi/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/mappi/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/mappi/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/mappi/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -63,7 +63,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type mappi_irq_type =
+static struct irq_chip mappi_irq_type =
 {
 	.typename = "MAPPI-IRQ",
 	.startup = startup_mappi_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/mappi2/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/mappi2/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/mappi2/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/mappi2/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type mappi2_irq_type =
+static struct irq_chip mappi2_irq_type =
 {
 	.typename = "MAPPI2-IRQ",
 	.startup = startup_mappi2_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/mappi3/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/mappi3/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/mappi3/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/mappi3/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type mappi3_irq_type =
+static struct irq_chip mappi3_irq_type =
 {
 	.typename = "MAPPI3-IRQ",
 	.startup = startup_mappi3_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/oaks32r/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/oaks32r/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/oaks32r/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/oaks32r/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,7 +61,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type oaks32r_irq_type =
+static struct irq_chip oaks32r_irq_type =
 {
 	.typename = "OAKS32R-IRQ",
 	.startup = startup_oaks32r_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/opsput/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/opsput/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/opsput/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/opsput/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type opsput_irq_type =
+static struct irq_chip opsput_irq_type =
 {
 	.typename = "OPSPUT-IRQ",
 	.startup = startup_opsput_irq,
@@ -147,7 +147,7 @@
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type opsput_pld_irq_type =
+static struct irq_chip opsput_pld_irq_type =
 {
 	.typename = "OPSPUT-PLD-IRQ",
 	.startup = startup_opsput_pld_irq,
@@ -216,7 +216,7 @@
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type opsput_lanpld_irq_type =
+static struct irq_chip opsput_lanpld_irq_type =
 {
 	.typename = "OPSPUT-PLD-LAN-IRQ",
 	.startup = startup_opsput_lanpld_irq,
@@ -285,7 +285,7 @@
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type opsput_lcdpld_irq_type =
+static struct irq_chip opsput_lcdpld_irq_type =
 {
 	"OPSPUT-PLD-LCD-IRQ",
 	startup_opsput_lcdpld_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m32r/platforms/usrv/setup.c linux-libre-2.6.31-gnu/arch/m32r/platforms/usrv/setup.c
--- linux-libre-2.6.30-gnu/arch/m32r/platforms/usrv/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m32r/platforms/usrv/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,7 +61,7 @@
 	outl(M32R_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type mappi_irq_type =
+static struct irq_chip mappi_irq_type =
 {
 	.typename = "M32700-IRQ",
 	.startup = startup_mappi_irq,
@@ -134,7 +134,7 @@
 	outw(PLD_ICUCR_ILEVEL7, port);
 }
 
-static struct hw_interrupt_type m32700ut_pld_irq_type =
+static struct irq_chip m32700ut_pld_irq_type =
 {
 	.typename = "USRV-PLD-IRQ",
 	.startup = startup_m32700ut_pld_irq,
diff -druN linux-libre-2.6.30-gnu/arch/m68k/amiga/config.c linux-libre-2.6.31-gnu/arch/m68k/amiga/config.c
--- linux-libre-2.6.30-gnu/arch/m68k/amiga/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/amiga/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -574,10 +574,11 @@
 
 	tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
 
-	while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+	while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt) {
 		tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
 		udelay(70);
 		tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+		--cnt;
 	}
 
 	if (!cnt)
@@ -649,10 +650,11 @@
 
 		tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
 
-		while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+		while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt) {
 			tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
 			udelay(70);
 			tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+			--cnt;
 		}
 
 		if (!cnt)
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/atomic_mm.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/atomic_mm.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/atomic_mm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/atomic_mm.h	2009-09-09 18:13:59.000000000 -0400
@@ -192,5 +192,5 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* __ARCH_M68K_ATOMIC __ */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/atomic_no.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/atomic_no.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/atomic_no.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/atomic_no.h	2009-09-09 18:13:59.000000000 -0400
@@ -151,5 +151,5 @@
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
 #define atomic_inc_return(v) atomic_add_return(1,(v))
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* __ARCH_M68KNOMMU_ATOMIC __ */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,21 +1,6 @@
 #ifndef __ASM_M68K_KMAP_TYPES_H
 #define __ASM_M68K_KMAP_TYPES_H
 
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
 #endif	/* __ASM_M68K_KMAP_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/m520xsim.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/m520xsim.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/m520xsim.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/m520xsim.h	2009-09-09 18:13:59.000000000 -0400
@@ -59,5 +59,14 @@
 #define MCFPIT_IMR		MCFINTC_IMRL
 #define MCFPIT_IMR_IBIT		(1 << MCFINT_PIT1)
 
+/*
+ *  Reset Controll Unit.
+ */
+#define	MCF_RCR			0xFC0A0000
+#define	MCF_RSR			0xFC0A0001
+
+#define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
+#define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
+
 /****************************************************************************/
 #endif  /* m520xsim_h */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/m523xsim.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/m523xsim.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/m523xsim.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/m523xsim.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,5 +41,14 @@
 #define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
 #define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
 
+/*
+ *  Reset Controll Unit (relative to IPSBAR).
+ */
+#define	MCF_RCR			0x110000
+#define	MCF_RSR			0x110001
+
+#define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
+#define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
+
 /****************************************************************************/
 #endif	/* m523xsim_h */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/m527xsim.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/m527xsim.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/m527xsim.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/m527xsim.h	2009-09-09 18:13:59.000000000 -0400
@@ -70,5 +70,14 @@
 #define UART2_ENABLE_MASK	0x3f00 
 #endif
 
+/*
+ *  Reset Controll Unit (relative to IPSBAR).
+ */
+#define	MCF_RCR			0x110000
+#define	MCF_RSR			0x110001
+
+#define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
+#define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
+
 /****************************************************************************/
 #endif	/* m527xsim_h */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/m528xsim.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/m528xsim.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/m528xsim.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/m528xsim.h	2009-09-09 18:13:59.000000000 -0400
@@ -56,6 +56,14 @@
 #define MCF5282_INTC0_ICR17     (volatile u8 *) (MCF_IPSBAR + 0x0C51)
 
 
+/*
+ *  Reset Control Unit (relative to IPSBAR).
+ */
+#define	MCF_RCR			0x110000
+#define	MCF_RSR			0x110001
+
+#define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
+#define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
 
 /*********************************************************************
 *
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/m532xsim.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/m532xsim.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/m532xsim.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/m532xsim.h	2009-09-09 18:13:59.000000000 -0400
@@ -127,6 +127,18 @@
 
 /*********************************************************************
  *
+ * Reset Controller Module
+ *
+ *********************************************************************/
+
+#define	MCF_RCR			0xFC0A0000
+#define	MCF_RSR			0xFC0A0001
+
+#define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
+#define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
+
+/*********************************************************************
+ *
  * Inter-IC (I2C) Module
  *
  *********************************************************************/
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/mman.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __M68K_MMAN_H__
 #define __M68K_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/motorola_pgalloc.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/motorola_pgalloc.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/motorola_pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/motorola_pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,12 +36,10 @@
 		return NULL;
 
 	pte = kmap(page);
-	if (pte) {
-		__flush_page_to_ram(pte);
-		flush_tlb_kernel_page(pte);
-		nocache_page(pte);
-	}
-	kunmap(pte);
+	__flush_page_to_ram(pte);
+	flush_tlb_kernel_page(pte);
+	nocache_page(pte);
+	kunmap(page);
 	pgtable_page_ctor(page);
 	return page;
 }
@@ -54,7 +52,8 @@
 	__free_page(page);
 }
 
-static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page)
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
+				  unsigned long address)
 {
 	pgtable_page_dtor(page);
 	cache_page(kmap(page));
@@ -73,7 +72,8 @@
 	return free_pointer_table(pmd);
 }
 
-static inline int __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+static inline int __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+				 unsigned long address)
 {
 	return free_pointer_table(pmd);
 }
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/page_mm.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/page_mm.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/page_mm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/page_mm.h	2009-09-09 18:13:59.000000000 -0400
@@ -223,6 +223,6 @@
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _M68K_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/page_no.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/page_no.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/page_no.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/page_no.h	2009-09-09 18:13:59.000000000 -0400
@@ -72,6 +72,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _M68KNOMMU_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/pgtable_mm.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/pgtable_mm.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/pgtable_mm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/pgtable_mm.h	2009-09-09 18:13:59.000000000 -0400
@@ -135,8 +135,6 @@
 #endif
 
 #ifndef __ASSEMBLY__
-#include <asm-generic/pgtable.h>
-
 /*
  * Macro to mark a page protection value as "uncacheable".
  */
@@ -154,6 +152,7 @@
 	    ? (__pgprot((pgprot_val(prot) & _CACHEMASK040) | _PAGE_NOCACHE_S))	\
 	    : (prot)))
 
+#include <asm-generic/pgtable.h>
 #endif /* !__ASSEMBLY__ */
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/processor_no.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/processor_no.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/processor_no.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/processor_no.h	2009-09-09 18:13:59.000000000 -0400
@@ -72,10 +72,10 @@
 	unsigned char  fpstate[FPSTATESIZE];  /* floating point state */
 };
 
-#define INIT_THREAD  { \
-	sizeof(init_stack) + (unsigned long) init_stack, 0, \
-	PS_S, __KERNEL_DS, \
-	{0, 0}, 0, {0,}, {0, 0, 0}, {0,}, \
+#define INIT_THREAD  {							\
+	.ksp	= sizeof(init_stack) + (unsigned long) init_stack,	\
+	.sr	= PS_S,							\
+	.fs	= __KERNEL_DS,						\
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/signal.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -103,7 +103,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/sun3_pgalloc.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/sun3_pgalloc.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/sun3_pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/sun3_pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,7 @@
         __free_page(page);
 }
 
-#define __pte_free_tlb(tlb,pte)				\
+#define __pte_free_tlb(tlb,pte,addr)			\
 do {							\
 	pgtable_page_dtor(pte);				\
 	tlb_remove_page((tlb), pte);			\
@@ -80,7 +80,7 @@
  * inside the pgd, so has no extra memory associated with it.
  */
 #define pmd_free(mm, x)			do { } while (0)
-#define __pmd_free_tlb(tlb, x)		do { } while (0)
+#define __pmd_free_tlb(tlb, x, addr)	do { } while (0)
 
 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/suspend.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/suspend.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/suspend.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _M68K_SUSPEND_H
-#define _M68K_SUSPEND_H
-
-/* Dummy include. */
-
-#endif  /* _M68K_SUSPEND_H */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/swab.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/swab.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/swab.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/swab.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef _M68K_SWAB_H
 #define _M68K_SWAB_H
 
-#include <asm/types.h>
+#include <linux/types.h>
 #include <linux/compiler.h>
 
 #define __SWAB_64_THRU_32__
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/system_no.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/system_no.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/system_no.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/system_no.h	2009-09-09 18:13:59.000000000 -0400
@@ -203,113 +203,6 @@
 #include <asm-generic/cmpxchg.h>
 #endif
 
-#if defined( CONFIG_M68328 ) || defined( CONFIG_M68EZ328 ) || \
-	defined (CONFIG_M68360) || defined( CONFIG_M68VZ328 )
-#define HARD_RESET_NOW() ({		\
-        local_irq_disable();		\
-        asm("				\
-        moveal #0x10c00000, %a0;	\
-        moveb #0, 0xFFFFF300;		\
-        moveal 0(%a0), %sp;		\
-        moveal 4(%a0), %a0;		\
-        jmp (%a0);			\
-        ");				\
-})
-#endif
-
-#ifdef CONFIG_COLDFIRE
-#if defined(CONFIG_M5272) && defined(CONFIG_NETtel)
-/*
- * Need to account for broken early mask of 5272 silicon. So don't
- * jump through the original start address. Jump strait into the
- * known start of the FLASH code.
- */
-#define HARD_RESET_NOW() ({		\
-        asm("				\
-	movew #0x2700, %sr;		\
-        jmp 0xf0000400;			\
-        ");				\
-})
-#elif defined(CONFIG_NETtel) || \
-      defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
-#define HARD_RESET_NOW() ({		\
-        asm("				\
-	movew #0x2700, %sr;		\
-	moveal #0x10000044, %a0;	\
-	movel #0xffffffff, (%a0);	\
-	moveal #0x10000001, %a0;	\
-	moveb #0x00, (%a0);		\
-        moveal #0xf0000004, %a0;	\
-        moveal (%a0), %a0;		\
-        jmp (%a0);			\
-        ");				\
-})
-#elif defined(CONFIG_M5272)
-/*
- * Retrieve the boot address in flash using CSBR0 and CSOR0
- * find the reset vector at flash_address + 4 (e.g. 0x400)
- * remap it in the flash's current location (e.g. 0xf0000400)
- * and jump there.
- */ 
-#define HARD_RESET_NOW() ({		\
-	asm("				\
-	movew #0x2700, %%sr;		\
-	move.l	%0+0x40,%%d0;		\
-	and.l	%0+0x44,%%d0;		\
-	andi.l	#0xfffff000,%%d0;	\
-	mov.l	%%d0,%%a0;		\
-	or.l	4(%%a0),%%d0;		\
-	mov.l	%%d0,%%a0;		\
-	jmp (%%a0);"			\
-	: /* No output */		\
-	: "o" (*(char *)MCF_MBAR) );	\
-})
-#elif defined(CONFIG_M528x)
-/*
- * The MCF528x has a bit (SOFTRST) in memory (Reset Control Register RCR),
- * that when set, resets the MCF528x.
- */
-#define HARD_RESET_NOW() \
-({						\
-	unsigned char volatile *reset;		\
-	asm("move.w	#0x2700, %sr");		\
-	reset = ((volatile unsigned char *)(MCF_IPSBAR + 0x110000));	\
-	while(1)				\
-	*reset |= (0x01 << 7);\
-})
-#elif defined(CONFIG_M523x)
-#define HARD_RESET_NOW() ({		\
-	asm("				\
-	movew #0x2700, %sr;		\
-	movel #0x01000000, %sp;		\
-	moveal #0x40110000, %a0;	\
-	moveb #0x80, (%a0);		\
-	");				\
-})
-#elif defined(CONFIG_M520x)
-	/*
-	 * The MCF5208 has a bit (SOFTRST) in memory (Reset Control Register 
-	 * RCR), that when set, resets the MCF5208.
-	 */
-#define HARD_RESET_NOW() 		\
-({					\
-	unsigned char volatile *reset;	\
-	asm("move.w     #0x2700, %sr");	\
-	reset = ((volatile unsigned char *)(MCF_IPSBAR + 0xA0000));	\
-	while(1)			\
-		*reset |= 0x80;		\
-})
-#else
-#define HARD_RESET_NOW() ({		\
-        asm("				\
-	movew #0x2700, %sr;		\
-        moveal #0x4, %a0;		\
-        moveal (%a0), %a0;		\
-        jmp (%a0);			\
-        ");				\
-})
-#endif
-#endif
 #define arch_align_stack(x) (x)
 
 
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/thread_info_mm.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/thread_info_mm.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/thread_info_mm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/thread_info_mm.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 {						\
 	.task		= &tsk,			\
 	.exec_domain	= &default_exec_domain,	\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/thread_info_no.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/thread_info_no.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/thread_info_no.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/thread_info_no.h	2009-09-09 18:13:59.000000000 -0400
@@ -49,6 +49,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
diff -druN linux-libre-2.6.30-gnu/arch/m68k/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/m68k/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/m68k/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -334,10 +334,12 @@
 #define __NR_inotify_init1	328
 #define __NR_preadv		329
 #define __NR_pwritev		330
+#define __NR_rt_tgsigqueueinfo	331
+#define __NR_perf_counter_open	332
 
 #ifdef __KERNEL__
 
-#define NR_syscalls		331
+#define NR_syscalls		333
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.30-gnu/arch/m68k/kernel/entry.S linux-libre-2.6.31-gnu/arch/m68k/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/m68k/kernel/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -755,4 +755,6 @@
 	.long sys_inotify_init1
 	.long sys_preadv
 	.long sys_pwritev		/* 330 */
+	.long sys_rt_tgsigqueueinfo
+	.long sys_perf_counter_open
 
diff -druN linux-libre-2.6.30-gnu/arch/m68k/kernel/module.c linux-libre-2.6.31-gnu/arch/m68k/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/m68k/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,8 +31,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* We don't need anything special. */
diff -druN linux-libre-2.6.30-gnu/arch/m68k/kernel/process.c linux-libre-2.6.31-gnu/arch/m68k/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/m68k/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,10 +42,6 @@
  */
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 union thread_union init_thread_union
 __attribute__((section(".data.init_task"), aligned(THREAD_SIZE)))
        = { INIT_THREAD_INFO(init_task) };
diff -druN linux-libre-2.6.30-gnu/arch/m68k/kernel/traps.c linux-libre-2.6.31-gnu/arch/m68k/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/m68k/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -1057,7 +1057,6 @@
 	if (fp->ptregs.sr & PS_S) {
 		if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
 			/* traced a trapping instruction */
-			current->ptrace |= PT_DTRACE;
 		} else
 			bad_super_trap(fp);
 		return;
diff -druN linux-libre-2.6.30-gnu/arch/m68k/mm/fault.c linux-libre-2.6.31-gnu/arch/m68k/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/m68k/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68k/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -155,7 +155,7 @@
 	 */
 
  survive:
-	fault = handle_mm_fault(mm, vma, address, write);
+	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
 #ifdef DEBUG
 	printk("handle_mm_fault returns %d\n",fault);
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/asm-offsets.c linux-libre-2.6.31-gnu/arch/m68knommu/kernel/asm-offsets.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/asm-offsets.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/asm-offsets.c	2009-09-09 18:13:59.000000000 -0400
@@ -73,7 +73,6 @@
 	DEFINE(TRAP_TRACE, TRAP_TRACE);
 
 	DEFINE(PT_PTRACED, PT_PTRACED);
-	DEFINE(PT_DTRACE, PT_DTRACE);
 
 	DEFINE(THREAD_SIZE, THREAD_SIZE);
 
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/entry.S linux-libre-2.6.31-gnu/arch/m68knommu/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,6 @@
 
 #include <linux/sys.h>
 #include <linux/linkage.h>
-#include <asm/thread_info.h>
 #include <asm/errno.h>
 #include <asm/setup.h>
 #include <asm/segment.h>
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/init_task.c linux-libre-2.6.31-gnu/arch/m68knommu/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,10 +14,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial task structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/module.c linux-libre-2.6.31-gnu/arch/m68knommu/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* We don't need anything special. */
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/process.c linux-libre-2.6.31-gnu/arch/m68knommu/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -290,7 +290,7 @@
 	unsigned char	*tp;
 	int		i;
 
-	printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" KERN_EMERG "\n");
+	printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
 	printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
 
 	if (current->mm) {
@@ -301,8 +301,7 @@
 			(int) current->mm->end_data,
 			(int) current->mm->end_data,
 			(int) current->mm->brk);
-		printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n"
-			KERN_EMERG "\n",
+		printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n",
 			(int) current->mm->start_stack,
 			(int)(((unsigned long) current) + THREAD_SIZE));
 	}
@@ -313,35 +312,35 @@
 		fp->d0, fp->d1, fp->d2, fp->d3);
 	printk(KERN_EMERG "d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
 		fp->d4, fp->d5, fp->a0, fp->a1);
-	printk(KERN_EMERG "\n" KERN_EMERG "USP: %08x   TRAPFRAME: %08x\n",
+	printk(KERN_EMERG "\nUSP: %08x   TRAPFRAME: %08x\n",
 		(unsigned int) rdusp(), (unsigned int) fp);
 
-	printk(KERN_EMERG "\n" KERN_EMERG "CODE:");
+	printk(KERN_EMERG "\nCODE:");
 	tp = ((unsigned char *) fp->pc) - 0x20;
 	for (sp = (unsigned long *) tp, i = 0; (i < 0x40);  i += 4) {
 		if ((i % 0x10) == 0)
-			printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+			printk(KERN_EMERG "%08x: ", (int) (tp + i));
 		printk("%08x ", (int) *sp++);
 	}
-	printk("\n" KERN_EMERG "\n");
+	printk(KERN_EMERG "\n");
 
 	printk(KERN_EMERG "KERNEL STACK:");
 	tp = ((unsigned char *) fp) - 0x40;
 	for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
 		if ((i % 0x10) == 0)
-			printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+			printk(KERN_EMERG "%08x: ", (int) (tp + i));
 		printk("%08x ", (int) *sp++);
 	}
-	printk("\n" KERN_EMERG "\n");
+	printk(KERN_EMERG "\n");
 
 	printk(KERN_EMERG "USER STACK:");
 	tp = (unsigned char *) (rdusp() - 0x10);
 	for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
 		if ((i % 0x10) == 0)
-			printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+			printk(KERN_EMERG "%08x: ", (int) (tp + i));
 		printk("%08x ", (int) *sp++);
 	}
-	printk("\n" KERN_EMERG "\n");
+	printk(KERN_EMERG "\n");
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/setup.c linux-libre-2.6.31-gnu/arch/m68knommu/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -166,15 +166,13 @@
 	printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n");
 #endif
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
-		"BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
-		(int) &_sdata, (int) &_edata,
-		(int) &_sbss, (int) &_ebss);
-	printk(KERN_DEBUG "MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ",
-		(int) &_ebss, (int) memory_start,
-		(int) memory_start, (int) memory_end);
-#endif
+	pr_debug("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
+		 "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
+		 (int) &_sdata, (int) &_edata,
+		 (int) &_sbss, (int) &_ebss);
+	pr_debug("MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ",
+		 (int) &_ebss, (int) memory_start,
+		 (int) memory_start, (int) memory_end);
 
 	/* Keep a copy of command line */
 	*cmdline_p = &command_line[0];
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/syscalltable.S linux-libre-2.6.31-gnu/arch/m68knommu/kernel/syscalltable.S
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/syscalltable.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/syscalltable.S	2009-09-09 18:13:59.000000000 -0400
@@ -349,6 +349,8 @@
 	.long sys_inotify_init1
 	.long sys_preadv
 	.long sys_pwritev		/* 330 */
+	.long sys_rt_tgsigqueueinfo
+	.long sys_perf_counter_open
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/kernel/traps.c linux-libre-2.6.31-gnu/arch/m68knommu/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -111,7 +111,7 @@
 	if (i % 5)
 		printk(KERN_CONT " [%08lx] ", addr);
 	else
-		printk(KERN_CONT "\n" KERN_EMERG " [%08lx] ", addr);
+		printk(KERN_EMERG " [%08lx] ", addr);
 	i++;
 #endif
 }
@@ -137,8 +137,8 @@
 		if (stack + 1 + i > endstack)
 			break;
 		if (i % 8 == 0)
-			printk("\n" KERN_EMERG "       ");
-		printk(" %08lx", *(stack + i));
+			printk(KERN_EMERG "       ");
+		printk(KERN_CONT " %08lx", *(stack + i));
 	}
 	printk("\n");
 	i = 0;
@@ -200,7 +200,6 @@
 	if (fp->ptregs.sr & PS_S) {
 		if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
 			/* traced a trapping instruction */
-			current->ptrace |= PT_DTRACE;
 		} else
 			bad_super_trap(fp);
 		return;
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/mm/init.c linux-libre-2.6.31-gnu/arch/m68knommu/mm/init.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -126,9 +126,7 @@
 	unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
 	unsigned long end_mem   = memory_end; /* DAVIDM - this must not include kernel stack at top */
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
-#endif
+	pr_debug("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
 
 	end_mem &= PAGE_MASK;
 	high_memory = (void *) end_mem;
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/5206/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/5206/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/5206/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/5206/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -21,10 +20,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m5206_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -109,10 +104,21 @@
 
 /***************************************************************************/
 
+void m5206_cpu_reset(void)
+{
+	local_irq_disable();
+	/* Set watchdog to soft reset, and enabled */
+	__raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+	for (;;)
+		/* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
-	mach_reset = coldfire_reset;
+	mach_reset = m5206_cpu_reset;
 }
 
 /***************************************************************************/
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/5206e/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/5206e/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/5206e/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/5206e/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -21,10 +20,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m5206e_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -109,6 +104,17 @@
 
 /***************************************************************************/
 
+void m5206e_cpu_reset(void)
+{
+	local_irq_disable();
+	/* Set watchdog to soft reset, and enabled */
+	__raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+	for (;;)
+		/* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
@@ -119,7 +125,7 @@
 	commandp[size-1] = 0;
 #endif /* CONFIG_NETtel */
 
-	mach_reset = coldfire_reset;
+	mach_reset = m5206e_cpu_reset;
 }
 
 /***************************************************************************/
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/520x/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/520x/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/520x/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/520x/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -23,10 +22,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m520x_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -169,9 +164,17 @@
 
 /***************************************************************************/
 
+static void m520x_cpu_reset(void)
+{
+	local_irq_disable();
+	__raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
-	mach_reset = coldfire_reset;
+	mach_reset = m520x_cpu_reset;
 	m520x_uarts_init();
 	m520x_fec_init();
 }
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/523x/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/523x/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/523x/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/523x/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -24,10 +23,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m523x_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -145,13 +140,20 @@
 {
 	/* Everything is auto-vectored on the 523x */
 }
+/***************************************************************************/
+
+static void m523x_cpu_reset(void)
+{
+	local_irq_disable();
+	__raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
+}
 
 /***************************************************************************/
 
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_disableall();
-	mach_reset = coldfire_reset;
+	mach_reset = m523x_cpu_reset;
 	m523x_uarts_init();
 	m523x_fec_init();
 }
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/5249/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/5249/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/5249/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/5249/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -20,10 +19,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m5249_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -106,10 +101,21 @@
 
 /***************************************************************************/
 
+void m5249_cpu_reset(void)
+{
+	local_irq_disable();
+	/* Set watchdog to soft reset, and enabled */
+	__raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+	for (;;)
+		/* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
-	mach_reset = coldfire_reset;
+	mach_reset = m5249_cpu_reset;
 }
 
 /***************************************************************************/
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/5272/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/5272/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/5272/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/5272/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -21,8 +20,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
 extern unsigned int mcf_timervector;
 extern unsigned int mcf_profilevector;
 extern unsigned int mcf_timerlevel;
@@ -170,6 +167,19 @@
 
 /***************************************************************************/
 
+static void m5272_cpu_reset(void)
+{
+	local_irq_disable();
+	/* Set watchdog to reset, and enabled */
+	__raw_writew(0, MCF_MBAR + MCFSIM_WIRR);
+	__raw_writew(1, MCF_MBAR + MCFSIM_WRRR);
+	__raw_writew(0, MCF_MBAR + MCFSIM_WCR);
+	for (;;)
+		/* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 #if defined (CONFIG_MOD5272)
@@ -194,7 +204,7 @@
 
 	mcf_timervector = 69;
 	mcf_profilevector = 70;
-	mach_reset = coldfire_reset;
+	mach_reset = m5272_cpu_reset;
 }
 
 /***************************************************************************/
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/527x/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/527x/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/527x/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/527x/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -24,10 +23,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m527x_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -227,10 +222,18 @@
 
 /***************************************************************************/
 
+static void m527x_cpu_reset(void)
+{
+	local_irq_disable();
+	__raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_disableall();
-	mach_reset = coldfire_reset;
+	mach_reset = m527x_cpu_reset;
 	m527x_uarts_init();
 	m527x_fec_init();
 }
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/528x/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/528x/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/528x/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/528x/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,10 +31,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
-/***************************************************************************/
-
 static struct mcf_platform_uart m528x_uart_platform[] = {
 	{
 		.mapbase	= MCF_MBAR + MCFUART_BASE1,
@@ -171,6 +167,14 @@
 
 /***************************************************************************/
 
+static void m528x_cpu_reset(void)
+{
+	local_irq_disable();
+	__raw_writeb(MCF_RCR_SWRESET, MCF_IPSBAR + MCF_RCR);
+}
+
+/***************************************************************************/
+
 #ifdef CONFIG_WILDFIRE
 void wildfire_halt(void)
 {
@@ -214,6 +218,7 @@
 
 static int __init init_BSP(void)
 {
+	mach_reset = m528x_cpu_reset;
 	m528x_uarts_init();
 	m528x_fec_init();
 	platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices));
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/5307/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/5307/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/5307/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/5307/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -22,8 +21,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
 extern unsigned int mcf_timervector;
 extern unsigned int mcf_profilevector;
 extern unsigned int mcf_timerlevel;
@@ -119,6 +116,17 @@
 
 /***************************************************************************/
 
+void m5307_cpu_reset(void)
+{
+	local_irq_disable();
+	/* Set watchdog to soft reset, and enabled */
+	__raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+	for (;;)
+		/* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
@@ -134,7 +142,7 @@
 	mcf_timerlevel = 6;
 #endif
 
-	mach_reset = coldfire_reset;
+	mach_reset = m5307_cpu_reset;
 
 #ifdef CONFIG_BDM_DISABLE
 	/*
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/532x/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/532x/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/532x/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/532x/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,8 +31,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
 extern unsigned int mcf_timervector;
 extern unsigned int mcf_profilevector;
 extern unsigned int mcf_timerlevel;
@@ -164,6 +162,14 @@
 
 /***************************************************************************/
 
+static void m532x_cpu_reset(void)
+{
+	local_irq_disable();
+	__raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
@@ -181,7 +187,7 @@
 
 	mcf_timervector = 64+32;
 	mcf_profilevector = 64+33;
-	mach_reset = coldfire_reset;
+	mach_reset = m532x_cpu_reset;
 
 #ifdef CONFIG_BDM_DISABLE
 	/*
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/5407/config.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/5407/config.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/5407/config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/5407/config.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
@@ -21,8 +20,6 @@
 
 /***************************************************************************/
 
-void coldfire_reset(void);
-
 extern unsigned int mcf_timervector;
 extern unsigned int mcf_profilevector;
 extern unsigned int mcf_timerlevel;
@@ -110,6 +107,17 @@
 
 /***************************************************************************/
 
+void m5407_cpu_reset(void)
+{
+	local_irq_disable();
+	/* set watchdog to soft reset, and enabled */
+	__raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+	for (;;)
+		/* wait for watchdog to timeout */;
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
@@ -121,7 +129,7 @@
 	mcf_timerlevel = 6;
 #endif
 
-	mach_reset = coldfire_reset;
+	mach_reset = m5407_cpu_reset;
 }
 
 /***************************************************************************/
diff -druN linux-libre-2.6.30-gnu/arch/m68knommu/platform/coldfire/vectors.c linux-libre-2.6.31-gnu/arch/m68knommu/platform/coldfire/vectors.c
--- linux-libre-2.6.30-gnu/arch/m68knommu/platform/coldfire/vectors.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/m68knommu/platform/coldfire/vectors.c	2009-09-09 18:13:59.000000000 -0400
@@ -96,10 +96,3 @@
 }
 
 /***************************************************************************/
-
-void coldfire_reset(void)
-{
-	HARD_RESET_NOW();
-}
-
-/***************************************************************************/
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/boot/Makefile linux-libre-2.6.31-gnu/arch/microblaze/boot/Makefile
--- linux-libre-2.6.30-gnu/arch/microblaze/boot/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/boot/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,6 +7,8 @@
 OBJCOPYFLAGS_linux.bin  := -O binary
 
 $(obj)/linux.bin: vmlinux FORCE
+	[ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \
+	touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image"
 	$(call if_changed,objcopy)
 	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/configs/mmu_defconfig linux-libre-2.6.31-gnu/arch/microblaze/configs/mmu_defconfig
--- linux-libre-2.6.30-gnu/arch/microblaze/configs/mmu_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/configs/mmu_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,800 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc6
+# Tue Aug 18 11:00:02 2009
+#
+CONFIG_MICROBLAZE=y
+# CONFIG_SWAP is not set
+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_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+# CONFIG_GENERIC_TIME_VSYSCALL is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_CSUM=y
+# CONFIG_PCI is not set
+CONFIG_NO_DMA=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="rootfs.cpio"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_INITRAMFS_COMPRESSION_NONE is not set
+CONFIG_INITRAMFS_COMPRESSION_GZIP=y
+# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set
+# CONFIG_INITRAMFS_COMPRESSION_LZMA is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_SHMEM is not set
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_BASE_SMALL=1
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# Platform options
+#
+CONFIG_PLATFORM_GENERIC=y
+CONFIG_OPT_LIB_FUNCTION=y
+CONFIG_OPT_LIB_ASM=y
+CONFIG_ALLOW_EDIT_AUTO=y
+
+#
+# Automatic platform settings from Kconfig.auto
+#
+
+#
+# Definitions for MICROBLAZE0
+#
+CONFIG_KERNEL_BASE_ADDR=0x90000000
+CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex5"
+CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
+CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1
+CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
+CONFIG_XILINX_MICROBLAZE0_USE_DIV=1
+CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2
+CONFIG_XILINX_MICROBLAZE0_USE_FPU=2
+CONFIG_XILINX_MICROBLAZE0_HW_VER="7.10.d"
+
+#
+# Processor type and features
+#
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT 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_SCHED_HRTICK is not set
+CONFIG_MMU=y
+
+#
+# Boot options
+#
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyUL0,115200"
+CONFIG_CMDLINE_FORCE=y
+CONFIG_OF=y
+CONFIG_PROC_DEVICETREE=y
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Exectuable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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_XFRM_STATISTICS is not set
+# 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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_XILINX_SYSACE is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_KS8842 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# 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_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_XILINX_HWICAP is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# 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 is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=y
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# 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=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_KMEMCHECK is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_HEART_BEAT=y
+CONFIG_DEBUG_BOOTMEM=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/configs/nommu_defconfig linux-libre-2.6.31-gnu/arch/microblaze/configs/nommu_defconfig
--- linux-libre-2.6.30-gnu/arch/microblaze/configs/nommu_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/configs/nommu_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc5
-# Mon May 11 09:01:02 2009
+# Linux kernel version: 2.6.31-rc6
+# Tue Aug 18 10:35:30 2009
 #
 CONFIG_MICROBLAZE=y
 # CONFIG_SWAP is not set
@@ -17,9 +17,12 @@
 # CONFIG_GENERIC_TIME_VSYSCALL is not set
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_CSUM=y
 # CONFIG_PCI is not set
-# CONFIG_NO_DMA is not set
+CONFIG_NO_DMA=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -64,7 +67,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -76,13 +78,23 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -95,7 +107,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -156,8 +168,16 @@
 CONFIG_CMDLINE="console=ttyUL0,115200"
 # CONFIG_CMDLINE_FORCE is not set
 CONFIG_OF=y
-CONFIG_OF_DEVICE=y
 CONFIG_PROC_DEVICETREE=y
+
+#
+# Advanced setup
+#
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_KERNEL_START=0x90000000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -169,7 +189,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1
 
 #
@@ -237,6 +257,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -254,7 +275,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -353,6 +378,7 @@
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
@@ -364,6 +390,7 @@
 # CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_XILINX_SYSACE is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_C2PORT is not set
@@ -383,7 +410,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -402,7 +428,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -463,23 +489,25 @@
 # CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
+# CONFIG_XILINX_HWICAP is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -489,22 +517,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -520,9 +533,10 @@
 # CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_SOUND is not set
 CONFIG_USB_SUPPORT=y
-# CONFIG_USB_ARCH_HAS_HCD is not set
+CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
 
@@ -543,9 +557,12 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-# CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -558,12 +575,15 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -813,6 +833,5 @@
 CONFIG_ZLIB_INFLATE=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,95 +1,7 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
 #ifndef _ASM_MICROBLAZE_ATOMIC_H
 #define _ASM_MICROBLAZE_ATOMIC_H
 
-#include <linux/types.h>
-#include <linux/compiler.h> /* likely */
-#include <asm/system.h> /* local_irq_XXX and friends */
-
-#define ATOMIC_INIT(i)		{ (i) }
-#define atomic_read(v)		((v)->counter)
-#define atomic_set(v, i)	(((v)->counter) = (i))
-
-#define atomic_inc(v)		(atomic_add_return(1, (v)))
-#define atomic_dec(v)		(atomic_sub_return(1, (v)))
-
-#define atomic_add(i, v)	(atomic_add_return(i, (v)))
-#define atomic_sub(i, v)	(atomic_sub_return(i, (v)))
-
-#define atomic_inc_return(v)	(atomic_add_return(1, (v)))
-#define atomic_dec_return(v)	(atomic_sub_return(1, (v)))
-
-#define atomic_inc_and_test(v)	(atomic_add_return(1, (v)) == 0)
-#define atomic_dec_and_test(v)	(atomic_sub_return(1, (v)) == 0)
-
-#define atomic_inc_not_zero(v)	(atomic_add_unless((v), 1, 0))
-
-#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-	int ret;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	ret = v->counter;
-	if (likely(ret == old))
-		v->counter = new;
-	local_irq_restore(flags);
-
-	return ret;
-}
-
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int c, old;
-
-	c = atomic_read(v);
-	while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
-		c = old;
-	return c != u;
-}
-
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	*addr &= ~mask;
-	local_irq_restore(flags);
-}
-
-/**
- * atomic_add_return - add and return
- * @i: integer value to add
- * @v: pointer of type atomic_t
- *
- * Atomically adds @i to @v and returns @i + @v
- */
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-	unsigned long flags;
-	int val;
-
-	local_irq_save(flags);
-	val = v->counter;
-	v->counter = val += i;
-	local_irq_restore(flags);
-
-	return val;
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	return atomic_add_return(-i, v);
-}
+#include <asm-generic/atomic.h>
 
 /*
  * Atomically test *v and decrement if it is greater than 0.
@@ -109,15 +21,4 @@
 	return res;
 }
 
-#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()	barrier()
-#define smp_mb__after_atomic_dec()	barrier()
-#define smp_mb__before_atomic_inc()	barrier()
-#define smp_mb__after_atomic_inc()	barrier()
-
-#include <asm-generic/atomic.h>
-
 #endif /* _ASM_MICROBLAZE_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bitops.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bitops.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bitops.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bitops.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,27 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_BITOPS_H
-#define _ASM_MICROBLAZE_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-#include <asm/byteorder.h> /* swab32 */
-#include <asm/system.h> /* save_flags */
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit()	barrier()
-#define smp_mb__after_clear_bit()	barrier()
 #include <asm-generic/bitops.h>
-#include <asm-generic/bitops/__fls.h>
-
-#endif /* _ASM_MICROBLAZE_BITOPS_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bug.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bug.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bug.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,15 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_BUG_H
-#define _ASM_MICROBLAZE_BUG_H
-
-#include <linux/kernel.h>
 #include <asm-generic/bug.h>
-
-#endif /* _ASM_MICROBLAZE_BUG_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bugs.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bugs.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/bugs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/bugs.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,17 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_BUGS_H
-#define _ASM_MICROBLAZE_BUGS_H
-
-static inline void check_bugs(void)
-{
-	/* nothing to do */
-}
-
-#endif /* _ASM_MICROBLAZE_BUGS_H */
+#include <asm-generic/bugs.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/cacheflush.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/cacheflush.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/cacheflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/cacheflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2007 PetaLogix
+ * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
  * based on v850 version which was
  * Copyright (C) 2001,02,03 NEC Electronics Corporation
@@ -43,6 +44,23 @@
 #define flush_icache_range(start, len)	__invalidate_icache_range(start, len)
 #define flush_icache_page(vma, pg)		do { } while (0)
 
+#ifndef CONFIG_MMU
+# define flush_icache_user_range(start, len)	do { } while (0)
+#else
+# define flush_icache_user_range(vma, pg, adr, len) __invalidate_icache_all()
+
+# define flush_page_to_ram(page)		do { } while (0)
+
+# define flush_icache()			__invalidate_icache_all()
+# define flush_cache_sigtramp(vaddr) \
+			__invalidate_icache_range(vaddr, vaddr + 8)
+
+# define flush_dcache_mmap_lock(mapping)	do { } while (0)
+# define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+
+# define flush_cache_dup_mm(mm)			do { } while (0)
+#endif
+
 #define flush_cache_vmap(start, end)		do { } while (0)
 #define flush_cache_vunmap(start, end)		do { } while (0)
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/checksum.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/checksum.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/checksum.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/checksum.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,12 +10,11 @@
 #ifndef _ASM_MICROBLAZE_CHECKSUM_H
 #define _ASM_MICROBLAZE_CHECKSUM_H
 
-#include <linux/in6.h>
-
 /*
  * computes the checksum of the TCP/UDP pseudo-header
  * returns a 16-bit checksum, already complemented
  */
+#define csum_tcpudp_nofold	csum_tcpudp_nofold
 static inline __wsum
 csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
 		   unsigned short proto, __wsum sum)
@@ -30,69 +29,6 @@
 	return sum;
 }
 
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy(const char *src, char *dst, int len, int sum);
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy_from_user(const char *src, char *dst,
-					int len, int sum, int *csum_err);
-
-#define csum_partial_copy_nocheck(src, dst, len, sum)	\
-	csum_partial_copy((src), (dst), (len), (sum))
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- *
- */
-extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- *	Fold a partial checksum
- */
-static inline __sum16 csum_fold(unsigned int sum)
-{
-	sum = (sum & 0xffff) + (sum >> 16);
-	sum = (sum & 0xffff) + (sum >> 16);
-	return ~sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-extern __sum16 ip_compute_csum(const unsigned char *buff, int len);
+#include <asm-generic/checksum.h>
 
 #endif /* _ASM_MICROBLAZE_CHECKSUM_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/current.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/current.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/current.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/current.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,6 +11,12 @@
 #ifndef _ASM_MICROBLAZE_CURRENT_H
 #define _ASM_MICROBLAZE_CURRENT_H
 
+/*
+ * Register used to hold the current task pointer while in the kernel.
+ * Any `call clobbered' register without a special meaning should be OK,
+ * but check asm/microblaze/kernel/entry.S to be sure.
+ */
+#define CURRENT_TASK	r31
 # ifndef __ASSEMBLY__
 /*
  * Dedicate r31 to keeping the current task pointer
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/dma.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/dma.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,8 +9,13 @@
 #ifndef _ASM_MICROBLAZE_DMA_H
 #define _ASM_MICROBLAZE_DMA_H
 
+#ifndef CONFIG_MMU
 /* we don't have dma address limit. define it as zero to be
  * unlimited. */
 #define MAX_DMA_ADDRESS		(0)
+#else
+/* Virtual address corresponding to last available physical memory address.  */
+#define MAX_DMA_ADDRESS (CONFIG_KERNEL_START + memory_size - 1)
+#endif
 
 #endif /* _ASM_MICROBLAZE_DMA_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,129 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_DMA_MAPPING_H
-#define _ASM_MICROBLAZE_DMA_MAPPING_H
-
-#include <asm/cacheflush.h>
-#include <linux/io.h>
-#include <linux/bug.h>
-
-struct scatterlist;
-
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-/* FIXME */
-static inline int
-dma_supported(struct device *dev, u64 mask)
-{
-	return 1;
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page,
-	unsigned long offset, size_t size,
-	enum dma_data_direction direction)
-{
-	BUG();
-	return 0;
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	enum dma_data_direction direction)
-{
-	BUG();
-	return 0;
-}
-
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-			enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline void
-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-		size_t size, enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-		enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline void
-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-		enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-	return 0;
-}
-
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-				dma_addr_t *dma_handle, int flag)
-{
-	return NULL; /* consistent_alloc(flag, size, dma_handle); */
-}
-
-static inline void dma_free_coherent(struct device *dev, size_t size,
-			void *vaddr, dma_addr_t dma_handle)
-{
-	BUG();
-}
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
-	enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
-
-	return virt_to_bus(ptr);
-}
-
-static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-				    size_t size,
-				    enum dma_data_direction direction)
-{
-	switch (direction) {
-	case DMA_FROM_DEVICE:
-		flush_dcache_range((unsigned)dma_addr,
-			(unsigned)dma_addr + size);
-			/* Fall through */
-	case DMA_TO_DEVICE:
-		break;
-	default:
-		BUG();
-	}
-}
-
-#endif /* _ASM_MICROBLAZE_DMA_MAPPING_H */
+#include <asm-generic/dma-mapping-broken.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/elf.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/elf.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/elf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/elf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -27,4 +29,95 @@
  */
 #define ELF_CLASS	ELFCLASS32
 
+#ifndef __uClinux__
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/byteorder.h>
+
+#ifndef ELF_GREG_T
+#define ELF_GREG_T
+typedef unsigned long elf_greg_t;
+#endif
+
+#ifndef ELF_NGREG
+#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
+#endif
+
+#ifndef ELF_GREGSET_T
+#define ELF_GREGSET_T
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+#endif
+
+#ifndef ELF_FPREGSET_T
+#define ELF_FPREGSET_T
+
+/* TBD */
+#define ELF_NFPREG	33	/* includes fsr */
+typedef unsigned long elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/* typedef struct user_fpu_struct elf_fpregset_t; */
+#endif
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+
+#define ELF_ET_DYN_BASE         (0x08000000)
+
+#ifdef __LITTLE_ENDIAN__
+#define ELF_DATA	ELFDATA2LSB
+#else
+#define ELF_DATA	ELFDATA2MSB
+#endif
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	4096
+
+
+#define ELF_CORE_COPY_REGS(_dest, _regs)			\
+	memcpy((char *) &_dest, (char *) _regs,		\
+	sizeof(struct pt_regs));
+
+/* This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports.  This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+#define ELF_HWCAP	(0)
+
+/* This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+
+ * For the moment, we have only optimizations for the Intel generations,
+ * but that could change...
+ */
+#define ELF_PLATFORM  (NULL)
+
+/* Added _f parameter. Is this definition correct: TBD */
+#define ELF_PLAT_INIT(_r, _f)				\
+do {							\
+	_r->r1 =  _r->r1 =  _r->r2 =  _r->r3 =		\
+	_r->r4 =  _r->r5 =  _r->r6 =  _r->r7 =		\
+	_r->r8 =  _r->r9 =  _r->r10 = _r->r11 =		\
+	_r->r12 = _r->r13 = _r->r14 = _r->r15 =		\
+	_r->r16 = _r->r17 = _r->r18 = _r->r19 =		\
+	_r->r20 = _r->r21 = _r->r22 = _r->r23 =		\
+	_r->r24 = _r->r25 = _r->r26 = _r->r27 =		\
+	_r->r28 = _r->r29 = _r->r30 = _r->r31 =		\
+	0;						\
+} while (0)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#endif
+
+#endif /* __uClinux__ */
+
 #endif /* _ASM_MICROBLAZE_ELF_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/entry.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/entry.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/entry.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/entry.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,8 @@
 /*
  * Definitions used by low-level trap handlers
  *
- * Copyright (C) 2008 Michal Simek
- * Copyright (C) 2007 - 2008 PetaLogix
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
  *
  * This file is subject to the terms and conditions of the GNU General
@@ -31,7 +31,40 @@
 DECLARE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */
 # endif /* __ASSEMBLY__ */
 
+#ifndef CONFIG_MMU
+
 /* noMMU hasn't any space for args */
 # define STATE_SAVE_ARG_SPACE	(0)
 
+#else /* CONFIG_MMU */
+
+/* If true, system calls save and restore all registers (except result
+ * registers, of course).  If false, then `call clobbered' registers
+ * will not be preserved, on the theory that system calls are basically
+ * function calls anyway, and the caller should be able to deal with it.
+ * This is a security risk, of course, as `internal' values may leak out
+ * after a system call, but that certainly doesn't matter very much for
+ * a processor with no MMU protection!  For a protected-mode kernel, it
+ * would be faster to just zero those registers before returning.
+ *
+ * I can not rely on the glibc implementation. If you turn it off make
+ * sure that r11/r12 is saved in user-space. --KAA
+ *
+ * These are special variables using by the kernel trap/interrupt code
+ * to save registers in, at a time when there are no spare registers we
+ * can use to do so, and we can't depend on the value of the stack
+ * pointer.  This means that they must be within a signed 16-bit
+ * displacement of 0x00000000.
+ */
+
+/* A `state save frame' is a struct pt_regs preceded by some extra space
+ * suitable for a function call stack frame. */
+
+/* Amount of room on the stack reserved for arguments and to satisfy the
+ * C calling conventions, in addition to the space used by the struct
+ * pt_regs that actually holds saved values. */
+#define STATE_SAVE_ARG_SPACE	(6*4) /* Up to six arguments */
+
+#endif /* CONFIG_MMU */
+
 #endif /* _ASM_MICROBLAZE_ENTRY_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/exceptions.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/exceptions.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/exceptions.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/exceptions.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,8 @@
 /*
  * Preliminary support for HW exception handing for Microblaze
  *
- * Copyright (C) 2008 Michal Simek
- * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au>
  *
  * This file is subject to the terms and conditions of the GNU General
@@ -64,21 +64,13 @@
 void die(const char *str, struct pt_regs *fp, long err);
 void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
 
-#if defined(CONFIG_XMON)
-extern void xmon(struct pt_regs *regs);
-extern int xmon_bpt(struct pt_regs *regs);
-extern int xmon_sstep(struct pt_regs *regs);
-extern int xmon_iabr_match(struct pt_regs *regs);
-extern int xmon_dabr_match(struct pt_regs *regs);
-extern void (*xmon_fault_handler)(struct pt_regs *regs);
+#ifdef CONFIG_MMU
+void __bug(const char *file, int line, void *data);
+int bad_trap(int trap_num, struct pt_regs *regs);
+int debug_trap(struct pt_regs *regs);
+#endif /* CONFIG_MMU */
 
-void (*debugger)(struct pt_regs *regs) = xmon;
-int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt;
-int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep;
-int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match;
-int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match;
-void (*debugger_fault_handler)(struct pt_regs *regs);
-#elif defined(CONFIG_KGDB)
+#if defined(CONFIG_KGDB)
 void (*debugger)(struct pt_regs *regs);
 int (*debugger_bpt)(struct pt_regs *regs);
 int (*debugger_sstep)(struct pt_regs *regs);
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/fb.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/fb.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/fb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/fb.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/fb.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/flat.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/flat.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/flat.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/flat.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,6 @@
 
 #include <asm/unaligned.h>
 
-#define	flat_stack_align(sp) /* nothing needed */
 #define	flat_argvp_envp_on_stack()	0
 #define	flat_old_ram_flag(flags)	(flags)
 #define	flat_reloc_valid(reloc, size)	((reloc) <= (size))
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/gpio.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/gpio.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,8 +11,8 @@
  * (at your option) any later version.
  */
 
-#ifndef __ASM_POWERPC_GPIO_H
-#define __ASM_POWERPC_GPIO_H
+#ifndef _ASM_MICROBLAZE_GPIO_H
+#define _ASM_MICROBLAZE_GPIO_H
 
 #include <linux/errno.h>
 #include <asm-generic/gpio.h>
@@ -53,4 +53,4 @@
 
 #endif /* CONFIG_GPIOLIB */
 
-#endif /* __ASM_POWERPC_GPIO_H */
+#endif /* _ASM_MICROBLAZE_GPIO_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/hardirq.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/hardirq.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/hardirq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/hardirq.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,21 +9,9 @@
 #ifndef _ASM_MICROBLAZE_HARDIRQ_H
 #define _ASM_MICROBLAZE_HARDIRQ_H
 
-#include <linux/cache.h>
-#include <linux/irq.h>
-#include <asm/irq.h>
-#include <asm/current.h>
-#include <linux/ptrace.h>
-
 /* should be defined in each interrupt controller driver */
 extern unsigned int get_irq(struct pt_regs *regs);
 
-typedef struct {
-	unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-void ack_bad_irq(unsigned int irq);
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#include <asm-generic/hardirq.h>
 
 #endif /* _ASM_MICROBLAZE_HARDIRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ioctls.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ioctls.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ioctls.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ioctls.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,91 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_IOCTLS_H
-#define _ASM_MICROBLAZE_IOCTLS_H
-
-#include <linux/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT	0x5426 /* For debugging only */
-#define TIOCSBRK	0x5427 /* BSD compatibility */
-#define TIOCCBRK	0x5428 /* BSD compatibility */
-#define TIOCGSID	0x5429 /* Return the session ID of FD */
-/* Get Pty Number (of pty-mux device) */
-#define TIOCGPTN	_IOR('T', 0x30, unsigned int)
-#define TIOCSPTLCK	_IOW('T', 0x31, int) /* Lock/unlock Pty */
-
-#define FIONCLEX	0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR	0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D /* read serial port inline interrupt counts */
-
-#define	FIOQSIZE	0x545E
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		0
-#define TIOCPKT_FLUSHREAD	1
-#define TIOCPKT_FLUSHWRITE	2
-#define TIOCPKT_STOP		4
-#define TIOCPKT_START		8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-
-#define TIOCSER_TEMT	0x01 /* Transmitter physically empty */
-
-#endif /* _ASM_MICROBLAZE_IOCTLS_H */
+#include <asm-generic/ioctls.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/io.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/io.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -12,6 +14,8 @@
 #include <asm/byteorder.h>
 #include <asm/page.h>
 #include <linux/types.h>
+#include <linux/mm.h>          /* Get struct page {...} */
+
 
 #define IO_SPACE_LIMIT (0xFFFFFFFF)
 
@@ -112,6 +116,30 @@
 #define memcpy_fromio(a, b, c)	memcpy((a), (void *)(b), (c))
 #define memcpy_toio(a, b, c)	memcpy((void *)(a), (b), (c))
 
+#ifdef CONFIG_MMU
+
+#define mm_ptov(addr)		((void *)__phys_to_virt(addr))
+#define mm_vtop(addr)		((unsigned long)__virt_to_phys(addr))
+#define phys_to_virt(addr)	((void *)__phys_to_virt(addr))
+#define virt_to_phys(addr)	((unsigned long)__virt_to_phys(addr))
+#define virt_to_bus(addr)	((unsigned long)__virt_to_phys(addr))
+
+#define __page_address(page) \
+		(PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define page_to_phys(page)	virt_to_phys((void *)__page_address(page))
+#define page_to_bus(page)	(page_to_phys(page))
+#define bus_to_virt(addr)	(phys_to_virt(addr))
+
+extern void iounmap(void *addr);
+/*extern void *__ioremap(phys_addr_t address, unsigned long size,
+		unsigned long flags);*/
+extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
+#define ioremap_writethrough(addr, size) ioremap((addr), (size))
+#define ioremap_nocache(addr, size)      ioremap((addr), (size))
+#define ioremap_fullcache(addr, size)    ioremap((addr), (size))
+
+#else /* CONFIG_MMU */
+
 /**
  *	virt_to_phys - map virtual addresses to physical
  *	@address: address to remap
@@ -160,6 +188,8 @@
 #define iounmap(addr)		((void)0)
 #define ioremap_nocache(physaddr, size)	ioremap(physaddr, size)
 
+#endif /* CONFIG_MMU */
+
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ipcbuf.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ipcbuf.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ipcbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ipcbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,36 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_IPCBUF_H
-#define _ASM_MICROBLAZE_IPCBUF_H
-
-/*
- * The user_ipc_perm structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm {
-	__kernel_key_t		key;
-	__kernel_uid32_t	uid;
-	__kernel_gid32_t	gid;
-	__kernel_uid32_t	cuid;
-	__kernel_gid32_t	cgid;
-	__kernel_mode_t		mode;
-	unsigned short		__pad1;
-	unsigned short		seq;
-	unsigned short		__pad2;
-	unsigned long		__unused1;
-	unsigned long		__unused2;
-};
-
-#endif /* _ASM_MICROBLAZE_IPCBUF_H */
+#include <asm-generic/ipcbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/irq.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/irq.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #define _ASM_MICROBLAZE_IRQ_H
 
 #define NR_IRQS 32
+#include <asm-generic/irq.h>
 
 #include <linux/interrupt.h>
 
@@ -17,11 +18,6 @@
 
 #define NO_IRQ (-1)
 
-static inline int irq_canonicalize(int irq)
-{
-	return irq;
-}
-
 struct pt_regs;
 extern void do_IRQ(struct pt_regs *regs);
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/Kbuild linux-libre-2.6.31-gnu/arch/microblaze/include/asm/Kbuild
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/Kbuild	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/Kbuild	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,3 @@
 include include/asm-generic/Kbuild.asm
 
-header-y += auxvec.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += linkage.h
-header-y += msgbuf.h
-header-y += poll.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += socket.h
-header-y += sockios.h
-header-y += statfs.h
-header-y += stat.h
-header-y += termbits.h
-header-y += ucontext.h
-
-unifdef-y += cputable.h
-unifdef-y += elf.h
-unifdef-y += termios.h
+header-y  += elf.h
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,29 +1,6 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
 #ifndef _ASM_MICROBLAZE_KMAP_TYPES_H
 #define _ASM_MICROBLAZE_KMAP_TYPES_H
 
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR,
-};
+#include <asm-generic/kmap_types.h>
 
 #endif /* _ASM_MICROBLAZE_KMAP_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mman.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_MMAN_H
-#define _ASM_MICROBLAZE_MMAN_H
-
 #include <asm-generic/mman.h>
-
-#define MAP_GROWSDOWN	0x0100 /* stack-like segment */
-#define MAP_DENYWRITE	0x0800 /* ETXTBSY */
-#define MAP_EXECUTABLE	0x1000 /* mark it as an executable */
-#define MAP_LOCKED	0x2000 /* pages are locked */
-#define MAP_NORESERVE	0x4000 /* don't check for reservations */
-#define MAP_POPULATE	0x8000 /* populate (prefault) pagetables */
-#define MAP_NONBLOCK	0x10000 /* do not block on IO */
-
-#define MCL_CURRENT	1 /* lock all current mappings */
-#define MCL_FUTURE	2 /* lock all future mappings */
-
-#endif /* _ASM_MICROBLAZE_MMAN_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mmu_context.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mmu_context.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mmu_context.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mmu_context.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,21 +1,5 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
-#define _ASM_MICROBLAZE_MMU_CONTEXT_H
-
-# define init_new_context(tsk, mm)		({ 0; })
-
-# define enter_lazy_tlb(mm, tsk)		do {} while (0)
-# define change_mm_context(old, ctx, _pml4)	do {} while (0)
-# define destroy_context(mm)			do {} while (0)
-# define deactivate_mm(tsk, mm)			do {} while (0)
-# define switch_mm(prev, next, tsk)		do {} while (0)
-# define activate_mm(prev, next)		do {} while (0)
-
-#endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */
+#ifdef CONFIG_MMU
+# include "mmu_context_mm.h"
+#else
+# include <asm-generic/mmu_context.h>
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mmu_context_mm.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mmu_context_mm.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mmu_context_mm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mmu_context_mm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * 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.
+ */
+
+#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
+#define _ASM_MICROBLAZE_MMU_CONTEXT_H
+
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+#include <asm/mmu.h>
+#include <asm-generic/mm_hooks.h>
+
+# ifdef __KERNEL__
+/*
+ * This function defines the mapping from contexts to VSIDs (virtual
+ * segment IDs).  We use a skew on both the context and the high 4 bits
+ * of the 32-bit virtual address (the "effective segment ID") in order
+ * to spread out the entries in the MMU hash table.
+ */
+# define CTX_TO_VSID(ctx, va)	(((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
+				 & 0xffffff)
+
+/*
+   MicroBlaze has 256 contexts, so we can just rotate through these
+   as a way of "switching" contexts.  If the TID of the TLB is zero,
+   the PID/TID comparison is disabled, so we can use a TID of zero
+   to represent all kernel pages as shared among all contexts.
+ */
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+# define NO_CONTEXT	256
+# define LAST_CONTEXT	255
+# define FIRST_CONTEXT	1
+
+/*
+ * Set the current MMU context.
+ * This is done byloading up the segment registers for the user part of the
+ * address space.
+ *
+ * Since the PGD is immediately available, it is much faster to simply
+ * pass this along as a second parameter, which is required for 8xx and
+ * can be used for debugging on all processors (if you happen to have
+ * an Abatron).
+ */
+extern void set_context(mm_context_t context, pgd_t *pgd);
+
+/*
+ * Bitmap of contexts in use.
+ * The size of this bitmap is LAST_CONTEXT + 1 bits.
+ */
+extern unsigned long context_map[];
+
+/*
+ * This caches the next context number that we expect to be free.
+ * Its use is an optimization only, we can't rely on this context
+ * number to be free, but it usually will be.
+ */
+extern mm_context_t next_mmu_context;
+
+/*
+ * Since we don't have sufficient contexts to give one to every task
+ * that could be in the system, we need to be able to steal contexts.
+ * These variables support that.
+ */
+extern atomic_t nr_free_contexts;
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
+extern void steal_context(void);
+
+/*
+ * Get a new mmu context for the address space described by `mm'.
+ */
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+	mm_context_t ctx;
+
+	if (mm->context != NO_CONTEXT)
+		return;
+	while (atomic_dec_if_positive(&nr_free_contexts) < 0)
+		steal_context();
+	ctx = next_mmu_context;
+	while (test_and_set_bit(ctx, context_map)) {
+		ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
+		if (ctx > LAST_CONTEXT)
+			ctx = 0;
+	}
+	next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+	mm->context = ctx;
+	context_mm[ctx] = mm;
+}
+
+/*
+ * Set up the context for a new address space.
+ */
+# define init_new_context(tsk, mm)	(((mm)->context = NO_CONTEXT), 0)
+
+/*
+ * We're finished using the context for an address space.
+ */
+static inline void destroy_context(struct mm_struct *mm)
+{
+	if (mm->context != NO_CONTEXT) {
+		clear_bit(mm->context, context_map);
+		mm->context = NO_CONTEXT;
+		atomic_inc(&nr_free_contexts);
+	}
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+	tsk->thread.pgdir = next->pgd;
+	get_mmu_context(next);
+	set_context(next->context, next->pgd);
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+static inline void activate_mm(struct mm_struct *active_mm,
+			struct mm_struct *mm)
+{
+	current->thread.pgdir = mm->pgd;
+	get_mmu_context(mm);
+	set_context(mm->context, mm->pgd);
+}
+
+extern void mmu_context_init(void);
+
+# endif /* __KERNEL__ */
+#endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mmu.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mmu.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/mmu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/mmu.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,11 +11,104 @@
 #ifndef _ASM_MICROBLAZE_MMU_H
 #define _ASM_MICROBLAZE_MMU_H
 
-#ifndef __ASSEMBLY__
-typedef struct {
-	struct vm_list_struct	*vmlist;
-	unsigned long		end_brk;
-} mm_context_t;
-#endif /* __ASSEMBLY__ */
+# ifndef CONFIG_MMU
+#  include <asm-generic/mmu.h>
+# else /* CONFIG_MMU */
+#  ifdef __KERNEL__
+#   ifndef __ASSEMBLY__
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+/* Hardware Page Table Entry */
+typedef struct _PTE {
+	unsigned long    v:1;	/* Entry is valid */
+	unsigned long vsid:24;	/* Virtual segment identifier */
+	unsigned long    h:1;	/* Hash algorithm indicator */
+	unsigned long  api:6;	/* Abbreviated page index */
+	unsigned long  rpn:20;	/* Real (physical) page number */
+	unsigned long     :3;	/* Unused */
+	unsigned long    r:1;	/* Referenced */
+	unsigned long    c:1;	/* Changed */
+	unsigned long    w:1;	/* Write-thru cache mode */
+	unsigned long    i:1;	/* Cache inhibited */
+	unsigned long    m:1;	/* Memory coherence */
+	unsigned long    g:1;	/* Guarded */
+	unsigned long     :1;	/* Unused */
+	unsigned long   pp:2;	/* Page protection */
+} PTE;
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#  define PP_RWXX	0 /* Supervisor read/write, User none */
+#  define PP_RWRX	1 /* Supervisor read/write, User read */
+#  define PP_RWRW	2 /* Supervisor read/write, User read/write */
+#  define PP_RXRX	3 /* Supervisor read,       User read */
+
+/* Segment Register */
+typedef struct _SEGREG {
+	unsigned long    t:1;	/* Normal or I/O  type */
+	unsigned long   ks:1;	/* Supervisor 'key' (normally 0) */
+	unsigned long   kp:1;	/* User 'key' (normally 1) */
+	unsigned long    n:1;	/* No-execute */
+	unsigned long     :4;	/* Unused */
+	unsigned long vsid:24;	/* Virtual Segment Identifier */
+} SEGREG;
+
+extern void _tlbie(unsigned long va);	/* invalidate a TLB entry */
+extern void _tlbia(void);		/* invalidate all TLB entries */
+#   endif /* __ASSEMBLY__ */
 
+/*
+ * The MicroBlaze processor has a TLB architecture identical to PPC-40x. The
+ * instruction and data sides share a unified, 64-entry, semi-associative
+ * TLB which is maintained totally under software control. In addition, the
+ * instruction side has a hardware-managed, 2,4, or 8-entry, fully-associative
+ * TLB which serves as a first level to the shared TLB. These two TLBs are
+ * known as the UTLB and ITLB, respectively.
+ */
+
+#  define MICROBLAZE_TLB_SIZE 64
+
+/*
+ * TLB entries are defined by a "high" tag portion and a "low" data
+ * portion. The data portion is 32-bits.
+ *
+ * TLB entries are managed entirely under software control by reading,
+ * writing, and searching using the MTS and MFS instructions.
+ */
+
+#  define TLB_LO		1
+#  define TLB_HI		0
+#  define TLB_DATA		TLB_LO
+#  define TLB_TAG		TLB_HI
+
+/* Tag portion */
+#  define TLB_EPN_MASK		0xFFFFFC00 /* Effective Page Number */
+#  define TLB_PAGESZ_MASK	0x00000380
+#  define TLB_PAGESZ(x)		(((x) & 0x7) << 7)
+#  define PAGESZ_1K		0
+#  define PAGESZ_4K		1
+#  define PAGESZ_16K		2
+#  define PAGESZ_64K		3
+#  define PAGESZ_256K		4
+#  define PAGESZ_1M		5
+#  define PAGESZ_4M		6
+#  define PAGESZ_16M		7
+#  define TLB_VALID		0x00000040 /* Entry is valid */
+
+/* Data portion */
+#  define TLB_RPN_MASK		0xFFFFFC00 /* Real Page Number */
+#  define TLB_PERM_MASK		0x00000300
+#  define TLB_EX		0x00000200 /* Instruction execution allowed */
+#  define TLB_WR		0x00000100 /* Writes permitted */
+#  define TLB_ZSEL_MASK		0x000000F0
+#  define TLB_ZSEL(x)		(((x) & 0xF) << 4)
+#  define TLB_ATTR_MASK		0x0000000F
+#  define TLB_W			0x00000008 /* Caching is write-through */
+#  define TLB_I			0x00000004 /* Caching is inhibited */
+#  define TLB_M			0x00000002 /* Memory is coherent */
+#  define TLB_G			0x00000001 /* Memory is guarded from prefetch */
+
+#  endif /* __KERNEL__ */
+# endif /* CONFIG_MMU */
 #endif /* _ASM_MICROBLAZE_MMU_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/module.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/module.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/module.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/module.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,8 @@
 #ifndef _ASM_MICROBLAZE_MODULE_H
 #define _ASM_MICROBLAZE_MODULE_H
 
+#include <asm-generic/module.h>
+
 /* Microblaze Relocations */
 #define R_MICROBLAZE_NONE 0
 #define R_MICROBLAZE_32 1
@@ -24,14 +26,6 @@
 /* Keep this the last entry. */
 #define R_MICROBLAZE_NUM 11
 
-struct mod_arch_specific {
-	int foo;
-};
-
-#define Elf_Shdr	Elf32_Shdr
-#define Elf_Sym		Elf32_Sym
-#define Elf_Ehdr	Elf32_Ehdr
-
 typedef struct { volatile int counter; } module_t;
 
 #endif /* _ASM_MICROBLAZE_MODULE_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/msgbuf.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/msgbuf.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/msgbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/msgbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,31 +1 @@
-#ifndef _ASM_MICROBLAZE_MSGBUF_H
-#define _ASM_MICROBLAZE_MSGBUF_H
-
-/*
- * The msqid64_ds structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-	struct ipc64_perm msg_perm;
-	__kernel_time_t msg_stime; /* last msgsnd time */
-	unsigned long __unused1;
-	__kernel_time_t msg_rtime; /* last msgrcv time */
-	unsigned long __unused2;
-	__kernel_time_t msg_ctime; /* last change time */
-	unsigned long __unused3;
-	unsigned long msg_cbytes; /* current number of bytes on queue */
-	unsigned long msg_qnum; /* number of messages in queue */
-	unsigned long msg_qbytes; /* max number of bytes on queue */
-	__kernel_pid_t msg_lspid; /* pid of last msgsnd */
-	__kernel_pid_t msg_lrpid; /* last receive pid */
-	unsigned long __unused4;
-	unsigned long __unused5;
-};
-
-#endif /* _ASM_MICROBLAZE_MSGBUF_H */
+#include <asm-generic/msgbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/page.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,8 @@
 /*
- * Copyright (C) 2008 Michal Simek
- * Copyright (C) 2008 PetaLogix
+ * VM ops
+ *
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  * Changes for MMU support:
  *    Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
@@ -15,14 +17,15 @@
 
 #include <linux/pfn.h>
 #include <asm/setup.h>
+#include <linux/const.h>
+
+#ifdef __KERNEL__
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	(12)
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #define PAGE_UP(addr)	(((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1)))
@@ -35,6 +38,7 @@
 /* align addr on a size boundary - adjust address up if needed */
 #define _ALIGN(addr, size)	_ALIGN_UP(addr, size)
 
+#ifndef CONFIG_MMU
 /*
  * PAGE_OFFSET -- the first address of the first page of memory. When not
  * using MMU this corresponds to the first free page in physical memory (aligned
@@ -43,15 +47,44 @@
 extern unsigned int __page_offset;
 #define PAGE_OFFSET __page_offset
 
-#define copy_page(to, from)			memcpy((to), (from), PAGE_SIZE)
-#define get_user_page(vaddr)			__get_free_page(GFP_KERNEL)
-#define free_user_page(page, addr)		free_page(addr)
+#else /* CONFIG_MMU */
 
-#define clear_page(pgaddr)			memset((pgaddr), 0, PAGE_SIZE)
+/*
+ * PAGE_OFFSET -- the first address of the first page of memory. With MMU
+ * it is set to the kernel start address (aligned on a page boundary).
+ *
+ * CONFIG_KERNEL_START is defined in arch/microblaze/config.in and used
+ * in arch/microblaze/Makefile.
+ */
+#define PAGE_OFFSET	CONFIG_KERNEL_START
 
+/*
+ * MAP_NR -- given an address, calculate the index of the page struct which
+ * points to the address's page.
+ */
+#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
 
-#define clear_user_page(pgaddr, vaddr, page)	memset((pgaddr), 0, PAGE_SIZE)
-#define copy_user_page(vto, vfrom, vaddr, topg) \
+/*
+ * The basic type of a PTE - 32 bit physical addressing.
+ */
+typedef unsigned long pte_basic_t;
+#define PTE_SHIFT	(PAGE_SHIFT - 2)	/* 1024 ptes per page */
+#define PTE_FMT		"%.8lx"
+
+#endif /* CONFIG_MMU */
+
+#  ifndef CONFIG_MMU
+#  define copy_page(to, from)			memcpy((to), (from), PAGE_SIZE)
+#  define get_user_page(vaddr)			__get_free_page(GFP_KERNEL)
+#  define free_user_page(page, addr)		free_page(addr)
+#  else /* CONFIG_MMU */
+extern void copy_page(void *to, void *from);
+#  endif /* CONFIG_MMU */
+
+# define clear_page(pgaddr)			memset((pgaddr), 0, PAGE_SIZE)
+
+# define clear_user_page(pgaddr, vaddr, page)	memset((pgaddr), 0, PAGE_SIZE)
+# define copy_user_page(vto, vfrom, vaddr, topg) \
 			memcpy((vto), (vfrom), PAGE_SIZE)
 
 /*
@@ -60,21 +93,32 @@
 typedef struct page *pgtable_t;
 typedef struct { unsigned long	pte; }		pte_t;
 typedef struct { unsigned long	pgprot; }	pgprot_t;
+/* FIXME this can depend on linux kernel version */
+#   ifdef CONFIG_MMU
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+#   else /* CONFIG_MMU */
 typedef struct { unsigned long	ste[64]; }	pmd_t;
 typedef struct { pmd_t		pue[1]; }	pud_t;
 typedef struct { pud_t		pge[1]; }	pgd_t;
+#   endif /* CONFIG_MMU */
 
+# define pte_val(x)	((x).pte)
+# define pgprot_val(x)	((x).pgprot)
 
-#define pte_val(x)	((x).pte)
-#define pgprot_val(x)	((x).pgprot)
-#define pmd_val(x)	((x).ste[0])
-#define pud_val(x)	((x).pue[0])
-#define pgd_val(x)	((x).pge[0])
+#   ifdef CONFIG_MMU
+#   define pmd_val(x)      ((x).pmd)
+#   define pgd_val(x)      ((x).pgd)
+#   else  /* CONFIG_MMU */
+#   define pmd_val(x)	((x).ste[0])
+#   define pud_val(x)	((x).pue[0])
+#   define pgd_val(x)	((x).pge[0])
+#   endif  /* CONFIG_MMU */
 
-#define __pte(x)	((pte_t) { (x) })
-#define __pmd(x)	((pmd_t) { (x) })
-#define __pgd(x)	((pgd_t) { (x) })
-#define __pgprot(x)	((pgprot_t) { (x) })
+# define __pte(x)	((pte_t) { (x) })
+# define __pmd(x)	((pmd_t) { (x) })
+# define __pgd(x)	((pgd_t) { (x) })
+# define __pgprot(x)	((pgprot_t) { (x) })
 
 /**
  * Conversions for virtual address, physical address, pfn, and struct
@@ -94,47 +138,83 @@
 extern unsigned long min_low_pfn;
 extern unsigned long max_pfn;
 
-#define __pa(vaddr)		((unsigned long) (vaddr))
-#define __va(paddr)		((void *) (paddr))
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+extern unsigned long memory_size;
 
-#define phys_to_pfn(phys)	(PFN_DOWN(phys))
-#define pfn_to_phys(pfn)	(PFN_PHYS(pfn))
+extern int page_is_ram(unsigned long pfn);
 
-#define virt_to_pfn(vaddr)	(phys_to_pfn((__pa(vaddr))))
-#define pfn_to_virt(pfn)	__va(pfn_to_phys((pfn)))
+# define phys_to_pfn(phys)	(PFN_DOWN(phys))
+# define pfn_to_phys(pfn)	(PFN_PHYS(pfn))
 
-#define virt_to_page(vaddr)	(pfn_to_page(virt_to_pfn(vaddr)))
-#define page_to_virt(page)	(pfn_to_virt(page_to_pfn(page)))
+# define virt_to_pfn(vaddr)	(phys_to_pfn((__pa(vaddr))))
+# define pfn_to_virt(pfn)	__va(pfn_to_phys((pfn)))
 
-#define page_to_phys(page)	(pfn_to_phys(page_to_pfn(page)))
-#define page_to_bus(page)	(page_to_phys(page))
-#define phys_to_page(paddr)	(pfn_to_page(phys_to_pfn(paddr)))
+#  ifdef CONFIG_MMU
+#  define virt_to_page(kaddr) 	(mem_map +  MAP_NR(kaddr))
+#  else /* CONFIG_MMU */
+#  define virt_to_page(vaddr)	(pfn_to_page(virt_to_pfn(vaddr)))
+#  define page_to_virt(page)	(pfn_to_virt(page_to_pfn(page)))
+#  define page_to_phys(page)	(pfn_to_phys(page_to_pfn(page)))
+#  define page_to_bus(page)	(page_to_phys(page))
+#  define phys_to_page(paddr)	(pfn_to_page(phys_to_pfn(paddr)))
+#  endif /* CONFIG_MMU */
 
-extern unsigned int memory_start;
-extern unsigned int memory_end;
-extern unsigned int memory_size;
+#  ifndef CONFIG_MMU
+#  define pfn_valid(pfn)	((pfn) >= min_low_pfn && (pfn) <= max_mapnr)
+#  define ARCH_PFN_OFFSET	(PAGE_OFFSET >> PAGE_SHIFT)
+#  else /* CONFIG_MMU */
+#  define ARCH_PFN_OFFSET	(memory_start >> PAGE_SHIFT)
+#  define pfn_valid(pfn)	((pfn) < (max_mapnr + ARCH_PFN_OFFSET))
+#  define VALID_PAGE(page) 	((page - mem_map) < max_mapnr)
+#  endif /* CONFIG_MMU */
 
-#define pfn_valid(pfn)		((pfn) >= min_low_pfn && (pfn) < max_mapnr)
+# endif /* __ASSEMBLY__ */
 
-#define ARCH_PFN_OFFSET		(PAGE_OFFSET >> PAGE_SHIFT)
+#define	virt_addr_valid(vaddr)	(pfn_valid(virt_to_pfn(vaddr)))
 
-#else
-#define tophys(rd, rs)	(addik rd, rs, 0)
-#define tovirt(rd, rs)	(addik rd, rs, 0)
-#endif /* __ASSEMBLY__ */
 
-#define virt_addr_valid(vaddr)	(pfn_valid(virt_to_pfn(vaddr)))
+#  ifndef CONFIG_MMU
+#  define __pa(vaddr)	((unsigned long) (vaddr))
+#  define __va(paddr)	((void *) (paddr))
+#  else /* CONFIG_MMU */
+#  define __pa(x)	__virt_to_phys((unsigned long)(x))
+#  define __va(x)	((void *)__phys_to_virt((unsigned long)(x)))
+#  endif /* CONFIG_MMU */
 
-/* Convert between virtual and physical address for MMU.  */
-/* Handle MicroBlaze processor with virtual memory.  */
+
+/* Convert between virtual and physical address for MMU. */
+/* Handle MicroBlaze processor with virtual memory. */
+#ifndef CONFIG_MMU
 #define __virt_to_phys(addr)	addr
 #define __phys_to_virt(addr)	addr
+#define tophys(rd, rs)	addik rd, rs, 0
+#define tovirt(rd, rs)	addik rd, rs, 0
+#else
+#define __virt_to_phys(addr) \
+	((addr) + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START)
+#define __phys_to_virt(addr) \
+	((addr) + CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR)
+#define tophys(rd, rs) \
+	addik rd, rs, (CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START)
+#define tovirt(rd, rs) \
+	addik rd, rs, (CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR)
+#endif /* CONFIG_MMU */
 
 #define TOPHYS(addr)  __virt_to_phys(addr)
 
+#ifdef CONFIG_MMU
+#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
+#define WANT_PAGE_VIRTUAL 1 /* page alloc 2 relies on this */
+#endif
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#endif /* CONFIG_MMU */
+
 #endif /* __KERNEL__ */
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _ASM_MICROBLAZE_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/param.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/param.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/param.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/param.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,30 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_PARAM_H
-#define _ASM_MICROBLAZE_PARAM_H
-
-#ifdef __KERNEL__
-#define HZ		CONFIG_HZ	/* internal kernel timer frequency */
-#define USER_HZ		100		/* for user interfaces in "ticks" */
-#define CLOCKS_PER_SEC	(USER_HZ)	/* frequency at which times() counts */
-#endif /* __KERNEL__ */
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE	4096
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif /* _ASM_MICROBLAZE_PARAM_H */
+#include <asm-generic/param.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/parport.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/parport.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/parport.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/parport.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/parport.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/pci.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -1 +1 @@
-#include <linux/io.h>
+#include <asm-generic/pci.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,6 +11,195 @@
 #ifndef _ASM_MICROBLAZE_PGALLOC_H
 #define _ASM_MICROBLAZE_PGALLOC_H
 
+#ifdef CONFIG_MMU
+
+#include <linux/kernel.h>	/* For min/max macros */
+#include <linux/highmem.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+
+#define PGDIR_ORDER	0
+
+/*
+ * This is handled very differently on MicroBlaze since out page tables
+ * are all 0's and I want to be able to use these zero'd pages elsewhere
+ * as well - it gives us quite a speedup.
+ * -- Cort
+ */
+extern struct pgtable_cache_struct {
+	unsigned long *pgd_cache;
+	unsigned long *pte_cache;
+	unsigned long pgtable_cache_sz;
+} quicklists;
+
+#define pgd_quicklist		(quicklists.pgd_cache)
+#define pmd_quicklist		((unsigned long *)0)
+#define pte_quicklist		(quicklists.pte_cache)
+#define pgtable_cache_size	(quicklists.pgtable_cache_sz)
+
+extern unsigned long *zero_cache; /* head linked list of pre-zero'd pages */
+extern atomic_t zero_sz; /* # currently pre-zero'd pages */
+extern atomic_t zeropage_hits; /* # zero'd pages request that we've done */
+extern atomic_t zeropage_calls; /* # zero'd pages request that've been made */
+extern atomic_t zerototal; /* # pages zero'd over time */
+
+#define zero_quicklist		(zero_cache)
+#define zero_cache_sz	 	(zero_sz)
+#define zero_cache_calls	(zeropage_calls)
+#define zero_cache_hits		(zeropage_hits)
+#define zero_cache_total	(zerototal)
+
+/*
+ * return a pre-zero'd page from the list,
+ * return NULL if none available -- Cort
+ */
+extern unsigned long get_zero_page_fast(void);
+
+extern void __bad_pte(pmd_t *pmd);
+
+extern inline pgd_t *get_pgd_slow(void)
+{
+	pgd_t *ret;
+
+	ret = (pgd_t *)__get_free_pages(GFP_KERNEL, PGDIR_ORDER);
+	if (ret != NULL)
+		clear_page(ret);
+	return ret;
+}
+
+extern inline pgd_t *get_pgd_fast(void)
+{
+	unsigned long *ret;
+
+	ret = pgd_quicklist;
+	if (ret != NULL) {
+		pgd_quicklist = (unsigned long *)(*ret);
+		ret[0] = 0;
+		pgtable_cache_size--;
+	} else
+		ret = (unsigned long *)get_pgd_slow();
+	return (pgd_t *)ret;
+}
+
+extern inline void free_pgd_fast(pgd_t *pgd)
+{
+	*(unsigned long **)pgd = pgd_quicklist;
+	pgd_quicklist = (unsigned long *) pgd;
+	pgtable_cache_size++;
+}
+
+extern inline void free_pgd_slow(pgd_t *pgd)
+{
+	free_page((unsigned long)pgd);
+}
+
+#define pgd_free(mm, pgd)        free_pgd_fast(pgd)
+#define pgd_alloc(mm)		get_pgd_fast()
+
+#define pmd_pgtable(pmd)	pmd_page(pmd)
+
+/*
+ * We don't have any real pmd's, and this code never triggers because
+ * the pgd will always be present..
+ */
+#define pmd_alloc_one_fast(mm, address)	({ BUG(); ((pmd_t *)1); })
+#define pmd_alloc_one(mm, address)	({ BUG(); ((pmd_t *)2); })
+/* FIXME two definition - look below */
+#define pmd_free(mm, x)			do { } while (0)
+#define pgd_populate(mm, pmd, pte)	BUG()
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+		unsigned long address)
+{
+	pte_t *pte;
+	extern int mem_init_done;
+	extern void *early_get_page(void);
+	if (mem_init_done) {
+		pte = (pte_t *)__get_free_page(GFP_KERNEL |
+					__GFP_REPEAT | __GFP_ZERO);
+	} else {
+		pte = (pte_t *)early_get_page();
+		if (pte)
+			clear_page(pte);
+	}
+	return pte;
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+		unsigned long address)
+{
+	struct page *ptepage;
+
+#ifdef CONFIG_HIGHPTE
+	int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+#else
+	int flags = GFP_KERNEL | __GFP_REPEAT;
+#endif
+
+	ptepage = alloc_pages(flags, 0);
+	if (ptepage)
+		clear_highpage(ptepage);
+	return ptepage;
+}
+
+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm,
+		unsigned long address)
+{
+	unsigned long *ret;
+
+	ret = pte_quicklist;
+	if (ret != NULL) {
+		pte_quicklist = (unsigned long *)(*ret);
+		ret[0] = 0;
+		pgtable_cache_size--;
+	}
+	return (pte_t *)ret;
+}
+
+extern inline void pte_free_fast(pte_t *pte)
+{
+	*(unsigned long **)pte = pte_quicklist;
+	pte_quicklist = (unsigned long *) pte;
+	pgtable_cache_size++;
+}
+
+extern inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+extern inline void pte_free_slow(struct page *ptepage)
+{
+	__free_page(ptepage);
+}
+
+extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
+{
+	__free_page(ptepage);
+}
+
+#define __pte_free_tlb(tlb, pte, addr)	pte_free((tlb)->mm, (pte))
+
+#define pmd_populate(mm, pmd, pte)	(pmd_val(*(pmd)) = page_address(pte))
+
+#define pmd_populate_kernel(mm, pmd, pte) \
+		(pmd_val(*(pmd)) = (unsigned long) (pte))
+
+/*
+ * We don't have any real pmd's, and this code never triggers because
+ * the pgd will always be present..
+ */
+#define pmd_alloc_one(mm, address)	({ BUG(); ((pmd_t *)2); })
+/*#define pmd_free(mm, x)			do { } while (0)*/
+#define __pmd_free_tlb(tlb, x, addr)	do { } while (0)
+#define pgd_populate(mm, pmd, pte)	BUG()
+
+extern int do_check_pgt_cache(int, int);
+
+#endif /* CONFIG_MMU */
+
 #define check_pgt_cache()	do {} while (0)
 
 #endif /* _ASM_MICROBLAZE_PGALLOC_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -14,6 +16,8 @@
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
+#ifndef CONFIG_MMU
+
 #define pgd_present(pgd)	(1) /* pages are always present on non MMU */
 #define pgd_none(pgd)		(0)
 #define pgd_bad(pgd)		(0)
@@ -27,6 +31,8 @@
 #define PAGE_READONLY		__pgprot(0) /* these mean nothing to non MMU */
 #define PAGE_KERNEL		__pgprot(0) /* these mean nothing to non MMU */
 
+#define pgprot_noncached(x)	(x)
+
 #define __swp_type(x)		(0)
 #define __swp_offset(x)		(0)
 #define __swp_entry(typ, off)	((swp_entry_t) { ((typ) | ((off) << 7)) })
@@ -45,6 +51,538 @@
 
 #define arch_enter_lazy_cpu_mode()	do {} while (0)
 
+#else /* CONFIG_MMU */
+
+#include <asm-generic/4level-fixup.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+#include <linux/threads.h>
+#include <asm/processor.h>		/* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+
+#define FIRST_USER_ADDRESS	0
+
+extern unsigned long va_to_phys(unsigned long address);
+extern pte_t *va_to_pte(unsigned long address);
+extern unsigned long ioremap_bot, ioremap_base;
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+
+static inline int pte_special(pte_t pte)	{ return 0; }
+
+static inline pte_t pte_mkspecial(pte_t pte)	{ return pte; }
+
+/* Start and end of the vmalloc area. */
+/* Make sure to map the vmalloc area above the pinned kernel memory area
+   of 32Mb.  */
+#define VMALLOC_START	(CONFIG_KERNEL_START + \
+				max(32 * 1024 * 1024UL, memory_size))
+#define VMALLOC_END	ioremap_bot
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The MicroBlaze MMU is identical to the PPC-40x MMU, and uses a hash
+ * table containing PTEs, together with a set of 16 segment registers, to
+ * define the virtual to physical address mapping.
+ *
+ * We use the hash table as an extended TLB, i.e. a cache of currently
+ * active mappings.  We maintain a two-level page table tree, much
+ * like that used by the i386, for the sake of the Linux memory
+ * management code.  Low-level assembler code in hashtable.S
+ * (procedure hash_page) is responsible for extracting ptes from the
+ * tree and putting them into the hash table when necessary, and
+ * updating the accessed and modified bits in the page table tree.
+ */
+
+/*
+ * The MicroBlaze processor has a TLB architecture identical to PPC-40x. The
+ * instruction and data sides share a unified, 64-entry, semi-associative
+ * TLB which is maintained totally under software control. In addition, the
+ * instruction side has a hardware-managed, 2,4, or 8-entry, fully-associative
+ * TLB which serves as a first level to the shared TLB. These two TLBs are
+ * known as the UTLB and ITLB, respectively (see "mmu.h" for definitions).
+ */
+
+/*
+ * The normal case is that PTEs are 32-bits and we have a 1-page
+ * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages.  -- paulus
+ *
+ */
+
+/* PMD_SHIFT determines the size of the area mapped by the PTE pages */
+#define PMD_SHIFT	(PAGE_SHIFT + PTE_SHIFT)
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a top-level page table entry can map */
+#define PGDIR_SHIFT	PMD_SHIFT
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: our page-table tree is two-level, so
+ * we don't really have any PMD directory.
+ */
+#define PTRS_PER_PTE	(1 << PTE_SHIFT)
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PGD	(1 << (32 - PGDIR_SHIFT))
+
+#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
+#define FIRST_USER_PGD_NR	0
+
+#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+
+#define pte_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pte "PTE_FMT".\n", \
+		__FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pmd %08lx.\n", \
+		__FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", \
+		__FILE__, __LINE__, pgd_val(e))
+
+/*
+ * Bits in a linux-style PTE.  These match the bits in the
+ * (hardware-defined) PTE as closely as possible.
+ */
+
+/* There are several potential gotchas here.  The hardware TLBLO
+ * field looks like this:
+ *
+ * 0  1  2  3  4  ... 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ * RPN.....................  0  0 EX WR ZSEL.......  W  I  M  G
+ *
+ * Where possible we make the Linux PTE bits match up with this
+ *
+ * - bits 20 and 21 must be cleared, because we use 4k pages (4xx can
+ * support down to 1k pages), this is done in the TLBMiss exception
+ * handler.
+ * - We use only zones 0 (for kernel pages) and 1 (for user pages)
+ * of the 16 available.  Bit 24-26 of the TLB are cleared in the TLB
+ * miss handler.  Bit 27 is PAGE_USER, thus selecting the correct
+ * zone.
+ * - PRESENT *must* be in the bottom two bits because swap cache
+ * entries use the top 30 bits.  Because 4xx doesn't support SMP
+ * anyway, M is irrelevant so we borrow it for PAGE_PRESENT.  Bit 30
+ * is cleared in the TLB miss handler before the TLB entry is loaded.
+ * - All other bits of the PTE are loaded into TLBLO without
+ *  * modification, leaving us only the bits 20, 21, 24, 25, 26, 30 for
+ * software PTE bits.  We actually use use bits 21, 24, 25, and
+ * 30 respectively for the software bits: ACCESSED, DIRTY, RW, and
+ * PRESENT.
+ */
+
+/* Definitions for MicroBlaze. */
+#define	_PAGE_GUARDED	0x001	/* G: page is guarded from prefetch */
+#define _PAGE_FILE	0x001	/* when !present: nonlinear file mapping */
+#define _PAGE_PRESENT	0x002	/* software: PTE contains a translation */
+#define	_PAGE_NO_CACHE	0x004	/* I: caching is inhibited */
+#define	_PAGE_WRITETHRU	0x008	/* W: caching is write-through */
+#define	_PAGE_USER	0x010	/* matches one of the zone permission bits */
+#define	_PAGE_RW	0x040	/* software: Writes permitted */
+#define	_PAGE_DIRTY	0x080	/* software: dirty page */
+#define _PAGE_HWWRITE	0x100	/* hardware: Dirty & RW, set in exception */
+#define _PAGE_HWEXEC	0x200	/* hardware: EX permission */
+#define _PAGE_ACCESSED	0x400	/* software: R: page referenced */
+#define _PMD_PRESENT	PAGE_MASK
+
+/*
+ * Some bits are unused...
+ */
+#ifndef _PAGE_HASHPTE
+#define _PAGE_HASHPTE	0
+#endif
+#ifndef _PTE_NONE_MASK
+#define _PTE_NONE_MASK	0
+#endif
+#ifndef _PAGE_SHARED
+#define _PAGE_SHARED	0
+#endif
+#ifndef _PAGE_HWWRITE
+#define _PAGE_HWWRITE	0
+#endif
+#ifndef _PAGE_HWEXEC
+#define _PAGE_HWEXEC	0
+#endif
+#ifndef _PAGE_EXEC
+#define _PAGE_EXEC	0
+#endif
+
+#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+/*
+ * Note: the _PAGE_COHERENT bit automatically gets set in the hardware
+ * PTE if CONFIG_SMP is defined (hash_page does this); there is no need
+ * to have it in the Linux PTE, and in fact the bit could be reused for
+ * another purpose.  -- paulus.
+ */
+#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define _PAGE_WRENABLE	(_PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE)
+
+#define _PAGE_KERNEL \
+	(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED | _PAGE_HWEXEC)
+
+#define _PAGE_IO	(_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED)
+
+#define PAGE_NONE	__pgprot(_PAGE_BASE)
+#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
+#define PAGE_SHARED_X \
+		__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
+#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+
+#define PAGE_KERNEL	__pgprot(_PAGE_KERNEL)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_SHARED)
+#define PAGE_KERNEL_CI	__pgprot(_PAGE_IO)
+
+/*
+ * We consider execute permission the same as read.
+ * Also, write permissions imply read permissions.
+ */
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY_X
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY_X
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY_X
+#define __P110	PAGE_COPY
+#define __P111	PAGE_COPY_X
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY_X
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED_X
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY_X
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED_X
+
+#ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[1024];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+#endif /* __ASSEMBLY__ */
+
+#define pte_none(pte)		((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
+#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
+#define pte_clear(mm, addr, ptep) \
+	do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0)
+
+#define pmd_none(pmd)		(!pmd_val(pmd))
+#define	pmd_bad(pmd)		((pmd_val(pmd) & _PMD_PRESENT) == 0)
+#define	pmd_present(pmd)	((pmd_val(pmd) & _PMD_PRESENT) != 0)
+#define	pmd_clear(pmdp)		do { pmd_val(*(pmdp)) = 0; } while (0)
+
+#define pte_page(x)		(mem_map + (unsigned long) \
+				((pte_val(x) - memory_start) >> PAGE_SHIFT))
+#define PFN_SHIFT_OFFSET	(PAGE_SHIFT)
+
+#define pte_pfn(x)		(pte_val(x) >> PFN_SHIFT_OFFSET)
+
+#define pfn_pte(pfn, prot) \
+	__pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) | pgprot_val(prot))
+
+#ifndef __ASSEMBLY__
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+static inline int pgd_none(pgd_t pgd)		{ return 0; }
+static inline int pgd_bad(pgd_t pgd)		{ return 0; }
+static inline int pgd_present(pgd_t pgd)	{ return 1; }
+#define pgd_clear(xp)				do { } while (0)
+#define pgd_page(pgd) \
+	((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
+static inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)  { return pte_val(pte) & _PAGE_FILE; }
+
+static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
+static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
+
+static inline pte_t pte_rdprotect(pte_t pte) \
+		{ pte_val(pte) &= ~_PAGE_USER; return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) \
+	{ pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
+static inline pte_t pte_exprotect(pte_t pte) \
+	{ pte_val(pte) &= ~_PAGE_EXEC; return pte; }
+static inline pte_t pte_mkclean(pte_t pte) \
+	{ pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
+static inline pte_t pte_mkold(pte_t pte) \
+	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+
+static inline pte_t pte_mkread(pte_t pte) \
+	{ pte_val(pte) |= _PAGE_USER; return pte; }
+static inline pte_t pte_mkexec(pte_t pte) \
+	{ pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) \
+	{ pte_val(pte) |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) \
+	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) \
+	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+static inline pte_t mk_pte_phys(phys_addr_t physpage, pgprot_t pgprot)
+{
+	pte_t pte;
+	pte_val(pte) = physpage | pgprot_val(pgprot);
+	return pte;
+}
+
+#define mk_pte(page, pgprot) \
+({									   \
+	pte_t pte;							   \
+	pte_val(pte) = (((page - mem_map) << PAGE_SHIFT) + memory_start) |  \
+			pgprot_val(pgprot);				   \
+	pte;								   \
+})
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+	return pte;
+}
+
+/*
+ * Atomic PTE updates.
+ *
+ * pte_update clears and sets bit atomically, and returns
+ * the old pte value.
+ * The ((unsigned long)(p+1) - 4) hack is to get to the least-significant
+ * 32 bits of the PTE regardless of whether PTEs are 32 or 64 bits.
+ */
+static inline unsigned long pte_update(pte_t *p, unsigned long clr,
+				unsigned long set)
+{
+	unsigned long old, tmp, msr;
+
+	__asm__ __volatile__("\
+	msrclr	%2, 0x2\n\
+	nop\n\
+	lw	%0, %4, r0\n\
+	andn	%1, %0, %5\n\
+	or	%1, %1, %6\n\
+	sw	%1, %4, r0\n\
+	mts     rmsr, %2\n\
+	nop"
+	: "=&r" (old), "=&r" (tmp), "=&r" (msr), "=m" (*p)
+	: "r" ((unsigned long)(p+1) - 4), "r" (clr), "r" (set), "m" (*p)
+	: "cc");
+
+	return old;
+}
+
+/*
+ * set_pte stores a linux PTE into the linux page table.
+ */
+static inline void set_pte(struct mm_struct *mm, unsigned long addr,
+		pte_t *ptep, pte_t pte)
+{
+	*ptep = pte;
+}
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+		pte_t *ptep, pte_t pte)
+{
+	*ptep = pte;
+}
+
+static inline int ptep_test_and_clear_young(struct mm_struct *mm,
+		unsigned long addr, pte_t *ptep)
+{
+	return (pte_update(ptep, _PAGE_ACCESSED, 0) & _PAGE_ACCESSED) != 0;
+}
+
+static inline int ptep_test_and_clear_dirty(struct mm_struct *mm,
+		unsigned long addr, pte_t *ptep)
+{
+	return (pte_update(ptep, \
+		(_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
+}
+
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
+		unsigned long addr, pte_t *ptep)
+{
+	return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0));
+}
+
+/*static inline void ptep_set_wrprotect(struct mm_struct *mm,
+		unsigned long addr, pte_t *ptep)
+{
+	pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), 0);
+}*/
+
+static inline void ptep_mkdirty(struct mm_struct *mm,
+		unsigned long addr, pte_t *ptep)
+{
+	pte_update(ptep, 0, _PAGE_DIRTY);
+}
+
+/*#define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)*/
+
+/* Convert pmd entry to page */
+/* our pmd entry is an effective address of pte table*/
+/* returns effective address of the pmd entry*/
+#define pmd_page_kernel(pmd)	((unsigned long) (pmd_val(pmd) & PAGE_MASK))
+
+/* returns struct *page of the pmd entry*/
+#define pmd_page(pmd)	(pfn_to_page(__pa(pmd_val(pmd)) >> PAGE_SHIFT))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(address)	 ((address) >> PGDIR_SHIFT)
+#define pgd_offset(mm, address)	 ((mm)->pgd + pgd_index(address))
+
+/* Find an entry in the second-level page table.. */
+static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
+{
+	return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */
+#define pte_index(address)		\
+	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, addr)	\
+	((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr))
+#define pte_offset_map(dir, addr)		\
+	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
+#define pte_offset_map_nested(dir, addr)	\
+	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
+
+#define pte_unmap(pte)		kunmap_atomic(pte, KM_PTE0)
+#define pte_unmap_nested(pte)	kunmap_atomic(pte, KM_PTE1)
+
+/* Encode and decode a nonlinear file mapping entry */
+#define PTE_FILE_MAX_BITS	29
+#define pte_to_pgoff(pte)	(pte_val(pte) >> 3)
+#define pgoff_to_pte(off)	((pte_t) { ((off) << 3) | _PAGE_FILE })
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/*
+ * When flushing the tlb entry for a page, we also need to flush the hash
+ * table entry.  flush_hash_page is assembler (for speed) in hashtable.S.
+ */
+extern int flush_hash_page(unsigned context, unsigned long va, pte_t *ptep);
+
+/* Add an HPTE to the hash table */
+extern void add_hash_page(unsigned context, unsigned long va, pte_t *ptep);
+
+/*
+ * Encode and decode a swap entry.
+ * Note that the bits we use in a PTE for representing a swap entry
+ * must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit
+ * (if used).  -- paulus
+ */
+#define __swp_type(entry)		((entry).val & 0x3f)
+#define __swp_offset(entry)	((entry).val >> 6)
+#define __swp_entry(type, offset) \
+		((swp_entry_t) { (type) | ((offset) << 6) })
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) >> 2 })
+#define __swp_entry_to_pte(x)	((pte_t) { (x).val << 2 })
+
+
+/* CONFIG_APUS */
+/* For virtual address to physical address conversion */
+extern void cache_clear(__u32 addr, int length);
+extern void cache_push(__u32 addr, int length);
+extern int mm_end_of_chunk(unsigned long addr, int len);
+extern unsigned long iopa(unsigned long addr);
+/* extern unsigned long mm_ptov(unsigned long addr) \
+	__attribute__ ((const)); TBD */
+
+/* Values for nocacheflag and cmode */
+/* These are not used by the APUS kernel_map, but prevents
+ * compilation errors.
+ */
+#define	IOMAP_FULL_CACHING	0
+#define	IOMAP_NOCACHE_SER	1
+#define	IOMAP_NOCACHE_NONSER	2
+#define	IOMAP_NO_COPYBACK	3
+
+/*
+ * Map some physical address range into the kernel address space.
+ */
+extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
+				int nocacheflag, unsigned long *memavailp);
+
+/*
+ * Set cache mode of (kernel space) address range.
+ */
+extern void kernel_set_cachemode(unsigned long address, unsigned long size,
+				unsigned int cmode);
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr)	(1)
+
+#define io_remap_page_range remap_page_range
+
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init()	do { } while (0)
+
+void do_page_fault(struct pt_regs *regs, unsigned long address,
+		   unsigned long error_code);
+
+void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
+			     unsigned int size, int flags);
+
+void __init adjust_total_lowmem(void);
+void mapin_ram(void);
+int map_page(unsigned long va, phys_addr_t pa, int flags);
+
+extern int mem_init_done;
+extern unsigned long ioremap_base;
+extern unsigned long ioremap_bot;
+
+asmlinkage void __init mmu_init(void);
+
+void __init *early_get_page(void);
+
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
+void consistent_free(void *vaddr);
+void consistent_sync(void *vaddr, size_t size, int direction);
+void consistent_sync_page(struct page *page, unsigned long offset,
+	size_t size, int direction);
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif /* CONFIG_MMU */
+
 #ifndef __ASSEMBLY__
 #include <asm-generic/pgtable.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/posix_types.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/posix_types.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/posix_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/posix_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,73 +1,9 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
 #ifndef _ASM_MICROBLAZE_POSIX_TYPES_H
 #define _ASM_MICROBLAZE_POSIX_TYPES_H
 
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long	__kernel_ino_t;
-typedef unsigned int	__kernel_mode_t;
-typedef unsigned int	__kernel_nlink_t;
-typedef long		__kernel_off_t;
-typedef int		__kernel_pid_t;
-typedef unsigned int	__kernel_ipc_pid_t;
-typedef unsigned int	__kernel_uid_t;
-typedef unsigned int	__kernel_gid_t;
-typedef unsigned long	__kernel_size_t;
-typedef long		__kernel_ssize_t;
-typedef int		__kernel_ptrdiff_t;
-typedef long		__kernel_time_t;
-typedef long		__kernel_suseconds_t;
-typedef long		__kernel_clock_t;
-typedef int		__kernel_timer_t;
-typedef int		__kernel_clockid_t;
-typedef int		__kernel_daddr_t;
-typedef char 		*__kernel_caddr_t;
-typedef unsigned short	__kernel_uid16_t;
-typedef unsigned short	__kernel_gid16_t;
-typedef unsigned int	__kernel_uid32_t;
-typedef unsigned int	__kernel_gid32_t;
-
-typedef unsigned int	__kernel_old_uid_t;
-typedef unsigned int	__kernel_old_gid_t;
-typedef unsigned int	__kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long	__kernel_loff_t;
-#endif
-
-typedef struct {
-#if defined(__KERNEL__) || defined(__USE_ALL)
-	int	val[2];
-#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
-	int	__val[2];
-#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-
-#undef	__FD_SET
-#define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-
-#undef	__FD_CLR
-#define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-
-#undef	__FD_ISSET
-#define	__FD_ISSET(d, set)	(!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
-
-#undef	__FD_ZERO
-#define __FD_ZERO(fdsetp) (memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+typedef unsigned short	__kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
 
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#include <asm-generic/posix_types.h>
 
 #endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/processor.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2008 Michal Simek
- * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -26,14 +26,15 @@
 # define cpu_sleep()		do {} while (0)
 # define prepare_to_copy(tsk)	do {} while (0)
 
-# endif /* __ASSEMBLY__ */
-
 #define task_pt_regs(tsk) \
 		(((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
 
 /* Do necessary setup to start up a newly executed thread. */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);
 
+# endif /* __ASSEMBLY__ */
+
+# ifndef CONFIG_MMU
 /*
  * User space process size: memory size
  *
@@ -85,4 +86,90 @@
 # define KSTK_EIP(tsk)	(0)
 # define KSTK_ESP(tsk)	(0)
 
+# else /* CONFIG_MMU */
+
+/*
+ * This is used to define STACK_TOP, and with MMU it must be below
+ * kernel base to select the correct PGD when handling MMU exceptions.
+ */
+# define TASK_SIZE	(CONFIG_KERNEL_START)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+# define TASK_UNMAPPED_BASE	(TASK_SIZE / 8 * 3)
+
+# define THREAD_KSP	0
+
+#  ifndef __ASSEMBLY__
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#  define current_text_addr()	({ __label__ _l; _l: &&_l; })
+
+/* If you change this, you must change the associated assembly-languages
+ * constants defined below, THREAD_*.
+ */
+struct thread_struct {
+	/* kernel stack pointer (must be first field in structure) */
+	unsigned long	ksp;
+	unsigned long	ksp_limit;	/* if ksp <= ksp_limit stack overflow */
+	void		*pgdir;		/* root of page-table tree */
+	struct pt_regs	*regs;		/* Pointer to saved register state */
+};
+
+#  define INIT_THREAD { \
+	.ksp   = sizeof init_stack + (unsigned long)init_stack, \
+	.pgdir = swapper_pg_dir, \
+}
+
+/* Do necessary setup to start up a newly executed thread.  */
+void start_thread(struct pt_regs *regs,
+		unsigned long pc, unsigned long usp);
+
+/* Free all resources held by a thread. */
+extern inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+/* Free current thread data structures etc.  */
+static inline void exit_thread(void)
+{
+}
+
+/* Return saved (kernel) PC of a blocked thread.  */
+#  define thread_saved_pc(tsk)	\
+	((tsk)->thread.regs ? (tsk)->thread.regs->r15 : 0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+/* The size allocated for kernel stacks. This _must_ be a power of two! */
+# define KERNEL_STACK_SIZE	0x2000
+
+/* Return some info about the user process TASK.  */
+#  define task_tos(task)	((unsigned long)(task) + KERNEL_STACK_SIZE)
+#  define task_regs(task) ((struct pt_regs *)task_tos(task) - 1)
+
+#  define task_pt_regs_plus_args(tsk) \
+	(((void *)task_pt_regs(tsk)) - STATE_SAVE_ARG_SPACE)
+
+#  define task_sp(task)	(task_regs(task)->r1)
+#  define task_pc(task)	(task_regs(task)->pc)
+/* Grotty old names for some.  */
+#  define KSTK_EIP(task)	(task_pc(task))
+#  define KSTK_ESP(task)	(task_sp(task))
+
+/* FIXME */
+#  define deactivate_mm(tsk, mm)	do { } while (0)
+
+#  define STACK_TOP	TASK_SIZE
+#  define STACK_TOP_MAX	STACK_TOP
+
+#  endif /* __ASSEMBLY__ */
+# endif /* CONFIG_MMU */
 #endif /* _ASM_MICROBLAZE_PROCESSOR_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/prom.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/prom.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/prom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/prom.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,18 @@
 #define _ASM_MICROBLAZE_PROM_H
 #ifdef __KERNEL__
 
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER		0xd00dfeed /* marker */
+#define OF_DT_BEGIN_NODE	0x1 /* Start of node, full name */
+#define OF_DT_END_NODE		0x2 /* End node */
+#define OF_DT_PROP		0x3 /* Property: name off, size, content */
+#define OF_DT_NOP		0x4 /* nop */
+#define OF_DT_END		0x9
+
+#define OF_DT_VERSION		0x10
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/platform_device.h>
@@ -29,16 +41,6 @@
 #define of_prop_cmp(s1, s2)		strcmp((s1), (s2))
 #define of_node_cmp(s1, s2)		strcasecmp((s1), (s2))
 
-/* Definitions used by the flattened device tree */
-#define OF_DT_HEADER		0xd00dfeed /* marker */
-#define OF_DT_BEGIN_NODE	0x1 /* Start of node, full name */
-#define OF_DT_END_NODE		0x2 /* End node */
-#define OF_DT_PROP		0x3 /* Property: name off, size, content */
-#define OF_DT_NOP		0x4 /* nop */
-#define OF_DT_END		0x9
-
-#define OF_DT_VERSION		0x10
-
 /*
  * This is what gets passed to the kernel by prom_init or kexec
  *
@@ -309,5 +311,6 @@
  */
 #include <linux/of.h>
 
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_PROM_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ptrace.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ptrace.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ptrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ptrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,6 @@
 #define _ASM_MICROBLAZE_PTRACE_H
 
 #ifndef __ASSEMBLY__
-#include <linux/types.h>
 
 typedef unsigned long microblaze_reg_t;
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/registers.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/registers.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/registers.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/registers.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2008 Michal Simek
- * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -30,4 +30,21 @@
 #define FSR_UF		(1<<1) /* Underflow */
 #define FSR_DO		(1<<0) /* Denormalized operand error */
 
+# ifdef CONFIG_MMU
+/* Machine State Register (MSR) Fields */
+# define MSR_UM		(1<<11) /* User Mode */
+# define MSR_UMS	(1<<12) /* User Mode Save */
+# define MSR_VM		(1<<13) /* Virtual Mode */
+# define MSR_VMS	(1<<14) /* Virtual Mode Save */
+
+# define MSR_KERNEL	(MSR_EE | MSR_VM)
+/* # define MSR_USER	(MSR_KERNEL | MSR_UM | MSR_IE) */
+# define MSR_KERNEL_VMS	(MSR_EE | MSR_VMS)
+/* # define MSR_USER_VMS	(MSR_KERNEL_VMS | MSR_UMS | MSR_IE) */
+
+/* Exception State Register (ESR) Fields */
+# define	  ESR_DIZ	(1<<11) /* Zone Protection */
+# define	  ESR_S		(1<<10) /* Store instruction */
+
+# endif /* CONFIG_MMU */
 #endif /* _ASM_MICROBLAZE_REGISTERS_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/scatterlist.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/scatterlist.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/scatterlist.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/scatterlist.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,28 +1 @@
-/*
- * Copyright (C) 2008 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_SCATTERLIST_H
-#define _ASM_MICROBLAZE_SCATTERLIST_H
-
-struct scatterlist {
-#ifdef CONFIG_DEBUG_SG
-	unsigned long	sg_magic;
-#endif
-	unsigned long	page_link;
-	dma_addr_t	dma_address;
-	unsigned int	offset;
-	unsigned int	length;
-};
-
-#define sg_dma_address(sg)      ((sg)->dma_address)
-#define sg_dma_len(sg)          ((sg)->length)
-
-#define ISA_DMA_THRESHOLD (~0UL)
-
-#endif /* _ASM_MICROBLAZE_SCATTERLIST_H */
+#include <asm-generic/scatterlist.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/sections.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/sections.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/sections.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/sections.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -14,6 +16,7 @@
 # ifndef __ASSEMBLY__
 extern char _ssbss[], _esbss[];
 extern unsigned long __ivt_start[], __ivt_end[];
+extern char _etext[], _stext[];
 
 #  ifdef CONFIG_MTD_UCLINUX
 extern char *_ebss;
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/segment.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/segment.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/segment.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/segment.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2008 Michal Simek
- * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -11,7 +11,7 @@
 #ifndef _ASM_MICROBLAZE_SEGMENT_H
 #define _ASM_MICROBLAZE_SEGMENT_H
 
-#ifndef __ASSEMBLY__
+# ifndef __ASSEMBLY__
 
 typedef struct {
 	unsigned long seg;
@@ -29,15 +29,21 @@
  *
  * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal.
  */
-#  define KERNEL_DS	((mm_segment_t){0})
+# define MAKE_MM_SEG(s)       ((mm_segment_t) { (s) })
+
+#  ifndef CONFIG_MMU
+#  define KERNEL_DS	MAKE_MM_SEG(0)
 #  define USER_DS	KERNEL_DS
+#  else
+#  define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+#  define USER_DS	MAKE_MM_SEG(TASK_SIZE - 1)
+#  endif
 
 # define get_ds()	(KERNEL_DS)
 # define get_fs()	(current_thread_info()->addr_limit)
-# define set_fs(x) \
-		do { current_thread_info()->addr_limit = (x); } while (0)
+# define set_fs(val)	(current_thread_info()->addr_limit = (val))
 
-# define segment_eq(a, b)		((a).seg == (b).seg)
+# define segment_eq(a, b)	((a).seg == (b).seg)
 
 # endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_SEGMENT_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/sembuf.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/sembuf.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/sembuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/sembuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,34 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_SEMBUF_H
-#define _ASM_MICROBLAZE_SEMBUF_H
-
-/*
- * The semid64_ds structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-	struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
-	__kernel_time_t	sem_otime; /* last semop time */
-	unsigned long	__unused1;
-	__kernel_time_t	sem_ctime; /* last change time */
-	unsigned long	__unused2;
-	unsigned long	sem_nsems; /* no. of semaphores in array */
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-
-#endif /* _ASM_MICROBLAZE_SEMBUF_H */
+#include <asm-generic/sembuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/serial.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/serial.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/serial.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/serial.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1 @@
-/*
- * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_SERIAL_H
-#define _ASM_MICROBLAZE_SERIAL_H
-
-# define BASE_BAUD (1843200 / 16)
-
-#endif /* _ASM_MICROBLAZE_SERIAL_H */
+#include <asm-generic/serial.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/setup.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/setup.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/setup.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/setup.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -18,7 +19,6 @@
 extern unsigned int boot_cpuid; /* move to smp.h */
 
 extern char cmd_line[COMMAND_LINE_SIZE];
-#  endif/* __KERNEL__ */
 
 void early_printk(const char *fmt, ...);
 
@@ -30,6 +30,11 @@
 
 unsigned long long sched_clock(void);
 
+#   ifdef CONFIG_MMU
+extern void mmu_reset(void);
+extern void early_console_reg_tlb_alloc(unsigned int addr);
+#   endif /* CONFIG_MMU */
+
 void time_init(void);
 void init_IRQ(void);
 void machine_early_init(const char *cmdline, unsigned int ram,
@@ -40,5 +45,6 @@
 void machine_halt(void);
 void machine_power_off(void);
 
+#  endif/* __KERNEL__ */
 # endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_SETUP_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/shmbuf.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/shmbuf.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/shmbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/shmbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,42 +1 @@
-#ifndef _ASM_MICROBLAZE_SHMBUF_H
-#define _ASM_MICROBLAZE_SHMBUF_H
-
-/*
- * The shmid64_ds structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-	struct ipc64_perm	shm_perm; /* operation perms */
-	size_t			shm_segsz; /* size of segment (bytes) */
-	__kernel_time_t		shm_atime; /* last attach time */
-	unsigned long		__unused1;
-	__kernel_time_t		shm_dtime; /* last detach time */
-	unsigned long		__unused2;
-	__kernel_time_t		shm_ctime; /* last change time */
-	unsigned long		__unused3;
-	__kernel_pid_t		shm_cpid; /* pid of creator */
-	__kernel_pid_t		shm_lpid; /* pid of last operator */
-	unsigned long		shm_nattch; /* no. of current attaches */
-	unsigned long		__unused4;
-	unsigned long		__unused5;
-};
-
-struct shminfo64 {
-	unsigned long	shmmax;
-	unsigned long	shmmin;
-	unsigned long	shmmni;
-	unsigned long	shmseg;
-	unsigned long	shmall;
-	unsigned long	__unused1;
-	unsigned long	__unused2;
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* _ASM_MICROBLAZE_SHMBUF_H */
+#include <asm-generic/shmbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/shmparam.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/shmparam.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/shmparam.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/shmparam.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1 @@
-#ifndef _ASM_MICROBLAZE_SHMPARAM_H
-#define _ASM_MICROBLAZE_SHMPARAM_H
-
-#define SHMLBA	PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _ASM_MICROBLAZE_SHMPARAM_H */
+#include <asm-generic/shmparam.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/siginfo.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/siginfo.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/siginfo.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/siginfo.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,15 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_SIGINFO_H
-#define _ASM_MICROBLAZE_SIGINFO_H
-
-#include <linux/types.h>
 #include <asm-generic/siginfo.h>
-
-#endif /* _ASM_MICROBLAZE_SIGINFO_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/signal.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,165 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *	Yasushi SHOJI <yashi@atmark-techno.com>
- *	Tetsuya OHKAWA <tetsuya@atmark-techno.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.
- */
-
-#ifndef _ASM_MICROBLAZE_SIGNAL_H
-#define _ASM_MICROBLAZE_SIGNAL_H
-
-#define SIGHUP		1
-#define SIGINT		2
-#define SIGQUIT		3
-#define SIGILL		4
-#define SIGTRAP		5
-#define SIGABRT		6
-#define SIGIOT		6
-#define SIGBUS		7
-#define SIGFPE		8
-#define SIGKILL		9
-#define SIGUSR1		10
-#define SIGSEGV		11
-#define SIGUSR2		12
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGSTKFLT	16
-#define SIGCHLD		17
-#define SIGCONT		18
-#define SIGSTOP		19
-#define SIGTSTP		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGURG		23
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGIO		29
-#define SIGPOLL		SIGIO
-/*
-#define SIGLOST		29
-*/
-#define SIGPWR		30
-#define SIGSYS		31
-#define	SIGUNUSED	31
-
-/* These should not be considered constants from userland. */
-#define SIGRTMIN	32
-#define SIGRTMAX	_NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-#define SA_RESTORER	0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
-
-# ifndef __ASSEMBLY__
-# include <linux/types.h>
-# include <asm-generic/signal.h>
-
-/* Avoid too many header ordering problems. */
-struct siginfo;
-
-#  ifdef __KERNEL__
-/*
- * Most things should be clean enough to redefine this at will, if care
- * is taken to make libc match.
- */
-#  define _NSIG		64
-#  define _NSIG_BPW	32
-#  define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t; /* at least 32 bits */
-
-typedef struct {
-	unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-struct old_sigaction {
-	__sighandler_t sa_handler;
-	old_sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
-struct sigaction {
-	__sighandler_t sa_handler;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-	sigset_t sa_mask; /* mask last for extensibility */
-};
-
-struct k_sigaction {
-	struct sigaction sa;
-};
-
-#  include <asm/sigcontext.h>
-#  undef __HAVE_ARCH_SIG_BITOPS
-
-#  define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#  else /* !__KERNEL__ */
-
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-#  define NSIG		32
-typedef unsigned long sigset_t;
-
-struct sigaction {
-	union {
-	__sighandler_t _sa_handler;
-	void (*_sa_sigaction)(int, struct siginfo *, void *);
-	} _u;
-	sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
-#  define sa_handler	_u._sa_handler
-#  define sa_sigaction	_u._sa_sigaction
-
-#  endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-	void *ss_sp;
-	int ss_flags;
-	size_t ss_size;
-} stack_t;
-
-# endif /* __ASSEMBLY__ */
-#endif /* _ASM_MICROBLAZE_SIGNAL_H */
+#include <asm-generic/signal.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/socket.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/socket.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/socket.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/socket.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,69 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_SOCKET_H
-#define _ASM_MICROBLAZE_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET	1
-
-#define SO_DEBUG	1
-#define SO_REUSEADDR	2
-#define SO_TYPE		3
-#define SO_ERROR	4
-#define SO_DONTROUTE	5
-#define SO_BROADCAST	6
-#define SO_SNDBUF	7
-#define SO_RCVBUF	8
-#define SO_SNDBUFFORCE	32
-#define SO_RCVBUFFORCE	33
-#define SO_KEEPALIVE	9
-#define SO_OOBINLINE	10
-#define SO_NO_CHECK	11
-#define SO_PRIORITY	12
-#define SO_LINGER	13
-#define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED	16
-#define SO_PEERCRED	17
-#define SO_RCVLOWAT	18
-#define SO_SNDLOWAT	19
-#define SO_RCVTIMEO	20
-#define SO_SNDTIMEO	21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION		22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
-#define SO_SECURITY_ENCRYPTION_NETWORK		24
-
-#define SO_BINDTODEVICE	25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER	26
-#define SO_DETACH_FILTER	27
-
-#define SO_PEERNAME		28
-#define SO_TIMESTAMP		29
-#define SCM_TIMESTAMP		SO_TIMESTAMP
-
-#define SO_ACCEPTCONN		30
-
-#define SO_PEERSEC		31
-#define SO_PASSSEC		34
-
-#define SO_TIMESTAMPNS		35
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
-
-#define SO_MARK			36
-
-#define SO_TIMESTAMPING		37
-#define SCM_TIMESTAMPING	SO_TIMESTAMPING
-
-#endif /* _ASM_MICROBLAZE_SOCKET_H */
+#include <asm-generic/socket.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/sockios.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/sockios.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/sockios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/sockios.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,23 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_SOCKIOS_H
-#define _ASM_MICROBLAZE_SOCKIOS_H
-
-#include <linux/ioctl.h>
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN	0x8901
-#define SIOCSPGRP	0x8902
-#define FIOGETOWN	0x8903
-#define SIOCGPGRP	0x8904
-#define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
-#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
-
-#endif /* _ASM_MICROBLAZE_SOCKIOS_H */
+#include <asm-generic/sockios.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/stat.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/stat.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/stat.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/stat.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,73 +1 @@
-/*
- * Microblaze stat structure
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
- *
- * 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.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef _ASM_MICROBLAZE_STAT_H
-#define _ASM_MICROBLAZE_STAT_H
-
-#include <linux/posix_types.h>
-
-struct stat {
-	unsigned int	st_dev;
-	unsigned long	st_ino;
-	unsigned int	st_mode;
-	unsigned int	st_nlink;
-	unsigned int	st_uid;
-	unsigned int	st_gid;
-	unsigned int	st_rdev;
-	unsigned long	st_size;
-	unsigned long	st_blksize;
-	unsigned long	st_blocks;
-	unsigned long	st_atime;
-	unsigned long	__unused1; /* unsigned long  st_atime_nsec */
-	unsigned long	st_mtime;
-	unsigned long	__unused2; /* unsigned long  st_mtime_nsec */
-	unsigned long	st_ctime;
-	unsigned long	__unused3; /* unsigned long  st_ctime_nsec */
-	unsigned long	__unused4;
-	unsigned long	__unused5;
-};
-
-struct stat64 {
-	unsigned long long	st_dev;
-	unsigned long	__unused1;
-
-	unsigned long long	st_ino;
-
-	unsigned int	st_mode;
-	unsigned int	st_nlink;
-
-	unsigned int	st_uid;
-	unsigned int	st_gid;
-
-	unsigned long long	st_rdev;
-	unsigned long	__unused3;
-
-	long long	st_size;
-	unsigned long	st_blksize;
-
-	unsigned long	st_blocks; /* No. of 512-byte blocks allocated */
-	unsigned long	__unused4; /* future possible st_blocks high bits */
-
-	unsigned long	st_atime;
-	unsigned long	st_atime_nsec;
-
-	unsigned long	st_mtime;
-	unsigned long	st_mtime_nsec;
-
-	unsigned long	st_ctime;
-	unsigned long	st_ctime_nsec;
-
-	unsigned long	__unused8;
-};
-
-#endif /* _ASM_MICROBLAZE_STAT_H */
+#include <asm-generic/stat.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/string.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/string.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/string.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/string.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,7 +9,7 @@
 #ifndef _ASM_MICROBLAZE_STRING_H
 #define _ASM_MICROBLAZE_STRING_H
 
-#ifndef __KERNEL__
+#ifdef __KERNEL__
 
 #define __HAVE_ARCH_MEMSET
 #define __HAVE_ARCH_MEMCPY
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/swab.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/swab.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/swab.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/swab.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1 @@
-#ifndef _ASM_MICROBLAZE_SWAB_H
-#define _ASM_MICROBLAZE_SWAB_H
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#define __SWAB_64_THRU_32__
-#endif
-
-#endif /* _ASM_MICROBLAZE_SWAB_H */
+#include <asm-generic/swab.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/syscalls.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/syscalls.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/syscalls.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/syscalls.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,45 +1,8 @@
 #ifndef __ASM_MICROBLAZE_SYSCALLS_H
-#define __ASM_MICROBLAZE_SYSCALLS_H
-#ifdef __KERNEL__
-
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <linux/signal.h>
-
-/* FIXME will be removed */
-asmlinkage int sys_ipc(uint call, int first, int second,
-				int third, void *ptr, long fifth);
 
-struct pt_regs;
-asmlinkage int sys_vfork(struct pt_regs *regs);
-asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs);
-asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
-			char __user *__user *envp, struct pt_regs *regs);
-
-asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
-			unsigned long prot, unsigned long flags,
-			unsigned long fd, unsigned long pgoff);
-
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
-			unsigned long prot, unsigned long flags,
-			unsigned long fd, off_t offset);
-
-/* from signal.c */
-asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs);
-
-asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
-		struct pt_regs *regs);
-
-asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act,
-		struct old_sigaction *oact);
-
-asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
-		struct pt_regs *regs);
-
-asmlinkage int sys_sigreturn(struct pt_regs *regs);
+asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs);
+#define sys_clone sys_clone
 
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs);
+#include <asm-generic/syscalls.h>
 
-#endif /* __KERNEL__ */
 #endif /* __ASM_MICROBLAZE_SYSCALLS_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/system.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/system.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,9 @@
 #include <asm/setup.h>
 #include <asm/irqflags.h>
 
+#include <asm-generic/cmpxchg.h>
+#include <asm-generic/cmpxchg-local.h>
+
 struct task_struct;
 struct thread_info;
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/termbits.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/termbits.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/termbits.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/termbits.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,203 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_TERMBITS_H
-#define _ASM_MICROBLAZE_TERMBITS_H
-
-#include <linux/posix_types.h>
-
-typedef unsigned char	cc_t;
-typedef unsigned int	speed_t;
-typedef unsigned int	tcflag_t;
-
-#define NCCS 19
-struct termios {
-	tcflag_t c_iflag; /* input mode flags */
-	tcflag_t c_oflag; /* output mode flags */
-	tcflag_t c_cflag; /* control mode flags */
-	tcflag_t c_lflag; /* local mode flags */
-	cc_t c_line; /* line discipline */
-	cc_t c_cc[NCCS]; /* control characters */
-};
-
-struct ktermios {
-	tcflag_t c_iflag; /* input mode flags */
-	tcflag_t c_oflag; /* output mode flags */
-	tcflag_t c_cflag; /* control mode flags */
-	tcflag_t c_lflag; /* local mode flags */
-	cc_t c_line; /* line discipline */
-	cc_t c_cc[NCCS]; /* control characters */
-	speed_t c_ispeed; /* input speed */
-	speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-
-#define IGNBRK	0000001
-#define BRKINT	0000002
-#define IGNPAR	0000004
-#define PARMRK	0000010
-#define INPCK	0000020
-#define ISTRIP	0000040
-#define INLCR	0000100
-#define IGNCR	0000200
-#define ICRNL	0000400
-#define IUCLC	0001000
-#define IXON	0002000
-#define IXANY	0004000
-#define IXOFF	0010000
-#define IMAXBEL	0020000
-#define IUTF8	0040000
-
-/* c_oflag bits */
-
-#define OPOST	0000001
-#define OLCUC	0000002
-#define ONLCR	0000004
-#define OCRNL	0000010
-#define ONOCR	0000020
-#define ONLRET	0000040
-#define OFILL	0000100
-#define OFDEL	0000200
-#define NLDLY	0000400
-#define NL0	0000000
-#define NL1	0000400
-#define CRDLY	0003000
-#define CR0	0000000
-#define CR1	0001000
-#define CR2	0002000
-#define CR3	0003000
-#define TABDLY	0014000
-#define TAB0	0000000
-#define TAB1	0004000
-#define TAB2	0010000
-#define TAB3	0014000
-#define XTABS	0014000
-#define BSDLY	0020000
-#define BS0	0000000
-#define BS1	0020000
-#define VTDLY	0040000
-#define VT0	0000000
-#define VT1	0040000
-#define FFDLY	0100000
-#define FF0	0000000
-#define FF1	0100000
-
-/* c_cflag bit meaning */
-
-#define CBAUD	0010017
-#define B0	0000000 /* hang up */
-#define B50	0000001
-#define B75	0000002
-#define B110	0000003
-#define B134	0000004
-#define B150	0000005
-#define B200	0000006
-#define B300	0000007
-#define B600	0000010
-#define B1200	0000011
-#define B1800	0000012
-#define B2400	0000013
-#define B4800	0000014
-#define B9600	0000015
-#define B19200	0000016
-#define B38400	0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE	0000060
-#define CS5	0000000
-#define CS6	0000020
-#define CS7	0000040
-#define CS8	0000060
-#define CSTOPB	0000100
-#define CREAD	0000200
-#define PARENB	0000400
-#define PARODD	0001000
-#define HUPCL	0002000
-#define CLOCAL	0004000
-#define CBAUDEX	0010000
-#define B57600	0010001
-#define B115200	0010002
-#define B230400	0010003
-#define B460800	0010004
-#define B500000	0010005
-#define B576000	0010006
-#define B921600	0010007
-#define BOTHER		0010000
-#define B1000000	0010010
-#define B1152000	0010011
-#define B1500000	0010012
-#define B2000000	0010013
-#define B2500000	0010014
-#define B3000000	0010015
-#define B3500000	0010016
-#define B4000000	0010017
-#define CIBAUD		002003600000 /* input baud rate (not used) */
-#define CMSPAR		010000000000 /* mark or space (stick) parity */
-#define CRTSCTS		020000000000 /* flow control */
-
-#define IBSHIFT	16		/* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-
-#define ISIG	0000001
-#define ICANON	0000002
-#define XCASE	0000004
-#define ECHO	0000010
-#define ECHOE	0000020
-#define ECHOK	0000040
-#define ECHONL	0000100
-#define NOFLSH	0000200
-#define TOSTOP	0000400
-#define ECHOCTL	0001000
-#define ECHOPRT	0002000
-#define ECHOKE	0004000
-#define FLUSHO	0010000
-#define PENDIN	0040000
-#define IEXTEN	0100000
-
-/* tcflow() and TCXONC use these */
-
-#define	TCOOFF		0
-#define	TCOON		1
-#define	TCIOFF		2
-#define	TCION		3
-
-/* tcflush() and TCFLSH use these */
-
-#define	TCIFLUSH	0
-#define	TCOFLUSH	1
-#define	TCIOFLUSH	2
-
-/* tcsetattr uses these */
-
-#define	TCSANOW		0
-#define	TCSADRAIN	1
-#define	TCSAFLUSH	2
-
-#endif /* _ASM_MICROBLAZE_TERMBITS_H */
+#include <asm-generic/termbits.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/termios.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,88 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_TERMIOS_H
-#define _ASM_MICROBLAZE_TERMIOS_H
-
-#include <linux/string.h>
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-	unsigned short ws_row;
-	unsigned short ws_col;
-	unsigned short ws_xpixel;
-	unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-	unsigned short c_iflag; /* input mode flags */
-	unsigned short c_oflag; /* output mode flags */
-	unsigned short c_cflag; /* control mode flags */
-	unsigned short c_lflag; /* local mode flags */
-	unsigned char c_line; /* line discipline */
-	unsigned char c_cc[NCC]; /* control characters */
-};
-
-#ifdef __KERNEL__
-/*	intr=^C		quit=^|		erase=del	kill=^U
-	eof=^D		vtime=\0	vmin=\1		sxtc=\0
-	start=^Q	stop=^S		susp=^Z		eol=\0
-	reprint=^R	discard=^U	werase=^W	lnext=^V
-	eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-#endif
-
-/* Modem lines */
-
-#define TIOCM_LE	0x001
-#define TIOCM_DTR	0x002
-#define TIOCM_RTS	0x004
-#define TIOCM_ST	0x008
-#define TIOCM_SR	0x010
-#define TIOCM_CTS	0x020
-#define TIOCM_CAR	0x040
-#define TIOCM_RNG	0x080
-#define TIOCM_DSR	0x100
-#define TIOCM_CD	TIOCM_CAR
-#define TIOCM_RI	TIOCM_RNG
-#define TIOCM_OUT1	0x2000
-#define TIOCM_OUT2	0x4000
-#define TIOCM_LOOP	0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-/* Line disciplines */
-
-#define N_TTY		0
-#define N_SLIP		1
-#define N_MOUSE		2
-#define N_PPP		3
-#define N_STRIP		4
-#define N_AX25		5
-#define N_X25		6 /* X.25 async */
-#define N_6PACK		7
-#define N_MASC		8 /* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964		9 /* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL	10 /* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11 /* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK	12 /* SMS block mode - for talking to GSM data cards
-				about SMS messages */
-#define N_HDLC		13 /* synchronous HDLC */
-#define N_SYNC_PPP	14
-#define N_HCI		15 /* Bluetooth HCI UART */
-
-#ifdef __KERNEL__
-
 #include <asm-generic/termios.h>
-
-#endif	/* __KERNEL__ */
-
-#endif /* _ASM_MICROBLAZE_TERMIOS_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -75,8 +75,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
@@ -84,7 +82,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -122,6 +120,8 @@
 #define TIF_SINGLESTEP		4
 #define TIF_IRET		5 /* return with iret */
 #define TIF_MEMDIE		6
+#define TIF_SYSCALL_AUDIT	9       /* syscall auditing active */
+#define TIF_SECCOMP		10      /* secure computing */
 #define TIF_FREEZE		14	/* Freezing for suspend */
 
 /* FIXME change in entry.S */
@@ -138,10 +138,17 @@
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
+#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_KERNEL_TRACE	(1 << TIF_KERNEL_TRACE)
 
+/* work to do in syscall trace */
+#define _TIF_WORK_SYSCALL_MASK  (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
+				 _TIF_SYSCALL_AUDIT | _TIF_SECCOMP)
+
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		0x0000FFFE
+
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK	0x0000FFFF
 
@@ -154,6 +161,17 @@
  */
 /* FPU was used by this task this quantum (SMP) */
 #define TS_USEDFPU		0x0001
+#define TS_RESTORE_SIGMASK	0x0002
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK 1
+static inline void set_restore_sigmask(void)
+{
+	struct thread_info *ti = current_thread_info();
+	ti->status |= TS_RESTORE_SIGMASK;
+	set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
+}
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_THREAD_INFO_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/timex.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/timex.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/timex.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/timex.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,10 +9,8 @@
 #ifndef _ASM_MICROBLAZE_TIMEX_H
 #define _ASM_MICROBLAZE_TIMEX_H
 
-#define CLOCK_TICK_RATE 1000 /* Timer input freq. */
-
-typedef unsigned long cycles_t;
+#include <asm-generic/timex.h>
 
-#define get_cycles()	(0)
+#define CLOCK_TICK_RATE 1000 /* Timer input freq. */
 
 #endif /* _ASM_TIMEX_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/tlbflush.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/tlbflush.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/tlbflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/tlbflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,6 +11,50 @@
 #ifndef _ASM_MICROBLAZE_TLBFLUSH_H
 #define _ASM_MICROBLAZE_TLBFLUSH_H
 
+#ifdef CONFIG_MMU
+
+#include <linux/sched.h>
+#include <linux/threads.h>
+#include <asm/processor.h>	/* For TASK_SIZE */
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+extern void _tlbie(unsigned long address);
+extern void _tlbia(void);
+
+#define __tlbia()	_tlbia()
+
+static inline void local_flush_tlb_all(void)
+	{ __tlbia(); }
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
+	{ __tlbia(); }
+static inline void local_flush_tlb_page(struct vm_area_struct *vma,
+				unsigned long vmaddr)
+	{ _tlbie(vmaddr); }
+static inline void local_flush_tlb_range(struct vm_area_struct *vma,
+		unsigned long start, unsigned long end)
+	{ __tlbia(); }
+
+#define flush_tlb_kernel_range(start, end)	do { } while (0)
+
+#define update_mmu_cache(vma, addr, pte)	do { } while (0)
+
+#define flush_tlb_all local_flush_tlb_all
+#define flush_tlb_mm local_flush_tlb_mm
+#define flush_tlb_page local_flush_tlb_page
+#define flush_tlb_range local_flush_tlb_range
+
+/*
+ * This is called in munmap when we have freed up some page-table
+ * pages.  We don't need to do anything here, there's nothing special
+ * about our page-table pages.  -- paulus
+ */
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+	unsigned long start, unsigned long end) { }
+
+#else /* CONFIG_MMU */
+
 #define flush_tlb()				BUG()
 #define flush_tlb_all()				BUG()
 #define flush_tlb_mm(mm)			BUG()
@@ -17,4 +63,6 @@
 #define flush_tlb_pgtables(mm, start, end)	BUG()
 #define flush_tlb_kernel_range(start, end)	BUG()
 
+#endif /* CONFIG_MMU */
+
 #endif /* _ASM_MICROBLAZE_TLBFLUSH_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,8 +11,14 @@
 #ifndef _ASM_MICROBLAZE_TLB_H
 #define _ASM_MICROBLAZE_TLB_H
 
-#define tlb_flush(tlb)	do {} while (0)
+#define tlb_flush(tlb)	flush_tlb_mm((tlb)->mm)
 
 #include <asm-generic/tlb.h>
 
+#ifdef CONFIG_MMU
+#define tlb_start_vma(tlb, vma)		do { } while (0)
+#define tlb_end_vma(tlb, vma)		do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#endif
+
 #endif /* _ASM_MICROBLAZE_TLB_H */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/types.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,38 +1 @@
-/*
- * Copyright (C) Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_TYPES_H
-#define _ASM_MICROBLAZE_TYPES_H
-
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-
-#include <asm-generic/int-ll64.h>
-
-# ifndef __ASSEMBLY__
-
-typedef unsigned short umode_t;
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#  ifdef __KERNEL__
-#  define BITS_PER_LONG 32
-
-/* Dma addresses are 32-bits wide. */
-
-typedef u32 dma_addr_t;
-
-#  endif/* __KERNEL__ */
-# endif /* __ASSEMBLY__ */
-#endif /* _ASM_MICROBLAZE_TYPES_H */
+#include <asm-generic/types.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/uaccess.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/uaccess.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/uaccess.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/uaccess.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -26,6 +28,10 @@
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
 
+#define __clear_user(addr, n)	(memset((void *)(addr), 0, (n)), 0)
+
+#ifndef CONFIG_MMU
+
 extern int ___range_ok(unsigned long addr, unsigned long size);
 
 #define __range_ok(addr, size) \
@@ -34,68 +40,68 @@
 #define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0)
 #define __access_ok(add, size) (__range_ok((addr), (size)) == 0)
 
-extern inline int bad_user_access_length(void)
-{
-	return 0;
-}
+/* Undefined function to trigger linker error */
+extern int bad_user_access_length(void);
+
 /* FIXME this is function for optimalization -> memcpy */
-#define __get_user(var, ptr)					\
-	({							\
-		int __gu_err = 0;				\
-		switch (sizeof(*(ptr))) {			\
-		case 1:						\
-		case 2:						\
-		case 4:						\
-			(var) = *(ptr);				\
-			break;					\
-		case 8:						\
-			memcpy((void *) &(var), (ptr), 8);	\
-			break;					\
-		default:					\
-			(var) = 0;				\
-			__gu_err = __get_user_bad();		\
-			break;					\
-		}						\
-		__gu_err;					\
-	})
+#define __get_user(var, ptr)				\
+({							\
+	int __gu_err = 0;				\
+	switch (sizeof(*(ptr))) {			\
+	case 1:						\
+	case 2:						\
+	case 4:						\
+		(var) = *(ptr);				\
+		break;					\
+	case 8:						\
+		memcpy((void *) &(var), (ptr), 8);	\
+		break;					\
+	default:					\
+		(var) = 0;				\
+		__gu_err = __get_user_bad();		\
+		break;					\
+	}						\
+	__gu_err;					\
+})
 
 #define __get_user_bad()	(bad_user_access_length(), (-EFAULT))
 
+/* FIXME is not there defined __pu_val */
 #define __put_user(var, ptr)					\
-	({							\
-		int __pu_err = 0;				\
-		switch (sizeof(*(ptr))) {			\
-		case 1:						\
-		case 2:						\
-		case 4:						\
-			*(ptr) = (var);				\
-			break;					\
-		case 8: {					\
-			typeof(*(ptr)) __pu_val = var;		\
-			memcpy(ptr, &__pu_val, sizeof(__pu_val));\
-			}					\
-			break;					\
-		default:					\
-			__pu_err = __put_user_bad();		\
-			break;					\
-		}							\
-		__pu_err;						\
-	})
+({								\
+	int __pu_err = 0;					\
+	switch (sizeof(*(ptr))) {				\
+	case 1:							\
+	case 2:							\
+	case 4:							\
+		*(ptr) = (var);					\
+		break;						\
+	case 8: {						\
+		typeof(*(ptr)) __pu_val = (var);		\
+		memcpy(ptr, &__pu_val, sizeof(__pu_val));	\
+		}						\
+		break;						\
+	default:						\
+		__pu_err = __put_user_bad();			\
+		break;						\
+	}							\
+	__pu_err;						\
+})
 
 #define __put_user_bad()	(bad_user_access_length(), (-EFAULT))
 
-#define put_user(x, ptr)	__put_user(x, ptr)
-#define get_user(x, ptr)	__get_user(x, ptr)
-
-#define copy_to_user(to, from, n)		(memcpy(to, from, n), 0)
-#define copy_from_user(to, from, n)		(memcpy(to, from, n), 0)
+#define put_user(x, ptr)	__put_user((x), (ptr))
+#define get_user(x, ptr)	__get_user((x), (ptr))
 
-#define __copy_to_user(to, from, n)		(copy_to_user(to, from, n))
-#define __copy_from_user(to, from, n)		(copy_from_user(to, from, n))
-#define __copy_to_user_inatomic(to, from, n)	(__copy_to_user(to, from, n))
-#define __copy_from_user_inatomic(to, from, n)	(__copy_from_user(to, from, n))
+#define copy_to_user(to, from, n)	(memcpy((to), (from), (n)), 0)
+#define copy_from_user(to, from, n)	(memcpy((to), (from), (n)), 0)
 
-#define __clear_user(addr, n)	(memset((void *)addr, 0, n), 0)
+#define __copy_to_user(to, from, n)	(copy_to_user((to), (from), (n)))
+#define __copy_from_user(to, from, n)	(copy_from_user((to), (from), (n)))
+#define __copy_to_user_inatomic(to, from, n) \
+			(__copy_to_user((to), (from), (n)))
+#define __copy_from_user_inatomic(to, from, n) \
+			(__copy_from_user((to), (from), (n)))
 
 static inline unsigned long clear_user(void *addr, unsigned long size)
 {
@@ -104,13 +110,200 @@
 	return size;
 }
 
-/* Returns 0 if exception not found and fixup otherwise. */
+/* Returns 0 if exception not found and fixup otherwise.  */
 extern unsigned long search_exception_table(unsigned long);
 
+extern long strncpy_from_user(char *dst, const char *src, long count);
+extern long strnlen_user(const char *src, long count);
 
-extern long strncpy_from_user(char *dst, const char __user *src, long count);
-extern long strnlen_user(const char __user *src, long count);
-extern long __strncpy_from_user(char *dst, const char __user *src, long count);
+#else /* CONFIG_MMU */
+
+/*
+ * Address is valid if:
+ *  - "addr", "addr + size" and "size" are all below the limit
+ */
+#define access_ok(type, addr, size) \
+	(get_fs().seg > (((unsigned long)(addr)) | \
+		(size) | ((unsigned long)(addr) + (size))))
+
+/* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n",
+ type?"WRITE":"READ",addr,size,get_fs().seg)) */
+
+/*
+ * All the __XXX versions macros/functions below do not perform
+ * access checking. It is assumed that the necessary checks have been
+ * already performed before the finction (macro) is called.
+ */
+
+#define get_user(x, ptr)						\
+({									\
+	access_ok(VERIFY_READ, (ptr), sizeof(*(ptr)))			\
+		? __get_user((x), (ptr)) : -EFAULT;			\
+})
+
+#define put_user(x, ptr)						\
+({									\
+	access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr)))			\
+		? __put_user((x), (ptr)) : -EFAULT;			\
+})
+
+#define __get_user(x, ptr)						\
+({									\
+	unsigned long __gu_val;						\
+	/*unsigned long __gu_ptr = (unsigned long)(ptr);*/		\
+	long __gu_err;							\
+	switch (sizeof(*(ptr))) {					\
+	case 1:								\
+		__get_user_asm("lbu", (ptr), __gu_val, __gu_err);	\
+		break;							\
+	case 2:								\
+		__get_user_asm("lhu", (ptr), __gu_val, __gu_err);	\
+		break;							\
+	case 4:								\
+		__get_user_asm("lw", (ptr), __gu_val, __gu_err);	\
+		break;							\
+	default:							\
+		__gu_val = 0; __gu_err = -EINVAL;			\
+	}								\
+	x = (__typeof__(*(ptr))) __gu_val;				\
+	__gu_err;							\
+})
+
+#define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err)		\
+({									\
+	__asm__ __volatile__ (						\
+			"1:"	insn	" %1, %2, r0;			\
+				addk	%0, r0, r0;			\
+			2:						\
+			.section .fixup,\"ax\";				\
+			3:	brid	2b;				\
+				addik	%0, r0, %3;			\
+			.previous;					\
+			.section __ex_table,\"a\";			\
+			.word	1b,3b;					\
+			.previous;"					\
+		: "=r"(__gu_err), "=r"(__gu_val)			\
+		: "r"(__gu_ptr), "i"(-EFAULT)				\
+	);								\
+})
+
+#define __put_user(x, ptr)						\
+({									\
+	__typeof__(*(ptr)) volatile __gu_val = (x);			\
+	long __gu_err = 0;						\
+	switch (sizeof(__gu_val)) {					\
+	case 1:								\
+		__put_user_asm("sb", (ptr), __gu_val, __gu_err);	\
+		break;							\
+	case 2: 							\
+		__put_user_asm("sh", (ptr), __gu_val, __gu_err);	\
+		break;							\
+	case 4:								\
+		__put_user_asm("sw", (ptr), __gu_val, __gu_err);	\
+		break;							\
+	case 8:								\
+		__put_user_asm_8((ptr), __gu_val, __gu_err);		\
+		break;							\
+	default:							\
+		__gu_err = -EINVAL;					\
+	}								\
+	__gu_err;							\
+})
+
+#define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err)	\
+({							\
+__asm__ __volatile__ ("	lwi	%0, %1, 0;		\
+		1:	swi	%0, %2, 0;		\
+			lwi	%0, %1, 4;		\
+		2:	swi	%0, %2, 4;		\
+			addk	%0,r0,r0;		\
+		3:					\
+		.section .fixup,\"ax\";			\
+		4:	brid	3b;			\
+			addik	%0, r0, %3;		\
+		.previous;				\
+		.section __ex_table,\"a\";		\
+		.word	1b,4b,2b,4b;			\
+		.previous;"				\
+	: "=&r"(__gu_err)				\
+	: "r"(&__gu_val),				\
+	"r"(__gu_ptr), "i"(-EFAULT)			\
+	);						\
+})
+
+#define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err)	\
+({								\
+	__asm__ __volatile__ (					\
+			"1:"	insn	" %1, %2, r0;		\
+				addk	%0, r0, r0;		\
+			2:					\
+			.section .fixup,\"ax\";			\
+			3:	brid	2b;			\
+				addik	%0, r0, %3;		\
+			.previous;				\
+			.section __ex_table,\"a\";		\
+			.word	1b,3b;				\
+			.previous;"				\
+		: "=r"(__gu_err)				\
+		: "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT)	\
+	);							\
+})
+
+/*
+ * Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail.
+ */
+static inline int clear_user(char *to, int size)
+{
+	if (size && access_ok(VERIFY_WRITE, to, size)) {
+		__asm__ __volatile__ ("				\
+				1:				\
+					sb	r0, %2, r0;	\
+					addik	%0, %0, -1;	\
+					bneid	%0, 1b;		\
+					addik	%2, %2, 1;	\
+				2:				\
+				.section __ex_table,\"a\";	\
+				.word	1b,2b;			\
+				.section .text;"		\
+			: "=r"(size)				\
+			: "0"(size), "r"(to)
+		);
+	}
+	return size;
+}
+
+extern unsigned long __copy_tofrom_user(void __user *to,
+		const void __user *from, unsigned long size);
+
+#define copy_to_user(to, from, n)					\
+	(access_ok(VERIFY_WRITE, (to), (n)) ?				\
+		__copy_tofrom_user((void __user *)(to),			\
+			(__force const void __user *)(from), (n))	\
+		: -EFAULT)
+
+#define __copy_to_user(to, from, n)	copy_to_user((to), (from), (n))
+#define __copy_to_user_inatomic(to, from, n)	copy_to_user((to), (from), (n))
+
+#define copy_from_user(to, from, n)					\
+	(access_ok(VERIFY_READ, (from), (n)) ?				\
+		__copy_tofrom_user((__force void __user *)(to),		\
+			(void __user *)(from), (n))			\
+		: -EFAULT)
+
+#define __copy_from_user(to, from, n)	copy_from_user((to), (from), (n))
+#define __copy_from_user_inatomic(to, from, n) \
+		copy_from_user((to), (from), (n))
+
+extern int __strncpy_user(char *to, const char __user *from, int len);
+extern int __strnlen_user(const char __user *sstr, int len);
+
+#define strncpy_from_user(to, from, len)	\
+		(access_ok(VERIFY_READ, from, 1) ?	\
+			__strncpy_user(to, from, len) : -EFAULT)
+#define strnlen_user(str, len)	\
+		(access_ok(VERIFY_READ, str, 1) ? __strnlen_user(str, len) : 0)
+
+#endif /* CONFIG_MMU */
 
 /*
  * The exception table consists of pairs of addresses: the first is the
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ucontext.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ucontext.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/ucontext.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/ucontext.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,22 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_UCONTEXT_H
-#define _ASM_MICROBLAZE_UCONTEXT_H
-
-#include <asm/sigcontext.h>
-
-struct ucontext {
-	unsigned long		uc_flags;
-	struct ucontext		*uc_link;
-	stack_t			uc_stack;
-	struct sigcontext	uc_mcontext;
-	sigset_t		uc_sigmask; /* mask last for extensibility */
-};
-
-#endif /* _ASM_MICROBLAZE_UCONTEXT_H */
+#include <asm-generic/ucontext.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/unaligned.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/unaligned.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/unaligned.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/unaligned.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,8 @@
 
 # ifdef __KERNEL__
 
-# include <linux/unaligned/access_ok.h>
+# include <linux/unaligned/be_struct.h>
+# include <linux/unaligned/le_byteshift.h>
 # include <linux/unaligned/generic.h>
 
 # define get_unaligned	__get_unaligned_be
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -380,8 +380,10 @@
 #define __NR_accept04		362 /* new */
 #define __NR_preadv		363 /* new */
 #define __NR_pwritev		364 /* new */
+#define __NR_rt_tgsigqueueinfo	365 /* new */
+#define __NR_perf_counter_open	366 /* new */
 
-#define __NR_syscalls		365
+#define __NR_syscalls		367
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
@@ -408,7 +410,7 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-/* #define __ARCH_WANT_SYS_RT_SIGSUSPEND */
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 /*
  * "Conditional" syscalls
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/include/asm/vga.h linux-libre-2.6.31-gnu/arch/microblaze/include/asm/vga.h
--- linux-libre-2.6.30-gnu/arch/microblaze/include/asm/vga.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/include/asm/vga.h	2009-09-09 18:13:59.000000000 -0400
@@ -1 +1 @@
-
+#include <asm-generic/vga.h>
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/Kconfig linux-libre-2.6.31-gnu/arch/microblaze/Kconfig
--- linux-libre-2.6.30-gnu/arch/microblaze/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,7 @@
 config MICROBLAZE
 	def_bool y
 	select HAVE_LMB
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config SWAP
 	def_bool n
@@ -49,13 +50,17 @@
 config GENERIC_HARDIRQS_NO__DO_IRQ
 	def_bool y
 
+config GENERIC_GPIO
+	def_bool y
+
+config GENERIC_CSUM
+	def_bool y
+
 config PCI
-	depends on !MMU
 	def_bool n
 
 config NO_DMA
-	depends on !MMU
-	def_bool n
+	def_bool y
 
 source "init/Kconfig"
 
@@ -72,7 +77,8 @@
 source "kernel/Kconfig.hz"
 
 config MMU
-	def_bool n
+	bool "MMU support"
+	default n
 
 config NO_MMU
 	bool
@@ -105,9 +111,6 @@
 config OF
 	def_bool y
 
-config OF_DEVICE
-	def_bool y
-
 config PROC_DEVICETREE
 	bool "Support for device tree in /proc"
 	depends on PROC_FS
@@ -118,6 +121,113 @@
 
 endmenu
 
+menu "Advanced setup"
+
+config ADVANCED_OPTIONS
+	bool "Prompt for advanced kernel configuration options"
+	depends on MMU
+	help
+	  This option will enable prompting for a variety of advanced kernel
+	  configuration options.  These options can cause the kernel to not
+	  work if they are set incorrectly, but can be used to optimize certain
+	  aspects of kernel memory management.
+
+	  Unless you know what you are doing, say N here.
+
+comment "Default settings for advanced configuration options are used"
+	depends on !ADVANCED_OPTIONS
+
+config HIGHMEM_START_BOOL
+	bool "Set high memory pool address"
+	depends on ADVANCED_OPTIONS && HIGHMEM
+	help
+	  This option allows you to set the base address of the kernel virtual
+	  area used to map high memory pages.  This can be useful in
+	  optimizing the layout of kernel virtual memory.
+
+	  Say N here unless you know what you are doing.
+
+config HIGHMEM_START
+	hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
+	depends on MMU
+	default "0xfe000000"
+
+config LOWMEM_SIZE_BOOL
+	bool "Set maximum low memory"
+	depends on ADVANCED_OPTIONS
+	help
+	  This option allows you to set the maximum amount of memory which
+	  will be used as "low memory", that is, memory which the kernel can
+	  access directly, without having to set up a kernel virtual mapping.
+	  This can be useful in optimizing the layout of kernel virtual
+	  memory.
+
+	  Say N here unless you know what you are doing.
+
+config LOWMEM_SIZE
+	hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
+	depends on MMU
+	default "0x30000000"
+
+config KERNEL_START_BOOL
+	bool "Set custom kernel base address"
+	depends on ADVANCED_OPTIONS
+	help
+	  This option allows you to set the kernel virtual address at which
+	  the kernel will map low memory (the kernel image will be linked at
+	  this address).  This can be useful in optimizing the virtual memory
+	  layout of the system.
+
+	  Say N here unless you know what you are doing.
+
+config KERNEL_START
+	hex "Virtual address of kernel base" if KERNEL_START_BOOL
+	default "0xc0000000" if MMU
+	default KERNEL_BASE_ADDR if !MMU
+
+config TASK_SIZE_BOOL
+	bool "Set custom user task size"
+	depends on ADVANCED_OPTIONS
+	help
+	  This option allows you to set the amount of virtual address space
+	  allocated to user tasks.  This can be useful in optimizing the
+	  virtual memory layout of the system.
+
+	  Say N here unless you know what you are doing.
+
+config TASK_SIZE
+	hex "Size of user task space" if TASK_SIZE_BOOL
+	depends on MMU
+	default "0x80000000"
+
+config CONSISTENT_START_BOOL
+	bool "Set custom consistent memory pool address"
+	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+	help
+	  This option allows you to set the base virtual address
+	  of the the consistent memory pool.  This pool of virtual
+	  memory is used to make consistent memory allocations.
+
+config CONSISTENT_START
+	hex "Base virtual address of consistent memory pool" if CONSISTENT_START_BOOL
+	depends on MMU
+	default "0xff100000" if NOT_COHERENT_CACHE
+
+config CONSISTENT_SIZE_BOOL
+	bool "Set custom consistent memory pool size"
+	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
+	help
+	  This option allows you to set the size of the the
+	  consistent memory pool.  This pool of virtual memory
+	  is used to make consistent memory allocations.
+
+config CONSISTENT_SIZE
+	hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
+	depends on MMU
+	default "0x00200000" if NOT_COHERENT_CACHE
+
+endmenu
+
 source "mm/Kconfig"
 
 menu "Exectuable file formats"
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/asm-offsets.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/asm-offsets.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/asm-offsets.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/asm-offsets.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
@@ -68,16 +69,26 @@
 
 	/* struct task_struct */
 	DEFINE(TS_THREAD_INFO, offsetof(struct task_struct, stack));
+#ifdef CONFIG_MMU
+	DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+	DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+	DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+	DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
+	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+	DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+	DEFINE(TASK_PID, offsetof(struct task_struct, pid));
+	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+	BLANK();
+
+	DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
+	BLANK();
+#endif
 
 	/* struct thread_info */
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
-	DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
-	DEFINE(TI_STATUS, offsetof(struct thread_info, status));
-	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
-	DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
-	DEFINE(TI_RESTART_BLOCK, offsetof(struct thread_info, restart_block));
 	DEFINE(TI_CPU_CONTEXT, offsetof(struct thread_info, cpu_context));
 	BLANK();
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/cpu/cpuinfo.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/cpu/cpuinfo.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,8 @@
 	{"7.10.b", 0x09},
 	{"7.10.c", 0x0a},
 	{"7.10.d", 0x0b},
+	{"7.20.a", 0x0c},
+	{"7.20.b", 0x0d},
 	/* FIXME There is no keycode defined in MBV for these versions */
 	{"2.10.a", 0x10},
 	{"3.00.a", 0x20},
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,7 @@
 
 #define CI(c, p) { ci->c = PVR_##p(pvr); }
 #define err_printk(x) \
-	early_printk("ERROR: Microblaze " x " - different for PVR and DTS\n");
+	early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
 
 void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
 {
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/cpu/cpuinfo-static.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/cpu/cpuinfo-static.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/cpu/cpuinfo-static.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/cpu/cpuinfo-static.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,7 @@
 static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
 
 #define err_printk(x) \
-	early_printk("ERROR: Microblaze " x "- different for kernel and DTS\n");
+	early_printk("ERROR: Microblaze " x "-different for kernel and DTS\n");
 
 void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
 {
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/early_printk.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/early_printk.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/early_printk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/early_printk.c	2009-09-09 18:13:59.000000000 -0400
@@ -87,6 +87,9 @@
 	base_addr = early_uartlite_console();
 	if (base_addr) {
 		early_console_initialized = 1;
+#ifdef CONFIG_MMU
+		early_console_reg_tlb_alloc(base_addr);
+#endif
 		early_printk("early_printk_console is enabled at 0x%08x\n",
 							base_addr);
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/entry-nommu.S linux-libre-2.6.31-gnu/arch/microblaze/kernel/entry-nommu.S
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/entry-nommu.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/entry-nommu.S	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,7 @@
 
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
 #include <asm/entry.h>
 #include <asm/asm-offsets.h>
 #include <asm/registers.h>
@@ -551,30 +551,22 @@
 	rtid	r14, 0
 	nop
 
-sys_vfork_wrapper:
-	brid	sys_vfork
+sys_vfork:
+	brid	microblaze_vfork
 	addk	r5, r1, r0
 
-sys_clone_wrapper:
-	brid	sys_clone
+sys_clone:
+	brid	microblaze_clone
 	addk	r7, r1, r0
 
-sys_execve_wrapper:
-	brid	sys_execve
+sys_execve:
+	brid	microblaze_execve
 	addk	r8, r1, r0
 
-sys_sigreturn_wrapper:
-	brid	sys_sigreturn
-	addk	r5, r1, r0
-
 sys_rt_sigreturn_wrapper:
 	brid	sys_rt_sigreturn
 	addk	r5, r1, r0
 
-sys_sigsuspend_wrapper:
-	brid	sys_rt_sigsuspend
-	addk	r6, r1, r0
-
 sys_rt_sigsuspend_wrapper:
 	brid	sys_rt_sigsuspend
 	addk	r7, r1, r0
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/entry.S linux-libre-2.6.31-gnu/arch/microblaze/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1092 @@
+/*
+ * Low-level system-call handling, trap handlers and context-switching
+ *
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
+ * Copyright (C) 2003		John Williams <jwilliams@itee.uq.edu.au>
+ * Copyright (C) 2001,2002	NEC Corporation
+ * Copyright (C) 2001,2002	Miles Bader <miles@gnu.org>
+ *
+ * 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.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ * Heavily modified by John Williams for Microblaze
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+
+#include <asm/entry.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+#include <asm/exceptions.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+
+#include <asm/page.h>
+#include <asm/unistd.h>
+
+#include <linux/errno.h>
+#include <asm/signal.h>
+
+/* The size of a state save frame. */
+#define STATE_SAVE_SIZE		(PT_SIZE + STATE_SAVE_ARG_SPACE)
+
+/* The offset of the struct pt_regs in a `state save frame' on the stack. */
+#define PTO	STATE_SAVE_ARG_SPACE /* 24 the space for args */
+
+#define C_ENTRY(name)	.globl name; .align 4; name
+
+/*
+ * Various ways of setting and clearing BIP in flags reg.
+ * This is mucky, but necessary using microblaze version that
+ * allows msr ops to write to BIP
+ */
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+	.macro	clear_bip
+	msrclr	r11, MSR_BIP
+	nop
+	.endm
+
+	.macro	set_bip
+	msrset	r11, MSR_BIP
+	nop
+	.endm
+
+	.macro	clear_eip
+	msrclr	r11, MSR_EIP
+	nop
+	.endm
+
+	.macro	set_ee
+	msrset	r11, MSR_EE
+	nop
+	.endm
+
+	.macro	disable_irq
+	msrclr	r11, MSR_IE
+	nop
+	.endm
+
+	.macro	enable_irq
+	msrset	r11, MSR_IE
+	nop
+	.endm
+
+	.macro	set_ums
+	msrset	r11, MSR_UMS
+	nop
+	msrclr	r11, MSR_VMS
+	nop
+	.endm
+
+	.macro	set_vms
+	msrclr	r11, MSR_UMS
+	nop
+	msrset	r11, MSR_VMS
+	nop
+	.endm
+
+	.macro	clear_vms_ums
+	msrclr	r11, MSR_VMS
+	nop
+	msrclr	r11, MSR_UMS
+	nop
+	.endm
+#else
+	.macro	clear_bip
+	mfs	r11, rmsr
+	nop
+	andi	r11, r11, ~MSR_BIP
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro	set_bip
+	mfs	r11, rmsr
+	nop
+	ori	r11, r11, MSR_BIP
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro	clear_eip
+	mfs	r11, rmsr
+	nop
+	andi	r11, r11, ~MSR_EIP
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro	set_ee
+	mfs	r11, rmsr
+	nop
+	ori	r11, r11, MSR_EE
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro	disable_irq
+	mfs	r11, rmsr
+	nop
+	andi	r11, r11, ~MSR_IE
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro	enable_irq
+	mfs	r11, rmsr
+	nop
+	ori	r11, r11, MSR_IE
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro set_ums
+	mfs	r11, rmsr
+	nop
+	ori	r11, r11, MSR_VMS
+	andni	r11, r11, MSR_UMS
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro	set_vms
+	mfs	r11, rmsr
+	nop
+	ori	r11, r11, MSR_VMS
+	andni	r11, r11, MSR_UMS
+	mts	rmsr, r11
+	nop
+	.endm
+
+	.macro	clear_vms_ums
+	mfs	r11, rmsr
+	nop
+	andni	r11, r11, (MSR_VMS|MSR_UMS)
+	mts	rmsr,r11
+	nop
+	.endm
+#endif
+
+/* Define how to call high-level functions. With MMU, virtual mode must be
+ * enabled when calling the high-level function. Clobbers R11.
+ * VM_ON, VM_OFF, DO_JUMP_BIPCLR, DO_CALL
+ */
+
+/* turn on virtual protected mode save */
+#define VM_ON		\
+	set_ums;		\
+	rted	r0, 2f;	\
+2: nop;
+
+/* turn off virtual protected mode save and user mode save*/
+#define VM_OFF			\
+	clear_vms_ums;			\
+	rted	r0, TOPHYS(1f);	\
+1: nop;
+
+#define SAVE_REGS \
+	swi	r2, r1, PTO+PT_R2;	/* Save SDA */			\
+	swi	r5, r1, PTO+PT_R5;					\
+	swi	r6, r1, PTO+PT_R6;					\
+	swi	r7, r1, PTO+PT_R7;					\
+	swi	r8, r1, PTO+PT_R8;					\
+	swi	r9, r1, PTO+PT_R9;					\
+	swi	r10, r1, PTO+PT_R10;					\
+	swi	r11, r1, PTO+PT_R11;	/* save clobbered regs after rval */\
+	swi	r12, r1, PTO+PT_R12;					\
+	swi	r13, r1, PTO+PT_R13;	/* Save SDA2 */			\
+	swi	r14, r1, PTO+PT_PC;	/* PC, before IRQ/trap */	\
+	swi	r15, r1, PTO+PT_R15;	/* Save LP */			\
+	swi	r18, r1, PTO+PT_R18;	/* Save asm scratch reg */	\
+	swi	r19, r1, PTO+PT_R19;					\
+	swi	r20, r1, PTO+PT_R20;					\
+	swi	r21, r1, PTO+PT_R21;					\
+	swi	r22, r1, PTO+PT_R22;					\
+	swi	r23, r1, PTO+PT_R23;					\
+	swi	r24, r1, PTO+PT_R24;					\
+	swi	r25, r1, PTO+PT_R25;					\
+	swi	r26, r1, PTO+PT_R26;					\
+	swi	r27, r1, PTO+PT_R27;					\
+	swi	r28, r1, PTO+PT_R28;					\
+	swi	r29, r1, PTO+PT_R29;					\
+	swi	r30, r1, PTO+PT_R30;					\
+	swi	r31, r1, PTO+PT_R31;	/* Save current task reg */	\
+	mfs	r11, rmsr;		/* save MSR */			\
+	nop;								\
+	swi	r11, r1, PTO+PT_MSR;
+
+#define RESTORE_REGS \
+	lwi	r11, r1, PTO+PT_MSR;					\
+	mts	rmsr , r11;						\
+	nop;								\
+	lwi	r2, r1, PTO+PT_R2;	/* restore SDA */		\
+	lwi	r5, r1, PTO+PT_R5;					\
+	lwi	r6, r1, PTO+PT_R6;					\
+	lwi	r7, r1, PTO+PT_R7;					\
+	lwi	r8, r1, PTO+PT_R8;					\
+	lwi	r9, r1, PTO+PT_R9;					\
+	lwi	r10, r1, PTO+PT_R10;					\
+	lwi	r11, r1, PTO+PT_R11;	/* restore clobbered regs after rval */\
+	lwi	r12, r1, PTO+PT_R12;					\
+	lwi	r13, r1, PTO+PT_R13;	/* restore SDA2 */		\
+	lwi	r14, r1, PTO+PT_PC;	/* RESTORE_LINK PC, before IRQ/trap */\
+	lwi	r15, r1, PTO+PT_R15;	/* restore LP */		\
+	lwi	r18, r1, PTO+PT_R18;	/* restore asm scratch reg */	\
+	lwi	r19, r1, PTO+PT_R19;					\
+	lwi	r20, r1, PTO+PT_R20;					\
+	lwi	r21, r1, PTO+PT_R21;					\
+	lwi	r22, r1, PTO+PT_R22;					\
+	lwi	r23, r1, PTO+PT_R23;					\
+	lwi	r24, r1, PTO+PT_R24;					\
+	lwi	r25, r1, PTO+PT_R25;					\
+	lwi	r26, r1, PTO+PT_R26;					\
+	lwi	r27, r1, PTO+PT_R27;					\
+	lwi	r28, r1, PTO+PT_R28;					\
+	lwi	r29, r1, PTO+PT_R29;					\
+	lwi	r30, r1, PTO+PT_R30;					\
+	lwi	r31, r1, PTO+PT_R31;	/* Restore cur task reg */
+
+.text
+
+/*
+ * User trap.
+ *
+ * System calls are handled here.
+ *
+ * Syscall protocol:
+ * Syscall number in r12, args in r5-r10
+ * Return value in r3
+ *
+ * Trap entered via brki instruction, so BIP bit is set, and interrupts
+ * are masked. This is nice, means we don't have to CLI before state save
+ */
+C_ENTRY(_user_exception):
+	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+	addi	r14, r14, 4	/* return address is 4 byte after call */
+	swi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11);	/* Save r11 */
+
+	lwi	r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/
+	beqi	r11, 1f;		/* Jump ahead if coming from user */
+/* Kernel-mode state save. */
+	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
+	tophys(r1,r11);
+	swi	r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
+	lwi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
+
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
+	SAVE_REGS
+
+	addi	r11, r0, 1; 		/* Was in kernel-mode. */
+	swi	r11, r1, PTO+PT_MODE; /* pt_regs -> kernel mode */
+	brid	2f;
+	nop;				/* Fill delay slot */
+
+/* User-mode state save.  */
+1:
+	lwi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11);	/* restore r11 */
+	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
+	tophys(r1,r1);
+	lwi	r1, r1, TS_THREAD_INFO;	/* get stack from task_struct */
+/* calculate kernel stack pointer from task struct 8k */
+	addik	r1, r1, THREAD_SIZE;
+	tophys(r1,r1);
+
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+	SAVE_REGS
+
+	swi	r0, r1, PTO+PT_MODE;			/* Was in user-mode. */
+	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	swi	r11, r1, PTO+PT_R1;		/* Store user SP.  */
+	addi	r11, r0, 1;
+	swi	r11, r0, TOPHYS(PER_CPU(KM));	/* Now we're in kernel-mode.  */
+2:	lwi	r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE));	/* get saved current */
+	/* Save away the syscall number.  */
+	swi	r12, r1, PTO+PT_R0;
+	tovirt(r1,r1)
+
+	la	r15, r0, ret_from_trap-8
+/* where the trap should return need -8 to adjust for rtsd r15, 8*/
+/* Jump to the appropriate function for the system call number in r12
+ * (r12 is not preserved), or return an error if r12 is not valid. The LP
+ * register should point to the location where
+ * the called function should return.  [note that MAKE_SYS_CALL uses label 1] */
+	/* See if the system call number is valid.  */
+	addi	r11, r12, -__NR_syscalls;
+	bgei	r11,1f;
+	/* Figure out which function to use for this system call.  */
+	/* Note Microblaze barrel shift is optional, so don't rely on it */
+	add	r12, r12, r12;			/* convert num -> ptr */
+	add	r12, r12, r12;
+
+	/* Trac syscalls and stored them to r0_ram */
+	lwi	r3, r12, 0x400 + TOPHYS(r0_ram)
+	addi	r3, r3, 1
+	swi	r3, r12, 0x400 + TOPHYS(r0_ram)
+
+	lwi	r12, r12, TOPHYS(sys_call_table); /* Function ptr */
+	/* Make the system call.  to r12*/
+	set_vms;
+	rtid	r12, 0;
+	nop;
+	/* The syscall number is invalid, return an error.  */
+1:	VM_ON;	/* RETURN() expects virtual mode*/
+	addi	r3, r0, -ENOSYS;
+	rtsd	r15,8;		/* looks like a normal subroutine return */
+	or 	r0, r0, r0
+
+
+/* Entry point used to return from a syscall/trap.  */
+/* We re-enable BIP bit before state restore */
+C_ENTRY(ret_from_trap):
+	set_bip;			/*  Ints masked for state restore*/
+	lwi	r11, r1, PTO+PT_MODE;
+/* See if returning to kernel mode, if so, skip resched &c.  */
+	bnei	r11, 2f;
+
+	/* We're returning to user mode, so check for various conditions that
+	 * trigger rescheduling. */
+	/* Get current task ptr into r11 */
+	add	r11, r0, CURRENT_TASK;	/* Get current task ptr into r11 */
+	lwi	r11, r11, TS_THREAD_INFO;	/* get thread info */
+	lwi	r11, r11, TI_FLAGS;		/* get flags in thread info */
+	andi	r11, r11, _TIF_NEED_RESCHED;
+	beqi	r11, 5f;
+
+	swi	r3, r1, PTO + PT_R3; /* store syscall result */
+	swi	r4, r1, PTO + PT_R4;
+	bralid	r15, schedule;	/* Call scheduler */
+	nop;				/* delay slot */
+	lwi	r3, r1, PTO + PT_R3; /* restore syscall result */
+	lwi	r4, r1, PTO + PT_R4;
+
+	/* Maybe handle a signal */
+5:	add	r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	lwi	r11, r11, TS_THREAD_INFO;	/* get thread info */
+	lwi	r11, r11, TI_FLAGS;	/* get flags in thread info */
+	andi	r11, r11, _TIF_SIGPENDING;
+	beqi	r11, 1f;		/* Signals to handle, handle them */
+
+	swi	r3, r1, PTO + PT_R3; /* store syscall result */
+	swi	r4, r1, PTO + PT_R4;
+	la	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
+	addi	r7, r0, 1;		/* Arg 3: int in_syscall */
+	bralid	r15, do_signal;	/* Handle any signals */
+	nop;
+	lwi	r3, r1, PTO + PT_R3; /* restore syscall result */
+	lwi	r4, r1, PTO + PT_R4;
+
+/* Finally, return to user state.  */
+1:	swi	r0, r0, PER_CPU(KM);	/* Now officially in user state. */
+	add	r11, r0, CURRENT_TASK;	/* Get current task ptr into r11 */
+	swi	r11, r0, PER_CPU(CURRENT_SAVE); /* save current */
+	VM_OFF;
+	tophys(r1,r1);
+	RESTORE_REGS;
+	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	lwi	r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
+	bri	6f;
+
+/* Return to kernel state.  */
+2:	VM_OFF;
+	tophys(r1,r1);
+	RESTORE_REGS;
+	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	tovirt(r1,r1);
+6:
+TRAP_return:		/* Make global symbol for debugging */
+	rtbd	r14, 0;	/* Instructions to return from an IRQ */
+	nop;
+
+
+/* These syscalls need access to the struct pt_regs on the stack, so we
+   implement them in assembly (they're basically all wrappers anyway).  */
+
+C_ENTRY(sys_fork_wrapper):
+	addi	r5, r0, SIGCHLD			/* Arg 0: flags */
+	lwi	r6, r1, PTO+PT_R1	/* Arg 1: child SP (use parent's) */
+	la	r7, r1, PTO			/* Arg 2: parent context */
+	add	r8. r0, r0			/* Arg 3: (unused) */
+	add	r9, r0, r0;			/* Arg 4: (unused) */
+	add	r10, r0, r0;			/* Arg 5: (unused) */
+	brid	do_fork		/* Do real work (tail-call) */
+	nop;
+
+/* This the initial entry point for a new child thread, with an appropriate
+   stack in place that makes it look the the child is in the middle of an
+   syscall.  This function is actually `returned to' from switch_thread
+   (copy_thread makes ret_from_fork the return address in each new thread's
+   saved context).  */
+C_ENTRY(ret_from_fork):
+	bralid	r15, schedule_tail; /* ...which is schedule_tail's arg */
+	add	r3, r5, r0;	/* switch_thread returns the prev task */
+				/* ( in the delay slot ) */
+	add	r3, r0, r0;	/* Child's fork call should return 0. */
+	brid	ret_from_trap;	/* Do normal trap return */
+	nop;
+
+C_ENTRY(sys_vfork):
+	brid	microblaze_vfork	/* Do real work (tail-call) */
+	la	r5, r1, PTO
+
+C_ENTRY(sys_clone):
+	bnei	r6, 1f;			/* See if child SP arg (arg 1) is 0. */
+	lwi	r6, r1, PTO+PT_R1;	/* If so, use paret's stack ptr */
+1:	la	r7, r1, PTO;			/* Arg 2: parent context */
+	add	r8, r0, r0;			/* Arg 3: (unused) */
+	add	r9, r0, r0;			/* Arg 4: (unused) */
+	add	r10, r0, r0;			/* Arg 5: (unused) */
+	brid	do_fork		/* Do real work (tail-call) */
+	nop;
+
+C_ENTRY(sys_execve):
+	la	r8, r1, PTO;		/* add user context as 4th arg */
+	brid	microblaze_execve;	/* Do real work (tail-call).*/
+	nop;
+
+C_ENTRY(sys_rt_sigsuspend_wrapper):
+	swi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	swi	r4, r1, PTO+PT_R4;
+	la	r7, r1, PTO;		/* add user context as 3rd arg */
+	brlid	r15, sys_rt_sigsuspend;	/* Do real work.*/
+	nop;
+	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	lwi	r4, r1, PTO+PT_R4;
+	bri ret_from_trap /* fall through will not work here due to align */
+	nop;
+
+C_ENTRY(sys_rt_sigreturn_wrapper):
+	swi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	swi	r4, r1, PTO+PT_R4;
+	la	r5, r1, PTO;		/* add user context as 1st arg */
+	brlid	r15, sys_rt_sigreturn	/* Do real work */
+	nop;
+	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	lwi	r4, r1, PTO+PT_R4;
+	bri ret_from_trap /* fall through will not work here due to align */
+	nop;
+
+/*
+ * HW EXCEPTION rutine start
+ */
+
+#define SAVE_STATE	\
+	swi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */	\
+	set_bip;	/*equalize initial state for all possible entries*/\
+	clear_eip;							\
+	enable_irq;							\
+	set_ee;								\
+	/* See if already in kernel mode.*/				\
+	lwi	r11, r0, TOPHYS(PER_CPU(KM));				\
+	beqi	r11, 1f;		/* Jump ahead if coming from user */\
+	/* Kernel-mode state save.  */					\
+	/* Reload kernel stack-ptr. */					\
+	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
+	tophys(r1,r11);							\
+	swi	r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */	\
+	lwi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */\
+	/* store return registers separately because			\
+	 * this macros is use for others exceptions */			\
+	swi	r3, r1, PTO + PT_R3;					\
+	swi	r4, r1, PTO + PT_R4;					\
+	SAVE_REGS							\
+	/* PC, before IRQ/trap - this is one instruction above */	\
+	swi	r17, r1, PTO+PT_PC;					\
+									\
+	addi	r11, r0, 1; 		/* Was in kernel-mode.  */	\
+	swi	r11, r1, PTO+PT_MODE; 	 				\
+	brid	2f;							\
+	nop;				/* Fill delay slot */		\
+1:	/* User-mode state save.  */					\
+	lwi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
+	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
+	tophys(r1,r1);							\
+	lwi	r1, r1, TS_THREAD_INFO;	/* get the thread info */	\
+	addik	r1, r1, THREAD_SIZE;	/* calculate kernel stack pointer */\
+	tophys(r1,r1);							\
+									\
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */\
+	/* store return registers separately because this macros	\
+	 * is use for others exceptions */				\
+	swi	r3, r1, PTO + PT_R3; 					\
+	swi	r4, r1, PTO + PT_R4;					\
+	SAVE_REGS							\
+	/* PC, before IRQ/trap - this is one instruction above FIXME*/	\
+	swi	r17, r1, PTO+PT_PC;					\
+									\
+	swi	r0, r1, PTO+PT_MODE; /* Was in user-mode.  */		\
+	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
+	swi	r11, r1, PTO+PT_R1; /* Store user SP.  */		\
+	addi	r11, r0, 1;						\
+	swi	r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode.*/\
+2:	lwi	r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
+	/* Save away the syscall number.  */				\
+	swi	r0, r1, PTO+PT_R0;					\
+	tovirt(r1,r1)
+
+C_ENTRY(full_exception_trap):
+	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+	/* adjust exception address for privileged instruction
+	 * for finding where is it */
+	addik	r17, r17, -4
+	SAVE_STATE /* Save registers */
+	/* FIXME this can be store directly in PT_ESR reg.
+	 * I tested it but there is a fault */
+	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
+	la	r15, r0, ret_from_exc - 8
+	la	r5, r1, PTO		 /* parameter struct pt_regs * regs */
+	mfs	r6, resr
+	nop
+	mfs	r7, rfsr;		/* save FSR */
+	nop
+	la	r12, r0, full_exception
+	set_vms;
+	rtbd	r12, 0;
+	nop;
+
+/*
+ * Unaligned data trap.
+ *
+ * Unaligned data trap last on 4k page is handled here.
+ *
+ * Trap entered via exception, so EE bit is set, and interrupts
+ * are masked.  This is nice, means we don't have to CLI before state save
+ *
+ * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S"
+ */
+C_ENTRY(unaligned_data_trap):
+	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+	SAVE_STATE		/* Save registers.*/
+	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
+	la	r15, r0, ret_from_exc-8
+	mfs	r3, resr		/* ESR */
+	nop
+	mfs	r4, rear		/* EAR */
+	nop
+	la	r7, r1, PTO		/* parameter struct pt_regs * regs */
+	la	r12, r0, _unaligned_data_exception
+	set_vms;
+	rtbd	r12, 0;	/* interrupts enabled */
+	nop;
+
+/*
+ * Page fault traps.
+ *
+ * If the real exception handler (from hw_exception_handler.S) didn't find
+ * the mapping for the process, then we're thrown here to handle such situation.
+ *
+ * Trap entered via exceptions, so EE bit is set, and interrupts
+ * are masked.  This is nice, means we don't have to CLI before state save
+ *
+ * Build a standard exception frame for TLB Access errors.  All TLB exceptions
+ * will bail out to this point if they can't resolve the lightweight TLB fault.
+ *
+ * The C function called is in "arch/microblaze/mm/fault.c", declared as:
+ * void do_page_fault(struct pt_regs *regs,
+ *				unsigned long address,
+ *				unsigned long error_code)
+ */
+/* data and intruction trap - which is choose is resolved int fault.c */
+C_ENTRY(page_fault_data_trap):
+	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+	SAVE_STATE		/* Save registers.*/
+	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
+	la	r15, r0, ret_from_exc-8
+	la	r5, r1, PTO		/* parameter struct pt_regs * regs */
+	mfs	r6, rear		/* parameter unsigned long address */
+	nop
+	mfs	r7, resr		/* parameter unsigned long error_code */
+	nop
+	la	r12, r0, do_page_fault
+	set_vms;
+	rtbd	r12, 0;	/* interrupts enabled */
+	nop;
+
+C_ENTRY(page_fault_instr_trap):
+	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+	SAVE_STATE		/* Save registers.*/
+	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
+	la	r15, r0, ret_from_exc-8
+	la	r5, r1, PTO		/* parameter struct pt_regs * regs */
+	mfs	r6, rear		/* parameter unsigned long address */
+	nop
+	ori	r7, r0, 0		/* parameter unsigned long error_code */
+	la	r12, r0, do_page_fault
+	set_vms;
+	rtbd	r12, 0;	/* interrupts enabled */
+	nop;
+
+/* Entry point used to return from an exception.  */
+C_ENTRY(ret_from_exc):
+	set_bip;			/*  Ints masked for state restore*/
+	lwi	r11, r1, PTO+PT_MODE;
+	bnei	r11, 2f;		/* See if returning to kernel mode, */
+					/* ... if so, skip resched &c.  */
+
+	/* We're returning to user mode, so check for various conditions that
+	   trigger rescheduling. */
+	/* Get current task ptr into r11 */
+	add	r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	lwi	r11, r11, TS_THREAD_INFO;	/* get thread info */
+	lwi	r11, r11, TI_FLAGS;	/* get flags in thread info */
+	andi	r11, r11, _TIF_NEED_RESCHED;
+	beqi	r11, 5f;
+
+/* Call the scheduler before returning from a syscall/trap. */
+	bralid	r15, schedule;	/* Call scheduler */
+	nop;				/* delay slot */
+
+	/* Maybe handle a signal */
+5:	add	r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	lwi	r11, r11, TS_THREAD_INFO;	/* get thread info */
+	lwi	r11, r11, TI_FLAGS;	/* get flags in thread info */
+	andi	r11, r11, _TIF_SIGPENDING;
+	beqi	r11, 1f;		/* Signals to handle, handle them */
+
+	/*
+	 * Handle a signal return; Pending signals should be in r18.
+	 *
+	 * Not all registers are saved by the normal trap/interrupt entry
+	 * points (for instance, call-saved registers (because the normal
+	 * C-compiler calling sequence in the kernel makes sure they're
+	 * preserved), and call-clobbered registers in the case of
+	 * traps), but signal handlers may want to examine or change the
+	 * complete register state.  Here we save anything not saved by
+	 * the normal entry sequence, so that it may be safely restored
+	 * (in a possibly modified form) after do_signal returns.
+	 * store return registers separately because this macros is use
+	 * for others exceptions */
+	swi	r3, r1, PTO + PT_R3;
+	swi	r4, r1, PTO + PT_R4;
+	la	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
+	addi	r7, r0, 0;		/* Arg 3: int in_syscall */
+	bralid	r15, do_signal;	/* Handle any signals */
+	nop;
+	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	lwi	r4, r1, PTO+PT_R4;
+
+/* Finally, return to user state.  */
+1:	swi	r0, r0, PER_CPU(KM);	/* Now officially in user state. */
+	add	r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	swi	r11, r0, PER_CPU(CURRENT_SAVE); /* save current */
+	VM_OFF;
+	tophys(r1,r1);
+
+	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	lwi	r4, r1, PTO+PT_R4;
+	RESTORE_REGS;
+	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+
+	lwi	r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
+	bri	6f;
+/* Return to kernel state.  */
+2:	VM_OFF;
+	tophys(r1,r1);
+	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	lwi	r4, r1, PTO+PT_R4;
+	RESTORE_REGS;
+	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+
+	tovirt(r1,r1);
+6:
+EXC_return:		/* Make global symbol for debugging */
+	rtbd	r14, 0;	/* Instructions to return from an IRQ */
+	nop;
+
+/*
+ * HW EXCEPTION rutine end
+ */
+
+/*
+ * Hardware maskable interrupts.
+ *
+ * The stack-pointer (r1) should have already been saved to the memory
+ * location PER_CPU(ENTRY_SP).
+ */
+C_ENTRY(_interrupt):
+/* MS: we are in physical address */
+/* Save registers, switch to proper stack, convert SP to virtual.*/
+	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
+	swi	r11, r0, TOPHYS(PER_CPU(R11_SAVE));
+	/* MS: See if already in kernel mode. */
+	lwi	r11, r0, TOPHYS(PER_CPU(KM));
+	beqi	r11, 1f; /* MS: Jump ahead if coming from user */
+
+/* Kernel-mode state save. */
+	or	r11, r1, r0
+	tophys(r1,r11); /* MS: I have in r1 physical address where stack is */
+/* MS: Save original SP - position PT_R1 to next stack frame 4 *1 - 152*/
+	swi	r11, r1, (PT_R1 - PT_SIZE);
+/* MS: restore r11 because of saving in SAVE_REGS */
+	lwi	r11, r0, TOPHYS(PER_CPU(R11_SAVE));
+	/* save registers */
+/* MS: Make room on the stack -> activation record */
+	addik	r1, r1, -STATE_SAVE_SIZE;
+/* MS: store return registers separately because
+ * this macros is use for others exceptions */
+	swi	r3, r1, PTO + PT_R3;
+	swi	r4, r1, PTO + PT_R4;
+	SAVE_REGS
+	/* MS: store mode */
+	addi	r11, r0, 1; /* MS: Was in kernel-mode. */
+	swi	r11, r1, PTO + PT_MODE; /* MS: and save it */
+	brid	2f;
+	nop; /* MS: Fill delay slot */
+
+1:
+/* User-mode state save. */
+/* MS: restore r11 -> FIXME move before SAVE_REG */
+	lwi	r11, r0, TOPHYS(PER_CPU(R11_SAVE));
+ /* MS: get the saved current */
+	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+	tophys(r1,r1);
+	lwi	r1, r1, TS_THREAD_INFO;
+	addik	r1, r1, THREAD_SIZE;
+	tophys(r1,r1);
+	/* save registers */
+	addik	r1, r1, -STATE_SAVE_SIZE;
+	swi	r3, r1, PTO+PT_R3;
+	swi	r4, r1, PTO+PT_R4;
+	SAVE_REGS
+	/* calculate mode */
+	swi	r0, r1, PTO + PT_MODE;
+	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	swi	r11, r1, PTO+PT_R1;
+	/* setup kernel mode to KM */
+	addi	r11, r0, 1;
+	swi	r11, r0, TOPHYS(PER_CPU(KM));
+
+2:
+	lwi	r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+	swi	r0, r1, PTO + PT_R0;
+	tovirt(r1,r1)
+	la	r5, r1, PTO;
+	set_vms;
+	la	r11, r0, do_IRQ;
+	la	r15, r0, irq_call;
+irq_call:rtbd	r11, 0;
+	nop;
+
+/* MS: we are in virtual mode */
+ret_from_irq:
+	lwi	r11, r1, PTO + PT_MODE;
+	bnei	r11, 2f;
+
+	add	r11, r0, CURRENT_TASK;
+	lwi	r11, r11, TS_THREAD_INFO;
+	lwi	r11, r11, TI_FLAGS; /* MS: get flags from thread info */
+	andi	r11, r11, _TIF_NEED_RESCHED;
+	beqi	r11, 5f
+	bralid	r15, schedule;
+	nop; /* delay slot */
+
+    /* Maybe handle a signal */
+5:	add	r11, r0, CURRENT_TASK;
+	lwi	r11, r11, TS_THREAD_INFO; /* MS: get thread info */
+	lwi	r11, r11, TI_FLAGS; /* get flags in thread info */
+	andi	r11, r11, _TIF_SIGPENDING;
+	beqid	r11, no_intr_resched
+/* Handle a signal return; Pending signals should be in r18. */
+	addi	r7, r0, 0; /* Arg 3: int in_syscall */
+	la	r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
+	bralid	r15, do_signal;	/* Handle any signals */
+	add	r6, r0, r0; /* Arg 2: sigset_t *oldset */
+
+/* Finally, return to user state. */
+no_intr_resched:
+    /* Disable interrupts, we are now committed to the state restore */
+	disable_irq
+	swi	r0, r0, PER_CPU(KM); /* MS: Now officially in user state. */
+	add	r11, r0, CURRENT_TASK;
+	swi	r11, r0, PER_CPU(CURRENT_SAVE);
+	VM_OFF;
+	tophys(r1,r1);
+	lwi	r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */
+	lwi	r4, r1, PTO + PT_R4;
+	RESTORE_REGS
+	addik	r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
+	lwi	r1, r1, PT_R1 - PT_SIZE;
+	bri	6f;
+/* MS: Return to kernel state. */
+2:	VM_OFF /* MS: turn off MMU */
+	tophys(r1,r1)
+	lwi	r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */
+	lwi	r4, r1, PTO + PT_R4;
+	RESTORE_REGS
+	addik	r1, r1, STATE_SAVE_SIZE	/* MS: Clean up stack space. */
+	tovirt(r1,r1);
+6:
+IRQ_return: /* MS: Make global symbol for debugging */
+	rtid	r14, 0
+	nop
+
+/*
+ * `Debug' trap
+ *  We enter dbtrap in "BIP" (breakpoint) mode.
+ *  So we exit the breakpoint mode with an 'rtbd' and proceed with the
+ *  original dbtrap.
+ *  however, wait to save state first
+ */
+C_ENTRY(_debug_exception):
+	/* BIP bit is set on entry, no interrupts can occur */
+	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
+
+	swi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */
+	set_bip;	/*equalize initial state for all possible entries*/
+	clear_eip;
+	enable_irq;
+	lwi	r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/
+	beqi	r11, 1f;		/* Jump ahead if coming from user */
+	/* Kernel-mode state save.  */
+	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
+	tophys(r1,r11);
+	swi	r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
+	lwi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
+
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+	swi	r3, r1, PTO + PT_R3;
+	swi	r4, r1, PTO + PT_R4;
+	SAVE_REGS;
+
+	addi	r11, r0, 1; 		/* Was in kernel-mode.  */
+	swi	r11, r1, PTO + PT_MODE;
+	brid	2f;
+	nop;				/* Fill delay slot */
+1:      /* User-mode state save.  */
+	lwi	r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
+	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
+	tophys(r1,r1);
+	lwi	r1, r1, TS_THREAD_INFO;	/* get the thread info */
+	addik	r1, r1, THREAD_SIZE;	/* calculate kernel stack pointer */
+	tophys(r1,r1);
+
+	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+	swi	r3, r1, PTO + PT_R3;
+	swi	r4, r1, PTO + PT_R4;
+	SAVE_REGS;
+
+	swi	r0, r1, PTO+PT_MODE; /* Was in user-mode.  */
+	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	swi	r11, r1, PTO+PT_R1; /* Store user SP.  */
+	addi	r11, r0, 1;
+	swi	r11, r0, TOPHYS(PER_CPU(KM));	/* Now we're in kernel-mode.  */
+2:	lwi	r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
+	/* Save away the syscall number.  */
+	swi	r0, r1, PTO+PT_R0;
+	tovirt(r1,r1)
+
+	addi	r5, r0, SIGTRAP		     /* send the trap signal */
+	add	r6, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	addk	r7, r0, r0		     /* 3rd param zero */
+
+	set_vms;
+	la	r11, r0, send_sig;
+	la	r15, r0, dbtrap_call;
+dbtrap_call:	rtbd	r11, 0;
+	nop;
+
+	set_bip;			/*  Ints masked for state restore*/
+	lwi	r11, r1, PTO+PT_MODE;
+	bnei	r11, 2f;
+
+	/* Get current task ptr into r11 */
+	add	r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	lwi	r11, r11, TS_THREAD_INFO;	/* get thread info */
+	lwi	r11, r11, TI_FLAGS;	/* get flags in thread info */
+	andi	r11, r11, _TIF_NEED_RESCHED;
+	beqi	r11, 5f;
+
+/* Call the scheduler before returning from a syscall/trap. */
+
+	bralid	r15, schedule;	/* Call scheduler */
+	nop;				/* delay slot */
+	/* XXX Is PT_DTRACE handling needed here? */
+	/* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here.  */
+
+	/* Maybe handle a signal */
+5:	add	r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	lwi	r11, r11, TS_THREAD_INFO;	/* get thread info */
+	lwi	r11, r11, TI_FLAGS;	/* get flags in thread info */
+	andi	r11, r11, _TIF_SIGPENDING;
+	beqi	r11, 1f;		/* Signals to handle, handle them */
+
+/* Handle a signal return; Pending signals should be in r18.  */
+	/* Not all registers are saved by the normal trap/interrupt entry
+	   points (for instance, call-saved registers (because the normal
+	   C-compiler calling sequence in the kernel makes sure they're
+	   preserved), and call-clobbered registers in the case of
+	   traps), but signal handlers may want to examine or change the
+	   complete register state.  Here we save anything not saved by
+	   the normal entry sequence, so that it may be safely restored
+	   (in a possibly modified form) after do_signal returns.  */
+
+	la	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
+	addi  r7, r0, 0;	/* Arg 3: int in_syscall */
+	bralid	r15, do_signal;	/* Handle any signals */
+	nop;
+
+
+/* Finally, return to user state.  */
+1:	swi	r0, r0, PER_CPU(KM);	/* Now officially in user state. */
+	add	r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
+	swi	r11, r0, PER_CPU(CURRENT_SAVE); /* save current */
+	VM_OFF;
+	tophys(r1,r1);
+
+	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	lwi	r4, r1, PTO+PT_R4;
+	RESTORE_REGS
+	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+
+
+	lwi	r1, r1, PT_R1 - PT_SIZE;
+					/* Restore user stack pointer. */
+	bri	6f;
+
+/* Return to kernel state.  */
+2:	VM_OFF;
+	tophys(r1,r1);
+	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
+	lwi	r4, r1, PTO+PT_R4;
+	RESTORE_REGS
+	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+
+	tovirt(r1,r1);
+6:
+DBTRAP_return:		/* Make global symbol for debugging */
+	rtbd	r14, 0;	/* Instructions to return from an IRQ */
+	nop;
+
+
+
+ENTRY(_switch_to)
+	/* prepare return value */
+	addk	r3, r0, r31
+
+	/* save registers in cpu_context */
+	/* use r11 and r12, volatile registers, as temp register */
+	/* give start of cpu_context for previous process */
+	addik	r11, r5, TI_CPU_CONTEXT
+	swi	r1, r11, CC_R1
+	swi	r2, r11, CC_R2
+	/* skip volatile registers.
+	 * they are saved on stack when we jumped to _switch_to() */
+	/* dedicated registers */
+	swi	r13, r11, CC_R13
+	swi	r14, r11, CC_R14
+	swi	r15, r11, CC_R15
+	swi	r16, r11, CC_R16
+	swi	r17, r11, CC_R17
+	swi	r18, r11, CC_R18
+	/* save non-volatile registers */
+	swi	r19, r11, CC_R19
+	swi	r20, r11, CC_R20
+	swi	r21, r11, CC_R21
+	swi	r22, r11, CC_R22
+	swi	r23, r11, CC_R23
+	swi	r24, r11, CC_R24
+	swi	r25, r11, CC_R25
+	swi	r26, r11, CC_R26
+	swi	r27, r11, CC_R27
+	swi	r28, r11, CC_R28
+	swi	r29, r11, CC_R29
+	swi	r30, r11, CC_R30
+	/* special purpose registers */
+	mfs	r12, rmsr
+	nop
+	swi	r12, r11, CC_MSR
+	mfs	r12, rear
+	nop
+	swi	r12, r11, CC_EAR
+	mfs	r12, resr
+	nop
+	swi	r12, r11, CC_ESR
+	mfs	r12, rfsr
+	nop
+	swi	r12, r11, CC_FSR
+
+	/* update r31, the current */
+	lwi	r31, r6, TI_TASK/* give me pointer to task which will be next */
+	/* stored it to current_save too */
+	swi	r31, r0, PER_CPU(CURRENT_SAVE)
+
+	/* get new process' cpu context and restore */
+	/* give me start where start context of next task */
+	addik	r11, r6, TI_CPU_CONTEXT
+
+	/* non-volatile registers */
+	lwi	r30, r11, CC_R30
+	lwi	r29, r11, CC_R29
+	lwi	r28, r11, CC_R28
+	lwi	r27, r11, CC_R27
+	lwi	r26, r11, CC_R26
+	lwi	r25, r11, CC_R25
+	lwi	r24, r11, CC_R24
+	lwi	r23, r11, CC_R23
+	lwi	r22, r11, CC_R22
+	lwi	r21, r11, CC_R21
+	lwi	r20, r11, CC_R20
+	lwi	r19, r11, CC_R19
+	/* dedicated registers */
+	lwi	r18, r11, CC_R18
+	lwi	r17, r11, CC_R17
+	lwi	r16, r11, CC_R16
+	lwi	r15, r11, CC_R15
+	lwi	r14, r11, CC_R14
+	lwi	r13, r11, CC_R13
+	/* skip volatile registers */
+	lwi	r2, r11, CC_R2
+	lwi	r1, r11, CC_R1
+
+	/* special purpose registers */
+	lwi	r12, r11, CC_FSR
+	mts	rfsr, r12
+	nop
+	lwi	r12, r11, CC_MSR
+	mts	rmsr, r12
+	nop
+
+	rtsd	r15, 8
+	nop
+
+ENTRY(_reset)
+	brai	0x70; /* Jump back to FS-boot */
+
+ENTRY(_break)
+	mfs	r5, rmsr
+	nop
+	swi	r5, r0, 0x250 + TOPHYS(r0_ram)
+	mfs	r5, resr
+	nop
+	swi	r5, r0, 0x254 + TOPHYS(r0_ram)
+	bri	0
+
+	/* These are compiled and loaded into high memory, then
+	 * copied into place in mach_early_setup */
+	.section	.init.ivt, "ax"
+	.org	0x0
+	/* this is very important - here is the reset vector */
+	/* in current MMU branch you don't care what is here - it is
+	 * used from bootloader site - but this is correct for FS-BOOT */
+	brai	0x70
+	nop
+	brai	TOPHYS(_user_exception); /* syscall handler */
+	brai	TOPHYS(_interrupt);	/* Interrupt handler */
+	brai	TOPHYS(_break);		/* nmi trap handler */
+	brai	TOPHYS(_hw_exception_handler);	/* HW exception handler */
+
+	.org	0x60
+	brai	TOPHYS(_debug_exception);	/* debug trap handler*/
+
+.section .rodata,"a"
+#include "syscall_table.S"
+
+syscall_table_size=(.-sys_call_table)
+
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/exceptions.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/exceptions.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/exceptions.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/exceptions.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,9 +21,9 @@
 
 #include <asm/exceptions.h>
 #include <asm/entry.h>		/* For KM CPU var */
-#include <asm/uaccess.h>
-#include <asm/errno.h>
-#include <asm/ptrace.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
 #include <asm/current.h>
 
 #define MICROBLAZE_ILL_OPCODE_EXCEPTION	0x02
@@ -31,7 +31,7 @@
 #define MICROBLAZE_DBUS_EXCEPTION	0x04
 #define MICROBLAZE_DIV_ZERO_EXCEPTION	0x05
 #define MICROBLAZE_FPU_EXCEPTION	0x06
-#define MICROBLAZE_PRIVILEG_EXCEPTION	0x07
+#define MICROBLAZE_PRIVILEGED_EXCEPTION	0x07
 
 static DEFINE_SPINLOCK(die_lock);
 
@@ -66,6 +66,11 @@
 asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
 							int fsr, int addr)
 {
+#ifdef CONFIG_MMU
+	int code;
+	addr = regs->pc;
+#endif
+
 #if 0
 	printk(KERN_WARNING "Exception %02x in %s mode, FSR=%08x PC=%08x ESR=%08x\n",
 			type, user_mode(regs) ? "user" : "kernel", fsr,
@@ -74,7 +79,13 @@
 
 	switch (type & 0x1F) {
 	case MICROBLAZE_ILL_OPCODE_EXCEPTION:
-		_exception(SIGILL, regs, ILL_ILLOPC, addr);
+		if (user_mode(regs)) {
+			printk(KERN_WARNING "Illegal opcode exception in user mode.\n");
+			_exception(SIGILL, regs, ILL_ILLOPC, addr);
+			return;
+		}
+		printk(KERN_WARNING "Illegal opcode exception in kernel mode.\n");
+		die("opcode exception", regs, SIGBUS);
 		break;
 	case MICROBLAZE_IBUS_EXCEPTION:
 		if (user_mode(regs)) {
@@ -95,11 +106,16 @@
 		die("bus exception", regs, SIGBUS);
 		break;
 	case MICROBLAZE_DIV_ZERO_EXCEPTION:
-		printk(KERN_WARNING "Divide by zero exception\n");
-		_exception(SIGILL, regs, ILL_ILLOPC, addr);
+		if (user_mode(regs)) {
+			printk(KERN_WARNING "Divide by zero exception in user mode\n");
+			_exception(SIGILL, regs, ILL_ILLOPC, addr);
+			return;
+		}
+		printk(KERN_WARNING "Divide by zero exception in kernel mode.\n");
+		die("Divide by exception", regs, SIGBUS);
 		break;
-
 	case MICROBLAZE_FPU_EXCEPTION:
+		printk(KERN_WARNING "FPU exception\n");
 		/* IEEE FP exception */
 		/* I removed fsr variable and use code var for storing fsr */
 		if (fsr & FSR_IO)
@@ -115,7 +131,20 @@
 		_exception(SIGFPE, regs, fsr, addr);
 		break;
 
+#ifdef CONFIG_MMU
+	case MICROBLAZE_PRIVILEGED_EXCEPTION:
+		printk(KERN_WARNING "Privileged exception\n");
+		/* "brk r0,r0" - used as debug breakpoint */
+		if (get_user(code, (unsigned long *)regs->pc) == 0
+			&& code == 0x980c0000) {
+			_exception(SIGTRAP, regs, TRAP_BRKPT, addr);
+		} else {
+			_exception(SIGILL, regs, ILL_PRVOPC, addr);
+		}
+		break;
+#endif
 	default:
+	/* FIXME what to do in unexpected exception */
 		printk(KERN_WARNING "Unexpected exception %02x "
 			"PC=%08x in %s mode\n", type, (unsigned int) addr,
 			kernel_mode(regs) ? "kernel" : "user");
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/head.S linux-libre-2.6.31-gnu/arch/microblaze/kernel/head.S
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/head.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/head.S	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,26 @@
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
  *
+ * MMU code derived from arch/ppc/kernel/head_4xx.S:
+ *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
+ *      Initial PowerPC version.
+ *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *      Rewritten for PReP
+ *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ *      Low-level exception handers, MMU support, and rewrite.
+ *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
+ *      PowerPC 8xx modifications.
+ *    Copyright (c) 1998-1999 TiVo, Inc.
+ *      PowerPC 403GCX modifications.
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *      PowerPC 403GCX/405GP modifications.
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405 modifications
+ *      PowerPC 403GCX/405GP modifications.
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.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.
@@ -11,6 +31,23 @@
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <asm/prom.h>		/* for OF_DT_HEADER */
+
+#ifdef CONFIG_MMU
+#include <asm/setup.h> /* COMMAND_LINE_SIZE */
+#include <asm/mmu.h>
+#include <asm/processor.h>
+
+.data
+.global empty_zero_page
+.align 12
+empty_zero_page:
+	.space	4096
+.global swapper_pg_dir
+swapper_pg_dir:
+	.space	4096
+
+#endif /* CONFIG_MMU */
 
 	.text
 ENTRY(_start)
@@ -18,11 +55,19 @@
 	andi	r1, r1, ~2
 	mts	rmsr, r1
 
-/* save fdt to kernel location */
-/* r7 stores pointer to fdt blob */
-	beqi	r7, no_fdt_arg
+/* r7 may point to an FDT, or there may be one linked in.
+   if it's in r7, we've got to save it away ASAP.
+   We ensure r7 points to a valid FDT, just in case the bootloader
+   is broken or non-existent */
+	beqi	r7, no_fdt_arg			/* NULL pointer?  don't copy */
+	lw	r11, r0, r7			/* Does r7 point to a */
+	rsubi	r11, r11, OF_DT_HEADER		/* valid FDT? */
+	beqi	r11, _prepare_copy_fdt
+	or	r7, r0, r0		/* clear R7 when not valid DTB */
+	bnei	r11, no_fdt_arg			/* No - get out of here */
+_prepare_copy_fdt:
 	or	r11, r0, r0 /* incremment */
-	ori	r4, r0, TOPHYS(_fdt_start) /* save bram context */
+	ori	r4, r0, TOPHYS(_fdt_start)
 	ori	r3, r0, (0x4000 - 4)
 _copy_fdt:
 	lw	r12, r7, r11 /* r12 = r7 + r11 */
@@ -32,6 +77,123 @@
 	addik	r3, r3, -4 /* descrement loop */
 no_fdt_arg:
 
+#ifdef CONFIG_MMU
+
+#ifndef CONFIG_CMDLINE_BOOL
+/*
+ * handling command line
+ * copy command line to __init_end. There is space for storing command line.
+ */
+	or	r6, r0, r0		/* incremment */
+	ori	r4, r0, __init_end	/* load address of command line */
+	tophys(r4,r4)			/* convert to phys address */
+	ori	r3, r0, COMMAND_LINE_SIZE - 1 /* number of loops */
+_copy_command_line:
+	lbu	r7, r5, r6 /* r7=r5+r6 - r5 contain pointer to command line */
+	sb	r7, r4, r6		/* addr[r4+r6]= r7*/
+	addik	r6, r6, 1		/* increment counting */
+	bgtid	r3, _copy_command_line	/* loop for all entries       */
+	addik	r3, r3, -1		/* descrement loop */
+	addik	r5, r4, 0		/* add new space for command line */
+	tovirt(r5,r5)
+#endif /* CONFIG_CMDLINE_BOOL */
+
+#ifdef NOT_COMPILE
+/* save bram context */
+	or	r6, r0, r0				/* incremment */
+	ori	r4, r0, TOPHYS(_bram_load_start)	/* save bram context */
+	ori	r3, r0, (LMB_SIZE - 4)
+_copy_bram:
+	lw	r7, r0, r6		/* r7 = r0 + r6 */
+	sw	r7, r4, r6		/* addr[r4 + r6] = r7*/
+	addik	r6, r6, 4		/* increment counting */
+	bgtid	r3, _copy_bram		/* loop for all entries */
+	addik	r3, r3, -4		/* descrement loop */
+#endif
+	/* We have to turn on the MMU right away. */
+
+	/*
+	 * Set up the initial MMU state so we can do the first level of
+	 * kernel initialization.  This maps the first 16 MBytes of memory 1:1
+	 * virtual to physical.
+	 */
+	nop
+	addik	r3, r0, 63		/* Invalidate all TLB entries */
+_invalidate:
+	mts	rtlbx, r3
+	mts	rtlbhi, r0			/* flush: ensure V is clear   */
+	bgtid	r3, _invalidate		/* loop for all entries       */
+	addik	r3, r3, -1
+	/* sync */
+
+	/*
+	 * We should still be executing code at physical address area
+	 * RAM_BASEADDR at this point. However, kernel code is at
+	 * a virtual address. So, set up a TLB mapping to cover this once
+	 * translation is enabled.
+	 */
+
+	addik	r3,r0, CONFIG_KERNEL_START /* Load the kernel virtual address */
+	tophys(r4,r3)			/* Load the kernel physical address */
+
+	mts	rpid,r0			/* Load the kernel PID */
+	nop
+	bri	4
+
+	/*
+	 * Configure and load two entries into TLB slots 0 and 1.
+	 * In case we are pinning TLBs, these are reserved in by the
+	 * other TLB functions.  If not reserving, then it doesn't
+	 * matter where they are loaded.
+	 */
+	andi	r4,r4,0xfffffc00	/* Mask off the real page number */
+	ori	r4,r4,(TLB_WR | TLB_EX)	/* Set the write and execute bits */
+
+	andi	r3,r3,0xfffffc00	/* Mask off the effective page number */
+	ori	r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
+
+	mts     rtlbx,r0		/* TLB slow 0 */
+
+	mts	rtlblo,r4		/* Load the data portion of the entry */
+	mts	rtlbhi,r3		/* Load the tag portion of the entry */
+
+	addik	r4, r4, 0x01000000	/* Map next 16 M entries */
+	addik	r3, r3, 0x01000000
+
+	ori	r6,r0,1			/* TLB slot 1 */
+	mts     rtlbx,r6
+
+	mts	rtlblo,r4		/* Load the data portion of the entry */
+	mts	rtlbhi,r3		/* Load the tag portion of the entry */
+
+	/*
+	 * Load a TLB entry for LMB, since we need access to
+	 * the exception vectors, using a 4k real==virtual mapping.
+	 */
+	ori	r6,r0,3			/* TLB slot 3 */
+	mts     rtlbx,r6
+
+	ori	r4,r0,(TLB_WR | TLB_EX)
+	ori	r3,r0,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))
+
+	mts	rtlblo,r4		/* Load the data portion of the entry */
+	mts	rtlbhi,r3		/* Load the tag portion of the entry */
+
+	/*
+	 * We now have the lower 16 Meg of RAM mapped into TLB entries, and the
+	 * caches ready to work.
+	 */
+turn_on_mmu:
+	ori	r15,r0,start_here
+	ori	r4,r0,MSR_KERNEL_VMS
+	mts	rmsr,r4
+	nop
+	rted	r15,0			/* enables MMU */
+	nop
+
+start_here:
+#endif /* CONFIG_MMU */
+
 	/* Initialize small data anchors */
 	la	r13, r0, _KERNEL_SDA_BASE_
 	la	r2, r0, _KERNEL_SDA2_BASE_
@@ -51,6 +213,43 @@
 	brald	r15, r8
 	nop
 
+#ifndef CONFIG_MMU
 	la	r15, r0, machine_halt
 	braid	start_kernel
 	nop
+#else
+	/*
+	 * Initialize the MMU.
+	 */
+	bralid	r15, mmu_init
+	nop
+
+	/* Go back to running unmapped so we can load up new values
+	 * and change to using our exception vectors.
+	 * On the MicroBlaze, all we invalidate the used TLB entries to clear
+	 * the old 16M byte TLB mappings.
+	 */
+	ori	r15,r0,TOPHYS(kernel_load_context)
+	ori	r4,r0,MSR_KERNEL
+	mts	rmsr,r4
+	nop
+	bri	4
+	rted	r15,0
+	nop
+
+	/* Load up the kernel context */
+kernel_load_context:
+	# Keep entry 0 and 1 valid. Entry 3 mapped to LMB can go away.
+	ori	r5,r0,3
+	mts     rtlbx,r5
+	nop
+	mts	rtlbhi,r0
+	nop
+	addi	r15, r0, machine_halt
+	ori	r17, r0, start_kernel
+	ori	r4, r0, MSR_KERNEL_VMS
+	mts	rmsr, r4
+	nop
+	rted	r17, 0		/* enable MMU and jump to start_kernel */
+	nop
+#endif /* CONFIG_MMU */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/hw_exception_handler.S linux-libre-2.6.31-gnu/arch/microblaze/kernel/hw_exception_handler.S
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/hw_exception_handler.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/hw_exception_handler.S	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,12 @@
  *   - Illegal instruction opcode
  *   - Divide-by-zero
  *
+ *   - Privileged instruction exception (MMU)
+ *   - Data storage exception (MMU)
+ *   - Instruction storage exception (MMU)
+ *   - Data TLB miss exception (MMU)
+ *   - Instruction TLB miss exception (MMU)
+ *
  * Note we disable interrupts during exception handling, otherwise we will
  * possibly get multiple re-entrancy if interrupt handles themselves cause
  * exceptions. JW
@@ -68,12 +74,28 @@
 
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
+#include <asm/signal.h>
 #include <asm/asm-offsets.h>
 
 /* Helpful Macros */
+#ifndef CONFIG_MMU
 #define EX_HANDLER_STACK_SIZ	(4*19)
+#endif
 #define NUM_TO_REG(num)		r ## num
 
+#ifdef CONFIG_MMU
+/* FIXME you can't change first load of MSR because there is
+ * hardcoded jump bri 4 */
+	#define RESTORE_STATE			\
+		lwi	r3, r1, PT_R3;		\
+		lwi	r4, r1, PT_R4;		\
+		lwi	r5, r1, PT_R5;		\
+		lwi	r6, r1, PT_R6;		\
+		lwi	r11, r1, PT_R11;	\
+		lwi	r31, r1, PT_R31;	\
+		lwi	r1, r0, TOPHYS(r0_ram + 0);
+#endif /* CONFIG_MMU */
+
 #define LWREG_NOP			\
 	bri	ex_handler_unhandled;	\
 	nop;
@@ -106,6 +128,54 @@
 	or	r3, r0, NUM_TO_REG (regnum);		\
 	bri	ex_sw_tail;
 
+#ifdef CONFIG_MMU
+	#define R3_TO_LWREG_VM_V(regnum)		\
+		brid	ex_lw_end_vm;			\
+		swi	r3, r7, 4 * regnum;
+
+	#define R3_TO_LWREG_VM(regnum)			\
+		brid	ex_lw_end_vm;			\
+		or	NUM_TO_REG (regnum), r0, r3;
+
+	#define SWREG_TO_R3_VM_V(regnum)		\
+		brid	ex_sw_tail_vm;			\
+		lwi	r3, r7, 4 * regnum;
+
+	#define SWREG_TO_R3_VM(regnum)			\
+		brid	ex_sw_tail_vm;			\
+		or	r3, r0, NUM_TO_REG (regnum);
+
+	/* Shift right instruction depending on available configuration */
+	#if CONFIG_XILINX_MICROBLAZE0_USE_BARREL > 0
+	#define BSRLI(rD, rA, imm)	\
+		bsrli rD, rA, imm
+	#elif CONFIG_XILINX_MICROBLAZE0_USE_DIV > 0
+	#define BSRLI(rD, rA, imm)	\
+		ori rD, r0, (1 << imm);	\
+		idivu rD, rD, rA
+	#else
+	#define BSRLI(rD, rA, imm) BSRLI ## imm (rD, rA)
+	/* Only the used shift constants defined here - add more if needed */
+	#define BSRLI2(rD, rA)				\
+		srl rD, rA;		/* << 1 */	\
+		srl rD, rD;		/* << 2 */
+	#define BSRLI10(rD, rA)				\
+		srl rD, rA;		/* << 1 */	\
+		srl rD, rD;		/* << 2 */	\
+		srl rD, rD;		/* << 3 */	\
+		srl rD, rD;		/* << 4 */	\
+		srl rD, rD;		/* << 5 */	\
+		srl rD, rD;		/* << 6 */	\
+		srl rD, rD;		/* << 7 */	\
+		srl rD, rD;		/* << 8 */	\
+		srl rD, rD;		/* << 9 */	\
+		srl rD, rD		/* << 10 */
+	#define BSRLI20(rD, rA)		\
+		BSRLI10(rD, rA);	\
+		BSRLI10(rD, rD)
+	#endif
+#endif /* CONFIG_MMU */
+
 .extern other_exception_handler /* Defined in exception.c */
 
 /*
@@ -163,34 +233,119 @@
 
 /* wrappers to restore state before coming to entry.S */
 
+#ifdef CONFIG_MMU
+.section .rodata
+.align 4
+_MB_HW_ExceptionVectorTable:
+/*  0 - Undefined */
+	.long	TOPHYS(ex_handler_unhandled)
+/*  1 - Unaligned data access exception */
+	.long	TOPHYS(handle_unaligned_ex)
+/*  2 - Illegal op-code exception */
+	.long	TOPHYS(full_exception_trapw)
+/*  3 - Instruction bus error exception */
+	.long	TOPHYS(full_exception_trapw)
+/*  4 - Data bus error exception */
+	.long	TOPHYS(full_exception_trapw)
+/*  5 - Divide by zero exception */
+	.long	TOPHYS(full_exception_trapw)
+/*  6 - Floating point unit exception */
+	.long	TOPHYS(full_exception_trapw)
+/*  7 - Privileged instruction exception */
+	.long	TOPHYS(full_exception_trapw)
+/*  8 - 15 - Undefined */
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+/* 16 - Data storage exception */
+	.long	TOPHYS(handle_data_storage_exception)
+/* 17 - Instruction storage exception */
+	.long	TOPHYS(handle_instruction_storage_exception)
+/* 18 - Data TLB miss exception */
+	.long	TOPHYS(handle_data_tlb_miss_exception)
+/* 19 - Instruction TLB miss exception */
+	.long	TOPHYS(handle_instruction_tlb_miss_exception)
+/* 20 - 31 - Undefined */
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+	.long	TOPHYS(ex_handler_unhandled)
+#endif
+
 .global _hw_exception_handler
 .section .text
 .align 4
 .ent _hw_exception_handler
 _hw_exception_handler:
+#ifndef CONFIG_MMU
 	addik	r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */
+#else
+	swi	r1, r0, TOPHYS(r0_ram + 0); /* GET_SP */
+	/* Save date to kernel memory. Here is the problem
+	 * when you came from user space */
+	ori	r1, r0, TOPHYS(r0_ram + 28);
+#endif
 	swi	r3, r1, PT_R3
 	swi	r4, r1, PT_R4
 	swi	r5, r1, PT_R5
 	swi	r6, r1, PT_R6
 
-	mfs	r5, rmsr;
-	nop
-	swi	r5, r1, 0;
-	mfs	r4, rbtr	/* Save BTR before jumping to handler */
-	nop
+#ifdef CONFIG_MMU
+	swi	r11, r1, PT_R11
+	swi	r31, r1, PT_R31
+	lwi	r31, r0, TOPHYS(PER_CPU(CURRENT_SAVE)) /* get saved current */
+#endif
+
 	mfs	r3, resr
 	nop
+	mfs	r4, rear;
+	nop
 
+#ifndef CONFIG_MMU
 	andi	r5, r3, 0x1000;		/* Check ESR[DS] */
 	beqi	r5, not_in_delay_slot;	/* Branch if ESR[DS] not set */
 	mfs	r17, rbtr;	/* ESR[DS] set - return address in BTR */
 	nop
 not_in_delay_slot:
 	swi	r17, r1, PT_R17
+#endif
 
 	andi	r5, r3, 0x1F;		/* Extract ESR[EXC] */
 
+#ifdef CONFIG_MMU
+	/* Calculate exception vector offset = r5 << 2 */
+	addk	r6, r5, r5; /* << 1 */
+	addk	r6, r6, r6; /* << 2 */
+
+/* counting which exception happen */
+	lwi	r5, r0, 0x200 + TOPHYS(r0_ram)
+	addi	r5, r5, 1
+	swi	r5, r0, 0x200 + TOPHYS(r0_ram)
+	lwi	r5, r6, 0x200 + TOPHYS(r0_ram)
+	addi	r5, r5, 1
+	swi	r5, r6, 0x200 + TOPHYS(r0_ram)
+/* end */
+	/* Load the HW Exception vector */
+	lwi	r6, r6, TOPHYS(_MB_HW_ExceptionVectorTable)
+	bra	r6
+
+full_exception_trapw:
+	RESTORE_STATE
+	bri	full_exception_trap
+#else
 	/* Exceptions enabled here. This will allow nested exceptions */
 	mfs	r6, rmsr;
 	nop
@@ -254,6 +409,7 @@
 	lwi	r18, r1, PT_R18
 
 	bri	ex_handler_done; /* Complete exception handling */
+#endif
 
 /* 0x01 - Unaligned data access exception
  * This occurs when a word access is not aligned on a word boundary,
@@ -265,11 +421,18 @@
 handle_unaligned_ex:
 	/* Working registers already saved: R3, R4, R5, R6
 	 *  R3 = ESR
-	 *  R4 = BTR
+	 *  R4 = EAR
 	 */
-	mfs	r4, rear;
+#ifdef CONFIG_MMU
+	andi	r6, r3, 0x1000			/* Check ESR[DS] */
+	beqi	r6, _no_delayslot		/* Branch if ESR[DS] not set */
+	mfs	r17, rbtr;	/* ESR[DS] set - return address in BTR */
 	nop
-
+_no_delayslot:
+	/* jump to high level unaligned handler */
+	RESTORE_STATE;
+	bri	unaligned_data_trap
+#endif
 	andi	r6, r3, 0x3E0; /* Mask and extract the register operand */
 	srl	r6, r6; /* r6 >> 5 */
 	srl	r6, r6;
@@ -355,6 +518,7 @@
 ex_sw_end: /* Exception handling of store word, ends. */
 
 ex_handler_done:
+#ifndef CONFIG_MMU
 	lwi	r5, r1, 0 /* RMSR */
 	mts	rmsr, r5
 	nop
@@ -366,13 +530,486 @@
 
 	rted	r17, 0
 	addik	r1, r1, (EX_HANDLER_STACK_SIZ); /* Restore stack frame */
+#else
+	RESTORE_STATE;
+	rted	r17, 0
+	nop
+#endif
+
+#ifdef CONFIG_MMU
+	/* Exception vector entry code. This code runs with address translation
+	 * turned off (i.e. using physical addresses). */
+
+	/* Exception vectors. */
+
+	/* 0x10 - Data Storage Exception
+	 * This happens for just a few reasons. U0 set (but we don't do that),
+	 * or zone protection fault (user violation, write to protected page).
+	 * If this is just an update of modified status, we do that quickly
+	 * and exit. Otherwise, we call heavyweight functions to do the work.
+	 */
+	handle_data_storage_exception:
+		/* Working registers already saved: R3, R4, R5, R6
+		 * R3 = ESR
+		 */
+		mfs	r11, rpid
+		nop
+		bri	4
+		mfs	r3, rear		/* Get faulting address */
+		nop
+		/* If we are faulting a kernel address, we have to use the
+		 * kernel page tables.
+		 */
+		ori	r4, r0, CONFIG_KERNEL_START
+		cmpu	r4, r3, r4
+		bgti	r4, ex3
+		/* First, check if it was a zone fault (which means a user
+		 * tried to access a kernel or read-protected page - always
+		 * a SEGV). All other faults here must be stores, so no
+		 * need to check ESR_S as well. */
+		mfs	r4, resr
+		nop
+		andi	r4, r4, 0x800		/* ESR_Z - zone protection */
+		bnei	r4, ex2
+
+		ori	r4, r0, swapper_pg_dir
+		mts	rpid, r0		/* TLB will have 0 TID */
+		nop
+		bri	ex4
+
+		/* Get the PGD for the current thread. */
+	ex3:
+		/* First, check if it was a zone fault (which means a user
+		 * tried to access a kernel or read-protected page - always
+		 * a SEGV). All other faults here must be stores, so no
+		 * need to check ESR_S as well. */
+		mfs	r4, resr
+		nop
+		andi	r4, r4, 0x800		/* ESR_Z */
+		bnei	r4, ex2
+		/* get current task address */
+		addi	r4 ,CURRENT_TASK, TOPHYS(0);
+		lwi	r4, r4, TASK_THREAD+PGDIR
+	ex4:
+		tophys(r4,r4)
+		BSRLI(r5,r3,20)		/* Create L1 (pgdir/pmd) address */
+		andi	r5, r5, 0xffc
+/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
+		or	r4, r4, r5
+		lwi	r4, r4, 0		/* Get L1 entry */
+		andi	r5, r4, 0xfffff000 /* Extract L2 (pte) base address */
+		beqi	r5, ex2			/* Bail if no table */
+
+		tophys(r5,r5)
+		BSRLI(r6,r3,10)			/* Compute PTE address */
+		andi	r6, r6, 0xffc
+		andi	r5, r5, 0xfffff003
+		or	r5, r5, r6
+		lwi	r4, r5, 0		/* Get Linux PTE */
+
+		andi	r6, r4, _PAGE_RW	/* Is it writeable? */
+		beqi	r6, ex2			/* Bail if not */
+
+		/* Update 'changed' */
+		ori	r4, r4, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
+		swi	r4, r5, 0		/* Update Linux page table */
+
+		/* Most of the Linux PTE is ready to load into the TLB LO.
+		 * We set ZSEL, where only the LS-bit determines user access.
+		 * We set execute, because we don't have the granularity to
+		 * properly set this at the page level (Linux problem).
+		 * If shared is set, we cause a zero PID->TID load.
+		 * Many of these bits are software only. Bits we don't set
+		 * here we (properly should) assume have the appropriate value.
+		 */
+		andni	r4, r4, 0x0ce2		/* Make sure 20, 21 are zero */
+		ori	r4, r4, _PAGE_HWEXEC	/* make it executable */
+
+		/* find the TLB index that caused the fault. It has to be here*/
+		mts	rtlbsx, r3
+		nop
+		mfs	r5, rtlbx		/* DEBUG: TBD */
+		nop
+		mts	rtlblo, r4		/* Load TLB LO */
+		nop
+						/* Will sync shadow TLBs */
+
+		/* Done...restore registers and get out of here. */
+		mts	rpid, r11
+		nop
+		bri 4
+
+		RESTORE_STATE;
+		rted	r17, 0
+		nop
+	ex2:
+		/* The bailout. Restore registers to pre-exception conditions
+		 * and call the heavyweights to help us out. */
+		mts	rpid, r11
+		nop
+		bri 4
+		RESTORE_STATE;
+		bri	page_fault_data_trap
+
+
+	/* 0x11 - Instruction Storage Exception
+	 * This is caused by a fetch from non-execute or guarded pages. */
+	handle_instruction_storage_exception:
+		/* Working registers already saved: R3, R4, R5, R6
+		 * R3 = ESR
+		 */
+
+		mfs	r3, rear		/* Get faulting address */
+		nop
+		RESTORE_STATE;
+		bri	page_fault_instr_trap
+
+	/* 0x12 - Data TLB Miss Exception
+	 * As the name implies, translation is not in the MMU, so search the
+	 * page tables and fix it. The only purpose of this function is to
+	 * load TLB entries from the page table if they exist.
+	 */
+	handle_data_tlb_miss_exception:
+		/* Working registers already saved: R3, R4, R5, R6
+		 * R3 = ESR
+		 */
+		mfs	r11, rpid
+		nop
+		bri	4
+		mfs	r3, rear		/* Get faulting address */
+		nop
+
+		/* If we are faulting a kernel address, we have to use the
+		 * kernel page tables. */
+		ori	r4, r0, CONFIG_KERNEL_START
+		cmpu	r4, r3, r4
+		bgti	r4, ex5
+		ori	r4, r0, swapper_pg_dir
+		mts	rpid, r0		/* TLB will have 0 TID */
+		nop
+		bri	ex6
+
+		/* Get the PGD for the current thread. */
+	ex5:
+		/* get current task address */
+		addi	r4 ,CURRENT_TASK, TOPHYS(0);
+		lwi	r4, r4, TASK_THREAD+PGDIR
+	ex6:
+		tophys(r4,r4)
+		BSRLI(r5,r3,20)		/* Create L1 (pgdir/pmd) address */
+		andi	r5, r5, 0xffc
+/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
+		or	r4, r4, r5
+		lwi	r4, r4, 0		/* Get L1 entry */
+		andi	r5, r4, 0xfffff000 /* Extract L2 (pte) base address */
+		beqi	r5, ex7			/* Bail if no table */
+
+		tophys(r5,r5)
+		BSRLI(r6,r3,10)			/* Compute PTE address */
+		andi	r6, r6, 0xffc
+		andi	r5, r5, 0xfffff003
+		or	r5, r5, r6
+		lwi	r4, r5, 0		/* Get Linux PTE */
+
+		andi	r6, r4, _PAGE_PRESENT
+		beqi	r6, ex7
+
+		ori	r4, r4, _PAGE_ACCESSED
+		swi	r4, r5, 0
 
+		/* Most of the Linux PTE is ready to load into the TLB LO.
+		 * We set ZSEL, where only the LS-bit determines user access.
+		 * We set execute, because we don't have the granularity to
+		 * properly set this at the page level (Linux problem).
+		 * If shared is set, we cause a zero PID->TID load.
+		 * Many of these bits are software only. Bits we don't set
+		 * here we (properly should) assume have the appropriate value.
+		 */
+		andni	r4, r4, 0x0ce2		/* Make sure 20, 21 are zero */
+
+		bri	finish_tlb_load
+	ex7:
+		/* The bailout. Restore registers to pre-exception conditions
+		 * and call the heavyweights to help us out.
+		 */
+		mts	rpid, r11
+		nop
+		bri	4
+		RESTORE_STATE;
+		bri	page_fault_data_trap
+
+	/* 0x13 - Instruction TLB Miss Exception
+	 * Nearly the same as above, except we get our information from
+	 * different registers and bailout to a different point.
+	 */
+	handle_instruction_tlb_miss_exception:
+		/* Working registers already saved: R3, R4, R5, R6
+		 *  R3 = ESR
+		 */
+		mfs	r11, rpid
+		nop
+		bri	4
+		mfs	r3, rear		/* Get faulting address */
+		nop
+
+		/* If we are faulting a kernel address, we have to use the
+		 * kernel page tables.
+		 */
+		ori	r4, r0, CONFIG_KERNEL_START
+		cmpu	r4, r3, r4
+		bgti	r4, ex8
+		ori	r4, r0, swapper_pg_dir
+		mts	rpid, r0		/* TLB will have 0 TID */
+		nop
+		bri	ex9
+
+		/* Get the PGD for the current thread. */
+	ex8:
+		/* get current task address */
+		addi	r4 ,CURRENT_TASK, TOPHYS(0);
+		lwi	r4, r4, TASK_THREAD+PGDIR
+	ex9:
+		tophys(r4,r4)
+		BSRLI(r5,r3,20)		/* Create L1 (pgdir/pmd) address */
+		andi	r5, r5, 0xffc
+/* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
+		or	r4, r4, r5
+		lwi	r4, r4, 0		/* Get L1 entry */
+		andi	r5, r4, 0xfffff000 /* Extract L2 (pte) base address */
+		beqi	r5, ex10		/* Bail if no table */
+
+		tophys(r5,r5)
+		BSRLI(r6,r3,10)			/* Compute PTE address */
+		andi	r6, r6, 0xffc
+		andi	r5, r5, 0xfffff003
+		or	r5, r5, r6
+		lwi	r4, r5, 0		/* Get Linux PTE */
+
+		andi	r6, r4, _PAGE_PRESENT
+		beqi	r6, ex7
+
+		ori	r4, r4, _PAGE_ACCESSED
+		swi	r4, r5, 0
+
+		/* Most of the Linux PTE is ready to load into the TLB LO.
+		 * We set ZSEL, where only the LS-bit determines user access.
+		 * We set execute, because we don't have the granularity to
+		 * properly set this at the page level (Linux problem).
+		 * If shared is set, we cause a zero PID->TID load.
+		 * Many of these bits are software only. Bits we don't set
+		 * here we (properly should) assume have the appropriate value.
+		 */
+		andni	r4, r4, 0x0ce2		/* Make sure 20, 21 are zero */
+
+		bri	finish_tlb_load
+	ex10:
+		/* The bailout. Restore registers to pre-exception conditions
+		 * and call the heavyweights to help us out.
+		 */
+		mts	rpid, r11
+		nop
+		bri 4
+		RESTORE_STATE;
+		bri	page_fault_instr_trap
+
+/* Both the instruction and data TLB miss get to this point to load the TLB.
+ *	r3 - EA of fault
+ *	r4 - TLB LO (info from Linux PTE)
+ *	r5, r6 - available to use
+ *	PID - loaded with proper value when we get here
+ *	Upon exit, we reload everything and RFI.
+ * A common place to load the TLB.
+ */
+	tlb_index:
+		.long	1 /* MS: storing last used tlb index */
+	finish_tlb_load:
+		/* MS: load the last used TLB index. */
+		lwi	r5, r0, TOPHYS(tlb_index)
+		addik	r5, r5, 1 /* MS: inc tlb_index -> use next one */
+
+/* MS: FIXME this is potential fault, because this is mask not count */
+		andi	r5, r5, (MICROBLAZE_TLB_SIZE-1)
+		ori	r6, r0, 1
+		cmp	r31, r5, r6
+		blti	r31, sem
+		addik	r5, r6, 1
+	sem:
+		/* MS: save back current TLB index */
+		swi	r5, r0, TOPHYS(tlb_index)
+
+		ori	r4, r4, _PAGE_HWEXEC	/* make it executable */
+		mts	rtlbx, r5		/* MS: save current TLB */
+		nop
+		mts	rtlblo,	r4		/* MS: save to TLB LO */
+		nop
+
+		/* Create EPN. This is the faulting address plus a static
+		 * set of bits. These are size, valid, E, U0, and ensure
+		 * bits 20 and 21 are zero.
+		 */
+		andi	r3, r3, 0xfffff000
+		ori	r3, r3, 0x0c0
+		mts	rtlbhi,	r3		/* Load TLB HI */
+		nop
+
+		/* Done...restore registers and get out of here. */
+	ex12:
+		mts	rpid, r11
+		nop
+		bri 4
+		RESTORE_STATE;
+		rted	r17, 0
+		nop
+
+	/* extern void giveup_fpu(struct task_struct *prev)
+	 *
+	 * The MicroBlaze processor may have an FPU, so this should not just
+	 * return: TBD.
+	 */
+	.globl giveup_fpu;
+	.align 4;
+	giveup_fpu:
+		bralid	r15,0			/* TBD */
+		nop
+
+	/* At present, this routine just hangs. - extern void abort(void) */
+	.globl abort;
+	.align 4;
+	abort:
+		br	r0
+
+	.globl set_context;
+	.align 4;
+	set_context:
+		mts	rpid, r5	/* Shadow TLBs are automatically */
+		nop
+		bri	4		/* flushed by changing PID */
+		rtsd	r15,8
+		nop
+
+#endif
 .end _hw_exception_handler
 
+#ifdef CONFIG_MMU
+/* Unaligned data access exception last on a 4k page for MMU.
+ * When this is called, we are in virtual mode with exceptions enabled
+ * and registers 1-13,15,17,18 saved.
+ *
+ * R3 = ESR
+ * R4 = EAR
+ * R7 = pointer to saved registers (struct pt_regs *regs)
+ *
+ * This handler perform the access, and returns via ret_from_exc.
+ */
+.global _unaligned_data_exception
+.ent _unaligned_data_exception
+_unaligned_data_exception:
+	andi	r8, r3, 0x3E0;	/* Mask and extract the register operand */
+	BSRLI(r8,r8,2);		/* r8 >> 2 = register operand * 8 */
+	andi	r6, r3, 0x400;	/* Extract ESR[S] */
+	bneid	r6, ex_sw_vm;
+	andi	r6, r3, 0x800;	/* Extract ESR[W] - delay slot */
+ex_lw_vm:
+	beqid	r6, ex_lhw_vm;
+load1:	lbui	r5, r4, 0;	/* Exception address in r4 - delay slot */
+/* Load a word, byte-by-byte from destination address and save it in tmp space*/
+	la	r6, r0, ex_tmp_data_loc_0;
+	sbi	r5, r6, 0;
+load2:	lbui	r5, r4, 1;
+	sbi	r5, r6, 1;
+load3:	lbui	r5, r4, 2;
+	sbi	r5, r6, 2;
+load4:	lbui	r5, r4, 3;
+	sbi	r5, r6, 3;
+	brid	ex_lw_tail_vm;
+/* Get the destination register value into r3 - delay slot */
+	lwi	r3, r6, 0;
+ex_lhw_vm:
+	/* Load a half-word, byte-by-byte from destination address and
+	 * save it in tmp space */
+	la	r6, r0, ex_tmp_data_loc_0;
+	sbi	r5, r6, 0;
+load5:	lbui	r5, r4, 1;
+	sbi	r5, r6, 1;
+	lhui	r3, r6, 0;	/* Get the destination register value into r3 */
+ex_lw_tail_vm:
+	/* Form load_word jump table offset (lw_table_vm + (8 * regnum)) */
+	addik	r5, r8, lw_table_vm;
+	bra	r5;
+ex_lw_end_vm:			/* Exception handling of load word, ends */
+	brai	ret_from_exc;
+ex_sw_vm:
+/* Form store_word jump table offset (sw_table_vm + (8 * regnum)) */
+	addik	r5, r8, sw_table_vm;
+	bra	r5;
+ex_sw_tail_vm:
+	la	r5, r0, ex_tmp_data_loc_0;
+	beqid	r6, ex_shw_vm;
+	swi	r3, r5, 0;	/* Get the word - delay slot */
+	/* Store the word, byte-by-byte into destination address */
+	lbui	r3, r5, 0;
+store1:	sbi	r3, r4, 0;
+	lbui	r3, r5, 1;
+store2:	sbi	r3, r4, 1;
+	lbui	r3, r5, 2;
+store3:	sbi	r3, r4, 2;
+	lbui	r3, r5, 3;
+	brid	ret_from_exc;
+store4:	sbi	r3, r4, 3;	/* Delay slot */
+ex_shw_vm:
+	/* Store the lower half-word, byte-by-byte into destination address */
+	lbui	r3, r5, 2;
+store5:	sbi	r3, r4, 0;
+	lbui	r3, r5, 3;
+	brid	ret_from_exc;
+store6:	sbi	r3, r4, 1;	/* Delay slot */
+ex_sw_end_vm:			/* Exception handling of store word, ends. */
+
+/* We have to prevent cases that get/put_user macros get unaligned pointer
+ * to bad page area. We have to find out which origin instruction caused it
+ * and called fixup for that origin instruction not instruction in unaligned
+ * handler */
+ex_unaligned_fixup:
+	ori	r5, r7, 0 /* setup pointer to pt_regs */
+	lwi	r6, r7, PT_PC; /* faulting address is one instruction above */
+	addik	r6, r6, -4 /* for finding proper fixup */
+	swi	r6, r7, PT_PC; /* a save back it to PT_PC */
+	addik	r7, r0, SIGSEGV
+	/* call bad_page_fault for finding aligned fixup, fixup address is saved
+	 * in PT_PC which is used as return address from exception */
+	la	r15, r0, ret_from_exc-8 /* setup return address */
+	brid	bad_page_fault
+	nop
+
+/* We prevent all load/store because it could failed any attempt to access */
+.section __ex_table,"a";
+	.word	load1,ex_unaligned_fixup;
+	.word	load2,ex_unaligned_fixup;
+	.word	load3,ex_unaligned_fixup;
+	.word	load4,ex_unaligned_fixup;
+	.word	load5,ex_unaligned_fixup;
+	.word	store1,ex_unaligned_fixup;
+	.word	store2,ex_unaligned_fixup;
+	.word	store3,ex_unaligned_fixup;
+	.word	store4,ex_unaligned_fixup;
+	.word	store5,ex_unaligned_fixup;
+	.word	store6,ex_unaligned_fixup;
+.previous;
+.end _unaligned_data_exception
+#endif /* CONFIG_MMU */
+
 ex_handler_unhandled:
 /* FIXME add handle function for unhandled exception - dump register */
 	bri 0
 
+/*
+ * hw_exception_handler Jump Table
+ * - Contains code snippets for each register that caused the unalign exception
+ * - Hence exception handler is NOT self-modifying
+ * - Separate table for load exceptions and store exceptions.
+ * - Each table is of size: (8 * 32) = 256 bytes
+ */
+
 .section .text
 .align 4
 lw_table:
@@ -407,7 +1044,11 @@
 lw_r28:		R3_TO_LWREG	(28);
 lw_r29:		R3_TO_LWREG	(29);
 lw_r30:		R3_TO_LWREG	(30);
+#ifdef CONFIG_MMU
+lw_r31: 	R3_TO_LWREG_V	(31);
+#else
 lw_r31:		R3_TO_LWREG	(31);
+#endif
 
 sw_table:
 sw_r0:		SWREG_TO_R3	(0);
@@ -441,7 +1082,81 @@
 sw_r28:		SWREG_TO_R3	(28);
 sw_r29:		SWREG_TO_R3	(29);
 sw_r30:		SWREG_TO_R3	(30);
+#ifdef CONFIG_MMU
+sw_r31:		SWREG_TO_R3_V	(31);
+#else
 sw_r31:		SWREG_TO_R3	(31);
+#endif
+
+#ifdef CONFIG_MMU
+lw_table_vm:
+lw_r0_vm:	R3_TO_LWREG_VM		(0);
+lw_r1_vm:	R3_TO_LWREG_VM_V	(1);
+lw_r2_vm:	R3_TO_LWREG_VM_V	(2);
+lw_r3_vm:	R3_TO_LWREG_VM_V	(3);
+lw_r4_vm:	R3_TO_LWREG_VM_V	(4);
+lw_r5_vm:	R3_TO_LWREG_VM_V	(5);
+lw_r6_vm:	R3_TO_LWREG_VM_V	(6);
+lw_r7_vm:	R3_TO_LWREG_VM_V	(7);
+lw_r8_vm:	R3_TO_LWREG_VM_V	(8);
+lw_r9_vm:	R3_TO_LWREG_VM_V	(9);
+lw_r10_vm:	R3_TO_LWREG_VM_V	(10);
+lw_r11_vm:	R3_TO_LWREG_VM_V	(11);
+lw_r12_vm:	R3_TO_LWREG_VM_V	(12);
+lw_r13_vm:	R3_TO_LWREG_VM_V	(13);
+lw_r14_vm:	R3_TO_LWREG_VM		(14);
+lw_r15_vm:	R3_TO_LWREG_VM_V	(15);
+lw_r16_vm:	R3_TO_LWREG_VM		(16);
+lw_r17_vm:	R3_TO_LWREG_VM_V	(17);
+lw_r18_vm:	R3_TO_LWREG_VM_V	(18);
+lw_r19_vm:	R3_TO_LWREG_VM		(19);
+lw_r20_vm:	R3_TO_LWREG_VM		(20);
+lw_r21_vm:	R3_TO_LWREG_VM		(21);
+lw_r22_vm:	R3_TO_LWREG_VM		(22);
+lw_r23_vm:	R3_TO_LWREG_VM		(23);
+lw_r24_vm:	R3_TO_LWREG_VM		(24);
+lw_r25_vm:	R3_TO_LWREG_VM		(25);
+lw_r26_vm:	R3_TO_LWREG_VM		(26);
+lw_r27_vm:	R3_TO_LWREG_VM		(27);
+lw_r28_vm:	R3_TO_LWREG_VM		(28);
+lw_r29_vm:	R3_TO_LWREG_VM		(29);
+lw_r30_vm:	R3_TO_LWREG_VM		(30);
+lw_r31_vm:	R3_TO_LWREG_VM_V	(31);
+
+sw_table_vm:
+sw_r0_vm:	SWREG_TO_R3_VM		(0);
+sw_r1_vm:	SWREG_TO_R3_VM_V	(1);
+sw_r2_vm:	SWREG_TO_R3_VM_V	(2);
+sw_r3_vm:	SWREG_TO_R3_VM_V	(3);
+sw_r4_vm:	SWREG_TO_R3_VM_V	(4);
+sw_r5_vm:	SWREG_TO_R3_VM_V	(5);
+sw_r6_vm:	SWREG_TO_R3_VM_V	(6);
+sw_r7_vm:	SWREG_TO_R3_VM_V	(7);
+sw_r8_vm:	SWREG_TO_R3_VM_V	(8);
+sw_r9_vm:	SWREG_TO_R3_VM_V	(9);
+sw_r10_vm:	SWREG_TO_R3_VM_V	(10);
+sw_r11_vm:	SWREG_TO_R3_VM_V	(11);
+sw_r12_vm:	SWREG_TO_R3_VM_V	(12);
+sw_r13_vm:	SWREG_TO_R3_VM_V	(13);
+sw_r14_vm:	SWREG_TO_R3_VM		(14);
+sw_r15_vm:	SWREG_TO_R3_VM_V	(15);
+sw_r16_vm:	SWREG_TO_R3_VM		(16);
+sw_r17_vm:	SWREG_TO_R3_VM_V	(17);
+sw_r18_vm:	SWREG_TO_R3_VM_V	(18);
+sw_r19_vm:	SWREG_TO_R3_VM		(19);
+sw_r20_vm:	SWREG_TO_R3_VM		(20);
+sw_r21_vm:	SWREG_TO_R3_VM		(21);
+sw_r22_vm:	SWREG_TO_R3_VM		(22);
+sw_r23_vm:	SWREG_TO_R3_VM		(23);
+sw_r24_vm:	SWREG_TO_R3_VM		(24);
+sw_r25_vm:	SWREG_TO_R3_VM		(25);
+sw_r26_vm:	SWREG_TO_R3_VM		(26);
+sw_r27_vm:	SWREG_TO_R3_VM		(27);
+sw_r28_vm:	SWREG_TO_R3_VM		(28);
+sw_r29_vm:	SWREG_TO_R3_VM		(29);
+sw_r30_vm:	SWREG_TO_R3_VM		(30);
+sw_r31_vm:	SWREG_TO_R3_VM_V	(31);
+#endif /* CONFIG_MMU */
 
 /* Temporary data structures used in the handler */
 .section .data
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/init_task.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,8 +18,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-EXPORT_SYMBOL(init_mm);
 
 union thread_union init_thread_union
 	__attribute__((__section__(".data.init_task"))) =
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/intc.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/intc.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/intc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/intc.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/irq.h>
 #include <asm/page.h>
 #include <linux/io.h>
+#include <linux/bug.h>
 
 #include <asm/prom.h>
 #include <asm/irq.h>
@@ -130,6 +131,7 @@
 		if (intc)
 			break;
 	}
+	BUG_ON(!intc);
 
 	intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL);
 	intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/irq.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,15 +30,6 @@
 }
 EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
 
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves.
- */
-void ack_bad_irq(unsigned int irq)
-{
-	printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
-}
-
 static u32 concurrent_irq;
 
 void do_IRQ(struct pt_regs *regs)
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/Makefile linux-libre-2.6.31-gnu/arch/microblaze/kernel/Makefile
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -15,5 +15,6 @@
 obj-$(CONFIG_SELFMOD)		+= selfmod.o
 obj-$(CONFIG_HEART_BEAT)	+= heartbeat.o
 obj-$(CONFIG_MODULES)		+= microblaze_ksyms.o module.o
+obj-$(CONFIG_MMU)		+= misc.o
 
-obj-y	+= entry$(MMUEXT).o
+obj-y	+= entry$(MMU).o
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/microblaze_ksyms.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/microblaze_ksyms.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/microblaze_ksyms.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/microblaze_ksyms.c	2009-09-09 18:13:59.000000000 -0400
@@ -45,3 +45,5 @@
 EXPORT_SYMBOL(__udivsi3);
 extern void __umodsi3(void);
 EXPORT_SYMBOL(__umodsi3);
+extern char *_ebss;
+EXPORT_SYMBOL_GPL(_ebss);
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/misc.S linux-libre-2.6.31-gnu/arch/microblaze/kernel/misc.S
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/misc.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/misc.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * Miscellaneous low-level MMU functions.
+ *
+ * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2008-2009 PetaLogix
+ * Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
+ *
+ * Derived from arch/ppc/kernel/misc.S
+ *
+ * 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/linkage.h>
+#include <linux/sys.h>
+#include <asm/unistd.h>
+#include <linux/errno.h>
+#include <asm/mmu.h>
+#include <asm/page.h>
+
+	.text
+/*
+ * Flush MMU TLB
+ *
+ * We avoid flushing the pinned 0, 1 and possibly 2 entries.
+ */
+.globl _tlbia;
+.align 4;
+_tlbia:
+	addik	r12, r0, 63 /* flush all entries (63 - 3) */
+	/* isync */
+_tlbia_1:
+	mts	rtlbx, r12
+	nop
+	mts	rtlbhi, r0 /* flush: ensure V is clear */
+	nop
+	addik	r11, r12, -2
+	bneid	r11, _tlbia_1 /* loop for all entries */
+	addik	r12, r12, -1
+	/* sync */
+	rtsd	r15, 8
+	nop
+
+/*
+ * Flush MMU TLB for a particular address (in r5)
+ */
+.globl _tlbie;
+.align 4;
+_tlbie:
+	mts	rtlbsx, r5 /* look up the address in TLB */
+	nop
+	mfs	r12, rtlbx /* Retrieve index */
+	nop
+	blti	r12, _tlbie_1 /* Check if found */
+	mts	rtlbhi, r0 /* flush: ensure V is clear */
+	nop
+_tlbie_1:
+	rtsd	r15, 8
+	nop
+
+/*
+ * Allocate TLB entry for early console
+ */
+.globl early_console_reg_tlb_alloc;
+.align 4;
+early_console_reg_tlb_alloc:
+	/*
+	 * Load a TLB entry for the UART, so that microblaze_progress() can use
+	 * the UARTs nice and early.  We use a 4k real==virtual mapping.
+	 */
+	ori	r4, r0, 63
+	mts	rtlbx, r4 /* TLB slot 2 */
+
+	or	r4,r5,r0
+	andi	r4,r4,0xfffff000
+	ori	r4,r4,(TLB_WR|TLB_I|TLB_M|TLB_G)
+
+	andi	r5,r5,0xfffff000
+	ori	r5,r5,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))
+
+	mts	rtlblo,r4 /* Load the data portion of the entry */
+	nop
+	mts	rtlbhi,r5 /* Load the tag portion of the entry */
+	nop
+	rtsd	r15, 8
+	nop
+
+/*
+ * Copy a whole page (4096 bytes).
+ */
+#define COPY_16_BYTES		\
+	lwi	r7, r6, 0;	\
+	lwi	r8, r6, 4;	\
+	lwi	r9, r6, 8;	\
+	lwi	r10, r6, 12;	\
+	swi	r7, r5, 0;	\
+	swi	r8, r5, 4;	\
+	swi	r9, r5, 8;	\
+	swi	r10, r5, 12
+
+
+/* FIXME DCACHE_LINE_BYTES (CONFIG_XILINX_MICROBLAZE0_DCACHE_LINE_LEN * 4)*/
+#define DCACHE_LINE_BYTES (4 * 4)
+
+.globl copy_page;
+.align 4;
+copy_page:
+	ori	r11, r0, (PAGE_SIZE/DCACHE_LINE_BYTES) - 1
+_copy_page_loop:
+	COPY_16_BYTES
+#if DCACHE_LINE_BYTES >= 32
+	COPY_16_BYTES
+#endif
+	addik	r6, r6, DCACHE_LINE_BYTES
+	addik	r5, r5, DCACHE_LINE_BYTES
+	bneid	r11, _copy_page_loop
+	addik	r11, r11, -1
+	rtsd	r15, 8
+	nop
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/module.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -57,7 +57,6 @@
 	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
 	Elf32_Sym *sym;
 	unsigned long int *location;
-	unsigned long int locoffs;
 	unsigned long int value;
 #if __GNUC__ < 4
 	unsigned long int old_value;
@@ -113,10 +112,12 @@
 			break;
 
 		case R_MICROBLAZE_64_PCREL:
-			locoffs = (location[0] & 0xFFFF) << 16 |
+#if __GNUC__ < 4
+			old_value = (location[0] & 0xFFFF) << 16 |
 				(location[1] & 0xFFFF);
-			value -= (unsigned long int)(location) + 4 +
-				locoffs;
+			value -= old_value;
+#endif
+			value -= (unsigned long int)(location) + 4;
 			location[0] = (location[0] & 0xFFFF0000) |
 					(value >> 16);
 			location[1] = (location[1] & 0xFFFF0000) |
@@ -125,6 +126,14 @@
 				value);
 			break;
 
+		case R_MICROBLAZE_32_PCREL_LO:
+			pr_debug("R_MICROBLAZE_32_PCREL_LO\n");
+			break;
+
+		case R_MICROBLAZE_64_NONE:
+			pr_debug("R_MICROBLAZE_NONE\n");
+			break;
+
 		case R_MICROBLAZE_NONE:
 			pr_debug("R_MICROBLAZE_NONE\n");
 			break;
@@ -133,7 +142,7 @@
 			printk(KERN_ERR "module %s: "
 				"Unknown relocation: %u\n",
 				module->name,
-				ELF32_R_TYPE(rela->r_info));
+				ELF32_R_TYPE(rela[i].r_info));
 			return -ENOEXEC;
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/process.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -126,9 +126,54 @@
 	else
 		childregs->r1 = ((unsigned long) ti) + THREAD_SIZE;
 
+#ifndef CONFIG_MMU
 	memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
 	ti->cpu_context.r1 = (unsigned long)childregs;
 	ti->cpu_context.msr = (unsigned long)childregs->msr;
+#else
+
+	/* if creating a kernel thread then update the current reg (we don't
+	 * want to use the parent's value when restoring by POP_STATE) */
+	if (kernel_mode(regs))
+		/* save new current on stack to use POP_STATE */
+		childregs->CURRENT_TASK = (unsigned long)p;
+	/* if returning to user then use the parent's value of this register */
+
+	/* if we're creating a new kernel thread then just zeroing all
+	 * the registers. That's OK for a brand new thread.*/
+	/* Pls. note that some of them will be restored in POP_STATE */
+	if (kernel_mode(regs))
+		memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
+	/* if this thread is created for fork/vfork/clone, then we want to
+	 * restore all the parent's context */
+	/* in addition to the registers which will be restored by POP_STATE */
+	else {
+		ti->cpu_context = *(struct cpu_context *)regs;
+		childregs->msr |= MSR_UMS;
+	}
+
+	/* FIXME STATE_SAVE_PT_OFFSET; */
+	ti->cpu_context.r1  = (unsigned long)childregs - STATE_SAVE_ARG_SPACE;
+	/* we should consider the fact that childregs is a copy of the parent
+	 * regs which were saved immediately after entering the kernel state
+	 * before enabling VM. This MSR will be restored in switch_to and
+	 * RETURN() and we want to have the right machine state there
+	 * specifically this state must have INTs disabled before and enabled
+	 * after performing rtbd
+	 * compose the right MSR for RETURN(). It will work for switch_to also
+	 * excepting for VM and UMS
+	 * don't touch UMS , CARRY and cache bits
+	 * right now MSR is a copy of parent one */
+	childregs->msr |= MSR_BIP;
+	childregs->msr &= ~MSR_EIP;
+	childregs->msr |= MSR_IE;
+	childregs->msr &= ~MSR_VM;
+	childregs->msr |= MSR_VMS;
+	childregs->msr |= MSR_EE; /* exceptions will be enabled*/
+
+	ti->cpu_context.msr = (childregs->msr|MSR_VM);
+	ti->cpu_context.msr &= ~MSR_UMS; /* switch_to to kernel mode */
+#endif
 	ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8;
 
 	if (clone_flags & CLONE_SETTLS)
@@ -137,6 +182,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_MMU
 /*
  * Return saved PC of a blocked thread.
  */
@@ -151,6 +197,7 @@
 	else
 		return ctx->r14;
 }
+#endif
 
 static void kernel_thread_helper(int (*fn)(void *), void *arg)
 {
@@ -173,6 +220,7 @@
 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
 			&regs, 0, NULL, NULL);
 }
+EXPORT_SYMBOL_GPL(kernel_thread);
 
 unsigned long get_wchan(struct task_struct *p)
 {
@@ -188,3 +236,14 @@
 	regs->r1 = usp;
 	regs->pt_mode = 0;
 }
+
+#ifdef CONFIG_MMU
+#include <linux/elfcore.h>
+/*
+ * Set up a thread for executing a new program
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+{
+	return 0; /* MicroBlaze has no separate FPU registers */
+}
+#endif /* CONFIG_MMU */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/prom.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/prom.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/prom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/prom.c	2009-09-09 18:13:59.000000000 -0400
@@ -509,12 +509,13 @@
 
 	prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
 	if (prop) {
-		initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
+		initrd_start = (unsigned long)
+					__va((u32)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));
+					__va((u32)of_read_ulong(prop, 1/4));
 			initrd_below_start_ok = 1;
 		} else {
 			initrd_start = 0;
@@ -563,7 +564,9 @@
 		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
 
 #ifdef CONFIG_CMDLINE
+#ifndef CONFIG_CMDLINE_FORCE
 	if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
+#endif
 		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 #endif /* CONFIG_CMDLINE */
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/setup.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,10 +42,6 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-#ifdef CONFIG_CMDLINE_FORCE
-	strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
-	strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
-#endif
 	*cmdline_p = cmd_line;
 
 	console_verbose();
@@ -102,14 +98,34 @@
 {
 	unsigned long *src, *dst = (unsigned long *)0x0;
 
+	/* If CONFIG_MTD_UCLINUX is defined, assume ROMFS is at the
+	 * end of kernel. There are two position which we want to check.
+	 * The first is __init_end and the second __bss_start.
+	 */
+#ifdef CONFIG_MTD_UCLINUX
+	int romfs_size;
+	unsigned int romfs_base;
+	char *old_klimit = klimit;
+
+	romfs_base = (ram ? ram : (unsigned int)&__init_end);
+	romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base));
+	if (!romfs_size) {
+		romfs_base = (unsigned int)&__bss_start;
+		romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base));
+	}
+
+	/* Move ROMFS out of BSS before clearing it */
+	if (romfs_size > 0) {
+		memmove(&_ebss, (int *)romfs_base, romfs_size);
+		klimit += romfs_size;
+	}
+#endif
+
 /* clearing bss section */
 	memset(__bss_start, 0, __bss_stop-__bss_start);
 	memset(_ssbss, 0, _esbss-_ssbss);
 
-	/*
-	 * Copy command line passed from bootloader, or use default
-	 * if none provided, or forced
-	 */
+	/* Copy command line passed from bootloader */
 #ifndef CONFIG_CMDLINE_BOOL
 	if (cmdline && cmdline[0] != '\0')
 		strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE);
@@ -122,31 +138,23 @@
 	setup_early_printk(NULL);
 #endif
 
-	early_printk("Ramdisk addr 0x%08x, FDT 0x%08x\n", ram, fdt);
-	printk(KERN_NOTICE "Found FDT at 0x%08x\n", fdt);
+	early_printk("Ramdisk addr 0x%08x, ", ram);
+	if (fdt)
+		early_printk("FDT at 0x%08x\n", fdt);
+	else
+		early_printk("Compiled-in FDT at 0x%08x\n",
+					(unsigned int)_fdt_start);
 
 #ifdef CONFIG_MTD_UCLINUX
-	{
-		int size;
-		unsigned int romfs_base;
-		romfs_base = (ram ? ram : (unsigned int)&__init_end);
-		/* if CONFIG_MTD_UCLINUX_EBSS is defined, assume ROMFS is at the
-		 * end of kernel, which is ROMFS_LOCATION defined above. */
-		size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base));
-		early_printk("Found romfs @ 0x%08x (0x%08x)\n",
-				romfs_base, size);
-		early_printk("#### klimit %p ####\n", klimit);
-		BUG_ON(size < 0); /* What else can we do? */
+	early_printk("Found romfs @ 0x%08x (0x%08x)\n",
+			romfs_base, romfs_size);
+	early_printk("#### klimit %p ####\n", old_klimit);
+	BUG_ON(romfs_size < 0); /* What else can we do? */
 
-		/* Use memmove to handle likely case of memory overlap */
-		early_printk("Moving 0x%08x bytes from 0x%08x to 0x%08x\n",
-			size, romfs_base, (unsigned)&_ebss);
-		memmove(&_ebss, (int *)romfs_base, size);
+	early_printk("Moved 0x%08x bytes from 0x%08x to 0x%08x\n",
+			romfs_size, romfs_base, (unsigned)&_ebss);
 
-		/* update klimit */
-		klimit += PAGE_ALIGN(size);
-		early_printk("New klimit: 0x%08x\n", (unsigned)klimit);
-	}
+	early_printk("New klimit: 0x%08x\n", (unsigned)klimit);
 #endif
 
 	for (src = __ivt_start; src < __ivt_end; src++, dst++)
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/signal.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/signal.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/signal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/signal.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
@@ -45,91 +44,8 @@
 
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
 
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
-{
-	sigset_t saveset;
-
-	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	siginitset(&current->blocked, mask);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->r3 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(regs, &saveset, 1))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
-		struct pt_regs *regs)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's. */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->r3 = -EINTR;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(regs, &saveset, 1))
-			return -EINTR;
-	}
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
-		struct old_sigaction *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-			__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-			__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-			__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-			__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
 
-asmlinkage int
+asmlinkage long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 		struct pt_regs *regs)
 {
@@ -139,7 +55,6 @@
 /*
  * Do a signal return; undo the signal stack.
  */
-
 struct sigframe {
 	struct sigcontext sc;
 	unsigned long extramask[_NSIG_WORDS-1];
@@ -152,8 +67,8 @@
 	unsigned long tramp[2];	/* signal trampoline */
 };
 
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
+static int restore_sigcontext(struct pt_regs *regs,
+				struct sigcontext __user *sc, int *rval_p)
 {
 	unsigned int err = 0;
 
@@ -176,46 +91,12 @@
 	return err;
 }
 
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
-{
-	struct sigframe *frame =
-			(struct sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE);
-
-	sigset_t set;
-	int rval;
-
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
-
-	if (__get_user(set.sig[0], &frame->sc.oldmask)
-		|| (_NSIG_WORDS > 1
-		&& __copy_from_user(&set.sig[1], &frame->extramask,
-					sizeof(frame->extramask))))
-		goto badframe;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (restore_sigcontext(regs, &frame->sc, &rval))
-		goto badframe;
-	return rval;
-
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 {
-	struct rt_sigframe *frame =
-			(struct rt_sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE);
+	struct rt_sigframe __user *frame =
+		(struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);
 
 	sigset_t set;
-	stack_t st;
 	int rval;
 
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
@@ -233,11 +114,10 @@
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
 		goto badframe;
 
-	if (__copy_from_user((void *)&st, &frame->uc.uc_stack, sizeof(st)))
-		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	 call it and ignore errors. */
-	do_sigaltstack(&st, NULL, regs->r1);
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1))
+		goto badframe;
 
 	return rval;
 
@@ -251,7 +131,7 @@
  */
 
 static int
-setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 		unsigned long mask)
 {
 	int err = 0;
@@ -278,7 +158,7 @@
 /*
  * Determine which stack to use..
  */
-static inline void *
+static inline void __user *
 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 {
 	/* Default to using normal stack */
@@ -287,87 +167,13 @@
 	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
-	return (void *)((sp - frame_size) & -8UL);
-}
-
-static void setup_frame(int sig, struct k_sigaction *ka,
-			sigset_t *set, struct pt_regs *regs)
-{
-	struct sigframe *frame;
-	int err = 0;
-	int signal;
-
-	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
-
-	signal = current_thread_info()->exec_domain
-		&& current_thread_info()->exec_domain->signal_invmap
-		&& sig < 32
-		? current_thread_info()->exec_domain->signal_invmap[sig]
-		: sig;
-
-	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
-
-	if (_NSIG_WORDS > 1) {
-		err |= __copy_to_user(frame->extramask, &set->sig[1],
-					sizeof(frame->extramask));
-	}
-
-	/* Set up to return from userspace. If provided, use a stub
-	 already in userspace. */
-	/* minus 8 is offset to cater for "rtsd r15,8" offset */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
-	} else {
-		/* Note, these encodings are _big endian_! */
-
-		/* addi r12, r0, __NR_sigreturn */
-		err |= __put_user(0x31800000 | __NR_sigreturn ,
-				frame->tramp + 0);
-		/* brki r14, 0x8 */
-		err |= __put_user(0xb9cc0008, frame->tramp + 1);
-
-		/* Return from sighandler will jump to the tramp.
-		 Negative 8 offset because return is rtsd r15, 8 */
-		regs->r15 = ((unsigned long)frame->tramp)-8;
-
-		__invalidate_cache_sigtramp((unsigned long)frame->tramp);
-	}
-
-	if (err)
-		goto give_sigsegv;
-
-	/* Set up registers for signal handler */
-	regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
-
-	/* Signal handler args: */
-	regs->r5 = signal; /* Arg 0: signum */
-	regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */
-
-	/* Offset of 4 to handle microblaze rtid r14, 0 */
-	regs->pc = (unsigned long)ka->sa.sa_handler;
-
-	set_fs(USER_DS);
-
-#ifdef DEBUG_SIG
-	printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
-		current->comm, current->pid, frame, regs->pc);
-#endif
-
-	return;
-
-give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	return (void __user *)((sp - frame_size) & -8UL);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			sigset_t *set, struct pt_regs *regs)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe __user *frame;
 	int err = 0;
 	int signal;
 
@@ -382,7 +188,8 @@
 		? current_thread_info()->exec_domain->signal_invmap[sig]
 		: sig;
 
-	err |= copy_siginfo_to_user(&frame->info, info);
+	if (info)
+		err |= copy_siginfo_to_user(&frame->info, info);
 
 	/* Create the ucontext. */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -399,21 +206,17 @@
 	/* Set up to return from userspace. If provided, use a stub
 	 already in userspace. */
 	/* minus 8 is offset to cater for "rtsd r15,8" */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
-	} else {
-		/* addi r12, r0, __NR_sigreturn */
-		err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
-				frame->tramp + 0);
-		/* brki r14, 0x8 */
-		err |= __put_user(0xb9cc0008, frame->tramp + 1);
+	/* addi r12, r0, __NR_sigreturn */
+	err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
+			frame->tramp + 0);
+	/* brki r14, 0x8 */
+	err |= __put_user(0xb9cc0008, frame->tramp + 1);
 
-		/* Return from sighandler will jump to the tramp.
-		 Negative 8 offset because return is rtsd r15, 8 */
-		regs->r15 = ((unsigned long)frame->tramp)-8;
+	/* Return from sighandler will jump to the tramp.
+	 Negative 8 offset because return is rtsd r15, 8 */
+	regs->r15 = ((unsigned long)frame->tramp)-8;
 
-		__invalidate_cache_sigtramp((unsigned long)frame->tramp);
-	}
+	__invalidate_cache_sigtramp((unsigned long)frame->tramp);
 
 	if (err)
 		goto give_sigsegv;
@@ -463,7 +266,15 @@
 	case -ERESTARTNOINTR:
 do_restart:
 		/* offset of 4 bytes to re-execute trap (brki) instruction */
+#ifndef CONFIG_MMU
 		regs->pc -= 4;
+#else
+		/* offset of 8 bytes required = 4 for rtbd
+		   offset, plus 4 for size of
+			"brki r14,8"
+		   instruction. */
+		regs->pc -= 8;
+#endif
 		break;
 	}
 }
@@ -472,7 +283,7 @@
  * OK, we're invoking a handler
  */
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
 		siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
@@ -480,7 +291,7 @@
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame(sig, ka, info, oldset, regs);
 	else
-		setup_frame(sig, ka, oldset, regs);
+		setup_rt_frame(sig, ka, NULL, oldset, regs);
 
 	if (ka->sa.sa_flags & SA_ONESHOT)
 		ka->sa.sa_handler = SIG_DFL;
@@ -493,6 +304,7 @@
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
 	}
+	return 1;
 }
 
 /*
@@ -523,7 +335,9 @@
 	if (kernel_mode(regs))
 		return 1;
 
-	if (!oldset)
+	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -531,13 +345,31 @@
 		/* Whee! Actually deliver the signal. */
 		if (in_syscall)
 			handle_restart(regs, &ka, 1);
-		handle_signal(signr, &ka, &info, oldset, regs);
+		if (handle_signal(signr, &ka, &info, oldset, regs)) {
+			/*
+			 * A signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TS_RESTORE_SIGMASK flag.
+			 */
+			current_thread_info()->status &=
+			    ~TS_RESTORE_SIGMASK;
+		}
 		return 1;
 	}
 
 	if (in_syscall)
 		handle_restart(regs, NULL, 0);
 
+	/*
+	 * If there's no signal to deliver, we just put the saved sigmask
+	 * back.
+	 */
+	if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+
 	/* Did we come from a system call? */
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/syscall_table.S linux-libre-2.6.31-gnu/arch/microblaze/kernel/syscall_table.S
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/syscall_table.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/syscall_table.S	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,11 @@
 	.long sys_restart_syscall	/* 0 - old "setup()" system call,
 					 * used for restarting */
 	.long sys_exit
-	.long sys_ni_syscall		/* was fork */
+#ifdef CONFIG_MMU
+	.long sys_fork_wrapper
+#else
+	.long sys_ni_syscall
+#endif
 	.long sys_read
 	.long sys_write
 	.long sys_open			/* 5 */
@@ -11,7 +15,7 @@
 	.long sys_creat
 	.long sys_link
 	.long sys_unlink		/* 10 */
-	.long sys_execve_wrapper
+	.long sys_execve
 	.long sys_chdir
 	.long sys_time
 	.long sys_mknod
@@ -67,12 +71,12 @@
 	.long sys_getppid
 	.long sys_getpgrp		/* 65 */
 	.long sys_setsid
-	.long sys_sigaction
+	.long sys_ni_syscall		/* sys_sigaction */
 	.long sys_sgetmask
 	.long sys_ssetmask
 	.long sys_setreuid		/* 70 */
 	.long sys_setregid
-	.long sys_sigsuspend_wrapper
+	.long sys_ni_syscall		/* sys_sigsuspend_wrapper */
 	.long sys_sigpending
 	.long sys_sethostname
 	.long sys_setrlimit		/* 75 */
@@ -117,10 +121,10 @@
 	.long sys_wait4
 	.long sys_swapoff		/* 115 */
 	.long sys_sysinfo
-	.long sys_ipc
+	.long sys_ni_syscall		/* old sys_ipc */
 	.long sys_fsync
-	.long sys_sigreturn_wrapper
-	.long sys_clone_wrapper		/* 120 */
+	.long sys_ni_syscall		/* sys_sigreturn_wrapper */
+	.long sys_clone		/* 120 */
 	.long sys_setdomainname
 	.long sys_newuname
 	.long sys_ni_syscall		/* modify_ldt */
@@ -190,7 +194,7 @@
 	.long sys_sendfile
 	.long sys_ni_syscall		/* reserved for streams1 */
 	.long sys_ni_syscall		/* reserved for streams2 */
-	.long sys_vfork_wrapper		/* 190 */
+	.long sys_vfork		/* 190 */
 	.long sys_getrlimit
 	.long sys_mmap2			/* mmap2 */
 	.long sys_truncate64
@@ -309,7 +313,7 @@
 	.long sys_fchmodat
 	.long sys_faccessat
 	.long sys_ni_syscall /* pselect6 */
-	.long sys_ni_syscall /* sys_ppoll */
+	.long sys_ppoll
 	.long sys_unshare		/* 310 */
 	.long sys_set_robust_list
 	.long sys_get_robust_list
@@ -365,3 +369,5 @@
 	.long sys_ni_syscall
 	.long sys_ni_syscall
 	.long sys_ni_syscall
+	.long sys_rt_tgsigqueueinfo	/* 365 */
+	.long sys_perf_counter_open
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/sys_microblaze.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/sys_microblaze.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/sys_microblaze.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/sys_microblaze.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
@@ -34,120 +33,21 @@
 #include <linux/unistd.h>
 
 #include <asm/syscalls.h>
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly. This will be remove with new toolchain.
- */
-asmlinkage int
-sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	ret = -EINVAL;
-	switch (call) {
-	case SEMOP:
-		ret = sys_semop(first, (struct sembuf *)ptr, second);
-		break;
-	case SEMGET:
-		ret = sys_semget(first, second, third);
-		break;
-	case SEMCTL:
-	{
-		union semun fourth;
-
-		if (!ptr)
-			break;
-		ret = (access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
-				|| (get_user(fourth.__pad, (void **)ptr)) ;
-		if (ret)
-			break;
-		ret = sys_semctl(first, second, third, fourth);
-		break;
-	}
-	case MSGSND:
-		ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third);
-		break;
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-
-			if (!ptr)
-				break;
-			ret = (access_ok(VERIFY_READ, ptr, sizeof(tmp))
-				? 0 : -EFAULT) || copy_from_user(&tmp,
-				(struct ipc_kludge *) ptr, sizeof(tmp));
-			if (ret)
-				break;
-			ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp,
-					third);
-			break;
-			}
-		default:
-			ret = sys_msgrcv(first, (struct msgbuf *) ptr,
-					second, fifth, third);
-			break;
-		}
-		break;
-	case MSGGET:
-		ret = sys_msgget((key_t) first, second);
-		break;
-	case MSGCTL:
-		ret = sys_msgctl(first, second, (struct msqid_ds *) ptr);
-		break;
-	case SHMAT:
-		switch (version) {
-		default: {
-			ulong raddr;
-			ret = access_ok(VERIFY_WRITE, (ulong *) third,
-					sizeof(ulong)) ? 0 : -EFAULT;
-			if (ret)
-				break;
-			ret = do_shmat(first, (char *) ptr, second, &raddr);
-			if (ret)
-				break;
-			ret = put_user(raddr, (ulong *) third);
-			break;
-			}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				break;
-			ret = do_shmat(first, (char *) ptr, second,
-					(ulong *) third);
-			break;
-		}
-		break;
-	case SHMDT:
-		ret = sys_shmdt((char *)ptr);
-		break;
-	case SHMGET:
-		ret = sys_shmget(first, second, third);
-		break;
-	case SHMCTL:
-		ret = sys_shmctl(first, second, (struct shmid_ds *) ptr);
-		break;
-	}
-	return ret;
-}
 
-asmlinkage int sys_vfork(struct pt_regs *regs)
+asmlinkage long microblaze_vfork(struct pt_regs *regs)
 {
 	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1,
 						regs, 0, NULL, NULL);
 }
 
-asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs)
+asmlinkage long microblaze_clone(int flags, unsigned long stack, struct pt_regs *regs)
 {
 	if (!stack)
 		stack = regs->r1;
 	return do_fork(flags, stack, regs, 0, NULL, NULL);
 }
 
-asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
+asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *argv,
 			char __user *__user *envp, struct pt_regs *regs)
 {
 	int error;
@@ -163,8 +63,8 @@
 	return error;
 }
 
-asmlinkage unsigned long
-sys_mmap2(unsigned long addr, size_t len,
+asmlinkage long
+sys_mmap2(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags,
 	unsigned long fd, unsigned long pgoff)
 {
@@ -189,18 +89,18 @@
 	return ret;
 }
 
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 			unsigned long prot, unsigned long flags,
-			unsigned long fd, off_t offset)
+			unsigned long fd, off_t pgoff)
 {
 	int err = -EINVAL;
 
-	if (offset & ~PAGE_MASK) {
+	if (pgoff & ~PAGE_MASK) {
 		printk(KERN_INFO "no pagemask in mmap\r\n");
 		goto out;
 	}
 
-	err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+	err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
 out:
 	return err;
 }
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/timer.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/timer.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/timer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/timer.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
+#include <linux/bug.h>
 #include <asm/cpuinfo.h>
 #include <asm/setup.h>
 #include <asm/prom.h>
@@ -234,6 +235,7 @@
 		if (timer)
 			break;
 	}
+	BUG_ON(!timer);
 
 	timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL);
 	timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/traps.c linux-libre-2.6.31-gnu/arch/microblaze/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,14 +22,6 @@
 	__enable_hw_exceptions();
 }
 
-void __bad_xchg(volatile void *ptr, int size)
-{
-	printk(KERN_INFO "xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n",
-		__builtin_return_address(0), ptr, size);
-	BUG();
-}
-EXPORT_SYMBOL(__bad_xchg);
-
 static int kstack_depth_to_print = 24;
 
 static int __init kstack_setup(char *s)
@@ -105,3 +97,37 @@
 	show_stack(NULL, NULL);
 }
 EXPORT_SYMBOL(dump_stack);
+
+#ifdef CONFIG_MMU
+void __bug(const char *file, int line, void *data)
+{
+	if (data)
+		printk(KERN_CRIT "kernel BUG at %s:%d (data = %p)!\n",
+			file, line, data);
+	else
+		printk(KERN_CRIT "kernel BUG at %s:%d!\n", file, line);
+
+	machine_halt();
+}
+
+int bad_trap(int trap_num, struct pt_regs *regs)
+{
+	printk(KERN_CRIT
+		"unimplemented trap %d called at 0x%08lx, pid %d!\n",
+		trap_num, regs->pc, current->pid);
+	return -ENOSYS;
+}
+
+int debug_trap(struct pt_regs *regs)
+{
+	int i;
+	printk(KERN_CRIT "debug trap\n");
+	for (i = 0; i < 32; i++) {
+		/* printk("r%i:%08X\t",i,regs->gpr[i]); */
+		if ((i % 4) == 3)
+			printk(KERN_CRIT "\n");
+	}
+	printk(KERN_CRIT "pc:%08lX\tmsr:%08lX\n", regs->pc, regs->msr);
+	return -ENOSYS;
+}
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/kernel/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/microblaze/kernel/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/microblaze/kernel/vmlinux.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/kernel/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -17,8 +17,7 @@
 jiffies = jiffies_64 + 4;
 
 SECTIONS {
-	. = CONFIG_KERNEL_BASE_ADDR;
-
+	. = CONFIG_KERNEL_START;
 	.text : {
 		_text = . ;
 		_stext = . ;
@@ -63,7 +62,8 @@
 
 	_sdata = . ;
 	.data ALIGN (4096) : { /* page aligned when MMU used - origin 0x4 */
-		*(.data)
+		DATA_DATA
+		CONSTRUCTORS
 	}
 	. = ALIGN(32);
 	.data.cacheline_aligned : { *(.data.cacheline_aligned) }
@@ -99,13 +99,13 @@
 	. = ALIGN(4096);
 	.init.text : {
 		_sinittext = . ;
-		*(.init.text)
-		*(.exit.text)
-		*(.exit.data)
+		INIT_TEXT
 		_einittext = .;
 	}
 
-	.init.data : { *(.init.data) }
+	.init.data : {
+		INIT_DATA
+	}
 
 	. = ALIGN(4);
 	.init.ivt : {
@@ -132,6 +132,8 @@
 		__con_initcall_end = .;
 	}
 
+	SECURITY_INIT
+
 	__init_end_before_initramfs = .;
 
 	.init.ramfs ALIGN(4096) : {
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/lib/checksum.c linux-libre-2.6.31-gnu/arch/microblaze/lib/checksum.c
--- linux-libre-2.6.30-gnu/arch/microblaze/lib/checksum.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/lib/checksum.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-/*
- *
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		IP/TCP/UDP checksumming routines
- *
- * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
- *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *		Tom May, <ftom@netcom.com>
- *		Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
- *		Lots of code moved from tcp.c and ip.c; see those files
- *		for more names.
- *
- * 03/02/96	Jes Sorensen, Andreas Schwab, Roman Hodek:
- *		Fixed some nasty bugs, causing some horrible crashes.
- *		A: At some points, the sum (%0) was used as
- *		length-counter instead of the length counter
- *		(%1). Thanks to Roman Hodek for pointing this out.
- *		B: GCC seems to mess up if one uses too many
- *		data-registers to hold input values and one tries to
- *		specify d0 and d1 as scratch registers. Letting gcc
- *		choose these registers itself solves the problem.
- *
- *		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.
- */
-
-/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
- kills, so most of the assembly has to go. */
-
-#include <net/checksum.h>
-#include <asm/checksum.h>
-#include <linux/module.h>
-
-static inline unsigned short from32to16(unsigned long x)
-{
-	/* add up 16-bit and 16-bit for 16+c bit */
-	x = (x & 0xffff) + (x >> 16);
-	/* add up carry.. */
-	x = (x & 0xffff) + (x >> 16);
-	return x;
-}
-
-static unsigned int do_csum(const unsigned char *buff, int len)
-{
-	int odd, count;
-	unsigned long result = 0;
-
-	if (len <= 0)
-		goto out;
-	odd = 1 & (unsigned long) buff;
-	if (odd) {
-		result = *buff;
-		len--;
-		buff++;
-	}
-	count = len >> 1;		/* nr of 16-bit words.. */
-	if (count) {
-		if (2 & (unsigned long) buff) {
-			result += *(unsigned short *) buff;
-			count--;
-			len -= 2;
-			buff += 2;
-		}
-		count >>= 1;		/* nr of 32-bit words.. */
-		if (count) {
-			unsigned long carry = 0;
-			do {
-				unsigned long w = *(unsigned long *) buff;
-				count--;
-				buff += 4;
-				result += carry;
-				result += w;
-				carry = (w > result);
-			} while (count);
-			result += carry;
-			result = (result & 0xffff) + (result >> 16);
-		}
-		if (len & 2) {
-			result += *(unsigned short *) buff;
-			buff += 2;
-		}
-	}
-	if (len & 1)
-		result += (*buff << 8);
-	result = from32to16(result);
-	if (odd)
-		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
-	return result;
-}
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	return (__force __sum16)~do_csum(iph, ihl*4);
-}
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
-	unsigned int result = do_csum(buff, len);
-
-	/* add in old sum, and carry.. */
-	result += sum;
-	if (sum > result)
-		result += 1;
-	return result;
-}
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const unsigned char *buff, int len)
-{
-	return ~do_csum(buff, len);
-}
-EXPORT_SYMBOL(ip_compute_csum);
-
-/*
- * copy from fs while checksumming, otherwise like csum_partial
- */
-__wsum
-csum_partial_copy_from_user(const char __user *src, char *dst, int len,
-						int sum, int *csum_err)
-{
-	if (csum_err)
-		*csum_err = 0;
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
-EXPORT_SYMBOL(csum_partial_copy_from_user);
-
-/*
- * copy from ds while checksumming, otherwise like csum_partial
- */
-__wsum
-csum_partial_copy(const char *src, char *dst, int len, int sum)
-{
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
-EXPORT_SYMBOL(csum_partial_copy);
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/lib/Makefile linux-libre-2.6.31-gnu/arch/microblaze/lib/Makefile
--- linux-libre-2.6.30-gnu/arch/microblaze/lib/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/lib/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile
 #
 
-lib-y :=  memset.o checksum.o
+lib-y :=  memset.o
 
 ifeq ($(CONFIG_OPT_LIB_ASM),y)
 lib-y += fastcopy.o
@@ -10,4 +10,5 @@
 lib-y += memcpy.o memmove.o
 endif
 
-lib-y +=  uaccess.o
+lib-$(CONFIG_NO_MMU) += uaccess.o
+lib-$(CONFIG_MMU) += uaccess_old.o
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/lib/memcpy.c linux-libre-2.6.31-gnu/arch/microblaze/lib/memcpy.c
--- linux-libre-2.6.30-gnu/arch/microblaze/lib/memcpy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/lib/memcpy.c	2009-09-09 18:13:59.000000000 -0400
@@ -154,8 +154,3 @@
 }
 EXPORT_SYMBOL(memcpy);
 #endif /* __HAVE_ARCH_MEMCPY */
-
-void *cacheable_memcpy(void *d, const void *s, __kernel_size_t c)
-{
-	return memcpy(d, s, c);
-}
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/lib/uaccess_old.S linux-libre-2.6.31-gnu/arch/microblaze/lib/uaccess_old.S
--- linux-libre-2.6.30-gnu/arch/microblaze/lib/uaccess_old.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/lib/uaccess_old.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 PetaLogix
+ * Copyright (C) 2007 LynuxWorks, Inc.
+ *
+ * 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/errno.h>
+#include <linux/linkage.h>
+
+/*
+ * int __strncpy_user(char *to, char *from, int len);
+ *
+ * Returns:
+ *  -EFAULT  for an exception
+ *  len      if we hit the buffer limit
+ *  bytes copied
+ */
+
+	.text
+.globl __strncpy_user;
+.align 4;
+__strncpy_user:
+
+	/*
+	 * r5 - to
+	 * r6 - from
+	 * r7 - len
+	 * r3 - temp count
+	 * r4 - temp val
+	 */
+	addik	r3,r7,0		/* temp_count = len */
+	beqi	r3,3f
+1:
+	lbu	r4,r6,r0
+	sb	r4,r5,r0
+
+	addik	r3,r3,-1
+	beqi	r3,2f		/* break on len */
+
+	addik	r5,r5,1
+	bneid	r4,1b
+	addik	r6,r6,1		/* delay slot */
+	addik	r3,r3,1		/* undo "temp_count--" */
+2:
+	rsubk	r3,r3,r7	/* temp_count = len - temp_count */
+3:
+	rtsd	r15,8
+	nop
+
+
+	.section	.fixup, "ax"
+	.align	2
+4:
+	brid	3b
+	addik	r3,r0, -EFAULT
+
+	.section	__ex_table, "a"
+	.word	1b,4b
+
+/*
+ * int __strnlen_user(char __user *str, int maxlen);
+ *
+ * Returns:
+ *  0 on error
+ *  maxlen + 1  if no NUL byte found within maxlen bytes
+ *  size of the string (including NUL byte)
+ */
+
+	.text
+.globl __strnlen_user;
+.align 4;
+__strnlen_user:
+	addik	r3,r6,0
+	beqi	r3,3f
+1:
+	lbu	r4,r5,r0
+	beqid	r4,2f		/* break on NUL */
+	addik	r3,r3,-1	/* delay slot */
+
+	bneid	r3,1b
+	addik	r5,r5,1		/* delay slot */
+
+	addik	r3,r3,-1	/* for break on len */
+2:
+	rsubk	r3,r3,r6
+3:
+	rtsd	r15,8
+	nop
+
+
+	.section	.fixup,"ax"
+4:
+	brid	3b
+	addk	r3,r0,r0
+
+	.section	__ex_table,"a"
+	.word	1b,4b
+
+/*
+ * int __copy_tofrom_user(char *to, char *from, int len)
+ * Return:
+ *   0 on success
+ *   number of not copied bytes on error
+ */
+	.text
+.globl __copy_tofrom_user;
+.align 4;
+__copy_tofrom_user:
+	/*
+	 * r5 - to
+	 * r6 - from
+	 * r7, r3 - count
+	 * r4 - tempval
+	 */
+	addik	r3,r7,0
+	beqi	r3,3f
+1:
+	lbu	r4,r6,r0
+	addik	r6,r6,1
+2:
+	sb	r4,r5,r0
+	addik	r3,r3,-1
+	bneid	r3,1b
+	addik	r5,r5,1		/* delay slot */
+3:
+	rtsd	r15,8
+	nop
+
+
+	.section	__ex_table,"a"
+	.word	1b,3b,2b,3b
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/Makefile linux-libre-2.6.31-gnu/arch/microblaze/Makefile
--- linux-libre-2.6.30-gnu/arch/microblaze/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,15 +1,21 @@
+ifeq ($(CONFIG_MMU),y)
+UTS_SYSNAME = -DUTS_SYSNAME=\"Linux\"
+else
 UTS_SYSNAME = -DUTS_SYSNAME=\"uClinux\"
+endif
 
 # What CPU vesion are we building for, and crack it open
 # as major.minor.rev
-CPU_VER=$(subst ",,$(CONFIG_XILINX_MICROBLAZE0_HW_VER) )
-CPU_MAJOR=$(shell echo $(CPU_VER) | cut -d '.' -f 1)
-CPU_MINOR=$(shell echo $(CPU_VER) | cut -d '.' -f 2)
-CPU_REV=$(shell echo $(CPU_VER) | cut -d '.' -f 3)
+CPU_VER   := $(shell echo $(CONFIG_XILINX_MICROBLAZE0_HW_VER))
+CPU_MAJOR := $(shell echo $(CPU_VER) | cut -d '.' -f 1)
+CPU_MINOR := $(shell echo $(CPU_VER) | cut -d '.' -f 2)
+CPU_REV   := $(shell echo $(CPU_VER) | cut -d '.' -f 3)
 
 export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV
 
 # Use cpu-related CONFIG_ vars to set compile options.
+# The various CONFIG_XILINX cpu features options are integers 0/1/2...
+# rather than bools y/n
 
 # Work out HW multipler support.  This is icky.
 # 1. Spartan2 has no HW multiplers.
@@ -30,28 +36,29 @@
 
 CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER))
 
-# The various CONFIG_XILINX cpu features options are integers 0/1/2...
-# rather than bools y/n
-
 # r31 holds current when in kernel mode
-CFLAGS_KERNEL += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
+KBUILD_KERNEL += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
 
-LDFLAGS_BLOB := --format binary --oformat elf32-microblaze
+LDFLAGS		:=
+LDFLAGS_vmlinux	:=
 
-LIBGCC := $(shell $(CC) $(CFLAGS_KERNEL) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_KERNEL) -print-libgcc-file-name)
 
-head-y		:= arch/microblaze/kernel/head.o
-libs-y		+= arch/microblaze/lib/ $(LIBGCC)
-core-y		+= arch/microblaze/kernel/ arch/microblaze/mm/ \
-		   arch/microblaze/platform/
+head-y := arch/microblaze/kernel/head.o
+libs-y += arch/microblaze/lib/
+libs-y += $(LIBGCC)
+core-y += arch/microblaze/kernel/
+core-y += arch/microblaze/mm/
+core-y += arch/microblaze/platform/
 
-boot := arch/$(ARCH)/boot
+boot := arch/microblaze/boot
 
 # defines filename extension depending memory management type
 ifeq ($(CONFIG_MMU),)
-MMUEXT		:= -nommu
+MMU := -nommu
 endif
-export	MMUEXT
+
+export MMU
 
 all: linux.bin
 
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/mm/fault.c linux-libre-2.6.31-gnu/arch/microblaze/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/microblaze/mm/fault.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,299 @@
+/*
+ *  arch/microblaze/mm/fault.c
+ *
+ *    Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
+ *
+ *  Derived from "arch/ppc/mm/fault.c"
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Derived from "arch/i386/mm/fault.c"
+ *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
+ *  Modified by Cort Dougan and Paul Mackerras.
+ *
+ * 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/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <asm/exceptions.h>
+
+#if defined(CONFIG_KGDB)
+int debugger_kernel_faults = 1;
+#endif
+
+static unsigned long pte_misses;	/* updated by do_page_fault() */
+static unsigned long pte_errors;	/* updated by do_page_fault() */
+
+/*
+ * Check whether the instruction at regs->pc is a store using
+ * an update addressing form which will update r1.
+ */
+static int store_updates_sp(struct pt_regs *regs)
+{
+	unsigned int inst;
+
+	if (get_user(inst, (unsigned int *)regs->pc))
+		return 0;
+	/* check for 1 in the rD field */
+	if (((inst >> 21) & 0x1f) != 1)
+		return 0;
+	/* check for store opcodes */
+	if ((inst & 0xd0000000) == 0xd0000000)
+		return 1;
+	return 0;
+}
+
+
+/*
+ * bad_page_fault is called when we have a bad access from the kernel.
+ * It is called from do_page_fault above and from some of the procedures
+ * in traps.c.
+ */
+void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
+{
+	const struct exception_table_entry *fixup;
+/* MS: no context */
+	/* Are we prepared to handle this fault?  */
+	fixup = search_exception_tables(regs->pc);
+	if (fixup) {
+		regs->pc = fixup->fixup;
+		return;
+	}
+
+	/* kernel has accessed a bad area */
+#if defined(CONFIG_KGDB)
+	if (debugger_kernel_faults)
+		debugger(regs);
+#endif
+	die("kernel access of bad area", regs, sig);
+}
+
+/*
+ * The error_code parameter is ESR for a data fault,
+ * 0 for an instruction fault.
+ */
+void do_page_fault(struct pt_regs *regs, unsigned long address,
+		   unsigned long error_code)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	siginfo_t info;
+	int code = SEGV_MAPERR;
+	int is_write = error_code & ESR_S;
+	int fault;
+
+	regs->ear = address;
+	regs->esr = error_code;
+
+	/* On a kernel SLB miss we can only check for a valid exception entry */
+	if (kernel_mode(regs) && (address >= TASK_SIZE)) {
+		printk(KERN_WARNING "kernel task_size exceed");
+		_exception(SIGSEGV, regs, code, address);
+	}
+
+	/* for instr TLB miss and instr storage exception ESR_S is undefined */
+	if ((error_code & 0x13) == 0x13 || (error_code & 0x11) == 0x11)
+		is_write = 0;
+
+#if defined(CONFIG_KGDB)
+	if (debugger_fault_handler && regs->trap == 0x300) {
+		debugger_fault_handler(regs);
+		return;
+	}
+#endif /* CONFIG_KGDB */
+
+	if (in_atomic() || !mm) {
+		if (kernel_mode(regs))
+			goto bad_area_nosemaphore;
+
+		/* in_atomic() in user mode is really bad,
+		   as is current->mm == NULL. */
+		printk(KERN_EMERG "Page fault in user mode with "
+		       "in_atomic(), mm = %p\n", mm);
+		printk(KERN_EMERG "r15 = %lx  MSR = %lx\n",
+		       regs->r15, regs->msr);
+		die("Weird page fault", regs, SIGSEGV);
+	}
+
+	/* When running in the kernel we expect faults to occur only to
+	 * addresses in user space.  All other faults represent errors in the
+	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+	 * erroneous fault occurring in a code path which already holds mmap_sem
+	 * we will deadlock attempting to validate the fault against the
+	 * address space.  Luckily the kernel only validly references user
+	 * space from well defined areas of code, which are listed in the
+	 * exceptions table.
+	 *
+	 * As the vast majority of faults will be valid we will only perform
+	 * the source reference check when there is a possibility of a deadlock.
+	 * Attempt to lock the address space, if we cannot we then validate the
+	 * source.  If this is invalid we can skip the address space check,
+	 * thus avoiding the deadlock.
+	 */
+	if (!down_read_trylock(&mm->mmap_sem)) {
+		if (kernel_mode(regs) && !search_exception_tables(regs->pc))
+			goto bad_area_nosemaphore;
+
+		down_read(&mm->mmap_sem);
+	}
+
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+
+	if (vma->vm_start <= address)
+		goto good_area;
+
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+
+	if (!is_write)
+		goto bad_area;
+
+	/*
+	 * N.B. The ABI allows programs to access up to
+	 * a few hundred bytes below the stack pointer (TBD).
+	 * The kernel signal delivery code writes up to about 1.5kB
+	 * below the stack pointer (r1) before decrementing it.
+	 * The exec code can write slightly over 640kB to the stack
+	 * before setting the user r1.  Thus we allow the stack to
+	 * expand to 1MB without further checks.
+	 */
+	if (address + 0x100000 < vma->vm_end) {
+
+		/* get user regs even if this fault is in kernel mode */
+		struct pt_regs *uregs = current->thread.regs;
+		if (uregs == NULL)
+			goto bad_area;
+
+		/*
+		 * A user-mode access to an address a long way below
+		 * the stack pointer is only valid if the instruction
+		 * is one which would update the stack pointer to the
+		 * address accessed if the instruction completed,
+		 * i.e. either stwu rs,n(r1) or stwux rs,r1,rb
+		 * (or the byte, halfword, float or double forms).
+		 *
+		 * If we don't check this then any write to the area
+		 * between the last mapped region and the stack will
+		 * expand the stack rather than segfaulting.
+		 */
+		if (address + 2048 < uregs->r1
+			&& (kernel_mode(regs) || !store_updates_sp(regs)))
+				goto bad_area;
+	}
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+good_area:
+	code = SEGV_ACCERR;
+
+	/* a write */
+	if (is_write) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+	/* a read */
+	} else {
+		/* protection fault */
+		if (error_code & 0x08000000)
+			goto bad_area;
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto bad_area;
+	}
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+survive:
+	fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0);
+	if (unlikely(fault & VM_FAULT_ERROR)) {
+		if (fault & VM_FAULT_OOM)
+			goto out_of_memory;
+		else if (fault & VM_FAULT_SIGBUS)
+			goto do_sigbus;
+		BUG();
+	}
+	if (fault & VM_FAULT_MAJOR)
+		current->maj_flt++;
+	else
+		current->min_flt++;
+	up_read(&mm->mmap_sem);
+	/*
+	 * keep track of tlb+htab misses that are good addrs but
+	 * just need pte's created via handle_mm_fault()
+	 * -- Cort
+	 */
+	pte_misses++;
+	return;
+
+bad_area:
+	up_read(&mm->mmap_sem);
+
+bad_area_nosemaphore:
+	pte_errors++;
+
+	/* User mode accesses cause a SIGSEGV */
+	if (user_mode(regs)) {
+		_exception(SIGSEGV, regs, code, address);
+/*		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = code;
+		info.si_addr = (void *) address;
+		force_sig_info(SIGSEGV, &info, current);*/
+		return;
+	}
+
+	bad_page_fault(regs, address, SIGSEGV);
+	return;
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+	if (current->pid == 1) {
+		yield();
+		down_read(&mm->mmap_sem);
+		goto survive;
+	}
+	up_read(&mm->mmap_sem);
+	printk(KERN_WARNING "VM: killing process %s\n", current->comm);
+	if (user_mode(regs))
+		do_exit(SIGKILL);
+	bad_page_fault(regs, address, SIGKILL);
+	return;
+
+do_sigbus:
+	up_read(&mm->mmap_sem);
+	if (user_mode(regs)) {
+		info.si_signo = SIGBUS;
+		info.si_errno = 0;
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void __user *)address;
+		force_sig_info(SIGBUS, &info, current);
+		return;
+	}
+	bad_page_fault(regs, address, SIGBUS);
+}
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/mm/init.c linux-libre-2.6.31-gnu/arch/microblaze/mm/init.c
--- linux-libre-2.6.30-gnu/arch/microblaze/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,16 @@
 #include <asm/sections.h>
 #include <asm/tlb.h>
 
+#ifndef CONFIG_MMU
 unsigned int __page_offset;
-/* EXPORT_SYMBOL(__page_offset); */
+EXPORT_SYMBOL(__page_offset);
+
+#else
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+int mem_init_done;
+static int init_bootmem_done;
+#endif /* CONFIG_MMU */
 
 char *klimit = _end;
 
@@ -32,28 +40,26 @@
  * Initialize the bootmem system and give it all the memory we
  * have available.
  */
-unsigned int memory_start;
-unsigned int memory_end; /* due to mm/nommu.c */
-unsigned int memory_size;
+unsigned long memory_start;
+unsigned long memory_end; /* due to mm/nommu.c */
+unsigned long memory_size;
 
 /*
  * paging_init() sets up the page tables - in fact we've already done this.
  */
 static void __init paging_init(void)
 {
-	int i;
 	unsigned long zones_size[MAX_NR_ZONES];
 
+	/* Clean every zones */
+	memset(zones_size, 0, sizeof(zones_size));
+
 	/*
 	 * old: we can DMA to/from any address.put all page into ZONE_DMA
 	 * We use only ZONE_NORMAL
 	 */
 	zones_size[ZONE_NORMAL] = max_mapnr;
 
-	/* every other zones are empty */
-	for (i = 1; i < MAX_NR_ZONES; i++)
-		zones_size[i] = 0;
-
 	free_area_init(zones_size);
 }
 
@@ -61,6 +67,7 @@
 {
 	int i;
 	unsigned long map_size;
+#ifndef CONFIG_MMU
 	u32 kernel_align_start, kernel_align_size;
 
 	/* Find main memory where is the kernel */
@@ -73,15 +80,15 @@
 			memory_size = memory_end - memory_start;
 			PAGE_OFFSET = memory_start;
 			printk(KERN_INFO "%s: Main mem: 0x%x-0x%x, "
-				"size 0x%08x\n", __func__, memory_start,
-						memory_end, memory_size);
+				"size 0x%08x\n", __func__, (u32) memory_start,
+					(u32) memory_end, (u32) memory_size);
 			break;
 		}
 	}
 
 	if (!memory_start || !memory_end) {
 		panic("%s: Missing memory setting 0x%08x-0x%08x\n",
-			__func__, memory_start, memory_end);
+			__func__, (u32) memory_start, (u32) memory_end);
 	}
 
 	/* reservation of region where is the kernel */
@@ -93,6 +100,7 @@
 		__func__, kernel_align_start, kernel_align_start
 			+ kernel_align_size, kernel_align_size);
 
+#endif
 	/*
 	 * Kernel:
 	 * start: base phys address of kernel - page align
@@ -121,10 +129,14 @@
 	 * for 4GB of memory, using 4kB pages), plus 1 page
 	 * (in case the address isn't page-aligned).
 	 */
-	map_size = init_bootmem_node(NODE_DATA(0), PFN_UP(TOPHYS((u32)_end)),
+#ifndef CONFIG_MMU
+	map_size = init_bootmem_node(NODE_DATA(0), PFN_UP(TOPHYS((u32)klimit)),
 					min_low_pfn, max_low_pfn);
-
-	lmb_reserve(PFN_UP(TOPHYS((u32)_end)) << PAGE_SHIFT, map_size);
+#else
+	map_size = init_bootmem_node(&contig_page_data,
+		PFN_UP(TOPHYS((u32)klimit)), min_low_pfn, max_low_pfn);
+#endif
+	lmb_reserve(PFN_UP(TOPHYS((u32)klimit)) << PAGE_SHIFT, map_size);
 
 	/* free bootmem is whole main memory */
 	free_bootmem(memory_start, memory_size);
@@ -137,6 +149,9 @@
 		reserve_bootmem(lmb.reserved.region[i].base,
 			lmb_size_bytes(&lmb.reserved, i) - 1, BOOTMEM_DEFAULT);
 	}
+#ifdef CONFIG_MMU
+	init_bootmem_done = 1;
+#endif
 	paging_init();
 }
 
@@ -191,11 +206,145 @@
 	printk(KERN_INFO "Memory: %luk/%luk available\n",
 	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
 	       num_physpages << (PAGE_SHIFT-10));
+#ifdef CONFIG_MMU
+	mem_init_done = 1;
+#endif
 }
 
+#ifndef CONFIG_MMU
 /* Check against bounds of physical memory */
 int ___range_ok(unsigned long addr, unsigned long size)
 {
 	return ((addr < memory_start) ||
 		((addr + size) > memory_end));
 }
+EXPORT_SYMBOL(___range_ok);
+
+#else
+int page_is_ram(unsigned long pfn)
+{
+	return pfn < max_low_pfn;
+}
+
+/*
+ * Check for command-line options that affect what MMU_init will do.
+ */
+static void mm_cmdline_setup(void)
+{
+	unsigned long maxmem = 0;
+	char *p = cmd_line;
+
+	/* Look for mem= option on command line */
+	p = strstr(cmd_line, "mem=");
+	if (p) {
+		p += 4;
+		maxmem = memparse(p, &p);
+		if (maxmem && memory_size > maxmem) {
+			memory_size = maxmem;
+			memory_end = memory_start + memory_size;
+			lmb.memory.region[0].size = memory_size;
+		}
+	}
+}
+
+/*
+ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
+ */
+static void __init mmu_init_hw(void)
+{
+	/*
+	 * The Zone Protection Register (ZPR) defines how protection will
+	 * be applied to every page which is a member of a given zone. At
+	 * present, we utilize only two of the zones.
+	 * The zone index bits (of ZSEL) in the PTE are used for software
+	 * indicators, except the LSB.  For user access, zone 1 is used,
+	 * for kernel access, zone 0 is used.  We set all but zone 1
+	 * to zero, allowing only kernel access as indicated in the PTE.
+	 * For zone 1, we set a 01 binary (a value of 10 will not work)
+	 * to allow user access as indicated in the PTE.  This also allows
+	 * kernel access as indicated in the PTE.
+	 */
+	__asm__ __volatile__ ("ori r11, r0, 0x10000000;" \
+			"mts rzpr, r11;"
+			: : : "r11");
+}
+
+/*
+ * MMU_init sets up the basic memory mappings for the kernel,
+ * including both RAM and possibly some I/O regions,
+ * and sets up the page tables and the MMU hardware ready to go.
+ */
+
+/* called from head.S */
+asmlinkage void __init mmu_init(void)
+{
+	unsigned int kstart, ksize;
+
+	if (!lmb.reserved.cnt) {
+		printk(KERN_EMERG "Error memory count\n");
+		machine_restart(NULL);
+	}
+
+	if ((u32) lmb.memory.region[0].size < 0x1000000) {
+		printk(KERN_EMERG "Memory must be greater than 16MB\n");
+		machine_restart(NULL);
+	}
+	/* Find main memory where the kernel is */
+	memory_start = (u32) lmb.memory.region[0].base;
+	memory_end = (u32) lmb.memory.region[0].base +
+				(u32) lmb.memory.region[0].size;
+	memory_size = memory_end - memory_start;
+
+	mm_cmdline_setup(); /* FIXME parse args from command line - not used */
+
+	/*
+	 * Map out the kernel text/data/bss from the available physical
+	 * memory.
+	 */
+	kstart = __pa(CONFIG_KERNEL_START); /* kernel start */
+	/* kernel size */
+	ksize = PAGE_ALIGN(((u32)_end - (u32)CONFIG_KERNEL_START));
+	lmb_reserve(kstart, ksize);
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/* Remove the init RAM disk from the available memory. */
+/*	if (initrd_start) {
+		mem_pieces_remove(&phys_avail, __pa(initrd_start),
+				  initrd_end - initrd_start, 1);
+	}*/
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Initialize the MMU hardware */
+	mmu_init_hw();
+
+	/* Map in all of RAM starting at CONFIG_KERNEL_START */
+	mapin_ram();
+
+#ifdef HIGHMEM_START_BOOL
+	ioremap_base = HIGHMEM_START;
+#else
+	ioremap_base = 0xfe000000UL;	/* for now, could be 0xfffff000 */
+#endif /* CONFIG_HIGHMEM */
+	ioremap_bot = ioremap_base;
+
+	/* Initialize the context management stuff */
+	mmu_context_init();
+}
+
+/* This is only called until mem_init is done. */
+void __init *early_get_page(void)
+{
+	void *p;
+	if (init_bootmem_done) {
+		p = alloc_bootmem_pages(PAGE_SIZE);
+	} else {
+		/*
+		 * Mem start + 32MB -> here is limit
+		 * because of mem mapping from head.S
+		 */
+		p = __va(lmb_alloc_base(PAGE_SIZE, PAGE_SIZE,
+					memory_start + 0x2000000));
+	}
+	return p;
+}
+#endif /* CONFIG_MMU */
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/mm/Makefile linux-libre-2.6.31-gnu/arch/microblaze/mm/Makefile
--- linux-libre-2.6.30-gnu/arch/microblaze/mm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/microblaze/mm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,3 +3,5 @@
 #
 
 obj-y := init.o
+
+obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/mm/mmu_context.c linux-libre-2.6.31-gnu/arch/microblaze/mm/mmu_context.c
--- linux-libre-2.6.30-gnu/arch/microblaze/mm/mmu_context.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/mm/mmu_context.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * This file contains the routines for handling the MMU.
+ *
+ *    Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
+ *
+ *  Derived from arch/ppc/mm/4xx_mmu.c:
+ *  -- paulus
+ *
+ *  Derived from arch/ppc/mm/init.c:
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ *    Copyright (C) 1996 Paul Mackerras
+ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ *  Derived from "arch/i386/mm/init.c"
+ *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
+ *  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/mm.h>
+#include <linux/init.h>
+
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+
+mm_context_t next_mmu_context;
+unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
+atomic_t nr_free_contexts;
+struct mm_struct *context_mm[LAST_CONTEXT+1];
+
+/*
+ * Initialize the context management stuff.
+ */
+void __init mmu_context_init(void)
+{
+	/*
+	 * The use of context zero is reserved for the kernel.
+	 * This code assumes FIRST_CONTEXT < 32.
+	 */
+	context_map[0] = (1 << FIRST_CONTEXT) - 1;
+	next_mmu_context = FIRST_CONTEXT;
+	atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
+}
+
+/*
+ * Steal a context from a task that has one at the moment.
+ *
+ * This isn't an LRU system, it just frees up each context in
+ * turn (sort-of pseudo-random replacement :).  This would be the
+ * place to implement an LRU scheme if anyone were motivated to do it.
+ */
+void steal_context(void)
+{
+	struct mm_struct *mm;
+
+	/* free up context `next_mmu_context' */
+	/* if we shouldn't free context 0, don't... */
+	if (next_mmu_context < FIRST_CONTEXT)
+		next_mmu_context = FIRST_CONTEXT;
+	mm = context_mm[next_mmu_context];
+	flush_tlb_mm(mm);
+	destroy_context(mm);
+}
diff -druN linux-libre-2.6.30-gnu/arch/microblaze/mm/pgtable.c linux-libre-2.6.31-gnu/arch/microblaze/mm/pgtable.c
--- linux-libre-2.6.30-gnu/arch/microblaze/mm/pgtable.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/microblaze/mm/pgtable.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,286 @@
+/*
+ *  This file contains the routines setting up the linux page tables.
+ *
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ *
+ *    Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
+ *
+ *  Derived from arch/ppc/mm/pgtable.c:
+ *    -- paulus
+ *
+ *  Derived from arch/ppc/mm/init.c:
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ *    Copyright (C) 1996 Paul Mackerras
+ *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
+ *
+ *  Derived from "arch/i386/mm/init.c"
+ *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
+ *  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/module.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <linux/io.h>
+#include <asm/mmu.h>
+#include <asm/sections.h>
+
+#define flush_HPTE(X, va, pg)	_tlbie(va)
+
+unsigned long ioremap_base;
+unsigned long ioremap_bot;
+
+/* The maximum lowmem defaults to 768Mb, but this can be configured to
+ * another value.
+ */
+#define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
+
+#ifndef CONFIG_SMP
+struct pgtable_cache_struct quicklists;
+#endif
+
+static void __iomem *__ioremap(phys_addr_t addr, unsigned long size,
+		unsigned long flags)
+{
+	unsigned long v, i;
+	phys_addr_t p;
+	int err;
+
+	/*
+	 * Choose an address to map it to.
+	 * Once the vmalloc system is running, we use it.
+	 * Before then, we use space going down from ioremap_base
+	 * (ioremap_bot records where we're up to).
+	 */
+	p = addr & PAGE_MASK;
+	size = PAGE_ALIGN(addr + size) - p;
+
+	/*
+	 * Don't allow anybody to remap normal RAM that we're using.
+	 * mem_init() sets high_memory so only do the check after that.
+	 *
+	 * However, allow remap of rootfs: TBD
+	 */
+	if (mem_init_done &&
+		p >= memory_start && p < virt_to_phys(high_memory) &&
+		!(p >= virt_to_phys((unsigned long)&__bss_stop) &&
+		p < virt_to_phys((unsigned long)__bss_stop))) {
+		printk(KERN_WARNING "__ioremap(): phys addr "PTE_FMT
+			" is RAM lr %p\n", (unsigned long)p,
+			__builtin_return_address(0));
+		return NULL;
+	}
+
+	if (size == 0)
+		return NULL;
+
+	/*
+	 * Is it already mapped? If the whole area is mapped then we're
+	 * done, otherwise remap it since we want to keep the virt addrs for
+	 * each request contiguous.
+	 *
+	 * We make the assumption here that if the bottom and top
+	 * of the range we want are mapped then it's mapped to the
+	 * same virt address (and this is contiguous).
+	 *  -- Cort
+	 */
+
+	if (mem_init_done) {
+		struct vm_struct *area;
+		area = get_vm_area(size, VM_IOREMAP);
+		if (area == NULL)
+			return NULL;
+		v = VMALLOC_VMADDR(area->addr);
+	} else {
+		v = (ioremap_bot -= size);
+	}
+
+	if ((flags & _PAGE_PRESENT) == 0)
+		flags |= _PAGE_KERNEL;
+	if (flags & _PAGE_NO_CACHE)
+		flags |= _PAGE_GUARDED;
+
+	err = 0;
+	for (i = 0; i < size && err == 0; i += PAGE_SIZE)
+		err = map_page(v + i, p + i, flags);
+	if (err) {
+		if (mem_init_done)
+			vfree((void *)v);
+		return NULL;
+	}
+
+	return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK));
+}
+
+void __iomem *ioremap(phys_addr_t addr, unsigned long size)
+{
+	return __ioremap(addr, size, _PAGE_NO_CACHE);
+}
+EXPORT_SYMBOL(ioremap);
+
+void iounmap(void *addr)
+{
+	if (addr > high_memory && (unsigned long) addr < ioremap_bot)
+		vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
+EXPORT_SYMBOL(iounmap);
+
+
+int map_page(unsigned long va, phys_addr_t pa, int flags)
+{
+	pmd_t *pd;
+	pte_t *pg;
+	int err = -ENOMEM;
+	/* spin_lock(&init_mm.page_table_lock); */
+	/* Use upper 10 bits of VA to index the first level map */
+	pd = pmd_offset(pgd_offset_k(va), va);
+	/* Use middle 10 bits of VA to index the second-level map */
+	pg = pte_alloc_kernel(pd, va); /* from powerpc - pgtable.c */
+	/* pg = pte_alloc_kernel(&init_mm, pd, va); */
+
+	if (pg != NULL) {
+		err = 0;
+		set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT,
+				__pgprot(flags)));
+		if (mem_init_done)
+			flush_HPTE(0, va, pmd_val(*pd));
+			/* flush_HPTE(0, va, pg); */
+
+	}
+	/* spin_unlock(&init_mm.page_table_lock); */
+	return err;
+}
+
+void __init adjust_total_lowmem(void)
+{
+/* TBD */
+#if 0
+	unsigned long max_low_mem = MAX_LOW_MEM;
+
+	if (total_lowmem > max_low_mem) {
+		total_lowmem = max_low_mem;
+#ifndef CONFIG_HIGHMEM
+		printk(KERN_INFO "Warning, memory limited to %ld Mb, use "
+				"CONFIG_HIGHMEM to reach %ld Mb\n",
+				max_low_mem >> 20, total_memory >> 20);
+		total_memory = total_lowmem;
+#endif /* CONFIG_HIGHMEM */
+	}
+#endif
+}
+
+static void show_tmem(unsigned long tmem)
+{
+	volatile unsigned long a;
+	a = a + tmem;
+}
+
+/*
+ * Map in all of physical memory starting at CONFIG_KERNEL_START.
+ */
+void __init mapin_ram(void)
+{
+	unsigned long v, p, s, f;
+
+	v = CONFIG_KERNEL_START;
+	p = memory_start;
+	show_tmem(memory_size);
+	for (s = 0; s < memory_size; s += PAGE_SIZE) {
+		f = _PAGE_PRESENT | _PAGE_ACCESSED |
+				_PAGE_SHARED | _PAGE_HWEXEC;
+		if ((char *) v < _stext || (char *) v >= _etext)
+			f |= _PAGE_WRENABLE;
+		else
+			/* On the MicroBlaze, no user access
+			   forces R/W kernel access */
+			f |= _PAGE_USER;
+		map_page(v, p, f);
+		v += PAGE_SIZE;
+		p += PAGE_SIZE;
+	}
+}
+
+/* is x a power of 2? */
+#define is_power_of_2(x)	((x) != 0 && (((x) & ((x) - 1)) == 0))
+
+/*
+ * Set up a mapping for a block of I/O.
+ * virt, phys, size must all be page-aligned.
+ * This should only be called before ioremap is called.
+ */
+void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
+			     unsigned int size, int flags)
+{
+	int i;
+
+	if (virt > CONFIG_KERNEL_START && virt < ioremap_bot)
+		ioremap_bot = ioremap_base = virt;
+
+	/* Put it in the page tables. */
+	for (i = 0; i < size; i += PAGE_SIZE)
+		map_page(virt + i, phys + i, flags);
+}
+
+/* Scan the real Linux page tables and return a PTE pointer for
+ * a virtual address in a context.
+ * Returns true (1) if PTE was found, zero otherwise.  The pointer to
+ * the PTE pointer is unmodified if PTE is not found.
+ */
+static int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+{
+	pgd_t	*pgd;
+	pmd_t	*pmd;
+	pte_t	*pte;
+	int     retval = 0;
+
+	pgd = pgd_offset(mm, addr & PAGE_MASK);
+	if (pgd) {
+		pmd = pmd_offset(pgd, addr & PAGE_MASK);
+		if (pmd_present(*pmd)) {
+			pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
+			if (pte) {
+				retval = 1;
+				*ptep = pte;
+			}
+		}
+	}
+	return retval;
+}
+
+/* Find physical address for this virtual address.  Normally used by
+ * I/O functions, but anyone can call it.
+ */
+unsigned long iopa(unsigned long addr)
+{
+	unsigned long pa;
+
+	pte_t *pte;
+	struct mm_struct *mm;
+
+	/* Allow mapping of user addresses (within the thread)
+	 * for DMA if necessary.
+	 */
+	if (addr < TASK_SIZE)
+		mm = current->mm;
+	else
+		mm = &init_mm;
+
+	pa = 0;
+	if (get_pteptr(mm, addr, &pte))
+		pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
+
+	return pa;
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/common/gpio.c linux-libre-2.6.31-gnu/arch/mips/alchemy/common/gpio.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/common/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/common/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,201 +0,0 @@
-/*
- *  Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
- *  	Architecture specific GPIO support
- *
- *  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.
- *
- *  Notes :
- * 	au1000 SoC have only one GPIO line : GPIO1
- * 	others have a second one : GPIO2
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/gpio.h>
-
-struct au1000_gpio_chip {
-	struct gpio_chip	chip;
-	void __iomem		*regbase;
-};
-
-#if !defined(CONFIG_SOC_AU1000)
-static int au1000_gpio2_get(struct gpio_chip *chip, unsigned offset)
-{
-	u32 mask = 1 << offset;
-	struct au1000_gpio_chip *gpch;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-	return readl(gpch->regbase + AU1000_GPIO2_ST) & mask;
-}
-
-static void au1000_gpio2_set(struct gpio_chip *chip,
-				unsigned offset, int value)
-{
-	u32 mask = ((GPIO2_OUT_EN_MASK << offset) | (!!value << offset));
-	struct au1000_gpio_chip *gpch;
-	unsigned long flags;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-
-	local_irq_save(flags);
-	writel(mask, gpch->regbase + AU1000_GPIO2_OUT);
-	local_irq_restore(flags);
-}
-
-static int au1000_gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	u32 mask = 1 << offset;
-	u32 tmp;
-	struct au1000_gpio_chip *gpch;
-	unsigned long flags;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-
-	local_irq_save(flags);
-	tmp = readl(gpch->regbase + AU1000_GPIO2_DIR);
-	tmp &= ~mask;
-	writel(tmp, gpch->regbase + AU1000_GPIO2_DIR);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static int au1000_gpio2_direction_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	u32 mask = 1 << offset;
-	u32 out_mask = ((GPIO2_OUT_EN_MASK << offset) | (!!value << offset));
-	u32 tmp;
-	struct au1000_gpio_chip *gpch;
-	unsigned long flags;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-
-	local_irq_save(flags);
-	tmp = readl(gpch->regbase + AU1000_GPIO2_DIR);
-	tmp |= mask;
-	writel(tmp, gpch->regbase + AU1000_GPIO2_DIR);
-	writel(out_mask, gpch->regbase + AU1000_GPIO2_OUT);
-	local_irq_restore(flags);
-
-	return 0;
-}
-#endif /* !defined(CONFIG_SOC_AU1000) */
-
-static int au1000_gpio1_get(struct gpio_chip *chip, unsigned offset)
-{
-	u32 mask = 1 << offset;
-	struct au1000_gpio_chip *gpch;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-	return readl(gpch->regbase + AU1000_GPIO1_ST) & mask;
-}
-
-static void au1000_gpio1_set(struct gpio_chip *chip,
-				unsigned offset, int value)
-{
-	u32 mask = 1 << offset;
-	u32 reg_offset;
-	struct au1000_gpio_chip *gpch;
-	unsigned long flags;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-
-	if (value)
-		reg_offset = AU1000_GPIO1_OUT;
-	else
-		reg_offset = AU1000_GPIO1_CLR;
-
-	local_irq_save(flags);
-	writel(mask, gpch->regbase + reg_offset);
-	local_irq_restore(flags);
-}
-
-static int au1000_gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	u32 mask = 1 << offset;
-	struct au1000_gpio_chip *gpch;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-	writel(mask, gpch->regbase + AU1000_GPIO1_ST);
-
-	return 0;
-}
-
-static int au1000_gpio1_direction_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	u32 mask = 1 << offset;
-	struct au1000_gpio_chip *gpch;
-
-	gpch = container_of(chip, struct au1000_gpio_chip, chip);
-
-	writel(mask, gpch->regbase + AU1000_GPIO1_TRI_OUT);
-	au1000_gpio1_set(chip, offset, value);
-
-	return 0;
-}
-
-struct au1000_gpio_chip au1000_gpio_chip[] = {
-	[0] = {
-		.regbase			= (void __iomem *)SYS_BASE,
-		.chip = {
-			.label			= "au1000-gpio1",
-			.direction_input	= au1000_gpio1_direction_input,
-			.direction_output	= au1000_gpio1_direction_output,
-			.get			= au1000_gpio1_get,
-			.set			= au1000_gpio1_set,
-			.base			= 0,
-			.ngpio			= 32,
-		},
-	},
-#if !defined(CONFIG_SOC_AU1000)
-	[1] = {
-		.regbase                        = (void __iomem *)GPIO2_BASE,
-		.chip = {
-			.label                  = "au1000-gpio2",
-			.direction_input        = au1000_gpio2_direction_input,
-			.direction_output       = au1000_gpio2_direction_output,
-			.get                    = au1000_gpio2_get,
-			.set                    = au1000_gpio2_set,
-			.base                   = AU1XXX_GPIO_BASE,
-			.ngpio                  = 32,
-		},
-	},
-#endif
-};
-
-static int __init au1000_gpio_init(void)
-{
-	gpiochip_add(&au1000_gpio_chip[0].chip);
-#if !defined(CONFIG_SOC_AU1000)
-	gpiochip_add(&au1000_gpio_chip[1].chip);
-#endif
-
-	return 0;
-}
-arch_initcall(au1000_gpio_init);
-
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/common/gpiolib-au1000.c linux-libre-2.6.31-gnu/arch/mips/alchemy/common/gpiolib-au1000.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/common/gpiolib-au1000.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/common/gpiolib-au1000.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,130 @@
+/*
+ *  Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *  	GPIOLIB support for Au1000, Au1500, Au1100, Au1550 and Au12x0.
+ *
+ *  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.
+ *
+ *  Notes :
+ * 	au1000 SoC have only one GPIO block : GPIO1
+ * 	Au1100, Au15x0, Au12x0 have a second one : GPIO2
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio.h>
+
+#if !defined(CONFIG_SOC_AU1000)
+static int gpio2_get(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE);
+}
+
+static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value);
+}
+
+static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_direction_input(offset + ALCHEMY_GPIO2_BASE);
+}
+
+static int gpio2_direction_output(struct gpio_chip *chip, unsigned offset,
+				  int value)
+{
+	return alchemy_gpio2_direction_output(offset + ALCHEMY_GPIO2_BASE,
+						value);
+}
+
+static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio2_to_irq(offset + ALCHEMY_GPIO2_BASE);
+}
+#endif /* !defined(CONFIG_SOC_AU1000) */
+
+static int gpio1_get(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE);
+}
+
+static void gpio1_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value);
+}
+
+static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_direction_input(offset + ALCHEMY_GPIO1_BASE);
+}
+
+static int gpio1_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	return alchemy_gpio1_direction_output(offset + ALCHEMY_GPIO1_BASE,
+					     value);
+}
+
+static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE);
+}
+
+struct gpio_chip alchemy_gpio_chip[] = {
+	[0] = {
+		.label			= "alchemy-gpio1",
+		.direction_input	= gpio1_direction_input,
+		.direction_output	= gpio1_direction_output,
+		.get			= gpio1_get,
+		.set			= gpio1_set,
+		.to_irq			= gpio1_to_irq,
+		.base			= ALCHEMY_GPIO1_BASE,
+		.ngpio			= ALCHEMY_GPIO1_NUM,
+	},
+#if !defined(CONFIG_SOC_AU1000)
+	[1] = {
+		.label                  = "alchemy-gpio2",
+		.direction_input        = gpio2_direction_input,
+		.direction_output       = gpio2_direction_output,
+		.get                    = gpio2_get,
+		.set                    = gpio2_set,
+		.to_irq			= gpio2_to_irq,
+		.base                   = ALCHEMY_GPIO2_BASE,
+		.ngpio                  = ALCHEMY_GPIO2_NUM,
+	},
+#endif
+};
+
+static int __init alchemy_gpiolib_init(void)
+{
+	gpiochip_add(&alchemy_gpio_chip[0]);
+#if !defined(CONFIG_SOC_AU1000)
+	gpiochip_add(&alchemy_gpio_chip[1]);
+#endif
+
+	return 0;
+}
+arch_initcall(alchemy_gpiolib_init);
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/common/Makefile linux-libre-2.6.31-gnu/arch/mips/alchemy/common/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/common/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/common/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,14 @@
 
 obj-y += prom.o irq.o puts.o time.o reset.o \
 	clocks.o platform.o power.o setup.o \
-	sleeper.o dma.o dbdma.o gpio.o
+	sleeper.o dma.o dbdma.o
+
+# optional gpiolib support
+ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
+ ifeq ($(CONFIG_GPIOLIB),y)
+  obj-$(CONFIG_ALCHEMY_GPIO_AU1000) += gpiolib-au1000.o
+ endif
+endif
 
 obj-$(CONFIG_PCI)		+= pci.o
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/common/reset.c linux-libre-2.6.31-gnu/arch/mips/alchemy/common/reset.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/common/reset.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/common/reset.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,8 +27,9 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <asm/cacheflush.h>
+#include <linux/gpio.h>
 
+#include <asm/cacheflush.h>
 #include <asm/mach-au1x00/au1000.h>
 
 void au1000_restart(char *command)
@@ -161,7 +162,7 @@
 #else
 	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
 #ifdef CONFIG_MIPS_MIRAGE
-	au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
+	gpio_direction_output(210, 1);
 #endif
 #ifdef CONFIG_MIPS_DB1200
 	au_writew(au_readw(0xB980001C) | (1 << 14), 0xB980001C);
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/gpio.h>
 #include <linux/init.h>
 
 #include <asm/mach-au1x00/au1000.h>
@@ -94,12 +95,12 @@
 #endif
 	bcsr->pcmcia = 0x0000; /* turn off PCMCIA power */
 
-#ifdef CONFIG_MIPS_MIRAGE
 	/* Enable GPIO[31:0] inputs */
-	au_writel(0, SYS_PININPUTEN);
+	alchemy_gpio1_input_enable();
 
-	/* GPIO[20] is output, tristate the other input primary GPIOs */
-	au_writel(~(1 << 20), SYS_TRIOUTCLR);
+#ifdef CONFIG_MIPS_MIRAGE
+	/* GPIO[20] is output */
+	alchemy_gpio_direction_output(20, 0);
 
 	/* Set GPIO[210:208] instead of SSI_0 */
 	pin_func = au_readl(SYS_PINFUNC) | SYS_PF_S0;
@@ -118,8 +119,7 @@
 	 * Enable speaker amplifier.  This should
 	 * be part of the audio driver.
 	 */
-	au_writel(au_readl(GPIO2_DIR) | 0x200, GPIO2_DIR);
-	au_writel(0x02000200, GPIO2_OUTPUT);
+	alchemy_gpio_direction_output(209, 1);
 #endif
 
 	au_sync();
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/mach-au1x00/au1000.h>
@@ -130,8 +131,11 @@
 	pin_func |= SYS_PF_USB;
 
 	au_writel(pin_func, SYS_PINFUNC);
-	au_writel(0x2800, SYS_TRIOUTCLR);
-	au_writel(0x0030, SYS_OUTPUTCLR);
+
+	alchemy_gpio_direction_input(11);
+	alchemy_gpio_direction_input(13);
+	alchemy_gpio_direction_output(4, 0);
+	alchemy_gpio_direction_output(5, 0);
 #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
 	/* Make GPIO 15 an input (for interrupt line) */
@@ -140,7 +144,7 @@
 	pin_func |= SYS_PF_I2S;
 	au_writel(pin_func, SYS_PINFUNC);
 
-	au_writel(0x8000, SYS_TRIOUTCLR);
+	alchemy_gpio_direction_input(15);
 
 	static_cfg0 = au_readl(MEM_STCFG0) & ~0xc00;
 	au_writel(static_cfg0, MEM_STCFG0);
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -88,7 +89,7 @@
 
 	/* Set AUX clock to 12 MHz * 8 = 96 MHz */
 	au_writel(8, SYS_AUXPLL);
-	au_writel(0, SYS_PININPUTEN);
+	alchemy_gpio1_input_enable();
 	udelay(100);
 
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,9 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
 
 #include <asm/mach-au1x00/au1000.h>
@@ -90,11 +91,12 @@
 	au_writel(0, SYS_PINSTATERD);
 	udelay(100);
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-
 	/* GPIO201 is input for PCMCIA card detect */
 	/* GPIO203 is input for PCMCIA interrupt request */
-	au_writel(au_readl(GPIO2_DIR) & ~((1 << 1) | (1 << 3)), GPIO2_DIR);
+	alchemy_gpio_direction_input(201);
+	alchemy_gpio_direction_input(203);
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 
 	/* Zero and disable FREQ2 */
 	sys_freqctrl = au_readl(SYS_FREQCTRL0);
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pm.c linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pm.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/devboards/pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/devboards/pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/suspend.h>
 #include <linux/sysfs.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio.h>
 
 /*
  * Generic suspend userspace interface for Alchemy development boards.
@@ -26,7 +27,7 @@
 static int db1x_pm_enter(suspend_state_t state)
 {
 	/* enable GPIO based wakeup */
-	au_writel(1, SYS_PININPUTEN);
+	alchemy_gpio1_input_enable();
 
 	/* clear and setup wake cause and source */
 	au_writel(0, SYS_WAKEMSK);
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/Kconfig linux-libre-2.6.31-gnu/arch/mips/alchemy/Kconfig
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,14 @@
+# au1000-style gpio
+config ALCHEMY_GPIO_AU1000
+	bool
+
+# select this in your board config if you don't want to use the gpio
+# namespace as documented in the manuals.  In this case however you need
+# to create the necessary gpio_* functions in your board code/headers!
+# see arch/mips/include/asm/mach-au1x00/gpio.h   for more information.
+config ALCHEMY_GPIO_INDIRECT
+	def_bool n
+
 choice
 	prompt "Machine type"
 	depends on MACH_ALCHEMY
@@ -108,22 +119,27 @@
 config SOC_AU1000
 	bool
 	select SOC_AU1X00
+	select ALCHEMY_GPIO_AU1000
 
 config SOC_AU1100
 	bool
 	select SOC_AU1X00
+	select ALCHEMY_GPIO_AU1000
 
 config SOC_AU1500
 	bool
 	select SOC_AU1X00
+	select ALCHEMY_GPIO_AU1000
 
 config SOC_AU1550
 	bool
 	select SOC_AU1X00
+	select ALCHEMY_GPIO_AU1000
 
 config SOC_AU1200
 	bool
 	select SOC_AU1X00
+	select ALCHEMY_GPIO_AU1000
 
 config SOC_AU1X00
 	bool
@@ -134,4 +150,5 @@
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_APM_EMULATION
-	select ARCH_REQUIRE_GPIOLIB
+	select GENERIC_GPIO
+	select ARCH_WANT_OPTIONAL_GPIOLIB
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/mtx-1/board_setup.c linux-libre-2.6.31-gnu/arch/mips/alchemy/mtx-1/board_setup.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/mtx-1/board_setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/mtx-1/board_setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/gpio.h>
 #include <linux/init.h>
 
 #include <asm/mach-au1x00/au1000.h>
@@ -55,10 +56,11 @@
 	}
 #endif
 
+	alchemy_gpio2_enable();
+
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 	/* Enable USB power switch */
-	au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR);
-	au_writel(0x100000, GPIO2_OUTPUT);
+	alchemy_gpio_direction_output(204, 0);
 #endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */
 
 #ifdef CONFIG_PCI
@@ -74,14 +76,14 @@
 
 	/* Initialize GPIO */
 	au_writel(0xFFFFFFFF, SYS_TRIOUTCLR);
-	au_writel(0x00000001, SYS_OUTPUTCLR); /* set M66EN (PCI 66MHz) to OFF */
-	au_writel(0x00000008, SYS_OUTPUTSET); /* set PCI CLKRUN# to OFF */
-	au_writel(0x00000002, SYS_OUTPUTSET); /* set EXT_IO3 ON */
-	au_writel(0x00000020, SYS_OUTPUTCLR); /* set eth PHY TX_ER to OFF */
+	alchemy_gpio_direction_output(0, 0);	/* Disable M66EN (PCI 66MHz) */
+	alchemy_gpio_direction_output(3, 1);	/* Disable PCI CLKRUN# */
+	alchemy_gpio_direction_output(1, 1);	/* Enable EXT_IO3 */
+	alchemy_gpio_direction_output(5, 0);	/* Disable eth PHY TX_ER */
 
 	/* Enable LED and set it to green */
-	au_writel(au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR);
-	au_writel(0x18000800, GPIO2_OUTPUT);
+	alchemy_gpio_direction_output(211, 1);	/* green on */
+	alchemy_gpio_direction_output(212, 0);	/* red off */
 
 	board_pci_idsel = mtx1_pci_idsel;
 
@@ -101,10 +103,10 @@
 
 	if (assert && devsel != 0)
 		/* Suppress signal to Cardbus */
-		au_writel(0x00000002, SYS_OUTPUTCLR); /* set EXT_IO3 OFF */
+		gpio_set_value(1, 0);	/* set EXT_IO3 OFF */
 	else
-		au_writel(0x00000002, SYS_OUTPUTSET); /* set EXT_IO3 ON */
+		gpio_set_value(1, 1);	/* set EXT_IO3 ON */
+
 	au_sync_udelay(1);
 	return 1;
 }
-
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/mtx-1/platform.c linux-libre-2.6.31-gnu/arch/mips/alchemy/mtx-1/platform.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/mtx-1/platform.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/mtx-1/platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * MTX-1 platform devices registration
  *
- * Copyright (C) 2007, Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2007-2009, 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
@@ -142,7 +142,17 @@
 
 static int __init mtx1_register_devices(void)
 {
-	gpio_direction_input(207);
+	int rc;
+
+	rc = gpio_request(mtx1_gpio_button[0].gpio,
+					mtx1_gpio_button[0].desc);
+	if (rc < 0) {
+		printk(KERN_INFO "mtx1: failed to request %d\n",
+					mtx1_gpio_button[0].gpio);
+		goto out;
+	}
+	gpio_direction_input(mtx1_gpio_button[0].gpio);
+out:
 	return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs));
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/alchemy/xxs1500/board_setup.c linux-libre-2.6.31-gnu/arch/mips/alchemy/xxs1500/board_setup.c
--- linux-libre-2.6.30-gnu/arch/mips/alchemy/xxs1500/board_setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/alchemy/xxs1500/board_setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 
@@ -50,6 +51,9 @@
 	}
 #endif
 
+	alchemy_gpio1_input_enable();
+	alchemy_gpio2_enable();
+
 	/* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
 	pin_func  = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
 	pin_func |= SYS_PF_UR3;
@@ -65,20 +69,19 @@
 	au_writel(0x01, UART3_ADDR + UART_MCR); /* UART_MCR_DTR is 0x01??? */
 
 #ifdef CONFIG_PCMCIA_XXS1500
-	/* Setup PCMCIA signals */
-	au_writel(0, SYS_PININPUTEN);
-
 	/* GPIO 0, 1, and 4 are inputs */
-	au_writel(1 | (1 << 1) | (1 << 4), SYS_TRIOUTCLR);
+	alchemy_gpio_direction_input(0);
+	alchemy_gpio_direction_input(1);
+	alchemy_gpio_direction_input(4);
 
-	/* Enable GPIO2 if not already enabled */
-	au_writel(1, GPIO2_ENABLE);
 	/* GPIO2 208/9/10/11 are inputs */
-	au_writel((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11), GPIO2_DIR);
+	alchemy_gpio_direction_input(208);
+	alchemy_gpio_direction_input(209);
+	alchemy_gpio_direction_input(210);
+	alchemy_gpio_direction_input(211);
 
 	/* Turn off power */
-	au_writel((au_readl(GPIO2_PINSTATE) & ~(1 << 14)) | (1 << 30),
-		  GPIO2_OUTPUT);
+	alchemy_gpio_direction_output(214, 0);
 #endif
 
 #ifdef CONFIG_PCI
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/clock.c linux-libre-2.6.31-gnu/arch/mips/ar7/clock.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gcd.h>
+#include <linux/io.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define BOOT_PLL_SOURCE_MASK	0x3
+#define CPU_PLL_SOURCE_SHIFT	16
+#define BUS_PLL_SOURCE_SHIFT	14
+#define USB_PLL_SOURCE_SHIFT	18
+#define DSP_PLL_SOURCE_SHIFT	22
+#define BOOT_PLL_SOURCE_AFE	0
+#define BOOT_PLL_SOURCE_BUS	0
+#define BOOT_PLL_SOURCE_REF	1
+#define BOOT_PLL_SOURCE_XTAL	2
+#define BOOT_PLL_SOURCE_CPU	3
+#define BOOT_PLL_BYPASS		0x00000020
+#define BOOT_PLL_ASYNC_MODE	0x02000000
+#define BOOT_PLL_2TO1_MODE	0x00008000
+
+#define TNETD7200_CLOCK_ID_CPU	0
+#define TNETD7200_CLOCK_ID_DSP	1
+#define TNETD7200_CLOCK_ID_USB	2
+
+#define TNETD7200_DEF_CPU_CLK	211000000
+#define TNETD7200_DEF_DSP_CLK	125000000
+#define TNETD7200_DEF_USB_CLK	48000000
+
+struct tnetd7300_clock {
+	u32 ctrl;
+#define PREDIV_MASK	0x001f0000
+#define PREDIV_SHIFT	16
+#define POSTDIV_MASK	0x0000001f
+	u32 unused1[3];
+	u32 pll;
+#define MUL_MASK	0x0000f000
+#define MUL_SHIFT	12
+#define PLL_MODE_MASK	0x00000001
+#define PLL_NDIV	0x00000800
+#define PLL_DIV		0x00000002
+#define PLL_STATUS	0x00000001
+	u32 unused2[3];
+};
+
+struct tnetd7300_clocks {
+	struct tnetd7300_clock bus;
+	struct tnetd7300_clock cpu;
+	struct tnetd7300_clock usb;
+	struct tnetd7300_clock dsp;
+};
+
+struct tnetd7200_clock {
+	u32 ctrl;
+	u32 unused1[3];
+#define DIVISOR_ENABLE_MASK 0x00008000
+	u32 mul;
+	u32 prediv;
+	u32 postdiv;
+	u32 postdiv2;
+	u32 unused2[6];
+	u32 cmd;
+	u32 status;
+	u32 cmden;
+	u32 padding[15];
+};
+
+struct tnetd7200_clocks {
+	struct tnetd7200_clock cpu;
+	struct tnetd7200_clock dsp;
+	struct tnetd7200_clock usb;
+};
+
+int ar7_cpu_clock = 150000000;
+EXPORT_SYMBOL(ar7_cpu_clock);
+int ar7_bus_clock = 125000000;
+EXPORT_SYMBOL(ar7_bus_clock);
+int ar7_dsp_clock;
+EXPORT_SYMBOL(ar7_dsp_clock);
+
+static void approximate(int base, int target, int *prediv,
+			int *postdiv, int *mul)
+{
+	int i, j, k, freq, res = target;
+	for (i = 1; i <= 16; i++)
+		for (j = 1; j <= 32; j++)
+			for (k = 1; k <= 32; k++) {
+				freq = abs(base / j * i / k - target);
+				if (freq < res) {
+					res = freq;
+					*mul = i;
+					*prediv = j;
+					*postdiv = k;
+				}
+			}
+}
+
+static void calculate(int base, int target, int *prediv, int *postdiv,
+	int *mul)
+{
+	int tmp_gcd, tmp_base, tmp_freq;
+
+	for (*prediv = 1; *prediv <= 32; (*prediv)++) {
+		tmp_base = base / *prediv;
+		tmp_gcd = gcd(target, tmp_base);
+		*mul = target / tmp_gcd;
+		*postdiv = tmp_base / tmp_gcd;
+		if ((*mul < 1) || (*mul >= 16))
+			continue;
+		if ((*postdiv > 0) & (*postdiv <= 32))
+			break;
+	}
+
+	if (base / *prediv * *mul / *postdiv != target) {
+		approximate(base, target, prediv, postdiv, mul);
+		tmp_freq = base / *prediv * *mul / *postdiv;
+		printk(KERN_WARNING
+		       "Adjusted requested frequency %d to %d\n",
+		       target, tmp_freq);
+	}
+
+	printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
+	       *prediv, *postdiv, *mul);
+}
+
+static int tnetd7300_dsp_clock(void)
+{
+	u32 didr1, didr2;
+	u8 rev = ar7_chip_rev();
+	didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
+	didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
+	if (didr2 & (1 << 23))
+		return 0;
+	if ((rev >= 0x23) && (rev != 0x57))
+		return 250000000;
+	if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
+	    > 4208000)
+		return 250000000;
+	return 0;
+}
+
+static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
+	u32 *bootcr, u32 bus_clock)
+{
+	int product;
+	int base_clock = AR7_REF_CLOCK;
+	u32 ctrl = readl(&clock->ctrl);
+	u32 pll = readl(&clock->pll);
+	int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
+	int postdiv = (ctrl & POSTDIV_MASK) + 1;
+	int divisor = prediv * postdiv;
+	int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
+
+	switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+	case BOOT_PLL_SOURCE_BUS:
+		base_clock = bus_clock;
+		break;
+	case BOOT_PLL_SOURCE_REF:
+		base_clock = AR7_REF_CLOCK;
+		break;
+	case BOOT_PLL_SOURCE_XTAL:
+		base_clock = AR7_XTAL_CLOCK;
+		break;
+	case BOOT_PLL_SOURCE_CPU:
+		base_clock = ar7_cpu_clock;
+		break;
+	}
+
+	if (*bootcr & BOOT_PLL_BYPASS)
+		return base_clock / divisor;
+
+	if ((pll & PLL_MODE_MASK) == 0)
+		return (base_clock >> (mul / 16 + 1)) / divisor;
+
+	if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
+		product = (mul & 1) ?
+			(base_clock * mul) >> 1 :
+			(base_clock * (mul - 1)) >> 2;
+		return product / divisor;
+	}
+
+	if (mul == 16)
+		return base_clock / divisor;
+
+	return base_clock * mul / divisor;
+}
+
+static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
+	u32 *bootcr, u32 frequency)
+{
+	int prediv, postdiv, mul;
+	int base_clock = ar7_bus_clock;
+
+	switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+	case BOOT_PLL_SOURCE_BUS:
+		base_clock = ar7_bus_clock;
+		break;
+	case BOOT_PLL_SOURCE_REF:
+		base_clock = AR7_REF_CLOCK;
+		break;
+	case BOOT_PLL_SOURCE_XTAL:
+		base_clock = AR7_XTAL_CLOCK;
+		break;
+	case BOOT_PLL_SOURCE_CPU:
+		base_clock = ar7_cpu_clock;
+		break;
+	}
+
+	calculate(base_clock, frequency, &prediv, &postdiv, &mul);
+
+	writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
+	msleep(1);
+	writel(4, &clock->pll);
+	while (readl(&clock->pll) & PLL_STATUS)
+		;
+	writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
+	msleep(75);
+}
+
+static void __init tnetd7300_init_clocks(void)
+{
+	u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+	struct tnetd7300_clocks *clocks =
+					ioremap_nocache(UR8_REGS_CLOCKS,
+					sizeof(struct tnetd7300_clocks));
+
+	ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
+		&clocks->bus, bootcr, AR7_AFE_CLOCK);
+
+	if (*bootcr & BOOT_PLL_ASYNC_MODE)
+		ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
+			&clocks->cpu, bootcr, AR7_AFE_CLOCK);
+	else
+		ar7_cpu_clock = ar7_bus_clock;
+
+	if (ar7_dsp_clock == 250000000)
+		tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
+			bootcr, ar7_dsp_clock);
+
+	iounmap(clocks);
+	iounmap(bootcr);
+}
+
+static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
+	int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
+{
+	printk(KERN_INFO
+		"Clocks: base = %d, frequency = %u, prediv = %d, "
+		"postdiv = %d, postdiv2 = %d, mul = %d\n",
+		base, frequency, prediv, postdiv, postdiv2, mul);
+
+	writel(0, &clock->ctrl);
+	writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
+	writel((mul - 1) & 0xF, &clock->mul);
+
+	while (readl(&clock->status) & 0x1)
+		; /* nop */
+
+	writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
+
+	writel(readl(&clock->cmden) | 1, &clock->cmden);
+	writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+	while (readl(&clock->status) & 0x1)
+		; /* nop */
+
+	writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
+
+	writel(readl(&clock->cmden) | 1, &clock->cmden);
+	writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+	while (readl(&clock->status) & 0x1)
+		; /* nop */
+
+	writel(readl(&clock->ctrl) | 1, &clock->ctrl);
+}
+
+static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
+{
+	if (*bootcr & BOOT_PLL_ASYNC_MODE)
+		/* Async */
+		switch (clock_id) {
+		case TNETD7200_CLOCK_ID_DSP:
+			return AR7_REF_CLOCK;
+		default:
+			return AR7_AFE_CLOCK;
+		}
+	else
+		/* Sync */
+		if (*bootcr & BOOT_PLL_2TO1_MODE)
+			/* 2:1 */
+			switch (clock_id) {
+			case TNETD7200_CLOCK_ID_DSP:
+				return AR7_REF_CLOCK;
+			default:
+				return AR7_AFE_CLOCK;
+			}
+		else
+			/* 1:1 */
+			return AR7_REF_CLOCK;
+}
+
+
+static void __init tnetd7200_init_clocks(void)
+{
+	u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+	struct tnetd7200_clocks *clocks =
+					ioremap_nocache(AR7_REGS_CLOCKS,
+					sizeof(struct tnetd7200_clocks));
+	int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
+	int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
+	int usb_base, usb_mul, usb_prediv, usb_postdiv;
+
+	cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
+	dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
+
+	if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+		printk(KERN_INFO "Clocks: Async mode\n");
+
+		printk(KERN_INFO "Clocks: Setting DSP clock\n");
+		calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
+			&dsp_prediv, &dsp_postdiv, &dsp_mul);
+		ar7_bus_clock =
+			((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
+		tnetd7200_set_clock(dsp_base, &clocks->dsp,
+			dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
+			ar7_bus_clock);
+
+		printk(KERN_INFO "Clocks: Setting CPU clock\n");
+		calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
+			&cpu_postdiv, &cpu_mul);
+		ar7_cpu_clock =
+			((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
+		tnetd7200_set_clock(cpu_base, &clocks->cpu,
+			cpu_prediv, cpu_postdiv, -1, cpu_mul,
+			ar7_cpu_clock);
+
+	} else
+		if (*bootcr & BOOT_PLL_2TO1_MODE) {
+			printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
+
+			printk(KERN_INFO "Clocks: Setting CPU clock\n");
+			calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
+				&cpu_postdiv, &cpu_mul);
+			ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul)
+								/ cpu_postdiv;
+			tnetd7200_set_clock(cpu_base, &clocks->cpu,
+				cpu_prediv, cpu_postdiv, -1, cpu_mul,
+				ar7_cpu_clock);
+
+			printk(KERN_INFO "Clocks: Setting DSP clock\n");
+			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
+				&dsp_postdiv, &dsp_mul);
+			ar7_bus_clock = ar7_cpu_clock / 2;
+			tnetd7200_set_clock(dsp_base, &clocks->dsp,
+				dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+				dsp_mul * 2, ar7_bus_clock);
+		} else {
+			printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
+
+			printk(KERN_INFO "Clocks: Setting DSP clock\n");
+			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
+				&dsp_postdiv, &dsp_mul);
+			ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul)
+								/ dsp_postdiv;
+			tnetd7200_set_clock(dsp_base, &clocks->dsp,
+				dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+				dsp_mul * 2, ar7_bus_clock);
+
+			ar7_cpu_clock = ar7_bus_clock;
+		}
+
+	printk(KERN_INFO "Clocks: Setting USB clock\n");
+	usb_base = ar7_bus_clock;
+	calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
+		&usb_postdiv, &usb_mul);
+	tnetd7200_set_clock(usb_base, &clocks->usb,
+		usb_prediv, usb_postdiv, -1, usb_mul,
+		TNETD7200_DEF_USB_CLK);
+
+	ar7_dsp_clock = ar7_cpu_clock;
+
+	iounmap(clocks);
+	iounmap(bootcr);
+}
+
+int __init ar7_init_clocks(void)
+{
+	switch (ar7_chip_id()) {
+	case AR7_CHIP_7100:
+	case AR7_CHIP_7200:
+		tnetd7200_init_clocks();
+		break;
+	case AR7_CHIP_7300:
+		ar7_dsp_clock = tnetd7300_dsp_clock();
+		tnetd7300_init_clocks();
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+arch_initcall(ar7_init_clocks);
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/gpio.c linux-libre-2.6.31-gnu/arch/mips/ar7/gpio.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach-ar7/gpio.h>
+
+static const char *ar7_gpio_list[AR7_GPIO_MAX];
+
+int gpio_request(unsigned gpio, const char *label)
+{
+	if (gpio >= AR7_GPIO_MAX)
+		return -EINVAL;
+
+	if (ar7_gpio_list[gpio])
+		return -EBUSY;
+
+	if (label)
+		ar7_gpio_list[gpio] = label;
+	else
+		ar7_gpio_list[gpio] = "busy";
+
+	return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+	BUG_ON(!ar7_gpio_list[gpio]);
+	ar7_gpio_list[gpio] = NULL;
+}
+EXPORT_SYMBOL(gpio_free);
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/irq.c linux-libre-2.6.31-gnu/arch/mips/ar7/irq.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define EXCEPT_OFFSET	0x80
+#define PACE_OFFSET	0xA0
+#define CHNLS_OFFSET	0x200
+
+#define REG_OFFSET(irq, reg)	((irq) / 32 * 0x4 + reg * 0x10)
+#define SEC_REG_OFFSET(reg)	(EXCEPT_OFFSET + reg * 0x8)
+#define SEC_SR_OFFSET		(SEC_REG_OFFSET(0))	/* 0x80 */
+#define CR_OFFSET(irq)		(REG_OFFSET(irq, 1))	/* 0x10 */
+#define SEC_CR_OFFSET		(SEC_REG_OFFSET(1))	/* 0x88 */
+#define ESR_OFFSET(irq)		(REG_OFFSET(irq, 2))	/* 0x20 */
+#define SEC_ESR_OFFSET		(SEC_REG_OFFSET(2))	/* 0x90 */
+#define ECR_OFFSET(irq)		(REG_OFFSET(irq, 3))	/* 0x30 */
+#define SEC_ECR_OFFSET		(SEC_REG_OFFSET(3))	/* 0x98 */
+#define PIR_OFFSET		(0x40)
+#define MSR_OFFSET		(0x44)
+#define PM_OFFSET(irq)		(REG_OFFSET(irq, 5))	/* 0x50 */
+#define TM_OFFSET(irq)		(REG_OFFSET(irq, 6))	/* 0x60 */
+
+#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
+
+#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
+
+static int ar7_irq_base;
+
+static void ar7_unmask_irq(unsigned int irq)
+{
+	writel(1 << ((irq - ar7_irq_base) % 32),
+	       REG(ESR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_mask_irq(unsigned int irq)
+{
+	writel(1 << ((irq - ar7_irq_base) % 32),
+	       REG(ECR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_ack_irq(unsigned int irq)
+{
+	writel(1 << ((irq - ar7_irq_base) % 32),
+	       REG(CR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_unmask_sec_irq(unsigned int irq)
+{
+	writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+}
+
+static void ar7_mask_sec_irq(unsigned int irq)
+{
+	writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+}
+
+static void ar7_ack_sec_irq(unsigned int irq)
+{
+	writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
+}
+
+static struct irq_chip ar7_irq_type = {
+	.name = "AR7",
+	.unmask = ar7_unmask_irq,
+	.mask = ar7_mask_irq,
+	.ack = ar7_ack_irq
+};
+
+static struct irq_chip ar7_sec_irq_type = {
+	.name = "AR7",
+	.unmask = ar7_unmask_sec_irq,
+	.mask = ar7_mask_sec_irq,
+	.ack = ar7_ack_sec_irq,
+};
+
+static struct irqaction ar7_cascade_action = {
+	.handler = no_action,
+	.name = "AR7 cascade interrupt"
+};
+
+static void __init ar7_irq_init(int base)
+{
+	int i;
+	/*
+	 * Disable interrupts and clear pending
+	 */
+	writel(0xffffffff, REG(ECR_OFFSET(0)));
+	writel(0xff, REG(ECR_OFFSET(32)));
+	writel(0xffffffff, REG(SEC_ECR_OFFSET));
+	writel(0xffffffff, REG(CR_OFFSET(0)));
+	writel(0xff, REG(CR_OFFSET(32)));
+	writel(0xffffffff, REG(SEC_CR_OFFSET));
+
+	ar7_irq_base = base;
+
+	for (i = 0; i < 40; i++) {
+		writel(i, REG(CHNL_OFFSET(i)));
+		/* Primary IRQ's */
+		set_irq_chip_and_handler(base + i, &ar7_irq_type,
+					 handle_level_irq);
+		/* Secondary IRQ's */
+		if (i < 32)
+			set_irq_chip_and_handler(base + i + 40,
+						 &ar7_sec_irq_type,
+						 handle_level_irq);
+	}
+
+	setup_irq(2, &ar7_cascade_action);
+	setup_irq(ar7_irq_base, &ar7_cascade_action);
+	set_c0_status(IE_IRQ0);
+}
+
+void __init arch_init_irq(void)
+{
+	mips_cpu_irq_init();
+	ar7_irq_init(8);
+}
+
+static void ar7_cascade(void)
+{
+	u32 status;
+	int i, irq;
+
+	/* Primary IRQ's */
+	irq = readl(REG(PIR_OFFSET)) & 0x3f;
+	if (irq) {
+		do_IRQ(ar7_irq_base + irq);
+		return;
+	}
+
+	/* Secondary IRQ's are cascaded through primary '0' */
+	writel(1, REG(CR_OFFSET(irq)));
+	status = readl(REG(SEC_SR_OFFSET));
+	for (i = 0; i < 32; i++) {
+		if (status & 1) {
+			do_IRQ(ar7_irq_base + i + 40);
+			return;
+		}
+		status >>= 1;
+	}
+
+	spurious_interrupt();
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+	if (pending & STATUSF_IP7)		/* cpu timer */
+		do_IRQ(7);
+	else if (pending & STATUSF_IP2)		/* int0 hardware line */
+		ar7_cascade();
+	else
+		spurious_interrupt();
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/Makefile linux-libre-2.6.31-gnu/arch/mips/ar7/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/ar7/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,11 @@
+
+obj-y := \
+	prom.o \
+	setup.o \
+	memory.o \
+	irq.o \
+	time.o \
+	platform.o \
+	gpio.o \
+	clock.o
+EXTRA_CFLAGS += -Werror
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/memory.c linux-libre-2.6.31-gnu/arch/mips/ar7/memory.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/memory.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/memory.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mips-boards/prom.h>
+
+static int __init memsize(void)
+{
+	u32 size = (64 << 20);
+	u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
+	u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
+	u32 *tmpaddr = addr;
+
+	while (tmpaddr > kernel_end) {
+		*tmpaddr = (u32)tmpaddr;
+		size >>= 1;
+		tmpaddr -= size >> 2;
+	}
+
+	do {
+		tmpaddr += size >> 2;
+		if (*tmpaddr != (u32)tmpaddr)
+			break;
+		size <<= 1;
+	} while (size < (64 << 20));
+
+	writel((u32)tmpaddr, &addr);
+
+	return size;
+}
+
+void __init prom_meminit(void)
+{
+	unsigned long pages;
+
+	pages = memsize() >> PAGE_SHIFT;
+	add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
+			  BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+	/* Nothing to free */
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/platform.c linux-libre-2.6.31-gnu/arch/mips/ar7/platform.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/vlynq.h>
+#include <linux/leds.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/prom.h>
+
+struct plat_vlynq_data {
+	struct plat_vlynq_ops ops;
+	int gpio_bit;
+	int reset_bit;
+};
+
+
+static int vlynq_on(struct vlynq_device *dev)
+{
+	int result;
+	struct plat_vlynq_data *pdata = dev->dev.platform_data;
+
+	result = gpio_request(pdata->gpio_bit, "vlynq");
+	if (result)
+		goto out;
+
+	ar7_device_reset(pdata->reset_bit);
+
+	result = ar7_gpio_disable(pdata->gpio_bit);
+	if (result)
+		goto out_enabled;
+
+	result = ar7_gpio_enable(pdata->gpio_bit);
+	if (result)
+		goto out_enabled;
+
+	result = gpio_direction_output(pdata->gpio_bit, 0);
+	if (result)
+		goto out_gpio_enabled;
+
+	msleep(50);
+
+	gpio_set_value(pdata->gpio_bit, 1);
+	msleep(50);
+
+	return 0;
+
+out_gpio_enabled:
+	ar7_gpio_disable(pdata->gpio_bit);
+out_enabled:
+	ar7_device_disable(pdata->reset_bit);
+	gpio_free(pdata->gpio_bit);
+out:
+	return result;
+}
+
+static void vlynq_off(struct vlynq_device *dev)
+{
+	struct plat_vlynq_data *pdata = dev->dev.platform_data;
+	ar7_gpio_disable(pdata->gpio_bit);
+	gpio_free(pdata->gpio_bit);
+	ar7_device_disable(pdata->reset_bit);
+}
+
+static struct resource physmap_flash_resource = {
+	.name = "mem",
+	.flags = IORESOURCE_MEM,
+	.start = 0x10000000,
+	.end = 0x107fffff,
+};
+
+static struct resource cpmac_low_res[] = {
+	{
+		.name = "regs",
+		.flags = IORESOURCE_MEM,
+		.start = AR7_REGS_MAC0,
+		.end = AR7_REGS_MAC0 + 0x7ff,
+	},
+	{
+		.name = "irq",
+		.flags = IORESOURCE_IRQ,
+		.start = 27,
+		.end = 27,
+	},
+};
+
+static struct resource cpmac_high_res[] = {
+	{
+		.name = "regs",
+		.flags = IORESOURCE_MEM,
+		.start = AR7_REGS_MAC1,
+		.end = AR7_REGS_MAC1 + 0x7ff,
+	},
+	{
+		.name = "irq",
+		.flags = IORESOURCE_IRQ,
+		.start = 41,
+		.end = 41,
+	},
+};
+
+static struct resource vlynq_low_res[] = {
+	{
+		.name = "regs",
+		.flags = IORESOURCE_MEM,
+		.start = AR7_REGS_VLYNQ0,
+		.end = AR7_REGS_VLYNQ0 + 0xff,
+	},
+	{
+		.name = "irq",
+		.flags = IORESOURCE_IRQ,
+		.start = 29,
+		.end = 29,
+	},
+	{
+		.name = "mem",
+		.flags = IORESOURCE_MEM,
+		.start = 0x04000000,
+		.end = 0x04ffffff,
+	},
+	{
+		.name = "devirq",
+		.flags = IORESOURCE_IRQ,
+		.start = 80,
+		.end = 111,
+	},
+};
+
+static struct resource vlynq_high_res[] = {
+	{
+		.name = "regs",
+		.flags = IORESOURCE_MEM,
+		.start = AR7_REGS_VLYNQ1,
+		.end = AR7_REGS_VLYNQ1 + 0xff,
+	},
+	{
+		.name = "irq",
+		.flags = IORESOURCE_IRQ,
+		.start = 33,
+		.end = 33,
+	},
+	{
+		.name = "mem",
+		.flags = IORESOURCE_MEM,
+		.start = 0x0c000000,
+		.end = 0x0cffffff,
+	},
+	{
+		.name = "devirq",
+		.flags = IORESOURCE_IRQ,
+		.start = 112,
+		.end = 143,
+	},
+};
+
+static struct resource usb_res[] = {
+	{
+		.name = "regs",
+		.flags = IORESOURCE_MEM,
+		.start = AR7_REGS_USB,
+		.end = AR7_REGS_USB + 0xff,
+	},
+	{
+		.name = "irq",
+		.flags = IORESOURCE_IRQ,
+		.start = 32,
+		.end = 32,
+	},
+	{
+		.name = "mem",
+		.flags = IORESOURCE_MEM,
+		.start = 0x03400000,
+		.end = 0x034001fff,
+	},
+};
+
+static struct physmap_flash_data physmap_flash_data = {
+	.width = 2,
+};
+
+static struct plat_cpmac_data cpmac_low_data = {
+	.reset_bit = 17,
+	.power_bit = 20,
+	.phy_mask = 0x80000000,
+};
+
+static struct plat_cpmac_data cpmac_high_data = {
+	.reset_bit = 21,
+	.power_bit = 22,
+	.phy_mask = 0x7fffffff,
+};
+
+static struct plat_vlynq_data vlynq_low_data = {
+	.ops.on = vlynq_on,
+	.ops.off = vlynq_off,
+	.reset_bit = 20,
+	.gpio_bit = 18,
+};
+
+static struct plat_vlynq_data vlynq_high_data = {
+	.ops.on = vlynq_on,
+	.ops.off = vlynq_off,
+	.reset_bit = 16,
+	.gpio_bit = 19,
+};
+
+static struct platform_device physmap_flash = {
+	.id = 0,
+	.name = "physmap-flash",
+	.dev.platform_data = &physmap_flash_data,
+	.resource = &physmap_flash_resource,
+	.num_resources = 1,
+};
+
+static u64 cpmac_dma_mask = DMA_BIT_MASK(32);
+static struct platform_device cpmac_low = {
+	.id = 0,
+	.name = "cpmac",
+	.dev = {
+		.dma_mask = &cpmac_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &cpmac_low_data,
+	},
+	.resource = cpmac_low_res,
+	.num_resources = ARRAY_SIZE(cpmac_low_res),
+};
+
+static struct platform_device cpmac_high = {
+	.id = 1,
+	.name = "cpmac",
+	.dev = {
+		.dma_mask = &cpmac_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &cpmac_high_data,
+	},
+	.resource = cpmac_high_res,
+	.num_resources = ARRAY_SIZE(cpmac_high_res),
+};
+
+static struct platform_device vlynq_low = {
+	.id = 0,
+	.name = "vlynq",
+	.dev.platform_data = &vlynq_low_data,
+	.resource = vlynq_low_res,
+	.num_resources = ARRAY_SIZE(vlynq_low_res),
+};
+
+static struct platform_device vlynq_high = {
+	.id = 1,
+	.name = "vlynq",
+	.dev.platform_data = &vlynq_high_data,
+	.resource = vlynq_high_res,
+	.num_resources = ARRAY_SIZE(vlynq_high_res),
+};
+
+
+static struct gpio_led default_leds[] = {
+	{
+		.name = "status",
+		.gpio = 8,
+		.active_low = 1,
+	},
+};
+
+static struct gpio_led dsl502t_leds[] = {
+	{
+		.name = "status",
+		.gpio = 9,
+		.active_low = 1,
+	},
+	{
+		.name = "ethernet",
+		.gpio = 7,
+		.active_low = 1,
+	},
+	{
+		.name = "usb",
+		.gpio = 12,
+		.active_low = 1,
+	},
+};
+
+static struct gpio_led dg834g_leds[] = {
+	{
+		.name = "ppp",
+		.gpio = 6,
+		.active_low = 1,
+	},
+	{
+		.name = "status",
+		.gpio = 7,
+		.active_low = 1,
+	},
+	{
+		.name = "adsl",
+		.gpio = 8,
+		.active_low = 1,
+	},
+	{
+		.name = "wifi",
+		.gpio = 12,
+		.active_low = 1,
+	},
+	{
+		.name = "power",
+		.gpio = 14,
+		.active_low = 1,
+		.default_trigger = "default-on",
+	},
+};
+
+static struct gpio_led fb_sl_leds[] = {
+	{
+		.name = "1",
+		.gpio = 7,
+	},
+	{
+		.name = "2",
+		.gpio = 13,
+		.active_low = 1,
+	},
+	{
+		.name = "3",
+		.gpio = 10,
+		.active_low = 1,
+	},
+	{
+		.name = "4",
+		.gpio = 12,
+		.active_low = 1,
+	},
+	{
+		.name = "5",
+		.gpio = 9,
+		.active_low = 1,
+	},
+};
+
+static struct gpio_led fb_fon_leds[] = {
+	{
+		.name = "1",
+		.gpio = 8,
+	},
+	{
+		.name = "2",
+		.gpio = 3,
+		.active_low = 1,
+	},
+	{
+		.name = "3",
+		.gpio = 5,
+	},
+	{
+		.name = "4",
+		.gpio = 4,
+		.active_low = 1,
+	},
+	{
+		.name = "5",
+		.gpio = 11,
+		.active_low = 1,
+	},
+};
+
+static struct gpio_led_platform_data ar7_led_data;
+
+static struct platform_device ar7_gpio_leds = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev = {
+		.platform_data = &ar7_led_data,
+	}
+};
+
+static struct platform_device ar7_udc = {
+	.id = -1,
+	.name = "ar7_udc",
+	.resource = usb_res,
+	.num_resources = ARRAY_SIZE(usb_res),
+};
+
+static inline unsigned char char2hex(char h)
+{
+	switch (h) {
+	case '0': case '1': case '2': case '3': case '4':
+	case '5': case '6': case '7': case '8': case '9':
+		return h - '0';
+	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+		return h - 'A' + 10;
+	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+		return h - 'a' + 10;
+	default:
+		return 0;
+	}
+}
+
+static void cpmac_get_mac(int instance, unsigned char *dev_addr)
+{
+	int i;
+	char name[5], default_mac[ETH_ALEN], *mac;
+
+	mac = NULL;
+	sprintf(name, "mac%c", 'a' + instance);
+	mac = prom_getenv(name);
+	if (!mac) {
+		sprintf(name, "mac%c", 'a');
+		mac = prom_getenv(name);
+	}
+	if (!mac) {
+		random_ether_addr(default_mac);
+		mac = default_mac;
+	}
+	for (i = 0; i < 6; i++)
+		dev_addr[i] = (char2hex(mac[i * 3]) << 4) +
+			char2hex(mac[i * 3 + 1]);
+}
+
+static void __init detect_leds(void)
+{
+	char *prid, *usb_prod;
+
+	/* Default LEDs	*/
+	ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
+	ar7_led_data.leds = default_leds;
+
+	/* FIXME: the whole thing is unreliable */
+	prid = prom_getenv("ProductID");
+	usb_prod = prom_getenv("usb_prod");
+
+	/* If we can't get the product id from PROM, use the default LEDs */
+	if (!prid)
+		return;
+
+	if (strstr(prid, "Fritz_Box_FON")) {
+		ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
+		ar7_led_data.leds = fb_fon_leds;
+	} else if (strstr(prid, "Fritz_Box_")) {
+		ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
+		ar7_led_data.leds = fb_sl_leds;
+	} else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
+		&& usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
+		ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
+		ar7_led_data.leds = dsl502t_leds;
+	} else if (strstr(prid, "DG834")) {
+		ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
+		ar7_led_data.leds = dg834g_leds;
+	}
+}
+
+static int __init ar7_register_devices(void)
+{
+	int res;
+#ifdef CONFIG_SERIAL_8250
+	static struct uart_port uart_port[2];
+
+	memset(uart_port, 0, sizeof(struct uart_port) * 2);
+
+	uart_port[0].type = PORT_16550A;
+	uart_port[0].line = 0;
+	uart_port[0].irq = AR7_IRQ_UART0;
+	uart_port[0].uartclk = ar7_bus_freq() / 2;
+	uart_port[0].iotype = UPIO_MEM32;
+	uart_port[0].mapbase = AR7_REGS_UART0;
+	uart_port[0].membase = ioremap(uart_port[0].mapbase, 256);
+	uart_port[0].regshift = 2;
+	res = early_serial_setup(&uart_port[0]);
+	if (res)
+		return res;
+
+
+	/* Only TNETD73xx have a second serial port */
+	if (ar7_has_second_uart()) {
+		uart_port[1].type = PORT_16550A;
+		uart_port[1].line = 1;
+		uart_port[1].irq = AR7_IRQ_UART1;
+		uart_port[1].uartclk = ar7_bus_freq() / 2;
+		uart_port[1].iotype = UPIO_MEM32;
+		uart_port[1].mapbase = UR8_REGS_UART1;
+		uart_port[1].membase = ioremap(uart_port[1].mapbase, 256);
+		uart_port[1].regshift = 2;
+		res = early_serial_setup(&uart_port[1]);
+		if (res)
+			return res;
+	}
+#endif /* CONFIG_SERIAL_8250 */
+	res = platform_device_register(&physmap_flash);
+	if (res)
+		return res;
+
+	ar7_device_disable(vlynq_low_data.reset_bit);
+	res = platform_device_register(&vlynq_low);
+	if (res)
+		return res;
+
+	if (ar7_has_high_vlynq()) {
+		ar7_device_disable(vlynq_high_data.reset_bit);
+		res = platform_device_register(&vlynq_high);
+		if (res)
+			return res;
+	}
+
+	if (ar7_has_high_cpmac()) {
+		cpmac_get_mac(1, cpmac_high_data.dev_addr);
+		res = platform_device_register(&cpmac_high);
+		if (res)
+			return res;
+	} else {
+		cpmac_low_data.phy_mask = 0xffffffff;
+	}
+
+	cpmac_get_mac(0, cpmac_low_data.dev_addr);
+	res = platform_device_register(&cpmac_low);
+	if (res)
+		return res;
+
+	detect_leds();
+	res = platform_device_register(&ar7_gpio_leds);
+	if (res)
+		return res;
+
+	res = platform_device_register(&ar7_udc);
+
+	return res;
+}
+arch_initcall(ar7_register_devices);
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/prom.c linux-libre-2.6.31-gnu/arch/mips/ar7/prom.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/prom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/prom.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,297 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <asm/bootinfo.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+#define MAX_ENTRY 80
+
+struct env_var {
+	char *name;
+	char *value;
+};
+
+static struct env_var adam2_env[MAX_ENTRY];
+
+char *prom_getenv(const char *name)
+{
+	int i;
+	for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++)
+		if (!strcmp(name, adam2_env[i].name))
+			return adam2_env[i].value;
+
+	return NULL;
+}
+EXPORT_SYMBOL(prom_getenv);
+
+char * __init prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+static void  __init ar7_init_cmdline(int argc, char *argv[])
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while (actr < argc) {
+		strcpy(cp, argv[actr]);
+		cp += strlen(argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) {
+		/* get rid of trailing space */
+		--cp;
+		*cp = '\0';
+	}
+}
+
+struct psbl_rec {
+	u32 psbl_size;
+	u32 env_base;
+	u32 env_size;
+	u32 ffs_base;
+	u32 ffs_size;
+};
+
+static __initdata char psp_env_version[] = "TIENV0.8";
+
+struct psp_env_chunk {
+	u8 num;
+	u8 ctrl;
+	u16 csum;
+	u8 len;
+	char data[11];
+} __attribute__ ((packed));
+
+struct psp_var_map_entry {
+	u8 num;
+	char *value;
+};
+
+static struct psp_var_map_entry psp_var_map[] = {
+	{ 1, "cpufrequency" },
+	{ 2, "memsize" },
+	{ 3, "flashsize" },
+	{ 4, "modetty0" },
+	{ 5, "modetty1" },
+	{ 8, "maca" },
+	{ 9, "macb" },
+	{ 28, "sysfrequency" },
+	{ 38, "mipsfrequency" },
+};
+
+/*
+
+Well-known variable (num is looked up in table above for matching variable name)
+Example: cpufrequency=211968000
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in a single chunk
+Example: NAME=VALUE
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in 2 chunks (len is the number of chunks)
+Example: bootloaderVersion=1.3.7.15
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Data is padded with 0xFF
+
+*/
+
+#define PSP_ENV_SIZE  4096
+
+static char psp_env_data[PSP_ENV_SIZE] = { 0, };
+
+static char * __init lookup_psp_var_map(u8 num)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(psp_var_map); i++)
+		if (psp_var_map[i].num == num)
+			return psp_var_map[i].value;
+
+	return NULL;
+}
+
+static void __init add_adam2_var(char *name, char *value)
+{
+	int i;
+	for (i = 0; i < MAX_ENTRY; i++) {
+		if (!adam2_env[i].name) {
+			adam2_env[i].name = name;
+			adam2_env[i].value = value;
+			return;
+		} else if (!strcmp(adam2_env[i].name, name)) {
+			adam2_env[i].value = value;
+			return;
+		}
+	}
+}
+
+static int __init parse_psp_env(void *psp_env_base)
+{
+	int i, n;
+	char *name, *value;
+	struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
+
+	memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
+
+	i = 1;
+	n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
+	while (i < n) {
+		if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
+			break;
+		value = chunks[i].data;
+		if (chunks[i].num) {
+			name = lookup_psp_var_map(chunks[i].num);
+		} else {
+			name = value;
+			value += strlen(name) + 1;
+		}
+		if (name)
+			add_adam2_var(name, value);
+		i += chunks[i].len;
+	}
+	return 0;
+}
+
+static void __init ar7_init_env(struct env_var *env)
+{
+	int i;
+	struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
+	void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
+
+	if (strcmp(psp_env, psp_env_version) == 0) {
+		parse_psp_env(psp_env);
+	} else {
+		for (i = 0; i < MAX_ENTRY; i++, env++)
+			if (env->name)
+				add_adam2_var(env->name, env->value);
+	}
+}
+
+static void __init console_config(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+	char console_string[40];
+	int baud = 0;
+	char parity = '\0', bits = '\0', flow = '\0';
+	char *s, *p;
+
+	if (strstr(prom_getcmdline(), "console="))
+		return;
+
+#ifdef CONFIG_KGDB
+	if (!strstr(prom_getcmdline(), "nokgdb")) {
+		strcat(prom_getcmdline(), " console=kgdb");
+		kgdb_enabled = 1;
+		return;
+	}
+#endif
+
+	s = prom_getenv("modetty0");
+	if (s) {
+		baud = simple_strtoul(s, &p, 10);
+		s = p;
+		if (*s == ',')
+			s++;
+		if (*s)
+			parity = *s++;
+		if (*s == ',')
+			s++;
+		if (*s)
+			bits = *s++;
+		if (*s == ',')
+			s++;
+		if (*s == 'h')
+			flow = 'r';
+	}
+
+	if (baud == 0)
+		baud = 38400;
+	if (parity != 'n' && parity != 'o' && parity != 'e')
+		parity = 'n';
+	if (bits != '7' && bits != '8')
+		bits = '8';
+
+	if (flow == 'r')
+		sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+			parity, bits, flow);
+	else
+		sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
+			bits);
+	strcat(prom_getcmdline(), console_string);
+#endif
+}
+
+void __init prom_init(void)
+{
+	ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
+	ar7_init_env((struct env_var *)fw_arg2);
+	console_config();
+}
+
+#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
+static inline unsigned int serial_in(int offset)
+{
+	return readl((void *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+	writel(value, (void *)PORT(offset));
+}
+
+char prom_getchar(void)
+{
+	while (!(serial_in(UART_LSR) & UART_LSR_DR))
+		;
+	return serial_in(UART_RX);
+}
+
+int prom_putchar(char c)
+{
+	while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
+		;
+	serial_out(UART_TX, c);
+	return 1;
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/setup.c linux-libre-2.6.31-gnu/arch/mips/ar7/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,93 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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/init.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+#include <linux/time.h>
+
+#include <asm/reboot.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+static void ar7_machine_restart(char *command)
+{
+	u32 *softres_reg = ioremap(AR7_REGS_RESET +
+					  AR7_RESET_SOFTWARE, 1);
+	writel(1, softres_reg);
+}
+
+static void ar7_machine_halt(void)
+{
+	while (1)
+		;
+}
+
+static void ar7_machine_power_off(void)
+{
+	u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1);
+	u32 power_state = readl(power_reg) | (3 << 30);
+	writel(power_state, power_reg);
+	ar7_machine_halt();
+}
+
+const char *get_system_type(void)
+{
+	u16 chip_id = ar7_chip_id();
+	switch (chip_id) {
+	case AR7_CHIP_7300:
+		return "TI AR7 (TNETD7300)";
+	case AR7_CHIP_7100:
+		return "TI AR7 (TNETD7100)";
+	case AR7_CHIP_7200:
+		return "TI AR7 (TNETD7200)";
+	default:
+		return "TI AR7 (Unknown)";
+	}
+}
+
+static int __init ar7_init_console(void)
+{
+	return 0;
+}
+console_initcall(ar7_init_console);
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+
+void __init plat_mem_setup(void)
+{
+	unsigned long io_base;
+
+	_machine_restart = ar7_machine_restart;
+	_machine_halt = ar7_machine_halt;
+	pm_power_off = ar7_machine_power_off;
+	panic_timeout = 3;
+
+	io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
+	if (!io_base)
+		panic("Can't remap IO base!\n");
+	set_io_port_base(io_base);
+
+	prom_meminit();
+
+	printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
+					get_system_type(),
+		ar7_chip_id(), ar7_chip_rev());
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/ar7/time.c linux-libre-2.6.31-gnu/arch/mips/ar7/time.c
--- linux-libre-2.6.30-gnu/arch/mips/ar7/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/ar7/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+
+#include <asm/time.h>
+#include <asm/mach-ar7/ar7.h>
+
+void __init plat_time_init(void)
+{
+	mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/dma-octeon.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/dma-octeon.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/dma-octeon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/dma-octeon.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,20 +13,327 @@
  */
 #include <linux/types.h>
 #include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+
+#include <linux/cache.h>
+#include <linux/io.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
 
 #include <dma-coherence.h>
 
+#ifdef CONFIG_PCI
+#include <asm/octeon/pci-octeon.h>
+#endif
+
+#define BAR2_PCI_ADDRESS 0x8000000000ul
+
+struct bar1_index_state {
+	int16_t ref_count;	/* Number of PCI mappings using this index */
+	uint16_t address_bits;	/* Upper bits of physical address. This is
+				   shifted 22 bits */
+};
+
+#ifdef CONFIG_PCI
+static DEFINE_SPINLOCK(bar1_lock);
+static struct bar1_index_state bar1_state[32];
+#endif
+
 dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
 {
+#ifndef CONFIG_PCI
 	/* Without PCI/PCIe this function can be called for Octeon internal
 	   devices such as USB. These devices all support 64bit addressing */
 	mb();
 	return virt_to_phys(ptr);
+#else
+	unsigned long flags;
+	uint64_t dma_mask;
+	int64_t start_index;
+	dma_addr_t result = -1;
+	uint64_t physical = virt_to_phys(ptr);
+	int64_t index;
+
+	mb();
+	/*
+	 * Use the DMA masks to determine the allowed memory
+	 * region. For us it doesn't limit the actual memory, just the
+	 * address visible over PCI.  Devices with limits need to use
+	 * lower indexed Bar1 entries.
+	 */
+	if (dev) {
+		dma_mask = dev->coherent_dma_mask;
+		if (dev->dma_mask)
+			dma_mask = *dev->dma_mask;
+	} else {
+		dma_mask = 0xfffffffful;
+	}
+
+	/*
+	 * Platform devices, such as the internal USB, skip all
+	 * translation and use Octeon physical addresses directly.
+	 */
+	if (!dev || dev->bus == &platform_bus_type)
+		return physical;
+
+	switch (octeon_dma_bar_type) {
+	case OCTEON_DMA_BAR_TYPE_PCIE:
+		if (unlikely(physical < (16ul << 10)))
+			panic("dma_map_single: Not allowed to map first 16KB."
+			      " It interferes with BAR0 special area\n");
+		else if ((physical + size >= (256ul << 20)) &&
+			 (physical < (512ul << 20)))
+			panic("dma_map_single: Not allowed to map bootbus\n");
+		else if ((physical + size >= 0x400000000ull) &&
+			 physical < 0x410000000ull)
+			panic("dma_map_single: "
+			      "Attempt to map illegal memory address 0x%llx\n",
+			      physical);
+		else if (physical >= 0x420000000ull)
+			panic("dma_map_single: "
+			      "Attempt to map illegal memory address 0x%llx\n",
+			      physical);
+		else if ((physical + size >=
+			  (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20))
+			 && physical < (4ull<<30))
+			pr_warning("dma_map_single: Warning: "
+				   "Mapping memory address that might "
+				   "conflict with devices 0x%llx-0x%llx\n",
+				   physical, physical+size-1);
+		/* The 2nd 256MB is mapped at 256<<20 instead of 0x410000000 */
+		if ((physical >= 0x410000000ull) && physical < 0x420000000ull)
+			result = physical - 0x400000000ull;
+		else
+			result = physical;
+		if (((result+size-1) & dma_mask) != result+size-1)
+			panic("dma_map_single: Attempt to map address "
+			      "0x%llx-0x%llx, which can't be accessed "
+			      "according to the dma mask 0x%llx\n",
+			      physical, physical+size-1, dma_mask);
+		goto done;
+
+	case OCTEON_DMA_BAR_TYPE_BIG:
+#ifdef CONFIG_64BIT
+		/* If the device supports 64bit addressing, then use BAR2 */
+		if (dma_mask > BAR2_PCI_ADDRESS) {
+			result = physical + BAR2_PCI_ADDRESS;
+			goto done;
+		}
+#endif
+		if (unlikely(physical < (4ul << 10))) {
+			panic("dma_map_single: Not allowed to map first 4KB. "
+			      "It interferes with BAR0 special area\n");
+		} else if (physical < (256ul << 20)) {
+			if (unlikely(physical + size > (256ul << 20)))
+				panic("dma_map_single: Requested memory spans "
+				      "Bar0 0:256MB and bootbus\n");
+			result = physical;
+			goto done;
+		} else if (unlikely(physical < (512ul << 20))) {
+			panic("dma_map_single: Not allowed to map bootbus\n");
+		} else if (physical < (2ul << 30)) {
+			if (unlikely(physical + size > (2ul << 30)))
+				panic("dma_map_single: Requested memory spans "
+				      "Bar0 512MB:2GB and BAR1\n");
+			result = physical;
+			goto done;
+		} else if (physical < (2ul << 30) + (128 << 20)) {
+			/* Fall through */
+		} else if (physical <
+			   (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) {
+			if (unlikely
+			    (physical + size >
+			     (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)))
+				panic("dma_map_single: Requested memory "
+				      "extends past Bar1 (4GB-%luMB)\n",
+				      OCTEON_PCI_BAR1_HOLE_SIZE);
+			result = physical;
+			goto done;
+		} else if ((physical >= 0x410000000ull) &&
+			   (physical < 0x420000000ull)) {
+			if (unlikely(physical + size > 0x420000000ull))
+				panic("dma_map_single: Requested memory spans "
+				      "non existant memory\n");
+			/* BAR0 fixed mapping 256MB:512MB ->
+			 * 16GB+256MB:16GB+512MB */
+			result = physical - 0x400000000ull;
+			goto done;
+		} else {
+			/* Continued below switch statement */
+		}
+		break;
+
+	case OCTEON_DMA_BAR_TYPE_SMALL:
+#ifdef CONFIG_64BIT
+		/* If the device supports 64bit addressing, then use BAR2 */
+		if (dma_mask > BAR2_PCI_ADDRESS) {
+			result = physical + BAR2_PCI_ADDRESS;
+			goto done;
+		}
+#endif
+		/* Continued below switch statement */
+		break;
+
+	default:
+		panic("dma_map_single: Invalid octeon_dma_bar_type\n");
+	}
+
+	/* Don't allow mapping to span multiple Bar entries. The hardware guys
+	   won't guarantee that DMA across boards work */
+	if (unlikely((physical >> 22) != ((physical + size - 1) >> 22)))
+		panic("dma_map_single: "
+		      "Requested memory spans more than one Bar1 entry\n");
+
+	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
+		start_index = 31;
+	else if (unlikely(dma_mask < (1ul << 27)))
+		start_index = (dma_mask >> 22);
+	else
+		start_index = 31;
+
+	/* Only one processor can access the Bar register at once */
+	spin_lock_irqsave(&bar1_lock, flags);
+
+	/* Look through Bar1 for existing mapping that will work */
+	for (index = start_index; index >= 0; index--) {
+		if ((bar1_state[index].address_bits == physical >> 22) &&
+		    (bar1_state[index].ref_count)) {
+			/* An existing mapping will work, use it */
+			bar1_state[index].ref_count++;
+			if (unlikely(bar1_state[index].ref_count < 0))
+				panic("dma_map_single: "
+				      "Bar1[%d] reference count overflowed\n",
+				      (int) index);
+			result = (index << 22) | (physical & ((1 << 22) - 1));
+			/* Large BAR1 is offset at 2GB */
+			if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
+				result += 2ul << 30;
+			goto done_unlock;
+		}
+	}
+
+	/* No existing mappings, look for a free entry */
+	for (index = start_index; index >= 0; index--) {
+		if (unlikely(bar1_state[index].ref_count == 0)) {
+			union cvmx_pci_bar1_indexx bar1_index;
+			/* We have a free entry, use it */
+			bar1_state[index].ref_count = 1;
+			bar1_state[index].address_bits = physical >> 22;
+			bar1_index.u32 = 0;
+			/* Address bits[35:22] sent to L2C */
+			bar1_index.s.addr_idx = physical >> 22;
+			/* Don't put PCI accesses in L2. */
+			bar1_index.s.ca = 1;
+			/* Endian Swap Mode */
+			bar1_index.s.end_swp = 1;
+			/* Set '1' when the selected address range is valid. */
+			bar1_index.s.addr_v = 1;
+			octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index),
+					   bar1_index.u32);
+			/* An existing mapping will work, use it */
+			result = (index << 22) | (physical & ((1 << 22) - 1));
+			/* Large BAR1 is offset at 2GB */
+			if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
+				result += 2ul << 30;
+			goto done_unlock;
+		}
+	}
+
+	pr_err("dma_map_single: "
+	       "Can't find empty BAR1 index for physical mapping 0x%llx\n",
+	       (unsigned long long) physical);
+
+done_unlock:
+	spin_unlock_irqrestore(&bar1_lock, flags);
+done:
+	pr_debug("dma_map_single 0x%llx->0x%llx\n", physical, result);
+	return result;
+#endif
 }
 
 void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
 {
-	/* Without PCI/PCIe this function can be called for Octeon internal
-	 * devices such as USB. These devices all support 64bit addressing */
+#ifndef CONFIG_PCI
+	/*
+	 * Without PCI/PCIe this function can be called for Octeon internal
+	 * devices such as USB. These devices all support 64bit addressing.
+	 */
 	return;
+#else
+	unsigned long flags;
+	uint64_t index;
+
+	/*
+	 * Platform devices, such as the internal USB, skip all
+	 * translation and use Octeon physical addresses directly.
+	 */
+	if (dev->bus == &platform_bus_type)
+		return;
+
+	switch (octeon_dma_bar_type) {
+	case OCTEON_DMA_BAR_TYPE_PCIE:
+		/* Nothing to do, all mappings are static */
+		goto done;
+
+	case OCTEON_DMA_BAR_TYPE_BIG:
+#ifdef CONFIG_64BIT
+		/* Nothing to do for addresses using BAR2 */
+		if (dma_addr >= BAR2_PCI_ADDRESS)
+			goto done;
+#endif
+		if (unlikely(dma_addr < (4ul << 10)))
+			panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
+			      dma_addr);
+		else if (dma_addr < (2ul << 30))
+			/* Nothing to do for addresses using BAR0 */
+			goto done;
+		else if (dma_addr < (2ul << 30) + (128ul << 20))
+			/* Need to unmap, fall through */
+			index = (dma_addr - (2ul << 30)) >> 22;
+		else if (dma_addr <
+			 (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20))
+			goto done;	/* Nothing to do for the rest of BAR1 */
+		else
+			panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
+			      dma_addr);
+		/* Continued below switch statement */
+		break;
+
+	case OCTEON_DMA_BAR_TYPE_SMALL:
+#ifdef CONFIG_64BIT
+		/* Nothing to do for addresses using BAR2 */
+		if (dma_addr >= BAR2_PCI_ADDRESS)
+			goto done;
+#endif
+		index = dma_addr >> 22;
+		/* Continued below switch statement */
+		break;
+
+	default:
+		panic("dma_unmap_single: Invalid octeon_dma_bar_type\n");
+	}
+
+	if (unlikely(index > 31))
+		panic("dma_unmap_single: "
+		      "Attempt to unmap an invalid address (0x%llx)\n",
+		      dma_addr);
+
+	spin_lock_irqsave(&bar1_lock, flags);
+	bar1_state[index].ref_count--;
+	if (bar1_state[index].ref_count == 0)
+		octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0);
+	else if (unlikely(bar1_state[index].ref_count < 0))
+		panic("dma_unmap_single: Bar1[%u] reference count < 0\n",
+		      (int) index);
+	spin_unlock_irqrestore(&bar1_lock, flags);
+done:
+	pr_debug("dma_unmap_single 0x%llx\n", dma_addr);
+	return;
+#endif
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-bootmem.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-bootmem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-bootmem.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-spinlock.h>
@@ -97,6 +98,33 @@
 	return cvmx_bootmem_alloc_range(size, alignment, 0, 0);
 }
 
+void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
+				     uint64_t max_addr, uint64_t align,
+				     char *name)
+{
+	int64_t addr;
+
+	addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr,
+						  align, name, 0);
+	if (addr >= 0)
+		return cvmx_phys_to_ptr(addr);
+	else
+		return NULL;
+}
+
+void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address,
+				       char *name)
+{
+    return cvmx_bootmem_alloc_named_range(size, address, address + size,
+					  0, name);
+}
+
+void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name)
+{
+    return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name);
+}
+EXPORT_SYMBOL(cvmx_bootmem_alloc_named);
+
 int cvmx_bootmem_free_named(char *name)
 {
 	return cvmx_bootmem_phy_named_block_free(name, 0);
@@ -106,6 +134,7 @@
 {
 	return cvmx_bootmem_phy_named_block_find(name, 0);
 }
+EXPORT_SYMBOL(cvmx_bootmem_find_named_block);
 
 void cvmx_bootmem_lock(void)
 {
@@ -584,3 +613,78 @@
 	cvmx_bootmem_unlock();
 	return named_block_ptr != NULL;	/* 0 on failure, 1 on success */
 }
+
+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
+					   uint64_t max_addr,
+					   uint64_t alignment,
+					   char *name,
+					   uint32_t flags)
+{
+	int64_t addr_allocated;
+	struct cvmx_bootmem_named_block_desc *named_block_desc_ptr;
+
+#ifdef DEBUG
+	cvmx_dprintf("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: "
+		     "0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n",
+		     (unsigned long long)size,
+		     (unsigned long long)min_addr,
+		     (unsigned long long)max_addr,
+		     (unsigned long long)alignment,
+		     name);
+#endif
+	if (cvmx_bootmem_desc->major_version != 3) {
+		cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: "
+			     "%d.%d at addr: %p\n",
+			     (int)cvmx_bootmem_desc->major_version,
+			     (int)cvmx_bootmem_desc->minor_version,
+			     cvmx_bootmem_desc);
+		return -1;
+	}
+
+	/*
+	 * Take lock here, as name lookup/block alloc/name add need to
+	 * be atomic.
+	 */
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_lock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
+
+	/* Get pointer to first available named block descriptor */
+	named_block_desc_ptr =
+		cvmx_bootmem_phy_named_block_find(NULL,
+						  flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
+
+	/*
+	 * Check to see if name already in use, return error if name
+	 * not available or no more room for blocks.
+	 */
+	if (cvmx_bootmem_phy_named_block_find(name,
+					      flags | CVMX_BOOTMEM_FLAG_NO_LOCKING) || !named_block_desc_ptr) {
+		if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+			cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
+		return -1;
+	}
+
+
+	/*
+	 * Round size up to mult of minimum alignment bytes We need
+	 * the actual size allocated to allow for blocks to be
+	 * coallesced when they are freed.  The alloc routine does the
+	 * same rounding up on all allocations.
+	 */
+	size = __ALIGN_MASK(size, (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1));
+
+	addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr,
+						alignment,
+						flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
+	if (addr_allocated >= 0) {
+		named_block_desc_ptr->base_addr = addr_allocated;
+		named_block_desc_ptr->size = size;
+		strncpy(named_block_desc_ptr->name, name,
+			cvmx_bootmem_desc->named_block_name_len);
+		named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0;
+	}
+
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
+	return addr_allocated;
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-errata.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,73 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ *
+ * Fixes and workaround for Octeon chip errata. This file
+ * contains functions called by cvmx-helper to workaround known
+ * chip errata. For the most part, code doesn't need to call
+ * these functions directly.
+ *
+ */
+#include <linux/module.h>
+
+#include <asm/octeon/octeon.h>
+
+#include <asm/octeon/cvmx-helper-jtag.h>
+
+/**
+ * Due to errata G-720, the 2nd order CDR circuit on CN52XX pass
+ * 1 doesn't work properly. The following code disables 2nd order
+ * CDR for the specified QLM.
+ *
+ * @qlm:    QLM to disable 2nd order CDR for.
+ */
+void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm)
+{
+	int lane;
+	cvmx_helper_qlm_jtag_init();
+	/* We need to load all four lanes of the QLM, a total of 1072 bits */
+	for (lane = 0; lane < 4; lane++) {
+		/*
+		 * Each lane has 268 bits. We need to set
+		 * cfg_cdr_incx<67:64> = 3 and cfg_cdr_secord<77> =
+		 * 1. All other bits are zero. Bits go in LSB first,
+		 * so start off with the zeros for bits <63:0>.
+		 */
+		cvmx_helper_qlm_jtag_shift_zeros(qlm, 63 - 0 + 1);
+		/* cfg_cdr_incx<67:64>=3 */
+		cvmx_helper_qlm_jtag_shift(qlm, 67 - 64 + 1, 3);
+		/* Zeros for bits <76:68> */
+		cvmx_helper_qlm_jtag_shift_zeros(qlm, 76 - 68 + 1);
+		/* cfg_cdr_secord<77>=1 */
+		cvmx_helper_qlm_jtag_shift(qlm, 77 - 77 + 1, 1);
+		/* Zeros for bits <267:78> */
+		cvmx_helper_qlm_jtag_shift_zeros(qlm, 267 - 78 + 1);
+	}
+	cvmx_helper_qlm_jtag_update(qlm);
+}
+EXPORT_SYMBOL(__cvmx_helper_errata_qlm_disable_2nd_order_cdr);
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-helper-jtag.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,144 @@
+
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ *
+ * Helper utilities for qlm_jtag.
+ *
+ */
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-helper-jtag.h>
+
+
+/**
+ * Initialize the internal QLM JTAG logic to allow programming
+ * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions.
+ * These functions should only be used at the direction of Cavium
+ * Networks. Programming incorrect values into the JTAG chain
+ * can cause chip damage.
+ */
+void cvmx_helper_qlm_jtag_init(void)
+{
+	union cvmx_ciu_qlm_jtgc jtgc;
+	uint32_t clock_div = 0;
+	uint32_t divisor = cvmx_sysinfo_get()->cpu_clock_hz / (25 * 1000000);
+	divisor = (divisor - 1) >> 2;
+	/* Convert the divisor into a power of 2 shift */
+	while (divisor) {
+		clock_div++;
+		divisor = divisor >> 1;
+	}
+
+	/*
+	 * Clock divider for QLM JTAG operations.  eclk is divided by
+	 * 2^(CLK_DIV + 2)
+	 */
+	jtgc.u64 = 0;
+	jtgc.s.clk_div = clock_div;
+	jtgc.s.mux_sel = 0;
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX))
+		jtgc.s.bypass = 0x3;
+	else
+		jtgc.s.bypass = 0xf;
+	cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64);
+	cvmx_read_csr(CVMX_CIU_QLM_JTGC);
+}
+
+/**
+ * Write up to 32bits into the QLM jtag chain. Bits are shifted
+ * into the MSB and out the LSB, so you should shift in the low
+ * order bits followed by the high order bits. The JTAG chain is
+ * 4 * 268 bits long, or 1072.
+ *
+ * @qlm:    QLM to shift value into
+ * @bits:   Number of bits to shift in (1-32).
+ * @data:   Data to shift in. Bit 0 enters the chain first, followed by
+ *               bit 1, etc.
+ *
+ * Returns The low order bits of the JTAG chain that shifted out of the
+ *         circle.
+ */
+uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data)
+{
+	union cvmx_ciu_qlm_jtgd jtgd;
+	jtgd.u64 = 0;
+	jtgd.s.shift = 1;
+	jtgd.s.shft_cnt = bits - 1;
+	jtgd.s.shft_reg = data;
+	if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X))
+		jtgd.s.select = 1 << qlm;
+	cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64);
+	do {
+		jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD);
+	} while (jtgd.s.shift);
+	return jtgd.s.shft_reg >> (32 - bits);
+}
+
+/**
+ * Shift long sequences of zeros into the QLM JTAG chain. It is
+ * common to need to shift more than 32 bits of zeros into the
+ * chain. This function is a convience wrapper around
+ * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of
+ * zeros at a time.
+ *
+ * @qlm:    QLM to shift zeros into
+ * @bits:
+ */
+void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits)
+{
+	while (bits > 0) {
+		int n = bits;
+		if (n > 32)
+			n = 32;
+		cvmx_helper_qlm_jtag_shift(qlm, n, 0);
+		bits -= n;
+	}
+}
+
+/**
+ * Program the QLM JTAG chain into all lanes of the QLM. You must
+ * have already shifted in 268*4, or 1072 bits into the JTAG
+ * chain. Updating invalid values can possibly cause chip damage.
+ *
+ * @qlm:    QLM to program
+ */
+void cvmx_helper_qlm_jtag_update(int qlm)
+{
+	union cvmx_ciu_qlm_jtgd jtgd;
+
+	/* Update the new data */
+	jtgd.u64 = 0;
+	jtgd.s.update = 1;
+	if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X))
+		jtgd.s.select = 1 << qlm;
+	cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64);
+	do {
+		jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD);
+	} while (jtgd.s.update);
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,7 @@
  * This module provides system/board/application information obtained
  * by the bootloader.
  */
+#include <linux/module.h>
 
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-spinlock.h>
@@ -69,6 +70,7 @@
 {
 	return &(state.sysinfo);
 }
+EXPORT_SYMBOL(cvmx_sysinfo_get);
 
 /**
  * This function is used in non-simple executive environments (such as
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/Makefile linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/executive/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/executive/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -11,3 +11,4 @@
 
 obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
 
+obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-jtag.o
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/octeon_boot.h linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/octeon_boot.h
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/octeon_boot.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/octeon_boot.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2004, 2005 Cavium Networks
+ *
+ * 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 __OCTEON_BOOT_H__
+#define __OCTEON_BOOT_H__
+
+#include <linux/types.h>
+
+struct boot_init_vector {
+	uint32_t stack_addr;
+	uint32_t code_addr;
+	uint32_t app_start_func_addr;
+	uint32_t k0_val;
+	uint32_t flags;
+	uint32_t boot_info_addr;
+	uint32_t pad;
+	uint32_t pad2;
+};
+
+/* similar to bootloader's linux_app_boot_info but without global data */
+struct linux_app_boot_info {
+	uint32_t labi_signature;
+	uint32_t start_core0_addr;
+	uint32_t avail_coremask;
+	uint32_t pci_console_active;
+	uint32_t icache_prefetch_disable;
+	uint32_t InitTLBStart_addr;
+	uint32_t start_app_addr;
+	uint32_t cur_exception_base;
+	uint32_t no_mark_private_data;
+	uint32_t compact_flash_common_base_addr;
+	uint32_t compact_flash_attribute_base_addr;
+	uint32_t led_display_base_addr;
+};
+
+/* If not to copy a lot of bootloader's structures
+   here is only offset of requested member */
+#define AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK    0x765c
+
+/* hardcoded in bootloader */
+#define  LABI_ADDR_IN_BOOTLOADER                         0x700
+
+#define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot"
+
+#define LABI_SIGNATURE 0xAABBCCDD
+
+/*  from uboot-headers/octeon_mem_map.h */
+#define EXCEPTION_BASE_INCR     (4 * 1024)
+			       /* Increment size for exception base addresses (4k minimum) */
+#define EXCEPTION_BASE_BASE     0
+#define BOOTLOADER_PRIV_DATA_BASE       (EXCEPTION_BASE_BASE + 0x800)
+#define BOOTLOADER_BOOT_VECTOR          (BOOTLOADER_PRIV_DATA_BASE)
+
+#endif /* __OCTEON_BOOT_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/octeon-irq.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/octeon-irq.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/octeon-irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/octeon-irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,9 +7,11 @@
  */
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/hardirq.h>
+#include <linux/smp.h>
 
 #include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-pexp-defs.h>
+#include <asm/octeon/cvmx-npi-defs.h>
 
 DEFINE_RWLOCK(octeon_irq_ciu0_rwlock);
 DEFINE_RWLOCK(octeon_irq_ciu1_rwlock);
@@ -177,7 +179,7 @@
 }
 
 #ifdef CONFIG_SMP
-static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
 {
 	int cpu;
 	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
@@ -199,6 +201,8 @@
 	 */
 	cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
 	write_unlock(&octeon_irq_ciu0_rwlock);
+
+	return 0;
 }
 #endif
 
@@ -292,7 +296,7 @@
 }
 
 #ifdef CONFIG_SMP
-static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
+static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
 {
 	int cpu;
 	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
@@ -315,6 +319,8 @@
 	 */
 	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
 	write_unlock(&octeon_irq_ciu1_rwlock);
+
+	return 0;
 }
 #endif
 
@@ -495,3 +501,62 @@
 		}
 	}
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int is_irq_enabled_on_cpu(unsigned int irq, unsigned int cpu)
+{
+       unsigned int isset;
+#ifdef CONFIG_SMP
+       int coreid = cpu_logical_map(cpu);
+#else
+	int coreid = cvmx_get_core_num();
+#endif
+	int bit = (irq < OCTEON_IRQ_WDOG0) ?
+		irq - OCTEON_IRQ_WORKQ0 : irq - OCTEON_IRQ_WDOG0;
+       if (irq < 64) {
+		isset = (cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)) &
+			(1ull << bit)) >> bit;
+       } else {
+	       isset = (cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)) &
+			(1ull << bit)) >> bit;
+       }
+       return isset;
+}
+
+void fixup_irqs(void)
+{
+       int irq;
+
+	for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++)
+		octeon_irq_core_disable_local(irq);
+
+	for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_GPIO15; irq++) {
+		if (is_irq_enabled_on_cpu(irq, smp_processor_id())) {
+			/* ciu irq migrates to next cpu */
+			octeon_irq_chip_ciu0.disable(irq);
+			octeon_irq_ciu0_set_affinity(irq, &cpu_online_map);
+		}
+	}
+
+#if 0
+	for (irq = OCTEON_IRQ_MBOX0; irq <= OCTEON_IRQ_MBOX1; irq++)
+		octeon_irq_mailbox_mask(irq);
+#endif
+	for (irq = OCTEON_IRQ_UART0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
+		if (is_irq_enabled_on_cpu(irq, smp_processor_id())) {
+			/* ciu irq migrates to next cpu */
+			octeon_irq_chip_ciu0.disable(irq);
+			octeon_irq_ciu0_set_affinity(irq, &cpu_online_map);
+		}
+	}
+
+	for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED135; irq++) {
+		if (is_irq_enabled_on_cpu(irq, smp_processor_id())) {
+			/* ciu irq migrates to next cpu */
+			octeon_irq_chip_ciu1.disable(irq);
+			octeon_irq_ciu1_set_affinity(irq, &cpu_online_map);
+		}
+	}
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/setup.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/serial.h>
+#include <linux/smp.h>
 #include <linux/types.h>
 #include <linux/string.h>	/* for memset */
 #include <linux/tty.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/smp.c linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/smp.c
--- linux-libre-2.6.30-gnu/arch/mips/cavium-octeon/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cavium-octeon/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2004-2008 Cavium Networks
  */
+#include <linux/cpu.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/smp.h>
@@ -19,10 +20,16 @@
 
 #include <asm/octeon/octeon.h>
 
+#include "octeon_boot.h"
+
 volatile unsigned long octeon_processor_boot = 0xff;
 volatile unsigned long octeon_processor_sp;
 volatile unsigned long octeon_processor_gp;
 
+#ifdef CONFIG_HOTPLUG_CPU
+static unsigned int InitTLBStart_addr;
+#endif
+
 static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
 {
 	const int coreid = cvmx_get_core_num();
@@ -67,8 +74,28 @@
 }
 
 /**
- * Detect available CPUs, populate phys_cpu_present_map
+ * Detect available CPUs, populate cpu_possible_map
  */
+static void octeon_smp_hotplug_setup(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+	uint32_t labi_signature;
+
+	labi_signature =
+		cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+					LABI_ADDR_IN_BOOTLOADER +
+					offsetof(struct linux_app_boot_info,
+						    labi_signature)));
+	if (labi_signature != LABI_SIGNATURE)
+		pr_err("The bootloader version on this board is incorrect\n");
+	InitTLBStart_addr =
+		cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+				   LABI_ADDR_IN_BOOTLOADER +
+					   offsetof(struct linux_app_boot_info,
+						    InitTLBStart_addr)));
+#endif
+}
+
 static void octeon_smp_setup(void)
 {
 	const int coreid = cvmx_get_core_num();
@@ -91,6 +118,9 @@
 			cpus++;
 		}
 	}
+	cpu_present_map = cpu_possible_map;
+
+	octeon_smp_hotplug_setup();
 }
 
 /**
@@ -128,6 +158,17 @@
 	const int coreid = cvmx_get_core_num();
 	union cvmx_ciu_intx_sum0 interrupt_enable;
 
+#ifdef CONFIG_HOTPLUG_CPU
+	unsigned int cur_exception_base;
+
+	cur_exception_base = cvmx_read64_uint32(
+		CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+			     LABI_ADDR_IN_BOOTLOADER +
+			     offsetof(struct linux_app_boot_info,
+				      cur_exception_base)));
+	/* cur_exception_base is incremented in bootloader after setting */
+	write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR));
+#endif
 	octeon_check_cpu_bist();
 	octeon_init_cvmcount();
 	/*
@@ -153,11 +194,11 @@
 void octeon_prepare_cpus(unsigned int max_cpus)
 {
 	cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
-	if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_SHARED,
+	if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
 			"mailbox0", mailbox_interrupt)) {
 		panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
 	}
-	if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_SHARED,
+	if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_DISABLED,
 			"mailbox1", mailbox_interrupt)) {
 		panic("Cannot request_irq(OCTEON_IRQ_MBOX1)\n");
 	}
@@ -199,6 +240,193 @@
 #endif
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+
+/* State of each CPU. */
+DEFINE_PER_CPU(int, cpu_state);
+
+extern void fixup_irqs(void);
+
+static DEFINE_SPINLOCK(smp_reserve_lock);
+
+static int octeon_cpu_disable(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	if (cpu == 0)
+		return -EBUSY;
+
+	spin_lock(&smp_reserve_lock);
+
+	cpu_clear(cpu, cpu_online_map);
+	cpu_clear(cpu, cpu_callin_map);
+	local_irq_disable();
+	fixup_irqs();
+	local_irq_enable();
+
+	flush_cache_all();
+	local_flush_tlb_all();
+
+	spin_unlock(&smp_reserve_lock);
+
+	return 0;
+}
+
+static void octeon_cpu_die(unsigned int cpu)
+{
+	int coreid = cpu_logical_map(cpu);
+	uint32_t avail_coremask;
+	struct cvmx_bootmem_named_block_desc *block_desc;
+
+#ifdef CONFIG_CAVIUM_OCTEON_WATCHDOG
+	/* Disable the watchdog */
+	cvmx_ciu_wdogx_t ciu_wdog;
+	ciu_wdog.u64 = cvmx_read_csr(CVMX_CIU_WDOGX(cpu));
+	ciu_wdog.s.mode = 0;
+	cvmx_write_csr(CVMX_CIU_WDOGX(cpu), ciu_wdog.u64);
+#endif
+
+	while (per_cpu(cpu_state, cpu) != CPU_DEAD)
+		cpu_relax();
+
+	/*
+	 * This is a bit complicated strategics of getting/settig available
+	 * cores mask, copied from bootloader
+	 */
+	/* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */
+	block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME);
+
+	if (!block_desc) {
+		avail_coremask =
+			cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+						   LABI_ADDR_IN_BOOTLOADER +
+						   offsetof
+						   (struct linux_app_boot_info,
+						    avail_coremask)));
+	} else {		       /* alternative, already initialized */
+	       avail_coremask =
+		   cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+						   block_desc->base_addr +
+						  AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK));
+	}
+
+	avail_coremask |= 1 << coreid;
+
+	/* Setting avail_coremask for bootoct binary */
+	if (!block_desc) {
+		cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+						LABI_ADDR_IN_BOOTLOADER +
+						offsetof(struct linux_app_boot_info,
+							 avail_coremask)),
+				   avail_coremask);
+	} else {
+		cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+						block_desc->base_addr +
+						AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK),
+				   avail_coremask);
+	}
+
+	pr_info("Reset core %d. Available Coremask = %x \n", coreid,
+		avail_coremask);
+	cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid);
+	cvmx_write_csr(CVMX_CIU_PP_RST, 0);
+}
+
+void play_dead(void)
+{
+	int coreid = cvmx_get_core_num();
+
+	idle_task_exit();
+	octeon_processor_boot = 0xff;
+	per_cpu(cpu_state, coreid) = CPU_DEAD;
+
+	while (1)	/* core will be reset here */
+		;
+}
+
+extern void kernel_entry(unsigned long arg1, ...);
+
+static void start_after_reset(void)
+{
+	kernel_entry(0, 0, 0);  /* set a2 = 0 for secondary core */
+}
+
+int octeon_update_boot_vector(unsigned int cpu)
+{
+
+	int coreid = cpu_logical_map(cpu);
+	unsigned int avail_coremask;
+	struct cvmx_bootmem_named_block_desc *block_desc;
+	struct boot_init_vector *boot_vect =
+		(struct boot_init_vector *) cvmx_phys_to_ptr(0x0 +
+						  BOOTLOADER_BOOT_VECTOR);
+
+	block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME);
+
+	if (!block_desc) {
+		avail_coremask =
+			cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+					   LABI_ADDR_IN_BOOTLOADER +
+						offsetof(struct linux_app_boot_info,
+						avail_coremask)));
+	} else {		       /* alternative, already initialized */
+	       avail_coremask =
+		   cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+						   block_desc->base_addr +
+						   AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK));
+	}
+
+	if (!(avail_coremask & (1 << coreid))) {
+		/* core not available, assume, that catched by simple-executive */
+		cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid);
+		cvmx_write_csr(CVMX_CIU_PP_RST, 0);
+	}
+
+	boot_vect[coreid].app_start_func_addr =
+		(uint32_t) (unsigned long) start_after_reset;
+	boot_vect[coreid].code_addr = InitTLBStart_addr;
+
+	CVMX_SYNC;
+
+	cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask);
+
+	return 0;
+}
+
+static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb,
+	unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+		octeon_update_boot_vector(cpu);
+		break;
+	case CPU_ONLINE:
+		pr_info("Cpu %d online\n", cpu);
+		break;
+	case CPU_DEAD:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata octeon_cpu_notifier = {
+	.notifier_call = octeon_cpu_callback,
+};
+
+static int __cpuinit register_cavium_notifier(void)
+{
+	register_hotcpu_notifier(&octeon_cpu_notifier);
+
+	return 0;
+}
+
+late_initcall(register_cavium_notifier);
+
+#endif  /* CONFIG_HOTPLUG_CPU */
+
 struct plat_smp_ops octeon_smp_ops = {
 	.send_ipi_single	= octeon_send_ipi_single,
 	.send_ipi_mask		= octeon_send_ipi_mask,
@@ -208,4 +436,8 @@
 	.boot_secondary		= octeon_boot_secondary,
 	.smp_setup		= octeon_smp_setup,
 	.prepare_cpus		= octeon_prepare_cpus,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable		= octeon_cpu_disable,
+	.cpu_die		= octeon_cpu_die,
+#endif
 };
diff -druN linux-libre-2.6.30-gnu/arch/mips/cobalt/buttons.c linux-libre-2.6.31-gnu/arch/mips/cobalt/buttons.c
--- linux-libre-2.6.30-gnu/arch/mips/cobalt/buttons.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cobalt/buttons.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Cobalt buttons platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/cobalt/lcd.c linux-libre-2.6.31-gnu/arch/mips/cobalt/lcd.c
--- linux-libre-2.6.30-gnu/arch/mips/cobalt/lcd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cobalt/lcd.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt LCD platform device.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/cobalt/led.c linux-libre-2.6.31-gnu/arch/mips/cobalt/led.c
--- linux-libre-2.6.30-gnu/arch/mips/cobalt/led.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cobalt/led.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt LED platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/cobalt/mtd.c linux-libre-2.6.31-gnu/arch/mips/cobalt/mtd.c
--- linux-libre-2.6.30-gnu/arch/mips/cobalt/mtd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cobalt/mtd.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt MTD device.
  *
- *  Copyright (C) 2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2006  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/cobalt/rtc.c linux-libre-2.6.31-gnu/arch/mips/cobalt/rtc.c
--- linux-libre-2.6.30-gnu/arch/mips/cobalt/rtc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cobalt/rtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt RTC platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/cobalt/serial.c linux-libre-2.6.31-gnu/arch/mips/cobalt/serial.c
--- linux-libre-2.6.30-gnu/arch/mips/cobalt/serial.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cobalt/serial.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt UART platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/cobalt/time.c linux-libre-2.6.31-gnu/arch/mips/cobalt/time.c
--- linux-libre-2.6.30-gnu/arch/mips/cobalt/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/cobalt/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Cobalt time initialization.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/configs/ar7_defconfig linux-libre-2.6.31-gnu/arch/mips/configs/ar7_defconfig
--- linux-libre-2.6.30-gnu/arch/mips/configs/ar7_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/configs/ar7_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1182 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30
+# Wed Jun 24 14:08:59 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+CONFIG_AR7=y
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_NO_EXCEPT_FILL=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+CONFIG_CPU_MIPS32_R1=y
+# 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_R5500 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 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=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_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+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_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_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_KEXEC=y
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_PROBE_INITRD_HEADER=y
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# 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 is not set
+# 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_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+CONFIG_TCP_CONG_WESTWOOD=y
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+CONFIG_DEFAULT_WESTWOOD=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="westwood"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_REDIRECT is not set
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_ATM is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_INGRESS is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_IPT is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+# CONFIG_AX25 is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+CONFIG_CPMAC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AR7_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_SERIAL=y
+CONFIG_SSB_DRIVER_MIPS=y
+CONFIG_SSB_EMBEDDED=y
+CONFIG_SSB_DRIVER_EXTIF=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+CONFIG_VLYNQ=y
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# 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_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/mips/configs/bigsur_defconfig linux-libre-2.6.31-gnu/arch/mips/configs/bigsur_defconfig
--- linux-libre-2.6.30-gnu/arch/mips/configs/bigsur_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/configs/bigsur_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -963,7 +963,7 @@
 CONFIG_SENSORS_PCF8574=y
 # CONFIG_PCF8575 is not set
 CONFIG_SENSORS_PCF8591=y
-CONFIG_SENSORS_MAX6875=y
+CONFIG_EEPROM_MAX6875=y
 # CONFIG_SENSORS_TSL2550 is not set
 CONFIG_I2C_DEBUG_CORE=y
 CONFIG_I2C_DEBUG_ALGO=y
diff -druN linux-libre-2.6.30-gnu/arch/mips/configs/mtx1_defconfig linux-libre-2.6.31-gnu/arch/mips/configs/mtx1_defconfig
--- linux-libre-2.6.30-gnu/arch/mips/configs/mtx1_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/configs/mtx1_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1849,7 +1849,7 @@
 CONFIG_SENSORS_PCF8574=m
 CONFIG_SENSORS_PCA9539=m
 CONFIG_SENSORS_PCF8591=m
-CONFIG_SENSORS_MAX6875=m
+CONFIG_EEPROM_MAX6875=m
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/ecc-berr.c linux-libre-2.6.31-gnu/arch/mips/dec/ecc-berr.c
--- linux-libre-2.6.30-gnu/arch/mips/dec/ecc-berr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/ecc-berr.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	linux/arch/mips/dec/ecc-berr.c
- *
  *	Bus error event handling code for systems equipped with ECC
  *	handling logic, i.e. DECstation/DECsystem 5000/200 (KN02),
  *	5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03),
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/int-handler.S linux-libre-2.6.31-gnu/arch/mips/dec/int-handler.S
--- linux-libre-2.6.30-gnu/arch/mips/dec/int-handler.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/int-handler.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * arch/mips/dec/int-handler.S
- *
  * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
  * Copyright (C) 2000, 2001, 2002, 2003, 2005  Maciej W. Rozycki
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/ioasic-irq.c linux-libre-2.6.31-gnu/arch/mips/dec/ioasic-irq.c
--- linux-libre-2.6.30-gnu/arch/mips/dec/ioasic-irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/ioasic-irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	linux/arch/mips/dec/ioasic-irq.c
- *
  *	DEC I/O ASIC interrupts.
  *
  *	Copyright (c) 2002, 2003  Maciej W. Rozycki
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/kn01-berr.c linux-libre-2.6.31-gnu/arch/mips/dec/kn01-berr.c
--- linux-libre-2.6.30-gnu/arch/mips/dec/kn01-berr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/kn01-berr.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	linux/arch/mips/dec/kn01-berr.c
- *
  *	Bus error event handling code for DECstation/DECsystem 3100
  *	and 2100 (KN01) systems equipped with parity error detection
  *	logic.
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/kn02-irq.c linux-libre-2.6.31-gnu/arch/mips/dec/kn02-irq.c
--- linux-libre-2.6.30-gnu/arch/mips/dec/kn02-irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/kn02-irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	linux/arch/mips/dec/kn02-irq.c
- *
  *	DECstation 5000/200 (KN02) Control and Status Register
  *	interrupts.
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/kn02xa-berr.c linux-libre-2.6.31-gnu/arch/mips/dec/kn02xa-berr.c
--- linux-libre-2.6.30-gnu/arch/mips/dec/kn02xa-berr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/kn02xa-berr.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	linux/arch/mips/dec/kn02xa-berr.c
- *
  *	Bus error event handling code for 5000-series systems equipped
  *	with parity error detection logic, i.e. DECstation/DECsystem
  *	5000/120, /125, /133 (KN02-BA), 5000/150 (KN04-BA) and Personal
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/prom/call_o32.S linux-libre-2.6.31-gnu/arch/mips/dec/prom/call_o32.S
--- linux-libre-2.6.30-gnu/arch/mips/dec/prom/call_o32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/prom/call_o32.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	arch/mips/dec/prom/call_o32.S
- *
  *	O32 interface for the 64 (or N32) ABI.
  *
  *	Copyright (C) 2002  Maciej W. Rozycki
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/prom/console.c linux-libre-2.6.31-gnu/arch/mips/dec/prom/console.c
--- linux-libre-2.6.30-gnu/arch/mips/dec/prom/console.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/prom/console.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	arch/mips/dec/prom/console.c
- *
  *	DECstation PROM-based early console support.
  *
  *	Copyright (C) 2004, 2007  Maciej W. Rozycki
diff -druN linux-libre-2.6.30-gnu/arch/mips/dec/time.c linux-libre-2.6.31-gnu/arch/mips/dec/time.c
--- linux-libre-2.6.30-gnu/arch/mips/dec/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/dec/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/mips/dec/time.c
- *
  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
  *  Copyright (C) 2000, 2003  Maciej W. Rozycki
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/emma/common/Makefile linux-libre-2.6.31-gnu/arch/mips/emma/common/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/emma/common/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/emma/common/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 #
-#  arch/mips/emma2rh/common/Makefile
-#       Makefile for the common code of NEC EMMA2RH based board.
-#
 #  Copyright (C) NEC Electronics Corporation 2005-2006
 #
 #  This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.30-gnu/arch/mips/emma/common/prom.c linux-libre-2.6.31-gnu/arch/mips/emma/common/prom.c
--- linux-libre-2.6.30-gnu/arch/mips/emma/common/prom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/emma/common/prom.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/common/prom.c
- *      This file is prom file.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/common/prom.c
diff -druN linux-libre-2.6.30-gnu/arch/mips/emma/markeins/irq.c linux-libre-2.6.31-gnu/arch/mips/emma/markeins/irq.c
--- linux-libre-2.6.30-gnu/arch/mips/emma/markeins/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/emma/markeins/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/irq.c
- *      This file defines the irq handler for EMMA2RH.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
diff -druN linux-libre-2.6.30-gnu/arch/mips/emma/markeins/led.c linux-libre-2.6.31-gnu/arch/mips/emma/markeins/led.c
--- linux-libre-2.6.30-gnu/arch/mips/emma/markeins/led.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/emma/markeins/led.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/led.c
- *      This file defines the led display for Mark-eins.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.30-gnu/arch/mips/emma/markeins/Makefile linux-libre-2.6.31-gnu/arch/mips/emma/markeins/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/emma/markeins/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/emma/markeins/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 #
-#  arch/mips/emma2rh/markeins/Makefile
-#       Makefile for the common code of NEC EMMA2RH based board.
-#
 #  Copyright (C) NEC Electronics Corporation 2005-2006
 #
 #  This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.30-gnu/arch/mips/emma/markeins/platform.c linux-libre-2.6.31-gnu/arch/mips/emma/markeins/platform.c
--- linux-libre-2.6.30-gnu/arch/mips/emma/markeins/platform.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/emma/markeins/platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/platofrm.c
- *      This file sets up platform devices for EMMA2RH Mark-eins.
- *
  *  Copyright(C) MontaVista Software Inc, 2006
  *
  *  Author: dmitry pervushin <dpervushin@ru.mvista.com>
diff -druN linux-libre-2.6.30-gnu/arch/mips/emma/markeins/setup.c linux-libre-2.6.31-gnu/arch/mips/emma/markeins/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/emma/markeins/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/emma/markeins/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/setup.c
- *      This file is setup for EMMA2RH Mark-eins.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/setup.c.
diff -druN linux-libre-2.6.30-gnu/arch/mips/fw/lib/call_o32.S linux-libre-2.6.31-gnu/arch/mips/fw/lib/call_o32.S
--- linux-libre-2.6.30-gnu/arch/mips/fw/lib/call_o32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/fw/lib/call_o32.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	arch/mips/dec/prom/call_o32.S
- *
  *	O32 interface for the 64 (or N32) ABI.
  *
  *	Copyright (C) 2002  Maciej W. Rozycki
diff -druN linux-libre-2.6.30-gnu/arch/mips/gt64120/wrppmc/serial.c linux-libre-2.6.31-gnu/arch/mips/gt64120/wrppmc/serial.c
--- linux-libre-2.6.30-gnu/arch/mips/gt64120/wrppmc/serial.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/gt64120/wrppmc/serial.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Registration of WRPPMC UART platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/amon.h linux-libre-2.6.31-gnu/arch/mips/include/asm/amon.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/amon.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/amon.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,7 @@
+/*
+ * Amon support
+ */
+
+int amon_cpu_avail(int);
+void amon_cpu_start(int, unsigned long, unsigned long,
+		    unsigned long, unsigned long);
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/mips/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -793,6 +793,6 @@
 #define smp_mb__before_atomic_inc()	smp_llsc_mb()
 #define smp_mb__after_atomic_inc()	smp_llsc_mb()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 
 #endif /* _ASM_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/mips/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,8 @@
+#ifndef __ASM_MIPS_BITSPERLONG_H
+#define __ASM_MIPS_BITSPERLONG_H
+
+#define __BITS_PER_LONG _MIPS_SZLONG
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_MIPS_BITSPERLONG_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/bug.h linux-libre-2.6.31-gnu/arch/mips/include/asm/bug.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/bug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/bug.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 #ifndef __ASM_BUG_H
 #define __ASM_BUG_H
 
+#include <linux/compiler.h>
 #include <asm/sgidefs.h>
 
 #ifdef CONFIG_BUG
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/bugs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/bugs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/bugs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/bugs.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 
 #include <linux/bug.h>
 #include <linux/delay.h>
+#include <linux/smp.h>
 
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/cpu-features.h linux-libre-2.6.31-gnu/arch/mips/include/asm/cpu-features.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/cpu-features.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/cpu-features.h	2009-09-09 18:13:59.000000000 -0400
@@ -147,6 +147,10 @@
 #define cpu_has_mips_r	(cpu_has_mips32r1 | cpu_has_mips32r2 | \
 			 cpu_has_mips64r1 | cpu_has_mips64r2)
 
+#ifndef cpu_has_mips_r2_exec_hazard
+#define cpu_has_mips_r2_exec_hazard cpu_has_mips_r2
+#endif
+
 /*
  * MIPS32, MIPS64, VR5500, IDT32332, IDT32334 and maybe a few other
  * pre-MIPS32/MIPS53 processors have CLO, CLZ.  For 64-bit kernels
@@ -230,4 +234,8 @@
 #define cpu_scache_line_size()	cpu_data[0].scache.linesz
 #endif
 
+#ifndef cpu_hwrena_impl_bits
+#define cpu_hwrena_impl_bits		0
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/delay.h linux-libre-2.6.31-gnu/arch/mips/include/asm/delay.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/delay.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/delay.h	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,7 @@
 extern void __ndelay(unsigned int ns);
 extern void __udelay(unsigned int us);
 
-#define ndelay(ns) __udelay(ns)
+#define ndelay(ns) __ndelay(ns)
 #define udelay(us) __udelay(us)
 
 /* make sure "usecs *= ..." in udelay do not overflow. */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/ds1287.h linux-libre-2.6.31-gnu/arch/mips/include/asm/ds1287.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/ds1287.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/ds1287.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  DS1287 timer functions.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/elf.h linux-libre-2.6.31-gnu/arch/mips/include/asm/elf.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/elf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/elf.h	2009-09-09 18:13:59.000000000 -0400
@@ -316,9 +316,13 @@
 extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
 
+#ifndef ELF_CORE_COPY_REGS
 #define ELF_CORE_COPY_REGS(elf_regs, regs)			\
 	elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
+#endif
+#ifndef ELF_CORE_COPY_TASK_REGS
 #define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+#endif
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
 	dump_task_fpu(tsk, elf_fpregs)
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/emma/emma2rh.h linux-libre-2.6.31-gnu/arch/mips/include/asm/emma/emma2rh.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/emma/emma2rh.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/emma/emma2rh.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/include/asm/emma/emma2rh.h
- *      This file is EMMA2RH common header.
- *
  *  Copyright (C) NEC Electronics Corporation 2005-2006
  *
  *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/emma/markeins.h linux-libre-2.6.31-gnu/arch/mips/include/asm/emma/markeins.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/emma/markeins.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/emma/markeins.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  include/asm-mips/emma2rh/markeins.h
- *      This file is EMMA2RH board depended header.
- *
  *  Copyright (C) NEC Electronics Corporation 2005-2006
  *
  *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/errno.h linux-libre-2.6.31-gnu/arch/mips/include/asm/errno.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/errno.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/errno.h	2009-09-09 18:13:59.000000000 -0400
@@ -119,6 +119,8 @@
 #define	EOWNERDEAD	165	/* Owner died */
 #define	ENOTRECOVERABLE	166	/* State not recoverable */
 
+#define	ERFKILL		167	/* Operation not possible due to RF-kill */
+
 #define EDQUOT		1133	/* Quota exceeded */
 
 #ifdef __KERNEL__
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/gcmpregs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/gcmpregs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/gcmpregs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/gcmpregs.h	2009-09-09 18:13:59.000000000 -0400
@@ -114,4 +114,6 @@
 #define GCMP_CCB_DINTGROUP_OFS		0x0030		/* DINT Group Participate */
 #define GCMP_CCB_DBGGROUP_OFS		0x0100		/* DebugBreak Group */
 
+extern int __init gcmp_probe(unsigned long, unsigned long);
+
 #endif /* _ASM_GCMPREGS_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/gic.h linux-libre-2.6.31-gnu/arch/mips/include/asm/gic.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/gic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/gic.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,7 +20,11 @@
 #define GIC_TRIG_EDGE			1
 #define GIC_TRIG_LEVEL			0
 
+#ifdef CONFIG_SMP
+#define GIC_NUM_INTRS			(24 + NR_CPUS * 2)
+#else
 #define GIC_NUM_INTRS			32
+#endif
 
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)		(*(volatile unsigned int *) (addr))
@@ -483,5 +487,7 @@
 
 extern unsigned int gic_get_int(void);
 extern void gic_send_ipi(unsigned int intr);
+extern unsigned int plat_ipi_call_int_xlate(unsigned int);
+extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 
 #endif /* _ASM_GICREGS_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/hugetlb.h linux-libre-2.6.31-gnu/arch/mips/include/asm/hugetlb.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/hugetlb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/hugetlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ * 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) 2008, 2009 Cavium Networks, Inc.
+ */
+
+#ifndef __ASM_HUGETLB_H
+#define __ASM_HUGETLB_H
+
+#include <asm/page.h>
+
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+					 unsigned long addr,
+					 unsigned long len)
+{
+	return 0;
+}
+
+static inline int prepare_hugepage_range(struct file *file,
+					 unsigned long addr,
+					 unsigned long len)
+{
+	unsigned long task_size = STACK_TOP;
+	struct hstate *h = hstate_file(file);
+
+	if (len & ~huge_page_mask(h))
+		return -EINVAL;
+	if (addr & ~huge_page_mask(h))
+		return -EINVAL;
+	if (len > task_size)
+		return -ENOMEM;
+	if (task_size - len < addr)
+		return -EINVAL;
+	return 0;
+}
+
+static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
+{
+}
+
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
+					  unsigned long addr,
+					  unsigned long end,
+					  unsigned long floor,
+					  unsigned long ceiling)
+{
+	free_pgd_range(tlb, addr, end, floor, ceiling);
+}
+
+static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+				   pte_t *ptep, pte_t pte)
+{
+	set_pte_at(mm, addr, ptep, pte);
+}
+
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+					    unsigned long addr, pte_t *ptep)
+{
+	pte_t clear;
+	pte_t pte = *ptep;
+
+	pte_val(clear) = (unsigned long)invalid_pte_table;
+	set_pte_at(mm, addr, ptep, clear);
+	return pte;
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+					 unsigned long addr, pte_t *ptep)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+	unsigned long val = pte_val(pte) & ~_PAGE_GLOBAL;
+	return !val || (val == (unsigned long)invalid_pte_table);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+	return pte_wrprotect(pte);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+					   unsigned long addr, pte_t *ptep)
+{
+	ptep_set_wrprotect(mm, addr, ptep);
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+					     unsigned long addr,
+					     pte_t *ptep, pte_t pte,
+					     int dirty)
+{
+	return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+}
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+	return *ptep;
+}
+
+static inline int arch_prepare_hugepage(struct page *page)
+{
+	return 0;
+}
+
+static inline void arch_release_hugepage(struct page *page)
+{
+}
+
+#endif /* __ASM_HUGETLB_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/i8253.h linux-libre-2.6.31-gnu/arch/mips/include/asm/i8253.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/i8253.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/i8253.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,8 +12,6 @@
 #define PIT_CH0			0x40
 #define PIT_CH2			0x42
 
-#define PIT_TICK_RATE		1193182UL
-
 extern spinlock_t i8253_lock;
 
 extern void setup_pit_timer(void);
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/ioctl.h linux-libre-2.6.31-gnu/arch/mips/include/asm/ioctl.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/ioctl.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/ioctl.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,40 +3,16 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 96, 99, 2001 Ralf Baechle
- */
-#ifndef _ASM_IOCTL_H
-#define _ASM_IOCTL_H
-
-/*
- * The original linux ioctl numbering scheme was just a general
- * "anything goes" setup, where more or less random numbers were
- * assigned.  Sorry, I was clueless when I started out on this.
- *
- * On the alpha, we'll try to clean it up a bit, using a more sane
- * ioctl numbering, and also trying to be compatible with OSF/1 in
- * the process. I'd like to clean it up for the i386 as well, but
- * it's so painful recognizing both the new and the old numbers..
- *
- * The same applies for for the MIPS ABI; in fact even the macros
- * from Linux/Alpha fit almost perfectly.
+ * Copyright (C) 1995, 96, 99, 2001 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2009 Wind River Systems
+ * Written by Ralf Baechle <ralf@linux-mips.org>
  */
+#ifndef __ASM_IOCTL_H
+#define __ASM_IOCTL_H
 
-#define _IOC_NRBITS	8
-#define _IOC_TYPEBITS	8
 #define _IOC_SIZEBITS	13
 #define _IOC_DIRBITS	3
 
-#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
-#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT	0
-#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
-#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
-#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
-
 /*
  * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
  * And this turns out useful to catch old ioctl numbers in header
@@ -46,53 +22,6 @@
 #define _IOC_READ	2U
 #define _IOC_WRITE	4U
 
-/*
- * The following are included for compatibility
- */
-#define _IOC_VOID	0x20000000
-#define _IOC_OUT	0x40000000
-#define _IOC_IN		0x80000000
-#define _IOC_INOUT	(IOC_IN|IOC_OUT)
-
-#define _IOC(dir, type, nr, size) \
-	(((dir)  << _IOC_DIRSHIFT) | \
-	 ((type) << _IOC_TYPESHIFT) | \
-	 ((nr)   << _IOC_NRSHIFT) | \
-	 ((size) << _IOC_SIZESHIFT))
-
-#ifdef __KERNEL__
-/* provoke compile error for invalid uses of size argument */
-extern unsigned int __invalid_size_argument_for_IOC;
-#define _IOC_TYPECHECK(t) \
-	((sizeof(t) == sizeof(t[1]) && \
-	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
-	  sizeof(t) : __invalid_size_argument_for_IOC)
-#else
-#define _IOC_TYPECHECK(t)	(sizeof(t))
-#endif
-
-/* used to create numbers */
-#define _IO(type, nr)		_IOC(_IOC_NONE, (type), (nr), 0)
-#define _IOR(type, nr, size)	_IOC(_IOC_READ, (type), (nr), (_IOC_TYPECHECK(size)))
-#define _IOW(type, nr, size)	_IOC(_IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size)))
-#define _IOWR(type, nr, size)	_IOC(_IOC_READ|_IOC_WRITE, (type), (nr), (_IOC_TYPECHECK(size)))
-#define _IOR_BAD(type, nr, size)	_IOC(_IOC_READ, (type), (nr), sizeof(size))
-#define _IOW_BAD(type, nr, size)	_IOC(_IOC_WRITE, (type), (nr), sizeof(size))
-#define _IOWR_BAD(type, nr, size)	_IOC(_IOC_READ|_IOC_WRITE, (type), (nr), sizeof(size))
-
-
-/* used to decode them.. */
-#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
-#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
-
-/* ...and for the drivers/sound files... */
-
-#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+#include <asm-generic/ioctl.h>
 
-#endif /* _ASM_IOCTL_H */
+#endif /* __ASM_IOCTL_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/irq_gt641xx.h linux-libre-2.6.31-gnu/arch/mips/include/asm/irq_gt641xx.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/irq_gt641xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/irq_gt641xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Galileo/Marvell GT641xx IRQ definitions.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/irq.h linux-libre-2.6.31-gnu/arch/mips/include/asm/irq.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #define _ASM_IRQ_H
 
 #include <linux/linkage.h>
+#include <linux/smp.h>
 
 #include <asm/mipsmtregs.h>
 
@@ -49,7 +50,7 @@
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
 #include <linux/cpumask.h>
 
-extern void plat_set_irq_affinity(unsigned int irq,
+extern int plat_set_irq_affinity(unsigned int irq,
 				  const struct cpumask *affinity);
 extern void smtc_forward_irq(unsigned int irq);
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/mips/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,30 +1,12 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-
 #ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
+#define  __WITH_KM_FENCE
 #endif
 
-enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_IRQ0,
-D(10)	KM_IRQ1,
-D(11)	KM_SOFTIRQ0,
-D(12)	KM_SOFTIRQ1,
-D(13)	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
-#undef D
+#undef __WITH_KM_FENCE
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/ar7.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/ar7.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/ar7.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/ar7.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AR7_H__
+#define __AR7_H__
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+
+#include <asm/addrspace.h>
+
+#define AR7_SDRAM_BASE	0x14000000
+
+#define AR7_REGS_BASE	0x08610000
+
+#define AR7_REGS_MAC0	(AR7_REGS_BASE + 0x0000)
+#define AR7_REGS_GPIO	(AR7_REGS_BASE + 0x0900)
+/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
+#define AR7_REGS_POWER	(AR7_REGS_BASE + 0x0a00)
+#define AR7_REGS_CLOCKS (AR7_REGS_POWER + 0x80)
+#define UR8_REGS_CLOCKS (AR7_REGS_POWER + 0x20)
+#define AR7_REGS_UART0	(AR7_REGS_BASE + 0x0e00)
+#define AR7_REGS_USB	(AR7_REGS_BASE + 0x1200)
+#define AR7_REGS_RESET	(AR7_REGS_BASE + 0x1600)
+#define AR7_REGS_VLYNQ0	(AR7_REGS_BASE + 0x1800)
+#define AR7_REGS_DCL	(AR7_REGS_BASE + 0x1a00)
+#define AR7_REGS_VLYNQ1	(AR7_REGS_BASE + 0x1c00)
+#define AR7_REGS_MDIO	(AR7_REGS_BASE + 0x1e00)
+#define AR7_REGS_IRQ	(AR7_REGS_BASE + 0x2400)
+#define AR7_REGS_MAC1	(AR7_REGS_BASE + 0x2800)
+
+#define AR7_REGS_WDT	(AR7_REGS_BASE + 0x1f00)
+#define UR8_REGS_WDT	(AR7_REGS_BASE + 0x0b00)
+#define UR8_REGS_UART1	(AR7_REGS_BASE + 0x0f00)
+
+#define AR7_RESET_PEREPHERIAL	0x0
+#define AR7_RESET_SOFTWARE	0x4
+#define AR7_RESET_STATUS	0x8
+
+#define AR7_RESET_BIT_CPMAC_LO	17
+#define AR7_RESET_BIT_CPMAC_HI	21
+#define AR7_RESET_BIT_MDIO	22
+#define AR7_RESET_BIT_EPHY	26
+
+/* GPIO control registers */
+#define AR7_GPIO_INPUT	0x0
+#define AR7_GPIO_OUTPUT	0x4
+#define AR7_GPIO_DIR	0x8
+#define AR7_GPIO_ENABLE	0xc
+
+#define AR7_CHIP_7100	0x18
+#define AR7_CHIP_7200	0x2b
+#define AR7_CHIP_7300	0x05
+
+/* Interrupts */
+#define AR7_IRQ_UART0	15
+#define AR7_IRQ_UART1	16
+
+/* Clocks */
+#define AR7_AFE_CLOCK	35328000
+#define AR7_REF_CLOCK	25000000
+#define AR7_XTAL_CLOCK	24000000
+
+struct plat_cpmac_data {
+	int reset_bit;
+	int power_bit;
+	u32 phy_mask;
+	char dev_addr[6];
+};
+
+struct plat_dsl_data {
+	int reset_bit_dsl;
+	int reset_bit_sar;
+};
+
+extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
+
+static inline u16 ar7_chip_id(void)
+{
+	return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
+}
+
+static inline u8 ar7_chip_rev(void)
+{
+	return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
+}
+
+static inline int ar7_cpu_freq(void)
+{
+	return ar7_cpu_clock;
+}
+
+static inline int ar7_bus_freq(void)
+{
+	return ar7_bus_clock;
+}
+
+static inline int ar7_vbus_freq(void)
+{
+	return ar7_bus_clock / 2;
+}
+#define ar7_cpmac_freq ar7_vbus_freq
+
+static inline int ar7_dsp_freq(void)
+{
+	return ar7_dsp_clock;
+}
+
+static inline int ar7_has_high_cpmac(void)
+{
+	u16 chip_id = ar7_chip_id();
+	switch (chip_id) {
+	case AR7_CHIP_7100:
+	case AR7_CHIP_7200:
+		return 0;
+	case AR7_CHIP_7300:
+		return 1;
+	default:
+		return -ENXIO;
+	}
+}
+#define ar7_has_high_vlynq ar7_has_high_cpmac
+#define ar7_has_second_uart ar7_has_high_cpmac
+
+static inline void ar7_device_enable(u32 bit)
+{
+	void *reset_reg =
+		(void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+	writel(readl(reset_reg) | (1 << bit), reset_reg);
+	msleep(20);
+}
+
+static inline void ar7_device_disable(u32 bit)
+{
+	void *reset_reg =
+		(void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+	writel(readl(reset_reg) & ~(1 << bit), reset_reg);
+	msleep(20);
+}
+
+static inline void ar7_device_reset(u32 bit)
+{
+	ar7_device_disable(bit);
+	ar7_device_enable(bit);
+}
+
+static inline void ar7_device_on(u32 bit)
+{
+	void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+	writel(readl(power_reg) | (1 << bit), power_reg);
+	msleep(20);
+}
+
+static inline void ar7_device_off(u32 bit)
+{
+	void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+	writel(readl(power_reg) & ~(1 << bit), power_reg);
+	msleep(20);
+}
+
+#endif /* __AR7_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/gpio.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/gpio.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AR7_GPIO_H__
+#define __AR7_GPIO_H__
+
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+
+/* Common GPIO layer */
+static inline int gpio_get_value(unsigned gpio)
+{
+	void __iomem *gpio_in =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
+
+	return readl(gpio_in) & (1 << gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	void __iomem *gpio_out =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+	unsigned tmp;
+
+	tmp = readl(gpio_out) & ~(1 << gpio);
+	if (value)
+		tmp |= 1 << gpio;
+	writel(tmp, gpio_out);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	void __iomem *gpio_dir =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+	if (gpio >= AR7_GPIO_MAX)
+		return -EINVAL;
+
+	writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
+
+	return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+	void __iomem *gpio_dir =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+	if (gpio >= AR7_GPIO_MAX)
+		return -EINVAL;
+
+	gpio_set_value(gpio, value);
+	writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
+
+	return 0;
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return -EINVAL;
+}
+
+/* Board specific GPIO functions */
+static inline int ar7_gpio_enable(unsigned gpio)
+{
+	void __iomem *gpio_en =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+	writel(readl(gpio_en) | (1 << gpio), gpio_en);
+
+	return 0;
+}
+
+static inline int ar7_gpio_disable(unsigned gpio)
+{
+	void __iomem *gpio_en =
+		(void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+	writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+	return 0;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/irq.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/irq.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ *
+ * Shamelessly copied from asm-mips/mach-emma2rh/
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_AR7_IRQ_H
+#define __ASM_AR7_IRQ_H
+
+#define NR_IRQS	256
+
+#include_next <irq.h>
+
+#endif /* __ASM_AR7_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/prom.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/prom.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/prom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/prom.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006, 2007 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.
+ *
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __PROM_H__
+#define __PROM_H__
+
+extern char *prom_getenv(const char *name);
+extern void prom_meminit(void);
+
+#endif /* __PROM_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/spaces.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/spaces.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/spaces.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/spaces.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * 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_AR7_SPACES_H
+#define _ASM_AR7_SPACES_H
+
+/*
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
+ */
+#define PAGE_OFFSET		0x94000000UL
+#define PHYS_OFFSET		0x14000000UL
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_AR7_SPACES_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/war.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/war.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ar7/war.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ar7/war.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * 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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_AR7_WAR_H
+#define __ASM_MIPS_MACH_AR7_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#define R4600_V1_HIT_CACHEOP_WAR	0
+#define R4600_V2_HIT_CACHEOP_WAR	0
+#define R5432_CP0_INTERRUPT_WAR		0
+#define BCM1250_M3_WAR			0
+#define SIBYTE_1956_WAR			0
+#define MIPS4K_ICACHE_REFILL_WAR	0
+#define MIPS_CACHE_SYNC_WAR		0
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#define RM9000_CDEX_SMP_WAR		0
+#define ICACHE_REFILLS_WORKAROUND_WAR	0
+#define R10000_LLSC_WAR			0
+#define MIPS34K_MISSED_ITLB_WAR		0
+
+#endif /* __ASM_MIPS_MACH_AR7_WAR_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-au1x00/au1000_gpio.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-au1x00/au1000_gpio.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-au1x00/au1000_gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-au1x00/au1000_gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- * FILE NAME au1000_gpio.h
- *
- * BRIEF MODULE DESCRIPTION
- *	API to Alchemy Au1xx0 GPIO device.
- *
- *  Author: MontaVista Software, Inc.  <source@mvista.com>
- *          Steve Longerbeam
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  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 __AU1000_GPIO_H
-#define __AU1000_GPIO_H
-
-#include <linux/ioctl.h>
-
-#define AU1000GPIO_IOC_MAGIC 'A'
-
-#define AU1000GPIO_IN		_IOR(AU1000GPIO_IOC_MAGIC, 0, int)
-#define AU1000GPIO_SET		_IOW(AU1000GPIO_IOC_MAGIC, 1, int)
-#define AU1000GPIO_CLEAR	_IOW(AU1000GPIO_IOC_MAGIC, 2, int)
-#define AU1000GPIO_OUT		_IOW(AU1000GPIO_IOC_MAGIC, 3, int)
-#define AU1000GPIO_TRISTATE	_IOW(AU1000GPIO_IOC_MAGIC, 4, int)
-#define AU1000GPIO_AVAIL_MASK	_IOR(AU1000GPIO_IOC_MAGIC, 5, int)
-
-#ifdef __KERNEL__
-extern u32 get_au1000_avail_gpio_mask(void);
-extern int au1000gpio_tristate(u32 data);
-extern int au1000gpio_in(u32 *data);
-extern int au1000gpio_set(u32 data);
-extern int au1000gpio_clear(u32 data);
-extern int au1000gpio_out(u32 data);
-#endif
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1000.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,604 @@
+/*
+ * GPIO functions for Au1000, Au1500, Au1100, Au1550, Au1200
+ *
+ * Copyright (c) 2009 Manuel Lauss.
+ *
+ * Licensed under the terms outlined in the file COPYING.
+ */
+
+#ifndef _ALCHEMY_GPIO_AU1000_H_
+#define _ALCHEMY_GPIO_AU1000_H_
+
+#include <asm/mach-au1x00/au1000.h>
+
+/* The default GPIO numberspace as documented in the Alchemy manuals.
+ * GPIO0-31 from GPIO1 block,   GPIO200-215 from GPIO2 block.
+ */
+#define ALCHEMY_GPIO1_BASE	0
+#define ALCHEMY_GPIO2_BASE	200
+
+#define ALCHEMY_GPIO1_NUM	32
+#define ALCHEMY_GPIO2_NUM	16
+#define ALCHEMY_GPIO1_MAX 	(ALCHEMY_GPIO1_BASE + ALCHEMY_GPIO1_NUM - 1)
+#define ALCHEMY_GPIO2_MAX	(ALCHEMY_GPIO2_BASE + ALCHEMY_GPIO2_NUM - 1)
+
+#define MAKE_IRQ(intc, off)	(AU1000_INTC##intc##_INT_BASE + (off))
+
+
+static inline int au1000_gpio1_to_irq(int gpio)
+{
+	return MAKE_IRQ(1, gpio - ALCHEMY_GPIO1_BASE);
+}
+
+static inline int au1000_gpio2_to_irq(int gpio)
+{
+	return -ENXIO;
+}
+
+#ifdef CONFIG_SOC_AU1000
+static inline int au1000_irq_to_gpio(int irq)
+{
+	if ((irq >= AU1000_GPIO_0) && (irq <= AU1000_GPIO_31))
+		return ALCHEMY_GPIO1_BASE + (irq - AU1000_GPIO_0) + 0;
+
+	return -ENXIO;
+}
+#endif
+
+static inline int au1500_gpio1_to_irq(int gpio)
+{
+	gpio -= ALCHEMY_GPIO1_BASE;
+
+	switch (gpio) {
+	case 0 ... 15:
+	case 20:
+	case 23 ... 28:	return MAKE_IRQ(1, gpio);
+	}
+
+	return -ENXIO;
+}
+
+static inline int au1500_gpio2_to_irq(int gpio)
+{
+	gpio -= ALCHEMY_GPIO2_BASE;
+
+	switch (gpio) {
+	case 0 ... 3:	return MAKE_IRQ(1, 16 + gpio - 0);
+	case 4 ... 5:	return MAKE_IRQ(1, 21 + gpio - 4);
+	case 6 ... 7:	return MAKE_IRQ(1, 29 + gpio - 6);
+	}
+
+	return -ENXIO;
+}
+
+#ifdef CONFIG_SOC_AU1500
+static inline int au1500_irq_to_gpio(int irq)
+{
+	switch (irq) {
+	case AU1000_GPIO_0 ... AU1000_GPIO_15:
+	case AU1500_GPIO_20:
+	case AU1500_GPIO_23 ... AU1500_GPIO_28:
+		return ALCHEMY_GPIO1_BASE + (irq - AU1000_GPIO_0) + 0;
+	case AU1500_GPIO_200 ... AU1500_GPIO_203:
+		return ALCHEMY_GPIO2_BASE + (irq - AU1500_GPIO_200) + 0;
+	case AU1500_GPIO_204 ... AU1500_GPIO_205:
+		return ALCHEMY_GPIO2_BASE + (irq - AU1500_GPIO_204) + 4;
+	case AU1500_GPIO_206 ... AU1500_GPIO_207:
+		return ALCHEMY_GPIO2_BASE + (irq - AU1500_GPIO_206) + 6;
+	case AU1500_GPIO_208_215:
+		return ALCHEMY_GPIO2_BASE + 8;
+	}
+
+	return -ENXIO;
+}
+#endif
+
+static inline int au1100_gpio1_to_irq(int gpio)
+{
+	return MAKE_IRQ(1, gpio - ALCHEMY_GPIO1_BASE);
+}
+
+static inline int au1100_gpio2_to_irq(int gpio)
+{
+	gpio -= ALCHEMY_GPIO2_BASE;
+
+	if ((gpio >= 8) && (gpio <= 15))
+		return MAKE_IRQ(0, 29);		/* shared GPIO208_215 */
+}
+
+#ifdef CONFIG_SOC_AU1100
+static inline int au1100_irq_to_gpio(int irq)
+{
+	switch (irq) {
+	case AU1000_GPIO_0 ... AU1000_GPIO_31:
+		return ALCHEMY_GPIO1_BASE + (irq - AU1000_GPIO_0) + 0;
+	case AU1100_GPIO_208_215:
+		return ALCHEMY_GPIO2_BASE + 8;
+	}
+
+	return -ENXIO;
+}
+#endif
+
+static inline int au1550_gpio1_to_irq(int gpio)
+{
+	gpio -= ALCHEMY_GPIO1_BASE;
+
+	switch (gpio) {
+	case 0 ... 15:
+	case 20 ... 28:	return MAKE_IRQ(1, gpio);
+	case 16 ... 17:	return MAKE_IRQ(1, 18 + gpio - 16);
+	}
+
+	return -ENXIO;
+}
+
+static inline int au1550_gpio2_to_irq(int gpio)
+{
+	gpio -= ALCHEMY_GPIO2_BASE;
+
+	switch (gpio) {
+	case 0:		return MAKE_IRQ(1, 16);
+	case 1 ... 5:	return MAKE_IRQ(1, 17);	/* shared GPIO201_205 */
+	case 6 ... 7:	return MAKE_IRQ(1, 29 + gpio - 6);
+	case 8 ... 15:	return MAKE_IRQ(1, 31);	/* shared GPIO208_215 */
+	}
+
+	return -ENXIO;
+}
+
+#ifdef CONFIG_SOC_AU1550
+static inline int au1550_irq_to_gpio(int irq)
+{
+	switch (irq) {
+	case AU1000_GPIO_0 ... AU1000_GPIO_15:
+		return ALCHEMY_GPIO1_BASE + (irq - AU1000_GPIO_0) + 0;
+	case AU1550_GPIO_200:
+	case AU1500_GPIO_201_205:
+		return ALCHEMY_GPIO2_BASE + (irq - AU1550_GPIO_200) + 0;
+	case AU1500_GPIO_16 ... AU1500_GPIO_28:
+		return ALCHEMY_GPIO1_BASE + (irq - AU1500_GPIO_16) + 16;
+	case AU1500_GPIO_206 ... AU1500_GPIO_208_218:
+		return ALCHEMY_GPIO2_BASE + (irq - AU1500_GPIO_206) + 6;
+	}
+
+	return -ENXIO;
+}
+#endif
+
+static inline int au1200_gpio1_to_irq(int gpio)
+{
+	return MAKE_IRQ(1, gpio - ALCHEMY_GPIO1_BASE);
+}
+
+static inline int au1200_gpio2_to_irq(int gpio)
+{
+	gpio -= ALCHEMY_GPIO2_BASE;
+
+	switch (gpio) {
+	case 0 ... 2:	return MAKE_IRQ(0, 5 + gpio - 0);
+	case 3:		return MAKE_IRQ(0, 22);
+	case 4 ... 7:	return MAKE_IRQ(0, 24 + gpio - 4);
+	case 8 ... 15:	return MAKE_IRQ(0, 28);	/* shared GPIO208_215 */
+	}
+
+	return -ENXIO;
+}
+
+#ifdef CONFIG_SOC_AU1200
+static inline int au1200_irq_to_gpio(int irq)
+{
+	switch (irq) {
+	case AU1000_GPIO_0 ... AU1000_GPIO_31:
+		return ALCHEMY_GPIO1_BASE + (irq - AU1000_GPIO_0) + 0;
+	case AU1200_GPIO_200 ... AU1200_GPIO_202:
+		return ALCHEMY_GPIO2_BASE + (irq - AU1200_GPIO_200) + 0;
+	case AU1200_GPIO_203:
+		return ALCHEMY_GPIO2_BASE + 3;
+	case AU1200_GPIO_204 ... AU1200_GPIO_208_215:
+		return ALCHEMY_GPIO2_BASE + (irq - AU1200_GPIO_204) + 4;
+	}
+
+	return -ENXIO;
+}
+#endif
+
+/*
+ * GPIO1 block macros for common linux gpio functions.
+ */
+static inline void alchemy_gpio1_set_value(int gpio, int v)
+{
+	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
+	unsigned long r = v ? SYS_OUTPUTSET : SYS_OUTPUTCLR;
+	au_writel(mask, r);
+	au_sync();
+}
+
+static inline int alchemy_gpio1_get_value(int gpio)
+{
+	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
+	return au_readl(SYS_PINSTATERD) & mask;
+}
+
+static inline int alchemy_gpio1_direction_input(int gpio)
+{
+	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
+	au_writel(mask, SYS_TRIOUTCLR);
+	au_sync();
+	return 0;
+}
+
+static inline int alchemy_gpio1_direction_output(int gpio, int v)
+{
+	/* hardware switches to "output" mode when one of the two
+	 * "set_value" registers is accessed.
+	 */
+	alchemy_gpio1_set_value(gpio, v);
+	return 0;
+}
+
+static inline int alchemy_gpio1_is_valid(int gpio)
+{
+	return ((gpio >= ALCHEMY_GPIO1_BASE) && (gpio <= ALCHEMY_GPIO1_MAX));
+}
+
+static inline int alchemy_gpio1_to_irq(int gpio)
+{
+#if defined(CONFIG_SOC_AU1000)
+	return au1000_gpio1_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1100)
+	return au1100_gpio1_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1500)
+	return au1500_gpio1_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1550)
+	return au1550_gpio1_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1200)
+	return au1200_gpio1_to_irq(gpio);
+#else
+	return -ENXIO;
+#endif
+}
+
+/*
+ * GPIO2 block macros for common linux GPIO functions. The 'gpio'
+ * parameter must be in range of ALCHEMY_GPIO2_BASE..ALCHEMY_GPIO2_MAX.
+ */
+static inline void __alchemy_gpio2_mod_dir(int gpio, int to_out)
+{
+	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO2_BASE);
+	unsigned long d = au_readl(GPIO2_DIR);
+	if (to_out)
+		d |= mask;
+	else
+		d &= ~mask;
+	au_writel(d, GPIO2_DIR);
+	au_sync();
+}
+
+static inline void alchemy_gpio2_set_value(int gpio, int v)
+{
+	unsigned long mask;
+	mask = ((v) ? 0x00010001 : 0x00010000) << (gpio - ALCHEMY_GPIO2_BASE);
+	au_writel(mask, GPIO2_OUTPUT);
+	au_sync();
+}
+
+static inline int alchemy_gpio2_get_value(int gpio)
+{
+	return au_readl(GPIO2_PINSTATE) & (1 << (gpio - ALCHEMY_GPIO2_BASE));
+}
+
+static inline int alchemy_gpio2_direction_input(int gpio)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	__alchemy_gpio2_mod_dir(gpio, 0);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static inline int alchemy_gpio2_direction_output(int gpio, int v)
+{
+	unsigned long flags;
+	alchemy_gpio2_set_value(gpio, v);
+	local_irq_save(flags);
+	__alchemy_gpio2_mod_dir(gpio, 1);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static inline int alchemy_gpio2_is_valid(int gpio)
+{
+	return ((gpio >= ALCHEMY_GPIO2_BASE) && (gpio <= ALCHEMY_GPIO2_MAX));
+}
+
+static inline int alchemy_gpio2_to_irq(int gpio)
+{
+#if defined(CONFIG_SOC_AU1000)
+	return au1000_gpio2_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1100)
+	return au1100_gpio2_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1500)
+	return au1500_gpio2_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1550)
+	return au1550_gpio2_to_irq(gpio);
+#elif defined(CONFIG_SOC_AU1200)
+	return au1200_gpio2_to_irq(gpio);
+#else
+	return -ENXIO;
+#endif
+}
+
+/**********************************************************************/
+
+/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
+ * SYS_PININPUTEN is written to at least once.  On Au1550/Au1200 this
+ * register enables use of GPIOs as wake source.
+ */
+static inline void alchemy_gpio1_input_enable(void)
+{
+	au_writel(0, SYS_PININPUTEN);	/* the write op is key */
+	au_sync();
+}
+
+/* GPIO2 shared interrupts and control */
+
+static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
+{
+	unsigned long r = au_readl(GPIO2_INTENABLE);
+	if (en)
+		r |= 1 << gpio2;
+	else
+		r &= ~(1 << gpio2);
+	au_writel(r, GPIO2_INTENABLE);
+	au_sync();
+}
+
+/**
+ * alchemy_gpio2_enable_int - Enable a GPIO2 pins' shared irq contribution.
+ * @gpio2:	The GPIO2 pin to activate (200...215).
+ *
+ * GPIO208-215 have one shared interrupt line to the INTC.  They are
+ * and'ed with a per-pin enable bit and finally or'ed together to form
+ * a single irq request (useful for active-high sources).
+ * With this function, a pins' individual contribution to the int request
+ * can be enabled.  As with all other GPIO-based interrupts, the INTC
+ * must be programmed to accept the GPIO208_215 interrupt as well.
+ *
+ * NOTE: Calling this macro is only necessary for GPIO208-215; all other
+ * GPIO2-based interrupts have their own request to the INTC.  Please
+ * consult your Alchemy databook for more information!
+ *
+ * NOTE: On the Au1550, GPIOs 201-205 also have a shared interrupt request
+ * line to the INTC, GPIO201_205.  This function can be used for those
+ * as well.
+ *
+ * NOTE: 'gpio2' parameter must be in range of the GPIO2 numberspace
+ * (200-215 by default). No sanity checks are made,
+ */
+static inline void alchemy_gpio2_enable_int(int gpio2)
+{
+	unsigned long flags;
+
+	gpio2 -= ALCHEMY_GPIO2_BASE;
+
+#if defined(CONFIG_SOC_AU1100) || defined(CONFIG_SOC_AU1500)
+	/* Au1100/Au1500 have GPIO208-215 enable bits at 0..7 */
+	gpio2 -= 8;
+#endif
+	local_irq_save(flags);
+	__alchemy_gpio2_mod_int(gpio2, 1);
+	local_irq_restore(flags);
+}
+
+/**
+ * alchemy_gpio2_disable_int - Disable a GPIO2 pins' shared irq contribution.
+ * @gpio2:	The GPIO2 pin to activate (200...215).
+ *
+ * see function alchemy_gpio2_enable_int() for more information.
+ */
+static inline void alchemy_gpio2_disable_int(int gpio2)
+{
+	unsigned long flags;
+
+	gpio2 -= ALCHEMY_GPIO2_BASE;
+
+#if defined(CONFIG_SOC_AU1100) || defined(CONFIG_SOC_AU1500)
+	/* Au1100/Au1500 have GPIO208-215 enable bits at 0..7 */
+	gpio2 -= 8;
+#endif
+	local_irq_save(flags);
+	__alchemy_gpio2_mod_int(gpio2, 0);
+	local_irq_restore(flags);
+}
+
+/**
+ * alchemy_gpio2_enable -  Activate GPIO2 block.
+ *
+ * The GPIO2 block must be enabled excplicitly to work.  On systems
+ * where this isn't done by the bootloader, this macro can be used.
+ */
+static inline void alchemy_gpio2_enable(void)
+{
+	au_writel(3, GPIO2_ENABLE);	/* reset, clock enabled */
+	au_sync();
+	au_writel(1, GPIO2_ENABLE);	/* clock enabled */
+	au_sync();
+}
+
+/**
+ * alchemy_gpio2_disable - disable GPIO2 block.
+ *
+ * Disable and put GPIO2 block in low-power mode.
+ */
+static inline void alchemy_gpio2_disable(void)
+{
+	au_writel(2, GPIO2_ENABLE);	/* reset, clock disabled */
+	au_sync();
+}
+
+/**********************************************************************/
+
+/* wrappers for on-chip gpios; can be used before gpio chips have been
+ * registered with gpiolib.
+ */
+static inline int alchemy_gpio_direction_input(int gpio)
+{
+	return (gpio >= ALCHEMY_GPIO2_BASE) ?
+		alchemy_gpio2_direction_input(gpio) :
+		alchemy_gpio1_direction_input(gpio);
+}
+
+static inline int alchemy_gpio_direction_output(int gpio, int v)
+{
+	return (gpio >= ALCHEMY_GPIO2_BASE) ?
+		alchemy_gpio2_direction_output(gpio, v) :
+		alchemy_gpio1_direction_output(gpio, v);
+}
+
+static inline int alchemy_gpio_get_value(int gpio)
+{
+	return (gpio >= ALCHEMY_GPIO2_BASE) ?
+		alchemy_gpio2_get_value(gpio) :
+		alchemy_gpio1_get_value(gpio);
+}
+
+static inline void alchemy_gpio_set_value(int gpio, int v)
+{
+	if (gpio >= ALCHEMY_GPIO2_BASE)
+		alchemy_gpio2_set_value(gpio, v);
+	else
+		alchemy_gpio1_set_value(gpio, v);
+}
+
+static inline int alchemy_gpio_is_valid(int gpio)
+{
+	return (gpio >= ALCHEMY_GPIO2_BASE) ?
+		alchemy_gpio2_is_valid(gpio) :
+		alchemy_gpio1_is_valid(gpio);
+}
+
+static inline int alchemy_gpio_cansleep(int gpio)
+{
+	return 0;	/* Alchemy never gets tired */
+}
+
+static inline int alchemy_gpio_to_irq(int gpio)
+{
+	return (gpio >= ALCHEMY_GPIO2_BASE) ?
+		alchemy_gpio2_to_irq(gpio) :
+		alchemy_gpio1_to_irq(gpio);
+}
+
+static inline int alchemy_irq_to_gpio(int irq)
+{
+#if defined(CONFIG_SOC_AU1000)
+	return au1000_irq_to_gpio(irq);
+#elif defined(CONFIG_SOC_AU1100)
+	return au1100_irq_to_gpio(irq);
+#elif defined(CONFIG_SOC_AU1500)
+	return au1500_irq_to_gpio(irq);
+#elif defined(CONFIG_SOC_AU1550)
+	return au1550_irq_to_gpio(irq);
+#elif defined(CONFIG_SOC_AU1200)
+	return au1200_irq_to_gpio(irq);
+#else
+	return -ENXIO;
+#endif
+}
+
+/**********************************************************************/
+
+/* Linux gpio framework integration.
+ *
+ * 4 use cases of Au1000-Au1200 GPIOS:
+ *(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
+ *	Board must register gpiochips.
+ *(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
+ *	2 (1 for Au1000) gpio_chips are registered.
+ *
+ *(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
+ *	the boards' gpio.h must provide	the linux gpio wrapper functions,
+ *
+ *(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
+ *	inlinable gpio functions are provided which enable access to the
+ *	Au1000 gpios only by using the numbers straight out of the data-
+ *	sheets.
+
+ * Cases 1 and 3 are intended for boards which want to provide their own
+ * GPIO namespace and -operations (i.e. for example you have 8 GPIOs
+ * which are in part provided by spare Au1000 GPIO pins and in part by
+ * an external FPGA but you still want them to be accssible in linux
+ * as gpio0-7. The board can of course use the alchemy_gpioX_* functions
+ * as required).
+ */
+
+#ifndef CONFIG_GPIOLIB
+
+
+#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (4) */
+
+static inline int gpio_direction_input(int gpio)
+{
+	return alchemy_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(int gpio, int v)
+{
+	return alchemy_gpio_direction_output(gpio, v);
+}
+
+static inline int gpio_get_value(int gpio)
+{
+	return alchemy_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(int gpio, int v)
+{
+	alchemy_gpio_set_value(gpio, v);
+}
+
+static inline int gpio_is_valid(int gpio)
+{
+	return alchemy_gpio_is_valid(gpio);
+}
+
+static inline int gpio_cansleep(int gpio)
+{
+	return alchemy_gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(int gpio)
+{
+	return alchemy_gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(int irq)
+{
+	return alchemy_irq_to_gpio(irq);
+}
+
+#endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
+
+
+#else	/* CONFIG GPIOLIB */
+
+
+ /* using gpiolib to provide up to 2 gpio_chips for on-chip gpios */
+#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT	/* case (2) */
+
+/* get everything through gpiolib */
+#define gpio_to_irq	__gpio_to_irq
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define irq_to_gpio	alchemy_irq_to_gpio
+
+#include <asm-generic/gpio.h>
+
+#endif	/* !CONFIG_ALCHEMY_GPIO_INDIRECT */
+
+
+#endif	/* !CONFIG_GPIOLIB */
+
+#endif /* _ALCHEMY_GPIO_AU1000_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-au1x00/gpio.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-au1x00/gpio.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-au1x00/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-au1x00/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,33 +1,10 @@
-#ifndef _AU1XXX_GPIO_H_
-#define _AU1XXX_GPIO_H_
-
-#include <linux/types.h>
-
-#define AU1XXX_GPIO_BASE	200
-
-/* GPIO bank 1 offsets */
-#define AU1000_GPIO1_TRI_OUT	0x0100
-#define AU1000_GPIO1_OUT	0x0108
-#define AU1000_GPIO1_ST		0x0110
-#define AU1000_GPIO1_CLR	0x010C
-
-/* GPIO bank 2 offsets */
-#define AU1000_GPIO2_DIR	0x00
-#define AU1000_GPIO2_RSVD	0x04
-#define AU1000_GPIO2_OUT	0x08
-#define AU1000_GPIO2_ST		0x0C
-#define AU1000_GPIO2_INT	0x10
-#define AU1000_GPIO2_EN		0x14
-
-#define GPIO2_OUT_EN_MASK	0x00010000
-
-#define gpio_to_irq(gpio)	NULL
+#ifndef _ALCHEMY_GPIO_H_
+#define _ALCHEMY_GPIO_H_
 
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
+#if defined(CONFIG_ALCHEMY_GPIO_AU1000)
 
-#define gpio_cansleep __gpio_cansleep
+#include <asm/mach-au1x00/gpio-au1000.h>
 
-#include <asm-generic/gpio.h>
+#endif
 
-#endif /* _AU1XXX_GPIO_H_ */
+#endif	/* _ALCHEMY_GPIO_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-bcm47xx/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,9 @@
 
 static inline int gpio_direction_output(unsigned gpio, int value)
 {
+	/* first set the gpio out value */
+	ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
+	/* then set the gpio mode */
 	ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h	2009-09-09 18:13:59.000000000 -0400
@@ -47,11 +47,13 @@
 #define cpu_has_mips32r2	0
 #define cpu_has_mips64r1	0
 #define cpu_has_mips64r2	1
+#define cpu_has_mips_r2_exec_hazard 0
 #define cpu_has_dsp		0
 #define cpu_has_mipsmt		0
 #define cpu_has_userlocal	0
 #define cpu_has_vint		0
 #define cpu_has_veic		0
+#define cpu_hwrena_impl_bits	0xc0000000
 #define ARCH_HAS_READ_CURRENT_TIMER 1
 #define ARCH_HAS_IRQ_PER_CPU	1
 #define ARCH_HAS_SPINLOCK_PREFETCH 1
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,12 +30,14 @@
 	return octeon_map_dma_mem(dev, page_address(page), PAGE_SIZE);
 }
 
-static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+	dma_addr_t dma_addr)
 {
 	return dma_addr;
 }
 
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction)
 {
 	octeon_unmap_dma_mem(dev, dma_addr);
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cobalt/irq.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cobalt/irq.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cobalt/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cobalt/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,7 @@
  * Copyright (C) 1997 Cobalt Microserver
  * Copyright (C) 1997, 2003 Ralf Baechle
  * Copyright (C) 2001-2003 Liam Davies (ldavies@agile.tv)
- * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org>
  */
 #ifndef _ASM_COBALT_IRQ_H
 #define _ASM_COBALT_IRQ_H
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cobalt/mach-gt64120.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cobalt/mach-gt64120.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-cobalt/mach-gt64120.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-cobalt/mach-gt64120.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2006  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-generic/dma-coherence.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-generic/dma-coherence.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-generic/dma-coherence.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-generic/dma-coherence.h	2009-09-09 18:13:59.000000000 -0400
@@ -23,12 +23,14 @@
 	return page_to_phys(page);
 }
 
-static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+	dma_addr_t dma_addr)
 {
 	return dma_addr;
 }
 
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction)
 {
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,12 +33,14 @@
 	return pa;
 }
 
-static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static unsigned long plat_dma_addr_to_phys(struct device *dev,
+	dma_addr_t dma_addr)
 {
 	return dma_addr & ~(0xffUL << 56);
 }
 
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction)
 {
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,8 @@
 }
 
 /* This is almost certainly wrong but it's what dma-ip32.c used to use  */
-static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static unsigned long plat_dma_addr_to_phys(struct device *dev,
+	dma_addr_t dma_addr)
 {
 	unsigned long addr = dma_addr & RAM_OFFSET_MASK;
 
@@ -60,7 +61,8 @@
 	return addr;
 }
 
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction)
 {
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-jazz/dma-coherence.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-jazz/dma-coherence.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-jazz/dma-coherence.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-jazz/dma-coherence.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,12 +22,14 @@
 	return vdma_alloc(page_to_phys(page), PAGE_SIZE);
 }
 
-static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static unsigned long plat_dma_addr_to_phys(struct device *dev,
+	dma_addr_t dma_addr)
 {
 	return vdma_log2phys(dma_addr);
 }
 
-static void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction)
 {
 	vdma_free(dma_addr);
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-lemote/dma-coherence.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-lemote/dma-coherence.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-lemote/dma-coherence.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-lemote/dma-coherence.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,12 +25,14 @@
 	return page_to_phys(page) | 0x80000000;
 }
 
-static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+	dma_addr_t dma_addr)
 {
 	return dma_addr & 0x7fffffff;
 }
 
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction)
 {
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,11 +53,6 @@
 #define cpu_has_smartmips		0
 
 #define cpu_has_vtag_icache		0
-/* #define cpu_has_dc_aliases		? */
-/* #define cpu_has_ic_fills_f_dc	? */
-/* #define cpu_has_pindexed_dcache	? */
-
-/* #define cpu_icache_snoops_remote_store	? */
 
 #define cpu_has_mips32r1		1
 #define cpu_has_mips32r2		0
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mipsregs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mipsregs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mipsregs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mipsregs.h	2009-09-09 18:13:59.000000000 -0400
@@ -220,6 +220,22 @@
 #error Bad page size configuration!
 #endif
 
+/*
+ * Default huge tlb size for a given kernel configuration
+ */
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PM_HUGE_MASK	PM_1M
+#elif defined(CONFIG_PAGE_SIZE_8KB)
+#define PM_HUGE_MASK	PM_4M
+#elif defined(CONFIG_PAGE_SIZE_16KB)
+#define PM_HUGE_MASK	PM_16M
+#elif defined(CONFIG_PAGE_SIZE_32KB)
+#define PM_HUGE_MASK	PM_64M
+#elif defined(CONFIG_PAGE_SIZE_64KB)
+#define PM_HUGE_MASK	PM_256M
+#elif defined(CONFIG_HUGETLB_PAGE)
+#error Bad page size configuration for hugetlbfs!
+#endif
 
 /*
  * Values used for computation of new tlb entries
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/mmu_context.h linux-libre-2.6.31-gnu/arch/mips/include/asm/mmu_context.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/mmu_context.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/mmu_context.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/slab.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2009-09-09 18:13:59.000000000 -0400
@@ -157,6 +157,13 @@
 	CVMX_BOARD_TYPE_NIC_XLE_4G = 21,
 	CVMX_BOARD_TYPE_EBT5600 = 22,
 	CVMX_BOARD_TYPE_EBH5201 = 23,
+	CVMX_BOARD_TYPE_EBT5200 = 24,
+	CVMX_BOARD_TYPE_CB5600  = 25,
+	CVMX_BOARD_TYPE_CB5601  = 26,
+	CVMX_BOARD_TYPE_CB5200  = 27,
+	/* Special 'generic' board type, supports many boards */
+	CVMX_BOARD_TYPE_GENERIC = 28,
+	CVMX_BOARD_TYPE_EBH5610 = 29,
 	CVMX_BOARD_TYPE_MAX,
 
 	/*
@@ -228,6 +235,12 @@
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5200)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5600)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5601)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CB5200)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_GENERIC)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5610)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX)
 
 			/* Customer boards listed here */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h	2009-09-09 18:13:59.000000000 -0400
@@ -183,6 +183,64 @@
  * Returns 0 on failure,
  *         !0 on success
  */
+
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader, and assign it a name in the
+ * global named block table.  (part of the cvmx_bootmem_descriptor_t structure)
+ * Named blocks can later be freed.
+ *
+ * @size:      Size in bytes of block to allocate
+ * @alignment: Alignment required - must be power of 2
+ * @name:      name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ *
+ * Returns a pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment,
+				      char *name);
+
+
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader, and assign it a name in the
+ * global named block table.  (part of the cvmx_bootmem_descriptor_t structure)
+ * Named blocks can later be freed.
+ *
+ * @size:     Size in bytes of block to allocate
+ * @address:  Physical address to allocate memory at.  If this
+ *            memory is not available, the allocation fails.
+ * @name:     name of block - must be less than CVMX_BOOTMEM_NAME_LEN
+ *            bytes
+ *
+ * Returns a pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address,
+					      char *name);
+
+
+
+/**
+ * Allocate a block of memory from a specific range of the free list
+ * that was passed to the application by the bootloader, and assign it
+ * a name in the global named block table.  (part of the
+ * cvmx_bootmem_descriptor_t structure) Named blocks can later be
+ * freed.  If request cannot be satisfied within the address range
+ * specified, NULL is returned
+ *
+ * @size:      Size in bytes of block to allocate
+ * @min_addr:  minimum address of range
+ * @max_addr:  maximum address of range
+ * @align:     Alignment of memory to be allocated. (must be a power of 2)
+ * @name:      name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ *
+ * Returns a pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
+					    uint64_t max_addr, uint64_t align,
+					    char *name);
+
 extern int cvmx_bootmem_free_named(char *name);
 
 /**
@@ -224,6 +282,33 @@
 			       uint32_t flags);
 
 /**
+ * Allocates a named block of physical memory from the free list, at
+ * (optional) requested address and alignment.
+ *
+ * @param size      size of region to allocate.  All requests are rounded
+ *                  up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE
+ *                  bytes size
+ * @param min_addr Minimum address that block can occupy.
+ * @param max_addr  Specifies the maximum address_min (inclusive) that
+ *                  the allocation can use.
+ * @param alignment Requested alignment of the block.  If this
+ *                  alignment cannot be met, the allocation fails.
+ *                  This must be a power of 2.  (Note: Alignment of
+ *                  CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and
+ *                  internally enforced.  Requested alignments of less
+ *                  than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to
+ *                  CVMX_BOOTMEM_ALIGNMENT_SIZE.)
+ * @param name      name to assign to named block
+ * @param flags     Flags to control options for the allocation.
+ *
+ * @return physical address of block allocated, or -1 on failure
+ */
+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
+					   uint64_t max_addr,
+					   uint64_t alignment,
+					   char *name, uint32_t flags);
+
+/**
  * Finds a named memory block by name.
  * Also used for finding an unused entry in the named block table.
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx.h	2009-09-09 18:13:59.000000000 -0400
@@ -376,6 +376,18 @@
 }
 
 /**
+ * Wait for the specified number of cycle
+ *
+ */
+static inline void cvmx_wait(uint64_t cycles)
+{
+	uint64_t done = cvmx_get_cycle() + cycles;
+
+	while (cvmx_get_cycle() < done)
+		; /* Spin */
+}
+
+/**
  * Reads a chip global cycle counter.  This counts CPU cycles since
  * chip reset.  The counter is 64 bit.
  * This register does not exist on CN38XX pass 1 silicion
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-helper-errata.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-helper-errata.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-helper-errata.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-helper-errata.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,33 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_HELPER_ERRATA_H__
+#define __CVMX_HELPER_ERRATA_H__
+
+extern void __cvmx_helper_errata_qlm_disable_2nd_order_cdr(int qlm);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-helper-jtag.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-helper-jtag.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-helper-jtag.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-helper-jtag.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,43 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ *
+ *  Helper utilities for qlm_jtag.
+ *
+ */
+
+#ifndef __CVMX_HELPER_JTAG_H__
+#define __CVMX_HELPER_JTAG_H__
+
+extern void cvmx_helper_qlm_jtag_init(void);
+extern uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data);
+extern void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits);
+extern void cvmx_helper_qlm_jtag_update(int qlm);
+
+#endif /* __CVMX_HELPER_JTAG_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-npei-defs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-npei-defs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-npei-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-npei-defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2560 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_NPEI_DEFS_H__
+#define __CVMX_NPEI_DEFS_H__
+
+#define CVMX_NPEI_BAR1_INDEXX(offset) \
+	 (0x0000000000000000ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_BIST_STATUS \
+	 (0x0000000000000580ull)
+#define CVMX_NPEI_BIST_STATUS2 \
+	 (0x0000000000000680ull)
+#define CVMX_NPEI_CTL_PORT0 \
+	 (0x0000000000000250ull)
+#define CVMX_NPEI_CTL_PORT1 \
+	 (0x0000000000000260ull)
+#define CVMX_NPEI_CTL_STATUS \
+	 (0x0000000000000570ull)
+#define CVMX_NPEI_CTL_STATUS2 \
+	 (0x0000000000003C00ull)
+#define CVMX_NPEI_DATA_OUT_CNT \
+	 (0x00000000000005F0ull)
+#define CVMX_NPEI_DBG_DATA \
+	 (0x0000000000000510ull)
+#define CVMX_NPEI_DBG_SELECT \
+	 (0x0000000000000500ull)
+#define CVMX_NPEI_DMA0_INT_LEVEL \
+	 (0x00000000000005C0ull)
+#define CVMX_NPEI_DMA1_INT_LEVEL \
+	 (0x00000000000005D0ull)
+#define CVMX_NPEI_DMAX_COUNTS(offset) \
+	 (0x0000000000000450ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMAX_DBELL(offset) \
+	 (0x00000000000003B0ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMAX_IBUFF_SADDR(offset) \
+	 (0x0000000000000400ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMAX_NADDR(offset) \
+	 (0x00000000000004A0ull + (((offset) & 7) * 16))
+#define CVMX_NPEI_DMA_CNTS \
+	 (0x00000000000005E0ull)
+#define CVMX_NPEI_DMA_CONTROL \
+	 (0x00000000000003A0ull)
+#define CVMX_NPEI_INT_A_ENB \
+	 (0x0000000000000560ull)
+#define CVMX_NPEI_INT_A_ENB2 \
+	 (0x0000000000003CE0ull)
+#define CVMX_NPEI_INT_A_SUM \
+	 (0x0000000000000550ull)
+#define CVMX_NPEI_INT_ENB \
+	 (0x0000000000000540ull)
+#define CVMX_NPEI_INT_ENB2 \
+	 (0x0000000000003CD0ull)
+#define CVMX_NPEI_INT_INFO \
+	 (0x0000000000000590ull)
+#define CVMX_NPEI_INT_SUM \
+	 (0x0000000000000530ull)
+#define CVMX_NPEI_INT_SUM2 \
+	 (0x0000000000003CC0ull)
+#define CVMX_NPEI_LAST_WIN_RDATA0 \
+	 (0x0000000000000600ull)
+#define CVMX_NPEI_LAST_WIN_RDATA1 \
+	 (0x0000000000000610ull)
+#define CVMX_NPEI_MEM_ACCESS_CTL \
+	 (0x00000000000004F0ull)
+#define CVMX_NPEI_MEM_ACCESS_SUBIDX(offset) \
+	 (0x0000000000000340ull + (((offset) & 31) * 16) - 16 * 12)
+#define CVMX_NPEI_MSI_ENB0 \
+	 (0x0000000000003C50ull)
+#define CVMX_NPEI_MSI_ENB1 \
+	 (0x0000000000003C60ull)
+#define CVMX_NPEI_MSI_ENB2 \
+	 (0x0000000000003C70ull)
+#define CVMX_NPEI_MSI_ENB3 \
+	 (0x0000000000003C80ull)
+#define CVMX_NPEI_MSI_RCV0 \
+	 (0x0000000000003C10ull)
+#define CVMX_NPEI_MSI_RCV1 \
+	 (0x0000000000003C20ull)
+#define CVMX_NPEI_MSI_RCV2 \
+	 (0x0000000000003C30ull)
+#define CVMX_NPEI_MSI_RCV3 \
+	 (0x0000000000003C40ull)
+#define CVMX_NPEI_MSI_RD_MAP \
+	 (0x0000000000003CA0ull)
+#define CVMX_NPEI_MSI_W1C_ENB0 \
+	 (0x0000000000003CF0ull)
+#define CVMX_NPEI_MSI_W1C_ENB1 \
+	 (0x0000000000003D00ull)
+#define CVMX_NPEI_MSI_W1C_ENB2 \
+	 (0x0000000000003D10ull)
+#define CVMX_NPEI_MSI_W1C_ENB3 \
+	 (0x0000000000003D20ull)
+#define CVMX_NPEI_MSI_W1S_ENB0 \
+	 (0x0000000000003D30ull)
+#define CVMX_NPEI_MSI_W1S_ENB1 \
+	 (0x0000000000003D40ull)
+#define CVMX_NPEI_MSI_W1S_ENB2 \
+	 (0x0000000000003D50ull)
+#define CVMX_NPEI_MSI_W1S_ENB3 \
+	 (0x0000000000003D60ull)
+#define CVMX_NPEI_MSI_WR_MAP \
+	 (0x0000000000003C90ull)
+#define CVMX_NPEI_PCIE_CREDIT_CNT \
+	 (0x0000000000003D70ull)
+#define CVMX_NPEI_PCIE_MSI_RCV \
+	 (0x0000000000003CB0ull)
+#define CVMX_NPEI_PCIE_MSI_RCV_B1 \
+	 (0x0000000000000650ull)
+#define CVMX_NPEI_PCIE_MSI_RCV_B2 \
+	 (0x0000000000000660ull)
+#define CVMX_NPEI_PCIE_MSI_RCV_B3 \
+	 (0x0000000000000670ull)
+#define CVMX_NPEI_PKTX_CNTS(offset) \
+	 (0x0000000000002400ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_BADDR(offset) \
+	 (0x0000000000002800ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \
+	 (0x0000000000002C00ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \
+	 (0x0000000000003000ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_INSTR_HEADER(offset) \
+	 (0x0000000000003400ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_IN_BP(offset) \
+	 (0x0000000000003800ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_SLIST_BADDR(offset) \
+	 (0x0000000000001400ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \
+	 (0x0000000000001800ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \
+	 (0x0000000000001C00ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKT_CNT_INT \
+	 (0x0000000000001110ull)
+#define CVMX_NPEI_PKT_CNT_INT_ENB \
+	 (0x0000000000001130ull)
+#define CVMX_NPEI_PKT_DATA_OUT_ES \
+	 (0x00000000000010B0ull)
+#define CVMX_NPEI_PKT_DATA_OUT_NS \
+	 (0x00000000000010A0ull)
+#define CVMX_NPEI_PKT_DATA_OUT_ROR \
+	 (0x0000000000001090ull)
+#define CVMX_NPEI_PKT_DPADDR \
+	 (0x0000000000001080ull)
+#define CVMX_NPEI_PKT_INPUT_CONTROL \
+	 (0x0000000000001150ull)
+#define CVMX_NPEI_PKT_INSTR_ENB \
+	 (0x0000000000001000ull)
+#define CVMX_NPEI_PKT_INSTR_RD_SIZE \
+	 (0x0000000000001190ull)
+#define CVMX_NPEI_PKT_INSTR_SIZE \
+	 (0x0000000000001020ull)
+#define CVMX_NPEI_PKT_INT_LEVELS \
+	 (0x0000000000001100ull)
+#define CVMX_NPEI_PKT_IN_BP \
+	 (0x00000000000006B0ull)
+#define CVMX_NPEI_PKT_IN_DONEX_CNTS(offset) \
+	 (0x0000000000002000ull + (((offset) & 31) * 16))
+#define CVMX_NPEI_PKT_IN_INSTR_COUNTS \
+	 (0x00000000000006A0ull)
+#define CVMX_NPEI_PKT_IN_PCIE_PORT \
+	 (0x00000000000011A0ull)
+#define CVMX_NPEI_PKT_IPTR \
+	 (0x0000000000001070ull)
+#define CVMX_NPEI_PKT_OUTPUT_WMARK \
+	 (0x0000000000001160ull)
+#define CVMX_NPEI_PKT_OUT_BMODE \
+	 (0x00000000000010D0ull)
+#define CVMX_NPEI_PKT_OUT_ENB \
+	 (0x0000000000001010ull)
+#define CVMX_NPEI_PKT_PCIE_PORT \
+	 (0x00000000000010E0ull)
+#define CVMX_NPEI_PKT_PORT_IN_RST \
+	 (0x0000000000000690ull)
+#define CVMX_NPEI_PKT_SLIST_ES \
+	 (0x0000000000001050ull)
+#define CVMX_NPEI_PKT_SLIST_ID_SIZE \
+	 (0x0000000000001180ull)
+#define CVMX_NPEI_PKT_SLIST_NS \
+	 (0x0000000000001040ull)
+#define CVMX_NPEI_PKT_SLIST_ROR \
+	 (0x0000000000001030ull)
+#define CVMX_NPEI_PKT_TIME_INT \
+	 (0x0000000000001120ull)
+#define CVMX_NPEI_PKT_TIME_INT_ENB \
+	 (0x0000000000001140ull)
+#define CVMX_NPEI_RSL_INT_BLOCKS \
+	 (0x0000000000000520ull)
+#define CVMX_NPEI_SCRATCH_1 \
+	 (0x0000000000000270ull)
+#define CVMX_NPEI_STATE1 \
+	 (0x0000000000000620ull)
+#define CVMX_NPEI_STATE2 \
+	 (0x0000000000000630ull)
+#define CVMX_NPEI_STATE3 \
+	 (0x0000000000000640ull)
+#define CVMX_NPEI_WINDOW_CTL \
+	 (0x0000000000000380ull)
+#define CVMX_NPEI_WIN_RD_ADDR \
+	 (0x0000000000000210ull)
+#define CVMX_NPEI_WIN_RD_DATA \
+	 (0x0000000000000240ull)
+#define CVMX_NPEI_WIN_WR_ADDR \
+	 (0x0000000000000200ull)
+#define CVMX_NPEI_WIN_WR_DATA \
+	 (0x0000000000000220ull)
+#define CVMX_NPEI_WIN_WR_MASK \
+	 (0x0000000000000230ull)
+
+union cvmx_npei_bar1_indexx {
+	uint32_t u32;
+	struct cvmx_npei_bar1_indexx_s {
+		uint32_t reserved_18_31:14;
+		uint32_t addr_idx:14;
+		uint32_t ca:1;
+		uint32_t end_swp:2;
+		uint32_t addr_v:1;
+	} s;
+	struct cvmx_npei_bar1_indexx_s cn52xx;
+	struct cvmx_npei_bar1_indexx_s cn52xxp1;
+	struct cvmx_npei_bar1_indexx_s cn56xx;
+	struct cvmx_npei_bar1_indexx_s cn56xxp1;
+};
+
+union cvmx_npei_bist_status {
+	uint64_t u64;
+	struct cvmx_npei_bist_status_s {
+		uint64_t pkt_rdf:1;
+		uint64_t pkt_pmem:1;
+		uint64_t pkt_p1:1;
+		uint64_t reserved_60_60:1;
+		uint64_t pcr_gim:1;
+		uint64_t pkt_pif:1;
+		uint64_t pcsr_int:1;
+		uint64_t pcsr_im:1;
+		uint64_t pcsr_cnt:1;
+		uint64_t pcsr_id:1;
+		uint64_t pcsr_sl:1;
+		uint64_t reserved_50_52:3;
+		uint64_t pkt_ind:1;
+		uint64_t pkt_slm:1;
+		uint64_t reserved_36_47:12;
+		uint64_t d0_pst:1;
+		uint64_t d1_pst:1;
+		uint64_t d2_pst:1;
+		uint64_t d3_pst:1;
+		uint64_t reserved_31_31:1;
+		uint64_t n2p0_c:1;
+		uint64_t n2p0_o:1;
+		uint64_t n2p1_c:1;
+		uint64_t n2p1_o:1;
+		uint64_t cpl_p0:1;
+		uint64_t cpl_p1:1;
+		uint64_t p2n1_po:1;
+		uint64_t p2n1_no:1;
+		uint64_t p2n1_co:1;
+		uint64_t p2n0_po:1;
+		uint64_t p2n0_no:1;
+		uint64_t p2n0_co:1;
+		uint64_t p2n0_c0:1;
+		uint64_t p2n0_c1:1;
+		uint64_t p2n0_n:1;
+		uint64_t p2n0_p0:1;
+		uint64_t p2n0_p1:1;
+		uint64_t p2n1_c0:1;
+		uint64_t p2n1_c1:1;
+		uint64_t p2n1_n:1;
+		uint64_t p2n1_p0:1;
+		uint64_t p2n1_p1:1;
+		uint64_t csm0:1;
+		uint64_t csm1:1;
+		uint64_t dif0:1;
+		uint64_t dif1:1;
+		uint64_t dif2:1;
+		uint64_t dif3:1;
+		uint64_t reserved_2_2:1;
+		uint64_t msi:1;
+		uint64_t ncb_cmd:1;
+	} s;
+	struct cvmx_npei_bist_status_cn52xx {
+		uint64_t pkt_rdf:1;
+		uint64_t pkt_pmem:1;
+		uint64_t pkt_p1:1;
+		uint64_t reserved_60_60:1;
+		uint64_t pcr_gim:1;
+		uint64_t pkt_pif:1;
+		uint64_t pcsr_int:1;
+		uint64_t pcsr_im:1;
+		uint64_t pcsr_cnt:1;
+		uint64_t pcsr_id:1;
+		uint64_t pcsr_sl:1;
+		uint64_t pkt_imem:1;
+		uint64_t pkt_pfm:1;
+		uint64_t pkt_pof:1;
+		uint64_t reserved_48_49:2;
+		uint64_t pkt_pop0:1;
+		uint64_t pkt_pop1:1;
+		uint64_t d0_mem:1;
+		uint64_t d1_mem:1;
+		uint64_t d2_mem:1;
+		uint64_t d3_mem:1;
+		uint64_t d4_mem:1;
+		uint64_t ds_mem:1;
+		uint64_t reserved_36_39:4;
+		uint64_t d0_pst:1;
+		uint64_t d1_pst:1;
+		uint64_t d2_pst:1;
+		uint64_t d3_pst:1;
+		uint64_t d4_pst:1;
+		uint64_t n2p0_c:1;
+		uint64_t n2p0_o:1;
+		uint64_t n2p1_c:1;
+		uint64_t n2p1_o:1;
+		uint64_t cpl_p0:1;
+		uint64_t cpl_p1:1;
+		uint64_t p2n1_po:1;
+		uint64_t p2n1_no:1;
+		uint64_t p2n1_co:1;
+		uint64_t p2n0_po:1;
+		uint64_t p2n0_no:1;
+		uint64_t p2n0_co:1;
+		uint64_t p2n0_c0:1;
+		uint64_t p2n0_c1:1;
+		uint64_t p2n0_n:1;
+		uint64_t p2n0_p0:1;
+		uint64_t p2n0_p1:1;
+		uint64_t p2n1_c0:1;
+		uint64_t p2n1_c1:1;
+		uint64_t p2n1_n:1;
+		uint64_t p2n1_p0:1;
+		uint64_t p2n1_p1:1;
+		uint64_t csm0:1;
+		uint64_t csm1:1;
+		uint64_t dif0:1;
+		uint64_t dif1:1;
+		uint64_t dif2:1;
+		uint64_t dif3:1;
+		uint64_t dif4:1;
+		uint64_t msi:1;
+		uint64_t ncb_cmd:1;
+	} cn52xx;
+	struct cvmx_npei_bist_status_cn52xxp1 {
+		uint64_t reserved_46_63:18;
+		uint64_t d0_mem0:1;
+		uint64_t d1_mem1:1;
+		uint64_t d2_mem2:1;
+		uint64_t d3_mem3:1;
+		uint64_t dr0_mem:1;
+		uint64_t d0_mem:1;
+		uint64_t d1_mem:1;
+		uint64_t d2_mem:1;
+		uint64_t d3_mem:1;
+		uint64_t dr1_mem:1;
+		uint64_t d0_pst:1;
+		uint64_t d1_pst:1;
+		uint64_t d2_pst:1;
+		uint64_t d3_pst:1;
+		uint64_t dr2_mem:1;
+		uint64_t n2p0_c:1;
+		uint64_t n2p0_o:1;
+		uint64_t n2p1_c:1;
+		uint64_t n2p1_o:1;
+		uint64_t cpl_p0:1;
+		uint64_t cpl_p1:1;
+		uint64_t p2n1_po:1;
+		uint64_t p2n1_no:1;
+		uint64_t p2n1_co:1;
+		uint64_t p2n0_po:1;
+		uint64_t p2n0_no:1;
+		uint64_t p2n0_co:1;
+		uint64_t p2n0_c0:1;
+		uint64_t p2n0_c1:1;
+		uint64_t p2n0_n:1;
+		uint64_t p2n0_p0:1;
+		uint64_t p2n0_p1:1;
+		uint64_t p2n1_c0:1;
+		uint64_t p2n1_c1:1;
+		uint64_t p2n1_n:1;
+		uint64_t p2n1_p0:1;
+		uint64_t p2n1_p1:1;
+		uint64_t csm0:1;
+		uint64_t csm1:1;
+		uint64_t dif0:1;
+		uint64_t dif1:1;
+		uint64_t dif2:1;
+		uint64_t dif3:1;
+		uint64_t dr3_mem:1;
+		uint64_t msi:1;
+		uint64_t ncb_cmd:1;
+	} cn52xxp1;
+	struct cvmx_npei_bist_status_cn56xx {
+		uint64_t pkt_rdf:1;
+		uint64_t reserved_60_62:3;
+		uint64_t pcr_gim:1;
+		uint64_t pkt_pif:1;
+		uint64_t pcsr_int:1;
+		uint64_t pcsr_im:1;
+		uint64_t pcsr_cnt:1;
+		uint64_t pcsr_id:1;
+		uint64_t pcsr_sl:1;
+		uint64_t pkt_imem:1;
+		uint64_t pkt_pfm:1;
+		uint64_t pkt_pof:1;
+		uint64_t reserved_48_49:2;
+		uint64_t pkt_pop0:1;
+		uint64_t pkt_pop1:1;
+		uint64_t d0_mem:1;
+		uint64_t d1_mem:1;
+		uint64_t d2_mem:1;
+		uint64_t d3_mem:1;
+		uint64_t d4_mem:1;
+		uint64_t ds_mem:1;
+		uint64_t reserved_36_39:4;
+		uint64_t d0_pst:1;
+		uint64_t d1_pst:1;
+		uint64_t d2_pst:1;
+		uint64_t d3_pst:1;
+		uint64_t d4_pst:1;
+		uint64_t n2p0_c:1;
+		uint64_t n2p0_o:1;
+		uint64_t n2p1_c:1;
+		uint64_t n2p1_o:1;
+		uint64_t cpl_p0:1;
+		uint64_t cpl_p1:1;
+		uint64_t p2n1_po:1;
+		uint64_t p2n1_no:1;
+		uint64_t p2n1_co:1;
+		uint64_t p2n0_po:1;
+		uint64_t p2n0_no:1;
+		uint64_t p2n0_co:1;
+		uint64_t p2n0_c0:1;
+		uint64_t p2n0_c1:1;
+		uint64_t p2n0_n:1;
+		uint64_t p2n0_p0:1;
+		uint64_t p2n0_p1:1;
+		uint64_t p2n1_c0:1;
+		uint64_t p2n1_c1:1;
+		uint64_t p2n1_n:1;
+		uint64_t p2n1_p0:1;
+		uint64_t p2n1_p1:1;
+		uint64_t csm0:1;
+		uint64_t csm1:1;
+		uint64_t dif0:1;
+		uint64_t dif1:1;
+		uint64_t dif2:1;
+		uint64_t dif3:1;
+		uint64_t dif4:1;
+		uint64_t msi:1;
+		uint64_t ncb_cmd:1;
+	} cn56xx;
+	struct cvmx_npei_bist_status_cn56xxp1 {
+		uint64_t reserved_58_63:6;
+		uint64_t pcsr_int:1;
+		uint64_t pcsr_im:1;
+		uint64_t pcsr_cnt:1;
+		uint64_t pcsr_id:1;
+		uint64_t pcsr_sl:1;
+		uint64_t pkt_pout:1;
+		uint64_t pkt_imem:1;
+		uint64_t pkt_cntm:1;
+		uint64_t pkt_ind:1;
+		uint64_t pkt_slm:1;
+		uint64_t pkt_odf:1;
+		uint64_t pkt_oif:1;
+		uint64_t pkt_out:1;
+		uint64_t pkt_i0:1;
+		uint64_t pkt_i1:1;
+		uint64_t pkt_s0:1;
+		uint64_t pkt_s1:1;
+		uint64_t d0_mem:1;
+		uint64_t d1_mem:1;
+		uint64_t d2_mem:1;
+		uint64_t d3_mem:1;
+		uint64_t d4_mem:1;
+		uint64_t d0_pst:1;
+		uint64_t d1_pst:1;
+		uint64_t d2_pst:1;
+		uint64_t d3_pst:1;
+		uint64_t d4_pst:1;
+		uint64_t n2p0_c:1;
+		uint64_t n2p0_o:1;
+		uint64_t n2p1_c:1;
+		uint64_t n2p1_o:1;
+		uint64_t cpl_p0:1;
+		uint64_t cpl_p1:1;
+		uint64_t p2n1_po:1;
+		uint64_t p2n1_no:1;
+		uint64_t p2n1_co:1;
+		uint64_t p2n0_po:1;
+		uint64_t p2n0_no:1;
+		uint64_t p2n0_co:1;
+		uint64_t p2n0_c0:1;
+		uint64_t p2n0_c1:1;
+		uint64_t p2n0_n:1;
+		uint64_t p2n0_p0:1;
+		uint64_t p2n0_p1:1;
+		uint64_t p2n1_c0:1;
+		uint64_t p2n1_c1:1;
+		uint64_t p2n1_n:1;
+		uint64_t p2n1_p0:1;
+		uint64_t p2n1_p1:1;
+		uint64_t csm0:1;
+		uint64_t csm1:1;
+		uint64_t dif0:1;
+		uint64_t dif1:1;
+		uint64_t dif2:1;
+		uint64_t dif3:1;
+		uint64_t dif4:1;
+		uint64_t msi:1;
+		uint64_t ncb_cmd:1;
+	} cn56xxp1;
+};
+
+union cvmx_npei_bist_status2 {
+	uint64_t u64;
+	struct cvmx_npei_bist_status2_s {
+		uint64_t reserved_5_63:59;
+		uint64_t psc_p0:1;
+		uint64_t psc_p1:1;
+		uint64_t pkt_gd:1;
+		uint64_t pkt_gl:1;
+		uint64_t pkt_blk:1;
+	} s;
+	struct cvmx_npei_bist_status2_s cn52xx;
+	struct cvmx_npei_bist_status2_s cn56xx;
+};
+
+union cvmx_npei_ctl_port0 {
+	uint64_t u64;
+	struct cvmx_npei_ctl_port0_s {
+		uint64_t reserved_21_63:43;
+		uint64_t waitl_com:1;
+		uint64_t intd:1;
+		uint64_t intc:1;
+		uint64_t intb:1;
+		uint64_t inta:1;
+		uint64_t intd_map:2;
+		uint64_t intc_map:2;
+		uint64_t intb_map:2;
+		uint64_t inta_map:2;
+		uint64_t ctlp_ro:1;
+		uint64_t reserved_6_6:1;
+		uint64_t ptlp_ro:1;
+		uint64_t bar2_enb:1;
+		uint64_t bar2_esx:2;
+		uint64_t bar2_cax:1;
+		uint64_t wait_com:1;
+	} s;
+	struct cvmx_npei_ctl_port0_s cn52xx;
+	struct cvmx_npei_ctl_port0_s cn52xxp1;
+	struct cvmx_npei_ctl_port0_s cn56xx;
+	struct cvmx_npei_ctl_port0_s cn56xxp1;
+};
+
+union cvmx_npei_ctl_port1 {
+	uint64_t u64;
+	struct cvmx_npei_ctl_port1_s {
+		uint64_t reserved_21_63:43;
+		uint64_t waitl_com:1;
+		uint64_t intd:1;
+		uint64_t intc:1;
+		uint64_t intb:1;
+		uint64_t inta:1;
+		uint64_t intd_map:2;
+		uint64_t intc_map:2;
+		uint64_t intb_map:2;
+		uint64_t inta_map:2;
+		uint64_t ctlp_ro:1;
+		uint64_t reserved_6_6:1;
+		uint64_t ptlp_ro:1;
+		uint64_t bar2_enb:1;
+		uint64_t bar2_esx:2;
+		uint64_t bar2_cax:1;
+		uint64_t wait_com:1;
+	} s;
+	struct cvmx_npei_ctl_port1_s cn52xx;
+	struct cvmx_npei_ctl_port1_s cn52xxp1;
+	struct cvmx_npei_ctl_port1_s cn56xx;
+	struct cvmx_npei_ctl_port1_s cn56xxp1;
+};
+
+union cvmx_npei_ctl_status {
+	uint64_t u64;
+	struct cvmx_npei_ctl_status_s {
+		uint64_t reserved_44_63:20;
+		uint64_t p1_ntags:6;
+		uint64_t p0_ntags:6;
+		uint64_t cfg_rtry:16;
+		uint64_t ring_en:1;
+		uint64_t lnk_rst:1;
+		uint64_t arb:1;
+		uint64_t pkt_bp:4;
+		uint64_t host_mode:1;
+		uint64_t chip_rev:8;
+	} s;
+	struct cvmx_npei_ctl_status_s cn52xx;
+	struct cvmx_npei_ctl_status_cn52xxp1 {
+		uint64_t reserved_44_63:20;
+		uint64_t p1_ntags:6;
+		uint64_t p0_ntags:6;
+		uint64_t cfg_rtry:16;
+		uint64_t reserved_15_15:1;
+		uint64_t lnk_rst:1;
+		uint64_t arb:1;
+		uint64_t reserved_9_12:4;
+		uint64_t host_mode:1;
+		uint64_t chip_rev:8;
+	} cn52xxp1;
+	struct cvmx_npei_ctl_status_s cn56xx;
+	struct cvmx_npei_ctl_status_cn56xxp1 {
+		uint64_t reserved_16_63:48;
+		uint64_t ring_en:1;
+		uint64_t lnk_rst:1;
+		uint64_t arb:1;
+		uint64_t pkt_bp:4;
+		uint64_t host_mode:1;
+		uint64_t chip_rev:8;
+	} cn56xxp1;
+};
+
+union cvmx_npei_ctl_status2 {
+	uint64_t u64;
+	struct cvmx_npei_ctl_status2_s {
+		uint64_t reserved_16_63:48;
+		uint64_t mps:1;
+		uint64_t mrrs:3;
+		uint64_t c1_w_flt:1;
+		uint64_t c0_w_flt:1;
+		uint64_t c1_b1_s:3;
+		uint64_t c0_b1_s:3;
+		uint64_t c1_wi_d:1;
+		uint64_t c1_b0_d:1;
+		uint64_t c0_wi_d:1;
+		uint64_t c0_b0_d:1;
+	} s;
+	struct cvmx_npei_ctl_status2_s cn52xx;
+	struct cvmx_npei_ctl_status2_s cn52xxp1;
+	struct cvmx_npei_ctl_status2_s cn56xx;
+	struct cvmx_npei_ctl_status2_s cn56xxp1;
+};
+
+union cvmx_npei_data_out_cnt {
+	uint64_t u64;
+	struct cvmx_npei_data_out_cnt_s {
+		uint64_t reserved_44_63:20;
+		uint64_t p1_ucnt:16;
+		uint64_t p1_fcnt:6;
+		uint64_t p0_ucnt:16;
+		uint64_t p0_fcnt:6;
+	} s;
+	struct cvmx_npei_data_out_cnt_s cn52xx;
+	struct cvmx_npei_data_out_cnt_s cn52xxp1;
+	struct cvmx_npei_data_out_cnt_s cn56xx;
+	struct cvmx_npei_data_out_cnt_s cn56xxp1;
+};
+
+union cvmx_npei_dbg_data {
+	uint64_t u64;
+	struct cvmx_npei_dbg_data_s {
+		uint64_t reserved_28_63:36;
+		uint64_t qlm0_rev_lanes:1;
+		uint64_t reserved_25_26:2;
+		uint64_t qlm1_spd:2;
+		uint64_t c_mul:5;
+		uint64_t dsel_ext:1;
+		uint64_t data:17;
+	} s;
+	struct cvmx_npei_dbg_data_cn52xx {
+		uint64_t reserved_29_63:35;
+		uint64_t qlm0_link_width:1;
+		uint64_t qlm0_rev_lanes:1;
+		uint64_t qlm1_mode:2;
+		uint64_t qlm1_spd:2;
+		uint64_t c_mul:5;
+		uint64_t dsel_ext:1;
+		uint64_t data:17;
+	} cn52xx;
+	struct cvmx_npei_dbg_data_cn52xx cn52xxp1;
+	struct cvmx_npei_dbg_data_cn56xx {
+		uint64_t reserved_29_63:35;
+		uint64_t qlm2_rev_lanes:1;
+		uint64_t qlm0_rev_lanes:1;
+		uint64_t qlm3_spd:2;
+		uint64_t qlm1_spd:2;
+		uint64_t c_mul:5;
+		uint64_t dsel_ext:1;
+		uint64_t data:17;
+	} cn56xx;
+	struct cvmx_npei_dbg_data_cn56xx cn56xxp1;
+};
+
+union cvmx_npei_dbg_select {
+	uint64_t u64;
+	struct cvmx_npei_dbg_select_s {
+		uint64_t reserved_16_63:48;
+		uint64_t dbg_sel:16;
+	} s;
+	struct cvmx_npei_dbg_select_s cn52xx;
+	struct cvmx_npei_dbg_select_s cn52xxp1;
+	struct cvmx_npei_dbg_select_s cn56xx;
+	struct cvmx_npei_dbg_select_s cn56xxp1;
+};
+
+union cvmx_npei_dmax_counts {
+	uint64_t u64;
+	struct cvmx_npei_dmax_counts_s {
+		uint64_t reserved_39_63:25;
+		uint64_t fcnt:7;
+		uint64_t dbell:32;
+	} s;
+	struct cvmx_npei_dmax_counts_s cn52xx;
+	struct cvmx_npei_dmax_counts_s cn52xxp1;
+	struct cvmx_npei_dmax_counts_s cn56xx;
+	struct cvmx_npei_dmax_counts_s cn56xxp1;
+};
+
+union cvmx_npei_dmax_dbell {
+	uint32_t u32;
+	struct cvmx_npei_dmax_dbell_s {
+		uint32_t reserved_16_31:16;
+		uint32_t dbell:16;
+	} s;
+	struct cvmx_npei_dmax_dbell_s cn52xx;
+	struct cvmx_npei_dmax_dbell_s cn52xxp1;
+	struct cvmx_npei_dmax_dbell_s cn56xx;
+	struct cvmx_npei_dmax_dbell_s cn56xxp1;
+};
+
+union cvmx_npei_dmax_ibuff_saddr {
+	uint64_t u64;
+	struct cvmx_npei_dmax_ibuff_saddr_s {
+		uint64_t reserved_37_63:27;
+		uint64_t idle:1;
+		uint64_t saddr:29;
+		uint64_t reserved_0_6:7;
+	} s;
+	struct cvmx_npei_dmax_ibuff_saddr_cn52xx {
+		uint64_t reserved_36_63:28;
+		uint64_t saddr:29;
+		uint64_t reserved_0_6:7;
+	} cn52xx;
+	struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn52xxp1;
+	struct cvmx_npei_dmax_ibuff_saddr_s cn56xx;
+	struct cvmx_npei_dmax_ibuff_saddr_cn52xx cn56xxp1;
+};
+
+union cvmx_npei_dmax_naddr {
+	uint64_t u64;
+	struct cvmx_npei_dmax_naddr_s {
+		uint64_t reserved_36_63:28;
+		uint64_t addr:36;
+	} s;
+	struct cvmx_npei_dmax_naddr_s cn52xx;
+	struct cvmx_npei_dmax_naddr_s cn52xxp1;
+	struct cvmx_npei_dmax_naddr_s cn56xx;
+	struct cvmx_npei_dmax_naddr_s cn56xxp1;
+};
+
+union cvmx_npei_dma0_int_level {
+	uint64_t u64;
+	struct cvmx_npei_dma0_int_level_s {
+		uint64_t time:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_npei_dma0_int_level_s cn52xx;
+	struct cvmx_npei_dma0_int_level_s cn52xxp1;
+	struct cvmx_npei_dma0_int_level_s cn56xx;
+	struct cvmx_npei_dma0_int_level_s cn56xxp1;
+};
+
+union cvmx_npei_dma1_int_level {
+	uint64_t u64;
+	struct cvmx_npei_dma1_int_level_s {
+		uint64_t time:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_npei_dma1_int_level_s cn52xx;
+	struct cvmx_npei_dma1_int_level_s cn52xxp1;
+	struct cvmx_npei_dma1_int_level_s cn56xx;
+	struct cvmx_npei_dma1_int_level_s cn56xxp1;
+};
+
+union cvmx_npei_dma_cnts {
+	uint64_t u64;
+	struct cvmx_npei_dma_cnts_s {
+		uint64_t dma1:32;
+		uint64_t dma0:32;
+	} s;
+	struct cvmx_npei_dma_cnts_s cn52xx;
+	struct cvmx_npei_dma_cnts_s cn52xxp1;
+	struct cvmx_npei_dma_cnts_s cn56xx;
+	struct cvmx_npei_dma_cnts_s cn56xxp1;
+};
+
+union cvmx_npei_dma_control {
+	uint64_t u64;
+	struct cvmx_npei_dma_control_s {
+		uint64_t reserved_39_63:25;
+		uint64_t dma4_enb:1;
+		uint64_t dma3_enb:1;
+		uint64_t dma2_enb:1;
+		uint64_t dma1_enb:1;
+		uint64_t dma0_enb:1;
+		uint64_t b0_lend:1;
+		uint64_t dwb_denb:1;
+		uint64_t dwb_ichk:9;
+		uint64_t fpa_que:3;
+		uint64_t o_add1:1;
+		uint64_t o_ro:1;
+		uint64_t o_ns:1;
+		uint64_t o_es:2;
+		uint64_t o_mode:1;
+		uint64_t csize:14;
+	} s;
+	struct cvmx_npei_dma_control_s cn52xx;
+	struct cvmx_npei_dma_control_cn52xxp1 {
+		uint64_t reserved_38_63:26;
+		uint64_t dma3_enb:1;
+		uint64_t dma2_enb:1;
+		uint64_t dma1_enb:1;
+		uint64_t dma0_enb:1;
+		uint64_t b0_lend:1;
+		uint64_t dwb_denb:1;
+		uint64_t dwb_ichk:9;
+		uint64_t fpa_que:3;
+		uint64_t o_add1:1;
+		uint64_t o_ro:1;
+		uint64_t o_ns:1;
+		uint64_t o_es:2;
+		uint64_t o_mode:1;
+		uint64_t csize:14;
+	} cn52xxp1;
+	struct cvmx_npei_dma_control_s cn56xx;
+	struct cvmx_npei_dma_control_s cn56xxp1;
+};
+
+union cvmx_npei_int_a_enb {
+	uint64_t u64;
+	struct cvmx_npei_int_a_enb_s {
+		uint64_t reserved_10_63:54;
+		uint64_t pout_err:1;
+		uint64_t pin_bp:1;
+		uint64_t p1_rdlk:1;
+		uint64_t p0_rdlk:1;
+		uint64_t pgl_err:1;
+		uint64_t pdi_err:1;
+		uint64_t pop_err:1;
+		uint64_t pins_err:1;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} s;
+	struct cvmx_npei_int_a_enb_cn52xx {
+		uint64_t reserved_8_63:56;
+		uint64_t p1_rdlk:1;
+		uint64_t p0_rdlk:1;
+		uint64_t pgl_err:1;
+		uint64_t pdi_err:1;
+		uint64_t pop_err:1;
+		uint64_t pins_err:1;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} cn52xx;
+	struct cvmx_npei_int_a_enb_cn52xxp1 {
+		uint64_t reserved_2_63:62;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} cn52xxp1;
+	struct cvmx_npei_int_a_enb_s cn56xx;
+};
+
+union cvmx_npei_int_a_enb2 {
+	uint64_t u64;
+	struct cvmx_npei_int_a_enb2_s {
+		uint64_t reserved_10_63:54;
+		uint64_t pout_err:1;
+		uint64_t pin_bp:1;
+		uint64_t p1_rdlk:1;
+		uint64_t p0_rdlk:1;
+		uint64_t pgl_err:1;
+		uint64_t pdi_err:1;
+		uint64_t pop_err:1;
+		uint64_t pins_err:1;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} s;
+	struct cvmx_npei_int_a_enb2_cn52xx {
+		uint64_t reserved_8_63:56;
+		uint64_t p1_rdlk:1;
+		uint64_t p0_rdlk:1;
+		uint64_t pgl_err:1;
+		uint64_t pdi_err:1;
+		uint64_t pop_err:1;
+		uint64_t pins_err:1;
+		uint64_t reserved_0_1:2;
+	} cn52xx;
+	struct cvmx_npei_int_a_enb2_cn52xxp1 {
+		uint64_t reserved_2_63:62;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} cn52xxp1;
+	struct cvmx_npei_int_a_enb2_s cn56xx;
+};
+
+union cvmx_npei_int_a_sum {
+	uint64_t u64;
+	struct cvmx_npei_int_a_sum_s {
+		uint64_t reserved_10_63:54;
+		uint64_t pout_err:1;
+		uint64_t pin_bp:1;
+		uint64_t p1_rdlk:1;
+		uint64_t p0_rdlk:1;
+		uint64_t pgl_err:1;
+		uint64_t pdi_err:1;
+		uint64_t pop_err:1;
+		uint64_t pins_err:1;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} s;
+	struct cvmx_npei_int_a_sum_cn52xx {
+		uint64_t reserved_8_63:56;
+		uint64_t p1_rdlk:1;
+		uint64_t p0_rdlk:1;
+		uint64_t pgl_err:1;
+		uint64_t pdi_err:1;
+		uint64_t pop_err:1;
+		uint64_t pins_err:1;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} cn52xx;
+	struct cvmx_npei_int_a_sum_cn52xxp1 {
+		uint64_t reserved_2_63:62;
+		uint64_t dma1_cpl:1;
+		uint64_t dma0_cpl:1;
+	} cn52xxp1;
+	struct cvmx_npei_int_a_sum_s cn56xx;
+};
+
+union cvmx_npei_int_enb {
+	uint64_t u64;
+	struct cvmx_npei_int_enb_s {
+		uint64_t mio_inta:1;
+		uint64_t reserved_62_62:1;
+		uint64_t int_a:1;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t crs1_dr:1;
+		uint64_t c1_se:1;
+		uint64_t crs1_er:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t crs0_dr:1;
+		uint64_t c0_se:1;
+		uint64_t crs0_er:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t dma4dbo:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} s;
+	struct cvmx_npei_int_enb_s cn52xx;
+	struct cvmx_npei_int_enb_cn52xxp1 {
+		uint64_t mio_inta:1;
+		uint64_t reserved_62_62:1;
+		uint64_t int_a:1;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t crs1_dr:1;
+		uint64_t c1_se:1;
+		uint64_t crs1_er:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t crs0_dr:1;
+		uint64_t c0_se:1;
+		uint64_t crs0_er:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t reserved_8_8:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn52xxp1;
+	struct cvmx_npei_int_enb_s cn56xx;
+	struct cvmx_npei_int_enb_cn56xxp1 {
+		uint64_t mio_inta:1;
+		uint64_t reserved_61_62:2;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t reserved_29_29:1;
+		uint64_t c1_se:1;
+		uint64_t reserved_27_27:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t reserved_22_22:1;
+		uint64_t c0_se:1;
+		uint64_t reserved_20_20:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t dma4dbo:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn56xxp1;
+};
+
+union cvmx_npei_int_enb2 {
+	uint64_t u64;
+	struct cvmx_npei_int_enb2_s {
+		uint64_t reserved_62_63:2;
+		uint64_t int_a:1;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t crs1_dr:1;
+		uint64_t c1_se:1;
+		uint64_t crs1_er:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t crs0_dr:1;
+		uint64_t c0_se:1;
+		uint64_t crs0_er:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t dma4dbo:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} s;
+	struct cvmx_npei_int_enb2_s cn52xx;
+	struct cvmx_npei_int_enb2_cn52xxp1 {
+		uint64_t reserved_62_63:2;
+		uint64_t int_a:1;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t crs1_dr:1;
+		uint64_t c1_se:1;
+		uint64_t crs1_er:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t crs0_dr:1;
+		uint64_t c0_se:1;
+		uint64_t crs0_er:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t reserved_8_8:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn52xxp1;
+	struct cvmx_npei_int_enb2_s cn56xx;
+	struct cvmx_npei_int_enb2_cn56xxp1 {
+		uint64_t reserved_61_63:3;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t reserved_29_29:1;
+		uint64_t c1_se:1;
+		uint64_t reserved_27_27:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t reserved_22_22:1;
+		uint64_t c0_se:1;
+		uint64_t reserved_20_20:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t dma4dbo:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn56xxp1;
+};
+
+union cvmx_npei_int_info {
+	uint64_t u64;
+	struct cvmx_npei_int_info_s {
+		uint64_t reserved_12_63:52;
+		uint64_t pidbof:6;
+		uint64_t psldbof:6;
+	} s;
+	struct cvmx_npei_int_info_s cn52xx;
+	struct cvmx_npei_int_info_s cn56xx;
+	struct cvmx_npei_int_info_s cn56xxp1;
+};
+
+union cvmx_npei_int_sum {
+	uint64_t u64;
+	struct cvmx_npei_int_sum_s {
+		uint64_t mio_inta:1;
+		uint64_t reserved_62_62:1;
+		uint64_t int_a:1;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t crs1_dr:1;
+		uint64_t c1_se:1;
+		uint64_t crs1_er:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t crs0_dr:1;
+		uint64_t c0_se:1;
+		uint64_t crs0_er:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t dma4dbo:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} s;
+	struct cvmx_npei_int_sum_s cn52xx;
+	struct cvmx_npei_int_sum_cn52xxp1 {
+		uint64_t mio_inta:1;
+		uint64_t reserved_62_62:1;
+		uint64_t int_a:1;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t crs1_dr:1;
+		uint64_t c1_se:1;
+		uint64_t crs1_er:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t crs0_dr:1;
+		uint64_t c0_se:1;
+		uint64_t crs0_er:1;
+		uint64_t c0_aeri:1;
+		uint64_t reserved_15_18:4;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t reserved_8_8:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn52xxp1;
+	struct cvmx_npei_int_sum_s cn56xx;
+	struct cvmx_npei_int_sum_cn56xxp1 {
+		uint64_t mio_inta:1;
+		uint64_t reserved_61_62:2;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t reserved_29_29:1;
+		uint64_t c1_se:1;
+		uint64_t reserved_27_27:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t reserved_22_22:1;
+		uint64_t c0_se:1;
+		uint64_t reserved_20_20:1;
+		uint64_t c0_aeri:1;
+		uint64_t ptime:1;
+		uint64_t pcnt:1;
+		uint64_t pidbof:1;
+		uint64_t psldbof:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t dma4dbo:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn56xxp1;
+};
+
+union cvmx_npei_int_sum2 {
+	uint64_t u64;
+	struct cvmx_npei_int_sum2_s {
+		uint64_t mio_inta:1;
+		uint64_t reserved_62_62:1;
+		uint64_t int_a:1;
+		uint64_t c1_ldwn:1;
+		uint64_t c0_ldwn:1;
+		uint64_t c1_exc:1;
+		uint64_t c0_exc:1;
+		uint64_t c1_up_wf:1;
+		uint64_t c0_up_wf:1;
+		uint64_t c1_un_wf:1;
+		uint64_t c0_un_wf:1;
+		uint64_t c1_un_bx:1;
+		uint64_t c1_un_wi:1;
+		uint64_t c1_un_b2:1;
+		uint64_t c1_un_b1:1;
+		uint64_t c1_un_b0:1;
+		uint64_t c1_up_bx:1;
+		uint64_t c1_up_wi:1;
+		uint64_t c1_up_b2:1;
+		uint64_t c1_up_b1:1;
+		uint64_t c1_up_b0:1;
+		uint64_t c0_un_bx:1;
+		uint64_t c0_un_wi:1;
+		uint64_t c0_un_b2:1;
+		uint64_t c0_un_b1:1;
+		uint64_t c0_un_b0:1;
+		uint64_t c0_up_bx:1;
+		uint64_t c0_up_wi:1;
+		uint64_t c0_up_b2:1;
+		uint64_t c0_up_b1:1;
+		uint64_t c0_up_b0:1;
+		uint64_t c1_hpint:1;
+		uint64_t c1_pmei:1;
+		uint64_t c1_wake:1;
+		uint64_t crs1_dr:1;
+		uint64_t c1_se:1;
+		uint64_t crs1_er:1;
+		uint64_t c1_aeri:1;
+		uint64_t c0_hpint:1;
+		uint64_t c0_pmei:1;
+		uint64_t c0_wake:1;
+		uint64_t crs0_dr:1;
+		uint64_t c0_se:1;
+		uint64_t crs0_er:1;
+		uint64_t c0_aeri:1;
+		uint64_t reserved_15_18:4;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t dma1fi:1;
+		uint64_t dma0fi:1;
+		uint64_t reserved_8_8:1;
+		uint64_t dma3dbo:1;
+		uint64_t dma2dbo:1;
+		uint64_t dma1dbo:1;
+		uint64_t dma0dbo:1;
+		uint64_t iob2big:1;
+		uint64_t bar0_to:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} s;
+	struct cvmx_npei_int_sum2_s cn52xx;
+	struct cvmx_npei_int_sum2_s cn52xxp1;
+	struct cvmx_npei_int_sum2_s cn56xx;
+};
+
+union cvmx_npei_last_win_rdata0 {
+	uint64_t u64;
+	struct cvmx_npei_last_win_rdata0_s {
+		uint64_t data:64;
+	} s;
+	struct cvmx_npei_last_win_rdata0_s cn52xx;
+	struct cvmx_npei_last_win_rdata0_s cn52xxp1;
+	struct cvmx_npei_last_win_rdata0_s cn56xx;
+	struct cvmx_npei_last_win_rdata0_s cn56xxp1;
+};
+
+union cvmx_npei_last_win_rdata1 {
+	uint64_t u64;
+	struct cvmx_npei_last_win_rdata1_s {
+		uint64_t data:64;
+	} s;
+	struct cvmx_npei_last_win_rdata1_s cn52xx;
+	struct cvmx_npei_last_win_rdata1_s cn52xxp1;
+	struct cvmx_npei_last_win_rdata1_s cn56xx;
+	struct cvmx_npei_last_win_rdata1_s cn56xxp1;
+};
+
+union cvmx_npei_mem_access_ctl {
+	uint64_t u64;
+	struct cvmx_npei_mem_access_ctl_s {
+		uint64_t reserved_14_63:50;
+		uint64_t max_word:4;
+		uint64_t timer:10;
+	} s;
+	struct cvmx_npei_mem_access_ctl_s cn52xx;
+	struct cvmx_npei_mem_access_ctl_s cn52xxp1;
+	struct cvmx_npei_mem_access_ctl_s cn56xx;
+	struct cvmx_npei_mem_access_ctl_s cn56xxp1;
+};
+
+union cvmx_npei_mem_access_subidx {
+	uint64_t u64;
+	struct cvmx_npei_mem_access_subidx_s {
+		uint64_t reserved_42_63:22;
+		uint64_t zero:1;
+		uint64_t port:2;
+		uint64_t nmerge:1;
+		uint64_t esr:2;
+		uint64_t esw:2;
+		uint64_t nsr:1;
+		uint64_t nsw:1;
+		uint64_t ror:1;
+		uint64_t row:1;
+		uint64_t ba:30;
+	} s;
+	struct cvmx_npei_mem_access_subidx_s cn52xx;
+	struct cvmx_npei_mem_access_subidx_s cn52xxp1;
+	struct cvmx_npei_mem_access_subidx_s cn56xx;
+	struct cvmx_npei_mem_access_subidx_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb0 {
+	uint64_t u64;
+	struct cvmx_npei_msi_enb0_s {
+		uint64_t enb:64;
+	} s;
+	struct cvmx_npei_msi_enb0_s cn52xx;
+	struct cvmx_npei_msi_enb0_s cn52xxp1;
+	struct cvmx_npei_msi_enb0_s cn56xx;
+	struct cvmx_npei_msi_enb0_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb1 {
+	uint64_t u64;
+	struct cvmx_npei_msi_enb1_s {
+		uint64_t enb:64;
+	} s;
+	struct cvmx_npei_msi_enb1_s cn52xx;
+	struct cvmx_npei_msi_enb1_s cn52xxp1;
+	struct cvmx_npei_msi_enb1_s cn56xx;
+	struct cvmx_npei_msi_enb1_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb2 {
+	uint64_t u64;
+	struct cvmx_npei_msi_enb2_s {
+		uint64_t enb:64;
+	} s;
+	struct cvmx_npei_msi_enb2_s cn52xx;
+	struct cvmx_npei_msi_enb2_s cn52xxp1;
+	struct cvmx_npei_msi_enb2_s cn56xx;
+	struct cvmx_npei_msi_enb2_s cn56xxp1;
+};
+
+union cvmx_npei_msi_enb3 {
+	uint64_t u64;
+	struct cvmx_npei_msi_enb3_s {
+		uint64_t enb:64;
+	} s;
+	struct cvmx_npei_msi_enb3_s cn52xx;
+	struct cvmx_npei_msi_enb3_s cn52xxp1;
+	struct cvmx_npei_msi_enb3_s cn56xx;
+	struct cvmx_npei_msi_enb3_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv0 {
+	uint64_t u64;
+	struct cvmx_npei_msi_rcv0_s {
+		uint64_t intr:64;
+	} s;
+	struct cvmx_npei_msi_rcv0_s cn52xx;
+	struct cvmx_npei_msi_rcv0_s cn52xxp1;
+	struct cvmx_npei_msi_rcv0_s cn56xx;
+	struct cvmx_npei_msi_rcv0_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv1 {
+	uint64_t u64;
+	struct cvmx_npei_msi_rcv1_s {
+		uint64_t intr:64;
+	} s;
+	struct cvmx_npei_msi_rcv1_s cn52xx;
+	struct cvmx_npei_msi_rcv1_s cn52xxp1;
+	struct cvmx_npei_msi_rcv1_s cn56xx;
+	struct cvmx_npei_msi_rcv1_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv2 {
+	uint64_t u64;
+	struct cvmx_npei_msi_rcv2_s {
+		uint64_t intr:64;
+	} s;
+	struct cvmx_npei_msi_rcv2_s cn52xx;
+	struct cvmx_npei_msi_rcv2_s cn52xxp1;
+	struct cvmx_npei_msi_rcv2_s cn56xx;
+	struct cvmx_npei_msi_rcv2_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rcv3 {
+	uint64_t u64;
+	struct cvmx_npei_msi_rcv3_s {
+		uint64_t intr:64;
+	} s;
+	struct cvmx_npei_msi_rcv3_s cn52xx;
+	struct cvmx_npei_msi_rcv3_s cn52xxp1;
+	struct cvmx_npei_msi_rcv3_s cn56xx;
+	struct cvmx_npei_msi_rcv3_s cn56xxp1;
+};
+
+union cvmx_npei_msi_rd_map {
+	uint64_t u64;
+	struct cvmx_npei_msi_rd_map_s {
+		uint64_t reserved_16_63:48;
+		uint64_t rd_int:8;
+		uint64_t msi_int:8;
+	} s;
+	struct cvmx_npei_msi_rd_map_s cn52xx;
+	struct cvmx_npei_msi_rd_map_s cn52xxp1;
+	struct cvmx_npei_msi_rd_map_s cn56xx;
+	struct cvmx_npei_msi_rd_map_s cn56xxp1;
+};
+
+union cvmx_npei_msi_w1c_enb0 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1c_enb0_s {
+		uint64_t clr:64;
+	} s;
+	struct cvmx_npei_msi_w1c_enb0_s cn52xx;
+	struct cvmx_npei_msi_w1c_enb0_s cn56xx;
+};
+
+union cvmx_npei_msi_w1c_enb1 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1c_enb1_s {
+		uint64_t clr:64;
+	} s;
+	struct cvmx_npei_msi_w1c_enb1_s cn52xx;
+	struct cvmx_npei_msi_w1c_enb1_s cn56xx;
+};
+
+union cvmx_npei_msi_w1c_enb2 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1c_enb2_s {
+		uint64_t clr:64;
+	} s;
+	struct cvmx_npei_msi_w1c_enb2_s cn52xx;
+	struct cvmx_npei_msi_w1c_enb2_s cn56xx;
+};
+
+union cvmx_npei_msi_w1c_enb3 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1c_enb3_s {
+		uint64_t clr:64;
+	} s;
+	struct cvmx_npei_msi_w1c_enb3_s cn52xx;
+	struct cvmx_npei_msi_w1c_enb3_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb0 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1s_enb0_s {
+		uint64_t set:64;
+	} s;
+	struct cvmx_npei_msi_w1s_enb0_s cn52xx;
+	struct cvmx_npei_msi_w1s_enb0_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb1 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1s_enb1_s {
+		uint64_t set:64;
+	} s;
+	struct cvmx_npei_msi_w1s_enb1_s cn52xx;
+	struct cvmx_npei_msi_w1s_enb1_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb2 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1s_enb2_s {
+		uint64_t set:64;
+	} s;
+	struct cvmx_npei_msi_w1s_enb2_s cn52xx;
+	struct cvmx_npei_msi_w1s_enb2_s cn56xx;
+};
+
+union cvmx_npei_msi_w1s_enb3 {
+	uint64_t u64;
+	struct cvmx_npei_msi_w1s_enb3_s {
+		uint64_t set:64;
+	} s;
+	struct cvmx_npei_msi_w1s_enb3_s cn52xx;
+	struct cvmx_npei_msi_w1s_enb3_s cn56xx;
+};
+
+union cvmx_npei_msi_wr_map {
+	uint64_t u64;
+	struct cvmx_npei_msi_wr_map_s {
+		uint64_t reserved_16_63:48;
+		uint64_t ciu_int:8;
+		uint64_t msi_int:8;
+	} s;
+	struct cvmx_npei_msi_wr_map_s cn52xx;
+	struct cvmx_npei_msi_wr_map_s cn52xxp1;
+	struct cvmx_npei_msi_wr_map_s cn56xx;
+	struct cvmx_npei_msi_wr_map_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_credit_cnt {
+	uint64_t u64;
+	struct cvmx_npei_pcie_credit_cnt_s {
+		uint64_t reserved_48_63:16;
+		uint64_t p1_ccnt:8;
+		uint64_t p1_ncnt:8;
+		uint64_t p1_pcnt:8;
+		uint64_t p0_ccnt:8;
+		uint64_t p0_ncnt:8;
+		uint64_t p0_pcnt:8;
+	} s;
+	struct cvmx_npei_pcie_credit_cnt_s cn52xx;
+	struct cvmx_npei_pcie_credit_cnt_s cn56xx;
+};
+
+union cvmx_npei_pcie_msi_rcv {
+	uint64_t u64;
+	struct cvmx_npei_pcie_msi_rcv_s {
+		uint64_t reserved_8_63:56;
+		uint64_t intr:8;
+	} s;
+	struct cvmx_npei_pcie_msi_rcv_s cn52xx;
+	struct cvmx_npei_pcie_msi_rcv_s cn52xxp1;
+	struct cvmx_npei_pcie_msi_rcv_s cn56xx;
+	struct cvmx_npei_pcie_msi_rcv_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_msi_rcv_b1 {
+	uint64_t u64;
+	struct cvmx_npei_pcie_msi_rcv_b1_s {
+		uint64_t reserved_16_63:48;
+		uint64_t intr:8;
+		uint64_t reserved_0_7:8;
+	} s;
+	struct cvmx_npei_pcie_msi_rcv_b1_s cn52xx;
+	struct cvmx_npei_pcie_msi_rcv_b1_s cn52xxp1;
+	struct cvmx_npei_pcie_msi_rcv_b1_s cn56xx;
+	struct cvmx_npei_pcie_msi_rcv_b1_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_msi_rcv_b2 {
+	uint64_t u64;
+	struct cvmx_npei_pcie_msi_rcv_b2_s {
+		uint64_t reserved_24_63:40;
+		uint64_t intr:8;
+		uint64_t reserved_0_15:16;
+	} s;
+	struct cvmx_npei_pcie_msi_rcv_b2_s cn52xx;
+	struct cvmx_npei_pcie_msi_rcv_b2_s cn52xxp1;
+	struct cvmx_npei_pcie_msi_rcv_b2_s cn56xx;
+	struct cvmx_npei_pcie_msi_rcv_b2_s cn56xxp1;
+};
+
+union cvmx_npei_pcie_msi_rcv_b3 {
+	uint64_t u64;
+	struct cvmx_npei_pcie_msi_rcv_b3_s {
+		uint64_t reserved_32_63:32;
+		uint64_t intr:8;
+		uint64_t reserved_0_23:24;
+	} s;
+	struct cvmx_npei_pcie_msi_rcv_b3_s cn52xx;
+	struct cvmx_npei_pcie_msi_rcv_b3_s cn52xxp1;
+	struct cvmx_npei_pcie_msi_rcv_b3_s cn56xx;
+	struct cvmx_npei_pcie_msi_rcv_b3_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_cnts {
+	uint64_t u64;
+	struct cvmx_npei_pktx_cnts_s {
+		uint64_t reserved_54_63:10;
+		uint64_t timer:22;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_npei_pktx_cnts_s cn52xx;
+	struct cvmx_npei_pktx_cnts_s cn56xx;
+	struct cvmx_npei_pktx_cnts_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_in_bp {
+	uint64_t u64;
+	struct cvmx_npei_pktx_in_bp_s {
+		uint64_t wmark:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_npei_pktx_in_bp_s cn52xx;
+	struct cvmx_npei_pktx_in_bp_s cn56xx;
+	struct cvmx_npei_pktx_in_bp_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_baddr {
+	uint64_t u64;
+	struct cvmx_npei_pktx_instr_baddr_s {
+		uint64_t addr:61;
+		uint64_t reserved_0_2:3;
+	} s;
+	struct cvmx_npei_pktx_instr_baddr_s cn52xx;
+	struct cvmx_npei_pktx_instr_baddr_s cn56xx;
+	struct cvmx_npei_pktx_instr_baddr_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_baoff_dbell {
+	uint64_t u64;
+	struct cvmx_npei_pktx_instr_baoff_dbell_s {
+		uint64_t aoff:32;
+		uint64_t dbell:32;
+	} s;
+	struct cvmx_npei_pktx_instr_baoff_dbell_s cn52xx;
+	struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xx;
+	struct cvmx_npei_pktx_instr_baoff_dbell_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_fifo_rsize {
+	uint64_t u64;
+	struct cvmx_npei_pktx_instr_fifo_rsize_s {
+		uint64_t max:9;
+		uint64_t rrp:9;
+		uint64_t wrp:9;
+		uint64_t fcnt:5;
+		uint64_t rsize:32;
+	} s;
+	struct cvmx_npei_pktx_instr_fifo_rsize_s cn52xx;
+	struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xx;
+	struct cvmx_npei_pktx_instr_fifo_rsize_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_instr_header {
+	uint64_t u64;
+	struct cvmx_npei_pktx_instr_header_s {
+		uint64_t reserved_44_63:20;
+		uint64_t pbp:1;
+		uint64_t rsv_f:5;
+		uint64_t rparmode:2;
+		uint64_t rsv_e:1;
+		uint64_t rskp_len:7;
+		uint64_t rsv_d:6;
+		uint64_t use_ihdr:1;
+		uint64_t rsv_c:5;
+		uint64_t par_mode:2;
+		uint64_t rsv_b:1;
+		uint64_t skp_len:7;
+		uint64_t rsv_a:6;
+	} s;
+	struct cvmx_npei_pktx_instr_header_s cn52xx;
+	struct cvmx_npei_pktx_instr_header_s cn56xx;
+	struct cvmx_npei_pktx_instr_header_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_slist_baddr {
+	uint64_t u64;
+	struct cvmx_npei_pktx_slist_baddr_s {
+		uint64_t addr:60;
+		uint64_t reserved_0_3:4;
+	} s;
+	struct cvmx_npei_pktx_slist_baddr_s cn52xx;
+	struct cvmx_npei_pktx_slist_baddr_s cn56xx;
+	struct cvmx_npei_pktx_slist_baddr_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_slist_baoff_dbell {
+	uint64_t u64;
+	struct cvmx_npei_pktx_slist_baoff_dbell_s {
+		uint64_t aoff:32;
+		uint64_t dbell:32;
+	} s;
+	struct cvmx_npei_pktx_slist_baoff_dbell_s cn52xx;
+	struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xx;
+	struct cvmx_npei_pktx_slist_baoff_dbell_s cn56xxp1;
+};
+
+union cvmx_npei_pktx_slist_fifo_rsize {
+	uint64_t u64;
+	struct cvmx_npei_pktx_slist_fifo_rsize_s {
+		uint64_t reserved_32_63:32;
+		uint64_t rsize:32;
+	} s;
+	struct cvmx_npei_pktx_slist_fifo_rsize_s cn52xx;
+	struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xx;
+	struct cvmx_npei_pktx_slist_fifo_rsize_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_cnt_int {
+	uint64_t u64;
+	struct cvmx_npei_pkt_cnt_int_s {
+		uint64_t reserved_32_63:32;
+		uint64_t port:32;
+	} s;
+	struct cvmx_npei_pkt_cnt_int_s cn52xx;
+	struct cvmx_npei_pkt_cnt_int_s cn56xx;
+	struct cvmx_npei_pkt_cnt_int_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_cnt_int_enb {
+	uint64_t u64;
+	struct cvmx_npei_pkt_cnt_int_enb_s {
+		uint64_t reserved_32_63:32;
+		uint64_t port:32;
+	} s;
+	struct cvmx_npei_pkt_cnt_int_enb_s cn52xx;
+	struct cvmx_npei_pkt_cnt_int_enb_s cn56xx;
+	struct cvmx_npei_pkt_cnt_int_enb_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_data_out_es {
+	uint64_t u64;
+	struct cvmx_npei_pkt_data_out_es_s {
+		uint64_t es:64;
+	} s;
+	struct cvmx_npei_pkt_data_out_es_s cn52xx;
+	struct cvmx_npei_pkt_data_out_es_s cn56xx;
+	struct cvmx_npei_pkt_data_out_es_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_data_out_ns {
+	uint64_t u64;
+	struct cvmx_npei_pkt_data_out_ns_s {
+		uint64_t reserved_32_63:32;
+		uint64_t nsr:32;
+	} s;
+	struct cvmx_npei_pkt_data_out_ns_s cn52xx;
+	struct cvmx_npei_pkt_data_out_ns_s cn56xx;
+	struct cvmx_npei_pkt_data_out_ns_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_data_out_ror {
+	uint64_t u64;
+	struct cvmx_npei_pkt_data_out_ror_s {
+		uint64_t reserved_32_63:32;
+		uint64_t ror:32;
+	} s;
+	struct cvmx_npei_pkt_data_out_ror_s cn52xx;
+	struct cvmx_npei_pkt_data_out_ror_s cn56xx;
+	struct cvmx_npei_pkt_data_out_ror_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_dpaddr {
+	uint64_t u64;
+	struct cvmx_npei_pkt_dpaddr_s {
+		uint64_t reserved_32_63:32;
+		uint64_t dptr:32;
+	} s;
+	struct cvmx_npei_pkt_dpaddr_s cn52xx;
+	struct cvmx_npei_pkt_dpaddr_s cn56xx;
+	struct cvmx_npei_pkt_dpaddr_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_in_bp {
+	uint64_t u64;
+	struct cvmx_npei_pkt_in_bp_s {
+		uint64_t reserved_32_63:32;
+		uint64_t bp:32;
+	} s;
+	struct cvmx_npei_pkt_in_bp_s cn56xx;
+};
+
+union cvmx_npei_pkt_in_donex_cnts {
+	uint64_t u64;
+	struct cvmx_npei_pkt_in_donex_cnts_s {
+		uint64_t reserved_32_63:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_npei_pkt_in_donex_cnts_s cn52xx;
+	struct cvmx_npei_pkt_in_donex_cnts_s cn56xx;
+	struct cvmx_npei_pkt_in_donex_cnts_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_in_instr_counts {
+	uint64_t u64;
+	struct cvmx_npei_pkt_in_instr_counts_s {
+		uint64_t wr_cnt:32;
+		uint64_t rd_cnt:32;
+	} s;
+	struct cvmx_npei_pkt_in_instr_counts_s cn52xx;
+	struct cvmx_npei_pkt_in_instr_counts_s cn56xx;
+};
+
+union cvmx_npei_pkt_in_pcie_port {
+	uint64_t u64;
+	struct cvmx_npei_pkt_in_pcie_port_s {
+		uint64_t pp:64;
+	} s;
+	struct cvmx_npei_pkt_in_pcie_port_s cn52xx;
+	struct cvmx_npei_pkt_in_pcie_port_s cn56xx;
+};
+
+union cvmx_npei_pkt_input_control {
+	uint64_t u64;
+	struct cvmx_npei_pkt_input_control_s {
+		uint64_t reserved_23_63:41;
+		uint64_t pkt_rr:1;
+		uint64_t pbp_dhi:13;
+		uint64_t d_nsr:1;
+		uint64_t d_esr:2;
+		uint64_t d_ror:1;
+		uint64_t use_csr:1;
+		uint64_t nsr:1;
+		uint64_t esr:2;
+		uint64_t ror:1;
+	} s;
+	struct cvmx_npei_pkt_input_control_s cn52xx;
+	struct cvmx_npei_pkt_input_control_s cn56xx;
+	struct cvmx_npei_pkt_input_control_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_instr_enb {
+	uint64_t u64;
+	struct cvmx_npei_pkt_instr_enb_s {
+		uint64_t reserved_32_63:32;
+		uint64_t enb:32;
+	} s;
+	struct cvmx_npei_pkt_instr_enb_s cn52xx;
+	struct cvmx_npei_pkt_instr_enb_s cn56xx;
+	struct cvmx_npei_pkt_instr_enb_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_instr_rd_size {
+	uint64_t u64;
+	struct cvmx_npei_pkt_instr_rd_size_s {
+		uint64_t rdsize:64;
+	} s;
+	struct cvmx_npei_pkt_instr_rd_size_s cn52xx;
+	struct cvmx_npei_pkt_instr_rd_size_s cn56xx;
+};
+
+union cvmx_npei_pkt_instr_size {
+	uint64_t u64;
+	struct cvmx_npei_pkt_instr_size_s {
+		uint64_t reserved_32_63:32;
+		uint64_t is_64b:32;
+	} s;
+	struct cvmx_npei_pkt_instr_size_s cn52xx;
+	struct cvmx_npei_pkt_instr_size_s cn56xx;
+	struct cvmx_npei_pkt_instr_size_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_int_levels {
+	uint64_t u64;
+	struct cvmx_npei_pkt_int_levels_s {
+		uint64_t reserved_54_63:10;
+		uint64_t time:22;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_npei_pkt_int_levels_s cn52xx;
+	struct cvmx_npei_pkt_int_levels_s cn56xx;
+	struct cvmx_npei_pkt_int_levels_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_iptr {
+	uint64_t u64;
+	struct cvmx_npei_pkt_iptr_s {
+		uint64_t reserved_32_63:32;
+		uint64_t iptr:32;
+	} s;
+	struct cvmx_npei_pkt_iptr_s cn52xx;
+	struct cvmx_npei_pkt_iptr_s cn56xx;
+	struct cvmx_npei_pkt_iptr_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_out_bmode {
+	uint64_t u64;
+	struct cvmx_npei_pkt_out_bmode_s {
+		uint64_t reserved_32_63:32;
+		uint64_t bmode:32;
+	} s;
+	struct cvmx_npei_pkt_out_bmode_s cn52xx;
+	struct cvmx_npei_pkt_out_bmode_s cn56xx;
+	struct cvmx_npei_pkt_out_bmode_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_out_enb {
+	uint64_t u64;
+	struct cvmx_npei_pkt_out_enb_s {
+		uint64_t reserved_32_63:32;
+		uint64_t enb:32;
+	} s;
+	struct cvmx_npei_pkt_out_enb_s cn52xx;
+	struct cvmx_npei_pkt_out_enb_s cn56xx;
+	struct cvmx_npei_pkt_out_enb_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_output_wmark {
+	uint64_t u64;
+	struct cvmx_npei_pkt_output_wmark_s {
+		uint64_t reserved_32_63:32;
+		uint64_t wmark:32;
+	} s;
+	struct cvmx_npei_pkt_output_wmark_s cn52xx;
+	struct cvmx_npei_pkt_output_wmark_s cn56xx;
+};
+
+union cvmx_npei_pkt_pcie_port {
+	uint64_t u64;
+	struct cvmx_npei_pkt_pcie_port_s {
+		uint64_t pp:64;
+	} s;
+	struct cvmx_npei_pkt_pcie_port_s cn52xx;
+	struct cvmx_npei_pkt_pcie_port_s cn56xx;
+	struct cvmx_npei_pkt_pcie_port_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_port_in_rst {
+	uint64_t u64;
+	struct cvmx_npei_pkt_port_in_rst_s {
+		uint64_t in_rst:32;
+		uint64_t out_rst:32;
+	} s;
+	struct cvmx_npei_pkt_port_in_rst_s cn52xx;
+	struct cvmx_npei_pkt_port_in_rst_s cn56xx;
+};
+
+union cvmx_npei_pkt_slist_es {
+	uint64_t u64;
+	struct cvmx_npei_pkt_slist_es_s {
+		uint64_t es:64;
+	} s;
+	struct cvmx_npei_pkt_slist_es_s cn52xx;
+	struct cvmx_npei_pkt_slist_es_s cn56xx;
+	struct cvmx_npei_pkt_slist_es_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_slist_id_size {
+	uint64_t u64;
+	struct cvmx_npei_pkt_slist_id_size_s {
+		uint64_t reserved_23_63:41;
+		uint64_t isize:7;
+		uint64_t bsize:16;
+	} s;
+	struct cvmx_npei_pkt_slist_id_size_s cn52xx;
+	struct cvmx_npei_pkt_slist_id_size_s cn56xx;
+	struct cvmx_npei_pkt_slist_id_size_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_slist_ns {
+	uint64_t u64;
+	struct cvmx_npei_pkt_slist_ns_s {
+		uint64_t reserved_32_63:32;
+		uint64_t nsr:32;
+	} s;
+	struct cvmx_npei_pkt_slist_ns_s cn52xx;
+	struct cvmx_npei_pkt_slist_ns_s cn56xx;
+	struct cvmx_npei_pkt_slist_ns_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_slist_ror {
+	uint64_t u64;
+	struct cvmx_npei_pkt_slist_ror_s {
+		uint64_t reserved_32_63:32;
+		uint64_t ror:32;
+	} s;
+	struct cvmx_npei_pkt_slist_ror_s cn52xx;
+	struct cvmx_npei_pkt_slist_ror_s cn56xx;
+	struct cvmx_npei_pkt_slist_ror_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_time_int {
+	uint64_t u64;
+	struct cvmx_npei_pkt_time_int_s {
+		uint64_t reserved_32_63:32;
+		uint64_t port:32;
+	} s;
+	struct cvmx_npei_pkt_time_int_s cn52xx;
+	struct cvmx_npei_pkt_time_int_s cn56xx;
+	struct cvmx_npei_pkt_time_int_s cn56xxp1;
+};
+
+union cvmx_npei_pkt_time_int_enb {
+	uint64_t u64;
+	struct cvmx_npei_pkt_time_int_enb_s {
+		uint64_t reserved_32_63:32;
+		uint64_t port:32;
+	} s;
+	struct cvmx_npei_pkt_time_int_enb_s cn52xx;
+	struct cvmx_npei_pkt_time_int_enb_s cn56xx;
+	struct cvmx_npei_pkt_time_int_enb_s cn56xxp1;
+};
+
+union cvmx_npei_rsl_int_blocks {
+	uint64_t u64;
+	struct cvmx_npei_rsl_int_blocks_s {
+		uint64_t reserved_31_63:33;
+		uint64_t iob:1;
+		uint64_t lmc1:1;
+		uint64_t agl:1;
+		uint64_t reserved_24_27:4;
+		uint64_t asxpcs1:1;
+		uint64_t asxpcs0:1;
+		uint64_t reserved_21_21:1;
+		uint64_t pip:1;
+		uint64_t reserved_18_19:2;
+		uint64_t lmc0:1;
+		uint64_t l2c:1;
+		uint64_t usb1:1;
+		uint64_t rad:1;
+		uint64_t usb:1;
+		uint64_t pow:1;
+		uint64_t tim:1;
+		uint64_t pko:1;
+		uint64_t ipd:1;
+		uint64_t reserved_8_8:1;
+		uint64_t zip:1;
+		uint64_t reserved_6_6:1;
+		uint64_t fpa:1;
+		uint64_t key:1;
+		uint64_t npei:1;
+		uint64_t gmx1:1;
+		uint64_t gmx0:1;
+		uint64_t mio:1;
+	} s;
+	struct cvmx_npei_rsl_int_blocks_s cn52xx;
+	struct cvmx_npei_rsl_int_blocks_s cn52xxp1;
+	struct cvmx_npei_rsl_int_blocks_cn56xx {
+		uint64_t reserved_31_63:33;
+		uint64_t iob:1;
+		uint64_t lmc1:1;
+		uint64_t agl:1;
+		uint64_t reserved_24_27:4;
+		uint64_t asxpcs1:1;
+		uint64_t asxpcs0:1;
+		uint64_t reserved_21_21:1;
+		uint64_t pip:1;
+		uint64_t reserved_18_19:2;
+		uint64_t lmc0:1;
+		uint64_t l2c:1;
+		uint64_t reserved_15_15:1;
+		uint64_t rad:1;
+		uint64_t usb:1;
+		uint64_t pow:1;
+		uint64_t tim:1;
+		uint64_t pko:1;
+		uint64_t ipd:1;
+		uint64_t reserved_8_8:1;
+		uint64_t zip:1;
+		uint64_t reserved_6_6:1;
+		uint64_t fpa:1;
+		uint64_t key:1;
+		uint64_t npei:1;
+		uint64_t gmx1:1;
+		uint64_t gmx0:1;
+		uint64_t mio:1;
+	} cn56xx;
+	struct cvmx_npei_rsl_int_blocks_cn56xx cn56xxp1;
+};
+
+union cvmx_npei_scratch_1 {
+	uint64_t u64;
+	struct cvmx_npei_scratch_1_s {
+		uint64_t data:64;
+	} s;
+	struct cvmx_npei_scratch_1_s cn52xx;
+	struct cvmx_npei_scratch_1_s cn52xxp1;
+	struct cvmx_npei_scratch_1_s cn56xx;
+	struct cvmx_npei_scratch_1_s cn56xxp1;
+};
+
+union cvmx_npei_state1 {
+	uint64_t u64;
+	struct cvmx_npei_state1_s {
+		uint64_t cpl1:12;
+		uint64_t cpl0:12;
+		uint64_t arb:1;
+		uint64_t csr:39;
+	} s;
+	struct cvmx_npei_state1_s cn52xx;
+	struct cvmx_npei_state1_s cn52xxp1;
+	struct cvmx_npei_state1_s cn56xx;
+	struct cvmx_npei_state1_s cn56xxp1;
+};
+
+union cvmx_npei_state2 {
+	uint64_t u64;
+	struct cvmx_npei_state2_s {
+		uint64_t reserved_48_63:16;
+		uint64_t npei:1;
+		uint64_t rac:1;
+		uint64_t csm1:15;
+		uint64_t csm0:15;
+		uint64_t nnp0:8;
+		uint64_t nnd:8;
+	} s;
+	struct cvmx_npei_state2_s cn52xx;
+	struct cvmx_npei_state2_s cn52xxp1;
+	struct cvmx_npei_state2_s cn56xx;
+	struct cvmx_npei_state2_s cn56xxp1;
+};
+
+union cvmx_npei_state3 {
+	uint64_t u64;
+	struct cvmx_npei_state3_s {
+		uint64_t reserved_56_63:8;
+		uint64_t psm1:15;
+		uint64_t psm0:15;
+		uint64_t nsm1:13;
+		uint64_t nsm0:13;
+	} s;
+	struct cvmx_npei_state3_s cn52xx;
+	struct cvmx_npei_state3_s cn52xxp1;
+	struct cvmx_npei_state3_s cn56xx;
+	struct cvmx_npei_state3_s cn56xxp1;
+};
+
+union cvmx_npei_win_rd_addr {
+	uint64_t u64;
+	struct cvmx_npei_win_rd_addr_s {
+		uint64_t reserved_51_63:13;
+		uint64_t ld_cmd:2;
+		uint64_t iobit:1;
+		uint64_t rd_addr:48;
+	} s;
+	struct cvmx_npei_win_rd_addr_s cn52xx;
+	struct cvmx_npei_win_rd_addr_s cn52xxp1;
+	struct cvmx_npei_win_rd_addr_s cn56xx;
+	struct cvmx_npei_win_rd_addr_s cn56xxp1;
+};
+
+union cvmx_npei_win_rd_data {
+	uint64_t u64;
+	struct cvmx_npei_win_rd_data_s {
+		uint64_t rd_data:64;
+	} s;
+	struct cvmx_npei_win_rd_data_s cn52xx;
+	struct cvmx_npei_win_rd_data_s cn52xxp1;
+	struct cvmx_npei_win_rd_data_s cn56xx;
+	struct cvmx_npei_win_rd_data_s cn56xxp1;
+};
+
+union cvmx_npei_win_wr_addr {
+	uint64_t u64;
+	struct cvmx_npei_win_wr_addr_s {
+		uint64_t reserved_49_63:15;
+		uint64_t iobit:1;
+		uint64_t wr_addr:46;
+		uint64_t reserved_0_1:2;
+	} s;
+	struct cvmx_npei_win_wr_addr_s cn52xx;
+	struct cvmx_npei_win_wr_addr_s cn52xxp1;
+	struct cvmx_npei_win_wr_addr_s cn56xx;
+	struct cvmx_npei_win_wr_addr_s cn56xxp1;
+};
+
+union cvmx_npei_win_wr_data {
+	uint64_t u64;
+	struct cvmx_npei_win_wr_data_s {
+		uint64_t wr_data:64;
+	} s;
+	struct cvmx_npei_win_wr_data_s cn52xx;
+	struct cvmx_npei_win_wr_data_s cn52xxp1;
+	struct cvmx_npei_win_wr_data_s cn56xx;
+	struct cvmx_npei_win_wr_data_s cn56xxp1;
+};
+
+union cvmx_npei_win_wr_mask {
+	uint64_t u64;
+	struct cvmx_npei_win_wr_mask_s {
+		uint64_t reserved_8_63:56;
+		uint64_t wr_mask:8;
+	} s;
+	struct cvmx_npei_win_wr_mask_s cn52xx;
+	struct cvmx_npei_win_wr_mask_s cn52xxp1;
+	struct cvmx_npei_win_wr_mask_s cn56xx;
+	struct cvmx_npei_win_wr_mask_s cn56xxp1;
+};
+
+union cvmx_npei_window_ctl {
+	uint64_t u64;
+	struct cvmx_npei_window_ctl_s {
+		uint64_t reserved_32_63:32;
+		uint64_t time:32;
+	} s;
+	struct cvmx_npei_window_ctl_s cn52xx;
+	struct cvmx_npei_window_ctl_s cn52xxp1;
+	struct cvmx_npei_window_ctl_s cn56xx;
+	struct cvmx_npei_window_ctl_s cn56xxp1;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-npi-defs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-npi-defs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-npi-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-npi-defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1735 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_NPI_DEFS_H__
+#define __CVMX_NPI_DEFS_H__
+
+#define CVMX_NPI_BASE_ADDR_INPUT0 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000070ull)
+#define CVMX_NPI_BASE_ADDR_INPUT1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000080ull)
+#define CVMX_NPI_BASE_ADDR_INPUT2 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000090ull)
+#define CVMX_NPI_BASE_ADDR_INPUT3 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000A0ull)
+#define CVMX_NPI_BASE_ADDR_INPUTX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000000070ull + (((offset) & 3) * 16))
+#define CVMX_NPI_BASE_ADDR_OUTPUT0 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000B8ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUT1 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000C0ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUT2 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000C8ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUT3 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000D0ull)
+#define CVMX_NPI_BASE_ADDR_OUTPUTX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F00000000B8ull + (((offset) & 3) * 8))
+#define CVMX_NPI_BIST_STATUS \
+	 CVMX_ADD_IO_SEG(0x00011F00000003F8ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT0 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000E0ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT1 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000E8ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT2 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000F0ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUT3 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000F8ull)
+#define CVMX_NPI_BUFF_SIZE_OUTPUTX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F00000000E0ull + (((offset) & 3) * 8))
+#define CVMX_NPI_COMP_CTL \
+	 CVMX_ADD_IO_SEG(0x00011F0000000218ull)
+#define CVMX_NPI_CTL_STATUS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000010ull)
+#define CVMX_NPI_DBG_SELECT \
+	 CVMX_ADD_IO_SEG(0x00011F0000000008ull)
+#define CVMX_NPI_DMA_CONTROL \
+	 CVMX_ADD_IO_SEG(0x00011F0000000128ull)
+#define CVMX_NPI_DMA_HIGHP_COUNTS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000148ull)
+#define CVMX_NPI_DMA_HIGHP_NADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000158ull)
+#define CVMX_NPI_DMA_LOWP_COUNTS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000140ull)
+#define CVMX_NPI_DMA_LOWP_NADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000150ull)
+#define CVMX_NPI_HIGHP_DBELL \
+	 CVMX_ADD_IO_SEG(0x00011F0000000120ull)
+#define CVMX_NPI_HIGHP_IBUFF_SADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000110ull)
+#define CVMX_NPI_INPUT_CONTROL \
+	 CVMX_ADD_IO_SEG(0x00011F0000000138ull)
+#define CVMX_NPI_INT_ENB \
+	 CVMX_ADD_IO_SEG(0x00011F0000000020ull)
+#define CVMX_NPI_INT_SUM \
+	 CVMX_ADD_IO_SEG(0x00011F0000000018ull)
+#define CVMX_NPI_LOWP_DBELL \
+	 CVMX_ADD_IO_SEG(0x00011F0000000118ull)
+#define CVMX_NPI_LOWP_IBUFF_SADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000108ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID3 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000028ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID4 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000030ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID5 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000038ull)
+#define CVMX_NPI_MEM_ACCESS_SUBID6 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000040ull)
+#define CVMX_NPI_MEM_ACCESS_SUBIDX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000000028ull + (((offset) & 7) * 8) - 8 * 3)
+#define CVMX_NPI_MSI_RCV \
+	 (0x0000000000000190ull)
+#define CVMX_NPI_NPI_MSI_RCV \
+	 CVMX_ADD_IO_SEG(0x00011F0000001190ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT0 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000050ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000058ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT2 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000060ull)
+#define CVMX_NPI_NUM_DESC_OUTPUT3 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000068ull)
+#define CVMX_NPI_NUM_DESC_OUTPUTX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000000050ull + (((offset) & 3) * 8))
+#define CVMX_NPI_OUTPUT_CONTROL \
+	 CVMX_ADD_IO_SEG(0x00011F0000000100ull)
+#define CVMX_NPI_P0_DBPAIR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000180ull)
+#define CVMX_NPI_P0_INSTR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F00000001C0ull)
+#define CVMX_NPI_P0_INSTR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F00000001A0ull)
+#define CVMX_NPI_P0_PAIR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000160ull)
+#define CVMX_NPI_P1_DBPAIR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000188ull)
+#define CVMX_NPI_P1_INSTR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F00000001C8ull)
+#define CVMX_NPI_P1_INSTR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F00000001A8ull)
+#define CVMX_NPI_P1_PAIR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000168ull)
+#define CVMX_NPI_P2_DBPAIR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000190ull)
+#define CVMX_NPI_P2_INSTR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F00000001D0ull)
+#define CVMX_NPI_P2_INSTR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F00000001B0ull)
+#define CVMX_NPI_P2_PAIR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000170ull)
+#define CVMX_NPI_P3_DBPAIR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000198ull)
+#define CVMX_NPI_P3_INSTR_ADDR \
+	 CVMX_ADD_IO_SEG(0x00011F00000001D8ull)
+#define CVMX_NPI_P3_INSTR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F00000001B8ull)
+#define CVMX_NPI_P3_PAIR_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000178ull)
+#define CVMX_NPI_PCI_BAR1_INDEXX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000001100ull + (((offset) & 31) * 4))
+#define CVMX_NPI_PCI_BIST_REG \
+	 CVMX_ADD_IO_SEG(0x00011F00000011C0ull)
+#define CVMX_NPI_PCI_BURST_SIZE \
+	 CVMX_ADD_IO_SEG(0x00011F00000000D8ull)
+#define CVMX_NPI_PCI_CFG00 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001800ull)
+#define CVMX_NPI_PCI_CFG01 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001804ull)
+#define CVMX_NPI_PCI_CFG02 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001808ull)
+#define CVMX_NPI_PCI_CFG03 \
+	 CVMX_ADD_IO_SEG(0x00011F000000180Cull)
+#define CVMX_NPI_PCI_CFG04 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001810ull)
+#define CVMX_NPI_PCI_CFG05 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001814ull)
+#define CVMX_NPI_PCI_CFG06 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001818ull)
+#define CVMX_NPI_PCI_CFG07 \
+	 CVMX_ADD_IO_SEG(0x00011F000000181Cull)
+#define CVMX_NPI_PCI_CFG08 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001820ull)
+#define CVMX_NPI_PCI_CFG09 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001824ull)
+#define CVMX_NPI_PCI_CFG10 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001828ull)
+#define CVMX_NPI_PCI_CFG11 \
+	 CVMX_ADD_IO_SEG(0x00011F000000182Cull)
+#define CVMX_NPI_PCI_CFG12 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001830ull)
+#define CVMX_NPI_PCI_CFG13 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001834ull)
+#define CVMX_NPI_PCI_CFG15 \
+	 CVMX_ADD_IO_SEG(0x00011F000000183Cull)
+#define CVMX_NPI_PCI_CFG16 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001840ull)
+#define CVMX_NPI_PCI_CFG17 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001844ull)
+#define CVMX_NPI_PCI_CFG18 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001848ull)
+#define CVMX_NPI_PCI_CFG19 \
+	 CVMX_ADD_IO_SEG(0x00011F000000184Cull)
+#define CVMX_NPI_PCI_CFG20 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001850ull)
+#define CVMX_NPI_PCI_CFG21 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001854ull)
+#define CVMX_NPI_PCI_CFG22 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001858ull)
+#define CVMX_NPI_PCI_CFG56 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018E0ull)
+#define CVMX_NPI_PCI_CFG57 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018E4ull)
+#define CVMX_NPI_PCI_CFG58 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018E8ull)
+#define CVMX_NPI_PCI_CFG59 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018ECull)
+#define CVMX_NPI_PCI_CFG60 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018F0ull)
+#define CVMX_NPI_PCI_CFG61 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018F4ull)
+#define CVMX_NPI_PCI_CFG62 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018F8ull)
+#define CVMX_NPI_PCI_CFG63 \
+	 CVMX_ADD_IO_SEG(0x00011F00000018FCull)
+#define CVMX_NPI_PCI_CNT_REG \
+	 CVMX_ADD_IO_SEG(0x00011F00000011B8ull)
+#define CVMX_NPI_PCI_CTL_STATUS_2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000118Cull)
+#define CVMX_NPI_PCI_INT_ARB_CFG \
+	 CVMX_ADD_IO_SEG(0x00011F0000000130ull)
+#define CVMX_NPI_PCI_INT_ENB2 \
+	 CVMX_ADD_IO_SEG(0x00011F00000011A0ull)
+#define CVMX_NPI_PCI_INT_SUM2 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001198ull)
+#define CVMX_NPI_PCI_READ_CMD \
+	 CVMX_ADD_IO_SEG(0x00011F0000000048ull)
+#define CVMX_NPI_PCI_READ_CMD_6 \
+	 CVMX_ADD_IO_SEG(0x00011F0000001180ull)
+#define CVMX_NPI_PCI_READ_CMD_C \
+	 CVMX_ADD_IO_SEG(0x00011F0000001184ull)
+#define CVMX_NPI_PCI_READ_CMD_E \
+	 CVMX_ADD_IO_SEG(0x00011F0000001188ull)
+#define CVMX_NPI_PCI_SCM_REG \
+	 CVMX_ADD_IO_SEG(0x00011F00000011A8ull)
+#define CVMX_NPI_PCI_TSR_REG \
+	 CVMX_ADD_IO_SEG(0x00011F00000011B0ull)
+#define CVMX_NPI_PORT32_INSTR_HDR \
+	 CVMX_ADD_IO_SEG(0x00011F00000001F8ull)
+#define CVMX_NPI_PORT33_INSTR_HDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000200ull)
+#define CVMX_NPI_PORT34_INSTR_HDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000208ull)
+#define CVMX_NPI_PORT35_INSTR_HDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000000210ull)
+#define CVMX_NPI_PORT_BP_CONTROL \
+	 CVMX_ADD_IO_SEG(0x00011F00000001F0ull)
+#define CVMX_NPI_PX_DBPAIR_ADDR(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000000180ull + (((offset) & 3) * 8))
+#define CVMX_NPI_PX_INSTR_ADDR(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F00000001C0ull + (((offset) & 3) * 8))
+#define CVMX_NPI_PX_INSTR_CNTS(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F00000001A0ull + (((offset) & 3) * 8))
+#define CVMX_NPI_PX_PAIR_CNTS(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000000160ull + (((offset) & 3) * 8))
+#define CVMX_NPI_RSL_INT_BLOCKS \
+	 CVMX_ADD_IO_SEG(0x00011F0000000000ull)
+#define CVMX_NPI_SIZE_INPUT0 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000078ull)
+#define CVMX_NPI_SIZE_INPUT1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000088ull)
+#define CVMX_NPI_SIZE_INPUT2 \
+	 CVMX_ADD_IO_SEG(0x00011F0000000098ull)
+#define CVMX_NPI_SIZE_INPUT3 \
+	 CVMX_ADD_IO_SEG(0x00011F00000000A8ull)
+#define CVMX_NPI_SIZE_INPUTX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000000078ull + (((offset) & 3) * 16))
+#define CVMX_NPI_WIN_READ_TO \
+	 CVMX_ADD_IO_SEG(0x00011F00000001E0ull)
+
+union cvmx_npi_base_addr_inputx {
+	uint64_t u64;
+	struct cvmx_npi_base_addr_inputx_s {
+		uint64_t baddr:61;
+		uint64_t reserved_0_2:3;
+	} s;
+	struct cvmx_npi_base_addr_inputx_s cn30xx;
+	struct cvmx_npi_base_addr_inputx_s cn31xx;
+	struct cvmx_npi_base_addr_inputx_s cn38xx;
+	struct cvmx_npi_base_addr_inputx_s cn38xxp2;
+	struct cvmx_npi_base_addr_inputx_s cn50xx;
+	struct cvmx_npi_base_addr_inputx_s cn58xx;
+	struct cvmx_npi_base_addr_inputx_s cn58xxp1;
+};
+
+union cvmx_npi_base_addr_outputx {
+	uint64_t u64;
+	struct cvmx_npi_base_addr_outputx_s {
+		uint64_t baddr:61;
+		uint64_t reserved_0_2:3;
+	} s;
+	struct cvmx_npi_base_addr_outputx_s cn30xx;
+	struct cvmx_npi_base_addr_outputx_s cn31xx;
+	struct cvmx_npi_base_addr_outputx_s cn38xx;
+	struct cvmx_npi_base_addr_outputx_s cn38xxp2;
+	struct cvmx_npi_base_addr_outputx_s cn50xx;
+	struct cvmx_npi_base_addr_outputx_s cn58xx;
+	struct cvmx_npi_base_addr_outputx_s cn58xxp1;
+};
+
+union cvmx_npi_bist_status {
+	uint64_t u64;
+	struct cvmx_npi_bist_status_s {
+		uint64_t reserved_20_63:44;
+		uint64_t csr_bs:1;
+		uint64_t dif_bs:1;
+		uint64_t rdp_bs:1;
+		uint64_t pcnc_bs:1;
+		uint64_t pcn_bs:1;
+		uint64_t rdn_bs:1;
+		uint64_t pcac_bs:1;
+		uint64_t pcad_bs:1;
+		uint64_t rdnl_bs:1;
+		uint64_t pgf_bs:1;
+		uint64_t pig_bs:1;
+		uint64_t pof0_bs:1;
+		uint64_t pof1_bs:1;
+		uint64_t pof2_bs:1;
+		uint64_t pof3_bs:1;
+		uint64_t pos_bs:1;
+		uint64_t nus_bs:1;
+		uint64_t dob_bs:1;
+		uint64_t pdf_bs:1;
+		uint64_t dpi_bs:1;
+	} s;
+	struct cvmx_npi_bist_status_cn30xx {
+		uint64_t reserved_20_63:44;
+		uint64_t csr_bs:1;
+		uint64_t dif_bs:1;
+		uint64_t rdp_bs:1;
+		uint64_t pcnc_bs:1;
+		uint64_t pcn_bs:1;
+		uint64_t rdn_bs:1;
+		uint64_t pcac_bs:1;
+		uint64_t pcad_bs:1;
+		uint64_t rdnl_bs:1;
+		uint64_t pgf_bs:1;
+		uint64_t pig_bs:1;
+		uint64_t pof0_bs:1;
+		uint64_t reserved_5_7:3;
+		uint64_t pos_bs:1;
+		uint64_t nus_bs:1;
+		uint64_t dob_bs:1;
+		uint64_t pdf_bs:1;
+		uint64_t dpi_bs:1;
+	} cn30xx;
+	struct cvmx_npi_bist_status_s cn31xx;
+	struct cvmx_npi_bist_status_s cn38xx;
+	struct cvmx_npi_bist_status_s cn38xxp2;
+	struct cvmx_npi_bist_status_cn50xx {
+		uint64_t reserved_20_63:44;
+		uint64_t csr_bs:1;
+		uint64_t dif_bs:1;
+		uint64_t rdp_bs:1;
+		uint64_t pcnc_bs:1;
+		uint64_t pcn_bs:1;
+		uint64_t rdn_bs:1;
+		uint64_t pcac_bs:1;
+		uint64_t pcad_bs:1;
+		uint64_t rdnl_bs:1;
+		uint64_t pgf_bs:1;
+		uint64_t pig_bs:1;
+		uint64_t pof0_bs:1;
+		uint64_t pof1_bs:1;
+		uint64_t reserved_5_6:2;
+		uint64_t pos_bs:1;
+		uint64_t nus_bs:1;
+		uint64_t dob_bs:1;
+		uint64_t pdf_bs:1;
+		uint64_t dpi_bs:1;
+	} cn50xx;
+	struct cvmx_npi_bist_status_s cn58xx;
+	struct cvmx_npi_bist_status_s cn58xxp1;
+};
+
+union cvmx_npi_buff_size_outputx {
+	uint64_t u64;
+	struct cvmx_npi_buff_size_outputx_s {
+		uint64_t reserved_23_63:41;
+		uint64_t isize:7;
+		uint64_t bsize:16;
+	} s;
+	struct cvmx_npi_buff_size_outputx_s cn30xx;
+	struct cvmx_npi_buff_size_outputx_s cn31xx;
+	struct cvmx_npi_buff_size_outputx_s cn38xx;
+	struct cvmx_npi_buff_size_outputx_s cn38xxp2;
+	struct cvmx_npi_buff_size_outputx_s cn50xx;
+	struct cvmx_npi_buff_size_outputx_s cn58xx;
+	struct cvmx_npi_buff_size_outputx_s cn58xxp1;
+};
+
+union cvmx_npi_comp_ctl {
+	uint64_t u64;
+	struct cvmx_npi_comp_ctl_s {
+		uint64_t reserved_10_63:54;
+		uint64_t pctl:5;
+		uint64_t nctl:5;
+	} s;
+	struct cvmx_npi_comp_ctl_s cn50xx;
+	struct cvmx_npi_comp_ctl_s cn58xx;
+	struct cvmx_npi_comp_ctl_s cn58xxp1;
+};
+
+union cvmx_npi_ctl_status {
+	uint64_t u64;
+	struct cvmx_npi_ctl_status_s {
+		uint64_t reserved_63_63:1;
+		uint64_t chip_rev:8;
+		uint64_t dis_pniw:1;
+		uint64_t out3_enb:1;
+		uint64_t out2_enb:1;
+		uint64_t out1_enb:1;
+		uint64_t out0_enb:1;
+		uint64_t ins3_enb:1;
+		uint64_t ins2_enb:1;
+		uint64_t ins1_enb:1;
+		uint64_t ins0_enb:1;
+		uint64_t ins3_64b:1;
+		uint64_t ins2_64b:1;
+		uint64_t ins1_64b:1;
+		uint64_t ins0_64b:1;
+		uint64_t pci_wdis:1;
+		uint64_t wait_com:1;
+		uint64_t reserved_37_39:3;
+		uint64_t max_word:5;
+		uint64_t reserved_10_31:22;
+		uint64_t timer:10;
+	} s;
+	struct cvmx_npi_ctl_status_cn30xx {
+		uint64_t reserved_63_63:1;
+		uint64_t chip_rev:8;
+		uint64_t dis_pniw:1;
+		uint64_t reserved_51_53:3;
+		uint64_t out0_enb:1;
+		uint64_t reserved_47_49:3;
+		uint64_t ins0_enb:1;
+		uint64_t reserved_43_45:3;
+		uint64_t ins0_64b:1;
+		uint64_t pci_wdis:1;
+		uint64_t wait_com:1;
+		uint64_t reserved_37_39:3;
+		uint64_t max_word:5;
+		uint64_t reserved_10_31:22;
+		uint64_t timer:10;
+	} cn30xx;
+	struct cvmx_npi_ctl_status_cn31xx {
+		uint64_t reserved_63_63:1;
+		uint64_t chip_rev:8;
+		uint64_t dis_pniw:1;
+		uint64_t reserved_52_53:2;
+		uint64_t out1_enb:1;
+		uint64_t out0_enb:1;
+		uint64_t reserved_48_49:2;
+		uint64_t ins1_enb:1;
+		uint64_t ins0_enb:1;
+		uint64_t reserved_44_45:2;
+		uint64_t ins1_64b:1;
+		uint64_t ins0_64b:1;
+		uint64_t pci_wdis:1;
+		uint64_t wait_com:1;
+		uint64_t reserved_37_39:3;
+		uint64_t max_word:5;
+		uint64_t reserved_10_31:22;
+		uint64_t timer:10;
+	} cn31xx;
+	struct cvmx_npi_ctl_status_s cn38xx;
+	struct cvmx_npi_ctl_status_s cn38xxp2;
+	struct cvmx_npi_ctl_status_cn31xx cn50xx;
+	struct cvmx_npi_ctl_status_s cn58xx;
+	struct cvmx_npi_ctl_status_s cn58xxp1;
+};
+
+union cvmx_npi_dbg_select {
+	uint64_t u64;
+	struct cvmx_npi_dbg_select_s {
+		uint64_t reserved_16_63:48;
+		uint64_t dbg_sel:16;
+	} s;
+	struct cvmx_npi_dbg_select_s cn30xx;
+	struct cvmx_npi_dbg_select_s cn31xx;
+	struct cvmx_npi_dbg_select_s cn38xx;
+	struct cvmx_npi_dbg_select_s cn38xxp2;
+	struct cvmx_npi_dbg_select_s cn50xx;
+	struct cvmx_npi_dbg_select_s cn58xx;
+	struct cvmx_npi_dbg_select_s cn58xxp1;
+};
+
+union cvmx_npi_dma_control {
+	uint64_t u64;
+	struct cvmx_npi_dma_control_s {
+		uint64_t reserved_36_63:28;
+		uint64_t b0_lend:1;
+		uint64_t dwb_denb:1;
+		uint64_t dwb_ichk:9;
+		uint64_t fpa_que:3;
+		uint64_t o_add1:1;
+		uint64_t o_ro:1;
+		uint64_t o_ns:1;
+		uint64_t o_es:2;
+		uint64_t o_mode:1;
+		uint64_t hp_enb:1;
+		uint64_t lp_enb:1;
+		uint64_t csize:14;
+	} s;
+	struct cvmx_npi_dma_control_s cn30xx;
+	struct cvmx_npi_dma_control_s cn31xx;
+	struct cvmx_npi_dma_control_s cn38xx;
+	struct cvmx_npi_dma_control_s cn38xxp2;
+	struct cvmx_npi_dma_control_s cn50xx;
+	struct cvmx_npi_dma_control_s cn58xx;
+	struct cvmx_npi_dma_control_s cn58xxp1;
+};
+
+union cvmx_npi_dma_highp_counts {
+	uint64_t u64;
+	struct cvmx_npi_dma_highp_counts_s {
+		uint64_t reserved_39_63:25;
+		uint64_t fcnt:7;
+		uint64_t dbell:32;
+	} s;
+	struct cvmx_npi_dma_highp_counts_s cn30xx;
+	struct cvmx_npi_dma_highp_counts_s cn31xx;
+	struct cvmx_npi_dma_highp_counts_s cn38xx;
+	struct cvmx_npi_dma_highp_counts_s cn38xxp2;
+	struct cvmx_npi_dma_highp_counts_s cn50xx;
+	struct cvmx_npi_dma_highp_counts_s cn58xx;
+	struct cvmx_npi_dma_highp_counts_s cn58xxp1;
+};
+
+union cvmx_npi_dma_highp_naddr {
+	uint64_t u64;
+	struct cvmx_npi_dma_highp_naddr_s {
+		uint64_t reserved_40_63:24;
+		uint64_t state:4;
+		uint64_t addr:36;
+	} s;
+	struct cvmx_npi_dma_highp_naddr_s cn30xx;
+	struct cvmx_npi_dma_highp_naddr_s cn31xx;
+	struct cvmx_npi_dma_highp_naddr_s cn38xx;
+	struct cvmx_npi_dma_highp_naddr_s cn38xxp2;
+	struct cvmx_npi_dma_highp_naddr_s cn50xx;
+	struct cvmx_npi_dma_highp_naddr_s cn58xx;
+	struct cvmx_npi_dma_highp_naddr_s cn58xxp1;
+};
+
+union cvmx_npi_dma_lowp_counts {
+	uint64_t u64;
+	struct cvmx_npi_dma_lowp_counts_s {
+		uint64_t reserved_39_63:25;
+		uint64_t fcnt:7;
+		uint64_t dbell:32;
+	} s;
+	struct cvmx_npi_dma_lowp_counts_s cn30xx;
+	struct cvmx_npi_dma_lowp_counts_s cn31xx;
+	struct cvmx_npi_dma_lowp_counts_s cn38xx;
+	struct cvmx_npi_dma_lowp_counts_s cn38xxp2;
+	struct cvmx_npi_dma_lowp_counts_s cn50xx;
+	struct cvmx_npi_dma_lowp_counts_s cn58xx;
+	struct cvmx_npi_dma_lowp_counts_s cn58xxp1;
+};
+
+union cvmx_npi_dma_lowp_naddr {
+	uint64_t u64;
+	struct cvmx_npi_dma_lowp_naddr_s {
+		uint64_t reserved_40_63:24;
+		uint64_t state:4;
+		uint64_t addr:36;
+	} s;
+	struct cvmx_npi_dma_lowp_naddr_s cn30xx;
+	struct cvmx_npi_dma_lowp_naddr_s cn31xx;
+	struct cvmx_npi_dma_lowp_naddr_s cn38xx;
+	struct cvmx_npi_dma_lowp_naddr_s cn38xxp2;
+	struct cvmx_npi_dma_lowp_naddr_s cn50xx;
+	struct cvmx_npi_dma_lowp_naddr_s cn58xx;
+	struct cvmx_npi_dma_lowp_naddr_s cn58xxp1;
+};
+
+union cvmx_npi_highp_dbell {
+	uint64_t u64;
+	struct cvmx_npi_highp_dbell_s {
+		uint64_t reserved_16_63:48;
+		uint64_t dbell:16;
+	} s;
+	struct cvmx_npi_highp_dbell_s cn30xx;
+	struct cvmx_npi_highp_dbell_s cn31xx;
+	struct cvmx_npi_highp_dbell_s cn38xx;
+	struct cvmx_npi_highp_dbell_s cn38xxp2;
+	struct cvmx_npi_highp_dbell_s cn50xx;
+	struct cvmx_npi_highp_dbell_s cn58xx;
+	struct cvmx_npi_highp_dbell_s cn58xxp1;
+};
+
+union cvmx_npi_highp_ibuff_saddr {
+	uint64_t u64;
+	struct cvmx_npi_highp_ibuff_saddr_s {
+		uint64_t reserved_36_63:28;
+		uint64_t saddr:36;
+	} s;
+	struct cvmx_npi_highp_ibuff_saddr_s cn30xx;
+	struct cvmx_npi_highp_ibuff_saddr_s cn31xx;
+	struct cvmx_npi_highp_ibuff_saddr_s cn38xx;
+	struct cvmx_npi_highp_ibuff_saddr_s cn38xxp2;
+	struct cvmx_npi_highp_ibuff_saddr_s cn50xx;
+	struct cvmx_npi_highp_ibuff_saddr_s cn58xx;
+	struct cvmx_npi_highp_ibuff_saddr_s cn58xxp1;
+};
+
+union cvmx_npi_input_control {
+	uint64_t u64;
+	struct cvmx_npi_input_control_s {
+		uint64_t reserved_23_63:41;
+		uint64_t pkt_rr:1;
+		uint64_t pbp_dhi:13;
+		uint64_t d_nsr:1;
+		uint64_t d_esr:2;
+		uint64_t d_ror:1;
+		uint64_t use_csr:1;
+		uint64_t nsr:1;
+		uint64_t esr:2;
+		uint64_t ror:1;
+	} s;
+	struct cvmx_npi_input_control_cn30xx {
+		uint64_t reserved_22_63:42;
+		uint64_t pbp_dhi:13;
+		uint64_t d_nsr:1;
+		uint64_t d_esr:2;
+		uint64_t d_ror:1;
+		uint64_t use_csr:1;
+		uint64_t nsr:1;
+		uint64_t esr:2;
+		uint64_t ror:1;
+	} cn30xx;
+	struct cvmx_npi_input_control_cn30xx cn31xx;
+	struct cvmx_npi_input_control_s cn38xx;
+	struct cvmx_npi_input_control_cn30xx cn38xxp2;
+	struct cvmx_npi_input_control_s cn50xx;
+	struct cvmx_npi_input_control_s cn58xx;
+	struct cvmx_npi_input_control_s cn58xxp1;
+};
+
+union cvmx_npi_int_enb {
+	uint64_t u64;
+	struct cvmx_npi_int_enb_s {
+		uint64_t reserved_62_63:2;
+		uint64_t q1_a_f:1;
+		uint64_t q1_s_e:1;
+		uint64_t pdf_p_f:1;
+		uint64_t pdf_p_e:1;
+		uint64_t pcf_p_f:1;
+		uint64_t pcf_p_e:1;
+		uint64_t rdx_s_e:1;
+		uint64_t rwx_s_e:1;
+		uint64_t pnc_a_f:1;
+		uint64_t pnc_s_e:1;
+		uint64_t com_a_f:1;
+		uint64_t com_s_e:1;
+		uint64_t q3_a_f:1;
+		uint64_t q3_s_e:1;
+		uint64_t q2_a_f:1;
+		uint64_t q2_s_e:1;
+		uint64_t pcr_a_f:1;
+		uint64_t pcr_s_e:1;
+		uint64_t fcr_a_f:1;
+		uint64_t fcr_s_e:1;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t i3_pperr:1;
+		uint64_t i2_pperr:1;
+		uint64_t i1_pperr:1;
+		uint64_t i0_pperr:1;
+		uint64_t p3_ptout:1;
+		uint64_t p2_ptout:1;
+		uint64_t p1_ptout:1;
+		uint64_t p0_ptout:1;
+		uint64_t p3_pperr:1;
+		uint64_t p2_pperr:1;
+		uint64_t p1_pperr:1;
+		uint64_t p0_pperr:1;
+		uint64_t g3_rtout:1;
+		uint64_t g2_rtout:1;
+		uint64_t g1_rtout:1;
+		uint64_t g0_rtout:1;
+		uint64_t p3_perr:1;
+		uint64_t p2_perr:1;
+		uint64_t p1_perr:1;
+		uint64_t p0_perr:1;
+		uint64_t p3_rtout:1;
+		uint64_t p2_rtout:1;
+		uint64_t p1_rtout:1;
+		uint64_t p0_rtout:1;
+		uint64_t i3_overf:1;
+		uint64_t i2_overf:1;
+		uint64_t i1_overf:1;
+		uint64_t i0_overf:1;
+		uint64_t i3_rtout:1;
+		uint64_t i2_rtout:1;
+		uint64_t i1_rtout:1;
+		uint64_t i0_rtout:1;
+		uint64_t po3_2sml:1;
+		uint64_t po2_2sml:1;
+		uint64_t po1_2sml:1;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} s;
+	struct cvmx_npi_int_enb_cn30xx {
+		uint64_t reserved_62_63:2;
+		uint64_t q1_a_f:1;
+		uint64_t q1_s_e:1;
+		uint64_t pdf_p_f:1;
+		uint64_t pdf_p_e:1;
+		uint64_t pcf_p_f:1;
+		uint64_t pcf_p_e:1;
+		uint64_t rdx_s_e:1;
+		uint64_t rwx_s_e:1;
+		uint64_t pnc_a_f:1;
+		uint64_t pnc_s_e:1;
+		uint64_t com_a_f:1;
+		uint64_t com_s_e:1;
+		uint64_t q3_a_f:1;
+		uint64_t q3_s_e:1;
+		uint64_t q2_a_f:1;
+		uint64_t q2_s_e:1;
+		uint64_t pcr_a_f:1;
+		uint64_t pcr_s_e:1;
+		uint64_t fcr_a_f:1;
+		uint64_t fcr_s_e:1;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t reserved_36_38:3;
+		uint64_t i0_pperr:1;
+		uint64_t reserved_32_34:3;
+		uint64_t p0_ptout:1;
+		uint64_t reserved_28_30:3;
+		uint64_t p0_pperr:1;
+		uint64_t reserved_24_26:3;
+		uint64_t g0_rtout:1;
+		uint64_t reserved_20_22:3;
+		uint64_t p0_perr:1;
+		uint64_t reserved_16_18:3;
+		uint64_t p0_rtout:1;
+		uint64_t reserved_12_14:3;
+		uint64_t i0_overf:1;
+		uint64_t reserved_8_10:3;
+		uint64_t i0_rtout:1;
+		uint64_t reserved_4_6:3;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn30xx;
+	struct cvmx_npi_int_enb_cn31xx {
+		uint64_t reserved_62_63:2;
+		uint64_t q1_a_f:1;
+		uint64_t q1_s_e:1;
+		uint64_t pdf_p_f:1;
+		uint64_t pdf_p_e:1;
+		uint64_t pcf_p_f:1;
+		uint64_t pcf_p_e:1;
+		uint64_t rdx_s_e:1;
+		uint64_t rwx_s_e:1;
+		uint64_t pnc_a_f:1;
+		uint64_t pnc_s_e:1;
+		uint64_t com_a_f:1;
+		uint64_t com_s_e:1;
+		uint64_t q3_a_f:1;
+		uint64_t q3_s_e:1;
+		uint64_t q2_a_f:1;
+		uint64_t q2_s_e:1;
+		uint64_t pcr_a_f:1;
+		uint64_t pcr_s_e:1;
+		uint64_t fcr_a_f:1;
+		uint64_t fcr_s_e:1;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t reserved_37_38:2;
+		uint64_t i1_pperr:1;
+		uint64_t i0_pperr:1;
+		uint64_t reserved_33_34:2;
+		uint64_t p1_ptout:1;
+		uint64_t p0_ptout:1;
+		uint64_t reserved_29_30:2;
+		uint64_t p1_pperr:1;
+		uint64_t p0_pperr:1;
+		uint64_t reserved_25_26:2;
+		uint64_t g1_rtout:1;
+		uint64_t g0_rtout:1;
+		uint64_t reserved_21_22:2;
+		uint64_t p1_perr:1;
+		uint64_t p0_perr:1;
+		uint64_t reserved_17_18:2;
+		uint64_t p1_rtout:1;
+		uint64_t p0_rtout:1;
+		uint64_t reserved_13_14:2;
+		uint64_t i1_overf:1;
+		uint64_t i0_overf:1;
+		uint64_t reserved_9_10:2;
+		uint64_t i1_rtout:1;
+		uint64_t i0_rtout:1;
+		uint64_t reserved_5_6:2;
+		uint64_t po1_2sml:1;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn31xx;
+	struct cvmx_npi_int_enb_s cn38xx;
+	struct cvmx_npi_int_enb_cn38xxp2 {
+		uint64_t reserved_42_63:22;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t i3_pperr:1;
+		uint64_t i2_pperr:1;
+		uint64_t i1_pperr:1;
+		uint64_t i0_pperr:1;
+		uint64_t p3_ptout:1;
+		uint64_t p2_ptout:1;
+		uint64_t p1_ptout:1;
+		uint64_t p0_ptout:1;
+		uint64_t p3_pperr:1;
+		uint64_t p2_pperr:1;
+		uint64_t p1_pperr:1;
+		uint64_t p0_pperr:1;
+		uint64_t g3_rtout:1;
+		uint64_t g2_rtout:1;
+		uint64_t g1_rtout:1;
+		uint64_t g0_rtout:1;
+		uint64_t p3_perr:1;
+		uint64_t p2_perr:1;
+		uint64_t p1_perr:1;
+		uint64_t p0_perr:1;
+		uint64_t p3_rtout:1;
+		uint64_t p2_rtout:1;
+		uint64_t p1_rtout:1;
+		uint64_t p0_rtout:1;
+		uint64_t i3_overf:1;
+		uint64_t i2_overf:1;
+		uint64_t i1_overf:1;
+		uint64_t i0_overf:1;
+		uint64_t i3_rtout:1;
+		uint64_t i2_rtout:1;
+		uint64_t i1_rtout:1;
+		uint64_t i0_rtout:1;
+		uint64_t po3_2sml:1;
+		uint64_t po2_2sml:1;
+		uint64_t po1_2sml:1;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn38xxp2;
+	struct cvmx_npi_int_enb_cn31xx cn50xx;
+	struct cvmx_npi_int_enb_s cn58xx;
+	struct cvmx_npi_int_enb_s cn58xxp1;
+};
+
+union cvmx_npi_int_sum {
+	uint64_t u64;
+	struct cvmx_npi_int_sum_s {
+		uint64_t reserved_62_63:2;
+		uint64_t q1_a_f:1;
+		uint64_t q1_s_e:1;
+		uint64_t pdf_p_f:1;
+		uint64_t pdf_p_e:1;
+		uint64_t pcf_p_f:1;
+		uint64_t pcf_p_e:1;
+		uint64_t rdx_s_e:1;
+		uint64_t rwx_s_e:1;
+		uint64_t pnc_a_f:1;
+		uint64_t pnc_s_e:1;
+		uint64_t com_a_f:1;
+		uint64_t com_s_e:1;
+		uint64_t q3_a_f:1;
+		uint64_t q3_s_e:1;
+		uint64_t q2_a_f:1;
+		uint64_t q2_s_e:1;
+		uint64_t pcr_a_f:1;
+		uint64_t pcr_s_e:1;
+		uint64_t fcr_a_f:1;
+		uint64_t fcr_s_e:1;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t i3_pperr:1;
+		uint64_t i2_pperr:1;
+		uint64_t i1_pperr:1;
+		uint64_t i0_pperr:1;
+		uint64_t p3_ptout:1;
+		uint64_t p2_ptout:1;
+		uint64_t p1_ptout:1;
+		uint64_t p0_ptout:1;
+		uint64_t p3_pperr:1;
+		uint64_t p2_pperr:1;
+		uint64_t p1_pperr:1;
+		uint64_t p0_pperr:1;
+		uint64_t g3_rtout:1;
+		uint64_t g2_rtout:1;
+		uint64_t g1_rtout:1;
+		uint64_t g0_rtout:1;
+		uint64_t p3_perr:1;
+		uint64_t p2_perr:1;
+		uint64_t p1_perr:1;
+		uint64_t p0_perr:1;
+		uint64_t p3_rtout:1;
+		uint64_t p2_rtout:1;
+		uint64_t p1_rtout:1;
+		uint64_t p0_rtout:1;
+		uint64_t i3_overf:1;
+		uint64_t i2_overf:1;
+		uint64_t i1_overf:1;
+		uint64_t i0_overf:1;
+		uint64_t i3_rtout:1;
+		uint64_t i2_rtout:1;
+		uint64_t i1_rtout:1;
+		uint64_t i0_rtout:1;
+		uint64_t po3_2sml:1;
+		uint64_t po2_2sml:1;
+		uint64_t po1_2sml:1;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} s;
+	struct cvmx_npi_int_sum_cn30xx {
+		uint64_t reserved_62_63:2;
+		uint64_t q1_a_f:1;
+		uint64_t q1_s_e:1;
+		uint64_t pdf_p_f:1;
+		uint64_t pdf_p_e:1;
+		uint64_t pcf_p_f:1;
+		uint64_t pcf_p_e:1;
+		uint64_t rdx_s_e:1;
+		uint64_t rwx_s_e:1;
+		uint64_t pnc_a_f:1;
+		uint64_t pnc_s_e:1;
+		uint64_t com_a_f:1;
+		uint64_t com_s_e:1;
+		uint64_t q3_a_f:1;
+		uint64_t q3_s_e:1;
+		uint64_t q2_a_f:1;
+		uint64_t q2_s_e:1;
+		uint64_t pcr_a_f:1;
+		uint64_t pcr_s_e:1;
+		uint64_t fcr_a_f:1;
+		uint64_t fcr_s_e:1;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t reserved_36_38:3;
+		uint64_t i0_pperr:1;
+		uint64_t reserved_32_34:3;
+		uint64_t p0_ptout:1;
+		uint64_t reserved_28_30:3;
+		uint64_t p0_pperr:1;
+		uint64_t reserved_24_26:3;
+		uint64_t g0_rtout:1;
+		uint64_t reserved_20_22:3;
+		uint64_t p0_perr:1;
+		uint64_t reserved_16_18:3;
+		uint64_t p0_rtout:1;
+		uint64_t reserved_12_14:3;
+		uint64_t i0_overf:1;
+		uint64_t reserved_8_10:3;
+		uint64_t i0_rtout:1;
+		uint64_t reserved_4_6:3;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn30xx;
+	struct cvmx_npi_int_sum_cn31xx {
+		uint64_t reserved_62_63:2;
+		uint64_t q1_a_f:1;
+		uint64_t q1_s_e:1;
+		uint64_t pdf_p_f:1;
+		uint64_t pdf_p_e:1;
+		uint64_t pcf_p_f:1;
+		uint64_t pcf_p_e:1;
+		uint64_t rdx_s_e:1;
+		uint64_t rwx_s_e:1;
+		uint64_t pnc_a_f:1;
+		uint64_t pnc_s_e:1;
+		uint64_t com_a_f:1;
+		uint64_t com_s_e:1;
+		uint64_t q3_a_f:1;
+		uint64_t q3_s_e:1;
+		uint64_t q2_a_f:1;
+		uint64_t q2_s_e:1;
+		uint64_t pcr_a_f:1;
+		uint64_t pcr_s_e:1;
+		uint64_t fcr_a_f:1;
+		uint64_t fcr_s_e:1;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t reserved_37_38:2;
+		uint64_t i1_pperr:1;
+		uint64_t i0_pperr:1;
+		uint64_t reserved_33_34:2;
+		uint64_t p1_ptout:1;
+		uint64_t p0_ptout:1;
+		uint64_t reserved_29_30:2;
+		uint64_t p1_pperr:1;
+		uint64_t p0_pperr:1;
+		uint64_t reserved_25_26:2;
+		uint64_t g1_rtout:1;
+		uint64_t g0_rtout:1;
+		uint64_t reserved_21_22:2;
+		uint64_t p1_perr:1;
+		uint64_t p0_perr:1;
+		uint64_t reserved_17_18:2;
+		uint64_t p1_rtout:1;
+		uint64_t p0_rtout:1;
+		uint64_t reserved_13_14:2;
+		uint64_t i1_overf:1;
+		uint64_t i0_overf:1;
+		uint64_t reserved_9_10:2;
+		uint64_t i1_rtout:1;
+		uint64_t i0_rtout:1;
+		uint64_t reserved_5_6:2;
+		uint64_t po1_2sml:1;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn31xx;
+	struct cvmx_npi_int_sum_s cn38xx;
+	struct cvmx_npi_int_sum_cn38xxp2 {
+		uint64_t reserved_42_63:22;
+		uint64_t iobdma:1;
+		uint64_t p_dperr:1;
+		uint64_t win_rto:1;
+		uint64_t i3_pperr:1;
+		uint64_t i2_pperr:1;
+		uint64_t i1_pperr:1;
+		uint64_t i0_pperr:1;
+		uint64_t p3_ptout:1;
+		uint64_t p2_ptout:1;
+		uint64_t p1_ptout:1;
+		uint64_t p0_ptout:1;
+		uint64_t p3_pperr:1;
+		uint64_t p2_pperr:1;
+		uint64_t p1_pperr:1;
+		uint64_t p0_pperr:1;
+		uint64_t g3_rtout:1;
+		uint64_t g2_rtout:1;
+		uint64_t g1_rtout:1;
+		uint64_t g0_rtout:1;
+		uint64_t p3_perr:1;
+		uint64_t p2_perr:1;
+		uint64_t p1_perr:1;
+		uint64_t p0_perr:1;
+		uint64_t p3_rtout:1;
+		uint64_t p2_rtout:1;
+		uint64_t p1_rtout:1;
+		uint64_t p0_rtout:1;
+		uint64_t i3_overf:1;
+		uint64_t i2_overf:1;
+		uint64_t i1_overf:1;
+		uint64_t i0_overf:1;
+		uint64_t i3_rtout:1;
+		uint64_t i2_rtout:1;
+		uint64_t i1_rtout:1;
+		uint64_t i0_rtout:1;
+		uint64_t po3_2sml:1;
+		uint64_t po2_2sml:1;
+		uint64_t po1_2sml:1;
+		uint64_t po0_2sml:1;
+		uint64_t pci_rsl:1;
+		uint64_t rml_wto:1;
+		uint64_t rml_rto:1;
+	} cn38xxp2;
+	struct cvmx_npi_int_sum_cn31xx cn50xx;
+	struct cvmx_npi_int_sum_s cn58xx;
+	struct cvmx_npi_int_sum_s cn58xxp1;
+};
+
+union cvmx_npi_lowp_dbell {
+	uint64_t u64;
+	struct cvmx_npi_lowp_dbell_s {
+		uint64_t reserved_16_63:48;
+		uint64_t dbell:16;
+	} s;
+	struct cvmx_npi_lowp_dbell_s cn30xx;
+	struct cvmx_npi_lowp_dbell_s cn31xx;
+	struct cvmx_npi_lowp_dbell_s cn38xx;
+	struct cvmx_npi_lowp_dbell_s cn38xxp2;
+	struct cvmx_npi_lowp_dbell_s cn50xx;
+	struct cvmx_npi_lowp_dbell_s cn58xx;
+	struct cvmx_npi_lowp_dbell_s cn58xxp1;
+};
+
+union cvmx_npi_lowp_ibuff_saddr {
+	uint64_t u64;
+	struct cvmx_npi_lowp_ibuff_saddr_s {
+		uint64_t reserved_36_63:28;
+		uint64_t saddr:36;
+	} s;
+	struct cvmx_npi_lowp_ibuff_saddr_s cn30xx;
+	struct cvmx_npi_lowp_ibuff_saddr_s cn31xx;
+	struct cvmx_npi_lowp_ibuff_saddr_s cn38xx;
+	struct cvmx_npi_lowp_ibuff_saddr_s cn38xxp2;
+	struct cvmx_npi_lowp_ibuff_saddr_s cn50xx;
+	struct cvmx_npi_lowp_ibuff_saddr_s cn58xx;
+	struct cvmx_npi_lowp_ibuff_saddr_s cn58xxp1;
+};
+
+union cvmx_npi_mem_access_subidx {
+	uint64_t u64;
+	struct cvmx_npi_mem_access_subidx_s {
+		uint64_t reserved_38_63:26;
+		uint64_t shortl:1;
+		uint64_t nmerge:1;
+		uint64_t esr:2;
+		uint64_t esw:2;
+		uint64_t nsr:1;
+		uint64_t nsw:1;
+		uint64_t ror:1;
+		uint64_t row:1;
+		uint64_t ba:28;
+	} s;
+	struct cvmx_npi_mem_access_subidx_s cn30xx;
+	struct cvmx_npi_mem_access_subidx_cn31xx {
+		uint64_t reserved_36_63:28;
+		uint64_t esr:2;
+		uint64_t esw:2;
+		uint64_t nsr:1;
+		uint64_t nsw:1;
+		uint64_t ror:1;
+		uint64_t row:1;
+		uint64_t ba:28;
+	} cn31xx;
+	struct cvmx_npi_mem_access_subidx_s cn38xx;
+	struct cvmx_npi_mem_access_subidx_cn31xx cn38xxp2;
+	struct cvmx_npi_mem_access_subidx_s cn50xx;
+	struct cvmx_npi_mem_access_subidx_s cn58xx;
+	struct cvmx_npi_mem_access_subidx_s cn58xxp1;
+};
+
+union cvmx_npi_msi_rcv {
+	uint64_t u64;
+	struct cvmx_npi_msi_rcv_s {
+		uint64_t int_vec:64;
+	} s;
+	struct cvmx_npi_msi_rcv_s cn30xx;
+	struct cvmx_npi_msi_rcv_s cn31xx;
+	struct cvmx_npi_msi_rcv_s cn38xx;
+	struct cvmx_npi_msi_rcv_s cn38xxp2;
+	struct cvmx_npi_msi_rcv_s cn50xx;
+	struct cvmx_npi_msi_rcv_s cn58xx;
+	struct cvmx_npi_msi_rcv_s cn58xxp1;
+};
+
+union cvmx_npi_num_desc_outputx {
+	uint64_t u64;
+	struct cvmx_npi_num_desc_outputx_s {
+		uint64_t reserved_32_63:32;
+		uint64_t size:32;
+	} s;
+	struct cvmx_npi_num_desc_outputx_s cn30xx;
+	struct cvmx_npi_num_desc_outputx_s cn31xx;
+	struct cvmx_npi_num_desc_outputx_s cn38xx;
+	struct cvmx_npi_num_desc_outputx_s cn38xxp2;
+	struct cvmx_npi_num_desc_outputx_s cn50xx;
+	struct cvmx_npi_num_desc_outputx_s cn58xx;
+	struct cvmx_npi_num_desc_outputx_s cn58xxp1;
+};
+
+union cvmx_npi_output_control {
+	uint64_t u64;
+	struct cvmx_npi_output_control_s {
+		uint64_t reserved_49_63:15;
+		uint64_t pkt_rr:1;
+		uint64_t p3_bmode:1;
+		uint64_t p2_bmode:1;
+		uint64_t p1_bmode:1;
+		uint64_t p0_bmode:1;
+		uint64_t o3_es:2;
+		uint64_t o3_ns:1;
+		uint64_t o3_ro:1;
+		uint64_t o2_es:2;
+		uint64_t o2_ns:1;
+		uint64_t o2_ro:1;
+		uint64_t o1_es:2;
+		uint64_t o1_ns:1;
+		uint64_t o1_ro:1;
+		uint64_t o0_es:2;
+		uint64_t o0_ns:1;
+		uint64_t o0_ro:1;
+		uint64_t o3_csrm:1;
+		uint64_t o2_csrm:1;
+		uint64_t o1_csrm:1;
+		uint64_t o0_csrm:1;
+		uint64_t reserved_20_23:4;
+		uint64_t iptr_o3:1;
+		uint64_t iptr_o2:1;
+		uint64_t iptr_o1:1;
+		uint64_t iptr_o0:1;
+		uint64_t esr_sl3:2;
+		uint64_t nsr_sl3:1;
+		uint64_t ror_sl3:1;
+		uint64_t esr_sl2:2;
+		uint64_t nsr_sl2:1;
+		uint64_t ror_sl2:1;
+		uint64_t esr_sl1:2;
+		uint64_t nsr_sl1:1;
+		uint64_t ror_sl1:1;
+		uint64_t esr_sl0:2;
+		uint64_t nsr_sl0:1;
+		uint64_t ror_sl0:1;
+	} s;
+	struct cvmx_npi_output_control_cn30xx {
+		uint64_t reserved_45_63:19;
+		uint64_t p0_bmode:1;
+		uint64_t reserved_32_43:12;
+		uint64_t o0_es:2;
+		uint64_t o0_ns:1;
+		uint64_t o0_ro:1;
+		uint64_t reserved_25_27:3;
+		uint64_t o0_csrm:1;
+		uint64_t reserved_17_23:7;
+		uint64_t iptr_o0:1;
+		uint64_t reserved_4_15:12;
+		uint64_t esr_sl0:2;
+		uint64_t nsr_sl0:1;
+		uint64_t ror_sl0:1;
+	} cn30xx;
+	struct cvmx_npi_output_control_cn31xx {
+		uint64_t reserved_46_63:18;
+		uint64_t p1_bmode:1;
+		uint64_t p0_bmode:1;
+		uint64_t reserved_36_43:8;
+		uint64_t o1_es:2;
+		uint64_t o1_ns:1;
+		uint64_t o1_ro:1;
+		uint64_t o0_es:2;
+		uint64_t o0_ns:1;
+		uint64_t o0_ro:1;
+		uint64_t reserved_26_27:2;
+		uint64_t o1_csrm:1;
+		uint64_t o0_csrm:1;
+		uint64_t reserved_18_23:6;
+		uint64_t iptr_o1:1;
+		uint64_t iptr_o0:1;
+		uint64_t reserved_8_15:8;
+		uint64_t esr_sl1:2;
+		uint64_t nsr_sl1:1;
+		uint64_t ror_sl1:1;
+		uint64_t esr_sl0:2;
+		uint64_t nsr_sl0:1;
+		uint64_t ror_sl0:1;
+	} cn31xx;
+	struct cvmx_npi_output_control_s cn38xx;
+	struct cvmx_npi_output_control_cn38xxp2 {
+		uint64_t reserved_48_63:16;
+		uint64_t p3_bmode:1;
+		uint64_t p2_bmode:1;
+		uint64_t p1_bmode:1;
+		uint64_t p0_bmode:1;
+		uint64_t o3_es:2;
+		uint64_t o3_ns:1;
+		uint64_t o3_ro:1;
+		uint64_t o2_es:2;
+		uint64_t o2_ns:1;
+		uint64_t o2_ro:1;
+		uint64_t o1_es:2;
+		uint64_t o1_ns:1;
+		uint64_t o1_ro:1;
+		uint64_t o0_es:2;
+		uint64_t o0_ns:1;
+		uint64_t o0_ro:1;
+		uint64_t o3_csrm:1;
+		uint64_t o2_csrm:1;
+		uint64_t o1_csrm:1;
+		uint64_t o0_csrm:1;
+		uint64_t reserved_20_23:4;
+		uint64_t iptr_o3:1;
+		uint64_t iptr_o2:1;
+		uint64_t iptr_o1:1;
+		uint64_t iptr_o0:1;
+		uint64_t esr_sl3:2;
+		uint64_t nsr_sl3:1;
+		uint64_t ror_sl3:1;
+		uint64_t esr_sl2:2;
+		uint64_t nsr_sl2:1;
+		uint64_t ror_sl2:1;
+		uint64_t esr_sl1:2;
+		uint64_t nsr_sl1:1;
+		uint64_t ror_sl1:1;
+		uint64_t esr_sl0:2;
+		uint64_t nsr_sl0:1;
+		uint64_t ror_sl0:1;
+	} cn38xxp2;
+	struct cvmx_npi_output_control_cn50xx {
+		uint64_t reserved_49_63:15;
+		uint64_t pkt_rr:1;
+		uint64_t reserved_46_47:2;
+		uint64_t p1_bmode:1;
+		uint64_t p0_bmode:1;
+		uint64_t reserved_36_43:8;
+		uint64_t o1_es:2;
+		uint64_t o1_ns:1;
+		uint64_t o1_ro:1;
+		uint64_t o0_es:2;
+		uint64_t o0_ns:1;
+		uint64_t o0_ro:1;
+		uint64_t reserved_26_27:2;
+		uint64_t o1_csrm:1;
+		uint64_t o0_csrm:1;
+		uint64_t reserved_18_23:6;
+		uint64_t iptr_o1:1;
+		uint64_t iptr_o0:1;
+		uint64_t reserved_8_15:8;
+		uint64_t esr_sl1:2;
+		uint64_t nsr_sl1:1;
+		uint64_t ror_sl1:1;
+		uint64_t esr_sl0:2;
+		uint64_t nsr_sl0:1;
+		uint64_t ror_sl0:1;
+	} cn50xx;
+	struct cvmx_npi_output_control_s cn58xx;
+	struct cvmx_npi_output_control_s cn58xxp1;
+};
+
+union cvmx_npi_px_dbpair_addr {
+	uint64_t u64;
+	struct cvmx_npi_px_dbpair_addr_s {
+		uint64_t reserved_63_63:1;
+		uint64_t state:2;
+		uint64_t naddr:61;
+	} s;
+	struct cvmx_npi_px_dbpair_addr_s cn30xx;
+	struct cvmx_npi_px_dbpair_addr_s cn31xx;
+	struct cvmx_npi_px_dbpair_addr_s cn38xx;
+	struct cvmx_npi_px_dbpair_addr_s cn38xxp2;
+	struct cvmx_npi_px_dbpair_addr_s cn50xx;
+	struct cvmx_npi_px_dbpair_addr_s cn58xx;
+	struct cvmx_npi_px_dbpair_addr_s cn58xxp1;
+};
+
+union cvmx_npi_px_instr_addr {
+	uint64_t u64;
+	struct cvmx_npi_px_instr_addr_s {
+		uint64_t state:3;
+		uint64_t naddr:61;
+	} s;
+	struct cvmx_npi_px_instr_addr_s cn30xx;
+	struct cvmx_npi_px_instr_addr_s cn31xx;
+	struct cvmx_npi_px_instr_addr_s cn38xx;
+	struct cvmx_npi_px_instr_addr_s cn38xxp2;
+	struct cvmx_npi_px_instr_addr_s cn50xx;
+	struct cvmx_npi_px_instr_addr_s cn58xx;
+	struct cvmx_npi_px_instr_addr_s cn58xxp1;
+};
+
+union cvmx_npi_px_instr_cnts {
+	uint64_t u64;
+	struct cvmx_npi_px_instr_cnts_s {
+		uint64_t reserved_38_63:26;
+		uint64_t fcnt:6;
+		uint64_t avail:32;
+	} s;
+	struct cvmx_npi_px_instr_cnts_s cn30xx;
+	struct cvmx_npi_px_instr_cnts_s cn31xx;
+	struct cvmx_npi_px_instr_cnts_s cn38xx;
+	struct cvmx_npi_px_instr_cnts_s cn38xxp2;
+	struct cvmx_npi_px_instr_cnts_s cn50xx;
+	struct cvmx_npi_px_instr_cnts_s cn58xx;
+	struct cvmx_npi_px_instr_cnts_s cn58xxp1;
+};
+
+union cvmx_npi_px_pair_cnts {
+	uint64_t u64;
+	struct cvmx_npi_px_pair_cnts_s {
+		uint64_t reserved_37_63:27;
+		uint64_t fcnt:5;
+		uint64_t avail:32;
+	} s;
+	struct cvmx_npi_px_pair_cnts_s cn30xx;
+	struct cvmx_npi_px_pair_cnts_s cn31xx;
+	struct cvmx_npi_px_pair_cnts_s cn38xx;
+	struct cvmx_npi_px_pair_cnts_s cn38xxp2;
+	struct cvmx_npi_px_pair_cnts_s cn50xx;
+	struct cvmx_npi_px_pair_cnts_s cn58xx;
+	struct cvmx_npi_px_pair_cnts_s cn58xxp1;
+};
+
+union cvmx_npi_pci_burst_size {
+	uint64_t u64;
+	struct cvmx_npi_pci_burst_size_s {
+		uint64_t reserved_14_63:50;
+		uint64_t wr_brst:7;
+		uint64_t rd_brst:7;
+	} s;
+	struct cvmx_npi_pci_burst_size_s cn30xx;
+	struct cvmx_npi_pci_burst_size_s cn31xx;
+	struct cvmx_npi_pci_burst_size_s cn38xx;
+	struct cvmx_npi_pci_burst_size_s cn38xxp2;
+	struct cvmx_npi_pci_burst_size_s cn50xx;
+	struct cvmx_npi_pci_burst_size_s cn58xx;
+	struct cvmx_npi_pci_burst_size_s cn58xxp1;
+};
+
+union cvmx_npi_pci_int_arb_cfg {
+	uint64_t u64;
+	struct cvmx_npi_pci_int_arb_cfg_s {
+		uint64_t reserved_13_63:51;
+		uint64_t hostmode:1;
+		uint64_t pci_ovr:4;
+		uint64_t reserved_5_7:3;
+		uint64_t en:1;
+		uint64_t park_mod:1;
+		uint64_t park_dev:3;
+	} s;
+	struct cvmx_npi_pci_int_arb_cfg_cn30xx {
+		uint64_t reserved_5_63:59;
+		uint64_t en:1;
+		uint64_t park_mod:1;
+		uint64_t park_dev:3;
+	} cn30xx;
+	struct cvmx_npi_pci_int_arb_cfg_cn30xx cn31xx;
+	struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xx;
+	struct cvmx_npi_pci_int_arb_cfg_cn30xx cn38xxp2;
+	struct cvmx_npi_pci_int_arb_cfg_s cn50xx;
+	struct cvmx_npi_pci_int_arb_cfg_s cn58xx;
+	struct cvmx_npi_pci_int_arb_cfg_s cn58xxp1;
+};
+
+union cvmx_npi_pci_read_cmd {
+	uint64_t u64;
+	struct cvmx_npi_pci_read_cmd_s {
+		uint64_t reserved_11_63:53;
+		uint64_t cmd_size:11;
+	} s;
+	struct cvmx_npi_pci_read_cmd_s cn30xx;
+	struct cvmx_npi_pci_read_cmd_s cn31xx;
+	struct cvmx_npi_pci_read_cmd_s cn38xx;
+	struct cvmx_npi_pci_read_cmd_s cn38xxp2;
+	struct cvmx_npi_pci_read_cmd_s cn50xx;
+	struct cvmx_npi_pci_read_cmd_s cn58xx;
+	struct cvmx_npi_pci_read_cmd_s cn58xxp1;
+};
+
+union cvmx_npi_port32_instr_hdr {
+	uint64_t u64;
+	struct cvmx_npi_port32_instr_hdr_s {
+		uint64_t reserved_44_63:20;
+		uint64_t pbp:1;
+		uint64_t rsv_f:5;
+		uint64_t rparmode:2;
+		uint64_t rsv_e:1;
+		uint64_t rskp_len:7;
+		uint64_t rsv_d:6;
+		uint64_t use_ihdr:1;
+		uint64_t rsv_c:5;
+		uint64_t par_mode:2;
+		uint64_t rsv_b:1;
+		uint64_t skp_len:7;
+		uint64_t rsv_a:6;
+	} s;
+	struct cvmx_npi_port32_instr_hdr_s cn30xx;
+	struct cvmx_npi_port32_instr_hdr_s cn31xx;
+	struct cvmx_npi_port32_instr_hdr_s cn38xx;
+	struct cvmx_npi_port32_instr_hdr_s cn38xxp2;
+	struct cvmx_npi_port32_instr_hdr_s cn50xx;
+	struct cvmx_npi_port32_instr_hdr_s cn58xx;
+	struct cvmx_npi_port32_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port33_instr_hdr {
+	uint64_t u64;
+	struct cvmx_npi_port33_instr_hdr_s {
+		uint64_t reserved_44_63:20;
+		uint64_t pbp:1;
+		uint64_t rsv_f:5;
+		uint64_t rparmode:2;
+		uint64_t rsv_e:1;
+		uint64_t rskp_len:7;
+		uint64_t rsv_d:6;
+		uint64_t use_ihdr:1;
+		uint64_t rsv_c:5;
+		uint64_t par_mode:2;
+		uint64_t rsv_b:1;
+		uint64_t skp_len:7;
+		uint64_t rsv_a:6;
+	} s;
+	struct cvmx_npi_port33_instr_hdr_s cn31xx;
+	struct cvmx_npi_port33_instr_hdr_s cn38xx;
+	struct cvmx_npi_port33_instr_hdr_s cn38xxp2;
+	struct cvmx_npi_port33_instr_hdr_s cn50xx;
+	struct cvmx_npi_port33_instr_hdr_s cn58xx;
+	struct cvmx_npi_port33_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port34_instr_hdr {
+	uint64_t u64;
+	struct cvmx_npi_port34_instr_hdr_s {
+		uint64_t reserved_44_63:20;
+		uint64_t pbp:1;
+		uint64_t rsv_f:5;
+		uint64_t rparmode:2;
+		uint64_t rsv_e:1;
+		uint64_t rskp_len:7;
+		uint64_t rsv_d:6;
+		uint64_t use_ihdr:1;
+		uint64_t rsv_c:5;
+		uint64_t par_mode:2;
+		uint64_t rsv_b:1;
+		uint64_t skp_len:7;
+		uint64_t rsv_a:6;
+	} s;
+	struct cvmx_npi_port34_instr_hdr_s cn38xx;
+	struct cvmx_npi_port34_instr_hdr_s cn38xxp2;
+	struct cvmx_npi_port34_instr_hdr_s cn58xx;
+	struct cvmx_npi_port34_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port35_instr_hdr {
+	uint64_t u64;
+	struct cvmx_npi_port35_instr_hdr_s {
+		uint64_t reserved_44_63:20;
+		uint64_t pbp:1;
+		uint64_t rsv_f:5;
+		uint64_t rparmode:2;
+		uint64_t rsv_e:1;
+		uint64_t rskp_len:7;
+		uint64_t rsv_d:6;
+		uint64_t use_ihdr:1;
+		uint64_t rsv_c:5;
+		uint64_t par_mode:2;
+		uint64_t rsv_b:1;
+		uint64_t skp_len:7;
+		uint64_t rsv_a:6;
+	} s;
+	struct cvmx_npi_port35_instr_hdr_s cn38xx;
+	struct cvmx_npi_port35_instr_hdr_s cn38xxp2;
+	struct cvmx_npi_port35_instr_hdr_s cn58xx;
+	struct cvmx_npi_port35_instr_hdr_s cn58xxp1;
+};
+
+union cvmx_npi_port_bp_control {
+	uint64_t u64;
+	struct cvmx_npi_port_bp_control_s {
+		uint64_t reserved_8_63:56;
+		uint64_t bp_on:4;
+		uint64_t enb:4;
+	} s;
+	struct cvmx_npi_port_bp_control_s cn30xx;
+	struct cvmx_npi_port_bp_control_s cn31xx;
+	struct cvmx_npi_port_bp_control_s cn38xx;
+	struct cvmx_npi_port_bp_control_s cn38xxp2;
+	struct cvmx_npi_port_bp_control_s cn50xx;
+	struct cvmx_npi_port_bp_control_s cn58xx;
+	struct cvmx_npi_port_bp_control_s cn58xxp1;
+};
+
+union cvmx_npi_rsl_int_blocks {
+	uint64_t u64;
+	struct cvmx_npi_rsl_int_blocks_s {
+		uint64_t reserved_32_63:32;
+		uint64_t rint_31:1;
+		uint64_t iob:1;
+		uint64_t reserved_28_29:2;
+		uint64_t rint_27:1;
+		uint64_t rint_26:1;
+		uint64_t rint_25:1;
+		uint64_t rint_24:1;
+		uint64_t asx1:1;
+		uint64_t asx0:1;
+		uint64_t rint_21:1;
+		uint64_t pip:1;
+		uint64_t spx1:1;
+		uint64_t spx0:1;
+		uint64_t lmc:1;
+		uint64_t l2c:1;
+		uint64_t rint_15:1;
+		uint64_t reserved_13_14:2;
+		uint64_t pow:1;
+		uint64_t tim:1;
+		uint64_t pko:1;
+		uint64_t ipd:1;
+		uint64_t rint_8:1;
+		uint64_t zip:1;
+		uint64_t dfa:1;
+		uint64_t fpa:1;
+		uint64_t key:1;
+		uint64_t npi:1;
+		uint64_t gmx1:1;
+		uint64_t gmx0:1;
+		uint64_t mio:1;
+	} s;
+	struct cvmx_npi_rsl_int_blocks_cn30xx {
+		uint64_t reserved_32_63:32;
+		uint64_t rint_31:1;
+		uint64_t iob:1;
+		uint64_t rint_29:1;
+		uint64_t rint_28:1;
+		uint64_t rint_27:1;
+		uint64_t rint_26:1;
+		uint64_t rint_25:1;
+		uint64_t rint_24:1;
+		uint64_t asx1:1;
+		uint64_t asx0:1;
+		uint64_t rint_21:1;
+		uint64_t pip:1;
+		uint64_t spx1:1;
+		uint64_t spx0:1;
+		uint64_t lmc:1;
+		uint64_t l2c:1;
+		uint64_t rint_15:1;
+		uint64_t rint_14:1;
+		uint64_t usb:1;
+		uint64_t pow:1;
+		uint64_t tim:1;
+		uint64_t pko:1;
+		uint64_t ipd:1;
+		uint64_t rint_8:1;
+		uint64_t zip:1;
+		uint64_t dfa:1;
+		uint64_t fpa:1;
+		uint64_t key:1;
+		uint64_t npi:1;
+		uint64_t gmx1:1;
+		uint64_t gmx0:1;
+		uint64_t mio:1;
+	} cn30xx;
+	struct cvmx_npi_rsl_int_blocks_cn30xx cn31xx;
+	struct cvmx_npi_rsl_int_blocks_cn38xx {
+		uint64_t reserved_32_63:32;
+		uint64_t rint_31:1;
+		uint64_t iob:1;
+		uint64_t rint_29:1;
+		uint64_t rint_28:1;
+		uint64_t rint_27:1;
+		uint64_t rint_26:1;
+		uint64_t rint_25:1;
+		uint64_t rint_24:1;
+		uint64_t asx1:1;
+		uint64_t asx0:1;
+		uint64_t rint_21:1;
+		uint64_t pip:1;
+		uint64_t spx1:1;
+		uint64_t spx0:1;
+		uint64_t lmc:1;
+		uint64_t l2c:1;
+		uint64_t rint_15:1;
+		uint64_t rint_14:1;
+		uint64_t rint_13:1;
+		uint64_t pow:1;
+		uint64_t tim:1;
+		uint64_t pko:1;
+		uint64_t ipd:1;
+		uint64_t rint_8:1;
+		uint64_t zip:1;
+		uint64_t dfa:1;
+		uint64_t fpa:1;
+		uint64_t key:1;
+		uint64_t npi:1;
+		uint64_t gmx1:1;
+		uint64_t gmx0:1;
+		uint64_t mio:1;
+	} cn38xx;
+	struct cvmx_npi_rsl_int_blocks_cn38xx cn38xxp2;
+	struct cvmx_npi_rsl_int_blocks_cn50xx {
+		uint64_t reserved_31_63:33;
+		uint64_t iob:1;
+		uint64_t lmc1:1;
+		uint64_t agl:1;
+		uint64_t reserved_24_27:4;
+		uint64_t asx1:1;
+		uint64_t asx0:1;
+		uint64_t reserved_21_21:1;
+		uint64_t pip:1;
+		uint64_t spx1:1;
+		uint64_t spx0:1;
+		uint64_t lmc:1;
+		uint64_t l2c:1;
+		uint64_t reserved_15_15:1;
+		uint64_t rad:1;
+		uint64_t usb:1;
+		uint64_t pow:1;
+		uint64_t tim:1;
+		uint64_t pko:1;
+		uint64_t ipd:1;
+		uint64_t reserved_8_8:1;
+		uint64_t zip:1;
+		uint64_t dfa:1;
+		uint64_t fpa:1;
+		uint64_t key:1;
+		uint64_t npi:1;
+		uint64_t gmx1:1;
+		uint64_t gmx0:1;
+		uint64_t mio:1;
+	} cn50xx;
+	struct cvmx_npi_rsl_int_blocks_cn38xx cn58xx;
+	struct cvmx_npi_rsl_int_blocks_cn38xx cn58xxp1;
+};
+
+union cvmx_npi_size_inputx {
+	uint64_t u64;
+	struct cvmx_npi_size_inputx_s {
+		uint64_t reserved_32_63:32;
+		uint64_t size:32;
+	} s;
+	struct cvmx_npi_size_inputx_s cn30xx;
+	struct cvmx_npi_size_inputx_s cn31xx;
+	struct cvmx_npi_size_inputx_s cn38xx;
+	struct cvmx_npi_size_inputx_s cn38xxp2;
+	struct cvmx_npi_size_inputx_s cn50xx;
+	struct cvmx_npi_size_inputx_s cn58xx;
+	struct cvmx_npi_size_inputx_s cn58xxp1;
+};
+
+union cvmx_npi_win_read_to {
+	uint64_t u64;
+	struct cvmx_npi_win_read_to_s {
+		uint64_t reserved_32_63:32;
+		uint64_t time:32;
+	} s;
+	struct cvmx_npi_win_read_to_s cn30xx;
+	struct cvmx_npi_win_read_to_s cn31xx;
+	struct cvmx_npi_win_read_to_s cn38xx;
+	struct cvmx_npi_win_read_to_s cn38xxp2;
+	struct cvmx_npi_win_read_to_s cn50xx;
+	struct cvmx_npi_win_read_to_s cn58xx;
+	struct cvmx_npi_win_read_to_s cn58xxp1;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pci-defs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pci-defs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pci-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pci-defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1645 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PCI_DEFS_H__
+#define __CVMX_PCI_DEFS_H__
+
+#define CVMX_PCI_BAR1_INDEXX(offset) \
+	 (0x0000000000000100ull + (((offset) & 31) * 4))
+#define CVMX_PCI_BIST_REG \
+	 (0x00000000000001C0ull)
+#define CVMX_PCI_CFG00 \
+	 (0x0000000000000000ull)
+#define CVMX_PCI_CFG01 \
+	 (0x0000000000000004ull)
+#define CVMX_PCI_CFG02 \
+	 (0x0000000000000008ull)
+#define CVMX_PCI_CFG03 \
+	 (0x000000000000000Cull)
+#define CVMX_PCI_CFG04 \
+	 (0x0000000000000010ull)
+#define CVMX_PCI_CFG05 \
+	 (0x0000000000000014ull)
+#define CVMX_PCI_CFG06 \
+	 (0x0000000000000018ull)
+#define CVMX_PCI_CFG07 \
+	 (0x000000000000001Cull)
+#define CVMX_PCI_CFG08 \
+	 (0x0000000000000020ull)
+#define CVMX_PCI_CFG09 \
+	 (0x0000000000000024ull)
+#define CVMX_PCI_CFG10 \
+	 (0x0000000000000028ull)
+#define CVMX_PCI_CFG11 \
+	 (0x000000000000002Cull)
+#define CVMX_PCI_CFG12 \
+	 (0x0000000000000030ull)
+#define CVMX_PCI_CFG13 \
+	 (0x0000000000000034ull)
+#define CVMX_PCI_CFG15 \
+	 (0x000000000000003Cull)
+#define CVMX_PCI_CFG16 \
+	 (0x0000000000000040ull)
+#define CVMX_PCI_CFG17 \
+	 (0x0000000000000044ull)
+#define CVMX_PCI_CFG18 \
+	 (0x0000000000000048ull)
+#define CVMX_PCI_CFG19 \
+	 (0x000000000000004Cull)
+#define CVMX_PCI_CFG20 \
+	 (0x0000000000000050ull)
+#define CVMX_PCI_CFG21 \
+	 (0x0000000000000054ull)
+#define CVMX_PCI_CFG22 \
+	 (0x0000000000000058ull)
+#define CVMX_PCI_CFG56 \
+	 (0x00000000000000E0ull)
+#define CVMX_PCI_CFG57 \
+	 (0x00000000000000E4ull)
+#define CVMX_PCI_CFG58 \
+	 (0x00000000000000E8ull)
+#define CVMX_PCI_CFG59 \
+	 (0x00000000000000ECull)
+#define CVMX_PCI_CFG60 \
+	 (0x00000000000000F0ull)
+#define CVMX_PCI_CFG61 \
+	 (0x00000000000000F4ull)
+#define CVMX_PCI_CFG62 \
+	 (0x00000000000000F8ull)
+#define CVMX_PCI_CFG63 \
+	 (0x00000000000000FCull)
+#define CVMX_PCI_CNT_REG \
+	 (0x00000000000001B8ull)
+#define CVMX_PCI_CTL_STATUS_2 \
+	 (0x000000000000018Cull)
+#define CVMX_PCI_DBELL_0 \
+	 (0x0000000000000080ull)
+#define CVMX_PCI_DBELL_1 \
+	 (0x0000000000000088ull)
+#define CVMX_PCI_DBELL_2 \
+	 (0x0000000000000090ull)
+#define CVMX_PCI_DBELL_3 \
+	 (0x0000000000000098ull)
+#define CVMX_PCI_DBELL_X(offset) \
+	 (0x0000000000000080ull + (((offset) & 3) * 8))
+#define CVMX_PCI_DMA_CNT0 \
+	 (0x00000000000000A0ull)
+#define CVMX_PCI_DMA_CNT1 \
+	 (0x00000000000000A8ull)
+#define CVMX_PCI_DMA_CNTX(offset) \
+	 (0x00000000000000A0ull + (((offset) & 1) * 8))
+#define CVMX_PCI_DMA_INT_LEV0 \
+	 (0x00000000000000A4ull)
+#define CVMX_PCI_DMA_INT_LEV1 \
+	 (0x00000000000000ACull)
+#define CVMX_PCI_DMA_INT_LEVX(offset) \
+	 (0x00000000000000A4ull + (((offset) & 1) * 8))
+#define CVMX_PCI_DMA_TIME0 \
+	 (0x00000000000000B0ull)
+#define CVMX_PCI_DMA_TIME1 \
+	 (0x00000000000000B4ull)
+#define CVMX_PCI_DMA_TIMEX(offset) \
+	 (0x00000000000000B0ull + (((offset) & 1) * 4))
+#define CVMX_PCI_INSTR_COUNT0 \
+	 (0x0000000000000084ull)
+#define CVMX_PCI_INSTR_COUNT1 \
+	 (0x000000000000008Cull)
+#define CVMX_PCI_INSTR_COUNT2 \
+	 (0x0000000000000094ull)
+#define CVMX_PCI_INSTR_COUNT3 \
+	 (0x000000000000009Cull)
+#define CVMX_PCI_INSTR_COUNTX(offset) \
+	 (0x0000000000000084ull + (((offset) & 3) * 8))
+#define CVMX_PCI_INT_ENB \
+	 (0x0000000000000038ull)
+#define CVMX_PCI_INT_ENB2 \
+	 (0x00000000000001A0ull)
+#define CVMX_PCI_INT_SUM \
+	 (0x0000000000000030ull)
+#define CVMX_PCI_INT_SUM2 \
+	 (0x0000000000000198ull)
+#define CVMX_PCI_MSI_RCV \
+	 (0x00000000000000F0ull)
+#define CVMX_PCI_PKTS_SENT0 \
+	 (0x0000000000000040ull)
+#define CVMX_PCI_PKTS_SENT1 \
+	 (0x0000000000000050ull)
+#define CVMX_PCI_PKTS_SENT2 \
+	 (0x0000000000000060ull)
+#define CVMX_PCI_PKTS_SENT3 \
+	 (0x0000000000000070ull)
+#define CVMX_PCI_PKTS_SENTX(offset) \
+	 (0x0000000000000040ull + (((offset) & 3) * 16))
+#define CVMX_PCI_PKTS_SENT_INT_LEV0 \
+	 (0x0000000000000048ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEV1 \
+	 (0x0000000000000058ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEV2 \
+	 (0x0000000000000068ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEV3 \
+	 (0x0000000000000078ull)
+#define CVMX_PCI_PKTS_SENT_INT_LEVX(offset) \
+	 (0x0000000000000048ull + (((offset) & 3) * 16))
+#define CVMX_PCI_PKTS_SENT_TIME0 \
+	 (0x000000000000004Cull)
+#define CVMX_PCI_PKTS_SENT_TIME1 \
+	 (0x000000000000005Cull)
+#define CVMX_PCI_PKTS_SENT_TIME2 \
+	 (0x000000000000006Cull)
+#define CVMX_PCI_PKTS_SENT_TIME3 \
+	 (0x000000000000007Cull)
+#define CVMX_PCI_PKTS_SENT_TIMEX(offset) \
+	 (0x000000000000004Cull + (((offset) & 3) * 16))
+#define CVMX_PCI_PKT_CREDITS0 \
+	 (0x0000000000000044ull)
+#define CVMX_PCI_PKT_CREDITS1 \
+	 (0x0000000000000054ull)
+#define CVMX_PCI_PKT_CREDITS2 \
+	 (0x0000000000000064ull)
+#define CVMX_PCI_PKT_CREDITS3 \
+	 (0x0000000000000074ull)
+#define CVMX_PCI_PKT_CREDITSX(offset) \
+	 (0x0000000000000044ull + (((offset) & 3) * 16))
+#define CVMX_PCI_READ_CMD_6 \
+	 (0x0000000000000180ull)
+#define CVMX_PCI_READ_CMD_C \
+	 (0x0000000000000184ull)
+#define CVMX_PCI_READ_CMD_E \
+	 (0x0000000000000188ull)
+#define CVMX_PCI_READ_TIMEOUT \
+	 CVMX_ADD_IO_SEG(0x00011F00000000B0ull)
+#define CVMX_PCI_SCM_REG \
+	 (0x00000000000001A8ull)
+#define CVMX_PCI_TSR_REG \
+	 (0x00000000000001B0ull)
+#define CVMX_PCI_WIN_RD_ADDR \
+	 (0x0000000000000008ull)
+#define CVMX_PCI_WIN_RD_DATA \
+	 (0x0000000000000020ull)
+#define CVMX_PCI_WIN_WR_ADDR \
+	 (0x0000000000000000ull)
+#define CVMX_PCI_WIN_WR_DATA \
+	 (0x0000000000000010ull)
+#define CVMX_PCI_WIN_WR_MASK \
+	 (0x0000000000000018ull)
+
+union cvmx_pci_bar1_indexx {
+	uint32_t u32;
+	struct cvmx_pci_bar1_indexx_s {
+		uint32_t reserved_18_31:14;
+		uint32_t addr_idx:14;
+		uint32_t ca:1;
+		uint32_t end_swp:2;
+		uint32_t addr_v:1;
+	} s;
+	struct cvmx_pci_bar1_indexx_s cn30xx;
+	struct cvmx_pci_bar1_indexx_s cn31xx;
+	struct cvmx_pci_bar1_indexx_s cn38xx;
+	struct cvmx_pci_bar1_indexx_s cn38xxp2;
+	struct cvmx_pci_bar1_indexx_s cn50xx;
+	struct cvmx_pci_bar1_indexx_s cn58xx;
+	struct cvmx_pci_bar1_indexx_s cn58xxp1;
+};
+
+union cvmx_pci_bist_reg {
+	uint64_t u64;
+	struct cvmx_pci_bist_reg_s {
+		uint64_t reserved_10_63:54;
+		uint64_t rsp_bs:1;
+		uint64_t dma0_bs:1;
+		uint64_t cmd0_bs:1;
+		uint64_t cmd_bs:1;
+		uint64_t csr2p_bs:1;
+		uint64_t csrr_bs:1;
+		uint64_t rsp2p_bs:1;
+		uint64_t csr2n_bs:1;
+		uint64_t dat2n_bs:1;
+		uint64_t dbg2n_bs:1;
+	} s;
+	struct cvmx_pci_bist_reg_s cn50xx;
+};
+
+union cvmx_pci_cfg00 {
+	uint32_t u32;
+	struct cvmx_pci_cfg00_s {
+		uint32_t devid:16;
+		uint32_t vendid:16;
+	} s;
+	struct cvmx_pci_cfg00_s cn30xx;
+	struct cvmx_pci_cfg00_s cn31xx;
+	struct cvmx_pci_cfg00_s cn38xx;
+	struct cvmx_pci_cfg00_s cn38xxp2;
+	struct cvmx_pci_cfg00_s cn50xx;
+	struct cvmx_pci_cfg00_s cn58xx;
+	struct cvmx_pci_cfg00_s cn58xxp1;
+};
+
+union cvmx_pci_cfg01 {
+	uint32_t u32;
+	struct cvmx_pci_cfg01_s {
+		uint32_t dpe:1;
+		uint32_t sse:1;
+		uint32_t rma:1;
+		uint32_t rta:1;
+		uint32_t sta:1;
+		uint32_t devt:2;
+		uint32_t mdpe:1;
+		uint32_t fbb:1;
+		uint32_t reserved_22_22:1;
+		uint32_t m66:1;
+		uint32_t cle:1;
+		uint32_t i_stat:1;
+		uint32_t reserved_11_18:8;
+		uint32_t i_dis:1;
+		uint32_t fbbe:1;
+		uint32_t see:1;
+		uint32_t ads:1;
+		uint32_t pee:1;
+		uint32_t vps:1;
+		uint32_t mwice:1;
+		uint32_t scse:1;
+		uint32_t me:1;
+		uint32_t msae:1;
+		uint32_t isae:1;
+	} s;
+	struct cvmx_pci_cfg01_s cn30xx;
+	struct cvmx_pci_cfg01_s cn31xx;
+	struct cvmx_pci_cfg01_s cn38xx;
+	struct cvmx_pci_cfg01_s cn38xxp2;
+	struct cvmx_pci_cfg01_s cn50xx;
+	struct cvmx_pci_cfg01_s cn58xx;
+	struct cvmx_pci_cfg01_s cn58xxp1;
+};
+
+union cvmx_pci_cfg02 {
+	uint32_t u32;
+	struct cvmx_pci_cfg02_s {
+		uint32_t cc:24;
+		uint32_t rid:8;
+	} s;
+	struct cvmx_pci_cfg02_s cn30xx;
+	struct cvmx_pci_cfg02_s cn31xx;
+	struct cvmx_pci_cfg02_s cn38xx;
+	struct cvmx_pci_cfg02_s cn38xxp2;
+	struct cvmx_pci_cfg02_s cn50xx;
+	struct cvmx_pci_cfg02_s cn58xx;
+	struct cvmx_pci_cfg02_s cn58xxp1;
+};
+
+union cvmx_pci_cfg03 {
+	uint32_t u32;
+	struct cvmx_pci_cfg03_s {
+		uint32_t bcap:1;
+		uint32_t brb:1;
+		uint32_t reserved_28_29:2;
+		uint32_t bcod:4;
+		uint32_t ht:8;
+		uint32_t lt:8;
+		uint32_t cls:8;
+	} s;
+	struct cvmx_pci_cfg03_s cn30xx;
+	struct cvmx_pci_cfg03_s cn31xx;
+	struct cvmx_pci_cfg03_s cn38xx;
+	struct cvmx_pci_cfg03_s cn38xxp2;
+	struct cvmx_pci_cfg03_s cn50xx;
+	struct cvmx_pci_cfg03_s cn58xx;
+	struct cvmx_pci_cfg03_s cn58xxp1;
+};
+
+union cvmx_pci_cfg04 {
+	uint32_t u32;
+	struct cvmx_pci_cfg04_s {
+		uint32_t lbase:20;
+		uint32_t lbasez:8;
+		uint32_t pf:1;
+		uint32_t typ:2;
+		uint32_t mspc:1;
+	} s;
+	struct cvmx_pci_cfg04_s cn30xx;
+	struct cvmx_pci_cfg04_s cn31xx;
+	struct cvmx_pci_cfg04_s cn38xx;
+	struct cvmx_pci_cfg04_s cn38xxp2;
+	struct cvmx_pci_cfg04_s cn50xx;
+	struct cvmx_pci_cfg04_s cn58xx;
+	struct cvmx_pci_cfg04_s cn58xxp1;
+};
+
+union cvmx_pci_cfg05 {
+	uint32_t u32;
+	struct cvmx_pci_cfg05_s {
+		uint32_t hbase:32;
+	} s;
+	struct cvmx_pci_cfg05_s cn30xx;
+	struct cvmx_pci_cfg05_s cn31xx;
+	struct cvmx_pci_cfg05_s cn38xx;
+	struct cvmx_pci_cfg05_s cn38xxp2;
+	struct cvmx_pci_cfg05_s cn50xx;
+	struct cvmx_pci_cfg05_s cn58xx;
+	struct cvmx_pci_cfg05_s cn58xxp1;
+};
+
+union cvmx_pci_cfg06 {
+	uint32_t u32;
+	struct cvmx_pci_cfg06_s {
+		uint32_t lbase:5;
+		uint32_t lbasez:23;
+		uint32_t pf:1;
+		uint32_t typ:2;
+		uint32_t mspc:1;
+	} s;
+	struct cvmx_pci_cfg06_s cn30xx;
+	struct cvmx_pci_cfg06_s cn31xx;
+	struct cvmx_pci_cfg06_s cn38xx;
+	struct cvmx_pci_cfg06_s cn38xxp2;
+	struct cvmx_pci_cfg06_s cn50xx;
+	struct cvmx_pci_cfg06_s cn58xx;
+	struct cvmx_pci_cfg06_s cn58xxp1;
+};
+
+union cvmx_pci_cfg07 {
+	uint32_t u32;
+	struct cvmx_pci_cfg07_s {
+		uint32_t hbase:32;
+	} s;
+	struct cvmx_pci_cfg07_s cn30xx;
+	struct cvmx_pci_cfg07_s cn31xx;
+	struct cvmx_pci_cfg07_s cn38xx;
+	struct cvmx_pci_cfg07_s cn38xxp2;
+	struct cvmx_pci_cfg07_s cn50xx;
+	struct cvmx_pci_cfg07_s cn58xx;
+	struct cvmx_pci_cfg07_s cn58xxp1;
+};
+
+union cvmx_pci_cfg08 {
+	uint32_t u32;
+	struct cvmx_pci_cfg08_s {
+		uint32_t lbasez:28;
+		uint32_t pf:1;
+		uint32_t typ:2;
+		uint32_t mspc:1;
+	} s;
+	struct cvmx_pci_cfg08_s cn30xx;
+	struct cvmx_pci_cfg08_s cn31xx;
+	struct cvmx_pci_cfg08_s cn38xx;
+	struct cvmx_pci_cfg08_s cn38xxp2;
+	struct cvmx_pci_cfg08_s cn50xx;
+	struct cvmx_pci_cfg08_s cn58xx;
+	struct cvmx_pci_cfg08_s cn58xxp1;
+};
+
+union cvmx_pci_cfg09 {
+	uint32_t u32;
+	struct cvmx_pci_cfg09_s {
+		uint32_t hbase:25;
+		uint32_t hbasez:7;
+	} s;
+	struct cvmx_pci_cfg09_s cn30xx;
+	struct cvmx_pci_cfg09_s cn31xx;
+	struct cvmx_pci_cfg09_s cn38xx;
+	struct cvmx_pci_cfg09_s cn38xxp2;
+	struct cvmx_pci_cfg09_s cn50xx;
+	struct cvmx_pci_cfg09_s cn58xx;
+	struct cvmx_pci_cfg09_s cn58xxp1;
+};
+
+union cvmx_pci_cfg10 {
+	uint32_t u32;
+	struct cvmx_pci_cfg10_s {
+		uint32_t cisp:32;
+	} s;
+	struct cvmx_pci_cfg10_s cn30xx;
+	struct cvmx_pci_cfg10_s cn31xx;
+	struct cvmx_pci_cfg10_s cn38xx;
+	struct cvmx_pci_cfg10_s cn38xxp2;
+	struct cvmx_pci_cfg10_s cn50xx;
+	struct cvmx_pci_cfg10_s cn58xx;
+	struct cvmx_pci_cfg10_s cn58xxp1;
+};
+
+union cvmx_pci_cfg11 {
+	uint32_t u32;
+	struct cvmx_pci_cfg11_s {
+		uint32_t ssid:16;
+		uint32_t ssvid:16;
+	} s;
+	struct cvmx_pci_cfg11_s cn30xx;
+	struct cvmx_pci_cfg11_s cn31xx;
+	struct cvmx_pci_cfg11_s cn38xx;
+	struct cvmx_pci_cfg11_s cn38xxp2;
+	struct cvmx_pci_cfg11_s cn50xx;
+	struct cvmx_pci_cfg11_s cn58xx;
+	struct cvmx_pci_cfg11_s cn58xxp1;
+};
+
+union cvmx_pci_cfg12 {
+	uint32_t u32;
+	struct cvmx_pci_cfg12_s {
+		uint32_t erbar:16;
+		uint32_t erbarz:5;
+		uint32_t reserved_1_10:10;
+		uint32_t erbar_en:1;
+	} s;
+	struct cvmx_pci_cfg12_s cn30xx;
+	struct cvmx_pci_cfg12_s cn31xx;
+	struct cvmx_pci_cfg12_s cn38xx;
+	struct cvmx_pci_cfg12_s cn38xxp2;
+	struct cvmx_pci_cfg12_s cn50xx;
+	struct cvmx_pci_cfg12_s cn58xx;
+	struct cvmx_pci_cfg12_s cn58xxp1;
+};
+
+union cvmx_pci_cfg13 {
+	uint32_t u32;
+	struct cvmx_pci_cfg13_s {
+		uint32_t reserved_8_31:24;
+		uint32_t cp:8;
+	} s;
+	struct cvmx_pci_cfg13_s cn30xx;
+	struct cvmx_pci_cfg13_s cn31xx;
+	struct cvmx_pci_cfg13_s cn38xx;
+	struct cvmx_pci_cfg13_s cn38xxp2;
+	struct cvmx_pci_cfg13_s cn50xx;
+	struct cvmx_pci_cfg13_s cn58xx;
+	struct cvmx_pci_cfg13_s cn58xxp1;
+};
+
+union cvmx_pci_cfg15 {
+	uint32_t u32;
+	struct cvmx_pci_cfg15_s {
+		uint32_t ml:8;
+		uint32_t mg:8;
+		uint32_t inta:8;
+		uint32_t il:8;
+	} s;
+	struct cvmx_pci_cfg15_s cn30xx;
+	struct cvmx_pci_cfg15_s cn31xx;
+	struct cvmx_pci_cfg15_s cn38xx;
+	struct cvmx_pci_cfg15_s cn38xxp2;
+	struct cvmx_pci_cfg15_s cn50xx;
+	struct cvmx_pci_cfg15_s cn58xx;
+	struct cvmx_pci_cfg15_s cn58xxp1;
+};
+
+union cvmx_pci_cfg16 {
+	uint32_t u32;
+	struct cvmx_pci_cfg16_s {
+		uint32_t trdnpr:1;
+		uint32_t trdard:1;
+		uint32_t rdsati:1;
+		uint32_t trdrs:1;
+		uint32_t trtae:1;
+		uint32_t twsei:1;
+		uint32_t twsen:1;
+		uint32_t twtae:1;
+		uint32_t tmae:1;
+		uint32_t tslte:3;
+		uint32_t tilt:4;
+		uint32_t pbe:12;
+		uint32_t dppmr:1;
+		uint32_t reserved_2_2:1;
+		uint32_t tswc:1;
+		uint32_t mltd:1;
+	} s;
+	struct cvmx_pci_cfg16_s cn30xx;
+	struct cvmx_pci_cfg16_s cn31xx;
+	struct cvmx_pci_cfg16_s cn38xx;
+	struct cvmx_pci_cfg16_s cn38xxp2;
+	struct cvmx_pci_cfg16_s cn50xx;
+	struct cvmx_pci_cfg16_s cn58xx;
+	struct cvmx_pci_cfg16_s cn58xxp1;
+};
+
+union cvmx_pci_cfg17 {
+	uint32_t u32;
+	struct cvmx_pci_cfg17_s {
+		uint32_t tscme:32;
+	} s;
+	struct cvmx_pci_cfg17_s cn30xx;
+	struct cvmx_pci_cfg17_s cn31xx;
+	struct cvmx_pci_cfg17_s cn38xx;
+	struct cvmx_pci_cfg17_s cn38xxp2;
+	struct cvmx_pci_cfg17_s cn50xx;
+	struct cvmx_pci_cfg17_s cn58xx;
+	struct cvmx_pci_cfg17_s cn58xxp1;
+};
+
+union cvmx_pci_cfg18 {
+	uint32_t u32;
+	struct cvmx_pci_cfg18_s {
+		uint32_t tdsrps:32;
+	} s;
+	struct cvmx_pci_cfg18_s cn30xx;
+	struct cvmx_pci_cfg18_s cn31xx;
+	struct cvmx_pci_cfg18_s cn38xx;
+	struct cvmx_pci_cfg18_s cn38xxp2;
+	struct cvmx_pci_cfg18_s cn50xx;
+	struct cvmx_pci_cfg18_s cn58xx;
+	struct cvmx_pci_cfg18_s cn58xxp1;
+};
+
+union cvmx_pci_cfg19 {
+	uint32_t u32;
+	struct cvmx_pci_cfg19_s {
+		uint32_t mrbcm:1;
+		uint32_t mrbci:1;
+		uint32_t mdwe:1;
+		uint32_t mdre:1;
+		uint32_t mdrimc:1;
+		uint32_t mdrrmc:3;
+		uint32_t tmes:8;
+		uint32_t teci:1;
+		uint32_t tmei:1;
+		uint32_t tmse:1;
+		uint32_t tmdpes:1;
+		uint32_t tmapes:1;
+		uint32_t reserved_9_10:2;
+		uint32_t tibcd:1;
+		uint32_t tibde:1;
+		uint32_t reserved_6_6:1;
+		uint32_t tidomc:1;
+		uint32_t tdomc:5;
+	} s;
+	struct cvmx_pci_cfg19_s cn30xx;
+	struct cvmx_pci_cfg19_s cn31xx;
+	struct cvmx_pci_cfg19_s cn38xx;
+	struct cvmx_pci_cfg19_s cn38xxp2;
+	struct cvmx_pci_cfg19_s cn50xx;
+	struct cvmx_pci_cfg19_s cn58xx;
+	struct cvmx_pci_cfg19_s cn58xxp1;
+};
+
+union cvmx_pci_cfg20 {
+	uint32_t u32;
+	struct cvmx_pci_cfg20_s {
+		uint32_t mdsp:32;
+	} s;
+	struct cvmx_pci_cfg20_s cn30xx;
+	struct cvmx_pci_cfg20_s cn31xx;
+	struct cvmx_pci_cfg20_s cn38xx;
+	struct cvmx_pci_cfg20_s cn38xxp2;
+	struct cvmx_pci_cfg20_s cn50xx;
+	struct cvmx_pci_cfg20_s cn58xx;
+	struct cvmx_pci_cfg20_s cn58xxp1;
+};
+
+union cvmx_pci_cfg21 {
+	uint32_t u32;
+	struct cvmx_pci_cfg21_s {
+		uint32_t scmre:32;
+	} s;
+	struct cvmx_pci_cfg21_s cn30xx;
+	struct cvmx_pci_cfg21_s cn31xx;
+	struct cvmx_pci_cfg21_s cn38xx;
+	struct cvmx_pci_cfg21_s cn38xxp2;
+	struct cvmx_pci_cfg21_s cn50xx;
+	struct cvmx_pci_cfg21_s cn58xx;
+	struct cvmx_pci_cfg21_s cn58xxp1;
+};
+
+union cvmx_pci_cfg22 {
+	uint32_t u32;
+	struct cvmx_pci_cfg22_s {
+		uint32_t mac:7;
+		uint32_t reserved_19_24:6;
+		uint32_t flush:1;
+		uint32_t mra:1;
+		uint32_t mtta:1;
+		uint32_t mrv:8;
+		uint32_t mttv:8;
+	} s;
+	struct cvmx_pci_cfg22_s cn30xx;
+	struct cvmx_pci_cfg22_s cn31xx;
+	struct cvmx_pci_cfg22_s cn38xx;
+	struct cvmx_pci_cfg22_s cn38xxp2;
+	struct cvmx_pci_cfg22_s cn50xx;
+	struct cvmx_pci_cfg22_s cn58xx;
+	struct cvmx_pci_cfg22_s cn58xxp1;
+};
+
+union cvmx_pci_cfg56 {
+	uint32_t u32;
+	struct cvmx_pci_cfg56_s {
+		uint32_t reserved_23_31:9;
+		uint32_t most:3;
+		uint32_t mmbc:2;
+		uint32_t roe:1;
+		uint32_t dpere:1;
+		uint32_t ncp:8;
+		uint32_t pxcid:8;
+	} s;
+	struct cvmx_pci_cfg56_s cn30xx;
+	struct cvmx_pci_cfg56_s cn31xx;
+	struct cvmx_pci_cfg56_s cn38xx;
+	struct cvmx_pci_cfg56_s cn38xxp2;
+	struct cvmx_pci_cfg56_s cn50xx;
+	struct cvmx_pci_cfg56_s cn58xx;
+	struct cvmx_pci_cfg56_s cn58xxp1;
+};
+
+union cvmx_pci_cfg57 {
+	uint32_t u32;
+	struct cvmx_pci_cfg57_s {
+		uint32_t reserved_30_31:2;
+		uint32_t scemr:1;
+		uint32_t mcrsd:3;
+		uint32_t mostd:3;
+		uint32_t mmrbcd:2;
+		uint32_t dc:1;
+		uint32_t usc:1;
+		uint32_t scd:1;
+		uint32_t m133:1;
+		uint32_t w64:1;
+		uint32_t bn:8;
+		uint32_t dn:5;
+		uint32_t fn:3;
+	} s;
+	struct cvmx_pci_cfg57_s cn30xx;
+	struct cvmx_pci_cfg57_s cn31xx;
+	struct cvmx_pci_cfg57_s cn38xx;
+	struct cvmx_pci_cfg57_s cn38xxp2;
+	struct cvmx_pci_cfg57_s cn50xx;
+	struct cvmx_pci_cfg57_s cn58xx;
+	struct cvmx_pci_cfg57_s cn58xxp1;
+};
+
+union cvmx_pci_cfg58 {
+	uint32_t u32;
+	struct cvmx_pci_cfg58_s {
+		uint32_t pmes:5;
+		uint32_t d2s:1;
+		uint32_t d1s:1;
+		uint32_t auxc:3;
+		uint32_t dsi:1;
+		uint32_t reserved_20_20:1;
+		uint32_t pmec:1;
+		uint32_t pcimiv:3;
+		uint32_t ncp:8;
+		uint32_t pmcid:8;
+	} s;
+	struct cvmx_pci_cfg58_s cn30xx;
+	struct cvmx_pci_cfg58_s cn31xx;
+	struct cvmx_pci_cfg58_s cn38xx;
+	struct cvmx_pci_cfg58_s cn38xxp2;
+	struct cvmx_pci_cfg58_s cn50xx;
+	struct cvmx_pci_cfg58_s cn58xx;
+	struct cvmx_pci_cfg58_s cn58xxp1;
+};
+
+union cvmx_pci_cfg59 {
+	uint32_t u32;
+	struct cvmx_pci_cfg59_s {
+		uint32_t pmdia:8;
+		uint32_t bpccen:1;
+		uint32_t bd3h:1;
+		uint32_t reserved_16_21:6;
+		uint32_t pmess:1;
+		uint32_t pmedsia:2;
+		uint32_t pmds:4;
+		uint32_t pmeens:1;
+		uint32_t reserved_2_7:6;
+		uint32_t ps:2;
+	} s;
+	struct cvmx_pci_cfg59_s cn30xx;
+	struct cvmx_pci_cfg59_s cn31xx;
+	struct cvmx_pci_cfg59_s cn38xx;
+	struct cvmx_pci_cfg59_s cn38xxp2;
+	struct cvmx_pci_cfg59_s cn50xx;
+	struct cvmx_pci_cfg59_s cn58xx;
+	struct cvmx_pci_cfg59_s cn58xxp1;
+};
+
+union cvmx_pci_cfg60 {
+	uint32_t u32;
+	struct cvmx_pci_cfg60_s {
+		uint32_t reserved_24_31:8;
+		uint32_t m64:1;
+		uint32_t mme:3;
+		uint32_t mmc:3;
+		uint32_t msien:1;
+		uint32_t ncp:8;
+		uint32_t msicid:8;
+	} s;
+	struct cvmx_pci_cfg60_s cn30xx;
+	struct cvmx_pci_cfg60_s cn31xx;
+	struct cvmx_pci_cfg60_s cn38xx;
+	struct cvmx_pci_cfg60_s cn38xxp2;
+	struct cvmx_pci_cfg60_s cn50xx;
+	struct cvmx_pci_cfg60_s cn58xx;
+	struct cvmx_pci_cfg60_s cn58xxp1;
+};
+
+union cvmx_pci_cfg61 {
+	uint32_t u32;
+	struct cvmx_pci_cfg61_s {
+		uint32_t msi31t2:30;
+		uint32_t reserved_0_1:2;
+	} s;
+	struct cvmx_pci_cfg61_s cn30xx;
+	struct cvmx_pci_cfg61_s cn31xx;
+	struct cvmx_pci_cfg61_s cn38xx;
+	struct cvmx_pci_cfg61_s cn38xxp2;
+	struct cvmx_pci_cfg61_s cn50xx;
+	struct cvmx_pci_cfg61_s cn58xx;
+	struct cvmx_pci_cfg61_s cn58xxp1;
+};
+
+union cvmx_pci_cfg62 {
+	uint32_t u32;
+	struct cvmx_pci_cfg62_s {
+		uint32_t msi:32;
+	} s;
+	struct cvmx_pci_cfg62_s cn30xx;
+	struct cvmx_pci_cfg62_s cn31xx;
+	struct cvmx_pci_cfg62_s cn38xx;
+	struct cvmx_pci_cfg62_s cn38xxp2;
+	struct cvmx_pci_cfg62_s cn50xx;
+	struct cvmx_pci_cfg62_s cn58xx;
+	struct cvmx_pci_cfg62_s cn58xxp1;
+};
+
+union cvmx_pci_cfg63 {
+	uint32_t u32;
+	struct cvmx_pci_cfg63_s {
+		uint32_t reserved_16_31:16;
+		uint32_t msimd:16;
+	} s;
+	struct cvmx_pci_cfg63_s cn30xx;
+	struct cvmx_pci_cfg63_s cn31xx;
+	struct cvmx_pci_cfg63_s cn38xx;
+	struct cvmx_pci_cfg63_s cn38xxp2;
+	struct cvmx_pci_cfg63_s cn50xx;
+	struct cvmx_pci_cfg63_s cn58xx;
+	struct cvmx_pci_cfg63_s cn58xxp1;
+};
+
+union cvmx_pci_cnt_reg {
+	uint64_t u64;
+	struct cvmx_pci_cnt_reg_s {
+		uint64_t reserved_38_63:26;
+		uint64_t hm_pcix:1;
+		uint64_t hm_speed:2;
+		uint64_t ap_pcix:1;
+		uint64_t ap_speed:2;
+		uint64_t pcicnt:32;
+	} s;
+	struct cvmx_pci_cnt_reg_s cn50xx;
+	struct cvmx_pci_cnt_reg_s cn58xx;
+	struct cvmx_pci_cnt_reg_s cn58xxp1;
+};
+
+union cvmx_pci_ctl_status_2 {
+	uint32_t u32;
+	struct cvmx_pci_ctl_status_2_s {
+		uint32_t reserved_29_31:3;
+		uint32_t bb1_hole:3;
+		uint32_t bb1_siz:1;
+		uint32_t bb_ca:1;
+		uint32_t bb_es:2;
+		uint32_t bb1:1;
+		uint32_t bb0:1;
+		uint32_t erst_n:1;
+		uint32_t bar2pres:1;
+		uint32_t scmtyp:1;
+		uint32_t scm:1;
+		uint32_t en_wfilt:1;
+		uint32_t reserved_14_14:1;
+		uint32_t ap_pcix:1;
+		uint32_t ap_64ad:1;
+		uint32_t b12_bist:1;
+		uint32_t pmo_amod:1;
+		uint32_t pmo_fpc:3;
+		uint32_t tsr_hwm:3;
+		uint32_t bar2_enb:1;
+		uint32_t bar2_esx:2;
+		uint32_t bar2_cax:1;
+	} s;
+	struct cvmx_pci_ctl_status_2_s cn30xx;
+	struct cvmx_pci_ctl_status_2_cn31xx {
+		uint32_t reserved_20_31:12;
+		uint32_t erst_n:1;
+		uint32_t bar2pres:1;
+		uint32_t scmtyp:1;
+		uint32_t scm:1;
+		uint32_t en_wfilt:1;
+		uint32_t reserved_14_14:1;
+		uint32_t ap_pcix:1;
+		uint32_t ap_64ad:1;
+		uint32_t b12_bist:1;
+		uint32_t pmo_amod:1;
+		uint32_t pmo_fpc:3;
+		uint32_t tsr_hwm:3;
+		uint32_t bar2_enb:1;
+		uint32_t bar2_esx:2;
+		uint32_t bar2_cax:1;
+	} cn31xx;
+	struct cvmx_pci_ctl_status_2_s cn38xx;
+	struct cvmx_pci_ctl_status_2_cn31xx cn38xxp2;
+	struct cvmx_pci_ctl_status_2_s cn50xx;
+	struct cvmx_pci_ctl_status_2_s cn58xx;
+	struct cvmx_pci_ctl_status_2_s cn58xxp1;
+};
+
+union cvmx_pci_dbellx {
+	uint32_t u32;
+	struct cvmx_pci_dbellx_s {
+		uint32_t reserved_16_31:16;
+		uint32_t inc_val:16;
+	} s;
+	struct cvmx_pci_dbellx_s cn30xx;
+	struct cvmx_pci_dbellx_s cn31xx;
+	struct cvmx_pci_dbellx_s cn38xx;
+	struct cvmx_pci_dbellx_s cn38xxp2;
+	struct cvmx_pci_dbellx_s cn50xx;
+	struct cvmx_pci_dbellx_s cn58xx;
+	struct cvmx_pci_dbellx_s cn58xxp1;
+};
+
+union cvmx_pci_dma_cntx {
+	uint32_t u32;
+	struct cvmx_pci_dma_cntx_s {
+		uint32_t dma_cnt:32;
+	} s;
+	struct cvmx_pci_dma_cntx_s cn30xx;
+	struct cvmx_pci_dma_cntx_s cn31xx;
+	struct cvmx_pci_dma_cntx_s cn38xx;
+	struct cvmx_pci_dma_cntx_s cn38xxp2;
+	struct cvmx_pci_dma_cntx_s cn50xx;
+	struct cvmx_pci_dma_cntx_s cn58xx;
+	struct cvmx_pci_dma_cntx_s cn58xxp1;
+};
+
+union cvmx_pci_dma_int_levx {
+	uint32_t u32;
+	struct cvmx_pci_dma_int_levx_s {
+		uint32_t pkt_cnt:32;
+	} s;
+	struct cvmx_pci_dma_int_levx_s cn30xx;
+	struct cvmx_pci_dma_int_levx_s cn31xx;
+	struct cvmx_pci_dma_int_levx_s cn38xx;
+	struct cvmx_pci_dma_int_levx_s cn38xxp2;
+	struct cvmx_pci_dma_int_levx_s cn50xx;
+	struct cvmx_pci_dma_int_levx_s cn58xx;
+	struct cvmx_pci_dma_int_levx_s cn58xxp1;
+};
+
+union cvmx_pci_dma_timex {
+	uint32_t u32;
+	struct cvmx_pci_dma_timex_s {
+		uint32_t dma_time:32;
+	} s;
+	struct cvmx_pci_dma_timex_s cn30xx;
+	struct cvmx_pci_dma_timex_s cn31xx;
+	struct cvmx_pci_dma_timex_s cn38xx;
+	struct cvmx_pci_dma_timex_s cn38xxp2;
+	struct cvmx_pci_dma_timex_s cn50xx;
+	struct cvmx_pci_dma_timex_s cn58xx;
+	struct cvmx_pci_dma_timex_s cn58xxp1;
+};
+
+union cvmx_pci_instr_countx {
+	uint32_t u32;
+	struct cvmx_pci_instr_countx_s {
+		uint32_t icnt:32;
+	} s;
+	struct cvmx_pci_instr_countx_s cn30xx;
+	struct cvmx_pci_instr_countx_s cn31xx;
+	struct cvmx_pci_instr_countx_s cn38xx;
+	struct cvmx_pci_instr_countx_s cn38xxp2;
+	struct cvmx_pci_instr_countx_s cn50xx;
+	struct cvmx_pci_instr_countx_s cn58xx;
+	struct cvmx_pci_instr_countx_s cn58xxp1;
+};
+
+union cvmx_pci_int_enb {
+	uint64_t u64;
+	struct cvmx_pci_int_enb_s {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t idtime1:1;
+		uint64_t idtime0:1;
+		uint64_t idcnt1:1;
+		uint64_t idcnt0:1;
+		uint64_t iptime3:1;
+		uint64_t iptime2:1;
+		uint64_t iptime1:1;
+		uint64_t iptime0:1;
+		uint64_t ipcnt3:1;
+		uint64_t ipcnt2:1;
+		uint64_t ipcnt1:1;
+		uint64_t ipcnt0:1;
+		uint64_t irsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t idperr:1;
+		uint64_t iaperr:1;
+		uint64_t iserr:1;
+		uint64_t itsr_abt:1;
+		uint64_t imsc_msg:1;
+		uint64_t imsi_mabt:1;
+		uint64_t imsi_tabt:1;
+		uint64_t imsi_per:1;
+		uint64_t imr_tto:1;
+		uint64_t imr_abt:1;
+		uint64_t itr_abt:1;
+		uint64_t imr_wtto:1;
+		uint64_t imr_wabt:1;
+		uint64_t itr_wabt:1;
+	} s;
+	struct cvmx_pci_int_enb_cn30xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t idtime1:1;
+		uint64_t idtime0:1;
+		uint64_t idcnt1:1;
+		uint64_t idcnt0:1;
+		uint64_t reserved_22_24:3;
+		uint64_t iptime0:1;
+		uint64_t reserved_18_20:3;
+		uint64_t ipcnt0:1;
+		uint64_t irsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t idperr:1;
+		uint64_t iaperr:1;
+		uint64_t iserr:1;
+		uint64_t itsr_abt:1;
+		uint64_t imsc_msg:1;
+		uint64_t imsi_mabt:1;
+		uint64_t imsi_tabt:1;
+		uint64_t imsi_per:1;
+		uint64_t imr_tto:1;
+		uint64_t imr_abt:1;
+		uint64_t itr_abt:1;
+		uint64_t imr_wtto:1;
+		uint64_t imr_wabt:1;
+		uint64_t itr_wabt:1;
+	} cn30xx;
+	struct cvmx_pci_int_enb_cn31xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t idtime1:1;
+		uint64_t idtime0:1;
+		uint64_t idcnt1:1;
+		uint64_t idcnt0:1;
+		uint64_t reserved_23_24:2;
+		uint64_t iptime1:1;
+		uint64_t iptime0:1;
+		uint64_t reserved_19_20:2;
+		uint64_t ipcnt1:1;
+		uint64_t ipcnt0:1;
+		uint64_t irsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t idperr:1;
+		uint64_t iaperr:1;
+		uint64_t iserr:1;
+		uint64_t itsr_abt:1;
+		uint64_t imsc_msg:1;
+		uint64_t imsi_mabt:1;
+		uint64_t imsi_tabt:1;
+		uint64_t imsi_per:1;
+		uint64_t imr_tto:1;
+		uint64_t imr_abt:1;
+		uint64_t itr_abt:1;
+		uint64_t imr_wtto:1;
+		uint64_t imr_wabt:1;
+		uint64_t itr_wabt:1;
+	} cn31xx;
+	struct cvmx_pci_int_enb_s cn38xx;
+	struct cvmx_pci_int_enb_s cn38xxp2;
+	struct cvmx_pci_int_enb_cn31xx cn50xx;
+	struct cvmx_pci_int_enb_s cn58xx;
+	struct cvmx_pci_int_enb_s cn58xxp1;
+};
+
+union cvmx_pci_int_enb2 {
+	uint64_t u64;
+	struct cvmx_pci_int_enb2_s {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t rdtime1:1;
+		uint64_t rdtime0:1;
+		uint64_t rdcnt1:1;
+		uint64_t rdcnt0:1;
+		uint64_t rptime3:1;
+		uint64_t rptime2:1;
+		uint64_t rptime1:1;
+		uint64_t rptime0:1;
+		uint64_t rpcnt3:1;
+		uint64_t rpcnt2:1;
+		uint64_t rpcnt1:1;
+		uint64_t rpcnt0:1;
+		uint64_t rrsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t rdperr:1;
+		uint64_t raperr:1;
+		uint64_t rserr:1;
+		uint64_t rtsr_abt:1;
+		uint64_t rmsc_msg:1;
+		uint64_t rmsi_mabt:1;
+		uint64_t rmsi_tabt:1;
+		uint64_t rmsi_per:1;
+		uint64_t rmr_tto:1;
+		uint64_t rmr_abt:1;
+		uint64_t rtr_abt:1;
+		uint64_t rmr_wtto:1;
+		uint64_t rmr_wabt:1;
+		uint64_t rtr_wabt:1;
+	} s;
+	struct cvmx_pci_int_enb2_cn30xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t rdtime1:1;
+		uint64_t rdtime0:1;
+		uint64_t rdcnt1:1;
+		uint64_t rdcnt0:1;
+		uint64_t reserved_22_24:3;
+		uint64_t rptime0:1;
+		uint64_t reserved_18_20:3;
+		uint64_t rpcnt0:1;
+		uint64_t rrsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t rdperr:1;
+		uint64_t raperr:1;
+		uint64_t rserr:1;
+		uint64_t rtsr_abt:1;
+		uint64_t rmsc_msg:1;
+		uint64_t rmsi_mabt:1;
+		uint64_t rmsi_tabt:1;
+		uint64_t rmsi_per:1;
+		uint64_t rmr_tto:1;
+		uint64_t rmr_abt:1;
+		uint64_t rtr_abt:1;
+		uint64_t rmr_wtto:1;
+		uint64_t rmr_wabt:1;
+		uint64_t rtr_wabt:1;
+	} cn30xx;
+	struct cvmx_pci_int_enb2_cn31xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t rdtime1:1;
+		uint64_t rdtime0:1;
+		uint64_t rdcnt1:1;
+		uint64_t rdcnt0:1;
+		uint64_t reserved_23_24:2;
+		uint64_t rptime1:1;
+		uint64_t rptime0:1;
+		uint64_t reserved_19_20:2;
+		uint64_t rpcnt1:1;
+		uint64_t rpcnt0:1;
+		uint64_t rrsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t rdperr:1;
+		uint64_t raperr:1;
+		uint64_t rserr:1;
+		uint64_t rtsr_abt:1;
+		uint64_t rmsc_msg:1;
+		uint64_t rmsi_mabt:1;
+		uint64_t rmsi_tabt:1;
+		uint64_t rmsi_per:1;
+		uint64_t rmr_tto:1;
+		uint64_t rmr_abt:1;
+		uint64_t rtr_abt:1;
+		uint64_t rmr_wtto:1;
+		uint64_t rmr_wabt:1;
+		uint64_t rtr_wabt:1;
+	} cn31xx;
+	struct cvmx_pci_int_enb2_s cn38xx;
+	struct cvmx_pci_int_enb2_s cn38xxp2;
+	struct cvmx_pci_int_enb2_cn31xx cn50xx;
+	struct cvmx_pci_int_enb2_s cn58xx;
+	struct cvmx_pci_int_enb2_s cn58xxp1;
+};
+
+union cvmx_pci_int_sum {
+	uint64_t u64;
+	struct cvmx_pci_int_sum_s {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t ptime3:1;
+		uint64_t ptime2:1;
+		uint64_t ptime1:1;
+		uint64_t ptime0:1;
+		uint64_t pcnt3:1;
+		uint64_t pcnt2:1;
+		uint64_t pcnt1:1;
+		uint64_t pcnt0:1;
+		uint64_t rsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t dperr:1;
+		uint64_t aperr:1;
+		uint64_t serr:1;
+		uint64_t tsr_abt:1;
+		uint64_t msc_msg:1;
+		uint64_t msi_mabt:1;
+		uint64_t msi_tabt:1;
+		uint64_t msi_per:1;
+		uint64_t mr_tto:1;
+		uint64_t mr_abt:1;
+		uint64_t tr_abt:1;
+		uint64_t mr_wtto:1;
+		uint64_t mr_wabt:1;
+		uint64_t tr_wabt:1;
+	} s;
+	struct cvmx_pci_int_sum_cn30xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t reserved_22_24:3;
+		uint64_t ptime0:1;
+		uint64_t reserved_18_20:3;
+		uint64_t pcnt0:1;
+		uint64_t rsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t dperr:1;
+		uint64_t aperr:1;
+		uint64_t serr:1;
+		uint64_t tsr_abt:1;
+		uint64_t msc_msg:1;
+		uint64_t msi_mabt:1;
+		uint64_t msi_tabt:1;
+		uint64_t msi_per:1;
+		uint64_t mr_tto:1;
+		uint64_t mr_abt:1;
+		uint64_t tr_abt:1;
+		uint64_t mr_wtto:1;
+		uint64_t mr_wabt:1;
+		uint64_t tr_wabt:1;
+	} cn30xx;
+	struct cvmx_pci_int_sum_cn31xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t reserved_23_24:2;
+		uint64_t ptime1:1;
+		uint64_t ptime0:1;
+		uint64_t reserved_19_20:2;
+		uint64_t pcnt1:1;
+		uint64_t pcnt0:1;
+		uint64_t rsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t dperr:1;
+		uint64_t aperr:1;
+		uint64_t serr:1;
+		uint64_t tsr_abt:1;
+		uint64_t msc_msg:1;
+		uint64_t msi_mabt:1;
+		uint64_t msi_tabt:1;
+		uint64_t msi_per:1;
+		uint64_t mr_tto:1;
+		uint64_t mr_abt:1;
+		uint64_t tr_abt:1;
+		uint64_t mr_wtto:1;
+		uint64_t mr_wabt:1;
+		uint64_t tr_wabt:1;
+	} cn31xx;
+	struct cvmx_pci_int_sum_s cn38xx;
+	struct cvmx_pci_int_sum_s cn38xxp2;
+	struct cvmx_pci_int_sum_cn31xx cn50xx;
+	struct cvmx_pci_int_sum_s cn58xx;
+	struct cvmx_pci_int_sum_s cn58xxp1;
+};
+
+union cvmx_pci_int_sum2 {
+	uint64_t u64;
+	struct cvmx_pci_int_sum2_s {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t ptime3:1;
+		uint64_t ptime2:1;
+		uint64_t ptime1:1;
+		uint64_t ptime0:1;
+		uint64_t pcnt3:1;
+		uint64_t pcnt2:1;
+		uint64_t pcnt1:1;
+		uint64_t pcnt0:1;
+		uint64_t rsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t dperr:1;
+		uint64_t aperr:1;
+		uint64_t serr:1;
+		uint64_t tsr_abt:1;
+		uint64_t msc_msg:1;
+		uint64_t msi_mabt:1;
+		uint64_t msi_tabt:1;
+		uint64_t msi_per:1;
+		uint64_t mr_tto:1;
+		uint64_t mr_abt:1;
+		uint64_t tr_abt:1;
+		uint64_t mr_wtto:1;
+		uint64_t mr_wabt:1;
+		uint64_t tr_wabt:1;
+	} s;
+	struct cvmx_pci_int_sum2_cn30xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t reserved_22_24:3;
+		uint64_t ptime0:1;
+		uint64_t reserved_18_20:3;
+		uint64_t pcnt0:1;
+		uint64_t rsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t dperr:1;
+		uint64_t aperr:1;
+		uint64_t serr:1;
+		uint64_t tsr_abt:1;
+		uint64_t msc_msg:1;
+		uint64_t msi_mabt:1;
+		uint64_t msi_tabt:1;
+		uint64_t msi_per:1;
+		uint64_t mr_tto:1;
+		uint64_t mr_abt:1;
+		uint64_t tr_abt:1;
+		uint64_t mr_wtto:1;
+		uint64_t mr_wabt:1;
+		uint64_t tr_wabt:1;
+	} cn30xx;
+	struct cvmx_pci_int_sum2_cn31xx {
+		uint64_t reserved_34_63:30;
+		uint64_t ill_rd:1;
+		uint64_t ill_wr:1;
+		uint64_t win_wr:1;
+		uint64_t dma1_fi:1;
+		uint64_t dma0_fi:1;
+		uint64_t dtime1:1;
+		uint64_t dtime0:1;
+		uint64_t dcnt1:1;
+		uint64_t dcnt0:1;
+		uint64_t reserved_23_24:2;
+		uint64_t ptime1:1;
+		uint64_t ptime0:1;
+		uint64_t reserved_19_20:2;
+		uint64_t pcnt1:1;
+		uint64_t pcnt0:1;
+		uint64_t rsl_int:1;
+		uint64_t ill_rrd:1;
+		uint64_t ill_rwr:1;
+		uint64_t dperr:1;
+		uint64_t aperr:1;
+		uint64_t serr:1;
+		uint64_t tsr_abt:1;
+		uint64_t msc_msg:1;
+		uint64_t msi_mabt:1;
+		uint64_t msi_tabt:1;
+		uint64_t msi_per:1;
+		uint64_t mr_tto:1;
+		uint64_t mr_abt:1;
+		uint64_t tr_abt:1;
+		uint64_t mr_wtto:1;
+		uint64_t mr_wabt:1;
+		uint64_t tr_wabt:1;
+	} cn31xx;
+	struct cvmx_pci_int_sum2_s cn38xx;
+	struct cvmx_pci_int_sum2_s cn38xxp2;
+	struct cvmx_pci_int_sum2_cn31xx cn50xx;
+	struct cvmx_pci_int_sum2_s cn58xx;
+	struct cvmx_pci_int_sum2_s cn58xxp1;
+};
+
+union cvmx_pci_msi_rcv {
+	uint32_t u32;
+	struct cvmx_pci_msi_rcv_s {
+		uint32_t reserved_6_31:26;
+		uint32_t intr:6;
+	} s;
+	struct cvmx_pci_msi_rcv_s cn30xx;
+	struct cvmx_pci_msi_rcv_s cn31xx;
+	struct cvmx_pci_msi_rcv_s cn38xx;
+	struct cvmx_pci_msi_rcv_s cn38xxp2;
+	struct cvmx_pci_msi_rcv_s cn50xx;
+	struct cvmx_pci_msi_rcv_s cn58xx;
+	struct cvmx_pci_msi_rcv_s cn58xxp1;
+};
+
+union cvmx_pci_pkt_creditsx {
+	uint32_t u32;
+	struct cvmx_pci_pkt_creditsx_s {
+		uint32_t pkt_cnt:16;
+		uint32_t ptr_cnt:16;
+	} s;
+	struct cvmx_pci_pkt_creditsx_s cn30xx;
+	struct cvmx_pci_pkt_creditsx_s cn31xx;
+	struct cvmx_pci_pkt_creditsx_s cn38xx;
+	struct cvmx_pci_pkt_creditsx_s cn38xxp2;
+	struct cvmx_pci_pkt_creditsx_s cn50xx;
+	struct cvmx_pci_pkt_creditsx_s cn58xx;
+	struct cvmx_pci_pkt_creditsx_s cn58xxp1;
+};
+
+union cvmx_pci_pkts_sentx {
+	uint32_t u32;
+	struct cvmx_pci_pkts_sentx_s {
+		uint32_t pkt_cnt:32;
+	} s;
+	struct cvmx_pci_pkts_sentx_s cn30xx;
+	struct cvmx_pci_pkts_sentx_s cn31xx;
+	struct cvmx_pci_pkts_sentx_s cn38xx;
+	struct cvmx_pci_pkts_sentx_s cn38xxp2;
+	struct cvmx_pci_pkts_sentx_s cn50xx;
+	struct cvmx_pci_pkts_sentx_s cn58xx;
+	struct cvmx_pci_pkts_sentx_s cn58xxp1;
+};
+
+union cvmx_pci_pkts_sent_int_levx {
+	uint32_t u32;
+	struct cvmx_pci_pkts_sent_int_levx_s {
+		uint32_t pkt_cnt:32;
+	} s;
+	struct cvmx_pci_pkts_sent_int_levx_s cn30xx;
+	struct cvmx_pci_pkts_sent_int_levx_s cn31xx;
+	struct cvmx_pci_pkts_sent_int_levx_s cn38xx;
+	struct cvmx_pci_pkts_sent_int_levx_s cn38xxp2;
+	struct cvmx_pci_pkts_sent_int_levx_s cn50xx;
+	struct cvmx_pci_pkts_sent_int_levx_s cn58xx;
+	struct cvmx_pci_pkts_sent_int_levx_s cn58xxp1;
+};
+
+union cvmx_pci_pkts_sent_timex {
+	uint32_t u32;
+	struct cvmx_pci_pkts_sent_timex_s {
+		uint32_t pkt_time:32;
+	} s;
+	struct cvmx_pci_pkts_sent_timex_s cn30xx;
+	struct cvmx_pci_pkts_sent_timex_s cn31xx;
+	struct cvmx_pci_pkts_sent_timex_s cn38xx;
+	struct cvmx_pci_pkts_sent_timex_s cn38xxp2;
+	struct cvmx_pci_pkts_sent_timex_s cn50xx;
+	struct cvmx_pci_pkts_sent_timex_s cn58xx;
+	struct cvmx_pci_pkts_sent_timex_s cn58xxp1;
+};
+
+union cvmx_pci_read_cmd_6 {
+	uint32_t u32;
+	struct cvmx_pci_read_cmd_6_s {
+		uint32_t reserved_9_31:23;
+		uint32_t min_data:6;
+		uint32_t prefetch:3;
+	} s;
+	struct cvmx_pci_read_cmd_6_s cn30xx;
+	struct cvmx_pci_read_cmd_6_s cn31xx;
+	struct cvmx_pci_read_cmd_6_s cn38xx;
+	struct cvmx_pci_read_cmd_6_s cn38xxp2;
+	struct cvmx_pci_read_cmd_6_s cn50xx;
+	struct cvmx_pci_read_cmd_6_s cn58xx;
+	struct cvmx_pci_read_cmd_6_s cn58xxp1;
+};
+
+union cvmx_pci_read_cmd_c {
+	uint32_t u32;
+	struct cvmx_pci_read_cmd_c_s {
+		uint32_t reserved_9_31:23;
+		uint32_t min_data:6;
+		uint32_t prefetch:3;
+	} s;
+	struct cvmx_pci_read_cmd_c_s cn30xx;
+	struct cvmx_pci_read_cmd_c_s cn31xx;
+	struct cvmx_pci_read_cmd_c_s cn38xx;
+	struct cvmx_pci_read_cmd_c_s cn38xxp2;
+	struct cvmx_pci_read_cmd_c_s cn50xx;
+	struct cvmx_pci_read_cmd_c_s cn58xx;
+	struct cvmx_pci_read_cmd_c_s cn58xxp1;
+};
+
+union cvmx_pci_read_cmd_e {
+	uint32_t u32;
+	struct cvmx_pci_read_cmd_e_s {
+		uint32_t reserved_9_31:23;
+		uint32_t min_data:6;
+		uint32_t prefetch:3;
+	} s;
+	struct cvmx_pci_read_cmd_e_s cn30xx;
+	struct cvmx_pci_read_cmd_e_s cn31xx;
+	struct cvmx_pci_read_cmd_e_s cn38xx;
+	struct cvmx_pci_read_cmd_e_s cn38xxp2;
+	struct cvmx_pci_read_cmd_e_s cn50xx;
+	struct cvmx_pci_read_cmd_e_s cn58xx;
+	struct cvmx_pci_read_cmd_e_s cn58xxp1;
+};
+
+union cvmx_pci_read_timeout {
+	uint64_t u64;
+	struct cvmx_pci_read_timeout_s {
+		uint64_t reserved_32_63:32;
+		uint64_t enb:1;
+		uint64_t cnt:31;
+	} s;
+	struct cvmx_pci_read_timeout_s cn30xx;
+	struct cvmx_pci_read_timeout_s cn31xx;
+	struct cvmx_pci_read_timeout_s cn38xx;
+	struct cvmx_pci_read_timeout_s cn38xxp2;
+	struct cvmx_pci_read_timeout_s cn50xx;
+	struct cvmx_pci_read_timeout_s cn58xx;
+	struct cvmx_pci_read_timeout_s cn58xxp1;
+};
+
+union cvmx_pci_scm_reg {
+	uint64_t u64;
+	struct cvmx_pci_scm_reg_s {
+		uint64_t reserved_32_63:32;
+		uint64_t scm:32;
+	} s;
+	struct cvmx_pci_scm_reg_s cn30xx;
+	struct cvmx_pci_scm_reg_s cn31xx;
+	struct cvmx_pci_scm_reg_s cn38xx;
+	struct cvmx_pci_scm_reg_s cn38xxp2;
+	struct cvmx_pci_scm_reg_s cn50xx;
+	struct cvmx_pci_scm_reg_s cn58xx;
+	struct cvmx_pci_scm_reg_s cn58xxp1;
+};
+
+union cvmx_pci_tsr_reg {
+	uint64_t u64;
+	struct cvmx_pci_tsr_reg_s {
+		uint64_t reserved_36_63:28;
+		uint64_t tsr:36;
+	} s;
+	struct cvmx_pci_tsr_reg_s cn30xx;
+	struct cvmx_pci_tsr_reg_s cn31xx;
+	struct cvmx_pci_tsr_reg_s cn38xx;
+	struct cvmx_pci_tsr_reg_s cn38xxp2;
+	struct cvmx_pci_tsr_reg_s cn50xx;
+	struct cvmx_pci_tsr_reg_s cn58xx;
+	struct cvmx_pci_tsr_reg_s cn58xxp1;
+};
+
+union cvmx_pci_win_rd_addr {
+	uint64_t u64;
+	struct cvmx_pci_win_rd_addr_s {
+		uint64_t reserved_49_63:15;
+		uint64_t iobit:1;
+		uint64_t reserved_0_47:48;
+	} s;
+	struct cvmx_pci_win_rd_addr_cn30xx {
+		uint64_t reserved_49_63:15;
+		uint64_t iobit:1;
+		uint64_t rd_addr:46;
+		uint64_t reserved_0_1:2;
+	} cn30xx;
+	struct cvmx_pci_win_rd_addr_cn30xx cn31xx;
+	struct cvmx_pci_win_rd_addr_cn38xx {
+		uint64_t reserved_49_63:15;
+		uint64_t iobit:1;
+		uint64_t rd_addr:45;
+		uint64_t reserved_0_2:3;
+	} cn38xx;
+	struct cvmx_pci_win_rd_addr_cn38xx cn38xxp2;
+	struct cvmx_pci_win_rd_addr_cn30xx cn50xx;
+	struct cvmx_pci_win_rd_addr_cn38xx cn58xx;
+	struct cvmx_pci_win_rd_addr_cn38xx cn58xxp1;
+};
+
+union cvmx_pci_win_rd_data {
+	uint64_t u64;
+	struct cvmx_pci_win_rd_data_s {
+		uint64_t rd_data:64;
+	} s;
+	struct cvmx_pci_win_rd_data_s cn30xx;
+	struct cvmx_pci_win_rd_data_s cn31xx;
+	struct cvmx_pci_win_rd_data_s cn38xx;
+	struct cvmx_pci_win_rd_data_s cn38xxp2;
+	struct cvmx_pci_win_rd_data_s cn50xx;
+	struct cvmx_pci_win_rd_data_s cn58xx;
+	struct cvmx_pci_win_rd_data_s cn58xxp1;
+};
+
+union cvmx_pci_win_wr_addr {
+	uint64_t u64;
+	struct cvmx_pci_win_wr_addr_s {
+		uint64_t reserved_49_63:15;
+		uint64_t iobit:1;
+		uint64_t wr_addr:45;
+		uint64_t reserved_0_2:3;
+	} s;
+	struct cvmx_pci_win_wr_addr_s cn30xx;
+	struct cvmx_pci_win_wr_addr_s cn31xx;
+	struct cvmx_pci_win_wr_addr_s cn38xx;
+	struct cvmx_pci_win_wr_addr_s cn38xxp2;
+	struct cvmx_pci_win_wr_addr_s cn50xx;
+	struct cvmx_pci_win_wr_addr_s cn58xx;
+	struct cvmx_pci_win_wr_addr_s cn58xxp1;
+};
+
+union cvmx_pci_win_wr_data {
+	uint64_t u64;
+	struct cvmx_pci_win_wr_data_s {
+		uint64_t wr_data:64;
+	} s;
+	struct cvmx_pci_win_wr_data_s cn30xx;
+	struct cvmx_pci_win_wr_data_s cn31xx;
+	struct cvmx_pci_win_wr_data_s cn38xx;
+	struct cvmx_pci_win_wr_data_s cn38xxp2;
+	struct cvmx_pci_win_wr_data_s cn50xx;
+	struct cvmx_pci_win_wr_data_s cn58xx;
+	struct cvmx_pci_win_wr_data_s cn58xxp1;
+};
+
+union cvmx_pci_win_wr_mask {
+	uint64_t u64;
+	struct cvmx_pci_win_wr_mask_s {
+		uint64_t reserved_8_63:56;
+		uint64_t wr_mask:8;
+	} s;
+	struct cvmx_pci_win_wr_mask_s cn30xx;
+	struct cvmx_pci_win_wr_mask_s cn31xx;
+	struct cvmx_pci_win_wr_mask_s cn38xx;
+	struct cvmx_pci_win_wr_mask_s cn38xxp2;
+	struct cvmx_pci_win_wr_mask_s cn50xx;
+	struct cvmx_pci_win_wr_mask_s cn58xx;
+	struct cvmx_pci_win_wr_mask_s cn58xxp1;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1365 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PCIEEP_DEFS_H__
+#define __CVMX_PCIEEP_DEFS_H__
+
+#define CVMX_PCIEEP_CFG000 \
+	 (0x0000000000000000ull)
+#define CVMX_PCIEEP_CFG001 \
+	 (0x0000000000000004ull)
+#define CVMX_PCIEEP_CFG002 \
+	 (0x0000000000000008ull)
+#define CVMX_PCIEEP_CFG003 \
+	 (0x000000000000000Cull)
+#define CVMX_PCIEEP_CFG004 \
+	 (0x0000000000000010ull)
+#define CVMX_PCIEEP_CFG004_MASK \
+	 (0x0000000080000010ull)
+#define CVMX_PCIEEP_CFG005 \
+	 (0x0000000000000014ull)
+#define CVMX_PCIEEP_CFG005_MASK \
+	 (0x0000000080000014ull)
+#define CVMX_PCIEEP_CFG006 \
+	 (0x0000000000000018ull)
+#define CVMX_PCIEEP_CFG006_MASK \
+	 (0x0000000080000018ull)
+#define CVMX_PCIEEP_CFG007 \
+	 (0x000000000000001Cull)
+#define CVMX_PCIEEP_CFG007_MASK \
+	 (0x000000008000001Cull)
+#define CVMX_PCIEEP_CFG008 \
+	 (0x0000000000000020ull)
+#define CVMX_PCIEEP_CFG008_MASK \
+	 (0x0000000080000020ull)
+#define CVMX_PCIEEP_CFG009 \
+	 (0x0000000000000024ull)
+#define CVMX_PCIEEP_CFG009_MASK \
+	 (0x0000000080000024ull)
+#define CVMX_PCIEEP_CFG010 \
+	 (0x0000000000000028ull)
+#define CVMX_PCIEEP_CFG011 \
+	 (0x000000000000002Cull)
+#define CVMX_PCIEEP_CFG012 \
+	 (0x0000000000000030ull)
+#define CVMX_PCIEEP_CFG012_MASK \
+	 (0x0000000080000030ull)
+#define CVMX_PCIEEP_CFG013 \
+	 (0x0000000000000034ull)
+#define CVMX_PCIEEP_CFG015 \
+	 (0x000000000000003Cull)
+#define CVMX_PCIEEP_CFG016 \
+	 (0x0000000000000040ull)
+#define CVMX_PCIEEP_CFG017 \
+	 (0x0000000000000044ull)
+#define CVMX_PCIEEP_CFG020 \
+	 (0x0000000000000050ull)
+#define CVMX_PCIEEP_CFG021 \
+	 (0x0000000000000054ull)
+#define CVMX_PCIEEP_CFG022 \
+	 (0x0000000000000058ull)
+#define CVMX_PCIEEP_CFG023 \
+	 (0x000000000000005Cull)
+#define CVMX_PCIEEP_CFG028 \
+	 (0x0000000000000070ull)
+#define CVMX_PCIEEP_CFG029 \
+	 (0x0000000000000074ull)
+#define CVMX_PCIEEP_CFG030 \
+	 (0x0000000000000078ull)
+#define CVMX_PCIEEP_CFG031 \
+	 (0x000000000000007Cull)
+#define CVMX_PCIEEP_CFG032 \
+	 (0x0000000000000080ull)
+#define CVMX_PCIEEP_CFG033 \
+	 (0x0000000000000084ull)
+#define CVMX_PCIEEP_CFG034 \
+	 (0x0000000000000088ull)
+#define CVMX_PCIEEP_CFG037 \
+	 (0x0000000000000094ull)
+#define CVMX_PCIEEP_CFG038 \
+	 (0x0000000000000098ull)
+#define CVMX_PCIEEP_CFG039 \
+	 (0x000000000000009Cull)
+#define CVMX_PCIEEP_CFG040 \
+	 (0x00000000000000A0ull)
+#define CVMX_PCIEEP_CFG041 \
+	 (0x00000000000000A4ull)
+#define CVMX_PCIEEP_CFG042 \
+	 (0x00000000000000A8ull)
+#define CVMX_PCIEEP_CFG064 \
+	 (0x0000000000000100ull)
+#define CVMX_PCIEEP_CFG065 \
+	 (0x0000000000000104ull)
+#define CVMX_PCIEEP_CFG066 \
+	 (0x0000000000000108ull)
+#define CVMX_PCIEEP_CFG067 \
+	 (0x000000000000010Cull)
+#define CVMX_PCIEEP_CFG068 \
+	 (0x0000000000000110ull)
+#define CVMX_PCIEEP_CFG069 \
+	 (0x0000000000000114ull)
+#define CVMX_PCIEEP_CFG070 \
+	 (0x0000000000000118ull)
+#define CVMX_PCIEEP_CFG071 \
+	 (0x000000000000011Cull)
+#define CVMX_PCIEEP_CFG072 \
+	 (0x0000000000000120ull)
+#define CVMX_PCIEEP_CFG073 \
+	 (0x0000000000000124ull)
+#define CVMX_PCIEEP_CFG074 \
+	 (0x0000000000000128ull)
+#define CVMX_PCIEEP_CFG448 \
+	 (0x0000000000000700ull)
+#define CVMX_PCIEEP_CFG449 \
+	 (0x0000000000000704ull)
+#define CVMX_PCIEEP_CFG450 \
+	 (0x0000000000000708ull)
+#define CVMX_PCIEEP_CFG451 \
+	 (0x000000000000070Cull)
+#define CVMX_PCIEEP_CFG452 \
+	 (0x0000000000000710ull)
+#define CVMX_PCIEEP_CFG453 \
+	 (0x0000000000000714ull)
+#define CVMX_PCIEEP_CFG454 \
+	 (0x0000000000000718ull)
+#define CVMX_PCIEEP_CFG455 \
+	 (0x000000000000071Cull)
+#define CVMX_PCIEEP_CFG456 \
+	 (0x0000000000000720ull)
+#define CVMX_PCIEEP_CFG458 \
+	 (0x0000000000000728ull)
+#define CVMX_PCIEEP_CFG459 \
+	 (0x000000000000072Cull)
+#define CVMX_PCIEEP_CFG460 \
+	 (0x0000000000000730ull)
+#define CVMX_PCIEEP_CFG461 \
+	 (0x0000000000000734ull)
+#define CVMX_PCIEEP_CFG462 \
+	 (0x0000000000000738ull)
+#define CVMX_PCIEEP_CFG463 \
+	 (0x000000000000073Cull)
+#define CVMX_PCIEEP_CFG464 \
+	 (0x0000000000000740ull)
+#define CVMX_PCIEEP_CFG465 \
+	 (0x0000000000000744ull)
+#define CVMX_PCIEEP_CFG466 \
+	 (0x0000000000000748ull)
+#define CVMX_PCIEEP_CFG467 \
+	 (0x000000000000074Cull)
+#define CVMX_PCIEEP_CFG468 \
+	 (0x0000000000000750ull)
+#define CVMX_PCIEEP_CFG490 \
+	 (0x00000000000007A8ull)
+#define CVMX_PCIEEP_CFG491 \
+	 (0x00000000000007ACull)
+#define CVMX_PCIEEP_CFG492 \
+	 (0x00000000000007B0ull)
+#define CVMX_PCIEEP_CFG516 \
+	 (0x0000000000000810ull)
+#define CVMX_PCIEEP_CFG517 \
+	 (0x0000000000000814ull)
+
+union cvmx_pcieep_cfg000 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg000_s {
+		uint32_t devid:16;
+		uint32_t vendid:16;
+	} s;
+	struct cvmx_pcieep_cfg000_s cn52xx;
+	struct cvmx_pcieep_cfg000_s cn52xxp1;
+	struct cvmx_pcieep_cfg000_s cn56xx;
+	struct cvmx_pcieep_cfg000_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg001 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg001_s {
+		uint32_t dpe:1;
+		uint32_t sse:1;
+		uint32_t rma:1;
+		uint32_t rta:1;
+		uint32_t sta:1;
+		uint32_t devt:2;
+		uint32_t mdpe:1;
+		uint32_t fbb:1;
+		uint32_t reserved_22_22:1;
+		uint32_t m66:1;
+		uint32_t cl:1;
+		uint32_t i_stat:1;
+		uint32_t reserved_11_18:8;
+		uint32_t i_dis:1;
+		uint32_t fbbe:1;
+		uint32_t see:1;
+		uint32_t ids_wcc:1;
+		uint32_t per:1;
+		uint32_t vps:1;
+		uint32_t mwice:1;
+		uint32_t scse:1;
+		uint32_t me:1;
+		uint32_t msae:1;
+		uint32_t isae:1;
+	} s;
+	struct cvmx_pcieep_cfg001_s cn52xx;
+	struct cvmx_pcieep_cfg001_s cn52xxp1;
+	struct cvmx_pcieep_cfg001_s cn56xx;
+	struct cvmx_pcieep_cfg001_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg002 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg002_s {
+		uint32_t bcc:8;
+		uint32_t sc:8;
+		uint32_t pi:8;
+		uint32_t rid:8;
+	} s;
+	struct cvmx_pcieep_cfg002_s cn52xx;
+	struct cvmx_pcieep_cfg002_s cn52xxp1;
+	struct cvmx_pcieep_cfg002_s cn56xx;
+	struct cvmx_pcieep_cfg002_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg003 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg003_s {
+		uint32_t bist:8;
+		uint32_t mfd:1;
+		uint32_t chf:7;
+		uint32_t lt:8;
+		uint32_t cls:8;
+	} s;
+	struct cvmx_pcieep_cfg003_s cn52xx;
+	struct cvmx_pcieep_cfg003_s cn52xxp1;
+	struct cvmx_pcieep_cfg003_s cn56xx;
+	struct cvmx_pcieep_cfg003_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg004 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg004_s {
+		uint32_t lbab:18;
+		uint32_t reserved_4_13:10;
+		uint32_t pf:1;
+		uint32_t typ:2;
+		uint32_t mspc:1;
+	} s;
+	struct cvmx_pcieep_cfg004_s cn52xx;
+	struct cvmx_pcieep_cfg004_s cn52xxp1;
+	struct cvmx_pcieep_cfg004_s cn56xx;
+	struct cvmx_pcieep_cfg004_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg004_mask {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg004_mask_s {
+		uint32_t lmask:31;
+		uint32_t enb:1;
+	} s;
+	struct cvmx_pcieep_cfg004_mask_s cn52xx;
+	struct cvmx_pcieep_cfg004_mask_s cn52xxp1;
+	struct cvmx_pcieep_cfg004_mask_s cn56xx;
+	struct cvmx_pcieep_cfg004_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg005 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg005_s {
+		uint32_t ubab:32;
+	} s;
+	struct cvmx_pcieep_cfg005_s cn52xx;
+	struct cvmx_pcieep_cfg005_s cn52xxp1;
+	struct cvmx_pcieep_cfg005_s cn56xx;
+	struct cvmx_pcieep_cfg005_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg005_mask {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg005_mask_s {
+		uint32_t umask:32;
+	} s;
+	struct cvmx_pcieep_cfg005_mask_s cn52xx;
+	struct cvmx_pcieep_cfg005_mask_s cn52xxp1;
+	struct cvmx_pcieep_cfg005_mask_s cn56xx;
+	struct cvmx_pcieep_cfg005_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg006 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg006_s {
+		uint32_t lbab:6;
+		uint32_t reserved_4_25:22;
+		uint32_t pf:1;
+		uint32_t typ:2;
+		uint32_t mspc:1;
+	} s;
+	struct cvmx_pcieep_cfg006_s cn52xx;
+	struct cvmx_pcieep_cfg006_s cn52xxp1;
+	struct cvmx_pcieep_cfg006_s cn56xx;
+	struct cvmx_pcieep_cfg006_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg006_mask {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg006_mask_s {
+		uint32_t lmask:31;
+		uint32_t enb:1;
+	} s;
+	struct cvmx_pcieep_cfg006_mask_s cn52xx;
+	struct cvmx_pcieep_cfg006_mask_s cn52xxp1;
+	struct cvmx_pcieep_cfg006_mask_s cn56xx;
+	struct cvmx_pcieep_cfg006_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg007 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg007_s {
+		uint32_t ubab:32;
+	} s;
+	struct cvmx_pcieep_cfg007_s cn52xx;
+	struct cvmx_pcieep_cfg007_s cn52xxp1;
+	struct cvmx_pcieep_cfg007_s cn56xx;
+	struct cvmx_pcieep_cfg007_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg007_mask {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg007_mask_s {
+		uint32_t umask:32;
+	} s;
+	struct cvmx_pcieep_cfg007_mask_s cn52xx;
+	struct cvmx_pcieep_cfg007_mask_s cn52xxp1;
+	struct cvmx_pcieep_cfg007_mask_s cn56xx;
+	struct cvmx_pcieep_cfg007_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg008 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg008_s {
+		uint32_t reserved_4_31:28;
+		uint32_t pf:1;
+		uint32_t typ:2;
+		uint32_t mspc:1;
+	} s;
+	struct cvmx_pcieep_cfg008_s cn52xx;
+	struct cvmx_pcieep_cfg008_s cn52xxp1;
+	struct cvmx_pcieep_cfg008_s cn56xx;
+	struct cvmx_pcieep_cfg008_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg008_mask {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg008_mask_s {
+		uint32_t lmask:31;
+		uint32_t enb:1;
+	} s;
+	struct cvmx_pcieep_cfg008_mask_s cn52xx;
+	struct cvmx_pcieep_cfg008_mask_s cn52xxp1;
+	struct cvmx_pcieep_cfg008_mask_s cn56xx;
+	struct cvmx_pcieep_cfg008_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg009 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg009_s {
+		uint32_t ubab:25;
+		uint32_t reserved_0_6:7;
+	} s;
+	struct cvmx_pcieep_cfg009_s cn52xx;
+	struct cvmx_pcieep_cfg009_s cn52xxp1;
+	struct cvmx_pcieep_cfg009_s cn56xx;
+	struct cvmx_pcieep_cfg009_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg009_mask {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg009_mask_s {
+		uint32_t umask:32;
+	} s;
+	struct cvmx_pcieep_cfg009_mask_s cn52xx;
+	struct cvmx_pcieep_cfg009_mask_s cn52xxp1;
+	struct cvmx_pcieep_cfg009_mask_s cn56xx;
+	struct cvmx_pcieep_cfg009_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg010 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg010_s {
+		uint32_t cisp:32;
+	} s;
+	struct cvmx_pcieep_cfg010_s cn52xx;
+	struct cvmx_pcieep_cfg010_s cn52xxp1;
+	struct cvmx_pcieep_cfg010_s cn56xx;
+	struct cvmx_pcieep_cfg010_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg011 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg011_s {
+		uint32_t ssid:16;
+		uint32_t ssvid:16;
+	} s;
+	struct cvmx_pcieep_cfg011_s cn52xx;
+	struct cvmx_pcieep_cfg011_s cn52xxp1;
+	struct cvmx_pcieep_cfg011_s cn56xx;
+	struct cvmx_pcieep_cfg011_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg012 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg012_s {
+		uint32_t eraddr:16;
+		uint32_t reserved_1_15:15;
+		uint32_t er_en:1;
+	} s;
+	struct cvmx_pcieep_cfg012_s cn52xx;
+	struct cvmx_pcieep_cfg012_s cn52xxp1;
+	struct cvmx_pcieep_cfg012_s cn56xx;
+	struct cvmx_pcieep_cfg012_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg012_mask {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg012_mask_s {
+		uint32_t mask:31;
+		uint32_t enb:1;
+	} s;
+	struct cvmx_pcieep_cfg012_mask_s cn52xx;
+	struct cvmx_pcieep_cfg012_mask_s cn52xxp1;
+	struct cvmx_pcieep_cfg012_mask_s cn56xx;
+	struct cvmx_pcieep_cfg012_mask_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg013 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg013_s {
+		uint32_t reserved_8_31:24;
+		uint32_t cp:8;
+	} s;
+	struct cvmx_pcieep_cfg013_s cn52xx;
+	struct cvmx_pcieep_cfg013_s cn52xxp1;
+	struct cvmx_pcieep_cfg013_s cn56xx;
+	struct cvmx_pcieep_cfg013_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg015 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg015_s {
+		uint32_t ml:8;
+		uint32_t mg:8;
+		uint32_t inta:8;
+		uint32_t il:8;
+	} s;
+	struct cvmx_pcieep_cfg015_s cn52xx;
+	struct cvmx_pcieep_cfg015_s cn52xxp1;
+	struct cvmx_pcieep_cfg015_s cn56xx;
+	struct cvmx_pcieep_cfg015_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg016 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg016_s {
+		uint32_t pmes:5;
+		uint32_t d2s:1;
+		uint32_t d1s:1;
+		uint32_t auxc:3;
+		uint32_t dsi:1;
+		uint32_t reserved_20_20:1;
+		uint32_t pme_clock:1;
+		uint32_t pmsv:3;
+		uint32_t ncp:8;
+		uint32_t pmcid:8;
+	} s;
+	struct cvmx_pcieep_cfg016_s cn52xx;
+	struct cvmx_pcieep_cfg016_s cn52xxp1;
+	struct cvmx_pcieep_cfg016_s cn56xx;
+	struct cvmx_pcieep_cfg016_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg017 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg017_s {
+		uint32_t pmdia:8;
+		uint32_t bpccee:1;
+		uint32_t bd3h:1;
+		uint32_t reserved_16_21:6;
+		uint32_t pmess:1;
+		uint32_t pmedsia:2;
+		uint32_t pmds:4;
+		uint32_t pmeens:1;
+		uint32_t reserved_4_7:4;
+		uint32_t nsr:1;
+		uint32_t reserved_2_2:1;
+		uint32_t ps:2;
+	} s;
+	struct cvmx_pcieep_cfg017_s cn52xx;
+	struct cvmx_pcieep_cfg017_s cn52xxp1;
+	struct cvmx_pcieep_cfg017_s cn56xx;
+	struct cvmx_pcieep_cfg017_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg020 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg020_s {
+		uint32_t reserved_24_31:8;
+		uint32_t m64:1;
+		uint32_t mme:3;
+		uint32_t mmc:3;
+		uint32_t msien:1;
+		uint32_t ncp:8;
+		uint32_t msicid:8;
+	} s;
+	struct cvmx_pcieep_cfg020_s cn52xx;
+	struct cvmx_pcieep_cfg020_s cn52xxp1;
+	struct cvmx_pcieep_cfg020_s cn56xx;
+	struct cvmx_pcieep_cfg020_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg021 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg021_s {
+		uint32_t lmsi:30;
+		uint32_t reserved_0_1:2;
+	} s;
+	struct cvmx_pcieep_cfg021_s cn52xx;
+	struct cvmx_pcieep_cfg021_s cn52xxp1;
+	struct cvmx_pcieep_cfg021_s cn56xx;
+	struct cvmx_pcieep_cfg021_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg022 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg022_s {
+		uint32_t umsi:32;
+	} s;
+	struct cvmx_pcieep_cfg022_s cn52xx;
+	struct cvmx_pcieep_cfg022_s cn52xxp1;
+	struct cvmx_pcieep_cfg022_s cn56xx;
+	struct cvmx_pcieep_cfg022_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg023 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg023_s {
+		uint32_t reserved_16_31:16;
+		uint32_t msimd:16;
+	} s;
+	struct cvmx_pcieep_cfg023_s cn52xx;
+	struct cvmx_pcieep_cfg023_s cn52xxp1;
+	struct cvmx_pcieep_cfg023_s cn56xx;
+	struct cvmx_pcieep_cfg023_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg028 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg028_s {
+		uint32_t reserved_30_31:2;
+		uint32_t imn:5;
+		uint32_t si:1;
+		uint32_t dpt:4;
+		uint32_t pciecv:4;
+		uint32_t ncp:8;
+		uint32_t pcieid:8;
+	} s;
+	struct cvmx_pcieep_cfg028_s cn52xx;
+	struct cvmx_pcieep_cfg028_s cn52xxp1;
+	struct cvmx_pcieep_cfg028_s cn56xx;
+	struct cvmx_pcieep_cfg028_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg029 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg029_s {
+		uint32_t reserved_28_31:4;
+		uint32_t cspls:2;
+		uint32_t csplv:8;
+		uint32_t reserved_16_17:2;
+		uint32_t rber:1;
+		uint32_t reserved_12_14:3;
+		uint32_t el1al:3;
+		uint32_t el0al:3;
+		uint32_t etfs:1;
+		uint32_t pfs:2;
+		uint32_t mpss:3;
+	} s;
+	struct cvmx_pcieep_cfg029_s cn52xx;
+	struct cvmx_pcieep_cfg029_s cn52xxp1;
+	struct cvmx_pcieep_cfg029_s cn56xx;
+	struct cvmx_pcieep_cfg029_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg030 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg030_s {
+		uint32_t reserved_22_31:10;
+		uint32_t tp:1;
+		uint32_t ap_d:1;
+		uint32_t ur_d:1;
+		uint32_t fe_d:1;
+		uint32_t nfe_d:1;
+		uint32_t ce_d:1;
+		uint32_t reserved_15_15:1;
+		uint32_t mrrs:3;
+		uint32_t ns_en:1;
+		uint32_t ap_en:1;
+		uint32_t pf_en:1;
+		uint32_t etf_en:1;
+		uint32_t mps:3;
+		uint32_t ro_en:1;
+		uint32_t ur_en:1;
+		uint32_t fe_en:1;
+		uint32_t nfe_en:1;
+		uint32_t ce_en:1;
+	} s;
+	struct cvmx_pcieep_cfg030_s cn52xx;
+	struct cvmx_pcieep_cfg030_s cn52xxp1;
+	struct cvmx_pcieep_cfg030_s cn56xx;
+	struct cvmx_pcieep_cfg030_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg031 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg031_s {
+		uint32_t pnum:8;
+		uint32_t reserved_22_23:2;
+		uint32_t lbnc:1;
+		uint32_t dllarc:1;
+		uint32_t sderc:1;
+		uint32_t cpm:1;
+		uint32_t l1el:3;
+		uint32_t l0el:3;
+		uint32_t aslpms:2;
+		uint32_t mlw:6;
+		uint32_t mls:4;
+	} s;
+	struct cvmx_pcieep_cfg031_s cn52xx;
+	struct cvmx_pcieep_cfg031_s cn52xxp1;
+	struct cvmx_pcieep_cfg031_s cn56xx;
+	struct cvmx_pcieep_cfg031_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg032 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg032_s {
+		uint32_t reserved_30_31:2;
+		uint32_t dlla:1;
+		uint32_t scc:1;
+		uint32_t lt:1;
+		uint32_t reserved_26_26:1;
+		uint32_t nlw:6;
+		uint32_t ls:4;
+		uint32_t reserved_10_15:6;
+		uint32_t hawd:1;
+		uint32_t ecpm:1;
+		uint32_t es:1;
+		uint32_t ccc:1;
+		uint32_t rl:1;
+		uint32_t ld:1;
+		uint32_t rcb:1;
+		uint32_t reserved_2_2:1;
+		uint32_t aslpc:2;
+	} s;
+	struct cvmx_pcieep_cfg032_s cn52xx;
+	struct cvmx_pcieep_cfg032_s cn52xxp1;
+	struct cvmx_pcieep_cfg032_s cn56xx;
+	struct cvmx_pcieep_cfg032_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg033 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg033_s {
+		uint32_t ps_num:13;
+		uint32_t nccs:1;
+		uint32_t emip:1;
+		uint32_t sp_ls:2;
+		uint32_t sp_lv:8;
+		uint32_t hp_c:1;
+		uint32_t hp_s:1;
+		uint32_t pip:1;
+		uint32_t aip:1;
+		uint32_t mrlsp:1;
+		uint32_t pcp:1;
+		uint32_t abp:1;
+	} s;
+	struct cvmx_pcieep_cfg033_s cn52xx;
+	struct cvmx_pcieep_cfg033_s cn52xxp1;
+	struct cvmx_pcieep_cfg033_s cn56xx;
+	struct cvmx_pcieep_cfg033_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg034 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg034_s {
+		uint32_t reserved_25_31:7;
+		uint32_t dlls_c:1;
+		uint32_t emis:1;
+		uint32_t pds:1;
+		uint32_t mrlss:1;
+		uint32_t ccint_d:1;
+		uint32_t pd_c:1;
+		uint32_t mrls_c:1;
+		uint32_t pf_d:1;
+		uint32_t abp_d:1;
+		uint32_t reserved_13_15:3;
+		uint32_t dlls_en:1;
+		uint32_t emic:1;
+		uint32_t pcc:1;
+		uint32_t pic:2;
+		uint32_t aic:2;
+		uint32_t hpint_en:1;
+		uint32_t ccint_en:1;
+		uint32_t pd_en:1;
+		uint32_t mrls_en:1;
+		uint32_t pf_en:1;
+		uint32_t abp_en:1;
+	} s;
+	struct cvmx_pcieep_cfg034_s cn52xx;
+	struct cvmx_pcieep_cfg034_s cn52xxp1;
+	struct cvmx_pcieep_cfg034_s cn56xx;
+	struct cvmx_pcieep_cfg034_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg037 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg037_s {
+		uint32_t reserved_5_31:27;
+		uint32_t ctds:1;
+		uint32_t ctrs:4;
+	} s;
+	struct cvmx_pcieep_cfg037_s cn52xx;
+	struct cvmx_pcieep_cfg037_s cn52xxp1;
+	struct cvmx_pcieep_cfg037_s cn56xx;
+	struct cvmx_pcieep_cfg037_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg038 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg038_s {
+		uint32_t reserved_5_31:27;
+		uint32_t ctd:1;
+		uint32_t ctv:4;
+	} s;
+	struct cvmx_pcieep_cfg038_s cn52xx;
+	struct cvmx_pcieep_cfg038_s cn52xxp1;
+	struct cvmx_pcieep_cfg038_s cn56xx;
+	struct cvmx_pcieep_cfg038_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg039 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg039_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pcieep_cfg039_s cn52xx;
+	struct cvmx_pcieep_cfg039_s cn52xxp1;
+	struct cvmx_pcieep_cfg039_s cn56xx;
+	struct cvmx_pcieep_cfg039_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg040 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg040_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pcieep_cfg040_s cn52xx;
+	struct cvmx_pcieep_cfg040_s cn52xxp1;
+	struct cvmx_pcieep_cfg040_s cn56xx;
+	struct cvmx_pcieep_cfg040_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg041 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg041_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pcieep_cfg041_s cn52xx;
+	struct cvmx_pcieep_cfg041_s cn52xxp1;
+	struct cvmx_pcieep_cfg041_s cn56xx;
+	struct cvmx_pcieep_cfg041_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg042 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg042_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pcieep_cfg042_s cn52xx;
+	struct cvmx_pcieep_cfg042_s cn52xxp1;
+	struct cvmx_pcieep_cfg042_s cn56xx;
+	struct cvmx_pcieep_cfg042_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg064 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg064_s {
+		uint32_t nco:12;
+		uint32_t cv:4;
+		uint32_t pcieec:16;
+	} s;
+	struct cvmx_pcieep_cfg064_s cn52xx;
+	struct cvmx_pcieep_cfg064_s cn52xxp1;
+	struct cvmx_pcieep_cfg064_s cn56xx;
+	struct cvmx_pcieep_cfg064_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg065 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg065_s {
+		uint32_t reserved_21_31:11;
+		uint32_t ures:1;
+		uint32_t ecrces:1;
+		uint32_t mtlps:1;
+		uint32_t ros:1;
+		uint32_t ucs:1;
+		uint32_t cas:1;
+		uint32_t cts:1;
+		uint32_t fcpes:1;
+		uint32_t ptlps:1;
+		uint32_t reserved_6_11:6;
+		uint32_t sdes:1;
+		uint32_t dlpes:1;
+		uint32_t reserved_0_3:4;
+	} s;
+	struct cvmx_pcieep_cfg065_s cn52xx;
+	struct cvmx_pcieep_cfg065_s cn52xxp1;
+	struct cvmx_pcieep_cfg065_s cn56xx;
+	struct cvmx_pcieep_cfg065_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg066 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg066_s {
+		uint32_t reserved_21_31:11;
+		uint32_t urem:1;
+		uint32_t ecrcem:1;
+		uint32_t mtlpm:1;
+		uint32_t rom:1;
+		uint32_t ucm:1;
+		uint32_t cam:1;
+		uint32_t ctm:1;
+		uint32_t fcpem:1;
+		uint32_t ptlpm:1;
+		uint32_t reserved_6_11:6;
+		uint32_t sdem:1;
+		uint32_t dlpem:1;
+		uint32_t reserved_0_3:4;
+	} s;
+	struct cvmx_pcieep_cfg066_s cn52xx;
+	struct cvmx_pcieep_cfg066_s cn52xxp1;
+	struct cvmx_pcieep_cfg066_s cn56xx;
+	struct cvmx_pcieep_cfg066_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg067 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg067_s {
+		uint32_t reserved_21_31:11;
+		uint32_t ures:1;
+		uint32_t ecrces:1;
+		uint32_t mtlps:1;
+		uint32_t ros:1;
+		uint32_t ucs:1;
+		uint32_t cas:1;
+		uint32_t cts:1;
+		uint32_t fcpes:1;
+		uint32_t ptlps:1;
+		uint32_t reserved_6_11:6;
+		uint32_t sdes:1;
+		uint32_t dlpes:1;
+		uint32_t reserved_0_3:4;
+	} s;
+	struct cvmx_pcieep_cfg067_s cn52xx;
+	struct cvmx_pcieep_cfg067_s cn52xxp1;
+	struct cvmx_pcieep_cfg067_s cn56xx;
+	struct cvmx_pcieep_cfg067_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg068 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg068_s {
+		uint32_t reserved_14_31:18;
+		uint32_t anfes:1;
+		uint32_t rtts:1;
+		uint32_t reserved_9_11:3;
+		uint32_t rnrs:1;
+		uint32_t bdllps:1;
+		uint32_t btlps:1;
+		uint32_t reserved_1_5:5;
+		uint32_t res:1;
+	} s;
+	struct cvmx_pcieep_cfg068_s cn52xx;
+	struct cvmx_pcieep_cfg068_s cn52xxp1;
+	struct cvmx_pcieep_cfg068_s cn56xx;
+	struct cvmx_pcieep_cfg068_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg069 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg069_s {
+		uint32_t reserved_14_31:18;
+		uint32_t anfem:1;
+		uint32_t rttm:1;
+		uint32_t reserved_9_11:3;
+		uint32_t rnrm:1;
+		uint32_t bdllpm:1;
+		uint32_t btlpm:1;
+		uint32_t reserved_1_5:5;
+		uint32_t rem:1;
+	} s;
+	struct cvmx_pcieep_cfg069_s cn52xx;
+	struct cvmx_pcieep_cfg069_s cn52xxp1;
+	struct cvmx_pcieep_cfg069_s cn56xx;
+	struct cvmx_pcieep_cfg069_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg070 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg070_s {
+		uint32_t reserved_9_31:23;
+		uint32_t ce:1;
+		uint32_t cc:1;
+		uint32_t ge:1;
+		uint32_t gc:1;
+		uint32_t fep:5;
+	} s;
+	struct cvmx_pcieep_cfg070_s cn52xx;
+	struct cvmx_pcieep_cfg070_s cn52xxp1;
+	struct cvmx_pcieep_cfg070_s cn56xx;
+	struct cvmx_pcieep_cfg070_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg071 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg071_s {
+		uint32_t dword1:32;
+	} s;
+	struct cvmx_pcieep_cfg071_s cn52xx;
+	struct cvmx_pcieep_cfg071_s cn52xxp1;
+	struct cvmx_pcieep_cfg071_s cn56xx;
+	struct cvmx_pcieep_cfg071_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg072 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg072_s {
+		uint32_t dword2:32;
+	} s;
+	struct cvmx_pcieep_cfg072_s cn52xx;
+	struct cvmx_pcieep_cfg072_s cn52xxp1;
+	struct cvmx_pcieep_cfg072_s cn56xx;
+	struct cvmx_pcieep_cfg072_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg073 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg073_s {
+		uint32_t dword3:32;
+	} s;
+	struct cvmx_pcieep_cfg073_s cn52xx;
+	struct cvmx_pcieep_cfg073_s cn52xxp1;
+	struct cvmx_pcieep_cfg073_s cn56xx;
+	struct cvmx_pcieep_cfg073_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg074 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg074_s {
+		uint32_t dword4:32;
+	} s;
+	struct cvmx_pcieep_cfg074_s cn52xx;
+	struct cvmx_pcieep_cfg074_s cn52xxp1;
+	struct cvmx_pcieep_cfg074_s cn56xx;
+	struct cvmx_pcieep_cfg074_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg448 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg448_s {
+		uint32_t rtl:16;
+		uint32_t rtltl:16;
+	} s;
+	struct cvmx_pcieep_cfg448_s cn52xx;
+	struct cvmx_pcieep_cfg448_s cn52xxp1;
+	struct cvmx_pcieep_cfg448_s cn56xx;
+	struct cvmx_pcieep_cfg448_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg449 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg449_s {
+		uint32_t omr:32;
+	} s;
+	struct cvmx_pcieep_cfg449_s cn52xx;
+	struct cvmx_pcieep_cfg449_s cn52xxp1;
+	struct cvmx_pcieep_cfg449_s cn56xx;
+	struct cvmx_pcieep_cfg449_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg450 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg450_s {
+		uint32_t lpec:8;
+		uint32_t reserved_22_23:2;
+		uint32_t link_state:6;
+		uint32_t force_link:1;
+		uint32_t reserved_8_14:7;
+		uint32_t link_num:8;
+	} s;
+	struct cvmx_pcieep_cfg450_s cn52xx;
+	struct cvmx_pcieep_cfg450_s cn52xxp1;
+	struct cvmx_pcieep_cfg450_s cn56xx;
+	struct cvmx_pcieep_cfg450_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg451 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg451_s {
+		uint32_t reserved_30_31:2;
+		uint32_t l1el:3;
+		uint32_t l0el:3;
+		uint32_t n_fts_cc:8;
+		uint32_t n_fts:8;
+		uint32_t ack_freq:8;
+	} s;
+	struct cvmx_pcieep_cfg451_s cn52xx;
+	struct cvmx_pcieep_cfg451_s cn52xxp1;
+	struct cvmx_pcieep_cfg451_s cn56xx;
+	struct cvmx_pcieep_cfg451_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg452 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg452_s {
+		uint32_t reserved_26_31:6;
+		uint32_t eccrc:1;
+		uint32_t reserved_22_24:3;
+		uint32_t lme:6;
+		uint32_t reserved_8_15:8;
+		uint32_t flm:1;
+		uint32_t reserved_6_6:1;
+		uint32_t dllle:1;
+		uint32_t reserved_4_4:1;
+		uint32_t ra:1;
+		uint32_t le:1;
+		uint32_t sd:1;
+		uint32_t omr:1;
+	} s;
+	struct cvmx_pcieep_cfg452_s cn52xx;
+	struct cvmx_pcieep_cfg452_s cn52xxp1;
+	struct cvmx_pcieep_cfg452_s cn56xx;
+	struct cvmx_pcieep_cfg452_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg453 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg453_s {
+		uint32_t dlld:1;
+		uint32_t reserved_26_30:5;
+		uint32_t ack_nak:1;
+		uint32_t fcd:1;
+		uint32_t ilst:24;
+	} s;
+	struct cvmx_pcieep_cfg453_s cn52xx;
+	struct cvmx_pcieep_cfg453_s cn52xxp1;
+	struct cvmx_pcieep_cfg453_s cn56xx;
+	struct cvmx_pcieep_cfg453_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg454 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg454_s {
+		uint32_t reserved_29_31:3;
+		uint32_t tmfcwt:5;
+		uint32_t tmanlt:5;
+		uint32_t tmrt:5;
+		uint32_t reserved_11_13:3;
+		uint32_t nskps:3;
+		uint32_t reserved_4_7:4;
+		uint32_t ntss:4;
+	} s;
+	struct cvmx_pcieep_cfg454_s cn52xx;
+	struct cvmx_pcieep_cfg454_s cn52xxp1;
+	struct cvmx_pcieep_cfg454_s cn56xx;
+	struct cvmx_pcieep_cfg454_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg455 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg455_s {
+		uint32_t m_cfg0_filt:1;
+		uint32_t m_io_filt:1;
+		uint32_t msg_ctrl:1;
+		uint32_t m_cpl_ecrc_filt:1;
+		uint32_t m_ecrc_filt:1;
+		uint32_t m_cpl_len_err:1;
+		uint32_t m_cpl_attr_err:1;
+		uint32_t m_cpl_tc_err:1;
+		uint32_t m_cpl_fun_err:1;
+		uint32_t m_cpl_rid_err:1;
+		uint32_t m_cpl_tag_err:1;
+		uint32_t m_lk_filt:1;
+		uint32_t m_cfg1_filt:1;
+		uint32_t m_bar_match:1;
+		uint32_t m_pois_filt:1;
+		uint32_t m_fun:1;
+		uint32_t dfcwt:1;
+		uint32_t reserved_11_14:4;
+		uint32_t skpiv:11;
+	} s;
+	struct cvmx_pcieep_cfg455_s cn52xx;
+	struct cvmx_pcieep_cfg455_s cn52xxp1;
+	struct cvmx_pcieep_cfg455_s cn56xx;
+	struct cvmx_pcieep_cfg455_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg456 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg456_s {
+		uint32_t reserved_2_31:30;
+		uint32_t m_vend1_drp:1;
+		uint32_t m_vend0_drp:1;
+	} s;
+	struct cvmx_pcieep_cfg456_s cn52xx;
+	struct cvmx_pcieep_cfg456_s cn52xxp1;
+	struct cvmx_pcieep_cfg456_s cn56xx;
+	struct cvmx_pcieep_cfg456_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg458 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg458_s {
+		uint32_t dbg_info_l32:32;
+	} s;
+	struct cvmx_pcieep_cfg458_s cn52xx;
+	struct cvmx_pcieep_cfg458_s cn52xxp1;
+	struct cvmx_pcieep_cfg458_s cn56xx;
+	struct cvmx_pcieep_cfg458_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg459 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg459_s {
+		uint32_t dbg_info_u32:32;
+	} s;
+	struct cvmx_pcieep_cfg459_s cn52xx;
+	struct cvmx_pcieep_cfg459_s cn52xxp1;
+	struct cvmx_pcieep_cfg459_s cn56xx;
+	struct cvmx_pcieep_cfg459_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg460 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg460_s {
+		uint32_t reserved_20_31:12;
+		uint32_t tphfcc:8;
+		uint32_t tpdfcc:12;
+	} s;
+	struct cvmx_pcieep_cfg460_s cn52xx;
+	struct cvmx_pcieep_cfg460_s cn52xxp1;
+	struct cvmx_pcieep_cfg460_s cn56xx;
+	struct cvmx_pcieep_cfg460_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg461 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg461_s {
+		uint32_t reserved_20_31:12;
+		uint32_t tchfcc:8;
+		uint32_t tcdfcc:12;
+	} s;
+	struct cvmx_pcieep_cfg461_s cn52xx;
+	struct cvmx_pcieep_cfg461_s cn52xxp1;
+	struct cvmx_pcieep_cfg461_s cn56xx;
+	struct cvmx_pcieep_cfg461_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg462 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg462_s {
+		uint32_t reserved_20_31:12;
+		uint32_t tchfcc:8;
+		uint32_t tcdfcc:12;
+	} s;
+	struct cvmx_pcieep_cfg462_s cn52xx;
+	struct cvmx_pcieep_cfg462_s cn52xxp1;
+	struct cvmx_pcieep_cfg462_s cn56xx;
+	struct cvmx_pcieep_cfg462_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg463 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg463_s {
+		uint32_t reserved_3_31:29;
+		uint32_t rqne:1;
+		uint32_t trbne:1;
+		uint32_t rtlpfccnr:1;
+	} s;
+	struct cvmx_pcieep_cfg463_s cn52xx;
+	struct cvmx_pcieep_cfg463_s cn52xxp1;
+	struct cvmx_pcieep_cfg463_s cn56xx;
+	struct cvmx_pcieep_cfg463_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg464 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg464_s {
+		uint32_t wrr_vc3:8;
+		uint32_t wrr_vc2:8;
+		uint32_t wrr_vc1:8;
+		uint32_t wrr_vc0:8;
+	} s;
+	struct cvmx_pcieep_cfg464_s cn52xx;
+	struct cvmx_pcieep_cfg464_s cn52xxp1;
+	struct cvmx_pcieep_cfg464_s cn56xx;
+	struct cvmx_pcieep_cfg464_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg465 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg465_s {
+		uint32_t wrr_vc7:8;
+		uint32_t wrr_vc6:8;
+		uint32_t wrr_vc5:8;
+		uint32_t wrr_vc4:8;
+	} s;
+	struct cvmx_pcieep_cfg465_s cn52xx;
+	struct cvmx_pcieep_cfg465_s cn52xxp1;
+	struct cvmx_pcieep_cfg465_s cn56xx;
+	struct cvmx_pcieep_cfg465_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg466 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg466_s {
+		uint32_t rx_queue_order:1;
+		uint32_t type_ordering:1;
+		uint32_t reserved_24_29:6;
+		uint32_t queue_mode:3;
+		uint32_t reserved_20_20:1;
+		uint32_t header_credits:8;
+		uint32_t data_credits:12;
+	} s;
+	struct cvmx_pcieep_cfg466_s cn52xx;
+	struct cvmx_pcieep_cfg466_s cn52xxp1;
+	struct cvmx_pcieep_cfg466_s cn56xx;
+	struct cvmx_pcieep_cfg466_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg467 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg467_s {
+		uint32_t reserved_24_31:8;
+		uint32_t queue_mode:3;
+		uint32_t reserved_20_20:1;
+		uint32_t header_credits:8;
+		uint32_t data_credits:12;
+	} s;
+	struct cvmx_pcieep_cfg467_s cn52xx;
+	struct cvmx_pcieep_cfg467_s cn52xxp1;
+	struct cvmx_pcieep_cfg467_s cn56xx;
+	struct cvmx_pcieep_cfg467_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg468 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg468_s {
+		uint32_t reserved_24_31:8;
+		uint32_t queue_mode:3;
+		uint32_t reserved_20_20:1;
+		uint32_t header_credits:8;
+		uint32_t data_credits:12;
+	} s;
+	struct cvmx_pcieep_cfg468_s cn52xx;
+	struct cvmx_pcieep_cfg468_s cn52xxp1;
+	struct cvmx_pcieep_cfg468_s cn56xx;
+	struct cvmx_pcieep_cfg468_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg490 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg490_s {
+		uint32_t reserved_26_31:6;
+		uint32_t header_depth:10;
+		uint32_t reserved_14_15:2;
+		uint32_t data_depth:14;
+	} s;
+	struct cvmx_pcieep_cfg490_s cn52xx;
+	struct cvmx_pcieep_cfg490_s cn52xxp1;
+	struct cvmx_pcieep_cfg490_s cn56xx;
+	struct cvmx_pcieep_cfg490_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg491 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg491_s {
+		uint32_t reserved_26_31:6;
+		uint32_t header_depth:10;
+		uint32_t reserved_14_15:2;
+		uint32_t data_depth:14;
+	} s;
+	struct cvmx_pcieep_cfg491_s cn52xx;
+	struct cvmx_pcieep_cfg491_s cn52xxp1;
+	struct cvmx_pcieep_cfg491_s cn56xx;
+	struct cvmx_pcieep_cfg491_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg492 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg492_s {
+		uint32_t reserved_26_31:6;
+		uint32_t header_depth:10;
+		uint32_t reserved_14_15:2;
+		uint32_t data_depth:14;
+	} s;
+	struct cvmx_pcieep_cfg492_s cn52xx;
+	struct cvmx_pcieep_cfg492_s cn52xxp1;
+	struct cvmx_pcieep_cfg492_s cn56xx;
+	struct cvmx_pcieep_cfg492_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg516 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg516_s {
+		uint32_t phy_stat:32;
+	} s;
+	struct cvmx_pcieep_cfg516_s cn52xx;
+	struct cvmx_pcieep_cfg516_s cn52xxp1;
+	struct cvmx_pcieep_cfg516_s cn56xx;
+	struct cvmx_pcieep_cfg516_s cn56xxp1;
+};
+
+union cvmx_pcieep_cfg517 {
+	uint32_t u32;
+	struct cvmx_pcieep_cfg517_s {
+		uint32_t phy_ctrl:32;
+	} s;
+	struct cvmx_pcieep_cfg517_s cn52xx;
+	struct cvmx_pcieep_cfg517_s cn52xxp1;
+	struct cvmx_pcieep_cfg517_s cn56xx;
+	struct cvmx_pcieep_cfg517_s cn56xxp1;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pciercx-defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1397 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PCIERCX_DEFS_H__
+#define __CVMX_PCIERCX_DEFS_H__
+
+#define CVMX_PCIERCX_CFG000(offset) \
+	 (0x0000000000000000ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG001(offset) \
+	 (0x0000000000000004ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG002(offset) \
+	 (0x0000000000000008ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG003(offset) \
+	 (0x000000000000000Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG004(offset) \
+	 (0x0000000000000010ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG005(offset) \
+	 (0x0000000000000014ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG006(offset) \
+	 (0x0000000000000018ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG007(offset) \
+	 (0x000000000000001Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG008(offset) \
+	 (0x0000000000000020ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG009(offset) \
+	 (0x0000000000000024ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG010(offset) \
+	 (0x0000000000000028ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG011(offset) \
+	 (0x000000000000002Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG012(offset) \
+	 (0x0000000000000030ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG013(offset) \
+	 (0x0000000000000034ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG014(offset) \
+	 (0x0000000000000038ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG015(offset) \
+	 (0x000000000000003Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG016(offset) \
+	 (0x0000000000000040ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG017(offset) \
+	 (0x0000000000000044ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG020(offset) \
+	 (0x0000000000000050ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG021(offset) \
+	 (0x0000000000000054ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG022(offset) \
+	 (0x0000000000000058ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG023(offset) \
+	 (0x000000000000005Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG028(offset) \
+	 (0x0000000000000070ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG029(offset) \
+	 (0x0000000000000074ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG030(offset) \
+	 (0x0000000000000078ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG031(offset) \
+	 (0x000000000000007Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG032(offset) \
+	 (0x0000000000000080ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG033(offset) \
+	 (0x0000000000000084ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG034(offset) \
+	 (0x0000000000000088ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG035(offset) \
+	 (0x000000000000008Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG036(offset) \
+	 (0x0000000000000090ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG037(offset) \
+	 (0x0000000000000094ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG038(offset) \
+	 (0x0000000000000098ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG039(offset) \
+	 (0x000000000000009Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG040(offset) \
+	 (0x00000000000000A0ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG041(offset) \
+	 (0x00000000000000A4ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG042(offset) \
+	 (0x00000000000000A8ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG064(offset) \
+	 (0x0000000000000100ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG065(offset) \
+	 (0x0000000000000104ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG066(offset) \
+	 (0x0000000000000108ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG067(offset) \
+	 (0x000000000000010Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG068(offset) \
+	 (0x0000000000000110ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG069(offset) \
+	 (0x0000000000000114ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG070(offset) \
+	 (0x0000000000000118ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG071(offset) \
+	 (0x000000000000011Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG072(offset) \
+	 (0x0000000000000120ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG073(offset) \
+	 (0x0000000000000124ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG074(offset) \
+	 (0x0000000000000128ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG075(offset) \
+	 (0x000000000000012Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG076(offset) \
+	 (0x0000000000000130ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG077(offset) \
+	 (0x0000000000000134ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG448(offset) \
+	 (0x0000000000000700ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG449(offset) \
+	 (0x0000000000000704ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG450(offset) \
+	 (0x0000000000000708ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG451(offset) \
+	 (0x000000000000070Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG452(offset) \
+	 (0x0000000000000710ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG453(offset) \
+	 (0x0000000000000714ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG454(offset) \
+	 (0x0000000000000718ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG455(offset) \
+	 (0x000000000000071Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG456(offset) \
+	 (0x0000000000000720ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG458(offset) \
+	 (0x0000000000000728ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG459(offset) \
+	 (0x000000000000072Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG460(offset) \
+	 (0x0000000000000730ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG461(offset) \
+	 (0x0000000000000734ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG462(offset) \
+	 (0x0000000000000738ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG463(offset) \
+	 (0x000000000000073Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG464(offset) \
+	 (0x0000000000000740ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG465(offset) \
+	 (0x0000000000000744ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG466(offset) \
+	 (0x0000000000000748ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG467(offset) \
+	 (0x000000000000074Cull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG468(offset) \
+	 (0x0000000000000750ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG490(offset) \
+	 (0x00000000000007A8ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG491(offset) \
+	 (0x00000000000007ACull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG492(offset) \
+	 (0x00000000000007B0ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG516(offset) \
+	 (0x0000000000000810ull + (((offset) & 1) * 0))
+#define CVMX_PCIERCX_CFG517(offset) \
+	 (0x0000000000000814ull + (((offset) & 1) * 0))
+
+union cvmx_pciercx_cfg000 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg000_s {
+		uint32_t devid:16;
+		uint32_t vendid:16;
+	} s;
+	struct cvmx_pciercx_cfg000_s cn52xx;
+	struct cvmx_pciercx_cfg000_s cn52xxp1;
+	struct cvmx_pciercx_cfg000_s cn56xx;
+	struct cvmx_pciercx_cfg000_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg001 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg001_s {
+		uint32_t dpe:1;
+		uint32_t sse:1;
+		uint32_t rma:1;
+		uint32_t rta:1;
+		uint32_t sta:1;
+		uint32_t devt:2;
+		uint32_t mdpe:1;
+		uint32_t fbb:1;
+		uint32_t reserved_22_22:1;
+		uint32_t m66:1;
+		uint32_t cl:1;
+		uint32_t i_stat:1;
+		uint32_t reserved_11_18:8;
+		uint32_t i_dis:1;
+		uint32_t fbbe:1;
+		uint32_t see:1;
+		uint32_t ids_wcc:1;
+		uint32_t per:1;
+		uint32_t vps:1;
+		uint32_t mwice:1;
+		uint32_t scse:1;
+		uint32_t me:1;
+		uint32_t msae:1;
+		uint32_t isae:1;
+	} s;
+	struct cvmx_pciercx_cfg001_s cn52xx;
+	struct cvmx_pciercx_cfg001_s cn52xxp1;
+	struct cvmx_pciercx_cfg001_s cn56xx;
+	struct cvmx_pciercx_cfg001_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg002 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg002_s {
+		uint32_t bcc:8;
+		uint32_t sc:8;
+		uint32_t pi:8;
+		uint32_t rid:8;
+	} s;
+	struct cvmx_pciercx_cfg002_s cn52xx;
+	struct cvmx_pciercx_cfg002_s cn52xxp1;
+	struct cvmx_pciercx_cfg002_s cn56xx;
+	struct cvmx_pciercx_cfg002_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg003 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg003_s {
+		uint32_t bist:8;
+		uint32_t mfd:1;
+		uint32_t chf:7;
+		uint32_t lt:8;
+		uint32_t cls:8;
+	} s;
+	struct cvmx_pciercx_cfg003_s cn52xx;
+	struct cvmx_pciercx_cfg003_s cn52xxp1;
+	struct cvmx_pciercx_cfg003_s cn56xx;
+	struct cvmx_pciercx_cfg003_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg004 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg004_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pciercx_cfg004_s cn52xx;
+	struct cvmx_pciercx_cfg004_s cn52xxp1;
+	struct cvmx_pciercx_cfg004_s cn56xx;
+	struct cvmx_pciercx_cfg004_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg005 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg005_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pciercx_cfg005_s cn52xx;
+	struct cvmx_pciercx_cfg005_s cn52xxp1;
+	struct cvmx_pciercx_cfg005_s cn56xx;
+	struct cvmx_pciercx_cfg005_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg006 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg006_s {
+		uint32_t slt:8;
+		uint32_t subbnum:8;
+		uint32_t sbnum:8;
+		uint32_t pbnum:8;
+	} s;
+	struct cvmx_pciercx_cfg006_s cn52xx;
+	struct cvmx_pciercx_cfg006_s cn52xxp1;
+	struct cvmx_pciercx_cfg006_s cn56xx;
+	struct cvmx_pciercx_cfg006_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg007 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg007_s {
+		uint32_t dpe:1;
+		uint32_t sse:1;
+		uint32_t rma:1;
+		uint32_t rta:1;
+		uint32_t sta:1;
+		uint32_t devt:2;
+		uint32_t mdpe:1;
+		uint32_t fbb:1;
+		uint32_t reserved_22_22:1;
+		uint32_t m66:1;
+		uint32_t reserved_16_20:5;
+		uint32_t lio_limi:4;
+		uint32_t reserved_9_11:3;
+		uint32_t io32b:1;
+		uint32_t lio_base:4;
+		uint32_t reserved_1_3:3;
+		uint32_t io32a:1;
+	} s;
+	struct cvmx_pciercx_cfg007_s cn52xx;
+	struct cvmx_pciercx_cfg007_s cn52xxp1;
+	struct cvmx_pciercx_cfg007_s cn56xx;
+	struct cvmx_pciercx_cfg007_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg008 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg008_s {
+		uint32_t ml_addr:12;
+		uint32_t reserved_16_19:4;
+		uint32_t mb_addr:12;
+		uint32_t reserved_0_3:4;
+	} s;
+	struct cvmx_pciercx_cfg008_s cn52xx;
+	struct cvmx_pciercx_cfg008_s cn52xxp1;
+	struct cvmx_pciercx_cfg008_s cn56xx;
+	struct cvmx_pciercx_cfg008_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg009 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg009_s {
+		uint32_t lmem_limit:12;
+		uint32_t reserved_17_19:3;
+		uint32_t mem64b:1;
+		uint32_t lmem_base:12;
+		uint32_t reserved_1_3:3;
+		uint32_t mem64a:1;
+	} s;
+	struct cvmx_pciercx_cfg009_s cn52xx;
+	struct cvmx_pciercx_cfg009_s cn52xxp1;
+	struct cvmx_pciercx_cfg009_s cn56xx;
+	struct cvmx_pciercx_cfg009_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg010 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg010_s {
+		uint32_t umem_base:32;
+	} s;
+	struct cvmx_pciercx_cfg010_s cn52xx;
+	struct cvmx_pciercx_cfg010_s cn52xxp1;
+	struct cvmx_pciercx_cfg010_s cn56xx;
+	struct cvmx_pciercx_cfg010_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg011 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg011_s {
+		uint32_t umem_limit:32;
+	} s;
+	struct cvmx_pciercx_cfg011_s cn52xx;
+	struct cvmx_pciercx_cfg011_s cn52xxp1;
+	struct cvmx_pciercx_cfg011_s cn56xx;
+	struct cvmx_pciercx_cfg011_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg012 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg012_s {
+		uint32_t uio_limit:16;
+		uint32_t uio_base:16;
+	} s;
+	struct cvmx_pciercx_cfg012_s cn52xx;
+	struct cvmx_pciercx_cfg012_s cn52xxp1;
+	struct cvmx_pciercx_cfg012_s cn56xx;
+	struct cvmx_pciercx_cfg012_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg013 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg013_s {
+		uint32_t reserved_8_31:24;
+		uint32_t cp:8;
+	} s;
+	struct cvmx_pciercx_cfg013_s cn52xx;
+	struct cvmx_pciercx_cfg013_s cn52xxp1;
+	struct cvmx_pciercx_cfg013_s cn56xx;
+	struct cvmx_pciercx_cfg013_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg014 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg014_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pciercx_cfg014_s cn52xx;
+	struct cvmx_pciercx_cfg014_s cn52xxp1;
+	struct cvmx_pciercx_cfg014_s cn56xx;
+	struct cvmx_pciercx_cfg014_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg015 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg015_s {
+		uint32_t reserved_28_31:4;
+		uint32_t dtsees:1;
+		uint32_t dts:1;
+		uint32_t sdt:1;
+		uint32_t pdt:1;
+		uint32_t fbbe:1;
+		uint32_t sbrst:1;
+		uint32_t mam:1;
+		uint32_t vga16d:1;
+		uint32_t vgae:1;
+		uint32_t isae:1;
+		uint32_t see:1;
+		uint32_t pere:1;
+		uint32_t inta:8;
+		uint32_t il:8;
+	} s;
+	struct cvmx_pciercx_cfg015_s cn52xx;
+	struct cvmx_pciercx_cfg015_s cn52xxp1;
+	struct cvmx_pciercx_cfg015_s cn56xx;
+	struct cvmx_pciercx_cfg015_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg016 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg016_s {
+		uint32_t pmes:5;
+		uint32_t d2s:1;
+		uint32_t d1s:1;
+		uint32_t auxc:3;
+		uint32_t dsi:1;
+		uint32_t reserved_20_20:1;
+		uint32_t pme_clock:1;
+		uint32_t pmsv:3;
+		uint32_t ncp:8;
+		uint32_t pmcid:8;
+	} s;
+	struct cvmx_pciercx_cfg016_s cn52xx;
+	struct cvmx_pciercx_cfg016_s cn52xxp1;
+	struct cvmx_pciercx_cfg016_s cn56xx;
+	struct cvmx_pciercx_cfg016_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg017 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg017_s {
+		uint32_t pmdia:8;
+		uint32_t bpccee:1;
+		uint32_t bd3h:1;
+		uint32_t reserved_16_21:6;
+		uint32_t pmess:1;
+		uint32_t pmedsia:2;
+		uint32_t pmds:4;
+		uint32_t pmeens:1;
+		uint32_t reserved_4_7:4;
+		uint32_t nsr:1;
+		uint32_t reserved_2_2:1;
+		uint32_t ps:2;
+	} s;
+	struct cvmx_pciercx_cfg017_s cn52xx;
+	struct cvmx_pciercx_cfg017_s cn52xxp1;
+	struct cvmx_pciercx_cfg017_s cn56xx;
+	struct cvmx_pciercx_cfg017_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg020 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg020_s {
+		uint32_t reserved_24_31:8;
+		uint32_t m64:1;
+		uint32_t mme:3;
+		uint32_t mmc:3;
+		uint32_t msien:1;
+		uint32_t ncp:8;
+		uint32_t msicid:8;
+	} s;
+	struct cvmx_pciercx_cfg020_s cn52xx;
+	struct cvmx_pciercx_cfg020_s cn52xxp1;
+	struct cvmx_pciercx_cfg020_s cn56xx;
+	struct cvmx_pciercx_cfg020_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg021 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg021_s {
+		uint32_t lmsi:30;
+		uint32_t reserved_0_1:2;
+	} s;
+	struct cvmx_pciercx_cfg021_s cn52xx;
+	struct cvmx_pciercx_cfg021_s cn52xxp1;
+	struct cvmx_pciercx_cfg021_s cn56xx;
+	struct cvmx_pciercx_cfg021_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg022 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg022_s {
+		uint32_t umsi:32;
+	} s;
+	struct cvmx_pciercx_cfg022_s cn52xx;
+	struct cvmx_pciercx_cfg022_s cn52xxp1;
+	struct cvmx_pciercx_cfg022_s cn56xx;
+	struct cvmx_pciercx_cfg022_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg023 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg023_s {
+		uint32_t reserved_16_31:16;
+		uint32_t msimd:16;
+	} s;
+	struct cvmx_pciercx_cfg023_s cn52xx;
+	struct cvmx_pciercx_cfg023_s cn52xxp1;
+	struct cvmx_pciercx_cfg023_s cn56xx;
+	struct cvmx_pciercx_cfg023_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg028 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg028_s {
+		uint32_t reserved_30_31:2;
+		uint32_t imn:5;
+		uint32_t si:1;
+		uint32_t dpt:4;
+		uint32_t pciecv:4;
+		uint32_t ncp:8;
+		uint32_t pcieid:8;
+	} s;
+	struct cvmx_pciercx_cfg028_s cn52xx;
+	struct cvmx_pciercx_cfg028_s cn52xxp1;
+	struct cvmx_pciercx_cfg028_s cn56xx;
+	struct cvmx_pciercx_cfg028_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg029 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg029_s {
+		uint32_t reserved_28_31:4;
+		uint32_t cspls:2;
+		uint32_t csplv:8;
+		uint32_t reserved_16_17:2;
+		uint32_t rber:1;
+		uint32_t reserved_12_14:3;
+		uint32_t el1al:3;
+		uint32_t el0al:3;
+		uint32_t etfs:1;
+		uint32_t pfs:2;
+		uint32_t mpss:3;
+	} s;
+	struct cvmx_pciercx_cfg029_s cn52xx;
+	struct cvmx_pciercx_cfg029_s cn52xxp1;
+	struct cvmx_pciercx_cfg029_s cn56xx;
+	struct cvmx_pciercx_cfg029_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg030 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg030_s {
+		uint32_t reserved_22_31:10;
+		uint32_t tp:1;
+		uint32_t ap_d:1;
+		uint32_t ur_d:1;
+		uint32_t fe_d:1;
+		uint32_t nfe_d:1;
+		uint32_t ce_d:1;
+		uint32_t reserved_15_15:1;
+		uint32_t mrrs:3;
+		uint32_t ns_en:1;
+		uint32_t ap_en:1;
+		uint32_t pf_en:1;
+		uint32_t etf_en:1;
+		uint32_t mps:3;
+		uint32_t ro_en:1;
+		uint32_t ur_en:1;
+		uint32_t fe_en:1;
+		uint32_t nfe_en:1;
+		uint32_t ce_en:1;
+	} s;
+	struct cvmx_pciercx_cfg030_s cn52xx;
+	struct cvmx_pciercx_cfg030_s cn52xxp1;
+	struct cvmx_pciercx_cfg030_s cn56xx;
+	struct cvmx_pciercx_cfg030_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg031 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg031_s {
+		uint32_t pnum:8;
+		uint32_t reserved_22_23:2;
+		uint32_t lbnc:1;
+		uint32_t dllarc:1;
+		uint32_t sderc:1;
+		uint32_t cpm:1;
+		uint32_t l1el:3;
+		uint32_t l0el:3;
+		uint32_t aslpms:2;
+		uint32_t mlw:6;
+		uint32_t mls:4;
+	} s;
+	struct cvmx_pciercx_cfg031_s cn52xx;
+	struct cvmx_pciercx_cfg031_s cn52xxp1;
+	struct cvmx_pciercx_cfg031_s cn56xx;
+	struct cvmx_pciercx_cfg031_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg032 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg032_s {
+		uint32_t lab:1;
+		uint32_t lbm:1;
+		uint32_t dlla:1;
+		uint32_t scc:1;
+		uint32_t lt:1;
+		uint32_t reserved_26_26:1;
+		uint32_t nlw:6;
+		uint32_t ls:4;
+		uint32_t reserved_12_15:4;
+		uint32_t lab_int_enb:1;
+		uint32_t lbm_int_enb:1;
+		uint32_t hawd:1;
+		uint32_t ecpm:1;
+		uint32_t es:1;
+		uint32_t ccc:1;
+		uint32_t rl:1;
+		uint32_t ld:1;
+		uint32_t rcb:1;
+		uint32_t reserved_2_2:1;
+		uint32_t aslpc:2;
+	} s;
+	struct cvmx_pciercx_cfg032_s cn52xx;
+	struct cvmx_pciercx_cfg032_s cn52xxp1;
+	struct cvmx_pciercx_cfg032_s cn56xx;
+	struct cvmx_pciercx_cfg032_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg033 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg033_s {
+		uint32_t ps_num:13;
+		uint32_t nccs:1;
+		uint32_t emip:1;
+		uint32_t sp_ls:2;
+		uint32_t sp_lv:8;
+		uint32_t hp_c:1;
+		uint32_t hp_s:1;
+		uint32_t pip:1;
+		uint32_t aip:1;
+		uint32_t mrlsp:1;
+		uint32_t pcp:1;
+		uint32_t abp:1;
+	} s;
+	struct cvmx_pciercx_cfg033_s cn52xx;
+	struct cvmx_pciercx_cfg033_s cn52xxp1;
+	struct cvmx_pciercx_cfg033_s cn56xx;
+	struct cvmx_pciercx_cfg033_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg034 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg034_s {
+		uint32_t reserved_25_31:7;
+		uint32_t dlls_c:1;
+		uint32_t emis:1;
+		uint32_t pds:1;
+		uint32_t mrlss:1;
+		uint32_t ccint_d:1;
+		uint32_t pd_c:1;
+		uint32_t mrls_c:1;
+		uint32_t pf_d:1;
+		uint32_t abp_d:1;
+		uint32_t reserved_13_15:3;
+		uint32_t dlls_en:1;
+		uint32_t emic:1;
+		uint32_t pcc:1;
+		uint32_t pic:2;
+		uint32_t aic:2;
+		uint32_t hpint_en:1;
+		uint32_t ccint_en:1;
+		uint32_t pd_en:1;
+		uint32_t mrls_en:1;
+		uint32_t pf_en:1;
+		uint32_t abp_en:1;
+	} s;
+	struct cvmx_pciercx_cfg034_s cn52xx;
+	struct cvmx_pciercx_cfg034_s cn52xxp1;
+	struct cvmx_pciercx_cfg034_s cn56xx;
+	struct cvmx_pciercx_cfg034_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg035 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg035_s {
+		uint32_t reserved_17_31:15;
+		uint32_t crssv:1;
+		uint32_t reserved_5_15:11;
+		uint32_t crssve:1;
+		uint32_t pmeie:1;
+		uint32_t sefee:1;
+		uint32_t senfee:1;
+		uint32_t secee:1;
+	} s;
+	struct cvmx_pciercx_cfg035_s cn52xx;
+	struct cvmx_pciercx_cfg035_s cn52xxp1;
+	struct cvmx_pciercx_cfg035_s cn56xx;
+	struct cvmx_pciercx_cfg035_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg036 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg036_s {
+		uint32_t reserved_18_31:14;
+		uint32_t pme_pend:1;
+		uint32_t pme_stat:1;
+		uint32_t pme_rid:16;
+	} s;
+	struct cvmx_pciercx_cfg036_s cn52xx;
+	struct cvmx_pciercx_cfg036_s cn52xxp1;
+	struct cvmx_pciercx_cfg036_s cn56xx;
+	struct cvmx_pciercx_cfg036_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg037 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg037_s {
+		uint32_t reserved_5_31:27;
+		uint32_t ctds:1;
+		uint32_t ctrs:4;
+	} s;
+	struct cvmx_pciercx_cfg037_s cn52xx;
+	struct cvmx_pciercx_cfg037_s cn52xxp1;
+	struct cvmx_pciercx_cfg037_s cn56xx;
+	struct cvmx_pciercx_cfg037_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg038 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg038_s {
+		uint32_t reserved_5_31:27;
+		uint32_t ctd:1;
+		uint32_t ctv:4;
+	} s;
+	struct cvmx_pciercx_cfg038_s cn52xx;
+	struct cvmx_pciercx_cfg038_s cn52xxp1;
+	struct cvmx_pciercx_cfg038_s cn56xx;
+	struct cvmx_pciercx_cfg038_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg039 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg039_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pciercx_cfg039_s cn52xx;
+	struct cvmx_pciercx_cfg039_s cn52xxp1;
+	struct cvmx_pciercx_cfg039_s cn56xx;
+	struct cvmx_pciercx_cfg039_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg040 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg040_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pciercx_cfg040_s cn52xx;
+	struct cvmx_pciercx_cfg040_s cn52xxp1;
+	struct cvmx_pciercx_cfg040_s cn56xx;
+	struct cvmx_pciercx_cfg040_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg041 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg041_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pciercx_cfg041_s cn52xx;
+	struct cvmx_pciercx_cfg041_s cn52xxp1;
+	struct cvmx_pciercx_cfg041_s cn56xx;
+	struct cvmx_pciercx_cfg041_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg042 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg042_s {
+		uint32_t reserved_0_31:32;
+	} s;
+	struct cvmx_pciercx_cfg042_s cn52xx;
+	struct cvmx_pciercx_cfg042_s cn52xxp1;
+	struct cvmx_pciercx_cfg042_s cn56xx;
+	struct cvmx_pciercx_cfg042_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg064 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg064_s {
+		uint32_t nco:12;
+		uint32_t cv:4;
+		uint32_t pcieec:16;
+	} s;
+	struct cvmx_pciercx_cfg064_s cn52xx;
+	struct cvmx_pciercx_cfg064_s cn52xxp1;
+	struct cvmx_pciercx_cfg064_s cn56xx;
+	struct cvmx_pciercx_cfg064_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg065 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg065_s {
+		uint32_t reserved_21_31:11;
+		uint32_t ures:1;
+		uint32_t ecrces:1;
+		uint32_t mtlps:1;
+		uint32_t ros:1;
+		uint32_t ucs:1;
+		uint32_t cas:1;
+		uint32_t cts:1;
+		uint32_t fcpes:1;
+		uint32_t ptlps:1;
+		uint32_t reserved_6_11:6;
+		uint32_t sdes:1;
+		uint32_t dlpes:1;
+		uint32_t reserved_0_3:4;
+	} s;
+	struct cvmx_pciercx_cfg065_s cn52xx;
+	struct cvmx_pciercx_cfg065_s cn52xxp1;
+	struct cvmx_pciercx_cfg065_s cn56xx;
+	struct cvmx_pciercx_cfg065_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg066 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg066_s {
+		uint32_t reserved_21_31:11;
+		uint32_t urem:1;
+		uint32_t ecrcem:1;
+		uint32_t mtlpm:1;
+		uint32_t rom:1;
+		uint32_t ucm:1;
+		uint32_t cam:1;
+		uint32_t ctm:1;
+		uint32_t fcpem:1;
+		uint32_t ptlpm:1;
+		uint32_t reserved_6_11:6;
+		uint32_t sdem:1;
+		uint32_t dlpem:1;
+		uint32_t reserved_0_3:4;
+	} s;
+	struct cvmx_pciercx_cfg066_s cn52xx;
+	struct cvmx_pciercx_cfg066_s cn52xxp1;
+	struct cvmx_pciercx_cfg066_s cn56xx;
+	struct cvmx_pciercx_cfg066_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg067 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg067_s {
+		uint32_t reserved_21_31:11;
+		uint32_t ures:1;
+		uint32_t ecrces:1;
+		uint32_t mtlps:1;
+		uint32_t ros:1;
+		uint32_t ucs:1;
+		uint32_t cas:1;
+		uint32_t cts:1;
+		uint32_t fcpes:1;
+		uint32_t ptlps:1;
+		uint32_t reserved_6_11:6;
+		uint32_t sdes:1;
+		uint32_t dlpes:1;
+		uint32_t reserved_0_3:4;
+	} s;
+	struct cvmx_pciercx_cfg067_s cn52xx;
+	struct cvmx_pciercx_cfg067_s cn52xxp1;
+	struct cvmx_pciercx_cfg067_s cn56xx;
+	struct cvmx_pciercx_cfg067_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg068 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg068_s {
+		uint32_t reserved_14_31:18;
+		uint32_t anfes:1;
+		uint32_t rtts:1;
+		uint32_t reserved_9_11:3;
+		uint32_t rnrs:1;
+		uint32_t bdllps:1;
+		uint32_t btlps:1;
+		uint32_t reserved_1_5:5;
+		uint32_t res:1;
+	} s;
+	struct cvmx_pciercx_cfg068_s cn52xx;
+	struct cvmx_pciercx_cfg068_s cn52xxp1;
+	struct cvmx_pciercx_cfg068_s cn56xx;
+	struct cvmx_pciercx_cfg068_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg069 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg069_s {
+		uint32_t reserved_14_31:18;
+		uint32_t anfem:1;
+		uint32_t rttm:1;
+		uint32_t reserved_9_11:3;
+		uint32_t rnrm:1;
+		uint32_t bdllpm:1;
+		uint32_t btlpm:1;
+		uint32_t reserved_1_5:5;
+		uint32_t rem:1;
+	} s;
+	struct cvmx_pciercx_cfg069_s cn52xx;
+	struct cvmx_pciercx_cfg069_s cn52xxp1;
+	struct cvmx_pciercx_cfg069_s cn56xx;
+	struct cvmx_pciercx_cfg069_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg070 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg070_s {
+		uint32_t reserved_9_31:23;
+		uint32_t ce:1;
+		uint32_t cc:1;
+		uint32_t ge:1;
+		uint32_t gc:1;
+		uint32_t fep:5;
+	} s;
+	struct cvmx_pciercx_cfg070_s cn52xx;
+	struct cvmx_pciercx_cfg070_s cn52xxp1;
+	struct cvmx_pciercx_cfg070_s cn56xx;
+	struct cvmx_pciercx_cfg070_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg071 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg071_s {
+		uint32_t dword1:32;
+	} s;
+	struct cvmx_pciercx_cfg071_s cn52xx;
+	struct cvmx_pciercx_cfg071_s cn52xxp1;
+	struct cvmx_pciercx_cfg071_s cn56xx;
+	struct cvmx_pciercx_cfg071_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg072 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg072_s {
+		uint32_t dword2:32;
+	} s;
+	struct cvmx_pciercx_cfg072_s cn52xx;
+	struct cvmx_pciercx_cfg072_s cn52xxp1;
+	struct cvmx_pciercx_cfg072_s cn56xx;
+	struct cvmx_pciercx_cfg072_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg073 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg073_s {
+		uint32_t dword3:32;
+	} s;
+	struct cvmx_pciercx_cfg073_s cn52xx;
+	struct cvmx_pciercx_cfg073_s cn52xxp1;
+	struct cvmx_pciercx_cfg073_s cn56xx;
+	struct cvmx_pciercx_cfg073_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg074 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg074_s {
+		uint32_t dword4:32;
+	} s;
+	struct cvmx_pciercx_cfg074_s cn52xx;
+	struct cvmx_pciercx_cfg074_s cn52xxp1;
+	struct cvmx_pciercx_cfg074_s cn56xx;
+	struct cvmx_pciercx_cfg074_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg075 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg075_s {
+		uint32_t reserved_3_31:29;
+		uint32_t fere:1;
+		uint32_t nfere:1;
+		uint32_t cere:1;
+	} s;
+	struct cvmx_pciercx_cfg075_s cn52xx;
+	struct cvmx_pciercx_cfg075_s cn52xxp1;
+	struct cvmx_pciercx_cfg075_s cn56xx;
+	struct cvmx_pciercx_cfg075_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg076 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg076_s {
+		uint32_t aeimn:5;
+		uint32_t reserved_7_26:20;
+		uint32_t femr:1;
+		uint32_t nfemr:1;
+		uint32_t fuf:1;
+		uint32_t multi_efnfr:1;
+		uint32_t efnfr:1;
+		uint32_t multi_ecr:1;
+		uint32_t ecr:1;
+	} s;
+	struct cvmx_pciercx_cfg076_s cn52xx;
+	struct cvmx_pciercx_cfg076_s cn52xxp1;
+	struct cvmx_pciercx_cfg076_s cn56xx;
+	struct cvmx_pciercx_cfg076_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg077 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg077_s {
+		uint32_t efnfsi:16;
+		uint32_t ecsi:16;
+	} s;
+	struct cvmx_pciercx_cfg077_s cn52xx;
+	struct cvmx_pciercx_cfg077_s cn52xxp1;
+	struct cvmx_pciercx_cfg077_s cn56xx;
+	struct cvmx_pciercx_cfg077_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg448 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg448_s {
+		uint32_t rtl:16;
+		uint32_t rtltl:16;
+	} s;
+	struct cvmx_pciercx_cfg448_s cn52xx;
+	struct cvmx_pciercx_cfg448_s cn52xxp1;
+	struct cvmx_pciercx_cfg448_s cn56xx;
+	struct cvmx_pciercx_cfg448_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg449 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg449_s {
+		uint32_t omr:32;
+	} s;
+	struct cvmx_pciercx_cfg449_s cn52xx;
+	struct cvmx_pciercx_cfg449_s cn52xxp1;
+	struct cvmx_pciercx_cfg449_s cn56xx;
+	struct cvmx_pciercx_cfg449_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg450 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg450_s {
+		uint32_t lpec:8;
+		uint32_t reserved_22_23:2;
+		uint32_t link_state:6;
+		uint32_t force_link:1;
+		uint32_t reserved_8_14:7;
+		uint32_t link_num:8;
+	} s;
+	struct cvmx_pciercx_cfg450_s cn52xx;
+	struct cvmx_pciercx_cfg450_s cn52xxp1;
+	struct cvmx_pciercx_cfg450_s cn56xx;
+	struct cvmx_pciercx_cfg450_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg451 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg451_s {
+		uint32_t reserved_30_31:2;
+		uint32_t l1el:3;
+		uint32_t l0el:3;
+		uint32_t n_fts_cc:8;
+		uint32_t n_fts:8;
+		uint32_t ack_freq:8;
+	} s;
+	struct cvmx_pciercx_cfg451_s cn52xx;
+	struct cvmx_pciercx_cfg451_s cn52xxp1;
+	struct cvmx_pciercx_cfg451_s cn56xx;
+	struct cvmx_pciercx_cfg451_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg452 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg452_s {
+		uint32_t reserved_26_31:6;
+		uint32_t eccrc:1;
+		uint32_t reserved_22_24:3;
+		uint32_t lme:6;
+		uint32_t reserved_8_15:8;
+		uint32_t flm:1;
+		uint32_t reserved_6_6:1;
+		uint32_t dllle:1;
+		uint32_t reserved_4_4:1;
+		uint32_t ra:1;
+		uint32_t le:1;
+		uint32_t sd:1;
+		uint32_t omr:1;
+	} s;
+	struct cvmx_pciercx_cfg452_s cn52xx;
+	struct cvmx_pciercx_cfg452_s cn52xxp1;
+	struct cvmx_pciercx_cfg452_s cn56xx;
+	struct cvmx_pciercx_cfg452_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg453 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg453_s {
+		uint32_t dlld:1;
+		uint32_t reserved_26_30:5;
+		uint32_t ack_nak:1;
+		uint32_t fcd:1;
+		uint32_t ilst:24;
+	} s;
+	struct cvmx_pciercx_cfg453_s cn52xx;
+	struct cvmx_pciercx_cfg453_s cn52xxp1;
+	struct cvmx_pciercx_cfg453_s cn56xx;
+	struct cvmx_pciercx_cfg453_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg454 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg454_s {
+		uint32_t reserved_29_31:3;
+		uint32_t tmfcwt:5;
+		uint32_t tmanlt:5;
+		uint32_t tmrt:5;
+		uint32_t reserved_11_13:3;
+		uint32_t nskps:3;
+		uint32_t reserved_4_7:4;
+		uint32_t ntss:4;
+	} s;
+	struct cvmx_pciercx_cfg454_s cn52xx;
+	struct cvmx_pciercx_cfg454_s cn52xxp1;
+	struct cvmx_pciercx_cfg454_s cn56xx;
+	struct cvmx_pciercx_cfg454_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg455 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg455_s {
+		uint32_t m_cfg0_filt:1;
+		uint32_t m_io_filt:1;
+		uint32_t msg_ctrl:1;
+		uint32_t m_cpl_ecrc_filt:1;
+		uint32_t m_ecrc_filt:1;
+		uint32_t m_cpl_len_err:1;
+		uint32_t m_cpl_attr_err:1;
+		uint32_t m_cpl_tc_err:1;
+		uint32_t m_cpl_fun_err:1;
+		uint32_t m_cpl_rid_err:1;
+		uint32_t m_cpl_tag_err:1;
+		uint32_t m_lk_filt:1;
+		uint32_t m_cfg1_filt:1;
+		uint32_t m_bar_match:1;
+		uint32_t m_pois_filt:1;
+		uint32_t m_fun:1;
+		uint32_t dfcwt:1;
+		uint32_t reserved_11_14:4;
+		uint32_t skpiv:11;
+	} s;
+	struct cvmx_pciercx_cfg455_s cn52xx;
+	struct cvmx_pciercx_cfg455_s cn52xxp1;
+	struct cvmx_pciercx_cfg455_s cn56xx;
+	struct cvmx_pciercx_cfg455_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg456 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg456_s {
+		uint32_t reserved_2_31:30;
+		uint32_t m_vend1_drp:1;
+		uint32_t m_vend0_drp:1;
+	} s;
+	struct cvmx_pciercx_cfg456_s cn52xx;
+	struct cvmx_pciercx_cfg456_s cn52xxp1;
+	struct cvmx_pciercx_cfg456_s cn56xx;
+	struct cvmx_pciercx_cfg456_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg458 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg458_s {
+		uint32_t dbg_info_l32:32;
+	} s;
+	struct cvmx_pciercx_cfg458_s cn52xx;
+	struct cvmx_pciercx_cfg458_s cn52xxp1;
+	struct cvmx_pciercx_cfg458_s cn56xx;
+	struct cvmx_pciercx_cfg458_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg459 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg459_s {
+		uint32_t dbg_info_u32:32;
+	} s;
+	struct cvmx_pciercx_cfg459_s cn52xx;
+	struct cvmx_pciercx_cfg459_s cn52xxp1;
+	struct cvmx_pciercx_cfg459_s cn56xx;
+	struct cvmx_pciercx_cfg459_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg460 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg460_s {
+		uint32_t reserved_20_31:12;
+		uint32_t tphfcc:8;
+		uint32_t tpdfcc:12;
+	} s;
+	struct cvmx_pciercx_cfg460_s cn52xx;
+	struct cvmx_pciercx_cfg460_s cn52xxp1;
+	struct cvmx_pciercx_cfg460_s cn56xx;
+	struct cvmx_pciercx_cfg460_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg461 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg461_s {
+		uint32_t reserved_20_31:12;
+		uint32_t tchfcc:8;
+		uint32_t tcdfcc:12;
+	} s;
+	struct cvmx_pciercx_cfg461_s cn52xx;
+	struct cvmx_pciercx_cfg461_s cn52xxp1;
+	struct cvmx_pciercx_cfg461_s cn56xx;
+	struct cvmx_pciercx_cfg461_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg462 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg462_s {
+		uint32_t reserved_20_31:12;
+		uint32_t tchfcc:8;
+		uint32_t tcdfcc:12;
+	} s;
+	struct cvmx_pciercx_cfg462_s cn52xx;
+	struct cvmx_pciercx_cfg462_s cn52xxp1;
+	struct cvmx_pciercx_cfg462_s cn56xx;
+	struct cvmx_pciercx_cfg462_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg463 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg463_s {
+		uint32_t reserved_3_31:29;
+		uint32_t rqne:1;
+		uint32_t trbne:1;
+		uint32_t rtlpfccnr:1;
+	} s;
+	struct cvmx_pciercx_cfg463_s cn52xx;
+	struct cvmx_pciercx_cfg463_s cn52xxp1;
+	struct cvmx_pciercx_cfg463_s cn56xx;
+	struct cvmx_pciercx_cfg463_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg464 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg464_s {
+		uint32_t wrr_vc3:8;
+		uint32_t wrr_vc2:8;
+		uint32_t wrr_vc1:8;
+		uint32_t wrr_vc0:8;
+	} s;
+	struct cvmx_pciercx_cfg464_s cn52xx;
+	struct cvmx_pciercx_cfg464_s cn52xxp1;
+	struct cvmx_pciercx_cfg464_s cn56xx;
+	struct cvmx_pciercx_cfg464_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg465 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg465_s {
+		uint32_t wrr_vc7:8;
+		uint32_t wrr_vc6:8;
+		uint32_t wrr_vc5:8;
+		uint32_t wrr_vc4:8;
+	} s;
+	struct cvmx_pciercx_cfg465_s cn52xx;
+	struct cvmx_pciercx_cfg465_s cn52xxp1;
+	struct cvmx_pciercx_cfg465_s cn56xx;
+	struct cvmx_pciercx_cfg465_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg466 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg466_s {
+		uint32_t rx_queue_order:1;
+		uint32_t type_ordering:1;
+		uint32_t reserved_24_29:6;
+		uint32_t queue_mode:3;
+		uint32_t reserved_20_20:1;
+		uint32_t header_credits:8;
+		uint32_t data_credits:12;
+	} s;
+	struct cvmx_pciercx_cfg466_s cn52xx;
+	struct cvmx_pciercx_cfg466_s cn52xxp1;
+	struct cvmx_pciercx_cfg466_s cn56xx;
+	struct cvmx_pciercx_cfg466_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg467 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg467_s {
+		uint32_t reserved_24_31:8;
+		uint32_t queue_mode:3;
+		uint32_t reserved_20_20:1;
+		uint32_t header_credits:8;
+		uint32_t data_credits:12;
+	} s;
+	struct cvmx_pciercx_cfg467_s cn52xx;
+	struct cvmx_pciercx_cfg467_s cn52xxp1;
+	struct cvmx_pciercx_cfg467_s cn56xx;
+	struct cvmx_pciercx_cfg467_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg468 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg468_s {
+		uint32_t reserved_24_31:8;
+		uint32_t queue_mode:3;
+		uint32_t reserved_20_20:1;
+		uint32_t header_credits:8;
+		uint32_t data_credits:12;
+	} s;
+	struct cvmx_pciercx_cfg468_s cn52xx;
+	struct cvmx_pciercx_cfg468_s cn52xxp1;
+	struct cvmx_pciercx_cfg468_s cn56xx;
+	struct cvmx_pciercx_cfg468_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg490 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg490_s {
+		uint32_t reserved_26_31:6;
+		uint32_t header_depth:10;
+		uint32_t reserved_14_15:2;
+		uint32_t data_depth:14;
+	} s;
+	struct cvmx_pciercx_cfg490_s cn52xx;
+	struct cvmx_pciercx_cfg490_s cn52xxp1;
+	struct cvmx_pciercx_cfg490_s cn56xx;
+	struct cvmx_pciercx_cfg490_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg491 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg491_s {
+		uint32_t reserved_26_31:6;
+		uint32_t header_depth:10;
+		uint32_t reserved_14_15:2;
+		uint32_t data_depth:14;
+	} s;
+	struct cvmx_pciercx_cfg491_s cn52xx;
+	struct cvmx_pciercx_cfg491_s cn52xxp1;
+	struct cvmx_pciercx_cfg491_s cn56xx;
+	struct cvmx_pciercx_cfg491_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg492 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg492_s {
+		uint32_t reserved_26_31:6;
+		uint32_t header_depth:10;
+		uint32_t reserved_14_15:2;
+		uint32_t data_depth:14;
+	} s;
+	struct cvmx_pciercx_cfg492_s cn52xx;
+	struct cvmx_pciercx_cfg492_s cn52xxp1;
+	struct cvmx_pciercx_cfg492_s cn56xx;
+	struct cvmx_pciercx_cfg492_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg516 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg516_s {
+		uint32_t phy_stat:32;
+	} s;
+	struct cvmx_pciercx_cfg516_s cn52xx;
+	struct cvmx_pciercx_cfg516_s cn52xxp1;
+	struct cvmx_pciercx_cfg516_s cn56xx;
+	struct cvmx_pciercx_cfg516_s cn56xxp1;
+};
+
+union cvmx_pciercx_cfg517 {
+	uint32_t u32;
+	struct cvmx_pciercx_cfg517_s {
+		uint32_t phy_ctrl:32;
+	} s;
+	struct cvmx_pciercx_cfg517_s cn52xx;
+	struct cvmx_pciercx_cfg517_s cn52xxp1;
+	struct cvmx_pciercx_cfg517_s cn56xx;
+	struct cvmx_pciercx_cfg517_s cn56xxp1;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pescx-defs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pescx-defs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pescx-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pescx-defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,410 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_PESCX_DEFS_H__
+#define __CVMX_PESCX_DEFS_H__
+
+#define CVMX_PESCX_BIST_STATUS(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000018ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_BIST_STATUS2(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000418ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CFG_RD(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000030ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CFG_WR(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000028ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CPL_LUT_VALID(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000098ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CTL_STATUS(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000000ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_CTL_STATUS2(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000400ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_DBG_INFO(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000008ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_DBG_INFO_EN(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C80000A0ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_DIAG_STATUS(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000020ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2N_BAR0_START(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000080ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2N_BAR1_START(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000088ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2N_BAR2_START(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000090ull + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2P_BARX_END(offset, block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000048ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_P2P_BARX_START(offset, block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000040ull + (((offset) & 3) * 16) + (((block_id) & 1) * 0x8000000ull))
+#define CVMX_PESCX_TLP_CREDITS(block_id) \
+	 CVMX_ADD_IO_SEG(0x00011800C8000038ull + (((block_id) & 1) * 0x8000000ull))
+
+union cvmx_pescx_bist_status {
+	uint64_t u64;
+	struct cvmx_pescx_bist_status_s {
+		uint64_t reserved_13_63:51;
+		uint64_t rqdata5:1;
+		uint64_t ctlp_or:1;
+		uint64_t ntlp_or:1;
+		uint64_t ptlp_or:1;
+		uint64_t retry:1;
+		uint64_t rqdata0:1;
+		uint64_t rqdata1:1;
+		uint64_t rqdata2:1;
+		uint64_t rqdata3:1;
+		uint64_t rqdata4:1;
+		uint64_t rqhdr1:1;
+		uint64_t rqhdr0:1;
+		uint64_t sot:1;
+	} s;
+	struct cvmx_pescx_bist_status_s cn52xx;
+	struct cvmx_pescx_bist_status_cn52xxp1 {
+		uint64_t reserved_12_63:52;
+		uint64_t ctlp_or:1;
+		uint64_t ntlp_or:1;
+		uint64_t ptlp_or:1;
+		uint64_t retry:1;
+		uint64_t rqdata0:1;
+		uint64_t rqdata1:1;
+		uint64_t rqdata2:1;
+		uint64_t rqdata3:1;
+		uint64_t rqdata4:1;
+		uint64_t rqhdr1:1;
+		uint64_t rqhdr0:1;
+		uint64_t sot:1;
+	} cn52xxp1;
+	struct cvmx_pescx_bist_status_s cn56xx;
+	struct cvmx_pescx_bist_status_cn52xxp1 cn56xxp1;
+};
+
+union cvmx_pescx_bist_status2 {
+	uint64_t u64;
+	struct cvmx_pescx_bist_status2_s {
+		uint64_t reserved_14_63:50;
+		uint64_t cto_p2e:1;
+		uint64_t e2p_cpl:1;
+		uint64_t e2p_n:1;
+		uint64_t e2p_p:1;
+		uint64_t e2p_rsl:1;
+		uint64_t dbg_p2e:1;
+		uint64_t peai_p2e:1;
+		uint64_t rsl_p2e:1;
+		uint64_t pef_tpf1:1;
+		uint64_t pef_tpf0:1;
+		uint64_t pef_tnf:1;
+		uint64_t pef_tcf1:1;
+		uint64_t pef_tc0:1;
+		uint64_t ppf:1;
+	} s;
+	struct cvmx_pescx_bist_status2_s cn52xx;
+	struct cvmx_pescx_bist_status2_s cn52xxp1;
+	struct cvmx_pescx_bist_status2_s cn56xx;
+	struct cvmx_pescx_bist_status2_s cn56xxp1;
+};
+
+union cvmx_pescx_cfg_rd {
+	uint64_t u64;
+	struct cvmx_pescx_cfg_rd_s {
+		uint64_t data:32;
+		uint64_t addr:32;
+	} s;
+	struct cvmx_pescx_cfg_rd_s cn52xx;
+	struct cvmx_pescx_cfg_rd_s cn52xxp1;
+	struct cvmx_pescx_cfg_rd_s cn56xx;
+	struct cvmx_pescx_cfg_rd_s cn56xxp1;
+};
+
+union cvmx_pescx_cfg_wr {
+	uint64_t u64;
+	struct cvmx_pescx_cfg_wr_s {
+		uint64_t data:32;
+		uint64_t addr:32;
+	} s;
+	struct cvmx_pescx_cfg_wr_s cn52xx;
+	struct cvmx_pescx_cfg_wr_s cn52xxp1;
+	struct cvmx_pescx_cfg_wr_s cn56xx;
+	struct cvmx_pescx_cfg_wr_s cn56xxp1;
+};
+
+union cvmx_pescx_cpl_lut_valid {
+	uint64_t u64;
+	struct cvmx_pescx_cpl_lut_valid_s {
+		uint64_t reserved_32_63:32;
+		uint64_t tag:32;
+	} s;
+	struct cvmx_pescx_cpl_lut_valid_s cn52xx;
+	struct cvmx_pescx_cpl_lut_valid_s cn52xxp1;
+	struct cvmx_pescx_cpl_lut_valid_s cn56xx;
+	struct cvmx_pescx_cpl_lut_valid_s cn56xxp1;
+};
+
+union cvmx_pescx_ctl_status {
+	uint64_t u64;
+	struct cvmx_pescx_ctl_status_s {
+		uint64_t reserved_28_63:36;
+		uint64_t dnum:5;
+		uint64_t pbus:8;
+		uint64_t qlm_cfg:2;
+		uint64_t lane_swp:1;
+		uint64_t pm_xtoff:1;
+		uint64_t pm_xpme:1;
+		uint64_t ob_p_cmd:1;
+		uint64_t reserved_7_8:2;
+		uint64_t nf_ecrc:1;
+		uint64_t dly_one:1;
+		uint64_t lnk_enb:1;
+		uint64_t ro_ctlp:1;
+		uint64_t reserved_2_2:1;
+		uint64_t inv_ecrc:1;
+		uint64_t inv_lcrc:1;
+	} s;
+	struct cvmx_pescx_ctl_status_s cn52xx;
+	struct cvmx_pescx_ctl_status_s cn52xxp1;
+	struct cvmx_pescx_ctl_status_cn56xx {
+		uint64_t reserved_28_63:36;
+		uint64_t dnum:5;
+		uint64_t pbus:8;
+		uint64_t qlm_cfg:2;
+		uint64_t reserved_12_12:1;
+		uint64_t pm_xtoff:1;
+		uint64_t pm_xpme:1;
+		uint64_t ob_p_cmd:1;
+		uint64_t reserved_7_8:2;
+		uint64_t nf_ecrc:1;
+		uint64_t dly_one:1;
+		uint64_t lnk_enb:1;
+		uint64_t ro_ctlp:1;
+		uint64_t reserved_2_2:1;
+		uint64_t inv_ecrc:1;
+		uint64_t inv_lcrc:1;
+	} cn56xx;
+	struct cvmx_pescx_ctl_status_cn56xx cn56xxp1;
+};
+
+union cvmx_pescx_ctl_status2 {
+	uint64_t u64;
+	struct cvmx_pescx_ctl_status2_s {
+		uint64_t reserved_2_63:62;
+		uint64_t pclk_run:1;
+		uint64_t pcierst:1;
+	} s;
+	struct cvmx_pescx_ctl_status2_s cn52xx;
+	struct cvmx_pescx_ctl_status2_cn52xxp1 {
+		uint64_t reserved_1_63:63;
+		uint64_t pcierst:1;
+	} cn52xxp1;
+	struct cvmx_pescx_ctl_status2_s cn56xx;
+	struct cvmx_pescx_ctl_status2_cn52xxp1 cn56xxp1;
+};
+
+union cvmx_pescx_dbg_info {
+	uint64_t u64;
+	struct cvmx_pescx_dbg_info_s {
+		uint64_t reserved_31_63:33;
+		uint64_t ecrc_e:1;
+		uint64_t rawwpp:1;
+		uint64_t racpp:1;
+		uint64_t ramtlp:1;
+		uint64_t rarwdns:1;
+		uint64_t caar:1;
+		uint64_t racca:1;
+		uint64_t racur:1;
+		uint64_t rauc:1;
+		uint64_t rqo:1;
+		uint64_t fcuv:1;
+		uint64_t rpe:1;
+		uint64_t fcpvwt:1;
+		uint64_t dpeoosd:1;
+		uint64_t rtwdle:1;
+		uint64_t rdwdle:1;
+		uint64_t mre:1;
+		uint64_t rte:1;
+		uint64_t acto:1;
+		uint64_t rvdm:1;
+		uint64_t rumep:1;
+		uint64_t rptamrc:1;
+		uint64_t rpmerc:1;
+		uint64_t rfemrc:1;
+		uint64_t rnfemrc:1;
+		uint64_t rcemrc:1;
+		uint64_t rpoison:1;
+		uint64_t recrce:1;
+		uint64_t rtlplle:1;
+		uint64_t rtlpmal:1;
+		uint64_t spoison:1;
+	} s;
+	struct cvmx_pescx_dbg_info_s cn52xx;
+	struct cvmx_pescx_dbg_info_s cn52xxp1;
+	struct cvmx_pescx_dbg_info_s cn56xx;
+	struct cvmx_pescx_dbg_info_s cn56xxp1;
+};
+
+union cvmx_pescx_dbg_info_en {
+	uint64_t u64;
+	struct cvmx_pescx_dbg_info_en_s {
+		uint64_t reserved_31_63:33;
+		uint64_t ecrc_e:1;
+		uint64_t rawwpp:1;
+		uint64_t racpp:1;
+		uint64_t ramtlp:1;
+		uint64_t rarwdns:1;
+		uint64_t caar:1;
+		uint64_t racca:1;
+		uint64_t racur:1;
+		uint64_t rauc:1;
+		uint64_t rqo:1;
+		uint64_t fcuv:1;
+		uint64_t rpe:1;
+		uint64_t fcpvwt:1;
+		uint64_t dpeoosd:1;
+		uint64_t rtwdle:1;
+		uint64_t rdwdle:1;
+		uint64_t mre:1;
+		uint64_t rte:1;
+		uint64_t acto:1;
+		uint64_t rvdm:1;
+		uint64_t rumep:1;
+		uint64_t rptamrc:1;
+		uint64_t rpmerc:1;
+		uint64_t rfemrc:1;
+		uint64_t rnfemrc:1;
+		uint64_t rcemrc:1;
+		uint64_t rpoison:1;
+		uint64_t recrce:1;
+		uint64_t rtlplle:1;
+		uint64_t rtlpmal:1;
+		uint64_t spoison:1;
+	} s;
+	struct cvmx_pescx_dbg_info_en_s cn52xx;
+	struct cvmx_pescx_dbg_info_en_s cn52xxp1;
+	struct cvmx_pescx_dbg_info_en_s cn56xx;
+	struct cvmx_pescx_dbg_info_en_s cn56xxp1;
+};
+
+union cvmx_pescx_diag_status {
+	uint64_t u64;
+	struct cvmx_pescx_diag_status_s {
+		uint64_t reserved_4_63:60;
+		uint64_t pm_dst:1;
+		uint64_t pm_stat:1;
+		uint64_t pm_en:1;
+		uint64_t aux_en:1;
+	} s;
+	struct cvmx_pescx_diag_status_s cn52xx;
+	struct cvmx_pescx_diag_status_s cn52xxp1;
+	struct cvmx_pescx_diag_status_s cn56xx;
+	struct cvmx_pescx_diag_status_s cn56xxp1;
+};
+
+union cvmx_pescx_p2n_bar0_start {
+	uint64_t u64;
+	struct cvmx_pescx_p2n_bar0_start_s {
+		uint64_t addr:50;
+		uint64_t reserved_0_13:14;
+	} s;
+	struct cvmx_pescx_p2n_bar0_start_s cn52xx;
+	struct cvmx_pescx_p2n_bar0_start_s cn52xxp1;
+	struct cvmx_pescx_p2n_bar0_start_s cn56xx;
+	struct cvmx_pescx_p2n_bar0_start_s cn56xxp1;
+};
+
+union cvmx_pescx_p2n_bar1_start {
+	uint64_t u64;
+	struct cvmx_pescx_p2n_bar1_start_s {
+		uint64_t addr:38;
+		uint64_t reserved_0_25:26;
+	} s;
+	struct cvmx_pescx_p2n_bar1_start_s cn52xx;
+	struct cvmx_pescx_p2n_bar1_start_s cn52xxp1;
+	struct cvmx_pescx_p2n_bar1_start_s cn56xx;
+	struct cvmx_pescx_p2n_bar1_start_s cn56xxp1;
+};
+
+union cvmx_pescx_p2n_bar2_start {
+	uint64_t u64;
+	struct cvmx_pescx_p2n_bar2_start_s {
+		uint64_t addr:25;
+		uint64_t reserved_0_38:39;
+	} s;
+	struct cvmx_pescx_p2n_bar2_start_s cn52xx;
+	struct cvmx_pescx_p2n_bar2_start_s cn52xxp1;
+	struct cvmx_pescx_p2n_bar2_start_s cn56xx;
+	struct cvmx_pescx_p2n_bar2_start_s cn56xxp1;
+};
+
+union cvmx_pescx_p2p_barx_end {
+	uint64_t u64;
+	struct cvmx_pescx_p2p_barx_end_s {
+		uint64_t addr:52;
+		uint64_t reserved_0_11:12;
+	} s;
+	struct cvmx_pescx_p2p_barx_end_s cn52xx;
+	struct cvmx_pescx_p2p_barx_end_s cn52xxp1;
+	struct cvmx_pescx_p2p_barx_end_s cn56xx;
+	struct cvmx_pescx_p2p_barx_end_s cn56xxp1;
+};
+
+union cvmx_pescx_p2p_barx_start {
+	uint64_t u64;
+	struct cvmx_pescx_p2p_barx_start_s {
+		uint64_t addr:52;
+		uint64_t reserved_0_11:12;
+	} s;
+	struct cvmx_pescx_p2p_barx_start_s cn52xx;
+	struct cvmx_pescx_p2p_barx_start_s cn52xxp1;
+	struct cvmx_pescx_p2p_barx_start_s cn56xx;
+	struct cvmx_pescx_p2p_barx_start_s cn56xxp1;
+};
+
+union cvmx_pescx_tlp_credits {
+	uint64_t u64;
+	struct cvmx_pescx_tlp_credits_s {
+		uint64_t reserved_0_63:64;
+	} s;
+	struct cvmx_pescx_tlp_credits_cn52xx {
+		uint64_t reserved_56_63:8;
+		uint64_t peai_ppf:8;
+		uint64_t pesc_cpl:8;
+		uint64_t pesc_np:8;
+		uint64_t pesc_p:8;
+		uint64_t npei_cpl:8;
+		uint64_t npei_np:8;
+		uint64_t npei_p:8;
+	} cn52xx;
+	struct cvmx_pescx_tlp_credits_cn52xxp1 {
+		uint64_t reserved_38_63:26;
+		uint64_t peai_ppf:8;
+		uint64_t pesc_cpl:5;
+		uint64_t pesc_np:5;
+		uint64_t pesc_p:5;
+		uint64_t npei_cpl:5;
+		uint64_t npei_np:5;
+		uint64_t npei_p:5;
+	} cn52xxp1;
+	struct cvmx_pescx_tlp_credits_cn52xx cn56xx;
+	struct cvmx_pescx_tlp_credits_cn52xxp1 cn56xxp1;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pexp-defs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pexp-defs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/cvmx-pexp-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/cvmx-pexp-defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,229 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * cvmx-pexp-defs.h
+ *
+ * Configuration and status register (CSR) definitions for
+ * OCTEON PEXP.
+ *
+ */
+#ifndef __CVMX_PEXP_DEFS_H__
+#define __CVMX_PEXP_DEFS_H__
+
+#define CVMX_PEXP_NPEI_BAR1_INDEXX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000008000ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_BIST_STATUS \
+	 CVMX_ADD_IO_SEG(0x00011F0000008580ull)
+#define CVMX_PEXP_NPEI_BIST_STATUS2 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008680ull)
+#define CVMX_PEXP_NPEI_CTL_PORT0 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008250ull)
+#define CVMX_PEXP_NPEI_CTL_PORT1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008260ull)
+#define CVMX_PEXP_NPEI_CTL_STATUS \
+	 CVMX_ADD_IO_SEG(0x00011F0000008570ull)
+#define CVMX_PEXP_NPEI_CTL_STATUS2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC00ull)
+#define CVMX_PEXP_NPEI_DATA_OUT_CNT \
+	 CVMX_ADD_IO_SEG(0x00011F00000085F0ull)
+#define CVMX_PEXP_NPEI_DBG_DATA \
+	 CVMX_ADD_IO_SEG(0x00011F0000008510ull)
+#define CVMX_PEXP_NPEI_DBG_SELECT \
+	 CVMX_ADD_IO_SEG(0x00011F0000008500ull)
+#define CVMX_PEXP_NPEI_DMA0_INT_LEVEL \
+	 CVMX_ADD_IO_SEG(0x00011F00000085C0ull)
+#define CVMX_PEXP_NPEI_DMA1_INT_LEVEL \
+	 CVMX_ADD_IO_SEG(0x00011F00000085D0ull)
+#define CVMX_PEXP_NPEI_DMAX_COUNTS(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000008450ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMAX_DBELL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F00000083B0ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMAX_IBUFF_SADDR(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000008400ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMAX_NADDR(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F00000084A0ull + (((offset) & 7) * 16))
+#define CVMX_PEXP_NPEI_DMA_CNTS \
+	 CVMX_ADD_IO_SEG(0x00011F00000085E0ull)
+#define CVMX_PEXP_NPEI_DMA_CONTROL \
+	 CVMX_ADD_IO_SEG(0x00011F00000083A0ull)
+#define CVMX_PEXP_NPEI_INT_A_ENB \
+	 CVMX_ADD_IO_SEG(0x00011F0000008560ull)
+#define CVMX_PEXP_NPEI_INT_A_ENB2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BCE0ull)
+#define CVMX_PEXP_NPEI_INT_A_SUM \
+	 CVMX_ADD_IO_SEG(0x00011F0000008550ull)
+#define CVMX_PEXP_NPEI_INT_ENB \
+	 CVMX_ADD_IO_SEG(0x00011F0000008540ull)
+#define CVMX_PEXP_NPEI_INT_ENB2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BCD0ull)
+#define CVMX_PEXP_NPEI_INT_INFO \
+	 CVMX_ADD_IO_SEG(0x00011F0000008590ull)
+#define CVMX_PEXP_NPEI_INT_SUM \
+	 CVMX_ADD_IO_SEG(0x00011F0000008530ull)
+#define CVMX_PEXP_NPEI_INT_SUM2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BCC0ull)
+#define CVMX_PEXP_NPEI_LAST_WIN_RDATA0 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008600ull)
+#define CVMX_PEXP_NPEI_LAST_WIN_RDATA1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008610ull)
+#define CVMX_PEXP_NPEI_MEM_ACCESS_CTL \
+	 CVMX_ADD_IO_SEG(0x00011F00000084F0ull)
+#define CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000008280ull + (((offset) & 31) * 16) - 16 * 12)
+#define CVMX_PEXP_NPEI_MSI_ENB0 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC50ull)
+#define CVMX_PEXP_NPEI_MSI_ENB1 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC60ull)
+#define CVMX_PEXP_NPEI_MSI_ENB2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC70ull)
+#define CVMX_PEXP_NPEI_MSI_ENB3 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC80ull)
+#define CVMX_PEXP_NPEI_MSI_RCV0 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC10ull)
+#define CVMX_PEXP_NPEI_MSI_RCV1 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC20ull)
+#define CVMX_PEXP_NPEI_MSI_RCV2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC30ull)
+#define CVMX_PEXP_NPEI_MSI_RCV3 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC40ull)
+#define CVMX_PEXP_NPEI_MSI_RD_MAP \
+	 CVMX_ADD_IO_SEG(0x00011F000000BCA0ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB0 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BCF0ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB1 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD00ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD10ull)
+#define CVMX_PEXP_NPEI_MSI_W1C_ENB3 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD20ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB0 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD30ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB1 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD40ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB2 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD50ull)
+#define CVMX_PEXP_NPEI_MSI_W1S_ENB3 \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD60ull)
+#define CVMX_PEXP_NPEI_MSI_WR_MAP \
+	 CVMX_ADD_IO_SEG(0x00011F000000BC90ull)
+#define CVMX_PEXP_NPEI_PCIE_CREDIT_CNT \
+	 CVMX_ADD_IO_SEG(0x00011F000000BD70ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV \
+	 CVMX_ADD_IO_SEG(0x00011F000000BCB0ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008650ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B2 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008660ull)
+#define CVMX_PEXP_NPEI_PCIE_MSI_RCV_B3 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008670ull)
+#define CVMX_PEXP_NPEI_PKTX_CNTS(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F000000A400ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_BADDR(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F000000A800ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_BAOFF_DBELL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F000000AC00ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_FIFO_RSIZE(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F000000B000ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_INSTR_HEADER(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F000000B400ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_IN_BP(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F000000B800ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_SLIST_BADDR(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000009400ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_SLIST_BAOFF_DBELL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000009800ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKTX_SLIST_FIFO_RSIZE(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F0000009C00ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKT_CNT_INT \
+	 CVMX_ADD_IO_SEG(0x00011F0000009110ull)
+#define CVMX_PEXP_NPEI_PKT_CNT_INT_ENB \
+	 CVMX_ADD_IO_SEG(0x00011F0000009130ull)
+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ES \
+	 CVMX_ADD_IO_SEG(0x00011F00000090B0ull)
+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_NS \
+	 CVMX_ADD_IO_SEG(0x00011F00000090A0ull)
+#define CVMX_PEXP_NPEI_PKT_DATA_OUT_ROR \
+	 CVMX_ADD_IO_SEG(0x00011F0000009090ull)
+#define CVMX_PEXP_NPEI_PKT_DPADDR \
+	 CVMX_ADD_IO_SEG(0x00011F0000009080ull)
+#define CVMX_PEXP_NPEI_PKT_INPUT_CONTROL \
+	 CVMX_ADD_IO_SEG(0x00011F0000009150ull)
+#define CVMX_PEXP_NPEI_PKT_INSTR_ENB \
+	 CVMX_ADD_IO_SEG(0x00011F0000009000ull)
+#define CVMX_PEXP_NPEI_PKT_INSTR_RD_SIZE \
+	 CVMX_ADD_IO_SEG(0x00011F0000009190ull)
+#define CVMX_PEXP_NPEI_PKT_INSTR_SIZE \
+	 CVMX_ADD_IO_SEG(0x00011F0000009020ull)
+#define CVMX_PEXP_NPEI_PKT_INT_LEVELS \
+	 CVMX_ADD_IO_SEG(0x00011F0000009100ull)
+#define CVMX_PEXP_NPEI_PKT_IN_BP \
+	 CVMX_ADD_IO_SEG(0x00011F00000086B0ull)
+#define CVMX_PEXP_NPEI_PKT_IN_DONEX_CNTS(offset) \
+	 CVMX_ADD_IO_SEG(0x00011F000000A000ull + (((offset) & 31) * 16))
+#define CVMX_PEXP_NPEI_PKT_IN_INSTR_COUNTS \
+	 CVMX_ADD_IO_SEG(0x00011F00000086A0ull)
+#define CVMX_PEXP_NPEI_PKT_IN_PCIE_PORT \
+	 CVMX_ADD_IO_SEG(0x00011F00000091A0ull)
+#define CVMX_PEXP_NPEI_PKT_IPTR \
+	 CVMX_ADD_IO_SEG(0x00011F0000009070ull)
+#define CVMX_PEXP_NPEI_PKT_OUTPUT_WMARK \
+	 CVMX_ADD_IO_SEG(0x00011F0000009160ull)
+#define CVMX_PEXP_NPEI_PKT_OUT_BMODE \
+	 CVMX_ADD_IO_SEG(0x00011F00000090D0ull)
+#define CVMX_PEXP_NPEI_PKT_OUT_ENB \
+	 CVMX_ADD_IO_SEG(0x00011F0000009010ull)
+#define CVMX_PEXP_NPEI_PKT_PCIE_PORT \
+	 CVMX_ADD_IO_SEG(0x00011F00000090E0ull)
+#define CVMX_PEXP_NPEI_PKT_PORT_IN_RST \
+	 CVMX_ADD_IO_SEG(0x00011F0000008690ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_ES \
+	 CVMX_ADD_IO_SEG(0x00011F0000009050ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_ID_SIZE \
+	 CVMX_ADD_IO_SEG(0x00011F0000009180ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_NS \
+	 CVMX_ADD_IO_SEG(0x00011F0000009040ull)
+#define CVMX_PEXP_NPEI_PKT_SLIST_ROR \
+	 CVMX_ADD_IO_SEG(0x00011F0000009030ull)
+#define CVMX_PEXP_NPEI_PKT_TIME_INT \
+	 CVMX_ADD_IO_SEG(0x00011F0000009120ull)
+#define CVMX_PEXP_NPEI_PKT_TIME_INT_ENB \
+	 CVMX_ADD_IO_SEG(0x00011F0000009140ull)
+#define CVMX_PEXP_NPEI_RSL_INT_BLOCKS \
+	 CVMX_ADD_IO_SEG(0x00011F0000008520ull)
+#define CVMX_PEXP_NPEI_SCRATCH_1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008270ull)
+#define CVMX_PEXP_NPEI_STATE1 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008620ull)
+#define CVMX_PEXP_NPEI_STATE2 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008630ull)
+#define CVMX_PEXP_NPEI_STATE3 \
+	 CVMX_ADD_IO_SEG(0x00011F0000008640ull)
+#define CVMX_PEXP_NPEI_WINDOW_CTL \
+	 CVMX_ADD_IO_SEG(0x00011F0000008380ull)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/octeon-feature.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/octeon-feature.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/octeon-feature.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/octeon-feature.h	2009-09-09 18:13:59.000000000 -0400
@@ -57,6 +57,13 @@
 	OCTEON_FEATURE_RAID,
 	/* Octeon has a builtin USB */
 	OCTEON_FEATURE_USB,
+	/* Octeon IPD can run without using work queue entries */
+	OCTEON_FEATURE_NO_WPTR,
+	/* Octeon has DFA state machines */
+	OCTEON_FEATURE_DFA,
+	/* Octeon MDIO block supports clause 45 transactions for 10
+	 * Gig support */
+	OCTEON_FEATURE_MDIO_CLAUSE_45,
 };
 
 static inline int cvmx_fuse_read(int fuse);
@@ -112,6 +119,26 @@
 	case OCTEON_FEATURE_USB:
 		return !(OCTEON_IS_MODEL(OCTEON_CN38XX)
 			 || OCTEON_IS_MODEL(OCTEON_CN58XX));
+	case OCTEON_FEATURE_NO_WPTR:
+		return (OCTEON_IS_MODEL(OCTEON_CN56XX)
+			 || OCTEON_IS_MODEL(OCTEON_CN52XX))
+			&& !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
+			&& !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X);
+	case OCTEON_FEATURE_DFA:
+		if (!OCTEON_IS_MODEL(OCTEON_CN38XX)
+		    && !OCTEON_IS_MODEL(OCTEON_CN31XX)
+		    && !OCTEON_IS_MODEL(OCTEON_CN58XX))
+			return 0;
+		else if (OCTEON_IS_MODEL(OCTEON_CN3020))
+			return 0;
+		else if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1))
+			return 1;
+		else
+			return !cvmx_fuse_read(120);
+	case OCTEON_FEATURE_MDIO_CLAUSE_45:
+		return !(OCTEON_IS_MODEL(OCTEON_CN3XXX)
+			 || OCTEON_IS_MODEL(OCTEON_CN58XX)
+			 || OCTEON_IS_MODEL(OCTEON_CN50XX));
 	}
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/octeon.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/octeon.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/octeon.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/octeon.h	2009-09-09 18:13:59.000000000 -0400
@@ -245,4 +245,6 @@
 	return cvmx_read64_uint32(address ^ 4);
 }
 
+extern struct cvmx_bootinfo *octeon_bootinfo;
+
 #endif /* __ASM_OCTEON_OCTEON_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/pci-octeon.h linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/pci-octeon.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/octeon/pci-octeon.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/octeon/pci-octeon.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * 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) 2005-2009 Cavium Networks
+ */
+
+#ifndef __PCI_OCTEON_H__
+#define __PCI_OCTEON_H__
+
+#include <linux/pci.h>
+
+/* Some PCI cards require delays when accessing config space. */
+#define PCI_CONFIG_SPACE_DELAY 10000
+
+/*
+ * pcibios_map_irq() is defined inside pci-octeon.c. All it does is
+ * call the Octeon specific version pointed to by this variable. This
+ * function needs to change for PCI or PCIe based hosts.
+ */
+extern int (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+				     u8 slot, u8 pin);
+
+/*
+ * The following defines are used when octeon_dma_bar_type =
+ * OCTEON_DMA_BAR_TYPE_BIG
+ */
+#define OCTEON_PCI_BAR1_HOLE_BITS 5
+#define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3))
+
+enum octeon_dma_bar_type {
+	OCTEON_DMA_BAR_TYPE_INVALID,
+	OCTEON_DMA_BAR_TYPE_SMALL,
+	OCTEON_DMA_BAR_TYPE_BIG,
+	OCTEON_DMA_BAR_TYPE_PCIE
+};
+
+/*
+ * This tells the DMA mapping system in dma-octeon.c how to map PCI
+ * DMA addresses.
+ */
+extern enum octeon_dma_bar_type octeon_dma_bar_type;
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/page.h linux-libre-2.6.31-gnu/arch/mips/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,13 @@
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
 #define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
 
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT	(PAGE_SHIFT + PAGE_SHIFT - 3)
+#define HPAGE_SIZE	((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK	(~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#endif /* CONFIG_HUGETLB_PAGE */
+
 #ifndef __ASSEMBLY__
 
 #include <linux/pfn.h>
@@ -160,7 +167,14 @@
 
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
+#define pfn_valid(pfn)							\
+({									\
+	unsigned long __pfn = (pfn);					\
+	/* avoid <linux/bootmem.h> include hell */			\
+	extern unsigned long min_low_pfn;				\
+									\
+	__pfn >= min_low_pfn && __pfn < max_mapnr;			\
+})
 
 #elif defined(CONFIG_SPARSEMEM)
 
@@ -189,6 +203,6 @@
 #define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _ASM_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/pci.h linux-libre-2.6.31-gnu/arch/mips/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -142,19 +142,6 @@
 extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 				    struct pci_bus_region *region);
 
-static inline struct resource *
-pcibios_select_root(struct pci_dev *pdev, struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
 static inline int pci_proc_domain(struct pci_bus *bus)
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/mips/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -98,23 +98,12 @@
 	__free_pages(pte, PTE_ORDER);
 }
 
-#define __pte_free_tlb(tlb,pte)				\
+#define __pte_free_tlb(tlb,pte,address)			\
 do {							\
 	pgtable_page_dtor(pte);				\
 	tlb_remove_page((tlb), pte);			\
 } while (0)
 
-#ifdef CONFIG_32BIT
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free(mm, x)			do { } while (0)
-#define __pmd_free_tlb(tlb, x)		do { } while (0)
-
-#endif
-
 #ifdef CONFIG_64BIT
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -132,7 +121,7 @@
 	free_pages((unsigned long)pmd, PMD_ORDER);
 }
 
-#define __pmd_free_tlb(tlb, x)	pmd_free((tlb)->mm, x)
+#define __pmd_free_tlb(tlb, x, addr)	pmd_free((tlb)->mm, x)
 
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/pgtable-bits.h linux-libre-2.6.31-gnu/arch/mips/include/asm/pgtable-bits.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/pgtable-bits.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/pgtable-bits.h	2009-09-09 18:13:59.000000000 -0400
@@ -72,6 +72,7 @@
 #else
 
 #define _PAGE_R4KBUG                (1<<5)  /* workaround for r4k bug  */
+#define _PAGE_HUGE                  (1<<5)  /* huge tlb page */
 #define _PAGE_GLOBAL                (1<<6)
 #define _PAGE_VALID                 (1<<7)
 #define _PAGE_SILENT_READ           (1<<7)  /* synonym                 */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/mips/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -292,6 +292,16 @@
 		pte_val(pte) |= _PAGE_SILENT_READ;
 	return pte;
 }
+
+#ifdef _PAGE_HUGE
+static inline int pte_huge(pte_t pte)	{ return pte_val(pte) & _PAGE_HUGE; }
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_HUGE;
+	return pte;
+}
+#endif /* _PAGE_HUGE */
 #endif
 static inline int pte_special(pte_t pte)	{ return 0; }
 static inline pte_t pte_mkspecial(pte_t pte)	{ return pte; }
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/war.h linux-libre-2.6.31-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/war.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/war.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/war.h	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,8 @@
 #if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
 	defined(CONFIG_PMC_MSP7120_FPGA)
 #define MIPS34K_MISSED_ITLB_WAR         1
+#else
+#define MIPS34K_MISSED_ITLB_WAR         0
 #endif
 
 #endif /* __ASM_MIPS_PMC_SIERRA_WAR_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/processor.h linux-libre-2.6.31-gnu/arch/mips/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -311,8 +311,9 @@
 
 unsigned long get_wchan(struct task_struct *p);
 
-#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + THREAD_SIZE - 32)
-#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk) - 1)
+#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \
+			 THREAD_SIZE - 32 - sizeof(struct pt_regs))
+#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk))
 #define KSTK_EIP(tsk) (task_pt_regs(tsk)->cp0_epc)
 #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29])
 #define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status)
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/r4kcache.h linux-libre-2.6.31-gnu/arch/mips/include/asm/r4kcache.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/r4kcache.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/r4kcache.h	2009-09-09 18:13:59.000000000 -0400
@@ -399,6 +399,7 @@
 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/reg.h linux-libre-2.6.31-gnu/arch/mips/include/asm/reg.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -69,7 +69,7 @@
 
 #endif
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
 
 #define EF_R0			 0
 #define EF_R1			 1
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/signal.h linux-libre-2.6.31-gnu/arch/mips/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -109,7 +109,7 @@
 #define SIG_UNBLOCK	2	/* for unblocking signals */
 #define SIG_SETMASK	3	/* for setting the signal mask */
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 struct sigaction {
 	unsigned int	sa_flags;
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/smp.h linux-libre-2.6.31-gnu/arch/mips/include/asm/smp.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/smp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/smp.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 
 #include <linux/bitops.h>
 #include <linux/linkage.h>
+#include <linux/smp.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 
@@ -40,6 +41,7 @@
 /* Octeon - Tell another core to flush its icache */
 #define SMP_ICACHE_FLUSH	0x4
 
+extern volatile cpumask_t cpu_callin_map;
 
 extern void asmlinkage smp_bootstrap(void);
 
@@ -55,6 +57,24 @@
 	mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static inline int __cpu_disable(void)
+{
+	extern struct plat_smp_ops *mp_ops;     /* private */
+
+	return mp_ops->cpu_disable();
+}
+
+static inline void __cpu_die(unsigned int cpu)
+{
+	extern struct plat_smp_ops *mp_ops;     /* private */
+
+	mp_ops->cpu_die(cpu);
+}
+
+extern void play_dead(void);
+#endif
+
 extern asmlinkage void smp_call_function_interrupt(void);
 
 extern void arch_send_call_function_single_ipi(int cpu);
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/smp-ops.h linux-libre-2.6.31-gnu/arch/mips/include/asm/smp-ops.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/smp-ops.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/smp-ops.h	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,10 @@
 	void (*boot_secondary)(int cpu, struct task_struct *idle);
 	void (*smp_setup)(void);
 	void (*prepare_cpus)(unsigned int max_cpus);
+#ifdef CONFIG_HOTPLUG_CPU
+	int (*cpu_disable)(void);
+	void (*cpu_die)(unsigned int cpu);
+#endif
 };
 
 extern void register_smp_ops(struct plat_smp_ops *ops);
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/sn/addrs.h linux-libre-2.6.31-gnu/arch/mips/include/asm/sn/addrs.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/sn/addrs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/sn/addrs.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 
 
 #ifndef __ASSEMBLY__
+#include <linux/smp.h>
 #include <linux/types.h>
 #endif /* !__ASSEMBLY__ */
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/suspend.h linux-libre-2.6.31-gnu/arch/mips/include/asm/suspend.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/suspend.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/suspend.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,9 @@
 #ifndef __ASM_SUSPEND_H
 #define __ASM_SUSPEND_H
 
-/* Somewhen...  Maybe :-)  */
+static inline int arch_prepare_suspend(void) { return 0; }
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
 
 #endif /* __ASM_SUSPEND_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/swab.h linux-libre-2.6.31-gnu/arch/mips/include/asm/swab.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/swab.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/swab.h	2009-09-09 18:13:59.000000000 -0400
@@ -38,7 +38,11 @@
 }
 #define __arch_swab32 __arch_swab32
 
-#ifdef CONFIG_CPU_MIPS64_R2
+/*
+ * Having already checked for CONFIG_CPU_MIPSR2, enable the
+ * optimized version for 64-bit kernel on r2 CPUs.
+ */
+#ifdef CONFIG_64BIT
 static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
 {
 	__asm__(
@@ -50,6 +54,6 @@
 	return x;
 }
 #define __arch_swab64 __arch_swab64
-#endif /* CONFIG_CPU_MIPS64_R2 */
+#endif /* CONFIG_64BIT */
 #endif /* CONFIG_CPU_MIPSR2 */
 #endif /* _ASM_SWAB_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/mips/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -39,8 +39,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
@@ -48,7 +46,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= _TIF_FIXADE,		\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/dmac.h linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/dmac.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/dmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/dmac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * TXx9 SoC DMA Controller
+ *
+ * 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.
+ */
+
+#ifndef __ASM_TXX9_DMAC_H
+#define __ASM_TXX9_DMAC_H
+
+#include <linux/dmaengine.h>
+
+#define TXX9_DMA_MAX_NR_CHANNELS	4
+
+/**
+ * struct txx9dmac_platform_data - Controller configuration parameters
+ * @memcpy_chan: Channel used for DMA_MEMCPY
+ * @have_64bit_regs: DMAC have 64 bit registers
+ */
+struct txx9dmac_platform_data {
+	int	memcpy_chan;
+	bool	have_64bit_regs;
+};
+
+/**
+ * struct txx9dmac_chan_platform_data - Channel configuration parameters
+ * @dmac_dev: A platform device for DMAC
+ */
+struct txx9dmac_chan_platform_data {
+	struct platform_device *dmac_dev;
+};
+
+/**
+ * struct txx9dmac_slave - Controller-specific information about a slave
+ * @tx_reg: physical address of data register used for
+ *	memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ *	peripheral-to-memory transfers
+ * @reg_width: peripheral register width
+ */
+struct txx9dmac_slave {
+	u64		tx_reg;
+	u64		rx_reg;
+	unsigned int	reg_width;
+};
+
+void txx9_dmac_init(int id, unsigned long baseaddr, int irq,
+		    const struct txx9dmac_platform_data *pdata);
+
+#endif /* __ASM_TXX9_DMAC_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/generic.h linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/generic.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/generic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/generic.h	2009-09-09 18:13:59.000000000 -0400
@@ -91,4 +91,10 @@
 		       void (*putc)(unsigned int pos, unsigned char val));
 int txx9_7segled_putc(unsigned int pos, char c);
 
+void __init txx9_aclc_init(unsigned long baseaddr, int irq,
+			   unsigned int dmac_id,
+			   unsigned int dma_chan_out,
+			   unsigned int dma_chan_in);
+void __init txx9_sramc_init(struct resource *r);
+
 #endif /* __ASM_TXX9_GENERIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/tx4927.h linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/tx4927.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/tx4927.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/tx4927.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,7 @@
 
 #define TX4927_SDRAMC_REG	(TX4927_REG_BASE + 0x8000)
 #define TX4927_EBUSC_REG	(TX4927_REG_BASE + 0x9000)
+#define TX4927_DMA_REG		(TX4927_REG_BASE + 0xb000)
 #define TX4927_PCIC_REG		(TX4927_REG_BASE + 0xd000)
 #define TX4927_CCFG_REG		(TX4927_REG_BASE + 0xe000)
 #define TX4927_IRC_REG		(TX4927_REG_BASE + 0xf600)
@@ -49,6 +50,7 @@
 #define TX4927_NR_SIO	2
 #define TX4927_SIO_REG(ch)	(TX4927_REG_BASE + 0xf300 + (ch) * 0x100)
 #define TX4927_PIO_REG		(TX4927_REG_BASE + 0xf500)
+#define TX4927_ACLC_REG		(TX4927_REG_BASE + 0xf700)
 
 #define TX4927_IR_ECCERR	0
 #define TX4927_IR_WTOERR	1
@@ -265,5 +267,7 @@
 void tx4927_setup_pcierr_irq(void);
 void tx4927_irq_init(void);
 void tx4927_mtd_init(int ch);
+void tx4927_dmac_init(int memcpy_chan);
+void tx4927_aclc_init(unsigned int dma_chan_out, unsigned int dma_chan_in);
 
 #endif /* __ASM_TXX9_TX4927_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/tx4938.h linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/tx4938.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/tx4938.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/tx4938.h	2009-09-09 18:13:59.000000000 -0400
@@ -305,5 +305,8 @@
 };
 
 void tx4938_ata_init(unsigned int irq, unsigned int shift, int tune);
+void tx4938_dmac_init(int memcpy_chan0, int memcpy_chan1);
+void tx4938_aclc_init(void);
+void tx4938_sramc_init(void);
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/tx4939.h linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/tx4939.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/txx9/tx4939.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/txx9/tx4939.h	2009-09-09 18:13:59.000000000 -0400
@@ -45,6 +45,8 @@
 #define TX4939_RTC_REG		(TX4939_REG_BASE + 0xfb00)
 #define TX4939_CIR_REG		(TX4939_REG_BASE + 0xfc00)
 
+#define TX4939_RNG_REG		(TX4939_CRYPTO_REG + 0xb0)
+
 struct tx4939_le_reg {
 	__u32 r;
 	__u32 unused;
@@ -544,5 +546,9 @@
 void tx4939_rtc_init(void);
 void tx4939_ndfmc_init(unsigned int hold, unsigned int spw,
 		       unsigned char ch_mask, unsigned char wide_mask);
+void tx4939_dmac_init(int memcpy_chan0, int memcpy_chan1);
+void tx4939_aclc_init(void);
+void tx4939_sramc_init(void);
+void tx4939_rng_init(void);
 
 #endif /* __ASM_TXX9_TX4939_H */
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/types.h linux-libre-2.6.31-gnu/arch/mips/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -31,9 +31,6 @@
  * These aren't exported outside the kernel to avoid name space clashes
  */
 #ifdef __KERNEL__
-
-#define BITS_PER_LONG _MIPS_SZLONG
-
 #ifndef __ASSEMBLY__
 
 #if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/mips/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -352,16 +352,19 @@
 #define __NR_inotify_init1		(__NR_Linux + 329)
 #define __NR_preadv			(__NR_Linux + 330)
 #define __NR_pwritev			(__NR_Linux + 331)
+#define __NR_rt_tgsigqueueinfo		(__NR_Linux + 332)
+#define __NR_perf_counter_open		(__NR_Linux + 333)
+#define __NR_accept4			(__NR_Linux + 334)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		331
+#define __NR_Linux_syscalls		334
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		331
+#define __NR_O32_Linux_syscalls		334
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -660,16 +663,19 @@
 #define __NR_inotify_init1		(__NR_Linux + 288)
 #define __NR_preadv			(__NR_Linux + 289)
 #define __NR_pwritev			(__NR_Linux + 290)
+#define __NR_rt_tgsigqueueinfo		(__NR_Linux + 291)
+#define __NR_perf_counter_open		(__NR_Linux + 292)
+#define __NR_accept4			(__NR_Linux + 293)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		290
+#define __NR_Linux_syscalls		293
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		290
+#define __NR_64_Linux_syscalls		293
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -972,16 +978,19 @@
 #define __NR_inotify_init1		(__NR_Linux + 292)
 #define __NR_preadv			(__NR_Linux + 293)
 #define __NR_pwritev			(__NR_Linux + 294)
+#define __NR_rt_tgsigqueueinfo		(__NR_Linux + 295)
+#define __NR_perf_counter_open		(__NR_Linux + 296)
+#define __NR_accept4			(__NR_Linux + 297)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		294
+#define __NR_Linux_syscalls		297
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		294
+#define __NR_N32_Linux_syscalls		297
 
 #ifdef __KERNEL__
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/capcella.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/capcella.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/capcella.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/capcella.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  capcella.h, Include file for ZAO Networks Capcella.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/giu.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/giu.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/giu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/giu.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series General-purpose I/O Unit.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2009  Yoichi Yuasa <yuasa@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
@@ -41,7 +41,8 @@
 	IRQ_SIGNAL_HOLD,
 } irq_signal_t;
 
-extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal);
+extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+				   irq_signal_t signal);
 
 typedef enum {
 	IRQ_LEVEL_LOW,
@@ -51,23 +52,6 @@
 extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level);
 
 typedef enum {
-	GPIO_DATA_LOW,
-	GPIO_DATA_HIGH,
-	GPIO_DATA_INVAL,
-} gpio_data_t;
-
-extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin);
-extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data);
-
-typedef enum {
-	GPIO_INPUT,
-	GPIO_OUTPUT,
-	GPIO_OUTPUT_DISABLE,
-} gpio_direction_t;
-
-extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir);
-
-typedef enum {
 	GPIO_PULL_DOWN,
 	GPIO_PULL_UP,
 	GPIO_PULL_DISABLE,
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/irq.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/irq.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
  * Copyright (C) 2001, 2002 Paul Mundt
  * Copyright (C) 2002 MontaVista Software, Inc.
  * Copyright (C) 2002 TimeSys Corp.
- * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/mpc30x.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/mpc30x.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/mpc30x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/mpc30x.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  mpc30x.h, Include file for Victor MP-C303/304.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/pci.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/pci.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series PCI Control Unit.
  *
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/siu.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/siu.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/siu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/siu.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series Serial Interface Unit.
  *
- *  Copyright (C) 2005-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2008  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/tb0219.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/tb0219.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/tb0219.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/tb0219.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  tb0219.h, Include file for TANBAC TB0219.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  Modified for TANBAC TB0219:
  *  Copyright (C) 2003 Megasolution Inc.  <matsu@megasolution.jp>
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/tb0226.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/tb0226.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/tb0226.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/tb0226.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  tb0226.h, Include file for TANBAC TB0226.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/vr41xx.h linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/vr41xx.h
--- linux-libre-2.6.30-gnu/arch/mips/include/asm/vr41xx/vr41xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/include/asm/vr41xx/vr41xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
  * Copyright (C) 2001, 2002 Paul Mundt
  * Copyright (C) 2002 MontaVista Software, Inc.
  * Copyright (C) 2002 TimeSys Corp.
- * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/jazz/irq.c linux-libre-2.6.31-gnu/arch/mips/jazz/irq.c
--- linux-libre-2.6.30-gnu/arch/mips/jazz/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/jazz/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <linux/spinlock.h>
 
 #include <asm/irq_cpu.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/jazz/jazzdma.c linux-libre-2.6.31-gnu/arch/mips/jazz/jazzdma.c
--- linux-libre-2.6.30-gnu/arch/mips/jazz/jazzdma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/jazz/jazzdma.c	2009-09-09 18:13:59.000000000 -0400
@@ -190,7 +190,7 @@
 		return -1;
 	}
 
-	while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES) {
+	while (i < VDMA_PGTBL_ENTRIES && pgtbl[i].owner == laddr) {
 		pgtbl[i].owner = VDMA_PAGE_EMPTY;
 		i++;
 	}
diff -druN linux-libre-2.6.30-gnu/arch/mips/Kconfig linux-libre-2.6.31-gnu/arch/mips/Kconfig
--- linux-libre-2.6.30-gnu/arch/mips/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,26 @@
 config MACH_ALCHEMY
 	bool "Alchemy processor based machines"
 
+config AR7
+	bool "Texas Instruments AR7"
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select CEVT_R4K
+	select CSRC_R4K
+	select IRQ_CPU
+	select NO_EXCEPT_FILL
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select GENERIC_GPIO
+	select GCD
+	select VLYNQ
+	help
+	  Support for the Texas Instruments AR7 System-on-a-Chip
+	  family: TNETD7100, 7200 and 7300.
+
 config BASLER_EXCITE
 	bool "Basler eXcite smart camera"
 	select CEVT_R4K
@@ -209,7 +229,7 @@
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select SYS_SUPPORTS_MIPS_CMP if BROKEN	# because SYNC_R4K is broken
+	select SYS_SUPPORTS_MIPS_CMP
 	select SYS_SUPPORTS_MULTITHREADING
 	select SYS_SUPPORTS_SMARTMIPS
 	help
@@ -247,6 +267,7 @@
 	select CEVT_R4K
 	select CSRC_R4K
 	select SYS_HAS_CPU_VR41XX
+	select ARCH_REQUIRE_GPIOLIB
 
 config NXP_STB220
 	bool "NXP STB220 board"
@@ -601,6 +622,7 @@
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_HOTPLUG_CPU
 	select SYS_HAS_CPU_CAVIUM_OCTEON
 	help
 	  The Octeon simulator is software performance model of the Cavium
@@ -615,9 +637,12 @@
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_HOTPLUG_CPU
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_HAS_CPU_CAVIUM_OCTEON
 	select SWAP_IO_SPACE
+	select HW_HAS_PCI
+	select ARCH_SUPPORTS_MSI
 	help
 	  This option supports all of the Octeon reference boards from Cavium
 	  Networks. It builds a kernel that dynamically determines the Octeon
@@ -782,8 +807,17 @@
 	bool
 
 config HOTPLUG_CPU
+	bool "Support for hot-pluggable CPUs"
+	depends on SMP && HOTPLUG && SYS_SUPPORTS_HOTPLUG_CPU
+	help
+	  Say Y here to allow turning CPUs off and on. CPUs can be
+	  controlled through /sys/devices/system/cpu.
+	  (Note: power management support will enable this option
+	    automatically on SMP systems. )
+	  Say N if you want to disable CPU hotplug.
+
+config SYS_SUPPORTS_HOTPLUG_CPU
 	bool
-	default n
 
 config I8259
 	bool
@@ -851,6 +885,11 @@
 config SYS_SUPPORTS_LITTLE_ENDIAN
 	bool
 
+config SYS_SUPPORTS_HUGETLBFS
+	bool
+	depends on CPU_SUPPORTS_HUGEPAGES && 64BIT
+	default y
+
 config IRQ_CPU
 	bool
 
@@ -1055,6 +1094,7 @@
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  Choose this option to build a kernel for release 1 or later of the
 	  MIPS64 architecture.  Many modern embedded systems with a 64-bit
@@ -1074,6 +1114,7 @@
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  Choose this option to build a kernel for release 2 or later of the
 	  MIPS64 architecture.  Many modern embedded systems with a 64-bit
@@ -1160,6 +1201,7 @@
 	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  NEC VR5500 and VR5500A series processors implement 64-bit MIPS IV
 	  instruction set.
@@ -1245,6 +1287,7 @@
 	select WEAK_ORDERING
 	select WEAK_REORDERING_BEYOND_LLSC
 	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
 	help
 	  The Cavium Octeon processor is a highly integrated chip containing
 	  many ethernet hardware widgets for networking tasks. The processor
@@ -1364,6 +1407,8 @@
 	bool
 config CPU_SUPPORTS_64BIT_KERNEL
 	bool
+config CPU_SUPPORTS_HUGEPAGES
+	bool
 
 #
 # Set to y for ptrace access to watch registers.
@@ -1611,7 +1656,7 @@
 config MIPS_CMP
 	bool "MIPS CMP framework support"
 	depends on SYS_SUPPORTS_MIPS_CMP
-	select SYNC_R4K if BROKEN
+	select SYNC_R4K
 	select SYS_SUPPORTS_SMP
 	select SYS_SUPPORTS_SCHED_SMT if SMP
 	select WEAK_ORDERING
@@ -2121,9 +2166,13 @@
 
 menu "Power management options"
 
+config ARCH_HIBERNATION_POSSIBLE
+	def_bool y
+	depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
+
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
-	depends on !SMP
+	depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
 
 source "kernel/power/Kconfig"
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/asm-offsets.c linux-libre-2.6.31-gnu/arch/mips/kernel/asm-offsets.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/asm-offsets.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/asm-offsets.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/kbuild.h>
+#include <linux/suspend.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 
@@ -326,3 +327,15 @@
 	BLANK();
 }
 #endif
+
+#ifdef CONFIG_HIBERNATION
+void output_pbe_defines(void)
+{
+	COMMENT(" Linux struct pbe offsets. ");
+	OFFSET(PBE_ADDRESS, pbe, address);
+	OFFSET(PBE_ORIG_ADDRESS, pbe, orig_address);
+	OFFSET(PBE_NEXT, pbe, next);
+	DEFINE(PBE_SIZE, sizeof(struct pbe));
+	BLANK();
+}
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/binfmt_elfo32.c linux-libre-2.6.31-gnu/arch/mips/kernel/binfmt_elfo32.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/binfmt_elfo32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/binfmt_elfo32.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,23 @@
 #define ELF_ET_DYN_BASE         (TASK32_SIZE / 3 * 2)
 
 #include <asm/processor.h>
+
+/*
+ * When this file is selected, we are definitely running a 64bit kernel.
+ * So using the right regs define in asm/reg.h
+ */
+#define WANT_COMPAT_REG_H
+
+/* These MUST be defined before elf.h gets included */
+extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
+#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
+#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest)				\
+({									\
+	int __res = 1;							\
+	elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk));		\
+	__res;								\
+})
+
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
@@ -110,9 +127,6 @@
 	value->tv_usec = rem / NSEC_PER_USEC;
 }
 
-#undef ELF_CORE_COPY_REGS
-#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
-
 void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
 {
 	int i;
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-bcm1480.c linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-bcm1480.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-bcm1480.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-bcm1480.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
+#include <linux/smp.h>
 
 #include <asm/addrspace.h>
 #include <asm/io.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-ds1287.c linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-ds1287.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-ds1287.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-ds1287.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  DS1287 clockevent driver
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-gt641xx.c linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-gt641xx.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-gt641xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-gt641xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  GT641xx clockevent routines.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-r4k.c linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-r4k.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-r4k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-r4k.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
+#include <linux/smp.h>
 
 #include <asm/smtc_ipi.h>
 #include <asm/time.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-sb1250.c linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-sb1250.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-sb1250.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-sb1250.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
+#include <linux/smp.h>
 
 #include <asm/addrspace.h>
 #include <asm/io.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-smtc.c linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-smtc.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-smtc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-smtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
+#include <linux/smp.h>
 
 #include <asm/smtc_ipi.h>
 #include <asm/time.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-txx9.c linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-txx9.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cevt-txx9.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cevt-txx9.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,22 +20,29 @@
 #define TIMER_CCD	0	/* 1/2 */
 #define TIMER_CLK(imclk)	((imclk) / (2 << TIMER_CCD))
 
-static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr;
+struct txx9_clocksource {
+	struct clocksource cs;
+	struct txx9_tmr_reg __iomem *tmrptr;
+};
 
 static cycle_t txx9_cs_read(struct clocksource *cs)
 {
-	return __raw_readl(&txx9_cs_tmrptr->trr);
+	struct txx9_clocksource *txx9_cs =
+		container_of(cs, struct txx9_clocksource, cs);
+	return __raw_readl(&txx9_cs->tmrptr->trr);
 }
 
 /* Use 1 bit smaller width to use full bits in that width */
 #define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1)
 
-static struct clocksource txx9_clocksource = {
-	.name		= "TXx9",
-	.rating		= 200,
-	.read		= txx9_cs_read,
-	.mask		= CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+static struct txx9_clocksource txx9_clocksource = {
+	.cs = {
+		.name		= "TXx9",
+		.rating		= 200,
+		.read		= txx9_cs_read,
+		.mask		= CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
+		.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	},
 };
 
 void __init txx9_clocksource_init(unsigned long baseaddr,
@@ -43,8 +50,8 @@
 {
 	struct txx9_tmr_reg __iomem *tmrptr;
 
-	clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk));
-	clocksource_register(&txx9_clocksource);
+	clocksource_set_clock(&txx9_clocksource.cs, TIMER_CLK(imbusclk));
+	clocksource_register(&txx9_clocksource.cs);
 
 	tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
 	__raw_writel(TCR_BASE, &tmrptr->tcr);
@@ -53,10 +60,13 @@
 	__raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr);
 	__raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra);
 	__raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
-	txx9_cs_tmrptr = tmrptr;
+	txx9_clocksource.tmrptr = tmrptr;
 }
 
-static struct txx9_tmr_reg __iomem *txx9_tmrptr;
+struct txx9_clock_event_device {
+	struct clock_event_device cd;
+	struct txx9_tmr_reg __iomem *tmrptr;
+};
 
 static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
 {
@@ -69,7 +79,9 @@
 static void txx9tmr_set_mode(enum clock_event_mode mode,
 			     struct clock_event_device *evt)
 {
-	struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+	struct txx9_clock_event_device *txx9_cd =
+		container_of(evt, struct txx9_clock_event_device, cd);
+	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 
 	txx9tmr_stop_and_clear(tmrptr);
 	switch (mode) {
@@ -99,7 +111,9 @@
 static int txx9tmr_set_next_event(unsigned long delta,
 				  struct clock_event_device *evt)
 {
-	struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+	struct txx9_clock_event_device *txx9_cd =
+		container_of(evt, struct txx9_clock_event_device, cd);
+	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 
 	txx9tmr_stop_and_clear(tmrptr);
 	/* start timer */
@@ -108,18 +122,22 @@
 	return 0;
 }
 
-static struct clock_event_device txx9tmr_clock_event_device = {
-	.name		= "TXx9",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_mode	= txx9tmr_set_mode,
-	.set_next_event	= txx9tmr_set_next_event,
+static struct txx9_clock_event_device txx9_clock_event_device = {
+	.cd = {
+		.name		= "TXx9",
+		.features	= CLOCK_EVT_FEAT_PERIODIC |
+				  CLOCK_EVT_FEAT_ONESHOT,
+		.rating		= 200,
+		.set_mode	= txx9tmr_set_mode,
+		.set_next_event	= txx9tmr_set_next_event,
+	},
 };
 
 static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *cd = &txx9tmr_clock_event_device;
-	struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
+	struct txx9_clock_event_device *txx9_cd = dev_id;
+	struct clock_event_device *cd = &txx9_cd->cd;
+	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
 
 	__raw_writel(0, &tmrptr->tisr);	/* ack interrupt */
 	cd->event_handler(cd);
@@ -130,19 +148,20 @@
 	.handler	= txx9tmr_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_PERCPU,
 	.name		= "txx9tmr",
+	.dev_id		= &txx9_clock_event_device,
 };
 
 void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
 				 unsigned int imbusclk)
 {
-	struct clock_event_device *cd = &txx9tmr_clock_event_device;
+	struct clock_event_device *cd = &txx9_clock_event_device.cd;
 	struct txx9_tmr_reg __iomem *tmrptr;
 
 	tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
 	txx9tmr_stop_and_clear(tmrptr);
 	__raw_writel(TIMER_CCD, &tmrptr->ccdr);
 	__raw_writel(0, &tmrptr->itmr);
-	txx9_tmrptr = tmrptr;
+	txx9_clock_event_device.tmrptr = tmrptr;
 
 	clockevent_set_clock(cd, TIMER_CLK(imbusclk));
 	cd->max_delta_ns =
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/cpu-probe.c linux-libre-2.6.31-gnu/arch/mips/kernel/cpu-probe.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/cpu-probe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/cpu-probe.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
+#include <linux/smp.h>
 #include <linux/stddef.h>
 
 #include <asm/bugs.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/csrc-ioasic.c linux-libre-2.6.31-gnu/arch/mips/kernel/csrc-ioasic.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/csrc-ioasic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/csrc-ioasic.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  DEC I/O ASIC's counter clocksource
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/head.S linux-libre-2.6.31-gnu/arch/mips/kernel/head.S
--- linux-libre-2.6.30-gnu/arch/mips/kernel/head.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/head.S	2009-09-09 18:13:59.000000000 -0400
@@ -188,7 +188,8 @@
 
 	MTC0		zero, CP0_CONTEXT	# clear context register
 	PTR_LA		$28, init_thread_union
-	PTR_LI		sp, _THREAD_SIZE - 32
+	/* Set the SP after an empty pt_regs.  */
+	PTR_LI		sp, _THREAD_SIZE - 32 - PT_SIZE
 	PTR_ADDU	sp, $28
 	set_saved_sp	sp, t0, t1
 	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/i8253.c linux-libre-2.6.31-gnu/arch/mips/kernel/i8253.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/i8253.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/i8253.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,6 +7,7 @@
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
+#include <linux/smp.h>
 #include <linux/spinlock.h>
 
 #include <asm/delay.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/init_task.c linux-libre-2.6.31-gnu/arch/mips/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,10 +11,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/irq-gic.c linux-libre-2.6.31-gnu/arch/mips/kernel/irq-gic.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/irq-gic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/irq-gic.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/init.h>
+#include <linux/smp.h>
 
 #include <asm/io.h>
 #include <asm/gic.h>
@@ -106,9 +107,7 @@
 {
 	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 	irq -= _irqbase;
-	/* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
-		 1 << (irq % 32));
+	GIC_SET_INTR_MASK(irq, 1);
 	return 0;
 }
 
@@ -119,8 +118,7 @@
 #endif
 	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 	irq -= _irqbase;
-	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
-		 1 << (irq % 32));
+	GIC_CLR_INTR_MASK(irq, 1);
 
 	if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
 		if (!gic_wedgeb2bok)
@@ -137,25 +135,21 @@
 {
 	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 	irq -= _irqbase;
-	/* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
-		 1 << (irq % 32));
+	GIC_CLR_INTR_MASK(irq, 1);
 }
 
 static void gic_unmask_irq(unsigned int irq)
 {
 	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 	irq -= _irqbase;
-	/* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
-		 1 << (irq % 32));
+	GIC_SET_INTR_MASK(irq, 1);
 }
 
 #ifdef CONFIG_SMP
 
 static DEFINE_SPINLOCK(gic_lock);
 
-static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 {
 	cpumask_t	tmp = CPU_MASK_NONE;
 	unsigned long	flags;
@@ -166,7 +160,7 @@
 
 	cpumask_and(&tmp, cpumask, cpu_online_mask);
 	if (cpus_empty(tmp))
-		return;
+		return -1;
 
 	/* Assumption : cpumask refers to a single CPU */
 	spin_lock_irqsave(&gic_lock, flags);
@@ -190,6 +184,7 @@
 	cpumask_copy(irq_desc[irq].affinity, cpumask);
 	spin_unlock_irqrestore(&gic_lock, flags);
 
+	return 0;
 }
 #endif
 
@@ -252,6 +247,10 @@
 		if (cpu == X)
 			continue;
 
+		if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 &&
+					_intrmap[i].ipiflag == 0)
+			continue;
+
 		setup_intr(_intrmap[i].intrnum,
 				_intrmap[i].cpunum,
 				_intrmap[i].pin,
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/irq-gt641xx.c linux-libre-2.6.31-gnu/arch/mips/kernel/irq-gt641xx.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/irq-gt641xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/irq-gt641xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  GT641xx IRQ routines.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/irq_txx9.c linux-libre-2.6.31-gnu/arch/mips/kernel/irq_txx9.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/irq_txx9.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/irq_txx9.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/kernel/irq_txx9.c
- *
  * Based on linux/arch/mips/jmr3927/rbhma3100/irq.c,
  *          linux/arch/mips/tx4927/common/tx4927_irq.c,
  *          linux/arch/mips/tx4938/common/irq.c
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/kgdb.c linux-libre-2.6.31-gnu/arch/mips/kernel/kgdb.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/kgdb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/kgdb.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <asm/inst.h>
 #include <asm/fpu.h>
 #include <asm/cacheflush.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/module.c linux-libre-2.6.31-gnu/arch/mips/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,8 +68,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
@@ -100,7 +98,8 @@
 static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
 {
 	if (v % 4) {
-		printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+		pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
+		       me->name);
 		return -ENOEXEC;
 	}
 
@@ -120,7 +119,8 @@
 static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
 {
 	if (v % 4) {
-		printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+		pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
+		       me->name);
 		return -ENOEXEC;
 	}
 
@@ -224,7 +224,7 @@
 	return 0;
 
 out_danger:
-	printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
+	pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name);
 
 	return -ENOEXEC;
 }
@@ -303,7 +303,7 @@
 		/* This is the symbol it is referring to */
 		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
 			+ ELF_MIPS_R_SYM(rel[i]);
-		if (!sym->st_value) {
+		if (IS_ERR_VALUE(sym->st_value)) {
 			/* Ignore unresolved weak symbol */
 			if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
 				continue;
@@ -343,7 +343,7 @@
 		/* This is the symbol it is referring to */
 		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
 			+ ELF_MIPS_R_SYM(rel[i]);
-		if (!sym->st_value) {
+		if (IS_ERR_VALUE(sym->st_value)) {
 			/* Ignore unresolved weak symbol */
 			if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
 				continue;
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/proc.c linux-libre-2.6.31-gnu/arch/mips/kernel/proc.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/proc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/proc.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/mips/kernel/proc.c
- *
  *  Copyright (C) 1995, 1996, 2001  Ralf Baechle
  *  Copyright (C) 2001, 2004  MIPS Technologies, Inc.
  *  Copyright (C) 2004  Maciej W. Rozycki
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/process.c linux-libre-2.6.31-gnu/arch/mips/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,10 +50,15 @@
  */
 void __noreturn cpu_idle(void)
 {
+	int cpu;
+
+	/* CPU is going idle. */
+	cpu = smp_processor_id();
+
 	/* endless idle loop with no priority at all */
 	while (1) {
 		tick_nohz_stop_sched_tick(1);
-		while (!need_resched()) {
+		while (!need_resched() && cpu_online(cpu)) {
 #ifdef CONFIG_MIPS_MT_SMTC
 			extern void smtc_idle_loop_hook(void);
 
@@ -62,6 +67,12 @@
 			if (cpu_wait)
 				(*cpu_wait)();
 		}
+#ifdef CONFIG_HOTPLUG_CPU
+		if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) &&
+		    (system_state == SYSTEM_RUNNING ||
+		     system_state == SYSTEM_BOOTING))
+			play_dead();
+#endif
 		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
 		schedule();
@@ -104,7 +115,7 @@
 {
 	struct thread_info *ti = task_thread_info(p);
 	struct pt_regs *childregs;
-	long childksp;
+	unsigned long childksp;
 	p->set_child_tid = p->clear_child_tid = NULL;
 
 	childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
@@ -121,6 +132,8 @@
 
 	/* set up new TSS. */
 	childregs = (struct pt_regs *) childksp - 1;
+	/*  Put the stack after the struct pt_regs.  */
+	childksp = (unsigned long) childregs;
 	*childregs = *regs;
 	childregs->regs[7] = 0;	/* Clear error flag */
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/ptrace32.c linux-libre-2.6.31-gnu/arch/mips/kernel/ptrace32.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/ptrace32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/ptrace32.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/scall32-o32.S linux-libre-2.6.31-gnu/arch/mips/kernel/scall32-o32.S
--- linux-libre-2.6.30-gnu/arch/mips/kernel/scall32-o32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/scall32-o32.S	2009-09-09 18:13:59.000000000 -0400
@@ -652,6 +652,9 @@
 	sys	sys_inotify_init1	1
 	sys	sys_preadv		6	/* 4330 */
 	sys	sys_pwritev		6
+	sys	sys_rt_tgsigqueueinfo	4
+	sys	sys_perf_counter_open	5
+	sys	sys_accept4		4
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/scall64-64.S linux-libre-2.6.31-gnu/arch/mips/kernel/scall64-64.S
--- linux-libre-2.6.30-gnu/arch/mips/kernel/scall64-64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/scall64-64.S	2009-09-09 18:13:59.000000000 -0400
@@ -489,4 +489,7 @@
 	PTR	sys_inotify_init1
 	PTR	sys_preadv
 	PTR	sys_pwritev			/* 5390 */
+	PTR	sys_rt_tgsigqueueinfo
+	PTR	sys_perf_counter_open
+	PTR	sys_accept4
 	.size	sys_call_table,.-sys_call_table
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/scall64-n32.S linux-libre-2.6.31-gnu/arch/mips/kernel/scall64-n32.S
--- linux-libre-2.6.30-gnu/arch/mips/kernel/scall64-n32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/scall64-n32.S	2009-09-09 18:13:59.000000000 -0400
@@ -415,4 +415,7 @@
 	PTR	sys_inotify_init1
 	PTR	sys_preadv
 	PTR	sys_pwritev
+	PTR	compat_sys_rt_tgsigqueueinfo	/* 5295 */
+	PTR	sys_perf_counter_open
+	PTR	sys_accept4
 	.size	sysn32_call_table,.-sysn32_call_table
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/scall64-o32.S linux-libre-2.6.31-gnu/arch/mips/kernel/scall64-o32.S
--- linux-libre-2.6.30-gnu/arch/mips/kernel/scall64-o32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/scall64-o32.S	2009-09-09 18:13:59.000000000 -0400
@@ -535,4 +535,7 @@
 	PTR	sys_inotify_init1
 	PTR	compat_sys_preadv		/* 4330 */
 	PTR	compat_sys_pwritev
+	PTR	compat_sys_rt_tgsigqueueinfo
+	PTR	sys_perf_counter_open
+	PTR	sys_accept4
 	.size	sys_call_table,.-sys_call_table
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/smp.c linux-libre-2.6.31-gnu/arch/mips/kernel/smp.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/smp.h>
 #include <linux/spinlock.h>
 #include <linux/threads.h>
 #include <linux/module.h>
@@ -44,7 +45,7 @@
 #include <asm/mipsmtregs.h>
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-static volatile cpumask_t cpu_callin_map;	/* Bitmask of started secondaries */
+volatile cpumask_t cpu_callin_map;	/* Bitmask of started secondaries */
 int __cpu_number_map[NR_CPUS];		/* Map physical to logical */
 int __cpu_logical_map[NR_CPUS];		/* Map logical to physical */
 
@@ -200,6 +201,8 @@
  * and keep control until "cpu_online(cpu)" is set.  Note: cpu is
  * physical, not logical.
  */
+static struct task_struct *cpu_idle_thread[NR_CPUS];
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	struct task_struct *idle;
@@ -209,9 +212,16 @@
 	 * The following code is purely to make sure
 	 * Linux can schedule processes on this slave.
 	 */
-	idle = fork_idle(cpu);
-	if (IS_ERR(idle))
-		panic(KERN_ERR "Fork failed for CPU %d", cpu);
+	if (!cpu_idle_thread[cpu]) {
+		idle = fork_idle(cpu);
+		cpu_idle_thread[cpu] = idle;
+
+		if (IS_ERR(idle))
+			panic(KERN_ERR "Fork failed for CPU %d", cpu);
+	} else {
+		idle = cpu_idle_thread[cpu];
+		init_idle(idle, cpu);
+	}
 
 	mp_ops->boot_secondary(cpu, idle);
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/smp-cmp.c linux-libre-2.6.31-gnu/arch/mips/kernel/smp-cmp.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/smp-cmp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/smp-cmp.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/interrupt.h>
 #include <linux/compiler.h>
@@ -36,80 +37,24 @@
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/mips_mt.h>
-
-/*
- * Crude manipulation of the CPU masks to control which
- * which CPU's are brought online during initialisation
- *
- * Beware... this needs to be called after CPU discovery
- * but before CPU bringup
- */
-static int __init allowcpus(char *str)
-{
-	cpumask_t cpu_allow_map;
-	char buf[256];
-	int len;
-
-	cpus_clear(cpu_allow_map);
-	if (cpulist_parse(str, &cpu_allow_map) == 0) {
-		cpu_set(0, cpu_allow_map);
-		cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map);
-		len = cpulist_scnprintf(buf, sizeof(buf)-1, &cpu_possible_map);
-		buf[len] = '\0';
-		pr_debug("Allowable CPUs: %s\n", buf);
-		return 1;
-	} else
-		return 0;
-}
-__setup("allowcpus=", allowcpus);
+#include <asm/amon.h>
+#include <asm/gic.h>
 
 static void ipi_call_function(unsigned int cpu)
 {
-	unsigned int action = 0;
-
 	pr_debug("CPU%d: %s cpu %d status %08x\n",
 		 smp_processor_id(), __func__, cpu, read_c0_status());
 
-	switch (cpu) {
-	case 0:
-		action = GIC_IPI_EXT_INTR_CALLFNC_VPE0;
-		break;
-	case 1:
-		action = GIC_IPI_EXT_INTR_CALLFNC_VPE1;
-		break;
-	case 2:
-		action = GIC_IPI_EXT_INTR_CALLFNC_VPE2;
-		break;
-	case 3:
-		action = GIC_IPI_EXT_INTR_CALLFNC_VPE3;
-		break;
-	}
-	gic_send_ipi(action);
+	gic_send_ipi(plat_ipi_call_int_xlate(cpu));
 }
 
 
 static void ipi_resched(unsigned int cpu)
 {
-	unsigned int action = 0;
-
 	pr_debug("CPU%d: %s cpu %d status %08x\n",
 		 smp_processor_id(), __func__, cpu, read_c0_status());
 
-	switch (cpu) {
-	case 0:
-		action = GIC_IPI_EXT_INTR_RESCHED_VPE0;
-		break;
-	case 1:
-		action = GIC_IPI_EXT_INTR_RESCHED_VPE1;
-		break;
-	case 2:
-		action = GIC_IPI_EXT_INTR_RESCHED_VPE2;
-		break;
-	case 3:
-		action = GIC_IPI_EXT_INTR_RESCHED_VPE3;
-		break;
-	}
-	gic_send_ipi(action);
+	gic_send_ipi(plat_ipi_resched_int_xlate(cpu));
 }
 
 /*
@@ -205,7 +150,7 @@
 			   (unsigned long)(gp + sizeof(struct thread_info)));
 #endif
 
-	amon_cpu_start(cpu, pc, sp, gp, a0);
+	amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0);
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/smp-up.c linux-libre-2.6.31-gnu/arch/mips/kernel/smp-up.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/smp-up.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/smp-up.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,6 +55,18 @@
 {
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int up_cpu_disable(void)
+{
+	return -ENOSYS;
+}
+
+static void up_cpu_die(unsigned int cpu)
+{
+	BUG();
+}
+#endif
+
 struct plat_smp_ops up_smp_ops = {
 	.send_ipi_single	= up_send_ipi_single,
 	.send_ipi_mask		= up_send_ipi_mask,
@@ -64,4 +76,8 @@
 	.boot_secondary		= up_boot_secondary,
 	.smp_setup		= up_smp_setup,
 	.prepare_cpus		= up_prepare_cpus,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable		= up_cpu_disable,
+	.cpu_die		= up_cpu_die,
+#endif
 };
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/smtc.c linux-libre-2.6.31-gnu/arch/mips/kernel/smtc.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/smtc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/smtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/clockchips.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
@@ -464,11 +465,8 @@
 	smtc_configure_tlb();
 
 	for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
-		/*
-		 * Set the MVP bits.
-		 */
-		settc(tc);
-		write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_MVP);
+		if (tcpervpe[vpe] == 0)
+			continue;
 		if (vpe != 0)
 			printk(", ");
 		printk("VPE %d: TC", vpe);
@@ -487,6 +485,12 @@
 		}
 		if (vpe != 0) {
 			/*
+			 * Allow this VPE to control others.
+			 */
+			write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() |
+					      VPECONF0_MVP);
+
+			/*
 			 * Clear any stale software interrupts from VPE's Cause
 			 */
 			write_vpe_c0_cause(0);
@@ -924,6 +928,7 @@
 	int irq = MIPS_CPU_IRQ_BASE + 1;
 
 	smtc_ipi_nq(&freeIPIq, pipi);
+
 	switch (type_copy) {
 	case SMTC_CLOCK_TICK:
 		irq_enter();
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/stacktrace.c linux-libre-2.6.31-gnu/arch/mips/kernel/stacktrace.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/stacktrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/stacktrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * arch/mips/kernel/stacktrace.c
- *
  * Stack trace management functions
  *
  *  Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/sync-r4k.c linux-libre-2.6.31-gnu/arch/mips/kernel/sync-r4k.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/sync-r4k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/sync-r4k.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Count register synchronisation.
  *
- * All CPUs will have their count registers synchronised to the CPU0 expirelo
+ * All CPUs will have their count registers synchronised to the CPU0 next time
  * value. This can cause a small timewarp for CPU0. All other CPU's should
  * not have done anything significant (but they may have had interrupts
  * enabled briefly - prom_smp_finish() should not be responsible for enabling
@@ -13,21 +13,22 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irqflags.h>
-#include <linux/r4k-timer.h>
+#include <linux/cpumask.h>
 
+#include <asm/r4k-timer.h>
 #include <asm/atomic.h>
 #include <asm/barrier.h>
-#include <asm/cpumask.h>
 #include <asm/mipsregs.h>
 
-static atomic_t __initdata count_start_flag = ATOMIC_INIT(0);
-static atomic_t __initdata count_count_start = ATOMIC_INIT(0);
-static atomic_t __initdata count_count_stop = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0);
 
 #define COUNTON	100
 #define NR_LOOPS 5
 
-void __init synchronise_count_master(void)
+void __cpuinit synchronise_count_master(void)
 {
 	int i;
 	unsigned long flags;
@@ -42,19 +43,20 @@
 	return;
 #endif
 
-	pr_info("Checking COUNT synchronization across %u CPUs: ",
-		num_online_cpus());
+	printk(KERN_INFO "Synchronize counters across %u CPUs: ",
+	       num_online_cpus());
 
 	local_irq_save(flags);
 
 	/*
 	 * Notify the slaves that it's time to start
 	 */
+	atomic_set(&count_reference, read_c0_count());
 	atomic_set(&count_start_flag, 1);
 	smp_wmb();
 
-	/* Count will be initialised to expirelo for all CPU's */
-	initcount = expirelo;
+	/* Count will be initialised to current timer for all CPU's */
+	initcount = read_c0_count();
 
 	/*
 	 * We loop a few times to get a primed instruction cache,
@@ -106,7 +108,7 @@
 	printk("done.\n");
 }
 
-void __init synchronise_count_slave(void)
+void __cpuinit synchronise_count_slave(void)
 {
 	int i;
 	unsigned long flags;
@@ -131,8 +133,8 @@
 	while (!atomic_read(&count_start_flag))
 		mb();
 
-	/* Count will be initialised to expirelo for all CPU's */
-	initcount = expirelo;
+	/* Count will be initialised to next expire for all CPU's */
+	initcount = atomic_read(&count_reference);
 
 	ncpus = num_online_cpus();
 	for (i = 0; i < NR_LOOPS; i++) {
@@ -156,4 +158,3 @@
 	local_irq_restore(flags);
 }
 #undef NR_LOOPS
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/topology.c linux-libre-2.6.31-gnu/arch/mips/kernel/topology.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/topology.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/topology.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,10 @@
 #endif /* CONFIG_NUMA */
 
 	for_each_present_cpu(i) {
-		ret = register_cpu(&per_cpu(cpu_devices, i), i);
+		struct cpu *c = &per_cpu(cpu_devices, i);
+
+		c->hotpluggable = 1;
+		ret = register_cpu(c, i);
 		if (ret)
 			printk(KERN_WARNING "topology_init: register_cpu %d "
 			       "failed (%d)\n", i, ret);
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/traps.c linux-libre-2.6.31-gnu/arch/mips/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -1502,7 +1502,7 @@
 			 status_set);
 
 	if (cpu_has_mips_r2) {
-		unsigned int enable = 0x0000000f;
+		unsigned int enable = 0x0000000f | cpu_hwrena_impl_bits;
 
 		if (!noulri && cpu_has_userlocal)
 			enable |= (1 << 29);
@@ -1510,10 +1510,6 @@
 		write_c0_hwrena(enable);
 	}
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-	write_c0_hwrena(0xc000000f); /* Octeon has register 30 and 31 */
-#endif
-
 #ifdef CONFIG_MIPS_MT_SMTC
 	if (!secondaryTC) {
 #endif /* CONFIG_MIPS_MT_SMTC */
diff -druN linux-libre-2.6.30-gnu/arch/mips/kernel/vpe.c linux-libre-2.6.31-gnu/arch/mips/kernel/vpe.c
--- linux-libre-2.6.30-gnu/arch/mips/kernel/vpe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/kernel/vpe.c	2009-09-09 18:13:59.000000000 -0400
@@ -73,7 +73,7 @@
 static const int minor = 1;	/* fixed for now  */
 
 #ifdef CONFIG_MIPS_APSP_KSPD
- static struct kspd_notifications kspd_events;
+static struct kspd_notifications kspd_events;
 static int kspd_events_reqd = 0;
 #endif
 
@@ -155,10 +155,9 @@
 };
 
 static void release_progmem(void *ptr);
-extern void save_gp_address(unsigned int secbase, unsigned int rel);
 
 /* get the vpe associated with this minor */
-struct vpe *get_vpe(int minor)
+static struct vpe *get_vpe(int minor)
 {
 	struct vpe *v;
 
@@ -174,7 +173,7 @@
 }
 
 /* get the vpe associated with this minor */
-struct tc *get_tc(int index)
+static struct tc *get_tc(int index)
 {
 	struct tc *t;
 
@@ -186,20 +185,8 @@
 	return NULL;
 }
 
-struct tc *get_tc_unused(void)
-{
-	struct tc *t;
-
-	list_for_each_entry(t, &vpecontrol.tc_list, list) {
-		if (t->state == TC_STATE_UNUSED)
-			return t;
-	}
-
-	return NULL;
-}
-
 /* allocate a vpe and associate it with this minor (or index) */
-struct vpe *alloc_vpe(int minor)
+static struct vpe *alloc_vpe(int minor)
 {
 	struct vpe *v;
 
@@ -216,7 +203,7 @@
 }
 
 /* allocate a tc. At startup only tc0 is running, all other can be halted. */
-struct tc *alloc_tc(int index)
+static struct tc *alloc_tc(int index)
 {
 	struct tc *tc;
 
@@ -232,7 +219,7 @@
 }
 
 /* clean up and free everything */
-void release_vpe(struct vpe *v)
+static void release_vpe(struct vpe *v)
 {
 	list_del(&v->list);
 	if (v->load_addr)
@@ -240,7 +227,7 @@
 	kfree(v);
 }
 
-void dump_mtregs(void)
+static void dump_mtregs(void)
 {
 	unsigned long val;
 
@@ -327,7 +314,8 @@
 			    || (s->sh_flags & masks[m][1])
 			    || s->sh_entsize != ~0UL)
 				continue;
-			s->sh_entsize = get_offset(&mod->core_size, s);
+			s->sh_entsize =
+				get_offset((unsigned long *)&mod->core_size, s);
 		}
 
 		if (m == 0)
@@ -461,16 +449,15 @@
 {
 	unsigned long insnlo = *location;
 	Elf32_Addr val, vallo;
+	struct mips_hi16 *l, *next;
 
 	/* Sign extend the addend we extract from the lo insn.  */
 	vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
 
 	if (mips_hi16_list != NULL) {
-		struct mips_hi16 *l;
 
 		l = mips_hi16_list;
 		while (l != NULL) {
-			struct mips_hi16 *next;
 			unsigned long insn;
 
 			/*
@@ -480,7 +467,7 @@
 				printk(KERN_DEBUG "VPE loader: "
 				       "apply_r_mips_lo16/hi16: \t"
 				       "inconsistent value information\n");
-				return -ENOEXEC;
+				goto out_free;
 			}
 
 			/*
@@ -518,6 +505,16 @@
 	*location = insnlo;
 
 	return 0;
+
+out_free:
+	while (l != NULL) {
+		next = l->next;
+		kfree(l);
+		l = next;
+	}
+	mips_hi16_list = NULL;
+
+	return -ENOEXEC;
 }
 
 static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
@@ -541,7 +538,7 @@
 	[R_MIPS_PC16] = "MIPS_PC16"
 };
 
-int apply_relocations(Elf32_Shdr *sechdrs,
+static int apply_relocations(Elf32_Shdr *sechdrs,
 		      const char *strtab,
 		      unsigned int symindex,
 		      unsigned int relsec,
@@ -586,7 +583,7 @@
 	return 0;
 }
 
-void save_gp_address(unsigned int secbase, unsigned int rel)
+static inline void save_gp_address(unsigned int secbase, unsigned int rel)
 {
 	gp_addr = secbase + rel;
 	gp_offs = gp_addr - (secbase & 0xffff0000);
@@ -1387,7 +1384,7 @@
 	return len;
 
 out_einval:
-	return -EINVAL;;
+	return -EINVAL;
 }
 
 static struct device_attribute vpe_class_attributes[] = {
diff -druN linux-libre-2.6.30-gnu/arch/mips/lib/delay.c linux-libre-2.6.31-gnu/arch/mips/lib/delay.c
--- linux-libre-2.6.30-gnu/arch/mips/lib/delay.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/lib/delay.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,7 +43,7 @@
 {
 	unsigned int lpj = current_cpu_data.udelay_val;
 
-	__delay((us * 0x000010c7 * HZ * lpj) >> 32);
+	__delay((us * 0x000010c7ull * HZ * lpj) >> 32);
 }
 EXPORT_SYMBOL(__udelay);
 
@@ -51,6 +51,6 @@
 {
 	unsigned int lpj = current_cpu_data.udelay_val;
 
-	__delay((us * 0x00000005 * HZ * lpj) >> 32);
+	__delay((ns * 0x00000005ull * HZ * lpj) >> 32);
 }
 EXPORT_SYMBOL(__ndelay);
diff -druN linux-libre-2.6.30-gnu/arch/mips/Makefile linux-libre-2.6.31-gnu/arch/mips/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -167,13 +167,19 @@
 libs-$(CONFIG_CFE)		+= arch/mips/fw/cfe/
 libs-$(CONFIG_SNIPROM)		+= arch/mips/fw/sni/
 libs-y				+= arch/mips/fw/lib/
-libs-$(CONFIG_SIBYTE_CFE)	+= arch/mips/sibyte/cfe/
 
 #
 # Board-dependent options and extra files
 #
 
 #
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7)		+= arch/mips/ar7/
+cflags-$(CONFIG_AR7)		+= -I$(srctree)/arch/mips/include/asm/mach-ar7
+load-$(CONFIG_AR7)		+= 0xffffffff94100000
+
+#
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
 core-$(CONFIG_MACH_JAZZ)	+= arch/mips/jazz/
@@ -184,7 +190,6 @@
 # Common Alchemy Au1x00 stuff
 #
 core-$(CONFIG_SOC_AU1X00)	+= arch/mips/alchemy/common/
-cflags-$(CONFIG_SOC_AU1X00)	+= -I$(srctree)/arch/mips/include/asm/mach-au1x00
 
 #
 # AMD Alchemy Pb1000 eval board
@@ -282,6 +287,10 @@
 libs-$(CONFIG_MIPS_XXS1500)	+= arch/mips/alchemy/xxs1500/
 load-$(CONFIG_MIPS_XXS1500)	+= 0xffffffff80100000
 
+# must be last for Alchemy systems for GPIO to work properly
+cflags-$(CONFIG_SOC_AU1X00)	+= -I$(srctree)/arch/mips/include/asm/mach-au1x00
+
+
 #
 # Cobalt Server
 #
@@ -675,6 +684,9 @@
 
 drivers-$(CONFIG_OPROFILE)	+= arch/mips/oprofile/
 
+# suspend and hibernation support
+drivers-$(CONFIG_PM)	+= arch/mips/power/
+
 ifdef CONFIG_LASAT
 rom.bin rom.sw: vmlinux
 	$(Q)$(MAKE) $(build)=arch/mips/lasat/image $@
diff -druN linux-libre-2.6.30-gnu/arch/mips/mipssim/sim_time.c linux-libre-2.6.31-gnu/arch/mips/mipssim/sim_time.c
--- linux-libre-2.6.30-gnu/arch/mips/mipssim/sim_time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mipssim/sim_time.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,12 +89,13 @@
 	if (cpu_has_veic) {
 		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
 		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
-	} else {
-#endif
-		if (cpu_has_vint)
-			set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
-		mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+
+		return mips_cpu_timer_irq;
 	}
+#endif
+	if (cpu_has_vint)
+		set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
+	mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
 
 	return mips_cpu_timer_irq;
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/c-octeon.c linux-libre-2.6.31-gnu/arch/mips/mm/c-octeon.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/c-octeon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/c-octeon.c	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 #include <linux/bitops.h>
 #include <linux/cpu.h>
@@ -288,7 +289,7 @@
 }
 
 /**
- * Called when the the exception is not recoverable
+ * Called when the the exception is recoverable
  */
 
 asmlinkage void cache_parity_error_octeon_recoverable(void)
@@ -297,7 +298,7 @@
 }
 
 /**
- * Called when the the exception is recoverable
+ * Called when the the exception is not recoverable
  */
 
 asmlinkage void cache_parity_error_octeon_non_recoverable(void)
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/c-r3k.c linux-libre-2.6.31-gnu/arch/mips/mm/c-r3k.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/c-r3k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/c-r3k.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 
 #include <asm/page.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/c-r4k.c linux-libre-2.6.31-gnu/arch/mips/mm/c-r4k.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/c-r4k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/c-r4k.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/linkage.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
@@ -100,6 +101,12 @@
 	blast_dcache32_page(addr);
 }
 
+static inline void r4k_blast_dcache_page_dc64(unsigned long addr)
+{
+	R4600_HIT_CACHEOP_WAR_IMPL;
+	blast_dcache64_page(addr);
+}
+
 static void __cpuinit r4k_blast_dcache_page_setup(void)
 {
 	unsigned long  dc_lsize = cpu_dcache_line_size();
@@ -110,6 +117,8 @@
 		r4k_blast_dcache_page = blast_dcache16_page;
 	else if (dc_lsize == 32)
 		r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
+	else if (dc_lsize == 64)
+		r4k_blast_dcache_page = r4k_blast_dcache_page_dc64;
 }
 
 static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
@@ -124,6 +133,8 @@
 		r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
 	else if (dc_lsize == 32)
 		r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
+	else if (dc_lsize == 64)
+		r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed;
 }
 
 static void (* r4k_blast_dcache)(void);
@@ -138,6 +149,8 @@
 		r4k_blast_dcache = blast_dcache16;
 	else if (dc_lsize == 32)
 		r4k_blast_dcache = blast_dcache32;
+	else if (dc_lsize == 64)
+		r4k_blast_dcache = blast_dcache64;
 }
 
 /* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/c-tx39.c linux-libre-2.6.31-gnu/arch/mips/mm/c-tx39.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/c-tx39.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/c-tx39.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 
 #include <asm/cacheops.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/dma-default.c linux-libre-2.6.31-gnu/arch/mips/mm/dma-default.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/dma-default.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/dma-default.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,9 +20,10 @@
 
 #include <dma-coherence.h>
 
-static inline unsigned long dma_addr_to_virt(dma_addr_t dma_addr)
+static inline unsigned long dma_addr_to_virt(struct device *dev,
+	dma_addr_t dma_addr)
 {
-	unsigned long addr = plat_dma_addr_to_phys(dma_addr);
+	unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr);
 
 	return (unsigned long)phys_to_virt(addr);
 }
@@ -111,7 +112,7 @@
 void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
 	dma_addr_t dma_handle)
 {
-	plat_unmap_dma_mem(dev, dma_handle);
+	plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
@@ -122,7 +123,7 @@
 {
 	unsigned long addr = (unsigned long) vaddr;
 
-	plat_unmap_dma_mem(dev, dma_handle);
+	plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
 
 	if (!plat_device_is_coherent(dev))
 		addr = CAC_ADDR(addr);
@@ -170,10 +171,10 @@
 	enum dma_data_direction direction)
 {
 	if (cpu_is_noncoherent_r10000(dev))
-		__dma_sync(dma_addr_to_virt(dma_addr), size,
+		__dma_sync(dma_addr_to_virt(dev, dma_addr), size,
 		           direction);
 
-	plat_unmap_dma_mem(dev, dma_addr);
+	plat_unmap_dma_mem(dev, dma_addr, size, direction);
 }
 
 EXPORT_SYMBOL(dma_unmap_single);
@@ -232,7 +233,7 @@
 			if (addr)
 				__dma_sync(addr, sg->length, direction);
 		}
-		plat_unmap_dma_mem(dev, sg->dma_address);
+		plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
 	}
 }
 
@@ -246,7 +247,7 @@
 	if (cpu_is_noncoherent_r10000(dev)) {
 		unsigned long addr;
 
-		addr = dma_addr_to_virt(dma_handle);
+		addr = dma_addr_to_virt(dev, dma_handle);
 		__dma_sync(addr, size, direction);
 	}
 }
@@ -262,7 +263,7 @@
 	if (!plat_device_is_coherent(dev)) {
 		unsigned long addr;
 
-		addr = dma_addr_to_virt(dma_handle);
+		addr = dma_addr_to_virt(dev, dma_handle);
 		__dma_sync(addr, size, direction);
 	}
 }
@@ -277,7 +278,7 @@
 	if (cpu_is_noncoherent_r10000(dev)) {
 		unsigned long addr;
 
-		addr = dma_addr_to_virt(dma_handle);
+		addr = dma_addr_to_virt(dev, dma_handle);
 		__dma_sync(addr + offset, size, direction);
 	}
 }
@@ -293,7 +294,7 @@
 	if (!plat_device_is_coherent(dev)) {
 		unsigned long addr;
 
-		addr = dma_addr_to_virt(dma_handle);
+		addr = dma_addr_to_virt(dev, dma_handle);
 		__dma_sync(addr + offset, size, direction);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/extable.c linux-libre-2.6.31-gnu/arch/mips/mm/extable.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/extable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/extable.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,9 @@
 /*
- * linux/arch/mips/mm/extable.c
+ * 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) 1997, 99, 2001 - 2004 Ralf Baechle <ralf@linux-mips.org>
  */
 #include <linux/module.h>
 #include <linux/spinlock.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/fault.c linux-libre-2.6.31-gnu/arch/mips/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -102,7 +102,7 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, address, write);
+	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -171,6 +171,7 @@
 	 * We ran out of memory, call the OOM killer, and return the userspace
 	 * (which will retry the fault, or kill us if we got oom-killed).
 	 */
+	up_read(&mm->mmap_sem);
 	pagefault_out_of_memory();
 	return;
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/highmem.c linux-libre-2.6.31-gnu/arch/mips/mm/highmem.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/highmem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/highmem.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,6 @@
 #include <linux/module.h>
 #include <linux/highmem.h>
+#include <linux/smp.h>
 #include <asm/fixmap.h>
 #include <asm/tlbflush.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/hugetlbpage.c linux-libre-2.6.31-gnu/arch/mips/mm/hugetlbpage.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/hugetlbpage.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/mm/hugetlbpage.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * MIPS Huge TLB Page Support for Kernel.
+ *
+ * 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) 2002, Rohit Seth <rohit.seth@intel.com>
+ * Copyright 2005, Embedded Alley Solutions, Inc.
+ * Matt Porter <mporter@embeddedalley.com>
+ * Copyright (C) 2008, 2009 Cavium Networks, Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr,
+		      unsigned long sz)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pte_t *pte = NULL;
+
+	pgd = pgd_offset(mm, addr);
+	pud = pud_alloc(mm, pgd, addr);
+	if (pud)
+		pte = (pte_t *)pmd_alloc(mm, pud, addr);
+
+	return pte;
+}
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd = NULL;
+
+	pgd = pgd_offset(mm, addr);
+	if (pgd_present(*pgd)) {
+		pud = pud_offset(pgd, addr);
+		if (pud_present(*pud))
+			pmd = pmd_offset(pud, addr);
+	}
+	return (pte_t *) pmd;
+}
+
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+	return 0;
+}
+
+/*
+ * This function checks for proper alignment of input addr and len parameters.
+ */
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
+{
+	if (len & ~HPAGE_MASK)
+		return -EINVAL;
+	if (addr & ~HPAGE_MASK)
+		return -EINVAL;
+	return 0;
+}
+
+struct page *
+follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+int pmd_huge(pmd_t pmd)
+{
+	return (pmd_val(pmd) & _PAGE_HUGE) != 0;
+}
+
+int pud_huge(pud_t pud)
+{
+	return (pud_val(pud) & _PAGE_HUGE) != 0;
+}
+
+struct page *
+follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+		pmd_t *pmd, int write)
+{
+	struct page *page;
+
+	page = pte_page(*(pte_t *)pmd);
+	if (page)
+		page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
+	return page;
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/init.c linux-libre-2.6.31-gnu/arch/mips/mm/init.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/Makefile linux-libre-2.6.31-gnu/arch/mips/mm/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/mm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,7 @@
 obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
+obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 
 obj-$(CONFIG_CPU_LOONGSON2)	+= c-r4k.o cex-gen.o tlb-r4k.o
 obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o tlb-r4k.o
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/page.c linux-libre-2.6.31-gnu/arch/mips/mm/page.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/page.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/page.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/tlbex.c linux-libre-2.6.31-gnu/arch/mips/mm/tlbex.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/tlbex.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/tlbex.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,8 +6,9 @@
  * Synthesize TLB refill handlers at runtime.
  *
  * Copyright (C) 2004, 2005, 2006, 2008  Thiemo Seufer
- * Copyright (C) 2005, 2007  Maciej W. Rozycki
+ * Copyright (C) 2005, 2007, 2008, 2009  Maciej W. Rozycki
  * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2008, 2009 Cavium Networks, Inc.
  *
  * ... and the days got worse and worse and now you see
  * I've gone completly out of my mind.
@@ -19,8 +20,10 @@
  * (Condolences to Napoleon XIV)
  */
 
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/smp.h>
 #include <linux/string.h>
 #include <linux/init.h>
 
@@ -82,6 +85,9 @@
 	label_nopage_tlbm,
 	label_smp_pgtable_change,
 	label_r3000_write_probe_fail,
+#ifdef CONFIG_HUGETLB_PAGE
+	label_tlb_huge_update,
+#endif
 };
 
 UASM_L_LA(_second_part)
@@ -98,6 +104,9 @@
 UASM_L_LA(_nopage_tlbm)
 UASM_L_LA(_smp_pgtable_change)
 UASM_L_LA(_r3000_write_probe_fail)
+#ifdef CONFIG_HUGETLB_PAGE
+UASM_L_LA(_tlb_huge_update)
+#endif
 
 /*
  * For debug purposes.
@@ -125,6 +134,7 @@
 #define C0_TCBIND	2, 2
 #define C0_ENTRYLO1	3, 0
 #define C0_CONTEXT	4, 0
+#define C0_PAGEMASK	5, 0
 #define C0_BADVADDR	8, 0
 #define C0_ENTRYHI	10, 0
 #define C0_EPC		14, 0
@@ -258,7 +268,8 @@
 	}
 
 	if (cpu_has_mips_r2) {
-		uasm_i_ehb(p);
+		if (cpu_has_mips_r2_exec_hazard)
+			uasm_i_ehb(p);
 		tlbw(p);
 		return;
 	}
@@ -310,7 +321,6 @@
 	case CPU_BCM3302:
 	case CPU_BCM4710:
 	case CPU_LOONGSON2:
-	case CPU_CAVIUM_OCTEON:
 	case CPU_R5500:
 		if (m4kc_tlbp_war())
 			uasm_i_nop(p);
@@ -382,6 +392,98 @@
 	}
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
+static __cpuinit void build_huge_tlb_write_entry(u32 **p,
+						 struct uasm_label **l,
+						 struct uasm_reloc **r,
+						 unsigned int tmp,
+						 enum tlb_write_entry wmode)
+{
+	/* Set huge page tlb entry size */
+	uasm_i_lui(p, tmp, PM_HUGE_MASK >> 16);
+	uasm_i_ori(p, tmp, tmp, PM_HUGE_MASK & 0xffff);
+	uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+
+	build_tlb_write_entry(p, l, r, wmode);
+
+	/* Reset default page size */
+	if (PM_DEFAULT_MASK >> 16) {
+		uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
+		uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff);
+		uasm_il_b(p, r, label_leave);
+		uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+	} else if (PM_DEFAULT_MASK) {
+		uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK);
+		uasm_il_b(p, r, label_leave);
+		uasm_i_mtc0(p, tmp, C0_PAGEMASK);
+	} else {
+		uasm_il_b(p, r, label_leave);
+		uasm_i_mtc0(p, 0, C0_PAGEMASK);
+	}
+}
+
+/*
+ * Check if Huge PTE is present, if so then jump to LABEL.
+ */
+static void __cpuinit
+build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp,
+		unsigned int pmd, int lid)
+{
+	UASM_i_LW(p, tmp, 0, pmd);
+	uasm_i_andi(p, tmp, tmp, _PAGE_HUGE);
+	uasm_il_bnez(p, r, tmp, lid);
+}
+
+static __cpuinit void build_huge_update_entries(u32 **p,
+						unsigned int pte,
+						unsigned int tmp)
+{
+	int small_sequence;
+
+	/*
+	 * A huge PTE describes an area the size of the
+	 * configured huge page size. This is twice the
+	 * of the large TLB entry size we intend to use.
+	 * A TLB entry half the size of the configured
+	 * huge page size is configured into entrylo0
+	 * and entrylo1 to cover the contiguous huge PTE
+	 * address space.
+	 */
+	small_sequence = (HPAGE_SIZE >> 7) < 0x10000;
+
+	/* We can clobber tmp.  It isn't used after this.*/
+	if (!small_sequence)
+		uasm_i_lui(p, tmp, HPAGE_SIZE >> (7 + 16));
+
+	UASM_i_SRL(p, pte, pte, 6); /* convert to entrylo */
+	uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* load it */
+	/* convert to entrylo1 */
+	if (small_sequence)
+		UASM_i_ADDIU(p, pte, pte, HPAGE_SIZE >> 7);
+	else
+		UASM_i_ADDU(p, pte, pte, tmp);
+
+	uasm_i_mtc0(p, pte, C0_ENTRYLO1); /* load it */
+}
+
+static __cpuinit void build_huge_handler_tail(u32 **p,
+					      struct uasm_reloc **r,
+					      struct uasm_label **l,
+					      unsigned int pte,
+					      unsigned int ptr)
+{
+#ifdef CONFIG_SMP
+	UASM_i_SC(p, pte, 0, ptr);
+	uasm_il_beqz(p, r, pte, label_tlb_huge_update);
+	UASM_i_LW(p, pte, 0, ptr); /* Needed because SC killed our PTE */
+#else
+	UASM_i_SW(p, pte, 0, ptr);
+#endif
+	build_huge_update_entries(p, pte, ptr);
+	build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed);
+}
+#endif /* CONFIG_HUGETLB_PAGE */
+
 #ifdef CONFIG_64BIT
 /*
  * TMP and PTR are scratch.
@@ -649,6 +751,14 @@
 #endif
 }
 
+/*
+ * For a 64-bit kernel, we are using the 64-bit XTLB refill exception
+ * because EXL == 0.  If we wrap, we can also use the 32 instruction
+ * slots before the XTLB refill exception handler which belong to the
+ * unused TLB refill exception.
+ */
+#define MIPS64_REFILL_INSNS 32
+
 static void __cpuinit build_r4000_tlb_refill_handler(void)
 {
 	u32 *p = tlb_handler;
@@ -680,12 +790,23 @@
 	build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
 #endif
 
+#ifdef CONFIG_HUGETLB_PAGE
+	build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
+#endif
+
 	build_get_ptep(&p, K0, K1);
 	build_update_entries(&p, K0, K1);
 	build_tlb_write_entry(&p, &l, &r, tlb_random);
 	uasm_l_leave(&l, p);
 	uasm_i_eret(&p); /* return from trap */
 
+#ifdef CONFIG_HUGETLB_PAGE
+	uasm_l_tlb_huge_update(&l, p);
+	UASM_i_LW(&p, K0, 0, K1);
+	build_huge_update_entries(&p, K0, K1);
+	build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random);
+#endif
+
 #ifdef CONFIG_64BIT
 	build_get_pgd_vmalloc64(&p, &l, &r, K0, K1);
 #endif
@@ -702,9 +823,10 @@
 	if ((p - tlb_handler) > 64)
 		panic("TLB refill handler space exceeded");
 #else
-	if (((p - tlb_handler) > 63)
-	    || (((p - tlb_handler) > 61)
-		&& uasm_insn_has_bdelay(relocs, tlb_handler + 29)))
+	if (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 1)
+	    || (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 3)
+		&& uasm_insn_has_bdelay(relocs,
+					tlb_handler + MIPS64_REFILL_INSNS - 3)))
 		panic("TLB refill handler space exceeded");
 #endif
 
@@ -717,39 +839,74 @@
 	uasm_copy_handler(relocs, labels, tlb_handler, p, f);
 	final_len = p - tlb_handler;
 #else /* CONFIG_64BIT */
-	f = final_handler + 32;
-	if ((p - tlb_handler) <= 32) {
+	f = final_handler + MIPS64_REFILL_INSNS;
+	if ((p - tlb_handler) <= MIPS64_REFILL_INSNS) {
 		/* Just copy the handler. */
 		uasm_copy_handler(relocs, labels, tlb_handler, p, f);
 		final_len = p - tlb_handler;
 	} else {
-		u32 *split = tlb_handler + 30;
+#if defined(CONFIG_HUGETLB_PAGE)
+		const enum label_id ls = label_tlb_huge_update;
+#elif defined(MODULE_START)
+		const enum label_id ls = label_module_alloc;
+#else
+		const enum label_id ls = label_vmalloc;
+#endif
+		u32 *split;
+		int ov = 0;
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(labels) && labels[i].lab != ls; i++)
+			;
+		BUG_ON(i == ARRAY_SIZE(labels));
+		split = labels[i].addr;
 
 		/*
-		 * Find the split point.
+		 * See if we have overflown one way or the other.
 		 */
-		if (uasm_insn_has_bdelay(relocs, split - 1))
-			split--;
+		if (split > tlb_handler + MIPS64_REFILL_INSNS ||
+		    split < p - MIPS64_REFILL_INSNS)
+			ov = 1;
 
+		if (ov) {
+			/*
+			 * Split two instructions before the end.  One
+			 * for the branch and one for the instruction
+			 * in the delay slot.
+			 */
+			split = tlb_handler + MIPS64_REFILL_INSNS - 2;
+
+			/*
+			 * If the branch would fall in a delay slot,
+			 * we must back up an additional instruction
+			 * so that it is no longer in a delay slot.
+			 */
+			if (uasm_insn_has_bdelay(relocs, split - 1))
+				split--;
+		}
 		/* Copy first part of the handler. */
 		uasm_copy_handler(relocs, labels, tlb_handler, split, f);
 		f += split - tlb_handler;
 
-		/* Insert branch. */
-		uasm_l_split(&l, final_handler);
-		uasm_il_b(&f, &r, label_split);
-		if (uasm_insn_has_bdelay(relocs, split))
-			uasm_i_nop(&f);
-		else {
-			uasm_copy_handler(relocs, labels, split, split + 1, f);
-			uasm_move_labels(labels, f, f + 1, -1);
-			f++;
-			split++;
+		if (ov) {
+			/* Insert branch. */
+			uasm_l_split(&l, final_handler);
+			uasm_il_b(&f, &r, label_split);
+			if (uasm_insn_has_bdelay(relocs, split))
+				uasm_i_nop(&f);
+			else {
+				uasm_copy_handler(relocs, labels,
+						  split, split + 1, f);
+				uasm_move_labels(labels, f, f + 1, -1);
+				f++;
+				split++;
+			}
 		}
 
 		/* Copy the rest of the handler. */
 		uasm_copy_handler(relocs, labels, split, p, final_handler);
-		final_len = (f - (final_handler + 32)) + (p - split);
+		final_len = (f - (final_handler + MIPS64_REFILL_INSNS)) +
+			    (p - split);
 	}
 #endif /* CONFIG_64BIT */
 
@@ -782,7 +939,7 @@
 u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
 
 static void __cpuinit
-iPTE_LW(u32 **p, struct uasm_label **l, unsigned int pte, unsigned int ptr)
+iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
 {
 #ifdef CONFIG_SMP
 # ifdef CONFIG_64BIT_PHYS_ADDR
@@ -862,13 +1019,13 @@
  * with it's original value.
  */
 static void __cpuinit
-build_pte_present(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
+build_pte_present(u32 **p, struct uasm_reloc **r,
 		  unsigned int pte, unsigned int ptr, enum label_id lid)
 {
 	uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
 	uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
 	uasm_il_bnez(p, r, pte, lid);
-	iPTE_LW(p, l, pte, ptr);
+	iPTE_LW(p, pte, ptr);
 }
 
 /* Make PTE valid, store result in PTR. */
@@ -886,13 +1043,13 @@
  * restore PTE with value from PTR when done.
  */
 static void __cpuinit
-build_pte_writable(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
+build_pte_writable(u32 **p, struct uasm_reloc **r,
 		   unsigned int pte, unsigned int ptr, enum label_id lid)
 {
 	uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
 	uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
 	uasm_il_bnez(p, r, pte, lid);
-	iPTE_LW(p, l, pte, ptr);
+	iPTE_LW(p, pte, ptr);
 }
 
 /* Make PTE writable, update software status bits as well, then store
@@ -913,12 +1070,12 @@
  * restore PTE with value from PTR when done.
  */
 static void __cpuinit
-build_pte_modifiable(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
+build_pte_modifiable(u32 **p, struct uasm_reloc **r,
 		     unsigned int pte, unsigned int ptr, enum label_id lid)
 {
 	uasm_i_andi(p, pte, pte, _PAGE_WRITE);
 	uasm_il_beqz(p, r, pte, lid);
-	iPTE_LW(p, l, pte, ptr);
+	iPTE_LW(p, pte, ptr);
 }
 
 /*
@@ -994,7 +1151,7 @@
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
-	build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
+	build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
 	uasm_i_nop(&p); /* load delay */
 	build_make_valid(&p, &r, K0, K1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1024,7 +1181,7 @@
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
-	build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
+	build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
 	uasm_i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
@@ -1054,7 +1211,7 @@
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
-	build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
+	build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
 	uasm_i_nop(&p); /* load delay */
 	build_make_write(&p, &r, K0, K1);
 	build_r3000_pte_reload_tlbwi(&p, K0, K1);
@@ -1087,6 +1244,15 @@
 	build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
 #endif
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * For huge tlb entries, pmd doesn't contain an address but
+	 * instead contains the tlb pte. Check the PAGE_HUGE bit and
+	 * see if we need to jump to huge tlb processing.
+	 */
+	build_is_huge_pte(p, r, pte, ptr, label_tlb_huge_update);
+#endif
+
 	UASM_i_MFC0(p, pte, C0_BADVADDR);
 	UASM_i_LW(p, ptr, 0, ptr);
 	UASM_i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
@@ -1096,7 +1262,7 @@
 #ifdef CONFIG_SMP
 	uasm_l_smp_pgtable_change(l, *p);
 #endif
-	iPTE_LW(p, l, pte, ptr); /* get even pte */
+	iPTE_LW(p, pte, ptr); /* get even pte */
 	if (!m4kc_tlbp_war())
 		build_tlb_probe_entry(p);
 }
@@ -1138,12 +1304,25 @@
 	}
 
 	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-	build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
+	build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 	build_make_valid(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * This is the entry point when build_r4000_tlbchange_handler_head
+	 * spots a huge page.
+	 */
+	uasm_l_tlb_huge_update(&l, p);
+	iPTE_LW(&p, K0, K1);
+	build_pte_present(&p, &r, K0, K1, label_nopage_tlbl);
+	build_tlb_probe_entry(&p);
+	uasm_i_ori(&p, K0, K0, (_PAGE_ACCESSED | _PAGE_VALID));
+	build_huge_handler_tail(&p, &r, &l, K0, K1);
+#endif
+
 	uasm_l_nopage_tlbl(&l, p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
 	uasm_i_nop(&p);
@@ -1169,12 +1348,26 @@
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-	build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
+	build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 	build_make_write(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * This is the entry point when
+	 * build_r4000_tlbchange_handler_head spots a huge page.
+	 */
+	uasm_l_tlb_huge_update(&l, p);
+	iPTE_LW(&p, K0, K1);
+	build_pte_writable(&p, &r, K0, K1, label_nopage_tlbs);
+	build_tlb_probe_entry(&p);
+	uasm_i_ori(&p, K0, K0,
+		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
+	build_huge_handler_tail(&p, &r, &l, K0, K1);
+#endif
+
 	uasm_l_nopage_tlbs(&l, p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
 	uasm_i_nop(&p);
@@ -1200,13 +1393,27 @@
 	memset(relocs, 0, sizeof(relocs));
 
 	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
-	build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
+	build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 	/* Present and writable bits set, set accessed and dirty bits. */
 	build_make_write(&p, &r, K0, K1);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/*
+	 * This is the entry point when
+	 * build_r4000_tlbchange_handler_head spots a huge page.
+	 */
+	uasm_l_tlb_huge_update(&l, p);
+	iPTE_LW(&p, K0, K1);
+	build_pte_modifiable(&p, &r, K0, K1, label_nopage_tlbm);
+	build_tlb_probe_entry(&p);
+	uasm_i_ori(&p, K0, K0,
+		   _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
+	build_huge_handler_tail(&p, &r, &l, K0, K1);
+#endif
+
 	uasm_l_nopage_tlbm(&l, p);
 	uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
 	uasm_i_nop(&p);
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/tlb-r3k.c linux-libre-2.6.31-gnu/arch/mips/mm/tlb-r3k.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/tlb-r3k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/tlb-r3k.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 
 #include <asm/page.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/tlb-r4k.c linux-libre-2.6.31-gnu/arch/mips/mm/tlb-r4k.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/tlb-r4k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/tlb-r4k.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,9 @@
  */
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
+#include <linux/hugetlb.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -295,21 +297,41 @@
 	pudp = pud_offset(pgdp, address);
 	pmdp = pmd_offset(pudp, address);
 	idx = read_c0_index();
-	ptep = pte_offset_map(pmdp, address);
+#ifdef CONFIG_HUGETLB_PAGE
+	/* this could be a huge page  */
+	if (pmd_huge(*pmdp)) {
+		unsigned long lo;
+		write_c0_pagemask(PM_HUGE_MASK);
+		ptep = (pte_t *)pmdp;
+		lo = pte_val(*ptep) >> 6;
+		write_c0_entrylo0(lo);
+		write_c0_entrylo1(lo + (HPAGE_SIZE >> 7));
+
+		mtc0_tlbw_hazard();
+		if (idx < 0)
+			tlb_write_random();
+		else
+			tlb_write_indexed();
+		write_c0_pagemask(PM_DEFAULT_MASK);
+	} else
+#endif
+	{
+		ptep = pte_offset_map(pmdp, address);
 
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
-	write_c0_entrylo0(ptep->pte_high);
-	ptep++;
-	write_c0_entrylo1(ptep->pte_high);
+		write_c0_entrylo0(ptep->pte_high);
+		ptep++;
+		write_c0_entrylo1(ptep->pte_high);
 #else
-	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-	write_c0_entrylo1(pte_val(*ptep) >> 6);
+		write_c0_entrylo0(pte_val(*ptep++) >> 6);
+		write_c0_entrylo1(pte_val(*ptep) >> 6);
 #endif
-	mtc0_tlbw_hazard();
-	if (idx < 0)
-		tlb_write_random();
-	else
-		tlb_write_indexed();
+		mtc0_tlbw_hazard();
+		if (idx < 0)
+			tlb_write_random();
+		else
+			tlb_write_indexed();
+	}
 	tlbw_use_hazard();
 	FLUSH_ITLB_VM(vma);
 	EXIT_CRITICAL(flags);
diff -druN linux-libre-2.6.30-gnu/arch/mips/mm/tlb-r8k.c linux-libre-2.6.31-gnu/arch/mips/mm/tlb-r8k.c
--- linux-libre-2.6.30-gnu/arch/mips/mm/tlb-r8k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mm/tlb-r8k.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
  */
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 
 #include <asm/cpu.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-init.c linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-init.c
--- linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-init.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 
+#include <asm/gcmpregs.h>
 #include <asm/mips-boards/prom.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/bonito64.h>
@@ -192,6 +193,8 @@
 
 void __init prom_init(void)
 {
+	int result;
+
 	prom_argc = fw_arg0;
 	_prom_argv = (int *) fw_arg1;
 	_prom_envp = (int *) fw_arg2;
@@ -358,12 +361,21 @@
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 	console_config();
 #endif
+	/* Early detection of CMP support */
+	result = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
+
 #ifdef CONFIG_MIPS_CMP
-	register_smp_ops(&cmp_smp_ops);
+	if (result)
+		register_smp_ops(&cmp_smp_ops);
 #endif
 #ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_CMP
+	if (!result)
+		register_smp_ops(&vsmp_smp_ops);
+#else
 	register_smp_ops(&vsmp_smp_ops);
 #endif
+#endif
 #ifdef CONFIG_MIPS_MT_SMTC
 	register_smp_ops(&msmtc_smp_ops);
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-int.c linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-int.c
--- linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-int.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-int.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -332,6 +333,21 @@
 };
 #endif /* CONFIG_MIPS_MT_SMP */
 
+static int gic_resched_int_base;
+static int gic_call_int_base;
+#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu))
+#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu))
+
+unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
+{
+	return GIC_CALL_INT(cpu);
+}
+
+unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
+{
+	return GIC_RESCHED_INT(cpu);
+}
+
 static struct irqaction i8259irq = {
 	.handler = no_action,
 	.name = "XT-PIC cascade"
@@ -369,7 +385,7 @@
  * Interrupts and CPUs/Core Interrupts. The nature of the External
  * Interrupts is also defined here - polarity/trigger.
  */
-static struct gic_intr_map gic_intr_map[] = {
+static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
 	{ GIC_EXT_INTR(0), 	X,	X,		X, 		X,		0 },
 	{ GIC_EXT_INTR(1), 	X,	X,		X, 		X,		0 },
 	{ GIC_EXT_INTR(2), 	X,	X,		X, 		X,		0 },
@@ -386,21 +402,14 @@
 	{ GIC_EXT_INTR(13), 	0,	GIC_MAP_TO_NMI_MSK,	GIC_POL_POS, GIC_TRIG_LEVEL,	0 },
 	{ GIC_EXT_INTR(14), 	0,	GIC_MAP_TO_NMI_MSK,	GIC_POL_POS, GIC_TRIG_LEVEL,	0 },
 	{ GIC_EXT_INTR(15), 	X,	X,		X, 		X,		0 },
-	{ GIC_EXT_INTR(16), 	0,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
-	{ GIC_EXT_INTR(17), 	0,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
-	{ GIC_EXT_INTR(18), 	1,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
-	{ GIC_EXT_INTR(19), 	1,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
-	{ GIC_EXT_INTR(20), 	2,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
-	{ GIC_EXT_INTR(21), 	2,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
-	{ GIC_EXT_INTR(22), 	3,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
-	{ GIC_EXT_INTR(23), 	3,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
+/* This is the end of the general interrupts now we do IPI ones */
 };
 #endif
 
 /*
  * GCMP needs to be detected before any SMP initialisation
  */
-static int __init gcmp_probe(unsigned long addr, unsigned long size)
+int __init gcmp_probe(unsigned long addr, unsigned long size)
 {
 	if (gcmp_present >= 0)
 		return gcmp_present;
@@ -415,28 +424,36 @@
 }
 
 #if defined(CONFIG_MIPS_MT_SMP)
+static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
+{
+	int intr = baseintr + cpu;
+	gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr);
+	gic_intr_map[intr].cpunum = cpu;
+	gic_intr_map[intr].pin = cpupin;
+	gic_intr_map[intr].polarity = GIC_POL_POS;
+	gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
+	gic_intr_map[intr].ipiflag = 1;
+	ipi_map[cpu] |= (1 << (cpupin + 2));
+}
+
 static void __init fill_ipi_map(void)
 {
-	int i;
+	int cpu;
 
-	for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) {
-		if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X))
-			ipi_map[gic_intr_map[i].cpunum] |=
-				(1 << (gic_intr_map[i].pin + 2));
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
+		fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
 	}
 }
 #endif
 
 void __init arch_init_irq(void)
 {
-	int gic_present, gcmp_present;
-
 	init_i8259_irqs();
 
 	if (!cpu_has_veic)
 		mips_cpu_irq_init();
 
-	gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
 	if (gcmp_present)  {
 		GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
 		gic_present = 1;
@@ -513,24 +530,10 @@
 	if (gic_present) {
 		/* FIXME */
 		int i;
-		struct {
-			unsigned int resched;
-			unsigned int call;
-		} ipiirq[] = {
-			{
-				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE0,
-				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE0},
-			{
-				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE1,
-				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE1
-			}, {
-				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE2,
-				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE2
-			}, {
-				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE3,
-				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE3
-			}
-		};
+
+		gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
+		gic_resched_int_base = gic_call_int_base - NR_CPUS;
+
 		fill_ipi_map();
 		gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
 		if (!gcmp_present) {
@@ -552,12 +555,15 @@
 		printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
 		write_c0_status(0x1100dc00);
 		printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
-		for (i = 0; i < ARRAY_SIZE(ipiirq); i++) {
-			setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched);
-			setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call);
-
-			set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq);
-			set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq);
+		for (i = 0; i < NR_CPUS; i++) {
+			setup_irq(MIPS_GIC_IRQ_BASE +
+					GIC_RESCHED_INT(i), &irq_resched);
+			setup_irq(MIPS_GIC_IRQ_BASE +
+					GIC_CALL_INT(i), &irq_call);
+			set_irq_handler(MIPS_GIC_IRQ_BASE +
+					GIC_RESCHED_INT(i), handle_percpu_irq);
+			set_irq_handler(MIPS_GIC_IRQ_BASE +
+					GIC_CALL_INT(i), handle_percpu_irq);
 		}
 	} else {
 		/* set up ipi interrupts */
diff -druN linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-reset.c linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-reset.c
--- linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-reset.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-reset.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,9 +28,6 @@
 #include <asm/reboot.h>
 #include <asm/mips-boards/generic.h>
 
-static void mips_machine_restart(char *command);
-static void mips_machine_halt(void);
-
 static void mips_machine_restart(char *command)
 {
 	unsigned int __iomem *softres_reg =
diff -druN linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-smtc.c linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-smtc.c
--- linux-libre-2.6.30-gnu/arch/mips/mti-malta/malta-smtc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/mti-malta/malta-smtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -114,7 +114,7 @@
  */
 
 
-void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
+int plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
 {
 	cpumask_t tmask;
 	int cpu = 0;
@@ -156,5 +156,7 @@
 
 	/* Do any generic SMTC IRQ affinity setup */
 	smtc_set_irq_affinity(irq, tmask);
+
+	return 0;
 }
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff -druN linux-libre-2.6.30-gnu/arch/mips/nxp/pnx8550/common/time.c linux-libre-2.6.31-gnu/arch/mips/nxp/pnx8550/common/time.c
--- linux-libre-2.6.30-gnu/arch/mips/nxp/pnx8550/common/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/nxp/pnx8550/common/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -138,7 +138,7 @@
 	 * HZ timer interrupts per second.
 	 */
 	mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
-	cpj = (mips_hpt_frequency + HZ / 2) / HZ;
+	cpj = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ);
 	write_c0_count(0);
 	timer_ack();
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/fixup-capcella.c linux-libre-2.6.31-gnu/arch/mips/pci/fixup-capcella.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/fixup-capcella.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/fixup-capcella.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups.
  *
- *  Copyright (C) 2002,2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002,2004  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/fixup-emma2rh.c linux-libre-2.6.31-gnu/arch/mips/pci/fixup-emma2rh.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/fixup-emma2rh.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/fixup-emma2rh.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/pci/fixup-emma2rh.c
- *      This file defines the PCI configration.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/fixup-mpc30x.c linux-libre-2.6.31-gnu/arch/mips/pci/fixup-mpc30x.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/fixup-mpc30x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/fixup-mpc30x.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups.
  *
- *  Copyright (C) 2002,2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002,2004  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/fixup-sb1250.c linux-libre-2.6.31-gnu/arch/mips/pci/fixup-sb1250.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/fixup-sb1250.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/fixup-sb1250.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	arch/mips/pci/fixup-sb1250.c
- *
  *	Copyright (C) 2004, 2006  MIPS Technologies, Inc.  All rights reserved.
  *	    Author:	Maciej W. Rozycki <macro@mips.com>
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/fixup-tb0219.c linux-libre-2.6.31-gnu/arch/mips/pci/fixup-tb0219.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/fixup-tb0219.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/fixup-tb0219.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
  *  fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups.
  *
  *  Copyright (C) 2003  Megasolution Inc. <matsu@megasolution.jp>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/fixup-tb0226.c linux-libre-2.6.31-gnu/arch/mips/pci/fixup-tb0226.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/fixup-tb0226.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/fixup-tb0226.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups.
  *
- *  Copyright (C) 2002-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/fixup-tb0287.c linux-libre-2.6.31-gnu/arch/mips/pci/fixup-tb0287.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/fixup-tb0287.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/fixup-tb0287.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/Makefile linux-libre-2.6.31-gnu/arch/mips/pci/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/pci/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -52,3 +52,8 @@
 obj-$(CONFIG_ZAO_CAPCELLA)	+= fixup-capcella.o
 obj-$(CONFIG_WR_PPMC)		+= fixup-wrppmc.o
 obj-$(CONFIG_MIKROTIK_RB532)	+= pci-rc32434.o ops-rc32434.o fixup-rc32434.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= pci-octeon.o pcie-octeon.o
+
+ifdef CONFIG_PCI_MSI
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= msi-octeon.o
+endif
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/msi-octeon.c linux-libre-2.6.31-gnu/arch/mips/pci/msi-octeon.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/msi-octeon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/pci/msi-octeon.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,288 @@
+/*
+ * 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) 2005-2009 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/msi.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
+#include <asm/octeon/cvmx-npei-defs.h>
+#include <asm/octeon/cvmx-pexp-defs.h>
+#include <asm/octeon/pci-octeon.h>
+
+/*
+ * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is
+ * in use.
+ */
+static uint64_t msi_free_irq_bitmask;
+
+/*
+ * Each bit in msi_multiple_irq_bitmask tells that the device using
+ * this bit in msi_free_irq_bitmask is also using the next bit. This
+ * is used so we can disable all of the MSI interrupts when a device
+ * uses multiple.
+ */
+static uint64_t msi_multiple_irq_bitmask;
+
+/*
+ * This lock controls updates to msi_free_irq_bitmask and
+ * msi_multiple_irq_bitmask.
+ */
+static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock);
+
+
+/**
+ * Called when a driver request MSI interrupts instead of the
+ * legacy INT A-D. This routine will allocate multiple interrupts
+ * for MSI devices that support them. A device can override this by
+ * programming the MSI control bits [6:4] before calling
+ * pci_enable_msi().
+ *
+ * @dev:    Device requesting MSI interrupts
+ * @desc:   MSI descriptor
+ *
+ * Returns 0 on success.
+ */
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+{
+	struct msi_msg msg;
+	uint16_t control;
+	int configured_private_bits;
+	int request_private_bits;
+	int irq;
+	int irq_step;
+	uint64_t search_mask;
+
+	/*
+	 * Read the MSI config to figure out how many IRQs this device
+	 * wants.  Most devices only want 1, which will give
+	 * configured_private_bits and request_private_bits equal 0.
+	 */
+	pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+			     &control);
+
+	/*
+	 * If the number of private bits has been configured then use
+	 * that value instead of the requested number. This gives the
+	 * driver the chance to override the number of interrupts
+	 * before calling pci_enable_msi().
+	 */
+	configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4;
+	if (configured_private_bits == 0) {
+		/* Nothing is configured, so use the hardware requested size */
+		request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1;
+	} else {
+		/*
+		 * Use the number of configured bits, assuming the
+		 * driver wanted to override the hardware request
+		 * value.
+		 */
+		request_private_bits = configured_private_bits;
+	}
+
+	/*
+	 * The PCI 2.3 spec mandates that there are at most 32
+	 * interrupts. If this device asks for more, only give it one.
+	 */
+	if (request_private_bits > 5)
+		request_private_bits = 0;
+
+try_only_one:
+	/*
+	 * The IRQs have to be aligned on a power of two based on the
+	 * number being requested.
+	 */
+	irq_step = 1 << request_private_bits;
+
+	/* Mask with one bit for each IRQ */
+	search_mask = (1 << irq_step) - 1;
+
+	/*
+	 * We're going to search msi_free_irq_bitmask_lock for zero
+	 * bits. This represents an MSI interrupt number that isn't in
+	 * use.
+	 */
+	spin_lock(&msi_free_irq_bitmask_lock);
+	for (irq = 0; irq < 64; irq += irq_step) {
+		if ((msi_free_irq_bitmask & (search_mask << irq)) == 0) {
+			msi_free_irq_bitmask |= search_mask << irq;
+			msi_multiple_irq_bitmask |= (search_mask >> 1) << irq;
+			break;
+		}
+	}
+	spin_unlock(&msi_free_irq_bitmask_lock);
+
+	/* Make sure the search for available interrupts didn't fail */
+	if (irq >= 64) {
+		if (request_private_bits) {
+			pr_err("arch_setup_msi_irq: Unable to find %d free "
+			       "interrupts, trying just one",
+			       1 << request_private_bits);
+			request_private_bits = 0;
+			goto try_only_one;
+		} else
+			panic("arch_setup_msi_irq: Unable to find a free MSI "
+			      "interrupt");
+	}
+
+	/* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */
+	irq += OCTEON_IRQ_MSI_BIT0;
+
+	switch (octeon_dma_bar_type) {
+	case OCTEON_DMA_BAR_TYPE_SMALL:
+		/* When not using big bar, Bar 0 is based at 128MB */
+		msg.address_lo =
+			((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff;
+		msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32;
+	case OCTEON_DMA_BAR_TYPE_BIG:
+		/* When using big bar, Bar 0 is based at 0 */
+		msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff;
+		msg.address_hi = (0 + CVMX_PCI_MSI_RCV) >> 32;
+		break;
+	case OCTEON_DMA_BAR_TYPE_PCIE:
+		/* When using PCIe, Bar 0 is based at 0 */
+		/* FIXME CVMX_NPEI_MSI_RCV* other than 0? */
+		msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff;
+		msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32;
+		break;
+	default:
+		panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type\n");
+	}
+	msg.data = irq - OCTEON_IRQ_MSI_BIT0;
+
+	/* Update the number of IRQs the device has available to it */
+	control &= ~PCI_MSI_FLAGS_QSIZE;
+	control |= request_private_bits << 4;
+	pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+			      control);
+
+	set_irq_msi(irq, desc);
+	write_msi_msg(irq, &msg);
+	return 0;
+}
+
+
+/**
+ * Called when a device no longer needs its MSI interrupts. All
+ * MSI interrupts for the device are freed.
+ *
+ * @irq:    The devices first irq number. There may be multple in sequence.
+ */
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	int number_irqs;
+	uint64_t bitmask;
+
+	if ((irq < OCTEON_IRQ_MSI_BIT0) || (irq > OCTEON_IRQ_MSI_BIT63))
+		panic("arch_teardown_msi_irq: Attempted to teardown illegal "
+		      "MSI interrupt (%d)", irq);
+	irq -= OCTEON_IRQ_MSI_BIT0;
+
+	/*
+	 * Count the number of IRQs we need to free by looking at the
+	 * msi_multiple_irq_bitmask. Each bit set means that the next
+	 * IRQ is also owned by this device.
+	 */
+	number_irqs = 0;
+	while ((irq+number_irqs < 64) &&
+	       (msi_multiple_irq_bitmask & (1ull << (irq + number_irqs))))
+		number_irqs++;
+	number_irqs++;
+	/* Mask with one bit for each IRQ */
+	bitmask = (1 << number_irqs) - 1;
+	/* Shift the mask to the correct bit location */
+	bitmask <<= irq;
+	if ((msi_free_irq_bitmask & bitmask) != bitmask)
+		panic("arch_teardown_msi_irq: Attempted to teardown MSI "
+		      "interrupt (%d) not in use", irq);
+
+	/* Checks are done, update the in use bitmask */
+	spin_lock(&msi_free_irq_bitmask_lock);
+	msi_free_irq_bitmask &= ~bitmask;
+	msi_multiple_irq_bitmask &= ~bitmask;
+	spin_unlock(&msi_free_irq_bitmask_lock);
+}
+
+
+/*
+ * Called by the interrupt handling code when an MSI interrupt
+ * occurs.
+ */
+static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id)
+{
+	uint64_t msi_bits;
+	int irq;
+
+	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE)
+		msi_bits = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_RCV0);
+	else
+		msi_bits = cvmx_read_csr(CVMX_NPI_NPI_MSI_RCV);
+	irq = fls64(msi_bits);
+	if (irq) {
+		irq += OCTEON_IRQ_MSI_BIT0 - 1;
+		if (irq_desc[irq].action) {
+			do_IRQ(irq);
+			return IRQ_HANDLED;
+		} else {
+			pr_err("Spurious MSI interrupt %d\n", irq);
+			if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+				/* These chips have PCIe */
+				cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0,
+					       1ull << (irq -
+							OCTEON_IRQ_MSI_BIT0));
+			} else {
+				/* These chips have PCI */
+				cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV,
+					       1ull << (irq -
+							OCTEON_IRQ_MSI_BIT0));
+			}
+		}
+	}
+	return IRQ_NONE;
+}
+
+
+/*
+ * Initializes the MSI interrupt handling code
+ */
+int octeon_msi_initialize(void)
+{
+	if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+		if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+				IRQF_SHARED,
+				"MSI[0:63]", octeon_msi_interrupt))
+			panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
+	} else if (octeon_is_pci_host()) {
+		if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+				IRQF_SHARED,
+				"MSI[0:15]", octeon_msi_interrupt))
+			panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
+
+		if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt,
+				IRQF_SHARED,
+				"MSI[16:31]", octeon_msi_interrupt))
+			panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed");
+
+		if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt,
+				IRQF_SHARED,
+				"MSI[32:47]", octeon_msi_interrupt))
+			panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed");
+
+		if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt,
+				IRQF_SHARED,
+				"MSI[48:63]", octeon_msi_interrupt))
+			panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed");
+
+	}
+	return 0;
+}
+
+subsys_initcall(octeon_msi_initialize);
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/ops-emma2rh.c linux-libre-2.6.31-gnu/arch/mips/pci/ops-emma2rh.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/ops-emma2rh.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/ops-emma2rh.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/pci/ops-emma2rh.c
- *      This file defines the PCI operation for EMMA2RH.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/pci/ops-vr41xx.c
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/ops-vr41xx.c linux-libre-2.6.31-gnu/arch/mips/pci/ops-vr41xx.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/ops-vr41xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/ops-vr41xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,8 @@
  *  ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series.
  *
  *  Copyright (C) 2001-2003 MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@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
@@ -21,7 +21,7 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  */
 #include <linux/pci.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-emma2rh.c linux-libre-2.6.31-gnu/arch/mips/pci/pci-emma2rh.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-emma2rh.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-emma2rh.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/pci/pci-emma2rh.c
- *      This file defines the PCI configration.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pcie-octeon.c linux-libre-2.6.31-gnu/arch/mips/pci/pcie-octeon.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pcie-octeon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pcie-octeon.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1372 @@
+/*
+ * 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, 2008 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npei-defs.h>
+#include <asm/octeon/cvmx-pciercx-defs.h>
+#include <asm/octeon/cvmx-pescx-defs.h>
+#include <asm/octeon/cvmx-pexp-defs.h>
+#include <asm/octeon/cvmx-helper-errata.h>
+#include <asm/octeon/pci-octeon.h>
+
+union cvmx_pcie_address {
+	uint64_t u64;
+	struct {
+		uint64_t upper:2;	/* Normally 2 for XKPHYS */
+		uint64_t reserved_49_61:13;	/* Must be zero */
+		uint64_t io:1;	/* 1 for IO space access */
+		uint64_t did:5;	/* PCIe DID = 3 */
+		uint64_t subdid:3;	/* PCIe SubDID = 1 */
+		uint64_t reserved_36_39:4;	/* Must be zero */
+		uint64_t es:2;	/* Endian swap = 1 */
+		uint64_t port:2;	/* PCIe port 0,1 */
+		uint64_t reserved_29_31:3;	/* Must be zero */
+		/*
+		 * Selects the type of the configuration request (0 = type 0,
+		 * 1 = type 1).
+		 */
+		uint64_t ty:1;
+		/* Target bus number sent in the ID in the request. */
+		uint64_t bus:8;
+		/*
+		 * Target device number sent in the ID in the
+		 * request. Note that Dev must be zero for type 0
+		 * configuration requests.
+		 */
+		uint64_t dev:5;
+		/* Target function number sent in the ID in the request. */
+		uint64_t func:3;
+		/*
+		 * Selects a register in the configuration space of
+		 * the target.
+		 */
+		uint64_t reg:12;
+	} config;
+	struct {
+		uint64_t upper:2;	/* Normally 2 for XKPHYS */
+		uint64_t reserved_49_61:13;	/* Must be zero */
+		uint64_t io:1;	/* 1 for IO space access */
+		uint64_t did:5;	/* PCIe DID = 3 */
+		uint64_t subdid:3;	/* PCIe SubDID = 2 */
+		uint64_t reserved_36_39:4;	/* Must be zero */
+		uint64_t es:2;	/* Endian swap = 1 */
+		uint64_t port:2;	/* PCIe port 0,1 */
+		uint64_t address:32;	/* PCIe IO address */
+	} io;
+	struct {
+		uint64_t upper:2;	/* Normally 2 for XKPHYS */
+		uint64_t reserved_49_61:13;	/* Must be zero */
+		uint64_t io:1;	/* 1 for IO space access */
+		uint64_t did:5;	/* PCIe DID = 3 */
+		uint64_t subdid:3;	/* PCIe SubDID = 3-6 */
+		uint64_t reserved_36_39:4;	/* Must be zero */
+		uint64_t address:36;	/* PCIe Mem address */
+	} mem;
+};
+
+/**
+ * Return the Core virtual base address for PCIe IO access. IOs are
+ * read/written as an offset from this address.
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns 64bit Octeon IO base address for read/write
+ */
+static inline uint64_t cvmx_pcie_get_io_base_address(int pcie_port)
+{
+	union cvmx_pcie_address pcie_addr;
+	pcie_addr.u64 = 0;
+	pcie_addr.io.upper = 0;
+	pcie_addr.io.io = 1;
+	pcie_addr.io.did = 3;
+	pcie_addr.io.subdid = 2;
+	pcie_addr.io.es = 1;
+	pcie_addr.io.port = pcie_port;
+	return pcie_addr.u64;
+}
+
+/**
+ * Size of the IO address region returned at address
+ * cvmx_pcie_get_io_base_address()
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns Size of the IO window
+ */
+static inline uint64_t cvmx_pcie_get_io_size(int pcie_port)
+{
+	return 1ull << 32;
+}
+
+/**
+ * Return the Core virtual base address for PCIe MEM access. Memory is
+ * read/written as an offset from this address.
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns 64bit Octeon IO base address for read/write
+ */
+static inline uint64_t cvmx_pcie_get_mem_base_address(int pcie_port)
+{
+	union cvmx_pcie_address pcie_addr;
+	pcie_addr.u64 = 0;
+	pcie_addr.mem.upper = 0;
+	pcie_addr.mem.io = 1;
+	pcie_addr.mem.did = 3;
+	pcie_addr.mem.subdid = 3 + pcie_port;
+	return pcie_addr.u64;
+}
+
+/**
+ * Size of the Mem address region returned at address
+ * cvmx_pcie_get_mem_base_address()
+ *
+ * @pcie_port: PCIe port the IO is for
+ *
+ * Returns Size of the Mem window
+ */
+static inline uint64_t cvmx_pcie_get_mem_size(int pcie_port)
+{
+	return 1ull << 36;
+}
+
+/**
+ * Read a PCIe config space register indirectly. This is used for
+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???.
+ *
+ * @pcie_port:  PCIe port to read from
+ * @cfg_offset: Address to read
+ *
+ * Returns Value read
+ */
+static uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset)
+{
+	union cvmx_pescx_cfg_rd pescx_cfg_rd;
+	pescx_cfg_rd.u64 = 0;
+	pescx_cfg_rd.s.addr = cfg_offset;
+	cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64);
+	pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port));
+	return pescx_cfg_rd.s.data;
+}
+
+/**
+ * Write a PCIe config space register indirectly. This is used for
+ * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???.
+ *
+ * @pcie_port:  PCIe port to write to
+ * @cfg_offset: Address to write
+ * @val:        Value to write
+ */
+static void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset,
+				 uint32_t val)
+{
+	union cvmx_pescx_cfg_wr pescx_cfg_wr;
+	pescx_cfg_wr.u64 = 0;
+	pescx_cfg_wr.s.addr = cfg_offset;
+	pescx_cfg_wr.s.data = val;
+	cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64);
+}
+
+/**
+ * Build a PCIe config space request address for a device
+ *
+ * @pcie_port: PCIe port to access
+ * @bus:       Sub bus
+ * @dev:       Device ID
+ * @fn:        Device sub function
+ * @reg:       Register to access
+ *
+ * Returns 64bit Octeon IO address
+ */
+static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus,
+						     int dev, int fn, int reg)
+{
+	union cvmx_pcie_address pcie_addr;
+	union cvmx_pciercx_cfg006 pciercx_cfg006;
+
+	pciercx_cfg006.u32 =
+	    cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port));
+	if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0))
+		return 0;
+
+	pcie_addr.u64 = 0;
+	pcie_addr.config.upper = 2;
+	pcie_addr.config.io = 1;
+	pcie_addr.config.did = 3;
+	pcie_addr.config.subdid = 1;
+	pcie_addr.config.es = 1;
+	pcie_addr.config.port = pcie_port;
+	pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum);
+	pcie_addr.config.bus = bus;
+	pcie_addr.config.dev = dev;
+	pcie_addr.config.func = fn;
+	pcie_addr.config.reg = reg;
+	return pcie_addr.u64;
+}
+
+/**
+ * Read 8bits from a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus:       Sub bus
+ * @dev:       Device ID
+ * @fn:        Device sub function
+ * @reg:       Register to access
+ *
+ * Returns Result of the read
+ */
+static uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev,
+				      int fn, int reg)
+{
+	uint64_t address =
+	    __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+	if (address)
+		return cvmx_read64_uint8(address);
+	else
+		return 0xff;
+}
+
+/**
+ * Read 16bits from a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus:       Sub bus
+ * @dev:       Device ID
+ * @fn:        Device sub function
+ * @reg:       Register to access
+ *
+ * Returns Result of the read
+ */
+static uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev,
+					int fn, int reg)
+{
+	uint64_t address =
+	    __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+	if (address)
+		return le16_to_cpu(cvmx_read64_uint16(address));
+	else
+		return 0xffff;
+}
+
+/**
+ * Read 32bits from a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus:       Sub bus
+ * @dev:       Device ID
+ * @fn:        Device sub function
+ * @reg:       Register to access
+ *
+ * Returns Result of the read
+ */
+static uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev,
+					int fn, int reg)
+{
+	uint64_t address =
+	    __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+	if (address)
+		return le32_to_cpu(cvmx_read64_uint32(address));
+	else
+		return 0xffffffff;
+}
+
+/**
+ * Write 8bits to a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus:       Sub bus
+ * @dev:       Device ID
+ * @fn:        Device sub function
+ * @reg:       Register to access
+ * @val:       Value to write
+ */
+static void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn,
+				    int reg, uint8_t val)
+{
+	uint64_t address =
+	    __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+	if (address)
+		cvmx_write64_uint8(address, val);
+}
+
+/**
+ * Write 16bits to a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus:       Sub bus
+ * @dev:       Device ID
+ * @fn:        Device sub function
+ * @reg:       Register to access
+ * @val:       Value to write
+ */
+static void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn,
+				     int reg, uint16_t val)
+{
+	uint64_t address =
+	    __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+	if (address)
+		cvmx_write64_uint16(address, cpu_to_le16(val));
+}
+
+/**
+ * Write 32bits to a Device's config space
+ *
+ * @pcie_port: PCIe port the device is on
+ * @bus:       Sub bus
+ * @dev:       Device ID
+ * @fn:        Device sub function
+ * @reg:       Register to access
+ * @val:       Value to write
+ */
+static void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn,
+				     int reg, uint32_t val)
+{
+	uint64_t address =
+	    __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg);
+	if (address)
+		cvmx_write64_uint32(address, cpu_to_le32(val));
+}
+
+/**
+ * Initialize the RC config space CSRs
+ *
+ * @pcie_port: PCIe port to initialize
+ */
+static void __cvmx_pcie_rc_initialize_config_space(int pcie_port)
+{
+	union cvmx_pciercx_cfg030 pciercx_cfg030;
+	union cvmx_npei_ctl_status2 npei_ctl_status2;
+	union cvmx_pciercx_cfg070 pciercx_cfg070;
+	union cvmx_pciercx_cfg001 pciercx_cfg001;
+	union cvmx_pciercx_cfg032 pciercx_cfg032;
+	union cvmx_pciercx_cfg006 pciercx_cfg006;
+	union cvmx_pciercx_cfg008 pciercx_cfg008;
+	union cvmx_pciercx_cfg009 pciercx_cfg009;
+	union cvmx_pciercx_cfg010 pciercx_cfg010;
+	union cvmx_pciercx_cfg011 pciercx_cfg011;
+	union cvmx_pciercx_cfg035 pciercx_cfg035;
+	union cvmx_pciercx_cfg075 pciercx_cfg075;
+	union cvmx_pciercx_cfg034 pciercx_cfg034;
+
+	/* Max Payload Size (PCIE*_CFG030[MPS]) */
+	/* Max Read Request Size (PCIE*_CFG030[MRRS]) */
+	/* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */
+	/* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */
+	pciercx_cfg030.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port));
+	/*
+	 * Max payload size = 128 bytes for best Octeon DMA
+	 * performance.
+	 */
+	pciercx_cfg030.s.mps = 0;
+	/*
+	 * Max read request size = 128 bytes for best Octeon DMA
+	 * performance.
+	 */
+	pciercx_cfg030.s.mrrs = 0;
+	/* Enable relaxed ordering. */
+	pciercx_cfg030.s.ro_en = 1;
+	/* Enable no snoop. */
+	pciercx_cfg030.s.ns_en = 1;
+	/* Correctable error reporting enable. */
+	pciercx_cfg030.s.ce_en = 1;
+	/* Non-fatal error reporting enable. */
+	pciercx_cfg030.s.nfe_en = 1;
+	/* Fatal error reporting enable. */
+	pciercx_cfg030.s.fe_en = 1;
+	/* Unsupported request reporting enable. */
+	pciercx_cfg030.s.ur_en = 1;
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port),
+			     pciercx_cfg030.u32);
+
+	/*
+	 * Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match
+	 * PCIE*_CFG030[MPS]
+	 *
+	 * Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not
+	 * exceed PCIE*_CFG030[MRRS].
+	 */
+	npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2);
+	/* Max payload size = 128 bytes for best Octeon DMA performance */
+	npei_ctl_status2.s.mps = 0;
+	/* Max read request size = 128 bytes for best Octeon DMA performance */
+	npei_ctl_status2.s.mrrs = 0;
+	cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64);
+
+	/* ECRC Generation (PCIE*_CFG070[GE,CE]) */
+	pciercx_cfg070.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port));
+	pciercx_cfg070.s.ge = 1;	/* ECRC generation enable. */
+	pciercx_cfg070.s.ce = 1;	/* ECRC check enable. */
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port),
+			     pciercx_cfg070.u32);
+
+	/*
+	 * Access Enables (PCIE*_CFG001[MSAE,ME]) ME and MSAE should
+	 * always be set.
+	 *
+	 * Interrupt Disable (PCIE*_CFG001[I_DIS]) System Error
+	 * Message Enable (PCIE*_CFG001[SEE])
+	 */
+	pciercx_cfg001.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port));
+	pciercx_cfg001.s.msae = 1;	/* Memory space enable. */
+	pciercx_cfg001.s.me = 1;	/* Bus master enable. */
+	pciercx_cfg001.s.i_dis = 1;	/* INTx assertion disable. */
+	pciercx_cfg001.s.see = 1;	/* SERR# enable */
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port),
+			pciercx_cfg001.u32);
+
+	/* Advanced Error Recovery Message Enables */
+	/* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0);
+	/* Use CVMX_PCIERCX_CFG067 hardware default */
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0);
+
+	/* Active State Power Management (PCIE*_CFG032[ASLPC]) */
+	pciercx_cfg032.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port));
+	pciercx_cfg032.s.aslpc = 0;	/* Active state Link PM control. */
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port),
+			     pciercx_cfg032.u32);
+
+	/* Entrance Latencies (PCIE*_CFG451[L0EL,L1EL]) */
+
+	/*
+	 * Link Width Mode (PCIERCn_CFG452[LME]) - Set during
+	 * cvmx_pcie_rc_initialize_link()
+	 *
+	 * Primary Bus Number (PCIERCn_CFG006[PBNUM])
+	 *
+	 * We set the primary bus number to 1 so IDT bridges are
+	 * happy. They don't like zero.
+	 */
+	pciercx_cfg006.u32 = 0;
+	pciercx_cfg006.s.pbnum = 1;
+	pciercx_cfg006.s.sbnum = 1;
+	pciercx_cfg006.s.subbnum = 1;
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port),
+			     pciercx_cfg006.u32);
+
+	/*
+	 * Memory-mapped I/O BAR (PCIERCn_CFG008)
+	 * Most applications should disable the memory-mapped I/O BAR by
+	 * setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR]
+	 */
+	pciercx_cfg008.u32 = 0;
+	pciercx_cfg008.s.mb_addr = 0x100;
+	pciercx_cfg008.s.ml_addr = 0;
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port),
+			     pciercx_cfg008.u32);
+
+	/*
+	 * Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011)
+	 * Most applications should disable the prefetchable BAR by setting
+	 * PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] <
+	 * PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE]
+	 */
+	pciercx_cfg009.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port));
+	pciercx_cfg010.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port));
+	pciercx_cfg011.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port));
+	pciercx_cfg009.s.lmem_base = 0x100;
+	pciercx_cfg009.s.lmem_limit = 0;
+	pciercx_cfg010.s.umem_base = 0x100;
+	pciercx_cfg011.s.umem_limit = 0;
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port),
+			     pciercx_cfg009.u32);
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port),
+			     pciercx_cfg010.u32);
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port),
+			     pciercx_cfg011.u32);
+
+	/*
+	 * System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE])
+	 * PME Interrupt Enables (PCIERCn_CFG035[PMEIE])
+	 */
+	pciercx_cfg035.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port));
+	/* System error on correctable error enable. */
+	pciercx_cfg035.s.secee = 1;
+	/* System error on fatal error enable. */
+	pciercx_cfg035.s.sefee = 1;
+	/* System error on non-fatal error enable. */
+	pciercx_cfg035.s.senfee = 1;
+	/* PME interrupt enable. */
+	pciercx_cfg035.s.pmeie = 1;
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port),
+			     pciercx_cfg035.u32);
+
+	/*
+	 * Advanced Error Recovery Interrupt Enables
+	 * (PCIERCn_CFG075[CERE,NFERE,FERE])
+	 */
+	pciercx_cfg075.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port));
+	/* Correctable error reporting enable. */
+	pciercx_cfg075.s.cere = 1;
+	/* Non-fatal error reporting enable. */
+	pciercx_cfg075.s.nfere = 1;
+	/* Fatal error reporting enable. */
+	pciercx_cfg075.s.fere = 1;
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port),
+			     pciercx_cfg075.u32);
+
+	/* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN],
+	 * PCIERCn_CFG034[DLLS_EN,CCINT_EN])
+	 */
+	pciercx_cfg034.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port));
+	/* Hot-plug interrupt enable. */
+	pciercx_cfg034.s.hpint_en = 1;
+	/* Data Link Layer state changed enable */
+	pciercx_cfg034.s.dlls_en = 1;
+	/* Command completed interrupt enable. */
+	pciercx_cfg034.s.ccint_en = 1;
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port),
+			     pciercx_cfg034.u32);
+}
+
+/**
+ * Initialize a host mode PCIe link. This function takes a PCIe
+ * port from reset to a link up state. Software can then begin
+ * configuring the rest of the link.
+ *
+ * @pcie_port: PCIe port to initialize
+ *
+ * Returns Zero on success
+ */
+static int __cvmx_pcie_rc_initialize_link(int pcie_port)
+{
+	uint64_t start_cycle;
+	union cvmx_pescx_ctl_status pescx_ctl_status;
+	union cvmx_pciercx_cfg452 pciercx_cfg452;
+	union cvmx_pciercx_cfg032 pciercx_cfg032;
+	union cvmx_pciercx_cfg448 pciercx_cfg448;
+
+	/* Set the lane width */
+	pciercx_cfg452.u32 =
+	    cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port));
+	pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port));
+	if (pescx_ctl_status.s.qlm_cfg == 0) {
+		/* We're in 8 lane (56XX) or 4 lane (54XX) mode */
+		pciercx_cfg452.s.lme = 0xf;
+	} else {
+		/* We're in 4 lane (56XX) or 2 lane (52XX) mode */
+		pciercx_cfg452.s.lme = 0x7;
+	}
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port),
+			     pciercx_cfg452.u32);
+
+	/*
+	 * CN52XX pass 1.x has an errata where length mismatches on UR
+	 * responses can cause bus errors on 64bit memory
+	 * reads. Turning off length error checking fixes this.
+	 */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+		union cvmx_pciercx_cfg455 pciercx_cfg455;
+		pciercx_cfg455.u32 =
+		    cvmx_pcie_cfgx_read(pcie_port,
+					CVMX_PCIERCX_CFG455(pcie_port));
+		pciercx_cfg455.s.m_cpl_len_err = 1;
+		cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port),
+				     pciercx_cfg455.u32);
+	}
+
+	/* Lane swap needs to be manually enabled for CN52XX */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) {
+		pescx_ctl_status.s.lane_swp = 1;
+		cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port),
+			       pescx_ctl_status.u64);
+	}
+
+	/* Bring up the link */
+	pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port));
+	pescx_ctl_status.s.lnk_enb = 1;
+	cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64);
+
+	/*
+	 * CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to
+	 * be disabled.
+	 */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
+		__cvmx_helper_errata_qlm_disable_2nd_order_cdr(0);
+
+	/* Wait for the link to come up */
+	cvmx_dprintf("PCIe: Waiting for port %d link\n", pcie_port);
+	start_cycle = cvmx_get_cycle();
+	do {
+		if (cvmx_get_cycle() - start_cycle >
+		    2 * cvmx_sysinfo_get()->cpu_clock_hz) {
+			cvmx_dprintf("PCIe: Port %d link timeout\n",
+				     pcie_port);
+			return -1;
+		}
+		cvmx_wait(10000);
+		pciercx_cfg032.u32 =
+		    cvmx_pcie_cfgx_read(pcie_port,
+					CVMX_PCIERCX_CFG032(pcie_port));
+	} while (pciercx_cfg032.s.dlla == 0);
+
+	/* Display the link status */
+	cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port,
+		     pciercx_cfg032.s.nlw);
+
+	/*
+	 * Update the Replay Time Limit. Empirically, some PCIe
+	 * devices take a little longer to respond than expected under
+	 * load. As a workaround for this we configure the Replay Time
+	 * Limit to the value expected for a 512 byte MPS instead of
+	 * our actual 256 byte MPS. The numbers below are directly
+	 * from the PCIe spec table 3-4.
+	 */
+	pciercx_cfg448.u32 =
+	    cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port));
+	switch (pciercx_cfg032.s.nlw) {
+	case 1:		/* 1 lane */
+		pciercx_cfg448.s.rtl = 1677;
+		break;
+	case 2:		/* 2 lanes */
+		pciercx_cfg448.s.rtl = 867;
+		break;
+	case 4:		/* 4 lanes */
+		pciercx_cfg448.s.rtl = 462;
+		break;
+	case 8:		/* 8 lanes */
+		pciercx_cfg448.s.rtl = 258;
+		break;
+	}
+	cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port),
+			     pciercx_cfg448.u32);
+
+	return 0;
+}
+
+/**
+ * Initialize a PCIe port for use in host(RC) mode. It doesn't
+ * enumerate the bus.
+ *
+ * @pcie_port: PCIe port to initialize
+ *
+ * Returns Zero on success
+ */
+static int cvmx_pcie_rc_initialize(int pcie_port)
+{
+	int i;
+	union cvmx_ciu_soft_prst ciu_soft_prst;
+	union cvmx_pescx_bist_status pescx_bist_status;
+	union cvmx_pescx_bist_status2 pescx_bist_status2;
+	union cvmx_npei_ctl_status npei_ctl_status;
+	union cvmx_npei_mem_access_ctl npei_mem_access_ctl;
+	union cvmx_npei_mem_access_subidx mem_access_subid;
+	union cvmx_npei_dbg_data npei_dbg_data;
+	union cvmx_pescx_ctl_status2 pescx_ctl_status2;
+
+	/*
+	 * Make sure we aren't trying to setup a target mode interface
+	 * in host mode.
+	 */
+	npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS);
+	if ((pcie_port == 0) && !npei_ctl_status.s.host_mode) {
+		cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called "
+			     "on port0, but port0 is not in host mode\n");
+		return -1;
+	}
+
+	/*
+	 * Make sure a CN52XX isn't trying to bring up port 1 when it
+	 * is disabled.
+	 */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
+		npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
+		if ((pcie_port == 1) && npei_dbg_data.cn52xx.qlm0_link_width) {
+			cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() "
+				     "called on port1, but port1 is "
+				     "disabled\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * PCIe switch arbitration mode. '0' == fixed priority NPEI,
+	 * PCIe0, then PCIe1. '1' == round robin.
+	 */
+	npei_ctl_status.s.arb = 1;
+	/* Allow up to 0x20 config retries */
+	npei_ctl_status.s.cfg_rtry = 0x20;
+	/*
+	 * CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS
+	 * don't reset.
+	 */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+		npei_ctl_status.s.p0_ntags = 0x20;
+		npei_ctl_status.s.p1_ntags = 0x20;
+	}
+	cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64);
+
+	/* Bring the PCIe out of reset */
+	if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) {
+		/*
+		 * The EBH5200 board swapped the PCIe reset lines on
+		 * the board. As a workaround for this bug, we bring
+		 * both PCIe ports out of reset at the same time
+		 * instead of on separate calls. So for port 0, we
+		 * bring both out of reset and do nothing on port 1.
+		 */
+		if (pcie_port == 0) {
+			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+			/*
+			 * After a chip reset the PCIe will also be in
+			 * reset. If it isn't, most likely someone is
+			 * trying to init it again without a proper
+			 * PCIe reset.
+			 */
+			if (ciu_soft_prst.s.soft_prst == 0) {
+				/* Reset the ports */
+				ciu_soft_prst.s.soft_prst = 1;
+				cvmx_write_csr(CVMX_CIU_SOFT_PRST,
+					       ciu_soft_prst.u64);
+				ciu_soft_prst.u64 =
+				    cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+				ciu_soft_prst.s.soft_prst = 1;
+				cvmx_write_csr(CVMX_CIU_SOFT_PRST1,
+					       ciu_soft_prst.u64);
+				/* Wait until pcie resets the ports. */
+				udelay(2000);
+			}
+			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+			ciu_soft_prst.s.soft_prst = 0;
+			cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
+			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+			ciu_soft_prst.s.soft_prst = 0;
+			cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
+		}
+	} else {
+		/*
+		 * The normal case: The PCIe ports are completely
+		 * separate and can be brought out of reset
+		 * independently.
+		 */
+		if (pcie_port)
+			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+		else
+			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+		/*
+		 * After a chip reset the PCIe will also be in
+		 * reset. If it isn't, most likely someone is trying
+		 * to init it again without a proper PCIe reset.
+		 */
+		if (ciu_soft_prst.s.soft_prst == 0) {
+			/* Reset the port */
+			ciu_soft_prst.s.soft_prst = 1;
+			if (pcie_port)
+				cvmx_write_csr(CVMX_CIU_SOFT_PRST1,
+					       ciu_soft_prst.u64);
+			else
+				cvmx_write_csr(CVMX_CIU_SOFT_PRST,
+					       ciu_soft_prst.u64);
+			/* Wait until pcie resets the ports. */
+			udelay(2000);
+		}
+		if (pcie_port) {
+			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1);
+			ciu_soft_prst.s.soft_prst = 0;
+			cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64);
+		} else {
+			ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+			ciu_soft_prst.s.soft_prst = 0;
+			cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64);
+		}
+	}
+
+	/*
+	 * Wait for PCIe reset to complete. Due to errata PCIE-700, we
+	 * don't poll PESCX_CTL_STATUS2[PCIERST], but simply wait a
+	 * fixed number of cycles.
+	 */
+	cvmx_wait(400000);
+
+	/* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and
+	   CN52XX, so we only probe it on newer chips */
+	if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
+	    && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+		/* Clear PCLK_RUN so we can check if the clock is running */
+		pescx_ctl_status2.u64 =
+		    cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port));
+		pescx_ctl_status2.s.pclk_run = 1;
+		cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port),
+			       pescx_ctl_status2.u64);
+		/*
+		 * Now that we cleared PCLK_RUN, wait for it to be set
+		 * again telling us the clock is running.
+		 */
+		if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port),
+					  union cvmx_pescx_ctl_status2,
+					  pclk_run, ==, 1, 10000)) {
+			cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n",
+				     pcie_port);
+			return -1;
+		}
+	}
+
+	/*
+	 * Check and make sure PCIe came out of reset. If it doesn't
+	 * the board probably hasn't wired the clocks up and the
+	 * interface should be skipped.
+	 */
+	pescx_ctl_status2.u64 =
+	    cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port));
+	if (pescx_ctl_status2.s.pcierst) {
+		cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n",
+			     pcie_port);
+		return -1;
+	}
+
+	/*
+	 * Check BIST2 status. If any bits are set skip this interface. This
+	 * is an attempt to catch PCIE-813 on pass 1 parts.
+	 */
+	pescx_bist_status2.u64 =
+	    cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port));
+	if (pescx_bist_status2.u64) {
+		cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this "
+			     "port isn't hooked up, skipping.\n",
+			     pcie_port);
+		return -1;
+	}
+
+	/* Check BIST status */
+	pescx_bist_status.u64 =
+	    cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port));
+	if (pescx_bist_status.u64)
+		cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n",
+			     pcie_port, CAST64(pescx_bist_status.u64));
+
+	/* Initialize the config space CSRs */
+	__cvmx_pcie_rc_initialize_config_space(pcie_port);
+
+	/* Bring the link up */
+	if (__cvmx_pcie_rc_initialize_link(pcie_port)) {
+		cvmx_dprintf
+		    ("PCIe: ERROR: cvmx_pcie_rc_initialize_link() failed\n");
+		return -1;
+	}
+
+	/* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */
+	npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL);
+	/* Allow 16 words to combine */
+	npei_mem_access_ctl.s.max_word = 0;
+	/* Wait up to 127 cycles for more data */
+	npei_mem_access_ctl.s.timer = 127;
+	cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64);
+
+	/* Setup Mem access SubDIDs */
+	mem_access_subid.u64 = 0;
+	/* Port the request is sent to. */
+	mem_access_subid.s.port = pcie_port;
+	/* Due to an errata on pass 1 chips, no merging is allowed. */
+	mem_access_subid.s.nmerge = 1;
+	/* Endian-swap for Reads. */
+	mem_access_subid.s.esr = 1;
+	/* Endian-swap for Writes. */
+	mem_access_subid.s.esw = 1;
+	/* No Snoop for Reads. */
+	mem_access_subid.s.nsr = 1;
+	/* No Snoop for Writes. */
+	mem_access_subid.s.nsw = 1;
+	/* Disable Relaxed Ordering for Reads. */
+	mem_access_subid.s.ror = 0;
+	/* Disable Relaxed Ordering for Writes. */
+	mem_access_subid.s.row = 0;
+	/* PCIe Adddress Bits <63:34>. */
+	mem_access_subid.s.ba = 0;
+
+	/*
+	 * Setup mem access 12-15 for port 0, 16-19 for port 1,
+	 * supplying 36 bits of address space.
+	 */
+	for (i = 12 + pcie_port * 4; i < 16 + pcie_port * 4; i++) {
+		cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i),
+			       mem_access_subid.u64);
+		/* Set each SUBID to extend the addressable range */
+		mem_access_subid.s.ba += 1;
+	}
+
+	/*
+	 * Disable the peer to peer forwarding register. This must be
+	 * setup by the OS after it enumerates the bus and assigns
+	 * addresses to the PCIe busses.
+	 */
+	for (i = 0; i < 4; i++) {
+		cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1);
+		cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1);
+	}
+
+	/* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */
+	cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0);
+
+	/*
+	 * Disable Octeon's BAR1. It isn't needed in RC mode since
+	 * BAR2 maps all of memory. BAR2 also maps 256MB-512MB into
+	 * the 2nd 256MB of memory.
+	 */
+	cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), -1);
+
+	/*
+	 * Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take
+	 * precedence where they overlap. It also overlaps with the
+	 * device addresses, so make sure the peer to peer forwarding
+	 * is set right.
+	 */
+	cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0);
+
+	/*
+	 * Setup BAR2 attributes
+	 *
+	 * Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM])
+	 * - PTLP_RO,CTLP_RO should normally be set (except for debug).
+	 * - WAIT_COM=0 will likely work for all applications.
+	 *
+	 * Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]).
+	 */
+	if (pcie_port) {
+		union cvmx_npei_ctl_port1 npei_ctl_port;
+		npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1);
+		npei_ctl_port.s.bar2_enb = 1;
+		npei_ctl_port.s.bar2_esx = 1;
+		npei_ctl_port.s.bar2_cax = 0;
+		npei_ctl_port.s.ptlp_ro = 1;
+		npei_ctl_port.s.ctlp_ro = 1;
+		npei_ctl_port.s.wait_com = 0;
+		npei_ctl_port.s.waitl_com = 0;
+		cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64);
+	} else {
+		union cvmx_npei_ctl_port0 npei_ctl_port;
+		npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0);
+		npei_ctl_port.s.bar2_enb = 1;
+		npei_ctl_port.s.bar2_esx = 1;
+		npei_ctl_port.s.bar2_cax = 0;
+		npei_ctl_port.s.ptlp_ro = 1;
+		npei_ctl_port.s.ctlp_ro = 1;
+		npei_ctl_port.s.wait_com = 0;
+		npei_ctl_port.s.waitl_com = 0;
+		cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64);
+	}
+	return 0;
+}
+
+
+/* Above was cvmx-pcie.c, below original pcie.c */
+
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @dev:    The Linux PCI device structure for the device to map
+ * @slot:   The slot number for this device on __BUS 0__. Linux
+ *               enumerates through all the bridges and figures out the
+ *               slot on Bus 0 where this device eventually hooks to.
+ * @pin:    The PCI interrupt pin read from the device, then swizzled
+ *               as it goes through each bridge.
+ * Returns Interrupt number for the device
+ */
+int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
+				       u8 slot, u8 pin)
+{
+	/*
+	 * The EBH5600 board with the PCI to PCIe bridge mistakenly
+	 * wires the first slot for both device id 2 and interrupt
+	 * A. According to the PCI spec, device id 2 should be C. The
+	 * following kludge attempts to fix this.
+	 */
+	if (strstr(octeon_board_type_string(), "EBH5600") &&
+	    dev->bus && dev->bus->parent) {
+		/*
+		 * Iterate all the way up the device chain and find
+		 * the root bus.
+		 */
+		while (dev->bus && dev->bus->parent)
+			dev = to_pci_dev(dev->bus->bridge);
+		/* If the root bus is number 0 and the PEX 8114 is the
+		 * root, assume we are behind the miswired bus. We
+		 * need to correct the swizzle level by two. Yuck.
+		 */
+		if ((dev->bus->number == 0) &&
+		    (dev->vendor == 0x10b5) && (dev->device == 0x8114)) {
+			/*
+			 * The pin field is one based, not zero. We
+			 * need to swizzle it by minus two.
+			 */
+			pin = ((pin - 3) & 3) + 1;
+		}
+	}
+	/*
+	 * The -1 is because pin starts with one, not zero. It might
+	 * be that this equation needs to include the slot number, but
+	 * I don't have hardware to check that against.
+	 */
+	return pin - 1 + OCTEON_IRQ_PCI_INT0;
+}
+
+/**
+ * Read a value from configuration space
+ *
+ * @bus:
+ * @devfn:
+ * @reg:
+ * @size:
+ * @val:
+ * Returns
+ */
+static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus,
+					  unsigned int devfn, int reg, int size,
+					  u32 *val)
+{
+	union octeon_cvmemctl cvmmemctl;
+	union octeon_cvmemctl cvmmemctl_save;
+	int bus_number = bus->number;
+
+	/*
+	 * For the top level bus make sure our hardware bus number
+	 * matches the software one.
+	 */
+	if (bus->parent == NULL) {
+		union cvmx_pciercx_cfg006 pciercx_cfg006;
+		pciercx_cfg006.u32 = cvmx_pcie_cfgx_read(pcie_port,
+			CVMX_PCIERCX_CFG006(pcie_port));
+		if (pciercx_cfg006.s.pbnum != bus_number) {
+			pciercx_cfg006.s.pbnum = bus_number;
+			pciercx_cfg006.s.sbnum = bus_number;
+			pciercx_cfg006.s.subbnum = bus_number;
+			cvmx_pcie_cfgx_write(pcie_port,
+				CVMX_PCIERCX_CFG006(pcie_port),
+				pciercx_cfg006.u32);
+		}
+	}
+
+	/*
+	 * PCIe only has a single device connected to Octeon. It is
+	 * always device ID 0. Don't bother doing reads for other
+	 * device IDs on the first segment.
+	 */
+	if ((bus->parent == NULL) && (devfn >> 3 != 0))
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	/*
+	 * The following is a workaround for the CN57XX, CN56XX,
+	 * CN55XX, and CN54XX errata with PCIe config reads from non
+	 * existent devices.  These chips will hang the PCIe link if a
+	 * config read is performed that causes a UR response.
+	 */
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) ||
+	    OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1)) {
+		/*
+		 * For our EBH5600 board, port 0 has a bridge with two
+		 * PCI-X slots. We need a new special checks to make
+		 * sure we only probe valid stuff.  The PCIe->PCI-X
+		 * bridge only respondes to device ID 0, function
+		 * 0-1
+		 */
+		if ((bus->parent == NULL) && (devfn >= 2))
+			return PCIBIOS_FUNC_NOT_SUPPORTED;
+		/*
+		 * The PCI-X slots are device ID 2,3. Choose one of
+		 * the below "if" blocks based on what is plugged into
+		 * the board.
+		 */
+#if 1
+		/* Use this option if you aren't using either slot */
+		if (bus_number == 1)
+			return PCIBIOS_FUNC_NOT_SUPPORTED;
+#elif 0
+		/*
+		 * Use this option if you are using the first slot but
+		 * not the second.
+		 */
+		if ((bus_number == 1) && (devfn >> 3 != 2))
+			return PCIBIOS_FUNC_NOT_SUPPORTED;
+#elif 0
+		/*
+		 * Use this option if you are using the second slot
+		 * but not the first.
+		 */
+		if ((bus_number == 1) && (devfn >> 3 != 3))
+			return PCIBIOS_FUNC_NOT_SUPPORTED;
+#elif 0
+		/* Use this opion if you are using both slots */
+		if ((bus_number == 1) &&
+		    !((devfn == (2 << 3)) || (devfn == (3 << 3))))
+			return PCIBIOS_FUNC_NOT_SUPPORTED;
+#endif
+
+		/*
+		 * Shorten the DID timeout so bus errors for PCIe
+		 * config reads from non existent devices happen
+		 * faster. This allows us to continue booting even if
+		 * the above "if" checks are wrong.  Once one of these
+		 * errors happens, the PCIe port is dead.
+		 */
+		cvmmemctl_save.u64 = __read_64bit_c0_register($11, 7);
+		cvmmemctl.u64 = cvmmemctl_save.u64;
+		cvmmemctl.s.didtto = 2;
+		__write_64bit_c0_register($11, 7, cvmmemctl.u64);
+	}
+
+	switch (size) {
+	case 4:
+		*val = cvmx_pcie_config_read32(pcie_port, bus_number,
+					       devfn >> 3, devfn & 0x7, reg);
+		break;
+	case 2:
+		*val = cvmx_pcie_config_read16(pcie_port, bus_number,
+					       devfn >> 3, devfn & 0x7, reg);
+		break;
+	case 1:
+		*val = cvmx_pcie_config_read8(pcie_port, bus_number, devfn >> 3,
+					      devfn & 0x7, reg);
+		break;
+	default:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1) ||
+	    OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_1))
+		__write_64bit_c0_register($11, 7, cvmmemctl_save.u64);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int octeon_pcie0_read_config(struct pci_bus *bus, unsigned int devfn,
+				    int reg, int size, u32 *val)
+{
+	return octeon_pcie_read_config(0, bus, devfn, reg, size, val);
+}
+
+static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn,
+				    int reg, int size, u32 *val)
+{
+	return octeon_pcie_read_config(1, bus, devfn, reg, size, val);
+}
+
+
+
+/**
+ * Write a value to PCI configuration space
+ *
+ * @bus:
+ * @devfn:
+ * @reg:
+ * @size:
+ * @val:
+ * Returns
+ */
+static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus,
+					   unsigned int devfn, int reg,
+					   int size, u32 val)
+{
+	int bus_number = bus->number;
+
+	switch (size) {
+	case 4:
+		cvmx_pcie_config_write32(pcie_port, bus_number, devfn >> 3,
+					 devfn & 0x7, reg, val);
+		return PCIBIOS_SUCCESSFUL;
+	case 2:
+		cvmx_pcie_config_write16(pcie_port, bus_number, devfn >> 3,
+					 devfn & 0x7, reg, val);
+		return PCIBIOS_SUCCESSFUL;
+	case 1:
+		cvmx_pcie_config_write8(pcie_port, bus_number, devfn >> 3,
+					devfn & 0x7, reg, val);
+		return PCIBIOS_SUCCESSFUL;
+	}
+#if PCI_CONFIG_SPACE_DELAY
+	udelay(PCI_CONFIG_SPACE_DELAY);
+#endif
+	return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+static int octeon_pcie0_write_config(struct pci_bus *bus, unsigned int devfn,
+				     int reg, int size, u32 val)
+{
+	return octeon_pcie_write_config(0, bus, devfn, reg, size, val);
+}
+
+static int octeon_pcie1_write_config(struct pci_bus *bus, unsigned int devfn,
+				     int reg, int size, u32 val)
+{
+	return octeon_pcie_write_config(1, bus, devfn, reg, size, val);
+}
+
+static struct pci_ops octeon_pcie0_ops = {
+	octeon_pcie0_read_config,
+	octeon_pcie0_write_config,
+};
+
+static struct resource octeon_pcie0_mem_resource = {
+	.name = "Octeon PCIe0 MEM",
+	.flags = IORESOURCE_MEM,
+};
+
+static struct resource octeon_pcie0_io_resource = {
+	.name = "Octeon PCIe0 IO",
+	.flags = IORESOURCE_IO,
+};
+
+static struct pci_controller octeon_pcie0_controller = {
+	.pci_ops = &octeon_pcie0_ops,
+	.mem_resource = &octeon_pcie0_mem_resource,
+	.io_resource = &octeon_pcie0_io_resource,
+};
+
+static struct pci_ops octeon_pcie1_ops = {
+	octeon_pcie1_read_config,
+	octeon_pcie1_write_config,
+};
+
+static struct resource octeon_pcie1_mem_resource = {
+	.name = "Octeon PCIe1 MEM",
+	.flags = IORESOURCE_MEM,
+};
+
+static struct resource octeon_pcie1_io_resource = {
+	.name = "Octeon PCIe1 IO",
+	.flags = IORESOURCE_IO,
+};
+
+static struct pci_controller octeon_pcie1_controller = {
+	.pci_ops = &octeon_pcie1_ops,
+	.mem_resource = &octeon_pcie1_mem_resource,
+	.io_resource = &octeon_pcie1_io_resource,
+};
+
+
+/**
+ * Initialize the Octeon PCIe controllers
+ *
+ * Returns
+ */
+static int __init octeon_pcie_setup(void)
+{
+	union cvmx_npei_ctl_status npei_ctl_status;
+	int result;
+
+	/* These chips don't have PCIe */
+	if (!octeon_has_feature(OCTEON_FEATURE_PCIE))
+		return 0;
+
+	/* Point pcibios_map_irq() to the PCIe version of it */
+	octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq;
+
+	/* Use the PCIe based DMA mappings */
+	octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE;
+
+	/*
+	 * PCIe I/O range. It is based on port 0 but includes up until
+	 * port 1's end.
+	 */
+	set_io_port_base(CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0)));
+	ioport_resource.start = 0;
+	ioport_resource.end =
+		cvmx_pcie_get_io_base_address(1) -
+		cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1;
+
+	npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS);
+	if (npei_ctl_status.s.host_mode) {
+		pr_notice("PCIe: Initializing port 0\n");
+		result = cvmx_pcie_rc_initialize(0);
+		if (result == 0) {
+			/* Memory offsets are physical addresses */
+			octeon_pcie0_controller.mem_offset =
+				cvmx_pcie_get_mem_base_address(0);
+			/* IO offsets are Mips virtual addresses */
+			octeon_pcie0_controller.io_map_base =
+				CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address
+						(0));
+			octeon_pcie0_controller.io_offset = 0;
+			/*
+			 * To keep things similar to PCI, we start
+			 * device addresses at the same place as PCI
+			 * uisng big bar support. This normally
+			 * translates to 4GB-256MB, which is the same
+			 * as most x86 PCs.
+			 */
+			octeon_pcie0_controller.mem_resource->start =
+				cvmx_pcie_get_mem_base_address(0) +
+				(4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20);
+			octeon_pcie0_controller.mem_resource->end =
+				cvmx_pcie_get_mem_base_address(0) +
+				cvmx_pcie_get_mem_size(0) - 1;
+			/*
+			 * Ports must be above 16KB for the ISA bus
+			 * filtering in the PCI-X to PCI bridge.
+			 */
+			octeon_pcie0_controller.io_resource->start = 4 << 10;
+			octeon_pcie0_controller.io_resource->end =
+				cvmx_pcie_get_io_size(0) - 1;
+			register_pci_controller(&octeon_pcie0_controller);
+		}
+	} else {
+		pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n");
+	}
+
+	/* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
+		union cvmx_npei_dbg_data npei_dbg_data;
+		npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
+		if (npei_dbg_data.cn52xx.qlm0_link_width)
+			return 0;
+	}
+
+	pr_notice("PCIe: Initializing port 1\n");
+	result = cvmx_pcie_rc_initialize(1);
+	if (result == 0) {
+		/* Memory offsets are physical addresses */
+		octeon_pcie1_controller.mem_offset =
+			cvmx_pcie_get_mem_base_address(1);
+		/* IO offsets are Mips virtual addresses */
+		octeon_pcie1_controller.io_map_base =
+			CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(1));
+		octeon_pcie1_controller.io_offset =
+			cvmx_pcie_get_io_base_address(1) -
+			cvmx_pcie_get_io_base_address(0);
+		/*
+		 * To keep things similar to PCI, we start device
+		 * addresses at the same place as PCI uisng big bar
+		 * support. This normally translates to 4GB-256MB,
+		 * which is the same as most x86 PCs.
+		 */
+		octeon_pcie1_controller.mem_resource->start =
+			cvmx_pcie_get_mem_base_address(1) + (4ul << 30) -
+			(OCTEON_PCI_BAR1_HOLE_SIZE << 20);
+		octeon_pcie1_controller.mem_resource->end =
+			cvmx_pcie_get_mem_base_address(1) +
+			cvmx_pcie_get_mem_size(1) - 1;
+		/*
+		 * Ports must be above 16KB for the ISA bus filtering
+		 * in the PCI-X to PCI bridge.
+		 */
+		octeon_pcie1_controller.io_resource->start =
+			cvmx_pcie_get_io_base_address(1) -
+			cvmx_pcie_get_io_base_address(0);
+		octeon_pcie1_controller.io_resource->end =
+			octeon_pcie1_controller.io_resource->start +
+			cvmx_pcie_get_io_size(1) - 1;
+		register_pci_controller(&octeon_pcie1_controller);
+	}
+	return 0;
+}
+
+arch_initcall(octeon_pcie_setup);
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-ip27.c linux-libre-2.6.31-gnu/arch/mips/pci/pci-ip27.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-ip27.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-ip27.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/smp.h>
 #include <asm/sn/arch.h>
 #include <asm/pci/bridge.h>
 #include <asm/paccess.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-octeon.c linux-libre-2.6.31-gnu/arch/mips/pci/pci-octeon.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-octeon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-octeon.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,675 @@
+/*
+ * 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) 2005-2009 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <asm/time.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-npi-defs.h>
+#include <asm/octeon/cvmx-pci-defs.h>
+#include <asm/octeon/pci-octeon.h>
+
+#define USE_OCTEON_INTERNAL_ARBITER
+
+/*
+ * Octeon's PCI controller uses did=3, subdid=2 for PCI IO
+ * addresses. Use PCI endian swapping 1 so no address swapping is
+ * necessary. The Linux io routines will endian swap the data.
+ */
+#define OCTEON_PCI_IOSPACE_BASE     0x80011a0400000000ull
+#define OCTEON_PCI_IOSPACE_SIZE     (1ull<<32)
+
+/* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */
+#define OCTEON_PCI_MEMSPACE_OFFSET  (0x00011b0000000000ull)
+
+/**
+ * This is the bit decoding used for the Octeon PCI controller addresses
+ */
+union octeon_pci_address {
+	uint64_t u64;
+	struct {
+		uint64_t upper:2;
+		uint64_t reserved:13;
+		uint64_t io:1;
+		uint64_t did:5;
+		uint64_t subdid:3;
+		uint64_t reserved2:4;
+		uint64_t endian_swap:2;
+		uint64_t reserved3:10;
+		uint64_t bus:8;
+		uint64_t dev:5;
+		uint64_t func:3;
+		uint64_t reg:8;
+	} s;
+};
+
+int __initdata (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+					 u8 slot, u8 pin);
+enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @dev:    The Linux PCI device structure for the device to map
+ * @slot:   The slot number for this device on __BUS 0__. Linux
+ *               enumerates through all the bridges and figures out the
+ *               slot on Bus 0 where this device eventually hooks to.
+ * @pin:    The PCI interrupt pin read from the device, then swizzled
+ *               as it goes through each bridge.
+ * Returns Interrupt number for the device
+ */
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (octeon_pcibios_map_irq)
+		return octeon_pcibios_map_irq(dev, slot, pin);
+	else
+		panic("octeon_pcibios_map_irq not set.");
+}
+
+
+/*
+ * Called to perform platform specific PCI setup
+ */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	uint16_t config;
+	uint32_t dconfig;
+	int pos;
+	/*
+	 * Force the Cache line setting to 64 bytes. The standard
+	 * Linux bus scan doesn't seem to set it. Octeon really has
+	 * 128 byte lines, but Intel bridges get really upset if you
+	 * try and set values above 64 bytes. Value is specified in
+	 * 32bit words.
+	 */
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4);
+	/* Set latency timers for all devices */
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48);
+
+	/* Enable reporting System errors and parity errors on all devices */
+	/* Enable parity checking and error reporting */
+	pci_read_config_word(dev, PCI_COMMAND, &config);
+	config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+	pci_write_config_word(dev, PCI_COMMAND, config);
+
+	if (dev->subordinate) {
+		/* Set latency timers on sub bridges */
+		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48);
+		/* More bridge error detection */
+		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config);
+		config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
+		pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config);
+	}
+
+	/* Enable the PCIe normal error reporting */
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (pos) {
+		/* Update Device Control */
+		pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
+		/* Correctable Error Reporting */
+		config |= PCI_EXP_DEVCTL_CERE;
+		/* Non-Fatal Error Reporting */
+		config |= PCI_EXP_DEVCTL_NFERE;
+		/* Fatal Error Reporting */
+		config |= PCI_EXP_DEVCTL_FERE;
+		/* Unsupported Request */
+		config |= PCI_EXP_DEVCTL_URRE;
+		pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
+	}
+
+	/* Find the Advanced Error Reporting capability */
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+	if (pos) {
+		/* Clear Uncorrectable Error Status */
+		pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+				      &dconfig);
+		pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+				       dconfig);
+		/* Enable reporting of all uncorrectable errors */
+		/* Uncorrectable Error Mask - turned on bits disable errors */
+		pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0);
+		/*
+		 * Leave severity at HW default. This only controls if
+		 * errors are reported as uncorrectable or
+		 * correctable, not if the error is reported.
+		 */
+		/* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */
+		/* Clear Correctable Error Status */
+		pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig);
+		pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig);
+		/* Enable reporting of all correctable errors */
+		/* Correctable Error Mask - turned on bits disable errors */
+		pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0);
+		/* Advanced Error Capabilities */
+		pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig);
+		/* ECRC Generation Enable */
+		if (config & PCI_ERR_CAP_ECRC_GENC)
+			config |= PCI_ERR_CAP_ECRC_GENE;
+		/* ECRC Check Enable */
+		if (config & PCI_ERR_CAP_ECRC_CHKC)
+			config |= PCI_ERR_CAP_ECRC_CHKE;
+		pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig);
+		/* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */
+		/* Report all errors to the root complex */
+		pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND,
+				       PCI_ERR_ROOT_CMD_COR_EN |
+				       PCI_ERR_ROOT_CMD_NONFATAL_EN |
+				       PCI_ERR_ROOT_CMD_FATAL_EN);
+		/* Clear the Root status register */
+		pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig);
+		pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
+	}
+
+	return 0;
+}
+
+/**
+ * Return the mapping of PCI device number to IRQ line. Each
+ * character in the return string represents the interrupt
+ * line for the device at that position. Device 1 maps to the
+ * first character, etc. The characters A-D are used for PCI
+ * interrupts.
+ *
+ * Returns PCI interrupt mapping
+ */
+const char *octeon_get_pci_interrupts(void)
+{
+	/*
+	 * Returning an empty string causes the interrupts to be
+	 * routed based on the PCI specification. From the PCI spec:
+	 *
+	 * INTA# of Device Number 0 is connected to IRQW on the system
+	 * board.  (Device Number has no significance regarding being
+	 * located on the system board or in a connector.) INTA# of
+	 * Device Number 1 is connected to IRQX on the system
+	 * board. INTA# of Device Number 2 is connected to IRQY on the
+	 * system board. INTA# of Device Number 3 is connected to IRQZ
+	 * on the system board. The table below describes how each
+	 * agent's INTx# lines are connected to the system board
+	 * interrupt lines. The following equation can be used to
+	 * determine to which INTx# signal on the system board a given
+	 * device's INTx# line(s) is connected.
+	 *
+	 * MB = (D + I) MOD 4 MB = System board Interrupt (IRQW = 0,
+	 * IRQX = 1, IRQY = 2, and IRQZ = 3) D = Device Number I =
+	 * Interrupt Number (INTA# = 0, INTB# = 1, INTC# = 2, and
+	 * INTD# = 3)
+	 */
+	switch (octeon_bootinfo->board_type) {
+	case CVMX_BOARD_TYPE_NAO38:
+		/* This is really the NAC38 */
+		return "AAAAADABAAAAAAAAAAAAAAAAAAAAAAAA";
+	case CVMX_BOARD_TYPE_THUNDER:
+		return "";
+	case CVMX_BOARD_TYPE_EBH3000:
+		return "";
+	case CVMX_BOARD_TYPE_EBH3100:
+	case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
+	case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
+		return "AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+	case CVMX_BOARD_TYPE_BBGW_REF:
+		return "AABCD";
+	default:
+		return "";
+	}
+}
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @dev:    The Linux PCI device structure for the device to map
+ * @slot:   The slot number for this device on __BUS 0__. Linux
+ *               enumerates through all the bridges and figures out the
+ *               slot on Bus 0 where this device eventually hooks to.
+ * @pin:    The PCI interrupt pin read from the device, then swizzled
+ *               as it goes through each bridge.
+ * Returns Interrupt number for the device
+ */
+int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev,
+				      u8 slot, u8 pin)
+{
+	int irq_num;
+	const char *interrupts;
+	int dev_num;
+
+	/* Get the board specific interrupt mapping */
+	interrupts = octeon_get_pci_interrupts();
+
+	dev_num = dev->devfn >> 3;
+	if (dev_num < strlen(interrupts))
+		irq_num = ((interrupts[dev_num] - 'A' + pin - 1) & 3) +
+			OCTEON_IRQ_PCI_INT0;
+	else
+		irq_num = ((slot + pin - 3) & 3) + OCTEON_IRQ_PCI_INT0;
+	return irq_num;
+}
+
+
+/*
+ * Read a value from configuration space
+ */
+static int octeon_read_config(struct pci_bus *bus, unsigned int devfn,
+			      int reg, int size, u32 *val)
+{
+	union octeon_pci_address pci_addr;
+
+	pci_addr.u64 = 0;
+	pci_addr.s.upper = 2;
+	pci_addr.s.io = 1;
+	pci_addr.s.did = 3;
+	pci_addr.s.subdid = 1;
+	pci_addr.s.endian_swap = 1;
+	pci_addr.s.bus = bus->number;
+	pci_addr.s.dev = devfn >> 3;
+	pci_addr.s.func = devfn & 0x7;
+	pci_addr.s.reg = reg;
+
+#if PCI_CONFIG_SPACE_DELAY
+	udelay(PCI_CONFIG_SPACE_DELAY);
+#endif
+	switch (size) {
+	case 4:
+		*val = le32_to_cpu(cvmx_read64_uint32(pci_addr.u64));
+		return PCIBIOS_SUCCESSFUL;
+	case 2:
+		*val = le16_to_cpu(cvmx_read64_uint16(pci_addr.u64));
+		return PCIBIOS_SUCCESSFUL;
+	case 1:
+		*val = cvmx_read64_uint8(pci_addr.u64);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+
+/*
+ * Write a value to PCI configuration space
+ */
+static int octeon_write_config(struct pci_bus *bus, unsigned int devfn,
+			       int reg, int size, u32 val)
+{
+	union octeon_pci_address pci_addr;
+
+	pci_addr.u64 = 0;
+	pci_addr.s.upper = 2;
+	pci_addr.s.io = 1;
+	pci_addr.s.did = 3;
+	pci_addr.s.subdid = 1;
+	pci_addr.s.endian_swap = 1;
+	pci_addr.s.bus = bus->number;
+	pci_addr.s.dev = devfn >> 3;
+	pci_addr.s.func = devfn & 0x7;
+	pci_addr.s.reg = reg;
+
+#if PCI_CONFIG_SPACE_DELAY
+	udelay(PCI_CONFIG_SPACE_DELAY);
+#endif
+	switch (size) {
+	case 4:
+		cvmx_write64_uint32(pci_addr.u64, cpu_to_le32(val));
+		return PCIBIOS_SUCCESSFUL;
+	case 2:
+		cvmx_write64_uint16(pci_addr.u64, cpu_to_le16(val));
+		return PCIBIOS_SUCCESSFUL;
+	case 1:
+		cvmx_write64_uint8(pci_addr.u64, val);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+
+static struct pci_ops octeon_pci_ops = {
+	octeon_read_config,
+	octeon_write_config,
+};
+
+static struct resource octeon_pci_mem_resource = {
+	.start = 0,
+	.end = 0,
+	.name = "Octeon PCI MEM",
+	.flags = IORESOURCE_MEM,
+};
+
+/*
+ * PCI ports must be above 16KB so the ISA bus filtering in the PCI-X to PCI
+ * bridge
+ */
+static struct resource octeon_pci_io_resource = {
+	.start = 0x4000,
+	.end = OCTEON_PCI_IOSPACE_SIZE - 1,
+	.name = "Octeon PCI IO",
+	.flags = IORESOURCE_IO,
+};
+
+static struct pci_controller octeon_pci_controller = {
+	.pci_ops = &octeon_pci_ops,
+	.mem_resource = &octeon_pci_mem_resource,
+	.mem_offset = OCTEON_PCI_MEMSPACE_OFFSET,
+	.io_resource = &octeon_pci_io_resource,
+	.io_offset = 0,
+	.io_map_base = OCTEON_PCI_IOSPACE_BASE,
+};
+
+
+/*
+ * Low level initialize the Octeon PCI controller
+ */
+static void octeon_pci_initialize(void)
+{
+	union cvmx_pci_cfg01 cfg01;
+	union cvmx_npi_ctl_status ctl_status;
+	union cvmx_pci_ctl_status_2 ctl_status_2;
+	union cvmx_pci_cfg19 cfg19;
+	union cvmx_pci_cfg16 cfg16;
+	union cvmx_pci_cfg22 cfg22;
+	union cvmx_pci_cfg56 cfg56;
+
+	/* Reset the PCI Bus */
+	cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1);
+	cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+
+	udelay(2000);		/* Hold PCI reset for 2 ms */
+
+	ctl_status.u64 = 0;	/* cvmx_read_csr(CVMX_NPI_CTL_STATUS); */
+	ctl_status.s.max_word = 1;
+	ctl_status.s.timer = 1;
+	cvmx_write_csr(CVMX_NPI_CTL_STATUS, ctl_status.u64);
+
+	/* Deassert PCI reset and advertize PCX Host Mode Device Capability
+	   (64b) */
+	cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x4);
+	cvmx_read_csr(CVMX_CIU_SOFT_PRST);
+
+	udelay(2000);		/* Wait 2 ms after deasserting PCI reset */
+
+	ctl_status_2.u32 = 0;
+	ctl_status_2.s.tsr_hwm = 1;	/* Initializes to 0.  Must be set
+					   before any PCI reads. */
+	ctl_status_2.s.bar2pres = 1;	/* Enable BAR2 */
+	ctl_status_2.s.bar2_enb = 1;
+	ctl_status_2.s.bar2_cax = 1;	/* Don't use L2 */
+	ctl_status_2.s.bar2_esx = 1;
+	ctl_status_2.s.pmo_amod = 1;	/* Round robin priority */
+	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) {
+		/* BAR1 hole */
+		ctl_status_2.s.bb1_hole = OCTEON_PCI_BAR1_HOLE_BITS;
+		ctl_status_2.s.bb1_siz = 1;  /* BAR1 is 2GB */
+		ctl_status_2.s.bb_ca = 1;    /* Don't use L2 with big bars */
+		ctl_status_2.s.bb_es = 1;    /* Big bar in byte swap mode */
+		ctl_status_2.s.bb1 = 1;      /* BAR1 is big */
+		ctl_status_2.s.bb0 = 1;      /* BAR0 is big */
+	}
+
+	octeon_npi_write32(CVMX_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32);
+	udelay(2000);		/* Wait 2 ms before doing PCI reads */
+
+	ctl_status_2.u32 = octeon_npi_read32(CVMX_NPI_PCI_CTL_STATUS_2);
+	pr_notice("PCI Status: %s %s-bit\n",
+		  ctl_status_2.s.ap_pcix ? "PCI-X" : "PCI",
+		  ctl_status_2.s.ap_64ad ? "64" : "32");
+
+	if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
+		union cvmx_pci_cnt_reg cnt_reg_start;
+		union cvmx_pci_cnt_reg cnt_reg_end;
+		unsigned long cycles, pci_clock;
+
+		cnt_reg_start.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG);
+		cycles = read_c0_cvmcount();
+		udelay(1000);
+		cnt_reg_end.u64 = cvmx_read_csr(CVMX_NPI_PCI_CNT_REG);
+		cycles = read_c0_cvmcount() - cycles;
+		pci_clock = (cnt_reg_end.s.pcicnt - cnt_reg_start.s.pcicnt) /
+			    (cycles / (mips_hpt_frequency / 1000000));
+		pr_notice("PCI Clock: %lu MHz\n", pci_clock);
+	}
+
+	/*
+	 * TDOMC must be set to one in PCI mode. TDOMC should be set to 4
+	 * in PCI-X mode to allow four oustanding splits. Otherwise,
+	 * should not change from its reset value. Don't write PCI_CFG19
+	 * in PCI mode (0x82000001 reset value), write it to 0x82000004
+	 * after PCI-X mode is known. MRBCI,MDWE,MDRE -> must be zero.
+	 * MRBCM -> must be one.
+	 */
+	if (ctl_status_2.s.ap_pcix) {
+		cfg19.u32 = 0;
+		/*
+		 * Target Delayed/Split request outstanding maximum
+		 * count. [1..31] and 0=32.  NOTE: If the user
+		 * programs these bits beyond the Designed Maximum
+		 * outstanding count, then the designed maximum table
+		 * depth will be used instead.  No additional
+		 * Deferred/Split transactions will be accepted if
+		 * this outstanding maximum count is
+		 * reached. Furthermore, no additional deferred/split
+		 * transactions will be accepted if the I/O delay/ I/O
+		 * Split Request outstanding maximum is reached.
+		 */
+		cfg19.s.tdomc = 4;
+		/*
+		 * Master Deferred Read Request Outstanding Max Count
+		 * (PCI only).  CR4C[26:24] Max SAC cycles MAX DAC
+		 * cycles 000 8 4 001 1 0 010 2 1 011 3 1 100 4 2 101
+		 * 5 2 110 6 3 111 7 3 For example, if these bits are
+		 * programmed to 100, the core can support 2 DAC
+		 * cycles, 4 SAC cycles or a combination of 1 DAC and
+		 * 2 SAC cycles. NOTE: For the PCI-X maximum
+		 * outstanding split transactions, refer to
+		 * CRE0[22:20].
+		 */
+		cfg19.s.mdrrmc = 2;
+		/*
+		 * Master Request (Memory Read) Byte Count/Byte Enable
+		 * select. 0 = Byte Enables valid. In PCI mode, a
+		 * burst transaction cannot be performed using Memory
+		 * Read command=4?h6. 1 = DWORD Byte Count valid
+		 * (default). In PCI Mode, the memory read byte
+		 * enables are automatically generated by the
+		 * core. Note: N3 Master Request transaction sizes are
+		 * always determined through the
+		 * am_attr[<35:32>|<7:0>] field.
+		 */
+		cfg19.s.mrbcm = 1;
+		octeon_npi_write32(CVMX_NPI_PCI_CFG19, cfg19.u32);
+	}
+
+
+	cfg01.u32 = 0;
+	cfg01.s.msae = 1;	/* Memory Space Access Enable */
+	cfg01.s.me = 1;		/* Master Enable */
+	cfg01.s.pee = 1;	/* PERR# Enable */
+	cfg01.s.see = 1;	/* System Error Enable */
+	cfg01.s.fbbe = 1;	/* Fast Back to Back Transaction Enable */
+
+	octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32);
+
+#ifdef USE_OCTEON_INTERNAL_ARBITER
+	/*
+	 * When OCTEON is a PCI host, most systems will use OCTEON's
+	 * internal arbiter, so must enable it before any PCI/PCI-X
+	 * traffic can occur.
+	 */
+	{
+		union cvmx_npi_pci_int_arb_cfg pci_int_arb_cfg;
+
+		pci_int_arb_cfg.u64 = 0;
+		pci_int_arb_cfg.s.en = 1;	/* Internal arbiter enable */
+		cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64);
+	}
+#endif	/* USE_OCTEON_INTERNAL_ARBITER */
+
+	/*
+	 * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE,
+	 * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to
+	 * 1..7.
+	 */
+	cfg16.u32 = 0;
+	cfg16.s.mltd = 1;	/* Master Latency Timer Disable */
+	octeon_npi_write32(CVMX_NPI_PCI_CFG16, cfg16.u32);
+
+	/*
+	 * Should be written to 0x4ff00. MTTV -> must be zero.
+	 * FLUSH -> must be 1. MRV -> should be 0xFF.
+	 */
+	cfg22.u32 = 0;
+	/* Master Retry Value [1..255] and 0=infinite */
+	cfg22.s.mrv = 0xff;
+	/*
+	 * AM_DO_FLUSH_I control NOTE: This bit MUST BE ONE for proper
+	 * N3K operation.
+	 */
+	cfg22.s.flush = 1;
+	octeon_npi_write32(CVMX_NPI_PCI_CFG22, cfg22.u32);
+
+	/*
+	 * MOST Indicates the maximum number of outstanding splits (in -1
+	 * notation) when OCTEON is in PCI-X mode.  PCI-X performance is
+	 * affected by the MOST selection.  Should generally be written
+	 * with one of 0x3be807, 0x2be807, 0x1be807, or 0x0be807,
+	 * depending on the desired MOST of 3, 2, 1, or 0, respectively.
+	 */
+	cfg56.u32 = 0;
+	cfg56.s.pxcid = 7;	/* RO - PCI-X Capability ID */
+	cfg56.s.ncp = 0xe8;	/* RO - Next Capability Pointer */
+	cfg56.s.dpere = 1;	/* Data Parity Error Recovery Enable */
+	cfg56.s.roe = 1;	/* Relaxed Ordering Enable */
+	cfg56.s.mmbc = 1;	/* Maximum Memory Byte Count
+				   [0=512B,1=1024B,2=2048B,3=4096B] */
+	cfg56.s.most = 3;	/* Maximum outstanding Split transactions [0=1
+				   .. 7=32] */
+
+	octeon_npi_write32(CVMX_NPI_PCI_CFG56, cfg56.u32);
+
+	/*
+	 * Affects PCI performance when OCTEON services reads to its
+	 * BAR1/BAR2. Refer to Section 10.6.1.  The recommended values are
+	 * 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and
+	 * PCI_READ_CMD_E, respectively. Unfortunately due to errata DDR-700,
+	 * these values need to be changed so they won't possibly prefetch off
+	 * of the end of memory if PCI is DMAing a buffer at the end of
+	 * memory. Note that these values differ from their reset values.
+	 */
+	octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_6, 0x21);
+	octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_C, 0x31);
+	octeon_npi_write32(CVMX_NPI_PCI_READ_CMD_E, 0x31);
+}
+
+
+/*
+ * Initialize the Octeon PCI controller
+ */
+static int __init octeon_pci_setup(void)
+{
+	union cvmx_npi_mem_access_subidx mem_access;
+	int index;
+
+	/* Only these chips have PCI */
+	if (octeon_has_feature(OCTEON_FEATURE_PCIE))
+		return 0;
+
+	/* Point pcibios_map_irq() to the PCI version of it */
+	octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
+
+	/* Only use the big bars on chips that support it */
+	if (OCTEON_IS_MODEL(OCTEON_CN31XX) ||
+	    OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) ||
+	    OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1))
+		octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_SMALL;
+	else
+		octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
+
+	/* PCI I/O and PCI MEM values */
+	set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
+	ioport_resource.start = 0;
+	ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1;
+	if (!octeon_is_pci_host()) {
+		pr_notice("Not in host mode, PCI Controller not initialized\n");
+		return 0;
+	}
+
+	pr_notice("%s Octeon big bar support\n",
+		  (octeon_dma_bar_type ==
+		  OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling");
+
+	octeon_pci_initialize();
+
+	mem_access.u64 = 0;
+	mem_access.s.esr = 1;	/* Endian-Swap on read. */
+	mem_access.s.esw = 1;	/* Endian-Swap on write. */
+	mem_access.s.nsr = 0;	/* No-Snoop on read. */
+	mem_access.s.nsw = 0;	/* No-Snoop on write. */
+	mem_access.s.ror = 0;	/* Relax Read on read. */
+	mem_access.s.row = 0;	/* Relax Order on write. */
+	mem_access.s.ba = 0;	/* PCI Address bits [63:36]. */
+	cvmx_write_csr(CVMX_NPI_MEM_ACCESS_SUBID3, mem_access.u64);
+
+	/*
+	 * Remap the Octeon BAR 2 above all 32 bit devices
+	 * (0x8000000000ul).  This is done here so it is remapped
+	 * before the readl()'s below. We don't want BAR2 overlapping
+	 * with BAR0/BAR1 during these reads.
+	 */
+	octeon_npi_write32(CVMX_NPI_PCI_CFG08, 0);
+	octeon_npi_write32(CVMX_NPI_PCI_CFG09, 0x80);
+
+	/* Disable the BAR1 movable mappings */
+	for (index = 0; index < 32; index++)
+		octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0);
+
+	if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) {
+		/* Remap the Octeon BAR 0 to 0-2GB */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG04, 0);
+		octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0);
+
+		/*
+		 * Remap the Octeon BAR 1 to map 2GB-4GB (minus the
+		 * BAR 1 hole).
+		 */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG06, 2ul << 30);
+		octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0);
+
+		/* Devices go after BAR1 */
+		octeon_pci_mem_resource.start =
+			OCTEON_PCI_MEMSPACE_OFFSET + (4ul << 30) -
+			(OCTEON_PCI_BAR1_HOLE_SIZE << 20);
+		octeon_pci_mem_resource.end =
+			octeon_pci_mem_resource.start + (1ul << 30);
+	} else {
+		/* Remap the Octeon BAR 0 to map 128MB-(128MB+4KB) */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG04, 128ul << 20);
+		octeon_npi_write32(CVMX_NPI_PCI_CFG05, 0);
+
+		/* Remap the Octeon BAR 1 to map 0-128MB */
+		octeon_npi_write32(CVMX_NPI_PCI_CFG06, 0);
+		octeon_npi_write32(CVMX_NPI_PCI_CFG07, 0);
+
+		/* Devices go after BAR0 */
+		octeon_pci_mem_resource.start =
+			OCTEON_PCI_MEMSPACE_OFFSET + (128ul << 20) +
+			(4ul << 10);
+		octeon_pci_mem_resource.end =
+			octeon_pci_mem_resource.start + (1ul << 30);
+	}
+
+	register_pci_controller(&octeon_pci_controller);
+
+	/*
+	 * Clear any errors that might be pending from before the bus
+	 * was setup properly.
+	 */
+	cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1);
+	return 0;
+}
+
+arch_initcall(octeon_pci_setup);
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-tx4927.c linux-libre-2.6.31-gnu/arch/mips/pci/pci-tx4927.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-tx4927.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-tx4927.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/pci/pci-tx4927.c
- *
  * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
  *	    and RBTX49xx patch from CELF patch archive.
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-tx4938.c linux-libre-2.6.31-gnu/arch/mips/pci/pci-tx4938.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-tx4938.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-tx4938.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/pci/pci-tx4938.c
- *
  * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
  *	    and RBTX49xx patch from CELF patch archive.
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-tx4939.c linux-libre-2.6.31-gnu/arch/mips/pci/pci-tx4939.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-tx4939.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-tx4939.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/pci/pci-tx4939.c
- *
  * Based on linux/arch/mips/txx9/rbtx4939/setup.c,
  *	    and RBTX49xx patch from CELF patch archive.
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-vr41xx.c linux-libre-2.6.31-gnu/arch/mips/pci/pci-vr41xx.c
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-vr41xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-vr41xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,8 @@
  *  pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2003 MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *  Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  */
 #include <linux/init.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/pci/pci-vr41xx.h linux-libre-2.6.31-gnu/arch/mips/pci/pci-vr41xx.h
--- linux-libre-2.6.30-gnu/arch/mips/pci/pci-vr41xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pci/pci-vr41xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,8 @@
  *  pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series.
  *
  *  Copyright (C) 2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/msp71xx/gpio.c linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/msp71xx/gpio.c
--- linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/msp71xx/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/msp71xx/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * @file /arch/mips/pmc-sierra/msp71xx/gpio.c
- *
  * Generic PMC MSP71xx GPIO handling. These base gpio are controlled by two
  * types of registers. The data register sets the output level when in output
  * mode and when in input mode will contain the value at the input. The config
diff -druN linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/msp71xx/gpio_extended.c linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/msp71xx/gpio_extended.c
--- linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/msp71xx/gpio_extended.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/msp71xx/gpio_extended.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * @file /arch/mips/pmc-sierra/msp71xx/gpio_extended.c
- *
  * Generic PMC MSP71xx EXTENDED (EXD) GPIO handling. The extended gpio is
  * a set of hardware registers that have no need for explicit locking as
  * it is handled by unique method of writing individual set/clr bits.
diff -druN linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
--- linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c	2009-09-09 18:13:59.000000000 -0400
@@ -45,13 +45,6 @@
  */
 static inline void ack_msp_slp_irq(unsigned int irq)
 {
-	mask_slp_irq(irq);
-
-	/*
-	 * only really necessary for 18, 16-14 and sometimes 3:0 (since
-	 * these can be edge sensitive) but it doesn't hurt  for the others.
-	 */
-
 	/* check for PER interrupt range */
 	if (irq < MSP_PER_INTBASE)
 		*SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE));
@@ -62,8 +55,7 @@
 static struct irq_chip msp_slp_irq_controller = {
 	.name = "MSP_SLP",
 	.ack = ack_msp_slp_irq,
-	.mask = ack_msp_slp_irq,
-	.mask_ack = ack_msp_slp_irq,
+	.mask = mask_msp_slp_irq,
 	.unmask = unmask_msp_slp_irq,
 };
 
@@ -79,7 +71,7 @@
 
 	/* initialize all the IRQ descriptors */
 	for (i = MSP_SLP_INTBASE; i < MSP_PER_INTBASE + 32; i++)
-		set_irq_chip_and_handler(i, &msp_slp_irq_controller
+		set_irq_chip_and_handler(i, &msp_slp_irq_controller,
 					 handle_level_irq);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
--- linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *  arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
- *
  *  Copyright (C) 2003 PMC-Sierra Inc.
  *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
  *
diff -druN linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/yosemite/smp.c linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/yosemite/smp.c
--- linux-libre-2.6.30-gnu/arch/mips/pmc-sierra/yosemite/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/pmc-sierra/yosemite/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,6 @@
 #include <linux/linkage.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 
 #include <asm/pmon.h>
 #include <asm/titan_dep.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/power/cpu.c linux-libre-2.6.31-gnu/arch/mips/power/cpu.c
--- linux-libre-2.6.30-gnu/arch/mips/power/cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/power/cpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Suspend support specific for mips.
+ *
+ * Licensed under the GPLv2
+ *
+ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Author: Hu Hongbing <huhb@lemote.com>
+ *         Wu Zhangjin <wuzj@lemote.com>
+ */
+#include <asm/suspend.h>
+#include <asm/fpu.h>
+#include <asm/dsp.h>
+
+static u32 saved_status;
+struct pt_regs saved_regs;
+
+void save_processor_state(void)
+{
+	saved_status = read_c0_status();
+
+	if (is_fpu_owner())
+		save_fp(current);
+	if (cpu_has_dsp)
+		save_dsp(current);
+}
+
+void restore_processor_state(void)
+{
+	write_c0_status(saved_status);
+
+	if (is_fpu_owner())
+		restore_fp(current);
+	if (cpu_has_dsp)
+		restore_dsp(current);
+}
+
+int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
+	unsigned long nosave_end_pfn = PFN_UP(__pa(&__nosave_end));
+
+	return	(pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/power/hibernate.S linux-libre-2.6.31-gnu/arch/mips/power/hibernate.S
--- linux-libre-2.6.30-gnu/arch/mips/power/hibernate.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/power/hibernate.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Hibernation support specific for mips - temporary page tables
+ *
+ * Licensed under the GPLv2
+ *
+ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Author: Hu Hongbing <huhb@lemote.com>
+ *         Wu Zhangjin <wuzj@lemote.com>
+ */
+#include <asm/asm-offsets.h>
+#include <asm/regdef.h>
+#include <asm/asm.h>
+
+.text
+LEAF(swsusp_arch_suspend)
+	PTR_LA t0, saved_regs
+	PTR_S ra, PT_R31(t0)
+	PTR_S sp, PT_R29(t0)
+	PTR_S fp, PT_R30(t0)
+	PTR_S gp, PT_R28(t0)
+	PTR_S s0, PT_R16(t0)
+	PTR_S s1, PT_R17(t0)
+	PTR_S s2, PT_R18(t0)
+	PTR_S s3, PT_R19(t0)
+	PTR_S s4, PT_R20(t0)
+	PTR_S s5, PT_R21(t0)
+	PTR_S s6, PT_R22(t0)
+	PTR_S s7, PT_R23(t0)
+	j swsusp_save
+END(swsusp_arch_suspend)
+
+LEAF(swsusp_arch_resume)
+	PTR_L t0, restore_pblist
+0:
+	PTR_L t1, PBE_ADDRESS(t0)   /* source */
+	PTR_L t2, PBE_ORIG_ADDRESS(t0) /* destination */
+	PTR_ADDIU t3, t1, _PAGE_SIZE
+1:
+	REG_L t8, (t1)
+	REG_S t8, (t2)
+	PTR_ADDIU t1, t1, SZREG
+	PTR_ADDIU t2, t2, SZREG
+	bne t1, t3, 1b
+	PTR_L t0, PBE_NEXT(t0)
+	bnez t0, 0b
+	PTR_LA t0, saved_regs
+	PTR_L ra, PT_R31(t0)
+	PTR_L sp, PT_R29(t0)
+	PTR_L fp, PT_R30(t0)
+	PTR_L gp, PT_R28(t0)
+	PTR_L s0, PT_R16(t0)
+	PTR_L s1, PT_R17(t0)
+	PTR_L s2, PT_R18(t0)
+	PTR_L s3, PT_R19(t0)
+	PTR_L s4, PT_R20(t0)
+	PTR_L s5, PT_R21(t0)
+	PTR_L s6, PT_R22(t0)
+	PTR_L s7, PT_R23(t0)
+	PTR_LI v0, 0x0
+	jr ra
+END(swsusp_arch_resume)
diff -druN linux-libre-2.6.30-gnu/arch/mips/power/Makefile linux-libre-2.6.31-gnu/arch/mips/power/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/power/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/power/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_HIBERNATION) += cpu.o hibernate.o
diff -druN linux-libre-2.6.30-gnu/arch/mips/rb532/irq.c linux-libre-2.6.31-gnu/arch/mips/rb532/irq.c
--- linux-libre-2.6.30-gnu/arch/mips/rb532/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/rb532/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -151,7 +151,8 @@
 		mask |= intr_bit;
 		WRITE_MASK(addr, mask);
 
-		if (group == GPIO_MAPPED_IRQ_GROUP)
+		/* There is a maximum of 14 GPIO interrupts */
+		if (group == GPIO_MAPPED_IRQ_GROUP && irq_nr <= (GROUP4_IRQ_BASE + 13))
 			rb532_gpio_set_istat(0, irq_nr - GPIO_MAPPED_IRQ_BASE);
 
 		/*
@@ -174,7 +175,7 @@
 	int gpio = irq_nr - GPIO_MAPPED_IRQ_BASE;
 	int group = irq_to_group(irq_nr);
 
-	if (group != GPIO_MAPPED_IRQ_GROUP)
+	if (group != GPIO_MAPPED_IRQ_GROUP || irq_nr > (GROUP4_IRQ_BASE + 13))
 		return (type == IRQ_TYPE_LEVEL_HIGH) ? 0 : -EINVAL;
 
 	switch (type) {
diff -druN linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-init.c linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-init.c
--- linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-init.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-irq.c linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-irq.c
--- linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/ioport.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
+#include <linux/smp.h>
 #include <linux/random.h>
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-timer.c linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-timer.c
--- linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-timer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-timer.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/param.h>
+#include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/mm.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-xtalk.c linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-xtalk.c
--- linux-libre-2.6.30-gnu/arch/mips/sgi-ip27/ip27-xtalk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sgi-ip27/ip27-xtalk.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <asm/sn/types.h>
 #include <asm/sn/klconfig.h>
 #include <asm/sn/hub.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/bcm1480/irq.c linux-libre-2.6.31-gnu/arch/mips/sibyte/bcm1480/irq.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/bcm1480/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/bcm1480/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/interrupt.h>
+#include <linux/smp.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -50,7 +51,7 @@
 static void disable_bcm1480_irq(unsigned int irq);
 static void ack_bcm1480_irq(unsigned int irq);
 #ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
+static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
 #endif
 
 #ifdef CONFIG_PCI
@@ -109,7 +110,7 @@
 }
 
 #ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	int i = 0, old_cpu, cpu, int_on, k;
 	u64 cur_ints;
@@ -118,7 +119,7 @@
 
 	if (cpumask_weight(mask) != 1) {
 		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
-		return;
+		return -1;
 	}
 	i = cpumask_first(mask);
 
@@ -152,6 +153,8 @@
 		}
 	}
 	spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
+
+	return 0;
 }
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/cfe/console.c linux-libre-2.6.31-gnu/arch/mips/sibyte/cfe/console.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/cfe/console.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/cfe/console.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/console.h>
-
-#include <asm/sibyte/board.h>
-
-#include <asm/fw/cfe/cfe_api.h>
-#include <asm/fw/cfe/cfe_error.h>
-
-extern int cfe_cons_handle;
-
-static void cfe_console_write(struct console *cons, const char *str,
-		       unsigned int count)
-{
-	int i, last, written;
-
-	for (i=0, last=0; i<count; i++) {
-		if (!str[i])
-			/* XXXKW can/should this ever happen? */
-			return;
-		if (str[i] == '\n') {
-			do {
-				written = cfe_write(cfe_cons_handle, &str[last], i-last);
-				if (written < 0)
-					;
-				last += written;
-			} while (last < i);
-			while (cfe_write(cfe_cons_handle, "\r", 1) <= 0)
-				;
-		}
-	}
-	if (last != count) {
-		do {
-			written = cfe_write(cfe_cons_handle, &str[last], count-last);
-			if (written < 0)
-				;
-			last += written;
-		} while (last < count);
-	}
-
-}
-
-static int cfe_console_setup(struct console *cons, char *str)
-{
-	char consdev[32];
-	/* XXXKW think about interaction with 'console=' cmdline arg */
-	/* If none of the console options are configured, the build will break. */
-	if (cfe_getenv("BOOT_CONSOLE", consdev, 32) >= 0) {
-#ifdef CONFIG_SERIAL_SB1250_DUART
-		if (!strcmp(consdev, "uart0")) {
-			setleds("u0cn");
-		} else if (!strcmp(consdev, "uart1")) {
-			setleds("u1cn");
-#endif
-#ifdef CONFIG_VGA_CONSOLE
-		} else if (!strcmp(consdev, "pcconsole0")) {
-			setleds("pccn");
-#endif
-		} else
-			return -ENODEV;
-	}
-	return 0;
-}
-
-static struct console sb1250_cfe_cons = {
-	.name		= "cfe",
-	.write		= cfe_console_write,
-	.setup		= cfe_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-static int __init sb1250_cfe_console_init(void)
-{
-	register_console(&sb1250_cfe_cons);
-	return 0;
-}
-
-console_initcall(sb1250_cfe_console_init);
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/cfe/Makefile linux-libre-2.6.31-gnu/arch/mips/sibyte/cfe/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/cfe/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/cfe/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-lib-y					= setup.o
-lib-$(CONFIG_SIBYTE_CFE_CONSOLE)	+= console.o
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/cfe/setup.c linux-libre-2.6.31-gnu/arch/mips/sibyte/cfe/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/cfe/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/cfe/setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,344 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom 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.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/linkage.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/bootmem.h>
-#include <linux/pm.h>
-#include <linux/smp.h>
-
-#include <asm/bootinfo.h>
-#include <asm/reboot.h>
-#include <asm/sibyte/board.h>
-#include <asm/smp-ops.h>
-
-#include <asm/fw/cfe/cfe_api.h>
-#include <asm/fw/cfe/cfe_error.h>
-
-/* Max ram addressable in 32-bit segments */
-#ifdef CONFIG_64BIT
-#define MAX_RAM_SIZE (~0ULL)
-#else
-#ifdef CONFIG_HIGHMEM
-#ifdef CONFIG_64BIT_PHYS_ADDR
-#define MAX_RAM_SIZE (~0ULL)
-#else
-#define MAX_RAM_SIZE (0xffffffffULL)
-#endif
-#else
-#define MAX_RAM_SIZE (0x1fffffffULL)
-#endif
-#endif
-
-#define SIBYTE_MAX_MEM_REGIONS 8
-phys_t board_mem_region_addrs[SIBYTE_MAX_MEM_REGIONS];
-phys_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS];
-unsigned int board_mem_region_count;
-
-int cfe_cons_handle;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned long initrd_start, initrd_end;
-#endif
-
-static void __noreturn cfe_linux_exit(void *arg)
-{
-	int warm = *(int *)arg;
-
-	if (smp_processor_id()) {
-		static int reboot_smp;
-
-		/* Don't repeat the process from another CPU */
-		if (!reboot_smp) {
-			/* Get CPU 0 to do the cfe_exit */
-			reboot_smp = 1;
-			smp_call_function(cfe_linux_exit, arg, 0);
-		}
-	} else {
-		printk("Passing control back to CFE...\n");
-		cfe_exit(warm, 0);
-		printk("cfe_exit returned??\n");
-	}
-	while (1);
-}
-
-static void __noreturn cfe_linux_restart(char *command)
-{
-	static const int zero;
-
-	cfe_linux_exit((void *)&zero);
-}
-
-static void __noreturn cfe_linux_halt(void)
-{
-	static const int one = 1;
-
-	cfe_linux_exit((void *)&one);
-}
-
-static __init void prom_meminit(void)
-{
-	u64 addr, size, type; /* regardless of 64BIT_PHYS_ADDR */
-	int mem_flags = 0;
-	unsigned int idx;
-	int rd_flag;
-#ifdef CONFIG_BLK_DEV_INITRD
-	unsigned long initrd_pstart;
-	unsigned long initrd_pend;
-
-	initrd_pstart = CPHYSADDR(initrd_start);
-	initrd_pend = CPHYSADDR(initrd_end);
-	if (initrd_start &&
-	    ((initrd_pstart > MAX_RAM_SIZE)
-	     || (initrd_pend > MAX_RAM_SIZE))) {
-		panic("initrd out of addressable memory");
-	}
-
-#endif /* INITRD */
-
-	for (idx = 0; cfe_enummem(idx, mem_flags, &addr, &size, &type) != CFE_ERR_NOMORE;
-	     idx++) {
-		rd_flag = 0;
-		if (type == CFE_MI_AVAILABLE) {
-			/*
-			 * See if this block contains (any portion of) the
-			 * ramdisk
-			 */
-#ifdef CONFIG_BLK_DEV_INITRD
-			if (initrd_start) {
-				if ((initrd_pstart > addr) &&
-				    (initrd_pstart < (addr + size))) {
-					add_memory_region(addr,
-					                  initrd_pstart - addr,
-					                  BOOT_MEM_RAM);
-					rd_flag = 1;
-				}
-				if ((initrd_pend > addr) &&
-				    (initrd_pend < (addr + size))) {
-					add_memory_region(initrd_pend,
-						(addr + size) - initrd_pend,
-						 BOOT_MEM_RAM);
-					rd_flag = 1;
-				}
-			}
-#endif
-			if (!rd_flag) {
-				if (addr > MAX_RAM_SIZE)
-					continue;
-				if (addr+size > MAX_RAM_SIZE)
-					size = MAX_RAM_SIZE - (addr+size) + 1;
-				/*
-				 * memcpy/__copy_user prefetch, which
-				 * will cause a bus error for
-				 * KSEG/KUSEG addrs not backed by RAM.
-				 * Hence, reserve some padding for the
-				 * prefetch distance.
-				 */
-				if (size > 512)
-					size -= 512;
-				add_memory_region(addr, size, BOOT_MEM_RAM);
-			}
-			board_mem_region_addrs[board_mem_region_count] = addr;
-			board_mem_region_sizes[board_mem_region_count] = size;
-			board_mem_region_count++;
-			if (board_mem_region_count ==
-			    SIBYTE_MAX_MEM_REGIONS) {
-				/*
-				 * Too many regions.  Need to configure more
-				 */
-				while(1);
-			}
-		}
-	}
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start) {
-		add_memory_region(initrd_pstart, initrd_pend - initrd_pstart,
-				  BOOT_MEM_RESERVED);
-	}
-#endif
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-static int __init initrd_setup(char *str)
-{
-	char rdarg[64];
-	int idx;
-	char *tmp, *endptr;
-	unsigned long initrd_size;
-
-	/* Make a copy of the initrd argument so we can smash it up here */
-	for (idx = 0; idx < sizeof(rdarg)-1; idx++) {
-		if (!str[idx] || (str[idx] == ' ')) break;
-		rdarg[idx] = str[idx];
-	}
-
-	rdarg[idx] = 0;
-	str = rdarg;
-
-	/*
-	 *Initrd location comes in the form "<hex size of ramdisk in bytes>@<location in memory>"
-	 *  e.g. initrd=3abfd@80010000.  This is set up by the loader.
-	 */
-	for (tmp = str; *tmp != '@'; tmp++) {
-		if (!*tmp) {
-			goto fail;
-		}
-	}
-	*tmp = 0;
-	tmp++;
-	if (!*tmp) {
-		goto fail;
-	}
-	initrd_size = simple_strtoul(str, &endptr, 16);
-	if (*endptr) {
-		*(tmp-1) = '@';
-		goto fail;
-	}
-	*(tmp-1) = '@';
-	initrd_start = simple_strtoul(tmp, &endptr, 16);
-	if (*endptr) {
-		goto fail;
-	}
-	initrd_end = initrd_start + initrd_size;
-	printk("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
-	return 1;
- fail:
-	printk("Bad initrd argument.  Disabling initrd\n");
-	initrd_start = 0;
-	initrd_end = 0;
-	return 1;
-}
-
-#endif
-
-extern struct plat_smp_ops sb_smp_ops;
-extern struct plat_smp_ops bcm1480_smp_ops;
-
-/*
- * prom_init is called just after the cpu type is determined, from setup_arch()
- */
-void __init prom_init(void)
-{
-	uint64_t cfe_ept, cfe_handle;
-	unsigned int cfe_eptseal;
-	int argc = fw_arg0;
-	char **envp = (char **) fw_arg2;
-	int *prom_vec = (int *) fw_arg3;
-
-	_machine_restart   = cfe_linux_restart;
-	_machine_halt      = cfe_linux_halt;
-	pm_power_off = cfe_linux_halt;
-
-	/*
-	 * Check if a loader was used; if NOT, the 4 arguments are
-	 * what CFE gives us (handle, 0, EPT and EPTSEAL)
-	 */
-	if (argc < 0) {
-		cfe_handle = (uint64_t)(long)argc;
-		cfe_ept = (long)envp;
-		cfe_eptseal = (uint32_t)(unsigned long)prom_vec;
-	} else {
-		if ((int32_t)(long)prom_vec < 0) {
-			/*
-			 * Old loader; all it gives us is the handle,
-			 * so use the "known" entrypoint and assume
-			 * the seal.
-			 */
-			cfe_handle = (uint64_t)(long)prom_vec;
-			cfe_ept = (uint64_t)((int32_t)0x9fc00500);
-			cfe_eptseal = CFE_EPTSEAL;
-		} else {
-			/*
-			 * Newer loaders bundle the handle/ept/eptseal
-			 * Note: prom_vec is in the loader's useg
-			 * which is still alive in the TLB.
-			 */
-			cfe_handle = (uint64_t)((int32_t *)prom_vec)[0];
-			cfe_ept = (uint64_t)((int32_t *)prom_vec)[2];
-			cfe_eptseal = (unsigned int)((uint32_t *)prom_vec)[3];
-		}
-	}
-	if (cfe_eptseal != CFE_EPTSEAL) {
-		/* too early for panic to do any good */
-		printk("CFE's entrypoint seal doesn't match. Spinning.");
-		while (1) ;
-	}
-	cfe_init(cfe_handle, cfe_ept);
-	/*
-	 * Get the handle for (at least) prom_putchar, possibly for
-	 * boot console
-	 */
-	cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
-	if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) {
-		if (argc >= 0) {
-			/* The loader should have set the command line */
-			/* too early for panic to do any good */
-			printk("LINUX_CMDLINE not defined in cfe.");
-			while (1) ;
-		}
-	}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	{
-		char *ptr;
-		/* Need to find out early whether we've got an initrd.  So scan
-		   the list looking now */
-		for (ptr = arcs_cmdline; *ptr; ptr++) {
-			while (*ptr == ' ') {
-				ptr++;
-			}
-			if (!strncmp(ptr, "initrd=", 7)) {
-				initrd_setup(ptr+7);
-				break;
-			} else {
-				while (*ptr && (*ptr != ' ')) {
-					ptr++;
-				}
-			}
-		}
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	/* Not sure this is needed, but it's the safe way. */
-	arcs_cmdline[CL_SIZE-1] = 0;
-
-	prom_meminit();
-
-#if defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250)
-	register_smp_ops(&sb_smp_ops);
-#endif
-#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
-	register_smp_ops(&bcm1480_smp_ops);
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-	/* Not sure what I'm supposed to do here.  Nothing, I think */
-}
-
-void prom_putchar(char c)
-{
-	int ret;
-
-	while ((ret = cfe_write(cfe_cons_handle, &c, 1)) == 0)
-		;
-}
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/common/cfe.c linux-libre-2.6.31-gnu/arch/mips/sibyte/common/cfe.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/common/cfe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/common/cfe.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/blkdev.h>
+#include <linux/bootmem.h>
+#include <linux/pm.h>
+#include <linux/smp.h>
+
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/sibyte/board.h>
+#include <asm/smp-ops.h>
+
+#include <asm/fw/cfe/cfe_api.h>
+#include <asm/fw/cfe/cfe_error.h>
+
+/* Max ram addressable in 32-bit segments */
+#ifdef CONFIG_64BIT
+#define MAX_RAM_SIZE (~0ULL)
+#else
+#ifdef CONFIG_HIGHMEM
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define MAX_RAM_SIZE (~0ULL)
+#else
+#define MAX_RAM_SIZE (0xffffffffULL)
+#endif
+#else
+#define MAX_RAM_SIZE (0x1fffffffULL)
+#endif
+#endif
+
+#define SIBYTE_MAX_MEM_REGIONS 8
+phys_t board_mem_region_addrs[SIBYTE_MAX_MEM_REGIONS];
+phys_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS];
+unsigned int board_mem_region_count;
+
+int cfe_cons_handle;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern unsigned long initrd_start, initrd_end;
+#endif
+
+static void __noreturn cfe_linux_exit(void *arg)
+{
+	int warm = *(int *)arg;
+
+	if (smp_processor_id()) {
+		static int reboot_smp;
+
+		/* Don't repeat the process from another CPU */
+		if (!reboot_smp) {
+			/* Get CPU 0 to do the cfe_exit */
+			reboot_smp = 1;
+			smp_call_function(cfe_linux_exit, arg, 0);
+		}
+	} else {
+		printk("Passing control back to CFE...\n");
+		cfe_exit(warm, 0);
+		printk("cfe_exit returned??\n");
+	}
+	while (1);
+}
+
+static void __noreturn cfe_linux_restart(char *command)
+{
+	static const int zero;
+
+	cfe_linux_exit((void *)&zero);
+}
+
+static void __noreturn cfe_linux_halt(void)
+{
+	static const int one = 1;
+
+	cfe_linux_exit((void *)&one);
+}
+
+static __init void prom_meminit(void)
+{
+	u64 addr, size, type; /* regardless of 64BIT_PHYS_ADDR */
+	int mem_flags = 0;
+	unsigned int idx;
+	int rd_flag;
+#ifdef CONFIG_BLK_DEV_INITRD
+	unsigned long initrd_pstart;
+	unsigned long initrd_pend;
+
+	initrd_pstart = CPHYSADDR(initrd_start);
+	initrd_pend = CPHYSADDR(initrd_end);
+	if (initrd_start &&
+	    ((initrd_pstart > MAX_RAM_SIZE)
+	     || (initrd_pend > MAX_RAM_SIZE))) {
+		panic("initrd out of addressable memory");
+	}
+
+#endif /* INITRD */
+
+	for (idx = 0; cfe_enummem(idx, mem_flags, &addr, &size, &type) != CFE_ERR_NOMORE;
+	     idx++) {
+		rd_flag = 0;
+		if (type == CFE_MI_AVAILABLE) {
+			/*
+			 * See if this block contains (any portion of) the
+			 * ramdisk
+			 */
+#ifdef CONFIG_BLK_DEV_INITRD
+			if (initrd_start) {
+				if ((initrd_pstart > addr) &&
+				    (initrd_pstart < (addr + size))) {
+					add_memory_region(addr,
+					                  initrd_pstart - addr,
+					                  BOOT_MEM_RAM);
+					rd_flag = 1;
+				}
+				if ((initrd_pend > addr) &&
+				    (initrd_pend < (addr + size))) {
+					add_memory_region(initrd_pend,
+						(addr + size) - initrd_pend,
+						 BOOT_MEM_RAM);
+					rd_flag = 1;
+				}
+			}
+#endif
+			if (!rd_flag) {
+				if (addr > MAX_RAM_SIZE)
+					continue;
+				if (addr+size > MAX_RAM_SIZE)
+					size = MAX_RAM_SIZE - (addr+size) + 1;
+				/*
+				 * memcpy/__copy_user prefetch, which
+				 * will cause a bus error for
+				 * KSEG/KUSEG addrs not backed by RAM.
+				 * Hence, reserve some padding for the
+				 * prefetch distance.
+				 */
+				if (size > 512)
+					size -= 512;
+				add_memory_region(addr, size, BOOT_MEM_RAM);
+			}
+			board_mem_region_addrs[board_mem_region_count] = addr;
+			board_mem_region_sizes[board_mem_region_count] = size;
+			board_mem_region_count++;
+			if (board_mem_region_count ==
+			    SIBYTE_MAX_MEM_REGIONS) {
+				/*
+				 * Too many regions.  Need to configure more
+				 */
+				while(1);
+			}
+		}
+	}
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start) {
+		add_memory_region(initrd_pstart, initrd_pend - initrd_pstart,
+				  BOOT_MEM_RESERVED);
+	}
+#endif
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static int __init initrd_setup(char *str)
+{
+	char rdarg[64];
+	int idx;
+	char *tmp, *endptr;
+	unsigned long initrd_size;
+
+	/* Make a copy of the initrd argument so we can smash it up here */
+	for (idx = 0; idx < sizeof(rdarg)-1; idx++) {
+		if (!str[idx] || (str[idx] == ' ')) break;
+		rdarg[idx] = str[idx];
+	}
+
+	rdarg[idx] = 0;
+	str = rdarg;
+
+	/*
+	 *Initrd location comes in the form "<hex size of ramdisk in bytes>@<location in memory>"
+	 *  e.g. initrd=3abfd@80010000.  This is set up by the loader.
+	 */
+	for (tmp = str; *tmp != '@'; tmp++) {
+		if (!*tmp) {
+			goto fail;
+		}
+	}
+	*tmp = 0;
+	tmp++;
+	if (!*tmp) {
+		goto fail;
+	}
+	initrd_size = simple_strtoul(str, &endptr, 16);
+	if (*endptr) {
+		*(tmp-1) = '@';
+		goto fail;
+	}
+	*(tmp-1) = '@';
+	initrd_start = simple_strtoul(tmp, &endptr, 16);
+	if (*endptr) {
+		goto fail;
+	}
+	initrd_end = initrd_start + initrd_size;
+	printk("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
+	return 1;
+ fail:
+	printk("Bad initrd argument.  Disabling initrd\n");
+	initrd_start = 0;
+	initrd_end = 0;
+	return 1;
+}
+
+#endif
+
+extern struct plat_smp_ops sb_smp_ops;
+extern struct plat_smp_ops bcm1480_smp_ops;
+
+/*
+ * prom_init is called just after the cpu type is determined, from setup_arch()
+ */
+void __init prom_init(void)
+{
+	uint64_t cfe_ept, cfe_handle;
+	unsigned int cfe_eptseal;
+	int argc = fw_arg0;
+	char **envp = (char **) fw_arg2;
+	int *prom_vec = (int *) fw_arg3;
+
+	_machine_restart   = cfe_linux_restart;
+	_machine_halt      = cfe_linux_halt;
+	pm_power_off = cfe_linux_halt;
+
+	/*
+	 * Check if a loader was used; if NOT, the 4 arguments are
+	 * what CFE gives us (handle, 0, EPT and EPTSEAL)
+	 */
+	if (argc < 0) {
+		cfe_handle = (uint64_t)(long)argc;
+		cfe_ept = (long)envp;
+		cfe_eptseal = (uint32_t)(unsigned long)prom_vec;
+	} else {
+		if ((int32_t)(long)prom_vec < 0) {
+			/*
+			 * Old loader; all it gives us is the handle,
+			 * so use the "known" entrypoint and assume
+			 * the seal.
+			 */
+			cfe_handle = (uint64_t)(long)prom_vec;
+			cfe_ept = (uint64_t)((int32_t)0x9fc00500);
+			cfe_eptseal = CFE_EPTSEAL;
+		} else {
+			/*
+			 * Newer loaders bundle the handle/ept/eptseal
+			 * Note: prom_vec is in the loader's useg
+			 * which is still alive in the TLB.
+			 */
+			cfe_handle = (uint64_t)((int32_t *)prom_vec)[0];
+			cfe_ept = (uint64_t)((int32_t *)prom_vec)[2];
+			cfe_eptseal = (unsigned int)((uint32_t *)prom_vec)[3];
+		}
+	}
+	if (cfe_eptseal != CFE_EPTSEAL) {
+		/* too early for panic to do any good */
+		printk("CFE's entrypoint seal doesn't match. Spinning.");
+		while (1) ;
+	}
+	cfe_init(cfe_handle, cfe_ept);
+	/*
+	 * Get the handle for (at least) prom_putchar, possibly for
+	 * boot console
+	 */
+	cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
+	if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) {
+		if (argc >= 0) {
+			/* The loader should have set the command line */
+			/* too early for panic to do any good */
+			printk("LINUX_CMDLINE not defined in cfe.");
+			while (1) ;
+		}
+	}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	{
+		char *ptr;
+		/* Need to find out early whether we've got an initrd.  So scan
+		   the list looking now */
+		for (ptr = arcs_cmdline; *ptr; ptr++) {
+			while (*ptr == ' ') {
+				ptr++;
+			}
+			if (!strncmp(ptr, "initrd=", 7)) {
+				initrd_setup(ptr+7);
+				break;
+			} else {
+				while (*ptr && (*ptr != ' ')) {
+					ptr++;
+				}
+			}
+		}
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Not sure this is needed, but it's the safe way. */
+	arcs_cmdline[CL_SIZE-1] = 0;
+
+	prom_meminit();
+
+#if defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250)
+	register_smp_ops(&sb_smp_ops);
+#endif
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+	register_smp_ops(&bcm1480_smp_ops);
+#endif
+}
+
+void __init prom_free_prom_memory(void)
+{
+	/* Not sure what I'm supposed to do here.  Nothing, I think */
+}
+
+void prom_putchar(char c)
+{
+	int ret;
+
+	while ((ret = cfe_write(cfe_cons_handle, &c, 1)) == 0)
+		;
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/common/cfe_console.c linux-libre-2.6.31-gnu/arch/mips/sibyte/common/cfe_console.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/common/cfe_console.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/common/cfe_console.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,80 @@
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/console.h>
+
+#include <asm/sibyte/board.h>
+
+#include <asm/fw/cfe/cfe_api.h>
+#include <asm/fw/cfe/cfe_error.h>
+
+extern int cfe_cons_handle;
+
+static void cfe_console_write(struct console *cons, const char *str,
+		       unsigned int count)
+{
+	int i, last, written;
+
+	for (i=0, last=0; i<count; i++) {
+		if (!str[i])
+			/* XXXKW can/should this ever happen? */
+			return;
+		if (str[i] == '\n') {
+			do {
+				written = cfe_write(cfe_cons_handle, &str[last], i-last);
+				if (written < 0)
+					;
+				last += written;
+			} while (last < i);
+			while (cfe_write(cfe_cons_handle, "\r", 1) <= 0)
+				;
+		}
+	}
+	if (last != count) {
+		do {
+			written = cfe_write(cfe_cons_handle, &str[last], count-last);
+			if (written < 0)
+				;
+			last += written;
+		} while (last < count);
+	}
+
+}
+
+static int cfe_console_setup(struct console *cons, char *str)
+{
+	char consdev[32];
+	/* XXXKW think about interaction with 'console=' cmdline arg */
+	/* If none of the console options are configured, the build will break. */
+	if (cfe_getenv("BOOT_CONSOLE", consdev, 32) >= 0) {
+#ifdef CONFIG_SERIAL_SB1250_DUART
+		if (!strcmp(consdev, "uart0")) {
+			setleds("u0cn");
+		} else if (!strcmp(consdev, "uart1")) {
+			setleds("u1cn");
+		} else
+#endif
+#ifdef CONFIG_VGA_CONSOLE
+		       if (!strcmp(consdev, "pcconsole0")) {
+				setleds("pccn");
+		} else
+#endif
+			return -ENODEV;
+	}
+	return 0;
+}
+
+static struct console sb1250_cfe_cons = {
+	.name		= "cfe",
+	.write		= cfe_console_write,
+	.setup		= cfe_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+};
+
+static int __init sb1250_cfe_console_init(void)
+{
+	register_console(&sb1250_cfe_cons);
+	return 0;
+}
+
+console_initcall(sb1250_cfe_console_init);
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/common/Makefile linux-libre-2.6.31-gnu/arch/mips/sibyte/common/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/common/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/common/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
-obj-y :=
-
+obj-y := cfe.o
+obj-$(CONFIG_SIBYTE_CFE_CONSOLE)	+= cfe_console.o
 obj-$(CONFIG_SIBYTE_TBPROF)		+= sb_tbprof.o
 
 EXTRA_CFLAGS += -Werror
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/Kconfig linux-libre-2.6.31-gnu/arch/mips/sibyte/Kconfig
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -75,6 +75,8 @@
 	select SWAP_IO_SPACE
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
+	select CFE
+	select SYS_HAS_EARLY_PRINTK
 
 choice
 	prompt "SiByte SOC Stepping"
@@ -128,13 +130,6 @@
 	bool
 	select SIBYTE_HAS_LDT if PCI
 
-config SIMULATION
-	bool "Running under simulation"
-	depends on SIBYTE_SB1xxx_SOC
-	help
-	  Build a kernel suitable for running under the GDB simulator.
-	  Primarily adjusts the kernel's notion of time.
-
 config SB1_CEX_ALWAYS_FATAL
 	bool "All cache exceptions considered fatal (no recovery attempted)"
 	depends on SIBYTE_SB1xxx_SOC
@@ -143,34 +138,14 @@
 	bool "Stall (rather than panic) on fatal cache error"
 	depends on SIBYTE_SB1xxx_SOC
 
-config SIBYTE_CFE
-	bool "Booting from CFE"
-	depends on SIBYTE_SB1xxx_SOC
-	select CFE
-	select SYS_HAS_EARLY_PRINTK
-	help
-	  Make use of the CFE API for enumerating available memory,
-	  controlling secondary CPUs, and possibly console output.
-
 config SIBYTE_CFE_CONSOLE
 	bool "Use firmware console"
-	depends on SIBYTE_CFE
+	depends on SIBYTE_SB1xxx_SOC
 	help
 	  Use the CFE API's console write routines during boot.  Other console
 	  options (VT console, sb1250 duart console, etc.) should not be
 	  configured.
 
-config SIBYTE_STANDALONE
-	bool
-	depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
-	select SYS_HAS_EARLY_PRINTK
-	default y
-
-config SIBYTE_STANDALONE_RAM_SIZE
-	int "Memory size (in megabytes)"
-	depends on SIBYTE_STANDALONE
-	default "32"
-
 config SIBYTE_BUS_WATCHER
 	bool "Support for Bus Watcher statistics"
 	depends on SIBYTE_SB1xxx_SOC
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/sb1250/irq.c linux-libre-2.6.31-gnu/arch/mips/sibyte/sb1250/irq.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/sb1250/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/sb1250/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,7 @@
 static void disable_sb1250_irq(unsigned int irq);
 static void ack_sb1250_irq(unsigned int irq);
 #ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
+static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
 #endif
 
 #ifdef CONFIG_SIBYTE_HAS_LDT
@@ -103,7 +103,7 @@
 }
 
 #ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	int i = 0, old_cpu, cpu, int_on;
 	u64 cur_ints;
@@ -111,11 +111,6 @@
 
 	i = cpumask_first(mask);
 
-	if (cpumask_weight(mask) > 1) {
-		printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
-		return;
-	}
-
 	/* Convert logical CPU to physical CPU */
 	cpu = cpu_logical_map(i);
 
@@ -143,6 +138,8 @@
 					R_IMR_INTERRUPT_MASK));
 	}
 	spin_unlock_irqrestore(&sb1250_imr_lock, flags);
+
+	return 0;
 }
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/sb1250/Makefile linux-libre-2.6.31-gnu/arch/mips/sibyte/sb1250/Makefile
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/sb1250/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/sb1250/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,6 @@
 obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)			+= smp.o
-obj-$(CONFIG_SIBYTE_STANDALONE)		+= prom.o
 obj-$(CONFIG_SIBYTE_BUS_WATCHER)	+= bus_watcher.o
 
 EXTRA_CFLAGS += -Werror
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/sb1250/prom.c linux-libre-2.6.31-gnu/arch/mips/sibyte/sb1250/prom.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/sb1250/prom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/sb1250/prom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Broadcom 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.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/bootmem.h>
-#include <linux/smp.h>
-#include <linux/initrd.h>
-#include <linux/pm.h>
-
-#include <asm/bootinfo.h>
-#include <asm/reboot.h>
-
-#define MAX_RAM_SIZE ((CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - 1)
-
-static __init void prom_meminit(void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
-	unsigned long initrd_pstart;
-	unsigned long initrd_pend;
-
-	initrd_pstart = __pa(initrd_start);
-	initrd_pend = __pa(initrd_end);
-	if (initrd_start &&
-	    ((initrd_pstart > MAX_RAM_SIZE)
-	     || (initrd_pend > MAX_RAM_SIZE))) {
-		panic("initrd out of addressable memory");
-	}
-
-	add_memory_region(0, initrd_pstart,
-			  BOOT_MEM_RAM);
-	add_memory_region(initrd_pstart, initrd_pend - initrd_pstart,
-			  BOOT_MEM_RESERVED);
-	add_memory_region(initrd_pend,
-			  (CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - initrd_pend,
-			  BOOT_MEM_RAM);
-#else
-	add_memory_region(0, CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024,
-			  BOOT_MEM_RAM);
-#endif
-}
-
-void prom_cpu0_exit(void *unused)
-{
-        while (1) ;
-}
-
-static void prom_linux_exit(void)
-{
-#ifdef CONFIG_SMP
-	if (smp_processor_id()) {
-		smp_call_function(prom_cpu0_exit, NULL, 1);
-	}
-#endif
-	while(1);
-}
-
-/*
- * prom_init is called just after the cpu type is determined, from setup_arch()
- */
-void __init prom_init(void)
-{
-	_machine_restart   = (void (*)(char *))prom_linux_exit;
-	_machine_halt      = prom_linux_exit;
-	pm_power_off = prom_linux_exit;
-
-	strcpy(arcs_cmdline, "root=/dev/ram0 ");
-
-	prom_meminit();
-}
-
-void __init prom_free_prom_memory(void)
-{
-	/* Not sure what I'm supposed to do here.  Nothing, I think */
-}
-
-void prom_putchar(char c)
-{
-}
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/swarm/setup.c linux-libre-2.6.31-gnu/arch/mips/sibyte/swarm/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/swarm/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/swarm/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -136,20 +136,6 @@
 	if (m41t81_probe())
 		swarm_rtc_type = RTC_M4LT81;
 
-	printk("This kernel optimized for "
-#ifdef CONFIG_SIMULATION
-	       "simulation"
-#else
-	       "board"
-#endif
-	       " runs "
-#ifdef CONFIG_SIBYTE_CFE
-	       "with"
-#else
-	       "without"
-#endif
-	       " CFE\n");
-
 #ifdef CONFIG_VT
 	screen_info = (struct screen_info) {
 		0, 0,           /* orig-x, orig-y */
diff -druN linux-libre-2.6.30-gnu/arch/mips/sibyte/swarm/swarm-i2c.c linux-libre-2.6.31-gnu/arch/mips/sibyte/swarm/swarm-i2c.c
--- linux-libre-2.6.30-gnu/arch/mips/sibyte/swarm/swarm-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sibyte/swarm/swarm-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- *	arch/mips/sibyte/swarm/swarm-i2c.c
- *
  *	Broadcom BCM91250A (SWARM), etc. I2C platform setup.
  *
  *	Copyright (c) 2008  Maciej W. Rozycki
diff -druN linux-libre-2.6.30-gnu/arch/mips/sni/eisa.c linux-libre-2.6.31-gnu/arch/mips/sni/eisa.c
--- linux-libre-2.6.30-gnu/arch/mips/sni/eisa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sni/eisa.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,7 +38,7 @@
 	if (!r)
 		return r;
 
-	eisa_root_dev.dev.driver_data = &eisa_bus_root;
+	dev_set_drvdata(&eisa_root_dev.dev, &eisa_bus_root);
 
 	if (eisa_root_register(&eisa_bus_root)) {
 		/* A real bridge may have been registered before
diff -druN linux-libre-2.6.30-gnu/arch/mips/sni/time.c linux-libre-2.6.31-gnu/arch/mips/sni/time.c
--- linux-libre-2.6.30-gnu/arch/mips/sni/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/sni/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/clockchips.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/generic/mem_tx4927.c linux-libre-2.6.31-gnu/arch/mips/txx9/generic/mem_tx4927.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/generic/mem_tx4927.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/generic/mem_tx4927.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/txx9/generic/mem_tx4927.c
- *
  * common tx4927 memory interface
  *
  * Author: MontaVista Software, Inc.
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup.c linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/txx9/generic/setup.c
- *
  * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
  *	    and RBTX49xx patch from CELF patch archive.
  *
@@ -24,6 +22,7 @@
 #include <linux/serial_core.h>
 #include <linux/mtd/physmap.h>
 #include <linux/leds.h>
+#include <linux/sysdev.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/reboot.h>
@@ -33,6 +32,7 @@
 #include <asm/txx9/pci.h>
 #include <asm/txx9tmr.h>
 #include <asm/txx9/ndfmc.h>
+#include <asm/txx9/dmac.h>
 #ifdef CONFIG_CPU_TX49XX
 #include <asm/txx9/tx4938.h>
 #endif
@@ -821,3 +821,176 @@
 {
 }
 #endif /* CONFIG_LEDS_GPIO */
+
+void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq,
+			   const struct txx9dmac_platform_data *pdata)
+{
+#if defined(CONFIG_TXX9_DMAC) || defined(CONFIG_TXX9_DMAC_MODULE)
+	struct resource res[] = {
+		{
+			.start = baseaddr,
+			.end = baseaddr + 0x800 - 1,
+			.flags = IORESOURCE_MEM,
+#ifndef CONFIG_MACH_TX49XX
+		}, {
+			.start = irq,
+			.flags = IORESOURCE_IRQ,
+#endif
+		}
+	};
+#ifdef CONFIG_MACH_TX49XX
+	struct resource chan_res[] = {
+		{
+			.flags = IORESOURCE_IRQ,
+		}
+	};
+#endif
+	struct platform_device *pdev = platform_device_alloc("txx9dmac", id);
+	struct txx9dmac_chan_platform_data cpdata;
+	int i;
+
+	if (!pdev ||
+	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
+	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
+	    platform_device_add(pdev)) {
+		platform_device_put(pdev);
+		return;
+	}
+	memset(&cpdata, 0, sizeof(cpdata));
+	cpdata.dmac_dev = pdev;
+	for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) {
+#ifdef CONFIG_MACH_TX49XX
+		chan_res[0].start = irq + i;
+#endif
+		pdev = platform_device_alloc("txx9dmac-chan",
+					     id * TXX9_DMA_MAX_NR_CHANNELS + i);
+		if (!pdev ||
+#ifdef CONFIG_MACH_TX49XX
+		    platform_device_add_resources(pdev, chan_res,
+						  ARRAY_SIZE(chan_res)) ||
+#endif
+		    platform_device_add_data(pdev, &cpdata, sizeof(cpdata)) ||
+		    platform_device_add(pdev))
+			platform_device_put(pdev);
+	}
+#endif
+}
+
+void __init txx9_aclc_init(unsigned long baseaddr, int irq,
+			   unsigned int dmac_id,
+			   unsigned int dma_chan_out,
+			   unsigned int dma_chan_in)
+{
+#if defined(CONFIG_SND_SOC_TXX9ACLC) || \
+	defined(CONFIG_SND_SOC_TXX9ACLC_MODULE)
+	unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS;
+	struct resource res[] = {
+		{
+			.start = baseaddr,
+			.end = baseaddr + 0x100 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.name = "txx9dmac-chan",
+			.start = dma_base + dma_chan_out,
+			.flags = IORESOURCE_DMA,
+		}, {
+			.name = "txx9dmac-chan",
+			.start = dma_base + dma_chan_in,
+			.flags = IORESOURCE_DMA,
+		}
+	};
+	struct platform_device *pdev =
+		platform_device_alloc("txx9aclc-ac97", -1);
+
+	if (!pdev ||
+	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+#endif
+}
+
+static struct sysdev_class txx9_sramc_sysdev_class;
+
+struct txx9_sramc_sysdev {
+	struct sys_device dev;
+	struct bin_attribute bindata_attr;
+	void __iomem *base;
+};
+
+static ssize_t txx9_sram_read(struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t pos, size_t size)
+{
+	struct txx9_sramc_sysdev *dev = bin_attr->private;
+	size_t ramsize = bin_attr->size;
+
+	if (pos >= ramsize)
+		return 0;
+	if (pos + size > ramsize)
+		size = ramsize - pos;
+	memcpy_fromio(buf, dev->base + pos, size);
+	return size;
+}
+
+static ssize_t txx9_sram_write(struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t pos, size_t size)
+{
+	struct txx9_sramc_sysdev *dev = bin_attr->private;
+	size_t ramsize = bin_attr->size;
+
+	if (pos >= ramsize)
+		return 0;
+	if (pos + size > ramsize)
+		size = ramsize - pos;
+	memcpy_toio(dev->base + pos, buf, size);
+	return size;
+}
+
+void __init txx9_sramc_init(struct resource *r)
+{
+	struct txx9_sramc_sysdev *dev;
+	size_t size;
+	int err;
+
+	if (!txx9_sramc_sysdev_class.name) {
+		txx9_sramc_sysdev_class.name = "txx9_sram";
+		err = sysdev_class_register(&txx9_sramc_sysdev_class);
+		if (err) {
+			txx9_sramc_sysdev_class.name = NULL;
+			return;
+		}
+	}
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return;
+	size = resource_size(r);
+	dev->base = ioremap(r->start, size);
+	if (!dev->base)
+		goto exit;
+	dev->dev.cls = &txx9_sramc_sysdev_class;
+	dev->bindata_attr.attr.name = "bindata";
+	dev->bindata_attr.attr.mode = S_IRUSR | S_IWUSR;
+	dev->bindata_attr.read = txx9_sram_read;
+	dev->bindata_attr.write = txx9_sram_write;
+	dev->bindata_attr.size = size;
+	dev->bindata_attr.private = dev;
+	err = sysdev_register(&dev->dev);
+	if (err)
+		goto exit;
+	err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
+	if (err) {
+		sysdev_unregister(&dev->dev);
+		goto exit;
+	}
+	return;
+exit:
+	if (dev) {
+		if (dev->base)
+			iounmap(dev->base);
+		kfree(dev);
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup_tx4927.c linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup_tx4927.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup_tx4927.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup_tx4927.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <asm/txx9tmr.h>
 #include <asm/txx9pio.h>
 #include <asm/txx9/generic.h>
+#include <asm/txx9/dmac.h>
 #include <asm/txx9/tx4927.h>
 
 static void __init tx4927_wdr_init(void)
@@ -253,6 +254,60 @@
 	txx9_physmap_flash_init(ch, start, size, &pdata);
 }
 
+void __init tx4927_dmac_init(int memcpy_chan)
+{
+	struct txx9dmac_platform_data plat_data = {
+		.memcpy_chan = memcpy_chan,
+		.have_64bit_regs = true,
+	};
+
+	txx9_dmac_init(0, TX4927_DMA_REG & 0xfffffffffULL,
+		       TXX9_IRQ_BASE + TX4927_IR_DMA(0), &plat_data);
+}
+
+void __init tx4927_aclc_init(unsigned int dma_chan_out,
+			     unsigned int dma_chan_in)
+{
+	u64 pcfg = __raw_readq(&tx4927_ccfgptr->pcfg);
+	__u64 dmasel_mask = 0, dmasel = 0;
+	unsigned long flags;
+
+	if (!(pcfg & TX4927_PCFG_SEL2))
+		return;
+	/* setup DMASEL (playback:ACLC ch0, capture:ACLC ch1) */
+	switch (dma_chan_out) {
+	case 0:
+		dmasel_mask |= TX4927_PCFG_DMASEL0_MASK;
+		dmasel |= TX4927_PCFG_DMASEL0_ACL0;
+		break;
+	case 2:
+		dmasel_mask |= TX4927_PCFG_DMASEL2_MASK;
+		dmasel |= TX4927_PCFG_DMASEL2_ACL0;
+		break;
+	default:
+		return;
+	}
+	switch (dma_chan_in) {
+	case 1:
+		dmasel_mask |= TX4927_PCFG_DMASEL1_MASK;
+		dmasel |= TX4927_PCFG_DMASEL1_ACL1;
+		break;
+	case 3:
+		dmasel_mask |= TX4927_PCFG_DMASEL3_MASK;
+		dmasel |= TX4927_PCFG_DMASEL3_ACL1;
+		break;
+	default:
+		return;
+	}
+	local_irq_save(flags);
+	txx9_clear64(&tx4927_ccfgptr->pcfg, dmasel_mask);
+	txx9_set64(&tx4927_ccfgptr->pcfg, dmasel);
+	local_irq_restore(flags);
+	txx9_aclc_init(TX4927_ACLC_REG & 0xfffffffffULL,
+		       TXX9_IRQ_BASE + TX4927_IR_ACLC,
+		       0, dma_chan_out, dma_chan_in);
+}
+
 static void __init tx4927_stop_unused_modules(void)
 {
 	__u64 pcfg, rst = 0, ckd = 0;
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup_tx4938.c linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup_tx4938.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup_tx4938.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup_tx4938.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 #include <asm/txx9pio.h>
 #include <asm/txx9/generic.h>
 #include <asm/txx9/ndfmc.h>
+#include <asm/txx9/dmac.h>
 #include <asm/txx9/tx4938.h>
 
 static void __init tx4938_wdr_init(void)
@@ -239,11 +240,6 @@
 	for (i = 0; i < TX4938_NR_TMR; i++)
 		txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL);
 
-	/* DMA */
-	for (i = 0; i < 2; i++)
-		____raw_writeq(TX4938_DMA_MCR_MSTEN,
-			       (void __iomem *)(TX4938_DMA_REG(i) + 0x50));
-
 	/* PIO */
 	txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, TX4938_NUM_PIO);
 	__raw_writel(0, &tx4938_pioptr->maskcpu);
@@ -403,6 +399,38 @@
 		txx9_ndfmc_init(baseaddr, &plat_data);
 }
 
+void __init tx4938_dmac_init(int memcpy_chan0, int memcpy_chan1)
+{
+	struct txx9dmac_platform_data plat_data = {
+		.have_64bit_regs = true,
+	};
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0;
+		txx9_dmac_init(i, TX4938_DMA_REG(i) & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4938_IR_DMA(i, 0),
+			       &plat_data);
+	}
+}
+
+void __init tx4938_aclc_init(void)
+{
+	u64 pcfg = __raw_readq(&tx4938_ccfgptr->pcfg);
+
+	if ((pcfg & TX4938_PCFG_SEL2) &&
+	    !(pcfg & TX4938_PCFG_ETH0_SEL))
+		txx9_aclc_init(TX4938_ACLC_REG & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4938_IR_ACLC,
+			       1, 0, 1);
+}
+
+void __init tx4938_sramc_init(void)
+{
+	if (tx4938_sram_resource.start)
+		txx9_sramc_init(&tx4938_sram_resource);
+}
+
 static void __init tx4938_stop_unused_modules(void)
 {
 	__u64 pcfg, rst = 0, ckd = 0;
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup_tx4939.c linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup_tx4939.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/generic/setup_tx4939.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/generic/setup_tx4939.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
 #include <asm/txx9tmr.h>
 #include <asm/txx9/generic.h>
 #include <asm/txx9/ndfmc.h>
+#include <asm/txx9/dmac.h>
 #include <asm/txx9/tx4939.h>
 
 static void __init tx4939_wdr_init(void)
@@ -259,11 +260,6 @@
 	for (i = 0; i < TX4939_NR_TMR; i++)
 		txx9_tmr_init(TX4939_TMR_REG(i) & 0xfffffffffULL);
 
-	/* DMA */
-	for (i = 0; i < 2; i++)
-		____raw_writeq(TX4938_DMA_MCR_MSTEN,
-			       (void __iomem *)(TX4939_DMA_REG(i) + 0x50));
-
 	/* set PCIC1 reset (required to prevent hangup on BIST) */
 	txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST);
 	pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg);
@@ -474,6 +470,53 @@
 	txx9_ndfmc_init(TX4939_NDFMC_REG & 0xfffffffffULL, &plat_data);
 }
 
+void __init tx4939_dmac_init(int memcpy_chan0, int memcpy_chan1)
+{
+	struct txx9dmac_platform_data plat_data = {
+		.have_64bit_regs = true,
+	};
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0;
+		txx9_dmac_init(i, TX4939_DMA_REG(i) & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4939_IR_DMA(i, 0),
+			       &plat_data);
+	}
+}
+
+void __init tx4939_aclc_init(void)
+{
+	u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg);
+
+	if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_ACLC)
+		txx9_aclc_init(TX4939_ACLC_REG & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4939_IR_ACLC, 1, 0, 1);
+}
+
+void __init tx4939_sramc_init(void)
+{
+	if (tx4939_sram_resource.start)
+		txx9_sramc_init(&tx4939_sram_resource);
+}
+
+void __init tx4939_rng_init(void)
+{
+	static struct resource res = {
+		.start = TX4939_RNG_REG & 0xfffffffffULL,
+		.end = (TX4939_RNG_REG & 0xfffffffffULL) + 0x30 - 1,
+		.flags = IORESOURCE_MEM,
+	};
+	static struct platform_device pdev = {
+		.name = "tx4939-rng",
+		.id = -1,
+		.num_resources = 1,
+		.resource = &res,
+	};
+
+	platform_device_register(&pdev);
+}
+
 static void __init tx4939_stop_unused_modules(void)
 {
 	__u64 pcfg, rst = 0, ckd = 0;
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/Kconfig linux-libre-2.6.31-gnu/arch/mips/txx9/Kconfig
--- linux-libre-2.6.30-gnu/arch/mips/txx9/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -69,6 +69,7 @@
 	select IRQ_TXX9
 	select PCI_TX4927
 	select GPIO_TXX9
+	select HAS_TXX9_ACLC
 
 config SOC_TX4938
 	bool
@@ -78,6 +79,7 @@
 	select IRQ_TXX9
 	select PCI_TX4927
 	select GPIO_TXX9
+	select HAS_TXX9_ACLC
 
 config SOC_TX4939
 	bool
@@ -85,6 +87,7 @@
 	select HAS_TXX9_SERIAL
 	select HW_HAS_PCI
 	select PCI_TX4927
+	select HAS_TXX9_ACLC
 
 config TXX9_7SEGLED
 	bool
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/rbtx4927/setup.c linux-libre-2.6.31-gnu/arch/mips/txx9/rbtx4927/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/rbtx4927/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/rbtx4927/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -337,6 +337,14 @@
 	rbtx4927_ne_init();
 	tx4927_wdt_init();
 	rbtx4927_mtd_init();
+	if (TX4927_REV_PCODE() == 0x4927) {
+		tx4927_dmac_init(2);
+		tx4927_aclc_init(0, 1);
+	} else {
+		tx4938_dmac_init(0, 2);
+		tx4938_aclc_init();
+	}
+	platform_device_register_simple("txx9aclc-generic", -1, NULL, 0);
 	txx9_iocled_init(RBTX4927_LED_ADDR - IO_BASE, -1, 3, 1, "green", NULL);
 	rbtx4927_gpioled_init();
 }
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/rbtx4938/setup.c linux-libre-2.6.31-gnu/arch/mips/txx9/rbtx4938/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/rbtx4938/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/rbtx4938/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -355,6 +355,10 @@
 	/* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */
 	tx4938_ndfmc_init(10, 35);
 	tx4938_ata_init(RBTX4938_IRQ_IOC_ATA, 0, 1);
+	tx4938_dmac_init(0, 2);
+	tx4938_aclc_init();
+	platform_device_register_simple("txx9aclc-generic", -1, NULL, 0);
+	tx4938_sramc_init();
 	txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mips/txx9/rbtx4939/setup.c linux-libre-2.6.31-gnu/arch/mips/txx9/rbtx4939/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/txx9/rbtx4939/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/txx9/rbtx4939/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -498,6 +498,11 @@
 	tx4939_wdt_init();
 	tx4939_ata_init();
 	tx4939_rtc_init();
+	tx4939_dmac_init(0, 2);
+	tx4939_aclc_init();
+	platform_device_register_simple("txx9aclc-generic", -1, NULL, 0);
+	tx4939_sramc_init();
+	tx4939_rng_init();
 }
 
 static void __init rbtx4939_setup(void)
@@ -507,10 +512,10 @@
 	rbtx4939_ebusc_setup();
 	/* always enable ATA0 */
 	txx9_set64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_ATA0MODE);
-	rbtx4939_update_ioc_pen();
 	if (txx9_master_clock == 0)
 		txx9_master_clock = 20000000;
 	tx4939_setup();
+	rbtx4939_update_ioc_pen();
 #ifdef HAVE_RBTX4939_IOSWAB
 	ioswabw = rbtx4939_ioswabw;
 	__mem_ioswabw = rbtx4939_mem_ioswabw;
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/casio-e55/setup.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/casio-e55/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/casio-e55/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/casio-e55/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
  *
- *  Copyright (C) 2002-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2006  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/bcu.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/bcu.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/bcu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/bcu.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,8 @@
  *  bcu.c, Bus Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@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
@@ -21,11 +21,11 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Added support for NEC VR4133.
  */
 #include <linux/kernel.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/cmu.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/cmu.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/cmu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/cmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,8 @@
  *  cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copuright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copuright (C) 2003-2005  Yoichi Yuasa <yuasa@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
@@ -21,11 +21,11 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Added support for NEC VR4133.
  */
 #include <linux/init.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/giu.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/giu.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/giu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/giu.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series GIU platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/icu.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/icu.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/icu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/icu.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,8 @@
  *  icu.c, Interrupt Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2006  Yoichi Yuasa <yuasa@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
@@ -21,11 +21,11 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Coped with INTASSIGN of NEC VR4133.
  */
 #include <linux/errno.h>
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/init.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/init.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  init.c, Common initialization routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2008  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/irq.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/irq.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Interrupt handing routines for NEC VR4100 series.
  *
- *  Copyright (C) 2005-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/pmu.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/pmu.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/pmu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  pmu.c, Power Management Unit routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/rtc.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/rtc.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/rtc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/rtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series RTC platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/siu.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/siu.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/siu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/siu.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series SIU platform device.
  *
- *  Copyright (C) 2007-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/type.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/type.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/common/type.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/common/type.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  type.c, System type for NEC VR4100 series.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mips/vr41xx/ibm-workpad/setup.c linux-libre-2.6.31-gnu/arch/mips/vr41xx/ibm-workpad/setup.c
--- linux-libre-2.6.30-gnu/arch/mips/vr41xx/ibm-workpad/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mips/vr41xx/ibm-workpad/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the IBM WorkPad z50.
  *
- *  Copyright (C) 2002-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2006  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -151,7 +151,7 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/elf.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/elf.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/elf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/elf.h	2009-09-09 18:13:59.000000000 -0400
@@ -28,13 +28,15 @@
 #define R_MN10300_PCREL8	6	/* PC-relative 8-bit signed.  */
 #define R_MN10300_24		9	/* Direct 24 bit.  */
 #define R_MN10300_RELATIVE	23	/* Adjust by program base.  */
+#define R_MN10300_SYM_DIFF	33	/* Adjustment when relaxing. */
+#define R_MN10300_ALIGN 	34	/* Alignment requirement. */
 
 /*
  * ELF register definitions..
  */
 typedef unsigned long elf_greg_t;
 
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+#define ELF_NGREG ((sizeof(struct pt_regs) / sizeof(elf_greg_t)) - 1)
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 #define ELF_NFPREG 32
@@ -76,6 +78,7 @@
 } while (0)
 
 #define USE_ELF_CORE_DUMP
+#define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,31 +1,6 @@
-/* MN10300 kmap_atomic() slot IDs
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
 #endif /* _ASM_KMAP_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/mman.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
 #ifndef _ASM_MMAN_H
 #define _ASM_MMAN_H
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/pci.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -59,7 +59,6 @@
 #include <linux/slab.h>
 #include <asm/scatterlist.h>
 #include <linux/string.h>
-#include <linux/mm.h>
 #include <asm/io.h>
 
 struct pci_dev;
@@ -70,10 +69,6 @@
  */
 #define PCI_DMA_BUS_IS_PHYS	(1)
 
-
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)	(0)
-
 /* Return the index of the PCI controller for device. */
 static inline int pci_controller_num(struct pci_dev *dev)
 {
@@ -106,19 +101,6 @@
 				    struct resource *res,
 				    struct pci_bus_region *region);
 
-static inline struct resource *
-pcibios_select_root(struct pci_dev *pdev, struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 #define pcibios_scan_all_fns(a, b)	0
 
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -51,6 +51,6 @@
 }
 
 
-#define __pte_free_tlb(tlb, pte) tlb_remove_page((tlb), (pte))
+#define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte))
 
 #endif /* _ASM_PGALLOC_H */
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/processor.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -143,13 +143,7 @@
 
 unsigned long get_wchan(struct task_struct *p);
 
-#define task_pt_regs(task)						\
-({									\
-       struct pt_regs *__regs__;					\
-       __regs__ = (struct pt_regs *) (KSTK_TOP(task_stack_page(task)) - 8); \
-       __regs__ - 1;							\
-})
-
+#define task_pt_regs(task) ((task)->thread.uregs)
 #define KSTK_EIP(task) (task_pt_regs(task)->pc)
 #define KSTK_ESP(task) (task_pt_regs(task)->sp)
 
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/ptrace.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/ptrace.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/ptrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/ptrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -77,8 +77,6 @@
 };
 #endif
 
-extern struct pt_regs *__frame; /* current frame pointer */
-
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
 #define PTRACE_SETREGS            13
@@ -90,14 +88,23 @@
 
 #if defined(__KERNEL__)
 
+extern struct pt_regs *__frame;		/* current frame pointer */
+
 #if !defined(__ASSEMBLY__)
+struct task_struct;
+
 #define user_mode(regs)			(((regs)->epsw & EPSW_nSL) == EPSW_nSL)
 #define instruction_pointer(regs)	((regs)->pc)
+#define user_stack_pointer(regs)	((regs)->sp)
 extern void show_regs(struct pt_regs *);
+
+#define arch_has_single_step()	(1)
+extern void user_enable_single_step(struct task_struct *);
+extern void user_disable_single_step(struct task_struct *);
+
 #endif  /*  !__ASSEMBLY  */
 
 #define profile_pc(regs) ((regs)->pc)
 
 #endif  /*  __KERNEL__  */
-
 #endif /* _ASM_PTRACE_H */
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/setup.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/setup.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/setup.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/setup.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,8 @@
 #ifndef _ASM_SETUP_H
 #define _ASM_SETUP_H
 
+#ifdef __KERNEL__
 extern void __init unit_setup(void);
 extern void __init unit_init_IRQ(void);
-
+#endif
 #endif /* _ASM_SETUP_H */
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/signal.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -115,7 +115,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -65,8 +65,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -76,7 +74,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/mn10300/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/mn10300/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -346,10 +346,12 @@
 #define __NR_inotify_init1	333
 #define __NR_preadv		334
 #define __NR_pwritev		335
+#define __NR_rt_tgsigqueueinfo	336
+#define __NR_perf_counter_open	337
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 326
+#define NR_syscalls 338
 
 /*
  * specify the deprecated syscalls we want to support on this arch
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/Kconfig linux-libre-2.6.31-gnu/arch/mn10300/Kconfig
--- linux-libre-2.6.30-gnu/arch/mn10300/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,7 @@
 config MN10300
 	def_bool y
 	select HAVE_OPROFILE
+	select HAVE_ARCH_TRACEHOOK
 
 config AM33
 	def_bool y
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/entry.S linux-libre-2.6.31-gnu/arch/mn10300/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -76,7 +76,7 @@
 	cmp	nr_syscalls,d0
 	bcc	syscall_badsys
 	btst	_TIF_SYSCALL_TRACE,(TI_flags,a2)
-	bne	syscall_trace_entry
+	bne	syscall_entry_trace
 syscall_call:
 	add	d0,d0,a1
 	add	a1,a1
@@ -104,11 +104,10 @@
 syscall_exit_work:
 	btst	_TIF_SYSCALL_TRACE,d2
 	beq	work_pending
-	__sti				# could let do_syscall_trace() call
+	__sti				# could let syscall_trace_exit() call
 					# schedule() instead
 	mov	fp,d0
-	mov	1,d1
-	call	do_syscall_trace[],0	# do_syscall_trace(regs,entryexit)
+	call	syscall_trace_exit[],0	# do_syscall_trace(regs)
 	jmp	resume_userspace
 
 	ALIGN
@@ -138,13 +137,11 @@
 	jmp	resume_userspace
 
 	# perform syscall entry tracing
-syscall_trace_entry:
+syscall_entry_trace:
 	mov	-ENOSYS,d0
 	mov	d0,(REG_D0,fp)
 	mov	fp,d0
-	clr	d1
-	call	do_syscall_trace[],0
-	mov	(REG_ORIG_D0,fp),d0
+	call	syscall_trace_entry[],0	# returns the syscall number to actually use
 	mov	(REG_D1,fp),d1
 	cmp	nr_syscalls,d0
 	bcs	syscall_call
@@ -725,6 +722,8 @@
 	.long sys_inotify_init1
 	.long sys_preadv
 	.long sys_pwritev		/* 335 */
+	.long sys_rt_tgsigqueueinfo
+	.long sys_perf_counter_open
 
 
 nr_syscalls=(.-sys_call_table)/4
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/init_task.c linux-libre-2.6.31-gnu/arch/mn10300/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,9 +20,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/module.c linux-libre-2.6.31-gnu/arch/mn10300/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 /* MN10300 Kernel module helper routines
  *
- * Copyright (C) 2007, 2008 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2007, 2008, 2009 Red Hat, Inc. All Rights Reserved.
  * Written by Mark Salter (msalter@redhat.com)
  * - Derived from arch/i386/kernel/module.c
  *
@@ -48,8 +48,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-	 * table entries. */
 }
 
 /*
@@ -105,10 +103,10 @@
 		       unsigned int relsec,
 		       struct module *me)
 {
-	unsigned int i;
+	unsigned int i, sym_diff_seen = 0;
 	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
 	Elf32_Sym *sym;
-	Elf32_Addr relocation;
+	Elf32_Addr relocation, sym_diff_val = 0;
 	uint8_t *location;
 	uint32_t value;
 
@@ -128,6 +126,22 @@
 		/* this is the adjustment to be made */
 		relocation = sym->st_value + rel[i].r_addend;
 
+		if (sym_diff_seen) {
+			switch (ELF32_R_TYPE(rel[i].r_info)) {
+			case R_MN10300_32:
+			case R_MN10300_24:
+			case R_MN10300_16:
+			case R_MN10300_8:
+				relocation -= sym_diff_val;
+				sym_diff_seen = 0;
+				break;
+			default:
+				printk(KERN_ERR "module %s: Unexpected SYM_DIFF relocation: %u\n",
+				       me->name, ELF32_R_TYPE(rel[i].r_info));
+				return -ENOEXEC;
+			}
+		}
+
 		switch (ELF32_R_TYPE(rel[i].r_info)) {
 			/* for the first four relocation types, we simply
 			 * store the adjustment at the location given */
@@ -159,12 +173,29 @@
 			*location = relocation - (uint32_t) location;
 			break;
 
+		case R_MN10300_SYM_DIFF:
+			/* This is used to adjust the next reloc as required
+			 * by relaxation. */
+			sym_diff_seen = 1;
+			sym_diff_val = sym->st_value;
+			break;
+
+		case R_MN10300_ALIGN:
+			/* Just ignore the ALIGN relocs.
+			 * Only interesting if kernel performed relaxation. */
+			continue;
+
 		default:
 			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
 			       me->name, ELF32_R_TYPE(rel[i].r_info));
 			return -ENOEXEC;
 		}
 	}
+	if (sym_diff_seen) {
+		printk(KERN_ERR "module %s: Nothing follows SYM_DIFF relocation: %u\n",
+				       me->name, ELF32_R_TYPE(rel[i].r_info));
+		return -ENOEXEC;
+	}
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/process.c linux-libre-2.6.31-gnu/arch/mn10300/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -281,9 +281,6 @@
 	error = PTR_ERR(filename);
 	if (!IS_ERR(filename)) {
 		error = do_execve(filename, argv, envp, __frame);
-		if (error == 0)
-			current->ptrace &= ~PT_DTRACE;
-
 		putname(filename);
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/mn10300/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,10 +13,12 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/regset.h>
+#include <linux/elf.h>
+#include <linux/tracehook.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -64,12 +66,6 @@
 		((unsigned long) task->thread.uregs + offset);
 }
 
-/*
- * this routine will put a word on the processes privileged stack.
- * the offset is how far from the base addr as stored in the TSS.
- * this routine assumes that all the privileged stacks are in our
- * data space.
- */
 static inline
 int put_stack_long(struct task_struct *task, int offset, unsigned long data)
 {
@@ -80,94 +76,233 @@
 	return 0;
 }
 
-static inline unsigned long get_fpregs(struct fpu_state_struct *buf,
-				       struct task_struct *tsk)
+/*
+ * retrieve the contents of MN10300 userspace general registers
+ */
+static int genregs_get(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       void *kbuf, void __user *ubuf)
 {
-	return __copy_to_user(buf, &tsk->thread.fpu_state,
-			      sizeof(struct fpu_state_struct));
+	const struct pt_regs *regs = task_pt_regs(target);
+	int ret;
+
+	/* we need to skip regs->next */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  regs, 0, PT_ORIG_D0 * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &regs->orig_d0, PT_ORIG_D0 * sizeof(long),
+				  NR_PTREGS * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					NR_PTREGS * sizeof(long), -1);
 }
 
-static inline unsigned long set_fpregs(struct task_struct *tsk,
-				       struct fpu_state_struct *buf)
+/*
+ * update the contents of the MN10300 userspace general registers
+ */
+static int genregs_set(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       const void *kbuf, const void __user *ubuf)
 {
-	return __copy_from_user(&tsk->thread.fpu_state, buf,
-				sizeof(struct fpu_state_struct));
+	struct pt_regs *regs = task_pt_regs(target);
+	unsigned long tmp;
+	int ret;
+
+	/* we need to skip regs->next */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 regs, 0, PT_ORIG_D0 * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->orig_d0, PT_ORIG_D0 * sizeof(long),
+				 PT_EPSW * sizeof(long));
+	if (ret < 0)
+		return ret;
+
+	/* we need to mask off changes to EPSW */
+	tmp = regs->epsw;
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &tmp, PT_EPSW * sizeof(long),
+				 PT_PC * sizeof(long));
+	tmp &= EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N | EPSW_FLAG_Z;
+	tmp |= regs->epsw & ~(EPSW_FLAG_V | EPSW_FLAG_C | EPSW_FLAG_N |
+			      EPSW_FLAG_Z);
+	regs->epsw = tmp;
+
+	if (ret < 0)
+		return ret;
+
+	/* and finally load the PC */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->pc, PT_PC * sizeof(long),
+				 NR_PTREGS * sizeof(long));
+
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					 NR_PTREGS * sizeof(long), -1);
 }
 
-static inline void fpsave_init(struct task_struct *task)
+/*
+ * retrieve the contents of MN10300 userspace FPU registers
+ */
+static int fpuregs_get(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       void *kbuf, void __user *ubuf)
 {
-	memset(&task->thread.fpu_state, 0, sizeof(struct fpu_state_struct));
+	const struct fpu_state_struct *fpregs = &target->thread.fpu_state;
+	int ret;
+
+	unlazy_fpu(target);
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  fpregs, 0, sizeof(*fpregs));
+	if (ret < 0)
+		return ret;
+
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					sizeof(*fpregs), -1);
 }
 
 /*
- * make sure the single step bit is not set
+ * update the contents of the MN10300 userspace FPU registers
  */
-void ptrace_disable(struct task_struct *child)
+static int fpuregs_set(struct task_struct *target,
+		       const struct user_regset *regset,
+		       unsigned int pos, unsigned int count,
+		       const void *kbuf, const void __user *ubuf)
+{
+	struct fpu_state_struct fpu_state = target->thread.fpu_state;
+	int ret;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &fpu_state, 0, sizeof(fpu_state));
+	if (ret < 0)
+		return ret;
+
+	fpu_kill_state(target);
+	target->thread.fpu_state = fpu_state;
+	set_using_fpu(target);
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					 sizeof(fpu_state), -1);
+}
+
+/*
+ * determine if the FPU registers have actually been used
+ */
+static int fpuregs_active(struct task_struct *target,
+			  const struct user_regset *regset)
+{
+	return is_using_fpu(target) ? regset->n : 0;
+}
+
+/*
+ * Define the register sets available on the MN10300 under Linux
+ */
+enum mn10300_regset {
+	REGSET_GENERAL,
+	REGSET_FPU,
+};
+
+static const struct user_regset mn10300_regsets[] = {
+	/*
+	 * General register format is:
+	 *	A3, A2, D3, D2, MCVF, MCRL, MCRH, MDRQ
+	 *	E1, E0, E7...E2, SP, LAR, LIR, MDR
+	 *	A1, A0, D1, D0, ORIG_D0, EPSW, PC
+	 */
+	[REGSET_GENERAL] = {
+		.core_note_type	= NT_PRSTATUS,
+		.n		= ELF_NGREG,
+		.size		= sizeof(long),
+		.align		= sizeof(long),
+		.get		= genregs_get,
+		.set		= genregs_set,
+	},
+	/*
+	 * FPU register format is:
+	 *	FS0-31, FPCR
+	 */
+	[REGSET_FPU] = {
+		.core_note_type	= NT_PRFPREG,
+		.n		= sizeof(struct fpu_state_struct) / sizeof(long),
+		.size		= sizeof(long),
+		.align		= sizeof(long),
+		.get		= fpuregs_get,
+		.set		= fpuregs_set,
+		.active		= fpuregs_active,
+	},
+};
+
+static const struct user_regset_view user_mn10300_native_view = {
+	.name		= "mn10300",
+	.e_machine	= EM_MN10300,
+	.regsets	= mn10300_regsets,
+	.n		= ARRAY_SIZE(mn10300_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &user_mn10300_native_view;
+}
+
+/*
+ * set the single-step bit
+ */
+void user_enable_single_step(struct task_struct *child)
 {
 #ifndef CONFIG_MN10300_USING_JTAG
 	struct user *dummy = NULL;
 	long tmp;
 
 	tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
-	tmp &= ~EPSW_T;
+	tmp |= EPSW_T;
 	put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
 #endif
 }
 
 /*
- * set the single step bit
+ * make sure the single-step bit is not set
  */
-void ptrace_enable(struct task_struct *child)
+void user_disable_single_step(struct task_struct *child)
 {
 #ifndef CONFIG_MN10300_USING_JTAG
 	struct user *dummy = NULL;
 	long tmp;
 
 	tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
-	tmp |= EPSW_T;
+	tmp &= ~EPSW_T;
 	put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
 #endif
 }
 
+void ptrace_disable(struct task_struct *child)
+{
+	user_disable_single_step(child);
+}
+
 /*
  * handle the arch-specific side of process tracing
  */
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	struct fpu_state_struct fpu_state;
-	int i, ret;
+	unsigned long tmp;
+	int ret;
 
 	switch (request) {
-	/* read the word at location addr. */
-	case PTRACE_PEEKTEXT: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp, (unsigned long *) data);
-		break;
-	}
-
-	/* read the word at location addr. */
-	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
-		int copied;
-
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			break;
-		ret = put_user(tmp, (unsigned long *) data);
-		break;
-	}
-
 	/* read the word at location addr in the USER area. */
-	case PTRACE_PEEKUSR: {
-		unsigned long tmp;
-
+	case PTRACE_PEEKUSR:
 		ret = -EIO;
 		if ((addr & 3) || addr < 0 ||
 		    addr > sizeof(struct user) - 3)
@@ -179,17 +314,6 @@
 					     ptrace_regid_to_frame[addr]);
 		ret = put_user(tmp, (unsigned long *) data);
 		break;
-	}
-
-	/* write the word at location addr. */
-	case PTRACE_POKETEXT:
-	case PTRACE_POKEDATA:
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) ==
-		    sizeof(data))
-			ret = 0;
-		else
-			ret = -EIO;
-		break;
 
 		/* write the word at location addr in the USER area */
 	case PTRACE_POKEUSR:
@@ -204,132 +328,32 @@
 					     data);
 		break;
 
-		/* continue and stop at next (return from) syscall */
-	case PTRACE_SYSCALL:
-		/* restart after signal. */
-	case PTRACE_CONT:
-		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
-			break;
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		ptrace_disable(child);
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-		/*
-		 * make the child exit
-		 * - the best I can do is send it a sigkill
-		 * - perhaps it should be put in the status that it wants to
-		 *   exit
-		 */
-	case PTRACE_KILL:
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
-		ptrace_disable(child);
-		wake_up_process(child);
-		break;
-
-	case PTRACE_SINGLESTEP: /* set the trap flag. */
-#ifndef CONFIG_MN10300_USING_JTAG
-		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
-			break;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		ptrace_enable(child);
-		child->exit_code = data;
-		wake_up_process(child);
-		ret = 0;
-#else
-		ret = -EINVAL;
-#endif
-		break;
-
-	case PTRACE_DETACH:	/* detach a process that was attached. */
-		ret = ptrace_detach(child, data);
-		break;
-
-		/* Get all gp regs from the child. */
-	case PTRACE_GETREGS: {
-		unsigned long tmp;
-
-		if (!access_ok(VERIFY_WRITE, (unsigned *) data, NR_PTREGS << 2)) {
-			ret = -EIO;
-			break;
-		}
-
-		for (i = 0; i < NR_PTREGS << 2; i += 4) {
-			tmp = get_stack_long(child, ptrace_regid_to_frame[i]);
-			__put_user(tmp, (unsigned long *) data);
-			data += sizeof(tmp);
-		}
-		ret = 0;
-		break;
-	}
-
-	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
-		unsigned long tmp;
-
-		if (!access_ok(VERIFY_READ, (unsigned long *)data,
-			       sizeof(struct pt_regs))) {
-			ret = -EIO;
-			break;
-		}
-
-		for (i = 0; i < NR_PTREGS << 2; i += 4) {
-			__get_user(tmp, (unsigned long *) data);
-			put_stack_long(child, ptrace_regid_to_frame[i], tmp);
-			data += sizeof(tmp);
-		}
-		ret = 0;
-		break;
-	}
-
-	case PTRACE_GETFPREGS: { /* Get the child FPU state. */
-		if (is_using_fpu(child)) {
-			unlazy_fpu(child);
-			fpu_state = child->thread.fpu_state;
-		} else {
-			memset(&fpu_state, 0, sizeof(fpu_state));
-		}
+	case PTRACE_GETREGS:	/* Get all integer regs from the child. */
+		return copy_regset_to_user(child, &user_mn10300_native_view,
+					   REGSET_GENERAL,
+					   0, NR_PTREGS * sizeof(long),
+					   (void __user *)data);
 
-		ret = -EIO;
-		if (copy_to_user((void *) data, &fpu_state,
-				 sizeof(fpu_state)) == 0)
-			ret = 0;
-		break;
-	}
+	case PTRACE_SETREGS:	/* Set all integer regs in the child. */
+		return copy_regset_from_user(child, &user_mn10300_native_view,
+					     REGSET_GENERAL,
+					     0, NR_PTREGS * sizeof(long),
+					     (const void __user *)data);
 
-	case PTRACE_SETFPREGS: { /* Set the child FPU state. */
-		ret = -EFAULT;
-		if (copy_from_user(&fpu_state, (const void *) data,
-				   sizeof(fpu_state)) == 0) {
-			fpu_kill_state(child);
-			child->thread.fpu_state = fpu_state;
-			set_using_fpu(child);
-			ret = 0;
-		}
-		break;
-	}
+	case PTRACE_GETFPREGS:	/* Get the child FPU state. */
+		return copy_regset_to_user(child, &user_mn10300_native_view,
+					   REGSET_FPU,
+					   0, sizeof(struct fpu_state_struct),
+					   (void __user *)data);
 
-	case PTRACE_SETOPTIONS: {
-		if (data & PTRACE_O_TRACESYSGOOD)
-			child->ptrace |= PT_TRACESYSGOOD;
-		else
-			child->ptrace &= ~PT_TRACESYSGOOD;
-		ret = 0;
-		break;
-	}
+	case PTRACE_SETFPREGS:	/* Set the child FPU state. */
+		return copy_regset_from_user(child, &user_mn10300_native_view,
+					     REGSET_FPU,
+					     0, sizeof(struct fpu_state_struct),
+					     (const void __user *)data);
 
 	default:
-		ret = -EIO;
+		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
 
@@ -337,43 +361,26 @@
 }
 
 /*
- * notification of system call entry/exit
- * - triggered by current->work.syscall_trace
+ * handle tracing of system call entry
+ * - return the revised system call number or ULONG_MAX to cause ENOSYS
  */
-asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
+asmlinkage unsigned long syscall_trace_entry(struct pt_regs *regs)
 {
-#if 0
-	/* just in case... */
-	printk(KERN_DEBUG "[%d] syscall_%lu(%lx,%lx,%lx,%lx) = %lx\n",
-	       current->pid,
-	       regs->orig_d0,
-	       regs->a0,
-	       regs->d1,
-	       regs->a3,
-	       regs->a2,
-	       regs->d0);
-	return;
-#endif
-
-	if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
-	    !test_thread_flag(TIF_SINGLESTEP))
-		return;
-	if (!(current->ptrace & PT_PTRACED))
-		return;
+	if (tracehook_report_syscall_entry(regs))
+		/* tracing decided this syscall should not happen, so
+		 * We'll return a bogus call number to get an ENOSYS
+		 * error, but leave the original number in
+		 * regs->orig_d0
+		 */
+		return ULONG_MAX;
 
-	/* the 0x80 provides a way for the tracing parent to distinguish
-	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP |
-		      ((current->ptrace & PT_TRACESYSGOOD) &&
-		       !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
+	return regs->orig_d0;
+}
 
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
+/*
+ * handle tracing of system call exit
+ */
+asmlinkage void syscall_trace_exit(struct pt_regs *regs)
+{
+	tracehook_report_syscall_exit(regs, 0);
 }
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/signal.c linux-libre-2.6.31-gnu/arch/mn10300/kernel/signal.c
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/signal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/signal.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
@@ -23,6 +22,7 @@
 #include <linux/tty.h>
 #include <linux/personality.h>
 #include <linux/suspend.h>
+#include <linux/tracehook.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -511,6 +511,9 @@
 			 * clear the TIF_RESTORE_SIGMASK flag */
 			if (test_thread_flag(TIF_RESTORE_SIGMASK))
 				clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+			tracehook_signal_handler(signr, &info, &ka, regs,
+						 test_thread_flag(TIF_SINGLESTEP));
 		}
 
 		return;
@@ -561,4 +564,9 @@
 	/* deal with pending signal delivery */
 	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
 		do_signal(regs);
+
+	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(__frame);
+	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/sys_mn10300.c linux-libre-2.6.31-gnu/arch/mn10300/kernel/sys_mn10300.c
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/sys_mn10300.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/sys_mn10300.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,6 @@
 #include <linux/syscalls.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
@@ -21,7 +20,6 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
-#include <linux/syscalls.h>
 #include <linux/tty.h>
 
 #include <asm/uaccess.h>
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/traps.c linux-libre-2.6.31-gnu/arch/mn10300/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
@@ -136,8 +135,7 @@
 	unsigned long *stack, addr, module_start, module_end;
 	int i;
 
-	printk(KERN_EMERG "\n"
-	       KERN_EMERG "Call Trace:");
+	printk(KERN_EMERG "\nCall Trace:");
 
 	stack = sp;
 	i = 0;
@@ -153,7 +151,7 @@
 			printk("\n");
 #else
 			if ((i % 6) == 0)
-				printk("\n" KERN_EMERG "  ");
+				printk(KERN_EMERG "  ");
 			printk("[<%08lx>] ", addr);
 			i++;
 #endif
@@ -180,7 +178,7 @@
 		if (((long) stack & (THREAD_SIZE - 1)) == 0)
 			break;
 		if ((i % 8) == 0)
-			printk("\n" KERN_EMERG "  ");
+			printk(KERN_EMERG "  ");
 		printk("%08lx ", *stack++);
 	}
 
@@ -264,8 +262,7 @@
 		show_stack(current, (unsigned long *) sp);
 
 #if 0
-		printk(KERN_EMERG "\n"
-		       KERN_EMERG "Code: ");
+		printk(KERN_EMERG "\nCode: ");
 		if (regs->pc < PAGE_OFFSET)
 			goto bad;
 
@@ -311,16 +308,14 @@
 {
 	console_verbose();
 	spin_lock_irq(&die_lock);
-	printk(KERN_EMERG "\n"
-	       KERN_EMERG "%s: %04x\n",
+	printk(KERN_EMERG "\n%s: %04x\n",
 	       str, code & 0xffff);
 	show_registers(regs);
 
 	if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 &&
 	    (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) {
 		printk(KERN_EMERG "Exception in usermode interrupt handler\n");
-		printk(KERN_EMERG "\n"
-		       KERN_EMERG "  Please connect to kernel debugger !!\n");
+		printk(KERN_EMERG "\nPlease connect to kernel debugger !!\n");
 		asm volatile ("0: bra 0b");
 	}
 
@@ -429,9 +424,8 @@
 {
 	console_verbose();
 
-	printk(KERN_EMERG "\n"
-	       KERN_EMERG "Asynchronous I/O Bus Error\n"
-	       KERN_EMERG "==========================\n");
+	printk(KERN_EMERG "Asynchronous I/O Bus Error\n");
+	printk(KERN_EMERG "==========================\n");
 
 	if (bcberr & BCBERR_BEME)
 		printk(KERN_EMERG "- Multiple recorded errors\n");
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/kernel/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/mn10300/kernel/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/mn10300/kernel/vmlinux.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/kernel/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -38,14 +38,10 @@
 
   _etext = .;			/* End of text section */
 
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
+  EXCEPTION_TABLE(16)
   BUG_TABLE
 
-  RODATA
+  RO_DATA(PAGE_SIZE)
 
   /* writeable */
   .data : {			/* Data */
@@ -53,27 +49,19 @@
 	CONSTRUCTORS
 	}
 
-  . = ALIGN(PAGE_SIZE);
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(PAGE_SIZE);
-  __nosave_end = .;
-
-  . = ALIGN(PAGE_SIZE);
-  .data.page_aligned : { *(.data.idt) }
+  .data_nosave : { NOSAVE_DATA; }
 
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+  .data.page_aligned : { PAGE_ALIGNED_DATA(PAGE_SIZE); }
+  .data.cacheline_aligned : { CACHELINE_ALIGNED_DATA(32); }
 
   /* rarely changed data like cpu maps */
   . = ALIGN(32);
   .data.read_mostly : AT(ADDR(.data.read_mostly)) {
-	*(.data.read_mostly)
+	READ_MOSTLY_DATA(32);
 	_edata = .;		/* End of data section */
   }
 
-  . = ALIGN(THREAD_SIZE);	/* init_task */
-  .data.init_task : { *(.data.init_task) }
+  .data.init_task : { INIT_TASK_DATA(THREAD_SIZE); }
 
   /* might get freed after init */
   . = ALIGN(PAGE_SIZE);
@@ -88,23 +76,18 @@
   __init_begin = .;
   .init.text : {
 	_sinittext = .;
-	*(.init.text)
+	INIT_TEXT;
 	_einittext = .;
   }
-  .init.data : { *(.init.data) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { KEEP(*(.init.setup)) }
-  __setup_end = .;
+  .init.data : { INIT_DATA; }
+  .setup.init : { INIT_SETUP(16); }
 
   __initcall_start = .;
   .initcall.init : {
 	INITCALLS
   }
   __initcall_end = .;
-  __con_initcall_start = .;
-  .con_initcall.init : { *(.con_initcall.init) }
-  __con_initcall_end = .;
+  .con_initcall.init : { CON_INITCALL; }
 
   SECURITY_INIT
   . = ALIGN(4);
@@ -114,28 +97,17 @@
  .altinstr_replacement : { *(.altinstr_replacement) }
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
-  .exit.text : { *(.exit.text) }
-  .exit.data : { *(.exit.data) }
+	.exit.text : { EXIT_TEXT; }
+	.exit.data : { EXIT_DATA; }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-  . = ALIGN(PAGE_SIZE);
-  __initramfs_start = .;
-  .init.ramfs : { *(.init.ramfs) }
-  __initramfs_end = .;
-#endif
+  .init.ramfs : { INIT_RAM_FS; }
 
   PERCPU(32)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
 
-  __bss_start = .;		/* BSS */
-  .bss : {
-	*(.bss.page_aligned)
-	*(.bss)
-  }
-  . = ALIGN(4);
-  __bss_stop = .;
+  BSS_SECTION(0, PAGE_SIZE, 4)
 
   _end = . ;
 
@@ -145,7 +117,7 @@
 
   /* Sections to be discarded */
   /DISCARD/ : {
-	*(.exitcall.exit)
+	EXIT_CALL
 	}
 
   STABS_DEBUG
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/mm/fault.c linux-libre-2.6.31-gnu/arch/mn10300/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/mn10300/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,7 +20,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
@@ -258,7 +257,7 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, address, write);
+	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/mm/misalignment.c linux-libre-2.6.31-gnu/arch/mn10300/mm/misalignment.c
--- linux-libre-2.6.30-gnu/arch/mn10300/mm/misalignment.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/mm/misalignment.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
diff -druN linux-libre-2.6.30-gnu/arch/mn10300/mm/tlb-mn10300.S linux-libre-2.6.31-gnu/arch/mn10300/mm/tlb-mn10300.S
--- linux-libre-2.6.30-gnu/arch/mn10300/mm/tlb-mn10300.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/mn10300/mm/tlb-mn10300.S	2009-09-09 18:13:59.000000000 -0400
@@ -165,24 +165,6 @@
 ENTRY(dtlb_aerror)
 	and	~EPSW_NMID,epsw
 	add	-4,sp
-	mov	d1,(sp)
-
-	movhu	(MMUFCR_DFC),d1			# is it the initial valid write
-						# to this page?
-	and	MMUFCR_xFC_INITWR,d1
- 	beq	dtlb_pagefault			# jump if not
-
-	mov	(DPTEL),d1			# set the dirty bit
-						# (don't replace with BSET!)
-	or	_PAGE_DIRTY,d1
-	mov	d1,(DPTEL)
-	mov	(sp),d1
-	add	4,sp
- 	rti
-
-	ALIGN
-dtlb_pagefault:
-	mov	(sp),d1
 	SAVE_ALL
 	add	-4,sp				# need to pass three params
 
diff -druN linux-libre-2.6.30-gnu/arch/parisc/hpux/fs.c linux-libre-2.6.31-gnu/arch/parisc/hpux/fs.c
--- linux-libre-2.6.30-gnu/arch/parisc/hpux/fs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/hpux/fs.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,11 +44,6 @@
 	error = do_execve(filename, (char __user * __user *) regs->gr[25],
 		(char __user * __user *) regs->gr[24], regs);
 
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
-		task_unlock(current);
-	}
 	putname(filename);
 
 out:
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -222,13 +222,13 @@
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
-#define atomic_add(i,v)	((void)(__atomic_add_return( ((int)(i)),(v))))
-#define atomic_sub(i,v)	((void)(__atomic_add_return(-((int)(i)),(v))))
+#define atomic_add(i,v)	((void)(__atomic_add_return( (i),(v))))
+#define atomic_sub(i,v)	((void)(__atomic_add_return(-(i),(v))))
 #define atomic_inc(v)	((void)(__atomic_add_return(   1,(v))))
 #define atomic_dec(v)	((void)(__atomic_add_return(  -1,(v))))
 
-#define atomic_add_return(i,v)	(__atomic_add_return( ((int)(i)),(v)))
-#define atomic_sub_return(i,v)	(__atomic_add_return(-((int)(i)),(v)))
+#define atomic_add_return(i,v)	(__atomic_add_return( (i),(v)))
+#define atomic_sub_return(i,v)	(__atomic_add_return(-(i),(v)))
 #define atomic_inc_return(v)	(__atomic_add_return(   1,(v)))
 #define atomic_dec_return(v)	(__atomic_add_return(  -1,(v)))
 
@@ -336,8 +336,12 @@
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
-#endif /* CONFIG_64BIT */
+#else /* CONFIG_64BIT */
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic64.h>
+
+#endif /* !CONFIG_64BIT */
+
+#include <asm-generic/atomic-long.h>
 
 #endif /* _ASM_PARISC_ATOMIC_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,20 @@
+#ifndef __ASM_PARISC_BITSPERLONG_H
+#define __ASM_PARISC_BITSPERLONG_H
+
+/*
+ * using CONFIG_* outside of __KERNEL__ is wrong,
+ * __LP64__ was also removed from headers, so what
+ * is the right approach on parisc?
+ *	-arnd
+ */
+#if (defined(__KERNEL__) && defined(CONFIG_64BIT)) || defined (__LP64__)
+#define __BITS_PER_LONG 64
+#define SHIFT_PER_LONG 6
+#else
+#define __BITS_PER_LONG 32
+#define SHIFT_PER_LONG 5
+#endif
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_PARISC_BITSPERLONG_H */
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/dma.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/dma.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,4 @@
-/* $Id: dma.h,v 1.2 1999/04/27 00:46:18 deller Exp $
- * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+/* asm/dma.h: Defines for using and allocating dma channels.
  * Written by Hennus Bergman, 1992.
  * High DMA channel support & info by Hannu Savolainen
  * and John Boyd, Nov. 1992.
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/errno.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/errno.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/errno.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/errno.h	2009-09-09 18:13:59.000000000 -0400
@@ -120,5 +120,6 @@
 #define EOWNERDEAD	254	/* Owner died */
 #define ENOTRECOVERABLE	255	/* State not recoverable */
 
+#define	ERFKILL		256	/* Operation not possible due to RF-kill */
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,30 +1,12 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-
 #ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
+#define  __WITH_KM_FENCE
 #endif
 
-enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_IRQ0,
-D(10)	KM_IRQ1,
-D(11)	KM_SOFTIRQ0,
-D(12)	KM_SOFTIRQ1,
-D(13)	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
-#undef D
+#undef __WITH_KM_FENCE
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/page.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -159,6 +159,6 @@
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _PARISC_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/pci.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -268,19 +268,6 @@
 pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 			struct pci_bus_region *region);
 
-static inline struct resource *
-pcibios_select_root(struct pci_dev *pdev, struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 static inline void pcibios_penalize_isa_irq(int irq, int active)
 {
 	/* We don't need to penalize isa irq's */
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/perf_counter.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/perf_counter.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/perf_counter.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/perf_counter.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef __ASM_PARISC_PERF_COUNTER_H
+#define __ASM_PARISC_PERF_COUNTER_H
+
+/* parisc only supports software counters through this interface. */
+static inline void set_perf_counter_pending(void) { }
+
+#endif /* __ASM_PARISC_PERF_COUNTER_H */
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/processor.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <asm/types.h>
 #include <asm/system.h>
 #include <asm/percpu.h>
+
 #endif /* __ASSEMBLY__ */
 
 #define KERNEL_STACK_SIZE 	(4*PAGE_SIZE)
@@ -127,6 +128,8 @@
 	unsigned long  flags;
 }; 
 
+#define task_pt_regs(tsk) ((struct pt_regs *)&((tsk)->thread.regs))
+
 /* Thread struct flags. */
 #define PARISC_UAC_NOPRINT	(1UL << 0)	/* see prctl and unaligned.c */
 #define PARISC_UAC_SIGBUS	(1UL << 1)
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/system.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/system.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -168,8 +168,8 @@
 /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
 #define __ldcw(a) ({						\
 	unsigned __ret;						\
-	__asm__ __volatile__(__LDCW " 0(%1),%0"			\
-		: "=r" (__ret) : "r" (a));			\
+	__asm__ __volatile__(__LDCW " 0(%2),%0"			\
+		: "=r" (__ret), "+m" (*(a)) : "r" (a));		\
 	__ret;							\
 })
 
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -23,7 +23,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
   	.restart_block	= {			\
 		.fn = do_no_restart_syscall	\
 	}					\
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/tlbflush.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/tlbflush.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/tlbflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/tlbflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,14 +12,12 @@
  * N class systems, only one PxTLB inter processor broadcast can be
  * active at any one time on the Merced bus.  This tlb purge
  * synchronisation is fairly lightweight and harmless so we activate
- * it on all SMP systems not just the N class.  We also need to have
- * preemption disabled on uniprocessor machines, and spin_lock does that
- * nicely.
+ * it on all systems not just the N class.
  */
 extern spinlock_t pa_tlb_lock;
 
-#define purge_tlb_start(x) spin_lock(&pa_tlb_lock)
-#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock)
+#define purge_tlb_start(flags)	spin_lock_irqsave(&pa_tlb_lock, flags)
+#define purge_tlb_end(flags)	spin_unlock_irqrestore(&pa_tlb_lock, flags)
 
 extern void flush_tlb_all(void);
 extern void flush_tlb_all_local(void *);
@@ -63,14 +61,16 @@
 static inline void flush_tlb_page(struct vm_area_struct *vma,
 	unsigned long addr)
 {
+	unsigned long flags;
+
 	/* For one page, it's not worth testing the split_tlb variable */
 
 	mb();
 	mtsp(vma->vm_mm->context,1);
-	purge_tlb_start();
+	purge_tlb_start(flags);
 	pdtlb(addr);
 	pitlb(addr);
-	purge_tlb_end();
+	purge_tlb_end(flags);
 }
 
 void __flush_tlb_range(unsigned long sid,
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,7 @@
 
 #include <asm-generic/tlb.h>
 
-#define __pmd_free_tlb(tlb, pmd)	pmd_free((tlb)->mm, pmd)
-#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
+#define __pmd_free_tlb(tlb, pmd, addr)	pmd_free((tlb)->mm, pmd)
+#define __pte_free_tlb(tlb, pte, addr)	pte_free((tlb)->mm, pte)
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/types.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -14,14 +14,6 @@
  */
 #ifdef __KERNEL__
 
-#ifdef CONFIG_64BIT
-#define BITS_PER_LONG 64
-#define SHIFT_PER_LONG 6
-#else
-#define BITS_PER_LONG 32
-#define SHIFT_PER_LONG 5
-#endif
-
 #ifndef __ASSEMBLY__
 
 /* Dma addresses are 32-bits wide.  */
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/uaccess.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/uaccess.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/uaccess.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/uaccess.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/cache.h>
-#include <asm-generic/uaccess.h>
+#include <asm-generic/uaccess-unaligned.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
diff -druN linux-libre-2.6.30-gnu/arch/parisc/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/parisc/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/parisc/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -807,8 +807,12 @@
 #define __NR_dup3		(__NR_Linux + 312)
 #define __NR_pipe2		(__NR_Linux + 313)
 #define __NR_inotify_init1	(__NR_Linux + 314)
+#define __NR_preadv		(__NR_Linux + 315)
+#define __NR_pwritev		(__NR_Linux + 316)
+#define __NR_rt_tgsigqueueinfo	(__NR_Linux + 317)
+#define __NR_perf_counter_open	(__NR_Linux + 318)
 
-#define __NR_Linux_syscalls	(__NR_inotify_init1 + 1)
+#define __NR_Linux_syscalls	(__NR_perf_counter_open + 1)
 
 
 #define __IGNORE_select		/* newselect */
diff -druN linux-libre-2.6.30-gnu/arch/parisc/Kconfig linux-libre-2.6.31-gnu/arch/parisc/Kconfig
--- linux-libre-2.6.30-gnu/arch/parisc/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,8 @@
 	select RTC_DRV_GENERIC
 	select INIT_ALL_POSSIBLE
 	select BUG
+	select HAVE_PERF_COUNTERS
+	select GENERIC_ATOMIC64 if !64BIT
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
 	  in many of their workstations & servers (HP9000 700 and 800 series,
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/cache.c linux-libre-2.6.31-gnu/arch/parisc/kernel/cache.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/cache.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/cache.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,4 @@
-/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
- *
+/*
  * 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.
@@ -398,12 +397,13 @@
 
 void clear_user_page_asm(void *page, unsigned long vaddr)
 {
+	unsigned long flags;
 	/* This function is implemented in assembly in pacache.S */
 	extern void __clear_user_page_asm(void *page, unsigned long vaddr);
 
-	purge_tlb_start();
+	purge_tlb_start(flags);
 	__clear_user_page_asm(page, vaddr);
-	purge_tlb_end();
+	purge_tlb_end(flags);
 }
 
 #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
@@ -444,20 +444,24 @@
 
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
+	unsigned long flags;
+
 	purge_kernel_dcache_page((unsigned long)page);
-	purge_tlb_start();
+	purge_tlb_start(flags);
 	pdtlb_kernel(page);
-	purge_tlb_end();
+	purge_tlb_end(flags);
 	clear_user_page_asm(page, vaddr);
 }
 EXPORT_SYMBOL(clear_user_page);
 
 void flush_kernel_dcache_page_addr(void *addr)
 {
+	unsigned long flags;
+
 	flush_kernel_dcache_page_asm(addr);
-	purge_tlb_start();
+	purge_tlb_start(flags);
 	pdtlb_kernel(addr);
-	purge_tlb_end();
+	purge_tlb_end(flags);
 }
 EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
 
@@ -490,8 +494,10 @@
 	if (npages >= 512)  /* 2MB of space: arbitrary, should be tuned */
 		flush_tlb_all();
 	else {
+		unsigned long flags;
+
 		mtsp(sid, 1);
-		purge_tlb_start();
+		purge_tlb_start(flags);
 		if (split_tlb) {
 			while (npages--) {
 				pdtlb(start);
@@ -504,7 +510,7 @@
 				start += PAGE_SIZE;
 			}
 		}
-		purge_tlb_end();
+		purge_tlb_end(flags);
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/entry.S linux-libre-2.6.31-gnu/arch/parisc/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -553,7 +553,7 @@
 	 * on most of those machines only handles cache transactions.
 	 */
 	extrd,u,*=	\pte,_PAGE_NO_CACHE_BIT+32,1,%r0
-	depi		1,12,1,\prot
+	depdi		1,12,1,\prot
 
 	/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
 	convert_for_tlb_insert20 \pte
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/init_task.c linux-libre-2.6.31-gnu/arch/parisc/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,10 +36,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial task structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/inventory.c linux-libre-2.6.31-gnu/arch/parisc/kernel/inventory.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/inventory.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/inventory.c	2009-09-09 18:13:59.000000000 -0400
@@ -170,23 +170,27 @@
 static int __init 
 pat_query_module(ulong pcell_loc, ulong mod_index)
 {
-	pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+	pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;
 	unsigned long bytecnt;
 	unsigned long temp;	/* 64-bit scratch value */
 	long status;		/* PDC return value status */
 	struct parisc_device *dev;
 
+	pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL);
+	if (!pa_pdc_cell)
+		panic("couldn't allocate memory for PDC_PAT_CELL!");
+
 	/* return cell module (PA or Processor view) */
 	status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
-				     PA_VIEW, &pa_pdc_cell);
+				     PA_VIEW, pa_pdc_cell);
 
 	if (status != PDC_OK) {
 		/* no more cell modules or error */
 		return status;
 	}
 
-	temp = pa_pdc_cell.cba;
-	dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path);
+	temp = pa_pdc_cell->cba;
+	dev = alloc_pa_dev(PAT_GET_CBA(temp), &(pa_pdc_cell->mod_path));
 	if (!dev) {
 		return PDC_OK;
 	}
@@ -203,8 +207,8 @@
 
 	/* save generic info returned from the call */
 	/* REVISIT: who is the consumer of this? not sure yet... */
-	dev->mod_info = pa_pdc_cell.mod_info;	/* pass to PAT_GET_ENTITY() */
-	dev->pmod_loc = pa_pdc_cell.mod_location;
+	dev->mod_info = pa_pdc_cell->mod_info;	/* pass to PAT_GET_ENTITY() */
+	dev->pmod_loc = pa_pdc_cell->mod_location;
 
 	register_parisc_device(dev);	/* advertise device */
 
@@ -216,14 +220,14 @@
 
 	case PAT_ENTITY_PROC:
 		printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n",
-			pa_pdc_cell.mod[0]);
+			pa_pdc_cell->mod[0]);
 		break;
 
 	case PAT_ENTITY_MEM:
 		printk(KERN_DEBUG 
 			"PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
-			pa_pdc_cell.mod[0], pa_pdc_cell.mod[1], 
-			pa_pdc_cell.mod[2]);
+			pa_pdc_cell->mod[0], pa_pdc_cell->mod[1],
+			pa_pdc_cell->mod[2]);
 		break;
 	case PAT_ENTITY_CA:
 		printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc);
@@ -243,23 +247,26 @@
  print_ranges:
 		pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
 				    IO_VIEW, &io_pdc_cell);
-		printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]);
-		for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
+		printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell->mod[1]);
+		for (i = 0; i < pa_pdc_cell->mod[1]; i++) {
 			printk(KERN_DEBUG 
 				"  PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 
-				i, pa_pdc_cell.mod[2 + i * 3],	/* type */
-				pa_pdc_cell.mod[3 + i * 3],	/* start */
-				pa_pdc_cell.mod[4 + i * 3]);	/* finish (ie end) */
+				i, pa_pdc_cell->mod[2 + i * 3],	/* type */
+				pa_pdc_cell->mod[3 + i * 3],	/* start */
+				pa_pdc_cell->mod[4 + i * 3]);	/* finish (ie end) */
 			printk(KERN_DEBUG 
 				"  IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 
-				i, io_pdc_cell.mod[2 + i * 3],	/* type */
-				io_pdc_cell.mod[3 + i * 3],	/* start */
-				io_pdc_cell.mod[4 + i * 3]);	/* finish (ie end) */
+				i, io_pdc_cell->mod[2 + i * 3],	/* type */
+				io_pdc_cell->mod[3 + i * 3],	/* start */
+				io_pdc_cell->mod[4 + i * 3]);	/* finish (ie end) */
 		}
 		printk(KERN_DEBUG "\n");
 		break;
 	}
 #endif /* DEBUG_PAT */
+
+	kfree(pa_pdc_cell);
+
 	return PDC_OK;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/irq.c linux-libre-2.6.31-gnu/arch/parisc/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -120,7 +120,7 @@
 	if (CHECK_IRQ_PER_CPU(irq)) {
 		/* Bad linux design decision.  The mask has already
 		 * been set; we must reset it */
-		cpumask_setall(&irq_desc[irq].affinity);
+		cpumask_setall(irq_desc[irq].affinity);
 		return -EINVAL;
 	}
 
@@ -130,19 +130,21 @@
 	return cpu_dest;
 }
 
-static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
 {
 	int cpu_dest;
 
 	cpu_dest = cpu_check_affinity(irq, dest);
 	if (cpu_dest < 0)
-		return;
+		return -1;
 
-	cpumask_copy(&irq_desc[irq].affinity, dest);
+	cpumask_copy(irq_desc[irq].affinity, dest);
+
+	return 0;
 }
 #endif
 
-static struct hw_interrupt_type cpu_interrupt_type = {
+static struct irq_chip cpu_interrupt_type = {
 	.typename	= "CPU",
 	.startup	= cpu_startup_irq,
 	.shutdown	= cpu_disable_irq,
@@ -297,7 +299,7 @@
 unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
-	cpumask_copy(&irq_desc[irq].affinity, cpumask_of(cpu));
+	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
 #endif
 
 	return per_cpu(cpu_data, cpu).txn_addr;
@@ -354,7 +356,7 @@
 	irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-	cpumask_copy(&dest, &irq_desc[irq].affinity);
+	cpumask_copy(&dest, irq_desc[irq].affinity);
 	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
 	    !cpu_isset(smp_processor_id(), dest)) {
 		int cpu = first_cpu(dest);
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/module.c linux-libre-2.6.31-gnu/arch/parisc/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,8 +86,12 @@
  * the bottom of the table, which has a maximum signed displacement of
  * 0x3fff; however, since we're only going forward, this becomes
  * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have
- * at most 1023 entries */
-#define MAX_GOTS	1023
+ * at most 1023 entries.
+ * To overcome this 14bit displacement with some kernel modules, we'll
+ * use instead the unusal 16bit displacement method (see reassemble_16a)
+ * which gives us a maximum positive displacement of 0x7fff, and as such
+ * allows us to allocate up to 4095 GOT entries. */
+#define MAX_GOTS	4095
 
 /* three functions to determine where in the module core
  * or init pieces the location is */
@@ -145,12 +149,40 @@
 /* The reassemble_* functions prepare an immediate value for
    insertion into an opcode. pa-risc uses all sorts of weird bitfields
    in the instruction to hold the value.  */
+static inline int sign_unext(int x, int len)
+{
+	int len_ones;
+
+	len_ones = (1 << len) - 1;
+	return x & len_ones;
+}
+
+static inline int low_sign_unext(int x, int len)
+{
+	int sign, temp;
+
+	sign = (x >> (len-1)) & 1;
+	temp = sign_unext(x, len-1);
+	return (temp << 1) | sign;
+}
+
 static inline int reassemble_14(int as14)
 {
 	return (((as14 & 0x1fff) << 1) |
 		((as14 & 0x2000) >> 13));
 }
 
+static inline int reassemble_16a(int as16)
+{
+	int s, t;
+
+	/* Unusual 16-bit encoding, for wide mode only.  */
+	t = (as16 << 1) & 0xffff;
+	s = (as16 & 0x8000);
+	return (t ^ s ^ (s >> 1)) | (s >> 15);
+}
+
+
 static inline int reassemble_17(int as17)
 {
 	return (((as17 & 0x10000) >> 16) |
@@ -267,8 +299,6 @@
 	mod->arch.section = NULL;
 
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* Additional bytes needed in front of individual sections */
@@ -409,6 +439,7 @@
 	enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec)
 {
 	struct stub_entry *stub;
+	int __maybe_unused d;
 
 	/* initialize stub_offset to point in front of the section */
 	if (!me->arch.section[targetsec].stub_offset) {
@@ -462,12 +493,19 @@
  */
 	switch (stub_type) {
 	case ELF_STUB_GOT:
-		stub->insns[0] = 0x537b0000;	/* ldd 0(%dp),%dp	*/
+		d = get_got(me, value, addend);
+		if (d <= 15) {
+			/* Format 5 */
+			stub->insns[0] = 0x0f6010db; /* ldd 0(%dp),%dp	*/
+			stub->insns[0] |= low_sign_unext(d, 5) << 16;
+		} else {
+			/* Format 3 */
+			stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp	*/
+			stub->insns[0] |= reassemble_16a(d);
+		}
 		stub->insns[1] = 0x53610020;	/* ldd 10(%dp),%r1	*/
 		stub->insns[2] = 0xe820d000;	/* bve (%r1)		*/
 		stub->insns[3] = 0x537b0030;	/* ldd 18(%dp),%dp	*/
-
-		stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
 		break;
 	case ELF_STUB_MILLI:
 		stub->insns[0] = 0x20200000;	/* ldil 0,%r1		*/
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/pci.c linux-libre-2.6.31-gnu/arch/parisc/kernel/pci.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,4 @@
-/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $
- *
+/*
  * 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.
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/pci-dma.c linux-libre-2.6.31-gnu/arch/parisc/kernel/pci-dma.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/pci-dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/pci-dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -90,12 +90,14 @@
 	if (end > PMD_SIZE)
 		end = PMD_SIZE;
 	do {
+		unsigned long flags;
+
 		if (!pte_none(*pte))
 			printk(KERN_ERR "map_pte_uncached: page already exists\n");
 		set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
-		purge_tlb_start();
+		purge_tlb_start(flags);
 		pdtlb_kernel(orig_vaddr);
-		purge_tlb_end();
+		purge_tlb_end(flags);
 		vaddr += PAGE_SIZE;
 		orig_vaddr += PAGE_SIZE;
 		(*paddr_ptr) += PAGE_SIZE;
@@ -168,11 +170,13 @@
 	if (end > PMD_SIZE)
 		end = PMD_SIZE;
 	do {
+		unsigned long flags;
 		pte_t page = *pte;
+
 		pte_clear(&init_mm, vaddr, pte);
-		purge_tlb_start();
+		purge_tlb_start(flags);
 		pdtlb_kernel(orig_vaddr);
-		purge_tlb_end();
+		purge_tlb_end(flags);
 		vaddr += PAGE_SIZE;
 		orig_vaddr += PAGE_SIZE;
 		pte++;
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/process.c linux-libre-2.6.31-gnu/arch/parisc/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -156,7 +156,7 @@
 	 * software. The user has to press the button himself. */
 
 	printk(KERN_EMERG "System shut down completed.\n"
-	       KERN_EMERG "Please power this system off now.");
+	       "Please power this system off now.");
 }
 
 void (*pm_power_off)(void) = machine_power_off;
@@ -349,11 +349,6 @@
 		goto out;
 	error = do_execve(filename, (char __user * __user *) regs->gr[25],
 		(char __user * __user *) regs->gr[24], regs);
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
-		task_unlock(current);
-	}
 	putname(filename);
 out:
 
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/processor.c linux-libre-2.6.31-gnu/arch/parisc/kernel/processor.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/processor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/processor.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,4 @@
-/*    $Id: processor.c,v 1.1 2002/07/20 16:27:06 rhirst Exp $
- *
+/*
  *    Initial setup-routines for HP 9000 based hardware.
  *
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
@@ -121,22 +120,28 @@
 	if (is_pdc_pat()) {
 		ulong status;
 		unsigned long bytecnt;
-	        pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+	        pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;
 #undef USE_PAT_CPUID
 #ifdef USE_PAT_CPUID
 		struct pdc_pat_cpu_num cpu_info;
 #endif
 
+		pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL);
+		if (!pa_pdc_cell)
+			panic("couldn't allocate memory for PDC_PAT_CELL!");
+
 		status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc,
-			dev->mod_index, PA_VIEW, &pa_pdc_cell);
+			dev->mod_index, PA_VIEW, pa_pdc_cell);
 
 		BUG_ON(PDC_OK != status);
 
 		/* verify it's the same as what do_pat_inventory() found */
-		BUG_ON(dev->mod_info != pa_pdc_cell.mod_info);
-		BUG_ON(dev->pmod_loc != pa_pdc_cell.mod_location);
+		BUG_ON(dev->mod_info != pa_pdc_cell->mod_info);
+		BUG_ON(dev->pmod_loc != pa_pdc_cell->mod_location);
 
-		txn_addr = pa_pdc_cell.mod[0];   /* id_eid for IO sapic */
+		txn_addr = pa_pdc_cell->mod[0];   /* id_eid for IO sapic */
+
+		kfree(pa_pdc_cell);
 
 #ifdef USE_PAT_CPUID
 /* We need contiguous numbers for cpuid. Firmware's notion
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/setup.c linux-libre-2.6.31-gnu/arch/parisc/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,4 @@
-/*    $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
- *
+/*
  *    Initial setup-routines for HP 9000 based hardware.
  *
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/syscall_table.S linux-libre-2.6.31-gnu/arch/parisc/kernel/syscall_table.S
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/syscall_table.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/syscall_table.S	2009-09-09 18:13:59.000000000 -0400
@@ -413,6 +413,10 @@
 	ENTRY_SAME(dup3)
 	ENTRY_SAME(pipe2)
 	ENTRY_SAME(inotify_init1)
+	ENTRY_COMP(preadv)		/* 315 */
+	ENTRY_COMP(pwritev)
+	ENTRY_COMP(rt_tgsigqueueinfo)
+	ENTRY_SAME(perf_counter_open)
 
 	/* Nothing yet */
 
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/sys_parisc32.c linux-libre-2.6.31-gnu/arch/parisc/kernel/sys_parisc32.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/sys_parisc32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/sys_parisc32.c	2009-09-09 18:13:59.000000000 -0400
@@ -77,11 +77,6 @@
 		goto out;
 	error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
 				 compat_ptr(regs->gr[24]), regs);
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
-		task_unlock(current);
-	}
 	putname(filename);
 out:
 
@@ -179,68 +174,6 @@
 	return ret;
 }
 
-/*** copied from mips64 ***/
-/*
- * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
- * 64-bit unsigned longs.
- */
-
-static inline int
-get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
-{
-	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
-	if (ufdset) {
-		unsigned long odd;
-
-		if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32)))
-			return -EFAULT;
-
-		odd = n & 1UL;
-		n &= ~1UL;
-		while (n) {
-			unsigned long h, l;
-			__get_user(l, ufdset);
-			__get_user(h, ufdset+1);
-			ufdset += 2;
-			*fdset++ = h << 32 | l;
-			n -= 2;
-		}
-		if (odd)
-			__get_user(*fdset, ufdset);
-	} else {
-		/* Tricky, must clear full unsigned long in the
-		 * kernel fdset at the end, this makes sure that
-		 * actually happens.
-		 */
-		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
-	}
-	return 0;
-}
-
-static inline void
-set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
-{
-	unsigned long odd;
-	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
-
-	if (!ufdset)
-		return;
-
-	odd = n & 1UL;
-	n &= ~1UL;
-	while (n) {
-		unsigned long h, l;
-		l = *fdset++;
-		h = l >> 32;
-		__put_user(l, ufdset);
-		__put_user(h, ufdset+1);
-		ufdset += 2;
-		n -= 2;
-	}
-	if (odd)
-		__put_user(*fdset, ufdset);
-}
-
 struct msgbuf32 {
     int mtype;
     char mtext[1];
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/time.c linux-libre-2.6.31-gnu/arch/parisc/kernel/time.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -56,9 +56,9 @@
  */
 irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
 {
-	unsigned long now;
+	unsigned long now, now2;
 	unsigned long next_tick;
-	unsigned long cycles_elapsed, ticks_elapsed;
+	unsigned long cycles_elapsed, ticks_elapsed = 1;
 	unsigned long cycles_remainder;
 	unsigned int cpu = smp_processor_id();
 	struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
@@ -71,44 +71,24 @@
 	/* Initialize next_tick to the expected tick time. */
 	next_tick = cpuinfo->it_value;
 
-	/* Get current interval timer.
-	 * CR16 reads as 64 bits in CPU wide mode.
-	 * CR16 reads as 32 bits in CPU narrow mode.
-	 */
+	/* Get current cycle counter (Control Register 16). */
 	now = mfctl(16);
 
 	cycles_elapsed = now - next_tick;
 
-	if ((cycles_elapsed >> 5) < cpt) {
+	if ((cycles_elapsed >> 6) < cpt) {
 		/* use "cheap" math (add/subtract) instead
 		 * of the more expensive div/mul method
 		 */
 		cycles_remainder = cycles_elapsed;
-		ticks_elapsed = 1;
 		while (cycles_remainder > cpt) {
 			cycles_remainder -= cpt;
 			ticks_elapsed++;
 		}
 	} else {
+		/* TODO: Reduce this to one fdiv op */
 		cycles_remainder = cycles_elapsed % cpt;
-		ticks_elapsed = 1 + cycles_elapsed / cpt;
-	}
-
-	/* Can we differentiate between "early CR16" (aka Scenario 1) and
-	 * "long delay" (aka Scenario 3)? I don't think so.
-	 *
-	 * We expected timer_interrupt to be delivered at least a few hundred
-	 * cycles after the IT fires. But it's arbitrary how much time passes
-	 * before we call it "late". I've picked one second.
-	 */
-	if (unlikely(ticks_elapsed > HZ)) {
-		/* Scenario 3: very long delay?  bad in any case */
-		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
-			" cycles %lX rem %lX "
-			" next/now %lX/%lX\n",
-			cpu,
-			cycles_elapsed, cycles_remainder,
-			next_tick, now );
+		ticks_elapsed += cycles_elapsed / cpt;
 	}
 
 	/* convert from "division remainder" to "remainder of clock tick" */
@@ -122,18 +102,56 @@
 
 	cpuinfo->it_value = next_tick;
 
-	/* Skip one clocktick on purpose if we are likely to miss next_tick.
-	 * We want to avoid the new next_tick being less than CR16.
-	 * If that happened, itimer wouldn't fire until CR16 wrapped.
-	 * We'll catch the tick we missed on the tick after that.
+	/* Program the IT when to deliver the next interrupt.
+	 * Only bottom 32-bits of next_tick are writable in CR16!
 	 */
-	if (!(cycles_remainder >> 13))
-		next_tick += cpt;
-
-	/* Program the IT when to deliver the next interrupt. */
-	/* Only bottom 32-bits of next_tick are written to cr16.  */
 	mtctl(next_tick, 16);
 
+	/* Skip one clocktick on purpose if we missed next_tick.
+	 * The new CR16 must be "later" than current CR16 otherwise
+	 * itimer would not fire until CR16 wrapped - e.g 4 seconds
+	 * later on a 1Ghz processor. We'll account for the missed
+	 * tick on the next timer interrupt.
+	 *
+	 * "next_tick - now" will always give the difference regardless
+	 * if one or the other wrapped. If "now" is "bigger" we'll end up
+	 * with a very large unsigned number.
+	 */
+	now2 = mfctl(16);
+	if (next_tick - now2 > cpt)
+		mtctl(next_tick+cpt, 16);
+
+#if 1
+/*
+ * GGG: DEBUG code for how many cycles programming CR16 used.
+ */
+	if (unlikely(now2 - now > 0x3000)) 	/* 12K cycles */
+		printk (KERN_CRIT "timer_interrupt(CPU %d): SLOW! 0x%lx cycles!"
+			" cyc %lX rem %lX "
+			" next/now %lX/%lX\n",
+			cpu, now2 - now, cycles_elapsed, cycles_remainder,
+			next_tick, now );
+#endif
+
+	/* Can we differentiate between "early CR16" (aka Scenario 1) and
+	 * "long delay" (aka Scenario 3)? I don't think so.
+	 *
+	 * Timer_interrupt will be delivered at least a few hundred cycles
+	 * after the IT fires. But it's arbitrary how much time passes
+	 * before we call it "late". I've picked one second.
+	 *
+	 * It's important NO printk's are between reading CR16 and
+	 * setting up the next value. May introduce huge variance.
+	 */
+	if (unlikely(ticks_elapsed > HZ)) {
+		/* Scenario 3: very long delay?  bad in any case */
+		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
+			" cycles %lX rem %lX "
+			" next/now %lX/%lX\n",
+			cpu,
+			cycles_elapsed, cycles_remainder,
+			next_tick, now );
+	}
 
 	/* Done mucking with unreliable delivery of interrupts.
 	 * Go do system house keeping.
@@ -173,7 +191,7 @@
 
 /* clock source code */
 
-static cycle_t read_cr16(void)
+static cycle_t read_cr16(struct clocksource *cs)
 {
 	return get_cycles();
 }
diff -druN linux-libre-2.6.30-gnu/arch/parisc/kernel/traps.c linux-libre-2.6.31-gnu/arch/parisc/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/parisc/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -250,15 +250,14 @@
 	oops_enter();
 
 	/* Amuse the user in a SPARC fashion */
-	if (err) printk(
-KERN_CRIT "      _______________________________ \n"
-KERN_CRIT "     < Your System ate a SPARC! Gah! >\n"
-KERN_CRIT "      ------------------------------- \n"
-KERN_CRIT "             \\   ^__^\n"
-KERN_CRIT "              \\  (xx)\\_______\n"
-KERN_CRIT "                 (__)\\       )\\/\\\n"
-KERN_CRIT "                  U  ||----w |\n"
-KERN_CRIT "                     ||     ||\n");
+	if (err) printk(KERN_CRIT
+			"      _______________________________ \n"
+			"     < Your System ate a SPARC! Gah! >\n"
+			"      ------------------------------- \n"
+			"             \\   ^__^\n"
+			"                 (__)\\       )\\/\\\n"
+			"                  U  ||----w |\n"
+			"                     ||     ||\n");
 	
 	/* unlock the pdc lock if necessary */
 	pdc_emergency_unlock();
@@ -533,7 +532,7 @@
 	  	/* Kill the user process later */
 	  	regs->iaoq[0] = 0 | 3;
 		regs->iaoq[1] = regs->iaoq[0] + 4;
-	 	regs->iasq[0] = regs->iasq[0] = regs->sr[7];
+	 	regs->iasq[0] = regs->iasq[1] = regs->sr[7];
 		regs->gr[0] &= ~PSW_B;
 		return;
 	}
@@ -797,7 +796,8 @@
 		else
 			printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
 			       code);
-		printk("pid=%d command='%s'\n", task_pid_nr(current), current->comm);
+		printk(KERN_CONT "pid=%d command='%s'\n",
+		       task_pid_nr(current), current->comm);
 		show_regs(regs);
 #endif
 		si.si_signo = SIGSEGV;
diff -druN linux-libre-2.6.30-gnu/arch/parisc/lib/checksum.c linux-libre-2.6.31-gnu/arch/parisc/lib/checksum.c
--- linux-libre-2.6.30-gnu/arch/parisc/lib/checksum.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/lib/checksum.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,8 +13,6 @@
  *		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.
- *
- * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $
  */
 #include <linux/module.h>
 #include <linux/types.h>
diff -druN linux-libre-2.6.30-gnu/arch/parisc/lib/memcpy.c linux-libre-2.6.31-gnu/arch/parisc/lib/memcpy.c
--- linux-libre-2.6.30-gnu/arch/parisc/lib/memcpy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/lib/memcpy.c	2009-09-09 18:13:59.000000000 -0400
@@ -405,7 +405,7 @@
 
 unaligned_copy:
 	/* possibly we are aligned on a word, but not on a double... */
-	if (likely(t1 & (sizeof(unsigned int)-1)) == 0) {
+	if (likely((t1 & (sizeof(unsigned int)-1)) == 0)) {
 		t2 = src & (sizeof(unsigned int) - 1);
 
 		if (unlikely(t2 != 0)) {
diff -druN linux-libre-2.6.30-gnu/arch/parisc/math-emu/decode_exc.c linux-libre-2.6.31-gnu/arch/parisc/math-emu/decode_exc.c
--- linux-libre-2.6.30-gnu/arch/parisc/math-emu/decode_exc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/math-emu/decode_exc.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
  * END_DESC
 */
 
-
+#include <linux/kernel.h>
 #include "float.h"
 #include "sgl_float.h"
 #include "dbl_float.h"
diff -druN linux-libre-2.6.30-gnu/arch/parisc/mm/fault.c linux-libre-2.6.31-gnu/arch/parisc/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/parisc/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,4 @@
-/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $
- *
+/*
  * 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.
@@ -202,7 +201,7 @@
 	 * fault.
 	 */
 
-	fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0);
+	fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		/*
 		 * We hit a shared mapping outside of the file, or some
diff -druN linux-libre-2.6.30-gnu/arch/parisc/mm/init.c linux-libre-2.6.31-gnu/arch/parisc/mm/init.c
--- linux-libre-2.6.30-gnu/arch/parisc/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/parisc/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -370,34 +370,22 @@
 
 void free_initmem(void)
 {
-	unsigned long addr, init_begin, init_end;
-
-	printk(KERN_INFO "Freeing unused kernel memory: ");
+	unsigned long addr;
+	unsigned long init_begin = (unsigned long)__init_begin;
+	unsigned long init_end = (unsigned long)__init_end;
 
 #ifdef CONFIG_DEBUG_KERNEL
 	/* Attempt to catch anyone trying to execute code here
 	 * by filling the page with BRK insns.
-	 * 
-	 * If we disable interrupts for all CPUs, then IPI stops working.
-	 * Kinda breaks the global cache flushing.
 	 */
-	local_irq_disable();
-
-	memset(__init_begin, 0x00,
-		(unsigned long)__init_end - (unsigned long)__init_begin);
-
-	flush_data_cache();
-	asm volatile("sync" : : );
-	flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
-	asm volatile("sync" : : );
-
-	local_irq_enable();
+	memset((void *)init_begin, 0x00, init_end - init_begin);
+	flush_icache_range(init_begin, init_end);
 #endif
 	
 	/* align __init_begin and __init_end to page size,
 	   ignoring linker script where we might have tried to save RAM */
-	init_begin = PAGE_ALIGN((unsigned long)(__init_begin));
-	init_end   = PAGE_ALIGN((unsigned long)(__init_end));
+	init_begin = PAGE_ALIGN(init_begin);
+	init_end = PAGE_ALIGN(init_end);
 	for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
@@ -409,7 +397,8 @@
 	/* set up a new led state on systems shipped LED State panel */
 	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
 	
-	printk("%luk freed\n", (init_end - init_begin) >> 10);
+	printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n",
+		(init_end - init_begin) >> 10);
 }
 
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/cuboot-85xx.c linux-libre-2.6.31-gnu/arch/powerpc/boot/cuboot-85xx.c
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/cuboot-85xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/cuboot-85xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include "cuboot.h"
 
 #define TARGET_85xx
+#define TARGET_HAS_ETH3
 #include "ppcboot.h"
 
 static bd_t bd;
@@ -27,6 +28,7 @@
 	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
 	dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
 	dt_fixup_mac_address_by_alias("ethernet2", bd.bi_enet2addr);
+	dt_fixup_mac_address_by_alias("ethernet3", bd.bi_enet3addr);
 	dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 8, bd.bi_busfreq);
 
 	/* Unfortunately, the specific model number is encoded in the
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/amigaone.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/amigaone.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/amigaone.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/amigaone.dts	2009-09-09 18:13:59.000000000 -0400
@@ -70,8 +70,8 @@
 			devsel-speed = <0x00000001>;
 			min-grant = <0>;
 			max-latency = <0>;
-			/* First 64k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */
-			ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00010000>;
+			/* First 4k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */
+			ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00001000>;
 			interrupt-parent = <&i8259>;
 			#interrupt-cells = <2>;
 			#address-cells = <2>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/asp834x-redboot.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/asp834x-redboot.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/asp834x-redboot.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/asp834x-redboot.dts	2009-09-09 18:13:59.000000000 -0400
@@ -167,7 +167,7 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <39 0x8>;
 			phy_type = "ulpi";
-			port1;
+			port0;
 		};
 		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
 		usb@23000 {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/gef_ppc9a.dts	2009-09-09 18:13:59.000000000 -0400
@@ -164,9 +164,21 @@
 		device_type = "soc";
 		compatible = "fsl,mpc8641-soc", "simple-bus";
 		ranges = <0x0 0xfef00000 0x00100000>;
-		reg = <0xfef00000 0x100000>;	// CCSRBAR 1M
 		bus-frequency = <33333333>;
 
+		mcm-law@0 {
+			compatible = "fsl,mcm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		mcm@1000 {
+			compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		i2c1: i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/gef_sbc310.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/gef_sbc310.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/gef_sbc310.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/gef_sbc310.dts	2009-09-09 18:13:59.000000000 -0400
@@ -163,9 +163,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xfef00000 0x00100000>;
-		reg = <0xfef00000 0x100000>;	// CCSRBAR 1M
 		bus-frequency = <33333333>;
 
+		mcm-law@0 {
+			compatible = "fsl,mcm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		mcm@1000 {
+			compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		i2c1: i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/gef_sbc610.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/gef_sbc610.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/gef_sbc610.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/gef_sbc610.dts	2009-09-09 18:13:59.000000000 -0400
@@ -128,9 +128,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xfef00000 0x00100000>;
-		reg = <0xfef00000 0x100000>;	// CCSRBAR 1M
 		bus-frequency = <33333333>;
 
+		mcm-law@0 {
+			compatible = "fsl,mcm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		mcm@1000 {
+			compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		i2c1: i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -140,6 +152,16 @@
 			interrupt-parent = <&mpic>;
 			dfsrr;
 
+			hwmon@48 {
+				compatible = "national,lm92";
+				reg = <0x48>;
+			};
+
+			hwmon@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+
 			rtc@51 {
 				compatible = "epson,rx8581";
 				reg = <0x00000051>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/kmeter1.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/kmeter1.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/kmeter1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/kmeter1.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,520 @@
+/*
+ * Keymile KMETER1 Device Tree Source
+ *
+ * 2008 DENX Software Engineering GmbH
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "KMETER1";
+	compatible = "keymile,KMETER1";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet_piggy2;
+		ethernet1 = &enet_estar1;
+		ethernet2 = &enet_estar2;
+		ethernet3 = &enet_eth1;
+		ethernet4 = &enet_eth2;
+		ethernet5 = &enet_eth3;
+		ethernet6 = &enet_eth4;
+		serial0 = &serial0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8360@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	/* Filled in by U-Boot */
+			bus-frequency = <0>;	/* Filled in by U-Boot */
+			clock-frequency = <0>;	/* Filled in by U-Boot */
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0>;	/* Filled in by U-Boot */
+	};
+
+	soc8360@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8360-immr", "simple-bus";
+		ranges = <0x0 0xe0000000 0x00200000>;
+		reg = <0xe0000000 0x00000200>;
+		bus-frequency = <0>;	/* Filled in by U-Boot */
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <14 0x8>;
+			interrupt-parent = <&ipic>;
+			dfsrr;
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <264000000>;
+			interrupts = <9 0x8>;
+			interrupt-parent = <&ipic>;
+		};
+
+		dma@82a8 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8360-dma", "fsl,elo-dma";
+			reg = <0x82a8 4>;
+			ranges = <0 0x8100 0x1a8>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
+				reg = <0 0x80>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
+				reg = <0x80 0x80>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
+				reg = <0x100 0x80>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
+				reg = <0x180 0x28>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+			};
+		};
+
+		ipic: pic@700 {
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			compatible = "fsl,pq2pro-pic", "fsl,ipic";
+			interrupt-controller;
+			reg = <0x700 0x100>;
+		};
+
+		par_io@1400 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x1400 0x100>;
+			compatible = "fsl,mpc8360-par_io";
+			num-ports = <7>;
+
+			pio_ucc1: ucc_pin@0 {
+				reg = <0>;
+
+				pio-map = <
+					/* port pin dir open_drain assignment has_irq */
+					0   1  3  0  2  0	/* MDIO   */
+					0   2  1  0  1  0	/* MDC    */
+
+					0   3  1  0  1  0	/* TxD0   */
+					0   4  1  0  1  0	/* TxD1   */
+					0   5  1  0  1  0	/* TxD2   */
+					0   6  1  0  1  0	/* TxD3   */
+					0   9  2  0  1  0	/* RxD0   */
+					0  10  2  0  1  0	/* RxD1   */
+					0  11  2  0  1  0	/* RxD2   */
+					0  12  2  0  1  0	/* RxD3   */
+					0   7  1  0  1  0	/* TX_EN  */
+					0   8  1  0  1  0	/* TX_ER  */
+					0  15  2  0  1  0	/* RX_DV  */
+					0  16  2  0  1  0	/* RX_ER  */
+					0   0  2  0  1  0	/* RX_CLK */
+					2   9  1  0  3  0	/* GTX_CLK - CLK10 */
+					2   8  2  0  1  0	/* GTX125  - CLK9  */
+				>;
+			};
+
+			pio_ucc2: ucc_pin@1 {
+				reg = <1>;
+
+				pio-map = <
+					/* port pin dir open_drain assignment has_irq */
+					0   1  3  0  2  0	/* MDIO   */
+					0   2  1  0  1  0	/* MDC    */
+
+					0  17  1  0  1  0	/* TxD0   */
+					0  18  1  0  1  0	/* TxD1   */
+					0  19  1  0  1  0	/* TxD2   */
+					0  20  1  0  1  0	/* TxD3   */
+					0  23  2  0  1  0	/* RxD0   */
+					0  24  2  0  1  0	/* RxD1   */
+					0  25  2  0  1  0	/* RxD2   */
+					0  26  2  0  1  0	/* RxD3   */
+					0  21  1  0  1  0	/* TX_EN  */
+					0  22  1  0  1  0	/* TX_ER  */
+					0  29  2  0  1  0	/* RX_DV  */
+					0  30  2  0  1  0	/* RX_ER  */
+					0  31  2  0  1  0	/* RX_CLK */
+					2  2   1  0  2  0	/* GTX_CLK - CLK3  */
+					2  3   2  0  1  0	/* GTX125  - CLK4  */
+				>;
+			};
+
+			pio_ucc4: ucc_pin@3 {
+				reg = <3>;
+
+				pio-map = <
+					/* port pin dir open_drain assignment has_irq */
+					0   1  3  0  2  0	/* MDIO */
+					0   2  1  0  1  0	/* MDC  */
+
+					1  14  1  0  1  0	/* TxD0   (PB14, out, f1) */
+					1  15  1  0  1  0	/* TxD1   (PB15, out, f1) */
+					1  20  2  0  1  0	/* RxD0   (PB20, in,  f1) */
+					1  21  2  0  1  0	/* RxD1   (PB21, in,  f1) */
+					1  18  1  0  1  0	/* TX_EN  (PB18, out, f1) */
+					1  26  2  0  1  0	/* RX_DV  (PB26, in,  f1) */
+					1  27  2  0  1  0	/* RX_ER  (PB27, in,  f1) */
+
+					2  16  2  0  1  0	/* UCC4_RMII_CLK (CLK17) */
+				>;
+			};
+
+			pio_ucc5: ucc_pin@4 {
+				reg = <4>;
+
+				pio-map = <
+					/* port pin dir open_drain assignment has_irq */
+					0   1  3  0  2  0	/* MDIO */
+					0   2  1  0  1  0	/* MDC  */
+
+					3   0  1  0  1  0	/* TxD0  (PD0,  out, f1) */
+					3   1  1  0  1  0	/* TxD1  (PD1,  out, f1) */
+					3   6  2  0  1  0	/* RxD0  (PD6,   in, f1) */
+					3   7  2  0  1  0	/* RxD1  (PD7,   in, f1) */
+					3   4  1  0  1  0	/* TX_EN (PD4,  out, f1) */
+					3  12  2  0  1  0	/* RX_DV (PD12,  in, f1) */
+					3  13  2  0  1  0	/* RX_ER (PD13,  in, f1) */
+				>;
+			};
+
+			pio_ucc6: ucc_pin@5 {
+				reg = <5>;
+
+				pio-map = <
+					/* port pin dir open_drain assignment has_irq */
+					0   1  3  0  2  0	/* MDIO */
+					0   2  1  0  1  0	/* MDC  */
+
+					3  14  1  0  1  0	/* TxD0   (PD14, out, f1) */
+					3  15  1  0  1  0	/* TxD1   (PD15, out, f1) */
+					3  20  2  0  1  0	/* RxD0   (PD20, in,  f1) */
+					3  21  2  0  1  0	/* RxD1   (PD21, in,  f1) */
+					3  18  1  0  1  0	/* TX_EN  (PD18, out, f1) */
+					3  26  2  0  1  0	/* RX_DV  (PD26, in,  f1) */
+					3  27  2  0  1  0	/* RX_ER  (PD27, in,  f1) */
+				>;
+			};
+
+			pio_ucc7: ucc_pin@6 {
+				reg = <6>;
+
+				pio-map = <
+					/* port pin dir open_drain assignment has_irq */
+					0   1  3  0  2  0	/* MDIO */
+					0   2  1  0  1  0	/* MDC  */
+
+					4   0  1  0  1  0	/* TxD0   (PE0,  out, f1) */
+					4   1  1  0  1  0	/* TxD1   (PE1,  out, f1) */
+					4   6  2  0  1  0	/* RxD0   (PE6,   in, f1) */
+					4   7  2  0  1  0	/* RxD1   (PE7,   in, f1) */
+					4   4  1  0  1  0	/* TX_EN  (PE4,  out, f1) */
+					4  12  2  0  1  0	/* RX_DV  (PE12,  in, f1) */
+					4  13  2  0  1  0	/* RX_ER  (PE13,  in, f1) */
+				>;
+			};
+
+			pio_ucc8: ucc_pin@7 {
+				reg = <7>;
+
+				pio-map = <
+					/* port pin dir open_drain assignment has_irq */
+					0   1  3  0  2  0	/* MDIO */
+					0   2  1  0  1  0	/* MDC  */
+
+					4  14  1  0  2  0	/* TxD0   (PE14, out, f2) */
+					4  15  1  0  1  0	/* TxD1   (PE15, out, f1) */
+					4  20  2  0  1  0	/* RxD0   (PE20, in,  f1) */
+					4  21  2  0  1  0	/* RxD1   (PE21, in,  f1) */
+					4  18  1  0  1  0	/* TX_EN  (PE18, out, f1) */
+					4  26  2  0  1  0	/* RX_DV  (PE26, in,  f1) */
+					4  27  2  0  1  0	/* RX_ER  (PE27, in,  f1) */
+
+					2  15  2  0  1  0	/* UCCx_RMII_CLK (CLK16) */
+				>;
+			};
+
+		};
+
+		qe@100000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,qe";
+			ranges = <0x0 0x100000 0x100000>;
+			reg = <0x100000 0x480>;
+			clock-frequency = <0>;	/* Filled in by U-Boot */
+			brg-frequency = <0>;	/* Filled in by U-Boot */
+			bus-frequency = <0>;	/* Filled in by U-Boot */
+
+			muram@10000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,qe-muram", "fsl,cpm-muram";
+				ranges = <0x0 0x00010000 0x0000c000>;
+
+				data-only@0 {
+					compatible = "fsl,qe-muram-data",
+						     "fsl,cpm-muram-data";
+					reg = <0x0 0xc000>;
+				};
+			};
+
+			/* ESTAR-1 (UCC1, MDIO 0x10, RGMII) */
+			enet_estar1: ucc@2000 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <1>;
+				reg = <0x2000 0x200>;
+				interrupts = <32>;
+				interrupt-parent = <&qeic>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				rx-clock-name = "none";
+				tx-clock-name = "clk9";
+				phy-handle = <&phy_estar1>;
+				phy-connection-type = "rgmii-id";
+				pio-handle = <&pio_ucc1>;
+			};
+
+			/* ESTAR-2 (UCC2, MDIO 0x11, RGMII) */
+			enet_estar2: ucc@3000 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <2>;
+				reg = <0x3000 0x200>;
+				interrupts = <33>;
+				interrupt-parent = <&qeic>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				rx-clock-name = "none";
+				tx-clock-name = "clk4";
+				phy-handle = <&phy_estar2>;
+				phy-connection-type = "rgmii-id";
+				pio-handle = <&pio_ucc2>;
+			};
+
+			/* Piggy2 (UCC4, MDIO 0x00, RMII) */
+			enet_piggy2: ucc@3200 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <4>;
+				reg = <0x3200 0x200>;
+				interrupts = <35>;
+				interrupt-parent = <&qeic>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				rx-clock-name = "none";
+				tx-clock-name = "clk17";
+				phy-handle = <&phy_piggy2>;
+				phy-connection-type = "rmii";
+				pio-handle = <&pio_ucc4>;
+			};
+
+			/* Eth-1 (UCC5, MDIO 0x08, RMII) */
+			enet_eth1: ucc@2400 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <5>;
+				reg = <0x2400 0x200>;
+				interrupts = <40>;
+				interrupt-parent = <&qeic>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				rx-clock-name = "none";
+				tx-clock-name = "clk16";
+				phy-handle = <&phy_eth1>;
+				phy-connection-type = "rmii";
+				pio-handle = <&pio_ucc5>;
+			};
+
+			/* Eth-2 (UCC6, MDIO 0x09, RMII) */
+			enet_eth2: ucc@3400 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <6>;
+				reg = <0x3400 0x200>;
+				interrupts = <41>;
+				interrupt-parent = <&qeic>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				rx-clock-name = "none";
+				tx-clock-name = "clk16";
+				phy-handle = <&phy_eth2>;
+				phy-connection-type = "rmii";
+				pio-handle = <&pio_ucc6>;
+			};
+
+			/* Eth-3 (UCC7, MDIO 0x0a, RMII) */
+			enet_eth3: ucc@2600 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <7>;
+				reg = <0x2600 0x200>;
+				interrupts = <42>;
+				interrupt-parent = <&qeic>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				rx-clock-name = "none";
+				tx-clock-name = "clk16";
+				phy-handle = <&phy_eth3>;
+				phy-connection-type = "rmii";
+				pio-handle = <&pio_ucc7>;
+			};
+
+			/* Eth-4 (UCC8, MDIO 0x0b, RMII) */
+			enet_eth4: ucc@3600 {
+				device_type = "network";
+				compatible = "ucc_geth";
+				cell-index = <8>;
+				reg = <0x3600 0x200>;
+				interrupts = <43>;
+				interrupt-parent = <&qeic>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				rx-clock-name = "none";
+				tx-clock-name = "clk16";
+				phy-handle = <&phy_eth4>;
+				phy-connection-type = "rmii";
+				pio-handle = <&pio_ucc8>;
+			};
+
+			mdio@3320 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x3320 0x18>;
+				compatible = "fsl,ucc-mdio";
+
+				/* Piggy2 (UCC4, MDIO 0x00, RMII) */
+				phy_piggy2: ethernet-phy@00 {
+					reg = <0x0>;
+				};
+
+				/* Eth-1 (UCC5, MDIO 0x08, RMII) */
+				phy_eth1: ethernet-phy@08 {
+					reg = <0x08>;
+				};
+
+				/* Eth-2 (UCC6, MDIO 0x09, RMII) */
+				phy_eth2: ethernet-phy@09 {
+					reg = <0x09>;
+				};
+
+				/* Eth-3 (UCC7, MDIO 0x0a, RMII) */
+				phy_eth3: ethernet-phy@0a {
+					reg = <0x0a>;
+				};
+
+				/* Eth-4 (UCC8, MDIO 0x0b, RMII) */
+				phy_eth4: ethernet-phy@0b {
+					reg = <0x0b>;
+				};
+
+				/* ESTAR-1 (UCC1, MDIO 0x10, RGMII) */
+				phy_estar1: ethernet-phy@10 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x10>;
+				};
+
+				/* ESTAR-2 (UCC2, MDIO 0x11, RGMII) */
+				phy_estar2: ethernet-phy@11 {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x11>;
+				};
+			};
+
+			qeic: interrupt-controller@80 {
+				interrupt-controller;
+				compatible = "fsl,qe-ic";
+				#address-cells = <0>;
+				#interrupt-cells = <1>;
+				reg = <0x80 0x80>;
+				interrupts = <32 8 33 8>;
+				interrupt-parent = <&ipic>;
+			};
+		};
+	};
+
+	localbus@e0005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
+			     "simple-bus";
+		reg = <0xe0005000 0xd8>;
+		ranges = <0 0 0xf0000000 0x04000000>;	/* Filled in by U-Boot */
+
+		flash@f0000000,0 {
+			compatible = "cfi-flash";
+			/*
+			 * The Intel P30 chip has 2 non-identical chips on
+			 * one die, so we need to define 2 seperate regions
+			 * that are scanned by physmap_of independantly.
+			 */
+			reg = <0 0x00000000 0x02000000
+			       0 0x02000000 0x02000000>;	/* Filled in by U-Boot */
+			bank-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "u-boot";
+				reg = <0 0x40000>;
+			};
+			partition@40000 {
+				label = "env";
+				reg = <0x40000 0x40000>;
+			};
+			partition@80000 {
+				label = "dtb";
+				reg = <0x80000 0x20000>;
+			};
+			partition@a0000 {
+				label = "kernel";
+				reg = <0xa0000 0x300000>;
+			};
+			partition@3a0000 {
+				label = "ramdisk";
+				reg = <0x3a0000 0x800000>;
+			};
+			partition@ba0000 {
+				label = "user";
+				reg = <0xba0000 0x3460000>;
+			};
+		};
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/ksi8560.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/ksi8560.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/ksi8560.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/ksi8560.dts	2009-09-09 18:13:59.000000000 -0400
@@ -56,6 +56,19 @@
 		ranges = <0x00000000 0xfdf00000 0x00100000>;
 		bus-frequency = <0>;				/* Fixed by bootwrapper */
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8540-memory-controller";
 			reg = <0x2000 0x1000>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8272ads.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8272ads.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8272ads.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8272ads.dts	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,13 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+		serial0 = &scc1;
+		serial1 = &scc4;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -46,13 +53,13 @@
 		#size-cells = <1>;
 		reg = <0xf0010100 0x40>;
 
-		ranges = <0x0 0x0 0xfe000000 0x2000000
+		ranges = <0x0 0x0 0xff800000 0x00800000
 		          0x1 0x0 0xf4500000 0x8000
 		          0x3 0x0 0xf8200000 0x8000>;
 
 		flash@0,0 {
 			compatible = "jedec-flash";
-			reg = <0x0 0x0 0x2000000>;
+			reg = <0x0 0x0 0x00800000>;
 			bank-width = <4>;
 			device-width = <1>;
 		};
@@ -144,7 +151,7 @@
 				reg = <0x119f0 0x10 0x115f0 0x10>;
 			};
 
-			serial@11a00 {
+			scc1: serial@11a00 {
 				device_type = "serial";
 				compatible = "fsl,mpc8272-scc-uart",
 				             "fsl,cpm2-scc-uart";
@@ -155,7 +162,7 @@
 				fsl,cpm-command = <0x800000>;
 			};
 
-			serial@11a60 {
+			scc4: serial@11a60 {
 				device_type = "serial";
 				compatible = "fsl,mpc8272-scc-uart",
 				             "fsl,cpm2-scc-uart";
@@ -192,7 +199,7 @@
 				};
 			};
 
-			ethernet@11300 {
+			eth0: ethernet@11300 {
 				device_type = "network";
 				compatible = "fsl,mpc8272-fcc-enet",
 				             "fsl,cpm2-fcc-enet";
@@ -205,7 +212,7 @@
 				fsl,cpm-command = <0x12000300>;
 			};
 
-			ethernet@11320 {
+			eth1: ethernet@11320 {
 				device_type = "network";
 				compatible = "fsl,mpc8272-fcc-enet",
 				             "fsl,cpm2-fcc-enet";
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8315erdb.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8315erdb.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8315erdb.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8315erdb.dts	2009-09-09 18:13:59.000000000 -0400
@@ -322,6 +322,21 @@
 			reg = <0x700 0x100>;
 			device_type = "ipic";
 		};
+
+		ipic-msi@7c0 {
+			compatible = "fsl,ipic-msi";
+			reg = <0x7c0 0x40>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <0x43 0x8
+				      0x4  0x8
+				      0x51 0x8
+				      0x52 0x8
+				      0x56 0x8
+				      0x57 0x8
+				      0x58 0x8
+				      0x59 0x8>;
+			interrupt-parent = < &ipic >;
+		};
 	};
 
 	pci0: pci@e0008500 {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc832x_mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc832x_mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc832x_mds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc832x_mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -249,6 +249,8 @@
 		reg = <0xe0100000 0x480>;
 		brg-frequency = <0>;
 		bus-frequency = <198000000>;
+		fsl,qe-num-riscs = <1>;
+		fsl,qe-num-snums = <28>;
 
 		muram@10000 {
 			#address-cells = <1>;
@@ -369,7 +371,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 				/* IDSEL 0x11 AD17 */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc832x_rdb.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc832x_rdb.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc832x_rdb.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc832x_rdb.dts	2009-09-09 18:13:59.000000000 -0400
@@ -221,6 +221,8 @@
 		reg = <0xe0100000 0x480>;
 		brg-frequency = <0>;
 		bus-frequency = <198000000>;
+		fsl,qe-num-riscs = <1>;
+		fsl,qe-num-snums = <28>;
 
 		muram@10000 {
  			#address-cells = <1>;
@@ -327,7 +329,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 				/* IDSEL 0x10 AD16 (USB) */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8349emitx.dts	2009-09-09 18:13:59.000000000 -0400
@@ -156,7 +156,7 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <39 0x8>;
 			phy_type = "ulpi";
-			port1;
+			port0;
 		};
 
 		usb@23000 {
@@ -278,7 +278,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 				/* IDSEL 0x10 - SATA */
@@ -301,7 +300,6 @@
 	};
 
 	pci1: pci@e0008600 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 				/* IDSEL 0x0E - MiniPCI Slot */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8349emitxgp.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8349emitxgp.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8349emitxgp.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8349emitxgp.dts	2009-09-09 18:13:59.000000000 -0400
@@ -227,7 +227,6 @@
 	};
 
 	pci0: pci@e0008600 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 				/* IDSEL 0x0F - PCI Slot */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc834x_mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc834x_mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc834x_mds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc834x_mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -153,7 +153,7 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <39 0x8>;
 			phy_type = "ulpi";
-			port1;
+			port0;
 		};
 		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
 		usb@23000 {
@@ -286,7 +286,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
@@ -348,7 +347,6 @@
 	};
 
 	pci1: pci@e0008600 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc836x_mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc836x_mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc836x_mds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc836x_mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -289,6 +289,8 @@
 		reg = <0xe0100000 0x480>;
 		brg-frequency = <0>;
 		bus-frequency = <396000000>;
+		fsl,qe-num-riscs = <2>;
+		fsl,qe-num-snums = <28>;
 
 		muram@10000 {
  			#address-cells = <1>;
@@ -410,7 +412,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc836x_rdk.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc836x_rdk.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc836x_rdk.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc836x_rdk.dts	2009-09-09 18:13:59.000000000 -0400
@@ -198,6 +198,8 @@
 			clock-frequency = <0>;
 			bus-frequency = <0>;
 			brg-frequency = <0>;
+			fsl,qe-num-riscs = <2>;
+			fsl,qe-num-snums = <28>;
 
 			muram@10000 {
 				#address-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8377_mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8377_mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8377_mds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8377_mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -155,7 +155,7 @@
 			};
 
 			sdhci@2e000 {
-				compatible = "fsl,mpc8377-esdhc", "fsl,mpc8379-esdhc";
+				compatible = "fsl,mpc8377-esdhc", "fsl,esdhc";
 				reg = <0x2e000 0x1000>;
 				interrupts = <42 0x8>;
 				interrupt-parent = <&ipic>;
@@ -383,7 +383,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8377_rdb.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8377_rdb.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8377_rdb.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8377_rdb.dts	2009-09-09 18:13:59.000000000 -0400
@@ -169,7 +169,7 @@
 			};
 
 			sdhci@2e000 {
-				compatible = "fsl,mpc8377-esdhc", "fsl,mpc8379-esdhc";
+				compatible = "fsl,mpc8377-esdhc", "fsl,esdhc";
 				reg = <0x2e000 0x1000>;
 				interrupts = <42 0x8>;
 				interrupt-parent = <&ipic>;
@@ -410,7 +410,7 @@
 		bus-range = <0 0>;
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-		          0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		          0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
 		sleep = <&pmc 0x00010000>;
 		clock-frequency = <66666666>;
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8378_mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8378_mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8378_mds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8378_mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -155,7 +155,7 @@
 			};
 
 			sdhci@2e000 {
-				compatible = "fsl,mpc8378-esdhc", "fsl,mpc8379-esdhc";
+				compatible = "fsl,mpc8378-esdhc", "fsl,esdhc";
 				reg = <0x2e000 0x1000>;
 				interrupts = <42 0x8>;
 				interrupt-parent = <&ipic>;
@@ -367,7 +367,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8378_rdb.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8378_rdb.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8378_rdb.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8378_rdb.dts	2009-09-09 18:13:59.000000000 -0400
@@ -169,7 +169,7 @@
 			};
 
 			sdhci@2e000 {
-				compatible = "fsl,mpc8378-esdhc", "fsl,mpc8379-esdhc";
+				compatible = "fsl,mpc8378-esdhc", "fsl,esdhc";
 				reg = <0x2e000 0x1000>;
 				interrupts = <42 0x8>;
 				interrupt-parent = <&ipic>;
@@ -394,7 +394,7 @@
 		bus-range = <0 0>;
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-		          0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		          0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
 		sleep = <&pmc 0x00010000>;
 		clock-frequency = <66666666>;
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8379_mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8379_mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8379_mds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8379_mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -153,7 +153,7 @@
 			};
 
 			sdhci@2e000 {
-				compatible = "fsl,mpc8379-esdhc";
+				compatible = "fsl,mpc8379-esdhc", "fsl,esdhc";
 				reg = <0x2e000 0x1000>;
 				interrupts = <42 0x8>;
 				interrupt-parent = <&ipic>;
@@ -397,7 +397,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8379_rdb.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8379_rdb.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8379_rdb.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8379_rdb.dts	2009-09-09 18:13:59.000000000 -0400
@@ -167,7 +167,7 @@
 			};
 
 			sdhci@2e000 {
-				compatible = "fsl,mpc8379-esdhc";
+				compatible = "fsl,mpc8379-esdhc", "fsl,esdhc";
 				reg = <0x2e000 0x1000>;
 				interrupts = <42 0x8>;
 				interrupt-parent = <&ipic>;
@@ -424,7 +424,7 @@
 		bus-range = <0x0 0x0>;
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-		          0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		          0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
 		sleep = <&pmc 0x00010000>;
 		clock-frequency = <66666666>;
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8536ds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8536ds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8536ds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8536ds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -51,9 +51,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xffe00000 0x100000>;
-		reg = <0xffe00000 0x1000>;
 		bus-frequency = <0>;		// Filled out by uboot.
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8536-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8536-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -321,7 +333,6 @@
 	};
 
 	pci0: pci@ffe08000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8540-pci";
 		device_type = "pci";
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
@@ -346,7 +357,6 @@
 	};
 
 	pci1: pcie@ffe09000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -383,7 +393,6 @@
 	};
 
 	pci2: pcie@ffe0a000 {
-		cell-index = <2>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -420,7 +429,6 @@
 	};
 
 	pci3: pcie@ffe0b000 {
-		cell-index = <3>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8540ads.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8540ads.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8540ads.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8540ads.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,9 +55,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x100000>;	// CCSRBAR 1M
 		bus-frequency = <0>;
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8540-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,8540-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -258,7 +270,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8541cds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8541cds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8541cds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8541cds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,9 +55,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
 		bus-frequency = <0>;
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8541-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,8541-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -272,7 +284,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
 		interrupt-map = <
 
@@ -344,7 +355,6 @@
 	};
 
 	pci1: pci@e0009000 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8544ds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8544ds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8544ds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8544ds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -57,9 +57,21 @@
 		compatible = "simple-bus";
 
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
 		bus-frequency = <0>;		// Filled out by uboot.
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8544-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,8544-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -274,7 +286,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8540-pci";
 		device_type = "pci";
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
@@ -306,7 +317,6 @@
 	};
 
 	pci1: pcie@e0009000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -343,7 +353,6 @@
 	};
 
 	pci2: pcie@e000a000 {
-		cell-index = <2>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -380,7 +389,6 @@
 	};
 
 	pci3: pcie@e000b000 {
-		cell-index = <3>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8548cds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8548cds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8548cds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8548cds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -60,9 +60,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x1000>;	// CCSRBAR
 		bus-frequency = <0>;
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,8548-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -328,7 +340,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 			/* IDSEL 0x4 (PCIX Slot 2) */
@@ -478,7 +489,6 @@
 	};
 
 	pci1: pci@e0009000 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
@@ -503,7 +513,6 @@
 	};
 
 	pci2: pcie@e000a000 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8555cds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8555cds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8555cds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8555cds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,9 +55,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
 		bus-frequency = <0>;
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8555-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,8555-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -272,7 +284,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
 		interrupt-map = <
 
@@ -344,7 +355,6 @@
 	};
 
 	pci1: pci@e0009000 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8560ads.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8560ads.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8560ads.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8560ads.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,9 +55,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x200>;
 		bus-frequency = <330000000>;
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,8540-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -291,7 +303,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8568mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8568mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8568mds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8568mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 		serial1 = &serial1;
 		pci0 = &pci0;
 		pci1 = &pci1;
+		rapidio0 = &rio0;
 	};
 
 	cpus {
@@ -62,9 +63,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x1000>;
 		bus-frequency = <0>;
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8568-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,8568-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -275,6 +288,22 @@
 			device_type = "open-pic";
 		};
 
+		msi@41600 {
+			compatible = "fsl,mpc8568-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
 		par_io@e0100 {
 			reg = <0xe0100 0x100>;
 			device_type = "par_io";
@@ -349,6 +378,8 @@
 		reg = <0xe0080000 0x480>;
 		brg-frequency = <0>;
 		bus-frequency = <396000000>;
+		fsl,qe-num-riscs = <2>;
+		fsl,qe-num-snums = <28>;
 
 		muram@10000 {
  			#address-cells = <1>;
@@ -459,7 +490,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 			/* IDSEL 0x12 AD18 */
@@ -490,7 +520,6 @@
 
 	/* PCI Express */
 	pci1: pcie@e000a000 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
@@ -526,4 +555,20 @@
 				  0x0 0x800000>;
 		};
 	};
+
+	rio0: rapidio@e00c00000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "fsl,mpc8568-rapidio", "fsl,rapidio-delta";
+		reg = <0xe00c0000 0x20000>;
+		ranges = <0x0 0x0 0xc0000000 0x0 0x20000000>;
+		interrupts = <48 2 /* error     */
+			      49 2 /* bell_outb */
+			      50 2 /* bell_inb  */
+			      53 2 /* msg1_tx   */
+			      54 2 /* msg1_rx   */
+			      55 2 /* msg2_tx   */
+			      56 2 /* msg2_rx   */>;
+		interrupt-parent = <&mpic>;
+	};
 };
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8569mds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8569mds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8569mds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8569mds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,673 @@
+/*
+ * MPC8569E MDS Device Tree Source
+ *
+ * Copyright (C) 2009 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "MPC8569EMDS";
+	compatible = "fsl,MPC8569EMDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		ethernet5 = &enet5;
+		ethernet7 = &enet7;
+		pci1 = &pci1;
+		rapidio0 = &rio0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8569@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	localbus@e0005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8569-elbc", "fsl,elbc", "simple-bus";
+		reg = <0xe0005000 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		ranges = <0x0 0x0 0xfe000000 0x02000000
+			  0x1 0x0 0xf8000000 0x00008000
+			  0x2 0x0 0xf0000000 0x04000000
+			  0x3 0x0 0xfc000000 0x00008000
+			  0x4 0x0 0xf8008000 0x00008000
+			  0x5 0x0 0xf8010000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x02000000>;
+			bank-width = <1>;
+			device-width = <1>;
+			partition@0 {
+				label = "ramdisk";
+				reg = <0x00000000 0x01c00000>;
+			};
+			partition@1c00000 {
+				label = "kernel";
+				reg = <0x01c00000 0x002e0000>;
+			};
+			partiton@1ee0000 {
+				label = "dtb";
+				reg = <0x01ee0000 0x00020000>;
+			};
+			partition@1f00000 {
+				label = "firmware";
+				reg = <0x01f00000 0x00080000>;
+				read-only;
+			};
+			partition@1f80000 {
+				label = "u-boot";
+				reg = <0x01f80000 0x00080000>;
+				read-only;
+			};
+		};
+
+		bcsr@1,0 {
+			compatible = "fsl,mpc8569mds-bcsr";
+			reg = <1 0 0x8000>;
+		};
+
+		nand@3,0 {
+			compatible = "fsl,mpc8569-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <3 0 0x8000>;
+		};
+
+		pib@4,0 {
+			compatible = "fsl,mpc8569mds-pib";
+			reg = <4 0 0x8000>;
+		};
+
+		pib@5,0 {
+			compatible = "fsl,mpc8569mds-pib";
+			reg = <5 0 0x8000>;
+		};
+	};
+
+	soc@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8569-immr", "simple-bus";
+		ranges = <0x0 0xe0000000 0x100000>;
+		bus-frequency = <0>;
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8569-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8569-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8569-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x80000>;	// L2, 512K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8569-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8569-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8569-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8569-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8569-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		sdhci@2e000 {
+			compatible = "fsl,mpc8569-esdhc", "fsl,esdhc";
+			reg = <0x2e000 0x1000>;
+			interrupts = <72 0x8>;
+			interrupt-parent = <&mpic>;
+			/* Filled in by U-Boot */
+			clock-frequency = <0>;
+			status = "disabled";
+			sdhci,1-bit-only;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4",
+				"fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2 58 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0xbfe>;
+			fsl,descriptor-types-mask = <0x3ab0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8568-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {
+			compatible = "fsl,mpc8569-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		par_io@e0100 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xe0100 0x100>;
+			ranges = <0x0 0xe0100 0x100>;
+			device_type = "par_io";
+			num-ports = <7>;
+
+			qe_pio_e: gpio-controller@80 {
+				#gpio-cells = <2>;
+				compatible = "fsl,mpc8569-qe-pario-bank",
+					     "fsl,mpc8323-qe-pario-bank";
+				reg = <0x80 0x18>;
+				gpio-controller;
+			};
+
+			pio1: ucc_pin@01 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					0x2  0x1f 0x1  0x0  0x1  0x0	/* QE_MUX_MDC */
+					0x2  0x1e 0x3  0x0  0x2  0x0	/* QE_MUX_MDIO */
+					0x2  0x0b 0x2  0x0  0x1  0x0	/* CLK12*/
+					0x0  0x0  0x1  0x0  0x3  0x0	/* ENET1_TXD0_SER1_TXD0 */
+					0x0  0x1  0x1  0x0  0x3  0x0	/* ENET1_TXD1_SER1_TXD1 */
+					0x0  0x2  0x1  0x0  0x1  0x0	/* ENET1_TXD2_SER1_TXD2 */
+					0x0  0x3  0x1  0x0  0x2  0x0	/* ENET1_TXD3_SER1_TXD3 */
+					0x0  0x6  0x2  0x0  0x3  0x0	/* ENET1_RXD0_SER1_RXD0	*/
+					0x0  0x7  0x2  0x0  0x1  0x0	/* ENET1_RXD1_SER1_RXD1	*/
+					0x0  0x8  0x2  0x0  0x2  0x0	/* ENET1_RXD2_SER1_RXD2	*/
+					0x0  0x9  0x2  0x0  0x2  0x0	/* ENET1_RXD3_SER1_RXD3	*/
+					0x0  0x4  0x1  0x0  0x2  0x0	/* ENET1_TX_EN_SER1_RTS_B */
+					0x0  0xc  0x2  0x0  0x3  0x0	/* ENET1_RX_DV_SER1_CTS_B */
+					0x2  0x8  0x2  0x0  0x1  0x0	/* ENET1_GRXCLK	*/
+					0x2  0x14 0x1  0x0  0x2  0x0>;	/* ENET1_GTXCLK	*/
+			};
+
+			pio2: ucc_pin@02 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					0x2  0x1f 0x1  0x0  0x1  0x0	/* QE_MUX_MDC */
+					0x2  0x1e 0x3  0x0  0x2  0x0	/* QE_MUX_MDIO */
+					0x2  0x10 0x2  0x0  0x3  0x0	/* CLK17 */
+					0x0  0xe  0x1  0x0  0x2  0x0	/* ENET2_TXD0_SER2_TXD0 */
+					0x0  0xf  0x1  0x0  0x2  0x0	/* ENET2_TXD1_SER2_TXD1 */
+					0x0  0x10 0x1  0x0  0x1  0x0	/* ENET2_TXD2_SER2_TXD2 */
+					0x0  0x11 0x1  0x0  0x1  0x0	/* ENET2_TXD3_SER2_TXD3 */
+					0x0  0x14 0x2  0x0  0x2  0x0	/* ENET2_RXD0_SER2_RXD0	*/
+					0x0  0x15 0x2  0x0  0x1  0x0	/* ENET2_RXD1_SER2_RXD1	*/
+					0x0  0x16 0x2  0x0  0x1  0x0	/* ENET2_RXD2_SER2_RXD2	*/
+					0x0  0x17 0x2  0x0  0x1  0x0	/* ENET2_RXD3_SER2_RXD3	*/
+					0x0  0x12 0x1  0x0  0x2  0x0	/* ENET2_TX_EN_SER2_RTS_B */
+					0x0  0x1a 0x2  0x0  0x3  0x0	/* ENET2_RX_DV_SER2_CTS_B */
+					0x2  0x3  0x2  0x0  0x1  0x0	/* ENET2_GRXCLK	*/
+					0x2  0x2 0x1  0x0  0x2  0x0>;	/* ENET2_GTXCLK	*/
+			};
+
+			pio3: ucc_pin@03 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					0x2  0x1f 0x1  0x0  0x1  0x0	/* QE_MUX_MDC */
+					0x2  0x1e 0x3  0x0  0x2  0x0	/* QE_MUX_MDIO */
+					0x2  0x0b 0x2  0x0  0x1  0x0	/* CLK12*/
+					0x0  0x1d 0x1  0x0  0x2  0x0	/* ENET3_TXD0_SER3_TXD0 */
+					0x0  0x1e 0x1  0x0  0x3  0x0	/* ENET3_TXD1_SER3_TXD1 */
+					0x0  0x1f 0x1  0x0  0x2  0x0	/* ENET3_TXD2_SER3_TXD2 */
+					0x1  0x0  0x1  0x0  0x3  0x0	/* ENET3_TXD3_SER3_TXD3 */
+					0x1  0x3  0x2  0x0  0x3  0x0	/* ENET3_RXD0_SER3_RXD0	*/
+					0x1  0x4  0x2  0x0  0x1  0x0	/* ENET3_RXD1_SER3_RXD1	*/
+					0x1  0x5  0x2  0x0  0x2  0x0	/* ENET3_RXD2_SER3_RXD2	*/
+					0x1  0x6  0x2  0x0  0x3  0x0	/* ENET3_RXD3_SER3_RXD3	*/
+					0x1  0x1  0x1  0x0  0x1  0x0	/* ENET3_TX_EN_SER3_RTS_B */
+					0x1  0x9  0x2  0x0  0x3  0x0	/* ENET3_RX_DV_SER3_CTS_B */
+					0x2  0x9  0x2  0x0  0x2  0x0	/* ENET3_GRXCLK	*/
+					0x2  0x19 0x1  0x0  0x2  0x0>;	/* ENET3_GTXCLK	*/
+			};
+
+			pio4: ucc_pin@04 {
+				pio-map = <
+			/* port  pin  dir  open_drain  assignment  has_irq */
+					0x2  0x1f 0x1  0x0  0x1  0x0	/* QE_MUX_MDC */
+					0x2  0x1e 0x3  0x0  0x2  0x0	/* QE_MUX_MDIO */
+					0x2  0x10 0x2  0x0  0x3  0x0	/* CLK17 */
+					0x1  0xc  0x1  0x0  0x2  0x0	/* ENET4_TXD0_SER4_TXD0 */
+					0x1  0xd  0x1  0x0  0x2  0x0	/* ENET4_TXD1_SER4_TXD1 */
+					0x1  0xe  0x1  0x0  0x1  0x0	/* ENET4_TXD2_SER4_TXD2 */
+					0x1  0xf  0x1  0x0  0x2  0x0	/* ENET4_TXD3_SER4_TXD3 */
+					0x1  0x12 0x2  0x0  0x2  0x0	/* ENET4_RXD0_SER4_RXD0	*/
+					0x1  0x13 0x2  0x0  0x1  0x0	/* ENET4_RXD1_SER4_RXD1	*/
+					0x1  0x14 0x2  0x0  0x1  0x0	/* ENET4_RXD2_SER4_RXD2	*/
+					0x1  0x15 0x2  0x0  0x2  0x0	/* ENET4_RXD3_SER4_RXD3	*/
+					0x1  0x10 0x1  0x0  0x2  0x0	/* ENET4_TX_EN_SER4_RTS_B */
+					0x1  0x18 0x2  0x0  0x3  0x0	/* ENET4_RX_DV_SER4_CTS_B */
+					0x2  0x11 0x2  0x0  0x2  0x0	/* ENET4_GRXCLK	*/
+					0x2  0x18 0x1  0x0  0x2  0x0>;	/* ENET4_GTXCLK	*/
+			};
+		};
+	};
+
+	qe@e0080000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "qe";
+		compatible = "fsl,qe";
+		ranges = <0x0 0xe0080000 0x40000>;
+		reg = <0xe0080000 0x480>;
+		brg-frequency = <0>;
+		bus-frequency = <0>;
+		fsl,qe-num-riscs = <4>;
+		fsl,qe-num-snums = <46>;
+
+		qeic: interrupt-controller@80 {
+			interrupt-controller;
+			compatible = "fsl,qe-ic";
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg = <0x80 0x80>;
+			interrupts = <46 2 46 2>; //high:30 low:30
+			interrupt-parent = <&mpic>;
+		};
+
+		spi@4c0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc8569-qe-spi", "fsl,spi";
+			reg = <0x4c0 0x40>;
+			cell-index = <0>;
+			interrupts = <2>;
+			interrupt-parent = <&qeic>;
+			gpios = <&qe_pio_e 30 0>;
+			mode = "cpu-qe";
+
+			serial-flash@0 {
+				compatible = "stm,m25p40";
+				reg = <0>;
+				spi-max-frequency = <25000000>;
+			};
+		};
+
+		spi@500 {
+			cell-index = <1>;
+			compatible = "fsl,spi";
+			reg = <0x500 0x40>;
+			interrupts = <1>;
+			interrupt-parent = <&qeic>;
+			mode = "cpu";
+		};
+
+		enet0: ucc@2000 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			cell-index = <1>;
+			reg = <0x2000 0x200>;
+			interrupts = <32>;
+			interrupt-parent = <&qeic>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			rx-clock-name = "none";
+			tx-clock-name = "clk12";
+			pio-handle = <&pio1>;
+			phy-handle = <&qe_phy0>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		mdio@2120 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x2120 0x18>;
+			compatible = "fsl,ucc-mdio";
+
+			qe_phy0: ethernet-phy@07 {
+				interrupt-parent = <&mpic>;
+				interrupts = <1 1>;
+				reg = <0x7>;
+				device_type = "ethernet-phy";
+			};
+			qe_phy1: ethernet-phy@01 {
+				interrupt-parent = <&mpic>;
+				interrupts = <2 1>;
+				reg = <0x1>;
+				device_type = "ethernet-phy";
+			};
+			qe_phy2: ethernet-phy@02 {
+				interrupt-parent = <&mpic>;
+				interrupts = <3 1>;
+				reg = <0x2>;
+				device_type = "ethernet-phy";
+			};
+			qe_phy3: ethernet-phy@03 {
+				interrupt-parent = <&mpic>;
+				interrupts = <4 1>;
+				reg = <0x3>;
+				device_type = "ethernet-phy";
+			};
+			qe_phy5: ethernet-phy@04 {
+				interrupt-parent = <&mpic>;
+				reg = <0x04>;
+				device_type = "ethernet-phy";
+			};
+			qe_phy7: ethernet-phy@06 {
+				interrupt-parent = <&mpic>;
+				reg = <0x6>;
+				device_type = "ethernet-phy";
+			};
+			tbi-phy@11 {
+				reg = <0x11>;
+				device_type = "tbi-phy";
+			};
+		};
+		mdio@3520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x3520 0x18>;
+			compatible = "fsl,ucc-mdio";
+
+			tbi0: tbi-phy@15 {
+			reg = <0x15>;
+			device_type = "tbi-phy";
+			};
+		};
+		mdio@3720 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x3720 0x38>;
+			compatible = "fsl,ucc-mdio";
+			tbi1: tbi-phy@17 {
+				reg = <0x17>;
+				device_type = "tbi-phy";
+			};
+		};
+
+		enet2: ucc@2200 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			cell-index = <3>;
+			reg = <0x2200 0x200>;
+			interrupts = <34>;
+			interrupt-parent = <&qeic>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			rx-clock-name = "none";
+			tx-clock-name = "clk12";
+			pio-handle = <&pio3>;
+			phy-handle = <&qe_phy2>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		enet1: ucc@3000 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			cell-index = <2>;
+			reg = <0x3000 0x200>;
+			interrupts = <33>;
+			interrupt-parent = <&qeic>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			rx-clock-name = "none";
+			tx-clock-name = "clk17";
+			pio-handle = <&pio2>;
+			phy-handle = <&qe_phy1>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		enet3: ucc@3200 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			cell-index = <4>;
+			reg = <0x3200 0x200>;
+			interrupts = <35>;
+			interrupt-parent = <&qeic>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			rx-clock-name = "none";
+			tx-clock-name = "clk17";
+			pio-handle = <&pio4>;
+			phy-handle = <&qe_phy3>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		enet5: ucc@3400 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			cell-index = <6>;
+			reg = <0x3400 0x200>;
+			interrupts = <41>;
+			interrupt-parent = <&qeic>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			rx-clock-name = "none";
+			tx-clock-name = "none";
+			tbi-handle = <&tbi0>;
+			phy-handle = <&qe_phy5>;
+			phy-connection-type = "sgmii";
+		};
+
+		enet7: ucc@3600 {
+			device_type = "network";
+			compatible = "ucc_geth";
+			cell-index = <8>;
+			reg = <0x3600 0x200>;
+			interrupts = <43>;
+			interrupt-parent = <&qeic>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			rx-clock-name = "none";
+			tx-clock-name = "none";
+			tbi-handle = <&tbi1>;
+			phy-handle = <&qe_phy7>;
+			phy-connection-type = "sgmii";
+		};
+
+		muram@10000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,qe-muram", "fsl,cpm-muram";
+			ranges = <0x0 0x10000 0x20000>;
+
+			data-only@0 {
+				compatible = "fsl,qe-muram-data",
+					     "fsl,cpm-muram-data";
+				reg = <0x0 0x20000>;
+			};
+		};
+
+	};
+
+	/* PCI Express */
+	pci1: pcie@e000a000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe000a000 0x1000>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 (PEX) */
+			00000 0x0 0x0 0x1 &mpic 0x0 0x1
+			00000 0x0 0x0 0x2 &mpic 0x1 0x1
+			00000 0x0 0x0 0x3 &mpic 0x2 0x1
+			00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
+			  0x1000000 0x0 0x00000000 0xe2800000 0x0 0x00800000>;
+		clock-frequency = <33333333>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x10000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x800000>;
+		};
+	};
+
+	rio0: rapidio@e00c00000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "fsl,mpc8569-rapidio", "fsl,rapidio-delta";
+		reg = <0xe00c0000 0x20000>;
+		ranges = <0x0 0x0 0xc0000000 0x0 0x20000000>;
+		interrupts = <48 2 /* error     */
+			      49 2 /* bell_outb */
+			      50 2 /* bell_inb  */
+			      53 2 /* msg1_tx   */
+			      54 2 /* msg1_rx   */
+			      55 2 /* msg2_tx   */
+			      56 2 /* msg2_rx   */>;
+		interrupt-parent = <&mpic>;
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds_36b.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds_36b.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds_36b.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds_36b.dts	2009-09-09 18:13:59.000000000 -0400
@@ -182,9 +182,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xf 0xffe00000 0x100000>;
-		reg = <0xf 0xffe00000 0 0x1000>;	// CCSRBAR & soc regs, remove once parse code for immrbase fixed
 		bus-frequency = <0>;		// Filled out by uboot.
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8572-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -514,7 +526,6 @@
 	};
 
 	pci0: pcie@fffe08000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -522,7 +533,7 @@
 		#address-cells = <3>;
 		reg = <0xf 0xffe08000 0 0x1000>;
 		bus-range = <0 255>;
-		ranges = <0x2000000 0x0 0xc0000000 0xc 0x00000000 0x0 0x20000000
+		ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
 			  0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x00010000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
@@ -649,8 +660,8 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			ranges = <0x2000000 0x0 0xc0000000
-				  0x2000000 0x0 0xc0000000
+			ranges = <0x2000000 0x0 0xe0000000
+				  0x2000000 0x0 0xe0000000
 				  0x0 0x20000000
 
 				  0x1000000 0x0 0x0
@@ -660,8 +671,8 @@
 				reg = <0x0 0x0 0x0 0x0 0x0>;
 				#size-cells = <2>;
 				#address-cells = <3>;
-				ranges = <0x2000000 0x0 0xc0000000
-					  0x2000000 0x0 0xc0000000
+				ranges = <0x2000000 0x0 0xe0000000
+					  0x2000000 0x0 0xe0000000
 					  0x0 0x20000000
 
 					  0x1000000 0x0 0x0
@@ -724,7 +735,6 @@
 	};
 
 	pci1: pcie@fffe09000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -732,7 +742,7 @@
 		#address-cells = <3>;
 		reg = <0xf 0xffe09000 0 0x1000>;
 		bus-range = <0 255>;
-		ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
+		ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
 			  0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x00010000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
@@ -750,8 +760,8 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			ranges = <0x2000000 0x0 0xc0000000
-				  0x2000000 0x0 0xc0000000
+			ranges = <0x2000000 0x0 0xe0000000
+				  0x2000000 0x0 0xe0000000
 				  0x0 0x20000000
 
 				  0x1000000 0x0 0x0
@@ -761,7 +771,6 @@
 	};
 
 	pci2: pcie@fffe0a000 {
-		cell-index = <2>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -769,7 +778,7 @@
 		#address-cells = <3>;
 		reg = <0xf 0xffe0a000 0 0x1000>;
 		bus-range = <0 255>;
-		ranges = <0x2000000 0x0 0xc0000000 0xc 0x40000000 0x0 0x20000000
+		ranges = <0x2000000 0x0 0xe0000000 0xc 0x40000000 0x0 0x20000000
 			  0x1000000 0x0 0x00000000 0xf 0xffc20000 0x0 0x00010000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
@@ -787,8 +796,8 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			ranges = <0x2000000 0x0 0xc0000000
-				  0x2000000 0x0 0xc0000000
+			ranges = <0x2000000 0x0 0xe0000000
+				  0x2000000 0x0 0xe0000000
 				  0x0 0x20000000
 
 				  0x1000000 0x0 0x0
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts	2009-09-09 18:13:59.000000000 -0400
@@ -59,9 +59,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xffe00000 0x100000>;
-		reg = <0xffe00000 0x1000>;	// CCSRBAR & soc regs, remove once parse code for immrbase fixed
 		bus-frequency = <0>;		// Filled out by uboot.
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8572-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -238,7 +250,6 @@
 	};
 
 	pci0: pcie@ffe08000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -448,7 +459,6 @@
 	};
 
 	pci1: pcie@ffe09000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts	2009-09-09 18:13:59.000000000 -0400
@@ -58,7 +58,6 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0xffe00000 0x100000>;
-		reg = <0xffe00000 0x1000>;	// CCSRBAR & soc regs, remove once parse code for immrbase fixed
 		bus-frequency = <0>;		// Filled out by uboot.
 
 		L2: l2-cache-controller@20000 {
@@ -196,7 +195,6 @@
 	};
 
 	pci2: pcie@ffe0a000 {
-		cell-index = <2>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8572ds.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8572ds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -182,9 +182,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x0 0 0xffe00000 0x100000>;
-		reg = <0 0xffe00000 0 0x1000>;	// CCSRBAR & soc regs, remove once parse code for immrbase fixed
 		bus-frequency = <0>;		// Filled out by uboot.
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8572-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -514,7 +526,6 @@
 	};
 
 	pci0: pcie@ffe08000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -724,7 +735,6 @@
 	};
 
 	pci1: pcie@ffe09000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -761,7 +771,6 @@
 	};
 
 	pci2: pcie@ffe0a000 {
-		cell-index = <2>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8610_hpcd.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8610_hpcd.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8610_hpcd.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8610_hpcd.dts	2009-09-09 18:13:59.000000000 -0400
@@ -100,8 +100,18 @@
 		};
 
 		board-control@3,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			compatible = "fsl,fpga-pixis";
 			reg = <3 0 0x20>;
+			ranges = <0 3 0 0x20>;
+
+			sdcsr_pio: gpio-controller@a {
+				#gpio-cells = <2>;
+				compatible = "fsl,fpga-pixis-gpio-bank";
+				reg = <0xa 1>;
+				gpio-controller;
+			};
 		};
 	};
 
@@ -112,9 +122,21 @@
 		device_type = "soc";
 		compatible = "fsl,mpc8610-immr", "simple-bus";
 		ranges = <0x0 0xe0000000 0x00100000>;
-		reg = <0xe0000000 0x1000>;
 		bus-frequency = <0>;
 
+		mcm-law@0 {
+			compatible = "fsl,mcm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		mcm@1000 {
+			compatible = "fsl,mpc8610-mcm", "fsl,mcm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -164,6 +186,28 @@
 			interrupt-parent = <&mpic>;
 		};
 
+		spi@7000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc8610-spi", "fsl,spi";
+			reg = <0x7000 0x40>;
+			cell-index = <0>;
+			interrupts = <59 2>;
+			interrupt-parent = <&mpic>;
+			mode = "cpu";
+			gpios = <&sdcsr_pio 7 0>;
+
+			mmc-slot@0 {
+				compatible = "fsl,mpc8610hpcd-mmc-slot",
+					     "mmc-spi-slot";
+				reg = <0>;
+				gpios = <&sdcsr_pio 0 1   /* nCD */
+					 &sdcsr_pio 1 0>; /*  WP */
+				voltage-ranges = <3300 3300>;
+				spi-max-frequency = <50000000>;
+			};
+		};
+
 		display@2c000 {
 			compatible = "fsl,diu";
 			reg = <0x2c000 100>;
@@ -316,7 +360,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8610-pci";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -346,7 +389,6 @@
 	};
 
 	pci1: pcie@e000a000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,609 @@
+/*
+ * MPC8641 HPCN Device Tree Source
+ *
+ * Copyright 2008-2009 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "MPC8641HPCN";
+	compatible = "fsl,mpc8641hpcn";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8641@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	// 33 MHz, from uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+		};
+		PowerPC,8641@1 {
+			device_type = "cpu";
+			reg = <1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	// 33 MHz, from uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x00000000 0x0 0x40000000>;	// 1G at 0x0
+	};
+
+	localbus@fffe05000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8641-localbus", "simple-bus";
+		reg = <0x0f 0xffe05000 0x0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		ranges = <0 0 0xf 0xef800000 0x00800000
+			  2 0 0xf 0xffdf8000 0x00008000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x00800000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "kernel";
+				reg = <0x00000000 0x00300000>;
+			};
+			partition@300000 {
+				label = "firmware b";
+				reg = <0x00300000 0x00100000>;
+				read-only;
+			};
+			partition@400000 {
+				label = "fs";
+				reg = <0x00400000 0x00300000>;
+			};
+			partition@700000 {
+				label = "firmware a";
+				reg = <0x00700000 0x00100000>;
+				read-only;
+			};
+		};
+	};
+
+	soc8641@fffe00000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x00000000 0x0f 0xffe00000 0x00100000>;
+		bus-frequency = <0>;
+
+		mcm-law@0 {
+			compatible = "fsl,mcm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		mcm@1000 {
+			compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8641-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8641-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8641-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8641-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
+			phy-handle = <&phy2>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <3>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <37 2 38 2 39 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi3>;
+			phy-handle = <&phy3>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <28 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		global-utilities@e0000 {
+			compatible = "fsl,mpc8641-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+	};
+
+	pci0: pcie@fffe08000 {
+		cell-index = <0>;
+		compatible = "fsl,mpc8641-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0x0f 0xffe08000 0x0 0x1000>;
+		bus-range = <0x0 0xff>;
+		ranges = <0x02000000 0x0 0xe0000000 0x0c 0x00000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0x0f 0xffc00000 0x0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		interrupt-map-mask = <0xff00 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x11 func 0 - PCI slot 1 */
+			0x8800 0 0 1 &mpic 2 1
+			0x8800 0 0 2 &mpic 3 1
+			0x8800 0 0 3 &mpic 4 1
+			0x8800 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x11 func 1 - PCI slot 1 */
+			0x8900 0 0 1 &mpic 2 1
+			0x8900 0 0 2 &mpic 3 1
+			0x8900 0 0 3 &mpic 4 1
+			0x8900 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x11 func 2 - PCI slot 1 */
+			0x8a00 0 0 1 &mpic 2 1
+			0x8a00 0 0 2 &mpic 3 1
+			0x8a00 0 0 3 &mpic 4 1
+			0x8a00 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x11 func 3 - PCI slot 1 */
+			0x8b00 0 0 1 &mpic 2 1
+			0x8b00 0 0 2 &mpic 3 1
+			0x8b00 0 0 3 &mpic 4 1
+			0x8b00 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x11 func 4 - PCI slot 1 */
+			0x8c00 0 0 1 &mpic 2 1
+			0x8c00 0 0 2 &mpic 3 1
+			0x8c00 0 0 3 &mpic 4 1
+			0x8c00 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x11 func 5 - PCI slot 1 */
+			0x8d00 0 0 1 &mpic 2 1
+			0x8d00 0 0 2 &mpic 3 1
+			0x8d00 0 0 3 &mpic 4 1
+			0x8d00 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x11 func 6 - PCI slot 1 */
+			0x8e00 0 0 1 &mpic 2 1
+			0x8e00 0 0 2 &mpic 3 1
+			0x8e00 0 0 3 &mpic 4 1
+			0x8e00 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x11 func 7 - PCI slot 1 */
+			0x8f00 0 0 1 &mpic 2 1
+			0x8f00 0 0 2 &mpic 3 1
+			0x8f00 0 0 3 &mpic 4 1
+			0x8f00 0 0 4 &mpic 1 1
+
+			/* IDSEL 0x12 func 0 - PCI slot 2 */
+			0x9000 0 0 1 &mpic 3 1
+			0x9000 0 0 2 &mpic 4 1
+			0x9000 0 0 3 &mpic 1 1
+			0x9000 0 0 4 &mpic 2 1
+
+			/* IDSEL 0x12 func 1 - PCI slot 2 */
+			0x9100 0 0 1 &mpic 3 1
+			0x9100 0 0 2 &mpic 4 1
+			0x9100 0 0 3 &mpic 1 1
+			0x9100 0 0 4 &mpic 2 1
+
+			/* IDSEL 0x12 func 2 - PCI slot 2 */
+			0x9200 0 0 1 &mpic 3 1
+			0x9200 0 0 2 &mpic 4 1
+			0x9200 0 0 3 &mpic 1 1
+			0x9200 0 0 4 &mpic 2 1
+
+			/* IDSEL 0x12 func 3 - PCI slot 2 */
+			0x9300 0 0 1 &mpic 3 1
+			0x9300 0 0 2 &mpic 4 1
+			0x9300 0 0 3 &mpic 1 1
+			0x9300 0 0 4 &mpic 2 1
+
+			/* IDSEL 0x12 func 4 - PCI slot 2 */
+			0x9400 0 0 1 &mpic 3 1
+			0x9400 0 0 2 &mpic 4 1
+			0x9400 0 0 3 &mpic 1 1
+			0x9400 0 0 4 &mpic 2 1
+
+			/* IDSEL 0x12 func 5 - PCI slot 2 */
+			0x9500 0 0 1 &mpic 3 1
+			0x9500 0 0 2 &mpic 4 1
+			0x9500 0 0 3 &mpic 1 1
+			0x9500 0 0 4 &mpic 2 1
+
+			/* IDSEL 0x12 func 6 - PCI slot 2 */
+			0x9600 0 0 1 &mpic 3 1
+			0x9600 0 0 2 &mpic 4 1
+			0x9600 0 0 3 &mpic 1 1
+			0x9600 0 0 4 &mpic 2 1
+
+			/* IDSEL 0x12 func 7 - PCI slot 2 */
+			0x9700 0 0 1 &mpic 3 1
+			0x9700 0 0 2 &mpic 4 1
+			0x9700 0 0 3 &mpic 1 1
+			0x9700 0 0 4 &mpic 2 1
+
+			// IDSEL 0x1c  USB
+			0xe000 0 0 1 &i8259 12 2
+			0xe100 0 0 2 &i8259 9 2
+			0xe200 0 0 3 &i8259 10 2
+			0xe300 0 0 4 &i8259 11 2
+
+			// IDSEL 0x1d  Audio
+			0xe800 0 0 1 &i8259 6 2
+
+			// IDSEL 0x1e Legacy
+			0xf000 0 0 1 &i8259 7 2
+			0xf100 0 0 1 &i8259 7 2
+
+			// IDSEL 0x1f IDE/SATA
+			0xf800 0 0 1 &i8259 14 2
+			0xf900 0 0 1 &i8259 5 2
+			>;
+
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0x0 0xe0000000
+				  0x02000000 0x0 0xe0000000
+				  0x0 0x20000000
+
+				  0x01000000 0x0 0x00000000
+				  0x01000000 0x0 0x00000000
+				  0x0 0x00010000>;
+			uli1575@0 {
+				reg = <0 0 0 0 0>;
+				#size-cells = <2>;
+				#address-cells = <3>;
+				ranges = <0x02000000 0x0 0xe0000000
+					  0x02000000 0x0 0xe0000000
+					  0x0 0x20000000
+					  0x01000000 0x0 0x00000000
+					  0x01000000 0x0 0x00000000
+					  0x0 0x00010000>;
+				isa@1e {
+					device_type = "isa";
+					#interrupt-cells = <2>;
+					#size-cells = <1>;
+					#address-cells = <2>;
+					reg = <0xf000 0 0 0 0>;
+					ranges = <1 0 0x01000000 0 0
+						  0x00001000>;
+					interrupt-parent = <&i8259>;
+
+					i8259: interrupt-controller@20 {
+						reg = <1 0x20 2
+						       1 0xa0 2
+						       1 0x4d0 2>;
+						interrupt-controller;
+						device_type = "interrupt-controller";
+						#address-cells = <0>;
+						#interrupt-cells = <2>;
+						compatible = "chrp,iic";
+						interrupts = <9 2>;
+						interrupt-parent = <&mpic>;
+					};
+
+					i8042@60 {
+						#size-cells = <0>;
+						#address-cells = <1>;
+						reg = <1 0x60 1 1 0x64 1>;
+						interrupts = <1 3 12 3>;
+						interrupt-parent =
+							<&i8259>;
+
+						keyboard@0 {
+							reg = <0>;
+							compatible = "pnpPNP,303";
+						};
+
+						mouse@1 {
+							reg = <1>;
+							compatible = "pnpPNP,f03";
+						};
+					};
+
+					rtc@70 {
+						compatible =
+							"pnpPNP,b00";
+						reg = <1 0x70 2>;
+					};
+
+					gpio@400 {
+						reg = <1 0x400 0x80>;
+					};
+				};
+			};
+		};
+
+	};
+
+	pci1: pcie@fffe09000 {
+		cell-index = <1>;
+		compatible = "fsl,mpc8641-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0x0f 0xffe09000 0x0 0x1000>;
+		bus-range = <0x0 0xff>;
+		ranges = <0x02000000 0x0 0xe0000000 0x0c 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0x0f 0xffc10000 0x0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0000 0 0 1 &mpic 4 1
+			0x0000 0 0 2 &mpic 5 1
+			0x0000 0 0 3 &mpic 6 1
+			0x0000 0 0 4 &mpic 7 1
+			>;
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0x0 0xe0000000
+				  0x02000000 0x0 0xe0000000
+				  0x0 0x20000000
+
+				  0x01000000 0x0 0x00000000
+				  0x01000000 0x0 0x00000000
+				  0x0 0x00010000>;
+		};
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8641_hpcn.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8641_hpcn.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/mpc8641_hpcn.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/mpc8641_hpcn.dts	2009-09-09 18:13:59.000000000 -0400
@@ -114,9 +114,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x00000000 0xffe00000 0x00100000>;
-		reg = <0xffe00000 0x00001000>;	// CCSRBAR
 		bus-frequency = <0>;
 
+		mcm-law@0 {
+			compatible = "fsl,mcm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		mcm@1000 {
+			compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -357,7 +369,6 @@
 	};
 
 	pci0: pcie@ffe08000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -566,7 +577,6 @@
 	};
 
 	pci1: pcie@ffe09000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/p2020ds.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/p2020ds.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/p2020ds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/p2020ds.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,704 @@
+/*
+ * P2020 DS Device Tree Source
+ *
+ * Copyright 2009 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+/ {
+	model = "fsl,P2020";
+	compatible = "fsl,P2020DS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,P2020@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			next-level-cache = <&L2>;
+		};
+
+		PowerPC,P2020@1 {
+			device_type = "cpu";
+			reg = <0x1>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	localbus@ffe05000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,elbc", "simple-bus";
+		reg = <0 0xffe05000 0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		ranges = <0x0 0x0 0x0 0xe8000000 0x08000000
+			  0x1 0x0 0x0 0xe0000000 0x08000000
+			  0x2 0x0 0x0 0xffa00000 0x00040000
+			  0x3 0x0 0x0 0xffdf0000 0x00008000
+			  0x4 0x0 0x0 0xffa40000 0x00040000
+			  0x5 0x0 0x0 0xffa80000 0x00040000
+			  0x6 0x0 0x0 0xffac0000 0x00040000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+			bank-width = <2>;
+			device-width = <1>;
+
+			ramdisk@0 {
+				reg = <0x0 0x03000000>;
+				read-only;
+			};
+
+			diagnostic@3000000 {
+				reg = <0x03000000 0x00e00000>;
+				read-only;
+			};
+
+			dink@3e00000 {
+				reg = <0x03e00000 0x00200000>;
+				read-only;
+			};
+
+			kernel@4000000 {
+				reg = <0x04000000 0x00400000>;
+				read-only;
+			};
+
+			jffs2@4400000 {
+				reg = <0x04400000 0x03b00000>;
+			};
+
+			dtb@7f00000 {
+				reg = <0x07f00000 0x00080000>;
+				read-only;
+			};
+
+			u-boot@7f80000 {
+				reg = <0x07f80000 0x00080000>;
+				read-only;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x2 0x0 0x40000>;
+
+			u-boot@0 {
+				reg = <0x0 0x02000000>;
+				read-only;
+			};
+
+			jffs2@2000000 {
+				reg = <0x02000000 0x10000000>;
+			};
+
+			ramdisk@12000000 {
+				reg = <0x12000000 0x08000000>;
+				read-only;
+			};
+
+			kernel@1a000000 {
+				reg = <0x1a000000 0x04000000>;
+			};
+
+			dtb@1e000000 {
+				reg = <0x1e000000 0x01000000>;
+				read-only;
+			};
+
+			empty@1f000000 {
+				reg = <0x1f000000 0x21000000>;
+			};
+		};
+
+		nand@4,0 {
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x4 0x0 0x40000>;
+		};
+
+		nand@5,0 {
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x5 0x0 0x40000>;
+		};
+
+		nand@6,0 {
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x6 0x0 0x40000>;
+		};
+	};
+
+	soc@ffe00000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,p2020-immr", "simple-bus";
+		ranges = <0x0 0 0xffe00000 0x100000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,p2020-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,p2020-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		spi@7000 {
+			compatible = "fsl,espi";
+			reg = <0x7000 0x1000>;
+			interrupts = <59 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		dma@c300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,eloplus-dma";
+			reg = <0xc300 0x4>;
+			ranges = <0x0 0xc100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <76 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <77 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <78 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <79 2>;
+			};
+		};
+
+		gpio: gpio-controller@f000 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8572-gpio";
+			reg = <0xf000 0x100>;
+			interrupts = <47 0x2>;
+			interrupt-parent = <&mpic>;
+			gpio-controller;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,p2020-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x80000>; // L2, 512k
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		usb@22000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-usb2-dr";
+			reg = <0x22000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <28 0x2>;
+			phy_type = "ulpi";
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <3 1>;
+					reg = <0x0>;
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <3 1>;
+					reg = <0x1>;
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <3 1>;
+					reg = <0x2>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
+			phy-handle = <&phy2>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		sdhci@2e000 {
+			compatible = "fsl,p2020-esdhc", "fsl,esdhc";
+			reg = <0x2e000 0x1000>;
+			interrupts = <72 0x2>;
+			interrupt-parent = <&mpic>;
+			/* Filled in by U-Boot */
+			clock-frequency = <0>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec3.1", "fsl,sec3.0", "fsl,sec2.4",
+				     "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2 58 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0xbfe>;
+			fsl,descriptor-types-mask = <0x3ab0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,p2020-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+	};
+
+	pci0: pcie@ffe08000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xffe08000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x8 0x1
+			0000 0x0 0x0 0x2 &mpic 0x9 0x1
+			0000 0x0 0x0 0x3 &mpic 0xa 0x1
+			0000 0x0 0x0 0x4 &mpic 0xb 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+
+	pci1: pcie@ffe09000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xffe09000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+		interrupt-map = <
+
+			// IDSEL 0x11 func 0 - PCI slot 1
+			0x8800 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8800 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x11 func 1 - PCI slot 1
+			0x8900 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8900 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x11 func 2 - PCI slot 1
+			0x8a00 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8a00 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x11 func 3 - PCI slot 1
+			0x8b00 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8b00 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x11 func 4 - PCI slot 1
+			0x8c00 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8c00 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x11 func 5 - PCI slot 1
+			0x8d00 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8d00 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x11 func 6 - PCI slot 1
+			0x8e00 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8e00 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x11 func 7 - PCI slot 1
+			0x8f00 0x0 0x0 0x1 &i8259 0x9 0x2
+			0x8f00 0x0 0x0 0x2 &i8259 0xa 0x2
+
+			// IDSEL 0x1d  Audio
+			0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+			// IDSEL 0x1e Legacy
+			0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
+			0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+			// IDSEL 0x1f IDE/SATA
+			0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
+			0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+			>;
+
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+			uli1575@0 {
+				reg = <0x0 0x0 0x0 0x0 0x0>;
+				#size-cells = <2>;
+				#address-cells = <3>;
+				ranges = <0x2000000 0x0 0xa0000000
+					  0x2000000 0x0 0xa0000000
+					  0x0 0x20000000
+
+					  0x1000000 0x0 0x0
+					  0x1000000 0x0 0x0
+					  0x0 0x10000>;
+				isa@1e {
+					device_type = "isa";
+					#interrupt-cells = <2>;
+					#size-cells = <1>;
+					#address-cells = <2>;
+					reg = <0xf000 0x0 0x0 0x0 0x0>;
+					ranges = <0x1 0x0 0x1000000 0x0 0x0
+						  0x1000>;
+					interrupt-parent = <&i8259>;
+
+					i8259: interrupt-controller@20 {
+						reg = <0x1 0x20 0x2
+						       0x1 0xa0 0x2
+						       0x1 0x4d0 0x2>;
+						interrupt-controller;
+						device_type = "interrupt-controller";
+						#address-cells = <0>;
+						#interrupt-cells = <2>;
+						compatible = "chrp,iic";
+						interrupts = <4 1>;
+						interrupt-parent = <&mpic>;
+					};
+
+					i8042@60 {
+						#size-cells = <0>;
+						#address-cells = <1>;
+						reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
+						interrupts = <1 3 12 3>;
+						interrupt-parent =
+							<&i8259>;
+
+						keyboard@0 {
+							reg = <0x0>;
+							compatible = "pnpPNP,303";
+						};
+
+						mouse@1 {
+							reg = <0x1>;
+							compatible = "pnpPNP,f03";
+						};
+					};
+
+					rtc@70 {
+						compatible = "pnpPNP,b00";
+						reg = <0x1 0x70 0x2>;
+					};
+
+					gpio@400 {
+						reg = <0x1 0x400 0x80>;
+					};
+				};
+			};
+		};
+
+	};
+
+	pci2: pcie@ffe0a000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xffe0a000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/pcm030.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/pcm030.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/pcm030.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/pcm030.dts	2009-09-09 18:13:59.000000000 -0400
@@ -258,34 +258,16 @@
 				compatible = "nxp,pcf8563";
 				reg = <0x51>;
 			};
-			/* FIXME: EEPROM */
+			eeprom@52 {
+				compatible = "catalyst,24c32";
+				reg = <0x52>;
+			};
 		};
 
 		sram@8000 {
 			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
 			reg = <0x8000 0x4000>;
 		};
-
-		/* This is only an example device to show the usage of gpios. It maps all available
-		 * gpios to the "gpio-provider" device.
-		 */
-		gpio {
-			compatible = "gpio-provider";
-
-						    /* mpc52xx		exp.con		patchfield */
-			gpios = <&gpio_wkup	0 0 /* GPIO_WKUP_7	11d		jp13-3     */
-				 &gpio_wkup	1 0 /* GPIO_WKUP_6	14c			   */
-				 &gpio_wkup	6 0 /* PSC2_4		43c		x5-11	   */
-				 &gpio_simple	2 0 /* IRDA_1		24c		x7-6	set GPS_PORT_CONFIG[IRDA] = 0 */
-				 &gpio_simple	3 0 /* IRDA_0				x8-5	set GPS_PORT_CONFIG[IRDA] = 0 */
-				 &gpt2		0 0 /* timer2		12d		x4-4	   */
-				 &gpt3		0 0 /* timer3		13d		x6-4	   */
-				 &gpt4		0 0 /* timer4		61c		x2-16	   */
-				 &gpt5		0 0 /* timer5		44c		x7-11	   */
-				 &gpt6		0 0 /* timer6		60c		x8-15	   */
-				 &gpt7		0 0 /* timer7		36a		x17-9	   */
-				 >;
-		};
 	};
 
 	pci@f0000d00 {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8349.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8349.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8349.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8349.dts	2009-09-09 18:13:59.000000000 -0400
@@ -144,7 +144,7 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <39 0x8>;
 			phy_type = "ulpi";
-			port1;
+			port0;
 		};
 		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
 		usb@23000 {
@@ -278,7 +278,6 @@
 	};
 
 	pci0: pci@e0008500 {
-		cell-index = <1>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8548.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8548.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8548.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8548.dts	2009-09-09 18:13:59.000000000 -0400
@@ -151,10 +151,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x00000000 0xe0000000 0x00100000>;
-		reg = <0xe0000000 0x00001000>;	// CCSRBAR
 		bus-frequency = <0>;
 		compatible = "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8548-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -350,7 +362,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 			/* IDSEL 0x01 (PCI-X slot) @66MHz */
@@ -380,7 +391,6 @@
 	};
 
 	pci2: pcie@e000a000 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8560.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8560.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8560.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8560.dts	2009-09-09 18:13:59.000000000 -0400
@@ -57,9 +57,21 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x0 0xff700000 0x00100000>;
-		reg = <0xff700000 0x00100000>;
 		clock-frequency = <0>;
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8560-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -296,7 +308,6 @@
 	};
 
 	pci0: pci@ff708000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8641d.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8641d.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sbc8641d.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sbc8641d.dts	2009-09-09 18:13:59.000000000 -0400
@@ -126,9 +126,21 @@
 		device_type = "soc";
 		compatible = "simple-bus";
 		ranges = <0x00000000 0xf8000000 0x00100000>;
-		reg = <0xf8000000 0x00001000>;	// CCSRBAR
 		bus-frequency = <0>;
 
+		mcm-law@0 {
+			compatible = "fsl,mcm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		mcm@1000 {
+			compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -371,7 +383,6 @@
 	};
 
 	pci0: pcie@f8008000 {
-		cell-index = <0>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -410,7 +421,6 @@
 	};
 
 	pci1: pcie@f8009000 {
-		cell-index = <1>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sequoia.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sequoia.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/sequoia.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/sequoia.dts	2009-09-09 18:13:59.000000000 -0400
@@ -199,6 +199,28 @@
 					};
 				};
 
+				ndfc@3,0 {
+					compatible = "ibm,ndfc";
+					reg = <0x00000003 0x00000000 0x00002000>;
+					ccr = <0x00001000>;
+					bank-settings = <0x80002222>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+
+					nand {
+						#address-cells = <1>;
+						#size-cells = <1>;
+
+						partition@0 {
+							label = "u-boot";
+							reg = <0x00000000 0x00084000>;
+						};
+						partition@84000 {
+							label = "user";
+							reg = <0x00000000 0x01f7c000>;
+						};
+					};
+				};
 			};
 
 			UART0: serial@ef600300 {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/socrates.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/socrates.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/socrates.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/socrates.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,10 +55,22 @@
 		device_type = "soc";
 
 		ranges = <0x00000000 0xe0000000 0x00100000>;
-		reg = <0xe0000000 0x00001000>;	// CCSRBAR 1M
 		bus-frequency = <0>;		// Filled in by U-Boot
 		compatible = "fsl,mpc8544-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8544-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8544-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -314,7 +326,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/stx_gp3_8560.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/stx_gp3_8560.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/stx_gp3_8560.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/stx_gp3_8560.dts	2009-09-09 18:13:59.000000000 -0400
@@ -52,10 +52,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0 0xfdf00000 0x100000>;
-		reg = <0xfdf00000 0x1000>;
 		bus-frequency = <0>;
 		compatible = "fsl,mpc8560-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8540-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -251,7 +263,6 @@
 	};
 
 	pci0: pci@fdf08000 {
-		cell-index = <0>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8540.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8540.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8540.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8540.dts	2009-09-09 18:13:59.000000000 -0400
@@ -54,10 +54,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x200>;
 		bus-frequency = <0>;
 		compatible = "fsl,mpc8540-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8540-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8540-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -266,7 +278,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8541.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8541.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8541.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8541.dts	2009-09-09 18:13:59.000000000 -0400
@@ -53,10 +53,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x200>;
 		bus-frequency = <0>;
 		compatible = "fsl,mpc8541-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8541-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8540-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -288,7 +300,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8548-bigflash.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8548-bigflash.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8548-bigflash.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8548-bigflash.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,10 +55,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x0 0xa0000000 0x100000>;
-		reg = <0xa0000000 0x1000>;	// CCSRBAR
 		bus-frequency = <0>;
 		compatible = "fsl,mpc8548-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8548-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -419,7 +431,6 @@
 	};
 
 	pci0: pci@a0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
@@ -441,7 +452,6 @@
 	};
 
 	pci1: pcie@a000a000 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 			/* IDSEL 0x0 (PEX) */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8548.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8548.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8548.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8548.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,10 +55,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x1000>;	// CCSRBAR
 		bus-frequency = <0>;
 		compatible = "fsl,mpc8548-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <10>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8548-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -419,7 +431,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
@@ -441,7 +452,6 @@
 	};
 
 	pci1: pcie@e000a000 {
-		cell-index = <2>;
 		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 		interrupt-map = <
 			/* IDSEL 0x0 (PEX) */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8555.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8555.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8555.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8555.dts	2009-09-09 18:13:59.000000000 -0400
@@ -53,10 +53,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x200>;
 		bus-frequency = <0>;
 		compatible = "fsl,mpc8555-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8555-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8540-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -288,7 +300,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8560.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8560.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/tqm8560.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/tqm8560.dts	2009-09-09 18:13:59.000000000 -0400
@@ -55,10 +55,22 @@
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0x0 0xe0000000 0x100000>;
-		reg = <0xe0000000 0x200>;
 		bus-frequency = <0>;
 		compatible = "fsl,mpc8560-immr", "simple-bus";
 
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8560-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
 		memory-controller@2000 {
 			compatible = "fsl,mpc8540-memory-controller";
 			reg = <0x2000 0x1000>;
@@ -359,7 +371,6 @@
 	};
 
 	pci0: pci@e0008000 {
-		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/virtex440-ml510.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/virtex440-ml510.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/virtex440-ml510.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/virtex440-ml510.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,465 @@
+/*
+ * Xilinx ML510 Reference Design support
+ *
+ * This DTS file was created for the ml510_bsb1_pcores_ppc440 reference design.
+ * The reference design contains a bug which prevent PCI DMA from working
+ * properly.  A description of the bug is given in the plbv46_pci section. It
+ * needs to be fixed by the user until Xilinx updates their reference design.
+ *
+ * Copyright 2009, Roderick Colenbrander
+ */
+
+/dts-v1/;
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "xlnx,ml510-ref-design", "xlnx,virtex440";
+	dcr-parent = <&ppc440_0>;
+	DDR2_SDRAM_DIMM0: memory@0 {
+		device_type = "memory";
+		reg = < 0x0 0x20000000 >;
+	} ;
+	alias {
+		ethernet0 = &Hard_Ethernet_MAC;
+		serial0 = &RS232_Uart_1;
+	} ;
+	chosen {
+		bootargs = "console=ttyS0 root=/dev/ram";
+		linux,stdout-path = "/plb@0/serial@83e00000";
+	} ;
+	cpus {
+		#address-cells = <1>;
+		#cpus = <0x1>;
+		#size-cells = <0>;
+		ppc440_0: cpu@0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clock-frequency = <300000000>;
+			compatible = "PowerPC,440", "ibm,ppc440";
+			d-cache-line-size = <0x20>;
+			d-cache-size = <0x8000>;
+			dcr-access-method = "native";
+			dcr-controller ;
+			device_type = "cpu";
+			i-cache-line-size = <0x20>;
+			i-cache-size = <0x8000>;
+			model = "PowerPC,440";
+			reg = <0>;
+			timebase-frequency = <300000000>;
+			xlnx,apu-control = <0x2000>;
+			xlnx,apu-udi-0 = <0x0>;
+			xlnx,apu-udi-1 = <0x0>;
+			xlnx,apu-udi-10 = <0x0>;
+			xlnx,apu-udi-11 = <0x0>;
+			xlnx,apu-udi-12 = <0x0>;
+			xlnx,apu-udi-13 = <0x0>;
+			xlnx,apu-udi-14 = <0x0>;
+			xlnx,apu-udi-15 = <0x0>;
+			xlnx,apu-udi-2 = <0x0>;
+			xlnx,apu-udi-3 = <0x0>;
+			xlnx,apu-udi-4 = <0x0>;
+			xlnx,apu-udi-5 = <0x0>;
+			xlnx,apu-udi-6 = <0x0>;
+			xlnx,apu-udi-7 = <0x0>;
+			xlnx,apu-udi-8 = <0x0>;
+			xlnx,apu-udi-9 = <0x0>;
+			xlnx,dcr-autolock-enable = <0x1>;
+			xlnx,dcu-rd-ld-cache-plb-prio = <0x0>;
+			xlnx,dcu-rd-noncache-plb-prio = <0x0>;
+			xlnx,dcu-rd-touch-plb-prio = <0x0>;
+			xlnx,dcu-rd-urgent-plb-prio = <0x0>;
+			xlnx,dcu-wr-flush-plb-prio = <0x0>;
+			xlnx,dcu-wr-store-plb-prio = <0x0>;
+			xlnx,dcu-wr-urgent-plb-prio = <0x0>;
+			xlnx,dma0-control = <0x0>;
+			xlnx,dma0-plb-prio = <0x0>;
+			xlnx,dma0-rxchannelctrl = <0x1010000>;
+			xlnx,dma0-rxirqtimer = <0x3ff>;
+			xlnx,dma0-txchannelctrl = <0x1010000>;
+			xlnx,dma0-txirqtimer = <0x3ff>;
+			xlnx,dma1-control = <0x0>;
+			xlnx,dma1-plb-prio = <0x0>;
+			xlnx,dma1-rxchannelctrl = <0x1010000>;
+			xlnx,dma1-rxirqtimer = <0x3ff>;
+			xlnx,dma1-txchannelctrl = <0x1010000>;
+			xlnx,dma1-txirqtimer = <0x3ff>;
+			xlnx,dma2-control = <0x0>;
+			xlnx,dma2-plb-prio = <0x0>;
+			xlnx,dma2-rxchannelctrl = <0x1010000>;
+			xlnx,dma2-rxirqtimer = <0x3ff>;
+			xlnx,dma2-txchannelctrl = <0x1010000>;
+			xlnx,dma2-txirqtimer = <0x3ff>;
+			xlnx,dma3-control = <0x0>;
+			xlnx,dma3-plb-prio = <0x0>;
+			xlnx,dma3-rxchannelctrl = <0x1010000>;
+			xlnx,dma3-rxirqtimer = <0x3ff>;
+			xlnx,dma3-txchannelctrl = <0x1010000>;
+			xlnx,dma3-txirqtimer = <0x3ff>;
+			xlnx,endian-reset = <0x0>;
+			xlnx,generate-plb-timespecs = <0x1>;
+			xlnx,icu-rd-fetch-plb-prio = <0x0>;
+			xlnx,icu-rd-spec-plb-prio = <0x0>;
+			xlnx,icu-rd-touch-plb-prio = <0x0>;
+			xlnx,interconnect-imask = <0xffffffff>;
+			xlnx,mplb-allow-lock-xfer = <0x1>;
+			xlnx,mplb-arb-mode = <0x0>;
+			xlnx,mplb-awidth = <0x20>;
+			xlnx,mplb-counter = <0x500>;
+			xlnx,mplb-dwidth = <0x80>;
+			xlnx,mplb-max-burst = <0x8>;
+			xlnx,mplb-native-dwidth = <0x80>;
+			xlnx,mplb-p2p = <0x0>;
+			xlnx,mplb-prio-dcur = <0x2>;
+			xlnx,mplb-prio-dcuw = <0x3>;
+			xlnx,mplb-prio-icu = <0x4>;
+			xlnx,mplb-prio-splb0 = <0x1>;
+			xlnx,mplb-prio-splb1 = <0x0>;
+			xlnx,mplb-read-pipe-enable = <0x1>;
+			xlnx,mplb-sync-tattribute = <0x0>;
+			xlnx,mplb-wdog-enable = <0x1>;
+			xlnx,mplb-write-pipe-enable = <0x1>;
+			xlnx,mplb-write-post-enable = <0x1>;
+			xlnx,num-dma = <0x0>;
+			xlnx,pir = <0xf>;
+			xlnx,ppc440mc-addr-base = <0x0>;
+			xlnx,ppc440mc-addr-high = <0x1fffffff>;
+			xlnx,ppc440mc-arb-mode = <0x0>;
+			xlnx,ppc440mc-bank-conflict-mask = <0x1800000>;
+			xlnx,ppc440mc-control = <0xf810008f>;
+			xlnx,ppc440mc-max-burst = <0x8>;
+			xlnx,ppc440mc-prio-dcur = <0x2>;
+			xlnx,ppc440mc-prio-dcuw = <0x3>;
+			xlnx,ppc440mc-prio-icu = <0x4>;
+			xlnx,ppc440mc-prio-splb0 = <0x1>;
+			xlnx,ppc440mc-prio-splb1 = <0x0>;
+			xlnx,ppc440mc-row-conflict-mask = <0x7ffe00>;
+			xlnx,ppcdm-asyncmode = <0x0>;
+			xlnx,ppcds-asyncmode = <0x0>;
+			xlnx,user-reset = <0x0>;
+		} ;
+	} ;
+	plb_v46_0: plb@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "xlnx,plb-v46-1.03.a", "simple-bus";
+		ranges ;
+		FLASH: flash@fc000000 {
+			bank-width = <2>;
+			compatible = "xlnx,xps-mch-emc-2.00.a", "cfi-flash";
+			reg = < 0xfc000000 0x2000000 >;
+			xlnx,family = "virtex5";
+			xlnx,include-datawidth-matching-0 = <0x1>;
+			xlnx,include-datawidth-matching-1 = <0x0>;
+			xlnx,include-datawidth-matching-2 = <0x0>;
+			xlnx,include-datawidth-matching-3 = <0x0>;
+			xlnx,include-negedge-ioregs = <0x0>;
+			xlnx,include-plb-ipif = <0x1>;
+			xlnx,include-wrbuf = <0x1>;
+			xlnx,max-mem-width = <0x10>;
+			xlnx,mch-native-dwidth = <0x20>;
+			xlnx,mch-plb-clk-period-ps = <0x2710>;
+			xlnx,mch-splb-awidth = <0x20>;
+			xlnx,mch0-accessbuf-depth = <0x10>;
+			xlnx,mch0-protocol = <0x0>;
+			xlnx,mch0-rddatabuf-depth = <0x10>;
+			xlnx,mch1-accessbuf-depth = <0x10>;
+			xlnx,mch1-protocol = <0x0>;
+			xlnx,mch1-rddatabuf-depth = <0x10>;
+			xlnx,mch2-accessbuf-depth = <0x10>;
+			xlnx,mch2-protocol = <0x0>;
+			xlnx,mch2-rddatabuf-depth = <0x10>;
+			xlnx,mch3-accessbuf-depth = <0x10>;
+			xlnx,mch3-protocol = <0x0>;
+			xlnx,mch3-rddatabuf-depth = <0x10>;
+			xlnx,mem0-width = <0x10>;
+			xlnx,mem1-width = <0x20>;
+			xlnx,mem2-width = <0x20>;
+			xlnx,mem3-width = <0x20>;
+			xlnx,num-banks-mem = <0x1>;
+			xlnx,num-channels = <0x2>;
+			xlnx,priority-mode = <0x0>;
+			xlnx,synch-mem-0 = <0x0>;
+			xlnx,synch-mem-1 = <0x0>;
+			xlnx,synch-mem-2 = <0x0>;
+			xlnx,synch-mem-3 = <0x0>;
+			xlnx,synch-pipedelay-0 = <0x2>;
+			xlnx,synch-pipedelay-1 = <0x2>;
+			xlnx,synch-pipedelay-2 = <0x2>;
+			xlnx,synch-pipedelay-3 = <0x2>;
+			xlnx,tavdv-ps-mem-0 = <0x1adb0>;
+			xlnx,tavdv-ps-mem-1 = <0x3a98>;
+			xlnx,tavdv-ps-mem-2 = <0x3a98>;
+			xlnx,tavdv-ps-mem-3 = <0x3a98>;
+			xlnx,tcedv-ps-mem-0 = <0x1adb0>;
+			xlnx,tcedv-ps-mem-1 = <0x3a98>;
+			xlnx,tcedv-ps-mem-2 = <0x3a98>;
+			xlnx,tcedv-ps-mem-3 = <0x3a98>;
+			xlnx,thzce-ps-mem-0 = <0x88b8>;
+			xlnx,thzce-ps-mem-1 = <0x1b58>;
+			xlnx,thzce-ps-mem-2 = <0x1b58>;
+			xlnx,thzce-ps-mem-3 = <0x1b58>;
+			xlnx,thzoe-ps-mem-0 = <0x1b58>;
+			xlnx,thzoe-ps-mem-1 = <0x1b58>;
+			xlnx,thzoe-ps-mem-2 = <0x1b58>;
+			xlnx,thzoe-ps-mem-3 = <0x1b58>;
+			xlnx,tlzwe-ps-mem-0 = <0x88b8>;
+			xlnx,tlzwe-ps-mem-1 = <0x0>;
+			xlnx,tlzwe-ps-mem-2 = <0x0>;
+			xlnx,tlzwe-ps-mem-3 = <0x0>;
+			xlnx,twc-ps-mem-0 = <0x1adb0>;
+			xlnx,twc-ps-mem-1 = <0x3a98>;
+			xlnx,twc-ps-mem-2 = <0x3a98>;
+			xlnx,twc-ps-mem-3 = <0x3a98>;
+			xlnx,twp-ps-mem-0 = <0x11170>;
+			xlnx,twp-ps-mem-1 = <0x2ee0>;
+			xlnx,twp-ps-mem-2 = <0x2ee0>;
+			xlnx,twp-ps-mem-3 = <0x2ee0>;
+			xlnx,xcl0-linesize = <0x4>;
+			xlnx,xcl0-writexfer = <0x1>;
+			xlnx,xcl1-linesize = <0x4>;
+			xlnx,xcl1-writexfer = <0x1>;
+			xlnx,xcl2-linesize = <0x4>;
+			xlnx,xcl2-writexfer = <0x1>;
+			xlnx,xcl3-linesize = <0x4>;
+			xlnx,xcl3-writexfer = <0x1>;
+		} ;
+		Hard_Ethernet_MAC: xps-ll-temac@81c00000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "xlnx,compound";
+			ethernet@81c00000 {
+				compatible = "xlnx,xps-ll-temac-1.01.b";
+				device_type = "network";
+				interrupt-parent = <&xps_intc_0>;
+				interrupts = < 8 2 >;
+				llink-connected = <&Hard_Ethernet_MAC_fifo>;
+				local-mac-address = [ 02 00 00 00 00 00 ];
+				reg = < 0x81c00000 0x40 >;
+				xlnx,bus2core-clk-ratio = <0x1>;
+				xlnx,phy-type = <0x3>;
+				xlnx,phyaddr = <0x1>;
+				xlnx,rxcsum = <0x0>;
+				xlnx,rxfifo = <0x8000>;
+				xlnx,temac-type = <0x0>;
+				xlnx,txcsum = <0x0>;
+				xlnx,txfifo = <0x8000>;
+			} ;
+		} ;
+		Hard_Ethernet_MAC_fifo: xps-ll-fifo@81a00000 {
+			compatible = "xlnx,xps-ll-fifo-1.01.a";
+			interrupt-parent = <&xps_intc_0>;
+			interrupts = < 6 2 >;
+			reg = < 0x81a00000 0x10000 >;
+			xlnx,family = "virtex5";
+		} ;
+		IIC_EEPROM: i2c@81600000 {
+			compatible = "xlnx,xps-iic-2.00.a";
+			interrupt-parent = <&xps_intc_0>;
+			interrupts = < 9 2 >;
+			reg = < 0x81600000 0x10000 >;
+			xlnx,clk-freq = <0x5f5e100>;
+			xlnx,family = "virtex5";
+			xlnx,gpo-width = <0x1>;
+			xlnx,iic-freq = <0x186a0>;
+			xlnx,scl-inertial-delay = <0x5>;
+			xlnx,sda-inertial-delay = <0x5>;
+			xlnx,ten-bit-adr = <0x0>;
+		} ;
+		LCD_OPTIONAL: gpio@81420000 {
+			compatible = "xlnx,xps-gpio-1.00.a";
+			reg = < 0x81420000 0x10000 >;
+			xlnx,all-inputs = <0x0>;
+			xlnx,all-inputs-2 = <0x0>;
+			xlnx,dout-default = <0x0>;
+			xlnx,dout-default-2 = <0x0>;
+			xlnx,family = "virtex5";
+			xlnx,gpio-width = <0xb>;
+			xlnx,interrupt-present = <0x0>;
+			xlnx,is-bidir = <0x1>;
+			xlnx,is-bidir-2 = <0x1>;
+			xlnx,is-dual = <0x0>;
+			xlnx,tri-default = <0xffffffff>;
+			xlnx,tri-default-2 = <0xffffffff>;
+		} ;
+		LEDs_4Bit: gpio@81400000 {
+			compatible = "xlnx,xps-gpio-1.00.a";
+			reg = < 0x81400000 0x10000 >;
+			xlnx,all-inputs = <0x0>;
+			xlnx,all-inputs-2 = <0x0>;
+			xlnx,dout-default = <0x0>;
+			xlnx,dout-default-2 = <0x0>;
+			xlnx,family = "virtex5";
+			xlnx,gpio-width = <0x4>;
+			xlnx,interrupt-present = <0x0>;
+			xlnx,is-bidir = <0x1>;
+			xlnx,is-bidir-2 = <0x1>;
+			xlnx,is-dual = <0x0>;
+			xlnx,tri-default = <0xffffffff>;
+			xlnx,tri-default-2 = <0xffffffff>;
+		} ;
+		RS232_Uart_1: serial@83e00000 {
+			clock-frequency = <100000000>;
+			compatible = "xlnx,xps-uart16550-2.00.b", "ns16550";
+			current-speed = <9600>;
+			device_type = "serial";
+			interrupt-parent = <&xps_intc_0>;
+			interrupts = < 11 2 >;
+			reg = < 0x83e00000 0x10000 >;
+			reg-offset = <0x1003>;
+			reg-shift = <2>;
+			xlnx,family = "virtex5";
+			xlnx,has-external-rclk = <0x0>;
+			xlnx,has-external-xin = <0x0>;
+			xlnx,is-a-16550 = <0x1>;
+		} ;
+		SPI_EEPROM: xps-spi@feff8000 {
+			compatible = "xlnx,xps-spi-2.00.b";
+			interrupt-parent = <&xps_intc_0>;
+			interrupts = < 10 2 >;
+			reg = < 0xfeff8000 0x80 >;
+			xlnx,family = "virtex5";
+			xlnx,fifo-exist = <0x1>;
+			xlnx,num-ss-bits = <0x1>;
+			xlnx,num-transfer-bits = <0x8>;
+			xlnx,sck-ratio = <0x80>;
+		} ;
+		SysACE_CompactFlash: sysace@83600000 {
+			compatible = "xlnx,xps-sysace-1.00.a";
+			interrupt-parent = <&xps_intc_0>;
+			interrupts = < 7 2 >;
+			reg = < 0x83600000 0x10000 >;
+			xlnx,family = "virtex5";
+			xlnx,mem-width = <0x10>;
+		} ;
+		plbv46_pci_0: plbv46-pci@85e00000 {
+			#size-cells = <2>;
+			#address-cells = <3>;
+			compatible = "xlnx,plbv46-pci-1.03.a";
+			device_type = "pci";
+			reg = < 0x85e00000 0x10000 >;
+
+			/*
+			 * The default ML510 BSB has C_IPIFBAR2PCIBAR_0 set to
+			 * 0 which means that a read/write to the memory mapped
+			 * i/o region (which starts at 0xa0000000) for pci
+			 * bar 0 on the plb side translates to 0.
+			 * It is important to set this value to 0xa0000000, so
+			 * that inbound and outbound pci transactions work
+			 * properly including DMA.
+			 */
+			ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x20000000
+				  0x01000000 0 0x00000000 0xf0000000 0 0x00010000>;
+
+			#interrupt-cells = <1>;
+			interrupt-parent = <&xps_intc_0>;
+			interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+			interrupt-map = <
+				/* IRQ mapping for pci slots and ALI M1533
+				 * periperhals. In total there are 5 interrupt
+				 * lines connected to a xps_intc controller.
+				 * Four of them are PCI IRQ A, B, C, D and
+				 * which correspond to respectively xpx_intc
+				 * 5, 4, 3 and 2.  The fifth interrupt line is
+				 * connected to the south bridge and this one
+				 * uses irq 1 and is active high instead of
+				 * active low.
+				 *
+				 * The M1533 contains various peripherals
+				 * including AC97 audio, a modem, USB, IDE and
+				 * some power management stuff. The modem
+				 * isn't connected on the ML510 and the power
+				 * management core also isn't used.
+				 */
+
+				/* IDSEL 0x16 / dev=6, bus=0 / PCI slot 3 */
+				0x3000 0 0 1 &xps_intc_0 3 2
+				0x3000 0 0 2 &xps_intc_0 2 2
+				0x3000 0 0 3 &xps_intc_0 5 2
+				0x3000 0 0 4 &xps_intc_0 4 2
+
+				/* IDSEL 0x13 / dev=3, bus=1 / PCI slot 4 */
+				/*
+				0x11800 0 0 1 &xps_intc_0 5 0 2
+				0x11800 0 0 2 &xps_intc_0 4 0 2
+				0x11800 0 0 3 &xps_intc_0 3 0 2
+				0x11800 0 0 4 &xps_intc_0 2 0 2
+				*/
+
+				/* According to the datasheet + schematic
+				 * ABCD [FPGA] of slot 5 is mapped to DABC.
+				 * Testing showed that at least A maps to B,
+				 * the mapping of the other pins is a guess
+				 * and for that reason the lines have been
+				 * commented out.
+				 */
+				/* IDSEL 0x15 / dev=5, bus=0 / PCI slot 5 */
+				0x2800 0 0 1 &xps_intc_0 4 2
+				/*
+				0x2800 0 0 2 &xps_intc_0 3 2
+				0x2800 0 0 3 &xps_intc_0 2 2
+				0x2800 0 0 4 &xps_intc_0 5 2
+				*/
+
+				/* IDSEL 0x12 / dev=2, bus=1 / PCI slot 6 */
+				/*
+				0x11000 0 0 1 &xps_intc_0 4 0 2
+				0x11000 0 0 2 &xps_intc_0 3 0 2
+				0x11000 0 0 3 &xps_intc_0 2 0 2
+				0x11000 0 0 4 &xps_intc_0 5 0 2
+				*/
+
+				/* IDSEL 0x11 / dev=1, bus=0 / AC97 audio */
+				0x0800 0 0 1 &i8259 7 2
+
+				/* IDSEL 0x1b / dev=11, bus=0 / IDE */
+				0x5800 0 0 1 &i8259 14 2
+
+				/* IDSEL 0x1f / dev 15, bus=0 / 2x USB 1.1 */
+				0x7800 0 0 1 &i8259 7 2
+			>;
+			ali_m1533 {
+				#size-cells = <1>;
+				#address-cells = <2>;
+				i8259: interrupt-controller@20 {
+					reg = <1 0x20 2
+							1 0xa0 2
+							1 0x4d0 2>;
+					interrupt-controller;
+					device_type = "interrupt-controller";
+					#address-cells = <0>;
+					#interrupt-cells = <2>;
+					compatible = "chrp,iic";
+
+					/* south bridge irq is active high */
+					interrupts = <1 3>;
+					interrupt-parent = <&xps_intc_0>;
+				};
+			};
+		} ;
+		xps_bram_if_cntlr_1: xps-bram-if-cntlr@ffff0000 {
+			compatible = "xlnx,xps-bram-if-cntlr-1.00.a";
+			reg = < 0xffff0000 0x10000 >;
+			xlnx,family = "virtex5";
+		} ;
+		xps_intc_0: interrupt-controller@81800000 {
+			#interrupt-cells = <0x2>;
+			compatible = "xlnx,xps-intc-1.00.a";
+			interrupt-controller ;
+			reg = < 0x81800000 0x10000 >;
+			xlnx,num-intr-inputs = <0xc>;
+		} ;
+		xps_tft_0: tft@86e00000 {
+			compatible = "xlnx,xps-tft-1.00.a";
+			reg = < 0x86e00000 0x10000 >;
+			xlnx,dcr-splb-slave-if = <0x1>;
+			xlnx,default-tft-base-addr = <0x0>;
+			xlnx,family = "virtex5";
+			xlnx,i2c-slave-addr = <0x76>;
+			xlnx,mplb-awidth = <0x20>;
+			xlnx,mplb-dwidth = <0x80>;
+			xlnx,mplb-native-dwidth = <0x40>;
+			xlnx,mplb-smallest-slave = <0x20>;
+			xlnx,tft-interface = <0x1>;
+		} ;
+	} ;
+}  ;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/warp.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/warp.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/warp.dts	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/warp.dts	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for PIKA Warp
  *
- * Copyright (c) 2008 PIKA Technologies
+ * Copyright (c) 2008-2009 PIKA Technologies
  *   Sean MacLennan <smaclennan@pikatech.com>
  *
  * This file is licensed under the terms of the GNU General Public
@@ -158,7 +158,7 @@
 
 					partition@0 {
 						label = "splash";
-						reg = <0x00000000 0x00020000>;
+						reg = <0x00000000 0x00010000>;
 					};
 					partition@300000 {
 						label = "fpga";
@@ -244,28 +244,28 @@
 			};
 
 			GPIO0: gpio@ef600b00 {
-				compatible = "ibm,gpio-440ep";
+				compatible = "ibm,ppc4xx-gpio";
 				reg = <0xef600b00 0x00000048>;
 				#gpio-cells = <2>;
 				gpio-controller;
 			};
 
 			GPIO1: gpio@ef600c00 {
-				compatible = "ibm,gpio-440ep";
+				compatible = "ibm,ppc4xx-gpio";
 				reg = <0xef600c00 0x00000048>;
 				#gpio-cells = <2>;
 				gpio-controller;
+			};
 
-				led@31 {
-					compatible = "linux,gpio-led";
-					linux,name = ":green:";
-					gpios = <&GPIO1 31 0>;
-				};		
-	
-				led@30 {	
-					compatible = "linux,gpio-led";
-					linux,name = ":red:";
-					gpios = <&GPIO1 30 0>;
+			power-leds {
+				compatible = "gpio-leds";
+				green {
+					gpios = <&GPIO1 0 0>;
+					default-state = "keep";
+				};
+				red {
+					gpios = <&GPIO1 1 0>;
+					default-state = "keep";
 				};
 			};
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xcalibur1501.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xcalibur1501.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xcalibur1501.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xcalibur1501.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,696 @@
+/*
+ * Copyright (C) 2008 Extreme Engineering Solutions, Inc.
+ * Based on MPC8572DS device tree from Freescale Semiconductor, Inc.
+ *
+ * XCalibur1501 6U CompactPCI single-board computer based on MPC8572E
+ *
+ * This 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.
+ */
+
+/dts-v1/;
+/ {
+	model = "xes,xcalibur1501";
+	compatible = "xes,xcalibur1501", "xes,MPC8572";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci2 = &pci2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8572@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		PowerPC,8572@1 {
+			device_type = "cpu";
+			reg = <0x1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x0>;	// Filled in by U-Boot
+	};
+
+	localbus@ef005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8572-elbc", "fsl,elbc", "simple-bus";
+		reg = <0 0xef005000 0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+		/* Local bus region mappings */
+		ranges = <0 0 0 0xf8000000 0x8000000  /* CS0: Flash 1 */
+			  1 0 0 0xf0000000 0x8000000  /* CS1: Flash 2 */
+			  2 0 0 0xef800000 0x40000    /* CS2: NAND CE1 */
+			  3 0 0 0xef840000 0x40000    /* CS3: NAND CE2 */
+			  4 0 0 0xe9000000 0x100000>; /* CS4: USB */
+
+		nor-boot@0,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			reg = <0 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Primary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Primary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Primary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Primary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Primary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nor-alternate@1,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			//reg = <0xf0000000 0x08000000>; /* 128MB */
+			reg = <1 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Secondary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Secondary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Secondary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Secondary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Secondary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/*
+			 * Actual part could be ST Micro NAND08GW3B2A (1 GB),
+			 * Micron MT29F8G08DAA (2x 512 MB), or Micron
+			 * MT29F16G08FAA (2x 1 GB), depending on the build
+			 * configuration
+			 */
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <2 0 0x40000>;
+			/* U-Boot should fix this up if chip size > 1 GB */
+			partition@0 {
+				label = "NAND Filesystem";
+				reg = <0 0x40000000>;
+			};
+		};
+
+		usb@4,0 {
+			compatible = "nxp,usb-isp1761";
+			reg = <4 0 0x100000>;
+			bus-width = <32>;
+			interrupt-parent = <&mpic>;
+			interrupts = <10 1>;
+		};
+	};
+
+	soc8572@ef000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8572-immr", "simple-bus";
+		ranges = <0x0 0 0xef000000 0x100000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		memory-controller@6000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x6000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8572-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x100000>; // L2, 1M
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			temp-sensor@48 {
+				compatible = "dallas,ds1631", "dallas,ds1621";
+				reg = <0x48>;
+			};
+
+			temp-sensor@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+
+			cpu-supervisor@51 {
+				compatible = "dallas,ds4510";
+				reg = <0x51>;
+			};
+
+			eeprom@54 {
+				compatible = "atmel,at24c128b";
+				reg = <0x54>;
+			};
+
+			rtc@68 {
+				compatible = "stm,m41t00",
+				             "dallas,ds1338";
+				reg = <0x68>;
+			};
+
+			pcie-switch@6a {
+				compatible = "plx,pex8648";
+				reg = <0x6a>;
+			};
+
+			/* On-board signals for VID, flash, serial */
+			gpio1: gpio@18 {
+				compatible = "nxp,pca9557";
+				reg = <0x18>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			/* PMC0/XMC0 signals */
+			gpio2: gpio@1c {
+				compatible = "nxp,pca9557";
+				reg = <0x1c>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			/* PMC1/XMC1 signals */
+			gpio3: gpio@1d {
+				compatible = "nxp,pca9557";
+				reg = <0x1d>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			/* CompactPCI signals (sysen, GA[4:0]) */
+			gpio4: gpio@1e {
+				compatible = "nxp,pca9557";
+				reg = <0x1e>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			/* CompactPCI J5 GPIO and FAL/DEG/PRST */
+			gpio5: gpio@1f {
+				compatible = "nxp,pca9557";
+				reg = <0x1f>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@c300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0xc300 0x4>;
+			ranges = <0x0 0xc100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <76 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <77 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <78 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <79 2>;
+			};
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		/* eTSEC 1 front panel 0 */
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <4 1>;
+					reg = <0x1>;
+				};
+				phy1: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <4 1>;
+					reg = <0x2>;
+				};
+				phy2: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x3>;
+				};
+				phy3: ethernet-phy@4 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x4>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC 2 front panel 1 */
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC 3 PICMG2.16 backplane port 0 */
+		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
+			phy-handle = <&phy2>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC 4 PICMG2.16 backplane port 1 */
+		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <3>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <37 2 38 2 39 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi3>;
+			phy-handle = <&phy3>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* UART0 */
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		/* UART1 */
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8572-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
+				     "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2 58 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0x9fe>;
+			fsl,descriptor-types-mask = <0x3ab0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		gpio0: gpio@f000 {
+			compatible = "fsl,mpc8572-gpio";
+			reg = <0xf000 0x1000>;
+			interrupts = <47 2>;
+			interrupt-parent = <&mpic>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+
+			heartbeat {
+				label = "Heartbeat";
+				gpios = <&gpio0 4 1>;
+				linux,default-trigger = "heartbeat";
+			};
+
+			yellow {
+				label = "Yellow";
+				gpios = <&gpio0 5 1>;
+			};
+
+			red {
+				label = "Red";
+				gpios = <&gpio0 6 1>;
+			};
+
+			green {
+				label = "Green";
+				gpios = <&gpio0 7 1>;
+			};
+		};
+
+		/* PME (pattern-matcher) */
+		pme@10000 {
+			compatible = "fsl,mpc8572-pme", "pme8572";
+			reg = <0x10000 0x5000>;
+			interrupts = <57 2 64 2 65 2 66 2 67 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@2f000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x2f000 0x1000>;
+			interupts = <61 2 >;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@15000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x15000 0x1000>;
+			interupts = <75 2>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	/*
+	 * PCI Express controller 3 @ ef008000 is not used.
+	 * This would have been pci0 on other mpc85xx platforms.
+	 *
+	 * PCI Express controller 2 @ ef009000 is not used.
+	 * This would have been pci1 on other mpc85xx platforms.
+	 */
+
+	/* PCI Express controller 1, wired to PEX8648 PCIe switch */
+	pci2: pcie@ef00a000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef00a000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x40000000
+			  0x1000000 0x0 0x00000000 0 0xe8000000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x40000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5200.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5200.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5200.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5200.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2009 Extreme Engineering Solutions, Inc.
+ * Based on TQM8548 device tree
+ *
+ * XPedite5200 PrPMC/XMC module based on MPC8548E
+ *
+ * This 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "xes,xpedite5200";
+	compatible = "xes,xpedite5200", "xes,MPC8548";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8548@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;	// L1, 32K
+			i-cache-size = <0x8000>;	// L1, 32K
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0>;	// Filled in by U-Boot
+	};
+
+	soc@ef000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		ranges = <0x0 0xef000000 0x100000>;
+		bus-frequency = <0>;
+		compatible = "fsl,mpc8548-immr", "simple-bus";
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8548-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8548-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x80000>;	// L2, 512K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		/* On-card I2C */
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			/*
+			 * Board GPIO:
+			 * 	0: BRD_CFG0 (1: P14 IO present)
+			 * 	1: BRD_CFG1 (1: FP ethernet present)
+			 * 	2: BRD_CFG2 (1: XMC IO present)
+			 * 	3: XMC root complex indicator
+			 * 	4: Flash boot device indicator
+			 * 	5: Flash write protect enable
+			 * 	6: PMC monarch indicator
+			 * 	7: PMC EREADY
+			 */
+			gpio1: gpio@18 {
+				compatible = "nxp,pca9556";
+				reg = <0x18>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			/* P14 GPIO */
+			gpio2: gpio@19 {
+				compatible = "nxp,pca9556";
+				reg = <0x19>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			eeprom@50 {
+				compatible = "atmel,at24c16";
+				reg = <0x50>;
+			};
+
+			rtc@68 {
+				compatible = "stm,m41t00",
+					     "dallas,ds1338";
+				reg = <0x68>;
+			};
+
+			dtt@48 {
+				compatible = "maxim,max1237";
+				reg = <0x34>;
+			};
+		};
+
+		/* Off-card I2C */
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8548-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		/* eTSEC1: Front panel port 0 */
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x1>;
+				};
+				phy1: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x2>;
+				};
+				phy2: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x3>;
+				};
+				phy3: ethernet-phy@4 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x4>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC2: Front panel port 1 */
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC3: Rear panel port 2 */
+		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
+			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC4: Rear panel port 3 */
+		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <3>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <37 2 38 2 39 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi3>;
+			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	// global utilities reg
+			compatible = "fsl,mpc8548-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+	};
+
+	localbus@ef005000 {
+		compatible = "fsl,mpc8548-localbus", "fsl,pq3-localbus",
+			     "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0xef005000 0x100>;	// BRx, ORx, etc.
+
+		ranges = <
+			0 0x0 0xfc000000 0x04000000	// NOR boot flash
+			1 0x0 0xf8000000 0x04000000	// NOR expansion flash
+			2 0x0 0xef800000 0x00010000	// NAND CE1
+			3 0x0 0xef840000 0x00010000	// NAND CE2
+		>;
+
+		nor-boot@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0 0x0 0x4000000>;
+			bank-width = <2>;
+
+			partition@0 {
+				label = "Primary OS";
+				reg = <0x00000000 0x180000>;
+			};
+			partition@180000 {
+				label = "Secondary OS";
+				reg = <0x00180000 0x180000>;
+			};
+			partition@300000 {
+				label = "User";
+				reg = <0x00300000 0x3c80000>;
+			};
+			partition@3f80000 {
+				label = "Boot firmware";
+				reg = <0x03f80000 0x80000>;
+			};
+		};
+
+		nor-alternate@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x4000000>;
+			bank-width = <2>;
+
+			partition@0 {
+				label = "Filesystem";
+				reg = <0x00000000 0x3f80000>;
+			};
+			partition@3f80000 {
+				label = "Alternate boot firmware";
+				reg = <0x03f80000 0x80000>;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "xes,address-ctl-nand";
+			reg = <2 0x0 0x10000>;
+			cle-line = <0x8>;	/* CLE tied to A3 */
+			ale-line = <0x10>;	/* ALE tied to A4 */
+
+			/* U-Boot should fix this up */
+			partition@0 {
+				label = "NAND Filesystem";
+				reg = <0 0x40000000>;
+			};
+		};
+	};
+
+	/* PMC interface */
+	pci0: pci@ef008000 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+		device_type = "pci";
+		reg = <0xef008000 0x1000>;
+		clock-frequency = <33333333>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+				/* IDSEL */
+				 0xe000 0 0 1 &mpic 2 1
+				 0xe000 0 0 2 &mpic 3 1>;
+
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		bus-range = <0 0>;
+		ranges = <0x02000000 0 0x80000000 0x80000000 0 0x40000000
+			  0x01000000 0 0x00000000 0xe8000000 0 0x00800000>;
+	};
+
+	/* XMC PCIe is not yet enabled in U-Boot on XPedite5200 */
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5200_xmon.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5200_xmon.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5200_xmon.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5200_xmon.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2009 Extreme Engineering Solutions, Inc.
+ * Based on TQM8548 device tree
+ *
+ * XPedite5200 PrPMC/XMC module based on MPC8548E.  This dts is for the
+ * xMon boot loader memory map which differs from U-Boot's.
+ *
+ * This 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "xes,xpedite5200";
+	compatible = "xes,xpedite5200", "xes,MPC8548";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	form-factor = "PMC/XMC";
+	boot-bank = <0x0>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8548@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;	// L1, 32K
+			i-cache-size = <0x8000>;	// L1, 32K
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0>;	// Filled in by boot loader
+	};
+
+	soc@ef000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		ranges = <0x0 0xef000000 0x100000>;
+		bus-frequency = <0>;
+		compatible = "fsl,mpc8548-immr", "simple-bus";
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8548-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8548-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8548-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x80000>;	// L2, 512K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		/* On-card I2C */
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			/*
+			 * Board GPIO:
+			 * 	0: BRD_CFG0 (1: P14 IO present)
+			 * 	1: BRD_CFG1 (1: FP ethernet present)
+			 * 	2: BRD_CFG2 (1: XMC IO present)
+			 * 	3: XMC root complex indicator
+			 * 	4: Flash boot device indicator
+			 * 	5: Flash write protect enable
+			 * 	6: PMC monarch indicator
+			 * 	7: PMC EREADY
+			 */
+			gpio1: gpio@18 {
+				compatible = "nxp,pca9556";
+				reg = <0x18>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			/* P14 GPIO */
+			gpio2: gpio@19 {
+				compatible = "nxp,pca9556";
+				reg = <0x19>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			eeprom@50 {
+				compatible = "atmel,at24c16";
+				reg = <0x50>;
+			};
+
+			rtc@68 {
+				compatible = "stm,m41t00",
+					     "dallas,ds1338";
+				reg = <0x68>;
+			};
+
+			dtt@48 {
+				compatible = "maxim,max1237";
+				reg = <0x34>;
+			};
+		};
+
+		/* Off-card I2C */
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8548-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8548-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		/* eTSEC1: Front panel port 0 */
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x1>;
+				};
+				phy1: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x2>;
+				};
+				phy2: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x3>;
+				};
+				phy3: ethernet-phy@4 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x4>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC2: Front panel port 1 */
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC3: Rear panel port 2 */
+		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
+			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC4: Rear panel port 3 */
+		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <3>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <37 2 38 2 39 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi3>;
+			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			current-speed = <9600>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			current-speed = <9600>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	// global utilities reg
+			compatible = "fsl,mpc8548-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+	};
+
+	localbus@ef005000 {
+		compatible = "fsl,mpc8548-localbus", "fsl,pq3-localbus",
+			     "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0xef005000 0x100>;	// BRx, ORx, etc.
+
+		ranges = <
+			0 0x0 0xf8000000 0x08000000	// NOR boot flash
+			1 0x0 0xf0000000 0x08000000	// NOR expansion flash
+			2 0x0 0xe8000000 0x00010000	// NAND CE1
+			3 0x0 0xe8010000 0x00010000	// NAND CE2
+		>;
+
+		nor-boot@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0 0x0 0x4000000>;
+			bank-width = <2>;
+
+			partition@0 {
+				label = "Primary OS";
+				reg = <0x00000000 0x180000>;
+			};
+			partition@180000 {
+				label = "Secondary OS";
+				reg = <0x00180000 0x180000>;
+			};
+			partition@300000 {
+				label = "User";
+				reg = <0x00300000 0x3c80000>;
+			};
+			partition@3f80000 {
+				label = "Boot firmware";
+				reg = <0x03f80000 0x80000>;
+			};
+		};
+
+		nor-alternate@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <1 0x0 0x4000000>;
+			bank-width = <2>;
+
+			partition@0 {
+				label = "Filesystem";
+				reg = <0x00000000 0x3f80000>;
+			};
+			partition@3f80000 {
+				label = "Alternate boot firmware";
+				reg = <0x03f80000 0x80000>;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "xes,address-ctl-nand";
+			reg = <2 0x0 0x10000>;
+			cle-line = <0x8>;	/* CLE tied to A3 */
+			ale-line = <0x10>;	/* ALE tied to A4 */
+
+			partition@0 {
+				label = "NAND Filesystem";
+				reg = <0 0x40000000>;
+			};
+		};
+	};
+
+	/* PMC interface */
+	pci0: pci@ef008000 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+		device_type = "pci";
+		reg = <0xef008000 0x1000>;
+		clock-frequency = <33333333>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+				/* IDSEL */
+				 0xe000 0 0 1 &mpic 2 1
+				 0xe000 0 0 2 &mpic 3 1>;
+
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		bus-range = <0 0>;
+		ranges = <0x02000000 0 0x80000000 0x80000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xd0000000 0 0x01000000>;
+	};
+
+	/* XMC PCIe */
+	pci1: pcie@ef00a000 {
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x00000 0 0 1 &mpic 0 1
+			0x00000 0 0 2 &mpic 1 1
+			0x00000 0 0 3 &mpic 2 1
+			0x00000 0 0 4 &mpic 3 1>;
+
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		bus-range = <0 0xff>;
+		ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xd1000000 0 0x01000000>;
+		clock-frequency = <33333333>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xef00a000 0x1000>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0 0xc0000000 0x02000000 0
+			          0xc0000000 0 0x20000000
+				  0x01000000 0 0x00000000 0x01000000 0
+				  0x00000000 0 0x08000000>;
+		};
+	};
+
+	/* Needed for dtbImage boot wrapper compatibility */
+	chosen {
+		linux,stdout-path = &serial0;
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5301.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5301.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5301.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5301.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2008 Extreme Engineering Solutions, Inc.
+ * Based on MPC8572DS device tree from Freescale Semiconductor, Inc.
+ *
+ * XPedite5301 PMC/XMC module based on MPC8572E
+ *
+ * This 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.
+ */
+
+/dts-v1/;
+/ {
+	model = "xes,xpedite5301";
+	compatible = "xes,xpedite5301", "xes,MPC8572";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	form-factor = "PMC/XMC";
+	boot-bank = <0x0>;	/* 0: Primary flash, 1: Secondary flash */
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci1 = &pci1;
+		pci2 = &pci2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8572@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		PowerPC,8572@1 {
+			device_type = "cpu";
+			reg = <0x1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x0>;	// Filled in by U-Boot
+	};
+
+	localbus@ef005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8572-elbc", "fsl,elbc", "simple-bus";
+		reg = <0 0xef005000 0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+		/* Local bus region mappings */
+		ranges = <0 0 0 0xf8000000 0x8000000 /* CS0: Boot flash */
+			  1 0 0 0xf0000000 0x8000000 /* CS1: Alternate flash */
+			  2 0 0 0xef800000 0x40000   /* CS2: NAND CE1 */
+			  3 0 0 0xef840000 0x40000>; /* CS3: NAND CE2 */
+
+		nor-boot@0,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			reg = <0 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Primary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Primary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Primary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Primary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Primary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nor-alternate@1,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			//reg = <0xf0000000 0x08000000>; /* 128MB */
+			reg = <1 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Secondary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Secondary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Secondary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Secondary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Secondary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/*
+			 * Actual part could be ST Micro NAND08GW3B2A (1 GB),
+			 * Micron MT29F8G08DAA (2x 512 MB), or Micron
+			 * MT29F16G08FAA (2x 1 GB), depending on the build
+			 * configuration
+			 */
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <2 0 0x40000>;
+			/* U-Boot should fix this up if chip size > 1 GB */
+			partition@0 {
+				label = "NAND Filesystem";
+				reg = <0 0x40000000>;
+			};
+		};
+
+	};
+
+	soc8572@ef000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8572-immr", "simple-bus";
+		ranges = <0x0 0 0xef000000 0x100000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		memory-controller@6000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x6000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8572-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x100000>; // L2, 1M
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			temp-sensor@48 {
+				compatible = "dallas,ds1631", "dallas,ds1621";
+				reg = <0x48>;
+			};
+
+			temp-sensor@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+
+			cpu-supervisor@51 {
+				compatible = "dallas,ds4510";
+				reg = <0x51>;
+			};
+
+			eeprom@54 {
+				compatible = "atmel,at24c128b";
+				reg = <0x54>;
+			};
+
+			rtc@68 {
+				compatible = "stm,m41t00",
+				             "dallas,ds1338";
+				reg = <0x68>;
+			};
+
+			pcie-switch@70 {
+				compatible = "plx,pex8518";
+				reg = <0x70>;
+			};
+
+			gpio1: gpio@18 {
+				compatible = "nxp,pca9557";
+				reg = <0x18>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio2: gpio@1c {
+				compatible = "nxp,pca9557";
+				reg = <0x1c>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio3: gpio@1e {
+				compatible = "nxp,pca9557";
+				reg = <0x1e>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio4: gpio@1f {
+				compatible = "nxp,pca9557";
+				reg = <0x1f>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@c300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0xc300 0x4>;
+			ranges = <0x0 0xc100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <76 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <77 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <78 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <79 2>;
+			};
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		/* eTSEC 1 */
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x1>;
+				};
+				phy1: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x2>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC 2 */
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* UART0 */
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		/* UART1 */
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8572-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
+				     "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2 58 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0x9fe>;
+			fsl,descriptor-types-mask = <0x3ab0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		gpio0: gpio@f000 {
+			compatible = "fsl,mpc8572-gpio";
+			reg = <0xf000 0x1000>;
+			interrupts = <47 2>;
+			interrupt-parent = <&mpic>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+
+			heartbeat {
+				label = "Heartbeat";
+				gpios = <&gpio0 4 1>;
+				linux,default-trigger = "heartbeat";
+			};
+
+			yellow {
+				label = "Yellow";
+				gpios = <&gpio0 5 1>;
+			};
+
+			red {
+				label = "Red";
+				gpios = <&gpio0 6 1>;
+			};
+
+			green {
+				label = "Green";
+				gpios = <&gpio0 7 1>;
+			};
+		};
+
+		/* PME (pattern-matcher) */
+		pme@10000 {
+			compatible = "fsl,mpc8572-pme", "pme8572";
+			reg = <0x10000 0x5000>;
+			interrupts = <57 2 64 2 65 2 66 2 67 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@2f000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x2f000 0x1000>;
+			interupts = <61 2 >;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@15000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x15000 0x1000>;
+			interupts = <75 2>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	/*
+	 * PCI Express controller 3 @ ef008000 is not used.
+	 * This would have been pci0 on other mpc85xx platforms.
+	 */
+
+	/* PCI Express controller 2, wired to XMC P15 connector */
+	pci1: pcie@ef009000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef009000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x10000000
+			  0x1000000 0x0 0x00000000 0 0xe8800000 0x0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0 0x0 0x0 0x1 &mpic 0x4 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x5 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x6 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+		pcie@0 {
+			reg = <0x00000000 0x00000000 0x00000000 0x00000000 0x00000000>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x10000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	/* PCI Express controller 1, wired to PEX8112 for PMC interface */
+	pci2: pcie@ef00a000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef00a000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x40000000
+			  0x1000000 0x0 0x00000000 0 0xe8000000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x40000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5330.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5330.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5330.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5330.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,707 @@
+/*
+ * Copyright (C) 2008 Extreme Engineering Solutions, Inc.
+ * Based on MPC8572DS device tree from Freescale Semiconductor, Inc.
+ *
+ * XPedite5330 3U CompactPCI module based on MPC8572E
+ *
+ * This 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.
+ */
+
+/dts-v1/;
+/ {
+	model = "xes,xpedite5330";
+	compatible = "xes,xpedite5330", "xes,MPC8572";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	form-factor = "3U CompactPCI";
+	boot-bank = <0x0>;	/* 0: Primary flash, 1: Secondary flash */
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+	};
+
+	pmcslots {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pmcslot@0 {
+			cell-index = <0>;
+			/*
+			 * boolean properties (true if defined):
+			 *     monarch;
+			 *     module-present;
+			 */
+		};
+	};
+
+	xmcslots {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		xmcslot@0 {
+			cell-index = <0>;
+			/*
+			 * boolean properties (true if defined):
+			 *     module-present;
+			 */
+		};
+	};
+
+	cpci {
+		/*
+		 * boolean properties (true if defined):
+		 *     system-controller;
+		 */
+		system-controller;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8572@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		PowerPC,8572@1 {
+			device_type = "cpu";
+			reg = <0x1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x0>;	// Filled in by U-Boot
+	};
+
+	localbus@ef005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8572-elbc", "fsl,elbc", "simple-bus";
+		reg = <0 0xef005000 0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+		/* Local bus region mappings */
+		ranges = <0 0 0 0xf8000000 0x8000000 /* CS0: Boot flash */
+			  1 0 0 0xf0000000 0x8000000 /* CS1: Alternate flash */
+			  2 0 0 0xef800000 0x40000   /* CS2: NAND CE1 */
+			  3 0 0 0xef840000 0x40000>; /* CS3: NAND CE2 */
+
+		nor-boot@0,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			reg = <0 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Primary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Primary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Primary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Primary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Primary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nor-alternate@1,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			//reg = <0xf0000000 0x08000000>; /* 128MB */
+			reg = <1 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Secondary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Secondary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Secondary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Secondary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Secondary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/*
+			 * Actual part could be ST Micro NAND08GW3B2A (1 GB),
+			 * Micron MT29F8G08DAA (2x 512 MB), or Micron
+			 * MT29F16G08FAA (2x 1 GB), depending on the build
+			 * configuration
+			 */
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <2 0 0x40000>;
+			/* U-Boot should fix this up if chip size > 1 GB */
+			partition@0 {
+				label = "NAND Filesystem";
+				reg = <0 0x40000000>;
+			};
+		};
+
+	};
+
+	soc8572@ef000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8572-immr", "simple-bus";
+		ranges = <0x0 0 0xef000000 0x100000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		memory-controller@6000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x6000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8572-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x100000>; // L2, 1M
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			temp-sensor@48 {
+				compatible = "dallas,ds1631", "dallas,ds1621";
+				reg = <0x48>;
+			};
+
+			temp-sensor@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+
+			cpu-supervisor@51 {
+				compatible = "dallas,ds4510";
+				reg = <0x51>;
+			};
+
+			eeprom@54 {
+				compatible = "atmel,at24c128b";
+				reg = <0x54>;
+			};
+
+			rtc@68 {
+				compatible = "stm,m41t00",
+				             "dallas,ds1338";
+				reg = <0x68>;
+			};
+
+			pcie-switch@70 {
+				compatible = "plx,pex8518";
+				reg = <0x70>;
+			};
+
+			gpio1: gpio@18 {
+				compatible = "nxp,pca9557";
+				reg = <0x18>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio2: gpio@1c {
+				compatible = "nxp,pca9557";
+				reg = <0x1c>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio3: gpio@1e {
+				compatible = "nxp,pca9557";
+				reg = <0x1e>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio4: gpio@1f {
+				compatible = "nxp,pca9557";
+				reg = <0x1f>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@c300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0xc300 0x4>;
+			ranges = <0x0 0xc100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <76 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <77 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <78 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <79 2>;
+			};
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		/* eTSEC 1 */
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x1>;
+				};
+				phy1: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x2>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC 2 */
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* UART0 */
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		/* UART1 */
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8572-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
+				     "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2 58 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0x9fe>;
+			fsl,descriptor-types-mask = <0x3ab0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		gpio0: gpio@f000 {
+			compatible = "fsl,mpc8572-gpio";
+			reg = <0xf000 0x1000>;
+			interrupts = <47 2>;
+			interrupt-parent = <&mpic>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+
+			heartbeat {
+				label = "Heartbeat";
+				gpios = <&gpio0 4 1>;
+				linux,default-trigger = "heartbeat";
+			};
+
+			yellow {
+				label = "Yellow";
+				gpios = <&gpio0 5 1>;
+			};
+
+			red {
+				label = "Red";
+				gpios = <&gpio0 6 1>;
+			};
+
+			green {
+				label = "Green";
+				gpios = <&gpio0 7 1>;
+			};
+		};
+
+		/* PME (pattern-matcher) */
+		pme@10000 {
+			compatible = "fsl,mpc8572-pme", "pme8572";
+			reg = <0x10000 0x5000>;
+			interrupts = <57 2 64 2 65 2 66 2 67 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@2f000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x2f000 0x1000>;
+			interupts = <61 2 >;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@15000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x15000 0x1000>;
+			interupts = <75 2>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	/* PCI Express controller 3 - CompactPCI bus via PEX8112 bridge */
+	pci0: pcie@ef008000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef008000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xe0000000 0 0xe0000000 0x0 0x10000000
+			  0x1000000 0x0 0x00000000 0 0xe9000000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+		interrupt-map = <
+			0x0 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0x0 0xe0000000
+				  0x02000000 0x0 0xe0000000
+				  0x0 0x10000000
+
+				  0x01000000 0x0 0x0
+				  0x01000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	/* PCI Express controller 2, PMC module via PEX8112 bridge */
+	pci1: pcie@ef009000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef009000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x10000000
+			  0x1000000 0x0 0x00000000 0 0xe8800000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0 0x0 0x0 0x1 &mpic 0x4 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x5 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x6 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x10000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	/* PCI Express controller 1, XMC P15 */
+	pci2: pcie@ef00a000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef00a000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x40000000
+			  0x1000000 0x0 0x00000000 0 0xe8000000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x40000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5370.dts linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5370.dts
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/dts/xpedite5370.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/dts/xpedite5370.dts	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2008 Extreme Engineering Solutions, Inc.
+ * Based on MPC8572DS device tree from Freescale Semiconductor, Inc.
+ *
+ * XPedite5370 3U VPX single-board computer based on MPC8572E
+ *
+ * This 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.
+ */
+
+/dts-v1/;
+/ {
+	model = "xes,xpedite5370";
+	compatible = "xes,xpedite5370", "xes,MPC8572";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci1 = &pci1;
+		pci2 = &pci2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8572@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		PowerPC,8572@1 {
+			device_type = "cpu";
+			reg = <0x1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x0>;	// Filled in by U-Boot
+	};
+
+	localbus@ef005000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8572-elbc", "fsl,elbc", "simple-bus";
+		reg = <0 0xef005000 0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+		/* Local bus region mappings */
+		ranges = <0 0 0 0xf8000000 0x8000000 /* CS0: Boot flash */
+			  1 0 0 0xf0000000 0x8000000 /* CS1: Alternate flash */
+			  2 0 0 0xef800000 0x40000   /* CS2: NAND CE1 */
+			  3 0 0 0xef840000 0x40000>; /* CS3: NAND CE2 */
+
+		nor-boot@0,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			reg = <0 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Primary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Primary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Primary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Primary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Primary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nor-alternate@1,0 {
+			compatible = "amd,s29gl01gp", "cfi-flash";
+			bank-width = <2>;
+			//reg = <0xf0000000 0x08000000>; /* 128MB */
+			reg = <1 0 0x8000000>; /* 128MB */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "Secondary user space";
+				reg = <0x00000000 0x6f00000>; /* 111 MB */
+			};
+			partition@6f00000 {
+				label = "Secondary kernel";
+				reg = <0x6f00000 0x1000000>; /* 16 MB */
+			};
+			partition@7f00000 {
+				label = "Secondary DTB";
+				reg = <0x7f00000 0x40000>; /* 256 KB */
+			};
+			partition@7f40000 {
+				label = "Secondary U-Boot environment";
+				reg = <0x7f40000 0x40000>; /* 256 KB */
+			};
+			partition@7f80000 {
+				label = "Secondary U-Boot";
+				reg = <0x7f80000 0x80000>; /* 512 KB */
+				read-only;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			/*
+			 * Actual part could be ST Micro NAND08GW3B2A (1 GB),
+			 * Micron MT29F8G08DAA (2x 512 MB), or Micron
+			 * MT29F16G08FAA (2x 1 GB), depending on the build
+			 * configuration
+			 */
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <2 0 0x40000>;
+			/* U-Boot should fix this up if chip size > 1 GB */
+			partition@0 {
+				label = "NAND Filesystem";
+				reg = <0 0x40000000>;
+			};
+		};
+
+	};
+
+	soc8572@ef000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "fsl,mpc8572-immr", "simple-bus";
+		ranges = <0x0 0 0xef000000 0x100000>;
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <12>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8572-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		memory-controller@6000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x6000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8572-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x100000>; // L2, 1M
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			temp-sensor@48 {
+				compatible = "dallas,ds1631", "dallas,ds1621";
+				reg = <0x48>;
+			};
+
+			temp-sensor@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+
+			cpu-supervisor@51 {
+				compatible = "dallas,ds4510";
+				reg = <0x51>;
+			};
+
+			eeprom@54 {
+				compatible = "atmel,at24c128b";
+				reg = <0x54>;
+			};
+
+			rtc@68 {
+				compatible = "stm,m41t00",
+				             "dallas,ds1338";
+				reg = <0x68>;
+			};
+
+			pcie-switch@70 {
+				compatible = "plx,pex8518";
+				reg = <0x70>;
+			};
+
+			gpio1: gpio@18 {
+				compatible = "nxp,pca9557";
+				reg = <0x18>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio2: gpio@1c {
+				compatible = "nxp,pca9557";
+				reg = <0x1c>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio3: gpio@1e {
+				compatible = "nxp,pca9557";
+				reg = <0x1e>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+
+			gpio4: gpio@1f {
+				compatible = "nxp,pca9557";
+				reg = <0x1f>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				polarity = <0x00>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@c300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0xc300 0x4>;
+			ranges = <0x0 0xc100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <76 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <77 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <78 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <79 2>;
+			};
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		/* eTSEC 1 */
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x1>;
+				};
+				phy1: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <0x2>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* eTSEC 2 */
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "sgmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		/* UART0 */
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		/* UART1 */
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8572-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
+				     "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2 58 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0x9fe>;
+			fsl,descriptor-types-mask = <0x3ab0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		gpio0: gpio@f000 {
+			compatible = "fsl,mpc8572-gpio";
+			reg = <0xf000 0x1000>;
+			interrupts = <47 2>;
+			interrupt-parent = <&mpic>;
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+
+			heartbeat {
+				label = "Heartbeat";
+				gpios = <&gpio0 4 1>;
+				linux,default-trigger = "heartbeat";
+			};
+
+			yellow {
+				label = "Yellow";
+				gpios = <&gpio0 5 1>;
+			};
+
+			red {
+				label = "Red";
+				gpios = <&gpio0 6 1>;
+			};
+
+			green {
+				label = "Green";
+				gpios = <&gpio0 7 1>;
+			};
+		};
+
+		/* PME (pattern-matcher) */
+		pme@10000 {
+			compatible = "fsl,mpc8572-pme", "pme8572";
+			reg = <0x10000 0x5000>;
+			interrupts = <57 2 64 2 65 2 66 2 67 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@2f000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x2f000 0x1000>;
+			interupts = <61 2 >;
+			interrupt-parent = <&mpic>;
+		};
+
+		tlu@15000 {
+			compatible = "fsl,mpc8572-tlu", "fsl_tlu";
+			reg = <0x15000 0x1000>;
+			interupts = <75 2>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	/*
+	 * PCI Express controller 3 @ ef008000 is not used.
+	 * This would have been pci0 on other mpc85xx platforms.
+	 */
+
+	/* PCI Express controller 2, wired to VPX P1,P2 backplane */
+	pci1: pcie@ef009000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef009000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x10000000
+			  0x1000000 0x0 0x00000000 0 0xe8800000 0x0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0 0x0 0x0 0x1 &mpic 0x4 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x5 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x6 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+		pcie@0 {
+			reg = <0x00000000 0x00000000 0x00000000 0x00000000 0x00000000>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x10000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	/* PCI Express controller 1, wired to PEX8518 PCIe switch */
+	pci2: pcie@ef00a000 {
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0 0xef00a000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x40000000
+			  0x1000000 0x0 0x00000000 0 0xe8000000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0x0 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x0 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x0 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x0 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x40000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/.gitignore linux-libre-2.6.31-gnu/arch/powerpc/boot/.gitignore
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/.gitignore	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/.gitignore	2009-09-09 18:13:59.000000000 -0400
@@ -36,3 +36,13 @@
 zconf.h
 zlib.h
 zutil.h
+fdt.c
+fdt.h
+fdt_ro.c
+fdt_rw.c
+fdt_strerror.c
+fdt_sw.c
+fdt_wip.c
+libfdt.h
+libfdt_internal.h
+
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/install.sh linux-libre-2.6.31-gnu/arch/powerpc/boot/install.sh
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/install.sh	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/install.sh	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,9 @@
 #   $5 and more - kernel boot files; zImage*, uImage, cuImage.*, etc.
 #
 
+# Bail with error code if anything goes wrong
+set -e
+
 # User may have a custom install script
 
 if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/boot/wrapper linux-libre-2.6.31-gnu/arch/powerpc/boot/wrapper
--- linux-libre-2.6.30-gnu/arch/powerpc/boot/wrapper	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/boot/wrapper	2009-09-09 18:13:59.000000000 -0400
@@ -225,6 +225,10 @@
     platformo="$object/fixed-head.o $object/redboot-83xx.o"
     binary=y
     ;;
+xpedite52*)
+    link_address='0x1400000'
+    platformo=$object/cuboot-85xx.o
+    ;;
 esac
 
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/acadia_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/acadia_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/acadia_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/acadia_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -252,7 +252,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/ep405_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/ep405_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/ep405_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/ep405_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -254,7 +254,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/kilauea_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/kilauea_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/kilauea_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/kilauea_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Tue Jan 20 08:17:52 2009
+# Linux kernel version: 2.6.30-rc7
+# Wed Jun  3 10:18:16 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -27,6 +27,7 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
@@ -49,10 +50,12 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_PPC_DCR_NATIVE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_DCR=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -67,9 +70,19 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -84,22 +97,24 @@
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_STRIP_GENERATED=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -109,10 +124,12 @@
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -120,6 +137,7 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -132,7 +150,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -148,11 +165,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 CONFIG_PPC4xx_PCI_EXPRESS=y
 
@@ -170,7 +182,7 @@
 # CONFIG_MAKALU is not set
 # CONFIG_WALNUT is not set
 # CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
-# CONFIG_PPC40x_SIMPLE is not set
+CONFIG_PPC40x_SIMPLE=y
 CONFIG_405EX=y
 # CONFIG_IPIC is not set
 # CONFIG_MPIC is not set
@@ -228,9 +240,12 @@
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
@@ -252,9 +267,10 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
 # CONFIG_HAS_RAPIDIO is not set
@@ -272,14 +288,12 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
-CONFIG_CONSISTENT_START=0xff100000
 CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -329,6 +343,7 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -341,7 +356,6 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
@@ -445,7 +459,6 @@
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
@@ -498,6 +511,7 @@
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -512,6 +526,8 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 CONFIG_IBM_NEW_EMAC=y
@@ -540,7 +556,6 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -678,6 +693,7 @@
 # CONFIG_EDAC is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -706,6 +722,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -749,6 +770,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -760,7 +782,6 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -776,6 +797,7 @@
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_NLS is not set
 # CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -790,11 +812,12 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
 
 #
 # Kernel hacking
@@ -812,6 +835,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -841,9 +867,12 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -851,17 +880,21 @@
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -892,10 +925,12 @@
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
 CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_AUTHENC is not set
 # CONFIG_CRYPTO_TEST is not set
@@ -964,6 +999,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -972,5 +1008,6 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_PPC4XX is not set
 # CONFIG_PPC_CLOCK is not set
 # CONFIG_VIRTUALIZATION is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/makalu_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/makalu_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/makalu_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/makalu_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Tue Jan 20 08:17:53 2009
+# Linux kernel version: 2.6.30-rc7
+# Wed Jun  3 09:11:02 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -27,6 +27,7 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
@@ -49,10 +50,12 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_PPC_DCR_NATIVE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_DCR=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -67,9 +70,19 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -84,22 +97,24 @@
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_STRIP_GENERATED=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -109,10 +124,12 @@
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -120,6 +137,7 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -132,7 +150,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -148,11 +165,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 CONFIG_PPC4xx_PCI_EXPRESS=y
 
@@ -170,7 +182,7 @@
 CONFIG_MAKALU=y
 # CONFIG_WALNUT is not set
 # CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
-# CONFIG_PPC40x_SIMPLE is not set
+CONFIG_PPC40x_SIMPLE=y
 CONFIG_405EX=y
 # CONFIG_IPIC is not set
 # CONFIG_MPIC is not set
@@ -228,9 +240,12 @@
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
@@ -252,9 +267,10 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
 # CONFIG_HAS_RAPIDIO is not set
@@ -272,14 +288,12 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
-CONFIG_CONSISTENT_START=0xff100000
 CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -329,6 +343,7 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -341,7 +356,6 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
@@ -445,7 +459,6 @@
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
@@ -498,6 +511,7 @@
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -512,6 +526,8 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 CONFIG_IBM_NEW_EMAC=y
@@ -540,7 +556,6 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -678,6 +693,7 @@
 # CONFIG_EDAC is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -706,6 +722,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -749,6 +770,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -760,7 +782,6 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -776,6 +797,7 @@
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_NLS is not set
 # CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -790,11 +812,12 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
 
 #
 # Kernel hacking
@@ -812,6 +835,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -841,9 +867,12 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -851,17 +880,21 @@
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -892,10 +925,12 @@
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
 CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_AUTHENC is not set
 # CONFIG_CRYPTO_TEST is not set
@@ -964,6 +999,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -972,5 +1008,6 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_PPC4XX is not set
 # CONFIG_PPC_CLOCK is not set
 # CONFIG_VIRTUALIZATION is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/virtex_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/virtex_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/40x/virtex_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/40x/virtex_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -258,7 +258,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/arches_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/arches_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/arches_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/arches_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -258,7 +258,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/bamboo_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/bamboo_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/bamboo_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/bamboo_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -262,7 +262,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/canyonlands_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/canyonlands_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/canyonlands_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/canyonlands_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -262,7 +262,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
@@ -716,7 +716,7 @@
 #
 # Multimedia drivers
 #
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 # CONFIG_USB_DABUSB is not set
 
 #
@@ -725,7 +725,7 @@
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 # CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/ebony_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/ebony_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/ebony_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/ebony_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -261,7 +261,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/katmai_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/katmai_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/katmai_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/katmai_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -256,7 +256,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/rainier_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/rainier_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/rainier_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/rainier_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -260,7 +260,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/redwood_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/redwood_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/redwood_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/redwood_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -265,7 +265,7 @@
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/sam440ep_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/sam440ep_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/sam440ep_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/sam440ep_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -262,7 +262,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/sequoia_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/sequoia_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/sequoia_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/sequoia_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Tue Jan 20 08:22:45 2009
+# Linux kernel version: 2.6.29
+# Tue Apr  7 17:04:52 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -57,6 +57,7 @@
 CONFIG_PPC_DCR_NATIVE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_DCR=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -74,6 +75,15 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
@@ -88,8 +98,12 @@
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
@@ -99,10 +113,8 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -112,10 +124,12 @@
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -123,6 +137,7 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -135,7 +150,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -151,11 +165,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 # CONFIG_PPC4xx_PCI_EXPRESS is not set
 
@@ -176,6 +185,7 @@
 # CONFIG_ARCHES is not set
 # CONFIG_CANYONLANDS is not set
 # CONFIG_GLACIER is not set
+# CONFIG_REDWOOD is not set
 # CONFIG_YOSEMITE is not set
 # CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set
 CONFIG_PPC44x_SIMPLE=y
@@ -238,9 +248,13 @@
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_STDBINUTILS=y
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_PROC_DEVICETREE=y
 CONFIG_CMDLINE_BOOL=y
@@ -262,9 +276,10 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
 # CONFIG_HAS_RAPIDIO is not set
@@ -278,18 +293,16 @@
 # Default settings for advanced configuration options are used
 #
 CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_LOWMEM_CAM_NUM=3
 CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
-CONFIG_CONSISTENT_START=0xff100000
-CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -339,6 +352,7 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -351,7 +365,6 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
@@ -448,14 +461,23 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_NDFC=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_FSL_ELBC is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
@@ -483,12 +505,16 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_HP_ILO is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -515,6 +541,7 @@
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -529,6 +556,8 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 CONFIG_IBM_NEW_EMAC=y
@@ -568,6 +597,7 @@
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
 # CONFIG_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
@@ -577,6 +607,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -586,6 +617,7 @@
 # CONFIG_BNX2X is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
 # CONFIG_TR is not set
 
 #
@@ -593,7 +625,6 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -734,7 +765,7 @@
 #
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 # CONFIG_USB_GADGET is not set
 
@@ -750,6 +781,7 @@
 # CONFIG_EDAC is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -778,6 +810,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -842,7 +879,6 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -858,6 +894,7 @@
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_NLS is not set
 # CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -873,11 +910,12 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
 
 #
 # Kernel hacking
@@ -924,9 +962,12 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -934,17 +975,20 @@
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -952,20 +996,7 @@
 # CONFIG_IRQSTACKS is not set
 # CONFIG_VIRQ_DEBUG is not set
 # CONFIG_BDI_SWITCH is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# 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 is not set
-CONFIG_PPC_EARLY_DEBUG_44x=y
-# CONFIG_PPC_EARLY_DEBUG_40x is not set
-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
-CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
-CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
@@ -988,10 +1019,12 @@
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
 CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_AUTHENC is not set
 # CONFIG_CRYPTO_TEST is not set
@@ -1060,6 +1093,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -1068,5 +1102,6 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_PPC4XX is not set
 # CONFIG_PPC_CLOCK is not set
 # CONFIG_VIRTUALIZATION is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/taishan_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/taishan_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/taishan_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/taishan_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -260,7 +260,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/virtex5_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/virtex5_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/virtex5_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/virtex5_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -263,7 +263,7 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/warp_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/warp_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/44x/warp_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/44x/warp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Fri Jan 23 07:57:16 2009
+# Linux kernel version: 2.6.30
+# Tue Jun  9 23:35:36 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -41,6 +41,7 @@
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -53,10 +54,12 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_PPC_DCR_NATIVE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_DCR=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -74,7 +77,17 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
@@ -82,27 +95,29 @@
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -110,10 +125,13 @@
 CONFIG_SHMEM=y
 CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -121,6 +139,7 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -133,7 +152,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -149,11 +167,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -173,10 +186,11 @@
 # CONFIG_ARCHES is not set
 # CONFIG_CANYONLANDS is not set
 # CONFIG_GLACIER is not set
+# CONFIG_REDWOOD is not set
 # CONFIG_YOSEMITE is not set
 # CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set
 # CONFIG_PPC44x_SIMPLE is not set
-# CONFIG_PPC4xx_GPIO is not set
+CONFIG_PPC4xx_GPIO=y
 CONFIG_440EP=y
 CONFIG_IBM440EP_ERR42=y
 # CONFIG_IPIC is not set
@@ -235,9 +249,13 @@
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_STDBINUTILS=y
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_PROC_DEVICETREE=y
 CONFIG_CMDLINE_BOOL=y
@@ -256,6 +274,7 @@
 # CONFIG_PCI_DOMAINS is not set
 # CONFIG_PCI_SYSCALL is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
 # CONFIG_HAS_RAPIDIO is not set
 
 #
@@ -271,14 +290,12 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
-CONFIG_CONSISTENT_START=0xff100000
 CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -353,6 +370,7 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -365,7 +383,6 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
@@ -378,8 +395,12 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_STANDALONE is not set
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -471,13 +492,21 @@
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
 #
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
@@ -495,10 +524,17 @@
 # CONFIG_XILINX_SYSACE is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -529,7 +565,7 @@
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
-CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_SCSI_WAIT_SCAN is not set
 
 #
 # SCSI Transports
@@ -541,10 +577,12 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 # CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -554,6 +592,8 @@
 # CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 CONFIG_IBM_NEW_EMAC=y
 CONFIG_IBM_NEW_EMAC_RXB=128
 CONFIG_IBM_NEW_EMAC_TXB=64
@@ -577,7 +617,6 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -646,6 +685,7 @@
 # CONFIG_HVC_UDBG is not set
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
@@ -663,6 +703,7 @@
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_GPIO is not set
 CONFIG_I2C_IBM_IIC=y
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_OCORES is not set
@@ -685,12 +726,9 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-CONFIG_EEPROM_AT24=y
-CONFIG_EEPROM_LEGACY=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -699,7 +737,30 @@
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
@@ -721,6 +782,7 @@
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -735,11 +797,15 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
 # CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
@@ -785,6 +851,7 @@
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
@@ -870,11 +937,11 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -915,7 +982,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -929,6 +995,8 @@
 #
 # OTG and related infrastructure
 #
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
@@ -946,6 +1014,7 @@
 #
 # CONFIG_MMC_SDHCI is not set
 # CONFIG_MMC_WBSD is not set
+CONFIG_MMC_PIKASD=y
 # CONFIG_MEMSTICK is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -953,16 +1022,31 @@
 #
 # LED drivers
 #
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_GPIO_PLATFORM is not set
+CONFIG_LEDS_GPIO_OF=y
+# CONFIG_LEDS_LP5521 is not set
 # CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
 
 #
 # LED Triggers
 #
-# CONFIG_LEDS_TRIGGERS is not set
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_EDAC is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -973,6 +1057,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 # CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
@@ -993,6 +1078,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1039,6 +1129,12 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
 CONFIG_CRAMFS=y
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1049,6 +1145,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1060,7 +1157,6 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1115,6 +1211,7 @@
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=y
 # CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1122,7 +1219,7 @@
 CONFIG_BITREVERSE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=y
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 CONFIG_CRC_T10DIF=y
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
@@ -1130,16 +1227,19 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
 
 #
 # Kernel hacking
 #
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
@@ -1152,11 +1252,15 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1180,9 +1284,12 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -1190,24 +1297,27 @@
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
 # CONFIG_XMON is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_VIRQ_DEBUG is not set
-CONFIG_BDI_SWITCH=y
+# CONFIG_BDI_SWITCH is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1223,6 +1333,8 @@
 # Crypto core or helper
 #
 # CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
 # CONFIG_CRYPTO_MANAGER is not set
 # CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
@@ -1294,13 +1406,15 @@
 #
 # Compression
 #
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
 
 #
 # Random Number Generation
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_PPC4XX is not set
 # CONFIG_PPC_CLOCK is not set
 # CONFIG_VIRTUALIZATION is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/asp8347_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/asp8347_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/asp8347_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/asp8347_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:05 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:02 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_FSL_EMB_PERFMON=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,6 +56,7 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_REDBOOT=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
@@ -60,6 +64,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,9 +125,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -136,6 +147,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 CONFIG_ASP834x=y
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -235,6 +251,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -490,6 +512,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -525,7 +548,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -545,14 +570,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -599,6 +627,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -618,8 +647,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -786,13 +817,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -847,6 +882,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -900,24 +936,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -960,6 +981,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1069,6 +1091,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1096,6 +1119,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1115,10 +1142,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1192,6 +1221,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1287,6 +1317,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1312,22 +1343,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,966 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:03 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_PPC_BOOK3S_32=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_FSL_EMB_PERFMON is not set
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
+CONFIG_DEFAULT_UIMAGE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# 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_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_FREEZER is not set
+
+#
+# Platform support
+#
+# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_PPC_83xx=y
+# CONFIG_MPC831x_RDB is not set
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
+# CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC836x_MDS is not set
+# CONFIG_MPC836x_RDK is not set
+# CONFIG_MPC837x_MDS is not set
+# CONFIG_MPC837x_RDB is not set
+# CONFIG_SBC834x is not set
+# CONFIG_ASP834x is not set
+CONFIG_KMETER1=y
+# CONFIG_PPC_86xx is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
+CONFIG_IPIC=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_QE_GPIO is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_FSL_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# 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 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
+# 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_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_PHRAM=y
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+CONFIG_MTD_UBI_DEBUG=y
+# CONFIG_MTD_UBI_DEBUG_MSG is not set
+# CONFIG_MTD_UBI_DEBUG_PARANOID is not set
+# CONFIG_MTD_UBI_DEBUG_DISABLE_BGT is not set
+# CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS is not set
+# CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES is not set
+# CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES is not set
+
+#
+# Additional UBI debugging messages
+#
+# CONFIG_MTD_UBI_DEBUG_MSG_BLD is not set
+# CONFIG_MTD_UBI_DEBUG_MSG_EBA is not set
+# CONFIG_MTD_UBI_DEBUG_MSG_WL is not set
+# CONFIG_MTD_UBI_DEBUG_MSG_IO is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD 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_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_FSL_PQ_MDIO=y
+# CONFIG_GIANFAR is not set
+CONFIG_UCC_GETH=y
+# CONFIG_UGETH_MAGIC_PACKET is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+CONFIG_WAN=y
+CONFIG_HDLC=y
+# CONFIG_HDLC_RAW is not set
+# CONFIG_HDLC_RAW_ETH is not set
+# CONFIG_HDLC_CISCO is not set
+# CONFIG_HDLC_FR is not set
+# CONFIG_HDLC_PPP is not set
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_DLCI is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=y
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=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_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
+# CONFIG_SERIAL_QE is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# 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 is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_UBIFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+CONFIG_UCC_FAST=y
+CONFIG_UCC=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_PPC_EMULATED_STATS is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_PPC_CLOCK is not set
+CONFIG_PPC_LIB_RHEAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:06 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:04 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC831x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -503,6 +525,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -539,7 +562,9 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -562,10 +587,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -583,6 +604,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -591,6 +613,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -610,7 +633,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -643,14 +665,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -714,6 +739,8 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -735,8 +762,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -924,7 +953,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -938,13 +966,18 @@
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1002,6 +1035,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1056,24 +1090,10 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1135,6 +1155,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1144,9 +1165,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1235,8 +1256,9 @@
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_M66592 is not set
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
@@ -1244,9 +1266,11 @@
 CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_NET2280=y
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 CONFIG_USB_ETH=y
 CONFIG_USB_ETH_RNDIS=y
 # CONFIG_USB_GADGETFS is not set
@@ -1298,6 +1322,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1332,6 +1357,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1351,10 +1380,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1428,6 +1459,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1464,7 +1496,46 @@
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1488,6 +1559,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1518,6 +1590,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1529,7 +1604,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1543,16 +1617,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1560,6 +1633,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:06 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:05 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC831x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -503,6 +525,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -539,7 +562,9 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -562,10 +587,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -583,6 +604,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -591,6 +613,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -610,7 +633,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -704,14 +726,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -775,6 +800,8 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -796,8 +823,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -985,7 +1014,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -999,13 +1027,18 @@
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1063,6 +1096,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1117,24 +1151,10 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1196,6 +1216,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1205,9 +1226,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1296,8 +1317,9 @@
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_M66592 is not set
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
@@ -1305,9 +1327,11 @@
 CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_NET2280=y
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 CONFIG_USB_ETH=y
 CONFIG_USB_ETH_RNDIS=y
 # CONFIG_USB_GADGETFS is not set
@@ -1359,6 +1383,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1393,6 +1418,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1412,10 +1441,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1489,6 +1520,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1525,7 +1557,46 @@
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1549,6 +1620,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1579,6 +1651,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1590,7 +1665,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1604,16 +1678,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1621,6 +1694,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc832x_mds_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc832x_mds_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc832x_mds_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:07 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:06 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC832x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -235,6 +251,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -404,6 +426,7 @@
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -438,7 +461,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -461,10 +486,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -482,6 +503,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -490,6 +512,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -509,7 +532,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -532,14 +554,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -586,6 +611,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -605,11 +631,13 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -787,13 +815,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -848,6 +880,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -896,23 +929,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -996,6 +1015,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1023,6 +1043,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1042,10 +1066,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1108,6 +1134,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1165,6 +1192,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1190,22 +1218,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:08 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:07 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC832x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -235,6 +251,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -405,6 +427,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -441,7 +464,9 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -464,10 +489,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -485,6 +506,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -493,6 +515,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -512,7 +535,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -535,14 +557,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -590,6 +615,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -609,11 +636,13 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -804,7 +833,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -817,13 +845,18 @@
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -881,6 +914,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -935,24 +969,10 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1014,6 +1034,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1023,9 +1044,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1127,6 +1148,8 @@
 # CONFIG_MMC_WBSD is not set
 # CONFIG_MMC_TIFM_SD is not set
 CONFIG_MMC_SPI=y
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_VIA_SDMMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
@@ -1136,6 +1159,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1155,10 +1182,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1224,6 +1253,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1325,6 +1355,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1350,22 +1381,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc834x_itx_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc834x_itx_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc834x_itx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:09 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:07 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -487,6 +509,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -523,7 +546,9 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -594,10 +619,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -615,6 +636,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -623,6 +645,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -642,7 +665,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -737,14 +759,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -791,8 +816,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -960,7 +987,6 @@
 CONFIG_SENSORS_PCF8574=y
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -973,13 +999,18 @@
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1026,24 +1057,10 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1085,6 +1102,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1208,6 +1226,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1242,6 +1261,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1261,10 +1284,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1331,6 +1356,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1429,6 +1455,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1454,22 +1481,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:10 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:08 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -487,6 +509,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -523,7 +546,9 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -546,10 +571,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -567,6 +588,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -575,6 +597,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -594,7 +617,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -617,14 +639,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -671,8 +696,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -840,7 +867,6 @@
 CONFIG_SENSORS_PCF8574=y
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -853,13 +879,18 @@
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -906,24 +937,10 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -965,6 +982,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1087,6 +1105,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1121,6 +1140,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1140,10 +1163,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1210,6 +1235,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1308,6 +1334,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1333,22 +1360,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc834x_mds_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc834x_mds_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc834x_mds_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:11 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:09 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -403,6 +425,7 @@
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -437,7 +460,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -457,14 +482,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -527,6 +555,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -548,8 +577,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -724,13 +755,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -785,6 +820,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -833,23 +869,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -933,6 +955,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -960,6 +983,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -979,10 +1006,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1045,6 +1074,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1100,6 +1130,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1125,22 +1156,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc836x_mds_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc836x_mds_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc836x_mds_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:12 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:10 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_AMIGAONE is not set
@@ -233,6 +249,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -253,9 +270,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -364,6 +381,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -381,7 +399,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -485,6 +507,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -519,7 +542,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -542,10 +567,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -563,6 +584,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -571,6 +593,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -590,7 +613,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -613,14 +635,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -667,6 +692,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -686,11 +712,13 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -868,13 +896,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -929,6 +961,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -977,23 +1010,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1077,6 +1096,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1104,6 +1124,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1123,10 +1147,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1190,6 +1216,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1247,6 +1274,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1272,22 +1300,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:13 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:12 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -54,12 +57,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,9 +125,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -136,6 +147,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_AMIGAONE is not set
@@ -233,6 +249,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -253,9 +270,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -498,6 +520,7 @@
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -533,7 +556,9 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -553,14 +578,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -607,11 +635,13 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -777,7 +807,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -791,13 +820,18 @@
 #
 CONFIG_SPI_BITBANG=y
 # CONFIG_SPI_GPIO is not set
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 CONFIG_SPI_SPIDEV=y
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -865,23 +899,10 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -990,6 +1011,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1009,10 +1034,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1086,6 +1113,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1145,6 +1173,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1170,22 +1199,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc837x_mds_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc837x_mds_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc837x_mds_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:12 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:11 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,8 +125,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -136,6 +147,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC837x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -403,6 +425,7 @@
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -437,7 +460,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -460,10 +485,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -481,6 +502,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -489,6 +511,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -508,7 +531,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -592,14 +614,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -646,6 +671,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -665,8 +691,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -844,13 +872,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -905,6 +937,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -953,23 +986,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1026,6 +1045,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1045,10 +1068,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1111,6 +1136,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1170,6 +1196,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1193,22 +1220,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:14 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:13 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,8 +125,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -136,6 +147,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@
 CONFIG_MPC837x_RDB=y
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC837x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -360,6 +377,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -377,7 +395,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -398,6 +420,7 @@
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -433,7 +456,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -456,10 +481,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -476,6 +497,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -484,6 +506,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -503,7 +526,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -598,14 +620,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -652,6 +677,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -671,8 +697,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -842,13 +870,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -903,6 +935,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -956,24 +989,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1011,7 +1029,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1028,10 +1046,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1057,6 +1076,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1141,6 +1161,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1160,10 +1184,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1226,6 +1252,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1262,7 +1289,46 @@
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1285,6 +1351,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1308,22 +1375,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/sbc834x_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/sbc834x_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/83xx/sbc834x_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/83xx/sbc834x_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:15 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:13 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,8 +124,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -134,6 +145,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +161,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -188,6 +203,7 @@
 # CONFIG_MPC837x_RDB is not set
 CONFIG_SBC834x=y
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -232,6 +248,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +269,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -363,6 +380,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -380,7 +398,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -401,6 +423,7 @@
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -435,7 +458,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -455,14 +480,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -509,6 +537,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -528,8 +557,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -688,13 +719,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -749,6 +784,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -797,23 +833,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -851,6 +873,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -862,10 +888,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -928,6 +956,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -971,6 +1000,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -994,22 +1024,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/ksi8560_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/ksi8560_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/ksi8560_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/ksi8560_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:16 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:14 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +111,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,8 +123,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -136,6 +145,11 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -143,7 +157,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -176,6 +190,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 CONFIG_KSI8560=y
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -224,6 +239,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +258,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -346,6 +362,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -363,7 +380,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -466,6 +487,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -520,7 +542,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -560,6 +581,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FCC=y
@@ -567,6 +589,7 @@
 CONFIG_NETDEV_1000=y
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -654,6 +677,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -710,22 +738,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -777,6 +790,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -797,10 +814,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -916,6 +935,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -946,6 +966,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -958,7 +981,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -972,16 +994,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -990,9 +1011,13 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/mpc8540_ads_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/mpc8540_ads_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/mpc8540_ads_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:17 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:15 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,8 +126,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -138,6 +147,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -145,7 +158,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -178,6 +191,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -226,6 +240,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -244,9 +259,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -348,6 +363,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -365,7 +381,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -387,6 +407,7 @@
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -423,7 +444,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -462,9 +482,11 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -555,6 +577,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -590,22 +617,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -657,6 +669,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -676,10 +692,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -794,6 +812,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -824,6 +843,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -835,7 +857,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -849,16 +870,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -866,6 +886,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/mpc8560_ads_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/mpc8560_ads_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/mpc8560_ads_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:17 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:16 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -112,7 +115,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -125,9 +127,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -141,6 +150,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +161,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -181,6 +194,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -229,6 +243,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -247,9 +262,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -360,6 +375,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -377,7 +393,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -400,6 +420,7 @@
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -431,6 +452,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -450,14 +472,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -504,6 +529,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -527,8 +553,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -646,6 +674,11 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -707,22 +740,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -779,6 +797,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -798,10 +820,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -916,6 +940,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -946,6 +971,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -957,7 +985,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -971,16 +998,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -988,6 +1014,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:18 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:17 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,9 +126,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -227,6 +241,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -245,9 +260,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -358,6 +373,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -375,7 +391,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -397,6 +417,7 @@
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -428,6 +449,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -502,14 +524,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -556,6 +581,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -575,8 +601,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -698,6 +726,11 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -737,22 +770,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -809,6 +827,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -828,10 +850,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -946,6 +970,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -976,6 +1001,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -987,7 +1015,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1001,16 +1028,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1018,6 +1044,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/sbc8548_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/sbc8548_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/sbc8548_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/sbc8548_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:19 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:18 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,8 +125,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -137,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -144,7 +157,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -177,6 +190,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -224,6 +238,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +257,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -354,6 +369,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -371,7 +387,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -391,6 +411,7 @@
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -422,6 +443,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -441,14 +463,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -495,6 +520,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -514,8 +540,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -637,6 +665,11 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -676,22 +709,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -721,6 +739,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -732,10 +754,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -838,6 +862,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -861,22 +886,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/sbc8560_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/sbc8560_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/sbc8560_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/sbc8560_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:20 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:19 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,7 +126,14 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -137,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -144,7 +157,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -177,6 +190,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -224,6 +238,7 @@
 CONFIG_BINFMT_MISC=y
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +257,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -346,6 +361,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -363,7 +379,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -385,6 +405,7 @@
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -421,7 +442,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -460,9 +480,11 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -551,6 +573,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -586,22 +613,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -690,6 +702,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -701,10 +717,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -819,6 +837,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -848,6 +867,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -859,7 +881,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -873,16 +894,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -890,6 +910,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/socrates_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/socrates_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/socrates_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/socrates_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:21 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:19 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -109,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -137,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -149,7 +162,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -182,6 +195,7 @@
 # CONFIG_MPC85xx_DS is not set
 CONFIG_SOCRATES=y
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -229,6 +243,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -247,9 +262,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -357,6 +372,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,6 +389,7 @@
 # CAN Device Drivers
 #
 # CONFIG_CAN_VCAN is not set
+# CONFIG_CAN_DEV is not set
 # CONFIG_CAN_DEBUG_DEVICES is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -382,7 +399,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -499,6 +520,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -535,7 +557,9 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -558,10 +582,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -588,14 +608,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -643,6 +666,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -662,8 +687,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -733,6 +760,7 @@
 # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
 # CONFIG_TOUCHSCREEN_AD7879_SPI is not set
 # CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -746,6 +774,7 @@
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
 # CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -862,7 +891,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -875,12 +903,18 @@
 # SPI Master Controller Drivers
 #
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -938,6 +972,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -973,24 +1008,10 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1110,7 +1131,7 @@
 # CONFIG_HID_CHERRY is not set
 # CONFIG_HID_CHICONY is not set
 # CONFIG_HID_CYPRESS is not set
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 # CONFIG_HID_EZKEY is not set
 # CONFIG_HID_KYE is not set
 # CONFIG_HID_GYRATION is not set
@@ -1124,10 +1145,11 @@
 # CONFIG_HID_SAMSUNG is not set
 # CONFIG_HID_SONY is not set
 # CONFIG_HID_SUNPLUS is not set
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1153,6 +1175,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1162,9 +1185,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1284,6 +1307,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1318,6 +1342,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1337,10 +1365,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1449,7 +1479,46 @@
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1473,6 +1542,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1498,22 +1568,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/stx_gp3_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/stx_gp3_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/stx_gp3_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/stx_gp3_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:22 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:20 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -112,7 +115,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -125,9 +127,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -142,6 +151,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -153,7 +166,7 @@
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -186,6 +199,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 CONFIG_STX_GP3=y
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -234,6 +248,7 @@
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +267,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -425,6 +440,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -442,7 +458,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -466,6 +486,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=m
+CONFIG_OF_MDIO=y
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
 # CONFIG_PARPORT_PC_FIFO is not set
@@ -507,7 +528,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -581,10 +604,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -602,6 +621,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -610,6 +630,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -631,7 +652,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -654,14 +674,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -708,6 +731,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_ATL2 is not set
 # CONFIG_FS_ENET is not set
@@ -729,8 +753,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -802,12 +828,13 @@
 #
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -821,6 +848,7 @@
 # CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
@@ -911,6 +939,7 @@
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_OCORES is not set
@@ -941,13 +970,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -1027,6 +1060,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1060,23 +1094,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1143,6 +1163,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1162,10 +1186,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1316,6 +1342,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1346,6 +1373,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1358,7 +1388,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1372,16 +1401,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1389,6 +1417,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8540_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8540_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8540_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8540_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:23 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:21 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -109,7 +112,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,9 +124,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -137,6 +146,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -144,7 +157,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -177,6 +190,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 CONFIG_TQM8540=y
 # CONFIG_TQM8541 is not set
@@ -225,6 +239,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -243,9 +258,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -353,6 +368,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -370,7 +386,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -471,6 +491,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -505,7 +526,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -580,14 +603,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -650,6 +676,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -671,8 +698,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -850,13 +879,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -911,6 +944,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -945,23 +979,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1018,6 +1038,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1037,10 +1061,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1167,6 +1193,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1192,22 +1219,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8541_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8541_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8541_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8541_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:23 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:22 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,9 +125,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 CONFIG_TQM8541=y
@@ -228,6 +242,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -246,9 +261,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -356,6 +371,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,7 +389,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -475,6 +495,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -509,7 +530,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -584,14 +607,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -654,6 +680,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -676,8 +703,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -831,6 +860,7 @@
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -859,13 +889,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -944,6 +978,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -979,23 +1014,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1073,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1071,10 +1096,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1201,6 +1228,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1226,22 +1254,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8548_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8548_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8548_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8548_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:24 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:23 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,9 +126,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -140,6 +149,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -152,7 +165,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -185,6 +198,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -234,6 +248,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +267,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -281,6 +296,8 @@
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -368,6 +385,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -497,6 +515,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -531,7 +550,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -551,14 +572,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -605,6 +629,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -624,8 +649,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -801,13 +828,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -862,6 +893,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -896,23 +928,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -977,6 +995,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1004,6 +1023,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1015,10 +1038,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1145,6 +1170,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1175,6 +1201,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1187,7 +1216,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1201,16 +1229,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1218,6 +1245,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8555_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8555_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8555_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8555_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:25 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:24 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,9 +125,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -228,6 +242,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -246,9 +261,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -356,6 +371,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,7 +389,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -475,6 +495,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -509,7 +530,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -584,14 +607,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -654,6 +680,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -676,8 +703,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -831,6 +860,7 @@
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -859,13 +889,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -944,6 +978,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -979,23 +1014,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1073,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1071,10 +1096,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1201,6 +1228,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1226,22 +1254,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8560_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8560_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/tqm8560_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/tqm8560_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:26 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:25 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,9 +125,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -228,6 +242,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -246,9 +261,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -356,6 +371,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,7 +389,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -475,6 +495,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -509,7 +530,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -584,14 +607,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -654,6 +680,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -676,8 +703,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -831,6 +860,7 @@
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -859,13 +889,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -944,6 +978,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -979,23 +1014,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1073,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1071,10 +1096,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1201,6 +1228,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1226,22 +1254,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1845 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:25 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_PPC_BOOK3S_32 is not set
+CONFIG_PPC_85xx=y
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_E500=y
+# CONFIG_PPC_E500MC is not set
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+CONFIG_FSL_EMB_PERFMON=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
+CONFIG_PPC_BOOK3E_MMU=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+CONFIG_PPC_MSI_BITMAP=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_MPC85xx=y
+# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_MPC85xx_CDS is not set
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC8536_DS is not set
+# CONFIG_MPC85xx_DS is not set
+# CONFIG_SOCRATES is not set
+# CONFIG_KSI8560 is not set
+CONFIG_XES_MPC85xx=y
+# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
+# CONFIG_TQM8541 is not set
+# CONFIG_TQM8548 is not set
+# CONFIG_TQM8555 is not set
+# CONFIG_TQM8560 is not set
+# CONFIG_SBC8548 is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_QUICC_ENGINE is not set
+# CONFIG_CPM2 is not set
+# CONFIG_FSL_ULI1575 is not set
+CONFIG_MPC8xxx_GPIO=y
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_FSL_LBC=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_LOWMEM_SIZE_BOOL=y
+CONFIG_LOWMEM_SIZE=0x40000000
+# CONFIG_LOWMEM_CAM_NUM_BOOL is not set
+CONFIG_LOWMEM_CAM_NUM=3
+# CONFIG_RELOCATABLE is not set
+CONFIG_PAGE_OFFSET_BOOL=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_KERNEL_START_BOOL=y
+CONFIG_KERNEL_START=0x80000000
+# CONFIG_PHYSICAL_START_BOOL is not set
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_PHYSICAL_ALIGN=0x04000000
+CONFIG_TASK_SIZE_BOOL=y
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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 is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+# 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=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_LRO 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 is not set
+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
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_NAND_FSL_ELBC=y
+CONFIG_MTD_NAND_FSL_UPM=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# 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_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_SATA_AHCI=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_FSL is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+CONFIG_PATA_ALI=y
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+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_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV 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_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_NVRAM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+CONFIG_GPIO_PCA953X=y
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+CONFIG_SENSORS_DS1621=y
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=y
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_BOOKE_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_ISP1760_HCD=y
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY 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
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+CONFIG_LEDS_GPIO_OF=y
+# CONFIG_LEDS_LP3944 is not set
+CONFIG_LEDS_PCA955X=y
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_GPIO=y
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_EDAC_MPC85XX=y
+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
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_GENERIC is not set
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+CONFIG_FSL_DMA=y
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# 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=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_TALITOS is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:31 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:31 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -56,11 +59,13 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -112,9 +117,7 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,8 +130,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -143,6 +153,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -156,7 +170,7 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -216,7 +230,7 @@
 #
 # Kernel options
 #
-# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -235,6 +249,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -256,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -285,14 +300,32 @@
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
 # CONFIG_PCI_LEGACY is not set
-CONFIG_PCI_DEBUG=y
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCI_IOV is not set
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PCMCIA_IOCTL is not set
+# CONFIG_CARDBUS is not set
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+# CONFIG_YENTA_O2 is not set
+# CONFIG_YENTA_RICOH is not set
+CONFIG_YENTA_TI=y
+# CONFIG_YENTA_TOSHIBA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=y
 # CONFIG_HOTPLUG_PCI is not set
 # CONFIG_HAS_RAPIDIO is not set
 
@@ -353,8 +386,8 @@
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -380,174 +413,26 @@
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_NETFILTER_ADVANCED=y
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# Core Netfilter Configuration
-#
-# CONFIG_NETFILTER_NETLINK_QUEUE is not set
-# CONFIG_NETFILTER_NETLINK_LOG is not set
-# CONFIG_NF_CONNTRACK is not set
-# CONFIG_NETFILTER_TPROXY is not set
-CONFIG_NETFILTER_XTABLES=m
-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
-# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
-# CONFIG_NETFILTER_XT_TARGET_HL is not set
-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
-# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
-# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
-# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
-# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
-# CONFIG_NETFILTER_XT_MATCH_ESP is not set
-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
-CONFIG_NETFILTER_XT_MATCH_HL=m
-# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
-# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
-# CONFIG_NETFILTER_XT_MATCH_MAC is not set
-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
-# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
-# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
-# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
-# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
-# CONFIG_NETFILTER_XT_MATCH_TIME is not set
-# CONFIG_NETFILTER_XT_MATCH_U32 is not set
-# CONFIG_IP_VS is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_NF_DEFRAG_IPV4 is not set
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-# CONFIG_IP_NF_MATCH_AH is not set
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_ECN=m
-# CONFIG_IP_NF_TARGET_TTL is not set
-CONFIG_IP_NF_RAW=m
-# CONFIG_IP_NF_SECURITY is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-# CONFIG_IP6_NF_MATCH_AH is not set
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-# CONFIG_IP6_NF_MATCH_MH is not set
-CONFIG_IP6_NF_MATCH_RT=m
-# CONFIG_IP6_NF_TARGET_HL is not set
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_FILTER=m
-# CONFIG_IP6_NF_TARGET_REJECT is not set
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_RAW=m
-# CONFIG_IP6_NF_SECURITY is not set
-# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP 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
-CONFIG_TIPC=m
-# CONFIG_TIPC_ADVANCED is not set
-# CONFIG_TIPC_DEBUG is not set
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-# CONFIG_ATM_BR2684_IPFILTER is not set
-CONFIG_STP=m
-CONFIG_BRIDGE=m
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_NET_DSA is not set
-CONFIG_VLAN_8021Q=m
-# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
-CONFIG_LLC=m
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
-CONFIG_WAN_ROUTER=m
+# CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
-CONFIG_NET_SCHED=y
-
-#
-# Queueing/Scheduling
-#
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-# CONFIG_NET_SCH_MULTIQ is not set
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-# CONFIG_NET_SCH_DRR is not set
-
-#
-# Classification
-#
-CONFIG_NET_CLS=y
-# CONFIG_NET_CLS_BASIC is not set
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_CLS_FLOW is not set
-# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
-# CONFIG_NET_CLS_IND is not set
-CONFIG_NET_SCH_FIFO=y
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
 #
@@ -560,12 +445,7 @@
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
 CONFIG_FIB_RULES=y
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+# CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -580,9 +460,9 @@
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
@@ -672,6 +552,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -707,9 +588,60 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 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
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
 
 #
 # SCSI device support
@@ -731,10 +663,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -751,6 +679,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -759,6 +688,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -778,7 +708,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -791,6 +720,7 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
@@ -842,6 +772,7 @@
 # CONFIG_PATA_NS87415 is not set
 # CONFIG_PATA_OPTI is not set
 # CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PCMCIA is not set
 # CONFIG_PATA_PDC_OLD is not set
 # CONFIG_PATA_RADISYS is not set
 # CONFIG_PATA_RZ1000 is not set
@@ -862,14 +793,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -916,6 +850,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -935,8 +870,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -963,22 +900,8 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_NET_PCMCIA is not set
 # CONFIG_WAN is not set
-CONFIG_ATM_DRIVERS=y
-# CONFIG_ATM_DUMMY is not set
-# CONFIG_ATM_TCP is not set
-# CONFIG_ATM_LANAI is not set
-# CONFIG_ATM_ENI is not set
-# CONFIG_ATM_FIRESTREAM is not set
-# CONFIG_ATM_ZATM is not set
-# CONFIG_ATM_NICSTAR is not set
-# CONFIG_ATM_IDT77252 is not set
-# CONFIG_ATM_AMBASSADOR is not set
-# CONFIG_ATM_HORIZON is not set
-# CONFIG_ATM_IA is not set
-# CONFIG_ATM_FORE200E is not set
-# CONFIG_ATM_HE is not set
-# CONFIG_ATM_SOLOS is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 CONFIG_PPP=m
@@ -990,7 +913,6 @@
 CONFIG_PPP_BSDCOMP=m
 # CONFIG_PPP_MPPE is not set
 CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
 # CONFIG_PPPOL2TP is not set
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
@@ -1010,7 +932,7 @@
 # Input device support
 #
 CONFIG_INPUT=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
 
 #
@@ -1058,6 +980,7 @@
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -1080,6 +1003,14 @@
 CONFIG_NVRAM=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
@@ -1143,18 +1074,21 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
-# CONFIG_DEBUG_GPIO is not set
-# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_SYSFS=y
 
 #
 # Memory mapped GPIO expanders:
@@ -1229,6 +1163,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1284,24 +1219,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1346,7 +1266,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1363,10 +1283,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1392,6 +1313,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1401,6 +1323,8 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1475,7 +1399,6 @@
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
-# CONFIG_USB_ATM is not set
 # CONFIG_USB_GADGET is not set
 
 #
@@ -1521,6 +1444,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 CONFIG_RTC_DRV_RX8581=y
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1548,6 +1472,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1569,10 +1497,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1589,8 +1519,11 @@
 #
 # CD-ROM/DVD Filesystems
 #
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -1598,8 +1531,8 @@
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1649,6 +1582,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1723,13 +1657,13 @@
 #
 CONFIG_BITREVERSE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
-CONFIG_CRC_CCITT=m
+CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
-# CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
+CONFIG_LIBCRC32C=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_DECOMPRESS_GZIP=y
@@ -1738,6 +1672,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1750,75 +1685,24 @@
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
-CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS 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 is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_MSI_BITMAP_SELFTEST is not set
-# CONFIG_XMON is not set
 # CONFIG_IRQSTACKS is not set
-# CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
@@ -1826,15 +1710,9 @@
 # Security options
 #
 # CONFIG_KEYS is not set
-CONFIG_SECURITY=y
+# CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-CONFIG_SECURITY_NETWORK=y
-# CONFIG_SECURITY_NETWORK_XFRM is not set
-# CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
-# CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
 #
@@ -1854,11 +1732,11 @@
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_NULL is not set
 CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_AUTHENC=m
-CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Authenticated Encryption with Associated Data
@@ -1873,53 +1751,52 @@
 CONFIG_CRYPTO_CBC=y
 # CONFIG_CRYPTO_CTR is not set
 # CONFIG_CRYPTO_CTS is not set
-CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_ECB is not set
 # CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_PCBC is not set
 # CONFIG_CRYPTO_XTS is not set
 
 #
 # Hash modes
 #
-CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_HMAC=m
 # CONFIG_CRYPTO_XCBC is not set
 
 #
 # Digest
 #
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_RMD128 is not set
 # CONFIG_CRYPTO_RMD160 is not set
 # CONFIG_CRYPTO_RMD256 is not set
 # CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_WP512 is not set
 
 #
 # Ciphers
 #
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_CAMELLIA is not set
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
-CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
 
 #
 # Compression
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:29 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:29 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -56,11 +59,13 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -91,7 +96,11 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_GROUP_SCHED is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
@@ -109,7 +118,6 @@
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,8 +130,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -138,6 +153,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -151,7 +170,7 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -168,7 +187,6 @@
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
 # CONFIG_FREEZER is not set
-CONFIG_PPC_MSI_BITMAP=y
 
 #
 # Platform support
@@ -212,7 +230,7 @@
 #
 # Kernel options
 #
-# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -231,6 +249,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +271,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -281,13 +300,32 @@
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
-CONFIG_PCI_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCI_IOV is not set
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PCMCIA_IOCTL is not set
+# CONFIG_CARDBUS is not set
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+# CONFIG_YENTA_O2 is not set
+# CONFIG_YENTA_RICOH is not set
+CONFIG_YENTA_TI=y
+# CONFIG_YENTA_TOSHIBA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=y
 # CONFIG_HOTPLUG_PCI is not set
 # CONFIG_HAS_RAPIDIO is not set
 
@@ -393,6 +431,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -421,7 +460,9 @@
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
@@ -511,6 +552,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -546,9 +588,60 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 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
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
 
 #
 # SCSI device support
@@ -570,10 +663,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -590,6 +679,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -598,6 +688,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -617,7 +708,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -630,6 +720,7 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
@@ -647,14 +738,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -701,6 +795,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -720,8 +815,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -748,6 +845,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_NET_PCMCIA is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -827,6 +925,7 @@
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -849,6 +948,14 @@
 CONFIG_NVRAM=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
@@ -912,13 +1019,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -997,6 +1108,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1052,24 +1164,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1114,7 +1211,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1131,10 +1228,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1160,6 +1258,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1169,6 +1268,8 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1288,6 +1389,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 CONFIG_RTC_DRV_RX8581=y
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1315,6 +1417,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1336,10 +1442,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1419,6 +1527,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1508,6 +1617,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1531,23 +1641,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:30 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:30 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -56,11 +59,13 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,8 +131,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -143,6 +154,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -156,7 +171,7 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -235,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -256,9 +272,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -285,6 +301,8 @@
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -510,6 +528,7 @@
 # CONFIG_ECONET is not set
 CONFIG_WAN_ROUTER=m
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -566,7 +585,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -678,6 +701,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -713,7 +737,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -737,10 +763,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -757,6 +779,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -765,6 +788,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -784,7 +808,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -868,14 +891,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -922,6 +948,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -941,8 +968,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -1149,13 +1178,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -1235,6 +1268,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1290,24 +1324,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1352,7 +1371,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1369,10 +1388,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1398,6 +1418,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1407,6 +1428,8 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1527,6 +1550,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 CONFIG_RTC_DRV_RX8581=y
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1554,6 +1578,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1575,10 +1603,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1645,6 +1675,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1734,6 +1765,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1759,10 +1791,14 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1774,7 +1810,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1788,17 +1823,16 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1806,6 +1840,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1829,7 +1866,6 @@
 # CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 # CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:28 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:27 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,11 +56,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -109,7 +114,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,9 +126,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -138,6 +149,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -150,7 +165,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -230,6 +245,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -250,9 +266,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -279,6 +295,8 @@
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -381,6 +399,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -398,7 +417,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -549,7 +572,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -620,10 +645,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -640,6 +661,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -648,6 +670,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -667,7 +690,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -751,14 +773,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -792,6 +817,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
@@ -959,13 +985,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -993,23 +1023,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1106,6 +1122,11 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
@@ -1130,6 +1151,7 @@
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1160,6 +1182,7 @@
 # CONFIG_SND_INTEL8X0 is not set
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1251,6 +1274,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1278,6 +1302,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1297,12 +1325,15 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -1464,6 +1495,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1494,6 +1526,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1506,7 +1541,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1520,16 +1554,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1537,6 +1570,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:28 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:28 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -54,11 +57,13 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -113,7 +118,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -126,9 +130,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -143,6 +154,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -156,7 +171,7 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -234,7 +249,9 @@
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -256,9 +273,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -401,6 +418,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -419,7 +437,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -444,6 +466,7 @@
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -479,7 +502,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -503,10 +528,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -524,6 +545,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -532,6 +554,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -551,7 +574,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -635,14 +657,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -689,6 +714,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -708,8 +734,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -909,13 +937,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -943,76 +975,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1017,11 @@
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1078,6 +1048,7 @@
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1108,6 +1079,7 @@
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1152,7 +1124,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1169,10 +1141,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1198,6 +1171,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1207,9 +1181,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1329,6 +1303,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1356,6 +1331,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1375,11 +1354,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1454,6 +1434,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1555,6 +1536,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1585,6 +1567,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1597,7 +1582,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1611,16 +1595,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1628,6 +1611,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/sbc8641d_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/sbc8641d_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/86xx/sbc8641d_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/86xx/sbc8641d_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:27 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:26 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -55,11 +58,13 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -113,7 +118,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -126,8 +130,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -142,6 +153,11 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -155,7 +171,7 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -234,6 +250,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -284,6 +301,8 @@
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -508,6 +527,7 @@
 # CONFIG_ECONET is not set
 CONFIG_WAN_ROUTER=m
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -564,7 +584,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -675,6 +699,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -709,7 +734,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -736,6 +763,7 @@
 CONFIG_DM_CRYPT=y
 CONFIG_DM_SNAPSHOT=y
 CONFIG_DM_MIRROR=y
+# CONFIG_DM_LOG_USERSPACE is not set
 CONFIG_DM_ZERO=y
 # CONFIG_DM_MULTIPATH is not set
 # CONFIG_DM_DELAY is not set
@@ -747,14 +775,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -801,6 +832,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -820,8 +852,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -1018,13 +1052,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1079,6 +1117,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1127,23 +1166,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1207,6 +1232,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1236,8 +1265,8 @@
 # CONFIG_REISERFS_FS_SECURITY is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 CONFIG_OCFS2_FS=m
 CONFIG_OCFS2_FS_O2CB=m
 CONFIG_OCFS2_FS_STATS=y
@@ -1245,6 +1274,8 @@
 # CONFIG_OCFS2_DEBUG_FS is not set
 # CONFIG_OCFS2_FS_POSIX_ACL is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1318,6 +1349,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1409,6 +1441,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1434,10 +1467,14 @@
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1449,7 +1486,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1463,17 +1499,16 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1482,9 +1517,13 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1505,7 +1544,6 @@
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 # CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 # CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/adder875_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/adder875_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/adder875_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/adder875_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:50 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:47 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -49,12 +50,14 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_REDBOOT=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -101,7 +104,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -114,8 +116,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -129,13 +138,18 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -220,6 +234,7 @@
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_8XX_MINIMAL_FPEMU is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -239,9 +254,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -280,6 +295,7 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -336,6 +352,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -353,7 +370,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -452,6 +473,7 @@
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
 # CONFIG_MISC_DEVICES is not set
@@ -469,7 +491,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -508,6 +529,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FEC=y
@@ -556,11 +578,11 @@
 #
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -622,6 +644,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -644,22 +671,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -685,6 +697,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -696,12 +712,15 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -818,6 +837,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -846,6 +866,9 @@
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -857,7 +880,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -870,16 +892,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -888,9 +909,13 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/c2k_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/c2k_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/c2k_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/c2k_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:51 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:48 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_NOT_COHERENT_CACHE=y
 CONFIG_CHECK_CACHE_COHERENCY=y
@@ -32,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -54,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -118,7 +123,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -131,16 +135,23 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
@@ -150,6 +161,11 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -162,7 +178,7 @@
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -258,6 +274,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -279,9 +296,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -331,6 +348,7 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -583,6 +601,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -663,7 +682,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -772,6 +795,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=m
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -816,10 +840,6 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
@@ -836,6 +856,7 @@
 CONFIG_SCSI_SRP_ATTRS=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 CONFIG_BLK_DEV_3W_XXXX_RAID=m
 CONFIG_SCSI_3W_9XXX=m
 CONFIG_SCSI_ACARD=m
@@ -854,6 +875,7 @@
 CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 CONFIG_SCSI_ARCMSR=m
@@ -875,7 +897,6 @@
 CONFIG_SCSI_IPS=m
 CONFIG_SCSI_INITIO=m
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=m
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
@@ -903,14 +924,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -957,6 +981,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -976,6 +1001,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_MV643XX_ETH=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
@@ -1177,13 +1203,17 @@
 CONFIG_SENSORS_PCF8574=m
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1238,6 +1268,7 @@
 CONFIG_SENSORS_SMSC47B397=m
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 CONFIG_SENSORS_VIA686A=m
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1266,7 +1297,6 @@
 #
 CONFIG_PCIPCWATCHDOG=m
 CONFIG_WDTPCI=m
-CONFIG_WDT_501_PCI=y
 
 #
 # USB-based Watchdog Cards
@@ -1289,23 +1319,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1354,6 +1370,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1362,9 +1379,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1545,6 +1562,10 @@
 #
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1563,11 +1584,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1652,6 +1674,7 @@
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1764,6 +1787,7 @@
 CONFIG_CHECK_SIGNATURE=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1794,6 +1818,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 CONFIG_DEBUG_SPINLOCK=y
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 CONFIG_STACKTRACE=y
@@ -1807,7 +1834,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_KPROBES_SANITY_TEST is not set
@@ -1824,30 +1850,34 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1869,7 +1899,6 @@
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 # CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/ep8248e_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/ep8248e_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/ep8248e_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/ep8248e_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:52 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:49 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,11 +56,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -99,7 +104,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -112,8 +116,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -127,6 +138,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -134,7 +149,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -213,6 +228,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -228,9 +244,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -300,6 +316,7 @@
 # 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=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
@@ -380,7 +397,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -485,6 +506,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -520,13 +542,17 @@
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -573,6 +599,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -594,8 +621,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_JME is not set
@@ -685,6 +714,10 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -728,22 +761,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -771,6 +789,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -787,9 +809,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -935,6 +958,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -960,6 +984,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -971,7 +998,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -985,22 +1011,23 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/ep88xc_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/ep88xc_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/ep88xc_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/ep88xc_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:53 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:49 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -49,11 +50,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -100,7 +103,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -113,8 +115,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -128,13 +137,17 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -220,6 +233,7 @@
 # CONFIG_MATH_EMULATION is not set
 CONFIG_8XX_MINIMAL_FPEMU=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -239,9 +253,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -280,6 +294,7 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -336,6 +351,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -353,7 +369,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -452,6 +472,7 @@
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
 # CONFIG_MISC_DEVICES is not set
@@ -469,7 +490,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -508,6 +528,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FEC=y
@@ -579,6 +600,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -602,22 +628,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -642,6 +653,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -653,12 +668,15 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -775,6 +793,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -803,6 +822,9 @@
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -814,7 +836,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -827,16 +848,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -844,6 +864,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/linkstation_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/linkstation_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/linkstation_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/linkstation_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:54 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:50 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +55,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,9 +131,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -143,6 +154,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -155,7 +170,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -237,6 +252,7 @@
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -257,9 +273,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -480,6 +496,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -498,7 +515,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -647,7 +668,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=m
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -670,10 +693,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -691,6 +710,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -699,6 +719,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -718,7 +739,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -802,14 +822,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -846,6 +869,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -865,8 +889,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -1074,13 +1100,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1135,6 +1165,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1169,23 +1200,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1245,6 +1262,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1254,9 +1272,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1423,6 +1441,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1450,6 +1469,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1469,14 +1492,16 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1548,6 +1573,7 @@
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
@@ -1578,7 +1604,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=m
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
@@ -1645,6 +1671,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1675,6 +1702,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1686,7 +1716,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1700,16 +1729,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1717,6 +1745,8 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mgcoge_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mgcoge_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mgcoge_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mgcoge_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:55 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:51 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,6 +56,7 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_HIBERNATE_32=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
@@ -60,6 +64,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -105,7 +110,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -119,8 +123,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -134,6 +145,11 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -141,7 +157,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -225,6 +241,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -240,9 +257,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -313,6 +330,7 @@
 # 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=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
@@ -374,7 +392,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -484,6 +506,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -523,13 +546,17 @@
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
+#
+
 #
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -577,6 +604,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
@@ -654,6 +682,10 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -697,22 +729,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -740,6 +757,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -757,9 +778,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -916,6 +938,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -941,6 +964,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -952,7 +978,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -966,16 +991,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -983,9 +1007,12 @@
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mgsuvd_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mgsuvd_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mgsuvd_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mgsuvd_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:55 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:52 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -48,11 +49,13 @@
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -102,7 +105,6 @@
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 # CONFIG_BUG is not set
@@ -115,7 +117,14 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -129,6 +138,11 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -136,7 +150,7 @@
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -222,6 +236,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -241,9 +256,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -281,6 +296,7 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -342,6 +358,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -359,7 +376,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -463,6 +484,7 @@
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -492,7 +514,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -531,6 +552,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
 # CONFIG_FS_ENET_HAS_FEC is not set
@@ -602,6 +624,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -625,22 +652,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -665,6 +677,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -687,10 +703,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -823,6 +841,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -844,24 +863,14 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_IRQSTACKS is not set
 # CONFIG_VIRQ_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc7448_hpc2_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc7448_hpc2_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc7448_hpc2_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc7448_hpc2_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:56 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:53 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +55,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -106,7 +111,6 @@
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -119,9 +123,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -134,6 +145,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -141,7 +156,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -220,6 +235,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -240,9 +256,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -348,6 +364,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -365,7 +382,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -385,6 +406,7 @@
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -416,6 +438,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -438,10 +461,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -458,6 +477,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -466,6 +486,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -485,7 +506,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -568,14 +588,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -642,6 +665,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -663,7 +687,9 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_TSI108_ETH=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -785,6 +811,11 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -824,22 +855,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -896,6 +912,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -915,11 +935,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1038,6 +1059,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1063,22 +1085,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc8272_ads_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc8272_ads_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc8272_ads_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc8272_ads_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:57 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:54 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,11 +56,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -99,7 +104,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -112,9 +116,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -128,6 +139,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -135,7 +150,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -216,6 +231,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -231,9 +247,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -303,6 +319,7 @@
 # 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=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
@@ -383,7 +400,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -489,6 +510,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -524,13 +546,17 @@
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
+#
+
 #
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -577,6 +603,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -598,8 +625,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_JME is not set
@@ -671,12 +700,13 @@
 #
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -741,6 +771,10 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -784,22 +818,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -828,6 +847,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -847,9 +870,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -998,6 +1022,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1028,6 +1053,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1039,7 +1067,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1053,22 +1080,23 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc83xx_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc83xx_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc83xx_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc83xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:58 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:55 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -54,6 +57,7 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_REDBOOT=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
@@ -61,6 +65,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +115,6 @@
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,8 +127,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -138,6 +149,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -150,7 +165,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -192,6 +207,7 @@
 CONFIG_MPC837x_RDB=y
 CONFIG_SBC834x=y
 CONFIG_ASP834x=y
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC831x=y
 CONFIG_PPC_MPC832x=y
 CONFIG_PPC_MPC834x=y
@@ -241,6 +257,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -261,9 +278,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -374,6 +391,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -391,7 +409,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -507,6 +529,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -542,7 +565,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -565,10 +590,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -586,6 +607,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -594,6 +616,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -613,7 +636,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -697,14 +719,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -751,6 +776,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -770,11 +796,13 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -965,13 +993,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -1050,6 +1082,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1104,24 +1137,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1159,7 +1177,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1176,10 +1194,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1205,6 +1224,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1291,6 +1311,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1310,10 +1334,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1377,6 +1403,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1413,7 +1440,46 @@
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 CONFIG_UCC_FAST=y
 CONFIG_UCC=y
@@ -1438,6 +1504,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1461,22 +1528,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc85xx_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc85xx_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc85xx_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc85xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Tue Apr 21 15:40:23 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:55 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -116,7 +119,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -129,9 +131,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -146,6 +155,11 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -158,7 +172,7 @@
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -191,6 +205,7 @@
 CONFIG_MPC85xx_DS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
+# CONFIG_XES_MPC85xx is not set
 CONFIG_STX_GP3=y
 CONFIG_TQM8540=y
 CONFIG_TQM8541=y
@@ -241,7 +256,9 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -260,9 +277,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -296,7 +313,8 @@
 # CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
 
 #
 # Advanced setup
@@ -406,6 +424,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -424,7 +443,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -450,6 +473,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -485,7 +509,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -509,10 +535,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -530,6 +552,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -538,6 +561,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -557,7 +581,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -641,14 +664,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -695,6 +721,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
@@ -718,11 +745,13 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -897,6 +926,7 @@
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 CONFIG_I2C_CPM=m
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -927,13 +957,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -987,76 +1021,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1096,6 +1063,11 @@
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1122,6 +1094,7 @@
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1152,6 +1125,7 @@
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1196,7 +1170,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1213,10 +1187,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1242,6 +1217,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1251,9 +1227,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1352,8 +1328,6 @@
 # CONFIG_EDAC_DEBUG is not set
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
-# CONFIG_EDAC_AMD8131 is not set
-# CONFIG_EDAC_AMD8111 is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1385,6 +1359,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1425,6 +1400,10 @@
 # CONFIG_DMATEST is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1445,11 +1424,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1524,6 +1504,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1628,6 +1609,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1658,6 +1640,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1670,7 +1655,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1684,16 +1668,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1702,9 +1685,13 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Tue Apr 21 15:41:18 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:56 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -35,15 +35,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -58,11 +59,13 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -117,7 +120,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -130,9 +132,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -148,6 +157,11 @@
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -161,7 +175,7 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -194,6 +208,7 @@
 CONFIG_MPC85xx_DS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
+# CONFIG_XES_MPC85xx is not set
 CONFIG_STX_GP3=y
 CONFIG_TQM8540=y
 CONFIG_TQM8541=y
@@ -244,7 +259,9 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -264,9 +281,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -300,7 +317,8 @@
 # CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
 
 #
 # Advanced setup
@@ -410,6 +428,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -428,7 +447,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -454,6 +477,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -489,7 +513,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -513,10 +539,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -534,6 +556,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -542,6 +565,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -561,7 +585,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -645,14 +668,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -699,6 +725,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
@@ -722,11 +749,13 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -901,6 +930,7 @@
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 CONFIG_I2C_CPM=m
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -931,13 +961,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -991,76 +1025,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1100,6 +1067,11 @@
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1126,6 +1098,7 @@
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1156,6 +1129,7 @@
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1200,7 +1174,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1217,10 +1191,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1246,6 +1221,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1255,9 +1231,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1356,8 +1332,6 @@
 # CONFIG_EDAC_DEBUG is not set
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
-# CONFIG_EDAC_AMD8131 is not set
-# CONFIG_EDAC_AMD8111 is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1389,6 +1363,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1429,6 +1404,10 @@
 # CONFIG_DMATEST is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1449,11 +1428,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1528,6 +1508,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1632,6 +1613,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1662,6 +1644,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1674,7 +1659,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1688,16 +1672,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1706,9 +1689,13 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc866_ads_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc866_ads_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc866_ads_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc866_ads_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:00 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:57 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -48,11 +49,13 @@
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -98,7 +101,6 @@
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 # CONFIG_BUG is not set
@@ -111,8 +113,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -126,6 +135,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -133,7 +146,7 @@
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -219,6 +232,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -238,9 +252,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -278,6 +292,7 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -339,6 +354,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -356,7 +372,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -374,6 +394,7 @@
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -407,7 +428,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -446,6 +466,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
 CONFIG_FS_ENET_HAS_FEC=y
@@ -453,6 +474,7 @@
 CONFIG_NETDEV_1000=y
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -496,11 +518,11 @@
 #
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -562,6 +584,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -597,22 +624,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -664,6 +676,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -685,10 +701,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -808,6 +826,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -831,22 +850,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc86xx_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc86xx_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc86xx_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc86xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:00 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:58 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -55,11 +58,13 @@
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,9 +131,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -144,6 +155,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -157,7 +172,7 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -236,7 +251,9 @@
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -258,9 +275,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -403,6 +420,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -421,7 +439,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -447,6 +469,7 @@
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -482,7 +505,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -506,10 +531,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -527,6 +548,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -535,6 +557,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -554,7 +577,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -638,14 +660,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -692,6 +717,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -711,8 +737,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -913,13 +941,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -973,76 +1005,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1082,6 +1047,11 @@
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1108,6 +1078,7 @@
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1138,6 +1109,7 @@
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1182,7 +1154,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1199,10 +1171,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1228,6 +1201,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1237,9 +1211,9 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1360,6 +1334,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1387,6 +1362,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1406,11 +1385,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1485,6 +1465,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1586,6 +1567,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1616,6 +1598,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1628,7 +1613,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1642,16 +1626,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1659,6 +1642,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc885_ads_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc885_ads_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/mpc885_ads_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/mpc885_ads_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:01 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:59 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -49,11 +50,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -100,7 +103,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -113,8 +115,15 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -128,13 +137,17 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -227,6 +240,7 @@
 # CONFIG_MATH_EMULATION is not set
 CONFIG_8XX_MINIMAL_FPEMU=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -246,9 +260,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -287,6 +301,7 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -343,6 +358,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -360,7 +376,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -463,6 +483,7 @@
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
 # CONFIG_MISC_DEVICES is not set
@@ -480,7 +501,6 @@
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -519,6 +539,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FEC=y
@@ -590,6 +611,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -613,22 +639,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -653,6 +664,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -664,12 +679,15 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -786,6 +804,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -814,6 +833,9 @@
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -825,7 +847,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -838,16 +859,15 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -855,6 +875,9 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/ppc6xx_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/ppc6xx_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/ppc6xx_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/ppc6xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1808,7 +1808,7 @@
 CONFIG_SENSORS_PCA9539=m
 CONFIG_SENSORS_PCF8591=m
 # CONFIG_TPS65010 is not set
-CONFIG_SENSORS_MAX6875=m
+CONFIG_EEPROM_MAX6875=m
 CONFIG_SENSORS_TSL2550=m
 CONFIG_MCU_MPC8349EMITX=m
 # CONFIG_I2C_DEBUG_CORE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/pq2fads_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/pq2fads_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/pq2fads_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/pq2fads_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:02 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:00 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,11 +56,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -103,7 +108,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -116,9 +120,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -132,6 +143,10 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -139,7 +154,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -219,6 +234,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -234,9 +250,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -307,6 +323,7 @@
 # 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=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
@@ -387,7 +404,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -493,6 +514,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -518,6 +540,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -583,13 +606,17 @@
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
 #
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -636,6 +663,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -657,8 +685,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_JME is not set
@@ -730,12 +760,13 @@
 #
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -802,6 +833,10 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -845,22 +880,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -903,8 +923,9 @@
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 CONFIG_USB_GADGET_M66592=y
 CONFIG_USB_M66592=y
 # CONFIG_USB_GADGET_AMD5536UDC is not set
@@ -912,9 +933,11 @@
 # CONFIG_USB_GADGET_CI13XXX is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 CONFIG_USB_ETH=y
 CONFIG_USB_ETH_RNDIS=y
 # CONFIG_USB_GADGETFS is not set
@@ -939,6 +962,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -958,9 +985,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1110,6 +1138,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1140,6 +1169,9 @@
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1151,7 +1183,6 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1165,22 +1196,23 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/prpmc2800_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/prpmc2800_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/prpmc2800_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/prpmc2800_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:03 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:01 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_NOT_COHERENT_CACHE=y
 CONFIG_CHECK_CACHE_COHERENCY=y
@@ -32,15 +34,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -54,11 +57,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,9 +131,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -142,6 +153,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -149,7 +164,7 @@
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -228,6 +243,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -249,9 +265,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -296,6 +312,7 @@
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -357,6 +374,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -374,7 +392,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -479,6 +501,7 @@
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -514,7 +537,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -591,10 +616,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -611,6 +632,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -619,6 +641,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -638,7 +661,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -721,7 +743,11 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -730,7 +756,6 @@
 # CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -797,6 +822,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -818,6 +844,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_MV643XX_ETH=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
@@ -1007,13 +1034,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1068,6 +1099,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1102,23 +1134,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1163,6 +1181,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
 # CONFIG_DRAGONRISE_FF is not set
 CONFIG_HID_EZKEY=y
 CONFIG_HID_KYE=y
@@ -1180,9 +1199,14 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
 # CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SMARTJOYPLUS=y
+# CONFIG_SMARTJOYPLUS_FF is not set
 CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
 CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_ZEROPLUS=y
 CONFIG_ZEROPLUS_FF=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1207,6 +1231,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1215,6 +1240,8 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1322,6 +1349,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1349,6 +1377,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1368,11 +1400,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1469,7 +1502,46 @@
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1494,6 +1566,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1519,22 +1592,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/ps3_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/ps3_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/ps3_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/ps3_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc5
-# Fri May 15 10:37:00 2009
+# Linux kernel version: 2.6.31-rc7
+# Mon Aug 24 17:38:50 2009
 #
 CONFIG_PPC64=y
 
 #
 # Processor support
 #
+CONFIG_PPC_BOOK3S_64=y
 CONFIG_PPC_BOOK3S=y
 # CONFIG_POWER4_ONLY is not set
 CONFIG_POWER3=y
@@ -20,6 +21,7 @@
 CONFIG_PPC_STD_MMU_64=y
 CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_64BIT=y
@@ -31,6 +33,7 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
@@ -41,7 +44,6 @@
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_PPC=y
@@ -62,6 +64,7 @@
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -113,7 +116,6 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -126,7 +128,14 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -145,6 +154,11 @@
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -210,7 +224,7 @@
 #
 # Cell Broadband Engine options
 #
-CONFIG_SPU_FS=y
+CONFIG_SPU_FS=m
 CONFIG_SPU_FS_64K_LS=y
 # CONFIG_SPU_TRACE is not set
 CONFIG_SPU_BASE=y
@@ -255,6 +269,7 @@
 CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_IOMMU_HELPER=y
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -285,9 +300,9 @@
 CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ARCH_MEMORY_PROBE=y
 CONFIG_PPC_HAS_HASH_64K=y
 CONFIG_PPC_4K_PAGES=y
@@ -399,6 +414,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -433,11 +449,14 @@
 CONFIG_WIRELESS=y
 CONFIG_CFG80211=m
 # CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 CONFIG_WIRELESS_EXT=y
 # CONFIG_WIRELESS_EXT_SYSFS is not set
 # CONFIG_LIB80211 is not set
 CONFIG_MAC80211=m
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
 
 #
 # Rate control algorithm selection
@@ -447,7 +466,6 @@
 CONFIG_MAC80211_RC_DEFAULT_PID=y
 # CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
 CONFIG_MAC80211_RC_DEFAULT="pid"
-# CONFIG_MAC80211_MESH is not set
 # CONFIG_MAC80211_LEDS is not set
 # CONFIG_MAC80211_DEBUGFS is not set
 # CONFIG_MAC80211_DEBUG_MENU is not set
@@ -472,77 +490,7 @@
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=0
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_TESTS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_MTD_OOPS is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# LPDDR flash memory drivers
-#
-# CONFIG_MTD_LPDDR is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
+# CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
@@ -590,10 +538,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -626,7 +570,6 @@
 # CONFIG_DM_UEVENT is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -646,10 +589,11 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_GELIC_NET=y
 CONFIG_GELIC_WIRELESS=y
-CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE=y
+# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
 # CONFIG_NETDEV_10000 is not set
 
 #
@@ -669,8 +613,7 @@
 # CONFIG_HOSTAP is not set
 # CONFIG_B43 is not set
 # CONFIG_B43LEGACY is not set
-CONFIG_ZD1211RW=m
-# CONFIG_ZD1211RW_DEBUG is not set
+# CONFIG_ZD1211RW is not set
 # CONFIG_RT2X00 is not set
 
 #
@@ -682,7 +625,7 @@
 #
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=m
+# CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_AX8817X=m
@@ -693,10 +636,11 @@
 # CONFIG_USB_NET_GL620A is not set
 # CONFIG_USB_NET_NET1080 is not set
 # CONFIG_USB_NET_PLUSB is not set
-CONFIG_USB_NET_MCS7830=m
+# CONFIG_USB_NET_MCS7830 is not set
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_INT51X1 is not set
 # CONFIG_WAN is not set
 CONFIG_PPP=m
 CONFIG_PPP_MULTILINK=y
@@ -771,8 +715,7 @@
 #
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HVC_UDBG is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
@@ -782,6 +725,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -805,22 +753,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -898,6 +831,11 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 # CONFIG_SND_DRIVERS is not set
 CONFIG_SND_PPC=y
 CONFIG_SND_PS3=m
@@ -930,29 +868,34 @@
 # Special HID drivers
 #
 # CONFIG_HID_A4TECH is not set
-# CONFIG_HID_APPLE is not set
-# CONFIG_HID_BELKIN is not set
-# CONFIG_HID_CHERRY is not set
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
 # CONFIG_HID_CHICONY is not set
 # CONFIG_HID_CYPRESS is not set
-# CONFIG_DRAGONRISE_FF is not set
-# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_DRAGONRISE is not set
+CONFIG_HID_EZKEY=m
 # CONFIG_HID_KYE is not set
 # CONFIG_HID_GYRATION is not set
 # CONFIG_HID_KENSINGTON is not set
-# CONFIG_HID_LOGITECH is not set
-# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
 # CONFIG_HID_MONTEREY is not set
 # CONFIG_HID_NTRIG is not set
 # CONFIG_HID_PANTHERLORD is not set
 # CONFIG_HID_PETALYNX is not set
 # CONFIG_HID_SAMSUNG is not set
 CONFIG_HID_SONY=m
-# CONFIG_HID_SUNPLUS is not set
-# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SUNPLUS=m
+# CONFIG_HID_GREENASIA is not set
+CONFIG_HID_SMARTJOYPLUS=m
+# CONFIG_SMARTJOYPLUS_FF is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -988,6 +931,8 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # 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
@@ -1115,6 +1060,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1141,11 +1090,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1205,7 +1155,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1222,6 +1171,7 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1359,7 +1309,6 @@
 CONFIG_DEBUG_LIST=y
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1374,31 +1323,21 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/configs/storcenter_defconfig linux-libre-2.6.31-gnu/arch/powerpc/configs/storcenter_defconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/configs/storcenter_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/configs/storcenter_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:04 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:01 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +55,13 @@
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -101,7 +106,6 @@
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -114,9 +118,16 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -129,6 +140,10 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -141,7 +156,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -222,6 +237,7 @@
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +258,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -347,6 +363,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -364,7 +381,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -501,7 +522,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -579,10 +602,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -599,6 +618,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -607,6 +627,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -626,7 +647,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -660,14 +680,17 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -695,8 +718,10 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -845,13 +870,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -879,23 +908,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -937,6 +952,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -946,6 +962,8 @@
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1064,6 +1082,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1091,6 +1110,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1110,7 +1133,6 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_POSIX_ACL is not set
@@ -1119,6 +1141,8 @@
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1273,6 +1297,7 @@
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1298,22 +1323,11 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/8253pit.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/8253pit.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/8253pit.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/8253pit.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,3 @@
-#ifndef _ASM_POWERPC_8253PIT_H
-#define _ASM_POWERPC_8253PIT_H
-
 /*
  * 8253/8254 Programmable Interval Timer
  */
-
-#define PIT_TICK_RATE	1193182UL
-
-#endif	/* _ASM_POWERPC_8253PIT_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -470,8 +470,11 @@
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
+#else  /* __powerpc64__ */
+#include <asm-generic/atomic64.h>
+
 #endif /* __powerpc64__ */
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_ATOMIC_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef __ASM_POWERPC_BITSPERLONG_H
+#define __ASM_POWERPC_BITSPERLONG_H
+
+#if defined(__powerpc64__)
+# define __BITS_PER_LONG 64
+#else
+# define __BITS_PER_LONG 32
+#endif
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_POWERPC_BITSPERLONG_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/cpm1.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/cpm1.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/cpm1.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/cpm1.h	2009-09-09 18:13:59.000000000 -0400
@@ -598,8 +598,6 @@
 #define CICR_IEN		((uint)0x00000080)	/* Int. enable */
 #define CICR_SPS		((uint)0x00000001)	/* SCC Spread */
 
-#define IMAP_ADDR		(get_immrbase())
-
 #define CPM_PIN_INPUT     0
 #define CPM_PIN_OUTPUT    1
 #define CPM_PIN_PRIMARY   0
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/cpm2.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/cpm2.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/cpm2.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/cpm2.h	2009-09-09 18:13:59.000000000 -0400
@@ -14,10 +14,6 @@
 #include <asm/cpm.h>
 #include <sysdev/fsl_soc.h>
 
-#ifdef CONFIG_PPC_85xx
-#define CPM_MAP_ADDR (get_immrbase() + 0x80000)
-#endif
-
 /* CPM Command register.
 */
 #define CPM_CR_RST	((uint)0x80000000)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/delay.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/delay.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/delay.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/delay.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,11 @@
 #define _ASM_POWERPC_DELAY_H
 #ifdef __KERNEL__
 
+#include <asm/time.h>
+
 /*
  * Copyright 1996, Paul Mackerras.
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,5 +33,40 @@
 #define mdelay(n)	udelay((n) * 1000)
 #endif
 
+/**
+ * spin_event_timeout - spin until a condition gets true or a timeout elapses
+ * @condition: a C expression to evalate
+ * @timeout: timeout, in microseconds
+ * @delay: the number of microseconds to delay between each evaluation of
+ *         @condition
+ *
+ * The process spins until the condition evaluates to true (non-zero) or the
+ * timeout elapses.  The return value of this macro is the value of
+ * @condition when the loop terminates. This allows you to determine the cause
+ * of the loop terminates.  If the return value is zero, then you know a
+ * timeout has occurred.
+ *
+ * This primary purpose of this macro is to poll on a hardware register
+ * until a status bit changes.  The timeout ensures that the loop still
+ * terminates even if the bit never changes.  The delay is for devices that
+ * need a delay in between successive reads.
+ *
+ * gcc will optimize out the if-statement if @delay is a constant.
+ */
+#define spin_event_timeout(condition, timeout, delay)                          \
+({                                                                             \
+	typeof(condition) __ret;                                               \
+	unsigned long __loops = tb_ticks_per_usec * timeout;                   \
+	unsigned long __start = get_tbl();                                     \
+	while (!(__ret = (condition)) && (tb_ticks_since(__start) <= __loops)) \
+		if (delay)                                                     \
+			udelay(delay);                                         \
+		else                                                           \
+			cpu_relax();                                           \
+	if (!__ret)                                                            \
+		__ret = (condition);                                           \
+	__ret;		                                                       \
+})
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DELAY_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -15,9 +15,18 @@
 #include <linux/scatterlist.h>
 #include <linux/dma-attrs.h>
 #include <asm/io.h>
+#include <asm/swiotlb.h>
 
 #define DMA_ERROR_CODE		(~(dma_addr_t)0x0)
 
+/* Some dma direct funcs must be visible for use in other dma_ops */
+extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag);
+extern void dma_direct_free_coherent(struct device *dev, size_t size,
+				     void *vaddr, dma_addr_t dma_handle);
+
+extern unsigned long get_dma_direct_offset(struct device *dev);
+
 #ifdef CONFIG_NOT_COHERENT_CACHE
 /*
  * DMA-consistent mapping functions for PowerPCs that don't support
@@ -78,6 +87,8 @@
 				dma_addr_t dma_address, size_t size,
 				enum dma_data_direction direction,
 				struct dma_attrs *attrs);
+	int		(*addr_needs_map)(struct device *dev, dma_addr_t addr,
+				size_t size);
 #ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
 	void            (*sync_single_range_for_cpu)(struct device *hwdev,
 				dma_addr_t dma_handle, unsigned long offset,
@@ -298,7 +309,9 @@
 	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
 	BUG_ON(!dma_ops);
-	dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0,
+
+	if (dma_ops->sync_single_range_for_cpu)
+		dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0,
 					   size, direction);
 }
 
@@ -309,7 +322,9 @@
 	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
 	BUG_ON(!dma_ops);
-	dma_ops->sync_single_range_for_device(dev, dma_handle,
+
+	if (dma_ops->sync_single_range_for_device)
+		dma_ops->sync_single_range_for_device(dev, dma_handle,
 					      0, size, direction);
 }
 
@@ -320,7 +335,9 @@
 	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
 	BUG_ON(!dma_ops);
-	dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
+
+	if (dma_ops->sync_sg_for_cpu)
+		dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
 }
 
 static inline void dma_sync_sg_for_device(struct device *dev,
@@ -330,7 +347,9 @@
 	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
 	BUG_ON(!dma_ops);
-	dma_ops->sync_sg_for_device(dev, sgl, nents, direction);
+
+	if (dma_ops->sync_sg_for_device)
+		dma_ops->sync_sg_for_device(dev, sgl, nents, direction);
 }
 
 static inline void dma_sync_single_range_for_cpu(struct device *dev,
@@ -340,7 +359,9 @@
 	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
 	BUG_ON(!dma_ops);
-	dma_ops->sync_single_range_for_cpu(dev, dma_handle,
+
+	if (dma_ops->sync_single_range_for_cpu)
+		dma_ops->sync_single_range_for_cpu(dev, dma_handle,
 					   offset, size, direction);
 }
 
@@ -351,7 +372,9 @@
 	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
 	BUG_ON(!dma_ops);
-	dma_ops->sync_single_range_for_device(dev, dma_handle, offset,
+
+	if (dma_ops->sync_single_range_for_device)
+		dma_ops->sync_single_range_for_device(dev, dma_handle, offset,
 					      size, direction);
 }
 #else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/elf.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/elf.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/elf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/elf.h	2009-09-09 18:13:59.000000000 -0400
@@ -256,11 +256,11 @@
  * even if we have an executable stack.
  */
 # define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
-		(exec_stk != EXSTACK_DISABLE_X) : 0)
+		(exec_stk == EXSTACK_DEFAULT) : 0)
 #else 
 # define SET_PERSONALITY(ex) \
   set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
-# define elf_read_implies_exec(ex, exec_stk) (exec_stk != EXSTACK_DISABLE_X)
+# define elf_read_implies_exec(ex, exec_stk) (exec_stk == EXSTACK_DEFAULT)
 #endif /* __powerpc64__ */
 
 extern int dcache_bsize;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/emulated_ops.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/emulated_ops.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/emulated_ops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/emulated_ops.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,73 @@
+/*
+ *  Copyright 2007 Sony 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; 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASM_POWERPC_EMULATED_OPS_H
+#define _ASM_POWERPC_EMULATED_OPS_H
+
+#include <asm/atomic.h>
+
+
+#ifdef CONFIG_PPC_EMULATED_STATS
+
+struct ppc_emulated_entry {
+	const char *name;
+	atomic_t val;
+};
+
+extern struct ppc_emulated {
+#ifdef CONFIG_ALTIVEC
+	struct ppc_emulated_entry altivec;
+#endif
+	struct ppc_emulated_entry dcba;
+	struct ppc_emulated_entry dcbz;
+	struct ppc_emulated_entry fp_pair;
+	struct ppc_emulated_entry isel;
+	struct ppc_emulated_entry mcrxr;
+	struct ppc_emulated_entry mfpvr;
+	struct ppc_emulated_entry multiple;
+	struct ppc_emulated_entry popcntb;
+	struct ppc_emulated_entry spe;
+	struct ppc_emulated_entry string;
+	struct ppc_emulated_entry unaligned;
+#ifdef CONFIG_MATH_EMULATION
+	struct ppc_emulated_entry math;
+#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
+	struct ppc_emulated_entry 8xx;
+#endif
+#ifdef CONFIG_VSX
+	struct ppc_emulated_entry vsx;
+#endif
+} ppc_emulated;
+
+extern u32 ppc_warn_emulated;
+
+extern void ppc_warn_emulated_print(const char *type);
+
+#define PPC_WARN_EMULATED(type)						 \
+	do {								 \
+		atomic_inc(&ppc_emulated.type.val);			 \
+		if (ppc_warn_emulated)					 \
+			ppc_warn_emulated_print(ppc_emulated.type.name); \
+	} while (0)
+
+#else /* !CONFIG_PPC_EMULATED_STATS */
+
+#define PPC_WARN_EMULATED(type)	do { } while (0)
+
+#endif /* !CONFIG_PPC_EMULATED_STATS */
+
+#endif /* _ASM_POWERPC_EMULATED_OPS_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/feature-fixups.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/feature-fixups.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/feature-fixups.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/feature-fixups.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,8 +8,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#ifdef __ASSEMBLY__
-
 /*
  * Feature section common macros
  *
@@ -23,10 +21,12 @@
 /* 64 bits kernel, 32 bits code (ie. vdso32) */
 #define FTR_ENTRY_LONG		.llong
 #define FTR_ENTRY_OFFSET	.long 0xffffffff; .long
+#elif defined(CONFIG_PPC64)
+#define FTR_ENTRY_LONG		.llong
+#define FTR_ENTRY_OFFSET	.llong
 #else
-/* 64 bit kernel 64 bit code, or 32 bit kernel 32 bit code */
-#define FTR_ENTRY_LONG		PPC_LONG
-#define FTR_ENTRY_OFFSET	PPC_LONG
+#define FTR_ENTRY_LONG		.long
+#define FTR_ENTRY_OFFSET	.long
 #endif
 
 #define START_FTR_SECTION(label)	label##1:
@@ -141,6 +141,21 @@
 #define ALT_FW_FTR_SECTION_END_IFCLR(msk)	\
 	ALT_FW_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
 
+#ifndef __ASSEMBLY__
+
+#define ASM_MMU_FTR_IF(section_if, section_else, msk, val)	\
+	stringify_in_c(BEGIN_MMU_FTR_SECTION)			\
+	section_if "; "						\
+	stringify_in_c(MMU_FTR_SECTION_ELSE)			\
+	section_else "; "					\
+	stringify_in_c(ALT_MMU_FTR_SECTION_END((msk), (val)))
+
+#define ASM_MMU_FTR_IFSET(section_if, section_else, msk)	\
+	ASM_MMU_FTR_IF(section_if, section_else, (msk), (msk))
+
+#define ASM_MMU_FTR_IFCLR(section_if, section_else, msk)	\
+	ASM_MMU_FTR_IF(section_if, section_else, (msk), 0)
+
 #endif /* __ASSEMBLY__ */
 
 /* LWSYNC feature sections */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/fsl_lbc.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/fsl_lbc.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/fsl_lbc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/fsl_lbc.h	2009-09-09 18:13:59.000000000 -0400
@@ -95,8 +95,8 @@
 };
 
 struct fsl_lbc_regs {
-	struct fsl_lbc_bank bank[8];
-	u8 res0[0x28];
+	struct fsl_lbc_bank bank[12];
+	u8 res0[0x8];
 	__be32 mar;             /**< UPM Address Register */
 	u8 res1[0x4];
 	__be32 mamr;            /**< UPMA Mode Register */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/highmem.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/highmem.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/highmem.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/highmem.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,9 +22,7 @@
 
 #ifdef __KERNEL__
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/highmem.h>
 #include <asm/kmap_types.h>
 #include <asm/tlbflush.h>
 #include <asm/page.h>
@@ -62,6 +60,9 @@
 
 extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
+extern void *kmap_atomic_prot(struct page *page, enum km_type type,
+			      pgprot_t prot);
+extern void kunmap_atomic(void *kvaddr, enum km_type type);
 
 static inline void *kmap(struct page *page)
 {
@@ -79,62 +80,11 @@
 	kunmap_high(page);
 }
 
-/*
- * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
- * gives a more generic (and caching) interface. But kmap_atomic can
- * be used in IRQ contexts, so in some (very limited) cases we need
- * it.
- */
-static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
-{
-	unsigned int idx;
-	unsigned long vaddr;
-
-	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
-	pagefault_disable();
-	if (!PageHighMem(page))
-		return page_address(page);
-
-	debug_kmap_atomic(type);
-	idx = type + KM_TYPE_NR*smp_processor_id();
-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
-	BUG_ON(!pte_none(*(kmap_pte-idx)));
-#endif
-	__set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1);
-	local_flush_tlb_page(NULL, vaddr);
-
-	return (void*) vaddr;
-}
-
 static inline void *kmap_atomic(struct page *page, enum km_type type)
 {
 	return kmap_atomic_prot(page, type, kmap_prot);
 }
 
-static inline void kunmap_atomic(void *kvaddr, enum km_type type)
-{
-#ifdef CONFIG_DEBUG_HIGHMEM
-	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
-
-	if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
-		pagefault_enable();
-		return;
-	}
-
-	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-
-	/*
-	 * force other mappings to Oops if they'll try to access
-	 * this pte without first remap it
-	 */
-	pte_clear(&init_mm, vaddr, kmap_pte-idx);
-	local_flush_tlb_page(NULL, vaddr);
-#endif
-	pagefault_enable();
-}
-
 static inline struct page *kmap_atomic_to_page(void *ptr)
 {
 	unsigned long idx, vaddr = (unsigned long) ptr;
@@ -148,6 +98,7 @@
 	return pte_page(*pte);
 }
 
+
 #define flush_cache_kmaps()	flush_cache_all()
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/hw_irq.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/hw_irq.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/hw_irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/hw_irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -68,37 +68,37 @@
 
 #if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+#define raw_local_irq_restore(flags)	__asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
 #else
 #define SET_MSR_EE(x)	mtmsr(x)
-#define local_irq_restore(flags)	mtmsr(flags)
+#define raw_local_irq_restore(flags)	mtmsr(flags)
 #endif
 
-static inline void local_irq_disable(void)
+static inline void raw_local_irq_disable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 0": : :"memory");
 #else
 	unsigned long msr;
-	__asm__ __volatile__("": : :"memory");
+
 	msr = mfmsr();
 	SET_MSR_EE(msr & ~MSR_EE);
 #endif
 }
 
-static inline void local_irq_enable(void)
+static inline void raw_local_irq_enable(void)
 {
 #ifdef CONFIG_BOOKE
 	__asm__ __volatile__("wrteei 1": : :"memory");
 #else
 	unsigned long msr;
-	__asm__ __volatile__("": : :"memory");
+
 	msr = mfmsr();
 	SET_MSR_EE(msr | MSR_EE);
 #endif
 }
 
-static inline void local_irq_save_ptr(unsigned long *flags)
+static inline void raw_local_irq_save_ptr(unsigned long *flags)
 {
 	unsigned long msr;
 	msr = mfmsr();
@@ -108,15 +108,14 @@
 #else
 	SET_MSR_EE(msr & ~MSR_EE);
 #endif
-	__asm__ __volatile__("": : :"memory");
 }
 
-#define local_save_flags(flags)	((flags) = mfmsr())
-#define local_irq_save(flags)	local_irq_save_ptr(&flags)
-#define irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_local_save_flags(flags)	((flags) = mfmsr())
+#define raw_local_irq_save(flags)	raw_local_irq_save_ptr(&flags)
+#define raw_irqs_disabled()		((mfmsr() & MSR_EE) == 0)
+#define raw_irqs_disabled_flags(flags)	(((flags) & MSR_EE) == 0)
 
-#define hard_irq_enable()	local_irq_enable()
-#define hard_irq_disable()	local_irq_disable()
+#define hard_irq_disable()		raw_local_irq_disable()
 
 static inline int irqs_disabled_flags(unsigned long flags)
 {
@@ -131,5 +130,43 @@
  */
 struct irq_chip;
 
+#ifdef CONFIG_PERF_COUNTERS
+
+#ifdef CONFIG_PPC64
+static inline unsigned long test_perf_counter_pending(void)
+{
+	unsigned long x;
+
+	asm volatile("lbz %0,%1(13)"
+		: "=r" (x)
+		: "i" (offsetof(struct paca_struct, perf_counter_pending)));
+	return x;
+}
+
+static inline void set_perf_counter_pending(void)
+{
+	asm volatile("stb %0,%1(13)" : :
+		"r" (1),
+		"i" (offsetof(struct paca_struct, perf_counter_pending)));
+}
+
+static inline void clear_perf_counter_pending(void)
+{
+	asm volatile("stb %0,%1(13)" : :
+		"r" (0),
+		"i" (offsetof(struct paca_struct, perf_counter_pending)));
+}
+#endif /* CONFIG_PPC64 */
+
+#else  /* CONFIG_PERF_COUNTERS */
+
+static inline unsigned long test_perf_counter_pending(void)
+{
+	return 0;
+}
+
+static inline void clear_perf_counter_pending(void) {}
+#endif /* CONFIG_PERF_COUNTERS */
+
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_POWERPC_HW_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/iommu.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/iommu.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/iommu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/iommu.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,6 +35,16 @@
 #define IOMMU_PAGE_MASK       (~((1 << IOMMU_PAGE_SHIFT) - 1))
 #define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE)
 
+/* Cell page table entries */
+#define CBE_IOPTE_PP_W		0x8000000000000000ul /* protection: write */
+#define CBE_IOPTE_PP_R		0x4000000000000000ul /* protection: read */
+#define CBE_IOPTE_M		0x2000000000000000ul /* coherency required */
+#define CBE_IOPTE_SO_R		0x1000000000000000ul /* ordering: writes */
+#define CBE_IOPTE_SO_RW		0x1800000000000000ul /* ordering: r & w */
+#define CBE_IOPTE_RPN_Mask	0x07fffffffffff000ul /* RPN */
+#define CBE_IOPTE_H		0x0000000000000800ul /* cache hint */
+#define CBE_IOPTE_IOID_Mask	0x00000000000007fful /* ioid */
+
 /* Boot time flags */
 extern int iommu_is_off;
 extern int iommu_force_on;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/kvm_host.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/kvm_host.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/kvm_host.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/kvm_host.h	2009-09-09 18:13:59.000000000 -0400
@@ -34,7 +34,7 @@
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 
 /* We don't currently support large pages. */
-#define KVM_PAGES_PER_HPAGE (1<<31)
+#define KVM_PAGES_PER_HPAGE (1UL << 31)
 
 struct kvm;
 struct kvm_run;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/lppaca.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/lppaca.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/lppaca.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/lppaca.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,11 @@
 #define _ASM_POWERPC_LPPACA_H
 #ifdef __KERNEL__
 
+/* These definitions relate to hypervisors that only exist when using
+ * a server type processor
+ */
+#ifdef CONFIG_PPC_BOOK3S
+
 //=============================================================================
 //
 //	This control block contains the data that is shared between the
@@ -158,5 +163,6 @@
 
 extern struct slb_shadow slb_shadow[];
 
+#endif /* CONFIG_PPC_BOOK3S */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_LPPACA_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/machdep.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/machdep.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/machdep.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/machdep.h	2009-09-09 18:13:59.000000000 -0400
@@ -110,6 +110,10 @@
 	void		(*show_percpuinfo)(struct seq_file *m, int i);
 
 	void		(*init_IRQ)(void);
+
+	/* Return an irq, or NO_IRQ to indicate there are none pending.
+	 * If for some reason there is no irq, but the interrupt
+	 * shouldn't be counted as spurious, return NO_IRQ_IGNORE. */
 	unsigned int	(*get_irq)(void);
 #ifdef CONFIG_KEXEC
 	void		(*kexec_cpu_down)(int crash_shutdown, int secondary);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mman.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef _ASM_POWERPC_MMAN_H
 #define _ASM_POWERPC_MMAN_H
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 /*
  * This program is free software; you can redistribute it and/or
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mmu.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mmu.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mmu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mmu.h	2009-09-09 18:13:59.000000000 -0400
@@ -52,6 +52,11 @@
  */
 #define MMU_FTR_NEED_DTLB_SW_LRU	ASM_CONST(0x00200000)
 
+/* This indicates that the processor uses the ISA 2.06 server tlbie
+ * mnemonics
+ */
+#define MMU_FTR_TLBIE_206		ASM_CONST(0x00400000)
+
 #ifndef __ASSEMBLY__
 #include <asm/cputable.h>
 
@@ -69,10 +74,10 @@
 #endif /* !__ASSEMBLY__ */
 
 
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PPC_STD_MMU_64)
 /* 64-bit classic hash table MMU */
 #  include <asm/mmu-hash64.h>
-#elif defined(CONFIG_PPC_STD_MMU)
+#elif defined(CONFIG_PPC_STD_MMU_32)
 /* 32-bit classic hash table MMU */
 #  include <asm/mmu-hash32.h>
 #elif defined(CONFIG_40x)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc512x.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc512x.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc512x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc512x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby, <jrigby@freescale.com>, Friday Apr 13 2007
- *
- * Description:
- * MPC5121 Prototypes and definitions
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_POWERPC_MPC512x_H__
-#define __ASM_POWERPC_MPC512x_H__
-
-extern unsigned long mpc512x_find_ips_freq(struct device_node *node);
-
-#endif /* __ASM_POWERPC_MPC512x_H__ */
-
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc52xx.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc52xx.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc52xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc52xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 #include <asm/prom.h>
+#include <asm/mpc5xxx.h>
 #endif /* __ASSEMBLY__ */
 
 #include <linux/suspend.h>
@@ -268,7 +269,6 @@
 #ifndef __ASSEMBLY__
 
 /* mpc52xx_common.c */
-extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node);
 extern void mpc5200_setup_xlb_arbiter(void);
 extern void mpc52xx_declare_of_platform_devices(void);
 extern void mpc52xx_map_common_devices(void);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc52xx_psc.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc52xx_psc.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc52xx_psc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc52xx_psc.h	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,10 @@
 #define MPC52xx_PSC_MAXNUM	6
 
 /* Programmable Serial Controller (PSC) status register bits */
+#define MPC52xx_PSC_SR_UNEX_RX	0x0001
+#define MPC52xx_PSC_SR_DATA_VAL	0x0002
+#define MPC52xx_PSC_SR_DATA_OVR	0x0004
+#define MPC52xx_PSC_SR_CMDSEND	0x0008
 #define MPC52xx_PSC_SR_CDE	0x0080
 #define MPC52xx_PSC_SR_RXRDY	0x0100
 #define MPC52xx_PSC_SR_RXFULL	0x0200
@@ -61,6 +65,12 @@
 #define MPC52xx_PSC_RXTX_FIFO_EMPTY	0x0001
 
 /* PSC interrupt status/mask bits */
+#define MPC52xx_PSC_IMR_UNEX_RX_SLOT 0x0001
+#define MPC52xx_PSC_IMR_DATA_VALID	0x0002
+#define MPC52xx_PSC_IMR_DATA_OVR	0x0004
+#define MPC52xx_PSC_IMR_CMD_SEND	0x0008
+#define MPC52xx_PSC_IMR_ERROR		0x0040
+#define MPC52xx_PSC_IMR_DEOF		0x0080
 #define MPC52xx_PSC_IMR_TXRDY		0x0100
 #define MPC52xx_PSC_IMR_RXRDY		0x0200
 #define MPC52xx_PSC_IMR_DB		0x0400
@@ -117,6 +127,7 @@
 #define MPC52xx_PSC_SICR_SIM_FIR		(0x6 << 24)
 #define MPC52xx_PSC_SICR_SIM_CODEC_24		(0x7 << 24)
 #define MPC52xx_PSC_SICR_SIM_CODEC_32		(0xf << 24)
+#define MPC52xx_PSC_SICR_AWR			(1 << 30)
 #define MPC52xx_PSC_SICR_GENCLK			(1 << 23)
 #define MPC52xx_PSC_SICR_I2S			(1 << 22)
 #define MPC52xx_PSC_SICR_CLKPOL			(1 << 21)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc5xxx.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc5xxx.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc5xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc5xxx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: John Rigby, <jrigby@freescale.com>, Friday Apr 13 2007
+ *
+ * Description:
+ * MPC5xxx Prototypes and definitions
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef __ASM_POWERPC_MPC5xxx_H__
+#define __ASM_POWERPC_MPC5xxx_H__
+
+extern unsigned long mpc5xxx_get_bus_frequency(struct device_node *node);
+
+#endif /* __ASM_POWERPC_MPC5xxx_H__ */
+
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc86xx.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc86xx.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/mpc86xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/mpc86xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * MPC86xx definitions
- *
- * Author: Jeff Brown
- *
- * Copyright 2004 Freescale Semiconductor, 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.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_POWERPC_MPC86xx_H__
-#define __ASM_POWERPC_MPC86xx_H__
-
-#include <asm/mmu.h>
-
-#ifdef CONFIG_PPC_86xx
-
-#define CPU0_BOOT_RELEASE 0x01000000
-#define CPU1_BOOT_RELEASE 0x02000000
-#define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
-#define MCM_PORT_CONFIG_OFFSET 0x1010
-
-/* Offset from CCSRBAR */
-#define MPC86xx_MCM_OFFSET      (0x00000)
-#define MPC86xx_MCM_SIZE        (0x02000)
-
-#endif /* CONFIG_PPC_86xx */
-#endif /* __ASM_POWERPC_MPC86xx_H__ */
-#endif /* __KERNEL__ */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/paca.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/paca.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/paca.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/paca.h	2009-09-09 18:13:59.000000000 -0400
@@ -43,6 +43,7 @@
  * processor.
  */
 struct paca_struct {
+#ifdef CONFIG_PPC_BOOK3S
 	/*
 	 * Because hw_cpu_id, unlike other paca fields, is accessed
 	 * routinely from other CPUs (from the IRQ code), we stick to
@@ -51,7 +52,7 @@
 	 */
 
 	struct lppaca *lppaca_ptr;	/* Pointer to LpPaca for PLIC */
-
+#endif /* CONFIG_PPC_BOOK3S */
 	/*
 	 * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c 
 	 * load lock_token and paca_index with a single lwz
@@ -64,13 +65,16 @@
 	u64 kernel_toc;			/* Kernel TOC address */
 	u64 kernelbase;			/* Base address of kernel */
 	u64 kernel_msr;			/* MSR while running in kernel */
+#ifdef CONFIG_PPC_STD_MMU_64
 	u64 stab_real;			/* Absolute address of segment table */
 	u64 stab_addr;			/* Virtual address of segment table */
+#endif /* CONFIG_PPC_STD_MMU_64 */
 	void *emergency_sp;		/* pointer to emergency stack */
 	u64 data_offset;		/* per cpu data offset */
 	s16 hw_cpu_id;			/* Physical processor number */
 	u8 cpu_start;			/* At startup, processor spins until */
 					/* this becomes non-zero. */
+#ifdef CONFIG_PPC_STD_MMU_64
 	struct slb_shadow *slb_shadow_ptr;
 
 	/*
@@ -81,11 +85,13 @@
 	u64 exmc[10];		/* used for machine checks */
 	u64 exslb[10];		/* used for SLB/segment table misses
  				 * on the linear mapping */
-
-	mm_context_t context;
+	/* SLB related definitions */
 	u16 vmalloc_sllp;
 	u16 slb_cache_ptr;
 	u16 slb_cache[SLB_CACHE_ENTRIES];
+#endif /* CONFIG_PPC_STD_MMU_64 */
+
+	mm_context_t context;
 
 	/*
 	 * then miscellaneous read-write fields
@@ -99,6 +105,7 @@
 	u8 soft_enabled;		/* irq soft-enable flag */
 	u8 hard_enabled;		/* set if irqs are enabled in MSR */
 	u8 io_sync;			/* writel() needs spin_unlock sync */
+	u8 perf_counter_pending;	/* PM interrupt while soft-disabled */
 
 	/* Stuff for accurate time accounting */
 	u64 user_time;			/* accumulated usermode TB ticks */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/page_32.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/page_32.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/page_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/page_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,7 @@
 static inline void clear_page(void *page) { clear_pages(page, 0); }
 extern void copy_page(void *to, void *from);
 
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #define PGD_T_LOG2	(__builtin_ffs(sizeof(pgd_t)) - 1)
 #define PTE_T_LOG2	(__builtin_ffs(sizeof(pte_t)) - 1)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/page_64.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/page_64.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/page_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/page_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -180,6 +180,6 @@
 	(test_thread_flag(TIF_32BIT) ? \
 	 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
 
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _ASM_POWERPC_PAGE_64_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/page.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -231,6 +231,11 @@
 		struct page *p);
 extern int page_is_ram(unsigned long pfn);
 
+#ifdef CONFIG_PPC_SMLPAR
+void arch_free_page(struct page *page, int order);
+#define HAVE_ARCH_FREE_PAGE
+#endif
+
 struct vm_area_struct;
 
 typedef struct page *pgtable_t;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pci-bridge.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pci-bridge.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pci-bridge.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pci-bridge.h	2009-09-09 18:13:59.000000000 -0400
@@ -86,17 +86,12 @@
 	void *io_base_alloc;
 #endif
 	resource_size_t io_base_phys;
-#ifndef CONFIG_PPC64
 	resource_size_t pci_io_size;
-#endif
 
 	/* Some machines (PReP) have a non 1:1 mapping of
 	 * the PCI memory space in the CPU bus space
 	 */
 	resource_size_t pci_mem_offset;
-#ifdef CONFIG_PPC64
-	unsigned long pci_io_size;
-#endif
 
 	/* Some machines have a special region to forward the ISA
 	 * "memory" cycles such as VGA memory regions. Left to 0
@@ -140,10 +135,12 @@
 	struct resource	io_resource;
 	struct resource mem_resources[3];
 	int global_number;		/* PCI domain number */
+
+	resource_size_t dma_window_base_cur;
+	resource_size_t dma_window_size;
+
 #ifdef CONFIG_PPC64
 	unsigned long buid;
-	unsigned long dma_window_base_cur;
-	unsigned long dma_window_size;
 
 	void *private_data;
 #endif	/* CONFIG_PPC64 */
@@ -185,7 +182,6 @@
 extern void setup_indirect_pci(struct pci_controller* hose,
 			       resource_size_t cfg_addr,
 			       resource_size_t cfg_data, u32 flags);
-extern void setup_grackle(struct pci_controller *hose);
 #else	/* CONFIG_PPC64 */
 
 /*
@@ -221,6 +217,7 @@
 #define PCI_DN(dn)	((struct pci_dn *) (dn)->data)
 
 extern struct device_node *fetch_dev_dn(struct pci_dev *dev);
+extern void * update_dn_pci_info(struct device_node *dn, void *data);
 
 /* Get a device_node from a pci_dev.  This code must be fast except
  * in the case where the sysdata is incorrect and needs to be fixed
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pci.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -195,19 +195,6 @@
 			struct resource *res,
 			struct pci_bus_region *region);
 
-static inline struct resource *pcibios_select_root(struct pci_dev *pdev,
-			struct resource *res)
-{
-	struct resource *root = NULL;
-
-	if (res->flags & IORESOURCE_IO)
-		root = &ioport_resource;
-	if (res->flags & IORESOURCE_MEM)
-		root = &iomem_resource;
-
-	return root;
-}
-
 extern void pcibios_claim_one_bus(struct pci_bus *b);
 
 extern void pcibios_finish_adding_to_bus(struct pci_bus *bus);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/perf_counter.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/perf_counter.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/perf_counter.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/perf_counter.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * Performance counter support - PowerPC-specific definitions.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/types.h>
+
+#include <asm/hw_irq.h>
+
+#define MAX_HWCOUNTERS		8
+#define MAX_EVENT_ALTERNATIVES	8
+#define MAX_LIMITED_HWCOUNTERS	2
+
+/*
+ * This struct provides the constants and functions needed to
+ * describe the PMU on a particular POWER-family CPU.
+ */
+struct power_pmu {
+	const char	*name;
+	int		n_counter;
+	int		max_alternatives;
+	unsigned long	add_fields;
+	unsigned long	test_adder;
+	int		(*compute_mmcr)(u64 events[], int n_ev,
+				unsigned int hwc[], unsigned long mmcr[]);
+	int		(*get_constraint)(u64 event, unsigned long *mskp,
+				unsigned long *valp);
+	int		(*get_alternatives)(u64 event, unsigned int flags,
+				u64 alt[]);
+	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
+	int		(*limited_pmc_event)(u64 event);
+	u32		flags;
+	int		n_generic;
+	int		*generic_events;
+	int		(*cache_events)[PERF_COUNT_HW_CACHE_MAX]
+			       [PERF_COUNT_HW_CACHE_OP_MAX]
+			       [PERF_COUNT_HW_CACHE_RESULT_MAX];
+};
+
+/*
+ * Values for power_pmu.flags
+ */
+#define PPMU_LIMITED_PMC5_6	1	/* PMC5/6 have limited function */
+#define PPMU_ALT_SIPR		2	/* uses alternate posn for SIPR/HV */
+
+/*
+ * Values for flags to get_alternatives()
+ */
+#define PPMU_LIMITED_PMC_OK	1	/* can put this on a limited PMC */
+#define PPMU_LIMITED_PMC_REQD	2	/* have to put this on a limited PMC */
+#define PPMU_ONLY_COUNT_RUN	4	/* only counting in run state */
+
+extern int register_power_pmu(struct power_pmu *);
+
+struct pt_regs;
+extern unsigned long perf_misc_flags(struct pt_regs *regs);
+extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
+
+#define PERF_COUNTER_INDEX_OFFSET	1
+
+/*
+ * Only override the default definitions in include/linux/perf_counter.h
+ * if we have hardware PMU support.
+ */
+#ifdef CONFIG_PPC_PERF_CTRS
+#define perf_misc_flags(regs)	perf_misc_flags(regs)
+#endif
+
+/*
+ * The power_pmu.get_constraint function returns a 32/64-bit value and
+ * a 32/64-bit mask that express the constraints between this event and
+ * other events.
+ *
+ * The value and mask are divided up into (non-overlapping) bitfields
+ * of three different types:
+ *
+ * Select field: this expresses the constraint that some set of bits
+ * in MMCR* needs to be set to a specific value for this event.  For a
+ * select field, the mask contains 1s in every bit of the field, and
+ * the value contains a unique value for each possible setting of the
+ * MMCR* bits.  The constraint checking code will ensure that two events
+ * that set the same field in their masks have the same value in their
+ * value dwords.
+ *
+ * Add field: this expresses the constraint that there can be at most
+ * N events in a particular class.  A field of k bits can be used for
+ * N <= 2^(k-1) - 1.  The mask has the most significant bit of the field
+ * set (and the other bits 0), and the value has only the least significant
+ * bit of the field set.  In addition, the 'add_fields' and 'test_adder'
+ * in the struct power_pmu for this processor come into play.  The
+ * add_fields value contains 1 in the LSB of the field, and the
+ * test_adder contains 2^(k-1) - 1 - N in the field.
+ *
+ * NAND field: this expresses the constraint that you may not have events
+ * in all of a set of classes.  (For example, on PPC970, you can't select
+ * events from the FPU, ISU and IDU simultaneously, although any two are
+ * possible.)  For N classes, the field is N+1 bits wide, and each class
+ * is assigned one bit from the least-significant N bits.  The mask has
+ * only the most-significant bit set, and the value has only the bit
+ * for the event's class set.  The test_adder has the least significant
+ * bit set in the field.
+ *
+ * If an event is not subject to the constraint expressed by a particular
+ * field, then it will have 0 in both the mask and value for that field.
+ */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgalloc-32.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgalloc-32.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgalloc-32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgalloc-32.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,7 @@
  */
 /* #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); }) */
 #define pmd_free(mm, x) 		do { } while (0)
-#define __pmd_free_tlb(tlb,x)		do { } while (0)
+#define __pmd_free_tlb(tlb,x,a)		do { } while (0)
 /* #define pgd_populate(mm, pmd, pte)      BUG() */
 
 #ifndef CONFIG_BOOKE
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgalloc-64.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgalloc-64.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgalloc-64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgalloc-64.h	2009-09-09 18:13:59.000000000 -0400
@@ -118,11 +118,11 @@
 		kmem_cache_free(pgtable_cache[cachenum], p);
 }
 
-#define __pmd_free_tlb(tlb, pmd) 	\
+#define __pmd_free_tlb(tlb, pmd,addr)		      \
 	pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
 		PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
 #ifndef CONFIG_PPC_64K_PAGES
-#define __pud_free_tlb(tlb, pud)	\
+#define __pud_free_tlb(tlb, pud, addr)		      \
 	pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
 		PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
 #endif /* CONFIG_PPC_64K_PAGES */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -38,14 +38,14 @@
 extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
 
 #ifdef CONFIG_SMP
-#define __pte_free_tlb(tlb,ptepage)	\
+#define __pte_free_tlb(tlb,ptepage,address)		\
 do { \
 	pgtable_page_dtor(ptepage); \
 	pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
-		PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \
+					PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \
 } while (0)
 #else
-#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, (pte))
+#define __pte_free_tlb(tlb, pte, address)	pte_free((tlb)->mm, (pte))
 #endif
 
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgtable-ppc64.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgtable-ppc64.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pgtable-ppc64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pgtable-ppc64.h	2009-09-09 18:13:59.000000000 -0400
@@ -31,9 +31,11 @@
 #error TASK_SIZE_USER64 exceeds pagetable range
 #endif
 
+#ifdef CONFIG_PPC_STD_MMU_64
 #if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
+#endif
 
 /*
  * Define the address range of the vmalloc VM area.
@@ -199,8 +201,11 @@
 	if (!huge)
 		assert_pte_locked(mm, addr);
 
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (old & _PAGE_HASHPTE)
 		hpte_need_flush(mm, addr, ptep, old, huge);
+#endif
+
 	return old;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ppc_asm.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ppc_asm.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ppc_asm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ppc_asm.h	2009-09-09 18:13:59.000000000 -0400
@@ -76,16 +76,6 @@
 				REST_10GPRS(22, base)
 #endif
 
-/*
- * Define what the VSX XX1 form instructions will look like, then add
- * the 128 bit load store instructions based on that.
- */
-#define VSX_XX1(xs, ra, rb)	(((xs) & 0x1f) << 21 | ((ra) << 16) |  \
-				 ((rb) << 11) | (((xs) >> 5)))
-
-#define STXVD2X(xs, ra, rb)	.long (0x7c000798 | VSX_XX1((xs), (ra), (rb)))
-#define LXVD2X(xs, ra, rb)	.long (0x7c000698 | VSX_XX1((xs), (ra), (rb)))
-
 #define SAVE_2GPRS(n, base)	SAVE_GPR(n, base); SAVE_GPR(n+1, base)
 #define SAVE_4GPRS(n, base)	SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
 #define SAVE_8GPRS(n, base)	SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ppc-opcode.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ppc-opcode.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ppc-opcode.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ppc-opcode.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 #define PPC_INST_LSWI			0x7c0004aa
 #define PPC_INST_LSWX			0x7c00042a
 #define PPC_INST_LWSYNC			0x7c2004ac
+#define PPC_INST_LXVD2X			0x7c000698
 #define PPC_INST_MCRXR			0x7c000400
 #define PPC_INST_MCRXR_MASK		0xfc0007fe
 #define PPC_INST_MFSPR_PVR		0x7c1f42a6
@@ -43,14 +44,18 @@
 
 #define PPC_INST_STSWI			0x7c0005aa
 #define PPC_INST_STSWX			0x7c00052a
+#define PPC_INST_STXVD2X		0x7c000798
+#define PPC_INST_TLBIE			0x7c000264
 #define PPC_INST_TLBILX			0x7c000024
 #define PPC_INST_WAIT			0x7c00007c
 
 /* macros to insert fields into opcodes */
-#define __PPC_RA(a)	((a & 0x1f) << 16)
-#define __PPC_RB(b)	((b & 0x1f) << 11)
-#define __PPC_T_TLB(t)	((t & 0x3) << 21)
-#define __PPC_WC(w)	((w & 0x3) << 21)
+#define __PPC_RA(a)	(((a) & 0x1f) << 16)
+#define __PPC_RB(b)	(((b) & 0x1f) << 11)
+#define __PPC_RS(s)	(((s) & 0x1f) << 21)
+#define __PPC_XS(s)	((((s) & 0x1f) << 21) | (((s) & 0x20) >> 5))
+#define __PPC_T_TLB(t)	(((t) & 0x3) << 21)
+#define __PPC_WC(w)	(((w) & 0x3) << 21)
 
 /* Deal with instructions that older assemblers aren't aware of */
 #define	PPC_DCBAL(a, b)		stringify_in_c(.long PPC_INST_DCBAL | \
@@ -69,5 +74,17 @@
 #define PPC_TLBILX_VA(a, b)	PPC_TLBILX(3, a, b)
 #define PPC_WAIT(w)		stringify_in_c(.long PPC_INST_WAIT | \
 					__PPC_WC(w))
+#define PPC_TLBIE(lp,a) 	stringify_in_c(.long PPC_INST_TLBIE | \
+					       __PPC_RB(a) | __PPC_RS(lp))
+
+/*
+ * Define what the VSX XX1 form instructions will look like, then add
+ * the 128 bit load store instructions based on that.
+ */
+#define VSX_XX1(s, a, b)	(__PPC_XS(s) | __PPC_RA(a) | __PPC_RB(b))
+#define STXVD2X(s, a, b)	stringify_in_c(.long PPC_INST_STXVD2X | \
+					       VSX_XX1((s), (a), (b)))
+#define LXVD2X(s, a, b)		stringify_in_c(.long PPC_INST_LXVD2X | \
+					       VSX_XX1((s), (a), (b)))
 
 #endif /* _ASM_POWERPC_PPC_OPCODE_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ps3gpu.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ps3gpu.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ps3gpu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ps3gpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ *  PS3 GPU declarations.
+ *
+ *  Copyright 2009 Sony 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; 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASM_POWERPC_PS3GPU_H
+#define _ASM_POWERPC_PS3GPU_H
+
+#include <linux/mutex.h>
+
+#include <asm/lv1call.h>
+
+
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC	0x101
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP	0x102
+
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP	0x600
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT		0x601
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC	0x602
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_CLOSE	0x603
+
+#define L1GPU_FB_BLIT_WAIT_FOR_COMPLETION	(1ULL << 32)
+
+#define L1GPU_DISPLAY_SYNC_HSYNC		1
+#define L1GPU_DISPLAY_SYNC_VSYNC		2
+
+
+/* mutex synchronizing GPU accesses and video mode changes */
+extern struct mutex ps3_gpu_mutex;
+
+
+static inline int lv1_gpu_display_sync(u64 context_handle, u64 head,
+				       u64 ddr_offset)
+{
+	return lv1_gpu_context_attribute(context_handle,
+					 L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					 head, ddr_offset, 0, 0);
+}
+
+static inline int lv1_gpu_display_flip(u64 context_handle, u64 head,
+				       u64 ddr_offset)
+{
+	return lv1_gpu_context_attribute(context_handle,
+					 L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					 head, ddr_offset, 0, 0);
+}
+
+static inline int lv1_gpu_fb_setup(u64 context_handle, u64 xdr_lpar,
+				   u64 xdr_size, u64 ioif_offset)
+{
+	return lv1_gpu_context_attribute(context_handle,
+					 L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
+					 xdr_lpar, xdr_size, ioif_offset, 0);
+}
+
+static inline int lv1_gpu_fb_blit(u64 context_handle, u64 ddr_offset,
+				  u64 ioif_offset, u64 sync_width, u64 pitch)
+{
+	return lv1_gpu_context_attribute(context_handle,
+					 L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
+					 ddr_offset, ioif_offset, sync_width,
+					 pitch);
+}
+
+static inline int lv1_gpu_fb_close(u64 context_handle)
+{
+	return lv1_gpu_context_attribute(context_handle,
+					 L1GPU_CONTEXT_ATTRIBUTE_FB_CLOSE, 0,
+					 0, 0, 0);
+}
+
+#endif /* _ASM_POWERPC_PS3GPU_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ps3.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ps3.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ps3.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ps3.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,13 @@
 extern u64 ps3_os_area_get_rtc_diff(void);
 extern void ps3_os_area_set_rtc_diff(u64 rtc_diff);
 
+struct ps3_os_area_flash_ops {
+	ssize_t (*read)(void *buf, size_t count, loff_t pos);
+	ssize_t (*write)(const void *buf, size_t count, loff_t pos);
+};
+
+extern void ps3_os_area_flash_register(const struct ps3_os_area_flash_ops *ops);
+
 /* dma routines */
 
 enum ps3_dma_page_size {
@@ -418,15 +425,15 @@
  * @data: Data to set
  */
 
-static inline void ps3_system_bus_set_driver_data(
+static inline void ps3_system_bus_set_drvdata(
 	struct ps3_system_bus_device *dev, void *data)
 {
-	dev->core.driver_data = data;
+	dev_set_drvdata(&dev->core, data);
 }
-static inline void *ps3_system_bus_get_driver_data(
+static inline void *ps3_system_bus_get_drvdata(
 	struct ps3_system_bus_device *dev)
 {
-	return dev->core.driver_data;
+	return dev_get_drvdata(&dev->core);
 }
 
 /* These two need global scope for get_dma_ops(). */
@@ -520,7 +527,4 @@
 u32 ps3_get_hw_thread_id(int cpu);
 u64 ps3_get_spe_id(void *arg);
 
-/* mutex synchronizing GPU accesses and video mode changes */
-extern struct mutex ps3_gpu_mutex;
-
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pte-hash64-64k.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pte-hash64-64k.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/pte-hash64-64k.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/pte-hash64-64k.h	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,8 @@
  * generic accessors and iterators here
  */
 #define __real_pte(e,p) 	((real_pte_t) { \
-	(e), pte_val(*((p) + PTRS_PER_PTE)) })
+			(e), ((e) & _PAGE_COMBO) ? \
+				(pte_val(*((p) + PTRS_PER_PTE))) : 0 })
 #define __rpte_to_hidx(r,index)	((pte_val((r).pte) & _PAGE_COMBO) ? \
         (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
 #define __rpte_to_pte(r)	((r).pte)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ptrace.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ptrace.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/ptrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/ptrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -135,7 +135,9 @@
  * These are defined as per linux/ptrace.h, which see.
  */
 #define arch_has_single_step()	(1)
+#define arch_has_block_step()	(!cpu_has_feature(CPU_FTR_601))
 extern void user_enable_single_step(struct task_struct *);
+extern void user_enable_block_step(struct task_struct *);
 extern void user_disable_single_step(struct task_struct *);
 
 #endif /* __ASSEMBLY__ */
@@ -288,4 +290,6 @@
 #define PPC_PTRACE_PEEKUSR_3264  0x91
 #define PPC_PTRACE_POKEUSR_3264  0x90
 
+#define PTRACE_SINGLEBLOCK	0x100	/* resume execution until next branch */
+
 #endif /* _ASM_POWERPC_PTRACE_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/qe.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/qe.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/qe.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/qe.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,7 @@
 #include <asm/cpm.h>
 #include <asm/immap_qe.h>
 
-#define QE_NUM_OF_SNUM	28
+#define QE_NUM_OF_SNUM	256	/* There are 256 serial number in QE */
 #define QE_NUM_OF_BRGS	16
 #define QE_NUM_OF_PORTS	1024
 
@@ -152,6 +152,9 @@
 int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
 int qe_get_snum(void);
 void qe_put_snum(u8 snum);
+unsigned int qe_get_num_of_risc(void);
+unsigned int qe_get_num_of_snums(void);
+
 /* we actually use cpm_muram implementation, define this for convenience */
 #define qe_muram_init cpm_muram_init
 #define qe_muram_alloc cpm_muram_alloc
@@ -231,12 +234,16 @@
 #define QE_ALIGNMENT_OF_PRAM	64
 
 /* RISC allocation */
-enum qe_risc_allocation {
-	QE_RISC_ALLOCATION_RISC1 = 1,	/* RISC 1 */
-	QE_RISC_ALLOCATION_RISC2 = 2,	/* RISC 2 */
-	QE_RISC_ALLOCATION_RISC1_AND_RISC2 = 3	/* Dynamically choose
-						   RISC 1 or RISC 2 */
-};
+#define QE_RISC_ALLOCATION_RISC1	0x1  /* RISC 1 */
+#define QE_RISC_ALLOCATION_RISC2	0x2  /* RISC 2 */
+#define QE_RISC_ALLOCATION_RISC3	0x4  /* RISC 3 */
+#define QE_RISC_ALLOCATION_RISC4	0x8  /* RISC 4 */
+#define QE_RISC_ALLOCATION_RISC1_AND_RISC2	(QE_RISC_ALLOCATION_RISC1 | \
+						 QE_RISC_ALLOCATION_RISC2)
+#define QE_RISC_ALLOCATION_FOUR_RISCS	(QE_RISC_ALLOCATION_RISC1 | \
+					 QE_RISC_ALLOCATION_RISC2 | \
+					 QE_RISC_ALLOCATION_RISC3 | \
+					 QE_RISC_ALLOCATION_RISC4)
 
 /* QE extended filtering Table Lookup Key Size */
 enum qe_fltr_tbl_lookup_key_size {
@@ -668,6 +675,8 @@
 #define UCC_GETH_UPSMR_RMM      0x00001000
 #define UCC_GETH_UPSMR_CAM      0x00000400
 #define UCC_GETH_UPSMR_BRO      0x00000200
+#define UCC_GETH_UPSMR_SMM	0x00000080
+#define UCC_GETH_UPSMR_SGMM	0x00000020
 
 /* UCC Transmit On Demand Register (UTODR) */
 #define UCC_SLOW_TOD	0x8000
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/reg_booke.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/reg_booke.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/reg_booke.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/reg_booke.h	2009-09-09 18:13:59.000000000 -0400
@@ -389,12 +389,14 @@
 #define ICCR_CACHE	1		/* Cacheable */
 
 /* Bit definitions for L1CSR0. */
+#define L1CSR0_CPE	0x00010000	/* Data Cache Parity Enable */
 #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_CPE	0x00010000	/* Instruction Cache Parity Enable */
 #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 */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/reg.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/reg.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -492,11 +492,13 @@
 #define   MMCR0_FCHV	0x00000001UL /* freeze conditions in hypervisor mode */
 #define SPRN_MMCR1	798
 #define SPRN_MMCRA	0x312
+#define   MMCRA_SDSYNC	0x80000000UL /* SDAR synced with SIAR */
 #define   MMCRA_SIHV	0x10000000UL /* state of MSR HV when SIAR set */
 #define   MMCRA_SIPR	0x08000000UL /* state of MSR PR when SIAR set */
 #define   MMCRA_SLOT	0x07000000UL /* SLOT bits (37-39) */
 #define   MMCRA_SLOT_SHIFT	24
 #define   MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
+#define   POWER6_MMCRA_SDSYNC 0x0000080000000000ULL	/* SDAR/SIAR synced */
 #define   POWER6_MMCRA_SIHV   0x0000040000000000ULL
 #define   POWER6_MMCRA_SIPR   0x0000020000000000ULL
 #define   POWER6_MMCRA_THRM	0x00000020UL
@@ -743,17 +745,18 @@
 			asm volatile("mfmsr %0" : "=r" (rval)); rval;})
 #ifdef CONFIG_PPC64
 #define __mtmsrd(v, l)	asm volatile("mtmsrd %0," __stringify(l) \
-				     : : "r" (v))
+				     : : "r" (v) : "memory")
 #define mtmsrd(v)	__mtmsrd((v), 0)
 #define mtmsr(v)	mtmsrd(v)
 #else
-#define mtmsr(v)	asm volatile("mtmsr %0" : : "r" (v))
+#define mtmsr(v)	asm volatile("mtmsr %0" : : "r" (v) : "memory")
 #endif
 
 #define mfspr(rn)	({unsigned long rval; \
 			asm volatile("mfspr %0," __stringify(rn) \
 				: "=r" (rval)); rval;})
-#define mtspr(rn, v)	asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
+#define mtspr(rn, v)	asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)\
+				     : "memory")
 
 #ifdef __powerpc64__
 #ifdef CONFIG_PPC_CELL
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/rtas.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/rtas.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/rtas.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/rtas.h	2009-09-09 18:13:59.000000000 -0400
@@ -58,7 +58,7 @@
 	unsigned long entry;		/* physical address pointer */
 	unsigned long base;		/* physical address pointer */
 	unsigned long size;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	struct rtas_args args;
 	struct device_node *dev;	/* virtual address pointer */
 };
@@ -245,5 +245,8 @@
 			(devfn << 8) | (reg & 0xff);
 }
 
+extern void __cpuinit rtas_give_timebase(void);
+extern void __cpuinit rtas_take_timebase(void);
+
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_RTAS_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/scatterlist.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/scatterlist.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/scatterlist.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/scatterlist.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,7 @@
 	unsigned int offset;
 	unsigned int length;
 
-	/* For TCE support */
+	/* For TCE or SWIOTLB support */
 	dma_addr_t dma_address;
 	u32 dma_length;
 };
@@ -34,11 +34,7 @@
  * is 0.
  */
 #define sg_dma_address(sg)	((sg)->dma_address)
-#ifdef __powerpc64__
 #define sg_dma_len(sg)		((sg)->dma_length)
-#else
-#define sg_dma_len(sg)		((sg)->length)
-#endif
 
 #ifdef __powerpc64__
 #define ISA_DMA_THRESHOLD	(~0UL)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/signal.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -94,7 +94,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 struct old_sigaction {
 	__sighandler_t sa_handler;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/swiotlb.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/swiotlb.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/swiotlb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/swiotlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __ASM_SWIOTLB_H
+#define __ASM_SWIOTLB_H
+
+#include <linux/swiotlb.h>
+
+extern struct dma_mapping_ops swiotlb_dma_ops;
+extern struct dma_mapping_ops swiotlb_pci_dma_ops;
+
+int swiotlb_arch_address_needs_mapping(struct device *, dma_addr_t,
+				       size_t size);
+
+static inline void dma_mark_clean(void *addr, size_t size) {}
+
+extern unsigned int ppc_swiotlb_enable;
+int __init swiotlb_setup_bus_notifier(void);
+
+#endif /* __ASM_SWIOTLB_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/systbl.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/systbl.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/systbl.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/systbl.h	2009-09-09 18:13:59.000000000 -0400
@@ -322,6 +322,7 @@
 SYSCALL_SPU(dup3)
 SYSCALL_SPU(pipe2)
 SYSCALL(inotify_init1)
-SYSCALL(ni_syscall)
+SYSCALL_SPU(perf_counter_open)
 COMPAT_SYS_SPU(preadv)
 COMPAT_SYS_SPU(pwritev)
+COMPAT_SYS(rt_tgsigqueueinfo)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/system.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/system.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -211,7 +211,7 @@
 
 extern unsigned int rtas_data;
 extern int mem_init_done;	/* set on boot once kmalloc can be called */
-extern int init_bootmem_done;	/* set on !NUMA once bootmem is available */
+extern int init_bootmem_done;	/* set once bootmem is available */
 extern phys_addr_t memory_limit;
 extern unsigned long klimit;
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/termios.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -78,7 +78,7 @@
 
 #ifdef __KERNEL__
 
-#include <asm-generic/termios.h>
+#include <asm-generic/termios-base.h>
 
 #endif	/* __KERNEL__ */
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -46,15 +46,13 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
 	.task =		&tsk,			\
 	.exec_domain =	&default_exec_domain,	\
 	.cpu =		0,			\
-	.preempt_count = 1,			\
+	.preempt_count = INIT_PREEMPT_COUNT,	\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/types.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -40,15 +40,6 @@
 #endif /* __ASSEMBLY__ */
 
 #ifdef __KERNEL__
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __powerpc64__
-#define BITS_PER_LONG 64
-#else
-#define BITS_PER_LONG 32
-#endif
-
 #ifndef __ASSEMBLY__
 
 typedef __vector128 vector128;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -341,12 +341,14 @@
 #define __NR_dup3		316
 #define __NR_pipe2		317
 #define __NR_inotify_init1	318
+#define __NR_perf_counter_open	319
 #define __NR_preadv		320
 #define __NR_pwritev		321
+#define __NR_rt_tgsigqueueinfo	322
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls		322
+#define __NR_syscalls		323
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/include/asm/xilinx_pci.h linux-libre-2.6.31-gnu/arch/powerpc/include/asm/xilinx_pci.h
--- linux-libre-2.6.30-gnu/arch/powerpc/include/asm/xilinx_pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/include/asm/xilinx_pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ * Xilinx pci external definitions
+ *
+ * Copyright 2009 Roderick Colenbrander
+ * Copyright 2009 Secret Lab Technologies Ltd.
+ *
+ * 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.
+ */
+
+#ifndef INCLUDE_XILINX_PCI
+#define INCLUDE_XILINX_PCI
+
+#ifdef CONFIG_XILINX_PCI
+extern void __init xilinx_pci_init(void);
+#else
+static inline void __init xilinx_pci_init(void) { return; }
+#endif
+
+#endif /* INCLUDE_XILINX_PCI */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/Kconfig linux-libre-2.6.31-gnu/arch/powerpc/Kconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -42,6 +42,10 @@
 	bool
 	default y
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+	bool
+	default y
+
 config HAVE_SETUP_PER_CPU_AREA
 	def_bool PPC64
 
@@ -58,7 +62,6 @@
 
 config TRACE_IRQFLAGS_SUPPORT
 	bool
-	depends on PPC64
 	default y
 
 config LOCKDEP_SUPPORT
@@ -89,10 +92,6 @@
 	bool
 	default y
 
-config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
-
 config GENERIC_FIND_NEXT_BIT
 	bool
 	default y
@@ -125,6 +124,8 @@
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_OPROFILE
 	select HAVE_SYSCALL_WRAPPERS if PPC64
+	select GENERIC_ATOMIC64 if PPC32
+	select HAVE_PERF_COUNTERS
 
 config EARLY_PRINTK
 	bool
@@ -296,9 +297,19 @@
 config IOMMU_HELPER
 	def_bool PPC64
 
+config SWIOTLB
+	bool "SWIOTLB support"
+	default n
+	select IOMMU_HELPER
+	---help---
+	  Support for IO bounce buffering for systems without an IOMMU.
+	  This allows us to DMA to the full physical address space on
+	  platforms where the size of a physical address is larger
+	  than the bus address.  Not all platforms support this.
+
 config PPC_NEED_DMA_SYNC_OPS
 	def_bool y
-	depends on NOT_COHERENT_CACHE
+	depends on (NOT_COHERENT_CACHE || SWIOTLB)
 
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/Kconfig.debug linux-libre-2.6.31-gnu/arch/powerpc/Kconfig.debug
--- linux-libre-2.6.30-gnu/arch/powerpc/Kconfig.debug	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/Kconfig.debug	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,23 @@
 
 source "lib/Kconfig.debug"
 
+config PPC_DISABLE_WERROR
+	bool "Don't build arch/powerpc code with -Werror"
+	default n
+	help
+	  This option tells the compiler NOT to build the code under
+	  arch/powerpc with the -Werror flag (which means warnings
+	  are treated as errors).
+
+	  Only enable this if you are hitting a build failure in the
+	  arch/powerpc code caused by a warning, and you don't feel
+	  inclined to fix it.
+
+config PPC_WERROR
+	bool
+	depends on !PPC_DISABLE_WERROR
+	default y
+
 config PRINT_STACK_DEPTH
 	int "Stack depth to print" if DEBUG_KERNEL
 	default 64
@@ -41,6 +58,19 @@
 	  This option will add a small amount of overhead to all hypervisor
 	  calls.
 
+config PPC_EMULATED_STATS
+	bool "Emulated instructions tracking"
+	depends on DEBUG_FS
+	help
+	  Adds code to keep track of the number of instructions that are
+	  emulated by the in-kernel emulator. Counters for the various classes
+	  of emulated instructions are available under
+	  powerpc/emulated_instructions/ in the root of the debugfs file
+	  system. Optionally (controlled by
+	  powerpc/emulated_instructions/do_warn in debugfs), rate-limited
+	  warnings can be printed to the console when instructions are
+	  emulated.
+
 config CODE_PATCHING_SELFTEST
 	bool "Run self-tests of the code-patching code."
 	depends on DEBUG_KERNEL
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/align.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/align.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/align.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/align.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 #include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/cputable.h>
+#include <asm/emulated_ops.h>
 
 struct aligninfo {
 	unsigned char len;
@@ -730,8 +731,10 @@
 	areg = dsisr & 0x1f;		/* register to update */
 
 #ifdef CONFIG_SPE
-	if ((instr >> 26) == 0x4)
+	if ((instr >> 26) == 0x4) {
+		PPC_WARN_EMULATED(spe);
 		return emulate_spe(regs, reg, instr);
+	}
 #endif
 
 	instr = (dsisr >> 10) & 0x7f;
@@ -783,23 +786,28 @@
 			flags |= SPLT;
 			nb = 8;
 		}
+		PPC_WARN_EMULATED(vsx);
 		return emulate_vsx(addr, reg, areg, regs, flags, nb);
 	}
 #endif
 	/* A size of 0 indicates an instruction we don't support, with
 	 * the exception of DCBZ which is handled as a special case here
 	 */
-	if (instr == DCBZ)
+	if (instr == DCBZ) {
+		PPC_WARN_EMULATED(dcbz);
 		return emulate_dcbz(regs, addr);
+	}
 	if (unlikely(nb == 0))
 		return 0;
 
 	/* Load/Store Multiple instructions are handled in their own
 	 * function
 	 */
-	if (flags & M)
+	if (flags & M) {
+		PPC_WARN_EMULATED(multiple);
 		return emulate_multiple(regs, addr, reg, nb,
 					flags, instr, swiz);
+	}
 
 	/* Verify the address of the operand */
 	if (unlikely(user_mode(regs) &&
@@ -816,8 +824,12 @@
 	}
 
 	/* Special case for 16-byte FP loads and stores */
-	if (nb == 16)
+	if (nb == 16) {
+		PPC_WARN_EMULATED(fp_pair);
 		return emulate_fp_pair(addr, reg, flags);
+	}
+
+	PPC_WARN_EMULATED(unaligned);
 
 	/* If we are loading, get the data from user space, else
 	 * get it from register values
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/asm-offsets.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/asm-offsets.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/asm-offsets.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/asm-offsets.c	2009-09-09 18:13:59.000000000 -0400
@@ -122,8 +122,6 @@
 	DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack));
 	DEFINE(PACACURRENT, offsetof(struct paca_struct, __current));
 	DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr));
-	DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real));
-	DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr));
 	DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
 	DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
 	DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
@@ -131,35 +129,31 @@
 	DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
 	DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
 	DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
-	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
-	DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
+	DEFINE(PACAPERFPEND, offsetof(struct paca_struct, perf_counter_pending));
 	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
-	DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
 #ifdef CONFIG_PPC_MM_SLICES
 	DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
 					    context.low_slices_psize));
 	DEFINE(PACAHIGHSLICEPSIZE, offsetof(struct paca_struct,
 					    context.high_slices_psize));
 	DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def));
+#endif /* CONFIG_PPC_MM_SLICES */
+#ifdef CONFIG_PPC_STD_MMU_64
+	DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real));
+	DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr));
+	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
+	DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
+	DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
+#ifdef CONFIG_PPC_MM_SLICES
 	DEFINE(MMUPSIZESLLP, offsetof(struct mmu_psize_def, sllp));
 #else
 	DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
-
 #endif /* CONFIG_PPC_MM_SLICES */
 	DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
 	DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
 	DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
-	DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
 	DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr));
-	DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
-	DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
-	DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
-	DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
-	DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
 	DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
-	DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
-	DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
-
 	DEFINE(SLBSHADOW_STACKVSID,
 	       offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
 	DEFINE(SLBSHADOW_STACKESID,
@@ -169,6 +163,15 @@
 	DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
 	DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
 	DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
+#endif /* CONFIG_PPC_STD_MMU_64 */
+	DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
+	DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
+	DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
+	DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
+	DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
+	DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
+	DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
+	DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
 #endif /* CONFIG_PPC64 */
 
 	/* RTAS */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/cpu_setup_6xx.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/cpu_setup_6xx.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/cpu_setup_6xx.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/cpu_setup_6xx.S	2009-09-09 18:13:59.000000000 -0400
@@ -239,6 +239,9 @@
 	ori	r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE
 	ori	r11,r11,HID0_LRSTK | HID0_BTIC
 	oris	r11,r11,HID0_DPM@h
+BEGIN_MMU_FTR_SECTION
+	oris	r11,r11,HID0_HIGH_BAT@h
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
 BEGIN_FTR_SECTION
 	xori	r11,r11,HID0_BTIC
 END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,40 @@
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
 
+_GLOBAL(__e500_icache_setup)
+	mfspr	r0, SPRN_L1CSR1
+	andi.	r3, r0, L1CSR1_ICE
+	bnelr				/* Already enabled */
+	oris	r0, r0, L1CSR1_CPE@h
+	ori	r0, r0, (L1CSR1_ICFI | L1CSR1_ICLFR |  L1CSR1_ICE)
+	mtspr	SPRN_L1CSR1, r0		/* Enable I-Cache */
+	isync
+	blr
+
+_GLOBAL(__e500_dcache_setup)
+	mfspr	r0, SPRN_L1CSR0
+	andi.	r3, r0, L1CSR0_DCE
+	bnelr				/* Already enabled */
+	msync
+	isync
+	li	r0, 0
+	mtspr	SPRN_L1CSR0, r0		/* Disable */
+	msync
+	isync
+	li	r0, (L1CSR0_DCFI | L1CSR0_CLFC)
+	mtspr	SPRN_L1CSR0, r0		/* Invalidate */
+	isync
+1:	mfspr	r0, SPRN_L1CSR0
+	andi.	r3, r0, L1CSR0_CLFC
+	bne+	1b			/* Wait for lock bits reset */
+	oris	r0, r0, L1CSR0_CPE@h
+	ori	r0, r0, L1CSR0_DCE
+	msync
+	isync
+	mtspr	SPRN_L1CSR0, r0		/* Enable */
+	isync
+	blr
+
 _GLOBAL(__setup_cpu_e200)
 	/* enable dedicated debug exception handling resources (Debug APU) */
 	mfspr	r3,SPRN_HID0
@@ -25,7 +59,16 @@
 	b	__setup_e200_ivors
 _GLOBAL(__setup_cpu_e500v1)
 _GLOBAL(__setup_cpu_e500v2)
-	b	__setup_e500_ivors
+	mflr	r4
+	bl	__e500_icache_setup
+	bl	__e500_dcache_setup
+	bl	__setup_e500_ivors
+	mtlr	r4
+	blr
 _GLOBAL(__setup_cpu_e500mc)
-	b	__setup_e500mc_ivors
-
+	mflr	r4
+	bl	__e500_icache_setup
+	bl	__e500_dcache_setup
+	bl	__setup_e500mc_ivors
+	mtlr	r4
+	blr
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/cputable.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/cputable.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/cputable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/cputable.c	2009-09-09 18:13:59.000000000 -0400
@@ -427,7 +427,8 @@
 		.cpu_name		= "POWER7 (architected)",
 		.cpu_features		= CPU_FTRS_POWER7,
 		.cpu_user_features	= COMMON_USER_POWER7,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
+		.mmu_features		= MMU_FTR_HPTE_TABLE |
+			MMU_FTR_TLBIE_206,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.machine_check		= machine_check_generic,
@@ -441,7 +442,8 @@
 		.cpu_name		= "POWER7 (raw)",
 		.cpu_features		= CPU_FTRS_POWER7,
 		.cpu_user_features	= COMMON_USER_POWER7,
-		.mmu_features		= MMU_FTR_HPTE_TABLE,
+		.mmu_features		= MMU_FTR_HPTE_TABLE |
+			MMU_FTR_TLBIE_206,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/dma.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/dma.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,6 +7,7 @@
 
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/lmb.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
 
@@ -19,7 +20,7 @@
  * default the offset is PCI_DRAM_OFFSET.
  */
 
-static unsigned long get_dma_direct_offset(struct device *dev)
+unsigned long get_dma_direct_offset(struct device *dev)
 {
 	if (dev)
 		return (unsigned long)dev->archdata.dma_data;
@@ -90,11 +91,10 @@
 static int dma_direct_dma_supported(struct device *dev, u64 mask)
 {
 #ifdef CONFIG_PPC64
-	/* Could be improved to check for memory though it better be
-	 * done via some global so platforms can set the limit in case
+	/* Could be improved so platforms can set the limit in case
 	 * they have limited DMA windows
 	 */
-	return mask >= DMA_BIT_MASK(32);
+	return mask >= (lmb_end_of_DRAM() - 1);
 #else
 	return 1;
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/dma-swiotlb.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/dma-swiotlb.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/dma-swiotlb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/dma-swiotlb.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,163 @@
+/*
+ * Contains routines needed to support swiotlb for ppc.
+ *
+ * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
+ *
+ * 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/dma-mapping.h>
+#include <linux/pfn.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/swiotlb.h>
+#include <asm/dma.h>
+#include <asm/abs_addr.h>
+
+int swiotlb __read_mostly;
+unsigned int ppc_swiotlb_enable;
+
+void *swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t addr)
+{
+	unsigned long pfn = PFN_DOWN(swiotlb_bus_to_phys(hwdev, addr));
+	void *pageaddr = page_address(pfn_to_page(pfn));
+
+	if (pageaddr != NULL)
+		return pageaddr + (addr % PAGE_SIZE);
+	return NULL;
+}
+
+dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
+{
+	return paddr + get_dma_direct_offset(hwdev);
+}
+
+phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
+
+{
+	return baddr - get_dma_direct_offset(hwdev);
+}
+
+/*
+ * Determine if an address needs bounce buffering via swiotlb.
+ * Going forward I expect the swiotlb code to generalize on using
+ * a dma_ops->addr_needs_map, and this function will move from here to the
+ * generic swiotlb code.
+ */
+int
+swiotlb_arch_address_needs_mapping(struct device *hwdev, dma_addr_t addr,
+				   size_t size)
+{
+	struct dma_mapping_ops *dma_ops = get_dma_ops(hwdev);
+
+	BUG_ON(!dma_ops);
+	return dma_ops->addr_needs_map(hwdev, addr, size);
+}
+
+/*
+ * Determine if an address is reachable by a pci device, or if we must bounce.
+ */
+static int
+swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
+{
+	u64 mask = dma_get_mask(hwdev);
+	dma_addr_t max;
+	struct pci_controller *hose;
+	struct pci_dev *pdev = to_pci_dev(hwdev);
+
+	hose = pci_bus_to_host(pdev->bus);
+	max = hose->dma_window_base_cur + hose->dma_window_size;
+
+	/* check that we're within mapped pci window space */
+	if ((addr + size > max) | (addr < hose->dma_window_base_cur))
+		return 1;
+
+	return !is_buffer_dma_capable(mask, addr, size);
+}
+
+static int
+swiotlb_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
+{
+	return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
+}
+
+
+/*
+ * At the moment, all platforms that use this code only require
+ * swiotlb to be used if we're operating on HIGHMEM.  Since
+ * we don't ever call anything other than map_sg, unmap_sg,
+ * map_page, and unmap_page on highmem, use normal dma_ops
+ * for everything else.
+ */
+struct dma_mapping_ops swiotlb_dma_ops = {
+	.alloc_coherent = dma_direct_alloc_coherent,
+	.free_coherent = dma_direct_free_coherent,
+	.map_sg = swiotlb_map_sg_attrs,
+	.unmap_sg = swiotlb_unmap_sg_attrs,
+	.dma_supported = swiotlb_dma_supported,
+	.map_page = swiotlb_map_page,
+	.unmap_page = swiotlb_unmap_page,
+	.addr_needs_map = swiotlb_addr_needs_map,
+	.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+	.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = swiotlb_sync_sg_for_device
+};
+
+struct dma_mapping_ops swiotlb_pci_dma_ops = {
+	.alloc_coherent = dma_direct_alloc_coherent,
+	.free_coherent = dma_direct_free_coherent,
+	.map_sg = swiotlb_map_sg_attrs,
+	.unmap_sg = swiotlb_unmap_sg_attrs,
+	.dma_supported = swiotlb_dma_supported,
+	.map_page = swiotlb_map_page,
+	.unmap_page = swiotlb_unmap_page,
+	.addr_needs_map = swiotlb_pci_addr_needs_map,
+	.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+	.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = swiotlb_sync_sg_for_device
+};
+
+static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
+				  unsigned long action, void *data)
+{
+	struct device *dev = data;
+
+	/* We are only intereted in device addition */
+	if (action != BUS_NOTIFY_ADD_DEVICE)
+		return 0;
+
+	/* May need to bounce if the device can't address all of DRAM */
+	if (dma_get_mask(dev) < lmb_end_of_DRAM())
+		set_dma_ops(dev, &swiotlb_dma_ops);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ppc_swiotlb_plat_bus_notifier = {
+	.notifier_call = ppc_swiotlb_bus_notify,
+	.priority = 0,
+};
+
+static struct notifier_block ppc_swiotlb_of_bus_notifier = {
+	.notifier_call = ppc_swiotlb_bus_notify,
+	.priority = 0,
+};
+
+int __init swiotlb_setup_bus_notifier(void)
+{
+	bus_register_notifier(&platform_bus_type,
+			      &ppc_swiotlb_plat_bus_notifier);
+	bus_register_notifier(&of_platform_bus_type,
+			      &ppc_swiotlb_of_bus_notifier);
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/entry_32.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/entry_32.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/entry_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/entry_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -191,11 +191,49 @@
 	mflr	r9
 	lwz	r11,0(r9)		/* virtual address of handler */
 	lwz	r9,4(r9)		/* where to go when done */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	lis	r12,reenable_mmu@h
+	ori	r12,r12,reenable_mmu@l
+	mtspr	SPRN_SRR0,r12
+	mtspr	SPRN_SRR1,r10
+	SYNC
+	RFI
+reenable_mmu:				/* re-enable mmu so we can */
+	mfmsr	r10
+	lwz	r12,_MSR(r1)
+	xor	r10,r10,r12
+	andi.	r10,r10,MSR_EE		/* Did EE change? */
+	beq	1f
+
+	/* Save handler and return address into the 2 unused words
+	 * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything
+	 * else can be recovered from the pt_regs except r3 which for
+	 * normal interrupts has been set to pt_regs and for syscalls
+	 * is an argument, so we temporarily use ORIG_GPR3 to save it
+	 */
+	stw	r9,8(r1)
+	stw	r11,12(r1)
+	stw	r3,ORIG_GPR3(r1)
+	bl	trace_hardirqs_off
+	lwz	r0,GPR0(r1)
+	lwz	r3,ORIG_GPR3(r1)
+	lwz	r4,GPR4(r1)
+	lwz	r5,GPR5(r1)
+	lwz	r6,GPR6(r1)
+	lwz	r7,GPR7(r1)
+	lwz	r8,GPR8(r1)
+	lwz	r9,8(r1)
+	lwz	r11,12(r1)
+1:	mtctr	r11
+	mtlr	r9
+	bctr				/* jump to handler */
+#else /* CONFIG_TRACE_IRQFLAGS */
 	mtspr	SPRN_SRR0,r11
 	mtspr	SPRN_SRR1,r10
 	mtlr	r9
 	SYNC
 	RFI				/* jump to handler, enable MMU */
+#endif /* CONFIG_TRACE_IRQFLAGS */
 
 #if defined (CONFIG_6xx) || defined(CONFIG_E500)
 4:	rlwinm	r12,r12,0,~_TLF_NAPPING
@@ -251,6 +289,31 @@
 #ifdef SHOW_SYSCALLS
 	bl	do_show_syscall
 #endif /* SHOW_SYSCALLS */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	/* Return from syscalls can (and generally will) hard enable
+	 * interrupts. You aren't supposed to call a syscall with
+	 * interrupts disabled in the first place. However, to ensure
+	 * that we get it right vs. lockdep if it happens, we force
+	 * that hard enable here with appropriate tracing if we see
+	 * that we have been called with interrupts off
+	 */
+	mfmsr	r11
+	andi.	r12,r11,MSR_EE
+	bne+	1f
+	/* We came in with interrupts disabled, we enable them now */
+	bl	trace_hardirqs_on
+	mfmsr	r11
+	lwz	r0,GPR0(r1)
+	lwz	r3,GPR3(r1)
+	lwz	r4,GPR4(r1)
+	ori	r11,r11,MSR_EE
+	lwz	r5,GPR5(r1)
+	lwz	r6,GPR6(r1)
+	lwz	r7,GPR7(r1)
+	lwz	r8,GPR8(r1)
+	mtmsr	r11
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
 	rlwinm	r10,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
 	lwz	r11,TI_FLAGS(r10)
 	andi.	r11,r11,_TIF_SYSCALL_T_OR_A
@@ -275,6 +338,7 @@
 	rlwinm	r12,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
 	/* disable interrupts so current_thread_info()->flags can't change */
 	LOAD_MSR_KERNEL(r10,MSR_KERNEL)	/* doesn't include MSR_EE */
+	/* Note: We don't bother telling lockdep about it */
 	SYNC
 	MTMSRD(r10)
 	lwz	r9,TI_FLAGS(r12)
@@ -288,6 +352,19 @@
 	oris	r11,r11,0x1000	/* Set SO bit in CR */
 	stw	r11,_CCR(r1)
 syscall_exit_cont:
+	lwz	r8,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	/* If we are going to return from the syscall with interrupts
+	 * off, we trace that here. It shouldn't happen though but we
+	 * want to catch the bugger if it does right ?
+	 */
+	andi.	r10,r8,MSR_EE
+	bne+	1f
+	stw	r3,GPR3(r1)
+	bl      trace_hardirqs_off
+	lwz	r3,GPR3(r1)
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 	/* If the process has its own DBCR0 value, load it up.  The internal
 	   debug mode bit tells us that dbcr0 should be loaded. */
@@ -311,7 +388,6 @@
 	mtlr	r4
 	mtcr	r5
 	lwz	r7,_NIP(r1)
-	lwz	r8,_MSR(r1)
 	FIX_SRR1(r8, r0)
 	lwz	r2,GPR2(r1)
 	lwz	r1,GPR1(r1)
@@ -394,7 +470,9 @@
 	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
 	beq	ret_from_except
 
-	/* Re-enable interrupts */
+	/* Re-enable interrupts. There is no need to trace that with
+	 * lockdep as we are supposed to have IRQs on at this point
+	 */
 	ori	r10,r10,MSR_EE
 	SYNC
 	MTMSRD(r10)
@@ -705,6 +783,7 @@
 	/* Hard-disable interrupts so that current_thread_info()->flags
 	 * can't change between when we test it and when we return
 	 * from the interrupt. */
+	/* Note: We don't bother telling lockdep about it */
 	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
 	SYNC			/* Some chip revs have problems here... */
 	MTMSRD(r10)		/* disable interrupts */
@@ -744,11 +823,24 @@
 	beq+	restore
 	andi.	r0,r3,MSR_EE	/* interrupts off? */
 	beq	restore		/* don't schedule if so */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	/* Lockdep thinks irqs are enabled, we need to call
+	 * preempt_schedule_irq with IRQs off, so we inform lockdep
+	 * now that we -did- turn them off already
+	 */
+	bl	trace_hardirqs_off
+#endif
 1:	bl	preempt_schedule_irq
 	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
 	lwz	r3,TI_FLAGS(r9)
 	andi.	r0,r3,_TIF_NEED_RESCHED
 	bne-	1b
+#ifdef CONFIG_TRACE_IRQFLAGS
+	/* And now, to properly rebalance the above, we tell lockdep they
+	 * are being turned back on, which will happen when we return
+	 */
+	bl	trace_hardirqs_on
+#endif
 #else
 resume_kernel:
 #endif /* CONFIG_PREEMPT */
@@ -765,6 +857,28 @@
 	stw	r6,icache_44x_need_flush@l(r4)
 1:
 #endif  /* CONFIG_44x */
+
+	lwz	r9,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	/* Lockdep doesn't know about the fact that IRQs are temporarily turned
+	 * off in this assembly code while peeking at TI_FLAGS() and such. However
+	 * we need to inform it if the exception turned interrupts off, and we
+	 * are about to trun them back on.
+	 *
+	 * The problem here sadly is that we don't know whether the exceptions was
+	 * one that turned interrupts off or not. So we always tell lockdep about
+	 * turning them on here when we go back to wherever we came from with EE
+	 * on, even if that may meen some redudant calls being tracked. Maybe later
+	 * we could encode what the exception did somewhere or test the exception
+	 * type in the pt_regs but that sounds overkill
+	 */
+	andi.	r10,r9,MSR_EE
+	beq	1f
+	bl	trace_hardirqs_on
+	lwz	r9,_MSR(r1)
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
+
 	lwz	r0,GPR0(r1)
 	lwz	r2,GPR2(r1)
 	REST_4GPRS(3, r1)
@@ -782,7 +896,6 @@
 	stwcx.	r0,0,r1			/* to clear the reservation */
 
 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-	lwz	r9,_MSR(r1)
 	andi.	r10,r9,MSR_RI		/* check if this exception occurred */
 	beql	nonrecoverable		/* at a bad place (MSR:RI = 0) */
 
@@ -805,7 +918,6 @@
 	MTMSRD(r10)		/* clear the RI bit */
 	.globl exc_exit_restart
 exc_exit_restart:
-	lwz	r9,_MSR(r1)
 	lwz	r12,_NIP(r1)
 	FIX_SRR1(r9,r10)
 	mtspr	SPRN_SRR0,r12
@@ -1035,11 +1147,18 @@
 	beq	do_user_signal
 
 do_resched:			/* r10 contains MSR_KERNEL here */
+	/* Note: We don't need to inform lockdep that we are enabling
+	 * interrupts here. As far as it knows, they are already enabled
+	 */
 	ori	r10,r10,MSR_EE
 	SYNC
 	MTMSRD(r10)		/* hard-enable interrupts */
 	bl	schedule
 recheck:
+	/* Note: And we don't tell it we are disabling them again
+	 * neither. Those disable/enable cycles used to peek at
+	 * TI_FLAGS aren't advertised.
+	 */
 	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
 	SYNC
 	MTMSRD(r10)		/* disable interrupts */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/entry_64.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/entry_64.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/entry_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/entry_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -526,6 +526,15 @@
 2:
 	TRACE_AND_RESTORE_IRQ(r5);
 
+#ifdef CONFIG_PERF_COUNTERS
+	/* check paca->perf_counter_pending if we're enabling ints */
+	lbz	r3,PACAPERFPEND(r13)
+	and.	r3,r3,r5
+	beq	27f
+	bl	.perf_counter_do_pending
+27:
+#endif /* CONFIG_PERF_COUNTERS */
+
 	/* extract EE bit and use it to restore paca->hard_enabled */
 	ld	r3,_MSR(r1)
 	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/exceptions-64s.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/exceptions-64s.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/exceptions-64s.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,978 @@
+/*
+ * This file contains the 64-bit "server" PowerPC variant
+ * of the low level exception handling including exception
+ * vectors, exception return, part of the slb and stab
+ * handling and other fixed offset specific things.
+ *
+ * This file is meant to be #included from head_64.S due to
+ * position dependant assembly.
+ *
+ * Most of this originates from head_64.S and thus has the same
+ * copyright history.
+ *
+ */
+
+/*
+ * We layout physical memory as follows:
+ * 0x0000 - 0x00ff : Secondary processor spin code
+ * 0x0100 - 0x2fff : pSeries Interrupt prologs
+ * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs
+ * 0x6000 - 0x6fff : Initial (CPU0) segment table
+ * 0x7000 - 0x7fff : FWNMI data area
+ * 0x8000 -        : Early init and support code
+ */
+
+
+/*
+ *   SPRG Usage
+ *
+ *   Register	Definition
+ *
+ *   SPRG0	reserved for hypervisor
+ *   SPRG1	temp - used to save gpr
+ *   SPRG2	temp - used to save gpr
+ *   SPRG3	virt addr of paca
+ */
+
+/*
+ * This is the start of the interrupt handlers for pSeries
+ * This code runs with relocation off.
+ * Code from here to __end_interrupts gets copied down to real
+ * address 0x100 when we are running a relocatable kernel.
+ * Therefore any relative branches in this section must only
+ * branch to labels in this section.
+ */
+	. = 0x100
+	.globl __start_interrupts
+__start_interrupts:
+
+	STD_EXCEPTION_PSERIES(0x100, system_reset)
+
+	. = 0x200
+_machine_check_pSeries:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+
+	. = 0x300
+	.globl data_access_pSeries
+data_access_pSeries:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13
+BEGIN_FTR_SECTION
+	mtspr	SPRN_SPRG2,r12
+	mfspr	r13,SPRN_DAR
+	mfspr	r12,SPRN_DSISR
+	srdi	r13,r13,60
+	rlwimi	r13,r12,16,0x20
+	mfcr	r12
+	cmpwi	r13,0x2c
+	beq	do_stab_bolted_pSeries
+	mtcrf	0x80,r12
+	mfspr	r12,SPRN_SPRG2
+END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common)
+
+	. = 0x380
+	.globl data_access_slb_pSeries
+data_access_slb_pSeries:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13
+	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */
+	std	r3,PACA_EXSLB+EX_R3(r13)
+	mfspr	r3,SPRN_DAR
+	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
+	mfcr	r9
+#ifdef __DISABLED__
+	/* Keep that around for when we re-implement dynamic VSIDs */
+	cmpdi	r3,0
+	bge	slb_miss_user_pseries
+#endif /* __DISABLED__ */
+	std	r10,PACA_EXSLB+EX_R10(r13)
+	std	r11,PACA_EXSLB+EX_R11(r13)
+	std	r12,PACA_EXSLB+EX_R12(r13)
+	mfspr	r10,SPRN_SPRG1
+	std	r10,PACA_EXSLB+EX_R13(r13)
+	mfspr	r12,SPRN_SRR1		/* and SRR1 */
+#ifndef CONFIG_RELOCATABLE
+	b	.slb_miss_realmode
+#else
+	/*
+	 * We can't just use a direct branch to .slb_miss_realmode
+	 * because the distance from here to there depends on where
+	 * the kernel ends up being put.
+	 */
+	mfctr	r11
+	ld	r10,PACAKBASE(r13)
+	LOAD_HANDLER(r10, .slb_miss_realmode)
+	mtctr	r10
+	bctr
+#endif
+
+	STD_EXCEPTION_PSERIES(0x400, instruction_access)
+
+	. = 0x480
+	.globl instruction_access_slb_pSeries
+instruction_access_slb_pSeries:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13
+	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */
+	std	r3,PACA_EXSLB+EX_R3(r13)
+	mfspr	r3,SPRN_SRR0		/* SRR0 is faulting address */
+	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
+	mfcr	r9
+#ifdef __DISABLED__
+	/* Keep that around for when we re-implement dynamic VSIDs */
+	cmpdi	r3,0
+	bge	slb_miss_user_pseries
+#endif /* __DISABLED__ */
+	std	r10,PACA_EXSLB+EX_R10(r13)
+	std	r11,PACA_EXSLB+EX_R11(r13)
+	std	r12,PACA_EXSLB+EX_R12(r13)
+	mfspr	r10,SPRN_SPRG1
+	std	r10,PACA_EXSLB+EX_R13(r13)
+	mfspr	r12,SPRN_SRR1		/* and SRR1 */
+#ifndef CONFIG_RELOCATABLE
+	b	.slb_miss_realmode
+#else
+	mfctr	r11
+	ld	r10,PACAKBASE(r13)
+	LOAD_HANDLER(r10, .slb_miss_realmode)
+	mtctr	r10
+	bctr
+#endif
+
+	MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
+	STD_EXCEPTION_PSERIES(0x600, alignment)
+	STD_EXCEPTION_PSERIES(0x700, program_check)
+	STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
+	MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
+	STD_EXCEPTION_PSERIES(0xa00, trap_0a)
+	STD_EXCEPTION_PSERIES(0xb00, trap_0b)
+
+	. = 0xc00
+	.globl	system_call_pSeries
+system_call_pSeries:
+	HMT_MEDIUM
+BEGIN_FTR_SECTION
+	cmpdi	r0,0x1ebe
+	beq-	1f
+END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
+	mr	r9,r13
+	mfspr	r13,SPRN_SPRG3
+	mfspr	r11,SPRN_SRR0
+	ld	r12,PACAKBASE(r13)
+	ld	r10,PACAKMSR(r13)
+	LOAD_HANDLER(r12, system_call_entry)
+	mtspr	SPRN_SRR0,r12
+	mfspr	r12,SPRN_SRR1
+	mtspr	SPRN_SRR1,r10
+	rfid
+	b	.	/* prevent speculative execution */
+
+/* Fast LE/BE switch system call */
+1:	mfspr	r12,SPRN_SRR1
+	xori	r12,r12,MSR_LE
+	mtspr	SPRN_SRR1,r12
+	rfid		/* return to userspace */
+	b	.
+
+	STD_EXCEPTION_PSERIES(0xd00, single_step)
+	STD_EXCEPTION_PSERIES(0xe00, trap_0e)
+
+	/* We need to deal with the Altivec unavailable exception
+	 * here which is at 0xf20, thus in the middle of the
+	 * prolog code of the PerformanceMonitor one. A little
+	 * trickery is thus necessary
+	 */
+	. = 0xf00
+	b	performance_monitor_pSeries
+
+	. = 0xf20
+	b	altivec_unavailable_pSeries
+
+	. = 0xf40
+	b	vsx_unavailable_pSeries
+
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
+#endif /* CONFIG_CBE_RAS */
+	STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
+#endif /* CONFIG_CBE_RAS */
+	STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
+#endif /* CONFIG_CBE_RAS */
+
+	. = 0x3000
+
+/*** pSeries interrupt support ***/
+
+	/* moved from 0xf00 */
+	STD_EXCEPTION_PSERIES(., performance_monitor)
+	STD_EXCEPTION_PSERIES(., altivec_unavailable)
+	STD_EXCEPTION_PSERIES(., vsx_unavailable)
+
+/*
+ * An interrupt came in while soft-disabled; clear EE in SRR1,
+ * clear paca->hard_enabled and return.
+ */
+masked_interrupt:
+	stb	r10,PACAHARDIRQEN(r13)
+	mtcrf	0x80,r9
+	ld	r9,PACA_EXGEN+EX_R9(r13)
+	mfspr	r10,SPRN_SRR1
+	rldicl	r10,r10,48,1		/* clear MSR_EE */
+	rotldi	r10,r10,16
+	mtspr	SPRN_SRR1,r10
+	ld	r10,PACA_EXGEN+EX_R10(r13)
+	mfspr	r13,SPRN_SPRG1
+	rfid
+	b	.
+
+	.align	7
+do_stab_bolted_pSeries:
+	mtcrf	0x80,r12
+	mfspr	r12,SPRN_SPRG2
+	EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
+
+#ifdef CONFIG_PPC_PSERIES
+/*
+ * Vectors for the FWNMI option.  Share common code.
+ */
+	.globl system_reset_fwnmi
+      .align 7
+system_reset_fwnmi:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+
+	.globl machine_check_fwnmi
+      .align 7
+machine_check_fwnmi:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+
+#endif /* CONFIG_PPC_PSERIES */
+
+#ifdef __DISABLED__
+/*
+ * This is used for when the SLB miss handler has to go virtual,
+ * which doesn't happen for now anymore but will once we re-implement
+ * dynamic VSIDs for shared page tables
+ */
+slb_miss_user_pseries:
+	std	r10,PACA_EXGEN+EX_R10(r13)
+	std	r11,PACA_EXGEN+EX_R11(r13)
+	std	r12,PACA_EXGEN+EX_R12(r13)
+	mfspr	r10,SPRG1
+	ld	r11,PACA_EXSLB+EX_R9(r13)
+	ld	r12,PACA_EXSLB+EX_R3(r13)
+	std	r10,PACA_EXGEN+EX_R13(r13)
+	std	r11,PACA_EXGEN+EX_R9(r13)
+	std	r12,PACA_EXGEN+EX_R3(r13)
+	clrrdi	r12,r13,32
+	mfmsr	r10
+	mfspr	r11,SRR0			/* save SRR0 */
+	ori	r12,r12,slb_miss_user_common@l	/* virt addr of handler */
+	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI
+	mtspr	SRR0,r12
+	mfspr	r12,SRR1			/* and SRR1 */
+	mtspr	SRR1,r10
+	rfid
+	b	.				/* prevent spec. execution */
+#endif /* __DISABLED__ */
+
+	.align	7
+	.globl	__end_interrupts
+__end_interrupts:
+
+/*
+ * Code from here down to __end_handlers is invoked from the
+ * exception prologs above.  Because the prologs assemble the
+ * addresses of these handlers using the LOAD_HANDLER macro,
+ * which uses an addi instruction, these handlers must be in
+ * the first 32k of the kernel image.
+ */
+
+/*** Common interrupt handlers ***/
+
+	STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
+
+	/*
+	 * Machine check is different because we use a different
+	 * save area: PACA_EXMC instead of PACA_EXGEN.
+	 */
+	.align	7
+	.globl machine_check_common
+machine_check_common:
+	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+	FINISH_NAP
+	DISABLE_INTS
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.machine_check_exception
+	b	.ret_from_except
+
+	STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt)
+	STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)
+	STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
+	STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
+	STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
+	STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)
+	STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
+#ifdef CONFIG_ALTIVEC
+	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
+#else
+	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
+#endif
+#ifdef CONFIG_CBE_RAS
+	STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
+	STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
+	STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
+#endif /* CONFIG_CBE_RAS */
+
+	.align	7
+system_call_entry:
+	b	system_call_common
+
+/*
+ * Here we have detected that the kernel stack pointer is bad.
+ * R9 contains the saved CR, r13 points to the paca,
+ * r10 contains the (bad) kernel stack pointer,
+ * r11 and r12 contain the saved SRR0 and SRR1.
+ * We switch to using an emergency stack, save the registers there,
+ * and call kernel_bad_stack(), which panics.
+ */
+bad_stack:
+	ld	r1,PACAEMERGSP(r13)
+	subi	r1,r1,64+INT_FRAME_SIZE
+	std	r9,_CCR(r1)
+	std	r10,GPR1(r1)
+	std	r11,_NIP(r1)
+	std	r12,_MSR(r1)
+	mfspr	r11,SPRN_DAR
+	mfspr	r12,SPRN_DSISR
+	std	r11,_DAR(r1)
+	std	r12,_DSISR(r1)
+	mflr	r10
+	mfctr	r11
+	mfxer	r12
+	std	r10,_LINK(r1)
+	std	r11,_CTR(r1)
+	std	r12,_XER(r1)
+	SAVE_GPR(0,r1)
+	SAVE_GPR(2,r1)
+	SAVE_4GPRS(3,r1)
+	SAVE_2GPRS(7,r1)
+	SAVE_10GPRS(12,r1)
+	SAVE_10GPRS(22,r1)
+	lhz	r12,PACA_TRAP_SAVE(r13)
+	std	r12,_TRAP(r1)
+	addi	r11,r1,INT_FRAME_SIZE
+	std	r11,0(r1)
+	li	r12,0
+	std	r12,0(r11)
+	ld	r2,PACATOC(r13)
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.kernel_bad_stack
+	b	1b
+
+/*
+ * Here r13 points to the paca, r9 contains the saved CR,
+ * SRR0 and SRR1 are saved in r11 and r12,
+ * r9 - r13 are saved in paca->exgen.
+ */
+	.align	7
+	.globl data_access_common
+data_access_common:
+	mfspr	r10,SPRN_DAR
+	std	r10,PACA_EXGEN+EX_DAR(r13)
+	mfspr	r10,SPRN_DSISR
+	stw	r10,PACA_EXGEN+EX_DSISR(r13)
+	EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
+	ld	r3,PACA_EXGEN+EX_DAR(r13)
+	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
+	li	r5,0x300
+	b	.do_hash_page	 	/* Try to handle as hpte fault */
+
+	.align	7
+	.globl instruction_access_common
+instruction_access_common:
+	EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
+	ld	r3,_NIP(r1)
+	andis.	r4,r12,0x5820
+	li	r5,0x400
+	b	.do_hash_page		/* Try to handle as hpte fault */
+
+/*
+ * Here is the common SLB miss user that is used when going to virtual
+ * mode for SLB misses, that is currently not used
+ */
+#ifdef __DISABLED__
+	.align	7
+	.globl	slb_miss_user_common
+slb_miss_user_common:
+	mflr	r10
+	std	r3,PACA_EXGEN+EX_DAR(r13)
+	stw	r9,PACA_EXGEN+EX_CCR(r13)
+	std	r10,PACA_EXGEN+EX_LR(r13)
+	std	r11,PACA_EXGEN+EX_SRR0(r13)
+	bl	.slb_allocate_user
+
+	ld	r10,PACA_EXGEN+EX_LR(r13)
+	ld	r3,PACA_EXGEN+EX_R3(r13)
+	lwz	r9,PACA_EXGEN+EX_CCR(r13)
+	ld	r11,PACA_EXGEN+EX_SRR0(r13)
+	mtlr	r10
+	beq-	slb_miss_fault
+
+	andi.	r10,r12,MSR_RI		/* check for unrecoverable exception */
+	beq-	unrecov_user_slb
+	mfmsr	r10
+
+.machine push
+.machine "power4"
+	mtcrf	0x80,r9
+.machine pop
+
+	clrrdi	r10,r10,2		/* clear RI before setting SRR0/1 */
+	mtmsrd	r10,1
+
+	mtspr	SRR0,r11
+	mtspr	SRR1,r12
+
+	ld	r9,PACA_EXGEN+EX_R9(r13)
+	ld	r10,PACA_EXGEN+EX_R10(r13)
+	ld	r11,PACA_EXGEN+EX_R11(r13)
+	ld	r12,PACA_EXGEN+EX_R12(r13)
+	ld	r13,PACA_EXGEN+EX_R13(r13)
+	rfid
+	b	.
+
+slb_miss_fault:
+	EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN)
+	ld	r4,PACA_EXGEN+EX_DAR(r13)
+	li	r5,0
+	std	r4,_DAR(r1)
+	std	r5,_DSISR(r1)
+	b	handle_page_fault
+
+unrecov_user_slb:
+	EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
+	DISABLE_INTS
+	bl	.save_nvgprs
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unrecoverable_exception
+	b	1b
+
+#endif /* __DISABLED__ */
+
+
+/*
+ * r13 points to the PACA, r9 contains the saved CR,
+ * r12 contain the saved SRR1, SRR0 is still ready for return
+ * r3 has the faulting address
+ * r9 - r13 are saved in paca->exslb.
+ * r3 is saved in paca->slb_r3
+ * We assume we aren't going to take any exceptions during this procedure.
+ */
+_GLOBAL(slb_miss_realmode)
+	mflr	r10
+#ifdef CONFIG_RELOCATABLE
+	mtctr	r11
+#endif
+
+	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
+	std	r10,PACA_EXSLB+EX_LR(r13)	/* save LR */
+
+	bl	.slb_allocate_realmode
+
+	/* All done -- return from exception. */
+
+	ld	r10,PACA_EXSLB+EX_LR(r13)
+	ld	r3,PACA_EXSLB+EX_R3(r13)
+	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
+#ifdef CONFIG_PPC_ISERIES
+BEGIN_FW_FTR_SECTION
+	ld	r11,PACALPPACAPTR(r13)
+	ld	r11,LPPACASRR0(r11)		/* get SRR0 value */
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+#endif /* CONFIG_PPC_ISERIES */
+
+	mtlr	r10
+
+	andi.	r10,r12,MSR_RI	/* check for unrecoverable exception */
+	beq-	2f
+
+.machine	push
+.machine	"power4"
+	mtcrf	0x80,r9
+	mtcrf	0x01,r9		/* slb_allocate uses cr0 and cr7 */
+.machine	pop
+
+#ifdef CONFIG_PPC_ISERIES
+BEGIN_FW_FTR_SECTION
+	mtspr	SPRN_SRR0,r11
+	mtspr	SPRN_SRR1,r12
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+#endif /* CONFIG_PPC_ISERIES */
+	ld	r9,PACA_EXSLB+EX_R9(r13)
+	ld	r10,PACA_EXSLB+EX_R10(r13)
+	ld	r11,PACA_EXSLB+EX_R11(r13)
+	ld	r12,PACA_EXSLB+EX_R12(r13)
+	ld	r13,PACA_EXSLB+EX_R13(r13)
+	rfid
+	b	.	/* prevent speculative execution */
+
+2:
+#ifdef CONFIG_PPC_ISERIES
+BEGIN_FW_FTR_SECTION
+	b	unrecov_slb
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+#endif /* CONFIG_PPC_ISERIES */
+	mfspr	r11,SPRN_SRR0
+	ld	r10,PACAKBASE(r13)
+	LOAD_HANDLER(r10,unrecov_slb)
+	mtspr	SPRN_SRR0,r10
+	ld	r10,PACAKMSR(r13)
+	mtspr	SPRN_SRR1,r10
+	rfid
+	b	.
+
+unrecov_slb:
+	EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
+	DISABLE_INTS
+	bl	.save_nvgprs
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unrecoverable_exception
+	b	1b
+
+	.align	7
+	.globl hardware_interrupt_common
+	.globl hardware_interrupt_entry
+hardware_interrupt_common:
+	EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
+	FINISH_NAP
+hardware_interrupt_entry:
+	DISABLE_INTS
+BEGIN_FTR_SECTION
+	bl	.ppc64_runlatch_on
+END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.do_IRQ
+	b	.ret_from_except_lite
+
+#ifdef CONFIG_PPC_970_NAP
+power4_fixup_nap:
+	andc	r9,r9,r10
+	std	r9,TI_LOCAL_FLAGS(r11)
+	ld	r10,_LINK(r1)		/* make idle task do the */
+	std	r10,_NIP(r1)		/* equivalent of a blr */
+	blr
+#endif
+
+	.align	7
+	.globl alignment_common
+alignment_common:
+	mfspr	r10,SPRN_DAR
+	std	r10,PACA_EXGEN+EX_DAR(r13)
+	mfspr	r10,SPRN_DSISR
+	stw	r10,PACA_EXGEN+EX_DSISR(r13)
+	EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)
+	ld	r3,PACA_EXGEN+EX_DAR(r13)
+	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
+	std	r3,_DAR(r1)
+	std	r4,_DSISR(r1)
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	ENABLE_INTS
+	bl	.alignment_exception
+	b	.ret_from_except
+
+	.align	7
+	.globl program_check_common
+program_check_common:
+	EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	ENABLE_INTS
+	bl	.program_check_exception
+	b	.ret_from_except
+
+	.align	7
+	.globl fp_unavailable_common
+fp_unavailable_common:
+	EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
+	bne	1f			/* if from user, just load it up */
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	ENABLE_INTS
+	bl	.kernel_fp_unavailable_exception
+	BUG_OPCODE
+1:	bl	.load_up_fpu
+	b	fast_exception_return
+
+	.align	7
+	.globl altivec_unavailable_common
+altivec_unavailable_common:
+	EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)
+#ifdef CONFIG_ALTIVEC
+BEGIN_FTR_SECTION
+	beq	1f
+	bl	.load_up_altivec
+	b	fast_exception_return
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+#endif
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	ENABLE_INTS
+	bl	.altivec_unavailable_exception
+	b	.ret_from_except
+
+	.align	7
+	.globl vsx_unavailable_common
+vsx_unavailable_common:
+	EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+	bne	.load_up_vsx
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	ENABLE_INTS
+	bl	.vsx_unavailable_exception
+	b	.ret_from_except
+
+	.align	7
+	.globl	__end_handlers
+__end_handlers:
+
+/*
+ * Return from an exception with minimal checks.
+ * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
+ * If interrupts have been enabled, or anything has been
+ * done that might have changed the scheduling status of
+ * any task or sent any task a signal, you should use
+ * ret_from_except or ret_from_except_lite instead of this.
+ */
+fast_exc_return_irq:			/* restores irq state too */
+	ld	r3,SOFTE(r1)
+	TRACE_AND_RESTORE_IRQ(r3);
+	ld	r12,_MSR(r1)
+	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
+	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
+	b	1f
+
+	.globl	fast_exception_return
+fast_exception_return:
+	ld	r12,_MSR(r1)
+1:	ld	r11,_NIP(r1)
+	andi.	r3,r12,MSR_RI		/* check if RI is set */
+	beq-	unrecov_fer
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+	andi.	r3,r12,MSR_PR
+	beq	2f
+	ACCOUNT_CPU_USER_EXIT(r3, r4)
+2:
+#endif
+
+	ld	r3,_CCR(r1)
+	ld	r4,_LINK(r1)
+	ld	r5,_CTR(r1)
+	ld	r6,_XER(r1)
+	mtcr	r3
+	mtlr	r4
+	mtctr	r5
+	mtxer	r6
+	REST_GPR(0, r1)
+	REST_8GPRS(2, r1)
+
+	mfmsr	r10
+	rldicl	r10,r10,48,1		/* clear EE */
+	rldicr	r10,r10,16,61		/* clear RI (LE is 0 already) */
+	mtmsrd	r10,1
+
+	mtspr	SPRN_SRR1,r12
+	mtspr	SPRN_SRR0,r11
+	REST_4GPRS(10, r1)
+	ld	r1,GPR1(r1)
+	rfid
+	b	.	/* prevent speculative execution */
+
+unrecov_fer:
+	bl	.save_nvgprs
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unrecoverable_exception
+	b	1b
+
+
+/*
+ * Hash table stuff
+ */
+	.align	7
+_STATIC(do_hash_page)
+	std	r3,_DAR(r1)
+	std	r4,_DSISR(r1)
+
+	andis.	r0,r4,0xa450		/* weird error? */
+	bne-	handle_page_fault	/* if not, try to insert a HPTE */
+BEGIN_FTR_SECTION
+	andis.	r0,r4,0x0020		/* Is it a segment table fault? */
+	bne-	do_ste_alloc		/* If so handle it */
+END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+
+	/*
+	 * On iSeries, we soft-disable interrupts here, then
+	 * hard-enable interrupts so that the hash_page code can spin on
+	 * the hash_table_lock without problems on a shared processor.
+	 */
+	DISABLE_INTS
+
+	/*
+	 * Currently, trace_hardirqs_off() will be called by DISABLE_INTS
+	 * and will clobber volatile registers when irq tracing is enabled
+	 * so we need to reload them. It may be possible to be smarter here
+	 * and move the irq tracing elsewhere but let's keep it simple for
+	 * now
+	 */
+#ifdef CONFIG_TRACE_IRQFLAGS
+	ld	r3,_DAR(r1)
+	ld	r4,_DSISR(r1)
+	ld	r5,_TRAP(r1)
+	ld	r12,_MSR(r1)
+	clrrdi	r5,r5,4
+#endif /* CONFIG_TRACE_IRQFLAGS */
+	/*
+	 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
+	 * accessing a userspace segment (even from the kernel). We assume
+	 * kernel addresses always have the high bit set.
+	 */
+	rlwinm	r4,r4,32-25+9,31-9,31-9	/* DSISR_STORE -> _PAGE_RW */
+	rotldi	r0,r3,15		/* Move high bit into MSR_PR posn */
+	orc	r0,r12,r0		/* MSR_PR | ~high_bit */
+	rlwimi	r4,r0,32-13,30,30	/* becomes _PAGE_USER access bit */
+	ori	r4,r4,1			/* add _PAGE_PRESENT */
+	rlwimi	r4,r5,22+2,31-2,31-2	/* Set _PAGE_EXEC if trap is 0x400 */
+
+	/*
+	 * r3 contains the faulting address
+	 * r4 contains the required access permissions
+	 * r5 contains the trap number
+	 *
+	 * at return r3 = 0 for success
+	 */
+	bl	.hash_page		/* build HPTE if possible */
+	cmpdi	r3,0			/* see if hash_page succeeded */
+
+BEGIN_FW_FTR_SECTION
+	/*
+	 * If we had interrupts soft-enabled at the point where the
+	 * DSI/ISI occurred, and an interrupt came in during hash_page,
+	 * handle it now.
+	 * We jump to ret_from_except_lite rather than fast_exception_return
+	 * because ret_from_except_lite will check for and handle pending
+	 * interrupts if necessary.
+	 */
+	beq	13f
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+
+BEGIN_FW_FTR_SECTION
+	/*
+	 * Here we have interrupts hard-disabled, so it is sufficient
+	 * to restore paca->{soft,hard}_enable and get out.
+	 */
+	beq	fast_exc_return_irq	/* Return from exception on success */
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
+
+	/* For a hash failure, we don't bother re-enabling interrupts */
+	ble-	12f
+
+	/*
+	 * hash_page couldn't handle it, set soft interrupt enable back
+	 * to what it was before the trap.  Note that .raw_local_irq_restore
+	 * handles any interrupts pending at this point.
+	 */
+	ld	r3,SOFTE(r1)
+	TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
+	bl	.raw_local_irq_restore
+	b	11f
+
+/* Here we have a page fault that hash_page can't handle. */
+handle_page_fault:
+	ENABLE_INTS
+11:	ld	r4,_DAR(r1)
+	ld	r5,_DSISR(r1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.do_page_fault
+	cmpdi	r3,0
+	beq+	13f
+	bl	.save_nvgprs
+	mr	r5,r3
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	lwz	r4,_DAR(r1)
+	bl	.bad_page_fault
+	b	.ret_from_except
+
+13:	b	.ret_from_except_lite
+
+/* We have a page fault that hash_page could handle but HV refused
+ * the PTE insertion
+ */
+12:	bl	.save_nvgprs
+	mr	r5,r3
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	ld	r4,_DAR(r1)
+	bl	.low_hash_fault
+	b	.ret_from_except
+
+	/* here we have a segment miss */
+do_ste_alloc:
+	bl	.ste_allocate		/* try to insert stab entry */
+	cmpdi	r3,0
+	bne-	handle_page_fault
+	b	fast_exception_return
+
+/*
+ * r13 points to the PACA, r9 contains the saved CR,
+ * r11 and r12 contain the saved SRR0 and SRR1.
+ * r9 - r13 are saved in paca->exslb.
+ * We assume we aren't going to take any exceptions during this procedure.
+ * We assume (DAR >> 60) == 0xc.
+ */
+	.align	7
+_GLOBAL(do_stab_bolted)
+	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
+	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
+
+	/* Hash to the primary group */
+	ld	r10,PACASTABVIRT(r13)
+	mfspr	r11,SPRN_DAR
+	srdi	r11,r11,28
+	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
+
+	/* Calculate VSID */
+	/* This is a kernel address, so protovsid = ESID */
+	ASM_VSID_SCRAMBLE(r11, r9, 256M)
+	rldic	r9,r11,12,16	/* r9 = vsid << 12 */
+
+	/* Search the primary group for a free entry */
+1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/
+	andi.	r11,r11,0x80
+	beq	2f
+	addi	r10,r10,16
+	andi.	r11,r10,0x70
+	bne	1b
+
+	/* Stick for only searching the primary group for now.		*/
+	/* At least for now, we use a very simple random castout scheme */
+	/* Use the TB as a random number ;  OR in 1 to avoid entry 0	*/
+	mftb	r11
+	rldic	r11,r11,4,57	/* r11 = (r11 << 4) & 0x70 */
+	ori	r11,r11,0x10
+
+	/* r10 currently points to an ste one past the group of interest */
+	/* make it point to the randomly selected entry			*/
+	subi	r10,r10,128
+	or 	r10,r10,r11	/* r10 is the entry to invalidate	*/
+
+	isync			/* mark the entry invalid		*/
+	ld	r11,0(r10)
+	rldicl	r11,r11,56,1	/* clear the valid bit */
+	rotldi	r11,r11,8
+	std	r11,0(r10)
+	sync
+
+	clrrdi	r11,r11,28	/* Get the esid part of the ste		*/
+	slbie	r11
+
+2:	std	r9,8(r10)	/* Store the vsid part of the ste	*/
+	eieio
+
+	mfspr	r11,SPRN_DAR		/* Get the new esid			*/
+	clrrdi	r11,r11,28	/* Permits a full 32b of ESID		*/
+	ori	r11,r11,0x90	/* Turn on valid and kp			*/
+	std	r11,0(r10)	/* Put new entry back into the stab	*/
+
+	sync
+
+	/* All done -- return from exception. */
+	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
+	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */
+
+	andi.	r10,r12,MSR_RI
+	beq-	unrecov_slb
+
+	mtcrf	0x80,r9			/* restore CR */
+
+	mfmsr	r10
+	clrrdi	r10,r10,2
+	mtmsrd	r10,1
+
+	mtspr	SPRN_SRR0,r11
+	mtspr	SPRN_SRR1,r12
+	ld	r9,PACA_EXSLB+EX_R9(r13)
+	ld	r10,PACA_EXSLB+EX_R10(r13)
+	ld	r11,PACA_EXSLB+EX_R11(r13)
+	ld	r12,PACA_EXSLB+EX_R12(r13)
+	ld	r13,PACA_EXSLB+EX_R13(r13)
+	rfid
+	b	.	/* prevent speculative execution */
+
+/*
+ * Space for CPU0's segment table.
+ *
+ * On iSeries, the hypervisor must fill in at least one entry before
+ * we get control (with relocate on).  The address is given to the hv
+ * as a page number (see xLparMap below), so this must be at a
+ * fixed address (the linker can't compute (u64)&initial_stab >>
+ * PAGE_SHIFT).
+ */
+	. = STAB0_OFFSET	/* 0x6000 */
+	.globl initial_stab
+initial_stab:
+	.space	4096
+
+#ifdef CONFIG_PPC_PSERIES
+/*
+ * Data area reserved for FWNMI option.
+ * This address (0x7000) is fixed by the RPA.
+ */
+	.= 0x7000
+	.globl fwnmi_data_area
+fwnmi_data_area:
+#endif /* CONFIG_PPC_PSERIES */
+
+	/* iSeries does not use the FWNMI stuff, so it is safe to put
+	 * this here, even if we later allow kernels that will boot on
+	 * both pSeries and iSeries */
+#ifdef CONFIG_PPC_ISERIES
+        . = LPARMAP_PHYS
+	.globl xLparMap
+xLparMap:
+	.quad	HvEsidsToMap		/* xNumberEsids */
+	.quad	HvRangesToMap		/* xNumberRanges */
+	.quad	STAB0_PAGE		/* xSegmentTableOffs */
+	.zero	40			/* xRsvd */
+	/* xEsids (HvEsidsToMap entries of 2 quads) */
+	.quad	PAGE_OFFSET_ESID	/* xKernelEsid */
+	.quad	PAGE_OFFSET_VSID	/* xKernelVsid */
+	.quad	VMALLOC_START_ESID	/* xKernelEsid */
+	.quad	VMALLOC_START_VSID	/* xKernelVsid */
+	/* xRanges (HvRangesToMap entries of 3 quads) */
+	.quad	HvPagesToMap		/* xPages */
+	.quad	0			/* xOffset */
+	.quad	PAGE_OFFSET_VSID << (SID_SHIFT - HW_PAGE_SHIFT)	/* xVPN */
+
+#endif /* CONFIG_PPC_ISERIES */
+
+#ifdef CONFIG_PPC_PSERIES
+        . = 0x8000
+#endif /* CONFIG_PPC_PSERIES */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/ftrace.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/ftrace.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/ftrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/ftrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,25 +23,14 @@
 #include <asm/code-patching.h>
 #include <asm/ftrace.h>
 
-#ifdef CONFIG_PPC32
-# define GET_ADDR(addr) addr
-#else
-/* PowerPC64's functions are data that points to the functions */
-# define GET_ADDR(addr) (*(unsigned long *)addr)
-#endif
 
 #ifdef CONFIG_DYNAMIC_FTRACE
-static unsigned int ftrace_nop_replace(void)
-{
-	return PPC_INST_NOP;
-}
-
 static unsigned int
 ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
 {
 	unsigned int op;
 
-	addr = GET_ADDR(addr);
+	addr = ppc_function_entry((void *)addr);
 
 	/* if (link) set op to 'bl' else 'b' */
 	op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
@@ -49,14 +38,6 @@
 	return op;
 }
 
-#ifdef CONFIG_PPC64
-# define _ASM_ALIGN	" .align 3 "
-# define _ASM_PTR	" .llong "
-#else
-# define _ASM_ALIGN	" .align 2 "
-# define _ASM_PTR	" .long "
-#endif
-
 static int
 ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
 {
@@ -197,7 +178,7 @@
 	ptr = ((unsigned long)jmp[0] << 32) + jmp[1];
 
 	/* This should match what was called */
-	if (ptr != GET_ADDR(addr)) {
+	if (ptr != ppc_function_entry((void *)addr)) {
 		printk(KERN_ERR "addr does not match %lx\n", ptr);
 		return -EINVAL;
 	}
@@ -328,7 +309,7 @@
 	if (test_24bit_addr(ip, addr)) {
 		/* within range */
 		old = ftrace_call_replace(ip, addr, 1);
-		new = ftrace_nop_replace();
+		new = PPC_INST_NOP;
 		return ftrace_modify_code(ip, old, new);
 	}
 
@@ -466,7 +447,7 @@
 	 */
 	if (test_24bit_addr(ip, addr)) {
 		/* within range */
-		old = ftrace_nop_replace();
+		old = PPC_INST_NOP;
 		new = ftrace_call_replace(ip, addr, 1);
 		return ftrace_modify_code(ip, old, new);
 	}
@@ -570,7 +551,7 @@
 		return_hooker = (unsigned long)&mod_return_to_handler;
 #endif
 
-	return_hooker = GET_ADDR(return_hooker);
+	return_hooker = ppc_function_entry((void *)return_hooker);
 
 	/*
 	 * Protect against fault, even if it shouldn't
@@ -605,7 +586,7 @@
 		return;
 	}
 
-	if (ftrace_push_return_trace(old, self_addr, &trace.depth) == -EBUSY) {
+	if (ftrace_push_return_trace(old, self_addr, &trace.depth, 0) == -EBUSY) {
 		*parent = old;
 		return;
 	}
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/head_32.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/head_32.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/head_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/head_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -733,9 +733,11 @@
 AltiVecUnavailable:
 	EXCEPTION_PROLOG
 #ifdef CONFIG_ALTIVEC
-	bne	load_up_altivec		/* if from user, just load it up */
+	beq	1f
+	bl	load_up_altivec		/* if from user, just load it up */
+	b	fast_exception_return
 #endif /* CONFIG_ALTIVEC */
-	addi	r3,r1,STACK_FRAME_OVERHEAD
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
 
 PerformanceMonitor:
@@ -743,101 +745,6 @@
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	EXC_XFER_STD(0xf00, performance_monitor_exception)
 
-#ifdef CONFIG_ALTIVEC
-/* Note that the AltiVec support is closely modeled after the FP
- * support.  Changes to one are likely to be applicable to the
- * other!  */
-load_up_altivec:
-/*
- * Disable AltiVec for the task which had AltiVec previously,
- * and save its AltiVec registers in its thread_struct.
- * Enables AltiVec for use in the kernel on return.
- * On SMP we know the AltiVec units are free, since we give it up every
- * switch.  -- Kumar
- */
-	mfmsr	r5
-	oris	r5,r5,MSR_VEC@h
-	MTMSRD(r5)			/* enable use of AltiVec now */
-	isync
-/*
- * For SMP, we don't do lazy AltiVec switching because it just gets too
- * horrendously complex, especially when a task switches from one CPU
- * to another.  Instead we call giveup_altivec in switch_to.
- */
-#ifndef CONFIG_SMP
-	tophys(r6,0)
-	addis	r3,r6,last_task_used_altivec@ha
-	lwz	r4,last_task_used_altivec@l(r3)
-	cmpwi	0,r4,0
-	beq	1f
-	add	r4,r4,r6
-	addi	r4,r4,THREAD	/* want THREAD of last_task_used_altivec */
-	SAVE_32VRS(0,r10,r4)
-	mfvscr	vr0
-	li	r10,THREAD_VSCR
-	stvx	vr0,r10,r4
-	lwz	r5,PT_REGS(r4)
-	add	r5,r5,r6
-	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	lis	r10,MSR_VEC@h
-	andc	r4,r4,r10	/* disable altivec for previous task */
-	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
-	/* enable use of AltiVec after return */
-	oris	r9,r9,MSR_VEC@h
-	mfspr	r5,SPRN_SPRG3		/* current task's THREAD (phys) */
-	li	r4,1
-	li	r10,THREAD_VSCR
-	stw	r4,THREAD_USED_VR(r5)
-	lvx	vr0,r10,r5
-	mtvscr	vr0
-	REST_32VRS(0,r10,r5)
-#ifndef CONFIG_SMP
-	subi	r4,r5,THREAD
-	sub	r4,r4,r6
-	stw	r4,last_task_used_altivec@l(r3)
-#endif /* CONFIG_SMP */
-	/* restore registers and return */
-	/* we haven't used ctr or xer or lr */
-	b	fast_exception_return
-
-/*
- * giveup_altivec(tsk)
- * Disable AltiVec for the task given as the argument,
- * and save the AltiVec registers in its thread_struct.
- * Enables AltiVec for use in the kernel on return.
- */
-
-	.globl	giveup_altivec
-giveup_altivec:
-	mfmsr	r5
-	oris	r5,r5,MSR_VEC@h
-	SYNC
-	MTMSRD(r5)			/* enable use of AltiVec now */
-	isync
-	cmpwi	0,r3,0
-	beqlr-				/* if no previous owner, done */
-	addi	r3,r3,THREAD		/* want THREAD of task */
-	lwz	r5,PT_REGS(r3)
-	cmpwi	0,r5,0
-	SAVE_32VRS(0, r4, r3)
-	mfvscr	vr0
-	li	r4,THREAD_VSCR
-	stvx	vr0,r4,r3
-	beq	1f
-	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	lis	r3,MSR_VEC@h
-	andc	r4,r4,r3		/* disable AltiVec for previous task */
-	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
-	li	r5,0
-	lis	r4,last_task_used_altivec@ha
-	stw	r5,last_task_used_altivec@l(r4)
-#endif /* CONFIG_SMP */
-	blr
-#endif /* CONFIG_ALTIVEC */
 
 /*
  * This code is jumped to from the startup code to copy
@@ -1217,9 +1124,8 @@
 	RFI
 
 /*
- * Use the first pair of BAT registers to map the 1st 16MB
- * of RAM to PAGE_OFFSET.  From this point on we can't safely
- * call OF any more.
+ * On 601, we use 3 BATs to map up to 24M of RAM at _PAGE_OFFSET
+ * (we keep one for debugging) and on others, we use one 256M BAT.
  */
 initial_bats:
 	lis	r11,PAGE_OFFSET@h
@@ -1229,12 +1135,16 @@
 	bne	4f
 	ori	r11,r11,4		/* set up BAT registers for 601 */
 	li	r8,0x7f			/* valid, block length = 8MB */
-	oris	r9,r11,0x800000@h	/* set up BAT reg for 2nd 8M */
-	oris	r10,r8,0x800000@h	/* set up BAT reg for 2nd 8M */
 	mtspr	SPRN_IBAT0U,r11		/* N.B. 601 has valid bit in */
 	mtspr	SPRN_IBAT0L,r8		/* lower BAT register */
-	mtspr	SPRN_IBAT1U,r9
-	mtspr	SPRN_IBAT1L,r10
+	addis	r11,r11,0x800000@h
+	addis	r8,r8,0x800000@h
+	mtspr	SPRN_IBAT1U,r11
+	mtspr	SPRN_IBAT1L,r8
+	addis	r11,r11,0x800000@h
+	addis	r8,r8,0x800000@h
+	mtspr	SPRN_IBAT2U,r11
+	mtspr	SPRN_IBAT2L,r8
 	isync
 	blr
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/head_64.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/head_64.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/head_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/head_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -12,8 +12,9 @@
  *  Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
  *    Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
  *
- *  This file contains the low-level support and setup for the
- *  PowerPC-64 platform, including trap and interrupt dispatch.
+ *  This file contains the entry point for the 64-bit kernel along
+ *  with some early initialization code common to all 64-bit powerpc
+ *  variants.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -38,36 +39,25 @@
 #include <asm/exception.h>
 #include <asm/irqflags.h>
 
-/*
- * We layout physical memory as follows:
- * 0x0000 - 0x00ff : Secondary processor spin code
- * 0x0100 - 0x2fff : pSeries Interrupt prologs
- * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs
- * 0x6000 - 0x6fff : Initial (CPU0) segment table
- * 0x7000 - 0x7fff : FWNMI data area
- * 0x8000 -        : Early init and support code
- */
-
-/*
- *   SPRG Usage
- *
- *   Register	Definition
- *
- *   SPRG0	reserved for hypervisor
- *   SPRG1	temp - used to save gpr
- *   SPRG2	temp - used to save gpr
- *   SPRG3	virt addr of paca
+/* The physical memory is layed out such that the secondary processor
+ * spin code sits at 0x0000...0x00ff. On server, the vectors follow
+ * using the layout described in exceptions-64s.S
  */
 
 /*
  * Entering into this code we make the following assumptions:
- *  For pSeries:
+ *
+ *  For pSeries or server processors:
  *   1. The MMU is off & open firmware is running in real mode.
  *   2. The kernel is entered at __start
  *
  *  For iSeries:
  *   1. The MMU is on (as it always is for iSeries)
  *   2. The kernel is entered at system_reset_iSeries
+ *
+ *  For Book3E processors:
+ *   1. The MMU is on running in AS0 in a state defined in ePAPR
+ *   2. The kernel is entered at __start
  */
 
 	.text
@@ -166,1065 +156,14 @@
 	.text
 
 /*
- * This is the start of the interrupt handlers for pSeries
- * This code runs with relocation off.
- * Code from here to __end_interrupts gets copied down to real
- * address 0x100 when we are running a relocatable kernel.
- * Therefore any relative branches in this section must only
- * branch to labels in this section.
- */
-	. = 0x100
-	.globl __start_interrupts
-__start_interrupts:
-
-	STD_EXCEPTION_PSERIES(0x100, system_reset)
-
-	. = 0x200
-_machine_check_pSeries:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
-
-	. = 0x300
-	.globl data_access_pSeries
-data_access_pSeries:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13
-BEGIN_FTR_SECTION
-	mtspr	SPRN_SPRG2,r12
-	mfspr	r13,SPRN_DAR
-	mfspr	r12,SPRN_DSISR
-	srdi	r13,r13,60
-	rlwimi	r13,r12,16,0x20
-	mfcr	r12
-	cmpwi	r13,0x2c
-	beq	do_stab_bolted_pSeries
-	mtcrf	0x80,r12
-	mfspr	r12,SPRN_SPRG2
-END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common)
-
-	. = 0x380
-	.globl data_access_slb_pSeries
-data_access_slb_pSeries:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13
-	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */
-	std	r3,PACA_EXSLB+EX_R3(r13)
-	mfspr	r3,SPRN_DAR
-	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
-	mfcr	r9
-#ifdef __DISABLED__
-	/* Keep that around for when we re-implement dynamic VSIDs */
-	cmpdi	r3,0
-	bge	slb_miss_user_pseries
-#endif /* __DISABLED__ */
-	std	r10,PACA_EXSLB+EX_R10(r13)
-	std	r11,PACA_EXSLB+EX_R11(r13)
-	std	r12,PACA_EXSLB+EX_R12(r13)
-	mfspr	r10,SPRN_SPRG1
-	std	r10,PACA_EXSLB+EX_R13(r13)
-	mfspr	r12,SPRN_SRR1		/* and SRR1 */
-#ifndef CONFIG_RELOCATABLE
-	b	.slb_miss_realmode
-#else
-	/*
-	 * We can't just use a direct branch to .slb_miss_realmode
-	 * because the distance from here to there depends on where
-	 * the kernel ends up being put.
-	 */
-	mfctr	r11
-	ld	r10,PACAKBASE(r13)
-	LOAD_HANDLER(r10, .slb_miss_realmode)
-	mtctr	r10
-	bctr
-#endif
-
-	STD_EXCEPTION_PSERIES(0x400, instruction_access)
-
-	. = 0x480
-	.globl instruction_access_slb_pSeries
-instruction_access_slb_pSeries:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13
-	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */
-	std	r3,PACA_EXSLB+EX_R3(r13)
-	mfspr	r3,SPRN_SRR0		/* SRR0 is faulting address */
-	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */
-	mfcr	r9
-#ifdef __DISABLED__
-	/* Keep that around for when we re-implement dynamic VSIDs */
-	cmpdi	r3,0
-	bge	slb_miss_user_pseries
-#endif /* __DISABLED__ */
-	std	r10,PACA_EXSLB+EX_R10(r13)
-	std	r11,PACA_EXSLB+EX_R11(r13)
-	std	r12,PACA_EXSLB+EX_R12(r13)
-	mfspr	r10,SPRN_SPRG1
-	std	r10,PACA_EXSLB+EX_R13(r13)
-	mfspr	r12,SPRN_SRR1		/* and SRR1 */
-#ifndef CONFIG_RELOCATABLE
-	b	.slb_miss_realmode
-#else
-	mfctr	r11
-	ld	r10,PACAKBASE(r13)
-	LOAD_HANDLER(r10, .slb_miss_realmode)
-	mtctr	r10
-	bctr
-#endif
-
-	MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
-	STD_EXCEPTION_PSERIES(0x600, alignment)
-	STD_EXCEPTION_PSERIES(0x700, program_check)
-	STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
-	MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
-	STD_EXCEPTION_PSERIES(0xa00, trap_0a)
-	STD_EXCEPTION_PSERIES(0xb00, trap_0b)
-
-	. = 0xc00
-	.globl	system_call_pSeries
-system_call_pSeries:
-	HMT_MEDIUM
-BEGIN_FTR_SECTION
-	cmpdi	r0,0x1ebe
-	beq-	1f
-END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
-	mr	r9,r13
-	mfspr	r13,SPRN_SPRG3
-	mfspr	r11,SPRN_SRR0
-	ld	r12,PACAKBASE(r13)
-	ld	r10,PACAKMSR(r13)
-	LOAD_HANDLER(r12, system_call_entry)
-	mtspr	SPRN_SRR0,r12
-	mfspr	r12,SPRN_SRR1
-	mtspr	SPRN_SRR1,r10
-	rfid
-	b	.	/* prevent speculative execution */
-
-/* Fast LE/BE switch system call */
-1:	mfspr	r12,SPRN_SRR1
-	xori	r12,r12,MSR_LE
-	mtspr	SPRN_SRR1,r12
-	rfid		/* return to userspace */
-	b	.
-
-	STD_EXCEPTION_PSERIES(0xd00, single_step)
-	STD_EXCEPTION_PSERIES(0xe00, trap_0e)
-
-	/* We need to deal with the Altivec unavailable exception
-	 * here which is at 0xf20, thus in the middle of the
-	 * prolog code of the PerformanceMonitor one. A little
-	 * trickery is thus necessary
-	 */
-	. = 0xf00
-	b	performance_monitor_pSeries
-
-	. = 0xf20
-	b	altivec_unavailable_pSeries
-
-	. = 0xf40
-	b	vsx_unavailable_pSeries
-
-#ifdef CONFIG_CBE_RAS
-	HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
-#endif /* CONFIG_CBE_RAS */
-	STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
-#ifdef CONFIG_CBE_RAS
-	HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
-#endif /* CONFIG_CBE_RAS */
-	STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
-#ifdef CONFIG_CBE_RAS
-	HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
-#endif /* CONFIG_CBE_RAS */
-
-	. = 0x3000
-
-/*** pSeries interrupt support ***/
-
-	/* moved from 0xf00 */
-	STD_EXCEPTION_PSERIES(., performance_monitor)
-	STD_EXCEPTION_PSERIES(., altivec_unavailable)
-	STD_EXCEPTION_PSERIES(., vsx_unavailable)
-
-/*
- * An interrupt came in while soft-disabled; clear EE in SRR1,
- * clear paca->hard_enabled and return.
- */
-masked_interrupt:
-	stb	r10,PACAHARDIRQEN(r13)
-	mtcrf	0x80,r9
-	ld	r9,PACA_EXGEN+EX_R9(r13)
-	mfspr	r10,SPRN_SRR1
-	rldicl	r10,r10,48,1		/* clear MSR_EE */
-	rotldi	r10,r10,16
-	mtspr	SPRN_SRR1,r10
-	ld	r10,PACA_EXGEN+EX_R10(r13)
-	mfspr	r13,SPRN_SPRG1
-	rfid
-	b	.
-
-	.align	7
-do_stab_bolted_pSeries:
-	mtcrf	0x80,r12
-	mfspr	r12,SPRN_SPRG2
-	EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
-
-#ifdef CONFIG_PPC_PSERIES
-/*
- * Vectors for the FWNMI option.  Share common code.
- */
-	.globl system_reset_fwnmi
-      .align 7
-system_reset_fwnmi:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
-
-	.globl machine_check_fwnmi
-      .align 7
-machine_check_fwnmi:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
-
-#endif /* CONFIG_PPC_PSERIES */
-
-#ifdef __DISABLED__
-/*
- * This is used for when the SLB miss handler has to go virtual,
- * which doesn't happen for now anymore but will once we re-implement
- * dynamic VSIDs for shared page tables
- */
-slb_miss_user_pseries:
-	std	r10,PACA_EXGEN+EX_R10(r13)
-	std	r11,PACA_EXGEN+EX_R11(r13)
-	std	r12,PACA_EXGEN+EX_R12(r13)
-	mfspr	r10,SPRG1
-	ld	r11,PACA_EXSLB+EX_R9(r13)
-	ld	r12,PACA_EXSLB+EX_R3(r13)
-	std	r10,PACA_EXGEN+EX_R13(r13)
-	std	r11,PACA_EXGEN+EX_R9(r13)
-	std	r12,PACA_EXGEN+EX_R3(r13)
-	clrrdi	r12,r13,32
-	mfmsr	r10
-	mfspr	r11,SRR0			/* save SRR0 */
-	ori	r12,r12,slb_miss_user_common@l	/* virt addr of handler */
-	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI
-	mtspr	SRR0,r12
-	mfspr	r12,SRR1			/* and SRR1 */
-	mtspr	SRR1,r10
-	rfid
-	b	.				/* prevent spec. execution */
-#endif /* __DISABLED__ */
-
-	.align	7
-	.globl	__end_interrupts
-__end_interrupts:
-
-/*
- * Code from here down to __end_handlers is invoked from the
- * exception prologs above.  Because the prologs assemble the
- * addresses of these handlers using the LOAD_HANDLER macro,
- * which uses an addi instruction, these handlers must be in
- * the first 32k of the kernel image.
- */
-
-/*** Common interrupt handlers ***/
-
-	STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
-
-	/*
-	 * Machine check is different because we use a different
-	 * save area: PACA_EXMC instead of PACA_EXGEN.
-	 */
-	.align	7
-	.globl machine_check_common
-machine_check_common:
-	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
-	FINISH_NAP
-	DISABLE_INTS
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.machine_check_exception
-	b	.ret_from_except
-
-	STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt)
-	STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)
-	STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
-	STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
-	STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
-	STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)
-	STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
-#ifdef CONFIG_ALTIVEC
-	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
-#else
-	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
-#endif
-#ifdef CONFIG_CBE_RAS
-	STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
-	STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
-	STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
-#endif /* CONFIG_CBE_RAS */
-
-	.align	7
-system_call_entry:
-	b	system_call_common
-
-/*
- * Here we have detected that the kernel stack pointer is bad.
- * R9 contains the saved CR, r13 points to the paca,
- * r10 contains the (bad) kernel stack pointer,
- * r11 and r12 contain the saved SRR0 and SRR1.
- * We switch to using an emergency stack, save the registers there,
- * and call kernel_bad_stack(), which panics.
- */
-bad_stack:
-	ld	r1,PACAEMERGSP(r13)
-	subi	r1,r1,64+INT_FRAME_SIZE
-	std	r9,_CCR(r1)
-	std	r10,GPR1(r1)
-	std	r11,_NIP(r1)
-	std	r12,_MSR(r1)
-	mfspr	r11,SPRN_DAR
-	mfspr	r12,SPRN_DSISR
-	std	r11,_DAR(r1)
-	std	r12,_DSISR(r1)
-	mflr	r10
-	mfctr	r11
-	mfxer	r12
-	std	r10,_LINK(r1)
-	std	r11,_CTR(r1)
-	std	r12,_XER(r1)
-	SAVE_GPR(0,r1)
-	SAVE_GPR(2,r1)
-	SAVE_4GPRS(3,r1)
-	SAVE_2GPRS(7,r1)
-	SAVE_10GPRS(12,r1)
-	SAVE_10GPRS(22,r1)
-	lhz	r12,PACA_TRAP_SAVE(r13)
-	std	r12,_TRAP(r1)
-	addi	r11,r1,INT_FRAME_SIZE
-	std	r11,0(r1)
-	li	r12,0
-	std	r12,0(r11)
-	ld	r2,PACATOC(r13)
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.kernel_bad_stack
-	b	1b
-
-/*
- * Here r13 points to the paca, r9 contains the saved CR,
- * SRR0 and SRR1 are saved in r11 and r12,
- * r9 - r13 are saved in paca->exgen.
- */
-	.align	7
-	.globl data_access_common
-data_access_common:
-	mfspr	r10,SPRN_DAR
-	std	r10,PACA_EXGEN+EX_DAR(r13)
-	mfspr	r10,SPRN_DSISR
-	stw	r10,PACA_EXGEN+EX_DSISR(r13)
-	EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
-	ld	r3,PACA_EXGEN+EX_DAR(r13)
-	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
-	li	r5,0x300
-	b	.do_hash_page	 	/* Try to handle as hpte fault */
-
-	.align	7
-	.globl instruction_access_common
-instruction_access_common:
-	EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
-	ld	r3,_NIP(r1)
-	andis.	r4,r12,0x5820
-	li	r5,0x400
-	b	.do_hash_page		/* Try to handle as hpte fault */
-
-/*
- * Here is the common SLB miss user that is used when going to virtual
- * mode for SLB misses, that is currently not used
- */
-#ifdef __DISABLED__
-	.align	7
-	.globl	slb_miss_user_common
-slb_miss_user_common:
-	mflr	r10
-	std	r3,PACA_EXGEN+EX_DAR(r13)
-	stw	r9,PACA_EXGEN+EX_CCR(r13)
-	std	r10,PACA_EXGEN+EX_LR(r13)
-	std	r11,PACA_EXGEN+EX_SRR0(r13)
-	bl	.slb_allocate_user
-
-	ld	r10,PACA_EXGEN+EX_LR(r13)
-	ld	r3,PACA_EXGEN+EX_R3(r13)
-	lwz	r9,PACA_EXGEN+EX_CCR(r13)
-	ld	r11,PACA_EXGEN+EX_SRR0(r13)
-	mtlr	r10
-	beq-	slb_miss_fault
-
-	andi.	r10,r12,MSR_RI		/* check for unrecoverable exception */
-	beq-	unrecov_user_slb
-	mfmsr	r10
-
-.machine push
-.machine "power4"
-	mtcrf	0x80,r9
-.machine pop
-
-	clrrdi	r10,r10,2		/* clear RI before setting SRR0/1 */
-	mtmsrd	r10,1
-
-	mtspr	SRR0,r11
-	mtspr	SRR1,r12
-
-	ld	r9,PACA_EXGEN+EX_R9(r13)
-	ld	r10,PACA_EXGEN+EX_R10(r13)
-	ld	r11,PACA_EXGEN+EX_R11(r13)
-	ld	r12,PACA_EXGEN+EX_R12(r13)
-	ld	r13,PACA_EXGEN+EX_R13(r13)
-	rfid
-	b	.
-
-slb_miss_fault:
-	EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN)
-	ld	r4,PACA_EXGEN+EX_DAR(r13)
-	li	r5,0
-	std	r4,_DAR(r1)
-	std	r5,_DSISR(r1)
-	b	handle_page_fault
-
-unrecov_user_slb:
-	EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
-	DISABLE_INTS
-	bl	.save_nvgprs
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.unrecoverable_exception
-	b	1b
-
-#endif /* __DISABLED__ */
-
-
-/*
- * r13 points to the PACA, r9 contains the saved CR,
- * r12 contain the saved SRR1, SRR0 is still ready for return
- * r3 has the faulting address
- * r9 - r13 are saved in paca->exslb.
- * r3 is saved in paca->slb_r3
- * We assume we aren't going to take any exceptions during this procedure.
- */
-_GLOBAL(slb_miss_realmode)
-	mflr	r10
-#ifdef CONFIG_RELOCATABLE
-	mtctr	r11
-#endif
-
-	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
-	std	r10,PACA_EXSLB+EX_LR(r13)	/* save LR */
-
-	bl	.slb_allocate_realmode
-
-	/* All done -- return from exception. */
-
-	ld	r10,PACA_EXSLB+EX_LR(r13)
-	ld	r3,PACA_EXSLB+EX_R3(r13)
-	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
-#ifdef CONFIG_PPC_ISERIES
-BEGIN_FW_FTR_SECTION
-	ld	r11,PACALPPACAPTR(r13)
-	ld	r11,LPPACASRR0(r11)		/* get SRR0 value */
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif /* CONFIG_PPC_ISERIES */
-
-	mtlr	r10
-
-	andi.	r10,r12,MSR_RI	/* check for unrecoverable exception */
-	beq-	2f
-
-.machine	push
-.machine	"power4"
-	mtcrf	0x80,r9
-	mtcrf	0x01,r9		/* slb_allocate uses cr0 and cr7 */
-.machine	pop
-
-#ifdef CONFIG_PPC_ISERIES
-BEGIN_FW_FTR_SECTION
-	mtspr	SPRN_SRR0,r11
-	mtspr	SPRN_SRR1,r12
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif /* CONFIG_PPC_ISERIES */
-	ld	r9,PACA_EXSLB+EX_R9(r13)
-	ld	r10,PACA_EXSLB+EX_R10(r13)
-	ld	r11,PACA_EXSLB+EX_R11(r13)
-	ld	r12,PACA_EXSLB+EX_R12(r13)
-	ld	r13,PACA_EXSLB+EX_R13(r13)
-	rfid
-	b	.	/* prevent speculative execution */
-
-2:
-#ifdef CONFIG_PPC_ISERIES
-BEGIN_FW_FTR_SECTION
-	b	unrecov_slb
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif /* CONFIG_PPC_ISERIES */
-	mfspr	r11,SPRN_SRR0
-	ld	r10,PACAKBASE(r13)
-	LOAD_HANDLER(r10,unrecov_slb)
-	mtspr	SPRN_SRR0,r10
-	ld	r10,PACAKMSR(r13)
-	mtspr	SPRN_SRR1,r10
-	rfid
-	b	.
-
-unrecov_slb:
-	EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
-	DISABLE_INTS
-	bl	.save_nvgprs
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.unrecoverable_exception
-	b	1b
-
-	.align	7
-	.globl hardware_interrupt_common
-	.globl hardware_interrupt_entry
-hardware_interrupt_common:
-	EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
-	FINISH_NAP
-hardware_interrupt_entry:
-	DISABLE_INTS
-BEGIN_FTR_SECTION
-	bl	.ppc64_runlatch_on
-END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.do_IRQ
-	b	.ret_from_except_lite
-
-#ifdef CONFIG_PPC_970_NAP
-power4_fixup_nap:
-	andc	r9,r9,r10
-	std	r9,TI_LOCAL_FLAGS(r11)
-	ld	r10,_LINK(r1)		/* make idle task do the */
-	std	r10,_NIP(r1)		/* equivalent of a blr */
-	blr
-#endif
-
-	.align	7
-	.globl alignment_common
-alignment_common:
-	mfspr	r10,SPRN_DAR
-	std	r10,PACA_EXGEN+EX_DAR(r13)
-	mfspr	r10,SPRN_DSISR
-	stw	r10,PACA_EXGEN+EX_DSISR(r13)
-	EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)
-	ld	r3,PACA_EXGEN+EX_DAR(r13)
-	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
-	std	r3,_DAR(r1)
-	std	r4,_DSISR(r1)
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	ENABLE_INTS
-	bl	.alignment_exception
-	b	.ret_from_except
-
-	.align	7
-	.globl program_check_common
-program_check_common:
-	EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	ENABLE_INTS
-	bl	.program_check_exception
-	b	.ret_from_except
-
-	.align	7
-	.globl fp_unavailable_common
-fp_unavailable_common:
-	EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
-	bne	1f			/* if from user, just load it up */
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	ENABLE_INTS
-	bl	.kernel_fp_unavailable_exception
-	BUG_OPCODE
-1:	bl	.load_up_fpu
-	b	fast_exception_return
-
-	.align	7
-	.globl altivec_unavailable_common
-altivec_unavailable_common:
-	EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)
-#ifdef CONFIG_ALTIVEC
-BEGIN_FTR_SECTION
-	beq	1f
-	bl	.load_up_altivec
-	b	fast_exception_return
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-#endif
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	ENABLE_INTS
-	bl	.altivec_unavailable_exception
-	b	.ret_from_except
-
-	.align	7
-	.globl vsx_unavailable_common
-vsx_unavailable_common:
-	EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-	bne	.load_up_vsx
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_VSX)
-#endif
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	ENABLE_INTS
-	bl	.vsx_unavailable_exception
-	b	.ret_from_except
-
-	.align	7
-	.globl	__end_handlers
-__end_handlers:
-
-/*
- * Return from an exception with minimal checks.
- * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
- * If interrupts have been enabled, or anything has been
- * done that might have changed the scheduling status of
- * any task or sent any task a signal, you should use
- * ret_from_except or ret_from_except_lite instead of this.
+ * On server, we include the exception vectors code here as it
+ * relies on absolute addressing which is only possible within
+ * this compilation unit
  */
-fast_exc_return_irq:			/* restores irq state too */
-	ld	r3,SOFTE(r1)
-	TRACE_AND_RESTORE_IRQ(r3);
-	ld	r12,_MSR(r1)
-	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
-	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
-	b	1f
-
-	.globl	fast_exception_return
-fast_exception_return:
-	ld	r12,_MSR(r1)
-1:	ld	r11,_NIP(r1)
-	andi.	r3,r12,MSR_RI		/* check if RI is set */
-	beq-	unrecov_fer
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	andi.	r3,r12,MSR_PR
-	beq	2f
-	ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
+#ifdef CONFIG_PPC_BOOK3S
+#include "exceptions-64s.S"
 #endif
 
-	ld	r3,_CCR(r1)
-	ld	r4,_LINK(r1)
-	ld	r5,_CTR(r1)
-	ld	r6,_XER(r1)
-	mtcr	r3
-	mtlr	r4
-	mtctr	r5
-	mtxer	r6
-	REST_GPR(0, r1)
-	REST_8GPRS(2, r1)
-
-	mfmsr	r10
-	rldicl	r10,r10,48,1		/* clear EE */
-	rldicr	r10,r10,16,61		/* clear RI (LE is 0 already) */
-	mtmsrd	r10,1
-
-	mtspr	SPRN_SRR1,r12
-	mtspr	SPRN_SRR0,r11
-	REST_4GPRS(10, r1)
-	ld	r1,GPR1(r1)
-	rfid
-	b	.	/* prevent speculative execution */
-
-unrecov_fer:
-	bl	.save_nvgprs
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.unrecoverable_exception
-	b	1b
-
-#ifdef CONFIG_ALTIVEC
-/*
- * load_up_altivec(unused, unused, tsk)
- * Disable VMX for the task which had it previously,
- * and save its vector registers in its thread_struct.
- * Enables the VMX for use in the kernel on return.
- * On SMP we know the VMX is free, since we give it up every
- * switch (ie, no lazy save of the vector registers).
- * On entry: r13 == 'current' && last_task_used_altivec != 'current'
- */
-_STATIC(load_up_altivec)
-	mfmsr	r5			/* grab the current MSR */
-	oris	r5,r5,MSR_VEC@h
-	mtmsrd	r5			/* enable use of VMX now */
-	isync
-
-/*
- * For SMP, we don't do lazy VMX switching because it just gets too
- * horrendously complex, especially when a task switches from one CPU
- * to another.  Instead we call giveup_altvec in switch_to.
- * VRSAVE isn't dealt with here, that is done in the normal context
- * switch code. Note that we could rely on vrsave value to eventually
- * avoid saving all of the VREGs here...
- */
-#ifndef CONFIG_SMP
-	ld	r3,last_task_used_altivec@got(r2)
-	ld	r4,0(r3)
-	cmpdi	0,r4,0
-	beq	1f
-	/* Save VMX state to last_task_used_altivec's THREAD struct */
-	addi	r4,r4,THREAD
-	SAVE_32VRS(0,r5,r4)
-	mfvscr	vr0
-	li	r10,THREAD_VSCR
-	stvx	vr0,r10,r4
-	/* Disable VMX for last_task_used_altivec */
-	ld	r5,PT_REGS(r4)
-	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	lis	r6,MSR_VEC@h
-	andc	r4,r4,r6
-	std	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
-	/* Hack: if we get an altivec unavailable trap with VRSAVE
-	 * set to all zeros, we assume this is a broken application
-	 * that fails to set it properly, and thus we switch it to
-	 * all 1's
-	 */
-	mfspr	r4,SPRN_VRSAVE
-	cmpdi	0,r4,0
-	bne+	1f
-	li	r4,-1
-	mtspr	SPRN_VRSAVE,r4
-1:
-	/* enable use of VMX after return */
-	ld	r4,PACACURRENT(r13)
-	addi	r5,r4,THREAD		/* Get THREAD */
-	oris	r12,r12,MSR_VEC@h
-	std	r12,_MSR(r1)
-	li	r4,1
-	li	r10,THREAD_VSCR
-	stw	r4,THREAD_USED_VR(r5)
-	lvx	vr0,r10,r5
-	mtvscr	vr0
-	REST_32VRS(0,r4,r5)
-#ifndef CONFIG_SMP
-	/* Update last_task_used_math to 'current' */
-	subi	r4,r5,THREAD		/* Back to 'current' */
-	std	r4,0(r3)
-#endif /* CONFIG_SMP */
-	/* restore registers and return */
-	blr
-#endif /* CONFIG_ALTIVEC */
-
-#ifdef CONFIG_VSX
-/*
- * load_up_vsx(unused, unused, tsk)
- * Disable VSX for the task which had it previously,
- * and save its vector registers in its thread_struct.
- * Reuse the fp and vsx saves, but first check to see if they have
- * been saved already.
- * On entry: r13 == 'current' && last_task_used_vsx != 'current'
- */
-_STATIC(load_up_vsx)
-/* Load FP and VSX registers if they haven't been done yet */
-	andi.	r5,r12,MSR_FP
-	beql+	load_up_fpu		/* skip if already loaded */
-	andis.	r5,r12,MSR_VEC@h
-	beql+	load_up_altivec		/* skip if already loaded */
-
-#ifndef CONFIG_SMP
-	ld	r3,last_task_used_vsx@got(r2)
-	ld	r4,0(r3)
-	cmpdi	0,r4,0
-	beq	1f
-	/* Disable VSX for last_task_used_vsx */
-	addi	r4,r4,THREAD
-	ld	r5,PT_REGS(r4)
-	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	lis	r6,MSR_VSX@h
-	andc	r6,r4,r6
-	std	r6,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
-	ld	r4,PACACURRENT(r13)
-	addi	r4,r4,THREAD		/* Get THREAD */
-	li	r6,1
-	stw	r6,THREAD_USED_VSR(r4) /* ... also set thread used vsr */
-	/* enable use of VSX after return */
-	oris	r12,r12,MSR_VSX@h
-	std	r12,_MSR(r1)
-#ifndef CONFIG_SMP
-	/* Update last_task_used_math to 'current' */
-	ld	r4,PACACURRENT(r13)
-	std	r4,0(r3)
-#endif /* CONFIG_SMP */
-	b	fast_exception_return
-#endif /* CONFIG_VSX */
-
-/*
- * Hash table stuff
- */
-	.align	7
-_STATIC(do_hash_page)
-	std	r3,_DAR(r1)
-	std	r4,_DSISR(r1)
-
-	andis.	r0,r4,0xa450		/* weird error? */
-	bne-	handle_page_fault	/* if not, try to insert a HPTE */
-BEGIN_FTR_SECTION
-	andis.	r0,r4,0x0020		/* Is it a segment table fault? */
-	bne-	do_ste_alloc		/* If so handle it */
-END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
-
-	/*
-	 * On iSeries, we soft-disable interrupts here, then
-	 * hard-enable interrupts so that the hash_page code can spin on
-	 * the hash_table_lock without problems on a shared processor.
-	 */
-	DISABLE_INTS
-
-	/*
-	 * Currently, trace_hardirqs_off() will be called by DISABLE_INTS
-	 * and will clobber volatile registers when irq tracing is enabled
-	 * so we need to reload them. It may be possible to be smarter here
-	 * and move the irq tracing elsewhere but let's keep it simple for
-	 * now
-	 */
-#ifdef CONFIG_TRACE_IRQFLAGS
-	ld	r3,_DAR(r1)
-	ld	r4,_DSISR(r1)
-	ld	r5,_TRAP(r1)
-	ld	r12,_MSR(r1)
-	clrrdi	r5,r5,4
-#endif /* CONFIG_TRACE_IRQFLAGS */
-	/*
-	 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
-	 * accessing a userspace segment (even from the kernel). We assume
-	 * kernel addresses always have the high bit set.
-	 */
-	rlwinm	r4,r4,32-25+9,31-9,31-9	/* DSISR_STORE -> _PAGE_RW */
-	rotldi	r0,r3,15		/* Move high bit into MSR_PR posn */
-	orc	r0,r12,r0		/* MSR_PR | ~high_bit */
-	rlwimi	r4,r0,32-13,30,30	/* becomes _PAGE_USER access bit */
-	ori	r4,r4,1			/* add _PAGE_PRESENT */
-	rlwimi	r4,r5,22+2,31-2,31-2	/* Set _PAGE_EXEC if trap is 0x400 */
-
-	/*
-	 * r3 contains the faulting address
-	 * r4 contains the required access permissions
-	 * r5 contains the trap number
-	 *
-	 * at return r3 = 0 for success
-	 */
-	bl	.hash_page		/* build HPTE if possible */
-	cmpdi	r3,0			/* see if hash_page succeeded */
-
-BEGIN_FW_FTR_SECTION
-	/*
-	 * If we had interrupts soft-enabled at the point where the
-	 * DSI/ISI occurred, and an interrupt came in during hash_page,
-	 * handle it now.
-	 * We jump to ret_from_except_lite rather than fast_exception_return
-	 * because ret_from_except_lite will check for and handle pending
-	 * interrupts if necessary.
-	 */
-	beq	13f
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-
-BEGIN_FW_FTR_SECTION
-	/*
-	 * Here we have interrupts hard-disabled, so it is sufficient
-	 * to restore paca->{soft,hard}_enable and get out.
-	 */
-	beq	fast_exc_return_irq	/* Return from exception on success */
-END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
-
-	/* For a hash failure, we don't bother re-enabling interrupts */
-	ble-	12f
-
-	/*
-	 * hash_page couldn't handle it, set soft interrupt enable back
-	 * to what it was before the trap.  Note that .raw_local_irq_restore
-	 * handles any interrupts pending at this point.
-	 */
-	ld	r3,SOFTE(r1)
-	TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
-	bl	.raw_local_irq_restore
-	b	11f
-
-/* Here we have a page fault that hash_page can't handle. */
-handle_page_fault:
-	ENABLE_INTS
-11:	ld	r4,_DAR(r1)
-	ld	r5,_DSISR(r1)
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.do_page_fault
-	cmpdi	r3,0
-	beq+	13f
-	bl	.save_nvgprs
-	mr	r5,r3
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	lwz	r4,_DAR(r1)
-	bl	.bad_page_fault
-	b	.ret_from_except
-
-13:	b	.ret_from_except_lite
-
-/* We have a page fault that hash_page could handle but HV refused
- * the PTE insertion
- */
-12:	bl	.save_nvgprs
-	mr	r5,r3
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	ld	r4,_DAR(r1)
-	bl	.low_hash_fault
-	b	.ret_from_except
-
-	/* here we have a segment miss */
-do_ste_alloc:
-	bl	.ste_allocate		/* try to insert stab entry */
-	cmpdi	r3,0
-	bne-	handle_page_fault
-	b	fast_exception_return
-
-/*
- * r13 points to the PACA, r9 contains the saved CR,
- * r11 and r12 contain the saved SRR0 and SRR1.
- * r9 - r13 are saved in paca->exslb.
- * We assume we aren't going to take any exceptions during this procedure.
- * We assume (DAR >> 60) == 0xc.
- */
-	.align	7
-_GLOBAL(do_stab_bolted)
-	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
-	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
-
-	/* Hash to the primary group */
-	ld	r10,PACASTABVIRT(r13)
-	mfspr	r11,SPRN_DAR
-	srdi	r11,r11,28
-	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
-
-	/* Calculate VSID */
-	/* This is a kernel address, so protovsid = ESID */
-	ASM_VSID_SCRAMBLE(r11, r9, 256M)
-	rldic	r9,r11,12,16	/* r9 = vsid << 12 */
-
-	/* Search the primary group for a free entry */
-1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/
-	andi.	r11,r11,0x80
-	beq	2f
-	addi	r10,r10,16
-	andi.	r11,r10,0x70
-	bne	1b
-
-	/* Stick for only searching the primary group for now.		*/
-	/* At least for now, we use a very simple random castout scheme */
-	/* Use the TB as a random number ;  OR in 1 to avoid entry 0	*/
-	mftb	r11
-	rldic	r11,r11,4,57	/* r11 = (r11 << 4) & 0x70 */
-	ori	r11,r11,0x10
-
-	/* r10 currently points to an ste one past the group of interest */
-	/* make it point to the randomly selected entry			*/
-	subi	r10,r10,128
-	or 	r10,r10,r11	/* r10 is the entry to invalidate	*/
-
-	isync			/* mark the entry invalid		*/
-	ld	r11,0(r10)
-	rldicl	r11,r11,56,1	/* clear the valid bit */
-	rotldi	r11,r11,8
-	std	r11,0(r10)
-	sync
-
-	clrrdi	r11,r11,28	/* Get the esid part of the ste		*/
-	slbie	r11
-
-2:	std	r9,8(r10)	/* Store the vsid part of the ste	*/
-	eieio
-
-	mfspr	r11,SPRN_DAR		/* Get the new esid			*/
-	clrrdi	r11,r11,28	/* Permits a full 32b of ESID		*/
-	ori	r11,r11,0x90	/* Turn on valid and kp			*/
-	std	r11,0(r10)	/* Put new entry back into the stab	*/
-
-	sync
-
-	/* All done -- return from exception. */
-	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
-	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */
-
-	andi.	r10,r12,MSR_RI
-	beq-	unrecov_slb
-
-	mtcrf	0x80,r9			/* restore CR */
-
-	mfmsr	r10
-	clrrdi	r10,r10,2
-	mtmsrd	r10,1
-
-	mtspr	SPRN_SRR0,r11
-	mtspr	SPRN_SRR1,r12
-	ld	r9,PACA_EXSLB+EX_R9(r13)
-	ld	r10,PACA_EXSLB+EX_R10(r13)
-	ld	r11,PACA_EXSLB+EX_R11(r13)
-	ld	r12,PACA_EXSLB+EX_R12(r13)
-	ld	r13,PACA_EXSLB+EX_R13(r13)
-	rfid
-	b	.	/* prevent speculative execution */
-
-/*
- * Space for CPU0's segment table.
- *
- * On iSeries, the hypervisor must fill in at least one entry before
- * we get control (with relocate on).  The address is given to the hv
- * as a page number (see xLparMap below), so this must be at a
- * fixed address (the linker can't compute (u64)&initial_stab >>
- * PAGE_SHIFT).
- */
-	. = STAB0_OFFSET	/* 0x6000 */
-	.globl initial_stab
-initial_stab:
-	.space	4096
-
-#ifdef CONFIG_PPC_PSERIES
-/*
- * Data area reserved for FWNMI option.
- * This address (0x7000) is fixed by the RPA.
- */
-	.= 0x7000
-	.globl fwnmi_data_area
-fwnmi_data_area:
-#endif /* CONFIG_PPC_PSERIES */
-
-	/* iSeries does not use the FWNMI stuff, so it is safe to put
-	 * this here, even if we later allow kernels that will boot on
-	 * both pSeries and iSeries */
-#ifdef CONFIG_PPC_ISERIES
-        . = LPARMAP_PHYS
-	.globl xLparMap
-xLparMap:
-	.quad	HvEsidsToMap		/* xNumberEsids */
-	.quad	HvRangesToMap		/* xNumberRanges */
-	.quad	STAB0_PAGE		/* xSegmentTableOffs */
-	.zero	40			/* xRsvd */
-	/* xEsids (HvEsidsToMap entries of 2 quads) */
-	.quad	PAGE_OFFSET_ESID	/* xKernelEsid */
-	.quad	PAGE_OFFSET_VSID	/* xKernelVsid */
-	.quad	VMALLOC_START_ESID	/* xKernelEsid */
-	.quad	VMALLOC_START_VSID	/* xKernelVsid */
-	/* xRanges (HvRangesToMap entries of 3 quads) */
-	.quad	HvPagesToMap		/* xPages */
-	.quad	0			/* xOffset */
-	.quad	PAGE_OFFSET_VSID << (SID_SHIFT - HW_PAGE_SHIFT)	/* xVPN */
-
-#endif /* CONFIG_PPC_ISERIES */
-
-#ifdef CONFIG_PPC_PSERIES
-        . = 0x8000
-#endif /* CONFIG_PPC_PSERIES */
 
 /*
  * On pSeries and most other platforms, secondary processors spin
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/head_booke.h linux-libre-2.6.31-gnu/arch/powerpc/kernel/head_booke.h
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/head_booke.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/head_booke.h	2009-09-09 18:13:59.000000000 -0400
@@ -256,7 +256,7 @@
 	 * off DE in the DSRR1 value and clearing the debug status.	      \
 	 */								      \
 	mfspr	r10,SPRN_DBSR;		/* check single-step/branch taken */  \
-	andis.	r10,r10,DBSR_IC@h;					      \
+	andis.	r10,r10,(DBSR_IC|DBSR_BT)@h;				      \
 	beq+	2f;							      \
 									      \
 	lis	r10,KERNELBASE@h;	/* check if exception in vectors */   \
@@ -271,7 +271,7 @@
 									      \
 	/* here it looks like we got an inappropriate debug exception. */     \
 1:	rlwinm	r9,r9,0,~MSR_DE;	/* clear DE in the CDRR1 value */     \
-	lis	r10,DBSR_IC@h;		/* clear the IC event */	      \
+	lis	r10,(DBSR_IC|DBSR_BT)@h;	/* clear the IC event */      \
 	mtspr	SPRN_DBSR,r10;						      \
 	/* restore state and get out */					      \
 	lwz	r10,_CCR(r11);						      \
@@ -309,7 +309,7 @@
 	 * off DE in the CSRR1 value and clearing the debug status.	      \
 	 */								      \
 	mfspr	r10,SPRN_DBSR;		/* check single-step/branch taken */  \
-	andis.	r10,r10,DBSR_IC@h;					      \
+	andis.	r10,r10,(DBSR_IC|DBSR_BT)@h;				      \
 	beq+	2f;							      \
 									      \
 	lis	r10,KERNELBASE@h;	/* check if exception in vectors */   \
@@ -317,14 +317,14 @@
 	cmplw	r12,r10;						      \
 	blt+	2f;			/* addr below exception vectors */    \
 									      \
-	lis	r10,DebugCrit@h;						      \
+	lis	r10,DebugCrit@h;					      \
 	ori	r10,r10,DebugCrit@l;					      \
 	cmplw	r12,r10;						      \
 	bgt+	2f;			/* addr above exception vectors */    \
 									      \
 	/* here it looks like we got an inappropriate debug exception. */     \
 1:	rlwinm	r9,r9,0,~MSR_DE;	/* clear DE in the CSRR1 value */     \
-	lis	r10,DBSR_IC@h;		/* clear the IC event */	      \
+	lis	r10,(DBSR_IC|DBSR_BT)@h;	/* clear the IC event */      \
 	mtspr	SPRN_DBSR,r10;						      \
 	/* restore state and get out */					      \
 	lwz	r10,_CCR(r11);						      \
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/init_task.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,10 +9,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/irq.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,7 @@
 #include <linux/bootmem.h>
 #include <linux/pci.h>
 #include <linux/debugfs.h>
+#include <linux/perf_counter.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -117,6 +118,7 @@
 	if (!en)
 		return;
 
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
 		/*
 		 * Do we need to disable preemption here?  Not really: in the
@@ -134,6 +136,12 @@
 		if (local_paca->lppaca_ptr->int_dword.any_int)
 			iseries_handle_interrupts();
 	}
+#endif /* CONFIG_PPC_STD_MMU_64 */
+
+	if (test_perf_counter_pending()) {
+		clear_perf_counter_pending();
+		perf_counter_do_pending();
+	}
 
 	/*
 	 * if (get_paca()->hard_enabled) return;
@@ -248,77 +256,84 @@
 }
 #endif
 
-void do_IRQ(struct pt_regs *regs)
-{
-	struct pt_regs *old_regs = set_irq_regs(regs);
-	unsigned int irq;
 #ifdef CONFIG_IRQSTACKS
+static inline void handle_one_irq(unsigned int irq)
+{
 	struct thread_info *curtp, *irqtp;
-#endif
+	unsigned long saved_sp_limit;
+	struct irq_desc *desc;
 
-	irq_enter();
+	/* Switch to the irq stack to handle this */
+	curtp = current_thread_info();
+	irqtp = hardirq_ctx[smp_processor_id()];
+
+	if (curtp == irqtp) {
+		/* We're already on the irq stack, just handle it */
+		generic_handle_irq(irq);
+		return;
+	}
+
+	desc = irq_desc + irq;
+	saved_sp_limit = current->thread.ksp_limit;
+
+	irqtp->task = curtp->task;
+	irqtp->flags = 0;
 
+	/* Copy the softirq bits in preempt_count so that the
+	 * softirq checks work in the hardirq context. */
+	irqtp->preempt_count = (irqtp->preempt_count & ~SOFTIRQ_MASK) |
+			       (curtp->preempt_count & SOFTIRQ_MASK);
+
+	current->thread.ksp_limit = (unsigned long)irqtp +
+		_ALIGN_UP(sizeof(struct thread_info), 16);
+
+	call_handle_irq(irq, desc, irqtp, desc->handle_irq);
+	current->thread.ksp_limit = saved_sp_limit;
+	irqtp->task = NULL;
+
+	/* Set any flag that may have been set on the
+	 * alternate stack
+	 */
+	if (irqtp->flags)
+		set_bits(irqtp->flags, &curtp->flags);
+}
+#else
+static inline void handle_one_irq(unsigned int irq)
+{
+	generic_handle_irq(irq);
+}
+#endif
+
+static inline void check_stack_overflow(void)
+{
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
-	/* Debugging check for stack overflow: is there less than 2KB free? */
-	{
-		long sp;
+	long sp;
 
-		sp = __get_SP() & (THREAD_SIZE-1);
+	sp = __get_SP() & (THREAD_SIZE-1);
 
-		if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
-			printk("do_IRQ: stack overflow: %ld\n",
-				sp - sizeof(struct thread_info));
-			dump_stack();
-		}
+	/* check for stack overflow: is there less than 2KB free? */
+	if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
+		printk("do_IRQ: stack overflow: %ld\n",
+			sp - sizeof(struct thread_info));
+		dump_stack();
 	}
 #endif
+}
 
-	/*
-	 * Every platform is required to implement ppc_md.get_irq.
-	 * This function will either return an irq number or NO_IRQ to
-	 * indicate there are no more pending.
-	 * The value NO_IRQ_IGNORE is for buggy hardware and means that this
-	 * IRQ has already been handled. -- Tom
-	 */
-	irq = ppc_md.get_irq();
-
-	if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) {
-#ifdef CONFIG_IRQSTACKS
-		/* Switch to the irq stack to handle this */
-		curtp = current_thread_info();
-		irqtp = hardirq_ctx[smp_processor_id()];
-		if (curtp != irqtp) {
-			struct irq_desc *desc = irq_desc + irq;
-			void *handler = desc->handle_irq;
-			unsigned long saved_sp_limit = current->thread.ksp_limit;
-			if (handler == NULL)
-				handler = &__do_IRQ;
-			irqtp->task = curtp->task;
-			irqtp->flags = 0;
+void do_IRQ(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	unsigned int irq;
 
-			/* Copy the softirq bits in preempt_count so that the
-			 * softirq checks work in the hardirq context.
-			 */
-			irqtp->preempt_count =
-				(irqtp->preempt_count & ~SOFTIRQ_MASK) |
-				(curtp->preempt_count & SOFTIRQ_MASK);
+	irq_enter();
 
-			current->thread.ksp_limit = (unsigned long)irqtp +
-				_ALIGN_UP(sizeof(struct thread_info), 16);
-			call_handle_irq(irq, desc, irqtp, handler);
-			current->thread.ksp_limit = saved_sp_limit;
-			irqtp->task = NULL;
+	check_stack_overflow();
 
+	irq = ppc_md.get_irq();
 
-			/* Set any flag that may have been set on the
-			 * alternate stack
-			 */
-			if (irqtp->flags)
-				set_bits(irqtp->flags, &curtp->flags);
-		} else
-#endif
-			generic_handle_irq(irq);
-	} else if (irq != NO_IRQ_IGNORE)
+	if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
+		handle_one_irq(irq);
+	else if (irq != NO_IRQ_IGNORE)
 		/* That's not SMP safe ... but who cares ? */
 		ppc_spurious_interrupts++;
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/lparcfg.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/lparcfg.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/lparcfg.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/lparcfg.c	2009-09-09 18:13:59.000000000 -0400
@@ -169,6 +169,9 @@
 	u8	unallocated_weight;
 	u16	active_procs_in_pool;
 	u16	active_system_procs;
+	u16	phys_platform_procs;
+	u32	max_proc_cap_avail;
+	u32	entitled_proc_cap_avail;
 };
 
 /*
@@ -190,13 +193,18 @@
  *            XX - Unallocated Variable Processor Capacity Weight.
  *              XXXX - Active processors in Physical Processor Pool.
  *                  XXXX  - Processors active on platform.
+ *  R8 (QQQQRRRRRRSSSSSS). if ibm,partition-performance-parameters-level >= 1
+ *	XXXX - Physical platform procs allocated to virtualization.
+ *	    XXXXXX - Max procs capacity % available to the partitions pool.
+ *	          XXXXXX - Entitled procs capacity % available to the
+ *			   partitions pool.
  */
 static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data)
 {
 	unsigned long rc;
-	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
 
-	rc = plpar_hcall(H_GET_PPP, retbuf);
+	rc = plpar_hcall9(H_GET_PPP, retbuf);
 
 	ppp_data->entitlement = retbuf[0];
 	ppp_data->unallocated_entitlement = retbuf[1];
@@ -210,6 +218,10 @@
 	ppp_data->active_procs_in_pool = (retbuf[3] >> 2 * 8) & 0xffff;
 	ppp_data->active_system_procs = retbuf[3] & 0xffff;
 
+	ppp_data->phys_platform_procs = retbuf[4] >> 6 * 8;
+	ppp_data->max_proc_cap_avail = (retbuf[4] >> 3 * 8) & 0xffffff;
+	ppp_data->entitled_proc_cap_avail = retbuf[4] & 0xffffff;
+
 	return rc;
 }
 
@@ -234,6 +246,8 @@
 static void parse_ppp_data(struct seq_file *m)
 {
 	struct hvcall_ppp_data ppp_data;
+	struct device_node *root;
+	const int *perf_level;
 	int rc;
 
 	rc = h_get_ppp(&ppp_data);
@@ -267,6 +281,28 @@
 	seq_printf(m, "capped=%d\n", ppp_data.capped);
 	seq_printf(m, "unallocated_capacity=%lld\n",
 		   ppp_data.unallocated_entitlement);
+
+	/* The last bits of information returned from h_get_ppp are only
+	 * valid if the ibm,partition-performance-parameters-level
+	 * property is >= 1.
+	 */
+	root = of_find_node_by_path("/");
+	if (root) {
+		perf_level = of_get_property(root,
+				"ibm,partition-performance-parameters-level",
+					     NULL);
+		if (perf_level && (*perf_level >= 1)) {
+			seq_printf(m,
+			    "physical_procs_allocated_to_virtualization=%d\n",
+				   ppp_data.phys_platform_procs);
+			seq_printf(m, "max_proc_capacity_available=%d\n",
+				   ppp_data.max_proc_cap_avail);
+			seq_printf(m, "entitled_proc_capacity_available=%d\n",
+				   ppp_data.entitled_proc_cap_avail);
+		}
+
+		of_node_put(root);
+	}
 }
 
 /**
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/Makefile linux-libre-2.6.31-gnu/arch/powerpc/kernel/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,6 +4,8 @@
 
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 CFLAGS_prom_init.o	+= -mno-minimal-toc
 endif
@@ -36,7 +38,7 @@
 				   firmware.o nvram_64.o
 obj64-$(CONFIG_RELOCATABLE)	+= reloc_64.o
 obj-$(CONFIG_PPC64)		+= vdso64/
-obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
+obj-$(CONFIG_ALTIVEC)		+= vecemu.o
 obj-$(CONFIG_PPC_970_NAP)	+= idle_power4.o
 obj-$(CONFIG_PPC_OF)		+= of_device.o of_platform.o prom_parse.o
 obj-$(CONFIG_PPC_CLOCK)		+= clock.o
@@ -82,6 +84,7 @@
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
+obj-$(CONFIG_SWIOTLB)		+= dma-swiotlb.o
 
 pci64-$(CONFIG_PPC64)		+= pci_dn.o isa-bridge.o
 obj-$(CONFIG_PCI)		+= pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
@@ -94,6 +97,10 @@
 
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
+obj-$(CONFIG_PPC_PERF_CTRS)	+= perf_counter.o
+obj64-$(CONFIG_PPC_PERF_CTRS)	+= power4-pmu.o ppc970-pmu.o power5-pmu.o \
+				   power5+-pmu.o power6-pmu.o power7-pmu.o
+obj32-$(CONFIG_PPC_PERF_CTRS)	+= mpc7450-pmu.o
 
 obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
 
@@ -102,12 +109,14 @@
 endif
 
 obj-$(CONFIG_PPC64)		+= $(obj64-y)
+obj-$(CONFIG_PPC32)		+= $(obj32-y)
 
 ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
 obj-y				+= ppc_save_regs.o
 endif
 
 extra-$(CONFIG_PPC_FPU)		+= fpu.o
+extra-$(CONFIG_ALTIVEC)		+= vector.o
 extra-$(CONFIG_PPC64)		+= entry_64.o
 
 extra-y				+= systbl_chk.i
@@ -120,6 +129,7 @@
 systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i
 	$(call cmd,systbl_chk)
 
+ifeq ($(CONFIG_PPC_OF_BOOT_TRAMPOLINE),y)
 $(obj)/built-in.o:		prom_init_check
 
 quiet_cmd_prom_init_check = CALL    $<
@@ -128,5 +138,6 @@
 PHONY += prom_init_check
 prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o
 	$(call cmd,prom_init_check)
+endif
 
 clean-files := vmlinux.lds
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/misc_64.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/misc_64.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/misc_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/misc_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -457,98 +457,6 @@
 	isync
 	blr
 
-#ifdef CONFIG_ALTIVEC
-
-#if 0 /* this has no callers for now */
-/*
- * disable_kernel_altivec()
- * Disable the VMX.
- */
-_GLOBAL(disable_kernel_altivec)
-	mfmsr	r3
-	rldicl	r0,r3,(63-MSR_VEC_LG),1
-	rldicl	r3,r0,(MSR_VEC_LG+1),0
-	mtmsrd	r3			/* disable use of VMX now */
-	isync
-	blr
-#endif /* 0 */
-
-/*
- * giveup_altivec(tsk)
- * Disable VMX for the task given as the argument,
- * and save the vector registers in its thread_struct.
- * Enables the VMX for use in the kernel on return.
- */
-_GLOBAL(giveup_altivec)
-	mfmsr	r5
-	oris	r5,r5,MSR_VEC@h
-	mtmsrd	r5			/* enable use of VMX now */
-	isync
-	cmpdi	0,r3,0
-	beqlr-				/* if no previous owner, done */
-	addi	r3,r3,THREAD		/* want THREAD of task */
-	ld	r5,PT_REGS(r3)
-	cmpdi	0,r5,0
-	SAVE_32VRS(0,r4,r3)
-	mfvscr	vr0
-	li	r4,THREAD_VSCR
-	stvx	vr0,r4,r3
-	beq	1f
-	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-	lis	r3,(MSR_VEC|MSR_VSX)@h
-FTR_SECTION_ELSE
-	lis	r3,MSR_VEC@h
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
-#else
-	lis	r3,MSR_VEC@h
-#endif
-	andc	r4,r4,r3		/* disable FP for previous task */
-	std	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
-	li	r5,0
-	ld	r4,last_task_used_altivec@got(r2)
-	std	r5,0(r4)
-#endif /* CONFIG_SMP */
-	blr
-
-#endif /* CONFIG_ALTIVEC */
-
-#ifdef CONFIG_VSX
-/*
- * __giveup_vsx(tsk)
- * Disable VSX for the task given as the argument.
- * Does NOT save vsx registers.
- * Enables the VSX for use in the kernel on return.
- */
-_GLOBAL(__giveup_vsx)
-	mfmsr	r5
-	oris	r5,r5,MSR_VSX@h
-	mtmsrd	r5			/* enable use of VSX now */
-	isync
-
-	cmpdi	0,r3,0
-	beqlr-				/* if no previous owner, done */
-	addi	r3,r3,THREAD		/* want THREAD of task */
-	ld	r5,PT_REGS(r3)
-	cmpdi	0,r5,0
-	beq	1f
-	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	lis	r3,MSR_VSX@h
-	andc	r4,r4,r3		/* disable VSX for previous task */
-	std	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
-	li	r5,0
-	ld	r4,last_task_used_vsx@got(r2)
-	std	r5,0(r4)
-#endif /* CONFIG_SMP */
-	blr
-
-#endif /* CONFIG_VSX */
-
 /* kexec_wait(phys_cpu)
  *
  * wait for the flag to change, indicating this kernel is going away but
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/module.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,8 +43,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/mpc7450-pmu.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/mpc7450-pmu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/mpc7450-pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/mpc7450-pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,417 @@
+/*
+ * Performance counter support for MPC7450-family processors.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/string.h>
+#include <linux/perf_counter.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+#define N_COUNTER	6	/* Number of hardware counters */
+#define MAX_ALT		3	/* Maximum number of event alternative codes */
+
+/*
+ * Bits in event code for MPC7450 family
+ */
+#define PM_THRMULT_MSKS	0x40000
+#define PM_THRESH_SH	12
+#define PM_THRESH_MSK	0x3f
+#define PM_PMC_SH	8
+#define PM_PMC_MSK	7
+#define PM_PMCSEL_MSK	0x7f
+
+/*
+ * Classify events according to how specific their PMC requirements are.
+ * Result is:
+ *	0: can go on any PMC
+ *	1: can go on PMCs 1-4
+ *	2: can go on PMCs 1,2,4
+ *	3: can go on PMCs 1 or 2
+ *	4: can only go on one PMC
+ *	-1: event code is invalid
+ */
+#define N_CLASSES	5
+
+static int mpc7450_classify_event(u32 event)
+{
+	int pmc;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc) {
+		if (pmc > N_COUNTER)
+			return -1;
+		return 4;
+	}
+	event &= PM_PMCSEL_MSK;
+	if (event <= 1)
+		return 0;
+	if (event <= 7)
+		return 1;
+	if (event <= 13)
+		return 2;
+	if (event <= 22)
+		return 3;
+	return -1;
+}
+
+/*
+ * Events using threshold and possible threshold scale:
+ *	code	scale?	name
+ *	11e	N	PM_INSTQ_EXCEED_CYC
+ *	11f	N	PM_ALTV_IQ_EXCEED_CYC
+ *	128	Y	PM_DTLB_SEARCH_EXCEED_CYC
+ *	12b	Y	PM_LD_MISS_EXCEED_L1_CYC
+ *	220	N	PM_CQ_EXCEED_CYC
+ *	30c	N	PM_GPR_RB_EXCEED_CYC
+ *	30d	?	PM_FPR_IQ_EXCEED_CYC ?
+ *	311	Y	PM_ITLB_SEARCH_EXCEED
+ *	410	N	PM_GPR_IQ_EXCEED_CYC
+ */
+
+/*
+ * Return use of threshold and threshold scale bits:
+ * 0 = uses neither, 1 = uses threshold, 2 = uses both
+ */
+static int mpc7450_threshold_use(u32 event)
+{
+	int pmc, sel;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	sel = event & PM_PMCSEL_MSK;
+	switch (pmc) {
+	case 1:
+		if (sel == 0x1e || sel == 0x1f)
+			return 1;
+		if (sel == 0x28 || sel == 0x2b)
+			return 2;
+		break;
+	case 2:
+		if (sel == 0x20)
+			return 1;
+		break;
+	case 3:
+		if (sel == 0xc || sel == 0xd)
+			return 1;
+		if (sel == 0x11)
+			return 2;
+		break;
+	case 4:
+		if (sel == 0x10)
+			return 1;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Layout of constraint bits:
+ * 33222222222211111111110000000000
+ * 10987654321098765432109876543210
+ *  |<    ><  > < > < ><><><><><><>
+ *  TS TV   G4   G3  G2P6P5P4P3P2P1
+ *
+ * P1 - P6
+ *	0 - 11: Count of events needing PMC1 .. PMC6
+ *
+ * G2
+ *	12 - 14: Count of events needing PMC1 or PMC2
+ *
+ * G3
+ *	16 - 18: Count of events needing PMC1, PMC2 or PMC4
+ *
+ * G4
+ *	20 - 23: Count of events needing PMC1, PMC2, PMC3 or PMC4
+ *
+ * TV
+ *	24 - 29: Threshold value requested
+ *
+ * TS
+ *	30: Threshold scale value requested
+ */
+
+static u32 pmcbits[N_COUNTER][2] = {
+	{ 0x00844002, 0x00111001 },	/* PMC1 mask, value: P1,G2,G3,G4 */
+	{ 0x00844008, 0x00111004 },	/* PMC2: P2,G2,G3,G4 */
+	{ 0x00800020, 0x00100010 },	/* PMC3: P3,G4 */
+	{ 0x00840080, 0x00110040 },	/* PMC4: P4,G3,G4 */
+	{ 0x00000200, 0x00000100 },	/* PMC5: P5 */
+	{ 0x00000800, 0x00000400 }	/* PMC6: P6 */
+};
+
+static u32 classbits[N_CLASSES - 1][2] = {
+	{ 0x00000000, 0x00000000 },	/* class 0: no constraint */
+	{ 0x00800000, 0x00100000 },	/* class 1: G4 */
+	{ 0x00040000, 0x00010000 },	/* class 2: G3 */
+	{ 0x00004000, 0x00001000 },	/* class 3: G2 */
+};
+
+static int mpc7450_get_constraint(u64 event, unsigned long *maskp,
+				  unsigned long *valp)
+{
+	int pmc, class;
+	u32 mask, value;
+	int thresh, tuse;
+
+	class = mpc7450_classify_event(event);
+	if (class < 0)
+		return -1;
+	if (class == 4) {
+		pmc = ((unsigned int)event >> PM_PMC_SH) & PM_PMC_MSK;
+		mask  = pmcbits[pmc - 1][0];
+		value = pmcbits[pmc - 1][1];
+	} else {
+		mask  = classbits[class][0];
+		value = classbits[class][1];
+	}
+
+	tuse = mpc7450_threshold_use(event);
+	if (tuse) {
+		thresh = ((unsigned int)event >> PM_THRESH_SH) & PM_THRESH_MSK;
+		mask  |= 0x3f << 24;
+		value |= thresh << 24;
+		if (tuse == 2) {
+			mask |= 0x40000000;
+			if ((unsigned int)event & PM_THRMULT_MSKS)
+				value |= 0x40000000;
+		}
+	}
+
+	*maskp = mask;
+	*valp = value;
+	return 0;
+}
+
+static const unsigned int event_alternatives[][MAX_ALT] = {
+	{ 0x217, 0x317 },		/* PM_L1_DCACHE_MISS */
+	{ 0x418, 0x50f, 0x60f },	/* PM_SNOOP_RETRY */
+	{ 0x502, 0x602 },		/* PM_L2_HIT */
+	{ 0x503, 0x603 },		/* PM_L3_HIT */
+	{ 0x504, 0x604 },		/* PM_L2_ICACHE_MISS */
+	{ 0x505, 0x605 },		/* PM_L3_ICACHE_MISS */
+	{ 0x506, 0x606 },		/* PM_L2_DCACHE_MISS */
+	{ 0x507, 0x607 },		/* PM_L3_DCACHE_MISS */
+	{ 0x50a, 0x623 },		/* PM_LD_HIT_L3 */
+	{ 0x50b, 0x624 },		/* PM_ST_HIT_L3 */
+	{ 0x50d, 0x60d },		/* PM_L2_TOUCH_HIT */
+	{ 0x50e, 0x60e },		/* PM_L3_TOUCH_HIT */
+	{ 0x512, 0x612 },		/* PM_INT_LOCAL */
+	{ 0x513, 0x61d },		/* PM_L2_MISS */
+	{ 0x514, 0x61e },		/* PM_L3_MISS */
+};
+
+/*
+ * Scan the alternatives table for a match and return the
+ * index into the alternatives table if found, else -1.
+ */
+static int find_alternative(u32 event)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
+		if (event < event_alternatives[i][0])
+			break;
+		for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
+			if (event == event_alternatives[i][j])
+				return i;
+	}
+	return -1;
+}
+
+static int mpc7450_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	int i, j, nalt = 1;
+	u32 ae;
+
+	alt[0] = event;
+	nalt = 1;
+	i = find_alternative((u32)event);
+	if (i >= 0) {
+		for (j = 0; j < MAX_ALT; ++j) {
+			ae = event_alternatives[i][j];
+			if (ae && ae != (u32)event)
+				alt[nalt++] = ae;
+		}
+	}
+	return nalt;
+}
+
+/*
+ * Bitmaps of which PMCs each class can use for classes 0 - 3.
+ * Bit i is set if PMC i+1 is usable.
+ */
+static const u8 classmap[N_CLASSES] = {
+	0x3f, 0x0f, 0x0b, 0x03, 0
+};
+
+/* Bit position and width of each PMCSEL field */
+static const int pmcsel_shift[N_COUNTER] = {
+	6,	0,	27,	22,	17,	11
+};
+static const u32 pmcsel_mask[N_COUNTER] = {
+	0x7f,	0x3f,	0x1f,	0x1f,	0x1f,	0x3f
+};
+
+/*
+ * Compute MMCR0/1/2 values for a set of events.
+ */
+static int mpc7450_compute_mmcr(u64 event[], int n_ev,
+				unsigned int hwc[], unsigned long mmcr[])
+{
+	u8 event_index[N_CLASSES][N_COUNTER];
+	int n_classevent[N_CLASSES];
+	int i, j, class, tuse;
+	u32 pmc_inuse = 0, pmc_avail;
+	u32 mmcr0 = 0, mmcr1 = 0, mmcr2 = 0;
+	u32 ev, pmc, thresh;
+
+	if (n_ev > N_COUNTER)
+		return -1;
+
+	/* First pass: count usage in each class */
+	for (i = 0; i < N_CLASSES; ++i)
+		n_classevent[i] = 0;
+	for (i = 0; i < n_ev; ++i) {
+		class = mpc7450_classify_event(event[i]);
+		if (class < 0)
+			return -1;
+		j = n_classevent[class]++;
+		event_index[class][j] = i;
+	}
+
+	/* Second pass: allocate PMCs from most specific event to least */
+	for (class = N_CLASSES - 1; class >= 0; --class) {
+		for (i = 0; i < n_classevent[class]; ++i) {
+			ev = event[event_index[class][i]];
+			if (class == 4) {
+				pmc = (ev >> PM_PMC_SH) & PM_PMC_MSK;
+				if (pmc_inuse & (1 << (pmc - 1)))
+					return -1;
+			} else {
+				/* Find a suitable PMC */
+				pmc_avail = classmap[class] & ~pmc_inuse;
+				if (!pmc_avail)
+					return -1;
+				pmc = ffs(pmc_avail);
+			}
+			pmc_inuse |= 1 << (pmc - 1);
+
+			tuse = mpc7450_threshold_use(ev);
+			if (tuse) {
+				thresh = (ev >> PM_THRESH_SH) & PM_THRESH_MSK;
+				mmcr0 |= thresh << 16;
+				if (tuse == 2 && (ev & PM_THRMULT_MSKS))
+					mmcr2 = 0x80000000;
+			}
+			ev &= pmcsel_mask[pmc - 1];
+			ev <<= pmcsel_shift[pmc - 1];
+			if (pmc <= 2)
+				mmcr0 |= ev;
+			else
+				mmcr1 |= ev;
+			hwc[event_index[class][i]] = pmc - 1;
+		}
+	}
+
+	if (pmc_inuse & 1)
+		mmcr0 |= MMCR0_PMC1CE;
+	if (pmc_inuse & 0x3e)
+		mmcr0 |= MMCR0_PMCnCE;
+
+	/* Return MMCRx values */
+	mmcr[0] = mmcr0;
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcr2;
+	return 0;
+}
+
+/*
+ * Disable counting by a PMC.
+ * Note that the pmc argument is 0-based here, not 1-based.
+ */
+static void mpc7450_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	if (pmc <= 1)
+		mmcr[0] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]);
+	else
+		mmcr[1] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]);
+}
+
+static int mpc7450_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= 1,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= 2,
+	[PERF_COUNT_HW_CACHE_MISSES]		= 0x217, /* PM_L1_DCACHE_MISS */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x122, /* PM_BR_CMPL */
+	[PERF_COUNT_HW_BRANCH_MISSES] 		= 0x41c, /* PM_BR_MPRED */
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int mpc7450_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x225	},
+		[C(OP_WRITE)] = {	0,		0x227	},
+		[C(OP_PREFETCH)] = {	0,		0	},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x129,		0x115	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	0x634,		0	},
+	},
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0	},
+		[C(OP_WRITE)] = {	0,		0	},
+		[C(OP_PREFETCH)] = {	0,		0	},
+	},
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x312	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(ITLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x223	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x122,		0x41c	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+};
+
+struct power_pmu mpc7450_pmu = {
+	.name			= "MPC7450 family",
+	.n_counter		= N_COUNTER,
+	.max_alternatives	= MAX_ALT,
+	.add_fields		= 0x00111555ul,
+	.test_adder		= 0x00301000ul,
+	.compute_mmcr		= mpc7450_compute_mmcr,
+	.get_constraint		= mpc7450_get_constraint,
+	.get_alternatives	= mpc7450_get_alternatives,
+	.disable_pmc		= mpc7450_disable_pmc,
+	.n_generic		= ARRAY_SIZE(mpc7450_generic_events),
+	.generic_events		= mpc7450_generic_events,
+	.cache_events		= &mpc7450_cache_events,
+};
+
+static int init_mpc7450_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450"))
+		return -ENODEV;
+
+	return register_power_pmu(&mpc7450_pmu);
+}
+
+arch_initcall(init_mpc7450_pmu);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/of_device.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/of_device.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/of_device.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/of_device.c	2009-09-09 18:13:59.000000000 -0400
@@ -76,7 +76,7 @@
 	dev->dev.archdata.of_node = np;
 
 	if (bus_id)
-		dev_set_name(&dev->dev, bus_id);
+		dev_set_name(&dev->dev, "%s", bus_id);
 	else
 		of_device_make_bus_id(dev);
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/paca.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/paca.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/paca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/paca.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,8 @@
  * field correctly */
 extern unsigned long __toc_start;
 
+#ifdef CONFIG_PPC_BOOK3S
+
 /*
  * The structure which the hypervisor knows about - this structure
  * should not cross a page boundary.  The vpa_init/register_vpa call
@@ -41,6 +43,10 @@
 	},
 };
 
+#endif /* CONFIG_PPC_BOOK3S */
+
+#ifdef CONFIG_PPC_STD_MMU_64
+
 /*
  * 3 persistent SLBs are registered here.  The buffer will be zero
  * initially, hence will all be invaild until we actually write them.
@@ -52,6 +58,8 @@
 	},
 };
 
+#endif /* CONFIG_PPC_STD_MMU_64 */
+
 /* The Paca is an array with one entry per processor.  Each contains an
  * lppaca, which contains the information shared between the
  * hypervisor and Linux.
@@ -77,15 +85,19 @@
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 		struct paca_struct *new_paca = &paca[cpu];
 
+#ifdef CONFIG_PPC_BOOK3S
 		new_paca->lppaca_ptr = &lppaca[cpu];
+#endif
 		new_paca->lock_token = 0x8000;
 		new_paca->paca_index = cpu;
 		new_paca->kernel_toc = kernel_toc;
 		new_paca->kernelbase = (unsigned long) _stext;
 		new_paca->kernel_msr = MSR_KERNEL;
 		new_paca->hw_cpu_id = 0xffff;
-		new_paca->slb_shadow_ptr = &slb_shadow[cpu];
 		new_paca->__current = &init_task;
+#ifdef CONFIG_PPC_STD_MMU_64
+		new_paca->slb_shadow_ptr = &slb_shadow[cpu];
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci_32.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci_32.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,6 @@
 
 void pcibios_make_OF_bus_map(void);
 
-static void fixup_broken_pcnet32(struct pci_dev* dev);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
 #ifdef CONFIG_PPC_OF
 static u8* pci_to_OF_bus_map;
@@ -72,16 +71,6 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl); 
 
 static void
-fixup_broken_pcnet32(struct pci_dev* dev)
-{
-	if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
-		dev->vendor = PCI_VENDOR_ID_AMD;
-		pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT,	PCI_ANY_ID,			fixup_broken_pcnet32);
-
-static void
 fixup_cpc710_pci64(struct pci_dev* dev)
 {
 	/* Hide the PCI64 BARs from the kernel as their content doesn't
@@ -447,14 +436,6 @@
 
 subsys_initcall(pcibios_init);
 
-/* the next one is stolen from the alpha port... */
-void __init
-pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-	/* XXX FIXME - update OF device tree node interrupt property */
-}
-
 static struct pci_controller*
 pci_bus_to_hose(int bus)
 {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci_64.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci_64.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,16 +43,6 @@
 unsigned long pci_io_base = ISA_IO_BASE;
 EXPORT_SYMBOL(pci_io_base);
 
-static void fixup_broken_pcnet32(struct pci_dev* dev)
-{
-	if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
-		dev->vendor = PCI_VENDOR_ID_AMD;
-		pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
-
-
 static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
 {
 	const u32 *prop;
@@ -430,6 +420,9 @@
 	 * so flushing the hash table is the only sane way to make sure
 	 * that no hash entries are covering that removed bridge area
 	 * while still allowing other busses overlapping those pages
+	 *
+	 * Note: If we ever support P2P hotplug on Book3E, we'll have
+	 * to do an appropriate TLB flush here too
 	 */
 	if (bus->self) {
 		struct resource *res = bus->resource[0];
@@ -437,8 +430,10 @@
 		pr_debug("IO unmapping for PCI-PCI bridge %s\n",
 			 pci_name(bus->self));
 
+#ifdef CONFIG_PPC_STD_MMU_64
 		__flush_hash_table_range(&init_mm, res->start + _IO_BASE,
 					 res->end + _IO_BASE + 1);
+#endif
 		return 0;
 	}
 
@@ -511,7 +506,7 @@
 	pr_debug("IO mapping for PHB %s\n", hose->dn->full_name);
 	pr_debug("  phys=0x%016llx, virt=0x%p (alloc=0x%p)\n",
 		 hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
-	pr_debug("  size=0x%016lx (alloc=0x%016lx)\n",
+	pr_debug("  size=0x%016llx (alloc=0x%016lx)\n",
 		 hose->pci_io_size, size_page);
 
 	/* Establish the mapping */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci-common.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci-common.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci-common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci-common.c	2009-09-09 18:13:59.000000000 -0400
@@ -1505,7 +1505,7 @@
  * rest of the code later, for now, keep it as-is as our main
  * resource allocation function doesn't deal with sub-trees yet.
  */
-void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
+void pcibios_claim_one_bus(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	struct pci_bus *child_bus;
@@ -1533,7 +1533,6 @@
 	list_for_each_entry(child_bus, &bus->children, node)
 		pcibios_claim_one_bus(child_bus);
 }
-EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
 
 
 /* pcibios_finish_adding_to_bus
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci_dn.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci_dn.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/pci_dn.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/pci_dn.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,6 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/ppc-pci.h>
 #include <asm/firmware.h>
 
@@ -35,7 +34,7 @@
  * Traverse_func that inits the PCI fields of the device node.
  * NOTE: this *must* be done before read/write config to the device.
  */
-static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
+void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
 {
 	struct pci_controller *phb = data;
 	const int *type =
@@ -184,29 +183,6 @@
 }
 EXPORT_SYMBOL(fetch_dev_dn);
 
-static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
-{
-	struct device_node *np = node;
-	struct pci_dn *pci = NULL;
-	int err = NOTIFY_OK;
-
-	switch (action) {
-	case PSERIES_RECONFIG_ADD:
-		pci = np->parent->data;
-		if (pci)
-			update_dn_pci_info(np, pci->phb);
-		break;
-	default:
-		err = NOTIFY_DONE;
-		break;
-	}
-	return err;
-}
-
-static struct notifier_block pci_dn_reconfig_nb = {
-	.notifier_call = pci_dn_reconfig_notifier,
-};
-
 /** 
  * pci_devs_phb_init - Initialize phbs and pci devs under them.
  * 
@@ -223,6 +199,4 @@
 	/* This must be done first so the device nodes have valid pci info! */
 	list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
 		pci_devs_phb_init_dynamic(phb);
-
-	pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/perf_counter.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/perf_counter.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/perf_counter.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/perf_counter.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1314 @@
+/*
+ * Performance counter support - powerpc architecture code
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/perf_counter.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <asm/reg.h>
+#include <asm/pmc.h>
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/ptrace.h>
+
+struct cpu_hw_counters {
+	int n_counters;
+	int n_percpu;
+	int disabled;
+	int n_added;
+	int n_limited;
+	u8  pmcs_enabled;
+	struct perf_counter *counter[MAX_HWCOUNTERS];
+	u64 events[MAX_HWCOUNTERS];
+	unsigned int flags[MAX_HWCOUNTERS];
+	unsigned long mmcr[3];
+	struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS];
+	u8  limited_hwidx[MAX_LIMITED_HWCOUNTERS];
+};
+DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters);
+
+struct power_pmu *ppmu;
+
+/*
+ * Normally, to ignore kernel events we set the FCS (freeze counters
+ * in supervisor mode) bit in MMCR0, but if the kernel runs with the
+ * hypervisor bit set in the MSR, or if we are running on a processor
+ * where the hypervisor bit is forced to 1 (as on Apple G5 processors),
+ * then we need to use the FCHV bit to ignore kernel events.
+ */
+static unsigned int freeze_counters_kernel = MMCR0_FCS;
+
+/*
+ * 32-bit doesn't have MMCRA but does have an MMCR2,
+ * and a few other names are different.
+ */
+#ifdef CONFIG_PPC32
+
+#define MMCR0_FCHV		0
+#define MMCR0_PMCjCE		MMCR0_PMCnCE
+
+#define SPRN_MMCRA		SPRN_MMCR2
+#define MMCRA_SAMPLE_ENABLE	0
+
+static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
+{
+	return 0;
+}
+static inline void perf_set_pmu_inuse(int inuse) { }
+static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { }
+static inline u32 perf_get_misc_flags(struct pt_regs *regs)
+{
+	return 0;
+}
+static inline void perf_read_regs(struct pt_regs *regs) { }
+static inline int perf_intr_is_nmi(struct pt_regs *regs)
+{
+	return 0;
+}
+
+#endif /* CONFIG_PPC32 */
+
+/*
+ * Things that are specific to 64-bit implementations.
+ */
+#ifdef CONFIG_PPC64
+
+static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
+{
+	unsigned long mmcra = regs->dsisr;
+
+	if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) {
+		unsigned long slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT;
+		if (slot > 1)
+			return 4 * (slot - 1);
+	}
+	return 0;
+}
+
+static inline void perf_set_pmu_inuse(int inuse)
+{
+	get_lppaca()->pmcregs_in_use = inuse;
+}
+
+/*
+ * The user wants a data address recorded.
+ * If we're not doing instruction sampling, give them the SDAR
+ * (sampled data address).  If we are doing instruction sampling, then
+ * only give them the SDAR if it corresponds to the instruction
+ * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC
+ * bit in MMCRA.
+ */
+static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
+{
+	unsigned long mmcra = regs->dsisr;
+	unsigned long sdsync = (ppmu->flags & PPMU_ALT_SIPR) ?
+		POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC;
+
+	if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync))
+		*addrp = mfspr(SPRN_SDAR);
+}
+
+static inline u32 perf_get_misc_flags(struct pt_regs *regs)
+{
+	unsigned long mmcra = regs->dsisr;
+
+	if (TRAP(regs) != 0xf00)
+		return 0;	/* not a PMU interrupt */
+
+	if (ppmu->flags & PPMU_ALT_SIPR) {
+		if (mmcra & POWER6_MMCRA_SIHV)
+			return PERF_EVENT_MISC_HYPERVISOR;
+		return (mmcra & POWER6_MMCRA_SIPR) ?
+			PERF_EVENT_MISC_USER : PERF_EVENT_MISC_KERNEL;
+	}
+	if (mmcra & MMCRA_SIHV)
+		return PERF_EVENT_MISC_HYPERVISOR;
+	return (mmcra & MMCRA_SIPR) ? PERF_EVENT_MISC_USER :
+		PERF_EVENT_MISC_KERNEL;
+}
+
+/*
+ * Overload regs->dsisr to store MMCRA so we only need to read it once
+ * on each interrupt.
+ */
+static inline void perf_read_regs(struct pt_regs *regs)
+{
+	regs->dsisr = mfspr(SPRN_MMCRA);
+}
+
+/*
+ * If interrupts were soft-disabled when a PMU interrupt occurs, treat
+ * it as an NMI.
+ */
+static inline int perf_intr_is_nmi(struct pt_regs *regs)
+{
+	return !regs->softe;
+}
+
+#endif /* CONFIG_PPC64 */
+
+static void perf_counter_interrupt(struct pt_regs *regs);
+
+void perf_counter_print_debug(void)
+{
+}
+
+/*
+ * Read one performance monitor counter (PMC).
+ */
+static unsigned long read_pmc(int idx)
+{
+	unsigned long val;
+
+	switch (idx) {
+	case 1:
+		val = mfspr(SPRN_PMC1);
+		break;
+	case 2:
+		val = mfspr(SPRN_PMC2);
+		break;
+	case 3:
+		val = mfspr(SPRN_PMC3);
+		break;
+	case 4:
+		val = mfspr(SPRN_PMC4);
+		break;
+	case 5:
+		val = mfspr(SPRN_PMC5);
+		break;
+	case 6:
+		val = mfspr(SPRN_PMC6);
+		break;
+#ifdef CONFIG_PPC64
+	case 7:
+		val = mfspr(SPRN_PMC7);
+		break;
+	case 8:
+		val = mfspr(SPRN_PMC8);
+		break;
+#endif /* CONFIG_PPC64 */
+	default:
+		printk(KERN_ERR "oops trying to read PMC%d\n", idx);
+		val = 0;
+	}
+	return val;
+}
+
+/*
+ * Write one PMC.
+ */
+static void write_pmc(int idx, unsigned long val)
+{
+	switch (idx) {
+	case 1:
+		mtspr(SPRN_PMC1, val);
+		break;
+	case 2:
+		mtspr(SPRN_PMC2, val);
+		break;
+	case 3:
+		mtspr(SPRN_PMC3, val);
+		break;
+	case 4:
+		mtspr(SPRN_PMC4, val);
+		break;
+	case 5:
+		mtspr(SPRN_PMC5, val);
+		break;
+	case 6:
+		mtspr(SPRN_PMC6, val);
+		break;
+#ifdef CONFIG_PPC64
+	case 7:
+		mtspr(SPRN_PMC7, val);
+		break;
+	case 8:
+		mtspr(SPRN_PMC8, val);
+		break;
+#endif /* CONFIG_PPC64 */
+	default:
+		printk(KERN_ERR "oops trying to write PMC%d\n", idx);
+	}
+}
+
+/*
+ * Check if a set of events can all go on the PMU at once.
+ * If they can't, this will look at alternative codes for the events
+ * and see if any combination of alternative codes is feasible.
+ * The feasible set is returned in event[].
+ */
+static int power_check_constraints(u64 event[], unsigned int cflags[],
+				   int n_ev)
+{
+	unsigned long mask, value, nv;
+	u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
+	unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
+	unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
+	unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS];
+	int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS];
+	int i, j;
+	unsigned long addf = ppmu->add_fields;
+	unsigned long tadd = ppmu->test_adder;
+
+	if (n_ev > ppmu->n_counter)
+		return -1;
+
+	/* First see if the events will go on as-is */
+	for (i = 0; i < n_ev; ++i) {
+		if ((cflags[i] & PPMU_LIMITED_PMC_REQD)
+		    && !ppmu->limited_pmc_event(event[i])) {
+			ppmu->get_alternatives(event[i], cflags[i],
+					       alternatives[i]);
+			event[i] = alternatives[i][0];
+		}
+		if (ppmu->get_constraint(event[i], &amasks[i][0],
+					 &avalues[i][0]))
+			return -1;
+	}
+	value = mask = 0;
+	for (i = 0; i < n_ev; ++i) {
+		nv = (value | avalues[i][0]) + (value & avalues[i][0] & addf);
+		if ((((nv + tadd) ^ value) & mask) != 0 ||
+		    (((nv + tadd) ^ avalues[i][0]) & amasks[i][0]) != 0)
+			break;
+		value = nv;
+		mask |= amasks[i][0];
+	}
+	if (i == n_ev)
+		return 0;	/* all OK */
+
+	/* doesn't work, gather alternatives... */
+	if (!ppmu->get_alternatives)
+		return -1;
+	for (i = 0; i < n_ev; ++i) {
+		choice[i] = 0;
+		n_alt[i] = ppmu->get_alternatives(event[i], cflags[i],
+						  alternatives[i]);
+		for (j = 1; j < n_alt[i]; ++j)
+			ppmu->get_constraint(alternatives[i][j],
+					     &amasks[i][j], &avalues[i][j]);
+	}
+
+	/* enumerate all possibilities and see if any will work */
+	i = 0;
+	j = -1;
+	value = mask = nv = 0;
+	while (i < n_ev) {
+		if (j >= 0) {
+			/* we're backtracking, restore context */
+			value = svalues[i];
+			mask = smasks[i];
+			j = choice[i];
+		}
+		/*
+		 * See if any alternative k for event i,
+		 * where k > j, will satisfy the constraints.
+		 */
+		while (++j < n_alt[i]) {
+			nv = (value | avalues[i][j]) +
+				(value & avalues[i][j] & addf);
+			if ((((nv + tadd) ^ value) & mask) == 0 &&
+			    (((nv + tadd) ^ avalues[i][j])
+			     & amasks[i][j]) == 0)
+				break;
+		}
+		if (j >= n_alt[i]) {
+			/*
+			 * No feasible alternative, backtrack
+			 * to event i-1 and continue enumerating its
+			 * alternatives from where we got up to.
+			 */
+			if (--i < 0)
+				return -1;
+		} else {
+			/*
+			 * Found a feasible alternative for event i,
+			 * remember where we got up to with this event,
+			 * go on to the next event, and start with
+			 * the first alternative for it.
+			 */
+			choice[i] = j;
+			svalues[i] = value;
+			smasks[i] = mask;
+			value = nv;
+			mask |= amasks[i][j];
+			++i;
+			j = -1;
+		}
+	}
+
+	/* OK, we have a feasible combination, tell the caller the solution */
+	for (i = 0; i < n_ev; ++i)
+		event[i] = alternatives[i][choice[i]];
+	return 0;
+}
+
+/*
+ * Check if newly-added counters have consistent settings for
+ * exclude_{user,kernel,hv} with each other and any previously
+ * added counters.
+ */
+static int check_excludes(struct perf_counter **ctrs, unsigned int cflags[],
+			  int n_prev, int n_new)
+{
+	int eu = 0, ek = 0, eh = 0;
+	int i, n, first;
+	struct perf_counter *counter;
+
+	n = n_prev + n_new;
+	if (n <= 1)
+		return 0;
+
+	first = 1;
+	for (i = 0; i < n; ++i) {
+		if (cflags[i] & PPMU_LIMITED_PMC_OK) {
+			cflags[i] &= ~PPMU_LIMITED_PMC_REQD;
+			continue;
+		}
+		counter = ctrs[i];
+		if (first) {
+			eu = counter->attr.exclude_user;
+			ek = counter->attr.exclude_kernel;
+			eh = counter->attr.exclude_hv;
+			first = 0;
+		} else if (counter->attr.exclude_user != eu ||
+			   counter->attr.exclude_kernel != ek ||
+			   counter->attr.exclude_hv != eh) {
+			return -EAGAIN;
+		}
+	}
+
+	if (eu || ek || eh)
+		for (i = 0; i < n; ++i)
+			if (cflags[i] & PPMU_LIMITED_PMC_OK)
+				cflags[i] |= PPMU_LIMITED_PMC_REQD;
+
+	return 0;
+}
+
+static void power_pmu_read(struct perf_counter *counter)
+{
+	s64 val, delta, prev;
+
+	if (!counter->hw.idx)
+		return;
+	/*
+	 * Performance monitor interrupts come even when interrupts
+	 * are soft-disabled, as long as interrupts are hard-enabled.
+	 * Therefore we treat them like NMIs.
+	 */
+	do {
+		prev = atomic64_read(&counter->hw.prev_count);
+		barrier();
+		val = read_pmc(counter->hw.idx);
+	} while (atomic64_cmpxchg(&counter->hw.prev_count, prev, val) != prev);
+
+	/* The counters are only 32 bits wide */
+	delta = (val - prev) & 0xfffffffful;
+	atomic64_add(delta, &counter->count);
+	atomic64_sub(delta, &counter->hw.period_left);
+}
+
+/*
+ * On some machines, PMC5 and PMC6 can't be written, don't respect
+ * the freeze conditions, and don't generate interrupts.  This tells
+ * us if `counter' is using such a PMC.
+ */
+static int is_limited_pmc(int pmcnum)
+{
+	return (ppmu->flags & PPMU_LIMITED_PMC5_6)
+		&& (pmcnum == 5 || pmcnum == 6);
+}
+
+static void freeze_limited_counters(struct cpu_hw_counters *cpuhw,
+				    unsigned long pmc5, unsigned long pmc6)
+{
+	struct perf_counter *counter;
+	u64 val, prev, delta;
+	int i;
+
+	for (i = 0; i < cpuhw->n_limited; ++i) {
+		counter = cpuhw->limited_counter[i];
+		if (!counter->hw.idx)
+			continue;
+		val = (counter->hw.idx == 5) ? pmc5 : pmc6;
+		prev = atomic64_read(&counter->hw.prev_count);
+		counter->hw.idx = 0;
+		delta = (val - prev) & 0xfffffffful;
+		atomic64_add(delta, &counter->count);
+	}
+}
+
+static void thaw_limited_counters(struct cpu_hw_counters *cpuhw,
+				  unsigned long pmc5, unsigned long pmc6)
+{
+	struct perf_counter *counter;
+	u64 val;
+	int i;
+
+	for (i = 0; i < cpuhw->n_limited; ++i) {
+		counter = cpuhw->limited_counter[i];
+		counter->hw.idx = cpuhw->limited_hwidx[i];
+		val = (counter->hw.idx == 5) ? pmc5 : pmc6;
+		atomic64_set(&counter->hw.prev_count, val);
+		perf_counter_update_userpage(counter);
+	}
+}
+
+/*
+ * Since limited counters don't respect the freeze conditions, we
+ * have to read them immediately after freezing or unfreezing the
+ * other counters.  We try to keep the values from the limited
+ * counters as consistent as possible by keeping the delay (in
+ * cycles and instructions) between freezing/unfreezing and reading
+ * the limited counters as small and consistent as possible.
+ * Therefore, if any limited counters are in use, we read them
+ * both, and always in the same order, to minimize variability,
+ * and do it inside the same asm that writes MMCR0.
+ */
+static void write_mmcr0(struct cpu_hw_counters *cpuhw, unsigned long mmcr0)
+{
+	unsigned long pmc5, pmc6;
+
+	if (!cpuhw->n_limited) {
+		mtspr(SPRN_MMCR0, mmcr0);
+		return;
+	}
+
+	/*
+	 * Write MMCR0, then read PMC5 and PMC6 immediately.
+	 * To ensure we don't get a performance monitor interrupt
+	 * between writing MMCR0 and freezing/thawing the limited
+	 * counters, we first write MMCR0 with the counter overflow
+	 * interrupt enable bits turned off.
+	 */
+	asm volatile("mtspr %3,%2; mfspr %0,%4; mfspr %1,%5"
+		     : "=&r" (pmc5), "=&r" (pmc6)
+		     : "r" (mmcr0 & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)),
+		       "i" (SPRN_MMCR0),
+		       "i" (SPRN_PMC5), "i" (SPRN_PMC6));
+
+	if (mmcr0 & MMCR0_FC)
+		freeze_limited_counters(cpuhw, pmc5, pmc6);
+	else
+		thaw_limited_counters(cpuhw, pmc5, pmc6);
+
+	/*
+	 * Write the full MMCR0 including the counter overflow interrupt
+	 * enable bits, if necessary.
+	 */
+	if (mmcr0 & (MMCR0_PMC1CE | MMCR0_PMCjCE))
+		mtspr(SPRN_MMCR0, mmcr0);
+}
+
+/*
+ * Disable all counters to prevent PMU interrupts and to allow
+ * counters to be added or removed.
+ */
+void hw_perf_disable(void)
+{
+	struct cpu_hw_counters *cpuhw;
+	unsigned long flags;
+
+	if (!ppmu)
+		return;
+	local_irq_save(flags);
+	cpuhw = &__get_cpu_var(cpu_hw_counters);
+
+	if (!cpuhw->disabled) {
+		cpuhw->disabled = 1;
+		cpuhw->n_added = 0;
+
+		/*
+		 * Check if we ever enabled the PMU on this cpu.
+		 */
+		if (!cpuhw->pmcs_enabled) {
+			if (ppc_md.enable_pmcs)
+				ppc_md.enable_pmcs();
+			cpuhw->pmcs_enabled = 1;
+		}
+
+		/*
+		 * Disable instruction sampling if it was enabled
+		 */
+		if (cpuhw->mmcr[2] & MMCRA_SAMPLE_ENABLE) {
+			mtspr(SPRN_MMCRA,
+			      cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
+			mb();
+		}
+
+		/*
+		 * Set the 'freeze counters' bit.
+		 * The barrier is to make sure the mtspr has been
+		 * executed and the PMU has frozen the counters
+		 * before we return.
+		 */
+		write_mmcr0(cpuhw, mfspr(SPRN_MMCR0) | MMCR0_FC);
+		mb();
+	}
+	local_irq_restore(flags);
+}
+
+/*
+ * Re-enable all counters if disable == 0.
+ * If we were previously disabled and counters were added, then
+ * put the new config on the PMU.
+ */
+void hw_perf_enable(void)
+{
+	struct perf_counter *counter;
+	struct cpu_hw_counters *cpuhw;
+	unsigned long flags;
+	long i;
+	unsigned long val;
+	s64 left;
+	unsigned int hwc_index[MAX_HWCOUNTERS];
+	int n_lim;
+	int idx;
+
+	if (!ppmu)
+		return;
+	local_irq_save(flags);
+	cpuhw = &__get_cpu_var(cpu_hw_counters);
+	if (!cpuhw->disabled) {
+		local_irq_restore(flags);
+		return;
+	}
+	cpuhw->disabled = 0;
+
+	/*
+	 * If we didn't change anything, or only removed counters,
+	 * no need to recalculate MMCR* settings and reset the PMCs.
+	 * Just reenable the PMU with the current MMCR* settings
+	 * (possibly updated for removal of counters).
+	 */
+	if (!cpuhw->n_added) {
+		mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
+		mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
+		if (cpuhw->n_counters == 0)
+			perf_set_pmu_inuse(0);
+		goto out_enable;
+	}
+
+	/*
+	 * Compute MMCR* values for the new set of counters
+	 */
+	if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_counters, hwc_index,
+			       cpuhw->mmcr)) {
+		/* shouldn't ever get here */
+		printk(KERN_ERR "oops compute_mmcr failed\n");
+		goto out;
+	}
+
+	/*
+	 * Add in MMCR0 freeze bits corresponding to the
+	 * attr.exclude_* bits for the first counter.
+	 * We have already checked that all counters have the
+	 * same values for these bits as the first counter.
+	 */
+	counter = cpuhw->counter[0];
+	if (counter->attr.exclude_user)
+		cpuhw->mmcr[0] |= MMCR0_FCP;
+	if (counter->attr.exclude_kernel)
+		cpuhw->mmcr[0] |= freeze_counters_kernel;
+	if (counter->attr.exclude_hv)
+		cpuhw->mmcr[0] |= MMCR0_FCHV;
+
+	/*
+	 * Write the new configuration to MMCR* with the freeze
+	 * bit set and set the hardware counters to their initial values.
+	 * Then unfreeze the counters.
+	 */
+	perf_set_pmu_inuse(1);
+	mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
+	mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
+	mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE))
+				| MMCR0_FC);
+
+	/*
+	 * Read off any pre-existing counters that need to move
+	 * to another PMC.
+	 */
+	for (i = 0; i < cpuhw->n_counters; ++i) {
+		counter = cpuhw->counter[i];
+		if (counter->hw.idx && counter->hw.idx != hwc_index[i] + 1) {
+			power_pmu_read(counter);
+			write_pmc(counter->hw.idx, 0);
+			counter->hw.idx = 0;
+		}
+	}
+
+	/*
+	 * Initialize the PMCs for all the new and moved counters.
+	 */
+	cpuhw->n_limited = n_lim = 0;
+	for (i = 0; i < cpuhw->n_counters; ++i) {
+		counter = cpuhw->counter[i];
+		if (counter->hw.idx)
+			continue;
+		idx = hwc_index[i] + 1;
+		if (is_limited_pmc(idx)) {
+			cpuhw->limited_counter[n_lim] = counter;
+			cpuhw->limited_hwidx[n_lim] = idx;
+			++n_lim;
+			continue;
+		}
+		val = 0;
+		if (counter->hw.sample_period) {
+			left = atomic64_read(&counter->hw.period_left);
+			if (left < 0x80000000L)
+				val = 0x80000000L - left;
+		}
+		atomic64_set(&counter->hw.prev_count, val);
+		counter->hw.idx = idx;
+		write_pmc(idx, val);
+		perf_counter_update_userpage(counter);
+	}
+	cpuhw->n_limited = n_lim;
+	cpuhw->mmcr[0] |= MMCR0_PMXE | MMCR0_FCECE;
+
+ out_enable:
+	mb();
+	write_mmcr0(cpuhw, cpuhw->mmcr[0]);
+
+	/*
+	 * Enable instruction sampling if necessary
+	 */
+	if (cpuhw->mmcr[2] & MMCRA_SAMPLE_ENABLE) {
+		mb();
+		mtspr(SPRN_MMCRA, cpuhw->mmcr[2]);
+	}
+
+ out:
+	local_irq_restore(flags);
+}
+
+static int collect_events(struct perf_counter *group, int max_count,
+			  struct perf_counter *ctrs[], u64 *events,
+			  unsigned int *flags)
+{
+	int n = 0;
+	struct perf_counter *counter;
+
+	if (!is_software_counter(group)) {
+		if (n >= max_count)
+			return -1;
+		ctrs[n] = group;
+		flags[n] = group->hw.counter_base;
+		events[n++] = group->hw.config;
+	}
+	list_for_each_entry(counter, &group->sibling_list, list_entry) {
+		if (!is_software_counter(counter) &&
+		    counter->state != PERF_COUNTER_STATE_OFF) {
+			if (n >= max_count)
+				return -1;
+			ctrs[n] = counter;
+			flags[n] = counter->hw.counter_base;
+			events[n++] = counter->hw.config;
+		}
+	}
+	return n;
+}
+
+static void counter_sched_in(struct perf_counter *counter, int cpu)
+{
+	counter->state = PERF_COUNTER_STATE_ACTIVE;
+	counter->oncpu = cpu;
+	counter->tstamp_running += counter->ctx->time - counter->tstamp_stopped;
+	if (is_software_counter(counter))
+		counter->pmu->enable(counter);
+}
+
+/*
+ * Called to enable a whole group of counters.
+ * Returns 1 if the group was enabled, or -EAGAIN if it could not be.
+ * Assumes the caller has disabled interrupts and has
+ * frozen the PMU with hw_perf_save_disable.
+ */
+int hw_perf_group_sched_in(struct perf_counter *group_leader,
+	       struct perf_cpu_context *cpuctx,
+	       struct perf_counter_context *ctx, int cpu)
+{
+	struct cpu_hw_counters *cpuhw;
+	long i, n, n0;
+	struct perf_counter *sub;
+
+	if (!ppmu)
+		return 0;
+	cpuhw = &__get_cpu_var(cpu_hw_counters);
+	n0 = cpuhw->n_counters;
+	n = collect_events(group_leader, ppmu->n_counter - n0,
+			   &cpuhw->counter[n0], &cpuhw->events[n0],
+			   &cpuhw->flags[n0]);
+	if (n < 0)
+		return -EAGAIN;
+	if (check_excludes(cpuhw->counter, cpuhw->flags, n0, n))
+		return -EAGAIN;
+	i = power_check_constraints(cpuhw->events, cpuhw->flags, n + n0);
+	if (i < 0)
+		return -EAGAIN;
+	cpuhw->n_counters = n0 + n;
+	cpuhw->n_added += n;
+
+	/*
+	 * OK, this group can go on; update counter states etc.,
+	 * and enable any software counters
+	 */
+	for (i = n0; i < n0 + n; ++i)
+		cpuhw->counter[i]->hw.config = cpuhw->events[i];
+	cpuctx->active_oncpu += n;
+	n = 1;
+	counter_sched_in(group_leader, cpu);
+	list_for_each_entry(sub, &group_leader->sibling_list, list_entry) {
+		if (sub->state != PERF_COUNTER_STATE_OFF) {
+			counter_sched_in(sub, cpu);
+			++n;
+		}
+	}
+	ctx->nr_active += n;
+
+	return 1;
+}
+
+/*
+ * Add a counter to the PMU.
+ * If all counters are not already frozen, then we disable and
+ * re-enable the PMU in order to get hw_perf_enable to do the
+ * actual work of reconfiguring the PMU.
+ */
+static int power_pmu_enable(struct perf_counter *counter)
+{
+	struct cpu_hw_counters *cpuhw;
+	unsigned long flags;
+	int n0;
+	int ret = -EAGAIN;
+
+	local_irq_save(flags);
+	perf_disable();
+
+	/*
+	 * Add the counter to the list (if there is room)
+	 * and check whether the total set is still feasible.
+	 */
+	cpuhw = &__get_cpu_var(cpu_hw_counters);
+	n0 = cpuhw->n_counters;
+	if (n0 >= ppmu->n_counter)
+		goto out;
+	cpuhw->counter[n0] = counter;
+	cpuhw->events[n0] = counter->hw.config;
+	cpuhw->flags[n0] = counter->hw.counter_base;
+	if (check_excludes(cpuhw->counter, cpuhw->flags, n0, 1))
+		goto out;
+	if (power_check_constraints(cpuhw->events, cpuhw->flags, n0 + 1))
+		goto out;
+
+	counter->hw.config = cpuhw->events[n0];
+	++cpuhw->n_counters;
+	++cpuhw->n_added;
+
+	ret = 0;
+ out:
+	perf_enable();
+	local_irq_restore(flags);
+	return ret;
+}
+
+/*
+ * Remove a counter from the PMU.
+ */
+static void power_pmu_disable(struct perf_counter *counter)
+{
+	struct cpu_hw_counters *cpuhw;
+	long i;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	perf_disable();
+
+	power_pmu_read(counter);
+
+	cpuhw = &__get_cpu_var(cpu_hw_counters);
+	for (i = 0; i < cpuhw->n_counters; ++i) {
+		if (counter == cpuhw->counter[i]) {
+			while (++i < cpuhw->n_counters)
+				cpuhw->counter[i-1] = cpuhw->counter[i];
+			--cpuhw->n_counters;
+			ppmu->disable_pmc(counter->hw.idx - 1, cpuhw->mmcr);
+			if (counter->hw.idx) {
+				write_pmc(counter->hw.idx, 0);
+				counter->hw.idx = 0;
+			}
+			perf_counter_update_userpage(counter);
+			break;
+		}
+	}
+	for (i = 0; i < cpuhw->n_limited; ++i)
+		if (counter == cpuhw->limited_counter[i])
+			break;
+	if (i < cpuhw->n_limited) {
+		while (++i < cpuhw->n_limited) {
+			cpuhw->limited_counter[i-1] = cpuhw->limited_counter[i];
+			cpuhw->limited_hwidx[i-1] = cpuhw->limited_hwidx[i];
+		}
+		--cpuhw->n_limited;
+	}
+	if (cpuhw->n_counters == 0) {
+		/* disable exceptions if no counters are running */
+		cpuhw->mmcr[0] &= ~(MMCR0_PMXE | MMCR0_FCECE);
+	}
+
+	perf_enable();
+	local_irq_restore(flags);
+}
+
+/*
+ * Re-enable interrupts on a counter after they were throttled
+ * because they were coming too fast.
+ */
+static void power_pmu_unthrottle(struct perf_counter *counter)
+{
+	s64 val, left;
+	unsigned long flags;
+
+	if (!counter->hw.idx || !counter->hw.sample_period)
+		return;
+	local_irq_save(flags);
+	perf_disable();
+	power_pmu_read(counter);
+	left = counter->hw.sample_period;
+	counter->hw.last_period = left;
+	val = 0;
+	if (left < 0x80000000L)
+		val = 0x80000000L - left;
+	write_pmc(counter->hw.idx, val);
+	atomic64_set(&counter->hw.prev_count, val);
+	atomic64_set(&counter->hw.period_left, left);
+	perf_counter_update_userpage(counter);
+	perf_enable();
+	local_irq_restore(flags);
+}
+
+struct pmu power_pmu = {
+	.enable		= power_pmu_enable,
+	.disable	= power_pmu_disable,
+	.read		= power_pmu_read,
+	.unthrottle	= power_pmu_unthrottle,
+};
+
+/*
+ * Return 1 if we might be able to put counter on a limited PMC,
+ * or 0 if not.
+ * A counter can only go on a limited PMC if it counts something
+ * that a limited PMC can count, doesn't require interrupts, and
+ * doesn't exclude any processor mode.
+ */
+static int can_go_on_limited_pmc(struct perf_counter *counter, u64 ev,
+				 unsigned int flags)
+{
+	int n;
+	u64 alt[MAX_EVENT_ALTERNATIVES];
+
+	if (counter->attr.exclude_user
+	    || counter->attr.exclude_kernel
+	    || counter->attr.exclude_hv
+	    || counter->attr.sample_period)
+		return 0;
+
+	if (ppmu->limited_pmc_event(ev))
+		return 1;
+
+	/*
+	 * The requested event isn't on a limited PMC already;
+	 * see if any alternative code goes on a limited PMC.
+	 */
+	if (!ppmu->get_alternatives)
+		return 0;
+
+	flags |= PPMU_LIMITED_PMC_OK | PPMU_LIMITED_PMC_REQD;
+	n = ppmu->get_alternatives(ev, flags, alt);
+
+	return n > 0;
+}
+
+/*
+ * Find an alternative event that goes on a normal PMC, if possible,
+ * and return the event code, or 0 if there is no such alternative.
+ * (Note: event code 0 is "don't count" on all machines.)
+ */
+static u64 normal_pmc_alternative(u64 ev, unsigned long flags)
+{
+	u64 alt[MAX_EVENT_ALTERNATIVES];
+	int n;
+
+	flags &= ~(PPMU_LIMITED_PMC_OK | PPMU_LIMITED_PMC_REQD);
+	n = ppmu->get_alternatives(ev, flags, alt);
+	if (!n)
+		return 0;
+	return alt[0];
+}
+
+/* Number of perf_counters counting hardware events */
+static atomic_t num_counters;
+/* Used to avoid races in calling reserve/release_pmc_hardware */
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+/*
+ * Release the PMU if this is the last perf_counter.
+ */
+static void hw_perf_counter_destroy(struct perf_counter *counter)
+{
+	if (!atomic_add_unless(&num_counters, -1, 1)) {
+		mutex_lock(&pmc_reserve_mutex);
+		if (atomic_dec_return(&num_counters) == 0)
+			release_pmc_hardware();
+		mutex_unlock(&pmc_reserve_mutex);
+	}
+}
+
+/*
+ * Translate a generic cache event config to a raw event code.
+ */
+static int hw_perf_cache_event(u64 config, u64 *eventp)
+{
+	unsigned long type, op, result;
+	int ev;
+
+	if (!ppmu->cache_events)
+		return -EINVAL;
+
+	/* unpack config */
+	type = config & 0xff;
+	op = (config >> 8) & 0xff;
+	result = (config >> 16) & 0xff;
+
+	if (type >= PERF_COUNT_HW_CACHE_MAX ||
+	    op >= PERF_COUNT_HW_CACHE_OP_MAX ||
+	    result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+		return -EINVAL;
+
+	ev = (*ppmu->cache_events)[type][op][result];
+	if (ev == 0)
+		return -EOPNOTSUPP;
+	if (ev == -1)
+		return -EINVAL;
+	*eventp = ev;
+	return 0;
+}
+
+const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
+{
+	u64 ev;
+	unsigned long flags;
+	struct perf_counter *ctrs[MAX_HWCOUNTERS];
+	u64 events[MAX_HWCOUNTERS];
+	unsigned int cflags[MAX_HWCOUNTERS];
+	int n;
+	int err;
+
+	if (!ppmu)
+		return ERR_PTR(-ENXIO);
+	switch (counter->attr.type) {
+	case PERF_TYPE_HARDWARE:
+		ev = counter->attr.config;
+		if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
+			return ERR_PTR(-EOPNOTSUPP);
+		ev = ppmu->generic_events[ev];
+		break;
+	case PERF_TYPE_HW_CACHE:
+		err = hw_perf_cache_event(counter->attr.config, &ev);
+		if (err)
+			return ERR_PTR(err);
+		break;
+	case PERF_TYPE_RAW:
+		ev = counter->attr.config;
+		break;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+	counter->hw.config_base = ev;
+	counter->hw.idx = 0;
+
+	/*
+	 * If we are not running on a hypervisor, force the
+	 * exclude_hv bit to 0 so that we don't care what
+	 * the user set it to.
+	 */
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		counter->attr.exclude_hv = 0;
+
+	/*
+	 * If this is a per-task counter, then we can use
+	 * PM_RUN_* events interchangeably with their non RUN_*
+	 * equivalents, e.g. PM_RUN_CYC instead of PM_CYC.
+	 * XXX we should check if the task is an idle task.
+	 */
+	flags = 0;
+	if (counter->ctx->task)
+		flags |= PPMU_ONLY_COUNT_RUN;
+
+	/*
+	 * If this machine has limited counters, check whether this
+	 * event could go on a limited counter.
+	 */
+	if (ppmu->flags & PPMU_LIMITED_PMC5_6) {
+		if (can_go_on_limited_pmc(counter, ev, flags)) {
+			flags |= PPMU_LIMITED_PMC_OK;
+		} else if (ppmu->limited_pmc_event(ev)) {
+			/*
+			 * The requested event is on a limited PMC,
+			 * but we can't use a limited PMC; see if any
+			 * alternative goes on a normal PMC.
+			 */
+			ev = normal_pmc_alternative(ev, flags);
+			if (!ev)
+				return ERR_PTR(-EINVAL);
+		}
+	}
+
+	/*
+	 * If this is in a group, check if it can go on with all the
+	 * other hardware counters in the group.  We assume the counter
+	 * hasn't been linked into its leader's sibling list at this point.
+	 */
+	n = 0;
+	if (counter->group_leader != counter) {
+		n = collect_events(counter->group_leader, ppmu->n_counter - 1,
+				   ctrs, events, cflags);
+		if (n < 0)
+			return ERR_PTR(-EINVAL);
+	}
+	events[n] = ev;
+	ctrs[n] = counter;
+	cflags[n] = flags;
+	if (check_excludes(ctrs, cflags, n, 1))
+		return ERR_PTR(-EINVAL);
+	if (power_check_constraints(events, cflags, n + 1))
+		return ERR_PTR(-EINVAL);
+
+	counter->hw.config = events[n];
+	counter->hw.counter_base = cflags[n];
+	counter->hw.last_period = counter->hw.sample_period;
+	atomic64_set(&counter->hw.period_left, counter->hw.last_period);
+
+	/*
+	 * See if we need to reserve the PMU.
+	 * If no counters are currently in use, then we have to take a
+	 * mutex to ensure that we don't race with another task doing
+	 * reserve_pmc_hardware or release_pmc_hardware.
+	 */
+	err = 0;
+	if (!atomic_inc_not_zero(&num_counters)) {
+		mutex_lock(&pmc_reserve_mutex);
+		if (atomic_read(&num_counters) == 0 &&
+		    reserve_pmc_hardware(perf_counter_interrupt))
+			err = -EBUSY;
+		else
+			atomic_inc(&num_counters);
+		mutex_unlock(&pmc_reserve_mutex);
+	}
+	counter->destroy = hw_perf_counter_destroy;
+
+	if (err)
+		return ERR_PTR(err);
+	return &power_pmu;
+}
+
+/*
+ * A counter has overflowed; update its count and record
+ * things if requested.  Note that interrupts are hard-disabled
+ * here so there is no possibility of being interrupted.
+ */
+static void record_and_restart(struct perf_counter *counter, unsigned long val,
+			       struct pt_regs *regs, int nmi)
+{
+	u64 period = counter->hw.sample_period;
+	s64 prev, delta, left;
+	int record = 0;
+
+	/* we don't have to worry about interrupts here */
+	prev = atomic64_read(&counter->hw.prev_count);
+	delta = (val - prev) & 0xfffffffful;
+	atomic64_add(delta, &counter->count);
+
+	/*
+	 * See if the total period for this counter has expired,
+	 * and update for the next period.
+	 */
+	val = 0;
+	left = atomic64_read(&counter->hw.period_left) - delta;
+	if (period) {
+		if (left <= 0) {
+			left += period;
+			if (left <= 0)
+				left = period;
+			record = 1;
+		}
+		if (left < 0x80000000LL)
+			val = 0x80000000LL - left;
+	}
+
+	/*
+	 * Finally record data if requested.
+	 */
+	if (record) {
+		struct perf_sample_data data = {
+			.regs	= regs,
+			.addr	= 0,
+			.period	= counter->hw.last_period,
+		};
+
+		if (counter->attr.sample_type & PERF_SAMPLE_ADDR)
+			perf_get_data_addr(regs, &data.addr);
+
+		if (perf_counter_overflow(counter, nmi, &data)) {
+			/*
+			 * Interrupts are coming too fast - throttle them
+			 * by setting the counter to 0, so it will be
+			 * at least 2^30 cycles until the next interrupt
+			 * (assuming each counter counts at most 2 counts
+			 * per cycle).
+			 */
+			val = 0;
+			left = ~0ULL >> 1;
+		}
+	}
+
+	write_pmc(counter->hw.idx, val);
+	atomic64_set(&counter->hw.prev_count, val);
+	atomic64_set(&counter->hw.period_left, left);
+	perf_counter_update_userpage(counter);
+}
+
+/*
+ * Called from generic code to get the misc flags (i.e. processor mode)
+ * for an event.
+ */
+unsigned long perf_misc_flags(struct pt_regs *regs)
+{
+	u32 flags = perf_get_misc_flags(regs);
+
+	if (flags)
+		return flags;
+	return user_mode(regs) ? PERF_EVENT_MISC_USER :
+		PERF_EVENT_MISC_KERNEL;
+}
+
+/*
+ * Called from generic code to get the instruction pointer
+ * for an event.
+ */
+unsigned long perf_instruction_pointer(struct pt_regs *regs)
+{
+	unsigned long ip;
+
+	if (TRAP(regs) != 0xf00)
+		return regs->nip;	/* not a PMU interrupt */
+
+	ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
+	return ip;
+}
+
+/*
+ * Performance monitor interrupt stuff
+ */
+static void perf_counter_interrupt(struct pt_regs *regs)
+{
+	int i;
+	struct cpu_hw_counters *cpuhw = &__get_cpu_var(cpu_hw_counters);
+	struct perf_counter *counter;
+	unsigned long val;
+	int found = 0;
+	int nmi;
+
+	if (cpuhw->n_limited)
+		freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5),
+					mfspr(SPRN_PMC6));
+
+	perf_read_regs(regs);
+
+	nmi = perf_intr_is_nmi(regs);
+	if (nmi)
+		nmi_enter();
+	else
+		irq_enter();
+
+	for (i = 0; i < cpuhw->n_counters; ++i) {
+		counter = cpuhw->counter[i];
+		if (!counter->hw.idx || is_limited_pmc(counter->hw.idx))
+			continue;
+		val = read_pmc(counter->hw.idx);
+		if ((int)val < 0) {
+			/* counter has overflowed */
+			found = 1;
+			record_and_restart(counter, val, regs, nmi);
+		}
+	}
+
+	/*
+	 * In case we didn't find and reset the counter that caused
+	 * the interrupt, scan all counters and reset any that are
+	 * negative, to avoid getting continual interrupts.
+	 * Any that we processed in the previous loop will not be negative.
+	 */
+	if (!found) {
+		for (i = 0; i < ppmu->n_counter; ++i) {
+			if (is_limited_pmc(i + 1))
+				continue;
+			val = read_pmc(i + 1);
+			if ((int)val < 0)
+				write_pmc(i + 1, 0);
+		}
+	}
+
+	/*
+	 * Reset MMCR0 to its normal value.  This will set PMXE and
+	 * clear FC (freeze counters) and PMAO (perf mon alert occurred)
+	 * and thus allow interrupts to occur again.
+	 * XXX might want to use MSR.PM to keep the counters frozen until
+	 * we get back out of this interrupt.
+	 */
+	write_mmcr0(cpuhw, cpuhw->mmcr[0]);
+
+	if (nmi)
+		nmi_exit();
+	else
+		irq_exit();
+}
+
+void hw_perf_counter_setup(int cpu)
+{
+	struct cpu_hw_counters *cpuhw = &per_cpu(cpu_hw_counters, cpu);
+
+	if (!ppmu)
+		return;
+	memset(cpuhw, 0, sizeof(*cpuhw));
+	cpuhw->mmcr[0] = MMCR0_FC;
+}
+
+int register_power_pmu(struct power_pmu *pmu)
+{
+	if (ppmu)
+		return -EBUSY;		/* something's already registered */
+
+	ppmu = pmu;
+	pr_info("%s performance monitor hardware support registered\n",
+		pmu->name);
+
+#ifdef MSR_HV
+	/*
+	 * Use FCHV to ignore kernel events if MSR.HV is set.
+	 */
+	if (mfmsr() & MSR_HV)
+		freeze_counters_kernel = MMCR0_FCHV;
+#endif /* CONFIG_PPC64 */
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/power4-pmu.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/power4-pmu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/power4-pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/power4-pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,616 @@
+/*
+ * Performance counter support for POWER4 (GP) and POWER4+ (GQ) processors.
+ *
+ * Copyright 2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/kernel.h>
+#include <linux/perf_counter.h>
+#include <linux/string.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Bits in event code for POWER4
+ */
+#define PM_PMC_SH	12	/* PMC number (1-based) for direct events */
+#define PM_PMC_MSK	0xf
+#define PM_UNIT_SH	8	/* TTMMUX number and setting - unit select */
+#define PM_UNIT_MSK	0xf
+#define PM_LOWER_SH	6
+#define PM_LOWER_MSK	1
+#define PM_LOWER_MSKS	0x40
+#define PM_BYTE_SH	4	/* Byte number of event bus to use */
+#define PM_BYTE_MSK	3
+#define PM_PMCSEL_MSK	7
+
+/*
+ * Unit code values
+ */
+#define PM_FPU		1
+#define PM_ISU1		2
+#define PM_IFU		3
+#define PM_IDU0		4
+#define PM_ISU1_ALT	6
+#define PM_ISU2		7
+#define PM_IFU_ALT	8
+#define PM_LSU0		9
+#define PM_LSU1		0xc
+#define PM_GPS		0xf
+
+/*
+ * Bits in MMCR0 for POWER4
+ */
+#define MMCR0_PMC1SEL_SH	8
+#define MMCR0_PMC2SEL_SH	1
+#define MMCR_PMCSEL_MSK		0x1f
+
+/*
+ * Bits in MMCR1 for POWER4
+ */
+#define MMCR1_TTM0SEL_SH	62
+#define MMCR1_TTC0SEL_SH	61
+#define MMCR1_TTM1SEL_SH	59
+#define MMCR1_TTC1SEL_SH	58
+#define MMCR1_TTM2SEL_SH	56
+#define MMCR1_TTC2SEL_SH	55
+#define MMCR1_TTM3SEL_SH	53
+#define MMCR1_TTC3SEL_SH	52
+#define MMCR1_TTMSEL_MSK	3
+#define MMCR1_TD_CP_DBG0SEL_SH	50
+#define MMCR1_TD_CP_DBG1SEL_SH	48
+#define MMCR1_TD_CP_DBG2SEL_SH	46
+#define MMCR1_TD_CP_DBG3SEL_SH	44
+#define MMCR1_DEBUG0SEL_SH	43
+#define MMCR1_DEBUG1SEL_SH	42
+#define MMCR1_DEBUG2SEL_SH	41
+#define MMCR1_DEBUG3SEL_SH	40
+#define MMCR1_PMC1_ADDER_SEL_SH	39
+#define MMCR1_PMC2_ADDER_SEL_SH	38
+#define MMCR1_PMC6_ADDER_SEL_SH	37
+#define MMCR1_PMC5_ADDER_SEL_SH	36
+#define MMCR1_PMC8_ADDER_SEL_SH	35
+#define MMCR1_PMC7_ADDER_SEL_SH	34
+#define MMCR1_PMC3_ADDER_SEL_SH	33
+#define MMCR1_PMC4_ADDER_SEL_SH	32
+#define MMCR1_PMC3SEL_SH	27
+#define MMCR1_PMC4SEL_SH	22
+#define MMCR1_PMC5SEL_SH	17
+#define MMCR1_PMC6SEL_SH	12
+#define MMCR1_PMC7SEL_SH	7
+#define MMCR1_PMC8SEL_SH	2	/* note bit 0 is in MMCRA for GP */
+
+static short mmcr1_adder_bits[8] = {
+	MMCR1_PMC1_ADDER_SEL_SH,
+	MMCR1_PMC2_ADDER_SEL_SH,
+	MMCR1_PMC3_ADDER_SEL_SH,
+	MMCR1_PMC4_ADDER_SEL_SH,
+	MMCR1_PMC5_ADDER_SEL_SH,
+	MMCR1_PMC6_ADDER_SEL_SH,
+	MMCR1_PMC7_ADDER_SEL_SH,
+	MMCR1_PMC8_ADDER_SEL_SH
+};
+
+/*
+ * Bits in MMCRA
+ */
+#define MMCRA_PMC8SEL0_SH	17	/* PMC8SEL bit 0 for GP */
+
+/*
+ * Layout of constraint bits:
+ * 6666555555555544444444443333333333222222222211111111110000000000
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ *        |[  >[  >[   >|||[  >[  ><  ><  ><  ><  ><><><><><><><><>
+ *        | UC1 UC2 UC3 ||| PS1 PS2 B0  B1  B2  B3 P1P2P3P4P5P6P7P8
+ * 	  \SMPL	        ||\TTC3SEL
+ * 		        |\TTC_IFU_SEL
+ * 		        \TTM2SEL0
+ *
+ * SMPL - SAMPLE_ENABLE constraint
+ *     56: SAMPLE_ENABLE value 0x0100_0000_0000_0000
+ *
+ * UC1 - unit constraint 1: can't have all three of FPU/ISU1/IDU0|ISU2
+ *     55: UC1 error 0x0080_0000_0000_0000
+ *     54: FPU events needed 0x0040_0000_0000_0000
+ *     53: ISU1 events needed 0x0020_0000_0000_0000
+ *     52: IDU0|ISU2 events needed 0x0010_0000_0000_0000
+ *
+ * UC2 - unit constraint 2: can't have all three of FPU/IFU/LSU0
+ *     51: UC2 error 0x0008_0000_0000_0000
+ *     50: FPU events needed 0x0004_0000_0000_0000
+ *     49: IFU events needed 0x0002_0000_0000_0000
+ *     48: LSU0 events needed 0x0001_0000_0000_0000
+ *
+ * UC3 - unit constraint 3: can't have all four of LSU0/IFU/IDU0|ISU2/ISU1
+ *     47: UC3 error 0x8000_0000_0000
+ *     46: LSU0 events needed 0x4000_0000_0000
+ *     45: IFU events needed 0x2000_0000_0000
+ *     44: IDU0|ISU2 events needed 0x1000_0000_0000
+ *     43: ISU1 events needed 0x0800_0000_0000
+ *
+ * TTM2SEL0
+ *     42: 0 = IDU0 events needed
+ *     	   1 = ISU2 events needed 0x0400_0000_0000
+ *
+ * TTC_IFU_SEL
+ *     41: 0 = IFU.U events needed
+ *     	   1 = IFU.L events needed 0x0200_0000_0000
+ *
+ * TTC3SEL
+ *     40: 0 = LSU1.U events needed
+ *     	   1 = LSU1.L events needed 0x0100_0000_0000
+ *
+ * PS1
+ *     39: PS1 error 0x0080_0000_0000
+ *     36-38: count of events needing PMC1/2/5/6 0x0070_0000_0000
+ *
+ * PS2
+ *     35: PS2 error 0x0008_0000_0000
+ *     32-34: count of events needing PMC3/4/7/8 0x0007_0000_0000
+ *
+ * B0
+ *     28-31: Byte 0 event source 0xf000_0000
+ *     	   1 = FPU
+ * 	   2 = ISU1
+ * 	   3 = IFU
+ * 	   4 = IDU0
+ * 	   7 = ISU2
+ * 	   9 = LSU0
+ * 	   c = LSU1
+ * 	   f = GPS
+ *
+ * B1, B2, B3
+ *     24-27, 20-23, 16-19: Byte 1, 2, 3 event sources
+ *
+ * P8
+ *     15: P8 error 0x8000
+ *     14-15: Count of events needing PMC8
+ *
+ * P1..P7
+ *     0-13: Count of events needing PMC1..PMC7
+ *
+ * Note: this doesn't allow events using IFU.U to be combined with events
+ * using IFU.L, though that is feasible (using TTM0 and TTM2).  However
+ * there are no listed events for IFU.L (they are debug events not
+ * verified for performance monitoring) so this shouldn't cause a
+ * problem.
+ */
+
+static struct unitinfo {
+	unsigned long	value, mask;
+	int		unit;
+	int		lowerbit;
+} p4_unitinfo[16] = {
+	[PM_FPU]  = { 0x44000000000000ul, 0x88000000000000ul, PM_FPU, 0 },
+	[PM_ISU1] = { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 },
+	[PM_ISU1_ALT] =
+		    { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 },
+	[PM_IFU]  = { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 },
+	[PM_IFU_ALT] =
+		    { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 },
+	[PM_IDU0] = { 0x10100000000000ul, 0x80840000000000ul, PM_IDU0, 1 },
+	[PM_ISU2] = { 0x10140000000000ul, 0x80840000000000ul, PM_ISU2, 0 },
+	[PM_LSU0] = { 0x01400000000000ul, 0x08800000000000ul, PM_LSU0, 0 },
+	[PM_LSU1] = { 0x00000000000000ul, 0x00010000000000ul, PM_LSU1, 40 },
+	[PM_GPS]  = { 0x00000000000000ul, 0x00000000000000ul, PM_GPS, 0 }
+};
+
+static unsigned char direct_marked_event[8] = {
+	(1<<2) | (1<<3),	/* PMC1: PM_MRK_GRP_DISP, PM_MRK_ST_CMPL */
+	(1<<3) | (1<<5),	/* PMC2: PM_THRESH_TIMEO, PM_MRK_BRU_FIN */
+	(1<<3),			/* PMC3: PM_MRK_ST_CMPL_INT */
+	(1<<4) | (1<<5),	/* PMC4: PM_MRK_GRP_CMPL, PM_MRK_CRU_FIN */
+	(1<<4) | (1<<5),	/* PMC5: PM_MRK_GRP_TIMEO */
+	(1<<3) | (1<<4) | (1<<5),
+		/* PMC6: PM_MRK_ST_GPS, PM_MRK_FXU_FIN, PM_MRK_GRP_ISSUED */
+	(1<<4) | (1<<5),	/* PMC7: PM_MRK_FPU_FIN, PM_MRK_INST_FIN */
+	(1<<4),			/* PMC8: PM_MRK_LSU_FIN */
+};
+
+/*
+ * Returns 1 if event counts things relating to marked instructions
+ * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
+ */
+static int p4_marked_instr_event(u64 event)
+{
+	int pmc, psel, unit, byte, bit;
+	unsigned int mask;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	psel = event & PM_PMCSEL_MSK;
+	if (pmc) {
+		if (direct_marked_event[pmc - 1] & (1 << psel))
+			return 1;
+		if (psel == 0)		/* add events */
+			bit = (pmc <= 4)? pmc - 1: 8 - pmc;
+		else if (psel == 6)	/* decode events */
+			bit = 4;
+		else
+			return 0;
+	} else
+		bit = psel;
+
+	byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	mask = 0;
+	switch (unit) {
+	case PM_LSU1:
+		if (event & PM_LOWER_MSKS)
+			mask = 1 << 28;		/* byte 7 bit 4 */
+		else
+			mask = 6 << 24;		/* byte 3 bits 1 and 2 */
+		break;
+	case PM_LSU0:
+		/* byte 3, bit 3; byte 2 bits 0,2,3,4,5; byte 1 */
+		mask = 0x083dff00;
+	}
+	return (mask >> (byte * 8 + bit)) & 1;
+}
+
+static int p4_get_constraint(u64 event, unsigned long *maskp,
+			     unsigned long *valp)
+{
+	int pmc, byte, unit, lower, sh;
+	unsigned long mask = 0, value = 0;
+	int grp = -1;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc) {
+		if (pmc > 8)
+			return -1;
+		sh = (pmc - 1) * 2;
+		mask |= 2 << sh;
+		value |= 1 << sh;
+		grp = ((pmc - 1) >> 1) & 1;
+	}
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+	if (unit) {
+		lower = (event >> PM_LOWER_SH) & PM_LOWER_MSK;
+
+		/*
+		 * Bus events on bytes 0 and 2 can be counted
+		 * on PMC1/2/5/6; bytes 1 and 3 on PMC3/4/7/8.
+		 */
+		if (!pmc)
+			grp = byte & 1;
+
+		if (!p4_unitinfo[unit].unit)
+			return -1;
+		mask  |= p4_unitinfo[unit].mask;
+		value |= p4_unitinfo[unit].value;
+		sh = p4_unitinfo[unit].lowerbit;
+		if (sh > 1)
+			value |= (unsigned long)lower << sh;
+		else if (lower != sh)
+			return -1;
+		unit = p4_unitinfo[unit].unit;
+
+		/* Set byte lane select field */
+		mask  |= 0xfULL << (28 - 4 * byte);
+		value |= (unsigned long)unit << (28 - 4 * byte);
+	}
+	if (grp == 0) {
+		/* increment PMC1/2/5/6 field */
+		mask  |= 0x8000000000ull;
+		value |= 0x1000000000ull;
+	} else {
+		/* increment PMC3/4/7/8 field */
+		mask  |= 0x800000000ull;
+		value |= 0x100000000ull;
+	}
+
+	/* Marked instruction events need sample_enable set */
+	if (p4_marked_instr_event(event)) {
+		mask  |= 1ull << 56;
+		value |= 1ull << 56;
+	}
+
+	/* PMCSEL=6 decode events on byte 2 need sample_enable clear */
+	if (pmc && (event & PM_PMCSEL_MSK) == 6 && byte == 2)
+		mask  |= 1ull << 56;
+
+	*maskp = mask;
+	*valp = value;
+	return 0;
+}
+
+static unsigned int ppc_inst_cmpl[] = {
+	0x1001, 0x4001, 0x6001, 0x7001, 0x8001
+};
+
+static int p4_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	int i, j, na;
+
+	alt[0] = event;
+	na = 1;
+
+	/* 2 possibilities for PM_GRP_DISP_REJECT */
+	if (event == 0x8003 || event == 0x0224) {
+		alt[1] = event ^ (0x8003 ^ 0x0224);
+		return 2;
+	}
+
+	/* 2 possibilities for PM_ST_MISS_L1 */
+	if (event == 0x0c13 || event == 0x0c23) {
+		alt[1] = event ^ (0x0c13 ^ 0x0c23);
+		return 2;
+	}
+
+	/* several possibilities for PM_INST_CMPL */
+	for (i = 0; i < ARRAY_SIZE(ppc_inst_cmpl); ++i) {
+		if (event == ppc_inst_cmpl[i]) {
+			for (j = 0; j < ARRAY_SIZE(ppc_inst_cmpl); ++j)
+				if (j != i)
+					alt[na++] = ppc_inst_cmpl[j];
+			break;
+		}
+	}
+
+	return na;
+}
+
+static int p4_compute_mmcr(u64 event[], int n_ev,
+			   unsigned int hwc[], unsigned long mmcr[])
+{
+	unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
+	unsigned int pmc, unit, byte, psel, lower;
+	unsigned int ttm, grp;
+	unsigned int pmc_inuse = 0;
+	unsigned int pmc_grp_use[2];
+	unsigned char busbyte[4];
+	unsigned char unituse[16];
+	unsigned int unitlower = 0;
+	int i;
+
+	if (n_ev > 8)
+		return -1;
+
+	/* First pass to count resource use */
+	pmc_grp_use[0] = pmc_grp_use[1] = 0;
+	memset(busbyte, 0, sizeof(busbyte));
+	memset(unituse, 0, sizeof(unituse));
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc) {
+			if (pmc_inuse & (1 << (pmc - 1)))
+				return -1;
+			pmc_inuse |= 1 << (pmc - 1);
+			/* count 1/2/5/6 vs 3/4/7/8 use */
+			++pmc_grp_use[((pmc - 1) >> 1) & 1];
+		}
+		unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+		byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+		lower = (event[i] >> PM_LOWER_SH) & PM_LOWER_MSK;
+		if (unit) {
+			if (!pmc)
+				++pmc_grp_use[byte & 1];
+			if (unit == 6 || unit == 8)
+				/* map alt ISU1/IFU codes: 6->2, 8->3 */
+				unit = (unit >> 1) - 1;
+			if (busbyte[byte] && busbyte[byte] != unit)
+				return -1;
+			busbyte[byte] = unit;
+			lower <<= unit;
+			if (unituse[unit] && lower != (unitlower & lower))
+				return -1;
+			unituse[unit] = 1;
+			unitlower |= lower;
+		}
+	}
+	if (pmc_grp_use[0] > 4 || pmc_grp_use[1] > 4)
+		return -1;
+
+	/*
+	 * Assign resources and set multiplexer selects.
+	 *
+	 * Units 1,2,3 are on TTM0, 4,6,7 on TTM1, 8,10 on TTM2.
+	 * Each TTMx can only select one unit, but since
+	 * units 2 and 6 are both ISU1, and 3 and 8 are both IFU,
+	 * we have some choices.
+	 */
+	if (unituse[2] & (unituse[1] | (unituse[3] & unituse[9]))) {
+		unituse[6] = 1;		/* Move 2 to 6 */
+		unituse[2] = 0;
+	}
+	if (unituse[3] & (unituse[1] | unituse[2])) {
+		unituse[8] = 1;		/* Move 3 to 8 */
+		unituse[3] = 0;
+		unitlower = (unitlower & ~8) | ((unitlower & 8) << 5);
+	}
+	/* Check only one unit per TTMx */
+	if (unituse[1] + unituse[2] + unituse[3] > 1 ||
+	    unituse[4] + unituse[6] + unituse[7] > 1 ||
+	    unituse[8] + unituse[9] > 1 ||
+	    (unituse[5] | unituse[10] | unituse[11] |
+	     unituse[13] | unituse[14]))
+		return -1;
+
+	/* Set TTMxSEL fields.  Note, units 1-3 => TTM0SEL codes 0-2 */
+	mmcr1 |= (unsigned long)(unituse[3] * 2 + unituse[2])
+		<< MMCR1_TTM0SEL_SH;
+	mmcr1 |= (unsigned long)(unituse[7] * 3 + unituse[6] * 2)
+		<< MMCR1_TTM1SEL_SH;
+	mmcr1 |= (unsigned long)unituse[9] << MMCR1_TTM2SEL_SH;
+
+	/* Set TTCxSEL fields. */
+	if (unitlower & 0xe)
+		mmcr1 |= 1ull << MMCR1_TTC0SEL_SH;
+	if (unitlower & 0xf0)
+		mmcr1 |= 1ull << MMCR1_TTC1SEL_SH;
+	if (unitlower & 0xf00)
+		mmcr1 |= 1ull << MMCR1_TTC2SEL_SH;
+	if (unitlower & 0x7000)
+		mmcr1 |= 1ull << MMCR1_TTC3SEL_SH;
+
+	/* Set byte lane select fields. */
+	for (byte = 0; byte < 4; ++byte) {
+		unit = busbyte[byte];
+		if (!unit)
+			continue;
+		if (unit == 0xf) {
+			/* special case for GPS */
+			mmcr1 |= 1ull << (MMCR1_DEBUG0SEL_SH - byte);
+		} else {
+			if (!unituse[unit])
+				ttm = unit - 1;		/* 2->1, 3->2 */
+			else
+				ttm = unit >> 2;
+			mmcr1 |= (unsigned long)ttm
+				<< (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
+		}
+	}
+
+	/* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+		byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+		psel = event[i] & PM_PMCSEL_MSK;
+		if (!pmc) {
+			/* Bus event or 00xxx direct event (off or cycles) */
+			if (unit)
+				psel |= 0x10 | ((byte & 2) << 2);
+			for (pmc = 0; pmc < 8; ++pmc) {
+				if (pmc_inuse & (1 << pmc))
+					continue;
+				grp = (pmc >> 1) & 1;
+				if (unit) {
+					if (grp == (byte & 1))
+						break;
+				} else if (pmc_grp_use[grp] < 4) {
+					++pmc_grp_use[grp];
+					break;
+				}
+			}
+			pmc_inuse |= 1 << pmc;
+		} else {
+			/* Direct event */
+			--pmc;
+			if (psel == 0 && (byte & 2))
+				/* add events on higher-numbered bus */
+				mmcr1 |= 1ull << mmcr1_adder_bits[pmc];
+			else if (psel == 6 && byte == 3)
+				/* seem to need to set sample_enable here */
+				mmcra |= MMCRA_SAMPLE_ENABLE;
+			psel |= 8;
+		}
+		if (pmc <= 1)
+			mmcr0 |= psel << (MMCR0_PMC1SEL_SH - 7 * pmc);
+		else
+			mmcr1 |= psel << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2));
+		if (pmc == 7)	/* PMC8 */
+			mmcra |= (psel & 1) << MMCRA_PMC8SEL0_SH;
+		hwc[i] = pmc;
+		if (p4_marked_instr_event(event[i]))
+			mmcra |= MMCRA_SAMPLE_ENABLE;
+	}
+
+	if (pmc_inuse & 1)
+		mmcr0 |= MMCR0_PMC1CE;
+	if (pmc_inuse & 0xfe)
+		mmcr0 |= MMCR0_PMCjCE;
+
+	mmcra |= 0x2000;	/* mark only one IOP per PPC instruction */
+
+	/* Return MMCRx values */
+	mmcr[0] = mmcr0;
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcra;
+	return 0;
+}
+
+static void p4_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	/*
+	 * Setting the PMCxSEL field to 0 disables PMC x.
+	 * (Note that pmc is 0-based here, not 1-based.)
+	 */
+	if (pmc <= 1) {
+		mmcr[0] &= ~(0x1fUL << (MMCR0_PMC1SEL_SH - 7 * pmc));
+	} else {
+		mmcr[1] &= ~(0x1fUL << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2)));
+		if (pmc == 7)
+			mmcr[2] &= ~(1UL << MMCRA_PMC8SEL0_SH);
+	}
+}
+
+static int p4_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= 7,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= 0x1001,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= 0x8c10, /* PM_LD_REF_L1 */
+	[PERF_COUNT_HW_CACHE_MISSES]		= 0x3c10, /* PM_LD_MISS_L1 */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x330,  /* PM_BR_ISSUED */
+	[PERF_COUNT_HW_BRANCH_MISSES]		= 0x331,  /* PM_BR_MPRED_CR */
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int power4_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x8c10,		0x3c10	},
+		[C(OP_WRITE)] = {	0x7c10,		0xc13	},
+		[C(OP_PREFETCH)] = {	0xc35,		0	},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	0,		0	},
+	},
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0	},
+		[C(OP_WRITE)] = {	0,		0	},
+		[C(OP_PREFETCH)] = {	0xc34,		0	},
+	},
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x904	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(ITLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x900	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x330,		0x331	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+};
+
+static struct power_pmu power4_pmu = {
+	.name			= "POWER4/4+",
+	.n_counter		= 8,
+	.max_alternatives	= 5,
+	.add_fields		= 0x0000001100005555ul,
+	.test_adder		= 0x0011083300000000ul,
+	.compute_mmcr		= p4_compute_mmcr,
+	.get_constraint		= p4_get_constraint,
+	.get_alternatives	= p4_get_alternatives,
+	.disable_pmc		= p4_disable_pmc,
+	.n_generic		= ARRAY_SIZE(p4_generic_events),
+	.generic_events		= p4_generic_events,
+	.cache_events		= &power4_cache_events,
+};
+
+static int init_power4_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4"))
+		return -ENODEV;
+
+	return register_power_pmu(&power4_pmu);
+}
+
+arch_initcall(init_power4_pmu);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/power5-pmu.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/power5-pmu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/power5-pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/power5-pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,628 @@
+/*
+ * Performance counter support for POWER5 (not POWER5++) processors.
+ *
+ * Copyright 2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/kernel.h>
+#include <linux/perf_counter.h>
+#include <linux/string.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Bits in event code for POWER5 (not POWER5++)
+ */
+#define PM_PMC_SH	20	/* PMC number (1-based) for direct events */
+#define PM_PMC_MSK	0xf
+#define PM_PMC_MSKS	(PM_PMC_MSK << PM_PMC_SH)
+#define PM_UNIT_SH	16	/* TTMMUX number and setting - unit select */
+#define PM_UNIT_MSK	0xf
+#define PM_BYTE_SH	12	/* Byte number of event bus to use */
+#define PM_BYTE_MSK	7
+#define PM_GRS_SH	8	/* Storage subsystem mux select */
+#define PM_GRS_MSK	7
+#define PM_BUSEVENT_MSK	0x80	/* Set if event uses event bus */
+#define PM_PMCSEL_MSK	0x7f
+
+/* Values in PM_UNIT field */
+#define PM_FPU		0
+#define PM_ISU0		1
+#define PM_IFU		2
+#define PM_ISU1		3
+#define PM_IDU		4
+#define PM_ISU0_ALT	6
+#define PM_GRS		7
+#define PM_LSU0		8
+#define PM_LSU1		0xc
+#define PM_LASTUNIT	0xc
+
+/*
+ * Bits in MMCR1 for POWER5
+ */
+#define MMCR1_TTM0SEL_SH	62
+#define MMCR1_TTM1SEL_SH	60
+#define MMCR1_TTM2SEL_SH	58
+#define MMCR1_TTM3SEL_SH	56
+#define MMCR1_TTMSEL_MSK	3
+#define MMCR1_TD_CP_DBG0SEL_SH	54
+#define MMCR1_TD_CP_DBG1SEL_SH	52
+#define MMCR1_TD_CP_DBG2SEL_SH	50
+#define MMCR1_TD_CP_DBG3SEL_SH	48
+#define MMCR1_GRS_L2SEL_SH	46
+#define MMCR1_GRS_L2SEL_MSK	3
+#define MMCR1_GRS_L3SEL_SH	44
+#define MMCR1_GRS_L3SEL_MSK	3
+#define MMCR1_GRS_MCSEL_SH	41
+#define MMCR1_GRS_MCSEL_MSK	7
+#define MMCR1_GRS_FABSEL_SH	39
+#define MMCR1_GRS_FABSEL_MSK	3
+#define MMCR1_PMC1_ADDER_SEL_SH	35
+#define MMCR1_PMC2_ADDER_SEL_SH	34
+#define MMCR1_PMC3_ADDER_SEL_SH	33
+#define MMCR1_PMC4_ADDER_SEL_SH	32
+#define MMCR1_PMC1SEL_SH	25
+#define MMCR1_PMC2SEL_SH	17
+#define MMCR1_PMC3SEL_SH	9
+#define MMCR1_PMC4SEL_SH	1
+#define MMCR1_PMCSEL_SH(n)	(MMCR1_PMC1SEL_SH - (n) * 8)
+#define MMCR1_PMCSEL_MSK	0x7f
+
+/*
+ * Bits in MMCRA
+ */
+
+/*
+ * Layout of constraint bits:
+ * 6666555555555544444444443333333333222222222211111111110000000000
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ *         <><>[  ><><>< ><> [  >[ >[ ><  ><  ><  ><  ><><><><><><>
+ *         T0T1 NC G0G1G2 G3  UC PS1PS2 B0  B1  B2  B3 P6P5P4P3P2P1
+ *
+ * T0 - TTM0 constraint
+ *     54-55: TTM0SEL value (0=FPU, 2=IFU, 3=ISU1) 0xc0_0000_0000_0000
+ *
+ * T1 - TTM1 constraint
+ *     52-53: TTM1SEL value (0=IDU, 3=GRS) 0x30_0000_0000_0000
+ *
+ * NC - number of counters
+ *     51: NC error 0x0008_0000_0000_0000
+ *     48-50: number of events needing PMC1-4 0x0007_0000_0000_0000
+ *
+ * G0..G3 - GRS mux constraints
+ *     46-47: GRS_L2SEL value
+ *     44-45: GRS_L3SEL value
+ *     41-44: GRS_MCSEL value
+ *     39-40: GRS_FABSEL value
+ *	Note that these match up with their bit positions in MMCR1
+ *
+ * UC - unit constraint: can't have all three of FPU|IFU|ISU1, ISU0, IDU|GRS
+ *     37: UC3 error 0x20_0000_0000
+ *     36: FPU|IFU|ISU1 events needed 0x10_0000_0000
+ *     35: ISU0 events needed 0x08_0000_0000
+ *     34: IDU|GRS events needed 0x04_0000_0000
+ *
+ * PS1
+ *     33: PS1 error 0x2_0000_0000
+ *     31-32: count of events needing PMC1/2 0x1_8000_0000
+ *
+ * PS2
+ *     30: PS2 error 0x4000_0000
+ *     28-29: count of events needing PMC3/4 0x3000_0000
+ *
+ * B0
+ *     24-27: Byte 0 event source 0x0f00_0000
+ *	      Encoding as for the event code
+ *
+ * B1, B2, B3
+ *     20-23, 16-19, 12-15: Byte 1, 2, 3 event sources
+ *
+ * P1..P6
+ *     0-11: Count of events needing PMC1..PMC6
+ */
+
+static const int grsel_shift[8] = {
+	MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH,
+	MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH,
+	MMCR1_GRS_MCSEL_SH, MMCR1_GRS_FABSEL_SH
+};
+
+/* Masks and values for using events from the various units */
+static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
+	[PM_FPU] =   { 0xc0002000000000ul, 0x00001000000000ul },
+	[PM_ISU0] =  { 0x00002000000000ul, 0x00000800000000ul },
+	[PM_ISU1] =  { 0xc0002000000000ul, 0xc0001000000000ul },
+	[PM_IFU] =   { 0xc0002000000000ul, 0x80001000000000ul },
+	[PM_IDU] =   { 0x30002000000000ul, 0x00000400000000ul },
+	[PM_GRS] =   { 0x30002000000000ul, 0x30000400000000ul },
+};
+
+static int power5_get_constraint(u64 event, unsigned long *maskp,
+				 unsigned long *valp)
+{
+	int pmc, byte, unit, sh;
+	int bit, fmask;
+	unsigned long mask = 0, value = 0;
+	int grp = -1;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc) {
+		if (pmc > 6)
+			return -1;
+		sh = (pmc - 1) * 2;
+		mask |= 2 << sh;
+		value |= 1 << sh;
+		if (pmc <= 4)
+			grp = (pmc - 1) >> 1;
+		else if (event != 0x500009 && event != 0x600005)
+			return -1;
+	}
+	if (event & PM_BUSEVENT_MSK) {
+		unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+		if (unit > PM_LASTUNIT)
+			return -1;
+		if (unit == PM_ISU0_ALT)
+			unit = PM_ISU0;
+		mask |= unit_cons[unit][0];
+		value |= unit_cons[unit][1];
+		byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+		if (byte >= 4) {
+			if (unit != PM_LSU1)
+				return -1;
+			/* Map LSU1 low word (bytes 4-7) to unit LSU1+1 */
+			++unit;
+			byte &= 3;
+		}
+		if (unit == PM_GRS) {
+			bit = event & 7;
+			fmask = (bit == 6)? 7: 3;
+			sh = grsel_shift[bit];
+			mask |= (unsigned long)fmask << sh;
+			value |= (unsigned long)((event >> PM_GRS_SH) & fmask)
+				<< sh;
+		}
+		/*
+		 * Bus events on bytes 0 and 2 can be counted
+		 * on PMC1/2; bytes 1 and 3 on PMC3/4.
+		 */
+		if (!pmc)
+			grp = byte & 1;
+		/* Set byte lane select field */
+		mask  |= 0xfUL << (24 - 4 * byte);
+		value |= (unsigned long)unit << (24 - 4 * byte);
+	}
+	if (grp == 0) {
+		/* increment PMC1/2 field */
+		mask  |= 0x200000000ul;
+		value |= 0x080000000ul;
+	} else if (grp == 1) {
+		/* increment PMC3/4 field */
+		mask  |= 0x40000000ul;
+		value |= 0x10000000ul;
+	}
+	if (pmc < 5) {
+		/* need a counter from PMC1-4 set */
+		mask  |= 0x8000000000000ul;
+		value |= 0x1000000000000ul;
+	}
+	*maskp = mask;
+	*valp = value;
+	return 0;
+}
+
+#define MAX_ALT	3	/* at most 3 alternatives for any event */
+
+static const unsigned int event_alternatives[][MAX_ALT] = {
+	{ 0x120e4,  0x400002 },			/* PM_GRP_DISP_REJECT */
+	{ 0x410c7,  0x441084 },			/* PM_THRD_L2MISS_BOTH_CYC */
+	{ 0x100005, 0x600005 },			/* PM_RUN_CYC */
+	{ 0x100009, 0x200009, 0x500009 },	/* PM_INST_CMPL */
+	{ 0x300009, 0x400009 },			/* PM_INST_DISP */
+};
+
+/*
+ * Scan the alternatives table for a match and return the
+ * index into the alternatives table if found, else -1.
+ */
+static int find_alternative(u64 event)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
+		if (event < event_alternatives[i][0])
+			break;
+		for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
+			if (event == event_alternatives[i][j])
+				return i;
+	}
+	return -1;
+}
+
+static const unsigned char bytedecode_alternatives[4][4] = {
+	/* PMC 1 */	{ 0x21, 0x23, 0x25, 0x27 },
+	/* PMC 2 */	{ 0x07, 0x17, 0x0e, 0x1e },
+	/* PMC 3 */	{ 0x20, 0x22, 0x24, 0x26 },
+	/* PMC 4 */	{ 0x07, 0x17, 0x0e, 0x1e }
+};
+
+/*
+ * Some direct events for decodes of event bus byte 3 have alternative
+ * PMCSEL values on other counters.  This returns the alternative
+ * event code for those that do, or -1 otherwise.
+ */
+static s64 find_alternative_bdecode(u64 event)
+{
+	int pmc, altpmc, pp, j;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc == 0 || pmc > 4)
+		return -1;
+	altpmc = 5 - pmc;	/* 1 <-> 4, 2 <-> 3 */
+	pp = event & PM_PMCSEL_MSK;
+	for (j = 0; j < 4; ++j) {
+		if (bytedecode_alternatives[pmc - 1][j] == pp) {
+			return (event & ~(PM_PMC_MSKS | PM_PMCSEL_MSK)) |
+				(altpmc << PM_PMC_SH) |
+				bytedecode_alternatives[altpmc - 1][j];
+		}
+	}
+	return -1;
+}
+
+static int power5_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	int i, j, nalt = 1;
+	s64 ae;
+
+	alt[0] = event;
+	nalt = 1;
+	i = find_alternative(event);
+	if (i >= 0) {
+		for (j = 0; j < MAX_ALT; ++j) {
+			ae = event_alternatives[i][j];
+			if (ae && ae != event)
+				alt[nalt++] = ae;
+		}
+	} else {
+		ae = find_alternative_bdecode(event);
+		if (ae > 0)
+			alt[nalt++] = ae;
+	}
+	return nalt;
+}
+
+/*
+ * Map of which direct events on which PMCs are marked instruction events.
+ * Indexed by PMCSEL value, bit i (LE) set if PMC i is a marked event.
+ * Bit 0 is set if it is marked for all PMCs.
+ * The 0x80 bit indicates a byte decode PMCSEL value.
+ */
+static unsigned char direct_event_is_marked[0x28] = {
+	0,	/* 00 */
+	0x1f,	/* 01 PM_IOPS_CMPL */
+	0x2,	/* 02 PM_MRK_GRP_DISP */
+	0xe,	/* 03 PM_MRK_ST_CMPL, PM_MRK_ST_GPS, PM_MRK_ST_CMPL_INT */
+	0,	/* 04 */
+	0x1c,	/* 05 PM_MRK_BRU_FIN, PM_MRK_INST_FIN, PM_MRK_CRU_FIN */
+	0x80,	/* 06 */
+	0x80,	/* 07 */
+	0, 0, 0,/* 08 - 0a */
+	0x18,	/* 0b PM_THRESH_TIMEO, PM_MRK_GRP_TIMEO */
+	0,	/* 0c */
+	0x80,	/* 0d */
+	0x80,	/* 0e */
+	0,	/* 0f */
+	0,	/* 10 */
+	0x14,	/* 11 PM_MRK_GRP_BR_REDIR, PM_MRK_GRP_IC_MISS */
+	0,	/* 12 */
+	0x10,	/* 13 PM_MRK_GRP_CMPL */
+	0x1f,	/* 14 PM_GRP_MRK, PM_MRK_{FXU,FPU,LSU}_FIN */
+	0x2,	/* 15 PM_MRK_GRP_ISSUED */
+	0x80,	/* 16 */
+	0x80,	/* 17 */
+	0, 0, 0, 0, 0,
+	0x80,	/* 1d */
+	0x80,	/* 1e */
+	0,	/* 1f */
+	0x80,	/* 20 */
+	0x80,	/* 21 */
+	0x80,	/* 22 */
+	0x80,	/* 23 */
+	0x80,	/* 24 */
+	0x80,	/* 25 */
+	0x80,	/* 26 */
+	0x80,	/* 27 */
+};
+
+/*
+ * Returns 1 if event counts things relating to marked instructions
+ * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
+ */
+static int power5_marked_instr_event(u64 event)
+{
+	int pmc, psel;
+	int bit, byte, unit;
+	u32 mask;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	psel = event & PM_PMCSEL_MSK;
+	if (pmc >= 5)
+		return 0;
+
+	bit = -1;
+	if (psel < sizeof(direct_event_is_marked)) {
+		if (direct_event_is_marked[psel] & (1 << pmc))
+			return 1;
+		if (direct_event_is_marked[psel] & 0x80)
+			bit = 4;
+		else if (psel == 0x08)
+			bit = pmc - 1;
+		else if (psel == 0x10)
+			bit = 4 - pmc;
+		else if (psel == 0x1b && (pmc == 1 || pmc == 3))
+			bit = 4;
+	} else if ((psel & 0x58) == 0x40)
+		bit = psel & 7;
+
+	if (!(event & PM_BUSEVENT_MSK))
+		return 0;
+
+	byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	if (unit == PM_LSU0) {
+		/* byte 1 bits 0-7, byte 2 bits 0,2-4,6 */
+		mask = 0x5dff00;
+	} else if (unit == PM_LSU1 && byte >= 4) {
+		byte -= 4;
+		/* byte 4 bits 1,3,5,7, byte 5 bits 6-7, byte 7 bits 0-4,6 */
+		mask = 0x5f00c0aa;
+	} else
+		return 0;
+
+	return (mask >> (byte * 8 + bit)) & 1;
+}
+
+static int power5_compute_mmcr(u64 event[], int n_ev,
+			       unsigned int hwc[], unsigned long mmcr[])
+{
+	unsigned long mmcr1 = 0;
+	unsigned long mmcra = 0;
+	unsigned int pmc, unit, byte, psel;
+	unsigned int ttm, grp;
+	int i, isbus, bit, grsel;
+	unsigned int pmc_inuse = 0;
+	unsigned int pmc_grp_use[2];
+	unsigned char busbyte[4];
+	unsigned char unituse[16];
+	int ttmuse;
+
+	if (n_ev > 6)
+		return -1;
+
+	/* First pass to count resource use */
+	pmc_grp_use[0] = pmc_grp_use[1] = 0;
+	memset(busbyte, 0, sizeof(busbyte));
+	memset(unituse, 0, sizeof(unituse));
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc) {
+			if (pmc > 6)
+				return -1;
+			if (pmc_inuse & (1 << (pmc - 1)))
+				return -1;
+			pmc_inuse |= 1 << (pmc - 1);
+			/* count 1/2 vs 3/4 use */
+			if (pmc <= 4)
+				++pmc_grp_use[(pmc - 1) >> 1];
+		}
+		if (event[i] & PM_BUSEVENT_MSK) {
+			unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+			byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+			if (unit > PM_LASTUNIT)
+				return -1;
+			if (unit == PM_ISU0_ALT)
+				unit = PM_ISU0;
+			if (byte >= 4) {
+				if (unit != PM_LSU1)
+					return -1;
+				++unit;
+				byte &= 3;
+			}
+			if (!pmc)
+				++pmc_grp_use[byte & 1];
+			if (busbyte[byte] && busbyte[byte] != unit)
+				return -1;
+			busbyte[byte] = unit;
+			unituse[unit] = 1;
+		}
+	}
+	if (pmc_grp_use[0] > 2 || pmc_grp_use[1] > 2)
+		return -1;
+
+	/*
+	 * Assign resources and set multiplexer selects.
+	 *
+	 * PM_ISU0 can go either on TTM0 or TTM1, but that's the only
+	 * choice we have to deal with.
+	 */
+	if (unituse[PM_ISU0] &
+	    (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_ISU1])) {
+		unituse[PM_ISU0_ALT] = 1;	/* move ISU to TTM1 */
+		unituse[PM_ISU0] = 0;
+	}
+	/* Set TTM[01]SEL fields. */
+	ttmuse = 0;
+	for (i = PM_FPU; i <= PM_ISU1; ++i) {
+		if (!unituse[i])
+			continue;
+		if (ttmuse++)
+			return -1;
+		mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH;
+	}
+	ttmuse = 0;
+	for (; i <= PM_GRS; ++i) {
+		if (!unituse[i])
+			continue;
+		if (ttmuse++)
+			return -1;
+		mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH;
+	}
+	if (ttmuse > 1)
+		return -1;
+
+	/* Set byte lane select fields, TTM[23]SEL and GRS_*SEL. */
+	for (byte = 0; byte < 4; ++byte) {
+		unit = busbyte[byte];
+		if (!unit)
+			continue;
+		if (unit == PM_ISU0 && unituse[PM_ISU0_ALT]) {
+			/* get ISU0 through TTM1 rather than TTM0 */
+			unit = PM_ISU0_ALT;
+		} else if (unit == PM_LSU1 + 1) {
+			/* select lower word of LSU1 for this byte */
+			mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte);
+		}
+		ttm = unit >> 2;
+		mmcr1 |= (unsigned long)ttm
+			<< (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
+	}
+
+	/* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+		byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+		psel = event[i] & PM_PMCSEL_MSK;
+		isbus = event[i] & PM_BUSEVENT_MSK;
+		if (!pmc) {
+			/* Bus event or any-PMC direct event */
+			for (pmc = 0; pmc < 4; ++pmc) {
+				if (pmc_inuse & (1 << pmc))
+					continue;
+				grp = (pmc >> 1) & 1;
+				if (isbus) {
+					if (grp == (byte & 1))
+						break;
+				} else if (pmc_grp_use[grp] < 2) {
+					++pmc_grp_use[grp];
+					break;
+				}
+			}
+			pmc_inuse |= 1 << pmc;
+		} else if (pmc <= 4) {
+			/* Direct event */
+			--pmc;
+			if ((psel == 8 || psel == 0x10) && isbus && (byte & 2))
+				/* add events on higher-numbered bus */
+				mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
+		} else {
+			/* Instructions or run cycles on PMC5/6 */
+			--pmc;
+		}
+		if (isbus && unit == PM_GRS) {
+			bit = psel & 7;
+			grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK;
+			mmcr1 |= (unsigned long)grsel << grsel_shift[bit];
+		}
+		if (power5_marked_instr_event(event[i]))
+			mmcra |= MMCRA_SAMPLE_ENABLE;
+		if (pmc <= 3)
+			mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc);
+		hwc[i] = pmc;
+	}
+
+	/* Return MMCRx values */
+	mmcr[0] = 0;
+	if (pmc_inuse & 1)
+		mmcr[0] = MMCR0_PMC1CE;
+	if (pmc_inuse & 0x3e)
+		mmcr[0] |= MMCR0_PMCjCE;
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcra;
+	return 0;
+}
+
+static void power5_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	if (pmc <= 3)
+		mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc));
+}
+
+static int power5_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= 0xf,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= 0x100009,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= 0x4c1090, /* LD_REF_L1 */
+	[PERF_COUNT_HW_CACHE_MISSES]		= 0x3c1088, /* LD_MISS_L1 */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x230e4,  /* BR_ISSUED */
+	[PERF_COUNT_HW_BRANCH_MISSES]		= 0x230e5,  /* BR_MPRED_CR */
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x4c1090,	0x3c1088	},
+		[C(OP_WRITE)] = {	0x3c1090,	0xc10c3		},
+		[C(OP_PREFETCH)] = {	0xc70e7,	0		},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	0,		0		},
+	},
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x3c309b	},
+		[C(OP_WRITE)] = {	0,		0		},
+		[C(OP_PREFETCH)] = {	0xc50c3,	0		},
+	},
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x2c4090,	0x800c4		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+	[C(ITLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x800c0		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x230e4,	0x230e5		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+};
+
+static struct power_pmu power5_pmu = {
+	.name			= "POWER5",
+	.n_counter		= 6,
+	.max_alternatives	= MAX_ALT,
+	.add_fields		= 0x7000090000555ul,
+	.test_adder		= 0x3000490000000ul,
+	.compute_mmcr		= power5_compute_mmcr,
+	.get_constraint		= power5_get_constraint,
+	.get_alternatives	= power5_get_alternatives,
+	.disable_pmc		= power5_disable_pmc,
+	.n_generic		= ARRAY_SIZE(power5_generic_events),
+	.generic_events		= power5_generic_events,
+	.cache_events		= &power5_cache_events,
+};
+
+static int init_power5_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
+		return -ENODEV;
+
+	return register_power_pmu(&power5_pmu);
+}
+
+arch_initcall(init_power5_pmu);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/power5+-pmu.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/power5+-pmu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/power5+-pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/power5+-pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,689 @@
+/*
+ * Performance counter support for POWER5+/++ (not POWER5) processors.
+ *
+ * Copyright 2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/kernel.h>
+#include <linux/perf_counter.h>
+#include <linux/string.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Bits in event code for POWER5+ (POWER5 GS) and POWER5++ (POWER5 GS DD3)
+ */
+#define PM_PMC_SH	20	/* PMC number (1-based) for direct events */
+#define PM_PMC_MSK	0xf
+#define PM_PMC_MSKS	(PM_PMC_MSK << PM_PMC_SH)
+#define PM_UNIT_SH	16	/* TTMMUX number and setting - unit select */
+#define PM_UNIT_MSK	0xf
+#define PM_BYTE_SH	12	/* Byte number of event bus to use */
+#define PM_BYTE_MSK	7
+#define PM_GRS_SH	8	/* Storage subsystem mux select */
+#define PM_GRS_MSK	7
+#define PM_BUSEVENT_MSK	0x80	/* Set if event uses event bus */
+#define PM_PMCSEL_MSK	0x7f
+
+/* Values in PM_UNIT field */
+#define PM_FPU		0
+#define PM_ISU0		1
+#define PM_IFU		2
+#define PM_ISU1		3
+#define PM_IDU		4
+#define PM_ISU0_ALT	6
+#define PM_GRS		7
+#define PM_LSU0		8
+#define PM_LSU1		0xc
+#define PM_LASTUNIT	0xc
+
+/*
+ * Bits in MMCR1 for POWER5+
+ */
+#define MMCR1_TTM0SEL_SH	62
+#define MMCR1_TTM1SEL_SH	60
+#define MMCR1_TTM2SEL_SH	58
+#define MMCR1_TTM3SEL_SH	56
+#define MMCR1_TTMSEL_MSK	3
+#define MMCR1_TD_CP_DBG0SEL_SH	54
+#define MMCR1_TD_CP_DBG1SEL_SH	52
+#define MMCR1_TD_CP_DBG2SEL_SH	50
+#define MMCR1_TD_CP_DBG3SEL_SH	48
+#define MMCR1_GRS_L2SEL_SH	46
+#define MMCR1_GRS_L2SEL_MSK	3
+#define MMCR1_GRS_L3SEL_SH	44
+#define MMCR1_GRS_L3SEL_MSK	3
+#define MMCR1_GRS_MCSEL_SH	41
+#define MMCR1_GRS_MCSEL_MSK	7
+#define MMCR1_GRS_FABSEL_SH	39
+#define MMCR1_GRS_FABSEL_MSK	3
+#define MMCR1_PMC1_ADDER_SEL_SH	35
+#define MMCR1_PMC2_ADDER_SEL_SH	34
+#define MMCR1_PMC3_ADDER_SEL_SH	33
+#define MMCR1_PMC4_ADDER_SEL_SH	32
+#define MMCR1_PMC1SEL_SH	25
+#define MMCR1_PMC2SEL_SH	17
+#define MMCR1_PMC3SEL_SH	9
+#define MMCR1_PMC4SEL_SH	1
+#define MMCR1_PMCSEL_SH(n)	(MMCR1_PMC1SEL_SH - (n) * 8)
+#define MMCR1_PMCSEL_MSK	0x7f
+
+/*
+ * Bits in MMCRA
+ */
+
+/*
+ * Layout of constraint bits:
+ * 6666555555555544444444443333333333222222222211111111110000000000
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ *             [  ><><>< ><> <><>[  >  <  ><  ><  ><  ><><><><><><>
+ *             NC  G0G1G2 G3 T0T1 UC    B0  B1  B2  B3 P6P5P4P3P2P1
+ *
+ * NC - number of counters
+ *     51: NC error 0x0008_0000_0000_0000
+ *     48-50: number of events needing PMC1-4 0x0007_0000_0000_0000
+ *
+ * G0..G3 - GRS mux constraints
+ *     46-47: GRS_L2SEL value
+ *     44-45: GRS_L3SEL value
+ *     41-44: GRS_MCSEL value
+ *     39-40: GRS_FABSEL value
+ *	Note that these match up with their bit positions in MMCR1
+ *
+ * T0 - TTM0 constraint
+ *     36-37: TTM0SEL value (0=FPU, 2=IFU, 3=ISU1) 0x30_0000_0000
+ *
+ * T1 - TTM1 constraint
+ *     34-35: TTM1SEL value (0=IDU, 3=GRS) 0x0c_0000_0000
+ *
+ * UC - unit constraint: can't have all three of FPU|IFU|ISU1, ISU0, IDU|GRS
+ *     33: UC3 error 0x02_0000_0000
+ *     32: FPU|IFU|ISU1 events needed 0x01_0000_0000
+ *     31: ISU0 events needed 0x01_8000_0000
+ *     30: IDU|GRS events needed 0x00_4000_0000
+ *
+ * B0
+ *     24-27: Byte 0 event source 0x0f00_0000
+ *	      Encoding as for the event code
+ *
+ * B1, B2, B3
+ *     20-23, 16-19, 12-15: Byte 1, 2, 3 event sources
+ *
+ * P6
+ *     11: P6 error 0x800
+ *     10-11: Count of events needing PMC6
+ *
+ * P1..P5
+ *     0-9: Count of events needing PMC1..PMC5
+ */
+
+static const int grsel_shift[8] = {
+	MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH,
+	MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH,
+	MMCR1_GRS_MCSEL_SH, MMCR1_GRS_FABSEL_SH
+};
+
+/* Masks and values for using events from the various units */
+static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
+	[PM_FPU] =   { 0x3200000000ul, 0x0100000000ul },
+	[PM_ISU0] =  { 0x0200000000ul, 0x0080000000ul },
+	[PM_ISU1] =  { 0x3200000000ul, 0x3100000000ul },
+	[PM_IFU] =   { 0x3200000000ul, 0x2100000000ul },
+	[PM_IDU] =   { 0x0e00000000ul, 0x0040000000ul },
+	[PM_GRS] =   { 0x0e00000000ul, 0x0c40000000ul },
+};
+
+static int power5p_get_constraint(u64 event, unsigned long *maskp,
+				  unsigned long *valp)
+{
+	int pmc, byte, unit, sh;
+	int bit, fmask;
+	unsigned long mask = 0, value = 0;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc) {
+		if (pmc > 6)
+			return -1;
+		sh = (pmc - 1) * 2;
+		mask |= 2 << sh;
+		value |= 1 << sh;
+		if (pmc >= 5 && !(event == 0x500009 || event == 0x600005))
+			return -1;
+	}
+	if (event & PM_BUSEVENT_MSK) {
+		unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+		if (unit > PM_LASTUNIT)
+			return -1;
+		if (unit == PM_ISU0_ALT)
+			unit = PM_ISU0;
+		mask |= unit_cons[unit][0];
+		value |= unit_cons[unit][1];
+		byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+		if (byte >= 4) {
+			if (unit != PM_LSU1)
+				return -1;
+			/* Map LSU1 low word (bytes 4-7) to unit LSU1+1 */
+			++unit;
+			byte &= 3;
+		}
+		if (unit == PM_GRS) {
+			bit = event & 7;
+			fmask = (bit == 6)? 7: 3;
+			sh = grsel_shift[bit];
+			mask |= (unsigned long)fmask << sh;
+			value |= (unsigned long)((event >> PM_GRS_SH) & fmask)
+				<< sh;
+		}
+		/* Set byte lane select field */
+		mask  |= 0xfUL << (24 - 4 * byte);
+		value |= (unsigned long)unit << (24 - 4 * byte);
+	}
+	if (pmc < 5) {
+		/* need a counter from PMC1-4 set */
+		mask  |= 0x8000000000000ul;
+		value |= 0x1000000000000ul;
+	}
+	*maskp = mask;
+	*valp = value;
+	return 0;
+}
+
+static int power5p_limited_pmc_event(u64 event)
+{
+	int pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+
+	return pmc == 5 || pmc == 6;
+}
+
+#define MAX_ALT	3	/* at most 3 alternatives for any event */
+
+static const unsigned int event_alternatives[][MAX_ALT] = {
+	{ 0x100c0,  0x40001f },			/* PM_GCT_FULL_CYC */
+	{ 0x120e4,  0x400002 },			/* PM_GRP_DISP_REJECT */
+	{ 0x230e2,  0x323087 },			/* PM_BR_PRED_CR */
+	{ 0x230e3,  0x223087, 0x3230a0 },	/* PM_BR_PRED_TA */
+	{ 0x410c7,  0x441084 },			/* PM_THRD_L2MISS_BOTH_CYC */
+	{ 0x800c4,  0xc20e0 },			/* PM_DTLB_MISS */
+	{ 0xc50c6,  0xc60e0 },			/* PM_MRK_DTLB_MISS */
+	{ 0x100005, 0x600005 },			/* PM_RUN_CYC */
+	{ 0x100009, 0x200009 },			/* PM_INST_CMPL */
+	{ 0x200015, 0x300015 },			/* PM_LSU_LMQ_SRQ_EMPTY_CYC */
+	{ 0x300009, 0x400009 },			/* PM_INST_DISP */
+};
+
+/*
+ * Scan the alternatives table for a match and return the
+ * index into the alternatives table if found, else -1.
+ */
+static int find_alternative(unsigned int event)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
+		if (event < event_alternatives[i][0])
+			break;
+		for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
+			if (event == event_alternatives[i][j])
+				return i;
+	}
+	return -1;
+}
+
+static const unsigned char bytedecode_alternatives[4][4] = {
+	/* PMC 1 */	{ 0x21, 0x23, 0x25, 0x27 },
+	/* PMC 2 */	{ 0x07, 0x17, 0x0e, 0x1e },
+	/* PMC 3 */	{ 0x20, 0x22, 0x24, 0x26 },
+	/* PMC 4 */	{ 0x07, 0x17, 0x0e, 0x1e }
+};
+
+/*
+ * Some direct events for decodes of event bus byte 3 have alternative
+ * PMCSEL values on other counters.  This returns the alternative
+ * event code for those that do, or -1 otherwise.  This also handles
+ * alternative PCMSEL values for add events.
+ */
+static s64 find_alternative_bdecode(u64 event)
+{
+	int pmc, altpmc, pp, j;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc == 0 || pmc > 4)
+		return -1;
+	altpmc = 5 - pmc;	/* 1 <-> 4, 2 <-> 3 */
+	pp = event & PM_PMCSEL_MSK;
+	for (j = 0; j < 4; ++j) {
+		if (bytedecode_alternatives[pmc - 1][j] == pp) {
+			return (event & ~(PM_PMC_MSKS | PM_PMCSEL_MSK)) |
+				(altpmc << PM_PMC_SH) |
+				bytedecode_alternatives[altpmc - 1][j];
+		}
+	}
+
+	/* new decode alternatives for power5+ */
+	if (pmc == 1 && (pp == 0x0d || pp == 0x0e))
+		return event + (2 << PM_PMC_SH) + (0x2e - 0x0d);
+	if (pmc == 3 && (pp == 0x2e || pp == 0x2f))
+		return event - (2 << PM_PMC_SH) - (0x2e - 0x0d);
+
+	/* alternative add event encodings */
+	if (pp == 0x10 || pp == 0x28)
+		return ((event ^ (0x10 ^ 0x28)) & ~PM_PMC_MSKS) |
+			(altpmc << PM_PMC_SH);
+
+	return -1;
+}
+
+static int power5p_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	int i, j, nalt = 1;
+	int nlim;
+	s64 ae;
+
+	alt[0] = event;
+	nalt = 1;
+	nlim = power5p_limited_pmc_event(event);
+	i = find_alternative(event);
+	if (i >= 0) {
+		for (j = 0; j < MAX_ALT; ++j) {
+			ae = event_alternatives[i][j];
+			if (ae && ae != event)
+				alt[nalt++] = ae;
+			nlim += power5p_limited_pmc_event(ae);
+		}
+	} else {
+		ae = find_alternative_bdecode(event);
+		if (ae > 0)
+			alt[nalt++] = ae;
+	}
+
+	if (flags & PPMU_ONLY_COUNT_RUN) {
+		/*
+		 * We're only counting in RUN state,
+		 * so PM_CYC is equivalent to PM_RUN_CYC
+		 * and PM_INST_CMPL === PM_RUN_INST_CMPL.
+		 * This doesn't include alternatives that don't provide
+		 * any extra flexibility in assigning PMCs (e.g.
+		 * 0x100005 for PM_RUN_CYC vs. 0xf for PM_CYC).
+		 * Note that even with these additional alternatives
+		 * we never end up with more than 3 alternatives for any event.
+		 */
+		j = nalt;
+		for (i = 0; i < nalt; ++i) {
+			switch (alt[i]) {
+			case 0xf:	/* PM_CYC */
+				alt[j++] = 0x600005;	/* PM_RUN_CYC */
+				++nlim;
+				break;
+			case 0x600005:	/* PM_RUN_CYC */
+				alt[j++] = 0xf;
+				break;
+			case 0x100009:	/* PM_INST_CMPL */
+				alt[j++] = 0x500009;	/* PM_RUN_INST_CMPL */
+				++nlim;
+				break;
+			case 0x500009:	/* PM_RUN_INST_CMPL */
+				alt[j++] = 0x100009;	/* PM_INST_CMPL */
+				alt[j++] = 0x200009;
+				break;
+			}
+		}
+		nalt = j;
+	}
+
+	if (!(flags & PPMU_LIMITED_PMC_OK) && nlim) {
+		/* remove the limited PMC events */
+		j = 0;
+		for (i = 0; i < nalt; ++i) {
+			if (!power5p_limited_pmc_event(alt[i])) {
+				alt[j] = alt[i];
+				++j;
+			}
+		}
+		nalt = j;
+	} else if ((flags & PPMU_LIMITED_PMC_REQD) && nlim < nalt) {
+		/* remove all but the limited PMC events */
+		j = 0;
+		for (i = 0; i < nalt; ++i) {
+			if (power5p_limited_pmc_event(alt[i])) {
+				alt[j] = alt[i];
+				++j;
+			}
+		}
+		nalt = j;
+	}
+
+	return nalt;
+}
+
+/*
+ * Map of which direct events on which PMCs are marked instruction events.
+ * Indexed by PMCSEL value, bit i (LE) set if PMC i is a marked event.
+ * Bit 0 is set if it is marked for all PMCs.
+ * The 0x80 bit indicates a byte decode PMCSEL value.
+ */
+static unsigned char direct_event_is_marked[0x28] = {
+	0,	/* 00 */
+	0x1f,	/* 01 PM_IOPS_CMPL */
+	0x2,	/* 02 PM_MRK_GRP_DISP */
+	0xe,	/* 03 PM_MRK_ST_CMPL, PM_MRK_ST_GPS, PM_MRK_ST_CMPL_INT */
+	0,	/* 04 */
+	0x1c,	/* 05 PM_MRK_BRU_FIN, PM_MRK_INST_FIN, PM_MRK_CRU_FIN */
+	0x80,	/* 06 */
+	0x80,	/* 07 */
+	0, 0, 0,/* 08 - 0a */
+	0x18,	/* 0b PM_THRESH_TIMEO, PM_MRK_GRP_TIMEO */
+	0,	/* 0c */
+	0x80,	/* 0d */
+	0x80,	/* 0e */
+	0,	/* 0f */
+	0,	/* 10 */
+	0x14,	/* 11 PM_MRK_GRP_BR_REDIR, PM_MRK_GRP_IC_MISS */
+	0,	/* 12 */
+	0x10,	/* 13 PM_MRK_GRP_CMPL */
+	0x1f,	/* 14 PM_GRP_MRK, PM_MRK_{FXU,FPU,LSU}_FIN */
+	0x2,	/* 15 PM_MRK_GRP_ISSUED */
+	0x80,	/* 16 */
+	0x80,	/* 17 */
+	0, 0, 0, 0, 0,
+	0x80,	/* 1d */
+	0x80,	/* 1e */
+	0,	/* 1f */
+	0x80,	/* 20 */
+	0x80,	/* 21 */
+	0x80,	/* 22 */
+	0x80,	/* 23 */
+	0x80,	/* 24 */
+	0x80,	/* 25 */
+	0x80,	/* 26 */
+	0x80,	/* 27 */
+};
+
+/*
+ * Returns 1 if event counts things relating to marked instructions
+ * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
+ */
+static int power5p_marked_instr_event(u64 event)
+{
+	int pmc, psel;
+	int bit, byte, unit;
+	u32 mask;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	psel = event & PM_PMCSEL_MSK;
+	if (pmc >= 5)
+		return 0;
+
+	bit = -1;
+	if (psel < sizeof(direct_event_is_marked)) {
+		if (direct_event_is_marked[psel] & (1 << pmc))
+			return 1;
+		if (direct_event_is_marked[psel] & 0x80)
+			bit = 4;
+		else if (psel == 0x08)
+			bit = pmc - 1;
+		else if (psel == 0x10)
+			bit = 4 - pmc;
+		else if (psel == 0x1b && (pmc == 1 || pmc == 3))
+			bit = 4;
+	} else if ((psel & 0x48) == 0x40) {
+		bit = psel & 7;
+	} else if (psel == 0x28) {
+		bit = pmc - 1;
+	} else if (pmc == 3 && (psel == 0x2e || psel == 0x2f)) {
+		bit = 4;
+	}
+
+	if (!(event & PM_BUSEVENT_MSK) || bit == -1)
+		return 0;
+
+	byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	if (unit == PM_LSU0) {
+		/* byte 1 bits 0-7, byte 2 bits 0,2-4,6 */
+		mask = 0x5dff00;
+	} else if (unit == PM_LSU1 && byte >= 4) {
+		byte -= 4;
+		/* byte 5 bits 6-7, byte 6 bits 0,4, byte 7 bits 0-4,6 */
+		mask = 0x5f11c000;
+	} else
+		return 0;
+
+	return (mask >> (byte * 8 + bit)) & 1;
+}
+
+static int power5p_compute_mmcr(u64 event[], int n_ev,
+				unsigned int hwc[], unsigned long mmcr[])
+{
+	unsigned long mmcr1 = 0;
+	unsigned long mmcra = 0;
+	unsigned int pmc, unit, byte, psel;
+	unsigned int ttm;
+	int i, isbus, bit, grsel;
+	unsigned int pmc_inuse = 0;
+	unsigned char busbyte[4];
+	unsigned char unituse[16];
+	int ttmuse;
+
+	if (n_ev > 6)
+		return -1;
+
+	/* First pass to count resource use */
+	memset(busbyte, 0, sizeof(busbyte));
+	memset(unituse, 0, sizeof(unituse));
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc) {
+			if (pmc > 6)
+				return -1;
+			if (pmc_inuse & (1 << (pmc - 1)))
+				return -1;
+			pmc_inuse |= 1 << (pmc - 1);
+		}
+		if (event[i] & PM_BUSEVENT_MSK) {
+			unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+			byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+			if (unit > PM_LASTUNIT)
+				return -1;
+			if (unit == PM_ISU0_ALT)
+				unit = PM_ISU0;
+			if (byte >= 4) {
+				if (unit != PM_LSU1)
+					return -1;
+				++unit;
+				byte &= 3;
+			}
+			if (busbyte[byte] && busbyte[byte] != unit)
+				return -1;
+			busbyte[byte] = unit;
+			unituse[unit] = 1;
+		}
+	}
+
+	/*
+	 * Assign resources and set multiplexer selects.
+	 *
+	 * PM_ISU0 can go either on TTM0 or TTM1, but that's the only
+	 * choice we have to deal with.
+	 */
+	if (unituse[PM_ISU0] &
+	    (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_ISU1])) {
+		unituse[PM_ISU0_ALT] = 1;	/* move ISU to TTM1 */
+		unituse[PM_ISU0] = 0;
+	}
+	/* Set TTM[01]SEL fields. */
+	ttmuse = 0;
+	for (i = PM_FPU; i <= PM_ISU1; ++i) {
+		if (!unituse[i])
+			continue;
+		if (ttmuse++)
+			return -1;
+		mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH;
+	}
+	ttmuse = 0;
+	for (; i <= PM_GRS; ++i) {
+		if (!unituse[i])
+			continue;
+		if (ttmuse++)
+			return -1;
+		mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH;
+	}
+	if (ttmuse > 1)
+		return -1;
+
+	/* Set byte lane select fields, TTM[23]SEL and GRS_*SEL. */
+	for (byte = 0; byte < 4; ++byte) {
+		unit = busbyte[byte];
+		if (!unit)
+			continue;
+		if (unit == PM_ISU0 && unituse[PM_ISU0_ALT]) {
+			/* get ISU0 through TTM1 rather than TTM0 */
+			unit = PM_ISU0_ALT;
+		} else if (unit == PM_LSU1 + 1) {
+			/* select lower word of LSU1 for this byte */
+			mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte);
+		}
+		ttm = unit >> 2;
+		mmcr1 |= (unsigned long)ttm
+			<< (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
+	}
+
+	/* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+		byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+		psel = event[i] & PM_PMCSEL_MSK;
+		isbus = event[i] & PM_BUSEVENT_MSK;
+		if (!pmc) {
+			/* Bus event or any-PMC direct event */
+			for (pmc = 0; pmc < 4; ++pmc) {
+				if (!(pmc_inuse & (1 << pmc)))
+					break;
+			}
+			if (pmc >= 4)
+				return -1;
+			pmc_inuse |= 1 << pmc;
+		} else if (pmc <= 4) {
+			/* Direct event */
+			--pmc;
+			if (isbus && (byte & 2) &&
+			    (psel == 8 || psel == 0x10 || psel == 0x28))
+				/* add events on higher-numbered bus */
+				mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
+		} else {
+			/* Instructions or run cycles on PMC5/6 */
+			--pmc;
+		}
+		if (isbus && unit == PM_GRS) {
+			bit = psel & 7;
+			grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK;
+			mmcr1 |= (unsigned long)grsel << grsel_shift[bit];
+		}
+		if (power5p_marked_instr_event(event[i]))
+			mmcra |= MMCRA_SAMPLE_ENABLE;
+		if ((psel & 0x58) == 0x40 && (byte & 1) != ((pmc >> 1) & 1))
+			/* select alternate byte lane */
+			psel |= 0x10;
+		if (pmc <= 3)
+			mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc);
+		hwc[i] = pmc;
+	}
+
+	/* Return MMCRx values */
+	mmcr[0] = 0;
+	if (pmc_inuse & 1)
+		mmcr[0] = MMCR0_PMC1CE;
+	if (pmc_inuse & 0x3e)
+		mmcr[0] |= MMCR0_PMCjCE;
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcra;
+	return 0;
+}
+
+static void power5p_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	if (pmc <= 3)
+		mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc));
+}
+
+static int power5p_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= 0xf,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= 0x100009,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= 0x1c10a8, /* LD_REF_L1 */
+	[PERF_COUNT_HW_CACHE_MISSES]		= 0x3c1088, /* LD_MISS_L1 */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x230e4,  /* BR_ISSUED */
+	[PERF_COUNT_HW_BRANCH_MISSES]		= 0x230e5,  /* BR_MPRED_CR */
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x1c10a8,	0x3c1088	},
+		[C(OP_WRITE)] = {	0x2c10a8,	0xc10c3		},
+		[C(OP_PREFETCH)] = {	0xc70e7,	-1		},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	0,		0		},
+	},
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0		},
+		[C(OP_WRITE)] = {	0,		0		},
+		[C(OP_PREFETCH)] = {	0xc50c3,	0		},
+	},
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0xc20e4,	0x800c4		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+	[C(ITLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x800c0		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x230e4,	0x230e5		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+};
+
+static struct power_pmu power5p_pmu = {
+	.name			= "POWER5+/++",
+	.n_counter		= 6,
+	.max_alternatives	= MAX_ALT,
+	.add_fields		= 0x7000000000055ul,
+	.test_adder		= 0x3000040000000ul,
+	.compute_mmcr		= power5p_compute_mmcr,
+	.get_constraint		= power5p_get_constraint,
+	.get_alternatives	= power5p_get_alternatives,
+	.disable_pmc		= power5p_disable_pmc,
+	.limited_pmc_event	= power5p_limited_pmc_event,
+	.flags			= PPMU_LIMITED_PMC5_6,
+	.n_generic		= ARRAY_SIZE(power5p_generic_events),
+	.generic_events		= power5p_generic_events,
+	.cache_events		= &power5p_cache_events,
+};
+
+static int init_power5p_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+")
+	     && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5++")))
+		return -ENODEV;
+
+	return register_power_pmu(&power5p_pmu);
+}
+
+arch_initcall(init_power5p_pmu);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/power6-pmu.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/power6-pmu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/power6-pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/power6-pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,547 @@
+/*
+ * Performance counter support for POWER6 processors.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/kernel.h>
+#include <linux/perf_counter.h>
+#include <linux/string.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Bits in event code for POWER6
+ */
+#define PM_PMC_SH	20	/* PMC number (1-based) for direct events */
+#define PM_PMC_MSK	0x7
+#define PM_PMC_MSKS	(PM_PMC_MSK << PM_PMC_SH)
+#define PM_UNIT_SH	16	/* Unit event comes (TTMxSEL encoding) */
+#define PM_UNIT_MSK	0xf
+#define PM_UNIT_MSKS	(PM_UNIT_MSK << PM_UNIT_SH)
+#define PM_LLAV		0x8000	/* Load lookahead match value */
+#define PM_LLA		0x4000	/* Load lookahead match enable */
+#define PM_BYTE_SH	12	/* Byte of event bus to use */
+#define PM_BYTE_MSK	3
+#define PM_SUBUNIT_SH	8	/* Subunit event comes from (NEST_SEL enc.) */
+#define PM_SUBUNIT_MSK	7
+#define PM_SUBUNIT_MSKS	(PM_SUBUNIT_MSK << PM_SUBUNIT_SH)
+#define PM_PMCSEL_MSK	0xff	/* PMCxSEL value */
+#define PM_BUSEVENT_MSK	0xf3700
+
+/*
+ * Bits in MMCR1 for POWER6
+ */
+#define MMCR1_TTM0SEL_SH	60
+#define MMCR1_TTMSEL_SH(n)	(MMCR1_TTM0SEL_SH - (n) * 4)
+#define MMCR1_TTMSEL_MSK	0xf
+#define MMCR1_TTMSEL(m, n)	(((m) >> MMCR1_TTMSEL_SH(n)) & MMCR1_TTMSEL_MSK)
+#define MMCR1_NESTSEL_SH	45
+#define MMCR1_NESTSEL_MSK	0x7
+#define MMCR1_NESTSEL(m)	(((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK)
+#define MMCR1_PMC1_LLA		(1ul << 44)
+#define MMCR1_PMC1_LLA_VALUE	(1ul << 39)
+#define MMCR1_PMC1_ADDR_SEL	(1ul << 35)
+#define MMCR1_PMC1SEL_SH	24
+#define MMCR1_PMCSEL_SH(n)	(MMCR1_PMC1SEL_SH - (n) * 8)
+#define MMCR1_PMCSEL_MSK	0xff
+
+/*
+ * Map of which direct events on which PMCs are marked instruction events.
+ * Indexed by PMCSEL value >> 1.
+ * Bottom 4 bits are a map of which PMCs are interesting,
+ * top 4 bits say what sort of event:
+ *   0 = direct marked event,
+ *   1 = byte decode event,
+ *   4 = add/and event (PMC1 -> bits 0 & 4),
+ *   5 = add/and event (PMC1 -> bits 1 & 5),
+ *   6 = add/and event (PMC1 -> bits 2 & 6),
+ *   7 = add/and event (PMC1 -> bits 3 & 7).
+ */
+static unsigned char direct_event_is_marked[0x60 >> 1] = {
+	0,	/* 00 */
+	0,	/* 02 */
+	0,	/* 04 */
+	0x07,	/* 06 PM_MRK_ST_CMPL, PM_MRK_ST_GPS, PM_MRK_ST_CMPL_INT */
+	0x04,	/* 08 PM_MRK_DFU_FIN */
+	0x06,	/* 0a PM_MRK_IFU_FIN, PM_MRK_INST_FIN */
+	0,	/* 0c */
+	0,	/* 0e */
+	0x02,	/* 10 PM_MRK_INST_DISP */
+	0x08,	/* 12 PM_MRK_LSU_DERAT_MISS */
+	0,	/* 14 */
+	0,	/* 16 */
+	0x0c,	/* 18 PM_THRESH_TIMEO, PM_MRK_INST_FIN */
+	0x0f,	/* 1a PM_MRK_INST_DISP, PM_MRK_{FXU,FPU,LSU}_FIN */
+	0x01,	/* 1c PM_MRK_INST_ISSUED */
+	0,	/* 1e */
+	0,	/* 20 */
+	0,	/* 22 */
+	0,	/* 24 */
+	0,	/* 26 */
+	0x15,	/* 28 PM_MRK_DATA_FROM_L2MISS, PM_MRK_DATA_FROM_L3MISS */
+	0,	/* 2a */
+	0,	/* 2c */
+	0,	/* 2e */
+	0x4f,	/* 30 */
+	0x7f,	/* 32 */
+	0x4f,	/* 34 */
+	0x5f,	/* 36 */
+	0x6f,	/* 38 */
+	0x4f,	/* 3a */
+	0,	/* 3c */
+	0x08,	/* 3e PM_MRK_INST_TIMEO */
+	0x1f,	/* 40 */
+	0x1f,	/* 42 */
+	0x1f,	/* 44 */
+	0x1f,	/* 46 */
+	0x1f,	/* 48 */
+	0x1f,	/* 4a */
+	0x1f,	/* 4c */
+	0x1f,	/* 4e */
+	0,	/* 50 */
+	0x05,	/* 52 PM_MRK_BR_TAKEN, PM_MRK_BR_MPRED */
+	0x1c,	/* 54 PM_MRK_PTEG_FROM_L3MISS, PM_MRK_PTEG_FROM_L2MISS */
+	0x02,	/* 56 PM_MRK_LD_MISS_L1 */
+	0,	/* 58 */
+	0,	/* 5a */
+	0,	/* 5c */
+	0,	/* 5e */
+};
+
+/*
+ * Masks showing for each unit which bits are marked events.
+ * These masks are in LE order, i.e. 0x00000001 is byte 0, bit 0.
+ */
+static u32 marked_bus_events[16] = {
+	0x01000000,	/* direct events set 1: byte 3 bit 0 */
+	0x00010000,	/* direct events set 2: byte 2 bit 0 */
+	0, 0, 0, 0,	/* IDU, IFU, nest: nothing */
+	0x00000088,	/* VMX set 1: byte 0 bits 3, 7 */
+	0x000000c0,	/* VMX set 2: byte 0 bits 4-7 */
+	0x04010000,	/* LSU set 1: byte 2 bit 0, byte 3 bit 2 */
+	0xff010000u,	/* LSU set 2: byte 2 bit 0, all of byte 3 */
+	0,		/* LSU set 3 */
+	0x00000010,	/* VMX set 3: byte 0 bit 4 */
+	0,		/* BFP set 1 */
+	0x00000022,	/* BFP set 2: byte 0 bits 1, 5 */
+	0, 0
+};
+	
+/*
+ * Returns 1 if event counts things relating to marked instructions
+ * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
+ */
+static int power6_marked_instr_event(u64 event)
+{
+	int pmc, psel, ptype;
+	int bit, byte, unit;
+	u32 mask;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	psel = (event & PM_PMCSEL_MSK) >> 1;	/* drop edge/level bit */
+	if (pmc >= 5)
+		return 0;
+
+	bit = -1;
+	if (psel < sizeof(direct_event_is_marked)) {
+		ptype = direct_event_is_marked[psel];
+		if (pmc == 0 || !(ptype & (1 << (pmc - 1))))
+			return 0;
+		ptype >>= 4;
+		if (ptype == 0)
+			return 1;
+		if (ptype == 1)
+			bit = 0;
+		else
+			bit = ptype ^ (pmc - 1);
+	} else if ((psel & 0x48) == 0x40)
+		bit = psel & 7;
+
+	if (!(event & PM_BUSEVENT_MSK) || bit == -1)
+		return 0;
+
+	byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	mask = marked_bus_events[unit];
+	return (mask >> (byte * 8 + bit)) & 1;
+}
+
+/*
+ * Assign PMC numbers and compute MMCR1 value for a set of events
+ */
+static int p6_compute_mmcr(u64 event[], int n_ev,
+			   unsigned int hwc[], unsigned long mmcr[])
+{
+	unsigned long mmcr1 = 0;
+	unsigned long mmcra = 0;
+	int i;
+	unsigned int pmc, ev, b, u, s, psel;
+	unsigned int ttmset = 0;
+	unsigned int pmc_inuse = 0;
+
+	if (n_ev > 6)
+		return -1;
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc) {
+			if (pmc_inuse & (1 << (pmc - 1)))
+				return -1;	/* collision! */
+			pmc_inuse |= 1 << (pmc - 1);
+		}
+	}
+	for (i = 0; i < n_ev; ++i) {
+		ev = event[i];
+		pmc = (ev >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc) {
+			--pmc;
+		} else {
+			/* can go on any PMC; find a free one */
+			for (pmc = 0; pmc < 4; ++pmc)
+				if (!(pmc_inuse & (1 << pmc)))
+					break;
+			if (pmc >= 4)
+				return -1;
+			pmc_inuse |= 1 << pmc;
+		}
+		hwc[i] = pmc;
+		psel = ev & PM_PMCSEL_MSK;
+		if (ev & PM_BUSEVENT_MSK) {
+			/* this event uses the event bus */
+			b = (ev >> PM_BYTE_SH) & PM_BYTE_MSK;
+			u = (ev >> PM_UNIT_SH) & PM_UNIT_MSK;
+			/* check for conflict on this byte of event bus */
+			if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u)
+				return -1;
+			mmcr1 |= (unsigned long)u << MMCR1_TTMSEL_SH(b);
+			ttmset |= 1 << b;
+			if (u == 5) {
+				/* Nest events have a further mux */
+				s = (ev >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK;
+				if ((ttmset & 0x10) &&
+				    MMCR1_NESTSEL(mmcr1) != s)
+					return -1;
+				ttmset |= 0x10;
+				mmcr1 |= (unsigned long)s << MMCR1_NESTSEL_SH;
+			}
+			if (0x30 <= psel && psel <= 0x3d) {
+				/* these need the PMCx_ADDR_SEL bits */
+				if (b >= 2)
+					mmcr1 |= MMCR1_PMC1_ADDR_SEL >> pmc;
+			}
+			/* bus select values are different for PMC3/4 */
+			if (pmc >= 2 && (psel & 0x90) == 0x80)
+				psel ^= 0x20;
+		}
+		if (ev & PM_LLA) {
+			mmcr1 |= MMCR1_PMC1_LLA >> pmc;
+			if (ev & PM_LLAV)
+				mmcr1 |= MMCR1_PMC1_LLA_VALUE >> pmc;
+		}
+		if (power6_marked_instr_event(event[i]))
+			mmcra |= MMCRA_SAMPLE_ENABLE;
+		if (pmc < 4)
+			mmcr1 |= (unsigned long)psel << MMCR1_PMCSEL_SH(pmc);
+	}
+	mmcr[0] = 0;
+	if (pmc_inuse & 1)
+		mmcr[0] = MMCR0_PMC1CE;
+	if (pmc_inuse & 0xe)
+		mmcr[0] |= MMCR0_PMCjCE;
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcra;
+	return 0;
+}
+
+/*
+ * Layout of constraint bits:
+ *
+ *	0-1	add field: number of uses of PMC1 (max 1)
+ *	2-3, 4-5, 6-7, 8-9, 10-11: ditto for PMC2, 3, 4, 5, 6
+ *	12-15	add field: number of uses of PMC1-4 (max 4)
+ *	16-19	select field: unit on byte 0 of event bus
+ *	20-23, 24-27, 28-31 ditto for bytes 1, 2, 3
+ *	32-34	select field: nest (subunit) event selector
+ */
+static int p6_get_constraint(u64 event, unsigned long *maskp,
+			     unsigned long *valp)
+{
+	int pmc, byte, sh, subunit;
+	unsigned long mask = 0, value = 0;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc) {
+		if (pmc > 4 && !(event == 0x500009 || event == 0x600005))
+			return -1;
+		sh = (pmc - 1) * 2;
+		mask |= 2 << sh;
+		value |= 1 << sh;
+	}
+	if (event & PM_BUSEVENT_MSK) {
+		byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+		sh = byte * 4 + (16 - PM_UNIT_SH);
+		mask |= PM_UNIT_MSKS << sh;
+		value |= (unsigned long)(event & PM_UNIT_MSKS) << sh;
+		if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) {
+			subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK;
+			mask  |= (unsigned long)PM_SUBUNIT_MSK << 32;
+			value |= (unsigned long)subunit << 32;
+		}
+	}
+	if (pmc <= 4) {
+		mask  |= 0x8000;	/* add field for count of PMC1-4 uses */
+		value |= 0x1000;
+	}
+	*maskp = mask;
+	*valp = value;
+	return 0;
+}
+
+static int p6_limited_pmc_event(u64 event)
+{
+	int pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+
+	return pmc == 5 || pmc == 6;
+}
+
+#define MAX_ALT	4	/* at most 4 alternatives for any event */
+
+static const unsigned int event_alternatives[][MAX_ALT] = {
+	{ 0x0130e8, 0x2000f6, 0x3000fc },	/* PM_PTEG_RELOAD_VALID */
+	{ 0x080080, 0x10000d, 0x30000c, 0x4000f0 }, /* PM_LD_MISS_L1 */
+	{ 0x080088, 0x200054, 0x3000f0 },	/* PM_ST_MISS_L1 */
+	{ 0x10000a, 0x2000f4, 0x600005 },	/* PM_RUN_CYC */
+	{ 0x10000b, 0x2000f5 },			/* PM_RUN_COUNT */
+	{ 0x10000e, 0x400010 },			/* PM_PURR */
+	{ 0x100010, 0x4000f8 },			/* PM_FLUSH */
+	{ 0x10001a, 0x200010 },			/* PM_MRK_INST_DISP */
+	{ 0x100026, 0x3000f8 },			/* PM_TB_BIT_TRANS */
+	{ 0x100054, 0x2000f0 },			/* PM_ST_FIN */
+	{ 0x100056, 0x2000fc },			/* PM_L1_ICACHE_MISS */
+	{ 0x1000f0, 0x40000a },			/* PM_INST_IMC_MATCH_CMPL */
+	{ 0x1000f8, 0x200008 },			/* PM_GCT_EMPTY_CYC */
+	{ 0x1000fc, 0x400006 },			/* PM_LSU_DERAT_MISS_CYC */
+	{ 0x20000e, 0x400007 },			/* PM_LSU_DERAT_MISS */
+	{ 0x200012, 0x300012 },			/* PM_INST_DISP */
+	{ 0x2000f2, 0x3000f2 },			/* PM_INST_DISP */
+	{ 0x2000f8, 0x300010 },			/* PM_EXT_INT */
+	{ 0x2000fe, 0x300056 },			/* PM_DATA_FROM_L2MISS */
+	{ 0x2d0030, 0x30001a },			/* PM_MRK_FPU_FIN */
+	{ 0x30000a, 0x400018 },			/* PM_MRK_INST_FIN */
+	{ 0x3000f6, 0x40000e },			/* PM_L1_DCACHE_RELOAD_VALID */
+	{ 0x3000fe, 0x400056 },			/* PM_DATA_FROM_L3MISS */
+};
+
+/*
+ * This could be made more efficient with a binary search on
+ * a presorted list, if necessary
+ */
+static int find_alternatives_list(u64 event)
+{
+	int i, j;
+	unsigned int alt;
+
+	for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
+		if (event < event_alternatives[i][0])
+			return -1;
+		for (j = 0; j < MAX_ALT; ++j) {
+			alt = event_alternatives[i][j];
+			if (!alt || event < alt)
+				break;
+			if (event == alt)
+				return i;
+		}
+	}
+	return -1;
+}
+
+static int p6_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	int i, j, nlim;
+	unsigned int psel, pmc;
+	unsigned int nalt = 1;
+	u64 aevent;
+
+	alt[0] = event;
+	nlim = p6_limited_pmc_event(event);
+
+	/* check the alternatives table */
+	i = find_alternatives_list(event);
+	if (i >= 0) {
+		/* copy out alternatives from list */
+		for (j = 0; j < MAX_ALT; ++j) {
+			aevent = event_alternatives[i][j];
+			if (!aevent)
+				break;
+			if (aevent != event)
+				alt[nalt++] = aevent;
+			nlim += p6_limited_pmc_event(aevent);
+		}
+
+	} else {
+		/* Check for alternative ways of computing sum events */
+		/* PMCSEL 0x32 counter N == PMCSEL 0x34 counter 5-N */
+		psel = event & (PM_PMCSEL_MSK & ~1);	/* ignore edge bit */
+		pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc && (psel == 0x32 || psel == 0x34))
+			alt[nalt++] = ((event ^ 0x6) & ~PM_PMC_MSKS) |
+				((5 - pmc) << PM_PMC_SH);
+
+		/* PMCSEL 0x38 counter N == PMCSEL 0x3a counter N+/-2 */
+		if (pmc && (psel == 0x38 || psel == 0x3a))
+			alt[nalt++] = ((event ^ 0x2) & ~PM_PMC_MSKS) |
+				((pmc > 2? pmc - 2: pmc + 2) << PM_PMC_SH);
+	}
+
+	if (flags & PPMU_ONLY_COUNT_RUN) {
+		/*
+		 * We're only counting in RUN state,
+		 * so PM_CYC is equivalent to PM_RUN_CYC,
+		 * PM_INST_CMPL === PM_RUN_INST_CMPL, PM_PURR === PM_RUN_PURR.
+		 * This doesn't include alternatives that don't provide
+		 * any extra flexibility in assigning PMCs (e.g.
+		 * 0x10000a for PM_RUN_CYC vs. 0x1e for PM_CYC).
+		 * Note that even with these additional alternatives
+		 * we never end up with more than 4 alternatives for any event.
+		 */
+		j = nalt;
+		for (i = 0; i < nalt; ++i) {
+			switch (alt[i]) {
+			case 0x1e:	/* PM_CYC */
+				alt[j++] = 0x600005;	/* PM_RUN_CYC */
+				++nlim;
+				break;
+			case 0x10000a:	/* PM_RUN_CYC */
+				alt[j++] = 0x1e;	/* PM_CYC */
+				break;
+			case 2:		/* PM_INST_CMPL */
+				alt[j++] = 0x500009;	/* PM_RUN_INST_CMPL */
+				++nlim;
+				break;
+			case 0x500009:	/* PM_RUN_INST_CMPL */
+				alt[j++] = 2;		/* PM_INST_CMPL */
+				break;
+			case 0x10000e:	/* PM_PURR */
+				alt[j++] = 0x4000f4;	/* PM_RUN_PURR */
+				break;
+			case 0x4000f4:	/* PM_RUN_PURR */
+				alt[j++] = 0x10000e;	/* PM_PURR */
+				break;
+			}
+		}
+		nalt = j;
+	}
+
+	if (!(flags & PPMU_LIMITED_PMC_OK) && nlim) {
+		/* remove the limited PMC events */
+		j = 0;
+		for (i = 0; i < nalt; ++i) {
+			if (!p6_limited_pmc_event(alt[i])) {
+				alt[j] = alt[i];
+				++j;
+			}
+		}
+		nalt = j;
+	} else if ((flags & PPMU_LIMITED_PMC_REQD) && nlim < nalt) {
+		/* remove all but the limited PMC events */
+		j = 0;
+		for (i = 0; i < nalt; ++i) {
+			if (p6_limited_pmc_event(alt[i])) {
+				alt[j] = alt[i];
+				++j;
+			}
+		}
+		nalt = j;
+	}
+
+	return nalt;
+}
+
+static void p6_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	/* Set PMCxSEL to 0 to disable PMCx */
+	if (pmc <= 3)
+		mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc));
+}
+
+static int power6_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= 0x1e,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= 2,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= 0x280030, /* LD_REF_L1 */
+	[PERF_COUNT_HW_CACHE_MISSES]		= 0x30000c, /* LD_MISS_L1 */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x410a0,  /* BR_PRED */
+	[PERF_COUNT_HW_BRANCH_MISSES]		= 0x400052, /* BR_MPRED */
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ * The "DTLB" and "ITLB" events relate to the DERAT and IERAT.
+ */
+static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x80082,	0x80080		},
+		[C(OP_WRITE)] = {	0x80086,	0x80088		},
+		[C(OP_PREFETCH)] = {	0x810a4,	0		},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x100056 	},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	0x4008c,	0		},
+	},
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x150730,	0x250532	},
+		[C(OP_WRITE)] = {	0x250432,	0x150432	},
+		[C(OP_PREFETCH)] = {	0x810a6,	0		},
+	},
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x20000e	},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+	[C(ITLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x420ce		},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x430e6,	0x400052	},
+		[C(OP_WRITE)] = {	-1,		-1		},
+		[C(OP_PREFETCH)] = {	-1,		-1		},
+	},
+};
+
+static struct power_pmu power6_pmu = {
+	.name			= "POWER6",
+	.n_counter		= 6,
+	.max_alternatives	= MAX_ALT,
+	.add_fields		= 0x1555,
+	.test_adder		= 0x3000,
+	.compute_mmcr		= p6_compute_mmcr,
+	.get_constraint		= p6_get_constraint,
+	.get_alternatives	= p6_get_alternatives,
+	.disable_pmc		= p6_disable_pmc,
+	.limited_pmc_event	= p6_limited_pmc_event,
+	.flags			= PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR,
+	.n_generic		= ARRAY_SIZE(power6_generic_events),
+	.generic_events		= power6_generic_events,
+	.cache_events		= &power6_cache_events,
+};
+
+static int init_power6_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6"))
+		return -ENODEV;
+
+	return register_power_pmu(&power6_pmu);
+}
+
+arch_initcall(init_power6_pmu);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/power7-pmu.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/power7-pmu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/power7-pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/power7-pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,376 @@
+/*
+ * Performance counter support for POWER7 processors.
+ *
+ * Copyright 2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/kernel.h>
+#include <linux/perf_counter.h>
+#include <linux/string.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Bits in event code for POWER7
+ */
+#define PM_PMC_SH	16	/* PMC number (1-based) for direct events */
+#define PM_PMC_MSK	0xf
+#define PM_PMC_MSKS	(PM_PMC_MSK << PM_PMC_SH)
+#define PM_UNIT_SH	12	/* TTMMUX number and setting - unit select */
+#define PM_UNIT_MSK	0xf
+#define PM_COMBINE_SH	11	/* Combined event bit */
+#define PM_COMBINE_MSK	1
+#define PM_COMBINE_MSKS	0x800
+#define PM_L2SEL_SH	8	/* L2 event select */
+#define PM_L2SEL_MSK	7
+#define PM_PMCSEL_MSK	0xff
+
+/*
+ * Bits in MMCR1 for POWER7
+ */
+#define MMCR1_TTM0SEL_SH	60
+#define MMCR1_TTM1SEL_SH	56
+#define MMCR1_TTM2SEL_SH	52
+#define MMCR1_TTM3SEL_SH	48
+#define MMCR1_TTMSEL_MSK	0xf
+#define MMCR1_L2SEL_SH		45
+#define MMCR1_L2SEL_MSK		7
+#define MMCR1_PMC1_COMBINE_SH	35
+#define MMCR1_PMC2_COMBINE_SH	34
+#define MMCR1_PMC3_COMBINE_SH	33
+#define MMCR1_PMC4_COMBINE_SH	32
+#define MMCR1_PMC1SEL_SH	24
+#define MMCR1_PMC2SEL_SH	16
+#define MMCR1_PMC3SEL_SH	8
+#define MMCR1_PMC4SEL_SH	0
+#define MMCR1_PMCSEL_SH(n)	(MMCR1_PMC1SEL_SH - (n) * 8)
+#define MMCR1_PMCSEL_MSK	0xff
+
+/*
+ * Bits in MMCRA
+ */
+
+/*
+ * Layout of constraint bits:
+ * 6666555555555544444444443333333333222222222211111111110000000000
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ *                                                 [  ><><><><><><>
+ *                                                  NC P6P5P4P3P2P1
+ *
+ * NC - number of counters
+ *     15: NC error 0x8000
+ *     12-14: number of events needing PMC1-4 0x7000
+ *
+ * P6
+ *     11: P6 error 0x800
+ *     10-11: Count of events needing PMC6
+ *
+ * P1..P5
+ *     0-9: Count of events needing PMC1..PMC5
+ */
+
+static int power7_get_constraint(u64 event, unsigned long *maskp,
+				 unsigned long *valp)
+{
+	int pmc, sh;
+	unsigned long mask = 0, value = 0;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc) {
+		if (pmc > 6)
+			return -1;
+		sh = (pmc - 1) * 2;
+		mask |= 2 << sh;
+		value |= 1 << sh;
+		if (pmc >= 5 && !(event == 0x500fa || event == 0x600f4))
+			return -1;
+	}
+	if (pmc < 5) {
+		/* need a counter from PMC1-4 set */
+		mask  |= 0x8000;
+		value |= 0x1000;
+	}
+	*maskp = mask;
+	*valp = value;
+	return 0;
+}
+
+#define MAX_ALT	2	/* at most 2 alternatives for any event */
+
+static const unsigned int event_alternatives[][MAX_ALT] = {
+	{ 0x200f2, 0x300f2 },		/* PM_INST_DISP */
+	{ 0x200f4, 0x600f4 },		/* PM_RUN_CYC */
+	{ 0x400fa, 0x500fa },		/* PM_RUN_INST_CMPL */
+};
+
+/*
+ * Scan the alternatives table for a match and return the
+ * index into the alternatives table if found, else -1.
+ */
+static int find_alternative(u64 event)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
+		if (event < event_alternatives[i][0])
+			break;
+		for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
+			if (event == event_alternatives[i][j])
+				return i;
+	}
+	return -1;
+}
+
+static s64 find_alternative_decode(u64 event)
+{
+	int pmc, psel;
+
+	/* this only handles the 4x decode events */
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	psel = event & PM_PMCSEL_MSK;
+	if ((pmc == 2 || pmc == 4) && (psel & ~7) == 0x40)
+		return event - (1 << PM_PMC_SH) + 8;
+	if ((pmc == 1 || pmc == 3) && (psel & ~7) == 0x48)
+		return event + (1 << PM_PMC_SH) - 8;
+	return -1;
+}
+
+static int power7_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	int i, j, nalt = 1;
+	s64 ae;
+
+	alt[0] = event;
+	nalt = 1;
+	i = find_alternative(event);
+	if (i >= 0) {
+		for (j = 0; j < MAX_ALT; ++j) {
+			ae = event_alternatives[i][j];
+			if (ae && ae != event)
+				alt[nalt++] = ae;
+		}
+	} else {
+		ae = find_alternative_decode(event);
+		if (ae > 0)
+			alt[nalt++] = ae;
+	}
+
+	if (flags & PPMU_ONLY_COUNT_RUN) {
+		/*
+		 * We're only counting in RUN state,
+		 * so PM_CYC is equivalent to PM_RUN_CYC
+		 * and PM_INST_CMPL === PM_RUN_INST_CMPL.
+		 * This doesn't include alternatives that don't provide
+		 * any extra flexibility in assigning PMCs.
+		 */
+		j = nalt;
+		for (i = 0; i < nalt; ++i) {
+			switch (alt[i]) {
+			case 0x1e:	/* PM_CYC */
+				alt[j++] = 0x600f4;	/* PM_RUN_CYC */
+				break;
+			case 0x600f4:	/* PM_RUN_CYC */
+				alt[j++] = 0x1e;
+				break;
+			case 0x2:	/* PM_PPC_CMPL */
+				alt[j++] = 0x500fa;	/* PM_RUN_INST_CMPL */
+				break;
+			case 0x500fa:	/* PM_RUN_INST_CMPL */
+				alt[j++] = 0x2;	/* PM_PPC_CMPL */
+				break;
+			}
+		}
+		nalt = j;
+	}
+
+	return nalt;
+}
+
+/*
+ * Returns 1 if event counts things relating to marked instructions
+ * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
+ */
+static int power7_marked_instr_event(u64 event)
+{
+	int pmc, psel;
+	int unit;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	psel = event & PM_PMCSEL_MSK & ~1;	/* trim off edge/level bit */
+	if (pmc >= 5)
+		return 0;
+
+	switch (psel >> 4) {
+	case 2:
+		return pmc == 2 || pmc == 4;
+	case 3:
+		if (psel == 0x3c)
+			return pmc == 1;
+		if (psel == 0x3e)
+			return pmc != 2;
+		return 1;
+	case 4:
+	case 5:
+		return unit == 0xd;
+	case 6:
+		if (psel == 0x64)
+			return pmc >= 3;
+	case 8:
+		return unit == 0xd;
+	}
+	return 0;
+}
+
+static int power7_compute_mmcr(u64 event[], int n_ev,
+			       unsigned int hwc[], unsigned long mmcr[])
+{
+	unsigned long mmcr1 = 0;
+	unsigned long mmcra = 0;
+	unsigned int pmc, unit, combine, l2sel, psel;
+	unsigned int pmc_inuse = 0;
+	int i;
+
+	/* First pass to count resource use */
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc) {
+			if (pmc > 6)
+				return -1;
+			if (pmc_inuse & (1 << (pmc - 1)))
+				return -1;
+			pmc_inuse |= 1 << (pmc - 1);
+		}
+	}
+
+	/* Second pass: assign PMCs, set all MMCR1 fields */
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+		combine = (event[i] >> PM_COMBINE_SH) & PM_COMBINE_MSK;
+		l2sel = (event[i] >> PM_L2SEL_SH) & PM_L2SEL_MSK;
+		psel = event[i] & PM_PMCSEL_MSK;
+		if (!pmc) {
+			/* Bus event or any-PMC direct event */
+			for (pmc = 0; pmc < 4; ++pmc) {
+				if (!(pmc_inuse & (1 << pmc)))
+					break;
+			}
+			if (pmc >= 4)
+				return -1;
+			pmc_inuse |= 1 << pmc;
+		} else {
+			/* Direct or decoded event */
+			--pmc;
+		}
+		if (pmc <= 3) {
+			mmcr1 |= (unsigned long) unit
+				<< (MMCR1_TTM0SEL_SH - 4 * pmc);
+			mmcr1 |= (unsigned long) combine
+				<< (MMCR1_PMC1_COMBINE_SH - pmc);
+			mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc);
+			if (unit == 6)	/* L2 events */
+				mmcr1 |= (unsigned long) l2sel
+					<< MMCR1_L2SEL_SH;
+		}
+		if (power7_marked_instr_event(event[i]))
+			mmcra |= MMCRA_SAMPLE_ENABLE;
+		hwc[i] = pmc;
+	}
+
+	/* Return MMCRx values */
+	mmcr[0] = 0;
+	if (pmc_inuse & 1)
+		mmcr[0] = MMCR0_PMC1CE;
+	if (pmc_inuse & 0x3e)
+		mmcr[0] |= MMCR0_PMCjCE;
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcra;
+	return 0;
+}
+
+static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	if (pmc <= 3)
+		mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc));
+}
+
+static int power7_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
+	[PERF_COUNT_HW_INSTRUCTIONS] = 2,
+	[PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880,	/* LD_REF_L1_LSU*/
+	[PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,		/* LD_MISS_L1	*/
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x10068,	/* BRU_FIN	*/
+	[PERF_COUNT_HW_BRANCH_MISSES] = 0x400f6,	/* BR_MPRED	*/
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0xc880,		0x400f0	},
+		[C(OP_WRITE)] = {	0,		0x300f0	},
+		[C(OP_PREFETCH)] = {	0xd8b8,		0	},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x200fc	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	0x408a,		0	},
+	},
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x16080,	0x26080	},
+		[C(OP_WRITE)] = {	0x16082,	0x26082	},
+		[C(OP_PREFETCH)] = {	0,		0	},
+	},
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x300fc	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(ITLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x400fc	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x10068,	0x400f6	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+};
+
+static struct power_pmu power7_pmu = {
+	.name			= "POWER7",
+	.n_counter		= 6,
+	.max_alternatives	= MAX_ALT + 1,
+	.add_fields		= 0x1555ul,
+	.test_adder		= 0x3000ul,
+	.compute_mmcr		= power7_compute_mmcr,
+	.get_constraint		= power7_get_constraint,
+	.get_alternatives	= power7_get_alternatives,
+	.disable_pmc		= power7_disable_pmc,
+	.flags			= PPMU_ALT_SIPR,
+	.n_generic		= ARRAY_SIZE(power7_generic_events),
+	.generic_events		= power7_generic_events,
+	.cache_events		= &power7_cache_events,
+};
+
+static int init_power7_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7"))
+		return -ENODEV;
+
+	return register_power_pmu(&power7_pmu);
+}
+
+arch_initcall(init_power7_pmu);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/ppc970-pmu.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/ppc970-pmu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/ppc970-pmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/ppc970-pmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,499 @@
+/*
+ * Performance counter support for PPC970-family processors.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM 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.
+ */
+#include <linux/string.h>
+#include <linux/perf_counter.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Bits in event code for PPC970
+ */
+#define PM_PMC_SH	12	/* PMC number (1-based) for direct events */
+#define PM_PMC_MSK	0xf
+#define PM_UNIT_SH	8	/* TTMMUX number and setting - unit select */
+#define PM_UNIT_MSK	0xf
+#define PM_SPCSEL_SH	6
+#define PM_SPCSEL_MSK	3
+#define PM_BYTE_SH	4	/* Byte number of event bus to use */
+#define PM_BYTE_MSK	3
+#define PM_PMCSEL_MSK	0xf
+
+/* Values in PM_UNIT field */
+#define PM_NONE		0
+#define PM_FPU		1
+#define PM_VPU		2
+#define PM_ISU		3
+#define PM_IFU		4
+#define PM_IDU		5
+#define PM_STS		6
+#define PM_LSU0		7
+#define PM_LSU1U	8
+#define PM_LSU1L	9
+#define PM_LASTUNIT	9
+
+/*
+ * Bits in MMCR0 for PPC970
+ */
+#define MMCR0_PMC1SEL_SH	8
+#define MMCR0_PMC2SEL_SH	1
+#define MMCR_PMCSEL_MSK		0x1f
+
+/*
+ * Bits in MMCR1 for PPC970
+ */
+#define MMCR1_TTM0SEL_SH	62
+#define MMCR1_TTM1SEL_SH	59
+#define MMCR1_TTM3SEL_SH	53
+#define MMCR1_TTMSEL_MSK	3
+#define MMCR1_TD_CP_DBG0SEL_SH	50
+#define MMCR1_TD_CP_DBG1SEL_SH	48
+#define MMCR1_TD_CP_DBG2SEL_SH	46
+#define MMCR1_TD_CP_DBG3SEL_SH	44
+#define MMCR1_PMC1_ADDER_SEL_SH	39
+#define MMCR1_PMC2_ADDER_SEL_SH	38
+#define MMCR1_PMC6_ADDER_SEL_SH	37
+#define MMCR1_PMC5_ADDER_SEL_SH	36
+#define MMCR1_PMC8_ADDER_SEL_SH	35
+#define MMCR1_PMC7_ADDER_SEL_SH	34
+#define MMCR1_PMC3_ADDER_SEL_SH	33
+#define MMCR1_PMC4_ADDER_SEL_SH	32
+#define MMCR1_PMC3SEL_SH	27
+#define MMCR1_PMC4SEL_SH	22
+#define MMCR1_PMC5SEL_SH	17
+#define MMCR1_PMC6SEL_SH	12
+#define MMCR1_PMC7SEL_SH	7
+#define MMCR1_PMC8SEL_SH	2
+
+static short mmcr1_adder_bits[8] = {
+	MMCR1_PMC1_ADDER_SEL_SH,
+	MMCR1_PMC2_ADDER_SEL_SH,
+	MMCR1_PMC3_ADDER_SEL_SH,
+	MMCR1_PMC4_ADDER_SEL_SH,
+	MMCR1_PMC5_ADDER_SEL_SH,
+	MMCR1_PMC6_ADDER_SEL_SH,
+	MMCR1_PMC7_ADDER_SEL_SH,
+	MMCR1_PMC8_ADDER_SEL_SH
+};
+
+/*
+ * Bits in MMCRA
+ */
+
+/*
+ * Layout of constraint bits:
+ * 6666555555555544444444443333333333222222222211111111110000000000
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ *               <><><>[  >[  >[  ><  ><  ><  ><  ><><><><><><><><>
+ *               SPT0T1 UC  PS1 PS2 B0  B1  B2  B3 P1P2P3P4P5P6P7P8
+ *
+ * SP - SPCSEL constraint
+ *     48-49: SPCSEL value 0x3_0000_0000_0000
+ *
+ * T0 - TTM0 constraint
+ *     46-47: TTM0SEL value (0=FPU, 2=IFU, 3=VPU) 0xC000_0000_0000
+ *
+ * T1 - TTM1 constraint
+ *     44-45: TTM1SEL value (0=IDU, 3=STS) 0x3000_0000_0000
+ *
+ * UC - unit constraint: can't have all three of FPU|IFU|VPU, ISU, IDU|STS
+ *     43: UC3 error 0x0800_0000_0000
+ *     42: FPU|IFU|VPU events needed 0x0400_0000_0000
+ *     41: ISU events needed 0x0200_0000_0000
+ *     40: IDU|STS events needed 0x0100_0000_0000
+ *
+ * PS1
+ *     39: PS1 error 0x0080_0000_0000
+ *     36-38: count of events needing PMC1/2/5/6 0x0070_0000_0000
+ *
+ * PS2
+ *     35: PS2 error 0x0008_0000_0000
+ *     32-34: count of events needing PMC3/4/7/8 0x0007_0000_0000
+ *
+ * B0
+ *     28-31: Byte 0 event source 0xf000_0000
+ *	      Encoding as for the event code
+ *
+ * B1, B2, B3
+ *     24-27, 20-23, 16-19: Byte 1, 2, 3 event sources
+ *
+ * P1
+ *     15: P1 error 0x8000
+ *     14-15: Count of events needing PMC1
+ *
+ * P2..P8
+ *     0-13: Count of events needing PMC2..PMC8
+ */
+
+static unsigned char direct_marked_event[8] = {
+	(1<<2) | (1<<3),	/* PMC1: PM_MRK_GRP_DISP, PM_MRK_ST_CMPL */
+	(1<<3) | (1<<5),	/* PMC2: PM_THRESH_TIMEO, PM_MRK_BRU_FIN */
+	(1<<3) | (1<<5),	/* PMC3: PM_MRK_ST_CMPL_INT, PM_MRK_VMX_FIN */
+	(1<<4) | (1<<5),	/* PMC4: PM_MRK_GRP_CMPL, PM_MRK_CRU_FIN */
+	(1<<4) | (1<<5),	/* PMC5: PM_GRP_MRK, PM_MRK_GRP_TIMEO */
+	(1<<3) | (1<<4) | (1<<5),
+		/* PMC6: PM_MRK_ST_STS, PM_MRK_FXU_FIN, PM_MRK_GRP_ISSUED */
+	(1<<4) | (1<<5),	/* PMC7: PM_MRK_FPU_FIN, PM_MRK_INST_FIN */
+	(1<<4)			/* PMC8: PM_MRK_LSU_FIN */
+};
+
+/*
+ * Returns 1 if event counts things relating to marked instructions
+ * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
+ */
+static int p970_marked_instr_event(u64 event)
+{
+	int pmc, psel, unit, byte, bit;
+	unsigned int mask;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	psel = event & PM_PMCSEL_MSK;
+	if (pmc) {
+		if (direct_marked_event[pmc - 1] & (1 << psel))
+			return 1;
+		if (psel == 0)		/* add events */
+			bit = (pmc <= 4)? pmc - 1: 8 - pmc;
+		else if (psel == 7 || psel == 13)	/* decode events */
+			bit = 4;
+		else
+			return 0;
+	} else
+		bit = psel;
+
+	byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	mask = 0;
+	switch (unit) {
+	case PM_VPU:
+		mask = 0x4c;		/* byte 0 bits 2,3,6 */
+	case PM_LSU0:
+		/* byte 2 bits 0,2,3,4,6; all of byte 1 */
+		mask = 0x085dff00;
+	case PM_LSU1L:
+		mask = 0x50 << 24;	/* byte 3 bits 4,6 */
+		break;
+	}
+	return (mask >> (byte * 8 + bit)) & 1;
+}
+
+/* Masks and values for using events from the various units */
+static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
+	[PM_FPU] =   { 0xc80000000000ull, 0x040000000000ull },
+	[PM_VPU] =   { 0xc80000000000ull, 0xc40000000000ull },
+	[PM_ISU] =   { 0x080000000000ull, 0x020000000000ull },
+	[PM_IFU] =   { 0xc80000000000ull, 0x840000000000ull },
+	[PM_IDU] =   { 0x380000000000ull, 0x010000000000ull },
+	[PM_STS] =   { 0x380000000000ull, 0x310000000000ull },
+};
+
+static int p970_get_constraint(u64 event, unsigned long *maskp,
+			       unsigned long *valp)
+{
+	int pmc, byte, unit, sh, spcsel;
+	unsigned long mask = 0, value = 0;
+	int grp = -1;
+
+	pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
+	if (pmc) {
+		if (pmc > 8)
+			return -1;
+		sh = (pmc - 1) * 2;
+		mask |= 2 << sh;
+		value |= 1 << sh;
+		grp = ((pmc - 1) >> 1) & 1;
+	}
+	unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
+	if (unit) {
+		if (unit > PM_LASTUNIT)
+			return -1;
+		mask |= unit_cons[unit][0];
+		value |= unit_cons[unit][1];
+		byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
+		/*
+		 * Bus events on bytes 0 and 2 can be counted
+		 * on PMC1/2/5/6; bytes 1 and 3 on PMC3/4/7/8.
+		 */
+		if (!pmc)
+			grp = byte & 1;
+		/* Set byte lane select field */
+		mask  |= 0xfULL << (28 - 4 * byte);
+		value |= (unsigned long)unit << (28 - 4 * byte);
+	}
+	if (grp == 0) {
+		/* increment PMC1/2/5/6 field */
+		mask  |= 0x8000000000ull;
+		value |= 0x1000000000ull;
+	} else if (grp == 1) {
+		/* increment PMC3/4/7/8 field */
+		mask  |= 0x800000000ull;
+		value |= 0x100000000ull;
+	}
+	spcsel = (event >> PM_SPCSEL_SH) & PM_SPCSEL_MSK;
+	if (spcsel) {
+		mask  |= 3ull << 48;
+		value |= (unsigned long)spcsel << 48;
+	}
+	*maskp = mask;
+	*valp = value;
+	return 0;
+}
+
+static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	alt[0] = event;
+
+	/* 2 alternatives for LSU empty */
+	if (event == 0x2002 || event == 0x3002) {
+		alt[1] = event ^ 0x1000;
+		return 2;
+	}
+		
+	return 1;
+}
+
+static int p970_compute_mmcr(u64 event[], int n_ev,
+			     unsigned int hwc[], unsigned long mmcr[])
+{
+	unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
+	unsigned int pmc, unit, byte, psel;
+	unsigned int ttm, grp;
+	unsigned int pmc_inuse = 0;
+	unsigned int pmc_grp_use[2];
+	unsigned char busbyte[4];
+	unsigned char unituse[16];
+	unsigned char unitmap[] = { 0, 0<<3, 3<<3, 1<<3, 2<<3, 0|4, 3|4 };
+	unsigned char ttmuse[2];
+	unsigned char pmcsel[8];
+	int i;
+	int spcsel;
+
+	if (n_ev > 8)
+		return -1;
+
+	/* First pass to count resource use */
+	pmc_grp_use[0] = pmc_grp_use[1] = 0;
+	memset(busbyte, 0, sizeof(busbyte));
+	memset(unituse, 0, sizeof(unituse));
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		if (pmc) {
+			if (pmc_inuse & (1 << (pmc - 1)))
+				return -1;
+			pmc_inuse |= 1 << (pmc - 1);
+			/* count 1/2/5/6 vs 3/4/7/8 use */
+			++pmc_grp_use[((pmc - 1) >> 1) & 1];
+		}
+		unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+		byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+		if (unit) {
+			if (unit > PM_LASTUNIT)
+				return -1;
+			if (!pmc)
+				++pmc_grp_use[byte & 1];
+			if (busbyte[byte] && busbyte[byte] != unit)
+				return -1;
+			busbyte[byte] = unit;
+			unituse[unit] = 1;
+		}
+	}
+	if (pmc_grp_use[0] > 4 || pmc_grp_use[1] > 4)
+		return -1;
+
+	/*
+	 * Assign resources and set multiplexer selects.
+	 *
+	 * PM_ISU can go either on TTM0 or TTM1, but that's the only
+	 * choice we have to deal with.
+	 */
+	if (unituse[PM_ISU] &
+	    (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_VPU]))
+		unitmap[PM_ISU] = 2 | 4;	/* move ISU to TTM1 */
+	/* Set TTM[01]SEL fields. */
+	ttmuse[0] = ttmuse[1] = 0;
+	for (i = PM_FPU; i <= PM_STS; ++i) {
+		if (!unituse[i])
+			continue;
+		ttm = unitmap[i];
+		++ttmuse[(ttm >> 2) & 1];
+		mmcr1 |= (unsigned long)(ttm & ~4) << MMCR1_TTM1SEL_SH;
+	}
+	/* Check only one unit per TTMx */
+	if (ttmuse[0] > 1 || ttmuse[1] > 1)
+		return -1;
+
+	/* Set byte lane select fields and TTM3SEL. */
+	for (byte = 0; byte < 4; ++byte) {
+		unit = busbyte[byte];
+		if (!unit)
+			continue;
+		if (unit <= PM_STS)
+			ttm = (unitmap[unit] >> 2) & 1;
+		else if (unit == PM_LSU0)
+			ttm = 2;
+		else {
+			ttm = 3;
+			if (unit == PM_LSU1L && byte >= 2)
+				mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte);
+		}
+		mmcr1 |= (unsigned long)ttm
+			<< (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
+	}
+
+	/* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */
+	memset(pmcsel, 0x8, sizeof(pmcsel));	/* 8 means don't count */
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
+		unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
+		byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
+		psel = event[i] & PM_PMCSEL_MSK;
+		if (!pmc) {
+			/* Bus event or any-PMC direct event */
+			if (unit)
+				psel |= 0x10 | ((byte & 2) << 2);
+			else
+				psel |= 8;
+			for (pmc = 0; pmc < 8; ++pmc) {
+				if (pmc_inuse & (1 << pmc))
+					continue;
+				grp = (pmc >> 1) & 1;
+				if (unit) {
+					if (grp == (byte & 1))
+						break;
+				} else if (pmc_grp_use[grp] < 4) {
+					++pmc_grp_use[grp];
+					break;
+				}
+			}
+			pmc_inuse |= 1 << pmc;
+		} else {
+			/* Direct event */
+			--pmc;
+			if (psel == 0 && (byte & 2))
+				/* add events on higher-numbered bus */
+				mmcr1 |= 1ull << mmcr1_adder_bits[pmc];
+		}
+		pmcsel[pmc] = psel;
+		hwc[i] = pmc;
+		spcsel = (event[i] >> PM_SPCSEL_SH) & PM_SPCSEL_MSK;
+		mmcr1 |= spcsel;
+		if (p970_marked_instr_event(event[i]))
+			mmcra |= MMCRA_SAMPLE_ENABLE;
+	}
+	for (pmc = 0; pmc < 2; ++pmc)
+		mmcr0 |= pmcsel[pmc] << (MMCR0_PMC1SEL_SH - 7 * pmc);
+	for (; pmc < 8; ++pmc)
+		mmcr1 |= (unsigned long)pmcsel[pmc]
+			<< (MMCR1_PMC3SEL_SH - 5 * (pmc - 2));
+	if (pmc_inuse & 1)
+		mmcr0 |= MMCR0_PMC1CE;
+	if (pmc_inuse & 0xfe)
+		mmcr0 |= MMCR0_PMCjCE;
+
+	mmcra |= 0x2000;	/* mark only one IOP per PPC instruction */
+
+	/* Return MMCRx values */
+	mmcr[0] = mmcr0;
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcra;
+	return 0;
+}
+
+static void p970_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	int shift, i;
+
+	if (pmc <= 1) {
+		shift = MMCR0_PMC1SEL_SH - 7 * pmc;
+		i = 0;
+	} else {
+		shift = MMCR1_PMC3SEL_SH - 5 * (pmc - 2);
+		i = 1;
+	}
+	/*
+	 * Setting the PMCxSEL field to 0x08 disables PMC x.
+	 */
+	mmcr[i] = (mmcr[i] & ~(0x1fUL << shift)) | (0x08UL << shift);
+}
+
+static int ppc970_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= 7,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= 1,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= 0x8810, /* PM_LD_REF_L1 */
+	[PERF_COUNT_HW_CACHE_MISSES]		= 0x3810, /* PM_LD_MISS_L1 */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x431,  /* PM_BR_ISSUED */
+	[PERF_COUNT_HW_BRANCH_MISSES] 		= 0x327,  /* PM_GRP_BR_MPRED */
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x8810,		0x3810	},
+		[C(OP_WRITE)] = {	0x7810,		0x813	},
+		[C(OP_PREFETCH)] = {	0x731,		0	},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	0,		0	},
+	},
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0	},
+		[C(OP_WRITE)] = {	0,		0	},
+		[C(OP_PREFETCH)] = {	0x733,		0	},
+	},
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x704	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(ITLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0x700	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0x431,		0x327	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+};
+
+static struct power_pmu ppc970_pmu = {
+	.name			= "PPC970/FX/MP",
+	.n_counter		= 8,
+	.max_alternatives	= 2,
+	.add_fields		= 0x001100005555ull,
+	.test_adder		= 0x013300000000ull,
+	.compute_mmcr		= p970_compute_mmcr,
+	.get_constraint		= p970_get_constraint,
+	.get_alternatives	= p970_get_alternatives,
+	.disable_pmc		= p970_disable_pmc,
+	.n_generic		= ARRAY_SIZE(ppc970_generic_events),
+	.generic_events		= ppc970_generic_events,
+	.cache_events		= &ppc970_cache_events,
+};
+
+static int init_ppc970_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970")
+	     && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970MP")))
+		return -ENODEV;
+
+	return register_power_pmu(&ppc970_pmu);
+}
+
+arch_initcall(init_ppc970_pmu);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/process.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -528,7 +528,7 @@
 
 	for (i = 0;  i < 32;  i++) {
 		if ((i % REGS_PER_LINE) == 0)
-			printk("\n" KERN_INFO "GPR%02d: ", i);
+			printk("\nGPR%02d: ", i);
 		printk(REG " ", regs->gpr[i]);
 		if (i == LAST_VOLATILE && !FULL_REGS(regs))
 			break;
@@ -650,7 +650,7 @@
 	p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
 				_ALIGN_UP(sizeof(struct thread_info), 16);
 
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (cpu_has_feature(CPU_FTR_SLB)) {
 		unsigned long sp_vsid;
 		unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/prom.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/prom.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/prom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/prom.c	2009-09-09 18:13:59.000000000 -0400
@@ -585,7 +585,7 @@
 		      ibm_pa_features, ARRAY_SIZE(ibm_pa_features));
 }
 
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_STD_MMU_64
 static void __init check_cpu_slb_size(unsigned long node)
 {
 	u32 *slb_size_ptr;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/prom_init.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/prom_init.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/prom_init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/prom_init.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,10 +44,7 @@
 #include <asm/sections.h>
 #include <asm/machdep.h>
 
-#ifdef CONFIG_LOGO_LINUX_CLUT224
 #include <linux/linux_logo.h>
-extern const struct linux_logo logo_linux_clut224;
-#endif
 
 /*
  * Properties whose value is longer than this get excluded from our
@@ -1950,8 +1947,47 @@
 	prom_setprop(isa, name, "ranges",
 			isa_ranges, sizeof(isa_ranges));
 }
+
+#define CPC925_MC_START		0xf8000000
+#define CPC925_MC_LENGTH	0x1000000
+/* The values for memory-controller don't have right number of cells */
+static void __init fixup_device_tree_maple_memory_controller(void)
+{
+	phandle mc;
+	u32 mc_reg[4];
+	char *name = "/hostbridge@f8000000";
+	struct prom_t *_prom = &RELOC(prom);
+	u32 ac, sc;
+
+	mc = call_prom("finddevice", 1, 1, ADDR(name));
+	if (!PHANDLE_VALID(mc))
+		return;
+
+	if (prom_getproplen(mc, "reg") != 8)
+		return;
+
+	prom_getprop(_prom->root, "#address-cells", &ac, sizeof(ac));
+	prom_getprop(_prom->root, "#size-cells", &sc, sizeof(sc));
+	if ((ac != 2) || (sc != 2))
+		return;
+
+	if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
+		return;
+
+	if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
+		return;
+
+	prom_printf("Fixing up bogus hostbridge on Maple...\n");
+
+	mc_reg[0] = 0x0;
+	mc_reg[1] = CPC925_MC_START;
+	mc_reg[2] = 0x0;
+	mc_reg[3] = CPC925_MC_LENGTH;
+	prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
+}
 #else
 #define fixup_device_tree_maple()
+#define fixup_device_tree_maple_memory_controller()
 #endif
 
 #ifdef CONFIG_PPC_CHRP
@@ -2192,6 +2228,7 @@
 static void __init fixup_device_tree(void)
 {
 	fixup_device_tree_maple();
+	fixup_device_tree_maple_memory_controller();
 	fixup_device_tree_chrp();
 	fixup_device_tree_pmac();
 	fixup_device_tree_efika();
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/ptrace32.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/ptrace32.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/ptrace32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/ptrace32.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/regset.h>
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -704,32 +704,52 @@
 
 	if (regs != NULL) {
 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+		task->thread.dbcr0 &= ~DBCR0_BT;
 		task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
 		regs->msr |= MSR_DE;
 #else
+		regs->msr &= ~MSR_BE;
 		regs->msr |= MSR_SE;
 #endif
 	}
 	set_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
 
-void user_disable_single_step(struct task_struct *task)
+void user_enable_block_step(struct task_struct *task)
 {
 	struct pt_regs *regs = task->thread.regs;
 
-
-#if defined(CONFIG_BOOKE)
-	/* If DAC then do not single step, skip */
-	if (task->thread.dabr)
-		return;
+	if (regs != NULL) {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+		task->thread.dbcr0 &= ~DBCR0_IC;
+		task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT;
+		regs->msr |= MSR_DE;
+#else
+		regs->msr &= ~MSR_SE;
+		regs->msr |= MSR_BE;
 #endif
+	}
+	set_tsk_thread_flag(task, TIF_SINGLESTEP);
+}
+
+void user_disable_single_step(struct task_struct *task)
+{
+	struct pt_regs *regs = task->thread.regs;
 
 	if (regs != NULL) {
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
-		task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM);
+#if defined(CONFIG_BOOKE)
+		/* If DAC don't clear DBCRO_IDM or MSR_DE */
+		if (task->thread.dabr)
+			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT);
+		else {
+			task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
+			regs->msr &= ~MSR_DE;
+		}
+#elif defined(CONFIG_40x)
+		task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
 		regs->msr &= ~MSR_DE;
 #else
-		regs->msr &= ~MSR_SE;
+		regs->msr &= ~(MSR_SE | MSR_BE);
 #endif
 	}
 	clear_tsk_thread_flag(task, TIF_SINGLESTEP);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/rtas.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/rtas.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/rtas.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/rtas.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,9 +38,10 @@
 #include <asm/syscalls.h>
 #include <asm/smp.h>
 #include <asm/atomic.h>
+#include <asm/time.h>
 
 struct rtas_t rtas = {
-	.lock = SPIN_LOCK_UNLOCKED
+	.lock = __RAW_SPIN_LOCK_UNLOCKED
 };
 EXPORT_SYMBOL(rtas);
 
@@ -67,6 +68,28 @@
 void (*rtas_flash_term_hook)(int);
 EXPORT_SYMBOL(rtas_flash_term_hook);
 
+/* RTAS use home made raw locking instead of spin_lock_irqsave
+ * because those can be called from within really nasty contexts
+ * such as having the timebase stopped which would lockup with
+ * normal locks and spinlock debugging enabled
+ */
+static unsigned long lock_rtas(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	preempt_disable();
+	__raw_spin_lock_flags(&rtas.lock, flags);
+	return flags;
+}
+
+static void unlock_rtas(unsigned long flags)
+{
+	__raw_spin_unlock(&rtas.lock);
+	local_irq_restore(flags);
+	preempt_enable();
+}
+
 /*
  * call_rtas_display_status and call_rtas_display_status_delay
  * are designed only for very early low-level debugging, which
@@ -79,7 +102,7 @@
 
 	if (!rtas.base)
 		return;
-	spin_lock_irqsave(&rtas.lock, s);
+	s = lock_rtas();
 
 	args->token = 10;
 	args->nargs = 1;
@@ -89,7 +112,7 @@
 
 	enter_rtas(__pa(args));
 
-	spin_unlock_irqrestore(&rtas.lock, s);
+	unlock_rtas(s);
 }
 
 static void call_rtas_display_status_delay(char c)
@@ -411,8 +434,7 @@
 	if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
 		return -1;
 
-	/* Gotta do something different here, use global lock for now... */
-	spin_lock_irqsave(&rtas.lock, s);
+	s = lock_rtas();
 	rtas_args = &rtas.args;
 
 	rtas_args->token = token;
@@ -439,8 +461,7 @@
 			outputs[i] = rtas_args->rets[i+1];
 	ret = (nret > 0)? rtas_args->rets[0]: 0;
 
-	/* Gotta do something different here, use global lock for now... */
-	spin_unlock_irqrestore(&rtas.lock, s);
+	unlock_rtas(s);
 
 	if (buff_copy) {
 		log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
@@ -837,7 +858,7 @@
 
 	buff_copy = get_errorlog_buffer();
 
-	spin_lock_irqsave(&rtas.lock, flags);
+	flags = lock_rtas();
 
 	rtas.args = args;
 	enter_rtas(__pa(&rtas.args));
@@ -848,7 +869,7 @@
 	if (args.rets[0] == -1)
 		errbuf = __fetch_rtas_last_error(buff_copy);
 
-	spin_unlock_irqrestore(&rtas.lock, flags);
+	unlock_rtas(flags);
 
 	if (buff_copy) {
 		if (errbuf)
@@ -951,3 +972,33 @@
 	/* break now */
 	return 1;
 }
+
+static raw_spinlock_t timebase_lock;
+static u64 timebase = 0;
+
+void __cpuinit rtas_give_timebase(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	hard_irq_disable();
+	__raw_spin_lock(&timebase_lock);
+	rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
+	timebase = get_tb();
+	__raw_spin_unlock(&timebase_lock);
+
+	while (timebase)
+		barrier();
+	rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
+	local_irq_restore(flags);
+}
+
+void __cpuinit rtas_take_timebase(void)
+{
+	while (!timebase)
+		barrier();
+	__raw_spin_lock(&timebase_lock);
+	set_tb(timebase >> 32, timebase & 0xffffffff);
+	timebase = 0;
+	__raw_spin_unlock(&timebase_lock);
+}
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/rtas_pci.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/rtas_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/rtas_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/rtas_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -93,10 +93,7 @@
 {
 	struct device_node *busdn, *dn;
 
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
+	busdn = pci_bus_to_OF_node(bus);
 
 	/* Search only direct children of the bus */
 	for (dn = busdn->child; dn; dn = dn->sibling) {
@@ -140,10 +137,7 @@
 {
 	struct device_node *busdn, *dn;
 
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
+	busdn = pci_bus_to_OF_node(bus);
 
 	/* Search only direct children of the bus */
 	for (dn = busdn->child; dn; dn = dn->sibling) {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/setup_32.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/setup_32.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/setup_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/setup_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,6 +39,7 @@
 #include <asm/serial.h>
 #include <asm/udbg.h>
 #include <asm/mmu_context.h>
+#include <asm/swiotlb.h>
 
 #include "setup.h"
 
@@ -118,6 +119,8 @@
  */
 notrace void __init machine_init(unsigned long dt_ptr)
 {
+	lockdep_init();
+
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
@@ -332,6 +335,11 @@
 		ppc_md.setup_arch();
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
+#ifdef CONFIG_SWIOTLB
+	if (ppc_swiotlb_enable)
+		swiotlb_init();
+#endif
+
 	paging_init();
 
 	/* Initialize the MMU context management stuff */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/setup_64.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/setup_64.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/setup_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/setup_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,6 +61,7 @@
 #include <asm/xmon.h>
 #include <asm/udbg.h>
 #include <asm/kexec.h>
+#include <asm/swiotlb.h>
 
 #include "setup.h"
 
@@ -417,12 +418,14 @@
 	if (ppc64_caches.iline_size != 0x80)
 		printk("ppc64_caches.icache_line_size = 0x%x\n",
 		       ppc64_caches.iline_size);
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (htab_address)
 		printk("htab_address                  = 0x%p\n", htab_address);
 	printk("htab_hash_mask                = 0x%lx\n", htab_hash_mask);
+#endif /* CONFIG_PPC_STD_MMU_64 */
 	if (PHYSICAL_START > 0)
-		printk("physical_start                = 0x%lx\n",
-		       PHYSICAL_START);
+		printk("physical_start                = 0x%llx\n",
+		       (unsigned long long)PHYSICAL_START);
 	printk("-----------------------------------------------------\n");
 
 	DBG(" <- setup_system()\n");
@@ -511,8 +514,9 @@
 	irqstack_early_init();
 	emergency_stack_init();
 
+#ifdef CONFIG_PPC_STD_MMU_64
 	stabs_alloc();
-
+#endif
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
 	sparse_init();
@@ -524,6 +528,11 @@
 	if (ppc_md.setup_arch)
 		ppc_md.setup_arch();
 
+#ifdef CONFIG_SWIOTLB
+	if (ppc_swiotlb_enable)
+		swiotlb_init();
+#endif
+
 	paging_init();
 	ppc64_boot_msg(0x15, "Setup Done");
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/smp.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,7 +68,8 @@
 /* SMP operations for this machine */
 struct smp_ops_t *smp_ops;
 
-static volatile unsigned int cpu_callin_map[NR_CPUS];
+/* Can't be static due to PowerMac hackery */
+volatile unsigned int cpu_callin_map[NR_CPUS];
 
 int smt_enabled_at_boot = 1;
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/time.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/time.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,6 +52,8 @@
 #include <linux/jiffies.h>
 #include <linux/posix-timers.h>
 #include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/perf_counter.h>
 
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -109,7 +111,7 @@
 static struct clock_event_device decrementer_clockevent = {
        .name           = "decrementer",
        .rating         = 200,
-       .shift          = 16,
+       .shift          = 0,	/* To be filled in */
        .mult           = 0,	/* To be filled in */
        .irq            = 0,
        .set_next_event = decrementer_set_next_event,
@@ -524,6 +526,26 @@
 }
 #endif /* CONFIG_PPC_ISERIES */
 
+#if defined(CONFIG_PERF_COUNTERS) && defined(CONFIG_PPC32)
+DEFINE_PER_CPU(u8, perf_counter_pending);
+
+void set_perf_counter_pending(void)
+{
+	get_cpu_var(perf_counter_pending) = 1;
+	set_dec(1);
+	put_cpu_var(perf_counter_pending);
+}
+
+#define test_perf_counter_pending()	__get_cpu_var(perf_counter_pending)
+#define clear_perf_counter_pending()	__get_cpu_var(perf_counter_pending) = 0
+
+#else  /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
+
+#define test_perf_counter_pending()	0
+#define clear_perf_counter_pending()
+
+#endif /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */
+
 /*
  * For iSeries shared processors, we have to let the hypervisor
  * set the hardware decrementer.  We set a virtual decrementer
@@ -550,6 +572,10 @@
 	set_dec(DECREMENTER_MAX);
 
 #ifdef CONFIG_PPC32
+	if (test_perf_counter_pending()) {
+		clear_perf_counter_pending();
+		perf_counter_do_pending();
+	}
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
 #endif
@@ -843,6 +869,22 @@
 		decrementer_set_next_event(DECREMENTER_MAX, dev);
 }
 
+static void __init setup_clockevent_multiplier(unsigned long hz)
+{
+	u64 mult, shift = 32;
+
+	while (1) {
+		mult = div_sc(hz, NSEC_PER_SEC, shift);
+		if (mult && (mult >> 32UL) == 0UL)
+			break;
+
+		shift--;
+	}
+
+	decrementer_clockevent.shift = shift;
+	decrementer_clockevent.mult = mult;
+}
+
 static void register_decrementer_clockevent(int cpu)
 {
 	struct clock_event_device *dec = &per_cpu(decrementers, cpu).event;
@@ -860,8 +902,7 @@
 {
 	int cpu = smp_processor_id();
 
-	decrementer_clockevent.mult = div_sc(ppc_tb_freq, NSEC_PER_SEC,
-					     decrementer_clockevent.shift);
+	setup_clockevent_multiplier(ppc_tb_freq);
 	decrementer_clockevent.max_delta_ns =
 		clockevent_delta2ns(DECREMENTER_MAX, &decrementer_clockevent);
 	decrementer_clockevent.min_delta_ns =
@@ -1128,6 +1169,15 @@
 
 }
 
+/* We don't need to calibrate delay, we use the CPU timebase for that */
+void calibrate_delay(void)
+{
+	/* Some generic code (such as spinlock debug) use loops_per_jiffy
+	 * as the number of __delay(1) in a jiffy, so make it so
+	 */
+	loops_per_jiffy = tb_ticks_per_jiffy;
+}
+
 static int __init rtc_init(void)
 {
 	struct platform_device *pdev;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/traps.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,9 @@
 #include <linux/backlight.h>
 #include <linux/bug.h>
 #include <linux/kdebug.h>
+#include <linux/debugfs.h>
 
+#include <asm/emulated_ops.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -757,36 +759,44 @@
 
 	/* Emulate the mfspr rD, PVR. */
 	if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) {
+		PPC_WARN_EMULATED(mfpvr);
 		rd = (instword >> 21) & 0x1f;
 		regs->gpr[rd] = mfspr(SPRN_PVR);
 		return 0;
 	}
 
 	/* Emulating the dcba insn is just a no-op.  */
-	if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA)
+	if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) {
+		PPC_WARN_EMULATED(dcba);
 		return 0;
+	}
 
 	/* Emulate the mcrxr insn.  */
 	if ((instword & PPC_INST_MCRXR_MASK) == PPC_INST_MCRXR) {
 		int shift = (instword >> 21) & 0x1c;
 		unsigned long msk = 0xf0000000UL >> shift;
 
+		PPC_WARN_EMULATED(mcrxr);
 		regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
 		regs->xer &= ~0xf0000000UL;
 		return 0;
 	}
 
 	/* Emulate load/store string insn. */
-	if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING)
+	if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) {
+		PPC_WARN_EMULATED(string);
 		return emulate_string_inst(regs, instword);
+	}
 
 	/* Emulate the popcntb (Population Count Bytes) instruction. */
 	if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) {
+		PPC_WARN_EMULATED(popcntb);
 		return emulate_popcntb_inst(regs, instword);
 	}
 
 	/* Emulate isel (Integer Select) instruction */
 	if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) {
+		PPC_WARN_EMULATED(isel);
 		return emulate_isel(regs, instword);
 	}
 
@@ -984,6 +994,8 @@
 
 #ifdef CONFIG_MATH_EMULATION
 	errcode = do_mathemu(regs);
+	if (errcode >= 0)
+		PPC_WARN_EMULATED(math);
 
 	switch (errcode) {
 	case 0:
@@ -1005,6 +1017,9 @@
 
 #elif defined(CONFIG_8XX_MINIMAL_FPEMU)
 	errcode = Soft_emulate_8xx(regs);
+	if (errcode >= 0)
+		PPC_WARN_EMULATED(8xx);
+
 	switch (errcode) {
 	case 0:
 		emulate_single_step(regs);
@@ -1026,7 +1041,34 @@
 
 void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 {
-	if (debug_status & DBSR_IC) {	/* instruction completion */
+	/* Hack alert: On BookE, Branch Taken stops on the branch itself, while
+	 * on server, it stops on the target of the branch. In order to simulate
+	 * the server behaviour, we thus restart right away with a single step
+	 * instead of stopping here when hitting a BT
+	 */
+	if (debug_status & DBSR_BT) {
+		regs->msr &= ~MSR_DE;
+
+		/* Disable BT */
+		mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_BT);
+		/* Clear the BT event */
+		mtspr(SPRN_DBSR, DBSR_BT);
+
+		/* Do the single step trick only when coming from userspace */
+		if (user_mode(regs)) {
+			current->thread.dbcr0 &= ~DBCR0_BT;
+			current->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
+			regs->msr |= MSR_DE;
+			return;
+		}
+
+		if (notify_die(DIE_SSTEP, "block_step", regs, 5,
+			       5, SIGTRAP) == NOTIFY_STOP) {
+			return;
+		}
+		if (debugger_sstep(regs))
+			return;
+	} else if (debug_status & DBSR_IC) { 	/* Instruction complete */
 		regs->msr &= ~MSR_DE;
 
 		/* Disable instruction completion */
@@ -1042,9 +1084,8 @@
 		if (debugger_sstep(regs))
 			return;
 
-		if (user_mode(regs)) {
-			current->thread.dbcr0 &= ~DBCR0_IC;
-		}
+		if (user_mode(regs))
+			current->thread.dbcr0 &= ~(DBCR0_IC);
 
 		_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
 	} else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
@@ -1088,6 +1129,7 @@
 
 	flush_altivec_to_thread(current);
 
+	PPC_WARN_EMULATED(altivec);
 	err = emulate_altivec(regs);
 	if (err == 0) {
 		regs->nip += 4;		/* skip emulated instruction */
@@ -1286,3 +1328,79 @@
 void __init trap_init(void)
 {
 }
+
+
+#ifdef CONFIG_PPC_EMULATED_STATS
+
+#define WARN_EMULATED_SETUP(type)	.type = { .name = #type }
+
+struct ppc_emulated ppc_emulated = {
+#ifdef CONFIG_ALTIVEC
+	WARN_EMULATED_SETUP(altivec),
+#endif
+	WARN_EMULATED_SETUP(dcba),
+	WARN_EMULATED_SETUP(dcbz),
+	WARN_EMULATED_SETUP(fp_pair),
+	WARN_EMULATED_SETUP(isel),
+	WARN_EMULATED_SETUP(mcrxr),
+	WARN_EMULATED_SETUP(mfpvr),
+	WARN_EMULATED_SETUP(multiple),
+	WARN_EMULATED_SETUP(popcntb),
+	WARN_EMULATED_SETUP(spe),
+	WARN_EMULATED_SETUP(string),
+	WARN_EMULATED_SETUP(unaligned),
+#ifdef CONFIG_MATH_EMULATION
+	WARN_EMULATED_SETUP(math),
+#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
+	WARN_EMULATED_SETUP(8xx),
+#endif
+#ifdef CONFIG_VSX
+	WARN_EMULATED_SETUP(vsx),
+#endif
+};
+
+u32 ppc_warn_emulated;
+
+void ppc_warn_emulated_print(const char *type)
+{
+	if (printk_ratelimit())
+		pr_warning("%s used emulated %s instruction\n", current->comm,
+			   type);
+}
+
+static int __init ppc_warn_emulated_init(void)
+{
+	struct dentry *dir, *d;
+	unsigned int i;
+	struct ppc_emulated_entry *entries = (void *)&ppc_emulated;
+
+	if (!powerpc_debugfs_root)
+		return -ENODEV;
+
+	dir = debugfs_create_dir("emulated_instructions",
+				 powerpc_debugfs_root);
+	if (!dir)
+		return -ENOMEM;
+
+	d = debugfs_create_u32("do_warn", S_IRUGO | S_IWUSR, dir,
+			       &ppc_warn_emulated);
+	if (!d)
+		goto fail;
+
+	for (i = 0; i < sizeof(ppc_emulated)/sizeof(*entries); i++) {
+		d = debugfs_create_u32(entries[i].name, S_IRUGO | S_IWUSR, dir,
+				       (u32 *)&entries[i].val.counter);
+		if (!d)
+			goto fail;
+	}
+
+	return 0;
+
+fail:
+	debugfs_remove_recursive(dir);
+	return -ENOMEM;
+}
+
+device_initcall(ppc_warn_emulated_init);
+
+#endif /* CONFIG_PPC_EMULATED_STATS */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/udbg_16550.c linux-libre-2.6.31-gnu/arch/powerpc/kernel/udbg_16550.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/udbg_16550.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/udbg_16550.c	2009-09-09 18:13:59.000000000 -0400
@@ -219,7 +219,7 @@
 #ifdef CONFIG_PPC_EARLY_DEBUG_44x
 #include <platforms/44x/44x.h>
 
-static int udbg_44x_as1_flush(void)
+static void udbg_44x_as1_flush(void)
 {
 	if (udbg_comport) {
 		while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kernel/vector.S linux-libre-2.6.31-gnu/arch/powerpc/kernel/vector.S
--- linux-libre-2.6.30-gnu/arch/powerpc/kernel/vector.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kernel/vector.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,215 @@
+#include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/reg.h>
+#include <asm/asm-offsets.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+
+/*
+ * load_up_altivec(unused, unused, tsk)
+ * Disable VMX for the task which had it previously,
+ * and save its vector registers in its thread_struct.
+ * Enables the VMX for use in the kernel on return.
+ * On SMP we know the VMX is free, since we give it up every
+ * switch (ie, no lazy save of the vector registers).
+ */
+_GLOBAL(load_up_altivec)
+	mfmsr	r5			/* grab the current MSR */
+	oris	r5,r5,MSR_VEC@h
+	MTMSRD(r5)			/* enable use of AltiVec now */
+	isync
+
+/*
+ * For SMP, we don't do lazy VMX switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another.  Instead we call giveup_altvec in switch_to.
+ * VRSAVE isn't dealt with here, that is done in the normal context
+ * switch code. Note that we could rely on vrsave value to eventually
+ * avoid saving all of the VREGs here...
+ */
+#ifndef CONFIG_SMP
+	LOAD_REG_ADDRBASE(r3, last_task_used_altivec)
+	toreal(r3)
+	PPC_LL	r4,ADDROFF(last_task_used_altivec)(r3)
+	PPC_LCMPI	0,r4,0
+	beq	1f
+
+	/* Save VMX state to last_task_used_altivec's THREAD struct */
+	toreal(r4)
+	addi	r4,r4,THREAD
+	SAVE_32VRS(0,r5,r4)
+	mfvscr	vr0
+	li	r10,THREAD_VSCR
+	stvx	vr0,r10,r4
+	/* Disable VMX for last_task_used_altivec */
+	PPC_LL	r5,PT_REGS(r4)
+	toreal(r5)
+	PPC_LL	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+	lis	r10,MSR_VEC@h
+	andc	r4,r4,r10
+	PPC_STL	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+
+	/* Hack: if we get an altivec unavailable trap with VRSAVE
+	 * set to all zeros, we assume this is a broken application
+	 * that fails to set it properly, and thus we switch it to
+	 * all 1's
+	 */
+	mfspr	r4,SPRN_VRSAVE
+	cmpdi	0,r4,0
+	bne+	1f
+	li	r4,-1
+	mtspr	SPRN_VRSAVE,r4
+1:
+	/* enable use of VMX after return */
+#ifdef CONFIG_PPC32
+	mfspr	r5,SPRN_SPRG3		/* current task's THREAD (phys) */
+	oris	r9,r9,MSR_VEC@h
+#else
+	ld	r4,PACACURRENT(r13)
+	addi	r5,r4,THREAD		/* Get THREAD */
+	oris	r12,r12,MSR_VEC@h
+	std	r12,_MSR(r1)
+#endif
+	li	r4,1
+	li	r10,THREAD_VSCR
+	stw	r4,THREAD_USED_VR(r5)
+	lvx	vr0,r10,r5
+	mtvscr	vr0
+	REST_32VRS(0,r4,r5)
+#ifndef CONFIG_SMP
+	/* Update last_task_used_altivec to 'current' */
+	subi	r4,r5,THREAD		/* Back to 'current' */
+	fromreal(r4)
+	PPC_STL	r4,ADDROFF(last_task_used_altivec)(r3)
+#endif /* CONFIG_SMP */
+	/* restore registers and return */
+	blr
+
+/*
+ * giveup_altivec(tsk)
+ * Disable VMX for the task given as the argument,
+ * and save the vector registers in its thread_struct.
+ * Enables the VMX for use in the kernel on return.
+ */
+_GLOBAL(giveup_altivec)
+	mfmsr	r5
+	oris	r5,r5,MSR_VEC@h
+	SYNC
+	MTMSRD(r5)			/* enable use of VMX now */
+	isync
+	PPC_LCMPI	0,r3,0
+	beqlr-				/* if no previous owner, done */
+	addi	r3,r3,THREAD		/* want THREAD of task */
+	PPC_LL	r5,PT_REGS(r3)
+	PPC_LCMPI	0,r5,0
+	SAVE_32VRS(0,r4,r3)
+	mfvscr	vr0
+	li	r4,THREAD_VSCR
+	stvx	vr0,r4,r3
+	beq	1f
+	PPC_LL	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+	lis	r3,(MSR_VEC|MSR_VSX)@h
+FTR_SECTION_ELSE
+	lis	r3,MSR_VEC@h
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
+#else
+	lis	r3,MSR_VEC@h
+#endif
+	andc	r4,r4,r3		/* disable FP for previous task */
+	PPC_STL	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+	li	r5,0
+	LOAD_REG_ADDRBASE(r4,last_task_used_altivec)
+	PPC_STL	r5,ADDROFF(last_task_used_altivec)(r4)
+#endif /* CONFIG_SMP */
+	blr
+
+#ifdef CONFIG_VSX
+
+#ifdef CONFIG_PPC32
+#error This asm code isn't ready for 32-bit kernels
+#endif
+
+/*
+ * load_up_vsx(unused, unused, tsk)
+ * Disable VSX for the task which had it previously,
+ * and save its vector registers in its thread_struct.
+ * Reuse the fp and vsx saves, but first check to see if they have
+ * been saved already.
+ */
+_GLOBAL(load_up_vsx)
+/* Load FP and VSX registers if they haven't been done yet */
+	andi.	r5,r12,MSR_FP
+	beql+	load_up_fpu		/* skip if already loaded */
+	andis.	r5,r12,MSR_VEC@h
+	beql+	load_up_altivec		/* skip if already loaded */
+
+#ifndef CONFIG_SMP
+	ld	r3,last_task_used_vsx@got(r2)
+	ld	r4,0(r3)
+	cmpdi	0,r4,0
+	beq	1f
+	/* Disable VSX for last_task_used_vsx */
+	addi	r4,r4,THREAD
+	ld	r5,PT_REGS(r4)
+	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+	lis	r6,MSR_VSX@h
+	andc	r6,r4,r6
+	std	r6,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+	ld	r4,PACACURRENT(r13)
+	addi	r4,r4,THREAD		/* Get THREAD */
+	li	r6,1
+	stw	r6,THREAD_USED_VSR(r4) /* ... also set thread used vsr */
+	/* enable use of VSX after return */
+	oris	r12,r12,MSR_VSX@h
+	std	r12,_MSR(r1)
+#ifndef CONFIG_SMP
+	/* Update last_task_used_vsx to 'current' */
+	ld	r4,PACACURRENT(r13)
+	std	r4,0(r3)
+#endif /* CONFIG_SMP */
+	b	fast_exception_return
+
+/*
+ * __giveup_vsx(tsk)
+ * Disable VSX for the task given as the argument.
+ * Does NOT save vsx registers.
+ * Enables the VSX for use in the kernel on return.
+ */
+_GLOBAL(__giveup_vsx)
+	mfmsr	r5
+	oris	r5,r5,MSR_VSX@h
+	mtmsrd	r5			/* enable use of VSX now */
+	isync
+
+	cmpdi	0,r3,0
+	beqlr-				/* if no previous owner, done */
+	addi	r3,r3,THREAD		/* want THREAD of task */
+	ld	r5,PT_REGS(r3)
+	cmpdi	0,r5,0
+	beq	1f
+	ld	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+	lis	r3,MSR_VSX@h
+	andc	r4,r4,r3		/* disable VSX for previous task */
+	std	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+	li	r5,0
+	ld	r4,last_task_used_vsx@got(r2)
+	std	r5,0(r4)
+#endif /* CONFIG_SMP */
+	blr
+
+#endif /* CONFIG_VSX */
+
 
 /*
  * The routines below are in assembler so we can closely control the
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kvm/Makefile linux-libre-2.6.31-gnu/arch/powerpc/kvm/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/kvm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kvm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module
 #
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
 
 common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/kvm/powerpc.c linux-libre-2.6.31-gnu/arch/powerpc/kvm/powerpc.c
--- linux-libre-2.6.30-gnu/arch/powerpc/kvm/powerpc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/kvm/powerpc.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,12 @@
 	return !!(v->arch.pending_exceptions);
 }
 
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+	/* do real check here */
+	return 1;
+}
+
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
 	return !(v->arch.msr & MSR_WE);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/lib/Makefile linux-libre-2.6.31-gnu/arch/powerpc/lib/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/lib/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/lib/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,8 @@
 # Makefile for ppc-specific library files..
 #
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS		+= -mno-minimal-toc
 endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/Makefile linux-libre-2.6.31-gnu/arch/powerpc/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -142,6 +142,7 @@
 
 head-$(CONFIG_PPC64)		+= arch/powerpc/kernel/entry_64.o
 head-$(CONFIG_PPC_FPU)		+= arch/powerpc/kernel/fpu.o
+head-$(CONFIG_ALTIVEC)		+= arch/powerpc/kernel/vector.o
 
 core-y				+= arch/powerpc/kernel/ \
 				   arch/powerpc/mm/ \
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/fault.c linux-libre-2.6.31-gnu/arch/powerpc/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
+#include <linux/perf_counter.h>
 
 #include <asm/firmware.h>
 #include <asm/page.h>
@@ -170,6 +171,8 @@
 		die("Weird page fault", regs, SIGSEGV);
 	}
 
+	perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
 	/* When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
 	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
@@ -299,7 +302,7 @@
 	 * the fault.
 	 */
  survive:
-	ret = handle_mm_fault(mm, vma, address, is_write);
+	ret = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(ret & VM_FAULT_ERROR)) {
 		if (ret & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -309,6 +312,8 @@
 	}
 	if (ret & VM_FAULT_MAJOR) {
 		current->maj_flt++;
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+				     regs, address);
 #ifdef CONFIG_PPC_SMLPAR
 		if (firmware_has_feature(FW_FEATURE_CMO)) {
 			preempt_disable();
@@ -316,8 +321,11 @@
 			preempt_enable();
 		}
 #endif
-	} else
+	} else {
 		current->min_flt++;
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+				     regs, address);
+	}
 	up_read(&mm->mmap_sem);
 	return 0;
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/gup.c linux-libre-2.6.31-gnu/arch/powerpc/mm/gup.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/gup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/gup.c	2009-09-09 18:13:59.000000000 -0400
@@ -159,7 +159,7 @@
 	int psize;
 #endif
 
-	pr_debug("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read");
+	pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read");
 
 	start &= PAGE_MASK;
 	addr = start;
@@ -170,7 +170,7 @@
 					start, len)))
 		goto slow_irqon;
 
-	pr_debug("  aligned: %lx .. %lx\n", start, end);
+	pr_devel("  aligned: %lx .. %lx\n", start, end);
 
 #ifdef CONFIG_HUGETLB_PAGE
 	/* We bail out on slice boundary crossing when hugetlb is
@@ -234,7 +234,7 @@
 		do {
 			VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift);
 			ptep = huge_pte_offset(mm, a);
-			pr_debug(" %016lx: huge ptep %p\n", a, ptep);
+			pr_devel(" %016lx: huge ptep %p\n", a, ptep);
 			if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages,
 						   &nr))
 				goto slow;
@@ -249,7 +249,7 @@
 #ifdef CONFIG_PPC64
 			VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift);
 #endif
-			pr_debug("  %016lx: normal pgd %p\n", addr,
+			pr_devel("  %016lx: normal pgd %p\n", addr,
 				 (void *)pgd_val(pgd));
 			next = pgd_addr_end(addr, end);
 			if (pgd_none(pgd))
@@ -269,7 +269,7 @@
 slow:
 		local_irq_enable();
 slow_irqon:
-		pr_debug("  slow path ! nr = %d\n", nr);
+		pr_devel("  slow path ! nr = %d\n", nr);
 
 		/* Try to get the remaining pages with get_user_pages */
 		start += nr << PAGE_SHIFT;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/hash_native_64.c linux-libre-2.6.31-gnu/arch/powerpc/mm/hash_native_64.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/hash_native_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/hash_native_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <asm/cputable.h>
 #include <asm/udbg.h>
 #include <asm/kexec.h>
+#include <asm/ppc-opcode.h>
 
 #ifdef DEBUG_LOW
 #define DBG_LOW(fmt...) udbg_printf(fmt)
@@ -49,14 +50,21 @@
 	case MMU_PAGE_4K:
 		va &= ~0xffful;
 		va |= ssize << 8;
-		asm volatile("tlbie %0,0" : : "r" (va) : "memory");
+		asm volatile(ASM_MMU_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0),
+					       %2)
+			     : : "r" (va), "r"(0), "i" (MMU_FTR_TLBIE_206)
+			     : "memory");
 		break;
 	default:
 		penc = mmu_psize_defs[psize].penc;
 		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
 		va |= penc << 12;
 		va |= ssize << 8;
-		asm volatile("tlbie %0,1" : : "r" (va) : "memory");
+		va |= 1; /* L */
+		asm volatile(ASM_MMU_FTR_IFCLR("tlbie %0,1", PPC_TLBIE(%1,%0),
+					       %2)
+			     : : "r" (va), "r"(0), "i" (MMU_FTR_TLBIE_206)
+			     : "memory");
 		break;
 	}
 }
@@ -80,6 +88,7 @@
 		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
 		va |= penc << 12;
 		va |= ssize << 8;
+		va |= 1; /* L */
 		asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
 			     : : "r"(va) : "memory");
 		break;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/highmem.c linux-libre-2.6.31-gnu/arch/powerpc/mm/highmem.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/highmem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/highmem.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ * highmem.c: virtual kernel memory mappings for high memory
+ *
+ * PowerPC version, stolen from the i386 version.
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual addresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ *		      Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with
+ * up to 16 Terrabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ *
+ * Reworked for PowerPC by various contributors. Moved from
+ * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp.
+ */
+
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+/*
+ * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
+ * gives a more generic (and caching) interface. But kmap_atomic can
+ * be used in IRQ contexts, so in some (very limited) cases we need
+ * it.
+ */
+void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+{
+	unsigned int idx;
+	unsigned long vaddr;
+
+	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+	pagefault_disable();
+	if (!PageHighMem(page))
+		return page_address(page);
+
+	debug_kmap_atomic(type);
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+	BUG_ON(!pte_none(*(kmap_pte-idx)));
+#endif
+	__set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1);
+	local_flush_tlb_page(NULL, vaddr);
+
+	return (void*) vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic_prot);
+
+void kunmap_atomic(void *kvaddr, enum km_type type)
+{
+#ifdef CONFIG_DEBUG_HIGHMEM
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+	if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
+		pagefault_enable();
+		return;
+	}
+
+	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+	/*
+	 * force other mappings to Oops if they'll try to access
+	 * this pte without first remap it
+	 */
+	pte_clear(&init_mm, vaddr, kmap_pte-idx);
+	local_flush_tlb_page(NULL, vaddr);
+#endif
+	pagefault_enable();
+}
+EXPORT_SYMBOL(kunmap_atomic);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/hugetlbpage.c linux-libre-2.6.31-gnu/arch/powerpc/mm/hugetlbpage.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/hugetlbpage.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/hugetlbpage.c	2009-09-09 18:13:59.000000000 -0400
@@ -305,7 +305,7 @@
 
 	pmd = pmd_offset(pud, start);
 	pud_clear(pud);
-	pmd_free_tlb(tlb, pmd);
+	pmd_free_tlb(tlb, pmd, start);
 }
 
 static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
@@ -348,7 +348,7 @@
 
 	pud = pud_offset(pgd, start);
 	pgd_clear(pgd);
-	pud_free_tlb(tlb, pud);
+	pud_free_tlb(tlb, pud, start);
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/init_64.c linux-libre-2.6.31-gnu/arch/powerpc/mm/init_64.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/init_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/init_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -66,6 +66,7 @@
 
 #include "mmu_decl.h"
 
+#ifdef CONFIG_PPC_STD_MMU_64
 #if PGTABLE_RANGE > USER_VSID_RANGE
 #warning Limited user VSID range means pagetable space is wasted
 #endif
@@ -73,6 +74,7 @@
 #if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
 #warning TASK_SIZE is smaller than it needs to be.
 #endif
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 phys_addr_t memstart_addr = ~0;
 phys_addr_t kernstart_addr;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/Makefile linux-libre-2.6.31-gnu/arch/powerpc/mm/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,8 @@
 # Makefile for the linux ppc-specific parts of the memory manager.
 #
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS	+= -mno-minimal-toc
 endif
@@ -11,10 +13,11 @@
 				   pgtable_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_PPC_MMU_NOHASH)	+= mmu_context_nohash.o tlb_nohash.o \
 				   tlb_nohash_low.o
-hash-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o
-obj-$(CONFIG_PPC64)		+= hash_utils_64.o \
+obj-$(CONFIG_PPC64)		+= mmap_64.o
+hash64-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o
+obj-$(CONFIG_PPC_STD_MMU_64)	+= hash_utils_64.o \
 				   slb_low.o slb.o stab.o \
-				   mmap_64.o $(hash-y)
+				   mmap_64.o $(hash64-y)
 obj-$(CONFIG_PPC_STD_MMU_32)	+= ppc_mmu_32.o
 obj-$(CONFIG_PPC_STD_MMU)	+= hash_low_$(CONFIG_WORD_SIZE).o \
 				   tlb_hash$(CONFIG_WORD_SIZE).o \
@@ -27,3 +30,4 @@
 obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 obj-$(CONFIG_PPC_SUBPAGE_PROT)	+= subpage-prot.o
 obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
+obj-$(CONFIG_HIGHMEM)		+= highmem.o
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/mmu_context_nohash.c linux-libre-2.6.31-gnu/arch/powerpc/mm/mmu_context_nohash.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/mmu_context_nohash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/mmu_context_nohash.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 static unsigned long *context_map;
 static unsigned long *stale_map[NR_CPUS];
 static struct mm_struct **context_mm;
-static spinlock_t context_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(context_lock);
 
 #define CTX_MAP_SIZE	\
 	(sizeof(unsigned long) * (last_context / BITS_PER_LONG + 1))
@@ -73,7 +73,6 @@
 	struct mm_struct *mm;
 	unsigned int cpu, max;
 
- again:
 	max = last_context - first_context;
 
 	/* Attempt to free next_context first and then loop until we manage */
@@ -90,7 +89,7 @@
 				id = first_context;
 			continue;
 		}
-		pr_debug("[%d] steal context %d from mm @%p\n",
+		pr_devel("[%d] steal context %d from mm @%p\n",
 			 smp_processor_id(), id, mm);
 
 		/* Mark this mm has having no context anymore */
@@ -108,7 +107,9 @@
 	spin_unlock(&context_lock);
 	cpu_relax();
 	spin_lock(&context_lock);
-	goto again;
+
+	/* This will cause the caller to try again */
+	return MMU_NO_CONTEXT;
 }
 #endif  /* CONFIG_SMP */
 
@@ -125,7 +126,7 @@
 	/* Pick up the victim mm */
 	mm = context_mm[id];
 
-	pr_debug("[%d] steal context %d from mm @%p\n", cpu, id, mm);
+	pr_devel("[%d] steal context %d from mm @%p\n", cpu, id, mm);
 
 	/* Flush the TLB for that context */
 	local_flush_tlb_mm(mm);
@@ -179,7 +180,7 @@
 	spin_lock(&context_lock);
 
 #ifndef DEBUG_STEAL_ONLY
-	pr_debug("[%d] activating context for mm @%p, active=%d, id=%d\n",
+	pr_devel("[%d] activating context for mm @%p, active=%d, id=%d\n",
 		 cpu, next, next->context.active, next->context.id);
 #endif
 
@@ -188,12 +189,14 @@
 	next->context.active++;
 	if (prev) {
 #ifndef DEBUG_STEAL_ONLY
-		pr_debug(" old context %p active was: %d\n",
+		pr_devel(" old context %p active was: %d\n",
 			 prev, prev->context.active);
 #endif
 		WARN_ON(prev->context.active < 1);
 		prev->context.active--;
 	}
+
+ again:
 #endif /* CONFIG_SMP */
 
 	/* If we already have a valid assigned context, skip all that */
@@ -212,6 +215,8 @@
 #ifdef CONFIG_SMP
 		if (num_online_cpus() > 1) {
 			id = steal_context_smp(id);
+			if (id == MMU_NO_CONTEXT)
+				goto again;
 			goto stolen;
 		}
 #endif /* CONFIG_SMP */
@@ -232,7 +237,7 @@
 	next->context.id = id;
 
 #ifndef DEBUG_STEAL_ONLY
-	pr_debug("[%d] picked up new id %d, nrf is now %d\n",
+	pr_devel("[%d] picked up new id %d, nrf is now %d\n",
 		 cpu, id, nr_free_contexts);
 #endif
 
@@ -243,7 +248,7 @@
 	 * local TLB for it and unmark it before we use it
 	 */
 	if (test_bit(id, stale_map[cpu])) {
-		pr_debug("[%d] flushing stale context %d for mm @%p !\n",
+		pr_devel("[%d] flushing stale context %d for mm @%p !\n",
 			 cpu, id, next);
 		local_flush_tlb_mm(next);
 
@@ -272,6 +277,7 @@
  */
 void destroy_context(struct mm_struct *mm)
 {
+	unsigned long flags;
 	unsigned int id;
 
 	if (mm->context.id == MMU_NO_CONTEXT)
@@ -279,18 +285,18 @@
 
 	WARN_ON(mm->context.active != 0);
 
-	spin_lock(&context_lock);
+	spin_lock_irqsave(&context_lock, flags);
 	id = mm->context.id;
 	if (id != MMU_NO_CONTEXT) {
 		__clear_bit(id, context_map);
 		mm->context.id = MMU_NO_CONTEXT;
 #ifdef DEBUG_MAP_CONSISTENCY
 		mm->context.active = 0;
-		context_mm[id] = NULL;
 #endif
+		context_mm[id] = NULL;
 		nr_free_contexts++;
 	}
-	spin_unlock(&context_lock);
+	spin_unlock_irqrestore(&context_lock, flags);
 }
 
 #ifdef CONFIG_SMP
@@ -309,13 +315,13 @@
 	switch (action) {
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
-		pr_debug("MMU: Allocating stale context map for CPU %d\n", cpu);
+		pr_devel("MMU: Allocating stale context map for CPU %d\n", cpu);
 		stale_map[cpu] = kzalloc(CTX_MAP_SIZE, GFP_KERNEL);
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
-		pr_debug("MMU: Freeing stale context map for CPU %d\n", cpu);
+		pr_devel("MMU: Freeing stale context map for CPU %d\n", cpu);
 		kfree(stale_map[cpu]);
 		stale_map[cpu] = NULL;
 		break;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/numa.c linux-libre-2.6.31-gnu/arch/powerpc/mm/numa.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/numa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/numa.c	2009-09-09 18:13:59.000000000 -0400
@@ -981,6 +981,8 @@
 		mark_reserved_regions_for_nid(nid);
 		sparse_memory_present_with_active_regions(nid);
 	}
+
+	init_bootmem_done = 1;
 }
 
 void __init paging_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/pgtable.c linux-libre-2.6.31-gnu/arch/powerpc/mm/pgtable.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/pgtable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/pgtable.c	2009-09-09 18:13:59.000000000 -0400
@@ -129,12 +129,12 @@
 	page = pfn_to_page(pfn);
 
 	if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) {
-		pr_debug("do_dcache_icache_coherency... flushing\n");
+		pr_devel("do_dcache_icache_coherency... flushing\n");
 		flush_dcache_icache_page(page);
 		set_bit(PG_arch_1, &page->flags);
 	}
 	else
-		pr_debug("do_dcache_icache_coherency... already clean\n");
+		pr_devel("do_dcache_icache_coherency... already clean\n");
 	return __pte(pte_val(pte) | _PAGE_HWEXEC);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/slb.c linux-libre-2.6.31-gnu/arch/powerpc/mm/slb.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/slb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/slb.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
  * PowerPC64 SLB support.
  *
  * Copyright (C) 2004 David Gibson <dwg@au.ibm.com>, IBM
- * Based on earlier code writteh by:
+ * Based on earlier code written by:
  * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
  *    Copyright (c) 2001 Dave Engebretsen
  * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM
@@ -14,8 +14,6 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG
-
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
@@ -27,11 +25,6 @@
 #include <linux/compiler.h>
 #include <asm/udbg.h>
 
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG pr_debug
-#endif
 
 extern void slb_allocate_realmode(unsigned long ea);
 extern void slb_allocate_user(unsigned long ea);
@@ -285,13 +278,13 @@
 		patch_slb_encoding(slb_compare_rr_to_size,
 				   mmu_slb_size);
 
-		DBG("SLB: linear  LLP = %04lx\n", linear_llp);
-		DBG("SLB: io      LLP = %04lx\n", io_llp);
+		pr_devel("SLB: linear  LLP = %04lx\n", linear_llp);
+		pr_devel("SLB: io      LLP = %04lx\n", io_llp);
 
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 		patch_slb_encoding(slb_miss_kernel_load_vmemmap,
 				   SLB_VSID_KERNEL | vmemmap_llp);
-		DBG("SLB: vmemmap LLP = %04lx\n", vmemmap_llp);
+		pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp);
 #endif
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/mm/tlb_hash64.c linux-libre-2.6.31-gnu/arch/powerpc/mm/tlb_hash64.c
--- linux-libre-2.6.30-gnu/arch/powerpc/mm/tlb_hash64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/mm/tlb_hash64.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,7 +72,7 @@
 	 */
 	if (huge) {
 #ifdef CONFIG_HUGETLB_PAGE
-		psize = get_slice_psize(mm, addr);;
+		psize = get_slice_psize(mm, addr);
 #else
 		BUG();
 		psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/oprofile/cell/vma_map.c linux-libre-2.6.31-gnu/arch/powerpc/oprofile/cell/vma_map.c
--- linux-libre-2.6.30-gnu/arch/powerpc/oprofile/cell/vma_map.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/oprofile/cell/vma_map.c	2009-09-09 18:13:59.000000000 -0400
@@ -185,7 +185,7 @@
 			goto fail;
 
 		if (shdr_str.sh_type != SHT_STRTAB)
-			goto fail;;
+			goto fail;
 
 		for (j = 0; j < shdr.sh_size / sizeof (sym); j++) {
 			if (copy_from_user(&sym, spu_elf_start +
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/oprofile/Makefile linux-libre-2.6.31-gnu/arch/powerpc/oprofile/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/oprofile/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/oprofile/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,5 @@
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS	+= -mno-minimal-toc
 endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/oprofile/op_model_fsl_emb.c linux-libre-2.6.31-gnu/arch/powerpc/oprofile/op_model_fsl_emb.c
--- linux-libre-2.6.30-gnu/arch/powerpc/oprofile/op_model_fsl_emb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/oprofile/op_model_fsl_emb.c	2009-09-09 18:13:59.000000000 -0400
@@ -228,20 +228,6 @@
 	mtpmr(PMRN_PMGC0, pmgc0);
 }
 
-static void dump_pmcs(void)
-{
-	printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0));
-	printk("pmc\t\tpmlca\t\tpmlcb\n");
-	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0),
-			mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0));
-	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1),
-			mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1));
-	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2),
-			mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2));
-	printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3),
-			mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
-}
-
 static int fsl_emb_cpu_setup(struct op_counter_config *ctr)
 {
 	int i;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/Kconfig linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/Kconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -45,6 +45,7 @@
 	depends on 40x
 	default n
 	select 405EX
+	select PPC40x_SIMPLE
 	select PPC4xx_PCI_EXPRESS
 	help
 	  This option enables support for the AMCC PPC405EX evaluation board.
@@ -56,6 +57,7 @@
 	select 405EX
 	select PCI
 	select PPC4xx_PCI_EXPRESS
+	select PPC40x_SIMPLE
 	help
 	  This option enables support for the AMCC PPC405EX board.
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/kilauea.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/kilauea.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/kilauea.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/kilauea.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * Kilauea board specific routines
- *
- * Copyright 2007-2008 DENX Software Engineering, Stefan Roese <sr@denx.de>
- *
- * Based on the Walnut code by
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- * Copyright 2007 IBM 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.
- */
-#include <linux/init.h>
-#include <linux/of_platform.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id kilauea_of_bus[] = {
-	{ .compatible = "ibm,plb4", },
-	{ .compatible = "ibm,opb", },
-	{ .compatible = "ibm,ebc", },
-	{},
-};
-
-static int __init kilauea_device_probe(void)
-{
-	of_platform_bus_probe(NULL, kilauea_of_bus, NULL);
-
-	return 0;
-}
-machine_device_initcall(kilauea, kilauea_device_probe);
-
-static int __init kilauea_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-
-	if (!of_flat_dt_is_compatible(root, "amcc,kilauea"))
-		return 0;
-
-	ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
-
-	return 1;
-}
-
-define_machine(kilauea) {
-	.name 				= "Kilauea",
-	.probe 				= kilauea_probe,
-	.progress 			= udbg_progress,
-	.init_IRQ 			= uic_init_tree,
-	.get_irq 			= uic_get_irq,
-	.restart			= ppc4xx_reset_system,
-	.calibrate_decr			= generic_calibrate_decr,
-};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/makalu.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/makalu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/makalu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/makalu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * Makalu board specific routines
- *
- * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de>
- *
- * Based on the Walnut code by
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- * Copyright 2007 IBM 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.
- */
-#include <linux/init.h>
-#include <linux/of_platform.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id makalu_of_bus[] = {
-	{ .compatible = "ibm,plb4", },
-	{ .compatible = "ibm,opb", },
-	{ .compatible = "ibm,ebc", },
-	{},
-};
-
-static int __init makalu_device_probe(void)
-{
-	of_platform_bus_probe(NULL, makalu_of_bus, NULL);
-
-	return 0;
-}
-machine_device_initcall(makalu, makalu_device_probe);
-
-static int __init makalu_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-
-	if (!of_flat_dt_is_compatible(root, "amcc,makalu"))
-		return 0;
-
-	ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
-
-	return 1;
-}
-
-define_machine(makalu) {
-	.name 				= "Makalu",
-	.probe 				= makalu_probe,
-	.progress 			= udbg_progress,
-	.init_IRQ 			= uic_init_tree,
-	.get_irq 			= uic_get_irq,
-	.restart			= ppc4xx_reset_system,
-	.calibrate_decr			= generic_calibrate_decr,
-};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/Makefile linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,4 @@
-obj-$(CONFIG_KILAUEA)				+= kilauea.o
 obj-$(CONFIG_HCU4)				+= hcu4.o
-obj-$(CONFIG_MAKALU)				+= makalu.o
 obj-$(CONFIG_WALNUT)				+= walnut.o
 obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD)	+= virtex.o
 obj-$(CONFIG_EP405)				+= ep405.o
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/ppc40x_simple.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/ppc40x_simple.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/ppc40x_simple.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/ppc40x_simple.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,7 +51,10 @@
  * board.c file for it rather than adding it to this list.
  */
 static char *board[] __initdata = {
-	"amcc,acadia"
+	"amcc,acadia",
+	"amcc,haleakala",
+	"amcc,kilauea",
+	"amcc,makalu"
 };
 
 static int __init ppc40x_probe(void)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/virtex.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/virtex.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/40x/virtex.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/40x/virtex.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/xilinx_intc.h>
+#include <asm/xilinx_pci.h>
 #include <asm/ppc4xx.h>
 
 static struct of_device_id xilinx_of_bus_ids[] __initdata = {
@@ -47,6 +48,7 @@
 define_machine(virtex) {
 	.name			= "Xilinx Virtex",
 	.probe			= virtex_probe,
+	.setup_arch		= xilinx_pci_init,
 	.init_IRQ		= xilinx_intc_init_tree,
 	.get_irq		= xilinx_intc_get_irq,
 	.restart		= ppc4xx_reset_system,
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/Kconfig linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/Kconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -156,7 +156,7 @@
 #	  This option enables support for the IBM PPC440GX evaluation board.
 
 config XILINX_VIRTEX440_GENERIC_BOARD
-	bool "Generic Xilinx Virtex 440 board"
+	bool "Generic Xilinx Virtex 5 FXT board support"
 	depends on 44x
 	default n
 	select XILINX_VIRTEX_5_FXT
@@ -171,6 +171,17 @@
 	  Most Virtex 5 designs should use this unless it needs to do some
 	  special configuration at board probe time.
 
+config XILINX_ML510
+	bool "Xilinx ML510 extra support"
+	depends on XILINX_VIRTEX440_GENERIC_BOARD
+	select PPC_PCI_CHOICE
+	select XILINX_PCI if PCI
+	select PPC_INDIRECT_PCI if PCI
+	select PPC_I8259 if PCI
+	help
+	  This option enables extra support for features on the Xilinx ML510
+	  board.  The ML510 has a PCI bus with ALI south bridge.
+
 config PPC44x_SIMPLE
 	bool "Simple PowerPC 44x board support"
 	depends on 44x
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/Makefile linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,3 +4,4 @@
 obj-$(CONFIG_SAM440EP) 	+= sam440ep.o
 obj-$(CONFIG_WARP)	+= warp.o
 obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
+obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/virtex.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/virtex.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/virtex.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/virtex.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/xilinx_intc.h>
+#include <asm/xilinx_pci.h>
 #include <asm/reg.h>
 #include <asm/ppc4xx.h>
 #include "44x.h"
@@ -53,6 +54,7 @@
 define_machine(virtex) {
 	.name			= "Xilinx Virtex440",
 	.probe			= virtex_probe,
+	.setup_arch		= xilinx_pci_init,
 	.init_IRQ		= xilinx_intc_init_tree,
 	.get_irq		= xilinx_intc_get_irq,
 	.calibrate_decr		= generic_calibrate_decr,
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/virtex_ml510.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/virtex_ml510.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/virtex_ml510.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/virtex_ml510.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,29 @@
+#include <asm/i8259.h>
+#include <linux/pci.h>
+#include "44x.h"
+
+/**
+ * ml510_ail_quirk
+ */
+static void __devinit ml510_ali_quirk(struct pci_dev *dev)
+{
+	/* Enable the IDE controller */
+	pci_write_config_byte(dev, 0x58, 0x4c);
+	/* Assign irq 14 to the primary ide channel */
+	pci_write_config_byte(dev, 0x44, 0x0d);
+	/* Assign irq 15 to the secondary ide channel */
+	pci_write_config_byte(dev, 0x75, 0x0f);
+	/* Set the ide controller in native mode */
+	pci_write_config_byte(dev, 0x09, 0xff);
+
+	/* INTB = disabled, INTA = disabled */
+	pci_write_config_byte(dev, 0x48, 0x00);
+	/* INTD = disabled, INTC = disabled */
+	pci_write_config_byte(dev, 0x4a, 0x00);
+	/* Audio = INT7, Modem = disabled. */
+	pci_write_config_byte(dev, 0x4b, 0x60);
+	/* USB = INT7 */
+	pci_write_config_byte(dev, 0x74, 0x06);
+}
+DECLARE_PCI_FIXUP_EARLY(0x10b9, 0x1533, ml510_ali_quirk);
+
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/warp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/warp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/44x/warp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/44x/warp.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * PIKA Warp(tm) board specific routines
  *
- * Copyright (c) 2008 PIKA Technologies
+ * Copyright (c) 2008-2009 PIKA Technologies
  *   Sean MacLennan <smaclennan@pikatech.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -15,6 +15,8 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/of_gpio.h>
+#include <linux/of_i2c.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -23,6 +25,7 @@
 #include <asm/uic.h>
 #include <asm/ppc4xx.h>
 
+
 static __initdata struct of_device_id warp_of_bus[] = {
 	{ .compatible = "ibm,plb4", },
 	{ .compatible = "ibm,opb", },
@@ -41,7 +44,13 @@
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	return of_flat_dt_is_compatible(root, "pika,warp");
+	if (!of_flat_dt_is_compatible(root, "pika,warp"))
+		return 0;
+
+	/* For __dma_alloc_coherent */
+	ISA_DMA_THRESHOLD = ~0L;
+
+	return 1;
 }
 
 define_machine(warp) {
@@ -55,7 +64,6 @@
 };
 
 
-/* I am not sure this is the best place for this... */
 static int __init warp_post_info(void)
 {
 	struct device_node *np;
@@ -84,14 +92,13 @@
 
 	return 0;
 }
-machine_late_initcall(warp, warp_post_info);
 
 
 #ifdef CONFIG_SENSORS_AD7414
 
 static LIST_HEAD(dtm_shutdown_list);
 static void __iomem *dtm_fpga;
-static void __iomem *gpio_base;
+static unsigned green_led, red_led;
 
 
 struct dtm_shutdown {
@@ -134,14 +141,17 @@
 static irqreturn_t temp_isr(int irq, void *context)
 {
 	struct dtm_shutdown *shutdown;
+	int value = 1;
 
 	local_irq_disable();
 
+	gpio_set_value(green_led, 0);
+
 	/* Run through the shutdown list. */
 	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
 		shutdown->func(shutdown->arg);
 
-	printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n");
+	printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n\n");
 
 	while (1) {
 		if (dtm_fpga) {
@@ -149,59 +159,39 @@
 			out_be32(dtm_fpga + 0x14, reset);
 		}
 
-		if (gpio_base) {
-			unsigned leds = in_be32(gpio_base);
-
-			/* green off, red toggle */
-			leds &= ~0x80000000;
-			leds ^=  0x40000000;
-
-			out_be32(gpio_base, leds);
-		}
-
+		gpio_set_value(red_led, value);
+		value ^= 1;
 		mdelay(500);
 	}
+
+	/* Not reached */
+	return IRQ_HANDLED;
 }
 
 static int pika_setup_leds(void)
 {
-	struct device_node *np;
-	const u32 *gpios;
-	int len;
+	struct device_node *np, *child;
 
-	np = of_find_compatible_node(NULL, NULL, "linux,gpio-led");
+	np = of_find_compatible_node(NULL, NULL, "gpio-leds");
 	if (!np) {
-		printk(KERN_ERR __FILE__ ": Unable to find gpio-led\n");
-		return -ENOENT;
-	}
-
-	gpios = of_get_property(np, "gpios", &len);
-	of_node_put(np);
-	if (!gpios || len < 4) {
-		printk(KERN_ERR __FILE__
-		       ": Unable to get gpios property (%d)\n", len);
+		printk(KERN_ERR __FILE__ ": Unable to find leds\n");
 		return -ENOENT;
 	}
 
-	np = of_find_node_by_phandle(gpios[0]);
-	if (!np) {
-		printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
-		return -ENOENT;
-	}
+	for_each_child_of_node(np, child)
+		if (strcmp(child->name, "green") == 0)
+			green_led = of_get_gpio(child, 0);
+		else if (strcmp(child->name, "red") == 0)
+			red_led = of_get_gpio(child, 0);
 
-	gpio_base = of_iomap(np, 0);
 	of_node_put(np);
-	if (!gpio_base) {
-		printk(KERN_ERR __FILE__ ": Unable to map gpio");
-		return -ENOMEM;
-	}
 
 	return 0;
 }
 
-static void pika_setup_critical_temp(struct i2c_client *client)
+static void pika_setup_critical_temp(struct device_node *np,
+				     struct i2c_client *client)
 {
-	struct device_node *np;
 	int irq, rc;
 
 	/* Do this before enabling critical temp interrupt since we
@@ -213,14 +203,7 @@
 	i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
 	i2c_smbus_write_byte_data(client, 3,  0); /* Tlow */
 
-	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
-	if (np == NULL) {
-		printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
-		return;
-	}
-
 	irq = irq_of_parse_and_map(np, 0);
-	of_node_put(np);
 	if (irq  == NO_IRQ) {
 		printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
 		return;
@@ -249,32 +232,24 @@
 
 static int pika_dtm_thread(void __iomem *fpga)
 {
-	struct i2c_adapter *adap;
+	struct device_node *np;
 	struct i2c_client *client;
 
-	/* We loop in case either driver was compiled as a module and
-	 * has not been insmoded yet.
-	 */
-	while (!(adap = i2c_get_adapter(0))) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ);
-	}
-
-	while (1) {
-		list_for_each_entry(client, &adap->clients, list)
-			if (client->addr == 0x4a)
-				goto found_it;
+	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
+	if (np == NULL)
+		return -ENOENT;
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ);
+	client = of_find_i2c_device_by_node(np);
+	if (client == NULL) {
+		of_node_put(np);
+		return -ENOENT;
 	}
 
-found_it:
-	i2c_put_adapter(adap);
+	pika_setup_critical_temp(np, client);
 
-	pika_setup_critical_temp(client);
+	of_node_put(np);
 
-	printk(KERN_INFO "PIKA DTM thread running.\n");
+	printk(KERN_INFO "Warp DTM thread running.\n");
 
 	while (!kthread_should_stop()) {
 		int val;
@@ -296,7 +271,6 @@
 	return 0;
 }
 
-
 static int __init pika_dtm_start(void)
 {
 	struct task_struct *dtm_thread;
@@ -311,6 +285,9 @@
 	if (dtm_fpga == NULL)
 		return -ENOENT;
 
+	/* Must get post info before thread starts. */
+	warp_post_info();
+
 	dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
 	if (IS_ERR(dtm_thread)) {
 		iounmap(dtm_fpga);
@@ -333,6 +310,8 @@
 	return 0;
 }
 
+machine_late_initcall(warp, warp_post_info);
+
 #endif
 
 EXPORT_SYMBOL(pika_dtm_register_shutdown);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/512x/clock.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/512x/clock.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/512x/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/512x/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,7 +24,7 @@
 #include <linux/io.h>
 
 #include <linux/of_platform.h>
-#include <asm/mpc512x.h>
+#include <asm/mpc5xxx.h>
 #include <asm/clk_interface.h>
 
 #undef CLK_DEBUG
@@ -83,13 +83,13 @@
 	mutex_lock(&clocks_mutex);
 	printk(KERN_INFO "CLOCKS:\n");
 	list_for_each_entry(p, &clocks, node) {
-		printk(KERN_INFO "  %s %ld", p->name, p->rate);
+		pr_info("  %s=%ld", p->name, p->rate);
 		if (p->parent)
-			printk(KERN_INFO " %s %ld", p->parent->name,
+			pr_cont(" %s=%ld", p->parent->name,
 			       p->parent->rate);
 		if (p->flags & CLK_HAS_CTRL)
-			printk(KERN_INFO " reg/bit %d/%d", p->reg, p->bit);
-		printk("\n");
+			pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
+		pr_cont("\n");
 	}
 	mutex_unlock(&clocks_mutex);
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/512x/mpc512x.h linux-libre-2.6.31-gnu/arch/powerpc/platforms/512x/mpc512x.h
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/512x/mpc512x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/512x/mpc512x.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,6 @@
 
 #ifndef __MPC512X_H__
 #define __MPC512X_H__
-extern unsigned long mpc512x_find_ips_freq(struct device_node *node);
 extern void __init mpc512x_init_IRQ(void);
 void __init mpc512x_declare_of_platform_devices(void);
 #endif				/* __MPC512X_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/512x/mpc512x_shared.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,29 +24,6 @@
 
 #include "mpc512x.h"
 
-unsigned long
-mpc512x_find_ips_freq(struct device_node *node)
-{
-	struct device_node *np;
-	const unsigned int *p_ips_freq = NULL;
-
-	of_node_get(node);
-	while (node) {
-		p_ips_freq = of_get_property(node, "bus-frequency", NULL);
-		if (p_ips_freq)
-			break;
-
-		np = of_get_parent(node);
-		of_node_put(node);
-		node = np;
-	}
-	if (node)
-		of_node_put(node);
-
-	return p_ips_freq ? *p_ips_freq : 0;
-}
-EXPORT_SYMBOL(mpc512x_find_ips_freq);
-
 void __init mpc512x_init_IRQ(void)
 {
 	struct device_node *np;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/52xx/efika.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/52xx/efika.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/52xx/efika.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/52xx/efika.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,7 +34,7 @@
 static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 			    int len, u32 * val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
 	    | (hose->global_number << 24);
@@ -49,7 +49,7 @@
 static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
 			     int offset, int len, u32 val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 	    | (((bus->number - hose->first_busno) & 0xff) << 16)
 	    | (hose->global_number << 24);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/52xx/mpc52xx_common.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,36 +47,6 @@
 static struct mpc52xx_gpt __iomem *mpc52xx_wdt;
 static struct mpc52xx_cdm __iomem *mpc52xx_cdm;
 
-/**
- * 	mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
- * 	@node:	device node
- *
- * 	Returns IPB bus frequency, or 0 if the bus frequency cannot be found.
- */
-unsigned int
-mpc52xx_find_ipb_freq(struct device_node *node)
-{
-	struct device_node *np;
-	const unsigned int *p_ipb_freq = NULL;
-
-	of_node_get(node);
-	while (node) {
-		p_ipb_freq = of_get_property(node, "bus-frequency", NULL);
-		if (p_ipb_freq)
-			break;
-
-		np = of_get_parent(node);
-		of_node_put(node);
-		node = np;
-	}
-	if (node)
-		of_node_put(node);
-
-	return p_ipb_freq ? *p_ipb_freq : 0;
-}
-EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
-
-
 /*
  * Configure the XLB arbiter settings to match what Linux expects.
  */
@@ -221,7 +191,7 @@
 	if (!mpc52xx_cdm)
 		return 0;
 
-	freq = mpc52xx_find_ipb_freq(node);
+	freq = mpc5xxx_get_bus_frequency(node);
 	if (!freq)
 		return 0;
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/52xx/mpc52xx_pci.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/52xx/mpc52xx_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/52xx/mpc52xx_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/52xx/mpc52xx_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -107,7 +107,7 @@
 mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
 				int offset, int len, u32 *val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	u32 value;
 
 	if (ppc_md.pci_exclude_device)
@@ -164,7 +164,7 @@
 mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
 				int offset, int len, u32 val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	u32 value, mask;
 
 	if (ppc_md.pci_exclude_device)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/82xx/ep8248e.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/82xx/ep8248e.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/82xx/ep8248e.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/82xx/ep8248e.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
 #include <linux/mdio-bitbang.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
 #include <asm/io.h>
@@ -115,7 +116,7 @@
 	struct mii_bus *bus;
 	struct resource res;
 	struct device_node *node;
-	int ret, i;
+	int ret;
 
 	node = of_get_parent(ofdev->node);
 	of_node_put(node);
@@ -130,17 +131,13 @@
 	if (!bus)
 		return -ENOMEM;
 
-	bus->phy_mask = 0;
 	bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
 
-	for (i = 0; i < PHY_MAX_ADDR; i++)
-		bus->irq[i] = -1;
-
 	bus->name = "ep8248e-mdio-bitbang";
 	bus->parent = &ofdev->dev;
 	snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
 
-	return mdiobus_register(bus);
+	return of_mdiobus_register(bus, ofdev->node);
 }
 
 static int ep8248e_mdio_remove(struct of_device *ofdev)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/82xx/pq2ads.h linux-libre-2.6.31-gnu/arch/powerpc/platforms/82xx/pq2ads.h
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/82xx/pq2ads.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/82xx/pq2ads.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,10 +24,6 @@
 
 #include <linux/seq_file.h>
 
-/* Backword-compatibility stuff for the drivers */
-#define CPM_MAP_ADDR		((uint)0xf0000000)
-#define CPM_IRQ_OFFSET 0
-
 /* The ADS8260 has 16, 32-bit wide control/status registers, accessed
  * only on word boundaries.
  * Not all are used (yet), or are interesting to us (yet).
@@ -44,14 +40,5 @@
 #define BCSR3_FETHIEN2		((uint)0x10000000)      /* 0 == enable*/
 #define BCSR3_FETH2_RST		((uint)0x80000000)      /* 0 == reset */
 
-/* cpm serial driver works with constants below */
-
-#define SIU_INT_SMC1		((uint)0x04+CPM_IRQ_OFFSET)
-#define SIU_INT_SMC2		((uint)0x05+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC1		((uint)0x28+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC2		((uint)0x29+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC3		((uint)0x2a+CPM_IRQ_OFFSET)
-#define SIU_INT_SCC4		((uint)0x2b+CPM_IRQ_OFFSET)
-
 #endif /* __MACH_ADS8260_DEFS */
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c	2009-09-09 18:13:59.000000000 -0400
@@ -147,7 +147,7 @@
 		goto out;
 	}
 
-	priv = alloc_bootmem(sizeof(struct pq2ads_pci_pic));
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		of_node_put(np);
 		ret = -ENOMEM;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/Kconfig linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/Kconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -96,6 +96,13 @@
 	  This enables support for the Analogue & Micro ASP 83xx
 	  board.
 
+config KMETER1
+	bool "Keymile KMETER1"
+	select DEFAULT_UIMAGE
+	select QUICC_ENGINE
+	help
+	  This enables support for the Keymile KMETER1 board.
+
 
 endif
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/kmeter1.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/kmeter1.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/kmeter1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/kmeter1.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2008 DENX Software Engineering GmbH
+ * Author: Heiko Schocher <hs@denx.de>
+ *
+ * Description:
+ * Keymile KMETER1 board specific routines.
+ *
+ * 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+
+#include "mpc83xx.h"
+
+#define SVR_REV(svr)    (((svr) >>  0) & 0xFFFF) /* Revision field */
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init kmeter1_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("kmeter1_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
+		mpc83xx_add_bridge(np);
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+	qe_reset();
+
+	np = of_find_node_by_name(NULL, "par_io");
+	if (np != NULL) {
+		par_io_init(np);
+		of_node_put(np);
+
+		for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+			par_io_of_config(np);
+	}
+
+	np = of_find_compatible_node(NULL, "network", "ucc_geth");
+	if (np != NULL) {
+		uint svid;
+
+		/* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */
+		svid = mfspr(SPRN_SVR);
+		if (SVR_REV(svid) == 0x0021) {
+			struct	device_node *np_par;
+			struct	resource res;
+			void	__iomem *base;
+			int	ret;
+
+			np_par = of_find_node_by_name(NULL, "par_io");
+			if (np_par == NULL) {
+				printk(KERN_WARNING "%s couldn;t find par_io node\n",
+					__func__);
+				return;
+			}
+			/* Map Parallel I/O ports registers */
+			ret = of_address_to_resource(np_par, 0, &res);
+			if (ret) {
+				printk(KERN_WARNING "%s couldn;t map par_io registers\n",
+					__func__);
+				return;
+			}
+			base = ioremap(res.start, res.end - res.start + 1);
+
+			/*
+			 * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2)
+			 * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1)
+			 */
+			setbits32((base + 0xa8), 0x0c003000);
+
+			/*
+			 * IMMR + 0x14AC[20:27] = 10101010
+			 * (data delay for both UCC's)
+			 */
+			clrsetbits_be32((base + 0xac), 0xff0, 0xaa0);
+			iounmap(base);
+			of_node_put(np_par);
+		}
+		of_node_put(np);
+	}
+#endif				/* CONFIG_QUICC_ENGINE */
+}
+
+static struct of_device_id kmeter_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .compatible = "simple-bus", },
+	{ .type = "qe", },
+	{ .compatible = "fsl,qe", },
+	{},
+};
+
+static int __init kmeter_declare_of_platform_devices(void)
+{
+	/* Publish the QE devices */
+	of_platform_bus_probe(NULL, kmeter_ids, NULL);
+
+	return 0;
+}
+machine_device_initcall(kmeter1, kmeter_declare_of_platform_devices);
+
+static void __init kmeter1_init_IRQ(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,pq2pro-pic");
+	if (!np) {
+		np = of_find_node_by_type(NULL, "ipic");
+		if (!np)
+			return;
+	}
+
+	ipic_init(np, 0);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+	of_node_put(np);
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+	if (!np) {
+		np = of_find_node_by_type(NULL, "qeic");
+		if (!np)
+			return;
+	}
+	qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
+	of_node_put(np);
+#endif				/* CONFIG_QUICC_ENGINE */
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init kmeter1_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "keymile,KMETER1");
+}
+
+define_machine(kmeter1) {
+	.name		= "KMETER1",
+	.probe		= kmeter1_probe,
+	.setup_arch	= kmeter1_setup_arch,
+	.init_IRQ	= kmeter1_init_IRQ,
+	.get_irq	= ipic_get_irq,
+	.restart	= mpc83xx_restart,
+	.time_init	= mpc83xx_time_init,
+	.calibrate_decr	= generic_calibrate_decr,
+	.progress	= udbg_progress,
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/Makefile linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -15,3 +15,4 @@
 obj-$(CONFIG_SBC834x)		+= sbc834x.o
 obj-$(CONFIG_MPC837x_RDB)	+= mpc837x_rdb.o
 obj-$(CONFIG_ASP834x)		+= asp834x.o
+obj-$(CONFIG_KMETER1)		+= kmeter1.o
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/mpc83xx.h linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/mpc83xx.h
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/mpc83xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/mpc83xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,8 +22,8 @@
 /* system i/o configuration register low */
 #define MPC83XX_SICRL_OFFS         0x114
 #define MPC834X_SICRL_USB_MASK     0x60000000
-#define MPC834X_SICRL_USB0         0x40000000
-#define MPC834X_SICRL_USB1         0x20000000
+#define MPC834X_SICRL_USB0         0x20000000
+#define MPC834X_SICRL_USB1         0x40000000
 #define MPC831X_SICRL_USB_MASK     0x00000c00
 #define MPC831X_SICRL_USB_ULPI     0x00000800
 #define MPC8315_SICRL_USB_MASK     0x000000fc
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/usb.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/usb.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/83xx/usb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/83xx/usb.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,25 +47,25 @@
 		sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
 
 		prop = of_get_property(np, "phy_type", NULL);
+		port1_is_dr = 1;
 		if (prop && (!strcmp(prop, "utmi") ||
 					!strcmp(prop, "utmi_wide"))) {
 			sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
 			sicrh |= MPC834X_SICRH_USB_UTMI;
-			port1_is_dr = 1;
+			port0_is_dr = 1;
 		} else if (prop && !strcmp(prop, "serial")) {
 			dr_mode = of_get_property(np, "dr_mode", NULL);
 			if (dr_mode && !strcmp(dr_mode, "otg")) {
 				sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
-				port1_is_dr = 1;
+				port0_is_dr = 1;
 			} else {
-				sicrl |= MPC834X_SICRL_USB0;
+				sicrl |= MPC834X_SICRL_USB1;
 			}
 		} else if (prop && !strcmp(prop, "ulpi")) {
-			sicrl |= MPC834X_SICRL_USB0;
+			sicrl |= MPC834X_SICRL_USB1;
 		} else {
 			printk(KERN_WARNING "834x USB PHY type not supported\n");
 		}
-		port0_is_dr = 1;
 		of_node_put(np);
 	}
 	np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph");
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/Kconfig linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/Kconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -34,12 +34,15 @@
 	bool "Freescale MPC85xx MDS"
 	select DEFAULT_UIMAGE
 	select PHYLIB
+	select HAS_RAPIDIO
+	select SWIOTLB
 	help
 	  This option enables support for the MPC85xx MDS board
 
 config MPC8536_DS
 	bool "Freescale MPC8536 DS"
 	select DEFAULT_UIMAGE
+	select SWIOTLB
 	help
 	  This option enables support for the MPC8536 DS board
 
@@ -48,6 +51,7 @@
 	select PPC_I8259
 	select DEFAULT_UIMAGE
 	select FSL_ULI1575
+	select SWIOTLB
 	help
 	  This option enables support for the MPC85xx DS (MPC8544 DS) board
 
@@ -63,6 +67,16 @@
         help
           This option enables support for the Emerson KSI8560 board
 
+config XES_MPC85xx
+	bool "X-ES single-board computer"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the various single-board
+	  computers from Extreme Engineering Solutions (X-ES) based on
+	  Freescale MPC85xx processors.
+	  Manufacturer: Extreme Engineering Solutions, Inc.
+	  URL: <http://www.xes-inc.com/>
+
 config STX_GP3
 	bool "Silicon Turnkey Express GP3"
 	help
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/Makefile linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -15,3 +15,4 @@
 obj-$(CONFIG_SBC8548)     += sbc8548.o
 obj-$(CONFIG_SOCRATES)    += socrates.o socrates_fpga_pic.o
 obj-$(CONFIG_KSI8560)	  += ksi8560.o
+obj-$(CONFIG_XES_MPC85xx) += xes_mpc85xx.o
\ No newline at end of file
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/mpc8536_ds.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/mpc8536_ds.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/mpc8536_ds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/mpc8536_ds.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
+#include <linux/lmb.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -26,6 +27,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/mpic.h>
+#include <asm/swiotlb.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
@@ -65,7 +67,9 @@
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	struct pci_controller *hose;
 #endif
+	dma_addr_t max = 0xffffffff;
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc8536_ds_setup_arch()", 0);
@@ -80,11 +84,22 @@
 				fsl_add_bridge(np, 1);
 			else
 				fsl_add_bridge(np, 0);
+
+			hose = pci_find_hose_for_OF_device(np);
+			max = min(max, hose->dma_window_base_cur +
+					hose->dma_window_size);
 		}
 	}
 
 #endif
 
+#ifdef CONFIG_SWIOTLB
+	if (lmb_end_of_DRAM() > max) {
+		ppc_swiotlb_enable = 1;
+		set_pci_dma_ops(&swiotlb_pci_dma_ops);
+	}
+#endif
+
 	printk("MPC8536 DS board from Freescale Semiconductor\n");
 }
 
@@ -102,6 +117,8 @@
 }
 machine_device_initcall(mpc8536_ds, mpc8536_ds_publish_devices);
 
+machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier);
+
 /*
  * Called very early, device-tree isn't unflattened
  */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
+#include <linux/lmb.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -30,6 +31,7 @@
 #include <asm/udbg.h>
 #include <asm/mpic.h>
 #include <asm/i8259.h>
+#include <asm/swiotlb.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
@@ -155,7 +157,9 @@
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	struct pci_controller *hose;
 #endif
+	dma_addr_t max = 0xffffffff;
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
@@ -163,13 +167,18 @@
 #ifdef CONFIG_PCI
 	for_each_node_by_type(np, "pci") {
 		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
+		    of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
+		    of_device_is_compatible(np, "fsl,p2020-pcie")) {
 			struct resource rsrc;
 			of_address_to_resource(np, 0, &rsrc);
 			if ((rsrc.start & 0xfffff) == primary_phb_addr)
 				fsl_add_bridge(np, 1);
 			else
 				fsl_add_bridge(np, 0);
+
+			hose = pci_find_hose_for_OF_device(np);
+			max = min(max, hose->dma_window_base_cur +
+					hose->dma_window_size);
 		}
 	}
 
@@ -180,6 +189,13 @@
 	mpc85xx_smp_init();
 #endif
 
+#ifdef CONFIG_SWIOTLB
+	if (lmb_end_of_DRAM() > max) {
+		ppc_swiotlb_enable = 1;
+		set_pci_dma_ops(&swiotlb_pci_dma_ops);
+	}
+#endif
+
 	printk("MPC85xx DS board from Freescale Semiconductor\n");
 }
 
@@ -195,9 +211,9 @@
 		primary_phb_addr = 0xb000;
 #endif
 		return 1;
-	} else {
-		return 0;
 	}
+
+	return 0;
 }
 
 static struct of_device_id __initdata mpc85xxds_ids[] = {
@@ -214,6 +230,11 @@
 }
 machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices);
 machine_device_initcall(mpc8572_ds, mpc85xxds_publish_devices);
+machine_device_initcall(p2020_ds, mpc85xxds_publish_devices);
+
+machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
+machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
+machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier);
 
 /*
  * Called very early, device-tree isn't unflattened
@@ -227,9 +248,26 @@
 		primary_phb_addr = 0x8000;
 #endif
 		return 1;
-	} else {
-		return 0;
 	}
+
+	return 0;
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p2020_ds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "fsl,P2020DS")) {
+#ifdef CONFIG_PCI
+		primary_phb_addr = 0x9000;
+#endif
+		return 1;
+	}
+
+	return 0;
 }
 
 define_machine(mpc8544_ds) {
@@ -252,6 +290,20 @@
 	.setup_arch		= mpc85xx_ds_setup_arch,
 	.init_IRQ		= mpc85xx_ds_pic_init,
 #ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
+
+define_machine(p2020_ds) {
+	.name			= "P2020 DS",
+	.probe			= p2020_ds_probe,
+	.setup_arch		= mpc85xx_ds_setup_arch,
+	.init_IRQ		= mpc85xx_ds_pic_init,
+#ifdef CONFIG_PCI
 	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
 #endif
 	.get_irq		= mpic_get_irq,
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/mpc85xx_mds.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 #include <linux/phy.h>
+#include <linux/lmb.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -49,6 +50,7 @@
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
 #include <asm/mpic.h>
+#include <asm/swiotlb.h>
 
 #undef DEBUG
 #ifdef DEBUG
@@ -155,6 +157,10 @@
 {
 	struct device_node *np;
 	static u8 __iomem *bcsr_regs = NULL;
+#ifdef CONFIG_PCI
+	struct pci_controller *hose;
+#endif
+	dma_addr_t max = 0xffffffff;
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
@@ -179,6 +185,10 @@
 				fsl_add_bridge(np, 1);
 			else
 				fsl_add_bridge(np, 0);
+
+			hose = pci_find_hose_for_OF_device(np);
+			max = min(max, hose->dma_window_base_cur +
+					hose->dma_window_size);
 		}
 	}
 #endif
@@ -206,26 +216,47 @@
 	}
 
 	if (bcsr_regs) {
+		if (machine_is(mpc8568_mds)) {
 #define BCSR_UCC1_GETH_EN	(0x1 << 7)
 #define BCSR_UCC2_GETH_EN	(0x1 << 7)
 #define BCSR_UCC1_MODE_MSK	(0x3 << 4)
 #define BCSR_UCC2_MODE_MSK	(0x3 << 0)
 
-		/* Turn off UCC1 & UCC2 */
-		clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
-		clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
+			/* Turn off UCC1 & UCC2 */
+			clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
+			clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
 
-		/* Mode is RGMII, all bits clear */
-		clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
-					 BCSR_UCC2_MODE_MSK);
+			/* Mode is RGMII, all bits clear */
+			clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
+						 BCSR_UCC2_MODE_MSK);
 
-		/* Turn UCC1 & UCC2 on */
-		setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
-		setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
+			/* Turn UCC1 & UCC2 on */
+			setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
+			setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
+		} else if (machine_is(mpc8569_mds)) {
+#define BCSR7_UCC12_GETHnRST	(0x1 << 2)
+#define BCSR8_UEM_MARVELL_RST	(0x1 << 1)
+			/*
+			 * U-Boot mangles interrupt polarity for Marvell PHYs,
+			 * so reset built-in and UEM Marvell PHYs, this puts
+			 * the PHYs into their normal state.
+			 */
+			clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
+			setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
 
+			setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
+			clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
+		}
 		iounmap(bcsr_regs);
 	}
 #endif	/* CONFIG_QUICC_ENGINE */
+
+#ifdef CONFIG_SWIOTLB
+	if (lmb_end_of_DRAM() > max) {
+		ppc_swiotlb_enable = 1;
+		set_pci_dma_ops(&swiotlb_pci_dma_ops);
+	}
+#endif
 }
 
 
@@ -257,7 +288,8 @@
 
 	return 0;
 }
-machine_arch_initcall(mpc85xx_mds, board_fixups);
+machine_arch_initcall(mpc8568_mds, board_fixups);
+machine_arch_initcall(mpc8569_mds, board_fixups);
 
 static struct of_device_id mpc85xx_ids[] = {
 	{ .type = "soc", },
@@ -266,6 +298,7 @@
 	{ .type = "qe", },
 	{ .compatible = "fsl,qe", },
 	{ .compatible = "gianfar", },
+	{ .compatible = "fsl,rapidio-delta", },
 	{},
 };
 
@@ -276,7 +309,11 @@
 
 	return 0;
 }
-machine_device_initcall(mpc85xx_mds, mpc85xx_publish_devices);
+machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
+machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
+
+machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
+machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
 
 static void __init mpc85xx_mds_pic_init(void)
 {
@@ -321,12 +358,33 @@
         return of_flat_dt_is_compatible(root, "MPC85xxMDS");
 }
 
-define_machine(mpc85xx_mds) {
-	.name		= "MPC85xx MDS",
+define_machine(mpc8568_mds) {
+	.name		= "MPC8568 MDS",
 	.probe		= mpc85xx_mds_probe,
 	.setup_arch	= mpc85xx_mds_setup_arch,
 	.init_IRQ	= mpc85xx_mds_pic_init,
 	.get_irq	= mpic_get_irq,
+	.restart	= fsl_rstcr_restart,
+	.calibrate_decr	= generic_calibrate_decr,
+	.progress	= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+};
+
+static int __init mpc8569_mds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS");
+}
+
+define_machine(mpc8569_mds) {
+	.name		= "MPC8569 MDS",
+	.probe		= mpc8569_mds_probe,
+	.setup_arch	= mpc85xx_mds_setup_arch,
+	.init_IRQ	= mpc85xx_mds_pic_init,
+	.get_irq	= mpic_get_irq,
 	.restart	= fsl_rstcr_restart,
 	.calibrate_decr	= generic_calibrate_decr,
 	.progress	= udbg_progress,
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/smp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,20 +52,19 @@
 
 	pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
 
-	local_irq_save(flags);
-
 	np = of_get_cpu_node(nr, NULL);
 	cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
 
 	if (cpu_rel_addr == NULL) {
 		printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr);
-		local_irq_restore(flags);
 		return;
 	}
 
 	/* Map the spin table */
 	bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY);
 
+	local_irq_save(flags);
+
 	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
 	out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
@@ -73,10 +72,10 @@
 	while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
 		mdelay(1);
 
-	iounmap(bptr_vaddr);
-
 	local_irq_restore(flags);
 
+	iounmap(bptr_vaddr);
+
 	pr_debug("waited %d msecs for CPU #%d.\n", n, nr);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/socrates.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/socrates.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/socrates.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/socrates.c	2009-09-09 18:13:59.000000000 -0400
@@ -102,10 +102,11 @@
 	{},
 };
 
-static void __init socrates_init(void)
+static int __init socrates_publish_devices(void)
 {
-	of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
+	return of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
 }
+machine_device_initcall(socrates, socrates_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
@@ -124,7 +125,6 @@
 	.name			= "Socrates",
 	.probe			= socrates_probe,
 	.setup_arch		= socrates_setup_arch,
-	.init			= socrates_init,
 	.init_IRQ		= socrates_pic_init,
 	.get_irq		= mpic_get_irq,
 	.restart		= fsl_rstcr_restart,
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/xes_mpc85xx.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/xes_mpc85xx.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/85xx/xes_mpc85xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/85xx/xes_mpc85xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2009 Extreme Engineering Solutions, Inc.
+ *
+ * X-ES board-specific functionality
+ *
+ * Based on mpc85xx_ds code from Freescale Semiconductor, Inc.
+ *
+ * Author: Nate Case <ncase@xes-inc.com>
+ *
+ * This 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.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+/* A few bit definitions needed for fixups on some boards */
+#define MPC85xx_L2CTL_L2E		0x80000000 /* L2 enable */
+#define MPC85xx_L2CTL_L2I		0x40000000 /* L2 flash invalidate */
+#define MPC85xx_L2CTL_L2SIZ_MASK	0x30000000 /* L2 SRAM size (R/O) */
+
+void __init xes_mpc85xx_pic_init(void)
+{
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "open-pic");
+	if (np == NULL) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Failed to map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+
+	mpic = mpic_alloc(np, r.start,
+			  MPIC_PRIMARY | MPIC_WANTS_RESET |
+			  MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
+			0, 256, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
+	of_node_put(np);
+
+	mpic_init(mpic);
+}
+
+static void xes_mpc85xx_configure_l2(void __iomem *l2_base)
+{
+	volatile uint32_t ctl, tmp;
+
+	asm volatile("msync; isync");
+	tmp = in_be32(l2_base);
+
+	/*
+	 * xMon may have enabled part of L2 as SRAM, so we need to set it
+	 * up for all cache mode just to be safe.
+	 */
+	printk(KERN_INFO "xes_mpc85xx: Enabling L2 as cache\n");
+
+	ctl = MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2I;
+	if (machine_is_compatible("MPC8540") ||
+	    machine_is_compatible("MPC8560"))
+		/*
+		 * Assume L2 SRAM is used fully for cache, so set
+		 * L2BLKSZ (bits 4:5) to match L2SIZ (bits 2:3).
+		 */
+		ctl |= (tmp & MPC85xx_L2CTL_L2SIZ_MASK) >> 2;
+
+	asm volatile("msync; isync");
+	out_be32(l2_base, ctl);
+	asm volatile("msync; isync");
+}
+
+static void xes_mpc85xx_fixups(void)
+{
+	struct device_node *np;
+	int err;
+
+	/*
+	 * Legacy xMon firmware on some X-ES boards does not enable L2
+	 * as cache.  We must ensure that they get enabled here.
+	 */
+	for_each_node_by_name(np, "l2-cache-controller") {
+		struct resource r[2];
+		void __iomem *l2_base;
+
+		/* Only MPC8548, MPC8540, and MPC8560 boards are affected */
+		if (!of_device_is_compatible(np,
+				    "fsl,mpc8548-l2-cache-controller") &&
+		    !of_device_is_compatible(np,
+				    "fsl,mpc8540-l2-cache-controller") &&
+		    !of_device_is_compatible(np,
+				    "fsl,mpc8560-l2-cache-controller"))
+			continue;
+
+		err = of_address_to_resource(np, 0, &r[0]);
+		if (err) {
+			printk(KERN_WARNING "xes_mpc85xx: Could not get "
+			       "resource for device tree node '%s'",
+			       np->full_name);
+			continue;
+		}
+
+		l2_base = ioremap(r[0].start, r[0].end - r[0].start + 1);
+
+		xes_mpc85xx_configure_l2(l2_base);
+	}
+}
+
+#ifdef CONFIG_PCI
+static int primary_phb_addr;
+#endif
+
+/*
+ * Setup the architecture
+ */
+#ifdef CONFIG_SMP
+extern void __init mpc85xx_smp_init(void);
+#endif
+static void __init xes_mpc85xx_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
+	struct device_node *root;
+	const char *model = "Unknown";
+
+	root = of_find_node_by_path("/");
+	if (root == NULL)
+		return;
+
+	model = of_get_property(root, "model", NULL);
+
+	printk(KERN_INFO "X-ES MPC85xx-based single-board computer: %s\n",
+	       model + strlen("xes,"));
+
+	xes_mpc85xx_fixups();
+
+#ifdef CONFIG_PCI
+	for_each_node_by_type(np, "pci") {
+		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
+		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
+			struct resource rsrc;
+			of_address_to_resource(np, 0, &rsrc);
+			if ((rsrc.start & 0xfffff) == primary_phb_addr)
+				fsl_add_bridge(np, 1);
+			else
+				fsl_add_bridge(np, 0);
+		}
+	}
+#endif
+
+#ifdef CONFIG_SMP
+	mpc85xx_smp_init();
+#endif
+}
+
+static struct of_device_id __initdata xes_mpc85xx_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
+	{},
+};
+
+static int __init xes_mpc85xx_publish_devices(void)
+{
+	return of_platform_bus_probe(NULL, xes_mpc85xx_ids, NULL);
+}
+machine_device_initcall(xes_mpc8572, xes_mpc85xx_publish_devices);
+machine_device_initcall(xes_mpc8548, xes_mpc85xx_publish_devices);
+machine_device_initcall(xes_mpc8540, xes_mpc85xx_publish_devices);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init xes_mpc8572_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "xes,MPC8572")) {
+#ifdef CONFIG_PCI
+		primary_phb_addr = 0x8000;
+#endif
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+static int __init xes_mpc8548_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "xes,MPC8548")) {
+#ifdef CONFIG_PCI
+		primary_phb_addr = 0xb000;
+#endif
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+static int __init xes_mpc8540_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "xes,MPC8540")) {
+#ifdef CONFIG_PCI
+		primary_phb_addr = 0xb000;
+#endif
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+define_machine(xes_mpc8572) {
+	.name			= "X-ES MPC8572",
+	.probe			= xes_mpc8572_probe,
+	.setup_arch		= xes_mpc85xx_setup_arch,
+	.init_IRQ		= xes_mpc85xx_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
+
+define_machine(xes_mpc8548) {
+	.name			= "X-ES MPC8548",
+	.probe			= xes_mpc8548_probe,
+	.setup_arch		= xes_mpc85xx_setup_arch,
+	.init_IRQ		= xes_mpc85xx_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
+
+define_machine(xes_mpc8540) {
+	.name			= "X-ES MPC8540",
+	.probe			= xes_mpc8540_probe,
+	.setup_arch		= xes_mpc85xx_setup_arch,
+	.init_IRQ		= xes_mpc85xx_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/gef_ppc9a.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/gef_ppc9a.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/gef_ppc9a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/gef_ppc9a.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,6 @@
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
 #include <asm/prom.h>
 #include <mm/mmu_decl.h>
 #include <asm/udbg.h>
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/gef_sbc310.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/gef_sbc310.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/gef_sbc310.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/gef_sbc310.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,6 @@
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
 #include <asm/prom.h>
 #include <mm/mmu_decl.h>
 #include <asm/udbg.h>
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/gef_sbc610.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/gef_sbc610.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/gef_sbc610.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/gef_sbc610.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,6 @@
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
 #include <asm/prom.h>
 #include <mm/mmu_decl.h>
 #include <asm/udbg.h>
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/Kconfig linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/Kconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 	select DEFAULT_UIMAGE
 	select FSL_ULI1575
 	select HAS_RAPIDIO
+	select SWIOTLB
 	help
 	  This option enables support for the MPC8641 HPCN board.
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/mpc8610_hpcd.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,6 @@
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
 #include <asm/prom.h>
 #include <mm/mmu_decl.h>
 #include <asm/udbg.h>
@@ -38,6 +37,7 @@
 #include <linux/of_platform.h>
 #include <sysdev/fsl_pci.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/simple_gpio.h>
 
 #include "mpc86xx.h"
 
@@ -52,6 +52,9 @@
 
 static int __init mpc8610_declare_of_platform_devices(void)
 {
+	/* Firstly, register PIXIS GPIOs. */
+	simple_gpiochip_init("fsl,fpga-pixis-gpio-bank");
+
 	/* Without this call, the SSI device driver won't get probed. */
 	of_platform_bus_probe(NULL, mpc8610_ids, NULL);
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,15 +19,16 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
+#include <linux/lmb.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
 #include <asm/prom.h>
 #include <mm/mmu_decl.h>
 #include <asm/udbg.h>
+#include <asm/swiotlb.h>
 
 #include <asm/mpic.h>
 
@@ -71,7 +72,9 @@
 {
 #ifdef CONFIG_PCI
 	struct device_node *np;
+	struct pci_controller *hose;
 #endif
+	dma_addr_t max = 0xffffffff;
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
@@ -84,6 +87,9 @@
 			fsl_add_bridge(np, 1);
 		else
 			fsl_add_bridge(np, 0);
+		hose = pci_find_hose_for_OF_device(np);
+		max = min(max, hose->dma_window_base_cur +
+			  hose->dma_window_size);
 	}
 
 	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
@@ -95,6 +101,13 @@
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
 #endif
+
+#ifdef CONFIG_SWIOTLB
+	if (lmb_end_of_DRAM() > max) {
+		ppc_swiotlb_enable = 1;
+		set_pci_dma_ops(&swiotlb_pci_dma_ops);
+	}
+#endif
 }
 
 
@@ -159,6 +172,7 @@
 	return 0;
 }
 machine_device_initcall(mpc86xx_hpcn, declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcn, swiotlb_setup_bus_notifier);
 
 define_machine(mpc86xx_hpcn) {
 	.name			= "MPC86xx HPCN",
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/mpc86xx_smp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/mpc86xx_smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/mpc86xx_smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/mpc86xx_smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,7 +20,6 @@
 #include <asm/pgtable.h>
 #include <asm/pci-bridge.h>
 #include <asm/mpic.h>
-#include <asm/mpc86xx.h>
 #include <asm/cacheflush.h>
 
 #include <sysdev/fsl_soc.h>
@@ -30,6 +29,11 @@
 extern void __secondary_start_mpc86xx(void);
 extern unsigned long __secondary_hold_acknowledge;
 
+#define MCM_PORT_CONFIG_OFFSET	0x10
+
+/* Offset from CCSRBAR */
+#define MPC86xx_MCM_OFFSET      (0x1000)
+#define MPC86xx_MCM_SIZE        (0x1000)
 
 static void __init
 smp_86xx_release_core(int nr)
@@ -48,6 +52,8 @@
 	pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));
 	pcr |= 1 << (nr + 24);
 	out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);
+
+	iounmap(mcm_vaddr);
 }
 
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/sbc8641d.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/sbc8641d.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/86xx/sbc8641d.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/86xx/sbc8641d.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,6 @@
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
 #include <asm/prom.h>
 #include <mm/mmu_decl.h>
 #include <asm/udbg.h>
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/8xx/mpc885ads.h linux-libre-2.6.31-gnu/arch/powerpc/platforms/8xx/mpc885ads.h
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/8xx/mpc885ads.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/8xx/mpc885ads.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,10 +17,6 @@
 
 #include <sysdev/fsl_soc.h>
 
-#define MPC8xx_CPM_OFFSET	(0x9c0)
-#define CPM_MAP_ADDR		(get_immrbase() + MPC8xx_CPM_OFFSET)
-#define CPM_IRQ_OFFSET		16     // for compability with cpm_uart driver
-
 /* Bits of interest in the BCSRs.
  */
 #define BCSR1_ETHEN		((uint)0x20000000)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/axon_msi.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/axon_msi.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/axon_msi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/axon_msi.c	2009-09-09 18:13:59.000000000 -0400
@@ -85,7 +85,7 @@
 
 static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
 {
-	pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
+	pr_devel("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
 
 	dcr_write(msic->dcr_host, dcr_n, val);
 }
@@ -98,7 +98,7 @@
 	int retry = 0;
 
 	write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
-	pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
+	pr_devel("axon_msi: original write_offset 0x%x\n", write_offset);
 
 	/* write_offset doesn't wrap properly, so we have to mask it */
 	write_offset &= MSIC_FIFO_SIZE_MASK;
@@ -108,7 +108,7 @@
 		msi  = le32_to_cpu(msic->fifo_virt[idx]);
 		msi &= 0xFFFF;
 
-		pr_debug("axon_msi: woff %x roff %x msi %x\n",
+		pr_devel("axon_msi: woff %x roff %x msi %x\n",
 			  write_offset, msic->read_offset, msi);
 
 		if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) {
@@ -123,12 +123,12 @@
 			 */
 			udelay(1);
 			retry++;
-			pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
+			pr_devel("axon_msi: invalid irq 0x%x!\n", msi);
 			continue;
 		}
 
 		if (retry) {
-			pr_debug("axon_msi: late irq 0x%x, retry %d\n",
+			pr_devel("axon_msi: late irq 0x%x, retry %d\n",
 				 msi, retry);
 			retry = 0;
 		}
@@ -329,10 +329,10 @@
 
 static int axon_msi_shutdown(struct of_device *device)
 {
-	struct axon_msic *msic = device->dev.platform_data;
+	struct axon_msic *msic = dev_get_drvdata(&device->dev);
 	u32 tmp;
 
-	pr_debug("axon_msi: disabling %s\n",
+	pr_devel("axon_msi: disabling %s\n",
 		  msic->irq_host->of_node->full_name);
 	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
@@ -349,7 +349,7 @@
 	unsigned int virq;
 	int dcr_base, dcr_len;
 
-	pr_debug("axon_msi: setting up dn %s\n", dn->full_name);
+	pr_devel("axon_msi: setting up dn %s\n", dn->full_name);
 
 	msic = kzalloc(sizeof(struct axon_msic), GFP_KERNEL);
 	if (!msic) {
@@ -403,7 +403,7 @@
 
 	set_irq_data(virq, msic);
 	set_irq_chained_handler(virq, axon_msi_cascade);
-	pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
+	pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq);
 
 	/* Enable the MSIC hardware */
 	msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
@@ -416,7 +416,7 @@
 	msic->read_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG)
 				& MSIC_FIFO_SIZE_MASK;
 
-	device->dev.platform_data = msic;
+	dev_set_drvdata(&device->dev, msic);
 
 	ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
 	ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
@@ -484,13 +484,13 @@
 
 	addr = of_translate_address(dn, of_get_property(dn, "reg", NULL));
 	if (addr == OF_BAD_ADDR) {
-		pr_debug("axon_msi: couldn't translate reg property\n");
+		pr_devel("axon_msi: couldn't translate reg property\n");
 		return;
 	}
 
 	msic->trigger = ioremap(addr, 0x4);
 	if (!msic->trigger) {
-		pr_debug("axon_msi: ioremap failed\n");
+		pr_devel("axon_msi: ioremap failed\n");
 		return;
 	}
 
@@ -498,7 +498,7 @@
 
 	if (!debugfs_create_file(name, 0600, powerpc_debugfs_root,
 				 msic, &fops_msic)) {
-		pr_debug("axon_msi: debugfs_create_file failed!\n");
+		pr_devel("axon_msi: debugfs_create_file failed!\n");
 		return;
 	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/celleb_pci.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/celleb_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/celleb_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/celleb_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -162,8 +162,7 @@
 		unsigned int devfn, int where, int size, u32 *val)
 {
 	char *config;
-	struct device_node *node;
-	struct pci_controller *hose;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	unsigned int devno = devfn >> 3;
 	unsigned int fn = devfn & 0x7;
 
@@ -171,8 +170,6 @@
 	BUG_ON(where % size);
 
 	pr_debug("    fake read: bus=0x%x, ", bus->number);
-	node = (struct device_node *)bus->sysdata;
-	hose = pci_find_hose_for_OF_device(node);
 	config = get_fake_config_start(hose, devno, fn);
 
 	pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size);
@@ -192,8 +189,7 @@
 		unsigned int devfn, int where, int size, u32 val)
 {
 	char *config;
-	struct device_node *node;
-	struct pci_controller *hose;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct celleb_pci_resource *res;
 	unsigned int devno = devfn >> 3;
 	unsigned int fn = devfn & 0x7;
@@ -201,8 +197,6 @@
 	/* allignment check */
 	BUG_ON(where % size);
 
-	node = (struct device_node *)bus->sysdata;
-	hose = pci_find_hose_for_OF_device(node);
 	config = get_fake_config_start(hose, devno, fn);
 
 	if (!config)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/celleb_scc_epci.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/celleb_scc_epci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/celleb_scc_epci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/celleb_scc_epci.c	2009-09-09 18:13:59.000000000 -0400
@@ -134,15 +134,11 @@
 {
 	PCI_IO_ADDR epci_base;
 	PCI_IO_ADDR addr;
-	struct device_node *node;
-	struct pci_controller *hose;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 
 	/* allignment check */
 	BUG_ON(where % size);
 
-	node = (struct device_node *)bus->sysdata;
-	hose = pci_find_hose_for_OF_device(node);
-
 	if (!celleb_epci_get_epci_cfg(hose))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -198,16 +194,11 @@
 {
 	PCI_IO_ADDR epci_base;
 	PCI_IO_ADDR addr;
-	struct device_node *node;
-	struct pci_controller *hose;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 
 	/* allignment check */
 	BUG_ON(where % size);
 
-	node = (struct device_node *)bus->sysdata;
-	hose = pci_find_hose_for_OF_device(node);
-
-
 	if (!celleb_epci_get_epci_cfg(hose))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/celleb_scc_pciex.c	2009-09-09 18:13:59.000000000 -0400
@@ -366,11 +366,7 @@
 static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
 				 int where, int size, unsigned int *val)
 {
-	struct device_node *dn;
-	struct pci_controller *phb;
-
-	dn = bus->sysdata;
-	phb = pci_find_hose_for_OF_device(dn);
+	struct pci_controller *phb = pci_bus_to_host(bus);
 
 	if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) {
 		*val = ~0;
@@ -389,11 +385,7 @@
 static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
 				  int where, int size, unsigned int val)
 {
-	struct device_node *dn;
-	struct pci_controller *phb;
-
-	dn = bus->sysdata;
-	phb = pci_find_hose_for_OF_device(dn);
+	struct pci_controller *phb = pci_bus_to_host(bus);
 
 	if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1)
 		return PCIBIOS_DEVICE_NOT_FOUND;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/iommu.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/iommu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/iommu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -100,16 +100,6 @@
 #define IOSTE_PS_1M		0x0000000000000005ul /*   - 1MB  */
 #define IOSTE_PS_16M		0x0000000000000007ul /*   - 16MB */
 
-/* Page table entries */
-#define IOPTE_PP_W		0x8000000000000000ul /* protection: write */
-#define IOPTE_PP_R		0x4000000000000000ul /* protection: read */
-#define IOPTE_M			0x2000000000000000ul /* coherency required */
-#define IOPTE_SO_R		0x1000000000000000ul /* ordering: writes */
-#define IOPTE_SO_RW             0x1800000000000000ul /* ordering: r & w */
-#define IOPTE_RPN_Mask		0x07fffffffffff000ul /* RPN */
-#define IOPTE_H			0x0000000000000800ul /* cache hint */
-#define IOPTE_IOID_Mask		0x00000000000007fful /* ioid */
-
 
 /* IOMMU sizing */
 #define IO_SEGMENT_SHIFT	28
@@ -193,19 +183,21 @@
 	 */
 	const unsigned long prot = 0xc48;
 	base_pte =
-		((prot << (52 + 4 * direction)) & (IOPTE_PP_W | IOPTE_PP_R))
-		| IOPTE_M | IOPTE_SO_RW | (window->ioid & IOPTE_IOID_Mask);
+		((prot << (52 + 4 * direction)) &
+		 (CBE_IOPTE_PP_W | CBE_IOPTE_PP_R)) |
+		CBE_IOPTE_M | CBE_IOPTE_SO_RW |
+		(window->ioid & CBE_IOPTE_IOID_Mask);
 #else
-	base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW |
-		(window->ioid & IOPTE_IOID_Mask);
+	base_pte = CBE_IOPTE_PP_W | CBE_IOPTE_PP_R | CBE_IOPTE_M |
+		CBE_IOPTE_SO_RW | (window->ioid & CBE_IOPTE_IOID_Mask);
 #endif
 	if (unlikely(dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs)))
-		base_pte &= ~IOPTE_SO_RW;
+		base_pte &= ~CBE_IOPTE_SO_RW;
 
 	io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
 
 	for (i = 0; i < npages; i++, uaddr += IOMMU_PAGE_SIZE)
-		io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask);
+		io_pte[i] = base_pte | (__pa(uaddr) & CBE_IOPTE_RPN_Mask);
 
 	mb();
 
@@ -231,8 +223,9 @@
 #else
 	/* spider bridge does PCI reads after freeing - insert a mapping
 	 * to a scratch page instead of an invalid entry */
-	pte = IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | __pa(window->iommu->pad_page)
-		| (window->ioid & IOPTE_IOID_Mask);
+	pte = CBE_IOPTE_PP_R | CBE_IOPTE_M | CBE_IOPTE_SO_RW |
+		__pa(window->iommu->pad_page) |
+		(window->ioid & CBE_IOPTE_IOID_Mask);
 #endif
 
 	io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
@@ -1001,7 +994,7 @@
 	pr_debug("iommu: addr %lx ptab %p segment %lx offset %lx\n",
 		  addr, ptab, segment, offset);
 
-	ptab[offset] = base_pte | (__pa(addr) & IOPTE_RPN_Mask);
+	ptab[offset] = base_pte | (__pa(addr) & CBE_IOPTE_RPN_Mask);
 }
 
 static void cell_iommu_setup_fixed_ptab(struct cbe_iommu *iommu,
@@ -1016,14 +1009,14 @@
 
 	pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
 
-	base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M
-		    | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
+	base_pte = CBE_IOPTE_PP_W | CBE_IOPTE_PP_R | CBE_IOPTE_M |
+		(cell_iommu_get_ioid(np) & CBE_IOPTE_IOID_Mask);
 
 	if (iommu_fixed_is_weak)
 		pr_info("IOMMU: Using weak ordering for fixed mapping\n");
 	else {
 		pr_info("IOMMU: Using strong ordering for fixed mapping\n");
-		base_pte |= IOPTE_SO_RW;
+		base_pte |= CBE_IOPTE_SO_RW;
 	}
 
 	for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/ras.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/ras.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/ras.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/ras.c	2009-09-09 18:13:59.000000000 -0400
@@ -122,8 +122,8 @@
 
 	area->nid = nid;
 	area->order = order;
-	area->pages = alloc_pages_node(area->nid, GFP_KERNEL | GFP_THISNODE,
-					area->order);
+	area->pages = alloc_pages_exact_node(area->nid, GFP_KERNEL|GFP_THISNODE,
+						area->order);
 
 	if (!area->pages) {
 		printk(KERN_WARNING "%s: no page on node %d\n",
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/smp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,6 @@
 #include <asm/prom.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
@@ -140,31 +139,6 @@
 	mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
 }
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase = 0;
-
-static void __devinit cell_give_timebase(void)
-{
-	spin_lock(&timebase_lock);
-	rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-	timebase = get_tb();
-	spin_unlock(&timebase_lock);
-
-	while (timebase)
-		barrier();
-	rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-static void __devinit cell_take_timebase(void)
-{
-	while (!timebase)
-		barrier();
-	spin_lock(&timebase_lock);
-	set_tb(timebase >> 32, timebase & 0xffffffff);
-	timebase = 0;
-	spin_unlock(&timebase_lock);
-}
-
 static void __devinit smp_cell_kick_cpu(int nr)
 {
 	BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -224,8 +198,8 @@
 
 	/* Non-lpar has additional take/give timebase */
 	if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
-		smp_ops->give_timebase = cell_give_timebase;
-		smp_ops->take_timebase = cell_take_timebase;
+		smp_ops->give_timebase = rtas_give_timebase;
+		smp_ops->take_timebase = rtas_take_timebase;
 	}
 
 	DBG(" <- smp_init_cell()\n");
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/spu_base.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/spu_base.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/spu_base.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/spu_base.c	2009-09-09 18:13:59.000000000 -0400
@@ -752,17 +752,8 @@
 		goto out_unregister_sysdev_class;
 	}
 
-	if (ret > 0) {
-		/*
-		 * We cannot put the forward declaration in
-		 * <linux/linux_logo.h> because of conflicting session type
-		 * conflicts for const and __initdata with different compiler
-		 * versions
-		 */
-		extern const struct linux_logo logo_spe_clut224;
-
+	if (ret > 0)
 		fb_append_extra_logo(&logo_spe_clut224, ret);
-	}
 
 	mutex_lock(&spu_full_list_mutex);
 	xmon_register_spus(&spu_full_list);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/spu_fault.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/spu_fault.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/spu_fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/spu_fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 	}
 
 	ret = 0;
-	*flt = handle_mm_fault(mm, vma, ea, is_write);
+	*flt = handle_mm_fault(mm, vma, ea, is_write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(*flt & VM_FAULT_ERROR)) {
 		if (*flt & VM_FAULT_OOM) {
 			ret = -ENOMEM;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/spufs/inode.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/spufs/inode.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/cell/spufs/inode.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/cell/spufs/inode.c	2009-09-09 18:13:59.000000000 -0400
@@ -631,10 +631,6 @@
 	if (IS_ERR(dentry))
 		goto out_dir;
 
-	ret = -EEXIST;
-	if (dentry->d_inode)
-		goto out_dput;
-
 	mode &= ~current_umask();
 
 	if (flags & SPU_CREATE_GANG)
@@ -648,8 +644,6 @@
 		fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
 	return ret;
 
-out_dput:
-	dput(dentry);
 out_dir:
 	mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
 out:
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/chrp/pci.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/chrp/pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/chrp/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/chrp/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,7 +34,7 @@
 			   int len, u32 *val)
 {
 	volatile void __iomem *cfg_data;
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 
 	if (bus->number > 7)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -61,7 +61,7 @@
 			    int len, u32 val)
 {
 	volatile void __iomem *cfg_data;
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 
 	if (bus->number > 7)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -96,7 +96,7 @@
 int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		     int len, u32 *val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 		| (((bus->number - hose->first_busno) & 0xff) << 16)
 		| (hose->global_number << 24);
@@ -111,7 +111,7 @@
 int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		      int len, u32 val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
 		| (((bus->number - hose->first_busno) & 0xff) << 16)
 		| (hose->global_number << 24);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/chrp/smp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/chrp/smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/chrp/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/chrp/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/mpic.h>
 #include <asm/rtas.h>
@@ -42,40 +41,12 @@
 	mpic_setup_this_cpu();
 }
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned int timebase_upper = 0, timebase_lower = 0;
-
-void __devinit smp_chrp_give_timebase(void)
-{
-	spin_lock(&timebase_lock);
-	rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-	timebase_upper = get_tbu();
-	timebase_lower = get_tbl();
-	spin_unlock(&timebase_lock);
-
-	while (timebase_upper || timebase_lower)
-		barrier();
-	rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-void __devinit smp_chrp_take_timebase(void)
-{
-	while (!(timebase_upper || timebase_lower))
-		barrier();
-	spin_lock(&timebase_lock);
-	set_tb(timebase_upper, timebase_lower);
-	timebase_upper = 0;
-	timebase_lower = 0;
-	spin_unlock(&timebase_lock);
-	printk("CPU %i taken timebase\n", smp_processor_id());
-}
-
 /* CHRP with openpic */
 struct smp_ops_t chrp_smp_ops = {
 	.message_pass = smp_mpic_message_pass,
 	.probe = smp_mpic_probe,
 	.kick_cpu = smp_chrp_kick_cpu,
 	.setup_cpu = smp_chrp_setup_cpu,
-	.give_timebase = smp_chrp_give_timebase,
-	.take_timebase = smp_chrp_take_timebase,
+	.give_timebase = rtas_give_timebase,
+	.take_timebase = rtas_take_timebase,
 };
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/fsl_uli1575.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/fsl_uli1575.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/fsl_uli1575.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/fsl_uli1575.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,13 +51,20 @@
 	ULI_8259_NONE,		/* PIRQH */
 };
 
+static inline bool is_quirk_valid(void)
+{
+	return (machine_is(mpc86xx_hpcn) ||
+		machine_is(mpc8544_ds) ||
+		machine_is(p2020_ds) ||
+		machine_is(mpc8572_ds));
+}
+
 /* Bridge */
 static void __devinit early_uli5249(struct pci_dev *dev)
 {
 	unsigned char temp;
 
-	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
-			!machine_is(mpc8572_ds))
+	if (!is_quirk_valid())
 		return;
 
 	pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO |
@@ -80,8 +87,7 @@
 {
 	int i;
 
-	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
-			!machine_is(mpc8572_ds))
+	if (!is_quirk_valid())
 		return;
 
 	/*
@@ -149,8 +155,7 @@
 	 * IRQ 14: Edge
 	 * IRQ 15: Edge
 	 */
-	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
-			!machine_is(mpc8572_ds))
+	if (!is_quirk_valid())
 		return;
 
 	outb(0xfa, 0x4d0);
@@ -176,8 +181,7 @@
 	unsigned char c;
 	unsigned int d;
 
-	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
-			!machine_is(mpc8572_ds))
+	if (!is_quirk_valid())
 		return;
 
 	/* read/write lock */
@@ -201,8 +205,7 @@
 {
 	unsigned short temp;
 
-	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
-			!machine_is(mpc8572_ds))
+	if (!is_quirk_valid())
 		return;
 
 	pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE |
@@ -270,7 +273,6 @@
 static void __devinit hpcd_quirk_uli5288(struct pci_dev *dev)
 {
 	unsigned char c;
-	unsigned short temp;
 
 	if (!machine_is(mpc86xx_hpcd))
 		return;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/dt.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/dt.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/dt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/dt.c	2009-09-09 18:13:59.000000000 -0400
@@ -204,7 +204,8 @@
 	dt_prop(dt, name, &data, sizeof(u32));
 }
 
-static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
+static void __init __maybe_unused dt_prop_u64(struct iseries_flat_dt *dt,
+					      const char *name,
 		u64 data)
 {
 	dt_prop(dt, name, &data, sizeof(u64));
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/iommu.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/iommu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/iommu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -177,7 +177,7 @@
 static void pci_dma_dev_setup_iseries(struct pci_dev *pdev)
 {
 	struct iommu_table *tbl;
-	struct device_node *dn = pdev->sysdata;
+	struct device_node *dn = pci_device_to_OF_node(pdev);
 	struct pci_dn *pdn = PCI_DN(dn);
 	const u32 *lsn = of_get_property(dn, "linux,logical-slot-number", NULL);
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/mf.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/mf.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/mf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/mf.c	2009-09-09 18:13:59.000000000 -0400
@@ -267,7 +267,8 @@
 	return ev;
 }
 
-static int signal_vsp_instruction(struct vsp_cmd_data *vsp_cmd)
+static int __maybe_unused
+signal_vsp_instruction(struct vsp_cmd_data *vsp_cmd)
 {
 	struct pending_event *ev = new_pending_event();
 	int rc;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/pci.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/iseries/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/iseries/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -318,6 +318,7 @@
 {
 	struct resource *bar_res = &dev->resource[bar_num];
 	long bar_size = pci_resource_len(dev, bar_num);
+	struct device_node *dn = pci_device_to_OF_node(dev);
 
 	/*
 	 * No space to allocate, quick exit, skip Allocation.
@@ -335,9 +336,9 @@
 	 * Allocate the number of table entries needed for BAR.
 	 */
 	while (bar_size > 0 ) {
-		iomm_table[current_iomm_table_entry] = dev->sysdata;
+		iomm_table[current_iomm_table_entry] = dn;
 		ds_addr_table[current_iomm_table_entry] =
-			iseries_ds_addr(dev->sysdata) | (bar_num << 24);
+			iseries_ds_addr(dn) | (bar_num << 24);
 		bar_size -= IOMM_TABLE_ENTRY_SIZE;
 		++current_iomm_table_entry;
 	}
@@ -410,7 +411,7 @@
 	struct device_node *node;
 	int i;
 
-	node = find_device_node(bus, pdev->devfn);
+	node = pci_device_to_OF_node(pdev);
 	pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
 		 pci_name(pdev), pdev, node);
 	if (!node) {
@@ -441,7 +442,6 @@
 		}
 	}
 
-	pdev->sysdata = node;
 	allocate_device_bars(pdev);
 	iseries_device_information(pdev, bus, *sub_bus);
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/Kconfig linux-libre-2.6.31-gnu/arch/powerpc/platforms/Kconfig
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -329,4 +329,8 @@
 	  also register MCU GPIOs with the generic GPIO API, so you'll able
 	  to use MCU pins as GPIOs.
 
+config XILINX_PCI
+	bool "Xilinx PCI host bridge support"
+	depends on PCI && XILINX_VIRTEX
+
 endmenu
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/Kconfig.cputype linux-libre-2.6.31-gnu/arch/powerpc/platforms/Kconfig.cputype
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/Kconfig.cputype	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/Kconfig.cputype	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 config PPC64
 	bool "64-bit kernel"
 	default n
+	select PPC_HAVE_PMU_SUPPORT
 	help
 	  This option selects whether a 32-bit or a 64-bit kernel
 	  will be built.
@@ -9,7 +10,6 @@
 choice
 	prompt "Processor Type"
 	depends on PPC32
-	default 6xx
 	help
 	  There are five families of 32 bit PowerPC chips supported.
 	  The most common ones are the desktop and server CPUs (601, 603,
@@ -21,7 +21,7 @@
 
 	  If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx.
 
-config 6xx
+config PPC_BOOK3S_32
 	bool "512x/52xx/6xx/7xx/74xx/82xx/83xx/86xx"
 	select PPC_FPU
 
@@ -57,13 +57,14 @@
 
 endchoice
 
-# Until we have a choice of exclusive CPU types on 64-bit, we always
-# use PPC_BOOK3S. On 32-bit, this is equivalent to 6xx which is
-# "classic" MMU
+config PPC_BOOK3S_64
+	def_bool y
+	depends on PPC64
+	select PPC_FPU
 
 config PPC_BOOK3S
-       def_bool y
-       depends on PPC64 || 6xx
+	def_bool y
+	depends on PPC_BOOK3S_32 || PPC_BOOK3S_64
 
 config POWER4_ONLY
 	bool "Optimize for POWER4"
@@ -74,6 +75,11 @@
 	  The resulting binary will not work on POWER3 or RS64 processors
 	  when compiled with binutils 2.15 or later.
 
+config 6xx
+	def_bool y
+	depends on PPC32 && PPC_BOOK3S
+	select PPC_HAVE_PMU_SUPPORT
+
 config POWER3
 	bool
 	depends on PPC64 && PPC_BOOK3S
@@ -202,9 +208,8 @@
 	  If in doubt, say Y here.
 
 config PPC_STD_MMU
-	bool
-	depends on 6xx || PPC64
-	default y
+	def_bool y
+	depends on PPC_BOOK3S
 
 config PPC_STD_MMU_32
 	def_bool y
@@ -242,6 +247,15 @@
 
 	  If in doubt, say Y here.
 
+config PPC_HAVE_PMU_SUPPORT
+       bool
+
+config PPC_PERF_CTRS
+       def_bool y
+       depends on PERF_COUNTERS && PPC_HAVE_PMU_SUPPORT
+       help
+         This enables the powerpc-specific perf_counter back-end.
+
 config SMP
 	depends on PPC_STD_MMU || FSL_BOOKE
 	bool "Symmetric multi-processing support"
@@ -262,8 +276,8 @@
 	  If you don't know what to do here, say N.
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-1024)"
-	range 2 1024
+	int "Maximum number of CPUs (2-8192)"
+	range 2 8192
 	depends on SMP
 	default "32" if PPC64
 	default "4"
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/Makefile linux-libre-2.6.31-gnu/arch/powerpc/platforms/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 obj-$(CONFIG_FSL_ULI1575)	+= fsl_uli1575.o
 
 obj-$(CONFIG_PPC_PMAC)		+= powermac/
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/maple/setup.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/maple/setup.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/maple/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/maple/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -335,3 +335,62 @@
 	.progress		= maple_progress,
 	.power_save		= power4_idle,
 };
+
+#ifdef CONFIG_EDAC
+/*
+ * Register a platform device for CPC925 memory controller on
+ * Motorola ATCA-6101 blade.
+ */
+#define MAPLE_CPC925_MODEL	"Motorola,ATCA-6101"
+static int __init maple_cpc925_edac_setup(void)
+{
+	struct platform_device *pdev;
+	struct device_node *np = NULL;
+	struct resource r;
+	const unsigned char *model;
+	int ret;
+
+	np = of_find_node_by_path("/");
+	if (!np) {
+		printk(KERN_ERR "%s: Unable to get root node\n", __func__);
+		return -ENODEV;
+	}
+
+	model = (const unsigned char *)of_get_property(np, "model", NULL);
+	if (!model) {
+		printk(KERN_ERR "%s: Unabel to get model info\n", __func__);
+		return -ENODEV;
+	}
+
+	ret = strcmp(model, MAPLE_CPC925_MODEL);
+	of_node_put(np);
+
+	if (ret != 0)
+		return 0;
+
+	np = of_find_node_by_type(NULL, "memory-controller");
+	if (!np) {
+		printk(KERN_ERR "%s: Unable to find memory-controller node\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	ret = of_address_to_resource(np, 0, &r);
+	of_node_put(np);
+
+	if (ret < 0) {
+		printk(KERN_ERR "%s: Unable to get memory-controller reg\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	pdev = platform_device_register_simple("cpc925_edac", 0, &r, 1);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	printk(KERN_INFO "%s: CPC925 platform device created\n", __func__);
+
+	return 0;
+}
+machine_device_initcall(maple, maple_cpc925_edac_setup);
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/phy.h>
-#include <linux/platform_device.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
 #define DELAY 1
@@ -39,6 +39,7 @@
 struct gpio_priv {
 	int mdc_pin;
 	int mdio_pin;
+	int mdio_irqs[PHY_MAX_ADDR];
 };
 
 #define MDC_PIN(bus)	(((struct gpio_priv *)bus->priv)->mdc_pin)
@@ -218,12 +219,11 @@
 				     const struct of_device_id *match)
 {
 	struct device *dev = &ofdev->dev;
-	struct device_node *phy_dn, *np = ofdev->node;
+	struct device_node *np = ofdev->node;
 	struct mii_bus *new_bus;
 	struct gpio_priv *priv;
 	const unsigned int *prop;
 	int err;
-	int i;
 
 	err = -ENOMEM;
 	priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
@@ -244,27 +244,7 @@
 	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop);
 	new_bus->priv = priv;
 
-	new_bus->phy_mask = 0;
-
-	new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-
-	if (!new_bus->irq)
-		goto out_free_bus;
-
-	for (i = 0; i < PHY_MAX_ADDR; i++)
-		new_bus->irq[i] = NO_IRQ;
-
-	for (phy_dn = of_get_next_child(np, NULL);
-	     phy_dn != NULL;
-	     phy_dn = of_get_next_child(np, phy_dn)) {
-		const unsigned int *ip, *regp;
-
-		ip = of_get_property(phy_dn, "interrupts", NULL);
-		regp = of_get_property(phy_dn, "reg", NULL);
-		if (!ip || !regp || *regp >= PHY_MAX_ADDR)
-			continue;
-		new_bus->irq[*regp] = irq_create_mapping(NULL, *ip);
-	}
+	new_bus->irq = priv->mdio_irqs;
 
 	prop = of_get_property(np, "mdc-pin", NULL);
 	priv->mdc_pin = *prop;
@@ -275,7 +255,7 @@
 	new_bus->parent = dev;
 	dev_set_drvdata(dev, new_bus);
 
-	err = mdiobus_register(new_bus);
+	err = of_mdiobus_register(new_bus, np);
 
 	if (err != 0) {
 		printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
@@ -286,8 +266,6 @@
 	return 0;
 
 out_free_irq:
-	kfree(new_bus->irq);
-out_free_bus:
 	kfree(new_bus);
 out_free_priv:
 	kfree(priv);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pasemi/setup.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pasemi/setup.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pasemi/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pasemi/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,20 +71,25 @@
 }
 
 #ifdef CONFIG_SMP
-static DEFINE_SPINLOCK(timebase_lock);
+static raw_spinlock_t timebase_lock;
 static unsigned long timebase;
 
 static void __devinit pas_give_timebase(void)
 {
-	spin_lock(&timebase_lock);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	hard_irq_disable();
+	__raw_spin_lock(&timebase_lock);
 	mtspr(SPRN_TBCTL, TBCTL_FREEZE);
 	isync();
 	timebase = get_tb();
-	spin_unlock(&timebase_lock);
+	__raw_spin_unlock(&timebase_lock);
 
 	while (timebase)
 		barrier();
 	mtspr(SPRN_TBCTL, TBCTL_RESTART);
+	local_irq_restore(flags);
 }
 
 static void __devinit pas_take_timebase(void)
@@ -92,10 +97,10 @@
 	while (!timebase)
 		smp_rmb();
 
-	spin_lock(&timebase_lock);
+	__raw_spin_lock(&timebase_lock);
 	set_tb(timebase >> 32, timebase & 0xffffffff);
 	timebase = 0;
-	spin_unlock(&timebase_lock);
+	__raw_spin_unlock(&timebase_lock);
 }
 
 struct smp_ops_t pas_smp_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/cpufreq_64.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/cpufreq_64.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/cpufreq_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/cpufreq_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -251,7 +251,7 @@
 static struct pmf_function *pfunc_cpu_setfreq_high;
 static struct pmf_function *pfunc_cpu_setfreq_low;
 static struct pmf_function *pfunc_cpu_getfreq;
-static struct pmf_function *pfunc_slewing_done;;
+static struct pmf_function *pfunc_slewing_done;
 
 static int g5_pfunc_switch_freq(int speed_mode)
 {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/pic.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/pic.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/pic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/pic.c	2009-09-09 18:13:59.000000000 -0400
@@ -221,7 +221,7 @@
 			continue;
 		irq += __ilog2(bits);
 		spin_unlock_irqrestore(&pmac_pic_lock, flags);
-		__do_IRQ(irq);
+		generic_handle_irq(irq);
 		spin_lock_irqsave(&pmac_pic_lock, flags);
 		rc = IRQ_HANDLED;
 	}
@@ -609,7 +609,7 @@
 	np = of_find_node_by_name(NULL, "via-pmu");
 	if (np == NULL)
 		goto not_found;
-	viaint = irq_of_parse_and_map(np, 0);;
+	viaint = irq_of_parse_and_map(np, 0);
 
 not_found:
 #endif /* CONFIG_ADB_PMU */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/setup.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/setup.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -103,11 +103,6 @@
 EXPORT_SYMBOL(smu_cmdbuf_abs);
 #endif
 
-#ifdef CONFIG_SMP
-extern struct smp_ops_t psurge_smp_ops;
-extern struct smp_ops_t core99_smp_ops;
-#endif /* CONFIG_SMP */
-
 static void pmac_show_cpuinfo(struct seq_file *m)
 {
 	struct device_node *np;
@@ -341,34 +336,6 @@
 		ROOT_DEV = DEFAULT_ROOT_DEVICE;
 #endif
 
-#ifdef CONFIG_SMP
-	/* Check for Core99 */
-	ic = of_find_node_by_name(NULL, "uni-n");
-	if (!ic)
-		ic = of_find_node_by_name(NULL, "u3");
-	if (!ic)
-		ic = of_find_node_by_name(NULL, "u4");
-	if (ic) {
-		of_node_put(ic);
-		smp_ops = &core99_smp_ops;
-	}
-#ifdef CONFIG_PPC32
-	else {
-		/*
-		 * We have to set bits in cpu_possible_map here since the
-		 * secondary CPU(s) aren't in the device tree, and
-		 * setup_per_cpu_areas only allocates per-cpu data for
-		 * CPUs in the cpu_possible_map.
-		 */
-		int cpu;
-
-		for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu)
-			cpu_set(cpu, cpu_possible_map);
-		smp_ops = &psurge_smp_ops;
-	}
-#endif
-#endif /* CONFIG_SMP */
-
 #ifdef CONFIG_ADB
 	if (strstr(cmd_line, "adb_sync")) {
 		extern int __adb_probe_sync;
@@ -512,6 +479,14 @@
 #ifdef CONFIG_PPC64
 	iommu_init_early_dart();
 #endif
+
+	/* SMP Init has to be done early as we need to patch up
+	 * cpu_possible_map before interrupt stacks are allocated
+	 * or kaboom...
+	 */
+#ifdef CONFIG_SMP
+	pmac_setup_smp();
+#endif
 }
 
 static int __init pmac_declare_of_platform_devices(void)
@@ -655,7 +630,7 @@
 /* Move that to pci.c */
 static int pmac_pci_probe_mode(struct pci_bus *bus)
 {
-	struct device_node *node = bus->sysdata;
+	struct device_node *node = pci_bus_to_OF_node(bus);
 
 	/* We need to use normal PCI probing for the AGP bus,
 	 * since the device for the AGP bridge isn't in the tree.
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/smp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/powermac/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/powermac/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,10 +64,11 @@
 extern void __secondary_start_pmac_0(void);
 extern int pmac_pfunc_base_install(void);
 
-#ifdef CONFIG_PPC32
+static void (*pmac_tb_freeze)(int freeze);
+static u64 timebase;
+static int tb_req;
 
-/* Sync flag for HW tb sync */
-static volatile int sec_tb_reset = 0;
+#ifdef CONFIG_PPC32
 
 /*
  * Powersurge (old powermac SMP) support.
@@ -294,6 +295,9 @@
 		psurge_quad_init();
 		/* All released cards using this HW design have 4 CPUs */
 		ncpus = 4;
+		/* No sure how timebase sync works on those, let's use SW */
+		smp_ops->give_timebase = smp_generic_give_timebase;
+		smp_ops->take_timebase = smp_generic_take_timebase;
 	} else {
 		iounmap(quad_base);
 		if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
@@ -308,18 +312,15 @@
 	psurge_start = ioremap(PSURGE_START, 4);
 	psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
 
-	/*
-	 * This is necessary because OF doesn't know about the
+	/* This is necessary because OF doesn't know about the
 	 * secondary cpu(s), and thus there aren't nodes in the
 	 * device tree for them, and smp_setup_cpu_maps hasn't
-	 * set their bits in cpu_possible_map and cpu_present_map.
+	 * set their bits in cpu_present_map.
 	 */
 	if (ncpus > NR_CPUS)
 		ncpus = NR_CPUS;
-	for (i = 1; i < ncpus ; ++i) {
+	for (i = 1; i < ncpus ; ++i)
 		cpu_set(i, cpu_present_map);
-		set_hard_smp_processor_id(i, i);
-	}
 
 	if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
 
@@ -329,8 +330,14 @@
 static void __init smp_psurge_kick_cpu(int nr)
 {
 	unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
-	unsigned long a;
-	int i;
+	unsigned long a, flags;
+	int i, j;
+
+	/* Defining this here is evil ... but I prefer hiding that
+	 * crap to avoid giving people ideas that they can do the
+	 * same.
+	 */
+	extern volatile unsigned int cpu_callin_map[NR_CPUS];
 
 	/* may need to flush here if secondary bats aren't setup */
 	for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
@@ -339,47 +346,52 @@
 
 	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
 
+	/* This is going to freeze the timeebase, we disable interrupts */
+	local_irq_save(flags);
+
 	out_be32(psurge_start, start);
 	mb();
 
 	psurge_set_ipi(nr);
+
 	/*
 	 * We can't use udelay here because the timebase is now frozen.
 	 */
 	for (i = 0; i < 2000; ++i)
-		barrier();
+		asm volatile("nop" : : : "memory");
 	psurge_clr_ipi(nr);
 
-	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
-}
-
-/*
- * With the dual-cpu powersurge board, the decrementers and timebases
- * of both cpus are frozen after the secondary cpu is started up,
- * until we give the secondary cpu another interrupt.  This routine
- * uses this to get the timebases synchronized.
- *  -- paulus.
- */
-static void __init psurge_dual_sync_tb(int cpu_nr)
-{
-	int t;
-
-	set_dec(tb_ticks_per_jiffy);
-	/* XXX fixme */
-	set_tb(0, 0);
+	/*
+	 * Also, because the timebase is frozen, we must not return to the
+	 * caller which will try to do udelay's etc... Instead, we wait -here-
+	 * for the CPU to callin.
+	 */
+	for (i = 0; i < 100000 && !cpu_callin_map[nr]; ++i) {
+		for (j = 1; j < 10000; j++)
+			asm volatile("nop" : : : "memory");
+		asm volatile("sync" : : : "memory");
+	}
+	if (!cpu_callin_map[nr])
+		goto stuck;
 
-	if (cpu_nr > 0) {
+	/* And we do the TB sync here too for standard dual CPU cards */
+	if (psurge_type == PSURGE_DUAL) {
+		while(!tb_req)
+			barrier();
+		tb_req = 0;
+		mb();
+		timebase = get_tb();
+		mb();
+		while (timebase)
+			barrier();
 		mb();
-		sec_tb_reset = 1;
-		return;
 	}
+ stuck:
+	/* now interrupt the secondary, restarting both TBs */
+	if (psurge_type == PSURGE_DUAL)
+		psurge_set_ipi(1);
 
-	/* wait for the secondary to have reset its TB before proceeding */
-	for (t = 10000000; t > 0 && !sec_tb_reset; --t)
-		;
-
-	/* now interrupt the secondary, starting both TBs */
-	psurge_set_ipi(1);
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
 }
 
 static struct irqaction psurge_irqaction = {
@@ -390,36 +402,35 @@
 
 static void __init smp_psurge_setup_cpu(int cpu_nr)
 {
+	if (cpu_nr != 0)
+		return;
 
-	if (cpu_nr == 0) {
-		/* If we failed to start the second CPU, we should still
-		 * send it an IPI to start the timebase & DEC or we might
-		 * have them stuck.
-		 */
-		if (num_online_cpus() < 2) {
-			if (psurge_type == PSURGE_DUAL)
-				psurge_set_ipi(1);
-			return;
-		}
-		/* reset the entry point so if we get another intr we won't
-		 * try to startup again */
-		out_be32(psurge_start, 0x100);
-		if (setup_irq(30, &psurge_irqaction))
-			printk(KERN_ERR "Couldn't get primary IPI interrupt");
-	}
-
-	if (psurge_type == PSURGE_DUAL)
-		psurge_dual_sync_tb(cpu_nr);
+	/* reset the entry point so if we get another intr we won't
+	 * try to startup again */
+	out_be32(psurge_start, 0x100);
+	if (setup_irq(30, &psurge_irqaction))
+		printk(KERN_ERR "Couldn't get primary IPI interrupt");
 }
 
 void __init smp_psurge_take_timebase(void)
 {
-	/* Dummy implementation */
+	if (psurge_type != PSURGE_DUAL)
+		return;
+
+	tb_req = 1;
+	mb();
+	while (!timebase)
+		barrier();
+	mb();
+	set_tb(timebase >> 32, timebase & 0xffffffff);
+	timebase = 0;
+	mb();
+	set_dec(tb_ticks_per_jiffy/2);
 }
 
 void __init smp_psurge_give_timebase(void)
 {
-	/* Dummy implementation */
+	/* Nothing to do here */
 }
 
 /* PowerSurge-style Macs */
@@ -437,9 +448,6 @@
  * Core 99 and later support
  */
 
-static void (*pmac_tb_freeze)(int freeze);
-static u64 timebase;
-static int tb_req;
 
 static void smp_core99_give_timebase(void)
 {
@@ -478,7 +486,6 @@
 	set_tb(timebase >> 32, timebase & 0xffffffff);
 	timebase = 0;
 	mb();
-	set_dec(tb_ticks_per_jiffy/2);
 
 	local_irq_restore(flags);
 }
@@ -920,3 +927,34 @@
 # endif
 #endif
 };
+
+void __init pmac_setup_smp(void)
+{
+	struct device_node *np;
+
+	/* Check for Core99 */
+	np = of_find_node_by_name(NULL, "uni-n");
+	if (!np)
+		np = of_find_node_by_name(NULL, "u3");
+	if (!np)
+		np = of_find_node_by_name(NULL, "u4");
+	if (np) {
+		of_node_put(np);
+		smp_ops = &core99_smp_ops;
+	}
+#ifdef CONFIG_PPC32
+	else {
+		/* We have to set bits in cpu_possible_map here since the
+		 * secondary CPU(s) aren't in the device tree. Various
+		 * things won't be initialized for CPUs not in the possible
+		 * map, so we really need to fix it up here.
+		 */
+		int cpu;
+
+		for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu)
+			cpu_set(cpu, cpu_possible_map);
+		smp_ops = &psurge_smp_ops;
+	}
+#endif /* CONFIG_PPC32 */
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/mm.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/mm.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/mm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/mm.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/lmb.h>
 
 #include <asm/firmware.h>
+#include <asm/iommu.h>
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
@@ -605,9 +606,8 @@
 				       r->ioid,
 				       iopte_flag);
 		if (result) {
-			printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region "
-				"failed: %s\n", __func__, __LINE__,
-				ps3_result(result));
+			pr_warning("%s:%d: lv1_put_iopte failed: %s\n",
+				   __func__, __LINE__, ps3_result(result));
 			goto fail_map;
 		}
 		DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__,
@@ -1001,7 +1001,8 @@
 		if (len > r->len)
 			len = r->len;
 		result = dma_sb_map_area(r, virt_addr, len, &tmp,
-			IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+			CBE_IOPTE_PP_W | CBE_IOPTE_PP_R | CBE_IOPTE_SO_RW |
+			CBE_IOPTE_M);
 		BUG_ON(result);
 	}
 
@@ -1014,7 +1015,8 @@
 		else
 			len -= map.rm.size - r->offset;
 		result = dma_sb_map_area(r, virt_addr, len, &tmp,
-			IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+			CBE_IOPTE_PP_W | CBE_IOPTE_PP_R | CBE_IOPTE_SO_RW |
+			CBE_IOPTE_M);
 		BUG_ON(result);
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/os-area.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/os-area.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/os-area.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/os-area.c	2009-09-09 18:13:59.000000000 -0400
@@ -226,6 +226,44 @@
 	.value = &saved_params.av_multi_out,
 };
 
+
+static DEFINE_MUTEX(os_area_flash_mutex);
+
+static const struct ps3_os_area_flash_ops *os_area_flash_ops;
+
+void ps3_os_area_flash_register(const struct ps3_os_area_flash_ops *ops)
+{
+	mutex_lock(&os_area_flash_mutex);
+	os_area_flash_ops = ops;
+	mutex_unlock(&os_area_flash_mutex);
+}
+EXPORT_SYMBOL_GPL(ps3_os_area_flash_register);
+
+static ssize_t os_area_flash_read(void *buf, size_t count, loff_t pos)
+{
+	ssize_t res = -ENODEV;
+
+	mutex_lock(&os_area_flash_mutex);
+	if (os_area_flash_ops)
+		res = os_area_flash_ops->read(buf, count, pos);
+	mutex_unlock(&os_area_flash_mutex);
+
+	return res;
+}
+
+static ssize_t os_area_flash_write(const void *buf, size_t count, loff_t pos)
+{
+	ssize_t res = -ENODEV;
+
+	mutex_lock(&os_area_flash_mutex);
+	if (os_area_flash_ops)
+		res = os_area_flash_ops->write(buf, count, pos);
+	mutex_unlock(&os_area_flash_mutex);
+
+	return res;
+}
+
+
 /**
  * os_area_set_property - Add or overwrite a saved_params value to the device tree.
  *
@@ -352,12 +390,12 @@
 	if (memcmp(db->magic_num, OS_AREA_DB_MAGIC_NUM,
 		sizeof(db->magic_num))) {
 		pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
-		return -1;
+		return -EINVAL;
 	}
 
 	if (db->version != 1) {
 		pr_debug("%s:%d version failed\n", __func__, __LINE__);
-		return -1;
+		return -EINVAL;
 	}
 
 	return 0;
@@ -578,59 +616,48 @@
  *
  */
 
-static void __maybe_unused update_flash_db(void)
+static int update_flash_db(void)
 {
-	int result;
-	int file;
-	off_t offset;
+	const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
+	struct os_area_header *header;
 	ssize_t count;
-	static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
-	const struct os_area_header *header;
+	int error;
+	loff_t pos;
 	struct os_area_db* db;
 
 	/* Read in header and db from flash. */
 
-	file = sys_open("/dev/ps3flash", O_RDWR, 0);
-
-	if (file < 0) {
-		pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);
-		goto fail_open;
-	}
-
 	header = kmalloc(buf_len, GFP_KERNEL);
-
 	if (!header) {
-		pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);
-		goto fail_malloc;
+		pr_debug("%s: kmalloc failed\n", __func__);
+		return -ENOMEM;
 	}
 
-	offset = sys_lseek(file, 0, SEEK_SET);
-
-	if (offset != 0) {
-		pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
-		goto fail_header_seek;
+	count = os_area_flash_read(header, buf_len, 0);
+	if (count < 0) {
+		pr_debug("%s: os_area_flash_read failed %zd\n", __func__,
+			 count);
+		error = count;
+		goto fail;
 	}
 
-	count = sys_read(file, (char __user *)header, buf_len);
-
-	result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)
-		|| count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;
-
-	if (result) {
-		pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
+	pos = header->db_area_offset * OS_AREA_SEGMENT_SIZE;
+	if (count < OS_AREA_SEGMENT_SIZE || verify_header(header) ||
+	    count < pos) {
+		pr_debug("%s: verify_header failed\n", __func__);
 		dump_header(header);
-		goto fail_header;
+		error = -EINVAL;
+		goto fail;
 	}
 
 	/* Now got a good db offset and some maybe good db data. */
 
-	db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;
-
-	result = db_verify(db);
+	db = (void *)header + pos;
 
-	if (result) {
-		printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "
-			"formatting.\n", __func__, __LINE__);
+	error = db_verify(db);
+	if (error) {
+		pr_notice("%s: Verify of flash database failed, formatting.\n",
+			  __func__);
 		dump_db(db);
 		os_area_db_init(db);
 	}
@@ -639,29 +666,16 @@
 
 	db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);
 
-	offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,
-		SEEK_SET);
-
-	if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {
-		pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
-		goto fail_db_seek;
-	}
-
-	count = sys_write(file, (const char __user *)db,
-		sizeof(struct os_area_db));
-
+	count = os_area_flash_write(db, sizeof(struct os_area_db), pos);
 	if (count < sizeof(struct os_area_db)) {
-		pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);
+		pr_debug("%s: os_area_flash_write failed %zd\n", __func__,
+			 count);
+		error = count < 0 ? count : -EIO;
 	}
 
-fail_db_seek:
-fail_header:
-fail_header_seek:
+fail:
 	kfree(header);
-fail_malloc:
-	sys_close(file);
-fail_open:
-	return;
+	return error;
 }
 
 /**
@@ -674,11 +688,11 @@
 static void os_area_queue_work_handler(struct work_struct *work)
 {
 	struct device_node *node;
+	int error;
 
 	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 
 	node = of_find_node_by_path("/");
-
 	if (node) {
 		os_area_set_property(node, &property_rtc_diff);
 		of_node_put(node);
@@ -686,12 +700,10 @@
 		pr_debug("%s:%d of_find_node_by_path failed\n",
 			__func__, __LINE__);
 
-#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
-	update_flash_db();
-#else
-	printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",
-		__func__, __LINE__);
-#endif
+	error = update_flash_db();
+	if (error)
+		pr_warning("%s: Could not update FLASH ROM\n", __func__);
+
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 }
 
@@ -808,7 +820,7 @@
 {
 	return saved_params.rtc_diff;
 }
-EXPORT_SYMBOL(ps3_os_area_get_rtc_diff);
+EXPORT_SYMBOL_GPL(ps3_os_area_get_rtc_diff);
 
 /**
  * ps3_os_area_set_rtc_diff - Set the rtc diff value.
@@ -824,7 +836,7 @@
 		os_area_queue_work();
 	}
 }
-EXPORT_SYMBOL(ps3_os_area_set_rtc_diff);
+EXPORT_SYMBOL_GPL(ps3_os_area_set_rtc_diff);
 
 /**
  * ps3_os_area_get_av_multi_out - Returns the default video mode.
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/platform.h linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/platform.h
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/platform.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/platform.h	2009-09-09 18:13:59.000000000 -0400
@@ -232,14 +232,4 @@
 int ps3_repository_read_vuart_av_port(unsigned int *port);
 int ps3_repository_read_vuart_sysmgr_port(unsigned int *port);
 
-/* Page table entries */
-#define IOPTE_PP_W		0x8000000000000000ul /* protection: write */
-#define IOPTE_PP_R		0x4000000000000000ul /* protection: read */
-#define IOPTE_M			0x2000000000000000ul /* coherency required */
-#define IOPTE_SO_R		0x1000000000000000ul /* ordering: writes */
-#define IOPTE_SO_RW             0x1800000000000000ul /* ordering: r & w */
-#define IOPTE_RPN_Mask		0x07fffffffffff000ul /* RPN */
-#define IOPTE_H			0x0000000000000800ul /* cache hint */
-#define IOPTE_IOID_Mask		0x00000000000007fful /* ioid */
-
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/setup.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/setup.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #include <asm/udbg.h>
 #include <asm/prom.h>
 #include <asm/lv1call.h>
+#include <asm/ps3gpu.h>
 
 #include "platform.h"
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/smp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,12 +32,6 @@
 #define DBG pr_debug
 #endif
 
-static irqreturn_t ipi_function_handler(int irq, void *msg)
-{
-	smp_message_recv((int)(long)msg);
-	return IRQ_HANDLED;
-}
-
 /**
   * ps3_ipi_virqs - a per cpu array of virqs for ipi use
   */
@@ -45,13 +39,6 @@
 #define MSG_COUNT 4
 static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]);
 
-static const char *names[MSG_COUNT] = {
-	"ipi call",
-	"ipi reschedule",
-	"ipi migrate",
-	"ipi debug brk"
-};
-
 static void do_message_pass(int target, int msg)
 {
 	int result;
@@ -119,8 +106,7 @@
 		DBG("%s:%d: (%d, %d) => virq %u\n",
 			__func__, __LINE__, cpu, i, virqs[i]);
 
-		result = request_irq(virqs[i], ipi_function_handler,
-			IRQF_DISABLED, names[i], (void*)(long)i);
+		result = smp_request_message_ipi(virqs[i], i);
 
 		if (result)
 			virqs[i] = NO_IRQ;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/system-bus.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/system-bus.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/system-bus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/system-bus.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
 #include <asm/firmware.h>
+#include <asm/iommu.h>
 
 #include "platform.h"
 
@@ -283,7 +284,6 @@
 	int result;
 
 	dump_mmio_region(r);
-;
 	result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
 		r->lpar_addr);
 
@@ -531,7 +531,8 @@
 	}
 
 	result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle,
-			     IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M);
+			     CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
+			     CBE_IOPTE_SO_RW | CBE_IOPTE_M);
 
 	if (result) {
 		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -575,7 +576,8 @@
 
 	result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
 			     &bus_addr,
-			     IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M);
+			     CBE_IOPTE_PP_R | CBE_IOPTE_PP_W |
+			     CBE_IOPTE_SO_RW | CBE_IOPTE_M);
 
 	if (result) {
 		pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
@@ -596,16 +598,16 @@
 	u64 iopte_flag;
 	void *ptr = page_address(page) + offset;
 
-	iopte_flag = IOPTE_M;
+	iopte_flag = CBE_IOPTE_M;
 	switch (direction) {
 	case DMA_BIDIRECTIONAL:
-		iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW;
+		iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW;
 		break;
 	case DMA_TO_DEVICE:
-		iopte_flag |= IOPTE_PP_R | IOPTE_SO_R;
+		iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_SO_R;
 		break;
 	case DMA_FROM_DEVICE:
-		iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW;
+		iopte_flag |= CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW;
 		break;
 	default:
 		/* not happned */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/time.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/time.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/ps3/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/ps3/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
+#include <asm/firmware.h>
 #include <asm/rtc.h>
 #include <asm/lv1call.h>
 #include <asm/ps3.h>
@@ -84,6 +85,9 @@
 {
 	struct platform_device *pdev;
 
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
 	pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
 	if (IS_ERR(pdev))
 		return PTR_ERR(pdev);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/eeh_driver.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/eeh_driver.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/eeh_driver.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/eeh_driver.c	2009-09-09 18:13:59.000000000 -0400
@@ -122,7 +122,7 @@
  * passed back in "userdata".
  */
 
-static void eeh_report_error(struct pci_dev *dev, void *userdata)
+static int eeh_report_error(struct pci_dev *dev, void *userdata)
 {
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver = dev->driver;
@@ -130,19 +130,21 @@
 	dev->error_state = pci_channel_io_frozen;
 
 	if (!driver)
-		return;
+		return 0;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->error_detected)
-		return;
+		return 0;
 
 	rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);
 
 	/* A driver that needs a reset trumps all others */
 	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+
+	return 0;
 }
 
 /**
@@ -153,7 +155,7 @@
  * Cumulative response passed back in "userdata".
  */
 
-static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
+static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
 {
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver = dev->driver;
@@ -161,26 +163,28 @@
 	if (!driver ||
 	    !driver->err_handler ||
 	    !driver->err_handler->mmio_enabled)
-		return;
+		return 0;
 
 	rc = driver->err_handler->mmio_enabled (dev);
 
 	/* A driver that needs a reset trumps all others */
 	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+
+	return 0;
 }
 
 /**
  * eeh_report_reset - tell device that slot has been reset
  */
 
-static void eeh_report_reset(struct pci_dev *dev, void *userdata)
+static int eeh_report_reset(struct pci_dev *dev, void *userdata)
 {
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver = dev->driver;
 
 	if (!driver)
-		return;
+		return 0;
 
 	dev->error_state = pci_channel_io_normal;
 
@@ -188,35 +192,39 @@
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->slot_reset)
-		return;
+		return 0;
 
 	rc = driver->err_handler->slot_reset(dev);
 	if ((*res == PCI_ERS_RESULT_NONE) ||
 	    (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
 	if (*res == PCI_ERS_RESULT_DISCONNECT &&
 	     rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
+
+	return 0;
 }
 
 /**
  * eeh_report_resume - tell device to resume normal operations
  */
 
-static void eeh_report_resume(struct pci_dev *dev, void *userdata)
+static int eeh_report_resume(struct pci_dev *dev, void *userdata)
 {
 	struct pci_driver *driver = dev->driver;
 
 	dev->error_state = pci_channel_io_normal;
 
 	if (!driver)
-		return;
+		return 0;
 
 	eeh_enable_irq(dev);
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->resume)
-		return;
+		return 0;
 
 	driver->err_handler->resume(dev);
+
+	return 0;
 }
 
 /**
@@ -226,22 +234,24 @@
  * dead, and that no further recovery attempts will be made on it.
  */
 
-static void eeh_report_failure(struct pci_dev *dev, void *userdata)
+static int eeh_report_failure(struct pci_dev *dev, void *userdata)
 {
 	struct pci_driver *driver = dev->driver;
 
 	dev->error_state = pci_channel_io_perm_failure;
 
 	if (!driver)
-		return;
+		return 0;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->error_detected)
-		return;
+		return 0;
 
 	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
+
+	return 0;
 }
 
 /* ------------------------------------------------------- */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/iommu.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/iommu.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/iommu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -388,7 +388,7 @@
 
 		while (pci->phb->dma_window_size * children > 0x80000000ul)
 			pci->phb->dma_window_size >>= 1;
-		pr_debug("No ISA/IDE, window size is 0x%lx\n",
+		pr_debug("No ISA/IDE, window size is 0x%llx\n",
 			 pci->phb->dma_window_size);
 		pci->phb->dma_window_base_cur = 0;
 
@@ -414,7 +414,7 @@
 	while (pci->phb->dma_window_size * children > 0x70000000ul)
 		pci->phb->dma_window_size >>= 1;
 
-	pr_debug("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
+	pr_debug("ISA/IDE, window size is 0x%llx\n", pci->phb->dma_window_size);
 }
 
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/lpar.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/lpar.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/lpar.c	2009-09-09 18:13:59.000000000 -0400
@@ -286,7 +286,7 @@
 	unsigned long hpte_v, hpte_r;
 
 	if (!(vflags & HPTE_V_BOLTED))
-		pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+		pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
 			 "rflags=%lx, vflags=%lx, psize=%d)\n",
 			 hpte_group, va, pa, rflags, vflags, psize);
 
@@ -294,7 +294,7 @@
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
 
 	if (!(vflags & HPTE_V_BOLTED))
-		pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+		pr_devel(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
 
 	/* Now fill in the actual HPTE */
 	/* Set CEC cookie to 0         */
@@ -311,7 +311,7 @@
 	lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
 	if (unlikely(lpar_rc == H_PTEG_FULL)) {
 		if (!(vflags & HPTE_V_BOLTED))
-			pr_debug(" full\n");
+			pr_devel(" full\n");
 		return -1;
 	}
 
@@ -322,11 +322,11 @@
 	 */
 	if (unlikely(lpar_rc != H_SUCCESS)) {
 		if (!(vflags & HPTE_V_BOLTED))
-			pr_debug(" lpar err %lu\n", lpar_rc);
+			pr_devel(" lpar err %lu\n", lpar_rc);
 		return -2;
 	}
 	if (!(vflags & HPTE_V_BOLTED))
-		pr_debug(" -> slot: %lu\n", slot & 7);
+		pr_devel(" -> slot: %lu\n", slot & 7);
 
 	/* Because of iSeries, we have to pass down the secondary
 	 * bucket bit here as well
@@ -418,17 +418,17 @@
 
 	want_v = hpte_encode_avpn(va, psize, ssize);
 
-	pr_debug("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
+	pr_devel("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
 		 want_v, slot, flags, psize);
 
 	lpar_rc = plpar_pte_protect(flags, slot, want_v);
 
 	if (lpar_rc == H_NOT_FOUND) {
-		pr_debug("not found !\n");
+		pr_devel("not found !\n");
 		return -1;
 	}
 
-	pr_debug("ok\n");
+	pr_devel("ok\n");
 
 	BUG_ON(lpar_rc != H_SUCCESS);
 
@@ -503,7 +503,7 @@
 	unsigned long lpar_rc;
 	unsigned long dummy1, dummy2;
 
-	pr_debug("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+	pr_devel("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
 		 slot, va, psize, local);
 
 	want_v = hpte_encode_avpn(va, psize, ssize);
@@ -609,3 +609,55 @@
 	ppc_md.flush_hash_range	= pSeries_lpar_flush_hash_range;
 	ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
 }
+
+#ifdef CONFIG_PPC_SMLPAR
+#define CMO_FREE_HINT_DEFAULT 1
+static int cmo_free_hint_flag = CMO_FREE_HINT_DEFAULT;
+
+static int __init cmo_free_hint(char *str)
+{
+	char *parm;
+	parm = strstrip(str);
+
+	if (strcasecmp(parm, "no") == 0 || strcasecmp(parm, "off") == 0) {
+		printk(KERN_INFO "cmo_free_hint: CMO free page hinting is not active.\n");
+		cmo_free_hint_flag = 0;
+		return 1;
+	}
+
+	cmo_free_hint_flag = 1;
+	printk(KERN_INFO "cmo_free_hint: CMO free page hinting is active.\n");
+
+	if (strcasecmp(parm, "yes") == 0 || strcasecmp(parm, "on") == 0)
+		return 1;
+
+	return 0;
+}
+
+__setup("cmo_free_hint=", cmo_free_hint);
+
+static void pSeries_set_page_state(struct page *page, int order,
+				   unsigned long state)
+{
+	int i, j;
+	unsigned long cmo_page_sz, addr;
+
+	cmo_page_sz = cmo_get_page_size();
+	addr = __pa((unsigned long)page_address(page));
+
+	for (i = 0; i < (1 << order); i++, addr += PAGE_SIZE) {
+		for (j = 0; j < PAGE_SIZE; j += cmo_page_sz)
+			plpar_hcall_norets(H_PAGE_INIT, state, addr + j, 0);
+	}
+}
+
+void arch_free_page(struct page *page, int order)
+{
+	if (!cmo_free_hint_flag || !firmware_has_feature(FW_FEATURE_CMO))
+		return;
+
+	pSeries_set_page_state(page, order, H_PAGE_SET_UNUSED);
+}
+EXPORT_SYMBOL(arch_free_page);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/rtasd.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/rtasd.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/rtasd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/rtasd.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,7 @@
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
-#include <linux/delay.h>
+#include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -387,36 +387,51 @@
 	} while(error == 0);
 }
 
-static void do_event_scan_all_cpus(long delay)
+static void rtas_event_scan(struct work_struct *w);
+DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan);
+
+/*
+ * Delay should be at least one second since some machines have problems if
+ * we call event-scan too quickly.
+ */
+static unsigned long event_scan_delay = 1*HZ;
+static int first_pass = 1;
+
+static void rtas_event_scan(struct work_struct *w)
 {
-	int cpu;
+	unsigned int cpu;
+
+	do_event_scan();
 
 	get_online_cpus();
-	cpu = first_cpu(cpu_online_map);
-	for (;;) {
-		set_cpus_allowed(current, cpumask_of_cpu(cpu));
-		do_event_scan();
-		set_cpus_allowed(current, CPU_MASK_ALL);
 
-		/* Drop hotplug lock, and sleep for the specified delay */
-		put_online_cpus();
-		msleep_interruptible(delay);
-		get_online_cpus();
+	cpu = next_cpu(smp_processor_id(), cpu_online_map);
+	if (cpu == NR_CPUS) {
+		cpu = first_cpu(cpu_online_map);
 
-		cpu = next_cpu(cpu, cpu_online_map);
-		if (cpu == NR_CPUS)
-			break;
+		if (first_pass) {
+			first_pass = 0;
+			event_scan_delay = 30*HZ/rtas_event_scan_rate;
+
+			if (surveillance_timeout != -1) {
+				pr_debug("rtasd: enabling surveillance\n");
+				enable_surveillance(surveillance_timeout);
+				pr_debug("rtasd: surveillance enabled\n");
+			}
+		}
 	}
+
+	schedule_delayed_work_on(cpu, &event_scan_work,
+		__round_jiffies_relative(event_scan_delay, cpu));
+
 	put_online_cpus();
 }
 
-static int rtasd(void *unused)
+static void start_event_scan(void)
 {
 	unsigned int err_type;
 	int rc;
 
-	daemonize("rtasd");
-
 	printk(KERN_DEBUG "RTAS daemon started\n");
 	pr_debug("rtasd: will sleep for %d milliseconds\n",
 		 (30000 / rtas_event_scan_rate));
@@ -434,22 +449,8 @@
 		}
 	}
 
-	/* First pass. */
-	do_event_scan_all_cpus(1000);
-
-	if (surveillance_timeout != -1) {
-		pr_debug("rtasd: enabling surveillance\n");
-		enable_surveillance(surveillance_timeout);
-		pr_debug("rtasd: surveillance enabled\n");
-	}
-
-	/* Delay should be at least one second since some
-	 * machines have problems if we call event-scan too
-	 * quickly. */
-	for (;;)
-		do_event_scan_all_cpus(30000/rtas_event_scan_rate);
-
-	return -EINVAL;
+	schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work,
+				 event_scan_delay);
 }
 
 static int __init rtas_init(void)
@@ -487,8 +488,7 @@
 	if (!entry)
 		printk(KERN_ERR "Failed to create error_log proc entry\n");
 
-	if (kernel_thread(rtasd, NULL, CLONE_FS) < 0)
-		printk(KERN_ERR "Failed to start RTAS daemon\n");
+	start_event_scan();
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/setup.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/setup.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -63,6 +63,7 @@
 #include <asm/smp.h>
 #include <asm/firmware.h>
 #include <asm/eeh.h>
+#include <asm/pSeries_reconfig.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
@@ -254,6 +255,29 @@
 	       " interrupt-controller\n");
 }
 
+static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
+{
+	struct device_node *np = node;
+	struct pci_dn *pci = NULL;
+	int err = NOTIFY_OK;
+
+	switch (action) {
+	case PSERIES_RECONFIG_ADD:
+		pci = np->parent->data;
+		if (pci)
+			update_dn_pci_info(np, pci->phb);
+		break;
+	default:
+		err = NOTIFY_DONE;
+		break;
+	}
+	return err;
+}
+
+static struct notifier_block pci_dn_reconfig_nb = {
+	.notifier_call = pci_dn_reconfig_notifier,
+};
+
 static void __init pSeries_setup_arch(void)
 {
 	/* Discover PIC type and setup ppc_md accordingly */
@@ -271,6 +295,7 @@
 	/* Find and initialize PCI host bridges */
 	init_pci_config_tokens();
 	find_and_init_phbs();
+	pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
 	eeh_init();
 
 	pSeries_nvram_init();
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/smp.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/smp.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,6 @@
 #include <asm/prom.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
@@ -118,31 +117,6 @@
 }
 #endif /* CONFIG_XICS */
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase = 0;
-
-static void __devinit pSeries_give_timebase(void)
-{
-	spin_lock(&timebase_lock);
-	rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-	timebase = get_tb();
-	spin_unlock(&timebase_lock);
-
-	while (timebase)
-		barrier();
-	rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-static void __devinit pSeries_take_timebase(void)
-{
-	while (!timebase)
-		barrier();
-	spin_lock(&timebase_lock);
-	set_tb(timebase >> 32, timebase & 0xffffffff);
-	timebase = 0;
-	spin_unlock(&timebase_lock);
-}
-
 static void __devinit smp_pSeries_kick_cpu(int nr)
 {
 	BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -209,8 +183,8 @@
 
 	/* Non-lpar has additional take/give timebase */
 	if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
-		smp_ops->give_timebase = pSeries_give_timebase;
-		smp_ops->take_timebase = pSeries_take_timebase;
+		smp_ops->give_timebase = rtas_give_timebase;
+		smp_ops->take_timebase = rtas_take_timebase;
 	}
 
 	pr_debug(" <- smp_init_pSeries()\n");
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/xics.c linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/xics.c
--- linux-libre-2.6.30-gnu/arch/powerpc/platforms/pseries/xics.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/platforms/pseries/xics.c	2009-09-09 18:13:59.000000000 -0400
@@ -190,10 +190,10 @@
 	int call_status;
 	int server;
 
-	pr_debug("xics: unmask virq %d\n", virq);
+	pr_devel("xics: unmask virq %d\n", virq);
 
 	irq = (unsigned int)irq_map[virq].hwirq;
-	pr_debug(" -> map to hwirq 0x%x\n", irq);
+	pr_devel(" -> map to hwirq 0x%x\n", irq);
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
 
@@ -252,7 +252,7 @@
 {
 	unsigned int irq;
 
-	pr_debug("xics: mask virq %d\n", virq);
+	pr_devel("xics: mask virq %d\n", virq);
 
 	irq = (unsigned int)irq_map[virq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
@@ -333,7 +333,7 @@
 	lpar_xirr_info_set((0xff << 24) | irq);
 }
 
-static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
+static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
 {
 	unsigned int irq;
 	int status;
@@ -342,14 +342,14 @@
 
 	irq = (unsigned int)irq_map[virq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
-		return;
+		return -1;
 
 	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
 	if (status) {
 		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
 			__func__, irq, status);
-		return;
+		return -1;
 	}
 
 	/*
@@ -363,7 +363,7 @@
 		printk(KERN_WARNING
 			"%s: No online cpus in the mask %s for irq %d\n",
 			__func__, cpulist, virq);
-		return;
+		return -1;
 	}
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
@@ -372,8 +372,10 @@
 	if (status) {
 		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
 			__func__, irq, status);
-		return;
+		return -1;
 	}
+
+	return 0;
 }
 
 static struct irq_chip xics_pic_direct = {
@@ -412,7 +414,7 @@
 static int xics_host_map(struct irq_host *h, unsigned int virq,
 			 irq_hw_number_t hw)
 {
-	pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
+	pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
 
 	/* Insert the interrupt mapping into the radix tree for fast lookup */
 	irq_radix_revmap_insert(xics_host, virq, hw);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/axonram.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/axonram.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/axonram.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/axonram.c	2009-09-09 18:13:59.000000000 -0400
@@ -250,7 +250,7 @@
 
 	set_capacity(bank->disk, bank->size >> AXON_RAM_SECTOR_SHIFT);
 	blk_queue_make_request(bank->disk->queue, axon_ram_make_request);
-	blk_queue_hardsect_size(bank->disk->queue, AXON_RAM_SECTOR_SIZE);
+	blk_queue_logical_block_size(bank->disk->queue, AXON_RAM_SECTOR_SIZE);
 	add_disk(bank->disk);
 
 	bank->irq_id = irq_of_parse_and_map(device->node, 0);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/cpm2.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/cpm2.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/cpm2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/cpm2.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,7 +61,7 @@
 void __init cpm2_reset(void)
 {
 #ifdef CONFIG_PPC_85xx
-	cpm2_immr = ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
+	cpm2_immr = ioremap(get_immrbase() + 0x80000, CPM_MAP_SIZE);
 #else
 	cpm2_immr = ioremap(get_immrbase(), CPM_MAP_SIZE);
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_msi.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_msi.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_msi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_msi.c	2009-09-09 18:13:59.000000000 -0400
@@ -113,8 +113,13 @@
 				  struct msi_msg *msg)
 {
 	struct fsl_msi *msi_data = fsl_msi;
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+	u32 base = 0;
 
-	msg->address_lo = msi_data->msi_addr_lo;
+	pci_bus_read_config_dword(hose->bus,
+		PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+
+	msg->address_lo = msi_data->msi_addr_lo + base;
 	msg->address_hi = msi_data->msi_addr_hi;
 	msg->data = hwirq;
 
@@ -271,7 +276,7 @@
 	msi->irqhost->host_data = msi;
 
 	msi->msi_addr_hi = 0x0;
-	msi->msi_addr_lo = res.start + features->msiir_offset;
+	msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff);
 
 	rc = fsl_msi_init_allocator(msi);
 	if (rc) {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_pci.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,8 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/lmb.h>
+#include <linux/log2.h>
 
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -96,7 +98,13 @@
 				  struct resource *rsrc)
 {
 	struct ccsr_pci __iomem *pci;
-	int i, j, n;
+	int i, j, n, mem_log, win_idx = 2;
+	u64 mem, sz, paddr_hi = 0;
+	u64 paddr_lo = ULLONG_MAX;
+	u32 pcicsrbar = 0, pcicsrbar_sz;
+	u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
+			PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
+	char *name = hose->dn->full_name;
 
 	pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
 		    (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
@@ -117,6 +125,9 @@
 		if (!(hose->mem_resources[i].flags & IORESOURCE_MEM))
 			continue;
 
+		paddr_lo = min(paddr_lo, (u64)hose->mem_resources[i].start);
+		paddr_hi = max(paddr_hi, (u64)hose->mem_resources[i].end);
+
 		n = setup_one_atmu(pci, j, &hose->mem_resources[i],
 				   hose->pci_mem_offset);
 
@@ -147,10 +158,105 @@
 		}
 	}
 
-	/* Setup 2G inbound Memory Window @ 1 */
-	out_be32(&pci->piw[2].pitar, 0x00000000);
-	out_be32(&pci->piw[2].piwbar,0x00000000);
-	out_be32(&pci->piw[2].piwar, PIWAR_2G);
+	/* convert to pci address space */
+	paddr_hi -= hose->pci_mem_offset;
+	paddr_lo -= hose->pci_mem_offset;
+
+	if (paddr_hi == paddr_lo) {
+		pr_err("%s: No outbound window space\n", name);
+		return ;
+	}
+
+	if (paddr_lo == 0) {
+		pr_err("%s: No space for inbound window\n", name);
+		return ;
+	}
+
+	/* setup PCSRBAR/PEXCSRBAR */
+	early_write_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, 0xffffffff);
+	early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, &pcicsrbar_sz);
+	pcicsrbar_sz = ~pcicsrbar_sz + 1;
+
+	if (paddr_hi < (0x100000000ull - pcicsrbar_sz) ||
+		(paddr_lo > 0x100000000ull))
+		pcicsrbar = 0x100000000ull - pcicsrbar_sz;
+	else
+		pcicsrbar = (paddr_lo - pcicsrbar_sz) & -pcicsrbar_sz;
+	early_write_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, pcicsrbar);
+
+	paddr_lo = min(paddr_lo, (u64)pcicsrbar);
+
+	pr_info("%s: PCICSRBAR @ 0x%x\n", name, pcicsrbar);
+
+	/* Setup inbound mem window */
+	mem = lmb_end_of_DRAM();
+	sz = min(mem, paddr_lo);
+	mem_log = __ilog2_u64(sz);
+
+	/* PCIe can overmap inbound & outbound since RX & TX are separated */
+	if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
+		/* Size window to exact size if power-of-two or one size up */
+		if ((1ull << mem_log) != mem) {
+			if ((1ull << mem_log) > mem)
+				pr_info("%s: Setting PCI inbound window "
+					"greater than memory size\n", name);
+			mem_log++;
+		}
+
+		piwar |= (mem_log - 1);
+
+		/* Setup inbound memory window */
+		out_be32(&pci->piw[win_idx].pitar,  0x00000000);
+		out_be32(&pci->piw[win_idx].piwbar, 0x00000000);
+		out_be32(&pci->piw[win_idx].piwar,  piwar);
+		win_idx--;
+
+		hose->dma_window_base_cur = 0x00000000;
+		hose->dma_window_size = (resource_size_t)sz;
+	} else {
+		u64 paddr = 0;
+
+		/* Setup inbound memory window */
+		out_be32(&pci->piw[win_idx].pitar,  paddr >> 12);
+		out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
+		out_be32(&pci->piw[win_idx].piwar,  (piwar | (mem_log - 1)));
+		win_idx--;
+
+		paddr += 1ull << mem_log;
+		sz -= 1ull << mem_log;
+
+		if (sz) {
+			mem_log = __ilog2_u64(sz);
+			piwar |= (mem_log - 1);
+
+			out_be32(&pci->piw[win_idx].pitar,  paddr >> 12);
+			out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
+			out_be32(&pci->piw[win_idx].piwar,  piwar);
+			win_idx--;
+
+			paddr += 1ull << mem_log;
+		}
+
+		hose->dma_window_base_cur = 0x00000000;
+		hose->dma_window_size = (resource_size_t)paddr;
+	}
+
+	if (hose->dma_window_size < mem) {
+#ifndef CONFIG_SWIOTLB
+		pr_err("%s: ERROR: Memory size exceeds PCI ATMU ability to "
+			"map - enable CONFIG_SWIOTLB to avoid dma errors.\n",
+			 name);
+#endif
+		/* adjusting outbound windows could reclaim space in mem map */
+		if (paddr_hi < 0xffffffffull)
+			pr_warning("%s: WARNING: Outbound window cfg leaves "
+				"gaps in memory map. Adjusting the memory map "
+				"could reduce unnecessary bounce buffering.\n",
+				name);
+
+		pr_info("%s: DMA window size is 0x%llx\n", name,
+			(u64)hose->dma_window_size);
+	}
 
 	iounmap(pci);
 }
@@ -176,19 +282,9 @@
 	}
 }
 
-static void __init setup_pci_pcsrbar(struct pci_controller *hose)
-{
-#ifdef CONFIG_PCI_MSI
-	phys_addr_t immr_base;
-
-	immr_base = get_immrbase();
-	early_write_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, immr_base);
-#endif
-}
-
 void fsl_pcibios_fixup_bus(struct pci_bus *bus)
 {
-	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	int i;
 
 	if ((bus->parent == hose->bus) &&
@@ -269,8 +365,6 @@
 	/* Setup PEX window registers */
 	setup_pci_atmu(hose, &rsrc);
 
-	/* Setup PEXCSRBAR */
-	setup_pci_pcsrbar(hose);
 	return 0;
 }
 
@@ -281,6 +375,8 @@
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8547E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567E, quirk_fsl_pcie_header);
@@ -296,6 +392,8 @@
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
 #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
 
 #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
@@ -324,7 +422,7 @@
 
 static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 
 	if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -350,7 +448,7 @@
 static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus,
 					    unsigned int devfn, int offset)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct mpc83xx_pcie_priv *pcie = hose->dn->data;
 	u8 bus_no = bus->number - hose->first_busno;
 	u32 dev_base = bus_no << 24 | devfn << 16;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_pci.h linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_pci.h
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,11 @@
 
 #define PCIE_LTSSM	0x0404		/* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0	0x16		/* L0 state */
-#define PIWAR_2G	0xa0f5501e	/* Enable, Prefetch, Local Mem, Snoop R/W, 2G */
+#define PIWAR_EN		0x80000000	/* Enable */
+#define PIWAR_PF		0x20000000	/* prefetch */
+#define PIWAR_TGI_LOCAL		0x00f00000	/* target - local memory */
+#define PIWAR_READ_SNOOP	0x00050000
+#define PIWAR_WRITE_SNOOP	0x00005000
 
 /* PCI/PCI Express outbound window reg */
 struct pci_outbound_window_regs {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_rio.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_rio.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_rio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_rio.c	2009-09-09 18:13:59.000000000 -0400
@@ -965,7 +965,7 @@
 			break;
 		default:
 			str = "Unknown";
-			break;;
+			break;
 		}
 		dev_info(dev, "Hardware port width: %s\n", str);
 
@@ -1026,8 +1026,7 @@
 		return -EFAULT;
 	}
 	dev_info(&dev->dev, "Of-device full name %s\n", dev->node->full_name);
-	dev_info(&dev->dev, "Regs start 0x%08x size 0x%08x\n",	regs.start,
-						regs.end - regs.start + 1);
+	dev_info(&dev->dev, "Regs: %pR\n", &regs);
 
 	dt_range = of_get_property(dev->node, "ranges", &rlen);
 	if (!dt_range) {
@@ -1077,8 +1076,9 @@
 
 	INIT_LIST_HEAD(&port->dbells);
 	port->iores.start = law_start;
-	port->iores.end = law_start + law_size;
+	port->iores.end = law_start + law_size - 1;
 	port->iores.flags = IORESOURCE_MEM;
+	port->iores.name = "rio_io_win";
 
 	priv->bellirq = irq_of_parse_and_map(dev->node, 2);
 	priv->txirq = irq_of_parse_and_map(dev->node, 3);
@@ -1156,14 +1156,15 @@
 		out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA);
 
 	/* Configure maintenance transaction window */
-	out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000);
-	out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);
+	out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12);
+	out_be32(&priv->maint_atmu_regs->rowar, 0x80077015);	/* 4M */
 
 	priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
 
 	/* Configure outbound doorbell window */
-	out_be32(&priv->dbell_atmu_regs->rowbar, 0x000c0400);
-	out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);
+	out_be32(&priv->dbell_atmu_regs->rowbar,
+			(law_start + RIO_MAINT_WIN_SIZE) >> 12);
+	out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b);	/* 4k */
 	fsl_rio_doorbell_init(port);
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_soc.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_soc.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/fsl_soc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/fsl_soc.c	2009-09-09 18:13:59.000000000 -0400
@@ -379,16 +379,10 @@
 	struct device_node *np;
 	np = of_find_node_by_name(NULL, "global-utilities");
 	if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
-		const u32 *prop = of_get_property(np, "reg", NULL);
-		if (prop) {
-			/* map reset control register
-			 * 0xE00B0 is offset of reset control register
-			 */
-			rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
-			if (!rstcr)
-				printk (KERN_EMERG "Error: reset control "
-						"register not mapped!\n");
-		}
+		rstcr = of_iomap(np, 0) + 0xb0;
+		if (!rstcr)
+			printk (KERN_EMERG "Error: reset control register "
+					"not mapped!\n");
 	} else
 		printk (KERN_INFO "rstcr compatible register does not exist!\n");
 	if (np)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/indirect_pci.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/indirect_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/indirect_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/indirect_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,7 +24,7 @@
 indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		     int len, u32 *val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	volatile void __iomem *cfg_data;
 	u8 cfg_type = 0;
 	u32 bus_no, reg;
@@ -82,7 +82,7 @@
 indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
 		      int len, u32 val)
 {
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	volatile void __iomem *cfg_data;
 	u8 cfg_type = 0;
 	u32 bus_no, reg;
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/ipic.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/ipic.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/ipic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/ipic.c	2009-09-09 18:13:59.000000000 -0400
@@ -728,12 +728,10 @@
 	if (ret)
 		return NULL;
 
-	ipic = alloc_bootmem(sizeof(struct ipic));
+	ipic = kzalloc(sizeof(*ipic), GFP_KERNEL);
 	if (ipic == NULL)
 		return NULL;
 
-	memset(ipic, 0, sizeof(struct ipic));
-
 	ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
 				       NR_IPIC_INTS,
 				       &ipic_host_ops, 0);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/Makefile linux-libre-2.6.31-gnu/arch/powerpc/sysdev/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,5 @@
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS			+= -mno-minimal-toc
 endif
@@ -34,6 +36,7 @@
 obj-$(CONFIG_4xx)		+= uic.o
 obj-$(CONFIG_4xx_SOC)		+= ppc4xx_soc.o
 obj-$(CONFIG_XILINX_VIRTEX)	+= xilinx_intc.o
+obj-$(CONFIG_XILINX_PCI)	+= xilinx_pci.o
 obj-$(CONFIG_OF_RTC)		+= of_rtc.o
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_4xx)		+= ppc4xx_pci.o
@@ -47,6 +50,9 @@
 obj-$(CONFIG_8xx)		+= mpc8xx_pic.o cpm1.o
 obj-$(CONFIG_UCODE_PATCH)	+= micropatch.o
 
+obj-$(CONFIG_PPC_MPC512x)	+= mpc5xxx_clocks.o
+obj-$(CONFIG_PPC_MPC52xx)	+= mpc5xxx_clocks.o
+
 ifeq ($(CONFIG_SUSPEND),y)
 obj-$(CONFIG_6xx)		+= 6xx-suspend.o
 endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/mpc5xxx_clocks.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,33 @@
+/**
+ * 	mpc5xxx_get_bus_frequency - Find the bus frequency for a device
+ * 	@node:	device node
+ *
+ * 	Returns bus frequency (IPS on MPC512x, IPB on MPC52xx),
+ * 	or 0 if the bus frequency cannot be found.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+
+unsigned int
+mpc5xxx_get_bus_frequency(struct device_node *node)
+{
+	struct device_node *np;
+	const unsigned int *p_bus_freq = NULL;
+
+	of_node_get(node);
+	while (node) {
+		p_bus_freq = of_get_property(node, "bus-frequency", NULL);
+		if (p_bus_freq)
+			break;
+
+		np = of_get_parent(node);
+		of_node_put(node);
+		node = np;
+	}
+	if (node)
+		of_node_put(node);
+
+	return p_bus_freq ? *p_bus_freq : 0;
+}
+EXPORT_SYMBOL(mpc5xxx_get_bus_frequency);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/mpic.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/mpic.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/mpic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/mpic.c	2009-09-09 18:13:59.000000000 -0400
@@ -279,28 +279,29 @@
 }
 
 #ifdef CONFIG_PPC_DCR
-static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
+static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node,
+			  struct mpic_reg_bank *rb,
 			  unsigned int offset, unsigned int size)
 {
 	const u32 *dbasep;
 
-	dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL);
+	dbasep = of_get_property(node, "dcr-reg", NULL);
 
-	rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size);
+	rb->dhost = dcr_map(node, *dbasep + offset, size);
 	BUG_ON(!DCR_MAP_OK(rb->dhost));
 }
 
-static inline void mpic_map(struct mpic *mpic, phys_addr_t phys_addr,
-			    struct mpic_reg_bank *rb, unsigned int offset,
-			    unsigned int size)
+static inline void mpic_map(struct mpic *mpic, struct device_node *node,
+			    phys_addr_t phys_addr, struct mpic_reg_bank *rb,
+			    unsigned int offset, unsigned int size)
 {
 	if (mpic->flags & MPIC_USES_DCR)
-		_mpic_map_dcr(mpic, rb, offset, size);
+		_mpic_map_dcr(mpic, node, rb, offset, size);
 	else
 		_mpic_map_mmio(mpic, phys_addr, rb, offset, size);
 }
 #else /* CONFIG_PPC_DCR */
-#define mpic_map(m,p,b,o,s)	_mpic_map_mmio(m,p,b,o,s)
+#define mpic_map(m,n,p,b,o,s)	_mpic_map_mmio(m,p,b,o,s)
 #endif /* !CONFIG_PPC_DCR */
 
 
@@ -507,9 +508,8 @@
 	printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
 
 	/* Allocate fixups array */
-	mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
+	mpic->fixups = kzalloc(128 * sizeof(*mpic->fixups), GFP_KERNEL);
 	BUG_ON(mpic->fixups == NULL);
-	memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
 
 	/* Init spinlock */
 	spin_lock_init(&mpic->fixup_lock);
@@ -613,23 +613,23 @@
 #define mpic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
 
 /* Find an mpic associated with a given linux interrupt */
-static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
+static struct mpic *mpic_find(unsigned int irq)
 {
-	unsigned int src = mpic_irq_to_hw(irq);
-	struct mpic *mpic;
-
 	if (irq < NUM_ISA_INTERRUPTS)
 		return NULL;
 
-	mpic = irq_desc[irq].chip_data;
+	return irq_desc[irq].chip_data;
+}
 
-	if (is_ipi)
-		*is_ipi = (src >= mpic->ipi_vecs[0] &&
-			   src <= mpic->ipi_vecs[3]);
+/* Determine if the linux irq is an IPI */
+static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq)
+{
+	unsigned int src = mpic_irq_to_hw(irq);
 
-	return mpic;
+	return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
 }
 
+
 /* Convert a cpu mask from logical to physical cpu numbers. */
 static inline u32 mpic_physmask(u32 cpumask)
 {
@@ -807,7 +807,7 @@
 
 #endif /* CONFIG_SMP */
 
-void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 {
 	struct mpic *mpic = mpic_from_irq(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
@@ -824,6 +824,8 @@
 		mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
 			       mpic_physmask(cpus_addr(tmp)[0]));
 	}
+
+	return 0;
 }
 
 static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
@@ -1050,11 +1052,10 @@
 	int		intvec_top;
 	u64		paddr = phys_addr;
 
-	mpic = alloc_bootmem(sizeof(struct mpic));
+	mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);
 	if (mpic == NULL)
 		return NULL;
-	
-	memset(mpic, 0, sizeof(struct mpic));
+
 	mpic->name = name;
 
 	mpic->hc_irq = mpic_irq_chip;
@@ -1107,9 +1108,8 @@
 			psize /= 4;
 			bits = intvec_top + 1;
 			mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long);
-			mpic->protected = alloc_bootmem(mapsize);
+			mpic->protected = kzalloc(mapsize, GFP_KERNEL);
 			BUG_ON(mpic->protected == NULL);
-			memset(mpic->protected, 0, mapsize);
 			for (i = 0; i < psize; i++) {
 				if (psrc[i] > intvec_top)
 					continue;
@@ -1150,8 +1150,8 @@
 	}
 
 	/* Map the global registers */
-	mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
-	mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
+	mpic_map(mpic, node, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
+	mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
 	/* Reset */
 	if (flags & MPIC_WANTS_RESET) {
@@ -1192,7 +1192,7 @@
 
 	/* Map the per-CPU registers */
 	for (i = 0; i < mpic->num_cpus; i++) {
-		mpic_map(mpic, paddr, &mpic->cpuregs[i],
+		mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
 			 MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
 			 0x1000);
 	}
@@ -1200,7 +1200,7 @@
 	/* Initialize main ISU if none provided */
 	if (mpic->isu_size == 0) {
 		mpic->isu_size = mpic->num_sources;
-		mpic_map(mpic, paddr, &mpic->isus[0],
+		mpic_map(mpic, node, paddr, &mpic->isus[0],
 			 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
 	}
 	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
@@ -1254,8 +1254,10 @@
 
 	BUG_ON(isu_num >= MPIC_MAX_ISU);
 
-	mpic_map(mpic, paddr, &mpic->isus[isu_num], 0,
+	mpic_map(mpic, mpic->irqhost->of_node,
+		 paddr, &mpic->isus[isu_num], 0,
 		 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
+
 	if ((isu_first + mpic->isu_size) > mpic->num_sources)
 		mpic->num_sources = isu_first + mpic->isu_size;
 }
@@ -1349,7 +1351,8 @@
 
 #ifdef CONFIG_PM
 	/* allocate memory to save mpic state */
-	mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save));
+	mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data),
+				  GFP_KERNEL);
 	BUG_ON(mpic->save_data == NULL);
 #endif
 }
@@ -1381,8 +1384,7 @@
 
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
 {
-	unsigned int is_ipi;
-	struct mpic *mpic = mpic_find(irq, &is_ipi);
+	struct mpic *mpic = mpic_find(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
 	unsigned long flags;
 	u32 reg;
@@ -1391,7 +1393,7 @@
 		return;
 
 	spin_lock_irqsave(&mpic_lock, flags);
-	if (is_ipi) {
+	if (mpic_is_ipi(mpic, irq)) {
 		reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) &
 			~MPIC_VECPRI_PRIORITY_MASK;
 		mpic_ipi_write(src - mpic->ipi_vecs[0],
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/mpic.h linux-libre-2.6.31-gnu/arch/powerpc/sysdev/mpic.h
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/mpic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/mpic.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,6 @@
 
 extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
 extern void mpic_set_vector(unsigned int virq, unsigned int vector);
-extern void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
+extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
 
 #endif /* _POWERPC_SYSDEV_MPIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/ppc4xx_pci.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/ppc4xx_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/ppc4xx_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/ppc4xx_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -1295,7 +1295,7 @@
 static int ppc4xx_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
 				    int offset, int len, u32 *val)
 {
-	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct ppc4xx_pciex_port *port =
 		&ppc4xx_pciex_ports[hose->indirect_type];
 	void __iomem *addr;
@@ -1352,7 +1352,7 @@
 static int ppc4xx_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
 				     int offset, int len, u32 val)
 {
-	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct ppc4xx_pciex_port *port =
 		&ppc4xx_pciex_ports[hose->indirect_type];
 	void __iomem *addr;
@@ -1531,7 +1531,7 @@
 		 */
 
 		/* Calculate window size */
-		sa = (0xffffffffffffffffull << ilog2(ep_size));;
+		sa = (0xffffffffffffffffull << ilog2(ep_size));
 
 		/* Setup BAR0 */
 		out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
@@ -1550,7 +1550,7 @@
 		out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr));
 	} else {
 		/* Calculate window size */
-		sa = (0xffffffffffffffffull << ilog2(size));;
+		sa = (0xffffffffffffffffull << ilog2(size));
 		if (res->flags & IORESOURCE_PREFETCH)
 			sa |= 0x8;
 
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/qe_lib/qe.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/qe_lib/qe.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/qe_lib/qe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/qe_lib/qe.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,6 +61,7 @@
 EXPORT_SYMBOL(qe_immr);
 
 static struct qe_snum snums[QE_NUM_OF_SNUM];	/* Dynamically allocated SNUMs */
+static unsigned int qe_num_of_snum;
 
 static phys_addr_t qebase = -1;
 
@@ -111,6 +112,7 @@
 {
 	unsigned long flags;
 	u8 mcn_shift = 0, dev_shift = 0;
+	u32 ret;
 
 	spin_lock_irqsave(&qe_lock, flags);
 	if (cmd == QE_RESET) {
@@ -138,11 +140,13 @@
 	}
 
 	/* wait for the QE_CR_FLG to clear */
-	while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG)
-		cpu_relax();
+	ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
+			   100, 0);
+	/* On timeout (e.g. failure), the expression will be false (ret == 0),
+	   otherwise it will be true (ret == 1). */
 	spin_unlock_irqrestore(&qe_lock, flags);
 
-	return 0;
+	return ret == 1;
 }
 EXPORT_SYMBOL(qe_issue_cmd);
 
@@ -264,10 +268,14 @@
 		0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
 		0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
 		0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
-		0xD8, 0xD9, 0xE8, 0xE9,
+		0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
+		0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
+		0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
 	};
 
-	for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+	qe_num_of_snum = qe_get_num_of_snums();
+
+	for (i = 0; i < qe_num_of_snum; i++) {
 		snums[i].num = snum_init[i];
 		snums[i].state = QE_SNUM_STATE_FREE;
 	}
@@ -280,7 +288,7 @@
 	int i;
 
 	spin_lock_irqsave(&qe_lock, flags);
-	for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+	for (i = 0; i < qe_num_of_snum; i++) {
 		if (snums[i].state == QE_SNUM_STATE_FREE) {
 			snums[i].state = QE_SNUM_STATE_USED;
 			snum = snums[i].num;
@@ -297,7 +305,7 @@
 {
 	int i;
 
-	for (i = 0; i < QE_NUM_OF_SNUM; i++) {
+	for (i = 0; i < qe_num_of_snum; i++) {
 		if (snums[i].num == snum) {
 			snums[i].state = QE_SNUM_STATE_FREE;
 			break;
@@ -575,3 +583,65 @@
 }
 EXPORT_SYMBOL(qe_get_firmware_info);
 
+unsigned int qe_get_num_of_risc(void)
+{
+	struct device_node *qe;
+	int size;
+	unsigned int num_of_risc = 0;
+	const u32 *prop;
+
+	qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+	if (!qe) {
+		/* Older devices trees did not have an "fsl,qe"
+		 * compatible property, so we need to look for
+		 * the QE node by name.
+		 */
+		qe = of_find_node_by_type(NULL, "qe");
+		if (!qe)
+			return num_of_risc;
+	}
+
+	prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
+	if (prop && size == sizeof(*prop))
+		num_of_risc = *prop;
+
+	of_node_put(qe);
+
+	return num_of_risc;
+}
+EXPORT_SYMBOL(qe_get_num_of_risc);
+
+unsigned int qe_get_num_of_snums(void)
+{
+	struct device_node *qe;
+	int size;
+	unsigned int num_of_snums;
+	const u32 *prop;
+
+	num_of_snums = 28; /* The default number of snum for threads is 28 */
+	qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+	if (!qe) {
+		/* Older devices trees did not have an "fsl,qe"
+		 * compatible property, so we need to look for
+		 * the QE node by name.
+		 */
+		qe = of_find_node_by_type(NULL, "qe");
+		if (!qe)
+			return num_of_snums;
+	}
+
+	prop = of_get_property(qe, "fsl,qe-num-snums", &size);
+	if (prop && size == sizeof(*prop)) {
+		num_of_snums = *prop;
+		if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
+			/* No QE ever has fewer than 28 SNUMs */
+			pr_err("QE: number of snum is invalid\n");
+			return -EINVAL;
+		}
+	}
+
+	of_node_put(qe);
+
+	return num_of_snums;
+}
+EXPORT_SYMBOL(qe_get_num_of_snums);
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c	2009-09-09 18:13:59.000000000 -0400
@@ -333,12 +333,10 @@
 	if (ret)
 		return;
 
-	qe_ic = alloc_bootmem(sizeof(struct qe_ic));
+	qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL);
 	if (qe_ic == NULL)
 		return;
 
-	memset(qe_ic, 0, sizeof(struct qe_ic));
-
 	qe_ic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
 					NR_QE_IC_INTS, &qe_ic_host_ops, 0);
 	if (qe_ic->irqhost == NULL)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/tsi108_pci.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/tsi108_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/tsi108_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/tsi108_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -63,7 +63,7 @@
 			   int offset, int len, u32 val)
 {
 	volatile unsigned char *cfg_addr;
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 
 	if (ppc_md.pci_exclude_device)
 		if (ppc_md.pci_exclude_device(hose, bus->number, devfunc))
@@ -149,7 +149,7 @@
 			  int len, u32 * val)
 {
 	volatile unsigned char *cfg_addr;
-	struct pci_controller *hose = bus->sysdata;
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	u32 temp;
 
 	if (ppc_md.pci_exclude_device)
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/uic.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/uic.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/uic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/uic.c	2009-09-09 18:13:59.000000000 -0400
@@ -258,11 +258,10 @@
 
 	BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
 
-	uic = alloc_bootmem(sizeof(*uic));
+	uic = kzalloc(sizeof(*uic), GFP_KERNEL);
 	if (! uic)
 		return NULL; /* FIXME: panic? */
 
-	memset(uic, 0, sizeof(*uic));
 	spin_lock_init(&uic->lock);
 	indexp = of_get_property(node, "cell-index", &len);
 	if (!indexp || (len != sizeof(u32))) {
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/xilinx_intc.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/xilinx_intc.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/xilinx_intc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/xilinx_intc.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/of.h>
 #include <asm/io.h>
 #include <asm/processor.h>
+#include <asm/i8259.h>
 #include <asm/irq.h>
 
 /*
@@ -191,20 +192,14 @@
 xilinx_intc_init(struct device_node *np)
 {
 	struct irq_host * irq;
-	struct resource res;
 	void * regs;
-	int rc;
 
 	/* Find and map the intc registers */
-	rc = of_address_to_resource(np, 0, &res);
-	if (rc) {
-		printk(KERN_ERR __FILE__ ": of_address_to_resource() failed\n");
+	regs = of_iomap(np, 0);
+	if (!regs) {
+		pr_err("xilinx_intc: could not map registers\n");
 		return NULL;
 	}
-	regs = ioremap(res.start, 32);
-
-	printk(KERN_INFO "Xilinx intc at 0x%08llx mapped to 0x%p\n",
-		(unsigned long long) res.start, regs);
 
 	/* Setup interrupt controller */
 	out_be32(regs + XINTC_IER, 0); /* disable all irqs */
@@ -217,6 +212,7 @@
 	if (!irq)
 		panic(__FILE__ ": Cannot allocate IRQ host\n");
 	irq->host_data = regs;
+
 	return irq;
 }
 
@@ -227,23 +223,69 @@
 	return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR));
 }
 
+#if defined(CONFIG_PPC_I8259)
+/*
+ * Support code for cascading to 8259 interrupt controllers
+ */
+static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned int cascade_irq = i8259_irq();
+	if (cascade_irq)
+		generic_handle_irq(cascade_irq);
+
+	/* Let xilinx_intc end the interrupt */
+	desc->chip->unmask(irq);
+}
+
+static void __init xilinx_i8259_setup_cascade(void)
+{
+	struct device_node *cascade_node;
+	int cascade_irq;
+
+	/* Initialize i8259 controller */
+	cascade_node = of_find_compatible_node(NULL, NULL, "chrp,iic");
+	if (!cascade_node)
+		return;
+
+	cascade_irq = irq_of_parse_and_map(cascade_node, 0);
+	if (!cascade_irq) {
+		pr_err("virtex_ml510: Failed to map cascade interrupt\n");
+		goto out;
+	}
+
+	i8259_init(cascade_node, 0);
+	set_irq_chained_handler(cascade_irq, xilinx_i8259_cascade);
+
+	/* Program irq 7 (usb/audio), 14/15 (ide) to level sensitive */
+	/* This looks like a dirty hack to me --gcl */
+	outb(0xc0, 0x4d0);
+	outb(0xc0, 0x4d1);
+
+ out:
+	of_node_put(cascade_node);
+}
+#else
+static inline void xilinx_i8259_setup_cascade(void) { return; }
+#endif /* defined(CONFIG_PPC_I8259) */
+
+static struct of_device_id xilinx_intc_match[] __initconst = {
+	{ .compatible = "xlnx,opb-intc-1.00.c", },
+	{ .compatible = "xlnx,xps-intc-1.00.a", },
+	{}
+};
+
+/*
+ * Initialize master Xilinx interrupt controller
+ */
 void __init xilinx_intc_init_tree(void)
 {
 	struct device_node *np;
 
 	/* find top level interrupt controller */
-	for_each_compatible_node(np, NULL, "xlnx,opb-intc-1.00.c") {
+	for_each_matching_node(np, xilinx_intc_match) {
 		if (!of_get_property(np, "interrupts", NULL))
 			break;
 	}
-	if (!np) {
-		for_each_compatible_node(np, NULL, "xlnx,xps-intc-1.00.a") {
-			if (!of_get_property(np, "interrupts", NULL))
-				break;
-		}
-	}
-
-	/* xilinx interrupt controller needs to be top level */
 	BUG_ON(!np);
 
 	master_irqhost = xilinx_intc_init(np);
@@ -251,4 +293,6 @@
 
 	irq_set_default_host(master_irqhost);
 	of_node_put(np);
+
+	xilinx_i8259_setup_cascade();
 }
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/sysdev/xilinx_pci.c linux-libre-2.6.31-gnu/arch/powerpc/sysdev/xilinx_pci.c
--- linux-libre-2.6.30-gnu/arch/powerpc/sysdev/xilinx_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/powerpc/sysdev/xilinx_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,132 @@
+/*
+ * PCI support for Xilinx plbv46_pci soft-core which can be used on
+ * Xilinx Virtex ML410 / ML510 boards.
+ *
+ * Copyright 2009 Roderick Colenbrander
+ * Copyright 2009 Secret Lab Technologies Ltd.
+ *
+ * The pci bridge fixup code was copied from ppc4xx_pci.c and was written
+ * by Benjamin Herrenschmidt.
+ * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ * 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/ioport.h>
+#include <linux/of.h>
+#include <linux/pci.h>
+#include <mm/mmu_decl.h>
+#include <asm/io.h>
+#include <asm/xilinx_pci.h>
+
+#define XPLB_PCI_ADDR 0x10c
+#define XPLB_PCI_DATA 0x110
+#define XPLB_PCI_BUS  0x114
+
+#define PCI_HOST_ENABLE_CMD PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
+
+static struct of_device_id xilinx_pci_match[] = {
+	{ .compatible = "xlnx,plbv46-pci-1.03.a", },
+	{}
+};
+
+/**
+ * xilinx_pci_fixup_bridge - Block Xilinx PHB configuration.
+ */
+static void xilinx_pci_fixup_bridge(struct pci_dev *dev)
+{
+	struct pci_controller *hose;
+	int i;
+
+	if (dev->devfn || dev->bus->self)
+		return;
+
+	hose = pci_bus_to_host(dev->bus);
+	if (!hose)
+		return;
+
+	if (!of_match_node(xilinx_pci_match, hose->dn))
+		return;
+
+	/* Hide the PCI host BARs from the kernel as their content doesn't
+	 * fit well in the resource management
+	 */
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		dev->resource[i].start = 0;
+		dev->resource[i].end = 0;
+		dev->resource[i].flags = 0;
+	}
+
+	dev_info(&dev->dev, "Hiding Xilinx plb-pci host bridge resources %s\n",
+		 pci_name(dev));
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, xilinx_pci_fixup_bridge);
+
+/**
+ * xilinx_pci_exclude_device - Don't do config access for non-root bus
+ *
+ * This is a hack.  Config access to any bus other than bus 0 does not
+ * currently work on the ML510 so we prevent it here.
+ */
+static int
+xilinx_pci_exclude_device(struct pci_controller *hose, u_char bus, u8 devfn)
+{
+	return (bus != 0);
+}
+
+/**
+ * xilinx_pci_init - Find and register a Xilinx PCI host bridge
+ */
+void __init xilinx_pci_init(void)
+{
+	struct pci_controller *hose;
+	struct resource r;
+	void __iomem *pci_reg;
+	struct device_node *pci_node;
+
+	pci_node = of_find_matching_node(NULL, xilinx_pci_match);
+	if(!pci_node)
+		return;
+
+	if (of_address_to_resource(pci_node, 0, &r)) {
+		pr_err("xilinx-pci: cannot resolve base address\n");
+		return;
+	}
+
+	hose = pcibios_alloc_controller(pci_node);
+	if (!hose) {
+		pr_err("xilinx-pci: pcibios_alloc_controller() failed\n");
+		return;
+	}
+
+	/* Setup config space */
+	setup_indirect_pci(hose, r.start + XPLB_PCI_ADDR,
+			   r.start + XPLB_PCI_DATA,
+			   PPC_INDIRECT_TYPE_SET_CFG_TYPE);
+
+	/* According to the xilinx plbv46_pci documentation the soft-core starts
+	 * a self-init when the bus master enable bit is set. Without this bit
+	 * set the pci bus can't be scanned.
+	 */
+	early_write_config_word(hose, 0, 0, PCI_COMMAND, PCI_HOST_ENABLE_CMD);
+
+	/* Set the max latency timer to 255 */
+	early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0xff);
+
+	/* Set the max bus number to 255 */
+	pci_reg = of_iomap(pci_node, 0);
+	out_8(pci_reg + XPLB_PCI_BUS, 0xff);
+	iounmap(pci_reg);
+
+	/* Nothing past the root bridge is working right now.  By default
+	 * exclude config access to anything except bus 0 */
+	if (!ppc_md.pci_exclude_device)
+		ppc_md.pci_exclude_device = xilinx_pci_exclude_device;
+
+	/* Register the host bridge with the linux kernel! */
+	pci_process_bridge_OF_ranges(hose, pci_node, 1);
+
+	pr_info("xilinx-pci: Registered PCI host bridge\n");
+}
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/xmon/Makefile linux-libre-2.6.31-gnu/arch/powerpc/xmon/Makefile
--- linux-libre-2.6.30-gnu/arch/powerpc/xmon/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/xmon/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,7 @@
 # Makefile for xmon
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifdef CONFIG_PPC64
 EXTRA_CFLAGS += -mno-minimal-toc
 endif
diff -druN linux-libre-2.6.30-gnu/arch/powerpc/xmon/xmon.c linux-libre-2.6.31-gnu/arch/powerpc/xmon/xmon.c
--- linux-libre-2.6.30-gnu/arch/powerpc/xmon/xmon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/powerpc/xmon/xmon.c	2009-09-09 18:13:59.000000000 -0400
@@ -110,6 +110,7 @@
 static void dump(void);
 static void prdump(unsigned long, long);
 static int ppc_inst_dump(unsigned long, long, int);
+static void dump_log_buf(void);
 static void backtrace(struct pt_regs *);
 static void excprint(struct pt_regs *);
 static void prregs(struct pt_regs *);
@@ -197,6 +198,7 @@
   di	dump instructions\n\
   df	dump float values\n\
   dd	dump double values\n\
+  dl    dump the kernel log buffer\n\
   dr	dump stream of raw bytes\n\
   e	print exception information\n\
   f	flush cache\n\
@@ -2009,6 +2011,8 @@
 			nidump = MAX_DUMP;
 		adrs += ppc_inst_dump(adrs, nidump, 1);
 		last_cmd = "di\n";
+	} else if (c == 'l') {
+		dump_log_buf();
 	} else if (c == 'r') {
 		scanhex(&ndump);
 		if (ndump == 0)
@@ -2122,6 +2126,49 @@
 	xmon_print_symbol(addr, "\t# ", "");
 }
 
+void
+dump_log_buf(void)
+{
+        const unsigned long size = 128;
+        unsigned long end, addr;
+        unsigned char buf[size + 1];
+
+        addr = 0;
+        buf[size] = '\0';
+
+        if (setjmp(bus_error_jmp) != 0) {
+                printf("Unable to lookup symbol __log_buf!\n");
+                return;
+        }
+
+        catch_memory_errors = 1;
+        sync();
+        addr = kallsyms_lookup_name("__log_buf");
+
+        if (! addr)
+                printf("Symbol __log_buf not found!\n");
+        else {
+                end = addr + (1 << CONFIG_LOG_BUF_SHIFT);
+                while (addr < end) {
+                        if (! mread(addr, buf, size)) {
+                                printf("Can't read memory at address 0x%lx\n", addr);
+                                break;
+                        }
+
+                        printf("%s", buf);
+
+                        if (strlen(buf) < size)
+                                break;
+
+                        addr += size;
+                }
+        }
+
+        sync();
+        /* wait a little while to see if we get a machine check */
+        __delay(200);
+        catch_memory_errors = 0;
+}
 
 /*
  * Memory operations - move, set, print differences
diff -druN linux-libre-2.6.30-gnu/arch/s390/appldata/appldata_base.c linux-libre-2.6.31-gnu/arch/s390/appldata/appldata_base.c
--- linux-libre-2.6.30-gnu/arch/s390/appldata/appldata_base.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/appldata/appldata_base.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,7 +5,7 @@
  * Exports appldata_register_ops() and appldata_unregister_ops() for the
  * data gathering modules.
  *
- * Copyright IBM Corp. 2003, 2008
+ * Copyright IBM Corp. 2003, 2009
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
@@ -26,6 +26,8 @@
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/workqueue.h>
+#include <linux/suspend.h>
+#include <linux/platform_device.h>
 #include <asm/appldata.h>
 #include <asm/timer.h>
 #include <asm/uaccess.h>
@@ -41,6 +43,9 @@
 
 #define TOD_MICRO	0x01000			/* nr. of TOD clock units
 						   for 1 microsecond */
+
+static struct platform_device *appldata_pdev;
+
 /*
  * /proc entries (sysctl)
  */
@@ -86,6 +91,7 @@
 static DEFINE_SPINLOCK(appldata_timer_lock);
 static int appldata_interval = APPLDATA_CPU_INTERVAL;
 static int appldata_timer_active;
+static int appldata_timer_suspended = 0;
 
 /*
  * Work queue
@@ -475,6 +481,93 @@
 /********************** module-ops management <END> **************************/
 
 
+/**************************** suspend / resume *******************************/
+static int appldata_freeze(struct device *dev)
+{
+	struct appldata_ops *ops;
+	int rc;
+	struct list_head *lh;
+
+	get_online_cpus();
+	spin_lock(&appldata_timer_lock);
+	if (appldata_timer_active) {
+		__appldata_vtimer_setup(APPLDATA_DEL_TIMER);
+		appldata_timer_suspended = 1;
+	}
+	spin_unlock(&appldata_timer_lock);
+	put_online_cpus();
+
+	mutex_lock(&appldata_ops_mutex);
+	list_for_each(lh, &appldata_ops_list) {
+		ops = list_entry(lh, struct appldata_ops, list);
+		if (ops->active == 1) {
+			rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
+					(unsigned long) ops->data, ops->size,
+					ops->mod_lvl);
+			if (rc != 0)
+				pr_err("Stopping the data collection for %s "
+				       "failed with rc=%d\n", ops->name, rc);
+		}
+	}
+	mutex_unlock(&appldata_ops_mutex);
+	return 0;
+}
+
+static int appldata_restore(struct device *dev)
+{
+	struct appldata_ops *ops;
+	int rc;
+	struct list_head *lh;
+
+	get_online_cpus();
+	spin_lock(&appldata_timer_lock);
+	if (appldata_timer_suspended) {
+		__appldata_vtimer_setup(APPLDATA_ADD_TIMER);
+		appldata_timer_suspended = 0;
+	}
+	spin_unlock(&appldata_timer_lock);
+	put_online_cpus();
+
+	mutex_lock(&appldata_ops_mutex);
+	list_for_each(lh, &appldata_ops_list) {
+		ops = list_entry(lh, struct appldata_ops, list);
+		if (ops->active == 1) {
+			ops->callback(ops->data);	// init record
+			rc = appldata_diag(ops->record_nr,
+					APPLDATA_START_INTERVAL_REC,
+					(unsigned long) ops->data, ops->size,
+					ops->mod_lvl);
+			if (rc != 0) {
+				pr_err("Starting the data collection for %s "
+				       "failed with rc=%d\n", ops->name, rc);
+			}
+		}
+	}
+	mutex_unlock(&appldata_ops_mutex);
+	return 0;
+}
+
+static int appldata_thaw(struct device *dev)
+{
+	return appldata_restore(dev);
+}
+
+static struct dev_pm_ops appldata_pm_ops = {
+	.freeze		= appldata_freeze,
+	.thaw		= appldata_thaw,
+	.restore	= appldata_restore,
+};
+
+static struct platform_driver appldata_pdrv = {
+	.driver = {
+		.name	= "appldata",
+		.owner	= THIS_MODULE,
+		.pm	= &appldata_pm_ops,
+	},
+};
+/************************* suspend / resume <END> ****************************/
+
+
 /******************************* init / exit *********************************/
 
 static void __cpuinit appldata_online_cpu(int cpu)
@@ -531,11 +624,23 @@
  */
 static int __init appldata_init(void)
 {
-	int i;
+	int i, rc;
 
+	rc = platform_driver_register(&appldata_pdrv);
+	if (rc)
+		return rc;
+
+	appldata_pdev = platform_device_register_simple("appldata", -1, NULL,
+							0);
+	if (IS_ERR(appldata_pdev)) {
+		rc = PTR_ERR(appldata_pdev);
+		goto out_driver;
+	}
 	appldata_wq = create_singlethread_workqueue("appldata");
-	if (!appldata_wq)
-		return -ENOMEM;
+	if (!appldata_wq) {
+		rc = -ENOMEM;
+		goto out_device;
+	}
 
 	get_online_cpus();
 	for_each_online_cpu(i)
@@ -547,6 +652,12 @@
 
 	appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
 	return 0;
+
+out_device:
+	platform_device_unregister(appldata_pdev);
+out_driver:
+	platform_driver_unregister(&appldata_pdrv);
+	return rc;
 }
 
 __initcall(appldata_init);
diff -druN linux-libre-2.6.30-gnu/arch/s390/defconfig linux-libre-2.6.31-gnu/arch/s390/defconfig
--- linux-libre-2.6.30-gnu/arch/s390/defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Thu Apr 23 09:29:52 2009
+# Linux kernel version: 2.6.30
+# Mon Jun 22 11:08:16 2009
 #
 CONFIG_SCHED_MC=y
 CONFIG_MMU=y
@@ -25,6 +25,7 @@
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_S390=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -90,7 +91,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -103,7 +103,14 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -119,6 +126,11 @@
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_HAVE_DEFAULT_NO_SPIN_MUTEXES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -150,7 +162,7 @@
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
 CONFIG_PREEMPT_NOTIFIERS=y
-# CONFIG_FREEZER is not set
+CONFIG_FREEZER=y
 
 #
 # Base setup
@@ -199,6 +211,7 @@
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -218,9 +231,9 @@
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # I/O subsystem configuration
@@ -257,6 +270,16 @@
 # CONFIG_ZFCPDUMP is not set
 CONFIG_S390_GUEST=y
 CONFIG_SECCOMP=y
+
+#
+# Power Management
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
 CONFIG_NET=y
 
 #
@@ -384,6 +407,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -446,6 +470,7 @@
 # CAN Device Drivers
 #
 CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEV is not set
 # CONFIG_CAN_DEBUG_DEVICES is not set
 # CONFIG_AF_RXRPC is not set
 # CONFIG_WIMAX is not set
@@ -524,10 +549,6 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
@@ -578,7 +599,6 @@
 # CONFIG_DM_DELAY is not set
 # CONFIG_DM_UEVENT is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_IFB is not set
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
@@ -595,6 +615,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 # CONFIG_TR is not set
@@ -674,6 +695,11 @@
 # CONFIG_MONREADER is not set
 CONFIG_MONWRITER=m
 CONFIG_S390_VMUR=m
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
@@ -683,6 +709,10 @@
 # CONFIG_NEW_LEDS is not set
 CONFIG_ACCESSIBILITY=y
 # CONFIG_AUXDISPLAY is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -703,11 +733,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -865,19 +896,23 @@
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -886,6 +921,7 @@
 CONFIG_SAMPLES=y
 # CONFIG_SAMPLE_KOBJECT is not set
 # CONFIG_SAMPLE_KPROBES is not set
+# CONFIG_KMEMCHECK is not set
 
 #
 # Security options
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/s390/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -268,13 +268,18 @@
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
 #undef __CSG_LOOP
-#endif
+
+#else /* __s390x__ */
+
+#include <asm-generic/atomic64.h>
+
+#endif /* __s390x__ */
 
 #define smp_mb__before_atomic_dec()	smp_mb()
 #define smp_mb__after_atomic_dec()	smp_mb()
 #define smp_mb__before_atomic_inc()	smp_mb()
 #define smp_mb__after_atomic_inc()	smp_mb()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* __KERNEL__ */
 #endif /* __ARCH_S390_ATOMIC__  */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/s390/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,13 @@
+#ifndef __ASM_S390_BITSPERLONG_H
+#define __ASM_S390_BITSPERLONG_H
+
+#ifndef __s390x__
+#define __BITS_PER_LONG 32
+#else
+#define __BITS_PER_LONG 64
+#endif
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_S390_BITSPERLONG_H */
+
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/ccwdev.h linux-libre-2.6.31-gnu/arch/s390/include/asm/ccwdev.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/ccwdev.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/ccwdev.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,11 +1,9 @@
 /*
- *  include/asm-s390/ccwdev.h
- *  include/asm-s390x/ccwdev.h
+ * Copyright  IBM Corp. 2002, 2009
  *
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Arnd Bergmann <arndb@de.ibm.com>
+ * Author(s): Arnd Bergmann <arndb@de.ibm.com>
  *
- *  Interface for CCW device drivers
+ * Interface for CCW device drivers
  */
 #ifndef _S390_CCWDEV_H_
 #define _S390_CCWDEV_H_
@@ -104,6 +102,11 @@
  * @set_offline: called when setting device offline
  * @notify: notify driver of device state changes
  * @shutdown: called at device shutdown
+ * @prepare: prepare for pm state transition
+ * @complete: undo work done in @prepare
+ * @freeze: callback for freezing during hibernation snapshotting
+ * @thaw: undo work done in @freeze
+ * @restore: callback for restoring after hibernation
  * @driver: embedded device driver structure
  * @name: device driver name
  */
@@ -116,6 +119,11 @@
 	int (*set_offline) (struct ccw_device *);
 	int (*notify) (struct ccw_device *, int);
 	void (*shutdown) (struct ccw_device *);
+	int (*prepare) (struct ccw_device *);
+	void (*complete) (struct ccw_device *);
+	int (*freeze)(struct ccw_device *);
+	int (*thaw) (struct ccw_device *);
+	int (*restore)(struct ccw_device *);
 	struct device_driver driver;
 	char *name;
 };
@@ -184,6 +192,7 @@
 #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
 
 extern struct ccw_device *ccw_device_probe_console(void);
+extern int ccw_device_force_console(void);
 
 // FIXME: these have to go
 extern int _ccw_device_get_subchannel_number(struct ccw_device *);
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/ccwgroup.h linux-libre-2.6.31-gnu/arch/s390/include/asm/ccwgroup.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/ccwgroup.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/ccwgroup.h	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,11 @@
  * @set_online: function called when device is set online
  * @set_offline: function called when device is set offline
  * @shutdown: function called when device is shut down
+ * @prepare: prepare for pm state transition
+ * @complete: undo work done in @prepare
+ * @freeze: callback for freezing during hibernation snapshotting
+ * @thaw: undo work done in @freeze
+ * @restore: callback for restoring after hibernation
  * @driver: embedded driver structure
  */
 struct ccwgroup_driver {
@@ -51,6 +56,11 @@
 	int (*set_online) (struct ccwgroup_device *);
 	int (*set_offline) (struct ccwgroup_device *);
 	void (*shutdown)(struct ccwgroup_device *);
+	int (*prepare) (struct ccwgroup_device *);
+	void (*complete) (struct ccwgroup_device *);
+	int (*freeze)(struct ccwgroup_device *);
+	int (*thaw) (struct ccwgroup_device *);
+	int (*restore)(struct ccwgroup_device *);
 
 	struct device_driver driver;
 };
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/compat.h linux-libre-2.6.31-gnu/arch/s390/include/asm/compat.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/compat.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/compat.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,6 +5,7 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/thread_info.h>
 
 #define PSW32_MASK_PER		0x40000000UL
 #define PSW32_MASK_DAT		0x04000000UL
@@ -163,12 +164,28 @@
 	return (u32)(unsigned long)uptr;
 }
 
+#ifdef CONFIG_COMPAT
+
+static inline int is_compat_task(void)
+{
+	return test_thread_flag(TIF_31BIT);
+}
+
+#else
+
+static inline int is_compat_task(void)
+{
+	return 0;
+}
+
+#endif
+
 static inline void __user *compat_alloc_user_space(long len)
 {
 	unsigned long stack;
 
 	stack = KSTK_ESP(current);
-	if (test_thread_flag(TIF_31BIT))
+	if (is_compat_task())
 		stack &= 0x7fffffffUL;
 	return (void __user *) (stack - len);
 }
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/cpu.h linux-libre-2.6.31-gnu/arch/s390/include/asm/cpu.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/cpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/cpu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- *  include/asm-s390/cpu.h
- *
- *    Copyright IBM Corp. 2007
- *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- */
-
-#ifndef _ASM_S390_CPU_H_
-#define _ASM_S390_CPU_H_
-
-#include <linux/types.h>
-#include <linux/percpu.h>
-#include <linux/spinlock.h>
-
-struct s390_idle_data {
-	spinlock_t lock;
-	unsigned long long idle_count;
-	unsigned long long idle_enter;
-	unsigned long long idle_time;
-};
-
-DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
-
-void vtime_start_cpu(void);
-
-static inline void s390_idle_check(void)
-{
-	if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
-		vtime_start_cpu();
-}
-
-#endif /* _ASM_S390_CPU_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/cputime.h linux-libre-2.6.31-gnu/arch/s390/include/asm/cputime.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/cputime.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/cputime.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,9 @@
 #ifndef _S390_CPUTIME_H
 #define _S390_CPUTIME_H
 
+#include <linux/types.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
 #include <asm/div64.h>
 
 /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */
@@ -174,8 +177,24 @@
        return __div(cputime, 4096000000ULL / USER_HZ);
 }
 
+struct s390_idle_data {
+	unsigned int sequence;
+	unsigned long long idle_count;
+	unsigned long long idle_enter;
+	unsigned long long idle_time;
+};
+
+DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
+
+void vtime_start_cpu(void);
 cputime64_t s390_get_idle_time(int cpu);
 
 #define arch_idle_time(cpu) s390_get_idle_time(cpu)
 
+static inline void s390_idle_check(void)
+{
+	if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
+		vtime_start_cpu();
+}
+
 #endif /* _S390_CPUTIME_H */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/debug.h linux-libre-2.6.31-gnu/arch/s390/include/asm/debug.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/debug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/debug.h	2009-09-09 18:13:59.000000000 -0400
@@ -248,14 +248,5 @@
 #define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
 #endif				/* DASD_DEBUG */
 
-#undef DEBUG_MALLOC
-#ifdef DEBUG_MALLOC
-void *b;
-#define kmalloc(x...) (PRINT_INFO(" kmalloc %p\n",b=kmalloc(x)),b)
-#define kfree(x) PRINT_INFO(" kfree %p\n",x);kfree(x)
-#define get_zeroed_page(x...) (PRINT_INFO(" gfp %p\n",b=get_zeroed_page(x)),b)
-#define __get_free_pages(x...) (PRINT_INFO(" gfps %p\n",b=__get_free_pages(x)),b)
-#endif				/* DEBUG_MALLOC */
-
 #endif				/* __KERNEL__ */
 #endif				/* DEBUG_H */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/ftrace.h linux-libre-2.6.31-gnu/arch/s390/include/asm/ftrace.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/ftrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/ftrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,28 @@
 #define _ASM_S390_FTRACE_H
 
 #ifndef __ASSEMBLY__
+
 extern void _mcount(void);
+extern unsigned long ftrace_dyn_func;
+
+struct dyn_arch_ftrace { };
+
+#define MCOUNT_ADDR ((long)_mcount)
+
+#ifdef CONFIG_64BIT
+#define MCOUNT_OFFSET_RET 18
+#define MCOUNT_INSN_SIZE  24
+#define MCOUNT_OFFSET	  14
+#else
+#define MCOUNT_OFFSET_RET 26
+#define MCOUNT_INSN_SIZE  30
+#define MCOUNT_OFFSET	   8
 #endif
 
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	return addr - MCOUNT_OFFSET;
+}
+
+#endif /* __ASSEMBLY__ */
 #endif /* _ASM_S390_FTRACE_H */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/s390/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,22 +2,7 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,	
-	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
 #endif
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/kvm_host.h linux-libre-2.6.31-gnu/arch/s390/include/asm/kvm_host.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/kvm_host.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/kvm_host.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,8 @@
 
 #ifndef ASM_KVM_HOST_H
 #define ASM_KVM_HOST_H
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
 #include <linux/kvm_host.h>
 #include <asm/debug.h>
 #include <asm/cpuid.h>
@@ -97,7 +99,9 @@
 	__u8	reservedd0[48];		/* 0x00d0 */
 	__u64	gcr[16];		/* 0x0100 */
 	__u64	gbea;			/* 0x0180 */
-	__u8	reserved188[120];	/* 0x0188 */
+	__u8	reserved188[24];	/* 0x0188 */
+	__u32	fac;			/* 0x01a0 */
+	__u8	reserved1a4[92];	/* 0x01a4 */
 } __attribute__((packed));
 
 struct kvm_vcpu_stat {
@@ -210,7 +214,8 @@
 	s390_fp_regs      guest_fpregs;
 	unsigned int      guest_acrs[NUM_ACRS];
 	struct kvm_s390_local_interrupt local_int;
-	struct timer_list ckc_timer;
+	struct hrtimer    ckc_timer;
+	struct tasklet_struct tasklet;
 	union  {
 		cpuid_t	  cpu_id;
 		u64	  stidp_data;
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/lowcore.h linux-libre-2.6.31-gnu/arch/s390/include/asm/lowcore.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/lowcore.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/lowcore.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 #define __LC_SUBCHANNEL_NR		0x00ba
 #define __LC_IO_INT_PARM		0x00bc
 #define __LC_IO_INT_WORD		0x00c0
+#define __LC_STFL_FAC_LIST		0x00c8
 #define __LC_MCCK_CODE			0x00e8
 
 #define __LC_DUMP_REIPL			0x0e00
@@ -67,6 +68,7 @@
 #define __LC_CPUID			0x02b0
 #define __LC_INT_CLOCK			0x02c8
 #define __LC_MACHINE_FLAGS		0x02d8
+#define __LC_FTRACE_FUNC		0x02dc
 #define __LC_IRB			0x0300
 #define __LC_PFAULT_INTPARM		0x0080
 #define __LC_CPU_TIMER_SAVE_AREA	0x00d8
@@ -112,6 +114,7 @@
 #define __LC_INT_CLOCK			0x0340
 #define __LC_VDSO_PER_CPU		0x0350
 #define __LC_MACHINE_FLAGS		0x0358
+#define __LC_FTRACE_FUNC		0x0360
 #define __LC_IRB			0x0380
 #define __LC_PASTE			0x03c0
 #define __LC_PFAULT_INTPARM		0x11b8
@@ -280,7 +283,8 @@
 	__u64	int_clock;			/* 0x02c8 */
 	__u64	clock_comparator;		/* 0x02d0 */
 	__u32	machine_flags;			/* 0x02d8 */
-	__u8	pad_0x02dc[0x0300-0x02dc];	/* 0x02dc */
+	__u32	ftrace_func;			/* 0x02dc */
+	__u8	pad_0x02f0[0x0300-0x02f0];	/* 0x02f0 */
 
 	/* Interrupt response block */
 	__u8	irb[64];			/* 0x0300 */
@@ -385,7 +389,8 @@
 	__u64	clock_comparator;		/* 0x0348 */
 	__u64	vdso_per_cpu_data;		/* 0x0350 */
 	__u64	machine_flags;			/* 0x0358 */
-	__u8	pad_0x0360[0x0380-0x0360];	/* 0x0360 */
+	__u64	ftrace_func;			/* 0x0360 */
+	__u8	pad_0x0368[0x0380-0x0368];	/* 0x0368 */
 
 	/* Interrupt response block. */
 	__u8	irb[64];			/* 0x0380 */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/mman.h linux-libre-2.6.31-gnu/arch/s390/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,7 +9,7 @@
 #ifndef __S390_MMAN_H__
 #define __S390_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/page.h linux-libre-2.6.31-gnu/arch/s390/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -150,7 +150,7 @@
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #define __HAVE_ARCH_GATE_AREA 1
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/perf_counter.h linux-libre-2.6.31-gnu/arch/s390/include/asm/perf_counter.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/perf_counter.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/perf_counter.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,10 @@
+/*
+ * Performance counter support - s390 specific definitions.
+ *
+ * Copyright 2009 Martin Schwidefsky, IBM Corporation.
+ */
+
+static inline void set_perf_counter_pending(void) {}
+static inline void clear_perf_counter_pending(void) {}
+
+#define PERF_COUNTER_INDEX_OFFSET 0
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/s390/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -112,12 +112,15 @@
  * effect, this also makes sure that 64 bit module code cannot be used
  * as system call address.
  */
+
+extern unsigned long VMALLOC_START;
+
 #ifndef __s390x__
-#define VMALLOC_START	0x78000000UL
+#define VMALLOC_SIZE	(96UL << 20)
 #define VMALLOC_END	0x7e000000UL
 #define VMEM_MAP_END	0x80000000UL
 #else /* __s390x__ */
-#define VMALLOC_START	0x3e000000000UL
+#define VMALLOC_SIZE	(1UL << 30)
 #define VMALLOC_END	0x3e040000000UL
 #define VMEM_MAP_END	0x40000000000UL
 #endif /* __s390x__ */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/qdio.h linux-libre-2.6.31-gnu/arch/s390/include/asm/qdio.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/qdio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/qdio.h	2009-09-09 18:13:59.000000000 -0400
@@ -380,7 +380,7 @@
 extern int qdio_activate(struct ccw_device *);
 
 extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
-		   int q_nr, int bufnr, int count);
+		   int q_nr, unsigned int bufnr, unsigned int count);
 extern int qdio_cleanup(struct ccw_device*, int);
 extern int qdio_shutdown(struct ccw_device*, int);
 extern int qdio_free(struct ccw_device *);
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/seccomp.h linux-libre-2.6.31-gnu/arch/s390/include/asm/seccomp.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/seccomp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/seccomp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef _ASM_S390_SECCOMP_H
+#define _ASM_S390_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read	__NR_read
+#define __NR_seccomp_write	__NR_write
+#define __NR_seccomp_exit	__NR_exit
+#define __NR_seccomp_sigreturn	__NR_sigreturn
+
+#define __NR_seccomp_read_32	__NR_read
+#define __NR_seccomp_write_32	__NR_write
+#define __NR_seccomp_exit_32	__NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif	/* _ASM_S390_SECCOMP_H */
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/signal.h linux-libre-2.6.31-gnu/arch/s390/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -115,7 +115,7 @@
 #define MINSIGSTKSZ     2048
 #define SIGSTKSZ        8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/spinlock.h linux-libre-2.6.31-gnu/arch/s390/include/asm/spinlock.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/spinlock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/spinlock.h	2009-09-09 18:13:59.000000000 -0400
@@ -122,8 +122,10 @@
 #define __raw_write_can_lock(x) ((x)->lock == 0)
 
 extern void _raw_read_lock_wait(raw_rwlock_t *lp);
+extern void _raw_read_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
 extern int _raw_read_trylock_retry(raw_rwlock_t *lp);
 extern void _raw_write_lock_wait(raw_rwlock_t *lp);
+extern void _raw_write_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
 extern int _raw_write_trylock_retry(raw_rwlock_t *lp);
 
 static inline void __raw_read_lock(raw_rwlock_t *rw)
@@ -134,6 +136,14 @@
 		_raw_read_lock_wait(rw);
 }
 
+static inline void __raw_read_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+	unsigned int old;
+	old = rw->lock & 0x7fffffffU;
+	if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old)
+		_raw_read_lock_wait_flags(rw, flags);
+}
+
 static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
 	unsigned int old, cmp;
@@ -151,6 +161,12 @@
 		_raw_write_lock_wait(rw);
 }
 
+static inline void __raw_write_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+	if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
+		_raw_write_lock_wait_flags(rw, flags);
+}
+
 static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
 	_raw_compare_and_swap(&rw->lock, 0x80000000, 0);
@@ -172,9 +188,6 @@
 	return _raw_write_trylock_retry(rw);
 }
 
-#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
-#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
-
 #define _raw_read_relax(lock)	cpu_relax()
 #define _raw_write_relax(lock)	cpu_relax()
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/suspend.h linux-libre-2.6.31-gnu/arch/s390/include/asm/suspend.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/suspend.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/suspend.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,10 @@
 #ifndef __ASM_S390_SUSPEND_H
 #define __ASM_S390_SUSPEND_H
 
+static inline int arch_prepare_suspend(void)
+{
+	return 0;
+}
+
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/syscall.h linux-libre-2.6.31-gnu/arch/s390/include/asm/syscall.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/syscall.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/syscall.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,7 @@
 #ifndef _ASM_SYSCALL_H
 #define _ASM_SYSCALL_H	1
 
+#include <linux/sched.h>
 #include <asm/ptrace.h>
 
 static inline long syscall_get_nr(struct task_struct *task,
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/system.h linux-libre-2.6.31-gnu/arch/s390/include/asm/system.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,11 +1,7 @@
 /*
- *  include/asm-s390/system.h
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ * Copyright IBM Corp. 1999, 2009
  *
- *  Derived from "include/asm-i386/system.h"
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
 #ifndef __ASM_SYSTEM_H
@@ -469,6 +465,20 @@
 extern psw_t io_restore_trace_psw;
 #endif
 
+static inline int tprot(unsigned long addr)
+{
+	int rc = -EFAULT;
+
+	asm volatile(
+		"	tprot	0(%1),0\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "+d" (rc) : "a" (addr) : "cc");
+	return rc;
+}
+
 #endif /* __KERNEL__ */
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/termios.h linux-libre-2.6.31-gnu/arch/s390/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -60,7 +60,7 @@
 #define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
 #define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
 
-#include <asm-generic/termios.h>
+#include <asm-generic/termios-base.h>
 
 #endif	/* __KERNEL__ */
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/s390/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -61,7 +61,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -83,14 +83,16 @@
 /*
  * thread information flags bit numbers
  */
-#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_NOTIFY_RESUME	1	/* callback before returning to user */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTART_SVC		4	/* restart svc with new svc number */
-#define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
 #define TIF_SINGLE_STEP		6	/* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING	7	/* machine check handling is pending */
+#define TIF_SYSCALL_TRACE	8	/* syscall trace active */
+#define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
+#define TIF_SECCOMP		10	/* secure computing */
+#define TIF_SYSCALL_FTRACE	11	/* ftrace syscall instrumentation */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling 
 					   TIF_NEED_RESCHED */
@@ -99,15 +101,17 @@
 #define TIF_RESTORE_SIGMASK	20	/* restore signal mask in do_signal() */
 #define TIF_FREEZE		21	/* thread is freezing for suspend */
 
-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_RESTART_SVC	(1<<TIF_RESTART_SVC)
-#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_SYSCALL_FTRACE	(1<<TIF_SYSCALL_FTRACE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/s390/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -96,7 +96,8 @@
  * pte_free_tlb frees a pte table and clears the CRSTE for the
  * page table from the tlb.
  */
-static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte)
+static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
+				unsigned long address)
 {
 	if (!tlb->fullmm) {
 		tlb->array[tlb->nr_ptes++] = pte;
@@ -113,7 +114,8 @@
  * as the pgd. pmd_free_tlb checks the asce_limit against 2GB
  * to avoid the double free of the pmd in this case.
  */
-static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+				unsigned long address)
 {
 #ifdef __s390x__
 	if (tlb->mm->context.asce_limit <= (1UL << 31))
@@ -134,7 +136,8 @@
  * as the pgd. pud_free_tlb checks the asce_limit against 4TB
  * to avoid the double free of the pud in this case.
  */
-static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
+				unsigned long address)
 {
 #ifdef __s390x__
 	if (tlb->mm->context.asce_limit <= (1UL << 42))
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/types.h linux-libre-2.6.31-gnu/arch/s390/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -28,12 +28,6 @@
  */
 #ifdef __KERNEL__
 
-#ifndef __s390x__
-#define BITS_PER_LONG 32
-#else
-#define BITS_PER_LONG 64
-#endif
-
 #ifndef __ASSEMBLY__
 
 typedef u64 dma64_addr_t;
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/uaccess.h linux-libre-2.6.31-gnu/arch/s390/include/asm/uaccess.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/uaccess.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/uaccess.h	2009-09-09 18:13:59.000000000 -0400
@@ -131,7 +131,7 @@
 
 #define put_user(x, ptr)					\
 ({								\
-	might_sleep();						\
+	might_fault();						\
 	__put_user(x, ptr);					\
 })
 
@@ -180,7 +180,7 @@
 
 #define get_user(x, ptr)					\
 ({								\
-	might_sleep();						\
+	might_fault();						\
 	__get_user(x, ptr);					\
 })
 
@@ -231,7 +231,7 @@
 static inline unsigned long __must_check
 copy_to_user(void __user *to, const void *from, unsigned long n)
 {
-	might_sleep();
+	might_fault();
 	if (access_ok(VERIFY_WRITE, to, n))
 		n = __copy_to_user(to, from, n);
 	return n;
@@ -282,7 +282,7 @@
 static inline unsigned long __must_check
 copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-	might_sleep();
+	might_fault();
 	if (access_ok(VERIFY_READ, from, n))
 		n = __copy_from_user(to, from, n);
 	else
@@ -299,7 +299,7 @@
 static inline unsigned long __must_check
 copy_in_user(void __user *to, const void __user *from, unsigned long n)
 {
-	might_sleep();
+	might_fault();
 	if (__access_ok(from,n) && __access_ok(to,n))
 		n = __copy_in_user(to, from, n);
 	return n;
@@ -312,7 +312,7 @@
 strncpy_from_user(char *dst, const char __user *src, long count)
 {
         long res = -EFAULT;
-        might_sleep();
+	might_fault();
         if (access_ok(VERIFY_READ, src, 1))
 		res = uaccess.strncpy_from_user(count, src, dst);
         return res;
@@ -321,7 +321,7 @@
 static inline unsigned long
 strnlen_user(const char __user * src, unsigned long n)
 {
-	might_sleep();
+	might_fault();
 	return uaccess.strnlen_user(n, src);
 }
 
@@ -354,7 +354,7 @@
 static inline unsigned long __must_check
 clear_user(void __user *to, unsigned long n)
 {
-	might_sleep();
+	might_fault();
 	if (access_ok(VERIFY_WRITE, to, n))
 		n = uaccess.clear_user(n, to);
 	return n;
diff -druN linux-libre-2.6.30-gnu/arch/s390/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/s390/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/s390/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -267,7 +267,9 @@
 #define __NR_epoll_create1	327
 #define	__NR_preadv		328
 #define	__NR_pwritev		329
-#define NR_syscalls 330
+#define __NR_rt_tgsigqueueinfo	330
+#define __NR_perf_counter_open	331
+#define NR_syscalls 332
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff -druN linux-libre-2.6.30-gnu/arch/s390/Kconfig linux-libre-2.6.31-gnu/arch/s390/Kconfig
--- linux-libre-2.6.30-gnu/arch/s390/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -82,6 +82,11 @@
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_SYSCALL_WRAPPERS
 	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FTRACE_SYSCALLS
+	select HAVE_DYNAMIC_FTRACE
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_DEFAULT_NO_SPIN_MUTEXES
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
@@ -89,6 +94,12 @@
 	select HAVE_KVM if 64BIT
 	select HAVE_ARCH_TRACEHOOK
 	select INIT_ALL_POSSIBLE
+	select HAVE_PERF_COUNTERS
+	select GENERIC_ATOMIC64 if !64BIT
+
+config SCHED_OMIT_FRAME_POINTER
+	bool
+	default y
 
 source "init/Kconfig"
 
@@ -110,6 +121,9 @@
 	bool
 	default y if !64BIT
 
+config KTIME_SCALAR
+	def_bool 32BIT
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -343,6 +357,9 @@
 config ARCH_ENABLE_MEMORY_HOTREMOVE
 	def_bool y
 
+config ARCH_HIBERNATION_POSSIBLE
+       def_bool y if 64BIT
+
 source "mm/Kconfig"
 
 comment "I/O subsystem configuration"
@@ -567,6 +584,30 @@
 	  the KVM hypervisor. This will add detection for KVM as well  as a
 	  virtio transport. If KVM is detected, the virtio console will be
 	  the default console.
+
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y.
+
+endmenu
+
+menu "Power Management"
+
+source "kernel/power/Kconfig"
+
 endmenu
 
 source "net/Kconfig"
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/compat_linux.c linux-libre-2.6.31-gnu/arch/s390/kernel/compat_linux.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/compat_linux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/compat_linux.c	2009-09-09 18:13:59.000000000 -0400
@@ -461,9 +461,6 @@
 		result = rc;
 		goto out_putname;
 	}
-	task_lock(current);
-	current->ptrace &= ~PT_DTRACE;
-	task_unlock(current);
 	current->thread.fp_regs.fpc=0;
 	asm volatile("sfpc %0,0" : : "d" (0));
 	result = regs->gprs[2];
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/compat_wrapper.S linux-libre-2.6.31-gnu/arch/s390/kernel/compat_wrapper.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/compat_wrapper.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/compat_wrapper.S	2009-09-09 18:13:59.000000000 -0400
@@ -1823,3 +1823,20 @@
 	llgfr	%r5,%r5			# u32
 	llgfr	%r6,%r6			# u32
 	jg	compat_sys_pwritev	# branch to system call
+
+	.globl	compat_sys_rt_tgsigqueueinfo_wrapper
+compat_sys_rt_tgsigqueueinfo_wrapper:
+	lgfr	%r2,%r2			# compat_pid_t
+	lgfr	%r3,%r3			# compat_pid_t
+	lgfr	%r4,%r4			# int
+	llgtr	%r5,%r5			# struct compat_siginfo *
+	jg	compat_sys_rt_tgsigqueueinfo_wrapper # branch to system call
+
+	.globl	sys_perf_counter_open_wrapper
+sys_perf_counter_open_wrapper:
+	llgtr	%r2,%r2			# const struct perf_counter_attr *
+	lgfr	%r3,%r3			# pid_t
+	lgfr	%r4,%r4			# int
+	lgfr	%r5,%r5			# int
+	llgfr	%r6,%r6			# unsigned long
+	jg	sys_perf_counter_open	# branch to system call
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/dis.c linux-libre-2.6.31-gnu/arch/s390/kernel/dis.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/dis.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/dis.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/early.c linux-libre-2.6.31-gnu/arch/s390/kernel/early.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/early.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/early.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  arch/s390/kernel/early.c
  *
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Hongjie Yang <hongjie@us.ibm.com>,
  *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/ftrace.h>
 #include <linux/lockdep.h>
 #include <linux/module.h>
 #include <linux/pfn.h>
@@ -207,6 +208,9 @@
 		machine_flags |= MACHINE_FLAG_KVM;
 	else
 		machine_flags |= MACHINE_FLAG_VM;
+
+	/* Store machine flags for setting up lowcore early */
+	S390_lowcore.machine_flags = machine_flags;
 }
 
 static __init void early_pgm_check_handler(void)
@@ -410,5 +414,8 @@
 	sclp_facilities_detect();
 	detect_memory_layout(memory_chunk);
 	S390_lowcore.machine_flags = machine_flags;
+#ifdef CONFIG_DYNAMIC_FTRACE
+	S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
+#endif
 	lockdep_on();
 }
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/entry64.S linux-libre-2.6.31-gnu/arch/s390/kernel/entry64.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/entry64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/entry64.S	2009-09-09 18:13:59.000000000 -0400
@@ -56,6 +56,8 @@
 		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
+		_TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -260,7 +262,7 @@
 	larl	%r10,sys_call_table_emu  # use 31 bit emulation system calls
 sysc_noemu:
 #endif
-	tm	__TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+	tm	__TI_flags+6(%r9),_TIF_SYSCALL
 	lgf	%r8,0(%r7,%r10) # load address of system call routine
 	jnz	sysc_tracesys
 	basr	%r14,%r8	# call sys_xxxx
@@ -391,7 +393,7 @@
 	basr	%r14,%r8		# call sys_xxx
 	stg	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
-	tm	__TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+	tm	__TI_flags+6(%r9),_TIF_SYSCALL
 	jz	sysc_return
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	larl	%r14,sysc_return	# return point is sysc_return
@@ -1058,6 +1060,7 @@
 
 		.section .rodata, "a"
 #define SYSCALL(esa,esame,emu)	.long esame
+	.globl	sys_call_table
 sys_call_table:
 #include "syscalls.S"
 #undef SYSCALL
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/entry.S linux-libre-2.6.31-gnu/arch/s390/kernel/entry.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,8 @@
 		 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
 		 _TIF_MCCK_PENDING)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
+		_TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -265,7 +267,7 @@
 	sth	%r7,SP_SVCNR(%r15)
 	sll	%r7,2		  # svc number *4
 	l	%r8,BASED(.Lsysc_table)
-	tm	__TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+	tm	__TI_flags+2(%r9),_TIF_SYSCALL
 	l	%r8,0(%r7,%r8)	  # get system call addr.
 	bnz	BASED(sysc_tracesys)
 	basr	%r14,%r8	  # call sys_xxxx
@@ -405,7 +407,7 @@
 	basr	%r14,%r8		# call sys_xxx
 	st	%r2,SP_R2(%r15)		# store return value
 sysc_tracenogo:
-	tm	__TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+	tm	__TI_flags+2(%r9),_TIF_SYSCALL
 	bz	BASED(sysc_return)
 	l	%r1,BASED(.Ltrace_exit)
 	la	%r2,SP_PTREGS(%r15)	# load pt_regs
@@ -1107,6 +1109,7 @@
 
 		.section .rodata, "a"
 #define SYSCALL(esa,esame,emu)	.long esa
+	.globl	sys_call_table
 sys_call_table:
 #include "syscalls.S"
 #undef SYSCALL
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/ftrace.c linux-libre-2.6.31-gnu/arch/s390/kernel/ftrace.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/ftrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/ftrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,260 @@
+/*
+ * Dynamic function tracer architecture backend.
+ *
+ * Copyright IBM Corp. 2009
+ *
+ *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+#include <linux/hardirq.h>
+#include <linux/uaccess.h>
+#include <linux/ftrace.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <trace/syscall.h>
+#include <asm/lowcore.h>
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+void ftrace_disable_code(void);
+void ftrace_disable_return(void);
+void ftrace_call_code(void);
+void ftrace_nop_code(void);
+
+#define FTRACE_INSN_SIZE 4
+
+#ifdef CONFIG_64BIT
+
+asm(
+	"	.align	4\n"
+	"ftrace_disable_code:\n"
+	"	j	0f\n"
+	"	.word	0x0024\n"
+	"	lg	%r1,"__stringify(__LC_FTRACE_FUNC)"\n"
+	"	basr	%r14,%r1\n"
+	"ftrace_disable_return:\n"
+	"	lg	%r14,8(15)\n"
+	"	lgr	%r0,%r0\n"
+	"0:\n");
+
+asm(
+	"	.align	4\n"
+	"ftrace_nop_code:\n"
+	"	j	.+"__stringify(MCOUNT_INSN_SIZE)"\n");
+
+asm(
+	"	.align	4\n"
+	"ftrace_call_code:\n"
+	"	stg	%r14,8(%r15)\n");
+
+#else /* CONFIG_64BIT */
+
+asm(
+	"	.align	4\n"
+	"ftrace_disable_code:\n"
+	"	j	0f\n"
+	"	l	%r1,"__stringify(__LC_FTRACE_FUNC)"\n"
+	"	basr	%r14,%r1\n"
+	"ftrace_disable_return:\n"
+	"	l	%r14,4(%r15)\n"
+	"	j	0f\n"
+	"	bcr	0,%r7\n"
+	"	bcr	0,%r7\n"
+	"	bcr	0,%r7\n"
+	"	bcr	0,%r7\n"
+	"	bcr	0,%r7\n"
+	"	bcr	0,%r7\n"
+	"0:\n");
+
+asm(
+	"	.align	4\n"
+	"ftrace_nop_code:\n"
+	"	j	.+"__stringify(MCOUNT_INSN_SIZE)"\n");
+
+asm(
+	"	.align	4\n"
+	"ftrace_call_code:\n"
+	"	st	%r14,4(%r15)\n");
+
+#endif /* CONFIG_64BIT */
+
+static int ftrace_modify_code(unsigned long ip,
+			      void *old_code, int old_size,
+			      void *new_code, int new_size)
+{
+	unsigned char replaced[MCOUNT_INSN_SIZE];
+
+	/*
+	 * Note: Due to modules code can disappear and change.
+	 *  We need to protect against faulting as well as code
+	 *  changing. We do this by using the probe_kernel_*
+	 *  functions.
+	 *  This however is just a simple sanity check.
+	 */
+	if (probe_kernel_read(replaced, (void *)ip, old_size))
+		return -EFAULT;
+	if (memcmp(replaced, old_code, old_size) != 0)
+		return -EINVAL;
+	if (probe_kernel_write((void *)ip, new_code, new_size))
+		return -EPERM;
+	return 0;
+}
+
+static int ftrace_make_initial_nop(struct module *mod, struct dyn_ftrace *rec,
+				   unsigned long addr)
+{
+	return ftrace_modify_code(rec->ip,
+				  ftrace_call_code, FTRACE_INSN_SIZE,
+				  ftrace_disable_code, MCOUNT_INSN_SIZE);
+}
+
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+		    unsigned long addr)
+{
+	if (addr == MCOUNT_ADDR)
+		return ftrace_make_initial_nop(mod, rec, addr);
+	return ftrace_modify_code(rec->ip,
+				  ftrace_call_code, FTRACE_INSN_SIZE,
+				  ftrace_nop_code, FTRACE_INSN_SIZE);
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	return ftrace_modify_code(rec->ip,
+				  ftrace_nop_code, FTRACE_INSN_SIZE,
+				  ftrace_call_code, FTRACE_INSN_SIZE);
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	ftrace_dyn_func = (unsigned long)func;
+	return 0;
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+	return 0;
+}
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Patch the kernel code at ftrace_graph_caller location:
+ * The instruction there is branch relative on condition. The condition mask
+ * is either all ones (always branch aka disable ftrace_graph_caller) or all
+ * zeroes (nop aka enable ftrace_graph_caller).
+ * Instruction format for brc is a7m4xxxx where m is the condition mask.
+ */
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	unsigned short opcode = 0xa704;
+
+	return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	unsigned short opcode = 0xa7f4;
+
+	return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
+}
+
+static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
+{
+	return addr - (ftrace_disable_return - ftrace_disable_code);
+}
+
+#else /* CONFIG_DYNAMIC_FTRACE */
+
+static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
+{
+	return addr - MCOUNT_OFFSET_RET;
+}
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+/*
+ * Hook the return address and push it in the stack of return addresses
+ * in current thread info.
+ */
+unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
+{
+	struct ftrace_graph_ent trace;
+
+	/* Nmi's are currently unsupported. */
+	if (unlikely(in_nmi()))
+		goto out;
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		goto out;
+	if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
+		goto out;
+	trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN;
+	/* Only trace if the calling function expects to. */
+	if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		goto out;
+	}
+	parent = (unsigned long)return_to_handler;
+out:
+	return parent;
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+extern unsigned int sys_call_table[];
+
+static struct syscall_metadata **syscalls_metadata;
+
+struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+	if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
+		return NULL;
+
+	return syscalls_metadata[nr];
+}
+
+static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
+{
+	struct syscall_metadata *start;
+	struct syscall_metadata *stop;
+	char str[KSYM_SYMBOL_LEN];
+
+	start = (struct syscall_metadata *)__start_syscalls_metadata;
+	stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+	kallsyms_lookup(syscall, NULL, NULL, NULL, str);
+
+	for ( ; start < stop; start++) {
+		if (start->name && !strcmp(start->name + 3, str + 3))
+			return start;
+	}
+	return NULL;
+}
+
+void arch_init_ftrace_syscalls(void)
+{
+	struct syscall_metadata *meta;
+	int i;
+	static atomic_t refs;
+
+	if (atomic_inc_return(&refs) != 1)
+		goto out;
+	syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
+				    GFP_KERNEL);
+	if (!syscalls_metadata)
+		goto out;
+	for (i = 0; i < NR_syscalls; i++) {
+		meta = find_syscall_meta((unsigned long)sys_call_table[i]);
+		syscalls_metadata[i] = meta;
+	}
+	return;
+out:
+	atomic_dec(&refs);
+}
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/head.S linux-libre-2.6.31-gnu/arch/s390/kernel/head.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/head.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/head.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,5 @@
 /*
- *  arch/s390/kernel/head.S
- *
- * Copyright (C) IBM Corp. 1999,2006
+ * Copyright IBM Corp. 1999,2009
  *
  *    Author(s): Hartmut Penner <hp@de.ibm.com>
  *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -64,7 +62,7 @@
 	.org   0x100
 #
 # subroutine for loading from tape
-# Paramters:
+# Parameters:
 #  R1 = device number
 #  R2 = load address
 .Lloader:
@@ -479,27 +477,58 @@
 	mvc	__LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
 	mvc	__LC_EXIT_TIMER(8),5f-.LPG0(%r13)
 #ifndef CONFIG_MARCH_G5
-	# check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10}
-	stidp	__LC_CPUID		# store cpuid
-	lhi	%r0,(3f-2f) / 2
-	la	%r1,2f-.LPG0(%r13)
-0:	clc	__LC_CPUID+4(2),0(%r1)
-	jne	3f
-	lpsw	1f-.LPG0(13)		# machine type not good enough, crash
+	# check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
+	xc	__LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
+	stfl	__LC_STFL_FAC_LIST	# store facility list
+	tm	__LC_STFL_FAC_LIST,0x01	# stfle available ?
+	jz	0f
+	la	%r0,0
+	.insn	s,0xb2b00000,__LC_STFL_FAC_LIST	# store facility list extended
+0:	l	%r0,__LC_STFL_FAC_LIST
+	n	%r0,2f+8-.LPG0(%r13)
+	cl	%r0,2f+8-.LPG0(%r13)
+	jne	1f
+	l	%r0,__LC_STFL_FAC_LIST+4
+	n	%r0,2f+12-.LPG0(%r13)
+	cl	%r0,2f+12-.LPG0(%r13)
+	je	3f
+1:	l	%r15,.Lstack-.LPG0(%r13)
+	ahi	%r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
+	ahi	%r15,-96
+	la	%r2,.Lals_string-.LPG0(%r13)
+	l	%r3,.Lsclp_print-.LPG0(%r13)
+	basr	%r14,%r3
+	lpsw	2f-.LPG0(%r13)		# machine type not good enough, crash
+.Lals_string:
+	.asciz	"The Linux kernel requires more recent processor hardware"
+.Lsclp_print:
+	.long	_sclp_print_early
+.Lstack:
+	.long	init_thread_union
 	.align 16
-1:	.long	0x000a0000,0x00000000
-2:
+2:	.long	0x000a0000,0x8badcccc
+#if defined(CONFIG_64BIT)
 #if defined(CONFIG_MARCH_Z10)
-	.short 0x9672, 0x2064, 0x2066, 0x2084, 0x2086, 0x2094, 0x2096
+	.long 0xc100efe3, 0xf0680000
 #elif defined(CONFIG_MARCH_Z9_109)
-	.short 0x9672, 0x2064, 0x2066, 0x2084, 0x2086
+	.long 0xc100efc3, 0x00000000
 #elif defined(CONFIG_MARCH_Z990)
-	.short 0x9672, 0x2064, 0x2066
+	.long 0xc0002000, 0x00000000
 #elif defined(CONFIG_MARCH_Z900)
-	.short 0x9672
+	.long 0xc0000000, 0x00000000
 #endif
-3:	la	%r1,2(%r1)
-	brct	%r0,0b
+#else
+#if defined(CONFIG_MARCH_Z10)
+	.long 0x8100c880, 0x00000000
+#elif defined(CONFIG_MARCH_Z9_109)
+	.long 0x8100c880, 0x00000000
+#elif defined(CONFIG_MARCH_Z990)
+	.long 0x80002000, 0x00000000
+#elif defined(CONFIG_MARCH_Z900)
+	.long 0x80000000, 0x00000000
+#endif
+#endif
+3:
 #endif
 
 	l	%r13,4f-.LPG0(%r13)
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/init_task.c linux-libre-2.6.31-gnu/arch/s390/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,10 +18,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/ipl.c linux-libre-2.6.31-gnu/arch/s390/kernel/ipl.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/ipl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/ipl.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,6 +70,7 @@
 	char *name;
 	void (*fn) (struct shutdown_trigger *trigger);
 	int (*init) (void);
+	int init_rc;
 };
 
 static char *ipl_type_str(enum ipl_type type)
@@ -1486,11 +1487,13 @@
 	int i;
 
 	for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
-		if (!shutdown_actions_list[i])
-			continue;
 		if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
-			trigger->action = shutdown_actions_list[i];
-			return len;
+			if (shutdown_actions_list[i]->init_rc) {
+				return shutdown_actions_list[i]->init_rc;
+			} else {
+				trigger->action = shutdown_actions_list[i];
+				return len;
+			}
 		}
 	}
 	return -EINVAL;
@@ -1640,8 +1643,8 @@
 	for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
 		if (!shutdown_actions_list[i]->init)
 			continue;
-		if (shutdown_actions_list[i]->init())
-			shutdown_actions_list[i] = NULL;
+		shutdown_actions_list[i]->init_rc =
+			shutdown_actions_list[i]->init();
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/kprobes.c linux-libre-2.6.31-gnu/arch/s390/kernel/kprobes.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/kprobes.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/kprobes.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,9 +25,9 @@
 #include <linux/preempt.h>
 #include <linux/stop_machine.h>
 #include <linux/kdebug.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/sections.h>
-#include <asm/uaccess.h>
 #include <linux/module.h>
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
@@ -154,66 +154,35 @@
 
 static int __kprobes swap_instruction(void *aref)
 {
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	unsigned long status = kcb->kprobe_status;
 	struct ins_replace_args *args = aref;
-	u32 *addr;
-	u32 instr;
-	int err = -EFAULT;
-
-	/*
-	 * Text segment is read-only, hence we use stura to bypass dynamic
-	 * address translation to exchange the instruction. Since stura
-	 * always operates on four bytes, but we only want to exchange two
-	 * bytes do some calculations to get things right. In addition we
-	 * shall not cross any page boundaries (vmalloc area!) when writing
-	 * the new instruction.
-	 */
-	addr = (u32 *)((unsigned long)args->ptr & -4UL);
-	if ((unsigned long)args->ptr & 2)
-		instr = ((*addr) & 0xffff0000) | args->new;
-	else
-		instr = ((*addr) & 0x0000ffff) | args->new << 16;
-
-	asm volatile(
-		"	lra	%1,0(%1)\n"
-		"0:	stura	%2,%1\n"
-		"1:	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b,2b)
-		: "+d" (err)
-		: "a" (addr), "d" (instr)
-		: "memory", "cc");
+	int rc;
 
-	return err;
+	kcb->kprobe_status = KPROBE_SWAP_INST;
+	rc = probe_kernel_write(args->ptr, &args->new, sizeof(args->new));
+	kcb->kprobe_status = status;
+	return rc;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-	unsigned long status = kcb->kprobe_status;
 	struct ins_replace_args args;
 
 	args.ptr = p->addr;
 	args.old = p->opcode;
 	args.new = BREAKPOINT_INSTRUCTION;
-
-	kcb->kprobe_status = KPROBE_SWAP_INST;
 	stop_machine(swap_instruction, &args, NULL);
-	kcb->kprobe_status = status;
 }
 
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-	unsigned long status = kcb->kprobe_status;
 	struct ins_replace_args args;
 
 	args.ptr = p->addr;
 	args.old = BREAKPOINT_INSTRUCTION;
 	args.new = p->opcode;
-
-	kcb->kprobe_status = KPROBE_SWAP_INST;
 	stop_machine(swap_instruction, &args, NULL);
-	kcb->kprobe_status = status;
 }
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/Makefile linux-libre-2.6.31-gnu/arch/s390/kernel/Makefile
--- linux-libre-2.6.30-gnu/arch/s390/kernel/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,8 +3,9 @@
 #
 
 ifdef CONFIG_FUNCTION_TRACER
-# Do not trace early boot code
+# Don't trace early setup code and tracing code
 CFLAGS_REMOVE_early.o = -pg
+CFLAGS_REMOVE_ftrace.o = -pg
 endif
 
 #
@@ -22,7 +23,7 @@
 obj-y	:=  bitmap.o traps.o time.o process.o base.o early.o setup.o \
 	    processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
 	    s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \
-	    vdso.o vtime.o sysinfo.o nmi.o
+	    vdso.o vtime.o sysinfo.o nmi.o sclp.o
 
 obj-y	+= $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y	+= $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
@@ -41,6 +42,8 @@
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
+obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 
 # Kexec part
 S390_KEXEC_OBJS := machine_kexec.o crash.o
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/mcount.S linux-libre-2.6.31-gnu/arch/s390/kernel/mcount.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/mcount.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/mcount.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
  *
  *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
  *
@@ -7,36 +7,64 @@
 
 #include <asm/asm-offsets.h>
 
-#ifndef CONFIG_64BIT
-.globl _mcount
+	.globl ftrace_stub
+ftrace_stub:
+	br	%r14
+
+#ifdef CONFIG_64BIT
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+	.globl _mcount
 _mcount:
-	stm	%r0,%r5,8(%r15)
-	st	%r14,56(%r15)
-	lr	%r1,%r15
-	ahi	%r15,-96
-	l	%r3,100(%r15)
-	la	%r2,0(%r14)
-	st	%r1,__SF_BACKCHAIN(%r15)
-	la	%r3,0(%r3)
-	bras	%r14,0f
-	.long	ftrace_trace_function
-0:	l	%r14,0(%r14)
-	l	%r14,0(%r14)
-	basr	%r14,%r14
-	ahi	%r15,96
-	lm	%r0,%r5,8(%r15)
-	l	%r14,56(%r15)
 	br	%r14
 
-.globl ftrace_stub
-ftrace_stub:
+	.globl ftrace_caller
+ftrace_caller:
+	larl	%r1,function_trace_stop
+	icm	%r1,0xf,0(%r1)
+	bnzr	%r14
+	stmg	%r2,%r5,32(%r15)
+	stg	%r14,112(%r15)
+	lgr	%r1,%r15
+	aghi	%r15,-160
+	stg	%r1,__SF_BACKCHAIN(%r15)
+	lgr	%r2,%r14
+	lg	%r3,168(%r15)
+	larl	%r14,ftrace_dyn_func
+	lg	%r14,0(%r14)
+	basr	%r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl	ftrace_graph_caller
+ftrace_graph_caller:
+	# This unconditional branch gets runtime patched. Change only if
+	# you know what you are doing. See ftrace_enable_graph_caller().
+	j	0f
+	lg	%r2,272(%r15)
+	lg	%r3,168(%r15)
+	brasl	%r14,prepare_ftrace_return
+	stg	%r2,168(%r15)
+0:
+#endif
+	aghi	%r15,160
+	lmg	%r2,%r5,32(%r15)
+	lg	%r14,112(%r15)
 	br	%r14
 
-#else /* CONFIG_64BIT */
+	.data
+	.globl	ftrace_dyn_func
+ftrace_dyn_func:
+	.quad	ftrace_stub
+	.previous
 
-.globl _mcount
+#else /* CONFIG_DYNAMIC_FTRACE */
+
+	.globl _mcount
 _mcount:
-	stmg	%r0,%r5,16(%r15)
+	larl	%r1,function_trace_stop
+	icm	%r1,0xf,0(%r1)
+	bnzr	%r14
+	stmg	%r2,%r5,32(%r15)
 	stg	%r14,112(%r15)
 	lgr	%r1,%r15
 	aghi	%r15,-160
@@ -46,13 +74,143 @@
 	larl	%r14,ftrace_trace_function
 	lg	%r14,0(%r14)
 	basr	%r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	lg	%r2,272(%r15)
+	lg	%r3,168(%r15)
+	brasl	%r14,prepare_ftrace_return
+	stg	%r2,168(%r15)
+#endif
 	aghi	%r15,160
-	lmg	%r0,%r5,16(%r15)
+	lmg	%r2,%r5,32(%r15)
 	lg	%r14,112(%r15)
 	br	%r14
 
-.globl ftrace_stub
-ftrace_stub:
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+	.globl	return_to_handler
+return_to_handler:
+	stmg	%r2,%r5,32(%r15)
+	lgr	%r1,%r15
+	aghi	%r15,-160
+	stg	%r1,__SF_BACKCHAIN(%r15)
+	brasl	%r14,ftrace_return_to_handler
+	aghi	%r15,160
+	lgr	%r14,%r2
+	lmg	%r2,%r5,32(%r15)
+	br	%r14
+
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#else /* CONFIG_64BIT */
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+	.globl _mcount
+_mcount:
+	br	%r14
+
+	.globl ftrace_caller
+ftrace_caller:
+	stm	%r2,%r5,16(%r15)
+	bras	%r1,2f
+0:	.long	ftrace_trace_function
+1:	.long	function_trace_stop
+2:	l	%r2,1b-0b(%r1)
+	icm	%r2,0xf,0(%r2)
+	jnz	3f
+	st	%r14,56(%r15)
+	lr	%r0,%r15
+	ahi	%r15,-96
+	l	%r3,100(%r15)
+	la	%r2,0(%r14)
+	st	%r0,__SF_BACKCHAIN(%r15)
+	la	%r3,0(%r3)
+	l	%r14,0b-0b(%r1)
+	l	%r14,0(%r14)
+	basr	%r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl	ftrace_graph_caller
+ftrace_graph_caller:
+	# This unconditional branch gets runtime patched. Change only if
+	# you know what you are doing. See ftrace_enable_graph_caller().
+	j	1f
+	bras	%r1,0f
+	.long	prepare_ftrace_return
+0:	l	%r2,152(%r15)
+	l	%r4,0(%r1)
+	l	%r3,100(%r15)
+	basr	%r14,%r4
+	st	%r2,100(%r15)
+1:
+#endif
+	ahi	%r15,96
+	l	%r14,56(%r15)
+3:	lm	%r2,%r5,16(%r15)
+	br	%r14
+
+	.data
+	.globl	ftrace_dyn_func
+ftrace_dyn_func:
+	.long	ftrace_stub
+	.previous
+
+#else /* CONFIG_DYNAMIC_FTRACE */
+
+	.globl _mcount
+_mcount:
+	stm	%r2,%r5,16(%r15)
+	bras	%r1,2f
+0:	.long	ftrace_trace_function
+1:	.long	function_trace_stop
+2:	l	%r2,1b-0b(%r1)
+	icm	%r2,0xf,0(%r2)
+	jnz	3f
+	st	%r14,56(%r15)
+	lr	%r0,%r15
+	ahi	%r15,-96
+	l	%r3,100(%r15)
+	la	%r2,0(%r14)
+	st	%r0,__SF_BACKCHAIN(%r15)
+	la	%r3,0(%r3)
+	l	%r14,0b-0b(%r1)
+	l	%r14,0(%r14)
+	basr	%r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	bras	%r1,0f
+	.long	prepare_ftrace_return
+0:	l	%r2,152(%r15)
+	l	%r4,0(%r1)
+	l	%r3,100(%r15)
+	basr	%r14,%r4
+	st	%r2,100(%r15)
+#endif
+	ahi	%r15,96
+	l	%r14,56(%r15)
+3:	lm	%r2,%r5,16(%r15)
+	br	%r14
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+	.globl	return_to_handler
+return_to_handler:
+	stm	%r2,%r5,16(%r15)
+	st	%r14,56(%r15)
+	lr	%r0,%r15
+	ahi	%r15,-96
+	st	%r0,__SF_BACKCHAIN(%r15)
+	bras	%r1,0f
+	.long	ftrace_return_to_handler
+0:	l	%r2,0b-0b(%r1)
+	basr	%r14,%r2
+	lr	%r14,%r2
+	ahi	%r15,96
+	lm	%r2,%r5,16(%r15)
 	br	%r14
 
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 #endif /* CONFIG_64BIT */
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/mem_detect.c linux-libre-2.6.31-gnu/arch/s390/kernel/mem_detect.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/mem_detect.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/mem_detect.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 /*
- *    Copyright IBM Corp. 2008
- *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ * Copyright IBM Corp. 2008, 2009
+ *
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
 #include <linux/kernel.h>
@@ -9,20 +10,6 @@
 #include <asm/sclp.h>
 #include <asm/setup.h>
 
-static inline int tprot(unsigned long addr)
-{
-	int rc = -EFAULT;
-
-	asm volatile(
-		"	tprot	0(%1),0\n"
-		"0:	ipm	%0\n"
-		"	srl	%0,28\n"
-		"1:\n"
-		EX_TABLE(0b,1b)
-		: "+d" (rc) : "a" (addr) : "cc");
-	return rc;
-}
-
 #define ADDR2G (1ULL << 31)
 
 static void find_memory_chunks(struct mem_chunk chunk[])
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/module.c linux-libre-2.6.31-gnu/arch/s390/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -56,8 +56,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 static void
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/nmi.c linux-libre-2.6.31-gnu/arch/s390/kernel/nmi.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/nmi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/nmi.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,7 @@
 #include <asm/lowcore.h>
 #include <asm/smp.h>
 #include <asm/etr.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
 #include <asm/nmi.h>
 #include <asm/crw.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/process.c linux-libre-2.6.31-gnu/arch/s390/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/elfcore.h>
 #include <linux/kernel_stat.h>
 #include <linux/syscalls.h>
+#include <asm/compat.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -204,7 +205,7 @@
 	save_fp_regs(&p->thread.fp_regs);
 	/* Set a new TLS ?  */
 	if (clone_flags & CLONE_SETTLS) {
-		if (test_thread_flag(TIF_31BIT)) {
+		if (is_compat_task()) {
 			p->thread.acrs[0] = (unsigned int) regs->gprs[6];
 		} else {
 			p->thread.acrs[0] = (unsigned int)(regs->gprs[6] >> 32);
@@ -265,9 +266,6 @@
 
 asmlinkage void execve_tail(void)
 {
-	task_lock(current);
-	current->ptrace &= ~PT_DTRACE;
-	task_unlock(current);
 	current->thread.fp_regs.fpc = 0;
 	if (MACHINE_HAS_IEEE)
 		asm volatile("sfpc %0,%0" : : "d" (0));
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/s390/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
@@ -36,7 +35,9 @@
 #include <linux/elf.h>
 #include <linux/regset.h>
 #include <linux/tracehook.h>
-
+#include <linux/seccomp.h>
+#include <trace/syscall.h>
+#include <asm/compat.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -69,7 +70,7 @@
 	if (per_info->single_step) {
 		per_info->control_regs.bits.starting_addr = 0;
 #ifdef CONFIG_COMPAT
-		if (test_thread_flag(TIF_31BIT))
+		if (is_compat_task())
 			per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
 		else
 #endif
@@ -482,8 +483,7 @@
 {
 	__u32 tmp;
 
-	if (!test_thread_flag(TIF_31BIT) ||
-	    (addr & 3) || addr > sizeof(struct user) - 3)
+	if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user) - 3)
 		return -EIO;
 
 	tmp = __peek_user_compat(child, addr);
@@ -584,8 +584,7 @@
 static int poke_user_compat(struct task_struct *child,
 			    addr_t addr, addr_t data)
 {
-	if (!test_thread_flag(TIF_31BIT) ||
-	    (addr & 3) || addr > sizeof(struct user32) - 3)
+	if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user32) - 3)
 		return -EIO;
 
 	return __poke_user_compat(child, addr, data);
@@ -642,6 +641,9 @@
 {
 	long ret;
 
+	/* Do the secure computing check first. */
+	secure_computing(regs->gprs[2]);
+
 	/*
 	 * The sysc_tracesys code in entry.S stored the system
 	 * call number to gprs[2].
@@ -659,8 +661,11 @@
 		ret = -1;
 	}
 
+	if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+		ftrace_syscall_enter(regs);
+
 	if (unlikely(current->audit_context))
-		audit_syscall_entry(test_thread_flag(TIF_31BIT) ?
+		audit_syscall_entry(is_compat_task() ?
 					AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
 				    regs->gprs[2], regs->orig_gpr2,
 				    regs->gprs[3], regs->gprs[4],
@@ -674,6 +679,9 @@
 		audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
 				   regs->gprs[2]);
 
+	if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+		ftrace_syscall_exit(regs);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall_exit(regs, 0);
 }
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/s390_ext.c linux-libre-2.6.31-gnu/arch/s390/kernel/s390_ext.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/s390_ext.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/s390_ext.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,10 +10,11 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/ftrace.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
 #include <asm/lowcore.h>
 #include <asm/s390_ext.h>
 #include <asm/irq_regs.h>
@@ -112,7 +113,7 @@
 	return 0;
 }
 
-void do_extint(struct pt_regs *regs, unsigned short code)
+void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
 {
         ext_int_info_t *p;
         int index;
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/sclp.S linux-libre-2.6.31-gnu/arch/s390/kernel/sclp.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/sclp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/sclp.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,327 @@
+/*
+ * Mini SCLP driver.
+ *
+ * Copyright IBM Corp. 2004,2009
+ *
+ *   Author(s):	Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>,
+ *		Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+LC_EXT_NEW_PSW		= 0x58			# addr of ext int handler
+LC_EXT_INT_PARAM	= 0x80			# addr of ext int parameter
+LC_EXT_INT_CODE		= 0x86			# addr of ext int code
+
+#
+# Subroutine which waits synchronously until either an external interruption
+# or a timeout occurs.
+#
+# Parameters:
+#   R2	= 0 for no timeout, non-zero for timeout in (approximated) seconds
+#
+# Returns:
+#   R2	= 0 on interrupt, 2 on timeout
+#   R3	= external interruption parameter if R2=0
+#
+
+.section ".init.text","ax"
+
+_sclp_wait_int:
+	stm	%r6,%r15,24(%r15)		# save registers
+	basr	%r13,0				# get base register
+.LbaseS1:
+	ahi	%r15,-96			# create stack frame
+	la	%r8,LC_EXT_NEW_PSW		# register int handler
+	mvc	.LoldpswS1-.LbaseS1(8,%r13),0(%r8)
+	mvc	0(8,%r8),.LextpswS1-.LbaseS1(%r13)
+	lhi	%r6,0x0200			# cr mask for ext int (cr0.54)
+	ltr	%r2,%r2
+	jz	.LsetctS1
+	ahi	%r6,0x0800			# cr mask for clock int (cr0.52)
+	stck	.LtimeS1-.LbaseS1(%r13)		# initiate timeout
+	al	%r2,.LtimeS1-.LbaseS1(%r13)
+	st	%r2,.LtimeS1-.LbaseS1(%r13)
+	sckc	.LtimeS1-.LbaseS1(%r13)
+
+.LsetctS1:
+	stctl	%c0,%c0,.LctlS1-.LbaseS1(%r13)	# enable required interrupts
+	l	%r0,.LctlS1-.LbaseS1(%r13)
+	lhi	%r1,~(0x200 | 0x800)		# clear old values
+	nr	%r1,%r0
+	or	%r1,%r6				# set new value
+	st	%r1,.LctlS1-.LbaseS1(%r13)
+	lctl	%c0,%c0,.LctlS1-.LbaseS1(%r13)
+	st	%r0,.LctlS1-.LbaseS1(%r13)
+	lhi	%r2,2				# return code for timeout
+.LloopS1:
+	lpsw	.LwaitpswS1-.LbaseS1(%r13)	# wait until interrupt
+.LwaitS1:
+	lh	%r7,LC_EXT_INT_CODE
+	chi	%r7,0x1004			# timeout?
+	je	.LtimeoutS1
+	chi	%r7,0x2401			# service int?
+	jne	.LloopS1
+	sr	%r2,%r2
+	l	%r3,LC_EXT_INT_PARAM
+.LtimeoutS1:
+	lctl	%c0,%c0,.LctlS1-.LbaseS1(%r13)	# restore interrupt setting
+	# restore old handler
+	mvc	0(8,%r8),.LoldpswS1-.LbaseS1(%r13)
+	lm	%r6,%r15,120(%r15)		# restore registers
+	br	%r14				# return to caller
+
+	.align	8
+.LoldpswS1:
+	.long	0, 0				# old ext int PSW
+.LextpswS1:
+	.long	0x00080000, 0x80000000+.LwaitS1	# PSW to handle ext int
+.LwaitpswS1:
+	.long	0x010a0000, 0x00000000+.LloopS1	# PSW to wait for ext int
+.LtimeS1:
+	.quad	0				# current time
+.LctlS1:
+	.long	0				# CT0 contents
+
+#
+# Subroutine to synchronously issue a service call.
+#
+# Parameters:
+#   R2	= command word
+#   R3	= sccb address
+#
+# Returns:
+#   R2	= 0 on success, 1 on failure
+#   R3	= sccb response code if R2 = 0
+#
+
+_sclp_servc:
+	stm	%r6,%r15,24(%r15)		# save registers
+	ahi	%r15,-96			# create stack frame
+	lr	%r6,%r2				# save command word
+	lr	%r7,%r3				# save sccb address
+.LretryS2:
+	lhi	%r2,1				# error return code
+	.insn	rre,0xb2200000,%r6,%r7		# servc
+	brc	1,.LendS2			# exit if not operational
+	brc	8,.LnotbusyS2			# go on if not busy
+	sr	%r2,%r2				# wait until no longer busy
+	bras	%r14,_sclp_wait_int
+	j	.LretryS2			# retry
+.LnotbusyS2:
+	sr	%r2,%r2				# wait until result
+	bras	%r14,_sclp_wait_int
+	sr	%r2,%r2
+	lh	%r3,6(%r7)
+.LendS2:
+	lm	%r6,%r15,120(%r15)		# restore registers
+	br	%r14
+
+#
+# Subroutine to set up the SCLP interface.
+#
+# Parameters:
+#   R2	= 0 to activate, non-zero to deactivate
+#
+# Returns:
+#   R2	= 0 on success, non-zero on failure
+#
+
+_sclp_setup:
+	stm	%r6,%r15,24(%r15)		# save registers
+	ahi	%r15,-96			# create stack frame
+	basr	%r13,0				# get base register
+.LbaseS3:
+	l	%r6,.LsccbS0-.LbaseS3(%r13)	# prepare init mask sccb
+	mvc	0(.LinitendS3-.LinitsccbS3,%r6),.LinitsccbS3-.LbaseS3(%r13)
+	ltr	%r2,%r2				# initialization?
+	jz	.LdoinitS3			# go ahead
+	# clear masks
+	xc	.LinitmaskS3-.LinitsccbS3(8,%r6),.LinitmaskS3-.LinitsccbS3(%r6)
+.LdoinitS3:
+	l	%r2,.LwritemaskS3-.LbaseS3(%r13)# get command word
+	lr	%r3,%r6				# get sccb address
+	bras	%r14,_sclp_servc		# issue service call
+	ltr	%r2,%r2				# servc successful?
+	jnz	.LerrorS3
+	chi	%r3,0x20			# write mask successful?
+	jne	.LerrorS3
+	# check masks
+	la	%r2,.LinitmaskS3-.LinitsccbS3(%r6)
+	l	%r1,0(%r2)			# receive mask ok?
+	n	%r1,12(%r2)
+	cl	%r1,0(%r2)
+	jne	.LerrorS3
+	l	%r1,4(%r2)			# send mask ok?
+	n	%r1,8(%r2)
+	cl	%r1,4(%r2)
+	sr	%r2,%r2
+	je	.LendS3
+.LerrorS3:
+	lhi	%r2,1				# error return code
+.LendS3:
+	lm	%r6,%r15,120(%r15)		# restore registers
+	br	%r14
+.LwritemaskS3:
+	.long	0x00780005			# SCLP command for write mask
+.LinitsccbS3:
+	.word	.LinitendS3-.LinitsccbS3
+	.byte	0,0,0,0
+	.word	0
+	.word	0
+	.word	4
+.LinitmaskS3:
+	.long	0x80000000
+	.long	0x40000000
+	.long	0
+	.long	0
+.LinitendS3:
+
+#
+# Subroutine which prints a given text to the SCLP console.
+#
+# Parameters:
+#   R2	= address of nil-terminated ASCII text
+#
+# Returns:
+#   R2	= 0 on success, 1 on failure
+#
+
+_sclp_print:
+	stm	%r6,%r15,24(%r15)		# save registers
+	ahi	%r15,-96			# create stack frame
+	basr	%r13,0				# get base register
+.LbaseS4:
+	l	%r8,.LsccbS0-.LbaseS4(%r13)	# prepare write data sccb
+	mvc	0(.LmtoS4-.LwritesccbS4,%r8),.LwritesccbS4-.LbaseS4(%r13)
+	la	%r7,.LmtoS4-.LwritesccbS4(%r8)	# current mto addr
+	sr	%r0,%r0
+	l	%r10,.Lascebc-.LbaseS4(%r13)	# address of translation table
+.LinitmtoS4:
+	# initialize mto
+	mvc	0(.LmtoendS4-.LmtoS4,%r7),.LmtoS4-.LbaseS4(%r13)
+	lhi	%r6,.LmtoendS4-.LmtoS4		# current mto length
+.LloopS4:
+	ic	%r0,0(%r2)			# get character
+	ahi	%r2,1
+	ltr	%r0,%r0				# end of string?
+	jz	.LfinalizemtoS4
+	chi	%r0,0x15			# end of line (NL)?
+	jz	.LfinalizemtoS4
+	stc	%r0,0(%r6,%r7)			# copy to mto
+	la	%r11,0(%r6,%r7)
+	tr	0(1,%r11),0(%r10)		# translate to EBCDIC
+	ahi	%r6,1
+	j	.LloopS4
+.LfinalizemtoS4:
+	sth	%r6,0(%r7)			# update mto length
+	lh	%r9,.LmdbS4-.LwritesccbS4(%r8)	# update mdb length
+	ar	%r9,%r6
+	sth	%r9,.LmdbS4-.LwritesccbS4(%r8)
+	lh	%r9,.LevbufS4-.LwritesccbS4(%r8)# update evbuf length
+	ar	%r9,%r6
+	sth	%r9,.LevbufS4-.LwritesccbS4(%r8)
+	lh	%r9,0(%r8)			# update sccb length
+	ar	%r9,%r6
+	sth	%r9,0(%r8)
+	ar	%r7,%r6				# update current mto adress
+	ltr	%r0,%r0				# more characters?
+	jnz	.LinitmtoS4
+	l	%r2,.LwritedataS4-.LbaseS4(%r13)# write data
+	lr	%r3,%r8
+	bras	%r14,_sclp_servc
+	ltr	%r2,%r2				# servc successful?
+	jnz	.LendS4
+	chi	%r3,0x20			# write data successful?
+	je	.LendS4
+	lhi	%r2,1				# error return code
+.LendS4:
+	lm	%r6,%r15,120(%r15)		# restore registers
+	br	%r14
+
+#
+# Function which prints a given text to the SCLP console.
+#
+# Parameters:
+#   R2	= address of nil-terminated ASCII text
+#
+# Returns:
+#   R2	= 0 on success, 1 on failure
+#
+
+	.globl _sclp_print_early
+_sclp_print_early:
+	stm	%r6,%r15,24(%r15)		# save registers
+	ahi	%r15,-96			# create stack frame
+	lr	%r10,%r2			# save string pointer
+	lhi	%r2,0
+	bras	%r14,_sclp_setup		# enable console
+	ltr	%r2,%r2
+	jnz	.LendS5
+	lr	%r2,%r10
+	bras	%r14,_sclp_print		# print string
+	ltr	%r2,%r2
+	jnz	.LendS5
+	lhi	%r2,1
+	bras	%r14,_sclp_setup		# disable console
+.LendS5:
+	lm	%r6,%r15,120(%r15)		# restore registers
+	br	%r14
+
+.LwritedataS4:
+	.long	0x00760005			# SCLP command for write data
+.LwritesccbS4:
+	# sccb
+	.word	.LmtoS4-.LwritesccbS4
+	.byte	0
+	.byte	0,0,0
+	.word	0
+
+	# evbuf
+.LevbufS4:
+	.word	.LmtoS4-.LevbufS4
+	.byte	0x02
+	.byte	0
+	.word	0
+
+.LmdbS4:
+	# mdb
+	.word	.LmtoS4-.LmdbS4
+	.word	1
+	.long	0xd4c4c240
+	.long	1
+
+	# go
+.LgoS4:
+	.word	.LmtoS4-.LgoS4
+	.word	1
+	.long	0
+	.byte	0,0,0,0,0,0,0,0
+	.byte	0,0,0
+	.byte	0
+	.byte	0,0,0,0,0,0,0
+	.byte	0
+	.word	0
+	.byte	0,0,0,0,0,0,0,0,0,0
+	.byte	0,0,0,0,0,0,0,0
+	.byte	0,0,0,0,0,0,0,0
+
+.LmtoS4:
+	.word	.LmtoendS4-.LmtoS4
+	.word	4
+	.word	0x1000
+	.byte	0
+	.byte	0,0,0
+.LmtoendS4:
+
+	# Global constants
+.LsccbS0:
+	.long	_sclp_work_area
+.Lascebc:
+	.long	_ascebc
+.previous
+
+.section ".init.data","a"
+	.balign 4096
+_sclp_work_area:
+	.fill	4096
+.previous
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/setup.c linux-libre-2.6.31-gnu/arch/s390/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,6 +42,7 @@
 #include <linux/ctype.h>
 #include <linux/reboot.h>
 #include <linux/topology.h>
+#include <linux/ftrace.h>
 
 #include <asm/ipl.h>
 #include <asm/uaccess.h>
@@ -153,6 +154,20 @@
 
 __setup("condev=", condev_setup);
 
+static void __init set_preferred_console(void)
+{
+	if (MACHINE_IS_KVM) {
+		add_preferred_console("hvc", 0, NULL);
+		s390_virtio_console_init();
+		return;
+	}
+
+	if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP)
+		add_preferred_console("ttyS", 0, NULL);
+	if (CONSOLE_IS_3270)
+		add_preferred_console("tty3270", 0, NULL);
+}
+
 static int __init conmode_setup(char *str)
 {
 #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
@@ -167,6 +182,7 @@
 	if (strncmp(str, "3270", 5) == 0)
 		SET_CONSOLE_3270;
 #endif
+	set_preferred_console();
         return 1;
 }
 
@@ -442,6 +458,7 @@
 	lc->steal_timer = S390_lowcore.steal_timer;
 	lc->last_update_timer = S390_lowcore.last_update_timer;
 	lc->last_update_clock = S390_lowcore.last_update_clock;
+	lc->ftrace_func = S390_lowcore.ftrace_func;
 	set_prefix((u32)(unsigned long) lc);
 	lowcore_ptr[0] = lc;
 }
@@ -778,9 +795,6 @@
 void __init
 setup_arch(char **cmdline_p)
 {
-	/* set up preferred console */
-	add_preferred_console("ttyS", 0, NULL);
-
         /*
          * print what head.S has found out about the machine
          */
@@ -800,11 +814,9 @@
 	if (MACHINE_IS_VM)
 		pr_info("Linux is running as a z/VM "
 			"guest operating system in 64-bit mode\n");
-	else if (MACHINE_IS_KVM) {
+	else if (MACHINE_IS_KVM)
 		pr_info("Linux is running under KVM in 64-bit mode\n");
-		add_preferred_console("hvc", 0, NULL);
-		s390_virtio_console_init();
-	} else
+	else
 		pr_info("Linux is running natively in 64-bit mode\n");
 #endif /* CONFIG_64BIT */
 
@@ -849,6 +861,7 @@
 
         /* Setup default console */
 	conmode_default();
+	set_preferred_console();
 
 	/* Setup zfcpdump support */
 	setup_zfcpdump(console_devno);
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/signal.c linux-libre-2.6.31-gnu/arch/s390/kernel/signal.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/signal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/signal.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/binfmts.h>
 #include <linux/tracehook.h>
 #include <linux/syscalls.h>
+#include <linux/compat.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
@@ -482,7 +483,7 @@
 		/* Whee!  Actually deliver the signal.  */
 		int ret;
 #ifdef CONFIG_COMPAT
-		if (test_thread_flag(TIF_31BIT)) {
+		if (is_compat_task()) {
 			ret = handle_signal32(signr, &ka, &info, oldset, regs);
 	        }
 		else
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/smp.c linux-libre-2.6.31-gnu/arch/s390/kernel/smp.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  arch/s390/kernel/smp.c
  *
- *    Copyright IBM Corp. 1999,2007
+ *    Copyright IBM Corp. 1999, 2009
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *		 Martin Schwidefsky (schwidefsky@de.ibm.com)
  *		 Heiko Carstens (heiko.carstens@de.ibm.com)
@@ -47,7 +47,7 @@
 #include <asm/timer.h>
 #include <asm/lowcore.h>
 #include <asm/sclp.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
 #include <asm/vdso.h>
 #include "entry.h"
 
@@ -572,6 +572,7 @@
 	cpu_lowcore->cpu_nr = cpu;
 	cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
 	cpu_lowcore->machine_flags = S390_lowcore.machine_flags;
+	cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func;
 	eieio();
 
 	while (signal_processor(cpu, sigp_restart) == sigp_busy)
@@ -686,13 +687,14 @@
 #ifndef CONFIG_64BIT
 	if (MACHINE_HAS_IEEE)
 		lowcore->extended_save_area_addr = (u32) save_area;
-#else
-	if (vdso_alloc_per_cpu(smp_processor_id(), lowcore))
-		BUG();
 #endif
 	set_prefix((u32)(unsigned long) lowcore);
 	local_mcck_enable();
 	local_irq_enable();
+#ifdef CONFIG_64BIT
+	if (vdso_alloc_per_cpu(smp_processor_id(), &S390_lowcore))
+		BUG();
+#endif
 	for_each_possible_cpu(cpu)
 		if (cpu != smp_processor_id())
 			smp_create_idle(cpu);
@@ -855,13 +857,20 @@
 {
 	struct s390_idle_data *idle;
 	unsigned long long idle_count;
+	unsigned int sequence;
 
 	idle = &per_cpu(s390_idle, dev->id);
-	spin_lock(&idle->lock);
+repeat:
+	sequence = idle->sequence;
+	smp_rmb();
+	if (sequence & 1)
+		goto repeat;
 	idle_count = idle->idle_count;
 	if (idle->idle_enter)
 		idle_count++;
-	spin_unlock(&idle->lock);
+	smp_rmb();
+	if (idle->sequence != sequence)
+		goto repeat;
 	return sprintf(buf, "%llu\n", idle_count);
 }
 static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -871,15 +880,22 @@
 {
 	struct s390_idle_data *idle;
 	unsigned long long now, idle_time, idle_enter;
+	unsigned int sequence;
 
 	idle = &per_cpu(s390_idle, dev->id);
-	spin_lock(&idle->lock);
 	now = get_clock();
+repeat:
+	sequence = idle->sequence;
+	smp_rmb();
+	if (sequence & 1)
+		goto repeat;
 	idle_time = idle->idle_time;
 	idle_enter = idle->idle_enter;
 	if (idle_enter != 0ULL && idle_enter < now)
 		idle_time += now - idle_enter;
-	spin_unlock(&idle->lock);
+	smp_rmb();
+	if (idle->sequence != sequence)
+		goto repeat;
 	return sprintf(buf, "%llu\n", idle_time >> 12);
 }
 static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
@@ -907,11 +923,7 @@
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
 		idle = &per_cpu(s390_idle, cpu);
-		spin_lock_irq(&idle->lock);
-		idle->idle_enter = 0;
-		idle->idle_time = 0;
-		idle->idle_count = 0;
-		spin_unlock_irq(&idle->lock);
+		memset(idle, 0, sizeof(struct s390_idle_data));
 		if (sysfs_create_group(&s->kobj, &cpu_online_attr_group))
 			return NOTIFY_BAD;
 		break;
@@ -1030,6 +1042,42 @@
 static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show,
 			 dispatching_store);
 
+/*
+ * If the resume kernel runs on another cpu than the suspended kernel,
+ * we have to switch the cpu IDs in the logical map.
+ */
+void smp_switch_boot_cpu_in_resume(u32 resume_phys_cpu_id,
+				   struct _lowcore *suspend_lowcore)
+{
+	int cpu, suspend_cpu_id, resume_cpu_id;
+	u32 suspend_phys_cpu_id;
+
+	suspend_phys_cpu_id = __cpu_logical_map[suspend_lowcore->cpu_nr];
+	suspend_cpu_id = suspend_lowcore->cpu_nr;
+
+	for_each_present_cpu(cpu) {
+		if (__cpu_logical_map[cpu] == resume_phys_cpu_id) {
+			resume_cpu_id = cpu;
+			goto found;
+		}
+	}
+	panic("Could not find resume cpu in logical map.\n");
+
+found:
+	printk("Resume  cpu ID: %i/%i\n", resume_phys_cpu_id, resume_cpu_id);
+	printk("Suspend cpu ID: %i/%i\n", suspend_phys_cpu_id, suspend_cpu_id);
+
+	__cpu_logical_map[resume_cpu_id] = suspend_phys_cpu_id;
+	__cpu_logical_map[suspend_cpu_id] = resume_phys_cpu_id;
+
+	lowcore_ptr[suspend_cpu_id]->cpu_addr = resume_phys_cpu_id;
+}
+
+u32 smp_get_phys_cpu_id(void)
+{
+	return __cpu_logical_map[smp_processor_id()];
+}
+
 static int __init topology_init(void)
 {
 	int cpu;
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/syscalls.S linux-libre-2.6.31-gnu/arch/s390/kernel/syscalls.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/syscalls.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/syscalls.S	2009-09-09 18:13:59.000000000 -0400
@@ -338,3 +338,5 @@
 SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
 SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
 SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
+SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo_wrapper) /* 330 */
+SYSCALL(sys_perf_counter_open,sys_perf_counter_open,sys_perf_counter_open_wrapper)
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/time.c linux-libre-2.6.31-gnu/arch/s390/kernel/time.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/time.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,6 @@
 #include <linux/notifier.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
-#include <linux/bootmem.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
@@ -62,15 +61,12 @@
 
 u64 sched_clock_base_cc = -1;	/* Force to data section. */
 
-static ext_int_info_t ext_int_info_cc;
-static ext_int_info_t ext_int_etr_cc;
-
 static DEFINE_PER_CPU(struct clock_event_device, comparators);
 
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
 	return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9;
 }
@@ -95,12 +91,6 @@
 	xtime->tv_nsec = ((todval * 1000) >> 12);
 }
 
-#ifdef CONFIG_PROFILING
-#define s390_do_profile()	profile_tick(CPU_PROFILING)
-#else
-#define s390_do_profile()	do { ; } while(0)
-#endif /* CONFIG_PROFILING */
-
 void clock_comparator_work(void)
 {
 	struct clock_event_device *cd;
@@ -109,7 +99,6 @@
 	set_clock_comparator(S390_lowcore.clock_comparator);
 	cd = &__get_cpu_var(comparators);
 	cd->event_handler(cd);
-	s390_do_profile();
 }
 
 /*
@@ -262,15 +251,11 @@
 	stp_reset();
 
 	/* request the clock comparator external interrupt */
-	if (register_early_external_interrupt(0x1004,
-					      clock_comparator_interrupt,
-					      &ext_int_info_cc) != 0)
+	if (register_external_interrupt(0x1004, clock_comparator_interrupt))
                 panic("Couldn't request external interrupt 0x1004");
 
 	/* request the timing alert external interrupt */
-	if (register_early_external_interrupt(0x1406,
-					      timing_alert_interrupt,
-					      &ext_int_etr_cc) != 0)
+	if (register_external_interrupt(0x1406, timing_alert_interrupt))
 		panic("Couldn't request external interrupt 0x1406");
 
 	if (clocksource_register(&clocksource_tod) != 0)
@@ -1452,14 +1437,14 @@
 {
 	int rc;
 
-	stp_page = alloc_bootmem_pages(PAGE_SIZE);
+	stp_page = (void *) get_zeroed_page(GFP_ATOMIC);
 	rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
 	if (rc == 0)
 		set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
 	else if (stp_online) {
 		pr_warning("The real or virtual hardware system does "
 			   "not provide an STP interface\n");
-		free_bootmem((unsigned long) stp_page, PAGE_SIZE);
+		free_page((unsigned long) stp_page);
 		stp_page = NULL;
 		stp_online = 0;
 	}
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/vdso64/clock_gettime.S linux-libre-2.6.31-gnu/arch/s390/kernel/vdso64/clock_gettime.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/vdso64/clock_gettime.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/vdso64/clock_gettime.S	2009-09-09 18:13:59.000000000 -0400
@@ -88,10 +88,17 @@
 	llilh	%r4,0x0100
 	sar	%a4,%r4
 	lghi	%r4,0
+	epsw	%r5,0
 	sacf	512				/* Magic ectg instruction */
 	.insn	ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
-	sacf	0
-	sar	%a4,%r2
+	tml	%r5,0x4000
+	jo	11f
+	tml	%r5,0x8000
+	jno	10f
+	sacf	256
+	j	11f
+10:	sacf	0
+11:	sar	%a4,%r2
 	algr	%r1,%r0				/* r1 = cputime as TOD value */
 	mghi	%r1,1000			/* convert to nanoseconds */
 	srlg	%r1,%r1,12			/* r1 = cputime in nanosec */
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/vdso.c linux-libre-2.6.31-gnu/arch/s390/kernel/vdso.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/vdso.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/vdso.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,7 @@
 #include <linux/elf.h>
 #include <linux/security.h>
 #include <linux/bootmem.h>
-
+#include <linux/compat.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/processor.h>
@@ -53,8 +53,19 @@
 
 static int __init vdso_setup(char *s)
 {
-	vdso_enabled = simple_strtoul(s, NULL, 0);
-	return 1;
+	unsigned long val;
+	int rc;
+
+	rc = 0;
+	if (strncmp(s, "on", 3) == 0)
+		vdso_enabled = 1;
+	else if (strncmp(s, "off", 4) == 0)
+		vdso_enabled = 0;
+	else {
+		rc = strict_strtoul(s, 0, &val);
+		vdso_enabled = rc ? 0 : !!val;
+	}
+	return !rc;
 }
 __setup("vdso=", vdso_setup);
 
@@ -203,7 +214,7 @@
 	vdso_pagelist = vdso64_pagelist;
 	vdso_pages = vdso64_pages;
 #ifdef CONFIG_COMPAT
-	if (test_thread_flag(TIF_31BIT)) {
+	if (is_compat_task()) {
 		vdso_pagelist = vdso32_pagelist;
 		vdso_pages = vdso32_pages;
 	}
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/s390/kernel/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/s390/kernel/vmlinux.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -34,6 +34,7 @@
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		IRQENTRY_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	} :text = 0x0700
diff -druN linux-libre-2.6.30-gnu/arch/s390/kernel/vtime.c linux-libre-2.6.31-gnu/arch/s390/kernel/vtime.c
--- linux-libre-2.6.30-gnu/arch/s390/kernel/vtime.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kernel/vtime.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,15 +23,11 @@
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
 #include <asm/irq_regs.h>
-#include <asm/cpu.h>
-
-static ext_int_info_t ext_int_info_timer;
+#include <asm/cputime.h>
 
 static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
-DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
-	.lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
-};
+DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
 
 static inline __u64 get_vtimer(void)
 {
@@ -153,11 +149,13 @@
 		vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer;
 	}
 
-	spin_lock(&idle->lock);
+	idle->sequence++;
+	smp_wmb();
 	idle->idle_time += idle_time;
 	idle->idle_enter = 0ULL;
 	idle->idle_count++;
-	spin_unlock(&idle->lock);
+	smp_wmb();
+	idle->sequence++;
 }
 
 void vtime_stop_cpu(void)
@@ -244,15 +242,23 @@
 {
 	struct s390_idle_data *idle;
 	unsigned long long now, idle_time, idle_enter;
+	unsigned int sequence;
 
 	idle = &per_cpu(s390_idle, cpu);
-	spin_lock(&idle->lock);
+
 	now = get_clock();
+repeat:
+	sequence = idle->sequence;
+	smp_rmb();
+	if (sequence & 1)
+		goto repeat;
 	idle_time = 0;
 	idle_enter = idle->idle_enter;
 	if (idle_enter != 0ULL && idle_enter < now)
 		idle_time = now - idle_enter;
-	spin_unlock(&idle->lock);
+	smp_rmb();
+	if (idle->sequence != sequence)
+		goto repeat;
 	return idle_time;
 }
 
@@ -557,8 +563,7 @@
 void __init vtime_init(void)
 {
 	/* request the cpu timer external interrupt */
-	if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt,
-					      &ext_int_info_timer) != 0)
+	if (register_external_interrupt(0x1005, do_cpu_timer_interrupt))
 		panic("Couldn't request external interrupt 0x1005");
 
 	/* Enable cpu timer interrupts on the boot cpu. */
diff -druN linux-libre-2.6.30-gnu/arch/s390/kvm/intercept.c linux-libre-2.6.31-gnu/arch/s390/kvm/intercept.c
--- linux-libre-2.6.30-gnu/arch/s390/kvm/intercept.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kvm/intercept.c	2009-09-09 18:13:59.000000000 -0400
@@ -154,17 +154,25 @@
 static int handle_validity(struct kvm_vcpu *vcpu)
 {
 	int viwhy = vcpu->arch.sie_block->ipb >> 16;
+	int rc;
+
 	vcpu->stat.exit_validity++;
-	if (viwhy == 0x37) {
-		fault_in_pages_writeable((char __user *)
-					 vcpu->kvm->arch.guest_origin +
-					 vcpu->arch.sie_block->prefix,
-					 PAGE_SIZE);
-		return 0;
-	}
-	VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
-		   viwhy);
-	return -ENOTSUPP;
+	if ((viwhy == 0x37) && (vcpu->arch.sie_block->prefix
+		<= vcpu->kvm->arch.guest_memsize - 2*PAGE_SIZE)){
+		rc = fault_in_pages_writeable((char __user *)
+			 vcpu->kvm->arch.guest_origin +
+			 vcpu->arch.sie_block->prefix,
+			 2*PAGE_SIZE);
+		if (rc)
+			/* user will receive sigsegv, exit to user */
+			rc = -ENOTSUPP;
+	} else
+		rc = -ENOTSUPP;
+
+	if (rc)
+		VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
+			   viwhy);
+	return rc;
 }
 
 static int handle_instruction(struct kvm_vcpu *vcpu)
diff -druN linux-libre-2.6.30-gnu/arch/s390/kvm/interrupt.c linux-libre-2.6.31-gnu/arch/s390/kvm/interrupt.c
--- linux-libre-2.6.30-gnu/arch/s390/kvm/interrupt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kvm/interrupt.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,8 @@
 
 #include <asm/lowcore.h>
 #include <asm/uaccess.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
 #include <linux/kvm_host.h>
 #include <linux/signal.h>
 #include "kvm-s390.h"
@@ -299,13 +301,13 @@
 	}
 
 	if ((!rc) && atomic_read(&fi->active)) {
-		spin_lock_bh(&fi->lock);
+		spin_lock(&fi->lock);
 		list_for_each_entry(inti, &fi->list, list)
 			if (__interrupt_is_deliverable(vcpu, inti)) {
 				rc = 1;
 				break;
 			}
-		spin_unlock_bh(&fi->lock);
+		spin_unlock(&fi->lock);
 	}
 
 	if ((!rc) && (vcpu->arch.sie_block->ckc <
@@ -318,6 +320,12 @@
 	return rc;
 }
 
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+	/* do real check here */
+	return 1;
+}
+
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 {
 	return 0;
@@ -355,14 +363,12 @@
 		return 0;
 	}
 
-	sltime = (vcpu->arch.sie_block->ckc - now) / (0xf4240000ul / HZ) + 1;
-
-	vcpu->arch.ckc_timer.expires = jiffies + sltime;
+	sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9;
 
-	add_timer(&vcpu->arch.ckc_timer);
-	VCPU_EVENT(vcpu, 5, "enabled wait timer:%llx jiffies", sltime);
+	hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
+	VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
 no_timer:
-	spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
+	spin_lock(&vcpu->arch.local_int.float_int->lock);
 	spin_lock_bh(&vcpu->arch.local_int.lock);
 	add_wait_queue(&vcpu->arch.local_int.wq, &wait);
 	while (list_empty(&vcpu->arch.local_int.list) &&
@@ -371,33 +377,46 @@
 		!signal_pending(current)) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_bh(&vcpu->arch.local_int.lock);
-		spin_unlock_bh(&vcpu->arch.local_int.float_int->lock);
+		spin_unlock(&vcpu->arch.local_int.float_int->lock);
 		vcpu_put(vcpu);
 		schedule();
 		vcpu_load(vcpu);
-		spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
+		spin_lock(&vcpu->arch.local_int.float_int->lock);
 		spin_lock_bh(&vcpu->arch.local_int.lock);
 	}
 	__unset_cpu_idle(vcpu);
 	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&vcpu->wq, &wait);
+	remove_wait_queue(&vcpu->arch.local_int.wq, &wait);
 	spin_unlock_bh(&vcpu->arch.local_int.lock);
-	spin_unlock_bh(&vcpu->arch.local_int.float_int->lock);
-	del_timer(&vcpu->arch.ckc_timer);
+	spin_unlock(&vcpu->arch.local_int.float_int->lock);
+	hrtimer_try_to_cancel(&vcpu->arch.ckc_timer);
 	return 0;
 }
 
-void kvm_s390_idle_wakeup(unsigned long data)
+void kvm_s390_tasklet(unsigned long parm)
 {
-	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+	struct kvm_vcpu *vcpu = (struct kvm_vcpu *) parm;
 
-	spin_lock_bh(&vcpu->arch.local_int.lock);
+	spin_lock(&vcpu->arch.local_int.lock);
 	vcpu->arch.local_int.timer_due = 1;
 	if (waitqueue_active(&vcpu->arch.local_int.wq))
 		wake_up_interruptible(&vcpu->arch.local_int.wq);
-	spin_unlock_bh(&vcpu->arch.local_int.lock);
+	spin_unlock(&vcpu->arch.local_int.lock);
 }
 
+/*
+ * low level hrtimer wake routine. Because this runs in hardirq context
+ * we schedule a tasklet to do the real work.
+ */
+enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
+{
+	struct kvm_vcpu *vcpu;
+
+	vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer);
+	tasklet_schedule(&vcpu->arch.tasklet);
+
+	return HRTIMER_NORESTART;
+}
 
 void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
 {
@@ -436,7 +455,7 @@
 	if (atomic_read(&fi->active)) {
 		do {
 			deliver = 0;
-			spin_lock_bh(&fi->lock);
+			spin_lock(&fi->lock);
 			list_for_each_entry_safe(inti, n, &fi->list, list) {
 				if (__interrupt_is_deliverable(vcpu, inti)) {
 					list_del(&inti->list);
@@ -447,7 +466,7 @@
 			}
 			if (list_empty(&fi->list))
 				atomic_set(&fi->active, 0);
-			spin_unlock_bh(&fi->lock);
+			spin_unlock(&fi->lock);
 			if (deliver) {
 				__do_deliver_interrupt(vcpu, inti);
 				kfree(inti);
@@ -512,7 +531,7 @@
 
 	mutex_lock(&kvm->lock);
 	fi = &kvm->arch.float_int;
-	spin_lock_bh(&fi->lock);
+	spin_lock(&fi->lock);
 	list_add_tail(&inti->list, &fi->list);
 	atomic_set(&fi->active, 1);
 	sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
@@ -529,7 +548,7 @@
 	if (waitqueue_active(&li->wq))
 		wake_up_interruptible(&li->wq);
 	spin_unlock_bh(&li->lock);
-	spin_unlock_bh(&fi->lock);
+	spin_unlock(&fi->lock);
 	mutex_unlock(&kvm->lock);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/s390/kvm/kvm-s390.c linux-libre-2.6.31-gnu/arch/s390/kvm/kvm-s390.c
--- linux-libre-2.6.30-gnu/arch/s390/kvm/kvm-s390.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kvm/kvm-s390.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/err.h>
 #include <linux/fs.h>
+#include <linux/hrtimer.h>
 #include <linux/init.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
@@ -24,6 +25,7 @@
 #include <asm/lowcore.h>
 #include <asm/pgtable.h>
 #include <asm/nmi.h>
+#include <asm/system.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -68,6 +70,7 @@
 	{ NULL }
 };
 
+static unsigned long long *facilities;
 
 /* Section: not file related */
 void kvm_arch_hardware_enable(void *garbage)
@@ -195,6 +198,10 @@
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
 	VCPU_EVENT(vcpu, 3, "%s", "free cpu");
+	if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
+		(__u64) vcpu->arch.sie_block)
+		vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
+	smp_mb();
 	free_page((unsigned long)(vcpu->arch.sie_block));
 	kvm_vcpu_uninit(vcpu);
 	kfree(vcpu);
@@ -283,8 +290,11 @@
 	vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin;
 	vcpu->arch.sie_block->ecb   = 2;
 	vcpu->arch.sie_block->eca   = 0xC1002001U;
-	setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
-		 (unsigned long) vcpu);
+	vcpu->arch.sie_block->fac   = (int) (long) facilities;
+	hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+	tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
+		     (unsigned long) vcpu);
+	vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
 	get_cpu_id(&vcpu->arch.cpu_id);
 	vcpu->arch.cpu_id.version = 0xff;
 	return 0;
@@ -307,19 +317,21 @@
 
 	vcpu->arch.sie_block->icpua = id;
 	BUG_ON(!kvm->arch.sca);
-	BUG_ON(kvm->arch.sca->cpu[id].sda);
-	kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
+	if (!kvm->arch.sca->cpu[id].sda)
+		kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
+	else
+		BUG_ON(!kvm->vcpus[id]); /* vcpu does already exist */
 	vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
 	vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
 
 	spin_lock_init(&vcpu->arch.local_int.lock);
 	INIT_LIST_HEAD(&vcpu->arch.local_int.list);
 	vcpu->arch.local_int.float_int = &kvm->arch.float_int;
-	spin_lock_bh(&kvm->arch.float_int.lock);
+	spin_lock(&kvm->arch.float_int.lock);
 	kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
 	init_waitqueue_head(&vcpu->arch.local_int.wq);
 	vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
-	spin_unlock_bh(&kvm->arch.float_int.lock);
+	spin_unlock(&kvm->arch.float_int.lock);
 
 	rc = kvm_vcpu_init(vcpu, kvm, id);
 	if (rc)
@@ -478,6 +490,12 @@
 
 	vcpu_load(vcpu);
 
+	/* verify, that memory has been registered */
+	if (!vcpu->kvm->arch.guest_memsize) {
+		vcpu_put(vcpu);
+		return -EINVAL;
+	}
+
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
@@ -497,7 +515,7 @@
 		BUG();
 	}
 
-	might_sleep();
+	might_fault();
 
 	do {
 		__vcpu_run(vcpu);
@@ -657,6 +675,8 @@
 				struct kvm_memory_slot old,
 				int user_alloc)
 {
+	int i;
+
 	/* A few sanity checks. We can have exactly one memory slot which has
 	   to start at guest virtual zero and which has to be located at a
 	   page boundary in userland and which has to end at a page boundary.
@@ -664,7 +684,7 @@
 	   vmas. It is okay to mmap() and munmap() stuff in this slot after
 	   doing this call at any time */
 
-	if (mem->slot)
+	if (mem->slot || kvm->arch.guest_memsize)
 		return -EINVAL;
 
 	if (mem->guest_phys_addr)
@@ -676,15 +696,39 @@
 	if (mem->memory_size & (PAGE_SIZE - 1))
 		return -EINVAL;
 
+	if (!user_alloc)
+		return -EINVAL;
+
+	/* lock all vcpus */
+	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+		if (!kvm->vcpus[i])
+			continue;
+		if (!mutex_trylock(&kvm->vcpus[i]->mutex))
+			goto fail_out;
+	}
+
 	kvm->arch.guest_origin = mem->userspace_addr;
 	kvm->arch.guest_memsize = mem->memory_size;
 
-	/* FIXME: we do want to interrupt running CPUs and update their memory
-	   configuration now to avoid race conditions. But hey, changing the
-	   memory layout while virtual CPUs are running is usually bad
-	   programming practice. */
+	/* update sie control blocks, and unlock all vcpus */
+	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+		if (kvm->vcpus[i]) {
+			kvm->vcpus[i]->arch.sie_block->gmsor =
+				kvm->arch.guest_origin;
+			kvm->vcpus[i]->arch.sie_block->gmslm =
+				kvm->arch.guest_memsize +
+				kvm->arch.guest_origin +
+				VIRTIODESCSPACE - 1ul;
+			mutex_unlock(&kvm->vcpus[i]->mutex);
+		}
+	}
 
 	return 0;
+
+fail_out:
+	for (; i >= 0; i--)
+		mutex_unlock(&kvm->vcpus[i]->mutex);
+	return -EINVAL;
 }
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
@@ -698,11 +742,29 @@
 
 static int __init kvm_s390_init(void)
 {
-	return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
+	int ret;
+	ret = kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
+	if (ret)
+		return ret;
+
+	/*
+	 * guests can ask for up to 255+1 double words, we need a full page
+	 * to hold the maximum amount of facilites. On the other hand, we
+	 * only set facilities that are known to work in KVM.
+	 */
+	facilities = (unsigned long long *) get_zeroed_page(GFP_DMA);
+	if (!facilities) {
+		kvm_exit();
+		return -ENOMEM;
+	}
+	stfle(facilities, 1);
+	facilities[0] &= 0xff00fff3f0700000ULL;
+	return 0;
 }
 
 static void __exit kvm_s390_exit(void)
 {
+	free_page((unsigned long) facilities);
 	kvm_exit();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/kvm/kvm-s390.h linux-libre-2.6.31-gnu/arch/s390/kvm/kvm-s390.h
--- linux-libre-2.6.30-gnu/arch/s390/kvm/kvm-s390.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kvm/kvm-s390.h	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #ifndef ARCH_S390_KVM_S390_H
 #define ARCH_S390_KVM_S390_H
 
+#include <linux/hrtimer.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 
@@ -41,7 +42,8 @@
 }
 
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
-void kvm_s390_idle_wakeup(unsigned long data);
+enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
+void kvm_s390_tasklet(unsigned long parm);
 void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
 int kvm_s390_inject_vm(struct kvm *kvm,
 		struct kvm_s390_interrupt *s390int);
diff -druN linux-libre-2.6.30-gnu/arch/s390/kvm/priv.c linux-libre-2.6.31-gnu/arch/s390/kvm/priv.c
--- linux-libre-2.6.30-gnu/arch/s390/kvm/priv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kvm/priv.c	2009-09-09 18:13:59.000000000 -0400
@@ -158,7 +158,7 @@
 
 	vcpu->stat.instruction_stfl++;
 	/* only pass the facility bits, which we can handle */
-	facility_list &= 0xfe00fff3;
+	facility_list &= 0xff00fff3;
 
 	rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
 			   &facility_list, sizeof(facility_list));
@@ -204,11 +204,11 @@
 	int cpus = 0;
 	int n;
 
-	spin_lock_bh(&fi->lock);
+	spin_lock(&fi->lock);
 	for (n = 0; n < KVM_MAX_VCPUS; n++)
 		if (fi->local_int[n])
 			cpus++;
-	spin_unlock_bh(&fi->lock);
+	spin_unlock(&fi->lock);
 
 	/* deal with other level 3 hypervisors */
 	if (stsi(mem, 3, 2, 2) == -ENOSYS)
diff -druN linux-libre-2.6.30-gnu/arch/s390/kvm/sigp.c linux-libre-2.6.31-gnu/arch/s390/kvm/sigp.c
--- linux-libre-2.6.30-gnu/arch/s390/kvm/sigp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/kvm/sigp.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,7 +52,7 @@
 	if (cpu_addr >= KVM_MAX_VCPUS)
 		return 3; /* not operational */
 
-	spin_lock_bh(&fi->lock);
+	spin_lock(&fi->lock);
 	if (fi->local_int[cpu_addr] == NULL)
 		rc = 3; /* not operational */
 	else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
@@ -64,7 +64,7 @@
 		*reg |= SIGP_STAT_STOPPED;
 		rc = 1; /* status stored */
 	}
-	spin_unlock_bh(&fi->lock);
+	spin_unlock(&fi->lock);
 
 	VCPU_EVENT(vcpu, 4, "sensed status of cpu %x rc %x", cpu_addr, rc);
 	return rc;
@@ -86,7 +86,7 @@
 
 	inti->type = KVM_S390_INT_EMERGENCY;
 
-	spin_lock_bh(&fi->lock);
+	spin_lock(&fi->lock);
 	li = fi->local_int[cpu_addr];
 	if (li == NULL) {
 		rc = 3; /* not operational */
@@ -102,7 +102,7 @@
 	spin_unlock_bh(&li->lock);
 	rc = 0; /* order accepted */
 unlock:
-	spin_unlock_bh(&fi->lock);
+	spin_unlock(&fi->lock);
 	VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr);
 	return rc;
 }
@@ -123,7 +123,7 @@
 
 	inti->type = KVM_S390_SIGP_STOP;
 
-	spin_lock_bh(&fi->lock);
+	spin_lock(&fi->lock);
 	li = fi->local_int[cpu_addr];
 	if (li == NULL) {
 		rc = 3; /* not operational */
@@ -142,7 +142,7 @@
 	spin_unlock_bh(&li->lock);
 	rc = 0; /* order accepted */
 unlock:
-	spin_unlock_bh(&fi->lock);
+	spin_unlock(&fi->lock);
 	VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
 	return rc;
 }
@@ -169,7 +169,7 @@
 			     unsigned long *reg)
 {
 	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
-	struct kvm_s390_local_interrupt *li;
+	struct kvm_s390_local_interrupt *li = NULL;
 	struct kvm_s390_interrupt_info *inti;
 	int rc;
 	u8 tmp;
@@ -188,10 +188,11 @@
 	if (!inti)
 		return 2; /* busy */
 
-	spin_lock_bh(&fi->lock);
-	li = fi->local_int[cpu_addr];
+	spin_lock(&fi->lock);
+	if (cpu_addr < KVM_MAX_VCPUS)
+		li = fi->local_int[cpu_addr];
 
-	if ((cpu_addr >= KVM_MAX_VCPUS) || (li == NULL)) {
+	if (li == NULL) {
 		rc = 1; /* incorrect state */
 		*reg &= SIGP_STAT_INCORRECT_STATE;
 		kfree(inti);
@@ -220,7 +221,7 @@
 out_li:
 	spin_unlock_bh(&li->lock);
 out_fi:
-	spin_unlock_bh(&fi->lock);
+	spin_unlock(&fi->lock);
 	return rc;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/s390/lib/delay.c linux-libre-2.6.31-gnu/arch/s390/lib/delay.c
--- linux-libre-2.6.30-gnu/arch/s390/lib/delay.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/lib/delay.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,9 +36,11 @@
 	cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
 	__ctl_load(cr0 , 0, 0);
 	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+	lockdep_off();
 	trace_hardirqs_on();
 	__load_psw_mask(mask);
 	local_irq_disable();
+	lockdep_on();
 	__ctl_load(cr0_saved, 0, 0);
 	local_tick_enable(clock_saved);
 	set_clock_comparator(S390_lowcore.clock_comparator);
diff -druN linux-libre-2.6.30-gnu/arch/s390/lib/Makefile linux-libre-2.6.31-gnu/arch/s390/lib/Makefile
--- linux-libre-2.6.30-gnu/arch/s390/lib/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/lib/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,6 @@
 #
 
 lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
-obj-$(CONFIG_32BIT) += div64.o qrnnd.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff -druN linux-libre-2.6.30-gnu/arch/s390/lib/spinlock.c linux-libre-2.6.31-gnu/arch/s390/lib/spinlock.c
--- linux-libre-2.6.30-gnu/arch/s390/lib/spinlock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/lib/spinlock.c	2009-09-09 18:13:59.000000000 -0400
@@ -124,6 +124,27 @@
 }
 EXPORT_SYMBOL(_raw_read_lock_wait);
 
+void _raw_read_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+	unsigned int old;
+	int count = spin_retry;
+
+	local_irq_restore(flags);
+	while (1) {
+		if (count-- <= 0) {
+			_raw_yield();
+			count = spin_retry;
+		}
+		if (!__raw_read_can_lock(rw))
+			continue;
+		old = rw->lock & 0x7fffffffU;
+		local_irq_disable();
+		if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
+			return;
+	}
+}
+EXPORT_SYMBOL(_raw_read_lock_wait_flags);
+
 int _raw_read_trylock_retry(raw_rwlock_t *rw)
 {
 	unsigned int old;
@@ -157,6 +178,25 @@
 }
 EXPORT_SYMBOL(_raw_write_lock_wait);
 
+void _raw_write_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+	int count = spin_retry;
+
+	local_irq_restore(flags);
+	while (1) {
+		if (count-- <= 0) {
+			_raw_yield();
+			count = spin_retry;
+		}
+		if (!__raw_write_can_lock(rw))
+			continue;
+		local_irq_disable();
+		if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
+			return;
+	}
+}
+EXPORT_SYMBOL(_raw_write_lock_wait_flags);
+
 int _raw_write_trylock_retry(raw_rwlock_t *rw)
 {
 	int count = spin_retry;
diff -druN linux-libre-2.6.30-gnu/arch/s390/lib/uaccess_pt.c linux-libre-2.6.31-gnu/arch/s390/lib/uaccess_pt.c
--- linux-libre-2.6.30-gnu/arch/s390/lib/uaccess_pt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/lib/uaccess_pt.c	2009-09-09 18:13:59.000000000 -0400
@@ -66,7 +66,7 @@
 	}
 
 survive:
-	fault = handle_mm_fault(mm, vma, address, write_access);
+	fault = handle_mm_fault(mm, vma, address, write_access ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/s390/lib/ucmpdi2.c linux-libre-2.6.31-gnu/arch/s390/lib/ucmpdi2.c
--- linux-libre-2.6.30-gnu/arch/s390/lib/ucmpdi2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/lib/ucmpdi2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,26 @@
+#include <linux/module.h>
+
+union ull_union {
+	unsigned long long ull;
+	struct {
+		unsigned int high;
+		unsigned int low;
+	} ui;
+};
+
+int __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+	union ull_union au = {.ull = a};
+	union ull_union bu = {.ull = b};
+
+	if (au.ui.high < bu.ui.high)
+		return 0;
+	else if (au.ui.high > bu.ui.high)
+		return 2;
+	if (au.ui.low < bu.ui.low)
+		return 0;
+	else if (au.ui.low > bu.ui.low)
+		return 2;
+	return 1;
+}
+EXPORT_SYMBOL(__ucmpdi2);
diff -druN linux-libre-2.6.30-gnu/arch/s390/Makefile linux-libre-2.6.31-gnu/arch/s390/Makefile
--- linux-libre-2.6.30-gnu/arch/s390/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -88,7 +88,9 @@
 head-y		:= arch/s390/kernel/head.o arch/s390/kernel/init_task.o
 
 core-y		+= arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
-		   arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
+		   arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/ \
+		   arch/s390/power/
+
 libs-y		+= arch/s390/lib/
 drivers-y	+= drivers/s390/
 drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
diff -druN linux-libre-2.6.30-gnu/arch/s390/mm/fault.c linux-libre-2.6.31-gnu/arch/s390/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/s390/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,9 +19,9 @@
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/compat.h>
 #include <linux/smp.h>
 #include <linux/kdebug.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/module.h>
@@ -239,7 +239,7 @@
 	up_read(&mm->mmap_sem);
 	clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
 #ifdef CONFIG_COMPAT
-	compat = test_tsk_thread_flag(current, TIF_31BIT);
+	compat = is_compat_task();
 	if (compat && instruction == 0x0a77)
 		sys32_sigreturn();
 	else if (compat && instruction == 0x0aad)
@@ -351,7 +351,7 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, address, write);
+	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM) {
 			up_read(&mm->mmap_sem);
diff -druN linux-libre-2.6.30-gnu/arch/s390/mm/maccess.c linux-libre-2.6.31-gnu/arch/s390/mm/maccess.c
--- linux-libre-2.6.30-gnu/arch/s390/mm/maccess.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/mm/maccess.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Access kernel memory without faulting -- s390 specific implementation.
+ *
+ * Copyright IBM Corp. 2009
+ *
+ *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+
+/*
+ * This function writes to kernel memory bypassing DAT and possible
+ * write protection. It copies one to four bytes from src to dst
+ * using the stura instruction.
+ * Returns the number of bytes copied or -EFAULT.
+ */
+static long probe_kernel_write_odd(void *dst, void *src, size_t size)
+{
+	unsigned long count, aligned;
+	int offset, mask;
+	int rc = -EFAULT;
+
+	aligned = (unsigned long) dst & ~3UL;
+	offset = (unsigned long) dst & 3;
+	count = min_t(unsigned long, 4 - offset, size);
+	mask = (0xf << (4 - count)) & 0xf;
+	mask >>= offset;
+	asm volatile(
+		"	bras	1,0f\n"
+		"	icm	0,0,0(%3)\n"
+		"0:	l	0,0(%1)\n"
+		"	lra	%1,0(%1)\n"
+		"1:	ex	%2,0(1)\n"
+		"2:	stura	0,%1\n"
+		"	la	%0,0\n"
+		"3:\n"
+		EX_TABLE(0b,3b) EX_TABLE(1b,3b) EX_TABLE(2b,3b)
+		: "+d" (rc), "+a" (aligned)
+		: "a" (mask), "a" (src) : "cc", "memory", "0", "1");
+	return rc ? rc : count;
+}
+
+long probe_kernel_write(void *dst, void *src, size_t size)
+{
+	long copied = 0;
+
+	while (size) {
+		copied = probe_kernel_write_odd(dst, src, size);
+		if (copied < 0)
+			break;
+		dst += copied;
+		src += copied;
+		size -= copied;
+	}
+	return copied < 0 ? -EFAULT : 0;
+}
diff -druN linux-libre-2.6.30-gnu/arch/s390/mm/Makefile linux-libre-2.6.31-gnu/arch/s390/mm/Makefile
--- linux-libre-2.6.30-gnu/arch/s390/mm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/mm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
+obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_PAGE_STATES) += page-states.o
diff -druN linux-libre-2.6.30-gnu/arch/s390/mm/mmap.c linux-libre-2.6.31-gnu/arch/s390/mm/mmap.c
--- linux-libre-2.6.30-gnu/arch/s390/mm/mmap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/mm/mmap.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <asm/pgalloc.h>
+#include <asm/compat.h>
 
 /*
  * Top of mmap area (just below the process stack).
@@ -55,7 +56,7 @@
 	/*
 	 * Force standard allocation for 64 bit programs.
 	 */
-	if (!test_thread_flag(TIF_31BIT))
+	if (!is_compat_task())
 		return 1;
 #endif
 	return sysctl_legacy_va_layout ||
@@ -91,7 +92,7 @@
 
 int s390_mmap_check(unsigned long addr, unsigned long len)
 {
-	if (!test_thread_flag(TIF_31BIT) &&
+	if (!is_compat_task() &&
 	    len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
 		return crst_table_upgrade(current->mm, 1UL << 53);
 	return 0;
@@ -108,8 +109,7 @@
 	area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
 	if (!(area & ~PAGE_MASK))
 		return area;
-	if (area == -ENOMEM &&
-	    !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+	if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
 		/* Upgrade the page table to 4 levels and retry. */
 		rc = crst_table_upgrade(mm, 1UL << 53);
 		if (rc)
@@ -131,8 +131,7 @@
 	area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
 	if (!(area & ~PAGE_MASK))
 		return area;
-	if (area == -ENOMEM &&
-	    !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+	if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
 		/* Upgrade the page table to 4 levels and retry. */
 		rc = crst_table_upgrade(mm, 1UL << 53);
 		if (rc)
diff -druN linux-libre-2.6.30-gnu/arch/s390/mm/pgtable.c linux-libre-2.6.31-gnu/arch/s390/mm/pgtable.c
--- linux-libre-2.6.30-gnu/arch/s390/mm/pgtable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/s390/mm/pgtable.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,5 @@
 /*
- *  arch/s390/mm/pgtable.c
- *
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007,2009
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
@@ -53,6 +51,18 @@
 
 #endif
 
+unsigned long VMALLOC_START = VMALLOC_END - VMALLOC_SIZE;
+EXPORT_SYMBOL(VMALLOC_START);
+
+static int __init parse_vmalloc(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+	VMALLOC_START = (VMALLOC_END - memparse(arg, &arg)) & PAGE_MASK;
+	return 0;
+}
+early_param("vmalloc", parse_vmalloc);
+
 unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
 {
 	struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
@@ -303,3 +313,22 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(s390_enable_sie);
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+#ifdef CONFIG_HIBERNATION
+bool kernel_page_present(struct page *page)
+{
+	unsigned long addr;
+	int cc;
+
+	addr = page_to_phys(page);
+	asm("lra %1,0(%1)\n"
+	    "ipm %0\n"
+	    "srl %0,28"
+	    :"=d"(cc),"+a"(addr)::"cc");
+	return cc == 0;
+}
+
+#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_DEBUG_PAGEALLOC */
+
diff -druN linux-libre-2.6.30-gnu/arch/s390/power/Makefile linux-libre-2.6.31-gnu/arch/s390/power/Makefile
--- linux-libre-2.6.30-gnu/arch/s390/power/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/power/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,8 @@
+#
+# Makefile for s390 PM support
+#
+
+obj-$(CONFIG_HIBERNATION) += suspend.o
+obj-$(CONFIG_HIBERNATION) += swsusp.o
+obj-$(CONFIG_HIBERNATION) += swsusp_64.o
+obj-$(CONFIG_HIBERNATION) += swsusp_asm64.o
diff -druN linux-libre-2.6.30-gnu/arch/s390/power/suspend.c linux-libre-2.6.31-gnu/arch/s390/power/suspend.c
--- linux-libre-2.6.30-gnu/arch/s390/power/suspend.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/power/suspend.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * Suspend support specific for s390.
+ *
+ * Copyright IBM Corp. 2009
+ *
+ * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/suspend.h>
+#include <linux/reboot.h>
+#include <linux/pfn.h>
+#include <asm/sections.h>
+#include <asm/ipl.h>
+
+/*
+ * References to section boundaries
+ */
+extern const void __nosave_begin, __nosave_end;
+
+/*
+ *  check if given pfn is in the 'nosave' or in the read only NSS section
+ */
+int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
+	unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end))
+					>> PAGE_SHIFT;
+	unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
+	unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));
+
+	if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
+		return 1;
+	if (pfn >= stext_pfn && pfn <= eshared_pfn) {
+		if (ipl_info.type == IPL_TYPE_NSS)
+			return 1;
+	} else if ((tprot(pfn * PAGE_SIZE) && pfn > 0))
+		return 1;
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/arch/s390/power/swsusp_64.c linux-libre-2.6.31-gnu/arch/s390/power/swsusp_64.c
--- linux-libre-2.6.30-gnu/arch/s390/power/swsusp_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/power/swsusp_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,17 @@
+/*
+ * Support for suspend and resume on s390
+ *
+ * Copyright IBM Corp. 2009
+ *
+ * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
+ *
+ */
+
+#include <asm/system.h>
+#include <linux/interrupt.h>
+
+void do_after_copyback(void)
+{
+	mb();
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/s390/power/swsusp_asm64.S linux-libre-2.6.31-gnu/arch/s390/power/swsusp_asm64.S
--- linux-libre-2.6.30-gnu/arch/s390/power/swsusp_asm64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/power/swsusp_asm64.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,184 @@
+/*
+ * S390 64-bit swsusp implementation
+ *
+ * Copyright IBM Corp. 2009
+ *
+ * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
+ *	      Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * Save register context in absolute 0 lowcore and call swsusp_save() to
+ * create in-memory kernel image. The context is saved in the designated
+ * "store status" memory locations (see POP).
+ * We return from this function twice. The first time during the suspend to
+ * disk process. The second time via the swsusp_arch_resume() function
+ * (see below) in the resume process.
+ * This function runs with disabled interrupts.
+ */
+	.section .text
+	.align	2
+	.globl swsusp_arch_suspend
+swsusp_arch_suspend:
+	stmg	%r6,%r15,__SF_GPRS(%r15)
+	lgr	%r1,%r15
+	aghi	%r15,-STACK_FRAME_OVERHEAD
+	stg	%r1,__SF_BACKCHAIN(%r15)
+
+	/* Deactivate DAT */
+	stnsm	__SF_EMPTY(%r15),0xfb
+
+	/* Store prefix register on stack */
+	stpx	__SF_EMPTY(%r15)
+
+	/* Save prefix register contents for lowcore */
+	llgf	%r4,__SF_EMPTY(%r15)
+
+	/* Get pointer to save area */
+	lghi	%r1,0x1000
+
+	/* Store registers */
+	mvc	0x318(4,%r1),__SF_EMPTY(%r15)	/* move prefix to lowcore */
+	stfpc	0x31c(%r1)			/* store fpu control */
+	std	0,0x200(%r1)			/* store f0 */
+	std	1,0x208(%r1)			/* store f1 */
+	std	2,0x210(%r1)			/* store f2 */
+	std	3,0x218(%r1)			/* store f3 */
+	std	4,0x220(%r1)			/* store f4 */
+	std	5,0x228(%r1)			/* store f5 */
+	std	6,0x230(%r1)			/* store f6 */
+	std	7,0x238(%r1)			/* store f7 */
+	std	8,0x240(%r1)			/* store f8 */
+	std	9,0x248(%r1)			/* store f9 */
+	std	10,0x250(%r1)			/* store f10 */
+	std	11,0x258(%r1)			/* store f11 */
+	std	12,0x260(%r1)			/* store f12 */
+	std	13,0x268(%r1)			/* store f13 */
+	std	14,0x270(%r1)			/* store f14 */
+	std	15,0x278(%r1)			/* store f15 */
+	stam	%a0,%a15,0x340(%r1)		/* store access registers */
+	stctg	%c0,%c15,0x380(%r1)		/* store control registers */
+	stmg	%r0,%r15,0x280(%r1)		/* store general registers */
+
+	stpt	0x328(%r1)			/* store timer */
+	stckc	0x330(%r1)			/* store clock comparator */
+
+	/* Activate DAT */
+	stosm	__SF_EMPTY(%r15),0x04
+
+	/* Set prefix page to zero */
+	xc	__SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
+	spx	__SF_EMPTY(%r15)
+
+	lghi	%r2,0
+	lghi	%r3,2*PAGE_SIZE
+	lghi	%r5,2*PAGE_SIZE
+1:	mvcle	%r2,%r4,0
+	jo	1b
+
+	/* Save image */
+	brasl	%r14,swsusp_save
+
+	/* Restore prefix register and return */
+	lghi	%r1,0x1000
+	spx	0x318(%r1)
+	lmg	%r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
+	lghi	%r2,0
+	br	%r14
+
+/*
+ * Restore saved memory image to correct place and restore register context.
+ * Then we return to the function that called swsusp_arch_suspend().
+ * swsusp_arch_resume() runs with disabled interrupts.
+ */
+	.globl swsusp_arch_resume
+swsusp_arch_resume:
+	stmg	%r6,%r15,__SF_GPRS(%r15)
+	lgr	%r1,%r15
+	aghi	%r15,-STACK_FRAME_OVERHEAD
+	stg	%r1,__SF_BACKCHAIN(%r15)
+
+#ifdef CONFIG_SMP
+	/* Save boot cpu number */
+	brasl	%r14,smp_get_phys_cpu_id
+	lgr	%r10,%r2
+#endif
+	/* Deactivate DAT */
+	stnsm	__SF_EMPTY(%r15),0xfb
+
+	/* Set prefix page to zero */
+	xc	__SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
+	spx	__SF_EMPTY(%r15)
+
+	/* Restore saved image */
+	larl	%r1,restore_pblist
+	lg	%r1,0(%r1)
+	ltgr	%r1,%r1
+	jz	2f
+0:
+	lg	%r2,8(%r1)
+	lg	%r4,0(%r1)
+	lghi	%r3,PAGE_SIZE
+	lghi	%r5,PAGE_SIZE
+1:
+	mvcle	%r2,%r4,0
+	jo	1b
+	lg	%r1,16(%r1)
+	ltgr	%r1,%r1
+	jnz	0b
+2:
+	ptlb				/* flush tlb */
+
+	/* Restore registers */
+	lghi	%r13,0x1000		/* %r1 = pointer to save arae */
+
+	spt	0x328(%r13)		/* reprogram timer */
+	//sckc	0x330(%r13)		/* set clock comparator */
+
+	lctlg	%c0,%c15,0x380(%r13)	/* load control registers */
+	lam	%a0,%a15,0x340(%r13)	/* load access registers */
+
+	lfpc	0x31c(%r13)		/* load fpu control */
+	ld	0,0x200(%r13)		/* load f0 */
+	ld	1,0x208(%r13)		/* load f1 */
+	ld	2,0x210(%r13)		/* load f2 */
+	ld	3,0x218(%r13)		/* load f3 */
+	ld	4,0x220(%r13)		/* load f4 */
+	ld	5,0x228(%r13)		/* load f5 */
+	ld	6,0x230(%r13)		/* load f6 */
+	ld	7,0x238(%r13)		/* load f7 */
+	ld	8,0x240(%r13)		/* load f8 */
+	ld	9,0x248(%r13)		/* load f9 */
+	ld	10,0x250(%r13)		/* load f10 */
+	ld	11,0x258(%r13)		/* load f11 */
+	ld	12,0x260(%r13)		/* load f12 */
+	ld	13,0x268(%r13)		/* load f13 */
+	ld	14,0x270(%r13)		/* load f14 */
+	ld	15,0x278(%r13)		/* load f15 */
+
+	/* Load old stack */
+	lg	%r15,0x2f8(%r13)
+
+	/* Pointer to save area */
+	lghi	%r13,0x1000
+
+#ifdef CONFIG_SMP
+	/* Switch CPUs */
+	lgr	%r2,%r10		/* get cpu id */
+	llgf	%r3,0x318(%r13)
+	brasl	%r14,smp_switch_boot_cpu_in_resume
+#endif
+	/* Restore prefix register */
+	spx	0x318(%r13)
+
+	/* Activate DAT */
+	stosm	__SF_EMPTY(%r15),0x04
+
+	/* Return 0 */
+	lmg	%r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
+	lghi	%r2,0
+	br	%r14
diff -druN linux-libre-2.6.30-gnu/arch/s390/power/swsusp.c linux-libre-2.6.31-gnu/arch/s390/power/swsusp.c
--- linux-libre-2.6.30-gnu/arch/s390/power/swsusp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/s390/power/swsusp.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Support for suspend and resume on s390
+ *
+ * Copyright IBM Corp. 2009
+ *
+ * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
+ *
+ */
+
+#include <asm/system.h>
+
+void save_processor_state(void)
+{
+	/* swsusp_arch_suspend() actually saves all cpu register contents.
+	 * Machine checks must be disabled since swsusp_arch_suspend() stores
+	 * register contents to their lowcore save areas. That's the same
+	 * place where register contents on machine checks would be saved.
+	 * To avoid register corruption disable machine checks.
+	 * We must also disable machine checks in the new psw mask for
+	 * program checks, since swsusp_arch_suspend() may generate program
+	 * checks. Disabling machine checks for all other new psw masks is
+	 * just paranoia.
+	 */
+	local_mcck_disable();
+	/* Disable lowcore protection */
+	__ctl_clear_bit(0,28);
+	S390_lowcore.external_new_psw.mask &= ~PSW_MASK_MCHECK;
+	S390_lowcore.svc_new_psw.mask &= ~PSW_MASK_MCHECK;
+	S390_lowcore.io_new_psw.mask &= ~PSW_MASK_MCHECK;
+	S390_lowcore.program_new_psw.mask &= ~PSW_MASK_MCHECK;
+}
+
+void restore_processor_state(void)
+{
+	S390_lowcore.external_new_psw.mask |= PSW_MASK_MCHECK;
+	S390_lowcore.svc_new_psw.mask |= PSW_MASK_MCHECK;
+	S390_lowcore.io_new_psw.mask |= PSW_MASK_MCHECK;
+	S390_lowcore.program_new_psw.mask |= PSW_MASK_MCHECK;
+	/* Enable lowcore protection */
+	__ctl_set_bit(0,28);
+	local_mcck_enable();
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/board-ap325rxa.c linux-libre-2.6.31-gnu/arch/sh/boards/board-ap325rxa.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/board-ap325rxa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/board-ap325rxa.c	2009-09-09 18:13:59.000000000 -0400
@@ -349,15 +349,6 @@
 	return 0;
 }
 
-static struct ov772x_camera_info ov7725_info = {
-	.buswidth  = SOCAM_DATAWIDTH_8,
-	.flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
-	.edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0),
-	.link = {
-		.power  = ov7725_power,
-	},
-};
-
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
 	.flags = SH_CEU_FLAG_USE_8BIT_BUS,
 };
@@ -402,25 +393,48 @@
 	},
 };
 
-static struct platform_device *ap325rxa_devices[] __initdata = {
-	&smsc9118_device,
-	&ap325rxa_nor_flash_device,
-	&lcdc_device,
-	&ceu_device,
-	&nand_flash_device,
-	&sdcard_cn3_device,
-};
-
 static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
 	},
+};
+
+static struct i2c_board_info ap325rxa_i2c_camera[] = {
 	{
 		I2C_BOARD_INFO("ov772x", 0x21),
-		.platform_data = &ov7725_info,
 	},
 };
 
+static struct ov772x_camera_info ov7725_info = {
+	.buswidth	= SOCAM_DATAWIDTH_8,
+	.flags		= OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
+	.edgectrl	= OV772X_AUTO_EDGECTRL(0xf, 0),
+	.link = {
+		.power		= ov7725_power,
+		.board_info	= &ap325rxa_i2c_camera[0],
+		.i2c_adapter_id	= 0,
+		.module_name	= "ov772x",
+	},
+};
+
+static struct platform_device ap325rxa_camera = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &ov7725_info.link,
+	},
+};
+
+static struct platform_device *ap325rxa_devices[] __initdata = {
+	&smsc9118_device,
+	&ap325rxa_nor_flash_device,
+	&lcdc_device,
+	&ceu_device,
+	&nand_flash_device,
+	&sdcard_cn3_device,
+	&ap325rxa_camera,
+};
+
 static struct spi_board_info ap325rxa_spi_devices[] = {
 	{
 		.modalias = "mmc_spi",
@@ -533,8 +547,20 @@
 	return platform_add_devices(ap325rxa_devices,
 				ARRAY_SIZE(ap325rxa_devices));
 }
-device_initcall(ap325rxa_devices_setup);
+arch_initcall(ap325rxa_devices_setup);
+
+/* Return the board specific boot mode pin configuration */
+static int ap325rxa_mode_pins(void)
+{
+	/* MD0=0, MD1=0, MD2=0: Clock Mode 0
+	 * MD3=0: 16-bit Area0 Bus Width
+	 * MD5=1: Little Endian
+	 * TSTMD=1, MD8=1: Test Mode Disabled
+	 */
+	return MODE_PIN5 | MODE_PIN8;
+}
 
 static struct sh_machine_vector mv_ap325rxa __initmv = {
 	.mv_name = "AP-325RXA",
+	.mv_mode_pins = ap325rxa_mode_pins,
 };
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/board-sh7785lcr.c linux-libre-2.6.31-gnu/arch/sh/boards/board-sh7785lcr.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/board-sh7785lcr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/board-sh7785lcr.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,12 +2,12 @@
  * Renesas Technology Corp. R0P7785LC0011RL Support.
  *
  * Copyright (C) 2008  Yoshihiro Shimoda
+ * Copyright (C) 2009  Paul Mundt
  *
  * 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/init.h>
 #include <linux/platform_device.h>
 #include <linux/sm501.h>
@@ -15,12 +15,18 @@
 #include <linux/fb.h>
 #include <linux/mtd/physmap.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/i2c-pca-platform.h>
 #include <linux/i2c-algo-pca.h>
+#include <linux/usb/r8a66597.h>
 #include <linux/irq.h>
-#include <asm/heartbeat.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
 #include <mach/sh7785lcr.h>
+#include <cpu/sh7785.h>
+#include <asm/heartbeat.h>
+#include <asm/clock.h>
 
 /*
  * NOTE: This board has 2 physical memory maps.
@@ -94,18 +100,21 @@
 	.resource	= nor_flash_resources,
 };
 
+static struct r8a66597_platdata r8a66597_data = {
+	.xtal = R8A66597_PLATDATA_XTAL_12MHZ,
+	.vif = 1,
+};
+
 static struct resource r8a66597_usb_host_resources[] = {
 	[0] = {
-		.name	= "r8a66597_hcd",
 		.start	= R8A66597_ADDR,
 		.end	= R8A66597_ADDR + R8A66597_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.name	= "r8a66597_hcd",
 		.start	= 2,
 		.end	= 2,
-		.flags	= IORESOURCE_IRQ,
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
 	},
 };
 
@@ -115,6 +124,7 @@
 	.dev = {
 		.dma_mask		= NULL,
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &r8a66597_data,
 	},
 	.num_resources	= ARRAY_SIZE(r8a66597_usb_host_resources),
 	.resource	= r8a66597_usb_host_resources,
@@ -273,6 +283,20 @@
 	plat_irq_setup_pins(IRQ_MODE_IRQ3210);
 }
 
+static int sh7785lcr_clk_init(void)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = clk_get(NULL, "extal");
+	if (!clk || IS_ERR(clk))
+		return PTR_ERR(clk);
+	ret = clk_set_rate(clk, 33333333);
+	clk_put(clk);
+
+	return ret;
+}
+
 static void sh7785lcr_power_off(void)
 {
 	unsigned char *p;
@@ -303,12 +327,34 @@
 	writel(0x000307c2, sm501_reg);
 }
 
+/* Return the board specific boot mode pin configuration */
+static int sh7785lcr_mode_pins(void)
+{
+	int value = 0;
+
+	/* These are the factory default settings of S1 and S2.
+	 * If you change these dip switches then you will need to
+	 * adjust the values below as well.
+	 */
+	value |= MODE_PIN4; /* Clock Mode 16 */
+	value |= MODE_PIN5; /* 32-bit Area0 bus width */
+	value |= MODE_PIN6; /* 32-bit Area0 bus width */
+	value |= MODE_PIN7; /* Area 0 SRAM interface [fixed] */
+	value |= MODE_PIN8; /* Little Endian */
+	value |= MODE_PIN9; /* Master Mode */
+	value |= MODE_PIN14; /* No PLL step-up */
+
+	return value;
+}
+
 /*
  * The Machine Vector
  */
 static struct sh_machine_vector mv_sh7785lcr __initmv = {
 	.mv_name		= "SH7785LCR",
 	.mv_setup		= sh7785lcr_setup,
+	.mv_clk_init		= sh7785lcr_clk_init,
 	.mv_init_irq		= init_sh7785lcr_IRQ,
+	.mv_mode_pins		= sh7785lcr_mode_pins,
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/board-urquell.c linux-libre-2.6.31-gnu/arch/sh/boards/board-urquell.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/board-urquell.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/board-urquell.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  * Renesas Technology Corp. SH7786 Urquell Support.
  *
  * Copyright (C) 2008  Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Copyright (C) 2009  Paul Mundt
  *
  * Based on board-sh7785lcr.c
  * Copyright (C) 2008  Yoshihiro Shimoda
@@ -178,6 +179,11 @@
 	plat_irq_setup_pins(IRQ_MODE_IRL3210_MASK);
 }
 
+static int urquell_mode_pins(void)
+{
+	return __raw_readw(UBOARDREG(MDSWMR));
+}
+
 /* Initialize the board */
 static void __init urquell_setup(char **cmdline_p)
 {
@@ -193,4 +199,5 @@
 	.mv_name	= "Urquell",
 	.mv_setup	= urquell_setup,
 	.mv_init_irq	= urquell_init_irq,
+	.mv_mode_pins	= urquell_mode_pins,
 };
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/Kconfig linux-libre-2.6.31-gnu/arch/sh/boards/Kconfig
--- linux-libre-2.6.30-gnu/arch/sh/boards/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,15 @@
 	  Select 7722 SolutionEngine if configuring for a Hitachi SH772
 	  evaluation board.
 
+config SH_7724_SOLUTION_ENGINE
+	bool "SolutionEngine7724"
+	select SOLUTION_ENGINE
+	depends on CPU_SUBTYPE_SH7724
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Select 7724 SolutionEngine if configuring for a Hitachi SH7724
+	  evaluation board.
+
 config SH_7751_SOLUTION_ENGINE
 	bool "SolutionEngine7751"
 	select SOLUTION_ENGINE
@@ -121,7 +130,7 @@
 	bool "RTS7751R2D"
 	depends on CPU_SUBTYPE_SH7751R
 	select SYS_SUPPORTS_PCI
-	select IO_TRAPPED
+	select IO_TRAPPED if MMU
 	help
 	  Select RTS7751R2D if configuring for a Renesas Technology
 	  Sales SH-Graphics board.
@@ -145,13 +154,13 @@
 	bool "Highlander"
 	depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
 	select SYS_SUPPORTS_PCI
-	select IO_TRAPPED
+	select IO_TRAPPED if MMU
 
 config SH_SH7785LCR
 	bool "SH7785LCR"
 	depends on CPU_SUBTYPE_SH7785
 	select SYS_SUPPORTS_PCI
-	select IO_TRAPPED
+	select IO_TRAPPED if MMU
 
 config SH_SH7785LCR_29BIT_PHYSMAPS
 	bool "SH7785LCR 29bit physmaps"
@@ -166,6 +175,7 @@
 	bool "Urquell"
 	depends on CPU_SUBTYPE_SH7786
 	select ARCH_REQUIRE_GPIOLIB
+	select SYS_SUPPORTS_PCI
 
 config SH_MIGOR
 	bool "Migo-R"
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/irq.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/irq.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -142,26 +142,11 @@
 	return irq;
 }
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-int cayman_irq_describe(char* p, int irq)
-{
-	if (irq < NR_INTC_IRQS) {
-		return intc_irq_describe(p, irq);
-	} else if (irq < NR_INTC_IRQS + 8) {
-		return sprintf(p, "(SMSC %d)", irq - NR_INTC_IRQS);
-	} else if ((irq >= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32)) {
-		return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24));
-	}
-
-	return 0;
-}
-#endif
-
 void init_cayman_irq(void)
 {
 	int i;
 
-	epld_virt = onchip_remap(EPLD_BASE, 1024, "EPLD");
+	epld_virt = (unsigned long)ioremap_nocache(EPLD_BASE, 1024);
 	if (!epld_virt) {
 		printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n");
 		return;
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/Makefile linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,4 @@
 #
 # Makefile for the Hitachi Cayman specific parts of the kernel
 #
-obj-y := setup.o irq.o
+obj-y := setup.o irq.o panic.o
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/panic.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/panic.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/panic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/panic.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2003  Richard Curnow, SuperH UK Limited
+ *
+ * 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/io.h>
+#include <cpu/registers.h>
+
+/* THIS IS A PHYSICAL ADDRESS */
+#define HDSP2534_ADDR (0x04002100)
+
+static void poor_mans_delay(void)
+{
+	int i;
+
+	for (i = 0; i < 2500000; i++)
+		cpu_relax();
+}
+
+static void show_value(unsigned long x)
+{
+	int i;
+	unsigned nibble;
+	for (i = 0; i < 8; i++) {
+		nibble = ((x >> (i * 4)) & 0xf);
+
+		__raw_writeb(nibble + ((nibble > 9) ? 55 : 48),
+			  HDSP2534_ADDR + 0xe0 + ((7 - i) << 2));
+	}
+}
+
+void
+panic_handler(unsigned long panicPC, unsigned long panicSSR,
+	      unsigned long panicEXPEVT)
+{
+	while (1) {
+		/* This piece of code displays the PC on the LED display */
+		show_value(panicPC);
+		poor_mans_delay();
+		show_value(panicSSR);
+		poor_mans_delay();
+		show_value(panicEXPEVT);
+		poor_mans_delay();
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/setup.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-cayman/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-cayman/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -102,7 +102,7 @@
 {
 	unsigned char devid, devrev;
 
-	smsc_superio_virt = onchip_remap(SMSC_SUPERIO_BASE, 1024, "SMSC SuperIO");
+	smsc_superio_virt = (unsigned long)ioremap_nocache(SMSC_SUPERIO_BASE, 1024);
 	if (!smsc_superio_virt) {
 		panic("Unable to remap SMSC SuperIO\n");
 	}
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-dreamcast/setup.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-dreamcast/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-dreamcast/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-dreamcast/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,6 @@
 
 extern struct irq_chip systemasic_int;
 extern void aica_time_init(void);
-extern int gapspci_init(void);
 extern int systemasic_irq_demux(int);
 
 static void __init dreamcast_setup(char **cmdline_p)
@@ -51,11 +50,6 @@
 					 handle_level_irq);
 
 	board_time_init = aica_time_init;
-
-#ifdef CONFIG_PCI
-	if (gapspci_init() < 0)
-		printk(KERN_WARNING "GAPSPCI was not detected.\n");
-#endif
 }
 
 static struct sh_machine_vector mv_dreamcast __initmv = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-highlander/setup.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-highlander/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-highlander/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-highlander/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,8 +17,11 @@
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
 #include <linux/types.h>
+#include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/r8a66597.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
 #include <mach/highlander.h>
@@ -27,18 +30,21 @@
 #include <asm/io.h>
 #include <asm/io_trapped.h>
 
+static struct r8a66597_platdata r8a66597_data = {
+	.xtal = R8A66597_PLATDATA_XTAL_12MHZ,
+	.vif = 1,
+};
+
 static struct resource r8a66597_usb_host_resources[] = {
 	[0] = {
-		.name	= "r8a66597_hcd",
 		.start	= 0xA4200000,
 		.end	= 0xA42000FF,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.name	= "r8a66597_hcd",
 		.start	= IRQ_EXT1,		/* irq number */
 		.end	= IRQ_EXT1,
-		.flags	= IORESOURCE_IRQ,
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
 	},
 };
 
@@ -48,6 +54,7 @@
 	.dev = {
 		.dma_mask		= NULL,		/* don't use dma */
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &r8a66597_data,
 	},
 	.num_resources	= ARRAY_SIZE(r8a66597_usb_host_resources),
 	.resource	= r8a66597_usb_host_resources,
@@ -178,6 +185,53 @@
 	.resource       = ax88796_resources,
 };
 
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 4 * 1024 * 1024,
+	},
+	{
+		.name		= "data",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data nor_flash_data = {
+	.width		= 4,
+	.parts		= nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
+};
+
+/* This config is flash board for mass production. */
+static struct resource nor_flash_resources[] = {
+	[0]	= {
+		.start	= PA_NORFLASH_ADDR,
+		.end	= PA_NORFLASH_ADDR + PA_NORFLASH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device nor_flash_device = {
+	.name		= "physmap-flash",
+	.dev		= {
+		.platform_data	= &nor_flash_data,
+	},
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+	.resource	= nor_flash_resources,
+};
+
 static struct resource smbus_resources[] = {
 	[0] = {
 		.start	= PA_SMCR,
@@ -209,6 +263,7 @@
 	&m66592_usb_peripheral_device,
 	&heartbeat_device,
 	&smbus_device,
+	&nor_flash_device,
 #ifndef CONFIG_SH_R7780RP
 	&ax88796_device,
 #endif
@@ -247,9 +302,10 @@
 /*
  * Platform specific clocks
  */
-static void ivdr_clk_enable(struct clk *clk)
+static int ivdr_clk_enable(struct clk *clk)
 {
 	ctrl_outw(ctrl_inw(PA_IVDRCTL) | (1 << IVDR_CK_ON), PA_IVDRCTL);
+	return 0;
 }
 
 static void ivdr_clk_disable(struct clk *clk)
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-migor/setup.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-migor/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-migor/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-migor/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -381,21 +381,6 @@
 	},
 };
 
-static struct ov772x_camera_info ov7725_info = {
-	.buswidth  = SOCAM_DATAWIDTH_8,
-	.link = {
-		.power  = ov7725_power,
-	},
-};
-
-static struct tw9910_video_info tw9910_info = {
-	.buswidth = SOCAM_DATAWIDTH_8,
-	.mpout    = TW9910_MPO_FIELD,
-	.link = {
-		.power  = tw9910_power,
-	}
-};
-
 struct spi_gpio_platform_data sdcard_cn9_platform_data = {
 	.sck = GPIO_PTD0,
 	.mosi = GPIO_PTD1,
@@ -410,16 +395,6 @@
 	},
 };
 
-static struct platform_device *migor_devices[] __initdata = {
-	&smc91x_eth_device,
-	&sh_keysc_device,
-	&migor_lcdc_device,
-	&migor_ceu_device,
-	&migor_nor_flash_device,
-	&migor_nand_flash_device,
-	&sdcard_cn9_device,
-};
-
 static struct i2c_board_info migor_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("rs5c372b", 0x32),
@@ -428,16 +403,66 @@
 		I2C_BOARD_INFO("migor_ts", 0x51),
 		.irq = 38, /* IRQ6 */
 	},
+};
+
+static struct i2c_board_info migor_i2c_camera[] = {
 	{
 		I2C_BOARD_INFO("ov772x", 0x21),
-		.platform_data = &ov7725_info,
 	},
 	{
 		I2C_BOARD_INFO("tw9910", 0x45),
-		.platform_data = &tw9910_info,
 	},
 };
 
+static struct ov772x_camera_info ov7725_info = {
+	.buswidth	= SOCAM_DATAWIDTH_8,
+	.link = {
+		.power		= ov7725_power,
+		.board_info	= &migor_i2c_camera[0],
+		.i2c_adapter_id	= 0,
+		.module_name	= "ov772x",
+	},
+};
+
+static struct tw9910_video_info tw9910_info = {
+	.buswidth	= SOCAM_DATAWIDTH_8,
+	.mpout		= TW9910_MPO_FIELD,
+	.link = {
+		.power		= tw9910_power,
+		.board_info	= &migor_i2c_camera[1],
+		.i2c_adapter_id	= 0,
+		.module_name	= "tw9910",
+	}
+};
+
+static struct platform_device migor_camera[] = {
+	{
+		.name	= "soc-camera-pdrv",
+		.id	= 0,
+		.dev	= {
+			.platform_data = &ov7725_info.link,
+		},
+	}, {
+		.name	= "soc-camera-pdrv",
+		.id	= 1,
+		.dev	= {
+			.platform_data = &tw9910_info.link,
+		},
+	},
+};
+
+static struct platform_device *migor_devices[] __initdata = {
+	&smc91x_eth_device,
+	&sh_keysc_device,
+	&migor_lcdc_device,
+	&migor_ceu_device,
+	&migor_nor_flash_device,
+	&migor_nand_flash_device,
+	&sdcard_cn9_device,
+	&migor_camera[0],
+	&migor_camera[1],
+};
+
 static struct spi_board_info migor_spi_devices[] = {
 	{
 		.modalias = "mmc_spi",
@@ -583,4 +608,23 @@
 
 	return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
 }
-__initcall(migor_devices_setup);
+arch_initcall(migor_devices_setup);
+
+/* Return the board specific boot mode pin configuration */
+static int migor_mode_pins(void)
+{
+	/* MD0=1, MD1=1, MD2=0: Clock Mode 3
+	 * MD3=0: 16-bit Area0 Bus Width
+	 * MD5=1: Little Endian
+	 * TSTMD=1, MD8=0: Test Mode Disabled
+	 */
+	return MODE_PIN0 | MODE_PIN1 | MODE_PIN5;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_migor __initmv = {
+	.mv_name		= "Migo-R",
+	.mv_mode_pins		= migor_mode_pins,
+};
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-r2d/setup.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-r2d/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-r2d/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-r2d/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,9 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
 #include <linux/ata_platform.h>
 #include <linux/sm501.h>
 #include <linux/sm501-regs.h>
@@ -181,6 +184,50 @@
 	.resource	= sm501_resources,
 };
 
+static struct mtd_partition r2d_partitions[] = {
+	{
+		.name		= "U-Boot",
+		.offset		= 0x00000000,
+		.size		= 0x00040000,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "Environment",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 0x00040000,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "Kernel",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 0x001c0000,
+	}, {
+		.name		= "Flash_FS",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct physmap_flash_data flash_data = {
+	.width		= 2,
+	.nr_parts	= ARRAY_SIZE(r2d_partitions),
+	.parts		= r2d_partitions,
+};
+
+static struct resource flash_resource = {
+	.start		= 0x00000000,
+	.end		= 0x02000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+	.name		= "physmap-flash",
+	.id		= -1,
+	.resource	= &flash_resource,
+	.num_resources	= 1,
+	.dev		= {
+		.platform_data = &flash_data,
+	},
+};
+
 static struct platform_device *rts7751r2d_devices[] __initdata = {
 	&sm501_device,
 	&heartbeat_device,
@@ -203,6 +250,9 @@
 	if (register_trapped_io(&cf_trapped_io) == 0)
 		platform_device_register(&cf_ide_device);
 
+	if (mach_is_r2d_plus())
+		platform_device_register(&flash_device);
+
 	spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
 
 	return platform_add_devices(rts7751r2d_devices,
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-rsk/devices-rsk7203.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-rsk/devices-rsk7203.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-rsk/devices-rsk7203.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-rsk/devices-rsk7203.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,13 +26,13 @@
 	.phy_interface	= PHY_INTERFACE_MODE_MII,
 	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
 	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
-	.flags		= SMSC911X_USE_16BIT,
+	.flags		= SMSC911X_USE_32BIT | SMSC911X_SWAP_FIFO,
 };
 
 static struct resource smsc911x_resources[] = {
 	[0] = {
 		.start		= 0x24000000,
-		.end		= 0x24000000 + 0x100,
+		.end		= 0x240000ff,
 		.flags		= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -99,6 +99,10 @@
 	gpio_request(GPIO_FN_TXD0, NULL);
 	gpio_request(GPIO_FN_RXD0, NULL);
 
+	/* Setup LAN9118: CS1 in 16-bit Big Endian Mode, IRQ0 at Port B */
+	ctrl_outl(0x36db0400, 0xfffc0008); /* CS1BCR */
+	gpio_request(GPIO_FN_IRQ0_PB, NULL);
+
 	return platform_add_devices(rsk7203_devices,
 				    ARRAY_SIZE(rsk7203_devices));
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7206/io.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7206/io.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7206/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7206/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,7 @@
 
 unsigned short se7206_inw(unsigned long port)
 {
-	return *port2adr(port);;
+	return *port2adr(port);
 }
 
 void se7206_outb(unsigned char value, unsigned long port)
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7724/irq.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7724/irq.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7724/irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7724/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,139 @@
+/*
+ * linux/arch/sh/boards/se/7724/irq.c
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on  linux/arch/sh/boards/se/7722/irq.c
+ * Copyright (C) 2007  Nobuhiro Iwamatsu
+ *
+ * Hitachi UL SolutionEngine 7724 Support.
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <mach-se/mach/se7724.h>
+
+struct fpga_irq {
+	unsigned long  sraddr;
+	unsigned long  mraddr;
+	unsigned short mask;
+	unsigned int   base;
+};
+
+static unsigned int fpga2irq(unsigned int irq)
+{
+	if (irq >= IRQ0_BASE &&
+	    irq <= IRQ0_END)
+		return IRQ0_IRQ;
+	else if (irq >= IRQ1_BASE &&
+		 irq <= IRQ1_END)
+		return IRQ1_IRQ;
+	else
+		return IRQ2_IRQ;
+}
+
+static struct fpga_irq get_fpga_irq(unsigned int irq)
+{
+	struct fpga_irq set;
+
+	switch (irq) {
+	case IRQ0_IRQ:
+		set.sraddr = IRQ0_SR;
+		set.mraddr = IRQ0_MR;
+		set.mask   = IRQ0_MASK;
+		set.base   = IRQ0_BASE;
+		break;
+	case IRQ1_IRQ:
+		set.sraddr = IRQ1_SR;
+		set.mraddr = IRQ1_MR;
+		set.mask   = IRQ1_MASK;
+		set.base   = IRQ1_BASE;
+		break;
+	default:
+		set.sraddr = IRQ2_SR;
+		set.mraddr = IRQ2_MR;
+		set.mask   = IRQ2_MASK;
+		set.base   = IRQ2_BASE;
+		break;
+	}
+
+	return set;
+}
+
+static void disable_se7724_irq(unsigned int irq)
+{
+	struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
+	unsigned int bit = irq - set.base;
+	ctrl_outw(ctrl_inw(set.mraddr) | 0x0001 << bit, set.mraddr);
+}
+
+static void enable_se7724_irq(unsigned int irq)
+{
+	struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
+	unsigned int bit = irq - set.base;
+	ctrl_outw(ctrl_inw(set.mraddr) & ~(0x0001 << bit), set.mraddr);
+}
+
+static struct irq_chip se7724_irq_chip __read_mostly = {
+	.name           = "SE7724-FPGA",
+	.mask           = disable_se7724_irq,
+	.unmask         = enable_se7724_irq,
+	.mask_ack       = disable_se7724_irq,
+};
+
+static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+	struct fpga_irq set = get_fpga_irq(irq);
+	unsigned short intv = ctrl_inw(set.sraddr);
+	struct irq_desc *ext_desc;
+	unsigned int ext_irq = set.base;
+
+	intv &= set.mask;
+
+	while (intv) {
+		if (intv & 0x0001) {
+			ext_desc = irq_desc + ext_irq;
+			handle_level_irq(ext_irq, ext_desc);
+		}
+		intv >>= 1;
+		ext_irq++;
+	}
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_se7724_IRQ(void)
+{
+	int i;
+
+	ctrl_outw(0xffff, IRQ0_MR);  /* mask all */
+	ctrl_outw(0xffff, IRQ1_MR);  /* mask all */
+	ctrl_outw(0xffff, IRQ2_MR);  /* mask all */
+	ctrl_outw(0x0000, IRQ0_SR);  /* clear irq */
+	ctrl_outw(0x0000, IRQ1_SR);  /* clear irq */
+	ctrl_outw(0x0000, IRQ2_SR);  /* clear irq */
+	ctrl_outw(0x002a, IRQ_MODE); /* set irq type */
+
+	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++)
+		set_irq_chip_and_handler_name(SE7724_FPGA_IRQ_BASE + i,
+					      &se7724_irq_chip,
+					      handle_level_irq, "level");
+
+	set_irq_chained_handler(IRQ0_IRQ, se7724_irq_demux);
+	set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+
+	set_irq_chained_handler(IRQ1_IRQ, se7724_irq_demux);
+	set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+
+	set_irq_chained_handler(IRQ2_IRQ, se7724_irq_demux);
+	set_irq_type(IRQ2_IRQ, IRQ_TYPE_LEVEL_LOW);
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7724/Makefile linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7724/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7724/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7724/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,10 @@
+#
+# Makefile for the HITACHI UL SolutionEngine 7724 specific parts of the kernel
+#
+# 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.
+#
+#
+
+obj-y	 := setup.o irq.o
\ No newline at end of file
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7724/setup.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7724/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7724/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7724/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,589 @@
+/*
+ * linux/arch/sh/boards/se/7724/setup.c
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.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.
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/delay.h>
+#include <linux/smc91x.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/usb/r8a66597.h>
+#include <video/sh_mobile_lcdc.h>
+#include <media/sh_mobile_ceu.h>
+#include <asm/io.h>
+#include <asm/heartbeat.h>
+#include <asm/sh_eth.h>
+#include <asm/clock.h>
+#include <asm/sh_keysc.h>
+#include <cpu/sh7724.h>
+#include <mach-se/mach/se7724.h>
+
+/*
+ * SWx    1234 5678
+ * ------------------------------------
+ * SW31 : 1001 1100    : default
+ * SW32 : 0111 1111    : use on board flash
+ *
+ * SW41 : abxx xxxx  -> a = 0 : Analog  monitor
+ *                          1 : Digital monitor
+ *                      b = 0 : VGA
+ *                          1 : SVGA
+ */
+
+/* Heartbeat */
+static struct heartbeat_data heartbeat_data = {
+	.regsize = 16,
+};
+
+static struct resource heartbeat_resources[] = {
+	[0] = {
+		.start  = PA_LED,
+		.end    = PA_LED,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device heartbeat_device = {
+	.name           = "heartbeat",
+	.id             = -1,
+	.dev = {
+		.platform_data = &heartbeat_data,
+	},
+	.num_resources  = ARRAY_SIZE(heartbeat_resources),
+	.resource       = heartbeat_resources,
+};
+
+/* LAN91C111 */
+static struct smc91x_platdata smc91x_info = {
+	.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+};
+
+static struct resource smc91x_eth_resources[] = {
+	[0] = {
+		.name   = "SMC91C111" ,
+		.start  = 0x1a300300,
+		.end    = 0x1a30030f,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ0_SMC,
+		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+};
+
+static struct platform_device smc91x_eth_device = {
+	.name	= "smc91x",
+	.num_resources  = ARRAY_SIZE(smc91x_eth_resources),
+	.resource       = smc91x_eth_resources,
+	.dev	= {
+		.platform_data	= &smc91x_info,
+	},
+};
+
+/* MTD */
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name = "uboot",
+		.offset = 0,
+		.size = (1 * 1024 * 1024),
+		.mask_flags = MTD_WRITEABLE,	/* Read-only */
+	}, {
+		.name = "kernel",
+		.offset = MTDPART_OFS_APPEND,
+		.size = (2 * 1024 * 1024),
+	}, {
+		.name = "free-area",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+	},
+};
+
+static struct physmap_flash_data nor_flash_data = {
+	.width		= 2,
+	.parts		= nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_flash_partitions),
+};
+
+static struct resource nor_flash_resources[] = {
+	[0] = {
+		.name	= "NOR Flash",
+		.start	= 0x00000000,
+		.end	= 0x01ffffff,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device nor_flash_device = {
+	.name		= "physmap-flash",
+	.resource	= nor_flash_resources,
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+	.dev		= {
+		.platform_data = &nor_flash_data,
+	},
+};
+
+/* LCDC */
+static struct sh_mobile_lcdc_info lcdc_info = {
+	.clock_source = LCDC_CLK_EXTERNAL,
+	.ch[0] = {
+		.chan = LCDC_CHAN_MAINLCD,
+		.bpp = 16,
+		.clock_divider = 1,
+		.lcd_cfg = {
+			.name = "LB070WV1",
+			.sync = 0, /* hsync and vsync are active low */
+		},
+		.lcd_size_cfg = { /* 7.0 inch */
+			.width = 152,
+			.height = 91,
+		},
+		.board_cfg = {
+		},
+	}
+};
+
+static struct resource lcdc_resources[] = {
+	[0] = {
+		.name	= "LCDC",
+		.start	= 0xfe940000,
+		.end	= 0xfe941fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 106,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device lcdc_device = {
+	.name		= "sh_mobile_lcdc_fb",
+	.num_resources	= ARRAY_SIZE(lcdc_resources),
+	.resource	= lcdc_resources,
+	.dev		= {
+		.platform_data	= &lcdc_info,
+	},
+};
+
+/* CEU0 */
+static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
+	.flags = SH_CEU_FLAG_USE_8BIT_BUS,
+};
+
+static struct resource ceu0_resources[] = {
+	[0] = {
+		.name	= "CEU0",
+		.start	= 0xfe910000,
+		.end	= 0xfe91009f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 52,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* place holder for contiguous memory */
+	},
+};
+
+static struct platform_device ceu0_device = {
+	.name		= "sh_mobile_ceu",
+	.id             = 0, /* "ceu0" clock */
+	.num_resources	= ARRAY_SIZE(ceu0_resources),
+	.resource	= ceu0_resources,
+	.dev	= {
+		.platform_data	= &sh_mobile_ceu0_info,
+	},
+};
+
+/* CEU1 */
+static struct sh_mobile_ceu_info sh_mobile_ceu1_info = {
+	.flags = SH_CEU_FLAG_USE_8BIT_BUS,
+};
+
+static struct resource ceu1_resources[] = {
+	[0] = {
+		.name	= "CEU1",
+		.start	= 0xfe914000,
+		.end	= 0xfe91409f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 63,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* place holder for contiguous memory */
+	},
+};
+
+static struct platform_device ceu1_device = {
+	.name		= "sh_mobile_ceu",
+	.id             = 1, /* "ceu1" clock */
+	.num_resources	= ARRAY_SIZE(ceu1_resources),
+	.resource	= ceu1_resources,
+	.dev	= {
+		.platform_data	= &sh_mobile_ceu1_info,
+	},
+};
+
+/* KEYSC in SoC (Needs SW33-2 set to ON) */
+static struct sh_keysc_info keysc_info = {
+	.mode = SH_KEYSC_MODE_1,
+	.scan_timing = 10,
+	.delay = 50,
+	.keycodes = {
+		KEY_1, KEY_2, KEY_3, KEY_4, KEY_5,
+		KEY_6, KEY_7, KEY_8, KEY_9, KEY_A,
+		KEY_B, KEY_C, KEY_D, KEY_E, KEY_F,
+		KEY_G, KEY_H, KEY_I, KEY_K, KEY_L,
+		KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q,
+		KEY_R, KEY_S, KEY_T, KEY_U, KEY_V,
+	},
+};
+
+static struct resource keysc_resources[] = {
+	[0] = {
+		.name	= "KEYSC",
+		.start  = 0x044b0000,
+		.end    = 0x044b000f,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 79,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device keysc_device = {
+	.name           = "sh_keysc",
+	.id             = 0, /* "keysc0" clock */
+	.num_resources  = ARRAY_SIZE(keysc_resources),
+	.resource       = keysc_resources,
+	.dev	= {
+		.platform_data	= &keysc_info,
+	},
+};
+
+/* SH Eth */
+static struct resource sh_eth_resources[] = {
+	[0] = {
+		.start = SH_ETH_ADDR,
+		.end   = SH_ETH_ADDR + 0x1FC,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = 91,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+	},
+};
+
+struct sh_eth_plat_data sh_eth_plat = {
+	.phy = 0x1f, /* SMSC LAN8187 */
+	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device sh_eth_device = {
+	.name = "sh-eth",
+	.id	= 0,
+	.dev = {
+		.platform_data = &sh_eth_plat,
+	},
+	.num_resources = ARRAY_SIZE(sh_eth_resources),
+	.resource = sh_eth_resources,
+};
+
+static struct r8a66597_platdata sh7724_usb0_host_data = {
+};
+
+static struct resource sh7724_usb0_host_resources[] = {
+	[0] = {
+		.start	= 0xa4d80000,
+		.end	= 0xa4d800ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 65,
+		.end	= 65,
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+	},
+};
+
+static struct platform_device sh7724_usb0_host_device = {
+	.name		= "r8a66597_hcd",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= NULL,         /*  not use dma */
+		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &sh7724_usb0_host_data,
+	},
+	.num_resources	= ARRAY_SIZE(sh7724_usb0_host_resources),
+	.resource	= sh7724_usb0_host_resources,
+};
+
+static struct platform_device *ms7724se_devices[] __initdata = {
+	&heartbeat_device,
+	&smc91x_eth_device,
+	&lcdc_device,
+	&nor_flash_device,
+	&ceu0_device,
+	&ceu1_device,
+	&keysc_device,
+	&sh_eth_device,
+	&sh7724_usb0_host_device,
+};
+
+#define EEPROM_OP   0xBA206000
+#define EEPROM_ADR  0xBA206004
+#define EEPROM_DATA 0xBA20600C
+#define EEPROM_STAT 0xBA206010
+#define EEPROM_STRT 0xBA206014
+static int __init sh_eth_is_eeprom_ready(void)
+{
+	int t = 10000;
+
+	while (t--) {
+		if (!ctrl_inw(EEPROM_STAT))
+			return 1;
+		cpu_relax();
+	}
+
+	printk(KERN_ERR "ms7724se can not access to eeprom\n");
+	return 0;
+}
+
+static void __init sh_eth_init(void)
+{
+	int i;
+	u16 mac[3];
+
+	/* check EEPROM status */
+	if (!sh_eth_is_eeprom_ready())
+		return;
+
+	/* read MAC addr from EEPROM */
+	for (i = 0 ; i < 3 ; i++) {
+		ctrl_outw(0x0, EEPROM_OP); /* read */
+		ctrl_outw(i*2, EEPROM_ADR);
+		ctrl_outw(0x1, EEPROM_STRT);
+		if (!sh_eth_is_eeprom_ready())
+			return;
+
+		mac[i] = ctrl_inw(EEPROM_DATA);
+		mac[i] = ((mac[i] & 0xFF) << 8) | (mac[i] >> 8); /* swap */
+	}
+
+	/* reset sh-eth */
+	ctrl_outl(0x1, SH_ETH_ADDR + 0x0);
+
+	/* set MAC addr */
+	ctrl_outl(((mac[0] << 16) | (mac[1])), SH_ETH_MAHR);
+	ctrl_outl((mac[2]), SH_ETH_MALR);
+}
+
+#define SW4140    0xBA201000
+#define FPGA_OUT  0xBA200400
+#define PORT_HIZA 0xA4050158
+#define PORT_MSELCRB 0xA4050182
+
+#define SW41_A    0x0100
+#define SW41_B    0x0200
+#define SW41_C    0x0400
+#define SW41_D    0x0800
+#define SW41_E    0x1000
+#define SW41_F    0x2000
+#define SW41_G    0x4000
+#define SW41_H    0x8000
+
+static int __init devices_setup(void)
+{
+	u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
+
+	/* Reset Release */
+	ctrl_outw(ctrl_inw(FPGA_OUT) &
+		  ~((1 << 1)  | /* LAN */
+		    (1 << 6)  | /* VIDEO DAC */
+		    (1 << 12) | /* USB0 */
+		    (1 << 14)), /* RMII */
+		  FPGA_OUT);
+
+	/* turn on USB clocks, use external clock */
+	ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
+
+	/* enable USB0 port */
+	ctrl_outw(0x0600, 0xa40501d4);
+
+	/* enable IRQ 0,1,2 */
+	gpio_request(GPIO_FN_INTC_IRQ0, NULL);
+	gpio_request(GPIO_FN_INTC_IRQ1, NULL);
+	gpio_request(GPIO_FN_INTC_IRQ2, NULL);
+
+	/* enable SCIFA3 */
+	gpio_request(GPIO_FN_SCIF3_I_SCK, NULL);
+	gpio_request(GPIO_FN_SCIF3_I_RXD, NULL);
+	gpio_request(GPIO_FN_SCIF3_I_TXD, NULL);
+	gpio_request(GPIO_FN_SCIF3_I_CTS, NULL);
+	gpio_request(GPIO_FN_SCIF3_I_RTS, NULL);
+
+	/* enable LCDC */
+	gpio_request(GPIO_FN_LCDD23,   NULL);
+	gpio_request(GPIO_FN_LCDD22,   NULL);
+	gpio_request(GPIO_FN_LCDD21,   NULL);
+	gpio_request(GPIO_FN_LCDD20,   NULL);
+	gpio_request(GPIO_FN_LCDD19,   NULL);
+	gpio_request(GPIO_FN_LCDD18,   NULL);
+	gpio_request(GPIO_FN_LCDD17,   NULL);
+	gpio_request(GPIO_FN_LCDD16,   NULL);
+	gpio_request(GPIO_FN_LCDD15,   NULL);
+	gpio_request(GPIO_FN_LCDD14,   NULL);
+	gpio_request(GPIO_FN_LCDD13,   NULL);
+	gpio_request(GPIO_FN_LCDD12,   NULL);
+	gpio_request(GPIO_FN_LCDD11,   NULL);
+	gpio_request(GPIO_FN_LCDD10,   NULL);
+	gpio_request(GPIO_FN_LCDD9,    NULL);
+	gpio_request(GPIO_FN_LCDD8,    NULL);
+	gpio_request(GPIO_FN_LCDD7,    NULL);
+	gpio_request(GPIO_FN_LCDD6,    NULL);
+	gpio_request(GPIO_FN_LCDD5,    NULL);
+	gpio_request(GPIO_FN_LCDD4,    NULL);
+	gpio_request(GPIO_FN_LCDD3,    NULL);
+	gpio_request(GPIO_FN_LCDD2,    NULL);
+	gpio_request(GPIO_FN_LCDD1,    NULL);
+	gpio_request(GPIO_FN_LCDD0,    NULL);
+	gpio_request(GPIO_FN_LCDDISP,  NULL);
+	gpio_request(GPIO_FN_LCDHSYN,  NULL);
+	gpio_request(GPIO_FN_LCDDCK,   NULL);
+	gpio_request(GPIO_FN_LCDVSYN,  NULL);
+	gpio_request(GPIO_FN_LCDDON,   NULL);
+	gpio_request(GPIO_FN_LCDVEPWC, NULL);
+	gpio_request(GPIO_FN_LCDVCPWC, NULL);
+	gpio_request(GPIO_FN_LCDRD,    NULL);
+	gpio_request(GPIO_FN_LCDLCLK,  NULL);
+	ctrl_outw((ctrl_inw(PORT_HIZA) & ~0x0001), PORT_HIZA);
+
+	/* enable CEU0 */
+	gpio_request(GPIO_FN_VIO0_D15, NULL);
+	gpio_request(GPIO_FN_VIO0_D14, NULL);
+	gpio_request(GPIO_FN_VIO0_D13, NULL);
+	gpio_request(GPIO_FN_VIO0_D12, NULL);
+	gpio_request(GPIO_FN_VIO0_D11, NULL);
+	gpio_request(GPIO_FN_VIO0_D10, NULL);
+	gpio_request(GPIO_FN_VIO0_D9,  NULL);
+	gpio_request(GPIO_FN_VIO0_D8,  NULL);
+	gpio_request(GPIO_FN_VIO0_D7,  NULL);
+	gpio_request(GPIO_FN_VIO0_D6,  NULL);
+	gpio_request(GPIO_FN_VIO0_D5,  NULL);
+	gpio_request(GPIO_FN_VIO0_D4,  NULL);
+	gpio_request(GPIO_FN_VIO0_D3,  NULL);
+	gpio_request(GPIO_FN_VIO0_D2,  NULL);
+	gpio_request(GPIO_FN_VIO0_D1,  NULL);
+	gpio_request(GPIO_FN_VIO0_D0,  NULL);
+	gpio_request(GPIO_FN_VIO0_VD,  NULL);
+	gpio_request(GPIO_FN_VIO0_CLK, NULL);
+	gpio_request(GPIO_FN_VIO0_FLD, NULL);
+	gpio_request(GPIO_FN_VIO0_HD,  NULL);
+	platform_resource_setup_memory(&ceu0_device, "ceu0", 4 << 20);
+
+	/* enable CEU1 */
+	gpio_request(GPIO_FN_VIO1_D7,  NULL);
+	gpio_request(GPIO_FN_VIO1_D6,  NULL);
+	gpio_request(GPIO_FN_VIO1_D5,  NULL);
+	gpio_request(GPIO_FN_VIO1_D4,  NULL);
+	gpio_request(GPIO_FN_VIO1_D3,  NULL);
+	gpio_request(GPIO_FN_VIO1_D2,  NULL);
+	gpio_request(GPIO_FN_VIO1_D1,  NULL);
+	gpio_request(GPIO_FN_VIO1_D0,  NULL);
+	gpio_request(GPIO_FN_VIO1_FLD, NULL);
+	gpio_request(GPIO_FN_VIO1_HD,  NULL);
+	gpio_request(GPIO_FN_VIO1_VD,  NULL);
+	gpio_request(GPIO_FN_VIO1_CLK, NULL);
+	platform_resource_setup_memory(&ceu1_device, "ceu1", 4 << 20);
+
+	/* KEYSC */
+	gpio_request(GPIO_FN_KEYOUT5_IN5, NULL);
+	gpio_request(GPIO_FN_KEYOUT4_IN6, NULL);
+	gpio_request(GPIO_FN_KEYIN4,      NULL);
+	gpio_request(GPIO_FN_KEYIN3,      NULL);
+	gpio_request(GPIO_FN_KEYIN2,      NULL);
+	gpio_request(GPIO_FN_KEYIN1,      NULL);
+	gpio_request(GPIO_FN_KEYIN0,      NULL);
+	gpio_request(GPIO_FN_KEYOUT3,     NULL);
+	gpio_request(GPIO_FN_KEYOUT2,     NULL);
+	gpio_request(GPIO_FN_KEYOUT1,     NULL);
+	gpio_request(GPIO_FN_KEYOUT0,     NULL);
+
+	/*
+	 * enable SH-Eth
+	 *
+	 * please remove J33 pin from your board !!
+	 *
+	 * ms7724 board should not use GPIO_FN_LNKSTA pin
+	 * So, This time PTX5 is set to input pin
+	 */
+	gpio_request(GPIO_FN_RMII_RXD0,    NULL);
+	gpio_request(GPIO_FN_RMII_RXD1,    NULL);
+	gpio_request(GPIO_FN_RMII_TXD0,    NULL);
+	gpio_request(GPIO_FN_RMII_TXD1,    NULL);
+	gpio_request(GPIO_FN_RMII_REF_CLK, NULL);
+	gpio_request(GPIO_FN_RMII_TX_EN,   NULL);
+	gpio_request(GPIO_FN_RMII_RX_ER,   NULL);
+	gpio_request(GPIO_FN_RMII_CRS_DV,  NULL);
+	gpio_request(GPIO_FN_MDIO,         NULL);
+	gpio_request(GPIO_FN_MDC,          NULL);
+	gpio_request(GPIO_PTX5, NULL);
+	gpio_direction_input(GPIO_PTX5);
+	sh_eth_init();
+
+	if (sw & SW41_B) {
+		/* SVGA */
+		lcdc_info.ch[0].lcd_cfg.xres         = 800;
+		lcdc_info.ch[0].lcd_cfg.yres         = 600;
+		lcdc_info.ch[0].lcd_cfg.left_margin  = 142;
+		lcdc_info.ch[0].lcd_cfg.right_margin = 52;
+		lcdc_info.ch[0].lcd_cfg.hsync_len    = 96;
+		lcdc_info.ch[0].lcd_cfg.upper_margin = 24;
+		lcdc_info.ch[0].lcd_cfg.lower_margin = 2;
+		lcdc_info.ch[0].lcd_cfg.vsync_len    = 2;
+	} else {
+		/* VGA */
+		lcdc_info.ch[0].lcd_cfg.xres         = 640;
+		lcdc_info.ch[0].lcd_cfg.yres         = 480;
+		lcdc_info.ch[0].lcd_cfg.left_margin  = 105;
+		lcdc_info.ch[0].lcd_cfg.right_margin = 50;
+		lcdc_info.ch[0].lcd_cfg.hsync_len    = 96;
+		lcdc_info.ch[0].lcd_cfg.upper_margin = 33;
+		lcdc_info.ch[0].lcd_cfg.lower_margin = 10;
+		lcdc_info.ch[0].lcd_cfg.vsync_len    = 2;
+	}
+
+	if (sw & SW41_A) {
+		/* Digital monitor */
+		lcdc_info.ch[0].interface_type = RGB18;
+		lcdc_info.ch[0].flags          = 0;
+	} else {
+		/* Analog monitor */
+		lcdc_info.ch[0].interface_type = RGB24;
+		lcdc_info.ch[0].flags          = LCDC_FLAGS_DWPOL;
+	}
+
+	return platform_add_devices(ms7724se_devices,
+				    ARRAY_SIZE(ms7724se_devices));
+}
+device_initcall(devices_setup);
+
+static struct sh_machine_vector mv_ms7724se __initmv = {
+	.mv_name	= "ms7724se",
+	.mv_init_irq	= init_se7724_IRQ,
+	.mv_nr_irqs	= SE7724_FPGA_IRQ_BASE + SE7724_FPGA_IRQ_NR,
+};
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7751/io.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7751/io.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7751/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7751/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,8 +34,6 @@
 {
 	if (PXSEG(port))
 		return *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port))
-		return *(volatile unsigned char *)pci_ioaddr(port);
 	else
 		return (*port2adr(port)) & 0xff;
 }
@@ -46,8 +44,6 @@
 
         if (PXSEG(port))
                 v = *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port))
-                v = *(volatile unsigned char *)pci_ioaddr(port);
 	else
 		v = (*port2adr(port)) & 0xff;
 	ctrl_delay();
@@ -58,8 +54,6 @@
 {
         if (PXSEG(port))
                 return *(volatile unsigned short *)port;
-	else if (is_pci_ioaddr(port))
-                return *(volatile unsigned short *)pci_ioaddr(port);
 	else if (port >= 0x2000)
 		return *port2adr(port);
 	else
@@ -71,8 +65,6 @@
 {
         if (PXSEG(port))
                 return *(volatile unsigned long *)port;
-	else if (is_pci_ioaddr(port))
-                return *(volatile unsigned int *)pci_ioaddr(port);
 	else if (port >= 0x2000)
 		return *port2adr(port);
 	else
@@ -85,8 +77,6 @@
 
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned char*)pci_ioaddr(port)) = value;
 	else
 		*(port2adr(port)) = value;
 }
@@ -95,8 +85,6 @@
 {
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned char*)pci_ioaddr(port)) = value;
 	else
 		*(port2adr(port)) = value;
 	ctrl_delay();
@@ -106,8 +94,6 @@
 {
         if (PXSEG(port))
                 *(volatile unsigned short *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned short *)pci_ioaddr(port)) = value;
 	else if (port >= 0x2000)
 		*port2adr(port) = value;
 	else
@@ -118,8 +104,6 @@
 {
         if (PXSEG(port))
                 *(volatile unsigned long *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned long*)pci_ioaddr(port)) = value;
 	else
 		maybebadio(port);
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7751/Makefile linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7751/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7751/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7751/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,5 +3,3 @@
 #
 
 obj-y	 := setup.o io.o irq.o
-
-obj-$(CONFIG_PCI) += pci.o
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7751/pci.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7751/pci.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7751/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7751/pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,147 +0,0 @@
-/*
- * linux/arch/sh/boards/se/7751/pci.c
- *
- * Author:  Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01)
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-#define PCIMCR_MRSET_OFF	0xBFFFFFFF
-#define PCIMCR_RFSH_OFF		0xFFFFFFFB
-
-/*
- * Only long word accesses of the PCIC's internal local registers and the
- * configuration registers from the CPU is supported.
- */
-#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
-#define PCIC_READ(x) readl(PCI_REG(x))
-
-/*
- * Description:  This function sets up and initializes the pcic, sets
- * up the BARS, maps the DRAM into the address space etc, etc.
- */
-int __init pcibios_init_platform(void)
-{
-   unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
-   unsigned short bcr2;
-
-   /*
-    * Initialize the slave bus controller on the pcic.  The values used
-    * here should not be hardcoded, but they should be taken from the bsc
-    * on the processor, to make this function as generic as possible.
-    * (i.e. Another sbc may usr different SDRAM timing settings -- in order
-    * for the pcic to work, its settings need to be exactly the same.)
-    */
-   bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
-   bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
-   wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
-   wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
-   wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
-   mcr = (*(volatile unsigned long*)(SH7751_MCR));
-
-   bcr1 = bcr1 | 0x00080000;  /* Enable Bit 19, BREQEN */
-   (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;   
-
-   bcr1 = bcr1 | 0x40080000;  /* Enable Bit 19 BREQEN, set PCIC to slave */
-   PCIC_WRITE(SH7751_PCIBCR1, bcr1);	 /* PCIC BCR1 */
-   PCIC_WRITE(SH7751_PCIBCR2, bcr2);     /* PCIC BCR2 */
-   PCIC_WRITE(SH7751_PCIWCR1, wcr1);     /* PCIC WCR1 */
-   PCIC_WRITE(SH7751_PCIWCR2, wcr2);     /* PCIC WCR2 */
-   PCIC_WRITE(SH7751_PCIWCR3, wcr3);     /* PCIC WCR3 */
-   mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
-   PCIC_WRITE(SH7751_PCIMCR, mcr);      /* PCIC MCR */
-
-
-   /* Enable all interrupts, so we know what to fix */
-   PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
-   PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
-
-   /* Set up standard PCI config registers */
-   PCIC_WRITE(SH7751_PCICONF1, 	0xF39000C7); /* Bus Master, Mem & I/O access */
-   PCIC_WRITE(SH7751_PCICONF2, 	0x00000000); /* PCI Class code & Revision ID */
-   PCIC_WRITE(SH7751_PCICONF4, 	0xab000001); /* PCI I/O address (local regs) */
-   PCIC_WRITE(SH7751_PCICONF5, 	0x0c000000); /* PCI MEM address (local RAM)  */
-   PCIC_WRITE(SH7751_PCICONF6, 	0xd0000000); /* PCI MEM address (unused)     */
-   PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
-   PCIC_WRITE(SH7751_PCILSR0, 0x03f00000);   /* MEM (full 64M exposed)       */
-   PCIC_WRITE(SH7751_PCILSR1, 0x00000000);   /* MEM (unused)                 */
-   PCIC_WRITE(SH7751_PCILAR0, 0x0c000000);   /* MEM (direct map from PCI)    */
-   PCIC_WRITE(SH7751_PCILAR1, 0x00000000);   /* MEM (unused)                 */
-
-   /* Now turn it on... */
-   PCIC_WRITE(SH7751_PCICR, 0xa5000001);
-
-   /*
-    * Set PCIMBR and PCIIOBR here, assuming a single window
-    * (16M MEM, 256K IO) is enough.  If a larger space is
-    * needed, the readx/writex and inx/outx functions will
-    * have to do more (e.g. setting registers for each call).
-    */
-
-   /*
-    * Set the MBR so PCI address is one-to-one with window,
-    * meaning all calls go straight through... use BUG_ON to
-    * catch erroneous assumption.
-    */
-   BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE);
-
-   PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM);
-
-   /* Set IOBR for window containing area specified in pci.h */
-   PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK));
-
-   /* All done, may as well say so... */
-   printk("SH7751 PCI: Finished initialization of the PCI controller\n");
-
-   return 1;
-}
-
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
-{
-        switch (slot) {
-        case 0: return 13;
-        case 1: return 13; 	/* AMD Ethernet controller */
-        case 2: return -1;
-        case 3: return -1;
-        case 4: return -1;
-        default:
-                printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
-                return -1;
-        }
-}
-
-static struct resource sh7751_io_resource = {
-	.name   = "SH7751 IO",
-	.start  = SH7751_PCI_IO_BASE,
-	.end    = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
-	.flags  = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
-	.name   = "SH7751 mem",
-	.start  = SH7751_PCI_MEMORY_BASE,
-	.end    = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
-	.flags  = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7780/irq.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7780/irq.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/7780/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/7780/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,10 +12,12 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <mach-se/mach/se7780.h>
 
+#define INTC_BASE	0xffd00000
+#define INTC_ICR1	(INTC_BASE+0x1c)
+
 /*
  * Initialize IRQ setting
  */
@@ -43,4 +45,24 @@
 	ctrl_outw((IRQPIN_PCCPW << IRQPOS_PCCPW), FPGA_INTSEL3);
 
 	plat_irq_setup_pins(IRQ_MODE_IRQ); /* install handlers for IRQ0-7 */
+
+	/* ICR1: detect low level(for 2ndcut) */
+	ctrl_outl(0xAAAA0000, INTC_ICR1);
+
+	/*
+	 * FPGA PCISEL register initialize
+	 *
+	 *  CPU  || SLOT1 | SLOT2 | S-ATA | USB
+	 *  -------------------------------------
+	 *  INTA || INTA  | INTD  |  --   | INTB
+	 *  -------------------------------------
+	 *  INTB || INTB  | INTA  |  --   | INTC
+	 *  -------------------------------------
+	 *  INTC || INTC  | INTB  | INTA  |  --
+	 *  -------------------------------------
+	 *  INTD || INTD  | INTC  |  --   | INTA
+	 *  -------------------------------------
+	 */
+	ctrl_outw(0x0013, FPGA_PCI_INTSEL1);
+	ctrl_outw(0xE402, FPGA_PCI_INTSEL2);
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/Makefile linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-se/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-se/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,3 +7,4 @@
 obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)	+= 7780/
 obj-$(CONFIG_SH_7343_SOLUTION_ENGINE)	+= 7343/
 obj-$(CONFIG_SH_7721_SOLUTION_ENGINE)	+= 7721/
+obj-$(CONFIG_SH_7724_SOLUTION_ENGINE)	+= 7724/
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-sh03/rtc.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-sh03/rtc.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-sh03/rtc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-sh03/rtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,13 +35,13 @@
 #define RTC_BUSY	1
 #define RTC_STOP	2
 
-extern spinlock_t rtc_lock;
+static DEFINE_SPINLOCK(sh03_rtc_lock);
 
 unsigned long get_cmos_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
 
-	spin_lock(&rtc_lock);
+	spin_lock(&sh03_rtc_lock);
  again:
 	do {
 		sec  = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10;
@@ -73,7 +73,7 @@
 		goto again;
 	}
 
-	spin_unlock(&rtc_lock);
+	spin_unlock(&sh03_rtc_lock);
 	return mktime(year, mon, day, hour, min, sec);
 }
 
@@ -91,7 +91,7 @@
 	int i;
 
 	/* gets recalled with irq locally disabled */
-	spin_lock(&rtc_lock);
+	spin_lock(&sh03_rtc_lock);
 	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
 		if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
 			break;
@@ -113,7 +113,7 @@
 		       cmos_minutes, real_minutes);
 		retval = -1;
 	}
-	spin_unlock(&rtc_lock);
+	spin_unlock(&sh03_rtc_lock);
 
 	return retval;
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-snapgear/io.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-snapgear/io.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-snapgear/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-snapgear/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,8 +36,6 @@
 {
 	if (PXSEG(port))
 		return *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port))
-		return *(volatile unsigned char *)pci_ioaddr(port);
 	else
 		return (*port2adr(port)) & 0xff;
 }
@@ -48,8 +46,6 @@
 
 	if (PXSEG(port))
 		v = *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port))
-		v = *(volatile unsigned char *)pci_ioaddr(port);
 	else
 		v = (*port2adr(port))&0xff;
 	ctrl_delay();
@@ -60,8 +56,6 @@
 {
 	if (PXSEG(port))
 		return *(volatile unsigned short *)port;
-	else if (is_pci_ioaddr(port))
-		return *(volatile unsigned short *)pci_ioaddr(port);
 	else if (port >= 0x2000)
 		return *port2adr(port);
 	else
@@ -73,8 +67,6 @@
 {
 	if (PXSEG(port))
 		return *(volatile unsigned long *)port;
-	else if (is_pci_ioaddr(port))
-		return *(volatile unsigned int *)pci_ioaddr(port);
 	else if (port >= 0x2000)
 		return *port2adr(port);
 	else
@@ -87,8 +79,6 @@
 
 	if (PXSEG(port))
 		*(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned char*)pci_ioaddr(port)) = value;
 	else
 		*(port2adr(port)) = value;
 }
@@ -97,8 +87,6 @@
 {
 	if (PXSEG(port))
 		*(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned char*)pci_ioaddr(port)) = value;
 	else
 		*(port2adr(port)) = value;
 	ctrl_delay();
@@ -108,8 +96,6 @@
 {
 	if (PXSEG(port))
 		*(volatile unsigned short *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned short *)pci_ioaddr(port)) = value;
 	else if (port >= 0x2000)
 		*port2adr(port) = value;
 	else
@@ -120,8 +106,6 @@
 {
 	if (PXSEG(port))
 		*(volatile unsigned long *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned long*)pci_ioaddr(port)) = value;
 	else
 		maybebadio(port);
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-systemh/io.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-systemh/io.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-systemh/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-systemh/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,8 +35,6 @@
 {
 	if (PXSEG(port))
 		return *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port))
-		return *(volatile unsigned char *)pci_ioaddr(port);
 	else if (port <= 0x3F1)
 		return *(volatile unsigned char *)ETHER_IOMAP(port);
 	else
@@ -49,8 +47,6 @@
 
         if (PXSEG(port))
                 v = *(volatile unsigned char *)port;
-	else if (is_pci_ioaddr(port))
-                v = *(volatile unsigned char *)pci_ioaddr(port);
 	else if (port <= 0x3F1)
 		v = *(volatile unsigned char *)ETHER_IOMAP(port);
 	else
@@ -63,8 +59,6 @@
 {
         if (PXSEG(port))
                 return *(volatile unsigned short *)port;
-	else if (is_pci_ioaddr(port))
-                return *(volatile unsigned short *)pci_ioaddr(port);
 	else if (port >= 0x2000)
 		return *port2adr(port);
 	else if (port <= 0x3F1)
@@ -78,8 +72,6 @@
 {
         if (PXSEG(port))
                 return *(volatile unsigned long *)port;
-	else if (is_pci_ioaddr(port))
-                return *(volatile unsigned int *)pci_ioaddr(port);
 	else if (port >= 0x2000)
 		return *port2adr(port);
 	else if (port <= 0x3F1)
@@ -94,8 +86,6 @@
 
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned char*)pci_ioaddr(port)) = value;
 	else if (port <= 0x3F1)
 		*(volatile unsigned char *)ETHER_IOMAP(port) = value;
 	else
@@ -106,8 +96,6 @@
 {
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned char*)pci_ioaddr(port)) = value;
 	else if (port <= 0x3F1)
 		*(volatile unsigned char *)ETHER_IOMAP(port) = value;
 	else
@@ -119,8 +107,6 @@
 {
         if (PXSEG(port))
                 *(volatile unsigned short *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned short *)pci_ioaddr(port)) = value;
 	else if (port >= 0x2000)
 		*port2adr(port) = value;
 	else if (port <= 0x3F1)
@@ -133,8 +119,6 @@
 {
         if (PXSEG(port))
                 *(volatile unsigned long *)port = value;
-	else if (is_pci_ioaddr(port))
-		*((unsigned long*)pci_ioaddr(port)) = value;
 	else
 		maybebadio(port);
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-titan/io.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-titan/io.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-titan/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-titan/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,8 +17,6 @@
 {
         if (PXSEG(port))
                 return ctrl_inb(port);
-        else if (is_pci_ioaddr(port))
-                return ctrl_inb(pci_ioaddr(port));
         return ctrl_inw(port2adr(port)) & 0xff;
 }
 
@@ -28,8 +26,6 @@
 
         if (PXSEG(port))
                 v = ctrl_inb(port);
-        else if (is_pci_ioaddr(port))
-                v = ctrl_inb(pci_ioaddr(port));
         else
                 v = ctrl_inw(port2adr(port)) & 0xff;
         ctrl_delay();
@@ -40,8 +36,6 @@
 {
         if (PXSEG(port))
                 return ctrl_inw(port);
-        else if (is_pci_ioaddr(port))
-                return ctrl_inw(pci_ioaddr(port));
         else if (port >= 0x2000)
                 return ctrl_inw(port2adr(port));
         else
@@ -53,8 +47,6 @@
 {
         if (PXSEG(port))
                 return ctrl_inl(port);
-        else if (is_pci_ioaddr(port))
-                return ctrl_inl(pci_ioaddr(port));
         else if (port >= 0x2000)
                 return ctrl_inw(port2adr(port));
         else
@@ -66,8 +58,6 @@
 {
         if (PXSEG(port))
                 ctrl_outb(value, port);
-        else if (is_pci_ioaddr(port))
-                ctrl_outb(value, pci_ioaddr(port));
         else
                 ctrl_outw(value, port2adr(port));
 }
@@ -76,8 +66,6 @@
 {
         if (PXSEG(port))
                 ctrl_outb(value, port);
-        else if (is_pci_ioaddr(port))
-                ctrl_outb(value, pci_ioaddr(port));
         else
                 ctrl_outw(value, port2adr(port));
         ctrl_delay();
@@ -87,8 +75,6 @@
 {
         if (PXSEG(port))
                 ctrl_outw(value, port);
-        else if (is_pci_ioaddr(port))
-                ctrl_outw(value, pci_ioaddr(port));
         else if (port >= 0x2000)
                 ctrl_outw(value, port2adr(port));
         else
@@ -99,8 +85,6 @@
 {
         if (PXSEG(port))
                 ctrl_outl(value, port);
-        else if (is_pci_ioaddr(port))
-                ctrl_outl(value, pci_ioaddr(port));
         else
                 maybebadio(port);
 }
@@ -117,10 +101,8 @@
 
 void __iomem *titan_ioport_map(unsigned long port, unsigned int size)
 {
-	if (PXSEG(port) || is_pci_memaddr(port))
+	if (PXSEG(port))
 		return (void __iomem *)port;
-	else if (is_pci_ioaddr(port))
-		return (void __iomem *)pci_ioaddr(port);
 
 	return (void __iomem *)port2adr(port);
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/boards/mach-x3proto/setup.c linux-libre-2.6.31-gnu/arch/sh/boards/mach-x3proto/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/boards/mach-x3proto/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boards/mach-x3proto/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,8 @@
 #include <linux/io.h>
 #include <linux/smc91x.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/r8a66597.h>
 #include <asm/ilsel.h>
 
 static struct resource heartbeat_resources[] = {
@@ -58,17 +60,20 @@
 	},
 };
 
+static struct r8a66597_platdata r8a66597_data = {
+	.xtal = R8A66597_PLATDATA_XTAL_12MHZ,
+	.vif = 1,
+};
+
 static struct resource r8a66597_usb_host_resources[] = {
 	[0] = {
-		.name	= "r8a66597_hcd",
 		.start	= 0x18040000,
 		.end	= 0x18080000 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.name	= "r8a66597_hcd",
 		/* Filled in by ilsel */
-		.flags	= IORESOURCE_IRQ,
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
 	},
 };
 
@@ -78,6 +83,7 @@
 	.dev = {
 		.dma_mask		= NULL,		/* don't use dma */
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &r8a66597_data,
 	},
 	.num_resources	= ARRAY_SIZE(r8a66597_usb_host_resources),
 	.resource	= r8a66597_usb_host_resources,
diff -druN linux-libre-2.6.30-gnu/arch/sh/boot/compressed/head_64.S linux-libre-2.6.31-gnu/arch/sh/boot/compressed/head_64.S
--- linux-libre-2.6.30-gnu/arch/sh/boot/compressed/head_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boot/compressed/head_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
  *   Copyright (C) 2002 Stuart Menefy (stuart.menefy@st.com)
  */
 #include <asm/cache.h>
+#include <asm/tlb.h>
 #include <cpu/mmu_context.h>
 #include <cpu/registers.h>
 
@@ -33,11 +34,7 @@
 #define	ICCR0_INIT_VAL	ICCR0_ON | ICCR0_ICI		/* ICE + ICI */
 #define	ICCR1_INIT_VAL	ICCR1_NOLOCK			/* No locking */
 
-#if 1
 #define	OCCR0_INIT_VAL	OCCR0_ON | OCCR0_OCI | OCCR0_WB	/* OCE + OCI + WB */
-#else
-#define	OCCR0_INIT_VAL	OCCR0_OFF
-#endif
 #define	OCCR1_INIT_VAL	OCCR1_NOLOCK			/* No locking */
 
 	.text
diff -druN linux-libre-2.6.30-gnu/arch/sh/boot/compressed/Makefile linux-libre-2.6.31-gnu/arch/sh/boot/compressed/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/boot/compressed/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boot/compressed/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,47 @@
-ifeq ($(CONFIG_SUPERH32),y)
-include ${srctree}/arch/sh/boot/compressed/Makefile_32
-else
-include ${srctree}/arch/sh/boot/compressed/Makefile_64
+#
+# linux/arch/sh/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
+		   head_$(BITS).o misc_$(BITS).o piggy.o
+
+OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc_$(BITS).o $(obj)/cache.o
+
+ifdef CONFIG_SH_STANDARD_BIOS
+OBJECTS += $(obj)/../../kernel/sh_bios.o
+endif
+
+#
+# IMAGE_OFFSET is the load offset of the compression loader
+#
+IMAGE_OFFSET	:= $(shell /bin/bash -c 'printf "0x%08x" \
+		     $$[$(CONFIG_PAGE_OFFSET)  + \
+			$(KERNEL_MEMORY) + \
+			$(CONFIG_BOOT_LINK_OFFSET)]')
+
+LIBGCC	:= $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+
+ifeq ($(CONFIG_FUNCTION_TRACER),y)
+ORIG_CFLAGS := $(KBUILD_CFLAGS)
+KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
+
+LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(IMAGE_OFFSET) -e startup \
+		   -T $(obj)/../../kernel/vmlinux.lds
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
+	$(call if_changed,ld)
+	@:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,gzip)
+
+OBJCOPYFLAGS += -R .empty_zero_page
+
+$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
+	$(call if_changed,as_o_S)
diff -druN linux-libre-2.6.30-gnu/arch/sh/boot/compressed/Makefile_32 linux-libre-2.6.31-gnu/arch/sh/boot/compressed/Makefile_32
--- linux-libre-2.6.30-gnu/arch/sh/boot/compressed/Makefile_32	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boot/compressed/Makefile_32	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-#
-# linux/arch/sh/boot/compressed/Makefile
-#
-# create a compressed vmlinux image from the original vmlinux
-#
-
-targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
-		   head_32.o misc_32.o piggy.o
-
-OBJECTS = $(obj)/head_32.o $(obj)/misc_32.o
-
-ifdef CONFIG_SH_STANDARD_BIOS
-OBJECTS += $(obj)/../../kernel/sh_bios.o
-endif
-
-#
-# IMAGE_OFFSET is the load offset of the compression loader
-#
-IMAGE_OFFSET	:= $(shell /bin/bash -c 'printf "0x%08x" \
-		     $$[$(CONFIG_PAGE_OFFSET)  + \
-			$(CONFIG_MEMORY_START) + \
-			$(CONFIG_BOOT_LINK_OFFSET)]')
-
-LIBGCC	:= $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
-ifeq ($(CONFIG_FUNCTION_TRACER),y)
-ORIG_CFLAGS := $(KBUILD_CFLAGS)
-KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
-endif
-
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
-
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
-	$(call if_changed,ld)
-	@:
-
-$(obj)/vmlinux.bin: vmlinux FORCE
-	$(call if_changed,objcopy)
-
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
-	$(call if_changed,gzip)
-
-OBJCOPYFLAGS += -R .empty_zero_page
-
-$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
-	$(call if_changed,as_o_S)
diff -druN linux-libre-2.6.30-gnu/arch/sh/boot/compressed/Makefile_64 linux-libre-2.6.31-gnu/arch/sh/boot/compressed/Makefile_64
--- linux-libre-2.6.30-gnu/arch/sh/boot/compressed/Makefile_64	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boot/compressed/Makefile_64	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-#
-# arch/sh/boot/compressed/Makefile_64
-#
-# create a compressed vmlinux image from the original vmlinux
-#
-# Copyright (C) 2002 Stuart Menefy
-# Copyright (C) 2004 Paul Mundt
-#
-# 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.
-#
-
-targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
-		   head_64.o misc_64.o cache.o piggy.o
-
-OBJECTS		:= $(obj)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o \
-		   $(obj)/cache.o
-
-#
-# ZIMAGE_OFFSET is the load offset of the compression loader
-# (4M for the kernel plus 64K for this loader)
-#
-ZIMAGE_OFFSET	:= $(shell /bin/bash -c 'printf "0x%08x" \
-		     $$[$(CONFIG_PAGE_OFFSET)+0x400000+0x10000]')
-
-LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \
-		    -T $(obj)/../../kernel/vmlinux.lds
-
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
-	$(call if_changed,ld)
-	@:
-
-$(obj)/vmlinux.bin: vmlinux FORCE
-	$(call if_changed,objcopy)
-
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
-	$(call if_changed,gzip)
-
-OBJCOPYFLAGS += -R .empty_zero_page
-
-$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE
-	$(call if_changed,as_o_S)
diff -druN linux-libre-2.6.30-gnu/arch/sh/boot/compressed/vmlinux_64.lds linux-libre-2.6.31-gnu/arch/sh/boot/compressed/vmlinux_64.lds
--- linux-libre-2.6.30-gnu/arch/sh/boot/compressed/vmlinux_64.lds	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boot/compressed/vmlinux_64.lds	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- * ld script to make compressed SuperH/shmedia Linux kernel+decompression
- *		bootstrap
- * Modified by Stuart Menefy from arch/sh/vmlinux.lds.S written by Niibe Yutaka
- */
-
-
-#ifdef CONFIG_LITTLE_ENDIAN
-/* OUTPUT_FORMAT("elf32-sh64l-linux", "elf32-sh64l-linux", "elf32-sh64l-linux") */
-#define NOP 0x6ff0fff0
-#else
-/* OUTPUT_FORMAT("elf32-sh64", "elf32-sh64", "elf32-sh64") */
-#define NOP 0xf0fff06f
-#endif
-
-OUTPUT_FORMAT("elf32-sh64-linux")
-OUTPUT_ARCH(sh)
-ENTRY(_start)
-
-#define ALIGNED_GAP(section, align) (((ADDR(section)+SIZEOF(section)+(align)-1) & ~((align)-1))-ADDR(section))
-#define FOLLOWING(section, align) AT (LOADADDR(section) + ALIGNED_GAP(section,align))
-
-SECTIONS
-{
-  _text = .;			/* Text and read-only data */
-
-  .text : {
-	*(.text)
-	*(.text64)
-	*(.text..SHmedia32)
-	*(.fixup)
-	*(.gnu.warning)
-	} = NOP
-  . = ALIGN(4);
-  .rodata : { *(.rodata) }
-
-  /* There is no 'real' reason for eight byte alignment, four would work
-   * as well, but gdb downloads much (*4) faster with this.
-   */
-  . = ALIGN(8);
-  .image : { *(.image) }
-  . = ALIGN(4);
-  _etext = .;			/* End of text section */
-
-  .data :			/* Data */
-	FOLLOWING(.image, 4)
-	{
-	_data = .;
-	*(.data)
-	}
-  _data_image = LOADADDR(.data);/* Address of data section in ROM */
-
-  _edata = .;			/* End of data section */
-
-  .stack : { stack = .;  _stack = .; }
-
-  . = ALIGN(4);
-  __bss_start = .;		/* BSS */
-  .bss : {
-	*(.bss)
-	}
-  . = ALIGN(4);
-  _end = . ;
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/boot/Makefile linux-libre-2.6.31-gnu/arch/sh/boot/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/boot/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/boot/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -20,9 +20,6 @@
 CONFIG_ZERO_PAGE_OFFSET	?= 0x00001000
 CONFIG_ENTRY_OFFSET	?= 0x00001000
 
-export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
-       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET
-
 targets := zImage vmlinux.srec uImage uImage.srec
 subdir- := compressed
 
@@ -43,6 +40,9 @@
 		     $$[$(CONFIG_MEMORY_START)]')
 endif
 
+export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \
+       CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY
+
 KERNEL_LOAD	:= $(shell /bin/bash -c 'printf "0x%08x" \
 		     $$[$(CONFIG_PAGE_OFFSET)  + \
 			$(KERNEL_MEMORY) + \
diff -druN linux-libre-2.6.30-gnu/arch/sh/cchips/hd6446x/hd64461.c linux-libre-2.6.31-gnu/arch/sh/cchips/hd6446x/hd64461.c
--- linux-libre-2.6.30-gnu/arch/sh/cchips/hd6446x/hd64461.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/cchips/hd6446x/hd64461.c	2009-09-09 18:13:59.000000000 -0400
@@ -80,7 +80,7 @@
 
 	printk(KERN_INFO
 	       "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
-	       CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE,
+	       HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE,
 	       HD64461_IRQBASE + 15);
 
 /* Should be at processor specific part.. */
diff -druN linux-libre-2.6.30-gnu/arch/sh/cchips/Kconfig linux-libre-2.6.31-gnu/arch/sh/cchips/Kconfig
--- linux-libre-2.6.30-gnu/arch/sh/cchips/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/cchips/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -34,11 +34,6 @@
 
 	  Do not change this unless you know what you are doing.
 
-config HD64461_IOBASE
-	hex "HD64461 start address"
-	depends on HD64461
-	default "0xb0000000"
-
 config HD64461_ENABLER
 	bool "HD64461 PCMCIA enabler"
 	depends on HD64461
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/ap325rxa_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/ap325rxa_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/ap325rxa_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/ap325rxa_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 17:46:53 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 16:04:11 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -86,18 +88,26 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -110,7 +120,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -159,6 +168,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_CPU_SUBTYPE_SH7723=y
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -168,8 +178,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -177,6 +185,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 CONFIG_29BIT=y
@@ -192,7 +201,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -205,9 +213,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -225,7 +233,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -236,10 +243,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_TMU=y
 # CONFIG_SH_TIMER_CMT is not set
-CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -281,12 +288,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=tty1 console=ttySC5,38400 root=/dev/nfs ip=dhcp"
 
@@ -369,6 +378,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -386,7 +396,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -529,6 +543,7 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
@@ -552,10 +567,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -572,14 +583,15 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -624,6 +636,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -695,6 +708,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=6
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -746,7 +760,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -818,10 +831,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
+CONFIG_MEDIA_SUPPORT=y
 
 #
 # Multimedia core support
@@ -1012,6 +1022,7 @@
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 CONFIG_UIO=y
@@ -1019,6 +1030,10 @@
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_UIO_SMX is not set
 # CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1030,6 +1045,7 @@
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
@@ -1039,10 +1055,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1052,6 +1069,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1100,6 +1122,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1191,15 +1214,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1303,6 +1324,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1320,3 +1342,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/cayman_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/cayman_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/cayman_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/cayman_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,24 +1,26 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 17:49:14 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:21:54 2009
 #
 CONFIG_SUPERH=y
 # CONFIG_SUPERH32 is not set
 CONFIG_SUPERH64=y
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/cayman_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CSUM=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 # CONFIG_GENERIC_GPIO is not set
-# CONFIG_GENERIC_TIME is not set
-# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 # CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -40,6 +42,7 @@
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
@@ -82,17 +85,25 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -105,7 +116,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -127,39 +137,6 @@
 # System type
 #
 CONFIG_CPU_SH5=y
-# CONFIG_CPU_SUBTYPE_SH7619 is not set
-# CONFIG_CPU_SUBTYPE_SH7201 is not set
-# CONFIG_CPU_SUBTYPE_SH7203 is not set
-# CONFIG_CPU_SUBTYPE_SH7206 is not set
-# CONFIG_CPU_SUBTYPE_SH7263 is not set
-# CONFIG_CPU_SUBTYPE_MXG is not set
-# CONFIG_CPU_SUBTYPE_SH7705 is not set
-# CONFIG_CPU_SUBTYPE_SH7706 is not set
-# CONFIG_CPU_SUBTYPE_SH7707 is not set
-# CONFIG_CPU_SUBTYPE_SH7708 is not set
-# CONFIG_CPU_SUBTYPE_SH7709 is not set
-# CONFIG_CPU_SUBTYPE_SH7710 is not set
-# CONFIG_CPU_SUBTYPE_SH7712 is not set
-# CONFIG_CPU_SUBTYPE_SH7720 is not set
-# CONFIG_CPU_SUBTYPE_SH7721 is not set
-# CONFIG_CPU_SUBTYPE_SH7750 is not set
-# CONFIG_CPU_SUBTYPE_SH7091 is not set
-# CONFIG_CPU_SUBTYPE_SH7750R is not set
-# CONFIG_CPU_SUBTYPE_SH7750S is not set
-# CONFIG_CPU_SUBTYPE_SH7751 is not set
-# CONFIG_CPU_SUBTYPE_SH7751R is not set
-# CONFIG_CPU_SUBTYPE_SH7760 is not set
-# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-# CONFIG_CPU_SUBTYPE_SH7723 is not set
-# CONFIG_CPU_SUBTYPE_SH7763 is not set
-# CONFIG_CPU_SUBTYPE_SH7770 is not set
-# CONFIG_CPU_SUBTYPE_SH7780 is not set
-# CONFIG_CPU_SUBTYPE_SH7785 is not set
-# CONFIG_CPU_SUBTYPE_SH7786 is not set
-# CONFIG_CPU_SUBTYPE_SHX3 is not set
-# CONFIG_CPU_SUBTYPE_SH7343 is not set
-# CONFIG_CPU_SUBTYPE_SH7722 is not set
-# CONFIG_CPU_SUBTYPE_SH7366 is not set
 CONFIG_CPU_SUBTYPE_SH5_101=y
 # CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
@@ -169,6 +146,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x20000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x80000000
 CONFIG_MEMORY_SIZE=0x00400000
 CONFIG_32BIT=y
@@ -182,7 +160,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -201,9 +178,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -219,7 +196,6 @@
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_SH_FPU=y
 # CONFIG_SH64_FPU_DENORM_FLUSH is not set
-CONFIG_SH64_USER_MISALIGNED_FIXUP=y
 CONFIG_SH64_ID2815_WORKAROUND=y
 CONFIG_CPU_HAS_FPU=y
 
@@ -231,8 +207,13 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
 # CPU Frequency scaling
@@ -266,12 +247,14 @@
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
-CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_BOOT_LINK_OFFSET=0x00400000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -279,8 +262,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -363,6 +344,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -380,7 +362,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -433,7 +419,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -456,10 +444,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -477,6 +461,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -485,6 +470,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -492,13 +478,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -527,7 +513,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -560,6 +545,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -568,6 +554,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -591,6 +578,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -750,7 +738,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -779,6 +766,7 @@
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -808,6 +796,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -854,92 +843,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-CONFIG_VIDEO_DEV=m
-CONFIG_VIDEO_V4L2_COMMON=m
-CONFIG_VIDEO_ALLOW_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_DVB_CORE=y
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-CONFIG_VIDEO_V4L2=m
-CONFIG_VIDEO_V4L1=m
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_BT848 is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_VIDEO_SAA7134 is not set
-# CONFIG_VIDEO_MXB is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
-# CONFIG_VIDEO_CX88 is not set
-# CONFIG_VIDEO_CX23885 is not set
-# CONFIG_VIDEO_IVTV is not set
-# CONFIG_VIDEO_CX18 is not set
-# CONFIG_VIDEO_CAFE_CCIC is not set
-# CONFIG_SOC_CAMERA is not set
-# CONFIG_RADIO_ADAPTERS is not set
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_AV7110 is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1042,7 +946,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1069,10 +972,15 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1082,6 +990,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1092,10 +1001,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1105,6 +1015,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1146,8 +1061,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1208,6 +1128,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 CONFIG_SCHEDSTATS=y
 # CONFIG_TIMER_STATS is not set
@@ -1241,24 +1164,29 @@
 # CONFIG_LATENCYTOP is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
 # CONFIG_PAGE_POISONING is not set
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 CONFIG_SH64_SR_WATCH=y
-# CONFIG_POOR_MANS_STRACE is not set
 
 #
 # Security options
@@ -1354,6 +1282,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1371,3 +1300,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/dreamcast_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/dreamcast_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/dreamcast_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/dreamcast_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 17:51:48 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:24:48 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -16,9 +17,11 @@
 # CONFIG_GENERIC_GPIO is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -83,13 +86,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
 # CONFIG_OPROFILE is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -98,6 +107,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -110,7 +121,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -156,6 +166,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +176,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -174,6 +183,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_29BIT=y
@@ -188,7 +198,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -207,9 +216,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -227,7 +236,6 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -238,9 +246,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=49876504
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -271,7 +280,7 @@
 CONFIG_SH_DMA_API=y
 CONFIG_SH_DMA=y
 CONFIG_SH_DMA_IRQ_MULTI=y
-CONFIG_NR_ONCHIP_DMA_CHANNELS=6
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
 CONFIG_NR_DMA_CHANNELS_BOOL=y
 CONFIG_NR_DMA_CHANNELS=9
 # CONFIG_PVR2_DMA is not set
@@ -304,12 +313,14 @@
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,115200 panic=3"
@@ -320,7 +331,6 @@
 CONFIG_MAPLE=y
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -399,6 +409,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -416,7 +427,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -461,6 +476,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -486,7 +502,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -539,6 +554,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -602,6 +618,7 @@
 # CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_MAPLE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
@@ -694,22 +711,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -812,7 +814,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -839,10 +840,15 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -854,10 +860,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -867,6 +874,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -910,6 +922,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -947,15 +960,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1051,6 +1062,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1068,3 +1080,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/edosk7705_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/edosk7705_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/edosk7705_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/edosk7705_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 17:54:02 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:25:35 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -17,6 +18,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -68,18 +70,26 @@
 # CONFIG_EVENTFD is not set
 CONFIG_SHMEM=y
 # CONFIG_AIO is not set
+
+#
+# Performance Counters
+#
 # CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
@@ -114,6 +124,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -123,8 +134,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -132,6 +141,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -148,7 +158,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -162,9 +171,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -192,9 +201,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=31250000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -239,6 +249,7 @@
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -331,21 +342,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -365,23 +362,35 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
 # File systems
 #
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+
+#
 # Pseudo filesystems
 #
 # CONFIG_PROC_FS is not set
@@ -409,15 +418,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -426,6 +433,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -441,3 +449,4 @@
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/edosk7760_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/edosk7760_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/edosk7760_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/edosk7760_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 17:54:57 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:25:55 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -40,6 +42,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -67,7 +70,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -89,13 +91,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -103,6 +111,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -115,7 +125,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -161,6 +170,7 @@
 CONFIG_CPU_SUBTYPE_SH7760=y
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -170,8 +180,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -179,6 +187,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -193,7 +202,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -206,9 +214,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -226,7 +234,6 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -237,9 +244,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -255,6 +263,7 @@
 #
 CONFIG_SH_DMA_API=y
 CONFIG_SH_DMA=y
+CONFIG_SH_DMA_IRQ_MULTI=y
 CONFIG_NR_ONCHIP_DMA_CHANNELS=8
 # CONFIG_NR_DMA_CHANNELS_BOOL is not set
 # CONFIG_SH_DMABRG is not set
@@ -286,12 +295,14 @@
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x02000000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=64M console=ttySC2,115200 root=/dev/nfs rw nfsroot=192.168.0.3:/scripts/filesys ip=192.168.0.4"
@@ -370,6 +381,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -387,7 +399,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -520,7 +536,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -545,6 +560,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -667,7 +683,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 CONFIG_I2C_DEBUG_CORE=y
 CONFIG_I2C_DEBUG_ALGO=y
@@ -700,22 +715,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -780,6 +780,11 @@
 # CONFIG_SND_VERBOSE_PROCFS is not set
 CONFIG_SND_VERBOSE_PRINTK=y
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
@@ -800,10 +805,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -815,6 +825,7 @@
 # CONFIG_EXT2_FS_SECURITY is not set
 CONFIG_EXT2_FS_XIP=y
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -825,10 +836,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -839,6 +851,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -883,6 +900,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -964,6 +982,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 CONFIG_TIMER_STATS=y
@@ -1001,18 +1022,22 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1024,10 +1049,8 @@
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1126,6 +1149,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1145,3 +1169,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/espt_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/espt_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/espt_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/espt_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 17:58:18 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:27:21 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -90,14 +92,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -106,6 +113,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -117,7 +126,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -164,6 +172,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 CONFIG_CPU_SUBTYPE_SH7763=y
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -173,8 +182,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -182,6 +189,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -198,7 +206,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -213,9 +220,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -244,9 +251,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=66666666
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -287,12 +295,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/nfs ip=bootp"
 
@@ -375,6 +385,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -527,10 +538,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -547,14 +554,15 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -599,6 +607,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -717,22 +726,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -906,10 +900,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -919,6 +918,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -929,10 +929,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -943,6 +944,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -985,8 +991,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -1074,17 +1085,17 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1179,6 +1190,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1197,3 +1209,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/hp6xx_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/hp6xx_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/hp6xx_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/hp6xx_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:01:05 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:28:12 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -79,18 +81,26 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -98,7 +108,6 @@
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -144,6 +153,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -153,8 +163,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -162,6 +170,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0d000000
 CONFIG_MEMORY_SIZE=0x00400000
 CONFIG_29BIT=y
@@ -176,7 +185,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -189,9 +197,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -220,9 +228,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=22110000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -246,7 +255,6 @@
 CONFIG_HD6446X_SERIES=y
 CONFIG_HD64461=y
 CONFIG_HD64461_IRQ=36
-CONFIG_HD64461_IOBASE=0xb0000000
 CONFIG_HD64461_ENABLER=y
 
 #
@@ -272,12 +280,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -367,10 +377,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -384,7 +390,9 @@
 # CONFIG_SCSI_SAS_LIBSAS is not set
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
 # CONFIG_SCSI_DH is not set
@@ -431,6 +439,7 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -519,21 +528,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -646,9 +641,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -662,9 +662,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -674,6 +675,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -719,6 +725,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 
 #
 # Partition Types
@@ -786,15 +793,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -898,6 +903,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -914,3 +920,4 @@
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/landisk_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/landisk_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/landisk_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/landisk_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:02:54 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:28:45 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -81,13 +83,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +103,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -107,7 +117,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -153,6 +162,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -162,8 +172,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -171,6 +179,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -185,7 +194,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -198,9 +206,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -218,7 +226,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -234,9 +241,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -278,12 +286,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
@@ -292,8 +302,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -419,6 +427,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -436,7 +445,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -487,6 +500,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -566,10 +580,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -587,6 +597,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -595,6 +606,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -602,13 +614,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -647,7 +659,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -696,6 +707,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -706,6 +718,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -729,6 +742,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -891,64 +905,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-CONFIG_VIDEO_DEV=m
-CONFIG_VIDEO_V4L2_COMMON=m
-CONFIG_VIDEO_ALLOW_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-# CONFIG_DVB_CORE is not set
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_VIDEO_V4L2=m
-CONFIG_VIDEO_V4L1=m
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_CPIA2 is not set
-# CONFIG_SOC_CAMERA is not set
-CONFIG_V4L_USB_DRIVERS=y
-# CONFIG_USB_VIDEO_CLASS is not set
-# CONFIG_USB_GSPCA is not set
-# CONFIG_VIDEO_HDPVR is not set
-CONFIG_VIDEO_USBVIDEO=m
-CONFIG_USB_VICAM=m
-CONFIG_USB_IBMCAM=m
-CONFIG_USB_KONICAWC=m
-# CONFIG_USB_QUICKCAM_MESSENGER is not set
-# CONFIG_USB_ET61X251 is not set
-CONFIG_USB_OV511=m
-CONFIG_USB_SE401=m
-CONFIG_USB_SN9C102=m
-CONFIG_USB_STV680=m
-# CONFIG_USB_ZC0301 is not set
-CONFIG_USB_PWC=m
-# CONFIG_USB_PWC_DEBUG is not set
-CONFIG_USB_PWC_INPUT_EVDEV=y
-# CONFIG_USB_ZR364XX is not set
-# CONFIG_USB_STKWEBCAM is not set
-# CONFIG_USB_S2255 is not set
-CONFIG_RADIO_ADAPTERS=y
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
-# CONFIG_RADIO_MAESTRO is not set
-CONFIG_USB_DSBR=m
-# CONFIG_USB_SI470X is not set
-# CONFIG_USB_MR800 is not set
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -994,15 +951,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=m
 CONFIG_HID_APPLE=m
 CONFIG_HID_BELKIN=m
 CONFIG_HID_CHERRY=m
 CONFIG_HID_CHICONY=m
 CONFIG_HID_CYPRESS=m
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=m
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=m
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=m
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1015,10 +974,11 @@
 CONFIG_HID_SAMSUNG=m
 CONFIG_HID_SONY=m
 CONFIG_HID_SUNPLUS=m
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1044,6 +1004,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1184,10 +1145,15 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1197,6 +1163,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1209,10 +1176,11 @@
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1222,6 +1190,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=m
@@ -1270,10 +1243,15 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 CONFIG_UFS_FS=m
 # CONFIG_UFS_FS_WRITE is not set
 # CONFIG_UFS_DEBUG is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
@@ -1364,16 +1342,14 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_EARLY_PRINTK is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1469,6 +1445,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1486,3 +1463,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/lboxre2_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/lboxre2_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/lboxre2_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/lboxre2_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:06:51 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:29:50 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -81,13 +83,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +103,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -107,7 +117,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -153,6 +162,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -162,8 +172,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -171,6 +179,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -185,7 +194,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -198,9 +206,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -218,7 +226,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -234,9 +241,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=40000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -278,12 +286,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,115200 root=/dev/sda1"
@@ -293,8 +303,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -417,6 +425,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -434,7 +443,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -484,6 +497,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -506,10 +520,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -527,6 +537,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -535,6 +546,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -542,13 +554,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -639,7 +651,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -692,6 +703,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -702,6 +714,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -725,6 +738,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -886,22 +900,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -931,7 +930,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -995,9 +993,14 @@
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1007,6 +1010,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1016,10 +1020,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1029,6 +1034,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1073,8 +1083,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -1151,16 +1166,14 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_EARLY_PRINTK is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1256,6 +1269,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1273,3 +1287,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/magicpanelr2_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/magicpanelr2_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/magicpanelr2_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/magicpanelr2_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:07:39 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:30:31 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,8 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -39,6 +42,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 # CONFIG_TASKSTATS is not set
@@ -66,7 +70,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -88,12 +91,18 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -101,6 +110,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -113,7 +124,6 @@
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -159,6 +169,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -168,8 +179,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -177,6 +186,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0C000000
 CONFIG_MEMORY_SIZE=0x03F00000
 CONFIG_29BIT=y
@@ -191,7 +201,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -204,9 +213,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -240,9 +249,11 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
+CONFIG_SH_TIMER_CMT=y
 CONFIG_SH_PCLK_FREQ=24000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -287,12 +298,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -369,6 +382,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -386,7 +400,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -525,7 +543,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -569,6 +586,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -724,22 +742,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -801,9 +804,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -813,24 +821,32 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 # CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -884,6 +900,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -965,6 +982,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1000,20 +1018,25 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0xa4430000
@@ -1022,10 +1045,8 @@
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1035,6 +1056,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1056,3 +1078,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/microdev_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/microdev_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/microdev_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/microdev_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:11:13 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:31:56 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -65,7 +67,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -86,18 +87,26 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -105,7 +114,6 @@
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -151,6 +159,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 CONFIG_CPU_SUBTYPE_SH4_202=y
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -160,8 +169,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -169,6 +176,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -183,7 +191,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -202,9 +209,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -222,7 +229,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -233,9 +239,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=66000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -280,12 +287,14 @@
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/hda1"
@@ -369,6 +378,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -386,7 +396,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -458,7 +472,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -483,6 +496,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -580,22 +594,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -634,10 +633,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -647,6 +651,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -656,10 +661,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -669,6 +675,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -715,6 +726,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -802,15 +814,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -914,6 +924,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -933,3 +944,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/migor_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/migor_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/migor_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/migor_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:14:03 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 16:06:48 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -20,6 +21,7 @@
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -67,7 +69,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -88,14 +89,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -104,6 +110,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -115,7 +123,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -165,6 +172,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -174,8 +182,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 CONFIG_CPU_SUBTYPE_SH7722=y
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -183,6 +189,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -201,7 +208,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -216,9 +222,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -237,7 +243,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_DSP=y
 
 #
@@ -251,10 +256,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_TMU=y
 # CONFIG_SH_TIMER_CMT is not set
-CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -295,14 +300,16 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ip=on root=/dev/nfs ip=dhcp"
+CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 earlyprintk=serial ip=on root=/dev/nfs ip=dhcp"
 
 #
 # Bus options
@@ -383,6 +390,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -402,7 +410,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -533,6 +545,7 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
@@ -556,10 +569,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -576,14 +585,15 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -608,6 +618,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -738,7 +749,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -794,10 +804,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
+CONFIG_MEDIA_SUPPORT=y
 
 #
 # Multimedia core support
@@ -851,7 +858,35 @@
 #
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -863,6 +898,27 @@
 # Console display driver support
 #
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+CONFIG_LOGO_SUPERH_VGA16=y
+# CONFIG_LOGO_SUPERH_CLUT224 is not set
 # CONFIG_SOUND is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
@@ -873,7 +929,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -898,6 +953,7 @@
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_IMX is not set
 CONFIG_USB_GADGET_M66592=y
@@ -908,9 +964,11 @@
 # CONFIG_USB_GADGET_CI13XXX is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ETH is not set
 # CONFIG_USB_GADGETFS is not set
 # CONFIG_USB_FILE_STORAGE is not set
@@ -982,6 +1040,7 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 CONFIG_UIO=y
@@ -989,6 +1048,10 @@
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_UIO_SMX is not set
 # CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1000,18 +1063,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1056,6 +1126,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -1104,19 +1175,19 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000
 CONFIG_EARLY_PRINTK=y
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1218,6 +1289,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1237,3 +1309,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/polaris_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/polaris_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/polaris_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/polaris_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:16:48 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:33:28 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -40,6 +42,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 # CONFIG_TASKSTATS is not set
@@ -88,12 +91,18 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -101,6 +110,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -113,7 +124,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -159,6 +169,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -168,8 +179,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -177,6 +186,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0C000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -191,7 +201,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -204,9 +213,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -236,9 +245,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -284,12 +294,14 @@
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,115200 root=/dev/mtdblock2 rootfstype=jffs2 mem=63M mtdparts=physmap-flash.0:0x00100000(bootloader)ro,0x00500000(Kernel)ro,0x00A00000(Filesystem)"
 
@@ -365,6 +377,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -518,7 +531,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -562,6 +574,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -674,22 +687,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -752,9 +750,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -766,18 +769,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -831,6 +841,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -874,6 +885,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -914,21 +928,26 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0x00000000
@@ -937,10 +956,8 @@
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -950,6 +967,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -970,3 +988,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/r7780mp_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/r7780mp_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/r7780mp_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/r7780mp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:20:17 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:34:44 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -90,15 +92,20 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -107,6 +114,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=0
@@ -118,7 +127,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -165,6 +173,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 CONFIG_CPU_SUBTYPE_SH7780=y
@@ -174,8 +183,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -183,6 +190,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 # CONFIG_29BIT is not set
@@ -201,7 +209,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -220,9 +227,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -256,9 +263,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
-CONFIG_SH_PCLK_FREQ=32000000
+CONFIG_SH_TIMER_TMU=y
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -299,12 +307,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
 
@@ -313,8 +323,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -404,6 +412,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -423,7 +432,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -445,7 +458,91 @@
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_CPQ_CISS_DA is not set
@@ -477,7 +574,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 CONFIG_EEPROM_93CX6=y
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -500,10 +599,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -521,6 +616,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -529,6 +625,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -536,13 +633,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -631,7 +728,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -685,6 +781,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 CONFIG_VIA_RHINE=m
 CONFIG_VIA_RHINE_MMIO=y
 # CONFIG_SC92031 is not set
@@ -696,6 +793,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -719,6 +817,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -891,7 +990,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -920,6 +1018,7 @@
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -949,6 +1048,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -984,22 +1084,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1027,7 +1112,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1108,9 +1192,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1120,6 +1209,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1130,10 +1220,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1141,6 +1232,12 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1181,6 +1278,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1191,6 +1289,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1279,6 +1378,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1315,35 +1417,40 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
-CONFIG_SH_STANDARD_BIOS=y
-# CONFIG_EARLY_SCIF_CONSOLE is not set
-CONFIG_EARLY_PRINTK=y
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1449,6 +1556,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1466,3 +1574,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/r7785rp_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/r7785rp_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/r7785rp_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/r7785rp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:24:35 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:37:20 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -20,6 +21,7 @@
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -43,6 +45,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -90,15 +93,20 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
@@ -108,6 +116,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -120,7 +130,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -168,6 +177,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -177,8 +187,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -186,6 +194,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 # CONFIG_29BIT is not set
@@ -208,7 +217,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 CONFIG_HUGETLB_PAGE_SIZE_1MB=y
@@ -229,9 +237,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -249,7 +257,6 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -264,9 +271,9 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
-CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_TIMER_TMU=y
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -323,12 +330,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
 
@@ -337,8 +346,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCI_LEGACY is not set
@@ -428,6 +435,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -448,7 +456,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -502,7 +514,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 CONFIG_EEPROM_93CX6=y
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -525,10 +539,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -546,6 +556,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -554,6 +565,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -561,13 +573,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -656,7 +668,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -690,6 +701,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -698,6 +710,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -721,6 +734,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -895,7 +909,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -948,6 +961,7 @@
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -970,6 +984,7 @@
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
@@ -977,6 +992,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1013,22 +1029,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1109,7 +1110,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1190,9 +1190,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1202,6 +1207,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1212,10 +1218,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1223,6 +1230,12 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1273,6 +1286,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1359,6 +1373,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1400,21 +1415,27 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1425,10 +1446,8 @@
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_4KSTACKS=y
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1534,6 +1553,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1552,3 +1572,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/rsk7201_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/rsk7201_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/rsk7201_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/rsk7201_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:29:08 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:39:54 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -14,10 +15,11 @@
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 # CONFIG_GENERIC_GPIO is not set
-# CONFIG_GENERIC_TIME is not set
-# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 # CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
+CONFIG_SYS_SUPPORTS_MTU2=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -65,7 +67,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -85,14 +86,19 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 # CONFIG_AIO is not set
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 # CONFIG_SLUB is not set
 CONFIG_SLOB=y
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -100,6 +106,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
@@ -110,7 +118,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -157,6 +164,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -166,14 +174,13 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
 #
 CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
+CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_29BIT=y
@@ -187,7 +194,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -200,7 +206,8 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1
 
 #
 # Cache configuration
@@ -227,10 +234,14 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_MTU2=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_MTU2=y
 CONFIG_SH_PCLK_FREQ=40000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_SH_CLK_MD=0
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
 # CPU Frequency scaling
@@ -266,12 +277,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ignore_loglevel"
 
@@ -505,21 +518,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -577,9 +576,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -592,17 +596,24 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-# CONFIG_FILE_LOCKING is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_FILE_LOCKING is not set
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -651,8 +662,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 
 #
 # Partition Types
@@ -685,17 +701,17 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -705,6 +721,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -724,3 +741,4 @@
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/rsk7203_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/rsk7203_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/rsk7203_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/rsk7203_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:30:34 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:40:44 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -14,11 +15,12 @@
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_GPIO=y
-# CONFIG_GENERIC_TIME is not set
-# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 # CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
 CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_MTU2=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -39,6 +41,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -70,7 +73,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -91,14 +93,19 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 # CONFIG_SLUB is not set
 CONFIG_SLOB=y
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -106,6 +113,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
@@ -116,7 +125,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -163,6 +171,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -172,14 +181,13 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
 #
 CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
+CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_29BIT=y
@@ -193,7 +201,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -206,7 +213,8 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1
 
 #
 # Cache configuration
@@ -233,11 +241,15 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_CMT=y
-# CONFIG_SH_MTU2 is not set
-CONFIG_SH_TIMER_IRQ=142
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_TIMER_MTU2=y
 CONFIG_SH_PCLK_FREQ=16670800
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_SH_CLK_MD=0
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
 # CPU Frequency scaling
@@ -288,12 +300,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ignore_loglevel"
 
@@ -373,6 +387,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -391,7 +406,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -526,7 +545,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -570,6 +588,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -703,24 +722,9 @@
 # CONFIG_REGULATOR_DEBUG is not set
 # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
 # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
 # CONFIG_REGULATOR_BQ24022 is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -750,15 +754,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -771,10 +777,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -874,6 +881,7 @@
 # LED drivers
 #
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
 
 #
 # LED Triggers
@@ -882,6 +890,7 @@
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+# CONFIG_LEDS_TRIGGER_GPIO is not set
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 
 #
@@ -925,9 +934,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -939,18 +953,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -989,8 +1010,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -1013,7 +1039,46 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 
 #
@@ -1033,6 +1098,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1075,19 +1143,26 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1098,10 +1173,8 @@
 CONFIG_DEBUG_BOOTMEM=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1111,6 +1184,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1130,3 +1204,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/rts7751r2d1_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/rts7751r2d1_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/rts7751r2d1_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/rts7751r2d1_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:33:25 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:42:26 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -82,15 +84,20 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -99,6 +106,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -110,7 +119,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -156,6 +164,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +174,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -174,6 +181,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -188,7 +196,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -201,9 +208,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -221,7 +228,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -243,9 +249,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=60000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -287,12 +294,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=serial"
@@ -302,8 +311,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -385,6 +392,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -404,7 +412,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -455,6 +467,7 @@
 #
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -477,10 +490,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -498,6 +507,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -506,6 +516,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -513,13 +524,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -608,7 +619,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -662,6 +672,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -672,6 +683,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -695,6 +707,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -793,6 +806,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=1
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -867,23 +881,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -985,6 +983,11 @@
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_MPU401_UART=m
 CONFIG_SND_OPL3_LIB=m
 CONFIG_SND_AC97_CODEC=m
@@ -1011,6 +1014,7 @@
 # CONFIG_SND_OXYGEN is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1041,6 +1045,7 @@
 # CONFIG_SND_INTEL8X0 is not set
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1079,15 +1084,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1100,10 +1107,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1129,6 +1137,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
@@ -1262,9 +1271,14 @@
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1278,10 +1292,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1291,6 +1306,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1337,6 +1357,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -1416,19 +1437,19 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
 CONFIG_EARLY_PRINTK=y
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1524,6 +1545,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1541,3 +1563,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/rts7751r2dplus_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/rts7751r2dplus_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/rts7751r2dplus_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/rts7751r2dplus_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:34:12 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:43:19 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -82,15 +84,20 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -99,6 +106,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -110,7 +119,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -156,6 +164,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +174,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -174,6 +181,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -188,7 +196,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -201,9 +208,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -221,7 +228,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -243,9 +249,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=60000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -287,12 +294,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=serial"
@@ -302,8 +311,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -385,6 +392,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -404,7 +412,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -424,7 +436,92 @@
 CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_CPQ_CISS_DA is not set
@@ -455,6 +552,7 @@
 #
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -477,10 +575,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -498,6 +592,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -506,6 +601,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -513,13 +609,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -608,7 +704,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -662,6 +757,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -672,6 +768,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -695,6 +792,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -793,6 +891,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=1
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -867,23 +966,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -985,6 +1068,11 @@
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_MPU401_UART=m
 CONFIG_SND_OPL3_LIB=m
 CONFIG_SND_AC97_CODEC=m
@@ -1011,6 +1099,7 @@
 # CONFIG_SND_OXYGEN is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1041,6 +1130,7 @@
 # CONFIG_SND_INTEL8X0 is not set
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1079,15 +1169,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1100,10 +1192,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1129,6 +1222,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
@@ -1262,9 +1356,14 @@
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1278,10 +1377,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1291,6 +1391,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1327,6 +1432,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1337,6 +1443,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -1416,19 +1523,19 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
 CONFIG_EARLY_PRINTK=y
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1524,6 +1631,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1541,3 +1649,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sdk7780_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sdk7780_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sdk7780_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sdk7780_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:34:43 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:43:54 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -41,6 +43,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -85,14 +88,20 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -100,6 +109,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -112,7 +123,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -159,6 +169,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 CONFIG_CPU_SUBTYPE_SH7780=y
@@ -168,8 +179,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -177,6 +186,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 # CONFIG_29BIT is not set
@@ -195,7 +205,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -214,9 +223,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -248,9 +257,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -296,12 +306,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x01800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=128M console=tty0 console=ttySC0,115200 ip=bootp root=/dev/nfs nfsroot=192.168.0.1:/home/rootfs"
 
@@ -310,8 +322,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCI_LEGACY is not set
@@ -439,6 +449,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -488,7 +499,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -611,10 +626,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -631,6 +642,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -639,6 +651,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -646,13 +659,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -753,7 +766,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -786,6 +798,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_ATL2 is not set
 # CONFIG_NETDEV_1000 is not set
@@ -968,22 +981,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1091,15 +1089,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1112,10 +1112,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1141,6 +1142,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1242,10 +1244,15 @@
 # CONFIG_LEDS_TRIGGERS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1257,6 +1264,7 @@
 # CONFIG_EXT2_FS_SECURITY is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1266,11 +1274,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1281,6 +1290,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
@@ -1331,6 +1345,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1418,6 +1433,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 CONFIG_TIMER_STATS=y
@@ -1455,18 +1473,22 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1477,10 +1499,8 @@
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1580,6 +1600,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1597,3 +1618,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7206_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7206_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7206_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7206_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:39:37 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:46:15 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -14,11 +15,12 @@
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 # CONFIG_GENERIC_GPIO is not set
-# CONFIG_GENERIC_TIME is not set
-# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 # CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
 CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_MTU2=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -40,11 +42,13 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_TREE=y
 
 #
 # RCU Subsystem
@@ -63,6 +67,7 @@
 CONFIG_CGROUP_NS=y
 # CONFIG_CGROUP_FREEZER is not set
 CONFIG_CGROUP_DEVICE=y
+# CONFIG_CPUSETS is not set
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEM_RES_CTLR=y
@@ -80,7 +85,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -101,14 +105,19 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 # CONFIG_SLUB is not set
 CONFIG_SLOB=y
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -116,6 +125,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
@@ -127,7 +138,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -174,6 +184,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -183,14 +194,13 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
 #
 CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
+CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -204,7 +214,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -217,7 +226,8 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1
 
 #
 # Cache configuration
@@ -242,11 +252,15 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_CMT=y
-# CONFIG_SH_MTU2 is not set
-CONFIG_SH_TIMER_IRQ=140
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_TIMER_MTU2=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_SH_CLK_MD=6
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
 # CPU Frequency scaling
@@ -297,12 +311,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC3,115200 ignore_loglevel earlyprintk=serial"
 
@@ -387,6 +403,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -405,7 +422,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -540,7 +561,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -565,6 +585,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -647,22 +668,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -719,9 +725,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -734,18 +745,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -785,8 +803,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -831,6 +854,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -868,19 +894,27 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -889,10 +923,8 @@
 # CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -991,6 +1023,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1014,3 +1047,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7343_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7343_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7343_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7343_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:42:00 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:47:07 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -40,6 +42,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
@@ -85,12 +88,18 @@
 CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -98,6 +107,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=0
@@ -109,7 +120,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -158,6 +168,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -167,8 +178,6 @@
 CONFIG_CPU_SUBTYPE_SH7343=y
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -176,6 +185,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_29BIT=y
@@ -190,7 +200,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -203,9 +212,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -235,10 +244,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_TMU=y
 # CONFIG_SH_TIMER_CMT is not set
-CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -279,12 +288,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200"
 
@@ -363,6 +374,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -380,7 +392,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -514,10 +530,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -538,7 +550,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -570,6 +581,7 @@
 CONFIG_USB_USBNET=y
 # CONFIG_USB_NET_AX8817X is not set
 CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
 CONFIG_USB_NET_DM9601=y
 # CONFIG_USB_NET_SMSC95XX is not set
 # CONFIG_USB_NET_GL620A is not set
@@ -579,6 +591,7 @@
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_INT51X1 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -692,7 +705,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -725,103 +737,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_ALLOW_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-# CONFIG_DVB_CORE is not set
-CONFIG_VIDEO_MEDIA=y
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=y
-CONFIG_MEDIA_TUNER_TDA8290=y
-CONFIG_MEDIA_TUNER_TDA9887=y
-CONFIG_MEDIA_TUNER_TEA5761=y
-CONFIG_MEDIA_TUNER_TEA5767=y
-CONFIG_MEDIA_TUNER_MT20XX=y
-CONFIG_MEDIA_TUNER_XC2028=y
-CONFIG_MEDIA_TUNER_XC5000=y
-CONFIG_MEDIA_TUNER_MC44S803=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_V4L1=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_CPIA2 is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_SOC_CAMERA is not set
-CONFIG_V4L_USB_DRIVERS=y
-# CONFIG_USB_VIDEO_CLASS is not set
-CONFIG_USB_GSPCA=m
-# CONFIG_USB_M5602 is not set
-# CONFIG_USB_STV06XX is not set
-# CONFIG_USB_GSPCA_CONEX is not set
-# CONFIG_USB_GSPCA_ETOMS is not set
-# CONFIG_USB_GSPCA_FINEPIX is not set
-# CONFIG_USB_GSPCA_MARS is not set
-# CONFIG_USB_GSPCA_MR97310A is not set
-# CONFIG_USB_GSPCA_OV519 is not set
-# CONFIG_USB_GSPCA_OV534 is not set
-# CONFIG_USB_GSPCA_PAC207 is not set
-# CONFIG_USB_GSPCA_PAC7311 is not set
-# CONFIG_USB_GSPCA_SONIXB is not set
-# CONFIG_USB_GSPCA_SONIXJ is not set
-# CONFIG_USB_GSPCA_SPCA500 is not set
-# CONFIG_USB_GSPCA_SPCA501 is not set
-# CONFIG_USB_GSPCA_SPCA505 is not set
-# CONFIG_USB_GSPCA_SPCA506 is not set
-# CONFIG_USB_GSPCA_SPCA508 is not set
-# CONFIG_USB_GSPCA_SPCA561 is not set
-# CONFIG_USB_GSPCA_SQ905 is not set
-# CONFIG_USB_GSPCA_SQ905C is not set
-# CONFIG_USB_GSPCA_STK014 is not set
-# CONFIG_USB_GSPCA_SUNPLUS is not set
-# CONFIG_USB_GSPCA_T613 is not set
-# CONFIG_USB_GSPCA_TV8532 is not set
-# CONFIG_USB_GSPCA_VC032X is not set
-# CONFIG_USB_GSPCA_ZC3XX is not set
-# CONFIG_VIDEO_PVRUSB2 is not set
-# CONFIG_VIDEO_HDPVR is not set
-# CONFIG_VIDEO_EM28XX is not set
-# CONFIG_VIDEO_USBVISION is not set
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_QUICKCAM_MESSENGER is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_VIDEO_OVCAMCHIP is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_STV680 is not set
-# CONFIG_USB_ZC0301 is not set
-# CONFIG_USB_PWC is not set
-# CONFIG_USB_ZR364XX is not set
-# CONFIG_USB_STKWEBCAM is not set
-# CONFIG_USB_S2255 is not set
-CONFIG_RADIO_ADAPTERS=y
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_SI470X is not set
-# CONFIG_USB_MR800 is not set
-# CONFIG_RADIO_TEA5764 is not set
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -887,6 +803,11 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
@@ -914,15 +835,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -935,10 +858,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -1033,6 +957,7 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
@@ -1041,6 +966,10 @@
 # CONFIG_UIO_PDRV_GENIRQ is not set
 # CONFIG_UIO_SMX is not set
 # CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1050,6 +979,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1059,18 +989,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1125,6 +1062,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1151,7 +1089,46 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 
 #
@@ -1174,17 +1151,15 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 CONFIG_EARLY_SCIF_CONSOLE=y
 CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000
 CONFIG_EARLY_PRINTK=y
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1279,6 +1254,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1298,3 +1274,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7619_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7619_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7619_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7619_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:44:53 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:47:56 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -14,8 +15,8 @@
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 # CONFIG_GENERIC_GPIO is not set
-# CONFIG_GENERIC_TIME is not set
-# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 # CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
 CONFIG_SYS_SUPPORTS_CMT=y
@@ -72,17 +73,25 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 # CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=1
@@ -134,6 +143,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -143,14 +153,13 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
 #
 CONFIG_QUICKLIST=y
 CONFIG_PAGE_OFFSET=0x00000000
+CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -164,7 +173,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -177,7 +185,8 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1
 
 #
 # Cache configuration
@@ -202,10 +211,14 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_CMT=y
-CONFIG_SH_TIMER_IRQ=86
+CONFIG_SH_TIMER_CMT=y
 CONFIG_SH_PCLK_FREQ=31250000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_SH_CLK_MD=5
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
 # CPU Frequency scaling
@@ -241,12 +254,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -475,21 +490,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -513,7 +514,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -538,10 +538,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -553,17 +558,24 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -601,8 +613,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 
 #
 # Partition Types
@@ -630,15 +647,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -647,6 +662,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -664,3 +680,4 @@
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7705_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7705_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7705_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7705_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:45:56 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:48:18 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -62,7 +64,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -82,18 +83,26 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -150,6 +159,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -159,8 +169,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -168,6 +176,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
 CONFIG_29BIT=y
@@ -182,7 +191,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -195,9 +203,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -228,9 +236,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -272,12 +281,14 @@
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -358,6 +369,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -375,7 +387,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -504,7 +520,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -529,6 +544,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -659,22 +675,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -698,7 +699,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -723,10 +723,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -740,9 +745,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -752,6 +758,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -804,6 +815,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -847,15 +859,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -949,6 +959,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -969,3 +980,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7712_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7712_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7712_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7712_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:48:18 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:49:00 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -17,6 +18,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -38,6 +40,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -81,12 +84,18 @@
 CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -94,6 +103,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -105,7 +116,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -151,6 +161,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -160,8 +171,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -169,6 +178,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
 CONFIG_29BIT=y
@@ -183,7 +193,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -196,9 +205,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -229,9 +238,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=66666666
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -273,12 +283,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
 
@@ -370,6 +382,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -423,7 +436,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -564,10 +581,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -584,7 +597,9 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
@@ -596,7 +611,6 @@
 CONFIG_PATA_PLATFORM=y
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -641,6 +655,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -725,22 +740,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -797,10 +797,15 @@
 # iptables trigger is under Netfilter config (LED target)
 #
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -812,6 +817,7 @@
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -821,18 +827,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -887,6 +900,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -927,6 +941,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -961,30 +976,33 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 # CONFIG_DUMP_CODE is not set
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1090,6 +1108,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1109,3 +1128,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7721_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7721_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7721_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7721_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:51:44 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:50:49 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -17,6 +18,8 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -38,6 +41,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -85,12 +89,18 @@
 CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -98,6 +108,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -109,7 +121,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -155,6 +166,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -164,8 +176,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -173,6 +183,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
 CONFIG_29BIT=y
@@ -187,7 +198,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -200,9 +210,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -232,9 +242,11 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
+CONFIG_SH_TIMER_CMT=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -276,12 +288,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda2"
 
@@ -373,6 +387,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -426,7 +441,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -568,10 +587,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -597,7 +612,6 @@
 CONFIG_PATA_PLATFORM=y
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -731,22 +745,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -776,15 +775,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -797,10 +798,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -928,10 +930,15 @@
 # iptables trigger is under Netfilter config (LED target)
 #
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -943,6 +950,7 @@
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -952,18 +960,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1021,6 +1036,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
 
 #
@@ -1085,6 +1101,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1119,30 +1136,33 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 # CONFIG_DUMP_CODE is not set
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1248,6 +1268,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1267,3 +1288,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7722_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7722_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7722_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7722_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:55:10 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 12:54:24 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -20,6 +21,7 @@
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -69,7 +71,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -90,13 +91,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
 # CONFIG_OPROFILE is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -105,6 +112,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -117,7 +126,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -167,6 +175,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -176,8 +185,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 CONFIG_CPU_SUBTYPE_SH7722=y
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -185,6 +192,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -203,7 +211,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -224,9 +231,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -245,7 +252,6 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_DSP=y
 
 #
@@ -258,10 +264,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_TMU=y
 # CONFIG_SH_TIMER_CMT is not set
-CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -303,12 +309,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -387,6 +395,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -404,7 +413,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -465,10 +478,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -485,7 +494,9 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
@@ -497,7 +508,6 @@
 CONFIG_PATA_PLATFORM=y
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -522,6 +532,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -653,22 +664,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -692,7 +688,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -754,9 +749,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -766,6 +766,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -776,10 +777,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -789,6 +791,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -832,6 +839,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -872,17 +880,15 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_EARLY_PRINTK is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -977,6 +983,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -996,3 +1003,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7724_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7724_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7724_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7724_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1566 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30
+# Mon Jun 29 16:28:43 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS 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_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+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_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+CONFIG_SOLUTION_ENGINE=y
+CONFIG_SH_7724_SOLUTION_ENGINE=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_TMU=y
+# CONFIG_SH_TIMER_CMT is not set
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_SECCOMP=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=tty1 console=ttySC3,115200 root=/dev/nfs ip=dhcp memchunk.vpu=4m"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# 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_ARPD 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 is not set
+# 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_LRO 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 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_MDIO_BITBANG=y
+# CONFIG_MDIO_GPIO is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+CONFIG_SH_ETH=y
+CONFIG_SMC91X=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_KEYBOARD_SH_KEYSC=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_SH_SCI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_CONTIG=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_SOC_CAMERA=y
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+CONFIG_SOC_CAMERA_OV772X=y
+CONFIG_VIDEO_SH_MOBILE_CEU=y
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_CX231XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+CONFIG_USB_R8A66597_HCD=y
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# 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
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_SPI=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY 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
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_UBIFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# 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_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7750_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7750_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7750_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7750_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:57:31 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:00:01 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -82,12 +84,18 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +103,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -106,7 +116,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -152,6 +161,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -161,8 +171,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -170,6 +178,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x02000000
 CONFIG_29BIT=y
@@ -184,7 +193,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -197,9 +205,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -218,7 +226,6 @@
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -230,9 +237,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -274,12 +282,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
@@ -362,6 +372,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -379,7 +390,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -532,10 +547,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -552,14 +563,15 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -584,6 +596,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -693,22 +706,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -747,10 +745,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -762,10 +765,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -775,6 +779,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -829,6 +838,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -886,15 +896,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -989,6 +997,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1008,3 +1017,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7751_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7751_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7751_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7751_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 18:59:59 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:02:26 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -65,7 +67,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -86,12 +87,18 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -99,6 +106,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -110,7 +119,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -156,6 +164,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -165,8 +174,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -174,6 +181,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -188,7 +196,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -201,9 +208,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -222,7 +229,6 @@
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -235,9 +241,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=60000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -279,12 +286,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,38400"
@@ -387,6 +396,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -404,7 +414,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -533,7 +547,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -558,6 +571,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -658,22 +672,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -712,10 +711,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -729,10 +733,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -742,6 +747,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -796,6 +806,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -833,15 +844,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -936,6 +945,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -956,3 +966,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/se7780_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/se7780_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/se7780_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/se7780_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:02:05 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:03:56 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -79,19 +81,27 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -103,7 +113,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -149,6 +158,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 CONFIG_CPU_SUBTYPE_SH7780=y
@@ -158,8 +168,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -167,6 +175,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 CONFIG_29BIT=y
@@ -183,7 +192,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -197,9 +205,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -230,9 +238,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -277,6 +286,7 @@
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00810000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0.115200 root=/dev/sda1"
 
@@ -285,8 +295,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -322,6 +330,7 @@
 # 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
 # CONFIG_INET_ESP is not set
@@ -376,7 +385,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -502,6 +515,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -523,10 +537,6 @@
 # CONFIG_BLK_DEV_SR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -543,6 +553,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -551,6 +562,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -558,13 +570,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -641,7 +653,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -707,6 +718,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_ATL2 is not set
 # CONFIG_NETDEV_1000 is not set
@@ -840,22 +852,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -957,15 +954,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -978,10 +977,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1093,10 +1093,15 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1110,9 +1115,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1122,6 +1128,10 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1245,16 +1255,14 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1345,6 +1353,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1363,3 +1372,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sh03_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sh03_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sh03_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sh03_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:04:59 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:04:41 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -16,9 +17,11 @@
 # CONFIG_GENERIC_GPIO is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -41,6 +44,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -67,7 +71,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -88,15 +91,20 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -105,6 +113,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -117,7 +127,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -163,6 +172,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -172,8 +182,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -181,6 +189,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 CONFIG_29BIT=y
@@ -195,7 +204,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -208,9 +216,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -229,7 +237,6 @@
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -241,9 +248,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=60000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -285,12 +293,14 @@
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00004000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,115200 mem=64M root=/dev/nfs"
@@ -300,8 +310,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -388,6 +396,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -406,7 +415,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -454,6 +467,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -526,10 +540,6 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -547,6 +557,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -555,6 +566,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -562,13 +574,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -597,7 +609,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -646,6 +657,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -656,6 +668,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -679,6 +692,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -842,22 +856,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -887,7 +886,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -914,10 +912,15 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -929,6 +932,7 @@
 # CONFIG_EXT2_FS_SECURITY is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -939,10 +943,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -952,6 +957,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=m
@@ -1001,6 +1011,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1111,18 +1122,18 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_EARLY_PRINTK is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1228,6 +1239,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1248,3 +1260,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sh7710voipgw_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sh7710voipgw_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sh7710voipgw_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sh7710voipgw_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:09:01 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:06:13 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -39,6 +41,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
@@ -84,12 +87,18 @@
 CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -97,6 +106,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=0
@@ -108,7 +119,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -154,6 +164,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -163,8 +174,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -172,6 +181,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x00800000
 CONFIG_29BIT=y
@@ -186,7 +196,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -199,9 +208,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -230,9 +239,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=32768000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -274,12 +284,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -376,6 +388,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -430,7 +443,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -560,7 +577,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -586,6 +602,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -689,22 +706,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -728,7 +730,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -753,10 +754,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -768,18 +774,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -834,6 +847,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -871,16 +885,14 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -975,6 +987,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -994,3 +1007,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sh7724_generic_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sh7724_generic_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sh7724_generic_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sh7724_generic_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,695 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:06:48 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+# CONFIG_CLASSIC_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+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_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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"
+CONFIG_FREEZER=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SHX2=y
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+CONFIG_CPU_SUBTYPE_SH7724=y
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+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_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_7724_SOLUTION_ENGINE is not set
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_TMU=y
+CONFIG_SH_TIMER_CMT=y
+CONFIG_SH_PCLK_FREQ=41666666
+CONFIG_SH_CLK_CPG=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_SH_CPU_FREQ=y
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_KEXEC_JUMP=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION_NVS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY 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_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# 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 is not set
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sh7763rdp_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sh7763rdp_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sh7763rdp_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sh7763rdp_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:10:57 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:07:15 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -90,14 +92,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -106,6 +113,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -117,7 +126,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -164,6 +172,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 CONFIG_CPU_SUBTYPE_SH7763=y
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -173,8 +182,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -182,6 +189,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -198,7 +206,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -213,9 +220,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -244,9 +251,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=66666666
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -287,12 +295,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC2,115200 root=/dev/sda1 rootdelay=10"
 
@@ -375,6 +385,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -394,7 +405,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -534,10 +549,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -554,14 +565,15 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -606,6 +618,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -724,22 +737,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -928,10 +926,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -941,6 +944,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -951,10 +955,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -965,6 +970,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1012,6 +1022,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -1099,17 +1110,17 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1204,6 +1215,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1221,3 +1233,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sh7770_generic_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sh7770_generic_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sh7770_generic_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sh7770_generic_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,688 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:08:05 2009
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+# CONFIG_CLASSIC_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+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_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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"
+CONFIG_FREEZER=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+CONFIG_CPU_SUBTYPE_SH7770=y
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SH7786 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+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_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+
+#
+# Cache configuration
+#
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_TMU=y
+CONFIG_SH_PCLK_FREQ=41666666
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_SH_CPU_FREQ=y
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_KEXEC_JUMP=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_HIBERNATION_NVS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# 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_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=6
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY 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_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# 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 is not set
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sh7785lcr_32bit_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sh7785lcr_32bit_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sh7785lcr_32bit_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sh7785lcr_32bit_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:12:18 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:08:29 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -20,6 +21,7 @@
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -91,13 +93,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
 # CONFIG_OPROFILE is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -106,6 +114,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -118,7 +128,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -166,6 +175,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -175,8 +185,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -184,6 +192,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x40000000
 CONFIG_MEMORY_SIZE=0x20000000
 # CONFIG_29BIT is not set
@@ -206,7 +215,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -221,9 +229,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -241,7 +249,6 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -253,9 +260,9 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_CLK_CPG=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -297,12 +304,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -310,8 +319,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -399,6 +406,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -417,7 +425,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -560,10 +572,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -655,7 +663,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -672,6 +679,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -859,7 +867,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -892,22 +899,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1009,15 +1001,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1030,10 +1024,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1059,6 +1054,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1206,9 +1202,14 @@
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1218,6 +1219,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -1227,10 +1229,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1240,6 +1243,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1289,6 +1297,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1377,6 +1386,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1413,18 +1425,22 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1434,10 +1450,8 @@
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 # CONFIG_DUMP_CODE is not set
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1542,6 +1556,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1559,3 +1574,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/sh7785lcr_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/sh7785lcr_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/sh7785lcr_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/sh7785lcr_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Wed Apr 22 19:17:56 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:09:34 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -21,6 +21,7 @@
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -80,7 +81,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -93,8 +93,13 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -187,6 +192,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 CONFIG_29BIT=y
@@ -204,7 +210,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -217,9 +222,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -237,7 +242,6 @@
 CONFIG_SH_STORE_QUEUES=y
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -250,9 +254,9 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=28
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_CLK_CPG=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -294,12 +298,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -307,8 +313,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -396,6 +400,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -414,7 +419,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -557,10 +566,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -652,7 +657,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -857,7 +861,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -890,22 +893,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1013,7 +1001,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1030,10 +1018,11 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1059,6 +1048,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1206,9 +1196,14 @@
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_SH is not set
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1228,10 +1223,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1424,18 +1420,16 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1450,10 +1444,8 @@
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 # CONFIG_DUMP_CODE is not set
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1576,3 +1568,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/shmin_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/shmin_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/shmin_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/shmin_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:19:03 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:10:33 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -17,6 +18,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -75,18 +77,26 @@
 CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 # CONFIG_SLUB is not set
 CONFIG_SLOB=y
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
@@ -137,6 +147,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -146,8 +157,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -155,6 +164,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x00800000
 CONFIG_29BIT=y
@@ -169,7 +179,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -182,9 +191,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -212,9 +221,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=32000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -256,12 +266,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00210000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,115200 root=1f01 mtdparts=phys_mapped_flash:64k(firm)ro,-(sys) netdev=34,0x300,eth0 "
 
@@ -341,6 +353,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -358,7 +371,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -485,7 +502,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -510,6 +526,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -595,22 +612,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -649,10 +651,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -664,17 +671,24 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -718,6 +732,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -762,16 +777,14 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 CONFIG_EARLY_PRINTK=y
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -864,6 +877,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -882,3 +896,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/shx3_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/shx3_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/shx3_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/shx3_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:20:54 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:11:03 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -22,6 +23,7 @@
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_SMP=y
 CONFIG_SYS_SUPPORTS_NUMA=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -42,6 +44,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
@@ -108,14 +111,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 # CONFIG_SLUB is not set
 CONFIG_SLOB=y
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
@@ -126,6 +134,8 @@
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
@@ -138,7 +148,6 @@
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -186,6 +195,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -195,8 +205,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -204,6 +212,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=7
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_29BIT=y
@@ -223,7 +232,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 CONFIG_PAGE_SIZE_64KB=y
-CONFIG_ENTRY_OFFSET=0x00010000
 # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 CONFIG_HUGETLB_PAGE_SIZE_1MB=y
@@ -246,9 +254,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -276,9 +284,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=50000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -336,12 +345,14 @@
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
-CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00010000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=bios ignore_loglevel"
 
@@ -441,6 +452,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -459,6 +471,7 @@
 # CAN Device Drivers
 #
 CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEV is not set
 # CONFIG_CAN_DEBUG_DEVICES is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -509,6 +522,7 @@
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
@@ -532,10 +546,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -552,7 +562,9 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
@@ -564,7 +576,6 @@
 CONFIG_PATA_PLATFORM=y
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -590,6 +601,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -646,6 +658,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=2
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
@@ -696,7 +709,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -753,22 +765,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -880,6 +877,7 @@
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_IMX is not set
 CONFIG_USB_GADGET_M66592=y
@@ -889,9 +887,11 @@
 # CONFIG_USB_GADGET_CI13XXX is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ETH is not set
 # CONFIG_USB_GADGETFS is not set
 # CONFIG_USB_FILE_STORAGE is not set
@@ -969,6 +969,7 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=y
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 CONFIG_UIO=m
@@ -976,6 +977,10 @@
 # CONFIG_UIO_PDRV_GENIRQ is not set
 # CONFIG_UIO_SMX is not set
 # CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -985,6 +990,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -995,10 +1001,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1008,6 +1015,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1051,6 +1063,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -1065,7 +1078,46 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
 
 #
@@ -1085,6 +1137,9 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1123,21 +1178,27 @@
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1147,10 +1208,8 @@
 # CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_IRQSTACKS is not set
 CONFIG_DUMP_CODE=y
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1245,6 +1304,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -1263,3 +1323,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/snapgear_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/snapgear_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/snapgear_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/snapgear_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:21:39 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:11:58 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -64,7 +66,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -85,19 +86,27 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -105,7 +114,6 @@
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -151,6 +159,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -160,8 +169,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -169,6 +176,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_29BIT=y
@@ -183,7 +191,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -196,9 +203,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -217,7 +224,6 @@
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -233,9 +239,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=60000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -281,12 +288,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
@@ -295,8 +304,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -366,6 +373,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +391,11 @@
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -528,7 +540,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -581,6 +592,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -695,22 +707,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -734,10 +731,15 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -751,18 +753,25 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -805,8 +814,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -844,15 +858,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -862,6 +874,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -881,3 +894,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/systemh_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/systemh_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/systemh_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/systemh_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:23:31 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:12:28 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -18,6 +19,7 @@
 CONFIG_GENERIC_CLOCKEVENTS=y
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -61,7 +63,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -82,12 +83,18 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -95,6 +102,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -107,7 +116,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -153,6 +161,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -162,8 +171,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -171,6 +178,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x00400000
 CONFIG_29BIT=y
@@ -185,7 +193,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -198,9 +205,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -218,7 +225,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -234,9 +240,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=60000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -278,12 +285,14 @@
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 # CONFIG_CMDLINE_BOOL is not set
 
@@ -426,21 +435,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -479,10 +474,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -494,9 +494,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -506,6 +507,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -547,8 +553,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 
 #
 # Partition Types
@@ -577,15 +588,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -595,6 +604,7 @@
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -613,3 +623,4 @@
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/titan_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/titan_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/titan_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/titan_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:24:55 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:12:54 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,7 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -40,6 +42,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
@@ -66,7 +69,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -88,13 +90,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_IOREMAP_PROT=y
@@ -102,6 +110,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -114,7 +124,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -160,6 +169,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -169,8 +179,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -178,6 +186,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08030000
 CONFIG_MEMORY_SIZE=0x7fd0000
 CONFIG_29BIT=y
@@ -192,7 +201,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -205,9 +213,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -226,7 +234,6 @@
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_IPR_IRQ=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_FPU=y
 
 #
@@ -242,9 +249,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=30000000
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -290,12 +298,14 @@
 # CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
 # CONFIG_GUSA_RB is not set
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x009e0000
+CONFIG_ENTRY_OFFSET=0x00001000
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf rw"
@@ -305,8 +315,6 @@
 #
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_AUTO=y
-CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
 # CONFIG_PCIEPORTBUS is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
@@ -416,6 +424,7 @@
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
 # CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_TPROXY is not set
 CONFIG_NETFILTER_XTABLES=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 # CONFIG_NETFILTER_XT_TARGET_DSCP is not set
@@ -453,6 +462,7 @@
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 # CONFIG_NETFILTER_XT_MATCH_TIME is not set
 # CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
 # CONFIG_IP_VS is not set
 
 #
@@ -516,6 +526,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -588,7 +599,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -730,6 +745,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -753,10 +769,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -774,6 +786,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -782,6 +795,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -789,13 +803,13 @@
 # CONFIG_SCSI_MPT2SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -824,7 +838,6 @@
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_IFB is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -896,6 +909,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -906,6 +920,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -929,6 +944,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -961,6 +977,7 @@
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_AX8817X=m
 CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_CDC_EEM is not set
 # CONFIG_USB_NET_DM9601 is not set
 # CONFIG_USB_NET_SMSC95XX is not set
 # CONFIG_USB_NET_GL620A is not set
@@ -970,6 +987,7 @@
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_NET_INT51X1 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -1126,22 +1144,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1182,7 +1185,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1208,6 +1210,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_TT_NEWSCHED=y
@@ -1347,7 +1350,7 @@
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
-CONFIG_RTC_LIB=m
+CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=m
 
 #
@@ -1381,9 +1384,14 @@
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SH=m
+# CONFIG_RTC_DRV_GENERIC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1393,6 +1401,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 # CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
@@ -1402,7 +1411,6 @@
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_POSIX_ACL is not set
@@ -1410,6 +1418,8 @@
 # CONFIG_XFS_DEBUG is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1417,6 +1427,12 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1467,8 +1483,13 @@
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1519,7 +1540,7 @@
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-CONFIG_NLS=m
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
@@ -1576,6 +1597,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1610,30 +1632,33 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_4KSTACKS is not set
-# CONFIG_IRQSTACKS is not set
 # CONFIG_DUMP_CODE is not set
 # CONFIG_SH_NO_BSS_INIT is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1741,6 +1766,7 @@
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1765,3 +1791,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/ul2_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/ul2_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/ul2_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/ul2_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:30:27 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:14:36 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -20,6 +21,7 @@
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_NUMA=y
 CONFIG_SYS_SUPPORTS_CMT=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -69,7 +71,6 @@
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -90,13 +91,19 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
 # CONFIG_OPROFILE is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -105,6 +112,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -117,7 +126,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -167,6 +175,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -176,8 +185,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 CONFIG_CPU_SUBTYPE_SH7366=y
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -185,6 +192,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x01f00000
 CONFIG_29BIT=y
@@ -203,7 +211,6 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_256K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -224,9 +231,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -245,7 +252,6 @@
 # CONFIG_SH_STORE_QUEUES is not set
 CONFIG_CPU_HAS_INTEVT=y
 CONFIG_CPU_HAS_SR_RB=y
-CONFIG_CPU_HAS_PTEA=y
 CONFIG_CPU_HAS_DSP=y
 
 #
@@ -255,10 +261,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_TMU=y
 # CONFIG_SH_TIMER_CMT is not set
-CONFIG_SH_TIMER_IRQ=16
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -300,12 +306,14 @@
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_GUSA=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/nfs ip=dhcp"
 
@@ -388,6 +396,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -409,6 +418,8 @@
 CONFIG_LIB80211=m
 # CONFIG_LIB80211_DEBUG is not set
 CONFIG_MAC80211=y
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
 
 #
 # Rate control algorithm selection
@@ -563,10 +574,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -583,7 +590,9 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
@@ -595,7 +604,6 @@
 CONFIG_PATA_PLATFORM=y
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -620,6 +628,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -645,6 +654,7 @@
 # CONFIG_B43LEGACY is not set
 # CONFIG_ZD1211RW is not set
 # CONFIG_RT2X00 is not set
+# CONFIG_IWM is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -660,6 +670,7 @@
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_AX8817X=y
 CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
 # CONFIG_USB_NET_DM9601 is not set
 # CONFIG_USB_NET_SMSC95XX is not set
 # CONFIG_USB_NET_GL620A is not set
@@ -669,6 +680,7 @@
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_INT51X1 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -771,22 +783,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -923,10 +920,15 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -936,6 +938,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
@@ -945,10 +948,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -958,6 +962,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1005,6 +1014,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
@@ -1095,15 +1105,13 @@
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
 
 #
 # Security options
@@ -1208,6 +1216,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1227,3 +1236,4 @@
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/configs/urquell_defconfig linux-libre-2.6.31-gnu/arch/sh/configs/urquell_defconfig
--- linux-libre-2.6.30-gnu/arch/sh/configs/urquell_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/configs/urquell_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29
-# Thu Apr  2 19:33:39 2009
+# Linux kernel version: 2.6.30
+# Thu Jun 18 13:15:28 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
+# CONFIG_SUPERH64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_BUG=y
@@ -19,6 +20,8 @@
 # CONFIG_ARCH_SUSPEND_POSSIBLE is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_SYS_SUPPORTS_NUMA=y
+CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_SYS_SUPPORTS_TMU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -33,25 +36,30 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_TREE=y
 
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
+# CONFIG_CLASSIC_RCU is not set
+CONFIG_TREE_RCU=y
 # CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
 # CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
@@ -59,15 +67,29 @@
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-# CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RT_GROUP_SCHED=y
+# CONFIG_USER_SCHED is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+# CONFIG_PROC_PID_CPUSET is not set
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_MEM_RES_CTLR=y
+CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
+CONFIG_MM_OWNER=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -75,6 +97,7 @@
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
@@ -88,12 +111,20 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
 # CONFIG_OPROFILE is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
@@ -102,6 +133,8 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -114,7 +147,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -125,12 +157,12 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-# CONFIG_FREEZER is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_FREEZER=y
 
 #
 # System type
@@ -162,6 +194,7 @@
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
 # CONFIG_CPU_SUBTYPE_SH4_202 is not set
 # CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7724 is not set
 # CONFIG_CPU_SUBTYPE_SH7763 is not set
 # CONFIG_CPU_SUBTYPE_SH7770 is not set
 # CONFIG_CPU_SUBTYPE_SH7780 is not set
@@ -171,8 +204,6 @@
 # CONFIG_CPU_SUBTYPE_SH7343 is not set
 # CONFIG_CPU_SUBTYPE_SH7722 is not set
 # CONFIG_CPU_SUBTYPE_SH7366 is not set
-# CONFIG_CPU_SUBTYPE_SH5_101 is not set
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
 
 #
 # Memory management options
@@ -180,6 +211,7 @@
 CONFIG_QUICKLIST=y
 CONFIG_MMU=y
 CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x08000000
 CONFIG_29BIT=y
@@ -198,7 +230,12 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_256K is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -213,9 +250,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=2
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Cache configuration
@@ -244,9 +281,10 @@
 #
 # Timer and clock configuration
 #
-CONFIG_SH_TMU=y
-CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_TIMER_TMU=y
 CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_SH_CLK_CPG=y
+CONFIG_SH_CLK_CPG_LEGACY=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -283,25 +321,37 @@
 CONFIG_SCHED_HRTICK=y
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
-# CONFIG_SECCOMP is not set
-# CONFIG_PREEMPT_NONE is not set
+CONFIG_SECCOMP=y
+CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
-CONFIG_PREEMPT=y
+# CONFIG_PREEMPT is not set
 CONFIG_GUSA=y
+CONFIG_SPARSE_IRQ=y
 
 #
 # Boot options
 #
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC1, 38400 earlyprintk=serial ip=on ignore_loglevel root=/dev/nfs ip=dhcp memchunk.vpu=4m"
+CONFIG_ENTRY_OFFSET=0x00001000
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Bus options
 #
+CONFIG_PCI=y
+# CONFIG_SH_PCIDMA_NONCOHERENT is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_DEBUG=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_LEGACY is not set
+CONFIG_PCI_DEBUG=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -309,13 +359,16 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_HAVE_AOUT is not set
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=y
 
 #
 # Power management options (EXPERIMENTAL)
 #
-# CONFIG_PM is not set
-# CONFIG_CPU_IDLE is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_HIBERNATION is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
 CONFIG_NET=y
 
 #
@@ -381,6 +434,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -388,6 +442,7 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_CAN is not set
 # CONFIG_IRDA is not set
@@ -399,7 +454,11 @@
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -415,6 +474,8 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
@@ -470,11 +531,13 @@
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
 # CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
 #
+# CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -500,9 +563,13 @@
 # CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# 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_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
@@ -534,10 +601,6 @@
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -558,24 +621,90 @@
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_SIL24=y
 CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
 # CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
 # CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
 # CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 # CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
 CONFIG_PHYLIB=y
 
 #
 # MII PHY device drivers
 #
-# CONFIG_MARVELL_PHY is not set
+CONFIG_MARVELL_PHY=y
 # CONFIG_DAVICOM_PHY is not set
 # CONFIG_QSEMI_PHY is not set
 # CONFIG_LXT_PHY is not set
@@ -594,11 +723,17 @@
 CONFIG_MII=y
 # CONFIG_AX88796 is not set
 # CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
 CONFIG_SMC91X=y
 # CONFIG_ETHOC is not set
 # CONFIG_SMC911X is not set
 # CONFIG_SMSC911X is not set
 # CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -606,9 +741,54 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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_NETDEV_1000 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=y
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+CONFIG_SKY2=y
+CONFIG_SKY2_DEBUG=y
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
 
 #
 # Wireless LAN
@@ -629,8 +809,11 @@
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -689,6 +872,7 @@
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
 
 #
 # Serial drivers
@@ -703,6 +887,7 @@
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
@@ -711,8 +896,10 @@
 CONFIG_HW_RANDOM=y
 # CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
@@ -724,6 +911,24 @@
 #
 
 #
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_GPIO is not set
@@ -739,6 +944,11 @@
 # CONFIG_I2C_TINY_USB is not set
 
 #
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
 # Other I2C/SMBus bus drivers
 #
 CONFIG_I2C_PCA_PLATFORM=y
@@ -751,7 +961,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -760,6 +969,7 @@
 # CONFIG_SPI is not set
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
 # CONFIG_GPIO_SYSFS is not set
 
 #
@@ -776,15 +986,79 @@
 #
 # PCI GPIO expanders:
 #
+# CONFIG_GPIO_BT8XX is not set
 
 #
 # SPI GPIO expanders:
 #
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
+CONFIG_THERMAL_HWMON=y
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -808,10 +1082,7 @@
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
+CONFIG_MEDIA_SUPPORT=y
 
 #
 # Multimedia core support
@@ -828,6 +1099,7 @@
 #
 # Graphics support
 #
+# CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
@@ -853,7 +1125,31 @@
 #
 # Frame buffer hardware drivers
 #
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
 CONFIG_FB_SH_MOBILE_LCDC=m
 CONFIG_FB_SM501=y
 # CONFIG_FB_VIRTUAL is not set
@@ -900,15 +1196,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -921,14 +1219,15 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
@@ -939,6 +1238,7 @@
 CONFIG_USB_DEVICEFS=y
 CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
@@ -950,12 +1250,19 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
-# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
 # CONFIG_USB_HWA_HCD is not set
 
 #
@@ -1029,14 +1336,74 @@
 #
 # CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
-# CONFIG_RTC_CLASS is not set
+# CONFIG_INFINIBAND 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
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+CONFIG_RTC_DRV_GENERIC=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1046,19 +1413,29 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4_FS is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
 CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
+CONFIG_BTRFS_FS=y
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1068,6 +1445,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1095,9 +1477,9 @@
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_CONFIGFS_FS=y
 CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
@@ -1110,26 +1492,23 @@
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
-CONFIG_MINIX_FS=y
+# CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-CONFIG_NFSD_V4=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
@@ -1192,32 +1571,74 @@
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS 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 is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
 # CONFIG_SH_STANDARD_BIOS is not set
-# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_MORE_COMPILE_OPTIONS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffeb0000
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_DUMP_CODE is not set
+# CONFIG_SH_NO_BSS_INIT is not set
 
 #
 # Security options
@@ -1277,7 +1698,7 @@
 #
 # Digest
 #
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=y
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
@@ -1322,6 +1743,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1329,13 +1751,18 @@
 CONFIG_BITREVERSE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 # CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=y
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/dma/Kconfig linux-libre-2.6.31-gnu/arch/sh/drivers/dma/Kconfig
--- linux-libre-2.6.30-gnu/arch/sh/drivers/dma/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/dma/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,8 @@
 		     CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7750R || \
 		     CPU_SUBTYPE_SH7751R || CPU_SUBTYPE_SH7091  || \
 		     CPU_SUBTYPE_SH7763  || CPU_SUBTYPE_SH7764  || \
-		     CPU_SUBTYPE_SH7780  || CPU_SUBTYPE_SH7785
+		     CPU_SUBTYPE_SH7780  || CPU_SUBTYPE_SH7785  || \
+		     CPU_SUBTYPE_SH7760
 
 config NR_ONCHIP_DMA_CHANNELS
 	int
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-cayman.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-cayman.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-cayman.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-cayman.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,77 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <cpu/irq.h>
+#include "pci-sh5.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int result = -1;
+
+	/* The complication here is that the PCI IRQ lines from the Cayman's 2
+	   5V slots get into the CPU via a different path from the IRQ lines
+	   from the 3 3.3V slots.  Thus, we have to detect whether the card's
+	   interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
+	   at the point where we cross from 5V to 3.3V is not the normal case.
+
+	   The added complication is that we don't know that the 5V slots are
+	   always bus 2, because a card containing a PCI-PCI bridge may be
+	   plugged into a 3.3V slot, and this changes the bus numbering.
+
+	   Also, the Cayman has an intermediate PCI bus that goes a custom
+	   expansion board header (and to the secondary bridge).  This bus has
+	   never been used in practice.
+
+	   The 1ary onboard PCI-PCI bridge is device 3 on bus 0
+	   The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of
+	   the 1ary bridge.
+	   */
+
+	struct slot_pin {
+		int slot;
+		int pin;
+	} path[4];
+	int i=0;
+
+	while (dev->bus->number > 0) {
+
+		slot = path[i].slot = PCI_SLOT(dev->devfn);
+		pin = path[i].pin = pci_swizzle_interrupt_pin(dev, pin);
+		dev = dev->bus->self;
+		i++;
+		if (i > 3) panic("PCI path to root bus too long!\n");
+	}
+
+	slot = PCI_SLOT(dev->devfn);
+	/* This is the slot on bus 0 through which the device is eventually
+	   reachable. */
+
+	/* Now work back up. */
+	if ((slot < 3) || (i == 0)) {
+		/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
+		   swizzle now. */
+		result = IRQ_INTA + pci_swizzle_interrupt_pin(dev, pin) - 1;
+	} else {
+		i--;
+		slot = path[i].slot;
+		pin  = path[i].pin;
+		if (slot > 0) {
+			panic("PCI expansion bus device found - not handled!\n");
+		} else {
+			if (i > 0) {
+				/* 5V slots */
+				i--;
+				slot = path[i].slot;
+				pin  = path[i].pin;
+				/* 'pin' was swizzled earlier wrt slot, don't do it again. */
+				result = IRQ_P2INTA + (pin - 1);
+			} else {
+				/* IRQ for 2ary PCI-PCI bridge : unused */
+				result = -1;
+			}
+		}
+	}
+
+	return result;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-dreamcast.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-dreamcast.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-dreamcast.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-dreamcast.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,7 @@
 
 static void __init gapspci_fixup_resources(struct pci_dev *dev)
 {
-	struct pci_channel *p = board_pci_channels;
+	struct pci_channel *p = dev->sysdata;
 
 	printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev));
 
@@ -41,6 +41,13 @@
 		 */
 		dev->resource[1].start	= p->io_resource->start  + 0x100;
 		dev->resource[1].end	= dev->resource[1].start + 0x200 - 1;
+
+		/*
+		 * This is not a normal BAR, prevent any attempts to move
+		 * the BAR, as this will result in a bus lock.
+		 */
+		dev->resource[1].flags |= IORESOURCE_PCI_FIXED;
+
 		/*
 		 * Redirect dma memory allocations to special memory window.
 		 */
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-landisk.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-landisk.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-landisk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-landisk.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * arch/sh/drivers/pci/ops-landisk.c
+ *
+ * PCI initialization for the I-O DATA Device, Inc. LANDISK board
+ *
+ * Copyright (C) 2006 kogiidena
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "pci-sh4.h"
+
+int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	/*
+	 * slot0: pin1-4 = irq5,6,7,8
+	 * slot1: pin1-4 = irq6,7,8,5
+	 * slot2: pin1-4 = irq7,8,5,6
+	 * slot3: pin1-4 = irq8,5,6,7
+	 */
+	int irq = ((slot + pin - 1) & 0x3) + 5;
+
+	if ((slot | (pin - 1)) > 0x3) {
+		printk("PCI: Bad IRQ mapping request for slot %d pin %c\n",
+		       slot, pin - 1 + 'A');
+		return -1;
+	}
+	return irq;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-lboxre2.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-lboxre2.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-lboxre2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-lboxre2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-lboxre2.c
- *
- * L-BOX RE2 PCI fixups
- *
- * Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * 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 "pci-sh4.h"
-
-#define PCIMCR_MRSET_OFF	0xBFFFFFFF
-#define PCIMCR_RFSH_OFF		0xFFFFFFFB
-
-int pci_fixup_pcic(void)
-{
-	unsigned long bcr1, mcr;
-
-	bcr1 = ctrl_inl(SH7751_BCR1);
-	bcr1 |= 0x40080000;	/* Enable Bit 19 BREQEN, set PCIC to slave */
-	pci_write_reg(bcr1, SH4_PCIBCR1);
-
-	/* Enable all interrupts, so we known what to fix */
-	pci_write_reg(0x0000c3ff, SH4_PCIINTM);
-	pci_write_reg(0x0000380f, SH4_PCIAINTM);
-	pci_write_reg(0xfb900047, SH7751_PCICONF1);
-	pci_write_reg(0xab000001, SH7751_PCICONF4);
-
-	mcr = ctrl_inl(SH7751_MCR);
-	mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
-	pci_write_reg(mcr, SH4_PCIMCR);
-
-	pci_write_reg(0x0c000000, SH7751_PCICONF5);
-	pci_write_reg(0xd0000000, SH7751_PCICONF6);
-	pci_write_reg(0x0c000000, SH4_PCILAR0);
-	pci_write_reg(0x00000000, SH4_PCILAR1);
-
-	return 0;
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-r7780rp.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-r7780rp.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-r7780rp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-r7780rp.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,35 +11,26 @@
  * for more details.
  */
 #include <linux/pci.h>
+#include <linux/io.h>
 #include "pci-sh4.h"
-#include <asm/io.h>
 
-int pci_fixup_pcic(void)
-{
-	pci_write_reg(0x000043ff, SH4_PCIINTM);
-	pci_write_reg(0x0000380f, SH4_PCIAINTM);
-
-	pci_write_reg(0xfbb00047, SH7780_PCICMD);
-	pci_write_reg(0x00000000, SH7780_PCIIBAR);
-
-	pci_write_reg(0x00011912, SH7780_PCISVID);
-	pci_write_reg(0x08000000, SH7780_PCICSCR0);
-	pci_write_reg(0x0000001b, SH7780_PCICSAR0);
-	pci_write_reg(0xfd000000, SH7780_PCICSCR1);
-	pci_write_reg(0x0000000f, SH7780_PCICSAR1);
-
-	pci_write_reg(0xfd000000, SH7780_PCIMBR0);
-	pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
+static char irq_tab[] __initdata = {
+	65, 66, 67, 68,
+};
 
-#ifdef CONFIG_32BIT
-	pci_write_reg(0xc0000000, SH7780_PCIMBR2);
-	pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
-#endif
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	return irq_tab[slot];
+}
 
-	/* Set IOBR for windows containing area specified in pci.h */
-	pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
-		      SH7780_PCIIOBR);
-	pci_write_reg(((SH7780_PCI_IO_SIZE-1) & (7<<18)), SH7780_PCIIOBMR);
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+	pci_write_reg(chan, 0x000043ff, SH4_PCIINTM);
+	pci_write_reg(chan, 0x00000000, SH7780_PCIIBAR);
+	pci_write_reg(chan, 0x08000000, SH7780_PCICSCR0);
+	pci_write_reg(chan, 0x0000001b, SH7780_PCICSAR0);
+	pci_write_reg(chan, 0xfd000000, SH7780_PCICSCR1);
+	pci_write_reg(chan, 0x0000000f, SH7780_PCICSAR1);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-rts7751r2d.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-rts7751r2d.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-rts7751r2d.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-rts7751r2d.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,43 +1,67 @@
 /*
  * arch/sh/drivers/pci/fixups-rts7751r2d.c
  *
- * RTS7751R2D PCI fixups
+ * RTS7751R2D / LBOXRE2 PCI fixups
  *
  * Copyright (C) 2003  Lineo uSolutions, Inc.
  * Copyright (C) 2004  Paul Mundt
+ * Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * 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/pci.h>
+#include <mach/lboxre2.h>
+#include <mach/r2d.h>
 #include "pci-sh4.h"
+#include <asm/machtypes.h>
 
 #define PCIMCR_MRSET_OFF	0xBFFFFFFF
 #define PCIMCR_RFSH_OFF		0xFFFFFFFB
 
-int pci_fixup_pcic(void)
+static u8 rts7751r2d_irq_tab[] __initdata = {
+	IRQ_PCI_INTA,
+	IRQ_PCI_INTB,
+	IRQ_PCI_INTC,
+	IRQ_PCI_INTD,
+};
+
+static char lboxre2_irq_tab[] __initdata = {
+	IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	if (mach_is_lboxre2())
+		return lboxre2_irq_tab[slot];
+	else
+		return rts7751r2d_irq_tab[slot];
+}
+
+int pci_fixup_pcic(struct pci_channel *chan)
 {
 	unsigned long bcr1, mcr;
 
 	bcr1 = ctrl_inl(SH7751_BCR1);
 	bcr1 |= 0x40080000;	/* Enable Bit 19 BREQEN, set PCIC to slave */
-	pci_write_reg(bcr1, SH4_PCIBCR1);
+	pci_write_reg(chan, bcr1, SH4_PCIBCR1);
 
 	/* Enable all interrupts, so we known what to fix */
-	pci_write_reg(0x0000c3ff, SH4_PCIINTM);
-	pci_write_reg(0x0000380f, SH4_PCIAINTM);
+	pci_write_reg(chan, 0x0000c3ff, SH4_PCIINTM);
+	pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
 
-	pci_write_reg(0xfb900047, SH7751_PCICONF1);
-	pci_write_reg(0xab000001, SH7751_PCICONF4);
+	pci_write_reg(chan, 0xfb900047, SH7751_PCICONF1);
+	pci_write_reg(chan, 0xab000001, SH7751_PCICONF4);
 
 	mcr = ctrl_inl(SH7751_MCR);
 	mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
-	pci_write_reg(mcr, SH4_PCIMCR);
+	pci_write_reg(chan, mcr, SH4_PCIMCR);
 
-	pci_write_reg(0x0c000000, SH7751_PCICONF5);
-	pci_write_reg(0xd0000000, SH7751_PCICONF6);
-	pci_write_reg(0x0c000000, SH4_PCILAR0);
-	pci_write_reg(0x00000000, SH4_PCILAR1);
+	pci_write_reg(chan, 0x0c000000, SH7751_PCICONF5);
+	pci_write_reg(chan, 0xd0000000, SH7751_PCICONF6);
+	pci_write_reg(chan, 0x0c000000, SH4_PCILAR0);
+	pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-sdk7780.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-sdk7780.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-sdk7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-sdk7780.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,55 +5,48 @@
  *
  * Copyright (C) 2003  Lineo uSolutions, Inc.
  * Copyright (C) 2004 - 2006  Paul Mundt
+ * Copyright (C) 2006  Nobuhiro Iwamatsu
  *
  * 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/pci.h>
+#include <linux/io.h>
 #include "pci-sh4.h"
-#include <asm/io.h>
 
-int pci_fixup_pcic(void)
-{
-	ctrl_outl(0x00000001, SH7780_PCI_VCR2);
+/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
+static char sdk7780_irq_tab[4][16] __initdata = {
+	/* INTA */
+	{ 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+	/* INTB */
+	{ 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+	/* INTC */
+	{ 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+	/* INTD */
+	{ 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+};
 
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       return sdk7780_irq_tab[pin-1][slot];
+}
+int pci_fixup_pcic(struct pci_channel *chan)
+{
 	/* Enable all interrupts, so we know what to fix */
-	pci_write_reg(0x0000C3FF, SH7780_PCIIMR);
-	pci_write_reg(0x0000380F, SH7780_PCIAINTM);
+	pci_write_reg(chan, 0x0000C3FF, SH7780_PCIIMR);
 
 	/* Set up standard PCI config registers */
-	pci_write_reg(0xFB00, SH7780_PCISTATUS);
-	pci_write_reg(0x0047, SH7780_PCICMD);
-	pci_write_reg(0x00, SH7780_PCIPIF);
-	pci_write_reg(0x00, SH7780_PCISUB);
-	pci_write_reg(0x06, SH7780_PCIBCC);
-	pci_write_reg(0x1912, SH7780_PCISVID);
-	pci_write_reg(0x0001, SH7780_PCISID);
-
-	pci_write_reg(0x08000000, SH7780_PCIMBAR0);	/* PCI */
-	pci_write_reg(0x08000000, SH7780_PCILAR0);	/* SHwy */
-	pci_write_reg(0x07F00001, SH7780_PCILSR);	/* size 128M w/ MBAR */
-
-	pci_write_reg(0x00000000, SH7780_PCIMBAR1);
-	pci_write_reg(0x00000000, SH7780_PCILAR1);
-	pci_write_reg(0x00000000, SH7780_PCILSR1);
-
-	pci_write_reg(0xAB000801, SH7780_PCIIBAR);
-
-	/*
-	 * Set the MBR so PCI address is one-to-one with window,
-	 * meaning all calls go straight through... use ifdef to
-	 * catch erroneous assumption.
-	 */
-	pci_write_reg(0xFD000000 , SH7780_PCIMBR0);
-	pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0);	/* 16M */
+	pci_write_reg(chan, 0x08000000, SH7780_PCIMBAR0);	/* PCI */
+	pci_write_reg(chan, 0x08000000, SH4_PCILAR0);	/* SHwy */
+	pci_write_reg(chan, 0x07F00001, SH4_PCILSR0);	/* size 128M w/ MBAR */
 
-	/* Set IOBR for window containing area specified in pci.h */
-	pci_write_reg(PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1), SH7780_PCIIOBR);
-	pci_write_reg((SH7780_PCI_IO_SIZE-1) & (7 << 18), SH7780_PCIIOBMR);
+	pci_write_reg(chan, 0x00000000, SH7780_PCIMBAR1);
+	pci_write_reg(chan, 0x00000000, SH4_PCILAR1);
+	pci_write_reg(chan, 0x00000000, SH4_PCILSR1);
 
-	pci_write_reg(0xA5000C01, SH7780_PCICR);
+	pci_write_reg(chan, 0xAB000801, SH7780_PCIIBAR);
+	pci_write_reg(chan, 0xA5000C01, SH4_PCICR);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-se7751.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-se7751.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-se7751.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-se7751.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,111 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+        switch (slot) {
+        case 0: return 13;
+        case 1: return 13;	/* AMD Ethernet controller */
+        case 2: return -1;
+        case 3: return -1;
+        case 4: return -1;
+        default:
+                printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+                return -1;
+        }
+}
+
+#define PCIMCR_MRSET_OFF	0xBFFFFFFF
+#define PCIMCR_RFSH_OFF		0xFFFFFFFB
+
+/*
+ * Only long word accesses of the PCIC's internal local registers and the
+ * configuration registers from the CPU is supported.
+ */
+#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
+#define PCIC_READ(x) readl(PCI_REG(x))
+
+/*
+ * Description:  This function sets up and initializes the pcic, sets
+ * up the BARS, maps the DRAM into the address space etc, etc.
+ */
+int pci_fixup_pcic(struct pci_channel *chan)
+{
+	unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
+	unsigned short bcr2;
+
+	/*
+	* Initialize the slave bus controller on the pcic.  The values used
+	* here should not be hardcoded, but they should be taken from the bsc
+	* on the processor, to make this function as generic as possible.
+	* (i.e. Another sbc may usr different SDRAM timing settings -- in order
+	* for the pcic to work, its settings need to be exactly the same.)
+	*/
+	bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
+	bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
+	wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
+	wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
+	wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
+	mcr = (*(volatile unsigned long*)(SH7751_MCR));
+
+	bcr1 = bcr1 | 0x00080000;  /* Enable Bit 19, BREQEN */
+	(*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;
+
+	bcr1 = bcr1 | 0x40080000;  /* Enable Bit 19 BREQEN, set PCIC to slave */
+	PCIC_WRITE(SH7751_PCIBCR1, bcr1);	 /* PCIC BCR1 */
+	PCIC_WRITE(SH7751_PCIBCR2, bcr2);     /* PCIC BCR2 */
+	PCIC_WRITE(SH7751_PCIWCR1, wcr1);     /* PCIC WCR1 */
+	PCIC_WRITE(SH7751_PCIWCR2, wcr2);     /* PCIC WCR2 */
+	PCIC_WRITE(SH7751_PCIWCR3, wcr3);     /* PCIC WCR3 */
+	mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+	PCIC_WRITE(SH7751_PCIMCR, mcr);      /* PCIC MCR */
+
+
+	/* Enable all interrupts, so we know what to fix */
+	PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
+	PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f);
+
+	/* Set up standard PCI config registers */
+	PCIC_WRITE(SH7751_PCICONF1,	0xF39000C7); /* Bus Master, Mem & I/O access */
+	PCIC_WRITE(SH7751_PCICONF2,	0x00000000); /* PCI Class code & Revision ID */
+	PCIC_WRITE(SH7751_PCICONF4,	0xab000001); /* PCI I/O address (local regs) */
+	PCIC_WRITE(SH7751_PCICONF5,	0x0c000000); /* PCI MEM address (local RAM)  */
+	PCIC_WRITE(SH7751_PCICONF6,	0xd0000000); /* PCI MEM address (unused)     */
+	PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */
+	PCIC_WRITE(SH7751_PCILSR0, 0x03f00000);   /* MEM (full 64M exposed)       */
+	PCIC_WRITE(SH7751_PCILSR1, 0x00000000);   /* MEM (unused)                 */
+	PCIC_WRITE(SH7751_PCILAR0, 0x0c000000);   /* MEM (direct map from PCI)    */
+	PCIC_WRITE(SH7751_PCILAR1, 0x00000000);   /* MEM (unused)                 */
+
+	/* Now turn it on... */
+	PCIC_WRITE(SH7751_PCICR, 0xa5000001);
+
+	/*
+	* Set PCIMBR and PCIIOBR here, assuming a single window
+	* (16M MEM, 256K IO) is enough.  If a larger space is
+	* needed, the readx/writex and inx/outx functions will
+	* have to do more (e.g. setting registers for each call).
+	*/
+
+	/*
+	* Set the MBR so PCI address is one-to-one with window,
+	* meaning all calls go straight through... use BUG_ON to
+	* catch erroneous assumption.
+	*/
+	BUG_ON(chan->mem_resource->start != SH7751_PCI_MEMORY_BASE);
+
+	PCIC_WRITE(SH7751_PCIMBR, chan->mem_resource->start);
+
+	/* Set IOBR for window containing area specified in pci.h */
+	PCIC_WRITE(SH7751_PCIIOBR, (chan->io_resource->start & SH7751_PCIIOBR_MASK));
+
+	/* All done, may as well say so... */
+	printk("SH7751 PCI: Finished initialization of the PCI controller\n");
+
+	return 1;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-se7780.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-se7780.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-se7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-se7780.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-se7780.c
- *
- * HITACHI UL Solution Engine 7780  PCI fixups
- *
- * Copyright (C) 2003  Lineo uSolutions, Inc.
- * Copyright (C) 2004 - 2006  Paul Mundt
- * Copyright (C) 2006  Nobuhiro Iwamatsu
- *
- * 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/pci.h>
-#include "pci-sh4.h"
-#include <asm/io.h>
-
-int pci_fixup_pcic(void)
-{
-	ctrl_outl(0x00000001, SH7780_PCI_VCR2);
-
-	/* Enable all interrupts, so we know what to fix */
-	pci_write_reg(0x0000C3FF, SH7780_PCIIMR);
-	pci_write_reg(0x0000380F, SH7780_PCIAINTM);
-
-	/* Set up standard PCI config registers */
-	ctrl_outw(0xFB00, PCI_REG(SH7780_PCISTATUS));
-	ctrl_outw(0x0047, PCI_REG(SH7780_PCICMD));
-	ctrl_outb(  0x00, PCI_REG(SH7780_PCIPIF));
-	ctrl_outb(  0x00, PCI_REG(SH7780_PCISUB));
-	ctrl_outb(  0x06, PCI_REG(SH7780_PCIBCC));
-	ctrl_outw(0x1912, PCI_REG(SH7780_PCISVID));
-	ctrl_outw(0x0001, PCI_REG(SH7780_PCISID));
-
-	pci_write_reg(0x08000000, SH7780_PCIMBAR0);     /* PCI */
-	pci_write_reg(0x08000000, SH7780_PCILAR0);     /* SHwy */
-	pci_write_reg(0x07F00001, SH7780_PCILSR);      /* size 128M w/ MBAR */
-
-	pci_write_reg(0x00000000, SH7780_PCIMBAR1);
-	pci_write_reg(0x00000000, SH7780_PCILAR1);
-	pci_write_reg(0x00000000, SH7780_PCILSR1);
-
-	pci_write_reg(0xAB000801, SH7780_PCIIBAR);
-
-	/*
-	 * Set the MBR so PCI address is one-to-one with window,
-	 * meaning all calls go straight through... use ifdef to
-	 * catch erroneous assumption.
-	 */
-	pci_write_reg(0xFD000000 , SH7780_PCIMBR0);
-	pci_write_reg(0x00FC0000 , SH7780_PCIMBMR0);    /* 16M */
-
-	/* Set IOBR for window containing area specified in pci.h */
-	pci_write_reg(PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE-1), SH7780_PCIIOBR);
-	pci_write_reg((SH7780_PCI_IO_SIZE-1) & (7 << 18), SH7780_PCIIOBMR);
-
-	pci_write_reg(0xA5000C01, SH7780_PCICR);
-
-	return 0;
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-sh7785lcr.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-sh7785lcr.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-sh7785lcr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-sh7785lcr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/*
- * arch/sh/drivers/pci/fixups-sh7785lcr.c
- *
- * R0P7785LC0011RL PCI fixups
- * Copyright (C) 2008  Yoshihiro Shimoda
- *
- * Based on arch/sh/drivers/pci/fixups-r7780rp.c
- * Copyright (C) 2003  Lineo uSolutions, Inc.
- * Copyright (C) 2004 - 2006  Paul Mundt
- *
- * 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/pci.h>
-#include "pci-sh4.h"
-
-int pci_fixup_pcic(void)
-{
-	pci_write_reg(0x000043ff, SH4_PCIINTM);
-	pci_write_reg(0x0000380f, SH4_PCIAINTM);
-
-	pci_write_reg(0xfbb00047, SH7780_PCICMD);
-	pci_write_reg(0x00000000, SH7780_PCIIBAR);
-
-	pci_write_reg(0x00011912, SH7780_PCISVID);
-	pci_write_reg(0x08000000, SH7780_PCICSCR0);
-	pci_write_reg(0x0000001b, SH7780_PCICSAR0);
-	pci_write_reg(0xfd000000, SH7780_PCICSCR1);
-	pci_write_reg(0x0000000f, SH7780_PCICSAR1);
-
-	pci_write_reg(0xfd000000, SH7780_PCIMBR0);
-	pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
-
-#ifdef CONFIG_32BIT
-	pci_write_reg(0xc0000000, SH7780_PCIMBR2);
-	pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
-#endif
-
-	/* Set IOBR for windows containing area specified in pci.h */
-	pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
-		      SH7780_PCIIOBR);
-	pci_write_reg(((SH7780_PCI_IO_SIZE - 1) & (7 << 18)), SH7780_PCIIOBMR);
-
-	return 0;
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-snapgear.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-snapgear.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-snapgear.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-snapgear.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * arch/sh/drivers/pci/ops-snapgear.c
+ *
+ * Author:  David McCullough <davidm@snapgear.com>
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the SnapGear boards
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	int irq = -1;
+
+	switch (slot) {
+	case 8:  /* the PCI bridge */ break;
+	case 11: irq = 8;  break; /* USB    */
+	case 12: irq = 11; break; /* PCMCIA */
+	case 13: irq = 5;  break; /* eth0   */
+	case 14: irq = 8;  break; /* eth1   */
+	case 15: irq = 11; break; /* safenet (unused) */
+	}
+
+	printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
+	       slot, pin - 1 + 'A', irq);
+
+	return irq;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-titan.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-titan.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/fixups-titan.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/fixups-titan.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * arch/sh/drivers/pci/ops-titan.c
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Modified from ops-snapgear.c written by  David McCullough
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the Titan boards
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <mach/titan.h>
+#include "pci-sh4.h"
+
+static char titan_irq_tab[] __initdata = {
+	TITAN_IRQ_WAN,
+	TITAN_IRQ_LAN,
+	TITAN_IRQ_MPCIA,
+	TITAN_IRQ_MPCIB,
+	TITAN_IRQ_USB,
+};
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+	int irq = titan_irq_tab[slot];
+
+	printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
+		slot, pin - 1 + 'A', irq);
+
+	return irq;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/Kconfig linux-libre-2.6.31-gnu/arch/sh/drivers/pci/Kconfig
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -17,21 +17,3 @@
 	  code will not have to flush the CPU's caches. If you have a PCI host
 	  bridge integrated with your SH CPU, refer carefully to the chip specs
 	  to see if you can say 'N' here. Otherwise, leave it as 'Y'.
-
-# This is also board-specific
-config PCI_AUTO
-	bool
-	depends on PCI
-	default y
-
-config PCI_AUTO_UPDATE_RESOURCES
-	bool
-	depends on PCI_AUTO
-	default y if !SH_DREAMCAST
-	help
-	  Selecting this option will cause the PCI auto code to leave your
-	  BAR values alone. Otherwise they will be updated automatically. If
-	  for some reason, you have a board that simply refuses to work
-	  with its resources updated beyond what they are when the device
-	  is powered up, set this to N. Everyone else will want this as Y.
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/Makefile linux-libre-2.6.31-gnu/arch/sh/drivers/pci/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,28 @@
 #
 # Makefile for the PCI specific kernel interface routines under Linux.
 #
-
 obj-y					+= pci.o
-obj-$(CONFIG_PCI_AUTO)			+= pci-auto.o
 
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= pci-sh7751.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751R)	+= pci-sh7751.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7763)	+= pci-sh7780.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= pci-sh7780.o ops-sh4.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)	+= pci-sh7780.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7786)	+= ops-sh7786.o
 obj-$(CONFIG_CPU_SH5)			+= pci-sh5.o ops-sh5.o
 
-obj-$(CONFIG_SH_DREAMCAST)		+= ops-dreamcast.o fixups-dreamcast.o
-obj-$(CONFIG_SH_SECUREEDGE5410)		+= ops-snapgear.o
-obj-$(CONFIG_SH_RTS7751R2D)		+= ops-rts7751r2d.o fixups-rts7751r2d.o
-obj-$(CONFIG_SH_SH03)			+= ops-sh03.o fixups-sh03.o
-obj-$(CONFIG_SH_HIGHLANDER)		+= ops-r7780rp.o fixups-r7780rp.o
-obj-$(CONFIG_SH_SDK7780)		+= ops-sdk7780.o fixups-sdk7780.o
-obj-$(CONFIG_SH_TITAN)			+= ops-titan.o
-obj-$(CONFIG_SH_LANDISK)		+= ops-landisk.o
-obj-$(CONFIG_SH_LBOX_RE2)		+= ops-lboxre2.o fixups-lboxre2.o
-obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)	+= ops-se7780.o fixups-se7780.o
-obj-$(CONFIG_SH_CAYMAN)			+= ops-cayman.o
-obj-$(CONFIG_SH_SH7785LCR)		+= ops-sh7785lcr.o fixups-sh7785lcr.o
+obj-$(CONFIG_SH_DREAMCAST)		+= ops-dreamcast.o fixups-dreamcast.o \
+					   pci-dreamcast.o
+obj-$(CONFIG_SH_SECUREEDGE5410)		+= fixups-snapgear.o
+obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)	+= fixups-se7751.o
+obj-$(CONFIG_SH_RTS7751R2D)		+= fixups-rts7751r2d.o
+obj-$(CONFIG_SH_SH03)			+= fixups-sh03.o
+obj-$(CONFIG_SH_HIGHLANDER)		+= fixups-r7780rp.o
+obj-$(CONFIG_SH_SH7785LCR)		+= fixups-r7780rp.o
+obj-$(CONFIG_SH_SDK7780)		+= fixups-sdk7780.o
+obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)	+= fixups-sdk7780.o
+obj-$(CONFIG_SH_TITAN)			+= fixups-titan.o
+obj-$(CONFIG_SH_LANDISK)		+= fixups-landisk.o
+obj-$(CONFIG_SH_LBOX_RE2)		+= fixups-rts7751r2d.o
+obj-$(CONFIG_SH_CAYMAN)			+= fixups-cayman.o
+obj-$(CONFIG_SH_URQUELL)		+= pcie-sh7786.o
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-cayman.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-cayman.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-cayman.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-cayman.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,89 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <cpu/irq.h>
-#include "pci-sh5.h"
-
-int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int result = -1;
-
-	/* The complication here is that the PCI IRQ lines from the Cayman's 2
-	   5V slots get into the CPU via a different path from the IRQ lines
-	   from the 3 3.3V slots.  Thus, we have to detect whether the card's
-	   interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
-	   at the point where we cross from 5V to 3.3V is not the normal case.
-
-	   The added complication is that we don't know that the 5V slots are
-	   always bus 2, because a card containing a PCI-PCI bridge may be
-	   plugged into a 3.3V slot, and this changes the bus numbering.
-
-	   Also, the Cayman has an intermediate PCI bus that goes a custom
-	   expansion board header (and to the secondary bridge).  This bus has
-	   never been used in practice.
-
-	   The 1ary onboard PCI-PCI bridge is device 3 on bus 0
-	   The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of
-	   the 1ary bridge.
-	   */
-
-	struct slot_pin {
-		int slot;
-		int pin;
-	} path[4];
-	int i=0;
-
-	while (dev->bus->number > 0) {
-
-		slot = path[i].slot = PCI_SLOT(dev->devfn);
-		pin = path[i].pin = pci_swizzle_interrupt_pin(dev, pin);
-		dev = dev->bus->self;
-		i++;
-		if (i > 3) panic("PCI path to root bus too long!\n");
-	}
-
-	slot = PCI_SLOT(dev->devfn);
-	/* This is the slot on bus 0 through which the device is eventually
-	   reachable. */
-
-	/* Now work back up. */
-	if ((slot < 3) || (i == 0)) {
-		/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
-		   swizzle now. */
-		result = IRQ_INTA + pci_swizzle_interrupt_pin(dev, pin) - 1;
-	} else {
-		i--;
-		slot = path[i].slot;
-		pin  = path[i].pin;
-		if (slot > 0) {
-			panic("PCI expansion bus device found - not handled!\n");
-		} else {
-			if (i > 0) {
-				/* 5V slots */
-				i--;
-				slot = path[i].slot;
-				pin  = path[i].pin;
-				/* 'pin' was swizzled earlier wrt slot, don't do it again. */
-				result = IRQ_P2INTA + (pin - 1);
-			} else {
-				/* IRQ for 2ary PCI-PCI bridge : unused */
-				result = -1;
-			}
-		}
-	}
-
-	return result;
-}
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh5_pci_ops, NULL, NULL, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-int __init pcibios_init_platform(void)
-{
-	return sh5pci_init(__pa(memory_start),
-			   __pa(memory_end) - __pa(memory_start));
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-dreamcast.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-dreamcast.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-dreamcast.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-dreamcast.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,15 +1,9 @@
 /*
- * arch/sh/drivers/pci/ops-dreamcast.c
- *
  * PCI operations for the Sega Dreamcast
  *
  * Copyright (C) 2001, 2002  M. R. Brown
  * Copyright (C) 2002, 2003  Paul Mundt
  *
- * This file originally bore the message (with enclosed-$):
- *	Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
- *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
- *
  * 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.
@@ -23,34 +17,9 @@
 #include <linux/irq.h>
 #include <linux/pci.h>
 #include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
+#include <linux/io.h>
 #include <mach/pci.h>
 
-static struct resource gapspci_io_resource = {
-	.name	= "GAPSPCI IO",
-	.start	= GAPSPCI_BBA_CONFIG,
-	.end	= GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
-	.flags	= IORESOURCE_IO,
-};
-
-static struct resource gapspci_mem_resource = {
-	.name	= "GAPSPCI mem",
-	.start	= GAPSPCI_DMA_BASE,
-	.end	= GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct pci_ops gapspci_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &gapspci_pci_ops, &gapspci_io_resource,
-	  &gapspci_mem_resource, 0, 1 },
-	{ 0, }
-};
-EXPORT_SYMBOL(board_pci_channels);
-
 /*
  * The !gapspci_config_access case really shouldn't happen, ever, unless
  * someone implicitly messes around with the last devfn value.. otherwise we
@@ -85,10 +54,10 @@
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	switch (size) {
-		case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
-		case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
-		case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
-	}	
+	case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
+	case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
+	case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
+	}
 
         return PCIBIOS_SUCCESSFUL;
 }
@@ -99,72 +68,15 @@
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	switch (size) {
-		case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
-		case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
-		case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
+	case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
+	case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
+	case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
 	}
 
         return PCIBIOS_SUCCESSFUL;
 }
 
-static struct pci_ops gapspci_pci_ops = {
+struct pci_ops gapspci_pci_ops = {
 	.read	= gapspci_read,
 	.write	= gapspci_write,
 };
-
-/*
- * gapspci init
- */
-
-int __init gapspci_init(void)
-{
-	char idbuf[16];
-	int i;
-
-	/*
-	 * FIXME: All of this wants documenting to some degree,
-	 * even some basic register definitions would be nice.
-	 *
-	 * I haven't seen anything this ugly since.. maple.
-	 */
-
-	for (i=0; i<16; i++)
-		idbuf[i] = inb(GAPSPCI_REGS+i);
-
-	if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
-		return -ENODEV;
-
-	outl(0x5a14a501, GAPSPCI_REGS+0x18);
-
-	for (i=0; i<1000000; i++)
-		;
-
-	if (inl(GAPSPCI_REGS+0x18) != 1)
-		return -EINVAL;
-
-	outl(0x01000000, GAPSPCI_REGS+0x20);
-	outl(0x01000000, GAPSPCI_REGS+0x24);
-
-	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
-	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
-
-	outl(1, GAPSPCI_REGS+0x14);
-	outl(1, GAPSPCI_REGS+0x34);
-
-	/* Setting Broadband Adapter */
-	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
-	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
-	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
-	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
-	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
-	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
-	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
-
-	return 0;
-}
-
-/* Haven't done anything here as yet */
-char * __devinit pcibios_setup(char *str)
-{
-	return str;
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-landisk.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-landisk.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-landisk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-landisk.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-/*
- * arch/sh/drivers/pci/ops-landisk.c
- *
- * PCI initialization for the I-O DATA Device, Inc. LANDISK board
- *
- * Copyright (C) 2006 kogiidena
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include "pci-sh4.h"
-
-static struct resource sh7751_io_resource = {
-	.name = "SH7751 IO",
-	.start = SH7751_PCI_IO_BASE,
-	.end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
-	.flags = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
-	.name = "SH7751 mem",
-	.start = SH7751_PCI_MEMORY_BASE,
-	.end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
-	.flags = IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
-	{&sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0x3ff},
-	{NULL, NULL, NULL, 0, 0},
-};
-
-static struct sh4_pci_address_map sh7751_pci_map = {
-	.window0 = {
-		.base	= SH7751_CS3_BASE_ADDR,
-		.size	= (64 << 20),	/* 64MB */
-	},
-
-	.flags = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	return sh7751_pcic_init(&sh7751_pci_map);
-}
-
-int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	/*
-	 * slot0: pin1-4 = irq5,6,7,8
-	 * slot1: pin1-4 = irq6,7,8,5
-	 * slot2: pin1-4 = irq7,8,5,6
-	 * slot3: pin1-4 = irq8,5,6,7
-	 */
-	int irq = ((slot + pin - 1) & 0x3) + 5;
-
-	if ((slot | (pin - 1)) > 0x3) {
-		printk("PCI: Bad IRQ mapping request for slot %d pin %c\n",
-		       slot, pin - 1 + 'A');
-		return -1;
-	}
-	return irq;
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-lboxre2.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-lboxre2.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-lboxre2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-lboxre2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-lboxre2.c
- *
- * Copyright (C) 2007 Nobuhiro Iwamatsu
- *
- * PCI initialization for the NTT COMWARE L-BOX RE2
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <mach/lboxre2.h>
-#include "pci-sh4.h"
-
-static char lboxre2_irq_tab[] __initdata = {
-	IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	return lboxre2_irq_tab[slot];
-}
-
-static struct resource sh7751_io_resource = {
-	.name	= "SH7751_IO",
-	.start	= SH7751_PCI_IO_BASE ,
-	.end	= SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
-	.name	= "SH7751_mem",
-	.start	= SH7751_PCI_MEMORY_BASE,
-	.end	= SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
-	.window0	= {
-		.base	= SH7751_CS3_BASE_ADDR,
-		.size	= 0x04000000,
-	},
-	.window1	= {
-		.base	= 0x00000000,	/* Unused */
-		.size	= 0x00000000,	/* Unused */
-	},
-	.flags	= SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	return sh7751_pcic_init(&sh7751_pci_map);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-r7780rp.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-r7780rp.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-r7780rp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-r7780rp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * Author:  Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas SH7780 Highlander R7780RP-1 board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <mach/highlander.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-static char irq_tab[] __initdata = {
-	65, 66, 67, 68,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	return irq_tab[slot];
-}
-
-static struct resource sh7780_io_resource = {
-	.name	= "SH7780_IO",
-	.start	= SH7780_PCI_IO_BASE,
-	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sh7780_mem_resource = {
-	.name	= "SH7780_mem",
-	.start	= SH7780_PCI_MEMORY_BASE,
-	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7780_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7780_pci_map = {
-	.window0	= {
-		.base	= SH7780_CS2_BASE_ADDR,
-		.size	= 0x04000000,
-	},
-
-	.window1	= {
-		.base	= SH7780_CS3_BASE_ADDR,
-		.size	= 0x04000000,
-	},
-
-	.flags	= SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	return sh7780_pcic_init(&sh7780_pci_map);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-rts7751r2d.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-rts7751r2d.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-rts7751r2d.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-rts7751r2d.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-rts7751r2d.c
- *
- * Author:  Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas SH7751R RTS7751R2D board
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <mach/r2d.h>
-#include "pci-sh4.h"
-
-static u8 rts7751r2d_irq_tab[] __initdata = {
-	IRQ_PCI_INTA,
-	IRQ_PCI_INTB,
-	IRQ_PCI_INTC,
-	IRQ_PCI_INTD,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	return rts7751r2d_irq_tab[slot];
-}
-
-static struct resource sh7751_io_resource = {
-	.name	= "SH7751_IO",
-	.start	= 0x4000,
-	.end	= SH7751_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
-	.name	= "SH7751_mem",
-	.start	= SH7751_PCI_MEMORY_BASE,
-	.end	= SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops sh7751_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
-	.window0	= {
-		.base	= SH7751_CS3_BASE_ADDR,
-		.size	= 0x04000000,
-	},
-
-	.window1	= {
-		.base	= 0x00000000,	/* Unused */
-		.size	= 0x00000000,	/* Unused */
-	},
-
-	.flags	= SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	__set_io_port_base(SH7751_PCI_IO_BASE);
-	return sh7751_pcic_init(&sh7751_pci_map);
-}
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sdk7780.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sdk7780.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sdk7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sdk7780.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,73 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-sdk7780.c
- *
- * Copyright (C) 2006  Nobuhiro Iwamatsu
- *
- * PCI initialization for the SDK7780SE03
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <mach/sdk7780.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
-static char sdk7780_irq_tab[4][16] __initdata = {
-	/* INTA */
-	{ 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-	/* INTB */
-	{ 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-	/* INTC */
-	{ 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-	/* INTD */
-	{ 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-       return sdk7780_irq_tab[pin-1][slot];
-}
-
-static struct resource sdk7780_io_resource = {
-	.name	= "SH7780_IO",
-	.start	= SH7780_PCI_IO_BASE,
-	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sdk7780_mem_resource = {
-	.name	= "SH7780_mem",
-	.start	= SH7780_PCI_MEMORY_BASE,
-	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sdk7780_io_resource, &sdk7780_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sdk7780_pci_map = {
-	.window0	= {
-		.base	= SH7780_CS2_BASE_ADDR,
-		.size	= 0x04000000,
-	},
-	.window1	= {
-		.base	= SH7780_CS3_BASE_ADDR,
-		.size	= 0x04000000,
-	},
-	.flags	= SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	printk(KERN_INFO "SH7780 PCI: Finished initializing PCI controller\n");
-	return sh7780_pcic_init(&sdk7780_pci_map);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-se7780.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-se7780.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-se7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-se7780.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-se7780.c
- *
- * Copyright (C) 2006  Nobuhiro Iwamatsu
- *
- * PCI initialization for the Hitachi UL Solution Engine 7780SE03
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <mach-se/mach/se7780.h>
-#include <asm/io.h>
-#include "pci-sh4.h"
-
-/*
- * IDSEL = AD16  PCI slot
- * IDSEL = AD17  PCI slot
- * IDSEL = AD18  Serial ATA Controller (Silicon Image SiL3512A)
- * IDSEL = AD19  USB Host Controller (NEC uPD7210100A)
- */
-
-/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
-static char se7780_irq_tab[4][16] __initdata = {
-	/* INTA */
-	{ 65, 68, 67, 68, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-	/* INTB */
-	{ 66, 65, -1, 65, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-	/* INTC */
-	{ 67, 66, -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-	/* INTD */
-	{ 68, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-       return se7780_irq_tab[pin-1][slot];
-}
-
-static struct resource se7780_io_resource = {
-	.name	= "SH7780_IO",
-	.start	= SH7780_PCI_IO_BASE,
-	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource se7780_mem_resource = {
-	.name	= "SH7780_mem",
-	.start	= SH7780_PCI_MEMORY_BASE,
-	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-extern struct pci_ops se7780_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &se7780_io_resource, &se7780_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map se7780_pci_map = {
-	.window0	= {
-		.base	= SH7780_CS2_BASE_ADDR,
-		.size	= 0x04000000,
-	},
-	.flags  = SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	printk("SH7780 PCI: Finished initialization of the PCI controller\n");
-
-	/*
-	 * FPGA PCISEL register initialize
-	 *
-	 *  CPU  || SLOT1 | SLOT2 | S-ATA | USB
-	 *  -------------------------------------
-	 *  INTA || INTA  | INTD  |  --   | INTB
-	 *  -------------------------------------
-	 *  INTB || INTB  | INTA  |  --   | INTC
-	 *  -------------------------------------
-	 *  INTC || INTC  | INTB  | INTA  |  --
-	 *  -------------------------------------
-	 *  INTD || INTD  | INTC  |  --   | INTA
-	 *  -------------------------------------
-	 */
-	ctrl_outw(0x0013, FPGA_PCI_INTSEL1);
-	ctrl_outw(0xE402, FPGA_PCI_INTSEL2);
-
-	return sh7780_pcic_init(&se7780_pci_map);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh03.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh03.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh03.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh03.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/*
- * linux/arch/sh/drivers/pci/ops-sh03.c
- *
- * PCI initialization for the Interface CTP/PCI-SH03 board
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include "pci-sh7751.h"
-
-/*
- * Description:  This function sets up and initializes the pcic, sets
- * up the BARS, maps the DRAM into the address space etc, etc.
- */
-int __init pcibios_init_platform(void)
-{
-	__set_io_port_base(SH7751_PCI_IO_BASE);
-	return 1;
-}
-
-static struct resource sh7751_io_resource = {
-	.name   = "SH03 IO",
-	.start  = SH7751_PCI_IO_BASE,
-	.end    = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
-	.flags  = IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
-	.name   = "SH03 mem",
-	.start  = SH7751_PCI_MEMORY_BASE,
-	.end    = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
-	.flags  = IORESOURCE_MEM
-};
-
-extern struct pci_ops sh4_pci_ops;
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh4.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh4.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh4.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,22 +1,22 @@
 /*
  * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
  *
- * Copyright (C) 2002 - 2006  Paul Mundt
+ * Copyright (C) 2002 - 2009  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License v2. See the file "COPYING" in the main directory of this archive
  * for more details.
  */
 #include <linux/pci.h>
+#include <linux/io.h>
 #include <asm/addrspace.h>
-#include <asm/io.h>
 #include "pci-sh4.h"
 
 /*
  * Direct access to PCI hardware...
  */
 #define CONFIG_CMD(bus, devfn, where) \
-	P1SEGADDR((bus->number << 16) | (devfn << 8) | (where & ~3))
+	(P1SEG | (bus->number << 16) | (devfn << 8) | (where & ~3))
 
 static DEFINE_SPINLOCK(sh4_pci_lock);
 
@@ -26,6 +26,7 @@
 static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
 			   int where, int size, u32 *val)
 {
+	struct pci_channel *chan = bus->sysdata;
 	unsigned long flags;
 	u32 data;
 
@@ -34,8 +35,8 @@
 	 * so we must do byte alignment by hand
 	 */
 	spin_lock_irqsave(&sh4_pci_lock, flags);
-	pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
-	data = pci_read_reg(SH4_PCIPDR);
+	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+	data = pci_read_reg(chan, SH4_PCIPDR);
 	spin_unlock_irqrestore(&sh4_pci_lock, flags);
 
 	switch (size) {
@@ -63,13 +64,14 @@
 static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
 			 int where, int size, u32 val)
 {
+	struct pci_channel *chan = bus->sysdata;
 	unsigned long flags;
 	int shift;
 	u32 data;
 
 	spin_lock_irqsave(&sh4_pci_lock, flags);
-	pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
-	data = pci_read_reg(SH4_PCIPDR);
+	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+	data = pci_read_reg(chan, SH4_PCIPDR);
 	spin_unlock_irqrestore(&sh4_pci_lock, flags);
 
 	switch (size) {
@@ -90,7 +92,7 @@
 		return PCIBIOS_FUNC_NOT_SUPPORTED;
 	}
 
-	pci_write_reg(data, SH4_PCIPDR);
+	pci_write_reg(chan, data, SH4_PCIPDR);
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -104,66 +106,31 @@
  * Not really related to pci_ops, but it's common and not worth shoving
  * somewhere else for now..
  */
-static unsigned int pci_probe = PCI_PROBE_CONF1;
-
-int __init sh4_pci_check_direct(void)
+int __init sh4_pci_check_direct(struct pci_channel *chan)
 {
 	/*
 	 * Check if configuration works.
 	 */
-	if (pci_probe & PCI_PROBE_CONF1) {
-		unsigned int tmp = pci_read_reg(SH4_PCIPAR);
-
-		pci_write_reg(P1SEG, SH4_PCIPAR);
-
-		if (pci_read_reg(SH4_PCIPAR) == P1SEG) {
-			pci_write_reg(tmp, SH4_PCIPAR);
-			printk(KERN_INFO "PCI: Using configuration type 1\n");
-			request_region(PCI_REG(SH4_PCIPAR), 8, "PCI conf1");
+	unsigned int tmp = pci_read_reg(chan, SH4_PCIPAR);
 
-			return 0;
-		}
+	pci_write_reg(chan, P1SEG, SH4_PCIPAR);
 
-		pci_write_reg(tmp, SH4_PCIPAR);
+	if (pci_read_reg(chan, SH4_PCIPAR) == P1SEG) {
+		pci_write_reg(chan, tmp, SH4_PCIPAR);
+		printk(KERN_INFO "PCI: Using configuration type 1\n");
+		request_region(chan->reg_base + SH4_PCIPAR, 8,
+			       "PCI conf1");
+		return 0;
 	}
 
-	pr_debug("PCI: pci_check_direct failed\n");
-	return -EINVAL;
-}
-
-/* Handle generic fixups */
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
-	int i;
-
-	/*
-	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
-	 */
-	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
-		return;
-	pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
-	for(i = 0; i < 4; i++) {
-		struct resource *r = &d->resource[i];
-
-		if ((r->start & ~0x80) == 0x374) {
-			r->start |= 2;
-			r->end = r->start;
-		}
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+	pci_write_reg(chan, tmp, SH4_PCIPAR);
 
-char * __devinit pcibios_setup(char *str)
-{
-	if (!strcmp(str, "off")) {
-		pci_probe = 0;
-		return NULL;
-	}
+	printk(KERN_ERR "PCI: %s failed\n", __func__);
 
-	return str;
+	return -EINVAL;
 }
 
-int __attribute__((weak)) pci_fixup_pcic(void)
+int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
 {
 	/* Nothing to do. */
 	return 0;
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh5.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh5.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh5.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,31 +22,6 @@
 #include <asm/io.h>
 #include "pci-sh5.h"
 
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
-	int i;
-
-	/*
-	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
-	 */
-	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
-		return;
-	printk("PCI: IDE base address fixup for %s\n", pci_name(d));
-	for(i=0; i<4; i++) {
-		struct resource *r = &d->resource[i];
-		if ((r->start & ~0x80) == 0x374) {
-			r->start |= 2;
-			r->end = r->start;
-		}
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-char * __devinit pcibios_setup(char *str)
-{
-	return str;
-}
-
 static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 			int size, u32 *val)
 {
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh7785lcr.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh7785lcr.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh7785lcr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh7785lcr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/*
- * Author:  Ian DaSilva (idasilva@mvista.com)
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the Renesas R0P7785LC0011RL board
- * Based on arch/sh/drivers/pci/ops-r7780rp.c
- *
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include "pci-sh4.h"
-
-static char irq_tab[] __initdata = {
-	65, 66, 67, 68,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	return irq_tab[slot];
-}
-
-static struct resource sh7785_io_resource = {
-	.name	= "SH7785_IO",
-	.start	= SH7780_PCI_IO_BASE,
-	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sh7785_mem_resource = {
-	.name	= "SH7785_mem",
-	.start	= SH7780_PCI_MEMORY_BASE,
-	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7785_io_resource, &sh7785_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7785_pci_map = {
-	.window0	= {
-#if defined(CONFIG_32BIT)
-		.base	= SH7780_32BIT_DDR_BASE_ADDR,
-		.size	= 0x40000000,
-#else
-		.base	= SH7780_CS0_BASE_ADDR,
-		.size	= 0x20000000,
-#endif
-	},
-
-	.flags	= SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	return sh7780_pcic_init(&sh7785_pci_map);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh7786.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh7786.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-sh7786.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-sh7786.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * Generic SH7786 PCI-Express operations.
+ *
+ *  Copyright (C) 2009  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include "pcie-sh7786.h"
+
+enum {
+	PCI_ACCESS_READ,
+	PCI_ACCESS_WRITE,
+};
+
+static DEFINE_SPINLOCK(sh7786_pcie_lock);
+
+static int sh7786_pcie_config_access(unsigned char access_type,
+		struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
+{
+	struct pci_channel *chan = bus->sysdata;
+	int dev, func;
+
+	dev = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+
+	if (bus->number > 255 || dev > 31 || func > 7)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	if (devfn)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Set the PIO address */
+	pci_write_reg(chan, (bus->number << 24) | (dev << 19) |
+				(func << 16) | (where & ~3), SH4A_PCIEPAR);
+
+	/* Enable the configuration access */
+	pci_write_reg(chan, (1 << 31), SH4A_PCIEPCTLR);
+
+	if (access_type == PCI_ACCESS_READ)
+		*data = pci_read_reg(chan, SH4A_PCIEPDR);
+	else
+		pci_write_reg(chan, *data, SH4A_PCIEPDR);
+
+	/* Check for master and target aborts */
+	if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
+			    int where, int size, u32 *val)
+{
+	unsigned long flags;
+	int ret;
+	u32 data;
+
+        if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	spin_lock_irqsave(&sh7786_pcie_lock, flags);
+	ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
+					devfn, where, &data);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		goto out;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 2) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=0x%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)*val);
+
+out:
+	spin_unlock_irqrestore(&sh7786_pcie_lock, flags);
+	return ret;
+}
+
+static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 val)
+{
+	unsigned long flags;
+	int shift, ret;
+	u32 data;
+
+        if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	spin_lock_irqsave(&sh7786_pcie_lock, flags);
+	ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
+					devfn, where, &data);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		goto out;
+
+	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)val);
+
+	if (size == 1) {
+		shift = (where & 3) << 3;
+		data &= ~(0xff << shift);
+		data |= ((val & 0xff) << shift);
+	} else if (size == 2) {
+		shift = (where & 2) << 3;
+		data &= ~(0xffff << shift);
+		data |= ((val & 0xffff) << shift);
+	} else
+		data = val;
+
+	ret = sh7786_pcie_config_access(PCI_ACCESS_WRITE, bus,
+					devfn, where, &data);
+out:
+	spin_unlock_irqrestore(&sh7786_pcie_lock, flags);
+	return ret;
+}
+
+struct pci_ops sh7786_pci_ops = {
+	.read	= sh7786_pcie_read,
+	.write	= sh7786_pcie_write,
+};
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-snapgear.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-snapgear.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-snapgear.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-snapgear.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,94 +0,0 @@
-/*
- * arch/sh/drivers/pci/ops-snapgear.c
- *
- * Author:  David McCullough <davidm@snapgear.com>
- *
- * Ported to new API by Paul Mundt <lethal@linux-sh.org>
- *
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the SnapGear boards
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include "pci-sh4.h"
-
-#define SNAPGEAR_PCI_IO		0x4000
-#define SNAPGEAR_PCI_MEM	0xfd000000
-
-/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
-#define SNAPGEAR_LSR0_SIZE    (64*(1<<20)) //64MB
-#define SNAPGEAR_LSR1_SIZE    (64*(1<<20)) //64MB
-
-static struct resource sh7751_io_resource = {
-	.name		= "SH7751 IO",
-	.start		= SNAPGEAR_PCI_IO,
-	.end		= SNAPGEAR_PCI_IO + (64*1024) - 1, /* 64KiB I/O */
-	.flags		= IORESOURCE_IO,
-};
-
-static struct resource sh7751_mem_resource = {
-	.name		= "SH7751 mem",
-	.start		= SNAPGEAR_PCI_MEM,
-	.end		= SNAPGEAR_PCI_MEM + (64*1024*1024) - 1, /* 64MiB mem */
-	.flags		= IORESOURCE_MEM,
-};
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-	{ 0, }
-};
-
-static struct sh4_pci_address_map sh7751_pci_map = {
-	.window0	= {
-		.base	= SH7751_CS2_BASE_ADDR,
-		.size	= SNAPGEAR_LSR0_SIZE,
-	},
-
-	.window1	= {
-		.base	= SH7751_CS2_BASE_ADDR,
-		.size	= SNAPGEAR_LSR1_SIZE,
-	},
-
-	.flags	= SH4_PCIC_NO_RESET,
-};
-
-/*
- * Initialize the SnapGear PCI interface
- * Setup hardware to be Central Funtion
- * Copy the BSR regs to the PCI interface
- * Setup PCI windows into local RAM
- */
-int __init pcibios_init_platform(void)
-{
-	return sh7751_pcic_init(&sh7751_pci_map);
-}
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	int irq = -1;
-
-	switch (slot) {
-	case 8:  /* the PCI bridge */ break;
-	case 11: irq = 8;  break; /* USB    */
-	case 12: irq = 11; break; /* PCMCIA */
-	case 13: irq = 5;  break; /* eth0   */
-	case 14: irq = 8;  break; /* eth1   */
-	case 15: irq = 11; break; /* safenet (unused) */
-	}
-
-	printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
-	       slot, pin - 1 + 'A', irq);
-
-	return irq;
-}
-
-void __init pcibios_fixup(void)
-{
-	/* Nothing to fixup .. */
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-titan.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-titan.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/ops-titan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/ops-titan.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- * arch/sh/drivers/pci/ops-titan.c
- *
- * Ported to new API by Paul Mundt <lethal@linux-sh.org>
- *
- * Modified from ops-snapgear.c written by  David McCullough
- * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * PCI initialization for the Titan boards
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-#include <mach/titan.h>
-#include "pci-sh4.h"
-
-static char titan_irq_tab[] __initdata = {
-	TITAN_IRQ_WAN,
-	TITAN_IRQ_LAN,
-	TITAN_IRQ_MPCIA,
-	TITAN_IRQ_MPCIB,
-	TITAN_IRQ_USB,
-};
-
-int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
-{
-	int irq = titan_irq_tab[slot];
-
-	printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
-		slot, pin - 1 + 'A', irq);
-
-	return irq;
-}
-
-static struct resource sh7751_io_resource = {
-	.name	= "SH7751_IO",
-	.start	= SH7751_PCI_IO_BASE,
-	.end	= SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource sh7751_mem_resource = {
-	.name	= "SH7751_mem",
-	.start	= SH7751_PCI_MEMORY_BASE,
-	.end	= SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
-	.flags	= IORESOURCE_MEM
-};
-
-struct pci_channel board_pci_channels[] = {
-	{ &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
-	{ NULL, NULL, NULL, 0, 0 },
-};
-EXPORT_SYMBOL(board_pci_channels);
-
-static struct sh4_pci_address_map sh7751_pci_map = {
-	.window0	= {
-		.base	= SH7751_CS2_BASE_ADDR,
-		.size	= SH7751_MEM_REGION_SIZE*2,	/* cs2 and cs3 */
-	},
-
-	.window1	= {
-		.base	= SH7751_CS2_BASE_ADDR,
-		.size	= SH7751_MEM_REGION_SIZE*2,
-	},
-
-	.flags	= SH4_PCIC_NO_RESET,
-};
-
-int __init pcibios_init_platform(void)
-{
-	return sh7751_pcic_init(&sh7751_pci_map);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-auto.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-auto.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-auto.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-auto.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,545 +0,0 @@
-/*
- * PCI autoconfiguration library
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * Copyright 2000, 2001 MontaVista Software Inc.
- * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
- * Copyright 2003 Paul Mundt <lethal@linux-sh.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.
- */
-
-/*
- * Modified for MIPS by Jun Sun, jsun@mvista.com
- *
- * . Simplify the interface between pci_auto and the rest: a single function.
- * . Assign resources from low address to upper address.
- * . change most int to u32.
- *
- * Further modified to include it as mips generic code, ppopov@mvista.com.
- *
- * 2001-10-26  Bradley D. LaRonde <brad@ltc.com>
- * - Add a top_bus argument to the "early config" functions so that
- *   they can set a fake parent bus pointer to convince the underlying
- *   pci ops to use type 1 configuration for sub busses.
- * - Set bridge base and limit registers correctly.
- * - Align io and memory base properly before and after bridge setup.
- * - Don't fall through to pci_setup_bars for bridge.
- * - Reformat the debug output to look more like lspci's output.
- *
- * Cloned for SuperH by M. R. Brown, mrbrown@0xd6.org
- *
- * 2003-08-05  Paul Mundt <lethal@linux-sh.org>
- * - Don't update the BAR values on systems that already have valid addresses
- *   and don't want these updated for whatever reason, by way of a new config
- *   option check. However, we still read in the old BAR values so that they
- *   can still be reported through the debug output.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#define	DEBUG
-#ifdef	DEBUG
-#define	DBG(x...)	printk(x)
-#else
-#define	DBG(x...)
-#endif
-
-/*
- * These functions are used early on before PCI scanning is done
- * and all of the pci_dev and pci_bus structures have been created.
- */
-static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
-	int top_bus, int busnr, int devfn)
-{
-	static struct pci_dev dev;
-	static struct pci_bus bus;
-
-	dev.bus = &bus;
-	dev.sysdata = hose;
-	dev.devfn = devfn;
-	bus.number = busnr;
-	bus.ops = hose->pci_ops;
-
-	if(busnr != top_bus)
-		/* Fake a parent bus structure. */
-		bus.parent = &bus;
-	else
-		bus.parent = NULL;
-
-	return &dev;
-}
-
-#define EARLY_PCI_OP(rw, size, type)					\
-static int early_##rw##_config_##size(struct pci_channel *hose,		\
-	int top_bus, int bus, int devfn, int offset, type value)	\
-{									\
-	return pci_##rw##_config_##size(				\
-		fake_pci_dev(hose, top_bus, bus, devfn),		\
-		offset, value);						\
-}
-
-EARLY_PCI_OP(read, byte, u8 *)
-EARLY_PCI_OP(read, word, u16 *)
-EARLY_PCI_OP(read, dword, u32 *)
-EARLY_PCI_OP(write, byte, u8)
-EARLY_PCI_OP(write, word, u16)
-EARLY_PCI_OP(write, dword, u32)
-
-static struct resource *io_resource_inuse;
-static struct resource *mem_resource_inuse;
-
-static u32 pciauto_lower_iospc;
-static u32 pciauto_upper_iospc;
-
-static u32 pciauto_lower_memspc;
-static u32 pciauto_upper_memspc;
-
-static void __init
-pciauto_setup_bars(struct pci_channel *hose,
-		   int top_bus,
-		   int current_bus,
-		   int pci_devfn,
-		   int bar_limit)
-{
-	u32 bar_response, bar_size, bar_value;
-	u32 bar, addr_mask, bar_nr = 0;
-	u32 * upper_limit;
-	u32 * lower_limit;
-	int found_mem64 = 0;
-
-	for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
-		u32 bar_addr;
-
-		/* Read the old BAR value */
-		early_read_config_dword(hose, top_bus,
-					current_bus,
-					pci_devfn,
-					bar,
-					&bar_addr);
-
-		/* Tickle the BAR and get the response */
-		early_write_config_dword(hose, top_bus,
-					 current_bus,
-					 pci_devfn,
-					 bar,
-					 0xffffffff);
-
-		early_read_config_dword(hose, top_bus,
-					current_bus,
-					pci_devfn,
-					bar,
-					&bar_response);
-
-		/*
-		 * Write the old BAR value back out, only update the BAR
-		 * if we implicitly want resources to be updated, which
-		 * is done by the generic code further down. -- PFM.
-		 */
-		early_write_config_dword(hose, top_bus,
-					 current_bus,
-					 pci_devfn,
-					 bar,
-					 bar_addr);
-
-		/* If BAR is not implemented go to the next BAR */
-		if (!bar_response)
-			continue;
-
-		/*
-		 * Workaround for a BAR that doesn't use its upper word,
-		 * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457).
-		 * bdl <brad@ltc.com>
-		 */
-		if (!(bar_response & 0xffff0000))
-			bar_response |= 0xffff0000;
-
-retry:
-		/* Check the BAR type and set our address mask */
-		if (bar_response & PCI_BASE_ADDRESS_SPACE) {
-			addr_mask = PCI_BASE_ADDRESS_IO_MASK;
-			upper_limit = &pciauto_upper_iospc;
-			lower_limit = &pciauto_lower_iospc;
-			DBG("        I/O");
-		} else {
-			if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
-			    PCI_BASE_ADDRESS_MEM_TYPE_64)
-				found_mem64 = 1;
-
-			addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
-			upper_limit = &pciauto_upper_memspc;
-			lower_limit = &pciauto_lower_memspc;
-			DBG("        Mem");
-		}
-
-
-		/* Calculate requested size */
-		bar_size = ~(bar_response & addr_mask) + 1;
-
-		/* Allocate a base address */
-		bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
-
-		if ((bar_value + bar_size) > *upper_limit) {
-			if (bar_response & PCI_BASE_ADDRESS_SPACE) {
-				if (io_resource_inuse->child) {
-					io_resource_inuse =
-						io_resource_inuse->child;
-					pciauto_lower_iospc =
-						io_resource_inuse->start;
-					pciauto_upper_iospc =
-						io_resource_inuse->end + 1;
-					goto retry;
-				}
-
-			} else {
-				if (mem_resource_inuse->child) {
-					mem_resource_inuse =
-						mem_resource_inuse->child;
-					pciauto_lower_memspc =
-						mem_resource_inuse->start;
-					pciauto_upper_memspc =
-						mem_resource_inuse->end + 1;
-					goto retry;
-				}
-			}
-			DBG(" unavailable -- skipping, value %x size %x\n",
-					bar_value, bar_size);
-			continue;
-		}
-
-		if (bar_value < *lower_limit || (bar_value + bar_size) >= *upper_limit) {
-			DBG(" unavailable -- skipping, value %x size %x\n",
-					bar_value, bar_size);
-			continue;
-		}
-
-#ifdef CONFIG_PCI_AUTO_UPDATE_RESOURCES
-		/* Write it out and update our limit */
-		early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-					 bar, bar_value);
-#endif
-
-		*lower_limit = bar_value + bar_size;
-
-		/*
-		 * If we are a 64-bit decoder then increment to the
-		 * upper 32 bits of the bar and force it to locate
-		 * in the lower 4GB of memory.
-		 */
-		if (found_mem64) {
-			bar += 4;
-			early_write_config_dword(hose, top_bus,
-						 current_bus,
-						 pci_devfn,
-						 bar,
-						 0x00000000);
-		}
-
-		DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size);
-
-		bar_nr++;
-	}
-
-}
-
-static void __init
-pciauto_prescan_setup_bridge(struct pci_channel *hose,
-			     int top_bus,
-			     int current_bus,
-			     int pci_devfn,
-			     int sub_bus)
-{
-	/* Configure bus number registers */
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-	                        PCI_PRIMARY_BUS, current_bus);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SECONDARY_BUS, sub_bus + 1);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, 0xff);
-
-	/* Align memory and I/O to 1MB and 4KB boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
-		& ~(0x100000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
-		& ~(0x1000 - 1);
-
-	/* Set base (lower limit) of address range behind bridge. */
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-		PCI_MEMORY_BASE, pciauto_lower_memspc >> 16);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-		PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8);
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-		PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16);
-
-	/* We don't support prefetchable memory for now, so disable */
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_PREF_MEMORY_BASE, 0);
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-				PCI_PREF_MEMORY_LIMIT, 0);
-}
-
-static void __init
-pciauto_postscan_setup_bridge(struct pci_channel *hose,
-			      int top_bus,
-			      int current_bus,
-			      int pci_devfn,
-			      int sub_bus)
-{
-	u32 temp;
-
-	/*
-	 * [jsun] we always bump up baselines a little, so that if there
-	 * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
-	 * spaces.
-	 */
-	pciauto_lower_memspc += 1;
-	pciauto_lower_iospc += 1;
-
-	/* Configure bus number registers */
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, sub_bus);
-
-	/* Set upper limit of address range behind bridge. */
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-		PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-		PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8);
-	early_write_config_word(hose, top_bus, current_bus, pci_devfn,
-		PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16);
-
-	/* Align memory and I/O to 1MB and 4KB boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1))
-		& ~(0x100000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1))
-		& ~(0x1000 - 1);
-
-	/* Enable memory and I/O accesses, enable bus master */
-	early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_COMMAND, &temp);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY
-		| PCI_COMMAND_MASTER);
-}
-
-static void __init
-pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose,
-			int top_bus,
-			int current_bus,
-			int pci_devfn,
-			int sub_bus)
-{
-	/* Configure bus number registers */
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_PRIMARY_BUS, current_bus);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SECONDARY_BUS, sub_bus + 1);
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, 0xff);
-
-	/* Align memory and I/O to 4KB and 4 byte boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
-		& ~(0x1000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
-		& ~(0x4 - 1);
-
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_CB_IO_BASE_0, pciauto_lower_iospc);
-}
-
-static void __init
-pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
-			int top_bus,
-			int current_bus,
-			int pci_devfn,
-			int sub_bus)
-{
-	u32 temp;
-
-	/*
-	 * [jsun] we always bump up baselines a little, so that if there
-	 * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
-	 * spaces.
-	 */
-	pciauto_lower_memspc += 1;
-	pciauto_lower_iospc += 1;
-
-	/*
-	 * Configure subordinate bus number.  The PCI subsystem
-	 * bus scan will renumber buses (reserving three additional
-	 * for this PCI<->CardBus bridge for the case where a CardBus
-	 * adapter contains a P2P or CB2CB bridge.
-	 */
-
-	early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-				PCI_SUBORDINATE_BUS, sub_bus);
-
-	/*
-	 * Reserve an additional 4MB for mem space and 16KB for
-	 * I/O space.  This should cover any additional space
-	 * requirement of unusual CardBus devices with
-	 * additional bridges that can consume more address space.
-	 *
-	 * Although pcmcia-cs currently will reprogram bridge
-	 * windows, the goal is to add an option to leave them
-	 * alone and use the bridge window ranges as the regions
-	 * that are searched for free resources upon hot-insertion
-	 * of a device.  This will allow a PCI<->CardBus bridge
-	 * configured by this routine to happily live behind a
-	 * P2P bridge in a system.
-	 */
-	/* Align memory and I/O to 4KB and 4 byte boundaries. */
-	pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
-		& ~(0x1000 - 1);
-	pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1))
-		& ~(0x4 - 1);
-	/* Set up memory and I/O filter limits, assume 32-bit I/O space */
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1);
-
-	/* Enable memory and I/O accesses, enable bus master */
-	early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_COMMAND, &temp);
-	early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-		PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-		PCI_COMMAND_MASTER);
-}
-
-#define	PCIAUTO_IDE_MODE_MASK		0x05
-
-static int __init
-pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
-{
-	int sub_bus;
-	u32 pci_devfn, pci_class, cmdstat, found_multi=0;
-	unsigned short vid, did;
-	unsigned char header_type;
-	int devfn_start = 0;
-	int devfn_stop = 0xff;
-
-	sub_bus = current_bus;
-
-	if (hose->first_devfn)
-		devfn_start = hose->first_devfn;
-	if (hose->last_devfn)
-		devfn_stop = hose->last_devfn;
-
-	for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
-
-		if (PCI_FUNC(pci_devfn) && !found_multi)
-			continue;
-
-		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
-				       PCI_VENDOR_ID, &vid);
-
-		if (vid == 0xffff) continue;
-
-		early_read_config_byte(hose, top_bus, current_bus, pci_devfn,
-				       PCI_HEADER_TYPE, &header_type);
-
-		if (!PCI_FUNC(pci_devfn))
-			found_multi = header_type & 0x80;
-
-		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
-				       PCI_DEVICE_ID, &did);
-
-		early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
-					PCI_CLASS_REVISION, &pci_class);
-
-		DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x",
-			current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn),
-			pci_class >> 16, vid, did);
-		if (pci_class & 0xff)
-			DBG(" (rev %.2x)", pci_class & 0xff);
-		DBG("\n");
-
-		if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
-			DBG("        Bridge: primary=%.2x, secondary=%.2x\n",
-				current_bus, sub_bus + 1);
-			pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
-						     pci_devfn, sub_bus);
-			DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
-				sub_bus + 1,
-				pciauto_lower_iospc, pciauto_lower_memspc);
-			sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
-			DBG("Back to bus %.2x\n", current_bus);
-			pciauto_postscan_setup_bridge(hose, top_bus, current_bus,
-							pci_devfn, sub_bus);
-			continue;
-		} else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) {
-			DBG("  CARDBUS  Bridge: primary=%.2x, secondary=%.2x\n",
-				current_bus, sub_bus + 1);
-			DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
-			/* Place CardBus Socket/ExCA registers */
-			pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
-
-			pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
-					current_bus, pci_devfn, sub_bus);
-
-			DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
-				sub_bus + 1,
-				pciauto_lower_iospc, pciauto_lower_memspc);
-			sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1);
-			DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus);
-			pciauto_postscan_setup_cardbus_bridge(hose, top_bus,
-					current_bus, pci_devfn, sub_bus);
-			continue;
-		} else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
-
-			unsigned char prg_iface;
-
-			early_read_config_byte(hose, top_bus, current_bus,
-				pci_devfn, PCI_CLASS_PROG, &prg_iface);
-			if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
-				DBG("Skipping legacy mode IDE controller\n");
-				continue;
-			}
-		}
-
-		/*
-		 * Found a peripheral, enable some standard
-		 * settings
-		 */
-		early_read_config_dword(hose, top_bus, current_bus, pci_devfn,
-					PCI_COMMAND, &cmdstat);
-		early_write_config_dword(hose, top_bus, current_bus, pci_devfn,
-					 PCI_COMMAND, cmdstat | PCI_COMMAND_IO |
-					 PCI_COMMAND_MEMORY |
-					 PCI_COMMAND_MASTER);
-		early_write_config_byte(hose, top_bus, current_bus, pci_devfn,
-					PCI_LATENCY_TIMER, 0x80);
-
-		/* Allocate PCI I/O and/or memory space */
-		pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5);
-	}
-	return sub_bus;
-}
-
-int __init
-pciauto_assign_resources(int busno, struct pci_channel *hose)
-{
-	/* setup resource limits */
-	io_resource_inuse = hose->io_resource;
-	mem_resource_inuse = hose->mem_resource;
-
-	pciauto_lower_iospc = io_resource_inuse->start;
-	pciauto_upper_iospc = io_resource_inuse->end + 1;
-	pciauto_lower_memspc = mem_resource_inuse->start;
-	pciauto_upper_memspc = mem_resource_inuse->end + 1;
-	DBG("Autoconfig PCI channel 0x%p\n", hose);
-	DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n",
-		busno, pciauto_lower_iospc, pciauto_upper_iospc, 
-		pciauto_lower_memspc, pciauto_upper_memspc);
-
-	return pciauto_bus_scan(hose, busno, busno);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,67 +1,146 @@
 /*
- * arch/sh/drivers/pci/pci.c
- *
- * Copyright (c) 2002 M. R. Brown  <mrbrown@linux-sh.org>
- * Copyright (c) 2004 - 2006 Paul Mundt  <lethal@linux-sh.org>
- *
- * These functions are collected here to reduce duplication of common
- * code amongst the many platform-specific PCI support code files.
+ * New-style PCI core.
  *
- * These routines require the following board-specific routines:
- * void pcibios_fixup_irqs();
+ * Copyright (c) 2004 - 2009  Paul Mundt
+ * Copyright (c) 2002  M. R. Brown
  *
- * See include/asm-sh/pci.h for more information.
+ * Modelled after arch/mips/pci/pci.c:
+ *  Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org)
  *
  * 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/mm.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/types.h>
 #include <linux/dma-debug.h>
-#include <asm/io.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
 
-static int __init pcibios_init(void)
+unsigned long PCIBIOS_MIN_IO = 0x0000;
+unsigned long PCIBIOS_MIN_MEM = 0;
+
+/*
+ * The PCI controller list.
+ */
+static struct pci_channel *hose_head, **hose_tail = &hose_head;
+
+static int pci_initialized;
+
+static void __devinit pcibios_scanbus(struct pci_channel *hose)
 {
-	struct pci_channel *p;
+	static int next_busno;
 	struct pci_bus *bus;
-	int busno;
 
-#ifdef CONFIG_PCI_AUTO
-	/* assign resources */
-	busno = 0;
-	for (p = board_pci_channels; p->pci_ops != NULL; p++)
-		busno = pciauto_assign_resources(busno, p) + 1;
-#endif
+	bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+	if (bus) {
+		next_busno = bus->subordinate + 1;
+		/* Don't allow 8-bit bus number overflow inside the hose -
+		   reserve some space for bridges. */
+		if (next_busno > 224)
+			next_busno = 0;
 
-	/* scan the buses */
-	busno = 0;
-	for (p = board_pci_channels; p->pci_ops != NULL; p++) {
-		bus = pci_scan_bus(busno, p->pci_ops, p);
-		busno = bus->subordinate + 1;
+		pci_bus_size_bridges(bus);
+		pci_bus_assign_resources(bus);
+		pci_enable_bridges(bus);
 	}
+}
+
+static DEFINE_MUTEX(pci_scan_mutex);
+
+void __devinit register_pci_controller(struct pci_channel *hose)
+{
+	request_resource(&iomem_resource, hose->mem_resource);
+	request_resource(&ioport_resource, hose->io_resource);
+
+	*hose_tail = hose;
+	hose_tail = &hose->next;
+
+	/*
+	 * Do not panic here but later - this might hapen before console init.
+	 */
+	if (!hose->io_map_base) {
+		printk(KERN_WARNING
+		       "registering PCI controller with io_map_base unset\n");
+	}
+
+	/*
+	 * Scan the bus if it is register after the PCI subsystem
+	 * initialization.
+	 */
+	if (pci_initialized) {
+		mutex_lock(&pci_scan_mutex);
+		pcibios_scanbus(hose);
+		mutex_unlock(&pci_scan_mutex);
+	}
+}
+
+static int __init pcibios_init(void)
+{
+	struct pci_channel *hose;
+
+	/* Scan all of the recorded PCI controllers.  */
+	for (hose = hose_head; hose; hose = hose->next)
+		pcibios_scanbus(hose);
 
 	pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
 
 	dma_debug_add_bus(&pci_bus_type);
 
+	pci_initialized = 1;
+
 	return 0;
 }
 subsys_initcall(pcibios_init);
 
+static void pcibios_fixup_device_resources(struct pci_dev *dev,
+	struct pci_bus *bus)
+{
+	/* Update device resources.  */
+	struct pci_channel *hose = bus->sysdata;
+	unsigned long offset = 0;
+	int i;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		if (!dev->resource[i].start)
+			continue;
+		if (dev->resource[i].flags & IORESOURCE_PCI_FIXED)
+			continue;
+		if (dev->resource[i].flags & IORESOURCE_IO)
+			offset = hose->io_offset;
+		else if (dev->resource[i].flags & IORESOURCE_MEM)
+			offset = hose->mem_offset;
+
+		dev->resource[i].start += offset;
+		dev->resource[i].end += offset;
+	}
+}
+
 /*
  *  Called after each bus is probed, but before its children
  *  are examined.
  */
-void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
-	pci_read_bridge_bases(bus);
-}
+	struct pci_dev *dev = bus->self;
+	struct list_head *ln;
+	struct pci_channel *chan = bus->sysdata;
 
-void pcibios_align_resource(void *data, struct resource *res,
-			    resource_size_t size, resource_size_t align)
-			    __attribute__ ((weak));
+	if (!dev) {
+		bus->resource[0] = chan->io_resource;
+		bus->resource[1] = chan->mem_resource;
+	}
+
+	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+		dev = pci_dev_b(ln);
+
+		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+			pcibios_fixup_device_resources(dev, bus);
+	}
+}
 
 /*
  * We need to avoid collisions with `mirrored' VGA ports
@@ -72,14 +151,58 @@
 void pcibios_align_resource(void *data, struct resource *res,
 			    resource_size_t size, resource_size_t align)
 {
+	struct pci_dev *dev = data;
+	struct pci_channel *chan = dev->sysdata;
+	resource_size_t start = res->start;
+
 	if (res->flags & IORESOURCE_IO) {
-		resource_size_t start = res->start;
+		if (start < PCIBIOS_MIN_IO + chan->io_resource->start)
+			start = PCIBIOS_MIN_IO + chan->io_resource->start;
 
+		/*
+                 * Put everything into 0x00-0xff region modulo 0x400.
+		 */
 		if (start & 0x300) {
 			start = (start + 0x3ff) & ~0x3ff;
 			res->start = start;
 		}
+	} else if (res->flags & IORESOURCE_MEM) {
+		if (start < PCIBIOS_MIN_MEM + chan->mem_resource->start)
+			start = PCIBIOS_MIN_MEM + chan->mem_resource->start;
 	}
+
+	res->start = start;
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			 struct resource *res)
+{
+	struct pci_channel *hose = dev->sysdata;
+	unsigned long offset = 0;
+
+	if (res->flags & IORESOURCE_IO)
+		offset = hose->io_offset;
+	else if (res->flags & IORESOURCE_MEM)
+		offset = hose->mem_offset;
+
+	region->start = res->start - offset;
+	region->end = res->end - offset;
+}
+
+void __devinit
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+			struct pci_bus_region *region)
+{
+	struct pci_channel *hose = dev->sysdata;
+	unsigned long offset = 0;
+
+	if (res->flags & IORESOURCE_IO)
+		offset = hose->io_offset;
+	else if (res->flags & IORESOURCE_MEM)
+		offset = hose->mem_offset;
+
+	res->start = region->start + offset;
+	res->end = region->end + offset;
 }
 
 int pcibios_enable_device(struct pci_dev *dev, int mask)
@@ -90,13 +213,21 @@
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	old_cmd = cmd;
-	for(idx=0; idx<6; idx++) {
-		if (!(mask & (1 << idx)))
+	for (idx=0; idx < PCI_NUM_RESOURCES; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1<<idx)))
 			continue;
+
 		r = &dev->resource[idx];
+		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+			continue;
+		if ((idx == PCI_ROM_RESOURCE) &&
+				(!(r->flags & IORESOURCE_ROM_ENABLE)))
+			continue;
 		if (!r->start && r->end) {
-			printk(KERN_ERR "PCI: Device %s not available because "
-			       "of resource collisions\n", pci_name(dev));
+			printk(KERN_ERR "PCI: Device %s not available "
+			       "because of resource collisions\n",
+			       pci_name(dev));
 			return -EINVAL;
 		}
 		if (r->flags & IORESOURCE_IO)
@@ -104,10 +235,8 @@
 		if (r->flags & IORESOURCE_MEM)
 			cmd |= PCI_COMMAND_MEMORY;
 	}
-	if (dev->resource[PCI_ROM_RESOURCE].start)
-		cmd |= PCI_COMMAND_MEMORY;
 	if (cmd != old_cmd) {
-		printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n",
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
 		       pci_name(dev), old_cmd, cmd);
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 	}
@@ -140,6 +269,43 @@
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
+char * __devinit pcibios_setup(char *str)
+{
+	return str;
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine)
+{
+	/*
+	 * I/O space can be accessed via normal processor loads and stores on
+	 * this platform but for now we elect not to do this and portable
+	 * drivers should not do this anyway.
+	 */
+	if (mmap_state == pci_mmap_io)
+		return -EINVAL;
+
+	/*
+	 * Ignore write-combine; for now only return uncached mappings.
+	 */
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot);
+}
+
+static void __iomem *ioport_map_pci(struct pci_dev *dev,
+				    unsigned long port, unsigned int nr)
+{
+	struct pci_channel *chan = dev->sysdata;
+
+	if (!chan->io_map_base)
+		chan->io_map_base = generic_io_base;
+
+	return (void __iomem *)(chan->io_map_base + port);
+}
+
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
 	resource_size_t start = pci_resource_start(dev, bar);
@@ -151,20 +317,24 @@
 	if (maxlen && len > maxlen)
 		len = maxlen;
 
+	if (flags & IORESOURCE_IO)
+		return ioport_map_pci(dev, start, len);
+
 	/*
 	 * Presently the IORESOURCE_MEM case is a bit special, most
 	 * SH7751 style PCI controllers have PCI memory at a fixed
-	 * location in the address space where no remapping is desired
-	 * (typically at 0xfd000000, but is_pci_memaddr() will know
-	 * best). With the IORESOURCE_MEM case more care has to be taken
+	 * location in the address space where no remapping is desired.
+	 * With the IORESOURCE_MEM case more care has to be taken
 	 * to inhibit page table mapping for legacy cores, but this is
 	 * punted off to __ioremap().
 	 *					-- PFM.
 	 */
-	if (flags & IORESOURCE_IO)
-		return ioport_map(start, len);
-	if (flags & IORESOURCE_MEM)
-		return ioremap(start, len);
+	if (flags & IORESOURCE_MEM) {
+		if (flags & IORESOURCE_CACHEABLE)
+			return ioremap(start, len);
+
+		return ioremap_nocache(start, len);
+	}
 
 	return NULL;
 }
@@ -175,3 +345,10 @@
 	iounmap(addr);
 }
 EXPORT_SYMBOL(pci_iounmap);
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+EXPORT_SYMBOL(PCIBIOS_MIN_IO);
+EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-dreamcast.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-dreamcast.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-dreamcast.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-dreamcast.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * PCI support for the Sega Dreamcast
+ *
+ * Copyright (C) 2001, 2002  M. R. Brown
+ * Copyright (C) 2002, 2003  Paul Mundt
+ *
+ * This file originally bore the message (with enclosed-$):
+ *	Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
+ *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ *
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/pci.h>
+
+static struct resource gapspci_io_resource = {
+	.name	= "GAPSPCI IO",
+	.start	= GAPSPCI_BBA_CONFIG,
+	.end	= GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource gapspci_mem_resource = {
+	.name	= "GAPSPCI mem",
+	.start	= GAPSPCI_DMA_BASE,
+	.end	= GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct pci_channel dreamcast_pci_controller = {
+	.pci_ops	= &gapspci_pci_ops,
+	.io_resource	= &gapspci_io_resource,
+	.io_offset	= 0x00000000,
+	.mem_resource	= &gapspci_mem_resource,
+	.mem_offset	= 0x00000000,
+};
+
+/*
+ * gapspci init
+ */
+
+static int __init gapspci_init(void)
+{
+	char idbuf[16];
+	int i;
+
+	/*
+	 * FIXME: All of this wants documenting to some degree,
+	 * even some basic register definitions would be nice.
+	 *
+	 * I haven't seen anything this ugly since.. maple.
+	 */
+
+	for (i=0; i<16; i++)
+		idbuf[i] = inb(GAPSPCI_REGS+i);
+
+	if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
+		return -ENODEV;
+
+	outl(0x5a14a501, GAPSPCI_REGS+0x18);
+
+	for (i=0; i<1000000; i++)
+		cpu_relax();
+
+	if (inl(GAPSPCI_REGS+0x18) != 1)
+		return -EINVAL;
+
+	outl(0x01000000, GAPSPCI_REGS+0x20);
+	outl(0x01000000, GAPSPCI_REGS+0x24);
+
+	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
+	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
+
+	outl(1, GAPSPCI_REGS+0x14);
+	outl(1, GAPSPCI_REGS+0x34);
+
+	/* Setting Broadband Adapter */
+	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
+	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
+	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
+	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
+	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
+	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
+	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
+
+	register_pci_controller(&dreamcast_pci_controller);
+
+	return 0;
+}
+arch_initcall(gapspci_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pcie-sh7786.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pcie-sh7786.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pcie-sh7786.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pcie-sh7786.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,355 @@
+/*
+ * Low-Level PCI Express Support for the SH7786
+ *
+ *  Copyright (C) 2009  Paul Mundt
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include "pcie-sh7786.h"
+#include <asm/sizes.h>
+
+struct sh7786_pcie_port {
+	struct pci_channel	*hose;
+	unsigned int		index;
+	int			endpoint;
+	int			link;
+};
+
+static struct sh7786_pcie_port *sh7786_pcie_ports;
+static unsigned int nr_ports;
+
+static struct sh7786_pcie_hwops {
+	int (*core_init)(void);
+	int (*port_init_hw)(struct sh7786_pcie_port *port);
+} *sh7786_pcie_hwops;
+
+static struct resource sh7786_pci_32bit_mem_resources[] = {
+	{
+		.name	= "pci0_mem",
+		.start	= SH4A_PCIMEM_BASEA,
+		.end	= SH4A_PCIMEM_BASEA + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "pci1_mem",
+		.start	= SH4A_PCIMEM_BASEA1,
+		.end	= SH4A_PCIMEM_BASEA1 + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "pci2_mem",
+		.start	= SH4A_PCIMEM_BASEA2,
+		.end	= SH4A_PCIMEM_BASEA2 + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource sh7786_pci_29bit_mem_resource = {
+	.start	= SH4A_PCIMEM_BASE,
+	.end	= SH4A_PCIMEM_BASE + SZ_64M - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource sh7786_pci_io_resources[] = {
+	{
+		.name	= "pci0_io",
+		.start	= SH4A_PCIIO_BASE,
+		.end	= SH4A_PCIIO_BASE + SZ_8M - 1,
+		.flags	= IORESOURCE_IO,
+	}, {
+		.name	= "pci1_io",
+		.start	= SH4A_PCIIO_BASE1,
+		.end	= SH4A_PCIIO_BASE1 + SZ_8M - 1,
+		.flags	= IORESOURCE_IO,
+	}, {
+		.name	= "pci2_io",
+		.start	= SH4A_PCIIO_BASE2,
+		.end	= SH4A_PCIIO_BASE2 + SZ_4M - 1,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+extern struct pci_ops sh7786_pci_ops;
+
+#define DEFINE_CONTROLLER(start, idx)				\
+{								\
+	.pci_ops	= &sh7786_pci_ops,			\
+	.reg_base	= start,				\
+	/* mem_resource filled in at probe time */		\
+	.mem_offset	= 0,					\
+	.io_resource	= &sh7786_pci_io_resources[idx],	\
+	.io_offset	= 0,					\
+}
+
+static struct pci_channel sh7786_pci_channels[] = {
+	DEFINE_CONTROLLER(0xfe000000, 0),
+	DEFINE_CONTROLLER(0xfe200000, 1),
+	DEFINE_CONTROLLER(0xfcc00000, 2),
+};
+
+static int phy_wait_for_ack(struct pci_channel *chan)
+{
+	unsigned int timeout = 100;
+
+	while (timeout--) {
+		if (pci_read_reg(chan, SH4A_PCIEPHYADRR) & (1 << BITS_ACK))
+			return 0;
+
+		udelay(100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
+{
+	unsigned int timeout = 100;
+
+	while (timeout--) {
+		if ((pci_read_reg(chan, SH4A_PCIEINTR) & mask) == mask)
+			return 0;
+
+		udelay(100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void phy_write_reg(struct pci_channel *chan, unsigned int addr,
+			  unsigned int lane, unsigned int data)
+{
+	unsigned long phyaddr, ctrl;
+
+	phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) +
+			((addr & 0xff) << BITS_ADR);
+
+	/* Enable clock */
+	ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
+	ctrl |= (1 << BITS_CKE);
+	pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
+
+	/* Set write data */
+	pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR);
+	pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR);
+
+	phy_wait_for_ack(chan);
+
+	/* Clear command */
+	pci_write_reg(chan, 0, SH4A_PCIEPHYADRR);
+
+	phy_wait_for_ack(chan);
+
+	/* Disable clock */
+	ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
+	ctrl &= ~(1 << BITS_CKE);
+	pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
+}
+
+static int phy_init(struct pci_channel *chan)
+{
+	unsigned int timeout = 100;
+
+	/* Initialize the phy */
+	phy_write_reg(chan, 0x60, 0xf, 0x004b008b);
+	phy_write_reg(chan, 0x61, 0xf, 0x00007b41);
+	phy_write_reg(chan, 0x64, 0xf, 0x00ff4f00);
+	phy_write_reg(chan, 0x65, 0xf, 0x09070907);
+	phy_write_reg(chan, 0x66, 0xf, 0x00000010);
+	phy_write_reg(chan, 0x74, 0xf, 0x0007001c);
+	phy_write_reg(chan, 0x79, 0xf, 0x01fc000d);
+
+	/* Deassert Standby */
+	phy_write_reg(chan, 0x67, 0xf, 0x00000400);
+
+	while (timeout--) {
+		if (pci_read_reg(chan, SH4A_PCIEPHYSR))
+			return 0;
+
+		udelay(100);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int pcie_init(struct sh7786_pcie_port *port)
+{
+	struct pci_channel *chan = port->hose;
+	unsigned int data;
+	int ret;
+
+	/* Begin initialization */
+	pci_write_reg(chan, 0, SH4A_PCIETCTLR);
+
+	/* Initialize as type1. */
+	data = pci_read_reg(chan, SH4A_PCIEPCICONF3);
+	data &= ~(0x7f << 16);
+	data |= PCI_HEADER_TYPE_BRIDGE << 16;
+	pci_write_reg(chan, data, SH4A_PCIEPCICONF3);
+
+	/* Initialize default capabilities. */
+	data = pci_read_reg(chan, SH4A_PCIEEXPCAP0);
+	data &= ~(PCI_EXP_FLAGS_TYPE << 16);
+
+	if (port->endpoint)
+		data |= PCI_EXP_TYPE_ENDPOINT << 20;
+	else
+		data |= PCI_EXP_TYPE_ROOT_PORT << 20;
+
+	data |= PCI_CAP_ID_EXP;
+	pci_write_reg(chan, data, SH4A_PCIEEXPCAP0);
+
+	/* Enable x4 link width and extended sync. */
+	data = pci_read_reg(chan, SH4A_PCIEEXPCAP4);
+	data &= ~(PCI_EXP_LNKSTA_NLW << 16);
+	data |= (1 << 22) | PCI_EXP_LNKCTL_ES;
+	pci_write_reg(chan, data, SH4A_PCIEEXPCAP4);
+
+	/* Set the completion timer timeout to the maximum 32ms. */
+	data = pci_read_reg(chan, SH4A_PCIETLCTLR);
+	data &= ~0xffff;
+	data |= 0x32 << 8;
+	pci_write_reg(chan, data, SH4A_PCIETLCTLR);
+
+	/*
+	 * Set fast training sequences to the maximum 255,
+	 * and enable MAC data scrambling.
+	 */
+	data = pci_read_reg(chan, SH4A_PCIEMACCTLR);
+	data &= ~PCIEMACCTLR_SCR_DIS;
+	data |= (0xff << 16);
+	pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
+
+	/* Finish initialization */
+	data = pci_read_reg(chan, SH4A_PCIETCTLR);
+	data |= 0x1;
+	pci_write_reg(chan, data, SH4A_PCIETCTLR);
+
+	/* Enable DL_Active Interrupt generation */
+	data = pci_read_reg(chan, SH4A_PCIEDLINTENR);
+	data |= PCIEDLINTENR_DLL_ACT_ENABLE;
+	pci_write_reg(chan, data, SH4A_PCIEDLINTENR);
+
+	/* Disable MAC data scrambling. */
+	data = pci_read_reg(chan, SH4A_PCIEMACCTLR);
+	data |= PCIEMACCTLR_SCR_DIS | (0xff << 16);
+	pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
+
+	ret = pci_wait_for_irq(chan, MASK_INT_TX_CTRL);
+	if (unlikely(ret != 0))
+		return -ENODEV;
+
+	pci_write_reg(chan, 0x00100007, SH4A_PCIEPCICONF1);
+	pci_write_reg(chan, 0x80888000, SH4A_PCIETXVC0DCTLR);
+	pci_write_reg(chan, 0x00222000, SH4A_PCIERXVC0DCTLR);
+	pci_write_reg(chan, 0x000050A0, SH4A_PCIEEXPCAP2);
+
+	wmb();
+
+	data = pci_read_reg(chan, SH4A_PCIEMACSR);
+	printk(KERN_NOTICE "PCI: PCIe#%d link width %d\n",
+	       port->index, (data >> 20) & 0x3f);
+
+	pci_write_reg(chan, 0x007c0000, SH4A_PCIEPAMR0);
+	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH0);
+	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL0);
+	pci_write_reg(chan, 0x80000100, SH4A_PCIEPTCTLR0);
+
+	pci_write_reg(chan, 0x03fc0000, SH4A_PCIEPAMR2);
+	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH2);
+	pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL2);
+	pci_write_reg(chan, 0x80000000, SH4A_PCIEPTCTLR2);
+
+	return 0;
+}
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+        return 71;
+}
+
+static int sh7786_pcie_core_init(void)
+{
+	/* Return the number of ports */
+	return test_mode_pin(MODE_PIN12) ? 3 : 2;
+}
+
+static int __devinit sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
+{
+	int ret;
+
+	ret = phy_init(port->hose);
+	if (unlikely(ret < 0))
+		return ret;
+
+	/*
+	 * Check if we are configured in endpoint or root complex mode,
+	 * this is a fixed pin setting that applies to all PCIe ports.
+	 */
+	port->endpoint = test_mode_pin(MODE_PIN11);
+
+	ret = pcie_init(port);
+	if (unlikely(ret < 0))
+		return ret;
+
+	register_pci_controller(port->hose);
+
+	return 0;
+}
+
+static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
+	.core_init	= sh7786_pcie_core_init,
+	.port_init_hw	= sh7786_pcie_init_hw,
+};
+
+static int __init sh7786_pcie_init(void)
+{
+	int ret = 0, i;
+
+	printk(KERN_NOTICE "PCI: Starting intialization.\n");
+
+	sh7786_pcie_hwops = &sh7786_65nm_pcie_hwops;
+
+	nr_ports = sh7786_pcie_hwops->core_init();
+	BUG_ON(nr_ports > ARRAY_SIZE(sh7786_pci_channels));
+
+	if (unlikely(nr_ports == 0))
+		return -ENODEV;
+
+	sh7786_pcie_ports = kzalloc(nr_ports * sizeof(struct sh7786_pcie_port),
+				    GFP_KERNEL);
+	if (unlikely(!sh7786_pcie_ports))
+		return -ENOMEM;
+
+	printk(KERN_NOTICE "PCI: probing %d ports.\n", nr_ports);
+
+	for (i = 0; i < nr_ports; i++) {
+		struct sh7786_pcie_port *port = sh7786_pcie_ports + i;
+
+		port->index		= i;
+		port->hose		= sh7786_pci_channels + i;
+		port->hose->io_map_base	= port->hose->io_resource->start;
+
+		/*
+		 * Check if we are booting in 29 or 32-bit mode
+		 *
+		 * 32-bit mode provides each controller with its own
+		 * memory window, while 29-bit mode uses a shared one.
+		 */
+		port->hose->mem_resource = test_mode_pin(MODE_PIN10) ?
+			&sh7786_pci_32bit_mem_resources[i] :
+			&sh7786_pci_29bit_mem_resource;
+
+		ret |= sh7786_pcie_hwops->port_init_hw(port);
+	}
+
+	if (unlikely(ret))
+		return ret;
+
+	return 0;
+}
+arch_initcall(sh7786_pcie_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pcie-sh7786.h linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pcie-sh7786.h
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pcie-sh7786.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pcie-sh7786.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,589 @@
+/*
+ * SH7786 PCI-Express controller definitions.
+ *
+ * Copyright (C) 2008, 2009 Renesas Technology Corp.
+ * All rights reserved.
+ *
+ * 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.
+ */
+#ifndef __PCI_SH7786_H
+#define __PCI_SH7786_H
+
+/* PCIe bus-0(x4) on SH7786 */			// Rev1.171
+#define SH4A_PCIE_SPW_BASE	0xFE000000	/* spw config address for controller 0 */
+#define SH4A_PCIE_SPW_BASE1	0xFE200000	/* spw config address for controller 1 (Rev1.14)*/
+#define SH4A_PCIE_SPW_BASE2	0xFCC00000	/* spw config address for controller 2 (Rev1.171)*/
+#define SH4A_PCIE_SPW_BASE_LEN	0x00080000
+
+#define SH4A_PCI_CNFG_BASE	0xFE040000	/* pci config address for controller 0 */
+#define SH4A_PCI_CNFG_BASE1	0xFE240000	/* pci config address for controller 1 (Rev1.14)*/
+#define SH4A_PCI_CNFG_BASE2	0xFCC40000	/* pci config address for controller 2 (Rev1.171)*/
+#define SH4A_PCI_CNFG_BASE_LEN	0x00040000
+
+#define SH4A_PCIPIO_ADDR_OFFSET	0x000001c0	/* offset to pci config_address */
+#define SH4A_PCIPIO_DATA_OFFSET	0x00000220	/* offset to pci config_data */
+
+/*
+ * for PEX8111(Max Payload Size=128B,PCIIO_SIZE=64K),
+ * for other(Max Payload Size=4096B,PCIIO_SIZE=8M)
+ */
+
+/* PCI0-0: PCI I/O space */
+#define SH4A_PCIIO_BASE		0xFD000000	/* PCI I/O for controller 0 */
+#define SH4A_PCIIO_BASE1	0xFD800000	/* PCI I/O for controller 1 (Rev1.14)*/
+#define SH4A_PCIIO_BASE2	0xFC800000	/* PCI I/O for controller 2 (Rev1.171)*/
+
+#define SH4A_PCIIO_SIZE64	0x00010000	/* PLX allows only 64K */
+#define SH4A_PCIIO_SIZE		0x00800000	/* 8M */
+#define SH4A_PCIIO_SIZE2	0x00400000	/* 4M (Rev1.171)*/
+
+/* PCI0-1: PCI memory space 29-bit address */
+#define SH4A_PCIMEM_BASE	0x10000000
+#define SH4A_PCIMEM_SIZE	0x04000000	/* 64M */
+
+/* PCI0-2: PCI memory space 32-bit address */
+#define SH4A_PCIMEM_BASEA	0xC0000000	/*  for controller 0 */
+#define SH4A_PCIMEM_BASEA1	0xA0000000	/*  for controller 1 (Rev1.14)*/
+#define SH4A_PCIMEM_BASEA2	0x80000000	/*  for controller 2 (Rev1.171)*/
+#define SH4A_PCIMEM_SIZEA	0x20000000	/* 512M */
+
+/* PCI0: PCI memory target transfer 32-bit address translation value(Rev1.11T)*/
+#define SH4A_PCIBMSTR_TRANSLATION	0x20000000
+
+#define SH4A_PCI_DEVICE_ID		0x0002
+#define SH4A_PCI_VENDOR_ID		0x1912
+
+// PCI compatible 000-03f
+#define PCI_CMD		0x004
+#define PCI_RID		0x008
+#define PCI_IBAR	0x010
+#define PCI_MBAR0	0x014
+#define PCI_MBAR1	0x018
+
+/* PCI power management/MSI/capablity 040-0ff */
+/* PCIE extended 100-fff */
+
+/* SH7786 device identification */	// Rev1.171
+#define SH4A_PVR		(0xFF000030)
+#define SH4A_PVR_SHX3		(0x10400000)
+#define SH4A_PRR		(0xFF000044)
+#define SH4A_PRR_SH7786		(0x00000400)	// Rev1.171
+
+/*	SPVCR0		*/
+#define	SH4A_PCIEVCR0		(0x000000)	/* R - 0x0000 0000 32 */
+#define		BITS_TOP_MB	(24)
+#define		MASK_TOP_MB	(0xff<<BITS_TOP_MB)
+#define		BITS_BOT_MB	(16)
+#define		MASK_BOT_MB	(0xff<<BITS_BOT_MB)
+#define		BITS_VC_ID	(0)
+#define		MASK_VC_ID	(0xffff<<BITS_VC_ID)
+
+/*	SPVCR1		*/
+#define	SH4A_PCIEVCR1		(0x000004)	/* R - 0x0000 0000 32*/
+#define		BITS_BADOPC	(5)		/* 5 BADOPC 0 R/W */
+#define		MASK_BADOPC	(1<<BITS_BADOPC)
+#define		BITS_BADDEST	(4)		/*4 BADDEST 0 R/W  */
+#define		MASK_BADDEST	(1<<BITS_BADDEST)
+#define		BITS_UNSOLRESP	(3)		/* 3 UNSOLRESP 0 R/W  */
+#define		MASK_UNSOLRESP	(1<<BITS_UNSOLRESP)
+#define		BITS_ERRSNT	(1)		/* 1 ERRSNT 0 */
+#define		MASK_ERRSNT	(1<<BITS_ERRSNT)
+#define		BITS_ERRRCV	(0)		/* 0 ERRRCV 0 */
+#define		MASK_ERRRCV	(1<<BITS_ERRRCV)
+
+/*	PCIEECR		*/
+#define	SH4A_PCIEECR		(0x000008)	/* R/W - 0x0000 0000 32 */
+#define		BITS_ENBL	(0)	/* 0 ENBL 0 R/W */
+#define		MASK_ENBL	(1<<BITS_ENBL)
+
+/*	PCIEPAR		*/
+#define	SH4A_PCIEPAR		(0x000010)	/* R/W - 0x0000 0000 32 */
+#define		BITS_BN		(24)
+#define		MASK_BN		(0xff<<BITS_BN)
+#define		BITS_DN		(19)
+#define		MASK_DN		(0x1f<<BITS_DN)
+#define		BITS_FN		(16)
+#define		MASK_FN		(0x7<<BITS_FN)
+#define		BITS_EREGNO	(8)
+#define		MASK_EREGNO	(0xff<<BITS_EREGNO)
+#define		BITS_REGNO	(2)
+#define		MASK_REGNO	(0x3f<<BITS_REGNO)
+
+/*	PCIEPCTLR	*/
+#define	SH4A_PCIEPCTLR		(0x000018)	/* R/W - 0x0000 0000 32 */
+#define		BITS_CCIE	(31)	/*  31 CCIE */
+#define		MASK_CCIE	(1<<BITS_CCIE)
+#define		BITS_TYPE	(8)
+#define		MASK_TYPE	(1<<BITS_TYPE)
+#define		BITS_C_VC	(0)
+#define		MASK_C_VC	(1<<BITS_C_VC)
+
+/*	PCIEPDR		*/
+#define	SH4A_PCIEPDR		(0x000020)	/* R/W - 0x0000 0000 32 */
+#define		BITS_PDR	(0)
+#define		MASK_PDR	(0xffffffff<<BITS_PDR)
+
+/*	PCIEMSGALR	*/
+#define	SH4A_PCIEMSGALR		(0x000030)	/* R/W - 0x0000 0000 32 */
+#define		BITS_MSGADRL	(0)
+#define		MASK_MSGADRL	(0xffffffff<<BITS_MSGADRL)
+
+/*	PCIEMSGAHR	*/
+#define	SH4A_PCIEMSGAHR		(0x000034)	/* R/W - 0x0000 0000 32 */
+#define		BITS_MSGADRH	(0)
+#define		MASK_MSGADRH	(0xffffffff<<BITS_MSGADRH)
+
+/*	PCIEMSGCTLR	*/
+#define	SH4A_PCIEMSGCTLR	(0x000038)	/* R/W - 0x0000 0000 32 */
+#define		BITS_MSGIE	(31)
+#define		MASK_MSGIE	(1<<BITS_MSGIE)
+#define		BITS_MROUTE	(16)
+#define		MASK_MROUTE	(0x7<<BITS_MROUTE)
+#define		BITS_MCODE	(8)
+#define		MASK_MCODE	(0xff<<BITS_MCODE)
+#define		BITS_M_VC	(0)
+#define		MASK_M_VC	(1<<BITS_M_VC)
+
+/*	PCIEMSG		*/
+#define	SH4A_PCIEMSG		(0x000040)	/* W - - 32	*/
+#define		BITS_MDATA	(0)
+#define		MASK_MDATA	(0xffffffff<<BITS_MDATA)
+
+/*	PCIEPHYCTLR	*/
+#define	SH4A_PCIEPHYCTLR	(0x010000)	/* R/W - 0x0000 0000 32 */
+#define		BITS_CKE	(0)
+#define		MASK_CKE	(1<<BITS_CKE)
+
+/*	PCIERMSGIER	*/
+#define	SH4A_PCIERMSGIER	(0x004040)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPHYADRR	*/
+#define	SH4A_PCIEPHYADRR	(0x010004)	/* R/W - 0x0000 0000 32 */
+#define		BITS_ACK	(24)			// Rev1.171
+#define		MASK_ACK	(1<<BITS_ACK)		// Rev1.171
+#define		BITS_CMD	(16)			// Rev1.171
+#define		MASK_CMD	(0x03<<BITS_CMD)	// Rev1.171
+#define		BITS_LANE	(8)
+#define		MASK_LANE	(0x0f<<BITS_LANE)
+#define		BITS_ADR	(0)
+#define		MASK_ADR	(0xff<<BITS_ADR)
+
+/*	PCIEPHYDINR	*/							// Rev1.171 start.
+#define	SH4A_PCIEPHYDINR	(0x010008)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPHYDOUTR	*/
+#define	SH4A_PCIEPHYDOUTR	(0x01000C)	/* R/W - 0x0000 0000 32 */
+
+/*	PCIEPHYSR	*/
+#define	SH4A_PCIEPHYSR		(0x010010)	/* R/W - 0x0000 0000 32 */	// Rev1.171 end.
+
+/*	PCIEPHYDATAR	*/
+#define	SH4A_PCIEPHYDATAR	(0x00008)	/* R/W - 0xxxxx xxxx 32 */
+#define		BITS_DATA	(0)
+#define		MASK_DATA	(0xffffffff<<BITS_DATA)
+
+/*	PCIETCTLR	*/
+#define	SH4A_PCIETCTLR		(0x020000)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_CFINT	(0)
+#define		MASK_CFINT	(1<<BITS_CFINT)
+
+/*	PCIETSTR	*/
+#define	SH4A_PCIETSTR		(0x020004)	/* R/W R/W 0x0000 0000 32  */
+
+/*	PCIEINTR	*/
+#define	SH4A_PCIEINTR		(0x020008)	/* R/W R/W 0x0000 0000 32  */
+#define		BITS_INT_RX_ERP			(31)
+#define		MASK_INT_RX_ERP			(1<<BITS_INT_RX_ERP)
+#define		BITS_INT_RX_VCX_Posted		(30)
+#define		MASK_INT_RX_VCX_Posted		(1<<BITS_INT_RX_VCX_Posted)
+#define		BITS_INT_RX_VCX_NonPosted	(29)
+#define		MASK_INT_RX_VCX_NonPosted	(1<<BITS_INT_RX_VCX_NonPosted)
+#define		BITS_INT_RX_VCX_CPL		(28)
+#define		MASK_INT_RX_VCX_CPL		(1<<BITS_INT_RX_VCX_CPL)
+#define		BITS_INT_TX_VCX_Posted		(26)
+#define		MASK_INT_TX_VCX_Posted		(1<<BITS_INT_TX_VCX_Posted)
+#define		BITS_INT_TX_VCX_NonPosted	(25)
+#define		MASK_INT_TX_VCX_NonPosted	(1<<BITS_INT_TX_VCX_NonPosted)
+#define		BITS_INT_TX_VCX_CPL		(24)
+#define		MASK_INT_TX_VCX_CPL		(1<<BITS_INT_TX_VCX_CPL)
+#define		BITS_INT_RX_VC0_Posted		(22)
+#define		MASK_INT_RX_VC0_Posted		(1<<BITS_INT_RX_VC0_Posted)
+#define		BITS_INT_RX_VC0_NonPosted	(21)
+#define		MASK_INT_RX_VC0_NonPosted	(1<<BITS_INT_RX_VC0_NonPosted)
+#define		BITS_INT_RX_VC0_CPL		(20)
+#define		MASK_INT_RX_VC0_CPL		(1<<BITS_INT_RX_VC0_CPL)
+#define		BITS_INT_TX_VC0_Posted		(18)
+#define		MASK_INT_TX_VC0_Posted		(1<<BITS_INT_TX_VC0_Posted)
+#define		BITS_INT_TX_VC0_NonPosted	(17)
+#define		MASK_INT_TX_VC0_NonPosted	(1<<BITS_INT_TX_VC0_NonPosted)
+#define		BITS_INT_TX_VC0_CPL		(16)
+#define		MASK_INT_TX_VC0_CPL		(1<<BITS_INT_TX_VC0_CPL)
+#define		BITS_INT_RX_CTRL		(15)
+#define		MASK_INT_RX_CTRL		(1<<BITS_INT_RX_CTRL)
+#define		BITS_INT_TX_CTRL		(14)
+#define		MASK_INT_TX_CTRL		(1<<BITS_INT_TX_CTRL)
+#define		BITS_INTTL			(11)
+#define		MASK_INTTL			(1<<BITS_INTTL)
+#define		BITS_INTDL			(10)
+#define		MASK_INTDL			(1<<BITS_INTDL)
+#define		BITS_INTMAC			(9)
+#define		MASK_INTMAC			(1<<BITS_INTMAC)
+#define		BITS_INTPM			(8)
+#define		MASK_INTPM			(1<<BITS_INTPM)
+
+/*	PCIEINTER	*/
+#define	SH4A_PCIEINTER		(0x02000C)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_INT_RX_ERP			(31)
+#define		MASK_INT_RX_ERP			(1<<BITS_INT_RX_ERP)
+#define		BITS_INT_RX_VCX_Posted		(30)
+#define		MASK_INT_RX_VCX_Posted		(1<<BITS_INT_RX_VCX_Posted)
+#define		BITS_INT_RX_VCX_NonPosted	(29)
+#define		MASK_INT_RX_VCX_NonPosted	(1<<BITS_INT_RX_VCX_NonPosted)
+#define		BITS_INT_RX_VCX_CPL		(28)
+#define		MASK_INT_RX_VCX_CPL		(1<<BITS_INT_RX_VCX_CPL)
+#define		BITS_INT_TX_VCX_Posted		(26)
+#define		MASK_INT_TX_VCX_Posted		(1<<BITS_INT_TX_VCX_Posted)
+#define		BITS_INT_TX_VCX_NonPosted	(25)
+#define		MASK_INT_TX_VCX_NonPosted	(1<<BITS_INT_TX_VCX_NonPosted)
+#define		BITS_INT_TX_VCX_CPL		(24)
+#define		MASK_INT_TX_VCX_CPL		(1<<BITS_INT_TX_VCX_CPL)
+#define		BITS_INT_RX_VC0_Posted		(22)
+#define		MASK_INT_RX_VC0_Posted		(1<<BITS_INT_RX_VC0_Posted)
+#define		BITS_INT_RX_VC0_NonPosted	(21)
+#define		MASK_INT_RX_VC0_NonPosted	(1<<BITS_INT_RX_VC0_NonPosted)
+#define		BITS_INT_RX_VC0_CPL		(20)
+#define		MASK_INT_RX_VC0_CPL		(1<<BITS_INT_RX_VC0_CPL)
+#define		BITS_INT_TX_VC0_Posted		(18)
+#define		MASK_INT_TX_VC0_Posted		(1<<BITS_INT_TX_VC0_Posted)
+#define		BITS_INT_TX_VC0_NonPosted	(17)
+#define		MASK_INT_TX_VC0_NonPosted	(1<<BITS_INT_TX_VC0_NonPosted)
+#define		BITS_INT_TX_VC0_CPL		(16)
+#define		MASK_INT_TX_VC0_CPL		(1<<BITS_INT_TX_VC0_CPL)
+#define		BITS_INT_RX_CTRL		(15)
+#define		MASK_INT_RX_CTRL		(1<<BITS_INT_RX_CTRL)
+#define		BITS_INT_TX_CTRL		(14)
+#define		MASK_INT_TX_CTRL		(1<<BITS_INT_TX_CTRL)
+#define		BITS_INTTL			(11)
+#define		MASK_INTTL			(1<<BITS_INTTL)
+#define		BITS_INTDL			(10)
+#define		MASK_INTDL			(1<<BITS_INTDL)
+#define		BITS_INTMAC			(9)
+#define		MASK_INTMAC			(1<<BITS_INTMAC)
+#define		BITS_INTPM			(8)
+#define		MASK_INTPM			(1<<BITS_INTPM)
+
+/*	PCIEAIR	 */
+#define	SH4A_PCIEAIR		(SH4A_PCIE_BASE + 0x020010)	/* R/W R/W 0xxxxx xxxx 32 */
+
+/*	 PCIECIR	 */
+#define	SH4A_PCIECIR		(SH4A_PCIE_BASE)	/* R/W R/W 0xxxxx xxxx 32 */
+
+/*	 PCIEERRFR	 */								// Rev1.18
+#define	SH4A_PCIEERRFR		(0x020020)		/* R/W R/W 0xxxxx xxxx 32 */	// Rev1.18
+											// Rev1.18
+/*	PCIELAR0	*/
+#define	SH4A_PCIELAR0		(0x020200)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_LARn	(20)
+#define		MASK_LARn	(0xfff<<BITS_LARn)
+
+#define	SH4A_PCIE_020204	(0x020204)	/* R/W R/W 0x0000 0000 32 */
+
+/*	PCIELAMR0	*/
+#define	SH4A_PCIELAMR0		(0x020208)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_LAMRn	(20)
+#define		MASK_LAMRn	(0x1ff<<BITS_LAMRn)
+#define		BITS_LAREn	(0)
+#define		MASK_LAREn	(0x1<<BITS_LAREn)
+
+/*	PCIECSCR0	*/
+#define	SH4A_PCIECSCR0		(0x020210)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_RANGE	(2)
+#define		MASK_RANGE	(0x7<<BITS_RANGE)
+#define		BITS_SNPMD	(0)
+#define		MASK_SNPMD	(0x3<<BITS_SNPMD)
+
+/*	PCIECSAR0	*/
+#define	SH4A_PCIECSAR0		(0x020214)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_CSADR	(0)
+#define		MASK_CSADR	(0xffffffff<<BITS_CSADR)
+
+/*	PCIESTCTLR0	*/
+#define	SH4A_PCIESTCTLR0	(0x020218)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_SHPRI	(8)
+#define		MASK_SHPRI	(0x0f<<BITS_SHPRI)
+
+#define	SH4A_PCIE_020224	(0x020224)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR1		(0x020220)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR1		(0x020228)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR1		(0x020230)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR1		(0x020234)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR1	(0x020238)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR2		(0x020240)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_020244	(0x020244)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR2		(0x020248)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR2		(0x020250)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR2		(0x020254)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR2	(0x020258)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR3		(0x020260)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_020264	(0x020264)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR3		(0x020268)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR3		(0x020270)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR3		(0x020274)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR3	(0x020278)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR4		(0x020280)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_020284	(0x020284)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR4		(0x020288)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR4		(0x020290)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR4		(0x020294)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR4	(0x020298)	/* R/W R/W 0x0000 0000 32 */
+
+#define	SH4A_PCIELAR5		(0x0202A0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIE_0202A4	(0x0202A4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIELAMR5		(0x0202A8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSCR5		(0x0202B0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIECSAR5		(0x0202B4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIESTCTLR5	(0x0202B8)	/* R/W R/W 0x0000 0000 32 */
+
+/*	PCIEPARL0	*/
+#define	SH4A_PCIEPARL0		(0x020400)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_PAL	(18)
+#define		MASK_PAL	(0x3fff<<BITS_PAL)
+
+/*	PCIEPARH0	*/
+#define	SH4A_PCIEPARH0		(0x020404)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_PAH	(0)
+#define		MASK_PAH	(0xffffffff<<BITS_PAH)
+
+/*	PCIEPAMR0	 */
+#define	SH4A_PCIEPAMR0		(0x020408)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_PAM	(18)
+#define		MASK_PAM	(0x3fff<<BITS_PAM)
+
+/*	PCIEPTCTLR0	*/
+#define	SH4A_PCIEPTCTLR0	(0x02040C)	/* R/W R/W 0x0000 0000 32 */
+#define		BITS_PARE	(31)
+#define		MASK_PARE	(0x1<<BITS_PARE)
+#define		BITS_TC		(20)
+#define		MASK_TC		(0x7<<BITS_TC)
+#define		BITS_T_VC	(16)
+#define		MASK_T_VC	(0x1<<BITS_T_VC)
+#define		BITS_LOCK	(12)
+#define		MASK_LOCK	(0x1<<BITS_LOCK)
+#define		BITS_SPC	(8)
+#define		MASK_SPC	(0x1<<BITS_SPC)
+
+#define	SH4A_PCIEPARL1		(0x020420)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARH1		(0x020424)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPAMR1		(0x020428)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPTCTLR1	(0x02042C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARL2		(0x020440)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARH2		(0x020444)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPAMR2		(0x020448)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPTCTLR2	(0x02044C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARL3		(0x020460)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARH3		(0x020464)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPAMR3		(0x020468)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPTCTLR3	(0x02046C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARL4		(0x020480)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARH4		(0x020484)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPAMR4		(0x020488)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPTCTLR4	(0x02048C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARL5		(0x0204A0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPARH5		(0x0204A4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPAMR5		(0x0204A8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPTCTLR5	(0x0204AC)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMAOR		(0x021000)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR0		(0x021100)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR0	(0x021104)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR0		(0x021108)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR0	(0x02110C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR0	(0x021110)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR0	(0x021114)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR0	(0x021118)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR0	(0x02111C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR0		(0x021120)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R0	(0x021124)	/* R/W R/W 0x0000 0000 - */
+#define	SH4A_PCIEDMCCCR0	(0x021128)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR1		(0x021140)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR1	(0x021144)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR1		(0x021148)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR1	(0x02114C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR1	(0x021150)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR1	(0x021154)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR1	(0x021158)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR1	(0x02115C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR1		(0x021160)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R1	(0x021164)	/* R/W R/W 0x0000 0000 - */
+#define	SH4A_PCIEDMCCCR1	(0x021168)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR2		(0x021180)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR2	(0x021184)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR2		(0x021188)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR2	(0x02118C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR2	(0x021190)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR2	(0x021194)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR2	(0x021198)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR2	(0x02119C)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR2		(0x0211A0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R2	(0x0211A4)	/* R/W R/W 0x0000 0000 -  */
+#define	SH4A_PCIEDMCCCR2	(0x0211A8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAR3		(0x0211C0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSAHR3	(0x0211C4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAR3		(0x0211C8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMDAHR3	(0x0211CC)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMBCNTR3	(0x0211D0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSBCNTR3	(0x0211D4)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMSTRR3	(0x0211D8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCAR3	(0x0211DC)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCCR3		(0x0211E0)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEDMCC2R3	(0x0211E4)	/* R/W R/W 0x0000 0000 -  */
+#define	SH4A_PCIEDMCCCR3	(0x0211E8)	/* R/W R/W 0x0000 0000 32 */
+#define	SH4A_PCIEPCICONF0	(0x040000)	/* R R - 8/16/32 */
+#define	SH4A_PCIEPCICONF1	(0x040004)	/* R/W R/W 0x0008 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF2	(0x040008)	/* R/W R/W 0xFF00 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF3	(0x04000C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF4	(0x040010)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF5	(0x040014)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF6	(0x040018)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF7	(0x04001C)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF8	(0x040020)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF9	(0x040024)	/* - R/W - 8/16/32 */
+#define	SH4A_PCIEPCICONF10	(0x040028)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF11	(0x04002C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF12	(0x040030)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF13	(0x040034)	/* R/W R/W 0x0000 0040 8/16/32 */
+#define	SH4A_PCIEPCICONF14	(0x040038)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEPCICONF15	(0x04003C)	/* R/W R/W 0x0000 00FF 8/16/32 */
+#define	SH4A_PCIEPMCAP0		(0x040040)	/* R/W R 0x0003 5001 8/16/32 */
+#define	SH4A_PCIEPMCAP1		(0x040044)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP0	(0x040050)	/* R/W R/W 0x0180 7005 8/16/32 */
+#define	SH4A_PCIEMSICAP1	(0x040054)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP2	(0x040058)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP3	(0x04005C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP4	(0x040060)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEMSICAP5	(0x040064)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP0	(0x040070)	/* R/W R/W 0x0001 0010 8/16/32 */
+#define	SH4A_PCIEEXPCAP1	(0x040074)	/* R/W R 0x0000 0005 8/16/32 */
+#define	SH4A_PCIEEXPCAP2	(0x040078)	/* R/W R/W 0x0000 0801 8/16/32 */
+#define	SH4A_PCIEEXPCAP3	(0x04007C)	/* R/W R 0x0003 F421 8/16/32 */
+#define	SH4A_PCIEEXPCAP4	(0x040080)	/* R/W R/W 0x0041 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP5	(0x040084)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP6	(0x040088)	/* R/W R/W 0x0000 03C0 8/16/32 */
+#define	SH4A_PCIEEXPCAP7	(0x04008C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEEXPCAP8	(0x040090)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP0		(0x040100)	/* R/W R 0x1B01 0002 8/16/32 */
+#define	SH4A_PCIEVCCAP1		(0x040104)	/* R R 0x0000 0001 8/16/32 */
+#define	SH4A_PCIEVCCAP2		(0x040108)	/* R R 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP3		(0x04010C)	/* R R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP4		(0x040110)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP5		(0x040114)	/* R/W R/W 0x8000 00FF 8/16/32 */
+#define	SH4A_PCIEVCCAP6		(0x040118)	/* R/W R 0x0002 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP7		(0x04011C)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP8		(0x040120)	/* R/W R/W 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEVCCAP9		(0x040124)	/* R/W R 0x0002 0000 8/16/32 */
+#define	SH4A_PCIENUMCAP0	(0x0001B0)	/* RW R 0x0001 0003 8/16/32 */
+#define	SH4A_PCIENUMCAP1	(0x0001B4)	/* R R 0x0000 0000 8/16/32 */
+#define	SH4A_PCIENUMCAP2	(0x0001B8)	/* R R 0x0000 0000 8/16/32 */
+#define	SH4A_PCIEIDSETR0	(0x041000)	/* R/W R 0x0000 FFFF 16/32 */
+#define	SH4A_PCIEIDSETR1	(0x041004)	/* R/W R 0xFF00 0000 16/32 */
+#define	SH4A_PCIEBAR0SETR	(0x041008)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR1SETR	(0x04100C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR2SETR	(0x041010)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR3SETR	(0x041014)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR4SETR	(0x041018)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEBAR5SETR	(0x04101C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIECISSETR	(0x041020)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEIDSETR2	(0x041024)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEEROMSETR	(0x041028)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDSERSETR0	(0x04102C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDSERSETR1	(0x041030)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIECTLR		(0x041040)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIETLSR		(0x041044)	/* R/W1C R 0x0000 0000 16/32 */
+#define	SH4A_PCIETLCTLR		(0x041048)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDLSR		(0x04104C)	/* R/W1C R 0x4003 0000 16/32 */
+#define	SH4A_PCIEDLCTLR		(0x041050)	/* R R 0x0000 0000 16/32 */
+#define	SH4A_PCIEMACSR		(0x041054)	/* R/W1C R 0x0041 0000 16/32 */
+#define	SH4A_PCIEMACCTLR	(0x041058)	/* R/W R 0x0000 0000 16/32 */
+#define		PCIEMACCTLR_SCR_DIS	(1 << 27)	/* scramble disable */
+#define	SH4A_PCIEPMSTR		(0x04105C)	/* R/W1C R 0x0000 0000 16/32 */
+#define	SH4A_PCIEPMCTLR		(0x041060)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIETLINTENR	(0x041064)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEDLINTENR	(0x041068)	/* R/W R 0x0000 0000 16/32 */
+#define		PCIEDLINTENR_DLL_ACT_ENABLE	(1 << 31) /* DL active irq */
+#define	SH4A_PCIEMACINTENR	(0x04106C)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIEPMINTENR	(0x041070)	/* R/W R 0x0000 0000 16/32 */
+#define	SH4A_PCIETXDCTLR	(0x044000)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXCTLR		(0x044020)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXSR		(0x044028)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVC0DCTLR	(0x044100)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVC0SR	(0x044108)	/* R/W - H'00888000_00000000 32/64 */
+#define	SH4A_PCIEVC0PDTXR	(0x044110)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PHTXR	(0x044118)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPDTXR	(0x044120)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPHTXR	(0x044128)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CDTXR	(0x044130)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CHTXR	(0x044138)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVCXDCTLR	(0x044200)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIETXVCXSR	(0x044208)	/* R/W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPDTXR	(0x044210)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPHTXR	(0x044218)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPDTXR	(0x044220)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPHTXR	(0x044228)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCDTXR	(0x044230)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCHTXR	(0x044238)	/* W - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERDCTLR		(0x046000)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEERPCTLR	(0x046008)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEERPHR		(0x046010)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEERPERR		(0x046018)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVC0DCTLR	(0x046100)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVC0SR	(0x046108)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PDRXR	(0x046140)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PHRXR	(0x046148)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0PERR	(0x046150)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPDRXR	(0x046158)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPHRXR	(0x046160)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0NPERR	(0x046168)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CDRXR	(0x046170)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CHRXR	(0x046178)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVC0CERR	(0x046180)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVCXDCTLR	(0x046200)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIERXVCXSR	(0x046208)	/* RW - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPDRXR	(0x046240)	/* R - H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPHRXR	(0x046248)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXPERR	(0x046250)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPDRXR	(0x046258)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPHRXR	(0x046260)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXNPERR	(0x046268)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCDRXR	(0x046270)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCHRXR	(0x046278)	/* R H'00000000_00000000 32/64 */
+#define	SH4A_PCIEVCXCERR	(0x046280)	/* R H'00000000_00000000 32/64 */
+
+/* SSI Register Definition for MSI WORK AROUND --hamada */
+#define SH4A_PCI_SSI_BASE	0xFFE00000	/* spw config address	*/
+#define SH4A_PCI_SSI_BASE_LEN	0x00100000	/* 1MB			*/
+
+#define	SH4A_SSICR0		(0x000000)
+#define	SH4A_SSICR1		(0x010000)
+#define	SH4A_SSICR2		(0x020000)
+#define	SH4A_SSICR3		(0x030000)
+
+#define PCI_REG(x)		((x) + 0x40000)
+
+static inline void
+pci_write_reg(struct pci_channel *chan, unsigned long val, unsigned long reg)
+{
+	__raw_writel(val, chan->reg_base + reg);
+}
+
+static inline unsigned long
+pci_read_reg(struct pci_channel *chan, unsigned long reg)
+{
+	return __raw_readl(chan->reg_base + reg);
+}
+
+#endif /* __PCI_SH7786_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh4.h linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh4.h
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh4.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh4.h	2009-09-09 18:13:59.000000000 -0400
@@ -149,13 +149,10 @@
   #define SH4_PCIPDTR_PB0	  0x000000001	/* Port 0 Enable */
 #define SH4_PCIPDR		0x220		/* Port IO Data Register */
 
-/* Flags */
-#define SH4_PCIC_NO_RESET	0x0001
-
 /* arch/sh/kernel/drivers/pci/ops-sh4.c */
 extern struct pci_ops sh4_pci_ops;
-int sh4_pci_check_direct(void);
-int pci_fixup_pcic(void);
+int sh4_pci_check_direct(struct pci_channel *chan);
+int pci_fixup_pcic(struct pci_channel *chan);
 
 struct sh4_pci_address_space {
 	unsigned long base;
@@ -165,16 +162,18 @@
 struct sh4_pci_address_map {
 	struct sh4_pci_address_space window0;
 	struct sh4_pci_address_space window1;
-	unsigned long flags;
 };
 
-static inline void pci_write_reg(unsigned long val, unsigned long reg)
+static inline void pci_write_reg(struct pci_channel *chan,
+				 unsigned long val, unsigned long reg)
 {
-	ctrl_outl(val, PCI_REG(reg));
+	ctrl_outl(val, chan->reg_base + reg);
 }
 
-static inline unsigned long pci_read_reg(unsigned long reg)
+static inline unsigned long pci_read_reg(struct pci_channel *chan,
+					 unsigned long reg)
 {
-	return ctrl_inl(PCI_REG(reg));
+	return ctrl_inl(chan->reg_base + reg);
 }
+
 #endif /* __PCI_SH4_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh5.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh5.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh5.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,8 +89,21 @@
 	return IRQ_NONE;
 }
 
-int __init sh5pci_init(unsigned long memStart, unsigned long memSize)
+static struct resource sh5_io_resource = { /* place holder */ };
+static struct resource sh5_mem_resource = { /* place holder */ };
+
+static struct pci_channel sh5pci_controller = {
+	.pci_ops		= &sh5_pci_ops,
+	.mem_resource		= &sh5_mem_resource,
+	.mem_offset		= 0x00000000,
+	.io_resource		= &sh5_io_resource,
+	.io_offset		= 0x00000000,
+};
+
+static int __init sh5pci_init(void)
 {
+	unsigned long memStart = __pa(memory_start);
+	unsigned long memSize = __pa(memory_end) - memStart;
 	u32 lsr0;
 	u32 uval;
 
@@ -106,12 +119,12 @@
                 return -EINVAL;
         }
 
-	pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR");
+	pcicr_virt = (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE, 1024);
 	if (!pcicr_virt) {
 		panic("Unable to remap PCICR\n");
 	}
 
-	PCI_IO_AREA = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO");
+	PCI_IO_AREA = (unsigned long)ioremap_nocache(SH5PCI_IO_BASE, 0x10000);
 	if (!PCI_IO_AREA) {
 		panic("Unable to remap PCIIO\n");
 	}
@@ -197,32 +210,14 @@
         SH5PCI_WRITE(AINTM, ~0);
         SH5PCI_WRITE(PINTM, ~0);
 
-	return 0;
-}
-
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
-	struct pci_dev *dev = bus->self;
-	int i;
+	sh5_io_resource.start = PCI_IO_AREA;
+	sh5_io_resource.end = PCI_IO_AREA + 0x10000;
 
-	if (dev) {
-		for (i= 0; i < 3; i++) {
-			bus->resource[i] =
-				&dev->resource[PCI_BRIDGE_RESOURCES+i];
-			bus->resource[i]->name = bus->name;
-		}
-		bus->resource[0]->flags |= IORESOURCE_IO;
-		bus->resource[1]->flags |= IORESOURCE_MEM;
+	sh5_mem_resource.start = memStart;
+	sh5_mem_resource.end = memStart + memSize;
 
-		/* For now, propagate host limits to the bus;
-		 * we'll adjust them later. */
-		bus->resource[0]->end = 64*1024 - 1 ;
-		bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1;
-		bus->resource[0]->start = PCIBIOS_MIN_IO;
-		bus->resource[1]->start = PCIBIOS_MIN_MEM;
+	register_pci_controller(&sh5pci_controller);
 
-		/* Turn off downstream PF memory address range by default */
-		bus->resource[2]->start = 1024*1024;
-		bus->resource[2]->end = bus->resource[2]->start - 1;
-	}
+	return 0;
 }
+arch_initcall(sh5pci_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh5.h linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh5.h
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh5.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh5.h	2009-09-09 18:13:59.000000000 -0400
@@ -107,7 +107,4 @@
 
 extern struct pci_ops sh5_pci_ops;
 
-/* arch/sh/drivers/pci/pci-sh5.c */
-int sh5pci_init(unsigned long memStart, unsigned long memSize);
-
 #endif /* __PCI_SH5_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7751.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7751.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7751.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7751.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,88 +1,100 @@
 /*
- *	Low-Level PCI Support for the SH7751
- *
- *  Dustin McIntire (dustin@sensoria.com)
- *	Derived from arch/i386/kernel/pci-*.c which bore the message:
- *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
+ * Low-Level PCI Support for the SH7751
  *
- *  Ported to the new API by Paul Mundt <lethal@linux-sh.org>
- *  With cleanup by Paul van Gool <pvangool@mimotech.com>
+ *  Copyright (C) 2003 - 2009  Paul Mundt
+ *  Copyright (C) 2001  Dustin McIntire
  *
- *  May be copied or modified under the terms of the GNU General Public
- *  License.  See linux/COPYING for more information.
+ *  With cleanup by Paul van Gool <pvangool@mimotech.com>, 2003.
  *
+ * 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.
  */
-#undef DEBUG
-
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/delay.h>
+#include <linux/io.h>
 #include "pci-sh4.h"
 #include <asm/addrspace.h>
-#include <asm/io.h>
-
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space.
- *
- * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the platform defined function
- * pcibios_init_platform().
- */
-static int __init sh7751_pci_init(void)
-{
-	unsigned int id;
-	int ret;
-
-	pr_debug("PCI: Starting intialization.\n");
 
-	/* check for SH7751/SH7751R hardware */
-	id = pci_read_reg(SH7751_PCICONF0);
-	if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
-	    id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
-		pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
-		return -ENODEV;
-	}
-
-	if ((ret = sh4_pci_check_direct()) != 0)
-		return ret;
-
-	return pcibios_init_platform();
-}
-subsys_initcall(sh7751_pci_init);
-
-static int __init __area_sdram_check(unsigned int area)
+static int __init __area_sdram_check(struct pci_channel *chan,
+				     unsigned int area)
 {
-	u32 word;
+	unsigned long word;
 
-	word = ctrl_inl(SH7751_BCR1);
+	word = __raw_readl(SH7751_BCR1);
 	/* check BCR for SDRAM in area */
 	if (((word >> area) & 1) == 0) {
-		printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
+		printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%lx\n",
 		       area, word);
 		return 0;
 	}
-	pci_write_reg(word, SH4_PCIBCR1);
+	pci_write_reg(chan, word, SH4_PCIBCR1);
 
-	word = (u16)ctrl_inw(SH7751_BCR2);
+	word = __raw_readw(SH7751_BCR2);
 	/* check BCR2 for 32bit SDRAM interface*/
 	if (((word >> (area << 1)) & 0x3) != 0x3) {
-		printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
+		printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%lx\n",
 		       area, word);
 		return 0;
 	}
-	pci_write_reg(word, SH4_PCIBCR2);
+	pci_write_reg(chan, word, SH4_PCIBCR2);
 
 	return 1;
 }
 
-int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
+static struct resource sh7751_io_resource = {
+	.name	= "SH7751_IO",
+	.start	= SH7751_PCI_IO_BASE,
+	.end	= SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+	.flags	= IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+	.name	= "SH7751_mem",
+	.start	= SH7751_PCI_MEMORY_BASE,
+	.end	= SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+	.flags	= IORESOURCE_MEM
+};
+
+static struct pci_channel sh7751_pci_controller = {
+	.pci_ops	= &sh4_pci_ops,
+	.mem_resource	= &sh7751_mem_resource,
+	.mem_offset	= 0x00000000,
+	.io_resource	= &sh7751_io_resource,
+	.io_offset	= 0x00000000,
+	.io_map_base	= SH7751_PCI_IO_BASE,
+};
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+	.window0	= {
+		.base	= SH7751_CS3_BASE_ADDR,
+		.size	= 0x04000000,
+	},
+};
+
+static int __init sh7751_pci_init(void)
 {
-	u32 reg;
-	u32 word;
+	struct pci_channel *chan = &sh7751_pci_controller;
+	unsigned int id;
+	u32 word, reg;
+	int ret;
+
+	printk(KERN_NOTICE "PCI: Starting intialization.\n");
+
+	chan->reg_base = 0xfe200000;
+
+	/* check for SH7751/SH7751R hardware */
+	id = pci_read_reg(chan, SH7751_PCICONF0);
+	if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+	    id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+		pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
+		return -ENODEV;
+	}
+
+	if ((ret = sh4_pci_check_direct(chan)) != 0)
+		return ret;
 
 	/* Set the BCR's to enable PCI access */
 	reg = ctrl_inl(SH7751_BCR1);
@@ -90,25 +102,10 @@
 	ctrl_outl(reg, SH7751_BCR1);
 
 	/* Turn the clocks back on (not done in reset)*/
-	pci_write_reg(0, SH4_PCICLKR);
+	pci_write_reg(chan, 0, SH4_PCICLKR);
 	/* Clear Powerdown IRQ's (not done in reset) */
 	word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
-	pci_write_reg(word, SH4_PCIPINT);
-
-	/*
-	 * This code is unused for some boards as it is done in the
-	 * bootloader and doing it here means the MAC addresses loaded
-	 * by the bootloader get lost.
-	 */
-	if (!(map->flags & SH4_PCIC_NO_RESET)) {
-		/* toggle PCI reset pin */
-		word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
-		pci_write_reg(word, SH4_PCICR);
-		/* Wait for a long time... not 1 sec. but long enough */
-		mdelay(100);
-		word = SH4_PCICR_PREFIX;
-		pci_write_reg(word, SH4_PCICR);
-	}
+	pci_write_reg(chan, word, SH4_PCIPINT);
 
 	/* set the command/status bits to:
 	 * Wait Cycle Control + Parity Enable + Bus Master +
@@ -116,89 +113,75 @@
 	 */
 	word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER |
 	       SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
-	pci_write_reg(word, SH7751_PCICONF1);
+	pci_write_reg(chan, word, SH7751_PCICONF1);
 
 	/* define this host as the host bridge */
 	word = PCI_BASE_CLASS_BRIDGE << 24;
-	pci_write_reg(word, SH7751_PCICONF2);
+	pci_write_reg(chan, word, SH7751_PCICONF2);
 
 	/* Set IO and Mem windows to local address
 	 * Make PCI and local address the same for easy 1 to 1 mapping
-	 * Window0 = map->window0.size @ non-cached area base = SDRAM
-	 * Window1 = map->window1.size @ cached area base = SDRAM
 	 */
-	word = map->window0.size - 1;
-	pci_write_reg(word, SH4_PCILSR0);
-	word = map->window1.size - 1;
-	pci_write_reg(word, SH4_PCILSR1);
+	word = sh7751_pci_map.window0.size - 1;
+	pci_write_reg(chan, word, SH4_PCILSR0);
 	/* Set the values on window 0 PCI config registers */
-	word = P2SEGADDR(map->window0.base);
-	pci_write_reg(word, SH4_PCILAR0);
-	pci_write_reg(word, SH7751_PCICONF5);
-	/* Set the values on window 1 PCI config registers */
-	word =  PHYSADDR(map->window1.base);
-	pci_write_reg(word, SH4_PCILAR1);
-	pci_write_reg(word, SH7751_PCICONF6);
+	word = P2SEGADDR(sh7751_pci_map.window0.base);
+	pci_write_reg(chan, word, SH4_PCILAR0);
+	pci_write_reg(chan, word, SH7751_PCICONF5);
 
 	/* Set the local 16MB PCI memory space window to
 	 * the lowest PCI mapped address
 	 */
-	word = PCIBIOS_MIN_MEM & SH4_PCIMBR_MASK;
+	word = chan->mem_resource->start & SH4_PCIMBR_MASK;
 	pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
-	pci_write_reg(word , SH4_PCIMBR);
-
-	/* Map IO space into PCI IO window
-	 * The IO window is 64K-PCIBIOS_MIN_IO in size
-	 * IO addresses will be translated to the
-	 * PCI IO window base address
-	 */
-	pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
-		 PCIBIOS_MIN_IO, (64 << 10),
-		 SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO);
+	pci_write_reg(chan, word , SH4_PCIMBR);
 
 	/* Make sure the MSB's of IO window are set to access PCI space
 	 * correctly */
-	word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
+	word = chan->io_resource->start & SH4_PCIIOBR_MASK;
 	pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
-	pci_write_reg(word, SH4_PCIIOBR);
+	pci_write_reg(chan, word, SH4_PCIIOBR);
 
 	/* Set PCI WCRx, BCRx's, copy from BSC locations */
 
 	/* check BCR for SDRAM in specified area */
-	switch (map->window0.base) {
-	case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(0); break;
-	case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(1); break;
-	case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(2); break;
-	case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(3); break;
-	case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(4); break;
-	case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(5); break;
-	case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(6); break;
+	switch (sh7751_pci_map.window0.base) {
+	case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(chan, 0); break;
+	case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(chan, 1); break;
+	case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(chan, 2); break;
+	case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(chan, 3); break;
+	case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(chan, 4); break;
+	case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(chan, 5); break;
+	case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(chan, 6); break;
 	}
 
 	if (!word)
-		return 0;
+		return -1;
 
 	/* configure the wait control registers */
 	word = ctrl_inl(SH7751_WCR1);
-	pci_write_reg(word, SH4_PCIWCR1);
+	pci_write_reg(chan, word, SH4_PCIWCR1);
 	word = ctrl_inl(SH7751_WCR2);
-	pci_write_reg(word, SH4_PCIWCR2);
+	pci_write_reg(chan, word, SH4_PCIWCR2);
 	word = ctrl_inl(SH7751_WCR3);
-	pci_write_reg(word, SH4_PCIWCR3);
+	pci_write_reg(chan, word, SH4_PCIWCR3);
 	word = ctrl_inl(SH7751_MCR);
-	pci_write_reg(word, SH4_PCIMCR);
+	pci_write_reg(chan, word, SH4_PCIMCR);
 
 	/* NOTE: I'm ignoring the PCI error IRQs for now..
 	 * TODO: add support for the internal error interrupts and
 	 * DMA interrupts...
 	 */
 
-	pci_fixup_pcic();
+	pci_fixup_pcic(chan);
 
 	/* SH7751 init done, set central function init complete */
 	/* use round robin mode to stop a device starving/overruning */
 	word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
-	pci_write_reg(word, SH4_PCICR);
+	pci_write_reg(chan, word, SH4_PCICR);
 
-	return 1;
+	register_pci_controller(chan);
+
+	return 0;
 }
+arch_initcall(sh7751_pci_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7751.h linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7751.h
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7751.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7751.h	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,6 @@
 #define SH7751_PCI_IO_SIZE           0x40000     /* Size of IO window */
 
 #define SH7751_PCIREG_BASE           0xFE200000  /* PCI regs base address */
-#define PCI_REG(n)                  (SH7751_PCIREG_BASE+ n)
 
 #define SH7751_PCICONF0            0x0           /* PCI Config Reg 0 */
   #define SH7751_PCICONF0_DEVID      0xFFFF0000  /* Device ID */
@@ -58,7 +57,7 @@
   #define SH7751_PCICONF2_SCC        0x00FF0000  /* Sub-Class Code */
   #define SH7751_PCICONF2_RLPI       0x0000FF00  /* Programming Interface */
   #define SH7751_PCICONF2_REV        0x000000FF  /* Revision ID */
-#define SH7751_PCICONF3            0xC           /* PCI Config Reg 3 */ 
+#define SH7751_PCICONF3            0xC           /* PCI Config Reg 3 */
   #define SH7751_PCICONF3_BIST7      0x80000000  /* Bist Supported */
   #define SH7751_PCICONF3_BIST6      0x40000000  /* Bist Executing */
   #define SH7751_PCICONF3_BIST3_0    0x0F000000  /* Bist Passed */
@@ -73,12 +72,12 @@
   #define SH7751_PCICONF5_BASE       0xFFFFFFF0  /* Mem Space Base Addr */
   #define SH7751_PCICONF5_LAP        0x00000008  /* Prefetch Enabled */
   #define SH7751_PCICONF5_LAT        0x00000006  /* Local Memory type */
-  #define SH7751_PCICONF5_ASI        0x00000001  /* Address Space Type */  
+  #define SH7751_PCICONF5_ASI        0x00000001  /* Address Space Type */
 #define SH7751_PCICONF6            0x18          /* PCI Config Reg 6 */
   #define SH7751_PCICONF6_BASE       0xFFFFFFF0  /* Mem Space Base Addr */
   #define SH7751_PCICONF6_LAP        0x00000008  /* Prefetch Enabled */
   #define SH7751_PCICONF6_LAT        0x00000006  /* Local Memory type */
-  #define SH7751_PCICONF6_ASI        0x00000001  /* Address Space Type */  
+  #define SH7751_PCICONF6_ASI        0x00000001  /* Address Space Type */
 /* PCICONF7 - PCICONF10 are undefined */
 #define SH7751_PCICONF11           0x2C          /* PCI Config Reg 11 */
   #define SH7751_PCICONF11_SSID      0xFFFF0000  /* Subsystem ID */
@@ -127,9 +126,4 @@
 #define SH7751_CS5_BASE_ADDR       (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
 #define SH7751_CS6_BASE_ADDR       (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
 
-struct sh4_pci_address_map;
-
-/* arch/sh/drivers/pci/pci-sh7751.c */
-int sh7751_pcic_init(struct sh4_pci_address_map *map);
-
 #endif /* _PCI_SH7751_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7780.c linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7780.c
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7780.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,19 +1,12 @@
 /*
- *	Low-Level PCI Support for the SH7780
- *
- *  Dustin McIntire (dustin@sensoria.com)
- *	Derived from arch/i386/kernel/pci-*.c which bore the message:
- *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
- *
- *  Ported to the new API by Paul Mundt <lethal@linux-sh.org>
- *  With cleanup by Paul van Gool <pvangool@mimotech.com>
+ * Low-Level PCI Support for the SH7780
  *
- *  May be copied or modified under the terms of the GNU General Public
- *  License.  See linux/COPYING for more information.
+ *  Copyright (C) 2005 - 2009  Paul Mundt
  *
+ * 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.
  */
-#undef DEBUG
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -22,135 +15,132 @@
 #include <linux/delay.h>
 #include "pci-sh4.h"
 
-#define INTC_BASE	0xffd00000
-#define INTC_ICR0	(INTC_BASE+0x0)
-#define INTC_ICR1	(INTC_BASE+0x1c)
-#define INTC_INTPRI	(INTC_BASE+0x10)
-#define INTC_INTREQ	(INTC_BASE+0x24)
-#define INTC_INTMSK0	(INTC_BASE+0x44)
-#define INTC_INTMSK1	(INTC_BASE+0x48)
-#define INTC_INTMSK2	(INTC_BASE+0x40080)
-#define INTC_INTMSKCLR0	(INTC_BASE+0x64)
-#define INTC_INTMSKCLR1	(INTC_BASE+0x68)
-#define INTC_INTMSKCLR2	(INTC_BASE+0x40084)
-#define INTC_INT2MSKR	(INTC_BASE+0x40038)
-#define INTC_INT2MSKCR	(INTC_BASE+0x4003c)
+static struct resource sh7785_io_resource = {
+	.name	= "SH7785_IO",
+	.start	= SH7780_PCI_IO_BASE,
+	.end	= SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1,
+	.flags	= IORESOURCE_IO
+};
+
+static struct resource sh7785_mem_resource = {
+	.name	= "SH7785_mem",
+	.start	= SH7780_PCI_MEMORY_BASE,
+	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+	.flags	= IORESOURCE_MEM
+};
+
+static struct pci_channel sh7780_pci_controller = {
+	.pci_ops	= &sh4_pci_ops,
+	.mem_resource	= &sh7785_mem_resource,
+	.mem_offset	= 0x00000000,
+	.io_resource	= &sh7785_io_resource,
+	.io_offset	= 0x00000000,
+	.io_map_base	= SH7780_PCI_IO_BASE,
+};
+
+static struct sh4_pci_address_map sh7780_pci_map = {
+	.window0	= {
+#if defined(CONFIG_32BIT)
+		.base	= SH7780_32BIT_DDR_BASE_ADDR,
+		.size	= 0x40000000,
+#else
+		.base	= SH7780_CS0_BASE_ADDR,
+		.size	= 0x20000000,
+#endif
+	},
+};
 
-/*
- * Initialization. Try all known PCI access methods. Note that we support
- * using both PCI BIOS and direct access: in such cases, we use I/O ports
- * to access config space.
- *
- * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the platform defined function
- * pcibios_init_platform().
- */
 static int __init sh7780_pci_init(void)
 {
+	struct pci_channel *chan = &sh7780_pci_controller;
 	unsigned int id;
-	int ret, match = 0;
+	const char *type = NULL;
+	int ret;
+	u32 word;
 
-	pr_debug("PCI: Starting intialization.\n");
+	printk(KERN_NOTICE "PCI: Starting intialization.\n");
 
-	ctrl_outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
+	chan->reg_base = 0xfe040000;
 
-	/* check for SH7780/SH7780R hardware */
-	id = pci_read_reg(SH7780_PCIVID);
-	if ((id & 0xffff) == SH7780_VENDOR_ID) {
-		switch ((id >> 16) & 0xffff) {
-		case SH7763_DEVICE_ID:
-		case SH7780_DEVICE_ID:
-		case SH7781_DEVICE_ID:
-		case SH7785_DEVICE_ID:
-			match = 1;
-			break;
-		}
-	}
+	/* Enable CPU access to the PCIC registers. */
+	__raw_writel(PCIECR_ENBL, PCIECR);
 
-	if (unlikely(!match)) {
-		printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
+	id = __raw_readw(chan->reg_base + SH7780_PCIVID);
+	if (id != SH7780_VENDOR_ID) {
+		printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
 		return -ENODEV;
 	}
 
-	/* Setup the INTC */
-	if (mach_is_7780se()) {
-		/* ICR0: IRL=use separately */
-		ctrl_outl(0x00C00020, INTC_ICR0);
-		/* ICR1: detect low level(for 2ndcut) */
-		ctrl_outl(0xAAAA0000, INTC_ICR1);
-		/* INTPRI: priority=3(all) */
-		ctrl_outl(0x33333333, INTC_INTPRI);
+	id = __raw_readw(chan->reg_base + SH7780_PCIDID);
+	type = (id == SH7763_DEVICE_ID)	? "SH7763" :
+	       (id == SH7780_DEVICE_ID) ? "SH7780" :
+	       (id == SH7781_DEVICE_ID) ? "SH7781" :
+	       (id == SH7785_DEVICE_ID) ? "SH7785" :
+					  NULL;
+	if (unlikely(!type)) {
+		printk(KERN_ERR "PCI: Found an unsupported Renesas host "
+		       "controller, device id 0x%04x.\n", id);
+		return -EINVAL;
 	}
 
-	if ((ret = sh4_pci_check_direct()) != 0)
-		return ret;
-
-	return pcibios_init_platform();
-}
-core_initcall(sh7780_pci_init);
+	printk(KERN_NOTICE "PCI: Found a Renesas %s host "
+	       "controller, revision %d.\n", type,
+	       __raw_readb(chan->reg_base + SH7780_PCIRID));
 
-int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
-{
-	u32 word;
+	if ((ret = sh4_pci_check_direct(chan)) != 0)
+		return ret;
 
 	/*
-	 * This code is unused for some boards as it is done in the
-	 * bootloader and doing it here means the MAC addresses loaded
-	 * by the bootloader get lost.
-	 */
-	if (!(map->flags & SH4_PCIC_NO_RESET)) {
-		/* toggle PCI reset pin */
-		word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
-		pci_write_reg(word, SH4_PCICR);
-		/* Wait for a long time... not 1 sec. but long enough */
-		mdelay(100);
-		word = SH4_PCICR_PREFIX;
-		pci_write_reg(word, SH4_PCICR);
-	}
-
-	/* set the command/status bits to:
-	 * Wait Cycle Control + Parity Enable + Bus Master +
-	 * Mem space enable
+	 * Set the class and sub-class codes.
 	 */
-	pci_write_reg(0x00000046, SH7780_PCICMD);
-
-	/* define this host as the host bridge */
-	word = PCI_BASE_CLASS_BRIDGE << 24;
-	pci_write_reg(word, SH7780_PCIRID);
+	__raw_writeb(PCI_CLASS_BRIDGE_HOST >> 8,
+		     chan->reg_base + SH7780_PCIBCC);
+	__raw_writeb(PCI_CLASS_BRIDGE_HOST & 0xff,
+		     chan->reg_base + SH7780_PCISUB);
 
-	/* Set IO and Mem windows to local address
+	/*
+	 * Set IO and Mem windows to local address
 	 * Make PCI and local address the same for easy 1 to 1 mapping
 	 */
-	pci_write_reg(map->window0.size - 0xfffff, SH4_PCILSR0);
-	pci_write_reg(map->window1.size - 0xfffff, SH4_PCILSR1);
+	pci_write_reg(chan, sh7780_pci_map.window0.size - 0xfffff, SH4_PCILSR0);
 	/* Set the values on window 0 PCI config registers */
-	pci_write_reg(map->window0.base, SH4_PCILAR0);
-	pci_write_reg(map->window0.base, SH7780_PCIMBAR0);
-	/* Set the values on window 1 PCI config registers */
-	pci_write_reg(map->window1.base, SH4_PCILAR1);
-	pci_write_reg(map->window1.base, SH7780_PCIMBAR1);
+	pci_write_reg(chan, sh7780_pci_map.window0.base, SH4_PCILAR0);
+	pci_write_reg(chan, sh7780_pci_map.window0.base, SH7780_PCIMBAR0);
 
-	/* Map IO space into PCI IO window
-	 * The IO window is 64K-PCIBIOS_MIN_IO in size
-	 * IO addresses will be translated to the
-	 * PCI IO window base address
-	 */
-	pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
-		 PCIBIOS_MIN_IO, (64 << 10),
-		 SH7780_PCI_IO_BASE + PCIBIOS_MIN_IO);
+	pci_write_reg(chan, 0x0000380f, SH4_PCIAINTM);
 
-	/* NOTE: I'm ignoring the PCI error IRQs for now..
-	 * TODO: add support for the internal error interrupts and
-	 * DMA interrupts...
-	 */
+	/* Set up standard PCI config registers */
+	__raw_writew(0xFB00, chan->reg_base + SH7780_PCISTATUS);
+	__raw_writew(0x0047, chan->reg_base + SH7780_PCICMD);
+	__raw_writew(0x1912, chan->reg_base + SH7780_PCISVID);
+	__raw_writew(0x0001, chan->reg_base + SH7780_PCISID);
+
+	__raw_writeb(0x00, chan->reg_base + SH7780_PCIPIF);
 
 	/* Apply any last-minute PCIC fixups */
-	pci_fixup_pcic();
+	pci_fixup_pcic(chan);
+
+	pci_write_reg(chan, 0xfd000000, SH7780_PCIMBR0);
+	pci_write_reg(chan, 0x00fc0000, SH7780_PCIMBMR0);
+
+#ifdef CONFIG_32BIT
+	pci_write_reg(chan, 0xc0000000, SH7780_PCIMBR2);
+	pci_write_reg(chan, 0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
+#endif
+
+	/* Set IOBR for windows containing area specified in pci.h */
+	pci_write_reg(chan, chan->io_resource->start & ~(SH7780_PCI_IO_SIZE-1),
+		      SH7780_PCIIOBR);
+	pci_write_reg(chan, ((SH7780_PCI_IO_SIZE-1) & (7<<18)),
+		      SH7780_PCIIOBMR);
 
 	/* SH7780 init done, set central function init complete */
 	/* use round robin mode to stop a device starving/overruning */
 	word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO;
-	pci_write_reg(word, SH4_PCICR);
+	pci_write_reg(chan, word, SH4_PCICR);
 
-	return 1;
+	register_pci_controller(chan);
+
+	return 0;
 }
+arch_initcall(sh7780_pci_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7780.h linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7780.h
--- linux-libre-2.6.30-gnu/arch/sh/drivers/pci/pci-sh7780.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/drivers/pci/pci-sh7780.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,9 +20,8 @@
 #define SH7785_DEVICE_ID	0x0007
 
 /* SH7780 Control Registers */
-#define	SH7780_PCI_VCR0		0xFE000000
-#define	SH7780_PCI_VCR1		0xFE000004
-#define	SH7780_PCI_VCR2		0xFE000008
+#define	PCIECR			0xFE000008
+#define PCIECR_ENBL		0x01
 
 /* SH7780 Specific Values */
 #define SH7780_PCI_CONFIG_BASE	0xFD000000	/* Config space base addr */
@@ -35,7 +34,6 @@
 #define SH7780_PCI_IO_SIZE	0x00400000	/* Size of IO window */
 
 #define SH7780_PCIREG_BASE	0xFE040000	/* PCI regs base address */
-#define PCI_REG(n)		(SH7780_PCIREG_BASE+n)
 
 /* SH7780 PCI Config Registers */
 #define SH7780_PCIVID		0x000		/* Vendor ID */
@@ -67,11 +65,6 @@
 #define SH7780_PCIPMCSR_BSE	0x046
 #define SH7780_PCICDD		0x047
 
-#define SH7780_PCICR		0x100		/* PCI Control Register */
-#define SH7780_PCILSR		0x104		/* PCI Local Space Register0 */
-#define SH7780_PCILSR1		0x108		/* PCI Local Space Register1 */
-#define SH7780_PCILAR0		0x10C		/* PCI Local Address Register1 */
-#define SH7780_PCILAR1		0x110		/* PCI Local Address Register1 */
 #define SH7780_PCIIR		0x114		/* PCI Interrupt Register */
 #define SH7780_PCIIMR		0x118		/* PCI Interrupt Mask Register */
 #define SH7780_PCIAIR		0x11C		/* Error Address Register */
@@ -106,9 +99,4 @@
 
 #define SH7780_32BIT_DDR_BASE_ADDR	0x40000000
 
-struct sh4_pci_address_map;
-
-/* arch/sh/drivers/pci/pci-sh7780.c */
-int sh7780_pcic_init(struct sh4_pci_address_map *map);
-
 #endif /* _PCI_SH7780_H_ */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/sh/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -45,7 +45,7 @@
 #define atomic_inc(v) atomic_add(1,(v))
 #define atomic_dec(v) atomic_sub(1,(v))
 
-#ifndef CONFIG_GUSA_RB
+#if !defined(CONFIG_GUSA_RB) && !defined(CONFIG_CPU_SH4A)
 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 {
 	int ret;
@@ -73,7 +73,7 @@
 
 	return ret != u;
 }
-#endif
+#endif /* !CONFIG_GUSA_RB && !CONFIG_CPU_SH4A */
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
@@ -84,5 +84,7 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
+#include <asm-generic/atomic64.h>
+
 #endif /* __ASM_SH_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/atomic-irq.h linux-libre-2.6.31-gnu/arch/sh/include/asm/atomic-irq.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/atomic-irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/atomic-irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,29 +10,29 @@
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	v->counter += i;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 static inline void atomic_sub(int i, atomic_t *v)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	v->counter -= i;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 static inline int atomic_add_return(int i, atomic_t *v)
 {
 	unsigned long temp, flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	temp = v->counter;
 	temp += i;
 	v->counter = temp;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return temp;
 }
@@ -41,11 +41,11 @@
 {
 	unsigned long temp, flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	temp = v->counter;
 	temp -= i;
 	v->counter = temp;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 
 	return temp;
 }
@@ -54,18 +54,18 @@
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	v->counter &= ~mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
 	unsigned long flags;
 
-	local_irq_save(flags);
+	raw_local_irq_save(flags);
 	v->counter |= mask;
-	local_irq_restore(flags);
+	raw_local_irq_restore(flags);
 }
 
 #endif /* __ASM_SH_ATOMIC_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/atomic-llsc.h linux-libre-2.6.31-gnu/arch/sh/include/asm/atomic-llsc.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/atomic-llsc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/atomic-llsc.h	2009-09-09 18:13:59.000000000 -0400
@@ -104,4 +104,31 @@
 	: "t");
 }
 
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int c, old;
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+
+	return c != (u);
+}
+
 #endif /* __ASM_SH_ATOMIC_LLSC_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/sh/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/cacheflush.h linux-libre-2.6.31-gnu/arch/sh/include/asm/cacheflush.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/cacheflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/cacheflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -75,7 +75,5 @@
 #define flush_cache_vmap(start, end)		flush_cache_all()
 #define flush_cache_vunmap(start, end)		flush_cache_all()
 
-#define HAVE_ARCH_UNMAPPED_AREA
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/checksum_64.h linux-libre-2.6.31-gnu/arch/sh/include/asm/checksum_64.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/checksum_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/checksum_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-#ifndef __ASM_SH_CHECKSUM_64_H
-#define __ASM_SH_CHECKSUM_64_H
-
-/*
- * include/asm-sh/checksum_64.h
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- * 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.
- */
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions.
- *
- *	If you use these functions directly please don't forget the
- *	access_ok().
- */
-
-
-__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len,
-				       __wsum sum);
-
-__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-					 int len, __wsum sum, int *err_ptr);
-
-static inline __sum16 csum_fold(__wsum csum)
-{
-	u32 sum = (__force u32)csum;
-        sum = (sum & 0xffff) + (sum >> 16);
-        sum = (sum & 0xffff) + (sum >> 16);
-        return (__force __sum16)~sum;
-}
-
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-				 unsigned short len, unsigned short proto,
-				 __wsum sum);
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-	return csum_fold(csum_partial(buff, len, 0));
-}
-
-#endif /* __ASM_SH_CHECKSUM_64_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/checksum.h linux-libre-2.6.31-gnu/arch/sh/include/asm/checksum.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/checksum.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/checksum.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 #ifdef CONFIG_SUPERH32
 # include "checksum_32.h"
 #else
-# include "checksum_64.h"
+# include <asm-generic/checksum.h>
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/clock.h linux-libre-2.6.31-gnu/arch/sh/include/asm/clock.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/clock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/clock.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,9 +1,9 @@
 #ifndef __ASM_SH_CLOCK_H
 #define __ASM_SH_CLOCK_H
 
-#include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/seq_file.h>
+#include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 
@@ -11,9 +11,9 @@
 
 struct clk_ops {
 	void (*init)(struct clk *clk);
-	void (*enable)(struct clk *clk);
+	int (*enable)(struct clk *clk);
 	void (*disable)(struct clk *clk);
-	void (*recalc)(struct clk *clk);
+	unsigned long (*recalc)(struct clk *clk);
 	int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id);
 	int (*set_parent)(struct clk *clk, struct clk *parent);
 	long (*round_rate)(struct clk *clk, unsigned long rate);
@@ -28,43 +28,47 @@
 	struct clk		*parent;
 	struct clk_ops		*ops;
 
-	struct kref		kref;
+	struct list_head	children;
+	struct list_head	sibling;	/* node for children */
+
+	int			usecount;
 
 	unsigned long		rate;
 	unsigned long		flags;
+
+	void __iomem		*enable_reg;
+	unsigned int		enable_bit;
+
 	unsigned long		arch_flags;
+	void			*priv;
+	struct dentry		*dentry;
+	struct cpufreq_frequency_table *freq_table;
 };
 
-#define CLK_ALWAYS_ENABLED	(1 << 0)
-#define CLK_RATE_PROPAGATES	(1 << 1)
+struct clk_lookup {
+	struct list_head	node;
+	const char		*dev_id;
+	const char		*con_id;
+	struct clk		*clk;
+};
+
+#define CLK_ENABLE_ON_INIT	(1 << 0)
 
 /* Should be defined by processor-specific code */
-void arch_init_clk_ops(struct clk_ops **, int type);
+void __deprecated arch_init_clk_ops(struct clk_ops **, int type);
 int __init arch_clk_init(void);
 
 /* arch/sh/kernel/cpu/clock.c */
 int clk_init(void);
-
-void clk_recalc_rate(struct clk *);
-
+unsigned long followparent_recalc(struct clk *);
+void recalculate_root_clocks(void);
+void propagate_rate(struct clk *);
+int clk_reparent(struct clk *child, struct clk *parent);
 int clk_register(struct clk *);
 void clk_unregister(struct clk *);
 
-static inline int clk_always_enable(const char *id)
-{
-	struct clk *clk;
-	int ret;
-
-	clk = clk_get(NULL, id);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	ret = clk_enable(clk);
-	if (ret)
-		clk_put(clk);
-
-	return ret;
-}
+/* arch/sh/kernel/cpu/clock-cpg.c */
+int __init __deprecated cpg_clk_init(void);
 
 /* the exported API, in addition to clk_set_rate */
 /**
@@ -96,4 +100,63 @@
 
 	IP_N1,
 };
+
+struct clk_div_mult_table {
+	unsigned int *divisors;
+	unsigned int nr_divisors;
+	unsigned int *multipliers;
+	unsigned int nr_multipliers;
+};
+
+struct cpufreq_frequency_table;
+void clk_rate_table_build(struct clk *clk,
+			  struct cpufreq_frequency_table *freq_table,
+			  int nr_freqs,
+			  struct clk_div_mult_table *src_table,
+			  unsigned long *bitmap);
+
+long clk_rate_table_round(struct clk *clk,
+			  struct cpufreq_frequency_table *freq_table,
+			  unsigned long rate);
+
+int clk_rate_table_find(struct clk *clk,
+			struct cpufreq_frequency_table *freq_table,
+			unsigned long rate);
+
+#define SH_CLK_MSTP32(_name, _id, _parent, _enable_reg,	\
+	    _enable_bit, _flags)			\
+{							\
+	.name		= _name,			\
+	.id		= _id,				\
+	.parent		= _parent,			\
+	.enable_reg	= (void __iomem *)_enable_reg,	\
+	.enable_bit	= _enable_bit,			\
+	.flags		= _flags,			\
+}
+
+int sh_clk_mstp32_register(struct clk *clks, int nr);
+
+#define SH_CLK_DIV4(_name, _parent, _reg, _shift, _div_bitmap, _flags)	\
+{									\
+	.name = _name,							\
+	.parent = _parent,						\
+	.enable_reg = (void __iomem *)_reg,				\
+	.enable_bit = _shift,						\
+	.arch_flags = _div_bitmap,					\
+	.flags = _flags,						\
+}
+
+int sh_clk_div4_register(struct clk *clks, int nr,
+			 struct clk_div_mult_table *table);
+
+#define SH_CLK_DIV6(_name, _parent, _reg, _flags)	\
+{							\
+	.name = _name,					\
+	.parent = _parent,				\
+	.enable_reg = (void __iomem *)_reg,		\
+	.flags = _flags,				\
+}
+
+int sh_clk_div6_register(struct clk *clks, int nr);
+
 #endif /* __ASM_SH_CLOCK_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/cmpxchg-llsc.h linux-libre-2.6.31-gnu/arch/sh/include/asm/cmpxchg-llsc.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/cmpxchg-llsc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/cmpxchg-llsc.h	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,7 @@
 		"mov		%0, %1				\n\t"
 		"cmp/eq		%1, %3				\n\t"
 		"bf		2f				\n\t"
-		"mov		%3, %0				\n\t"
+		"mov		%4, %0				\n\t"
 		"2:						\n\t"
 		"movco.l	%0, @%2				\n\t"
 		"bf		1b				\n\t"
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/current.h linux-libre-2.6.31-gnu/arch/sh/include/asm/current.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/current.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/current.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,20 +1 @@
-#ifndef __ASM_SH_CURRENT_H
-#define __ASM_SH_CURRENT_H
-
-/*
- * Copyright (C) 1999 Niibe Yutaka
- *
- */
-
-#include <linux/thread_info.h>
-
-struct task_struct;
-
-static __inline__ struct task_struct * get_current(void)
-{
-	return current_thread_info()->task;
-}
-
-#define current get_current()
-
-#endif /* __ASM_SH_CURRENT_H */
+#include <asm-generic/current.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/device.h linux-libre-2.6.31-gnu/arch/sh/include/asm/device.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/device.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/device.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,3 +10,5 @@
 int platform_resource_setup_memory(struct platform_device *pdev,
 				   char *name, unsigned long memsize);
 
+void plat_early_device_setup(void);
+
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/dma.h linux-libre-2.6.31-gnu/arch/sh/include/asm/dma.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/dma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/dma.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,13 +16,7 @@
 #include <linux/sched.h>
 #include <linux/sysdev.h>
 #include <cpu/dma.h>
-
-/* The maximum address that we can perform a DMA transfer to on this platform */
-/* Don't define MAX_DMA_ADDRESS; it's useless on the SuperH and any
-   occurrence should be flagged as an error.  */
-/* But... */
-/* XXX: This is not applicable to SuperH, just needed for alloc_bootmem */
-#define MAX_DMA_ADDRESS		(PAGE_OFFSET+0x10000000)
+#include <asm-generic/dma.h>
 
 #ifdef CONFIG_NR_DMA_CHANNELS
 #  define MAX_DMA_CHANNELS   (CONFIG_NR_DMA_CHANNELS)
@@ -137,8 +131,6 @@
 
 extern int request_dma_bycap(const char **dmac, const char **caps,
 			     const char *dev_id);
-extern int request_dma(unsigned int chan, const char *dev_id);
-extern void free_dma(unsigned int chan);
 extern int get_dma_residue(unsigned int chan);
 extern struct dma_info *get_dma_info(unsigned int chan);
 extern struct dma_channel *get_dma_channel(unsigned int chan);
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/sh/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -97,7 +97,7 @@
 	dma_unmap_single(dev, dma_address, size, dir);
 }
 
-static inline void dma_sync_single(struct device *dev, dma_addr_t dma_handle,
+static inline void __dma_sync_single(struct device *dev, dma_addr_t dma_handle,
 				   size_t size, enum dma_data_direction dir)
 {
 #if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT)
@@ -119,7 +119,7 @@
 	dma_cache_sync(dev, phys_to_virt(dma_handle) + offset, size, dir);
 }
 
-static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
+static inline void __dma_sync_sg(struct device *dev, struct scatterlist *sg,
 			       int nelems, enum dma_data_direction dir)
 {
 	int i;
@@ -137,7 +137,7 @@
 					   dma_addr_t dma_handle, size_t size,
 					   enum dma_data_direction dir)
 {
-	dma_sync_single(dev, dma_handle, size, dir);
+	__dma_sync_single(dev, dma_handle, size, dir);
 	debug_dma_sync_single_for_cpu(dev, dma_handle, size, dir);
 }
 
@@ -146,7 +146,7 @@
 					      size_t size,
 					      enum dma_data_direction dir)
 {
-	dma_sync_single(dev, dma_handle, size, dir);
+	__dma_sync_single(dev, dma_handle, size, dir);
 	debug_dma_sync_single_for_device(dev, dma_handle, size, dir);
 }
 
@@ -177,7 +177,7 @@
 				       struct scatterlist *sg, int nelems,
 				       enum dma_data_direction dir)
 {
-	dma_sync_sg(dev, sg, nelems, dir);
+	__dma_sync_sg(dev, sg, nelems, dir);
 	debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir);
 }
 
@@ -185,7 +185,7 @@
 					  struct scatterlist *sg, int nelems,
 					  enum dma_data_direction dir)
 {
-	dma_sync_sg(dev, sg, nelems, dir);
+	__dma_sync_sg(dev, sg, nelems, dir);
 	debug_dma_sync_sg_for_device(dev, sg, nelems, dir);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/hd64461.h linux-libre-2.6.31-gnu/arch/sh/include/asm/hd64461.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/hd64461.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/hd64461.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,18 +13,20 @@
 #define	HD64461_PCC_WINDOW	0x01000000
 
 /* Area 6 - Slot 0 - memory and/or IO card */
-#define	HD64461_PCC0_BASE	(CONFIG_HD64461_IOBASE + 0x8000000)
+#define HD64461_IOBASE		0xb0000000
+#define HD64461_IO_OFFSET(x)	(HD64461_IOBASE + (x))
+#define	HD64461_PCC0_BASE	HD64461_IO_OFFSET(0x8000000)
 #define	HD64461_PCC0_ATTR	(HD64461_PCC0_BASE)				/* 0xb80000000 */
 #define	HD64461_PCC0_COMM	(HD64461_PCC0_BASE+HD64461_PCC_WINDOW)		/* 0xb90000000 */
 #define	HD64461_PCC0_IO		(HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW)	/* 0xba0000000 */
 
 /* Area 5 - Slot 1 - memory card only */
-#define	HD64461_PCC1_BASE	(CONFIG_HD64461_IOBASE + 0x4000000)
+#define	HD64461_PCC1_BASE	HD64461_IO_OFFSET(0x4000000)
 #define	HD64461_PCC1_ATTR	(HD64461_PCC1_BASE)				/* 0xb4000000 */
 #define	HD64461_PCC1_COMM	(HD64461_PCC1_BASE+HD64461_PCC_WINDOW)		/* 0xb5000000 */
 
 /* Standby Control Register for HD64461 */
-#define	HD64461_STBCR			CONFIG_HD64461_IOBASE
+#define	HD64461_STBCR			HD64461_IO_OFFSET(0x00000000)
 #define	HD64461_STBCR_CKIO_STBY		0x2000
 #define	HD64461_STBCR_SAFECKE_IST	0x1000
 #define	HD64461_STBCR_SLCKE_IST		0x0800
@@ -41,19 +43,19 @@
 #define	HD64461_STBCR_SURTST		0x0001
 
 /* System Configuration Register */
-#define	HD64461_SYSCR		(CONFIG_HD64461_IOBASE + 0x02)
+#define	HD64461_SYSCR		HD64461_IO_OFFSET(0x02)
 
 /* CPU Data Bus Control Register */
-#define	HD64461_SCPUCR		(CONFIG_HD64461_IOBASE + 0x04)
+#define	HD64461_SCPUCR		HD64461_IO_OFFSET(0x04)
 
 /* Base Address Register */
-#define	HD64461_LCDCBAR		(CONFIG_HD64461_IOBASE + 0x1000)
+#define	HD64461_LCDCBAR		HD64461_IO_OFFSET(0x1000)
 
 /* Line increment address */
-#define	HD64461_LCDCLOR		(CONFIG_HD64461_IOBASE + 0x1002)
+#define	HD64461_LCDCLOR		HD64461_IO_OFFSET(0x1002)
 
 /* Controls LCD controller */
-#define	HD64461_LCDCCR		(CONFIG_HD64461_IOBASE + 0x1004)
+#define	HD64461_LCDCCR		HD64461_IO_OFFSET(0x1004)
 
 /* LCCDR control bits */
 #define	HD64461_LCDCCR_STBACK	0x0400	/* Standby Back */
@@ -64,30 +66,30 @@
 #define	HD64461_LCDCCR_SPON	0x0010	/* Start Power On */
 
 /* Controls LCD (1) */
-#define	HD64461_LDR1		(CONFIG_HD64461_IOBASE + 0x1010)
+#define	HD64461_LDR1		HD64461_IO_OFFSET(0x1010)
 #define	HD64461_LDR1_DON	0x01	/* Display On */
 #define	HD64461_LDR1_DINV	0x80	/* Display Invert */
 
 /* Controls LCD (2) */
-#define	HD64461_LDR2		(CONFIG_HD64461_IOBASE + 0x1012)
-#define	HD64461_LDHNCR		(CONFIG_HD64461_IOBASE + 0x1014)	/* Number of horizontal characters */
-#define	HD64461_LDHNSR		(CONFIG_HD64461_IOBASE + 0x1016)	/* Specify output start position + width of CL1 */
-#define	HD64461_LDVNTR		(CONFIG_HD64461_IOBASE + 0x1018)	/* Specify total vertical lines */
-#define	HD64461_LDVNDR		(CONFIG_HD64461_IOBASE + 0x101a)	/* specify number of display vertical lines */
-#define	HD64461_LDVSPR		(CONFIG_HD64461_IOBASE + 0x101c)	/* specify vertical synchronization pos and AC nr */
+#define	HD64461_LDR2		HD64461_IO_OFFSET(0x1012)
+#define	HD64461_LDHNCR		HD64461_IO_OFFSET(0x1014)	/* Number of horizontal characters */
+#define	HD64461_LDHNSR		HD64461_IO_OFFSET(0x1016)	/* Specify output start position + width of CL1 */
+#define	HD64461_LDVNTR		HD64461_IO_OFFSET(0x1018)	/* Specify total vertical lines */
+#define	HD64461_LDVNDR		HD64461_IO_OFFSET(0x101a)	/* specify number of display vertical lines */
+#define	HD64461_LDVSPR		HD64461_IO_OFFSET(0x101c)	/* specify vertical synchronization pos and AC nr */
 
 /* Controls LCD (3) */
-#define	HD64461_LDR3		(CONFIG_HD64461_IOBASE + 0x101e)
+#define	HD64461_LDR3		HD64461_IO_OFFSET(0x101e)
 
 /* Palette Registers */
-#define	HD64461_CPTWAR		(CONFIG_HD64461_IOBASE + 0x1030)	/* Color Palette Write Address Register */
-#define	HD64461_CPTWDR		(CONFIG_HD64461_IOBASE + 0x1032)	/* Color Palette Write Data Register */
-#define	HD64461_CPTRAR		(CONFIG_HD64461_IOBASE + 0x1034)	/* Color Palette Read Address Register */
-#define	HD64461_CPTRDR		(CONFIG_HD64461_IOBASE + 0x1036)	/* Color Palette Read Data Register */
+#define	HD64461_CPTWAR		HD64461_IO_OFFSET(0x1030)	/* Color Palette Write Address Register */
+#define	HD64461_CPTWDR		HD64461_IO_OFFSET(0x1032)	/* Color Palette Write Data Register */
+#define	HD64461_CPTRAR		HD64461_IO_OFFSET(0x1034)	/* Color Palette Read Address Register */
+#define	HD64461_CPTRDR		HD64461_IO_OFFSET(0x1036)	/* Color Palette Read Data Register */
 
-#define	HD64461_GRDOR		(CONFIG_HD64461_IOBASE + 0x1040)	/* Display Resolution Offset Register */
-#define	HD64461_GRSCR		(CONFIG_HD64461_IOBASE + 0x1042)	/* Solid Color Register */
-#define	HD64461_GRCFGR		(CONFIG_HD64461_IOBASE + 0x1044)	/* Accelerator Configuration Register */
+#define	HD64461_GRDOR		HD64461_IO_OFFSET(0x1040)	/* Display Resolution Offset Register */
+#define	HD64461_GRSCR		HD64461_IO_OFFSET(0x1042)	/* Solid Color Register */
+#define	HD64461_GRCFGR		HD64461_IO_OFFSET(0x1044)	/* Accelerator Configuration Register */
 
 #define	HD64461_GRCFGR_ACCSTATUS	0x10	/* Accelerator Status */
 #define	HD64461_GRCFGR_ACCRESET		0x08	/* Accelerator Reset */
@@ -97,41 +99,41 @@
 #define	HD64461_GRCFGR_COLORDEPTH8	0x01	/* Sets Colordepth 8 for Accelerator */
 
 /* Line Drawing Registers */
-#define	HD64461_LNSARH		(CONFIG_HD64461_IOBASE + 0x1046)	/* Line Start Address Register (H) */
-#define	HD64461_LNSARL		(CONFIG_HD64461_IOBASE + 0x1048)	/* Line Start Address Register (L) */
-#define	HD64461_LNAXLR		(CONFIG_HD64461_IOBASE + 0x104a)	/* Axis Pixel Length Register */
-#define	HD64461_LNDGR		(CONFIG_HD64461_IOBASE + 0x104c)	/* Diagonal Register */
-#define	HD64461_LNAXR		(CONFIG_HD64461_IOBASE + 0x104e)	/* Axial Register */
-#define	HD64461_LNERTR		(CONFIG_HD64461_IOBASE + 0x1050)	/* Start Error Term Register */
-#define	HD64461_LNMDR		(CONFIG_HD64461_IOBASE + 0x1052)	/* Line Mode Register */
+#define	HD64461_LNSARH		HD64461_IO_OFFSET(0x1046)	/* Line Start Address Register (H) */
+#define	HD64461_LNSARL		HD64461_IO_OFFSET(0x1048)	/* Line Start Address Register (L) */
+#define	HD64461_LNAXLR		HD64461_IO_OFFSET(0x104a)	/* Axis Pixel Length Register */
+#define	HD64461_LNDGR		HD64461_IO_OFFSET(0x104c)	/* Diagonal Register */
+#define	HD64461_LNAXR		HD64461_IO_OFFSET(0x104e)	/* Axial Register */
+#define	HD64461_LNERTR		HD64461_IO_OFFSET(0x1050)	/* Start Error Term Register */
+#define	HD64461_LNMDR		HD64461_IO_OFFSET(0x1052)	/* Line Mode Register */
 
 /* BitBLT Registers */
-#define	HD64461_BBTSSARH	(CONFIG_HD64461_IOBASE + 0x1054)	/* Source Start Address Register (H) */
-#define	HD64461_BBTSSARL	(CONFIG_HD64461_IOBASE + 0x1056)	/* Source Start Address Register (L) */
-#define	HD64461_BBTDSARH	(CONFIG_HD64461_IOBASE + 0x1058)	/* Destination Start Address Register (H) */
-#define	HD64461_BBTDSARL	(CONFIG_HD64461_IOBASE + 0x105a)	/* Destination Start Address Register (L) */
-#define	HD64461_BBTDWR		(CONFIG_HD64461_IOBASE + 0x105c)	/* Destination Block Width Register */
-#define	HD64461_BBTDHR		(CONFIG_HD64461_IOBASE + 0x105e)	/* Destination Block Height Register */
-#define	HD64461_BBTPARH		(CONFIG_HD64461_IOBASE + 0x1060)	/* Pattern Start Address Register (H) */
-#define	HD64461_BBTPARL		(CONFIG_HD64461_IOBASE + 0x1062)	/* Pattern Start Address Register (L) */
-#define	HD64461_BBTMARH		(CONFIG_HD64461_IOBASE + 0x1064)	/* Mask Start Address Register (H) */
-#define	HD64461_BBTMARL		(CONFIG_HD64461_IOBASE + 0x1066)	/* Mask Start Address Register (L) */
-#define	HD64461_BBTROPR		(CONFIG_HD64461_IOBASE + 0x1068)	/* ROP Register */
-#define	HD64461_BBTMDR		(CONFIG_HD64461_IOBASE + 0x106a)	/* BitBLT Mode Register */
+#define	HD64461_BBTSSARH	HD64461_IO_OFFSET(0x1054)	/* Source Start Address Register (H) */
+#define	HD64461_BBTSSARL	HD64461_IO_OFFSET(0x1056)	/* Source Start Address Register (L) */
+#define	HD64461_BBTDSARH	HD64461_IO_OFFSET(0x1058)	/* Destination Start Address Register (H) */
+#define	HD64461_BBTDSARL	HD64461_IO_OFFSET(0x105a)	/* Destination Start Address Register (L) */
+#define	HD64461_BBTDWR		HD64461_IO_OFFSET(0x105c)	/* Destination Block Width Register */
+#define	HD64461_BBTDHR		HD64461_IO_OFFSET(0x105e)	/* Destination Block Height Register */
+#define	HD64461_BBTPARH		HD64461_IO_OFFSET(0x1060)	/* Pattern Start Address Register (H) */
+#define	HD64461_BBTPARL		HD64461_IO_OFFSET(0x1062)	/* Pattern Start Address Register (L) */
+#define	HD64461_BBTMARH		HD64461_IO_OFFSET(0x1064)	/* Mask Start Address Register (H) */
+#define	HD64461_BBTMARL		HD64461_IO_OFFSET(0x1066)	/* Mask Start Address Register (L) */
+#define	HD64461_BBTROPR		HD64461_IO_OFFSET(0x1068)	/* ROP Register */
+#define	HD64461_BBTMDR		HD64461_IO_OFFSET(0x106a)	/* BitBLT Mode Register */
 
 /* PC Card Controller Registers */
 /* Maps to Physical Area 6 */
-#define	HD64461_PCC0ISR		(CONFIG_HD64461_IOBASE + 0x2000)	/* socket 0 interface status */
-#define	HD64461_PCC0GCR		(CONFIG_HD64461_IOBASE + 0x2002)	/* socket 0 general control */
-#define	HD64461_PCC0CSCR	(CONFIG_HD64461_IOBASE + 0x2004)	/* socket 0 card status change */
-#define	HD64461_PCC0CSCIER	(CONFIG_HD64461_IOBASE + 0x2006)	/* socket 0 card status change interrupt enable */
-#define	HD64461_PCC0SCR		(CONFIG_HD64461_IOBASE + 0x2008)	/* socket 0 software control */
+#define	HD64461_PCC0ISR		HD64461_IO_OFFSET(0x2000)	/* socket 0 interface status */
+#define	HD64461_PCC0GCR		HD64461_IO_OFFSET(0x2002)	/* socket 0 general control */
+#define	HD64461_PCC0CSCR	HD64461_IO_OFFSET(0x2004)	/* socket 0 card status change */
+#define	HD64461_PCC0CSCIER	HD64461_IO_OFFSET(0x2006)	/* socket 0 card status change interrupt enable */
+#define	HD64461_PCC0SCR		HD64461_IO_OFFSET(0x2008)	/* socket 0 software control */
 /* Maps to Physical Area 5 */
-#define	HD64461_PCC1ISR		(CONFIG_HD64461_IOBASE + 0x2010)	/* socket 1 interface status */
-#define	HD64461_PCC1GCR		(CONFIG_HD64461_IOBASE + 0x2012)	/* socket 1 general control */
-#define	HD64461_PCC1CSCR	(CONFIG_HD64461_IOBASE + 0x2014)	/* socket 1 card status change */
-#define	HD64461_PCC1CSCIER	(CONFIG_HD64461_IOBASE + 0x2016)	/* socket 1 card status change interrupt enable */
-#define	HD64461_PCC1SCR		(CONFIG_HD64461_IOBASE + 0x2018)	/* socket 1 software control */
+#define	HD64461_PCC1ISR		HD64461_IO_OFFSET(0x2010)	/* socket 1 interface status */
+#define	HD64461_PCC1GCR		HD64461_IO_OFFSET(0x2012)	/* socket 1 general control */
+#define	HD64461_PCC1CSCR	HD64461_IO_OFFSET(0x2014)	/* socket 1 card status change */
+#define	HD64461_PCC1CSCIER	HD64461_IO_OFFSET(0x2016)	/* socket 1 card status change interrupt enable */
+#define	HD64461_PCC1SCR		HD64461_IO_OFFSET(0x2018)	/* socket 1 software control */
 
 /* PCC Interface Status Register */
 #define	HD64461_PCCISR_READY		0x80	/* card ready */
@@ -189,41 +191,41 @@
 #define	HD64461_PCCSCR_SWP		0x01	/* write protect */
 
 /* PCC0 Output Pins Control Register */
-#define	HD64461_P0OCR		(CONFIG_HD64461_IOBASE + 0x202a)
+#define	HD64461_P0OCR		HD64461_IO_OFFSET(0x202a)
 
 /* PCC1 Output Pins Control Register */
-#define	HD64461_P1OCR		(CONFIG_HD64461_IOBASE + 0x202c)
+#define	HD64461_P1OCR		HD64461_IO_OFFSET(0x202c)
 
 /* PC Card General Control Register */
-#define	HD64461_PGCR		(CONFIG_HD64461_IOBASE + 0x202e)
+#define	HD64461_PGCR		HD64461_IO_OFFSET(0x202e)
 
 /* Port Control Registers */
-#define	HD64461_GPACR		(CONFIG_HD64461_IOBASE + 0x4000)	/* Port A - Handles IRDA/TIMER */
-#define	HD64461_GPBCR		(CONFIG_HD64461_IOBASE + 0x4002)	/* Port B - Handles UART */
-#define	HD64461_GPCCR		(CONFIG_HD64461_IOBASE + 0x4004)	/* Port C - Handles PCMCIA 1 */
-#define	HD64461_GPDCR		(CONFIG_HD64461_IOBASE + 0x4006)	/* Port D - Handles PCMCIA 1 */
+#define	HD64461_GPACR		HD64461_IO_OFFSET(0x4000)	/* Port A - Handles IRDA/TIMER */
+#define	HD64461_GPBCR		HD64461_IO_OFFSET(0x4002)	/* Port B - Handles UART */
+#define	HD64461_GPCCR		HD64461_IO_OFFSET(0x4004)	/* Port C - Handles PCMCIA 1 */
+#define	HD64461_GPDCR		HD64461_IO_OFFSET(0x4006)	/* Port D - Handles PCMCIA 1 */
 
 /* Port Control Data Registers */
-#define	HD64461_GPADR		(CONFIG_HD64461_IOBASE + 0x4010)	/* A */
-#define	HD64461_GPBDR		(CONFIG_HD64461_IOBASE + 0x4012)	/* B */
-#define	HD64461_GPCDR		(CONFIG_HD64461_IOBASE + 0x4014)	/* C */
-#define	HD64461_GPDDR		(CONFIG_HD64461_IOBASE + 0x4016)	/* D */
+#define	HD64461_GPADR		HD64461_IO_OFFSET(0x4010)	/* A */
+#define	HD64461_GPBDR		HD64461_IO_OFFSET(0x4012)	/* B */
+#define	HD64461_GPCDR		HD64461_IO_OFFSET(0x4014)	/* C */
+#define	HD64461_GPDDR		HD64461_IO_OFFSET(0x4016)	/* D */
 
 /* Interrupt Control Registers */
-#define	HD64461_GPAICR		(CONFIG_HD64461_IOBASE + 0x4020)	/* A */
-#define	HD64461_GPBICR		(CONFIG_HD64461_IOBASE + 0x4022)	/* B */
-#define	HD64461_GPCICR		(CONFIG_HD64461_IOBASE + 0x4024)	/* C */
-#define	HD64461_GPDICR		(CONFIG_HD64461_IOBASE + 0x4026)	/* D */
+#define	HD64461_GPAICR		HD64461_IO_OFFSET(0x4020)	/* A */
+#define	HD64461_GPBICR		HD64461_IO_OFFSET(0x4022)	/* B */
+#define	HD64461_GPCICR		HD64461_IO_OFFSET(0x4024)	/* C */
+#define	HD64461_GPDICR		HD64461_IO_OFFSET(0x4026)	/* D */
 
 /* Interrupt Status Registers */
-#define	HD64461_GPAISR		(CONFIG_HD64461_IOBASE + 0x4040)	/* A */
-#define	HD64461_GPBISR		(CONFIG_HD64461_IOBASE + 0x4042)	/* B */
-#define	HD64461_GPCISR		(CONFIG_HD64461_IOBASE + 0x4044)	/* C */
-#define	HD64461_GPDISR		(CONFIG_HD64461_IOBASE + 0x4046)	/* D */
+#define	HD64461_GPAISR		HD64461_IO_OFFSET(0x4040)	/* A */
+#define	HD64461_GPBISR		HD64461_IO_OFFSET(0x4042)	/* B */
+#define	HD64461_GPCISR		HD64461_IO_OFFSET(0x4044)	/* C */
+#define	HD64461_GPDISR		HD64461_IO_OFFSET(0x4046)	/* D */
 
 /* Interrupt Request Register & Interrupt Mask Register */
-#define	HD64461_NIRR		(CONFIG_HD64461_IOBASE + 0x5000)
-#define	HD64461_NIMR		(CONFIG_HD64461_IOBASE + 0x5002)
+#define	HD64461_NIRR		HD64461_IO_OFFSET(0x5000)
+#define	HD64461_NIMR		HD64461_IO_OFFSET(0x5002)
 
 #define	HD64461_IRQBASE		OFFCHIP_IRQ_BASE
 #define	OFFCHIP_IRQ_BASE	64
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/io.h linux-libre-2.6.31-gnu/arch/sh/include/asm/io.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/io.h	2009-09-09 18:13:59.000000000 -0400
@@ -123,10 +123,15 @@
 
 __BUILD_MEMORY_STRING(b, u8)
 __BUILD_MEMORY_STRING(w, u16)
-__BUILD_MEMORY_STRING(q, u64)
 
+#ifdef CONFIG_SUPERH32
 void __raw_writesl(void __iomem *addr, const void *data, int longlen);
 void __raw_readsl(const void __iomem *addr, void *data, int longlen);
+#else
+__BUILD_MEMORY_STRING(l, u32)
+#endif
+
+__BUILD_MEMORY_STRING(q, u64)
 
 #define writesb			__raw_writesb
 #define writesw			__raw_writesw
@@ -224,17 +229,6 @@
 			unsigned long flags);
 void __iounmap(void __iomem *addr);
 
-/* arch/sh/mm/ioremap_64.c */
-unsigned long onchip_remap(unsigned long addr, unsigned long size,
-			   const char *name);
-extern void onchip_unmap(unsigned long vaddr);
-#else
-#define __ioremap(offset, size, flags)	((void __iomem *)(offset))
-#define __iounmap(addr)			do { } while (0)
-#define onchip_remap(addr, size, name)	(addr)
-#define onchip_unmap(addr)		do { } while (0)
-#endif /* CONFIG_MMU */
-
 static inline void __iomem *
 __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
 {
@@ -268,6 +262,10 @@
 
 	return __ioremap(offset, size, flags);
 }
+#else
+#define __ioremap_mode(offset, size, flags)	((void __iomem *)(offset))
+#define __iounmap(addr)				do { } while (0)
+#endif /* CONFIG_MMU */
 
 #define ioremap(offset, size)				\
 	__ioremap_mode((offset), (size), 0)
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/ipcbuf.h linux-libre-2.6.31-gnu/arch/sh/include/asm/ipcbuf.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/ipcbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/ipcbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,29 +1 @@
-#ifndef __ASM_SH_IPCBUF_H__
-#define __ASM_SH_IPCBUF_H__
-
-/*
- * The ipc64_perm structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm
-{
-	__kernel_key_t		key;
-	__kernel_uid32_t	uid;
-	__kernel_gid32_t	gid;
-	__kernel_uid32_t	cuid;
-	__kernel_gid32_t	cgid;
-	__kernel_mode_t		mode;
-	unsigned short		__pad1;
-	unsigned short		seq;
-	unsigned short		__pad2;
-	unsigned long		__unused1;
-	unsigned long		__unused2;
-};
-
-#endif /* __ASM_SH_IPCBUF_H__ */
+#include <asm-generic/ipcbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/irq.h linux-libre-2.6.31-gnu/arch/sh/include/asm/irq.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,8 @@
  * advised to cap this at the hard limit that they're interested in
  * through the machvec.
  */
-#define NR_IRQS 256
+#define NR_IRQS			256
+#define NR_IRQS_LEGACY		8	/* Legacy external IRQ0-7 */
 
 /*
  * Convert back and forth between INTEVT and IRQ values.
@@ -38,7 +39,6 @@
 	return irq;
 }
 
-#define irq_canonicalize(irq)	(irq)
 #define irq_demux(irq)		sh_mv.mv_irq_demux(irq)
 
 void init_IRQ(void);
@@ -53,6 +53,7 @@
 # define irq_ctx_exit(cpu) do { } while (0)
 #endif
 
+#include <asm-generic/irq.h>
 #ifdef CONFIG_CPU_SH5
 #include <cpu/irq.h>
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/sh/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,30 +3,12 @@
 
 /* Dummy header just to define km_type. */
 
-
 #ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
+#define  __WITH_KM_FENCE
 #endif
 
-enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_IRQ0,
-D(10)	KM_IRQ1,
-D(11)	KM_SOFTIRQ0,
-D(12)	KM_SOFTIRQ1,
-D(13)	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
-#undef D
+#undef __WITH_KM_FENCE
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/kprobes.h linux-libre-2.6.31-gnu/arch/sh/include/asm/kprobes.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/kprobes.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/kprobes.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,7 +6,7 @@
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
-typedef u16 kprobe_opcode_t;
+typedef insn_size_t kprobe_opcode_t;
 #define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/machvec.h linux-libre-2.6.31-gnu/arch/sh/include/asm/machvec.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/machvec.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/machvec.h	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,9 @@
 
 	void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
 	void (*mv_ioport_unmap)(void __iomem *);
+
+	int (*mv_clk_init)(void);
+	int (*mv_mode_pins)(void);
 };
 
 extern struct sh_machine_vector sh_mv;
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/mman.h linux-libre-2.6.31-gnu/arch/sh/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,17 +1 @@
-#ifndef __ASM_SH_MMAN_H
-#define __ASM_SH_MMAN_H
-
 #include <asm-generic/mman.h>
-
-#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
-#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
-#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
-#define MAP_LOCKED	0x2000		/* pages are locked */
-#define MAP_NORESERVE	0x4000		/* don't check for reservations */
-#define MAP_POPULATE	0x8000		/* populate (prefault) page tables */
-#define MAP_NONBLOCK	0x10000		/* do not block on IO */
-
-#define MCL_CURRENT	1		/* lock all current mappings */
-#define MCL_FUTURE	2		/* lock all future mappings */
-
-#endif /* __ASM_SH_MMAN_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/mmu_context.h linux-libre-2.6.31-gnu/arch/sh/include/asm/mmu_context.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/mmu_context.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/mmu_context.h	2009-09-09 18:13:59.000000000 -0400
@@ -122,30 +122,30 @@
 	unsigned int cpu = smp_processor_id();
 
 	if (likely(prev != next)) {
-		cpu_set(cpu, next->cpu_vm_mask);
+		cpumask_set_cpu(cpu, mm_cpumask(next));
 		set_TTB(next->pgd);
 		activate_context(next, cpu);
 	} else
-		if (!cpu_test_and_set(cpu, next->cpu_vm_mask))
+		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)))
 			activate_context(next, cpu);
 }
+
+#define activate_mm(prev, next)		switch_mm((prev),(next),NULL)
+#define deactivate_mm(tsk,mm)		do { } while (0)
+#define enter_lazy_tlb(mm,tsk)		do { } while (0)
+
 #else
-#define get_mmu_context(mm)		do { } while (0)
-#define init_new_context(tsk,mm)	(0)
-#define destroy_context(mm)		do { } while (0)
+
 #define set_asid(asid)			do { } while (0)
 #define get_asid()			(0)
 #define cpu_asid(cpu, mm)		({ (void)cpu; NO_CONTEXT; })
 #define switch_and_save_asid(asid)	(0)
 #define set_TTB(pgd)			do { } while (0)
 #define get_TTB()			(0)
-#define activate_context(mm,cpu)	do { } while (0)
-#define switch_mm(prev,next,tsk)	do { } while (0)
-#endif /* CONFIG_MMU */
 
-#define activate_mm(prev, next)		switch_mm((prev),(next),NULL)
-#define deactivate_mm(tsk,mm)		do { } while (0)
-#define enter_lazy_tlb(mm,tsk)		do { } while (0)
+#include <asm-generic/mmu_context.h>
+
+#endif /* CONFIG_MMU */
 
 #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
 /*
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/module.h linux-libre-2.6.31-gnu/arch/sh/include/asm/module.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/module.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/module.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,17 +1,7 @@
 #ifndef _ASM_SH_MODULE_H
 #define _ASM_SH_MODULE_H
 
-/*
- * This file contains the SH architecture specific module code.
- */
-
-struct mod_arch_specific {
-	/* Nothing to see here .. */
-};
-
-#define Elf_Shdr		Elf32_Shdr
-#define Elf_Sym			Elf32_Sym
-#define Elf_Ehdr		Elf32_Ehdr
+#include <asm-generic/module.h>
 
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 # ifdef CONFIG_CPU_SH2
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/msgbuf.h linux-libre-2.6.31-gnu/arch/sh/include/asm/msgbuf.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/msgbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/msgbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,31 +1 @@
-#ifndef __ASM_SH_MSGBUF_H
-#define __ASM_SH_MSGBUF_H
-
-/* 
- * The msqid64_ds structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-	struct ipc64_perm msg_perm;
-	__kernel_time_t msg_stime;	/* last msgsnd time */
-	unsigned long	__unused1;
-	__kernel_time_t msg_rtime;	/* last msgrcv time */
-	unsigned long	__unused2;
-	__kernel_time_t msg_ctime;	/* last change time */
-	unsigned long	__unused3;
-	unsigned long  msg_cbytes;	/* current number of bytes on queue */
-	unsigned long  msg_qnum;	/* number of messages in queue */
-	unsigned long  msg_qbytes;	/* max number of bytes on queue */
-	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
-	__kernel_pid_t msg_lrpid;	/* last receive pid */
-	unsigned long  __unused4;
-	unsigned long  __unused5;
-};
-
-#endif /* __ASM_SH_MSGBUF_H */
+#include <asm-generic/msgbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/page.h linux-libre-2.6.31-gnu/arch/sh/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -163,7 +163,7 @@
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 /* vDSO support */
 #ifdef CONFIG_VSYSCALL
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/param.h linux-libre-2.6.31-gnu/arch/sh/include/asm/param.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/param.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/param.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,22 +1 @@
-#ifndef __ASM_SH_PARAM_H
-#define __ASM_SH_PARAM_H
-
-#ifdef __KERNEL__
-# define HZ		CONFIG_HZ
-# define USER_HZ	100		/* User interfaces are in "ticks" */
-# define CLOCKS_PER_SEC	(USER_HZ)	/* frequency at which times() counts */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE	4096
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif /* __ASM_SH_PARAM_H */
+#include <asm-generic/param.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/parport.h linux-libre-2.6.31-gnu/arch/sh/include/asm/parport.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/parport.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/parport.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,16 +1 @@
-/*
- * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
- *
- * This file should only be included by drivers/parport/parport_pc.c.
- */
-#ifndef __ASM_SH_PARPORT_H
-#define __ASM_SH_PARPORT_H
-
-static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
-
-static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
-{
-	return parport_pc_find_isa_ports(autoirq, autodma);
-}
-
-#endif /* __ASM_SH_PARPORT_H */
+#include <asm-generic/parport.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/pci.h linux-libre-2.6.31-gnu/arch/sh/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,54 +17,29 @@
  * external) PCI controllers.
  */
 struct pci_channel {
-	struct pci_ops *pci_ops;
-	struct resource *io_resource;
-	struct resource *mem_resource;
-	int first_devfn;
-	int last_devfn;
-};
+	struct pci_channel	*next;
 
-/*
- * Each board initializes this array and terminates it with a NULL entry.
- */
-extern struct pci_channel board_pci_channels[];
+	struct pci_ops		*pci_ops;
+	struct resource		*io_resource;
+	struct resource		*mem_resource;
 
-#define PCIBIOS_MIN_IO		board_pci_channels->io_resource->start
-#define PCIBIOS_MIN_MEM		board_pci_channels->mem_resource->start
+	unsigned long		io_offset;
+	unsigned long		mem_offset;
 
-/*
- * I/O routine helpers
- */
-#if defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
-#define PCI_IO_AREA		0xFE400000
-#define PCI_IO_SIZE		0x00400000
-#elif defined(CONFIG_CPU_SH5)
-extern unsigned long PCI_IO_AREA;
-#define PCI_IO_SIZE		0x00010000
-#else
-#define PCI_IO_AREA		0xFE240000
-#define PCI_IO_SIZE		0x00040000
-#endif
+	unsigned long		reg_base;
 
-#define PCI_MEM_SIZE		0x01000000
+	unsigned long		io_map_base;
+};
 
-#define SH4_PCIIOBR_MASK	0xFFFC0000
-#define pci_ioaddr(addr)	(PCI_IO_AREA + (addr & ~SH4_PCIIOBR_MASK))
+extern void register_pci_controller(struct pci_channel *hose);
 
-#if defined(CONFIG_PCI)
-#define is_pci_ioaddr(port)		\
-	(((port) >= PCIBIOS_MIN_IO) &&	\
-	 ((port) < (PCIBIOS_MIN_IO + PCI_IO_SIZE)))
-#define is_pci_memaddr(port)		\
-	(((port) >= PCIBIOS_MIN_MEM) &&	\
-	 ((port) < (PCIBIOS_MIN_MEM + PCI_MEM_SIZE)))
-#else
-#define is_pci_ioaddr(port)	(0)
-#define is_pci_memaddr(port)	(0)
-#endif
+extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM;
 
 struct pci_dev;
 
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+	enum pci_mmap_state mmap_state, int write_combine);
 extern void pcibios_set_master(struct pci_dev *dev);
 
 static inline void pcibios_penalize_isa_irq(int irq, int active)
@@ -114,31 +89,63 @@
 #endif
 
 #ifdef CONFIG_PCI
+/*
+ * None of the SH PCI controllers support MWI, it is always treated as a
+ * direct memory write.
+ */
+#define PCI_DISABLE_MWI
+
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
 					unsigned long *strategy_parameter)
 {
-	*strat = PCI_DMA_BURST_INFINITY;
-	*strategy_parameter = ~0UL;
+	unsigned long cacheline_size;
+	u8 byte;
+
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+
+	if (byte == 0)
+		cacheline_size = L1_CACHE_BYTES;
+	else
+		cacheline_size = byte << 2;
+
+	*strat = PCI_DMA_BURST_MULTIPLE;
+	*strategy_parameter = cacheline_size;
 }
 #endif
 
+#ifdef CONFIG_SUPERH32
+/*
+ * If we're on an SH7751 or SH7780 PCI controller, PCI memory is mapped
+ * at the end of the address space in a special non-translatable area.
+ */
+#define PCI_MEM_FIXED_START	0xfd000000
+#define PCI_MEM_FIXED_END	(PCI_MEM_FIXED_START + 0x01000000)
+
+#define is_pci_memory_fixed_range(s, e)	\
+	((s) >= PCI_MEM_FIXED_START && (e) < PCI_MEM_FIXED_END)
+#else
+#define is_pci_memory_fixed_range(s, e)	(0)
+#endif
+
 /* Board-specific fixup routines. */
-void pcibios_fixup(void);
-int pcibios_init_platform(void);
 int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
 
-#ifdef CONFIG_PCI_AUTO
-int pciauto_assign_resources(int busno, struct pci_channel *hose);
-#endif
+extern void pcibios_resource_to_bus(struct pci_dev *dev,
+	struct pci_bus_region *region, struct resource *res);
 
-#endif /* __KERNEL__ */
+extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+				    struct pci_bus_region *region);
 
-/* generic pci stuff */
-#include <asm-generic/pci.h>
+/* Chances are this interrupt is wired PC-style ...  */
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return channel ? 15 : 14;
+}
 
 /* generic DMA-mapping stuff */
 #include <asm-generic/pci-dma-compat.h>
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_SH_PCI_H */
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/perf_counter.h linux-libre-2.6.31-gnu/arch/sh/include/asm/perf_counter.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/perf_counter.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/perf_counter.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef __ASM_SH_PERF_COUNTER_H
+#define __ASM_SH_PERF_COUNTER_H
+
+/* SH only supports software counters through this interface. */
+static inline void set_perf_counter_pending(void) {}
+
+#define PERF_COUNTER_INDEX_OFFSET	0
+
+#endif /* __ASM_SH_PERF_COUNTER_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/sh/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -73,20 +73,12 @@
 	quicklist_free_page(QUICK_PT, NULL, pte);
 }
 
-#define __pte_free_tlb(tlb,pte)				\
+#define __pte_free_tlb(tlb,pte,addr)			\
 do {							\
 	pgtable_page_dtor(pte);				\
 	tlb_remove_page((tlb), (pte));			\
 } while (0)
 
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-
-#define pmd_free(mm, x)			do { } while (0)
-#define __pmd_free_tlb(tlb,x)		do { } while (0)
-
 static inline void check_pgt_cache(void)
 {
 	quicklist_trim(QUICK_PGD, NULL, 25, 16);
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/sh/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -154,6 +154,10 @@
 #define kmap_coherent_init()	do { } while (0)
 #endif
 
+/* arch/sh/mm/mmap.c */
+#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
 #include <asm-generic/pgtable.h>
 
 #endif /* __ASM_SH_PGTABLE_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/posix_types_32.h linux-libre-2.6.31-gnu/arch/sh/include/asm/posix_types_32.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/posix_types_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/posix_types_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,118 +1,29 @@
-#ifndef __ASM_SH_POSIX_TYPES_H
-#define __ASM_SH_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
+#ifndef __ASM_SH_POSIX_TYPES_32_H
+#define __ASM_SH_POSIX_TYPES_32_H
 
-typedef unsigned long	__kernel_ino_t;
 typedef unsigned short	__kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
 typedef unsigned short	__kernel_nlink_t;
-typedef long		__kernel_off_t;
-typedef int		__kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
 typedef unsigned short	__kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
 typedef unsigned short	__kernel_uid_t;
+#define __kernel_uid_t __kernel_uid_t
 typedef unsigned short	__kernel_gid_t;
-typedef unsigned int	__kernel_size_t;
-typedef int		__kernel_ssize_t;
-typedef int		__kernel_ptrdiff_t;
-typedef long		__kernel_time_t;
-typedef long		__kernel_suseconds_t;
-typedef long		__kernel_clock_t;
-typedef int		__kernel_timer_t;
-typedef int		__kernel_clockid_t;
-typedef int		__kernel_daddr_t;
-typedef char *		__kernel_caddr_t;
-typedef unsigned short	__kernel_uid16_t;
-typedef unsigned short	__kernel_gid16_t;
+#define __kernel_gid_t __kernel_gid_t
+
 typedef unsigned int	__kernel_uid32_t;
+#define __kernel_uid32_t __kernel_uid32_t
 typedef unsigned int	__kernel_gid32_t;
+#define __kernel_gid32_t __kernel_gid32_t
 
 typedef unsigned short	__kernel_old_uid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
 typedef unsigned short	__kernel_old_gid_t;
+#define __kernel_old_gid_t __kernel_old_gid_t
 typedef unsigned short	__kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#ifdef __GNUC__
-typedef long long	__kernel_loff_t;
-#endif
-
-typedef struct {
-	int	val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef	__FD_SET
-static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-	unsigned long __tmp = __fd / __NFDBITS;
-	unsigned long __rem = __fd % __NFDBITS;
-	__fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef	__FD_CLR
-static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-	unsigned long __tmp = __fd / __NFDBITS;
-	unsigned long __rem = __fd % __NFDBITS;
-	__fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-
-#undef	__FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{ 
-	unsigned long __tmp = __fd / __NFDBITS;
-	unsigned long __rem = __fd % __NFDBITS;
-	return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef	__FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
-{
-	unsigned long *__tmp = __p->fds_bits;
-	int __i;
-
-	if (__builtin_constant_p(__FDSET_LONGS)) {
-		switch (__FDSET_LONGS) {
-		case 16:
-			__tmp[ 0] = 0; __tmp[ 1] = 0;
-			__tmp[ 2] = 0; __tmp[ 3] = 0;
-			__tmp[ 4] = 0; __tmp[ 5] = 0;
-			__tmp[ 6] = 0; __tmp[ 7] = 0;
-			__tmp[ 8] = 0; __tmp[ 9] = 0;
-			__tmp[10] = 0; __tmp[11] = 0;
-			__tmp[12] = 0; __tmp[13] = 0;
-			__tmp[14] = 0; __tmp[15] = 0;
-			return;
-
-		case 8:
-			__tmp[ 0] = 0; __tmp[ 1] = 0;
-			__tmp[ 2] = 0; __tmp[ 3] = 0;
-			__tmp[ 4] = 0; __tmp[ 5] = 0;
-			__tmp[ 6] = 0; __tmp[ 7] = 0;
-			return;
-
-		case 4:
-			__tmp[ 0] = 0; __tmp[ 1] = 0;
-			__tmp[ 2] = 0; __tmp[ 3] = 0;
-			return;
-		}
-	}
-	__i = __FDSET_LONGS;
-	while (__i) {
-		__i--;
-		*__tmp = 0;
-		__tmp++;
-	}
-}
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
-#endif /* __ASM_SH_POSIX_TYPES_H */
+#endif /* __ASM_SH_POSIX_TYPES_32_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/posix_types_64.h linux-libre-2.6.31-gnu/arch/sh/include/asm/posix_types_64.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/posix_types_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/posix_types_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,127 +1,34 @@
-#ifndef __ASM_SH64_POSIX_TYPES_H
-#define __ASM_SH64_POSIX_TYPES_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/posix_types.h
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003  Paul Mundt
- *
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
+#ifndef __ASM_SH_POSIX_TYPES_64_H
+#define __ASM_SH_POSIX_TYPES_64_H
 
-typedef unsigned long	__kernel_ino_t;
 typedef unsigned short	__kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
 typedef unsigned short	__kernel_nlink_t;
-typedef long		__kernel_off_t;
-typedef int		__kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
 typedef unsigned short	__kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
 typedef unsigned short	__kernel_uid_t;
+#define __kernel_uid_t __kernel_uid_t
 typedef unsigned short	__kernel_gid_t;
+#define __kernel_gid_t __kernel_gid_t
 typedef long unsigned int	__kernel_size_t;
+#define __kernel_size_t __kernel_size_t
 typedef int		__kernel_ssize_t;
+#define __kernel_ssize_t __kernel_ssize_t
 typedef int		__kernel_ptrdiff_t;
-typedef long		__kernel_time_t;
-typedef long		__kernel_suseconds_t;
-typedef long		__kernel_clock_t;
-typedef int		__kernel_timer_t;
-typedef int		__kernel_clockid_t;
-typedef int		__kernel_daddr_t;
-typedef char *		__kernel_caddr_t;
-typedef unsigned short	__kernel_uid16_t;
-typedef unsigned short	__kernel_gid16_t;
+#define __kernel_ptrdiff_t __kernel_ptrdiff_t
 typedef unsigned int	__kernel_uid32_t;
+#define __kernel_uid32_t __kernel_uid32_t
 typedef unsigned int	__kernel_gid32_t;
+#define __kernel_gid32_t __kernel_gid32_t
 
 typedef unsigned short	__kernel_old_uid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
 typedef unsigned short	__kernel_old_gid_t;
+#define __kernel_old_gid_t __kernel_old_gid_t
 typedef unsigned short	__kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#ifdef __GNUC__
-typedef long long	__kernel_loff_t;
-#endif
-
-typedef struct {
-	int	val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef	__FD_SET
-static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-	unsigned long __tmp = __fd / __NFDBITS;
-	unsigned long __rem = __fd % __NFDBITS;
-	__fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef	__FD_CLR
-static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-	unsigned long __tmp = __fd / __NFDBITS;
-	unsigned long __rem = __fd % __NFDBITS;
-	__fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-
-#undef	__FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{
-	unsigned long __tmp = __fd / __NFDBITS;
-	unsigned long __rem = __fd % __NFDBITS;
-	return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef	__FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
-{
-	unsigned long *__tmp = __p->fds_bits;
-	int __i;
-
-	if (__builtin_constant_p(__FDSET_LONGS)) {
-		switch (__FDSET_LONGS) {
-		case 16:
-			__tmp[ 0] = 0; __tmp[ 1] = 0;
-			__tmp[ 2] = 0; __tmp[ 3] = 0;
-			__tmp[ 4] = 0; __tmp[ 5] = 0;
-			__tmp[ 6] = 0; __tmp[ 7] = 0;
-			__tmp[ 8] = 0; __tmp[ 9] = 0;
-			__tmp[10] = 0; __tmp[11] = 0;
-			__tmp[12] = 0; __tmp[13] = 0;
-			__tmp[14] = 0; __tmp[15] = 0;
-			return;
-
-		case 8:
-			__tmp[ 0] = 0; __tmp[ 1] = 0;
-			__tmp[ 2] = 0; __tmp[ 3] = 0;
-			__tmp[ 4] = 0; __tmp[ 5] = 0;
-			__tmp[ 6] = 0; __tmp[ 7] = 0;
-			return;
-
-		case 4:
-			__tmp[ 0] = 0; __tmp[ 1] = 0;
-			__tmp[ 2] = 0; __tmp[ 3] = 0;
-			return;
-		}
-	}
-	__i = __FDSET_LONGS;
-	while (__i) {
-		__i--;
-		*__tmp = 0;
-		__tmp++;
-	}
-}
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
-#endif /* __ASM_SH64_POSIX_TYPES_H */
+#endif /* __ASM_SH_POSIX_TYPES_64_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/processor.h linux-libre-2.6.31-gnu/arch/sh/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,7 @@
 
 	/* SH-4A types */
 	CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SH7786,
-	CPU_SH7723, CPU_SHX3,
+	CPU_SH7723, CPU_SH7724, CPU_SHX3,
 
 	/* SH4AL-DSP types */
 	CPU_SH7343, CPU_SH7722, CPU_SH7366,
@@ -94,6 +94,27 @@
 const char *get_cpu_subtype(struct sh_cpuinfo *c);
 extern const struct seq_operations cpuinfo_op;
 
+/* processor boot mode configuration */
+#define MODE_PIN0 (1 << 0)
+#define MODE_PIN1 (1 << 1)
+#define MODE_PIN2 (1 << 2)
+#define MODE_PIN3 (1 << 3)
+#define MODE_PIN4 (1 << 4)
+#define MODE_PIN5 (1 << 5)
+#define MODE_PIN6 (1 << 6)
+#define MODE_PIN7 (1 << 7)
+#define MODE_PIN8 (1 << 8)
+#define MODE_PIN9 (1 << 9)
+#define MODE_PIN10 (1 << 10)
+#define MODE_PIN11 (1 << 11)
+#define MODE_PIN12 (1 << 12)
+#define MODE_PIN13 (1 << 13)
+#define MODE_PIN14 (1 << 14)
+#define MODE_PIN15 (1 << 15)
+
+int generic_mode_pins(void);
+int test_mode_pin(int pin);
+
 #ifdef CONFIG_VSYSCALL
 int vsyscall_init(void);
 #else
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/ptrace.h linux-libre-2.6.31-gnu/arch/sh/include/asm/ptrace.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/ptrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/ptrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -102,6 +102,11 @@
 #define	PTRACE_GETDSPREGS	55	/* DSP registers */
 #define	PTRACE_SETDSPREGS	56
 
+#define PT_TEXT_END_ADDR 	240
+#define PT_TEXT_ADDR 		244	/* &(struct user)->start_code */
+#define PT_DATA_ADDR 		248	/* &(struct user)->start_data */
+#define PT_TEXT_LEN		252
+
 #ifdef __KERNEL__
 #include <asm/addrspace.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/rtc.h linux-libre-2.6.31-gnu/arch/sh/include/asm/rtc.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/rtc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/rtc.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,17 @@
 extern void (*rtc_sh_get_time)(struct timespec *);
 extern int (*rtc_sh_set_time)(const time_t);
 
+/* some dummy definitions */
+#define RTC_BATT_BAD 0x100	/* battery bad */
+#define RTC_SQWE 0x08		/* enable square-wave output */
+#define RTC_DM_BINARY 0x04	/* all time/date values are BCD if clear */
+#define RTC_24H 0x02		/* 24 hour mode - else hours bit 7 means pm */
+#define RTC_DST_EN 0x01	        /* auto switch DST - works f. USA only */
+
+struct rtc_time;
+unsigned int get_rtc_time(struct rtc_time *);
+int set_rtc_time(struct rtc_time *);
+
 #define RTC_CAP_4_DIGIT_YEAR	(1 << 0)
 
 struct sh_rtc_platform_info {
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/scatterlist.h linux-libre-2.6.31-gnu/arch/sh/include/asm/scatterlist.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/scatterlist.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/scatterlist.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,28 +1,8 @@
 #ifndef __ASM_SH_SCATTERLIST_H
 #define __ASM_SH_SCATTERLIST_H
 
-#include <asm/types.h>
-
-struct scatterlist {
-#ifdef CONFIG_DEBUG_SG
-	unsigned long	sg_magic;
-#endif
-	unsigned long	page_link;
-	unsigned int	offset;		/* for highmem, page offset */
-	unsigned int	length;
-	dma_addr_t	dma_address;
-	unsigned int	dma_length;
-};
-
 #define ISA_DMA_THRESHOLD	PHYS_ADDR_MASK
 
-/* These macros should be used after a pci_map_sg call has been done
- * to get bus addresses of each of the SG entries and their lengths.
- * You should only work with the number of sg entries pci_map_sg
- * returns, or alternatively stop on the first sg_dma_len(sg) which
- * is 0.
- */
-#define sg_dma_address(sg)	((sg)->dma_address)
-#define sg_dma_len(sg)		((sg)->length)
+#include <asm-generic/scatterlist.h>
 
-#endif /* !(__ASM_SH_SCATTERLIST_H) */
+#endif /* __ASM_SH_SCATTERLIST_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/sembuf.h linux-libre-2.6.31-gnu/arch/sh/include/asm/sembuf.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/sembuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/sembuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,25 +1 @@
-#ifndef __ASM_SH_SEMBUF_H
-#define __ASM_SH_SEMBUF_H
-
-/* 
- * The semid64_ds structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
-	__kernel_time_t	sem_otime;		/* last semop time */
-	unsigned long	__unused1;
-	__kernel_time_t	sem_ctime;		/* last change time */
-	unsigned long	__unused2;
-	unsigned long	sem_nsems;		/* no. of semaphores in array */
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* __ASM_SH_SEMBUF_H */
+#include <asm-generic/sembuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/serial.h linux-libre-2.6.31-gnu/arch/sh/include/asm/serial.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/serial.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/serial.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,19 +1 @@
-/*
- * include/asm-sh/serial.h
- *
- * Configuration details for 8250, 16450, 16550, etc. serial ports
- */
-
-#ifndef _ASM_SERIAL_H
-#define _ASM_SERIAL_H
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD ( 1843200 / 16 )
-
-#endif /* _ASM_SERIAL_H */
+#include <asm-generic/serial.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/setup.h linux-libre-2.6.31-gnu/arch/sh/include/asm/setup.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/setup.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/setup.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef _SH_SETUP_H
 #define _SH_SETUP_H
 
-#define COMMAND_LINE_SIZE 256
+#include <asm-generic/setup.h>
 
 #ifdef __KERNEL__
 /*
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/shmbuf.h linux-libre-2.6.31-gnu/arch/sh/include/asm/shmbuf.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/shmbuf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/shmbuf.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,42 +1 @@
-#ifndef __ASM_SH_SHMBUF_H
-#define __ASM_SH_SHMBUF_H
-
-/* 
- * The shmid64_ds structure for i386 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-	struct ipc64_perm	shm_perm;	/* operation perms */
-	size_t			shm_segsz;	/* size of segment (bytes) */
-	__kernel_time_t		shm_atime;	/* last attach time */
-	unsigned long		__unused1;
-	__kernel_time_t		shm_dtime;	/* last detach time */
-	unsigned long		__unused2;
-	__kernel_time_t		shm_ctime;	/* last change time */
-	unsigned long		__unused3;
-	__kernel_pid_t		shm_cpid;	/* pid of creator */
-	__kernel_pid_t		shm_lpid;	/* pid of last operator */
-	unsigned long		shm_nattch;	/* no. of current attaches */
-	unsigned long		__unused4;
-	unsigned long		__unused5;
-};
-
-struct shminfo64 {
-	unsigned long	shmmax;
-	unsigned long	shmmin;
-	unsigned long	shmmni;
-	unsigned long	shmseg;
-	unsigned long	shmall;
-	unsigned long	__unused1;
-	unsigned long	__unused2;
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* __ASM_SH_SHMBUF_H */
+#include <asm-generic/shmbuf.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/signal.h linux-libre-2.6.31-gnu/arch/sh/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,114 +1,10 @@
 #ifndef __ASM_SH_SIGNAL_H
 #define __ASM_SH_SIGNAL_H
 
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct pt_regs;
-struct siginfo;
-
-#ifdef __KERNEL__
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define _NSIG		64
-#define _NSIG_BPW	32
-#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t;		/* at least 32 bits */
-
-typedef struct {
-	unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG		32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-#define SIGBUS		 7
-#define SIGFPE		 8
-#define SIGKILL		 9
-#define SIGUSR1		10
-#define SIGSEGV		11
-#define SIGUSR2		12
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGSTKFLT	16
-#define SIGCHLD		17
-#define SIGCONT		18
-#define SIGSTOP		19
-#define SIGTSTP		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGURG		23
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGIO		29
-#define SIGPOLL		SIGIO
-/*
-#define SIGLOST		29
-*/
-#define SIGPWR		30
-#define SIGSYS		31
-#define	SIGUNUSED	31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN	32
-#define SIGRTMAX	_NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
-
 #include <asm-generic/signal.h>
 
-#ifdef __KERNEL__
 struct old_sigaction {
 	__sighandler_t sa_handler;
 	old_sigset_t sa_mask;
@@ -116,45 +12,4 @@
 	void (*sa_restorer)(void);
 };
 
-struct sigaction {
-	__sighandler_t sa_handler;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-	sigset_t sa_mask;		/* mask last for extensibility */
-};
-
-struct k_sigaction {
-	struct sigaction sa;
-};
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-	union {
-	  __sighandler_t _sa_handler;
-	  void (*_sa_sigaction)(int, struct siginfo *, void *);
-	} _u;
-	sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
-#define sa_handler	_u._sa_handler
-#define sa_sigaction	_u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-	void *ss_sp;
-	int ss_flags;
-	size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-#include <asm/sigcontext.h>
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_SIGNAL_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/smp.h linux-libre-2.6.31-gnu/arch/sh/include/asm/smp.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/smp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/smp.h	2009-09-09 18:13:59.000000000 -0400
@@ -43,7 +43,8 @@
 void plat_send_ipi(unsigned int cpu, unsigned int message);
 
 void arch_send_call_function_single_ipi(int cpu);
-void arch_send_call_function_ipi(cpumask_t mask);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
 
 #else
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/socket.h linux-libre-2.6.31-gnu/arch/sh/include/asm/socket.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/socket.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/socket.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,60 +1 @@
-#ifndef __ASM_SH_SOCKET_H
-#define __ASM_SH_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET	1
-
-#define SO_DEBUG	1
-#define SO_REUSEADDR	2
-#define SO_TYPE		3
-#define SO_ERROR	4
-#define SO_DONTROUTE	5
-#define SO_BROADCAST	6
-#define SO_SNDBUF	7
-#define SO_RCVBUF	8
-#define SO_RCVBUFFORCE	32
-#define SO_SNDBUFFORCE	33
-#define SO_KEEPALIVE	9
-#define SO_OOBINLINE	10
-#define SO_NO_CHECK	11
-#define SO_PRIORITY	12
-#define SO_LINGER	13
-#define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED	16
-#define SO_PEERCRED	17
-#define SO_RCVLOWAT	18
-#define SO_SNDLOWAT	19
-#define SO_RCVTIMEO	20
-#define SO_SNDTIMEO	21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION		22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
-#define SO_SECURITY_ENCRYPTION_NETWORK		24
-
-#define SO_BINDTODEVICE	25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP		29
-#define SCM_TIMESTAMP		SO_TIMESTAMP
-
-#define SO_ACCEPTCONN		30
-
-#define SO_PEERSEC		31
-#define SO_PASSSEC		34
-#define SO_TIMESTAMPNS		35
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
-
-#define SO_MARK			36
-
-#define SO_TIMESTAMPING		37
-#define SCM_TIMESTAMPING	SO_TIMESTAMPING
-
-#endif /* __ASM_SH_SOCKET_H */
+#include <asm-generic/socket.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/spinlock.h linux-libre-2.6.31-gnu/arch/sh/include/asm/spinlock.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/spinlock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/spinlock.h	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,7 @@
 #define __raw_spin_is_locked(x)		((x)->lock <= 0)
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 #define __raw_spin_unlock_wait(x) \
-	do { cpu_relax(); } while ((x)->lock)
+	do { while (__raw_spin_is_locked(x)) cpu_relax(); } while (0)
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/swab.h linux-libre-2.6.31-gnu/arch/sh/include/asm/swab.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/swab.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/swab.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,22 +7,21 @@
  */
 #include <linux/compiler.h>
 #include <linux/types.h>
-
-#define __SWAB_64_THRU_32__
+#include <asm-generic/swab.h>
 
 static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
 {
 	__asm__(
 #ifdef __SH5__
-		"byterev	%0, %0\n\t"
+		"byterev	%1, %0\n\t"
 		"shari		%0, 32, %0"
 #else
-		"swap.b		%0, %0\n\t"
+		"swap.b		%1, %0\n\t"
 		"swap.w		%0, %0\n\t"
 		"swap.b		%0, %0"
 #endif
 		: "=r" (x)
-		: "0" (x));
+		: "r" (x));
 
 	return x;
 }
@@ -32,13 +31,13 @@
 {
 	__asm__(
 #ifdef __SH5__
-		"byterev	%0, %0\n\t"
+		"byterev	%1, %0\n\t"
 		"shari		%0, 32, %0"
 #else
-		"swap.b		%0, %0"
+		"swap.b		%1, %0"
 #endif
 		: "=r" (x)
-		:  "0" (x));
+		:  "r" (x));
 
 	return x;
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/syscall_32.h linux-libre-2.6.31-gnu/arch/sh/include/asm/syscall_32.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/syscall_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/syscall_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/err.h>
 #include <asm/ptrace.h>
 
 /* The system call number is given by the user in R3 */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/system_32.h linux-libre-2.6.31-gnu/arch/sh/include/asm/system_32.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/system_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/system_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -198,7 +198,7 @@
 })
 #endif
 
-int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
+int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
 			    struct mem_access *ma);
 
 asmlinkage void do_address_error(struct pt_regs *regs,
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/system.h linux-libre-2.6.31-gnu/arch/sh/include/asm/system.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/system.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/system.h	2009-09-09 18:13:59.000000000 -0400
@@ -154,6 +154,7 @@
 
 void per_cpu_trap_init(void);
 void default_idle(void);
+void cpu_idle_wait(void);
 
 asmlinkage void break_point_trap(void);
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/termbits.h linux-libre-2.6.31-gnu/arch/sh/include/asm/termbits.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/termbits.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/termbits.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,198 +1 @@
-#ifndef __ASM_SH_TERMBITS_H
-#define __ASM_SH_TERMBITS_H
-
-#include <linux/posix_types.h>
-
-typedef unsigned char	cc_t;
-typedef unsigned int	speed_t;
-typedef unsigned int	tcflag_t;
-
-#define NCCS 19
-struct termios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-};
-
-struct termios2 {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-struct ktermios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-#define IGNBRK	0000001
-#define BRKINT	0000002
-#define IGNPAR	0000004
-#define PARMRK	0000010
-#define INPCK	0000020
-#define ISTRIP	0000040
-#define INLCR	0000100
-#define IGNCR	0000200
-#define ICRNL	0000400
-#define IUCLC	0001000
-#define IXON	0002000
-#define IXANY	0004000
-#define IXOFF	0010000
-#define IMAXBEL	0020000
-#define IUTF8	0040000
-
-/* c_oflag bits */
-#define OPOST	0000001
-#define OLCUC	0000002
-#define ONLCR	0000004
-#define OCRNL	0000010
-#define ONOCR	0000020
-#define ONLRET	0000040
-#define OFILL	0000100
-#define OFDEL	0000200
-#define NLDLY	0000400
-#define   NL0	0000000
-#define   NL1	0000400
-#define CRDLY	0003000
-#define   CR0	0000000
-#define   CR1	0001000
-#define   CR2	0002000
-#define   CR3	0003000
-#define TABDLY	0014000
-#define   TAB0	0000000
-#define   TAB1	0004000
-#define   TAB2	0010000
-#define   TAB3	0014000
-#define   XTABS	0014000
-#define BSDLY	0020000
-#define   BS0	0000000
-#define   BS1	0020000
-#define VTDLY	0040000
-#define   VT0	0000000
-#define   VT1	0040000
-#define FFDLY	0100000
-#define   FF0	0000000
-#define   FF1	0100000
-
-/* c_cflag bit meaning */
-#define CBAUD	0010017
-#define  B0	0000000		/* hang up */
-#define  B50	0000001
-#define  B75	0000002
-#define  B110	0000003
-#define  B134	0000004
-#define  B150	0000005
-#define  B200	0000006
-#define  B300	0000007
-#define  B600	0000010
-#define  B1200	0000011
-#define  B1800	0000012
-#define  B2400	0000013
-#define  B4800	0000014
-#define  B9600	0000015
-#define  B19200	0000016
-#define  B38400	0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE	0000060
-#define   CS5	0000000
-#define   CS6	0000020
-#define   CS7	0000040
-#define   CS8	0000060
-#define CSTOPB	0000100
-#define CREAD	0000200
-#define PARENB	0000400
-#define PARODD	0001000
-#define HUPCL	0002000
-#define CLOCAL	0004000
-#define CBAUDEX 0010000
-#define	   BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD	  002003600000		/* input baud rate */
-#define CMSPAR	  010000000000		/* mark or space (stick) parity */
-#define CRTSCTS	  020000000000		/* flow control */
-
-#define IBSHIFT	16		/* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG	0000001
-#define ICANON	0000002
-#define XCASE	0000004
-#define ECHO	0000010
-#define ECHOE	0000020
-#define ECHOK	0000040
-#define ECHONL	0000100
-#define NOFLSH	0000200
-#define TOSTOP	0000400
-#define ECHOCTL	0001000
-#define ECHOPRT	0002000
-#define ECHOKE	0004000
-#define FLUSHO	0010000
-#define PENDIN	0040000
-#define IEXTEN	0100000
-
-/* tcflow() and TCXONC use these */
-#define	TCOOFF		0
-#define	TCOON		1
-#define	TCIOFF		2
-#define	TCION		3
-
-/* tcflush() and TCFLSH use these */
-#define	TCIFLUSH	0
-#define	TCOFLUSH	1
-#define	TCIOFLUSH	2
-
-/* tcsetattr uses these */
-#define	TCSANOW		0
-#define	TCSADRAIN	1
-#define	TCSAFLUSH	2
-
-#endif /* __ASM_SH_TERMBITS_H */
+#include <asm-generic/termbits.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/termios.h linux-libre-2.6.31-gnu/arch/sh/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,90 +1 @@
-#ifndef __ASM_SH_TERMIOS_H
-#define __ASM_SH_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-	unsigned short ws_row;
-	unsigned short ws_col;
-	unsigned short ws_xpixel;
-	unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-	unsigned short c_iflag;		/* input mode flags */
-	unsigned short c_oflag;		/* output mode flags */
-	unsigned short c_cflag;		/* control mode flags */
-	unsigned short c_lflag;		/* local mode flags */
-	unsigned char c_line;		/* line discipline */
-	unsigned char c_cc[NCC];	/* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE	0x001
-#define TIOCM_DTR	0x002
-#define TIOCM_RTS	0x004
-#define TIOCM_ST	0x008
-#define TIOCM_SR	0x010
-#define TIOCM_CTS	0x020
-#define TIOCM_CAR	0x040
-#define TIOCM_RNG	0x080
-#define TIOCM_DSR	0x100
-#define TIOCM_CD	TIOCM_CAR
-#define TIOCM_RI	TIOCM_RNG
-#define TIOCM_OUT1	0x2000
-#define TIOCM_OUT2	0x4000
-#define TIOCM_LOOP	0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/*	intr=^C		quit=^\		erase=del	kill=^U
-	eof=^D		vtime=\0	vmin=\1		sxtc=\0
-	start=^Q	stop=^S		susp=^Z		eol=\0
-	reprint=^R	discard=^U	werase=^W	lnext=^V
-	eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
-	unsigned short __tmp; \
-	get_user(__tmp,&(termio)->x); \
-	*(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
-	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-	put_user((termios)->c_iflag, &(termio)->c_iflag); \
-	put_user((termios)->c_oflag, &(termio)->c_oflag); \
-	put_user((termios)->c_cflag, &(termio)->c_cflag); \
-	put_user((termios)->c_lflag, &(termio)->c_lflag); \
-	put_user((termios)->c_line,  &(termio)->c_line); \
-	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif	/* __KERNEL__ */
-
-#endif	/* __ASM_SH_TERMIOS_H */
+#include <asm-generic/termios.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/sh/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -51,7 +51,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/timer.h linux-libre-2.6.31-gnu/arch/sh/include/asm/timer.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/timer.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/timer.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-#ifndef __ASM_SH_TIMER_H
-#define __ASM_SH_TIMER_H
-
-#include <linux/sysdev.h>
-#include <linux/clocksource.h>
-#include <cpu/timer.h>
-
-struct sys_timer_ops {
-	int (*init)(void);
-	int (*start)(void);
-	int (*stop)(void);
-#ifndef CONFIG_GENERIC_TIME
-	unsigned long (*get_offset)(void);
-#endif
-};
-
-struct sys_timer {
-	const char		*name;
-
-	struct sys_device	dev;
-	struct sys_timer_ops	*ops;
-};
-
-#define TICK_SIZE (tick_nsec / 1000)
-
-extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer;
-extern struct sys_timer *sys_timer;
-
-#ifndef CONFIG_GENERIC_TIME
-static inline unsigned long get_timer_offset(void)
-{
-	return sys_timer->ops->get_offset();
-}
-#endif
-
-/* arch/sh/kernel/timers/timer.c */
-struct sys_timer *get_sys_timer(void);
-
-/* arch/sh/kernel/time.c */
-void handle_timer_tick(void);
-
-extern struct clocksource clocksource_sh;
-
-#endif /* __ASM_SH_TIMER_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/timex.h linux-libre-2.6.31-gnu/arch/sh/include/asm/timex.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/timex.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/timex.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,11 +8,6 @@
 
 #define CLOCK_TICK_RATE		(CONFIG_SH_PCLK_FREQ / 4) /* Underlying HZ */
 
-typedef unsigned long long cycles_t;
-
-static __inline__ cycles_t get_cycles (void)
-{
-	return 0;
-}
+#include <asm-generic/timex.h>
 
 #endif /* __ASM_SH_TIMEX_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/sh/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -91,9 +91,9 @@
 }
 
 #define tlb_remove_page(tlb,page)	free_page_and_swap_cache(page)
-#define pte_free_tlb(tlb, ptep)		pte_free((tlb)->mm, ptep)
-#define pmd_free_tlb(tlb, pmdp)		pmd_free((tlb)->mm, pmdp)
-#define pud_free_tlb(tlb, pudp)		pud_free((tlb)->mm, pudp)
+#define pte_free_tlb(tlb, ptep, addr)	pte_free((tlb)->mm, ptep)
+#define pmd_free_tlb(tlb, pmdp, addr)	pmd_free((tlb)->mm, pmdp)
+#define pud_free_tlb(tlb, pudp, addr)	pud_free((tlb)->mm, pudp)
 
 #define tlb_migrate_finish(mm)		do { } while (0)
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/topology.h linux-libre-2.6.31-gnu/arch/sh/include/asm/topology.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/topology.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/topology.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,9 +35,6 @@
 #define cpumask_of_node(node)	((void)node, cpu_online_mask)
 
 #define pcibus_to_node(bus)	((void)(bus), -1)
-#define pcibus_to_cpumask(bus)	(pcibus_to_node(bus) == -1 ? \
-					CPU_MASK_ALL : \
-					node_to_cpumask(pcibus_to_node(bus)))
 #define cpumask_of_pcibus(bus)	(pcibus_to_node(bus) == -1 ? \
 					CPU_MASK_ALL_PTR : \
 					cpumask_of_node(pcibus_to_node(bus)))
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/types.h linux-libre-2.6.31-gnu/arch/sh/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,35 +1,21 @@
 #ifndef __ASM_SH_TYPES_H
 #define __ASM_SH_TYPES_H
 
-#include <asm-generic/int-ll64.h>
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned short umode_t;
-
-#endif /* __ASSEMBLY__ */
+#include <asm-generic/types.h>
 
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
 #ifdef __KERNEL__
-
-#define BITS_PER_LONG 32
-
 #ifndef __ASSEMBLY__
 
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
 #ifdef CONFIG_SUPERH32
-typedef u16 opcode_t;
+typedef u16 insn_size_t;
 #else
-typedef u32 opcode_t;
+typedef u32 insn_size_t;
 #endif
 
 #endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_SH_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/ubc.h linux-libre-2.6.31-gnu/arch/sh/include/asm/ubc.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/ubc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/ubc.h	2009-09-09 18:13:59.000000000 -0400
@@ -42,12 +42,23 @@
 
 #define BRCR_CMFA		(1 << 15)
 #define BRCR_CMFB		(1 << 14)
+
+#if defined CONFIG_CPU_SH2A
+#define BRCR_CMFCA		(1 << 15)
+#define BRCR_CMFCB		(1 << 14)
+#define BRCR_CMFDA		(1 << 13)
+#define BRCR_CMFDB		(1 << 12)
+#define BRCR_PCBB		(1 << 6)	/* 1: after execution */
+#define BRCR_PCBA		(1 << 5)	/* 1: after execution */
+#define BRCR_PCTE		0
+#else
 #define BRCR_PCTE		(1 << 11)
 #define BRCR_PCBA		(1 << 10)	/* 1: after execution */
 #define BRCR_DBEB		(1 << 7)
 #define BRCR_PCBB		(1 << 6)
 #define BRCR_SEQ		(1 << 3)
 #define BRCR_UBDE		(1 << 0)
+#endif
 
 #ifndef __ASSEMBLY__
 /* arch/sh/kernel/cpu/ubc.S */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/ucontext.h linux-libre-2.6.31-gnu/arch/sh/include/asm/ucontext.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/ucontext.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/ucontext.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,12 +1 @@
-#ifndef __ASM_SH_UCONTEXT_H
-#define __ASM_SH_UCONTEXT_H
-
-struct ucontext {
-	unsigned long	  uc_flags;
-	struct ucontext  *uc_link;
-	stack_t		  uc_stack;
-	struct sigcontext uc_mcontext;
-	sigset_t	  uc_sigmask;	/* mask last for extensibility */
-};
-
-#endif /* __ASM_SH_UCONTEXT_H */
+#include <asm-generic/ucontext.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/unaligned.h linux-libre-2.6.31-gnu/arch/sh/include/asm/unaligned.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/unaligned.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/unaligned.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,19 +6,7 @@
 #include <asm/unaligned-sh4a.h>
 #else
 /* Otherwise, SH can't handle unaligned accesses. */
-#ifdef __LITTLE_ENDIAN__
-# include <linux/unaligned/le_struct.h>
-# include <linux/unaligned/be_byteshift.h>
-# include <linux/unaligned/generic.h>
-# define get_unaligned	__get_unaligned_le
-# define put_unaligned	__put_unaligned_le
-#else
-# include <linux/unaligned/be_struct.h>
-# include <linux/unaligned/le_byteshift.h>
-# include <linux/unaligned/generic.h>
-# define get_unaligned	__get_unaligned_be
-# define put_unaligned	__put_unaligned_be
-#endif
+#include <asm-generic/unaligned.h>
 #endif
 
 #endif /* _ASM_SH_UNALIGNED_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/unaligned-sh4a.h linux-libre-2.6.31-gnu/arch/sh/include/asm/unaligned-sh4a.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/unaligned-sh4a.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/unaligned-sh4a.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,9 +3,9 @@
 
 /*
  * SH-4A has support for unaligned 32-bit loads, and 32-bit loads only.
- * Support for 16 and 64-bit accesses are done through shifting and
- * masking relative to the endianness. Unaligned stores are not supported
- * by the instruction encoding, so these continue to use the packed
+ * Support for 64-bit accesses are done through shifting and masking
+ * relative to the endianness. Unaligned stores are not supported by the
+ * instruction encoding, so these continue to use the packed
  * struct.
  *
  * The same note as with the movli.l/movco.l pair applies here, as long
@@ -41,9 +41,9 @@
 static inline u16 __get_unaligned_cpu16(const u8 *p)
 {
 #ifdef __LITTLE_ENDIAN
-	return __get_unaligned_cpu32(p) & 0xffff;
+	return p[0] | p[1] << 8;
 #else
-	return __get_unaligned_cpu32(p) >> 16;
+	return p[0] << 8 | p[1];
 #endif
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/unistd_32.h linux-libre-2.6.31-gnu/arch/sh/include/asm/unistd_32.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/unistd_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/unistd_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -343,8 +343,10 @@
 #define __NR_inotify_init1	332
 #define __NR_preadv		333
 #define __NR_pwritev		334
+#define __NR_rt_tgsigqueueinfo	335
+#define __NR_perf_counter_open	336
 
-#define NR_syscalls 335
+#define NR_syscalls 337
 
 #ifdef __KERNEL__
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/asm/unistd_64.h linux-libre-2.6.31-gnu/arch/sh/include/asm/unistd_64.h
--- linux-libre-2.6.30-gnu/arch/sh/include/asm/unistd_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/asm/unistd_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -383,10 +383,12 @@
 #define __NR_inotify_init1	360
 #define __NR_preadv		361
 #define __NR_pwritev		362
+#define __NR_rt_tgsigqueueinfo	363
+#define __NR_perf_counter_open	364
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 363
+#define NR_syscalls 365
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh2a/cpu/ubc.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh2a/cpu/ubc.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh2a/cpu/ubc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh2a/cpu/ubc.h	2009-09-09 18:13:59.000000000 -0400
@@ -1 +1,28 @@
-#include <cpu-sh2/cpu/ubc.h>
+/*
+ * SH-2A UBC definitions
+ *
+ * Copyright (C) 2008 Kieran Bingham
+ *
+ * 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.
+ */
+
+#ifndef __ASM_CPU_SH2A_UBC_H
+#define __ASM_CPU_SH2A_UBC_H
+
+#define UBC_BARA                0xfffc0400
+#define UBC_BAMRA               0xfffc0404
+#define UBC_BBRA                0xfffc04a0	/* 16 bit access */
+#define UBC_BDRA                0xfffc0408
+#define UBC_BDMRA               0xfffc040c
+
+#define UBC_BARB                0xfffc0410
+#define UBC_BAMRB               0xfffc0414
+#define UBC_BBRB                0xfffc04b0	/* 16 bit access */
+#define UBC_BDRB                0xfffc0418
+#define UBC_BDMRB               0xfffc041c
+
+#define UBC_BRCR                0xfffc04c0
+
+#endif /* __ASM_CPU_SH2A_UBC_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh3/cpu/timer.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh3/cpu/timer.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh3/cpu/timer.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh3/cpu/timer.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-/*
- * include/asm-sh/cpu-sh3/timer.h
- *
- * Copyright (C) 2004 Lineo Solutions, Inc.
- *
- * 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.
- */
-#ifndef __ASM_CPU_SH3_TIMER_H
-#define __ASM_CPU_SH3_TIMER_H
-
-/*
- * ---------------------------------------------------------------------------
- * TMU Common definitions for SH3 processors
- *	SH7706
- *	SH7709S
- *	SH7727
- *	SH7729R
- *	SH7710
- *	SH7720
- *	SH7710
- * ---------------------------------------------------------------------------
- */
-
-#if  !defined(CONFIG_CPU_SUBTYPE_SH7720) && !defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define TMU_TOCR	0xfffffe90	/* Byte access */
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7710) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define TMU_012_TSTR	0xa412fe92	/* Byte access */
-
-#define TMU0_TCOR	0xa412fe94	/* Long access */
-#define TMU0_TCNT	0xa412fe98	/* Long access */
-#define TMU0_TCR	0xa412fe9c	/* Word access */
-
-#define TMU1_TCOR	0xa412fea0	/* Long access */
-#define TMU1_TCNT	0xa412fea4	/* Long access */
-#define TMU1_TCR	0xa412fea8	/* Word access */
-
-#define TMU2_TCOR	0xa412feac	/* Long access */
-#define TMU2_TCNT	0xa412feb0	/* Long access */
-#define TMU2_TCR	0xa412feb4	/* Word access */
-
-#else
-#define TMU_012_TSTR	0xfffffe92	/* Byte access */
-
-#define TMU0_TCOR	0xfffffe94	/* Long access */
-#define TMU0_TCNT	0xfffffe98	/* Long access */
-#define TMU0_TCR	0xfffffe9c	/* Word access */
-
-#define TMU1_TCOR	0xfffffea0	/* Long access */
-#define TMU1_TCNT	0xfffffea4	/* Long access */
-#define TMU1_TCR	0xfffffea8	/* Word access */
-
-#define TMU2_TCOR	0xfffffeac	/* Long access */
-#define TMU2_TCNT	0xfffffeb0	/* Long access */
-#define TMU2_TCR	0xfffffeb4	/* Word access */
-#if !defined(CONFIG_CPU_SUBTYPE_SH7720) && !defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define TMU2_TCPR2	0xfffffeb8	/* Long access */
-#endif
-#endif
-
-#endif /* __ASM_CPU_SH3_TIMER_H */
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/cache.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/cache.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/cache.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/cache.h	2009-09-09 18:13:59.000000000 -0400
@@ -38,5 +38,7 @@
 #define CACHE_IC_ADDRESS_ARRAY	0xf0000000
 #define CACHE_OC_ADDRESS_ARRAY	0xf4000000
 
+#define RAMCR			0xFF000074
+
 #endif /* __ASM_CPU_SH4_CACHE_H */
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/freq.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/freq.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/freq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/freq.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,24 @@
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
       defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define	FRQCR			0xffc80000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define FRQCRA			0xa4150000
+#define FRQCRB			0xa4150004
+#define VCLKCR			0xa4150048
+
+#define FCLKACR			0xa4150008
+#define FCLKBCR			0xa415000c
+#define FRQCR			FRQCRA
+#define SCLKACR			FCLKACR
+#define SCLKBCR			FCLKBCR
+#define FCLKACR			0xa4150008
+#define FCLKBCR			0xa415000c
+#define IrDACLKCR		0xa4150018
+
+#define MSTPCR0			0xa4150030
+#define MSTPCR1			0xa4150034
+#define MSTPCR2			0xa4150038
+
 #elif defined(CONFIG_CPU_SUBTYPE_SH7785)
 #define FRQCR0			0xffc80000
 #define FRQCR1			0xffc80004
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7722.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7722.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7722.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7722.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,20 @@
 #ifndef __ASM_SH7722_H__
 #define __ASM_SH7722_H__
 
+/* Boot Mode Pins:
+ *
+ * MD0: CPG - Clock Mode 0->3
+ * MD1: CPG - Clock Mode 0->3
+ * MD2: CPG - Reserved (L: Normal operation)
+ * MD3: BSC - Area0 Bus Width (16/32-bit) [CS0BCR.9,10]
+ * MD5: BSC - Endian Mode (L: Big, H: Little) [CMNCR.3]
+ * MD8: Test Mode
+ */
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function
+ * GPIO_Pxx - GPIO mapped to real I/O pin on CPU
+ */
 enum {
 	/* PTA */
 	GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7723.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7723.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7723.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7723.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,20 @@
 #ifndef __ASM_SH7723_H__
 #define __ASM_SH7723_H__
 
+/* Boot Mode Pins:
+ *
+ * MD0: CPG - Clock Mode 0->3
+ * MD1: CPG - Clock Mode 0->3
+ * MD2: CPG - Reserved (L: Normal operation)
+ * MD3: BSC - Area0 Bus Width (16/32-bit) [CS0BCR.9,10]
+ * MD5: BSC - Endian Mode (L: Big, H: Little) [CMNCR.3]
+ * MD8: Test Mode
+ */
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function
+ * GPIO_Pxx - GPIO mapped to real I/O pin on CPU
+ */
 enum {
 	/* PTA */
 	GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7724.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7724.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7724.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7724.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,269 @@
+#ifndef __ASM_SH7724_H__
+#define __ASM_SH7724_H__
+
+/* Boot Mode Pins:
+ *
+ * MD0: CPG - Clock Mode 0->7
+ * MD1: CPG - Clock Mode 0->7
+ * MD2: CPG - Clock Mode 0->7
+ * MD3: BSC - Area0 Bus Width (16/32-bit) [CS0BCR.9,10]
+ * MD5: BSC - Endian Mode (L: Big, H: Little) [CMNCR.3]
+ * MD8: Test Mode
+ */
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function
+ * GPIO_Pxx - GPIO mapped to real I/O pin on CPU
+ */
+enum {
+	/* PTA */
+	GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
+	GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+
+	/* PTB */
+	GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
+	GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+
+	/* PTC */
+	GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4,
+	GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0,
+
+	/* PTD */
+	GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
+	GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+
+	/* PTE */
+	GPIO_PTE7, GPIO_PTE6, GPIO_PTE5, GPIO_PTE4,
+	GPIO_PTE3, GPIO_PTE2, GPIO_PTE1, GPIO_PTE0,
+
+	/* PTF */
+	GPIO_PTF7, GPIO_PTF6, GPIO_PTF5, GPIO_PTF4,
+	GPIO_PTF3, GPIO_PTF2, GPIO_PTF1, GPIO_PTF0,
+
+	/* PTG */
+			      GPIO_PTG5, GPIO_PTG4,
+	GPIO_PTG3, GPIO_PTG2, GPIO_PTG1, GPIO_PTG0,
+
+	/* PTH */
+	GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4,
+	GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+
+	/* PTJ */
+	GPIO_PTJ7, GPIO_PTJ6, GPIO_PTJ5,
+	GPIO_PTJ3, GPIO_PTJ2, GPIO_PTJ1, GPIO_PTJ0,
+
+	/* PTK */
+	GPIO_PTK7, GPIO_PTK6, GPIO_PTK5, GPIO_PTK4,
+	GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+
+	/* PTL */
+	GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4,
+	GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0,
+
+	/* PTM */
+	GPIO_PTM7, GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
+	GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+
+	/* PTN */
+	GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4,
+	GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
+
+	/* PTQ */
+	GPIO_PTQ7, GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
+	GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
+
+	/* PTR */
+	GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4,
+	GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+
+	/* PTS */
+		   GPIO_PTS6, GPIO_PTS5, GPIO_PTS4,
+	GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+
+	/* PTT */
+	GPIO_PTT7, GPIO_PTT6, GPIO_PTT5, GPIO_PTT4,
+	GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0,
+
+	/* PTU */
+	GPIO_PTU7, GPIO_PTU6, GPIO_PTU5, GPIO_PTU4,
+	GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0,
+
+	/* PTV */
+	GPIO_PTV7, GPIO_PTV6, GPIO_PTV5, GPIO_PTV4,
+	GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+
+	/* PTW */
+	GPIO_PTW7, GPIO_PTW6, GPIO_PTW5, GPIO_PTW4,
+	GPIO_PTW3, GPIO_PTW2, GPIO_PTW1, GPIO_PTW0,
+
+	/* PTX */
+	GPIO_PTX7, GPIO_PTX6, GPIO_PTX5, GPIO_PTX4,
+	GPIO_PTX3, GPIO_PTX2, GPIO_PTX1, GPIO_PTX0,
+
+	/* PTY */
+	GPIO_PTY7, GPIO_PTY6, GPIO_PTY5, GPIO_PTY4,
+	GPIO_PTY3, GPIO_PTY2, GPIO_PTY1, GPIO_PTY0,
+
+	/* PTZ */
+	GPIO_PTZ7, GPIO_PTZ6, GPIO_PTZ5, GPIO_PTZ4,
+	GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1, GPIO_PTZ0,
+
+	/* BSC (PTA/PTB/PTJ/PTQ/PTR/PTT) */
+	GPIO_FN_D31, GPIO_FN_D30, GPIO_FN_D29, GPIO_FN_D28,
+	GPIO_FN_D27, GPIO_FN_D26, GPIO_FN_D25, GPIO_FN_D24,
+	GPIO_FN_D23, GPIO_FN_D22, GPIO_FN_D21, GPIO_FN_D20,
+	GPIO_FN_D19, GPIO_FN_D18, GPIO_FN_D17, GPIO_FN_D16,
+	GPIO_FN_D15, GPIO_FN_D14, GPIO_FN_D13, GPIO_FN_D12,
+	GPIO_FN_D11, GPIO_FN_D10, GPIO_FN_D9,  GPIO_FN_D8,
+	GPIO_FN_D7,  GPIO_FN_D6,  GPIO_FN_D5,  GPIO_FN_D4,
+	GPIO_FN_D3,  GPIO_FN_D2,  GPIO_FN_D1,  GPIO_FN_D0,
+	GPIO_FN_A25, GPIO_FN_A24, GPIO_FN_A23, GPIO_FN_A22,
+	GPIO_FN_CS6B_CE1B,  GPIO_FN_CS6A_CE2B,
+	GPIO_FN_CS5B_CE1A,  GPIO_FN_CS5A_CE2A,
+	GPIO_FN_WE3_ICIOWR, GPIO_FN_WE2_ICIORD,
+	GPIO_FN_IOIS16,     GPIO_FN_WAIT,
+	GPIO_FN_BS,
+
+	/* KEYSC (PTA/PTB)*/
+	GPIO_FN_KEYOUT5_IN5, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYIN4,
+	GPIO_FN_KEYIN3,  GPIO_FN_KEYIN2,  GPIO_FN_KEYIN1,  GPIO_FN_KEYIN0,
+	GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT2, GPIO_FN_KEYOUT1, GPIO_FN_KEYOUT0,
+
+	/* ATAPI (PTA/PTB/PTK/PTR/PTS/PTW) */
+	GPIO_FN_IDED15, GPIO_FN_IDED14, GPIO_FN_IDED13, GPIO_FN_IDED12,
+	GPIO_FN_IDED11, GPIO_FN_IDED10, GPIO_FN_IDED9,  GPIO_FN_IDED8,
+	GPIO_FN_IDED7,  GPIO_FN_IDED6,  GPIO_FN_IDED5,  GPIO_FN_IDED4,
+	GPIO_FN_IDED3,  GPIO_FN_IDED2,  GPIO_FN_IDED1,  GPIO_FN_IDED0,
+	GPIO_FN_IDEA2,     GPIO_FN_IDEA1,     GPIO_FN_IDEA0,  GPIO_FN_IDEIOWR,
+	GPIO_FN_IODREQ,    GPIO_FN_IDECS0,    GPIO_FN_IDECS1, GPIO_FN_IDEIORD,
+	GPIO_FN_DIRECTION, GPIO_FN_EXBUF_ENB, GPIO_FN_IDERST, GPIO_FN_IODACK,
+	GPIO_FN_IDEINT,    GPIO_FN_IDEIORDY,
+
+	/* TPU (PTB/PTR/PTS) */
+	GPIO_FN_TPUTO3, GPIO_FN_TPUTO2, GPIO_FN_TPUTO1, GPIO_FN_TPUTO0,
+	GPIO_FN_TPUTI3, GPIO_FN_TPUTI2,
+
+	/* LCDC (PTC/PTD/PTE/PTF/PTM/PTR) */
+	GPIO_FN_LCDD23, GPIO_FN_LCDD22, GPIO_FN_LCDD21, GPIO_FN_LCDD20,
+	GPIO_FN_LCDD19, GPIO_FN_LCDD18, GPIO_FN_LCDD17, GPIO_FN_LCDD16,
+	GPIO_FN_LCDD15, GPIO_FN_LCDD14, GPIO_FN_LCDD13, GPIO_FN_LCDD12,
+	GPIO_FN_LCDD11, GPIO_FN_LCDD10, GPIO_FN_LCDD9,  GPIO_FN_LCDD8,
+	GPIO_FN_LCDD7,  GPIO_FN_LCDD6,  GPIO_FN_LCDD5,  GPIO_FN_LCDD4,
+	GPIO_FN_LCDD3,  GPIO_FN_LCDD2,  GPIO_FN_LCDD1,  GPIO_FN_LCDD0,
+	GPIO_FN_LCDVSYN,  GPIO_FN_LCDDISP,  GPIO_FN_LCDRS,  GPIO_FN_LCDHSYN,
+	GPIO_FN_LCDCS,    GPIO_FN_LCDDON,   GPIO_FN_LCDDCK, GPIO_FN_LCDWR,
+	GPIO_FN_LCDVEPWC, GPIO_FN_LCDVCPWC, GPIO_FN_LCDRD,  GPIO_FN_LCDLCLK,
+
+	/* SCIF0 (PTF/PTM) */
+	GPIO_FN_SCIF0_TXD, GPIO_FN_SCIF0_RXD, GPIO_FN_SCIF0_SCK,
+
+	/* SCIF1 (PTL) */
+	GPIO_FN_SCIF1_SCK, GPIO_FN_SCIF1_RXD, GPIO_FN_SCIF1_TXD,
+
+	/* SCIF2 (PTE/PTF/PTN) with LCDC, VOU */
+	GPIO_FN_SCIF2_L_TXD, GPIO_FN_SCIF2_L_SCK, GPIO_FN_SCIF2_L_RXD,
+	GPIO_FN_SCIF2_V_TXD, GPIO_FN_SCIF2_V_SCK, GPIO_FN_SCIF2_V_RXD,
+
+	/* SCIF3 (PTL/PTN/PTZ) with VOU, IRQ */
+	GPIO_FN_SCIF3_V_SCK, GPIO_FN_SCIF3_V_RXD, GPIO_FN_SCIF3_V_TXD,
+	GPIO_FN_SCIF3_V_CTS, GPIO_FN_SCIF3_V_RTS,
+	GPIO_FN_SCIF3_I_SCK, GPIO_FN_SCIF3_I_RXD, GPIO_FN_SCIF3_I_TXD,
+	GPIO_FN_SCIF3_I_CTS, GPIO_FN_SCIF3_I_RTS,
+
+	/* SCIF4 (PTE) */
+	GPIO_FN_SCIF4_SCK, GPIO_FN_SCIF4_RXD, GPIO_FN_SCIF4_TXD,
+
+	/* SCIF5 (PTS) */
+	GPIO_FN_SCIF5_SCK, GPIO_FN_SCIF5_RXD, GPIO_FN_SCIF5_TXD,
+
+	/* FSI (PTE/PTU/PTV) */
+	GPIO_FN_FSIMCKB,   GPIO_FN_FSIMCKA,    GPIO_FN_FSIOASD,
+	GPIO_FN_FSIIABCK,  GPIO_FN_FSIIALRCK,  GPIO_FN_FSIOABCK,
+	GPIO_FN_FSIOALRCK, GPIO_FN_CLKAUDIOAO, GPIO_FN_FSIIBSD,
+	GPIO_FN_FSIOBSD,   GPIO_FN_FSIIBBCK,   GPIO_FN_FSIIBLRCK,
+	GPIO_FN_FSIOBBCK,  GPIO_FN_FSIOBLRCK,  GPIO_FN_CLKAUDIOBO,
+	GPIO_FN_FSIIASD,
+
+	/* AUD (PTG) */
+	GPIO_FN_AUDCK,   GPIO_FN_AUDSYNC, GPIO_FN_AUDATA3,
+	GPIO_FN_AUDATA2, GPIO_FN_AUDATA1, GPIO_FN_AUDATA0,
+
+	/* VIO (PTS) (common?) */
+	GPIO_FN_VIO_CKO,
+
+	/* VIO0 (PTH/PTK) */
+	GPIO_FN_VIO0_D15, GPIO_FN_VIO0_D14, GPIO_FN_VIO0_D13, GPIO_FN_VIO0_D12,
+	GPIO_FN_VIO0_D11, GPIO_FN_VIO0_D10, GPIO_FN_VIO0_D9,  GPIO_FN_VIO0_D8,
+	GPIO_FN_VIO0_D7,  GPIO_FN_VIO0_D6,  GPIO_FN_VIO0_D5,  GPIO_FN_VIO0_D4,
+	GPIO_FN_VIO0_D3,  GPIO_FN_VIO0_D2,  GPIO_FN_VIO0_D1,  GPIO_FN_VIO0_D0,
+	GPIO_FN_VIO0_VD,  GPIO_FN_VIO0_CLK,
+	GPIO_FN_VIO0_FLD, GPIO_FN_VIO0_HD,
+
+	/* VIO1 (PTK/PTS) */
+	GPIO_FN_VIO1_D7,  GPIO_FN_VIO1_D6, GPIO_FN_VIO1_D5, GPIO_FN_VIO1_D4,
+	GPIO_FN_VIO1_D3,  GPIO_FN_VIO1_D2, GPIO_FN_VIO1_D1, GPIO_FN_VIO1_D0,
+	GPIO_FN_VIO1_FLD, GPIO_FN_VIO1_HD, GPIO_FN_VIO1_VD, GPIO_FN_VIO1_CLK,
+
+	/* Eth  (PTL/PTN/PTX) */
+	GPIO_FN_RMII_RXD0,    GPIO_FN_RMII_RXD1,
+	GPIO_FN_RMII_TXD0,    GPIO_FN_RMII_TXD1,
+	GPIO_FN_RMII_REF_CLK, GPIO_FN_RMII_TX_EN,
+	GPIO_FN_RMII_RX_ER,   GPIO_FN_RMII_CRS_DV,
+	GPIO_FN_LNKSTA,       GPIO_FN_MDIO,
+	GPIO_FN_MDC,
+
+	/* System (PTJ) */
+	GPIO_FN_PDSTATUS, GPIO_FN_STATUS2, GPIO_FN_STATUS0,
+
+	/* VOU (PTL/PTM/PTN*/
+	GPIO_FN_DV_D15,  GPIO_FN_DV_D14, GPIO_FN_DV_D13,   GPIO_FN_DV_D12,
+	GPIO_FN_DV_D11,  GPIO_FN_DV_D10, GPIO_FN_DV_D9,    GPIO_FN_DV_D8,
+	GPIO_FN_DV_D7,   GPIO_FN_DV_D6,  GPIO_FN_DV_D5,    GPIO_FN_DV_D4,
+	GPIO_FN_DV_D3,   GPIO_FN_DV_D2,  GPIO_FN_DV_D1,    GPIO_FN_DV_D0,
+	GPIO_FN_DV_CLKI, GPIO_FN_DV_CLK, GPIO_FN_DV_VSYNC, GPIO_FN_DV_HSYNC,
+
+	/* MSIOF0 (PTL/PTM) */
+	GPIO_FN_MSIOF0_RXD,   GPIO_FN_MSIOF0_TXD,
+	GPIO_FN_MSIOF0_MCK,   GPIO_FN_MSIOF0_TSCK,
+	GPIO_FN_MSIOF0_SS1,   GPIO_FN_MSIOF0_SS2,
+	GPIO_FN_MSIOF0_TSYNC, GPIO_FN_MSIOF0_RSCK,
+	GPIO_FN_MSIOF0_RSYNC,
+
+	/* MSIOF1 (PTV) */
+	GPIO_FN_MSIOF1_RXD,   GPIO_FN_MSIOF1_TXD,
+	GPIO_FN_MSIOF1_MCK,   GPIO_FN_MSIOF1_TSCK,
+	GPIO_FN_MSIOF1_SS1,   GPIO_FN_MSIOF1_SS2,
+	GPIO_FN_MSIOF1_TSYNC, GPIO_FN_MSIOF1_RSCK,
+	GPIO_FN_MSIOF1_RSYNC,
+
+	/* DMAC (PTU/PTX) */
+	GPIO_FN_DMAC_DACK0, GPIO_FN_DMAC_DREQ0,
+	GPIO_FN_DMAC_DACK1, GPIO_FN_DMAC_DREQ1,
+
+	/* SDHI0 (PTY) */
+	GPIO_FN_SDHI0CD, GPIO_FN_SDHI0WP, GPIO_FN_SDHI0CMD, GPIO_FN_SDHI0CLK,
+	GPIO_FN_SDHI0D3, GPIO_FN_SDHI0D2, GPIO_FN_SDHI0D1,  GPIO_FN_SDHI0D0,
+
+	/* SDHI1 (PTW) */
+	GPIO_FN_SDHI1CD, GPIO_FN_SDHI1WP, GPIO_FN_SDHI1CMD, GPIO_FN_SDHI1CLK,
+	GPIO_FN_SDHI1D3, GPIO_FN_SDHI1D2, GPIO_FN_SDHI1D1,  GPIO_FN_SDHI1D0,
+
+	/* MMC (PTW/PTX)*/
+	GPIO_FN_MMC_D7,  GPIO_FN_MMC_D6,  GPIO_FN_MMC_D5, GPIO_FN_MMC_D4,
+	GPIO_FN_MMC_D3,  GPIO_FN_MMC_D2,  GPIO_FN_MMC_D1, GPIO_FN_MMC_D0,
+	GPIO_FN_MMC_CLK, GPIO_FN_MMC_CMD,
+
+	/* IrDA (PTX) */
+	GPIO_FN_IRDA_OUT, GPIO_FN_IRDA_IN,
+
+	/* TSIF (PTX) */
+	GPIO_FN_TSIF_TS0_SDAT, GPIO_FN_TSIF_TS0_SCK,
+	GPIO_FN_TSIF_TS0_SDEN, GPIO_FN_TSIF_TS0_SPSYNC,
+
+	/* IRQ (PTZ) */
+	GPIO_FN_INTC_IRQ7, GPIO_FN_INTC_IRQ6, GPIO_FN_INTC_IRQ5,
+	GPIO_FN_INTC_IRQ4, GPIO_FN_INTC_IRQ3, GPIO_FN_INTC_IRQ2,
+	GPIO_FN_INTC_IRQ1, GPIO_FN_INTC_IRQ0,
+};
+
+#endif /* __ASM_SH7724_H__ */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7785.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7785.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/sh7785.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/sh7785.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,31 @@
 #ifndef __ASM_SH7785_H__
 #define __ASM_SH7785_H__
 
+/* Boot Mode Pins:
+ *
+ * MODE0: CPG - Initial Pck/Bck Frequency [FRQMR1]
+ * MODE1: CPG - Initial Uck/SHck/DDRck Frequency [FRQMR1]
+ * MODE2: CPG - Reserved (L: Normal operation)
+ * MODE3: CPG - Reserved (L: Normal operation)
+ * MODE4: CPG - Initial PLL setting (72x/36x)
+ * MODE5: LBSC - Area0 Memory Type / Bus Width [CS0BCR.8]
+ * MODE6: LBSC - Area0 Memory Type / Bus Width [CS0BCR.9]
+ * MODE7: LBSC - Area0 Memory Type / Bus Width [CS0BCR.3]
+ * MODE8: LBSC - Endian Mode (L: Big, H: Little) [BCR.31]
+ * MODE9: LBSC - Master/Slave Mode (L: Slave) [BCR.30]
+ * MODE10: CPG - Clock Input (L: Ext Clk, H: Crystal)
+ * MODE11: PCI - Pin Mode (LL: PCI host, LH: PCI slave)
+ * MODE12: PCI - Pin Mode (HL: Local bus, HH: DU)
+ * MODE13: Boot Address Mode (L: 29-bit, H: 32-bit)
+ * MODE14: Reserved (H: Normal operation)
+ *
+ * More information in sh7785 manual Rev.1.00, page 1628.
+ */
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function
+ * GPIO_Pxx - GPIO mapped to real I/O pin on CPU
+ */
 enum {
 	/* PA */
 	GPIO_PA7, GPIO_PA6, GPIO_PA5, GPIO_PA4,
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/timer.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/timer.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh4/cpu/timer.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh4/cpu/timer.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/*
- * include/asm-sh/cpu-sh4/timer.h
- *
- * Copyright (C) 2004 Lineo Solutions, Inc.
- *
- * 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.
- */
-#ifndef __ASM_CPU_SH4_TIMER_H
-#define __ASM_CPU_SH4_TIMER_H
-
-/*
- * ---------------------------------------------------------------------------
- * TMU Common definitions for SH4 processors
- *	SH7750S/SH7750R
- *	SH7751/SH7751R
- *	SH7760
- *	SH-X3
- * ---------------------------------------------------------------------------
- */
-#ifdef CONFIG_CPU_SUBTYPE_SHX3
-#define TMU_012_BASE	0xffc10000
-#define TMU_345_BASE	0xffc20000
-#else
-#define TMU_012_BASE	0xffd80000
-#define TMU_345_BASE	0xfe100000
-#endif
-
-#define TMU_TOCR	TMU_012_BASE	/* Not supported on all CPUs */
-
-#define TMU_012_TSTR	(TMU_012_BASE + 0x04)
-#define TMU_345_TSTR	(TMU_345_BASE + 0x04)
-
-#define TMU0_TCOR	(TMU_012_BASE + 0x08)
-#define TMU0_TCNT	(TMU_012_BASE + 0x0c)
-#define TMU0_TCR	(TMU_012_BASE + 0x10)
-
-#define TMU1_TCOR       (TMU_012_BASE + 0x14)
-#define TMU1_TCNT       (TMU_012_BASE + 0x18)
-#define TMU1_TCR        (TMU_012_BASE + 0x1c)
-
-#define TMU2_TCOR       (TMU_012_BASE + 0x20)
-#define TMU2_TCNT       (TMU_012_BASE + 0x24)
-#define TMU2_TCR	(TMU_012_BASE + 0x28)
-#define TMU2_TCPR	(TMU_012_BASE + 0x2c)
-
-#define TMU3_TCOR	(TMU_345_BASE + 0x08)
-#define TMU3_TCNT	(TMU_345_BASE + 0x0c)
-#define TMU3_TCR	(TMU_345_BASE + 0x10)
-
-#define TMU4_TCOR	(TMU_345_BASE + 0x14)
-#define TMU4_TCNT	(TMU_345_BASE + 0x18)
-#define TMU4_TCR	(TMU_345_BASE + 0x1c)
-
-#define TMU5_TCOR	(TMU_345_BASE + 0x20)
-#define TMU5_TCNT	(TMU_345_BASE + 0x24)
-#define TMU5_TCR	(TMU_345_BASE + 0x28)
-
-#endif /* __ASM_CPU_SH4_TIMER_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh5/cpu/irq.h linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh5/cpu/irq.h
--- linux-libre-2.6.30-gnu/arch/sh/include/cpu-sh5/cpu/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/cpu-sh5/cpu/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -111,7 +111,6 @@
 #define TOP_PRIORITY	15
 
 extern int intc_evt_to_irq[(0xE20/0x20)+1];
-int intc_irq_describe(char* p, int irq);
 extern int platform_int_priority[NR_INTC_IRQS];
 
 #endif /* __ASM_SH_CPU_SH5_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/mach-common/mach/highlander.h linux-libre-2.6.31-gnu/arch/sh/include/mach-common/mach/highlander.h
--- linux-libre-2.6.30-gnu/arch/sh/include/mach-common/mach/highlander.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/mach-common/mach/highlander.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,9 @@
 #define __ASM_SH_RENESAS_R7780RP_H
 
 /* Box specific addresses.  */
+#define PA_NORFLASH_ADDR	0x00000000
+#define PA_NORFLASH_SIZE	0x04000000
+
 #if defined(CONFIG_SH_R7780MP)
 #define PA_BCR          0xa4000000      /* FPGA */
 #define PA_SDPOW	(-1)
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/mach-common/mach/sh7785lcr.h linux-libre-2.6.31-gnu/arch/sh/include/mach-common/mach/sh7785lcr.h
--- linux-libre-2.6.30-gnu/arch/sh/include/mach-common/mach/sh7785lcr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/mach-common/mach/sh7785lcr.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,11 +9,11 @@
  * -----------------------------+---------------+---------------
  * 0x00000000 - 0x03ffffff(CS0)	| NOR Flash	| NOR Flash
  * 0x04000000 - 0x05ffffff(CS1)	| PLD		| PLD
- * 0x06000000 - 0x07ffffff(CS1)	| reserved	| I2C
+ * 0x06000000 - 0x07ffffff(CS1)	| I2C		| I2C
  * 0x08000000 - 0x0bffffff(CS2)	| USB		| DDR SDRAM
  * 0x0c000000 - 0x0fffffff(CS3)	| SD		| DDR SDRAM
  * 0x10000000 - 0x13ffffff(CS4)	| SM107		| SM107
- * 0x14000000 - 0x17ffffff(CS5)	| I2C		| USB
+ * 0x14000000 - 0x17ffffff(CS5)	| reserved	| USB
  * 0x18000000 - 0x1bffffff(CS6)	| reserved	| SD
  * 0x40000000 - 0x5fffffff	| DDR SDRAM	| (cannot use)
  *
@@ -32,6 +32,9 @@
 #define PLD_VERSR		(PLD_BASE_ADDR + 0x0c)
 #define PLD_MMSR		(PLD_BASE_ADDR + 0x0e)
 
+#define PCA9564_ADDR		0x06000000	/* I2C */
+#define PCA9564_SIZE		0x00000100
+
 #define SM107_MEM_ADDR		0x10000000
 #define SM107_MEM_SIZE		0x00e00000
 #define SM107_REG_ADDR		0x13e00000
@@ -40,16 +43,13 @@
 #if defined(CONFIG_SH_SH7785LCR_29BIT_PHYSMAPS)
 #define R8A66597_ADDR		0x14000000	/* USB */
 #define CG200_ADDR		0x18000000	/* SD */
-#define PCA9564_ADDR		0x06000000	/* I2C */
 #else
 #define R8A66597_ADDR		0x08000000
 #define CG200_ADDR		0x0c000000
-#define PCA9564_ADDR		0x14000000
 #endif
 
 #define R8A66597_SIZE		0x00000100
 #define CG200_SIZE		0x00010000
-#define PCA9564_SIZE		0x00000100
 
 #endif  /* __ASM_SH_RENESAS_SH7785LCR_H */
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/mach-dreamcast/mach/pci.h linux-libre-2.6.31-gnu/arch/sh/include/mach-dreamcast/mach/pci.h
--- linux-libre-2.6.30-gnu/arch/sh/include/mach-dreamcast/mach/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/include/mach-dreamcast/mach/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,5 +21,7 @@
 
 #define	GAPSPCI_IRQ		HW_EVENT_EXTERNAL
 
+extern struct pci_ops gapspci_pci_ops;
+
 #endif /* __ASM_SH_DREAMCAST_PCI_H */
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/include/mach-se/mach/se7724.h linux-libre-2.6.31-gnu/arch/sh/include/mach-se/mach/se7724.h
--- linux-libre-2.6.30-gnu/arch/sh/include/mach-se/mach/se7724.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/include/mach-se/mach/se7724.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,72 @@
+#ifndef __ASM_SH_SE7724_H
+#define __ASM_SH_SE7724_H
+
+/*
+ * linux/include/asm-sh/se7724.h
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Hitachi UL SolutionEngine 7724 Support.
+ *
+ * Based on se7722.h
+ * Copyright (C) 2007  Nobuhiro Iwamatsu
+ *
+ * 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/addrspace.h>
+
+/* SH Eth */
+#define SH_ETH_ADDR	(0xA4600000)
+#define SH_ETH_MAHR	(SH_ETH_ADDR + 0x1C0)
+#define SH_ETH_MALR	(SH_ETH_ADDR + 0x1C8)
+
+#define PA_LED		(0xba203000)	/* 8bit LED */
+#define IRQ_MODE	(0xba200010)
+#define IRQ0_SR		(0xba200014)
+#define IRQ1_SR		(0xba200018)
+#define IRQ2_SR		(0xba20001c)
+#define IRQ0_MR		(0xba200020)
+#define IRQ1_MR		(0xba200024)
+#define IRQ2_MR		(0xba200028)
+
+/* IRQ */
+#define IRQ0_IRQ        32
+#define IRQ1_IRQ        33
+#define IRQ2_IRQ        34
+
+/* Bits in IRQ012 registers */
+#define SE7724_FPGA_IRQ_BASE	220
+
+/* IRQ0 */
+#define IRQ0_BASE	SE7724_FPGA_IRQ_BASE
+#define IRQ0_KEY	(IRQ0_BASE + 12)
+#define IRQ0_RMII	(IRQ0_BASE + 13)
+#define IRQ0_SMC	(IRQ0_BASE + 14)
+#define IRQ0_MASK	0x7fff
+#define IRQ0_END	IRQ0_SMC
+/* IRQ1 */
+#define IRQ1_BASE	(IRQ0_END + 1)
+#define IRQ1_TS		(IRQ1_BASE + 0)
+#define IRQ1_MASK	0x0001
+#define IRQ1_END	IRQ1_TS
+/* IRQ2 */
+#define IRQ2_BASE	(IRQ1_END + 1)
+#define IRQ2_USB0	(IRQ1_BASE + 0)
+#define IRQ2_USB1	(IRQ1_BASE + 1)
+#define IRQ2_MASK	0x0003
+#define IRQ2_END	IRQ2_USB1
+
+#define SE7724_FPGA_IRQ_NR	(IRQ2_END - IRQ0_BASE)
+
+/* arch/sh/boards/se/7724/irq.c */
+void init_se7724_IRQ(void);
+
+#define __IO_PREFIX		se7724
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_SE7724_H */
diff -druN linux-libre-2.6.30-gnu/arch/sh/Kconfig linux-libre-2.6.31-gnu/arch/sh/Kconfig
--- linux-libre-2.6.30-gnu/arch/sh/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,9 @@
 	select HAVE_IOREMAP_PROT if MMU
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_DMA_API_DEBUG
+	select HAVE_PERF_COUNTERS
+	select RTC_LIB
+	select GENERIC_ATOMIC64
 	help
 	  The SuperH is a RISC processor targeted for use in embedded systems
 	  and consumer electronics; it was also used in the Sega Dreamcast
@@ -49,6 +52,10 @@
 	def_bool y
 	depends on BUG && SUPERH32
 
+config GENERIC_CSUM
+	def_bool y
+	depends on SUPERH64
+
 config GENERIC_FIND_NEXT_BIT
 	def_bool y
 
@@ -64,6 +71,9 @@
 config GENERIC_IRQ_PROBE
 	def_bool y
 
+config IRQ_PER_CPU
+	def_bool y
+
 config GENERIC_GPIO
 	def_bool n
 
@@ -74,14 +84,18 @@
 	bool
 
 config GENERIC_TIME
-	def_bool n
+	def_bool y
 
 config GENERIC_CLOCKEVENTS
-	def_bool n
+	def_bool y
 
 config GENERIC_CLOCKEVENTS_BROADCAST
 	bool
 
+config GENERIC_CMOS_UPDATE
+	def_bool y
+	depends on SH_SH03 || SH_DREAMCAST
+
 config GENERIC_LOCKBREAK
 	def_bool y
 	depends on SMP && PREEMPT
@@ -112,6 +126,12 @@
 config SYS_SUPPORTS_CMT
 	bool
 
+config SYS_SUPPORTS_MTU2
+	bool
+
+config SYS_SUPPORTS_TMU
+	bool
+
 config STACKTRACE_SUPPORT
 	def_bool y
 
@@ -134,6 +154,9 @@
 config ARCH_HAS_DEFAULT_IDLE
 	def_bool y
 
+config ARCH_HAS_CPU_IDLE_WAIT
+	def_bool y
+
 config IO_TRAPPED
 	bool
 
@@ -157,13 +180,14 @@
 	bool
 	select CPU_HAS_INTEVT
 	select CPU_HAS_SR_RB
+	select SYS_SUPPORTS_TMU
 
 config CPU_SH4
 	bool
 	select CPU_HAS_INTEVT
 	select CPU_HAS_SR_RB
-	select CPU_HAS_PTEA if !CPU_SH4A || CPU_SHX2
 	select CPU_HAS_FPU if !CPU_SH4AL_DSP
+	select SYS_SUPPORTS_TMU
 
 config CPU_SH4A
 	bool
@@ -177,6 +201,7 @@
 config CPU_SH5
 	bool
 	select CPU_HAS_FPU
+	select SYS_SUPPORTS_TMU
 
 config CPU_SHX2
 	bool
@@ -210,27 +235,32 @@
 	bool "Support SH7201 processor"
 	select CPU_SH2A
 	select CPU_HAS_FPU
+	select SYS_SUPPORTS_MTU2
  
 config CPU_SUBTYPE_SH7203
 	bool "Support SH7203 processor"
 	select CPU_SH2A
 	select CPU_HAS_FPU
 	select SYS_SUPPORTS_CMT
+	select SYS_SUPPORTS_MTU2
 
 config CPU_SUBTYPE_SH7206
 	bool "Support SH7206 processor"
 	select CPU_SH2A
 	select SYS_SUPPORTS_CMT
+	select SYS_SUPPORTS_MTU2
 
 config CPU_SUBTYPE_SH7263
 	bool "Support SH7263 processor"
 	select CPU_SH2A
 	select CPU_HAS_FPU
 	select SYS_SUPPORTS_CMT
+	select SYS_SUPPORTS_MTU2
 
 config CPU_SUBTYPE_MXG
 	bool "Support MX-G processor"
 	select CPU_SH2A
+	select SYS_SUPPORTS_MTU2
 	help
 	  Select MX-G if running on an R8A03022BG part.
 
@@ -283,6 +313,7 @@
 	bool "Support SH7720 processor"
 	select CPU_SH3
 	select CPU_HAS_DSP
+	select SYS_SUPPORTS_CMT
 	help
 	  Select SH7720 if you have a SH3-DSP SH7720 CPU.
 
@@ -290,6 +321,7 @@
 	bool "Support SH7721 processor"
 	select CPU_SH3
 	select CPU_HAS_DSP
+	select SYS_SUPPORTS_CMT
 	help
 	  Select SH7721 if you have a SH3-DSP SH7721 CPU.
 
@@ -347,6 +379,16 @@
 	help
 	  Select SH7723 if you have an SH-MobileR2 CPU.
 
+config CPU_SUBTYPE_SH7724
+	bool "Support SH7724 processor"
+	select CPU_SH4A
+	select CPU_SHX2
+	select ARCH_SHMOBILE
+	select ARCH_SPARSEMEM_ENABLE
+	select SYS_SUPPORTS_CMT
+	help
+	  Select SH7724 if you have an SH-MobileR2R CPU.
+
 config CPU_SUBTYPE_SH7763
 	bool "Support SH7763 processor"
 	select CPU_SH4A
@@ -375,6 +417,8 @@
 	select CPU_HAS_PTEAEX
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
+	select SYS_SUPPORTS_SMP
+	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
 
 config CPU_SUBTYPE_SHX3
 	bool "Support SH-X3 processor"
@@ -442,48 +486,26 @@
 
 menu "Timer and clock configuration"
 
-config SH_TMU
-	bool "TMU timer support"
-	depends on CPU_SH3 || CPU_SH4
+config SH_TIMER_TMU
+	bool "TMU timer driver"
+	depends on SYS_SUPPORTS_TMU
 	default y
-	select GENERIC_TIME
-	select GENERIC_CLOCKEVENTS
 	help
-	  This enables the use of the TMU as the system timer.
+	  This enables the build of the TMU timer driver.
 
-config SH_CMT
-	bool "CMT timer support"
-	depends on SYS_SUPPORTS_CMT && CPU_SH2
+config SH_TIMER_CMT
+	bool "CMT timer driver"
+	depends on SYS_SUPPORTS_CMT
 	default y
 	help
-	  This enables the use of the CMT as the system timer.
-
-#
-# Support for the new-style CMT driver. This will replace SH_CMT
-# once its other dependencies are merged.
-#
-config SH_TIMER_CMT
-	bool "CMT clockevents driver"
-	depends on SYS_SUPPORTS_CMT && !SH_CMT
-	select GENERIC_CLOCKEVENTS
+	  This enables build of the CMT timer driver.
 
-config SH_MTU2
-	bool "MTU2 timer support"
-	depends on CPU_SH2A
+config SH_TIMER_MTU2
+	bool "MTU2 timer driver"
+	depends on SYS_SUPPORTS_MTU2
 	default y
 	help
-	  This enables the use of the MTU2 as the system timer.
-
-config SH_TIMER_IRQ
-	int
-	default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 || \
-			CPU_SUBTYPE_SH7763
-	default "86" if CPU_SUBTYPE_SH7619
-	default "140" if CPU_SUBTYPE_SH7206
-	default "142" if CPU_SUBTYPE_SH7203 && SH_CMT
-	default "153" if CPU_SUBTYPE_SH7203 && SH_MTU2
-	default "238" if CPU_SUBTYPE_MXG
-	default "16"
+	  This enables build of the MTU2 timer driver.
 
 config SH_PCLK_FREQ
 	int "Peripheral clock frequency (in Hz)"
@@ -494,7 +516,7 @@
 			      CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
 			      CPU_SUBTYPE_SH7203 || CPU_SUBTYPE_SH7206 || \
 			      CPU_SUBTYPE_SH7263 || CPU_SUBTYPE_MXG    || \
-			      CPU_SUBTYPE_SH7786
+			      CPU_SUBTYPE_SH7786 || CPU_SUBTYPE_SH7724
 	default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
 	default "66000000" if CPU_SUBTYPE_SH4_202
 	default "50000000"
@@ -503,6 +525,13 @@
 	  This is necessary for determining the reference clock value on
 	  platforms lacking an RTC.
 
+config SH_CLK_CPG
+	def_bool y
+
+config SH_CLK_CPG_LEGACY
+	depends on SH_CLK_CPG
+	def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE
+
 config SH_CLK_MD
 	int "CPU Mode Pin Setting"
 	depends on CPU_SH2
@@ -627,7 +656,7 @@
 	int "Maximum number of CPUs (2-32)"
 	range 2 32
 	depends on SMP
-	default "4" if CPU_SHX3
+	default "4" if CPU_SUBTYPE_SHX3
 	default "2"
 	help
 	  This allows you to specify the maximum number of CPUs which this
@@ -663,27 +692,54 @@
 	  LLSC, this should be more efficient than the other alternative of
 	  disabling interrupts around the atomic sequence.
 
+config SPARSE_IRQ
+	bool "Support sparse irq numbering"
+	depends on EXPERIMENTAL
+	help
+	  This enables support for sparse irqs. This is useful in general
+	  as most CPUs have a fairly sparse array of IRQ vectors, which
+	  the irq_desc then maps directly on to. Systems with a high
+	  number of off-chip IRQs will want to treat this as
+	  experimental until they have been independently verified.
+
+	  If you don't know what to do here, say N.
+
 endmenu
 
 menu "Boot options"
 
 config ZERO_PAGE_OFFSET
-	hex "Zero page offset"
-	default "0x00004000" if SH_SH03
-	default "0x00010000" if PAGE_SIZE_64KB
+	hex
+	default "0x00010000" if PAGE_SIZE_64KB || SH_RTS7751R2D || \
+				SH_7751_SOLUTION_ENGINE
+	default "0x00004000" if PAGE_SIZE_16KB || SH_SH03
 	default "0x00002000" if PAGE_SIZE_8KB
 	default "0x00001000"
 	help
 	  This sets the default offset of zero page.
 
 config BOOT_LINK_OFFSET
-	hex "Link address offset for booting"
+	hex
+	default "0x00210000" if SH_SHMIN
+	default "0x00400000" if SH_CAYMAN
+	default "0x00810000" if SH_7780_SOLUTION_ENGINE
+	default "0x009e0000" if SH_TITAN
+	default "0x01800000" if SH_SDK7780
+	default "0x02000000" if SH_EDOSK7760
 	default "0x00800000"
 	help
 	  This option allows you to set the link address offset of the zImage.
 	  This can be useful if you are on a board which has a small amount of
 	  memory.
 
+config ENTRY_OFFSET
+	hex
+	default "0x00001000" if PAGE_SIZE_4KB
+	default "0x00002000" if PAGE_SIZE_8KB
+	default "0x00004000" if PAGE_SIZE_16KB
+	default "0x00010000" if PAGE_SIZE_64KB
+	default "0x00000000"
+
 config UBC_WAKEUP
 	bool "Wakeup UBC on startup"
 	depends on CPU_SH4 && !CPU_SH4A
diff -druN linux-libre-2.6.30-gnu/arch/sh/Kconfig.cpu linux-libre-2.6.31-gnu/arch/sh/Kconfig.cpu
--- linux-libre-2.6.30-gnu/arch/sh/Kconfig.cpu	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/Kconfig.cpu	2009-09-09 18:13:59.000000000 -0400
@@ -76,11 +76,6 @@
 
 	  If unsure, say N.
 
-config SH64_USER_MISALIGNED_FIXUP
-	def_bool y
-	prompt "Fixup misaligned loads/stores occurring in user mode"
-	depends on SUPERH64
-
 config SH64_ID2815_WORKAROUND
 	bool "Include workaround for SH5-101 cut2 silicon defect ID2815"
 	depends on CPU_SUBTYPE_SH5_101
@@ -101,9 +96,6 @@
 	  See <file:Documentation/sh/register-banks.txt> for further
 	  information on SR.RB and register banking in the kernel in general.
 
-config CPU_HAS_PTEA
-	bool
-
 config CPU_HAS_PTEAEX
 	bool
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/Kconfig.debug linux-libre-2.6.31-gnu/arch/sh/Kconfig.debug
--- linux-libre-2.6.30-gnu/arch/sh/Kconfig.debug	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/Kconfig.debug	2009-09-09 18:13:59.000000000 -0400
@@ -38,10 +38,11 @@
 	default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
 				CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
 				CPU_SUBTYPE_SH7343
-	default "0xffe80000" if CPU_SH4
 	default "0xffea0000" if CPU_SUBTYPE_SH7785
+	default "0xffeb0000" if CPU_SUBTYPE_SH7786
 	default "0xfffe8000" if CPU_SUBTYPE_SH7203
 	default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
+	default "0xffe80000" if CPU_SH4
 	default "0x00000000"
 
 config EARLY_PRINTK
@@ -60,10 +61,6 @@
 	  select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
 	  the kernel command line option to toggle back and forth.
 
-config DEBUG_BOOTMEM
-	depends on DEBUG_KERNEL
-	bool "Debug BOOTMEM initialization"
-
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL && SUPERH32
@@ -92,7 +89,7 @@
 
 config IRQSTACKS
 	bool "Use separate kernel stacks when processing interrupts"
-	depends on DEBUG_KERNEL && SUPERH32
+	depends on DEBUG_KERNEL && SUPERH32 && BROKEN
 	help
 	  If you say Y here the kernel will use separate kernel stacks
 	  for handling hard and soft interrupts.  This can help avoid
@@ -122,27 +119,8 @@
 	  For all other cases, say N. If this option seems perplexing, or
 	  you aren't sure, say N.
 
-config MORE_COMPILE_OPTIONS
-	bool "Add any additional compile options"
-	help
-	  If you want to add additional CFLAGS to the kernel build, enable this
-	  option and then enter what you would like to add in the next question.
-	  Note however that -g is already appended with the selection of KGDB.
-
-config COMPILE_OPTIONS
-	string "Additional compile arguments"
-	depends on MORE_COMPILE_OPTIONS
-
 config SH64_SR_WATCH
 	bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
 	depends on SUPERH64
 
-config POOR_MANS_STRACE
-	bool "Debug: enable rudimentary strace facility"
-	depends on SUPERH64
-	help
-	  This option allows system calls to be traced to the console.  It also
-	  aids in detecting kernel stack underflow.  It is useful for debugging
-	  early-userland problems (e.g. init incurring fatal exceptions.)
-
 endmenu
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/clock.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/clock.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/clock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/clock.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,15 +1,19 @@
 /*
  * arch/sh/kernel/cpu/clock.c - SuperH clock framework
  *
- *  Copyright (C) 2005, 2006, 2007  Paul Mundt
+ *  Copyright (C) 2005 - 2009  Paul Mundt
  *
  * This clock framework is derived from the OMAP version by:
  *
- *	Copyright (C) 2004 - 2005 Nokia Corporation
+ *	Copyright (C) 2004 - 2008 Nokia Corporation
  *	Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *
  *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
  *
+ *  With clkdev bits:
+ *
+ *	Copyright (C) 2008 Russell King.
+ *
  * 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.
@@ -19,134 +23,159 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
-#include <linux/kref.h>
 #include <linux/kobject.h>
 #include <linux/sysdev.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
-#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/cpufreq.h>
 #include <asm/clock.h>
-#include <asm/timer.h>
+#include <asm/machvec.h>
 
 static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
 static DEFINE_MUTEX(clock_list_sem);
 
-/*
- * Each subtype is expected to define the init routines for these clocks,
- * as each subtype (or processor family) will have these clocks at the
- * very least. These are all provided through the CPG, which even some of
- * the more quirky parts (such as ST40, SH4-202, etc.) still have.
- *
- * The processor-specific code is expected to register any additional
- * clock sources that are of interest.
- */
-static struct clk master_clk = {
-	.name		= "master_clk",
-	.flags		= CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
-	.rate		= CONFIG_SH_PCLK_FREQ,
-};
+void clk_rate_table_build(struct clk *clk,
+			  struct cpufreq_frequency_table *freq_table,
+			  int nr_freqs,
+			  struct clk_div_mult_table *src_table,
+			  unsigned long *bitmap)
+{
+	unsigned long mult, div;
+	unsigned long freq;
+	int i;
 
-static struct clk module_clk = {
-	.name		= "module_clk",
-	.parent		= &master_clk,
-	.flags		= CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
-};
+	for (i = 0; i < nr_freqs; i++) {
+		div = 1;
+		mult = 1;
 
-static struct clk bus_clk = {
-	.name		= "bus_clk",
-	.parent		= &master_clk,
-	.flags		= CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
-};
+		if (src_table->divisors && i < src_table->nr_divisors)
+			div = src_table->divisors[i];
 
-static struct clk cpu_clk = {
-	.name		= "cpu_clk",
-	.parent		= &master_clk,
-	.flags		= CLK_ALWAYS_ENABLED,
-};
+		if (src_table->multipliers && i < src_table->nr_multipliers)
+			mult = src_table->multipliers[i];
 
-/*
- * The ordering of these clocks matters, do not change it.
- */
-static struct clk *onchip_clocks[] = {
-	&master_clk,
-	&module_clk,
-	&bus_clk,
-	&cpu_clk,
-};
+		if (!div || !mult || (bitmap && !test_bit(i, bitmap)))
+			freq = CPUFREQ_ENTRY_INVALID;
+		else
+			freq = clk->parent->rate * mult / div;
 
-static void propagate_rate(struct clk *clk)
+		freq_table[i].index = i;
+		freq_table[i].frequency = freq;
+	}
+
+	/* Termination entry */
+	freq_table[i].index = i;
+	freq_table[i].frequency = CPUFREQ_TABLE_END;
+}
+
+long clk_rate_table_round(struct clk *clk,
+			  struct cpufreq_frequency_table *freq_table,
+			  unsigned long rate)
 {
-	struct clk *clkp;
+	unsigned long rate_error, rate_error_prev = ~0UL;
+	unsigned long rate_best_fit = rate;
+	unsigned long highest, lowest;
+	int i;
 
-	list_for_each_entry(clkp, &clock_list, node) {
-		if (likely(clkp->parent != clk))
+	highest = lowest = 0;
+
+	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+		unsigned long freq = freq_table[i].frequency;
+
+		if (freq == CPUFREQ_ENTRY_INVALID)
 			continue;
-		if (likely(clkp->ops && clkp->ops->recalc))
-			clkp->ops->recalc(clkp);
-		if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
-			propagate_rate(clkp);
+
+		if (freq > highest)
+			highest = freq;
+		if (freq < lowest)
+			lowest = freq;
+
+		rate_error = abs(freq - rate);
+		if (rate_error < rate_error_prev) {
+			rate_best_fit = freq;
+			rate_error_prev = rate_error;
+		}
+
+		if (rate_error == 0)
+			break;
 	}
+
+	if (rate >= highest)
+		rate_best_fit = highest;
+	if (rate <= lowest)
+		rate_best_fit = lowest;
+
+	return rate_best_fit;
 }
 
-static int __clk_enable(struct clk *clk)
+int clk_rate_table_find(struct clk *clk,
+			struct cpufreq_frequency_table *freq_table,
+			unsigned long rate)
 {
-	/*
-	 * See if this is the first time we're enabling the clock, some
-	 * clocks that are always enabled still require "special"
-	 * initialization. This is especially true if the clock mode
-	 * changes and the clock needs to hunt for the proper set of
-	 * divisors to use before it can effectively recalc.
-	 */
-	if (unlikely(atomic_read(&clk->kref.refcount) == 1))
-		if (clk->ops && clk->ops->init)
-			clk->ops->init(clk);
+	int i;
 
-	kref_get(&clk->kref);
+	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+		unsigned long freq = freq_table[i].frequency;
 
-	if (clk->flags & CLK_ALWAYS_ENABLED)
-		return 0;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
 
-	if (likely(clk->ops && clk->ops->enable))
-		clk->ops->enable(clk);
+		if (freq == rate)
+			return i;
+	}
 
-	return 0;
+	return -ENOENT;
 }
 
-int clk_enable(struct clk *clk)
+/* Used for clocks that always have same value as the parent clock */
+unsigned long followparent_recalc(struct clk *clk)
 {
-	unsigned long flags;
-	int ret;
-
-	if (!clk)
-		return -EINVAL;
+	return clk->parent ? clk->parent->rate : 0;
+}
 
-	clk_enable(clk->parent);
+int clk_reparent(struct clk *child, struct clk *parent)
+{
+	list_del_init(&child->sibling);
+	if (parent)
+		list_add(&child->sibling, &parent->children);
+	child->parent = parent;
 
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = __clk_enable(clk);
-	spin_unlock_irqrestore(&clock_lock, flags);
+	/* now do the debugfs renaming to reattach the child
+	   to the proper parent */
 
-	return ret;
+	return 0;
 }
-EXPORT_SYMBOL_GPL(clk_enable);
 
-static void clk_kref_release(struct kref *kref)
+/* Propagate rate to children */
+void propagate_rate(struct clk *tclk)
 {
-	/* Nothing to do */
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &tclk->children, sibling) {
+		if (clkp->ops && clkp->ops->recalc)
+			clkp->rate = clkp->ops->recalc(clkp);
+
+		propagate_rate(clkp);
+	}
 }
 
 static void __clk_disable(struct clk *clk)
 {
-	int count = kref_put(&clk->kref, clk_kref_release);
-
-	if (clk->flags & CLK_ALWAYS_ENABLED)
+	if (clk->usecount == 0) {
+		printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
+		       clk->name);
+		WARN_ON(1);
 		return;
+	}
 
-	if (!count) {	/* count reaches zero, disable the clock */
+	if (!(--clk->usecount)) {
 		if (likely(clk->ops && clk->ops->disable))
 			clk->ops->disable(clk);
+		if (likely(clk->parent))
+			__clk_disable(clk->parent);
 	}
 }
 
@@ -160,28 +189,97 @@
 	spin_lock_irqsave(&clock_lock, flags);
 	__clk_disable(clk);
 	spin_unlock_irqrestore(&clock_lock, flags);
-
-	clk_disable(clk->parent);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
+static int __clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (clk->usecount++ == 0) {
+		if (clk->parent) {
+			ret = __clk_enable(clk->parent);
+			if (unlikely(ret))
+				goto err;
+		}
+
+		if (clk->ops && clk->ops->enable) {
+			ret = clk->ops->enable(clk);
+			if (ret) {
+				if (clk->parent)
+					__clk_disable(clk->parent);
+				goto err;
+			}
+		}
+	}
+
+	return ret;
+err:
+	clk->usecount--;
+	return ret;
+}
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret;
+
+	if (!clk)
+		return -EINVAL;
+
+	spin_lock_irqsave(&clock_lock, flags);
+	ret = __clk_enable(clk);
+	spin_unlock_irqrestore(&clock_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+static LIST_HEAD(root_clks);
+
+/**
+ * recalculate_root_clocks - recalculate and propagate all root clocks
+ *
+ * Recalculates all root clocks (clocks with no parent), which if the
+ * clock's .recalc is set correctly, should also propagate their rates.
+ * Called at init.
+ */
+void recalculate_root_clocks(void)
+{
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &root_clks, sibling) {
+		if (clkp->ops && clkp->ops->recalc)
+			clkp->rate = clkp->ops->recalc(clkp);
+		propagate_rate(clkp);
+	}
+}
+
 int clk_register(struct clk *clk)
 {
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	/*
+	 * trap out already registered clocks
+	 */
+	if (clk->node.next || clk->node.prev)
+		return 0;
+
 	mutex_lock(&clock_list_sem);
 
-	list_add(&clk->node, &clock_list);
-	kref_init(&clk->kref);
+	INIT_LIST_HEAD(&clk->children);
+	clk->usecount = 0;
 
-	mutex_unlock(&clock_list_sem);
+	if (clk->parent)
+		list_add(&clk->sibling, &clk->parent->children);
+	else
+		list_add(&clk->sibling, &root_clks);
 
-	if (clk->flags & CLK_ALWAYS_ENABLED) {
-		pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name);
-		if (clk->ops && clk->ops->init)
-			clk->ops->init(clk);
-		if (clk->ops && clk->ops->enable)
-			clk->ops->enable(clk);
-		pr_debug( "Enabled.");
-	}
+	list_add(&clk->node, &clock_list);
+	if (clk->ops && clk->ops->init)
+		clk->ops->init(clk);
+	mutex_unlock(&clock_list_sem);
 
 	return 0;
 }
@@ -190,11 +288,21 @@
 void clk_unregister(struct clk *clk)
 {
 	mutex_lock(&clock_list_sem);
+	list_del(&clk->sibling);
 	list_del(&clk->node);
 	mutex_unlock(&clock_list_sem);
 }
 EXPORT_SYMBOL_GPL(clk_unregister);
 
+static void clk_enable_init_clocks(void)
+{
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &clock_list, node)
+		if (clkp->flags & CLK_ENABLE_ON_INIT)
+			clk_enable(clkp);
+}
+
 unsigned long clk_get_rate(struct clk *clk)
 {
 	return clk->rate;
@@ -210,56 +318,59 @@
 int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
 {
 	int ret = -EOPNOTSUPP;
+	unsigned long flags;
 
-	if (likely(clk->ops && clk->ops->set_rate)) {
-		unsigned long flags;
+	spin_lock_irqsave(&clock_lock, flags);
 
-		spin_lock_irqsave(&clock_lock, flags);
+	if (likely(clk->ops && clk->ops->set_rate)) {
 		ret = clk->ops->set_rate(clk, rate, algo_id);
-		spin_unlock_irqrestore(&clock_lock, flags);
+		if (ret != 0)
+			goto out_unlock;
+	} else {
+		clk->rate = rate;
+		ret = 0;
 	}
 
-	if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
-		propagate_rate(clk);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(clk_set_rate_ex);
+	if (clk->ops && clk->ops->recalc)
+		clk->rate = clk->ops->recalc(clk);
 
-void clk_recalc_rate(struct clk *clk)
-{
-	if (likely(clk->ops && clk->ops->recalc)) {
-		unsigned long flags;
+	propagate_rate(clk);
 
-		spin_lock_irqsave(&clock_lock, flags);
-		clk->ops->recalc(clk);
-		spin_unlock_irqrestore(&clock_lock, flags);
-	}
+out_unlock:
+	spin_unlock_irqrestore(&clock_lock, flags);
 
-	if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
-		propagate_rate(clk);
+	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_recalc_rate);
+EXPORT_SYMBOL_GPL(clk_set_rate_ex);
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
+	unsigned long flags;
 	int ret = -EINVAL;
-	struct clk *old;
 
 	if (!parent || !clk)
 		return ret;
+	if (clk->parent == parent)
+		return 0;
 
-	old = clk->parent;
-	if (likely(clk->ops && clk->ops->set_parent)) {
-		unsigned long flags;
-		spin_lock_irqsave(&clock_lock, flags);
-		ret = clk->ops->set_parent(clk, parent);
-		spin_unlock_irqrestore(&clock_lock, flags);
-		clk->parent = (ret ? old : parent);
-	}
+	spin_lock_irqsave(&clock_lock, flags);
+	if (clk->usecount == 0) {
+		if (clk->ops->set_parent)
+			ret = clk->ops->set_parent(clk, parent);
+		else
+			ret = clk_reparent(clk, parent);
+
+		if (ret == 0) {
+			pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
+				 clk->name, clk->parent->name, clk->rate);
+			if (clk->ops->recalc)
+				clk->rate = clk->ops->recalc(clk);
+			propagate_rate(clk);
+		}
+	} else
+		ret = -EBUSY;
+	spin_unlock_irqrestore(&clock_lock, flags);
 
-	if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
-		propagate_rate(clk);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_set_parent);
@@ -287,14 +398,69 @@
 EXPORT_SYMBOL_GPL(clk_round_rate);
 
 /*
+ * Find the correct struct clk for the device and connection ID.
+ * We do slightly fuzzy matching here:
+ *  An entry with a NULL ID is assumed to be a wildcard.
+ *  If an entry has a device ID, it must match
+ *  If an entry has a connection ID, it must match
+ * Then we take the most specific entry - with the following
+ * order of precidence: dev+con > dev only > con only.
+ */
+static struct clk *clk_find(const char *dev_id, const char *con_id)
+{
+	struct clk_lookup *p;
+	struct clk *clk = NULL;
+	int match, best = 0;
+
+	list_for_each_entry(p, &clock_list, node) {
+		match = 0;
+		if (p->dev_id) {
+			if (!dev_id || strcmp(p->dev_id, dev_id))
+				continue;
+			match += 2;
+		}
+		if (p->con_id) {
+			if (!con_id || strcmp(p->con_id, con_id))
+				continue;
+			match += 1;
+		}
+		if (match == 0)
+			continue;
+
+		if (match > best) {
+			clk = p->clk;
+			best = match;
+		}
+	}
+	return clk;
+}
+
+struct clk *clk_get_sys(const char *dev_id, const char *con_id)
+{
+	struct clk *clk;
+
+	mutex_lock(&clock_list_sem);
+	clk = clk_find(dev_id, con_id);
+	mutex_unlock(&clock_list_sem);
+
+	return clk ? clk : ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(clk_get_sys);
+
+/*
  * Returns a clock. Note that we first try to use device id on the bus
  * and clock name. If this fails, we try to use clock name only.
  */
 struct clk *clk_get(struct device *dev, const char *id)
 {
+	const char *dev_id = dev ? dev_name(dev) : NULL;
 	struct clk *p, *clk = ERR_PTR(-ENOENT);
 	int idno;
 
+	clk = clk_get_sys(dev_id, id);
+	if (clk && !IS_ERR(clk))
+		return clk;
+
 	if (dev == NULL || dev->bus != &platform_bus_type)
 		idno = -1;
 	else
@@ -330,36 +496,6 @@
 }
 EXPORT_SYMBOL_GPL(clk_put);
 
-void __init __attribute__ ((weak))
-arch_init_clk_ops(struct clk_ops **ops, int type)
-{
-}
-
-int __init __attribute__ ((weak))
-arch_clk_init(void)
-{
-	return 0;
-}
-
-static int show_clocks(char *buf, char **start, off_t off,
-		       int len, int *eof, void *data)
-{
-	struct clk *clk;
-	char *p = buf;
-
-	list_for_each_entry_reverse(clk, &clock_list, node) {
-		unsigned long rate = clk_get_rate(clk);
-
-		p += sprintf(p, "%-12s\t: %ld.%02ldMHz\t%s\n", clk->name,
-			     rate / 1000000, (rate % 1000000) / 10000,
-			     ((clk->flags & CLK_ALWAYS_ENABLED) ||
-			      (atomic_read(&clk->kref.refcount) != 1)) ?
-			     "enabled" : "disabled");
-	}
-
-	return p - buf;
-}
-
 #ifdef CONFIG_PM
 static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
 {
@@ -369,20 +505,22 @@
 	switch (state.event) {
 	case PM_EVENT_ON:
 		/* Resumeing from hibernation */
-		if (prev_state.event == PM_EVENT_FREEZE) {
-			list_for_each_entry(clkp, &clock_list, node)
-				if (likely(clkp->ops)) {
-					unsigned long rate = clkp->rate;
+		if (prev_state.event != PM_EVENT_FREEZE)
+			break;
 
-					if (likely(clkp->ops->set_parent))
-						clkp->ops->set_parent(clkp,
-							clkp->parent);
-					if (likely(clkp->ops->set_rate))
-						clkp->ops->set_rate(clkp,
-							rate, NO_CHANGE);
-					else if (likely(clkp->ops->recalc))
-						clkp->ops->recalc(clkp);
-					}
+		list_for_each_entry(clkp, &clock_list, node) {
+			if (likely(clkp->ops)) {
+				unsigned long rate = clkp->rate;
+
+				if (likely(clkp->ops->set_parent))
+					clkp->ops->set_parent(clkp,
+						clkp->parent);
+				if (likely(clkp->ops->set_rate))
+					clkp->ops->set_rate(clkp,
+						rate, NO_CHANGE);
+				else if (likely(clkp->ops->recalc))
+					clkp->rate = clkp->ops->recalc(clkp);
+			}
 		}
 		break;
 	case PM_EVENT_FREEZE:
@@ -426,34 +564,116 @@
 
 int __init clk_init(void)
 {
-	int i, ret = 0;
-
-	BUG_ON(!master_clk.rate);
-
-	for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
-		struct clk *clk = onchip_clocks[i];
+	int ret;
 
-		arch_init_clk_ops(&clk->ops, i);
-		ret |= clk_register(clk);
+	ret = arch_clk_init();
+	if (unlikely(ret)) {
+		pr_err("%s: CPU clock registration failed.\n", __func__);
+		return ret;
 	}
 
-	ret |= arch_clk_init();
+	if (sh_mv.mv_clk_init) {
+		ret = sh_mv.mv_clk_init();
+		if (unlikely(ret)) {
+			pr_err("%s: machvec clock initialization failed.\n",
+			       __func__);
+			return ret;
+		}
+	}
 
 	/* Kick the child clocks.. */
-	propagate_rate(&master_clk);
-	propagate_rate(&bus_clk);
+	recalculate_root_clocks();
+
+	/* Enable the necessary init clocks */
+	clk_enable_init_clocks();
 
 	return ret;
 }
 
-static int __init clk_proc_init(void)
+/*
+ *	debugfs support to trace clock tree hierarchy and attributes
+ */
+static struct dentry *clk_debugfs_root;
+
+static int clk_debugfs_register_one(struct clk *c)
 {
-	struct proc_dir_entry *p;
-	p = create_proc_read_entry("clocks", S_IRUSR, NULL,
-				   show_clocks, NULL);
-	if (unlikely(!p))
-		return -EINVAL;
+	int err;
+	struct dentry *d, *child;
+	struct clk *pa = c->parent;
+	char s[255];
+	char *p = s;
+
+	p += sprintf(p, "%s", c->name);
+	if (c->id >= 0)
+		sprintf(p, ":%d", c->id);
+	d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
+	if (!d)
+		return -ENOMEM;
+	c->dentry = d;
 
+	d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
 	return 0;
+
+err_out:
+	d = c->dentry;
+	list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
+		debugfs_remove(child);
+	debugfs_remove(c->dentry);
+	return err;
 }
-subsys_initcall(clk_proc_init);
+
+static int clk_debugfs_register(struct clk *c)
+{
+	int err;
+	struct clk *pa = c->parent;
+
+	if (pa && !pa->dentry) {
+		err = clk_debugfs_register(pa);
+		if (err)
+			return err;
+	}
+
+	if (!c->dentry) {
+		err = clk_debugfs_register_one(c);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+	struct clk *c;
+	struct dentry *d;
+	int err;
+
+	d = debugfs_create_dir("clock", NULL);
+	if (!d)
+		return -ENOMEM;
+	clk_debugfs_root = d;
+
+	list_for_each_entry(c, &clock_list, node) {
+		err = clk_debugfs_register(c);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+err_out:
+	debugfs_remove(clk_debugfs_root); /* REVISIT: Cleanup correctly */
+	return err;
+}
+late_initcall(clk_debugfs_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/clock-cpg.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/clock-cpg.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/clock-cpg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/clock-cpg.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,258 @@
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+
+static int sh_clk_mstp32_enable(struct clk *clk)
+{
+	__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
+		     clk->enable_reg);
+	return 0;
+}
+
+static void sh_clk_mstp32_disable(struct clk *clk)
+{
+	__raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
+		     clk->enable_reg);
+}
+
+static struct clk_ops sh_clk_mstp32_clk_ops = {
+	.enable		= sh_clk_mstp32_enable,
+	.disable	= sh_clk_mstp32_disable,
+	.recalc		= followparent_recalc,
+};
+
+int __init sh_clk_mstp32_register(struct clk *clks, int nr)
+{
+	struct clk *clkp;
+	int ret = 0;
+	int k;
+
+	for (k = 0; !ret && (k < nr); k++) {
+		clkp = clks + k;
+		clkp->ops = &sh_clk_mstp32_clk_ops;
+		ret |= clk_register(clkp);
+	}
+
+	return ret;
+}
+
+static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk_rate_table_round(clk, clk->freq_table, rate);
+}
+
+static int sh_clk_div6_divisors[64] = {
+	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+	17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
+};
+
+static struct clk_div_mult_table sh_clk_div6_table = {
+	.divisors = sh_clk_div6_divisors,
+	.nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
+};
+
+static unsigned long sh_clk_div6_recalc(struct clk *clk)
+{
+	struct clk_div_mult_table *table = &sh_clk_div6_table;
+	unsigned int idx;
+
+	clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+			     table, NULL);
+
+	idx = __raw_readl(clk->enable_reg) & 0x003f;
+
+	return clk->freq_table[idx].frequency;
+}
+
+static int sh_clk_div6_set_rate(struct clk *clk,
+				unsigned long rate, int algo_id)
+{
+	unsigned long value;
+	int idx;
+
+	idx = clk_rate_table_find(clk, clk->freq_table, rate);
+	if (idx < 0)
+		return idx;
+
+	value = __raw_readl(clk->enable_reg);
+	value &= ~0x3f;
+	value |= idx;
+	__raw_writel(value, clk->enable_reg);
+	return 0;
+}
+
+static int sh_clk_div6_enable(struct clk *clk)
+{
+	unsigned long value;
+	int ret;
+
+	ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
+	if (ret == 0) {
+		value = __raw_readl(clk->enable_reg);
+		value &= ~0x100; /* clear stop bit to enable clock */
+		__raw_writel(value, clk->enable_reg);
+	}
+	return ret;
+}
+
+static void sh_clk_div6_disable(struct clk *clk)
+{
+	unsigned long value;
+
+	value = __raw_readl(clk->enable_reg);
+	value |= 0x100; /* stop clock */
+	value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
+	__raw_writel(value, clk->enable_reg);
+}
+
+static struct clk_ops sh_clk_div6_clk_ops = {
+	.recalc		= sh_clk_div6_recalc,
+	.round_rate	= sh_clk_div_round_rate,
+	.set_rate	= sh_clk_div6_set_rate,
+	.enable		= sh_clk_div6_enable,
+	.disable	= sh_clk_div6_disable,
+};
+
+int __init sh_clk_div6_register(struct clk *clks, int nr)
+{
+	struct clk *clkp;
+	void *freq_table;
+	int nr_divs = sh_clk_div6_table.nr_divisors;
+	int freq_table_size = sizeof(struct cpufreq_frequency_table);
+	int ret = 0;
+	int k;
+
+	freq_table_size *= (nr_divs + 1);
+	freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
+	if (!freq_table) {
+		pr_err("sh_clk_div6_register: unable to alloc memory\n");
+		return -ENOMEM;
+	}
+
+	for (k = 0; !ret && (k < nr); k++) {
+		clkp = clks + k;
+
+		clkp->ops = &sh_clk_div6_clk_ops;
+		clkp->id = -1;
+		clkp->freq_table = freq_table + (k * freq_table_size);
+		clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
+
+		ret = clk_register(clkp);
+	}
+
+	return ret;
+}
+
+static unsigned long sh_clk_div4_recalc(struct clk *clk)
+{
+	struct clk_div_mult_table *table = clk->priv;
+	unsigned int idx;
+
+	clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+			     table, &clk->arch_flags);
+
+	idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+
+	return clk->freq_table[idx].frequency;
+}
+
+static struct clk_ops sh_clk_div4_clk_ops = {
+	.recalc		= sh_clk_div4_recalc,
+	.round_rate	= sh_clk_div_round_rate,
+};
+
+int __init sh_clk_div4_register(struct clk *clks, int nr,
+				struct clk_div_mult_table *table)
+{
+	struct clk *clkp;
+	void *freq_table;
+	int nr_divs = table->nr_divisors;
+	int freq_table_size = sizeof(struct cpufreq_frequency_table);
+	int ret = 0;
+	int k;
+
+	freq_table_size *= (nr_divs + 1);
+	freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
+	if (!freq_table) {
+		pr_err("sh_clk_div4_register: unable to alloc memory\n");
+		return -ENOMEM;
+	}
+
+	for (k = 0; !ret && (k < nr); k++) {
+		clkp = clks + k;
+
+		clkp->ops = &sh_clk_div4_clk_ops;
+		clkp->id = -1;
+		clkp->priv = table;
+
+		clkp->freq_table = freq_table + (k * freq_table_size);
+		clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
+
+		ret = clk_register(clkp);
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_SH_CLK_CPG_LEGACY
+static struct clk master_clk = {
+	.name		= "master_clk",
+	.flags		= CLK_ENABLE_ON_INIT,
+	.rate		= CONFIG_SH_PCLK_FREQ,
+};
+
+static struct clk peripheral_clk = {
+	.name		= "peripheral_clk",
+	.parent		= &master_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static struct clk bus_clk = {
+	.name		= "bus_clk",
+	.parent		= &master_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static struct clk cpu_clk = {
+	.name		= "cpu_clk",
+	.parent		= &master_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+/*
+ * The ordering of these clocks matters, do not change it.
+ */
+static struct clk *onchip_clocks[] = {
+	&master_clk,
+	&peripheral_clk,
+	&bus_clk,
+	&cpu_clk,
+};
+
+int __init __deprecated cpg_clk_init(void)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
+		struct clk *clk = onchip_clocks[i];
+		arch_init_clk_ops(&clk->ops, i);
+		if (clk->ops)
+			ret |= clk_register(clk);
+	}
+
+	return ret;
+}
+
+/*
+ * Placeholder for compatability, until the lazy CPUs do this
+ * on their own.
+ */
+int __init __weak arch_clk_init(void)
+{
+	return cpg_clk_init();
+}
+#endif /* CONFIG_SH_CPG_CLK_LEGACY */
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/init.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/init.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,11 @@
 #define speculative_execution_init()	do { } while (0)
 #endif
 
+/* 2nd-level cache init */
+void __uses_jump_to_uncached __attribute__ ((weak)) l2_cache_init(void)
+{
+}
+
 /*
  * Generic first-level cache init
  */
@@ -146,6 +151,8 @@
 	flags &= ~CCR_CACHE_ENABLE;
 #endif
 
+	l2_cache_init();
+
 	ctrl_outl(flags, CCR);
 	back_to_cached();
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/irq/imask.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/irq/imask.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/irq/imask.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/irq/imask.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,38 +18,17 @@
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 #include <linux/irq.h>
+#include <linux/bitmap.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
 /* Bitmap of IRQ masked */
-static unsigned long imask_mask = 0x7fff;
-static int interrupt_priority = 0;
-
-static void enable_imask_irq(unsigned int irq);
-static void disable_imask_irq(unsigned int irq);
-static void shutdown_imask_irq(unsigned int irq);
-static void mask_and_ack_imask(unsigned int);
-static void end_imask_irq(unsigned int irq);
-
 #define IMASK_PRIORITY	15
 
-static unsigned int startup_imask_irq(unsigned int irq)
-{
-	/* Nothing to do */
-	return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type imask_irq_type = {
-	.typename = "SR.IMASK",
-	.startup = startup_imask_irq,
-	.shutdown = shutdown_imask_irq,
-	.enable = enable_imask_irq,
-	.disable = disable_imask_irq,
-	.ack = mask_and_ack_imask,
-	.end = end_imask_irq
-};
+static DECLARE_BITMAP(imask_mask, IMASK_PRIORITY);
+static int interrupt_priority;
 
-void static inline set_interrupt_registers(int ip)
+static inline void set_interrupt_registers(int ip)
 {
 	unsigned long __dummy;
 
@@ -72,42 +51,31 @@
 		     : "t");
 }
 
-static void disable_imask_irq(unsigned int irq)
+static void mask_imask_irq(unsigned int irq)
 {
-	clear_bit(irq, &imask_mask);
+	clear_bit(irq, imask_mask);
 	if (interrupt_priority < IMASK_PRIORITY - irq)
 		interrupt_priority = IMASK_PRIORITY - irq;
-
 	set_interrupt_registers(interrupt_priority);
 }
 
-static void enable_imask_irq(unsigned int irq)
+static void unmask_imask_irq(unsigned int irq)
 {
-	set_bit(irq, &imask_mask);
-	interrupt_priority = IMASK_PRIORITY - ffz(imask_mask);
-
+	set_bit(irq, imask_mask);
+	interrupt_priority = IMASK_PRIORITY -
+		find_first_zero_bit(imask_mask, IMASK_PRIORITY);
 	set_interrupt_registers(interrupt_priority);
 }
 
-static void mask_and_ack_imask(unsigned int irq)
-{
-	disable_imask_irq(irq);
-}
-
-static void end_imask_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_imask_irq(irq);
-}
-
-static void shutdown_imask_irq(unsigned int irq)
-{
-	/* Nothing to do */
-}
+static struct irq_chip imask_irq_chip = {
+	.typename	= "SR.IMASK",
+	.mask		= mask_imask_irq,
+	.unmask		= unmask_imask_irq,
+	.mask_ack	= mask_imask_irq,
+};
 
 void make_imask_irq(unsigned int irq)
 {
-	disable_irq_nosync(irq);
-	irq_desc[irq].chip = &imask_irq_type;
-	enable_irq(irq);
+	set_irq_chip_and_handler_name(irq, &imask_irq_chip,
+				      handle_level_irq, "level");
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c	2009-09-09 18:13:59.000000000 -0400
@@ -84,7 +84,7 @@
 static void mask_and_ack_intc(unsigned int);
 static void end_intc_irq(unsigned int irq);
 
-static struct hw_interrupt_type intc_irq_type = {
+static struct irq_chip intc_irq_type = {
 	.typename = "INTC",
 	.startup = startup_intc_irq,
 	.shutdown = shutdown_intc_irq,
@@ -152,43 +152,13 @@
 	enable_intc_irq(irq);
 }
 
-/* For future use, if we ever support IRLM=0) */
-void make_intc_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	irq_desc[irq].chip = &intc_irq_type;
-	disable_intc_irq(irq);
-}
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-static int IRQ_to_vectorN[NR_INTC_IRQS] = {
-	0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /*  0- 7 */
-	  -1,   -1,   -1,   -1, 0x50, 0x51, 0x52, 0x53,	/*  8-15 */
-	0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36,   -1, /* 16-23 */
-	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1, /* 24-31 */
-	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38,	/* 32-39 */
-        0x39, 0x3A, 0x3B,   -1,   -1,   -1,   -1,   -1, /* 40-47 */
-	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1, /* 48-55 */
-	  -1,   -1,   -1,   -1,   -1,   -1,   -1, 0x2B, /* 56-63 */
-
-};
-
-int intc_irq_describe(char* p, int irq)
-{
-	if (irq < NR_INTC_IRQS)
-		return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20);
-	else
-		return 0;
-}
-#endif
-
 void __init plat_irq_setup(void)
 {
 	unsigned long long __dummy0, __dummy1=~0x00000000100000f0;
 	unsigned long reg;
 	int i;
 
-	intc_virt = onchip_remap(INTC_BASE, 1024, "INTC");
+	intc_virt = (unsigned long)ioremap_nocache(INTC_BASE, 1024);
 	if (!intc_virt) {
 		panic("Unable to remap INTC\n");
 	}
@@ -196,7 +166,7 @@
 
 	/* Set default: per-line enable/disable, priority driven ack/eoi */
 	for (i = 0; i < NR_INTC_IRQS; i++)
-		irq_desc[i].chip = &intc_irq_type;
+		set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
 
 
 	/* Disable all interrupts and set all priorities to 0 to avoid trouble */
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/irq/ipr.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/irq/ipr.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/irq/ipr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/irq/ipr.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
+#include <linux/topology.h>
 
 static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
 {
@@ -59,10 +60,18 @@
 
 	for (i = 0; i < desc->nr_irqs; i++) {
 		struct ipr_data *p = desc->ipr_data + i;
+		struct irq_desc *irq_desc;
 
 		BUG_ON(p->ipr_idx >= desc->nr_offsets);
 		BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
 
+		irq_desc = irq_to_desc_alloc_node(p->irq, numa_node_id());
+		if (unlikely(!irq_desc)) {
+			printk(KERN_INFO "can not get irq_desc for %d\n",
+			       p->irq);
+			continue;
+		}
+
 		disable_irq_nosync(p->irq);
 		set_irq_chip_and_handler_name(p->irq, &desc->chip,
 				      handle_level_irq, "level");
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/Makefile linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -17,5 +17,6 @@
 
 obj-$(CONFIG_UBC_WAKEUP)	+= ubc.o
 obj-$(CONFIG_SH_ADC)		+= adc.o
+obj-$(CONFIG_SH_CLK_CPG)	+= clock-cpg.o
 
 obj-y	+= irq/ init.o clock.o
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2/clock-sh7619.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2/clock-sh7619.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2/clock-sh7619.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2/clock-sh7619.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,32 +38,27 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FREQCR) & 0x0007);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7619_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
+	return clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
 }
 
 static struct clk_ops sh7619_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
 static struct clk_ops sh7619_cpu_clk_ops = {
-	.recalc		= cpu_clk_recalc,
+	.recalc		= followparent_recalc,
 };
 
 static struct clk_ops *sh7619_clk_ops[] = {
@@ -78,4 +73,3 @@
 	if (idx < ARRAY_SIZE(sh7619_clk_ops))
 		*ops = sh7619_clk_ops[idx];
 }
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2/setup-sh7619.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2/setup-sh7619.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2/setup-sh7619.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2/setup-sh7619.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
 
 enum {
 	UNUSED = 0,
@@ -109,9 +111,75 @@
 	.resource = eth_resources,
 };
 
+static struct sh_timer_config cmt0_platform_data = {
+	.name = "CMT0",
+	.channel_offset = 0x02,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+	[0] = {
+		.name	= "CMT0",
+		.start	= 0xf84a0072,
+		.end	= 0xf84a0077,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 86,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt0_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt0_platform_data,
+	},
+	.resource	= cmt0_resources,
+	.num_resources	= ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+	.name = "CMT1",
+	.channel_offset = 0x08,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+	[0] = {
+		.name	= "CMT1",
+		.start	= 0xf84a0078,
+		.end	= 0xf84a007d,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 87,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt1_device = {
+	.name		= "sh_cmt",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &cmt1_platform_data,
+	},
+	.resource	= cmt1_resources,
+	.num_resources	= ARRAY_SIZE(cmt1_resources),
+};
+
 static struct platform_device *sh7619_devices[] __initdata = {
 	&sci_device,
 	&eth_device,
+	&cmt0_device,
+	&cmt1_device,
 };
 
 static int __init sh7619_devices_setup(void)
@@ -119,9 +187,25 @@
 	return platform_add_devices(sh7619_devices,
 				    ARRAY_SIZE(sh7619_devices));
 }
-__initcall(sh7619_devices_setup);
+arch_initcall(sh7619_devices_setup);
 
 void __init plat_irq_setup(void)
 {
 	register_intc_controller(&intc_desc);
 }
+
+static struct platform_device *sh7619_early_devices[] __initdata = {
+	&cmt0_device,
+	&cmt1_device,
+};
+
+#define STBCR3 0xf80a0000
+
+void __init plat_early_device_setup(void)
+{
+	/* enable CMT clock */
+	__raw_writeb(__raw_readb(STBCR3) & ~0x10, STBCR3);
+
+	early_platform_add_devices(sh7619_early_devices,
+				   ARRAY_SIZE(sh7619_early_devices));
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7201.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7201.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7201.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,37 +34,37 @@
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate = 10000000 * PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+	return 10000000 * PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7201_master_clk_ops = {
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FREQCR) & 0x0007);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7201_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FREQCR) & 0x0007);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7201_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inw(FREQCR) >> 4) & 0x0007);
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7201_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7203.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7203.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7203.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,33 +46,28 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FREQCR) & 0x0007);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7203_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FREQCR) & 0x0007);
-	clk->rate = clk->parent->rate / pfc_divisors[idx-2];
+	return clk->parent->rate / pfc_divisors[idx-2];
 }
 
 static struct clk_ops sh7203_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
 static struct clk_ops sh7203_cpu_clk_ops = {
-	.recalc		= cpu_clk_recalc,
+	.recalc		= followparent_recalc,
 };
 
 static struct clk_ops *sh7203_clk_ops[] = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7206.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7206.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/clock-sh7206.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,29 +41,29 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FREQCR) & 0x0007);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7206_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
-	clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+	return clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7206_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FREQCR) & 0x0007);
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7206_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-mxg.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-mxg.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-mxg.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-mxg.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
 
 enum {
 	UNUSED = 0,
@@ -24,7 +25,7 @@
 
 	SCIF0, SCIF1,
 
-	MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5
+	MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5,
 	MTU2_TGI3B, MTU2_TGI3C,
 
 	/* interrupt groups */
@@ -113,6 +114,99 @@
 static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 
+static struct sh_timer_config mtu2_0_platform_data = {
+	.name = "MTU2_0",
+	.channel_offset = -0x80,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+	[0] = {
+		.name	= "MTU2_0",
+		.start	= 0xff801300,
+		.end	= 0xff801326,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 228,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_0_device = {
+	.name		= "sh_mtu2",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &mtu2_0_platform_data,
+	},
+	.resource	= mtu2_0_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+	.name = "MTU2_1",
+	.channel_offset = -0x100,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+	[0] = {
+		.name	= "MTU2_1",
+		.start	= 0xff801380,
+		.end	= 0xff801390,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 234,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_1_device = {
+	.name		= "sh_mtu2",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &mtu2_1_platform_data,
+	},
+	.resource	= mtu2_1_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct sh_timer_config mtu2_2_platform_data = {
+	.name = "MTU2_2",
+	.channel_offset = 0x80,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_2_resources[] = {
+	[0] = {
+		.name	= "MTU2_2",
+		.start	= 0xff801000,
+		.end	= 0xff80100a,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 240,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_2_device = {
+	.name		= "sh_mtu2",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &mtu2_2_platform_data,
+	},
+	.resource	= mtu2_2_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_2_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xff804000,
@@ -134,6 +228,9 @@
 
 static struct platform_device *mxg_devices[] __initdata = {
 	&sci_device,
+	&mtu2_0_device,
+	&mtu2_1_device,
+	&mtu2_2_device,
 };
 
 static int __init mxg_devices_setup(void)
@@ -141,9 +238,21 @@
 	return platform_add_devices(mxg_devices,
 				    ARRAY_SIZE(mxg_devices));
 }
-__initcall(mxg_devices_setup);
+arch_initcall(mxg_devices_setup);
 
 void __init plat_irq_setup(void)
 {
 	register_intc_controller(&intc_desc);
 }
+
+static struct platform_device *mxg_early_devices[] __initdata = {
+	&mtu2_0_device,
+	&mtu2_1_device,
+	&mtu2_2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(mxg_early_devices,
+				   ARRAY_SIZE(mxg_early_devices));
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7201.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7201.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7201.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
 
 enum {
 	UNUSED = 0,
@@ -249,9 +251,105 @@
 	.resource	= rtc_resources,
 };
 
+static struct sh_timer_config mtu2_0_platform_data = {
+	.name = "MTU2_0",
+	.channel_offset = -0x80,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+	[0] = {
+		.name	= "MTU2_0",
+		.start	= 0xfffe4300,
+		.end	= 0xfffe4326,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 108,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_0_device = {
+	.name		= "sh_mtu2",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &mtu2_0_platform_data,
+	},
+	.resource	= mtu2_0_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+	.name = "MTU2_1",
+	.channel_offset = -0x100,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+	[0] = {
+		.name	= "MTU2_1",
+		.start	= 0xfffe4380,
+		.end	= 0xfffe4390,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 116,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_1_device = {
+	.name		= "sh_mtu2",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &mtu2_1_platform_data,
+	},
+	.resource	= mtu2_1_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct sh_timer_config mtu2_2_platform_data = {
+	.name = "MTU2_2",
+	.channel_offset = 0x80,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_2_resources[] = {
+	[0] = {
+		.name	= "MTU2_2",
+		.start	= 0xfffe4000,
+		.end	= 0xfffe400a,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 124,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_2_device = {
+	.name		= "sh_mtu2",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &mtu2_2_platform_data,
+	},
+	.resource	= mtu2_2_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_2_resources),
+};
+
 static struct platform_device *sh7201_devices[] __initdata = {
 	&sci_device,
 	&rtc_device,
+	&mtu2_0_device,
+	&mtu2_1_device,
+	&mtu2_2_device,
 };
 
 static int __init sh7201_devices_setup(void)
@@ -259,9 +357,26 @@
 	return platform_add_devices(sh7201_devices,
 				    ARRAY_SIZE(sh7201_devices));
 }
-__initcall(sh7201_devices_setup);
+arch_initcall(sh7201_devices_setup);
 
 void __init plat_irq_setup(void)
 {
 	register_intc_controller(&intc_desc);
 }
+
+static struct platform_device *sh7201_early_devices[] __initdata = {
+	&mtu2_0_device,
+	&mtu2_1_device,
+	&mtu2_2_device,
+};
+
+#define STBCR3 0xfffe0408
+
+void __init plat_early_device_setup(void)
+{
+	/* enable MTU2 clock */
+	__raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+	early_platform_add_devices(sh7201_early_devices,
+				   ARRAY_SIZE(sh7201_early_devices));
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7203.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,8 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
 
 enum {
 	UNUSED = 0,
@@ -205,6 +207,132 @@
 	},
 };
 
+static struct sh_timer_config cmt0_platform_data = {
+	.name = "CMT0",
+	.channel_offset = 0x02,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+	[0] = {
+		.name	= "CMT0",
+		.start	= 0xfffec002,
+		.end	= 0xfffec007,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 142,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt0_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt0_platform_data,
+	},
+	.resource	= cmt0_resources,
+	.num_resources	= ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+	.name = "CMT1",
+	.channel_offset = 0x08,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+	[0] = {
+		.name	= "CMT1",
+		.start	= 0xfffec008,
+		.end	= 0xfffec00d,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 143,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt1_device = {
+	.name		= "sh_cmt",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &cmt1_platform_data,
+	},
+	.resource	= cmt1_resources,
+	.num_resources	= ARRAY_SIZE(cmt1_resources),
+};
+
+static struct sh_timer_config mtu2_0_platform_data = {
+	.name = "MTU2_0",
+	.channel_offset = -0x80,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+	[0] = {
+		.name	= "MTU2_0",
+		.start	= 0xfffe4300,
+		.end	= 0xfffe4326,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 146,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_0_device = {
+	.name		= "sh_mtu2",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &mtu2_0_platform_data,
+	},
+	.resource	= mtu2_0_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+	.name = "MTU2_1",
+	.channel_offset = -0x100,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+	[0] = {
+		.name	= "MTU2_1",
+		.start	= 0xfffe4380,
+		.end	= 0xfffe4390,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 153,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_1_device = {
+	.name		= "sh_mtu2",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &mtu2_1_platform_data,
+	},
+	.resource	= mtu2_1_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_1_resources),
+};
+
 static struct resource rtc_resources[] = {
 	[0] = {
 		.start	= 0xffff2000,
@@ -227,6 +355,10 @@
 
 static struct platform_device *sh7203_devices[] __initdata = {
 	&sci_device,
+	&cmt0_device,
+	&cmt1_device,
+	&mtu2_0_device,
+	&mtu2_1_device,
 	&rtc_device,
 };
 
@@ -235,9 +367,31 @@
 	return platform_add_devices(sh7203_devices,
 				    ARRAY_SIZE(sh7203_devices));
 }
-__initcall(sh7203_devices_setup);
+arch_initcall(sh7203_devices_setup);
 
 void __init plat_irq_setup(void)
 {
 	register_intc_controller(&intc_desc);
 }
+
+static struct platform_device *sh7203_early_devices[] __initdata = {
+	&cmt0_device,
+	&cmt1_device,
+	&mtu2_0_device,
+	&mtu2_1_device,
+};
+
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+
+void __init plat_early_device_setup(void)
+{
+	/* enable CMT clock */
+	__raw_writeb(__raw_readb(STBCR4) & ~0x04, STBCR4);
+
+	/* enable MTU2 clock */
+	__raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+	early_platform_add_devices(sh7203_early_devices,
+				   ARRAY_SIZE(sh7203_early_devices));
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7206.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7206.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh2a/setup-sh7206.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
 
 enum {
 	UNUSED = 0,
@@ -165,8 +167,170 @@
 	},
 };
 
+static struct sh_timer_config cmt0_platform_data = {
+	.name = "CMT0",
+	.channel_offset = 0x02,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt0_resources[] = {
+	[0] = {
+		.name	= "CMT0",
+		.start	= 0xfffec002,
+		.end	= 0xfffec007,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 140,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt0_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt0_platform_data,
+	},
+	.resource	= cmt0_resources,
+	.num_resources	= ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+	.name = "CMT1",
+	.channel_offset = 0x08,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 0, /* disabled due to code generation issues */
+};
+
+static struct resource cmt1_resources[] = {
+	[0] = {
+		.name	= "CMT1",
+		.start	= 0xfffec008,
+		.end	= 0xfffec00d,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 144,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt1_device = {
+	.name		= "sh_cmt",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &cmt1_platform_data,
+	},
+	.resource	= cmt1_resources,
+	.num_resources	= ARRAY_SIZE(cmt1_resources),
+};
+
+static struct sh_timer_config mtu2_0_platform_data = {
+	.name = "MTU2_0",
+	.channel_offset = -0x80,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] = {
+	[0] = {
+		.name	= "MTU2_0",
+		.start	= 0xfffe4300,
+		.end	= 0xfffe4326,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 156,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_0_device = {
+	.name		= "sh_mtu2",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &mtu2_0_platform_data,
+	},
+	.resource	= mtu2_0_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_0_resources),
+};
+
+static struct sh_timer_config mtu2_1_platform_data = {
+	.name = "MTU2_1",
+	.channel_offset = -0x100,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_1_resources[] = {
+	[0] = {
+		.name	= "MTU2_1",
+		.start	= 0xfffe4380,
+		.end	= 0xfffe4390,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 164,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_1_device = {
+	.name		= "sh_mtu2",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &mtu2_1_platform_data,
+	},
+	.resource	= mtu2_1_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_1_resources),
+};
+
+static struct sh_timer_config mtu2_2_platform_data = {
+	.name = "MTU2_2",
+	.channel_offset = 0x80,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource mtu2_2_resources[] = {
+	[0] = {
+		.name	= "MTU2_2",
+		.start	= 0xfffe4000,
+		.end	= 0xfffe400a,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 180,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mtu2_2_device = {
+	.name		= "sh_mtu2",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &mtu2_2_platform_data,
+	},
+	.resource	= mtu2_2_resources,
+	.num_resources	= ARRAY_SIZE(mtu2_2_resources),
+};
+
 static struct platform_device *sh7206_devices[] __initdata = {
 	&sci_device,
+	&cmt0_device,
+	&cmt1_device,
+	&mtu2_0_device,
+	&mtu2_1_device,
+	&mtu2_2_device,
 };
 
 static int __init sh7206_devices_setup(void)
@@ -174,9 +338,32 @@
 	return platform_add_devices(sh7206_devices,
 				    ARRAY_SIZE(sh7206_devices));
 }
-__initcall(sh7206_devices_setup);
+arch_initcall(sh7206_devices_setup);
 
 void __init plat_irq_setup(void)
 {
 	register_intc_controller(&intc_desc);
 }
+
+static struct platform_device *sh7206_early_devices[] __initdata = {
+	&cmt0_device,
+	&cmt1_device,
+	&mtu2_0_device,
+	&mtu2_1_device,
+	&mtu2_2_device,
+};
+
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+
+void __init plat_early_device_setup(void)
+{
+	/* enable CMT clock */
+	__raw_writeb(__raw_readb(STBCR4) & ~0x04, STBCR4);
+
+	/* enable MTU2 clock */
+	__raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+	early_platform_add_devices(sh7206_early_devices,
+				   ARRAY_SIZE(sh7206_early_devices));
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh3.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh3.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh3.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,36 +38,36 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh3_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
 
-	clk->rate = clk->parent->rate / stc_multipliers[idx];
+	return clk->parent->rate / stc_multipliers[idx];
 }
 
 static struct clk_ops sh3_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
 
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh3_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7705.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7705.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7705.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7705.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,30 +39,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = ctrl_inw(FRQCR) & 0x0003;
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7705_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8;
-	clk->rate = clk->parent->rate / stc_multipliers[idx];
+	return clk->parent->rate / stc_multipliers[idx];
 }
 
 static struct clk_ops sh7705_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4;
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7705_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7706.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7706.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7706.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7706.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,36 +34,36 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7706_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
 
-	clk->rate = clk->parent->rate / stc_multipliers[idx];
+	return clk->parent->rate / stc_multipliers[idx];
 }
 
 static struct clk_ops sh7706_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
 
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7706_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7709.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7709.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7709.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7709.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,12 +41,12 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
 
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7709_module_clk_ops = {
@@ -56,25 +56,25 @@
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = (frqcr & 0x0080) ?
 		((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1;
 
-	clk->rate = clk->parent->rate * stc_multipliers[idx];
+	return clk->parent->rate * stc_multipliers[idx];
 }
 
 static struct clk_ops sh7709_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
 
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7709_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7710.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7710.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7710.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7710.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,30 +33,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) & 0x0007);
-	clk->rate = clk->parent->rate / md_table[idx];
+	return clk->parent->rate / md_table[idx];
 }
 
 static struct clk_ops sh7710_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8;
-	clk->rate = clk->parent->rate / md_table[idx];
+	return clk->parent->rate / md_table[idx];
 }
 
 static struct clk_ops sh7710_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4;
-	clk->rate = clk->parent->rate / md_table[idx];
+	return clk->parent->rate / md_table[idx];
 }
 
 static struct clk_ops sh7710_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7712.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7712.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/clock-sh7712.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/clock-sh7712.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,24 +33,24 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = frqcr & 0x0007;
 
-	clk->rate = clk->parent->rate / divisors[idx];
+	return clk->parent->rate / divisors[idx];
 }
 
 static struct clk_ops sh7712_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int frqcr = ctrl_inw(FRQCR);
 	int idx = (frqcr & 0x0030) >> 4;
 
-	clk->rate = clk->parent->rate / divisors[idx];
+	return clk->parent->rate / divisors[idx];
 }
 
 static struct clk_ops sh7712_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh7705.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh7705.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh7705.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh7705.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
 #include <asm/rtc.h>
 
 enum {
@@ -116,7 +117,102 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x02,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xfffffe94,
+		.end	= 0xfffffe9f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0xe,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xfffffea0,
+		.end	= 0xfffffeab,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1a,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xfffffeac,
+		.end	= 0xfffffebb,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct platform_device *sh7705_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 	&sci_device,
 	&rtc_device,
 };
@@ -126,7 +222,19 @@
 	return platform_add_devices(sh7705_devices,
 				    ARRAY_SIZE(sh7705_devices));
 }
-__initcall(sh7705_devices_setup);
+arch_initcall(sh7705_devices_setup);
+
+static struct platform_device *sh7705_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7705_early_devices,
+				   ARRAY_SIZE(sh7705_early_devices));
+}
 
 void __init plat_irq_setup(void)
 {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh770x.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh770x.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh770x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh770x.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
 
 enum {
 	UNUSED = 0,
@@ -144,7 +145,102 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x02,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xfffffe94,
+		.end	= 0xfffffe9f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0xe,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xfffffea0,
+		.end	= 0xfffffeab,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1a,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xfffffeac,
+		.end	= 0xfffffebb,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct platform_device *sh770x_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 	&sci_device,
 	&rtc_device,
 };
@@ -154,7 +250,19 @@
 	return platform_add_devices(sh770x_devices,
 		ARRAY_SIZE(sh770x_devices));
 }
-__initcall(sh770x_devices_setup);
+arch_initcall(sh770x_devices_setup);
+
+static struct platform_device *sh770x_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh770x_early_devices,
+				   ARRAY_SIZE(sh770x_early_devices));
+}
 
 void __init plat_irq_setup(void)
 {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh7710.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh7710.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh7710.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh7710.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
 #include <asm/rtc.h>
 
 enum {
@@ -120,7 +121,102 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x02,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xa412fe94,
+		.end	= 0xa412fe9f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0xe,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xa412fea0,
+		.end	= 0xa412feab,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1a,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xa412feac,
+		.end	= 0xa412feb5,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct platform_device *sh7710_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 	&sci_device,
 	&rtc_device,
 };
@@ -130,7 +226,19 @@
 	return platform_add_devices(sh7710_devices,
 				    ARRAY_SIZE(sh7710_devices));
 }
-__initcall(sh7710_devices_setup);
+arch_initcall(sh7710_devices_setup);
+
+static struct platform_device *sh7710_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7710_early_devices,
+				   ARRAY_SIZE(sh7710_early_devices));
+}
 
 void __init plat_irq_setup(void)
 {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh7720.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh7720.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh3/setup-sh7720.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh3/setup-sh7720.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/serial.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
 #include <asm/rtc.h>
 
 static struct resource rtc_resources[] = {
@@ -123,7 +124,259 @@
 	.resource	= usbf_resources,
 };
 
+static struct sh_timer_config cmt0_platform_data = {
+	.name = "CMT0",
+	.channel_offset = 0x10,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 125,
+};
+
+static struct resource cmt0_resources[] = {
+	[0] = {
+		.name	= "CMT0",
+		.start	= 0x044a0010,
+		.end	= 0x044a001b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt0_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt0_platform_data,
+	},
+	.resource	= cmt0_resources,
+	.num_resources	= ARRAY_SIZE(cmt0_resources),
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+	.name = "CMT1",
+	.channel_offset = 0x20,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource cmt1_resources[] = {
+	[0] = {
+		.name	= "CMT1",
+		.start	= 0x044a0020,
+		.end	= 0x044a002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt1_device = {
+	.name		= "sh_cmt",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &cmt1_platform_data,
+	},
+	.resource	= cmt1_resources,
+	.num_resources	= ARRAY_SIZE(cmt1_resources),
+};
+
+static struct sh_timer_config cmt2_platform_data = {
+	.name = "CMT2",
+	.channel_offset = 0x30,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource cmt2_resources[] = {
+	[0] = {
+		.name	= "CMT2",
+		.start	= 0x044a0030,
+		.end	= 0x044a003b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt2_device = {
+	.name		= "sh_cmt",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &cmt2_platform_data,
+	},
+	.resource	= cmt2_resources,
+	.num_resources	= ARRAY_SIZE(cmt2_resources),
+};
+
+static struct sh_timer_config cmt3_platform_data = {
+	.name = "CMT3",
+	.channel_offset = 0x40,
+	.timer_bit = 3,
+	.clk = "peripheral_clk",
+};
+
+static struct resource cmt3_resources[] = {
+	[0] = {
+		.name	= "CMT3",
+		.start	= 0x044a0040,
+		.end	= 0x044a004b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt3_device = {
+	.name		= "sh_cmt",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &cmt3_platform_data,
+	},
+	.resource	= cmt3_resources,
+	.num_resources	= ARRAY_SIZE(cmt3_resources),
+};
+
+static struct sh_timer_config cmt4_platform_data = {
+	.name = "CMT4",
+	.channel_offset = 0x50,
+	.timer_bit = 4,
+	.clk = "peripheral_clk",
+};
+
+static struct resource cmt4_resources[] = {
+	[0] = {
+		.name	= "CMT4",
+		.start	= 0x044a0050,
+		.end	= 0x044a005b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt4_device = {
+	.name		= "sh_cmt",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &cmt4_platform_data,
+	},
+	.resource	= cmt4_resources,
+	.num_resources	= ARRAY_SIZE(cmt4_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x02,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xa412fe94,
+		.end	= 0xa412fe9f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0xe,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xa412fea0,
+		.end	= 0xa412feab,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1a,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xa412feac,
+		.end	= 0xa412feb5,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct platform_device *sh7720_devices[] __initdata = {
+	&cmt0_device,
+	&cmt1_device,
+	&cmt2_device,
+	&cmt3_device,
+	&cmt4_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 	&rtc_device,
 	&sci_device,
 	&usb_ohci_device,
@@ -135,7 +388,24 @@
 	return platform_add_devices(sh7720_devices,
 				    ARRAY_SIZE(sh7720_devices));
 }
-__initcall(sh7720_devices_setup);
+arch_initcall(sh7720_devices_setup);
+
+static struct platform_device *sh7720_early_devices[] __initdata = {
+	&cmt0_device,
+	&cmt1_device,
+	&cmt2_device,
+	&cmt3_device,
+	&cmt4_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7720_early_devices,
+				   ARRAY_SIZE(sh7720_early_devices));
+}
 
 enum {
 	UNUSED = 0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/clock-sh4-202.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/clock-sh4-202.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/clock-sh4-202.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,10 +21,10 @@
 static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 };
 static int frqcr3_values[]   = { 0, 1, 2, 3, 4, 5, 6  };
 
-static void emi_clk_recalc(struct clk *clk)
+static unsigned long emi_clk_recalc(struct clk *clk)
 {
 	int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007;
-	clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+	return clk->parent->rate / frqcr3_divisors[idx];
 }
 
 static inline int frqcr3_lookup(struct clk *clk, unsigned long rate)
@@ -46,14 +46,14 @@
 
 static struct clk sh4202_emi_clk = {
 	.name		= "emi_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &sh4202_emi_clk_ops,
 };
 
-static void femi_clk_recalc(struct clk *clk)
+static unsigned long femi_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007;
-	clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+	return clk->parent->rate / frqcr3_divisors[idx];
 }
 
 static struct clk_ops sh4202_femi_clk_ops = {
@@ -62,7 +62,7 @@
 
 static struct clk sh4202_femi_clk = {
 	.name		= "femi_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &sh4202_femi_clk_ops,
 };
 
@@ -90,10 +90,10 @@
 	WARN_ON(i == ARRAY_SIZE(frqcr3_divisors));	/* Undefined clock */
 }
 
-static void shoc_clk_recalc(struct clk *clk)
+static unsigned long shoc_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007;
-	clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+	return clk->parent->rate / frqcr3_divisors[idx];
 }
 
 static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
@@ -140,7 +140,7 @@
 
 static struct clk sh4202_shoc_clk = {
 	.name		= "shoc_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &sh4202_shoc_clk_ops,
 };
 
@@ -150,31 +150,22 @@
 	&sh4202_shoc_clk,
 };
 
-static int __init sh4202_clk_init(void)
+int __init arch_clk_init(void)
 {
-	struct clk *clk = clk_get(NULL, "master_clk");
-	int i;
+	struct clk *clk;
+	int i, ret = 0;
+
+	cpg_clk_init();
 
+	clk = clk_get(NULL, "master_clk");
 	for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
 		struct clk *clkp = sh4202_onchip_clocks[i];
 
 		clkp->parent = clk;
-		clk_register(clkp);
-		clk_enable(clkp);
+		ret |= clk_register(clkp);
 	}
 
-	/*
-	 * Now that we have the rest of the clocks registered, we need to
-	 * force the parent clock to propagate so that these clocks will
-	 * automatically figure out their rate. We cheat by handing the
-	 * parent clock its current rate and forcing child propagation.
-	 */
-	clk_set_rate(clk, clk_get_rate(clk));
-
 	clk_put(clk);
 
-	return 0;
+	return ret;
 }
-
-arch_initcall(sh4202_clk_init);
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/clock-sh4.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/clock-sh4.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/clock-sh4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/clock-sh4.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,30 +35,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) & 0x0007);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh4_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007;
-	clk->rate = clk->parent->rate / bfc_divisors[idx];
+	return clk->parent->rate / bfc_divisors[idx];
 }
 
 static struct clk_ops sh4_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007;
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh4_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/probe.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/probe.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/probe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/probe.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,12 +60,18 @@
 		if ((cvr & 0x10000000) == 0)
 			boot_cpu_data.flags |= CPU_HAS_DSP;
 
-		boot_cpu_data.flags |= CPU_HAS_LLSC;
+		boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_PERF_COUNTER;
 		boot_cpu_data.cut_major = pvr & 0x7f;
+
+		boot_cpu_data.icache.ways = 4;
+		boot_cpu_data.dcache.ways = 4;
+	} else {
+		/* And some SH-4 defaults.. */
+		boot_cpu_data.flags |= CPU_HAS_PTEA;
 	}
 
 	/* FPU detection works for everyone */
-	if ((cvr & 0x20000000) == 1)
+	if ((cvr & 0x20000000))
 		boot_cpu_data.flags |= CPU_HAS_FPU;
 
 	/* Mask off the upper chip ID */
@@ -78,25 +84,20 @@
 	switch (pvr) {
 	case 0x205:
 		boot_cpu_data.type = CPU_SH7750;
-		boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
-				   CPU_HAS_PERF_COUNTER;
+		boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG |
+				       CPU_HAS_PERF_COUNTER;
 		break;
 	case 0x206:
 		boot_cpu_data.type = CPU_SH7750S;
-		boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
-				   CPU_HAS_PERF_COUNTER;
+		boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG |
+				       CPU_HAS_PERF_COUNTER;
 		break;
 	case 0x1100:
 		boot_cpu_data.type = CPU_SH7751;
-		boot_cpu_data.flags |= CPU_HAS_FPU;
 		break;
 	case 0x2001:
 	case 0x2004:
 		boot_cpu_data.type = CPU_SH7770;
-		boot_cpu_data.icache.ways = 4;
-		boot_cpu_data.dcache.ways = 4;
-
-		boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
 		break;
 	case 0x2006:
 	case 0x200A:
@@ -107,45 +108,26 @@
 		else
 			boot_cpu_data.type = CPU_SH7780;
 
-		boot_cpu_data.icache.ways = 4;
-		boot_cpu_data.dcache.ways = 4;
-
-		boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
-				   CPU_HAS_LLSC;
 		break;
 	case 0x3000:
 	case 0x3003:
 	case 0x3009:
 		boot_cpu_data.type = CPU_SH7343;
-		boot_cpu_data.icache.ways = 4;
-		boot_cpu_data.dcache.ways = 4;
-		boot_cpu_data.flags |= CPU_HAS_LLSC;
 		break;
 	case 0x3004:
 	case 0x3007:
 		boot_cpu_data.type = CPU_SH7785;
-		boot_cpu_data.icache.ways = 4;
-		boot_cpu_data.dcache.ways = 4;
-		boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
-					  CPU_HAS_LLSC;
 		break;
 	case 0x4004:
 		boot_cpu_data.type = CPU_SH7786;
-		boot_cpu_data.icache.ways = 4;
-		boot_cpu_data.dcache.ways = 4;
-		boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
-			CPU_HAS_LLSC | CPU_HAS_PTEAEX;
+		boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE;
 		break;
 	case 0x3008:
-		boot_cpu_data.icache.ways = 4;
-		boot_cpu_data.dcache.ways = 4;
-		boot_cpu_data.flags |= CPU_HAS_LLSC;
-
 		switch (prr) {
 		case 0x50:
 		case 0x51:
 			boot_cpu_data.type = CPU_SH7723;
-			boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_L2_CACHE;
+			boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
 			break;
 		case 0x70:
 			boot_cpu_data.type = CPU_SH7366;
@@ -156,13 +138,13 @@
 			break;
 		}
 		break;
+	case 0x300b:
+		boot_cpu_data.type = CPU_SH7724;
+		boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
+		break;
 	case 0x4000:	/* 1st cut */
 	case 0x4001:	/* 2nd cut */
 		boot_cpu_data.type = CPU_SHX3;
-		boot_cpu_data.icache.ways = 4;
-		boot_cpu_data.dcache.ways = 4;
-		boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
-					  CPU_HAS_LLSC;
 		break;
 	case 0x700:
 		boot_cpu_data.type = CPU_SH4_501;
@@ -173,7 +155,6 @@
 		boot_cpu_data.type = CPU_SH4_202;
 		boot_cpu_data.icache.ways = 2;
 		boot_cpu_data.dcache.ways = 2;
-		boot_cpu_data.flags |= CPU_HAS_FPU;
 		break;
 	case 0x500 ... 0x501:
 		switch (prr) {
@@ -191,18 +172,12 @@
 		boot_cpu_data.icache.ways = 2;
 		boot_cpu_data.dcache.ways = 2;
 
-		boot_cpu_data.flags |= CPU_HAS_FPU;
-
 		break;
 	default:
 		boot_cpu_data.type = CPU_SH_NONE;
 		break;
 	}
 
-#ifdef CONFIG_CPU_HAS_PTEA
-	boot_cpu_data.flags |= CPU_HAS_PTEA;
-#endif
-
 	/*
 	 * On anything that's not a direct-mapped cache, look to the CVR
 	 * for I/D-cache specifics.
@@ -222,43 +197,48 @@
 	}
 
 	/*
-	 * Setup the L2 cache desc
-	 *
 	 * SH-4A's have an optional PIPT L2.
 	 */
 	if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
-		/* Bug if we can't decode the L2 info */
-		BUG_ON(!(cvr & 0xf));
-
-		/* Silicon and specifications have clearly never met.. */
-		cvr ^= 0xf;
-
 		/*
-		 * Size calculation is much more sensible
-		 * than it is for the L1.
-		 *
-		 * Sizes are 128KB, 258KB, 512KB, and 1MB.
+		 * Verify that it really has something hooked up, this
+		 * is the safety net for CPUs that have optional L2
+		 * support yet do not implement it.
 		 */
-		size = (cvr & 0xf) << 17;
+		if ((cvr & 0xf) == 0)
+			boot_cpu_data.flags &= ~CPU_HAS_L2_CACHE;
+		else {
+			/*
+			 * Silicon and specifications have clearly never
+			 * met..
+			 */
+			cvr ^= 0xf;
 
-		BUG_ON(!size);
+			/*
+			 * Size calculation is much more sensible
+			 * than it is for the L1.
+			 *
+			 * Sizes are 128KB, 258KB, 512KB, and 1MB.
+			 */
+			size = (cvr & 0xf) << 17;
 
-		boot_cpu_data.scache.way_incr		= (1 << 16);
-		boot_cpu_data.scache.entry_shift	= 5;
-		boot_cpu_data.scache.ways		= 4;
-		boot_cpu_data.scache.linesz		= L1_CACHE_BYTES;
+			boot_cpu_data.scache.way_incr		= (1 << 16);
+			boot_cpu_data.scache.entry_shift	= 5;
+			boot_cpu_data.scache.ways		= 4;
+			boot_cpu_data.scache.linesz		= L1_CACHE_BYTES;
 
-		boot_cpu_data.scache.entry_mask	=
-			(boot_cpu_data.scache.way_incr -
-			 boot_cpu_data.scache.linesz);
+			boot_cpu_data.scache.entry_mask	=
+				(boot_cpu_data.scache.way_incr -
+				 boot_cpu_data.scache.linesz);
 
-		boot_cpu_data.scache.sets	= size /
-			(boot_cpu_data.scache.linesz *
-			 boot_cpu_data.scache.ways);
+			boot_cpu_data.scache.sets	= size /
+				(boot_cpu_data.scache.linesz *
+				 boot_cpu_data.scache.ways);
 
-		boot_cpu_data.scache.way_size	=
-			(boot_cpu_data.scache.sets *
-			 boot_cpu_data.scache.linesz);
+			boot_cpu_data.scache.way_size	=
+				(boot_cpu_data.scache.sets *
+				 boot_cpu_data.scache.linesz);
+		}
 	}
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/setup-sh4-202.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/setup-sh4-202.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/setup-sh4-202.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  * SH4-202 Setup
  *
  *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2009  Magnus Damm
  *
  * 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
@@ -11,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
 
 static struct plat_sci_port sci_platform_data[] = {
 	{
@@ -31,8 +34,103 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct platform_device *sh4202_devices[] __initdata = {
 	&sci_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 };
 
 static int __init sh4202_devices_setup(void)
@@ -40,9 +138,73 @@
 	return platform_add_devices(sh4202_devices,
 				    ARRAY_SIZE(sh4202_devices));
 }
-__initcall(sh4202_devices_setup);
+arch_initcall(sh4202_devices_setup);
+
+static struct platform_device *sh4202_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh4202_early_devices,
+				   ARRAY_SIZE(sh4202_early_devices));
+}
+
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources */
+	IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
+	HUDI, TMU0, TMU1, TMU2, RTC, SCIF, WDT,
+};
+
+static struct intc_vect vectors[] __initdata = {
+	INTC_VECT(HUDI, 0x600),
+	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+	INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+	INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+	INTC_VECT(RTC, 0x4c0),
+	INTC_VECT(SCIF, 0x700), INTC_VECT(SCIF, 0x720),
+	INTC_VECT(SCIF, 0x740), INTC_VECT(SCIF, 0x760),
+	INTC_VECT(WDT, 0x560),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+	{ 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+	{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, 0, 0, 0 } },
+	{ 0xffd0000c, 0, 16, 4, /* IPRC */ { 0, 0, SCIF, HUDI } },
+	{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh4-202", vectors, NULL,
+			 NULL, prio_registers, NULL);
+
+static struct intc_vect vectors_irlm[] __initdata = {
+	INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+	INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irlm, "sh4-202_irlm", vectors_irlm, NULL,
+			 NULL, prio_registers, NULL);
 
 void __init plat_irq_setup(void)
 {
-	/* do nothing - all IRL interrupts are handled by the board code */
+	register_intc_controller(&intc_desc);
+}
+
+#define INTC_ICR	0xffd00000UL
+#define INTC_ICR_IRLM   (1<<7)
+
+void __init plat_irq_setup_pins(int mode)
+{
+	switch (mode) {
+	case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */
+		ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+		register_intc_controller(&intc_desc_irlm);
+		break;
+	default:
+		BUG();
+	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/setup-sh7750.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/setup-sh7750.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/setup-sh7750.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/setup-sh7750.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/io.h>
+#include <linux/sh_timer.h>
 #include <linux/serial_sci.h>
 
 static struct resource rtc_resources[] = {
@@ -60,9 +61,177 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751R)
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xfe100008,
+		.end	= 0xfe100013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 72,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xfe100014,
+		.end	= 0xfe10001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 76,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+#endif
+
 static struct platform_device *sh7750_devices[] __initdata = {
 	&rtc_device,
 	&sci_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751R)
+	&tmu3_device,
+	&tmu4_device,
+#endif
 };
 
 static int __init sh7750_devices_setup(void)
@@ -70,7 +239,25 @@
 	return platform_add_devices(sh7750_devices,
 				    ARRAY_SIZE(sh7750_devices));
 }
-__initcall(sh7750_devices_setup);
+arch_initcall(sh7750_devices_setup);
+
+static struct platform_device *sh7750_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7751R)
+	&tmu3_device,
+	&tmu4_device,
+#endif
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7750_early_devices,
+				   ARRAY_SIZE(sh7750_early_devices));
+}
 
 enum {
 	UNUSED = 0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/setup-sh7760.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/setup-sh7760.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4/setup-sh7760.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4/setup-sh7760.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/serial.h>
+#include <linux/sh_timer.h>
 #include <linux/serial_sci.h>
 #include <linux/io.h>
 
@@ -18,10 +19,7 @@
 
 	/* interrupt sources */
 	IRL0, IRL1, IRL2, IRL3,
-	HUDI, GPIOI,
-	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
-	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
-	DMAC_DMAE,
+	HUDI, GPIOI, DMAC,
 	IRQ4, IRQ5, IRQ6, IRQ7,
 	HCAN20, HCAN21,
 	SSI0, SSI1,
@@ -36,21 +34,20 @@
 	HSPI,
 	MMCIF0, MMCIF1, MMCIF2, MMCIF3,
 	MFI, ADC, CMT,
-	TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
-	WDT,
-	REF_RCMI, REF_ROVI,
+	TMU0, TMU1, TMU2,
+	WDT, REF,
 
 	/* interrupt groups */
-	DMAC, DMABRG, SCIF0, SCIF1, SCIF2, SIM, MMCIF, TMU2, REF,
+	DMABRG, SCIF0, SCIF1, SCIF2, SIM, MMCIF,
 };
 
 static struct intc_vect vectors[] __initdata = {
 	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
-	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
-	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
-	INTC_VECT(DMAC_DMAE, 0x6c0),
+	INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+	INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+	INTC_VECT(DMAC, 0x780), INTC_VECT(DMAC, 0x7a0),
+	INTC_VECT(DMAC, 0x7c0), INTC_VECT(DMAC, 0x7e0),
+	INTC_VECT(DMAC, 0x6c0),
 	INTC_VECT(IRQ4, 0x800), INTC_VECT(IRQ5, 0x820),
 	INTC_VECT(IRQ6, 0x840), INTC_VECT(IRQ6, 0x860),
 	INTC_VECT(HCAN20, 0x900), INTC_VECT(HCAN21, 0x920),
@@ -74,23 +71,18 @@
 	INTC_VECT(MFI, 0xe80), /* 0xf80 according to data sheet */
 	INTC_VECT(ADC, 0xf80), INTC_VECT(CMT, 0xfa0),
 	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
-	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+	INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
 	INTC_VECT(WDT, 0x560),
-	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+	INTC_VECT(REF, 0x580), INTC_VECT(REF, 0x5a0),
 };
 
 static struct intc_group groups[] __initdata = {
-	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
-		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
 	INTC_GROUP(DMABRG, DMABRG0, DMABRG1, DMABRG2),
 	INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
 	INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
 	INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
 	INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI),
 	INTC_GROUP(MMCIF, MMCIF0, MMCIF1, MMCIF2, MMCIF3),
-	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
-	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
 };
 
 static struct intc_mask_reg mask_registers[] __initdata = {
@@ -168,8 +160,104 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+
 static struct platform_device *sh7760_devices[] __initdata = {
 	&sci_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 };
 
 static int __init sh7760_devices_setup(void)
@@ -177,7 +265,19 @@
 	return platform_add_devices(sh7760_devices,
 				    ARRAY_SIZE(sh7760_devices));
 }
-__initcall(sh7760_devices_setup);
+arch_initcall(sh7760_devices_setup);
+
+static struct platform_device *sh7760_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7760_early_devices,
+				   ARRAY_SIZE(sh7760_early_devices));
+}
 
 #define INTC_ICR	0xffd00000UL
 #define INTC_ICR_IRLM	(1 << 7)
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7343.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7343.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7343.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,211 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7343.c
+ *
+ * SH7343 clock framework support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+
+/* SH7343 registers */
+#define FRQCR		0xa4150000
+#define VCLKCR		0xa4150004
+#define SCLKACR		0xa4150008
+#define SCLKBCR		0xa415000c
+#define PLLCR		0xa4150024
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+#define DLLFRQ		0xa4150050
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+	.name           = "rclk",
+	.id             = -1,
+	.rate           = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
+};
+
+/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
+{
+	unsigned long mult;
+
+	if (__raw_readl(PLLCR) & 0x1000)
+		mult = __raw_readl(DLLFRQ);
+	else
+		mult = 0;
+
+	return clk->parent->rate * mult;
+}
+
+static struct clk_ops dll_clk_ops = {
+	.recalc		= dll_recalc,
+};
+
+static struct clk dll_clk = {
+	.name           = "dll_clk",
+	.id             = -1,
+	.ops		= &dll_clk_ops,
+	.parent		= &r_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+	unsigned long mult = 1;
+
+	if (__raw_readl(PLLCR) & 0x4000)
+		mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+
+	return clk->parent->rate * mult;
+}
+
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+};
+
+static struct clk pll_clk = {
+	.name		= "pll_clk",
+	.id		= -1,
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+	&r_clk,
+	&extal_clk,
+	&dll_clk,
+	&pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+static struct clk_div_mult_table div4_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+	.multipliers = multipliers,
+	.nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
+       DIV4_SIUA, DIV4_SIUB, DIV4_NR };
+
+#define DIV4(_str, _reg, _bit, _mask, _flags) \
+  SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0),
+	[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0),
+	[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0),
+};
+
+struct clk div6_clks[] = {
+	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
+};
+
+#define MSTP(_str, _parent, _reg, _bit, _flags) \
+  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
+
+static struct clk mstp_clks[] = {
+	MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
+	MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
+	MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
+	MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+	MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
+	MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0),
+	MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0),
+	MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0),
+	MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0),
+	MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0),
+	MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0),
+	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
+	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
+	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
+	MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0),
+	MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
+	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
+	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
+	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
+	MSTP("scif3", &div4_clks[DIV4_P], MSTPCR0, 4, 0),
+	MSTP("sio0", &div4_clks[DIV4_P], MSTPCR0, 3, 0),
+	MSTP("siof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0),
+	MSTP("siof1", &div4_clks[DIV4_P], MSTPCR0, 1, 0),
+
+	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
+	MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0),
+
+	MSTP("tpu0", &div4_clks[DIV4_P], MSTPCR2, 25, 0),
+	MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0),
+	MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
+	MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0),
+	MSTP("sim0", &div4_clks[DIV4_P], MSTPCR2, 16, 0),
+	MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
+	MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 13, 0),
+	MSTP("s3d40", &div4_clks[DIV4_P], MSTPCR2, 12, 0),
+	MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
+	MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
+	MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
+	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
+	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
+	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
+	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
+	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
+	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
+};
+
+int __init arch_clk_init(void)
+{
+	int k, ret = 0;
+
+	/* autodetect extal or dll configuration */
+	if (__raw_readl(PLLCR) & 0x1000)
+		pll_clk.parent = &dll_clk;
+	else
+		pll_clk.parent = &extal_clk;
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
+
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7366.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7366.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7366.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,211 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7366.c
+ *
+ * SH7366 clock framework support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+
+/* SH7366 registers */
+#define FRQCR		0xa4150000
+#define VCLKCR		0xa4150004
+#define SCLKACR		0xa4150008
+#define SCLKBCR		0xa415000c
+#define PLLCR		0xa4150024
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+#define DLLFRQ		0xa4150050
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+	.name           = "rclk",
+	.id             = -1,
+	.rate           = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
+};
+
+/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
+{
+	unsigned long mult;
+
+	if (__raw_readl(PLLCR) & 0x1000)
+		mult = __raw_readl(DLLFRQ);
+	else
+		mult = 0;
+
+	return clk->parent->rate * mult;
+}
+
+static struct clk_ops dll_clk_ops = {
+	.recalc		= dll_recalc,
+};
+
+static struct clk dll_clk = {
+	.name           = "dll_clk",
+	.id             = -1,
+	.ops		= &dll_clk_ops,
+	.parent		= &r_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+	unsigned long mult = 1;
+	unsigned long div = 1;
+
+	if (__raw_readl(PLLCR) & 0x4000)
+		mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+	else
+		div = 2;
+
+	return (clk->parent->rate * mult) / div;
+}
+
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+};
+
+static struct clk pll_clk = {
+	.name		= "pll_clk",
+	.id		= -1,
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+	&r_clk,
+	&extal_clk,
+	&dll_clk,
+	&pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+static struct clk_div_mult_table div4_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+	.multipliers = multipliers,
+	.nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
+       DIV4_SIUA, DIV4_SIUB, DIV4_NR };
+
+#define DIV4(_str, _reg, _bit, _mask, _flags) \
+  SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
+	[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0),
+	[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0),
+	[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0),
+};
+
+struct clk div6_clks[] = {
+	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
+};
+
+#define MSTP(_str, _parent, _reg, _bit, _flags) \
+  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
+
+static struct clk mstp_clks[] = {
+	/* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
+	MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
+	MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
+	MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
+	MSTP("rsmem0", &div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+	MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
+	MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0),
+	MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0),
+	MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0),
+	MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0),
+	MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0),
+	MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0),
+	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
+	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
+	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
+	MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0),
+	MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
+	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
+	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
+	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
+	MSTP("msiof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0),
+	MSTP("sbr0", &div4_clks[DIV4_P], MSTPCR0, 1, 0),
+
+	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
+
+	MSTP("icb0", &div4_clks[DIV4_P], MSTPCR2, 27, 0),
+	MSTP("meram0", &div4_clks[DIV4_P], MSTPCR2, 26, 0),
+	MSTP("dacy1", &div4_clks[DIV4_P], MSTPCR2, 24, 0),
+	MSTP("dacy0", &div4_clks[DIV4_P], MSTPCR2, 23, 0),
+	MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 22, 0),
+	MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
+	MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0),
+	MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
+	MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
+	MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT),
+	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
+	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
+	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
+	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
+	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
+	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
+};
+
+int __init arch_clk_init(void)
+{
+	int k, ret = 0;
+
+	/* autodetect extal or dll configuration */
+	if (__raw_readl(PLLCR) & 0x1000)
+		pll_clk.parent = &dll_clk;
+	else
+		pll_clk.parent = &extal_clk;
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
+
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7722.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7722.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7722.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,844 +1,197 @@
 /*
  * arch/sh/kernel/cpu/sh4a/clock-sh7722.c
  *
- * SH7343, SH7722, SH7723 & SH7366 support for the clock framework
+ * SH7722 clock framework support
  *
- * Copyright (c) 2006-2007 Nomad Global Solutions Inc
- * Based on code for sh7343 by Paul Mundt
+ * Copyright (C) 2009 Magnus Damm
  *
- * 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.
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/stringify.h>
 #include <asm/clock.h>
-#include <asm/freq.h>
-
-#define N  (-1)
-#define NM (-2)
-#define ROUND_NEAREST 0
-#define ROUND_DOWN -1
-#define ROUND_UP   +1
 
-static int adjust_algos[][3] = {
-	{},	/* NO_CHANGE */
-	{ NM, N, 1 },   /* N:1, N:1 */
-	{ 3, 2, 2 },	/* 3:2:2 */
-	{ 5, 2, 2 },    /* 5:2:2 */
-	{ N, 1, 1 },	/* N:1:1 */
-
-	{ N, 1 },	/* N:1 */
-
-	{ N, 1 },	/* N:1 */
-	{ 3, 2 },
-	{ 4, 3 },
-	{ 5, 4 },
+/* SH7722 registers */
+#define FRQCR		0xa4150000
+#define VCLKCR		0xa4150004
+#define SCLKACR		0xa4150008
+#define SCLKBCR		0xa415000c
+#define IRDACLKCR	0xa4150018
+#define PLLCR		0xa4150024
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+#define DLLFRQ		0xa4150050
 
-	{ N, 1 }
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+	.name           = "rclk",
+	.id             = -1,
+	.rate           = 32768,
 };
 
-static unsigned long adjust_pair_of_clocks(unsigned long r1, unsigned long r2,
-			int m1, int m2, int round_flag)
-{
-	unsigned long rem, div;
-	int the_one = 0;
-
-	pr_debug( "Actual values: r1 = %ld\n", r1);
-	pr_debug( "...............r2 = %ld\n", r2);
-
-	if (m1 == m2) {
-		r2 = r1;
-		pr_debug( "setting equal rates: r2 now %ld\n", r2);
-	} else if ((m2 == N  && m1 == 1) ||
-		   (m2 == NM && m1 == N)) { /* N:1 or NM:N */
-		pr_debug( "Setting rates as 1:N (N:N*M)\n");
-		rem = r2 % r1;
-		pr_debug( "...remainder = %ld\n", rem);
-		if (rem) {
-			div = r2 / r1;
-			pr_debug( "...div = %ld\n", div);
-			switch (round_flag) {
-			case ROUND_NEAREST:
-				the_one = rem >= r1/2 ? 1 : 0; break;
-			case ROUND_UP:
-				the_one = 1; break;
-			case ROUND_DOWN:
-				the_one = 0; break;
-			}
-
-			r2 = r1 * (div + the_one);
-			pr_debug( "...setting r2 to %ld\n", r2);
-		}
-	} else if ((m2 == 1  && m1 == N) ||
-		   (m2 == N && m1 == NM)) { /* 1:N or N:NM */
-		pr_debug( "Setting rates as N:1 (N*M:N)\n");
-		rem = r1 % r2;
-		pr_debug( "...remainder = %ld\n", rem);
-		if (rem) {
-			div = r1 / r2;
-			pr_debug( "...div = %ld\n", div);
-			switch (round_flag) {
-			case ROUND_NEAREST:
-				the_one = rem > r2/2 ? 1 : 0; break;
-			case ROUND_UP:
-				the_one = 0; break;
-			case ROUND_DOWN:
-				the_one = 1; break;
-			}
-
-			r2 = r1 / (div + the_one);
-			pr_debug( "...setting r2 to %ld\n", r2);
-		}
-	} else { /* value:value */
-		pr_debug( "Setting rates as %d:%d\n", m1, m2);
-		div = r1 / m1;
-		r2 = div * m2;
-		pr_debug( "...div = %ld\n", div);
-		pr_debug( "...setting r2 to %ld\n", r2);
-	}
-
-	return r2;
-}
-
-static void adjust_clocks(int originate, int *l, unsigned long v[],
-			  int n_in_line)
-{
-	int x;
-
-	pr_debug( "Go down from %d...\n", originate);
-	/* go up recalculation clocks */
-	for (x = originate; x>0; x -- )
-		v[x-1] = adjust_pair_of_clocks(v[x], v[x-1],
-					l[x], l[x-1],
-					ROUND_UP);
-
-	pr_debug( "Go up from %d...\n", originate);
-	/* go down recalculation clocks */
-	for (x = originate; x<n_in_line - 1; x ++ )
-		v[x+1] = adjust_pair_of_clocks(v[x], v[x+1],
-					l[x], l[x+1],
-					ROUND_UP);
-}
-
-
-/*
- * SH7722 uses a common set of multipliers and divisors, so this
- * is quite simple..
- */
-
 /*
- * Instead of having two separate multipliers/divisors set, like this:
- *
- * static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
- * static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
- *
- * I created the divisors2 array, which is used to calculate rate like
- *   rate = parent * 2 / divisors2[ divisor ];
-*/
-static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 };
-
-static void master_clk_recalc(struct clk *clk)
-{
-	unsigned frqcr = ctrl_inl(FRQCR);
-
-	clk->rate = CONFIG_SH_PCLK_FREQ * (((frqcr >> 24) & 0x1f) + 1);
-}
-
-static void master_clk_init(struct clk *clk)
-{
-	clk->parent = NULL;
-	clk->flags |= CLK_RATE_PROPAGATES;
-	clk->rate = CONFIG_SH_PCLK_FREQ;
-	master_clk_recalc(clk);
-}
-
-
-static void module_clk_recalc(struct clk *clk)
-{
-	unsigned long frqcr = ctrl_inl(FRQCR);
-
-	clk->rate = clk->parent->rate / (((frqcr >> 24) & 0x1f) + 1);
-}
-
-static int master_clk_setrate(struct clk *clk, unsigned long rate, int id)
-{
-	int div = rate / clk->rate;
-	int master_divs[] = { 2, 3, 4, 6, 8, 16 };
-	int index;
-	unsigned long frqcr;
-
-	for (index = 1; index < ARRAY_SIZE(master_divs); index++)
-		if (div >= master_divs[index - 1] && div < master_divs[index])
-			break;
-
-	if (index >= ARRAY_SIZE(master_divs))
-		index = ARRAY_SIZE(master_divs);
-	div = master_divs[index - 1];
-
-	frqcr = ctrl_inl(FRQCR);
-	frqcr &= ~(0xF << 24);
-	frqcr |= ( (div-1) << 24);
-	ctrl_outl(frqcr, FRQCR);
-
-	return 0;
-}
-
-static struct clk_ops sh7722_master_clk_ops = {
-	.init = master_clk_init,
-	.recalc = master_clk_recalc,
-	.set_rate = master_clk_setrate,
-};
-
-static struct clk_ops sh7722_module_clk_ops = {
-       .recalc = module_clk_recalc,
-};
-
-struct frqcr_context {
-	unsigned mask;
-	unsigned shift;
-};
-
-struct frqcr_context sh7722_get_clk_context(const char *name)
-{
-	struct frqcr_context ctx = { 0, };
-
-	if (!strcmp(name, "peripheral_clk")) {
-		ctx.shift = 0;
-		ctx.mask = 0xF;
-	} else if (!strcmp(name, "sdram_clk")) {
-		ctx.shift = 4;
-		ctx.mask = 0xF;
-	} else if (!strcmp(name, "bus_clk")) {
-		ctx.shift = 8;
-		ctx.mask = 0xF;
-	} else if (!strcmp(name, "sh_clk")) {
-		ctx.shift = 12;
-		ctx.mask = 0xF;
-	} else if (!strcmp(name, "umem_clk")) {
-		ctx.shift = 16;
-		ctx.mask = 0xF;
-	} else if (!strcmp(name, "cpu_clk")) {
-		ctx.shift = 20;
-		ctx.mask = 7;
-	}
-	return ctx;
-}
-
-/**
- * sh7722_find_div_index - find divisor for setting rate
- *
- * All sh7722 clocks use the same set of multipliers/divisors. This function
- * chooses correct divisor to set the rate of clock with parent clock that
- * generates frequency of 'parent_rate'
- *
- * @parent_rate: rate of parent clock
- * @rate: requested rate to be set
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
  */
-static int sh7722_find_div_index(unsigned long parent_rate, unsigned rate)
-{
-	unsigned div2 = parent_rate * 2 / rate;
-	int index;
-
-	if (rate > parent_rate)
-		return -EINVAL;
-
-	for (index = 1; index < ARRAY_SIZE(divisors2); index++) {
-		if (div2 > divisors2[index - 1] && div2 <= divisors2[index])
-			break;
-	}
-	if (index >= ARRAY_SIZE(divisors2))
-		index = ARRAY_SIZE(divisors2) - 1;
-	return index;
-}
-
-static void sh7722_frqcr_recalc(struct clk *clk)
-{
-	struct frqcr_context ctx = sh7722_get_clk_context(clk->name);
-	unsigned long frqcr = ctrl_inl(FRQCR);
-	int index;
-
-	index = (frqcr >> ctx.shift) & ctx.mask;
-	clk->rate = clk->parent->rate * 2 / divisors2[index];
-}
-
-static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate,
-				 int algo_id)
-{
-	struct frqcr_context ctx = sh7722_get_clk_context(clk->name);
-	unsigned long parent_rate = clk->parent->rate;
-	int div;
-	unsigned long frqcr;
-	int err = 0;
-
-	/* pretty invalid */
-	if (parent_rate < rate)
-		return -EINVAL;
-
-	/* look for multiplier/divisor pair */
-	div = sh7722_find_div_index(parent_rate, rate);
-	if (div<0)
-		return div;
-
-	/* calculate new value of clock rate */
-	clk->rate = parent_rate * 2 / divisors2[div];
-	frqcr = ctrl_inl(FRQCR);
-
-	/* FIXME: adjust as algo_id specifies */
-	if (algo_id != NO_CHANGE) {
-		int originator;
-		char *algo_group_1[] = { "cpu_clk", "umem_clk", "sh_clk" };
-		char *algo_group_2[] = { "sh_clk", "bus_clk" };
-		char *algo_group_3[] = { "sh_clk", "sdram_clk" };
-		char *algo_group_4[] = { "bus_clk", "peripheral_clk" };
-		char *algo_group_5[] = { "cpu_clk", "peripheral_clk" };
-		char **algo_current = NULL;
-		/* 3 is the maximum number of clocks in relation */
-		struct clk *ck[3];
-		unsigned long values[3]; /* the same comment as above */
-		int part_length = -1;
-		int i;
-
-		/*
-		 * all the steps below only required if adjustion was
-		 * requested
-		 */
-		if (algo_id == IUS_N1_N1 ||
-		    algo_id == IUS_322 ||
-		    algo_id == IUS_522 ||
-		    algo_id == IUS_N11) {
-			algo_current = algo_group_1;
-			part_length = 3;
-		}
-		if (algo_id == SB_N1) {
-			algo_current = algo_group_2;
-			part_length = 2;
-		}
-		if (algo_id == SB3_N1 ||
-		    algo_id == SB3_32 ||
-		    algo_id == SB3_43 ||
-		    algo_id == SB3_54) {
-			algo_current = algo_group_3;
-			part_length = 2;
-		}
-		if (algo_id == BP_N1) {
-			algo_current = algo_group_4;
-			part_length = 2;
-		}
-		if (algo_id == IP_N1) {
-			algo_current = algo_group_5;
-			part_length = 2;
-		}
-		if (!algo_current)
-			goto incorrect_algo_id;
-
-		originator = -1;
-		for (i = 0; i < part_length; i ++ ) {
-			if (originator >= 0 && !strcmp(clk->name,
-						       algo_current[i]))
-				originator = i;
-			ck[i] = clk_get(NULL, algo_current[i]);
-			values[i] = clk_get_rate(ck[i]);
-		}
-
-		if (originator >= 0)
-			adjust_clocks(originator, adjust_algos[algo_id],
-				      values, part_length);
-
-		for (i = 0; i < part_length; i ++ ) {
-			struct frqcr_context part_ctx;
-			int part_div;
-
-			if (likely(!err)) {
-				part_div = sh7722_find_div_index(parent_rate,
-								rate);
-				if (part_div > 0) {
-					part_ctx = sh7722_get_clk_context(
-								ck[i]->name);
-					frqcr &= ~(part_ctx.mask <<
-						   part_ctx.shift);
-					frqcr |= part_div << part_ctx.shift;
-				} else
-					err = part_div;
-			}
-
-			ck[i]->ops->recalc(ck[i]);
-			clk_put(ck[i]);
-		}
-	}
-
-	/* was there any error during recalculation ? If so, bail out.. */
-	if (unlikely(err!=0))
-		goto out_err;
-
-	/* clear FRQCR bits */
-	frqcr &= ~(ctx.mask << ctx.shift);
-	frqcr |= div << ctx.shift;
-
-	/* ...and perform actual change */
-	ctrl_outl(frqcr, FRQCR);
-	return 0;
-
-incorrect_algo_id:
-	return -EINVAL;
-out_err:
-	return err;
-}
-
-static long sh7722_frqcr_round_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk->parent->rate;
-	int div;
-
-	/* look for multiplier/divisor pair */
-	div = sh7722_find_div_index(parent_rate, rate);
-	if (div < 0)
-		return clk->rate;
-
-	/* calculate new value of clock rate */
-	return parent_rate * 2 / divisors2[div];
-}
-
-static struct clk_ops sh7722_frqcr_clk_ops = {
-	.recalc = sh7722_frqcr_recalc,
-	.set_rate = sh7722_frqcr_set_rate,
-	.round_rate = sh7722_frqcr_round_rate,
+struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
 };
 
-/*
- * clock ops methods for SIU A/B and IrDA clock
- *
- */
-
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
-
-static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id)
-{
-	unsigned long r;
-	int div;
-
-	r = ctrl_inl(clk->arch_flags);
-	div = sh7722_find_div_index(clk->parent->rate, rate);
-	if (div < 0)
-		return div;
-	r = (r & ~0xF) | div;
-	ctrl_outl(r, clk->arch_flags);
-	return 0;
-}
-
-static void sh7722_siu_recalc(struct clk *clk)
-{
-	unsigned long r;
-
-	r = ctrl_inl(clk->arch_flags);
-	clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
-}
-
-static int sh7722_siu_start_stop(struct clk *clk, int enable)
+/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
 {
-	unsigned long r;
+	unsigned long mult;
 
-	r = ctrl_inl(clk->arch_flags);
-	if (enable)
-		ctrl_outl(r & ~(1 << 8), clk->arch_flags);
+	if (__raw_readl(PLLCR) & 0x1000)
+		mult = __raw_readl(DLLFRQ);
 	else
-		ctrl_outl(r | (1 << 8), clk->arch_flags);
-	return 0;
-}
-
-static void sh7722_siu_enable(struct clk *clk)
-{
-	sh7722_siu_start_stop(clk, 1);
-}
+		mult = 0;
 
-static void sh7722_siu_disable(struct clk *clk)
-{
-	sh7722_siu_start_stop(clk, 0);
+	return clk->parent->rate * mult;
 }
 
-static struct clk_ops sh7722_siu_clk_ops = {
-	.recalc = sh7722_siu_recalc,
-	.set_rate = sh7722_siu_set_rate,
-	.enable = sh7722_siu_enable,
-	.disable = sh7722_siu_disable,
+static struct clk_ops dll_clk_ops = {
+	.recalc		= dll_recalc,
 };
 
-#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
-
-static void sh7722_video_enable(struct clk *clk)
-{
-	unsigned long r;
-
-	r = ctrl_inl(VCLKCR);
-	ctrl_outl( r & ~(1<<8), VCLKCR);
-}
-
-static void sh7722_video_disable(struct clk *clk)
-{
-	unsigned long r;
-
-	r = ctrl_inl(VCLKCR);
-	ctrl_outl( r | (1<<8), VCLKCR);
-}
+static struct clk dll_clk = {
+	.name           = "dll_clk",
+	.id             = -1,
+	.ops		= &dll_clk_ops,
+	.parent		= &r_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
 
-static int sh7722_video_set_rate(struct clk *clk, unsigned long rate,
-				 int algo_id)
+static unsigned long pll_recalc(struct clk *clk)
 {
-	unsigned long r;
-
-	r = ctrl_inl(VCLKCR);
-	r &= ~0x3F;
-	r |= ((clk->parent->rate / rate - 1) & 0x3F);
-	ctrl_outl(r, VCLKCR);
-	return 0;
-}
+	unsigned long mult = 1;
+	unsigned long div = 1;
 
-static void sh7722_video_recalc(struct clk *clk)
-{
-	unsigned long r;
+	if (__raw_readl(PLLCR) & 0x4000)
+		mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+	else
+		div = 2;
 
-	r = ctrl_inl(VCLKCR);
-	clk->rate = clk->parent->rate / ((r & 0x3F) + 1);
+	return (clk->parent->rate * mult) / div;
 }
 
-static struct clk_ops sh7722_video_clk_ops = {
-	.recalc = sh7722_video_recalc,
-	.set_rate = sh7722_video_set_rate,
-	.enable = sh7722_video_enable,
-	.disable = sh7722_video_disable,
-};
-/*
- * and at last, clock definitions themselves
- */
-static struct clk sh7722_umem_clock = {
-	.name = "umem_clk",
-	.ops = &sh7722_frqcr_clk_ops,
-	.flags = CLK_RATE_PROPAGATES,
-};
-
-static struct clk sh7722_sh_clock = {
-	.name = "sh_clk",
-	.ops = &sh7722_frqcr_clk_ops,
-	.flags = CLK_RATE_PROPAGATES,
-};
-
-static struct clk sh7722_peripheral_clock = {
-	.name = "peripheral_clk",
-	.ops = &sh7722_frqcr_clk_ops,
-	.flags = CLK_RATE_PROPAGATES,
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
 };
 
-static struct clk sh7722_sdram_clock = {
-	.name = "sdram_clk",
-	.ops = &sh7722_frqcr_clk_ops,
+static struct clk pll_clk = {
+	.name		= "pll_clk",
+	.id		= -1,
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
 };
 
-static struct clk sh7722_r_clock = {
-	.name = "r_clk",
-	.rate = 32768,
-	.flags = CLK_RATE_PROPAGATES,
+struct clk *main_clks[] = {
+	&r_clk,
+	&extal_clk,
+	&dll_clk,
+	&pll_clk,
 };
 
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
 
-/*
- * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops
- * methods of clk_ops determine which register they should access by
- * examining clk->name field
- */
-static struct clk sh7722_siu_a_clock = {
-	.name = "siu_a_clk",
-	.arch_flags = SCLKACR,
-	.ops = &sh7722_siu_clk_ops,
+static struct clk_div_mult_table div4_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+	.multipliers = multipliers,
+	.nr_multipliers = ARRAY_SIZE(multipliers),
 };
 
-static struct clk sh7722_siu_b_clock = {
-	.name = "siu_b_clk",
-	.arch_flags = SCLKBCR,
-	.ops = &sh7722_siu_clk_ops,
-};
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
+       DIV4_SIUA, DIV4_SIUB, DIV4_IRDA, DIV4_NR };
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-static struct clk sh7722_irda_clock = {
-	.name = "irda_clk",
-	.arch_flags = IrDACLKCR,
-	.ops = &sh7722_siu_clk_ops,
-};
-#endif
-#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
+#define DIV4(_str, _reg, _bit, _mask, _flags) \
+  SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
 
-static struct clk sh7722_video_clock = {
-	.name = "video_clk",
-	.ops = &sh7722_video_clk_ops,
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
+	[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
+	[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0),
+	[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0),
+	[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0),
+	[DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x1fff, 0),
 };
 
-#define MSTPCR_ARCH_FLAGS(reg, bit) (((reg) << 8) | (bit))
-#define MSTPCR_ARCH_FLAGS_REG(value) ((value) >> 8)
-#define MSTPCR_ARCH_FLAGS_BIT(value) ((value) & 0xff)
-
-static int sh7722_mstpcr_start_stop(struct clk *clk, int enable)
-{
-	unsigned long bit = MSTPCR_ARCH_FLAGS_BIT(clk->arch_flags);
-	unsigned long reg;
-	unsigned long r;
-
-	switch(MSTPCR_ARCH_FLAGS_REG(clk->arch_flags)) {
-	case 0:
-		reg = MSTPCR0;
-		break;
-	case 1:
-		reg = MSTPCR1;
-		break;
-	case 2:
-		reg = MSTPCR2;
-		break;
-	default:
-		return -EINVAL;
-	}  
-
-	r = ctrl_inl(reg);
-
-	if (enable)
-		r &= ~(1 << bit);
-	else
-		r |= (1 << bit);
-
-	ctrl_outl(r, reg);
-	return 0;
-}
-
-static void sh7722_mstpcr_enable(struct clk *clk)
-{
-	sh7722_mstpcr_start_stop(clk, 1);
-}
-
-static void sh7722_mstpcr_disable(struct clk *clk)
-{
-	sh7722_mstpcr_start_stop(clk, 0);
-}
-
-static void sh7722_mstpcr_recalc(struct clk *clk)
-{
-	if (clk->parent)
-		clk->rate = clk->parent->rate;
-}
-
-static struct clk_ops sh7722_mstpcr_clk_ops = {
-	.enable = sh7722_mstpcr_enable,
-	.disable = sh7722_mstpcr_disable,
-	.recalc = sh7722_mstpcr_recalc,
+struct clk div6_clks[] = {
+	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
 };
 
-#define MSTPCR(_name, _parent, regnr, bitnr) \
-{						\
-	.name = _name,				\
-	.arch_flags = MSTPCR_ARCH_FLAGS(regnr, bitnr),	\
-	.ops = (void *)_parent,		\
-}
+#define MSTP(_str, _parent, _reg, _bit, _flags) \
+  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
 
-static struct clk sh7722_mstpcr_clocks[] = {
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-	MSTPCR("uram0", "umem_clk", 0, 28),
-	MSTPCR("xymem0", "bus_clk", 0, 26),
-	MSTPCR("tmu0", "peripheral_clk", 0, 15),
-	MSTPCR("cmt0", "r_clk", 0, 14),
-	MSTPCR("rwdt0", "r_clk", 0, 13),
-	MSTPCR("flctl0", "peripheral_clk", 0, 10),
-	MSTPCR("scif0", "peripheral_clk", 0, 7),
-	MSTPCR("scif1", "peripheral_clk", 0, 6),
-	MSTPCR("scif2", "peripheral_clk", 0, 5),
-	MSTPCR("i2c0", "peripheral_clk", 1, 9),
-	MSTPCR("rtc0", "r_clk", 1, 8),
-	MSTPCR("sdhi0", "peripheral_clk", 2, 18),
-	MSTPCR("keysc0", "r_clk", 2, 14),
-	MSTPCR("usbf0", "peripheral_clk", 2, 11),
-	MSTPCR("2dg0", "bus_clk", 2, 9),
-	MSTPCR("siu0", "bus_clk", 2, 8),
-	MSTPCR("vou0", "bus_clk", 2, 5),
-	MSTPCR("jpu0", "bus_clk", 2, 6),
-	MSTPCR("beu0", "bus_clk", 2, 4),
-	MSTPCR("ceu0", "bus_clk", 2, 3),
-	MSTPCR("veu0", "bus_clk", 2, 2),
-	MSTPCR("vpu0", "bus_clk", 2, 1),
-	MSTPCR("lcdc0", "bus_clk", 2, 0),
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7723)
-	/* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
-	MSTPCR("tlb0", "cpu_clk", 0, 31),
-	MSTPCR("ic0", "cpu_clk", 0, 30),
-	MSTPCR("oc0", "cpu_clk", 0, 29),
-	MSTPCR("l2c0", "sh_clk", 0, 28),
-	MSTPCR("ilmem0", "cpu_clk", 0, 27),
-	MSTPCR("fpu0", "cpu_clk", 0, 24),
-	MSTPCR("intc0", "cpu_clk", 0, 22),
-	MSTPCR("dmac0", "bus_clk", 0, 21),
-	MSTPCR("sh0", "sh_clk", 0, 20),
-	MSTPCR("hudi0", "peripheral_clk", 0, 19),
-	MSTPCR("ubc0", "cpu_clk", 0, 17),
-	MSTPCR("tmu0", "peripheral_clk", 0, 15),
-	MSTPCR("cmt0", "r_clk", 0, 14),
-	MSTPCR("rwdt0", "r_clk", 0, 13),
-	MSTPCR("dmac1", "bus_clk", 0, 12),
-	MSTPCR("tmu1", "peripheral_clk", 0, 11),
-	MSTPCR("flctl0", "peripheral_clk", 0, 10),
-	MSTPCR("scif0", "peripheral_clk", 0, 9),
-	MSTPCR("scif1", "peripheral_clk", 0, 8),
-	MSTPCR("scif2", "peripheral_clk", 0, 7),
-	MSTPCR("scif3", "bus_clk", 0, 6),
-	MSTPCR("scif4", "bus_clk", 0, 5),
-	MSTPCR("scif5", "bus_clk", 0, 4),
-	MSTPCR("msiof0", "bus_clk", 0, 2),
-	MSTPCR("msiof1", "bus_clk", 0, 1),
-	MSTPCR("meram0", "sh_clk", 0, 0),
-	MSTPCR("i2c0", "peripheral_clk", 1, 9),
-	MSTPCR("rtc0", "r_clk", 1, 8),
-	MSTPCR("atapi0", "sh_clk", 2, 28),
-	MSTPCR("adc0", "peripheral_clk", 2, 28),
-	MSTPCR("tpu0", "bus_clk", 2, 25),
-	MSTPCR("irda0", "peripheral_clk", 2, 24),
-	MSTPCR("tsif0", "bus_clk", 2, 22),
-	MSTPCR("icb0", "bus_clk", 2, 21),
-	MSTPCR("sdhi0", "bus_clk", 2, 18),
-	MSTPCR("sdhi1", "bus_clk", 2, 17),
-	MSTPCR("keysc0", "r_clk", 2, 14),
-	MSTPCR("usb0", "bus_clk", 2, 11),
-	MSTPCR("2dg0", "bus_clk", 2, 10),
-	MSTPCR("siu0", "bus_clk", 2, 8),
-	MSTPCR("veu1", "bus_clk", 2, 6),
-	MSTPCR("vou0", "bus_clk", 2, 5),
-	MSTPCR("beu0", "bus_clk", 2, 4),
-	MSTPCR("ceu0", "bus_clk", 2, 3),
-	MSTPCR("veu0", "bus_clk", 2, 2),
-	MSTPCR("vpu0", "bus_clk", 2, 1),
-	MSTPCR("lcdc0", "bus_clk", 2, 0),
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7343)
-	MSTPCR("uram0", "umem_clk", 0, 28),
-	MSTPCR("xymem0", "bus_clk", 0, 26),
-	MSTPCR("tmu0", "peripheral_clk", 0, 15),
-	MSTPCR("cmt0", "r_clk", 0, 14),
-	MSTPCR("rwdt0", "r_clk", 0, 13),
-	MSTPCR("scif0", "peripheral_clk", 0, 7),
-	MSTPCR("scif1", "peripheral_clk", 0, 6),
-	MSTPCR("scif2", "peripheral_clk", 0, 5),
-	MSTPCR("scif3", "peripheral_clk", 0, 4),
-	MSTPCR("i2c0", "peripheral_clk", 1, 9),
-	MSTPCR("i2c1", "peripheral_clk", 1, 8),
-	MSTPCR("sdhi0", "peripheral_clk", 2, 18),
-	MSTPCR("keysc0", "r_clk", 2, 14),
-	MSTPCR("usbf0", "peripheral_clk", 2, 11),
-	MSTPCR("siu0", "bus_clk", 2, 8),
-	MSTPCR("jpu0", "bus_clk", 2, 6),
-	MSTPCR("vou0", "bus_clk", 2, 5),
-	MSTPCR("beu0", "bus_clk", 2, 4),
-	MSTPCR("ceu0", "bus_clk", 2, 3),
-	MSTPCR("veu0", "bus_clk", 2, 2),
-	MSTPCR("vpu0", "bus_clk", 2, 1),
-	MSTPCR("lcdc0", "bus_clk", 2, 0),
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7366)
-	/* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
-	MSTPCR("tlb0", "cpu_clk", 0, 31),
-	MSTPCR("ic0", "cpu_clk", 0, 30),
-	MSTPCR("oc0", "cpu_clk", 0, 29),
-	MSTPCR("rsmem0", "sh_clk", 0, 28),
-	MSTPCR("xymem0", "cpu_clk", 0, 26),
-	MSTPCR("intc30", "peripheral_clk", 0, 23),
-	MSTPCR("intc0", "peripheral_clk", 0, 22),
-	MSTPCR("dmac0", "bus_clk", 0, 21),
-	MSTPCR("sh0", "sh_clk", 0, 20),
-	MSTPCR("hudi0", "peripheral_clk", 0, 19),
-	MSTPCR("ubc0", "cpu_clk", 0, 17),
-	MSTPCR("tmu0", "peripheral_clk", 0, 15),
-	MSTPCR("cmt0", "r_clk", 0, 14),
-	MSTPCR("rwdt0", "r_clk", 0, 13),
-	MSTPCR("flctl0", "peripheral_clk", 0, 10),
-	MSTPCR("scif0", "peripheral_clk", 0, 7),
-	MSTPCR("scif1", "bus_clk", 0, 6),
-	MSTPCR("scif2", "bus_clk", 0, 5),
-	MSTPCR("msiof0", "peripheral_clk", 0, 2),
-	MSTPCR("sbr0", "peripheral_clk", 0, 1),
-	MSTPCR("i2c0", "peripheral_clk", 1, 9),
-	MSTPCR("icb0", "bus_clk", 2, 27),
-	MSTPCR("meram0", "sh_clk", 2, 26),
-	MSTPCR("dacc0", "peripheral_clk", 2, 24),
-	MSTPCR("dacy0", "peripheral_clk", 2, 23),
-	MSTPCR("tsif0", "bus_clk", 2, 22),
-	MSTPCR("sdhi0", "bus_clk", 2, 18),
-	MSTPCR("mmcif0", "bus_clk", 2, 17),
-	MSTPCR("usb0", "bus_clk", 2, 11),
-	MSTPCR("siu0", "bus_clk", 2, 8),
-	MSTPCR("veu1", "bus_clk", 2, 7),
-	MSTPCR("vou0", "bus_clk", 2, 5),
-	MSTPCR("beu0", "bus_clk", 2, 4),
-	MSTPCR("ceu0", "bus_clk", 2, 3),
-	MSTPCR("veu0", "bus_clk", 2, 2),
-	MSTPCR("vpu0", "bus_clk", 2, 1),
-	MSTPCR("lcdc0", "bus_clk", 2, 0),
-#endif
-};
+static struct clk mstp_clks[] = {
+	MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+	MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
+	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
+	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
+	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
+	MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
+	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
+	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
+	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
 
-static struct clk *sh7722_clocks[] = {
-	&sh7722_umem_clock,
-	&sh7722_sh_clock,
-	&sh7722_peripheral_clock,
-	&sh7722_sdram_clock,
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
-	&sh7722_siu_a_clock,
-	&sh7722_siu_b_clock,
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-	&sh7722_irda_clock,
-#endif
-#endif
-	&sh7722_video_clock,
-};
+	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
+	MSTP("rtc0", &r_clk, MSTPCR1, 8, 0),
 
-/*
- * init in order: master, module, bus, cpu
- */
-struct clk_ops *onchip_ops[] = {
-	&sh7722_master_clk_ops,
-	&sh7722_module_clk_ops,
-	&sh7722_frqcr_clk_ops,
-	&sh7722_frqcr_clk_ops,
+	MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
+	MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
+	MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
+	MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
+	MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
+	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
+	MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
+	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
+	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
+	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
+	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
+	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
 };
 
-void __init
-arch_init_clk_ops(struct clk_ops **ops, int type)
-{
-	BUG_ON(type < 0 || type > ARRAY_SIZE(onchip_ops));
-	*ops = onchip_ops[type];
-}
-
 int __init arch_clk_init(void)
 {
-	struct clk *clk;
-	int i;
+	int k, ret = 0;
 
-	clk = clk_get(NULL, "master_clk");
-	for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) {
-		pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name);
-		sh7722_clocks[i]->parent = clk;
-		clk_register(sh7722_clocks[i]);
-	}
-	clk_put(clk);
+	/* autodetect extal or dll configuration */
+	if (__raw_readl(PLLCR) & 0x1000)
+		pll_clk.parent = &dll_clk;
+	else
+		pll_clk.parent = &extal_clk;
 
-	clk_register(&sh7722_r_clock);
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
 
-	for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr_clocks); i++) {
-		pr_debug( "Registering mstpcr clock '%s'\n",
-			  sh7722_mstpcr_clocks[i].name);
-		clk = clk_get(NULL, (void *) sh7722_mstpcr_clocks[i].ops);
-		sh7722_mstpcr_clocks[i].parent = clk;
-		sh7722_mstpcr_clocks[i].ops = &sh7722_mstpcr_clk_ops;
-		clk_register(&sh7722_mstpcr_clocks[i]);
-		clk_put(clk);
-	}
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 
-	clk_recalc_rate(&sh7722_r_clock); /* make sure rate gets propagated */
+	if (!ret)
+		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
 
-	return 0;
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+
+	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7723.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7723.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7723.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,222 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+ *
+ * SH7723 clock framework support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+
+/* SH7723 registers */
+#define FRQCR		0xa4150000
+#define VCLKCR		0xa4150004
+#define SCLKACR		0xa4150008
+#define SCLKBCR		0xa415000c
+#define IRDACLKCR	0xa4150018
+#define PLLCR		0xa4150024
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+#define DLLFRQ		0xa4150050
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+	.name           = "rclk",
+	.id             = -1,
+	.rate           = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
+};
+
+/* The dll multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
+{
+	unsigned long mult;
+
+	if (__raw_readl(PLLCR) & 0x1000)
+		mult = __raw_readl(DLLFRQ);
+	else
+		mult = 0;
+
+	return clk->parent->rate * mult;
+}
+
+static struct clk_ops dll_clk_ops = {
+	.recalc		= dll_recalc,
+};
+
+static struct clk dll_clk = {
+	.name           = "dll_clk",
+	.id             = -1,
+	.ops		= &dll_clk_ops,
+	.parent		= &r_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+	unsigned long mult = 1;
+	unsigned long div = 1;
+
+	if (__raw_readl(PLLCR) & 0x4000)
+		mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+	else
+		div = 2;
+
+	return (clk->parent->rate * mult) / div;
+}
+
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+};
+
+static struct clk pll_clk = {
+	.name		= "pll_clk",
+	.id		= -1,
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+	&r_clk,
+	&extal_clk,
+	&dll_clk,
+	&pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+static struct clk_div_mult_table div4_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+	.multipliers = multipliers,
+	.nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
+       DIV4_SIUA, DIV4_SIUB, DIV4_IRDA, DIV4_NR };
+
+#define DIV4(_str, _reg, _bit, _mask, _flags) \
+  SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT),
+	[DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT),
+	[DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT),
+	[DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT),
+	[DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x0dbf, 0),
+	[DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0),
+	[DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0),
+	[DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x0dbf, 0),
+};
+
+struct clk div6_clks[] = {
+	SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
+};
+
+#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
+  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+
+static struct clk mstp_clks[] = {
+	/* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
+	MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
+	MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
+	MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
+	MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0),
+	MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
+	MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
+	MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0),
+	MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
+	MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
+	MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
+	MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
+	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
+	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
+	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
+	MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
+	MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0),
+	MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
+	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
+	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
+	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
+	MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
+	MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
+	MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
+	MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
+	MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
+	MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0),
+
+	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
+	MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0),
+
+	MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0),
+	MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0),
+	MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
+	MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
+	MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
+	MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
+	MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
+	MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
+	MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0),
+	MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0),
+	MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1),
+	MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0),
+	MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
+	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
+	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
+	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
+	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
+	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
+	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+};
+
+int __init arch_clk_init(void)
+{
+	int k, ret = 0;
+
+	/* autodetect extal or dll configuration */
+	if (__raw_readl(PLLCR) & 0x1000)
+		pll_clk.parent = &dll_clk;
+	else
+		pll_clk.parent = &extal_clk;
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
+
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7724.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,242 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+ *
+ * SH7724 clock framework support
+ *
+ * Copyright (C) 2009 Magnus Damm
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+
+/* SH7724 registers */
+#define FRQCRA		0xa4150000
+#define FRQCRB		0xa4150004
+#define VCLKCR		0xa4150048
+#define FCLKACR		0xa4150008
+#define FCLKBCR		0xa415000c
+#define IRDACLKCR	0xa4150018
+#define PLLCR		0xa4150024
+#define MSTPCR0		0xa4150030
+#define MSTPCR1		0xa4150034
+#define MSTPCR2		0xa4150038
+#define SPUCLKCR	0xa415003c
+#define FLLFRQ		0xa4150050
+#define LSTATS		0xa4150060
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+	.name           = "rclk",
+	.id             = -1,
+	.rate           = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
+};
+
+/* The fll multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long fll_recalc(struct clk *clk)
+{
+	unsigned long mult = 0;
+	unsigned long div = 1;
+
+	if (__raw_readl(PLLCR) & 0x1000)
+		mult = __raw_readl(FLLFRQ) & 0x3ff;
+
+	if (__raw_readl(FLLFRQ) & 0x4000)
+		div = 2;
+
+	return (clk->parent->rate * mult) / div;
+}
+
+static struct clk_ops fll_clk_ops = {
+	.recalc		= fll_recalc,
+};
+
+static struct clk fll_clk = {
+	.name           = "fll_clk",
+	.id             = -1,
+	.ops		= &fll_clk_ops,
+	.parent		= &r_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+	unsigned long mult = 1;
+
+	if (__raw_readl(PLLCR) & 0x4000)
+		mult = (((__raw_readl(FRQCRA) >> 24) & 0x3f) + 1) * 2;
+
+	return clk->parent->rate * mult;
+}
+
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+};
+
+static struct clk pll_clk = {
+	.name		= "pll_clk",
+	.id		= -1,
+	.ops		= &pll_clk_ops,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+/* A fixed divide-by-3 block use by the div6 clocks */
+static unsigned long div3_recalc(struct clk *clk)
+{
+	return clk->parent->rate / 3;
+}
+
+static struct clk_ops div3_clk_ops = {
+	.recalc		= div3_recalc,
+};
+
+static struct clk div3_clk = {
+	.name		= "div3_clk",
+	.id		= -1,
+	.ops		= &div3_clk_ops,
+	.parent		= &pll_clk,
+};
+
+struct clk *main_clks[] = {
+	&r_clk,
+	&extal_clk,
+	&fll_clk,
+	&pll_clk,
+	&div3_clk,
+};
+
+static int divisors[] = { 2, 0, 4, 6, 8, 12, 16, 0, 24, 32, 36, 48, 0, 72 };
+
+static struct clk_div_mult_table div4_table = {
+	.divisors = divisors,
+	.nr_divisors = ARRAY_SIZE(divisors),
+};
+
+enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR };
+
+#define DIV4(_str, _reg, _bit, _mask, _flags) \
+  SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I] = DIV4("cpu_clk", FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT),
+	[DIV4_SH] = DIV4("shyway_clk", FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4("bus_clk", FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT),
+	[DIV4_P] = DIV4("peripheral_clk", FRQCRA, 0, 0x2f7c, 0),
+	[DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, 0),
+};
+
+struct clk div6_clks[] = {
+	SH_CLK_DIV6("video_clk", &div3_clk, VCLKCR, 0),
+	SH_CLK_DIV6("fsia_clk", &div3_clk, FCLKACR, 0),
+	SH_CLK_DIV6("fsib_clk", &div3_clk, FCLKBCR, 0),
+	SH_CLK_DIV6("irda_clk", &div3_clk, IRDACLKCR, 0),
+	SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0),
+};
+
+#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
+  SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
+
+static struct clk mstp_clks[] = {
+	MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
+	MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
+	MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
+	MSTP("rs0", &div4_clks[DIV4_B], MSTPCR0, 28, 1, 1, 0),
+	MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
+	MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 26, 1, 1, 0),
+	MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
+	MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 1, 1, 0),
+	MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
+	MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
+	MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
+	MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
+	MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
+	MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
+	MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
+	MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
+	MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
+	MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
+	MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
+	MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
+	MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
+	MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
+	MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
+	MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
+	MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
+
+	MSTP("keysc0", &r_clk, MSTPCR1, 12, 0, 0, 0),
+	MSTP("rtc0", &r_clk, MSTPCR1, 11, 0, 0, 0),
+	MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
+	MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0, 1, 0),
+
+	MSTP("mmc0", &div4_clks[DIV4_B], MSTPCR2, 29, 0, 1, 0),
+	MSTP("eth0", &div4_clks[DIV4_B], MSTPCR2, 28, 0, 1, 0),
+	MSTP("atapi0", &div4_clks[DIV4_B], MSTPCR2, 26, 0, 1, 0),
+	MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
+	MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
+	MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
+	MSTP("usb1", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
+	MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 20, 0, 1, 1),
+	MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 19, 0, 1, 1),
+	MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
+	MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
+	MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 15, 1, 1, 1),
+	MSTP("ceu1", &div4_clks[DIV4_B], MSTPCR2, 13, 0, 1, 1),
+	MSTP("beu1", &div4_clks[DIV4_B], MSTPCR2, 12, 0, 1, 1),
+	MSTP("2ddmac0", &div4_clks[DIV4_SH], MSTPCR2, 10, 0, 1, 1),
+	MSTP("spu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0, 1, 0),
+	MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
+	MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
+	MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
+	MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
+	MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
+	MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
+	MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
+};
+
+int __init arch_clk_init(void)
+{
+	int k, ret = 0;
+
+	/* autodetect extal or fll configuration */
+	if (__raw_readl(PLLCR) & 0x1000)
+		pll_clk.parent = &fll_clk;
+	else
+		pll_clk.parent = &extal_clk;
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
+
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
+
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7763.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7763.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7763.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,33 +29,28 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 4) & 0x07);
-	clk->rate = clk->parent->rate / p0fc_divisors[idx];
+	return clk->parent->rate / p0fc_divisors[idx];
 }
 
 static struct clk_ops sh7763_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 16) & 0x07);
-	clk->rate = clk->parent->rate / bfc_divisors[idx];
+	return clk->parent->rate / bfc_divisors[idx];
 }
 
 static struct clk_ops sh7763_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
-{
-	clk->rate = clk->parent->rate;
-}
-
 static struct clk_ops sh7763_cpu_clk_ops = {
-	.recalc		= cpu_clk_recalc,
+	.recalc		= followparent_recalc,
 };
 
 static struct clk_ops *sh7763_clk_ops[] = {
@@ -71,10 +66,10 @@
 		*ops = sh7763_clk_ops[idx];
 }
 
-static void shyway_clk_recalc(struct clk *clk)
+static unsigned long shyway_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 20) & 0x07);
-	clk->rate = clk->parent->rate / cfc_divisors[idx];
+	return clk->parent->rate / cfc_divisors[idx];
 }
 
 static struct clk_ops sh7763_shyway_clk_ops = {
@@ -83,7 +78,7 @@
 
 static struct clk sh7763_shyway_clk = {
 	.name		= "shyway_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &sh7763_shyway_clk_ops,
 };
 
@@ -95,31 +90,22 @@
 	&sh7763_shyway_clk,
 };
 
-static int __init sh7763_clk_init(void)
+int __init arch_clk_init(void)
 {
-	struct clk *clk = clk_get(NULL, "master_clk");
-	int i;
+	struct clk *clk;
+	int i, ret = 0;
+
+	cpg_clk_init();
 
+	clk = clk_get(NULL, "master_clk");
 	for (i = 0; i < ARRAY_SIZE(sh7763_onchip_clocks); i++) {
 		struct clk *clkp = sh7763_onchip_clocks[i];
 
 		clkp->parent = clk;
-		clk_register(clkp);
-		clk_enable(clkp);
+		ret |= clk_register(clkp);
 	}
 
-	/*
-	 * Now that we have the rest of the clocks registered, we need to
-	 * force the parent clock to propagate so that these clocks will
-	 * automatically figure out their rate. We cheat by handing the
-	 * parent clock its current rate and forcing child propagation.
-	 */
-	clk_set_rate(clk, clk_get_rate(clk));
-
 	clk_put(clk);
 
-	return 0;
+	return ret;
 }
-
-arch_initcall(sh7763_clk_init);
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7770.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7770.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7770.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,30 +28,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7770_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inl(FRQCR) & 0x000f);
-	clk->rate = clk->parent->rate / bfc_divisors[idx];
+	return clk->parent->rate / bfc_divisors[idx];
 }
 
 static struct clk_ops sh7770_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f);
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7770_cpu_clk_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7780.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7780.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,30 +29,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inl(FRQCR) & 0x0003);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7780_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007);
-	clk->rate = clk->parent->rate / bfc_divisors[idx];
+	return clk->parent->rate / bfc_divisors[idx];
 }
 
 static struct clk_ops sh7780_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001);
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7780_cpu_clk_ops = {
@@ -72,10 +72,10 @@
 		*ops = sh7780_clk_ops[idx];
 }
 
-static void shyway_clk_recalc(struct clk *clk)
+static unsigned long shyway_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007);
-	clk->rate = clk->parent->rate / cfc_divisors[idx];
+	return clk->parent->rate / cfc_divisors[idx];
 }
 
 static struct clk_ops sh7780_shyway_clk_ops = {
@@ -84,7 +84,7 @@
 
 static struct clk sh7780_shyway_clk = {
 	.name		= "shyway_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &sh7780_shyway_clk_ops,
 };
 
@@ -96,31 +96,22 @@
 	&sh7780_shyway_clk,
 };
 
-static int __init sh7780_clk_init(void)
+int __init arch_clk_init(void)
 {
-	struct clk *clk = clk_get(NULL, "master_clk");
-	int i;
+	struct clk *clk;
+	int i, ret = 0;
+
+	cpg_clk_init();
 
+	clk = clk_get(NULL, "master_clk");
 	for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {
 		struct clk *clkp = sh7780_onchip_clocks[i];
 
 		clkp->parent = clk;
-		clk_register(clkp);
-		clk_enable(clkp);
+		ret |= clk_register(clkp);
 	}
 
-	/*
-	 * Now that we have the rest of the clocks registered, we need to
-	 * force the parent clock to propagate so that these clocks will
-	 * automatically figure out their rate. We cheat by handing the
-	 * parent clock its current rate and forcing child propagation.
-	 */
-	clk_set_rate(clk, clk_get_rate(clk));
-
 	clk_put(clk);
 
-	return 0;
+	return ret;
 }
-
-arch_initcall(sh7780_clk_init);
-
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7785.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7785.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7785.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * SH7785 support for the clock framework
  *
- *  Copyright (C) 2007  Paul Mundt
+ *  Copyright (C) 2007 - 2009  Paul Mundt
  *
  * 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
@@ -11,152 +11,116 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/cpufreq.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
-#include <asm/io.h>
-
-static int ifc_divisors[] = { 1, 2, 4, 6 };
-static int ufc_divisors[] = { 1, 1, 4, 6 };
-static int sfc_divisors[] = { 1, 1, 4, 6 };
-static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18,
-			     24, 32, 36, 48, 1, 1, 1, 1 };
-static int mfc_divisors[] = { 1, 1, 4, 6 };
-static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18,
-			      24, 32, 36, 48, 1, 1, 1, 1 };
-
-static void master_clk_init(struct clk *clk)
-{
-	clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
-}
+#include <cpu/sh7785.h>
 
-static struct clk_ops sh7785_master_clk_ops = {
-	.init		= master_clk_init,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long pll_recalc(struct clk *clk)
 {
-	int idx = (ctrl_inl(FRQMR1) & 0x000f);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
-}
+	int multiplier;
 
-static struct clk_ops sh7785_module_clk_ops = {
-	.recalc		= module_clk_recalc,
-};
+	multiplier = test_mode_pin(MODE_PIN4) ? 36 : 72;
 
-static void bus_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
-	clk->rate = clk->parent->rate / bfc_divisors[idx];
+	return clk->parent->rate * multiplier;
 }
 
-static struct clk_ops sh7785_bus_clk_ops = {
-	.recalc		= bus_clk_recalc,
+static struct clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
-}
-
-static struct clk_ops sh7785_cpu_clk_ops = {
-	.recalc		= cpu_clk_recalc,
+static struct clk pll_clk = {
+	.name		= "pll_clk",
+	.id		= -1,
+	.ops		= &pll_clk_ops,
+	.parent		= &extal_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
 };
 
-static struct clk_ops *sh7785_clk_ops[] = {
-	&sh7785_master_clk_ops,
-	&sh7785_module_clk_ops,
-	&sh7785_bus_clk_ops,
-	&sh7785_cpu_clk_ops,
+static struct clk *clks[] = {
+	&extal_clk,
+	&pll_clk,
 };
 
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-	if (idx < ARRAY_SIZE(sh7785_clk_ops))
-		*ops = sh7785_clk_ops[idx];
-}
-
-static void shyway_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
-	clk->rate = clk->parent->rate / sfc_divisors[idx];
-}
-
-static struct clk_ops sh7785_shyway_clk_ops = {
-	.recalc		= shyway_clk_recalc,
-};
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+			       24, 32, 36, 48 };
 
-static struct clk sh7785_shyway_clk = {
-	.name		= "shyway_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
-	.ops		= &sh7785_shyway_clk_ops,
+static struct clk_div_mult_table div4_table = {
+	.divisors = div2,
+	.nr_divisors = ARRAY_SIZE(div2),
 };
 
-static void ddr_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
-	clk->rate = clk->parent->rate / mfc_divisors[idx];
-}
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA,
+	DIV4_DU, DIV4_P, DIV4_NR };
 
-static struct clk_ops sh7785_ddr_clk_ops = {
-	.recalc		= ddr_clk_recalc,
-};
+#define DIV4(_str, _bit, _mask, _flags) \
+  SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags)
 
-static struct clk sh7785_ddr_clk = {
-	.name		= "ddr_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
-	.ops		= &sh7785_ddr_clk_ops,
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_P] = DIV4("peripheral_clk", 0, 0x0f80, 0),
+	[DIV4_DU] = DIV4("du_clk", 4, 0x0ff0, 0),
+	[DIV4_GA] = DIV4("ga_clk", 8, 0x0030, 0),
+	[DIV4_DDR] = DIV4("ddr_clk", 12, 0x000c, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4("bus_clk", 16, 0x0fe0, CLK_ENABLE_ON_INIT),
+	[DIV4_SH] = DIV4("shyway_clk", 20, 0x000c, CLK_ENABLE_ON_INIT),
+	[DIV4_U] = DIV4("umem_clk", 24, 0x000c, CLK_ENABLE_ON_INIT),
+	[DIV4_I] = DIV4("cpu_clk", 28, 0x000e, CLK_ENABLE_ON_INIT),
 };
 
-static void ram_clk_recalc(struct clk *clk)
-{
-	int idx = ((ctrl_inl(FRQMR1) >> 24) & 0x0003);
-	clk->rate = clk->parent->rate / ufc_divisors[idx];
-}
-
-static struct clk_ops sh7785_ram_clk_ops = {
-	.recalc		= ram_clk_recalc,
-};
+#define MSTPCR0		0xffc80030
+#define MSTPCR1		0xffc80034
 
-static struct clk sh7785_ram_clk = {
-	.name		= "ram_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
-	.ops		= &sh7785_ram_clk_ops,
-};
+static struct clk mstp_clks[] = {
+	/* MSTPCR0 */
+	SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0),
+	SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0),
+	SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0),
+	SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0),
+	SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0),
+	SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0),
+	SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0),
+	SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0),
+	SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0),
+	SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0),
+	SH_CLK_MSTP32("mmcif_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 13, 0),
+	SH_CLK_MSTP32("flctl_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 12, 0),
+	SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0),
+	SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0),
+	SH_CLK_MSTP32("siof_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 3, 0),
+	SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0),
 
-/*
- * Additional SH7785-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *sh7785_onchip_clocks[] = {
-	&sh7785_shyway_clk,
-	&sh7785_ddr_clk,
-	&sh7785_ram_clk,
+	/* MSTPCR1 */
+	SH_CLK_MSTP32("hudi_fck", -1, NULL, MSTPCR1, 19, 0),
+	SH_CLK_MSTP32("ubc_fck", -1, NULL, MSTPCR1, 17, 0),
+	SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0),
+	SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0),
+	SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 0),
 };
 
-static int __init sh7785_clk_init(void)
+int __init arch_clk_init(void)
 {
-	struct clk *clk = clk_get(NULL, "master_clk");
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(sh7785_onchip_clocks); i++) {
-		struct clk *clkp = sh7785_onchip_clocks[i];
-
-		clkp->parent = clk;
-		clk_register(clkp);
-		clk_enable(clkp);
-	}
+	int i, ret = 0;
 
-	/*
-	 * Now that we have the rest of the clocks registered, we need to
-	 * force the parent clock to propagate so that these clocks will
-	 * automatically figure out their rate. We cheat by handing the
-	 * parent clock its current rate and forcing child propagation.
-	 */
-	clk_set_rate(clk, clk_get_rate(clk));
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		ret |= clk_register(clks[i]);
 
-	clk_put(clk);
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+					   &div4_table);
+	if (!ret)
+		ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
 
-	return 0;
+	return ret;
 }
-arch_initcall(sh7785_clk_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7786.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7786.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7786.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,30 +36,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inl(FRQMR1) & 0x000f);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops sh7786_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
-	clk->rate = clk->parent->rate / bfc_divisors[idx];
+	return clk->parent->rate / bfc_divisors[idx];
 }
 
 static struct clk_ops sh7786_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops sh7786_cpu_clk_ops = {
@@ -79,10 +79,10 @@
 		*ops = sh7786_clk_ops[idx];
 }
 
-static void shyway_clk_recalc(struct clk *clk)
+static unsigned long shyway_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
-	clk->rate = clk->parent->rate / sfc_divisors[idx];
+	return clk->parent->rate / sfc_divisors[idx];
 }
 
 static struct clk_ops sh7786_shyway_clk_ops = {
@@ -91,14 +91,14 @@
 
 static struct clk sh7786_shyway_clk = {
 	.name		= "shyway_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &sh7786_shyway_clk_ops,
 };
 
-static void ddr_clk_recalc(struct clk *clk)
+static unsigned long ddr_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
-	clk->rate = clk->parent->rate / mfc_divisors[idx];
+	return clk->parent->rate / mfc_divisors[idx];
 }
 
 static struct clk_ops sh7786_ddr_clk_ops = {
@@ -107,7 +107,7 @@
 
 static struct clk sh7786_ddr_clk = {
 	.name		= "ddr_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &sh7786_ddr_clk_ops,
 };
 
@@ -120,29 +120,22 @@
 	&sh7786_ddr_clk,
 };
 
-static int __init sh7786_clk_init(void)
+int __init arch_clk_init(void)
 {
-	struct clk *clk = clk_get(NULL, "master_clk");
-	int i;
+	struct clk *clk;
+	int i, ret = 0;
 
+	cpg_clk_init();
+
+	clk = clk_get(NULL, "master_clk");
 	for (i = 0; i < ARRAY_SIZE(sh7786_onchip_clocks); i++) {
 		struct clk *clkp = sh7786_onchip_clocks[i];
 
 		clkp->parent = clk;
-		clk_register(clkp);
-		clk_enable(clkp);
+		ret |= clk_register(clkp);
 	}
 
-	/*
-	 * Now that we have the rest of the clocks registered, we need to
-	 * force the parent clock to propagate so that these clocks will
-	 * automatically figure out their rate. We cheat by handing the
-	 * parent clock its current rate and forcing child propagation.
-	 */
-	clk_set_rate(clk, clk_get_rate(clk));
-
 	clk_put(clk);
 
-	return 0;
+	return ret;
 }
-arch_initcall(sh7786_clk_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-shx3.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-shx3.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/clock-shx3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/clock-shx3.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,30 +40,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
-	clk->rate = clk->parent->rate / pfc_divisors[idx];
+	return clk->parent->rate / pfc_divisors[idx];
 }
 
 static struct clk_ops shx3_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
-	clk->rate = clk->parent->rate / bfc_divisors[idx];
+	return clk->parent->rate / bfc_divisors[idx];
 }
 
 static struct clk_ops shx3_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
-	clk->rate = clk->parent->rate / ifc_divisors[idx];
+	return clk->parent->rate / ifc_divisors[idx];
 }
 
 static struct clk_ops shx3_cpu_clk_ops = {
@@ -83,10 +83,10 @@
 		*ops = shx3_clk_ops[idx];
 }
 
-static void shyway_clk_recalc(struct clk *clk)
+static unsigned long shyway_clk_recalc(struct clk *clk)
 {
 	int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
-	clk->rate = clk->parent->rate / cfc_divisors[idx];
+	return clk->parent->rate / cfc_divisors[idx];
 }
 
 static struct clk_ops shx3_shyway_clk_ops = {
@@ -95,7 +95,7 @@
 
 static struct clk shx3_shyway_clk = {
 	.name		= "shyway_clk",
-	.flags		= CLK_ALWAYS_ENABLED,
+	.flags		= CLK_ENABLE_ON_INIT,
 	.ops		= &shx3_shyway_clk_ops,
 };
 
@@ -107,29 +107,22 @@
 	&shx3_shyway_clk,
 };
 
-static int __init shx3_clk_init(void)
+int __init arch_clk_init(void)
 {
-	struct clk *clk = clk_get(NULL, "master_clk");
-	int i;
+	struct clk *clk;
+	int i, ret = 0;
+
+	cpg_clk_init();
 
+	clk = clk_get(NULL, "master_clk");
 	for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
 		struct clk *clkp = shx3_onchip_clocks[i];
 
 		clkp->parent = clk;
-		clk_register(clkp);
-		clk_enable(clkp);
+		ret |= clk_register(clkp);
 	}
 
-	/*
-	 * Now that we have the rest of the clocks registered, we need to
-	 * force the parent clock to propagate so that these clocks will
-	 * automatically figure out their rate. We cheat by handing the
-	 * parent clock its current rate and forcing child propagation.
-	 */
-	clk_set_rate(clk, clk_get_rate(clk));
-
 	clk_put(clk);
 
-	return 0;
+	return ret;
 }
-arch_initcall(shx3_clk_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/Makefile linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -11,11 +11,12 @@
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7722)	+= setup-sh7722.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7723)	+= setup-sh7723.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7724)	+= setup-sh7724.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7366)	+= setup-sh7366.o
 obj-$(CONFIG_CPU_SUBTYPE_SHX3)		+= setup-shx3.o
 
 # SMP setup
-smp-$(CONFIG_CPU_SUBTYPE_SHX3)		:= smp-shx3.o
+smp-$(CONFIG_CPU_SHX3)			:= smp-shx3.o
 
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SUBTYPE_SH7763)	:= clock-sh7763.o
@@ -23,18 +24,20 @@
 clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7785)	:= clock-sh7785.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7786)	:= clock-sh7786.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7722.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7722.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7366)	:= clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7723)	:= clock-sh7723.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7724)	:= clock-sh7724.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7366)	:= clock-sh7366.o
 clock-$(CONFIG_CPU_SUBTYPE_SHX3)	:= clock-shx3.o
 
 # Pinmux setup
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7722)	:= pinmux-sh7722.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7723)	:= pinmux-sh7723.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7724)	:= pinmux-sh7724.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7785)	:= pinmux-sh7785.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7786)	:= pinmux-sh7786.o
 
-obj-y			+= $(clock-y)
-obj-$(CONFIG_SMP)	+= $(smp-y)
+obj-y				+= $(clock-y)
+obj-$(CONFIG_SMP)		+= $(smp-y)
 obj-$(CONFIG_GENERIC_GPIO)	+= $(pinmux-y)
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2230 @@
+/*
+ * SH7724 Pinmux
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7723 Pinmux
+ *  Copyright (C) 2008  Magnus Damm
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7724.h>
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	PINMUX_DATA_BEGIN,
+	PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+	PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA,
+	PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+	PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA,
+	PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+	PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA,
+	PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+	PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA,
+	PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+	PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA,
+	PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+	PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA,
+			      PTG5_DATA, PTG4_DATA,
+	PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA,
+	PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+	PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
+	PTJ7_DATA, PTJ6_DATA, PTJ5_DATA,
+	PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA,
+	PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+	PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA,
+	PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+	PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA,
+	PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+	PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA,
+	PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+	PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA,
+	PTQ7_DATA, PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+	PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA,
+	PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+	PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA,
+		   PTS6_DATA, PTS5_DATA, PTS4_DATA,
+	PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA,
+	PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
+	PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
+	PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
+	PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
+	PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+	PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA,
+	PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+	PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA,
+	PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+	PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA,
+	PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+	PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA,
+	PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+	PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA,
+	PINMUX_DATA_END,
+
+	PINMUX_INPUT_BEGIN,
+	PTA7_IN, PTA6_IN, PTA5_IN, PTA4_IN,
+	PTA3_IN, PTA2_IN, PTA1_IN, PTA0_IN,
+	PTB7_IN, PTB6_IN, PTB5_IN, PTB4_IN,
+	PTB3_IN, PTB2_IN, PTB1_IN, PTB0_IN,
+	PTC7_IN, PTC6_IN, PTC5_IN, PTC4_IN,
+	PTC3_IN, PTC2_IN, PTC1_IN, PTC0_IN,
+	PTD7_IN, PTD6_IN, PTD5_IN, PTD4_IN,
+	PTD3_IN, PTD2_IN, PTD1_IN, PTD0_IN,
+	PTE7_IN, PTE6_IN, PTE5_IN, PTE4_IN,
+	PTE3_IN, PTE2_IN, PTE1_IN, PTE0_IN,
+	PTF7_IN, PTF6_IN, PTF5_IN, PTF4_IN,
+	PTF3_IN, PTF2_IN, PTF1_IN, PTF0_IN,
+	PTH7_IN, PTH6_IN, PTH5_IN, PTH4_IN,
+	PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN,
+	PTJ3_IN, PTJ2_IN, PTJ1_IN, PTJ0_IN,
+	PTK7_IN, PTK6_IN, PTK5_IN, PTK4_IN,
+	PTK3_IN, PTK2_IN, PTK1_IN, PTK0_IN,
+	PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN,
+	PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN,
+	PTM7_IN, PTM6_IN, PTM5_IN, PTM4_IN,
+	PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN,
+	PTN7_IN, PTN6_IN, PTN5_IN, PTN4_IN,
+	PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN,
+	PTQ7_IN, PTQ6_IN, PTQ5_IN, PTQ4_IN,
+	PTQ3_IN, PTQ2_IN, PTQ1_IN, PTQ0_IN,
+	PTR7_IN, PTR6_IN, PTR5_IN, PTR4_IN,
+	PTR3_IN, PTR2_IN, PTR1_IN, PTR0_IN,
+		 PTS6_IN, PTS5_IN, PTS4_IN,
+	PTS3_IN, PTS2_IN, PTS1_IN, PTS0_IN,
+	PTT7_IN, PTT6_IN, PTT5_IN, PTT4_IN,
+	PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN,
+	PTU7_IN, PTU6_IN, PTU5_IN, PTU4_IN,
+	PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
+	PTV7_IN, PTV6_IN, PTV5_IN, PTV4_IN,
+	PTV3_IN, PTV2_IN, PTV1_IN, PTV0_IN,
+	PTW7_IN, PTW6_IN, PTW5_IN, PTW4_IN,
+	PTW3_IN, PTW2_IN, PTW1_IN, PTW0_IN,
+	PTX7_IN, PTX6_IN, PTX5_IN, PTX4_IN,
+	PTX3_IN, PTX2_IN, PTX1_IN, PTX0_IN,
+	PTY7_IN, PTY6_IN, PTY5_IN, PTY4_IN,
+	PTY3_IN, PTY2_IN, PTY1_IN, PTY0_IN,
+	PTZ7_IN, PTZ6_IN, PTZ5_IN, PTZ4_IN,
+	PTZ3_IN, PTZ2_IN, PTZ1_IN, PTZ0_IN,
+	PINMUX_INPUT_END,
+
+	PINMUX_INPUT_PULLUP_BEGIN,
+	PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU,
+	PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
+	PTB7_IN_PU, PTB6_IN_PU, PTB5_IN_PU, PTB4_IN_PU,
+	PTB3_IN_PU, PTB2_IN_PU, PTB1_IN_PU, PTB0_IN_PU,
+	PTC7_IN_PU, PTC6_IN_PU, PTC5_IN_PU, PTC4_IN_PU,
+	PTC3_IN_PU, PTC2_IN_PU, PTC1_IN_PU, PTC0_IN_PU,
+	PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
+	PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
+	PTE7_IN_PU, PTE6_IN_PU, PTE5_IN_PU, PTE4_IN_PU,
+	PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
+	PTF7_IN_PU, PTF6_IN_PU, PTF5_IN_PU, PTF4_IN_PU,
+	PTF3_IN_PU, PTF2_IN_PU, PTF1_IN_PU, PTF0_IN_PU,
+	PTH7_IN_PU, PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
+	PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
+	PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
+	PTK7_IN_PU, PTK6_IN_PU, PTK5_IN_PU, PTK4_IN_PU,
+	PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
+	PTL7_IN_PU, PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU,
+	PTL3_IN_PU, PTL2_IN_PU, PTL1_IN_PU, PTL0_IN_PU,
+	PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
+	PTM3_IN_PU, PTM2_IN_PU, PTM1_IN_PU, PTM0_IN_PU,
+	PTN7_IN_PU, PTN6_IN_PU, PTN5_IN_PU, PTN4_IN_PU,
+	PTN3_IN_PU, PTN2_IN_PU, PTN1_IN_PU, PTN0_IN_PU,
+	PTQ7_IN_PU, PTQ6_IN_PU, PTQ5_IN_PU, PTQ4_IN_PU,
+	PTQ3_IN_PU, PTQ2_IN_PU, PTQ1_IN_PU, PTQ0_IN_PU,
+	PTR7_IN_PU, PTR6_IN_PU, PTR5_IN_PU, PTR4_IN_PU,
+	PTR3_IN_PU, PTR2_IN_PU, PTR1_IN_PU, PTR0_IN_PU,
+		    PTS6_IN_PU, PTS5_IN_PU, PTS4_IN_PU,
+	PTS3_IN_PU, PTS2_IN_PU, PTS1_IN_PU, PTS0_IN_PU,
+	PTT7_IN_PU, PTT6_IN_PU, PTT5_IN_PU, PTT4_IN_PU,
+	PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
+	PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU,
+	PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
+	PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU,
+	PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
+	PTW7_IN_PU, PTW6_IN_PU, PTW5_IN_PU, PTW4_IN_PU,
+	PTW3_IN_PU, PTW2_IN_PU, PTW1_IN_PU, PTW0_IN_PU,
+	PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU,
+	PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU,
+	PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU,
+	PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU,
+	PTZ7_IN_PU, PTZ6_IN_PU, PTZ5_IN_PU, PTZ4_IN_PU,
+	PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU, PTZ0_IN_PU,
+	PINMUX_INPUT_PULLUP_END,
+
+	PINMUX_OUTPUT_BEGIN,
+	PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
+	PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
+	PTB7_OUT, PTB6_OUT, PTB5_OUT, PTB4_OUT,
+	PTB3_OUT, PTB2_OUT, PTB1_OUT, PTB0_OUT,
+	PTC7_OUT, PTC6_OUT, PTC5_OUT, PTC4_OUT,
+	PTC3_OUT, PTC2_OUT, PTC1_OUT, PTC0_OUT,
+	PTD7_OUT, PTD6_OUT, PTD5_OUT, PTD4_OUT,
+	PTD3_OUT, PTD2_OUT, PTD1_OUT, PTD0_OUT,
+	PTE7_OUT, PTE6_OUT, PTE5_OUT, PTE4_OUT,
+	PTE3_OUT, PTE2_OUT, PTE1_OUT, PTE0_OUT,
+	PTF7_OUT, PTF6_OUT, PTF5_OUT, PTF4_OUT,
+	PTF3_OUT, PTF2_OUT, PTF1_OUT, PTF0_OUT,
+			    PTG5_OUT, PTG4_OUT,
+	PTG3_OUT, PTG2_OUT, PTG1_OUT, PTG0_OUT,
+	PTH7_OUT, PTH6_OUT, PTH5_OUT, PTH4_OUT,
+	PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
+	PTJ7_OUT, PTJ6_OUT, PTJ5_OUT,
+	PTJ3_OUT, PTJ2_OUT, PTJ1_OUT, PTJ0_OUT,
+	PTK7_OUT, PTK6_OUT, PTK5_OUT, PTK4_OUT,
+	PTK3_OUT, PTK2_OUT, PTK1_OUT, PTK0_OUT,
+	PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT,
+	PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT,
+	PTM7_OUT, PTM6_OUT, PTM5_OUT, PTM4_OUT,
+	PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT,
+	PTN7_OUT, PTN6_OUT, PTN5_OUT, PTN4_OUT,
+	PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT,
+	PTQ7_OUT, PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
+	PTQ3_OUT, PTQ2_OUT, PTQ1_OUT, PTQ0_OUT,
+	PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT,
+			    PTR1_OUT, PTR0_OUT,
+		  PTS6_OUT, PTS5_OUT, PTS4_OUT,
+	PTS3_OUT, PTS2_OUT, PTS1_OUT, PTS0_OUT,
+	PTT7_OUT, PTT6_OUT, PTT5_OUT, PTT4_OUT,
+	PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT,
+	PTU7_OUT, PTU6_OUT, PTU5_OUT, PTU4_OUT,
+	PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT,
+	PTV7_OUT, PTV6_OUT, PTV5_OUT, PTV4_OUT,
+	PTV3_OUT, PTV2_OUT, PTV1_OUT, PTV0_OUT,
+	PTW7_OUT, PTW6_OUT, PTW5_OUT, PTW4_OUT,
+	PTW3_OUT, PTW2_OUT, PTW1_OUT, PTW0_OUT,
+	PTX7_OUT, PTX6_OUT, PTX5_OUT, PTX4_OUT,
+	PTX3_OUT, PTX2_OUT, PTX1_OUT, PTX0_OUT,
+	PTY7_OUT, PTY6_OUT, PTY5_OUT, PTY4_OUT,
+	PTY3_OUT, PTY2_OUT, PTY1_OUT, PTY0_OUT,
+	PTZ7_OUT, PTZ6_OUT, PTZ5_OUT, PTZ4_OUT,
+	PTZ3_OUT, PTZ2_OUT, PTZ1_OUT, PTZ0_OUT,
+	PINMUX_OUTPUT_END,
+
+	PINMUX_FUNCTION_BEGIN,
+	PTA7_FN, PTA6_FN, PTA5_FN, PTA4_FN,
+	PTA3_FN, PTA2_FN, PTA1_FN, PTA0_FN,
+	PTB7_FN, PTB6_FN, PTB5_FN, PTB4_FN,
+	PTB3_FN, PTB2_FN, PTB1_FN, PTB0_FN,
+	PTC7_FN, PTC6_FN, PTC5_FN, PTC4_FN,
+	PTC3_FN, PTC2_FN, PTC1_FN, PTC0_FN,
+	PTD7_FN, PTD6_FN, PTD5_FN, PTD4_FN,
+	PTD3_FN, PTD2_FN, PTD1_FN, PTD0_FN,
+	PTE7_FN, PTE6_FN, PTE5_FN, PTE4_FN,
+	PTE3_FN, PTE2_FN, PTE1_FN, PTE0_FN,
+	PTF7_FN, PTF6_FN, PTF5_FN, PTF4_FN,
+	PTF3_FN, PTF2_FN, PTF1_FN, PTF0_FN,
+			  PTG5_FN, PTG4_FN,
+	PTG3_FN, PTG2_FN, PTG1_FN, PTG0_FN,
+	PTH7_FN, PTH6_FN, PTH5_FN, PTH4_FN,
+	PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN,
+	PTJ7_FN, PTJ6_FN, PTJ5_FN,
+	PTJ3_FN, PTJ2_FN, PTJ1_FN, PTJ0_FN,
+	PTK7_FN, PTK6_FN, PTK5_FN, PTK4_FN,
+	PTK3_FN, PTK2_FN, PTK1_FN, PTK0_FN,
+	PTL7_FN, PTL6_FN, PTL5_FN, PTL4_FN,
+	PTL3_FN, PTL2_FN, PTL1_FN, PTL0_FN,
+	PTM7_FN, PTM6_FN, PTM5_FN, PTM4_FN,
+	PTM3_FN, PTM2_FN, PTM1_FN, PTM0_FN,
+	PTN7_FN, PTN6_FN, PTN5_FN, PTN4_FN,
+	PTN3_FN, PTN2_FN, PTN1_FN, PTN0_FN,
+	PTQ7_FN, PTQ6_FN, PTQ5_FN, PTQ4_FN,
+	PTQ3_FN, PTQ2_FN, PTQ1_FN, PTQ0_FN,
+	PTR7_FN, PTR6_FN, PTR5_FN, PTR4_FN,
+	PTR3_FN, PTR2_FN, PTR1_FN, PTR0_FN,
+		 PTS6_FN, PTS5_FN, PTS4_FN,
+	PTS3_FN, PTS2_FN, PTS1_FN, PTS0_FN,
+	PTT7_FN, PTT6_FN, PTT5_FN, PTT4_FN,
+	PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN,
+	PTU7_FN, PTU6_FN, PTU5_FN, PTU4_FN,
+	PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN,
+	PTV7_FN, PTV6_FN, PTV5_FN, PTV4_FN,
+	PTV3_FN, PTV2_FN, PTV1_FN, PTV0_FN,
+	PTW7_FN, PTW6_FN, PTW5_FN, PTW4_FN,
+	PTW3_FN, PTW2_FN, PTW1_FN, PTW0_FN,
+	PTX7_FN, PTX6_FN, PTX5_FN, PTX4_FN,
+	PTX3_FN, PTX2_FN, PTX1_FN, PTX0_FN,
+	PTY7_FN, PTY6_FN, PTY5_FN, PTY4_FN,
+	PTY3_FN, PTY2_FN, PTY1_FN, PTY0_FN,
+	PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN,
+	PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN,
+
+
+	PSA15_0, PSA15_1,
+	PSA14_0, PSA14_1,
+	PSA13_0, PSA13_1,
+	PSA12_0, PSA12_1,
+	PSA10_0, PSA10_1,
+	PSA9_0,  PSA9_1,
+	PSA8_0,  PSA8_1,
+	PSA7_0,  PSA7_1,
+	PSA6_0,  PSA6_1,
+	PSA5_0,  PSA5_1,
+	PSA3_0,  PSA3_1,
+	PSA2_0,  PSA2_1,
+	PSA1_0,  PSA1_1,
+	PSA0_0,  PSA0_1,
+
+	PSB14_0, PSB14_1,
+	PSB13_0, PSB13_1,
+	PSB12_0, PSB12_1,
+	PSB11_0, PSB11_1,
+	PSB10_0, PSB10_1,
+	PSB9_0,  PSB9_1,
+	PSB8_0,  PSB8_1,
+	PSB7_0,  PSB7_1,
+	PSB6_0,  PSB6_1,
+	PSB5_0,  PSB5_1,
+	PSB4_0,  PSB4_1,
+	PSB3_0,  PSB3_1,
+	PSB2_0,  PSB2_1,
+	PSB1_0,  PSB1_1,
+	PSB0_0,  PSB0_1,
+
+	PSC15_0, PSC15_1,
+	PSC14_0, PSC14_1,
+	PSC13_0, PSC13_1,
+	PSC12_0, PSC12_1,
+	PSC11_0, PSC11_1,
+	PSC10_0, PSC10_1,
+	PSC9_0,  PSC9_1,
+	PSC8_0,  PSC8_1,
+	PSC7_0,  PSC7_1,
+	PSC6_0,  PSC6_1,
+	PSC5_0,  PSC5_1,
+	PSC4_0,  PSC4_1,
+	PSC2_0,  PSC2_1,
+	PSC1_0,  PSC1_1,
+	PSC0_0,  PSC0_1,
+
+	PSD15_0, PSD15_1,
+	PSD14_0, PSD14_1,
+	PSD13_0, PSD13_1,
+	PSD12_0, PSD12_1,
+	PSD11_0, PSD11_1,
+	PSD10_0, PSD10_1,
+	PSD9_0,  PSD9_1,
+	PSD8_0,  PSD8_1,
+	PSD7_0,  PSD7_1,
+	PSD6_0,  PSD6_1,
+	PSD5_0,  PSD5_1,
+	PSD4_0,  PSD4_1,
+	PSD3_0,  PSD3_1,
+	PSD2_0,  PSD2_1,
+	PSD1_0,  PSD1_1,
+	PSD0_0,  PSD0_1,
+
+	PSE15_0, PSE15_1,
+	PSE14_0, PSE14_1,
+	PSE13_0, PSE13_1,
+	PSE12_0, PSE12_1,
+	PSE11_0, PSE11_1,
+	PSE10_0, PSE10_1,
+	PSE9_0,  PSE9_1,
+	PSE8_0,  PSE8_1,
+	PSE7_0,  PSE7_1,
+	PSE6_0,  PSE6_1,
+	PSE5_0,  PSE5_1,
+	PSE4_0,  PSE4_1,
+	PSE3_0,  PSE3_1,
+	PSE2_0,  PSE2_1,
+	PSE1_0,  PSE1_1,
+	PSE0_0,  PSE0_1,
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+	/*PTA*/
+	D23_MARK,	KEYOUT2_MARK,		IDED15_MARK,
+	D22_MARK,	KEYOUT1_MARK,		IDED14_MARK,
+	D21_MARK,	KEYOUT0_MARK,		IDED13_MARK,
+	D20_MARK,	KEYIN4_MARK,		IDED12_MARK,
+	D19_MARK,	KEYIN3_MARK,		IDED11_MARK,
+	D18_MARK,	KEYIN2_MARK,		IDED10_MARK,
+	D17_MARK,	KEYIN1_MARK,		IDED9_MARK,
+	D16_MARK,	KEYIN0_MARK,		IDED8_MARK,
+
+	/*PTB*/
+	D31_MARK,	TPUTO1_MARK,		IDEA1_MARK,
+	D30_MARK,	TPUTO0_MARK,		IDEA0_MARK,
+	D29_MARK,				IODREQ_MARK,
+	D28_MARK,				IDECS0_MARK,
+	D27_MARK,				IDECS1_MARK,
+	D26_MARK,	KEYOUT5_IN5_MARK,	IDEIORD_MARK,
+	D25_MARK,	KEYOUT4_IN6_MARK,	IDEIOWR_MARK,
+	D24_MARK,	KEYOUT3_MARK,		IDEINT_MARK,
+
+	/*PTC*/
+	LCDD7_MARK,
+	LCDD6_MARK,
+	LCDD5_MARK,
+	LCDD4_MARK,
+	LCDD3_MARK,
+	LCDD2_MARK,
+	LCDD1_MARK,
+	LCDD0_MARK,
+
+	/*PTD*/
+	LCDD15_MARK,
+	LCDD14_MARK,
+	LCDD13_MARK,
+	LCDD12_MARK,
+	LCDD11_MARK,
+	LCDD10_MARK,
+	LCDD9_MARK,
+	LCDD8_MARK,
+
+	/*PTE*/
+	FSIMCKB_MARK,
+	FSIMCKA_MARK,
+	LCDD21_MARK,	SCIF2_L_TXD_MARK,
+	LCDD20_MARK,	SCIF4_SCK_MARK,
+	LCDD19_MARK,	SCIF4_RXD_MARK,
+	LCDD18_MARK,	SCIF4_TXD_MARK,
+	LCDD17_MARK,
+	LCDD16_MARK,
+
+	/*PTF*/
+	LCDVSYN_MARK,
+	LCDDISP_MARK,	LCDRS_MARK,
+	LCDHSYN_MARK,	LCDCS_MARK,
+	LCDDON_MARK,
+	LCDDCK_MARK,	LCDWR_MARK,
+	LCDVEPWC_MARK,	SCIF0_TXD_MARK,
+	LCDD23_MARK,	SCIF2_L_SCK_MARK,
+	LCDD22_MARK,	SCIF2_L_RXD_MARK,
+
+	/*PTG*/
+	AUDCK_MARK,
+	AUDSYNC_MARK,
+	AUDATA3_MARK,
+	AUDATA2_MARK,
+	AUDATA1_MARK,
+	AUDATA0_MARK,
+
+	/*PTH*/
+	VIO0_VD_MARK,
+	VIO0_CLK_MARK,
+	VIO0_D7_MARK,
+	VIO0_D6_MARK,
+	VIO0_D5_MARK,
+	VIO0_D4_MARK,
+	VIO0_D3_MARK,
+	VIO0_D2_MARK,
+
+	/*PTJ*/
+	PDSTATUS_MARK,
+	STATUS2_MARK,
+	STATUS0_MARK,
+	A25_MARK,		BS_MARK,
+	A24_MARK,
+	A23_MARK,
+	A22_MARK,
+
+	/*PTK*/
+	VIO1_D5_MARK,	VIO0_D13_MARK,	IDED5_MARK,
+	VIO1_D4_MARK,	VIO0_D12_MARK,	IDED4_MARK,
+	VIO1_D3_MARK,	VIO0_D11_MARK,	IDED3_MARK,
+	VIO1_D2_MARK,	VIO0_D10_MARK,	IDED2_MARK,
+	VIO1_D1_MARK,	VIO0_D9_MARK,	IDED1_MARK,
+	VIO1_D0_MARK,	VIO0_D8_MARK,	IDED0_MARK,
+	VIO0_FLD_MARK,
+	VIO0_HD_MARK,
+
+	/*PTL*/
+	DV_D5_MARK,	SCIF3_V_SCK_MARK,	RMII_RXD0_MARK,
+	DV_D4_MARK,	SCIF3_V_RXD_MARK,	RMII_RXD1_MARK,
+	DV_D3_MARK,	SCIF3_V_TXD_MARK,	RMII_REF_CLK_MARK,
+	DV_D2_MARK,	SCIF1_SCK_MARK,		RMII_TX_EN_MARK,
+	DV_D1_MARK,	SCIF1_RXD_MARK,		RMII_TXD0_MARK,
+	DV_D0_MARK,	SCIF1_TXD_MARK,		RMII_TXD1_MARK,
+	DV_D15_MARK,
+	DV_D14_MARK,	MSIOF0_MCK_MARK,
+
+	/*PTM*/
+	DV_D13_MARK,	MSIOF0_TSCK_MARK,
+	DV_D12_MARK,	MSIOF0_RXD_MARK,
+	DV_D11_MARK,	MSIOF0_TXD_MARK,
+	DV_D10_MARK,	MSIOF0_TSYNC_MARK,
+	DV_D9_MARK,	MSIOF0_SS1_MARK,	MSIOF0_RSCK_MARK,
+	DV_D8_MARK,	MSIOF0_SS2_MARK,	MSIOF0_RSYNC_MARK,
+	LCDVCPWC_MARK,	SCIF0_RXD_MARK,
+	LCDRD_MARK,	SCIF0_SCK_MARK,
+
+	/*PTN*/
+	VIO0_D1_MARK,
+	VIO0_D0_MARK,
+	DV_CLKI_MARK,
+	DV_CLK_MARK,	SCIF2_V_SCK_MARK,
+	DV_VSYNC_MARK,	SCIF2_V_RXD_MARK,
+	DV_HSYNC_MARK,	SCIF2_V_TXD_MARK,
+	DV_D7_MARK,	SCIF3_V_CTS_MARK,	RMII_RX_ER_MARK,
+	DV_D6_MARK,	SCIF3_V_RTS_MARK,	RMII_CRS_DV_MARK,
+
+	/*PTQ*/
+	D7_MARK,
+	D6_MARK,
+	D5_MARK,
+	D4_MARK,
+	D3_MARK,
+	D2_MARK,
+	D1_MARK,
+	D0_MARK,
+
+	/*PTR*/
+	CS6B_CE1B_MARK,
+	CS6A_CE2B_MARK,
+	CS5B_CE1A_MARK,
+	CS5A_CE2A_MARK,
+	IOIS16_MARK,		LCDLCLK_MARK,
+	WAIT_MARK,
+	WE3_ICIOWR_MARK,	TPUTO3_MARK,	TPUTI3_MARK,
+	WE2_ICIORD_MARK,	TPUTO2_MARK,	IDEA2_MARK,
+
+	/*PTS*/
+	VIO_CKO_MARK,
+	VIO1_FLD_MARK,	TPUTI2_MARK,		IDEIORDY_MARK,
+	VIO1_HD_MARK,	SCIF5_SCK_MARK,
+	VIO1_VD_MARK,	SCIF5_RXD_MARK,
+	VIO1_CLK_MARK,	SCIF5_TXD_MARK,
+	VIO1_D7_MARK,	VIO0_D15_MARK,		IDED7_MARK,
+	VIO1_D6_MARK,	VIO0_D14_MARK,		IDED6_MARK,
+
+	/*PTT*/
+	D15_MARK,
+	D14_MARK,
+	D13_MARK,
+	D12_MARK,
+	D11_MARK,
+	D10_MARK,
+	D9_MARK,
+	D8_MARK,
+
+	/*PTU*/
+	DMAC_DACK0_MARK,
+	DMAC_DREQ0_MARK,
+	FSIOASD_MARK,
+	FSIIABCK_MARK,
+	FSIIALRCK_MARK,
+	FSIOABCK_MARK,
+	FSIOALRCK_MARK,
+	CLKAUDIOAO_MARK,
+
+	/*PTV*/
+	FSIIBSD_MARK,		MSIOF1_SS2_MARK,	MSIOF1_RSYNC_MARK,
+	FSIOBSD_MARK,		MSIOF1_SS1_MARK,	MSIOF1_RSCK_MARK,
+	FSIIBBCK_MARK,		MSIOF1_RXD_MARK,
+	FSIIBLRCK_MARK,		MSIOF1_TSYNC_MARK,
+	FSIOBBCK_MARK,		MSIOF1_TSCK_MARK,
+	FSIOBLRCK_MARK,		MSIOF1_TXD_MARK,
+	CLKAUDIOBO_MARK,	MSIOF1_MCK_MARK,
+	FSIIASD_MARK,
+
+	/*PTW*/
+	MMC_D7_MARK,		SDHI1CD_MARK,		IODACK_MARK,
+	MMC_D6_MARK,		SDHI1WP_MARK,		IDERST_MARK,
+	MMC_D5_MARK,		SDHI1D3_MARK,		EXBUF_ENB_MARK,
+	MMC_D4_MARK,		SDHI1D2_MARK,		DIRECTION_MARK,
+	MMC_D3_MARK,		SDHI1D1_MARK,
+	MMC_D2_MARK,		SDHI1D0_MARK,
+	MMC_D1_MARK,		SDHI1CMD_MARK,
+	MMC_D0_MARK,		SDHI1CLK_MARK,
+
+	/*PTX*/
+	DMAC_DACK1_MARK,	IRDA_OUT_MARK,
+	DMAC_DREQ1_MARK,	IRDA_IN_MARK,
+	TSIF_TS0_SDAT_MARK,				LNKSTA_MARK,
+	TSIF_TS0_SCK_MARK,				MDIO_MARK,
+	TSIF_TS0_SDEN_MARK,				MDC_MARK,
+	TSIF_TS0_SPSYNC_MARK,
+	MMC_CLK_MARK,
+	MMC_CMD_MARK,
+
+	/*PTY*/
+	SDHI0CD_MARK,
+	SDHI0WP_MARK,
+	SDHI0D3_MARK,
+	SDHI0D2_MARK,
+	SDHI0D1_MARK,
+	SDHI0D0_MARK,
+	SDHI0CMD_MARK,
+	SDHI0CLK_MARK,
+
+	/*PTZ*/
+	INTC_IRQ7_MARK,		SCIF3_I_CTS_MARK,
+	INTC_IRQ6_MARK,		SCIF3_I_RTS_MARK,
+	INTC_IRQ5_MARK,		SCIF3_I_SCK_MARK,
+	INTC_IRQ4_MARK,		SCIF3_I_RXD_MARK,
+	INTC_IRQ3_MARK,		SCIF3_I_TXD_MARK,
+	INTC_IRQ2_MARK,
+	INTC_IRQ1_MARK,
+	INTC_IRQ0_MARK,
+	PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+	/* PTA GPIO */
+	PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT, PTA7_IN_PU),
+	PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT, PTA6_IN_PU),
+	PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT, PTA5_IN_PU),
+	PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT, PTA4_IN_PU),
+	PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT, PTA3_IN_PU),
+	PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT, PTA2_IN_PU),
+	PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT, PTA1_IN_PU),
+	PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT, PTA0_IN_PU),
+
+	/* PTB GPIO */
+	PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT, PTB7_IN_PU),
+	PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT, PTB6_IN_PU),
+	PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT, PTB5_IN_PU),
+	PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT, PTB4_IN_PU),
+	PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT, PTB3_IN_PU),
+	PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT, PTB2_IN_PU),
+	PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT, PTB1_IN_PU),
+	PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT, PTB0_IN_PU),
+
+	/* PTC GPIO */
+	PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT, PTC7_IN_PU),
+	PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT, PTC6_IN_PU),
+	PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT, PTC5_IN_PU),
+	PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT, PTC4_IN_PU),
+	PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT, PTC3_IN_PU),
+	PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT, PTC2_IN_PU),
+	PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT, PTC1_IN_PU),
+	PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT, PTC0_IN_PU),
+
+	/* PTD GPIO */
+	PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT, PTD7_IN_PU),
+	PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT, PTD6_IN_PU),
+	PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT, PTD5_IN_PU),
+	PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT, PTD4_IN_PU),
+	PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT, PTD3_IN_PU),
+	PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT, PTD2_IN_PU),
+	PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT, PTD1_IN_PU),
+	PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT, PTD0_IN_PU),
+
+	/* PTE GPIO */
+	PINMUX_DATA(PTE7_DATA, PTE7_IN, PTE7_OUT, PTE7_IN_PU),
+	PINMUX_DATA(PTE6_DATA, PTE6_IN, PTE6_OUT, PTE6_IN_PU),
+	PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT, PTE5_IN_PU),
+	PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT, PTE4_IN_PU),
+	PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT, PTE3_IN_PU),
+	PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT, PTE2_IN_PU),
+	PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT, PTE1_IN_PU),
+	PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT, PTE0_IN_PU),
+
+	/* PTF GPIO */
+	PINMUX_DATA(PTF7_DATA, PTF7_IN, PTF7_OUT, PTF7_IN_PU),
+	PINMUX_DATA(PTF6_DATA, PTF6_IN, PTF6_OUT, PTF6_IN_PU),
+	PINMUX_DATA(PTF5_DATA, PTF5_IN, PTF5_OUT, PTF5_IN_PU),
+	PINMUX_DATA(PTF4_DATA, PTF4_IN, PTF4_OUT, PTF4_IN_PU),
+	PINMUX_DATA(PTF3_DATA, PTF3_IN, PTF3_OUT, PTF3_IN_PU),
+	PINMUX_DATA(PTF2_DATA, PTF2_IN, PTF2_OUT, PTF2_IN_PU),
+	PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_OUT, PTF1_IN_PU),
+	PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT, PTF0_IN_PU),
+
+	/* PTG GPIO */
+	PINMUX_DATA(PTG5_DATA, PTG5_OUT),
+	PINMUX_DATA(PTG4_DATA, PTG4_OUT),
+	PINMUX_DATA(PTG3_DATA, PTG3_OUT),
+	PINMUX_DATA(PTG2_DATA, PTG2_OUT),
+	PINMUX_DATA(PTG1_DATA, PTG1_OUT),
+	PINMUX_DATA(PTG0_DATA, PTG0_OUT),
+
+	/* PTH GPIO */
+	PINMUX_DATA(PTH7_DATA, PTH7_IN, PTH7_OUT, PTH7_IN_PU),
+	PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT, PTH6_IN_PU),
+	PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT, PTH5_IN_PU),
+	PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT, PTH4_IN_PU),
+	PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT, PTH3_IN_PU),
+	PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT, PTH2_IN_PU),
+	PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT, PTH1_IN_PU),
+	PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT, PTH0_IN_PU),
+
+	/* PTJ GPIO */
+	PINMUX_DATA(PTJ7_DATA, PTJ7_OUT),
+	PINMUX_DATA(PTJ6_DATA, PTJ6_OUT),
+	PINMUX_DATA(PTJ5_DATA, PTJ5_OUT),
+	PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT, PTJ3_IN_PU),
+	PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT, PTJ2_IN_PU),
+	PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT, PTJ1_IN_PU),
+	PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT, PTJ0_IN_PU),
+
+	/* PTK GPIO */
+	PINMUX_DATA(PTK7_DATA, PTK7_IN, PTK7_OUT, PTK7_IN_PU),
+	PINMUX_DATA(PTK6_DATA, PTK6_IN, PTK6_OUT, PTK6_IN_PU),
+	PINMUX_DATA(PTK5_DATA, PTK5_IN, PTK5_OUT, PTK5_IN_PU),
+	PINMUX_DATA(PTK4_DATA, PTK4_IN, PTK4_OUT, PTK4_IN_PU),
+	PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT, PTK3_IN_PU),
+	PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT, PTK2_IN_PU),
+	PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT, PTK1_IN_PU),
+	PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT, PTK0_IN_PU),
+
+	/* PTL GPIO */
+	PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT, PTL7_IN_PU),
+	PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT, PTL6_IN_PU),
+	PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT, PTL5_IN_PU),
+	PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT, PTL4_IN_PU),
+	PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT, PTL3_IN_PU),
+	PINMUX_DATA(PTL2_DATA, PTL2_IN, PTL2_OUT, PTL2_IN_PU),
+	PINMUX_DATA(PTL1_DATA, PTL1_IN, PTL1_OUT, PTL1_IN_PU),
+	PINMUX_DATA(PTL0_DATA, PTL0_IN, PTL0_OUT, PTL0_IN_PU),
+
+	/* PTM GPIO */
+	PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT, PTM7_IN_PU),
+	PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT, PTM6_IN_PU),
+	PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT, PTM5_IN_PU),
+	PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT, PTM4_IN_PU),
+	PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT, PTM3_IN_PU),
+	PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT, PTM2_IN_PU),
+	PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT, PTM1_IN_PU),
+	PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT, PTM0_IN_PU),
+
+	/* PTN GPIO */
+	PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT, PTN7_IN_PU),
+	PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT, PTN6_IN_PU),
+	PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT, PTN5_IN_PU),
+	PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT, PTN4_IN_PU),
+	PINMUX_DATA(PTN3_DATA, PTN3_IN, PTN3_OUT, PTN3_IN_PU),
+	PINMUX_DATA(PTN2_DATA, PTN2_IN, PTN2_OUT, PTN2_IN_PU),
+	PINMUX_DATA(PTN1_DATA, PTN1_IN, PTN1_OUT, PTN1_IN_PU),
+	PINMUX_DATA(PTN0_DATA, PTN0_IN, PTN0_OUT, PTN0_IN_PU),
+
+	/* PTQ GPIO */
+	PINMUX_DATA(PTQ7_DATA, PTQ7_IN, PTQ7_OUT, PTQ7_IN_PU),
+	PINMUX_DATA(PTQ6_DATA, PTQ6_IN, PTQ6_OUT, PTQ6_IN_PU),
+	PINMUX_DATA(PTQ5_DATA, PTQ5_IN, PTQ5_OUT, PTQ5_IN_PU),
+	PINMUX_DATA(PTQ4_DATA, PTQ4_IN, PTQ4_OUT, PTQ4_IN_PU),
+	PINMUX_DATA(PTQ3_DATA, PTQ3_IN, PTQ3_OUT, PTQ3_IN_PU),
+	PINMUX_DATA(PTQ2_DATA, PTQ2_IN, PTQ2_OUT, PTQ2_IN_PU),
+	PINMUX_DATA(PTQ1_DATA, PTQ1_IN, PTQ1_OUT, PTQ1_IN_PU),
+	PINMUX_DATA(PTQ0_DATA, PTQ0_IN, PTQ0_OUT, PTQ0_IN_PU),
+
+	/* PTR GPIO */
+	PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT, PTR7_IN_PU),
+	PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT, PTR6_IN_PU),
+	PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT, PTR5_IN_PU),
+	PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT, PTR4_IN_PU),
+	PINMUX_DATA(PTR3_DATA, PTR3_IN,           PTR3_IN_PU),
+	PINMUX_DATA(PTR2_DATA, PTR2_IN,           PTR2_IN_PU),
+	PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT, PTR1_IN_PU),
+	PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT, PTR0_IN_PU),
+
+	/* PTS GPIO */
+	PINMUX_DATA(PTS6_DATA, PTS6_IN, PTS6_OUT, PTS6_IN_PU),
+	PINMUX_DATA(PTS5_DATA, PTS5_IN, PTS5_OUT, PTS5_IN_PU),
+	PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT, PTS4_IN_PU),
+	PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT, PTS3_IN_PU),
+	PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT, PTS2_IN_PU),
+	PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT, PTS1_IN_PU),
+	PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT, PTS0_IN_PU),
+
+	/* PTT GPIO */
+	PINMUX_DATA(PTT7_DATA, PTT7_IN, PTT7_OUT, PTT7_IN_PU),
+	PINMUX_DATA(PTT6_DATA, PTT6_IN, PTT6_OUT, PTT6_IN_PU),
+	PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT, PTT5_IN_PU),
+	PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT, PTT4_IN_PU),
+	PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT, PTT3_IN_PU),
+	PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT, PTT2_IN_PU),
+	PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT, PTT1_IN_PU),
+	PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT, PTT0_IN_PU),
+
+	/* PTU GPIO */
+	PINMUX_DATA(PTU7_DATA, PTU7_IN, PTU7_OUT, PTU7_IN_PU),
+	PINMUX_DATA(PTU6_DATA, PTU6_IN, PTU6_OUT, PTU6_IN_PU),
+	PINMUX_DATA(PTU5_DATA, PTU5_IN, PTU5_OUT, PTU5_IN_PU),
+	PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT, PTU4_IN_PU),
+	PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT, PTU3_IN_PU),
+	PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT, PTU2_IN_PU),
+	PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT, PTU1_IN_PU),
+	PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT, PTU0_IN_PU),
+
+	/* PTV GPIO */
+	PINMUX_DATA(PTV7_DATA, PTV7_IN, PTV7_OUT, PTV7_IN_PU),
+	PINMUX_DATA(PTV6_DATA, PTV6_IN, PTV6_OUT, PTV6_IN_PU),
+	PINMUX_DATA(PTV5_DATA, PTV5_IN, PTV5_OUT, PTV5_IN_PU),
+	PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT, PTV4_IN_PU),
+	PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT, PTV3_IN_PU),
+	PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT, PTV2_IN_PU),
+	PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT, PTV1_IN_PU),
+	PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT, PTV0_IN_PU),
+
+	/* PTW GPIO */
+	PINMUX_DATA(PTW7_DATA, PTW7_IN, PTW7_OUT, PTW7_IN_PU),
+	PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_OUT, PTW6_IN_PU),
+	PINMUX_DATA(PTW5_DATA, PTW5_IN, PTW5_OUT, PTW5_IN_PU),
+	PINMUX_DATA(PTW4_DATA, PTW4_IN, PTW4_OUT, PTW4_IN_PU),
+	PINMUX_DATA(PTW3_DATA, PTW3_IN, PTW3_OUT, PTW3_IN_PU),
+	PINMUX_DATA(PTW2_DATA, PTW2_IN, PTW2_OUT, PTW2_IN_PU),
+	PINMUX_DATA(PTW1_DATA, PTW1_IN, PTW1_OUT, PTW1_IN_PU),
+	PINMUX_DATA(PTW0_DATA, PTW0_IN, PTW0_OUT, PTW0_IN_PU),
+
+	/* PTX GPIO */
+	PINMUX_DATA(PTX7_DATA, PTX7_IN, PTX7_OUT, PTX7_IN_PU),
+	PINMUX_DATA(PTX6_DATA, PTX6_IN, PTX6_OUT, PTX6_IN_PU),
+	PINMUX_DATA(PTX5_DATA, PTX5_IN, PTX5_OUT, PTX5_IN_PU),
+	PINMUX_DATA(PTX4_DATA, PTX4_IN, PTX4_OUT, PTX4_IN_PU),
+	PINMUX_DATA(PTX3_DATA, PTX3_IN, PTX3_OUT, PTX3_IN_PU),
+	PINMUX_DATA(PTX2_DATA, PTX2_IN, PTX2_OUT, PTX2_IN_PU),
+	PINMUX_DATA(PTX1_DATA, PTX1_IN, PTX1_OUT, PTX1_IN_PU),
+	PINMUX_DATA(PTX0_DATA, PTX0_IN, PTX0_OUT, PTX0_IN_PU),
+
+	/* PTY GPIO */
+	PINMUX_DATA(PTY7_DATA, PTY7_IN, PTY7_OUT, PTY7_IN_PU),
+	PINMUX_DATA(PTY6_DATA, PTY6_IN, PTY6_OUT, PTY6_IN_PU),
+	PINMUX_DATA(PTY5_DATA, PTY5_IN, PTY5_OUT, PTY5_IN_PU),
+	PINMUX_DATA(PTY4_DATA, PTY4_IN, PTY4_OUT, PTY4_IN_PU),
+	PINMUX_DATA(PTY3_DATA, PTY3_IN, PTY3_OUT, PTY3_IN_PU),
+	PINMUX_DATA(PTY2_DATA, PTY2_IN, PTY2_OUT, PTY2_IN_PU),
+	PINMUX_DATA(PTY1_DATA, PTY1_IN, PTY1_OUT, PTY1_IN_PU),
+	PINMUX_DATA(PTY0_DATA, PTY0_IN, PTY0_OUT, PTY0_IN_PU),
+
+	/* PTZ GPIO */
+	PINMUX_DATA(PTZ7_DATA, PTZ7_IN, PTZ7_OUT, PTZ7_IN_PU),
+	PINMUX_DATA(PTZ6_DATA, PTZ6_IN, PTZ6_OUT, PTZ6_IN_PU),
+	PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_OUT, PTZ5_IN_PU),
+	PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_OUT, PTZ4_IN_PU),
+	PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_OUT, PTZ3_IN_PU),
+	PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_OUT, PTZ2_IN_PU),
+	PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_OUT, PTZ1_IN_PU),
+	PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT, PTZ0_IN_PU),
+
+	/* PTA FN */
+	PINMUX_DATA(D23_MARK,	PSA15_0, PSA14_0, PTA7_FN),
+	PINMUX_DATA(D22_MARK,	PSA15_0, PSA14_0, PTA6_FN),
+	PINMUX_DATA(D21_MARK,	PSA15_0, PSA14_0, PTA5_FN),
+	PINMUX_DATA(D20_MARK,	PSA15_0, PSA14_0, PTA4_FN),
+	PINMUX_DATA(D19_MARK,	PSA15_0, PSA14_0, PTA3_FN),
+	PINMUX_DATA(D18_MARK,	PSA15_0, PSA14_0, PTA2_FN),
+	PINMUX_DATA(D17_MARK,	PSA15_0, PSA14_0, PTA1_FN),
+	PINMUX_DATA(D16_MARK,	PSA15_0, PSA14_0, PTA0_FN),
+
+	PINMUX_DATA(KEYOUT2_MARK,	PSA15_0, PSA14_1, PTA7_FN),
+	PINMUX_DATA(KEYOUT1_MARK,	PSA15_0, PSA14_1, PTA6_FN),
+	PINMUX_DATA(KEYOUT0_MARK,	PSA15_0, PSA14_1, PTA5_FN),
+	PINMUX_DATA(KEYIN4_MARK,	PSA15_0, PSA14_1, PTA4_FN),
+	PINMUX_DATA(KEYIN3_MARK,	PSA15_0, PSA14_1, PTA3_FN),
+	PINMUX_DATA(KEYIN2_MARK,	PSA15_0, PSA14_1, PTA2_FN),
+	PINMUX_DATA(KEYIN1_MARK,	PSA15_0, PSA14_1, PTA1_FN),
+	PINMUX_DATA(KEYIN0_MARK,	PSA15_0, PSA14_1, PTA0_FN),
+
+	PINMUX_DATA(IDED15_MARK,	PSA15_1, PSA14_0, PTA7_FN),
+	PINMUX_DATA(IDED14_MARK,	PSA15_1, PSA14_0, PTA6_FN),
+	PINMUX_DATA(IDED13_MARK,	PSA15_1, PSA14_0, PTA5_FN),
+	PINMUX_DATA(IDED12_MARK,	PSA15_1, PSA14_0, PTA4_FN),
+	PINMUX_DATA(IDED11_MARK,	PSA15_1, PSA14_0, PTA3_FN),
+	PINMUX_DATA(IDED10_MARK,	PSA15_1, PSA14_0, PTA2_FN),
+	PINMUX_DATA(IDED9_MARK,		PSA15_1, PSA14_0, PTA1_FN),
+	PINMUX_DATA(IDED8_MARK,		PSA15_1, PSA14_0, PTA0_FN),
+
+	/* PTB FN */
+	PINMUX_DATA(D31_MARK,		PSE15_0, PSE14_0, PTB7_FN),
+	PINMUX_DATA(D30_MARK,		PSE15_0, PSE14_0, PTB6_FN),
+	PINMUX_DATA(D29_MARK,		PSE11_0,          PTB5_FN),
+	PINMUX_DATA(D28_MARK,		PSE11_0,          PTB4_FN),
+	PINMUX_DATA(D27_MARK,		PSE11_0,          PTB3_FN),
+	PINMUX_DATA(D26_MARK,		PSA15_0, PSA14_0, PTB2_FN),
+	PINMUX_DATA(D25_MARK,		PSA15_0, PSA14_0, PTB1_FN),
+	PINMUX_DATA(D24_MARK,		PSA15_0, PSA14_0, PTB0_FN),
+
+	PINMUX_DATA(IDEA1_MARK,		PSE15_1, PSE14_0, PTB7_FN),
+	PINMUX_DATA(IDEA0_MARK,		PSE15_1, PSE14_0, PTB6_FN),
+	PINMUX_DATA(IODREQ_MARK,	PSE11_1,          PTB5_FN),
+	PINMUX_DATA(IDECS0_MARK,	PSE11_1,          PTB4_FN),
+	PINMUX_DATA(IDECS1_MARK,	PSE11_1,          PTB3_FN),
+	PINMUX_DATA(IDEIORD_MARK,	PSA15_1, PSA14_0, PTB2_FN),
+	PINMUX_DATA(IDEIOWR_MARK,	PSA15_1, PSA14_0, PTB1_FN),
+	PINMUX_DATA(IDEINT_MARK,	PSA15_1, PSA14_0, PTB0_FN),
+
+	PINMUX_DATA(TPUTO1_MARK,	PSE15_0, PSE14_1, PTB7_FN),
+	PINMUX_DATA(TPUTO0_MARK,	PSE15_0, PSE14_1, PTB6_FN),
+
+	PINMUX_DATA(KEYOUT5_IN5_MARK,	PSA15_0, PSA14_1, PTB2_FN),
+	PINMUX_DATA(KEYOUT4_IN6_MARK,	PSA15_0, PSA14_1, PTB1_FN),
+	PINMUX_DATA(KEYOUT3_MARK,	PSA15_0, PSA14_1, PTB0_FN),
+
+	/* PTC FN */
+	PINMUX_DATA(LCDD7_MARK, PSD5_0, PTC7_FN),
+	PINMUX_DATA(LCDD6_MARK, PSD5_0, PTC6_FN),
+	PINMUX_DATA(LCDD5_MARK, PSD5_0, PTC5_FN),
+	PINMUX_DATA(LCDD4_MARK, PSD5_0, PTC4_FN),
+	PINMUX_DATA(LCDD3_MARK, PSD5_0, PTC3_FN),
+	PINMUX_DATA(LCDD2_MARK, PSD5_0, PTC2_FN),
+	PINMUX_DATA(LCDD1_MARK, PSD5_0, PTC1_FN),
+	PINMUX_DATA(LCDD0_MARK, PSD5_0, PTC0_FN),
+
+	/* PTD FN */
+	PINMUX_DATA(LCDD15_MARK, PSD5_0, PTD7_FN),
+	PINMUX_DATA(LCDD14_MARK, PSD5_0, PTD6_FN),
+	PINMUX_DATA(LCDD13_MARK, PSD5_0, PTD5_FN),
+	PINMUX_DATA(LCDD12_MARK, PSD5_0, PTD4_FN),
+	PINMUX_DATA(LCDD11_MARK, PSD5_0, PTD3_FN),
+	PINMUX_DATA(LCDD10_MARK, PSD5_0, PTD2_FN),
+	PINMUX_DATA(LCDD9_MARK,  PSD5_0, PTD1_FN),
+	PINMUX_DATA(LCDD8_MARK,  PSD5_0, PTD0_FN),
+
+	/* PTE FN */
+	PINMUX_DATA(FSIMCKB_MARK, PTE7_FN),
+	PINMUX_DATA(FSIMCKA_MARK, PTE6_FN),
+
+	PINMUX_DATA(LCDD21_MARK,	PSC5_0, PSC4_0, PTE5_FN),
+	PINMUX_DATA(LCDD20_MARK,	PSD3_0, PSD2_0, PTE4_FN),
+	PINMUX_DATA(LCDD19_MARK,	PSA3_0, PSA2_0, PTE3_FN),
+	PINMUX_DATA(LCDD18_MARK,	PSA3_0, PSA2_0, PTE2_FN),
+	PINMUX_DATA(LCDD17_MARK,	PSD5_0,         PTE1_FN),
+	PINMUX_DATA(LCDD16_MARK,	PSD5_0,         PTE0_FN),
+
+	PINMUX_DATA(SCIF2_L_TXD_MARK,	PSC5_0, PSC4_1, PTE5_FN),
+	PINMUX_DATA(SCIF4_SCK_MARK,	PSD3_0, PSD2_1, PTE4_FN),
+	PINMUX_DATA(SCIF4_RXD_MARK,	PSA3_0, PSA2_1, PTE3_FN),
+	PINMUX_DATA(SCIF4_TXD_MARK,	PSA3_0, PSA2_1, PTE2_FN),
+
+	/* PTF FN */
+	PINMUX_DATA(LCDVSYN_MARK,	PSD8_0,          PTF7_FN),
+	PINMUX_DATA(LCDDISP_MARK,	PSD10_0, PSD9_0, PTF6_FN),
+	PINMUX_DATA(LCDHSYN_MARK,	PSD10_0, PSD9_0, PTF5_FN),
+	PINMUX_DATA(LCDDON_MARK,	PSD8_0,          PTF4_FN),
+	PINMUX_DATA(LCDDCK_MARK,	PSD10_0, PSD9_0, PTF3_FN),
+	PINMUX_DATA(LCDVEPWC_MARK,	PSA6_0,          PTF2_FN),
+	PINMUX_DATA(LCDD23_MARK,	PSC7_0,  PSC6_0, PTF1_FN),
+	PINMUX_DATA(LCDD22_MARK,	PSC5_0,  PSC4_0, PTF0_FN),
+
+	PINMUX_DATA(LCDRS_MARK,		PSD10_0, PSD9_1, PTF6_FN),
+	PINMUX_DATA(LCDCS_MARK,		PSD10_0, PSD9_1, PTF5_FN),
+	PINMUX_DATA(LCDWR_MARK,		PSD10_0, PSD9_1, PTF3_FN),
+
+	PINMUX_DATA(SCIF0_TXD_MARK,	PSA6_1,          PTF2_FN),
+	PINMUX_DATA(SCIF2_L_SCK_MARK,	PSC7_0,  PSC6_1, PTF1_FN),
+	PINMUX_DATA(SCIF2_L_RXD_MARK,	PSC5_0,  PSC4_1, PTF0_FN),
+
+	/* PTG FN */
+	PINMUX_DATA(AUDCK_MARK,   PTG5_FN),
+	PINMUX_DATA(AUDSYNC_MARK, PTG4_FN),
+	PINMUX_DATA(AUDATA3_MARK, PTG3_FN),
+	PINMUX_DATA(AUDATA2_MARK, PTG2_FN),
+	PINMUX_DATA(AUDATA1_MARK, PTG1_FN),
+	PINMUX_DATA(AUDATA0_MARK, PTG0_FN),
+
+	/* PTH FN */
+	PINMUX_DATA(VIO0_VD_MARK,  PTH7_FN),
+	PINMUX_DATA(VIO0_CLK_MARK, PTH6_FN),
+	PINMUX_DATA(VIO0_D7_MARK,  PTH5_FN),
+	PINMUX_DATA(VIO0_D6_MARK,  PTH4_FN),
+	PINMUX_DATA(VIO0_D5_MARK,  PTH3_FN),
+	PINMUX_DATA(VIO0_D4_MARK,  PTH2_FN),
+	PINMUX_DATA(VIO0_D3_MARK,  PTH1_FN),
+	PINMUX_DATA(VIO0_D2_MARK,  PTH0_FN),
+
+	/* PTJ FN */
+	PINMUX_DATA(PDSTATUS_MARK,	PTJ7_FN),
+	PINMUX_DATA(STATUS2_MARK,	PTJ6_FN),
+	PINMUX_DATA(STATUS0_MARK,	PTJ5_FN),
+	PINMUX_DATA(A25_MARK,		PSA8_0, PTJ3_FN),
+	PINMUX_DATA(BS_MARK,		PSA8_1, PTJ3_FN),
+	PINMUX_DATA(A24_MARK,		PTJ2_FN),
+	PINMUX_DATA(A23_MARK,		PTJ1_FN),
+	PINMUX_DATA(A22_MARK,		PTJ0_FN),
+
+	/* PTK FN */
+	PINMUX_DATA(VIO1_D5_MARK,	PSB7_0, PSB6_0, PTK7_FN),
+	PINMUX_DATA(VIO1_D4_MARK,	PSB7_0, PSB6_0, PTK6_FN),
+	PINMUX_DATA(VIO1_D3_MARK,	PSB7_0, PSB6_0, PTK5_FN),
+	PINMUX_DATA(VIO1_D2_MARK,	PSB7_0, PSB6_0, PTK4_FN),
+	PINMUX_DATA(VIO1_D1_MARK,	PSB7_0, PSB6_0, PTK3_FN),
+	PINMUX_DATA(VIO1_D0_MARK,	PSB7_0, PSB6_0, PTK2_FN),
+
+	PINMUX_DATA(VIO0_D13_MARK,	PSB7_0, PSB6_1, PTK7_FN),
+	PINMUX_DATA(VIO0_D12_MARK,	PSB7_0, PSB6_1, PTK6_FN),
+	PINMUX_DATA(VIO0_D11_MARK,	PSB7_0, PSB6_1, PTK5_FN),
+	PINMUX_DATA(VIO0_D10_MARK,	PSB7_0, PSB6_1, PTK4_FN),
+	PINMUX_DATA(VIO0_D9_MARK,	PSB7_0, PSB6_1, PTK3_FN),
+	PINMUX_DATA(VIO0_D8_MARK,	PSB7_0, PSB6_1, PTK2_FN),
+
+	PINMUX_DATA(IDED5_MARK,		PSB7_1, PSB6_0, PTK7_FN),
+	PINMUX_DATA(IDED4_MARK,		PSB7_1, PSB6_0, PTK6_FN),
+	PINMUX_DATA(IDED3_MARK,		PSB7_1, PSB6_0, PTK5_FN),
+	PINMUX_DATA(IDED2_MARK,		PSB7_1, PSB6_0, PTK4_FN),
+	PINMUX_DATA(IDED1_MARK,		PSB7_1, PSB6_0, PTK3_FN),
+	PINMUX_DATA(IDED0_MARK,		PSB7_1, PSB6_0, PTK2_FN),
+
+	PINMUX_DATA(VIO0_FLD_MARK,	PTK1_FN),
+	PINMUX_DATA(VIO0_HD_MARK,	PTK0_FN),
+
+	/* PTL FN */
+	PINMUX_DATA(DV_D5_MARK,		PSB9_0, PSB8_0, PTL7_FN),
+	PINMUX_DATA(DV_D4_MARK,		PSB9_0, PSB8_0, PTL6_FN),
+	PINMUX_DATA(DV_D3_MARK,		PSE7_0, PSE6_0, PTL5_FN),
+	PINMUX_DATA(DV_D2_MARK,		PSC9_0, PSC8_0, PTL4_FN),
+	PINMUX_DATA(DV_D1_MARK,		PSC9_0, PSC8_0, PTL3_FN),
+	PINMUX_DATA(DV_D0_MARK,		PSC9_0, PSC8_0, PTL2_FN),
+	PINMUX_DATA(DV_D15_MARK,	PSD4_0,         PTL1_FN),
+	PINMUX_DATA(DV_D14_MARK,	PSE5_0, PSE4_0, PTL0_FN),
+
+	PINMUX_DATA(SCIF3_V_SCK_MARK,	PSB9_0, PSB8_1, PTL7_FN),
+	PINMUX_DATA(SCIF3_V_RXD_MARK,	PSB9_0, PSB8_1, PTL6_FN),
+	PINMUX_DATA(SCIF3_V_TXD_MARK,	PSE7_0, PSE6_1, PTL5_FN),
+	PINMUX_DATA(SCIF1_SCK_MARK,	PSC9_0, PSC8_1, PTL4_FN),
+	PINMUX_DATA(SCIF1_RXD_MARK,	PSC9_0, PSC8_1, PTL3_FN),
+	PINMUX_DATA(SCIF1_TXD_MARK,	PSC9_0, PSC8_1, PTL2_FN),
+
+	PINMUX_DATA(RMII_RXD0_MARK,	PSB9_1, PSB8_0, PTL7_FN),
+	PINMUX_DATA(RMII_RXD1_MARK,	PSB9_1, PSB8_0, PTL6_FN),
+	PINMUX_DATA(RMII_REF_CLK_MARK,	PSE7_1, PSE6_0, PTL5_FN),
+	PINMUX_DATA(RMII_TX_EN_MARK,	PSC9_1, PSC8_0, PTL4_FN),
+	PINMUX_DATA(RMII_TXD0_MARK,	PSC9_1, PSC8_0, PTL3_FN),
+	PINMUX_DATA(RMII_TXD1_MARK,	PSC9_1, PSC8_0, PTL2_FN),
+
+	PINMUX_DATA(MSIOF0_MCK_MARK,	PSE5_0, PSE4_1, PTL0_FN),
+
+	/* PTM FN */
+	PINMUX_DATA(DV_D13_MARK,	PSC13_0, PSC12_0, PTM7_FN),
+	PINMUX_DATA(DV_D12_MARK,	PSC13_0, PSC12_0, PTM6_FN),
+	PINMUX_DATA(DV_D11_MARK,	PSC13_0, PSC12_0, PTM5_FN),
+	PINMUX_DATA(DV_D10_MARK,	PSC13_0, PSC12_0, PTM4_FN),
+	PINMUX_DATA(DV_D9_MARK,		PSC11_0, PSC10_0, PTM3_FN),
+	PINMUX_DATA(DV_D8_MARK,		PSC11_0, PSC10_0, PTM2_FN),
+
+	PINMUX_DATA(MSIOF0_TSCK_MARK,	PSC13_0, PSC12_1, PTM7_FN),
+	PINMUX_DATA(MSIOF0_RXD_MARK,	PSC13_0, PSC12_1, PTM6_FN),
+	PINMUX_DATA(MSIOF0_TXD_MARK,	PSC13_0, PSC12_1, PTM5_FN),
+	PINMUX_DATA(MSIOF0_TSYNC_MARK,	PSC13_0, PSC12_1, PTM4_FN),
+	PINMUX_DATA(MSIOF0_SS1_MARK,	PSC11_0, PSC10_1, PTM3_FN),
+	PINMUX_DATA(MSIOF0_RSCK_MARK,	PSC11_1, PSC10_0, PTM3_FN),
+	PINMUX_DATA(MSIOF0_SS2_MARK,	PSC11_0, PSC10_1, PTM2_FN),
+	PINMUX_DATA(MSIOF0_RSYNC_MARK,	PSC11_1, PSC10_0, PTM2_FN),
+
+	PINMUX_DATA(LCDVCPWC_MARK,	PSA6_0, PTM1_FN),
+	PINMUX_DATA(LCDRD_MARK,		PSA7_0, PTM0_FN),
+
+	PINMUX_DATA(SCIF0_RXD_MARK,	PSA6_1, PTM1_FN),
+	PINMUX_DATA(SCIF0_SCK_MARK,	PSA7_1, PTM0_FN),
+
+	/* PTN FN */
+	PINMUX_DATA(VIO0_D1_MARK,	PTN7_FN),
+	PINMUX_DATA(VIO0_D0_MARK,	PTN6_FN),
+
+	PINMUX_DATA(DV_CLKI_MARK,	PSD11_0,          PTN5_FN),
+	PINMUX_DATA(DV_CLK_MARK,	PSD13_0, PSD12_0, PTN4_FN),
+	PINMUX_DATA(DV_VSYNC_MARK,	PSD15_0, PSD14_0, PTN3_FN),
+	PINMUX_DATA(DV_HSYNC_MARK,	PSB5_0,  PSB4_0,  PTN2_FN),
+	PINMUX_DATA(DV_D7_MARK,		PSB3_0,  PSB2_0,  PTN1_FN),
+	PINMUX_DATA(DV_D6_MARK,		PSB1_0,  PSB0_0,  PTN0_FN),
+
+	PINMUX_DATA(SCIF2_V_SCK_MARK,	PSD13_0, PSD12_1, PTN4_FN),
+	PINMUX_DATA(SCIF2_V_RXD_MARK,	PSD15_0, PSD14_1, PTN3_FN),
+	PINMUX_DATA(SCIF2_V_TXD_MARK,	PSB5_0,  PSB4_1,  PTN2_FN),
+	PINMUX_DATA(SCIF3_V_CTS_MARK,	PSB3_0,  PSB2_1,  PTN1_FN),
+	PINMUX_DATA(SCIF3_V_RTS_MARK,	PSB1_0,  PSB0_1,  PTN0_FN),
+
+	PINMUX_DATA(RMII_RX_ER_MARK,	PSB3_1, PSB2_0, PTN1_FN),
+	PINMUX_DATA(RMII_CRS_DV_MARK,	PSB1_1, PSB0_0, PTN0_FN),
+
+	/* PTQ FN */
+	PINMUX_DATA(D7_MARK, PTQ7_FN),
+	PINMUX_DATA(D6_MARK, PTQ6_FN),
+	PINMUX_DATA(D5_MARK, PTQ5_FN),
+	PINMUX_DATA(D4_MARK, PTQ4_FN),
+	PINMUX_DATA(D3_MARK, PTQ3_FN),
+	PINMUX_DATA(D2_MARK, PTQ2_FN),
+	PINMUX_DATA(D1_MARK, PTQ1_FN),
+	PINMUX_DATA(D0_MARK, PTQ0_FN),
+
+	/* PTR FN */
+	PINMUX_DATA(CS6B_CE1B_MARK,	                PTR7_FN),
+	PINMUX_DATA(CS6A_CE2B_MARK,	                PTR6_FN),
+	PINMUX_DATA(CS5B_CE1A_MARK,	                PTR5_FN),
+	PINMUX_DATA(CS5A_CE2A_MARK,	                PTR4_FN),
+	PINMUX_DATA(IOIS16_MARK,	PSA5_0,         PTR3_FN),
+	PINMUX_DATA(WAIT_MARK,		                PTR2_FN),
+	PINMUX_DATA(WE3_ICIOWR_MARK,	PSA1_0, PSA0_0, PTR1_FN),
+	PINMUX_DATA(WE2_ICIORD_MARK,	PSD1_0, PSD0_0, PTR0_FN),
+
+	PINMUX_DATA(LCDLCLK_MARK,	PSA5_1,         PTR3_FN),
+
+	PINMUX_DATA(IDEA2_MARK,		PSD1_1, PSD0_0, PTR0_FN),
+
+	PINMUX_DATA(TPUTO3_MARK,	PSA1_0, PSA0_1, PTR1_FN),
+	PINMUX_DATA(TPUTI3_MARK,	PSA1_1, PSA0_0, PTR1_FN),
+	PINMUX_DATA(TPUTO2_MARK,	PSD1_0, PSD0_1, PTR0_FN),
+
+	/* PTS FN */
+	PINMUX_DATA(VIO_CKO_MARK,	PTS6_FN),
+
+	PINMUX_DATA(TPUTI2_MARK,	PSE9_0, PSE8_1, PTS5_FN),
+
+	PINMUX_DATA(IDEIORDY_MARK,	PSE9_1, PSE8_0, PTS5_FN),
+
+	PINMUX_DATA(VIO1_FLD_MARK,	PSE9_0, PSE8_0, PTS5_FN),
+	PINMUX_DATA(VIO1_HD_MARK,	PSA10_0,        PTS4_FN),
+	PINMUX_DATA(VIO1_VD_MARK,	PSA9_0,         PTS3_FN),
+	PINMUX_DATA(VIO1_CLK_MARK,	PSA9_0,         PTS2_FN),
+	PINMUX_DATA(VIO1_D7_MARK,	PSB7_0, PSB6_0, PTS1_FN),
+	PINMUX_DATA(VIO1_D6_MARK,	PSB7_0, PSB6_0, PTS0_FN),
+
+	PINMUX_DATA(SCIF5_SCK_MARK,	PSA10_1, PTS4_FN),
+	PINMUX_DATA(SCIF5_RXD_MARK,	PSA9_1,  PTS3_FN),
+	PINMUX_DATA(SCIF5_TXD_MARK,	PSA9_1,  PTS2_FN),
+
+	PINMUX_DATA(VIO0_D15_MARK,	PSB7_0, PSB6_1, PTS1_FN),
+	PINMUX_DATA(VIO0_D14_MARK,	PSB7_0, PSB6_1, PTS0_FN),
+
+	PINMUX_DATA(IDED7_MARK,		PSB7_1, PSB6_0, PTS1_FN),
+	PINMUX_DATA(IDED6_MARK,		PSB7_1, PSB6_0, PTS0_FN),
+
+	/* PTT FN */
+	PINMUX_DATA(D15_MARK, PTT7_FN),
+	PINMUX_DATA(D14_MARK, PTT6_FN),
+	PINMUX_DATA(D13_MARK, PTT5_FN),
+	PINMUX_DATA(D12_MARK, PTT4_FN),
+	PINMUX_DATA(D11_MARK, PTT3_FN),
+	PINMUX_DATA(D10_MARK, PTT2_FN),
+	PINMUX_DATA(D9_MARK,  PTT1_FN),
+	PINMUX_DATA(D8_MARK,  PTT0_FN),
+
+	/* PTU FN */
+	PINMUX_DATA(DMAC_DACK0_MARK, PTU7_FN),
+	PINMUX_DATA(DMAC_DREQ0_MARK, PTU6_FN),
+
+	PINMUX_DATA(FSIOASD_MARK,	PSE1_0, PTU5_FN),
+	PINMUX_DATA(FSIIABCK_MARK,	PSE1_0, PTU4_FN),
+	PINMUX_DATA(FSIIALRCK_MARK,	PSE1_0, PTU3_FN),
+	PINMUX_DATA(FSIOABCK_MARK,	PSE1_0, PTU2_FN),
+	PINMUX_DATA(FSIOALRCK_MARK,	PSE1_0, PTU1_FN),
+	PINMUX_DATA(CLKAUDIOAO_MARK,	PSE0_0, PTU0_FN),
+
+	/* PTV FN */
+	PINMUX_DATA(FSIIBSD_MARK,	PSD7_0,  PSD6_0,  PTV7_FN),
+	PINMUX_DATA(FSIOBSD_MARK,	PSD7_0,  PSD6_0,  PTV6_FN),
+	PINMUX_DATA(FSIIBBCK_MARK,	PSC15_0, PSC14_0, PTV5_FN),
+	PINMUX_DATA(FSIIBLRCK_MARK,	PSC15_0, PSC14_0, PTV4_FN),
+	PINMUX_DATA(FSIOBBCK_MARK,	PSC15_0, PSC14_0, PTV3_FN),
+	PINMUX_DATA(FSIOBLRCK_MARK,	PSC15_0, PSC14_0, PTV2_FN),
+	PINMUX_DATA(CLKAUDIOBO_MARK,	PSE3_0,  PSE2_0,  PTV1_FN),
+	PINMUX_DATA(FSIIASD_MARK,	PSE10_0,          PTV0_FN),
+
+	PINMUX_DATA(MSIOF1_SS2_MARK,	PSD7_0,  PSD6_1,  PTV7_FN),
+	PINMUX_DATA(MSIOF1_RSYNC_MARK,	PSD7_1,  PSD6_0,  PTV7_FN),
+	PINMUX_DATA(MSIOF1_SS1_MARK,	PSD7_0,  PSD6_1,  PTV6_FN),
+	PINMUX_DATA(MSIOF1_RSCK_MARK,	PSD7_1,  PSD6_0,  PTV6_FN),
+	PINMUX_DATA(MSIOF1_RXD_MARK,	PSC15_0, PSC14_1, PTV5_FN),
+	PINMUX_DATA(MSIOF1_TSYNC_MARK,	PSC15_0, PSC14_1, PTV4_FN),
+	PINMUX_DATA(MSIOF1_TSCK_MARK,	PSC15_0, PSC14_1, PTV3_FN),
+	PINMUX_DATA(MSIOF1_TXD_MARK,	PSC15_0, PSC14_1, PTV2_FN),
+	PINMUX_DATA(MSIOF1_MCK_MARK,	PSE3_0,  PSE2_1,  PTV1_FN),
+
+	/* PTW FN */
+	PINMUX_DATA(MMC_D7_MARK,	PSE13_0, PSE12_0, PTW7_FN),
+	PINMUX_DATA(MMC_D6_MARK,	PSE13_0, PSE12_0, PTW6_FN),
+	PINMUX_DATA(MMC_D5_MARK,	PSE13_0, PSE12_0, PTW5_FN),
+	PINMUX_DATA(MMC_D4_MARK,	PSE13_0, PSE12_0, PTW4_FN),
+	PINMUX_DATA(MMC_D3_MARK,	PSA13_0,          PTW3_FN),
+	PINMUX_DATA(MMC_D2_MARK,	PSA13_0,          PTW2_FN),
+	PINMUX_DATA(MMC_D1_MARK,	PSA13_0,          PTW1_FN),
+	PINMUX_DATA(MMC_D0_MARK,	PSA13_0,          PTW0_FN),
+
+	PINMUX_DATA(SDHI1CD_MARK,	PSE13_0, PSE12_1, PTW7_FN),
+	PINMUX_DATA(SDHI1WP_MARK,	PSE13_0, PSE12_1, PTW6_FN),
+	PINMUX_DATA(SDHI1D3_MARK,	PSE13_0, PSE12_1, PTW5_FN),
+	PINMUX_DATA(SDHI1D2_MARK,	PSE13_0, PSE12_1, PTW4_FN),
+	PINMUX_DATA(SDHI1D1_MARK,	PSA13_1,          PTW3_FN),
+	PINMUX_DATA(SDHI1D0_MARK,	PSA13_1,          PTW2_FN),
+	PINMUX_DATA(SDHI1CMD_MARK,	PSA13_1,          PTW1_FN),
+	PINMUX_DATA(SDHI1CLK_MARK,	PSA13_1,          PTW0_FN),
+
+	PINMUX_DATA(IODACK_MARK,	PSE13_1, PSE12_0, PTW7_FN),
+	PINMUX_DATA(IDERST_MARK,	PSE13_1, PSE12_0, PTW6_FN),
+	PINMUX_DATA(EXBUF_ENB_MARK,	PSE13_1, PSE12_0, PTW5_FN),
+	PINMUX_DATA(DIRECTION_MARK,	PSE13_1, PSE12_0, PTW4_FN),
+
+	/* PTX FN */
+	PINMUX_DATA(DMAC_DACK1_MARK,	PSA12_0, PTX7_FN),
+	PINMUX_DATA(DMAC_DREQ1_MARK,	PSA12_0, PTX6_FN),
+
+	PINMUX_DATA(IRDA_OUT_MARK,	PSA12_1, PTX7_FN),
+	PINMUX_DATA(IRDA_IN_MARK,	PSA12_1, PTX6_FN),
+
+	PINMUX_DATA(TSIF_TS0_SDAT_MARK,	PSC0_0, PTX5_FN),
+	PINMUX_DATA(TSIF_TS0_SCK_MARK,	PSC1_0, PTX4_FN),
+	PINMUX_DATA(TSIF_TS0_SDEN_MARK,	PSC2_0, PTX3_FN),
+	PINMUX_DATA(TSIF_TS0_SPSYNC_MARK,       PTX2_FN),
+
+	PINMUX_DATA(LNKSTA_MARK,	PSC0_1, PTX5_FN),
+	PINMUX_DATA(MDIO_MARK,		PSC1_1, PTX4_FN),
+	PINMUX_DATA(MDC_MARK,		PSC2_1, PTX3_FN),
+
+	PINMUX_DATA(MMC_CLK_MARK, PTX1_FN),
+	PINMUX_DATA(MMC_CMD_MARK, PTX0_FN),
+
+	/* PTY FN */
+	PINMUX_DATA(SDHI0CD_MARK,  PTY7_FN),
+	PINMUX_DATA(SDHI0WP_MARK,  PTY6_FN),
+	PINMUX_DATA(SDHI0D3_MARK,  PTY5_FN),
+	PINMUX_DATA(SDHI0D2_MARK,  PTY4_FN),
+	PINMUX_DATA(SDHI0D1_MARK,  PTY3_FN),
+	PINMUX_DATA(SDHI0D0_MARK,  PTY2_FN),
+	PINMUX_DATA(SDHI0CMD_MARK, PTY1_FN),
+	PINMUX_DATA(SDHI0CLK_MARK, PTY0_FN),
+
+	/* PTZ FN */
+	PINMUX_DATA(INTC_IRQ7_MARK,	PSB10_0, PTZ7_FN),
+	PINMUX_DATA(INTC_IRQ6_MARK,	PSB11_0, PTZ6_FN),
+	PINMUX_DATA(INTC_IRQ5_MARK,	PSB12_0, PTZ5_FN),
+	PINMUX_DATA(INTC_IRQ4_MARK,	PSB13_0, PTZ4_FN),
+	PINMUX_DATA(INTC_IRQ3_MARK,	PSB14_0, PTZ3_FN),
+	PINMUX_DATA(INTC_IRQ2_MARK,	         PTZ2_FN),
+	PINMUX_DATA(INTC_IRQ1_MARK,	         PTZ1_FN),
+	PINMUX_DATA(INTC_IRQ0_MARK,	         PTZ0_FN),
+
+	PINMUX_DATA(SCIF3_I_CTS_MARK,	PSB10_1, PTZ7_FN),
+	PINMUX_DATA(SCIF3_I_RTS_MARK,	PSB11_1, PTZ6_FN),
+	PINMUX_DATA(SCIF3_I_SCK_MARK,	PSB12_1, PTZ5_FN),
+	PINMUX_DATA(SCIF3_I_RXD_MARK,	PSB13_1, PTZ4_FN),
+	PINMUX_DATA(SCIF3_I_TXD_MARK,	PSB14_1, PTZ3_FN),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+	/* PTA */
+	PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
+	PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
+	PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
+	PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
+	PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
+	PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
+	PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
+	PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+
+	/* PTB */
+	PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
+	PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
+	PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
+	PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
+	PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
+	PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
+	PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
+	PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+
+	/* PTC */
+	PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
+	PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
+	PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
+	PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
+	PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
+	PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
+	PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
+	PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+
+	/* PTD */
+	PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
+	PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
+	PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
+	PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
+	PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
+	PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
+	PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
+	PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+
+	/* PTE */
+	PINMUX_GPIO(GPIO_PTE7, PTE7_DATA),
+	PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
+	PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
+	PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
+	PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
+	PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
+	PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
+	PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+
+	/* PTF */
+	PINMUX_GPIO(GPIO_PTF7, PTF7_DATA),
+	PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
+	PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
+	PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
+	PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
+	PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
+	PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
+	PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+
+	/* PTG */
+	PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
+	PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
+	PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
+	PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
+	PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
+	PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+
+	/* PTH */
+	PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
+	PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
+	PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
+	PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
+	PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
+	PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
+	PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
+	PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+
+	/* PTJ */
+	PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
+	PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
+	PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
+	PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
+	PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
+	PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
+	PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+
+	/* PTK */
+	PINMUX_GPIO(GPIO_PTK7, PTK7_DATA),
+	PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
+	PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
+	PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
+	PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
+	PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
+	PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
+	PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+
+	/* PTL */
+	PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
+	PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
+	PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
+	PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
+	PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
+	PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
+	PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
+	PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+
+	/* PTM */
+	PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
+	PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
+	PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
+	PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
+	PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
+	PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
+	PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
+	PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+
+	/* PTN */
+	PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
+	PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
+	PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
+	PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
+	PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
+	PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
+	PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
+	PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+
+	/* PTQ */
+	PINMUX_GPIO(GPIO_PTQ7, PTQ7_DATA),
+	PINMUX_GPIO(GPIO_PTQ6, PTQ6_DATA),
+	PINMUX_GPIO(GPIO_PTQ5, PTQ5_DATA),
+	PINMUX_GPIO(GPIO_PTQ4, PTQ4_DATA),
+	PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
+	PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
+	PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
+	PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+
+	/* PTR */
+	PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
+	PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
+	PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
+	PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
+	PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
+	PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
+	PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
+	PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+
+	/* PTS */
+	PINMUX_GPIO(GPIO_PTS6, PTS6_DATA),
+	PINMUX_GPIO(GPIO_PTS5, PTS5_DATA),
+	PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
+	PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
+	PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
+	PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
+	PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+
+	/* PTT */
+	PINMUX_GPIO(GPIO_PTT7, PTT7_DATA),
+	PINMUX_GPIO(GPIO_PTT6, PTT6_DATA),
+	PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
+	PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
+	PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
+	PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
+	PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
+	PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+
+	/* PTU */
+	PINMUX_GPIO(GPIO_PTU7, PTU7_DATA),
+	PINMUX_GPIO(GPIO_PTU6, PTU6_DATA),
+	PINMUX_GPIO(GPIO_PTU5, PTU5_DATA),
+	PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
+	PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
+	PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
+	PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
+	PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+
+	/* PTV */
+	PINMUX_GPIO(GPIO_PTV7, PTV7_DATA),
+	PINMUX_GPIO(GPIO_PTV6, PTV6_DATA),
+	PINMUX_GPIO(GPIO_PTV5, PTV5_DATA),
+	PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
+	PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
+	PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
+	PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
+	PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+
+	/* PTW */
+	PINMUX_GPIO(GPIO_PTW7, PTW7_DATA),
+	PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
+	PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
+	PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
+	PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
+	PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
+	PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
+	PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+
+	/* PTX */
+	PINMUX_GPIO(GPIO_PTX7, PTX7_DATA),
+	PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
+	PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
+	PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
+	PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
+	PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
+	PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
+	PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+
+	/* PTY */
+	PINMUX_GPIO(GPIO_PTY7, PTY7_DATA),
+	PINMUX_GPIO(GPIO_PTY6, PTY6_DATA),
+	PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
+	PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
+	PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
+	PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
+	PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
+	PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+
+	/* PTZ */
+	PINMUX_GPIO(GPIO_PTZ7, PTZ7_DATA),
+	PINMUX_GPIO(GPIO_PTZ6, PTZ6_DATA),
+	PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
+	PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
+	PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
+	PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
+	PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
+	PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+
+	/* BSC */
+	PINMUX_GPIO(GPIO_FN_D31,	D31_MARK),
+	PINMUX_GPIO(GPIO_FN_D30,	D30_MARK),
+	PINMUX_GPIO(GPIO_FN_D29,	D29_MARK),
+	PINMUX_GPIO(GPIO_FN_D28,	D28_MARK),
+	PINMUX_GPIO(GPIO_FN_D27,	D27_MARK),
+	PINMUX_GPIO(GPIO_FN_D26,	D26_MARK),
+	PINMUX_GPIO(GPIO_FN_D25,	D25_MARK),
+	PINMUX_GPIO(GPIO_FN_D24,	D24_MARK),
+	PINMUX_GPIO(GPIO_FN_D23,	D23_MARK),
+	PINMUX_GPIO(GPIO_FN_D22,	D22_MARK),
+	PINMUX_GPIO(GPIO_FN_D21,	D21_MARK),
+	PINMUX_GPIO(GPIO_FN_D20,	D20_MARK),
+	PINMUX_GPIO(GPIO_FN_D19,	D19_MARK),
+	PINMUX_GPIO(GPIO_FN_D18,	D18_MARK),
+	PINMUX_GPIO(GPIO_FN_D17,	D17_MARK),
+	PINMUX_GPIO(GPIO_FN_D16,	D16_MARK),
+	PINMUX_GPIO(GPIO_FN_D15,	D15_MARK),
+	PINMUX_GPIO(GPIO_FN_D14,	D14_MARK),
+	PINMUX_GPIO(GPIO_FN_D13,	D13_MARK),
+	PINMUX_GPIO(GPIO_FN_D12,	D12_MARK),
+	PINMUX_GPIO(GPIO_FN_D11,	D11_MARK),
+	PINMUX_GPIO(GPIO_FN_D10,	D10_MARK),
+	PINMUX_GPIO(GPIO_FN_D9,		D9_MARK),
+	PINMUX_GPIO(GPIO_FN_D8,		D8_MARK),
+	PINMUX_GPIO(GPIO_FN_D7,		D7_MARK),
+	PINMUX_GPIO(GPIO_FN_D6,		D6_MARK),
+	PINMUX_GPIO(GPIO_FN_D5,		D5_MARK),
+	PINMUX_GPIO(GPIO_FN_D4,		D4_MARK),
+	PINMUX_GPIO(GPIO_FN_D3,		D3_MARK),
+	PINMUX_GPIO(GPIO_FN_D2,		D2_MARK),
+	PINMUX_GPIO(GPIO_FN_D1,		D1_MARK),
+	PINMUX_GPIO(GPIO_FN_D0,		D0_MARK),
+	PINMUX_GPIO(GPIO_FN_A25,	A25_MARK),
+	PINMUX_GPIO(GPIO_FN_A24,	A24_MARK),
+	PINMUX_GPIO(GPIO_FN_A23,	A23_MARK),
+	PINMUX_GPIO(GPIO_FN_A22,	A22_MARK),
+	PINMUX_GPIO(GPIO_FN_CS6B_CE1B,	CS6B_CE1B_MARK),
+	PINMUX_GPIO(GPIO_FN_CS6A_CE2B,	CS6A_CE2B_MARK),
+	PINMUX_GPIO(GPIO_FN_CS5B_CE1A,	CS5B_CE1A_MARK),
+	PINMUX_GPIO(GPIO_FN_CS5A_CE2A,	CS5A_CE2A_MARK),
+	PINMUX_GPIO(GPIO_FN_WE3_ICIOWR,	WE3_ICIOWR_MARK),
+	PINMUX_GPIO(GPIO_FN_WE2_ICIORD,	WE2_ICIORD_MARK),
+	PINMUX_GPIO(GPIO_FN_IOIS16,	IOIS16_MARK),
+	PINMUX_GPIO(GPIO_FN_WAIT,	WAIT_MARK),
+	PINMUX_GPIO(GPIO_FN_BS,		BS_MARK),
+
+	/* KEYSC */
+	PINMUX_GPIO(GPIO_FN_KEYOUT5_IN5,	KEYOUT5_IN5_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYOUT4_IN6,	KEYOUT4_IN6_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYIN4,		KEYIN4_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYIN3,		KEYIN3_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYIN2,		KEYIN2_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYIN1,		KEYIN1_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYIN0,		KEYIN0_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYOUT3,		KEYOUT3_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYOUT2,		KEYOUT2_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYOUT1,		KEYOUT1_MARK),
+	PINMUX_GPIO(GPIO_FN_KEYOUT0,		KEYOUT0_MARK),
+
+	/* ATAPI */
+	PINMUX_GPIO(GPIO_FN_IDED15,	IDED15_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED14,	IDED14_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED13,	IDED13_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED12,	IDED12_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED11,	IDED11_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED10,	IDED10_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED9,	IDED9_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED8,	IDED8_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED7,	IDED7_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED6,	IDED6_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED5,	IDED5_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED4,	IDED4_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED3,	IDED3_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED2,	IDED2_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED1,	IDED1_MARK),
+	PINMUX_GPIO(GPIO_FN_IDED0,	IDED0_MARK),
+	PINMUX_GPIO(GPIO_FN_IDEA2,	IDEA2_MARK),
+	PINMUX_GPIO(GPIO_FN_IDEA1,	IDEA1_MARK),
+	PINMUX_GPIO(GPIO_FN_IDEA0,	IDEA0_MARK),
+	PINMUX_GPIO(GPIO_FN_IDEIOWR,	IDEIOWR_MARK),
+	PINMUX_GPIO(GPIO_FN_IODREQ,	IODREQ_MARK),
+	PINMUX_GPIO(GPIO_FN_IDECS0,	IDECS0_MARK),
+	PINMUX_GPIO(GPIO_FN_IDECS1,	IDECS1_MARK),
+	PINMUX_GPIO(GPIO_FN_IDEIORD,	IDEIORD_MARK),
+	PINMUX_GPIO(GPIO_FN_DIRECTION,	DIRECTION_MARK),
+	PINMUX_GPIO(GPIO_FN_EXBUF_ENB,	EXBUF_ENB_MARK),
+	PINMUX_GPIO(GPIO_FN_IDERST,	IDERST_MARK),
+	PINMUX_GPIO(GPIO_FN_IODACK,	IODACK_MARK),
+	PINMUX_GPIO(GPIO_FN_IDEINT,	IDEINT_MARK),
+	PINMUX_GPIO(GPIO_FN_IDEIORDY,	IDEIORDY_MARK),
+
+	/* TPU */
+	PINMUX_GPIO(GPIO_FN_TPUTO3,	TPUTO3_MARK),
+	PINMUX_GPIO(GPIO_FN_TPUTO2,	TPUTO2_MARK),
+	PINMUX_GPIO(GPIO_FN_TPUTO1,	TPUTO1_MARK),
+	PINMUX_GPIO(GPIO_FN_TPUTO0,	TPUTO0_MARK),
+	PINMUX_GPIO(GPIO_FN_TPUTI3,	TPUTI3_MARK),
+	PINMUX_GPIO(GPIO_FN_TPUTI2,	TPUTI2_MARK),
+
+	/* LCDC */
+	PINMUX_GPIO(GPIO_FN_LCDD23,	LCDD23_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD22,	LCDD22_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD21,	LCDD21_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD20,	LCDD20_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD19,	LCDD19_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD18,	LCDD18_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD17,	LCDD17_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD16,	LCDD16_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD15,	LCDD15_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD14,	LCDD14_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD13,	LCDD13_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD12,	LCDD12_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD11,	LCDD11_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD10,	LCDD10_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD9,	LCDD9_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD8,	LCDD8_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD7,	LCDD7_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD6,	LCDD6_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD5,	LCDD5_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD4,	LCDD4_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD3,	LCDD3_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD2,	LCDD2_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD1,	LCDD1_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDD0,	LCDD0_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDVSYN,	LCDVSYN_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDDISP,	LCDDISP_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDRS,	LCDRS_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDHSYN,	LCDHSYN_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDCS,	LCDCS_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDDON,	LCDDON_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDDCK,	LCDDCK_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDWR,	LCDWR_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDVEPWC,	LCDVEPWC_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDVCPWC,	LCDVCPWC_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDRD,	LCDRD_MARK),
+	PINMUX_GPIO(GPIO_FN_LCDLCLK,	LCDLCLK_MARK),
+
+	/* SCIF0 */
+	PINMUX_GPIO(GPIO_FN_SCIF0_TXD,	SCIF0_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF0_RXD,	SCIF0_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF0_SCK,	SCIF0_SCK_MARK),
+
+	/* SCIF1 */
+	PINMUX_GPIO(GPIO_FN_SCIF1_SCK,	SCIF1_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF1_RXD,	SCIF1_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF1_TXD,	SCIF1_TXD_MARK),
+
+	/* SCIF2 */
+	PINMUX_GPIO(GPIO_FN_SCIF2_L_TXD,	SCIF2_L_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF2_L_SCK,	SCIF2_L_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF2_L_RXD,	SCIF2_L_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF2_V_TXD,	SCIF2_V_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF2_V_SCK,	SCIF2_V_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF2_V_RXD,	SCIF2_V_RXD_MARK),
+
+	/* SCIF3 */
+	PINMUX_GPIO(GPIO_FN_SCIF3_V_SCK,	SCIF3_V_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_V_RXD,	SCIF3_V_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_V_TXD,	SCIF3_V_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_V_CTS,	SCIF3_V_CTS_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_V_RTS,	SCIF3_V_RTS_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_I_SCK,	SCIF3_I_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_I_RXD,	SCIF3_I_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_I_TXD,	SCIF3_I_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_I_CTS,	SCIF3_I_CTS_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF3_I_RTS,	SCIF3_I_RTS_MARK),
+
+	/* SCIF4 */
+	PINMUX_GPIO(GPIO_FN_SCIF4_SCK,	SCIF4_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF4_RXD,	SCIF4_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF4_TXD,	SCIF4_TXD_MARK),
+
+	/* SCIF5 */
+	PINMUX_GPIO(GPIO_FN_SCIF5_SCK,	SCIF5_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF5_RXD,	SCIF5_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_SCIF5_TXD,	SCIF5_TXD_MARK),
+
+	/* FSI */
+	PINMUX_GPIO(GPIO_FN_FSIMCKB,	FSIMCKB_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIMCKA,	FSIMCKA_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIOASD,	FSIOASD_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIIABCK,	FSIIABCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIIALRCK,	FSIIALRCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIOABCK,	FSIOABCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIOALRCK,	FSIOALRCK_MARK),
+	PINMUX_GPIO(GPIO_FN_CLKAUDIOAO,	CLKAUDIOAO_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIIBSD,	FSIIBSD_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIOBSD,	FSIOBSD_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIIBBCK,	FSIIBBCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIIBLRCK,	FSIIBLRCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIOBBCK,	FSIOBBCK_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIOBLRCK,	FSIOBLRCK_MARK),
+	PINMUX_GPIO(GPIO_FN_CLKAUDIOBO,	CLKAUDIOBO_MARK),
+	PINMUX_GPIO(GPIO_FN_FSIIASD,	FSIIASD_MARK),
+
+	/* AUD */
+	PINMUX_GPIO(GPIO_FN_AUDCK,	AUDCK_MARK),
+	PINMUX_GPIO(GPIO_FN_AUDSYNC,	AUDSYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_AUDATA3,	AUDATA3_MARK),
+	PINMUX_GPIO(GPIO_FN_AUDATA2,	AUDATA2_MARK),
+	PINMUX_GPIO(GPIO_FN_AUDATA1,	AUDATA1_MARK),
+	PINMUX_GPIO(GPIO_FN_AUDATA0,	AUDATA0_MARK),
+
+	/* VIO */
+	PINMUX_GPIO(GPIO_FN_VIO_CKO,	VIO_CKO_MARK),
+
+	/* VIO0 */
+	PINMUX_GPIO(GPIO_FN_VIO0_D15,	VIO0_D15_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D14,	VIO0_D14_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D13,	VIO0_D13_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D12,	VIO0_D12_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D11,	VIO0_D11_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D10,	VIO0_D10_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D9,	VIO0_D9_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D8,	VIO0_D8_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D7,	VIO0_D7_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D6,	VIO0_D6_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D5,	VIO0_D5_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D4,	VIO0_D4_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D3,	VIO0_D3_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D2,	VIO0_D2_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D1,	VIO0_D1_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_D0,	VIO0_D0_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_VD,	VIO0_VD_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_CLK,	VIO0_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_FLD,	VIO0_FLD_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO0_HD,	VIO0_HD_MARK),
+
+	/* VIO1 */
+	PINMUX_GPIO(GPIO_FN_VIO1_D7,	VIO1_D7_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_D6,	VIO1_D6_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_D5,	VIO1_D5_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_D4,	VIO1_D4_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_D3,	VIO1_D3_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_D2,	VIO1_D2_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_D1,	VIO1_D1_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_D0,	VIO1_D0_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_FLD,	VIO1_FLD_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_HD,	VIO1_HD_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_VD,	VIO1_VD_MARK),
+	PINMUX_GPIO(GPIO_FN_VIO1_CLK,	VIO1_CLK_MARK),
+
+	/* Eth */
+	PINMUX_GPIO(GPIO_FN_RMII_RXD0,		RMII_RXD0_MARK),
+	PINMUX_GPIO(GPIO_FN_RMII_RXD1,		RMII_RXD1_MARK),
+	PINMUX_GPIO(GPIO_FN_RMII_TXD0,		RMII_TXD0_MARK),
+	PINMUX_GPIO(GPIO_FN_RMII_TXD1,		RMII_TXD1_MARK),
+	PINMUX_GPIO(GPIO_FN_RMII_REF_CLK,	RMII_REF_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_RMII_TX_EN,		RMII_TX_EN_MARK),
+	PINMUX_GPIO(GPIO_FN_RMII_RX_ER,		RMII_RX_ER_MARK),
+	PINMUX_GPIO(GPIO_FN_RMII_CRS_DV,	RMII_CRS_DV_MARK),
+	PINMUX_GPIO(GPIO_FN_LNKSTA,		LNKSTA_MARK),
+	PINMUX_GPIO(GPIO_FN_MDIO,		MDIO_MARK),
+	PINMUX_GPIO(GPIO_FN_MDC,		MDC_MARK),
+
+	/* System */
+	PINMUX_GPIO(GPIO_FN_PDSTATUS,	PDSTATUS_MARK),
+	PINMUX_GPIO(GPIO_FN_STATUS2,	STATUS2_MARK),
+	PINMUX_GPIO(GPIO_FN_STATUS0,	STATUS0_MARK),
+
+	/* VOU */
+	PINMUX_GPIO(GPIO_FN_DV_D15,	DV_D15_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D14,	DV_D14_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D13,	DV_D13_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D12,	DV_D12_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D11,	DV_D11_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D10,	DV_D10_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D9,	DV_D9_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D8,	DV_D8_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D7,	DV_D7_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D6,	DV_D6_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D5,	DV_D5_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D4,	DV_D4_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D3,	DV_D3_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D2,	DV_D2_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D1,	DV_D1_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_D0,	DV_D0_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_CLKI,	DV_CLKI_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_CLK,	DV_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_VSYNC,	DV_VSYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_DV_HSYNC,	DV_HSYNC_MARK),
+
+	/* MSIOF0 */
+	PINMUX_GPIO(GPIO_FN_MSIOF0_RXD,		MSIOF0_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_TXD,		MSIOF0_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_MCK,		MSIOF0_MCK_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_TSCK,	MSIOF0_TSCK_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_SS1,		MSIOF0_SS1_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_SS2,		MSIOF0_SS2_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_TSYNC,	MSIOF0_TSYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_RSCK,	MSIOF0_RSCK_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF0_RSYNC,	MSIOF0_RSYNC_MARK),
+
+	/* MSIOF1 */
+	PINMUX_GPIO(GPIO_FN_MSIOF1_RXD,		MSIOF1_RXD_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_TXD,		MSIOF1_TXD_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_MCK,		MSIOF1_MCK_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_TSCK,	MSIOF1_TSCK_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_SS1,		MSIOF1_SS1_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_SS2,		MSIOF1_SS2_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_TSYNC,	MSIOF1_TSYNC_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_RSCK,	MSIOF1_RSCK_MARK),
+	PINMUX_GPIO(GPIO_FN_MSIOF1_RSYNC,	MSIOF1_RSYNC_MARK),
+
+	/* DMAC */
+	PINMUX_GPIO(GPIO_FN_DMAC_DACK0,	DMAC_DACK0_MARK),
+	PINMUX_GPIO(GPIO_FN_DMAC_DREQ0,	DMAC_DREQ0_MARK),
+	PINMUX_GPIO(GPIO_FN_DMAC_DACK1,	DMAC_DACK1_MARK),
+	PINMUX_GPIO(GPIO_FN_DMAC_DREQ1,	DMAC_DREQ1_MARK),
+
+	/* SDHI0 */
+	PINMUX_GPIO(GPIO_FN_SDHI0CD,	SDHI0CD_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI0WP,	SDHI0WP_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI0CMD,	SDHI0CMD_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI0CLK,	SDHI0CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI0D3,	SDHI0D3_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI0D2,	SDHI0D2_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI0D1,	SDHI0D1_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI0D0,	SDHI0D0_MARK),
+
+	/* SDHI1 */
+	PINMUX_GPIO(GPIO_FN_SDHI1CD,	SDHI1CD_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI1WP,	SDHI1WP_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI1CMD,	SDHI1CMD_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI1CLK,	SDHI1CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI1D3,	SDHI1D3_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI1D2,	SDHI1D2_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI1D1,	SDHI1D1_MARK),
+	PINMUX_GPIO(GPIO_FN_SDHI1D0,	SDHI1D0_MARK),
+
+	/* MMC */
+	PINMUX_GPIO(GPIO_FN_MMC_D7,	MMC_D7_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_D6,	MMC_D6_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_D5,	MMC_D5_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_D4,	MMC_D4_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_D3,	MMC_D3_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_D2,	MMC_D2_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_D1,	MMC_D1_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_D0,	MMC_D0_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_CLK,	MMC_CLK_MARK),
+	PINMUX_GPIO(GPIO_FN_MMC_CMD,	MMC_CMD_MARK),
+
+	/* IrDA */
+	PINMUX_GPIO(GPIO_FN_IRDA_OUT,	IRDA_OUT_MARK),
+	PINMUX_GPIO(GPIO_FN_IRDA_IN,	IRDA_IN_MARK),
+
+	/* TSIF */
+	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SDAT,	TSIF_TS0_SDAT_MARK),
+	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SCK,	TSIF_TS0_SCK_MARK),
+	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SDEN,	TSIF_TS0_SDEN_MARK),
+	PINMUX_GPIO(GPIO_FN_TSIF_TS0_SPSYNC,	TSIF_TS0_SPSYNC_MARK),
+
+	/* IRQ */
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ7,	INTC_IRQ7_MARK),
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ6,	INTC_IRQ6_MARK),
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ5,	INTC_IRQ5_MARK),
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ4,	INTC_IRQ4_MARK),
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ3,	INTC_IRQ3_MARK),
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ2,	INTC_IRQ2_MARK),
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ1,	INTC_IRQ1_MARK),
+	PINMUX_GPIO(GPIO_FN_INTC_IRQ0,	INTC_IRQ0_MARK),
+ };
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+	{ PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
+		PTA7_FN, PTA7_OUT, PTA7_IN_PU, PTA7_IN,
+		PTA6_FN, PTA6_OUT, PTA6_IN_PU, PTA6_IN,
+		PTA5_FN, PTA5_OUT, PTA5_IN_PU, PTA5_IN,
+		PTA4_FN, PTA4_OUT, PTA4_IN_PU, PTA4_IN,
+		PTA3_FN, PTA3_OUT, PTA3_IN_PU, PTA3_IN,
+		PTA2_FN, PTA2_OUT, PTA2_IN_PU, PTA2_IN,
+		PTA1_FN, PTA1_OUT, PTA1_IN_PU, PTA1_IN,
+		PTA0_FN, PTA0_OUT, PTA0_IN_PU, PTA0_IN }
+	},
+	{ PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
+		PTB7_FN, PTB7_OUT, PTB7_IN_PU, PTB7_IN,
+		PTB6_FN, PTB6_OUT, PTB6_IN_PU, PTB6_IN,
+		PTB5_FN, PTB5_OUT, PTB5_IN_PU, PTB5_IN,
+		PTB4_FN, PTB4_OUT, PTB4_IN_PU, PTB4_IN,
+		PTB3_FN, PTB3_OUT, PTB3_IN_PU, PTB3_IN,
+		PTB2_FN, PTB2_OUT, PTB2_IN_PU, PTB2_IN,
+		PTB1_FN, PTB1_OUT, PTB1_IN_PU, PTB1_IN,
+		PTB0_FN, PTB0_OUT, PTB0_IN_PU, PTB0_IN }
+	},
+	{ PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
+		PTC7_FN, PTC7_OUT, PTC7_IN_PU, PTC7_IN,
+		PTC6_FN, PTC6_OUT, PTC6_IN_PU, PTC6_IN,
+		PTC5_FN, PTC5_OUT, PTC5_IN_PU, PTC5_IN,
+		PTC4_FN, PTC4_OUT, PTC4_IN_PU, PTC4_IN,
+		PTC3_FN, PTC3_OUT, PTC3_IN_PU, PTC3_IN,
+		PTC2_FN, PTC2_OUT, PTC2_IN_PU, PTC2_IN,
+		PTC1_FN, PTC1_OUT, PTC1_IN_PU, PTC1_IN,
+		PTC0_FN, PTC0_OUT, PTC0_IN_PU, PTC0_IN }
+	},
+	{ PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
+		PTD7_FN, PTD7_OUT, PTD7_IN_PU, PTD7_IN,
+		PTD6_FN, PTD6_OUT, PTD6_IN_PU, PTD6_IN,
+		PTD5_FN, PTD5_OUT, PTD5_IN_PU, PTD5_IN,
+		PTD4_FN, PTD4_OUT, PTD4_IN_PU, PTD4_IN,
+		PTD3_FN, PTD3_OUT, PTD3_IN_PU, PTD3_IN,
+		PTD2_FN, PTD2_OUT, PTD2_IN_PU, PTD2_IN,
+		PTD1_FN, PTD1_OUT, PTD1_IN_PU, PTD1_IN,
+		PTD0_FN, PTD0_OUT, PTD0_IN_PU, PTD0_IN }
+	},
+	{ PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
+		PTE7_FN, PTE7_OUT, PTE7_IN_PU, PTE7_IN,
+		PTE6_FN, PTE6_OUT, PTE6_IN_PU, PTE6_IN,
+		PTE5_FN, PTE5_OUT, PTE5_IN_PU, PTE5_IN,
+		PTE4_FN, PTE4_OUT, PTE4_IN_PU, PTE4_IN,
+		PTE3_FN, PTE3_OUT, PTE3_IN_PU, PTE3_IN,
+		PTE2_FN, PTE2_OUT, PTE2_IN_PU, PTE2_IN,
+		PTE1_FN, PTE1_OUT, PTE1_IN_PU, PTE1_IN,
+		PTE0_FN, PTE0_OUT, PTE0_IN_PU, PTE0_IN }
+	},
+	{ PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
+		PTF7_FN, PTF7_OUT, PTF7_IN_PU, PTF7_IN,
+		PTF6_FN, PTF6_OUT, PTF6_IN_PU, PTF6_IN,
+		PTF5_FN, PTF5_OUT, PTF5_IN_PU, PTF5_IN,
+		PTF4_FN, PTF4_OUT, PTF4_IN_PU, PTF4_IN,
+		PTF3_FN, PTF3_OUT, PTF3_IN_PU, PTF3_IN,
+		PTF2_FN, PTF2_OUT, PTF2_IN_PU, PTF2_IN,
+		PTF1_FN, PTF1_OUT, PTF1_IN_PU, PTF1_IN,
+		PTF0_FN, PTF0_OUT, PTF0_IN_PU, PTF0_IN }
+	},
+	{ PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
+		0, 0, 0, 0,
+		0, 0, 0, 0,
+		PTG5_FN, PTG5_OUT, 0, 0,
+		PTG4_FN, PTG4_OUT, 0, 0,
+		PTG3_FN, PTG3_OUT, 0, 0,
+		PTG2_FN, PTG2_OUT, 0, 0,
+		PTG1_FN, PTG1_OUT, 0, 0,
+		PTG0_FN, PTG0_OUT, 0, 0 }
+	},
+	{ PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
+		PTH7_FN, PTH7_OUT, PTH7_IN_PU, PTH7_IN,
+		PTH6_FN, PTH6_OUT, PTH6_IN_PU, PTH6_IN,
+		PTH5_FN, PTH5_OUT, PTH5_IN_PU, PTH5_IN,
+		PTH4_FN, PTH4_OUT, PTH4_IN_PU, PTH4_IN,
+		PTH3_FN, PTH3_OUT, PTH3_IN_PU, PTH3_IN,
+		PTH2_FN, PTH2_OUT, PTH2_IN_PU, PTH2_IN,
+		PTH1_FN, PTH1_OUT, PTH1_IN_PU, PTH1_IN,
+		PTH0_FN, PTH0_OUT, PTH0_IN_PU, PTH0_IN }
+	},
+	{ PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
+		PTJ7_FN, PTJ7_OUT, 0, 0,
+		PTJ6_FN, PTJ6_OUT, 0, 0,
+		PTJ5_FN, PTJ5_OUT, 0, 0,
+		0, 0, 0, 0,
+		PTJ3_FN, PTJ3_OUT, PTJ3_IN_PU, PTJ3_IN,
+		PTJ2_FN, PTJ2_OUT, PTJ2_IN_PU, PTJ2_IN,
+		PTJ1_FN, PTJ1_OUT, PTJ1_IN_PU, PTJ1_IN,
+		PTJ0_FN, PTJ0_OUT, PTJ0_IN_PU, PTJ0_IN }
+	},
+	{ PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
+		PTK7_FN, PTK7_OUT, PTK7_IN_PU, PTK7_IN,
+		PTK6_FN, PTK6_OUT, PTK6_IN_PU, PTK6_IN,
+		PTK5_FN, PTK5_OUT, PTK5_IN_PU, PTK5_IN,
+		PTK4_FN, PTK4_OUT, PTK4_IN_PU, PTK4_IN,
+		PTK3_FN, PTK3_OUT, PTK3_IN_PU, PTK3_IN,
+		PTK2_FN, PTK2_OUT, PTK2_IN_PU, PTK2_IN,
+		PTK1_FN, PTK1_OUT, PTK1_IN_PU, PTK1_IN,
+		PTK0_FN, PTK0_OUT, PTK0_IN_PU, PTK0_IN }
+	},
+	{ PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
+		PTL7_FN, PTL7_OUT, PTL7_IN_PU, PTL7_IN,
+		PTL6_FN, PTL6_OUT, PTL6_IN_PU, PTL6_IN,
+		PTL5_FN, PTL5_OUT, PTL5_IN_PU, PTL5_IN,
+		PTL4_FN, PTL4_OUT, PTL4_IN_PU, PTL4_IN,
+		PTL3_FN, PTL3_OUT, PTL3_IN_PU, PTL3_IN,
+		PTL2_FN, PTL2_OUT, PTL2_IN_PU, PTL2_IN,
+		PTL1_FN, PTL1_OUT, PTL1_IN_PU, PTL1_IN,
+		PTL0_FN, PTL0_OUT, PTL0_IN_PU, PTL0_IN }
+	},
+	{ PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
+		PTM7_FN, PTM7_OUT, PTM7_IN_PU, PTM7_IN,
+		PTM6_FN, PTM6_OUT, PTM6_IN_PU, PTM6_IN,
+		PTM5_FN, PTM5_OUT, PTM5_IN_PU, PTM5_IN,
+		PTM4_FN, PTM4_OUT, PTM4_IN_PU, PTM4_IN,
+		PTM3_FN, PTM3_OUT, PTM3_IN_PU, PTM3_IN,
+		PTM2_FN, PTM2_OUT, PTM2_IN_PU, PTM2_IN,
+		PTM1_FN, PTM1_OUT, PTM1_IN_PU, PTM1_IN,
+		PTM0_FN, PTM0_OUT, PTM0_IN_PU, PTM0_IN }
+	},
+	{ PINMUX_CFG_REG("PNCR", 0xa4050118, 16, 2) {
+		PTN7_FN, PTN7_OUT, PTN7_IN_PU, PTN7_IN,
+		PTN6_FN, PTN6_OUT, PTN6_IN_PU, PTN6_IN,
+		PTN5_FN, PTN5_OUT, PTN5_IN_PU, PTN5_IN,
+		PTN4_FN, PTN4_OUT, PTN4_IN_PU, PTN4_IN,
+		PTN3_FN, PTN3_OUT, PTN3_IN_PU, PTN3_IN,
+		PTN2_FN, PTN2_OUT, PTN2_IN_PU, PTN2_IN,
+		PTN1_FN, PTN1_OUT, PTN1_IN_PU, PTN1_IN,
+		PTN0_FN, PTN0_OUT, PTN0_IN_PU, PTN0_IN }
+	},
+	{ PINMUX_CFG_REG("PQCR", 0xa405011a, 16, 2) {
+		PTQ7_FN, PTQ7_OUT, PTQ7_IN_PU, PTQ7_IN,
+		PTQ6_FN, PTQ6_OUT, PTQ6_IN_PU, PTQ6_IN,
+		PTQ5_FN, PTQ5_OUT, PTQ5_IN_PU, PTQ5_IN,
+		PTQ4_FN, PTQ4_OUT, PTQ4_IN_PU, PTQ4_IN,
+		PTQ3_FN, PTQ3_OUT, PTQ3_IN_PU, PTQ3_IN,
+		PTQ2_FN, PTQ2_OUT, PTQ2_IN_PU, PTQ2_IN,
+		PTQ1_FN, PTQ1_OUT, PTQ1_IN_PU, PTQ1_IN,
+		PTQ0_FN, PTQ0_OUT, PTQ0_IN_PU, PTQ0_IN }
+	},
+	{ PINMUX_CFG_REG("PRCR", 0xa405011c, 16, 2) {
+		PTR7_FN, PTR7_OUT, PTR7_IN_PU, PTR7_IN,
+		PTR6_FN, PTR6_OUT, PTR6_IN_PU, PTR6_IN,
+		PTR5_FN, PTR5_OUT, PTR5_IN_PU, PTR5_IN,
+		PTR4_FN, PTR4_OUT, PTR4_IN_PU, PTR4_IN,
+		PTR3_FN, 0,        PTR3_IN_PU, PTR3_IN,
+		PTR2_FN, 0,        PTR2_IN_PU, PTR2_IN,
+		PTR1_FN, PTR1_OUT, PTR1_IN_PU, PTR1_IN,
+		PTR0_FN, PTR0_OUT, PTR0_IN_PU, PTR0_IN }
+	},
+	{ PINMUX_CFG_REG("PSCR", 0xa405011e, 16, 2) {
+		0, 0, 0, 0,
+		PTS6_FN, PTS6_OUT, PTS6_IN_PU, PTS6_IN,
+		PTS5_FN, PTS5_OUT, PTS5_IN_PU, PTS5_IN,
+		PTS4_FN, PTS4_OUT, PTS4_IN_PU, PTS4_IN,
+		PTS3_FN, PTS3_OUT, PTS3_IN_PU, PTS3_IN,
+		PTS2_FN, PTS2_OUT, PTS2_IN_PU, PTS2_IN,
+		PTS1_FN, PTS1_OUT, PTS1_IN_PU, PTS1_IN,
+		PTS0_FN, PTS0_OUT, PTS0_IN_PU, PTS0_IN }
+	},
+	{ PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2) {
+		PTT7_FN, PTT7_OUT, PTT7_IN_PU, PTT7_IN,
+		PTT6_FN, PTT6_OUT, PTT6_IN_PU, PTT6_IN,
+		PTT5_FN, PTT5_OUT, PTT5_IN_PU, PTT5_IN,
+		PTT4_FN, PTT4_OUT, PTT4_IN_PU, PTT4_IN,
+		PTT3_FN, PTT3_OUT, PTT3_IN_PU, PTT3_IN,
+		PTT2_FN, PTT2_OUT, PTT2_IN_PU, PTT2_IN,
+		PTT1_FN, PTT1_OUT, PTT1_IN_PU, PTT1_IN,
+		PTT0_FN, PTT0_OUT, PTT0_IN_PU, PTT0_IN }
+	},
+	{ PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2) {
+		PTU7_FN, PTU7_OUT, PTU7_IN_PU, PTU7_IN,
+		PTU6_FN, PTU6_OUT, PTU6_IN_PU, PTU6_IN,
+		PTU5_FN, PTU5_OUT, PTU5_IN_PU, PTU5_IN,
+		PTU4_FN, PTU4_OUT, PTU4_IN_PU, PTU4_IN,
+		PTU3_FN, PTU3_OUT, PTU3_IN_PU, PTU3_IN,
+		PTU2_FN, PTU2_OUT, PTU2_IN_PU, PTU2_IN,
+		PTU1_FN, PTU1_OUT, PTU1_IN_PU, PTU1_IN,
+		PTU0_FN, PTU0_OUT, PTU0_IN_PU, PTU0_IN }
+	},
+	{ PINMUX_CFG_REG("PVCR", 0xa4050144, 16, 2) {
+		PTV7_FN, PTV7_OUT, PTV7_IN_PU, PTV7_IN,
+		PTV6_FN, PTV6_OUT, PTV6_IN_PU, PTV6_IN,
+		PTV5_FN, PTV5_OUT, PTV5_IN_PU, PTV5_IN,
+		PTV4_FN, PTV4_OUT, PTV4_IN_PU, PTV4_IN,
+		PTV3_FN, PTV3_OUT, PTV3_IN_PU, PTV3_IN,
+		PTV2_FN, PTV2_OUT, PTV2_IN_PU, PTV2_IN,
+		PTV1_FN, PTV1_OUT, PTV1_IN_PU, PTV1_IN,
+		PTV0_FN, PTV0_OUT, PTV0_IN_PU, PTV0_IN }
+	},
+	{ PINMUX_CFG_REG("PWCR", 0xa4050146, 16, 2) {
+		PTW7_FN, PTW7_OUT, PTW7_IN_PU, PTW7_IN,
+		PTW6_FN, PTW6_OUT, PTW6_IN_PU, PTW6_IN,
+		PTW5_FN, PTW5_OUT, PTW5_IN_PU, PTW5_IN,
+		PTW4_FN, PTW4_OUT, PTW4_IN_PU, PTW4_IN,
+		PTW3_FN, PTW3_OUT, PTW3_IN_PU, PTW3_IN,
+		PTW2_FN, PTW2_OUT, PTW2_IN_PU, PTW2_IN,
+		PTW1_FN, PTW1_OUT, PTW1_IN_PU, PTW1_IN,
+		PTW0_FN, PTW0_OUT, PTW0_IN_PU, PTW0_IN }
+	},
+	{ PINMUX_CFG_REG("PXCR", 0xa4050148, 16, 2) {
+		PTX7_FN, PTX7_OUT, PTX7_IN_PU, PTX7_IN,
+		PTX6_FN, PTX6_OUT, PTX6_IN_PU, PTX6_IN,
+		PTX5_FN, PTX5_OUT, PTX5_IN_PU, PTX5_IN,
+		PTX4_FN, PTX4_OUT, PTX4_IN_PU, PTX4_IN,
+		PTX3_FN, PTX3_OUT, PTX3_IN_PU, PTX3_IN,
+		PTX2_FN, PTX2_OUT, PTX2_IN_PU, PTX2_IN,
+		PTX1_FN, PTX1_OUT, PTX1_IN_PU, PTX1_IN,
+		PTX0_FN, PTX0_OUT, PTX0_IN_PU, PTX0_IN }
+	},
+	{ PINMUX_CFG_REG("PYCR", 0xa405014a, 16, 2) {
+		PTY7_FN, PTY7_OUT, PTY7_IN_PU, PTY7_IN,
+		PTY6_FN, PTY6_OUT, PTY6_IN_PU, PTY6_IN,
+		PTY5_FN, PTY5_OUT, PTY5_IN_PU, PTY5_IN,
+		PTY4_FN, PTY4_OUT, PTY4_IN_PU, PTY4_IN,
+		PTY3_FN, PTY3_OUT, PTY3_IN_PU, PTY3_IN,
+		PTY2_FN, PTY2_OUT, PTY2_IN_PU, PTY2_IN,
+		PTY1_FN, PTY1_OUT, PTY1_IN_PU, PTY1_IN,
+		PTY0_FN, PTY0_OUT, PTY0_IN_PU, PTY0_IN }
+	},
+	{ PINMUX_CFG_REG("PZCR", 0xa405014c, 16, 2) {
+		PTZ7_FN, PTZ7_OUT, PTZ7_IN_PU, PTZ7_IN,
+		PTZ6_FN, PTZ6_OUT, PTZ6_IN_PU, PTZ6_IN,
+		PTZ5_FN, PTZ5_OUT, PTZ5_IN_PU, PTZ5_IN,
+		PTZ4_FN, PTZ4_OUT, PTZ4_IN_PU, PTZ4_IN,
+		PTZ3_FN, PTZ3_OUT, PTZ3_IN_PU, PTZ3_IN,
+		PTZ2_FN, PTZ2_OUT, PTZ2_IN_PU, PTZ2_IN,
+		PTZ1_FN, PTZ1_OUT, PTZ1_IN_PU, PTZ1_IN,
+		PTZ0_FN, PTZ0_OUT, PTZ0_IN_PU, PTZ0_IN }
+	},
+	{ PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 1) {
+		PSA15_0, PSA15_1,
+		PSA14_0, PSA14_1,
+		PSA13_0, PSA13_1,
+		PSA12_0, PSA12_1,
+		0, 0,
+		PSA10_0, PSA10_1,
+		PSA9_0,  PSA9_1,
+		PSA8_0,  PSA8_1,
+		PSA7_0,  PSA7_1,
+		PSA6_0,  PSA6_1,
+		PSA5_0,  PSA5_1,
+		0, 0,
+		PSA3_0,  PSA3_1,
+		PSA2_0,  PSA2_1,
+		PSA1_0,  PSA1_1,
+		PSA0_0,  PSA0_1}
+	},
+	{ PINMUX_CFG_REG("PSELB", 0xa4050150, 16, 1) {
+		0, 0,
+		PSB14_0, PSB14_1,
+		PSB13_0, PSB13_1,
+		PSB12_0, PSB12_1,
+		PSB11_0, PSB11_1,
+		PSB10_0, PSB10_1,
+		PSB9_0,  PSB9_1,
+		PSB8_0,  PSB8_1,
+		PSB7_0,  PSB7_1,
+		PSB6_0,  PSB6_1,
+		PSB5_0,  PSB5_1,
+		PSB4_0,  PSB4_1,
+		PSB3_0,  PSB3_1,
+		PSB2_0,  PSB2_1,
+		PSB1_0,  PSB1_1,
+		PSB0_0,  PSB0_1}
+	},
+	{ PINMUX_CFG_REG("PSELC", 0xa4050152, 16, 1) {
+		PSC15_0, PSC15_1,
+		PSC14_0, PSC14_1,
+		PSC13_0, PSC13_1,
+		PSC12_0, PSC12_1,
+		PSC11_0, PSC11_1,
+		PSC10_0, PSC10_1,
+		PSC9_0,  PSC9_1,
+		PSC8_0,  PSC8_1,
+		PSC7_0,  PSC7_1,
+		PSC6_0,  PSC6_1,
+		PSC5_0,  PSC5_1,
+		PSC4_0,  PSC4_1,
+		0, 0,
+		PSC2_0,  PSC2_1,
+		PSC1_0,  PSC1_1,
+		PSC0_0,  PSC0_1}
+	},
+	{ PINMUX_CFG_REG("PSELD", 0xa4050154, 16, 1) {
+		PSD15_0, PSD15_1,
+		PSD14_0, PSD14_1,
+		PSD13_0, PSD13_1,
+		PSD12_0, PSD12_1,
+		PSD11_0, PSD11_1,
+		PSD10_0, PSD10_1,
+		PSD9_0,  PSD9_1,
+		PSD8_0,  PSD8_1,
+		PSD7_0,  PSD7_1,
+		PSD6_0,  PSD6_1,
+		PSD5_0,  PSD5_1,
+		PSD4_0,  PSD4_1,
+		PSD3_0,  PSD3_1,
+		PSD2_0,  PSD2_1,
+		PSD1_0,  PSD1_1,
+		PSD0_0,  PSD0_1}
+	},
+	{ PINMUX_CFG_REG("PSELE", 0xa4050156, 16, 1) {
+		PSE15_0, PSE15_1,
+		PSE14_0, PSE14_1,
+		PSE13_0, PSE13_1,
+		PSE12_0, PSE12_1,
+		PSE11_0, PSE11_1,
+		PSE10_0, PSE10_1,
+		PSE9_0,  PSE9_1,
+		PSE8_0,  PSE8_1,
+		PSE7_0,  PSE7_1,
+		PSE6_0,  PSE6_1,
+		PSE5_0,  PSE5_1,
+		PSE4_0,  PSE4_1,
+		PSE3_0,  PSE3_1,
+		PSE2_0,  PSE2_1,
+		PSE1_0,  PSE1_1,
+		PSE0_0,  PSE0_1}
+	},
+	{}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+	{ PINMUX_DATA_REG("PADR", 0xa4050120, 8) {
+		PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+		PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
+	},
+	{ PINMUX_DATA_REG("PBDR", 0xa4050122, 8) {
+		PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+		PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA }
+	},
+	{ PINMUX_DATA_REG("PCDR", 0xa4050124, 8) {
+		PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+		PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA }
+	},
+	{ PINMUX_DATA_REG("PDDR", 0xa4050126, 8) {
+		PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+		PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA }
+	},
+	{ PINMUX_DATA_REG("PEDR", 0xa4050128, 8) {
+		PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+		PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA }
+	},
+	{ PINMUX_DATA_REG("PFDR", 0xa405012a, 8) {
+		PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+		PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA }
+	},
+	{ PINMUX_DATA_REG("PGDR", 0xa405012c, 8) {
+		0,         0,         PTG5_DATA, PTG4_DATA,
+		PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA }
+	},
+	{ PINMUX_DATA_REG("PHDR", 0xa405012e, 8) {
+		PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+		PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA }
+	},
+	{ PINMUX_DATA_REG("PJDR", 0xa4050130, 8) {
+		PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, 0,
+		PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA }
+	},
+	{ PINMUX_DATA_REG("PKDR", 0xa4050132, 8) {
+		PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+		PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
+	},
+	{ PINMUX_DATA_REG("PLDR", 0xa4050134, 8) {
+		PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+		PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA }
+	},
+	{ PINMUX_DATA_REG("PMDR", 0xa4050136, 8) {
+		PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+		PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
+	},
+	{ PINMUX_DATA_REG("PNDR", 0xa4050138, 8) {
+		PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+		PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA }
+	},
+	{ PINMUX_DATA_REG("PQDR", 0xa405013a, 8) {
+		PTQ7_DATA, PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+		PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA }
+	},
+	{ PINMUX_DATA_REG("PRDR", 0xa405013c, 8) {
+		PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+		PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA }
+	},
+	{ PINMUX_DATA_REG("PSDR", 0xa405013e, 8) {
+		0,         PTS6_DATA, PTS5_DATA, PTS4_DATA,
+		PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
+	},
+	{ PINMUX_DATA_REG("PTDR", 0xa4050160, 8) {
+		PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
+		PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
+	},
+	{ PINMUX_DATA_REG("PUDR", 0xa4050162, 8) {
+		PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
+		PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA }
+	},
+	{ PINMUX_DATA_REG("PVDR", 0xa4050164, 8) {
+		PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+		PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA }
+	},
+	{ PINMUX_DATA_REG("PWDR", 0xa4050166, 8) {
+		PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+		PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA }
+	},
+	{ PINMUX_DATA_REG("PXDR", 0xa4050168, 8) {
+		PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+		PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA }
+	},
+	{ PINMUX_DATA_REG("PYDR", 0xa405016a, 8) {
+		PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+		PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA }
+	},
+	{ PINMUX_DATA_REG("PZDR", 0xa405016c, 8) {
+		PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+		PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA }
+	},
+	{ },
+};
+
+static struct pinmux_info sh7724_pinmux_info = {
+	.name = "sh7724_pfc",
+	.reserved_id = PINMUX_RESERVED,
+	.data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+	.input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+	.input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+	.output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+	.mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+	.first_gpio = GPIO_PTA7,
+	.last_gpio = GPIO_FN_INTC_IRQ0,
+
+	.gpios = pinmux_gpios,
+	.cfg_regs = pinmux_config_regs,
+	.data_regs = pinmux_data_regs,
+
+	.gpio_data = pinmux_data,
+	.gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+	return register_pinmux(&sh7724_pinmux_info);
+}
+arch_initcall(plat_pinmux_setup);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7343.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7343.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7343.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
 #include <asm/clock.h>
 
 static struct resource iic0_resources[] = {
@@ -141,7 +141,7 @@
 	.num_resources	= ARRAY_SIZE(jpu_resources),
 };
 
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
 	.name = "CMT",
 	.channel_offset = 0x60,
 	.timer_bit = 5,
@@ -173,27 +173,123 @@
 	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu0",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu0",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu0",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 80, 80, 80, 80 },
+		.clk		= "scif0",
 	}, {
 		.mapbase	= 0xffe10000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 81, 81, 81, 81 },
+		.clk		= "scif1",
 	}, {
 		.mapbase	= 0xffe20000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 82, 82, 82, 82 },
+		.clk		= "scif2",
 	}, {
 		.mapbase	= 0xffe30000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 83, 83, 83, 83 },
+		.clk		= "scif3",
 	}, {
 		.flags = 0,
 	}
@@ -209,6 +305,9 @@
 
 static struct platform_device *sh7343_devices[] __initdata = {
 	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 	&iic0_device,
 	&iic1_device,
 	&sci_device,
@@ -219,12 +318,6 @@
 
 static int __init sh7343_devices_setup(void)
 {
-	clk_always_enable("uram0"); /* URAM */
-	clk_always_enable("xymem0"); /* XYMEM */
-	clk_always_enable("veu0"); /* VEU */
-	clk_always_enable("vpu0"); /* VPU */
-	clk_always_enable("jpu0"); /* JPU */
-
 	platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
 	platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
 	platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20);
@@ -232,7 +325,20 @@
 	return platform_add_devices(sh7343_devices,
 				    ARRAY_SIZE(sh7343_devices));
 }
-__initcall(sh7343_devices_setup);
+arch_initcall(sh7343_devices_setup);
+
+static struct platform_device *sh7343_early_devices[] __initdata = {
+	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7343_early_devices,
+				   ARRAY_SIZE(sh7343_early_devices));
+}
 
 enum {
 	UNUSED = 0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7366.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7366.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7366.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,7 +14,8 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
+#include <linux/usb/r8a66597.h>
 #include <asm/clock.h>
 
 static struct resource iic_resources[] = {
@@ -38,18 +39,20 @@
 	.resource       = iic_resources,
 };
 
+static struct r8a66597_platdata r8a66597_data = {
+	/* This set zero to all members */
+};
+
 static struct resource usb_host_resources[] = {
 	[0] = {
-		.name   = "r8a66597_hcd",
 		.start  = 0xa4d80000,
 		.end    = 0xa4d800ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.name   = "r8a66597_hcd",
 		.start  = 65,
 		.end    = 65,
-		.flags  = IORESOURCE_IRQ,
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
 	},
 };
 
@@ -59,6 +62,7 @@
 	.dev = {
 		.dma_mask		= NULL,
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &r8a66597_data,
 	},
 	.num_resources	= ARRAY_SIZE(usb_host_resources),
 	.resource	= usb_host_resources,
@@ -148,7 +152,7 @@
 	.num_resources	= ARRAY_SIZE(veu1_resources),
 };
 
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
 	.name = "CMT",
 	.channel_offset = 0x60,
 	.timer_bit = 5,
@@ -180,12 +184,105 @@
 	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu0",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu0",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu0",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 80, 80, 80, 80 },
+		.clk		= "scif0",
 	}, {
 		.flags = 0,
 	}
@@ -201,6 +298,9 @@
 
 static struct platform_device *sh7366_devices[] __initdata = {
 	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 	&iic_device,
 	&sci_device,
 	&usb_host_device,
@@ -211,12 +311,6 @@
 
 static int __init sh7366_devices_setup(void)
 {
-	clk_always_enable("rsmem0"); /* RSMEM */
-	clk_always_enable("xymem0"); /* XYMEM */
-	clk_always_enable("veu1"); /* VEU-2 */
-	clk_always_enable("veu0"); /* VEU-1 */
-	clk_always_enable("vpu0"); /* VPU */
-
 	platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
 	platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
 	platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
@@ -224,7 +318,20 @@
 	return platform_add_devices(sh7366_devices,
 				    ARRAY_SIZE(sh7366_devices));
 }
-__initcall(sh7366_devices_setup);
+arch_initcall(sh7366_devices_setup);
+
+static struct platform_device *sh7366_early_devices[] __initdata = {
+	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7366_early_devices,
+				   ARRAY_SIZE(sh7366_early_devices));
+}
 
 enum {
 	UNUSED=0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7722.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/serial_sci.h>
 #include <linux/mm.h>
 #include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
 
@@ -177,13 +177,13 @@
 	.num_resources	= ARRAY_SIZE(jpu_resources),
 };
 
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
 	.name = "CMT",
 	.channel_offset = 0x60,
 	.timer_bit = 5,
 	.clk = "cmt0",
 	.clockevent_rating = 125,
-	.clocksource_rating = 200,
+	.clocksource_rating = 125,
 };
 
 static struct resource cmt_resources[] = {
@@ -209,24 +209,119 @@
 	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu0",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu0",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu0",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffe00000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 80, 80, 80, 80 },
+		.clk		= "scif0",
 	},
 	{
 		.mapbase	= 0xffe10000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 81, 81, 81, 81 },
+		.clk		= "scif1",
 	},
 	{
 		.mapbase	= 0xffe20000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 82, 82, 82, 82 },
+		.clk		= "scif2",
 	},
 	{
 		.flags = 0,
@@ -243,6 +338,9 @@
 
 static struct platform_device *sh7722_devices[] __initdata = {
 	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
 	&rtc_device,
 	&usbf_device,
 	&iic_device,
@@ -254,12 +352,6 @@
 
 static int __init sh7722_devices_setup(void)
 {
-	clk_always_enable("uram0"); /* URAM */
-	clk_always_enable("xymem0"); /* XYMEM */
-	clk_always_enable("veu0"); /* VEU */
-	clk_always_enable("vpu0"); /* VPU */
-	clk_always_enable("jpu0"); /* JPU */
-
 	platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
 	platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
 	platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20);
@@ -267,7 +359,20 @@
 	return platform_add_devices(sh7722_devices,
 				    ARRAY_SIZE(sh7722_devices));
 }
-__initcall(sh7722_devices_setup);
+arch_initcall(sh7722_devices_setup);
+
+static struct platform_device *sh7722_early_devices[] __initdata = {
+	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7722_early_devices,
+				   ARRAY_SIZE(sh7722_early_devices));
+}
 
 enum {
 	UNUSED=0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7723.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7723.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7723.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,9 @@
 #include <linux/mm.h>
 #include <linux/serial_sci.h>
 #include <linux/uio_driver.h>
-#include <linux/sh_cmt.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/mmzone.h>
 
@@ -101,13 +103,13 @@
 	.num_resources	= ARRAY_SIZE(veu1_resources),
 };
 
-static struct sh_cmt_config cmt_platform_data = {
+static struct sh_timer_config cmt_platform_data = {
 	.name = "CMT",
 	.channel_offset = 0x60,
 	.timer_bit = 5,
 	.clk = "cmt0",
 	.clockevent_rating = 125,
-	.clocksource_rating = 200,
+	.clocksource_rating = 125,
 };
 
 static struct resource cmt_resources[] = {
@@ -133,37 +135,225 @@
 	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu0",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu0",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu0",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu1",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffd90008,
+		.end	= 0xffd90013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 57,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu1",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffd90014,
+		.end	= 0xffd9001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 58,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu1",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffd90020,
+		.end	= 0xffd9002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 57,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase        = 0xffe00000,
 		.flags          = UPF_BOOT_AUTOCONF,
 		.type           = PORT_SCIF,
 		.irqs           = { 80, 80, 80, 80 },
+		.clk		= "scif0",
 	},{
 		.mapbase        = 0xffe10000,
 		.flags          = UPF_BOOT_AUTOCONF,
 		.type           = PORT_SCIF,
 		.irqs           = { 81, 81, 81, 81 },
+		.clk		= "scif1",
 	},{
 		.mapbase        = 0xffe20000,
 		.flags          = UPF_BOOT_AUTOCONF,
 		.type           = PORT_SCIF,
 		.irqs           = { 82, 82, 82, 82 },
+		.clk		= "scif2",
 	},{
 		.mapbase	= 0xa4e30000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIFA,
 		.irqs		= { 56, 56, 56, 56 },
+		.clk		= "scif3",
 	},{
 		.mapbase	= 0xa4e40000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIFA,
 		.irqs		= { 88, 88, 88, 88 },
+		.clk		= "scif4",
 	},{
 		.mapbase	= 0xa4e50000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIFA,
 		.irqs		= { 109, 109, 109, 109 },
+		.clk		= "scif5",
 	}, {
 		.flags = 0,
 	}
@@ -207,9 +397,12 @@
 	.resource	= rtc_resources,
 };
 
+static struct r8a66597_platdata r8a66597_data = {
+	/* This set zero to all members */
+};
+
 static struct resource sh7723_usb_host_resources[] = {
 	[0] = {
-		.name	= "r8a66597_hcd",
 		.start	= 0xa4d80000,
 		.end	= 0xa4d800ff,
 		.flags	= IORESOURCE_MEM,
@@ -217,7 +410,7 @@
 	[1] = {
 		.start	= 65,
 		.end	= 65,
-		.flags	= IORESOURCE_IRQ,
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
 	},
 };
 
@@ -227,6 +420,7 @@
 	.dev = {
 		.dma_mask		= NULL,         /*  not use dma */
 		.coherent_dma_mask	= 0xffffffff,
+		.platform_data		= &r8a66597_data,
 	},
 	.num_resources	= ARRAY_SIZE(sh7723_usb_host_resources),
 	.resource	= sh7723_usb_host_resources,
@@ -255,6 +449,12 @@
 
 static struct platform_device *sh7723_devices[] __initdata = {
 	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
 	&sci_device,
 	&rtc_device,
 	&iic_device,
@@ -266,11 +466,6 @@
 
 static int __init sh7723_devices_setup(void)
 {
-	clk_always_enable("meram0"); /* MERAM */
-	clk_always_enable("veu1"); /* VEU2H1 */
-	clk_always_enable("veu0"); /* VEU2H0 */
-	clk_always_enable("vpu0"); /* VPU */
-
 	platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
 	platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
 	platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
@@ -278,7 +473,32 @@
 	return platform_add_devices(sh7723_devices,
 				    ARRAY_SIZE(sh7723_devices));
 }
-__initcall(sh7723_devices_setup);
+arch_initcall(sh7723_devices_setup);
+
+static struct platform_device *sh7723_early_devices[] __initdata = {
+	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7723_early_devices,
+				   ARRAY_SIZE(sh7723_early_devices));
+}
+
+#define RAMCR_CACHE_L2FC	0x0002
+#define RAMCR_CACHE_L2E		0x0001
+#define L2_CACHE_ENABLE		(RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC)
+void __uses_jump_to_uncached l2_cache_init(void)
+{
+	/* Enable L2 cache */
+	ctrl_outl(L2_CACHE_ENABLE, RAMCR);
+}
 
 enum {
 	UNUSED=0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7724.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,786 @@
+/*
+ * SH7724 Setup
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7723 Setup
+ * Copyright (C) 2008  Paul Mundt
+ *
+ * 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/serial_sci.h>
+#include <linux/uio_driver.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/mmzone.h>
+
+/* Serial */
+static struct plat_sci_port sci_platform_data[] = {
+	{
+		.mapbase        = 0xffe00000,
+		.flags          = UPF_BOOT_AUTOCONF,
+		.type           = PORT_SCIF,
+		.irqs           = { 80, 80, 80, 80 },
+		.clk		= "scif0",
+	}, {
+		.mapbase        = 0xffe10000,
+		.flags          = UPF_BOOT_AUTOCONF,
+		.type           = PORT_SCIF,
+		.irqs           = { 81, 81, 81, 81 },
+		.clk		= "scif1",
+	}, {
+		.mapbase        = 0xffe20000,
+		.flags          = UPF_BOOT_AUTOCONF,
+		.type           = PORT_SCIF,
+		.irqs           = { 82, 82, 82, 82 },
+		.clk		= "scif2",
+	}, {
+		.mapbase	= 0xa4e30000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIFA,
+		.irqs		= { 56, 56, 56, 56 },
+		.clk		= "scif3",
+	}, {
+		.mapbase	= 0xa4e40000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIFA,
+		.irqs		= { 88, 88, 88, 88 },
+		.clk		= "scif4",
+	}, {
+		.mapbase	= 0xa4e50000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIFA,
+		.irqs		= { 109, 109, 109, 109 },
+		.clk		= "scif5",
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct platform_device sci_device = {
+	.name		= "sh-sci",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= sci_platform_data,
+	},
+};
+
+/* RTC */
+static struct resource rtc_resources[] = {
+	[0] = {
+		.start	= 0xa465fec0,
+		.end	= 0xa465fec0 + 0x58 - 1,
+		.flags	= IORESOURCE_IO,
+	},
+	[1] = {
+		/* Period IRQ */
+		.start	= 69,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* Carry IRQ */
+		.start	= 70,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		/* Alarm IRQ */
+		.start	= 68,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device rtc_device = {
+	.name		= "sh-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtc_resources),
+	.resource	= rtc_resources,
+};
+
+/* I2C0 */
+static struct resource iic0_resources[] = {
+	[0] = {
+		.name	= "IIC0",
+		.start  = 0x04470000,
+		.end    = 0x04470018 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 96,
+		.end    = 99,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device iic0_device = {
+	.name           = "i2c-sh_mobile",
+	.id             = 0, /* "i2c0" clock */
+	.num_resources  = ARRAY_SIZE(iic0_resources),
+	.resource       = iic0_resources,
+};
+
+/* I2C1 */
+static struct resource iic1_resources[] = {
+	[0] = {
+		.name	= "IIC1",
+		.start  = 0x04750000,
+		.end    = 0x04750018 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 92,
+		.end    = 95,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device iic1_device = {
+	.name           = "i2c-sh_mobile",
+	.id             = 1, /* "i2c1" clock */
+	.num_resources  = ARRAY_SIZE(iic1_resources),
+	.resource       = iic1_resources,
+};
+
+/* VPU */
+static struct uio_info vpu_platform_data = {
+	.name = "VPU5F",
+	.version = "0",
+	.irq = 60,
+};
+
+static struct resource vpu_resources[] = {
+	[0] = {
+		.name	= "VPU",
+		.start	= 0xfe900000,
+		.end	= 0xfe902807,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
+};
+
+static struct platform_device vpu_device = {
+	.name		= "uio_pdrv_genirq",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &vpu_platform_data,
+	},
+	.resource	= vpu_resources,
+	.num_resources	= ARRAY_SIZE(vpu_resources),
+};
+
+/* VEU0 */
+static struct uio_info veu0_platform_data = {
+	.name = "VEU3F0",
+	.version = "0",
+	.irq = 83,
+};
+
+static struct resource veu0_resources[] = {
+	[0] = {
+		.name	= "VEU3F0",
+		.start	= 0xfe920000,
+		.end	= 0xfe9200cb - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
+};
+
+static struct platform_device veu0_device = {
+	.name		= "uio_pdrv_genirq",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &veu0_platform_data,
+	},
+	.resource	= veu0_resources,
+	.num_resources	= ARRAY_SIZE(veu0_resources),
+};
+
+/* VEU1 */
+static struct uio_info veu1_platform_data = {
+	.name = "VEU3F1",
+	.version = "0",
+	.irq = 54,
+};
+
+static struct resource veu1_resources[] = {
+	[0] = {
+		.name	= "VEU3F1",
+		.start	= 0xfe924000,
+		.end	= 0xfe9240cb - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
+};
+
+static struct platform_device veu1_device = {
+	.name		= "uio_pdrv_genirq",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &veu1_platform_data,
+	},
+	.resource	= veu1_resources,
+	.num_resources	= ARRAY_SIZE(veu1_resources),
+};
+
+static struct sh_timer_config cmt_platform_data = {
+	.name = "CMT",
+	.channel_offset = 0x60,
+	.timer_bit = 5,
+	.clk = "cmt0",
+	.clockevent_rating = 125,
+	.clocksource_rating = 200,
+};
+
+static struct resource cmt_resources[] = {
+	[0] = {
+		.name	= "CMT",
+		.start	= 0x044a0060,
+		.end	= 0x044a006b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 104,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cmt_device = {
+	.name		= "sh_cmt",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &cmt_platform_data,
+	},
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu0",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu0",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu0",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu1",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffd90008,
+		.end	= 0xffd90013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 57,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu1",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffd90014,
+		.end	= 0xffd9001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 58,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu1",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffd90020,
+		.end	= 0xffd9002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 57,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
+
+/* JPU */
+static struct uio_info jpu_platform_data = {
+	.name = "JPU",
+	.version = "0",
+	.irq = 27,
+};
+
+static struct resource jpu_resources[] = {
+	[0] = {
+		.name	= "JPU",
+		.start	= 0xfe980000,
+		.end	= 0xfe9902d3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
+};
+
+static struct platform_device jpu_device = {
+	.name		= "uio_pdrv_genirq",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &jpu_platform_data,
+	},
+	.resource	= jpu_resources,
+	.num_resources	= ARRAY_SIZE(jpu_resources),
+};
+
+static struct platform_device *sh7724_devices[] __initdata = {
+	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+	&sci_device,
+	&rtc_device,
+	&iic0_device,
+	&iic1_device,
+	&vpu_device,
+	&veu0_device,
+	&veu1_device,
+	&jpu_device,
+};
+
+static int __init sh7724_devices_setup(void)
+{
+	platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
+	platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
+	platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
+	platform_resource_setup_memory(&jpu_device,  "jpu",  2 << 20);
+
+	return platform_add_devices(sh7724_devices,
+				    ARRAY_SIZE(sh7724_devices));
+}
+arch_initcall(sh7724_devices_setup);
+
+static struct platform_device *sh7724_early_devices[] __initdata = {
+	&cmt_device,
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7724_early_devices,
+				   ARRAY_SIZE(sh7724_early_devices));
+}
+
+#define RAMCR_CACHE_L2FC	0x0002
+#define RAMCR_CACHE_L2E		0x0001
+#define L2_CACHE_ENABLE		(RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC)
+void __uses_jump_to_uncached l2_cache_init(void)
+{
+	/* Enable L2 cache */
+	ctrl_outl(L2_CACHE_ENABLE, RAMCR);
+}
+
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources */
+	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+	HUDI,
+	DMAC1A_DEI0, DMAC1A_DEI1, DMAC1A_DEI2, DMAC1A_DEI3,
+	_2DG_TRI, _2DG_INI, _2DG_CEI,
+	DMAC0A_DEI0, DMAC0A_DEI1, DMAC0A_DEI2, DMAC0A_DEI3,
+	VIO_CEU0, VIO_BEU0, VIO_VEU1, VIO_VOU,
+	SCIFA3,
+	VPU,
+	TPU,
+	CEU1,
+	BEU1,
+	USB0, USB1,
+	ATAPI,
+	RTC_ATI, RTC_PRI, RTC_CUI,
+	DMAC1B_DEI4, DMAC1B_DEI5, DMAC1B_DADERR,
+	DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR,
+	KEYSC,
+	SCIF_SCIF0, SCIF_SCIF1, SCIF_SCIF2,
+	VEU0,
+	MSIOF_MSIOFI0, MSIOF_MSIOFI1,
+	SPU_SPUI0, SPU_SPUI1,
+	SCIFA4,
+	ICB,
+	ETHI,
+	I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI,
+	I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI,
+	SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2, SDHI0_SDHII3,
+	CMT,
+	TSIF,
+	FSI,
+	SCIFA5,
+	TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
+	IRDA,
+	SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2,
+	JPU,
+	_2DDMAC,
+	MMC_MMC2I, MMC_MMC3I,
+	LCDC,
+	TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2,
+
+	/* interrupt groups */
+	DMAC1A, _2DG, DMAC0A, VIO, USB, RTC,
+	DMAC1B, DMAC0B, I2C0, I2C1, SDHI0, SDHI1, SPU, MMCIF,
+};
+
+static struct intc_vect vectors[] __initdata = {
+	INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
+	INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+	INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+	INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
+
+	INTC_VECT(DMAC1A_DEI0, 0x700),
+	INTC_VECT(DMAC1A_DEI1, 0x720),
+	INTC_VECT(DMAC1A_DEI2, 0x740),
+	INTC_VECT(DMAC1A_DEI3, 0x760),
+
+	INTC_VECT(_2DG_TRI, 0x780),
+	INTC_VECT(_2DG_INI, 0x7A0),
+	INTC_VECT(_2DG_CEI, 0x7C0),
+
+	INTC_VECT(DMAC0A_DEI0, 0x800),
+	INTC_VECT(DMAC0A_DEI1, 0x820),
+	INTC_VECT(DMAC0A_DEI2, 0x840),
+	INTC_VECT(DMAC0A_DEI3, 0x860),
+
+	INTC_VECT(VIO_CEU0, 0x880),
+	INTC_VECT(VIO_BEU0, 0x8A0),
+	INTC_VECT(VIO_VEU1, 0x8C0),
+	INTC_VECT(VIO_VOU,  0x8E0),
+
+	INTC_VECT(SCIFA3, 0x900),
+	INTC_VECT(VPU,    0x980),
+	INTC_VECT(TPU,    0x9A0),
+	INTC_VECT(CEU1,   0x9E0),
+	INTC_VECT(BEU1,   0xA00),
+	INTC_VECT(USB0,   0xA20),
+	INTC_VECT(USB1,   0xA40),
+	INTC_VECT(ATAPI,  0xA60),
+
+	INTC_VECT(RTC_ATI, 0xA80),
+	INTC_VECT(RTC_PRI, 0xAA0),
+	INTC_VECT(RTC_CUI, 0xAC0),
+
+	INTC_VECT(DMAC1B_DEI4, 0xB00),
+	INTC_VECT(DMAC1B_DEI5, 0xB20),
+	INTC_VECT(DMAC1B_DADERR, 0xB40),
+
+	INTC_VECT(DMAC0B_DEI4, 0xB80),
+	INTC_VECT(DMAC0B_DEI5, 0xBA0),
+	INTC_VECT(DMAC0B_DADERR, 0xBC0),
+
+	INTC_VECT(KEYSC,      0xBE0),
+	INTC_VECT(SCIF_SCIF0, 0xC00),
+	INTC_VECT(SCIF_SCIF1, 0xC20),
+	INTC_VECT(SCIF_SCIF2, 0xC40),
+	INTC_VECT(VEU0,       0xC60),
+	INTC_VECT(MSIOF_MSIOFI0, 0xC80),
+	INTC_VECT(MSIOF_MSIOFI1, 0xCA0),
+	INTC_VECT(SPU_SPUI0, 0xCC0),
+	INTC_VECT(SPU_SPUI1, 0xCE0),
+	INTC_VECT(SCIFA4,    0xD00),
+
+	INTC_VECT(ICB,  0xD20),
+	INTC_VECT(ETHI, 0xD60),
+
+	INTC_VECT(I2C1_ALI, 0xD80),
+	INTC_VECT(I2C1_TACKI, 0xDA0),
+	INTC_VECT(I2C1_WAITI, 0xDC0),
+	INTC_VECT(I2C1_DTEI, 0xDE0),
+
+	INTC_VECT(I2C0_ALI, 0xE00),
+	INTC_VECT(I2C0_TACKI, 0xE20),
+	INTC_VECT(I2C0_WAITI, 0xE40),
+	INTC_VECT(I2C0_DTEI, 0xE60),
+
+	INTC_VECT(SDHI0_SDHII0, 0xE80),
+	INTC_VECT(SDHI0_SDHII1, 0xEA0),
+	INTC_VECT(SDHI0_SDHII2, 0xEC0),
+	INTC_VECT(SDHI0_SDHII3, 0xEE0),
+
+	INTC_VECT(CMT,    0xF00),
+	INTC_VECT(TSIF,   0xF20),
+	INTC_VECT(FSI,    0xF80),
+	INTC_VECT(SCIFA5, 0xFA0),
+
+	INTC_VECT(TMU0_TUNI0, 0x400),
+	INTC_VECT(TMU0_TUNI1, 0x420),
+	INTC_VECT(TMU0_TUNI2, 0x440),
+
+	INTC_VECT(IRDA,    0x480),
+
+	INTC_VECT(SDHI1_SDHII0, 0x4E0),
+	INTC_VECT(SDHI1_SDHII1, 0x500),
+	INTC_VECT(SDHI1_SDHII2, 0x520),
+
+	INTC_VECT(JPU, 0x560),
+	INTC_VECT(_2DDMAC, 0x4A0),
+
+	INTC_VECT(MMC_MMC2I, 0x5A0),
+	INTC_VECT(MMC_MMC3I, 0x5C0),
+
+	INTC_VECT(LCDC, 0xF40),
+
+	INTC_VECT(TMU1_TUNI0, 0x920),
+	INTC_VECT(TMU1_TUNI1, 0x940),
+	INTC_VECT(TMU1_TUNI2, 0x960),
+};
+
+static struct intc_group groups[] __initdata = {
+	INTC_GROUP(DMAC1A, DMAC1A_DEI0, DMAC1A_DEI1, DMAC1A_DEI2, DMAC1A_DEI3),
+	INTC_GROUP(_2DG, _2DG_TRI, _2DG_INI, _2DG_CEI),
+	INTC_GROUP(DMAC0A, DMAC0A_DEI0, DMAC0A_DEI1, DMAC0A_DEI2, DMAC0A_DEI3),
+	INTC_GROUP(VIO, VIO_CEU0, VIO_BEU0, VIO_VEU1, VIO_VOU),
+	INTC_GROUP(USB, USB0, USB1),
+	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+	INTC_GROUP(DMAC1B, DMAC1B_DEI4, DMAC1B_DEI5, DMAC1B_DADERR),
+	INTC_GROUP(DMAC0B, DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR),
+	INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI),
+	INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI),
+	INTC_GROUP(SDHI0, SDHI0_SDHII0, SDHI0_SDHII1, SDHI0_SDHII2, SDHI0_SDHII3),
+	INTC_GROUP(SDHI1, SDHI1_SDHII0, SDHI1_SDHII1, SDHI1_SDHII2),
+	INTC_GROUP(SPU, SPU_SPUI0, SPU_SPUI1),
+	INTC_GROUP(MMCIF, MMC_MMC2I, MMC_MMC3I),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
+	  { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
+	    0, SDHI1_SDHII2, SDHI1_SDHII1, SDHI1_SDHII0 } },
+	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
+	  { VIO_VOU, VIO_VEU1, VIO_BEU0, VIO_CEU0,
+	    DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } },
+	{ 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
+	  { 0, 0, 0, VPU, ATAPI, ETHI, 0, SCIFA3 } },
+	{ 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
+	  { DMAC1A_DEI3, DMAC1A_DEI2, DMAC1A_DEI1, DMAC1A_DEI0,
+	    SPU_SPUI1, SPU_SPUI0, BEU1, IRDA } },
+	{ 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
+	  { 0, TMU0_TUNI2, TMU0_TUNI1, TMU0_TUNI0,
+	    JPU, 0, 0, LCDC } },
+	{ 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
+	  { KEYSC, DMAC0B_DADERR, DMAC0B_DEI5, DMAC0B_DEI4,
+	    VEU0, SCIF_SCIF2, SCIF_SCIF1, SCIF_SCIF0 } },
+	{ 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
+	  { 0, 0, ICB, SCIFA4,
+	    CEU1, 0, MSIOF_MSIOFI1, MSIOF_MSIOFI0 } },
+	{ 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
+	  { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
+	    I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } },
+	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
+	  { SDHI0_SDHII3, SDHI0_SDHII2, SDHI0_SDHII1, SDHI0_SDHII0,
+	    0, 0, SCIFA5, FSI } },
+	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
+	  { 0, 0, 0, CMT, 0, USB1, USB0, 0 } },
+	{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
+	  { 0, DMAC1B_DADERR, DMAC1B_DEI5, DMAC1B_DEI4,
+	    0, RTC_CUI, RTC_PRI, RTC_ATI } },
+	{ 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
+	  { 0, _2DG_CEI, _2DG_INI, _2DG_TRI,
+	    0, TPU, 0, TSIF } },
+	{ 0xa40800b0, 0xa40800f0, 8, /* IMR12 / IMCR12 */
+	  { 0, 0, MMC_MMC3I, MMC_MMC2I, 0, 0, 0, _2DDMAC } },
+	{ 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+	{ 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0_TUNI0, TMU0_TUNI1,
+					     TMU0_TUNI2, IRDA } },
+	{ 0xa4080004, 0, 16, 4, /* IPRB */ { JPU, LCDC, DMAC1A, BEU1 } },
+	{ 0xa4080008, 0, 16, 4, /* IPRC */ { TMU1_TUNI0, TMU1_TUNI1,
+					     TMU1_TUNI2, SPU } },
+	{ 0xa408000c, 0, 16, 4, /* IPRD */ { 0, MMCIF, 0, ATAPI } },
+	{ 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0A, VIO, SCIFA3, VPU } },
+	{ 0xa4080014, 0, 16, 4, /* IPRF */ { KEYSC, DMAC0B, USB, CMT } },
+	{ 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF_SCIF0, SCIF_SCIF1,
+					     SCIF_SCIF2, VEU0 } },
+	{ 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF_MSIOFI0, MSIOF_MSIOFI1,
+					     I2C1, I2C0 } },
+	{ 0xa4080020, 0, 16, 4, /* IPRI */ { SCIFA4, ICB, TSIF, _2DG } },
+	{ 0xa4080024, 0, 16, 4, /* IPRJ */ { CEU1, ETHI, FSI, SDHI1 } },
+	{ 0xa4080028, 0, 16, 4, /* IPRK */ { RTC, DMAC1B, 0, SDHI0 } },
+	{ 0xa408002c, 0, 16, 4, /* IPRL */ { SCIFA5, 0, TPU, _2DDMAC } },
+	{ 0xa4140010, 0, 32, 4, /* INTPRI00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+	{ 0xa414001c, 16, 2, /* ICR1 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+	{ 0xa4140024, 0, 8, /* INTREQ00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7724", vectors, groups,
+			     mask_registers, prio_registers, sense_registers,
+			     ack_registers);
+
+void __init plat_irq_setup(void)
+{
+	register_intc_controller(&intc_desc);
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7763.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7763.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7763.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/serial.h>
+#include <linux/sh_timer.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
 
@@ -113,7 +114,195 @@
 	.resource	= usbf_resources,
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 28,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 29,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 30,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffd88008,
+		.end	= 0xffd88013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 96,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffd88014,
+		.end	= 0xffd8801f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 97,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffd88020,
+		.end	= 0xffd8802b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 98,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
+
 static struct platform_device *sh7763_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
 	&rtc_device,
 	&sci_device,
 	&usb_ohci_device,
@@ -125,7 +314,22 @@
 	return platform_add_devices(sh7763_devices,
 				    ARRAY_SIZE(sh7763_devices));
 }
-__initcall(sh7763_devices_setup);
+arch_initcall(sh7763_devices_setup);
+
+static struct platform_device *sh7763_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7763_early_devices,
+				   ARRAY_SIZE(sh7763_early_devices));
+}
 
 enum {
 	UNUSED = 0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7770.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7770.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7770.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,8 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
 
 static struct plat_sci_port sci_platform_data[] = {
 	{
@@ -76,7 +78,288 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffd81008,
+		.end	= 0xffd81013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 19,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffd81014,
+		.end	= 0xffd8101f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 20,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffd81020,
+		.end	= 0xffd8102f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 21,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
+
+static struct sh_timer_config tmu6_platform_data = {
+	.name = "TMU6",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu6_resources[] = {
+	[0] = {
+		.name	= "TMU6",
+		.start	= 0xffd82008,
+		.end	= 0xffd82013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 22,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu6_device = {
+	.name		= "sh_tmu",
+	.id		= 6,
+	.dev = {
+		.platform_data	= &tmu6_platform_data,
+	},
+	.resource	= tmu6_resources,
+	.num_resources	= ARRAY_SIZE(tmu6_resources),
+};
+
+static struct sh_timer_config tmu7_platform_data = {
+	.name = "TMU7",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu7_resources[] = {
+	[0] = {
+		.name	= "TMU7",
+		.start	= 0xffd82014,
+		.end	= 0xffd8201f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 23,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu7_device = {
+	.name		= "sh_tmu",
+	.id		= 7,
+	.dev = {
+		.platform_data	= &tmu7_platform_data,
+	},
+	.resource	= tmu7_resources,
+	.num_resources	= ARRAY_SIZE(tmu7_resources),
+};
+
+static struct sh_timer_config tmu8_platform_data = {
+	.name = "TMU8",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu8_resources[] = {
+	[0] = {
+		.name	= "TMU8",
+		.start	= 0xffd82020,
+		.end	= 0xffd8202b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 24,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu8_device = {
+	.name		= "sh_tmu",
+	.id		= 8,
+	.dev = {
+		.platform_data	= &tmu8_platform_data,
+	},
+	.resource	= tmu8_resources,
+	.num_resources	= ARRAY_SIZE(tmu8_resources),
+};
+
 static struct platform_device *sh7770_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+	&tmu6_device,
+	&tmu7_device,
+	&tmu8_device,
 	&sci_device,
 };
 
@@ -85,8 +368,271 @@
 	return platform_add_devices(sh7770_devices,
 				    ARRAY_SIZE(sh7770_devices));
 }
-__initcall(sh7770_devices_setup);
+arch_initcall(sh7770_devices_setup);
+
+static struct platform_device *sh7770_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+	&tmu6_device,
+	&tmu7_device,
+	&tmu8_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7770_early_devices,
+				   ARRAY_SIZE(sh7770_early_devices));
+}
+
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources */
+	IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+	IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+	IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+	IRL_HHLL, IRL_HHLH, IRL_HHHL,
+
+	IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
+
+	GPIO,
+	TMU0, TMU1, TMU2, TMU2_TICPI,
+	TMU3, TMU4, TMU5, TMU5_TICPI,
+	TMU6, TMU7, TMU8,
+	HAC, IPI, SPDIF, HUDI, I2C,
+	DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
+	I2S0, I2S1, I2S2, I2S3,
+	SRC_RX, SRC_TX, SRC_SPDIF,
+	DU, VIDEO_IN, REMOTE, YUV, USB, ATAPI, CAN, GPS, GFX2D,
+	GFX3D_MBX, GFX3D_DMAC,
+	EXBUS_ATA,
+	SPI0, SPI1,
+	SCIF089, SCIF1234, SCIF567,
+	ADC,
+	BBDMAC_0_3, BBDMAC_4_7, BBDMAC_8_10, BBDMAC_11_14,
+	BBDMAC_15_18, BBDMAC_19_22, BBDMAC_23_26, BBDMAC_27,
+	BBDMAC_28, BBDMAC_29, BBDMAC_30, BBDMAC_31,
+
+	/* interrupt groups */
+	TMU, DMAC, I2S, SRC, GFX3D, SPI, SCIF, BBDMAC,
+};
+
+static struct intc_vect vectors[] __initdata = {
+	INTC_VECT(GPIO, 0x3e0),
+	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+	INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+	INTC_VECT(TMU3, 0x480), INTC_VECT(TMU4, 0x4a0),
+	INTC_VECT(TMU5, 0x4c0), INTC_VECT(TMU5_TICPI, 0x4e0),
+	INTC_VECT(TMU6, 0x500), INTC_VECT(TMU7, 0x520),
+	INTC_VECT(TMU8, 0x540),
+	INTC_VECT(HAC, 0x580), INTC_VECT(IPI, 0x5c0),
+	INTC_VECT(SPDIF, 0x5e0),
+	INTC_VECT(HUDI, 0x600), INTC_VECT(I2C, 0x620),
+	INTC_VECT(DMAC0_DMINT0, 0x640), INTC_VECT(DMAC0_DMINT1, 0x660),
+	INTC_VECT(DMAC0_DMINT2, 0x680),
+	INTC_VECT(I2S0, 0x6a0), INTC_VECT(I2S1, 0x6c0),
+	INTC_VECT(I2S2, 0x6e0), INTC_VECT(I2S3, 0x700),
+	INTC_VECT(SRC_RX, 0x720), INTC_VECT(SRC_TX, 0x740),
+	INTC_VECT(SRC_SPDIF, 0x760),
+	INTC_VECT(DU, 0x780), INTC_VECT(VIDEO_IN, 0x7a0),
+	INTC_VECT(REMOTE, 0x7c0), INTC_VECT(YUV, 0x7e0),
+	INTC_VECT(USB, 0x840), INTC_VECT(ATAPI, 0x860),
+	INTC_VECT(CAN, 0x880), INTC_VECT(GPS, 0x8a0),
+	INTC_VECT(GFX2D, 0x8c0),
+	INTC_VECT(GFX3D_MBX, 0x900), INTC_VECT(GFX3D_DMAC, 0x920),
+	INTC_VECT(EXBUS_ATA, 0x940),
+	INTC_VECT(SPI0, 0x960), INTC_VECT(SPI1, 0x980),
+	INTC_VECT(SCIF089, 0x9a0), INTC_VECT(SCIF1234, 0x9c0),
+	INTC_VECT(SCIF1234, 0x9e0), INTC_VECT(SCIF1234, 0xa00),
+	INTC_VECT(SCIF1234, 0xa20), INTC_VECT(SCIF567, 0xa40),
+	INTC_VECT(SCIF567, 0xa60), INTC_VECT(SCIF567, 0xa80),
+	INTC_VECT(SCIF089, 0xaa0), INTC_VECT(SCIF089, 0xac0),
+	INTC_VECT(ADC, 0xb20),
+	INTC_VECT(BBDMAC_0_3, 0xba0), INTC_VECT(BBDMAC_0_3, 0xbc0),
+	INTC_VECT(BBDMAC_0_3, 0xbe0), INTC_VECT(BBDMAC_0_3, 0xc00),
+	INTC_VECT(BBDMAC_4_7, 0xc20), INTC_VECT(BBDMAC_4_7, 0xc40),
+	INTC_VECT(BBDMAC_4_7, 0xc60), INTC_VECT(BBDMAC_4_7, 0xc80),
+	INTC_VECT(BBDMAC_8_10, 0xca0), INTC_VECT(BBDMAC_8_10, 0xcc0),
+	INTC_VECT(BBDMAC_8_10, 0xce0), INTC_VECT(BBDMAC_11_14, 0xd00),
+	INTC_VECT(BBDMAC_11_14, 0xd20), INTC_VECT(BBDMAC_11_14, 0xd40),
+	INTC_VECT(BBDMAC_11_14, 0xd60), INTC_VECT(BBDMAC_15_18, 0xd80),
+	INTC_VECT(BBDMAC_15_18, 0xda0), INTC_VECT(BBDMAC_15_18, 0xdc0),
+	INTC_VECT(BBDMAC_15_18, 0xde0), INTC_VECT(BBDMAC_19_22, 0xe00),
+	INTC_VECT(BBDMAC_19_22, 0xe20), INTC_VECT(BBDMAC_19_22, 0xe40),
+	INTC_VECT(BBDMAC_19_22, 0xe60), INTC_VECT(BBDMAC_23_26, 0xe80),
+	INTC_VECT(BBDMAC_23_26, 0xea0), INTC_VECT(BBDMAC_23_26, 0xec0),
+	INTC_VECT(BBDMAC_23_26, 0xee0), INTC_VECT(BBDMAC_27, 0xf00),
+	INTC_VECT(BBDMAC_28, 0xf20), INTC_VECT(BBDMAC_29, 0xf40),
+	INTC_VECT(BBDMAC_30, 0xf60), INTC_VECT(BBDMAC_31, 0xf80),
+};
+
+static struct intc_group groups[] __initdata = {
+	INTC_GROUP(TMU, TMU0, TMU1, TMU2, TMU2_TICPI, TMU3, TMU4, TMU5,
+		   TMU5_TICPI, TMU6, TMU7, TMU8),
+	INTC_GROUP(DMAC, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2),
+	INTC_GROUP(I2S, I2S0, I2S1, I2S2, I2S3),
+	INTC_GROUP(SRC, SRC_RX, SRC_TX, SRC_SPDIF),
+	INTC_GROUP(GFX3D, GFX3D_MBX, GFX3D_DMAC),
+	INTC_GROUP(SPI, SPI0, SPI1),
+	INTC_GROUP(SCIF, SCIF089, SCIF1234, SCIF567),
+	INTC_GROUP(BBDMAC,
+		   BBDMAC_0_3, BBDMAC_4_7, BBDMAC_8_10, BBDMAC_11_14,
+		   BBDMAC_15_18, BBDMAC_19_22, BBDMAC_23_26, BBDMAC_27,
+		   BBDMAC_28, BBDMAC_29, BBDMAC_30, BBDMAC_31),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+	{ 0xffe00040, 0xffe00044, 32, /* INT2MSKR / INT2MSKCR */
+	  { 0, BBDMAC, ADC, SCIF, SPI, EXBUS_ATA, GFX3D, GFX2D,
+	    GPS, CAN, ATAPI, USB, YUV, REMOTE, VIDEO_IN, DU, SRC, I2S,
+	    DMAC, I2C, HUDI, SPDIF, IPI, HAC, TMU, GPIO } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+	{ 0xffe00000, 0, 32, 8, /* INT2PRI0 */ { GPIO, TMU0, 0, HAC } },
+	{ 0xffe00004, 0, 32, 8, /* INT2PRI1 */ { IPI, SPDIF, HUDI, I2C } },
+	{ 0xffe00008, 0, 32, 8, /* INT2PRI2 */ { DMAC, I2S, SRC, DU } },
+	{ 0xffe0000c, 0, 32, 8, /* INT2PRI3 */ { VIDEO_IN, REMOTE, YUV, USB } },
+	{ 0xffe00010, 0, 32, 8, /* INT2PRI4 */ { ATAPI, CAN, GPS, GFX2D } },
+	{ 0xffe00014, 0, 32, 8, /* INT2PRI5 */ { 0, GFX3D, EXBUS_ATA, SPI } },
+	{ 0xffe00018, 0, 32, 8, /* INT2PRI6 */ { SCIF1234, SCIF567, SCIF089 } },
+	{ 0xffe0001c, 0, 32, 8, /* INT2PRI7 */ { ADC, 0, 0, BBDMAC_0_3 } },
+	{ 0xffe00020, 0, 32, 8, /* INT2PRI8 */
+	  { BBDMAC_4_7, BBDMAC_8_10, BBDMAC_11_14, BBDMAC_15_18 } },
+	{ 0xffe00024, 0, 32, 8, /* INT2PRI9 */
+	  { BBDMAC_19_22, BBDMAC_23_26, BBDMAC_27, BBDMAC_28 } },
+	{ 0xffe00028, 0, 32, 8, /* INT2PRI10 */
+	  { BBDMAC_29, BBDMAC_30, BBDMAC_31 } },
+	{ 0xffe0002c, 0, 32, 8, /* INT2PRI11 */
+	  { TMU1, TMU2, TMU2_TICPI, TMU3 } },
+	{ 0xffe00030, 0, 32, 8, /* INT2PRI12 */
+	  { TMU4, TMU5, TMU5_TICPI, TMU6 } },
+	{ 0xffe00034, 0, 32, 8, /* INT2PRI13 */
+	  { TMU7, TMU8 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7770", vectors, groups,
+			 mask_registers, prio_registers, NULL);
+
+/* Support for external interrupt pins in IRQ mode */
+static struct intc_vect irq_vectors[] __initdata = {
+	INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+	INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
+	INTC_VECT(IRQ4, 0x340), INTC_VECT(IRQ5, 0x380),
+};
+
+static struct intc_mask_reg irq_mask_registers[] __initdata = {
+	{ 0xffd00044, 0xffd00064, 32, /* INTMSK0 / INTMSKCLR0 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, } },
+};
+
+static struct intc_prio_reg irq_prio_registers[] __initdata = {
+	{ 0xffd00010, 0, 32, 4, /* INTPRI */ { IRQ0, IRQ1, IRQ2, IRQ3,
+					       IRQ4, IRQ5, } },
+};
+
+static struct intc_sense_reg irq_sense_registers[] __initdata = {
+	{ 0xffd0001c, 32, 2, /* ICR1 */   { IRQ0, IRQ1, IRQ2, IRQ3,
+					    IRQ4, IRQ5, } },
+};
+
+static DECLARE_INTC_DESC(intc_irq_desc, "sh7770-irq", irq_vectors,
+			 NULL, irq_mask_registers, irq_prio_registers,
+			 irq_sense_registers);
+
+/* External interrupt pins in IRL mode */
+static struct intc_vect irl_vectors[] __initdata = {
+	INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220),
+	INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260),
+	INTC_VECT(IRL_LHLL, 0x280), INTC_VECT(IRL_LHLH, 0x2a0),
+	INTC_VECT(IRL_LHHL, 0x2c0), INTC_VECT(IRL_LHHH, 0x2e0),
+	INTC_VECT(IRL_HLLL, 0x300), INTC_VECT(IRL_HLLH, 0x320),
+	INTC_VECT(IRL_HLHL, 0x340), INTC_VECT(IRL_HLHH, 0x360),
+	INTC_VECT(IRL_HHLL, 0x380), INTC_VECT(IRL_HHLH, 0x3a0),
+	INTC_VECT(IRL_HHHL, 0x3c0),
+};
+
+static struct intc_mask_reg irl3210_mask_registers[] __initdata = {
+	{ 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */
+	  { IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+	    IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+	    IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+	    IRL_HHLL, IRL_HHLH, IRL_HHHL, } },
+};
+
+static struct intc_mask_reg irl7654_mask_registers[] __initdata = {
+	{ 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */
+	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+	    IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+	    IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+	    IRL_HHLL, IRL_HHLH, IRL_HHHL, } },
+};
+
+static DECLARE_INTC_DESC(intc_irl7654_desc, "sh7780-irl7654", irl_vectors,
+			 NULL, irl7654_mask_registers, NULL, NULL);
+
+static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7780-irl3210", irl_vectors,
+			 NULL, irl3210_mask_registers, NULL, NULL);
+
+#define INTC_ICR0	0xffd00000
+#define INTC_INTMSK0	0xffd00044
+#define INTC_INTMSK1	0xffd00048
+#define INTC_INTMSK2	0xffd40080
+#define INTC_INTMSKCLR1	0xffd00068
+#define INTC_INTMSKCLR2	0xffd40084
 
 void __init plat_irq_setup(void)
 {
+	/* disable IRQ7-0 */
+	ctrl_outl(0xff000000, INTC_INTMSK0);
+
+	/* disable IRL3-0 + IRL7-4 */
+	ctrl_outl(0xc0000000, INTC_INTMSK1);
+	ctrl_outl(0xfffefffe, INTC_INTMSK2);
+
+	/* select IRL mode for IRL3-0 + IRL7-4 */
+	ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+
+	/* disable holding function, ie enable "SH-4 Mode" */
+	ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+
+	register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+	switch (mode) {
+	case IRQ_MODE_IRQ:
+		/* select IRQ mode for IRL3-0 + IRL7-4 */
+		ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
+		register_intc_controller(&intc_irq_desc);
+		break;
+	case IRQ_MODE_IRL7654:
+		/* enable IRL7-4 but don't provide any masking */
+		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+		break;
+	case IRQ_MODE_IRL3210:
+		/* enable IRL0-3 but don't provide any masking */
+		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+		break;
+	case IRQ_MODE_IRL7654_MASK:
+		/* enable IRL7-4 and mask using cpu intc controller */
+		ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+		register_intc_controller(&intc_irl7654_desc);
+		break;
+	case IRQ_MODE_IRL3210_MASK:
+		/* enable IRL0-3 and mask using cpu intc controller */
+		ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+		register_intc_controller(&intc_irl3210_desc);
+		break;
+	default:
+		BUG();
+	}
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7780.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7780.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,189 @@
 #include <linux/serial.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 28,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 29,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 30,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffdc0008,
+		.end	= 0xffdc0013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 96,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffdc0014,
+		.end	= 0xffdc001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 97,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffdc0020,
+		.end	= 0xffdc002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 98,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
 
 static struct resource rtc_resources[] = {
 	[0] = {
@@ -58,6 +241,12 @@
 };
 
 static struct platform_device *sh7780_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
 	&rtc_device,
 	&sci_device,
 };
@@ -67,7 +256,22 @@
 	return platform_add_devices(sh7780_devices,
 				    ARRAY_SIZE(sh7780_devices));
 }
-__initcall(sh7780_devices_setup);
+arch_initcall(sh7780_devices_setup);
+
+static struct platform_device *sh7780_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7780_early_devices,
+				   ARRAY_SIZE(sh7780_early_devices));
+}
 
 enum {
 	UNUSED = 0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7785.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7785.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7785.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,39 +13,228 @@
 #include <linux/serial_sci.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/sh_timer.h>
 #include <asm/mmzone.h>
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu012_fck",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 28,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu012_fck",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 29,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu012_fck",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 30,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "tmu345_fck",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffdc0008,
+		.end	= 0xffdc0013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 96,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "tmu345_fck",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffdc0014,
+		.end	= 0xffdc001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 97,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "tmu345_fck",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffdc0020,
+		.end	= 0xffdc002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 98,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
+
 static struct plat_sci_port sci_platform_data[] = {
 	{
 		.mapbase	= 0xffea0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 40, 40, 40, 40 },
+		.clk		= "scif_fck",
 	}, {
 		.mapbase	= 0xffeb0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 44, 44, 44, 44 },
+		.clk		= "scif_fck",
 	}, {
 		.mapbase	= 0xffec0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 60, 60, 60, 60 },
+		.clk		= "scif_fck",
 	}, {
 		.mapbase	= 0xffed0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 61, 61, 61, 61 },
+		.clk		= "scif_fck",
 	}, {
 		.mapbase	= 0xffee0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 62, 62, 62, 62 },
+		.clk		= "scif_fck",
 	}, {
 		.mapbase	= 0xffef0000,
 		.flags		= UPF_BOOT_AUTOCONF,
 		.type		= PORT_SCIF,
 		.irqs		= { 63, 63, 63, 63 },
+		.clk		= "scif_fck",
 	}, {
 		.flags = 0,
 	}
@@ -60,6 +249,12 @@
 };
 
 static struct platform_device *sh7785_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
 	&sci_device,
 };
 
@@ -68,7 +263,22 @@
 	return platform_add_devices(sh7785_devices,
 				    ARRAY_SIZE(sh7785_devices));
 }
-__initcall(sh7785_devices_setup);
+arch_initcall(sh7785_devices_setup);
+
+static struct platform_device *sh7785_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7785_early_devices,
+				   ARRAY_SIZE(sh7785_early_devices));
+}
 
 enum {
 	UNUSED = 0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2009  Renesas Solutions Corp.
  * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Paul Mundt <paul.mundt@renesas.com>
  *
  * Based on SH7785 Setup
  *
@@ -19,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <linux/sh_timer.h>
 #include <asm/mmzone.h>
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -69,6 +71,368 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffd80008,
+		.end	= 0xffd80013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffd80014,
+		.end	= 0xffd8001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffd80020,
+		.end	= 0xffd8002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffda0008,
+		.end	= 0xffda0013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 20,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffda0014,
+		.end	= 0xffda001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 21,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffda0020,
+		.end	= 0xffda002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 22,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
+
+static struct sh_timer_config tmu6_platform_data = {
+	.name = "TMU6",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu6_resources[] = {
+	[0] = {
+		.name	= "TMU6",
+		.start	= 0xffdc0008,
+		.end	= 0xffdc0013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 45,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu6_device = {
+	.name		= "sh_tmu",
+	.id		= 6,
+	.dev = {
+		.platform_data	= &tmu6_platform_data,
+	},
+	.resource	= tmu6_resources,
+	.num_resources	= ARRAY_SIZE(tmu6_resources),
+};
+
+static struct sh_timer_config tmu7_platform_data = {
+	.name = "TMU7",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu7_resources[] = {
+	[0] = {
+		.name	= "TMU7",
+		.start	= 0xffdc0014,
+		.end	= 0xffdc001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 45,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu7_device = {
+	.name		= "sh_tmu",
+	.id		= 7,
+	.dev = {
+		.platform_data	= &tmu7_platform_data,
+	},
+	.resource	= tmu7_resources,
+	.num_resources	= ARRAY_SIZE(tmu7_resources),
+};
+
+static struct sh_timer_config tmu8_platform_data = {
+	.name = "TMU8",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu8_resources[] = {
+	[0] = {
+		.name	= "TMU8",
+		.start	= 0xffdc0020,
+		.end	= 0xffdc002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 45,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu8_device = {
+	.name		= "sh_tmu",
+	.id		= 8,
+	.dev = {
+		.platform_data	= &tmu8_platform_data,
+	},
+	.resource	= tmu8_resources,
+	.num_resources	= ARRAY_SIZE(tmu8_resources),
+};
+
+static struct sh_timer_config tmu9_platform_data = {
+	.name = "TMU9",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu9_resources[] = {
+	[0] = {
+		.name	= "TMU9",
+		.start	= 0xffde0008,
+		.end	= 0xffde0013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 46,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu9_device = {
+	.name		= "sh_tmu",
+	.id		= 9,
+	.dev = {
+		.platform_data	= &tmu9_platform_data,
+	},
+	.resource	= tmu9_resources,
+	.num_resources	= ARRAY_SIZE(tmu9_resources),
+};
+
+static struct sh_timer_config tmu10_platform_data = {
+	.name = "TMU10",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu10_resources[] = {
+	[0] = {
+		.name	= "TMU10",
+		.start	= 0xffde0014,
+		.end	= 0xffde001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 46,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu10_device = {
+	.name		= "sh_tmu",
+	.id		= 10,
+	.dev = {
+		.platform_data	= &tmu10_platform_data,
+	},
+	.resource	= tmu10_resources,
+	.num_resources	= ARRAY_SIZE(tmu10_resources),
+};
+
+static struct sh_timer_config tmu11_platform_data = {
+	.name = "TMU11",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu11_resources[] = {
+	[0] = {
+		.name	= "TMU11",
+		.start	= 0xffde0020,
+		.end	= 0xffde002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 46,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu11_device = {
+	.name		= "sh_tmu",
+	.id		= 11,
+	.dev = {
+		.platform_data	= &tmu11_platform_data,
+	},
+	.resource	= tmu11_resources,
+	.num_resources	= ARRAY_SIZE(tmu11_resources),
+};
+
 static struct resource usb_ohci_resources[] = {
 	[0] = {
 		.start	= 0xffe70400,
@@ -94,6 +458,21 @@
 	.resource	= usb_ohci_resources,
 };
 
+static struct platform_device *sh7786_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+	&tmu6_device,
+	&tmu7_device,
+	&tmu8_device,
+	&tmu9_device,
+	&tmu10_device,
+	&tmu11_device,
+};
+
 static struct platform_device *sh7786_devices[] __initdata = {
 	&sci_device,
 	&usb_ohci_device,
@@ -156,11 +535,25 @@
 
 static int __init sh7786_devices_setup(void)
 {
+	int ret;
+
 	sh7786_usb_setup();
+
+	ret = platform_add_devices(sh7786_early_devices,
+				   ARRAY_SIZE(sh7786_early_devices));
+	if (unlikely(ret != 0))
+		return ret;
+
 	return platform_add_devices(sh7786_devices,
 				    ARRAY_SIZE(sh7786_devices));
 }
-device_initcall(sh7786_devices_setup);
+arch_initcall(sh7786_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7786_early_devices,
+				   ARRAY_SIZE(sh7786_early_devices));
+}
 
 enum {
 	UNUSED = 0,
@@ -202,9 +595,8 @@
 	HSPI,
 	GPIO0, GPIO1,
 	Thermal,
-	INTC0, INTC1, INTC2, INTC3, INTC4, INTC5, INTC6, INTC7,
-
-	/* interrupt groups */
+	INTICI0, INTICI1, INTICI2, INTICI3,
+	INTICI4, INTICI5, INTICI6, INTICI7,
 };
 
 static struct intc_vect vectors[] __initdata = {
@@ -245,10 +637,12 @@
 	INTC_VECT(HSPI, 0xe80),
 	INTC_VECT(GPIO0, 0xea0), INTC_VECT(GPIO1, 0xec0),
 	INTC_VECT(Thermal, 0xee0),
+	INTC_VECT(INTICI0, 0xf00), INTC_VECT(INTICI1, 0xf20),
+	INTC_VECT(INTICI2, 0xf40), INTC_VECT(INTICI3, 0xf60),
+	INTC_VECT(INTICI4, 0xf80), INTC_VECT(INTICI5, 0xfa0),
+	INTC_VECT(INTICI6, 0xfc0), INTC_VECT(INTICI7, 0xfe0),
 };
 
-/* FIXME: Main CPU support only now */
-#if 1 /* Main CPU */
 #define CnINTMSK0	0xfe410030
 #define CnINTMSK1	0xfe410040
 #define CnINTMSKCLR0	0xfe410050
@@ -261,21 +655,6 @@
 #define CnINT2MSKCR1	0xfe410a34
 #define CnINT2MSKCR2	0xfe410a38
 #define CnINT2MSKCR3	0xfe410a3c
-#else /* Sub CPU */
-#define CnINTMSK0	0xfe410034
-#define CnINTMSK1	0xfe410044
-#define CnINTMSKCLR0	0xfe410054
-#define CnINTMSKCLR1	0xfe410064
-#define CnINT2MSKR0	0xfe410b20
-#define CnINT2MSKR1	0xfe410b24
-#define CnINT2MSKR2	0xfe410b28
-#define CnINT2MSKR3	0xfe410b2c
-#define CnINT2MSKCR0	0xfe410b30
-#define CnINT2MSKCR1	0xfe410b34
-#define CnINT2MSKCR2	0xfe410b38
-#define CnINT2MSKCR3	0xfe410b3c
-#endif
-
 #define INTMSK2		0xfe410068
 #define INTMSKCLR2	0xfe41006c
 
@@ -360,6 +739,9 @@
 						  GPIO1, Thermal } },
 	{ 0xfe41085c, 0, 32, 8, /* INT2PRI23 */ { 0, 0, 0, 0 } },
 	{ 0xfe410860, 0, 32, 8, /* INT2PRI24 */ { 0, 0, 0, 0 } },
+	{ 0xfe410090, 0xfe4100a0, 32, 4, /* CnICIPRI / CnICIPRICLR */
+	  { INTICI7, INTICI6, INTICI5, INTICI4,
+	    INTICI3, INTICI2, INTICI1, INTICI0 }, INTC_SMP(4, 2) },
 };
 
 static DECLARE_INTC_DESC(intc_desc, "sh7786", vectors, NULL,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-shx3.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-shx3.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/setup-shx3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/setup-shx3.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
- * SH-X3 Setup
+ * SH-X3 Prototype Setup
  *
- *  Copyright (C) 2007  Paul Mundt
+ *  Copyright (C) 2007 - 2009  Paul Mundt
  *
  * 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
@@ -12,6 +12,7 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/io.h>
+#include <linux/sh_timer.h>
 #include <asm/mmzone.h>
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -48,16 +49,220 @@
 	},
 };
 
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= 0xffc10008,
+		.end	= 0xffc10013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 16,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= 0xffc10014,
+		.end	= 0xffc1001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 17,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= 0xffc10020,
+		.end	= 0xffc1002f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 18,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct sh_timer_config tmu3_platform_data = {
+	.name = "TMU3",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu3_resources[] = {
+	[0] = {
+		.name	= "TMU3",
+		.start	= 0xffc20008,
+		.end	= 0xffc20013,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 19,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu3_device = {
+	.name		= "sh_tmu",
+	.id		= 3,
+	.dev = {
+		.platform_data	= &tmu3_platform_data,
+	},
+	.resource	= tmu3_resources,
+	.num_resources	= ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+	.name = "TMU4",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu4_resources[] = {
+	[0] = {
+		.name	= "TMU4",
+		.start	= 0xffc20014,
+		.end	= 0xffc2001f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 20,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu4_device = {
+	.name		= "sh_tmu",
+	.id		= 4,
+	.dev = {
+		.platform_data	= &tmu4_platform_data,
+	},
+	.resource	= tmu4_resources,
+	.num_resources	= ARRAY_SIZE(tmu4_resources),
+};
+
+static struct sh_timer_config tmu5_platform_data = {
+	.name = "TMU5",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu5_resources[] = {
+	[0] = {
+		.name	= "TMU5",
+		.start	= 0xffc20020,
+		.end	= 0xffc2002b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 21,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu5_device = {
+	.name		= "sh_tmu",
+	.id		= 5,
+	.dev = {
+		.platform_data	= &tmu5_platform_data,
+	},
+	.resource	= tmu5_resources,
+	.num_resources	= ARRAY_SIZE(tmu5_resources),
+};
+
+static struct platform_device *shx3_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+	&tmu3_device,
+	&tmu4_device,
+	&tmu5_device,
+};
+
 static struct platform_device *shx3_devices[] __initdata = {
 	&sci_device,
 };
 
 static int __init shx3_devices_setup(void)
 {
+	int ret;
+
+	ret = platform_add_devices(shx3_early_devices,
+				   ARRAY_SIZE(shx3_early_devices));
+	if (unlikely(ret != 0))
+		return ret;
+
 	return platform_add_devices(shx3_devices,
 				    ARRAY_SIZE(shx3_devices));
 }
-__initcall(shx3_devices_setup);
+arch_initcall(shx3_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(shx3_early_devices,
+				   ARRAY_SIZE(shx3_early_devices));
+}
 
 enum {
 	UNUSED = 0,
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh4a/smp-shx3.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,8 +35,7 @@
 	unsigned int cpu = 0;
 	int i, num;
 
-	cpus_clear(cpu_possible_map);
-	cpu_set(cpu, cpu_possible_map);
+	init_cpu_possible(cpumask_of(cpu));
 
 	__cpu_number_map[0] = 0;
 	__cpu_logical_map[0] = 0;
@@ -46,7 +45,7 @@
 	 * for the total number of cores.
 	 */
 	for (i = 1, num = 0; i < NR_CPUS; i++) {
-		cpu_set(i, cpu_possible_map);
+		set_cpu_possible(i, true);
 		__cpu_number_map[i] = ++num;
 		__cpu_logical_map[num] = i;
 	}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/clock-sh5.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/clock-sh5.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/clock-sh5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/clock-sh5.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,30 +32,30 @@
 	.init		= master_clk_init,
 };
 
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(cprc_base) >> 12) & 0x0007;
-	clk->rate = clk->parent->rate / ifc_table[idx];
+	return clk->parent->rate / ifc_table[idx];
 }
 
 static struct clk_ops sh5_module_clk_ops = {
 	.recalc		= module_clk_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(cprc_base) >> 3) & 0x0007;
-	clk->rate = clk->parent->rate / ifc_table[idx];
+	return clk->parent->rate / ifc_table[idx];
 }
 
 static struct clk_ops sh5_bus_clk_ops = {
 	.recalc		= bus_clk_recalc,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
 {
 	int idx = (ctrl_inw(cprc_base) & 0x0007);
-	clk->rate = clk->parent->rate / ifc_table[idx];
+	return clk->parent->rate / ifc_table[idx];
 }
 
 static struct clk_ops sh5_cpu_clk_ops = {
@@ -71,7 +71,7 @@
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
-	cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC");
+	cprc_base = (unsigned long)ioremap_nocache(CPRC_BASE, 1024);
 	BUG_ON(!cprc_base);
 
 	if (idx < ARRAY_SIZE(sh5_clk_ops))
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/entry.S linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/entry.S
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -812,27 +812,6 @@
 	! exceptions
 	add	SP, ZERO, r14
 
-#ifdef CONFIG_POOR_MANS_STRACE
-	/* We've pushed all the registers now, so only r2-r4 hold anything
-	 * useful. Move them into callee save registers */
-	or	r2, ZERO, r28
-	or	r3, ZERO, r29
-	or	r4, ZERO, r30
-
-	/* Preserve r2 as the event code */
-	movi	evt_debug, r3
-	ori	r3, 1, r3
-	ptabs	r3, tr0
-
-	or	SP, ZERO, r6
-	getcon	TRA, r5
-	blink	tr0, LINK
-
-	or	r28, ZERO, r2
-	or	r29, ZERO, r3
-	or	r30, ZERO, r4
-#endif
-
 	/* For syscall and debug race condition, get TRA now */
 	getcon	TRA, r5
 
@@ -887,11 +866,6 @@
  */
 	.global ret_from_irq
 ret_from_irq:
-#ifdef CONFIG_POOR_MANS_STRACE
-	pta	evt_debug_ret_from_irq, tr0
-	ori	SP, 0, r2
-	blink	tr0, LINK
-#endif
 	ld.q	SP, FRAME_S(FSSR), r6
 	shlri	r6, 30, r6
 	andi	r6, 1, r6
@@ -905,12 +879,6 @@
 ret_from_exception:
 	preempt_stop()
 
-#ifdef CONFIG_POOR_MANS_STRACE
-	pta	evt_debug_ret_from_exc, tr0
-	ori	SP, 0, r2
-	blink	tr0, LINK
-#endif
-
 	ld.q	SP, FRAME_S(FSSR), r6
 	shlri	r6, 30, r6
 	andi	r6, 1, r6
@@ -1236,18 +1204,6 @@
 	.global syscall_ret
 syscall_ret:
 	st.q	SP, FRAME_R(9), r2	/* Expecting SP back to BASIC frame */
-
-#ifdef CONFIG_POOR_MANS_STRACE
-	/* nothing useful in registers at this point */
-
-	movi	evt_debug2, r5
-	ori	r5, 1, r5
-	ptabs	r5, tr0
-	ld.q	SP, FRAME_R(9), r2
-	or	SP, ZERO, r3
-	blink	tr0, LINK
-#endif
-
 	ld.q	SP, FRAME_S(FSPC), r2
 	addi	r2, 4, r2		/* Move PC, being pre-execution event */
 	st.q	SP, FRAME_S(FSPC), r2
@@ -1268,25 +1224,12 @@
 	ptabs	r5, tr0
 	blink	tr0, LINK
 
-#ifdef CONFIG_POOR_MANS_STRACE
-	/* nothing useful in registers at this point */
-
-	movi	evt_debug2, r5
-	ori	r5, 1, r5
-	ptabs	r5, tr0
-	ld.q	SP, FRAME_R(9), r2
-	or	SP, ZERO, r3
-	blink	tr0, LINK
-#endif
-
 	ld.q	SP, FRAME_S(FSPC), r2
 	addi	r2, 4, r2		/* Move PC, being pre-execution event */
 	st.q	SP, FRAME_S(FSPC), r2
 	pta	ret_from_syscall, tr0
 	blink	tr0, ZERO
 
-
-
 syscall_allowed:
 	/* Use LINK to deflect the exit point, default is syscall_ret */
 	pta	syscall_ret, tr0
@@ -1410,8 +1353,8 @@
 	   r2(out) : result quadword
 
 	   This is provided as a cheapskate way of manipulating device
-	   registers for debugging (to avoid the need to onchip_remap the debug
-	   module, and to avoid the need to onchip_remap the watchpoint
+	   registers for debugging (to avoid the need to ioremap the debug
+	   module, and to avoid the need to ioremap the watchpoint
 	   controller in a way that identity maps sufficient bits to avoid the
 	   SH5-101 cut2 silicon defect).
 
@@ -1459,8 +1402,8 @@
 	   r3 : quadword value to write.
 
 	   This is provided as a cheapskate way of manipulating device
-	   registers for debugging (to avoid the need to onchip_remap the debug
-	   module, and to avoid the need to onchip_remap the watchpoint
+	   registers for debugging (to avoid the need to ioremap the debug
+	   module, and to avoid the need to ioremap the watchpoint
 	   controller in a way that identity maps sufficient bits to avoid the
 	   SH5-101 cut2 silicon defect).
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/Makefile linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,9 @@
 obj-$(CONFIG_SH_FPU)		+= fpu.o
 obj-$(CONFIG_KALLSYMS)		+= unwind.o
 
+# CPU subtype setup
+obj-$(CONFIG_CPU_SH5)		+= setup-sh5.o
+
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH5)		:= clock-sh5.o
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/setup-sh5.c linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/setup-sh5.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/sh5/setup-sh5.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/sh5/setup-sh5.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * SH5-101/SH5-103 CPU Setup
+ *
+ *  Copyright (C) 2009  Paul Mundt
+ *
+ * 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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/sh_timer.h>
+#include <asm/addrspace.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+	{
+		.mapbase	= PHYS_PERIPHERAL_BLOCK + 0x01030000,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+		.type		= PORT_SCIF,
+		.irqs		= { 39, 40, 42, 0 },
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct platform_device sci_device = {
+	.name		= "sh-sci",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= sci_platform_data,
+	},
+};
+
+static struct resource rtc_resources[] = {
+	[0] = {
+		.start	= PHYS_PERIPHERAL_BLOCK + 0x01040000,
+		.end	= PHYS_PERIPHERAL_BLOCK + 0x01040000 + 0x58 - 1,
+		.flags	= IORESOURCE_IO,
+	},
+	[1] = {
+		/* Period IRQ */
+		.start	= IRQ_PRI,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* Carry IRQ */
+		.start	= IRQ_CUI,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		/* Alarm IRQ */
+		.start	= IRQ_ATI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device rtc_device = {
+	.name		= "sh-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtc_resources),
+	.resource	= rtc_resources,
+};
+
+#define	TMU_BLOCK_OFF	0x01020000
+#define TMU_BASE	PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
+#define TMU0_BASE	(TMU_BASE + 0x8 + (0xc * 0x0))
+#define TMU1_BASE	(TMU_BASE + 0x8 + (0xc * 0x1))
+#define TMU2_BASE	(TMU_BASE + 0x8 + (0xc * 0x2))
+
+static struct sh_timer_config tmu0_platform_data = {
+	.name = "TMU0",
+	.channel_offset = 0x04,
+	.timer_bit = 0,
+	.clk = "peripheral_clk",
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+	[0] = {
+		.name	= "TMU0",
+		.start	= TMU0_BASE,
+		.end	= TMU0_BASE + 0xc - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_TUNI0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu0_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu0_platform_data,
+	},
+	.resource	= tmu0_resources,
+	.num_resources	= ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+	.name = "TMU1",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clk = "peripheral_clk",
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+	[0] = {
+		.name	= "TMU1",
+		.start	= TMU1_BASE,
+		.end	= TMU1_BASE + 0xc - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_TUNI1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu1_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu1_platform_data,
+	},
+	.resource	= tmu1_resources,
+	.num_resources	= ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+	.name = "TMU2",
+	.channel_offset = 0x1c,
+	.timer_bit = 2,
+	.clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+	[0] = {
+		.name	= "TMU2",
+		.start	= TMU2_BASE,
+		.end	= TMU2_BASE + 0xc - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_TUNI2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu2_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu2_platform_data,
+	},
+	.resource	= tmu2_resources,
+	.num_resources	= ARRAY_SIZE(tmu2_resources),
+};
+
+static struct platform_device *sh5_early_devices[] __initdata = {
+	&tmu0_device,
+	&tmu1_device,
+	&tmu2_device,
+};
+
+static struct platform_device *sh5_devices[] __initdata = {
+	&sci_device,
+	&rtc_device,
+};
+
+static int __init sh5_devices_setup(void)
+{
+	int ret;
+
+	ret = platform_add_devices(sh5_early_devices,
+				   ARRAY_SIZE(sh5_early_devices));
+	if (unlikely(ret != 0))
+		return ret;
+
+	return platform_add_devices(sh5_devices,
+				    ARRAY_SIZE(sh5_devices));
+}
+arch_initcall(sh5_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh5_early_devices,
+				   ARRAY_SIZE(sh5_early_devices));
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/shmobile/sleep.S linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/shmobile/sleep.S
--- linux-libre-2.6.30-gnu/arch/sh/kernel/cpu/shmobile/sleep.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/cpu/shmobile/sleep.S	2009-09-09 18:13:59.000000000 -0400
@@ -26,8 +26,30 @@
 
 	tst	#SUSP_SH_SF, r0
 	bt	skip_set_sf
+#ifdef CONFIG_CPU_SUBTYPE_SH7724
+	/* DBSC: put memory in self-refresh mode */
 
-	/* SDRAM: disable power down and put in self-refresh mode */
+	mov.l	dben_reg, r4
+	mov.l	dben_data0, r1
+	mov.l	r1, @r4
+
+	mov.l	dbrfpdn0_reg, r4
+	mov.l	dbrfpdn0_data0, r1
+	mov.l	r1, @r4
+
+	mov.l	dbcmdcnt_reg, r4
+	mov.l	dbcmdcnt_data0, r1
+	mov.l	r1, @r4
+
+	mov.l	dbcmdcnt_reg, r4
+	mov.l	dbcmdcnt_data1, r1
+	mov.l	r1, @r4
+
+	mov.l	dbrfpdn0_reg, r4
+	mov.l	dbrfpdn0_data1, r1
+	mov.l	r1, @r4
+#else
+	/* SBSC: disable power down and put in self-refresh mode */
 	mov.l	1f, r4
 	mov.l	2f, r1
 	mov.l	@r4, r2
@@ -35,6 +57,7 @@
 	mov.l   3f, r3
 	and	r3, r2
 	mov.l	r2, @r4
+#endif
 
 skip_set_sf:
 	tst	#SUSP_SH_SLEEP, r0
@@ -84,7 +107,36 @@
 	tst	#SUSP_SH_SF, r0
 	bt	skip_restore_sf
 
-	/* SDRAM: set auto-refresh mode */
+#ifdef CONFIG_CPU_SUBTYPE_SH7724
+	/* DBSC: put memory in auto-refresh mode */
+
+	mov.l	dbrfpdn0_reg, r4
+	mov.l	dbrfpdn0_data0, r1
+	mov.l	r1, @r4
+
+	/* sleep 140 ns */
+	nop
+	nop
+	nop
+	nop
+
+	mov.l	dbcmdcnt_reg, r4
+	mov.l	dbcmdcnt_data0, r1
+	mov.l	r1, @r4
+
+	mov.l	dbcmdcnt_reg, r4
+	mov.l	dbcmdcnt_data1, r1
+	mov.l	r1, @r4
+
+	mov.l	dben_reg, r4
+	mov.l	dben_data1, r1
+	mov.l	r1, @r4
+
+	mov.l	dbrfpdn0_reg, r4
+	mov.l	dbrfpdn0_data2, r1
+	mov.l	r1, @r4
+#else
+	/* SBSC: set auto-refresh mode */
 	mov.l	1f, r4
 	mov.l	@r4, r2
 	mov.l   4f, r3
@@ -98,15 +150,29 @@
 	add	r4, r3
 	or	r2, r3
 	mov.l	r3, @r1
+#endif
 skip_restore_sf:
 	rts
 	 nop
 
 	.balign 4
+#ifdef CONFIG_CPU_SUBTYPE_SH7724
+dben_reg:	.long	0xfd000010 /* DBEN */
+dben_data0:	.long	0
+dben_data1:	.long	1
+dbrfpdn0_reg:	.long	0xfd000040 /* DBRFPDN0 */
+dbrfpdn0_data0:	.long	0
+dbrfpdn0_data1:	.long	1
+dbrfpdn0_data2:	.long	0x00010000
+dbcmdcnt_reg:	.long	0xfd000014 /* DBCMDCNT */
+dbcmdcnt_data0:	.long	2
+dbcmdcnt_data1:	.long	4
+#else
 1:	.long	0xfe400008 /* SDCR0 */
 2:	.long	0x00000400
 3:	.long	0xffff7fff
 4:	.long	0xfffffbff
+#endif
 5:	.long	0xa4150020 /* STBCR */
 6:	.long   0xfe40001c /* RTCOR */
 7:	.long   0xfe400018 /* RTCNT */
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/ftrace.c linux-libre-2.6.31-gnu/arch/sh/kernel/ftrace.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/ftrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/ftrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Matt Fleming <mjf@gentoo.org>
+ * Copyright (C) 2008 Matt Fleming <matt@console-pimps.org>
  * Copyright (C) 2008 Paul Mundt <lethal@linux-sh.org>
  *
  * Code for replacing ftrace calls with jumps.
@@ -19,30 +19,37 @@
 #include <asm/ftrace.h>
 #include <asm/cacheflush.h>
 
-static unsigned char ftrace_nop[] = {
-	0x09, 0x00,		/* nop */
-	0x09, 0x00,		/* nop */
-};
-
 static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE];
 
-unsigned char *ftrace_nop_replace(void)
+static unsigned char ftrace_nop[4];
+/*
+ * If we're trying to nop out a call to a function, we instead
+ * place a call to the address after the memory table.
+ *
+ * 8c011060 <a>:
+ * 8c011060:       02 d1           mov.l   8c01106c <a+0xc>,r1
+ * 8c011062:       22 4f           sts.l   pr,@-r15
+ * 8c011064:       02 c7           mova    8c011070 <a+0x10>,r0
+ * 8c011066:       2b 41           jmp     @r1
+ * 8c011068:       2a 40           lds     r0,pr
+ * 8c01106a:       09 00           nop
+ * 8c01106c:       68 24           .word 0x2468     <--- ip
+ * 8c01106e:       1d 8c           .word 0x8c1d
+ * 8c011070:       26 4f           lds.l   @r15+,pr <--- ip + MCOUNT_INSN_SIZE
+ *
+ * We write 0x8c011070 to 0x8c01106c so that on entry to a() we branch
+ * past the _mcount call and continue executing code like normal.
+ */
+static unsigned char *ftrace_nop_replace(unsigned long ip)
 {
+	__raw_writel(ip + MCOUNT_INSN_SIZE, ftrace_nop);
 	return ftrace_nop;
 }
 
-static int is_sh_nop(unsigned char *ip)
-{
-	return strncmp(ip, ftrace_nop, sizeof(ftrace_nop));
-}
-
-unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
+static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
 {
 	/* Place the address in the memory table. */
-	if (addr == CALLER_ADDR)
-		__raw_writel(addr + MCOUNT_INSN_OFFSET, ftrace_replaced_code);
-	else
-		__raw_writel(addr, ftrace_replaced_code);
+	__raw_writel(addr, ftrace_replaced_code);
 
 	/*
 	 * No locking needed, this must be called via kstop_machine
@@ -51,7 +58,7 @@
 	return ftrace_replaced_code;
 }
 
-int ftrace_modify_code(unsigned long ip, unsigned char *old_code,
+static int ftrace_modify_code(unsigned long ip, unsigned char *old_code,
 		       unsigned char *new_code)
 {
 	unsigned char replaced[MCOUNT_INSN_SIZE];
@@ -66,13 +73,6 @@
 	 * kstop_machine, or before SMP starts.
 	 */
 
-	/*
-	 * If we're trying to nop out a call to a function, we instead
-	 * place a call to the address after the memory table.
-	 */
-	if (is_sh_nop(new_code) == 0)
-		__raw_writel(ip + MCOUNT_INSN_SIZE, (unsigned long)new_code);
-
 	/* read the text we want to modify */
 	if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
 		return -EFAULT;
@@ -92,13 +92,13 @@
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-	unsigned long ip = (unsigned long)(&ftrace_call);
+	unsigned long ip = (unsigned long)(&ftrace_call) + MCOUNT_INSN_OFFSET;
 	unsigned char old[MCOUNT_INSN_SIZE], *new;
 
-	memcpy(old, (unsigned char *)(ip + MCOUNT_INSN_OFFSET), MCOUNT_INSN_SIZE);
+	memcpy(old, (unsigned char *)ip, MCOUNT_INSN_SIZE);
 	new = ftrace_call_replace(ip, (unsigned long)func);
 
-	return ftrace_modify_code(ip + MCOUNT_INSN_OFFSET, old, new);
+	return ftrace_modify_code(ip, old, new);
 }
 
 int ftrace_make_nop(struct module *mod,
@@ -108,7 +108,7 @@
 	unsigned long ip = rec->ip;
 
 	old = ftrace_call_replace(ip, addr);
-	new = ftrace_nop_replace();
+	new = ftrace_nop_replace(ip);
 
 	return ftrace_modify_code(rec->ip, old, new);
 }
@@ -118,7 +118,7 @@
 	unsigned char *new, *old;
 	unsigned long ip = rec->ip;
 
-	old = ftrace_nop_replace();
+	old = ftrace_nop_replace(ip);
 	new = ftrace_call_replace(ip, addr);
 
 	return ftrace_modify_code(rec->ip, old, new);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/idle.c linux-libre-2.6.31-gnu/arch/sh/kernel/idle.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/idle.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/idle.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * The idle loop for all SuperH platforms.
  *
- *  Copyright (C) 2002 - 2008  Paul Mundt
+ *  Copyright (C) 2002 - 2009  Paul Mundt
  *
  * 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
@@ -15,6 +15,7 @@
 #include <linux/preempt.h>
 #include <linux/thread_info.h>
 #include <linux/irqflags.h>
+#include <linux/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -79,3 +80,23 @@
 		check_pgt_cache();
 	}
 }
+
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+	smp_mb();
+	/* kick all the CPUs so that they exit out of pm_idle */
+	smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/init_task.c linux-libre-2.6.31-gnu/arch/sh/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,9 +10,6 @@
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 struct pt_regs fake_swapper_regs;
-struct mm_struct init_mm = INIT_MM(init_mm);
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial thread structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/io.c linux-libre-2.6.31-gnu/arch/sh/kernel/io.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,7 @@
  * for more details.
  */
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <asm/machvec.h>
 #include <asm/io.h>
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/io_trapped.c linux-libre-2.6.31-gnu/arch/sh/kernel/io_trapped.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/io_trapped.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/io_trapped.c	2009-09-09 18:13:59.000000000 -0400
@@ -267,7 +267,7 @@
 int handle_trapped_io(struct pt_regs *regs, unsigned long address)
 {
 	mm_segment_t oldfs;
-	opcode_t instruction;
+	insn_size_t instruction;
 	int tmp;
 
 	if (!lookup_tiop(address))
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/irq.c linux-libre-2.6.31-gnu/arch/sh/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,39 +31,64 @@
 }
 
 #if defined(CONFIG_PROC_FS)
+/*
+ * /proc/interrupts printing:
+ */
+static int show_other_interrupts(struct seq_file *p, int prec)
+{
+	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+	return 0;
+}
+
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
+	unsigned long flags, any_count = 0;
+	int i = *(loff_t *)v, j, prec;
+	struct irqaction *action;
+	struct irq_desc *desc;
+
+	if (i > nr_irqs)
+		return 0;
+
+	for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
+		j *= 10;
+
+	if (i == nr_irqs)
+		return show_other_interrupts(p, prec);
 
 	if (i == 0) {
-		seq_puts(p, "           ");
+		seq_printf(p, "%*s", prec + 8, "");
 		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
+			seq_printf(p, "CPU%-8d", j);
 		seq_putc(p, '\n');
 	}
 
-	if (i < sh_mv.mv_nr_irqs) {
-		spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto unlock;
-		seq_printf(p, "%3d: ",i);
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
-		seq_printf(p, "-%-8s", irq_desc[i].name);
-		seq_printf(p, "  %s", action->name);
+	desc = irq_to_desc(i);
+	if (!desc)
+		return 0;
 
-		for (action=action->next; action; action = action->next)
+	spin_lock_irqsave(&desc->lock, flags);
+	for_each_online_cpu(j)
+		any_count |= kstat_irqs_cpu(i, j);
+	action = desc->action;
+	if (!action && !any_count)
+		goto out;
+
+	seq_printf(p, "%*d: ", prec, i);
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+	seq_printf(p, " %14s", desc->chip->name);
+	seq_printf(p, "-%-8s", desc->name);
+
+	if (action) {
+		seq_printf(p, "  %s", action->name);
+		while ((action = action->next) != NULL)
 			seq_printf(p, ", %s", action->name);
-		seq_putc(p, '\n');
-unlock:
-		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == sh_mv.mv_nr_irqs)
-		seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
+	}
 
+	seq_putc(p, '\n');
+out:
+	spin_unlock_irqrestore(&desc->lock, flags);
 	return 0;
 }
 #endif
@@ -254,3 +279,11 @@
 
 	irq_ctx_init(smp_processor_id());
 }
+
+#ifdef CONFIG_SPARSE_IRQ
+int __init arch_probe_nr_irqs(void)
+{
+	nr_irqs = sh_mv.mv_nr_irqs;
+	return 0;
+}
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/kgdb.c linux-libre-2.6.31-gnu/arch/sh/kernel/kgdb.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/kgdb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/kgdb.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,7 @@
 /* Calculate the new address for after a step */
 static short *get_step_address(struct pt_regs *linux_regs)
 {
-	opcode_t op = __raw_readw(linux_regs->pc);
+	insn_size_t op = __raw_readw(linux_regs->pc);
 	long addr;
 
 	/* BT */
@@ -134,7 +134,7 @@
  */
 
 static unsigned long stepped_address;
-static opcode_t stepped_opcode;
+static insn_size_t stepped_opcode;
 
 static void do_single_step(struct pt_regs *linux_regs)
 {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/localtimer.c linux-libre-2.6.31-gnu/arch/sh/kernel/localtimer.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/localtimer.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * Dummy local timer
+ *
+ * Copyright (C) 2008  Paul Mundt
+ *
+ * cloned from:
+ *
+ *  linux/arch/arm/mach-realview/localtimer.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/jiffies.h>
+#include <linux/percpu.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+
+static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
+
+/*
+ * Used on SMP for either the local timer or SMP_MSG_TIMER
+ */
+void local_timer_interrupt(void)
+{
+	struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
+
+	clk->event_handler(clk);
+}
+
+static void dummy_timer_set_mode(enum clock_event_mode mode,
+				 struct clock_event_device *clk)
+{
+}
+
+void __cpuinit local_timer_setup(unsigned int cpu)
+{
+	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
+
+	clk->name		= "dummy_timer";
+	clk->features		= CLOCK_EVT_FEAT_DUMMY;
+	clk->rating		= 200;
+	clk->mult		= 1;
+	clk->set_mode		= dummy_timer_set_mode;
+	clk->broadcast		= smp_timer_broadcast;
+	clk->cpumask		= cpumask_of(cpu);
+
+	clockevents_register_device(clk);
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/machvec.c linux-libre-2.6.31-gnu/arch/sh/kernel/machvec.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/machvec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/machvec.c	2009-09-09 18:13:59.000000000 -0400
@@ -129,6 +129,7 @@
 	mv_set(ioport_map);
 	mv_set(ioport_unmap);
 	mv_set(irq_demux);
+	mv_set(mode_pins);
 
 	if (!sh_mv.mv_nr_irqs)
 		sh_mv.mv_nr_irqs = NR_IRQS;
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/Makefile_32 linux-libre-2.6.31-gnu/arch/sh/kernel/Makefile_32
--- linux-libre-2.6.30-gnu/arch/sh/kernel/Makefile_32	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/Makefile_32	2009-09-09 18:13:59.000000000 -0400
@@ -11,10 +11,10 @@
 
 obj-y	:= debugtraps.o idle.o io.o io_generic.o irq.o			\
 	   machvec.o process_32.o ptrace_32.o setup.o signal_32.o	\
-	   sys_sh.o sys_sh32.o syscalls_32.o time_32.o topology.o	\
+	   sys_sh.o sys_sh32.o syscalls_32.o time.o topology.o	\
 	   traps.o traps_32.o
 
-obj-y				+= cpu/ timers/
+obj-y				+= cpu/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
@@ -32,4 +32,6 @@
 obj-$(CONFIG_DUMP_CODE)		+= disassemble.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o
 
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= localtimer.o
+
 EXTRA_CFLAGS += -Werror
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/Makefile_64 linux-libre-2.6.31-gnu/arch/sh/kernel/Makefile_64
--- linux-libre-2.6.30-gnu/arch/sh/kernel/Makefile_64	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/Makefile_64	2009-09-09 18:13:59.000000000 -0400
@@ -2,19 +2,18 @@
 
 obj-y	:= debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \
 	   ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
-	   syscalls_64.o time_64.o topology.o traps.o traps_64.o
+	   syscalls_64.o time.o topology.o traps.o traps_64.o
 
-obj-y				+= cpu/ timers/
-obj-$(CONFIG_VSYSCALL)		+= vsyscall/
+obj-y				+= cpu/
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
 obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
 obj-$(CONFIG_MODULES)		+= sh_ksyms_64.o module.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
-obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_IO_TRAPPED)	+= io_trapped.o
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= localtimer.o
+
 EXTRA_CFLAGS += -Werror
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/module.c linux-libre-2.6.31-gnu/arch/sh/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,8 +46,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* We don't need anything special. */
@@ -90,7 +88,7 @@
 		 * SHmedia, the LSB of the symbol needs to be asserted
 		 * for the CPU to be in SHmedia mode when it starts executing
 		 * the branch target. */
-		relocation |= (sym->st_other & 4);
+		relocation |= !!(sym->st_other & 4);
 #endif
 
 		switch (ELF32_R_TYPE(rel[i].r_info)) {
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/process_32.c linux-libre-2.6.31-gnu/arch/sh/kernel/process_32.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/process_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/process_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -119,8 +119,6 @@
 	pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
 		      &regs, 0, NULL, NULL);
 
-	trace_mark(kernel_arch_kthread_create, "pid %d fn %p", pid, fn);
-
 	return pid;
 }
 
@@ -251,7 +249,8 @@
 
 	if (current_cpu_data.type == CPU_SH7729 ||
 	    current_cpu_data.type == CPU_SH7710 ||
-	    current_cpu_data.type == CPU_SH7712) {
+	    current_cpu_data.type == CPU_SH7712 ||
+	    current_cpu_data.type == CPU_SH7203){
 		ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
 		ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
 	} else {
@@ -366,11 +365,6 @@
 		goto out;
 
 	error = do_execve(filename, uargv, uenvp, regs);
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
-		task_unlock(current);
-	}
 	putname(filename);
 out:
 	return error;
@@ -407,6 +401,7 @@
 #else
 	ctrl_outw(0, UBC_BBRA);
 	ctrl_outw(0, UBC_BBRB);
+	ctrl_outl(0, UBC_BRCR);
 #endif
 	current->thread.ubc_pc = 0;
 	ubc_usercnt -= 1;
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/process_64.c linux-libre-2.6.31-gnu/arch/sh/kernel/process_64.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/process_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/process_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -323,7 +323,6 @@
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
 	struct pt_regs regs;
-	int pid;
 
 	memset(&regs, 0, sizeof(regs));
 	regs.regs[2] = (unsigned long)arg;
@@ -333,12 +332,8 @@
 	regs.sr = (1 << 30);
 
 	/* Ok, create the new process.. */
-	pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
 		      &regs, 0, NULL, NULL);
-
-	trace_mark(kernel_arch_kthread_create, "pid %d fn %p", pid, fn);
-
-	return pid;
 }
 
 /*
@@ -529,11 +524,6 @@
 			  (char __user * __user *)uargv,
 			  (char __user * __user *)uenvp,
 			  pregs);
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
-		task_unlock(current);
-	}
 	putname(filename);
 out:
 	return error;
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/ptrace_32.c linux-libre-2.6.31-gnu/arch/sh/kernel/ptrace_32.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/ptrace_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/ptrace_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -334,6 +334,14 @@
 					[(addr - (long)&dummy->fpu) >> 2];
 		} else if (addr == (long) &dummy->u_fpvalid)
 			tmp = !!tsk_used_math(child);
+		else if (addr == PT_TEXT_ADDR)
+			tmp = child->mm->start_code;
+		else if (addr == PT_DATA_ADDR)
+			tmp = child->mm->start_data;
+		else if (addr == PT_TEXT_END_ADDR)
+			tmp = child->mm->end_code;
+		else if (addr == PT_TEXT_LEN)
+			tmp = child->mm->end_code - child->mm->start_code;
 		else
 			tmp = 0;
 		ret = put_user(tmp, datap);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/setup.c linux-libre-2.6.31-gnu/arch/sh/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/mmzone.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/page.h>
@@ -155,7 +156,7 @@
 			&crash_size, &crash_base);
 	if (ret == 0 && crash_size) {
 		if (crash_base <= 0) {
-			vp = alloc_bootmem_nopanic(crash_size); 
+			vp = alloc_bootmem_nopanic(crash_size);
 			if (!vp) {
 				printk(KERN_INFO "crashkernel allocation "
 				       "failed\n");
@@ -184,7 +185,6 @@
 {}
 #endif
 
-#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
 void __cpuinit calibrate_delay(void)
 {
 	struct clk *clk = clk_get(NULL, "cpu_clk");
@@ -200,7 +200,6 @@
 			 (loops_per_jiffy/(5000/HZ)) % 100,
 			 loops_per_jiffy);
 }
-#endif
 
 void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
 						unsigned long end_pfn)
@@ -328,6 +327,10 @@
 early_param("elfcorehdr", parse_elfcorehdr);
 #endif
 
+void __init __attribute__ ((weak)) plat_early_device_setup(void)
+{
+}
+
 void __init setup_arch(char **cmdline_p)
 {
 	enable_mmu();
@@ -381,6 +384,8 @@
 
 	parse_early_param();
 
+	plat_early_device_setup();
+
 	sh_mv_setup();
 
 	/*
@@ -415,6 +420,18 @@
 #endif
 }
 
+/* processor boot mode configuration */
+int generic_mode_pins(void)
+{
+	pr_warning("generic_mode_pins(): missing mode pin configuration\n");
+	return 0;
+}
+
+int test_mode_pin(int pin)
+{
+	return sh_mv.mv_mode_pins() & pin;
+}
+
 static const char *cpu_name[] = {
 	[CPU_SH7201]	= "SH7201",
 	[CPU_SH7203]	= "SH7203",	[CPU_SH7263]	= "SH7263",
@@ -435,7 +452,8 @@
 	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
 	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
 	[CPU_MXG]	= "MX-G",	[CPU_SH7723]	= "SH7723",
-	[CPU_SH7366]	= "SH7366",	[CPU_SH_NONE]	= "Unknown"
+	[CPU_SH7366]	= "SH7366",	[CPU_SH7724]	= "SH7724",
+	[CPU_SH_NONE]	= "Unknown"
 };
 
 const char *get_cpu_subtype(struct sh_cpuinfo *c)
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/sh_ksyms_32.c linux-libre-2.6.31-gnu/arch/sh/kernel/sh_ksyms_32.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/sh_ksyms_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/sh_ksyms_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,14 +19,10 @@
 #include <asm/ftrace.h>
 
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
-extern struct hw_interrupt_type no_irq_type;
 
 /* platform dependent support */
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(irq_desc);
-EXPORT_SYMBOL(no_irq_type);
-
 EXPORT_SYMBOL(strlen);
 
 /* PCI exports */
@@ -41,11 +37,6 @@
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(__copy_user);
-
-#ifdef CONFIG_MMU
-EXPORT_SYMBOL(get_vm_area);
-#endif
-
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__const_udelay);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/sh_ksyms_64.c linux-libre-2.6.31-gnu/arch/sh/kernel/sh_ksyms_64.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/sh_ksyms_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/sh_ksyms_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,13 +38,6 @@
 EXPORT_SYMBOL(flush_dcache_page);
 #endif
 
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial);
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
-#ifdef CONFIG_IPV6
-EXPORT_SYMBOL(csum_ipv6_magic);
-#endif
-
 #ifdef CONFIG_VT
 EXPORT_SYMBOL(screen_info);
 #endif
@@ -76,5 +69,7 @@
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
 
 DECLARE_EXPORT(__sdivsi3);
+DECLARE_EXPORT(__sdivsi3_1);
+DECLARE_EXPORT(__sdivsi3_2);
 DECLARE_EXPORT(__udivsi3);
 DECLARE_EXPORT(__div_table);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/signal_32.c linux-libre-2.6.31-gnu/arch/sh/kernel/signal_32.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/signal_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/signal_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -332,8 +332,8 @@
 
 /* These symbols are defined with the addresses in the vsyscall page.
    See vsyscall-trapa.S.  */
-extern void __user __kernel_sigreturn;
-extern void __user __kernel_rt_sigreturn;
+extern void __kernel_sigreturn(void);
+extern void __kernel_rt_sigreturn(void);
 
 static int setup_frame(int sig, struct k_sigaction *ka,
 			sigset_t *set, struct pt_regs *regs)
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/smp.c linux-libre-2.6.31-gnu/arch/sh/kernel/smp.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,7 @@
 	plat_prepare_cpus(max_cpus);
 
 #ifndef CONFIG_HOTPLUG_CPU
-	cpu_present_map = cpu_possible_map;
+	init_cpu_present(&cpu_possible_map);
 #endif
 }
 
@@ -58,8 +58,8 @@
 	__cpu_number_map[0] = cpu;
 	__cpu_logical_map[0] = cpu;
 
-	cpu_set(cpu, cpu_online_map);
-	cpu_set(cpu, cpu_possible_map);
+	set_cpu_online(cpu, true);
+	set_cpu_possible(cpu, true);
 }
 
 asmlinkage void __cpuinit start_secondary(void)
@@ -171,11 +171,11 @@
 	smp_call_function(stop_this_cpu, 0, 0);
 }
 
-void arch_send_call_function_ipi(cpumask_t mask)
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
 	int cpu;
 
-	for_each_cpu_mask(cpu, mask)
+	for_each_cpu(cpu, mask)
 		plat_send_ipi(cpu, SMP_MSG_FUNCTION);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/syscalls_32.S linux-libre-2.6.31-gnu/arch/sh/kernel/syscalls_32.S
--- linux-libre-2.6.30-gnu/arch/sh/kernel/syscalls_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/syscalls_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -350,4 +350,6 @@
 	.long sys_pipe2
 	.long sys_inotify_init1
 	.long sys_preadv
-	.long sys_writev
+	.long sys_pwritev
+	.long sys_rt_tgsigqueueinfo	/* 335 */
+	.long sys_perf_counter_open
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/syscalls_64.S linux-libre-2.6.31-gnu/arch/sh/kernel/syscalls_64.S
--- linux-libre-2.6.30-gnu/arch/sh/kernel/syscalls_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/syscalls_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -389,3 +389,5 @@
 	.long sys_inotify_init1		/* 360 */
 	.long sys_preadv
 	.long sys_pwritev
+	.long sys_rt_tgsigqueueinfo
+	.long sys_perf_counter_open
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/sys_sh.c linux-libre-2.6.31-gnu/arch/sh/kernel/sys_sh.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/sys_sh.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/sys_sh.c	2009-09-09 18:13:59.000000000 -0400
@@ -88,8 +88,6 @@
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
-	trace_mark(kernel_arch_ipc_call, "call %u first %d", call, first);
-
 	if (call <= SEMTIMEDOP)
 		switch (call) {
 		case SEMOP:
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/time_32.c linux-libre-2.6.31-gnu/arch/sh/kernel/time_32.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/time_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/time_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,240 +0,0 @@
-/*
- *  arch/sh/kernel/time_32.c
- *
- *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
- *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002 - 2008  Paul Mundt
- *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
- *
- *  Some code taken from i386 version.
- *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-#include <linux/timex.h>
-#include <linux/sched.h>
-#include <linux/clockchips.h>
-#include <linux/mc146818rtc.h>	/* for rtc_lock */
-#include <linux/smp.h>
-#include <asm/clock.h>
-#include <asm/rtc.h>
-#include <asm/timer.h>
-#include <asm/kgdb.h>
-
-struct sys_timer *sys_timer;
-
-/* Move this somewhere more sensible.. */
-DEFINE_SPINLOCK(rtc_lock);
-EXPORT_SYMBOL(rtc_lock);
-
-/* Dummy RTC ops */
-static void null_rtc_get_time(struct timespec *tv)
-{
-	tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
-	tv->tv_nsec = 0;
-}
-
-static int null_rtc_set_time(const time_t secs)
-{
-	return 0;
-}
-
-void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
-int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
-
-#ifndef CONFIG_GENERIC_TIME
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long flags;
-	unsigned long seq;
-	unsigned long usec, sec;
-
-	do {
-		/*
-		 * Turn off IRQs when grabbing xtime_lock, so that
-		 * the sys_timer get_offset code doesn't have to handle it.
-		 */
-		seq = read_seqbegin_irqsave(&xtime_lock, flags);
-		usec = get_timer_offset();
-		sec = xtime.tv_sec;
-		usec += xtime.tv_nsec / NSEC_PER_USEC;
-	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	nsec -= get_timer_offset() * NSEC_PER_USEC;
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	ntp_clear();
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-
-	return 0;
-}
-EXPORT_SYMBOL(do_settimeofday);
-#endif /* !CONFIG_GENERIC_TIME */
-
-/* last time the RTC clock got updated */
-static long last_rtc_update;
-
-/*
- * handle_timer_tick() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-void handle_timer_tick(void)
-{
-	if (current->pid)
-		profile_tick(CPU_PROFILING);
-
-	/*
-	 * Here we are in the timer irq handler. We just have irqs locally
-	 * disabled but we don't know if the timer_bh is running on the other
-	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-	 * the irq version of write_lock because as just said we have irq
-	 * locally disabled. -arca
-	 */
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-
-	/*
-	 * If we have an externally synchronized Linux clock, then update
-	 * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if (ntp_synced() &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
-	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-		if (rtc_sh_set_time(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			/* do it again in 60s */
-			last_rtc_update = xtime.tv_sec - 600;
-	}
-	write_sequnlock(&xtime_lock);
-
-#ifndef CONFIG_SMP
-	update_process_times(user_mode(get_irq_regs()));
-#endif
-}
-
-#ifdef CONFIG_PM
-int timer_suspend(struct sys_device *dev, pm_message_t state)
-{
-	struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
-
-	sys_timer->ops->stop();
-
-	return 0;
-}
-
-int timer_resume(struct sys_device *dev)
-{
-	struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
-
-	sys_timer->ops->start();
-
-	return 0;
-}
-#else
-#define timer_suspend NULL
-#define timer_resume NULL
-#endif
-
-static struct sysdev_class timer_sysclass = {
-	.name	 = "timer",
-	.suspend = timer_suspend,
-	.resume	 = timer_resume,
-};
-
-static int __init timer_init_sysfs(void)
-{
-	int ret;
-
-	if (!sys_timer)
-		return 0;
-
-	ret = sysdev_class_register(&timer_sysclass);
-	if (ret != 0)
-		return ret;
-
-	sys_timer->dev.cls = &timer_sysclass;
-	return sysdev_register(&sys_timer->dev);
-}
-device_initcall(timer_init_sysfs);
-
-void (*board_time_init)(void);
-
-struct clocksource clocksource_sh = {
-	.name		= "SuperH",
-};
-
-#ifdef CONFIG_GENERIC_TIME
-unsigned long long sched_clock(void)
-{
-	unsigned long long cycles;
-
-	/* jiffies based sched_clock if no clocksource is installed */
-	if (!clocksource_sh.rating)
-		return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ);
-
-	cycles = clocksource_sh.read(&clocksource_sh);
-	return cyc2ns(&clocksource_sh, cycles);
-}
-#endif
-
-void __init time_init(void)
-{
-	if (board_time_init)
-		board_time_init();
-
-	clk_init();
-
-	rtc_sh_get_time(&xtime);
-	set_normalized_timespec(&wall_to_monotonic,
-				-xtime.tv_sec, -xtime.tv_nsec);
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-	local_timer_setup(smp_processor_id());
-#endif
-
-	/*
-	 * Find the timer to use as the system timer, it will be
-	 * initialized for us.
-	 */
-	sys_timer = get_sys_timer();
-	if (unlikely(!sys_timer))
-		panic("System timer missing.\n");
-
-	printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/time_64.c linux-libre-2.6.31-gnu/arch/sh/kernel/time_64.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/time_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/time_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,363 +0,0 @@
-/*
- * arch/sh/kernel/time_64.c
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003 - 2007  Paul Mundt
- * Copyright (C) 2003  Richard Curnow
- *
- *    Original TMU/RTC code taken from sh version.
- *    Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
- *      Some code taken from i386 version.
- *      Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * 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/errno.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-#include <linux/smp.h>
-#include <linux/module.h>
-#include <linux/bcd.h>
-#include <linux/timex.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <cpu/registers.h>	 /* required by inline __asm__ stmt. */
-#include <cpu/irq.h>
-#include <asm/addrspace.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/clock.h>
-
-#define TMU_TOCR_INIT	0x00
-#define TMU0_TCR_INIT	0x0020
-#define TMU_TSTR_INIT	1
-#define TMU_TSTR_OFF	0
-
-/* Real Time Clock */
-#define	RTC_BLOCK_OFF	0x01040000
-#define RTC_BASE	PHYS_PERIPHERAL_BLOCK + RTC_BLOCK_OFF
-#define RTC_RCR1_CIE	0x10	/* Carry Interrupt Enable */
-#define RTC_RCR1	(rtc_base + 0x38)
-
-/* Time Management Unit */
-#define	TMU_BLOCK_OFF	0x01020000
-#define TMU_BASE	PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
-#define TMU0_BASE	tmu_base + 0x8 + (0xc * 0x0)
-#define TMU1_BASE	tmu_base + 0x8 + (0xc * 0x1)
-#define TMU2_BASE	tmu_base + 0x8 + (0xc * 0x2)
-
-#define TMU_TOCR	tmu_base+0x0	/* Byte access */
-#define TMU_TSTR	tmu_base+0x4	/* Byte access */
-
-#define TMU0_TCOR	TMU0_BASE+0x0	/* Long access */
-#define TMU0_TCNT	TMU0_BASE+0x4	/* Long access */
-#define TMU0_TCR	TMU0_BASE+0x8	/* Word access */
-
-#define TICK_SIZE (tick_nsec / 1000)
-
-static unsigned long tmu_base, rtc_base;
-unsigned long cprc_base;
-
-/* Variables to allow interpolation of time of day to resolution better than a
- * jiffy. */
-
-/* This is effectively protected by xtime_lock */
-static unsigned long ctc_last_interrupt;
-static unsigned long long usecs_per_jiffy = 1000000/HZ; /* Approximation */
-
-#define CTC_JIFFY_SCALE_SHIFT 40
-
-/* 2**CTC_JIFFY_SCALE_SHIFT / ctc_ticks_per_jiffy */
-static unsigned long long scaled_recip_ctc_ticks_per_jiffy;
-
-/* Estimate number of microseconds that have elapsed since the last timer tick,
-   by scaling the delta that has occurred in the CTC register.
-
-   WARNING WARNING WARNING : This algorithm relies on the CTC decrementing at
-   the CPU clock rate.  If the CPU sleeps, the CTC stops counting.  Bear this
-   in mind if enabling SLEEP_WORKS in process.c.  In that case, this algorithm
-   probably needs to use TMU.TCNT0 instead.  This will work even if the CPU is
-   sleeping, though will be coarser.
-
-   FIXME : What if usecs_per_tick is moving around too much, e.g. if an adjtime
-   is running or if the freq or tick arguments of adjtimex are modified after
-   we have calibrated the scaling factor?  This will result in either a jump at
-   the end of a tick period, or a wrap backwards at the start of the next one,
-   if the application is reading the time of day often enough.  I think we
-   ought to do better than this.  For this reason, usecs_per_jiffy is left
-   separated out in the calculation below.  This allows some future hook into
-   the adjtime-related stuff in kernel/timer.c to remove this hazard.
-
-*/
-
-static unsigned long usecs_since_tick(void)
-{
-	unsigned long long current_ctc;
-	long ctc_ticks_since_interrupt;
-	unsigned long long ull_ctc_ticks_since_interrupt;
-	unsigned long result;
-
-	unsigned long long mul1_out;
-	unsigned long long mul1_out_high;
-	unsigned long long mul2_out_low, mul2_out_high;
-
-	/* Read CTC register */
-	asm ("getcon cr62, %0" : "=r" (current_ctc));
-	/* Note, the CTC counts down on each CPU clock, not up.
-	   Note(2), use long type to get correct wraparound arithmetic when
-	   the counter crosses zero. */
-	ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc;
-	ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt;
-
-	/* Inline assembly to do 32x32x32->64 multiplier */
-	asm volatile ("mulu.l %1, %2, %0" :
-	     "=r" (mul1_out) :
-	     "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy));
-
-	mul1_out_high = mul1_out >> 32;
-
-	asm volatile ("mulu.l %1, %2, %0" :
-	     "=r" (mul2_out_low) :
-	     "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy));
-
-#if 1
-	asm volatile ("mulu.l %1, %2, %0" :
-	     "=r" (mul2_out_high) :
-	     "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy));
-#endif
-
-	result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT);
-
-	return result;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long flags;
-	unsigned long seq;
-	unsigned long usec, sec;
-
-	do {
-		seq = read_seqbegin_irqsave(&xtime_lock, flags);
-		usec = usecs_since_tick();
-		sec = xtime.tv_sec;
-		usec += xtime.tv_nsec / 1000;
-	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	nsec -= 1000 * usecs_since_tick();
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	ntp_clear();
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-
-	return 0;
-}
-EXPORT_SYMBOL(do_settimeofday);
-
-/* Dummy RTC ops */
-static void null_rtc_get_time(struct timespec *tv)
-{
-	tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
-	tv->tv_nsec = 0;
-}
-
-static int null_rtc_set_time(const time_t secs)
-{
-	return 0;
-}
-
-void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
-int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
-
-/* last time the RTC clock got updated */
-static long last_rtc_update;
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static inline void do_timer_interrupt(void)
-{
-	unsigned long long current_ctc;
-
-	if (current->pid)
-		profile_tick(CPU_PROFILING);
-
-	/*
-	 * Here we are in the timer irq handler. We just have irqs locally
-	 * disabled but we don't know if the timer_bh is running on the other
-	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-	 * the irq version of write_lock because as just said we have irq
-	 * locally disabled. -arca
-	 */
-	write_seqlock(&xtime_lock);
-	asm ("getcon cr62, %0" : "=r" (current_ctc));
-	ctc_last_interrupt = (unsigned long) current_ctc;
-
-	do_timer(1);
-
-	/*
-	 * If we have an externally synchronized Linux clock, then update
-	 * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if (ntp_synced() &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
-	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-		if (rtc_sh_set_time(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			/* do it again in 60 s */
-			last_rtc_update = xtime.tv_sec - 600;
-	}
-	write_sequnlock(&xtime_lock);
-
-#ifndef CONFIG_SMP
-	update_process_times(user_mode(get_irq_regs()));
-#endif
-}
-
-/*
- * This is the same as the above, except we _also_ save the current
- * Time Stamp Counter value at the time of the timer interrupt, so that
- * we later on can estimate the time of day more exactly.
- */
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-	unsigned long timer_status;
-
-	/* Clear UNF bit */
-	timer_status = ctrl_inw(TMU0_TCR);
-	timer_status &= ~0x100;
-	ctrl_outw(timer_status, TMU0_TCR);
-
-	do_timer_interrupt();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction irq0  = {
-	.handler = timer_interrupt,
-	.flags = IRQF_DISABLED,
-	.name = "timer",
-};
-
-void __init time_init(void)
-{
-	unsigned long interval;
-	struct clk *clk;
-
-	tmu_base = onchip_remap(TMU_BASE, 1024, "TMU");
-	if (!tmu_base) {
-		panic("Unable to remap TMU\n");
-	}
-
-	rtc_base = onchip_remap(RTC_BASE, 1024, "RTC");
-	if (!rtc_base) {
-		panic("Unable to remap RTC\n");
-	}
-
-	clk = clk_get(NULL, "cpu_clk");
-	scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) /
-			(unsigned long long)(clk_get_rate(clk) / HZ));
-
-	rtc_sh_get_time(&xtime);
-
-	setup_irq(TIMER_IRQ, &irq0);
-
-	clk = clk_get(NULL, "module_clk");
-	interval = (clk_get_rate(clk)/(HZ*4));
-
-	printk("Interval = %ld\n", interval);
-
-	/* Start TMU0 */
-	ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
-	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
-	ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
-	ctrl_outl(interval, TMU0_TCOR);
-	ctrl_outl(interval, TMU0_TCNT);
-	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-}
-
-static struct resource rtc_resources[] = {
-	[0] = {
-		/* RTC base, filled in by rtc_init */
-		.flags	= IORESOURCE_IO,
-	},
-	[1] = {
-		/* Period IRQ */
-		.start	= IRQ_PRI,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		/* Carry IRQ */
-		.start	= IRQ_CUI,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		/* Alarm IRQ */
-		.start	= IRQ_ATI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device rtc_device = {
-	.name		= "sh-rtc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(rtc_resources),
-	.resource	= rtc_resources,
-};
-
-static int __init rtc_init(void)
-{
-	rtc_resources[0].start	= rtc_base;
-	rtc_resources[0].end	= rtc_resources[0].start + 0x58 - 1;
-
-	return platform_device_register(&rtc_device);
-}
-device_initcall(rtc_init);
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/time.c linux-libre-2.6.31-gnu/arch/sh/kernel/time.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/time.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ *  arch/sh/kernel/time.c
+ *
+ *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 2002 - 2009  Paul Mundt
+ *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/profile.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/rtc.h>
+#include <asm/clock.h>
+#include <asm/rtc.h>
+
+/* Dummy RTC ops */
+static void null_rtc_get_time(struct timespec *tv)
+{
+	tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
+	tv->tv_nsec = 0;
+}
+
+static int null_rtc_set_time(const time_t secs)
+{
+	return 0;
+}
+
+void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
+int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
+
+#ifdef CONFIG_GENERIC_CMOS_UPDATE
+unsigned long read_persistent_clock(void)
+{
+	struct timespec tv;
+	rtc_sh_get_time(&tv);
+	return tv.tv_sec;
+}
+
+int update_persistent_clock(struct timespec now)
+{
+	return rtc_sh_set_time(now.tv_sec);
+}
+#endif
+
+unsigned int get_rtc_time(struct rtc_time *tm)
+{
+	if (rtc_sh_get_time != null_rtc_get_time) {
+		struct timespec tv;
+
+		rtc_sh_get_time(&tv);
+		rtc_time_to_tm(tv.tv_sec, tm);
+	}
+
+	return RTC_24H;
+}
+EXPORT_SYMBOL(get_rtc_time);
+
+int set_rtc_time(struct rtc_time *tm)
+{
+	unsigned long secs;
+
+	rtc_tm_to_time(tm, &secs);
+	return rtc_sh_set_time(secs);
+}
+EXPORT_SYMBOL(set_rtc_time);
+
+static int __init rtc_generic_init(void)
+{
+	struct platform_device *pdev;
+
+	if (rtc_sh_get_time == null_rtc_get_time)
+		return -ENODEV;
+
+	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	return 0;
+}
+module_init(rtc_generic_init);
+
+void (*board_time_init)(void);
+
+void __init time_init(void)
+{
+	if (board_time_init)
+		board_time_init();
+
+	clk_init();
+
+	rtc_sh_get_time(&xtime);
+	set_normalized_timespec(&wall_to_monotonic,
+				-xtime.tv_sec, -xtime.tv_nsec);
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+	local_timer_setup(smp_processor_id());
+#endif
+
+	/*
+	 * Make sure all compiled-in early timers register themselves.
+	 *
+	 * Run probe() for two "earlytimer" devices, these will be the
+	 * clockevents and clocksource devices respectively. In the event
+	 * that only a clockevents device is available, we -ENODEV on the
+	 * clocksource and the jiffies clocksource is used transparently
+	 * instead. No error handling is necessary here.
+	 */
+	early_platform_driver_register_all("earlytimer");
+	early_platform_driver_probe("earlytimer", 2, 0);
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/timers/Makefile linux-libre-2.6.31-gnu/arch/sh/kernel/timers/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/kernel/timers/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/timers/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-#
-# Makefile for the various Linux/SuperH timers
-#
-
-obj-y	:= timer.o
-
-obj-$(CONFIG_SH_TMU)		+= timer-tmu.o
-obj-$(CONFIG_SH_MTU2)		+= timer-mtu2.o
-obj-$(CONFIG_SH_CMT)		+= timer-cmt.o
-
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= timer-broadcast.o
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-broadcast.c linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-broadcast.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-broadcast.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-broadcast.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/*
- * Dummy local timer
- *
- * Copyright (C) 2008  Paul Mundt
- *
- * cloned from:
- *
- *  linux/arch/arm/mach-realview/localtimer.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * 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.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/smp.h>
-#include <linux/jiffies.h>
-#include <linux/percpu.h>
-#include <linux/clockchips.h>
-#include <linux/irq.h>
-
-static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
-
-/*
- * Used on SMP for either the local timer or SMP_MSG_TIMER
- */
-void local_timer_interrupt(void)
-{
-	struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
-
-	clk->event_handler(clk);
-}
-
-static void dummy_timer_set_mode(enum clock_event_mode mode,
-				 struct clock_event_device *clk)
-{
-}
-
-void __cpuinit local_timer_setup(unsigned int cpu)
-{
-	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
-
-	clk->name		= "dummy_timer";
-	clk->features		= CLOCK_EVT_FEAT_DUMMY;
-	clk->rating		= 200;
-	clk->mult		= 1;
-	clk->set_mode		= dummy_timer_set_mode;
-	clk->broadcast		= smp_timer_broadcast;
-	clk->cpumask		= cpumask_of(cpu);
-
-	clockevents_register_device(clk);
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer.c linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/*
- * arch/sh/kernel/timers/timer.c - Common timer code
- *
- *  Copyright (C) 2005  Paul Mundt
- *
- * 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/init.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <asm/timer.h>
-
-static struct sys_timer *sys_timers[] = {
-#ifdef CONFIG_SH_TMU
-	&tmu_timer,
-#endif
-#ifdef CONFIG_SH_MTU2
-	&mtu2_timer,
-#endif
-#ifdef CONFIG_SH_CMT
-	&cmt_timer,
-#endif
-	NULL,
-};
-
-static char timer_override[10];
-static int __init timer_setup(char *str)
-{
-	if (str)
-		strlcpy(timer_override, str, sizeof(timer_override));
-	return 1;
-}
-__setup("timer=", timer_setup);
-
-struct sys_timer *get_sys_timer(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(sys_timers); i++) {
-		struct sys_timer *t = sys_timers[i];
-
-		if (unlikely(!t))
-			break;
-		if (unlikely(timer_override[0]))
-			if ((strcmp(timer_override, t->name) != 0))
-				continue;
-		if (likely(t->ops->init() == 0))
-			return t;
-	}
-
-	return NULL;
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-cmt.c linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-cmt.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-cmt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-cmt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,188 +0,0 @@
-/*
- * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support
- *
- *  Copyright (C) 2005  Yoshinori Sato
- *
- * 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/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/seqlock.h>
-#include <asm/timer.h>
-#include <asm/rtc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/clock.h>
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7619)
-#define CMT_CMSTR	0xf84a0070
-#define CMT_CMCSR_0	0xf84a0072
-#define CMT_CMCNT_0	0xf84a0074
-#define CMT_CMCOR_0	0xf84a0076
-#define CMT_CMCSR_1	0xf84a0078
-#define CMT_CMCNT_1	0xf84a007a
-#define CMT_CMCOR_1	0xf84a007c
-
-#define STBCR3		0xf80a0000
-#define cmt_clock_enable() do {	ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0)
-#define CMT_CMCSR_INIT	0x0040
-#define CMT_CMCSR_CALIB	0x0000
-#elif defined(CONFIG_CPU_SUBTYPE_SH7203) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7206) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7263)
-#define CMT_CMSTR	0xfffec000
-#define CMT_CMCSR_0	0xfffec002
-#define CMT_CMCNT_0	0xfffec004
-#define CMT_CMCOR_0	0xfffec006
-
-#define STBCR4		0xfffe040c
-#define cmt_clock_enable() do {	ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0)
-#define CMT_CMCSR_INIT	0x0040
-#define CMT_CMCSR_CALIB	0x0000
-#else
-#error "Unknown CPU SUBTYPE"
-#endif
-
-static unsigned long cmt_timer_get_offset(void)
-{
-	int count;
-	static unsigned short count_p = 0xffff;    /* for the first call after boot */
-	static unsigned long jiffies_p = 0;
-
-	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off.
-	 */
-	unsigned long jiffies_t;
-
-	/* timer count may underflow right here */
-	count =  ctrl_inw(CMT_CMCOR_0);
-	count -= ctrl_inw(CMT_CMCNT_0);
-
-	jiffies_t = jiffies;
-
-	/*
-	 * avoiding timer inconsistencies (they are rare, but they happen)...
-	 * there is one kind of problem that must be avoided here:
-	 *  1. the timer counter underflows
-	 */
-
-	if (jiffies_t == jiffies_p) {
-		if (count > count_p) {
-			/* the nutcase */
-			if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */
-				count -= LATCH;
-			} else {
-				printk("%s (): hardware timer problem?\n",
-				       __func__);
-			}
-		}
-	} else
-		jiffies_p = jiffies_t;
-
-	count_p = count;
-
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	count = (count + LATCH/2) / LATCH;
-
-	return count;
-}
-
-static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
-{
-	unsigned long timer_status;
-
-	/* Clear CMF bit */
-	timer_status = ctrl_inw(CMT_CMCSR_0);
-	timer_status &= ~0x80;
-	ctrl_outw(timer_status, CMT_CMCSR_0);
-
-	handle_timer_tick();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction cmt_irq = {
-	.name		= "timer",
-	.handler	= cmt_timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-};
-
-static void cmt_clk_init(struct clk *clk)
-{
-	u8 divisor = CMT_CMCSR_INIT & 0x3;
-	ctrl_inw(CMT_CMCSR_0);
-	ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0);
-	clk->parent = clk_get(NULL, "module_clk");
-	clk->rate = clk->parent->rate / (8 << (divisor << 1));
-}
-
-static void cmt_clk_recalc(struct clk *clk)
-{
-	u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3;
-	clk->rate = clk->parent->rate / (8 << (divisor << 1));
-}
-
-static struct clk_ops cmt_clk_ops = {
-	.init		= cmt_clk_init,
-	.recalc		= cmt_clk_recalc,
-};
-
-static struct clk cmt0_clk = {
-	.name		= "cmt0_clk",
-	.ops		= &cmt_clk_ops,
-};
-
-static int cmt_timer_start(void)
-{
-	ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
-	return 0;
-}
-
-static int cmt_timer_stop(void)
-{
-	ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR);
-	return 0;
-}
-
-static int cmt_timer_init(void)
-{
-	unsigned long interval;
-
-	cmt_clock_enable();
-
-	setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq);
-
-	cmt0_clk.parent = clk_get(NULL, "module_clk");
-
-	cmt_timer_stop();
-
-	interval = cmt0_clk.parent->rate / 8 / HZ;
-	printk(KERN_INFO "Interval = %ld\n", interval);
-
-	ctrl_outw(interval, CMT_CMCOR_0);
-
-	clk_register(&cmt0_clk);
-	clk_enable(&cmt0_clk);
-
-	cmt_timer_start();
-
-	return 0;
-}
-
-static struct sys_timer_ops cmt_timer_ops = {
-	.init		= cmt_timer_init,
-	.start		= cmt_timer_start,
-	.stop		= cmt_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
-	.get_offset	= cmt_timer_get_offset,
-#endif
-};
-
-struct sys_timer cmt_timer = {
-	.name	= "cmt",
-	.ops	= &cmt_timer_ops,
-};
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-mtu2.c linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-mtu2.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-mtu2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-mtu2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,202 +0,0 @@
-/*
- * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support
- *
- *  Copyright (C) 2005  Paul Mundt
- *
- * Based off of arch/sh/kernel/timers/timer-tmu.c
- *
- * 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/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/seqlock.h>
-#include <asm/timer.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/clock.h>
-
-/*
- * We use channel 1 for our lowly system timer. Channel 2 would be the other
- * likely candidate, but we leave it alone as it has higher divisors that
- * would be of more use to other more interesting applications.
- *
- * TODO: Presently we only implement a 16-bit single-channel system timer.
- * However, we can implement channel cascade if we go the overflow route and
- * get away with using 2 MTU2 channels as a 32-bit timer.
- */
-#define MTU2_TSTR	0xfffe4280
-#define MTU2_TCR_1	0xfffe4380
-#define MTU2_TMDR_1	0xfffe4381
-#define MTU2_TIOR_1	0xfffe4382
-#define MTU2_TIER_1	0xfffe4384
-#define MTU2_TSR_1	0xfffe4385
-#define MTU2_TCNT_1	0xfffe4386	/* 16-bit counter */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7201) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7203)
-#define MTU2_TGRA_1	0xfffe4388
-#else
-#define MTU2_TGRA_1	0xfffe438a
-#endif
-
-#define STBCR3		0xfffe0408
-
-#define MTU2_TSTR_CST1	(1 << 1)	/* Counter Start 1 */
-
-#define MTU2_TSR_TGFA	(1 << 0)	/* GRA compare match */
-
-#define MTU2_TIER_TGIEA	(1 << 0)	/* GRA compare match  interrupt enable */
-
-#define MTU2_TCR_INIT	0x22
-
-#define MTU2_TCR_CALIB  0x00
-
-static unsigned long mtu2_timer_get_offset(void)
-{
-	int count;
-	static int count_p = 0x7fff;	/* for the first call after boot */
-	static unsigned long jiffies_p = 0;
-
-	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off.
-	 */
-	unsigned long jiffies_t;
-
-	/* timer count may underflow right here */
-	count = ctrl_inw(MTU2_TCNT_1);	/* read the latched count */
-
-	jiffies_t = jiffies;
-
-	/*
-	 * avoiding timer inconsistencies (they are rare, but they happen)...
-	 * there is one kind of problem that must be avoided here:
-	 *  1. the timer counter underflows
-	 */
-
-	if (jiffies_t == jiffies_p) {
-		if (count > count_p) {
-			if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) {
-				count -= LATCH;
-			} else {
-				printk("%s (): hardware timer problem?\n",
-				       __func__);
-			}
-		}
-	} else
-		jiffies_p = jiffies_t;
-
-	count_p = count;
-
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	count = (count + LATCH/2) / LATCH;
-
-	return count;
-}
-
-static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
-{
-	unsigned long timer_status;
-
-	/* Clear TGFA bit */
-	timer_status = ctrl_inb(MTU2_TSR_1);
-	timer_status &= ~MTU2_TSR_TGFA;
-	ctrl_outb(timer_status, MTU2_TSR_1);
-
-	/* Do timer tick */
-	handle_timer_tick();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mtu2_irq = {
-	.name		= "timer",
-	.handler	= mtu2_timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-};
-
-static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 };
-
-static void mtu2_clk_init(struct clk *clk)
-{
-	u8 idx = MTU2_TCR_INIT & 0x7;
-
-	clk->rate = clk->parent->rate / divisors[idx];
-	/* Start TCNT counting */
-	ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
-
-}
-
-static void mtu2_clk_recalc(struct clk *clk)
-{
-	u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7;
-	clk->rate = clk->parent->rate / divisors[idx];
-}
-
-static struct clk_ops mtu2_clk_ops = {
-	.init		= mtu2_clk_init,
-	.recalc		= mtu2_clk_recalc,
-};
-
-static struct clk mtu2_clk1 = {
-	.name		= "mtu2_clk1",
-	.ops		= &mtu2_clk_ops,
-};
-
-static int mtu2_timer_start(void)
-{
-	ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
-	return 0;
-}
-
-static int mtu2_timer_stop(void)
-{
-	ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR);
-	return 0;
-}
-
-static int mtu2_timer_init(void)
-{
-	unsigned long interval;
-
-	setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq);
-
-	mtu2_clk1.parent = clk_get(NULL, "module_clk");
-
-	ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3);
-
-	/* Normal operation */
-	ctrl_outb(0, MTU2_TMDR_1);
-	ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1);
-	ctrl_outb(0x01, MTU2_TIOR_1);
-
-	/* Enable underflow interrupt */
-	ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1);
-
-	interval = CONFIG_SH_PCLK_FREQ / 16 / HZ;
-	printk(KERN_INFO "Interval = %ld\n", interval);
-
-	ctrl_outw(interval, MTU2_TGRA_1);
-	ctrl_outw(0, MTU2_TCNT_1);
-
-	clk_register(&mtu2_clk1);
-	clk_enable(&mtu2_clk1);
-
-	return 0;
-}
-
-struct sys_timer_ops mtu2_timer_ops = {
-	.init		= mtu2_timer_init,
-	.start		= mtu2_timer_start,
-	.stop		= mtu2_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
-	.get_offset	= mtu2_timer_get_offset,
-#endif
-};
-
-struct sys_timer mtu2_timer = {
-	.name	= "mtu2",
-	.ops	= &mtu2_timer_ops,
-};
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-tmu.c linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-tmu.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/timers/timer-tmu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/timers/timer-tmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,297 +0,0 @@
-/*
- * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
- *
- *  Copyright (C) 2005 - 2007  Paul Mundt
- *
- * TMU handling code hacked out of arch/sh/kernel/time.c
- *
- *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
- *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002, 2003, 2004  Paul Mundt
- *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
- *
- * 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/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/seqlock.h>
-#include <linux/clockchips.h>
-#include <asm/timer.h>
-#include <asm/rtc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/clock.h>
-
-#define TMU_TOCR_INIT	0x00
-#define TMU_TCR_INIT	0x0020
-
-#define TMU0		(0)
-#define TMU1		(1)
-
-static inline void _tmu_start(int tmu_num)
-{
-	ctrl_outb(ctrl_inb(TMU_012_TSTR) | (0x1<<tmu_num), TMU_012_TSTR);
-}
-
-static inline void _tmu_set_irq(int tmu_num, int enabled)
-{
-	register unsigned long tmu_tcr = TMU0_TCR + (0xc*tmu_num);
-	ctrl_outw( (enabled ? ctrl_inw(tmu_tcr) | (1<<5) : ctrl_inw(tmu_tcr) & ~(1<<5)), tmu_tcr);
-}
-
-static inline void _tmu_stop(int tmu_num)
-{
-	ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~(0x1<<tmu_num), TMU_012_TSTR);
-}
-
-static inline void _tmu_clear_status(int tmu_num)
-{
-	register unsigned long tmu_tcr = TMU0_TCR + (0xc*tmu_num);
-	/* Clear UNF bit */
-	ctrl_outw(ctrl_inw(tmu_tcr) & ~0x100, tmu_tcr);
-}
-
-static inline unsigned long _tmu_read(int tmu_num)
-{
-        return ctrl_inl(TMU0_TCNT+0xC*tmu_num);
-}
-
-static int tmu_timer_start(void)
-{
-	_tmu_start(TMU0);
-	_tmu_start(TMU1);
-	_tmu_set_irq(TMU0,1);
-	return 0;
-}
-
-static int tmu_timer_stop(void)
-{
-	_tmu_stop(TMU0);
-	_tmu_stop(TMU1);
-	_tmu_clear_status(TMU0);
-	return 0;
-}
-
-/*
- * also when the module_clk is scaled the TMU1
- * will show the same frequency
- */
-static int tmus_are_scaled;
-
-static cycle_t tmu_timer_read(struct clocksource *cs)
-{
-	return ((cycle_t)(~_tmu_read(TMU1)))<<tmus_are_scaled;
-}
-
-
-static unsigned long tmu_latest_interval[3];
-static void tmu_timer_set_interval(int tmu_num, unsigned long interval, unsigned int reload)
-{
-	unsigned long tmu_tcnt = TMU0_TCNT + tmu_num*0xC;
-	unsigned long tmu_tcor = TMU0_TCOR + tmu_num*0xC;
-
-	_tmu_stop(tmu_num);
-
-	ctrl_outl(interval, tmu_tcnt);
-	tmu_latest_interval[tmu_num] = interval;
-
-	/*
-	 * TCNT reloads from TCOR on underflow, clear it if we don't
-	 * intend to auto-reload
-	 */
-	ctrl_outl( reload ? interval : 0 , tmu_tcor);
-
-	_tmu_start(tmu_num);
-}
-
-static int tmu_set_next_event(unsigned long cycles,
-			      struct clock_event_device *evt)
-{
-	tmu_timer_set_interval(TMU0,cycles, evt->mode == CLOCK_EVT_MODE_PERIODIC);
-	_tmu_set_irq(TMU0,1);
-	return 0;
-}
-
-static void tmu_set_mode(enum clock_event_mode mode,
-			 struct clock_event_device *evt)
-{
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		ctrl_outl(tmu_latest_interval[TMU0], TMU0_TCOR);
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		ctrl_outl(0, TMU0_TCOR);
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device tmu0_clockevent = {
-	.name		= "tmu0",
-	.shift		= 32,
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= tmu_set_mode,
-	.set_next_event	= tmu_set_next_event,
-};
-
-static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
-{
-	struct clock_event_device *evt = &tmu0_clockevent;
-	_tmu_clear_status(TMU0);
-	_tmu_set_irq(TMU0,tmu0_clockevent.mode != CLOCK_EVT_MODE_ONESHOT);
-
-	switch (tmu0_clockevent.mode) {
-	case CLOCK_EVT_MODE_ONESHOT:
-	case CLOCK_EVT_MODE_PERIODIC:
-		evt->event_handler(evt);
-		break;
-	default:
-		break;
-	}
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction tmu0_irq = {
-	.name		= "periodic/oneshot timer",
-	.handler	= tmu_timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-};
-
-static void __init tmu_clk_init(struct clk *clk)
-{
-	u8 divisor  = TMU_TCR_INIT & 0x7;
-	int tmu_num = clk->name[3]-'0';
-	ctrl_outw(TMU_TCR_INIT, TMU0_TCR+(tmu_num*0xC));
-	clk->rate = clk_get_rate(clk->parent) / (4 << (divisor << 1));
-}
-
-static void tmu_clk_recalc(struct clk *clk)
-{
-	int tmu_num = clk->name[3]-'0';
-	unsigned long prev_rate = clk_get_rate(clk);
-	unsigned long flags;
-	u8 divisor = ctrl_inw(TMU0_TCR+tmu_num*0xC) & 0x7;
-	clk->rate  = clk_get_rate(clk->parent) / (4 << (divisor << 1));
-
-	if(prev_rate==clk_get_rate(clk))
-		return;
-
-	if(tmu_num)
-		return; /* No more work on TMU1 */
-
-	local_irq_save(flags);
-	tmus_are_scaled = (prev_rate > clk->rate);
-
-	_tmu_stop(TMU0);
-
-	tmu0_clockevent.mult = div_sc(clk->rate, NSEC_PER_SEC,
-				tmu0_clockevent.shift);
-	tmu0_clockevent.max_delta_ns =
-			clockevent_delta2ns(-1, &tmu0_clockevent);
-	tmu0_clockevent.min_delta_ns =
-			clockevent_delta2ns(1, &tmu0_clockevent);
-
-	if (tmus_are_scaled)
-		tmu_latest_interval[TMU0] >>= 1;
-	else
-		tmu_latest_interval[TMU0] <<= 1;
-
-	tmu_timer_set_interval(TMU0,
-		tmu_latest_interval[TMU0],
-		tmu0_clockevent.mode == CLOCK_EVT_MODE_PERIODIC);
-
-	_tmu_start(TMU0);
-
-	local_irq_restore(flags);
-}
-
-static struct clk_ops tmu_clk_ops = {
-	.init		= tmu_clk_init,
-	.recalc		= tmu_clk_recalc,
-};
-
-static struct clk tmu0_clk = {
-	.name		= "tmu0_clk",
-	.ops		= &tmu_clk_ops,
-};
-
-static struct clk tmu1_clk = {
-	.name		= "tmu1_clk",
-	.ops		= &tmu_clk_ops,
-};
-
-static int tmu_timer_init(void)
-{
-	unsigned long interval;
-	unsigned long frequency;
-
-	setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq);
-
-	tmu0_clk.parent = clk_get(NULL, "module_clk");
-	tmu1_clk.parent = clk_get(NULL, "module_clk");
-
-	tmu_timer_stop();
-
-#if !defined(CONFIG_CPU_SUBTYPE_SH7720) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7721) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7785) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7786) && \
-    !defined(CONFIG_CPU_SUBTYPE_SHX3)
-	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
-#endif
-
-	clk_register(&tmu0_clk);
-	clk_register(&tmu1_clk);
-	clk_enable(&tmu0_clk);
-	clk_enable(&tmu1_clk);
-
-	frequency = clk_get_rate(&tmu0_clk);
-	interval = (frequency + HZ / 2) / HZ;
-
-	tmu_timer_set_interval(TMU0,interval, 1);
-	tmu_timer_set_interval(TMU1,~0,1);
-
-	_tmu_start(TMU1);
-
-	clocksource_sh.rating = 200;
-	clocksource_sh.mask = CLOCKSOURCE_MASK(32);
-	clocksource_sh.read = tmu_timer_read;
-	clocksource_sh.shift = 10;
-	clocksource_sh.mult = clocksource_hz2mult(clk_get_rate(&tmu1_clk),
-						  clocksource_sh.shift);
-	clocksource_sh.flags = CLOCK_SOURCE_IS_CONTINUOUS;
-	clocksource_register(&clocksource_sh);
-
-	tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
-				      tmu0_clockevent.shift);
-	tmu0_clockevent.max_delta_ns =
-			clockevent_delta2ns(-1, &tmu0_clockevent);
-	tmu0_clockevent.min_delta_ns =
-			clockevent_delta2ns(1, &tmu0_clockevent);
-
-	tmu0_clockevent.cpumask = cpumask_of(0);
-	tmu0_clockevent.rating = 100;
-
-	clockevents_register_device(&tmu0_clockevent);
-
-	return 0;
-}
-
-static struct sys_timer_ops tmu_timer_ops = {
-	.init		= tmu_timer_init,
-	.start		= tmu_timer_start,
-	.stop		= tmu_timer_stop,
-};
-
-struct sys_timer tmu_timer = {
-	.name	= "tmu",
-	.ops	= &tmu_timer_ops,
-};
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/traps_32.c linux-libre-2.6.31-gnu/arch/sh/kernel/traps_32.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/traps_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/traps_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,6 +34,7 @@
 # define TRAP_ILLEGAL_SLOT_INST	6
 # define TRAP_ADDRESS_ERROR	9
 # ifdef CONFIG_CPU_SH2A
+#  define TRAP_UBC		12
 #  define TRAP_FPU_ERROR	13
 #  define TRAP_DIVZERO_ERROR	17
 #  define TRAP_DIVOVF_ERROR	18
@@ -176,7 +177,7 @@
  *   (if that instruction is in a branch delay slot)
  * - return 0 if emulation okay, -EFAULT on existential error
  */
-static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
+static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
 				struct mem_access *ma)
 {
 	int ret, index, count;
@@ -321,10 +322,10 @@
  * - fetches the instruction from PC+2
  */
 static inline int handle_delayslot(struct pt_regs *regs,
-				   opcode_t old_instruction,
+				   insn_size_t old_instruction,
 				   struct mem_access *ma)
 {
-	opcode_t instruction;
+	insn_size_t instruction;
 	void __user *addr = (void __user *)(regs->pc +
 		instruction_size(old_instruction));
 
@@ -364,7 +365,7 @@
 
 static int handle_unaligned_notify_count = 10;
 
-int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
+int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
 			    struct mem_access *ma)
 {
 	u_int rm;
@@ -522,7 +523,7 @@
 	unsigned long error_code = 0;
 	mm_segment_t oldfs;
 	siginfo_t info;
-	opcode_t instruction;
+	insn_size_t instruction;
 	int tmp;
 
 	/* Intentional ifdef */
@@ -849,6 +850,10 @@
 #endif
 #endif
 
+#ifdef TRAP_UBC
+	set_exception_table_vec(TRAP_UBC, break_point_trap);
+#endif
+
 	/* Setup VBR for boot cpu */
 	per_cpu_trap_init();
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/traps_64.c linux-libre-2.6.31-gnu/arch/sh/kernel/traps_64.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/traps_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/traps_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -370,7 +370,6 @@
 		return -1;
 	}
 
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 	/* Check accessible.  For misaligned access in the kernel, assume the
 	   address is always accessible (and if not, just fault when the
 	   load/store gets done.) */
@@ -380,18 +379,13 @@
 		}
 		/* Do access_ok check later - it depends on whether it's a load or a store. */
 	}
-#endif
 
 	*address = addr;
 	return 0;
 }
 
-/* Default value as for sh */
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 static int user_mode_unaligned_fixup_count = 10;
 static int user_mode_unaligned_fixup_enable = 1;
-#endif
-
 static int kernel_mode_unaligned_fixup_count = 32;
 
 static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result)
@@ -440,7 +434,6 @@
 	}
 
 	destreg = (opcode >> 4) & 0x3f;
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 	if (user_mode(regs)) {
 		__u64 buffer;
 
@@ -470,9 +463,7 @@
 				width_shift, (unsigned long) regs->pc);
 			break;
 		}
-	} else
-#endif
-	{
+	} else {
 		/* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
 		__u64 lo, hi;
 
@@ -519,7 +510,6 @@
 	}
 
 	srcreg = (opcode >> 4) & 0x3f;
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 	if (user_mode(regs)) {
 		__u64 buffer;
 
@@ -546,9 +536,7 @@
 		if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) {
 			return -1; /* fault */
 		}
-	} else
-#endif
-	{
+	} else {
 		/* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
 		__u64 val = regs->regs[srcreg];
 
@@ -576,7 +564,6 @@
 
 }
 
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 /* Never need to fix up misaligned FPU accesses within the kernel since that's a real
    error. */
 static int misaligned_fpu_load(struct pt_regs *regs,
@@ -727,7 +714,6 @@
 		return -1;
 	}
 }
-#endif
 
 static int misaligned_fixup(struct pt_regs *regs)
 {
@@ -735,12 +721,8 @@
 	int error;
 	int major, minor;
 
-#if !defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
-	/* Never fixup user mode misaligned accesses without this option enabled. */
-	return -1;
-#else
-	if (!user_mode_unaligned_fixup_enable) return -1;
-#endif
+	if (!user_mode_unaligned_fixup_enable)
+		return -1;
 
 	error = read_opcode(regs->pc, &opcode, user_mode(regs));
 	if (error < 0) {
@@ -749,15 +731,12 @@
 	major = (opcode >> 26) & 0x3f;
 	minor = (opcode >> 16) & 0xf;
 
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 	if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) {
 		--user_mode_unaligned_fixup_count;
 		/* Only do 'count' worth of these reports, to remove a potential DoS against syslog */
 		printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
 		       current->comm, task_pid_nr(current), (__u32)regs->pc, opcode);
-	} else
-#endif
-	if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
+	} else if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
 		--kernel_mode_unaligned_fixup_count;
 		if (in_interrupt()) {
 			printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n",
@@ -830,7 +809,6 @@
 			}
 			break;
 
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 		case (0x94>>2): /* FLD.S */
 			error = misaligned_fpu_load(regs, opcode, 1, 2, 0);
 			break;
@@ -881,7 +859,6 @@
 				break;
 			}
 			break;
-#endif
 
 		default:
 			/* Fault */
@@ -907,7 +884,6 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
-#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "user_reports",
@@ -923,7 +899,6 @@
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec},
-#endif
 	{}
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/traps.c linux-libre-2.6.31-gnu/arch/sh/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/sh/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,11 +22,11 @@
 
 int is_valid_bugaddr(unsigned long addr)
 {
-	unsigned short opcode;
+	insn_size_t opcode;
 
 	if (addr < PAGE_OFFSET)
 		return 0;
-	if (probe_kernel_address((u16 *)addr, opcode))
+	if (probe_kernel_address((insn_size_t *)addr, opcode))
 		return 0;
 
 	return opcode == TRAPA_BUG_OPCODE;
@@ -66,9 +66,10 @@
 
 #ifdef CONFIG_BUG
 	if (__kernel_text_address(instruction_pointer(regs))) {
-		opcode_t insn = *(opcode_t *)instruction_pointer(regs);
+		insn_size_t insn = *(insn_size_t *)instruction_pointer(regs);
 		if (insn == TRAPA_BUG_OPCODE)
 			handle_BUG(regs);
+		return;
 	}
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/vmlinux_32.lds.S linux-libre-2.6.31-gnu/arch/sh/kernel/vmlinux_32.lds.S
--- linux-libre-2.6.30-gnu/arch/sh/kernel/vmlinux_32.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/vmlinux_32.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-/*
- * ld script to make SuperH Linux kernel
- * Written by Niibe Yutaka
- */
-#include <asm/thread_info.h>
-#include <asm/cache.h>
-#include <asm-generic/vmlinux.lds.h>
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
-#else
-OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux")
-#endif
-OUTPUT_ARCH(sh)
-ENTRY(_start)
-SECTIONS
-{
-#ifdef CONFIG_PMB_FIXED
-	. = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) +
-	    CONFIG_ZERO_PAGE_OFFSET;
-#elif defined(CONFIG_32BIT)
-	. = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
-#else
-	. = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
-#endif
-
-	_text = .;			/* Text and read-only data */
-
-	.empty_zero_page : {
-		*(.empty_zero_page)
-	} = 0
-
-	.text : {
-		HEAD_TEXT
-		TEXT_TEXT
-		SCHED_TEXT
-		LOCK_TEXT
-		KPROBES_TEXT
-		*(.fixup)
-		*(.gnu.warning)
-	} = 0x0009
-
-	. = ALIGN(16);		/* Exception table */
-	__start___ex_table = .;
-	__ex_table : { *(__ex_table) }
-	__stop___ex_table = .;
-
-	_etext = .;			/* End of text section */
-
-	NOTES
-	RO_DATA(PAGE_SIZE)
-
-	/*
-	 * Code which must be executed uncached and the associated data
-	 */
-	. = ALIGN(PAGE_SIZE);
-	__uncached_start = .;
-	.uncached.text : { *(.uncached.text) }
-	.uncached.data : { *(.uncached.data) }
-	__uncached_end = .;
-
-	. = ALIGN(THREAD_SIZE);
-	.data : {			/* Data */
-		*(.data.init_task)
-
-		. = ALIGN(L1_CACHE_BYTES);
-		*(.data.cacheline_aligned)
-
-		. = ALIGN(L1_CACHE_BYTES);
-		*(.data.read_mostly)
-
-		. = ALIGN(PAGE_SIZE);
-		*(.data.page_aligned)
-
-		__nosave_begin = .;
-		*(.data.nosave)
-		. = ALIGN(PAGE_SIZE);
-		__nosave_end = .;
-
-		DATA_DATA
-		CONSTRUCTORS
-	}
-
-	_edata = .;			/* End of data section */
-
-	. = ALIGN(PAGE_SIZE);		/* Init code and data */
-	__init_begin = .;
-	_sinittext = .;
-	.init.text : { INIT_TEXT }
-	_einittext = .;
-	.init.data : { INIT_DATA }
-
-	. = ALIGN(16);
-	__setup_start = .;
-	.init.setup : { *(.init.setup) }
-	__setup_end = .;
-
-	__initcall_start = .;
-	.initcall.init : {
-		INITCALLS
-	}
-	__initcall_end = .;
-	__con_initcall_start = .;
-	.con_initcall.init : { *(.con_initcall.init) }
-	__con_initcall_end = .;
-
-	SECURITY_INIT
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	. = ALIGN(PAGE_SIZE);
-	__initramfs_start = .;
-	.init.ramfs : { *(.init.ramfs) }
-	__initramfs_end = .;
-#endif
-
-	. = ALIGN(4);
-	__machvec_start = .;
-	.machvec.init : { *(.machvec.init) }
-	__machvec_end = .;
-
-	PERCPU(PAGE_SIZE)
-
-	/*
-	 * .exit.text is discarded at runtime, not link time, to deal with
-	 * references from __bug_table
-	 */
-	.exit.text : { EXIT_TEXT }
-	.exit.data : { EXIT_DATA }
-
-	. = ALIGN(PAGE_SIZE);
-	.bss : {
-		__init_end = .;
-		__bss_start = .;		/* BSS */
-		*(.bss.page_aligned)
-		*(.bss)
-		*(COMMON)
-		. = ALIGN(4);
-		_ebss = .;			/* uClinux MTD sucks */
-		_end = . ;
-	}
-
-	/*
-	 * When something in the kernel is NOT compiled as a module, the
-	 * module cleanup code and data are put into these segments. Both
-	 * can then be thrown away, as cleanup code is never called unless
-	 * it's a module.
-	 */
-	/DISCARD/ : {
-		*(.exitcall.exit)
-	}
-
-	STABS_DEBUG
-	DWARF_DEBUG
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/vmlinux_64.lds.S linux-libre-2.6.31-gnu/arch/sh/kernel/vmlinux_64.lds.S
--- linux-libre-2.6.30-gnu/arch/sh/kernel/vmlinux_64.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/vmlinux_64.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-/*
- * ld script to make SH64 Linux kernel
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- * benedict.gaster@superh.com:	 2nd May 2002
- *    Add definition of empty_zero_page to be the first page of kernel image.
- *
- * benedict.gaster@superh.com:	 3rd May 2002
- *    Added support for ramdisk, removing statically linked romfs at the
- *    same time.
- *
- * lethal@linux-sh.org:          9th May 2003
- *    Kill off GLOBAL_NAME() usage and other CDC-isms.
- *
- * lethal@linux-sh.org:         19th May 2003
- *    Remove support for ancient toolchains.
- *
- * 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/page.h>
-#include <asm/cache.h>
-#include <asm/thread_info.h>
-
-#define LOAD_OFFSET	CONFIG_PAGE_OFFSET
-#include <asm-generic/vmlinux.lds.h>
-
-OUTPUT_ARCH(sh:sh5)
-
-#define C_PHYS(x) AT (ADDR(x) - LOAD_OFFSET)
-
-ENTRY(__start)
-SECTIONS
-{
-	. = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + PAGE_SIZE;
-	_text = .;			/* Text and read-only data */
-
-	.empty_zero_page : C_PHYS(.empty_zero_page) {
-		*(.empty_zero_page)
-	} = 0
-
-	.text : C_PHYS(.text) {
-		HEAD_TEXT
-		TEXT_TEXT
-		*(.text64)
-		*(.text..SHmedia32)
-		SCHED_TEXT
-		LOCK_TEXT
-		KPROBES_TEXT
-		*(.fixup)
-		*(.gnu.warning)
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-	} = 0x6ff0fff0
-#else
-	} = 0xf0fff06f
-#endif
-
-	/* We likely want __ex_table to be Cache Line aligned */
-	. = ALIGN(L1_CACHE_BYTES);		/* Exception table */
-	__start___ex_table = .;
-	__ex_table : C_PHYS(__ex_table) { *(__ex_table) }
-	__stop___ex_table = .;
-
-	_etext = .;			/* End of text section */
-
-	NOTES 
-	RO_DATA(PAGE_SIZE)
-
-	. = ALIGN(THREAD_SIZE);
-	.data : C_PHYS(.data) {			/* Data */
-		*(.data.init_task)
-
-		. = ALIGN(L1_CACHE_BYTES);
-		*(.data.cacheline_aligned)
-
-		. = ALIGN(L1_CACHE_BYTES);
-		*(.data.read_mostly)
-
-		. = ALIGN(PAGE_SIZE);
-		*(.data.page_aligned)
-
-		__nosave_begin = .;
-		*(.data.nosave)
-		. = ALIGN(PAGE_SIZE);
-		__nosave_end = .;
-
-		DATA_DATA
-		CONSTRUCTORS
-	}
-
-	_edata = .;			/* End of data section */
-
-	. = ALIGN(PAGE_SIZE);		/* Init code and data */
-	__init_begin = .;
-	_sinittext = .;
-	.init.text : C_PHYS(.init.text) { INIT_TEXT }
-	_einittext = .;
-	.init.data : C_PHYS(.init.data) { INIT_DATA }
-	. = ALIGN(L1_CACHE_BYTES);	/* Better if Cache Line aligned */
-	__setup_start = .;
-	.init.setup : C_PHYS(.init.setup) { *(.init.setup) }
-	__setup_end = .;
-	__initcall_start = .;
-	.initcall.init : C_PHYS(.initcall.init) {
-		INITCALLS
-	}
-	__initcall_end = .;
-	__con_initcall_start = .;
-	.con_initcall.init : C_PHYS(.con_initcall.init) {
-		*(.con_initcall.init)
-	}
-	__con_initcall_end = .;
-
-	SECURITY_INIT
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	. = ALIGN(PAGE_SIZE);
-	__initramfs_start = .;
-	.init.ramfs : C_PHYS(.init.ramfs) { *(.init.ramfs) }
-	__initramfs_end = .;
-#endif
-
-	. = ALIGN(8);
-	__machvec_start = .;
-	.machvec.init : C_PHYS(.machvec.init) { *(.machvec.init) }
-	__machvec_end = .;
-
-	PERCPU(PAGE_SIZE)
-
-	/*
-	 * .exit.text is discarded at runtime, not link time, to deal with
-	 * references from __bug_table
-	 */
-	.exit.text : C_PHYS(.exit.text) { EXIT_TEXT }
-	.exit.data : C_PHYS(.exit.data) { EXIT_DATA }
-
-	. = ALIGN(PAGE_SIZE);
-	.bss : C_PHYS(.bss) {
-		__init_end = .;
-		__bss_start = .;		/* BSS */
-		*(.bss.page_aligned)
-		*(.bss)
-		*(COMMON)
-		. = ALIGN(4);
-		_ebss = .;			/* uClinux MTD sucks */
-		_end = . ;
-	}
-
-	/*
-	 * When something in the kernel is NOT compiled as a module, the
-	 * module cleanup code and data are put into these segments. Both
-	 * can then be thrown away, as cleanup code is never called unless
-	 * it's a module.
-	 */
-	/DISCARD/ : {
-		*(.exitcall.exit)
-	}
-
-	STABS_DEBUG
-	DWARF_DEBUG
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/kernel/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/sh/kernel/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/sh/kernel/vmlinux.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/kernel/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,178 @@
-#ifdef CONFIG_SUPERH32
-# include "vmlinux_32.lds.S"
+/*
+ * ld script to make SuperH Linux kernel
+ * Written by Niibe Yutaka and Paul Mundt
+ */
+#ifdef CONFIG_SUPERH64
+#define LOAD_OFFSET	CONFIG_PAGE_OFFSET
+OUTPUT_ARCH(sh:sh5)
 #else
-# include "vmlinux_64.lds.S"
+#define LOAD_OFFSET	0
+OUTPUT_ARCH(sh)
 #endif
+
+#include <asm/thread_info.h>
+#include <asm/cache.h>
+#include <asm-generic/vmlinux.lds.h>
+
+ENTRY(_start)
+SECTIONS
+{
+#ifdef CONFIG_PMB_FIXED
+	. = CONFIG_PAGE_OFFSET + (CONFIG_MEMORY_START & 0x1fffffff) +
+	    CONFIG_ZERO_PAGE_OFFSET;
+#elif defined(CONFIG_32BIT)
+	. = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET;
+#else
+	. = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
+#endif
+
+	_text = .;		/* Text and read-only data */
+
+	.empty_zero_page : AT(ADDR(.empty_zero_page) - LOAD_OFFSET) {
+		*(.empty_zero_page)
+	} = 0
+
+	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+		HEAD_TEXT
+		TEXT_TEXT
+
+#ifdef CONFIG_SUPERH64
+		*(.text64)
+		*(.text..SHmedia32)
+#endif
+
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		IRQENTRY_TEXT
+		*(.fixup)
+		*(.gnu.warning)
+		_etext = .;		/* End of text section */
+	} = 0x0009
+
+	. = ALIGN(16);		/* Exception table */
+	__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+		__start___ex_table = .;
+		*(__ex_table)
+		__stop___ex_table = .;
+	}
+
+	NOTES
+	RO_DATA(PAGE_SIZE)
+
+	/*
+	 * Code which must be executed uncached and the associated data
+	 */
+	. = ALIGN(PAGE_SIZE);
+	.uncached : AT(ADDR(.uncached) - LOAD_OFFSET) {
+		__uncached_start = .;
+		*(.uncached.text)
+		*(.uncached.data)
+		__uncached_end = .;
+	}
+
+	. = ALIGN(THREAD_SIZE);
+	.data : AT(ADDR(.data) - LOAD_OFFSET) {		/* Data */
+		*(.data.init_task)
+
+		. = ALIGN(L1_CACHE_BYTES);
+		*(.data.cacheline_aligned)
+
+		. = ALIGN(L1_CACHE_BYTES);
+		*(.data.read_mostly)
+
+		. = ALIGN(PAGE_SIZE);
+		*(.data.page_aligned)
+
+		__nosave_begin = .;
+		*(.data.nosave)
+		. = ALIGN(PAGE_SIZE);
+		__nosave_end = .;
+
+		DATA_DATA
+		CONSTRUCTORS
+	}
+
+	_edata = .;			/* End of data section */
+
+	. = ALIGN(PAGE_SIZE);		/* Init code and data */
+	.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
+		__init_begin = .;
+		_sinittext = .;
+		INIT_TEXT
+		_einittext = .;
+	}
+
+	.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { INIT_DATA }
+
+	. = ALIGN(16);
+	.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+		__setup_start = .;
+		*(.init.setup)
+		__setup_end = .;
+	}
+
+	.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+		__initcall_start = .;
+		INITCALLS
+		__initcall_end = .;
+	}
+
+	.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+		__con_initcall_start = .;
+		*(.con_initcall.init)
+		__con_initcall_end = .;
+	}
+
+	SECURITY_INIT
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	. = ALIGN(PAGE_SIZE);
+	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+		__initramfs_start = .;
+		*(.init.ramfs)
+		__initramfs_end = .;
+	}
+#endif
+
+	. = ALIGN(4);
+	.machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) {
+		__machvec_start = .;
+		*(.machvec.init)
+		__machvec_end = .;
+	}
+
+	PERCPU(PAGE_SIZE)
+
+	/*
+	 * .exit.text is discarded at runtime, not link time, to deal with
+	 * references from __bug_table
+	 */
+	.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { EXIT_TEXT }
+	.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA }
+
+	. = ALIGN(PAGE_SIZE);
+	.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+		__init_end = .;
+		__bss_start = .;		/* BSS */
+		*(.bss.page_aligned)
+		*(.bss)
+		*(COMMON)
+		. = ALIGN(4);
+		_ebss = .;			/* uClinux MTD sucks */
+		_end = . ;
+	}
+
+	/*
+	 * When something in the kernel is NOT compiled as a module, the
+	 * module cleanup code and data are put into these segments. Both
+	 * can then be thrown away, as cleanup code is never called unless
+	 * it's a module.
+	 */
+	/DISCARD/ : {
+		*(.exitcall.exit)
+	}
+
+	STABS_DEBUG
+	DWARF_DEBUG
+}
diff -druN linux-libre-2.6.30-gnu/arch/sh/lib64/c-checksum.c linux-libre-2.6.31-gnu/arch/sh/lib64/c-checksum.c
--- linux-libre-2.6.30-gnu/arch/sh/lib64/c-checksum.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/lib64/c-checksum.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,214 +0,0 @@
-/*
- * arch/sh/lib64/c-checksum.c
- *
- * This file contains network checksum routines that are better done
- * in an architecture-specific manner due to speed..
- */
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-static inline unsigned short from64to16(unsigned long long x)
-{
-	/* add up 32-bit words for 33 bits */
-	x = (x & 0xffffffff) + (x >> 32);
-	/* add up 16-bit and 17-bit words for 17+c bits */
-	x = (x & 0xffff) + (x >> 16);
-	/* add up 16-bit and 2-bit for 16+c bit */
-	x = (x & 0xffff) + (x >> 16);
-	/* add up carry.. */
-	x = (x & 0xffff) + (x >> 16);
-	return x;
-}
-
-static inline unsigned short foldto16(unsigned long x)
-{
-	/* add up 16-bit for 17 bits */
-	x = (x & 0xffff) + (x >> 16);
-	/* add up carry.. */
-	x = (x & 0xffff) + (x >> 16);
-	return x;
-}
-
-static inline unsigned short myfoldto16(unsigned long long x)
-{
-	/* Fold down to 32-bits so we don't lose in the typedef-less
-	   network stack.  */
-	/* 64 to 33 */
-	x = (x & 0xffffffff) + (x >> 32);
-	/* 33 to 32 */
-	x = (x & 0xffffffff) + (x >> 32);
-
-	/* add up 16-bit for 17 bits */
-	x = (x & 0xffff) + (x >> 16);
-	/* add up carry.. */
-	x = (x & 0xffff) + (x >> 16);
-	return x;
-}
-
-#define odd(x) ((x)&1)
-#define U16(x) ntohs(x)
-
-static unsigned long do_csum(const unsigned char *buff, int len)
-{
-	int odd, count;
-	unsigned long result = 0;
-
-	pr_debug("do_csum buff %p, len %d (0x%x)\n", buff, len, len);
-#ifdef DEBUG
-	for (i = 0; i < len; i++) {
-		if ((i % 26) == 0)
-			printk("\n");
-		printk("%02X ", buff[i]);
-	}
-#endif
-
-	if (len <= 0)
-		goto out;
-
-	odd = 1 & (unsigned long) buff;
-	if (odd) {
-		result = *buff << 8;
-		len--;
-		buff++;
-	}
-	count = len >> 1;	/* nr of 16-bit words.. */
-	if (count) {
-		if (2 & (unsigned long) buff) {
-			result += *(unsigned short *) buff;
-			count--;
-			len -= 2;
-			buff += 2;
-		}
-		count >>= 1;	/* nr of 32-bit words.. */
-		if (count) {
-			unsigned long carry = 0;
-			do {
-				unsigned long w = *(unsigned long *) buff;
-				buff += 4;
-				count--;
-				result += carry;
-				result += w;
-				carry = (w > result);
-			} while (count);
-			result += carry;
-			result = (result & 0xffff) + (result >> 16);
-		}
-		if (len & 2) {
-			result += *(unsigned short *) buff;
-			buff += 2;
-		}
-	}
-	if (len & 1)
-		result += *buff;
-	result = foldto16(result);
-	if (odd)
-		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-
-	pr_debug("\nCHECKSUM is 0x%lx\n", result);
-
-      out:
-	return result;
-}
-
-/* computes the checksum of a memory block at buff, length len,
-   and adds in "sum" (32-bit)  */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
-	unsigned long long result = do_csum(buff, len);
-
-	/* add in old sum, and carry.. */
-	result += (__force u32)sum;
-	/* 32+c bits -> 32 bits */
-	result = (result & 0xffffffff) + (result >> 32);
-
-	pr_debug("csum_partial, buff %p len %d sum 0x%x result=0x%016Lx\n",
-		buff, len, sum, result);
-
-	return (__force __wsum)result;
-}
-
-/* Copy while checksumming, otherwise like csum_partial.  */
-__wsum
-csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
-{
-	sum = csum_partial(src, len, sum);
-	memcpy(dst, src, len);
-
-	return sum;
-}
-
-/* Copy from userspace and compute checksum.  If we catch an exception
-   then zero the rest of the buffer.  */
-__wsum
-csum_partial_copy_from_user(const void __user *src, void *dst, int len,
-			    __wsum sum, int *err_ptr)
-{
-	int missing;
-
-	pr_debug
-	    ("csum_partial_copy_from_user src %p, dest %p, len %d, sum %08x, err_ptr %p\n",
-	     src, dst, len, sum, err_ptr);
-	missing = copy_from_user(dst, src, len);
-	pr_debug("  access_ok %d\n", __access_ok((unsigned long) src, len));
-	pr_debug("  missing %d\n", missing);
-	if (missing) {
-		memset(dst + len - missing, 0, missing);
-		*err_ptr = -EFAULT;
-	}
-
-	return csum_partial(dst, len, sum);
-}
-
-/* Copy to userspace and compute checksum.  */
-__wsum
-csum_partial_copy_to_user(const unsigned char *src, unsigned char *dst, int len,
-			  __wsum sum, int *err_ptr)
-{
-	sum = csum_partial(src, len, sum);
-
-	if (copy_to_user(dst, src, len))
-		*err_ptr = -EFAULT;
-
-	return sum;
-}
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	pr_debug("ip_fast_csum %p,%d\n", iph, ihl);
-
-	return (__force __sum16)~do_csum(iph, ihl * 4);
-}
-
-__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-				unsigned short len,
-				unsigned short proto, __wsum sum)
-{
-	unsigned long long result;
-
-	pr_debug("ntohs(0x%x)=0x%x\n", 0xdead, ntohs(0xdead));
-	pr_debug("htons(0x%x)=0x%x\n", 0xdead, htons(0xdead));
-
-	result = (__force u64) saddr + (__force u64) daddr +
-		 (__force u64) sum + ((len + proto) << 8);
-
-	/* Fold down to 32-bits so we don't lose in the typedef-less
-	   network stack.  */
-	/* 64 to 33 */
-	result = (result & 0xffffffff) + (result >> 32);
-	/* 33 to 32 */
-	result = (result & 0xffffffff) + (result >> 32);
-
-	pr_debug("%s saddr %x daddr %x len %x proto %x sum %x result %08Lx\n",
-		__func__, saddr, daddr, len, proto, sum, result);
-
-	return (__wsum)result;
-}
-EXPORT_SYMBOL(csum_tcpudp_nofold);
diff -druN linux-libre-2.6.30-gnu/arch/sh/lib64/dbg.c linux-libre-2.6.31-gnu/arch/sh/lib64/dbg.c
--- linux-libre-2.6.30-gnu/arch/sh/lib64/dbg.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/lib64/dbg.c	2009-09-09 18:13:59.000000000 -0400
@@ -135,140 +135,6 @@
 	    (" =============================================================\n");
 }
 
-/* ======================================================================= */
-
-#ifdef CONFIG_POOR_MANS_STRACE
-
-#include "syscalltab.h"
-
-struct ring_node {
-	int evt;
-	int ret_addr;
-	int event;
-	int tra;
-	int pid;
-	unsigned long sp;
-	unsigned long pc;
-};
-
-static struct ring_node event_ring[16];
-static int event_ptr = 0;
-
-struct stored_syscall_data {
-	int pid;
-	int syscall_number;
-};
-
-#define N_STORED_SYSCALLS 16
-
-static struct stored_syscall_data stored_syscalls[N_STORED_SYSCALLS];
-static int syscall_next=0;
-static int syscall_next_print=0;
-
-void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs)
-{
-	int syscallno = tra & 0xff;
-	unsigned long sp;
-	unsigned long stack_bottom;
-	int pid;
-	struct ring_node *rr;
-
-	pid = current->pid;
-	stack_bottom = (unsigned long) task_stack_page(current);
-	asm volatile("ori r15, 0, %0" : "=r" (sp));
-	rr = event_ring + event_ptr;
-	rr->evt = evt;
-	rr->ret_addr = ret_addr;
-	rr->event = event;
-	rr->tra = tra;
-	rr->pid = pid;
-	rr->sp = sp;
-	rr->pc = regs->pc;
-
-	if (sp < stack_bottom + 3092) {
-		int i, j;
-		printk("evt_debug : stack underflow report\n");
-		for (j=0, i = event_ptr; j<16; j++) {
-			rr = event_ring + i;
-			printk("evt=%08x event=%08x tra=%08x pid=%5d sp=%08lx pc=%08lx\n",
-				rr->evt, rr->event, rr->tra, rr->pid, rr->sp, rr->pc);
-			i--;
-			i &= 15;
-		}
-		panic("STACK UNDERFLOW\n");
-	}
-
-	event_ptr = (event_ptr + 1) & 15;
-
-	if ((event == 2) && (evt == 0x160)) {
-		if (syscallno < NUM_SYSCALL_INFO_ENTRIES) {
-			/* Store the syscall information to print later.  We
-			 * can't print this now - currently we're running with
-			 * SR.BL=1, so we can't take a tlbmiss (which could occur
-			 * in the console drivers under printk).
-			 *
-			 * Just overwrite old entries on ring overflow - this
-			 * is only for last-hope debugging. */
-			stored_syscalls[syscall_next].pid = current->pid;
-			stored_syscalls[syscall_next].syscall_number = syscallno;
-			syscall_next++;
-			syscall_next &= (N_STORED_SYSCALLS - 1);
-		}
-	}
-}
-
-static void drain_syscalls(void) {
-	while (syscall_next_print != syscall_next) {
-		printk("Task %d: %s()\n",
-			stored_syscalls[syscall_next_print].pid,
-			syscall_info_table[stored_syscalls[syscall_next_print].syscall_number].name);
-			syscall_next_print++;
-			syscall_next_print &= (N_STORED_SYSCALLS - 1);
-	}
-}
-
-void evt_debug2(unsigned int ret)
-{
-	drain_syscalls();
-	printk("Task %d: syscall returns %08x\n", current->pid, ret);
-}
-
-void evt_debug_ret_from_irq(struct pt_regs *regs)
-{
-	int pid;
-	struct ring_node *rr;
-
-	pid = current->pid;
-	rr = event_ring + event_ptr;
-	rr->evt = 0xffff;
-	rr->ret_addr = 0;
-	rr->event = 0;
-	rr->tra = 0;
-	rr->pid = pid;
-	rr->pc = regs->pc;
-	event_ptr = (event_ptr + 1) & 15;
-}
-
-void evt_debug_ret_from_exc(struct pt_regs *regs)
-{
-	int pid;
-	struct ring_node *rr;
-
-	pid = current->pid;
-	rr = event_ring + event_ptr;
-	rr->evt = 0xfffe;
-	rr->ret_addr = 0;
-	rr->event = 0;
-	rr->tra = 0;
-	rr->pid = pid;
-	rr->pc = regs->pc;
-	event_ptr = (event_ptr + 1) & 15;
-}
-
-#endif /* CONFIG_POOR_MANS_STRACE */
-
-/* ======================================================================= */
-
 void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
 {
 
@@ -380,51 +246,3 @@
 	print_dtlb();
 	print_itlb();
 }
-
-/* ======================================================================= */
-
-/*
-** Depending on <base> scan the MMU, Data or Instruction side
-** looking for a valid mapping matching Eaddr & asid.
-** Return -1 if not found or the TLB id entry otherwise.
-** Note: it works only for 4k pages!
-*/
-static unsigned long
-lookup_mmu_side(unsigned long base, unsigned long Eaddr, unsigned long asid)
-{
-	regType_t pteH;
-	unsigned long epn;
-	int count;
-
-	epn = Eaddr & 0xfffff000;
-
-	for (count = 0; count < MAX_TLBs; count++, base += TLB_STEP) {
-		pteH = getConfigReg(base);
-		if (GET_VALID(pteH))
-			if ((unsigned long) GET_EPN(pteH) == epn)
-				if ((unsigned long) GET_ASID(pteH) == asid)
-					break;
-	}
-	return ((unsigned long) ((count < MAX_TLBs) ? base : -1));
-}
-
-unsigned long lookup_dtlb(unsigned long Eaddr)
-{
-	unsigned long asid = get_asid();
-	return (lookup_mmu_side((u64) DTLB_BASE, Eaddr, asid));
-}
-
-unsigned long lookup_itlb(unsigned long Eaddr)
-{
-	unsigned long asid = get_asid();
-	return (lookup_mmu_side((u64) ITLB_BASE, Eaddr, asid));
-}
-
-void print_page(struct page *page)
-{
-	printk("  page[%p] -> index 0x%lx,  count 0x%x,  flags 0x%lx\n",
-	       page, page->index, page_count(page), page->flags);
-	printk("       address_space = %p, pages =%ld\n", page->mapping,
-	       page->mapping->nrpages);
-
-}
diff -druN linux-libre-2.6.30-gnu/arch/sh/lib64/.gitignore linux-libre-2.6.31-gnu/arch/sh/lib64/.gitignore
--- linux-libre-2.6.30-gnu/arch/sh/lib64/.gitignore	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/lib64/.gitignore	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-syscalltab.h
diff -druN linux-libre-2.6.30-gnu/arch/sh/lib64/Makefile linux-libre-2.6.31-gnu/arch/sh/lib64/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/lib64/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/lib64/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,7 @@
 #
 
 # Panic should really be compiled as PIC
-lib-y  := udelay.o c-checksum.o dbg.o panic.o memcpy.o memset.o \
+lib-y  := udelay.o dbg.o panic.o memcpy.o memset.o \
 	  copy_user_memcpy.o copy_page.o clear_page.o strcpy.o strlen.o
 
 # Extracted from libgcc
diff -druN linux-libre-2.6.30-gnu/arch/sh/lib64/panic.c linux-libre-2.6.31-gnu/arch/sh/lib64/panic.c
--- linux-libre-2.6.30-gnu/arch/sh/lib64/panic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/lib64/panic.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,53 +6,10 @@
  * for more details.
  */
 
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <cpu/registers.h>
-
-/* THIS IS A PHYSICAL ADDRESS */
-#define HDSP2534_ADDR (0x04002100)
-
-#ifdef CONFIG_SH_CAYMAN
-
-static void poor_mans_delay(void)
-{
-	int i;
-	for (i = 0; i < 2500000; i++) {
-	}		/* poor man's delay */
-}
-
-static void show_value(unsigned long x)
-{
-	int i;
-	unsigned nibble;
-	for (i = 0; i < 8; i++) {
-		nibble = ((x >> (i * 4)) & 0xf);
-
-		ctrl_outb(nibble + ((nibble > 9) ? 55 : 48),
-			  HDSP2534_ADDR + 0xe0 + ((7 - i) << 2));
-	}
-}
-
-#endif
-
 void
 panic_handler(unsigned long panicPC, unsigned long panicSSR,
 	      unsigned long panicEXPEVT)
 {
-#ifdef CONFIG_SH_CAYMAN
-	while (1) {
-		/* This piece of code displays the PC on the LED display */
-		show_value(panicPC);
-		poor_mans_delay();
-		show_value(panicSSR);
-		poor_mans_delay();
-		show_value(panicEXPEVT);
-		poor_mans_delay();
-	}
-#endif
-
 	/* Never return from the panic handler */
 	for (;;) ;
-
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/lib64/sdivsi3.S linux-libre-2.6.31-gnu/arch/sh/lib64/sdivsi3.S
--- linux-libre-2.6.30-gnu/arch/sh/lib64/sdivsi3.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/lib64/sdivsi3.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,6 @@
 	.global	__sdivsi3
+	.global	__sdivsi3_1
+	.global	__sdivsi3_2
 	.section	.text..SHmedia32,"ax"
 	.align	2
 
@@ -6,13 +8,15 @@
 	/* clobbered: r1,r18,r19,r20,r21,r25,tr0 */
 	/* result in r0 */
 __sdivsi3:
+__sdivsi3_1:
 	ptb __div_table,tr0
+	gettr tr0,r20
 
+__sdivsi3_2:
 	nsb r5, r1
 	shlld r5, r1, r25    /* normalize; [-2 ..1, 1..2) in s2.62 */
 	shari r25, 58, r21   /* extract 5(6) bit index (s2.4 with hole -1..1) */
 	/* bubble */
-	gettr tr0,r20
 	ldx.ub r20, r21, r19 /* u0.8 */
 	shari r25, 32, r25   /* normalize to s2.30 */
 	shlli r21, 1, r21
diff -druN linux-libre-2.6.30-gnu/arch/sh/lib64/udelay.c linux-libre-2.6.31-gnu/arch/sh/lib64/udelay.c
--- linux-libre-2.6.30-gnu/arch/sh/lib64/udelay.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/lib64/udelay.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,7 @@
 			     :"0"(loops));
 }
 
-inline void __const_udelay(unsigned long xloops)
+void __const_udelay(unsigned long xloops)
 {
 	__delay(xloops * (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy));
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/Makefile linux-libre-2.6.31-gnu/arch/sh/Makefile
--- linux-libre-2.6.30-gnu/arch/sh/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -70,9 +70,6 @@
 cflags-y	+= $(call cc-option,-mno-fdpic)
 cflags-y	+= $(isaflags-y) -ffreestanding
 
-cflags-$(CONFIG_MORE_COMPILE_OPTIONS)	+= \
-	$(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g')
-
 OBJCOPYFLAGS	:= -O binary -R .note -R .note.gnu.build-id -R .comment \
 		   -R .stab -R .stabstr -S
 
@@ -85,7 +82,6 @@
 defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE)	:= vmlinux
 
 # Set some sensible Kbuild defaults
-KBUILD_DEFCONFIG	:= shx3_defconfig
 KBUILD_IMAGE		:= $(defaultimage-y)
 
 #
@@ -93,26 +89,38 @@
 # error messages during linking.
 #
 ifdef CONFIG_SUPERH32
-UTS_MACHINE	:= sh
-LDFLAGS_vmlinux	+= -e _stext
+UTS_MACHINE		:= sh
+BITS			:= 32
+LDFLAGS_vmlinux		+= -e _stext
+KBUILD_DEFCONFIG	:= shx3_defconfig
 else
-UTS_MACHINE	:= sh64
-LDFLAGS_vmlinux	+= --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \
-		   --defsym phys_stext_shmedia=phys_stext+1 \
-		   -e phys_stext_shmedia
+UTS_MACHINE		:= sh64
+BITS			:= 64
+LDFLAGS_vmlinux		+= --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \
+			   --defsym phys_stext_shmedia=phys_stext+1 \
+			   -e phys_stext_shmedia
+KBUILD_DEFCONFIG	:= cayman_defconfig
+endif
+
+ifneq ($(SUBARCH),$(ARCH))
+  ifeq ($(CROSS_COMPILE),)
+    CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux-  $(UTS_MACHINE)-linux-gnu-  $(UTS_MACHINE)-unknown-linux-gnu-)
+  endif
 endif
 
 ifdef CONFIG_CPU_LITTLE_ENDIAN
-LDFLAGS_vmlinux		+= --defsym 'jiffies=jiffies_64'
+ld-bfd			:= elf32-$(UTS_MACHINE)-linux
+LDFLAGS_vmlinux		+= --defsym 'jiffies=jiffies_64' --oformat $(ld-bfd)
 LDFLAGS			+= -EL
 else
-LDFLAGS_vmlinux		+= --defsym 'jiffies=jiffies_64+4'
+ld-bfd			:= elf32-$(UTS_MACHINE)big-linux
+LDFLAGS_vmlinux		+= --defsym 'jiffies=jiffies_64+4' --oformat $(ld-bfd)
 LDFLAGS			+= -EB
 endif
 
-head-y			:= arch/sh/kernel/init_task.o
-head-$(CONFIG_SUPERH32)	+= arch/sh/kernel/head_32.o
-head-$(CONFIG_SUPERH64)	+= arch/sh/kernel/head_64.o
+export ld-bfd BITS
+
+head-y	:= arch/sh/kernel/init_task.o arch/sh/kernel/head_$(BITS).o
 
 core-y				+= arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/
 core-$(CONFIG_SH_FPU_EMU)	+= arch/sh/math-emu/
@@ -193,10 +201,11 @@
 
 compressed: zImage
 
-archprepare: maketools arch/sh/lib64/syscalltab.h
+archprepare: maketools
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
+	$(Q)$(MAKE) $(clean)=arch/sh/kernel/vsyscall
 
 define archhelp
 	@echo '* zImage 	           - Compressed kernel image'
@@ -205,34 +214,4 @@
 	@echo '  uImage.srec  	           - Create an S-record for U-Boot'
 endef
 
-define filechk_gen-syscalltab
-       (set -e; \
-	echo "/*"; \
-	echo " * DO NOT MODIFY."; \
-	echo " *"; \
-	echo " * This file was generated by arch/sh/Makefile"; \
-	echo " * Any changes will be reverted at build time."; \
-	echo " */"; \
-	echo ""; \
-	echo "#ifndef __SYSCALLTAB_H"; \
-	echo "#define __SYSCALLTAB_H"; \
-	echo ""; \
-	echo "#include <linux/kernel.h>"; \
-	echo ""; \
-	echo "struct syscall_info {"; \
-	echo "	const char *name;"; \
-	echo "} syscall_info_table[] = {"; \
-	sed -e '/^.*\.long /!d;s//	{ "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \
-		s/[ \t]*$$//g;s/$$/" },/;s/\("\)sys_/\1/g'; \
-	echo "};"; \
-	echo ""; \
-	echo "#define NUM_SYSCALL_INFO_ENTRIES ARRAY_SIZE(syscall_info_table)";\
-	echo ""; \
-	echo "#endif /* __SYSCALLTAB_H */" )
-endef
-
-arch/sh/lib64/syscalltab.h: arch/sh/kernel/syscalls_64.S
-	$(call filechk,gen-syscalltab)
-
-CLEAN_FILES += arch/sh/lib64/syscalltab.h \
-	       include/asm-sh/machtypes.h
+CLEAN_FILES += include/asm-sh/machtypes.h
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/cache-sh5.c linux-libre-2.6.31-gnu/arch/sh/mm/cache-sh5.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/cache-sh5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/cache-sh5.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,7 +60,7 @@
 static inline void sh64_icache_inv_all(void)
 {
 	unsigned long long addr, flag, data;
-	unsigned int flags;
+	unsigned long flags;
 
 	addr = ICCR0;
 	flag = ICCR0_ICI;
@@ -172,7 +172,7 @@
 		unsigned long eaddr;
 		unsigned long after_last_page_start;
 		unsigned long mm_asid, current_asid;
-		unsigned long long flags = 0ULL;
+		unsigned long flags = 0;
 
 		mm_asid = cpu_asid(smp_processor_id(), mm);
 		current_asid = get_asid();
@@ -236,7 +236,7 @@
 	unsigned long long eaddr = start;
 	unsigned long long eaddr_end = start + len;
 	unsigned long current_asid, mm_asid;
-	unsigned long long flags;
+	unsigned long flags;
 	unsigned long long epage_start;
 
 	/*
@@ -342,7 +342,7 @@
 			 * alloco is a NOP if the cache is write-through.
 			 */
 			if (test_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags)))
-				ctrl_inb(eaddr);
+				__raw_readb((unsigned long)eaddr);
 		}
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/fault_32.c linux-libre-2.6.31-gnu/arch/sh/mm/fault_32.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/fault_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/fault_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,12 +15,28 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
-#include <linux/marker.h>
+#include <linux/perf_counter.h>
 #include <asm/io_trapped.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
+static inline int notify_page_fault(struct pt_regs *regs, int trap)
+{
+	int ret = 0;
+
+#ifdef CONFIG_KPROBES
+	if (!user_mode(regs)) {
+		preempt_disable();
+		if (kprobe_running() && kprobe_fault_handler(regs, trap))
+			ret = 1;
+		preempt_enable();
+	}
+#endif
+
+	return ret;
+}
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -87,13 +103,16 @@
 		return;
 	}
 
+	mm = tsk->mm;
+
+	if (unlikely(notify_page_fault(regs, lookup_exception_vector())))
+		return;
+
 	/* Only enable interrupts if they were on before the fault */
-	if ((regs->sr & SR_IMASK) != SR_IMASK) {
-		trace_hardirqs_on();
+	if ((regs->sr & SR_IMASK) != SR_IMASK)
 		local_irq_enable();
-	}
 
-	mm = tsk->mm;
+	perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
 
 	/*
 	 * If we're in an interrupt or have no user
@@ -133,7 +152,7 @@
 	 * the fault.
 	 */
 survive:
-	fault = handle_mm_fault(mm, vma, address, writeaccess);
+	fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -141,10 +160,15 @@
 			goto do_sigbus;
 		BUG();
 	}
-	if (fault & VM_FAULT_MAJOR)
+	if (fault & VM_FAULT_MAJOR) {
 		tsk->maj_flt++;
-	else
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+				     regs, address);
+	} else {
 		tsk->min_flt++;
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+				     regs, address);
+	}
 
 	up_read(&mm->mmap_sem);
 	return;
@@ -245,25 +269,6 @@
 		goto no_context;
 }
 
-static inline int notify_page_fault(struct pt_regs *regs, int trap)
-{
-	int ret = 0;
-
-	trace_mark(kernel_arch_trap_entry, "trap_id %d ip #p%ld",
-		   trap >> 5, instruction_pointer(regs));
-
-#ifdef CONFIG_KPROBES
-	if (!user_mode(regs)) {
-		preempt_disable();
-		if (kprobe_running() && kprobe_fault_handler(regs, trap))
-			ret = 1;
-		preempt_enable();
-	}
-#endif
-
-	return ret;
-}
-
 /*
  * Called with interrupts disabled.
  */
@@ -276,12 +281,7 @@
 	pmd_t *pmd;
 	pte_t *pte;
 	pte_t entry;
-	int ret = 0;
-
-	if (notify_page_fault(regs, lookup_exception_vector()))
-		goto out;
-
-	ret = 1;
+	int ret = 1;
 
 	/*
 	 * We don't take page faults for P1, P2, and parts of P4, these
@@ -327,6 +327,5 @@
 
 	ret = 0;
 out:
-	trace_mark(kernel_arch_trap_exit, MARK_NOARGS);
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/init.c linux-libre-2.6.31-gnu/arch/sh/mm/init.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 	}
 
 	set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
-	flush_tlb_one(get_asid(), addr);
+	local_flush_tlb_one(get_asid(), addr);
 }
 
 /*
@@ -177,14 +177,11 @@
 
 	free_area_init_nodes(max_zone_pfns);
 
-#ifdef CONFIG_SUPERH32
 	/* Set up the uncached fixmap */
 	set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start));
-#endif
 }
 
 static struct kcore_list kcore_mem, kcore_vmalloc;
-int after_bootmem = 0;
 
 void __init mem_init(void)
 {
@@ -217,8 +214,6 @@
 	memset(empty_zero_page, 0, PAGE_SIZE);
 	__flush_wback_region(empty_zero_page, PAGE_SIZE);
 
-	after_bootmem = 1;
-
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/ioremap_32.c linux-libre-2.6.31-gnu/arch/sh/mm/ioremap_32.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/ioremap_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/ioremap_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,17 +46,15 @@
 		return NULL;
 
 	/*
-	 * If we're on an SH7751 or SH7780 PCI controller, PCI memory is
-	 * mapped at the end of the address space (typically 0xfd000000)
-	 * in a non-translatable area, so mapping through page tables for
-	 * this area is not only pointless, but also fundamentally
-	 * broken. Just return the physical address instead.
+	 * If we're in the fixed PCI memory range, mapping through page
+	 * tables is not only pointless, but also fundamentally broken.
+	 * Just return the physical address instead.
 	 *
 	 * For boards that map a small PCI memory aperture somewhere in
 	 * P1/P2 space, ioremap() will already do the right thing,
 	 * and we'll never get this far.
 	 */
-	if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr))
+	if (is_pci_memory_fixed_range(phys_addr, size))
 		return (void __iomem *)phys_addr;
 
 #if !defined(CONFIG_PMB_FIXED)
@@ -121,7 +119,9 @@
 	unsigned long seg = PXSEG(vaddr);
 	struct vm_struct *p;
 
-	if (seg < P3SEG || vaddr >= P3_ADDR_MAX || is_pci_memaddr(vaddr))
+	if (seg < P3SEG || vaddr >= P3_ADDR_MAX)
+		return;
+	if (is_pci_memory_fixed_range(vaddr, 0))
 		return;
 
 #ifdef CONFIG_PMB
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/ioremap_64.c linux-libre-2.6.31-gnu/arch/sh/mm/ioremap_64.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/ioremap_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/ioremap_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/bootmem.h>
 #include <linux/proc_fs.h>
+#include <linux/slab.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/addrspace.h>
@@ -27,88 +28,17 @@
 #include <asm/tlbflush.h>
 #include <asm/mmu.h>
 
-static void shmedia_mapioaddr(unsigned long, unsigned long);
-static unsigned long shmedia_ioremap(struct resource *, u32, int);
-
-/*
- * Generic mapping function (not visible outside):
- */
-
-/*
- * Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
- *
- * NOTE! We need to allow non-page-aligned mappings too: we will obviously
- * have to convert them into an offset in a page-aligned mapping, but the
- * caller shouldn't need to know that small detail.
- */
-void *__ioremap(unsigned long phys_addr, unsigned long size,
-		unsigned long flags)
-{
-	void * addr;
-	struct vm_struct * area;
-	unsigned long offset, last_addr;
-	pgprot_t pgprot;
-
-	/* Don't allow wraparound or zero size */
-	last_addr = phys_addr + size - 1;
-	if (!size || last_addr < phys_addr)
-		return NULL;
-
-	pgprot = __pgprot(_PAGE_PRESENT  | _PAGE_READ   |
-			  _PAGE_WRITE    | _PAGE_DIRTY  |
-			  _PAGE_ACCESSED | _PAGE_SHARED | flags);
-
-	/*
-	 * Mappings have to be page-aligned
-	 */
-	offset = phys_addr & ~PAGE_MASK;
-	phys_addr &= PAGE_MASK;
-	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
-	/*
-	 * Ok, go for it..
-	 */
-	area = get_vm_area(size, VM_IOREMAP);
-	if (!area)
-		return NULL;
-	pr_debug("Get vm_area returns %p addr %p\n", area, area->addr);
-	area->phys_addr = phys_addr;
-	addr = area->addr;
-	if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
-			       phys_addr, pgprot)) {
-		vunmap(addr);
-		return NULL;
-	}
-	return (void *) (offset + (char *)addr);
-}
-EXPORT_SYMBOL(__ioremap);
-
-void __iounmap(void *addr)
-{
-	struct vm_struct *area;
-
-	vfree((void *) (PAGE_MASK & (unsigned long) addr));
-	area = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr));
-	if (!area) {
-		printk(KERN_ERR "iounmap: bad address %p\n", addr);
-		return;
-	}
-
-	kfree(area);
-}
-EXPORT_SYMBOL(__iounmap);
-
 static struct resource shmedia_iomap = {
 	.name	= "shmedia_iomap",
 	.start	= IOBASE_VADDR + PAGE_SIZE,
 	.end	= IOBASE_END - 1,
 };
 
-static void shmedia_mapioaddr(unsigned long pa, unsigned long va);
+static void shmedia_mapioaddr(unsigned long pa, unsigned long va,
+			      unsigned long flags);
 static void shmedia_unmapioaddr(unsigned long vaddr);
-static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz);
+static void __iomem *shmedia_ioremap(struct resource *res, u32 pa,
+				     int sz, unsigned long flags);
 
 /*
  * We have the same problem as the SPARC, so lets have the same comment:
@@ -130,18 +60,18 @@
 
 static struct xresource *xres_alloc(void)
 {
-        struct xresource *xrp;
-        int n;
+	struct xresource *xrp;
+	int n;
 
-        xrp = xresv;
-        for (n = 0; n < XNRES; n++) {
-                if (xrp->xflag == 0) {
-                        xrp->xflag = 1;
-                        return xrp;
-                }
-                xrp++;
-        }
-        return NULL;
+	xrp = xresv;
+	for (n = 0; n < XNRES; n++) {
+		if (xrp->xflag == 0) {
+			xrp->xflag = 1;
+			return xrp;
+		}
+		xrp++;
+	}
+	return NULL;
 }
 
 static void xres_free(struct xresource *xrp)
@@ -161,76 +91,71 @@
 	return NULL;
 }
 
-static unsigned long shmedia_alloc_io(unsigned long phys, unsigned long size,
-				      const char *name)
+static void __iomem *shmedia_alloc_io(unsigned long phys, unsigned long size,
+				      const char *name, unsigned long flags)
 {
-        static int printed_full = 0;
-        struct xresource *xres;
-        struct resource *res;
-        char *tack;
-        int tlen;
+	static int printed_full;
+	struct xresource *xres;
+	struct resource *res;
+	char *tack;
+	int tlen;
 
-        if (name == NULL) name = "???";
+	if (name == NULL)
+		name = "???";
 
-        if ((xres = xres_alloc()) != 0) {
-                tack = xres->xname;
-                res = &xres->xres;
-        } else {
-                if (!printed_full) {
-                        printk("%s: done with statics, switching to kmalloc\n",
-			       __func__);
-                        printed_full = 1;
-                }
-                tlen = strlen(name);
-                tack = kmalloc(sizeof (struct resource) + tlen + 1, GFP_KERNEL);
-                if (!tack)
-			return -ENOMEM;
-                memset(tack, 0, sizeof(struct resource));
-                res = (struct resource *) tack;
-                tack += sizeof (struct resource);
-        }
+	xres = xres_alloc();
+	if (xres != 0) {
+		tack = xres->xname;
+		res = &xres->xres;
+	} else {
+		if (!printed_full) {
+			printk(KERN_NOTICE "%s: done with statics, "
+			       "switching to kmalloc\n", __func__);
+			printed_full = 1;
+		}
+		tlen = strlen(name);
+		tack = kmalloc(sizeof(struct resource) + tlen + 1, GFP_KERNEL);
+		if (!tack)
+			return NULL;
+		memset(tack, 0, sizeof(struct resource));
+		res = (struct resource *) tack;
+		tack += sizeof(struct resource);
+	}
 
-        strncpy(tack, name, XNMLN);
-        tack[XNMLN] = 0;
-        res->name = tack;
+	strncpy(tack, name, XNMLN);
+	tack[XNMLN] = 0;
+	res->name = tack;
 
-        return shmedia_ioremap(res, phys, size);
+	return shmedia_ioremap(res, phys, size, flags);
 }
 
-static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz)
+static void __iomem *shmedia_ioremap(struct resource *res, u32 pa, int sz,
+				     unsigned long flags)
 {
-        unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK);
+	unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK);
 	unsigned long round_sz = (offset + sz + PAGE_SIZE-1) & PAGE_MASK;
-        unsigned long va;
-        unsigned int psz;
+	unsigned long va;
+	unsigned int psz;
 
-        if (allocate_resource(&shmedia_iomap, res, round_sz,
+	if (allocate_resource(&shmedia_iomap, res, round_sz,
 			      shmedia_iomap.start, shmedia_iomap.end,
 			      PAGE_SIZE, NULL, NULL) != 0) {
-                panic("alloc_io_res(%s): cannot occupy\n",
-                    (res->name != NULL)? res->name: "???");
-        }
+		panic("alloc_io_res(%s): cannot occupy\n",
+		      (res->name != NULL) ? res->name : "???");
+	}
 
-        va = res->start;
-        pa &= PAGE_MASK;
+	va = res->start;
+	pa &= PAGE_MASK;
 
 	psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
 
-	/* log at boot time ... */
-	printk("mapioaddr: %6s  [%2d page%s]  va 0x%08lx   pa 0x%08x\n",
-	       ((res->name != NULL) ? res->name : "???"),
-	       psz, psz == 1 ? " " : "s", va, pa);
-
-        for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) {
-                shmedia_mapioaddr(pa, va);
-                va += PAGE_SIZE;
-                pa += PAGE_SIZE;
-        }
-
-        res->start += offset;
-        res->end = res->start + sz - 1;         /* not strictly necessary.. */
+	for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) {
+		shmedia_mapioaddr(pa, va, flags);
+		va += PAGE_SIZE;
+		pa += PAGE_SIZE;
+	}
 
-        return res->start;
+	return (void __iomem *)(unsigned long)(res->start + offset);
 }
 
 static void shmedia_free_io(struct resource *res)
@@ -249,14 +174,12 @@
 
 static __init_refok void *sh64_get_page(void)
 {
-	extern int after_bootmem;
 	void *page;
 
-	if (after_bootmem) {
-		page = (void *)get_zeroed_page(GFP_ATOMIC);
-	} else {
+	if (slab_is_available())
+		page = (void *)get_zeroed_page(GFP_KERNEL);
+	else
 		page = alloc_bootmem_pages(PAGE_SIZE);
-	}
 
 	if (!page || ((unsigned long)page & ~PAGE_MASK))
 		panic("sh64_get_page: Out of memory already?\n");
@@ -264,17 +187,20 @@
 	return page;
 }
 
-static void shmedia_mapioaddr(unsigned long pa, unsigned long va)
+static void shmedia_mapioaddr(unsigned long pa, unsigned long va,
+			      unsigned long flags)
 {
 	pgd_t *pgdp;
 	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep, pte;
 	pgprot_t prot;
-	unsigned long flags = 1; /* 1 = CB0-1 device */
 
 	pr_debug("shmedia_mapiopage pa %08lx va %08lx\n",  pa, va);
 
+	if (!flags)
+		flags = 1; /* 1 = CB0-1 device */
+
 	pgdp = pgd_offset_k(va);
 	if (pgd_none(*pgdp) || !pgd_present(*pgdp)) {
 		pudp = (pud_t *)sh64_get_page();
@@ -288,7 +214,7 @@
 	}
 
 	pmdp = pmd_offset(pudp, va);
-	if (pmd_none(*pmdp) || !pmd_present(*pmdp) ) {
+	if (pmd_none(*pmdp) || !pmd_present(*pmdp)) {
 		ptep = (pte_t *)sh64_get_page();
 		set_pmd(pmdp, __pmd((unsigned long)ptep + _PAGE_TABLE));
 	}
@@ -336,17 +262,19 @@
 	pte_clear(&init_mm, vaddr, ptep);
 }
 
-unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *name)
+void __iomem *__ioremap(unsigned long offset, unsigned long size,
+			unsigned long flags)
 {
-	if (size < PAGE_SIZE)
-		size = PAGE_SIZE;
+	char name[14];
 
-	return shmedia_alloc_io(phys, size, name);
+	sprintf(name, "phys_%08x", (u32)offset);
+	return shmedia_alloc_io(offset, size, name, flags);
 }
-EXPORT_SYMBOL(onchip_remap);
+EXPORT_SYMBOL(__ioremap);
 
-void onchip_unmap(unsigned long vaddr)
+void __iounmap(void __iomem *virtual)
 {
+	unsigned long vaddr = (unsigned long)virtual & PAGE_MASK;
 	struct resource *res;
 	unsigned int psz;
 
@@ -357,10 +285,7 @@
 		return;
 	}
 
-        psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
-
-        printk(KERN_DEBUG "unmapioaddr: %6s  [%2d page%s] freed\n",
-	       res->name, psz, psz == 1 ? " " : "s");
+	psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE;
 
 	shmedia_free_io(res);
 
@@ -371,9 +296,8 @@
 		kfree(res);
 	}
 }
-EXPORT_SYMBOL(onchip_unmap);
+EXPORT_SYMBOL(__iounmap);
 
-#ifdef CONFIG_PROC_FS
 static int
 ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof,
 		  void *data)
@@ -385,7 +309,10 @@
 	for (r = ((struct resource *)data)->child; r != NULL; r = r->sibling) {
 		if (p + 32 >= e)        /* Better than nothing */
 			break;
-		if ((nm = r->name) == 0) nm = "???";
+		nm = r->name;
+		if (nm == NULL)
+			nm = "???";
+
 		p += sprintf(p, "%08lx-%08lx: %s\n",
 			     (unsigned long)r->start,
 			     (unsigned long)r->end, nm);
@@ -393,14 +320,11 @@
 
 	return p-buf;
 }
-#endif /* CONFIG_PROC_FS */
 
 static int __init register_proc_onchip(void)
 {
-#ifdef CONFIG_PROC_FS
-	create_proc_read_entry("io_map",0,0, ioremap_proc_info, &shmedia_iomap);
-#endif
+	create_proc_read_entry("io_map", 0, 0, ioremap_proc_info,
+			       &shmedia_iomap);
 	return 0;
 }
-
-__initcall(register_proc_onchip);
+late_initcall(register_proc_onchip);
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/Kconfig linux-libre-2.6.31-gnu/arch/sh/mm/Kconfig
--- linux-libre-2.6.30-gnu/arch/sh/mm/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,29 @@
 	default "0x20000000" if MMU && SUPERH64
 	default "0x00000000"
 
+config FORCE_MAX_ZONEORDER
+	int "Maximum zone order"
+	range 9 64 if PAGE_SIZE_16KB
+	default "9" if PAGE_SIZE_16KB
+	range 7 64 if PAGE_SIZE_64KB
+	default "7" if PAGE_SIZE_64KB
+	range 11 64
+	default "14" if !MMU
+	default "11"
+	help
+	  The kernel memory allocator divides physically contiguous memory
+	  blocks into "zones", where each zone is a power of two number of
+	  pages.  This option selects the largest power of two that the kernel
+	  keeps in the memory allocator.  If you need to allocate very large
+	  blocks of physically contiguous memory, then you may need to
+	  increase this value.
+
+	  This config option is actually maximum order plus one. For example,
+	  a value of 11 means that the largest free memory block is 2^10 pages.
+
+	  The page size is not necessarily 4KB. Keep this in mind when
+	  choosing a value for this option.
+
 config MEMORY_START
 	hex "Physical memory start address"
 	default "0x08000000"
@@ -201,14 +224,6 @@
 
 endchoice
 
-config ENTRY_OFFSET
-	hex
-	default "0x00001000" if PAGE_SIZE_4KB
-	default "0x00002000" if PAGE_SIZE_8KB
-	default "0x00004000" if PAGE_SIZE_16KB
-	default "0x00010000" if PAGE_SIZE_64KB
-	default "0x00000000"
-
 choice
 	prompt "HugeTLB page size"
 	depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/mmap.c linux-libre-2.6.31-gnu/arch/sh/mm/mmap.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/mmap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/mmap.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * arch/sh/mm/mmap.c
  *
- * Copyright (C) 2008  Paul Mundt
+ * Copyright (C) 2008 - 2009  Paul Mundt
  *
  * 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
@@ -21,9 +21,26 @@
 /*
  * To avoid cache aliases, we map the shared page with same color.
  */
-#define COLOUR_ALIGN(addr, pgoff)				\
-	((((addr) + shm_align_mask) & ~shm_align_mask) +	\
-	 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
+static inline unsigned long COLOUR_ALIGN(unsigned long addr,
+					 unsigned long pgoff)
+{
+	unsigned long base = (addr + shm_align_mask) & ~shm_align_mask;
+	unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
+
+	return base + off;
+}
+
+static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
+					      unsigned long pgoff)
+{
+	unsigned long base = addr & ~shm_align_mask;
+	unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;
+
+	if (base + off <= addr)
+		return base + off;
+
+	return base - off;
+}
 
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	unsigned long len, unsigned long pgoff, unsigned long flags)
@@ -103,6 +120,117 @@
 			addr = COLOUR_ALIGN(addr, pgoff);
 	}
 }
+
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+			  const unsigned long len, const unsigned long pgoff,
+			  const unsigned long flags)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long addr = addr0;
+	int do_colour_align;
+
+	if (flags & MAP_FIXED) {
+		/* We do not accept a shared mapping if it would violate
+		 * cache aliasing constraints.
+		 */
+		if ((flags & MAP_SHARED) &&
+		    ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
+			return -EINVAL;
+		return addr;
+	}
+
+	if (unlikely(len > TASK_SIZE))
+		return -ENOMEM;
+
+	do_colour_align = 0;
+	if (filp || (flags & MAP_SHARED))
+		do_colour_align = 1;
+
+	/* requesting a specific address */
+	if (addr) {
+		if (do_colour_align)
+			addr = COLOUR_ALIGN(addr, pgoff);
+		else
+			addr = PAGE_ALIGN(addr);
+
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+	/* check if free_area_cache is useful for us */
+	if (len <= mm->cached_hole_size) {
+	        mm->cached_hole_size = 0;
+		mm->free_area_cache = mm->mmap_base;
+	}
+
+	/* either no address requested or can't fit in requested address hole */
+	addr = mm->free_area_cache;
+	if (do_colour_align) {
+		unsigned long base = COLOUR_ALIGN_DOWN(addr-len, pgoff);
+
+		addr = base + len;
+	}
+
+	/* make sure it can fit in the remaining address space */
+	if (likely(addr > len)) {
+		vma = find_vma(mm, addr-len);
+		if (!vma || addr <= vma->vm_start) {
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr-len);
+		}
+	}
+
+	if (unlikely(mm->mmap_base < len))
+		goto bottomup;
+
+	addr = mm->mmap_base-len;
+	if (do_colour_align)
+		addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+
+	do {
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * else if new region fits below vma->vm_start,
+		 * return with success:
+		 */
+		vma = find_vma(mm, addr);
+		if (likely(!vma || addr+len <= vma->vm_start)) {
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+		}
+
+		/* remember the largest hole we saw so far */
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
+
+		/* try just below the current vma->vm_start */
+		addr = vma->vm_start-len;
+		if (do_colour_align)
+			addr = COLOUR_ALIGN_DOWN(addr, pgoff);
+	} while (likely(len < vma->vm_start));
+
+bottomup:
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->cached_hole_size = ~0UL;
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = mm->mmap_base;
+	mm->cached_hole_size = ~0UL;
+
+	return addr;
+}
 #endif /* CONFIG_MMU */
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/tlbflush_64.c linux-libre-2.6.31-gnu/arch/sh/mm/tlbflush_64.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/tlbflush_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/tlbflush_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Richard Curnow (/proc/tlb, bug fixes)
- * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2003 - 2009 Paul Mundt
  *
  * 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
@@ -20,6 +20,7 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/perf_counter.h>
 #include <linux/interrupt.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -115,6 +116,8 @@
 	/* Not an IO address, so reenable interrupts */
 	local_irq_enable();
 
+	perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
@@ -187,7 +190,7 @@
 	 * the fault.
 	 */
 survive:
-	fault = handle_mm_fault(mm, vma, address, writeaccess);
+	fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -195,10 +198,16 @@
 			goto do_sigbus;
 		BUG();
 	}
-	if (fault & VM_FAULT_MAJOR)
+
+	if (fault & VM_FAULT_MAJOR) {
 		tsk->maj_flt++;
-	else
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+				     regs, address);
+	} else {
 		tsk->min_flt++;
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+				     regs, address);
+	}
 
 	/* If we get here, the page fault has been handled.  Do the TLB refill
 	   now from the newly-setup PTE, to avoid having to fault again right
diff -druN linux-libre-2.6.30-gnu/arch/sh/mm/tlb-sh3.c linux-libre-2.6.31-gnu/arch/sh/mm/tlb-sh3.c
--- linux-libre-2.6.30-gnu/arch/sh/mm/tlb-sh3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/mm/tlb-sh3.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
 #include <asm/system.h>
diff -druN linux-libre-2.6.30-gnu/arch/sh/oprofile/common.c linux-libre-2.6.31-gnu/arch/sh/oprofile/common.c
--- linux-libre-2.6.30-gnu/arch/sh/oprofile/common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/oprofile/common.c	2009-09-09 18:13:59.000000000 -0400
@@ -109,6 +109,7 @@
 	case CPU_SH7785:
 	case CPU_SH7786:
 	case CPU_SH7723:
+	case CPU_SH7724:
 	case CPU_SHX3:
 		lmodel = &op_model_sh4a_ops;
 		break;
diff -druN linux-libre-2.6.30-gnu/arch/sh/tools/mach-types linux-libre-2.6.31-gnu/arch/sh/tools/mach-types
--- linux-libre-2.6.30-gnu/arch/sh/tools/mach-types	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sh/tools/mach-types	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,7 @@
 7619SE			SH_7619_SOLUTION_ENGINE
 7721SE			SH_7721_SOLUTION_ENGINE
 7722SE			SH_7722_SOLUTION_ENGINE
+7724SE			SH_7724_SOLUTION_ENGINE
 7751SE			SH_7751_SOLUTION_ENGINE
 7780SE			SH_7780_SOLUTION_ENGINE
 7751SYSTEMH		SH_7751_SYSTEMH
diff -druN linux-libre-2.6.30-gnu/arch/sparc/boot/Makefile linux-libre-2.6.31-gnu/arch/sparc/boot/Makefile
--- linux-libre-2.6.30-gnu/arch/sparc/boot/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/boot/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -15,7 +15,7 @@
 
 ifeq ($(CONFIG_SPARC32),y)
 quiet_cmd_piggy		= PIGGY   $@
-      cmd_piggy		= $(obj)/piggyback_32 $@ $(obj)/System.map $(ROOT_IMG)
+      cmd_piggy		= $(obj)/piggyback_32 $@ System.map $(ROOT_IMG)
 quiet_cmd_btfix		= BTFIX   $@
       cmd_btfix		= $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
 quiet_cmd_sysmap        = SYSMAP  $(obj)/System.map
@@ -58,7 +58,7 @@
 $(obj)/zImage: $(obj)/image
 	$(call if_changed,strip)
 
-$(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE
+$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE
 	$(call if_changed,elftoaout)
 	$(call if_changed,piggy)
 
@@ -79,7 +79,7 @@
 	$(call if_changed,strip)
 	@echo '  kernel: $@ is ready'
 
-$(obj)/tftpboot.img: vmlinux $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE
+$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE
 	$(call if_changed,elftoaout)
 	$(call if_changed,piggy)
 	@echo '  kernel: $@ is ready'
diff -druN linux-libre-2.6.30-gnu/arch/sparc/boot/piggyback_32.c linux-libre-2.6.31-gnu/arch/sparc/boot/piggyback_32.c
--- linux-libre-2.6.30-gnu/arch/sparc/boot/piggyback_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/boot/piggyback_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 int main(int argc,char **argv)
 {
 	static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
-	unsigned char buffer[1024], *q, *r;
+	char buffer[1024], *q, *r;
 	unsigned int i, j, k, start, end, offset;
 	FILE *map;
 	struct stat s;
@@ -84,7 +84,7 @@
 	while (fgets (buffer, 1024, map)) {
 		if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n"))
 			start = strtoul (buffer, NULL, 16);
-		else if (!strcmp (buffer + 8, " A end\n") || !strcmp (buffer + 16, " A end\n"))
+		else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n"))
 			end = strtoul (buffer, NULL, 16);
 	}
 	fclose (map);
diff -druN linux-libre-2.6.30-gnu/arch/sparc/boot/piggyback_64.c linux-libre-2.6.31-gnu/arch/sparc/boot/piggyback_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/boot/piggyback_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/boot/piggyback_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,7 @@
 	struct stat s;
 	int image, tail;
 	
+	start = end = 0;
 	if (stat (argv[3], &s) < 0) die (argv[3]);
 	map = fopen (argv[2], "r");
 	if (!map) die(argv[2]);
diff -druN linux-libre-2.6.30-gnu/arch/sparc/configs/sparc32_defconfig linux-libre-2.6.31-gnu/arch/sparc/configs/sparc32_defconfig
--- linux-libre-2.6.30-gnu/arch/sparc/configs/sparc32_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/configs/sparc32_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Fri Apr 17 04:04:46 2009
+# Linux kernel version: 2.6.31-rc1
+# Tue Aug 18 23:45:52 2009
 #
 # CONFIG_64BIT is not set
 CONFIG_SPARC=y
@@ -17,6 +17,7 @@
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_OF=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -74,7 +75,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -87,8 +87,13 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -97,6 +102,10 @@
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -109,7 +118,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -154,9 +163,9 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_SUN_PM=y
 # CONFIG_SPARC_LED is not set
 CONFIG_SERIAL_CONSOLE=y
@@ -264,6 +273,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -281,7 +291,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -335,6 +349,7 @@
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -358,10 +373,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -379,6 +390,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -387,6 +399,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -401,7 +414,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -426,13 +438,16 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -463,6 +478,7 @@
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -482,6 +498,7 @@
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -629,6 +646,11 @@
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -668,22 +690,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -776,6 +783,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -799,10 +810,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -985,6 +998,7 @@
 CONFIG_KGDB_SERIAL_CONSOLE=y
 CONFIG_KGDB_TESTS=y
 # CONFIG_KGDB_TESTS_ON_BOOT is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_STACK_DEBUG is not set
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/configs/sparc64_defconfig linux-libre-2.6.31-gnu/arch/sparc/configs/sparc64_defconfig
--- linux-libre-2.6.30-gnu/arch/sparc/configs/sparc64_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/configs/sparc64_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Fri Apr 17 02:03:07 2009
+# Linux kernel version: 2.6.31-rc1
+# Tue Aug 18 23:56:02 2009
 #
 CONFIG_64BIT=y
 CONFIG_SPARC=y
@@ -19,12 +19,14 @@
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_HAVE_DYNAMIC_PER_CPU_AREA=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_MMU=y
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_OF=y
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -82,7 +84,6 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -95,16 +96,21 @@
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
@@ -114,6 +120,11 @@
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -199,9 +210,9 @@
 CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=1
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=8192
 CONFIG_SCHED_SMT=y
 CONFIG_SCHED_MC=y
 # CONFIG_PREEMPT_NONE is not set
@@ -321,6 +332,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -340,7 +352,11 @@
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -364,6 +380,7 @@
 CONFIG_CONNECTOR=m
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=m
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -398,7 +415,9 @@
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -477,10 +496,6 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -499,6 +514,7 @@
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -507,6 +523,7 @@
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -521,7 +538,6 @@
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -552,6 +568,7 @@
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
+# CONFIG_DM_LOG_USERSPACE is not set
 CONFIG_DM_ZERO=m
 # CONFIG_DM_MULTIPATH is not set
 # CONFIG_DM_DELAY is not set
@@ -563,13 +580,16 @@
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -635,6 +655,7 @@
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -657,6 +678,7 @@
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
+# CONFIG_CNIC is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -763,6 +785,7 @@
 # CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
@@ -860,6 +883,7 @@
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
 
@@ -888,13 +912,17 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -949,6 +977,7 @@
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -984,23 +1013,9 @@
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1127,6 +1142,11 @@
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+CONFIG_SND_RAWMIDI_SEQ=m
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_MPU401_UART=m
 CONFIG_SND_AC97_CODEC=m
 CONFIG_SND_DRIVERS=y
@@ -1153,6 +1173,7 @@
 # CONFIG_SND_OXYGEN is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1183,6 +1204,7 @@
 # CONFIG_SND_INTEL8X0 is not set
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1229,6 +1251,7 @@
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
 # CONFIG_DRAGONRISE_FF is not set
 CONFIG_HID_EZKEY=y
 CONFIG_HID_KYE=y
@@ -1246,9 +1269,14 @@
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
 # CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SMARTJOYPLUS=y
+# CONFIG_SMARTJOYPLUS_FF is not set
 CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
 # CONFIG_THRUSTMASTER_FF is not set
+CONFIG_HID_ZEROPLUS=y
 # CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1261,7 +1289,6 @@
 #
 # Miscellaneous USB options
 #
-CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
@@ -1273,6 +1300,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1351,7 +1379,6 @@
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
@@ -1397,6 +1424,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1425,6 +1453,10 @@
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1457,11 +1489,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1536,7 +1569,7 @@
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
 CONFIG_SUN_PARTITION=y
-CONFIG_NLS=m
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
@@ -1636,25 +1669,28 @@
 # CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_NOP_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 CONFIG_BLK_DEV_IO_TRACE=y
 # CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/atomic_32.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/atomic_32.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/atomic_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/atomic_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -161,5 +161,5 @@
 
 #endif /* !(__KERNEL__) */
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* !(__ARCH_SPARC_ATOMIC__) */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/atomic_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/atomic_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/atomic_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/atomic_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -114,5 +114,5 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,13 @@
+#ifndef __ASM_ALPHA_BITSPERLONG_H
+#define __ASM_ALPHA_BITSPERLONG_H
+
+#if defined(__sparc__) && defined(__arch64__)
+#define __BITS_PER_LONG 64
+#else
+#define __BITS_PER_LONG 32
+#endif
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_ALPHA_BITSPERLONG_H */
+
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/cpudata_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/cpudata_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/cpudata_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/cpudata_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,9 +6,6 @@
 #ifndef _SPARC64_CPUDATA_H
 #define _SPARC64_CPUDATA_H
 
-#include <asm/hypervisor.h>
-#include <asm/asi.h>
-
 #ifndef __ASSEMBLY__
 
 #include <linux/percpu.h>
@@ -38,202 +35,10 @@
 #define cpu_data(__cpu)		per_cpu(__cpu_data, (__cpu))
 #define local_cpu_data()	__get_cpu_var(__cpu_data)
 
-/* Trap handling code needs to get at a few critical values upon
- * trap entry and to process TSB misses.  These cannot be in the
- * per_cpu() area as we really need to lock them into the TLB and
- * thus make them part of the main kernel image.  As a result we
- * try to make this as small as possible.
- *
- * This is padded out and aligned to 64-bytes to avoid false sharing
- * on SMP.
- */
-
-/* If you modify the size of this structure, please update
- * TRAP_BLOCK_SZ_SHIFT below.
- */
-struct thread_info;
-struct trap_per_cpu {
-/* D-cache line 1: Basic thread information, cpu and device mondo queues */
-	struct thread_info	*thread;
-	unsigned long		pgd_paddr;
-	unsigned long		cpu_mondo_pa;
-	unsigned long		dev_mondo_pa;
-
-/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
-	unsigned long		resum_mondo_pa;
-	unsigned long		resum_kernel_buf_pa;
-	unsigned long		nonresum_mondo_pa;
-	unsigned long		nonresum_kernel_buf_pa;
-
-/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
-	struct hv_fault_status	fault_info;
-
-/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list.  */
-	unsigned long		cpu_mondo_block_pa;
-	unsigned long		cpu_list_pa;
-	unsigned long		tsb_huge;
-	unsigned long		tsb_huge_temp;
-
-/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size.  */
-	unsigned long		irq_worklist_pa;
-	unsigned int		cpu_mondo_qmask;
-	unsigned int		dev_mondo_qmask;
-	unsigned int		resum_qmask;
-	unsigned int		nonresum_qmask;
-	void			*hdesc;
-} __attribute__((aligned(64)));
-extern struct trap_per_cpu trap_block[NR_CPUS];
-extern void init_cur_cpu_trap(struct thread_info *);
-extern void setup_tba(void);
-extern int ncpus_probed;
 extern const struct seq_operations cpuinfo_op;
 
-extern unsigned long real_hard_smp_processor_id(void);
-
-struct cpuid_patch_entry {
-	unsigned int	addr;
-	unsigned int	cheetah_safari[4];
-	unsigned int	cheetah_jbus[4];
-	unsigned int	starfire[4];
-	unsigned int	sun4v[4];
-};
-extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
-
-struct sun4v_1insn_patch_entry {
-	unsigned int	addr;
-	unsigned int	insn;
-};
-extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
-	__sun4v_1insn_patch_end;
-
-struct sun4v_2insn_patch_entry {
-	unsigned int	addr;
-	unsigned int	insns[2];
-};
-extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
-	__sun4v_2insn_patch_end;
-
 #endif /* !(__ASSEMBLY__) */
 
-#define TRAP_PER_CPU_THREAD		0x00
-#define TRAP_PER_CPU_PGD_PADDR		0x08
-#define TRAP_PER_CPU_CPU_MONDO_PA	0x10
-#define TRAP_PER_CPU_DEV_MONDO_PA	0x18
-#define TRAP_PER_CPU_RESUM_MONDO_PA	0x20
-#define TRAP_PER_CPU_RESUM_KBUF_PA	0x28
-#define TRAP_PER_CPU_NONRESUM_MONDO_PA	0x30
-#define TRAP_PER_CPU_NONRESUM_KBUF_PA	0x38
-#define TRAP_PER_CPU_FAULT_INFO		0x40
-#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA	0xc0
-#define TRAP_PER_CPU_CPU_LIST_PA	0xc8
-#define TRAP_PER_CPU_TSB_HUGE		0xd0
-#define TRAP_PER_CPU_TSB_HUGE_TEMP	0xd8
-#define TRAP_PER_CPU_IRQ_WORKLIST_PA	0xe0
-#define TRAP_PER_CPU_CPU_MONDO_QMASK	0xe8
-#define TRAP_PER_CPU_DEV_MONDO_QMASK	0xec
-#define TRAP_PER_CPU_RESUM_QMASK	0xf0
-#define TRAP_PER_CPU_NONRESUM_QMASK	0xf4
-
-#define TRAP_BLOCK_SZ_SHIFT		8
-
-#include <asm/scratchpad.h>
-
-#define __GET_CPUID(REG)				\
-	/* Spitfire implementation (default). */	\
-661:	ldxa		[%g0] ASI_UPA_CONFIG, REG;	\
-	srlx		REG, 17, REG;			\
-	 and		REG, 0x1f, REG;			\
-	nop;						\
-	.section	.cpuid_patch, "ax";		\
-	/* Instruction location. */			\
-	.word		661b;				\
-	/* Cheetah Safari implementation. */		\
-	ldxa		[%g0] ASI_SAFARI_CONFIG, REG;	\
-	srlx		REG, 17, REG;			\
-	and		REG, 0x3ff, REG;		\
-	nop;						\
-	/* Cheetah JBUS implementation. */		\
-	ldxa		[%g0] ASI_JBUS_CONFIG, REG;	\
-	srlx		REG, 17, REG;			\
-	and		REG, 0x1f, REG;			\
-	nop;						\
-	/* Starfire implementation. */			\
-	sethi		%hi(0x1fff40000d0 >> 9), REG;	\
-	sllx		REG, 9, REG;			\
-	or		REG, 0xd0, REG;			\
-	lduwa		[REG] ASI_PHYS_BYPASS_EC_E, REG;\
-	/* sun4v implementation. */			\
-	mov		SCRATCHPAD_CPUID, REG;		\
-	ldxa		[REG] ASI_SCRATCHPAD, REG;	\
-	nop;						\
-	nop;						\
-	.previous;
-
-#ifdef CONFIG_SMP
-
-#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	__GET_CPUID(TMP)			\
-	sethi	%hi(trap_block), DEST;		\
-	sllx	TMP, TRAP_BLOCK_SZ_SHIFT, TMP;	\
-	or	DEST, %lo(trap_block), DEST;	\
-	add	DEST, TMP, DEST;		\
-
-/* Clobbers TMP, current address space PGD phys address into DEST.  */
-#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
-
-/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
-#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
-
-/* Clobbers TMP, loads DEST with current thread info pointer.  */
-#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
-
-/* Given the current thread info pointer in THR, load the per-cpu
- * area base of the current processor into DEST.  REG1, REG2, and REG3 are
- * clobbered.
- *
- * You absolutely cannot use DEST as a temporary in this code.  The
- * reason is that traps can happen during execution, and return from
- * trap will load the fully resolved DEST per-cpu base.  This can corrupt
- * the calculations done by the macro mid-stream.
- */
-#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)	\
-	lduh	[THR + TI_CPU], REG1;			\
-	sethi	%hi(__per_cpu_shift), REG3;		\
-	sethi	%hi(__per_cpu_base), REG2;		\
-	ldx	[REG3 + %lo(__per_cpu_shift)], REG3;	\
-	ldx	[REG2 + %lo(__per_cpu_base)], REG2;	\
-	sllx	REG1, REG3, REG3;			\
-	add	REG3, REG2, DEST;
-
-#else
-
-#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	sethi	%hi(trap_block), DEST;		\
-	or	DEST, %lo(trap_block), DEST;	\
-
-/* Uniprocessor versions, we know the cpuid is zero.  */
-#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
-
-/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
-#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
-
-#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
-
-/* No per-cpu areas on uniprocessor, so no need to load DEST.  */
-#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
-
-#endif /* !(CONFIG_SMP) */
+#include <asm/trap_block.h>
 
 #endif /* _SPARC64_CPUDATA_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/dma-mapping_32.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/dma-mapping_32.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/dma-mapping_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/dma-mapping_32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-#ifndef _ASM_SPARC_DMA_MAPPING_H
-#define _ASM_SPARC_DMA_MAPPING_H
-
-#include <linux/types.h>
-
-struct device;
-struct scatterlist;
-struct page;
-
-#define DMA_ERROR_CODE	(~(dma_addr_t)0x0)
-
-extern int dma_supported(struct device *dev, u64 mask);
-extern int dma_set_mask(struct device *dev, u64 dma_mask);
-extern void *dma_alloc_coherent(struct device *dev, size_t size,
-				dma_addr_t *dma_handle, gfp_t flag);
-extern void dma_free_coherent(struct device *dev, size_t size,
-			      void *cpu_addr, dma_addr_t dma_handle);
-extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-				 size_t size,
-				 enum dma_data_direction direction);
-extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-			     size_t size,
-			     enum dma_data_direction direction);
-extern dma_addr_t dma_map_page(struct device *dev, struct page *page,
-			       unsigned long offset, size_t size,
-			       enum dma_data_direction direction);
-extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-			   size_t size, enum dma_data_direction direction);
-extern int dma_map_sg(struct device *dev, struct scatterlist *sg,
-		      int nents, enum dma_data_direction direction);
-extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-			 int nents, enum dma_data_direction direction);
-extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-				    size_t size,
-				    enum dma_data_direction direction);
-extern void dma_sync_single_for_device(struct device *dev,
-				       dma_addr_t dma_handle,
-				       size_t size,
-				       enum dma_data_direction direction);
-extern void dma_sync_single_range_for_cpu(struct device *dev,
-					  dma_addr_t dma_handle,
-					  unsigned long offset,
-					  size_t size,
-					  enum dma_data_direction direction);
-extern void dma_sync_single_range_for_device(struct device *dev,
-					     dma_addr_t dma_handle,
-					     unsigned long offset, size_t size,
-					     enum dma_data_direction direction);
-extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
-				int nelems, enum dma_data_direction direction);
-extern void dma_sync_sg_for_device(struct device *dev,
-				   struct scatterlist *sg, int nelems,
-				   enum dma_data_direction direction);
-extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
-extern int dma_get_cache_alignment(void);
-
-#define dma_alloc_noncoherent	dma_alloc_coherent
-#define dma_free_noncoherent	dma_free_coherent
-
-#endif /* _ASM_SPARC_DMA_MAPPING_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/dma-mapping_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/dma-mapping_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/dma-mapping_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/dma-mapping_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-#ifndef _ASM_SPARC64_DMA_MAPPING_H
-#define _ASM_SPARC64_DMA_MAPPING_H
-
-#include <linux/scatterlist.h>
-#include <linux/mm.h>
-
-#define DMA_ERROR_CODE	(~(dma_addr_t)0x0)
-
-struct dma_ops {
-	void *(*alloc_coherent)(struct device *dev, size_t size,
-				dma_addr_t *dma_handle, gfp_t flag);
-	void (*free_coherent)(struct device *dev, size_t size,
-			      void *cpu_addr, dma_addr_t dma_handle);
-	dma_addr_t (*map_single)(struct device *dev, void *cpu_addr,
-				 size_t size,
-				 enum dma_data_direction direction);
-	void (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
-			     size_t size,
-			     enum dma_data_direction direction);
-	int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
-		      enum dma_data_direction direction);
-	void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
-			 int nhwentries,
-			 enum dma_data_direction direction);
-	void (*sync_single_for_cpu)(struct device *dev,
-				    dma_addr_t dma_handle, size_t size,
-				    enum dma_data_direction direction);
-	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
-				int nelems,
-				enum dma_data_direction direction);
-};
-extern const struct dma_ops *dma_ops;
-
-extern int dma_supported(struct device *dev, u64 mask);
-extern int dma_set_mask(struct device *dev, u64 dma_mask);
-
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-				       dma_addr_t *dma_handle, gfp_t flag)
-{
-	return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
-}
-
-static inline void dma_free_coherent(struct device *dev, size_t size,
-				     void *cpu_addr, dma_addr_t dma_handle)
-{
-	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
-}
-
-static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-					size_t size,
-					enum dma_data_direction direction)
-{
-	return dma_ops->map_single(dev, cpu_addr, size, direction);
-}
-
-static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-				    size_t size,
-				    enum dma_data_direction direction)
-{
-	dma_ops->unmap_single(dev, dma_addr, size, direction);
-}
-
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-				      unsigned long offset, size_t size,
-				      enum dma_data_direction direction)
-{
-	return dma_ops->map_single(dev, page_address(page) + offset,
-				   size, direction);
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-				  size_t size,
-				  enum dma_data_direction direction)
-{
-	dma_ops->unmap_single(dev, dma_address, size, direction);
-}
-
-static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
-			     int nents, enum dma_data_direction direction)
-{
-	return dma_ops->map_sg(dev, sg, nents, direction);
-}
-
-static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-				int nents, enum dma_data_direction direction)
-{
-	dma_ops->unmap_sg(dev, sg, nents, direction);
-}
-
-static inline void dma_sync_single_for_cpu(struct device *dev,
-					   dma_addr_t dma_handle, size_t size,
-					   enum dma_data_direction direction)
-{
-	dma_ops->sync_single_for_cpu(dev, dma_handle, size, direction);
-}
-
-static inline void dma_sync_single_for_device(struct device *dev,
-					      dma_addr_t dma_handle,
-					      size_t size,
-					      enum dma_data_direction direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-static inline void dma_sync_single_range_for_cpu(struct device *dev,
-						 dma_addr_t dma_handle,
-						 unsigned long offset,
-						 size_t size,
-						 enum dma_data_direction direction)
-{
-	dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction);
-}
-
-static inline void dma_sync_single_range_for_device(struct device *dev,
-						    dma_addr_t dma_handle,
-						    unsigned long offset,
-						    size_t size,
-						    enum dma_data_direction direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-
-static inline void dma_sync_sg_for_cpu(struct device *dev,
-				       struct scatterlist *sg, int nelems,
-				       enum dma_data_direction direction)
-{
-	dma_ops->sync_sg_for_cpu(dev, sg, nelems, direction);
-}
-
-static inline void dma_sync_sg_for_device(struct device *dev,
-					  struct scatterlist *sg, int nelems,
-					  enum dma_data_direction direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-	return (dma_addr == DMA_ERROR_CODE);
-}
-
-static inline int dma_get_cache_alignment(void)
-{
-	/* no easy way to get cache size on all processors, so return
-	 * the maximum possible, to be safe */
-	return (1 << INTERNODE_CACHE_SHIFT);
-}
-
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-#define dma_is_consistent(d, h)	(1)
-
-#endif /* _ASM_SPARC64_DMA_MAPPING_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,166 @@
 #ifndef ___ASM_SPARC_DMA_MAPPING_H
 #define ___ASM_SPARC_DMA_MAPPING_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/dma-mapping_64.h>
-#else
-#include <asm/dma-mapping_32.h>
-#endif
+
+#include <linux/scatterlist.h>
+#include <linux/mm.h>
+
+#define DMA_ERROR_CODE	(~(dma_addr_t)0x0)
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d, h)	(1)
+
+struct dma_ops {
+	void *(*alloc_coherent)(struct device *dev, size_t size,
+				dma_addr_t *dma_handle, gfp_t flag);
+	void (*free_coherent)(struct device *dev, size_t size,
+			      void *cpu_addr, dma_addr_t dma_handle);
+	dma_addr_t (*map_page)(struct device *dev, struct page *page,
+			       unsigned long offset, size_t size,
+			       enum dma_data_direction direction);
+	void (*unmap_page)(struct device *dev, dma_addr_t dma_addr,
+			   size_t size,
+			   enum dma_data_direction direction);
+	int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
+		      enum dma_data_direction direction);
+	void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
+			 int nhwentries,
+			 enum dma_data_direction direction);
+	void (*sync_single_for_cpu)(struct device *dev,
+				    dma_addr_t dma_handle, size_t size,
+				    enum dma_data_direction direction);
+	void (*sync_single_for_device)(struct device *dev,
+				       dma_addr_t dma_handle, size_t size,
+				       enum dma_data_direction direction);
+	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
+				int nelems,
+				enum dma_data_direction direction);
+	void (*sync_sg_for_device)(struct device *dev,
+				   struct scatterlist *sg, int nents,
+				   enum dma_data_direction dir);
+};
+extern const struct dma_ops *dma_ops;
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
+					size_t size,
+					enum dma_data_direction direction)
+{
+	return dma_ops->map_page(dev, virt_to_page(cpu_addr),
+				 (unsigned long)cpu_addr & ~PAGE_MASK, size,
+				 direction);
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+				    size_t size,
+				    enum dma_data_direction direction)
+{
+	dma_ops->unmap_page(dev, dma_addr, size, direction);
+}
+
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
+				      unsigned long offset, size_t size,
+				      enum dma_data_direction direction)
+{
+	return dma_ops->map_page(dev, page, offset, size, direction);
+}
+
+static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+				  size_t size,
+				  enum dma_data_direction direction)
+{
+	dma_ops->unmap_page(dev, dma_address, size, direction);
+}
+
+static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
+			     int nents, enum dma_data_direction direction)
+{
+	return dma_ops->map_sg(dev, sg, nents, direction);
+}
+
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction direction)
+{
+	dma_ops->unmap_sg(dev, sg, nents, direction);
+}
+
+static inline void dma_sync_single_for_cpu(struct device *dev,
+					   dma_addr_t dma_handle, size_t size,
+					   enum dma_data_direction direction)
+{
+	dma_ops->sync_single_for_cpu(dev, dma_handle, size, direction);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+					      dma_addr_t dma_handle,
+					      size_t size,
+					      enum dma_data_direction direction)
+{
+	if (dma_ops->sync_single_for_device)
+		dma_ops->sync_single_for_device(dev, dma_handle, size,
+						direction);
+}
+
+static inline void dma_sync_sg_for_cpu(struct device *dev,
+				       struct scatterlist *sg, int nelems,
+				       enum dma_data_direction direction)
+{
+	dma_ops->sync_sg_for_cpu(dev, sg, nelems, direction);
+}
+
+static inline void dma_sync_sg_for_device(struct device *dev,
+					  struct scatterlist *sg, int nelems,
+					  enum dma_data_direction direction)
+{
+	if (dma_ops->sync_sg_for_device)
+		dma_ops->sync_sg_for_device(dev, sg, nelems, direction);
+}
+
+static inline void dma_sync_single_range_for_cpu(struct device *dev,
+						 dma_addr_t dma_handle,
+						 unsigned long offset,
+						 size_t size,
+						 enum dma_data_direction dir)
+{
+	dma_sync_single_for_cpu(dev, dma_handle+offset, size, dir);
+}
+
+static inline void dma_sync_single_range_for_device(struct device *dev,
+						    dma_addr_t dma_handle,
+						    unsigned long offset,
+						    size_t size,
+						    enum dma_data_direction dir)
+{
+	dma_sync_single_for_device(dev, dma_handle+offset, size, dir);
+}
+
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	return (dma_addr == DMA_ERROR_CODE);
+}
+
+static inline int dma_get_cache_alignment(void)
+{
+	/*
+	 * no easy way to get cache size on all processors, so return
+	 * the maximum possible, to be safe
+	 */
+	return (1 << INTERNODE_CACHE_SHIFT);
+}
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/errno.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/errno.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/errno.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/errno.h	2009-09-09 18:13:59.000000000 -0400
@@ -110,4 +110,6 @@
 #define	EOWNERDEAD	132	/* Owner died */
 #define	ENOTRECOVERABLE	133	/* State not recoverable */
 
+#define	ERFKILL		134	/* Operation not possible due to RF-kill */
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/ftrace.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/ftrace.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/ftrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/ftrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,4 +11,15 @@
 
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* reloction of mcount call site is the same as the address */
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+#endif /*  CONFIG_DYNAMIC_FTRACE */
+
 #endif /* _ASM_SPARC64_FTRACE */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,21 +5,6 @@
  * is actually used on sparc.  -DaveM
  */
 
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/mdesc.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/mdesc.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/mdesc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/mdesc.h	2009-09-09 18:13:59.000000000 -0400
@@ -71,7 +71,8 @@
 
 extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
 
-extern void mdesc_fill_in_cpu_data(cpumask_t mask);
+extern void mdesc_fill_in_cpu_data(cpumask_t *mask);
+extern void mdesc_populate_present_mask(cpumask_t *mask);
 
 extern void sun4v_mdesc_init(void);
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/mman.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __SPARC_MMAN_H__
 #define __SPARC_MMAN_H__
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 /* SunOS'ified... */
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/page_32.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/page_32.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/page_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/page_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -152,6 +152,6 @@
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _SPARC_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/page_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/page_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/page_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/page_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -132,6 +132,6 @@
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif /* _SPARC64_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/pci_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/pci_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/pci_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/pci_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -191,8 +191,6 @@
 pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 			struct pci_bus_region *region);
 
-extern struct resource *pcibios_select_root(struct pci_dev *, struct resource *);
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
 	return PCI_IRQ_NONE;
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/percpu_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/percpu_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/percpu_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/percpu_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,20 +7,16 @@
 
 #ifdef CONFIG_SMP
 
-extern void real_setup_per_cpu_areas(void);
+#include <asm/trap_block.h>
 
-extern unsigned long __per_cpu_base;
-extern unsigned long __per_cpu_shift;
 #define __per_cpu_offset(__cpu) \
-	(__per_cpu_base + ((unsigned long)(__cpu) << __per_cpu_shift))
+	(trap_block[(__cpu)].__per_cpu_base)
 #define per_cpu_offset(x) (__per_cpu_offset(x))
 
 #define __my_cpu_offset __local_per_cpu_offset
 
 #else /* ! SMP */
 
-#define real_setup_per_cpu_areas()		do { } while (0)
-
 #endif	/* SMP */
 
 #include <asm-generic/percpu.h>
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/pgalloc_32.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/pgalloc_32.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/pgalloc_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/pgalloc_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -44,8 +44,8 @@
 BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
 #define free_pmd_fast(pmd)	BTFIXUP_CALL(free_pmd_fast)(pmd)
 
-#define pmd_free(mm, pmd)	free_pmd_fast(pmd)
-#define __pmd_free_tlb(tlb, pmd) pmd_free((tlb)->mm, pmd)
+#define pmd_free(mm, pmd)		free_pmd_fast(pmd)
+#define __pmd_free_tlb(tlb, pmd, addr)	pmd_free((tlb)->mm, pmd)
 
 BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *)
 #define pmd_populate(MM, PMD, PTE)        BTFIXUP_CALL(pmd_populate)(PMD, PTE)
@@ -62,7 +62,7 @@
 #define pte_free_kernel(mm, pte)	BTFIXUP_CALL(free_pte_fast)(pte)
 
 BTFIXUPDEF_CALL(void, pte_free, pgtable_t )
-#define pte_free(mm, pte)	BTFIXUP_CALL(pte_free)(pte)
-#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
+#define pte_free(mm, pte)		BTFIXUP_CALL(pte_free)(pte)
+#define __pte_free_tlb(tlb, pte, addr)	pte_free((tlb)->mm, pte)
 
 #endif /* _SPARC_PGALLOC_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/pgtable_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/pgtable_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/pgtable_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/pgtable_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -726,11 +726,17 @@
 extern pte_t pgoff_to_pte(unsigned long);
 #define PTE_FILE_MAX_BITS	(64UL - PAGE_SHIFT - 1UL)
 
-extern unsigned long *sparc64_valid_addr_bitmap;
+extern unsigned long sparc64_valid_addr_bitmap[];
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr)	\
-	(test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
+static inline bool kern_addr_valid(unsigned long addr)
+{
+	unsigned long paddr = __pa(addr);
+
+	if ((paddr >> 41UL) != 0UL)
+		return false;
+	return test_bit(paddr >> 22, sparc64_valid_addr_bitmap);
+}
 
 extern int page_in_phys_avail(unsigned long paddr);
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/prom.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/prom.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/prom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/prom.h	2009-09-09 18:13:59.000000000 -0400
@@ -86,6 +86,8 @@
 #endif
 
 extern void prom_build_devicetree(void);
+extern void of_populate_present_mask(void);
+extern void of_fill_in_cpu_data(void);
 
 /* Dummy ref counting routines - to be implemented later */
 static inline struct device_node *of_node_get(struct device_node *node)
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/signal.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -176,7 +176,7 @@
 #define SA_STATIC_ALLOC         0x8000
 #endif
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 struct __new_sigaction {
 	__sighandler_t		sa_handler;
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/thread_info_32.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/thread_info_32.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/thread_info_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/thread_info_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -54,8 +54,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)				\
 {							\
@@ -64,7 +62,7 @@
 	.exec_domain	=	&default_exec_domain,	\
 	.flags		=	0,			\
 	.cpu		=	0,			\
-	.preempt_count	=	1,			\
+	.preempt_count	=	INIT_PREEMPT_COUNT,	\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/thread_info_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/thread_info_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/thread_info_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/thread_info_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -102,8 +102,8 @@
 #define TI_KERN_CNTD1	0x00000488
 #define TI_PCR		0x00000490
 #define TI_RESTART_BLOCK 0x00000498
-#define TI_KUNA_REGS	0x000004c0
-#define TI_KUNA_INSN	0x000004c8
+#define TI_KUNA_REGS	0x000004c8
+#define TI_KUNA_INSN	0x000004d0
 #define TI_FPREGS	0x00000500
 
 /* We embed this in the uppermost byte of thread_info->flags */
@@ -125,8 +125,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -135,7 +133,7 @@
 	.task		=	&tsk,			\
 	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
 	.exec_domain	=	&default_exec_domain,	\
-	.preempt_count	=	1,			\
+	.preempt_count	=	INIT_PREEMPT_COUNT,	\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/tlb_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/tlb_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/tlb_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/tlb_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -100,9 +100,9 @@
 }
 
 #define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0)
-#define pte_free_tlb(mp, ptepage) pte_free((mp)->mm, ptepage)
-#define pmd_free_tlb(mp, pmdp) pmd_free((mp)->mm, pmdp)
-#define pud_free_tlb(tlb,pudp) __pud_free_tlb(tlb,pudp)
+#define pte_free_tlb(mp, ptepage, addr) pte_free((mp)->mm, ptepage)
+#define pmd_free_tlb(mp, pmdp, addr) pmd_free((mp)->mm, pmdp)
+#define pud_free_tlb(tlb,pudp, addr) __pud_free_tlb(tlb,pudp,addr)
 
 #define tlb_migrate_finish(mm)	do { } while (0)
 #define tlb_start_vma(tlb, vma) do { } while (0)
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/trap_block.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/trap_block.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/trap_block.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/trap_block.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,207 @@
+#ifndef _SPARC_TRAP_BLOCK_H
+#define _SPARC_TRAP_BLOCK_H
+
+#include <asm/hypervisor.h>
+#include <asm/asi.h>
+
+#ifndef __ASSEMBLY__
+
+/* Trap handling code needs to get at a few critical values upon
+ * trap entry and to process TSB misses.  These cannot be in the
+ * per_cpu() area as we really need to lock them into the TLB and
+ * thus make them part of the main kernel image.  As a result we
+ * try to make this as small as possible.
+ *
+ * This is padded out and aligned to 64-bytes to avoid false sharing
+ * on SMP.
+ */
+
+/* If you modify the size of this structure, please update
+ * TRAP_BLOCK_SZ_SHIFT below.
+ */
+struct thread_info;
+struct trap_per_cpu {
+/* D-cache line 1: Basic thread information, cpu and device mondo queues */
+	struct thread_info	*thread;
+	unsigned long		pgd_paddr;
+	unsigned long		cpu_mondo_pa;
+	unsigned long		dev_mondo_pa;
+
+/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
+	unsigned long		resum_mondo_pa;
+	unsigned long		resum_kernel_buf_pa;
+	unsigned long		nonresum_mondo_pa;
+	unsigned long		nonresum_kernel_buf_pa;
+
+/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
+	struct hv_fault_status	fault_info;
+
+/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list.  */
+	unsigned long		cpu_mondo_block_pa;
+	unsigned long		cpu_list_pa;
+	unsigned long		tsb_huge;
+	unsigned long		tsb_huge_temp;
+
+/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size.  */
+	unsigned long		irq_worklist_pa;
+	unsigned int		cpu_mondo_qmask;
+	unsigned int		dev_mondo_qmask;
+	unsigned int		resum_qmask;
+	unsigned int		nonresum_qmask;
+	unsigned long		__per_cpu_base;
+} __attribute__((aligned(64)));
+extern struct trap_per_cpu trap_block[NR_CPUS];
+extern void init_cur_cpu_trap(struct thread_info *);
+extern void setup_tba(void);
+extern int ncpus_probed;
+
+extern unsigned long real_hard_smp_processor_id(void);
+
+struct cpuid_patch_entry {
+	unsigned int	addr;
+	unsigned int	cheetah_safari[4];
+	unsigned int	cheetah_jbus[4];
+	unsigned int	starfire[4];
+	unsigned int	sun4v[4];
+};
+extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
+
+struct sun4v_1insn_patch_entry {
+	unsigned int	addr;
+	unsigned int	insn;
+};
+extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
+	__sun4v_1insn_patch_end;
+
+struct sun4v_2insn_patch_entry {
+	unsigned int	addr;
+	unsigned int	insns[2];
+};
+extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
+	__sun4v_2insn_patch_end;
+
+
+#endif /* !(__ASSEMBLY__) */
+
+#define TRAP_PER_CPU_THREAD		0x00
+#define TRAP_PER_CPU_PGD_PADDR		0x08
+#define TRAP_PER_CPU_CPU_MONDO_PA	0x10
+#define TRAP_PER_CPU_DEV_MONDO_PA	0x18
+#define TRAP_PER_CPU_RESUM_MONDO_PA	0x20
+#define TRAP_PER_CPU_RESUM_KBUF_PA	0x28
+#define TRAP_PER_CPU_NONRESUM_MONDO_PA	0x30
+#define TRAP_PER_CPU_NONRESUM_KBUF_PA	0x38
+#define TRAP_PER_CPU_FAULT_INFO		0x40
+#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA	0xc0
+#define TRAP_PER_CPU_CPU_LIST_PA	0xc8
+#define TRAP_PER_CPU_TSB_HUGE		0xd0
+#define TRAP_PER_CPU_TSB_HUGE_TEMP	0xd8
+#define TRAP_PER_CPU_IRQ_WORKLIST_PA	0xe0
+#define TRAP_PER_CPU_CPU_MONDO_QMASK	0xe8
+#define TRAP_PER_CPU_DEV_MONDO_QMASK	0xec
+#define TRAP_PER_CPU_RESUM_QMASK	0xf0
+#define TRAP_PER_CPU_NONRESUM_QMASK	0xf4
+#define TRAP_PER_CPU_PER_CPU_BASE	0xf8
+
+#define TRAP_BLOCK_SZ_SHIFT		8
+
+#include <asm/scratchpad.h>
+
+#define __GET_CPUID(REG)				\
+	/* Spitfire implementation (default). */	\
+661:	ldxa		[%g0] ASI_UPA_CONFIG, REG;	\
+	srlx		REG, 17, REG;			\
+	 and		REG, 0x1f, REG;			\
+	nop;						\
+	.section	.cpuid_patch, "ax";		\
+	/* Instruction location. */			\
+	.word		661b;				\
+	/* Cheetah Safari implementation. */		\
+	ldxa		[%g0] ASI_SAFARI_CONFIG, REG;	\
+	srlx		REG, 17, REG;			\
+	and		REG, 0x3ff, REG;		\
+	nop;						\
+	/* Cheetah JBUS implementation. */		\
+	ldxa		[%g0] ASI_JBUS_CONFIG, REG;	\
+	srlx		REG, 17, REG;			\
+	and		REG, 0x1f, REG;			\
+	nop;						\
+	/* Starfire implementation. */			\
+	sethi		%hi(0x1fff40000d0 >> 9), REG;	\
+	sllx		REG, 9, REG;			\
+	or		REG, 0xd0, REG;			\
+	lduwa		[REG] ASI_PHYS_BYPASS_EC_E, REG;\
+	/* sun4v implementation. */			\
+	mov		SCRATCHPAD_CPUID, REG;		\
+	ldxa		[REG] ASI_SCRATCHPAD, REG;	\
+	nop;						\
+	nop;						\
+	.previous;
+
+#ifdef CONFIG_SMP
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	__GET_CPUID(TMP)			\
+	sethi	%hi(trap_block), DEST;		\
+	sllx	TMP, TRAP_BLOCK_SZ_SHIFT, TMP;	\
+	or	DEST, %lo(trap_block), DEST;	\
+	add	DEST, TMP, DEST;		\
+
+/* Clobbers TMP, current address space PGD phys address into DEST.  */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+/* Clobbers TMP, loads DEST with current thread info pointer.  */
+#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* Given the current thread info pointer in THR, load the per-cpu
+ * area base of the current processor into DEST.  REG1, REG2, and REG3 are
+ * clobbered.
+ *
+ * You absolutely cannot use DEST as a temporary in this code.  The
+ * reason is that traps can happen during execution, and return from
+ * trap will load the fully resolved DEST per-cpu base.  This can corrupt
+ * the calculations done by the macro mid-stream.
+ */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)	\
+	lduh	[THR + TI_CPU], REG1;			\
+	sethi	%hi(trap_block), REG2;			\
+	sllx	REG1, TRAP_BLOCK_SZ_SHIFT, REG1;	\
+	or	REG2, %lo(trap_block), REG2;		\
+	add	REG2, REG1, REG2;			\
+	ldx	[REG2 + TRAP_PER_CPU_PER_CPU_BASE], DEST;
+
+#else
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	sethi	%hi(trap_block), DEST;		\
+	or	DEST, %lo(trap_block), DEST;	\
+
+/* Uniprocessor versions, we know the cpuid is zero.  */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* No per-cpu areas on uniprocessor, so no need to load DEST.  */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
+
+#endif /* !(CONFIG_SMP) */
+
+#endif /* _SPARC_TRAP_BLOCK_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/types.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,8 +21,6 @@
 
 #ifdef __KERNEL__
 
-#define BITS_PER_LONG 64
-
 #ifndef __ASSEMBLY__
 
 /* Dma addresses come in generic and 64-bit flavours.  */
@@ -46,8 +44,6 @@
 
 #ifdef __KERNEL__
 
-#define BITS_PER_LONG 32
-
 #ifndef __ASSEMBLY__
 
 typedef u32 dma_addr_t;
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/uaccess_32.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/uaccess_32.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/uaccess_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/uaccess_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,9 @@
 
 #ifndef __ASSEMBLY__
 
+#define ARCH_HAS_SORT_EXTABLE
+#define ARCH_HAS_SEARCH_EXTABLE
+
 /* Sparc is not segmented, however we need to be able to fool access_ok()
  * when doing system calls from kernel mode legitimately.
  *
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/uaccess_64.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/uaccess_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/uaccess_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/uaccess_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
 #include <asm/asi.h>
 #include <asm/system.h>
 #include <asm/spitfire.h>
-#include <asm-generic/uaccess.h>
+#include <asm-generic/uaccess-unaligned.h>
 #endif
 
 #ifndef __ASSEMBLY__
diff -druN linux-libre-2.6.30-gnu/arch/sparc/include/asm/unistd.h linux-libre-2.6.31-gnu/arch/sparc/include/asm/unistd.h
--- linux-libre-2.6.30-gnu/arch/sparc/include/asm/unistd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/include/asm/unistd.h	2009-09-09 18:13:59.000000000 -0400
@@ -394,8 +394,9 @@
 #define __NR_accept4		323
 #define __NR_preadv		324
 #define __NR_pwritev		325
+#define __NR_rt_tgsigqueueinfo	326
 
-#define NR_SYSCALLS		326
+#define NR_SYSCALLS		327
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
diff -druN linux-libre-2.6.30-gnu/arch/sparc/Kconfig linux-libre-2.6.31-gnu/arch/sparc/Kconfig
--- linux-libre-2.6.30-gnu/arch/sparc/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,8 @@
 	select HAVE_KPROBES
 	select HAVE_LMB
 	select HAVE_SYSCALL_WRAPPERS
+	select HAVE_DYNAMIC_FTRACE
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select RTC_DRV_CMOS
 	select RTC_DRV_BQ4802
@@ -93,6 +95,9 @@
 config HAVE_SETUP_PER_CPU_AREA
 	def_bool y if SPARC64
 
+config HAVE_DYNAMIC_PER_CPU_AREA
+	def_bool y if SPARC64
+
 config GENERIC_HARDIRQS_NO__DO_IRQ
 	bool
 	def_bool y if SPARC64
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/cpumap.c linux-libre-2.6.31-gnu/arch/sparc/kernel/cpumap.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/cpumap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/cpumap.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,431 @@
+/* cpumap.c: used for optimizing CPU assignment
+ *
+ * Copyright (C) 2009 Hong H. Pham <hong.pham@windriver.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <asm/cpudata.h>
+#include "cpumap.h"
+
+
+enum {
+	CPUINFO_LVL_ROOT = 0,
+	CPUINFO_LVL_NODE,
+	CPUINFO_LVL_CORE,
+	CPUINFO_LVL_PROC,
+	CPUINFO_LVL_MAX,
+};
+
+enum {
+	ROVER_NO_OP              = 0,
+	/* Increment rover every time level is visited */
+	ROVER_INC_ON_VISIT       = 1 << 0,
+	/* Increment parent's rover every time rover wraps around */
+	ROVER_INC_PARENT_ON_LOOP = 1 << 1,
+};
+
+struct cpuinfo_node {
+	int id;
+	int level;
+	int num_cpus;    /* Number of CPUs in this hierarchy */
+	int parent_index;
+	int child_start; /* Array index of the first child node */
+	int child_end;   /* Array index of the last child node */
+	int rover;       /* Child node iterator */
+};
+
+struct cpuinfo_level {
+	int start_index; /* Index of first node of a level in a cpuinfo tree */
+	int end_index;   /* Index of last node of a level in a cpuinfo tree */
+	int num_nodes;   /* Number of nodes in a level in a cpuinfo tree */
+};
+
+struct cpuinfo_tree {
+	int total_nodes;
+
+	/* Offsets into nodes[] for each level of the tree */
+	struct cpuinfo_level level[CPUINFO_LVL_MAX];
+	struct cpuinfo_node  nodes[0];
+};
+
+
+static struct cpuinfo_tree *cpuinfo_tree;
+
+static u16 cpu_distribution_map[NR_CPUS];
+static DEFINE_SPINLOCK(cpu_map_lock);
+
+
+/* Niagara optimized cpuinfo tree traversal. */
+static const int niagara_iterate_method[] = {
+	[CPUINFO_LVL_ROOT] = ROVER_NO_OP,
+
+	/* Strands (or virtual CPUs) within a core may not run concurrently
+	 * on the Niagara, as instruction pipeline(s) are shared.  Distribute
+	 * work to strands in different cores first for better concurrency.
+	 * Go to next NUMA node when all cores are used.
+	 */
+	[CPUINFO_LVL_NODE] = ROVER_INC_ON_VISIT|ROVER_INC_PARENT_ON_LOOP,
+
+	/* Strands are grouped together by proc_id in cpuinfo_sparc, i.e.
+	 * a proc_id represents an instruction pipeline.  Distribute work to
+	 * strands in different proc_id groups if the core has multiple
+	 * instruction pipelines (e.g. the Niagara 2/2+ has two).
+	 */
+	[CPUINFO_LVL_CORE] = ROVER_INC_ON_VISIT,
+
+	/* Pick the next strand in the proc_id group. */
+	[CPUINFO_LVL_PROC] = ROVER_INC_ON_VISIT,
+};
+
+/* Generic cpuinfo tree traversal.  Distribute work round robin across NUMA
+ * nodes.
+ */
+static const int generic_iterate_method[] = {
+	[CPUINFO_LVL_ROOT] = ROVER_INC_ON_VISIT,
+	[CPUINFO_LVL_NODE] = ROVER_NO_OP,
+	[CPUINFO_LVL_CORE] = ROVER_INC_PARENT_ON_LOOP,
+	[CPUINFO_LVL_PROC] = ROVER_INC_ON_VISIT|ROVER_INC_PARENT_ON_LOOP,
+};
+
+
+static int cpuinfo_id(int cpu, int level)
+{
+	int id;
+
+	switch (level) {
+	case CPUINFO_LVL_ROOT:
+		id = 0;
+		break;
+	case CPUINFO_LVL_NODE:
+		id = cpu_to_node(cpu);
+		break;
+	case CPUINFO_LVL_CORE:
+		id = cpu_data(cpu).core_id;
+		break;
+	case CPUINFO_LVL_PROC:
+		id = cpu_data(cpu).proc_id;
+		break;
+	default:
+		id = -EINVAL;
+	}
+	return id;
+}
+
+/*
+ * Enumerate the CPU information in __cpu_data to determine the start index,
+ * end index, and number of nodes for each level in the cpuinfo tree.  The
+ * total number of cpuinfo nodes required to build the tree is returned.
+ */
+static int enumerate_cpuinfo_nodes(struct cpuinfo_level *tree_level)
+{
+	int prev_id[CPUINFO_LVL_MAX];
+	int i, n, num_nodes;
+
+	for (i = CPUINFO_LVL_ROOT; i < CPUINFO_LVL_MAX; i++) {
+		struct cpuinfo_level *lv = &tree_level[i];
+
+		prev_id[i] = -1;
+		lv->start_index = lv->end_index = lv->num_nodes = 0;
+	}
+
+	num_nodes = 1; /* Include the root node */
+
+	for (i = 0; i < num_possible_cpus(); i++) {
+		if (!cpu_online(i))
+			continue;
+
+		n = cpuinfo_id(i, CPUINFO_LVL_NODE);
+		if (n > prev_id[CPUINFO_LVL_NODE]) {
+			tree_level[CPUINFO_LVL_NODE].num_nodes++;
+			prev_id[CPUINFO_LVL_NODE] = n;
+			num_nodes++;
+		}
+		n = cpuinfo_id(i, CPUINFO_LVL_CORE);
+		if (n > prev_id[CPUINFO_LVL_CORE]) {
+			tree_level[CPUINFO_LVL_CORE].num_nodes++;
+			prev_id[CPUINFO_LVL_CORE] = n;
+			num_nodes++;
+		}
+		n = cpuinfo_id(i, CPUINFO_LVL_PROC);
+		if (n > prev_id[CPUINFO_LVL_PROC]) {
+			tree_level[CPUINFO_LVL_PROC].num_nodes++;
+			prev_id[CPUINFO_LVL_PROC] = n;
+			num_nodes++;
+		}
+	}
+
+	tree_level[CPUINFO_LVL_ROOT].num_nodes = 1;
+
+	n = tree_level[CPUINFO_LVL_NODE].num_nodes;
+	tree_level[CPUINFO_LVL_NODE].start_index = 1;
+	tree_level[CPUINFO_LVL_NODE].end_index   = n;
+
+	n++;
+	tree_level[CPUINFO_LVL_CORE].start_index = n;
+	n += tree_level[CPUINFO_LVL_CORE].num_nodes;
+	tree_level[CPUINFO_LVL_CORE].end_index   = n - 1;
+
+	tree_level[CPUINFO_LVL_PROC].start_index = n;
+	n += tree_level[CPUINFO_LVL_PROC].num_nodes;
+	tree_level[CPUINFO_LVL_PROC].end_index   = n - 1;
+
+	return num_nodes;
+}
+
+/* Build a tree representation of the CPU hierarchy using the per CPU
+ * information in __cpu_data.  Entries in __cpu_data[0..NR_CPUS] are
+ * assumed to be sorted in ascending order based on node, core_id, and
+ * proc_id (in order of significance).
+ */
+static struct cpuinfo_tree *build_cpuinfo_tree(void)
+{
+	struct cpuinfo_tree *new_tree;
+	struct cpuinfo_node *node;
+	struct cpuinfo_level tmp_level[CPUINFO_LVL_MAX];
+	int num_cpus[CPUINFO_LVL_MAX];
+	int level_rover[CPUINFO_LVL_MAX];
+	int prev_id[CPUINFO_LVL_MAX];
+	int n, id, cpu, prev_cpu, last_cpu, level;
+
+	n = enumerate_cpuinfo_nodes(tmp_level);
+
+	new_tree = kzalloc(sizeof(struct cpuinfo_tree) +
+	                   (sizeof(struct cpuinfo_node) * n), GFP_ATOMIC);
+	if (!new_tree)
+		return NULL;
+
+	new_tree->total_nodes = n;
+	memcpy(&new_tree->level, tmp_level, sizeof(tmp_level));
+
+	prev_cpu = cpu = first_cpu(cpu_online_map);
+
+	/* Initialize all levels in the tree with the first CPU */
+	for (level = CPUINFO_LVL_PROC; level >= CPUINFO_LVL_ROOT; level--) {
+		n = new_tree->level[level].start_index;
+
+		level_rover[level] = n;
+		node = &new_tree->nodes[n];
+
+		id = cpuinfo_id(cpu, level);
+		if (unlikely(id < 0)) {
+			kfree(new_tree);
+			return NULL;
+		}
+		node->id = id;
+		node->level = level;
+		node->num_cpus = 1;
+
+		node->parent_index = (level > CPUINFO_LVL_ROOT)
+		    ? new_tree->level[level - 1].start_index : -1;
+
+		node->child_start = node->child_end = node->rover =
+		    (level == CPUINFO_LVL_PROC)
+		    ? cpu : new_tree->level[level + 1].start_index;
+
+		prev_id[level] = node->id;
+		num_cpus[level] = 1;
+	}
+
+	for (last_cpu = (num_possible_cpus() - 1); last_cpu >= 0; last_cpu--) {
+		if (cpu_online(last_cpu))
+			break;
+	}
+
+	while (++cpu <= last_cpu) {
+		if (!cpu_online(cpu))
+			continue;
+
+		for (level = CPUINFO_LVL_PROC; level >= CPUINFO_LVL_ROOT;
+		     level--) {
+			id = cpuinfo_id(cpu, level);
+			if (unlikely(id < 0)) {
+				kfree(new_tree);
+				return NULL;
+			}
+
+			if ((id != prev_id[level]) || (cpu == last_cpu)) {
+				prev_id[level] = id;
+				node = &new_tree->nodes[level_rover[level]];
+				node->num_cpus = num_cpus[level];
+				num_cpus[level] = 1;
+
+				if (cpu == last_cpu)
+					node->num_cpus++;
+
+				/* Connect tree node to parent */
+				if (level == CPUINFO_LVL_ROOT)
+					node->parent_index = -1;
+				else
+					node->parent_index =
+					    level_rover[level - 1];
+
+				if (level == CPUINFO_LVL_PROC) {
+					node->child_end =
+					    (cpu == last_cpu) ? cpu : prev_cpu;
+				} else {
+					node->child_end =
+					    level_rover[level + 1] - 1;
+				}
+
+				/* Initialize the next node in the same level */
+				n = ++level_rover[level];
+				if (n <= new_tree->level[level].end_index) {
+					node = &new_tree->nodes[n];
+					node->id = id;
+					node->level = level;
+
+					/* Connect node to child */
+					node->child_start = node->child_end =
+					node->rover =
+					    (level == CPUINFO_LVL_PROC)
+					    ? cpu : level_rover[level + 1];
+				}
+			} else
+				num_cpus[level]++;
+		}
+		prev_cpu = cpu;
+	}
+
+	return new_tree;
+}
+
+static void increment_rover(struct cpuinfo_tree *t, int node_index,
+                            int root_index, const int *rover_inc_table)
+{
+	struct cpuinfo_node *node = &t->nodes[node_index];
+	int top_level, level;
+
+	top_level = t->nodes[root_index].level;
+	for (level = node->level; level >= top_level; level--) {
+		node->rover++;
+		if (node->rover <= node->child_end)
+			return;
+
+		node->rover = node->child_start;
+		/* If parent's rover does not need to be adjusted, stop here. */
+		if ((level == top_level) ||
+		    !(rover_inc_table[level] & ROVER_INC_PARENT_ON_LOOP))
+			return;
+
+		node = &t->nodes[node->parent_index];
+	}
+}
+
+static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
+{
+	const int *rover_inc_table;
+	int level, new_index, index = root_index;
+
+	switch (sun4v_chip_type) {
+	case SUN4V_CHIP_NIAGARA1:
+	case SUN4V_CHIP_NIAGARA2:
+		rover_inc_table = niagara_iterate_method;
+		break;
+	default:
+		rover_inc_table = generic_iterate_method;
+	}
+
+	for (level = t->nodes[root_index].level; level < CPUINFO_LVL_MAX;
+	     level++) {
+		new_index = t->nodes[index].rover;
+		if (rover_inc_table[level] & ROVER_INC_ON_VISIT)
+			increment_rover(t, index, root_index, rover_inc_table);
+
+		index = new_index;
+	}
+	return index;
+}
+
+static void _cpu_map_rebuild(void)
+{
+	int i;
+
+	if (cpuinfo_tree) {
+		kfree(cpuinfo_tree);
+		cpuinfo_tree = NULL;
+	}
+
+	cpuinfo_tree = build_cpuinfo_tree();
+	if (!cpuinfo_tree)
+		return;
+
+	/* Build CPU distribution map that spans all online CPUs.  No need
+	 * to check if the CPU is online, as that is done when the cpuinfo
+	 * tree is being built.
+	 */
+	for (i = 0; i < cpuinfo_tree->nodes[0].num_cpus; i++)
+		cpu_distribution_map[i] = iterate_cpu(cpuinfo_tree, 0);
+}
+
+/* Fallback if the cpuinfo tree could not be built.  CPU mapping is linear
+ * round robin.
+ */
+static int simple_map_to_cpu(unsigned int index)
+{
+	int i, end, cpu_rover;
+
+	cpu_rover = 0;
+	end = index % num_online_cpus();
+	for (i = 0; i < num_possible_cpus(); i++) {
+		if (cpu_online(cpu_rover)) {
+			if (cpu_rover >= end)
+				return cpu_rover;
+
+			cpu_rover++;
+		}
+	}
+
+	/* Impossible, since num_online_cpus() <= num_possible_cpus() */
+	return first_cpu(cpu_online_map);
+}
+
+static int _map_to_cpu(unsigned int index)
+{
+	struct cpuinfo_node *root_node;
+
+	if (unlikely(!cpuinfo_tree)) {
+		_cpu_map_rebuild();
+		if (!cpuinfo_tree)
+			return simple_map_to_cpu(index);
+	}
+
+	root_node = &cpuinfo_tree->nodes[0];
+#ifdef CONFIG_HOTPLUG_CPU
+	if (unlikely(root_node->num_cpus != num_online_cpus())) {
+		_cpu_map_rebuild();
+		if (!cpuinfo_tree)
+			return simple_map_to_cpu(index);
+	}
+#endif
+	return cpu_distribution_map[index % root_node->num_cpus];
+}
+
+int map_to_cpu(unsigned int index)
+{
+	int mapped_cpu;
+	unsigned long flag;
+
+	spin_lock_irqsave(&cpu_map_lock, flag);
+	mapped_cpu = _map_to_cpu(index);
+
+#ifdef CONFIG_HOTPLUG_CPU
+	while (unlikely(!cpu_online(mapped_cpu)))
+		mapped_cpu = _map_to_cpu(index);
+#endif
+	spin_unlock_irqrestore(&cpu_map_lock, flag);
+	return mapped_cpu;
+}
+EXPORT_SYMBOL(map_to_cpu);
+
+void cpu_map_rebuild(void)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&cpu_map_lock, flag);
+	_cpu_map_rebuild();
+	spin_unlock_irqrestore(&cpu_map_lock, flag);
+}
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/cpumap.h linux-libre-2.6.31-gnu/arch/sparc/kernel/cpumap.h
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/cpumap.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/cpumap.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef _CPUMAP_H
+#define _CPUMAP_H
+
+#ifdef CONFIG_SMP
+extern void cpu_map_rebuild(void);
+extern int  map_to_cpu(unsigned int index);
+#define cpu_map_init() cpu_map_rebuild()
+#else
+#define cpu_map_init() do {} while (0)
+static inline int map_to_cpu(unsigned int index)
+{
+	return raw_smp_processor_id();
+}
+#endif
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/dma.c linux-libre-2.6.31-gnu/arch/sparc/kernel/dma.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,8 +35,8 @@
 }
 EXPORT_SYMBOL(dma_set_mask);
 
-void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, gfp_t flag)
+static void *dma32_alloc_coherent(struct device *dev, size_t size,
+				  dma_addr_t *dma_handle, gfp_t flag)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type)
@@ -44,10 +44,9 @@
 #endif
 	return sbus_alloc_consistent(dev, size, dma_handle);
 }
-EXPORT_SYMBOL(dma_alloc_coherent);
 
-void dma_free_coherent(struct device *dev, size_t size,
-		       void *cpu_addr, dma_addr_t dma_handle)
+static void dma32_free_coherent(struct device *dev, size_t size,
+				void *cpu_addr, dma_addr_t dma_handle)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type) {
@@ -58,38 +57,10 @@
 #endif
 	sbus_free_consistent(dev, size, cpu_addr, dma_handle);
 }
-EXPORT_SYMBOL(dma_free_coherent);
-
-dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-			  size_t size, enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
-	if (dev->bus == &pci_bus_type)
-		return pci_map_single(to_pci_dev(dev), cpu_addr,
-				      size, (int)direction);
-#endif
-	return sbus_map_single(dev, cpu_addr, size, (int)direction);
-}
-EXPORT_SYMBOL(dma_map_single);
 
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-		      size_t size,
-		      enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
-	if (dev->bus == &pci_bus_type) {
-		pci_unmap_single(to_pci_dev(dev), dma_addr,
-				 size, (int)direction);
-		return;
-	}
-#endif
-	sbus_unmap_single(dev, dma_addr, size, (int)direction);
-}
-EXPORT_SYMBOL(dma_unmap_single);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-			unsigned long offset, size_t size,
-			enum dma_data_direction direction)
+static dma_addr_t dma32_map_page(struct device *dev, struct page *page,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type)
@@ -99,10 +70,9 @@
 	return sbus_map_single(dev, page_address(page) + offset,
 			       size, (int)direction);
 }
-EXPORT_SYMBOL(dma_map_page);
 
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-		    size_t size, enum dma_data_direction direction)
+static void dma32_unmap_page(struct device *dev, dma_addr_t dma_address,
+			     size_t size, enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type) {
@@ -113,10 +83,9 @@
 #endif
 	sbus_unmap_single(dev, dma_address, size, (int)direction);
 }
-EXPORT_SYMBOL(dma_unmap_page);
 
-int dma_map_sg(struct device *dev, struct scatterlist *sg,
-			     int nents, enum dma_data_direction direction)
+static int dma32_map_sg(struct device *dev, struct scatterlist *sg,
+			int nents, enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type)
@@ -124,10 +93,9 @@
 #endif
 	return sbus_map_sg(dev, sg, nents, direction);
 }
-EXPORT_SYMBOL(dma_map_sg);
 
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-		  int nents, enum dma_data_direction direction)
+void dma32_unmap_sg(struct device *dev, struct scatterlist *sg,
+		    int nents, enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type) {
@@ -137,10 +105,10 @@
 #endif
 	sbus_unmap_sg(dev, sg, nents, (int)direction);
 }
-EXPORT_SYMBOL(dma_unmap_sg);
 
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-			     size_t size, enum dma_data_direction direction)
+static void dma32_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+				      size_t size,
+				      enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type) {
@@ -151,10 +119,10 @@
 #endif
 	sbus_dma_sync_single_for_cpu(dev, dma_handle, size, (int) direction);
 }
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
 
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-				size_t size, enum dma_data_direction direction)
+static void dma32_sync_single_for_device(struct device *dev,
+					 dma_addr_t dma_handle, size_t size,
+					 enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type) {
@@ -165,28 +133,9 @@
 #endif
 	sbus_dma_sync_single_for_device(dev, dma_handle, size, (int) direction);
 }
-EXPORT_SYMBOL(dma_sync_single_for_device);
 
-void dma_sync_single_range_for_cpu(struct device *dev,
-				   dma_addr_t dma_handle,
-				   unsigned long offset,
-				   size_t size,
-				   enum dma_data_direction direction)
-{
-	dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction);
-}
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
-
-void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-				      unsigned long offset, size_t size,
-				      enum dma_data_direction direction)
-{
-	dma_sync_single_for_device(dev, dma_handle+offset, size, direction);
-}
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
-
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
-			 int nelems, enum dma_data_direction direction)
+static void dma32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+				  int nelems, enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type) {
@@ -197,11 +146,10 @@
 #endif
 	BUG();
 }
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
 
-void dma_sync_sg_for_device(struct device *dev,
-			    struct scatterlist *sg, int nelems,
-			    enum dma_data_direction direction)
+static void dma32_sync_sg_for_device(struct device *dev,
+				     struct scatterlist *sg, int nelems,
+				     enum dma_data_direction direction)
 {
 #ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type) {
@@ -212,16 +160,19 @@
 #endif
 	BUG();
 }
-EXPORT_SYMBOL(dma_sync_sg_for_device);
 
-int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-	return (dma_addr == DMA_ERROR_CODE);
-}
-EXPORT_SYMBOL(dma_mapping_error);
+static const struct dma_ops dma32_dma_ops = {
+	.alloc_coherent		= dma32_alloc_coherent,
+	.free_coherent		= dma32_free_coherent,
+	.map_page		= dma32_map_page,
+	.unmap_page		= dma32_unmap_page,
+	.map_sg			= dma32_map_sg,
+	.unmap_sg		= dma32_unmap_sg,
+	.sync_single_for_cpu	= dma32_sync_single_for_cpu,
+	.sync_single_for_device	= dma32_sync_single_for_device,
+	.sync_sg_for_cpu	= dma32_sync_sg_for_cpu,
+	.sync_sg_for_device	= dma32_sync_sg_for_device,
+};
 
-int dma_get_cache_alignment(void)
-{
-	return 32;
-}
-EXPORT_SYMBOL(dma_get_cache_alignment);
+const struct dma_ops *dma_ops = &dma32_dma_ops;
+EXPORT_SYMBOL(dma_ops);
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/ds.c linux-libre-2.6.31-gnu/arch/sparc/kernel/ds.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/ds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/ds.c	2009-09-09 18:13:59.000000000 -0400
@@ -544,7 +544,8 @@
 			     resp_len, ncpus, mask,
 			     DR_CPU_STAT_CONFIGURED);
 
-	mdesc_fill_in_cpu_data(*mask);
+	mdesc_populate_present_mask(mask);
+	mdesc_fill_in_cpu_data(mask);
 
 	for_each_cpu_mask(cpu, *mask) {
 		int err;
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/ftrace.c linux-libre-2.6.31-gnu/arch/sparc/kernel/ftrace.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/ftrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/ftrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,14 +7,10 @@
 
 #include <asm/ftrace.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 static const u32 ftrace_nop = 0x01000000;
 
-unsigned char *ftrace_nop_replace(void)
-{
-	return (char *)&ftrace_nop;
-}
-
-unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
+static u32 ftrace_call_replace(unsigned long ip, unsigned long addr)
 {
 	static u32 call;
 	s32 off;
@@ -22,15 +18,11 @@
 	off = ((s32)addr - (s32)ip);
 	call = 0x40000000 | ((u32)off >> 2);
 
-	return (unsigned char *) &call;
+	return call;
 }
 
-int
-ftrace_modify_code(unsigned long ip, unsigned char *old_code,
-		   unsigned char *new_code)
+static int ftrace_modify_code(unsigned long ip, u32 old, u32 new)
 {
-	u32 old = *(u32 *)old_code;
-	u32 new = *(u32 *)new_code;
 	u32 replaced;
 	int faulted;
 
@@ -59,18 +51,43 @@
 	return faulted;
 }
 
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long ip = rec->ip;
+	u32 old, new;
+
+	old = ftrace_call_replace(ip, addr);
+	new = ftrace_nop;
+	return ftrace_modify_code(ip, old, new);
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long ip = rec->ip;
+	u32 old, new;
+
+	old = ftrace_nop;
+	new = ftrace_call_replace(ip, addr);
+	return ftrace_modify_code(ip, old, new);
+}
+
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
 	unsigned long ip = (unsigned long)(&ftrace_call);
-	unsigned char old[MCOUNT_INSN_SIZE], *new;
+	u32 old, new;
 
-	memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
+	old = *(u32 *) &ftrace_call;
 	new = ftrace_call_replace(ip, (unsigned long)func);
 	return ftrace_modify_code(ip, old, new);
 }
 
 int __init ftrace_dyn_arch_init(void *data)
 {
-	ftrace_mcount_set(data);
+	unsigned long *p = data;
+
+	*p = 0;
+
 	return 0;
 }
+#endif
+
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/head_64.S linux-libre-2.6.31-gnu/arch/sparc/kernel/head_64.S
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/head_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/head_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -641,28 +641,6 @@
 	/* Not reached... */
 
 1:
-	/* If we boot on a non-zero cpu, all of the per-cpu
-	 * variable references we make before setting up the
-	 * per-cpu areas will use a bogus offset.  Put a
-	 * compensating factor into __per_cpu_base to handle
-	 * this cleanly.
-	 *
-	 * What the per-cpu code calculates is:
-	 *
-	 *	__per_cpu_base + (cpu << __per_cpu_shift)
-	 *
-	 * These two variables are zero initially, so to
-	 * make it all cancel out to zero we need to put
-	 * "0 - (cpu << 0)" into __per_cpu_base so that the
-	 * above formula evaluates to zero.
-	 *
-	 * We cannot even perform a printk() until this stuff
-	 * is setup as that calls cpu_clock() which uses
-	 * per-cpu variables.
-	 */
-	sub	%g0, %o0, %o1
-	sethi	%hi(__per_cpu_base), %o2
-	stx	%o1, [%o2 + %lo(__per_cpu_base)]
 #else
 	mov	0, %o0
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/init_task.c linux-libre-2.6.31-gnu/arch/sparc/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,10 +10,7 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
 struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_mm);
 EXPORT_SYMBOL(init_task);
 
 /* .text section in head.S is aligned at 8k boundary and this gets linked
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/iommu.c linux-libre-2.6.31-gnu/arch/sparc/kernel/iommu.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/iommu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -351,8 +351,9 @@
 		free_pages((unsigned long)cpu, order);
 }
 
-static dma_addr_t dma_4u_map_single(struct device *dev, void *ptr, size_t sz,
-				    enum dma_data_direction direction)
+static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,
+				  unsigned long offset, size_t sz,
+				  enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
@@ -368,7 +369,7 @@
 	if (unlikely(direction == DMA_NONE))
 		goto bad_no_ctx;
 
-	oaddr = (unsigned long)ptr;
+	oaddr = (unsigned long)(page_address(page) + offset);
 	npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
 	npages >>= IO_PAGE_SHIFT;
 
@@ -472,8 +473,8 @@
 		       vaddr, ctx, npages);
 }
 
-static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
-				size_t sz, enum dma_data_direction direction)
+static void dma_4u_unmap_page(struct device *dev, dma_addr_t bus_addr,
+			      size_t sz, enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
@@ -824,8 +825,8 @@
 static const struct dma_ops sun4u_dma_ops = {
 	.alloc_coherent		= dma_4u_alloc_coherent,
 	.free_coherent		= dma_4u_free_coherent,
-	.map_single		= dma_4u_map_single,
-	.unmap_single		= dma_4u_unmap_single,
+	.map_page		= dma_4u_map_page,
+	.unmap_page		= dma_4u_unmap_page,
 	.map_sg			= dma_4u_map_sg,
 	.unmap_sg		= dma_4u_unmap_sg,
 	.sync_single_for_cpu	= dma_4u_sync_single_for_cpu,
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/irq_64.c linux-libre-2.6.31-gnu/arch/sparc/kernel/irq_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/irq_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/irq_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,7 +20,6 @@
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/bootmem.h>
 #include <linux/irq.h>
 
 #include <asm/ptrace.h>
@@ -45,6 +44,7 @@
 #include <asm/cacheflush.h>
 
 #include "entry.h"
+#include "cpumap.h"
 
 #define NUM_IVECS	(IMAP_INR + 1)
 
@@ -256,35 +256,13 @@
 	int cpuid;
 
 	cpumask_copy(&mask, irq_desc[virt_irq].affinity);
-	if (cpus_equal(mask, CPU_MASK_ALL)) {
-		static int irq_rover;
-		static DEFINE_SPINLOCK(irq_rover_lock);
-		unsigned long flags;
-
-		/* Round-robin distribution... */
-	do_round_robin:
-		spin_lock_irqsave(&irq_rover_lock, flags);
-
-		while (!cpu_online(irq_rover)) {
-			if (++irq_rover >= nr_cpu_ids)
-				irq_rover = 0;
-		}
-		cpuid = irq_rover;
-		do {
-			if (++irq_rover >= nr_cpu_ids)
-				irq_rover = 0;
-		} while (!cpu_online(irq_rover));
-
-		spin_unlock_irqrestore(&irq_rover_lock, flags);
+	if (cpus_equal(mask, cpu_online_map)) {
+		cpuid = map_to_cpu(virt_irq);
 	} else {
 		cpumask_t tmp;
 
 		cpus_and(tmp, cpu_online_map, mask);
-
-		if (cpus_empty(tmp))
-			goto do_round_robin;
-
-		cpuid = first_cpu(tmp);
+		cpuid = cpus_empty(tmp) ? map_to_cpu(virt_irq) : first_cpu(tmp);
 	}
 
 	return cpuid;
@@ -318,10 +296,12 @@
 	}
 }
 
-static void sun4u_set_affinity(unsigned int virt_irq,
+static int sun4u_set_affinity(unsigned int virt_irq,
 			       const struct cpumask *mask)
 {
 	sun4u_irq_enable(virt_irq);
+
+	return 0;
 }
 
 /* Don't do anything.  The desc->status check for IRQ_DISABLED in
@@ -377,7 +357,7 @@
 		       ino, err);
 }
 
-static void sun4v_set_affinity(unsigned int virt_irq,
+static int sun4v_set_affinity(unsigned int virt_irq,
 			       const struct cpumask *mask)
 {
 	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
@@ -388,6 +368,8 @@
 	if (err != HV_EOK)
 		printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): "
 		       "err(%d)\n", ino, cpuid, err);
+
+	return 0;
 }
 
 static void sun4v_irq_disable(unsigned int virt_irq)
@@ -445,7 +427,7 @@
 		       dev_handle, dev_ino, err);
 }
 
-static void sun4v_virt_set_affinity(unsigned int virt_irq,
+static int sun4v_virt_set_affinity(unsigned int virt_irq,
 				    const struct cpumask *mask)
 {
 	unsigned long cpuid, dev_handle, dev_ino;
@@ -461,6 +443,8 @@
 		printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): "
 		       "err(%d)\n",
 		       dev_handle, dev_ino, cpuid, err);
+
+	return 0;
 }
 
 static void sun4v_virq_disable(unsigned int virt_irq)
@@ -902,7 +886,7 @@
  * Therefore you cannot make any OBP calls, not even prom_printf,
  * from these two routines.
  */
-static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask)
+static void __cpuinit notrace register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask)
 {
 	unsigned long num_entries = (qmask + 1) / 64;
 	unsigned long status;
@@ -929,25 +913,19 @@
 			   tb->nonresum_qmask);
 }
 
-static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask)
-{
-	unsigned long size = PAGE_ALIGN(qmask + 1);
-	void *p = __alloc_bootmem(size, size, 0);
-	if (!p) {
-		prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
-		prom_halt();
-	}
-
-	*pa_ptr = __pa(p);
-}
-
-static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask)
+/* Each queue region must be a power of 2 multiple of 64 bytes in
+ * size.  The base real address must be aligned to the size of the
+ * region.  Thus, an 8KB queue must be 8KB aligned, for example.
+ */
+static void __init alloc_one_queue(unsigned long *pa_ptr, unsigned long qmask)
 {
 	unsigned long size = PAGE_ALIGN(qmask + 1);
-	void *p = __alloc_bootmem(size, size, 0);
+	unsigned long order = get_order(size);
+	unsigned long p;
 
+	p = __get_free_pages(GFP_KERNEL, order);
 	if (!p) {
-		prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
+		prom_printf("SUN4V: Error, cannot allocate queue.\n");
 		prom_halt();
 	}
 
@@ -957,11 +935,11 @@
 static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb)
 {
 #ifdef CONFIG_SMP
-	void *page;
+	unsigned long page;
 
 	BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
 
-	page = alloc_bootmem_pages(PAGE_SIZE);
+	page = get_zeroed_page(GFP_KERNEL);
 	if (!page) {
 		prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
 		prom_halt();
@@ -980,13 +958,13 @@
 	for_each_possible_cpu(cpu) {
 		struct trap_per_cpu *tb = &trap_block[cpu];
 
-		alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask);
-		alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask);
-		alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask);
-		alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask);
-		alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask);
-		alloc_one_kbuf(&tb->nonresum_kernel_buf_pa,
-			       tb->nonresum_qmask);
+		alloc_one_queue(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask);
+		alloc_one_queue(&tb->dev_mondo_pa, tb->dev_mondo_qmask);
+		alloc_one_queue(&tb->resum_mondo_pa, tb->resum_qmask);
+		alloc_one_queue(&tb->resum_kernel_buf_pa, tb->resum_qmask);
+		alloc_one_queue(&tb->nonresum_mondo_pa, tb->nonresum_qmask);
+		alloc_one_queue(&tb->nonresum_kernel_buf_pa,
+				tb->nonresum_qmask);
 	}
 }
 
@@ -1014,7 +992,7 @@
 	kill_prom_timer();
 
 	size = sizeof(struct ino_bucket) * NUM_IVECS;
-	ivector_table = alloc_bootmem(size);
+	ivector_table = kzalloc(size, GFP_KERNEL);
 	if (!ivector_table) {
 		prom_printf("Fatal error, cannot allocate ivector_table\n");
 		prom_halt();
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/ktlb.S linux-libre-2.6.31-gnu/arch/sparc/kernel/ktlb.S
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/ktlb.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/ktlb.S	2009-09-09 18:13:59.000000000 -0400
@@ -151,12 +151,46 @@
 	 * Must preserve %g1 and %g6 (TAG).
 	 */
 kvmap_dtlb_tsb4m_miss:
-	sethi		%hi(kpte_linear_bitmap), %g2
-	or		%g2, %lo(kpte_linear_bitmap), %g2
+	/* Clear the PAGE_OFFSET top virtual bits, shift
+	 * down to get PFN, and make sure PFN is in range.
+	 */
+	sllx		%g4, 21, %g5
 
-	/* Clear the PAGE_OFFSET top virtual bits, then shift
-	 * down to get a 256MB physical address index.
+	/* Check to see if we know about valid memory at the 4MB
+	 * chunk this physical address will reside within.
 	 */
+	srlx		%g5, 21 + 41, %g2
+	brnz,pn		%g2, kvmap_dtlb_longpath
+	 nop
+
+	/* This unconditional branch and delay-slot nop gets patched
+	 * by the sethi sequence once the bitmap is properly setup.
+	 */
+	.globl		valid_addr_bitmap_insn
+valid_addr_bitmap_insn:
+	ba,pt		%xcc, 2f
+	 nop
+	.subsection	2
+	.globl		valid_addr_bitmap_patch
+valid_addr_bitmap_patch:
+	sethi		%hi(sparc64_valid_addr_bitmap), %g7
+	or		%g7, %lo(sparc64_valid_addr_bitmap), %g7
+	.previous
+
+	srlx		%g5, 21 + 22, %g2
+	srlx		%g2, 6, %g5
+	and		%g2, 63, %g2
+	sllx		%g5, 3, %g5
+	ldx		[%g7 + %g5], %g5
+	mov		1, %g7
+	sllx		%g7, %g2, %g7
+	andcc		%g5, %g7, %g0
+	be,pn		%xcc, kvmap_dtlb_longpath
+
+2:	 sethi		%hi(kpte_linear_bitmap), %g2
+	or		%g2, %lo(kpte_linear_bitmap), %g2
+
+	/* Get the 256MB physical address index. */
 	sllx		%g4, 21, %g5
 	mov		1, %g7
 	srlx		%g5, 21 + 28, %g5
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/Makefile linux-libre-2.6.31-gnu/arch/sparc/kernel/Makefile
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,7 @@
 obj-$(CONFIG_SPARC32)   += muldiv.o
 obj-y                   += prom_common.o
 obj-y                   += prom_$(BITS).o
+obj-y                   += of_device_common.o
 obj-y                   += of_device_$(BITS).o
 obj-$(CONFIG_SPARC64)   += prom_irqtrans.o
 
@@ -54,6 +55,7 @@
 obj-$(CONFIG_SPARC64)   += mdesc.o
 obj-$(CONFIG_SPARC64)	+= pcr.o
 obj-$(CONFIG_SPARC64)	+= nmi.o
+obj-$(CONFIG_SPARC64_SMP) += cpumap.o
 
 # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation
 obj-$(CONFIG_SPARC32)     += devres.o
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/mdesc.c linux-libre-2.6.31-gnu/arch/sparc/kernel/mdesc.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/mdesc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/mdesc.c	2009-09-09 18:13:59.000000000 -0400
@@ -574,7 +574,7 @@
 	mdesc_release(hp);
 }
 
-static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
+static void __cpuinit fill_in_one_cache(cpuinfo_sparc *c,
 					struct mdesc_handle *hp,
 					u64 mp)
 {
@@ -619,8 +619,7 @@
 	}
 }
 
-static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
-				    int core_id)
+static void __cpuinit mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
 {
 	u64 a;
 
@@ -653,7 +652,7 @@
 	}
 }
 
-static void __devinit set_core_ids(struct mdesc_handle *hp)
+static void __cpuinit set_core_ids(struct mdesc_handle *hp)
 {
 	int idx;
 	u64 mp;
@@ -678,8 +677,7 @@
 	}
 }
 
-static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
-				    int proc_id)
+static void __cpuinit mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
 {
 	u64 a;
 
@@ -698,8 +696,7 @@
 	}
 }
 
-static void __devinit __set_proc_ids(struct mdesc_handle *hp,
-				     const char *exec_unit_name)
+static void __cpuinit __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
 {
 	int idx;
 	u64 mp;
@@ -720,13 +717,13 @@
 	}
 }
 
-static void __devinit set_proc_ids(struct mdesc_handle *hp)
+static void __cpuinit set_proc_ids(struct mdesc_handle *hp)
 {
 	__set_proc_ids(hp, "exec_unit");
 	__set_proc_ids(hp, "exec-unit");
 }
 
-static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
+static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
 					 unsigned char def)
 {
 	u64 val;
@@ -745,7 +742,7 @@
 	*mask = ((1U << def) * 64U) - 1U;
 }
 
-static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
+static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
 				     struct trap_per_cpu *tb)
 {
 	const u64 *val;
@@ -763,23 +760,15 @@
 	get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
 }
 
-void __cpuinit mdesc_fill_in_cpu_data(cpumask_t mask)
+static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
 {
 	struct mdesc_handle *hp = mdesc_grab();
+	void *ret = NULL;
 	u64 mp;
 
-	ncpus_probed = 0;
 	mdesc_for_each_node_by_name(hp, mp, "cpu") {
 		const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
-		const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
-		struct trap_per_cpu *tb;
-		cpuinfo_sparc *c;
-		int cpuid;
-		u64 a;
-
-		ncpus_probed++;
-
-		cpuid = *id;
+		int cpuid = *id;
 
 #ifdef CONFIG_SMP
 		if (cpuid >= NR_CPUS) {
@@ -788,62 +777,104 @@
 			       cpuid, NR_CPUS);
 			continue;
 		}
-		if (!cpu_isset(cpuid, mask))
-			continue;
-#else
-		/* On uniprocessor we only want the values for the
-		 * real physical cpu the kernel booted onto, however
-		 * cpu_data() only has one entry at index 0.
-		 */
-		if (cpuid != real_hard_smp_processor_id())
+		if (!cpu_isset(cpuid, *mask))
 			continue;
-		cpuid = 0;
 #endif
 
-		c = &cpu_data(cpuid);
-		c->clock_tick = *cfreq;
+		ret = func(hp, mp, cpuid, arg);
+		if (ret)
+			goto out;
+	}
+out:
+	mdesc_release(hp);
+	return ret;
+}
 
-		tb = &trap_block[cpuid];
-		get_mondo_data(hp, mp, tb);
+static void * __cpuinit record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
+{
+	ncpus_probed++;
+#ifdef CONFIG_SMP
+	set_cpu_present(cpuid, true);
+#endif
+	return NULL;
+}
 
-		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
-			u64 j, t = mdesc_arc_target(hp, a);
-			const char *t_name;
+void __cpuinit mdesc_populate_present_mask(cpumask_t *mask)
+{
+	if (tlb_type != hypervisor)
+		return;
 
-			t_name = mdesc_node_name(hp, t);
-			if (!strcmp(t_name, "cache")) {
-				fill_in_one_cache(c, hp, t);
-				continue;
-			}
+	ncpus_probed = 0;
+	mdesc_iterate_over_cpus(record_one_cpu, NULL, mask);
+}
 
-			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
-				u64 n = mdesc_arc_target(hp, j);
-				const char *n_name;
+static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
+{
+	const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
+	struct trap_per_cpu *tb;
+	cpuinfo_sparc *c;
+	u64 a;
 
-				n_name = mdesc_node_name(hp, n);
-				if (!strcmp(n_name, "cache"))
-					fill_in_one_cache(c, hp, n);
-			}
+#ifndef CONFIG_SMP
+	/* On uniprocessor we only want the values for the
+	 * real physical cpu the kernel booted onto, however
+	 * cpu_data() only has one entry at index 0.
+	 */
+	if (cpuid != real_hard_smp_processor_id())
+		return NULL;
+	cpuid = 0;
+#endif
+
+	c = &cpu_data(cpuid);
+	c->clock_tick = *cfreq;
+
+	tb = &trap_block[cpuid];
+	get_mondo_data(hp, mp, tb);
+
+	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
+		u64 j, t = mdesc_arc_target(hp, a);
+		const char *t_name;
+
+		t_name = mdesc_node_name(hp, t);
+		if (!strcmp(t_name, "cache")) {
+			fill_in_one_cache(c, hp, t);
+			continue;
 		}
 
-#ifdef CONFIG_SMP
-		cpu_set(cpuid, cpu_present_map);
-#endif
+		mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
+			u64 n = mdesc_arc_target(hp, j);
+			const char *n_name;
 
-		c->core_id = 0;
-		c->proc_id = -1;
+			n_name = mdesc_node_name(hp, n);
+			if (!strcmp(n_name, "cache"))
+				fill_in_one_cache(c, hp, n);
+		}
 	}
 
+	c->core_id = 0;
+	c->proc_id = -1;
+
+	return NULL;
+}
+
+void __cpuinit mdesc_fill_in_cpu_data(cpumask_t *mask)
+{
+	struct mdesc_handle *hp;
+
+	mdesc_iterate_over_cpus(fill_in_one_cpu, NULL, mask);
+
 #ifdef CONFIG_SMP
 	sparc64_multi_core = 1;
 #endif
 
+	hp = mdesc_grab();
+
 	set_core_ids(hp);
 	set_proc_ids(hp);
 
-	smp_fill_in_sib_core_maps();
-
 	mdesc_release(hp);
+
+	smp_fill_in_sib_core_maps();
 }
 
 static ssize_t mdesc_read(struct file *file, char __user *buf,
@@ -887,7 +918,6 @@
 {
 	struct mdesc_handle *hp;
 	unsigned long len, real_len, status;
-	cpumask_t mask;
 
 	(void) sun4v_mach_desc(0UL, 0UL, &len);
 
@@ -911,7 +941,4 @@
 	cur_mdesc = hp;
 
 	report_platform_properties();
-
-	cpus_setall(mask);
-	mdesc_fill_in_cpu_data(mask);
 }
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/module.c linux-libre-2.6.31-gnu/arch/sparc/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -75,8 +75,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-           table entries. */
 }
 
 /* Make generic code ignore STT_REGISTER dummy undefined symbols.  */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/nmi.c linux-libre-2.6.31-gnu/arch/sparc/kernel/nmi.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/nmi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/nmi.c	2009-09-09 18:13:59.000000000 -0400
@@ -103,7 +103,7 @@
 	}
 	if (!touched && __get_cpu_var(last_irq_sum) == sum) {
 		local_inc(&__get_cpu_var(alert_counter));
-		if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz)
+		if (local_read(&__get_cpu_var(alert_counter)) == 30 * nmi_hz)
 			die_nmi("BUG: NMI Watchdog detected LOCKUP",
 				regs, panic_on_timeout);
 	} else {
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_32.c linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_32.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,159 +6,11 @@
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 
-static int node_match(struct device *dev, void *data)
-{
-	struct of_device *op = to_of_device(dev);
-	struct device_node *dp = data;
-
-	return (op->node == dp);
-}
-
-struct of_device *of_find_device_by_node(struct device_node *dp)
-{
-	struct device *dev = bus_find_device(&of_platform_bus_type, NULL,
-					     dp, node_match);
-
-	if (dev)
-		return to_of_device(dev);
-
-	return NULL;
-}
-EXPORT_SYMBOL(of_find_device_by_node);
-
-unsigned int irq_of_parse_and_map(struct device_node *node, int index)
-{
-	struct of_device *op = of_find_device_by_node(node);
-
-	if (!op || index >= op->num_irqs)
-		return 0;
-
-	return op->irqs[index];
-}
-EXPORT_SYMBOL(irq_of_parse_and_map);
-
-/* Take the archdata values for IOMMU, STC, and HOSTDATA found in
- * BUS and propagate to all child of_device objects.
- */
-void of_propagate_archdata(struct of_device *bus)
-{
-	struct dev_archdata *bus_sd = &bus->dev.archdata;
-	struct device_node *bus_dp = bus->node;
-	struct device_node *dp;
-
-	for (dp = bus_dp->child; dp; dp = dp->sibling) {
-		struct of_device *op = of_find_device_by_node(dp);
-
-		op->dev.archdata.iommu = bus_sd->iommu;
-		op->dev.archdata.stc = bus_sd->stc;
-		op->dev.archdata.host_controller = bus_sd->host_controller;
-		op->dev.archdata.numa_node = bus_sd->numa_node;
-
-		if (dp->child)
-			of_propagate_archdata(op);
-	}
-}
-
-struct bus_type of_platform_bus_type;
-EXPORT_SYMBOL(of_platform_bus_type);
-
-static inline u64 of_read_addr(const u32 *cell, int size)
-{
-	u64 r = 0;
-	while (size--)
-		r = (r << 32) | *(cell++);
-	return r;
-}
-
-static void __init get_cells(struct device_node *dp,
-			     int *addrc, int *sizec)
-{
-	if (addrc)
-		*addrc = of_n_addr_cells(dp);
-	if (sizec)
-		*sizec = of_n_size_cells(dp);
-}
-
-/* Max address size we deal with */
-#define OF_MAX_ADDR_CELLS	4
-
-struct of_bus {
-	const char	*name;
-	const char	*addr_prop_name;
-	int		(*match)(struct device_node *parent);
-	void		(*count_cells)(struct device_node *child,
-				       int *addrc, int *sizec);
-	int		(*map)(u32 *addr, const u32 *range,
-			       int na, int ns, int pna);
-	unsigned long	(*get_flags)(const u32 *addr, unsigned long);
-};
-
-/*
- * Default translator (generic bus)
- */
-
-static void of_bus_default_count_cells(struct device_node *dev,
-				       int *addrc, int *sizec)
-{
-	get_cells(dev, addrc, sizec);
-}
-
-/* Make sure the least significant 64-bits are in-range.  Even
- * for 3 or 4 cell values it is a good enough approximation.
- */
-static int of_out_of_range(const u32 *addr, const u32 *base,
-			   const u32 *size, int na, int ns)
-{
-	u64 a = of_read_addr(addr, na);
-	u64 b = of_read_addr(base, na);
-
-	if (a < b)
-		return 1;
-
-	b += of_read_addr(size, ns);
-	if (a >= b)
-		return 1;
-
-	return 0;
-}
-
-static int of_bus_default_map(u32 *addr, const u32 *range,
-			      int na, int ns, int pna)
-{
-	u32 result[OF_MAX_ADDR_CELLS];
-	int i;
-
-	if (ns > 2) {
-		printk("of_device: Cannot handle size cells (%d) > 2.", ns);
-		return -EINVAL;
-	}
-
-	if (of_out_of_range(addr, range, range + na + pna, na, ns))
-		return -EINVAL;
-
-	/* Start with the parent range base.  */
-	memcpy(result, range + na, pna * 4);
-
-	/* Add in the child address offset.  */
-	for (i = 0; i < na; i++)
-		result[pna - 1 - i] +=
-			(addr[na - 1 - i] -
-			 range[na - 1 - i]);
-
-	memcpy(addr, result, pna * 4);
-
-	return 0;
-}
-
-static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
-{
-	if (flags)
-		return flags;
-	return IORESOURCE_MEM;
-}
+#include "of_device_common.h"
 
 /*
  * PCI bus specific translator
@@ -240,47 +92,6 @@
 	return flags;
 }
 
-/*
- * SBUS bus specific translator
- */
-
-static int of_bus_sbus_match(struct device_node *np)
-{
-	struct device_node *dp = np;
-
-	while (dp) {
-		if (!strcmp(dp->name, "sbus") ||
-		    !strcmp(dp->name, "sbi"))
-			return 1;
-
-		/* Have a look at use_1to1_mapping().  We're trying
-		 * to match SBUS if that's the top-level bus and we
-		 * don't have some intervening real bus that provides
-		 * ranges based translations.
-		 */
-		if (of_find_property(dp, "ranges", NULL) != NULL)
-			break;
-
-		dp = dp->parent;
-	}
-
-	return 0;
-}
-
-static void of_bus_sbus_count_cells(struct device_node *child,
-				   int *addrc, int *sizec)
-{
-	if (addrc)
-		*addrc = 2;
-	if (sizec)
-		*sizec = 1;
-}
-
-static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna)
-{
-	return of_bus_default_map(addr, range, na, ns, pna);
-}
-
 static unsigned long of_bus_sbus_get_flags(const u32 *addr, unsigned long flags)
 {
 	return IORESOURCE_MEM;
@@ -307,7 +118,7 @@
 		.addr_prop_name = "reg",
 		.match = of_bus_sbus_match,
 		.count_cells = of_bus_sbus_count_cells,
-		.map = of_bus_sbus_map,
+		.map = of_bus_default_map,
 		.get_flags = of_bus_sbus_get_flags,
 	},
 	/* Default */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_64.c linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,8 @@
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 
+#include "of_device_common.h"
+
 void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name)
 {
 	unsigned long ret = res->start + offset;
@@ -35,156 +37,6 @@
 }
 EXPORT_SYMBOL(of_iounmap);
 
-static int node_match(struct device *dev, void *data)
-{
-	struct of_device *op = to_of_device(dev);
-	struct device_node *dp = data;
-
-	return (op->node == dp);
-}
-
-struct of_device *of_find_device_by_node(struct device_node *dp)
-{
-	struct device *dev = bus_find_device(&of_platform_bus_type, NULL,
-					     dp, node_match);
-
-	if (dev)
-		return to_of_device(dev);
-
-	return NULL;
-}
-EXPORT_SYMBOL(of_find_device_by_node);
-
-unsigned int irq_of_parse_and_map(struct device_node *node, int index)
-{
-	struct of_device *op = of_find_device_by_node(node);
-
-	if (!op || index >= op->num_irqs)
-		return 0;
-
-	return op->irqs[index];
-}
-EXPORT_SYMBOL(irq_of_parse_and_map);
-
-/* Take the archdata values for IOMMU, STC, and HOSTDATA found in
- * BUS and propagate to all child of_device objects.
- */
-void of_propagate_archdata(struct of_device *bus)
-{
-	struct dev_archdata *bus_sd = &bus->dev.archdata;
-	struct device_node *bus_dp = bus->node;
-	struct device_node *dp;
-
-	for (dp = bus_dp->child; dp; dp = dp->sibling) {
-		struct of_device *op = of_find_device_by_node(dp);
-
-		op->dev.archdata.iommu = bus_sd->iommu;
-		op->dev.archdata.stc = bus_sd->stc;
-		op->dev.archdata.host_controller = bus_sd->host_controller;
-		op->dev.archdata.numa_node = bus_sd->numa_node;
-
-		if (dp->child)
-			of_propagate_archdata(op);
-	}
-}
-
-struct bus_type of_platform_bus_type;
-EXPORT_SYMBOL(of_platform_bus_type);
-
-static inline u64 of_read_addr(const u32 *cell, int size)
-{
-	u64 r = 0;
-	while (size--)
-		r = (r << 32) | *(cell++);
-	return r;
-}
-
-static void get_cells(struct device_node *dp, int *addrc, int *sizec)
-{
-	if (addrc)
-		*addrc = of_n_addr_cells(dp);
-	if (sizec)
-		*sizec = of_n_size_cells(dp);
-}
-
-/* Max address size we deal with */
-#define OF_MAX_ADDR_CELLS	4
-
-struct of_bus {
-	const char	*name;
-	const char	*addr_prop_name;
-	int		(*match)(struct device_node *parent);
-	void		(*count_cells)(struct device_node *child,
-				       int *addrc, int *sizec);
-	int		(*map)(u32 *addr, const u32 *range,
-			       int na, int ns, int pna);
-	unsigned long	(*get_flags)(const u32 *addr, unsigned long);
-};
-
-/*
- * Default translator (generic bus)
- */
-
-static void of_bus_default_count_cells(struct device_node *dev,
-				       int *addrc, int *sizec)
-{
-	get_cells(dev, addrc, sizec);
-}
-
-/* Make sure the least significant 64-bits are in-range.  Even
- * for 3 or 4 cell values it is a good enough approximation.
- */
-static int of_out_of_range(const u32 *addr, const u32 *base,
-			   const u32 *size, int na, int ns)
-{
-	u64 a = of_read_addr(addr, na);
-	u64 b = of_read_addr(base, na);
-
-	if (a < b)
-		return 1;
-
-	b += of_read_addr(size, ns);
-	if (a >= b)
-		return 1;
-
-	return 0;
-}
-
-static int of_bus_default_map(u32 *addr, const u32 *range,
-			      int na, int ns, int pna)
-{
-	u32 result[OF_MAX_ADDR_CELLS];
-	int i;
-
-	if (ns > 2) {
-		printk("of_device: Cannot handle size cells (%d) > 2.", ns);
-		return -EINVAL;
-	}
-
-	if (of_out_of_range(addr, range, range + na + pna, na, ns))
-		return -EINVAL;
-
-	/* Start with the parent range base.  */
-	memcpy(result, range + na, pna * 4);
-
-	/* Add in the child address offset.  */
-	for (i = 0; i < na; i++)
-		result[pna - 1 - i] +=
-			(addr[na - 1 - i] -
-			 range[na - 1 - i]);
-
-	memcpy(addr, result, pna * 4);
-
-	return 0;
-}
-
-static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
-{
-	if (flags)
-		return flags;
-	return IORESOURCE_MEM;
-}
-
 /*
  * PCI bus specific translator
  */
@@ -295,42 +147,6 @@
 }
 
 /*
- * SBUS bus specific translator
- */
-
-static int of_bus_sbus_match(struct device_node *np)
-{
-	struct device_node *dp = np;
-
-	while (dp) {
-		if (!strcmp(dp->name, "sbus") ||
-		    !strcmp(dp->name, "sbi"))
-			return 1;
-
-		/* Have a look at use_1to1_mapping().  We're trying
-		 * to match SBUS if that's the top-level bus and we
-		 * don't have some intervening real bus that provides
-		 * ranges based translations.
-		 */
-		if (of_find_property(dp, "ranges", NULL) != NULL)
-			break;
-
-		dp = dp->parent;
-	}
-
-	return 0;
-}
-
-static void of_bus_sbus_count_cells(struct device_node *child,
-				   int *addrc, int *sizec)
-{
-	if (addrc)
-		*addrc = 2;
-	if (sizec)
-		*sizec = 1;
-}
-
-/*
  * FHC/Central bus specific translator.
  *
  * This is just needed to hard-code the address and size cell
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_common.c linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_common.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_common.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,174 @@
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include "of_device_common.h"
+
+static int node_match(struct device *dev, void *data)
+{
+	struct of_device *op = to_of_device(dev);
+	struct device_node *dp = data;
+
+	return (op->node == dp);
+}
+
+struct of_device *of_find_device_by_node(struct device_node *dp)
+{
+	struct device *dev = bus_find_device(&of_platform_bus_type, NULL,
+					     dp, node_match);
+
+	if (dev)
+		return to_of_device(dev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_node);
+
+unsigned int irq_of_parse_and_map(struct device_node *node, int index)
+{
+	struct of_device *op = of_find_device_by_node(node);
+
+	if (!op || index >= op->num_irqs)
+		return 0;
+
+	return op->irqs[index];
+}
+EXPORT_SYMBOL(irq_of_parse_and_map);
+
+/* Take the archdata values for IOMMU, STC, and HOSTDATA found in
+ * BUS and propagate to all child of_device objects.
+ */
+void of_propagate_archdata(struct of_device *bus)
+{
+	struct dev_archdata *bus_sd = &bus->dev.archdata;
+	struct device_node *bus_dp = bus->node;
+	struct device_node *dp;
+
+	for (dp = bus_dp->child; dp; dp = dp->sibling) {
+		struct of_device *op = of_find_device_by_node(dp);
+
+		op->dev.archdata.iommu = bus_sd->iommu;
+		op->dev.archdata.stc = bus_sd->stc;
+		op->dev.archdata.host_controller = bus_sd->host_controller;
+		op->dev.archdata.numa_node = bus_sd->numa_node;
+
+		if (dp->child)
+			of_propagate_archdata(op);
+	}
+}
+
+struct bus_type of_platform_bus_type;
+EXPORT_SYMBOL(of_platform_bus_type);
+
+static void get_cells(struct device_node *dp, int *addrc, int *sizec)
+{
+	if (addrc)
+		*addrc = of_n_addr_cells(dp);
+	if (sizec)
+		*sizec = of_n_size_cells(dp);
+}
+
+/*
+ * Default translator (generic bus)
+ */
+
+void of_bus_default_count_cells(struct device_node *dev, int *addrc, int *sizec)
+{
+	get_cells(dev, addrc, sizec);
+}
+
+/* Make sure the least significant 64-bits are in-range.  Even
+ * for 3 or 4 cell values it is a good enough approximation.
+ */
+int of_out_of_range(const u32 *addr, const u32 *base,
+		    const u32 *size, int na, int ns)
+{
+	u64 a = of_read_addr(addr, na);
+	u64 b = of_read_addr(base, na);
+
+	if (a < b)
+		return 1;
+
+	b += of_read_addr(size, ns);
+	if (a >= b)
+		return 1;
+
+	return 0;
+}
+
+int of_bus_default_map(u32 *addr, const u32 *range, int na, int ns, int pna)
+{
+	u32 result[OF_MAX_ADDR_CELLS];
+	int i;
+
+	if (ns > 2) {
+		printk("of_device: Cannot handle size cells (%d) > 2.", ns);
+		return -EINVAL;
+	}
+
+	if (of_out_of_range(addr, range, range + na + pna, na, ns))
+		return -EINVAL;
+
+	/* Start with the parent range base.  */
+	memcpy(result, range + na, pna * 4);
+
+	/* Add in the child address offset.  */
+	for (i = 0; i < na; i++)
+		result[pna - 1 - i] +=
+			(addr[na - 1 - i] -
+			 range[na - 1 - i]);
+
+	memcpy(addr, result, pna * 4);
+
+	return 0;
+}
+
+unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags)
+{
+	if (flags)
+		return flags;
+	return IORESOURCE_MEM;
+}
+
+/*
+ * SBUS bus specific translator
+ */
+
+int of_bus_sbus_match(struct device_node *np)
+{
+	struct device_node *dp = np;
+
+	while (dp) {
+		if (!strcmp(dp->name, "sbus") ||
+		    !strcmp(dp->name, "sbi"))
+			return 1;
+
+		/* Have a look at use_1to1_mapping().  We're trying
+		 * to match SBUS if that's the top-level bus and we
+		 * don't have some intervening real bus that provides
+		 * ranges based translations.
+		 */
+		if (of_find_property(dp, "ranges", NULL) != NULL)
+			break;
+
+		dp = dp->parent;
+	}
+
+	return 0;
+}
+
+void of_bus_sbus_count_cells(struct device_node *child, int *addrc, int *sizec)
+{
+	if (addrc)
+		*addrc = 2;
+	if (sizec)
+		*sizec = 1;
+}
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_common.h linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_common.h
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/of_device_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/of_device_common.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,36 @@
+#ifndef _OF_DEVICE_COMMON_H
+#define _OF_DEVICE_COMMON_H
+
+static inline u64 of_read_addr(const u32 *cell, int size)
+{
+	u64 r = 0;
+	while (size--)
+		r = (r << 32) | *(cell++);
+	return r;
+}
+
+void of_bus_default_count_cells(struct device_node *dev, int *addrc,
+				int *sizec);
+int of_out_of_range(const u32 *addr, const u32 *base,
+		    const u32 *size, int na, int ns);
+int of_bus_default_map(u32 *addr, const u32 *range, int na, int ns, int pna);
+unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long flags);
+
+int of_bus_sbus_match(struct device_node *np);
+void of_bus_sbus_count_cells(struct device_node *child, int *addrc, int *sizec);
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS	4
+
+struct of_bus {
+	const char	*name;
+	const char	*addr_prop_name;
+	int		(*match)(struct device_node *parent);
+	void		(*count_cells)(struct device_node *child,
+				       int *addrc, int *sizec);
+	int		(*map)(u32 *addr, const u32 *range,
+			       int na, int ns, int pna);
+	unsigned long	(*get_flags)(const u32 *addr, unsigned long);
+};
+
+#endif /* _OF_DEVICE_COMMON_H */
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/pci.c linux-libre-2.6.31-gnu/arch/sparc/kernel/pci.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -711,19 +711,6 @@
 	pbus->resource[1] = &pbm->mem_space;
 }
 
-struct resource *pcibios_select_root(struct pci_dev *pdev, struct resource *r)
-{
-	struct pci_pbm_info *pbm = pdev->bus->sysdata;
-	struct resource *root = NULL;
-
-	if (r->flags & IORESOURCE_IO)
-		root = &pbm->io_space;
-	if (r->flags & IORESOURCE_MEM)
-		root = &pbm->mem_space;
-
-	return root;
-}
-
 void pcibios_update_irq(struct pci_dev *pdev, int irq)
 {
 }
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/pci_sun4v.c linux-libre-2.6.31-gnu/arch/sparc/kernel/pci_sun4v.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/pci_sun4v.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/pci_sun4v.c	2009-09-09 18:13:59.000000000 -0400
@@ -230,8 +230,9 @@
 		free_pages((unsigned long)cpu, order);
 }
 
-static dma_addr_t dma_4v_map_single(struct device *dev, void *ptr, size_t sz,
-				    enum dma_data_direction direction)
+static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
+				  unsigned long offset, size_t sz,
+				  enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	unsigned long flags, npages, oaddr;
@@ -245,7 +246,7 @@
 	if (unlikely(direction == DMA_NONE))
 		goto bad;
 
-	oaddr = (unsigned long)ptr;
+	oaddr = (unsigned long)(page_address(page) + offset);
 	npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
 	npages >>= IO_PAGE_SHIFT;
 
@@ -294,8 +295,8 @@
 	return DMA_ERROR_CODE;
 }
 
-static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
-				size_t sz, enum dma_data_direction direction)
+static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
+			      size_t sz, enum dma_data_direction direction)
 {
 	struct pci_pbm_info *pbm;
 	struct iommu *iommu;
@@ -537,8 +538,8 @@
 static const struct dma_ops sun4v_dma_ops = {
 	.alloc_coherent			= dma_4v_alloc_coherent,
 	.free_coherent			= dma_4v_free_coherent,
-	.map_single			= dma_4v_map_single,
-	.unmap_single			= dma_4v_unmap_single,
+	.map_page			= dma_4v_map_page,
+	.unmap_page			= dma_4v_unmap_page,
 	.map_sg				= dma_4v_map_sg,
 	.unmap_sg			= dma_4v_unmap_sg,
 	.sync_single_for_cpu		= dma_4v_sync_single_for_cpu,
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/prom_64.c linux-libre-2.6.31-gnu/arch/sparc/kernel/prom_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/prom_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/prom_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -374,75 +374,26 @@
 	return (tlb_type == spitfire ? "upa-portid" : "portid");
 }
 
-struct device_node *of_find_node_by_cpuid(int cpuid)
-{
-	struct device_node *dp;
-	const char *mid_prop = get_mid_prop();
-
-	for_each_node_by_type(dp, "cpu") {
-		int id = of_getintprop_default(dp, mid_prop, -1);
-		const char *this_mid_prop = mid_prop;
-
-		if (id < 0) {
-			this_mid_prop = "cpuid";
-			id = of_getintprop_default(dp, this_mid_prop, -1);
-		}
-
-		if (id < 0) {
-			prom_printf("OF: Serious problem, cpu lacks "
-				    "%s property", this_mid_prop);
-			prom_halt();
-		}
-		if (cpuid == id)
-			return dp;
-	}
-	return NULL;
-}
-
-void __init of_fill_in_cpu_data(void)
+static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg)
 {
 	struct device_node *dp;
 	const char *mid_prop;
 
-	if (tlb_type == hypervisor)
-		return;
-
 	mid_prop = get_mid_prop();
-	ncpus_probed = 0;
 	for_each_node_by_type(dp, "cpu") {
 		int cpuid = of_getintprop_default(dp, mid_prop, -1);
 		const char *this_mid_prop = mid_prop;
-		struct device_node *portid_parent;
-		int portid = -1;
+		void *ret;
 
-		portid_parent = NULL;
 		if (cpuid < 0) {
 			this_mid_prop = "cpuid";
 			cpuid = of_getintprop_default(dp, this_mid_prop, -1);
-			if (cpuid >= 0) {
-				int limit = 2;
-
-				portid_parent = dp;
-				while (limit--) {
-					portid_parent = portid_parent->parent;
-					if (!portid_parent)
-						break;
-					portid = of_getintprop_default(portid_parent,
-								       "portid", -1);
-					if (portid >= 0)
-						break;
-				}
-			}
 		}
-
 		if (cpuid < 0) {
 			prom_printf("OF: Serious problem, cpu lacks "
 				    "%s property", this_mid_prop);
 			prom_halt();
 		}
-
-		ncpus_probed++;
-
 #ifdef CONFIG_SMP
 		if (cpuid >= NR_CPUS) {
 			printk(KERN_WARNING "Ignoring CPU %d which is "
@@ -450,79 +401,142 @@
 			       cpuid, NR_CPUS);
 			continue;
 		}
-#else
-		/* On uniprocessor we only want the values for the
-		 * real physical cpu the kernel booted onto, however
-		 * cpu_data() only has one entry at index 0.
-		 */
-		if (cpuid != real_hard_smp_processor_id())
-			continue;
-		cpuid = 0;
 #endif
+		ret = func(dp, cpuid, arg);
+		if (ret)
+			return ret;
+	}
+	return NULL;
+}
 
-		cpu_data(cpuid).clock_tick =
-			of_getintprop_default(dp, "clock-frequency", 0);
+static void *check_cpu_node(struct device_node *dp, int cpuid, int id)
+{
+	if (id == cpuid)
+		return dp;
+	return NULL;
+}
 
-		if (portid_parent) {
-			cpu_data(cpuid).dcache_size =
-				of_getintprop_default(dp, "l1-dcache-size",
-						      16 * 1024);
-			cpu_data(cpuid).dcache_line_size =
-				of_getintprop_default(dp, "l1-dcache-line-size",
-						      32);
-			cpu_data(cpuid).icache_size =
-				of_getintprop_default(dp, "l1-icache-size",
-						      8 * 1024);
-			cpu_data(cpuid).icache_line_size =
-				of_getintprop_default(dp, "l1-icache-line-size",
-						      32);
-			cpu_data(cpuid).ecache_size =
-				of_getintprop_default(dp, "l2-cache-size", 0);
-			cpu_data(cpuid).ecache_line_size =
-				of_getintprop_default(dp, "l2-cache-line-size", 0);
-			if (!cpu_data(cpuid).ecache_size ||
-			    !cpu_data(cpuid).ecache_line_size) {
-				cpu_data(cpuid).ecache_size =
-					of_getintprop_default(portid_parent,
-							      "l2-cache-size",
-							      (4 * 1024 * 1024));
-				cpu_data(cpuid).ecache_line_size =
-					of_getintprop_default(portid_parent,
-							      "l2-cache-line-size", 64);
-			}
+struct device_node *of_find_node_by_cpuid(int cpuid)
+{
+	return of_iterate_over_cpus(check_cpu_node, cpuid);
+}
 
-			cpu_data(cpuid).core_id = portid + 1;
-			cpu_data(cpuid).proc_id = portid;
+static void *record_one_cpu(struct device_node *dp, int cpuid, int arg)
+{
+	ncpus_probed++;
 #ifdef CONFIG_SMP
-			sparc64_multi_core = 1;
+	set_cpu_present(cpuid, true);
+	set_cpu_possible(cpuid, true);
 #endif
-		} else {
-			cpu_data(cpuid).dcache_size =
-				of_getintprop_default(dp, "dcache-size", 16 * 1024);
-			cpu_data(cpuid).dcache_line_size =
-				of_getintprop_default(dp, "dcache-line-size", 32);
+	return NULL;
+}
 
-			cpu_data(cpuid).icache_size =
-				of_getintprop_default(dp, "icache-size", 16 * 1024);
-			cpu_data(cpuid).icache_line_size =
-				of_getintprop_default(dp, "icache-line-size", 32);
+void __init of_populate_present_mask(void)
+{
+	if (tlb_type == hypervisor)
+		return;
 
+	ncpus_probed = 0;
+	of_iterate_over_cpus(record_one_cpu, 0);
+}
+
+static void *fill_in_one_cpu(struct device_node *dp, int cpuid, int arg)
+{
+	struct device_node *portid_parent = NULL;
+	int portid = -1;
+
+	if (of_find_property(dp, "cpuid", NULL)) {
+		int limit = 2;
+
+		portid_parent = dp;
+		while (limit--) {
+			portid_parent = portid_parent->parent;
+			if (!portid_parent)
+				break;
+			portid = of_getintprop_default(portid_parent,
+						       "portid", -1);
+			if (portid >= 0)
+				break;
+		}
+	}
+
+#ifndef CONFIG_SMP
+	/* On uniprocessor we only want the values for the
+	 * real physical cpu the kernel booted onto, however
+	 * cpu_data() only has one entry at index 0.
+	 */
+	if (cpuid != real_hard_smp_processor_id())
+		return NULL;
+	cpuid = 0;
+#endif
+
+	cpu_data(cpuid).clock_tick =
+		of_getintprop_default(dp, "clock-frequency", 0);
+
+	if (portid_parent) {
+		cpu_data(cpuid).dcache_size =
+			of_getintprop_default(dp, "l1-dcache-size",
+					      16 * 1024);
+		cpu_data(cpuid).dcache_line_size =
+			of_getintprop_default(dp, "l1-dcache-line-size",
+					      32);
+		cpu_data(cpuid).icache_size =
+			of_getintprop_default(dp, "l1-icache-size",
+					      8 * 1024);
+		cpu_data(cpuid).icache_line_size =
+			of_getintprop_default(dp, "l1-icache-line-size",
+					      32);
+		cpu_data(cpuid).ecache_size =
+			of_getintprop_default(dp, "l2-cache-size", 0);
+		cpu_data(cpuid).ecache_line_size =
+			of_getintprop_default(dp, "l2-cache-line-size", 0);
+		if (!cpu_data(cpuid).ecache_size ||
+		    !cpu_data(cpuid).ecache_line_size) {
 			cpu_data(cpuid).ecache_size =
-				of_getintprop_default(dp, "ecache-size",
+				of_getintprop_default(portid_parent,
+						      "l2-cache-size",
 						      (4 * 1024 * 1024));
 			cpu_data(cpuid).ecache_line_size =
-				of_getintprop_default(dp, "ecache-line-size", 64);
-
-			cpu_data(cpuid).core_id = 0;
-			cpu_data(cpuid).proc_id = -1;
+				of_getintprop_default(portid_parent,
+						      "l2-cache-line-size", 64);
 		}
 
+		cpu_data(cpuid).core_id = portid + 1;
+		cpu_data(cpuid).proc_id = portid;
 #ifdef CONFIG_SMP
-		set_cpu_present(cpuid, true);
-		set_cpu_possible(cpuid, true);
+		sparc64_multi_core = 1;
 #endif
+	} else {
+		cpu_data(cpuid).dcache_size =
+			of_getintprop_default(dp, "dcache-size", 16 * 1024);
+		cpu_data(cpuid).dcache_line_size =
+			of_getintprop_default(dp, "dcache-line-size", 32);
+
+		cpu_data(cpuid).icache_size =
+			of_getintprop_default(dp, "icache-size", 16 * 1024);
+		cpu_data(cpuid).icache_line_size =
+			of_getintprop_default(dp, "icache-line-size", 32);
+
+		cpu_data(cpuid).ecache_size =
+			of_getintprop_default(dp, "ecache-size",
+					      (4 * 1024 * 1024));
+		cpu_data(cpuid).ecache_line_size =
+			of_getintprop_default(dp, "ecache-line-size", 64);
+
+		cpu_data(cpuid).core_id = 0;
+		cpu_data(cpuid).proc_id = -1;
 	}
 
+	return NULL;
+}
+
+void __init of_fill_in_cpu_data(void)
+{
+	if (tlb_type == hypervisor)
+		return;
+
+	of_iterate_over_cpus(fill_in_one_cpu, 0);
+
 	smp_fill_in_sib_core_maps();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/prom_common.c linux-libre-2.6.31-gnu/arch/sparc/kernel/prom_common.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/prom_common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/prom_common.c	2009-09-09 18:13:59.000000000 -0400
@@ -313,6 +313,4 @@
 
 	printk("PROM: Built device tree with %u bytes of memory.\n",
 	       prom_early_allocated);
-
-	of_fill_in_cpu_data();
 }
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/prom.h linux-libre-2.6.31-gnu/arch/sparc/kernel/prom.h
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/prom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/prom.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,6 @@
 
 extern char *build_path_component(struct device_node *dp);
 extern void of_console_init(void);
-extern void of_fill_in_cpu_data(void);
 
 extern unsigned int prom_early_allocated;
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/ptrace_32.c linux-libre-2.6.31-gnu/arch/sparc/kernel/ptrace_32.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/ptrace_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/ptrace_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,6 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/security.h>
 #include <linux/signal.h>
 #include <linux/regset.h>
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/ptrace_64.c linux-libre-2.6.31-gnu/arch/sparc/kernel/ptrace_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/ptrace_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/ptrace_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/security.h>
 #include <linux/seccomp.h>
 #include <linux/audit.h>
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/smp_64.c linux-libre-2.6.31-gnu/arch/sparc/kernel/smp_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/smp_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/smp_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,7 +20,8 @@
 #include <linux/cache.h>
 #include <linux/jiffies.h>
 #include <linux/profile.h>
-#include <linux/lmb.h>
+#include <linux/bootmem.h>
+#include <linux/vmalloc.h>
 #include <linux/cpu.h>
 
 #include <asm/head.h>
@@ -47,6 +48,8 @@
 #include <asm/ldc.h>
 #include <asm/hypervisor.h>
 
+#include "cpumap.h"
+
 int sparc64_multi_core __read_mostly;
 
 DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
@@ -278,7 +281,7 @@
 	return kern_base + (val - KERNBASE);
 }
 
-static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg)
+static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg, void **descrp)
 {
 	extern unsigned long sparc64_ttable_tl0;
 	extern unsigned long kern_locked_tte_data;
@@ -298,12 +301,12 @@
 		       "hvtramp_descr.\n");
 		return;
 	}
+	*descrp = hdesc;
 
 	hdesc->cpu = cpu;
 	hdesc->num_mappings = num_kernel_image_mappings;
 
 	tb = &trap_block[cpu];
-	tb->hdesc = hdesc;
 
 	hdesc->fault_info_va = (unsigned long) &tb->fault_info;
 	hdesc->fault_info_pa = kimage_addr_to_ra(&tb->fault_info);
@@ -341,12 +344,12 @@
 
 static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
 {
-	struct trap_per_cpu *tb = &trap_block[cpu];
 	unsigned long entry =
 		(unsigned long)(&sparc64_cpu_startup);
 	unsigned long cookie =
 		(unsigned long)(&cpu_new_thread);
 	struct task_struct *p;
+	void *descr = NULL;
 	int timeout, ret;
 
 	p = fork_idle(cpu);
@@ -359,7 +362,8 @@
 #if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
 		if (ldom_domaining_enabled)
 			ldom_startcpu_cpuid(cpu,
-					    (unsigned long) cpu_new_thread);
+					    (unsigned long) cpu_new_thread,
+					    &descr);
 		else
 #endif
 			prom_startcpu_cpuid(cpu, entry, cookie);
@@ -383,10 +387,7 @@
 	}
 	cpu_new_thread = NULL;
 
-	if (tb->hdesc) {
-		kfree(tb->hdesc);
-		tb->hdesc = NULL;
-	}
+	kfree(descr);
 
 	return ret;
 }
@@ -1315,6 +1316,8 @@
 	cpu_clear(cpu, cpu_online_map);
 	ipi_call_unlock();
 
+	cpu_map_rebuild();
+
 	return 0;
 }
 
@@ -1373,36 +1376,171 @@
 {
 }
 
-unsigned long __per_cpu_base __read_mostly;
-unsigned long __per_cpu_shift __read_mostly;
+/**
+ * pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
+ * @cpu: cpu to allocate for
+ * @size: size allocation in bytes
+ * @align: alignment
+ *
+ * Allocate @size bytes aligned at @align for cpu @cpu.  This wrapper
+ * does the right thing for NUMA regardless of the current
+ * configuration.
+ *
+ * RETURNS:
+ * Pointer to the allocated area on success, NULL on failure.
+ */
+static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
+					unsigned long align)
+{
+	const unsigned long goal = __pa(MAX_DMA_ADDRESS);
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+	int node = cpu_to_node(cpu);
+	void *ptr;
 
-EXPORT_SYMBOL(__per_cpu_base);
-EXPORT_SYMBOL(__per_cpu_shift);
+	if (!node_online(node) || !NODE_DATA(node)) {
+		ptr = __alloc_bootmem(size, align, goal);
+		pr_info("cpu %d has no node %d or node-local memory\n",
+			cpu, node);
+		pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
+			 cpu, size, __pa(ptr));
+	} else {
+		ptr = __alloc_bootmem_node(NODE_DATA(node),
+					   size, align, goal);
+		pr_debug("per cpu data for cpu%d %lu bytes on node%d at "
+			 "%016lx\n", cpu, size, node, __pa(ptr));
+	}
+	return ptr;
+#else
+	return __alloc_bootmem(size, align, goal);
+#endif
+}
 
-void __init real_setup_per_cpu_areas(void)
+static size_t pcpur_size __initdata;
+static void **pcpur_ptrs __initdata;
+
+static struct page * __init pcpur_get_page(unsigned int cpu, int pageno)
 {
-	unsigned long paddr, goal, size, i;
-	char *ptr;
+	size_t off = (size_t)pageno << PAGE_SHIFT;
 
-	/* Copy section for each CPU (we discard the original) */
-	goal = PERCPU_ENOUGH_ROOM;
+	if (off >= pcpur_size)
+		return NULL;
 
-	__per_cpu_shift = PAGE_SHIFT;
-	for (size = PAGE_SIZE; size < goal; size <<= 1UL)
-		__per_cpu_shift++;
+	return virt_to_page(pcpur_ptrs[cpu] + off);
+}
 
-	paddr = lmb_alloc(size * NR_CPUS, PAGE_SIZE);
-	if (!paddr) {
-		prom_printf("Cannot allocate per-cpu memory.\n");
-		prom_halt();
+#define PCPU_CHUNK_SIZE (4UL * 1024UL * 1024UL)
+
+static void __init pcpu_map_range(unsigned long start, unsigned long end,
+				  struct page *page)
+{
+	unsigned long pfn = page_to_pfn(page);
+	unsigned long pte_base;
+
+	BUG_ON((pfn<<PAGE_SHIFT)&(PCPU_CHUNK_SIZE - 1UL));
+
+	pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U |
+		    _PAGE_CP_4U | _PAGE_CV_4U |
+		    _PAGE_P_4U | _PAGE_W_4U);
+	if (tlb_type == hypervisor)
+		pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
+			    _PAGE_CP_4V | _PAGE_CV_4V |
+			    _PAGE_P_4V | _PAGE_W_4V);
+
+	while (start < end) {
+		pgd_t *pgd = pgd_offset_k(start);
+		unsigned long this_end;
+		pud_t *pud;
+		pmd_t *pmd;
+		pte_t *pte;
+
+		pud = pud_offset(pgd, start);
+		if (pud_none(*pud)) {
+			pmd_t *new;
+
+			new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+			pud_populate(&init_mm, pud, new);
+		}
+
+		pmd = pmd_offset(pud, start);
+		if (!pmd_present(*pmd)) {
+			pte_t *new;
+
+			new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+			pmd_populate_kernel(&init_mm, pmd, new);
+		}
+
+		pte = pte_offset_kernel(pmd, start);
+		this_end = (start + PMD_SIZE) & PMD_MASK;
+		if (this_end > end)
+			this_end = end;
+
+		while (start < this_end) {
+			unsigned long paddr = pfn << PAGE_SHIFT;
+
+			pte_val(*pte) = (paddr | pte_base);
+
+			start += PAGE_SIZE;
+			pte++;
+			pfn++;
+		}
 	}
+}
 
-	ptr = __va(paddr);
-	__per_cpu_base = ptr - __per_cpu_start;
+void __init setup_per_cpu_areas(void)
+{
+	size_t dyn_size, static_size = __per_cpu_end - __per_cpu_start;
+	static struct vm_struct vm;
+	unsigned long delta, cpu;
+	size_t pcpu_unit_size;
+	size_t ptrs_size;
 
-	for (i = 0; i < NR_CPUS; i++, ptr += size)
-		memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+	pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
+			       PERCPU_DYNAMIC_RESERVE);
+	dyn_size = pcpur_size - static_size - PERCPU_MODULE_RESERVE;
+
+
+	ptrs_size = PFN_ALIGN(nr_cpu_ids * sizeof(pcpur_ptrs[0]));
+	pcpur_ptrs = alloc_bootmem(ptrs_size);
+
+	for_each_possible_cpu(cpu) {
+		pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PCPU_CHUNK_SIZE,
+						     PCPU_CHUNK_SIZE);
+
+		free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size),
+			     PCPU_CHUNK_SIZE - pcpur_size);
+
+		memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size);
+	}
+
+	/* allocate address and map */
+	vm.flags = VM_ALLOC;
+	vm.size = nr_cpu_ids * PCPU_CHUNK_SIZE;
+	vm_area_register_early(&vm, PCPU_CHUNK_SIZE);
+
+	for_each_possible_cpu(cpu) {
+		unsigned long start = (unsigned long) vm.addr;
+		unsigned long end;
+
+		start += cpu * PCPU_CHUNK_SIZE;
+		end = start + PCPU_CHUNK_SIZE;
+		pcpu_map_range(start, end, virt_to_page(pcpur_ptrs[cpu]));
+	}
+
+	pcpu_unit_size = pcpu_setup_first_chunk(pcpur_get_page, static_size,
+						PERCPU_MODULE_RESERVE, dyn_size,
+						PCPU_CHUNK_SIZE, vm.addr, NULL);
+
+	free_bootmem(__pa(pcpur_ptrs), ptrs_size);
+
+	delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
+	for_each_possible_cpu(cpu) {
+		__per_cpu_offset(cpu) = delta + cpu * pcpu_unit_size;
+	}
 
 	/* Setup %g5 for the boot cpu.  */
 	__local_per_cpu_offset = __per_cpu_offset(smp_processor_id());
+
+	of_fill_in_cpu_data();
+	if (tlb_type == hypervisor)
+		mdesc_fill_in_cpu_data(cpu_all_mask);
 }
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/sun4d_smp.c linux-libre-2.6.31-gnu/arch/sparc/kernel/sun4d_smp.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/sun4d_smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/sun4d_smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -162,9 +162,6 @@
  */
  
 extern struct linux_prom_registers smp_penguin_ctable;
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
 
 void __init smp4d_boot_cpus(void)
 {
@@ -235,25 +232,6 @@
 	*prev = first;
 	local_flush_cache_all();
 
-	/* Free unneeded trap tables */
-	ClearPageReserved(virt_to_page(trapbase_cpu1));
-	init_page_count(virt_to_page(trapbase_cpu1));
-	free_page((unsigned long)trapbase_cpu1);
-	totalram_pages++;
-	num_physpages++;
-
-	ClearPageReserved(virt_to_page(trapbase_cpu2));
-	init_page_count(virt_to_page(trapbase_cpu2));
-	free_page((unsigned long)trapbase_cpu2);
-	totalram_pages++;
-	num_physpages++;
-
-	ClearPageReserved(virt_to_page(trapbase_cpu3));
-	init_page_count(virt_to_page(trapbase_cpu3));
-	free_page((unsigned long)trapbase_cpu3);
-	totalram_pages++;
-	num_physpages++;
-
 	/* Ok, they are spinning and ready to go. */
 	smp_processors_ready = 1;
 	sun4d_distribute_irqs();
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/sun4m_smp.c linux-libre-2.6.31-gnu/arch/sparc/kernel/sun4m_smp.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/sun4m_smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/sun4m_smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -121,9 +121,6 @@
  */
  
 extern struct linux_prom_registers smp_penguin_ctable;
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
 
 void __init smp4m_boot_cpus(void)
 {
@@ -193,29 +190,6 @@
 	*prev = first;
 	local_flush_cache_all();
 
-	/* Free unneeded trap tables */
-	if (!cpu_isset(1, cpu_present_map)) {
-		ClearPageReserved(virt_to_page(trapbase_cpu1));
-		init_page_count(virt_to_page(trapbase_cpu1));
-		free_page((unsigned long)trapbase_cpu1);
-		totalram_pages++;
-		num_physpages++;
-	}
-	if (!cpu_isset(2, cpu_present_map)) {
-		ClearPageReserved(virt_to_page(trapbase_cpu2));
-		init_page_count(virt_to_page(trapbase_cpu2));
-		free_page((unsigned long)trapbase_cpu2);
-		totalram_pages++;
-		num_physpages++;
-	}
-	if (!cpu_isset(3, cpu_present_map)) {
-		ClearPageReserved(virt_to_page(trapbase_cpu3));
-		init_page_count(virt_to_page(trapbase_cpu3));
-		free_page((unsigned long)trapbase_cpu3);
-		totalram_pages++;
-		num_physpages++;
-	}
-
 	/* Ok, they are spinning and ready to go. */
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/sys32.S linux-libre-2.6.31-gnu/arch/sparc/kernel/sys32.S
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/sys32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/sys32.S	2009-09-09 18:13:59.000000000 -0400
@@ -134,10 +134,12 @@
 SIGN1(sys32_getsockname, sys_getsockname, %o0)
 SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
 SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
-SIGN2(sys32_splice, sys_splice, %o0, %o1)
+SIGN2(sys32_splice, sys_splice, %o0, %o2)
 SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
 SIGN2(sys32_tee, sys_tee, %o0, %o1)
 SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
+SIGN1(sys32_truncate, sys_truncate, %o1)
+SIGN1(sys32_ftruncate, sys_ftruncate, %o1)
 
 	.globl		sys32_mmap2
 sys32_mmap2:
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/systbls_32.S linux-libre-2.6.31-gnu/arch/sparc/kernel/systbls_32.S
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/systbls_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/systbls_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -81,4 +81,6 @@
 /*305*/	.long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
 /*310*/	.long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
 /*315*/	.long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/	.long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv, sys_pwritev
+/*320*/	.long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
+/*325*/	.long sys_pwritev, sys_rt_tgsigqueueinfo
+
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/systbls_64.S linux-libre-2.6.31-gnu/arch/sparc/kernel/systbls_64.S
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/systbls_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/systbls_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -43,8 +43,8 @@
 /*110*/	.word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
 	.word sys32_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
-	.word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
-/*130*/	.word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
+	.word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys32_truncate
+/*130*/	.word sys32_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
 /*140*/	.word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
 	.word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write
@@ -82,7 +82,8 @@
 	.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
 /*310*/	.word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
 	.word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv, compat_sys_pwritev
+/*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
+	.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo
 
 #endif /* CONFIG_COMPAT */
 
@@ -156,4 +157,5 @@
 	.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
 /*310*/	.word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
 	.word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
-/*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv, sys_pwritev
+/*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
+	.word sys_pwritev, sys_rt_tgsigqueueinfo
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/time_64.c linux-libre-2.6.31-gnu/arch/sparc/kernel/time_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/time_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/time_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,6 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/string.h>
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/traps_32.c linux-libre-2.6.31-gnu/arch/sparc/kernel/traps_32.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/traps_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/traps_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kdebug.h>
 
 #include <asm/delay.h>
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/traps_64.c linux-libre-2.6.31-gnu/arch/sparc/kernel/traps_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/traps_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/traps_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -2509,6 +2509,7 @@
 }
 
 struct trap_per_cpu trap_block[NR_CPUS];
+EXPORT_SYMBOL(trap_block);
 
 /* This can get invoked before sched_init() so play it super safe
  * and use hard_smp_processor_id().
@@ -2530,84 +2531,97 @@
 void __init trap_init(void)
 {
 	/* Compile time sanity check. */
-	if (TI_TASK != offsetof(struct thread_info, task) ||
-	    TI_FLAGS != offsetof(struct thread_info, flags) ||
-	    TI_CPU != offsetof(struct thread_info, cpu) ||
-	    TI_FPSAVED != offsetof(struct thread_info, fpsaved) ||
-	    TI_KSP != offsetof(struct thread_info, ksp) ||
-	    TI_FAULT_ADDR != offsetof(struct thread_info, fault_address) ||
-	    TI_KREGS != offsetof(struct thread_info, kregs) ||
-	    TI_UTRAPS != offsetof(struct thread_info, utraps) ||
-	    TI_EXEC_DOMAIN != offsetof(struct thread_info, exec_domain) ||
-	    TI_REG_WINDOW != offsetof(struct thread_info, reg_window) ||
-	    TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) ||
-	    TI_GSR != offsetof(struct thread_info, gsr) ||
-	    TI_XFSR != offsetof(struct thread_info, xfsr) ||
-	    TI_USER_CNTD0 != offsetof(struct thread_info, user_cntd0) ||
-	    TI_USER_CNTD1 != offsetof(struct thread_info, user_cntd1) ||
-	    TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) ||
-	    TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) ||
-	    TI_PCR != offsetof(struct thread_info, pcr_reg) ||
-	    TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
-	    TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
-	    TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) ||
-	    TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) ||
-	    TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) ||
-	    TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) ||
-	    TI_FPREGS != offsetof(struct thread_info, fpregs) ||
-	    (TI_FPREGS & (64 - 1)))
-		thread_info_offsets_are_bolixed_dave();
+	BUILD_BUG_ON(TI_TASK != offsetof(struct thread_info, task) ||
+		     TI_FLAGS != offsetof(struct thread_info, flags) ||
+		     TI_CPU != offsetof(struct thread_info, cpu) ||
+		     TI_FPSAVED != offsetof(struct thread_info, fpsaved) ||
+		     TI_KSP != offsetof(struct thread_info, ksp) ||
+		     TI_FAULT_ADDR != offsetof(struct thread_info,
+					       fault_address) ||
+		     TI_KREGS != offsetof(struct thread_info, kregs) ||
+		     TI_UTRAPS != offsetof(struct thread_info, utraps) ||
+		     TI_EXEC_DOMAIN != offsetof(struct thread_info,
+						exec_domain) ||
+		     TI_REG_WINDOW != offsetof(struct thread_info,
+					       reg_window) ||
+		     TI_RWIN_SPTRS != offsetof(struct thread_info,
+					       rwbuf_stkptrs) ||
+		     TI_GSR != offsetof(struct thread_info, gsr) ||
+		     TI_XFSR != offsetof(struct thread_info, xfsr) ||
+		     TI_USER_CNTD0 != offsetof(struct thread_info,
+					       user_cntd0) ||
+		     TI_USER_CNTD1 != offsetof(struct thread_info,
+					       user_cntd1) ||
+		     TI_KERN_CNTD0 != offsetof(struct thread_info,
+					       kernel_cntd0) ||
+		     TI_KERN_CNTD1 != offsetof(struct thread_info,
+					       kernel_cntd1) ||
+		     TI_PCR != offsetof(struct thread_info, pcr_reg) ||
+		     TI_PRE_COUNT != offsetof(struct thread_info,
+					      preempt_count) ||
+		     TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
+		     TI_SYS_NOERROR != offsetof(struct thread_info,
+						syscall_noerror) ||
+		     TI_RESTART_BLOCK != offsetof(struct thread_info,
+						  restart_block) ||
+		     TI_KUNA_REGS != offsetof(struct thread_info,
+					      kern_una_regs) ||
+		     TI_KUNA_INSN != offsetof(struct thread_info,
+					      kern_una_insn) ||
+		     TI_FPREGS != offsetof(struct thread_info, fpregs) ||
+		     (TI_FPREGS & (64 - 1)));
 
-	if (TRAP_PER_CPU_THREAD != offsetof(struct trap_per_cpu, thread) ||
-	    (TRAP_PER_CPU_PGD_PADDR !=
-	     offsetof(struct trap_per_cpu, pgd_paddr)) ||
-	    (TRAP_PER_CPU_CPU_MONDO_PA !=
-	     offsetof(struct trap_per_cpu, cpu_mondo_pa)) ||
-	    (TRAP_PER_CPU_DEV_MONDO_PA !=
-	     offsetof(struct trap_per_cpu, dev_mondo_pa)) ||
-	    (TRAP_PER_CPU_RESUM_MONDO_PA !=
-	     offsetof(struct trap_per_cpu, resum_mondo_pa)) ||
-	    (TRAP_PER_CPU_RESUM_KBUF_PA !=
-	     offsetof(struct trap_per_cpu, resum_kernel_buf_pa)) ||
-	    (TRAP_PER_CPU_NONRESUM_MONDO_PA !=
-	     offsetof(struct trap_per_cpu, nonresum_mondo_pa)) ||
-	    (TRAP_PER_CPU_NONRESUM_KBUF_PA !=
-	     offsetof(struct trap_per_cpu, nonresum_kernel_buf_pa)) ||
-	    (TRAP_PER_CPU_FAULT_INFO !=
-	     offsetof(struct trap_per_cpu, fault_info)) ||
-	    (TRAP_PER_CPU_CPU_MONDO_BLOCK_PA !=
-	     offsetof(struct trap_per_cpu, cpu_mondo_block_pa)) ||
-	    (TRAP_PER_CPU_CPU_LIST_PA !=
-	     offsetof(struct trap_per_cpu, cpu_list_pa)) ||
-	    (TRAP_PER_CPU_TSB_HUGE !=
-	     offsetof(struct trap_per_cpu, tsb_huge)) ||
-	    (TRAP_PER_CPU_TSB_HUGE_TEMP !=
-	     offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
-	    (TRAP_PER_CPU_IRQ_WORKLIST_PA !=
-	     offsetof(struct trap_per_cpu, irq_worklist_pa)) ||
-	    (TRAP_PER_CPU_CPU_MONDO_QMASK !=
-	     offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
-	    (TRAP_PER_CPU_DEV_MONDO_QMASK !=
-	     offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
-	    (TRAP_PER_CPU_RESUM_QMASK !=
-	     offsetof(struct trap_per_cpu, resum_qmask)) ||
-	    (TRAP_PER_CPU_NONRESUM_QMASK !=
-	     offsetof(struct trap_per_cpu, nonresum_qmask)))
-		trap_per_cpu_offsets_are_bolixed_dave();
+	BUILD_BUG_ON(TRAP_PER_CPU_THREAD != offsetof(struct trap_per_cpu,
+						     thread) ||
+		     (TRAP_PER_CPU_PGD_PADDR !=
+		      offsetof(struct trap_per_cpu, pgd_paddr)) ||
+		     (TRAP_PER_CPU_CPU_MONDO_PA !=
+		      offsetof(struct trap_per_cpu, cpu_mondo_pa)) ||
+		     (TRAP_PER_CPU_DEV_MONDO_PA !=
+		      offsetof(struct trap_per_cpu, dev_mondo_pa)) ||
+		     (TRAP_PER_CPU_RESUM_MONDO_PA !=
+		      offsetof(struct trap_per_cpu, resum_mondo_pa)) ||
+		     (TRAP_PER_CPU_RESUM_KBUF_PA !=
+		      offsetof(struct trap_per_cpu, resum_kernel_buf_pa)) ||
+		     (TRAP_PER_CPU_NONRESUM_MONDO_PA !=
+		      offsetof(struct trap_per_cpu, nonresum_mondo_pa)) ||
+		     (TRAP_PER_CPU_NONRESUM_KBUF_PA !=
+		      offsetof(struct trap_per_cpu, nonresum_kernel_buf_pa)) ||
+		     (TRAP_PER_CPU_FAULT_INFO !=
+		      offsetof(struct trap_per_cpu, fault_info)) ||
+		     (TRAP_PER_CPU_CPU_MONDO_BLOCK_PA !=
+		      offsetof(struct trap_per_cpu, cpu_mondo_block_pa)) ||
+		     (TRAP_PER_CPU_CPU_LIST_PA !=
+		      offsetof(struct trap_per_cpu, cpu_list_pa)) ||
+		     (TRAP_PER_CPU_TSB_HUGE !=
+		      offsetof(struct trap_per_cpu, tsb_huge)) ||
+		     (TRAP_PER_CPU_TSB_HUGE_TEMP !=
+		      offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
+		     (TRAP_PER_CPU_IRQ_WORKLIST_PA !=
+		      offsetof(struct trap_per_cpu, irq_worklist_pa)) ||
+		     (TRAP_PER_CPU_CPU_MONDO_QMASK !=
+		      offsetof(struct trap_per_cpu, cpu_mondo_qmask)) ||
+		     (TRAP_PER_CPU_DEV_MONDO_QMASK !=
+		      offsetof(struct trap_per_cpu, dev_mondo_qmask)) ||
+		     (TRAP_PER_CPU_RESUM_QMASK !=
+		      offsetof(struct trap_per_cpu, resum_qmask)) ||
+		     (TRAP_PER_CPU_NONRESUM_QMASK !=
+		      offsetof(struct trap_per_cpu, nonresum_qmask)) ||
+		     (TRAP_PER_CPU_PER_CPU_BASE !=
+		      offsetof(struct trap_per_cpu, __per_cpu_base)));
 
-	if ((TSB_CONFIG_TSB !=
-	     offsetof(struct tsb_config, tsb)) ||
-	    (TSB_CONFIG_RSS_LIMIT !=
-	     offsetof(struct tsb_config, tsb_rss_limit)) ||
-	    (TSB_CONFIG_NENTRIES !=
-	     offsetof(struct tsb_config, tsb_nentries)) ||
-	    (TSB_CONFIG_REG_VAL !=
-	     offsetof(struct tsb_config, tsb_reg_val)) ||
-	    (TSB_CONFIG_MAP_VADDR !=
-	     offsetof(struct tsb_config, tsb_map_vaddr)) ||
-	    (TSB_CONFIG_MAP_PTE !=
-	     offsetof(struct tsb_config, tsb_map_pte)))
-		tsb_config_offsets_are_bolixed_dave();
+	BUILD_BUG_ON((TSB_CONFIG_TSB !=
+		      offsetof(struct tsb_config, tsb)) ||
+		     (TSB_CONFIG_RSS_LIMIT !=
+		      offsetof(struct tsb_config, tsb_rss_limit)) ||
+		     (TSB_CONFIG_NENTRIES !=
+		      offsetof(struct tsb_config, tsb_nentries)) ||
+		     (TSB_CONFIG_REG_VAL !=
+		      offsetof(struct tsb_config, tsb_reg_val)) ||
+		     (TSB_CONFIG_MAP_VADDR !=
+		      offsetof(struct tsb_config, tsb_map_vaddr)) ||
+		     (TSB_CONFIG_MAP_PTE !=
+		      offsetof(struct tsb_config, tsb_map_pte)));
 
 	/* Attach to the address space of init_task.  On SMP we
 	 * do this in smp.c:smp_callin for other cpus.
diff -druN linux-libre-2.6.30-gnu/arch/sparc/kernel/vio.c linux-libre-2.6.31-gnu/arch/sparc/kernel/vio.c
--- linux-libre-2.6.30-gnu/arch/sparc/kernel/vio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/kernel/vio.c	2009-09-09 18:13:59.000000000 -0400
@@ -224,7 +224,12 @@
 	if (!strcmp(type, "domain-services-port"))
 		bus_id_name = "ds";
 
-	if (strlen(bus_id_name) >= BUS_ID_SIZE - 4) {
+	/*
+	 * 20 char is the old driver-core name size limit, which is no more.
+	 * This check can probably be removed after review and possible
+	 * adaption of the vio users name length handling.
+	 */
+	if (strlen(bus_id_name) >= 20 - 4) {
 		printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n",
 		       bus_id_name);
 		return NULL;
diff -druN linux-libre-2.6.30-gnu/arch/sparc/mm/extable.c linux-libre-2.6.31-gnu/arch/sparc/mm/extable.c
--- linux-libre-2.6.30-gnu/arch/sparc/mm/extable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/mm/extable.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,10 @@
 	 *	word 3: last insn address + 4 bytes
 	 *	word 4: fixup code address
 	 *
+	 * Deleted entries are encoded as:
+	 *	word 1: unused
+	 *	word 2: -1
+	 *
 	 * See asm/uaccess.h for more details.
 	 */
 
@@ -39,6 +43,10 @@
 			continue;
 		}
 
+		/* A deleted entry; see trim_init_extable */
+		if (walk->fixup == -1)
+			continue;
+
 		if (walk->insn == value)
 			return walk;
 	}
@@ -57,6 +65,27 @@
         return NULL;
 }
 
+#ifdef CONFIG_MODULES
+/* We could memmove them around; easier to mark the trimmed ones. */
+void trim_init_extable(struct module *m)
+{
+	unsigned int i;
+	bool range;
+
+	for (i = 0; i < m->num_exentries; i += range ? 2 : 1) {
+		range = m->extable[i].fixup == 0;
+
+		if (within_module_init(m->extable[i].insn, m)) {
+			m->extable[i].fixup = -1;
+			if (range)
+				m->extable[i+1].fixup = -1;
+		}
+		if (range)
+			i++;
+	}
+}
+#endif /* CONFIG_MODULES */
+
 /* Special extable search, which handles ranges.  Returns fixup */
 unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
 {
diff -druN linux-libre-2.6.30-gnu/arch/sparc/mm/fault_32.c linux-libre-2.6.31-gnu/arch/sparc/mm/fault_32.c
--- linux-libre-2.6.30-gnu/arch/sparc/mm/fault_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/mm/fault_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -241,7 +241,7 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, address, write);
+	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -319,9 +319,10 @@
  */
 out_of_memory:
 	up_read(&mm->mmap_sem);
-	printk("VM: killing process %s\n", tsk->comm);
-	if (from_user)
-		do_group_exit(SIGKILL);
+	if (from_user) {
+		pagefault_out_of_memory();
+		return;
+	}
 	goto no_context;
 
 do_sigbus:
@@ -484,7 +485,7 @@
 		if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
-	switch (handle_mm_fault(mm, vma, address, write)) {
+	switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) {
 	case VM_FAULT_SIGBUS:
 	case VM_FAULT_OOM:
 		goto do_sigbus;
diff -druN linux-libre-2.6.30-gnu/arch/sparc/mm/fault_64.c linux-libre-2.6.31-gnu/arch/sparc/mm/fault_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/mm/fault_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/mm/fault_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -398,7 +398,7 @@
 			goto bad_area;
 	}
 
-	fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE));
+	fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
@@ -447,9 +447,10 @@
 out_of_memory:
 	insn = get_fault_insn(regs, insn);
 	up_read(&mm->mmap_sem);
-	printk("VM: killing process %s\n", current->comm);
-	if (!(regs->tstate & TSTATE_PRIV))
-		do_group_exit(SIGKILL);
+	if (!(regs->tstate & TSTATE_PRIV)) {
+		pagefault_out_of_memory();
+		return;
+	}
 	goto handle_kernel_fault;
 
 intr_or_no_mm:
diff -druN linux-libre-2.6.30-gnu/arch/sparc/mm/init_32.c linux-libre-2.6.31-gnu/arch/sparc/mm/init_32.c
--- linux-libre-2.6.30-gnu/arch/sparc/mm/init_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/mm/init_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -358,6 +358,7 @@
 	protection_map[15] = PAGE_SHARED;
 	btfixup();
 	prom_build_devicetree();
+	of_fill_in_cpu_data();
 	device_scan();
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/sparc/mm/init_64.c linux-libre-2.6.31-gnu/arch/sparc/mm/init_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/mm/init_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/mm/init_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -145,7 +145,8 @@
 	     cmp_p64, NULL);
 }
 
-unsigned long *sparc64_valid_addr_bitmap __read_mostly;
+unsigned long sparc64_valid_addr_bitmap[VALID_ADDR_BITMAP_BYTES /
+					sizeof(unsigned long)];
 EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
 
 /* Kernel physical address base and size in bytes.  */
@@ -1679,11 +1680,6 @@
 static void sun4u_pgprot_init(void);
 static void sun4v_pgprot_init(void);
 
-/* Dummy function */
-void __init setup_per_cpu_areas(void)
-{
-}
-
 void __init paging_init(void)
 {
 	unsigned long end_pfn, shift, phys_base;
@@ -1799,16 +1795,19 @@
 	if (tlb_type == hypervisor)
 		sun4v_ktsb_register();
 
-	/* We must setup the per-cpu areas before we pull in the
-	 * PROM and the MDESC.  The code there fills in cpu and
-	 * other information into per-cpu data structures.
-	 */
-	real_setup_per_cpu_areas();
-
 	prom_build_devicetree();
+	of_populate_present_mask();
+#ifndef CONFIG_SMP
+	of_fill_in_cpu_data();
+#endif
 
-	if (tlb_type == hypervisor)
+	if (tlb_type == hypervisor) {
 		sun4v_mdesc_init();
+		mdesc_populate_present_mask(cpu_all_mask);
+#ifndef CONFIG_SMP
+		mdesc_fill_in_cpu_data(cpu_all_mask);
+#endif
+	}
 
 	/* Once the OF device tree and MDESC have been setup, we know
 	 * the list of possible cpus.  Therefore we can allocate the
@@ -1876,7 +1875,7 @@
  * memory list again, and make sure it provides at least as much
  * memory as 'pavail' does.
  */
-static void __init setup_valid_addr_bitmap_from_pavail(void)
+static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap)
 {
 	int i;
 
@@ -1899,8 +1898,7 @@
 
 				if (new_start <= old_start &&
 				    new_end >= (old_start + PAGE_SIZE)) {
-					set_bit(old_start >> 22,
-						sparc64_valid_addr_bitmap);
+					set_bit(old_start >> 22, bitmap);
 					goto do_next_page;
 				}
 			}
@@ -1921,20 +1919,21 @@
 	}
 }
 
+static void __init patch_tlb_miss_handler_bitmap(void)
+{
+	extern unsigned int valid_addr_bitmap_insn[];
+	extern unsigned int valid_addr_bitmap_patch[];
+
+	valid_addr_bitmap_insn[1] = valid_addr_bitmap_patch[1];
+	mb();
+	valid_addr_bitmap_insn[0] = valid_addr_bitmap_patch[0];
+	flushi(&valid_addr_bitmap_insn[0]);
+}
+
 void __init mem_init(void)
 {
 	unsigned long codepages, datapages, initpages;
 	unsigned long addr, last;
-	int i;
-
-	i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
-	i += 1;
-	sparc64_valid_addr_bitmap = (unsigned long *) alloc_bootmem(i << 3);
-	if (sparc64_valid_addr_bitmap == NULL) {
-		prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
-		prom_halt();
-	}
-	memset(sparc64_valid_addr_bitmap, 0, i << 3);
 
 	addr = PAGE_OFFSET + kern_base;
 	last = PAGE_ALIGN(kern_size) + addr;
@@ -1943,15 +1942,19 @@
 		addr += PAGE_SIZE;
 	}
 
-	setup_valid_addr_bitmap_from_pavail();
+	setup_valid_addr_bitmap_from_pavail(sparc64_valid_addr_bitmap);
+	patch_tlb_miss_handler_bitmap();
 
 	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-	for_each_online_node(i) {
-		if (NODE_DATA(i)->node_spanned_pages != 0) {
-			totalram_pages +=
-				free_all_bootmem_node(NODE_DATA(i));
+	{
+		int i;
+		for_each_online_node(i) {
+			if (NODE_DATA(i)->node_spanned_pages != 0) {
+				totalram_pages +=
+					free_all_bootmem_node(NODE_DATA(i));
+			}
 		}
 	}
 #else
diff -druN linux-libre-2.6.30-gnu/arch/sparc/mm/init_64.h linux-libre-2.6.31-gnu/arch/sparc/mm/init_64.h
--- linux-libre-2.6.30-gnu/arch/sparc/mm/init_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/mm/init_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,10 +5,13 @@
  * marked non-static so that assembler code can get at them.
  */
 
-#define MAX_PHYS_ADDRESS	(1UL << 42UL)
-#define KPTE_BITMAP_CHUNK_SZ	(256UL * 1024UL * 1024UL)
+#define MAX_PHYS_ADDRESS	(1UL << 41UL)
+#define KPTE_BITMAP_CHUNK_SZ		(256UL * 1024UL * 1024UL)
 #define KPTE_BITMAP_BYTES	\
 	((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8)
+#define VALID_ADDR_BITMAP_CHUNK_SZ	(4UL * 1024UL * 1024UL)
+#define VALID_ADDR_BITMAP_BYTES	\
+	((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8)
 
 extern unsigned long kern_linear_pte_xor[2];
 extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
diff -druN linux-libre-2.6.30-gnu/arch/sparc/mm/srmmu.c linux-libre-2.6.31-gnu/arch/sparc/mm/srmmu.c
--- linux-libre-2.6.30-gnu/arch/sparc/mm/srmmu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/mm/srmmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/kdebug.h>
+#include <linux/log2.h>
 
 #include <asm/bitext.h>
 #include <asm/page.h>
@@ -349,7 +350,7 @@
 		    vaddr, srmmu_nocache_end);
 		BUG();
 	}
-	if (size & (size-1)) {
+	if (!is_power_of_2(size)) {
 		printk("Size 0x%x is not a power of 2\n", size);
 		BUG();
 	}
diff -druN linux-libre-2.6.30-gnu/arch/sparc/prom/misc_64.c linux-libre-2.6.31-gnu/arch/sparc/prom/misc_64.c
--- linux-libre-2.6.30-gnu/arch/sparc/prom/misc_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/prom/misc_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -88,7 +88,7 @@
 /* Drop into the prom, but completely terminate the program.
  * No chance of continuing.
  */
-void prom_halt(void)
+void notrace prom_halt(void)
 {
 #ifdef CONFIG_SUN_LDOMS
 	if (ldom_domaining_enabled)
diff -druN linux-libre-2.6.30-gnu/arch/sparc/prom/printf.c linux-libre-2.6.31-gnu/arch/sparc/prom/printf.c
--- linux-libre-2.6.30-gnu/arch/sparc/prom/printf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/sparc/prom/printf.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,14 +14,14 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/compiler.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
 static char ppbuf[1024];
 
-void
-prom_write(const char *buf, unsigned int n)
+void notrace prom_write(const char *buf, unsigned int n)
 {
 	char ch;
 
@@ -33,8 +33,7 @@
 	}
 }
 
-void
-prom_printf(const char *fmt, ...)
+void notrace prom_printf(const char *fmt, ...)
 {
 	va_list args;
 	int i;
diff -druN linux-libre-2.6.30-gnu/arch/um/drivers/net_kern.c linux-libre-2.6.31-gnu/arch/um/drivers/net_kern.c
--- linux-libre-2.6.30-gnu/arch/um/drivers/net_kern.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/drivers/net_kern.c	2009-09-09 18:13:59.000000000 -0400
@@ -360,7 +360,7 @@
 
 static void net_device_release(struct device *dev)
 {
-	struct uml_net *device = dev->driver_data;
+	struct uml_net *device = dev_get_drvdata(dev);
 	struct net_device *netdev = device->dev;
 	struct uml_net_private *lp = netdev_priv(netdev);
 
@@ -440,7 +440,7 @@
 	device->pdev.id = n;
 	device->pdev.name = DRIVER_NAME;
 	device->pdev.dev.release = net_device_release;
-	device->pdev.dev.driver_data = device;
+	dev_set_drvdata(&device->pdev.dev, device);
 	if (platform_device_register(&device->pdev))
 		goto out_free_netdev;
 	SET_NETDEV_DEV(dev,&device->pdev.dev);
diff -druN linux-libre-2.6.30-gnu/arch/um/drivers/slip_kern.c linux-libre-2.6.31-gnu/arch/um/drivers/slip_kern.c
--- linux-libre-2.6.30-gnu/arch/um/drivers/slip_kern.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/drivers/slip_kern.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,6 @@
 
 	slip_proto_init(&spri->slip);
 
-	dev->init = NULL;
 	dev->hard_header_len = 0;
 	dev->header_ops = NULL;
 	dev->addr_len = 0;
diff -druN linux-libre-2.6.30-gnu/arch/um/drivers/slirp_kern.c linux-libre-2.6.31-gnu/arch/um/drivers/slirp_kern.c
--- linux-libre-2.6.30-gnu/arch/um/drivers/slirp_kern.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/drivers/slirp_kern.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,6 @@
 
 	slip_proto_init(&spri->slip);
 
-	dev->init = NULL;
 	dev->hard_header_len = 0;
 	dev->header_ops = NULL;
 	dev->addr_len = 0;
diff -druN linux-libre-2.6.30-gnu/arch/um/drivers/ubd_kern.c linux-libre-2.6.31-gnu/arch/um/drivers/ubd_kern.c
--- linux-libre-2.6.30-gnu/arch/um/drivers/ubd_kern.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/drivers/ubd_kern.c	2009-09-09 18:13:59.000000000 -0400
@@ -451,23 +451,6 @@
 
 /* Only changed by ubd_init, which is an initcall. */
 static int thread_fd = -1;
-
-static void ubd_end_request(struct request *req, int bytes, int error)
-{
-	blk_end_request(req, error, bytes);
-}
-
-/* Callable only from interrupt context - otherwise you need to do
- * spin_lock_irq()/spin_lock_irqsave() */
-static inline void ubd_finish(struct request *req, int bytes)
-{
-	if(bytes < 0){
-		ubd_end_request(req, 0, -EIO);
-		return;
-	}
-	ubd_end_request(req, bytes, 0);
-}
-
 static LIST_HEAD(restart);
 
 /* XXX - move this inside ubd_intr. */
@@ -475,7 +458,6 @@
 static void ubd_handler(void)
 {
 	struct io_thread_req *req;
-	struct request *rq;
 	struct ubd *ubd;
 	struct list_head *list, *next_ele;
 	unsigned long flags;
@@ -492,10 +474,7 @@
 			return;
 		}
 
-		rq = req->req;
-		rq->nr_sectors -= req->length >> 9;
-		if(rq->nr_sectors == 0)
-			ubd_finish(rq, rq->hard_nr_sectors << 9);
+		blk_end_request(req->req, 0, req->length);
 		kfree(req);
 	}
 	reactivate_fd(thread_fd, UBD_IRQ);
@@ -799,7 +778,7 @@
 
 static void ubd_device_release(struct device *dev)
 {
-	struct ubd *ubd_dev = dev->driver_data;
+	struct ubd *ubd_dev = dev_get_drvdata(dev);
 
 	blk_cleanup_queue(ubd_dev->queue);
 	*ubd_dev = ((struct ubd) DEFAULT_UBD);
@@ -828,7 +807,7 @@
 		ubd_devs[unit].pdev.id   = unit;
 		ubd_devs[unit].pdev.name = DRIVER_NAME;
 		ubd_devs[unit].pdev.dev.release = ubd_device_release;
-		ubd_devs[unit].pdev.dev.driver_data = &ubd_devs[unit];
+		dev_set_drvdata(&ubd_devs[unit].pdev.dev, &ubd_devs[unit]);
 		platform_device_register(&ubd_devs[unit].pdev);
 		disk->driverfs_dev = &ubd_devs[unit].pdev.dev;
 	}
@@ -1243,27 +1222,26 @@
 {
 	struct io_thread_req *io_req;
 	struct request *req;
-	int n, last_sectors;
+	sector_t sector;
+	int n;
 
 	while(1){
 		struct ubd *dev = q->queuedata;
 		if(dev->end_sg == 0){
-			struct request *req = elv_next_request(q);
+			struct request *req = blk_fetch_request(q);
 			if(req == NULL)
 				return;
 
 			dev->request = req;
-			blkdev_dequeue_request(req);
 			dev->start_sg = 0;
 			dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
 		}
 
 		req = dev->request;
-		last_sectors = 0;
+		sector = blk_rq_pos(req);
 		while(dev->start_sg < dev->end_sg){
 			struct scatterlist *sg = &dev->sg[dev->start_sg];
 
-			req->sector += last_sectors;
 			io_req = kmalloc(sizeof(struct io_thread_req),
 					 GFP_ATOMIC);
 			if(io_req == NULL){
@@ -1272,10 +1250,10 @@
 				return;
 			}
 			prepare_request(req, io_req,
-					(unsigned long long) req->sector << 9,
+					(unsigned long long)sector << 9,
 					sg->offset, sg->length, sg_page(sg));
 
-			last_sectors = sg->length >> 9;
+			sector += sg->length >> 9;
 			n = os_write_file(thread_fd, &io_req,
 					  sizeof(struct io_thread_req *));
 			if(n != sizeof(struct io_thread_req *)){
diff -druN linux-libre-2.6.30-gnu/arch/um/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/um/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/um/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -79,14 +79,14 @@
 }
 
 static inline void
-dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
 		enum dma_data_direction direction)
 {
 	BUG();
 }
 
 static inline void
-dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 	    enum dma_data_direction direction)
 {
 	BUG();
diff -druN linux-libre-2.6.30-gnu/arch/um/include/asm/page.h linux-libre-2.6.31-gnu/arch/um/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/um/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -116,7 +116,7 @@
 #define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #endif	/* __ASSEMBLY__ */
 #endif	/* __UM_PAGE_H */
diff -druN linux-libre-2.6.30-gnu/arch/um/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/um/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/um/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 	__free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte)				\
+#define __pte_free_tlb(tlb,pte, address)		\
 do {							\
 	pgtable_page_dtor(pte);				\
 	tlb_remove_page((tlb),(pte));			\
@@ -53,7 +53,7 @@
 	free_page((unsigned long)pmd);
 }
 
-#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+#define __pmd_free_tlb(tlb,x, address)   tlb_remove_page((tlb),virt_to_page(x))
 #endif
 
 #define check_pgt_cache()	do { } while (0)
diff -druN linux-libre-2.6.30-gnu/arch/um/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/um/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/um/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,16 +53,21 @@
 #else
 # define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
 #endif
+#define MODULES_VADDR	VMALLOC_START
+#define MODULES_END	VMALLOC_END
+#define MODULES_LEN	(MODULES_VADDR - MODULES_END)
 
 #define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
-
+#define __PAGE_KERNEL_EXEC                                              \
+	 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC)
 
 /*
  * The i386 can't do page protection for execute, and considers that the same
diff -druN linux-libre-2.6.30-gnu/arch/um/include/asm/suspend.h linux-libre-2.6.31-gnu/arch/um/include/asm/suspend.h
--- linux-libre-2.6.30-gnu/arch/um/include/asm/suspend.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-#ifndef __UM_SUSPEND_H
-#define __UM_SUSPEND_H
-
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/um/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/um/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/um/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,7 @@
 	.exec_domain =	&default_exec_domain,	\
 	.flags =		0,		\
 	.cpu =		0,			\
-	.preempt_count =	1,		\
+	.preempt_count = INIT_PREEMPT_COUNT,	\
 	.addr_limit =	KERNEL_DS,		\
 	.restart_block =  {			\
 		.fn =  do_no_restart_syscall,	\
diff -druN linux-libre-2.6.30-gnu/arch/um/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/um/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/um/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -116,11 +116,11 @@
 		__tlb_remove_tlb_entry(tlb, ptep, address);	\
 	} while (0)
 
-#define pte_free_tlb(tlb, ptep) __pte_free_tlb(tlb, ptep)
+#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr)
 
-#define pud_free_tlb(tlb, pudp) __pud_free_tlb(tlb, pudp)
+#define pud_free_tlb(tlb, pudp, addr) __pud_free_tlb(tlb, pudp, addr)
 
-#define pmd_free_tlb(tlb, pmdp) __pmd_free_tlb(tlb, pmdp)
+#define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr)
 
 #define tlb_migrate_finish(mm) do {} while (0)
 
diff -druN linux-libre-2.6.30-gnu/arch/um/include/shared/init.h linux-libre-2.6.31-gnu/arch/um/include/shared/init.h
--- linux-libre-2.6.30-gnu/arch/um/include/shared/init.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/shared/init.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,7 @@
  * sign followed by value, e.g.:
  *
  * static int init_variable __initdata = 0;
- * static char linux_logo[] __initdata = { 0x32, 0x36, ... };
+ * static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
  *
  * Don't forget to initialize data not at file scope, i.e. within a function,
  * as gcc otherwise puts the data into the bss section and not into the init
diff -druN linux-libre-2.6.30-gnu/arch/um/include/shared/net_user.h linux-libre-2.6.31-gnu/arch/um/include/shared/net_user.h
--- linux-libre-2.6.30-gnu/arch/um/include/shared/net_user.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/include/shared/net_user.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,7 @@
 
 #define ETH_ADDR_LEN (6)
 #define ETH_HEADER_ETHERTAP (16)
-#define ETH_HEADER_OTHER (14)
+#define ETH_HEADER_OTHER (26) /* 14 for ethernet + VLAN + MPLS for crazy people */
 #define ETH_MAX_PACKET (1500)
 
 #define UML_NET_VERSION (4)
diff -druN linux-libre-2.6.30-gnu/arch/um/kernel/init_task.c linux-libre-2.6.31-gnu/arch/um/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/um/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,11 +10,8 @@
 #include "linux/mqueue.h"
 #include "asm/uaccess.h"
 
-struct mm_struct init_mm = INIT_MM(init_mm);
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-EXPORT_SYMBOL(init_mm);
-
 /*
  * Initial task structure.
  *
diff -druN linux-libre-2.6.30-gnu/arch/um/kernel/irq.c linux-libre-2.6.31-gnu/arch/um/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/um/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -358,7 +358,7 @@
 EXPORT_SYMBOL(reactivate_fd);
 
 /*
- * hw_interrupt_type must define (startup || enable) &&
+ * irq_chip must define (startup || enable) &&
  * (shutdown || disable) && end
  */
 static void dummy(unsigned int irq)
@@ -366,7 +366,7 @@
 }
 
 /* This is used for everything else than the timer. */
-static struct hw_interrupt_type normal_irq_type = {
+static struct irq_chip normal_irq_type = {
 	.typename = "SIGIO",
 	.release = free_irq_by_irq_and_dev,
 	.disable = dummy,
@@ -375,7 +375,7 @@
 	.end = dummy
 };
 
-static struct hw_interrupt_type SIGVTALRM_irq_type = {
+static struct irq_chip SIGVTALRM_irq_type = {
 	.typename = "SIGVTALRM",
 	.release = free_irq_by_irq_and_dev,
 	.shutdown = dummy, /* never called */
diff -druN linux-libre-2.6.30-gnu/arch/um/kernel/sysrq.c linux-libre-2.6.31-gnu/arch/um/kernel/sysrq.c
--- linux-libre-2.6.30-gnu/arch/um/kernel/sysrq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/kernel/sysrq.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,8 +70,8 @@
 		if (kstack_end(stack))
 			break;
 		if (i && ((i % 8) == 0))
-			printk("\n" KERN_INFO "       ");
-		printk("%08lx ", *stack++);
+			printk(KERN_INFO "       ");
+		printk(KERN_CONT "%08lx ", *stack++);
 	}
 
 	show_trace(task, esp);
diff -druN linux-libre-2.6.30-gnu/arch/um/kernel/trap.c linux-libre-2.6.31-gnu/arch/um/kernel/trap.c
--- linux-libre-2.6.30-gnu/arch/um/kernel/trap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/kernel/trap.c	2009-09-09 18:13:59.000000000 -0400
@@ -65,7 +65,7 @@
 	do {
 		int fault;
 
-		fault = handle_mm_fault(mm, vma, address, is_write);
+		fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0);
 		if (unlikely(fault & VM_FAULT_ERROR)) {
 			if (fault & VM_FAULT_OOM) {
 				goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/um/sys-i386/Makefile linux-libre-2.6.31-gnu/arch/um/sys-i386/Makefile
--- linux-libre-2.6.30-gnu/arch/um/sys-i386/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/sys-i386/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,7 @@
 
 subarch-obj-y = lib/semaphore_32.o lib/string_32.o
 subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o
+subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
 USER_OBJS := bugs.o ptrace_user.o fault.o
 
diff -druN linux-libre-2.6.30-gnu/arch/um/sys-i386/stub.S linux-libre-2.6.31-gnu/arch/um/sys-i386/stub.S
--- linux-libre-2.6.30-gnu/arch/um/sys-i386/stub.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/sys-i386/stub.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #include "as-layout.h"
 
 	.globl syscall_stub
-.section .__syscall_stub, "x"
+.section .__syscall_stub, "ax"
 
 	.globl batch_syscall_stub
 batch_syscall_stub:
diff -druN linux-libre-2.6.30-gnu/arch/um/sys-x86_64/asm/elf.h linux-libre-2.6.31-gnu/arch/um/sys-x86_64/asm/elf.h
--- linux-libre-2.6.30-gnu/arch/um/sys-x86_64/asm/elf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/sys-x86_64/asm/elf.h	2009-09-09 18:13:59.000000000 -0400
@@ -66,28 +66,28 @@
 	PT_REGS_R15(regs) = 0; \
 } while (0)
 
-#define ELF_CORE_COPY_REGS(pr_reg, regs)		\
-	(pr_reg)[0] = (regs)->regs.gp[0];			\
-	(pr_reg)[1] = (regs)->regs.gp[1];			\
-	(pr_reg)[2] = (regs)->regs.gp[2];			\
-	(pr_reg)[3] = (regs)->regs.gp[3];			\
-	(pr_reg)[4] = (regs)->regs.gp[4];			\
-	(pr_reg)[5] = (regs)->regs.gp[5];			\
-	(pr_reg)[6] = (regs)->regs.gp[6];			\
-	(pr_reg)[7] = (regs)->regs.gp[7];			\
-	(pr_reg)[8] = (regs)->regs.gp[8];			\
-	(pr_reg)[9] = (regs)->regs.gp[9];			\
-	(pr_reg)[10] = (regs)->regs.gp[10];			\
-	(pr_reg)[11] = (regs)->regs.gp[11];			\
-	(pr_reg)[12] = (regs)->regs.gp[12];			\
-	(pr_reg)[13] = (regs)->regs.gp[13];			\
-	(pr_reg)[14] = (regs)->regs.gp[14];			\
-	(pr_reg)[15] = (regs)->regs.gp[15];			\
-	(pr_reg)[16] = (regs)->regs.gp[16];			\
-	(pr_reg)[17] = (regs)->regs.gp[17];			\
-	(pr_reg)[18] = (regs)->regs.gp[18];			\
-	(pr_reg)[19] = (regs)->regs.gp[19];			\
-	(pr_reg)[20] = (regs)->regs.gp[20];			\
+#define ELF_CORE_COPY_REGS(pr_reg, _regs)		\
+	(pr_reg)[0] = (_regs)->regs.gp[0];			\
+	(pr_reg)[1] = (_regs)->regs.gp[1];			\
+	(pr_reg)[2] = (_regs)->regs.gp[2];			\
+	(pr_reg)[3] = (_regs)->regs.gp[3];			\
+	(pr_reg)[4] = (_regs)->regs.gp[4];			\
+	(pr_reg)[5] = (_regs)->regs.gp[5];			\
+	(pr_reg)[6] = (_regs)->regs.gp[6];			\
+	(pr_reg)[7] = (_regs)->regs.gp[7];			\
+	(pr_reg)[8] = (_regs)->regs.gp[8];			\
+	(pr_reg)[9] = (_regs)->regs.gp[9];			\
+	(pr_reg)[10] = (_regs)->regs.gp[10];			\
+	(pr_reg)[11] = (_regs)->regs.gp[11];			\
+	(pr_reg)[12] = (_regs)->regs.gp[12];			\
+	(pr_reg)[13] = (_regs)->regs.gp[13];			\
+	(pr_reg)[14] = (_regs)->regs.gp[14];			\
+	(pr_reg)[15] = (_regs)->regs.gp[15];			\
+	(pr_reg)[16] = (_regs)->regs.gp[16];			\
+	(pr_reg)[17] = (_regs)->regs.gp[17];			\
+	(pr_reg)[18] = (_regs)->regs.gp[18];			\
+	(pr_reg)[19] = (_regs)->regs.gp[19];			\
+	(pr_reg)[20] = (_regs)->regs.gp[20];			\
 	(pr_reg)[21] = current->thread.arch.fs;			\
 	(pr_reg)[22] = 0;					\
 	(pr_reg)[23] = 0;					\
diff -druN linux-libre-2.6.30-gnu/arch/um/sys-x86_64/Makefile linux-libre-2.6.31-gnu/arch/um/sys-x86_64/Makefile
--- linux-libre-2.6.30-gnu/arch/um/sys-x86_64/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/sys-x86_64/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,10 +8,8 @@
 	setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
 	sysrq.o ksyms.o tls.o
 
-obj-$(CONFIG_MODULES) += um_module.o
-
 subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o
+subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
 ldt-y = ../sys-i386/ldt.o
 
diff -druN linux-libre-2.6.30-gnu/arch/um/sys-x86_64/stub.S linux-libre-2.6.31-gnu/arch/um/sys-x86_64/stub.S
--- linux-libre-2.6.30-gnu/arch/um/sys-x86_64/stub.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/sys-x86_64/stub.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #include "as-layout.h"
 
 	.globl syscall_stub
-.section .__syscall_stub, "x"
+.section .__syscall_stub, "ax"
 syscall_stub:
 	syscall
 	/* We don't have 64-bit constants, so this constructs the address
diff -druN linux-libre-2.6.30-gnu/arch/um/sys-x86_64/um_module.c linux-libre-2.6.31-gnu/arch/um/sys-x86_64/um_module.c
--- linux-libre-2.6.30-gnu/arch/um/sys-x86_64/um_module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/um/sys-x86_64/um_module.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-#include <linux/vmalloc.h>
-#include <linux/moduleloader.h>
-
-/* Copied from i386 arch/i386/kernel/module.c */
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc_exec(size);
-}
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-	/*
-	 * FIXME: If module_region == mod->init_region, trim exception
-	 * table entries.
-	 */
-}
-
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/a20.c linux-libre-2.6.31-gnu/arch/x86/boot/a20.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/a20.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/a20.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
- *   Copyright 2009 Intel Corporation
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -90,8 +90,11 @@
 
 static void enable_a20_bios(void)
 {
-	asm volatile("pushfl; int $0x15; popfl"
-		     : : "a" ((u16)0x2401));
+	struct biosregs ireg;
+
+	initregs(&ireg);
+	ireg.ax = 0x2401;
+	intcall(0x15, &ireg, NULL);
 }
 
 static void enable_a20_kbc(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/apm.c linux-libre-2.6.31-gnu/arch/x86/boot/apm.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/apm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/apm.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   Original APM BIOS checking by Stephen Rothwell, May 1994
  *   (sfr@canb.auug.org.au)
@@ -19,75 +20,56 @@
 
 int query_apm_bios(void)
 {
-	u16 ax, bx, cx, dx, di;
-	u32 ebx, esi;
-	u8 err;
+	struct biosregs ireg, oreg;
 
 	/* APM BIOS installation check */
-	ax = 0x5300;
-	bx = cx = 0;
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
-		     : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
-		     : : "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x53;
+	intcall(0x15, &ireg, &oreg);
 
-	if (err)
+	if (oreg.flags & X86_EFLAGS_CF)
 		return -1;		/* No APM BIOS */
 
-	if (bx != 0x504d)	/* "PM" signature */
+	if (oreg.bx != 0x504d)		/* "PM" signature */
 		return -1;
 
-	if (!(cx & 0x02))		/* 32 bits supported? */
+	if (!(oreg.cx & 0x02))		/* 32 bits supported? */
 		return -1;
 
 	/* Disconnect first, just in case */
-	ax = 0x5304;
-	bx = 0;
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
-		     : "+a" (ax), "+b" (bx)
-		     : : "ecx", "edx", "esi", "edi");
-
-	/* Paranoia */
-	ebx = esi = 0;
-	cx = dx = di = 0;
+	ireg.al = 0x04;
+	intcall(0x15, &ireg, NULL);
 
 	/* 32-bit connect */
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6"
-		     : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx),
-		       "+S" (esi), "+D" (di), "=m" (err)
-		     : "a" (0x5303));
+	ireg.al = 0x03;
+	intcall(0x15, &ireg, &oreg);
 
-	boot_params.apm_bios_info.cseg = ax;
-	boot_params.apm_bios_info.offset = ebx;
-	boot_params.apm_bios_info.cseg_16 = cx;
-	boot_params.apm_bios_info.dseg = dx;
-	boot_params.apm_bios_info.cseg_len = (u16)esi;
-	boot_params.apm_bios_info.cseg_16_len = esi >> 16;
-	boot_params.apm_bios_info.dseg_len = di;
+	boot_params.apm_bios_info.cseg        = oreg.ax;
+	boot_params.apm_bios_info.offset      = oreg.ebx;
+	boot_params.apm_bios_info.cseg_16     = oreg.cx;
+	boot_params.apm_bios_info.dseg        = oreg.dx;
+	boot_params.apm_bios_info.cseg_len    = oreg.si;
+	boot_params.apm_bios_info.cseg_16_len = oreg.hsi;
+	boot_params.apm_bios_info.dseg_len    = oreg.di;
 
-	if (err)
+	if (oreg.flags & X86_EFLAGS_CF)
 		return -1;
 
 	/* Redo the installation check as the 32-bit connect;
 	   some BIOSes return different flags this way... */
 
-	ax = 0x5300;
-	bx = cx = 0;
-	asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
-		     : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
-		     : : "esi", "edi");
+	ireg.al = 0x00;
+	intcall(0x15, &ireg, &oreg);
 
-	if (err || bx != 0x504d) {
+	if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) {
 		/* Failure with 32-bit connect, try to disconect and ignore */
-		ax = 0x5304;
-		bx = 0;
-		asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
-			     : "+a" (ax), "+b" (bx)
-			     : : "ecx", "edx", "esi", "edi");
+		ireg.al = 0x04;
+		intcall(0x15, &ireg, NULL);
 		return -1;
 	}
 
-	boot_params.apm_bios_info.version = ax;
-	boot_params.apm_bios_info.flags = cx;
+	boot_params.apm_bios_info.version = oreg.ax;
+	boot_params.apm_bios_info.flags   = oreg.cx;
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/bioscall.S linux-libre-2.6.31-gnu/arch/x86/boot/bioscall.S
--- linux-libre-2.6.30-gnu/arch/x86/boot/bioscall.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/boot/bioscall.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,82 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2 or (at your
+ *   option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * "Glove box" for BIOS calls.  Avoids the constant problems with BIOSes
+ * touching registers they shouldn't be.
+ */
+
+	.code16gcc
+	.text
+	.globl	intcall
+	.type	intcall, @function
+intcall:
+	/* Self-modify the INT instruction.  Ugly, but works. */
+	cmpb	%al, 3f
+	je	1f
+	movb	%al, 3f
+	jmp	1f		/* Synchronize pipeline */
+1:
+	/* Save state */
+	pushfl
+	pushw	%fs
+	pushw	%gs
+	pushal
+
+	/* Copy input state to stack frame */
+	subw	$44, %sp
+	movw	%dx, %si
+	movw	%sp, %di
+	movw	$11, %cx
+	rep; movsd
+
+	/* Pop full state from the stack */
+	popal
+	popw	%gs
+	popw	%fs
+	popw	%es
+	popw	%ds
+	popfl
+
+	/* Actual INT */
+	.byte	0xcd		/* INT opcode */
+3:	.byte	0
+
+	/* Push full state to the stack */
+	pushfl
+	pushw	%ds
+	pushw	%es
+	pushw	%fs
+	pushw	%gs
+	pushal
+
+	/* Re-establish C environment invariants */
+	cld
+	movzwl	%sp, %esp
+	movw	%cs, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+
+	/* Copy output state from stack frame */
+	movw	68(%esp), %di	/* Original %cx == 3rd argument */
+	andw	%di, %di
+	jz	4f
+	movw	%sp, %si
+	movw	$11, %cx
+	rep; movsd
+4:	addw	$44, %sp
+
+	/* Restore state and return */
+	popal
+	popw	%gs
+	popw	%fs
+	popfl
+	retl
+	.size	intcall, .-intcall
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/boot.h linux-libre-2.6.31-gnu/arch/x86/boot/boot.h
--- linux-libre-2.6.30-gnu/arch/x86/boot/boot.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/boot.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -26,6 +27,7 @@
 #include <asm/setup.h>
 #include "bitops.h"
 #include <asm/cpufeature.h>
+#include <asm/processor-flags.h>
 
 /* Useful macros */
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
@@ -241,6 +243,49 @@
 /* apm.c */
 int query_apm_bios(void);
 
+/* bioscall.c */
+struct biosregs {
+	union {
+		struct {
+			u32 edi;
+			u32 esi;
+			u32 ebp;
+			u32 _esp;
+			u32 ebx;
+			u32 edx;
+			u32 ecx;
+			u32 eax;
+			u32 _fsgs;
+			u32 _dses;
+			u32 eflags;
+		};
+		struct {
+			u16 di, hdi;
+			u16 si, hsi;
+			u16 bp, hbp;
+			u16 _sp, _hsp;
+			u16 bx, hbx;
+			u16 dx, hdx;
+			u16 cx, hcx;
+			u16 ax, hax;
+			u16 gs, fs;
+			u16 es, ds;
+			u16 flags, hflags;
+		};
+		struct {
+			u8 dil, dih, edi2, edi3;
+			u8 sil, sih, esi2, esi3;
+			u8 bpl, bph, ebp2, ebp3;
+			u8 _spl, _sph, _esp2, _esp3;
+			u8 bl, bh, ebx2, ebx3;
+			u8 dl, dh, edx2, edx3;
+			u8 cl, ch, ecx2, ecx3;
+			u8 al, ah, eax2, eax3;
+		};
+	};
+};
+void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
+
 /* cmdline.c */
 int cmdline_find_option(const char *option, char *buffer, int bufsize);
 int cmdline_find_option_bool(const char *option);
@@ -279,6 +324,9 @@
 int vsprintf(char *buf, const char *fmt, va_list args);
 int printf(const char *fmt, ...);
 
+/* regs.c */
+void initregs(struct biosregs *regs);
+
 /* string.c */
 int strcmp(const char *str1, const char *str2);
 size_t strnlen(const char *s, size_t maxlen);
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/.gitignore linux-libre-2.6.31-gnu/arch/x86/boot/compressed/.gitignore
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/.gitignore	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/.gitignore	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,6 @@
 relocs
 vmlinux.bin.all
 vmlinux.relocs
+vmlinux.lds
+mkpiggy
+piggy.S
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/head_32.S linux-libre-2.6.31-gnu/arch/x86/boot/compressed/head_32.S
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/head_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/head_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -12,16 +12,16 @@
  * the page directory. [According to comments etc elsewhere on a compressed
  * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
  *
- * Page 0 is deliberately kept safe, since System Management Mode code in 
+ * Page 0 is deliberately kept safe, since System Management Mode code in
  * laptops may need to access the BIOS data stored there.  This is also
- * useful for future device drivers that either access the BIOS via VM86 
+ * useful for future device drivers that either access the BIOS via VM86
  * mode.
  */
 
 /*
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
-.text
+	.text
 
 #include <linux/linkage.h>
 #include <asm/segment.h>
@@ -29,161 +29,151 @@
 #include <asm/boot.h>
 #include <asm/asm-offsets.h>
 
-.section ".text.head","ax",@progbits
+	.section ".text.head","ax",@progbits
 ENTRY(startup_32)
 	cld
-	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
-	 * us to not reload segments */
-	testb $(1<<6), BP_loadflags(%esi)
-	jnz 1f
+	/*
+	 * Test KEEP_SEGMENTS flag to see if the bootloader is asking
+	 * us to not reload segments
+	 */
+	testb	$(1<<6), BP_loadflags(%esi)
+	jnz	1f
 
 	cli
-	movl $(__BOOT_DS),%eax
-	movl %eax,%ds
-	movl %eax,%es
-	movl %eax,%fs
-	movl %eax,%gs
-	movl %eax,%ss
+	movl	$__BOOT_DS, %eax
+	movl	%eax, %ds
+	movl	%eax, %es
+	movl	%eax, %fs
+	movl	%eax, %gs
+	movl	%eax, %ss
 1:
 
-/* Calculate the delta between where we were compiled to run
+/*
+ * Calculate the delta between where we were compiled to run
  * at and where we were actually loaded at.  This can only be done
  * with a short local call on x86.  Nothing  else will tell us what
  * address we are running at.  The reserved chunk of the real-mode
  * data at 0x1e4 (defined as a scratch field) are used as the stack
  * for this calculation. Only 4 bytes are needed.
  */
-	leal (0x1e4+4)(%esi), %esp
-	call 1f
-1:	popl %ebp
-	subl $1b, %ebp
+	leal	(BP_scratch+4)(%esi), %esp
+	call	1f
+1:	popl	%ebp
+	subl	$1b, %ebp
 
-/* %ebp contains the address we are loaded at by the boot loader and %ebx
+/*
+ * %ebp contains the address we are loaded at by the boot loader and %ebx
  * contains the address where we should move the kernel image temporarily
  * for safe in-place decompression.
  */
 
 #ifdef CONFIG_RELOCATABLE
-	movl 	%ebp, %ebx
-	addl    $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
-	andl    $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
+	movl	%ebp, %ebx
+	movl	BP_kernel_alignment(%esi), %eax
+	decl	%eax
+	addl    %eax, %ebx
+	notl	%eax
+	andl    %eax, %ebx
 #else
-	movl $LOAD_PHYSICAL_ADDR, %ebx
+	movl	$LOAD_PHYSICAL_ADDR, %ebx
 #endif
 
-	/* Replace the compressed data size with the uncompressed size */
-	subl input_len(%ebp), %ebx
-	movl output_len(%ebp), %eax
-	addl %eax, %ebx
-	/* Add 8 bytes for every 32K input block */
-	shrl $12, %eax
-	addl %eax, %ebx
-	/* Add 32K + 18 bytes of extra slack */
-	addl $(32768 + 18), %ebx
-	/* Align on a 4K boundary */
-	addl $4095, %ebx
-	andl $~4095, %ebx
+	/* Target address to relocate to for decompression */
+	addl	$z_extract_offset, %ebx
 
-/* Copy the compressed kernel to the end of our buffer
+	/* Set up the stack */
+	leal	boot_stack_end(%ebx), %esp
+
+	/* Zero EFLAGS */
+	pushl	$0
+	popfl
+
+/*
+ * Copy the compressed kernel to the end of our buffer
  * where decompression in place becomes safe.
  */
-	pushl %esi
-	leal _end(%ebp), %esi
-	leal _end(%ebx), %edi
-	movl $(_end - startup_32), %ecx
+	pushl	%esi
+	leal	(_bss-4)(%ebp), %esi
+	leal	(_bss-4)(%ebx), %edi
+	movl	$(_bss - startup_32), %ecx
+	shrl	$2, %ecx
 	std
-	rep
-	movsb
+	rep	movsl
 	cld
-	popl %esi
-
-/* Compute the kernel start address.
- */
-#ifdef CONFIG_RELOCATABLE
-	addl    $(CONFIG_PHYSICAL_ALIGN - 1), %ebp
-	andl    $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp
-#else
-	movl	$LOAD_PHYSICAL_ADDR, %ebp
-#endif
+	popl	%esi
 
 /*
  * Jump to the relocated address.
  */
-	leal relocated(%ebx), %eax
-	jmp *%eax
+	leal	relocated(%ebx), %eax
+	jmp	*%eax
 ENDPROC(startup_32)
 
-.section ".text"
+	.text
 relocated:
 
 /*
- * Clear BSS
- */
-	xorl %eax,%eax
-	leal _edata(%ebx),%edi
-	leal _end(%ebx), %ecx
-	subl %edi,%ecx
-	cld
-	rep
-	stosb
-
-/*
- * Setup the stack for the decompressor
+ * Clear BSS (stack is currently empty)
  */
-	leal boot_stack_end(%ebx), %esp
+	xorl	%eax, %eax
+	leal	_bss(%ebx), %edi
+	leal	_ebss(%ebx), %ecx
+	subl	%edi, %ecx
+	shrl	$2, %ecx
+	rep	stosl
 
 /*
  * Do the decompression, and jump to the new kernel..
  */
-	movl output_len(%ebx), %eax
-	pushl %eax
-			# push arguments for decompress_kernel:
-	pushl %ebp	# output address
-	movl input_len(%ebx), %eax
-	pushl %eax	# input_len
-	leal input_data(%ebx), %eax
-	pushl %eax	# input_data
-	leal boot_heap(%ebx), %eax
-	pushl %eax	# heap area
-	pushl %esi	# real mode pointer
-	call decompress_kernel
-	addl $20, %esp
-	popl %ecx
+	leal	z_extract_offset_negative(%ebx), %ebp
+				/* push arguments for decompress_kernel: */
+	pushl	%ebp		/* output address */
+	pushl	$z_input_len	/* input_len */
+	leal	input_data(%ebx), %eax
+	pushl	%eax		/* input_data */
+	leal	boot_heap(%ebx), %eax
+	pushl	%eax		/* heap area */
+	pushl	%esi		/* real mode pointer */
+	call	decompress_kernel
+	addl	$20, %esp
 
 #if CONFIG_RELOCATABLE
-/* Find the address of the relocations.
+/*
+ * Find the address of the relocations.
  */
-	movl %ebp, %edi
-	addl %ecx, %edi
+	leal	z_output_len(%ebp), %edi
 
-/* Calculate the delta between where vmlinux was compiled to run
+/*
+ * Calculate the delta between where vmlinux was compiled to run
  * and where it was actually loaded.
  */
-	movl %ebp, %ebx
-	subl $LOAD_PHYSICAL_ADDR, %ebx
-	jz   2f		/* Nothing to be done if loaded at compiled addr. */
+	movl	%ebp, %ebx
+	subl	$LOAD_PHYSICAL_ADDR, %ebx
+	jz	2f	/* Nothing to be done if loaded at compiled addr. */
 /*
  * Process relocations.
  */
 
-1:	subl $4, %edi
-	movl 0(%edi), %ecx
-	testl %ecx, %ecx
-	jz 2f
-	addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)
-	jmp 1b
+1:	subl	$4, %edi
+	movl	(%edi), %ecx
+	testl	%ecx, %ecx
+	jz	2f
+	addl	%ebx, -__PAGE_OFFSET(%ebx, %ecx)
+	jmp	1b
 2:
 #endif
 
 /*
  * Jump to the decompressed kernel.
  */
-	xorl %ebx,%ebx
-	jmp *%ebp
+	xorl	%ebx, %ebx
+	jmp	*%ebp
 
-.bss
-/* Stack and heap for uncompression */
-.balign 4
+/*
+ * Stack and heap for uncompression
+ */
+	.bss
+	.balign 4
 boot_heap:
 	.fill BOOT_HEAP_SIZE, 1, 0
 boot_stack:
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/head_64.S linux-libre-2.6.31-gnu/arch/x86/boot/compressed/head_64.S
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/head_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/head_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -21,8 +21,8 @@
 /*
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
-.code32
-.text
+	.code32
+	.text
 
 #include <linux/linkage.h>
 #include <asm/segment.h>
@@ -33,12 +33,14 @@
 #include <asm/processor-flags.h>
 #include <asm/asm-offsets.h>
 
-.section ".text.head"
+	.section ".text.head"
 	.code32
 ENTRY(startup_32)
 	cld
-	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
-	 * us to not reload segments */
+	/*
+	 * Test KEEP_SEGMENTS flag to see if the bootloader is asking
+	 * us to not reload segments
+	 */
 	testb $(1<<6), BP_loadflags(%esi)
 	jnz 1f
 
@@ -49,14 +51,15 @@
 	movl	%eax, %ss
 1:
 
-/* Calculate the delta between where we were compiled to run
+/*
+ * Calculate the delta between where we were compiled to run
  * at and where we were actually loaded at.  This can only be done
  * with a short local call on x86.  Nothing  else will tell us what
  * address we are running at.  The reserved chunk of the real-mode
  * data at 0x1e4 (defined as a scratch field) are used as the stack
  * for this calculation. Only 4 bytes are needed.
  */
-	leal	(0x1e4+4)(%esi), %esp
+	leal	(BP_scratch+4)(%esi), %esp
 	call	1f
 1:	popl	%ebp
 	subl	$1b, %ebp
@@ -70,32 +73,28 @@
 	testl	%eax, %eax
 	jnz	no_longmode
 
-/* Compute the delta between where we were compiled to run at
+/*
+ * Compute the delta between where we were compiled to run at
  * and where the code will actually run at.
- */
-/* %ebp contains the address we are loaded at by the boot loader and %ebx
+ *
+ * %ebp contains the address we are loaded at by the boot loader and %ebx
  * contains the address where we should move the kernel image temporarily
  * for safe in-place decompression.
  */
 
 #ifdef CONFIG_RELOCATABLE
 	movl	%ebp, %ebx
-	addl	$(PMD_PAGE_SIZE -1), %ebx
-	andl	$PMD_PAGE_MASK, %ebx
+	movl	BP_kernel_alignment(%esi), %eax
+	decl	%eax
+	addl	%eax, %ebx
+	notl	%eax
+	andl	%eax, %ebx
 #else
-	movl	$CONFIG_PHYSICAL_START, %ebx
+	movl	$LOAD_PHYSICAL_ADDR, %ebx
 #endif
 
-	/* Replace the compressed data size with the uncompressed size */
-	subl	input_len(%ebp), %ebx
-	movl	output_len(%ebp), %eax
-	addl	%eax, %ebx
-	/* Add 8 bytes for every 32K input block */
-	shrl	$12, %eax
-	addl	%eax, %ebx
-	/* Add 32K + 18 bytes of extra slack and align on a 4K boundary */
-	addl	$(32768 + 18 + 4095), %ebx
-	andl	$~4095, %ebx
+	/* Target address to relocate to for decompression */
+	addl	$z_extract_offset, %ebx
 
 /*
  * Prepare for entering 64 bit mode
@@ -114,7 +113,7 @@
  /*
   * Build early 4G boot pagetable
   */
-	/* Initialize Page tables to 0*/
+	/* Initialize Page tables to 0 */
 	leal	pgtable(%ebx), %edi
 	xorl	%eax, %eax
 	movl	$((4096*6)/4), %ecx
@@ -155,7 +154,8 @@
 	btsl	$_EFER_LME, %eax
 	wrmsr
 
-	/* Setup for the jump to 64bit mode
+	/*
+	 * Setup for the jump to 64bit mode
 	 *
 	 * When the jump is performend we will be in long mode but
 	 * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
@@ -184,7 +184,8 @@
 
 #include "../../kernel/verify_cpu_64.S"
 
-	/* Be careful here startup_64 needs to be at a predictable
+	/*
+	 * Be careful here startup_64 needs to be at a predictable
 	 * address so I can export it in an ELF header.  Bootloaders
 	 * should look at the ELF header to find this address, as
 	 * it may change in the future.
@@ -192,7 +193,8 @@
 	.code64
 	.org 0x200
 ENTRY(startup_64)
-	/* We come here either from startup_32 or directly from a
+	/*
+	 * We come here either from startup_32 or directly from a
 	 * 64bit bootloader.  If we come here from a bootloader we depend on
 	 * an identity mapped page table being provied that maps our
 	 * entire text+data+bss and hopefully all of memory.
@@ -209,50 +211,54 @@
 	movl    $0x20, %eax
 	ltr	%ax
 
-	/* Compute the decompressed kernel start address.  It is where
+	/*
+	 * Compute the decompressed kernel start address.  It is where
 	 * we were loaded at aligned to a 2M boundary. %rbp contains the
 	 * decompressed kernel start address.
 	 *
 	 * If it is a relocatable kernel then decompress and run the kernel
 	 * from load address aligned to 2MB addr, otherwise decompress and
-	 * run the kernel from CONFIG_PHYSICAL_START
+	 * run the kernel from LOAD_PHYSICAL_ADDR
+	 *
+	 * We cannot rely on the calculation done in 32-bit mode, since we
+	 * may have been invoked via the 64-bit entry point.
 	 */
 
 	/* Start with the delta to where the kernel will run at. */
 #ifdef CONFIG_RELOCATABLE
 	leaq	startup_32(%rip) /* - $startup_32 */, %rbp
-	addq	$(PMD_PAGE_SIZE - 1), %rbp
-	andq	$PMD_PAGE_MASK, %rbp
-	movq	%rbp, %rbx
+	movl	BP_kernel_alignment(%rsi), %eax
+	decl	%eax
+	addq	%rax, %rbp
+	notq	%rax
+	andq	%rax, %rbp
 #else
-	movq	$CONFIG_PHYSICAL_START, %rbp
-	movq	%rbp, %rbx
+	movq	$LOAD_PHYSICAL_ADDR, %rbp
 #endif
 
-	/* Replace the compressed data size with the uncompressed size */
-	movl	input_len(%rip), %eax
-	subq	%rax, %rbx
-	movl	output_len(%rip), %eax
-	addq	%rax, %rbx
-	/* Add 8 bytes for every 32K input block */
-	shrq	$12, %rax
-	addq	%rax, %rbx
-	/* Add 32K + 18 bytes of extra slack and align on a 4K boundary */
-	addq	$(32768 + 18 + 4095), %rbx
-	andq	$~4095, %rbx
+	/* Target address to relocate to for decompression */
+	leaq	z_extract_offset(%rbp), %rbx
 
-/* Copy the compressed kernel to the end of our buffer
+	/* Set up the stack */
+	leaq	boot_stack_end(%rbx), %rsp
+
+	/* Zero EFLAGS */
+	pushq	$0
+	popfq
+
+/*
+ * Copy the compressed kernel to the end of our buffer
  * where decompression in place becomes safe.
  */
-	leaq	_end_before_pgt(%rip), %r8
-	leaq	_end_before_pgt(%rbx), %r9
-	movq	$_end_before_pgt /* - $startup_32 */, %rcx
-1:	subq	$8, %r8
-	subq	$8, %r9
-	movq	0(%r8), %rax
-	movq	%rax, 0(%r9)
-	subq	$8, %rcx
-	jnz	1b
+	pushq	%rsi
+	leaq	(_bss-8)(%rip), %rsi
+	leaq	(_bss-8)(%rbx), %rdi
+	movq	$_bss /* - $startup_32 */, %rcx
+	shrq	$3, %rcx
+	std
+	rep	movsq
+	cld
+	popq	%rsi
 
 /*
  * Jump to the relocated address.
@@ -260,37 +266,28 @@
 	leaq	relocated(%rbx), %rax
 	jmp	*%rax
 
-.section ".text"
+	.text
 relocated:
 
 /*
- * Clear BSS
+ * Clear BSS (stack is currently empty)
  */
-	xorq	%rax, %rax
-	leaq    _edata(%rbx), %rdi
-	leaq    _end_before_pgt(%rbx), %rcx
+	xorl	%eax, %eax
+	leaq    _bss(%rip), %rdi
+	leaq    _ebss(%rip), %rcx
 	subq	%rdi, %rcx
-	cld
-	rep
-	stosb
-
-	/* Setup the stack */
-	leaq	boot_stack_end(%rip), %rsp
-
-	/* zero EFLAGS after setting rsp */
-	pushq	$0
-	popfq
+	shrq	$3, %rcx
+	rep	stosq
 
 /*
  * Do the decompression, and jump to the new kernel..
  */
-	pushq	%rsi			# Save the real mode argument
-	movq	%rsi, %rdi		# real mode address
-	leaq	boot_heap(%rip), %rsi	# malloc area for uncompression
-	leaq	input_data(%rip), %rdx  # input_data
-	movl	input_len(%rip), %eax
-	movq	%rax, %rcx		# input_len
-	movq	%rbp, %r8		# output
+	pushq	%rsi			/* Save the real mode argument */
+	movq	%rsi, %rdi		/* real mode address */
+	leaq	boot_heap(%rip), %rsi	/* malloc area for uncompression */
+	leaq	input_data(%rip), %rdx  /* input_data */
+	movl	$z_input_len, %ecx	/* input_len */
+	movq	%rbp, %r8		/* output target address */
 	call	decompress_kernel
 	popq	%rsi
 
@@ -311,11 +308,21 @@
 	.quad   0x0000000000000000	/* TS continued */
 gdt_end:
 
-.bss
-/* Stack and heap for uncompression */
-.balign 4
+/*
+ * Stack and heap for uncompression
+ */
+	.bss
+	.balign 4
 boot_heap:
 	.fill BOOT_HEAP_SIZE, 1, 0
 boot_stack:
 	.fill BOOT_STACK_SIZE, 1, 0
 boot_stack_end:
+
+/*
+ * Space for page tables (not in .bss so not zeroed)
+ */
+	.section ".pgtable","a",@nobits
+	.balign 4096
+pgtable:
+	.fill 6*4096, 1, 0
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/Makefile linux-libre-2.6.31-gnu/arch/x86/boot/compressed/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -15,11 +15,14 @@
 KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
 
 KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
+GCOV_PROFILE := n
 
 LDFLAGS := -m elf_$(UTS_MACHINE)
 LDFLAGS_vmlinux := -T
 
-$(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
+hostprogs-y	:= mkpiggy
+
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
 	@:
 
@@ -29,7 +32,7 @@
 
 
 targets += vmlinux.bin.all vmlinux.relocs relocs
-hostprogs-$(CONFIG_X86_32) += relocs
+hostprogs-$(CONFIG_X86_NEED_RELOCS) += relocs
 
 quiet_cmd_relocs = RELOCS  $@
       cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
@@ -37,46 +40,22 @@
 	$(call if_changed,relocs)
 
 vmlinux.bin.all-y := $(obj)/vmlinux.bin
-vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
-quiet_cmd_relocbin = BUILD   $@
-      cmd_relocbin = cat $(filter-out FORCE,$^) > $@
-$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
-	$(call if_changed,relocbin)
-
-ifeq ($(CONFIG_X86_32),y)
-
-ifdef CONFIG_RELOCATABLE
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
-	$(call if_changed,gzip)
-$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin.all FORCE
-	$(call if_changed,bzip2)
-$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin.all FORCE
-	$(call if_changed,lzma)
-else
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
-	$(call if_changed,gzip)
-$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
-	$(call if_changed,bzip2)
-$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
-	$(call if_changed,lzma)
-endif
-LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
-
-else
+vmlinux.bin.all-$(CONFIG_X86_NEED_RELOCS) += $(obj)/vmlinux.relocs
 
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,gzip)
-$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
+$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,bzip2)
-$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lzma)
 
-LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
-endif
+suffix-$(CONFIG_KERNEL_GZIP)	:= gz
+suffix-$(CONFIG_KERNEL_BZIP2)	:= bz2
+suffix-$(CONFIG_KERNEL_LZMA)	:= lzma
 
-suffix_$(CONFIG_KERNEL_GZIP)  = gz
-suffix_$(CONFIG_KERNEL_BZIP2) = bz2
-suffix_$(CONFIG_KERNEL_LZMA)  = lzma
+quiet_cmd_mkpiggy = MKPIGGY $@
+      cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false )
 
-$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE
-	$(call if_changed,ld)
+targets += piggy.S
+$(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE
+	$(call if_changed,mkpiggy)
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/misc.c linux-libre-2.6.31-gnu/arch/x86/boot/compressed/misc.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/misc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/misc.c	2009-09-09 18:13:59.000000000 -0400
@@ -325,21 +325,19 @@
 	free_mem_ptr     = heap;	/* Heap */
 	free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
 
+	if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
+		error("Destination address inappropriately aligned");
 #ifdef CONFIG_X86_64
-	if ((unsigned long)output & (__KERNEL_ALIGN - 1))
-		error("Destination address not 2M aligned");
-	if ((unsigned long)output >= 0xffffffffffUL)
+	if (heap > 0x3fffffffffffUL)
 		error("Destination address too large");
 #else
-	if ((u32)output & (CONFIG_PHYSICAL_ALIGN - 1))
-		error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
 	if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
 		error("Destination address too large");
+#endif
 #ifndef CONFIG_RELOCATABLE
-	if ((u32)output != LOAD_PHYSICAL_ADDR)
+	if ((unsigned long)output != LOAD_PHYSICAL_ADDR)
 		error("Wrong destination address");
 #endif
-#endif
 
 	if (!quiet)
 		putstr("\nDecompressing Linux... ");
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/mkpiggy.c linux-libre-2.6.31-gnu/arch/x86/boot/compressed/mkpiggy.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/mkpiggy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/mkpiggy.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,97 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *  Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License version
+ *  2 as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ *
+ *  H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Compute the desired load offset from a compressed program; outputs
+ * a small assembly wrapper with the appropriate symbols defined.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+static uint32_t getle32(const void *p)
+{
+	const uint8_t *cp = p;
+
+	return (uint32_t)cp[0] + ((uint32_t)cp[1] << 8) +
+		((uint32_t)cp[2] << 16) + ((uint32_t)cp[3] << 24);
+}
+
+int main(int argc, char *argv[])
+{
+	uint32_t olen;
+	long ilen;
+	unsigned long offs;
+	FILE *f;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s compressed_file\n", argv[0]);
+		return 1;
+	}
+
+	/* Get the information for the compressed kernel image first */
+
+	f = fopen(argv[1], "r");
+	if (!f) {
+		perror(argv[1]);
+		return 1;
+	}
+
+
+	if (fseek(f, -4L, SEEK_END)) {
+		perror(argv[1]);
+	}
+	fread(&olen, sizeof olen, 1, f);
+	ilen = ftell(f);
+	olen = getle32(&olen);
+	fclose(f);
+
+	/*
+	 * Now we have the input (compressed) and output (uncompressed)
+	 * sizes, compute the necessary decompression offset...
+	 */
+
+	offs = (olen > ilen) ? olen - ilen : 0;
+	offs += olen >> 12;	/* Add 8 bytes for each 32K block */
+	offs += 32*1024 + 18;	/* Add 32K + 18 bytes slack */
+	offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
+
+	printf(".section \".rodata.compressed\",\"a\",@progbits\n");
+	printf(".globl z_input_len\n");
+	printf("z_input_len = %lu\n", ilen);
+	printf(".globl z_output_len\n");
+	printf("z_output_len = %lu\n", (unsigned long)olen);
+	printf(".globl z_extract_offset\n");
+	printf("z_extract_offset = 0x%lx\n", offs);
+	/* z_extract_offset_negative allows simplification of head_32.S */
+	printf(".globl z_extract_offset_negative\n");
+	printf("z_extract_offset_negative = -0x%lx\n", offs);
+
+	printf(".globl input_data, input_data_end\n");
+	printf("input_data:\n");
+	printf(".incbin \"%s\"\n", argv[1]);
+	printf("input_data_end:\n");
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux_32.lds linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux_32.lds
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux_32.lds	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux_32.lds	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(startup_32)
-SECTIONS
-{
-	/* Be careful parts of head_32.S assume startup_32 is at
-	 * address 0.
-	 */
-	. = 0;
-	.text.head : {
-		_head = . ;
-		*(.text.head)
-		_ehead = . ;
-	}
-	.rodata.compressed : {
-		*(.rodata.compressed)
-	}
-	.text :	{
-		_text = .; 	/* Text */
-		*(.text)
-		*(.text.*)
-		_etext = . ;
-	}
-	.rodata : {
-		_rodata = . ;
-		*(.rodata)	 /* read-only data */
-		*(.rodata.*)
-		_erodata = . ;
-	}
-	.data :	{
-		_data = . ;
-		*(.data)
-		*(.data.*)
-		_edata = . ;
-	}
-	.bss : {
-		_bss = . ;
-		*(.bss)
-		*(.bss.*)
-		*(COMMON)
-		_end = . ;
-	}
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux_64.lds linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux_64.lds
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux_64.lds	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux_64.lds	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-OUTPUT_ARCH(i386:x86-64)
-ENTRY(startup_64)
-SECTIONS
-{
-	/* Be careful parts of head_64.S assume startup_32 is at
-	 * address 0.
-	 */
-	. = 0;
-	.text.head : {
-		_head = . ;
-		*(.text.head)
-		_ehead = . ;
-	}
-	.rodata.compressed : {
-		*(.rodata.compressed)
-	}
-	.text :	{
-		_text = .; 	/* Text */
-		*(.text)
-		*(.text.*)
-		_etext = . ;
-	}
-	.rodata : {
-		_rodata = . ;
-		*(.rodata)	 /* read-only data */
-		*(.rodata.*)
-		_erodata = . ;
-	}
-	.data :	{
-		_data = . ;
-		*(.data)
-		*(.data.*)
-		_edata = . ;
-	}
-	.bss : {
-		_bss = . ;
-		*(.bss)
-		*(.bss.*)
-		*(COMMON)
-		. = ALIGN(8);
-		_end_before_pgt = . ;
-		. = ALIGN(4096);
-		pgtable = . ;
-		. = . + 4096 * 6;
-		_ebss = .;
-	}
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,65 @@
+OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT)
+
+#undef i386
+
+#include <asm/page_types.h>
+
+#ifdef CONFIG_X86_64
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(startup_64)
+#else
+OUTPUT_ARCH(i386)
+ENTRY(startup_32)
+#endif
+
+SECTIONS
+{
+	/* Be careful parts of head_64.S assume startup_32 is at
+	 * address 0.
+	 */
+	. = 0;
+	.text.head : {
+		_head = . ;
+		*(.text.head)
+		_ehead = . ;
+	}
+	.rodata.compressed : {
+		*(.rodata.compressed)
+	}
+	.text :	{
+		_text = .; 	/* Text */
+		*(.text)
+		*(.text.*)
+		_etext = . ;
+	}
+	.rodata : {
+		_rodata = . ;
+		*(.rodata)	 /* read-only data */
+		*(.rodata.*)
+		_erodata = . ;
+	}
+	.data :	{
+		_data = . ;
+		*(.data)
+		*(.data.*)
+		_edata = . ;
+	}
+	. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+	.bss : {
+		_bss = . ;
+		*(.bss)
+		*(.bss.*)
+		*(COMMON)
+		. = ALIGN(8);	/* For convenience during zeroing */
+		_ebss = .;
+	}
+#ifdef CONFIG_X86_64
+       . = ALIGN(PAGE_SIZE);
+       .pgtable : {
+		_pgtable = . ;
+		*(.pgtable)
+		_epgtable = . ;
+	}
+#endif
+	_end = .;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux.scr linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux.scr
--- linux-libre-2.6.30-gnu/arch/x86/boot/compressed/vmlinux.scr	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/compressed/vmlinux.scr	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-SECTIONS
-{
-  .rodata.compressed : {
-	input_len = .;
-	LONG(input_data_end - input_data) input_data = .;
-	*(.data)
-	output_len = . - 4;
-	input_data_end = .;
-	}
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/edd.c linux-libre-2.6.31-gnu/arch/x86/boot/edd.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/edd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/edd.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -22,17 +23,17 @@
  */
 static int read_mbr(u8 devno, void *buf)
 {
-	u16 ax, bx, cx, dx;
+	struct biosregs ireg, oreg;
 
-	ax = 0x0201;		/* Legacy Read, one sector */
-	cx = 0x0001;		/* Sector 0-0-1 */
-	dx = devno;
-	bx = (size_t)buf;
-	asm volatile("pushfl; stc; int $0x13; setc %%al; popfl"
-		     : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
-		     : : "esi", "edi", "memory");
+	initregs(&ireg);
+	ireg.ax = 0x0201;		/* Legacy Read, one sector */
+	ireg.cx = 0x0001;		/* Sector 0-0-1 */
+	ireg.dl = devno;
+	ireg.bx = (size_t)buf;
 
-	return -(u8)ax;		/* 0 or -1 */
+	intcall(0x13, &ireg, &oreg);
+
+	return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */
 }
 
 static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig)
@@ -72,56 +73,46 @@
 
 static int get_edd_info(u8 devno, struct edd_info *ei)
 {
-	u16 ax, bx, cx, dx, di;
+	struct biosregs ireg, oreg;
 
 	memset(ei, 0, sizeof *ei);
 
 	/* Check Extensions Present */
 
-	ax = 0x4100;
-	bx = EDDMAGIC1;
-	dx = devno;
-	asm("pushfl; stc; int $0x13; setc %%al; popfl"
-	    : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx)
-	    : : "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x41;
+	ireg.bx = EDDMAGIC1;
+	ireg.dl = devno;
+	intcall(0x13, &ireg, &oreg);
 
-	if ((u8)ax)
+	if (oreg.eflags & X86_EFLAGS_CF)
 		return -1;	/* No extended information */
 
-	if (bx != EDDMAGIC2)
+	if (oreg.bx != EDDMAGIC2)
 		return -1;
 
 	ei->device  = devno;
-	ei->version = ax >> 8;	/* EDD version number */
-	ei->interface_support = cx; /* EDD functionality subsets */
+	ei->version = oreg.ah;		 /* EDD version number */
+	ei->interface_support = oreg.cx; /* EDD functionality subsets */
 
 	/* Extended Get Device Parameters */
 
 	ei->params.length = sizeof(ei->params);
-	ax = 0x4800;
-	dx = devno;
-	asm("pushfl; int $0x13; popfl"
-	    : "+a" (ax), "+d" (dx), "=m" (ei->params)
-	    : "S" (&ei->params)
-	    : "ebx", "ecx", "edi");
+	ireg.ah = 0x48;
+	ireg.si = (size_t)&ei->params;
+	intcall(0x13, &ireg, &oreg);
 
 	/* Get legacy CHS parameters */
 
 	/* Ralf Brown recommends setting ES:DI to 0:0 */
-	ax = 0x0800;
-	dx = devno;
-	di = 0;
-	asm("pushw %%es; "
-	    "movw %%di,%%es; "
-	    "pushfl; stc; int $0x13; setc %%al; popfl; "
-	    "popw %%es"
-	    : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di)
-	    : : "esi");
+	ireg.ah = 0x08;
+	ireg.es = 0;
+	intcall(0x13, &ireg, &oreg);
 
-	if ((u8)ax == 0) {
-		ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2);
-		ei->legacy_max_head = dx >> 8;
-		ei->legacy_sectors_per_track = cx & 0x3f;
+	if (!(oreg.eflags & X86_EFLAGS_CF)) {
+		ei->legacy_max_cylinder = oreg.ch + ((oreg.cl & 0xc0) << 2);
+		ei->legacy_max_head = oreg.dh;
+		ei->legacy_sectors_per_track = oreg.cl & 0x3f;
 	}
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/.gitignore linux-libre-2.6.31-gnu/arch/x86/boot/.gitignore
--- linux-libre-2.6.30-gnu/arch/x86/boot/.gitignore	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/.gitignore	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,8 @@
 cpustr.h
 mkcpustr
 offsets.h
+voffset.h
+zoffset.h
 setup
 setup.bin
 setup.elf
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/header.S linux-libre-2.6.31-gnu/arch/x86/boot/header.S
--- linux-libre-2.6.30-gnu/arch/x86/boot/header.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/header.S	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,8 @@
 #include <asm/page_types.h>
 #include <asm/setup.h>
 #include "boot.h"
-#include "offsets.h"
+#include "voffset.h"
+#include "zoffset.h"
 
 BOOTSEG		= 0x07C0		/* original address of boot-sector */
 SYSSEG		= 0x1000		/* historical load address >> 4 */
@@ -115,7 +116,7 @@
 	# Part 2 of the header, from the old setup.S
 
 		.ascii	"HdrS"		# header signature
-		.word	0x0209		# header version number (>= 0x0105)
+		.word	0x020a		# header version number (>= 0x0105)
 					# or else old loadlin-1.5 will fail)
 		.globl realmode_swtch
 realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
@@ -168,7 +169,11 @@
 					# end of setup code can be used by setup
 					# for local heap purposes.
 
-pad1:		.word	0
+ext_loader_ver:
+		.byte	0		# Extended boot loader version
+ext_loader_type:
+		.byte	0		# Extended boot loader type
+
 cmd_line_ptr:	.long	0		# (Header version 0x0202 or later)
 					# If nonzero, a 32-bit pointer
 					# to the kernel command line.
@@ -200,7 +205,7 @@
 #else
 relocatable_kernel:    .byte 0
 #endif
-pad2:			.byte 0
+min_alignment:		.byte MIN_KERNEL_ALIGN_LG2	# minimum alignment
 pad3:			.word 0
 
 cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
@@ -212,16 +217,27 @@
 
 hardware_subarch_data:	.quad 0
 
-payload_offset:		.long input_data
-payload_length:		.long input_data_end-input_data
+payload_offset:		.long ZO_input_data
+payload_length:		.long ZO_z_input_len
 
 setup_data:		.quad 0			# 64-bit physical pointer to
 						# single linked list of
 						# struct setup_data
 
+pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
+
+#define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_z_extract_offset)
+#define VO_INIT_SIZE	(VO__end - VO__text)
+#if ZO_INIT_SIZE > VO_INIT_SIZE
+#define INIT_SIZE ZO_INIT_SIZE
+#else
+#define INIT_SIZE VO_INIT_SIZE
+#endif
+init_size:		.long INIT_SIZE		# kernel initialization size
+
 # End of setup header #####################################################
 
-	.section ".inittext", "ax"
+	.section ".entrytext", "ax"
 start_of_setup:
 #ifdef SAFE_RESET_DISK_CONTROLLER
 # Reset the disk controller.
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/main.c linux-libre-2.6.31-gnu/arch/x86/boot/main.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -61,11 +62,10 @@
  */
 static void keyboard_set_repeat(void)
 {
-	u16 ax = 0x0305;
-	u16 bx = 0;
-	asm volatile("int $0x16"
-		     : "+a" (ax), "+b" (bx)
-		     : : "ecx", "edx", "esi", "edi");
+	struct biosregs ireg;
+	initregs(&ireg);
+	ireg.ax = 0x0305;
+	intcall(0x16, &ireg, NULL);
 }
 
 /*
@@ -73,18 +73,22 @@
  */
 static void query_ist(void)
 {
+	struct biosregs ireg, oreg;
+
 	/* Some older BIOSes apparently crash on this call, so filter
 	   it from machines too old to have SpeedStep at all. */
 	if (cpu.level < 6)
 		return;
 
-	asm("int $0x15"
-	    : "=a" (boot_params.ist_info.signature),
-	      "=b" (boot_params.ist_info.command),
-	      "=c" (boot_params.ist_info.event),
-	      "=d" (boot_params.ist_info.perf_level)
-	    : "a" (0x0000e980),	 /* IST Support */
-	      "d" (0x47534943)); /* Request value */
+	initregs(&ireg);
+	ireg.ax  = 0xe980;	 /* IST Support */
+	ireg.edx = 0x47534943;	 /* Request value */
+	intcall(0x15, &ireg, &oreg);
+
+	boot_params.ist_info.signature  = oreg.eax;
+	boot_params.ist_info.command    = oreg.ebx;
+	boot_params.ist_info.event      = oreg.ecx;
+	boot_params.ist_info.perf_level = oreg.edx;
 }
 
 /*
@@ -93,13 +97,12 @@
 static void set_bios_mode(void)
 {
 #ifdef CONFIG_X86_64
-	u32 eax, ebx;
+	struct biosregs ireg;
 
-	eax = 0xec00;
-	ebx = 2;
-	asm volatile("int $0x15"
-		     : "+a" (eax), "+b" (ebx)
-		     : : "ecx", "edx", "esi", "edi");
+	initregs(&ireg);
+	ireg.ax = 0xec00;
+	ireg.bx = 2;
+	intcall(0x15, &ireg, NULL);
 #endif
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/Makefile linux-libre-2.6.31-gnu/arch/x86/boot/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/boot/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -26,9 +26,10 @@
 targets		+= fdimage fdimage144 fdimage288 image.iso mtools.conf
 subdir-		:= compressed
 
-setup-y		+= a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+setup-y		+= a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
 setup-y		+= header.o main.o mca.o memory.o pm.o pmjump.o
-setup-y		+= printf.o string.o tty.o video.o video-mode.o version.o
+setup-y		+= printf.o regs.o string.o tty.o video.o video-mode.o
+setup-y		+= version.o
 setup-$(CONFIG_X86_APM_BOOT) += apm.o
 
 # The link order of the video-*.o modules can matter.  In particular,
@@ -69,6 +70,7 @@
 		   $(call cc-option, -mpreferred-stack-boundary=2)
 KBUILD_CFLAGS	+= $(call cc-option, -m32)
 KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
+GCOV_PROFILE := n
 
 $(obj)/bzImage: asflags-y  := $(SVGA_MODE)
 
@@ -86,19 +88,27 @@
 
 SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
 
-sed-offsets := -e 's/^00*/0/' \
-        -e 's/^\([0-9a-fA-F]*\) . \(input_data\|input_data_end\)$$/\#define \2 0x\1/p'
+sed-voffset := -e 's/^\([0-9a-fA-F]*\) . \(_text\|_end\)$$/\#define VO_\2 0x\1/p'
 
-quiet_cmd_offsets = OFFSETS $@
-      cmd_offsets = $(NM) $< | sed -n $(sed-offsets) > $@
+quiet_cmd_voffset = VOFFSET $@
+      cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@
 
-$(obj)/offsets.h: $(obj)/compressed/vmlinux FORCE
-	$(call if_changed,offsets)
+targets += voffset.h
+$(obj)/voffset.h: vmlinux FORCE
+	$(call if_changed,voffset)
+
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+
+quiet_cmd_zoffset = ZOFFSET $@
+      cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
+
+targets += zoffset.h
+$(obj)/zoffset.h: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,zoffset)
 
-targets += offsets.h
 
 AFLAGS_header.o += -I$(obj)
-$(obj)/header.o: $(obj)/offsets.h
+$(obj)/header.o: $(obj)/voffset.h $(obj)/zoffset.h
 
 LDFLAGS_setup.elf	:= -T
 $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/mca.c linux-libre-2.6.31-gnu/arch/x86/boot/mca.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/mca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/mca.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -16,26 +17,22 @@
 
 int query_mca(void)
 {
-	u8 err;
-	u16 es, bx, len;
+	struct biosregs ireg, oreg;
+	u16 len;
 
-	asm("pushw %%es ; "
-	    "int $0x15 ; "
-	    "setc %0 ; "
-	    "movw %%es, %1 ; "
-	    "popw %%es"
-	    : "=acd" (err), "=acdSD" (es), "=b" (bx)
-	    : "a" (0xc000));
+	initregs(&ireg);
+	ireg.ah = 0xc0;
+	intcall(0x15, &ireg, &oreg);
 
-	if (err)
+	if (oreg.eflags & X86_EFLAGS_CF)
 		return -1;	/* No MCA present */
 
-	set_fs(es);
-	len = rdfs16(bx);
+	set_fs(oreg.es);
+	len = rdfs16(oreg.bx);
 
 	if (len > sizeof(boot_params.sys_desc_table))
 		len = sizeof(boot_params.sys_desc_table);
 
-	copy_from_fs(&boot_params.sys_desc_table, bx, len);
+	copy_from_fs(&boot_params.sys_desc_table, oreg.bx, len);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/memory.c linux-libre-2.6.31-gnu/arch/x86/boot/memory.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/memory.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/memory.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,12 +20,16 @@
 static int detect_memory_e820(void)
 {
 	int count = 0;
-	u32 next = 0;
-	u32 size, id, edi;
-	u8 err;
+	struct biosregs ireg, oreg;
 	struct e820entry *desc = boot_params.e820_map;
 	static struct e820entry buf; /* static so it is zeroed */
 
+	initregs(&ireg);
+	ireg.ax  = 0xe820;
+	ireg.cx  = sizeof buf;
+	ireg.edx = SMAP;
+	ireg.di  = (size_t)&buf;
+
 	/*
 	 * Note: at least one BIOS is known which assumes that the
 	 * buffer pointed to by one e820 call is the same one as
@@ -41,22 +45,13 @@
 	 */
 
 	do {
-		size = sizeof buf;
-
-		/* Important: %edx and %esi are clobbered by some BIOSes,
-		   so they must be either used for the error output
-		   or explicitly marked clobbered.  Given that, assume there
-		   is something out there clobbering %ebp and %edi, too. */
-		asm("pushl %%ebp; int $0x15; popl %%ebp; setc %0"
-		    : "=d" (err), "+b" (next), "=a" (id), "+c" (size),
-		      "=D" (edi), "+m" (buf)
-		    : "D" (&buf), "d" (SMAP), "a" (0xe820)
-		    : "esi");
+		intcall(0x15, &ireg, &oreg);
+		ireg.ebx = oreg.ebx; /* for next iteration... */
 
 		/* BIOSes which terminate the chain with CF = 1 as opposed
 		   to %ebx = 0 don't always report the SMAP signature on
 		   the final, failing, probe. */
-		if (err)
+		if (oreg.eflags & X86_EFLAGS_CF)
 			break;
 
 		/* Some BIOSes stop returning SMAP in the middle of
@@ -64,60 +59,64 @@
 		   screwed up the map at that point, we might have a
 		   partial map, the full map, or complete garbage, so
 		   just return failure. */
-		if (id != SMAP) {
+		if (oreg.eax != SMAP) {
 			count = 0;
 			break;
 		}
 
 		*desc++ = buf;
 		count++;
-	} while (next && count < ARRAY_SIZE(boot_params.e820_map));
+	} while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));
 
 	return boot_params.e820_entries = count;
 }
 
 static int detect_memory_e801(void)
 {
-	u16 ax, bx, cx, dx;
-	u8 err;
+	struct biosregs ireg, oreg;
 
-	bx = cx = dx = 0;
-	ax = 0xe801;
-	asm("stc; int $0x15; setc %0"
-	    : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
+	initregs(&ireg);
+	ireg.ax = 0xe801;
+	intcall(0x15, &ireg, &oreg);
 
-	if (err)
+	if (oreg.eflags & X86_EFLAGS_CF)
 		return -1;
 
 	/* Do we really need to do this? */
-	if (cx || dx) {
-		ax = cx;
-		bx = dx;
+	if (oreg.cx || oreg.dx) {
+		oreg.ax = oreg.cx;
+		oreg.bx = oreg.dx;
 	}
 
-	if (ax > 15*1024)
+	if (oreg.ax > 15*1024) {
 		return -1;	/* Bogus! */
-
-	/* This ignores memory above 16MB if we have a memory hole
-	   there.  If someone actually finds a machine with a memory
-	   hole at 16MB and no support for 0E820h they should probably
-	   generate a fake e820 map. */
-	boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
+	} else if (oreg.ax == 15*1024) {
+		boot_params.alt_mem_k = (oreg.dx << 6) + oreg.ax;
+	} else {
+		/*
+		 * This ignores memory above 16MB if we have a memory
+		 * hole there.  If someone actually finds a machine
+		 * with a memory hole at 16MB and no support for
+		 * 0E820h they should probably generate a fake e820
+		 * map.
+		 */
+		boot_params.alt_mem_k = oreg.ax;
+	}
 
 	return 0;
 }
 
 static int detect_memory_88(void)
 {
-	u16 ax;
-	u8 err;
+	struct biosregs ireg, oreg;
 
-	ax = 0x8800;
-	asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
+	initregs(&ireg);
+	ireg.ah = 0x88;
+	intcall(0x15, &ireg, &oreg);
 
-	boot_params.screen_info.ext_mem_k = ax;
+	boot_params.screen_info.ext_mem_k = oreg.ax;
 
-	return -err;
+	return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */
 }
 
 int detect_memory(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/regs.c linux-libre-2.6.31-gnu/arch/x86/boot/regs.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/regs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/boot/regs.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,29 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2 or (at your
+ *   option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Simple helper function for initializing a register set.
+ *
+ * Note that this sets EFLAGS_CF in the input register set; this
+ * makes it easier to catch functions which do nothing but don't
+ * explicitly set CF.
+ */
+
+#include "boot.h"
+
+void initregs(struct biosregs *reg)
+{
+	memset(reg, 0, sizeof *reg);
+	reg->eflags |= X86_EFLAGS_CF;
+	reg->ds = ds();
+	reg->es = ds();
+	reg->fs = fs();
+	reg->gs = gs();
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/setup.ld linux-libre-2.6.31-gnu/arch/x86/boot/setup.ld
--- linux-libre-2.6.30-gnu/arch/x86/boot/setup.ld	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/setup.ld	2009-09-09 18:13:59.000000000 -0400
@@ -15,8 +15,11 @@
 
 	. = 497;
 	.header		: { *(.header) }
+	.entrytext	: { *(.entrytext) }
 	.inittext	: { *(.inittext) }
 	.initdata	: { *(.initdata) }
+	__end_init = .;
+
 	.text		: { *(.text) }
 	.text32		: { *(.text32) }
 
@@ -52,4 +55,7 @@
 
 	. = ASSERT(_end <= 0x8000, "Setup too big!");
 	. = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
+	/* Necessary for the very-old-loader check to work... */
+	. = ASSERT(__end_init <= 5*512, "init sections too big!");
+
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/tty.c linux-libre-2.6.31-gnu/arch/x86/boot/tty.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/tty.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/tty.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -22,24 +23,23 @@
 
 void __attribute__((section(".inittext"))) putchar(int ch)
 {
-	unsigned char c = ch;
+	struct biosregs ireg;
 
-	if (c == '\n')
+	if (ch == '\n')
 		putchar('\r');	/* \n -> \r\n */
 
-	/* int $0x10 is known to have bugs involving touching registers
-	   it shouldn't.  Be extra conservative... */
-	asm volatile("pushal; pushw %%ds; int $0x10; popw %%ds; popal"
-		     : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch));
+	initregs(&ireg);
+	ireg.bx = 0x0007;
+	ireg.cx = 0x0001;
+	ireg.ah = 0x0e;
+	ireg.al = ch;
+	intcall(0x10, &ireg, NULL);
 }
 
 void __attribute__((section(".inittext"))) puts(const char *str)
 {
-	int n = 0;
-	while (*str) {
+	while (*str)
 		putchar(*str++);
-		n++;
-	}
 }
 
 /*
@@ -49,14 +49,13 @@
 
 static u8 gettime(void)
 {
-	u16 ax = 0x0200;
-	u16 cx, dx;
+	struct biosregs ireg, oreg;
 
-	asm volatile("int $0x1a"
-		     : "+a" (ax), "=c" (cx), "=d" (dx)
-		     : : "ebx", "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x02;
+	intcall(0x1a, &ireg, &oreg);
 
-	return dx >> 8;
+	return oreg.dh;
 }
 
 /*
@@ -64,19 +63,24 @@
  */
 int getchar(void)
 {
-	u16 ax = 0;
-	asm volatile("int $0x16" : "+a" (ax));
+	struct biosregs ireg, oreg;
 
-	return ax & 0xff;
+	initregs(&ireg);
+	/* ireg.ah = 0x00; */
+	intcall(0x16, &ireg, &oreg);
+
+	return oreg.al;
 }
 
 static int kbd_pending(void)
 {
-	u8 pending;
-	asm volatile("int $0x16; setnz %0"
-		     : "=qm" (pending)
-		     : "a" (0x0100));
-	return pending;
+	struct biosregs ireg, oreg;
+
+	initregs(&ireg);
+	ireg.ah = 0x01;
+	intcall(0x16, &ireg, &oreg);
+
+	return !(oreg.eflags & X86_EFLAGS_ZF);
 }
 
 void kbd_flush(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/video-bios.c linux-libre-2.6.31-gnu/arch/x86/boot/video-bios.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/video-bios.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/video-bios.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -29,21 +30,20 @@
 
 static int set_bios_mode(u8 mode)
 {
-	u16 ax;
+	struct biosregs ireg, oreg;
 	u8 new_mode;
 
-	ax = mode;		/* AH=0x00 Set Video Mode */
-	asm volatile(INT10
-		     : "+a" (ax)
-		     : : "ebx", "ecx", "edx", "esi", "edi");
+	initregs(&ireg);
+	ireg.al = mode;		/* AH=0x00 Set Video Mode */
+	intcall(0x10, &ireg, NULL);
 
-	ax = 0x0f00;		/* Get Current Video Mode */
-	asm volatile(INT10
-		     : "+a" (ax)
-		     : : "ebx", "ecx", "edx", "esi", "edi");
+	ireg.ah = 0x0f;		/* Get Current Video Mode */
+	intcall(0x10, &ireg, &oreg);
 
 	do_restore = 1;		/* Assume video contents were lost */
-	new_mode = ax & 0x7f;	/* Not all BIOSes are clean with the top bit */
+
+	/* Not all BIOSes are clean with the top bit */
+	new_mode = oreg.al & 0x7f;
 
 	if (new_mode == mode)
 		return 0;	/* Mode change OK */
@@ -53,10 +53,8 @@
 		/* Mode setting failed, but we didn't end up where we
 		   started.  That's bad.  Try to revert to the original
 		   video mode. */
-		ax = boot_params.screen_info.orig_video_mode;
-		asm volatile(INT10
-			     : "+a" (ax)
-			     : : "ebx", "ecx", "edx", "esi", "edi");
+		ireg.ax = boot_params.screen_info.orig_video_mode;
+		intcall(0x10, &ireg, NULL);
 	}
 #endif
 	return -1;
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/video.c linux-libre-2.6.31-gnu/arch/x86/boot/video.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/video.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -18,33 +19,29 @@
 
 static void store_cursor_position(void)
 {
-	u16 curpos;
-	u16 ax, bx;
+	struct biosregs ireg, oreg;
 
-	ax = 0x0300;
-	bx = 0;
-	asm(INT10
-	    : "=d" (curpos), "+a" (ax), "+b" (bx)
-	    : : "ecx", "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x03;
+	intcall(0x10, &ireg, &oreg);
 
-	boot_params.screen_info.orig_x = curpos;
-	boot_params.screen_info.orig_y = curpos >> 8;
+	boot_params.screen_info.orig_x = oreg.dl;
+	boot_params.screen_info.orig_y = oreg.dh;
 }
 
 static void store_video_mode(void)
 {
-	u16 ax, page;
+	struct biosregs ireg, oreg;
 
 	/* N.B.: the saving of the video page here is a bit silly,
 	   since we pretty much assume page 0 everywhere. */
-	ax = 0x0f00;
-	asm(INT10
-	    : "+a" (ax), "=b" (page)
-	    : : "ecx", "edx", "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x0f;
+	intcall(0x10, &ireg, &oreg);
 
 	/* Not all BIOSes are clean with respect to the top bit */
-	boot_params.screen_info.orig_video_mode = ax & 0x7f;
-	boot_params.screen_info.orig_video_page = page >> 8;
+	boot_params.screen_info.orig_video_mode = oreg.al & 0x7f;
+	boot_params.screen_info.orig_video_page = oreg.bh;
 }
 
 /*
@@ -257,7 +254,7 @@
 	int y;
 	addr_t dst = 0;
 	u16 *src = saved.data;
-	u16 ax, bx, dx;
+	struct biosregs ireg;
 
 	if (graphic_mode)
 		return;		/* Can't restore onto a graphic mode */
@@ -296,12 +293,11 @@
 	}
 
 	/* Restore cursor position */
-	ax = 0x0200;		/* Set cursor position */
-	bx = 0;			/* Page number (<< 8) */
-	dx = (saved.cury << 8)+saved.curx;
-	asm volatile(INT10
-		     : "+a" (ax), "+b" (bx), "+d" (dx)
-		     : : "ecx", "esi", "edi");
+	initregs(&ireg);
+	ireg.ah = 0x02;		/* Set cursor position */
+	ireg.dh = saved.cury;
+	ireg.dl = saved.curx;
+	intcall(0x10, &ireg, NULL);
 }
 #else
 #define save_screen()		((void)0)
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/video.h linux-libre-2.6.31-gnu/arch/x86/boot/video.h
--- linux-libre-2.6.30-gnu/arch/x86/boot/video.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/video.h	2009-09-09 18:13:59.000000000 -0400
@@ -112,20 +112,6 @@
 extern int do_restore;		/* Restore screen contents */
 extern int graphic_mode;	/* Graphics mode with linear frame buffer */
 
-/*
- * int $0x10 is notorious for touching registers it shouldn't.
- * gcc doesn't like %ebp being clobbered, so define it as a push/pop
- * sequence here.
- *
- * A number of systems, including the original PC can clobber %bp in
- * certain circumstances, like when scrolling.  There exists at least
- * one Trident video card which could clobber DS under a set of
- * circumstances that we are unlikely to encounter (scrolling when
- * using an extended graphics mode of more than 800x600 pixels), but
- * it's cheap insurance to deal with that here.
- */
-#define INT10 "pushl %%ebp; pushw %%ds; int $0x10; popw %%ds; popl %%ebp"
-
 /* Accessing VGA indexed registers */
 static inline u8 in_idx(u16 port, u8 index)
 {
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/video-vesa.c linux-libre-2.6.31-gnu/arch/x86/boot/video-vesa.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/video-vesa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/video-vesa.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -31,7 +32,7 @@
 static int vesa_probe(void)
 {
 #if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID)
-	u16 ax, cx, di;
+	struct biosregs ireg, oreg;
 	u16 mode;
 	addr_t mode_ptr;
 	struct mode_info *mi;
@@ -39,13 +40,12 @@
 
 	video_vesa.modes = GET_HEAP(struct mode_info, 0);
 
-	ax = 0x4f00;
-	di = (size_t)&vginfo;
-	asm(INT10
-	    : "+a" (ax), "+D" (di), "=m" (vginfo)
-	    : : "ebx", "ecx", "edx", "esi");
+	initregs(&ireg);
+	ireg.ax = 0x4f00;
+	ireg.di = (size_t)&vginfo;
+	intcall(0x10, &ireg, &oreg);
 
-	if (ax != 0x004f ||
+	if (oreg.ax != 0x004f ||
 	    vginfo.signature != VESA_MAGIC ||
 	    vginfo.version < 0x0102)
 		return 0;	/* Not present */
@@ -65,14 +65,12 @@
 
 		memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
 
-		ax = 0x4f01;
-		cx = mode;
-		di = (size_t)&vminfo;
-		asm(INT10
-		    : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo)
-		    : : "ebx", "edx", "esi");
+		ireg.ax = 0x4f01;
+		ireg.cx = mode;
+		ireg.di = (size_t)&vminfo;
+		intcall(0x10, &ireg, &oreg);
 
-		if (ax != 0x004f)
+		if (oreg.ax != 0x004f)
 			continue;
 
 		if ((vminfo.mode_attr & 0x15) == 0x05) {
@@ -111,20 +109,19 @@
 
 static int vesa_set_mode(struct mode_info *mode)
 {
-	u16 ax, bx, cx, di;
+	struct biosregs ireg, oreg;
 	int is_graphic;
 	u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA;
 
 	memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
 
-	ax = 0x4f01;
-	cx = vesa_mode;
-	di = (size_t)&vminfo;
-	asm(INT10
-	    : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo)
-	    : : "ebx", "edx", "esi");
+	initregs(&ireg);
+	ireg.ax = 0x4f01;
+	ireg.cx = vesa_mode;
+	ireg.di = (size_t)&vminfo;
+	intcall(0x10, &ireg, &oreg);
 
-	if (ax != 0x004f)
+	if (oreg.ax != 0x004f)
 		return -1;
 
 	if ((vminfo.mode_attr & 0x15) == 0x05) {
@@ -141,14 +138,12 @@
 	}
 
 
-	ax = 0x4f02;
-	bx = vesa_mode;
-	di = 0;
-	asm volatile(INT10
-		     : "+a" (ax), "+b" (bx), "+D" (di)
-		     : : "ecx", "edx", "esi");
+	initregs(&ireg);
+	ireg.ax = 0x4f02;
+	ireg.bx = vesa_mode;
+	intcall(0x10, &ireg, &oreg);
 
-	if (ax != 0x004f)
+	if (oreg.ax != 0x004f)
 		return -1;
 
 	graphic_mode = is_graphic;
@@ -171,50 +166,45 @@
 /* Switch DAC to 8-bit mode */
 static void vesa_dac_set_8bits(void)
 {
+	struct biosregs ireg, oreg;
 	u8 dac_size = 6;
 
 	/* If possible, switch the DAC to 8-bit mode */
 	if (vginfo.capabilities & 1) {
-		u16 ax, bx;
-
-		ax = 0x4f08;
-		bx = 0x0800;
-		asm volatile(INT10
-			     : "+a" (ax), "+b" (bx)
-			     : : "ecx", "edx", "esi", "edi");
-
-		if (ax == 0x004f)
-			dac_size = bx >> 8;
+		initregs(&ireg);
+		ireg.ax = 0x4f08;
+		ireg.bh = 0x08;
+		intcall(0x10, &ireg, &oreg);
+		if (oreg.ax == 0x004f)
+			dac_size = oreg.bh;
 	}
 
 	/* Set the color sizes to the DAC size, and offsets to 0 */
-	boot_params.screen_info.red_size = dac_size;
+	boot_params.screen_info.red_size   = dac_size;
 	boot_params.screen_info.green_size = dac_size;
-	boot_params.screen_info.blue_size = dac_size;
-	boot_params.screen_info.rsvd_size = dac_size;
+	boot_params.screen_info.blue_size  = dac_size;
+	boot_params.screen_info.rsvd_size  = dac_size;
 
-	boot_params.screen_info.red_pos = 0;
-	boot_params.screen_info.green_pos = 0;
-	boot_params.screen_info.blue_pos = 0;
-	boot_params.screen_info.rsvd_pos = 0;
+	boot_params.screen_info.red_pos    = 0;
+	boot_params.screen_info.green_pos  = 0;
+	boot_params.screen_info.blue_pos   = 0;
+	boot_params.screen_info.rsvd_pos   = 0;
 }
 
 /* Save the VESA protected mode info */
 static void vesa_store_pm_info(void)
 {
-	u16 ax, bx, di, es;
+	struct biosregs ireg, oreg;
 
-	ax = 0x4f0a;
-	bx = di = 0;
-	asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es"
-	    : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di)
-	    : : "ecx", "esi");
+	initregs(&ireg);
+	ireg.ax = 0x4f0a;
+	intcall(0x10, &ireg, &oreg);
 
-	if (ax != 0x004f)
+	if (oreg.ax != 0x004f)
 		return;
 
-	boot_params.screen_info.vesapm_seg = es;
-	boot_params.screen_info.vesapm_off = di;
+	boot_params.screen_info.vesapm_seg = oreg.es;
+	boot_params.screen_info.vesapm_off = oreg.di;
 }
 
 /*
@@ -252,7 +242,7 @@
 void vesa_store_edid(void)
 {
 #ifdef CONFIG_FIRMWARE_EDID
-	u16 ax, bx, cx, dx, di;
+	struct biosregs ireg, oreg;
 
 	/* Apparently used as a nonsense token... */
 	memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info);
@@ -260,33 +250,26 @@
 	if (vginfo.version < 0x0200)
 		return;		/* EDID requires VBE 2.0+ */
 
-	ax = 0x4f15;		/* VBE DDC */
-	bx = 0x0000;		/* Report DDC capabilities */
-	cx = 0;			/* Controller 0 */
-	di = 0;			/* ES:DI must be 0 by spec */
-
-	/* Note: The VBE DDC spec is different from the main VESA spec;
-	   we genuinely have to assume all registers are destroyed here. */
-
-	asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
-	    : "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di)
-	    : : "esi", "edx");
+	initregs(&ireg);
+	ireg.ax = 0x4f15;		/* VBE DDC */
+	/* ireg.bx = 0x0000; */		/* Report DDC capabilities */
+	/* ireg.cx = 0;	*/		/* Controller 0 */
+	ireg.es = 0;			/* ES:DI must be 0 by spec */
+	intcall(0x10, &ireg, &oreg);
 
-	if (ax != 0x004f)
+	if (oreg.ax != 0x004f)
 		return;		/* No EDID */
 
 	/* BH = time in seconds to transfer EDD information */
 	/* BL = DDC level supported */
 
-	ax = 0x4f15;		/* VBE DDC */
-	bx = 0x0001;		/* Read EDID */
-	cx = 0;			/* Controller 0 */
-	dx = 0;			/* EDID block number */
-	di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */
-	asm(INT10
-	    : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info),
-	      "+c" (cx), "+D" (di)
-	    : : "esi");
+	ireg.ax = 0x4f15;		/* VBE DDC */
+	ireg.bx = 0x0001;		/* Read EDID */
+	/* ireg.cx = 0; */		/* Controller 0 */
+	/* ireg.dx = 0;	*/		/* EDID block number */
+	ireg.es = ds();
+	ireg.di =(size_t)&boot_params.edid_info; /* (ES:)Pointer to block */
+	intcall(0x10, &ireg, &oreg);
 #endif /* CONFIG_FIRMWARE_EDID */
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/boot/video-vga.c linux-libre-2.6.31-gnu/arch/x86/boot/video-vga.c
--- linux-libre-2.6.30-gnu/arch/x86/boot/video-vga.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/boot/video-vga.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
@@ -39,30 +40,30 @@
 /* Set basic 80x25 mode */
 static u8 vga_set_basic_mode(void)
 {
+	struct biosregs ireg, oreg;
 	u16 ax;
 	u8 rows;
 	u8 mode;
 
+	initregs(&ireg);
+
 #ifdef CONFIG_VIDEO_400_HACK
 	if (adapter >= ADAPTER_VGA) {
-		asm volatile(INT10
-			     : : "a" (0x1202), "b" (0x0030)
-			     : "ecx", "edx", "esi", "edi");
+		ireg.ax = 0x1202;
+		ireg.bx = 0x0030;
+		intcall(0x10, &ireg, NULL);
 	}
 #endif
 
 	ax = 0x0f00;
-	asm volatile(INT10
-		     : "+a" (ax)
-		     : : "ebx", "ecx", "edx", "esi", "edi");
-
-	mode = (u8)ax;
+	intcall(0x10, &ireg, &oreg);
+	mode = oreg.al;
 
 	set_fs(0);
 	rows = rdfs8(0x484);	/* rows minus one */
 
 #ifndef CONFIG_VIDEO_400_HACK
-	if ((ax == 0x5003 || ax == 0x5007) &&
+	if ((oreg.ax == 0x5003 || oreg.ax == 0x5007) &&
 	    (rows == 0 || rows == 24))
 		return mode;
 #endif
@@ -71,10 +72,8 @@
 		mode = 3;
 
 	/* Set the mode */
-	ax = mode;
-	asm volatile(INT10
-		     : "+a" (ax)
-		     : : "ebx", "ecx", "edx", "esi", "edi");
+	ireg.ax = mode;		/* AH=0: set mode */
+	intcall(0x10, &ireg, NULL);
 	do_restore = 1;
 	return mode;
 }
@@ -82,43 +81,69 @@
 static void vga_set_8font(void)
 {
 	/* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
+	struct biosregs ireg;
+
+	initregs(&ireg);
 
 	/* Set 8x8 font */
-	asm volatile(INT10 : : "a" (0x1112), "b" (0));
+	ireg.ax = 0x1112;
+	/* ireg.bl = 0; */
+	intcall(0x10, &ireg, NULL);
 
 	/* Use alternate print screen */
-	asm volatile(INT10 : : "a" (0x1200), "b" (0x20));
+	ireg.ax = 0x1200;
+	ireg.bl = 0x20;
+	intcall(0x10, &ireg, NULL);
 
 	/* Turn off cursor emulation */
-	asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+	ireg.ax = 0x1201;
+	ireg.bl = 0x34;
+	intcall(0x10, &ireg, NULL);
 
 	/* Cursor is scan lines 6-7 */
-	asm volatile(INT10 : : "a" (0x0100), "c" (0x0607));
+	ireg.ax = 0x0100;
+	ireg.cx = 0x0607;
+	intcall(0x10, &ireg, NULL);
 }
 
 static void vga_set_14font(void)
 {
 	/* Set 9x14 font - 80x28 on VGA */
+	struct biosregs ireg;
+
+	initregs(&ireg);
 
 	/* Set 9x14 font */
-	asm volatile(INT10 : : "a" (0x1111), "b" (0));
+	ireg.ax = 0x1111;
+	/* ireg.bl = 0; */
+	intcall(0x10, &ireg, NULL);
 
 	/* Turn off cursor emulation */
-	asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+	ireg.ax = 0x1201;
+	ireg.bl = 0x34;
+	intcall(0x10, &ireg, NULL);
 
 	/* Cursor is scan lines 11-12 */
-	asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c));
+	ireg.ax = 0x0100;
+	ireg.cx = 0x0b0c;
+	intcall(0x10, &ireg, NULL);
 }
 
 static void vga_set_80x43(void)
 {
 	/* Set 80x43 mode on VGA (not EGA) */
+	struct biosregs ireg;
+
+	initregs(&ireg);
 
 	/* Set 350 scans */
-	asm volatile(INT10 : : "a" (0x1201), "b" (0x30));
+	ireg.ax = 0x1201;
+	ireg.bl = 0x30;
+	intcall(0x10, &ireg, NULL);
 
 	/* Reset video mode */
-	asm volatile(INT10 : : "a" (0x0003));
+	ireg.ax = 0x0003;
+	intcall(0x10, &ireg, NULL);
 
 	vga_set_8font();
 }
@@ -225,8 +250,6 @@
  */
 static int vga_probe(void)
 {
-	u16 ega_bx;
-
 	static const char *card_name[] = {
 		"CGA/MDA/HGC", "EGA", "VGA"
 	};
@@ -240,26 +263,26 @@
 		sizeof(ega_modes)/sizeof(struct mode_info),
 		sizeof(vga_modes)/sizeof(struct mode_info),
 	};
-	u8 vga_flag;
 
-	asm(INT10
-	    : "=b" (ega_bx)
-	    : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
-	    : "ecx", "edx", "esi", "edi");
+	struct biosregs ireg, oreg;
+
+	initregs(&ireg);
+
+	ireg.ax = 0x1200;
+	ireg.bl = 0x10;		/* Check EGA/VGA */
+	intcall(0x10, &ireg, &oreg);
 
 #ifndef _WAKEUP
-	boot_params.screen_info.orig_video_ega_bx = ega_bx;
+	boot_params.screen_info.orig_video_ega_bx = oreg.bx;
 #endif
 
 	/* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
-	if ((u8)ega_bx != 0x10) {
+	if (oreg.bl != 0x10) {
 		/* EGA/VGA */
-		asm(INT10
-		    : "=a" (vga_flag)
-		    : "a" (0x1a00)
-		    : "ebx", "ecx", "edx", "esi", "edi");
+		ireg.ax = 0x1a00;
+		intcall(0x10, &ireg, &oreg);
 
-		if (vga_flag == 0x1a) {
+		if (oreg.al == 0x1a) {
 			adapter = ADAPTER_VGA;
 #ifndef _WAKEUP
 			boot_params.screen_info.orig_video_isVGA = 1;
diff -druN linux-libre-2.6.30-gnu/arch/x86/configs/i386_defconfig linux-libre-2.6.31-gnu/arch/x86/configs/i386_defconfig
--- linux-libre-2.6.30-gnu/arch/x86/configs/i386_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/configs/i386_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,12 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc4
-# Tue Feb 24 15:50:58 2009
+# Linux kernel version: 2.6.30-rc2
+# Mon May 11 16:21:55 2009
 #
 # CONFIG_64BIT is not set
 CONFIG_X86_32=y
 # CONFIG_X86_64 is not set
 CONFIG_X86=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
 CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CMOS_UPDATE=y
@@ -33,6 +34,7 @@
 CONFIG_ARCH_HAS_DEFAULT_IDLE=y
 CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_HAVE_DYNAMIC_PER_CPU_AREA=y
 # CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
@@ -40,15 +42,16 @@
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 # CONFIG_AUDIT_ARCH is not set
 CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
-CONFIG_X86_SMP=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_X86_32_SMP=y
 CONFIG_X86_HT=y
-CONFIG_X86_BIOS_REBOOT=y
 CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_32_LAZY_GS=y
 CONFIG_KTIME_SCALAR=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -60,10 +63,17 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_TASKSTATS=y
@@ -113,23 +123,26 @@
 CONFIG_NET_NS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_PCSPKR_PLATFORM=y
-# CONFIG_COMPAT_BRK is not set
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -139,6 +152,7 @@
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
@@ -154,6 +168,8 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -167,7 +183,6 @@
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_BLK_DEV_BSG=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -194,12 +209,12 @@
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 CONFIG_SMP=y
 CONFIG_SPARSE_IRQ=y
-CONFIG_X86_FIND_SMP_CONFIG=y
 CONFIG_X86_MPPARSE=y
+# CONFIG_X86_BIGSMP is not set
+CONFIG_X86_EXTENDED_PLATFORM=y
 # CONFIG_X86_ELAN is not set
-# CONFIG_X86_GENERICARCH is not set
-# CONFIG_X86_VSMP is not set
 # CONFIG_X86_RDC321X is not set
+# CONFIG_X86_32_NON_STANDARD is not set
 CONFIG_SCHED_OMIT_FRAME_POINTER=y
 # CONFIG_PARAVIRT_GUEST is not set
 # CONFIG_MEMTEST is not set
@@ -230,8 +245,10 @@
 # CONFIG_GENERIC_CPU is not set
 CONFIG_X86_GENERIC=y
 CONFIG_X86_CPU=y
+CONFIG_X86_L1_CACHE_BYTES=64
+CONFIG_X86_INTERNODE_CACHE_BYTES=64
 CONFIG_X86_CMPXCHG=y
-CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_L1_CACHE_SHIFT=5
 CONFIG_X86_XADD=y
 # CONFIG_X86_PPRO_FENCE is not set
 CONFIG_X86_WP_WORKS_OK=y
@@ -247,7 +264,7 @@
 CONFIG_CPU_SUP_INTEL=y
 CONFIG_CPU_SUP_CYRIX_32=y
 CONFIG_CPU_SUP_AMD=y
-CONFIG_CPU_SUP_CENTAUR_32=y
+CONFIG_CPU_SUP_CENTAUR=y
 CONFIG_CPU_SUP_TRANSMETA_32=y
 CONFIG_CPU_SUP_UMC_32=y
 CONFIG_X86_DS=y
@@ -279,6 +296,7 @@
 CONFIG_MICROCODE_OLD_INTERFACE=y
 CONFIG_X86_MSR=y
 CONFIG_X86_CPUID=y
+# CONFIG_X86_CPU_DEBUG is not set
 # CONFIG_NOHIGHMEM is not set
 CONFIG_HIGHMEM4G=y
 # CONFIG_HIGHMEM64G is not set
@@ -302,6 +320,8 @@
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_HIGHPTE=y
 CONFIG_X86_CHECK_BIOS_CORRUPTION=y
 CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
@@ -312,6 +332,7 @@
 CONFIG_X86_PAT=y
 CONFIG_EFI=y
 CONFIG_SECCOMP=y
+# CONFIG_CC_STACKPROTECTOR is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_250 is not set
 # CONFIG_HZ_300 is not set
@@ -322,8 +343,9 @@
 CONFIG_CRASH_DUMP=y
 # CONFIG_KEXEC_JUMP is not set
 CONFIG_PHYSICAL_START=0x1000000
-# CONFIG_RELOCATABLE is not set
-CONFIG_PHYSICAL_ALIGN=0x200000
+CONFIG_RELOCATABLE=y
+CONFIG_X86_NEED_RELOCS=y
+CONFIG_PHYSICAL_ALIGN=0x1000000
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_COMPAT_VDSO is not set
 # CONFIG_CMDLINE_BOOL is not set
@@ -363,7 +385,6 @@
 CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 # CONFIG_ACPI_PCI_SLOT is not set
-CONFIG_ACPI_SYSTEM=y
 CONFIG_X86_PM_TIMER=y
 CONFIG_ACPI_CONTAINER=y
 # CONFIG_ACPI_SBS is not set
@@ -425,6 +446,7 @@
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_DMAR is not set
 CONFIG_PCIEPORTBUS=y
 # CONFIG_HOTPLUG_PCI_PCIE is not set
 CONFIG_PCIEAER=y
@@ -435,6 +457,7 @@
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
 CONFIG_ISA_DMA_API=y
 # CONFIG_ISA is not set
 # CONFIG_MCA is not set
@@ -481,7 +504,6 @@
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -639,6 +661,7 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -696,6 +719,7 @@
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
 CONFIG_HAMRADIO=y
 
 #
@@ -706,12 +730,10 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 CONFIG_FIB_RULES=y
 CONFIG_WIRELESS=y
 CONFIG_CFG80211=y
 # CONFIG_CFG80211_REG_DEBUG is not set
-CONFIG_NL80211=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
@@ -789,6 +811,7 @@
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
 # CONFIG_C2PORT is not set
 
 #
@@ -842,6 +865,7 @@
 # CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_ATA_ACPI=y
@@ -940,6 +964,7 @@
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_IFB is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -977,6 +1002,8 @@
 CONFIG_NET_VENDOR_3COM=y
 # CONFIG_VORTEX is not set
 # CONFIG_TYPHOON is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 CONFIG_NET_TULIP=y
 # CONFIG_DE2104X is not set
 # CONFIG_TULIP is not set
@@ -1026,6 +1053,7 @@
 CONFIG_E1000E=y
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -1040,6 +1068,7 @@
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
 # CONFIG_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
@@ -1049,6 +1078,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -1058,6 +1088,7 @@
 # CONFIG_BNX2X is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
 CONFIG_TR=y
 # CONFIG_IBMOL is not set
 # CONFIG_IBMLS is not set
@@ -1073,8 +1104,8 @@
 # CONFIG_LIBERTAS is not set
 # CONFIG_LIBERTAS_THINFIRM is not set
 # CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
 # CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
 # CONFIG_AIRO_CS is not set
 # CONFIG_PCMCIA_WL3501 is not set
 # CONFIG_PRISM54 is not set
@@ -1084,21 +1115,21 @@
 # CONFIG_RTL8187 is not set
 # CONFIG_ADM8211 is not set
 # CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
 # CONFIG_P54_COMMON is not set
 CONFIG_ATH5K=y
 # CONFIG_ATH5K_DEBUG is not set
 # CONFIG_ATH9K is not set
+# CONFIG_AR9170_USB is not set
 # CONFIG_IPW2100 is not set
 # CONFIG_IPW2200 is not set
-# CONFIG_IWLCORE is not set
-# CONFIG_IWLWIFI_LEDS is not set
-# CONFIG_IWLAGN is not set
-# CONFIG_IWL3945 is not set
+# CONFIG_IWLWIFI is not set
 # CONFIG_HOSTAP is not set
 # CONFIG_B43 is not set
 # CONFIG_B43LEGACY is not set
 # CONFIG_ZD1211RW is not set
 # CONFIG_RT2X00 is not set
+# CONFIG_HERMES is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -1209,6 +1240,8 @@
 # CONFIG_TABLET_USB_KBTAB is not set
 # CONFIG_TABLET_USB_WACOM is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -1303,6 +1336,7 @@
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
 CONFIG_HW_RANDOM_INTEL=y
 CONFIG_HW_RANDOM_AMD=y
 CONFIG_HW_RANDOM_GEODE=y
@@ -1390,7 +1424,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -1424,6 +1457,7 @@
 # CONFIG_SENSORS_ADT7475 is not set
 # CONFIG_SENSORS_K8TEMP is not set
 # CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATK0110 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_I5K_AMB is not set
@@ -1433,6 +1467,7 @@
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_CORETEMP is not set
@@ -1448,11 +1483,14 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
 # CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
@@ -1643,7 +1681,6 @@
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_VT8623 is not set
-# CONFIG_FB_CYBLA is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_ARK is not set
 # CONFIG_FB_PM3 is not set
@@ -1652,6 +1689,7 @@
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
@@ -1738,6 +1776,8 @@
 # CONFIG_SND_INDIGO is not set
 # CONFIG_SND_INDIGOIO is not set
 # CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -1811,15 +1851,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
 CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
 CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
 CONFIG_HID_LOGITECH=y
 CONFIG_LOGITECH_FF=y
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1885,11 +1927,11 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -1931,7 +1973,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -1947,6 +1988,7 @@
 #
 # OTG and related infrastructure
 #
+# CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_UWB is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
@@ -1958,8 +2000,10 @@
 #
 # CONFIG_LEDS_ALIX2 is not set
 # CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_LP5521 is not set
 # CONFIG_LEDS_CLEVO_MAIL is not set
 # CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
 
 #
 # LED Triggers
@@ -1969,6 +2013,10 @@
 # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
 # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
 # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 CONFIG_EDAC=y
@@ -2037,6 +2085,7 @@
 # DMA Devices
 #
 # CONFIG_INTEL_IOATDMA is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 CONFIG_X86_PLATFORM_DEVICES=y
@@ -2071,6 +2120,7 @@
 #
 # CONFIG_EXT2_FS is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
@@ -2101,6 +2151,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
@@ -2151,6 +2206,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -2164,7 +2220,6 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -2251,6 +2306,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
@@ -2266,6 +2322,7 @@
 # CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_HIGHMEM is not set
 CONFIG_DEBUG_BUGVERBOSE=y
@@ -2289,13 +2346,19 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_NOP_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_HAVE_HW_BRANCH_TRACER=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -2305,13 +2368,21 @@
 # CONFIG_SYSPROF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_FTRACE_SYSCALLS is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_POWER_TRACER is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_HW_BRANCH_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_MMIOTRACE is not set
 CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -2321,7 +2392,6 @@
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUG_PER_CPU_MAPS is not set
 # CONFIG_X86_PTDUMP is not set
 CONFIG_DEBUG_RODATA=y
@@ -2329,7 +2399,7 @@
 CONFIG_DEBUG_NX_TEST=m
 # CONFIG_4KSTACKS is not set
 CONFIG_DOUBLEFAULT=y
-# CONFIG_MMIOTRACE is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
 CONFIG_IO_DELAY_TYPE_0X80=0
 CONFIG_IO_DELAY_TYPE_0XED=1
 CONFIG_IO_DELAY_TYPE_UDELAY=2
@@ -2365,6 +2435,8 @@
 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
 # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
 # CONFIG_SECURITY_SMACK is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_IMA is not set
 CONFIG_CRYPTO=y
 
 #
@@ -2380,10 +2452,12 @@
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
 CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_AUTHENC=y
 # CONFIG_CRYPTO_TEST is not set
@@ -2456,6 +2530,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -2467,11 +2542,13 @@
 # CONFIG_CRYPTO_DEV_GEODE is not set
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
 CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
 CONFIG_VIRTUALIZATION=y
 # CONFIG_KVM is not set
 # CONFIG_LGUEST is not set
 # CONFIG_VIRTIO_PCI is not set
 # CONFIG_VIRTIO_BALLOON is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -2489,7 +2566,10 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_AUDIT_GENERIC=y
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/x86/configs/x86_64_defconfig linux-libre-2.6.31-gnu/arch/x86/configs/x86_64_defconfig
--- linux-libre-2.6.30-gnu/arch/x86/configs/x86_64_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/configs/x86_64_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,12 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc4
-# Tue Feb 24 15:44:16 2009
+# Linux kernel version: 2.6.30-rc2
+# Mon May 11 16:22:00 2009
 #
 CONFIG_64BIT=y
 # CONFIG_X86_32 is not set
 CONFIG_X86_64=y
 CONFIG_X86=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
 CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CMOS_UPDATE=y
@@ -34,6 +35,7 @@
 CONFIG_ARCH_HAS_DEFAULT_IDLE=y
 CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_HAVE_DYNAMIC_PER_CPU_AREA=y
 CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
@@ -41,14 +43,14 @@
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_PENDING_IRQ=y
-CONFIG_X86_SMP=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_X86_64_SMP=y
 CONFIG_X86_HT=y
-CONFIG_X86_BIOS_REBOOT=y
 CONFIG_X86_TRAMPOLINE=y
 # CONFIG_KTIME_SCALAR is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -61,10 +63,17 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_TASKSTATS=y
@@ -114,23 +123,26 @@
 CONFIG_NET_NS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_PCSPKR_PLATFORM=y
-# CONFIG_COMPAT_BRK is not set
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -140,6 +152,7 @@
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
@@ -155,6 +168,8 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -167,7 +182,6 @@
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_BLK_DEV_BSG=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 CONFIG_BLOCK_COMPAT=y
@@ -195,12 +209,10 @@
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 CONFIG_SMP=y
 CONFIG_SPARSE_IRQ=y
-# CONFIG_NUMA_MIGRATE_IRQ_DESC is not set
-CONFIG_X86_FIND_SMP_CONFIG=y
 CONFIG_X86_MPPARSE=y
-# CONFIG_X86_ELAN is not set
-# CONFIG_X86_GENERICARCH is not set
+CONFIG_X86_EXTENDED_PLATFORM=y
 # CONFIG_X86_VSMP is not set
+# CONFIG_X86_UV is not set
 CONFIG_SCHED_OMIT_FRAME_POINTER=y
 # CONFIG_PARAVIRT_GUEST is not set
 # CONFIG_MEMTEST is not set
@@ -230,10 +242,10 @@
 # CONFIG_MCORE2 is not set
 CONFIG_GENERIC_CPU=y
 CONFIG_X86_CPU=y
-CONFIG_X86_L1_CACHE_BYTES=128
-CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_BYTES=64
+CONFIG_X86_INTERNODE_CACHE_BYTES=64
 CONFIG_X86_CMPXCHG=y
-CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_L1_CACHE_SHIFT=6
 CONFIG_X86_WP_WORKS_OK=y
 CONFIG_X86_TSC=y
 CONFIG_X86_CMPXCHG64=y
@@ -242,7 +254,7 @@
 CONFIG_X86_DEBUGCTLMSR=y
 CONFIG_CPU_SUP_INTEL=y
 CONFIG_CPU_SUP_AMD=y
-CONFIG_CPU_SUP_CENTAUR_64=y
+CONFIG_CPU_SUP_CENTAUR=y
 CONFIG_X86_DS=y
 CONFIG_X86_PTRACE_BTS=y
 CONFIG_HPET_TIMER=y
@@ -269,6 +281,7 @@
 CONFIG_X86_MCE=y
 CONFIG_X86_MCE_INTEL=y
 CONFIG_X86_MCE_AMD=y
+CONFIG_X86_MCE_THRESHOLD=y
 # CONFIG_I8K is not set
 CONFIG_MICROCODE=y
 CONFIG_MICROCODE_INTEL=y
@@ -276,6 +289,7 @@
 CONFIG_MICROCODE_OLD_INTERFACE=y
 CONFIG_X86_MSR=y
 CONFIG_X86_CPUID=y
+# CONFIG_X86_CPU_DEBUG is not set
 CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
 CONFIG_DIRECT_GBPAGES=y
 CONFIG_NUMA=y
@@ -309,6 +323,8 @@
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_X86_CHECK_BIOS_CORRUPTION=y
 CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
 CONFIG_X86_RESERVE_LOW_64K=y
@@ -317,6 +333,7 @@
 CONFIG_X86_PAT=y
 CONFIG_EFI=y
 CONFIG_SECCOMP=y
+# CONFIG_CC_STACKPROTECTOR is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_250 is not set
 # CONFIG_HZ_300 is not set
@@ -325,9 +342,10 @@
 CONFIG_SCHED_HRTICK=y
 CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
+# CONFIG_KEXEC_JUMP is not set
 CONFIG_PHYSICAL_START=0x1000000
-# CONFIG_RELOCATABLE is not set
-CONFIG_PHYSICAL_ALIGN=0x200000
+CONFIG_RELOCATABLE=y
+CONFIG_PHYSICAL_ALIGN=0x1000000
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_COMPAT_VDSO is not set
 # CONFIG_CMDLINE_BOOL is not set
@@ -370,7 +388,6 @@
 CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 # CONFIG_ACPI_PCI_SLOT is not set
-CONFIG_ACPI_SYSTEM=y
 CONFIG_X86_PM_TIMER=y
 CONFIG_ACPI_CONTAINER=y
 # CONFIG_ACPI_SBS is not set
@@ -436,6 +453,7 @@
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
 CONFIG_ISA_DMA_API=y
 CONFIG_K8_NB=y
 CONFIG_PCCARD=y
@@ -481,7 +499,6 @@
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -639,6 +656,7 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -696,6 +714,7 @@
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
 CONFIG_HAMRADIO=y
 
 #
@@ -706,12 +725,10 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 CONFIG_FIB_RULES=y
 CONFIG_WIRELESS=y
 CONFIG_CFG80211=y
 # CONFIG_CFG80211_REG_DEBUG is not set
-CONFIG_NL80211=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
@@ -788,9 +805,8 @@
 # CONFIG_TIFM_CORE is not set
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_SGI_XP is not set
 # CONFIG_HP_ILO is not set
-# CONFIG_SGI_GRU is not set
+# CONFIG_ISL29003 is not set
 # CONFIG_C2PORT is not set
 
 #
@@ -844,6 +860,7 @@
 # CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_ATA_ACPI=y
@@ -940,6 +957,7 @@
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_IFB is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -977,6 +995,8 @@
 CONFIG_NET_VENDOR_3COM=y
 # CONFIG_VORTEX is not set
 # CONFIG_TYPHOON is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 CONFIG_NET_TULIP=y
 # CONFIG_DE2104X is not set
 # CONFIG_TULIP is not set
@@ -1026,6 +1046,7 @@
 # CONFIG_E1000E is not set
 # CONFIG_IP1000 is not set
 # CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -1040,6 +1061,7 @@
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
 # CONFIG_JME is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
@@ -1049,6 +1071,7 @@
 # CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_NIU is not set
@@ -1058,6 +1081,7 @@
 # CONFIG_BNX2X is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
 CONFIG_TR=y
 # CONFIG_IBMOL is not set
 # CONFIG_3C359 is not set
@@ -1072,8 +1096,8 @@
 # CONFIG_LIBERTAS is not set
 # CONFIG_LIBERTAS_THINFIRM is not set
 # CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
 # CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
 # CONFIG_AIRO_CS is not set
 # CONFIG_PCMCIA_WL3501 is not set
 # CONFIG_PRISM54 is not set
@@ -1083,21 +1107,21 @@
 # CONFIG_RTL8187 is not set
 # CONFIG_ADM8211 is not set
 # CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
 # CONFIG_P54_COMMON is not set
 CONFIG_ATH5K=y
 # CONFIG_ATH5K_DEBUG is not set
 # CONFIG_ATH9K is not set
+# CONFIG_AR9170_USB is not set
 # CONFIG_IPW2100 is not set
 # CONFIG_IPW2200 is not set
-# CONFIG_IWLCORE is not set
-# CONFIG_IWLWIFI_LEDS is not set
-# CONFIG_IWLAGN is not set
-# CONFIG_IWL3945 is not set
+# CONFIG_IWLWIFI is not set
 # CONFIG_HOSTAP is not set
 # CONFIG_B43 is not set
 # CONFIG_B43LEGACY is not set
 # CONFIG_ZD1211RW is not set
 # CONFIG_RT2X00 is not set
+# CONFIG_HERMES is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -1208,6 +1232,8 @@
 # CONFIG_TABLET_USB_KBTAB is not set
 # CONFIG_TABLET_USB_WACOM is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -1301,6 +1327,7 @@
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_HW_RANDOM_INTEL is not set
 # CONFIG_HW_RANDOM_AMD is not set
 CONFIG_NVRAM=y
@@ -1382,7 +1409,6 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -1416,6 +1442,7 @@
 # CONFIG_SENSORS_ADT7475 is not set
 # CONFIG_SENSORS_K8TEMP is not set
 # CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATK0110 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_I5K_AMB is not set
@@ -1425,6 +1452,7 @@
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_CORETEMP is not set
@@ -1440,11 +1468,14 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
 # CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
@@ -1635,6 +1666,7 @@
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
@@ -1720,6 +1752,8 @@
 # CONFIG_SND_INDIGO is not set
 # CONFIG_SND_INDIGOIO is not set
 # CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -1792,15 +1826,17 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
 CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
 CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
 CONFIG_HID_LOGITECH=y
 CONFIG_LOGITECH_FF=y
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
@@ -1866,11 +1902,11 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -1912,7 +1948,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -1928,6 +1963,7 @@
 #
 # OTG and related infrastructure
 #
+# CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_UWB is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
@@ -1939,8 +1975,10 @@
 #
 # CONFIG_LEDS_ALIX2 is not set
 # CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_LP5521 is not set
 # CONFIG_LEDS_CLEVO_MAIL is not set
 # CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
 
 #
 # LED Triggers
@@ -1950,6 +1988,10 @@
 # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
 # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
 # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 CONFIG_EDAC=y
@@ -2018,6 +2060,7 @@
 # DMA Devices
 #
 # CONFIG_INTEL_IOATDMA is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 CONFIG_X86_PLATFORM_DEVICES=y
@@ -2051,6 +2094,7 @@
 #
 # CONFIG_EXT2_FS is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
@@ -2082,6 +2126,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
@@ -2132,6 +2181,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -2145,7 +2195,6 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -2232,6 +2281,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
@@ -2247,6 +2297,7 @@
 # CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
@@ -2269,13 +2320,19 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_NOP_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_HAVE_HW_BRANCH_TRACER=y
+CONFIG_HAVE_FTRACE_SYSCALLS=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -2285,13 +2342,21 @@
 # CONFIG_SYSPROF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_FTRACE_SYSCALLS is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_POWER_TRACER is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_HW_BRANCH_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_MMIOTRACE is not set
 CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -2301,14 +2366,13 @@
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUG_PER_CPU_MAPS is not set
 # CONFIG_X86_PTDUMP is not set
 CONFIG_DEBUG_RODATA=y
 # CONFIG_DEBUG_RODATA_TEST is not set
 CONFIG_DEBUG_NX_TEST=m
 # CONFIG_IOMMU_DEBUG is not set
-# CONFIG_MMIOTRACE is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
 CONFIG_IO_DELAY_TYPE_0X80=0
 CONFIG_IO_DELAY_TYPE_0XED=1
 CONFIG_IO_DELAY_TYPE_UDELAY=2
@@ -2344,6 +2408,8 @@
 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
 # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
 # CONFIG_SECURITY_SMACK is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_IMA is not set
 CONFIG_CRYPTO=y
 
 #
@@ -2359,10 +2425,12 @@
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
 CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_AUTHENC=y
 # CONFIG_CRYPTO_TEST is not set
@@ -2414,6 +2482,7 @@
 #
 CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_AES_X86_64 is not set
+# CONFIG_CRYPTO_AES_NI_INTEL is not set
 # CONFIG_CRYPTO_ANUBIS is not set
 CONFIG_CRYPTO_ARC4=y
 # CONFIG_CRYPTO_BLOWFISH is not set
@@ -2435,6 +2504,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -2444,10 +2514,12 @@
 CONFIG_CRYPTO_HW=y
 # CONFIG_CRYPTO_DEV_HIFN_795X is not set
 CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
 CONFIG_VIRTUALIZATION=y
 # CONFIG_KVM is not set
 # CONFIG_VIRTIO_PCI is not set
 # CONFIG_VIRTIO_BALLOON is not set
+CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
@@ -2464,7 +2536,10 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -druN linux-libre-2.6.30-gnu/arch/x86/crypto/aesni-intel_asm.S linux-libre-2.6.31-gnu/arch/x86/crypto/aesni-intel_asm.S
--- linux-libre-2.6.30-gnu/arch/x86/crypto/aesni-intel_asm.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/crypto/aesni-intel_asm.S	2009-09-09 18:13:59.000000000 -0400
@@ -845,7 +845,7 @@
  */
 ENTRY(aesni_cbc_dec)
 	cmp $16, LEN
-	jb .Lcbc_dec_ret
+	jb .Lcbc_dec_just_ret
 	mov 480(KEYP), KLEN
 	add $240, KEYP
 	movups (IVP), IV
@@ -891,6 +891,7 @@
 	add $16, OUTP
 	cmp $16, LEN
 	jge .Lcbc_dec_loop1
-	movups IV, (IVP)
 .Lcbc_dec_ret:
+	movups IV, (IVP)
+.Lcbc_dec_just_ret:
 	ret
diff -druN linux-libre-2.6.30-gnu/arch/x86/crypto/aesni-intel_glue.c linux-libre-2.6.31-gnu/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-2.6.30-gnu/arch/x86/crypto/aesni-intel_glue.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/crypto/aesni-intel_glue.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,22 @@
 #include <asm/i387.h>
 #include <asm/aes.h>
 
+#if defined(CONFIG_CRYPTO_CTR) || defined(CONFIG_CRYPTO_CTR_MODULE)
+#define HAS_CTR
+#endif
+
+#if defined(CONFIG_CRYPTO_LRW) || defined(CONFIG_CRYPTO_LRW_MODULE)
+#define HAS_LRW
+#endif
+
+#if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE)
+#define HAS_PCBC
+#endif
+
+#if defined(CONFIG_CRYPTO_XTS) || defined(CONFIG_CRYPTO_XTS_MODULE)
+#define HAS_XTS
+#endif
+
 struct async_aes_ctx {
 	struct cryptd_ablkcipher *cryptd_tfm;
 };
@@ -137,6 +153,41 @@
 	}
 };
 
+static void __aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
+
+	aesni_enc(ctx, dst, src);
+}
+
+static void __aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(tfm));
+
+	aesni_dec(ctx, dst, src);
+}
+
+static struct crypto_alg __aesni_alg = {
+	.cra_name		= "__aes-aesni",
+	.cra_driver_name	= "__driver-aes-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_aes_ctx)+AESNI_ALIGN-1,
+	.cra_alignmask		= 0,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(__aesni_alg.cra_list),
+	.cra_u	= {
+		.cipher	= {
+			.cia_min_keysize	= AES_MIN_KEY_SIZE,
+			.cia_max_keysize	= AES_MAX_KEY_SIZE,
+			.cia_setkey		= aes_set_key,
+			.cia_encrypt		= __aes_encrypt,
+			.cia_decrypt		= __aes_decrypt
+		}
+	}
+};
+
 static int ecb_encrypt(struct blkcipher_desc *desc,
 		       struct scatterlist *dst, struct scatterlist *src,
 		       unsigned int nbytes)
@@ -147,6 +198,7 @@
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
@@ -170,6 +222,7 @@
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
@@ -215,6 +268,7 @@
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
@@ -238,6 +292,7 @@
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
@@ -277,8 +332,16 @@
 			unsigned int key_len)
 {
 	struct async_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base;
+	int err;
 
-	return crypto_ablkcipher_setkey(&ctx->cryptd_tfm->base, key, key_len);
+	crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm)
+				    & CRYPTO_TFM_REQ_MASK);
+	err = crypto_ablkcipher_setkey(child, key, key_len);
+	crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child)
+				    & CRYPTO_TFM_RES_MASK);
+	return err;
 }
 
 static int ablk_encrypt(struct ablkcipher_request *req)
@@ -411,6 +474,163 @@
 	},
 };
 
+#ifdef HAS_CTR
+static int ablk_ctr_init(struct crypto_tfm *tfm)
+{
+	struct cryptd_ablkcipher *cryptd_tfm;
+
+	cryptd_tfm = cryptd_alloc_ablkcipher("fpu(ctr(__driver-aes-aesni))",
+					     0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ablk_init_common(tfm, cryptd_tfm);
+	return 0;
+}
+
+static struct crypto_alg ablk_ctr_alg = {
+	.cra_name		= "ctr(aes)",
+	.cra_driver_name	= "ctr-aes-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct async_aes_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(ablk_ctr_alg.cra_list),
+	.cra_init		= ablk_ctr_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.ivsize		= AES_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+			.geniv		= "chainiv",
+		},
+	},
+};
+#endif
+
+#ifdef HAS_LRW
+static int ablk_lrw_init(struct crypto_tfm *tfm)
+{
+	struct cryptd_ablkcipher *cryptd_tfm;
+
+	cryptd_tfm = cryptd_alloc_ablkcipher("fpu(lrw(__driver-aes-aesni))",
+					     0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ablk_init_common(tfm, cryptd_tfm);
+	return 0;
+}
+
+static struct crypto_alg ablk_lrw_alg = {
+	.cra_name		= "lrw(aes)",
+	.cra_driver_name	= "lrw-aes-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_aes_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(ablk_lrw_alg.cra_list),
+	.cra_init		= ablk_lrw_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
+			.ivsize		= AES_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+};
+#endif
+
+#ifdef HAS_PCBC
+static int ablk_pcbc_init(struct crypto_tfm *tfm)
+{
+	struct cryptd_ablkcipher *cryptd_tfm;
+
+	cryptd_tfm = cryptd_alloc_ablkcipher("fpu(pcbc(__driver-aes-aesni))",
+					     0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ablk_init_common(tfm, cryptd_tfm);
+	return 0;
+}
+
+static struct crypto_alg ablk_pcbc_alg = {
+	.cra_name		= "pcbc(aes)",
+	.cra_driver_name	= "pcbc-aes-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_aes_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(ablk_pcbc_alg.cra_list),
+	.cra_init		= ablk_pcbc_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.ivsize		= AES_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+};
+#endif
+
+#ifdef HAS_XTS
+static int ablk_xts_init(struct crypto_tfm *tfm)
+{
+	struct cryptd_ablkcipher *cryptd_tfm;
+
+	cryptd_tfm = cryptd_alloc_ablkcipher("fpu(xts(__driver-aes-aesni))",
+					     0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ablk_init_common(tfm, cryptd_tfm);
+	return 0;
+}
+
+static struct crypto_alg ablk_xts_alg = {
+	.cra_name		= "xts(aes)",
+	.cra_driver_name	= "xts-aes-aesni",
+	.cra_priority		= 400,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_aes_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(ablk_xts_alg.cra_list),
+	.cra_init		= ablk_xts_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+			.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+			.ivsize		= AES_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+};
+#endif
+
 static int __init aesni_init(void)
 {
 	int err;
@@ -421,6 +641,8 @@
 	}
 	if ((err = crypto_register_alg(&aesni_alg)))
 		goto aes_err;
+	if ((err = crypto_register_alg(&__aesni_alg)))
+		goto __aes_err;
 	if ((err = crypto_register_alg(&blk_ecb_alg)))
 		goto blk_ecb_err;
 	if ((err = crypto_register_alg(&blk_cbc_alg)))
@@ -429,9 +651,41 @@
 		goto ablk_ecb_err;
 	if ((err = crypto_register_alg(&ablk_cbc_alg)))
 		goto ablk_cbc_err;
+#ifdef HAS_CTR
+	if ((err = crypto_register_alg(&ablk_ctr_alg)))
+		goto ablk_ctr_err;
+#endif
+#ifdef HAS_LRW
+	if ((err = crypto_register_alg(&ablk_lrw_alg)))
+		goto ablk_lrw_err;
+#endif
+#ifdef HAS_PCBC
+	if ((err = crypto_register_alg(&ablk_pcbc_alg)))
+		goto ablk_pcbc_err;
+#endif
+#ifdef HAS_XTS
+	if ((err = crypto_register_alg(&ablk_xts_alg)))
+		goto ablk_xts_err;
+#endif
 
 	return err;
 
+#ifdef HAS_XTS
+ablk_xts_err:
+#endif
+#ifdef HAS_PCBC
+	crypto_unregister_alg(&ablk_pcbc_alg);
+ablk_pcbc_err:
+#endif
+#ifdef HAS_LRW
+	crypto_unregister_alg(&ablk_lrw_alg);
+ablk_lrw_err:
+#endif
+#ifdef HAS_CTR
+	crypto_unregister_alg(&ablk_ctr_alg);
+ablk_ctr_err:
+#endif
+	crypto_unregister_alg(&ablk_cbc_alg);
 ablk_cbc_err:
 	crypto_unregister_alg(&ablk_ecb_alg);
 ablk_ecb_err:
@@ -439,6 +693,8 @@
 blk_cbc_err:
 	crypto_unregister_alg(&blk_ecb_alg);
 blk_ecb_err:
+	crypto_unregister_alg(&__aesni_alg);
+__aes_err:
 	crypto_unregister_alg(&aesni_alg);
 aes_err:
 	return err;
@@ -446,10 +702,23 @@
 
 static void __exit aesni_exit(void)
 {
+#ifdef HAS_XTS
+	crypto_unregister_alg(&ablk_xts_alg);
+#endif
+#ifdef HAS_PCBC
+	crypto_unregister_alg(&ablk_pcbc_alg);
+#endif
+#ifdef HAS_LRW
+	crypto_unregister_alg(&ablk_lrw_alg);
+#endif
+#ifdef HAS_CTR
+	crypto_unregister_alg(&ablk_ctr_alg);
+#endif
 	crypto_unregister_alg(&ablk_cbc_alg);
 	crypto_unregister_alg(&ablk_ecb_alg);
 	crypto_unregister_alg(&blk_cbc_alg);
 	crypto_unregister_alg(&blk_ecb_alg);
+	crypto_unregister_alg(&__aesni_alg);
 	crypto_unregister_alg(&aesni_alg);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/crypto/fpu.c linux-libre-2.6.31-gnu/arch/x86/crypto/fpu.c
--- linux-libre-2.6.30-gnu/arch/x86/crypto/fpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/crypto/fpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,166 @@
+/*
+ * FPU: Wrapper for blkcipher touching fpu
+ *
+ * Copyright (c) Intel Corp.
+ *   Author: Huang Ying <ying.huang@intel.com>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/i387.h>
+
+struct crypto_fpu_ctx {
+	struct crypto_blkcipher *child;
+};
+
+static int crypto_fpu_setkey(struct crypto_tfm *parent, const u8 *key,
+			     unsigned int keylen)
+{
+	struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(parent);
+	struct crypto_blkcipher *child = ctx->child;
+	int err;
+
+	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
+				   CRYPTO_TFM_REQ_MASK);
+	err = crypto_blkcipher_setkey(child, key, keylen);
+	crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
+				     CRYPTO_TFM_RES_MASK);
+	return err;
+}
+
+static int crypto_fpu_encrypt(struct blkcipher_desc *desc_in,
+			      struct scatterlist *dst, struct scatterlist *src,
+			      unsigned int nbytes)
+{
+	int err;
+	struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
+	struct crypto_blkcipher *child = ctx->child;
+	struct blkcipher_desc desc = {
+		.tfm = child,
+		.info = desc_in->info,
+		.flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
+	};
+
+	kernel_fpu_begin();
+	err = crypto_blkcipher_crt(desc.tfm)->encrypt(&desc, dst, src, nbytes);
+	kernel_fpu_end();
+	return err;
+}
+
+static int crypto_fpu_decrypt(struct blkcipher_desc *desc_in,
+			      struct scatterlist *dst, struct scatterlist *src,
+			      unsigned int nbytes)
+{
+	int err;
+	struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
+	struct crypto_blkcipher *child = ctx->child;
+	struct blkcipher_desc desc = {
+		.tfm = child,
+		.info = desc_in->info,
+		.flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
+	};
+
+	kernel_fpu_begin();
+	err = crypto_blkcipher_crt(desc.tfm)->decrypt(&desc, dst, src, nbytes);
+	kernel_fpu_end();
+	return err;
+}
+
+static int crypto_fpu_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+	struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_blkcipher *cipher;
+
+	cipher = crypto_spawn_blkcipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	ctx->child = cipher;
+	return 0;
+}
+
+static void crypto_fpu_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
+	crypto_free_blkcipher(ctx->child);
+}
+
+static struct crypto_instance *crypto_fpu_alloc(struct rtattr **tb)
+{
+	struct crypto_instance *inst;
+	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
+	if (IS_ERR(alg))
+		return ERR_CAST(alg);
+
+	inst = crypto_alloc_instance("fpu", alg);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	inst->alg.cra_flags = alg->cra_flags;
+	inst->alg.cra_priority = alg->cra_priority;
+	inst->alg.cra_blocksize = alg->cra_blocksize;
+	inst->alg.cra_alignmask = alg->cra_alignmask;
+	inst->alg.cra_type = alg->cra_type;
+	inst->alg.cra_blkcipher.ivsize = alg->cra_blkcipher.ivsize;
+	inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+	inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+	inst->alg.cra_ctxsize = sizeof(struct crypto_fpu_ctx);
+	inst->alg.cra_init = crypto_fpu_init_tfm;
+	inst->alg.cra_exit = crypto_fpu_exit_tfm;
+	inst->alg.cra_blkcipher.setkey = crypto_fpu_setkey;
+	inst->alg.cra_blkcipher.encrypt = crypto_fpu_encrypt;
+	inst->alg.cra_blkcipher.decrypt = crypto_fpu_decrypt;
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return inst;
+}
+
+static void crypto_fpu_free(struct crypto_instance *inst)
+{
+	crypto_drop_spawn(crypto_instance_ctx(inst));
+	kfree(inst);
+}
+
+static struct crypto_template crypto_fpu_tmpl = {
+	.name = "fpu",
+	.alloc = crypto_fpu_alloc,
+	.free = crypto_fpu_free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_fpu_module_init(void)
+{
+	return crypto_register_template(&crypto_fpu_tmpl);
+}
+
+static void __exit crypto_fpu_module_exit(void)
+{
+	crypto_unregister_template(&crypto_fpu_tmpl);
+}
+
+module_init(crypto_fpu_module_init);
+module_exit(crypto_fpu_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FPU block cipher wrapper");
diff -druN linux-libre-2.6.30-gnu/arch/x86/crypto/Makefile linux-libre-2.6.31-gnu/arch/x86/crypto/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/crypto/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/crypto/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,8 @@
 # Arch-specific CryptoAPI modules.
 #
 
+obj-$(CONFIG_CRYPTO_FPU) += fpu.o
+
 obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
 obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
 obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/ia32/ia32entry.S linux-libre-2.6.31-gnu/arch/x86/ia32/ia32entry.S
--- linux-libre-2.6.30-gnu/arch/x86/ia32/ia32entry.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/ia32/ia32entry.S	2009-09-09 18:13:59.000000000 -0400
@@ -825,9 +825,11 @@
 	.quad compat_sys_signalfd4
 	.quad sys_eventfd2
 	.quad sys_epoll_create1
-	.quad sys_dup3			/* 330 */
+	.quad sys_dup3				/* 330 */
 	.quad sys_pipe2
 	.quad sys_inotify_init1
 	.quad compat_sys_preadv
 	.quad compat_sys_pwritev
+	.quad compat_sys_rt_tgsigqueueinfo	/* 335 */
+	.quad sys_perf_counter_open
 ia32_syscall_end:
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/acpi.h linux-libre-2.6.31-gnu/arch/x86/include/asm/acpi.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/acpi.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/acpi.h	2009-09-09 18:13:59.000000000 -0400
@@ -144,6 +144,7 @@
 
 #else /* !CONFIG_ACPI */
 
+#define acpi_disabled 1
 #define acpi_lapic 0
 #define acpi_ioapic 0
 static inline void acpi_noirq_set(void) { }
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/alternative.h linux-libre-2.6.31-gnu/arch/x86/include/asm/alternative.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/alternative.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/alternative.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/stddef.h>
+#include <linux/stringify.h>
 #include <asm/asm.h>
 
 /*
@@ -74,6 +75,22 @@
 
 const unsigned char *const *find_nop_table(void);
 
+/* alternative assembly primitive: */
+#define ALTERNATIVE(oldinstr, newinstr, feature)			\
+									\
+      "661:\n\t" oldinstr "\n662:\n"					\
+      ".section .altinstructions,\"a\"\n"				\
+      _ASM_ALIGN "\n"							\
+      _ASM_PTR "661b\n"				/* label           */	\
+      _ASM_PTR "663f\n"				/* new instruction */	\
+      "	 .byte " __stringify(feature) "\n"	/* feature bit     */	\
+      "	 .byte 662b-661b\n"			/* sourcelen       */	\
+      "	 .byte 664f-663f\n"			/* replacementlen  */	\
+      ".previous\n"							\
+      ".section .altinstr_replacement, \"ax\"\n"			\
+      "663:\n\t" newinstr "\n664:\n"		/* replacement     */	\
+      ".previous"
+
 /*
  * Alternative instructions for different CPU types or capabilities.
  *
@@ -87,18 +104,7 @@
  * without volatile and memory clobber.
  */
 #define alternative(oldinstr, newinstr, feature)			\
-	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
-		      ".section .altinstructions,\"a\"\n"		\
-		      _ASM_ALIGN "\n"					\
-		      _ASM_PTR "661b\n"		/* label */		\
-		      _ASM_PTR "663f\n"		/* new instruction */	\
-		      "	 .byte %c0\n"		/* feature bit */	\
-		      "	 .byte 662b-661b\n"	/* sourcelen */		\
-		      "	 .byte 664f-663f\n"	/* replacementlen */	\
-		      ".previous\n"					\
-		      ".section .altinstr_replacement,\"ax\"\n"		\
-		      "663:\n\t" newinstr "\n664:\n"  /* replacement */	\
-		      ".previous" :: "i" (feature) : "memory")
+	asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")
 
 /*
  * Alternative inline assembly with input.
@@ -109,35 +115,16 @@
  * Best is to use constraints that are fixed size (like (%1) ... "r")
  * If you use variable sized constraints like "m" or "g" in the
  * replacement make sure to pad to the worst case length.
+ * Leaving an unused argument 0 to keep API compatibility.
  */
 #define alternative_input(oldinstr, newinstr, feature, input...)	\
-	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
-		      ".section .altinstructions,\"a\"\n"		\
-		      _ASM_ALIGN "\n"					\
-		      _ASM_PTR "661b\n"		/* label */		\
-		      _ASM_PTR "663f\n"		/* new instruction */	\
-		      "	 .byte %c0\n"		/* feature bit */	\
-		      "	 .byte 662b-661b\n"	/* sourcelen */		\
-		      "	 .byte 664f-663f\n"	/* replacementlen */	\
-		      ".previous\n"					\
-		      ".section .altinstr_replacement,\"ax\"\n"		\
-		      "663:\n\t" newinstr "\n664:\n"  /* replacement */	\
-		      ".previous" :: "i" (feature), ##input)
+	asm volatile (ALTERNATIVE(oldinstr, newinstr, feature)		\
+		: : "i" (0), ## input)
 
 /* Like alternative_input, but with a single output argument */
 #define alternative_io(oldinstr, newinstr, feature, output, input...)	\
-	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
-		      ".section .altinstructions,\"a\"\n"		\
-		      _ASM_ALIGN "\n"					\
-		      _ASM_PTR "661b\n"		/* label */		\
-		      _ASM_PTR "663f\n"		/* new instruction */	\
-		      "	 .byte %c[feat]\n"	/* feature bit */	\
-		      "	 .byte 662b-661b\n"	/* sourcelen */		\
-		      "	 .byte 664f-663f\n"	/* replacementlen */	\
-		      ".previous\n"					\
-		      ".section .altinstr_replacement,\"ax\"\n"		\
-		      "663:\n\t" newinstr "\n664:\n"  /* replacement */ \
-		      ".previous" : output : [feat] "i" (feature), ##input)
+	asm volatile (ALTERNATIVE(oldinstr, newinstr, feature)		\
+		: output : "i" (0), ## input)
 
 /*
  * use this macro(s) if you need more than one output parameter
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/amd_iommu.h linux-libre-2.6.31-gnu/arch/x86/include/asm/amd_iommu.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/amd_iommu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/amd_iommu.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,9 +27,13 @@
 extern int amd_iommu_init_dma_ops(void);
 extern void amd_iommu_detect(void);
 extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
+extern void amd_iommu_flush_all_domains(void);
+extern void amd_iommu_flush_all_devices(void);
+extern void amd_iommu_shutdown(void);
 #else
 static inline int amd_iommu_init(void) { return -ENODEV; }
 static inline void amd_iommu_detect(void) { }
+static inline void amd_iommu_shutdown(void) { }
 #endif
 
 #endif /* _ASM_X86_AMD_IOMMU_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/amd_iommu_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/amd_iommu_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/amd_iommu_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/amd_iommu_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -194,6 +194,27 @@
 #define PD_DMA_OPS_MASK		(1UL << 0) /* domain used for dma_ops */
 #define PD_DEFAULT_MASK		(1UL << 1) /* domain is a default dma_ops
 					      domain for an IOMMU */
+extern bool amd_iommu_dump;
+#define DUMP_printk(format, arg...)					\
+	do {								\
+		if (amd_iommu_dump)						\
+			printk(KERN_INFO "AMD IOMMU: " format, ## arg);	\
+	} while(0);
+
+/*
+ * Make iterating over all IOMMUs easier
+ */
+#define for_each_iommu(iommu) \
+	list_for_each_entry((iommu), &amd_iommu_list, list)
+#define for_each_iommu_safe(iommu, next) \
+	list_for_each_entry_safe((iommu), (next), &amd_iommu_list, list)
+
+#define APERTURE_RANGE_SHIFT	27	/* 128 MB */
+#define APERTURE_RANGE_SIZE	(1ULL << APERTURE_RANGE_SHIFT)
+#define APERTURE_RANGE_PAGES	(APERTURE_RANGE_SIZE >> PAGE_SHIFT)
+#define APERTURE_MAX_RANGES	32	/* allows 4GB of DMA address space */
+#define APERTURE_RANGE_INDEX(a)	((a) >> APERTURE_RANGE_SHIFT)
+#define APERTURE_PAGE_INDEX(a)	(((a) >> 21) & 0x3fULL)
 
 /*
  * This structure contains generic data for  IOMMU protection domains
@@ -210,6 +231,26 @@
 };
 
 /*
+ * For dynamic growth the aperture size is split into ranges of 128MB of
+ * DMA address space each. This struct represents one such range.
+ */
+struct aperture_range {
+
+	/* address allocation bitmap */
+	unsigned long *bitmap;
+
+	/*
+	 * Array of PTE pages for the aperture. In this array we save all the
+	 * leaf pages of the domain page table used for the aperture. This way
+	 * we don't need to walk the page table to find a specific PTE. We can
+	 * just calculate its address in constant time.
+	 */
+	u64 *pte_pages[64];
+
+	unsigned long offset;
+};
+
+/*
  * Data container for a dma_ops specific protection domain
  */
 struct dma_ops_domain {
@@ -222,18 +263,10 @@
 	unsigned long aperture_size;
 
 	/* address we start to search for free addresses */
-	unsigned long next_bit;
-
-	/* address allocation bitmap */
-	unsigned long *bitmap;
+	unsigned long next_address;
 
-	/*
-	 * Array of PTE pages for the aperture. In this array we save all the
-	 * leaf pages of the domain page table used for the aperture. This way
-	 * we don't need to walk the page table to find a specific PTE. We can
-	 * just calculate its address in constant time.
-	 */
-	u64 **pte_pages;
+	/* address space relevant data */
+	struct aperture_range *aperture[APERTURE_MAX_RANGES];
 
 	/* This will be set to true when TLB needs to be flushed */
 	bool need_flush;
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/apicdef.h linux-libre-2.6.31-gnu/arch/x86/include/asm/apicdef.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/apicdef.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/apicdef.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #  define	APIC_INTEGRATED(x)	(1)
 #endif
 #define		APIC_XAPIC(x)		((x) >= 0x14)
+#define		APIC_EXT_SPACE(x)	((x) & 0x80000000)
 #define	APIC_TASKPRI	0x80
 #define		APIC_TPRI_MASK		0xFFu
 #define	APIC_ARBPRI	0x90
@@ -116,7 +117,9 @@
 #define		APIC_TDR_DIV_32		0x8
 #define		APIC_TDR_DIV_64		0x9
 #define		APIC_TDR_DIV_128	0xA
-#define	APIC_EILVT0     0x500
+#define	APIC_EFEAT	0x400
+#define	APIC_ECTRL	0x410
+#define APIC_EILVTn(n)	(0x500 + 0x10 * n)
 #define		APIC_EILVT_NR_AMD_K8	1	/* # of extended interrupts */
 #define		APIC_EILVT_NR_AMD_10H	4
 #define		APIC_EILVT_LVTOFF(x)	(((x) >> 4) & 0xF)
@@ -125,9 +128,6 @@
 #define		APIC_EILVT_MSG_NMI	0x4
 #define		APIC_EILVT_MSG_EXT	0x7
 #define		APIC_EILVT_MASKED	(1 << 16)
-#define	APIC_EILVT1     0x510
-#define	APIC_EILVT2     0x520
-#define	APIC_EILVT3     0x530
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 #define APIC_BASE_MSR	0x800
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/apic.h linux-libre-2.6.31-gnu/arch/x86/include/asm/apic.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/apic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/apic.h	2009-09-09 18:13:59.000000000 -0400
@@ -107,8 +107,7 @@
 extern void native_apic_icr_write(u32 low, u32 id);
 extern u64 native_apic_icr_read(void);
 
-#define EIM_8BIT_APIC_ID	0
-#define EIM_32BIT_APIC_ID	1
+extern int x2apic_mode;
 
 #ifdef CONFIG_X86_X2APIC
 /*
@@ -166,10 +165,9 @@
 	return val;
 }
 
-extern int x2apic, x2apic_phys;
+extern int x2apic_phys;
 extern void check_x2apic(void);
 extern void enable_x2apic(void);
-extern void enable_IR_x2apic(void);
 extern void x2apic_icr_write(u32 low, u32 id);
 static inline int x2apic_enabled(void)
 {
@@ -183,6 +181,8 @@
 		return 1;
 	return 0;
 }
+
+#define x2apic_supported()	(cpu_has_x2apic)
 #else
 static inline void check_x2apic(void)
 {
@@ -190,28 +190,20 @@
 static inline void enable_x2apic(void)
 {
 }
-static inline void enable_IR_x2apic(void)
-{
-}
 static inline int x2apic_enabled(void)
 {
 	return 0;
 }
 
-#define	x2apic	0
-
+#define	x2apic_preenabled 0
+#define	x2apic_supported()	0
 #endif
 
-extern int get_physical_broadcast(void);
+extern void enable_IR_x2apic(void);
 
-#ifdef CONFIG_X86_X2APIC
-static inline void ack_x2APIC_irq(void)
-{
-	/* Docs say use 0 for future compatibility */
-	native_apic_msr_write(APIC_EOI, 0);
-}
-#endif
+extern int get_physical_broadcast(void);
 
+extern void apic_disable(void);
 extern int lapic_get_maxlvt(void);
 extern void clear_local_APIC(void);
 extern void connect_bsp_APIC(void);
@@ -252,7 +244,7 @@
 #define local_apic_timer_c2_ok		1
 static inline void init_apic_mappings(void) { }
 static inline void disable_local_APIC(void) { }
-
+static inline void apic_disable(void) { }
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
 #ifdef CONFIG_X86_64
@@ -410,7 +402,7 @@
 {
 	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
 
-	if (APIC_XAPIC(ver))
+	if (APIC_XAPIC(ver) || boot_cpu_has(X86_FEATURE_EXTD_APICID))
 		return (x >> 24) & 0xFF;
 	else
 		return (x >> 24) & 0x0F;
@@ -478,6 +470,9 @@
 extern void default_setup_apic_routing(void);
 
 #ifdef CONFIG_X86_32
+
+extern struct apic apic_default;
+
 /*
  * Set up the logical destination ID.
  *
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/atomic_32.h linux-libre-2.6.31-gnu/arch/x86/include/asm/atomic_32.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/atomic_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/atomic_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,10 @@
  *
  * Atomically reads the value of @v.
  */
-#define atomic_read(v)		((v)->counter)
+static inline int atomic_read(const atomic_t *v)
+{
+	return v->counter;
+}
 
 /**
  * atomic_set - set atomic variable
@@ -28,7 +31,10 @@
  *
  * Atomically sets the value of @v to @i.
  */
-#define atomic_set(v, i)	(((v)->counter) = (i))
+static inline void atomic_set(atomic_t *v, int i)
+{
+	v->counter = i;
+}
 
 /**
  * atomic_add - add integer to atomic variable
@@ -200,8 +206,15 @@
 	return atomic_add_return(-i, v);
 }
 
-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	return cmpxchg(&v->counter, old, new);
+}
+
+static inline int atomic_xchg(atomic_t *v, int new)
+{
+	return xchg(&v->counter, new);
+}
 
 /**
  * atomic_add_unless - add unless the number is already a given value
@@ -247,5 +260,156 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+/* An 64bit atomic type */
+
+typedef struct {
+	u64 __aligned(8) counter;
+} atomic64_t;
+
+#define ATOMIC64_INIT(val)	{ (val) }
+
+extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val);
+
+/**
+ * atomic64_xchg - xchg atomic64 variable
+ * @ptr:      pointer to type atomic64_t
+ * @new_val:  value to assign
+ *
+ * Atomically xchgs the value of @ptr to @new_val and returns
+ * the old value.
+ */
+extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val);
+
+/**
+ * atomic64_set - set atomic64 variable
+ * @ptr:      pointer to type atomic64_t
+ * @new_val:  value to assign
+ *
+ * Atomically sets the value of @ptr to @new_val.
+ */
+extern void atomic64_set(atomic64_t *ptr, u64 new_val);
+
+/**
+ * atomic64_read - read atomic64 variable
+ * @ptr:      pointer to type atomic64_t
+ *
+ * Atomically reads the value of @ptr and returns it.
+ */
+static inline u64 atomic64_read(atomic64_t *ptr)
+{
+	u64 res;
+
+	/*
+	 * Note, we inline this atomic64_t primitive because
+	 * it only clobbers EAX/EDX and leaves the others
+	 * untouched. We also (somewhat subtly) rely on the
+	 * fact that cmpxchg8b returns the current 64-bit value
+	 * of the memory location we are touching:
+	 */
+	asm volatile(
+		"mov %%ebx, %%eax\n\t"
+		"mov %%ecx, %%edx\n\t"
+		LOCK_PREFIX "cmpxchg8b %1\n"
+			: "=&A" (res)
+			: "m" (*ptr)
+		);
+
+	return res;
+}
+
+extern u64 atomic64_read(atomic64_t *ptr);
+
+/**
+ * atomic64_add_return - add and return
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr and returns @delta + *@ptr
+ */
+extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr);
+
+/*
+ * Other variants with different arithmetic operators:
+ */
+extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr);
+extern u64 atomic64_inc_return(atomic64_t *ptr);
+extern u64 atomic64_dec_return(atomic64_t *ptr);
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr.
+ */
+extern void atomic64_add(u64 delta, atomic64_t *ptr);
+
+/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @delta: integer value to subtract
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically subtracts @delta from @ptr.
+ */
+extern void atomic64_sub(u64 delta, atomic64_t *ptr);
+
+/**
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @delta: integer value to subtract
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically subtracts @delta from @ptr and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr);
+
+/**
+ * atomic64_inc - increment atomic64 variable
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically increments @ptr by 1.
+ */
+extern void atomic64_inc(atomic64_t *ptr);
+
+/**
+ * atomic64_dec - decrement atomic64 variable
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically decrements @ptr by 1.
+ */
+extern void atomic64_dec(atomic64_t *ptr);
+
+/**
+ * atomic64_dec_and_test - decrement and test
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically decrements @ptr by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+extern int atomic64_dec_and_test(atomic64_t *ptr);
+
+/**
+ * atomic64_inc_and_test - increment and test
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically increments @ptr by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+extern int atomic64_inc_and_test(atomic64_t *ptr);
+
+/**
+ * atomic64_add_negative - add and test if negative
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+extern int atomic64_add_negative(u64 delta, atomic64_t *ptr);
+
+#include <asm-generic/atomic-long.h>
 #endif /* _ASM_X86_ATOMIC_32_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/atomic_64.h linux-libre-2.6.31-gnu/arch/x86/include/asm/atomic_64.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/atomic_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/atomic_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,10 @@
  *
  * Atomically reads the value of @v.
  */
-#define atomic_read(v)		((v)->counter)
+static inline int atomic_read(const atomic_t *v)
+{
+	return v->counter;
+}
 
 /**
  * atomic_set - set atomic variable
@@ -27,7 +30,10 @@
  *
  * Atomically sets the value of @v to @i.
  */
-#define atomic_set(v, i)		(((v)->counter) = (i))
+static inline void atomic_set(atomic_t *v, int i)
+{
+	v->counter = i;
+}
 
 /**
  * atomic_add - add integer to atomic variable
@@ -192,7 +198,10 @@
  * Atomically reads the value of @v.
  * Doesn't imply a read memory barrier.
  */
-#define atomic64_read(v)		((v)->counter)
+static inline long atomic64_read(const atomic64_t *v)
+{
+	return v->counter;
+}
 
 /**
  * atomic64_set - set atomic64 variable
@@ -201,7 +210,10 @@
  *
  * Atomically sets the value of @v to @i.
  */
-#define atomic64_set(v, i)		(((v)->counter) = (i))
+static inline void atomic64_set(atomic64_t *v, long i)
+{
+	v->counter = i;
+}
 
 /**
  * atomic64_add - add integer to atomic64 variable
@@ -355,11 +367,25 @@
 #define atomic64_inc_return(v)  (atomic64_add_return(1, (v)))
 #define atomic64_dec_return(v)  (atomic64_sub_return(1, (v)))
 
-#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
-#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
+{
+	return cmpxchg(&v->counter, old, new);
+}
 
-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+static inline long atomic64_xchg(atomic64_t *v, long new)
+{
+	return xchg(&v->counter, new);
+}
+
+static inline long atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	return cmpxchg(&v->counter, old, new);
+}
+
+static inline long atomic_xchg(atomic_t *v, int new)
+{
+	return xchg(&v->counter, new);
+}
 
 /**
  * atomic_add_unless - add unless the number is a given value
@@ -455,5 +481,5 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* _ASM_X86_ATOMIC_64_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/x86/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,13 @@
+#ifndef __ASM_X86_BITSPERLONG_H
+#define __ASM_X86_BITSPERLONG_H
+
+#ifdef __x86_64__
+# define __BITS_PER_LONG 64
+#else
+# define __BITS_PER_LONG 32
+#endif
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_X86_BITSPERLONG_H */
+
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/boot.h linux-libre-2.6.31-gnu/arch/x86/include/asm/boot.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/boot.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/boot.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,11 +8,26 @@
 
 #ifdef __KERNEL__
 
+#include <asm/pgtable_types.h>
+
 /* Physical address where kernel should be loaded. */
 #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
 				+ (CONFIG_PHYSICAL_ALIGN - 1)) \
 				& ~(CONFIG_PHYSICAL_ALIGN - 1))
 
+/* Minimum kernel alignment, as a power of two */
+#ifdef CONFIG_X86_64
+#define MIN_KERNEL_ALIGN_LG2	PMD_SHIFT
+#else
+#define MIN_KERNEL_ALIGN_LG2	(PAGE_SHIFT + THREAD_ORDER)
+#endif
+#define MIN_KERNEL_ALIGN	(_AC(1, UL) << MIN_KERNEL_ALIGN_LG2)
+
+#if (CONFIG_PHYSICAL_ALIGN & (CONFIG_PHYSICAL_ALIGN-1)) || \
+	(CONFIG_PHYSICAL_ALIGN < (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2))
+#error "Invalid value for CONFIG_PHYSICAL_ALIGN"
+#endif
+
 #ifdef CONFIG_KERNEL_BZIP2
 #define BOOT_HEAP_SIZE             0x400000
 #else /* !CONFIG_KERNEL_BZIP2 */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/bootparam.h linux-libre-2.6.31-gnu/arch/x86/include/asm/bootparam.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/bootparam.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/bootparam.h	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,8 @@
 	__u32	ramdisk_size;
 	__u32	bootsect_kludge;
 	__u16	heap_end_ptr;
-	__u16	_pad1;
+	__u8	ext_loader_ver;
+	__u8	ext_loader_type;
 	__u32	cmd_line_ptr;
 	__u32	initrd_addr_max;
 	__u32	kernel_alignment;
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/cpu_debug.h linux-libre-2.6.31-gnu/arch/x86/include/asm/cpu_debug.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/cpu_debug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/cpu_debug.h	2009-09-09 18:13:59.000000000 -0400
@@ -86,105 +86,7 @@
 	CPU_VALUE_BIT,				/* value		*/
 };
 
-#define	CPU_FILE_VALUE			(1 << CPU_VALUE_BIT)
-
-/*
- * DisplayFamily_DisplayModel	Processor Families/Processor Number Series
- * --------------------------	------------------------------------------
- * 05_01, 05_02, 05_04		Pentium, Pentium with MMX
- *
- * 06_01			Pentium Pro
- * 06_03, 06_05			Pentium II Xeon, Pentium II
- * 06_07, 06_08, 06_0A, 06_0B	Pentium III Xeon, Pentum III
- *
- * 06_09, 060D			Pentium M
- *
- * 06_0E			Core Duo, Core Solo
- *
- * 06_0F			Xeon 3000, 3200, 5100, 5300, 7300 series,
- *				Core 2 Quad, Core 2 Extreme, Core 2 Duo,
- *				Pentium dual-core
- * 06_17			Xeon 5200, 5400 series, Core 2 Quad Q9650
- *
- * 06_1C			Atom
- *
- * 0F_00, 0F_01, 0F_02		Xeon, Xeon MP, Pentium 4
- * 0F_03, 0F_04			Xeon, Xeon MP, Pentium 4, Pentium D
- *
- * 0F_06			Xeon 7100, 5000 Series, Xeon MP,
- *				Pentium 4, Pentium D
- */
-
-/* Register processors bits */
-enum cpu_processor_bit {
-	CPU_NONE,
-/* Intel */
-	CPU_INTEL_PENTIUM_BIT,
-	CPU_INTEL_P6_BIT,
-	CPU_INTEL_PENTIUM_M_BIT,
-	CPU_INTEL_CORE_BIT,
-	CPU_INTEL_CORE2_BIT,
-	CPU_INTEL_ATOM_BIT,
-	CPU_INTEL_XEON_P4_BIT,
-	CPU_INTEL_XEON_MP_BIT,
-/* AMD */
-	CPU_AMD_K6_BIT,
-	CPU_AMD_K7_BIT,
-	CPU_AMD_K8_BIT,
-	CPU_AMD_0F_BIT,
-	CPU_AMD_10_BIT,
-	CPU_AMD_11_BIT,
-};
-
-#define	CPU_INTEL_PENTIUM	(1 << CPU_INTEL_PENTIUM_BIT)
-#define	CPU_INTEL_P6		(1 << CPU_INTEL_P6_BIT)
-#define	CPU_INTEL_PENTIUM_M	(1 << CPU_INTEL_PENTIUM_M_BIT)
-#define	CPU_INTEL_CORE		(1 << CPU_INTEL_CORE_BIT)
-#define	CPU_INTEL_CORE2		(1 << CPU_INTEL_CORE2_BIT)
-#define	CPU_INTEL_ATOM		(1 << CPU_INTEL_ATOM_BIT)
-#define	CPU_INTEL_XEON_P4	(1 << CPU_INTEL_XEON_P4_BIT)
-#define	CPU_INTEL_XEON_MP	(1 << CPU_INTEL_XEON_MP_BIT)
-
-#define	CPU_INTEL_PX		(CPU_INTEL_P6 | CPU_INTEL_PENTIUM_M)
-#define	CPU_INTEL_COREX		(CPU_INTEL_CORE | CPU_INTEL_CORE2)
-#define	CPU_INTEL_XEON		(CPU_INTEL_XEON_P4 | CPU_INTEL_XEON_MP)
-#define	CPU_CO_AT		(CPU_INTEL_CORE | CPU_INTEL_ATOM)
-#define	CPU_C2_AT		(CPU_INTEL_CORE2 | CPU_INTEL_ATOM)
-#define	CPU_CX_AT		(CPU_INTEL_COREX | CPU_INTEL_ATOM)
-#define	CPU_CX_XE		(CPU_INTEL_COREX | CPU_INTEL_XEON)
-#define	CPU_P6_XE		(CPU_INTEL_P6 | CPU_INTEL_XEON)
-#define	CPU_PM_CO_AT		(CPU_INTEL_PENTIUM_M | CPU_CO_AT)
-#define	CPU_C2_AT_XE		(CPU_C2_AT | CPU_INTEL_XEON)
-#define	CPU_CX_AT_XE		(CPU_CX_AT | CPU_INTEL_XEON)
-#define	CPU_P6_CX_AT		(CPU_INTEL_P6 | CPU_CX_AT)
-#define	CPU_P6_CX_XE		(CPU_P6_XE | CPU_INTEL_COREX)
-#define	CPU_P6_CX_AT_XE		(CPU_INTEL_P6 | CPU_CX_AT_XE)
-#define	CPU_PM_CX_AT_XE		(CPU_INTEL_PENTIUM_M | CPU_CX_AT_XE)
-#define	CPU_PM_CX_AT		(CPU_INTEL_PENTIUM_M | CPU_CX_AT)
-#define	CPU_PM_CX_XE		(CPU_INTEL_PENTIUM_M | CPU_CX_XE)
-#define	CPU_PX_CX_AT		(CPU_INTEL_PX | CPU_CX_AT)
-#define	CPU_PX_CX_AT_XE		(CPU_INTEL_PX | CPU_CX_AT_XE)
-
-/* Select all supported Intel CPUs */
-#define	CPU_INTEL_ALL		(CPU_INTEL_PENTIUM | CPU_PX_CX_AT_XE)
-
-#define	CPU_AMD_K6		(1 << CPU_AMD_K6_BIT)
-#define	CPU_AMD_K7		(1 << CPU_AMD_K7_BIT)
-#define	CPU_AMD_K8		(1 << CPU_AMD_K8_BIT)
-#define	CPU_AMD_0F		(1 << CPU_AMD_0F_BIT)
-#define	CPU_AMD_10		(1 << CPU_AMD_10_BIT)
-#define	CPU_AMD_11		(1 << CPU_AMD_11_BIT)
-
-#define	CPU_K10_PLUS		(CPU_AMD_10 | CPU_AMD_11)
-#define	CPU_K0F_PLUS		(CPU_AMD_0F | CPU_K10_PLUS)
-#define	CPU_K8_PLUS		(CPU_AMD_K8 | CPU_K0F_PLUS)
-#define	CPU_K7_PLUS		(CPU_AMD_K7 | CPU_K8_PLUS)
-
-/* Select all supported AMD CPUs */
-#define	CPU_AMD_ALL		(CPU_AMD_K6 | CPU_K7_PLUS)
-
-/* Select all supported CPUs */
-#define	CPU_ALL			(CPU_INTEL_ALL | CPU_AMD_ALL)
+#define	CPU_FILE_VALUE		(1 << CPU_VALUE_BIT)
 
 #define MAX_CPU_FILES		512
 
@@ -220,7 +122,6 @@
 	unsigned		min;		/* Register range min	*/
 	unsigned		max;		/* Register range max	*/
 	unsigned		flag;		/* Supported flags	*/
-	unsigned		model;		/* Supported models	*/
 };
 
 #endif /* _ASM_X86_CPU_DEBUG_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/cpufeature.h linux-libre-2.6.31-gnu/arch/x86/include/asm/cpufeature.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/cpufeature.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/cpufeature.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,7 @@
 #define X86_FEATURE_TSC		(0*32+ 4) /* Time Stamp Counter */
 #define X86_FEATURE_MSR		(0*32+ 5) /* Model-Specific Registers */
 #define X86_FEATURE_PAE		(0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Architecture */
+#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Exception */
 #define X86_FEATURE_CX8		(0*32+ 8) /* CMPXCHG8 instruction */
 #define X86_FEATURE_APIC	(0*32+ 9) /* Onboard APIC */
 #define X86_FEATURE_SEP		(0*32+11) /* SYSENTER/SYSEXIT */
@@ -94,6 +94,7 @@
 #define X86_FEATURE_TSC_RELIABLE (3*32+23) /* TSC is known to be reliable */
 #define X86_FEATURE_NONSTOP_TSC	(3*32+24) /* TSC does not stop in C states */
 #define X86_FEATURE_CLFLUSH_MONITOR (3*32+25) /* "" clflush reqd with monitor */
+#define X86_FEATURE_EXTD_APICID	(3*32+26) /* has extended APICID (8 bits) */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* "pni" SSE-3 */
@@ -115,6 +116,8 @@
 #define X86_FEATURE_XMM4_1	(4*32+19) /* "sse4_1" SSE-4.1 */
 #define X86_FEATURE_XMM4_2	(4*32+20) /* "sse4_2" SSE-4.2 */
 #define X86_FEATURE_X2APIC	(4*32+21) /* x2APIC */
+#define X86_FEATURE_MOVBE	(4*32+22) /* MOVBE instruction */
+#define X86_FEATURE_POPCNT      (4*32+23) /* POPCNT instruction */
 #define X86_FEATURE_AES		(4*32+25) /* AES instructions */
 #define X86_FEATURE_XSAVE	(4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
 #define X86_FEATURE_OSXSAVE	(4*32+27) /* "" XSAVE enabled in the OS */
@@ -192,11 +195,11 @@
 #define clear_cpu_cap(c, bit)	clear_bit(bit, (unsigned long *)((c)->x86_capability))
 #define setup_clear_cpu_cap(bit) do { \
 	clear_cpu_cap(&boot_cpu_data, bit);	\
-	set_bit(bit, (unsigned long *)cleared_cpu_caps); \
+	set_bit(bit, (unsigned long *)cpu_caps_cleared); \
 } while (0)
 #define setup_force_cpu_cap(bit) do { \
 	set_cpu_cap(&boot_cpu_data, bit);	\
-	clear_bit(bit, (unsigned long *)cleared_cpu_caps);	\
+	set_bit(bit, (unsigned long *)cpu_caps_set);	\
 } while (0)
 
 #define cpu_has_fpu		boot_cpu_has(X86_FEATURE_FPU)
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/desc.h linux-libre-2.6.31-gnu/arch/x86/include/asm/desc.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/desc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/desc.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,6 @@
 #ifndef _ASM_X86_DESC_H
 #define _ASM_X86_DESC_H
 
-#ifndef __ASSEMBLY__
 #include <asm/desc_defs.h>
 #include <asm/ldt.h>
 #include <asm/mmu.h>
@@ -380,29 +379,4 @@
 	_set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
 }
 
-#else
-/*
- * GET_DESC_BASE reads the descriptor base of the specified segment.
- *
- * Args:
- *    idx - descriptor index
- *    gdt - GDT pointer
- *    base - 32bit register to which the base will be written
- *    lo_w - lo word of the "base" register
- *    lo_b - lo byte of the "base" register
- *    hi_b - hi byte of the low word of the "base" register
- *
- * Example:
- *    GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
- *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
- */
-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
-	movb idx * 8 + 4(gdt), lo_b;			\
-	movb idx * 8 + 7(gdt), hi_b;			\
-	shll $16, base;					\
-	movw idx * 8 + 2(gdt), lo_w;
-
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* _ASM_X86_DESC_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/dma-mapping.h linux-libre-2.6.31-gnu/arch/x86/include/asm/dma-mapping.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/dma-mapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/dma-mapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,7 @@
  * Documentation/DMA-API.txt for documentation.
  */
 
+#include <linux/kmemcheck.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-debug.h>
 #include <linux/dma-attrs.h>
@@ -32,6 +33,8 @@
 #endif
 }
 
+#include <asm-generic/dma-mapping-common.h>
+
 /* Make sure we keep the same behaviour */
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
@@ -52,171 +55,6 @@
 extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
 					dma_addr_t *dma_addr, gfp_t flag);
 
-static inline dma_addr_t
-dma_map_single(struct device *hwdev, void *ptr, size_t size,
-	       enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-	dma_addr_t addr;
-
-	BUG_ON(!valid_dma_direction(dir));
-	addr = ops->map_page(hwdev, virt_to_page(ptr),
-			     (unsigned long)ptr & ~PAGE_MASK, size,
-			     dir, NULL);
-	debug_dma_map_page(hwdev, virt_to_page(ptr),
-			   (unsigned long)ptr & ~PAGE_MASK, size,
-			   dir, addr, true);
-	return addr;
-}
-
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
-		 enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(dev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->unmap_page)
-		ops->unmap_page(dev, addr, size, dir, NULL);
-	debug_dma_unmap_page(dev, addr, size, dir, true);
-}
-
-static inline int
-dma_map_sg(struct device *hwdev, struct scatterlist *sg,
-	   int nents, enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-	int ents;
-
-	BUG_ON(!valid_dma_direction(dir));
-	ents = ops->map_sg(hwdev, sg, nents, dir, NULL);
-	debug_dma_map_sg(hwdev, sg, nents, ents, dir);
-
-	return ents;
-}
-
-static inline void
-dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
-	     enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	debug_dma_unmap_sg(hwdev, sg, nents, dir);
-	if (ops->unmap_sg)
-		ops->unmap_sg(hwdev, sg, nents, dir, NULL);
-}
-
-static inline void
-dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
-			size_t size, enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->sync_single_for_cpu)
-		ops->sync_single_for_cpu(hwdev, dma_handle, size, dir);
-	debug_dma_sync_single_for_cpu(hwdev, dma_handle, size, dir);
-	flush_write_buffers();
-}
-
-static inline void
-dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
-			   size_t size, enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->sync_single_for_device)
-		ops->sync_single_for_device(hwdev, dma_handle, size, dir);
-	debug_dma_sync_single_for_device(hwdev, dma_handle, size, dir);
-	flush_write_buffers();
-}
-
-static inline void
-dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
-			      unsigned long offset, size_t size,
-			      enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->sync_single_range_for_cpu)
-		ops->sync_single_range_for_cpu(hwdev, dma_handle, offset,
-					       size, dir);
-	debug_dma_sync_single_range_for_cpu(hwdev, dma_handle,
-					    offset, size, dir);
-	flush_write_buffers();
-}
-
-static inline void
-dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
-				 unsigned long offset, size_t size,
-				 enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->sync_single_range_for_device)
-		ops->sync_single_range_for_device(hwdev, dma_handle,
-						  offset, size, dir);
-	debug_dma_sync_single_range_for_device(hwdev, dma_handle,
-					       offset, size, dir);
-	flush_write_buffers();
-}
-
-static inline void
-dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
-		    int nelems, enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->sync_sg_for_cpu)
-		ops->sync_sg_for_cpu(hwdev, sg, nelems, dir);
-	debug_dma_sync_sg_for_cpu(hwdev, sg, nelems, dir);
-	flush_write_buffers();
-}
-
-static inline void
-dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
-		       int nelems, enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(hwdev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->sync_sg_for_device)
-		ops->sync_sg_for_device(hwdev, sg, nelems, dir);
-	debug_dma_sync_sg_for_device(hwdev, sg, nelems, dir);
-
-	flush_write_buffers();
-}
-
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-				      size_t offset, size_t size,
-				      enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(dev);
-	dma_addr_t addr;
-
-	BUG_ON(!valid_dma_direction(dir));
-	addr = ops->map_page(dev, page, offset, size, dir, NULL);
-	debug_dma_map_page(dev, page, offset, size, dir, addr, false);
-
-	return addr;
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
-				  size_t size, enum dma_data_direction dir)
-{
-	struct dma_map_ops *ops = get_dma_ops(dev);
-
-	BUG_ON(!valid_dma_direction(dir));
-	if (ops->unmap_page)
-		ops->unmap_page(dev, addr, size, dir, NULL);
-	debug_dma_unmap_page(dev, addr, size, dir, false);
-}
-
 static inline void
 dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	enum dma_data_direction dir)
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/ds.h linux-libre-2.6.31-gnu/arch/x86/include/asm/ds.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/ds.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/ds.h	2009-09-09 18:13:59.000000000 -0400
@@ -15,8 +15,8 @@
  * - buffer allocation (memory accounting)
  *
  *
- * Copyright (C) 2007-2008 Intel Corporation.
- * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008
+ * Copyright (C) 2007-2009 Intel Corporation.
+ * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
  */
 
 #ifndef _ASM_X86_DS_H
@@ -83,8 +83,10 @@
  * The interrupt threshold is independent from the overflow callback
  * to allow users to use their own overflow interrupt handling mechanism.
  *
- * task: the task to request recording for;
- *       NULL for per-cpu recording on the current cpu
+ * The function might sleep.
+ *
+ * task: the task to request recording for
+ * cpu:  the cpu to request recording for
  * base: the base pointer for the (non-pageable) buffer;
  * size: the size of the provided buffer in bytes
  * ovfl: pointer to a function to be called on buffer overflow;
@@ -93,19 +95,28 @@
  *     -1 if no interrupt threshold is requested.
  * flags: a bit-mask of the above flags
  */
-extern struct bts_tracer *ds_request_bts(struct task_struct *task,
-					 void *base, size_t size,
-					 bts_ovfl_callback_t ovfl,
-					 size_t th, unsigned int flags);
-extern struct pebs_tracer *ds_request_pebs(struct task_struct *task,
-					   void *base, size_t size,
-					   pebs_ovfl_callback_t ovfl,
-					   size_t th, unsigned int flags);
+extern struct bts_tracer *ds_request_bts_task(struct task_struct *task,
+					      void *base, size_t size,
+					      bts_ovfl_callback_t ovfl,
+					      size_t th, unsigned int flags);
+extern struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size,
+					     bts_ovfl_callback_t ovfl,
+					     size_t th, unsigned int flags);
+extern struct pebs_tracer *ds_request_pebs_task(struct task_struct *task,
+						void *base, size_t size,
+						pebs_ovfl_callback_t ovfl,
+						size_t th, unsigned int flags);
+extern struct pebs_tracer *ds_request_pebs_cpu(int cpu,
+					       void *base, size_t size,
+					       pebs_ovfl_callback_t ovfl,
+					       size_t th, unsigned int flags);
 
 /*
  * Release BTS or PEBS resources
  * Suspend and resume BTS or PEBS tracing
  *
+ * Must be called with irq's enabled.
+ *
  * tracer: the tracer handle returned from ds_request_~()
  */
 extern void ds_release_bts(struct bts_tracer *tracer);
@@ -115,6 +126,28 @@
 extern void ds_suspend_pebs(struct pebs_tracer *tracer);
 extern void ds_resume_pebs(struct pebs_tracer *tracer);
 
+/*
+ * Release BTS or PEBS resources
+ * Suspend and resume BTS or PEBS tracing
+ *
+ * Cpu tracers must call this on the traced cpu.
+ * Task tracers must call ds_release_~_noirq() for themselves.
+ *
+ * May be called with irq's disabled.
+ *
+ * Returns 0 if successful;
+ * -EPERM if the cpu tracer does not trace the current cpu.
+ * -EPERM if the task tracer does not trace itself.
+ *
+ * tracer: the tracer handle returned from ds_request_~()
+ */
+extern int ds_release_bts_noirq(struct bts_tracer *tracer);
+extern int ds_suspend_bts_noirq(struct bts_tracer *tracer);
+extern int ds_resume_bts_noirq(struct bts_tracer *tracer);
+extern int ds_release_pebs_noirq(struct pebs_tracer *tracer);
+extern int ds_suspend_pebs_noirq(struct pebs_tracer *tracer);
+extern int ds_resume_pebs_noirq(struct pebs_tracer *tracer);
+
 
 /*
  * The raw DS buffer state as it is used for BTS and PEBS recording.
@@ -170,9 +203,9 @@
 		} lbr;
 		/* BTS_TASK_ARRIVES or BTS_TASK_DEPARTS */
 		struct {
-			__u64 jiffies;
+			__u64 clock;
 			pid_t pid;
-		} timestamp;
+		} event;
 	} variant;
 };
 
@@ -201,8 +234,12 @@
 struct pebs_trace {
 	struct ds_trace ds;
 
-	/* the PEBS reset value */
-	unsigned long long reset_value;
+	/* the number of valid counters in the below array */
+	unsigned int counters;
+
+#define MAX_PEBS_COUNTERS 4
+	/* the counter reset value */
+	unsigned long long counter_reset[MAX_PEBS_COUNTERS];
 };
 
 
@@ -237,9 +274,11 @@
  * Returns 0 on success; -Eerrno on error
  *
  * tracer: the tracer handle returned from ds_request_pebs()
+ * counter: the index of the counter
  * value: the new counter reset value
  */
-extern int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value);
+extern int ds_set_pebs_reset(struct pebs_tracer *tracer,
+			     unsigned int counter, u64 value);
 
 /*
  * Initialization
@@ -252,21 +291,12 @@
  */
 extern void ds_switch_to(struct task_struct *prev, struct task_struct *next);
 
-/*
- * Task clone/init and cleanup work
- */
-extern void ds_copy_thread(struct task_struct *tsk, struct task_struct *father);
-extern void ds_exit_thread(struct task_struct *tsk);
-
 #else /* CONFIG_X86_DS */
 
 struct cpuinfo_x86;
 static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {}
 static inline void ds_switch_to(struct task_struct *prev,
 				struct task_struct *next) {}
-static inline void ds_copy_thread(struct task_struct *tsk,
-				  struct task_struct *father) {}
-static inline void ds_exit_thread(struct task_struct *tsk) {}
 
 #endif /* CONFIG_X86_DS */
 #endif /* _ASM_X86_DS_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/efi.h linux-libre-2.6.31-gnu/arch/x86/include/asm/efi.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/efi.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/efi.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,7 @@
 #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)	\
 	efi_call_virt(f, a1, a2, a3, a4, a5, a6)
 
-#define efi_ioremap(addr, size)			ioremap_cache(addr, size)
+#define efi_ioremap(addr, size, type)		ioremap_cache(addr, size)
 
 #else /* !CONFIG_X86_32 */
 
@@ -84,7 +84,8 @@
 	efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
 		  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
-extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size);
+extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
+				 u32 type);
 
 #endif /* CONFIG_X86_32 */
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/entry_arch.h linux-libre-2.6.31-gnu/arch/x86/include/asm/entry_arch.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/entry_arch.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/entry_arch.h	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
 BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
 BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
+BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
 
 BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0,
 		 smp_invalidate_interrupt)
@@ -49,11 +50,19 @@
 BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
 
 #ifdef CONFIG_PERF_COUNTERS
-BUILD_INTERRUPT(perf_counter_interrupt, LOCAL_PERF_VECTOR)
+BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR)
 #endif
 
-#ifdef CONFIG_X86_MCE_P4THERMAL
+#ifdef CONFIG_X86_THERMAL_VECTOR
 BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
 #endif
 
+#ifdef CONFIG_X86_MCE_THRESHOLD
+BUILD_INTERRUPT(threshold_interrupt,THRESHOLD_APIC_VECTOR)
+#endif
+
+#ifdef CONFIG_X86_NEW_MCE
+BUILD_INTERRUPT(mce_self_interrupt,MCE_SELF_VECTOR)
+#endif
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/fixmap.h linux-libre-2.6.31-gnu/arch/x86/include/asm/fixmap.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/fixmap.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/fixmap.h	2009-09-09 18:13:59.000000000 -0400
@@ -111,12 +111,9 @@
 #ifdef CONFIG_PARAVIRT
 	FIX_PARAVIRT_BOOTMAP,
 #endif
-	FIX_TEXT_POKE0,	/* reserve 2 pages for text_poke() */
-	FIX_TEXT_POKE1,
+	FIX_TEXT_POKE1,	/* reserve 2 pages for text_poke() */
+	FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
 	__end_of_permanent_fixed_addresses,
-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
-	FIX_OHCI1394_BASE,
-#endif
 	/*
 	 * 256 temporary boot-time mappings, used by early_ioremap(),
 	 * before ioremap() is functional.
@@ -129,6 +126,9 @@
 	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
 			(__end_of_permanent_fixed_addresses & 255),
 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+	FIX_OHCI1394_BASE,
+#endif
 #ifdef CONFIG_X86_32
 	FIX_WP_TEST,
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/hardirq.h linux-libre-2.6.31-gnu/arch/x86/include/asm/hardirq.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/hardirq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/hardirq.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,8 @@
 	unsigned int irq_spurious_count;
 #endif
 	unsigned int generic_irqs;	/* arch dependent */
+	unsigned int apic_perf_irqs;
+	unsigned int apic_pending_irqs;
 #ifdef CONFIG_SMP
 	unsigned int irq_resched_count;
 	unsigned int irq_call_count;
@@ -20,7 +22,7 @@
 #endif
 #ifdef CONFIG_X86_MCE
 	unsigned int irq_thermal_count;
-# ifdef CONFIG_X86_64
+# ifdef CONFIG_X86_MCE_THRESHOLD
 	unsigned int irq_threshold_count;
 # endif
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/hw_irq.h linux-libre-2.6.31-gnu/arch/x86/include/asm/hw_irq.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/hw_irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/hw_irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,9 +29,12 @@
 extern void apic_timer_interrupt(void);
 extern void generic_interrupt(void);
 extern void error_interrupt(void);
+extern void perf_pending_interrupt(void);
+
 extern void spurious_interrupt(void);
 extern void thermal_interrupt(void);
 extern void reschedule_interrupt(void);
+extern void mce_self_interrupt(void);
 
 extern void invalidate_interrupt(void);
 extern void invalidate_interrupt0(void);
@@ -44,6 +47,7 @@
 extern void invalidate_interrupt7(void);
 
 extern void irq_move_cleanup_interrupt(void);
+extern void reboot_interrupt(void);
 extern void threshold_interrupt(void);
 
 extern void call_function_interrupt(void);
@@ -63,7 +67,26 @@
 extern void init_VISWS_APIC_irqs(void);
 extern void setup_IO_APIC(void);
 extern void disable_IO_APIC(void);
-extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
+
+struct io_apic_irq_attr {
+	int ioapic;
+	int ioapic_pin;
+	int trigger;
+	int polarity;
+};
+
+static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr,
+					int ioapic, int ioapic_pin,
+					int trigger, int polarity)
+{
+	irq_attr->ioapic     = ioapic;
+	irq_attr->ioapic_pin = ioapic_pin;
+	irq_attr->trigger    = trigger;
+	irq_attr->polarity   = polarity;
+}
+
+extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin,
+					struct io_apic_irq_attr *irq_attr);
 extern void setup_ioapic_dest(void);
 
 extern void enable_IO_APIC(void);
@@ -78,7 +101,11 @@
 /* SMP */
 extern void smp_apic_timer_interrupt(struct pt_regs *);
 extern void smp_spurious_interrupt(struct pt_regs *);
+extern void smp_generic_interrupt(struct pt_regs *);
 extern void smp_error_interrupt(struct pt_regs *);
+#ifdef CONFIG_X86_IO_APIC
+extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
+#endif
 #ifdef CONFIG_SMP
 extern void smp_reschedule_interrupt(struct pt_regs *);
 extern void smp_call_function_interrupt(struct pt_regs *);
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/i387.h linux-libre-2.6.31-gnu/arch/x86/include/asm/i387.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/i387.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/i387.h	2009-09-09 18:13:59.000000000 -0400
@@ -67,7 +67,7 @@
 		     ".previous\n"
 		     _ASM_EXTABLE(1b, 3b)
 		     : [err] "=r" (err)
-#if 0 /* See comment in __save_init_fpu() below. */
+#if 0 /* See comment in fxsave() below. */
 		     : [fx] "r" (fx), "m" (*fx), "0" (0));
 #else
 		     : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
@@ -75,14 +75,6 @@
 	return err;
 }
 
-static inline int restore_fpu_checking(struct task_struct *tsk)
-{
-	if (task_thread_info(tsk)->status & TS_XSAVE)
-		return xrstor_checking(&tsk->thread.xstate->xsave);
-	else
-		return fxrstor_checking(&tsk->thread.xstate->fxsave);
-}
-
 /* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
    is pending. Clear the x87 state here by setting it to fixed
    values. The kernel data segment can be sometimes 0 and sometimes
@@ -120,7 +112,7 @@
 		     ".previous\n"
 		     _ASM_EXTABLE(1b, 3b)
 		     : [err] "=r" (err), "=m" (*fx)
-#if 0 /* See comment in __fxsave_clear() below. */
+#if 0 /* See comment in fxsave() below. */
 		     : [fx] "r" (fx), "0" (0));
 #else
 		     : [fx] "cdaSDb" (fx), "0" (0));
@@ -185,12 +177,9 @@
 	asm volatile("fnclex ; fwait");
 }
 
-static inline void restore_fpu(struct task_struct *tsk)
+/* perform fxrstor iff the processor has extended states, otherwise frstor */
+static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
 {
-	if (task_thread_info(tsk)->status & TS_XSAVE) {
-		xrstor_checking(&tsk->thread.xstate->xsave);
-		return;
-	}
 	/*
 	 * The "nop" is needed to make the instructions the same
 	 * length.
@@ -199,7 +188,9 @@
 		"nop ; frstor %1",
 		"fxrstor %1",
 		X86_FEATURE_FXSR,
-		"m" (tsk->thread.xstate->fxsave));
+		"m" (*fx));
+
+	return 0;
 }
 
 /* We need a safe address that is cheap to find and that is already
@@ -262,6 +253,14 @@
 
 #endif	/* CONFIG_X86_64 */
 
+static inline int restore_fpu_checking(struct task_struct *tsk)
+{
+	if (task_thread_info(tsk)->status & TS_XSAVE)
+		return xrstor_checking(&tsk->thread.xstate->xsave);
+	else
+		return fxrstor_checking(&tsk->thread.xstate->fxsave);
+}
+
 /*
  * Signal frame handlers...
  */
@@ -305,18 +304,18 @@
 /*
  * Some instructions like VIA's padlock instructions generate a spurious
  * DNA fault but don't modify SSE registers. And these instructions
- * get used from interrupt context aswell. To prevent these kernel instructions
- * in interrupt context interact wrongly with other user/kernel fpu usage, we
+ * get used from interrupt context as well. To prevent these kernel instructions
+ * in interrupt context interacting wrongly with other user/kernel fpu usage, we
  * should use them only in the context of irq_ts_save/restore()
  */
 static inline int irq_ts_save(void)
 {
 	/*
-	 * If we are in process context, we are ok to take a spurious DNA fault.
-	 * Otherwise, doing clts() in process context require pre-emption to
-	 * be disabled or some heavy lifting like kernel_fpu_begin()
+	 * If in process context and not atomic, we can take a spurious DNA fault.
+	 * Otherwise, doing clts() in process context requires disabling preemption
+	 * or some heavy lifting like kernel_fpu_begin()
 	 */
-	if (!in_interrupt())
+	if (!in_atomic())
 		return 0;
 
 	if (read_cr0() & X86_CR0_TS) {
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/i8259.h linux-libre-2.6.31-gnu/arch/x86/include/asm/i8259.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/i8259.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/i8259.h	2009-09-09 18:13:59.000000000 -0400
@@ -60,8 +60,4 @@
 extern void mask_8259A(void);
 extern void unmask_8259A(void);
 
-#ifdef CONFIG_X86_32
-extern void init_ISA_irqs(void);
-#endif
-
 #endif /* _ASM_X86_I8259_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/intel_arch_perfmon.h linux-libre-2.6.31-gnu/arch/x86/include/asm/intel_arch_perfmon.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/intel_arch_perfmon.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/intel_arch_perfmon.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,31 +0,0 @@
-#ifndef _ASM_X86_INTEL_ARCH_PERFMON_H
-#define _ASM_X86_INTEL_ARCH_PERFMON_H
-
-#define MSR_ARCH_PERFMON_PERFCTR0		0xc1
-#define MSR_ARCH_PERFMON_PERFCTR1		0xc2
-
-#define MSR_ARCH_PERFMON_EVENTSEL0		0x186
-#define MSR_ARCH_PERFMON_EVENTSEL1		0x187
-
-#define ARCH_PERFMON_EVENTSEL0_ENABLE	(1 << 22)
-#define ARCH_PERFMON_EVENTSEL_INT	(1 << 20)
-#define ARCH_PERFMON_EVENTSEL_OS	(1 << 17)
-#define ARCH_PERFMON_EVENTSEL_USR	(1 << 16)
-
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL	(0x3c)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK	(0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX (0)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
-	(1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
-
-union cpuid10_eax {
-	struct {
-		unsigned int version_id:8;
-		unsigned int num_counters:8;
-		unsigned int bit_width:8;
-		unsigned int mask_length:8;
-	} split;
-	unsigned int full;
-};
-
-#endif /* _ASM_X86_INTEL_ARCH_PERFMON_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/io_apic.h linux-libre-2.6.31-gnu/arch/x86/include/asm/io_apic.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/io_apic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/io_apic.h	2009-09-09 18:13:59.000000000 -0400
@@ -154,22 +154,20 @@
 extern int io_apic_get_unique_id(int ioapic, int apic_id);
 extern int io_apic_get_version(int ioapic);
 extern int io_apic_get_redir_entries(int ioapic);
-extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
-				   int edge_level, int active_high_low);
 #endif /* CONFIG_ACPI */
 
+struct io_apic_irq_attr;
+extern int io_apic_set_pci_routing(struct device *dev, int irq,
+		 struct io_apic_irq_attr *irq_attr);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
+extern void ioapic_insert_resources(void);
 
-#ifdef CONFIG_X86_64
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
 extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
-extern void reinit_intr_remapped_IO_APIC(int intr_remapping,
-	struct IO_APIC_route_entry **ioapic_entries);
-#endif
 
 extern void probe_nr_irqs_gsi(void);
 
@@ -183,6 +181,7 @@
 #define io_apic_assign_pci_irqs 0
 static const int timer_through_8259 = 0;
 static inline void ioapic_init_mappings(void)	{ }
+static inline void ioapic_insert_resources(void) { }
 
 static inline void probe_nr_irqs_gsi(void)	{ }
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/iomap.h linux-libre-2.6.31-gnu/arch/x86/include/asm/iomap.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/iomap.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/iomap.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,6 @@
+#ifndef _ASM_X86_IOMAP_H
+#define _ASM_X86_IOMAP_H
+
 /*
  * Copyright © 2008 Ingo Molnar
  *
@@ -31,3 +34,5 @@
 
 void
 iounmap_atomic(void *kvaddr, enum km_type type);
+
+#endif /* _ASM_X86_IOMAP_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/iommu.h linux-libre-2.6.31-gnu/arch/x86/include/asm/iommu.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/iommu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/iommu.h	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,7 @@
 extern struct dma_map_ops nommu_dma_ops;
 extern int force_iommu, no_iommu;
 extern int iommu_detected;
+extern int iommu_pass_through;
 
 /* 10 seconds */
 #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/irqflags.h linux-libre-2.6.31-gnu/arch/x86/include/asm/irqflags.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/irqflags.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/irqflags.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,9 +12,15 @@
 {
 	unsigned long flags;
 
+	/*
+	 * Note: this needs to be "=r" not "=rm", because we have the
+	 * stack offset from what gcc expects at the time the "pop" is
+	 * executed, and so a memory reference with respect to the stack
+	 * would end up using the wrong address.
+	 */
 	asm volatile("# __raw_save_flags\n\t"
 		     "pushf ; pop %0"
-		     : "=g" (flags)
+		     : "=r" (flags)
 		     : /* no input */
 		     : "memory");
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/irq_remapping.h linux-libre-2.6.31-gnu/arch/x86/include/asm/irq_remapping.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/irq_remapping.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/irq_remapping.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 #ifndef _ASM_X86_IRQ_REMAPPING_H
 #define _ASM_X86_IRQ_REMAPPING_H
 
-#define IRTE_DEST(dest) ((x2apic) ? dest : dest << 8)
+#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
 
 #endif	/* _ASM_X86_IRQ_REMAPPING_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/irq_vectors.h linux-libre-2.6.31-gnu/arch/x86/include/asm/irq_vectors.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/irq_vectors.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/irq_vectors.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
  */
 
 #define NMI_VECTOR			0x02
+#define MCE_VECTOR			0x12
 
 /*
  * IDT vectors usable for external interrupt sources start
@@ -34,6 +35,7 @@
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
+# define IA32_SYSCALL_VECTOR		0x80
 #else
 # define IA32_SYSCALL_VECTOR		0x80
 #endif
@@ -86,13 +88,8 @@
 #define CALL_FUNCTION_VECTOR		0xfc
 #define CALL_FUNCTION_SINGLE_VECTOR	0xfb
 #define THERMAL_APIC_VECTOR		0xfa
-
-#ifdef CONFIG_X86_32
-/* 0xf8 - 0xf9 : free */
-#else
-# define THRESHOLD_APIC_VECTOR		0xf9
-# define UV_BAU_MESSAGE			0xf8
-#endif
+#define THRESHOLD_APIC_VECTOR		0xf9
+#define REBOOT_VECTOR			0xf8
 
 /* f0-f7 used for spreading out TLB flushes: */
 #define INVALIDATE_TLB_VECTOR_END	0xf7
@@ -107,14 +104,21 @@
 #define LOCAL_TIMER_VECTOR		0xef
 
 /*
- * Performance monitoring interrupt vector:
+ * Generic system vector for platform specific use
  */
-#define LOCAL_PERF_VECTOR		0xee
+#define GENERIC_INTERRUPT_VECTOR	0xed
 
 /*
- * Generic system vector for platform specific use
+ * Performance monitoring pending work vector:
  */
-#define GENERIC_INTERRUPT_VECTOR	0xed
+#define LOCAL_PENDING_VECTOR		0xec
+
+#define UV_BAU_MESSAGE			0xec
+
+/*
+ * Self IPI vector for machine checks
+ */
+#define MCE_SELF_VECTOR			0xeb
 
 /*
  * First APIC vector available to drivers: (vectors 0x30-0xee) we
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/k8.h linux-libre-2.6.31-gnu/arch/x86/include/asm/k8.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/k8.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/k8.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,4 +12,17 @@
 extern void k8_flush_garts(void);
 extern int k8_scan_nodes(unsigned long start, unsigned long end);
 
+#ifdef CONFIG_K8_NB
+static inline struct pci_dev *node_to_k8_nb_misc(int node)
+{
+	return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
+}
+#else
+static inline struct pci_dev *node_to_k8_nb_misc(int node)
+{
+	return NULL;
+}
+#endif
+
+
 #endif /* _ASM_X86_K8_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,28 +2,11 @@
 #define _ASM_X86_KMAP_TYPES_H
 
 #if defined(CONFIG_X86_32) && defined(CONFIG_DEBUG_HIGHMEM)
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
+#define  __WITH_KM_FENCE
 #endif
 
-enum km_type {
-D(0)	KM_BOUNCE_READ,
-D(1)	KM_SKB_SUNRPC_DATA,
-D(2)	KM_SKB_DATA_SOFTIRQ,
-D(3)	KM_USER0,
-D(4)	KM_USER1,
-D(5)	KM_BIO_SRC_IRQ,
-D(6)	KM_BIO_DST_IRQ,
-D(7)	KM_PTE0,
-D(8)	KM_PTE1,
-D(9)	KM_IRQ0,
-D(10)	KM_IRQ1,
-D(11)	KM_SOFTIRQ0,
-D(12)	KM_SOFTIRQ1,
-D(13)	KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
-#undef D
+#undef __WITH_KM_FENCE
 
 #endif /* _ASM_X86_KMAP_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/kmemcheck.h linux-libre-2.6.31-gnu/arch/x86/include/asm/kmemcheck.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/kmemcheck.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/kmemcheck.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+#ifndef ASM_X86_KMEMCHECK_H
+#define ASM_X86_KMEMCHECK_H
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+
+#ifdef CONFIG_KMEMCHECK
+bool kmemcheck_active(struct pt_regs *regs);
+
+void kmemcheck_show(struct pt_regs *regs);
+void kmemcheck_hide(struct pt_regs *regs);
+
+bool kmemcheck_fault(struct pt_regs *regs,
+	unsigned long address, unsigned long error_code);
+bool kmemcheck_trap(struct pt_regs *regs);
+#else
+static inline bool kmemcheck_active(struct pt_regs *regs)
+{
+	return false;
+}
+
+static inline void kmemcheck_show(struct pt_regs *regs)
+{
+}
+
+static inline void kmemcheck_hide(struct pt_regs *regs)
+{
+}
+
+static inline bool kmemcheck_fault(struct pt_regs *regs,
+	unsigned long address, unsigned long error_code)
+{
+	return false;
+}
+
+static inline bool kmemcheck_trap(struct pt_regs *regs)
+{
+	return false;
+}
+#endif /* CONFIG_KMEMCHECK */
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/kvm.h linux-libre-2.6.31-gnu/arch/x86/include/asm/kvm.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/kvm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/kvm.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #define __KVM_HAVE_MSI
 #define __KVM_HAVE_USER_NMI
 #define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_MSIX
 
 /* Architectural interrupt line count. */
 #define KVM_NR_INTERRUPTS 256
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/kvm_host.h linux-libre-2.6.31-gnu/arch/x86/include/asm/kvm_host.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/kvm_host.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/kvm_host.h	2009-09-09 18:13:59.000000000 -0400
@@ -185,6 +185,7 @@
 		unsigned access:3;
 		unsigned invalid:1;
 		unsigned cr4_pge:1;
+		unsigned nxe:1;
 	};
 };
 
@@ -212,7 +213,6 @@
 	int multimapped;         /* More than one parent_pte? */
 	int root_count;          /* Currently serving as active root */
 	bool unsync;
-	bool global;
 	unsigned int unsync_children;
 	union {
 		u64 *parent_pte;               /* !multimapped */
@@ -261,13 +261,11 @@
 	union kvm_mmu_page_role base_role;
 
 	u64 *pae_root;
+	u64 rsvd_bits_mask[2][4];
 };
 
 struct kvm_vcpu_arch {
 	u64 host_tsc;
-	int interrupt_window_open;
-	unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
-	DECLARE_BITMAP(irq_pending, KVM_NR_INTERRUPTS);
 	/*
 	 * rip and regs accesses must go through
 	 * kvm_{register,rip}_{read,write} functions.
@@ -286,6 +284,7 @@
 	u64 shadow_efer;
 	u64 apic_base;
 	struct kvm_lapic *apic;    /* kernel irqchip context */
+	int32_t apic_arb_prio;
 	int mp_state;
 	int sipi_vector;
 	u64 ia32_misc_enable_msr;
@@ -320,6 +319,8 @@
 	struct kvm_pio_request pio;
 	void *pio_data;
 
+	u8 event_exit_inst_len;
+
 	struct kvm_queued_exception {
 		bool pending;
 		bool has_error_code;
@@ -329,11 +330,12 @@
 
 	struct kvm_queued_interrupt {
 		bool pending;
+		bool soft;
 		u8 nr;
 	} interrupt;
 
 	struct {
-		int active;
+		int vm86_active;
 		u8 save_iopl;
 		struct kvm_save_segment {
 			u16 selector;
@@ -356,9 +358,9 @@
 	unsigned int time_offset;
 	struct page *time_page;
 
+	bool singlestep; /* guest is single stepped by KVM */
 	bool nmi_pending;
 	bool nmi_injected;
-	bool nmi_window_open;
 
 	struct mtrr_state_type mtrr_state;
 	u32 pat;
@@ -392,15 +394,14 @@
 	 */
 	struct list_head active_mmu_pages;
 	struct list_head assigned_dev_head;
-	struct list_head oos_global_pages;
 	struct iommu_domain *iommu_domain;
+	int iommu_flags;
 	struct kvm_pic *vpic;
 	struct kvm_ioapic *vioapic;
 	struct kvm_pit *vpit;
 	struct hlist_head irq_ack_notifier_list;
 	int vapics_in_nmi_mode;
 
-	int round_robin_prev_vcpu;
 	unsigned int tss_addr;
 	struct page *apic_access_page;
 
@@ -423,7 +424,6 @@
 	u32 mmu_recycled;
 	u32 mmu_cache_miss;
 	u32 mmu_unsync;
-	u32 mmu_unsync_global;
 	u32 remote_tlb_flush;
 	u32 lpages;
 };
@@ -443,7 +443,6 @@
 	u32 halt_exits;
 	u32 halt_wakeup;
 	u32 request_irq_exits;
-	u32 request_nmi_exits;
 	u32 irq_exits;
 	u32 host_state_reload;
 	u32 efer_reload;
@@ -511,20 +510,22 @@
 	void (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run);
 	int (*handle_exit)(struct kvm_run *run, struct kvm_vcpu *vcpu);
 	void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
+	void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
+	u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
 	void (*patch_hypercall)(struct kvm_vcpu *vcpu,
 				unsigned char *hypercall_addr);
-	int (*get_irq)(struct kvm_vcpu *vcpu);
-	void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
+	void (*set_irq)(struct kvm_vcpu *vcpu);
+	void (*set_nmi)(struct kvm_vcpu *vcpu);
 	void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
 				bool has_error_code, u32 error_code);
-	bool (*exception_injected)(struct kvm_vcpu *vcpu);
-	void (*inject_pending_irq)(struct kvm_vcpu *vcpu);
-	void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
-				       struct kvm_run *run);
-
+	int (*interrupt_allowed)(struct kvm_vcpu *vcpu);
+	int (*nmi_allowed)(struct kvm_vcpu *vcpu);
+	void (*enable_nmi_window)(struct kvm_vcpu *vcpu);
+	void (*enable_irq_window)(struct kvm_vcpu *vcpu);
+	void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
 	int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
 	int (*get_tdp_level)(void);
-	int (*get_mt_mask_shift)(void);
+	u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
 };
 
 extern struct kvm_x86_ops *kvm_x86_ops;
@@ -538,7 +539,7 @@
 void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte);
 void kvm_mmu_set_base_ptes(u64 base_pte);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 mt_mask);
+		u64 dirty_mask, u64 nx_mask, u64 x_mask);
 
 int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot);
@@ -552,6 +553,7 @@
 			  const void *val, int bytes);
 int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
 		  gpa_t addr, unsigned long *ret);
+u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
 
 extern bool tdp_enabled;
 
@@ -563,6 +565,7 @@
 
 #define EMULTYPE_NO_DECODE	    (1 << 0)
 #define EMULTYPE_TRAP_UD	    (1 << 1)
+#define EMULTYPE_SKIP		    (1 << 2)
 int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
 			unsigned long cr2, u16 error_code, int emulation_type);
 void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context);
@@ -638,7 +641,6 @@
 int kvm_mmu_load(struct kvm_vcpu *vcpu);
 void kvm_mmu_unload(struct kvm_vcpu *vcpu);
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
-void kvm_mmu_sync_global(struct kvm_vcpu *vcpu);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
@@ -769,6 +771,8 @@
 #define HF_GIF_MASK		(1 << 0)
 #define HF_HIF_MASK		(1 << 1)
 #define HF_VINTR_MASK		(1 << 2)
+#define HF_NMI_MASK		(1 << 3)
+#define HF_IRET_MASK		(1 << 4)
 
 /*
  * Hardware virtualization extension instructions may fault if a
@@ -791,5 +795,6 @@
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
 int kvm_age_hva(struct kvm *kvm, unsigned long hva);
+int cpuid_maxphyaddr(struct kvm_vcpu *vcpu);
 
 #endif /* _ASM_X86_KVM_HOST_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/kvm_x86_emulate.h linux-libre-2.6.31-gnu/arch/x86/include/asm/kvm_x86_emulate.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/kvm_x86_emulate.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/kvm_x86_emulate.h	2009-09-09 18:13:59.000000000 -0400
@@ -143,6 +143,9 @@
 	struct fetch_cache fetch;
 };
 
+#define X86_SHADOW_INT_MOV_SS  1
+#define X86_SHADOW_INT_STI     2
+
 struct x86_emulate_ctxt {
 	/* Register state before/after emulation. */
 	struct kvm_vcpu *vcpu;
@@ -152,6 +155,9 @@
 	int mode;
 	u32 cs_base;
 
+	/* interruptibility state, as a result of execution of STI or MOV SS */
+	int interruptibility;
+
 	/* decode cache */
 	struct decode_cache decode;
 };
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/lguest.h linux-libre-2.6.31-gnu/arch/x86/include/asm/lguest.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/lguest.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/lguest.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,8 +17,12 @@
 /* Pages for switcher itself, then two pages per cpu */
 #define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * nr_cpu_ids)
 
-/* We map at -4M for ease of mapping into the guest (one PTE page). */
+/* We map at -4M (-2M for PAE) for ease of mapping (one PTE page). */
+#ifdef CONFIG_X86_PAE
+#define SWITCHER_ADDR 0xFFE00000
+#else
 #define SWITCHER_ADDR 0xFFC00000
+#endif
 
 /* Found in switcher.S */
 extern unsigned long default_idt_entries[];
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/lguest_hcall.h linux-libre-2.6.31-gnu/arch/x86/include/asm/lguest_hcall.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/lguest_hcall.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/lguest_hcall.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,11 +12,13 @@
 #define LHCALL_TS		8
 #define LHCALL_SET_CLOCKEVENT	9
 #define LHCALL_HALT		10
+#define LHCALL_SET_PMD		13
 #define LHCALL_SET_PTE		14
-#define LHCALL_SET_PMD		15
+#define LHCALL_SET_PGD		15
 #define LHCALL_LOAD_TLS		16
 #define LHCALL_NOTIFY		17
 #define LHCALL_LOAD_GDT_ENTRY	18
+#define LHCALL_SEND_INTERRUPTS	19
 
 #define LGUEST_TRAP_ENTRY 0x1F
 
@@ -28,27 +30,28 @@
 #include <asm/hw_irq.h>
 #include <asm/kvm_para.h>
 
-/*G:031 But first, how does our Guest contact the Host to ask for privileged
+/*G:030
+ * But first, how does our Guest contact the Host to ask for privileged
  * operations?  There are two ways: the direct way is to make a "hypercall",
  * to make requests of the Host Itself.
  *
- * We use the KVM hypercall mechanism. Eighteen hypercalls are
- * available: the hypercall number is put in the %eax register, and the
- * arguments (when required) are placed in %ebx, %ecx and %edx.  If a return
- * value makes sense, it's returned in %eax.
+ * We use the KVM hypercall mechanism, though completely different hypercall
+ * numbers. Seventeen hypercalls are available: the hypercall number is put in
+ * the %eax register, and the arguments (when required) are placed in %ebx,
+ * %ecx, %edx and %esi.  If a return value makes sense, it's returned in %eax.
  *
  * Grossly invalid calls result in Sudden Death at the hands of the vengeful
  * Host, rather than returning failure.  This reflects Winston Churchill's
- * definition of a gentleman: "someone who is only rude intentionally". */
-/*:*/
+ * definition of a gentleman: "someone who is only rude intentionally".
+:*/
 
 /* Can't use our min() macro here: needs to be a constant */
 #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
 
 #define LHCALL_RING_SIZE 64
 struct hcall_args {
-	/* These map directly onto eax, ebx, ecx, edx in struct lguest_regs */
-	unsigned long arg0, arg1, arg2, arg3;
+	/* These map directly onto eax/ebx/ecx/edx/esi in struct lguest_regs */
+	unsigned long arg0, arg1, arg2, arg3, arg4;
 };
 
 #endif /* !__ASSEMBLY__ */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/mce.h linux-libre-2.6.31-gnu/arch/x86/include/asm/mce.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/mce.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/mce.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,6 @@
 #ifndef _ASM_X86_MCE_H
 #define _ASM_X86_MCE_H
 
-#ifdef __x86_64__
-
 #include <linux/types.h>
 #include <asm/ioctls.h>
 
@@ -10,21 +8,35 @@
  * Machine Check support for x86
  */
 
-#define MCG_CTL_P	 (1UL<<8)   /* MCG_CAP register available */
-#define MCG_EXT_P	 (1ULL<<9)   /* Extended registers available */
-#define MCG_CMCI_P	 (1ULL<<10)  /* CMCI supported */
+#define MCG_BANKCNT_MASK	0xff         /* Number of Banks */
+#define MCG_CTL_P		(1ULL<<8)    /* MCG_CAP register available */
+#define MCG_EXT_P		(1ULL<<9)    /* Extended registers available */
+#define MCG_CMCI_P		(1ULL<<10)   /* CMCI supported */
+#define MCG_EXT_CNT_MASK	0xff0000     /* Number of Extended registers */
+#define MCG_EXT_CNT_SHIFT	16
+#define MCG_EXT_CNT(c)		(((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
+#define MCG_SER_P	 	(1ULL<<24)   /* MCA recovery/new status bits */
 
-#define MCG_STATUS_RIPV  (1UL<<0)   /* restart ip valid */
-#define MCG_STATUS_EIPV  (1UL<<1)   /* ip points to correct instruction */
-#define MCG_STATUS_MCIP  (1UL<<2)   /* machine check in progress */
+#define MCG_STATUS_RIPV  (1ULL<<0)   /* restart ip valid */
+#define MCG_STATUS_EIPV  (1ULL<<1)   /* ip points to correct instruction */
+#define MCG_STATUS_MCIP  (1ULL<<2)   /* machine check in progress */
 
-#define MCI_STATUS_VAL   (1UL<<63)  /* valid error */
-#define MCI_STATUS_OVER  (1UL<<62)  /* previous errors lost */
-#define MCI_STATUS_UC    (1UL<<61)  /* uncorrected error */
-#define MCI_STATUS_EN    (1UL<<60)  /* error enabled */
-#define MCI_STATUS_MISCV (1UL<<59)  /* misc error reg. valid */
-#define MCI_STATUS_ADDRV (1UL<<58)  /* addr reg. valid */
-#define MCI_STATUS_PCC   (1UL<<57)  /* processor context corrupt */
+#define MCI_STATUS_VAL   (1ULL<<63)  /* valid error */
+#define MCI_STATUS_OVER  (1ULL<<62)  /* previous errors lost */
+#define MCI_STATUS_UC    (1ULL<<61)  /* uncorrected error */
+#define MCI_STATUS_EN    (1ULL<<60)  /* error enabled */
+#define MCI_STATUS_MISCV (1ULL<<59)  /* misc error reg. valid */
+#define MCI_STATUS_ADDRV (1ULL<<58)  /* addr reg. valid */
+#define MCI_STATUS_PCC   (1ULL<<57)  /* processor context corrupt */
+#define MCI_STATUS_S	 (1ULL<<56)  /* Signaled machine check */
+#define MCI_STATUS_AR	 (1ULL<<55)  /* Action required */
+
+/* MISC register defines */
+#define MCM_ADDR_SEGOFF  0	/* segment offset */
+#define MCM_ADDR_LINEAR  1	/* linear address */
+#define MCM_ADDR_PHYS	 2	/* physical address */
+#define MCM_ADDR_MEM	 3	/* memory address */
+#define MCM_ADDR_GENERIC 7	/* generic */
 
 /* Fields are zero when not available */
 struct mce {
@@ -34,13 +46,19 @@
 	__u64 mcgstatus;
 	__u64 ip;
 	__u64 tsc;	/* cpu time stamp counter */
-	__u64 res1;	/* for future extension */
-	__u64 res2;	/* dito. */
+	__u64 time;	/* wall time_t when error was detected */
+	__u8  cpuvendor;	/* cpu vendor as encoded in system.h */
+	__u8  pad1;
+	__u16 pad2;
+	__u32 cpuid;	/* CPUID 1 EAX */
 	__u8  cs;		/* code segment */
 	__u8  bank;	/* machine check bank */
-	__u8  cpu;	/* cpu that raised the error */
+	__u8  cpu;	/* cpu number; obsolete; use extcpu now */
 	__u8  finished;   /* entry is valid */
-	__u32 pad;
+	__u32 extcpu;	/* linux cpu number that detected the error */
+	__u32 socketid;	/* CPU socket ID */
+	__u32 apicid;	/* CPU initial apic ID */
+	__u64 mcgcap;	/* MCGCAP MSR: machine check capabilities of CPU */
 };
 
 /*
@@ -57,7 +75,7 @@
 	unsigned len;	    /* = MCE_LOG_LEN */
 	unsigned next;
 	unsigned flags;
-	unsigned pad0;
+	unsigned recordlen;	/* length of struct mce */
 	struct mce entry[MCE_LOG_LEN];
 };
 
@@ -82,20 +100,41 @@
 #define K8_MCE_THRESHOLD_BANK_5    (MCE_THRESHOLD_BASE + 5 * 9)
 #define K8_MCE_THRESHOLD_DRAM_ECC  (MCE_THRESHOLD_BANK_4 + 0)
 
-#endif /* __x86_64__ */
-
 #ifdef __KERNEL__
 
-#ifdef CONFIG_X86_32
+#include <linux/percpu.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+
 extern int mce_disabled;
-#else /* CONFIG_X86_32 */
+extern int mce_p5_enabled;
 
-#include <asm/atomic.h>
+#ifdef CONFIG_X86_MCE
+void mcheck_init(struct cpuinfo_x86 *c);
+#else
+static inline void mcheck_init(struct cpuinfo_x86 *c) {}
+#endif
+
+#ifdef CONFIG_X86_OLD_MCE
+extern int nr_mce_banks;
+void amd_mcheck_init(struct cpuinfo_x86 *c);
+void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
+void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
+#endif
+
+#ifdef CONFIG_X86_ANCIENT_MCE
+void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
+void winchip_mcheck_init(struct cpuinfo_x86 *c);
+static inline void enable_p5_mce(void) { mce_p5_enabled = 1; }
+#else
+static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
+static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
+static inline void enable_p5_mce(void) {}
+#endif
 
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
-DECLARE_PER_CPU(struct sys_device, device_mce);
-extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
+DECLARE_PER_CPU(struct sys_device, mce_dev);
 
 /*
  * To support more than 128 would need to escape the predefined
@@ -104,6 +143,8 @@
 #define MAX_NR_BANKS (MCE_EXTENDED_BANK - 1)
 
 #ifdef CONFIG_X86_MCE_INTEL
+extern int mce_cmci_disabled;
+extern int mce_ignore_ce;
 void mce_intel_feature_init(struct cpuinfo_x86 *c);
 void cmci_clear(void);
 void cmci_reenable(void);
@@ -123,14 +164,13 @@
 static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
 #endif
 
-extern int mce_available(struct cpuinfo_x86 *c);
+int mce_available(struct cpuinfo_x86 *c);
 
-void mce_log_therm_throt_event(__u64 status);
+DECLARE_PER_CPU(unsigned, mce_exception_count);
+DECLARE_PER_CPU(unsigned, mce_poll_count);
 
 extern atomic_t mce_entry;
 
-extern void do_machine_check(struct pt_regs *, long);
-
 typedef DECLARE_BITMAP(mce_banks_t, MAX_NR_BANKS);
 DECLARE_PER_CPU(mce_banks_t, mce_poll_banks);
 
@@ -139,19 +179,40 @@
 	MCP_UC = (1 << 1),		/* log uncorrected errors */
 	MCP_DONTLOG = (1 << 2),		/* only clear, don't log */
 };
-extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
+void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
 
-extern int mce_notify_user(void);
+int mce_notify_irq(void);
+void mce_notify_process(void);
 
-#endif /* !CONFIG_X86_32 */
+DECLARE_PER_CPU(struct mce, injectm);
+extern struct file_operations mce_chrdev_ops;
 
-#ifdef CONFIG_X86_MCE
-extern void mcheck_init(struct cpuinfo_x86 *c);
-#else
-#define mcheck_init(c) do { } while (0)
-#endif
+/*
+ * Exception handler
+ */
+
+/* Call the installed machine check handler for this CPU setup. */
+extern void (*machine_check_vector)(struct pt_regs *, long error_code);
+void do_machine_check(struct pt_regs *, long);
+
+/*
+ * Threshold handler
+ */
 
 extern void (*mce_threshold_vector)(void);
+extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
+
+/*
+ * Thermal handler
+ */
+
+void intel_init_thermal(struct cpuinfo_x86 *c);
+
+#ifdef CONFIG_X86_NEW_MCE
+void mce_log_therm_throt_event(__u64 status);
+#else
+static inline void mce_log_therm_throt_event(__u64 status) {}
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_MCE_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/microcode.h linux-libre-2.6.31-gnu/arch/x86/include/asm/microcode.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/microcode.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/microcode.h	2009-09-09 18:13:59.000000000 -0400
@@ -9,20 +9,31 @@
 
 struct device;
 
+enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
+
 struct microcode_ops {
-	int  (*request_microcode_user) (int cpu, const void __user *buf, size_t size);
-	int  (*request_microcode_fw) (int cpu, struct device *device);
+	enum ucode_state (*request_microcode_user) (int cpu,
+				const void __user *buf, size_t size);
 
-	void (*apply_microcode) (int cpu);
+	enum ucode_state (*request_microcode_fw) (int cpu,
+				struct device *device);
 
-	int  (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
 	void (*microcode_fini_cpu) (int cpu);
+
+	/*
+	 * The generic 'microcode_core' part guarantees that
+	 * the callbacks below run on a target cpu when they
+	 * are being called.
+	 * See also the "Synchronization" section in microcode_core.c.
+	 */
+	int (*apply_microcode) (int cpu);
+	int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
 };
 
 struct ucode_cpu_info {
-	struct cpu_signature cpu_sig;
-	int valid;
-	void *mc;
+	struct cpu_signature	cpu_sig;
+	int			valid;
+	void			*mc;
 };
 extern struct ucode_cpu_info ucode_cpu_info[];
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/mman.h linux-libre-2.6.31-gnu/arch/x86/include/asm/mman.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/mman.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/mman.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef _ASM_X86_MMAN_H
 #define _ASM_X86_MMAN_H
 
-#include <asm-generic/mman.h>
+#include <asm-generic/mman-common.h>
 
 #define MAP_32BIT	0x40		/* only give out 32bit addresses */
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/mpspec.h linux-libre-2.6.31-gnu/arch/x86/include/asm/mpspec.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/mpspec.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/mpspec.h	2009-09-09 18:13:59.000000000 -0400
@@ -61,9 +61,11 @@
 #ifdef CONFIG_X86_MPPARSE
 extern void find_smp_config(void);
 extern void early_reserve_e820_mpc_new(void);
+extern int enable_update_mptable;
 #else
 static inline void find_smp_config(void) { }
 static inline void early_reserve_e820_mpc_new(void) { }
+#define enable_update_mptable 0
 #endif
 
 void __cpuinit generic_processor_info(int apicid, int version);
@@ -72,20 +74,13 @@
 extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
-extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+struct device;
+extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
+				 int active_high_low);
 extern int acpi_probe_gsi(void);
 #ifdef CONFIG_X86_IO_APIC
-extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
-				u32 gsi, int triggering, int polarity);
 extern int mp_find_ioapic(int gsi);
 extern int mp_find_ioapic_pin(int ioapic, int gsi);
-#else
-static inline int
-mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
-		   u32 gsi, int triggering, int polarity)
-{
-	return 0;
-}
 #endif
 #else /* !CONFIG_ACPI: */
 static inline int acpi_probe_gsi(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/msr.h linux-libre-2.6.31-gnu/arch/x86/include/asm/msr.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/msr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/msr.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,15 +3,23 @@
 
 #include <asm/msr-index.h>
 
-#ifndef __ASSEMBLY__
-# include <linux/types.h>
-#endif
-
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
+#include <linux/types.h>
 #include <asm/asm.h>
 #include <asm/errno.h>
+#include <asm/cpumask.h>
+
+struct msr {
+	union {
+		struct {
+			u32 l;
+			u32 h;
+		};
+		u64 q;
+	};
+};
 
 static inline unsigned long long native_read_tscp(unsigned int *aux)
 {
@@ -216,6 +224,8 @@
 #ifdef CONFIG_SMP
 int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs);
+void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs);
 int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
 #else  /*  CONFIG_SMP  */
@@ -229,6 +239,16 @@
 	wrmsr(msr_no, l, h);
 	return 0;
 }
+static inline void rdmsr_on_cpus(const cpumask_t *m, u32 msr_no,
+				struct msr *msrs)
+{
+       rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h));
+}
+static inline void wrmsr_on_cpus(const cpumask_t *m, u32 msr_no,
+				struct msr *msrs)
+{
+       wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h);
+}
 static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no,
 				    u32 *l, u32 *h)
 {
@@ -241,6 +261,4 @@
 #endif  /* CONFIG_SMP */
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
-
-
 #endif /* _ASM_X86_MSR_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/msr-index.h linux-libre-2.6.31-gnu/arch/x86/include/asm/msr-index.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/msr-index.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/msr-index.h	2009-09-09 18:13:59.000000000 -0400
@@ -121,7 +121,6 @@
 #define MSR_K8_TOP_MEM1			0xc001001a
 #define MSR_K8_TOP_MEM2			0xc001001d
 #define MSR_K8_SYSCFG			0xc0010010
-#define MSR_K8_HWCR			0xc0010015
 #define MSR_K8_INT_PENDING_MSG		0xc0010055
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK		0x18000000
@@ -208,7 +207,14 @@
 
 #define MSR_IA32_THERM_CONTROL		0x0000019a
 #define MSR_IA32_THERM_INTERRUPT	0x0000019b
+
+#define THERM_INT_LOW_ENABLE		(1 << 0)
+#define THERM_INT_HIGH_ENABLE		(1 << 1)
+
 #define MSR_IA32_THERM_STATUS		0x0000019c
+
+#define THERM_STATUS_PROCHOT		(1 << 0)
+
 #define MSR_IA32_MISC_ENABLE		0x000001a0
 
 /* MISC_ENABLE bits: architectural */
@@ -240,10 +246,6 @@
 #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE	(1ULL << 38)
 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE	(1ULL << 39)
 
-/* Intel Model 6 */
-#define MSR_P6_EVNTSEL0			0x00000186
-#define MSR_P6_EVNTSEL1			0x00000187
-
 /* P4/Xeon+ specific */
 #define MSR_IA32_MCG_EAX		0x00000180
 #define MSR_IA32_MCG_EBX		0x00000181
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/nmi.h linux-libre-2.6.31-gnu/arch/x86/include/asm/nmi.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/nmi.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/nmi.h	2009-09-09 18:13:59.000000000 -0400
@@ -64,7 +64,7 @@
 	 * but since they are power of two we could use a
 	 * cheaper way --cvg
 	 */
-	return nmi_watchdog & 0x3;
+	return nmi_watchdog & (NMI_LOCAL_APIC | NMI_IO_APIC);
 }
 #endif
 
@@ -72,7 +72,6 @@
 int lapic_watchdog_init(unsigned nmi_hz);
 int lapic_wd_event(unsigned nmi_hz);
 unsigned lapic_adjust_nmi_hz(unsigned hz);
-int lapic_watchdog_ok(void);
 void disable_lapic_nmi_watchdog(void);
 void enable_lapic_nmi_watchdog(void);
 void stop_nmi(void);
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/numa_64.h linux-libre-2.6.31-gnu/arch/x86/include/asm/numa_64.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/numa_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/numa_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,9 +17,6 @@
 extern void numa_init_array(void);
 extern int numa_off;
 
-extern void srat_reserve_add_area(int nodeid);
-extern int hotadd_percent;
-
 extern s16 apicid_to_node[MAX_LOCAL_APIC];
 
 extern unsigned long numa_free_all_bootmem(void);
@@ -27,6 +24,13 @@
 			       unsigned long end);
 
 #ifdef CONFIG_NUMA
+/*
+ * Too small node sizes may confuse the VM badly. Usually they
+ * result from BIOS bugs. So dont recognize nodes as standalone
+ * NUMA entities that have less than this amount of RAM listed:
+ */
+#define NODE_MIN_SIZE (4*1024*1024)
+
 extern void __init init_cpu_to_node(void);
 extern void __cpuinit numa_set_node(int cpu, int node);
 extern void __cpuinit numa_clear_node(int cpu);
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/page_32_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/page_32_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/page_32_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/page_32_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -54,10 +54,6 @@
 extern int sysctl_legacy_va_layout;
 
 extern void find_low_pfn_range(void);
-extern unsigned long init_memory_mapping(unsigned long start,
-					 unsigned long end);
-extern void initmem_init(unsigned long, unsigned long);
-extern void free_initmem(void);
 extern void setup_bootmem_allocator(void);
 
 #endif	/* !__ASSEMBLY__ */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/page_64_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/page_64_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/page_64_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/page_64_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,24 +32,16 @@
  */
 #define __PAGE_OFFSET           _AC(0xffff880000000000, UL)
 
-#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 __PHYSICAL_START	((CONFIG_PHYSICAL_START +	 	\
+				  (CONFIG_PHYSICAL_ALIGN - 1)) &	\
+				 ~(CONFIG_PHYSICAL_ALIGN - 1))
 
 #define __START_KERNEL		(__START_KERNEL_map + __PHYSICAL_START)
 #define __START_KERNEL_map	_AC(0xffffffff80000000, UL)
 
-/* See Documentation/x86_64/mm.txt for a description of the memory map. */
+/* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */
 #define __PHYSICAL_MASK_SHIFT	46
-#define __VIRTUAL_MASK_SHIFT	48
+#define __VIRTUAL_MASK_SHIFT	47
 
 /*
  * Kernel image size is limited to 512 MB (see level2_kernel_pgt in
@@ -71,12 +63,6 @@
 
 #define vmemmap ((struct page *)VMEMMAP_START)
 
-extern unsigned long init_memory_mapping(unsigned long start,
-					 unsigned long end);
-
-extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn);
-extern void free_initmem(void);
-
 extern void init_extra_mapping_uc(unsigned long phys, unsigned long size);
 extern void init_extra_mapping_wb(unsigned long phys, unsigned long size);
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/page.h linux-libre-2.6.31-gnu/arch/x86/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -56,7 +56,7 @@
 #endif	/* __ASSEMBLY__ */
 
 #include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
 
 #define __HAVE_ARCH_GATE_AREA 1
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/page_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/page_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/page_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/page_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,12 @@
 extern unsigned long max_low_pfn_mapped;
 extern unsigned long max_pfn_mapped;
 
+extern unsigned long init_memory_mapping(unsigned long start,
+					 unsigned long end);
+
+extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn);
+extern void free_initmem(void);
+
 #endif	/* !__ASSEMBLY__ */
 
 #endif	/* _ASM_X86_PAGE_DEFS_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/paravirt.h linux-libre-2.6.31-gnu/arch/x86/include/asm/paravirt.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/paravirt.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/paravirt.h	2009-09-09 18:13:59.000000000 -0400
@@ -56,6 +56,7 @@
 struct tss_struct;
 struct mm_struct;
 struct desc_struct;
+struct task_struct;
 
 /*
  * Wrapper type for pointers to code which uses the non-standard
@@ -203,7 +204,8 @@
 
 	void (*swapgs)(void);
 
-	struct pv_lazy_ops lazy_mode;
+	void (*start_context_switch)(struct task_struct *prev);
+	void (*end_context_switch)(struct task_struct *next);
 };
 
 struct pv_irq_ops {
@@ -1399,25 +1401,23 @@
 };
 
 enum paravirt_lazy_mode paravirt_get_lazy_mode(void);
-void paravirt_enter_lazy_cpu(void);
-void paravirt_leave_lazy_cpu(void);
+void paravirt_start_context_switch(struct task_struct *prev);
+void paravirt_end_context_switch(struct task_struct *next);
+
 void paravirt_enter_lazy_mmu(void);
 void paravirt_leave_lazy_mmu(void);
-void paravirt_leave_lazy(enum paravirt_lazy_mode mode);
 
-#define  __HAVE_ARCH_ENTER_LAZY_CPU_MODE
-static inline void arch_enter_lazy_cpu_mode(void)
+#define  __HAVE_ARCH_START_CONTEXT_SWITCH
+static inline void arch_start_context_switch(struct task_struct *prev)
 {
-	PVOP_VCALL0(pv_cpu_ops.lazy_mode.enter);
+	PVOP_VCALL1(pv_cpu_ops.start_context_switch, prev);
 }
 
-static inline void arch_leave_lazy_cpu_mode(void)
+static inline void arch_end_context_switch(struct task_struct *next)
 {
-	PVOP_VCALL0(pv_cpu_ops.lazy_mode.leave);
+	PVOP_VCALL1(pv_cpu_ops.end_context_switch, next);
 }
 
-void arch_flush_lazy_cpu_mode(void);
-
 #define  __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 static inline void arch_enter_lazy_mmu_mode(void)
 {
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pci.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pci.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pci.h	2009-09-09 18:13:59.000000000 -0400
@@ -91,7 +91,7 @@
 
 #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
 
-#if defined(CONFIG_X86_64) || defined(CONFIG_DMA_API_DEBUG)
+#if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG)
 
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       \
 	        dma_addr_t ADDR_NAME;
@@ -130,6 +130,7 @@
 
 /* generic pci stuff */
 #include <asm-generic/pci.h>
+#define PCIBIOS_MAX_MEM_32 0xffffffff
 
 #ifdef CONFIG_NUMA
 /* Returns the node based on pci bus */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pci_x86.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pci_x86.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pci_x86.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pci_x86.h	2009-09-09 18:13:59.000000000 -0400
@@ -121,6 +121,9 @@
 extern int __init pci_mmcfg_arch_init(void);
 extern void __init pci_mmcfg_arch_free(void);
 
+extern struct acpi_mcfg_allocation *pci_mmcfg_config;
+extern int pci_mmcfg_config_num;
+
 /*
  * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
  * on their northbrige except through the * %eax register. As such, you MUST
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/percpu.h linux-libre-2.6.31-gnu/arch/x86/include/asm/percpu.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/percpu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/percpu.h	2009-09-09 18:13:59.000000000 -0400
@@ -42,6 +42,7 @@
 
 #else /* ...!ASSEMBLY */
 
+#include <linux/kernel.h>
 #include <linux/stringify.h>
 
 #ifdef CONFIG_SMP
@@ -155,6 +156,15 @@
 /* We can use this directly for local CPU (faster). */
 DECLARE_PER_CPU(unsigned long, this_cpu_off);
 
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+void *pcpu_lpage_remapped(void *kaddr);
+#else
+static inline void *pcpu_lpage_remapped(void *kaddr)
+{
+	return NULL;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_SMP
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/perf_counter.h linux-libre-2.6.31-gnu/arch/x86/include/asm/perf_counter.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/perf_counter.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/perf_counter.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,98 @@
+#ifndef _ASM_X86_PERF_COUNTER_H
+#define _ASM_X86_PERF_COUNTER_H
+
+/*
+ * Performance counter hw details:
+ */
+
+#define X86_PMC_MAX_GENERIC					8
+#define X86_PMC_MAX_FIXED					3
+
+#define X86_PMC_IDX_GENERIC				        0
+#define X86_PMC_IDX_FIXED				       32
+#define X86_PMC_IDX_MAX					       64
+
+#define MSR_ARCH_PERFMON_PERFCTR0			      0xc1
+#define MSR_ARCH_PERFMON_PERFCTR1			      0xc2
+
+#define MSR_ARCH_PERFMON_EVENTSEL0			     0x186
+#define MSR_ARCH_PERFMON_EVENTSEL1			     0x187
+
+#define ARCH_PERFMON_EVENTSEL0_ENABLE			  (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_INT			  (1 << 20)
+#define ARCH_PERFMON_EVENTSEL_OS			  (1 << 17)
+#define ARCH_PERFMON_EVENTSEL_USR			  (1 << 16)
+
+/*
+ * Includes eventsel and unit mask as well:
+ */
+#define ARCH_PERFMON_EVENT_MASK				    0xffff
+
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL		      0x3c
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK		(0x00 << 8)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 		 0
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
+		(1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
+
+#define ARCH_PERFMON_BRANCH_MISSES_RETIRED			 6
+
+/*
+ * Intel "Architectural Performance Monitoring" CPUID
+ * detection/enumeration details:
+ */
+union cpuid10_eax {
+	struct {
+		unsigned int version_id:8;
+		unsigned int num_counters:8;
+		unsigned int bit_width:8;
+		unsigned int mask_length:8;
+	} split;
+	unsigned int full;
+};
+
+union cpuid10_edx {
+	struct {
+		unsigned int num_counters_fixed:4;
+		unsigned int reserved:28;
+	} split;
+	unsigned int full;
+};
+
+
+/*
+ * Fixed-purpose performance counters:
+ */
+
+/*
+ * All 3 fixed-mode PMCs are configured via this single MSR:
+ */
+#define MSR_ARCH_PERFMON_FIXED_CTR_CTRL			0x38d
+
+/*
+ * The counts are available in three separate MSRs:
+ */
+
+/* Instr_Retired.Any: */
+#define MSR_ARCH_PERFMON_FIXED_CTR0			0x309
+#define X86_PMC_IDX_FIXED_INSTRUCTIONS			(X86_PMC_IDX_FIXED + 0)
+
+/* CPU_CLK_Unhalted.Core: */
+#define MSR_ARCH_PERFMON_FIXED_CTR1			0x30a
+#define X86_PMC_IDX_FIXED_CPU_CYCLES			(X86_PMC_IDX_FIXED + 1)
+
+/* CPU_CLK_Unhalted.Ref: */
+#define MSR_ARCH_PERFMON_FIXED_CTR2			0x30b
+#define X86_PMC_IDX_FIXED_BUS_CYCLES			(X86_PMC_IDX_FIXED + 2)
+
+#ifdef CONFIG_PERF_COUNTERS
+extern void init_hw_perf_counters(void);
+extern void perf_counters_lapic_init(void);
+
+#define PERF_COUNTER_INDEX_OFFSET			0
+
+#else
+static inline void init_hw_perf_counters(void)		{ }
+static inline void perf_counters_lapic_init(void)	{ }
+#endif
+
+#endif /* _ASM_X86_PERF_COUNTER_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pgalloc.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pgalloc.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pgalloc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pgalloc.h	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,13 @@
 	__free_page(pte);
 }
 
-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+extern void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
+				  unsigned long address)
+{
+	___pte_free_tlb(tlb, pte);
+}
 
 static inline void pmd_populate_kernel(struct mm_struct *mm,
 				       pmd_t *pmd, pte_t *pte)
@@ -78,7 +84,13 @@
 	free_page((unsigned long)pmd);
 }
 
-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+extern void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+
+static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+				  unsigned long adddress)
+{
+	___pmd_free_tlb(tlb, pmd);
+}
 
 #ifdef CONFIG_X86_PAE
 extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
@@ -108,7 +120,14 @@
 	free_page((unsigned long)pud);
 }
 
-extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+extern void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+
+static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
+				  unsigned long address)
+{
+	___pud_free_tlb(tlb, pud);
+}
+
 #endif	/* PAGETABLE_LEVELS > 3 */
 #endif	/* PAGETABLE_LEVELS > 2 */
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_32.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_32.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -49,13 +49,17 @@
 #endif
 
 #if defined(CONFIG_HIGHPTE)
+#define __KM_PTE			\
+	(in_nmi() ? KM_NMI_PTE : 	\
+	 in_irq() ? KM_IRQ_PTE :	\
+	 KM_PTE0)
 #define pte_offset_map(dir, address)					\
-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) +		\
+	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), __KM_PTE) +		\
 	 pte_index((address)))
 #define pte_offset_map_nested(dir, address)				\
 	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) +		\
 	 pte_index((address)))
-#define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
+#define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE)
 #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
 #else
 #define pte_offset_map(dir, address)					\
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_32_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_32_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_32_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_32_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,10 @@
 # define VMALLOC_END	(FIXADDR_START - 2 * PAGE_SIZE)
 #endif
 
+#define MODULES_VADDR	VMALLOC_START
+#define MODULES_END	VMALLOC_END
+#define MODULES_LEN	(MODULES_VADDR - MODULES_END)
+
 #define MAXMEM	(VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE)
 
 #endif /* _ASM_X86_PGTABLE_32_DEFS_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_64.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_64.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,10 +25,6 @@
 
 extern void paging_init(void);
 
-#endif /* !__ASSEMBLY__ */
-
-#ifndef __ASSEMBLY__
-
 #define pte_ERROR(e)					\
 	printk("%s:%d: bad pte %p(%016lx).\n",		\
 	       __FILE__, __LINE__, &(e), pte_val(e))
@@ -135,8 +131,6 @@
 
 #define update_mmu_cache(vma, address, pte) do { } while (0)
 
-extern int direct_gbpages;
-
 /* Encode and de-code a swap entry */
 #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
 #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
@@ -171,10 +165,7 @@
 
 /* fs/proc/kcore.c */
 #define	kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
-#define	kc_offset_to_vaddr(o)				\
-	(((o) & (1UL << (__VIRTUAL_MASK_SHIFT - 1)))	\
-	 ? ((o) | ~__VIRTUAL_MASK)			\
-	 : (o))
+#define	kc_offset_to_vaddr(o) ((o) | ~__VIRTUAL_MASK)
 
 #define __HAVE_ARCH_PTE_SAME
 #endif /* !__ASSEMBLY__ */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_64_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_64_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_64_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_64_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -51,11 +51,11 @@
 #define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE - 1))
 
-
+/* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */
 #define MAXMEM		 _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL)
-#define VMALLOC_START    _AC(0xffffc20000000000, UL)
-#define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
-#define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
+#define VMALLOC_START    _AC(0xffffc90000000000, UL)
+#define VMALLOC_END      _AC(0xffffe8ffffffffff, UL)
+#define VMEMMAP_START	 _AC(0xffffea0000000000, UL)
 #define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
 #define MODULES_END      _AC(0xffffffffff000000, UL)
 #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
 #define _ASM_X86_PGTABLE_H
 
 #include <asm/page.h>
+#include <asm/e820.h>
 
 #include <asm/pgtable_types.h>
 
@@ -81,6 +82,8 @@
 #define pte_val(x)	native_pte_val(x)
 #define __pte(x)	native_make_pte(x)
 
+#define arch_end_context_switch(prev)	do {} while(0)
+
 #endif	/* CONFIG_PARAVIRT */
 
 /*
@@ -267,10 +270,17 @@
 
 #define canon_pgprot(p) __pgprot(massage_pgprot(p))
 
-static inline int is_new_memtype_allowed(unsigned long flags,
-						unsigned long new_flags)
+static inline int is_new_memtype_allowed(u64 paddr, unsigned long size,
+					 unsigned long flags,
+					 unsigned long new_flags)
 {
 	/*
+	 * PAT type is always WB for ISA. So no need to check.
+	 */
+	if (is_ISA_range(paddr, paddr + size - 1))
+		return 1;
+
+	/*
 	 * Certain new memtypes are not allowed with certain
 	 * requested memtype:
 	 * - request is uncached, return cannot be write-back
@@ -315,6 +325,11 @@
 	return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
 }
 
+static inline int pte_hidden(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_HIDDEN;
+}
+
 static inline int pmd_present(pmd_t pmd)
 {
 	return pmd_flags(pmd) & _PAGE_PRESENT;
@@ -503,6 +518,8 @@
 
 #ifndef __ASSEMBLY__
 
+extern int direct_gbpages;
+
 /* local pte updates need not use xchg for locking */
 static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
 {
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/pgtable_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/pgtable_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,7 @@
 #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
 #define _PAGE_BIT_UNUSED1	9	/* available for programmer */
 #define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
-#define _PAGE_BIT_UNUSED3	11
+#define _PAGE_BIT_HIDDEN	11	/* hidden by kmemcheck */
 #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
 #define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
 #define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
@@ -41,13 +41,18 @@
 #define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
 #define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
 #define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
-#define _PAGE_UNUSED3	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
 #define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
 #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
 #define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
 #define _PAGE_CPA_TEST	(_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
 #define __HAVE_ARCH_PTE_SPECIAL
 
+#ifdef CONFIG_KMEMCHECK
+#define _PAGE_HIDDEN	(_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
+#else
+#define _PAGE_HIDDEN	(_AT(pteval_t, 0))
+#endif
+
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
 #define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
 #else
@@ -273,7 +278,6 @@
 
 extern pteval_t __supported_pte_mask;
 extern int nx_enabled;
-extern void set_nx(void);
 
 #define pgprot_writecombine	pgprot_writecombine
 extern pgprot_t pgprot_writecombine(pgprot_t prot);
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/processor.h linux-libre-2.6.31-gnu/arch/x86/include/asm/processor.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/processor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/processor.h	2009-09-09 18:13:59.000000000 -0400
@@ -135,7 +135,8 @@
 extern struct cpuinfo_x86	new_cpu_data;
 
 extern struct tss_struct	doublefault_tss;
-extern __u32			cleared_cpu_caps[NCAPINTS];
+extern __u32			cpu_caps_cleared[NCAPINTS];
+extern __u32			cpu_caps_set[NCAPINTS];
 
 #ifdef CONFIG_SMP
 DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
@@ -409,9 +410,6 @@
 extern unsigned int xstate_size;
 extern void free_thread_xstate(struct task_struct *);
 extern struct kmem_cache *task_xstate_cachep;
-extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
-extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
-extern unsigned short num_cache_leaves;
 
 struct thread_struct {
 	/* Cached TLS descriptors: */
@@ -427,8 +425,12 @@
 	unsigned short		fsindex;
 	unsigned short		gsindex;
 #endif
+#ifdef CONFIG_X86_32
 	unsigned long		ip;
+#endif
+#ifdef CONFIG_X86_64
 	unsigned long		fs;
+#endif
 	unsigned long		gs;
 	/* Hardware debugging registers: */
 	unsigned long		debugreg0;
@@ -460,14 +462,8 @@
 	unsigned		io_bitmap_max;
 /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
 	unsigned long	debugctlmsr;
-#ifdef CONFIG_X86_DS
-/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */
+	/* Debug Store context; see asm/ds.h */
 	struct ds_context	*ds_ctx;
-#endif /* CONFIG_X86_DS */
-#ifdef CONFIG_X86_PTRACE_BTS
-/* the signal to send on a bts buffer overflow */
-	unsigned int	bts_ovfl_signal;
-#endif /* CONFIG_X86_PTRACE_BTS */
 };
 
 static inline unsigned long native_get_debugreg(int regno)
@@ -795,6 +791,21 @@
     return debugctlmsr;
 }
 
+static inline unsigned long get_debugctlmsr_on_cpu(int cpu)
+{
+	u64 debugctlmsr = 0;
+	u32 val1, val2;
+
+#ifndef CONFIG_X86_DEBUGCTLMSR
+	if (boot_cpu_data.x86 < 6)
+		return 0;
+#endif
+	rdmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, &val1, &val2);
+	debugctlmsr = val1 | ((u64)val2 << 32);
+
+	return debugctlmsr;
+}
+
 static inline void update_debugctlmsr(unsigned long debugctlmsr)
 {
 #ifndef CONFIG_X86_DEBUGCTLMSR
@@ -804,6 +815,18 @@
 	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
 }
 
+static inline void update_debugctlmsr_on_cpu(int cpu,
+					     unsigned long debugctlmsr)
+{
+#ifndef CONFIG_X86_DEBUGCTLMSR
+	if (boot_cpu_data.x86 < 6)
+		return;
+#endif
+	wrmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR,
+		     (u32)((u64)debugctlmsr),
+		     (u32)((u64)debugctlmsr >> 32));
+}
+
 /*
  * from system description table in BIOS. Mostly for MCA use, but
  * others may find it useful:
@@ -814,6 +837,7 @@
 
 /* Boot loader type from the setup header: */
 extern int			bootloader_type;
+extern int			bootloader_version;
 
 extern char			ignore_fpu_irq;
 
@@ -874,7 +898,6 @@
 	.vm86_info		= NULL,					  \
 	.sysenter_cs		= __KERNEL_CS,				  \
 	.io_bitmap_ptr		= NULL,					  \
-	.fs			= __KERNEL_PERCPU,			  \
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/proto.h linux-libre-2.6.31-gnu/arch/x86/include/asm/proto.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/proto.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/proto.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,14 @@
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 
-#define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1))
-#define round_down(x, y) ((x) & ~((y) - 1))
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x,y) ((__typeof__(x))((y)-1))
+#define round_up(x,y) ((((x)-1) | __round_mask(x,y))+1)
+#define round_down(x,y) ((x) & ~__round_mask(x,y))
 
 #endif /* _ASM_X86_PROTO_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/ptrace.h linux-libre-2.6.31-gnu/arch/x86/include/asm/ptrace.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/ptrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/ptrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -236,12 +236,11 @@
 extern int do_set_thread_area(struct task_struct *p, int idx,
 			      struct user_desc __user *info, int can_allocate);
 
-extern void x86_ptrace_untrace(struct task_struct *);
-extern void x86_ptrace_fork(struct task_struct *child,
-			    unsigned long clone_flags);
+#ifdef CONFIG_X86_PTRACE_BTS
+extern void ptrace_bts_untrace(struct task_struct *tsk);
 
-#define arch_ptrace_untrace(tsk) x86_ptrace_untrace(tsk)
-#define arch_ptrace_fork(child, flags) x86_ptrace_fork(child, flags)
+#define arch_ptrace_untrace(tsk)	ptrace_bts_untrace(tsk)
+#endif /* CONFIG_X86_PTRACE_BTS */
 
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/required-features.h linux-libre-2.6.31-gnu/arch/x86/include/asm/required-features.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/required-features.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/required-features.h	2009-09-09 18:13:59.000000000 -0400
@@ -48,9 +48,15 @@
 #endif
 
 #ifdef CONFIG_X86_64
+#ifdef CONFIG_PARAVIRT
+/* Paravirtualized systems may not have PSE or PGE available */
 #define NEED_PSE	0
-#define NEED_MSR	(1<<(X86_FEATURE_MSR & 31))
 #define NEED_PGE	0
+#else
+#define NEED_PSE	(1<<(X86_FEATURE_PSE) & 31)
+#define NEED_PGE	(1<<(X86_FEATURE_PGE) & 31)
+#endif
+#define NEED_MSR	(1<<(X86_FEATURE_MSR & 31))
 #define NEED_FXSR	(1<<(X86_FEATURE_FXSR & 31))
 #define NEED_XMM	(1<<(X86_FEATURE_XMM & 31))
 #define NEED_XMM2	(1<<(X86_FEATURE_XMM2 & 31))
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/setup.h linux-libre-2.6.31-gnu/arch/x86/include/asm/setup.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/setup.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/setup.h	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,6 @@
 	int (*setup_ioapic_ids)(void);
 };
 
-extern void x86_quirk_pre_intr_init(void);
 extern void x86_quirk_intr_init(void);
 
 extern void x86_quirk_trap_init(void);
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/signal.h linux-libre-2.6.31-gnu/arch/x86/include/asm/signal.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/signal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/signal.h	2009-09-09 18:13:59.000000000 -0400
@@ -117,7 +117,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#include <asm-generic/signal.h>
+#include <asm-generic/signal-defs.h>
 
 #ifndef __ASSEMBLY__
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/smp.h linux-libre-2.6.31-gnu/arch/x86/include/asm/smp.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/smp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/smp.h	2009-09-09 18:13:59.000000000 -0400
@@ -180,7 +180,7 @@
 static inline int logical_smp_processor_id(void)
 {
 	/* we don't want to mark this access volatile - bad code generation */
-	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+	return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
 }
 
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/sparsemem.h linux-libre-2.6.31-gnu/arch/x86/include/asm/sparsemem.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/sparsemem.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/sparsemem.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,7 @@
 #else /* CONFIG_X86_32 */
 # define SECTION_SIZE_BITS	27 /* matt - 128 is convenient right now */
 # define MAX_PHYSADDR_BITS	44
-# define MAX_PHYSMEM_BITS	44 /* Can be max 45 bits */
+# define MAX_PHYSMEM_BITS	46
 #endif
 
 #endif /* CONFIG_SPARSEMEM */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/spinlock.h linux-libre-2.6.31-gnu/arch/x86/include/asm/spinlock.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/spinlock.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/spinlock.h	2009-09-09 18:13:59.000000000 -0400
@@ -302,4 +302,8 @@
 #define _raw_read_relax(lock)	cpu_relax()
 #define _raw_write_relax(lock)	cpu_relax()
 
+/* The {read|write|spin}_lock() on x86 are full memory barriers. */
+static inline void smp_mb__after_lock(void) { }
+#define ARCH_HAS_SMP_MB_AFTER_LOCK
+
 #endif /* _ASM_X86_SPINLOCK_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/stacktrace.h linux-libre-2.6.31-gnu/arch/x86/include/asm/stacktrace.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/stacktrace.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/stacktrace.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,8 @@
 
 extern int kstack_depth_to_print;
 
+int x86_is_stack_id(int id, char *name);
+
 /* Generic stack tracer with callbacks */
 
 struct stacktrace_ops {
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/string_32.h linux-libre-2.6.31-gnu/arch/x86/include/asm/string_32.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/string_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/string_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -177,10 +177,18 @@
  *	No 3D Now!
  */
 
+#ifndef CONFIG_KMEMCHECK
 #define memcpy(t, f, n)				\
 	(__builtin_constant_p((n))		\
 	 ? __constant_memcpy((t), (f), (n))	\
 	 : __memcpy((t), (f), (n)))
+#else
+/*
+ * kmemcheck becomes very happy if we use the REP instructions unconditionally,
+ * because it means that we know both memory operands in advance.
+ */
+#define memcpy(t, f, n) __memcpy((t), (f), (n))
+#endif
 
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/string_64.h linux-libre-2.6.31-gnu/arch/x86/include/asm/string_64.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/string_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/string_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
    function. */
 
 #define __HAVE_ARCH_MEMCPY 1
+#ifndef CONFIG_KMEMCHECK
 #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
 extern void *memcpy(void *to, const void *from, size_t len);
 #else
@@ -42,6 +43,13 @@
 	__ret;							\
 })
 #endif
+#else
+/*
+ * kmemcheck becomes very happy if we use the REP instructions unconditionally,
+ * because it means that we know both memory operands in advance.
+ */
+#define memcpy(dst, src, len) __inline_memcpy((dst), (src), (len))
+#endif
 
 #define __HAVE_ARCH_MEMSET
 void *memset(void *s, int c, size_t n);
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/svm.h linux-libre-2.6.31-gnu/arch/x86/include/asm/svm.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/svm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/svm.h	2009-09-09 18:13:59.000000000 -0400
@@ -225,6 +225,7 @@
 #define SVM_EVTINJ_VALID_ERR (1 << 11)
 
 #define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
+#define SVM_EXITINTINFO_TYPE_MASK SVM_EVTINJ_TYPE_MASK
 
 #define	SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
 #define	SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/syscalls.h linux-libre-2.6.31-gnu/arch/x86/include/asm/syscalls.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/syscalls.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/syscalls.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * syscalls.h - Linux syscall interfaces (arch-specific)
  *
- * Copyright (c) 2008 Jaswinder Singh
+ * Copyright (c) 2008 Jaswinder Singh Rajput
  *
  * This file is released under the GPLv2.
  * See the file COPYING for more details.
@@ -12,50 +12,55 @@
 
 #include <linux/compiler.h>
 #include <linux/linkage.h>
-#include <linux/types.h>
 #include <linux/signal.h>
+#include <linux/types.h>
 
 /* Common in X86_32 and X86_64 */
 /* kernel/ioport.c */
 asmlinkage long sys_ioperm(unsigned long, unsigned long, int);
 
+/* kernel/process.c */
+int sys_fork(struct pt_regs *);
+int sys_vfork(struct pt_regs *);
+
 /* kernel/ldt.c */
 asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
 
+/* kernel/signal.c */
+long sys_rt_sigreturn(struct pt_regs *);
+
 /* kernel/tls.c */
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
 asmlinkage int sys_get_thread_area(struct user_desc __user *);
 
 /* X86_32 only */
 #ifdef CONFIG_X86_32
+/* kernel/ioport.c */
+long sys_iopl(struct pt_regs *);
+
 /* kernel/process_32.c */
-int sys_fork(struct pt_regs *);
 int sys_clone(struct pt_regs *);
-int sys_vfork(struct pt_regs *);
 int sys_execve(struct pt_regs *);
 
-/* kernel/signal_32.c */
+/* kernel/signal.c */
 asmlinkage int sys_sigsuspend(int, int, old_sigset_t);
 asmlinkage int sys_sigaction(int, const struct old_sigaction __user *,
 			     struct old_sigaction __user *);
 int sys_sigaltstack(struct pt_regs *);
 unsigned long sys_sigreturn(struct pt_regs *);
-long sys_rt_sigreturn(struct pt_regs *);
-
-/* kernel/ioport.c */
-long sys_iopl(struct pt_regs *);
 
 /* kernel/sys_i386_32.c */
+struct mmap_arg_struct;
+struct sel_arg_struct;
+struct oldold_utsname;
+struct old_utsname;
+
 asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
 			  unsigned long, unsigned long, unsigned long);
-struct mmap_arg_struct;
 asmlinkage int old_mmap(struct mmap_arg_struct __user *);
-struct sel_arg_struct;
 asmlinkage int old_select(struct sel_arg_struct __user *);
 asmlinkage int sys_ipc(uint, int, int, int, void __user *, long);
-struct old_utsname;
 asmlinkage int sys_uname(struct old_utsname __user *);
-struct oldold_utsname;
 asmlinkage int sys_olduname(struct oldold_utsname __user *);
 
 /* kernel/vm86_32.c */
@@ -65,29 +70,27 @@
 #else /* CONFIG_X86_32 */
 
 /* X86_64 only */
+/* kernel/ioport.c */
+asmlinkage long sys_iopl(unsigned int, struct pt_regs *);
+
 /* kernel/process_64.c */
-asmlinkage long sys_fork(struct pt_regs *);
 asmlinkage long sys_clone(unsigned long, unsigned long,
 			  void __user *, void __user *,
 			  struct pt_regs *);
-asmlinkage long sys_vfork(struct pt_regs *);
 asmlinkage long sys_execve(char __user *, char __user * __user *,
 			   char __user * __user *,
 			   struct pt_regs *);
 long sys_arch_prctl(int, unsigned long);
 
-/* kernel/ioport.c */
-asmlinkage long sys_iopl(unsigned int, struct pt_regs *);
-
-/* kernel/signal_64.c */
+/* kernel/signal.c */
 asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *,
 				struct pt_regs *);
-long sys_rt_sigreturn(struct pt_regs *);
 
 /* kernel/sys_x86_64.c */
+struct new_utsname;
+
 asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long,
 			 unsigned long, unsigned long, unsigned long);
-struct new_utsname;
 asmlinkage long sys_uname(struct new_utsname __user *);
 
 #endif /* CONFIG_X86_32 */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/termios.h linux-libre-2.6.31-gnu/arch/x86/include/asm/termios.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/termios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/termios.h	2009-09-09 18:13:59.000000000 -0400
@@ -67,6 +67,7 @@
 	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag);
 	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag);
 	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag);
+	get_user(termios->c_line, &termio->c_line);
 	return copy_from_user(termios->c_cc, termio->c_cc, NCC);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/therm_throt.h linux-libre-2.6.31-gnu/arch/x86/include/asm/therm_throt.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/therm_throt.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/therm_throt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#ifndef _ASM_X86_THERM_THROT_H
-#define _ASM_X86_THERM_THROT_H
-
-#include <asm/atomic.h>
-
-extern atomic_t therm_throt_en;
-int therm_throt_process(int curr);
-
-#endif /* _ASM_X86_THERM_THROT_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/x86/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -94,7 +94,8 @@
 #define TIF_FORCED_TF		24	/* true if TF in eflags artificially */
 #define TIF_DEBUGCTLMSR		25	/* uses thread_struct.debugctlmsr */
 #define TIF_DS_AREA_MSR		26      /* uses thread_struct.ds_area_msr */
-#define TIF_SYSCALL_FTRACE	27	/* for ftrace syscall instrumentation */
+#define TIF_LAZY_MMU_UPDATES	27	/* task is updating the mmu lazily */
+#define TIF_SYSCALL_FTRACE	28	/* for ftrace syscall instrumentation */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
@@ -116,6 +117,7 @@
 #define _TIF_FORCED_TF		(1 << TIF_FORCED_TF)
 #define _TIF_DEBUGCTLMSR	(1 << TIF_DEBUGCTLMSR)
 #define _TIF_DS_AREA_MSR	(1 << TIF_DS_AREA_MSR)
+#define _TIF_LAZY_MMU_UPDATES	(1 << TIF_LAZY_MMU_UPDATES)
 #define _TIF_SYSCALL_FTRACE	(1 << TIF_SYSCALL_FTRACE)
 
 /* work to do in syscall_trace_enter() */
@@ -152,9 +154,9 @@
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define THREAD_FLAGS (GFP_KERNEL | __GFP_ZERO)
+#define THREAD_FLAGS (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
 #else
-#define THREAD_FLAGS GFP_KERNEL
+#define THREAD_FLAGS (GFP_KERNEL | __GFP_NOTRACK)
 #endif
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/timer.h linux-libre-2.6.31-gnu/arch/x86/include/asm/timer.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/timer.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/timer.h	2009-09-09 18:13:59.000000000 -0400
@@ -45,12 +45,16 @@
  */
 
 DECLARE_PER_CPU(unsigned long, cyc2ns);
+DECLARE_PER_CPU(unsigned long long, cyc2ns_offset);
 
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
 static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
 {
-	return cyc * per_cpu(cyc2ns, smp_processor_id()) >> CYC2NS_SCALE_FACTOR;
+	int cpu = smp_processor_id();
+	unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
+	ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR;
+	return ns;
 }
 
 static inline unsigned long long cycles_2_ns(unsigned long long cyc)
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/timex.h linux-libre-2.6.31-gnu/arch/x86/include/asm/timex.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/timex.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/timex.h	2009-09-09 18:13:59.000000000 -0400
@@ -4,9 +4,7 @@
 #include <asm/processor.h>
 #include <asm/tsc.h>
 
-/* The PIT ticks at this frequency (in HZ): */
-#define PIT_TICK_RATE		1193182
-
+/* Assume we use the PIT time source for the clock tick */
 #define CLOCK_TICK_RATE		PIT_TICK_RATE
 
 #define ARCH_HAS_READ_CURRENT_TIMER
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/tlbflush.h linux-libre-2.6.31-gnu/arch/x86/include/asm/tlbflush.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/tlbflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/tlbflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 
 static inline void __native_flush_tlb(void)
 {
-	write_cr3(read_cr3());
+	native_write_cr3(native_read_cr3());
 }
 
 static inline void __native_flush_tlb_global(void)
@@ -32,11 +32,11 @@
 	 */
 	raw_local_irq_save(flags);
 
-	cr4 = read_cr4();
+	cr4 = native_read_cr4();
 	/* clear PGE */
-	write_cr4(cr4 & ~X86_CR4_PGE);
+	native_write_cr4(cr4 & ~X86_CR4_PGE);
 	/* write old PGE again and flush TLBs */
-	write_cr4(cr4);
+	native_write_cr4(cr4);
 
 	raw_local_irq_restore(flags);
 }
@@ -172,6 +172,6 @@
 	flush_tlb_all();
 }
 
-extern void zap_low_mappings(void);
+extern void zap_low_mappings(bool early);
 
 #endif /* _ASM_X86_TLBFLUSH_H */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/topology.h linux-libre-2.6.31-gnu/arch/x86/include/asm/topology.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/topology.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/topology.h	2009-09-09 18:13:59.000000000 -0400
@@ -203,7 +203,8 @@
 void x86_pci_root_bus_res_quirks(struct pci_bus *b);
 
 #ifdef CONFIG_SMP
-#define mc_capable()	(cpumask_weight(cpu_core_mask(0)) != nr_cpu_ids)
+#define mc_capable()	((boot_cpu_data.x86_max_cores > 1) && \
+			(cpumask_weight(cpu_core_mask(0)) != nr_cpu_ids))
 #define smt_capable()			(smp_num_siblings > 1)
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/traps.h linux-libre-2.6.31-gnu/arch/x86/include/asm/traps.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/traps.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/traps.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,7 @@
 #define _ASM_X86_TRAPS_H
 
 #include <asm/debugreg.h>
+#include <asm/siginfo.h>			/* TRAP_TRACE, ... */
 
 #ifdef CONFIG_X86_32
 #define dotraplinkage
@@ -13,6 +14,9 @@
 asmlinkage void debug(void);
 asmlinkage void nmi(void);
 asmlinkage void int3(void);
+asmlinkage void xen_debug(void);
+asmlinkage void xen_int3(void);
+asmlinkage void xen_stack_segment(void);
 asmlinkage void overflow(void);
 asmlinkage void bounds(void);
 asmlinkage void invalid_op(void);
@@ -74,7 +78,6 @@
 }
 
 extern int panic_on_unrecovered_nmi;
-extern int kstack_depth_to_print;
 
 void math_error(void __user *);
 void math_emulate(struct math_emu_info *);
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/types.h linux-libre-2.6.31-gnu/arch/x86/include/asm/types.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -14,12 +14,6 @@
  */
 #ifdef __KERNEL__
 
-#ifdef CONFIG_X86_32
-# define BITS_PER_LONG 32
-#else
-# define BITS_PER_LONG 64
-#endif
-
 #ifndef __ASSEMBLY__
 
 typedef u64 dma64_addr_t;
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/uaccess_64.h linux-libre-2.6.31-gnu/arch/x86/include/asm/uaccess_64.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/uaccess_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/uaccess_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -88,11 +88,11 @@
 			      ret, "l", "k", "ir", 4);
 		return ret;
 	case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
-			      ret, "q", "", "ir", 8);
+			      ret, "q", "", "er", 8);
 		return ret;
 	case 10:
 		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
-			       ret, "q", "", "ir", 10);
+			       ret, "q", "", "er", 10);
 		if (unlikely(ret))
 			return ret;
 		asm("":::"memory");
@@ -101,12 +101,12 @@
 		return ret;
 	case 16:
 		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
-			       ret, "q", "", "ir", 16);
+			       ret, "q", "", "er", 16);
 		if (unlikely(ret))
 			return ret;
 		asm("":::"memory");
 		__put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
-			       ret, "q", "", "ir", 8);
+			       ret, "q", "", "er", 8);
 		return ret;
 	default:
 		return copy_user_generic((__force void *)dst, src, size);
@@ -157,7 +157,7 @@
 			       ret, "q", "", "=r", 8);
 		if (likely(!ret))
 			__put_user_asm(tmp, (u64 __user *)dst,
-				       ret, "q", "", "ir", 8);
+				       ret, "q", "", "er", 8);
 		return ret;
 	}
 	default:
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/uaccess.h linux-libre-2.6.31-gnu/arch/x86/include/asm/uaccess.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/uaccess.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/uaccess.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,7 @@
 #define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
 
 #define KERNEL_DS	MAKE_MM_SEG(-1UL)
-#define USER_DS		MAKE_MM_SEG(PAGE_OFFSET)
+#define USER_DS 	MAKE_MM_SEG(TASK_SIZE_MAX)
 
 #define get_ds()	(KERNEL_DS)
 #define get_fs()	(current_thread_info()->addr_limit)
@@ -212,9 +212,9 @@
 		     : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
 #else
 #define __put_user_asm_u64(x, ptr, retval, errret) \
-	__put_user_asm(x, ptr, retval, "q", "", "Zr", errret)
+	__put_user_asm(x, ptr, retval, "q", "", "er", errret)
 #define __put_user_asm_ex_u64(x, addr)	\
-	__put_user_asm_ex(x, addr, "q", "", "Zr")
+	__put_user_asm_ex(x, addr, "q", "", "er")
 #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/unistd_32.h linux-libre-2.6.31-gnu/arch/x86/include/asm/unistd_32.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/unistd_32.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/unistd_32.h	2009-09-09 18:13:59.000000000 -0400
@@ -340,6 +340,8 @@
 #define __NR_inotify_init1	332
 #define __NR_preadv		333
 #define __NR_pwritev		334
+#define __NR_rt_tgsigqueueinfo	335
+#define __NR_perf_counter_open	336
 
 #ifdef __KERNEL__
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/unistd_64.h linux-libre-2.6.31-gnu/arch/x86/include/asm/unistd_64.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/unistd_64.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/unistd_64.h	2009-09-09 18:13:59.000000000 -0400
@@ -657,7 +657,10 @@
 __SYSCALL(__NR_preadv, sys_preadv)
 #define __NR_pwritev				296
 __SYSCALL(__NR_pwritev, sys_pwritev)
-
+#define __NR_rt_tgsigqueueinfo			297
+__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
+#define __NR_perf_counter_open			298
+__SYSCALL(__NR_perf_counter_open, sys_perf_counter_open)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/uv/uv_bau.h linux-libre-2.6.31-gnu/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/uv/uv_bau.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/uv/uv_bau.h	2009-09-09 18:13:59.000000000 -0400
@@ -37,7 +37,7 @@
 #define UV_CPUS_PER_ACT_STATUS		32
 #define UV_ACT_STATUS_MASK		0x3
 #define UV_ACT_STATUS_SIZE		2
-#define UV_ACTIVATION_DESCRIPTOR_SIZE	32
+#define UV_ADP_SIZE			32
 #define UV_DISTRIBUTION_SIZE		256
 #define UV_SW_ACK_NPENDING		8
 #define UV_NET_ENDPOINT_INTD		0x38
@@ -133,7 +133,7 @@
  * see table 4.2.3.0.1 in broacast_assist spec.
  */
 struct bau_msg_header {
-	unsigned int dest_subnodeid:6;	/* must be zero */
+	unsigned int dest_subnodeid:6;	/* must be 0x10, for the LB */
 	/* bits 5:0 */
 	unsigned int base_dest_nodeid:15; /* nasid>>1 (pnode) of */
 	/* bits 20:6 */			  /* first bit in node_map */
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/uv/uv_hub.h linux-libre-2.6.31-gnu/arch/x86/include/asm/uv/uv_hub.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/uv/uv_hub.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/uv/uv_hub.h	2009-09-09 18:13:59.000000000 -0400
@@ -133,6 +133,7 @@
 struct uv_hub_info_s {
 	unsigned long		global_mmr_base;
 	unsigned long		gpa_mask;
+	unsigned int		gnode_extra;
 	unsigned long		gnode_upper;
 	unsigned long		lowmem_remap_top;
 	unsigned long		lowmem_remap_base;
@@ -159,7 +160,8 @@
  * 		p -  PNODE (local part of nsids, right shifted 1)
  */
 #define UV_NASID_TO_PNODE(n)		(((n) >> 1) & uv_hub_info->pnode_mask)
-#define UV_PNODE_TO_NASID(p)		(((p) << 1) | uv_hub_info->gnode_upper)
+#define UV_PNODE_TO_GNODE(p)		((p) |uv_hub_info->gnode_extra)
+#define UV_PNODE_TO_NASID(p)		(UV_PNODE_TO_GNODE(p) << 1)
 
 #define UV_LOCAL_MMR_BASE		0xf4000000UL
 #define UV_GLOBAL_MMR32_BASE		0xf8000000UL
@@ -173,7 +175,7 @@
 #define UV_GLOBAL_MMR32_PNODE_BITS(p)	((p) << (UV_GLOBAL_MMR32_PNODE_SHIFT))
 
 #define UV_GLOBAL_MMR64_PNODE_BITS(p)					\
-	((unsigned long)(p) << UV_GLOBAL_MMR64_PNODE_SHIFT)
+	(((unsigned long)(p)) << UV_GLOBAL_MMR64_PNODE_SHIFT)
 
 #define UV_APIC_PNODE_SHIFT	6
 
@@ -325,6 +327,7 @@
 	unsigned short	nr_possible_cpus;
 	unsigned short	nr_online_cpus;
 	unsigned short	pnode;
+	short		memory_nid;
 };
 extern struct uv_blade_info *uv_blade_info;
 extern short *uv_node_to_blade;
@@ -361,6 +364,12 @@
 	return uv_blade_info[bid].pnode;
 }
 
+/* Nid of memory node on blade. -1 if no blade-local memory */
+static inline int uv_blade_to_memory_nid(int bid)
+{
+	return uv_blade_info[bid].memory_nid;
+}
+
 /* Determine the number of possible cpus on a blade */
 static inline int uv_blade_nr_possible_cpus(int bid)
 {
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/vmx.h linux-libre-2.6.31-gnu/arch/x86/include/asm/vmx.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/vmx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/vmx.h	2009-09-09 18:13:59.000000000 -0400
@@ -247,6 +247,7 @@
 #define EXIT_REASON_MSR_READ            31
 #define EXIT_REASON_MSR_WRITE           32
 #define EXIT_REASON_MWAIT_INSTRUCTION   36
+#define EXIT_REASON_MCE_DURING_VMENTRY	 41
 #define EXIT_REASON_TPR_BELOW_THRESHOLD 43
 #define EXIT_REASON_APIC_ACCESS         44
 #define EXIT_REASON_EPT_VIOLATION       48
diff -druN linux-libre-2.6.30-gnu/arch/x86/include/asm/xor.h linux-libre-2.6.31-gnu/arch/x86/include/asm/xor.h
--- linux-libre-2.6.30-gnu/arch/x86/include/asm/xor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/include/asm/xor.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,10 @@
+#ifdef CONFIG_KMEMCHECK
+/* kmemcheck doesn't handle MMX/SSE/SSE2 instructions */
+# include <asm-generic/xor.h>
+#else
 #ifdef CONFIG_X86_32
 # include "xor_32.h"
 #else
 # include "xor_64.h"
 #endif
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/Kbuild linux-libre-2.6.31-gnu/arch/x86/Kbuild
--- linux-libre-2.6.30-gnu/arch/x86/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/Kbuild	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,16 @@
+
+obj-$(CONFIG_KVM) += kvm/
+
+# Xen paravirtualization support
+obj-$(CONFIG_XEN) += xen/
+
+# lguest paravirtualization support
+obj-$(CONFIG_LGUEST_GUEST) += lguest/
+
+obj-y += kernel/
+obj-y += mm/
+
+obj-y += crypto/
+obj-y += vdso/
+obj-$(CONFIG_IA32_EMULATION) += ia32/
+
diff -druN linux-libre-2.6.30-gnu/arch/x86/Kconfig linux-libre-2.6.31-gnu/arch/x86/Kconfig
--- linux-libre-2.6.30-gnu/arch/x86/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -24,15 +24,18 @@
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
 	select HAVE_OPROFILE
+	select HAVE_PERF_COUNTERS if (!M386 && !M486)
 	select HAVE_IOREMAP_PROT
 	select HAVE_KPROBES
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_WANT_FRAME_POINTERS
+	select HAVE_DMA_ATTRS
 	select HAVE_KRETPROBES
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_FUNCTION_GRAPH_FP_TEST
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
 	select HAVE_FTRACE_SYSCALLS
@@ -46,6 +49,12 @@
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
+	select HAVE_ARCH_KMEMCHECK
+
+config OUTPUT_FORMAT
+	string
+	default "elf32-i386" if X86_32
+	default "elf64-x86-64" if X86_64
 
 config ARCH_DEFCONFIG
 	string
@@ -274,15 +283,9 @@
 
 	  If you don't know what to do here, say N.
 
-config NUMA_MIGRATE_IRQ_DESC
-	bool "Move irq desc when changing irq smp_affinity"
+config NUMA_IRQ_DESC
+	def_bool y
 	depends on SPARSE_IRQ && NUMA
-	depends on BROKEN
-	default n
-	---help---
-	  This enables moving irq_desc to cpu/node that irq will use handled.
-
-	  If you don't know what to do here, say N.
 
 config X86_MPPARSE
 	bool "Enable MPS table" if ACPI
@@ -355,7 +358,7 @@
 	depends on X86_64
 	depends on X86_EXTENDED_PLATFORM
 	depends on NUMA
-	select X86_X2APIC
+	depends on X86_X2APIC
 	---help---
 	  This option is needed in order to support SGI Ultraviolet systems.
 	  If you don't have one of these, you should say N here.
@@ -789,10 +792,26 @@
 	  to disable it.  MCE support simply ignores non-MCE processors like
 	  the 386 and 486, so nearly everyone can say Y here.
 
+config X86_OLD_MCE
+	depends on X86_32 && X86_MCE
+	bool "Use legacy machine check code (will go away)"
+	default n
+	select X86_ANCIENT_MCE
+	---help---
+	  Use the old i386 machine check code. This is merely intended for
+	  testing in a transition period. Try this if you run into any machine
+	  check related software problems, but report the problem to
+	  linux-kernel.  When in doubt say no.
+
+config X86_NEW_MCE
+	depends on X86_MCE
+	bool
+	default y if (!X86_OLD_MCE && X86_32) || X86_64
+
 config X86_MCE_INTEL
 	def_bool y
 	prompt "Intel MCE features"
-	depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+	depends on X86_NEW_MCE && X86_LOCAL_APIC
 	---help---
 	   Additional support for intel specific MCE features such as
 	   the thermal monitor.
@@ -800,19 +819,36 @@
 config X86_MCE_AMD
 	def_bool y
 	prompt "AMD MCE features"
-	depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+	depends on X86_NEW_MCE && X86_LOCAL_APIC
 	---help---
 	   Additional support for AMD specific MCE features such as
 	   the DRAM Error Threshold.
 
+config X86_ANCIENT_MCE
+	def_bool n
+	depends on X86_32
+	prompt "Support for old Pentium 5 / WinChip machine checks"
+	---help---
+	  Include support for machine check handling on old Pentium 5 or WinChip
+	  systems. These typically need to be enabled explicitely on the command
+	  line.
+
 config X86_MCE_THRESHOLD
 	depends on X86_MCE_AMD || X86_MCE_INTEL
 	bool
 	default y
 
+config X86_MCE_INJECT
+	depends on X86_NEW_MCE
+	tristate "Machine check injector support"
+	---help---
+	  Provide support for injecting machine checks for testing purposes.
+	  If you don't know what a machine check is and you don't do kernel
+	  QA it is safe to say n.
+
 config X86_MCE_NONFATAL
 	tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
-	depends on X86_32 && X86_MCE
+	depends on X86_OLD_MCE
 	---help---
 	  Enabling this feature starts a timer that triggers every 5 seconds which
 	  will look at the machine check registers to see if anything happened.
@@ -825,11 +861,15 @@
 
 config X86_MCE_P4THERMAL
 	bool "check for P4 thermal throttling interrupt."
-	depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP)
+	depends on X86_OLD_MCE && X86_MCE && (X86_UP_APIC || SMP)
 	---help---
 	  Enabling this feature will cause a message to be printed when the P4
 	  enters thermal throttling.
 
+config X86_THERMAL_VECTOR
+	def_bool y
+	depends on X86_MCE_P4THERMAL || X86_MCE_INTEL
+
 config VM86
 	bool "Enable VM86 support" if EMBEDDED
 	default y
@@ -1466,9 +1506,7 @@
 
 config PHYSICAL_START
 	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
-	default "0x1000000" if X86_NUMAQ
-	default "0x200000" if X86_64
-	default "0x100000"
+	default "0x1000000"
 	---help---
 	  This gives the physical address where the kernel is loaded.
 
@@ -1487,15 +1525,15 @@
 	  to be specifically compiled to run from a specific memory area
 	  (normally a reserved region) and this option comes handy.
 
-	  So if you are using bzImage for capturing the crash dump, leave
-	  the value here unchanged to 0x100000 and set CONFIG_RELOCATABLE=y.
-	  Otherwise if you plan to use vmlinux for capturing the crash dump
-	  change this value to start of the reserved region (Typically 16MB
-	  0x1000000). In other words, it can be set based on the "X" value as
-	  specified in the "crashkernel=YM@XM" command line boot parameter
-	  passed to the panic-ed kernel. Typically this parameter is set as
-	  crashkernel=64M@16M. Please take a look at
-	  Documentation/kdump/kdump.txt for more details about crash dumps.
+	  So if you are using bzImage for capturing the crash dump,
+	  leave the value here unchanged to 0x1000000 and set
+	  CONFIG_RELOCATABLE=y.  Otherwise if you plan to use vmlinux
+	  for capturing the crash dump change this value to start of
+	  the reserved region.  In other words, it can be set based on
+	  the "X" value as specified in the "crashkernel=YM@XM"
+	  command line boot parameter passed to the panic-ed
+	  kernel. Please take a look at Documentation/kdump/kdump.txt
+	  for more details about crash dumps.
 
 	  Usage of bzImage for capturing the crash dump is recommended as
 	  one does not have to build two kernels. Same kernel can be used
@@ -1508,8 +1546,8 @@
 	  Don't change this unless you know what you are doing.
 
 config RELOCATABLE
-	bool "Build a relocatable kernel (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "Build a relocatable kernel"
+	default y
 	---help---
 	  This builds a kernel image that retains relocation information
 	  so it can be loaded someplace besides the default 1MB.
@@ -1524,12 +1562,16 @@
 	  it has been loaded at and the compile time physical address
 	  (CONFIG_PHYSICAL_START) is ignored.
 
+# Relocation on x86-32 needs some additional build support
+config X86_NEED_RELOCS
+	def_bool y
+	depends on X86_32 && RELOCATABLE
+
 config PHYSICAL_ALIGN
 	hex
 	prompt "Alignment value to which kernel should be aligned" if X86_32
-	default "0x100000" if X86_32
-	default "0x200000" if X86_64
-	range 0x2000 0x400000
+	default "0x1000000"
+	range 0x2000 0x1000000
 	---help---
 	  This value puts the alignment restrictions on physical address
 	  where kernel is loaded and run from. Kernel is compiled for an
@@ -1871,25 +1913,26 @@
 	  recommended you say N here while the DMAR code remains
 	  experimental.
 
-config DMAR_GFX_WA
-	def_bool y
-	prompt "Support for Graphics workaround"
+config DMAR_BROKEN_GFX_WA
+	def_bool n
+	prompt "Workaround broken graphics drivers (going away soon)"
 	depends on DMAR
 	---help---
 	  Current Graphics drivers tend to use physical address
 	  for DMA and avoid using DMA APIs. Setting this config
 	  option permits the IOMMU driver to set a unity map for
 	  all the OS-visible memory. Hence the driver can continue
-	  to use physical addresses for DMA.
+	  to use physical addresses for DMA, at least until this
+	  option is removed in the 2.6.32 kernel.
 
 config DMAR_FLOPPY_WA
 	def_bool y
 	depends on DMAR
 	---help---
-	  Floppy disk drivers are know to bypass DMA API calls
+	  Floppy disk drivers are known to bypass DMA API calls
 	  thereby failing to work when IOMMU is enabled. This
 	  workaround will setup a 1:1 mapping for the first
-	  16M to make floppy (an ISA device) work.
+	  16MiB to make floppy (an ISA device) work.
 
 config INTR_REMAP
 	bool "Support for Interrupt Remapping (EXPERIMENTAL)"
diff -druN linux-libre-2.6.30-gnu/arch/x86/Kconfig.debug linux-libre-2.6.31-gnu/arch/x86/Kconfig.debug
--- linux-libre-2.6.30-gnu/arch/x86/Kconfig.debug	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/Kconfig.debug	2009-09-09 18:13:59.000000000 -0400
@@ -159,14 +159,30 @@
 	  options. See Documentation/x86_64/boot-options.txt for more
 	  details.
 
+config IOMMU_STRESS
+	bool "Enable IOMMU stress-test mode"
+	---help---
+	  This option disables various optimizations in IOMMU related
+	  code to do real stress testing of the IOMMU code. This option
+	  will cause a performance drop and should only be enabled for
+	  testing.
+
 config IOMMU_LEAK
 	bool "IOMMU leak tracing"
-	depends on DEBUG_KERNEL
-	depends on IOMMU_DEBUG
+	depends on IOMMU_DEBUG && DMA_API_DEBUG
 	---help---
 	  Add a simple leak tracer to the IOMMU code. This is useful when you
 	  are debugging a buggy device driver that leaks IOMMU mappings.
 
+config X86_DS_SELFTEST
+    bool "DS selftest"
+    default y
+    depends on DEBUG_KERNEL
+    depends on X86_DS
+	---help---
+	  Perform Debug Store selftests at boot time.
+	  If in doubt, say "N".
+
 config HAVE_MMIOTRACE_SUPPORT
 	def_bool y
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/boot.c linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/boot.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/boot.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/boot.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/ioport.h>
+#include <linux/pci.h>
 
 #include <asm/pgtable.h>
 #include <asm/io_apic.h>
@@ -43,11 +44,7 @@
 
 static int __initdata acpi_force = 0;
 u32 acpi_rsdt_forced;
-#ifdef	CONFIG_ACPI
-int acpi_disabled = 0;
-#else
-int acpi_disabled = 1;
-#endif
+int acpi_disabled;
 EXPORT_SYMBOL(acpi_disabled);
 
 #ifdef	CONFIG_X86_64
@@ -121,72 +118,6 @@
 	early_iounmap(map, size);
 }
 
-#ifdef CONFIG_PCI_MMCONFIG
-
-static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
-
-/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
-struct acpi_mcfg_allocation *pci_mmcfg_config;
-int pci_mmcfg_config_num;
-
-static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
-{
-	if (!strcmp(mcfg->header.oem_id, "SGI"))
-		acpi_mcfg_64bit_base_addr = TRUE;
-
-	return 0;
-}
-
-int __init acpi_parse_mcfg(struct acpi_table_header *header)
-{
-	struct acpi_table_mcfg *mcfg;
-	unsigned long i;
-	int config_size;
-
-	if (!header)
-		return -EINVAL;
-
-	mcfg = (struct acpi_table_mcfg *)header;
-
-	/* how many config structures do we have */
-	pci_mmcfg_config_num = 0;
-	i = header->length - sizeof(struct acpi_table_mcfg);
-	while (i >= sizeof(struct acpi_mcfg_allocation)) {
-		++pci_mmcfg_config_num;
-		i -= sizeof(struct acpi_mcfg_allocation);
-	};
-	if (pci_mmcfg_config_num == 0) {
-		printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
-		return -ENODEV;
-	}
-
-	config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
-	pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);
-	if (!pci_mmcfg_config) {
-		printk(KERN_WARNING PREFIX
-		       "No memory for MCFG config tables\n");
-		return -ENOMEM;
-	}
-
-	memcpy(pci_mmcfg_config, &mcfg[1], config_size);
-
-	acpi_mcfg_oem_check(mcfg);
-
-	for (i = 0; i < pci_mmcfg_config_num; ++i) {
-		if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
-		    !acpi_mcfg_64bit_base_addr) {
-			printk(KERN_ERR PREFIX
-			       "MMCONFIG not in low 4GB of memory\n");
-			kfree(pci_mmcfg_config);
-			pci_mmcfg_config_num = 0;
-			return -ENODEV;
-		}
-	}
-
-	return 0;
-}
-#endif				/* CONFIG_PCI_MMCONFIG */
-
 #ifdef CONFIG_X86_LOCAL_APIC
 static int __init acpi_parse_madt(struct acpi_table_header *table)
 {
@@ -522,7 +453,7 @@
  * success: return IRQ number (>=0)
  * failure: return < 0
  */
-int acpi_register_gsi(u32 gsi, int triggering, int polarity)
+int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 {
 	unsigned int irq;
 	unsigned int plat_gsi = gsi;
@@ -532,14 +463,14 @@
 	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
 	 */
 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
-		if (triggering == ACPI_LEVEL_SENSITIVE)
+		if (trigger == ACPI_LEVEL_SENSITIVE)
 			eisa_set_level_irq(gsi);
 	}
 #endif
 
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
-		plat_gsi = mp_register_gsi(gsi, triggering, polarity);
+		plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
 	}
 #endif
 	acpi_gsi_to_irq(plat_gsi, &irq);
@@ -903,10 +834,8 @@
 #endif
 
 static struct {
-	int apic_id;
 	int gsi_base;
 	int gsi_end;
-	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 
 int mp_find_ioapic(int gsi)
@@ -986,16 +915,12 @@
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
 	mp_ioapics[idx].apicid = uniq_ioapic_id(id);
-#ifdef CONFIG_X86_32
 	mp_ioapics[idx].apicver = io_apic_get_version(idx);
-#else
-	mp_ioapics[idx].apicver = 0;
-#endif
+
 	/*
 	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
 	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
 	 */
-	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
 	mp_ioapic_routing[idx].gsi_base = gsi_base;
 	mp_ioapic_routing[idx].gsi_end = gsi_base +
 	    io_apic_get_redir_entries(idx);
@@ -1158,26 +1083,52 @@
 	}
 }
 
-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
+			int polarity)
 {
+#ifdef CONFIG_X86_MPPARSE
+	struct mpc_intsrc mp_irq;
+	struct pci_dev *pdev;
+	unsigned char number;
+	unsigned int devfn;
 	int ioapic;
-	int ioapic_pin;
-#ifdef CONFIG_X86_32
-#define MAX_GSI_NUM	4096
-#define IRQ_COMPRESSION_START	64
+	u8 pin;
 
-	static int pci_irq = IRQ_COMPRESSION_START;
-	/*
-	 * Mapping between Global System Interrupts, which
-	 * represent all possible interrupts, and IRQs
-	 * assigned to actual devices.
-	 */
-	static int gsi_to_irq[MAX_GSI_NUM];
-#else
+	if (!acpi_ioapic)
+		return 0;
+	if (!dev)
+		return 0;
+	if (dev->bus != &pci_bus_type)
+		return 0;
+
+	pdev = to_pci_dev(dev);
+	number = pdev->bus->number;
+	devfn = pdev->devfn;
+	pin = pdev->pin;
+	/* print the entry should happen on mptable identically */
+	mp_irq.type = MP_INTSRC;
+	mp_irq.irqtype = mp_INT;
+	mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	mp_irq.srcbus = number;
+	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	mp_irq.dstapic = mp_ioapics[ioapic].apicid;
+	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+
+	save_mp_irq(&mp_irq);
+#endif
+	return 0;
+}
+
+int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+{
+	int ioapic;
+	int ioapic_pin;
+	struct io_apic_irq_attr irq_attr;
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
-#endif
 
 	/* Don't set up the ACPI SCI because it's already set up */
 	if (acpi_gbl_FADT.sci_interrupt == gsi)
@@ -1196,93 +1147,22 @@
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
 
-	/*
-	 * Avoid pin reprogramming.  PRTs typically include entries
-	 * with redundant pin->gsi mappings (but unique PCI devices);
-	 * we only program the IOAPIC on the first.
-	 */
 	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
 		printk(KERN_ERR "Invalid reference to IOAPIC pin "
-		       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
+		       "%d-%d\n", mp_ioapics[ioapic].apicid,
 		       ioapic_pin);
 		return gsi;
 	}
-	if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
-		pr_debug("Pin %d-%d already programmed\n",
-			 mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-#ifdef CONFIG_X86_32
-		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
-#else
-		return gsi;
-#endif
-	}
-
-	set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
-#ifdef CONFIG_X86_32
-	/*
-	 * For GSI >= 64, use IRQ compression
-	 */
-	if ((gsi >= IRQ_COMPRESSION_START)
-	    && (triggering == ACPI_LEVEL_SENSITIVE)) {
-		/*
-		 * For PCI devices assign IRQs in order, avoiding gaps
-		 * due to unused I/O APIC pins.
-		 */
-		int irq = gsi;
-		if (gsi < MAX_GSI_NUM) {
-			/*
-			 * Retain the VIA chipset work-around (gsi > 15), but
-			 * avoid a problem where the 8254 timer (IRQ0) is setup
-			 * via an override (so it's not on pin 0 of the ioapic),
-			 * and at the same time, the pin 0 interrupt is a PCI
-			 * type.  The gsi > 15 test could cause these two pins
-			 * to be shared as IRQ0, and they are not shareable.
-			 * So test for this condition, and if necessary, avoid
-			 * the pin collision.
-			 */
-			gsi = pci_irq++;
-			/*
-			 * Don't assign IRQ used by ACPI SCI
-			 */
-			if (gsi == acpi_gbl_FADT.sci_interrupt)
-				gsi = pci_irq++;
-			gsi_to_irq[irq] = gsi;
-		} else {
-			printk(KERN_ERR "GSI %u is too high\n", gsi);
-			return gsi;
-		}
-	}
-#endif
-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
-				triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
-				polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-	return gsi;
-}
 
-int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
-			u32 gsi, int triggering, int polarity)
-{
-#ifdef CONFIG_X86_MPPARSE
-	struct mpc_intsrc mp_irq;
-	int ioapic;
-
-	if (!acpi_ioapic)
-		return 0;
+	if (enable_update_mptable)
+		mp_config_acpi_gsi(dev, gsi, trigger, polarity);
 
-	/* print the entry should happen on mptable identically */
-	mp_irq.type = MP_INTSRC;
-	mp_irq.irqtype = mp_INT;
-	mp_irq.irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
-				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
-	mp_irq.srcbus = number;
-	mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
-	ioapic = mp_find_ioapic(gsi);
-	mp_irq.dstapic = mp_ioapic_routing[ioapic].apic_id;
-	mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+	set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
+			     trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
+			     polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+	io_apic_set_pci_routing(dev, gsi, &irq_attr);
 
-	save_mp_irq(&mp_irq);
-#endif
-	return 0;
+	return gsi;
 }
 
 /*
@@ -1568,14 +1448,6 @@
 		     },
 	 },
 	{
-	 .callback = force_acpi_ht,
-	 .ident = "ASUS P4B266",
-	 .matches = {
-		     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-		     DMI_MATCH(DMI_BOARD_NAME, "P4B266"),
-		     },
-	 },
-	{
 	 .callback = force_acpi_ht,
 	 .ident = "ASUS P2B-DS",
 	 .matches = {
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/cstate.c linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/cstate.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/cstate.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/cstate.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,12 +34,22 @@
 		flags->bm_check = 1;
 	else if (c->x86_vendor == X86_VENDOR_INTEL) {
 		/*
-		 * Today all CPUs that support C3 share cache.
-		 * TBD: This needs to look at cache shared map, once
-		 * multi-core detection patch makes to the base.
+		 * Today all MP CPUs that support C3 share cache.
+		 * And caches should not be flushed by software while
+		 * entering C3 type state.
 		 */
 		flags->bm_check = 1;
 	}
+
+	/*
+	 * On all recent Intel platforms, ARB_DISABLE is a nop.
+	 * So, set bm_control to zero to indicate that ARB_DISABLE
+	 * is not required while entering C3 type state on
+	 * P4, Core and beyond CPUs
+	 */
+	if (c->x86_vendor == X86_VENDOR_INTEL &&
+	    (c->x86 > 0x6 || (c->x86 == 6 && c->x86_model >= 14)))
+			flags->bm_control = 0;
 }
 EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/processor.c linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/processor.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/processor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/processor.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,6 +72,7 @@
 	return;
 }
 
+
 /* Initialize _PDC data based on the CPU vendor */
 void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
 {
@@ -85,3 +86,15 @@
 }
 
 EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
+
+void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr)
+{
+	if (pr->pdc) {
+		kfree(pr->pdc->pointer->buffer.pointer);
+		kfree(pr->pdc->pointer);
+		kfree(pr->pdc);
+		pr->pdc = NULL;
+	}
+}
+
+EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/realmode/bioscall.S linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/realmode/bioscall.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/realmode/bioscall.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/realmode/bioscall.S	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include "../../../boot/bioscall.S"
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/realmode/Makefile linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/realmode/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/realmode/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/realmode/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -9,7 +9,7 @@
 always		:= wakeup.bin
 targets		:= wakeup.elf wakeup.lds
 
-wakeup-y	+= wakeup.o wakemain.o video-mode.o copy.o
+wakeup-y	+= wakeup.o wakemain.o video-mode.o copy.o bioscall.o regs.o
 
 # The link order of the video-*.o modules can matter.  In particular,
 # video-vga.o *must* be listed first, followed by video-vesa.o.
@@ -42,6 +42,7 @@
 		   $(call cc-option, -mpreferred-stack-boundary=2)
 KBUILD_CFLAGS	+= $(call cc-option, -m32)
 KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
+GCOV_PROFILE := n
 
 WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y))
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/realmode/regs.c linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/realmode/regs.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/realmode/regs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/realmode/regs.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include "../../../boot/regs.c"
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/sleep.c linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/sleep.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/acpi/sleep.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/acpi/sleep.c	2009-09-09 18:13:59.000000000 -0400
@@ -104,7 +104,7 @@
 	initial_gs = per_cpu_offset(smp_processor_id());
 #endif
 	initial_code = (unsigned long)wakeup_long64;
-	saved_magic = 0x123456789abcdef0;
+       saved_magic = 0x123456789abcdef0L;
 #endif /* CONFIG_64BIT */
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/amd_iommu.c linux-libre-2.6.31-gnu/arch/x86/kernel/amd_iommu.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/amd_iommu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/amd_iommu.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,16 @@
 static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 			     struct unity_map_entry *e);
 static struct dma_ops_domain *find_protection_domain(u16 devid);
+static u64* alloc_pte(struct protection_domain *dom,
+		      unsigned long address, u64
+		      **pte_page, gfp_t gfp);
+static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
+				      unsigned long start_page,
+				      unsigned int pages);
 
+#ifndef BUS_NOTIFY_UNBOUND_DRIVER
+#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005
+#endif
 
 #ifdef CONFIG_AMD_IOMMU_STATS
 
@@ -213,7 +222,7 @@
 {
 	struct amd_iommu *iommu;
 
-	list_for_each_entry(iommu, &amd_iommu_list, list)
+	for_each_iommu(iommu)
 		iommu_poll_events(iommu);
 
 	return IRQ_HANDLED;
@@ -425,6 +434,16 @@
 	iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
 }
 
+/* Flush the whole IO/TLB for a given protection domain - including PDE */
+static void iommu_flush_tlb_pde(struct amd_iommu *iommu, u16 domid)
+{
+       u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+
+       INC_STATS_COUNTER(domain_flush_single);
+
+       iommu_queue_inv_iommu_pages(iommu, address, domid, 1, 1);
+}
+
 /*
  * This function is used to flush the IO/TLB for a given protection domain
  * on every IOMMU in the system
@@ -440,7 +459,7 @@
 	__iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
 				      domid, 1, 1);
 
-	list_for_each_entry(iommu, &amd_iommu_list, list) {
+	for_each_iommu(iommu) {
 		spin_lock_irqsave(&iommu->lock, flags);
 		__iommu_queue_command(iommu, &cmd);
 		__iommu_completion_wait(iommu);
@@ -449,6 +468,35 @@
 	}
 }
 
+void amd_iommu_flush_all_domains(void)
+{
+	int i;
+
+	for (i = 1; i < MAX_DOMAIN_ID; ++i) {
+		if (!test_bit(i, amd_iommu_pd_alloc_bitmap))
+			continue;
+		iommu_flush_domain(i);
+	}
+}
+
+void amd_iommu_flush_all_devices(void)
+{
+	struct amd_iommu *iommu;
+	int i;
+
+	for (i = 0; i <= amd_iommu_last_bdf; ++i) {
+		if (amd_iommu_pd_table[i] == NULL)
+			continue;
+
+		iommu = amd_iommu_rlookup_table[i];
+		if (!iommu)
+			continue;
+
+		iommu_queue_inv_dev_entry(iommu, i);
+		iommu_completion_wait(iommu);
+	}
+}
+
 /****************************************************************************
  *
  * The functions below are used the create the page table mappings for
@@ -468,7 +516,7 @@
 			  unsigned long phys_addr,
 			  int prot)
 {
-	u64 __pte, *pte, *page;
+	u64 __pte, *pte;
 
 	bus_addr  = PAGE_ALIGN(bus_addr);
 	phys_addr = PAGE_ALIGN(phys_addr);
@@ -477,27 +525,7 @@
 	if (bus_addr > IOMMU_MAP_SIZE_L3 || !(prot & IOMMU_PROT_MASK))
 		return -EINVAL;
 
-	pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(bus_addr)];
-
-	if (!IOMMU_PTE_PRESENT(*pte)) {
-		page = (u64 *)get_zeroed_page(GFP_KERNEL);
-		if (!page)
-			return -ENOMEM;
-		*pte = IOMMU_L2_PDE(virt_to_phys(page));
-	}
-
-	pte = IOMMU_PTE_PAGE(*pte);
-	pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
-
-	if (!IOMMU_PTE_PRESENT(*pte)) {
-		page = (u64 *)get_zeroed_page(GFP_KERNEL);
-		if (!page)
-			return -ENOMEM;
-		*pte = IOMMU_L1_PDE(virt_to_phys(page));
-	}
-
-	pte = IOMMU_PTE_PAGE(*pte);
-	pte = &pte[IOMMU_PTE_L0_INDEX(bus_addr)];
+	pte = alloc_pte(dom, bus_addr, NULL, GFP_KERNEL);
 
 	if (IOMMU_PTE_PRESENT(*pte))
 		return -EBUSY;
@@ -595,7 +623,8 @@
 		 * as allocated in the aperture
 		 */
 		if (addr < dma_dom->aperture_size)
-			__set_bit(addr >> PAGE_SHIFT, dma_dom->bitmap);
+			__set_bit(addr >> PAGE_SHIFT,
+				  dma_dom->aperture[0]->bitmap);
 	}
 
 	return 0;
@@ -632,42 +661,191 @@
  ****************************************************************************/
 
 /*
- * The address allocator core function.
+ * The address allocator core functions.
  *
  * called with domain->lock held
  */
+
+/*
+ * This function checks if there is a PTE for a given dma address. If
+ * there is one, it returns the pointer to it.
+ */
+static u64* fetch_pte(struct protection_domain *domain,
+		      unsigned long address)
+{
+	u64 *pte;
+
+	pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(address)];
+
+	if (!IOMMU_PTE_PRESENT(*pte))
+		return NULL;
+
+	pte = IOMMU_PTE_PAGE(*pte);
+	pte = &pte[IOMMU_PTE_L1_INDEX(address)];
+
+	if (!IOMMU_PTE_PRESENT(*pte))
+		return NULL;
+
+	pte = IOMMU_PTE_PAGE(*pte);
+	pte = &pte[IOMMU_PTE_L0_INDEX(address)];
+
+	return pte;
+}
+
+/*
+ * This function is used to add a new aperture range to an existing
+ * aperture in case of dma_ops domain allocation or address allocation
+ * failure.
+ */
+static int alloc_new_range(struct amd_iommu *iommu,
+			   struct dma_ops_domain *dma_dom,
+			   bool populate, gfp_t gfp)
+{
+	int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT;
+	int i;
+
+#ifdef CONFIG_IOMMU_STRESS
+	populate = false;
+#endif
+
+	if (index >= APERTURE_MAX_RANGES)
+		return -ENOMEM;
+
+	dma_dom->aperture[index] = kzalloc(sizeof(struct aperture_range), gfp);
+	if (!dma_dom->aperture[index])
+		return -ENOMEM;
+
+	dma_dom->aperture[index]->bitmap = (void *)get_zeroed_page(gfp);
+	if (!dma_dom->aperture[index]->bitmap)
+		goto out_free;
+
+	dma_dom->aperture[index]->offset = dma_dom->aperture_size;
+
+	if (populate) {
+		unsigned long address = dma_dom->aperture_size;
+		int i, num_ptes = APERTURE_RANGE_PAGES / 512;
+		u64 *pte, *pte_page;
+
+		for (i = 0; i < num_ptes; ++i) {
+			pte = alloc_pte(&dma_dom->domain, address,
+					&pte_page, gfp);
+			if (!pte)
+				goto out_free;
+
+			dma_dom->aperture[index]->pte_pages[i] = pte_page;
+
+			address += APERTURE_RANGE_SIZE / 64;
+		}
+	}
+
+	dma_dom->aperture_size += APERTURE_RANGE_SIZE;
+
+	/* Intialize the exclusion range if necessary */
+	if (iommu->exclusion_start &&
+	    iommu->exclusion_start >= dma_dom->aperture[index]->offset &&
+	    iommu->exclusion_start < dma_dom->aperture_size) {
+		unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
+		int pages = iommu_num_pages(iommu->exclusion_start,
+					    iommu->exclusion_length,
+					    PAGE_SIZE);
+		dma_ops_reserve_addresses(dma_dom, startpage, pages);
+	}
+
+	/*
+	 * Check for areas already mapped as present in the new aperture
+	 * range and mark those pages as reserved in the allocator. Such
+	 * mappings may already exist as a result of requested unity
+	 * mappings for devices.
+	 */
+	for (i = dma_dom->aperture[index]->offset;
+	     i < dma_dom->aperture_size;
+	     i += PAGE_SIZE) {
+		u64 *pte = fetch_pte(&dma_dom->domain, i);
+		if (!pte || !IOMMU_PTE_PRESENT(*pte))
+			continue;
+
+		dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1);
+	}
+
+	return 0;
+
+out_free:
+	free_page((unsigned long)dma_dom->aperture[index]->bitmap);
+
+	kfree(dma_dom->aperture[index]);
+	dma_dom->aperture[index] = NULL;
+
+	return -ENOMEM;
+}
+
+static unsigned long dma_ops_area_alloc(struct device *dev,
+					struct dma_ops_domain *dom,
+					unsigned int pages,
+					unsigned long align_mask,
+					u64 dma_mask,
+					unsigned long start)
+{
+	unsigned long next_bit = dom->next_address % APERTURE_RANGE_SIZE;
+	int max_index = dom->aperture_size >> APERTURE_RANGE_SHIFT;
+	int i = start >> APERTURE_RANGE_SHIFT;
+	unsigned long boundary_size;
+	unsigned long address = -1;
+	unsigned long limit;
+
+	next_bit >>= PAGE_SHIFT;
+
+	boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+			PAGE_SIZE) >> PAGE_SHIFT;
+
+	for (;i < max_index; ++i) {
+		unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT;
+
+		if (dom->aperture[i]->offset >= dma_mask)
+			break;
+
+		limit = iommu_device_max_index(APERTURE_RANGE_PAGES, offset,
+					       dma_mask >> PAGE_SHIFT);
+
+		address = iommu_area_alloc(dom->aperture[i]->bitmap,
+					   limit, next_bit, pages, 0,
+					    boundary_size, align_mask);
+		if (address != -1) {
+			address = dom->aperture[i]->offset +
+				  (address << PAGE_SHIFT);
+			dom->next_address = address + (pages << PAGE_SHIFT);
+			break;
+		}
+
+		next_bit = 0;
+	}
+
+	return address;
+}
+
 static unsigned long dma_ops_alloc_addresses(struct device *dev,
 					     struct dma_ops_domain *dom,
 					     unsigned int pages,
 					     unsigned long align_mask,
 					     u64 dma_mask)
 {
-	unsigned long limit;
 	unsigned long address;
-	unsigned long boundary_size;
 
-	boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
-			PAGE_SIZE) >> PAGE_SHIFT;
-	limit = iommu_device_max_index(dom->aperture_size >> PAGE_SHIFT, 0,
-				       dma_mask >> PAGE_SHIFT);
+#ifdef CONFIG_IOMMU_STRESS
+	dom->next_address = 0;
+	dom->need_flush = true;
+#endif
 
-	if (dom->next_bit >= limit) {
-		dom->next_bit = 0;
-		dom->need_flush = true;
-	}
+	address = dma_ops_area_alloc(dev, dom, pages, align_mask,
+				     dma_mask, dom->next_address);
 
-	address = iommu_area_alloc(dom->bitmap, limit, dom->next_bit, pages,
-				   0 , boundary_size, align_mask);
 	if (address == -1) {
-		address = iommu_area_alloc(dom->bitmap, limit, 0, pages,
-				0, boundary_size, align_mask);
+		dom->next_address = 0;
+		address = dma_ops_area_alloc(dev, dom, pages, align_mask,
+					     dma_mask, 0);
 		dom->need_flush = true;
 	}
 
-	if (likely(address != -1)) {
-		dom->next_bit = address + pages;
-		address <<= PAGE_SHIFT;
-	} else
+	if (unlikely(address == -1))
 		address = bad_dma_address;
 
 	WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size);
@@ -684,11 +862,23 @@
 				   unsigned long address,
 				   unsigned int pages)
 {
-	address >>= PAGE_SHIFT;
-	iommu_area_free(dom->bitmap, address, pages);
+	unsigned i = address >> APERTURE_RANGE_SHIFT;
+	struct aperture_range *range = dom->aperture[i];
 
-	if (address >= dom->next_bit)
+	BUG_ON(i >= APERTURE_MAX_RANGES || range == NULL);
+
+#ifdef CONFIG_IOMMU_STRESS
+	if (i < 4)
+		return;
+#endif
+
+	if (address >= dom->next_address)
 		dom->need_flush = true;
+
+	address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT;
+
+	iommu_area_free(range->bitmap, address, pages);
+
 }
 
 /****************************************************************************
@@ -736,12 +926,16 @@
 				      unsigned long start_page,
 				      unsigned int pages)
 {
-	unsigned int last_page = dom->aperture_size >> PAGE_SHIFT;
+	unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT;
 
 	if (start_page + pages > last_page)
 		pages = last_page - start_page;
 
-	iommu_area_reserve(dom->bitmap, start_page, pages);
+	for (i = start_page; i < start_page + pages; ++i) {
+		int index = i / APERTURE_RANGE_PAGES;
+		int page  = i % APERTURE_RANGE_PAGES;
+		__set_bit(page, dom->aperture[index]->bitmap);
+	}
 }
 
 static void free_pagetable(struct protection_domain *domain)
@@ -780,14 +974,19 @@
  */
 static void dma_ops_domain_free(struct dma_ops_domain *dom)
 {
+	int i;
+
 	if (!dom)
 		return;
 
 	free_pagetable(&dom->domain);
 
-	kfree(dom->pte_pages);
-
-	kfree(dom->bitmap);
+	for (i = 0; i < APERTURE_MAX_RANGES; ++i) {
+		if (!dom->aperture[i])
+			continue;
+		free_page((unsigned long)dom->aperture[i]->bitmap);
+		kfree(dom->aperture[i]);
+	}
 
 	kfree(dom);
 }
@@ -797,19 +996,9 @@
  * It also intializes the page table and the address allocator data
  * structures required for the dma_ops interface
  */
-static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
-						   unsigned order)
+static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)
 {
 	struct dma_ops_domain *dma_dom;
-	unsigned i, num_pte_pages;
-	u64 *l2_pde;
-	u64 address;
-
-	/*
-	 * Currently the DMA aperture must be between 32 MB and 1GB in size
-	 */
-	if ((order < 25) || (order > 30))
-		return NULL;
 
 	dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL);
 	if (!dma_dom)
@@ -826,55 +1015,20 @@
 	dma_dom->domain.priv = dma_dom;
 	if (!dma_dom->domain.pt_root)
 		goto free_dma_dom;
-	dma_dom->aperture_size = (1ULL << order);
-	dma_dom->bitmap = kzalloc(dma_dom->aperture_size / (PAGE_SIZE * 8),
-				  GFP_KERNEL);
-	if (!dma_dom->bitmap)
-		goto free_dma_dom;
-	/*
-	 * mark the first page as allocated so we never return 0 as
-	 * a valid dma-address. So we can use 0 as error value
-	 */
-	dma_dom->bitmap[0] = 1;
-	dma_dom->next_bit = 0;
 
 	dma_dom->need_flush = false;
 	dma_dom->target_dev = 0xffff;
 
-	/* Intialize the exclusion range if necessary */
-	if (iommu->exclusion_start &&
-	    iommu->exclusion_start < dma_dom->aperture_size) {
-		unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
-		int pages = iommu_num_pages(iommu->exclusion_start,
-					    iommu->exclusion_length,
-					    PAGE_SIZE);
-		dma_ops_reserve_addresses(dma_dom, startpage, pages);
-	}
+	if (alloc_new_range(iommu, dma_dom, true, GFP_KERNEL))
+		goto free_dma_dom;
 
 	/*
-	 * At the last step, build the page tables so we don't need to
-	 * allocate page table pages in the dma_ops mapping/unmapping
-	 * path.
+	 * mark the first page as allocated so we never return 0 as
+	 * a valid dma-address. So we can use 0 as error value
 	 */
-	num_pte_pages = dma_dom->aperture_size / (PAGE_SIZE * 512);
-	dma_dom->pte_pages = kzalloc(num_pte_pages * sizeof(void *),
-			GFP_KERNEL);
-	if (!dma_dom->pte_pages)
-		goto free_dma_dom;
-
-	l2_pde = (u64 *)get_zeroed_page(GFP_KERNEL);
-	if (l2_pde == NULL)
-		goto free_dma_dom;
+	dma_dom->aperture[0]->bitmap[0] = 1;
+	dma_dom->next_address = 0;
 
-	dma_dom->domain.pt_root[0] = IOMMU_L2_PDE(virt_to_phys(l2_pde));
-
-	for (i = 0; i < num_pte_pages; ++i) {
-		dma_dom->pte_pages[i] = (u64 *)get_zeroed_page(GFP_KERNEL);
-		if (!dma_dom->pte_pages[i])
-			goto free_dma_dom;
-		address = virt_to_phys(dma_dom->pte_pages[i]);
-		l2_pde[i] = IOMMU_L1_PDE(address);
-	}
 
 	return dma_dom;
 
@@ -934,7 +1088,13 @@
 	amd_iommu_pd_table[devid] = domain;
 	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
 
+       /*
+        * We might boot into a crash-kernel here. The crashed kernel
+        * left the caches in the IOMMU dirty. So we have to flush
+        * here to evict all dirty stuff.
+        */
 	iommu_queue_inv_dev_entry(iommu, devid);
+	iommu_flush_tlb_pde(iommu, domain->id);
 }
 
 /*
@@ -983,7 +1143,6 @@
 	struct protection_domain *domain;
 	struct dma_ops_domain *dma_domain;
 	struct amd_iommu *iommu;
-	int order = amd_iommu_aperture_order;
 	unsigned long flags;
 
 	if (devid > amd_iommu_last_bdf)
@@ -1002,17 +1161,7 @@
 			  "to a non-dma-ops domain\n", dev_name(dev));
 
 	switch (action) {
-	case BUS_NOTIFY_BOUND_DRIVER:
-		if (domain)
-			goto out;
-		dma_domain = find_protection_domain(devid);
-		if (!dma_domain)
-			dma_domain = iommu->default_dom;
-		attach_device(iommu, &dma_domain->domain, devid);
-		printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
-		       "device %s\n", dma_domain->domain.id, dev_name(dev));
-		break;
-	case BUS_NOTIFY_UNBIND_DRIVER:
+	case BUS_NOTIFY_UNBOUND_DRIVER:
 		if (!domain)
 			goto out;
 		detach_device(domain, devid);
@@ -1022,7 +1171,7 @@
 		dma_domain = find_protection_domain(devid);
 		if (dma_domain)
 			goto out;
-		dma_domain = dma_ops_domain_alloc(iommu, order);
+		dma_domain = dma_ops_domain_alloc(iommu);
 		if (!dma_domain)
 			goto out;
 		dma_domain->target_dev = devid;
@@ -1043,7 +1192,7 @@
 	return 0;
 }
 
-struct notifier_block device_nb = {
+static struct notifier_block device_nb = {
 	.notifier_call = device_change_notifier,
 };
 
@@ -1133,8 +1282,8 @@
 			dma_dom = (*iommu)->default_dom;
 		*domain = &dma_dom->domain;
 		attach_device(*iommu, *domain, *bdf);
-		printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
-				"device %s\n", (*domain)->id, dev_name(dev));
+		DUMP_printk("Using protection domain %d for device %s\n",
+			    (*domain)->id, dev_name(dev));
 	}
 
 	if (domain_for_device(_bdf) == NULL)
@@ -1144,6 +1293,66 @@
 }
 
 /*
+ * If the pte_page is not yet allocated this function is called
+ */
+static u64* alloc_pte(struct protection_domain *dom,
+		      unsigned long address, u64 **pte_page, gfp_t gfp)
+{
+	u64 *pte, *page;
+
+	pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(address)];
+
+	if (!IOMMU_PTE_PRESENT(*pte)) {
+		page = (u64 *)get_zeroed_page(gfp);
+		if (!page)
+			return NULL;
+		*pte = IOMMU_L2_PDE(virt_to_phys(page));
+	}
+
+	pte = IOMMU_PTE_PAGE(*pte);
+	pte = &pte[IOMMU_PTE_L1_INDEX(address)];
+
+	if (!IOMMU_PTE_PRESENT(*pte)) {
+		page = (u64 *)get_zeroed_page(gfp);
+		if (!page)
+			return NULL;
+		*pte = IOMMU_L1_PDE(virt_to_phys(page));
+	}
+
+	pte = IOMMU_PTE_PAGE(*pte);
+
+	if (pte_page)
+		*pte_page = pte;
+
+	pte = &pte[IOMMU_PTE_L0_INDEX(address)];
+
+	return pte;
+}
+
+/*
+ * This function fetches the PTE for a given address in the aperture
+ */
+static u64* dma_ops_get_pte(struct dma_ops_domain *dom,
+			    unsigned long address)
+{
+	struct aperture_range *aperture;
+	u64 *pte, *pte_page;
+
+	aperture = dom->aperture[APERTURE_RANGE_INDEX(address)];
+	if (!aperture)
+		return NULL;
+
+	pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
+	if (!pte) {
+		pte = alloc_pte(&dom->domain, address, &pte_page, GFP_ATOMIC);
+		aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page;
+	} else
+		pte += IOMMU_PTE_L0_INDEX(address);
+
+	return pte;
+}
+
+/*
  * This is the generic map function. It maps one 4kb page at paddr to
  * the given address in the DMA address space for the domain.
  */
@@ -1159,8 +1368,9 @@
 
 	paddr &= PAGE_MASK;
 
-	pte  = dom->pte_pages[IOMMU_PTE_L1_INDEX(address)];
-	pte += IOMMU_PTE_L0_INDEX(address);
+	pte  = dma_ops_get_pte(dom, address);
+	if (!pte)
+		return bad_dma_address;
 
 	__pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC;
 
@@ -1185,14 +1395,20 @@
 				 struct dma_ops_domain *dom,
 				 unsigned long address)
 {
+	struct aperture_range *aperture;
 	u64 *pte;
 
 	if (address >= dom->aperture_size)
 		return;
 
-	WARN_ON(address & ~PAGE_MASK || address >= dom->aperture_size);
+	aperture = dom->aperture[APERTURE_RANGE_INDEX(address)];
+	if (!aperture)
+		return;
+
+	pte  = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
+	if (!pte)
+		return;
 
-	pte  = dom->pte_pages[IOMMU_PTE_L1_INDEX(address)];
 	pte += IOMMU_PTE_L0_INDEX(address);
 
 	WARN_ON(!*pte);
@@ -1216,7 +1432,7 @@
 			       u64 dma_mask)
 {
 	dma_addr_t offset = paddr & ~PAGE_MASK;
-	dma_addr_t address, start;
+	dma_addr_t address, start, ret;
 	unsigned int pages;
 	unsigned long align_mask = 0;
 	int i;
@@ -1232,14 +1448,33 @@
 	if (align)
 		align_mask = (1UL << get_order(size)) - 1;
 
+retry:
 	address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask,
 					  dma_mask);
-	if (unlikely(address == bad_dma_address))
-		goto out;
+	if (unlikely(address == bad_dma_address)) {
+		/*
+		 * setting next_address here will let the address
+		 * allocator only scan the new allocated range in the
+		 * first run. This is a small optimization.
+		 */
+		dma_dom->next_address = dma_dom->aperture_size;
+
+		if (alloc_new_range(iommu, dma_dom, false, GFP_ATOMIC))
+			goto out;
+
+		/*
+		 * aperture was sucessfully enlarged by 128 MB, try
+		 * allocation again
+		 */
+		goto retry;
+	}
 
 	start = address;
 	for (i = 0; i < pages; ++i) {
-		dma_ops_domain_map(iommu, dma_dom, start, paddr, dir);
+		ret = dma_ops_domain_map(iommu, dma_dom, start, paddr, dir);
+		if (ret == bad_dma_address)
+			goto out_unmap;
+
 		paddr += PAGE_SIZE;
 		start += PAGE_SIZE;
 	}
@@ -1255,6 +1490,17 @@
 
 out:
 	return address;
+
+out_unmap:
+
+	for (--i; i >= 0; --i) {
+		start -= PAGE_SIZE;
+		dma_ops_domain_unmap(iommu, dma_dom, start);
+	}
+
+	dma_ops_free_addresses(dma_dom, address, pages);
+
+	return bad_dma_address;
 }
 
 /*
@@ -1517,7 +1763,7 @@
 	flag |= __GFP_ZERO;
 	virt_addr = (void *)__get_free_pages(flag, get_order(size));
 	if (!virt_addr)
-		return 0;
+		return NULL;
 
 	paddr = virt_to_phys(virt_addr);
 
@@ -1537,8 +1783,10 @@
 	*dma_addr = __map_single(dev, iommu, domain->priv, paddr,
 				 size, DMA_BIDIRECTIONAL, true, dma_mask);
 
-	if (*dma_addr == bad_dma_address)
+	if (*dma_addr == bad_dma_address) {
+		spin_unlock_irqrestore(&domain->lock, flags);
 		goto out_free;
+	}
 
 	iommu_completion_wait(iommu);
 
@@ -1625,7 +1873,6 @@
 	struct pci_dev *dev = NULL;
 	struct dma_ops_domain *dma_dom;
 	struct amd_iommu *iommu;
-	int order = amd_iommu_aperture_order;
 	u16 devid;
 
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
@@ -1638,7 +1885,7 @@
 		iommu = amd_iommu_rlookup_table[devid];
 		if (!iommu)
 			continue;
-		dma_dom = dma_ops_domain_alloc(iommu, order);
+		dma_dom = dma_ops_domain_alloc(iommu);
 		if (!dma_dom)
 			continue;
 		init_unity_mappings_for_device(dma_dom, devid);
@@ -1664,7 +1911,6 @@
 int __init amd_iommu_init_dma_ops(void)
 {
 	struct amd_iommu *iommu;
-	int order = amd_iommu_aperture_order;
 	int ret;
 
 	/*
@@ -1672,8 +1918,8 @@
 	 * found in the system. Devices not assigned to any other
 	 * protection domain will be assigned to the default one.
 	 */
-	list_for_each_entry(iommu, &amd_iommu_list, list) {
-		iommu->default_dom = dma_ops_domain_alloc(iommu, order);
+	for_each_iommu(iommu) {
+		iommu->default_dom = dma_ops_domain_alloc(iommu);
 		if (iommu->default_dom == NULL)
 			return -ENOMEM;
 		iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
@@ -1710,7 +1956,7 @@
 
 free_domains:
 
-	list_for_each_entry(iommu, &amd_iommu_list, list) {
+	for_each_iommu(iommu) {
 		if (iommu->default_dom)
 			dma_ops_domain_free(iommu->default_dom);
 	}
@@ -1842,7 +2088,7 @@
 
 	old_domain = domain_for_device(devid);
 	if (old_domain)
-		return -EBUSY;
+		detach_device(old_domain, devid);
 
 	attach_device(iommu, domain, devid);
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/amd_iommu_init.c linux-libre-2.6.31-gnu/arch/x86/kernel/amd_iommu_init.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/amd_iommu_init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/amd_iommu_init.c	2009-09-09 18:13:59.000000000 -0400
@@ -115,15 +115,21 @@
 	u64 range_length;
 } __attribute__((packed));
 
+bool amd_iommu_dump;
+
 static int __initdata amd_iommu_detected;
 
 u16 amd_iommu_last_bdf;			/* largest PCI device id we have
 					   to handle */
 LIST_HEAD(amd_iommu_unity_map);		/* a list of required unity mappings
 					   we find in ACPI */
-unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */
+#ifdef CONFIG_IOMMU_STRESS
+bool amd_iommu_isolate = false;
+#else
 bool amd_iommu_isolate = true;		/* if true, device isolation is
 					   enabled */
+#endif
+
 bool amd_iommu_unmap_flush;		/* if true, flush on every unmap */
 
 LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
@@ -175,7 +181,7 @@
 static inline unsigned long tbl_size(int entry_size)
 {
 	unsigned shift = PAGE_SHIFT +
-			 get_order(amd_iommu_last_bdf * entry_size);
+			 get_order(((int)amd_iommu_last_bdf + 1) * entry_size);
 
 	return 1UL << shift;
 }
@@ -193,7 +199,7 @@
  * This function set the exclusion range in the IOMMU. DMA accesses to the
  * exclusion range are passed through untranslated
  */
-static void __init iommu_set_exclusion_range(struct amd_iommu *iommu)
+static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
 	u64 start = iommu->exclusion_start & PAGE_MASK;
 	u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
@@ -225,7 +231,7 @@
 }
 
 /* Generic functions to enable/disable certain features of the IOMMU. */
-static void __init iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
+static void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
 {
 	u32 ctrl;
 
@@ -244,7 +250,7 @@
 }
 
 /* Function to enable the hardware */
-static void __init iommu_enable(struct amd_iommu *iommu)
+static void iommu_enable(struct amd_iommu *iommu)
 {
 	printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at %s cap 0x%hx\n",
 	       dev_name(&iommu->dev->dev), iommu->cap_ptr);
@@ -252,11 +258,17 @@
 	iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
 }
 
-/* Function to enable IOMMU event logging and event interrupts */
-static void __init iommu_enable_event_logging(struct amd_iommu *iommu)
+static void iommu_disable(struct amd_iommu *iommu)
 {
-	iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+	/* Disable command buffer */
+	iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
+
+	/* Disable event logging and event interrupts */
+	iommu_feature_disable(iommu, CONTROL_EVT_INT_EN);
+	iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
+
+	/* Disable IOMMU hardware itself */
+	iommu_feature_disable(iommu, CONTROL_IOMMU_EN);
 }
 
 /*
@@ -413,25 +425,36 @@
 {
 	u8 *cmd_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 			get_order(CMD_BUFFER_SIZE));
-	u64 entry;
 
 	if (cmd_buf == NULL)
 		return NULL;
 
 	iommu->cmd_buf_size = CMD_BUFFER_SIZE;
 
-	entry = (u64)virt_to_phys(cmd_buf);
+	return cmd_buf;
+}
+
+/*
+ * This function writes the command buffer address to the hardware and
+ * enables it.
+ */
+static void iommu_enable_command_buffer(struct amd_iommu *iommu)
+{
+	u64 entry;
+
+	BUG_ON(iommu->cmd_buf == NULL);
+
+	entry = (u64)virt_to_phys(iommu->cmd_buf);
 	entry |= MMIO_CMD_SIZE_512;
+
 	memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,
-			&entry, sizeof(entry));
+		    &entry, sizeof(entry));
 
 	/* set head and tail to zero manually */
 	writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
 	writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
 
 	iommu_feature_enable(iommu, CONTROL_CMDBUF_EN);
-
-	return cmd_buf;
 }
 
 static void __init free_command_buffer(struct amd_iommu *iommu)
@@ -443,20 +466,33 @@
 /* allocates the memory where the IOMMU will log its events to */
 static u8 * __init alloc_event_buffer(struct amd_iommu *iommu)
 {
-	u64 entry;
 	iommu->evt_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 						get_order(EVT_BUFFER_SIZE));
 
 	if (iommu->evt_buf == NULL)
 		return NULL;
 
+	iommu->evt_buf_size = EVT_BUFFER_SIZE;
+
+	return iommu->evt_buf;
+}
+
+static void iommu_enable_event_buffer(struct amd_iommu *iommu)
+{
+	u64 entry;
+
+	BUG_ON(iommu->evt_buf == NULL);
+
 	entry = (u64)virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK;
+
 	memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET,
 		    &entry, sizeof(entry));
 
-	iommu->evt_buf_size = EVT_BUFFER_SIZE;
+	/* set head and tail to zero manually */
+	writel(0x00, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
+	writel(0x00, iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
 
-	return iommu->evt_buf;
+	iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
 }
 
 static void __init free_event_buffer(struct amd_iommu *iommu)
@@ -596,32 +632,84 @@
 	p += sizeof(struct ivhd_header);
 	end += h->length;
 
+
 	while (p < end) {
 		e = (struct ivhd_entry *)p;
 		switch (e->type) {
 		case IVHD_DEV_ALL:
+
+			DUMP_printk("  DEV_ALL\t\t\t first devid: %02x:%02x.%x"
+				    " last device %02x:%02x.%x flags: %02x\n",
+				    PCI_BUS(iommu->first_device),
+				    PCI_SLOT(iommu->first_device),
+				    PCI_FUNC(iommu->first_device),
+				    PCI_BUS(iommu->last_device),
+				    PCI_SLOT(iommu->last_device),
+				    PCI_FUNC(iommu->last_device),
+				    e->flags);
+
 			for (dev_i = iommu->first_device;
 					dev_i <= iommu->last_device; ++dev_i)
 				set_dev_entry_from_acpi(iommu, dev_i,
 							e->flags, 0);
 			break;
 		case IVHD_DEV_SELECT:
+
+			DUMP_printk("  DEV_SELECT\t\t\t devid: %02x:%02x.%x "
+				    "flags: %02x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags);
+
 			devid = e->devid;
 			set_dev_entry_from_acpi(iommu, devid, e->flags, 0);
 			break;
 		case IVHD_DEV_SELECT_RANGE_START:
+
+			DUMP_printk("  DEV_SELECT_RANGE_START\t "
+				    "devid: %02x:%02x.%x flags: %02x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags);
+
 			devid_start = e->devid;
 			flags = e->flags;
 			ext_flags = 0;
 			alias = false;
 			break;
 		case IVHD_DEV_ALIAS:
+
+			DUMP_printk("  DEV_ALIAS\t\t\t devid: %02x:%02x.%x "
+				    "flags: %02x devid_to: %02x:%02x.%x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags,
+				    PCI_BUS(e->ext >> 8),
+				    PCI_SLOT(e->ext >> 8),
+				    PCI_FUNC(e->ext >> 8));
+
 			devid = e->devid;
 			devid_to = e->ext >> 8;
-			set_dev_entry_from_acpi(iommu, devid, e->flags, 0);
+			set_dev_entry_from_acpi(iommu, devid   , e->flags, 0);
+			set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0);
 			amd_iommu_alias_table[devid] = devid_to;
 			break;
 		case IVHD_DEV_ALIAS_RANGE:
+
+			DUMP_printk("  DEV_ALIAS_RANGE\t\t "
+				    "devid: %02x:%02x.%x flags: %02x "
+				    "devid_to: %02x:%02x.%x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags,
+				    PCI_BUS(e->ext >> 8),
+				    PCI_SLOT(e->ext >> 8),
+				    PCI_FUNC(e->ext >> 8));
+
 			devid_start = e->devid;
 			flags = e->flags;
 			devid_to = e->ext >> 8;
@@ -629,24 +717,48 @@
 			alias = true;
 			break;
 		case IVHD_DEV_EXT_SELECT:
+
+			DUMP_printk("  DEV_EXT_SELECT\t\t devid: %02x:%02x.%x "
+				    "flags: %02x ext: %08x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags, e->ext);
+
 			devid = e->devid;
 			set_dev_entry_from_acpi(iommu, devid, e->flags,
 						e->ext);
 			break;
 		case IVHD_DEV_EXT_SELECT_RANGE:
+
+			DUMP_printk("  DEV_EXT_SELECT_RANGE\t devid: "
+				    "%02x:%02x.%x flags: %02x ext: %08x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid),
+				    e->flags, e->ext);
+
 			devid_start = e->devid;
 			flags = e->flags;
 			ext_flags = e->ext;
 			alias = false;
 			break;
 		case IVHD_DEV_RANGE_END:
+
+			DUMP_printk("  DEV_RANGE_END\t\t devid: %02x:%02x.%x\n",
+				    PCI_BUS(e->devid),
+				    PCI_SLOT(e->devid),
+				    PCI_FUNC(e->devid));
+
 			devid = e->devid;
 			for (dev_i = devid_start; dev_i <= devid; ++dev_i) {
-				if (alias)
+				if (alias) {
 					amd_iommu_alias_table[dev_i] = devid_to;
-				set_dev_entry_from_acpi(iommu,
-						amd_iommu_alias_table[dev_i],
-						flags, ext_flags);
+					set_dev_entry_from_acpi(iommu,
+						devid_to, flags, ext_flags);
+				}
+				set_dev_entry_from_acpi(iommu, dev_i,
+							flags, ext_flags);
 			}
 			break;
 		default:
@@ -679,7 +791,7 @@
 {
 	struct amd_iommu *iommu, *next;
 
-	list_for_each_entry_safe(iommu, next, &amd_iommu_list, list) {
+	for_each_iommu_safe(iommu, next) {
 		list_del(&iommu->list);
 		free_iommu_one(iommu);
 		kfree(iommu);
@@ -710,7 +822,6 @@
 	if (!iommu->mmio_base)
 		return -ENOMEM;
 
-	iommu_set_device_table(iommu);
 	iommu->cmd_buf = alloc_command_buffer(iommu);
 	if (!iommu->cmd_buf)
 		return -ENOMEM;
@@ -746,6 +857,15 @@
 		h = (struct ivhd_header *)p;
 		switch (*p) {
 		case ACPI_IVHD_TYPE:
+
+			DUMP_printk("IOMMU: device: %02x:%02x.%01x cap: %04x "
+				    "seg: %d flags: %01x info %04x\n",
+				    PCI_BUS(h->devid), PCI_SLOT(h->devid),
+				    PCI_FUNC(h->devid), h->cap_ptr,
+				    h->pci_seg, h->flags, h->info);
+			DUMP_printk("       mmio-addr: %016llx\n",
+				    h->mmio_phys);
+
 			iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL);
 			if (iommu == NULL)
 				return -ENOMEM;
@@ -773,56 +893,9 @@
  *
  ****************************************************************************/
 
-static int __init iommu_setup_msix(struct amd_iommu *iommu)
-{
-	struct amd_iommu *curr;
-	struct msix_entry entries[32]; /* only 32 supported by AMD IOMMU */
-	int nvec = 0, i;
-
-	list_for_each_entry(curr, &amd_iommu_list, list) {
-		if (curr->dev == iommu->dev) {
-			entries[nvec].entry = curr->evt_msi_num;
-			entries[nvec].vector = 0;
-			curr->int_enabled = true;
-			nvec++;
-		}
-	}
-
-	if (pci_enable_msix(iommu->dev, entries, nvec)) {
-		pci_disable_msix(iommu->dev);
-		return 1;
-	}
-
-	for (i = 0; i < nvec; ++i) {
-		int r = request_irq(entries->vector, amd_iommu_int_handler,
-				    IRQF_SAMPLE_RANDOM,
-				    "AMD IOMMU",
-				    NULL);
-		if (r)
-			goto out_free;
-	}
-
-	return 0;
-
-out_free:
-	for (i -= 1; i >= 0; --i)
-		free_irq(entries->vector, NULL);
-
-	pci_disable_msix(iommu->dev);
-
-	return 1;
-}
-
 static int __init iommu_setup_msi(struct amd_iommu *iommu)
 {
 	int r;
-	struct amd_iommu *curr;
-
-	list_for_each_entry(curr, &amd_iommu_list, list) {
-		if (curr->dev == iommu->dev)
-			curr->int_enabled = true;
-	}
-
 
 	if (pci_enable_msi(iommu->dev))
 		return 1;
@@ -837,17 +910,18 @@
 		return 1;
 	}
 
+	iommu->int_enabled = true;
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
 	return 0;
 }
 
-static int __init iommu_init_msi(struct amd_iommu *iommu)
+static int iommu_init_msi(struct amd_iommu *iommu)
 {
 	if (iommu->int_enabled)
 		return 0;
 
-	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSIX))
-		return iommu_setup_msix(iommu);
-	else if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
+	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
 		return iommu_setup_msi(iommu);
 
 	return 1;
@@ -899,6 +973,7 @@
 static int __init init_unity_map_range(struct ivmd_header *m)
 {
 	struct unity_map_entry *e = 0;
+	char *s;
 
 	e = kzalloc(sizeof(*e), GFP_KERNEL);
 	if (e == NULL)
@@ -906,14 +981,19 @@
 
 	switch (m->type) {
 	default:
+		kfree(e);
+		return 0;
 	case ACPI_IVMD_TYPE:
+		s = "IVMD_TYPEi\t\t\t";
 		e->devid_start = e->devid_end = m->devid;
 		break;
 	case ACPI_IVMD_TYPE_ALL:
+		s = "IVMD_TYPE_ALL\t\t";
 		e->devid_start = 0;
 		e->devid_end = amd_iommu_last_bdf;
 		break;
 	case ACPI_IVMD_TYPE_RANGE:
+		s = "IVMD_TYPE_RANGE\t\t";
 		e->devid_start = m->devid;
 		e->devid_end = m->aux;
 		break;
@@ -922,6 +1002,13 @@
 	e->address_end = e->address_start + PAGE_ALIGN(m->range_length);
 	e->prot = m->flags >> 1;
 
+	DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
+		    " range_start: %016llx range_end: %016llx flags: %x\n", s,
+		    PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start),
+		    PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end),
+		    PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
+		    e->address_start, e->address_end, m->flags);
+
 	list_add_tail(&e->list, &amd_iommu_unity_map);
 
 	return 0;
@@ -967,18 +1054,29 @@
  * This function finally enables all IOMMUs found in the system after
  * they have been initialized
  */
-static void __init enable_iommus(void)
+static void enable_iommus(void)
 {
 	struct amd_iommu *iommu;
 
-	list_for_each_entry(iommu, &amd_iommu_list, list) {
+	for_each_iommu(iommu) {
+		iommu_disable(iommu);
+		iommu_set_device_table(iommu);
+		iommu_enable_command_buffer(iommu);
+		iommu_enable_event_buffer(iommu);
 		iommu_set_exclusion_range(iommu);
 		iommu_init_msi(iommu);
-		iommu_enable_event_logging(iommu);
 		iommu_enable(iommu);
 	}
 }
 
+static void disable_iommus(void)
+{
+	struct amd_iommu *iommu;
+
+	for_each_iommu(iommu)
+		iommu_disable(iommu);
+}
+
 /*
  * Suspend/Resume support
  * disable suspend until real resume implemented
@@ -986,12 +1084,25 @@
 
 static int amd_iommu_resume(struct sys_device *dev)
 {
+	/* re-load the hardware */
+	enable_iommus();
+
+	/*
+	 * we have to flush after the IOMMUs are enabled because a
+	 * disabled IOMMU will never execute the commands we send
+	 */
+	amd_iommu_flush_all_devices();
+	amd_iommu_flush_all_domains();
+
 	return 0;
 }
 
 static int amd_iommu_suspend(struct sys_device *dev, pm_message_t state)
 {
-	return -EINVAL;
+	/* disable IOMMUs to go out of the way for BIOS */
+	disable_iommus();
+
+	return 0;
 }
 
 static struct sysdev_class amd_iommu_sysdev_class = {
@@ -1137,9 +1248,6 @@
 
 	enable_iommus();
 
-	printk(KERN_INFO "AMD IOMMU: aperture size is %d MB\n",
-			(1 << (amd_iommu_aperture_order-20)));
-
 	printk(KERN_INFO "AMD IOMMU: device isolation ");
 	if (amd_iommu_isolate)
 		printk("enabled\n");
@@ -1177,6 +1285,11 @@
 	goto out;
 }
 
+void amd_iommu_shutdown(void)
+{
+	disable_iommus();
+}
+
 /****************************************************************************
  *
  * Early detect code. This code runs at IOMMU detection time in the DMA
@@ -1211,6 +1324,13 @@
  *
  ****************************************************************************/
 
+static int __init parse_amd_iommu_dump(char *str)
+{
+	amd_iommu_dump = true;
+
+	return 1;
+}
+
 static int __init parse_amd_iommu_options(char *str)
 {
 	for (; *str; ++str) {
@@ -1225,15 +1345,5 @@
 	return 1;
 }
 
-static int __init parse_amd_iommu_size_options(char *str)
-{
-	unsigned order = PAGE_SHIFT + get_order(memparse(str, &str));
-
-	if ((order > 24) && (order < 31))
-		amd_iommu_aperture_order = order;
-
-	return 1;
-}
-
+__setup("amd_iommu_dump", parse_amd_iommu_dump);
 __setup("amd_iommu=", parse_amd_iommu_options);
-__setup("amd_iommu_size=", parse_amd_iommu_size_options);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/apic.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/apic.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/apic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/apic.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
  *	Mikael Pettersson	:	PM converted to driver model.
  */
 
+#include <linux/perf_counter.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi_pmtmr.h>
@@ -34,6 +35,7 @@
 #include <linux/smp.h>
 #include <linux/mm.h>
 
+#include <asm/perf_counter.h>
 #include <asm/pgalloc.h>
 #include <asm/atomic.h>
 #include <asm/mpspec.h>
@@ -98,6 +100,29 @@
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 static int enabled_via_apicbase;
 
+/*
+ * Handle interrupt mode configuration register (IMCR).
+ * This register controls whether the interrupt signals
+ * that reach the BSP come from the master PIC or from the
+ * local APIC. Before entering Symmetric I/O Mode, either
+ * the BIOS or the operating system must switch out of
+ * PIC Mode by changing the IMCR.
+ */
+static inline void imcr_pic_to_apic(void)
+{
+	/* select IMCR register */
+	outb(0x70, 0x22);
+	/* NMI and 8259 INTR go through APIC */
+	outb(0x01, 0x23);
+}
+
+static inline void imcr_apic_to_pic(void)
+{
+	/* select IMCR register */
+	outb(0x70, 0x22);
+	/* NMI and 8259 INTR go directly to BSP */
+	outb(0x00, 0x23);
+}
 #endif
 
 #ifdef CONFIG_X86_64
@@ -111,14 +136,18 @@
 __setup("apicpmtimer", setup_apicpmtimer);
 #endif
 
+int x2apic_mode;
 #ifdef CONFIG_X86_X2APIC
-int x2apic;
 /* x2apic enabled before OS handover */
 static int x2apic_preenabled;
-static int disable_x2apic;
 static __init int setup_nox2apic(char *str)
 {
-	disable_x2apic = 1;
+	if (x2apic_enabled()) {
+		pr_warning("Bios already enabled x2apic, "
+			   "can't enforce nox2apic");
+		return 0;
+	}
+
 	setup_clear_cpu_cap(X86_FEATURE_X2APIC);
 	return 0;
 }
@@ -209,6 +238,31 @@
 	return lapic_get_version() >= 0x14;
 }
 
+/*
+ * bare function to substitute write operation
+ * and it's _that_ fast :)
+ */
+static void native_apic_write_dummy(u32 reg, u32 v)
+{
+	WARN_ON_ONCE((cpu_has_apic || !disable_apic));
+}
+
+static u32 native_apic_read_dummy(u32 reg)
+{
+	WARN_ON_ONCE((cpu_has_apic && !disable_apic));
+	return 0;
+}
+
+/*
+ * right after this call apic->write/read doesn't do anything
+ * note that there is no restore operation it works one way
+ */
+void apic_disable(void)
+{
+	apic->read = native_apic_read_dummy;
+	apic->write = native_apic_write_dummy;
+}
+
 void native_apic_wait_icr_idle(void)
 {
 	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
@@ -348,7 +402,7 @@
 
 static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
 {
-	unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
+	unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
 	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
 
 	apic_write(reg, v);
@@ -815,7 +869,7 @@
 	u32 v;
 
 	/* APIC hasn't been mapped yet */
-	if (!x2apic && !apic_phys)
+	if (!x2apic_mode && !apic_phys)
 		return;
 
 	maxlvt = lapic_get_maxlvt();
@@ -843,7 +897,7 @@
 	}
 
 	/* lets not touch this if we didn't frob it */
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
+#ifdef CONFIG_X86_THERMAL_VECTOR
 	if (maxlvt >= 5) {
 		v = apic_read(APIC_LVTTHMR);
 		apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
@@ -1133,6 +1187,7 @@
 		apic_write(APIC_ESR, 0);
 	}
 #endif
+	perf_counters_lapic_init();
 
 	preempt_disable();
 
@@ -1287,7 +1342,7 @@
 {
 	if (x2apic_enabled()) {
 		pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
-		x2apic_preenabled = x2apic = 1;
+		x2apic_preenabled = x2apic_mode = 1;
 	}
 }
 
@@ -1295,7 +1350,7 @@
 {
 	int msr, msr2;
 
-	if (!x2apic)
+	if (!x2apic_mode)
 		return;
 
 	rdmsr(MSR_IA32_APICBASE, msr, msr2);
@@ -1304,6 +1359,7 @@
 		wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
 	}
 }
+#endif /* CONFIG_X86_X2APIC */
 
 void __init enable_IR_x2apic(void)
 {
@@ -1312,32 +1368,21 @@
 	unsigned long flags;
 	struct IO_APIC_route_entry **ioapic_entries = NULL;
 
-	if (!cpu_has_x2apic)
-		return;
-
-	if (!x2apic_preenabled && disable_x2apic) {
-		pr_info("Skipped enabling x2apic and Interrupt-remapping "
-			"because of nox2apic\n");
-		return;
+	ret = dmar_table_init();
+	if (ret) {
+		pr_debug("dmar_table_init() failed with %d:\n", ret);
+		goto ir_failed;
 	}
 
-	if (x2apic_preenabled && disable_x2apic)
-		panic("Bios already enabled x2apic, can't enforce nox2apic");
-
-	if (!x2apic_preenabled && skip_ioapic_setup) {
-		pr_info("Skipped enabling x2apic and Interrupt-remapping "
-			"because of skipping io-apic setup\n");
-		return;
+	if (!intr_remapping_supported()) {
+		pr_debug("intr-remapping not supported\n");
+		goto ir_failed;
 	}
 
-	ret = dmar_table_init();
-	if (ret) {
-		pr_info("dmar_table_init() failed with %d:\n", ret);
 
-		if (x2apic_preenabled)
-			panic("x2apic enabled by bios. But IR enabling failed");
-		else
-			pr_info("Not enabling x2apic,Intr-remapping\n");
+	if (!x2apic_preenabled && skip_ioapic_setup) {
+		pr_info("Skipped enabling intr-remap because of skipping "
+			"io-apic setup\n");
 		return;
 	}
 
@@ -1357,19 +1402,16 @@
 	mask_IO_APIC_setup(ioapic_entries);
 	mask_8259A();
 
-	ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
-
-	if (ret && x2apic_preenabled) {
-		local_irq_restore(flags);
-		panic("x2apic enabled by bios. But IR enabling failed");
-	}
-
+	ret = enable_intr_remapping(x2apic_supported());
 	if (ret)
 		goto end_restore;
 
-	if (!x2apic) {
-		x2apic = 1;
+	pr_info("Enabled Interrupt-remapping\n");
+
+	if (x2apic_supported() && !x2apic_mode) {
+		x2apic_mode = 1;
 		enable_x2apic();
+		pr_info("Enabled x2apic\n");
 	}
 
 end_restore:
@@ -1378,37 +1420,34 @@
 		 * IR enabling failed
 		 */
 		restore_IO_APIC_setup(ioapic_entries);
-	else
-		reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);
 
 	unmask_8259A();
 	local_irq_restore(flags);
 
 end:
-	if (!ret) {
-		if (!x2apic_preenabled)
-			pr_info("Enabled x2apic and interrupt-remapping\n");
-		else
-			pr_info("Enabled Interrupt-remapping\n");
-	} else
-		pr_err("Failed to enable Interrupt-remapping and x2apic\n");
 	if (ioapic_entries)
 		free_ioapic_entries(ioapic_entries);
+
+	if (!ret)
+		return;
+
+ir_failed:
+	if (x2apic_preenabled)
+		panic("x2apic enabled by bios. But IR enabling failed");
+	else if (cpu_has_x2apic)
+		pr_info("Not enabling x2apic,Intr-remapping\n");
 #else
 	if (!cpu_has_x2apic)
 		return;
 
 	if (x2apic_preenabled)
 		panic("x2apic enabled prior OS handover,"
-		      " enable CONFIG_INTR_REMAP");
-
-	pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping "
-		" and x2apic\n");
+		      " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
 #endif
 
 	return;
 }
-#endif /* CONFIG_X86_X2APIC */
+
 
 #ifdef CONFIG_X86_64
 /*
@@ -1425,7 +1464,6 @@
 	}
 
 	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-	boot_cpu_physical_apicid = 0;
 	return 0;
 }
 #else
@@ -1539,32 +1577,49 @@
  */
 void __init init_apic_mappings(void)
 {
-	if (x2apic) {
+	unsigned int new_apicid;
+
+	if (x2apic_mode) {
 		boot_cpu_physical_apicid = read_apic_id();
 		return;
 	}
 
-	/*
-	 * If no local APIC can be found then set up a fake all
-	 * zeroes page to simulate the local APIC and another
-	 * one for the IO-APIC.
-	 */
+	/* If no local APIC can be found return early */
 	if (!smp_found_config && detect_init_APIC()) {
-		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-		apic_phys = __pa(apic_phys);
-	} else
+		/* lets NOP'ify apic operations */
+		pr_info("APIC: disable apic facility\n");
+		apic_disable();
+	} else {
 		apic_phys = mp_lapic_addr;
 
-	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-	apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
-				APIC_BASE, apic_phys);
+		/*
+		 * acpi lapic path already maps that address in
+		 * acpi_register_lapic_address()
+		 */
+		if (!acpi_lapic)
+			set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+
+		apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
+					APIC_BASE, apic_phys);
+	}
 
 	/*
 	 * Fetch the APIC ID of the BSP in case we have a
 	 * default configuration (or the MP table is broken).
 	 */
-	if (boot_cpu_physical_apicid == -1U)
-		boot_cpu_physical_apicid = read_apic_id();
+	new_apicid = read_apic_id();
+	if (boot_cpu_physical_apicid != new_apicid) {
+		boot_cpu_physical_apicid = new_apicid;
+		/*
+		 * yeah -- we lie about apic_version
+		 * in case if apic was disabled via boot option
+		 * but it's not a problem for SMP compiled kernel
+		 * since smp_sanity_check is prepared for such a case
+		 * and disable smp mode
+		 */
+		apic_version[new_apicid] =
+			 GET_APIC_VERSION(apic_read(APIC_LVR));
+	}
 }
 
 /*
@@ -1733,8 +1788,7 @@
 		 */
 		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
 				"enabling APIC mode.\n");
-		outb(0x70, 0x22);
-		outb(0x01, 0x23);
+		imcr_pic_to_apic();
 	}
 #endif
 	if (apic->enable_apic_mode)
@@ -1762,8 +1816,7 @@
 		 */
 		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
 				"entering PIC mode.\n");
-		outb(0x70, 0x22);
-		outb(0x00, 0x23);
+		imcr_apic_to_pic();
 		return;
 	}
 #endif
@@ -1962,17 +2015,17 @@
 	apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
 	apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
 	apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
+#ifdef CONFIG_X86_THERMAL_VECTOR
 	if (maxlvt >= 5)
 		apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
 #endif
 
 	local_irq_save(flags);
 	disable_local_APIC();
-#ifdef CONFIG_INTR_REMAP
+
 	if (intr_remapping_enabled)
 		disable_intr_remapping();
-#endif
+
 	local_irq_restore(flags);
 	return 0;
 }
@@ -1982,42 +2035,34 @@
 	unsigned int l, h;
 	unsigned long flags;
 	int maxlvt;
-
-#ifdef CONFIG_INTR_REMAP
-	int ret;
+	int ret = 0;
 	struct IO_APIC_route_entry **ioapic_entries = NULL;
 
 	if (!apic_pm_state.active)
 		return 0;
 
 	local_irq_save(flags);
-	if (x2apic) {
+	if (intr_remapping_enabled) {
 		ioapic_entries = alloc_ioapic_entries();
 		if (!ioapic_entries) {
 			WARN(1, "Alloc ioapic_entries in lapic resume failed.");
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto restore;
 		}
 
 		ret = save_IO_APIC_setup(ioapic_entries);
 		if (ret) {
 			WARN(1, "Saving IO-APIC state failed: %d\n", ret);
 			free_ioapic_entries(ioapic_entries);
-			return ret;
+			goto restore;
 		}
 
 		mask_IO_APIC_setup(ioapic_entries);
 		mask_8259A();
-		enable_x2apic();
 	}
-#else
-	if (!apic_pm_state.active)
-		return 0;
 
-	local_irq_save(flags);
-	if (x2apic)
+	if (x2apic_mode)
 		enable_x2apic();
-#endif
-
 	else {
 		/*
 		 * Make sure the APICBASE points to the right address
@@ -2055,21 +2100,16 @@
 	apic_write(APIC_ESR, 0);
 	apic_read(APIC_ESR);
 
-#ifdef CONFIG_INTR_REMAP
-	if (intr_remapping_enabled)
-		reenable_intr_remapping(EIM_32BIT_APIC_ID);
-
-	if (x2apic) {
+	if (intr_remapping_enabled) {
+		reenable_intr_remapping(x2apic_mode);
 		unmask_8259A();
 		restore_IO_APIC_setup(ioapic_entries);
 		free_ioapic_entries(ioapic_entries);
 	}
-#endif
-
+restore:
 	local_irq_restore(flags);
 
-
-	return 0;
+	return ret;
 }
 
 /*
@@ -2117,31 +2157,14 @@
 #endif	/* CONFIG_PM */
 
 #ifdef CONFIG_X86_64
-/*
- * apic_is_clustered_box() -- Check if we can expect good TSC
- *
- * Thus far, the major user of this is IBM's Summit2 series:
- *
- * Clustered boxes may have unsynced TSC problems if they are
- * multi-chassis. Use available data to take a good guess.
- * If in doubt, go HPET.
- */
-__cpuinit int apic_is_clustered_box(void)
+
+static int __cpuinit apic_cluster_num(void)
 {
 	int i, clusters, zeros;
 	unsigned id;
 	u16 *bios_cpu_apicid;
 	DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
 
-	/*
-	 * there is not this kind of box with AMD CPU yet.
-	 * Some AMD box with quadcore cpu and 8 sockets apicid
-	 * will be [4, 0x23] or [8, 0x27] could be thought to
-	 * vsmp box still need checking...
-	 */
-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
-		return 0;
-
 	bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
 	bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
 
@@ -2177,18 +2200,67 @@
 			++zeros;
 	}
 
-	/* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
-	 * not guaranteed to be synced between boards
-	 */
-	if (is_vsmp_box() && clusters > 1)
+	return clusters;
+}
+
+static int __cpuinitdata multi_checked;
+static int __cpuinitdata multi;
+
+static int __cpuinit set_multi(const struct dmi_system_id *d)
+{
+	if (multi)
+		return 0;
+	pr_info("APIC: %s detected, Multi Chassis\n", d->ident);
+	multi = 1;
+	return 0;
+}
+
+static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = {
+	{
+		.callback = set_multi,
+		.ident = "IBM System Summit2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"),
+		},
+	},
+	{}
+};
+
+static void __cpuinit dmi_check_multi(void)
+{
+	if (multi_checked)
+		return;
+
+	dmi_check_system(multi_dmi_table);
+	multi_checked = 1;
+}
+
+/*
+ * apic_is_clustered_box() -- Check if we can expect good TSC
+ *
+ * Thus far, the major user of this is IBM's Summit2 series:
+ * Clustered boxes may have unsynced TSC problems if they are
+ * multi-chassis.
+ * Use DMI to check them
+ */
+__cpuinit int apic_is_clustered_box(void)
+{
+	dmi_check_multi();
+	if (multi)
 		return 1;
 
+	if (!is_vsmp_box())
+		return 0;
+
 	/*
-	 * If clusters > 2, then should be multi-chassis.
-	 * May have to revisit this when multi-core + hyperthreaded CPUs come
-	 * out, but AFAIK this will work even for them.
+	 * ScaleMP vSMPowered boxes have one cluster per board and TSCs are
+	 * not guaranteed to be synced between boards
 	 */
-	return (clusters > 2);
+	if (apic_cluster_num() > 1)
+		return 1;
+
+	return 0;
 }
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/apic_flat_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/apic_flat_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/apic_flat_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/apic_flat_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -161,7 +161,7 @@
 
 static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
 {
-	return hard_smp_processor_id() >> index_msb;
+	return initial_apic_id >> index_msb;
 }
 
 struct apic apic_flat =  {
@@ -235,7 +235,7 @@
 	 * regardless of how many processors are present (x86_64 ES7000
 	 * is an example).
 	 */
-	if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
+	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
 		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
 		printk(KERN_DEBUG "system APIC only can use physical flat");
 		return 1;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/es7000_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/es7000_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/es7000_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/es7000_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -145,7 +145,7 @@
 	return gsi;
 }
 
-static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
+static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
 {
 	unsigned long vect = 0, psaival = 0;
 
@@ -652,7 +652,8 @@
 	return ret && es7000_apic_is_cluster();
 }
 
-struct apic apic_es7000_cluster = {
+/* We've been warned by a false positive warning.Use __refdata to keep calm. */
+struct apic __refdata apic_es7000_cluster = {
 
 	.name				= "es7000",
 	.probe				= probe_es7000,
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/io_apic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/io_apic.c	2009-09-09 18:13:59.000000000 -0400
@@ -59,6 +59,7 @@
 #include <asm/setup.h>
 #include <asm/irq_remapping.h>
 #include <asm/hpet.h>
+#include <asm/hw_irq.h>
 #include <asm/uv/uv_hub.h>
 #include <asm/uv/uv_irq.h>
 
@@ -129,12 +130,9 @@
 	struct irq_pin_list *next;
 };
 
-static struct irq_pin_list *get_one_free_irq_2_pin(int cpu)
+static struct irq_pin_list *get_one_free_irq_2_pin(int node)
 {
 	struct irq_pin_list *pin;
-	int node;
-
-	node = cpu_to_node(cpu);
 
 	pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
 
@@ -148,9 +146,6 @@
 	unsigned move_cleanup_count;
 	u8 vector;
 	u8 move_in_progress : 1;
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
-	u8 move_desc_pending : 1;
-#endif
 };
 
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -182,16 +177,18 @@
 	struct irq_cfg *cfg;
 	struct irq_desc *desc;
 	int count;
+	int node;
 	int i;
 
 	cfg = irq_cfgx;
 	count = ARRAY_SIZE(irq_cfgx);
+	node= cpu_to_node(boot_cpu_id);
 
 	for (i = 0; i < count; i++) {
 		desc = irq_to_desc(i);
 		desc->chip_data = &cfg[i];
-		alloc_bootmem_cpumask_var(&cfg[i].domain);
-		alloc_bootmem_cpumask_var(&cfg[i].old_domain);
+		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
+		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
 		if (i < NR_IRQS_LEGACY)
 			cpumask_setall(cfg[i].domain);
 	}
@@ -212,12 +209,9 @@
 	return cfg;
 }
 
-static struct irq_cfg *get_one_free_irq_cfg(int cpu)
+static struct irq_cfg *get_one_free_irq_cfg(int node)
 {
 	struct irq_cfg *cfg;
-	int node;
-
-	node = cpu_to_node(cpu);
 
 	cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
 	if (cfg) {
@@ -238,13 +232,13 @@
 	return cfg;
 }
 
-int arch_init_chip_data(struct irq_desc *desc, int cpu)
+int arch_init_chip_data(struct irq_desc *desc, int node)
 {
 	struct irq_cfg *cfg;
 
 	cfg = desc->chip_data;
 	if (!cfg) {
-		desc->chip_data = get_one_free_irq_cfg(cpu);
+		desc->chip_data = get_one_free_irq_cfg(node);
 		if (!desc->chip_data) {
 			printk(KERN_ERR "can not alloc irq_cfg\n");
 			BUG_ON(1);
@@ -254,10 +248,9 @@
 	return 0;
 }
 
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
-
+/* for move_irq_desc */
 static void
-init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
+init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
 {
 	struct irq_pin_list *old_entry, *head, *tail, *entry;
 
@@ -266,7 +259,7 @@
 	if (!old_entry)
 		return;
 
-	entry = get_one_free_irq_2_pin(cpu);
+	entry = get_one_free_irq_2_pin(node);
 	if (!entry)
 		return;
 
@@ -276,7 +269,7 @@
 	tail		= entry;
 	old_entry	= old_entry->next;
 	while (old_entry) {
-		entry = get_one_free_irq_2_pin(cpu);
+		entry = get_one_free_irq_2_pin(node);
 		if (!entry) {
 			entry = head;
 			while (entry) {
@@ -316,12 +309,12 @@
 }
 
 void arch_init_copy_chip_data(struct irq_desc *old_desc,
-				 struct irq_desc *desc, int cpu)
+				 struct irq_desc *desc, int node)
 {
 	struct irq_cfg *cfg;
 	struct irq_cfg *old_cfg;
 
-	cfg = get_one_free_irq_cfg(cpu);
+	cfg = get_one_free_irq_cfg(node);
 
 	if (!cfg)
 		return;
@@ -332,7 +325,7 @@
 
 	memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
 
-	init_copy_irq_2_pin(old_cfg, cfg, cpu);
+	init_copy_irq_2_pin(old_cfg, cfg, node);
 }
 
 static void free_irq_cfg(struct irq_cfg *old_cfg)
@@ -356,19 +349,7 @@
 		old_desc->chip_data = NULL;
 	}
 }
-
-static void
-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
-	struct irq_cfg *cfg = desc->chip_data;
-
-	if (!cfg->move_in_progress) {
-		/* it means that domain is not changed */
-		if (!cpumask_intersects(desc->affinity, mask))
-			cfg->move_desc_pending = 1;
-	}
-}
-#endif
+/* end for move_irq_desc */
 
 #else
 static struct irq_cfg *irq_cfg(unsigned int irq)
@@ -378,13 +359,6 @@
 
 #endif
 
-#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
-static inline void
-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
-}
-#endif
-
 struct io_apic {
 	unsigned int index;
 	unsigned int unused[3];
@@ -488,7 +462,8 @@
 static void
 __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
 {
-	union entry_union eu;
+	union entry_union eu = {{0, 0}};
+
 	eu.entry = e;
 	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
 	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
@@ -518,132 +493,18 @@
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-#ifdef CONFIG_SMP
-static void send_cleanup_vector(struct irq_cfg *cfg)
-{
-	cpumask_var_t cleanup_mask;
-
-	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
-		unsigned int i;
-		cfg->move_cleanup_count = 0;
-		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
-			cfg->move_cleanup_count++;
-		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
-			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
-	} else {
-		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
-		cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
-		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
-		free_cpumask_var(cleanup_mask);
-	}
-	cfg->move_in_progress = 0;
-}
-
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
-{
-	int apic, pin;
-	struct irq_pin_list *entry;
-	u8 vector = cfg->vector;
-
-	entry = cfg->irq_2_pin;
-	for (;;) {
-		unsigned int reg;
-
-		if (!entry)
-			break;
-
-		apic = entry->apic;
-		pin = entry->pin;
-		/*
-		 * With interrupt-remapping, destination information comes
-		 * from interrupt-remapping table entry.
-		 */
-		if (!irq_remapped(irq))
-			io_apic_write(apic, 0x11 + pin*2, dest);
-		reg = io_apic_read(apic, 0x10 + pin*2);
-		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
-		reg |= vector;
-		io_apic_modify(apic, 0x10 + pin*2, reg);
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-}
-
-static int
-assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
-
-/*
- * Either sets desc->affinity to a valid value, and returns
- * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
- * leaves desc->affinity untouched.
- */
-static unsigned int
-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
-{
-	struct irq_cfg *cfg;
-	unsigned int irq;
-
-	if (!cpumask_intersects(mask, cpu_online_mask))
-		return BAD_APICID;
-
-	irq = desc->irq;
-	cfg = desc->chip_data;
-	if (assign_irq_vector(irq, cfg, mask))
-		return BAD_APICID;
-
-	/* check that before desc->addinity get updated */
-	set_extra_move_desc(desc, mask);
-
-	cpumask_copy(desc->affinity, mask);
-
-	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
-}
-
-static void
-set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
-{
-	struct irq_cfg *cfg;
-	unsigned long flags;
-	unsigned int dest;
-	unsigned int irq;
-
-	irq = desc->irq;
-	cfg = desc->chip_data;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	dest = set_desc_affinity(desc, mask);
-	if (dest != BAD_APICID) {
-		/* Only the high 8 bits are valid. */
-		dest = SET_APIC_LOGICAL_ID(dest);
-		__target_IO_APIC_irq(irq, dest, cfg);
-	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-static void
-set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
-{
-	struct irq_desc *desc;
-
-	desc = irq_to_desc(irq);
-
-	set_ioapic_affinity_irq_desc(desc, mask);
-}
-#endif /* CONFIG_SMP */
-
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
+static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
 {
 	struct irq_pin_list *entry;
 
 	entry = cfg->irq_2_pin;
 	if (!entry) {
-		entry = get_one_free_irq_2_pin(cpu);
+		entry = get_one_free_irq_2_pin(node);
 		if (!entry) {
 			printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",
 					apic, pin);
@@ -663,7 +524,7 @@
 		entry = entry->next;
 	}
 
-	entry->next = get_one_free_irq_2_pin(cpu);
+	entry->next = get_one_free_irq_2_pin(node);
 	entry = entry->next;
 	entry->apic = apic;
 	entry->pin = pin;
@@ -672,7 +533,7 @@
 /*
  * Reroute an IRQ to a different pin.
  */
-static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
+static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
 				      int oldapic, int oldpin,
 				      int newapic, int newpin)
 {
@@ -692,7 +553,7 @@
 
 	/* why? call replace before add? */
 	if (!replaced)
-		add_pin_to_irq_cpu(cfg, cpu, newapic, newpin);
+		add_pin_to_irq_node(cfg, node, newapic, newpin);
 }
 
 static inline void io_apic_modify_irq(struct irq_cfg *cfg,
@@ -850,7 +711,6 @@
 __setup("pirq=", ioapic_pirq_setup);
 #endif /* CONFIG_X86_32 */
 
-#ifdef CONFIG_INTR_REMAP
 struct IO_APIC_route_entry **alloc_ioapic_entries(void)
 {
 	int apic;
@@ -948,20 +808,6 @@
 	return 0;
 }
 
-void reinit_intr_remapped_IO_APIC(int intr_remapping,
-	struct IO_APIC_route_entry **ioapic_entries)
-
-{
-	/*
-	 * for now plain restore of previous settings.
-	 * TBD: In the case of OS enabling interrupt-remapping,
-	 * IO-APIC RTE's need to be setup to point to interrupt-remapping
-	 * table entries. for now, do a plain restore, and wait for
-	 * the setup_IO_APIC_irqs() to do proper initialization.
-	 */
-	restore_IO_APIC_setup(ioapic_entries);
-}
-
 void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
 {
 	int apic;
@@ -971,7 +817,6 @@
 
 	kfree(ioapic_entries);
 }
-#endif
 
 /*
  * Find the IRQ entry number of a certain pin.
@@ -1032,54 +877,6 @@
 	return -1;
 }
 
-/*
- * Find a specific PCI IRQ entry.
- * Not an __init, possibly needed by modules
- */
-static int pin_2_irq(int idx, int apic, int pin);
-
-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
-{
-	int apic, i, best_guess = -1;
-
-	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
-		bus, slot, pin);
-	if (test_bit(bus, mp_bus_not_pci)) {
-		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
-		return -1;
-	}
-	for (i = 0; i < mp_irq_entries; i++) {
-		int lbus = mp_irqs[i].srcbus;
-
-		for (apic = 0; apic < nr_ioapics; apic++)
-			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
-			    mp_irqs[i].dstapic == MP_APIC_ALL)
-				break;
-
-		if (!test_bit(lbus, mp_bus_not_pci) &&
-		    !mp_irqs[i].irqtype &&
-		    (bus == lbus) &&
-		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
-			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
-
-			if (!(apic || IO_APIC_IRQ(irq)))
-				continue;
-
-			if (pin == (mp_irqs[i].srcbusirq & 3))
-				return irq;
-			/*
-			 * Use the first all-but-pin matching entry as a
-			 * best-guess fuzzy result for broken mptables.
-			 */
-			if (best_guess < 0)
-				best_guess = irq;
-		}
-	}
-	return best_guess;
-}
-
-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
-
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 /*
  * EISA Edge/Level control register, ELCR
@@ -1298,6 +1095,64 @@
 	return irq;
 }
 
+/*
+ * Find a specific PCI IRQ entry.
+ * Not an __init, possibly needed by modules
+ */
+int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
+				struct io_apic_irq_attr *irq_attr)
+{
+	int apic, i, best_guess = -1;
+
+	apic_printk(APIC_DEBUG,
+		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+		    bus, slot, pin);
+	if (test_bit(bus, mp_bus_not_pci)) {
+		apic_printk(APIC_VERBOSE,
+			    "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+		return -1;
+	}
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].srcbus;
+
+		for (apic = 0; apic < nr_ioapics; apic++)
+			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
+			    mp_irqs[i].dstapic == MP_APIC_ALL)
+				break;
+
+		if (!test_bit(lbus, mp_bus_not_pci) &&
+		    !mp_irqs[i].irqtype &&
+		    (bus == lbus) &&
+		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
+			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+
+			if (!(apic || IO_APIC_IRQ(irq)))
+				continue;
+
+			if (pin == (mp_irqs[i].srcbusirq & 3)) {
+				set_io_apic_irq_attr(irq_attr, apic,
+						     mp_irqs[i].dstirq,
+						     irq_trigger(i),
+						     irq_polarity(i));
+				return irq;
+			}
+			/*
+			 * Use the first all-but-pin matching entry as a
+			 * best-guess fuzzy result for broken mptables.
+			 */
+			if (best_guess < 0) {
+				set_io_apic_irq_attr(irq_attr, apic,
+						     mp_irqs[i].dstirq,
+						     irq_trigger(i),
+						     irq_polarity(i));
+				best_guess = irq;
+			}
+		}
+	}
+	return best_guess;
+}
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+
 void lock_vector_lock(void)
 {
 	/* Used to the online set of cpus does not change
@@ -1559,6 +1414,9 @@
 		irte.vector = vector;
 		irte.dest_id = IRTE_DEST(destination);
 
+		/* Set source-id of interrupt request */
+		set_ioapic_sid(&irte, apic_id);
+
 		modify_irte(irq, &irte);
 
 		ir_entry->index2 = (index >> 15) & 0x1;
@@ -1628,58 +1486,70 @@
 	ioapic_write_entry(apic_id, pin, entry);
 }
 
+static struct {
+	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
+} mp_ioapic_routing[MAX_IO_APICS];
+
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id, pin, idx, irq;
+	int apic_id = 0, pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
-	int cpu = boot_cpu_id;
+	int node = cpu_to_node(boot_cpu_id);
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
-		for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic) {
+		apic_id = mp_find_ioapic(0);
+		if (apic_id < 0)
+			apic_id = 0;
+	}
+#endif
 
-			idx = find_irq_entry(apic_id, pin, mp_INT);
-			if (idx == -1) {
-				if (!notcon) {
-					notcon = 1;
-					apic_printk(APIC_VERBOSE,
-						KERN_DEBUG " %d-%d",
-						mp_ioapics[apic_id].apicid, pin);
-				} else
-					apic_printk(APIC_VERBOSE, " %d-%d",
-						mp_ioapics[apic_id].apicid, pin);
-				continue;
-			}
-			if (notcon) {
+	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+		idx = find_irq_entry(apic_id, pin, mp_INT);
+		if (idx == -1) {
+			if (!notcon) {
+				notcon = 1;
 				apic_printk(APIC_VERBOSE,
-					" (apicid-pin) not connected\n");
-				notcon = 0;
-			}
-
-			irq = pin_2_irq(idx, apic_id, pin);
+					KERN_DEBUG " %d-%d",
+					mp_ioapics[apic_id].apicid, pin);
+			} else
+				apic_printk(APIC_VERBOSE, " %d-%d",
+					mp_ioapics[apic_id].apicid, pin);
+			continue;
+		}
+		if (notcon) {
+			apic_printk(APIC_VERBOSE,
+				" (apicid-pin) not connected\n");
+			notcon = 0;
+		}
 
-			/*
-			 * Skip the timer IRQ if there's a quirk handler
-			 * installed and if it returns 1:
-			 */
-			if (apic->multi_timer_check &&
-					apic->multi_timer_check(apic_id, irq))
-				continue;
+		irq = pin_2_irq(idx, apic_id, pin);
 
-			desc = irq_to_desc_alloc_cpu(irq, cpu);
-			if (!desc) {
-				printk(KERN_INFO "can not get irq_desc for %d\n", irq);
-				continue;
-			}
-			cfg = desc->chip_data;
-			add_pin_to_irq_cpu(cfg, cpu, apic_id, pin);
+		/*
+		 * Skip the timer IRQ if there's a quirk handler
+		 * installed and if it returns 1:
+		 */
+		if (apic->multi_timer_check &&
+				apic->multi_timer_check(apic_id, irq))
+			continue;
 
-			setup_IO_APIC_irq(apic_id, pin, irq, desc,
-					irq_trigger(idx), irq_polarity(idx));
+		desc = irq_to_desc_alloc_node(irq, node);
+		if (!desc) {
+			printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+			continue;
 		}
+		cfg = desc->chip_data;
+		add_pin_to_irq_node(cfg, node, apic_id, pin);
+		/*
+		 * don't mark it in pin_programmed, so later acpi could
+		 * set it correctly when irq < 16
+		 */
+		setup_IO_APIC_irq(apic_id, pin, irq, desc,
+				irq_trigger(idx), irq_polarity(idx));
 	}
 
 	if (notcon)
@@ -1846,36 +1716,30 @@
 	return;
 }
 
-__apicdebuginit(void) print_APIC_bitfield(int base)
+__apicdebuginit(void) print_APIC_field(int base)
 {
-	unsigned int v;
-	int i, j;
+	int i;
 
 	if (apic_verbosity == APIC_QUIET)
 		return;
 
-	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
-	for (i = 0; i < 8; i++) {
-		v = apic_read(base + i*0x10);
-		for (j = 0; j < 32; j++) {
-			if (v & (1<<j))
-				printk("1");
-			else
-				printk("0");
-		}
-		printk("\n");
-	}
+	printk(KERN_DEBUG);
+
+	for (i = 0; i < 8; i++)
+		printk(KERN_CONT "%08x", apic_read(base + i*0x10));
+
+	printk(KERN_CONT "\n");
 }
 
 __apicdebuginit(void) print_local_APIC(void *dummy)
 {
-	unsigned int v, ver, maxlvt;
+	unsigned int i, v, ver, maxlvt;
 	u64 icr;
 
 	if (apic_verbosity == APIC_QUIET)
 		return;
 
-	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+	printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
 		smp_processor_id(), hard_smp_processor_id());
 	v = apic_read(APIC_ID);
 	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
@@ -1916,11 +1780,11 @@
 	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
 
 	printk(KERN_DEBUG "... APIC ISR field:\n");
-	print_APIC_bitfield(APIC_ISR);
+	print_APIC_field(APIC_ISR);
 	printk(KERN_DEBUG "... APIC TMR field:\n");
-	print_APIC_bitfield(APIC_TMR);
+	print_APIC_field(APIC_TMR);
 	printk(KERN_DEBUG "... APIC IRR field:\n");
-	print_APIC_bitfield(APIC_IRR);
+	print_APIC_field(APIC_IRR);
 
 	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
 		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
@@ -1957,6 +1821,18 @@
 	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
 	v = apic_read(APIC_TDCR);
 	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
+
+	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
+		v = apic_read(APIC_EFEAT);
+		maxlvt = (v >> 16) & 0xff;
+		printk(KERN_DEBUG "... APIC EFEAT: %08x\n", v);
+		v = apic_read(APIC_ECTRL);
+		printk(KERN_DEBUG "... APIC ECTRL: %08x\n", v);
+		for (i = 0; i < maxlvt; i++) {
+			v = apic_read(APIC_EILVTn(i));
+			printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v);
+		}
+	}
 	printk("\n");
 }
 
@@ -2005,6 +1881,11 @@
 __apicdebuginit(int) print_all_ICs(void)
 {
 	print_PIC();
+
+	/* don't print out if apic is not there */
+	if (!cpu_has_apic || disable_apic)
+		return 0;
+
 	print_all_local_APICs();
 	print_IO_APIC();
 
@@ -2120,7 +2001,9 @@
 	/*
 	 * Use virtual wire A mode when interrupt remapping is enabled.
 	 */
-	disconnect_bsp_APIC(!intr_remapping_enabled && ioapic_i8259.pin != -1);
+	if (cpu_has_apic)
+		disconnect_bsp_APIC(!intr_remapping_enabled &&
+				ioapic_i8259.pin != -1);
 }
 
 #ifdef CONFIG_X86_32
@@ -2360,6 +2243,118 @@
  */
 
 #ifdef CONFIG_SMP
+static void send_cleanup_vector(struct irq_cfg *cfg)
+{
+	cpumask_var_t cleanup_mask;
+
+	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+		unsigned int i;
+		cfg->move_cleanup_count = 0;
+		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+			cfg->move_cleanup_count++;
+		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+	} else {
+		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+		cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		free_cpumask_var(cleanup_mask);
+	}
+	cfg->move_in_progress = 0;
+}
+
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+{
+	int apic, pin;
+	struct irq_pin_list *entry;
+	u8 vector = cfg->vector;
+
+	entry = cfg->irq_2_pin;
+	for (;;) {
+		unsigned int reg;
+
+		if (!entry)
+			break;
+
+		apic = entry->apic;
+		pin = entry->pin;
+		/*
+		 * With interrupt-remapping, destination information comes
+		 * from interrupt-remapping table entry.
+		 */
+		if (!irq_remapped(irq))
+			io_apic_write(apic, 0x11 + pin*2, dest);
+		reg = io_apic_read(apic, 0x10 + pin*2);
+		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+		reg |= vector;
+		io_apic_modify(apic, 0x10 + pin*2, reg);
+		if (!entry->next)
+			break;
+		entry = entry->next;
+	}
+}
+
+static int
+assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
+
+/*
+ * Either sets desc->affinity to a valid value, and returns
+ * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
+ * leaves desc->affinity untouched.
+ */
+static unsigned int
+set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+{
+	struct irq_cfg *cfg;
+	unsigned int irq;
+
+	if (!cpumask_intersects(mask, cpu_online_mask))
+		return BAD_APICID;
+
+	irq = desc->irq;
+	cfg = desc->chip_data;
+	if (assign_irq_vector(irq, cfg, mask))
+		return BAD_APICID;
+
+	cpumask_copy(desc->affinity, mask);
+
+	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+}
+
+static int
+set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+{
+	struct irq_cfg *cfg;
+	unsigned long flags;
+	unsigned int dest;
+	unsigned int irq;
+	int ret = -1;
+
+	irq = desc->irq;
+	cfg = desc->chip_data;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	dest = set_desc_affinity(desc, mask);
+	if (dest != BAD_APICID) {
+		/* Only the high 8 bits are valid. */
+		dest = SET_APIC_LOGICAL_ID(dest);
+		__target_IO_APIC_irq(irq, dest, cfg);
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return ret;
+}
+
+static int
+set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
+{
+	struct irq_desc *desc;
+
+	desc = irq_to_desc(irq);
+
+	return set_ioapic_affinity_irq_desc(desc, mask);
+}
 
 #ifdef CONFIG_INTR_REMAP
 
@@ -2374,26 +2369,25 @@
  * Real vector that is used for interrupting cpu will be coming from
  * the interrupt-remapping table entry.
  */
-static void
+static int
 migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
 {
 	struct irq_cfg *cfg;
 	struct irte irte;
 	unsigned int dest;
 	unsigned int irq;
+	int ret = -1;
 
 	if (!cpumask_intersects(mask, cpu_online_mask))
-		return;
+		return ret;
 
 	irq = desc->irq;
 	if (get_irte(irq, &irte))
-		return;
+		return ret;
 
 	cfg = desc->chip_data;
 	if (assign_irq_vector(irq, cfg, mask))
-		return;
-
-	set_extra_move_desc(desc, mask);
+		return ret;
 
 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
 
@@ -2409,27 +2403,30 @@
 		send_cleanup_vector(cfg);
 
 	cpumask_copy(desc->affinity, mask);
+
+	return 0;
 }
 
 /*
  * Migrates the IRQ destination in the process context.
  */
-static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
 					    const struct cpumask *mask)
 {
-	migrate_ioapic_irq_desc(desc, mask);
+	return migrate_ioapic_irq_desc(desc, mask);
 }
-static void set_ir_ioapic_affinity_irq(unsigned int irq,
+static int set_ir_ioapic_affinity_irq(unsigned int irq,
 				       const struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	set_ir_ioapic_affinity_irq_desc(desc, mask);
+	return set_ir_ioapic_affinity_irq_desc(desc, mask);
 }
 #else
-static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
 						   const struct cpumask *mask)
 {
+	return 0;
 }
 #endif
 
@@ -2491,86 +2488,19 @@
 	struct irq_cfg *cfg = desc->chip_data;
 	unsigned vector, me;
 
-	if (likely(!cfg->move_in_progress)) {
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
-		if (likely(!cfg->move_desc_pending))
-			return;
-
-		/* domain has not changed, but affinity did */
-		me = smp_processor_id();
-		if (cpumask_test_cpu(me, desc->affinity)) {
-			*descp = desc = move_irq_desc(desc, me);
-			/* get the new one */
-			cfg = desc->chip_data;
-			cfg->move_desc_pending = 0;
-		}
-#endif
+	if (likely(!cfg->move_in_progress))
 		return;
-	}
 
 	vector = ~get_irq_regs()->orig_ax;
 	me = smp_processor_id();
 
-	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
-		*descp = desc = move_irq_desc(desc, me);
-		/* get the new one */
-		cfg = desc->chip_data;
-#endif
+	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
 		send_cleanup_vector(cfg);
-	}
 }
 #else
 static inline void irq_complete_move(struct irq_desc **descp) {}
 #endif
 
-static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
-{
-	int apic, pin;
-	struct irq_pin_list *entry;
-
-	entry = cfg->irq_2_pin;
-	for (;;) {
-
-		if (!entry)
-			break;
-
-		apic = entry->apic;
-		pin = entry->pin;
-		io_apic_eoi(apic, pin);
-		entry = entry->next;
-	}
-}
-
-static void
-eoi_ioapic_irq(struct irq_desc *desc)
-{
-	struct irq_cfg *cfg;
-	unsigned long flags;
-	unsigned int irq;
-
-	irq = desc->irq;
-	cfg = desc->chip_data;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__eoi_ioapic_irq(irq, cfg);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-#ifdef CONFIG_X86_X2APIC
-static void ack_x2apic_level(unsigned int irq)
-{
-	struct irq_desc *desc = irq_to_desc(irq);
-	ack_x2APIC_irq();
-	eoi_ioapic_irq(desc);
-}
-
-static void ack_x2apic_edge(unsigned int irq)
-{
-	ack_x2APIC_irq();
-}
-#endif
-
 static void ack_apic_edge(unsigned int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
@@ -2634,9 +2564,6 @@
 	 */
 	ack_APIC_irq();
 
-	if (irq_remapped(irq))
-		eoi_ioapic_irq(desc);
-
 	/* Now we can move and renable the irq */
 	if (unlikely(do_unmask_irq)) {
 		/* Only migrate the irq if the ack has been received.
@@ -2683,22 +2610,50 @@
 }
 
 #ifdef CONFIG_INTR_REMAP
+static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+	int apic, pin;
+	struct irq_pin_list *entry;
+
+	entry = cfg->irq_2_pin;
+	for (;;) {
+
+		if (!entry)
+			break;
+
+		apic = entry->apic;
+		pin = entry->pin;
+		io_apic_eoi(apic, pin);
+		entry = entry->next;
+	}
+}
+
+static void
+eoi_ioapic_irq(struct irq_desc *desc)
+{
+	struct irq_cfg *cfg;
+	unsigned long flags;
+	unsigned int irq;
+
+	irq = desc->irq;
+	cfg = desc->chip_data;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__eoi_ioapic_irq(irq, cfg);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
 static void ir_ack_apic_edge(unsigned int irq)
 {
-#ifdef CONFIG_X86_X2APIC
-       if (x2apic_enabled())
-               return ack_x2apic_edge(irq);
-#endif
-       return ack_apic_edge(irq);
+	ack_APIC_irq();
 }
 
 static void ir_ack_apic_level(unsigned int irq)
 {
-#ifdef CONFIG_X86_X2APIC
-       if (x2apic_enabled())
-               return ack_x2apic_level(irq);
-#endif
-       return ack_apic_level(irq);
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	ack_APIC_irq();
+	eoi_ioapic_irq(desc);
 }
 #endif /* CONFIG_INTR_REMAP */
 
@@ -2903,7 +2858,7 @@
 {
 	struct irq_desc *desc = irq_to_desc(0);
 	struct irq_cfg *cfg = desc->chip_data;
-	int cpu = boot_cpu_id;
+	int node = cpu_to_node(boot_cpu_id);
 	int apic1, pin1, apic2, pin2;
 	unsigned long flags;
 	int no_pin1 = 0;
@@ -2969,7 +2924,7 @@
 		 * Ok, does IRQ0 through the IOAPIC work?
 		 */
 		if (no_pin1) {
-			add_pin_to_irq_cpu(cfg, cpu, apic1, pin1);
+			add_pin_to_irq_node(cfg, node, apic1, pin1);
 			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
 		} else {
 			/* for edge trigger, setup_IO_APIC_irq already
@@ -3006,7 +2961,7 @@
 		/*
 		 * legacy devices should be connected to IO APIC #0
 		 */
-		replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2);
+		replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
 		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
 		enable_8259A_irq(0);
 		if (timer_irq_works()) {
@@ -3218,14 +3173,13 @@
 /*
  * Dynamic irq allocate and deallocation
  */
-unsigned int create_irq_nr(unsigned int irq_want)
+unsigned int create_irq_nr(unsigned int irq_want, int node)
 {
 	/* Allocate an unused irq */
 	unsigned int irq;
 	unsigned int new;
 	unsigned long flags;
 	struct irq_cfg *cfg_new = NULL;
-	int cpu = boot_cpu_id;
 	struct irq_desc *desc_new = NULL;
 
 	irq = 0;
@@ -3234,7 +3188,7 @@
 
 	spin_lock_irqsave(&vector_lock, flags);
 	for (new = irq_want; new < nr_irqs; new++) {
-		desc_new = irq_to_desc_alloc_cpu(new, cpu);
+		desc_new = irq_to_desc_alloc_node(new, node);
 		if (!desc_new) {
 			printk(KERN_INFO "can not get irq_desc for %d\n", new);
 			continue;
@@ -3243,6 +3197,9 @@
 
 		if (cfg_new->vector != 0)
 			continue;
+
+		desc_new = move_irq_desc(desc_new, node);
+
 		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
 			irq = new;
 		break;
@@ -3260,11 +3217,12 @@
 
 int create_irq(void)
 {
+	int node = cpu_to_node(boot_cpu_id);
 	unsigned int irq_want;
 	int irq;
 
 	irq_want = nr_irqs_gsi;
-	irq = create_irq_nr(irq_want);
+	irq = create_irq_nr(irq_want, node);
 
 	if (irq == 0)
 		irq = -1;
@@ -3329,6 +3287,9 @@
 		irte.vector = cfg->vector;
 		irte.dest_id = IRTE_DEST(dest);
 
+		/* Set source-id of interrupt request */
+		set_msi_sid(&irte, pdev);
+
 		modify_irte(irq, &irte);
 
 		msg->address_hi = MSI_ADDR_BASE_HI;
@@ -3366,7 +3327,7 @@
 }
 
 #ifdef CONFIG_SMP
-static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	struct irq_cfg *cfg;
@@ -3375,7 +3336,7 @@
 
 	dest = set_desc_affinity(desc, mask);
 	if (dest == BAD_APICID)
-		return;
+		return -1;
 
 	cfg = desc->chip_data;
 
@@ -3387,13 +3348,15 @@
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	write_msi_msg_desc(desc, &msg);
+
+	return 0;
 }
 #ifdef CONFIG_INTR_REMAP
 /*
  * Migrate the MSI irq to another cpumask. This migration is
  * done in the process context using interrupt-remapping hardware.
  */
-static void
+static int
 ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
@@ -3402,11 +3365,11 @@
 	struct irte irte;
 
 	if (get_irte(irq, &irte))
-		return;
+		return -1;
 
 	dest = set_desc_affinity(desc, mask);
 	if (dest == BAD_APICID)
-		return;
+		return -1;
 
 	irte.vector = cfg->vector;
 	irte.dest_id = IRTE_DEST(dest);
@@ -3423,6 +3386,8 @@
 	 */
 	if (cfg->move_in_progress)
 		send_cleanup_vector(cfg);
+
+	return 0;
 }
 
 #endif
@@ -3518,15 +3483,17 @@
 	unsigned int irq_want;
 	struct intel_iommu *iommu = NULL;
 	int index = 0;
+	int node;
 
 	/* x86 doesn't support multiple MSI yet */
 	if (type == PCI_CAP_ID_MSI && nvec > 1)
 		return 1;
 
+	node = dev_to_node(&dev->dev);
 	irq_want = nr_irqs_gsi;
 	sub_handle = 0;
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = create_irq_nr(irq_want);
+		irq = create_irq_nr(irq_want, node);
 		if (irq == 0)
 			return -1;
 		irq_want = irq + 1;
@@ -3576,7 +3543,7 @@
 
 #if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
 #ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	struct irq_cfg *cfg;
@@ -3585,7 +3552,7 @@
 
 	dest = set_desc_affinity(desc, mask);
 	if (dest == BAD_APICID)
-		return;
+		return -1;
 
 	cfg = desc->chip_data;
 
@@ -3597,11 +3564,13 @@
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	dmar_msi_write(irq, &msg);
+
+	return 0;
 }
 
 #endif /* CONFIG_SMP */
 
-struct irq_chip dmar_msi_type = {
+static struct irq_chip dmar_msi_type = {
 	.name = "DMAR_MSI",
 	.unmask = dmar_msi_unmask,
 	.mask = dmar_msi_mask,
@@ -3630,7 +3599,7 @@
 #ifdef CONFIG_HPET_TIMER
 
 #ifdef CONFIG_SMP
-static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	struct irq_cfg *cfg;
@@ -3639,7 +3608,7 @@
 
 	dest = set_desc_affinity(desc, mask);
 	if (dest == BAD_APICID)
-		return;
+		return -1;
 
 	cfg = desc->chip_data;
 
@@ -3651,6 +3620,8 @@
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	hpet_msi_write(irq, &msg);
+
+	return 0;
 }
 
 #endif /* CONFIG_SMP */
@@ -3707,7 +3678,7 @@
 	write_ht_irq_msg(irq, &msg);
 }
 
-static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	struct irq_cfg *cfg;
@@ -3715,11 +3686,13 @@
 
 	dest = set_desc_affinity(desc, mask);
 	if (dest == BAD_APICID)
-		return;
+		return -1;
 
 	cfg = desc->chip_data;
 
 	target_ht_irq(irq, dest, cfg->vector);
+
+	return 0;
 }
 
 #endif
@@ -3794,6 +3767,8 @@
 	unsigned long flags;
 	int err;
 
+	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
 	cfg = irq_cfg(irq);
 
 	err = assign_irq_vector(irq, cfg, eligible_cpu);
@@ -3807,19 +3782,20 @@
 
 	mmr_value = 0;
 	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
-	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
-
-	entry->vector = cfg->vector;
-	entry->delivery_mode = apic->irq_delivery_mode;
-	entry->dest_mode = apic->irq_dest_mode;
-	entry->polarity = 0;
-	entry->trigger = 0;
-	entry->mask = 0;
-	entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
+	entry->vector		= cfg->vector;
+	entry->delivery_mode	= apic->irq_delivery_mode;
+	entry->dest_mode	= apic->irq_dest_mode;
+	entry->polarity		= 0;
+	entry->trigger		= 0;
+	entry->mask		= 0;
+	entry->dest		= apic->cpu_mask_to_apicid(eligible_cpu);
 
 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
 
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
 	return irq;
 }
 
@@ -3833,10 +3809,10 @@
 	struct uv_IO_APIC_route_entry *entry;
 	int mmr_pnode;
 
+	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
 	mmr_value = 0;
 	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
-	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
-
 	entry->mask = 1;
 
 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
@@ -3900,6 +3876,71 @@
 }
 #endif
 
+static int __io_apic_set_pci_routing(struct device *dev, int irq,
+				struct io_apic_irq_attr *irq_attr)
+{
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+	int node;
+	int ioapic, pin;
+	int trigger, polarity;
+
+	ioapic = irq_attr->ioapic;
+	if (!IO_APIC_IRQ(irq)) {
+		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+			ioapic);
+		return -EINVAL;
+	}
+
+	if (dev)
+		node = dev_to_node(dev);
+	else
+		node = cpu_to_node(boot_cpu_id);
+
+	desc = irq_to_desc_alloc_node(irq, node);
+	if (!desc) {
+		printk(KERN_INFO "can not get irq_desc %d\n", irq);
+		return 0;
+	}
+
+	pin = irq_attr->ioapic_pin;
+	trigger = irq_attr->trigger;
+	polarity = irq_attr->polarity;
+
+	/*
+	 * IRQs < 16 are already in the irq_2_pin[] map
+	 */
+	if (irq >= NR_IRQS_LEGACY) {
+		cfg = desc->chip_data;
+		add_pin_to_irq_node(cfg, node, ioapic, pin);
+	}
+
+	setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
+
+	return 0;
+}
+
+int io_apic_set_pci_routing(struct device *dev, int irq,
+				struct io_apic_irq_attr *irq_attr)
+{
+	int ioapic, pin;
+	/*
+	 * Avoid pin reprogramming.  PRTs typically include entries
+	 * with redundant pin->gsi mappings (but unique PCI devices);
+	 * we only program the IOAPIC on the first.
+	 */
+	ioapic = irq_attr->ioapic;
+	pin = irq_attr->ioapic_pin;
+	if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
+		pr_debug("Pin %d-%d already programmed\n",
+			 mp_ioapics[ioapic].apicid, pin);
+		return 0;
+	}
+	set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
+
+	return __io_apic_set_pci_routing(dev, irq, irq_attr);
+}
+
 /* --------------------------------------------------------------------------
                           ACPI-based IOAPIC Configuration
    -------------------------------------------------------------------------- */
@@ -3980,6 +4021,7 @@
 
 	return apic_id;
 }
+#endif
 
 int __init io_apic_get_version(int ioapic)
 {
@@ -3992,39 +4034,6 @@
 
 	return reg_01.bits.version;
 }
-#endif
-
-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
-{
-	struct irq_desc *desc;
-	struct irq_cfg *cfg;
-	int cpu = boot_cpu_id;
-
-	if (!IO_APIC_IRQ(irq)) {
-		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
-			ioapic);
-		return -EINVAL;
-	}
-
-	desc = irq_to_desc_alloc_cpu(irq, cpu);
-	if (!desc) {
-		printk(KERN_INFO "can not get irq_desc %d\n", irq);
-		return 0;
-	}
-
-	/*
-	 * IRQs < 16 are already in the irq_2_pin[] map
-	 */
-	if (irq >= NR_IRQS_LEGACY) {
-		cfg = desc->chip_data;
-		add_pin_to_irq_cpu(cfg, cpu, ioapic, pin);
-	}
-
-	setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity);
-
-	return 0;
-}
-
 
 int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
 {
@@ -4055,51 +4064,44 @@
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic, irq, irq_entry;
+	int pin, ioapic = 0, irq, irq_entry;
 	struct irq_desc *desc;
-	struct irq_cfg *cfg;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
-		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
-			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
-			if (irq_entry == -1)
-				continue;
-			irq = pin_2_irq(irq_entry, ioapic, pin);
-
-			/* setup_IO_APIC_irqs could fail to get vector for some device
-			 * when you have too many devices, because at that time only boot
-			 * cpu is online.
-			 */
-			desc = irq_to_desc(irq);
-			cfg = desc->chip_data;
-			if (!cfg->vector) {
-				setup_IO_APIC_irq(ioapic, pin, irq, desc,
-						  irq_trigger(irq_entry),
-						  irq_polarity(irq_entry));
-				continue;
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled && acpi_ioapic) {
+		ioapic = mp_find_ioapic(0);
+		if (ioapic < 0)
+			ioapic = 0;
+	}
+#endif
 
-			}
+	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+		if (irq_entry == -1)
+			continue;
+		irq = pin_2_irq(irq_entry, ioapic, pin);
 
-			/*
-			 * Honour affinities which have been set in early boot
-			 */
-			if (desc->status &
-			    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
-				mask = desc->affinity;
-			else
-				mask = apic->target_cpus();
+		desc = irq_to_desc(irq);
 
-			if (intr_remapping_enabled)
-				set_ir_ioapic_affinity_irq_desc(desc, mask);
-			else
-				set_ioapic_affinity_irq_desc(desc, mask);
-		}
+		/*
+		 * Honour affinities which have been set in early boot
+		 */
+		if (desc->status &
+		    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+			mask = desc->affinity;
+		else
+			mask = apic->target_cpus();
 
+		if (intr_remapping_enabled)
+			set_ir_ioapic_affinity_irq_desc(desc, mask);
+		else
+			set_ioapic_affinity_irq_desc(desc, mask);
 	}
+
 }
 #endif
 
@@ -4182,28 +4184,20 @@
 	}
 }
 
-static int __init ioapic_insert_resources(void)
+void __init ioapic_insert_resources(void)
 {
 	int i;
 	struct resource *r = ioapic_resources;
 
 	if (!r) {
-		if (nr_ioapics > 0) {
+		if (nr_ioapics > 0)
 			printk(KERN_ERR
 				"IO APIC resources couldn't be allocated.\n");
-			return -1;
-		}
-		return 0;
+		return;
 	}
 
 	for (i = 0; i < nr_ioapics; i++) {
 		insert_resource(&iomem_resource, r);
 		r++;
 	}
-
-	return 0;
 }
-
-/* Insert the IO APIC resources after PCI initialization has occured to handle
- * IO APICS that are mapped in on a BAR in PCI space. */
-late_initcall(ioapic_insert_resources);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/ipi.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/ipi.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/ipi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/ipi.c	2009-09-09 18:13:59.000000000 -0400
@@ -106,6 +106,9 @@
 	unsigned long mask = cpumask_bits(cpumask)[0];
 	unsigned long flags;
 
+	if (WARN_ONCE(!mask, "empty IPI mask"))
+		return;
+
 	local_irq_save(flags);
 	WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
 	__default_send_IPI_dest_field(mask, vector, apic->dest_logical);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/nmi.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/nmi.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/nmi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/nmi.c	2009-09-09 18:13:59.000000000 -0400
@@ -66,7 +66,7 @@
 
 static inline int mce_in_progress(void)
 {
-#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
+#if defined(CONFIG_X86_NEW_MCE)
 	return atomic_read(&mce_entry) > 0;
 #endif
 	return 0;
@@ -104,7 +104,7 @@
 }
 #endif
 
-static void report_broken_nmi(int cpu, int *prev_nmi_count)
+static void report_broken_nmi(int cpu, unsigned int *prev_nmi_count)
 {
 	printk(KERN_CONT "\n");
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/numaq_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/numaq_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/numaq_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/numaq_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -493,7 +493,8 @@
 		(u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD);
 }
 
-struct apic apic_numaq = {
+/* Use __refdata to keep false positive warning calm.	*/
+struct apic __refdata apic_numaq = {
 
 	.name				= "NUMAQ",
 	.probe				= probe_numaq,
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/probe_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/probe_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/probe_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/probe_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,23 +20,12 @@
 #include <asm/apic.h>
 #include <asm/setup.h>
 
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <asm/mpspec.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
 #include <linux/smp.h>
-#include <linux/init.h>
 #include <asm/ipi.h>
 
-#include <linux/smp.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/acpi.h>
 #include <asm/e820.h>
-#include <asm/setup.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
 #define DEFAULT_SEND_IPI	(1)
@@ -160,7 +149,6 @@
 extern struct apic apic_bigsmp;
 extern struct apic apic_es7000;
 extern struct apic apic_es7000_cluster;
-extern struct apic apic_default;
 
 struct apic *apic = &apic_default;
 EXPORT_SYMBOL_GPL(apic);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/probe_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/probe_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/probe_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/probe_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,13 +44,18 @@
 	NULL,
 };
 
+static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
+{
+	return hard_smp_processor_id() >> index_msb;
+}
+
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
  */
 void __init default_setup_apic_routing(void)
 {
 #ifdef CONFIG_X86_X2APIC
-	if (x2apic && (apic != &apic_x2apic_phys &&
+	if (x2apic_mode && (apic != &apic_x2apic_phys &&
 #ifdef CONFIG_X86_UV
 		       apic != &apic_x2apic_uv_x &&
 #endif
@@ -69,6 +74,11 @@
 		printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
 	}
 
+	if (is_vsmp_box()) {
+		/* need to update phys_pkg_id */
+		apic->phys_pkg_id = apicid_phys_pkg_id;
+	}
+
 	/*
 	 * Now that apic routing model is selected, configure the
 	 * fault handling for intr remapping.
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/summit_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/summit_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/summit_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/summit_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,7 +44,6 @@
 #include <asm/ipi.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/init.h>
 #include <linux/gfp.h>
 #include <linux/smp.h>
 
@@ -173,13 +172,6 @@
 		rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
 }
 
-
-/* In clustered mode, the high nibble of APIC ID is a cluster number.
- * The low nibble is a 4-bit bitmap. */
-#define XAPIC_DEST_CPUS_SHIFT	4
-#define XAPIC_DEST_CPUS_MASK	((1u << XAPIC_DEST_CPUS_SHIFT) - 1)
-#define XAPIC_DEST_CLUSTER_MASK	(XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT)
-
 #define SUMMIT_APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
 
 static const struct cpumask *summit_target_cpus(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/x2apic_cluster.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/x2apic_cluster.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,18 +10,20 @@
 #include <asm/apic.h>
 #include <asm/ipi.h>
 
-DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
+static DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
 
 static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
 	return x2apic_enabled();
 }
 
-/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
-
+/*
+ * need to use more than cpu 0, because we need more vectors when
+ * MSI-X are used.
+ */
 static const struct cpumask *x2apic_target_cpus(void)
 {
-	return cpumask_of(0);
+	return cpu_online_mask;
 }
 
 /*
@@ -170,7 +172,7 @@
 
 static int x2apic_cluster_phys_pkg_id(int initial_apicid, int index_msb)
 {
-	return current_cpu_data.initial_apicid >> index_msb;
+	return initial_apicid >> index_msb;
 }
 
 static void x2apic_send_IPI_self(int vector)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/x2apic_phys.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/x2apic_phys.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/x2apic_phys.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/x2apic_phys.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,11 +27,13 @@
 		return 0;
 }
 
-/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
-
+/*
+ * need to use more than cpu 0, because we need more vectors when
+ * MSI-X are used.
+ */
 static const struct cpumask *x2apic_target_cpus(void)
 {
-	return cpumask_of(0);
+	return cpu_online_mask;
 }
 
 static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
@@ -162,7 +164,7 @@
 
 static int x2apic_phys_pkg_id(int initial_apicid, int index_msb)
 {
-	return current_cpu_data.initial_apicid >> index_msb;
+	return initial_apicid >> index_msb;
 }
 
 static void x2apic_send_IPI_self(int vector)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apic/x2apic_uv_x.c linux-libre-2.6.31-gnu/arch/x86/kernel/apic/x2apic_uv_x.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 	return node_id.s.node_id;
 }
 
-static int uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
 	if (!strcmp(oem_id, "SGI")) {
 		if (!strcmp(oem_table_id, "UVL"))
@@ -105,7 +105,7 @@
 	cpumask_set_cpu(cpu, retmask);
 }
 
-static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
+static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
 {
 #ifdef CONFIG_SMP
 	unsigned long val;
@@ -253,7 +253,7 @@
 	apic_write(APIC_SELF_IPI, vector);
 }
 
-struct apic apic_x2apic_uv_x = {
+struct apic __refdata apic_x2apic_uv_x = {
 
 	.name				= "UV large system",
 	.probe				= NULL,
@@ -261,7 +261,7 @@
 	.apic_id_registered		= uv_apic_id_registered,
 
 	.irq_delivery_mode		= dest_Fixed,
-	.irq_dest_mode			= 1, /* logical */
+	.irq_dest_mode			= 0, /* physical */
 
 	.target_cpus			= uv_target_cpus,
 	.disable_esr			= 0,
@@ -362,12 +362,6 @@
 	BUG();
 }
 
-static __init void map_low_mmrs(void)
-{
-	init_extra_mapping_uc(UV_GLOBAL_MMR32_BASE, UV_GLOBAL_MMR32_SIZE);
-	init_extra_mapping_uc(UV_LOCAL_MMR_BASE, UV_LOCAL_MMR_SIZE);
-}
-
 enum map_type {map_wb, map_uc};
 
 static __init void map_high(char *id, unsigned long base, int shift,
@@ -395,26 +389,6 @@
 		map_high("GRU", gru.s.base, shift, max_pnode, map_wb);
 }
 
-static __init void map_config_high(int max_pnode)
-{
-	union uvh_rh_gam_cfg_overlay_config_mmr_u cfg;
-	int shift = UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_BASE_SHFT;
-
-	cfg.v = uv_read_local_mmr(UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR);
-	if (cfg.s.enable)
-		map_high("CONFIG", cfg.s.base, shift, max_pnode, map_uc);
-}
-
-static __init void map_mmr_high(int max_pnode)
-{
-	union uvh_rh_gam_mmr_overlay_config_mmr_u mmr;
-	int shift = UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT;
-
-	mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR);
-	if (mmr.s.enable)
-		map_high("MMR", mmr.s.base, shift, max_pnode, map_uc);
-}
-
 static __init void map_mmioh_high(int max_pnode)
 {
 	union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh;
@@ -463,7 +437,7 @@
 	uv_set_scir_bits(bits);
 
 	/* enable next timer period */
-	mod_timer(timer, jiffies + SCIR_CPU_HB_INTERVAL);
+	mod_timer_pinned(timer, jiffies + SCIR_CPU_HB_INTERVAL);
 }
 
 static void __cpuinit uv_heartbeat_enable(int cpu)
@@ -562,18 +536,23 @@
 	union uvh_node_id_u node_id;
 	unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size;
 	int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val;
-	int max_pnode = 0;
+	int gnode_extra, max_pnode = 0;
 	unsigned long mmr_base, present, paddr;
 	unsigned short pnode_mask;
 
-	map_low_mmrs();
-
 	m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG);
 	m_val = m_n_config.s.m_skt;
 	n_val = m_n_config.s.n_skt;
 	mmr_base =
 	    uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
 	    ~UV_MMR_ENABLE;
+	pnode_mask = (1 << n_val) - 1;
+	node_id.v = uv_read_local_mmr(UVH_NODE_ID);
+	gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1;
+	gnode_upper = ((unsigned long)gnode_extra  << m_val);
+	printk(KERN_DEBUG "UV: N %d, M %d, gnode_upper 0x%lx, gnode_extra 0x%x\n",
+			n_val, m_val, gnode_upper, gnode_extra);
+
 	printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);
 
 	for(i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++)
@@ -583,15 +562,20 @@
 
 	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
 	uv_blade_info = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!uv_blade_info);
+	for (blade = 0; blade < uv_num_possible_blades(); blade++)
+		uv_blade_info[blade].memory_nid = -1;
 
 	get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
 
 	bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
 	uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!uv_node_to_blade);
 	memset(uv_node_to_blade, 255, bytes);
 
 	bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
 	uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!uv_cpu_to_blade);
 	memset(uv_cpu_to_blade, 255, bytes);
 
 	blade = 0;
@@ -607,11 +591,6 @@
 		}
 	}
 
-	pnode_mask = (1 << n_val) - 1;
-	node_id.v = uv_read_local_mmr(UVH_NODE_ID);
-	gnode_upper = (((unsigned long)node_id.s.node_id) &
-		       ~((1 << n_val) - 1)) << m_val;
-
 	uv_bios_init();
 	uv_bios_get_sn_info(0, &uv_type, &sn_partition_id,
 			    &sn_coherency_id, &sn_region_size);
@@ -624,6 +603,9 @@
 		lcpu = uv_blade_info[blade].nr_possible_cpus;
 		uv_blade_info[blade].nr_possible_cpus++;
 
+		/* Any node on the blade, else will contain -1. */
+		uv_blade_info[blade].memory_nid = nid;
+
 		uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base;
 		uv_cpu_hub_info(cpu)->lowmem_remap_top = lowmem_redir_size;
 		uv_cpu_hub_info(cpu)->m_val = m_val;
@@ -634,6 +616,7 @@
 		uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
 		uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1;
 		uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
+		uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;
 		uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
 		uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id;
 		uv_cpu_hub_info(cpu)->scir.offset = SCIR_LOCAL_MMR_BASE + lcpu;
@@ -656,11 +639,10 @@
 		pnode = (paddr >> m_val) & pnode_mask;
 		blade = boot_pnode_to_blade(pnode);
 		uv_node_to_blade[nid] = blade;
+		max_pnode = max(pnode, max_pnode);
 	}
 
 	map_gru_high(max_pnode);
-	map_mmr_high(max_pnode);
-	map_config_high(max_pnode);
 	map_mmioh_high(max_pnode);
 
 	uv_cpu_init();
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/apm_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/apm_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/apm_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/apm_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -811,7 +811,7 @@
 	u8 ret = 0;
 	int idled = 0;
 	int polling;
-	int err;
+	int err = 0;
 
 	polling = !!(current_thread_info()->status & TS_POLLING);
 	if (polling) {
@@ -1233,9 +1233,9 @@
 	int err;
 	struct apm_user	*as;
 
-	device_suspend(PMSG_SUSPEND);
+	dpm_suspend_start(PMSG_SUSPEND);
 
-	device_power_down(PMSG_SUSPEND);
+	dpm_suspend_noirq(PMSG_SUSPEND);
 
 	local_irq_disable();
 	sysdev_suspend(PMSG_SUSPEND);
@@ -1259,9 +1259,9 @@
 	sysdev_resume();
 	local_irq_enable();
 
-	device_power_up(PMSG_RESUME);
+	dpm_resume_noirq(PMSG_RESUME);
 
-	device_resume(PMSG_RESUME);
+	dpm_resume_end(PMSG_RESUME);
 	queue_event(APM_NORMAL_RESUME, NULL);
 	spin_lock(&user_list_lock);
 	for (as = user_list; as != NULL; as = as->next) {
@@ -1277,7 +1277,7 @@
 {
 	int err;
 
-	device_power_down(PMSG_SUSPEND);
+	dpm_suspend_noirq(PMSG_SUSPEND);
 
 	local_irq_disable();
 	sysdev_suspend(PMSG_SUSPEND);
@@ -1291,7 +1291,7 @@
 	sysdev_resume();
 	local_irq_enable();
 
-	device_power_up(PMSG_RESUME);
+	dpm_resume_noirq(PMSG_RESUME);
 }
 
 static apm_event_t get_event(void)
@@ -1376,7 +1376,7 @@
 			ignore_bounce = 1;
 			if ((event != APM_NORMAL_RESUME)
 			    || (ignore_normal_resume == 0)) {
-				device_resume(PMSG_RESUME);
+				dpm_resume_end(PMSG_RESUME);
 				queue_event(event, NULL);
 			}
 			ignore_normal_resume = 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/asm-offsets_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/asm-offsets_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/asm-offsets_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/asm-offsets_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -126,6 +126,7 @@
 #if defined(CONFIG_LGUEST) || defined(CONFIG_LGUEST_GUEST) || defined(CONFIG_LGUEST_MODULE)
 	BLANK();
 	OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
+	OFFSET(LGUEST_DATA_irq_pending, lguest_data, irq_pending);
 	OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir);
 
 	BLANK();
@@ -146,4 +147,5 @@
 	OFFSET(BP_loadflags, boot_params, hdr.loadflags);
 	OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
 	OFFSET(BP_version, boot_params, hdr.version);
+	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/asm-offsets_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/asm-offsets_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/asm-offsets_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/asm-offsets_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -125,6 +125,7 @@
 	OFFSET(BP_loadflags, boot_params, hdr.loadflags);
 	OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
 	OFFSET(BP_version, boot_params, hdr.version);
+	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
 
 	BLANK();
 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/amd.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/amd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/amd.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,7 @@
 #include <asm/processor.h>
 #include <asm/apic.h>
 #include <asm/cpu.h>
+#include <asm/pci-direct.h>
 
 #ifdef CONFIG_X86_64
 # include <asm/numa_64.h>
@@ -257,13 +258,15 @@
 {
 #ifdef CONFIG_X86_HT
 	unsigned bits;
+	int cpu = smp_processor_id();
 
 	bits = c->x86_coreid_bits;
-
 	/* Low order bits define the core id (index of core in socket) */
 	c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
 	/* Convert the initial APIC ID into the socket ID */
 	c->phys_proc_id = c->initial_apicid >> bits;
+	/* use socket ID also for last level cache */
+	per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
 #endif
 }
 
@@ -272,7 +275,7 @@
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
 	int cpu = smp_processor_id();
 	int node;
-	unsigned apicid = hard_smp_processor_id();
+	unsigned apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
 
 	node = c->phys_proc_id;
 	if (apicid_to_node[apicid] != NUMA_NO_NODE)
@@ -351,6 +354,15 @@
 		    (c->x86_model == 8 && c->x86_mask >= 8))
 			set_cpu_cap(c, X86_FEATURE_K6_MTRR);
 #endif
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
+	/* check CPU config space for extended APIC ID */
+	if (cpu_has_apic && c->x86 >= 0xf) {
+		unsigned int val;
+		val = read_pci_config(0, 24, 0, 0x68);
+		if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18)))
+			set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
+	}
+#endif
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -388,6 +400,13 @@
 		level = cpuid_eax(1);
 		if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
 			set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+
+		/*
+		 * Some BIOSes incorrectly force this feature, but only K8
+		 * revision D (model = 0x14) and later actually support it.
+		 */
+		if (c->x86_model < 0x14)
+			clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
 	}
 	if (c->x86 == 0x10 || c->x86 == 0x11)
 		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/common.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/common.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/common.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 
 #include <asm/stackprotector.h>
+#include <asm/perf_counter.h>
 #include <asm/mmu_context.h>
 #include <asm/hypervisor.h>
 #include <asm/processor.h>
@@ -58,7 +59,30 @@
 	alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
 }
 
-static const struct cpu_dev *this_cpu __cpuinitdata;
+static void __cpuinit default_init(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+	display_cacheinfo(c);
+#else
+	/* Not much we can do here... */
+	/* Check if at least it has cpuid */
+	if (c->cpuid_level == -1) {
+		/* No cpuid. It must be an ancient CPU */
+		if (c->x86 == 4)
+			strcpy(c->x86_model_id, "486");
+		else if (c->x86 == 3)
+			strcpy(c->x86_model_id, "386");
+	}
+#endif
+}
+
+static const struct cpu_dev __cpuinitconst default_cpu = {
+	.c_init		= default_init,
+	.c_vendor	= "Unknown",
+	.c_x86_vendor	= X86_VENDOR_UNKNOWN,
+};
+
+static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
 
 DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
 #ifdef CONFIG_X86_64
@@ -107,7 +131,7 @@
 	/* data */
 	[GDT_ENTRY_APMBIOS_BASE+2]	= { { { 0x0000ffff, 0x00409200 } } },
 
-	[GDT_ENTRY_ESPFIX_SS]		= { { { 0x00000000, 0x00c09200 } } },
+	[GDT_ENTRY_ESPFIX_SS]		= { { { 0x0000ffff, 0x00cf9200 } } },
 	[GDT_ENTRY_PERCPU]		= { { { 0x0000ffff, 0x00cf9200 } } },
 	GDT_STACK_CANARY_INIT
 #endif
@@ -299,7 +323,8 @@
 	return NULL;		/* Not found */
 }
 
-__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
+__u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
 
 void load_percpu_segment(int cpu)
 {
@@ -330,29 +355,6 @@
 
 static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
 
-static void __cpuinit default_init(struct cpuinfo_x86 *c)
-{
-#ifdef CONFIG_X86_64
-	display_cacheinfo(c);
-#else
-	/* Not much we can do here... */
-	/* Check if at least it has cpuid */
-	if (c->cpuid_level == -1) {
-		/* No cpuid. It must be an ancient CPU */
-		if (c->x86 == 4)
-			strcpy(c->x86_model_id, "486");
-		else if (c->x86 == 3)
-			strcpy(c->x86_model_id, "386");
-	}
-#endif
-}
-
-static const struct cpu_dev __cpuinitconst default_cpu = {
-	.c_init	= default_init,
-	.c_vendor = "Unknown",
-	.c_x86_vendor = X86_VENDOR_UNKNOWN,
-};
-
 static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
 {
 	unsigned int *v;
@@ -485,7 +487,6 @@
 static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
 {
 	char *v = c->x86_vendor_id;
-	static int printed;
 	int i;
 
 	for (i = 0; i < X86_VENDOR_NUM; i++) {
@@ -502,13 +503,9 @@
 		}
 	}
 
-	if (!printed) {
-		printed++;
-		printk(KERN_ERR
-		    "CPU: vendor_id '%s' unknown, using generic init.\n", v);
-
-		printk(KERN_ERR "CPU: Your system may be unstable.\n");
-	}
+	printk_once(KERN_ERR
+			"CPU: vendor_id '%s' unknown, using generic init.\n" \
+			"CPU: Your system may be unstable.\n", v);
 
 	c->x86_vendor = X86_VENDOR_UNKNOWN;
 	this_cpu = &default_cpu;
@@ -768,6 +765,12 @@
 	if (this_cpu->c_identify)
 		this_cpu->c_identify(c);
 
+	/* Clear/Set all flags overriden by options, after probe */
+	for (i = 0; i < NCAPINTS; i++) {
+		c->x86_capability[i] &= ~cpu_caps_cleared[i];
+		c->x86_capability[i] |= cpu_caps_set[i];
+	}
+
 #ifdef CONFIG_X86_64
 	c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
 #endif
@@ -813,6 +816,16 @@
 #endif
 
 	init_hypervisor(c);
+
+	/*
+	 * Clear/Set all flags overriden by options, need do it
+	 * before following smp all cpus cap AND.
+	 */
+	for (i = 0; i < NCAPINTS; i++) {
+		c->x86_capability[i] &= ~cpu_caps_cleared[i];
+		c->x86_capability[i] |= cpu_caps_set[i];
+	}
+
 	/*
 	 * On SMP, boot_cpu_data holds the common feature set between
 	 * all CPUs; so make sure that we indicate which features are
@@ -825,10 +838,6 @@
 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
 	}
 
-	/* Clear all flags overriden by options */
-	for (i = 0; i < NCAPINTS; i++)
-		c->x86_capability[i] &= ~cleared_cpu_caps[i];
-
 #ifdef CONFIG_X86_MCE
 	/* Init Machine Check Exception if available. */
 	mcheck_init(c);
@@ -861,6 +870,7 @@
 #else
 	vgetcpu_set_mode();
 #endif
+	init_hw_perf_counters();
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpu_debug.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpu_debug.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpu_debug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpu_debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,9 +32,7 @@
 
 static DEFINE_PER_CPU(struct cpu_cpuX_base, cpu_arr[CPU_REG_ALL_BIT]);
 static DEFINE_PER_CPU(struct cpu_private *, priv_arr[MAX_CPU_FILES]);
-static DEFINE_PER_CPU(unsigned, cpu_modelflag);
 static DEFINE_PER_CPU(int, cpu_priv_count);
-static DEFINE_PER_CPU(unsigned, cpu_model);
 
 static DEFINE_MUTEX(cpu_debug_lock);
 
@@ -80,302 +78,102 @@
 	{ "value",	CPU_REG_ALL,	1	},
 };
 
-/* Intel Registers Range */
-static struct cpu_debug_range cpu_intel_range[] = {
-	{ 0x00000000, 0x00000001, CPU_MC,	CPU_INTEL_ALL		},
-	{ 0x00000006, 0x00000007, CPU_MONITOR,	CPU_CX_AT_XE		},
-	{ 0x00000010, 0x00000010, CPU_TIME,	CPU_INTEL_ALL		},
-	{ 0x00000011, 0x00000013, CPU_PMC,	CPU_INTEL_PENTIUM	},
-	{ 0x00000017, 0x00000017, CPU_PLATFORM,	CPU_PX_CX_AT_XE		},
-	{ 0x0000001B, 0x0000001B, CPU_APIC,	CPU_P6_CX_AT_XE		},
-
-	{ 0x0000002A, 0x0000002A, CPU_POWERON,	CPU_PX_CX_AT_XE		},
-	{ 0x0000002B, 0x0000002B, CPU_POWERON,	CPU_INTEL_XEON		},
-	{ 0x0000002C, 0x0000002C, CPU_FREQ,	CPU_INTEL_XEON		},
-	{ 0x0000003A, 0x0000003A, CPU_CONTROL,	CPU_CX_AT_XE		},
-
-	{ 0x00000040, 0x00000043, CPU_LBRANCH,	CPU_PM_CX_AT_XE		},
-	{ 0x00000044, 0x00000047, CPU_LBRANCH,	CPU_PM_CO_AT		},
-	{ 0x00000060, 0x00000063, CPU_LBRANCH,	CPU_C2_AT		},
-	{ 0x00000064, 0x00000067, CPU_LBRANCH,	CPU_INTEL_ATOM		},
-
-	{ 0x00000079, 0x00000079, CPU_BIOS,	CPU_P6_CX_AT_XE		},
-	{ 0x00000088, 0x0000008A, CPU_CACHE,	CPU_INTEL_P6		},
-	{ 0x0000008B, 0x0000008B, CPU_BIOS,	CPU_P6_CX_AT_XE		},
-	{ 0x0000009B, 0x0000009B, CPU_MONITOR,	CPU_INTEL_XEON		},
-
-	{ 0x000000C1, 0x000000C2, CPU_PMC,	CPU_P6_CX_AT		},
-	{ 0x000000CD, 0x000000CD, CPU_FREQ,	CPU_CX_AT		},
-	{ 0x000000E7, 0x000000E8, CPU_PERF,	CPU_CX_AT		},
-	{ 0x000000FE, 0x000000FE, CPU_MTRR,	CPU_P6_CX_XE		},
-
-	{ 0x00000116, 0x00000116, CPU_CACHE,	CPU_INTEL_P6		},
-	{ 0x00000118, 0x00000118, CPU_CACHE,	CPU_INTEL_P6		},
-	{ 0x00000119, 0x00000119, CPU_CACHE,	CPU_INTEL_PX		},
-	{ 0x0000011A, 0x0000011B, CPU_CACHE,	CPU_INTEL_P6		},
-	{ 0x0000011E, 0x0000011E, CPU_CACHE,	CPU_PX_CX_AT		},
-
-	{ 0x00000174, 0x00000176, CPU_SYSENTER,	CPU_P6_CX_AT_XE		},
-	{ 0x00000179, 0x0000017A, CPU_MC,	CPU_PX_CX_AT_XE		},
-	{ 0x0000017B, 0x0000017B, CPU_MC,	CPU_P6_XE		},
-	{ 0x00000186, 0x00000187, CPU_PMC,	CPU_P6_CX_AT		},
-	{ 0x00000198, 0x00000199, CPU_PERF,	CPU_PM_CX_AT_XE		},
-	{ 0x0000019A, 0x0000019A, CPU_TIME,	CPU_PM_CX_AT_XE		},
-	{ 0x0000019B, 0x0000019D, CPU_THERM,	CPU_PM_CX_AT_XE		},
-	{ 0x000001A0, 0x000001A0, CPU_MISC,	CPU_PM_CX_AT_XE		},
-
-	{ 0x000001C9, 0x000001C9, CPU_LBRANCH,	CPU_PM_CX_AT		},
-	{ 0x000001D7, 0x000001D8, CPU_LBRANCH,	CPU_INTEL_XEON		},
-	{ 0x000001D9, 0x000001D9, CPU_DEBUG,	CPU_CX_AT_XE		},
-	{ 0x000001DA, 0x000001DA, CPU_LBRANCH,	CPU_INTEL_XEON		},
-	{ 0x000001DB, 0x000001DB, CPU_LBRANCH,	CPU_P6_XE		},
-	{ 0x000001DC, 0x000001DC, CPU_LBRANCH,	CPU_INTEL_P6		},
-	{ 0x000001DD, 0x000001DE, CPU_LBRANCH,	CPU_PX_CX_AT_XE		},
-	{ 0x000001E0, 0x000001E0, CPU_LBRANCH,	CPU_INTEL_P6		},
-
-	{ 0x00000200, 0x0000020F, CPU_MTRR,	CPU_P6_CX_XE		},
-	{ 0x00000250, 0x00000250, CPU_MTRR,	CPU_P6_CX_XE		},
-	{ 0x00000258, 0x00000259, CPU_MTRR,	CPU_P6_CX_XE		},
-	{ 0x00000268, 0x0000026F, CPU_MTRR,	CPU_P6_CX_XE		},
-	{ 0x00000277, 0x00000277, CPU_PAT,	CPU_C2_AT_XE		},
-	{ 0x000002FF, 0x000002FF, CPU_MTRR,	CPU_P6_CX_XE		},
-
-	{ 0x00000300, 0x00000308, CPU_PMC,	CPU_INTEL_XEON		},
-	{ 0x00000309, 0x0000030B, CPU_PMC,	CPU_C2_AT_XE		},
-	{ 0x0000030C, 0x00000311, CPU_PMC,	CPU_INTEL_XEON		},
-	{ 0x00000345, 0x00000345, CPU_PMC,	CPU_C2_AT		},
-	{ 0x00000360, 0x00000371, CPU_PMC,	CPU_INTEL_XEON		},
-	{ 0x0000038D, 0x00000390, CPU_PMC,	CPU_C2_AT		},
-	{ 0x000003A0, 0x000003BE, CPU_PMC,	CPU_INTEL_XEON		},
-	{ 0x000003C0, 0x000003CD, CPU_PMC,	CPU_INTEL_XEON		},
-	{ 0x000003E0, 0x000003E1, CPU_PMC,	CPU_INTEL_XEON		},
-	{ 0x000003F0, 0x000003F0, CPU_PMC,	CPU_INTEL_XEON		},
-	{ 0x000003F1, 0x000003F1, CPU_PMC,	CPU_C2_AT_XE		},
-	{ 0x000003F2, 0x000003F2, CPU_PMC,	CPU_INTEL_XEON		},
-
-	{ 0x00000400, 0x00000402, CPU_MC,	CPU_PM_CX_AT_XE		},
-	{ 0x00000403, 0x00000403, CPU_MC,	CPU_INTEL_XEON		},
-	{ 0x00000404, 0x00000406, CPU_MC,	CPU_PM_CX_AT_XE		},
-	{ 0x00000407, 0x00000407, CPU_MC,	CPU_INTEL_XEON		},
-	{ 0x00000408, 0x0000040A, CPU_MC,	CPU_PM_CX_AT_XE		},
-	{ 0x0000040B, 0x0000040B, CPU_MC,	CPU_INTEL_XEON		},
-	{ 0x0000040C, 0x0000040E, CPU_MC,	CPU_PM_CX_XE		},
-	{ 0x0000040F, 0x0000040F, CPU_MC,	CPU_INTEL_XEON		},
-	{ 0x00000410, 0x00000412, CPU_MC,	CPU_PM_CX_AT_XE		},
-	{ 0x00000413, 0x00000417, CPU_MC,	CPU_CX_AT_XE		},
-	{ 0x00000480, 0x0000048B, CPU_VMX,	CPU_CX_AT_XE		},
-
-	{ 0x00000600, 0x00000600, CPU_DEBUG,	CPU_PM_CX_AT_XE		},
-	{ 0x00000680, 0x0000068F, CPU_LBRANCH,	CPU_INTEL_XEON		},
-	{ 0x000006C0, 0x000006CF, CPU_LBRANCH,	CPU_INTEL_XEON		},
+/* CPU Registers Range */
+static struct cpu_debug_range cpu_reg_range[] = {
+	{ 0x00000000, 0x00000001, CPU_MC,	},
+	{ 0x00000006, 0x00000007, CPU_MONITOR,	},
+	{ 0x00000010, 0x00000010, CPU_TIME,	},
+	{ 0x00000011, 0x00000013, CPU_PMC,	},
+	{ 0x00000017, 0x00000017, CPU_PLATFORM,	},
+	{ 0x0000001B, 0x0000001B, CPU_APIC,	},
+	{ 0x0000002A, 0x0000002B, CPU_POWERON,	},
+	{ 0x0000002C, 0x0000002C, CPU_FREQ,	},
+	{ 0x0000003A, 0x0000003A, CPU_CONTROL,	},
+	{ 0x00000040, 0x00000047, CPU_LBRANCH,	},
+	{ 0x00000060, 0x00000067, CPU_LBRANCH,	},
+	{ 0x00000079, 0x00000079, CPU_BIOS,	},
+	{ 0x00000088, 0x0000008A, CPU_CACHE,	},
+	{ 0x0000008B, 0x0000008B, CPU_BIOS,	},
+	{ 0x0000009B, 0x0000009B, CPU_MONITOR,	},
+	{ 0x000000C1, 0x000000C4, CPU_PMC,	},
+	{ 0x000000CD, 0x000000CD, CPU_FREQ,	},
+	{ 0x000000E7, 0x000000E8, CPU_PERF,	},
+	{ 0x000000FE, 0x000000FE, CPU_MTRR,	},
 
-	{ 0x000107CC, 0x000107D3, CPU_PMC,	CPU_INTEL_XEON_MP	},
+	{ 0x00000116, 0x0000011E, CPU_CACHE,	},
+	{ 0x00000174, 0x00000176, CPU_SYSENTER,	},
+	{ 0x00000179, 0x0000017B, CPU_MC,	},
+	{ 0x00000186, 0x00000189, CPU_PMC,	},
+	{ 0x00000198, 0x00000199, CPU_PERF,	},
+	{ 0x0000019A, 0x0000019A, CPU_TIME,	},
+	{ 0x0000019B, 0x0000019D, CPU_THERM,	},
+	{ 0x000001A0, 0x000001A0, CPU_MISC,	},
+	{ 0x000001C9, 0x000001C9, CPU_LBRANCH,	},
+	{ 0x000001D7, 0x000001D8, CPU_LBRANCH,	},
+	{ 0x000001D9, 0x000001D9, CPU_DEBUG,	},
+	{ 0x000001DA, 0x000001E0, CPU_LBRANCH,	},
 
-	{ 0xC0000080, 0xC0000080, CPU_FEATURES,	CPU_INTEL_XEON		},
-	{ 0xC0000081, 0xC0000082, CPU_CALL,	CPU_INTEL_XEON		},
-	{ 0xC0000084, 0xC0000084, CPU_CALL,	CPU_INTEL_XEON		},
-	{ 0xC0000100, 0xC0000102, CPU_BASE,	CPU_INTEL_XEON		},
-};
+	{ 0x00000200, 0x0000020F, CPU_MTRR,	},
+	{ 0x00000250, 0x00000250, CPU_MTRR,	},
+	{ 0x00000258, 0x00000259, CPU_MTRR,	},
+	{ 0x00000268, 0x0000026F, CPU_MTRR,	},
+	{ 0x00000277, 0x00000277, CPU_PAT,	},
+	{ 0x000002FF, 0x000002FF, CPU_MTRR,	},
 
-/* AMD Registers Range */
-static struct cpu_debug_range cpu_amd_range[] = {
-	{ 0x00000000, 0x00000001, CPU_MC,	CPU_K10_PLUS,		},
-	{ 0x00000010, 0x00000010, CPU_TIME,	CPU_K8_PLUS,		},
-	{ 0x0000001B, 0x0000001B, CPU_APIC,	CPU_K8_PLUS,		},
-	{ 0x0000002A, 0x0000002A, CPU_POWERON,	CPU_K7_PLUS		},
-	{ 0x0000008B, 0x0000008B, CPU_VER,	CPU_K8_PLUS		},
-	{ 0x000000FE, 0x000000FE, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0x00000300, 0x00000311, CPU_PMC,	},
+	{ 0x00000345, 0x00000345, CPU_PMC,	},
+	{ 0x00000360, 0x00000371, CPU_PMC,	},
+	{ 0x0000038D, 0x00000390, CPU_PMC,	},
+	{ 0x000003A0, 0x000003BE, CPU_PMC,	},
+	{ 0x000003C0, 0x000003CD, CPU_PMC,	},
+	{ 0x000003E0, 0x000003E1, CPU_PMC,	},
+	{ 0x000003F0, 0x000003F2, CPU_PMC,	},
 
-	{ 0x00000174, 0x00000176, CPU_SYSENTER,	CPU_K8_PLUS,		},
-	{ 0x00000179, 0x0000017B, CPU_MC,	CPU_K8_PLUS,		},
-	{ 0x000001D9, 0x000001D9, CPU_DEBUG,	CPU_K8_PLUS,		},
-	{ 0x000001DB, 0x000001DE, CPU_LBRANCH,	CPU_K8_PLUS,		},
+	{ 0x00000400, 0x00000417, CPU_MC,	},
+	{ 0x00000480, 0x0000048B, CPU_VMX,	},
 
-	{ 0x00000200, 0x0000020F, CPU_MTRR,	CPU_K8_PLUS,		},
-	{ 0x00000250, 0x00000250, CPU_MTRR,	CPU_K8_PLUS,		},
-	{ 0x00000258, 0x00000259, CPU_MTRR,	CPU_K8_PLUS,		},
-	{ 0x00000268, 0x0000026F, CPU_MTRR,	CPU_K8_PLUS,		},
-	{ 0x00000277, 0x00000277, CPU_PAT,	CPU_K8_PLUS,		},
-	{ 0x000002FF, 0x000002FF, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0x00000600, 0x00000600, CPU_DEBUG,	},
+	{ 0x00000680, 0x0000068F, CPU_LBRANCH,	},
+	{ 0x000006C0, 0x000006CF, CPU_LBRANCH,	},
 
-	{ 0x00000400, 0x00000413, CPU_MC,	CPU_K8_PLUS,		},
+	{ 0x000107CC, 0x000107D3, CPU_PMC,	},
 
-	{ 0xC0000080, 0xC0000080, CPU_FEATURES,	CPU_AMD_ALL,		},
-	{ 0xC0000081, 0xC0000084, CPU_CALL,	CPU_K8_PLUS,		},
-	{ 0xC0000100, 0xC0000102, CPU_BASE,	CPU_K8_PLUS,		},
-	{ 0xC0000103, 0xC0000103, CPU_TIME,	CPU_K10_PLUS,		},
+	{ 0xC0000080, 0xC0000080, CPU_FEATURES,	},
+	{ 0xC0000081, 0xC0000084, CPU_CALL,	},
+	{ 0xC0000100, 0xC0000102, CPU_BASE,	},
+	{ 0xC0000103, 0xC0000103, CPU_TIME,	},
 
-	{ 0xC0010000, 0xC0010007, CPU_PMC,	CPU_K8_PLUS,		},
-	{ 0xC0010010, 0xC0010010, CPU_CONF,	CPU_K7_PLUS,		},
-	{ 0xC0010015, 0xC0010015, CPU_CONF,	CPU_K7_PLUS,		},
-	{ 0xC0010016, 0xC001001A, CPU_MTRR,	CPU_K8_PLUS,		},
-	{ 0xC001001D, 0xC001001D, CPU_MTRR,	CPU_K8_PLUS,		},
-	{ 0xC001001F, 0xC001001F, CPU_CONF,	CPU_K8_PLUS,		},
-	{ 0xC0010030, 0xC0010035, CPU_BIOS,	CPU_K8_PLUS,		},
-	{ 0xC0010044, 0xC0010048, CPU_MC,	CPU_K8_PLUS,		},
-	{ 0xC0010050, 0xC0010056, CPU_SMM,	CPU_K0F_PLUS,		},
-	{ 0xC0010058, 0xC0010058, CPU_CONF,	CPU_K10_PLUS,		},
-	{ 0xC0010060, 0xC0010060, CPU_CACHE,	CPU_AMD_11,		},
-	{ 0xC0010061, 0xC0010068, CPU_SMM,	CPU_K10_PLUS,		},
-	{ 0xC0010069, 0xC001006B, CPU_SMM,	CPU_AMD_11,		},
-	{ 0xC0010070, 0xC0010071, CPU_SMM,	CPU_K10_PLUS,		},
-	{ 0xC0010111, 0xC0010113, CPU_SMM,	CPU_K8_PLUS,		},
-	{ 0xC0010114, 0xC0010118, CPU_SVM,	CPU_K10_PLUS,		},
-	{ 0xC0010140, 0xC0010141, CPU_OSVM,	CPU_K10_PLUS,		},
-	{ 0xC0011022, 0xC0011023, CPU_CONF,	CPU_K10_PLUS,		},
+	{ 0xC0010000, 0xC0010007, CPU_PMC,	},
+	{ 0xC0010010, 0xC0010010, CPU_CONF,	},
+	{ 0xC0010015, 0xC0010015, CPU_CONF,	},
+	{ 0xC0010016, 0xC001001A, CPU_MTRR,	},
+	{ 0xC001001D, 0xC001001D, CPU_MTRR,	},
+	{ 0xC001001F, 0xC001001F, CPU_CONF,	},
+	{ 0xC0010030, 0xC0010035, CPU_BIOS,	},
+	{ 0xC0010044, 0xC0010048, CPU_MC,	},
+	{ 0xC0010050, 0xC0010056, CPU_SMM,	},
+	{ 0xC0010058, 0xC0010058, CPU_CONF,	},
+	{ 0xC0010060, 0xC0010060, CPU_CACHE,	},
+	{ 0xC0010061, 0xC0010068, CPU_SMM,	},
+	{ 0xC0010069, 0xC001006B, CPU_SMM,	},
+	{ 0xC0010070, 0xC0010071, CPU_SMM,	},
+	{ 0xC0010111, 0xC0010113, CPU_SMM,	},
+	{ 0xC0010114, 0xC0010118, CPU_SVM,	},
+	{ 0xC0010140, 0xC0010141, CPU_OSVM,	},
+	{ 0xC0011022, 0xC0011023, CPU_CONF,	},
 };
 
-
-/* Intel */
-static int get_intel_modelflag(unsigned model)
-{
-	int flag;
-
-	switch (model) {
-	case 0x0501:
-	case 0x0502:
-	case 0x0504:
-		flag = CPU_INTEL_PENTIUM;
-		break;
-	case 0x0601:
-	case 0x0603:
-	case 0x0605:
-	case 0x0607:
-	case 0x0608:
-	case 0x060A:
-	case 0x060B:
-		flag = CPU_INTEL_P6;
-		break;
-	case 0x0609:
-	case 0x060D:
-		flag = CPU_INTEL_PENTIUM_M;
-		break;
-	case 0x060E:
-		flag = CPU_INTEL_CORE;
-		break;
-	case 0x060F:
-	case 0x0617:
-		flag = CPU_INTEL_CORE2;
-		break;
-	case 0x061C:
-		flag = CPU_INTEL_ATOM;
-		break;
-	case 0x0F00:
-	case 0x0F01:
-	case 0x0F02:
-	case 0x0F03:
-	case 0x0F04:
-		flag = CPU_INTEL_XEON_P4;
-		break;
-	case 0x0F06:
-		flag = CPU_INTEL_XEON_MP;
-		break;
-	default:
-		flag = CPU_NONE;
-		break;
-	}
-
-	return flag;
-}
-
-/* AMD */
-static int get_amd_modelflag(unsigned model)
-{
-	int flag;
-
-	switch (model >> 8) {
-	case 0x6:
-		flag = CPU_AMD_K6;
-		break;
-	case 0x7:
-		flag = CPU_AMD_K7;
-		break;
-	case 0x8:
-		flag = CPU_AMD_K8;
-		break;
-	case 0xf:
-		flag = CPU_AMD_0F;
-		break;
-	case 0x10:
-		flag = CPU_AMD_10;
-		break;
-	case 0x11:
-		flag = CPU_AMD_11;
-		break;
-	default:
-		flag = CPU_NONE;
-		break;
-	}
-
-	return flag;
-}
-
-static int get_cpu_modelflag(unsigned cpu)
-{
-	int flag;
-
-	flag = per_cpu(cpu_model, cpu);
-
-	switch (flag >> 16) {
-	case X86_VENDOR_INTEL:
-		flag = get_intel_modelflag(flag);
-		break;
-	case X86_VENDOR_AMD:
-		flag = get_amd_modelflag(flag & 0xffff);
-		break;
-	default:
-		flag = CPU_NONE;
-		break;
-	}
-
-	return flag;
-}
-
-static int get_cpu_range_count(unsigned cpu)
-{
-	int index;
-
-	switch (per_cpu(cpu_model, cpu) >> 16) {
-	case X86_VENDOR_INTEL:
-		index = ARRAY_SIZE(cpu_intel_range);
-		break;
-	case X86_VENDOR_AMD:
-		index = ARRAY_SIZE(cpu_amd_range);
-		break;
-	default:
-		index = 0;
-		break;
-	}
-
-	return index;
-}
-
 static int is_typeflag_valid(unsigned cpu, unsigned flag)
 {
-	unsigned vendor, modelflag;
-	int i, index;
+	int i;
 
 	/* Standard Registers should be always valid */
 	if (flag >= CPU_TSS)
 		return 1;
 
-	modelflag = per_cpu(cpu_modelflag, cpu);
-	vendor = per_cpu(cpu_model, cpu) >> 16;
-	index = get_cpu_range_count(cpu);
-
-	for (i = 0; i < index; i++) {
-		switch (vendor) {
-		case X86_VENDOR_INTEL:
-			if ((cpu_intel_range[i].model & modelflag) &&
-			    (cpu_intel_range[i].flag & flag))
-				return 1;
-			break;
-		case X86_VENDOR_AMD:
-			if ((cpu_amd_range[i].model & modelflag) &&
-			    (cpu_amd_range[i].flag & flag))
-				return 1;
-			break;
-		}
+	for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) {
+		if (cpu_reg_range[i].flag == flag)
+			return 1;
 	}
 
 	/* Invalid */
@@ -385,26 +183,11 @@
 static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max,
 			      int index, unsigned flag)
 {
-	unsigned modelflag;
-
-	modelflag = per_cpu(cpu_modelflag, cpu);
-	*max = 0;
-	switch (per_cpu(cpu_model, cpu) >> 16) {
-	case X86_VENDOR_INTEL:
-		if ((cpu_intel_range[index].model & modelflag) &&
-		    (cpu_intel_range[index].flag & flag)) {
-			*min = cpu_intel_range[index].min;
-			*max = cpu_intel_range[index].max;
-		}
-		break;
-	case X86_VENDOR_AMD:
-		if ((cpu_amd_range[index].model & modelflag) &&
-		    (cpu_amd_range[index].flag & flag)) {
-			*min = cpu_amd_range[index].min;
-			*max = cpu_amd_range[index].max;
-		}
-		break;
-	}
+	if (cpu_reg_range[index].flag == flag) {
+		*min = cpu_reg_range[index].min;
+		*max = cpu_reg_range[index].max;
+	} else
+		*max = 0;
 
 	return *max;
 }
@@ -434,7 +217,7 @@
 	unsigned msr, msr_min, msr_max;
 	struct cpu_private *priv;
 	u32 low, high;
-	int i, range;
+	int i;
 
 	if (seq) {
 		priv = seq->private;
@@ -446,9 +229,7 @@
 		}
 	}
 
-	range = get_cpu_range_count(cpu);
-
-	for (i = 0; i < range; i++) {
+	for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) {
 		if (!get_cpu_range(cpu, &msr_min, &msr_max, i, flag))
 			continue;
 
@@ -588,8 +369,20 @@
 	seq_printf(seq, " TMICT\t\t: %08x\n",  apic_read(APIC_TMICT));
 	seq_printf(seq, " TMCCT\t\t: %08x\n",  apic_read(APIC_TMCCT));
 	seq_printf(seq, " TDCR\t\t: %08x\n",  apic_read(APIC_TDCR));
-#endif /* CONFIG_X86_LOCAL_APIC */
+	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
+		unsigned int i, v, maxeilvt;
 
+		v = apic_read(APIC_EFEAT);
+		maxeilvt = (v >> 16) & 0xff;
+		seq_printf(seq, " EFEAT\t\t: %08x\n", v);
+		seq_printf(seq, " ECTRL\t\t: %08x\n", apic_read(APIC_ECTRL));
+
+		for (i = 0; i < maxeilvt; i++) {
+			v = apic_read(APIC_EILVTn(i));
+			seq_printf(seq, " EILVT%d\t\t: %08x\n", i, v);
+		}
+	}
+#endif /* CONFIG_X86_LOCAL_APIC */
 	seq_printf(seq, "\n MSR\t:\n");
 }
 
@@ -788,13 +581,11 @@
 {
 	struct dentry *cpu_dentry = NULL;
 	unsigned reg, reg_min, reg_max;
-	int i, range, err = 0;
+	int i, err = 0;
 	char reg_dir[12];
 	u32 low, high;
 
-	range = get_cpu_range_count(cpu);
-
-	for (i = 0; i < range; i++) {
+	for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) {
 		if (!get_cpu_range(cpu, &reg_min, &reg_max, i,
 				   cpu_base[type].flag))
 			continue;
@@ -850,10 +641,6 @@
 		cpui = &cpu_data(cpu);
 		if (!cpu_has(cpui, X86_FEATURE_MSR))
 			continue;
-		per_cpu(cpu_model, cpu) = ((cpui->x86_vendor << 16) |
-					   (cpui->x86 << 8) |
-					   (cpui->x86_model));
-		per_cpu(cpu_modelflag, cpu) = get_cpu_modelflag(cpu);
 
 		sprintf(cpu_dir, "cpu%d", cpu);
 		cpu_dentry = debugfs_create_dir(cpu_dir, cpu_debugfs_dir);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c	2009-09-09 18:13:59.000000000 -0400
@@ -90,11 +90,7 @@
 {
 	struct cpuinfo_x86 *cpu = &cpu_data(cpuid);
 
-	if (cpu->x86_vendor != X86_VENDOR_INTEL ||
-	    !cpu_has(cpu, X86_FEATURE_EST))
-		return 0;
-
-	return 1;
+	return cpu_has(cpu, X86_FEATURE_EST);
 }
 
 static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/Kconfig linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/Kconfig
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -220,11 +220,14 @@
 	  If in doubt, say N.
 
 config X86_E_POWERSAVER
-	tristate "VIA C7 Enhanced PowerSaver"
+	tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
 	select CPU_FREQ_TABLE
-	depends on X86_32
+	depends on X86_32 && EXPERIMENTAL
 	help
-	  This adds the CPUFreq driver for VIA C7 processors.
+	  This adds the CPUFreq driver for VIA C7 processors.  However, this driver
+	  does not have any safeguards to prevent operating the CPU out of spec
+	  and is thus considered dangerous.  Please use the regular ACPI cpufreq
+	  driver, enabled by CONFIG_X86_ACPI_CPUFREQ.
 
 	  If in doubt, say N.
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,4 @@
+
 /*
  *   (c) 2003-2006 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
@@ -117,20 +118,17 @@
 	u32 i = 0;
 
 	if (cpu_family == CPU_HW_PSTATE) {
-		if (data->currpstate == HW_PSTATE_INVALID) {
-			/* read (initial) hw pstate if not yet set */
-			rdmsr(MSR_PSTATE_STATUS, lo, hi);
-			i = lo & HW_PSTATE_MASK;
+		rdmsr(MSR_PSTATE_STATUS, lo, hi);
+		i = lo & HW_PSTATE_MASK;
+		data->currpstate = i;
+
+		/*
+		 * a workaround for family 11h erratum 311 might cause
+		 * an "out-of-range Pstate if the core is in Pstate-0
+		 */
+		if ((boot_cpu_data.x86 == 0x11) && (i >= data->numps))
+			data->currpstate = HW_PSTATE_0;
 
-			/*
-			 * a workaround for family 11h erratum 311 might cause
-			 * an "out-of-range Pstate if the core is in Pstate-0
-			 */
-			if (i >= data->numps)
-				data->currpstate = HW_PSTATE_0;
-			else
-				data->currpstate = i;
-		}
 		return 0;
 	}
 	do {
@@ -301,7 +299,7 @@
 static int transition_fid_vid(struct powernow_k8_data *data,
 		u32 reqfid, u32 reqvid)
 {
-	if (core_voltage_pre_transition(data, reqvid))
+	if (core_voltage_pre_transition(data, reqvid, reqfid))
 		return 1;
 
 	if (core_frequency_transition(data, reqfid))
@@ -329,17 +327,20 @@
 
 /* Phase 1 - core voltage transition ... setup voltage */
 static int core_voltage_pre_transition(struct powernow_k8_data *data,
-		u32 reqvid)
+		u32 reqvid, u32 reqfid)
 {
 	u32 rvosteps = data->rvo;
 	u32 savefid = data->currfid;
-	u32 maxvid, lo;
+	u32 maxvid, lo, rvomult = 1;
 
 	dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, "
 		"reqvid 0x%x, rvo 0x%x\n",
 		smp_processor_id(),
 		data->currfid, data->currvid, reqvid, data->rvo);
 
+	if ((savefid < LO_FID_TABLE_TOP) && (reqfid < LO_FID_TABLE_TOP))
+		rvomult = 2;
+	rvosteps *= rvomult;
 	rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
 	maxvid = 0x1f & (maxvid >> 16);
 	dprintk("ph1 maxvid=0x%x\n", maxvid);
@@ -353,7 +354,8 @@
 			return 1;
 	}
 
-	while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
+	while ((rvosteps > 0) &&
+			((rvomult * data->rvo + data->currvid) > reqvid)) {
 		if (data->currvid == maxvid) {
 			rvosteps = 0;
 		} else {
@@ -386,13 +388,6 @@
 	u32 vcoreqfid, vcocurrfid, vcofiddiff;
 	u32 fid_interval, savevid = data->currvid;
 
-	if ((reqfid < HI_FID_TABLE_BOTTOM) &&
-	    (data->currfid < HI_FID_TABLE_BOTTOM)) {
-		printk(KERN_ERR PFX "ph2: illegal lo-lo transition "
-				"0x%x 0x%x\n", reqfid, data->currfid);
-		return 1;
-	}
-
 	if (data->currfid == reqfid) {
 		printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n",
 				data->currfid);
@@ -409,6 +404,9 @@
 	vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
 	    : vcoreqfid - vcocurrfid;
 
+	if ((reqfid <= LO_FID_TABLE_TOP) && (data->currfid <= LO_FID_TABLE_TOP))
+		vcofiddiff = 0;
+
 	while (vcofiddiff > 2) {
 		(data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);
 
@@ -510,41 +508,34 @@
 	return 0;
 }
 
-static int check_supported_cpu(unsigned int cpu)
+static void check_supported_cpu(void *_rc)
 {
-	cpumask_t oldmask;
 	u32 eax, ebx, ecx, edx;
-	unsigned int rc = 0;
-
-	oldmask = current->cpus_allowed;
-	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+	int *rc = _rc;
 
-	if (smp_processor_id() != cpu) {
-		printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
-		goto out;
-	}
+	*rc = -ENODEV;
 
 	if (current_cpu_data.x86_vendor != X86_VENDOR_AMD)
-		goto out;
+		return;
 
 	eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
 	if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
 	    ((eax & CPUID_XFAM) < CPUID_XFAM_10H))
-		goto out;
+		return;
 
 	if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
 		if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
 		    ((eax & CPUID_XMOD) > CPUID_XMOD_REV_MASK)) {
 			printk(KERN_INFO PFX
 				"Processor cpuid %x not supported\n", eax);
-			goto out;
+			return;
 		}
 
 		eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
 		if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
 			printk(KERN_INFO PFX
 			       "No frequency change capabilities detected\n");
-			goto out;
+			return;
 		}
 
 		cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
@@ -552,21 +543,17 @@
 			!= P_STATE_TRANSITION_CAPABLE) {
 			printk(KERN_INFO PFX
 				"Power state transitions not supported\n");
-			goto out;
+			return;
 		}
 	} else { /* must be a HW Pstate capable processor */
 		cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
 		if ((edx & USE_HW_PSTATE) == USE_HW_PSTATE)
 			cpu_family = CPU_HW_PSTATE;
 		else
-			goto out;
+			return;
 	}
 
-	rc = 1;
-
-out:
-	set_cpus_allowed_ptr(current, &oldmask);
-	return rc;
+	*rc = 0;
 }
 
 static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst,
@@ -823,13 +810,14 @@
 	if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE))
 		return;
 
-	control = data->acpi_data.states[index].control; data->irt = (control
-			>> IRT_SHIFT) & IRT_MASK; data->rvo = (control >>
-				RVO_SHIFT) & RVO_MASK; data->exttype = (control
-					>> EXT_TYPE_SHIFT) & EXT_TYPE_MASK;
-	data->plllock = (control >> PLL_L_SHIFT) & PLL_L_MASK; data->vidmvs = 1
-		<< ((control >> MVS_SHIFT) & MVS_MASK); data->vstable =
-		(control >> VST_SHIFT) & VST_MASK; }
+	control = data->acpi_data.states[index].control;
+	data->irt = (control >> IRT_SHIFT) & IRT_MASK;
+	data->rvo = (control >> RVO_SHIFT) & RVO_MASK;
+	data->exttype = (control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK;
+	data->plllock = (control >> PLL_L_SHIFT) & PLL_L_MASK;
+	data->vidmvs = 1 << ((control >> MVS_SHIFT) & MVS_MASK);
+	data->vstable = (control >> VST_SHIFT) & VST_MASK;
+}
 
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 {
@@ -1046,6 +1034,19 @@
 		if (cur_latency > max_latency)
 			max_latency = cur_latency;
 	}
+	if (max_latency == 0) {
+		/*
+		 * Fam 11h always returns 0 as transition latency.
+		 * This is intended and means "very fast". While cpufreq core
+		 * and governors currently can handle that gracefully, better
+		 * set it to 1 to avoid problems in the future.
+		 * For all others it's a BIOS bug.
+		 */
+		if (!boot_cpu_data.x86 == 0x11)
+			printk(KERN_ERR FW_WARN PFX "Invalid zero transition "
+				"latency\n");
+		max_latency = 1;
+	}
 	/* value in usecs, needs to be in nanoseconds */
 	return 1000 * max_latency;
 }
@@ -1080,20 +1081,12 @@
 		return 0;
 	}
 
-	if ((fid < HI_FID_TABLE_BOTTOM) &&
-	    (data->currfid < HI_FID_TABLE_BOTTOM)) {
-		printk(KERN_ERR PFX
-		       "ignoring illegal change in lo freq table-%x to 0x%x\n",
-		       data->currfid, fid);
-		return 1;
-	}
-
 	dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
 		smp_processor_id(), fid, vid);
 	freqs.old = find_khz_freq_from_fid(data->currfid);
 	freqs.new = find_khz_freq_from_fid(fid);
 
-	for_each_cpu_mask_nr(i, *(data->available_cores)) {
+	for_each_cpu(i, data->available_cores) {
 		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	}
@@ -1101,7 +1094,7 @@
 	res = transition_fid_vid(data, fid, vid);
 	freqs.new = find_khz_freq_from_fid(data->currfid);
 
-	for_each_cpu_mask_nr(i, *(data->available_cores)) {
+	for_each_cpu(i, data->available_cores) {
 		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	}
@@ -1126,7 +1119,7 @@
 			data->currpstate);
 	freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
 
-	for_each_cpu_mask_nr(i, *(data->available_cores)) {
+	for_each_cpu(i, data->available_cores) {
 		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	}
@@ -1134,7 +1127,7 @@
 	res = transition_pstate(data, pstate);
 	freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
 
-	for_each_cpu_mask_nr(i, *(data->available_cores)) {
+	for_each_cpu(i, data->available_cores) {
 		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	}
@@ -1235,21 +1228,47 @@
 	return cpufreq_frequency_table_verify(pol, data->powernow_table);
 }
 
-static const char ACPI_PSS_BIOS_BUG_MSG[] =
-	KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n"
-	KERN_ERR FW_BUG PFX "Try again with latest BIOS.\n";
+struct init_on_cpu {
+	struct powernow_k8_data *data;
+	int rc;
+};
+
+static void __cpuinit powernowk8_cpu_init_on_cpu(void *_init_on_cpu)
+{
+	struct init_on_cpu *init_on_cpu = _init_on_cpu;
+
+	if (pending_bit_stuck()) {
+		printk(KERN_ERR PFX "failing init, change pending bit set\n");
+		init_on_cpu->rc = -ENODEV;
+		return;
+	}
+
+	if (query_current_values_with_pending_wait(init_on_cpu->data)) {
+		init_on_cpu->rc = -ENODEV;
+		return;
+	}
+
+	if (cpu_family == CPU_OPTERON)
+		fidvid_msr_init();
+
+	init_on_cpu->rc = 0;
+}
 
 /* per CPU init entry point to the driver */
 static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 {
+	static const char ACPI_PSS_BIOS_BUG_MSG[] =
+		KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n"
+		FW_BUG PFX "Try again with latest BIOS.\n";
 	struct powernow_k8_data *data;
-	cpumask_t oldmask;
+	struct init_on_cpu init_on_cpu;
 	int rc;
 
 	if (!cpu_online(pol->cpu))
 		return -ENODEV;
 
-	if (!check_supported_cpu(pol->cpu))
+	smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1);
+	if (rc)
 		return -ENODEV;
 
 	data = kzalloc(sizeof(struct powernow_k8_data), GFP_KERNEL);
@@ -1289,27 +1308,12 @@
 		pol->cpuinfo.transition_latency = get_transition_latency(data);
 
 	/* only run on specific CPU from here on */
-	oldmask = current->cpus_allowed;
-	set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
-
-	if (smp_processor_id() != pol->cpu) {
-		printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
-		goto err_out_unmask;
-	}
-
-	if (pending_bit_stuck()) {
-		printk(KERN_ERR PFX "failing init, change pending bit set\n");
-		goto err_out_unmask;
-	}
-
-	if (query_current_values_with_pending_wait(data))
-		goto err_out_unmask;
-
-	if (cpu_family == CPU_OPTERON)
-		fidvid_msr_init();
-
-	/* run on any CPU again */
-	set_cpus_allowed_ptr(current, &oldmask);
+	init_on_cpu.data = data;
+	smp_call_function_single(data->cpu, powernowk8_cpu_init_on_cpu,
+				 &init_on_cpu, 1);
+	rc = init_on_cpu.rc;
+	if (rc != 0)
+		goto err_out_exit_acpi;
 
 	if (cpu_family == CPU_HW_PSTATE)
 		cpumask_copy(pol->cpus, cpumask_of(pol->cpu));
@@ -1346,8 +1350,7 @@
 
 	return 0;
 
-err_out_unmask:
-	set_cpus_allowed_ptr(current, &oldmask);
+err_out_exit_acpi:
 	powernow_k8_cpu_exit_acpi(data);
 
 err_out:
@@ -1372,28 +1375,25 @@
 	return 0;
 }
 
+static void query_values_on_cpu(void *_err)
+{
+	int *err = _err;
+	struct powernow_k8_data *data = __get_cpu_var(powernow_data);
+
+	*err = query_current_values_with_pending_wait(data);
+}
+
 static unsigned int powernowk8_get(unsigned int cpu)
 {
-	struct powernow_k8_data *data;
-	cpumask_t oldmask = current->cpus_allowed;
+	struct powernow_k8_data *data = per_cpu(powernow_data, cpu);
 	unsigned int khz = 0;
-	unsigned int first;
-
-	first = cpumask_first(cpu_core_mask(cpu));
-	data = per_cpu(powernow_data, first);
+	int err;
 
 	if (!data)
 		return -EINVAL;
 
-	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-	if (smp_processor_id() != cpu) {
-		printk(KERN_ERR PFX
-			"limiting to CPU %d failed in powernowk8_get\n", cpu);
-		set_cpus_allowed_ptr(current, &oldmask);
-		return 0;
-	}
-
-	if (query_current_values_with_pending_wait(data))
+	smp_call_function_single(cpu, query_values_on_cpu, &err, true);
+	if (err)
 		goto out;
 
 	if (cpu_family == CPU_HW_PSTATE)
@@ -1404,7 +1404,6 @@
 
 
 out:
-	set_cpus_allowed_ptr(current, &oldmask);
 	return khz;
 }
 
@@ -1430,7 +1429,9 @@
 	unsigned int i, supported_cpus = 0;
 
 	for_each_online_cpu(i) {
-		if (check_supported_cpu(i))
+		int rc;
+		smp_call_function_single(i, check_supported_cpu, &rc, 1);
+		if (rc == 0)
 			supported_cpus++;
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.h linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.h	2009-09-09 18:13:59.000000000 -0400
@@ -215,7 +215,8 @@
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg)
 
-static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid);
+static int core_voltage_pre_transition(struct powernow_k8_data *data,
+	u32 reqvid, u32 regfid);
 static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid);
 static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
 
@@ -223,14 +224,3 @@
 
 static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
 static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
-
-#ifdef CONFIG_SMP
-static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
-{
-}
-#else
-static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
-{
-	cpu_set(0, cpu_sharedcore_mask[0]);
-}
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c	2009-09-09 18:13:59.000000000 -0400
@@ -323,14 +323,8 @@
 {
 	unsigned l, h;
 	unsigned clock_freq;
-	cpumask_t saved_mask;
-
-	saved_mask = current->cpus_allowed;
-	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-	if (smp_processor_id() != cpu)
-		return 0;
 
-	rdmsr(MSR_IA32_PERF_STATUS, l, h);
+	rdmsr_on_cpu(cpu, MSR_IA32_PERF_STATUS, &l, &h);
 	clock_freq = extract_clock(l, cpu, 0);
 
 	if (unlikely(clock_freq == 0)) {
@@ -340,11 +334,9 @@
 		 * P-state transition (like TM2). Get the last freq set 
 		 * in PERF_CTL.
 		 */
-		rdmsr(MSR_IA32_PERF_CTL, l, h);
+		rdmsr_on_cpu(cpu, MSR_IA32_PERF_CTL, &l, &h);
 		clock_freq = extract_clock(l, cpu, 1);
 	}
-
-	set_cpus_allowed_ptr(current, &saved_mask);
 	return clock_freq;
 }
 
@@ -467,15 +459,10 @@
 	struct cpufreq_freqs	freqs;
 	int			retval = 0;
 	unsigned int		j, k, first_cpu, tmp;
-	cpumask_var_t saved_mask, covered_cpus;
+	cpumask_var_t covered_cpus;
 
-	if (unlikely(!alloc_cpumask_var(&saved_mask, GFP_KERNEL)))
-		return -ENOMEM;
-	if (unlikely(!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))) {
-		free_cpumask_var(saved_mask);
+	if (unlikely(!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL)))
 		return -ENOMEM;
-	}
-	cpumask_copy(saved_mask, &current->cpus_allowed);
 
 	if (unlikely(per_cpu(centrino_model, cpu) == NULL)) {
 		retval = -ENODEV;
@@ -493,7 +480,7 @@
 
 	first_cpu = 1;
 	for_each_cpu(j, policy->cpus) {
-		const struct cpumask *mask;
+		int good_cpu;
 
 		/* cpufreq holds the hotplug lock, so we are safe here */
 		if (!cpu_online(j))
@@ -504,32 +491,30 @@
 		 * Make sure we are running on CPU that wants to change freq
 		 */
 		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
-			mask = policy->cpus;
+			good_cpu = cpumask_any_and(policy->cpus,
+						   cpu_online_mask);
 		else
-			mask = cpumask_of(j);
+			good_cpu = j;
 
-		set_cpus_allowed_ptr(current, mask);
-		preempt_disable();
-		if (unlikely(!cpu_isset(smp_processor_id(), *mask))) {
+		if (good_cpu >= nr_cpu_ids) {
 			dprintk("couldn't limit to CPUs in this domain\n");
 			retval = -EAGAIN;
 			if (first_cpu) {
 				/* We haven't started the transition yet. */
-				goto migrate_end;
+				goto out;
 			}
-			preempt_enable();
 			break;
 		}
 
 		msr = per_cpu(centrino_model, cpu)->op_points[newstate].index;
 
 		if (first_cpu) {
-			rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+			rdmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, &oldmsr, &h);
 			if (msr == (oldmsr & 0xffff)) {
 				dprintk("no change needed - msr was and needs "
 					"to be %x\n", oldmsr);
 				retval = 0;
-				goto migrate_end;
+				goto out;
 			}
 
 			freqs.old = extract_clock(oldmsr, cpu, 0);
@@ -553,14 +538,11 @@
 			oldmsr |= msr;
 		}
 
-		wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
-			preempt_enable();
+		wrmsr_on_cpu(good_cpu, MSR_IA32_PERF_CTL, oldmsr, h);
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
 			break;
-		}
 
-		cpu_set(j, *covered_cpus);
-		preempt_enable();
+		cpumask_set_cpu(j, covered_cpus);
 	}
 
 	for_each_cpu(k, policy->cpus) {
@@ -578,10 +560,8 @@
 		 * Best effort undo..
 		 */
 
-		for_each_cpu_mask_nr(j, *covered_cpus) {
-			set_cpus_allowed_ptr(current, &cpumask_of_cpu(j));
-			wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-		}
+		for_each_cpu(j, covered_cpus)
+			wrmsr_on_cpu(j, MSR_IA32_PERF_CTL, oldmsr, h);
 
 		tmp = freqs.new;
 		freqs.new = freqs.old;
@@ -593,15 +573,9 @@
 			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 		}
 	}
-	set_cpus_allowed_ptr(current, saved_mask);
 	retval = 0;
-	goto out;
 
-migrate_end:
-	preempt_enable();
-	set_cpus_allowed_ptr(current, saved_mask);
 out:
-	free_cpumask_var(saved_mask);
 	free_cpumask_var(covered_cpus);
 	return retval;
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,7 +89,8 @@
  * speedstep_set_state - set the SpeedStep state
  * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
- *   Tries to change the SpeedStep state.
+ *   Tries to change the SpeedStep state.  Can be called from
+ *   smp_call_function_single.
  */
 static void speedstep_set_state(unsigned int state)
 {
@@ -143,6 +144,11 @@
 	return;
 }
 
+/* Wrapper for smp_call_function_single. */
+static void _speedstep_set_state(void *_state)
+{
+	speedstep_set_state(*(unsigned int *)_state);
+}
 
 /**
  * speedstep_activate - activate SpeedStep control in the chipset
@@ -226,22 +232,28 @@
 	return 0;
 }
 
-static unsigned int _speedstep_get(const struct cpumask *cpus)
-{
+struct get_freq_data {
 	unsigned int speed;
-	cpumask_t cpus_allowed;
+	unsigned int processor;
+};
 
-	cpus_allowed = current->cpus_allowed;
-	set_cpus_allowed_ptr(current, cpus);
-	speed = speedstep_get_frequency(speedstep_processor);
-	set_cpus_allowed_ptr(current, &cpus_allowed);
-	dprintk("detected %u kHz as current frequency\n", speed);
-	return speed;
+static void get_freq_data(void *_data)
+{
+	struct get_freq_data *data = _data;
+
+	data->speed = speedstep_get_frequency(data->processor);
 }
 
 static unsigned int speedstep_get(unsigned int cpu)
 {
-	return _speedstep_get(cpumask_of(cpu));
+	struct get_freq_data data = { .processor = cpu };
+
+	/* You're supposed to ensure CPU is online. */
+	if (smp_call_function_single(cpu, get_freq_data, &data, 1) != 0)
+		BUG();
+
+	dprintk("detected %u kHz as current frequency\n", data.speed);
+	return data.speed;
 }
 
 /**
@@ -257,16 +269,16 @@
 			     unsigned int target_freq,
 			     unsigned int relation)
 {
-	unsigned int newstate = 0;
+	unsigned int newstate = 0, policy_cpu;
 	struct cpufreq_freqs freqs;
-	cpumask_t cpus_allowed;
 	int i;
 
 	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
 				target_freq, relation, &newstate))
 		return -EINVAL;
 
-	freqs.old = _speedstep_get(policy->cpus);
+	policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
+	freqs.old = speedstep_get(policy_cpu);
 	freqs.new = speedstep_freqs[newstate].frequency;
 	freqs.cpu = policy->cpu;
 
@@ -276,20 +288,13 @@
 	if (freqs.old == freqs.new)
 		return 0;
 
-	cpus_allowed = current->cpus_allowed;
-
 	for_each_cpu(i, policy->cpus) {
 		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	}
 
-	/* switch to physical CPU where state is to be changed */
-	set_cpus_allowed_ptr(current, policy->cpus);
-
-	speedstep_set_state(newstate);
-
-	/* allow to be run on all CPUs */
-	set_cpus_allowed_ptr(current, &cpus_allowed);
+	smp_call_function_single(policy_cpu, _speedstep_set_state, &newstate,
+				 true);
 
 	for_each_cpu(i, policy->cpus) {
 		freqs.cpu = i;
@@ -312,33 +317,43 @@
 	return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
 }
 
+struct get_freqs {
+	struct cpufreq_policy *policy;
+	int ret;
+};
+
+static void get_freqs_on_cpu(void *_get_freqs)
+{
+	struct get_freqs *get_freqs = _get_freqs;
+
+	get_freqs->ret =
+		speedstep_get_freqs(speedstep_processor,
+			    &speedstep_freqs[SPEEDSTEP_LOW].frequency,
+			    &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+			    &get_freqs->policy->cpuinfo.transition_latency,
+			    &speedstep_set_state);
+}
 
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
-	int result = 0;
-	unsigned int speed;
-	cpumask_t cpus_allowed;
+	int result;
+	unsigned int policy_cpu, speed;
+	struct get_freqs gf;
 
 	/* only run on CPU to be set, or on its sibling */
 #ifdef CONFIG_SMP
 	cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
 #endif
-
-	cpus_allowed = current->cpus_allowed;
-	set_cpus_allowed_ptr(current, policy->cpus);
+	policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
 
 	/* detect low and high frequency and transition latency */
-	result = speedstep_get_freqs(speedstep_processor,
-				     &speedstep_freqs[SPEEDSTEP_LOW].frequency,
-				     &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
-				     &policy->cpuinfo.transition_latency,
-				     &speedstep_set_state);
-	set_cpus_allowed_ptr(current, &cpus_allowed);
-	if (result)
-		return result;
+	gf.policy = policy;
+	smp_call_function_single(policy_cpu, get_freqs_on_cpu, &gf, 1);
+	if (gf.ret)
+		return gf.ret;
 
 	/* get current speed setting */
-	speed = _speedstep_get(policy->cpus);
+	speed = speedstep_get(policy_cpu);
 	if (!speed)
 		return -EIO;
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c	2009-09-09 18:13:59.000000000 -0400
@@ -226,6 +226,7 @@
 }
 
 
+/* Warning: may get called from smp_call_function_single. */
 unsigned int speedstep_get_frequency(unsigned int processor)
 {
 	switch (processor) {
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/intel.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/intel.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/intel.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/intel.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,6 +86,29 @@
 	 */
 	if (c->x86 == 6 && c->x86_model < 15)
 		clear_cpu_cap(c, X86_FEATURE_PAT);
+
+#ifdef CONFIG_KMEMCHECK
+	/*
+	 * P4s have a "fast strings" feature which causes single-
+	 * stepping REP instructions to only generate a #DB on
+	 * cache-line boundaries.
+	 *
+	 * Ingo Molnar reported a Pentium D (model 6) and a Xeon
+	 * (model 2) with the same problem.
+	 */
+	if (c->x86 == 15) {
+		u64 misc_enable;
+
+		rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+		if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING) {
+			printk(KERN_INFO "kmemcheck: Disabling fast string operations\n");
+
+			misc_enable &= ~MSR_IA32_MISC_ENABLE_FAST_STRING;
+			wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+		}
+	}
+#endif
 }
 
 #ifdef CONFIG_X86_32
@@ -229,12 +252,12 @@
 }
 #endif
 
-static void __cpuinit srat_detect_node(void)
+static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
 {
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
 	unsigned node;
 	int cpu = smp_processor_id();
-	int apicid = hard_smp_processor_id();
+	int apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
 
 	/* Don't do the funky fallback heuristics the AMD version employs
 	   for now. */
@@ -400,7 +423,7 @@
 	}
 
 	/* Work around errata */
-	srat_detect_node();
+	srat_detect_node(c);
 
 	if (cpu_has(c, X86_FEATURE_VMX))
 		detect_vmx_virtcap(c);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 
 #include <asm/processor.h>
 #include <asm/smp.h>
+#include <asm/k8.h>
 
 #define LVL_1_INST	1
 #define LVL_1_DATA	2
@@ -159,14 +160,6 @@
 	unsigned long can_disable;
 };
 
-#if defined(CONFIG_PCI) && defined(CONFIG_SYSFS)
-static struct pci_device_id k8_nb_id[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) },
-	{}
-};
-#endif
-
 unsigned short			num_cache_leaves;
 
 /* AMD doesn't have CPUID4. Emulate it here to report the same
@@ -207,10 +200,17 @@
 };
 
 static const unsigned short __cpuinitconst assocs[] = {
-	[1] = 1, [2] = 2, [4] = 4, [6] = 8,
-	[8] = 16, [0xa] = 32, [0xb] = 48,
+	[1] = 1,
+	[2] = 2,
+	[4] = 4,
+	[6] = 8,
+	[8] = 16,
+	[0xa] = 32,
+	[0xb] = 48,
 	[0xc] = 64,
-	[0xf] = 0xffff // ??
+	[0xd] = 96,
+	[0xe] = 128,
+	[0xf] = 0xffff /* fully associative - no way to show this currently */
 };
 
 static const unsigned char __cpuinitconst levels[] = { 1, 1, 2, 3 };
@@ -271,7 +271,8 @@
 	eax->split.type = types[leaf];
 	eax->split.level = levels[leaf];
 	if (leaf == 3)
-		eax->split.num_threads_sharing = current_cpu_data.x86_max_cores - 1;
+		eax->split.num_threads_sharing =
+			current_cpu_data.x86_max_cores - 1;
 	else
 		eax->split.num_threads_sharing = 0;
 	eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
@@ -291,6 +292,14 @@
 {
 	if (index < 3)
 		return;
+
+	if (boot_cpu_data.x86 == 0x11)
+		return;
+
+	/* see erratum #382 */
+	if ((boot_cpu_data.x86 == 0x10) && (boot_cpu_data.x86_model < 0x8))
+		return;
+
 	this_leaf->can_disable = 1;
 }
 
@@ -696,97 +705,75 @@
 #define to_object(k)	container_of(k, struct _index_kobject, kobj)
 #define to_attr(a)	container_of(a, struct _cache_attr, attr)
 
-#ifdef CONFIG_PCI
-static struct pci_dev *get_k8_northbridge(int node)
-{
-	struct pci_dev *dev = NULL;
-	int i;
-
-	for (i = 0; i <= node; i++) {
-		do {
-			dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-			if (!dev)
-				break;
-		} while (!pci_match_id(&k8_nb_id[0], dev));
-		if (!dev)
-			break;
-	}
-	return dev;
-}
-#else
-static struct pci_dev *get_k8_northbridge(int node)
-{
-	return NULL;
-}
-#endif
-
-static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf)
+static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
+				  unsigned int index)
 {
-	const struct cpumask *mask = to_cpumask(this_leaf->shared_cpu_map);
-	int node = cpu_to_node(cpumask_first(mask));
-	struct pci_dev *dev = NULL;
-	ssize_t ret = 0;
-	int i;
+	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
+	int node = cpu_to_node(cpu);
+	struct pci_dev *dev = node_to_k8_nb_misc(node);
+	unsigned int reg = 0;
 
 	if (!this_leaf->can_disable)
-		return sprintf(buf, "Feature not enabled\n");
-
-	dev = get_k8_northbridge(node);
-	if (!dev) {
-		printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
 		return -EINVAL;
-	}
 
-	for (i = 0; i < 2; i++) {
-		unsigned int reg;
+	if (!dev)
+		return -EINVAL;
 
-		pci_read_config_dword(dev, 0x1BC + i * 4, &reg);
+	pci_read_config_dword(dev, 0x1BC + index * 4, &reg);
+	return sprintf(buf, "%x\n", reg);
+}
 
-		ret += sprintf(buf, "%sEntry: %d\n", buf, i);
-		ret += sprintf(buf, "%sReads:  %s\tNew Entries: %s\n",  
-			buf,
-			reg & 0x80000000 ? "Disabled" : "Allowed",
-			reg & 0x40000000 ? "Disabled" : "Allowed");
-		ret += sprintf(buf, "%sSubCache: %x\tIndex: %x\n",
-			buf, (reg & 0x30000) >> 16, reg & 0xfff);
-	}
-	return ret;
+#define SHOW_CACHE_DISABLE(index)					\
+static ssize_t								\
+show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf)  	\
+{									\
+	return show_cache_disable(this_leaf, buf, index);		\
 }
+SHOW_CACHE_DISABLE(0)
+SHOW_CACHE_DISABLE(1)
 
-static ssize_t
-store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf,
-		    size_t count)
+static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
+	const char *buf, size_t count, unsigned int index)
 {
-	const struct cpumask *mask = to_cpumask(this_leaf->shared_cpu_map);
-	int node = cpu_to_node(cpumask_first(mask));
-	struct pci_dev *dev = NULL;
-	unsigned int ret, index, val;
+	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
+	int node = cpu_to_node(cpu);
+	struct pci_dev *dev = node_to_k8_nb_misc(node);
+	unsigned long val = 0;
+	unsigned int scrubber = 0;
 
 	if (!this_leaf->can_disable)
-		return 0;
-
-	if (strlen(buf) > 15)
 		return -EINVAL;
 
-	ret = sscanf(buf, "%x %x", &index, &val);
-	if (ret != 2)
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!dev)
 		return -EINVAL;
-	if (index > 1)
+
+	if (strict_strtoul(buf, 10, &val) < 0)
 		return -EINVAL;
 
 	val |= 0xc0000000;
-	dev = get_k8_northbridge(node);
-	if (!dev) {
-		printk(KERN_ERR "Attempting AMD northbridge operation on a system with no northbridge\n");
-		return -EINVAL;
-	}
+
+	pci_read_config_dword(dev, 0x58, &scrubber);
+	scrubber &= ~0x1f000000;
+	pci_write_config_dword(dev, 0x58, scrubber);
 
 	pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000);
 	wbinvd();
 	pci_write_config_dword(dev, 0x1BC + index * 4, val);
+	return count;
+}
 
-	return 1;
+#define STORE_CACHE_DISABLE(index)					\
+static ssize_t								\
+store_cache_disable_##index(struct _cpuid4_info *this_leaf,	     	\
+			    const char *buf, size_t count)		\
+{									\
+	return store_cache_disable(this_leaf, buf, count, index);	\
 }
+STORE_CACHE_DISABLE(0)
+STORE_CACHE_DISABLE(1)
 
 struct _cache_attr {
 	struct attribute attr;
@@ -808,7 +795,10 @@
 define_one_ro(shared_cpu_map);
 define_one_ro(shared_cpu_list);
 
-static struct _cache_attr cache_disable = __ATTR(cache_disable, 0644, show_cache_disable, store_cache_disable);
+static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
+		show_cache_disable_0, store_cache_disable_0);
+static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
+		show_cache_disable_1, store_cache_disable_1);
 
 static struct attribute * default_attrs[] = {
 	&type.attr,
@@ -820,7 +810,8 @@
 	&size.attr,
 	&shared_cpu_map.attr,
 	&shared_cpu_list.attr,
-	&cache_disable.attr,
+	&cache_disable_0.attr,
+	&cache_disable_1.attr,
 	NULL
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/Makefile linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 #
-# Makefile for x86-compatible CPU details and quirks
+# Makefile for x86-compatible CPU details, features and quirks
 #
 
 # Don't trace early stages of a secondary CPU boot
@@ -7,6 +7,10 @@
 CFLAGS_REMOVE_common.o = -pg
 endif
 
+# Make sure load_percpu_segment has no stackprotector
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_common.o		:= $(nostackp)
+
 obj-y			:= intel_cacheinfo.o addon_cpuid_features.o
 obj-y			+= proc.o capflags.o powerflags.o common.o
 obj-y			+= vmware.o hypervisor.o
@@ -23,11 +27,13 @@
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
-obj-$(CONFIG_X86_MCE)	+= mcheck/
-obj-$(CONFIG_MTRR)	+= mtrr/
-obj-$(CONFIG_CPU_FREQ)	+= cpufreq/
+obj-$(CONFIG_PERF_COUNTERS)		+= perf_counter.o
 
-obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o
+obj-$(CONFIG_X86_MCE)			+= mcheck/
+obj-$(CONFIG_MTRR)			+= mtrr/
+obj-$(CONFIG_CPU_FREQ)			+= cpufreq/
+
+obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o
 
 quiet_cmd_mkcapflags = MKCAP   $@
       cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/k7.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/k7.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/k7.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/k7.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,25 +2,23 @@
  * Athlon specific Machine Check Exception Reporting
  * (C) Copyright 2002 Dave Jones <davej@redhat.com>
  */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
 #include <linux/smp.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
-/* Machine Check Handler For AMD Athlon/Duron */
+/* Machine Check Handler For AMD Athlon/Duron: */
 static void k7_machine_check(struct pt_regs *regs, long error_code)
 {
-	int recover = 1;
 	u32 alow, ahigh, high, low;
 	u32 mcgstl, mcgsth;
+	int recover = 1;
 	int i;
 
 	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
@@ -32,15 +30,19 @@
 
 	for (i = 1; i < nr_mce_banks; i++) {
 		rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
-		if (high&(1<<31)) {
+		if (high & (1<<31)) {
 			char misc[20];
 			char addr[24];
-			misc[0] = addr[0] = '\0';
+
+			misc[0] = '\0';
+			addr[0] = '\0';
+
 			if (high & (1<<29))
 				recover |= 1;
 			if (high & (1<<25))
 				recover |= 2;
 			high &= ~(1<<31);
+
 			if (high & (1<<27)) {
 				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
 				snprintf(misc, 20, "[%08x%08x]", ahigh, alow);
@@ -49,27 +51,31 @@
 				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
 				snprintf(addr, 24, " at %08x%08x", ahigh, alow);
 			}
+
 			printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n",
 				smp_processor_id(), i, high, low, misc, addr);
-			/* Clear it */
+
+			/* Clear it: */
 			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
-			/* Serialize */
+			/* Serialize: */
 			wmb();
 			add_taint(TAINT_MACHINE_CHECK);
 		}
 	}
 
-	if (recover&2)
+	if (recover & 2)
 		panic("CPU context corrupt");
-	if (recover&1)
+	if (recover & 1)
 		panic("Unable to continue");
+
 	printk(KERN_EMERG "Attempting to continue.\n");
+
 	mcgstl &= ~(1<<2);
 	wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 }
 
 
-/* AMD K7 machine check is Intel like */
+/* AMD K7 machine check is Intel like: */
 void amd_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
@@ -79,21 +85,26 @@
 		return;
 
 	machine_check_vector = k7_machine_check;
+	/* Make sure the vector pointer is visible before we enable MCEs: */
 	wmb();
 
 	printk(KERN_INFO "Intel machine check architecture supported.\n");
+
 	rdmsr(MSR_IA32_MCG_CAP, l, h);
 	if (l & (1<<8))	/* Control register present ? */
 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 	nr_mce_banks = l & 0xff;
 
-	/* Clear status for MC index 0 separately, we don't touch CTL,
-	 * as some K7 Athlons cause spurious MCEs when its enabled. */
+	/*
+	 * Clear status for MC index 0 separately, we don't touch CTL,
+	 * as some K7 Athlons cause spurious MCEs when its enabled:
+	 */
 	if (boot_cpu_data.x86 == 6) {
 		wrmsr(MSR_IA32_MC0_STATUS, 0x0, 0x0);
 		i = 1;
 	} else
 		i = 0;
+
 	for (; i < nr_mce_banks; i++) {
 		wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
 		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/Makefile linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,12 @@
-obj-y				=  mce_$(BITS).o therm_throt.o
+obj-y				=  mce.o
 
-obj-$(CONFIG_X86_32)		+= k7.o p4.o p5.o p6.o winchip.o
-obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel_64.o
-obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd_64.o
+obj-$(CONFIG_X86_NEW_MCE)	+= mce-severity.o
+obj-$(CONFIG_X86_OLD_MCE)	+= k7.o p4.o p6.o
+obj-$(CONFIG_X86_ANCIENT_MCE)	+= winchip.o p5.o
+obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel.o
+obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd.o
 obj-$(CONFIG_X86_MCE_NONFATAL)	+= non-fatal.o
 obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
+obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
+
+obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- * mce.c - x86 Machine Check Exception Reporting
- * (c) 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>, Dave Jones <davej@redhat.com>
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/smp.h>
-#include <linux/thread_info.h>
-
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/mce.h>
-
-#include "mce.h"
-
-int mce_disabled;
-int nr_mce_banks;
-
-EXPORT_SYMBOL_GPL(nr_mce_banks);	/* non-fatal.o */
-
-/* Handle unconfigured int18 (should never happen) */
-static void unexpected_machine_check(struct pt_regs *regs, long error_code)
-{
-	printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
-}
-
-/* Call the installed machine check handler for this CPU setup. */
-void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
-
-/* This has to be run for each processor */
-void mcheck_init(struct cpuinfo_x86 *c)
-{
-	if (mce_disabled == 1)
-		return;
-
-	switch (c->x86_vendor) {
-	case X86_VENDOR_AMD:
-		amd_mcheck_init(c);
-		break;
-
-	case X86_VENDOR_INTEL:
-		if (c->x86 == 5)
-			intel_p5_mcheck_init(c);
-		if (c->x86 == 6)
-			intel_p6_mcheck_init(c);
-		if (c->x86 == 15)
-			intel_p4_mcheck_init(c);
-		break;
-
-	case X86_VENDOR_CENTAUR:
-		if (c->x86 == 5)
-			winchip_mcheck_init(c);
-		break;
-
-	default:
-		break;
-	}
-}
-
-static int __init mcheck_disable(char *str)
-{
-	mce_disabled = 1;
-	return 1;
-}
-
-static int __init mcheck_enable(char *str)
-{
-	mce_disabled = -1;
-	return 1;
-}
-
-__setup("nomce", mcheck_disable);
-__setup("mce", mcheck_enable);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1187 +0,0 @@
-/*
- * Machine check handler.
- * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs.
- * Rest from unknown author(s).
- * 2004 Andi Kleen. Rewrote most of it.
- * Copyright 2008 Intel Corporation
- * Author: Andi Kleen
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/string.h>
-#include <linux/rcupdate.h>
-#include <linux/kallsyms.h>
-#include <linux/sysdev.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/capability.h>
-#include <linux/cpu.h>
-#include <linux/percpu.h>
-#include <linux/poll.h>
-#include <linux/thread_info.h>
-#include <linux/ctype.h>
-#include <linux/kmod.h>
-#include <linux/kdebug.h>
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-#include <linux/ratelimit.h>
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/mce.h>
-#include <asm/uaccess.h>
-#include <asm/smp.h>
-#include <asm/idle.h>
-
-#define MISC_MCELOG_MINOR 227
-
-atomic_t mce_entry;
-
-static int mce_dont_init;
-
-/*
- * Tolerant levels:
- *   0: always panic on uncorrected errors, log corrected errors
- *   1: panic or SIGBUS on uncorrected errors, log corrected errors
- *   2: SIGBUS or log uncorrected errors (if possible), log corrected errors
- *   3: never panic or SIGBUS, log all errors (for testing only)
- */
-static int tolerant = 1;
-static int banks;
-static u64 *bank;
-static unsigned long notify_user;
-static int rip_msr;
-static int mce_bootlog = -1;
-static atomic_t mce_events;
-
-static char trigger[128];
-static char *trigger_argv[2] = { trigger, NULL };
-
-static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
-
-/* MCA banks polled by the period polling timer for corrected events */
-DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
-	[0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
-};
-
-/* Do initial initialization of a struct mce */
-void mce_setup(struct mce *m)
-{
-	memset(m, 0, sizeof(struct mce));
-	m->cpu = smp_processor_id();
-	rdtscll(m->tsc);
-}
-
-/*
- * Lockless MCE logging infrastructure.
- * This avoids deadlocks on printk locks without having to break locks. Also
- * separate MCEs from kernel messages to avoid bogus bug reports.
- */
-
-static struct mce_log mcelog = {
-	MCE_LOG_SIGNATURE,
-	MCE_LOG_LEN,
-};
-
-void mce_log(struct mce *mce)
-{
-	unsigned next, entry;
-	atomic_inc(&mce_events);
-	mce->finished = 0;
-	wmb();
-	for (;;) {
-		entry = rcu_dereference(mcelog.next);
-		for (;;) {
-			/* When the buffer fills up discard new entries. Assume
-			   that the earlier errors are the more interesting. */
-			if (entry >= MCE_LOG_LEN) {
-				set_bit(MCE_OVERFLOW, (unsigned long *)&mcelog.flags);
-				return;
-			}
-			/* Old left over entry. Skip. */
-			if (mcelog.entry[entry].finished) {
-				entry++;
-				continue;
-			}
-			break;
-		}
-		smp_rmb();
-		next = entry + 1;
-		if (cmpxchg(&mcelog.next, entry, next) == entry)
-			break;
-	}
-	memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
-	wmb();
-	mcelog.entry[entry].finished = 1;
-	wmb();
-
-	set_bit(0, &notify_user);
-}
-
-static void print_mce(struct mce *m)
-{
-	printk(KERN_EMERG "\n"
-	       KERN_EMERG "HARDWARE ERROR\n"
-	       KERN_EMERG
-	       "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
-	       m->cpu, m->mcgstatus, m->bank, m->status);
-	if (m->ip) {
-		printk(KERN_EMERG "RIP%s %02x:<%016Lx> ",
-		       !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
-		       m->cs, m->ip);
-		if (m->cs == __KERNEL_CS)
-			print_symbol("{%s}", m->ip);
-		printk("\n");
-	}
-	printk(KERN_EMERG "TSC %llx ", m->tsc);
-	if (m->addr)
-		printk("ADDR %llx ", m->addr);
-	if (m->misc)
-		printk("MISC %llx ", m->misc);
-	printk("\n");
-	printk(KERN_EMERG "This is not a software problem!\n");
-	printk(KERN_EMERG "Run through mcelog --ascii to decode "
-	       "and contact your hardware vendor\n");
-}
-
-static void mce_panic(char *msg, struct mce *backup, unsigned long start)
-{
-	int i;
-
-	oops_begin();
-	for (i = 0; i < MCE_LOG_LEN; i++) {
-		unsigned long tsc = mcelog.entry[i].tsc;
-
-		if (time_before(tsc, start))
-			continue;
-		print_mce(&mcelog.entry[i]);
-		if (backup && mcelog.entry[i].tsc == backup->tsc)
-			backup = NULL;
-	}
-	if (backup)
-		print_mce(backup);
-	panic(msg);
-}
-
-int mce_available(struct cpuinfo_x86 *c)
-{
-	if (mce_dont_init)
-		return 0;
-	return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
-}
-
-static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
-{
-	if (regs && (m->mcgstatus & MCG_STATUS_RIPV)) {
-		m->ip = regs->ip;
-		m->cs = regs->cs;
-	} else {
-		m->ip = 0;
-		m->cs = 0;
-	}
-	if (rip_msr) {
-		/* Assume the RIP in the MSR is exact. Is this true? */
-		m->mcgstatus |= MCG_STATUS_EIPV;
-		rdmsrl(rip_msr, m->ip);
-		m->cs = 0;
-	}
-}
-
-/*
- * Poll for corrected events or events that happened before reset.
- * Those are just logged through /dev/mcelog.
- *
- * This is executed in standard interrupt context.
- */
-void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
-{
-	struct mce m;
-	int i;
-
-	mce_setup(&m);
-
-	rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
-	for (i = 0; i < banks; i++) {
-		if (!bank[i] || !test_bit(i, *b))
-			continue;
-
-		m.misc = 0;
-		m.addr = 0;
-		m.bank = i;
-		m.tsc = 0;
-
-		barrier();
-		rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
-		if (!(m.status & MCI_STATUS_VAL))
-			continue;
-
-		/*
-		 * Uncorrected events are handled by the exception handler
-		 * when it is enabled. But when the exception is disabled log
-		 * everything.
-		 *
-		 * TBD do the same check for MCI_STATUS_EN here?
-		 */
-		if ((m.status & MCI_STATUS_UC) && !(flags & MCP_UC))
-			continue;
-
-		if (m.status & MCI_STATUS_MISCV)
-			rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc);
-		if (m.status & MCI_STATUS_ADDRV)
-			rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
-
-		if (!(flags & MCP_TIMESTAMP))
-			m.tsc = 0;
-		/*
-		 * Don't get the IP here because it's unlikely to
-		 * have anything to do with the actual error location.
-		 */
-		if (!(flags & MCP_DONTLOG)) {
-			mce_log(&m);
-			add_taint(TAINT_MACHINE_CHECK);
-		}
-
-		/*
-		 * Clear state for this bank.
-		 */
-		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
-	}
-
-	/*
-	 * Don't clear MCG_STATUS here because it's only defined for
-	 * exceptions.
-	 */
-}
-
-/*
- * The actual machine check handler. This only handles real
- * exceptions when something got corrupted coming in through int 18.
- *
- * This is executed in NMI context not subject to normal locking rules. This
- * implies that most kernel services cannot be safely used. Don't even
- * think about putting a printk in there!
- */
-void do_machine_check(struct pt_regs * regs, long error_code)
-{
-	struct mce m, panicm;
-	u64 mcestart = 0;
-	int i;
-	int panicm_found = 0;
-	/*
-	 * If no_way_out gets set, there is no safe way to recover from this
-	 * MCE.  If tolerant is cranked up, we'll try anyway.
-	 */
-	int no_way_out = 0;
-	/*
-	 * If kill_it gets set, there might be a way to recover from this
-	 * error.
-	 */
-	int kill_it = 0;
-	DECLARE_BITMAP(toclear, MAX_NR_BANKS);
-
-	atomic_inc(&mce_entry);
-
-	if (notify_die(DIE_NMI, "machine check", regs, error_code,
-			   18, SIGKILL) == NOTIFY_STOP)
-		goto out2;
-	if (!banks)
-		goto out2;
-
-	mce_setup(&m);
-
-	rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
-	/* if the restart IP is not valid, we're done for */
-	if (!(m.mcgstatus & MCG_STATUS_RIPV))
-		no_way_out = 1;
-
-	rdtscll(mcestart);
-	barrier();
-
-	for (i = 0; i < banks; i++) {
-		__clear_bit(i, toclear);
-		if (!bank[i])
-			continue;
-
-		m.misc = 0;
-		m.addr = 0;
-		m.bank = i;
-
-		rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
-		if ((m.status & MCI_STATUS_VAL) == 0)
-			continue;
-
-		/*
-		 * Non uncorrected errors are handled by machine_check_poll
-		 * Leave them alone.
-		 */
-		if ((m.status & MCI_STATUS_UC) == 0)
-			continue;
-
-		/*
-		 * Set taint even when machine check was not enabled.
-		 */
-		add_taint(TAINT_MACHINE_CHECK);
-
-		__set_bit(i, toclear);
-
-		if (m.status & MCI_STATUS_EN) {
-			/* if PCC was set, there's no way out */
-			no_way_out |= !!(m.status & MCI_STATUS_PCC);
-			/*
-			 * If this error was uncorrectable and there was
-			 * an overflow, we're in trouble.  If no overflow,
-			 * we might get away with just killing a task.
-			 */
-			if (m.status & MCI_STATUS_UC) {
-				if (tolerant < 1 || m.status & MCI_STATUS_OVER)
-					no_way_out = 1;
-				kill_it = 1;
-			}
-		} else {
-			/*
-			 * Machine check event was not enabled. Clear, but
-			 * ignore.
-			 */
-			continue;
-		}
-
-		if (m.status & MCI_STATUS_MISCV)
-			rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc);
-		if (m.status & MCI_STATUS_ADDRV)
-			rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
-
-		mce_get_rip(&m, regs);
-		mce_log(&m);
-
-		/* Did this bank cause the exception? */
-		/* Assume that the bank with uncorrectable errors did it,
-		   and that there is only a single one. */
-		if ((m.status & MCI_STATUS_UC) && (m.status & MCI_STATUS_EN)) {
-			panicm = m;
-			panicm_found = 1;
-		}
-	}
-
-	/* If we didn't find an uncorrectable error, pick
-	   the last one (shouldn't happen, just being safe). */
-	if (!panicm_found)
-		panicm = m;
-
-	/*
-	 * If we have decided that we just CAN'T continue, and the user
-	 *  has not set tolerant to an insane level, give up and die.
-	 */
-	if (no_way_out && tolerant < 3)
-		mce_panic("Machine check", &panicm, mcestart);
-
-	/*
-	 * If the error seems to be unrecoverable, something should be
-	 * done.  Try to kill as little as possible.  If we can kill just
-	 * one task, do that.  If the user has set the tolerance very
-	 * high, don't try to do anything at all.
-	 */
-	if (kill_it && tolerant < 3) {
-		int user_space = 0;
-
-		/*
-		 * If the EIPV bit is set, it means the saved IP is the
-		 * instruction which caused the MCE.
-		 */
-		if (m.mcgstatus & MCG_STATUS_EIPV)
-			user_space = panicm.ip && (panicm.cs & 3);
-
-		/*
-		 * If we know that the error was in user space, send a
-		 * SIGBUS.  Otherwise, panic if tolerance is low.
-		 *
-		 * force_sig() takes an awful lot of locks and has a slight
-		 * risk of deadlocking.
-		 */
-		if (user_space) {
-			force_sig(SIGBUS, current);
-		} else if (panic_on_oops || tolerant < 2) {
-			mce_panic("Uncorrected machine check",
-				&panicm, mcestart);
-		}
-	}
-
-	/* notify userspace ASAP */
-	set_thread_flag(TIF_MCE_NOTIFY);
-
-	/* the last thing we do is clear state */
-	for (i = 0; i < banks; i++) {
-		if (test_bit(i, toclear))
-			wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
-	}
-	wrmsrl(MSR_IA32_MCG_STATUS, 0);
- out2:
-	atomic_dec(&mce_entry);
-}
-
-#ifdef CONFIG_X86_MCE_INTEL
-/***
- * mce_log_therm_throt_event - Logs the thermal throttling event to mcelog
- * @cpu: The CPU on which the event occurred.
- * @status: Event status information
- *
- * This function should be called by the thermal interrupt after the
- * event has been processed and the decision was made to log the event
- * further.
- *
- * The status parameter will be saved to the 'status' field of 'struct mce'
- * and historically has been the register value of the
- * MSR_IA32_THERMAL_STATUS (Intel) msr.
- */
-void mce_log_therm_throt_event(__u64 status)
-{
-	struct mce m;
-
-	mce_setup(&m);
-	m.bank = MCE_THERMAL_BANK;
-	m.status = status;
-	mce_log(&m);
-}
-#endif /* CONFIG_X86_MCE_INTEL */
-
-/*
- * Periodic polling timer for "silent" machine check errors.  If the
- * poller finds an MCE, poll 2x faster.  When the poller finds no more
- * errors, poll 2x slower (up to check_interval seconds).
- */
-
-static int check_interval = 5 * 60; /* 5 minutes */
-static DEFINE_PER_CPU(int, next_interval); /* in jiffies */
-static void mcheck_timer(unsigned long);
-static DEFINE_PER_CPU(struct timer_list, mce_timer);
-
-static void mcheck_timer(unsigned long data)
-{
-	struct timer_list *t = &per_cpu(mce_timer, data);
-	int *n;
-
-	WARN_ON(smp_processor_id() != data);
-
-	if (mce_available(&current_cpu_data))
-		machine_check_poll(MCP_TIMESTAMP,
-				&__get_cpu_var(mce_poll_banks));
-
-	/*
-	 * Alert userspace if needed.  If we logged an MCE, reduce the
-	 * polling interval, otherwise increase the polling interval.
-	 */
-	n = &__get_cpu_var(next_interval);
-	if (mce_notify_user()) {
-		*n = max(*n/2, HZ/100);
-	} else {
-		*n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ));
-	}
-
-	t->expires = jiffies + *n;
-	add_timer(t);
-}
-
-static void mce_do_trigger(struct work_struct *work)
-{
-	call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
-}
-
-static DECLARE_WORK(mce_trigger_work, mce_do_trigger);
-
-/*
- * Notify the user(s) about new machine check events.
- * Can be called from interrupt context, but not from machine check/NMI
- * context.
- */
-int mce_notify_user(void)
-{
-	/* Not more than two messages every minute */
-	static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2);
-
-	clear_thread_flag(TIF_MCE_NOTIFY);
-	if (test_and_clear_bit(0, &notify_user)) {
-		wake_up_interruptible(&mce_wait);
-
-		/*
-		 * There is no risk of missing notifications because
-		 * work_pending is always cleared before the function is
-		 * executed.
-		 */
-		if (trigger[0] && !work_pending(&mce_trigger_work))
-			schedule_work(&mce_trigger_work);
-
-		if (__ratelimit(&ratelimit))
-			printk(KERN_INFO "Machine check events logged\n");
-
-		return 1;
-	}
-	return 0;
-}
-
-/* see if the idle task needs to notify userspace */
-static int
-mce_idle_callback(struct notifier_block *nfb, unsigned long action, void *junk)
-{
-	/* IDLE_END should be safe - interrupts are back on */
-	if (action == IDLE_END && test_thread_flag(TIF_MCE_NOTIFY))
-		mce_notify_user();
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block mce_idle_notifier = {
-	.notifier_call = mce_idle_callback,
-};
-
-static __init int periodic_mcheck_init(void)
-{
-       idle_notifier_register(&mce_idle_notifier);
-       return 0;
-}
-__initcall(periodic_mcheck_init);
-
-/*
- * Initialize Machine Checks for a CPU.
- */
-static int mce_cap_init(void)
-{
-	u64 cap;
-	unsigned b;
-
-	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	b = cap & 0xff;
-	if (b > MAX_NR_BANKS) {
-		printk(KERN_WARNING
-		       "MCE: Using only %u machine check banks out of %u\n",
-			MAX_NR_BANKS, b);
-		b = MAX_NR_BANKS;
-	}
-
-	/* Don't support asymmetric configurations today */
-	WARN_ON(banks != 0 && b != banks);
-	banks = b;
-	if (!bank) {
-		bank = kmalloc(banks * sizeof(u64), GFP_KERNEL);
-		if (!bank)
-			return -ENOMEM;
-		memset(bank, 0xff, banks * sizeof(u64));
-	}
-
-	/* Use accurate RIP reporting if available. */
-	if ((cap & (1<<9)) && ((cap >> 16) & 0xff) >= 9)
-		rip_msr = MSR_IA32_MCG_EIP;
-
-	return 0;
-}
-
-static void mce_init(void *dummy)
-{
-	u64 cap;
-	int i;
-	mce_banks_t all_banks;
-
-	/*
-	 * Log the machine checks left over from the previous reset.
-	 */
-	bitmap_fill(all_banks, MAX_NR_BANKS);
-	machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks);
-
-	set_in_cr4(X86_CR4_MCE);
-
-	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	if (cap & MCG_CTL_P)
-		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
-
-	for (i = 0; i < banks; i++) {
-		wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
-		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
-	}
-}
-
-/* Add per CPU specific workarounds here */
-static void mce_cpu_quirks(struct cpuinfo_x86 *c)
-{
-	/* This should be disabled by the BIOS, but isn't always */
-	if (c->x86_vendor == X86_VENDOR_AMD) {
-		if (c->x86 == 15 && banks > 4)
-			/* disable GART TBL walk error reporting, which trips off
-			   incorrectly with the IOMMU & 3ware & Cerberus. */
-			clear_bit(10, (unsigned long *)&bank[4]);
-		if(c->x86 <= 17 && mce_bootlog < 0)
-			/* Lots of broken BIOS around that don't clear them
-			   by default and leave crap in there. Don't log. */
-			mce_bootlog = 0;
-	}
-
-}
-
-static void mce_cpu_features(struct cpuinfo_x86 *c)
-{
-	switch (c->x86_vendor) {
-	case X86_VENDOR_INTEL:
-		mce_intel_feature_init(c);
-		break;
-	case X86_VENDOR_AMD:
-		mce_amd_feature_init(c);
-		break;
-	default:
-		break;
-	}
-}
-
-static void mce_init_timer(void)
-{
-	struct timer_list *t = &__get_cpu_var(mce_timer);
-	int *n = &__get_cpu_var(next_interval);
-
-	*n = check_interval * HZ;
-	if (!*n)
-		return;
-	setup_timer(t, mcheck_timer, smp_processor_id());
-	t->expires = round_jiffies(jiffies + *n);
-	add_timer(t);
-}
-
-/*
- * Called for each booted CPU to set up machine checks.
- * Must be called with preempt off.
- */
-void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
-{
-	if (!mce_available(c))
-		return;
-
-	if (mce_cap_init() < 0) {
-		mce_dont_init = 1;
-		return;
-	}
-	mce_cpu_quirks(c);
-
-	mce_init(NULL);
-	mce_cpu_features(c);
-	mce_init_timer();
-}
-
-/*
- * Character device to read and clear the MCE log.
- */
-
-static DEFINE_SPINLOCK(mce_state_lock);
-static int open_count;	/* #times opened */
-static int open_exclu;	/* already open exclusive? */
-
-static int mce_open(struct inode *inode, struct file *file)
-{
-	lock_kernel();
-	spin_lock(&mce_state_lock);
-
-	if (open_exclu || (open_count && (file->f_flags & O_EXCL))) {
-		spin_unlock(&mce_state_lock);
-		unlock_kernel();
-		return -EBUSY;
-	}
-
-	if (file->f_flags & O_EXCL)
-		open_exclu = 1;
-	open_count++;
-
-	spin_unlock(&mce_state_lock);
-	unlock_kernel();
-
-	return nonseekable_open(inode, file);
-}
-
-static int mce_release(struct inode *inode, struct file *file)
-{
-	spin_lock(&mce_state_lock);
-
-	open_count--;
-	open_exclu = 0;
-
-	spin_unlock(&mce_state_lock);
-
-	return 0;
-}
-
-static void collect_tscs(void *data)
-{
-	unsigned long *cpu_tsc = (unsigned long *)data;
-
-	rdtscll(cpu_tsc[smp_processor_id()]);
-}
-
-static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
-			loff_t *off)
-{
-	unsigned long *cpu_tsc;
-	static DEFINE_MUTEX(mce_read_mutex);
-	unsigned prev, next;
-	char __user *buf = ubuf;
-	int i, err;
-
-	cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL);
-	if (!cpu_tsc)
-		return -ENOMEM;
-
-	mutex_lock(&mce_read_mutex);
-	next = rcu_dereference(mcelog.next);
-
-	/* Only supports full reads right now */
-	if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) {
-		mutex_unlock(&mce_read_mutex);
-		kfree(cpu_tsc);
-		return -EINVAL;
-	}
-
-	err = 0;
-	prev = 0;
-	do {
-		for (i = prev; i < next; i++) {
-			unsigned long start = jiffies;
-
-			while (!mcelog.entry[i].finished) {
-				if (time_after_eq(jiffies, start + 2)) {
-					memset(mcelog.entry + i, 0,
-					       sizeof(struct mce));
-					goto timeout;
-				}
-				cpu_relax();
-			}
-			smp_rmb();
-			err |= copy_to_user(buf, mcelog.entry + i,
-					    sizeof(struct mce));
-			buf += sizeof(struct mce);
-timeout:
-			;
-		}
-
-		memset(mcelog.entry + prev, 0,
-		       (next - prev) * sizeof(struct mce));
-		prev = next;
-		next = cmpxchg(&mcelog.next, prev, 0);
-	} while (next != prev);
-
-	synchronize_sched();
-
-	/*
-	 * Collect entries that were still getting written before the
-	 * synchronize.
-	 */
-	on_each_cpu(collect_tscs, cpu_tsc, 1);
-	for (i = next; i < MCE_LOG_LEN; i++) {
-		if (mcelog.entry[i].finished &&
-		    mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) {
-			err |= copy_to_user(buf, mcelog.entry+i,
-					    sizeof(struct mce));
-			smp_rmb();
-			buf += sizeof(struct mce);
-			memset(&mcelog.entry[i], 0, sizeof(struct mce));
-		}
-	}
-	mutex_unlock(&mce_read_mutex);
-	kfree(cpu_tsc);
-	return err ? -EFAULT : buf - ubuf;
-}
-
-static unsigned int mce_poll(struct file *file, poll_table *wait)
-{
-	poll_wait(file, &mce_wait, wait);
-	if (rcu_dereference(mcelog.next))
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
-	int __user *p = (int __user *)arg;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	switch (cmd) {
-	case MCE_GET_RECORD_LEN:
-		return put_user(sizeof(struct mce), p);
-	case MCE_GET_LOG_LEN:
-		return put_user(MCE_LOG_LEN, p);
-	case MCE_GETCLEAR_FLAGS: {
-		unsigned flags;
-
-		do {
-			flags = mcelog.flags;
-		} while (cmpxchg(&mcelog.flags, flags, 0) != flags);
-		return put_user(flags, p);
-	}
-	default:
-		return -ENOTTY;
-	}
-}
-
-static const struct file_operations mce_chrdev_ops = {
-	.open = mce_open,
-	.release = mce_release,
-	.read = mce_read,
-	.poll = mce_poll,
-	.unlocked_ioctl = mce_ioctl,
-};
-
-static struct miscdevice mce_log_device = {
-	MISC_MCELOG_MINOR,
-	"mcelog",
-	&mce_chrdev_ops,
-};
-
-/*
- * Old style boot options parsing. Only for compatibility.
- */
-static int __init mcheck_disable(char *str)
-{
-	mce_dont_init = 1;
-	return 1;
-}
-
-/* mce=off disables machine check.
-   mce=TOLERANCELEVEL (number, see above)
-   mce=bootlog Log MCEs from before booting. Disabled by default on AMD.
-   mce=nobootlog Don't log MCEs from before booting. */
-static int __init mcheck_enable(char *str)
-{
-	if (!strcmp(str, "off"))
-		mce_dont_init = 1;
-	else if (!strcmp(str, "bootlog") || !strcmp(str,"nobootlog"))
-		mce_bootlog = str[0] == 'b';
-	else if (isdigit(str[0]))
-		get_option(&str, &tolerant);
-	else
-		printk("mce= argument %s ignored. Please use /sys", str);
-	return 1;
-}
-
-__setup("nomce", mcheck_disable);
-__setup("mce=", mcheck_enable);
-
-/*
- * Sysfs support
- */
-
-/*
- * Disable machine checks on suspend and shutdown. We can't really handle
- * them later.
- */
-static int mce_disable(void)
-{
-	int i;
-
-	for (i = 0; i < banks; i++)
-		wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
-	return 0;
-}
-
-static int mce_suspend(struct sys_device *dev, pm_message_t state)
-{
-	return mce_disable();
-}
-
-static int mce_shutdown(struct sys_device *dev)
-{
-	return mce_disable();
-}
-
-/* On resume clear all MCE state. Don't want to see leftovers from the BIOS.
-   Only one CPU is active at this time, the others get readded later using
-   CPU hotplug. */
-static int mce_resume(struct sys_device *dev)
-{
-	mce_init(NULL);
-	mce_cpu_features(&current_cpu_data);
-	return 0;
-}
-
-static void mce_cpu_restart(void *data)
-{
-	del_timer_sync(&__get_cpu_var(mce_timer));
-	if (mce_available(&current_cpu_data))
-		mce_init(NULL);
-	mce_init_timer();
-}
-
-/* Reinit MCEs after user configuration changes */
-static void mce_restart(void)
-{
-	on_each_cpu(mce_cpu_restart, NULL, 1);
-}
-
-static struct sysdev_class mce_sysclass = {
-	.suspend = mce_suspend,
-	.shutdown = mce_shutdown,
-	.resume = mce_resume,
-	.name = "machinecheck",
-};
-
-DEFINE_PER_CPU(struct sys_device, device_mce);
-void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu) __cpuinitdata;
-
-/* Why are there no generic functions for this? */
-#define ACCESSOR(name, var, start) \
-	static ssize_t show_ ## name(struct sys_device *s,		\
-				     struct sysdev_attribute *attr,	\
-				     char *buf) {			\
-		return sprintf(buf, "%lx\n", (unsigned long)var);	\
-	}								\
-	static ssize_t set_ ## name(struct sys_device *s,		\
-				    struct sysdev_attribute *attr,	\
-				    const char *buf, size_t siz) {	\
-		char *end;						\
-		unsigned long new = simple_strtoul(buf, &end, 0);	\
-		if (end == buf) return -EINVAL;				\
-		var = new;						\
-		start;							\
-		return end-buf;						\
-	}								\
-	static SYSDEV_ATTR(name, 0644, show_ ## name, set_ ## name);
-
-static struct sysdev_attribute *bank_attrs;
-
-static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr,
-			 char *buf)
-{
-	u64 b = bank[attr - bank_attrs];
-	return sprintf(buf, "%llx\n", b);
-}
-
-static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
-			const char *buf, size_t siz)
-{
-	char *end;
-	u64 new = simple_strtoull(buf, &end, 0);
-	if (end == buf)
-		return -EINVAL;
-	bank[attr - bank_attrs] = new;
-	mce_restart();
-	return end-buf;
-}
-
-static ssize_t show_trigger(struct sys_device *s, struct sysdev_attribute *attr,
-				char *buf)
-{
-	strcpy(buf, trigger);
-	strcat(buf, "\n");
-	return strlen(trigger) + 1;
-}
-
-static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
-				const char *buf,size_t siz)
-{
-	char *p;
-	int len;
-	strncpy(trigger, buf, sizeof(trigger));
-	trigger[sizeof(trigger)-1] = 0;
-	len = strlen(trigger);
-	p = strchr(trigger, '\n');
-	if (*p) *p = 0;
-	return len;
-}
-
-static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
-static SYSDEV_INT_ATTR(tolerant, 0644, tolerant);
-ACCESSOR(check_interval,check_interval,mce_restart())
-static struct sysdev_attribute *mce_attributes[] = {
-	&attr_tolerant.attr, &attr_check_interval, &attr_trigger,
-	NULL
-};
-
-static cpumask_var_t mce_device_initialized;
-
-/* Per cpu sysdev init.  All of the cpus still share the same ctl bank */
-static __cpuinit int mce_create_device(unsigned int cpu)
-{
-	int err;
-	int i;
-
-	if (!mce_available(&boot_cpu_data))
-		return -EIO;
-
-	memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
-	per_cpu(device_mce,cpu).id = cpu;
-	per_cpu(device_mce,cpu).cls = &mce_sysclass;
-
-	err = sysdev_register(&per_cpu(device_mce,cpu));
-	if (err)
-		return err;
-
-	for (i = 0; mce_attributes[i]; i++) {
-		err = sysdev_create_file(&per_cpu(device_mce,cpu),
-					 mce_attributes[i]);
-		if (err)
-			goto error;
-	}
-	for (i = 0; i < banks; i++) {
-		err = sysdev_create_file(&per_cpu(device_mce, cpu),
-					&bank_attrs[i]);
-		if (err)
-			goto error2;
-	}
-	cpumask_set_cpu(cpu, mce_device_initialized);
-
-	return 0;
-error2:
-	while (--i >= 0) {
-		sysdev_remove_file(&per_cpu(device_mce, cpu),
-					&bank_attrs[i]);
-	}
-error:
-	while (--i >= 0) {
-		sysdev_remove_file(&per_cpu(device_mce,cpu),
-				   mce_attributes[i]);
-	}
-	sysdev_unregister(&per_cpu(device_mce,cpu));
-
-	return err;
-}
-
-static __cpuinit void mce_remove_device(unsigned int cpu)
-{
-	int i;
-
-	if (!cpumask_test_cpu(cpu, mce_device_initialized))
-		return;
-
-	for (i = 0; mce_attributes[i]; i++)
-		sysdev_remove_file(&per_cpu(device_mce,cpu),
-			mce_attributes[i]);
-	for (i = 0; i < banks; i++)
-		sysdev_remove_file(&per_cpu(device_mce, cpu),
-			&bank_attrs[i]);
-	sysdev_unregister(&per_cpu(device_mce,cpu));
-	cpumask_clear_cpu(cpu, mce_device_initialized);
-}
-
-/* Make sure there are no machine checks on offlined CPUs. */
-static void mce_disable_cpu(void *h)
-{
-	int i;
-	unsigned long action = *(unsigned long *)h;
-
-	if (!mce_available(&current_cpu_data))
-		return;
-	if (!(action & CPU_TASKS_FROZEN))
-		cmci_clear();
-	for (i = 0; i < banks; i++)
-		wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
-}
-
-static void mce_reenable_cpu(void *h)
-{
-	int i;
-	unsigned long action = *(unsigned long *)h;
-
-	if (!mce_available(&current_cpu_data))
-		return;
-	if (!(action & CPU_TASKS_FROZEN))
-		cmci_reenable();
-	for (i = 0; i < banks; i++)
-		wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
-}
-
-/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static int __cpuinit mce_cpu_callback(struct notifier_block *nfb,
-				      unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long)hcpu;
-	struct timer_list *t = &per_cpu(mce_timer, cpu);
-
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		mce_create_device(cpu);
-		if (threshold_cpu_callback)
-			threshold_cpu_callback(action, cpu);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		if (threshold_cpu_callback)
-			threshold_cpu_callback(action, cpu);
-		mce_remove_device(cpu);
-		break;
-	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
-		del_timer_sync(t);
-		smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
-		break;
-	case CPU_DOWN_FAILED:
-	case CPU_DOWN_FAILED_FROZEN:
-		t->expires = round_jiffies(jiffies +
-						__get_cpu_var(next_interval));
-		add_timer_on(t, cpu);
-		smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
-		break;
-	case CPU_POST_DEAD:
-		/* intentionally ignoring frozen here */
-		cmci_rediscover(cpu);
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block mce_cpu_notifier __cpuinitdata = {
-	.notifier_call = mce_cpu_callback,
-};
-
-static __init int mce_init_banks(void)
-{
-	int i;
-
-	bank_attrs = kzalloc(sizeof(struct sysdev_attribute) * banks,
-				GFP_KERNEL);
-	if (!bank_attrs)
-		return -ENOMEM;
-
-	for (i = 0; i < banks; i++) {
-		struct sysdev_attribute *a = &bank_attrs[i];
-		a->attr.name = kasprintf(GFP_KERNEL, "bank%d", i);
-		if (!a->attr.name)
-			goto nomem;
-		a->attr.mode = 0644;
-		a->show = show_bank;
-		a->store = set_bank;
-	}
-	return 0;
-
-nomem:
-	while (--i >= 0)
-		kfree(bank_attrs[i].attr.name);
-	kfree(bank_attrs);
-	bank_attrs = NULL;
-	return -ENOMEM;
-}
-
-static __init int mce_init_device(void)
-{
-	int err;
-	int i = 0;
-
-	if (!mce_available(&boot_cpu_data))
-		return -EIO;
-
-	zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL);
-
-	err = mce_init_banks();
-	if (err)
-		return err;
-
-	err = sysdev_class_register(&mce_sysclass);
-	if (err)
-		return err;
-
-	for_each_online_cpu(i) {
-		err = mce_create_device(i);
-		if (err)
-			return err;
-	}
-
-	register_hotcpu_notifier(&mce_cpu_notifier);
-	misc_register(&mce_log_device);
-	return err;
-}
-
-device_initcall(mce_init_device);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_amd_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_amd_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_amd_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,696 +0,0 @@
-/*
- *  (c) 2005, 2006 Advanced Micro Devices, Inc.
- *  Your use of this code is subject to the terms and conditions of the
- *  GNU general public license version 2. See "COPYING" or
- *  http://www.gnu.org/licenses/gpl.html
- *
- *  Written by Jacob Shin - AMD, Inc.
- *
- *  Support : jacob.shin@amd.com
- *
- *  April 2006
- *     - added support for AMD Family 0x10 processors
- *
- *  All MC4_MISCi registers are shared between multi-cores
- */
-
-#include <linux/cpu.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kobject.h>
-#include <linux/notifier.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/sysdev.h>
-#include <linux/sysfs.h>
-#include <asm/apic.h>
-#include <asm/mce.h>
-#include <asm/msr.h>
-#include <asm/percpu.h>
-#include <asm/idle.h>
-
-#define PFX               "mce_threshold: "
-#define VERSION           "version 1.1.1"
-#define NR_BANKS          6
-#define NR_BLOCKS         9
-#define THRESHOLD_MAX     0xFFF
-#define INT_TYPE_APIC     0x00020000
-#define MASK_VALID_HI     0x80000000
-#define MASK_CNTP_HI      0x40000000
-#define MASK_LOCKED_HI    0x20000000
-#define MASK_LVTOFF_HI    0x00F00000
-#define MASK_COUNT_EN_HI  0x00080000
-#define MASK_INT_TYPE_HI  0x00060000
-#define MASK_OVERFLOW_HI  0x00010000
-#define MASK_ERR_COUNT_HI 0x00000FFF
-#define MASK_BLKPTR_LO    0xFF000000
-#define MCG_XBLK_ADDR     0xC0000400
-
-struct threshold_block {
-	unsigned int block;
-	unsigned int bank;
-	unsigned int cpu;
-	u32 address;
-	u16 interrupt_enable;
-	u16 threshold_limit;
-	struct kobject kobj;
-	struct list_head miscj;
-};
-
-/* defaults used early on boot */
-static struct threshold_block threshold_defaults = {
-	.interrupt_enable = 0,
-	.threshold_limit = THRESHOLD_MAX,
-};
-
-struct threshold_bank {
-	struct kobject *kobj;
-	struct threshold_block *blocks;
-	cpumask_var_t cpus;
-};
-static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]);
-
-#ifdef CONFIG_SMP
-static unsigned char shared_bank[NR_BANKS] = {
-	0, 0, 0, 0, 1
-};
-#endif
-
-static DEFINE_PER_CPU(unsigned char, bank_map);	/* see which banks are on */
-
-static void amd_threshold_interrupt(void);
-
-/*
- * CPU Initialization
- */
-
-struct thresh_restart {
-	struct threshold_block *b;
-	int reset;
-	u16 old_limit;
-};
-
-/* must be called with correct cpu affinity */
-/* Called via smp_call_function_single() */
-static void threshold_restart_bank(void *_tr)
-{
-	struct thresh_restart *tr = _tr;
-	u32 mci_misc_hi, mci_misc_lo;
-
-	rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
-
-	if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
-		tr->reset = 1;	/* limit cannot be lower than err count */
-
-	if (tr->reset) {		/* reset err count and overflow bit */
-		mci_misc_hi =
-		    (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
-		    (THRESHOLD_MAX - tr->b->threshold_limit);
-	} else if (tr->old_limit) {	/* change limit w/o reset */
-		int new_count = (mci_misc_hi & THRESHOLD_MAX) +
-		    (tr->old_limit - tr->b->threshold_limit);
-		mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) |
-		    (new_count & THRESHOLD_MAX);
-	}
-
-	tr->b->interrupt_enable ?
-	    (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
-	    (mci_misc_hi &= ~MASK_INT_TYPE_HI);
-
-	mci_misc_hi |= MASK_COUNT_EN_HI;
-	wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
-}
-
-/* cpu init entry point, called from mce.c with preempt off */
-void mce_amd_feature_init(struct cpuinfo_x86 *c)
-{
-	unsigned int bank, block;
-	unsigned int cpu = smp_processor_id();
-	u8 lvt_off;
-	u32 low = 0, high = 0, address = 0;
-	struct thresh_restart tr;
-
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		for (block = 0; block < NR_BLOCKS; ++block) {
-			if (block == 0)
-				address = MSR_IA32_MC0_MISC + bank * 4;
-			else if (block == 1) {
-				address = (low & MASK_BLKPTR_LO) >> 21;
-				if (!address)
-					break;
-				address += MCG_XBLK_ADDR;
-			}
-			else
-				++address;
-
-			if (rdmsr_safe(address, &low, &high))
-				break;
-
-			if (!(high & MASK_VALID_HI)) {
-				if (block)
-					continue;
-				else
-					break;
-			}
-
-			if (!(high & MASK_CNTP_HI)  ||
-			     (high & MASK_LOCKED_HI))
-				continue;
-
-			if (!block)
-				per_cpu(bank_map, cpu) |= (1 << bank);
-#ifdef CONFIG_SMP
-			if (shared_bank[bank] && c->cpu_core_id)
-				break;
-#endif
-			lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
-						       APIC_EILVT_MSG_FIX, 0);
-
-			high &= ~MASK_LVTOFF_HI;
-			high |= lvt_off << 20;
-			wrmsr(address, low, high);
-
-			threshold_defaults.address = address;
-			tr.b = &threshold_defaults;
-			tr.reset = 0;
-			tr.old_limit = 0;
-			threshold_restart_bank(&tr);
-
-			mce_threshold_vector = amd_threshold_interrupt;
-		}
-	}
-}
-
-/*
- * APIC Interrupt Handler
- */
-
-/*
- * threshold interrupt handler will service THRESHOLD_APIC_VECTOR.
- * the interrupt goes off when error_count reaches threshold_limit.
- * the handler will simply log mcelog w/ software defined bank number.
- */
-static void amd_threshold_interrupt(void)
-{
-	unsigned int bank, block;
-	struct mce m;
-	u32 low = 0, high = 0, address = 0;
-
-	mce_setup(&m);
-
-	/* assume first bank caused it */
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
-			continue;
-		for (block = 0; block < NR_BLOCKS; ++block) {
-			if (block == 0)
-				address = MSR_IA32_MC0_MISC + bank * 4;
-			else if (block == 1) {
-				address = (low & MASK_BLKPTR_LO) >> 21;
-				if (!address)
-					break;
-				address += MCG_XBLK_ADDR;
-			}
-			else
-				++address;
-
-			if (rdmsr_safe(address, &low, &high))
-				break;
-
-			if (!(high & MASK_VALID_HI)) {
-				if (block)
-					continue;
-				else
-					break;
-			}
-
-			if (!(high & MASK_CNTP_HI)  ||
-			     (high & MASK_LOCKED_HI))
-				continue;
-
-			/* Log the machine check that caused the threshold
-			   event. */
-			machine_check_poll(MCP_TIMESTAMP,
-					&__get_cpu_var(mce_poll_banks));
-
-			if (high & MASK_OVERFLOW_HI) {
-				rdmsrl(address, m.misc);
-				rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
-				       m.status);
-				m.bank = K8_MCE_THRESHOLD_BASE
-				       + bank * NR_BLOCKS
-				       + block;
-				mce_log(&m);
-				return;
-			}
-		}
-	}
-}
-
-/*
- * Sysfs Interface
- */
-
-struct threshold_attr {
-	struct attribute attr;
-	ssize_t(*show) (struct threshold_block *, char *);
-	ssize_t(*store) (struct threshold_block *, const char *, size_t count);
-};
-
-#define SHOW_FIELDS(name)                                           \
-static ssize_t show_ ## name(struct threshold_block * b, char *buf) \
-{                                                                   \
-        return sprintf(buf, "%lx\n", (unsigned long) b->name);      \
-}
-SHOW_FIELDS(interrupt_enable)
-SHOW_FIELDS(threshold_limit)
-
-static ssize_t store_interrupt_enable(struct threshold_block *b,
-				      const char *buf, size_t count)
-{
-	char *end;
-	struct thresh_restart tr;
-	unsigned long new = simple_strtoul(buf, &end, 0);
-	if (end == buf)
-		return -EINVAL;
-	b->interrupt_enable = !!new;
-
-	tr.b = b;
-	tr.reset = 0;
-	tr.old_limit = 0;
-	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-
-	return end - buf;
-}
-
-static ssize_t store_threshold_limit(struct threshold_block *b,
-				     const char *buf, size_t count)
-{
-	char *end;
-	struct thresh_restart tr;
-	unsigned long new = simple_strtoul(buf, &end, 0);
-	if (end == buf)
-		return -EINVAL;
-	if (new > THRESHOLD_MAX)
-		new = THRESHOLD_MAX;
-	if (new < 1)
-		new = 1;
-	tr.old_limit = b->threshold_limit;
-	b->threshold_limit = new;
-	tr.b = b;
-	tr.reset = 0;
-
-	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-
-	return end - buf;
-}
-
-struct threshold_block_cross_cpu {
-	struct threshold_block *tb;
-	long retval;
-};
-
-static void local_error_count_handler(void *_tbcc)
-{
-	struct threshold_block_cross_cpu *tbcc = _tbcc;
-	struct threshold_block *b = tbcc->tb;
-	u32 low, high;
-
-	rdmsr(b->address, low, high);
-	tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
-}
-
-static ssize_t show_error_count(struct threshold_block *b, char *buf)
-{
-	struct threshold_block_cross_cpu tbcc = { .tb = b, };
-
-	smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1);
-	return sprintf(buf, "%lx\n", tbcc.retval);
-}
-
-static ssize_t store_error_count(struct threshold_block *b,
-				 const char *buf, size_t count)
-{
-	struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
-
-	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-	return 1;
-}
-
-#define THRESHOLD_ATTR(_name,_mode,_show,_store) {            \
-        .attr = {.name = __stringify(_name), .mode = _mode }, \
-        .show = _show,                                        \
-        .store = _store,                                      \
-};
-
-#define RW_ATTR(name)                                           \
-static struct threshold_attr name =                             \
-        THRESHOLD_ATTR(name, 0644, show_## name, store_## name)
-
-RW_ATTR(interrupt_enable);
-RW_ATTR(threshold_limit);
-RW_ATTR(error_count);
-
-static struct attribute *default_attrs[] = {
-	&interrupt_enable.attr,
-	&threshold_limit.attr,
-	&error_count.attr,
-	NULL
-};
-
-#define to_block(k) container_of(k, struct threshold_block, kobj)
-#define to_attr(a) container_of(a, struct threshold_attr, attr)
-
-static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
-{
-	struct threshold_block *b = to_block(kobj);
-	struct threshold_attr *a = to_attr(attr);
-	ssize_t ret;
-	ret = a->show ? a->show(b, buf) : -EIO;
-	return ret;
-}
-
-static ssize_t store(struct kobject *kobj, struct attribute *attr,
-		     const char *buf, size_t count)
-{
-	struct threshold_block *b = to_block(kobj);
-	struct threshold_attr *a = to_attr(attr);
-	ssize_t ret;
-	ret = a->store ? a->store(b, buf, count) : -EIO;
-	return ret;
-}
-
-static struct sysfs_ops threshold_ops = {
-	.show = show,
-	.store = store,
-};
-
-static struct kobj_type threshold_ktype = {
-	.sysfs_ops = &threshold_ops,
-	.default_attrs = default_attrs,
-};
-
-static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
-					       unsigned int bank,
-					       unsigned int block,
-					       u32 address)
-{
-	int err;
-	u32 low, high;
-	struct threshold_block *b = NULL;
-
-	if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
-		return 0;
-
-	if (rdmsr_safe_on_cpu(cpu, address, &low, &high))
-		return 0;
-
-	if (!(high & MASK_VALID_HI)) {
-		if (block)
-			goto recurse;
-		else
-			return 0;
-	}
-
-	if (!(high & MASK_CNTP_HI)  ||
-	     (high & MASK_LOCKED_HI))
-		goto recurse;
-
-	b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	b->block = block;
-	b->bank = bank;
-	b->cpu = cpu;
-	b->address = address;
-	b->interrupt_enable = 0;
-	b->threshold_limit = THRESHOLD_MAX;
-
-	INIT_LIST_HEAD(&b->miscj);
-
-	if (per_cpu(threshold_banks, cpu)[bank]->blocks)
-		list_add(&b->miscj,
-			 &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
-	else
-		per_cpu(threshold_banks, cpu)[bank]->blocks = b;
-
-	err = kobject_init_and_add(&b->kobj, &threshold_ktype,
-				   per_cpu(threshold_banks, cpu)[bank]->kobj,
-				   "misc%i", block);
-	if (err)
-		goto out_free;
-recurse:
-	if (!block) {
-		address = (low & MASK_BLKPTR_LO) >> 21;
-		if (!address)
-			return 0;
-		address += MCG_XBLK_ADDR;
-	} else
-		++address;
-
-	err = allocate_threshold_blocks(cpu, bank, ++block, address);
-	if (err)
-		goto out_free;
-
-	if (b)
-		kobject_uevent(&b->kobj, KOBJ_ADD);
-
-	return err;
-
-out_free:
-	if (b) {
-		kobject_put(&b->kobj);
-		kfree(b);
-	}
-	return err;
-}
-
-static __cpuinit long
-local_allocate_threshold_blocks(int cpu, unsigned int bank)
-{
-	return allocate_threshold_blocks(cpu, bank, 0,
-					 MSR_IA32_MC0_MISC + bank * 4);
-}
-
-/* symlinks sibling shared banks to first core.  first core owns dir/files. */
-static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
-{
-	int i, err = 0;
-	struct threshold_bank *b = NULL;
-	char name[32];
-
-	sprintf(name, "threshold_bank%i", bank);
-
-#ifdef CONFIG_SMP
-	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
-		i = cpumask_first(cpu_core_mask(cpu));
-
-		/* first core not up yet */
-		if (cpu_data(i).cpu_core_id)
-			goto out;
-
-		/* already linked */
-		if (per_cpu(threshold_banks, cpu)[bank])
-			goto out;
-
-		b = per_cpu(threshold_banks, i)[bank];
-
-		if (!b)
-			goto out;
-
-		err = sysfs_create_link(&per_cpu(device_mce, cpu).kobj,
-					b->kobj, name);
-		if (err)
-			goto out;
-
-		cpumask_copy(b->cpus, cpu_core_mask(cpu));
-		per_cpu(threshold_banks, cpu)[bank] = b;
-		goto out;
-	}
-#endif
-
-	b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
-	if (!b) {
-		err = -ENOMEM;
-		goto out;
-	}
-	if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
-		kfree(b);
-		err = -ENOMEM;
-		goto out;
-	}
-
-	b->kobj = kobject_create_and_add(name, &per_cpu(device_mce, cpu).kobj);
-	if (!b->kobj)
-		goto out_free;
-
-#ifndef CONFIG_SMP
-	cpumask_setall(b->cpus);
-#else
-	cpumask_copy(b->cpus, cpu_core_mask(cpu));
-#endif
-
-	per_cpu(threshold_banks, cpu)[bank] = b;
-
-	err = local_allocate_threshold_blocks(cpu, bank);
-	if (err)
-		goto out_free;
-
-	for_each_cpu(i, b->cpus) {
-		if (i == cpu)
-			continue;
-
-		err = sysfs_create_link(&per_cpu(device_mce, i).kobj,
-					b->kobj, name);
-		if (err)
-			goto out;
-
-		per_cpu(threshold_banks, i)[bank] = b;
-	}
-
-	goto out;
-
-out_free:
-	per_cpu(threshold_banks, cpu)[bank] = NULL;
-	free_cpumask_var(b->cpus);
-	kfree(b);
-out:
-	return err;
-}
-
-/* create dir/files for all valid threshold banks */
-static __cpuinit int threshold_create_device(unsigned int cpu)
-{
-	unsigned int bank;
-	int err = 0;
-
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
-			continue;
-		err = threshold_create_bank(cpu, bank);
-		if (err)
-			goto out;
-	}
-out:
-	return err;
-}
-
-/*
- * let's be hotplug friendly.
- * in case of multiple core processors, the first core always takes ownership
- *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
- */
-
-static void deallocate_threshold_block(unsigned int cpu,
-						 unsigned int bank)
-{
-	struct threshold_block *pos = NULL;
-	struct threshold_block *tmp = NULL;
-	struct threshold_bank *head = per_cpu(threshold_banks, cpu)[bank];
-
-	if (!head)
-		return;
-
-	list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
-		kobject_put(&pos->kobj);
-		list_del(&pos->miscj);
-		kfree(pos);
-	}
-
-	kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
-	per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
-}
-
-static void threshold_remove_bank(unsigned int cpu, int bank)
-{
-	int i = 0;
-	struct threshold_bank *b;
-	char name[32];
-
-	b = per_cpu(threshold_banks, cpu)[bank];
-
-	if (!b)
-		return;
-
-	if (!b->blocks)
-		goto free_out;
-
-	sprintf(name, "threshold_bank%i", bank);
-
-#ifdef CONFIG_SMP
-	/* sibling symlink */
-	if (shared_bank[bank] && b->blocks->cpu != cpu) {
-		sysfs_remove_link(&per_cpu(device_mce, cpu).kobj, name);
-		per_cpu(threshold_banks, cpu)[bank] = NULL;
-		return;
-	}
-#endif
-
-	/* remove all sibling symlinks before unregistering */
-	for_each_cpu(i, b->cpus) {
-		if (i == cpu)
-			continue;
-
-		sysfs_remove_link(&per_cpu(device_mce, i).kobj, name);
-		per_cpu(threshold_banks, i)[bank] = NULL;
-	}
-
-	deallocate_threshold_block(cpu, bank);
-
-free_out:
-	kobject_del(b->kobj);
-	kobject_put(b->kobj);
-	free_cpumask_var(b->cpus);
-	kfree(b);
-	per_cpu(threshold_banks, cpu)[bank] = NULL;
-}
-
-static void threshold_remove_device(unsigned int cpu)
-{
-	unsigned int bank;
-
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
-			continue;
-		threshold_remove_bank(cpu, bank);
-	}
-}
-
-/* get notified when a cpu comes on/off */
-static void __cpuinit amd_64_threshold_cpu_callback(unsigned long action,
-						     unsigned int cpu)
-{
-	if (cpu >= NR_CPUS)
-		return;
-
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		threshold_create_device(cpu);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		threshold_remove_device(cpu);
-		break;
-	default:
-		break;
-	}
-}
-
-static __init int threshold_init_device(void)
-{
-	unsigned lcpu = 0;
-
-	/* to hit CPUs online before the notifier is up */
-	for_each_online_cpu(lcpu) {
-		int err = threshold_create_device(lcpu);
-		if (err)
-			return err;
-	}
-	threshold_cpu_callback = amd_64_threshold_cpu_callback;
-	return 0;
-}
-
-device_initcall(threshold_init_device);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,703 @@
+/*
+ *  (c) 2005, 2006 Advanced Micro Devices, Inc.
+ *  Your use of this code is subject to the terms and conditions of the
+ *  GNU general public license version 2. See "COPYING" or
+ *  http://www.gnu.org/licenses/gpl.html
+ *
+ *  Written by Jacob Shin - AMD, Inc.
+ *
+ *  Support : jacob.shin@amd.com
+ *
+ *  April 2006
+ *     - added support for AMD Family 0x10 processors
+ *
+ *  All MC4_MISCi registers are shared between multi-cores
+ */
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/kobject.h>
+#include <linux/percpu.h>
+#include <linux/sysdev.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/sysfs.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+
+#include <asm/apic.h>
+#include <asm/idle.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
+
+#define PFX               "mce_threshold: "
+#define VERSION           "version 1.1.1"
+#define NR_BANKS          6
+#define NR_BLOCKS         9
+#define THRESHOLD_MAX     0xFFF
+#define INT_TYPE_APIC     0x00020000
+#define MASK_VALID_HI     0x80000000
+#define MASK_CNTP_HI      0x40000000
+#define MASK_LOCKED_HI    0x20000000
+#define MASK_LVTOFF_HI    0x00F00000
+#define MASK_COUNT_EN_HI  0x00080000
+#define MASK_INT_TYPE_HI  0x00060000
+#define MASK_OVERFLOW_HI  0x00010000
+#define MASK_ERR_COUNT_HI 0x00000FFF
+#define MASK_BLKPTR_LO    0xFF000000
+#define MCG_XBLK_ADDR     0xC0000400
+
+struct threshold_block {
+	unsigned int		block;
+	unsigned int		bank;
+	unsigned int		cpu;
+	u32			address;
+	u16			interrupt_enable;
+	u16			threshold_limit;
+	struct kobject		kobj;
+	struct list_head	miscj;
+};
+
+/* defaults used early on boot */
+static struct threshold_block threshold_defaults = {
+	.interrupt_enable	= 0,
+	.threshold_limit	= THRESHOLD_MAX,
+};
+
+struct threshold_bank {
+	struct kobject		*kobj;
+	struct threshold_block	*blocks;
+	cpumask_var_t		cpus;
+};
+static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]);
+
+#ifdef CONFIG_SMP
+static unsigned char shared_bank[NR_BANKS] = {
+	0, 0, 0, 0, 1
+};
+#endif
+
+static DEFINE_PER_CPU(unsigned char, bank_map);	/* see which banks are on */
+
+static void amd_threshold_interrupt(void);
+
+/*
+ * CPU Initialization
+ */
+
+struct thresh_restart {
+	struct threshold_block	*b;
+	int			reset;
+	u16			old_limit;
+};
+
+/* must be called with correct cpu affinity */
+/* Called via smp_call_function_single() */
+static void threshold_restart_bank(void *_tr)
+{
+	struct thresh_restart *tr = _tr;
+	u32 mci_misc_hi, mci_misc_lo;
+
+	rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+
+	if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
+		tr->reset = 1;	/* limit cannot be lower than err count */
+
+	if (tr->reset) {		/* reset err count and overflow bit */
+		mci_misc_hi =
+		    (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
+		    (THRESHOLD_MAX - tr->b->threshold_limit);
+	} else if (tr->old_limit) {	/* change limit w/o reset */
+		int new_count = (mci_misc_hi & THRESHOLD_MAX) +
+		    (tr->old_limit - tr->b->threshold_limit);
+
+		mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) |
+		    (new_count & THRESHOLD_MAX);
+	}
+
+	tr->b->interrupt_enable ?
+	    (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
+	    (mci_misc_hi &= ~MASK_INT_TYPE_HI);
+
+	mci_misc_hi |= MASK_COUNT_EN_HI;
+	wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+}
+
+/* cpu init entry point, called from mce.c with preempt off */
+void mce_amd_feature_init(struct cpuinfo_x86 *c)
+{
+	unsigned int cpu = smp_processor_id();
+	u32 low = 0, high = 0, address = 0;
+	unsigned int bank, block;
+	struct thresh_restart tr;
+	u8 lvt_off;
+
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		for (block = 0; block < NR_BLOCKS; ++block) {
+			if (block == 0)
+				address = MSR_IA32_MC0_MISC + bank * 4;
+			else if (block == 1) {
+				address = (low & MASK_BLKPTR_LO) >> 21;
+				if (!address)
+					break;
+				address += MCG_XBLK_ADDR;
+			} else
+				++address;
+
+			if (rdmsr_safe(address, &low, &high))
+				break;
+
+			if (!(high & MASK_VALID_HI)) {
+				if (block)
+					continue;
+				else
+					break;
+			}
+
+			if (!(high & MASK_CNTP_HI)  ||
+			     (high & MASK_LOCKED_HI))
+				continue;
+
+			if (!block)
+				per_cpu(bank_map, cpu) |= (1 << bank);
+#ifdef CONFIG_SMP
+			if (shared_bank[bank] && c->cpu_core_id)
+				break;
+#endif
+			lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
+						       APIC_EILVT_MSG_FIX, 0);
+
+			high &= ~MASK_LVTOFF_HI;
+			high |= lvt_off << 20;
+			wrmsr(address, low, high);
+
+			threshold_defaults.address = address;
+			tr.b = &threshold_defaults;
+			tr.reset = 0;
+			tr.old_limit = 0;
+			threshold_restart_bank(&tr);
+
+			mce_threshold_vector = amd_threshold_interrupt;
+		}
+	}
+}
+
+/*
+ * APIC Interrupt Handler
+ */
+
+/*
+ * threshold interrupt handler will service THRESHOLD_APIC_VECTOR.
+ * the interrupt goes off when error_count reaches threshold_limit.
+ * the handler will simply log mcelog w/ software defined bank number.
+ */
+static void amd_threshold_interrupt(void)
+{
+	u32 low = 0, high = 0, address = 0;
+	unsigned int bank, block;
+	struct mce m;
+
+	mce_setup(&m);
+
+	/* assume first bank caused it */
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
+			continue;
+		for (block = 0; block < NR_BLOCKS; ++block) {
+			if (block == 0) {
+				address = MSR_IA32_MC0_MISC + bank * 4;
+			} else if (block == 1) {
+				address = (low & MASK_BLKPTR_LO) >> 21;
+				if (!address)
+					break;
+				address += MCG_XBLK_ADDR;
+			} else {
+				++address;
+			}
+
+			if (rdmsr_safe(address, &low, &high))
+				break;
+
+			if (!(high & MASK_VALID_HI)) {
+				if (block)
+					continue;
+				else
+					break;
+			}
+
+			if (!(high & MASK_CNTP_HI)  ||
+			     (high & MASK_LOCKED_HI))
+				continue;
+
+			/*
+			 * Log the machine check that caused the threshold
+			 * event.
+			 */
+			machine_check_poll(MCP_TIMESTAMP,
+					&__get_cpu_var(mce_poll_banks));
+
+			if (high & MASK_OVERFLOW_HI) {
+				rdmsrl(address, m.misc);
+				rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
+				       m.status);
+				m.bank = K8_MCE_THRESHOLD_BASE
+				       + bank * NR_BLOCKS
+				       + block;
+				mce_log(&m);
+				return;
+			}
+		}
+	}
+}
+
+/*
+ * Sysfs Interface
+ */
+
+struct threshold_attr {
+	struct attribute attr;
+	ssize_t (*show) (struct threshold_block *, char *);
+	ssize_t (*store) (struct threshold_block *, const char *, size_t count);
+};
+
+#define SHOW_FIELDS(name)						\
+static ssize_t show_ ## name(struct threshold_block *b, char *buf)	\
+{									\
+	return sprintf(buf, "%lx\n", (unsigned long) b->name);		\
+}
+SHOW_FIELDS(interrupt_enable)
+SHOW_FIELDS(threshold_limit)
+
+static ssize_t
+store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
+{
+	struct thresh_restart tr;
+	unsigned long new;
+
+	if (strict_strtoul(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	b->interrupt_enable = !!new;
+
+	tr.b		= b;
+	tr.reset	= 0;
+	tr.old_limit	= 0;
+
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
+
+	return size;
+}
+
+static ssize_t
+store_threshold_limit(struct threshold_block *b, const char *buf, size_t size)
+{
+	struct thresh_restart tr;
+	unsigned long new;
+
+	if (strict_strtoul(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	if (new > THRESHOLD_MAX)
+		new = THRESHOLD_MAX;
+	if (new < 1)
+		new = 1;
+
+	tr.old_limit = b->threshold_limit;
+	b->threshold_limit = new;
+	tr.b = b;
+	tr.reset = 0;
+
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
+
+	return size;
+}
+
+struct threshold_block_cross_cpu {
+	struct threshold_block	*tb;
+	long			retval;
+};
+
+static void local_error_count_handler(void *_tbcc)
+{
+	struct threshold_block_cross_cpu *tbcc = _tbcc;
+	struct threshold_block *b = tbcc->tb;
+	u32 low, high;
+
+	rdmsr(b->address, low, high);
+	tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
+}
+
+static ssize_t show_error_count(struct threshold_block *b, char *buf)
+{
+	struct threshold_block_cross_cpu tbcc = { .tb = b, };
+
+	smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1);
+	return sprintf(buf, "%lx\n", tbcc.retval);
+}
+
+static ssize_t store_error_count(struct threshold_block *b,
+				 const char *buf, size_t count)
+{
+	struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
+
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
+	return 1;
+}
+
+#define RW_ATTR(val)							\
+static struct threshold_attr val = {					\
+	.attr	= {.name = __stringify(val), .mode = 0644 },		\
+	.show	= show_## val,						\
+	.store	= store_## val,						\
+};
+
+RW_ATTR(interrupt_enable);
+RW_ATTR(threshold_limit);
+RW_ATTR(error_count);
+
+static struct attribute *default_attrs[] = {
+	&interrupt_enable.attr,
+	&threshold_limit.attr,
+	&error_count.attr,
+	NULL
+};
+
+#define to_block(k)	container_of(k, struct threshold_block, kobj)
+#define to_attr(a)	container_of(a, struct threshold_attr, attr)
+
+static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct threshold_block *b = to_block(kobj);
+	struct threshold_attr *a = to_attr(attr);
+	ssize_t ret;
+
+	ret = a->show ? a->show(b, buf) : -EIO;
+
+	return ret;
+}
+
+static ssize_t store(struct kobject *kobj, struct attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct threshold_block *b = to_block(kobj);
+	struct threshold_attr *a = to_attr(attr);
+	ssize_t ret;
+
+	ret = a->store ? a->store(b, buf, count) : -EIO;
+
+	return ret;
+}
+
+static struct sysfs_ops threshold_ops = {
+	.show			= show,
+	.store			= store,
+};
+
+static struct kobj_type threshold_ktype = {
+	.sysfs_ops		= &threshold_ops,
+	.default_attrs		= default_attrs,
+};
+
+static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
+					       unsigned int bank,
+					       unsigned int block,
+					       u32 address)
+{
+	struct threshold_block *b = NULL;
+	u32 low, high;
+	int err;
+
+	if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
+		return 0;
+
+	if (rdmsr_safe_on_cpu(cpu, address, &low, &high))
+		return 0;
+
+	if (!(high & MASK_VALID_HI)) {
+		if (block)
+			goto recurse;
+		else
+			return 0;
+	}
+
+	if (!(high & MASK_CNTP_HI)  ||
+	     (high & MASK_LOCKED_HI))
+		goto recurse;
+
+	b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
+	if (!b)
+		return -ENOMEM;
+
+	b->block		= block;
+	b->bank			= bank;
+	b->cpu			= cpu;
+	b->address		= address;
+	b->interrupt_enable	= 0;
+	b->threshold_limit	= THRESHOLD_MAX;
+
+	INIT_LIST_HEAD(&b->miscj);
+
+	if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
+		list_add(&b->miscj,
+			 &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
+	} else {
+		per_cpu(threshold_banks, cpu)[bank]->blocks = b;
+	}
+
+	err = kobject_init_and_add(&b->kobj, &threshold_ktype,
+				   per_cpu(threshold_banks, cpu)[bank]->kobj,
+				   "misc%i", block);
+	if (err)
+		goto out_free;
+recurse:
+	if (!block) {
+		address = (low & MASK_BLKPTR_LO) >> 21;
+		if (!address)
+			return 0;
+		address += MCG_XBLK_ADDR;
+	} else {
+		++address;
+	}
+
+	err = allocate_threshold_blocks(cpu, bank, ++block, address);
+	if (err)
+		goto out_free;
+
+	if (b)
+		kobject_uevent(&b->kobj, KOBJ_ADD);
+
+	return err;
+
+out_free:
+	if (b) {
+		kobject_put(&b->kobj);
+		kfree(b);
+	}
+	return err;
+}
+
+static __cpuinit long
+local_allocate_threshold_blocks(int cpu, unsigned int bank)
+{
+	return allocate_threshold_blocks(cpu, bank, 0,
+					 MSR_IA32_MC0_MISC + bank * 4);
+}
+
+/* symlinks sibling shared banks to first core.  first core owns dir/files. */
+static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
+{
+	int i, err = 0;
+	struct threshold_bank *b = NULL;
+	char name[32];
+
+	sprintf(name, "threshold_bank%i", bank);
+
+#ifdef CONFIG_SMP
+	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
+		i = cpumask_first(cpu_core_mask(cpu));
+
+		/* first core not up yet */
+		if (cpu_data(i).cpu_core_id)
+			goto out;
+
+		/* already linked */
+		if (per_cpu(threshold_banks, cpu)[bank])
+			goto out;
+
+		b = per_cpu(threshold_banks, i)[bank];
+
+		if (!b)
+			goto out;
+
+		err = sysfs_create_link(&per_cpu(mce_dev, cpu).kobj,
+					b->kobj, name);
+		if (err)
+			goto out;
+
+		cpumask_copy(b->cpus, cpu_core_mask(cpu));
+		per_cpu(threshold_banks, cpu)[bank] = b;
+
+		goto out;
+	}
+#endif
+
+	b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
+	if (!b) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
+		kfree(b);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	b->kobj = kobject_create_and_add(name, &per_cpu(mce_dev, cpu).kobj);
+	if (!b->kobj)
+		goto out_free;
+
+#ifndef CONFIG_SMP
+	cpumask_setall(b->cpus);
+#else
+	cpumask_copy(b->cpus, cpu_core_mask(cpu));
+#endif
+
+	per_cpu(threshold_banks, cpu)[bank] = b;
+
+	err = local_allocate_threshold_blocks(cpu, bank);
+	if (err)
+		goto out_free;
+
+	for_each_cpu(i, b->cpus) {
+		if (i == cpu)
+			continue;
+
+		err = sysfs_create_link(&per_cpu(mce_dev, i).kobj,
+					b->kobj, name);
+		if (err)
+			goto out;
+
+		per_cpu(threshold_banks, i)[bank] = b;
+	}
+
+	goto out;
+
+out_free:
+	per_cpu(threshold_banks, cpu)[bank] = NULL;
+	free_cpumask_var(b->cpus);
+	kfree(b);
+out:
+	return err;
+}
+
+/* create dir/files for all valid threshold banks */
+static __cpuinit int threshold_create_device(unsigned int cpu)
+{
+	unsigned int bank;
+	int err = 0;
+
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
+			continue;
+		err = threshold_create_bank(cpu, bank);
+		if (err)
+			goto out;
+	}
+out:
+	return err;
+}
+
+/*
+ * let's be hotplug friendly.
+ * in case of multiple core processors, the first core always takes ownership
+ *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
+ */
+
+static void deallocate_threshold_block(unsigned int cpu,
+						 unsigned int bank)
+{
+	struct threshold_block *pos = NULL;
+	struct threshold_block *tmp = NULL;
+	struct threshold_bank *head = per_cpu(threshold_banks, cpu)[bank];
+
+	if (!head)
+		return;
+
+	list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
+		kobject_put(&pos->kobj);
+		list_del(&pos->miscj);
+		kfree(pos);
+	}
+
+	kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
+	per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
+}
+
+static void threshold_remove_bank(unsigned int cpu, int bank)
+{
+	struct threshold_bank *b;
+	char name[32];
+	int i = 0;
+
+	b = per_cpu(threshold_banks, cpu)[bank];
+	if (!b)
+		return;
+	if (!b->blocks)
+		goto free_out;
+
+	sprintf(name, "threshold_bank%i", bank);
+
+#ifdef CONFIG_SMP
+	/* sibling symlink */
+	if (shared_bank[bank] && b->blocks->cpu != cpu) {
+		sysfs_remove_link(&per_cpu(mce_dev, cpu).kobj, name);
+		per_cpu(threshold_banks, cpu)[bank] = NULL;
+
+		return;
+	}
+#endif
+
+	/* remove all sibling symlinks before unregistering */
+	for_each_cpu(i, b->cpus) {
+		if (i == cpu)
+			continue;
+
+		sysfs_remove_link(&per_cpu(mce_dev, i).kobj, name);
+		per_cpu(threshold_banks, i)[bank] = NULL;
+	}
+
+	deallocate_threshold_block(cpu, bank);
+
+free_out:
+	kobject_del(b->kobj);
+	kobject_put(b->kobj);
+	free_cpumask_var(b->cpus);
+	kfree(b);
+	per_cpu(threshold_banks, cpu)[bank] = NULL;
+}
+
+static void threshold_remove_device(unsigned int cpu)
+{
+	unsigned int bank;
+
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
+			continue;
+		threshold_remove_bank(cpu, bank);
+	}
+}
+
+/* get notified when a cpu comes on/off */
+static void __cpuinit
+amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu)
+{
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		threshold_create_device(cpu);
+		break;
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
+		threshold_remove_device(cpu);
+		break;
+	default:
+		break;
+	}
+}
+
+static __init int threshold_init_device(void)
+{
+	unsigned lcpu = 0;
+
+	/* to hit CPUs online before the notifier is up */
+	for_each_online_cpu(lcpu) {
+		int err = threshold_create_device(lcpu);
+
+		if (err)
+			return err;
+	}
+	threshold_cpu_callback = amd_64_threshold_cpu_callback;
+
+	return 0;
+}
+device_initcall(threshold_init_device);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2060 @@
+/*
+ * Machine check handler.
+ *
+ * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs.
+ * Rest from unknown author(s).
+ * 2004 Andi Kleen. Rewrote most of it.
+ * Copyright 2008 Intel Corporation
+ * Author: Andi Kleen
+ */
+#include <linux/thread_info.h>
+#include <linux/capability.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/ratelimit.h>
+#include <linux/kallsyms.h>
+#include <linux/rcupdate.h>
+#include <linux/kobject.h>
+#include <linux/uaccess.h>
+#include <linux/kdebug.h>
+#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/sched.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kmod.h>
+#include <linux/poll.h>
+#include <linux/nmi.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/processor.h>
+#include <asm/hw_irq.h>
+#include <asm/apic.h>
+#include <asm/idle.h>
+#include <asm/ipi.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
+
+#include "mce-internal.h"
+
+/* Handle unconfigured int18 (should never happen) */
+static void unexpected_machine_check(struct pt_regs *regs, long error_code)
+{
+	printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
+	       smp_processor_id());
+}
+
+/* Call the installed machine check handler for this CPU setup. */
+void (*machine_check_vector)(struct pt_regs *, long error_code) =
+						unexpected_machine_check;
+
+int mce_disabled __read_mostly;
+
+#ifdef CONFIG_X86_NEW_MCE
+
+#define MISC_MCELOG_MINOR	227
+
+#define SPINUNIT 100	/* 100ns */
+
+atomic_t mce_entry;
+
+DEFINE_PER_CPU(unsigned, mce_exception_count);
+
+/*
+ * Tolerant levels:
+ *   0: always panic on uncorrected errors, log corrected errors
+ *   1: panic or SIGBUS on uncorrected errors, log corrected errors
+ *   2: SIGBUS or log uncorrected errors (if possible), log corrected errors
+ *   3: never panic or SIGBUS, log all errors (for testing only)
+ */
+static int			tolerant		__read_mostly = 1;
+static int			banks			__read_mostly;
+static u64			*bank			__read_mostly;
+static int			rip_msr			__read_mostly;
+static int			mce_bootlog		__read_mostly = -1;
+static int			monarch_timeout		__read_mostly = -1;
+static int			mce_panic_timeout	__read_mostly;
+static int			mce_dont_log_ce		__read_mostly;
+int				mce_cmci_disabled	__read_mostly;
+int				mce_ignore_ce		__read_mostly;
+int				mce_ser			__read_mostly;
+
+/* User mode helper program triggered by machine check event */
+static unsigned long		mce_need_notify;
+static char			mce_helper[128];
+static char			*mce_helper_argv[2] = { mce_helper, NULL };
+
+static unsigned long		dont_init_banks;
+
+static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
+static DEFINE_PER_CPU(struct mce, mces_seen);
+static int			cpu_missing;
+
+
+/* MCA banks polled by the period polling timer for corrected events */
+DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
+	[0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
+};
+
+static inline int skip_bank_init(int i)
+{
+	return i < BITS_PER_LONG && test_bit(i, &dont_init_banks);
+}
+
+static DEFINE_PER_CPU(struct work_struct, mce_work);
+
+/* Do initial initialization of a struct mce */
+void mce_setup(struct mce *m)
+{
+	memset(m, 0, sizeof(struct mce));
+	m->cpu = m->extcpu = smp_processor_id();
+	rdtscll(m->tsc);
+	/* We hope get_seconds stays lockless */
+	m->time = get_seconds();
+	m->cpuvendor = boot_cpu_data.x86_vendor;
+	m->cpuid = cpuid_eax(1);
+#ifdef CONFIG_SMP
+	m->socketid = cpu_data(m->extcpu).phys_proc_id;
+#endif
+	m->apicid = cpu_data(m->extcpu).initial_apicid;
+	rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap);
+}
+
+DEFINE_PER_CPU(struct mce, injectm);
+EXPORT_PER_CPU_SYMBOL_GPL(injectm);
+
+/*
+ * Lockless MCE logging infrastructure.
+ * This avoids deadlocks on printk locks without having to break locks. Also
+ * separate MCEs from kernel messages to avoid bogus bug reports.
+ */
+
+static struct mce_log mcelog = {
+	.signature	= MCE_LOG_SIGNATURE,
+	.len		= MCE_LOG_LEN,
+	.recordlen	= sizeof(struct mce),
+};
+
+void mce_log(struct mce *mce)
+{
+	unsigned next, entry;
+
+	mce->finished = 0;
+	wmb();
+	for (;;) {
+		entry = rcu_dereference(mcelog.next);
+		for (;;) {
+			/*
+			 * When the buffer fills up discard new entries.
+			 * Assume that the earlier errors are the more
+			 * interesting ones:
+			 */
+			if (entry >= MCE_LOG_LEN) {
+				set_bit(MCE_OVERFLOW,
+					(unsigned long *)&mcelog.flags);
+				return;
+			}
+			/* Old left over entry. Skip: */
+			if (mcelog.entry[entry].finished) {
+				entry++;
+				continue;
+			}
+			break;
+		}
+		smp_rmb();
+		next = entry + 1;
+		if (cmpxchg(&mcelog.next, entry, next) == entry)
+			break;
+	}
+	memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
+	wmb();
+	mcelog.entry[entry].finished = 1;
+	wmb();
+
+	mce->finished = 1;
+	set_bit(0, &mce_need_notify);
+}
+
+static void print_mce(struct mce *m)
+{
+	printk(KERN_EMERG
+	       "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
+	       m->extcpu, m->mcgstatus, m->bank, m->status);
+	if (m->ip) {
+		printk(KERN_EMERG "RIP%s %02x:<%016Lx> ",
+		       !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
+		       m->cs, m->ip);
+		if (m->cs == __KERNEL_CS)
+			print_symbol("{%s}", m->ip);
+		printk(KERN_CONT "\n");
+	}
+	printk(KERN_EMERG "TSC %llx ", m->tsc);
+	if (m->addr)
+		printk(KERN_CONT "ADDR %llx ", m->addr);
+	if (m->misc)
+		printk(KERN_CONT "MISC %llx ", m->misc);
+	printk(KERN_CONT "\n");
+	printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
+			m->cpuvendor, m->cpuid, m->time, m->socketid,
+			m->apicid);
+}
+
+static void print_mce_head(void)
+{
+	printk(KERN_EMERG "\nHARDWARE ERROR\n");
+}
+
+static void print_mce_tail(void)
+{
+	printk(KERN_EMERG "This is not a software problem!\n"
+	       "Run through mcelog --ascii to decode and contact your hardware vendor\n");
+}
+
+#define PANIC_TIMEOUT 5 /* 5 seconds */
+
+static atomic_t mce_paniced;
+
+/* Panic in progress. Enable interrupts and wait for final IPI */
+static void wait_for_panic(void)
+{
+	long timeout = PANIC_TIMEOUT*USEC_PER_SEC;
+	preempt_disable();
+	local_irq_enable();
+	while (timeout-- > 0)
+		udelay(1);
+	if (panic_timeout == 0)
+		panic_timeout = mce_panic_timeout;
+	panic("Panicing machine check CPU died");
+}
+
+static void mce_panic(char *msg, struct mce *final, char *exp)
+{
+	int i;
+
+	/*
+	 * Make sure only one CPU runs in machine check panic
+	 */
+	if (atomic_add_return(1, &mce_paniced) > 1)
+		wait_for_panic();
+	barrier();
+
+	bust_spinlocks(1);
+	console_verbose();
+	print_mce_head();
+	/* First print corrected ones that are still unlogged */
+	for (i = 0; i < MCE_LOG_LEN; i++) {
+		struct mce *m = &mcelog.entry[i];
+		if (!(m->status & MCI_STATUS_VAL))
+			continue;
+		if (!(m->status & MCI_STATUS_UC))
+			print_mce(m);
+	}
+	/* Now print uncorrected but with the final one last */
+	for (i = 0; i < MCE_LOG_LEN; i++) {
+		struct mce *m = &mcelog.entry[i];
+		if (!(m->status & MCI_STATUS_VAL))
+			continue;
+		if (!(m->status & MCI_STATUS_UC))
+			continue;
+		if (!final || memcmp(m, final, sizeof(struct mce)))
+			print_mce(m);
+	}
+	if (final)
+		print_mce(final);
+	if (cpu_missing)
+		printk(KERN_EMERG "Some CPUs didn't answer in synchronization\n");
+	print_mce_tail();
+	if (exp)
+		printk(KERN_EMERG "Machine check: %s\n", exp);
+	if (panic_timeout == 0)
+		panic_timeout = mce_panic_timeout;
+	panic(msg);
+}
+
+/* Support code for software error injection */
+
+static int msr_to_offset(u32 msr)
+{
+	unsigned bank = __get_cpu_var(injectm.bank);
+	if (msr == rip_msr)
+		return offsetof(struct mce, ip);
+	if (msr == MSR_IA32_MC0_STATUS + bank*4)
+		return offsetof(struct mce, status);
+	if (msr == MSR_IA32_MC0_ADDR + bank*4)
+		return offsetof(struct mce, addr);
+	if (msr == MSR_IA32_MC0_MISC + bank*4)
+		return offsetof(struct mce, misc);
+	if (msr == MSR_IA32_MCG_STATUS)
+		return offsetof(struct mce, mcgstatus);
+	return -1;
+}
+
+/* MSR access wrappers used for error injection */
+static u64 mce_rdmsrl(u32 msr)
+{
+	u64 v;
+	if (__get_cpu_var(injectm).finished) {
+		int offset = msr_to_offset(msr);
+		if (offset < 0)
+			return 0;
+		return *(u64 *)((char *)&__get_cpu_var(injectm) + offset);
+	}
+	rdmsrl(msr, v);
+	return v;
+}
+
+static void mce_wrmsrl(u32 msr, u64 v)
+{
+	if (__get_cpu_var(injectm).finished) {
+		int offset = msr_to_offset(msr);
+		if (offset >= 0)
+			*(u64 *)((char *)&__get_cpu_var(injectm) + offset) = v;
+		return;
+	}
+	wrmsrl(msr, v);
+}
+
+/*
+ * Simple lockless ring to communicate PFNs from the exception handler with the
+ * process context work function. This is vastly simplified because there's
+ * only a single reader and a single writer.
+ */
+#define MCE_RING_SIZE 16	/* we use one entry less */
+
+struct mce_ring {
+	unsigned short start;
+	unsigned short end;
+	unsigned long ring[MCE_RING_SIZE];
+};
+static DEFINE_PER_CPU(struct mce_ring, mce_ring);
+
+/* Runs with CPU affinity in workqueue */
+static int mce_ring_empty(void)
+{
+	struct mce_ring *r = &__get_cpu_var(mce_ring);
+
+	return r->start == r->end;
+}
+
+static int mce_ring_get(unsigned long *pfn)
+{
+	struct mce_ring *r;
+	int ret = 0;
+
+	*pfn = 0;
+	get_cpu();
+	r = &__get_cpu_var(mce_ring);
+	if (r->start == r->end)
+		goto out;
+	*pfn = r->ring[r->start];
+	r->start = (r->start + 1) % MCE_RING_SIZE;
+	ret = 1;
+out:
+	put_cpu();
+	return ret;
+}
+
+/* Always runs in MCE context with preempt off */
+static int mce_ring_add(unsigned long pfn)
+{
+	struct mce_ring *r = &__get_cpu_var(mce_ring);
+	unsigned next;
+
+	next = (r->end + 1) % MCE_RING_SIZE;
+	if (next == r->start)
+		return -1;
+	r->ring[r->end] = pfn;
+	wmb();
+	r->end = next;
+	return 0;
+}
+
+int mce_available(struct cpuinfo_x86 *c)
+{
+	if (mce_disabled)
+		return 0;
+	return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
+}
+
+static void mce_schedule_work(void)
+{
+	if (!mce_ring_empty()) {
+		struct work_struct *work = &__get_cpu_var(mce_work);
+		if (!work_pending(work))
+			schedule_work(work);
+	}
+}
+
+/*
+ * Get the address of the instruction at the time of the machine check
+ * error.
+ */
+static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
+{
+
+	if (regs && (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV))) {
+		m->ip = regs->ip;
+		m->cs = regs->cs;
+	} else {
+		m->ip = 0;
+		m->cs = 0;
+	}
+	if (rip_msr)
+		m->ip = mce_rdmsrl(rip_msr);
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC 
+/*
+ * Called after interrupts have been reenabled again
+ * when a MCE happened during an interrupts off region
+ * in the kernel.
+ */
+asmlinkage void smp_mce_self_interrupt(struct pt_regs *regs)
+{
+	ack_APIC_irq();
+	exit_idle();
+	irq_enter();
+	mce_notify_irq();
+	mce_schedule_work();
+	irq_exit();
+}
+#endif
+
+static void mce_report_event(struct pt_regs *regs)
+{
+	if (regs->flags & (X86_VM_MASK|X86_EFLAGS_IF)) {
+		mce_notify_irq();
+		/*
+		 * Triggering the work queue here is just an insurance
+		 * policy in case the syscall exit notify handler
+		 * doesn't run soon enough or ends up running on the
+		 * wrong CPU (can happen when audit sleeps)
+		 */
+		mce_schedule_work();
+		return;
+	}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	/*
+	 * Without APIC do not notify. The event will be picked
+	 * up eventually.
+	 */
+	if (!cpu_has_apic)
+		return;
+
+	/*
+	 * When interrupts are disabled we cannot use
+	 * kernel services safely. Trigger an self interrupt
+	 * through the APIC to instead do the notification
+	 * after interrupts are reenabled again.
+	 */
+	apic->send_IPI_self(MCE_SELF_VECTOR);
+
+	/*
+	 * Wait for idle afterwards again so that we don't leave the
+	 * APIC in a non idle state because the normal APIC writes
+	 * cannot exclude us.
+	 */
+	apic_wait_icr_idle();
+#endif
+}
+
+DEFINE_PER_CPU(unsigned, mce_poll_count);
+
+/*
+ * Poll for corrected events or events that happened before reset.
+ * Those are just logged through /dev/mcelog.
+ *
+ * This is executed in standard interrupt context.
+ *
+ * Note: spec recommends to panic for fatal unsignalled
+ * errors here. However this would be quite problematic --
+ * we would need to reimplement the Monarch handling and
+ * it would mess up the exclusion between exception handler
+ * and poll hander -- * so we skip this for now.
+ * These cases should not happen anyways, or only when the CPU
+ * is already totally * confused. In this case it's likely it will
+ * not fully execute the machine check handler either.
+ */
+void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
+{
+	struct mce m;
+	int i;
+
+	__get_cpu_var(mce_poll_count)++;
+
+	mce_setup(&m);
+
+	m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
+	for (i = 0; i < banks; i++) {
+		if (!bank[i] || !test_bit(i, *b))
+			continue;
+
+		m.misc = 0;
+		m.addr = 0;
+		m.bank = i;
+		m.tsc = 0;
+
+		barrier();
+		m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
+		if (!(m.status & MCI_STATUS_VAL))
+			continue;
+
+		/*
+		 * Uncorrected or signalled events are handled by the exception
+		 * handler when it is enabled, so don't process those here.
+		 *
+		 * TBD do the same check for MCI_STATUS_EN here?
+		 */
+		if (!(flags & MCP_UC) &&
+		    (m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)))
+			continue;
+
+		if (m.status & MCI_STATUS_MISCV)
+			m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
+		if (m.status & MCI_STATUS_ADDRV)
+			m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
+
+		if (!(flags & MCP_TIMESTAMP))
+			m.tsc = 0;
+		/*
+		 * Don't get the IP here because it's unlikely to
+		 * have anything to do with the actual error location.
+		 */
+		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) {
+			mce_log(&m);
+			add_taint(TAINT_MACHINE_CHECK);
+		}
+
+		/*
+		 * Clear state for this bank.
+		 */
+		mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+	}
+
+	/*
+	 * Don't clear MCG_STATUS here because it's only defined for
+	 * exceptions.
+	 */
+
+	sync_core();
+}
+EXPORT_SYMBOL_GPL(machine_check_poll);
+
+/*
+ * Do a quick check if any of the events requires a panic.
+ * This decides if we keep the events around or clear them.
+ */
+static int mce_no_way_out(struct mce *m, char **msg)
+{
+	int i;
+
+	for (i = 0; i < banks; i++) {
+		m->status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
+		if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY)
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Variable to establish order between CPUs while scanning.
+ * Each CPU spins initially until executing is equal its number.
+ */
+static atomic_t mce_executing;
+
+/*
+ * Defines order of CPUs on entry. First CPU becomes Monarch.
+ */
+static atomic_t mce_callin;
+
+/*
+ * Check if a timeout waiting for other CPUs happened.
+ */
+static int mce_timed_out(u64 *t)
+{
+	/*
+	 * The others already did panic for some reason.
+	 * Bail out like in a timeout.
+	 * rmb() to tell the compiler that system_state
+	 * might have been modified by someone else.
+	 */
+	rmb();
+	if (atomic_read(&mce_paniced))
+		wait_for_panic();
+	if (!monarch_timeout)
+		goto out;
+	if ((s64)*t < SPINUNIT) {
+		/* CHECKME: Make panic default for 1 too? */
+		if (tolerant < 1)
+			mce_panic("Timeout synchronizing machine check over CPUs",
+				  NULL, NULL);
+		cpu_missing = 1;
+		return 1;
+	}
+	*t -= SPINUNIT;
+out:
+	touch_nmi_watchdog();
+	return 0;
+}
+
+/*
+ * The Monarch's reign.  The Monarch is the CPU who entered
+ * the machine check handler first. It waits for the others to
+ * raise the exception too and then grades them. When any
+ * error is fatal panic. Only then let the others continue.
+ *
+ * The other CPUs entering the MCE handler will be controlled by the
+ * Monarch. They are called Subjects.
+ *
+ * This way we prevent any potential data corruption in a unrecoverable case
+ * and also makes sure always all CPU's errors are examined.
+ *
+ * Also this detects the case of an machine check event coming from outer
+ * space (not detected by any CPUs) In this case some external agent wants
+ * us to shut down, so panic too.
+ *
+ * The other CPUs might still decide to panic if the handler happens
+ * in a unrecoverable place, but in this case the system is in a semi-stable
+ * state and won't corrupt anything by itself. It's ok to let the others
+ * continue for a bit first.
+ *
+ * All the spin loops have timeouts; when a timeout happens a CPU
+ * typically elects itself to be Monarch.
+ */
+static void mce_reign(void)
+{
+	int cpu;
+	struct mce *m = NULL;
+	int global_worst = 0;
+	char *msg = NULL;
+	char *nmsg = NULL;
+
+	/*
+	 * This CPU is the Monarch and the other CPUs have run
+	 * through their handlers.
+	 * Grade the severity of the errors of all the CPUs.
+	 */
+	for_each_possible_cpu(cpu) {
+		int severity = mce_severity(&per_cpu(mces_seen, cpu), tolerant,
+					    &nmsg);
+		if (severity > global_worst) {
+			msg = nmsg;
+			global_worst = severity;
+			m = &per_cpu(mces_seen, cpu);
+		}
+	}
+
+	/*
+	 * Cannot recover? Panic here then.
+	 * This dumps all the mces in the log buffer and stops the
+	 * other CPUs.
+	 */
+	if (m && global_worst >= MCE_PANIC_SEVERITY && tolerant < 3)
+		mce_panic("Fatal Machine check", m, msg);
+
+	/*
+	 * For UC somewhere we let the CPU who detects it handle it.
+	 * Also must let continue the others, otherwise the handling
+	 * CPU could deadlock on a lock.
+	 */
+
+	/*
+	 * No machine check event found. Must be some external
+	 * source or one CPU is hung. Panic.
+	 */
+	if (!m && tolerant < 3)
+		mce_panic("Machine check from unknown source", NULL, NULL);
+
+	/*
+	 * Now clear all the mces_seen so that they don't reappear on
+	 * the next mce.
+	 */
+	for_each_possible_cpu(cpu)
+		memset(&per_cpu(mces_seen, cpu), 0, sizeof(struct mce));
+}
+
+static atomic_t global_nwo;
+
+/*
+ * Start of Monarch synchronization. This waits until all CPUs have
+ * entered the exception handler and then determines if any of them
+ * saw a fatal event that requires panic. Then it executes them
+ * in the entry order.
+ * TBD double check parallel CPU hotunplug
+ */
+static int mce_start(int *no_way_out)
+{
+	int order;
+	int cpus = num_online_cpus();
+	u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
+
+	if (!timeout)
+		return -1;
+
+	atomic_add(*no_way_out, &global_nwo);
+	/*
+	 * global_nwo should be updated before mce_callin
+	 */
+	smp_wmb();
+	order = atomic_add_return(1, &mce_callin);
+
+	/*
+	 * Wait for everyone.
+	 */
+	while (atomic_read(&mce_callin) != cpus) {
+		if (mce_timed_out(&timeout)) {
+			atomic_set(&global_nwo, 0);
+			return -1;
+		}
+		ndelay(SPINUNIT);
+	}
+
+	/*
+	 * mce_callin should be read before global_nwo
+	 */
+	smp_rmb();
+
+	if (order == 1) {
+		/*
+		 * Monarch: Starts executing now, the others wait.
+		 */
+		atomic_set(&mce_executing, 1);
+	} else {
+		/*
+		 * Subject: Now start the scanning loop one by one in
+		 * the original callin order.
+		 * This way when there are any shared banks it will be
+		 * only seen by one CPU before cleared, avoiding duplicates.
+		 */
+		while (atomic_read(&mce_executing) < order) {
+			if (mce_timed_out(&timeout)) {
+				atomic_set(&global_nwo, 0);
+				return -1;
+			}
+			ndelay(SPINUNIT);
+		}
+	}
+
+	/*
+	 * Cache the global no_way_out state.
+	 */
+	*no_way_out = atomic_read(&global_nwo);
+
+	return order;
+}
+
+/*
+ * Synchronize between CPUs after main scanning loop.
+ * This invokes the bulk of the Monarch processing.
+ */
+static int mce_end(int order)
+{
+	int ret = -1;
+	u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
+
+	if (!timeout)
+		goto reset;
+	if (order < 0)
+		goto reset;
+
+	/*
+	 * Allow others to run.
+	 */
+	atomic_inc(&mce_executing);
+
+	if (order == 1) {
+		/* CHECKME: Can this race with a parallel hotplug? */
+		int cpus = num_online_cpus();
+
+		/*
+		 * Monarch: Wait for everyone to go through their scanning
+		 * loops.
+		 */
+		while (atomic_read(&mce_executing) <= cpus) {
+			if (mce_timed_out(&timeout))
+				goto reset;
+			ndelay(SPINUNIT);
+		}
+
+		mce_reign();
+		barrier();
+		ret = 0;
+	} else {
+		/*
+		 * Subject: Wait for Monarch to finish.
+		 */
+		while (atomic_read(&mce_executing) != 0) {
+			if (mce_timed_out(&timeout))
+				goto reset;
+			ndelay(SPINUNIT);
+		}
+
+		/*
+		 * Don't reset anything. That's done by the Monarch.
+		 */
+		return 0;
+	}
+
+	/*
+	 * Reset all global state.
+	 */
+reset:
+	atomic_set(&global_nwo, 0);
+	atomic_set(&mce_callin, 0);
+	barrier();
+
+	/*
+	 * Let others run again.
+	 */
+	atomic_set(&mce_executing, 0);
+	return ret;
+}
+
+/*
+ * Check if the address reported by the CPU is in a format we can parse.
+ * It would be possible to add code for most other cases, but all would
+ * be somewhat complicated (e.g. segment offset would require an instruction
+ * parser). So only support physical addresses upto page granuality for now.
+ */
+static int mce_usable_address(struct mce *m)
+{
+	if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV))
+		return 0;
+	if ((m->misc & 0x3f) > PAGE_SHIFT)
+		return 0;
+	if (((m->misc >> 6) & 7) != MCM_ADDR_PHYS)
+		return 0;
+	return 1;
+}
+
+static void mce_clear_state(unsigned long *toclear)
+{
+	int i;
+
+	for (i = 0; i < banks; i++) {
+		if (test_bit(i, toclear))
+			mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+	}
+}
+
+/*
+ * The actual machine check handler. This only handles real
+ * exceptions when something got corrupted coming in through int 18.
+ *
+ * This is executed in NMI context not subject to normal locking rules. This
+ * implies that most kernel services cannot be safely used. Don't even
+ * think about putting a printk in there!
+ *
+ * On Intel systems this is entered on all CPUs in parallel through
+ * MCE broadcast. However some CPUs might be broken beyond repair,
+ * so be always careful when synchronizing with others.
+ */
+void do_machine_check(struct pt_regs *regs, long error_code)
+{
+	struct mce m, *final;
+	int i;
+	int worst = 0;
+	int severity;
+	/*
+	 * Establish sequential order between the CPUs entering the machine
+	 * check handler.
+	 */
+	int order;
+	/*
+	 * If no_way_out gets set, there is no safe way to recover from this
+	 * MCE.  If tolerant is cranked up, we'll try anyway.
+	 */
+	int no_way_out = 0;
+	/*
+	 * If kill_it gets set, there might be a way to recover from this
+	 * error.
+	 */
+	int kill_it = 0;
+	DECLARE_BITMAP(toclear, MAX_NR_BANKS);
+	char *msg = "Unknown";
+
+	atomic_inc(&mce_entry);
+
+	__get_cpu_var(mce_exception_count)++;
+
+	if (notify_die(DIE_NMI, "machine check", regs, error_code,
+			   18, SIGKILL) == NOTIFY_STOP)
+		goto out;
+	if (!banks)
+		goto out;
+
+	mce_setup(&m);
+
+	m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
+	no_way_out = mce_no_way_out(&m, &msg);
+
+	final = &__get_cpu_var(mces_seen);
+	*final = m;
+
+	barrier();
+
+	/*
+	 * When no restart IP must always kill or panic.
+	 */
+	if (!(m.mcgstatus & MCG_STATUS_RIPV))
+		kill_it = 1;
+
+	/*
+	 * Go through all the banks in exclusion of the other CPUs.
+	 * This way we don't report duplicated events on shared banks
+	 * because the first one to see it will clear it.
+	 */
+	order = mce_start(&no_way_out);
+	for (i = 0; i < banks; i++) {
+		__clear_bit(i, toclear);
+		if (!bank[i])
+			continue;
+
+		m.misc = 0;
+		m.addr = 0;
+		m.bank = i;
+
+		m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
+		if ((m.status & MCI_STATUS_VAL) == 0)
+			continue;
+
+		/*
+		 * Non uncorrected or non signaled errors are handled by
+		 * machine_check_poll. Leave them alone, unless this panics.
+		 */
+		if (!(m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)) &&
+			!no_way_out)
+			continue;
+
+		/*
+		 * Set taint even when machine check was not enabled.
+		 */
+		add_taint(TAINT_MACHINE_CHECK);
+
+		severity = mce_severity(&m, tolerant, NULL);
+
+		/*
+		 * When machine check was for corrected handler don't touch,
+		 * unless we're panicing.
+		 */
+		if (severity == MCE_KEEP_SEVERITY && !no_way_out)
+			continue;
+		__set_bit(i, toclear);
+		if (severity == MCE_NO_SEVERITY) {
+			/*
+			 * Machine check event was not enabled. Clear, but
+			 * ignore.
+			 */
+			continue;
+		}
+
+		/*
+		 * Kill on action required.
+		 */
+		if (severity == MCE_AR_SEVERITY)
+			kill_it = 1;
+
+		if (m.status & MCI_STATUS_MISCV)
+			m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
+		if (m.status & MCI_STATUS_ADDRV)
+			m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
+
+		/*
+		 * Action optional error. Queue address for later processing.
+		 * When the ring overflows we just ignore the AO error.
+		 * RED-PEN add some logging mechanism when
+		 * usable_address or mce_add_ring fails.
+		 * RED-PEN don't ignore overflow for tolerant == 0
+		 */
+		if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
+			mce_ring_add(m.addr >> PAGE_SHIFT);
+
+		mce_get_rip(&m, regs);
+		mce_log(&m);
+
+		if (severity > worst) {
+			*final = m;
+			worst = severity;
+		}
+	}
+
+	if (!no_way_out)
+		mce_clear_state(toclear);
+
+	/*
+	 * Do most of the synchronization with other CPUs.
+	 * When there's any problem use only local no_way_out state.
+	 */
+	if (mce_end(order) < 0)
+		no_way_out = worst >= MCE_PANIC_SEVERITY;
+
+	/*
+	 * If we have decided that we just CAN'T continue, and the user
+	 * has not set tolerant to an insane level, give up and die.
+	 *
+	 * This is mainly used in the case when the system doesn't
+	 * support MCE broadcasting or it has been disabled.
+	 */
+	if (no_way_out && tolerant < 3)
+		mce_panic("Fatal machine check on current CPU", final, msg);
+
+	/*
+	 * If the error seems to be unrecoverable, something should be
+	 * done.  Try to kill as little as possible.  If we can kill just
+	 * one task, do that.  If the user has set the tolerance very
+	 * high, don't try to do anything at all.
+	 */
+
+	if (kill_it && tolerant < 3)
+		force_sig(SIGBUS, current);
+
+	/* notify userspace ASAP */
+	set_thread_flag(TIF_MCE_NOTIFY);
+
+	if (worst > 0)
+		mce_report_event(regs);
+	mce_wrmsrl(MSR_IA32_MCG_STATUS, 0);
+out:
+	atomic_dec(&mce_entry);
+	sync_core();
+}
+EXPORT_SYMBOL_GPL(do_machine_check);
+
+/* dummy to break dependency. actual code is in mm/memory-failure.c */
+void __attribute__((weak)) memory_failure(unsigned long pfn, int vector)
+{
+	printk(KERN_ERR "Action optional memory failure at %lx ignored\n", pfn);
+}
+
+/*
+ * Called after mce notification in process context. This code
+ * is allowed to sleep. Call the high level VM handler to process
+ * any corrupted pages.
+ * Assume that the work queue code only calls this one at a time
+ * per CPU.
+ * Note we don't disable preemption, so this code might run on the wrong
+ * CPU. In this case the event is picked up by the scheduled work queue.
+ * This is merely a fast path to expedite processing in some common
+ * cases.
+ */
+void mce_notify_process(void)
+{
+	unsigned long pfn;
+	mce_notify_irq();
+	while (mce_ring_get(&pfn))
+		memory_failure(pfn, MCE_VECTOR);
+}
+
+static void mce_process_work(struct work_struct *dummy)
+{
+	mce_notify_process();
+}
+
+#ifdef CONFIG_X86_MCE_INTEL
+/***
+ * mce_log_therm_throt_event - Logs the thermal throttling event to mcelog
+ * @cpu: The CPU on which the event occurred.
+ * @status: Event status information
+ *
+ * This function should be called by the thermal interrupt after the
+ * event has been processed and the decision was made to log the event
+ * further.
+ *
+ * The status parameter will be saved to the 'status' field of 'struct mce'
+ * and historically has been the register value of the
+ * MSR_IA32_THERMAL_STATUS (Intel) msr.
+ */
+void mce_log_therm_throt_event(__u64 status)
+{
+	struct mce m;
+
+	mce_setup(&m);
+	m.bank = MCE_THERMAL_BANK;
+	m.status = status;
+	mce_log(&m);
+}
+#endif /* CONFIG_X86_MCE_INTEL */
+
+/*
+ * Periodic polling timer for "silent" machine check errors.  If the
+ * poller finds an MCE, poll 2x faster.  When the poller finds no more
+ * errors, poll 2x slower (up to check_interval seconds).
+ */
+static int check_interval = 5 * 60; /* 5 minutes */
+
+static DEFINE_PER_CPU(int, next_interval); /* in jiffies */
+static DEFINE_PER_CPU(struct timer_list, mce_timer);
+
+static void mcheck_timer(unsigned long data)
+{
+	struct timer_list *t = &per_cpu(mce_timer, data);
+	int *n;
+
+	WARN_ON(smp_processor_id() != data);
+
+	if (mce_available(&current_cpu_data)) {
+		machine_check_poll(MCP_TIMESTAMP,
+				&__get_cpu_var(mce_poll_banks));
+	}
+
+	/*
+	 * Alert userspace if needed.  If we logged an MCE, reduce the
+	 * polling interval, otherwise increase the polling interval.
+	 */
+	n = &__get_cpu_var(next_interval);
+	if (mce_notify_irq())
+		*n = max(*n/2, HZ/100);
+	else
+		*n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ));
+
+	t->expires = jiffies + *n;
+	add_timer_on(t, smp_processor_id());
+}
+
+static void mce_do_trigger(struct work_struct *work)
+{
+	call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT);
+}
+
+static DECLARE_WORK(mce_trigger_work, mce_do_trigger);
+
+/*
+ * Notify the user(s) about new machine check events.
+ * Can be called from interrupt context, but not from machine check/NMI
+ * context.
+ */
+int mce_notify_irq(void)
+{
+	/* Not more than two messages every minute */
+	static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2);
+
+	clear_thread_flag(TIF_MCE_NOTIFY);
+
+	if (test_and_clear_bit(0, &mce_need_notify)) {
+		wake_up_interruptible(&mce_wait);
+
+		/*
+		 * There is no risk of missing notifications because
+		 * work_pending is always cleared before the function is
+		 * executed.
+		 */
+		if (mce_helper[0] && !work_pending(&mce_trigger_work))
+			schedule_work(&mce_trigger_work);
+
+		if (__ratelimit(&ratelimit))
+			printk(KERN_INFO "Machine check events logged\n");
+
+		return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mce_notify_irq);
+
+/*
+ * Initialize Machine Checks for a CPU.
+ */
+static int mce_cap_init(void)
+{
+	unsigned b;
+	u64 cap;
+
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
+
+	b = cap & MCG_BANKCNT_MASK;
+	printk(KERN_INFO "mce: CPU supports %d MCE banks\n", b);
+
+	if (b > MAX_NR_BANKS) {
+		printk(KERN_WARNING
+		       "MCE: Using only %u machine check banks out of %u\n",
+			MAX_NR_BANKS, b);
+		b = MAX_NR_BANKS;
+	}
+
+	/* Don't support asymmetric configurations today */
+	WARN_ON(banks != 0 && b != banks);
+	banks = b;
+	if (!bank) {
+		bank = kmalloc(banks * sizeof(u64), GFP_KERNEL);
+		if (!bank)
+			return -ENOMEM;
+		memset(bank, 0xff, banks * sizeof(u64));
+	}
+
+	/* Use accurate RIP reporting if available. */
+	if ((cap & MCG_EXT_P) && MCG_EXT_CNT(cap) >= 9)
+		rip_msr = MSR_IA32_MCG_EIP;
+
+	if (cap & MCG_SER_P)
+		mce_ser = 1;
+
+	return 0;
+}
+
+static void mce_init(void)
+{
+	mce_banks_t all_banks;
+	u64 cap;
+	int i;
+
+	/*
+	 * Log the machine checks left over from the previous reset.
+	 */
+	bitmap_fill(all_banks, MAX_NR_BANKS);
+	machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks);
+
+	set_in_cr4(X86_CR4_MCE);
+
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
+	if (cap & MCG_CTL_P)
+		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
+
+	for (i = 0; i < banks; i++) {
+		if (skip_bank_init(i))
+			continue;
+		wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
+		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+	}
+}
+
+/* Add per CPU specific workarounds here */
+static int mce_cpu_quirks(struct cpuinfo_x86 *c)
+{
+	if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
+		pr_info("MCE: unknown CPU type - not enabling MCE support.\n");
+		return -EOPNOTSUPP;
+	}
+
+	/* This should be disabled by the BIOS, but isn't always */
+	if (c->x86_vendor == X86_VENDOR_AMD) {
+		if (c->x86 == 15 && banks > 4) {
+			/*
+			 * disable GART TBL walk error reporting, which
+			 * trips off incorrectly with the IOMMU & 3ware
+			 * & Cerberus:
+			 */
+			clear_bit(10, (unsigned long *)&bank[4]);
+		}
+		if (c->x86 <= 17 && mce_bootlog < 0) {
+			/*
+			 * Lots of broken BIOS around that don't clear them
+			 * by default and leave crap in there. Don't log:
+			 */
+			mce_bootlog = 0;
+		}
+		/*
+		 * Various K7s with broken bank 0 around. Always disable
+		 * by default.
+		 */
+		 if (c->x86 == 6 && banks > 0)
+			bank[0] = 0;
+	}
+
+	if (c->x86_vendor == X86_VENDOR_INTEL) {
+		/*
+		 * SDM documents that on family 6 bank 0 should not be written
+		 * because it aliases to another special BIOS controlled
+		 * register.
+		 * But it's not aliased anymore on model 0x1a+
+		 * Don't ignore bank 0 completely because there could be a
+		 * valid event later, merely don't write CTL0.
+		 */
+
+		if (c->x86 == 6 && c->x86_model < 0x1A)
+			__set_bit(0, &dont_init_banks);
+
+		/*
+		 * All newer Intel systems support MCE broadcasting. Enable
+		 * synchronization with a one second timeout.
+		 */
+		if ((c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xe)) &&
+			monarch_timeout < 0)
+			monarch_timeout = USEC_PER_SEC;
+
+		/*
+		 * There are also broken BIOSes on some Pentium M and
+		 * earlier systems:
+		 */
+		if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0)
+			mce_bootlog = 0;
+	}
+	if (monarch_timeout < 0)
+		monarch_timeout = 0;
+	if (mce_bootlog != 0)
+		mce_panic_timeout = 30;
+
+	return 0;
+}
+
+static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c)
+{
+	if (c->x86 != 5)
+		return;
+	switch (c->x86_vendor) {
+	case X86_VENDOR_INTEL:
+		intel_p5_mcheck_init(c);
+		break;
+	case X86_VENDOR_CENTAUR:
+		winchip_mcheck_init(c);
+		break;
+	}
+}
+
+static void mce_cpu_features(struct cpuinfo_x86 *c)
+{
+	switch (c->x86_vendor) {
+	case X86_VENDOR_INTEL:
+		mce_intel_feature_init(c);
+		break;
+	case X86_VENDOR_AMD:
+		mce_amd_feature_init(c);
+		break;
+	default:
+		break;
+	}
+}
+
+static void mce_init_timer(void)
+{
+	struct timer_list *t = &__get_cpu_var(mce_timer);
+	int *n = &__get_cpu_var(next_interval);
+
+	if (mce_ignore_ce)
+		return;
+
+	*n = check_interval * HZ;
+	if (!*n)
+		return;
+	setup_timer(t, mcheck_timer, smp_processor_id());
+	t->expires = round_jiffies(jiffies + *n);
+	add_timer_on(t, smp_processor_id());
+}
+
+/*
+ * Called for each booted CPU to set up machine checks.
+ * Must be called with preempt off:
+ */
+void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
+{
+	if (mce_disabled)
+		return;
+
+	mce_ancient_init(c);
+
+	if (!mce_available(c))
+		return;
+
+	if (mce_cap_init() < 0 || mce_cpu_quirks(c) < 0) {
+		mce_disabled = 1;
+		return;
+	}
+
+	machine_check_vector = do_machine_check;
+
+	mce_init();
+	mce_cpu_features(c);
+	mce_init_timer();
+	INIT_WORK(&__get_cpu_var(mce_work), mce_process_work);
+}
+
+/*
+ * Character device to read and clear the MCE log.
+ */
+
+static DEFINE_SPINLOCK(mce_state_lock);
+static int		open_count;		/* #times opened */
+static int		open_exclu;		/* already open exclusive? */
+
+static int mce_open(struct inode *inode, struct file *file)
+{
+	spin_lock(&mce_state_lock);
+
+	if (open_exclu || (open_count && (file->f_flags & O_EXCL))) {
+		spin_unlock(&mce_state_lock);
+
+		return -EBUSY;
+	}
+
+	if (file->f_flags & O_EXCL)
+		open_exclu = 1;
+	open_count++;
+
+	spin_unlock(&mce_state_lock);
+
+	return nonseekable_open(inode, file);
+}
+
+static int mce_release(struct inode *inode, struct file *file)
+{
+	spin_lock(&mce_state_lock);
+
+	open_count--;
+	open_exclu = 0;
+
+	spin_unlock(&mce_state_lock);
+
+	return 0;
+}
+
+static void collect_tscs(void *data)
+{
+	unsigned long *cpu_tsc = (unsigned long *)data;
+
+	rdtscll(cpu_tsc[smp_processor_id()]);
+}
+
+static DEFINE_MUTEX(mce_read_mutex);
+
+static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
+			loff_t *off)
+{
+	char __user *buf = ubuf;
+	unsigned long *cpu_tsc;
+	unsigned prev, next;
+	int i, err;
+
+	cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL);
+	if (!cpu_tsc)
+		return -ENOMEM;
+
+	mutex_lock(&mce_read_mutex);
+	next = rcu_dereference(mcelog.next);
+
+	/* Only supports full reads right now */
+	if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) {
+		mutex_unlock(&mce_read_mutex);
+		kfree(cpu_tsc);
+
+		return -EINVAL;
+	}
+
+	err = 0;
+	prev = 0;
+	do {
+		for (i = prev; i < next; i++) {
+			unsigned long start = jiffies;
+
+			while (!mcelog.entry[i].finished) {
+				if (time_after_eq(jiffies, start + 2)) {
+					memset(mcelog.entry + i, 0,
+					       sizeof(struct mce));
+					goto timeout;
+				}
+				cpu_relax();
+			}
+			smp_rmb();
+			err |= copy_to_user(buf, mcelog.entry + i,
+					    sizeof(struct mce));
+			buf += sizeof(struct mce);
+timeout:
+			;
+		}
+
+		memset(mcelog.entry + prev, 0,
+		       (next - prev) * sizeof(struct mce));
+		prev = next;
+		next = cmpxchg(&mcelog.next, prev, 0);
+	} while (next != prev);
+
+	synchronize_sched();
+
+	/*
+	 * Collect entries that were still getting written before the
+	 * synchronize.
+	 */
+	on_each_cpu(collect_tscs, cpu_tsc, 1);
+
+	for (i = next; i < MCE_LOG_LEN; i++) {
+		if (mcelog.entry[i].finished &&
+		    mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) {
+			err |= copy_to_user(buf, mcelog.entry+i,
+					    sizeof(struct mce));
+			smp_rmb();
+			buf += sizeof(struct mce);
+			memset(&mcelog.entry[i], 0, sizeof(struct mce));
+		}
+	}
+	mutex_unlock(&mce_read_mutex);
+	kfree(cpu_tsc);
+
+	return err ? -EFAULT : buf - ubuf;
+}
+
+static unsigned int mce_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &mce_wait, wait);
+	if (rcu_dereference(mcelog.next))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static long mce_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	int __user *p = (int __user *)arg;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	switch (cmd) {
+	case MCE_GET_RECORD_LEN:
+		return put_user(sizeof(struct mce), p);
+	case MCE_GET_LOG_LEN:
+		return put_user(MCE_LOG_LEN, p);
+	case MCE_GETCLEAR_FLAGS: {
+		unsigned flags;
+
+		do {
+			flags = mcelog.flags;
+		} while (cmpxchg(&mcelog.flags, flags, 0) != flags);
+
+		return put_user(flags, p);
+	}
+	default:
+		return -ENOTTY;
+	}
+}
+
+/* Modified in mce-inject.c, so not static or const */
+struct file_operations mce_chrdev_ops = {
+	.open			= mce_open,
+	.release		= mce_release,
+	.read			= mce_read,
+	.poll			= mce_poll,
+	.unlocked_ioctl		= mce_ioctl,
+};
+EXPORT_SYMBOL_GPL(mce_chrdev_ops);
+
+static struct miscdevice mce_log_device = {
+	MISC_MCELOG_MINOR,
+	"mcelog",
+	&mce_chrdev_ops,
+};
+
+/*
+ * mce=off Disables machine check
+ * mce=no_cmci Disables CMCI
+ * mce=dont_log_ce Clears corrected events silently, no log created for CEs.
+ * mce=ignore_ce Disables polling and CMCI, corrected events are not cleared.
+ * mce=TOLERANCELEVEL[,monarchtimeout] (number, see above)
+ *	monarchtimeout is how long to wait for other CPUs on machine
+ *	check, or 0 to not wait
+ * mce=bootlog Log MCEs from before booting. Disabled by default on AMD.
+ * mce=nobootlog Don't log MCEs from before booting.
+ */
+static int __init mcheck_enable(char *str)
+{
+	if (*str == 0)
+		enable_p5_mce();
+	if (*str == '=')
+		str++;
+	if (!strcmp(str, "off"))
+		mce_disabled = 1;
+	else if (!strcmp(str, "no_cmci"))
+		mce_cmci_disabled = 1;
+	else if (!strcmp(str, "dont_log_ce"))
+		mce_dont_log_ce = 1;
+	else if (!strcmp(str, "ignore_ce"))
+		mce_ignore_ce = 1;
+	else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog"))
+		mce_bootlog = (str[0] == 'b');
+	else if (isdigit(str[0])) {
+		get_option(&str, &tolerant);
+		if (*str == ',') {
+			++str;
+			get_option(&str, &monarch_timeout);
+		}
+	} else {
+		printk(KERN_INFO "mce argument %s ignored. Please use /sys\n",
+		       str);
+		return 0;
+	}
+	return 1;
+}
+__setup("mce", mcheck_enable);
+
+/*
+ * Sysfs support
+ */
+
+/*
+ * Disable machine checks on suspend and shutdown. We can't really handle
+ * them later.
+ */
+static int mce_disable(void)
+{
+	int i;
+
+	for (i = 0; i < banks; i++) {
+		if (!skip_bank_init(i))
+			wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+	}
+	return 0;
+}
+
+static int mce_suspend(struct sys_device *dev, pm_message_t state)
+{
+	return mce_disable();
+}
+
+static int mce_shutdown(struct sys_device *dev)
+{
+	return mce_disable();
+}
+
+/*
+ * On resume clear all MCE state. Don't want to see leftovers from the BIOS.
+ * Only one CPU is active at this time, the others get re-added later using
+ * CPU hotplug:
+ */
+static int mce_resume(struct sys_device *dev)
+{
+	mce_init();
+	mce_cpu_features(&current_cpu_data);
+
+	return 0;
+}
+
+static void mce_cpu_restart(void *data)
+{
+	del_timer_sync(&__get_cpu_var(mce_timer));
+	if (!mce_available(&current_cpu_data))
+		return;
+	mce_init();
+	mce_init_timer();
+}
+
+/* Reinit MCEs after user configuration changes */
+static void mce_restart(void)
+{
+	on_each_cpu(mce_cpu_restart, NULL, 1);
+}
+
+/* Toggle features for corrected errors */
+static void mce_disable_ce(void *all)
+{
+	if (!mce_available(&current_cpu_data))
+		return;
+	if (all)
+		del_timer_sync(&__get_cpu_var(mce_timer));
+	cmci_clear();
+}
+
+static void mce_enable_ce(void *all)
+{
+	if (!mce_available(&current_cpu_data))
+		return;
+	cmci_reenable();
+	cmci_recheck();
+	if (all)
+		mce_init_timer();
+}
+
+static struct sysdev_class mce_sysclass = {
+	.suspend	= mce_suspend,
+	.shutdown	= mce_shutdown,
+	.resume		= mce_resume,
+	.name		= "machinecheck",
+};
+
+DEFINE_PER_CPU(struct sys_device, mce_dev);
+
+__cpuinitdata
+void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
+
+static struct sysdev_attribute *bank_attrs;
+
+static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr,
+			 char *buf)
+{
+	u64 b = bank[attr - bank_attrs];
+
+	return sprintf(buf, "%llx\n", b);
+}
+
+static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
+			const char *buf, size_t size)
+{
+	u64 new;
+
+	if (strict_strtoull(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	bank[attr - bank_attrs] = new;
+	mce_restart();
+
+	return size;
+}
+
+static ssize_t
+show_trigger(struct sys_device *s, struct sysdev_attribute *attr, char *buf)
+{
+	strcpy(buf, mce_helper);
+	strcat(buf, "\n");
+	return strlen(mce_helper) + 1;
+}
+
+static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
+				const char *buf, size_t siz)
+{
+	char *p;
+
+	strncpy(mce_helper, buf, sizeof(mce_helper));
+	mce_helper[sizeof(mce_helper)-1] = 0;
+	p = strchr(mce_helper, '\n');
+
+	if (p)
+		*p = 0;
+
+	return strlen(mce_helper) + !!p;
+}
+
+static ssize_t set_ignore_ce(struct sys_device *s,
+			     struct sysdev_attribute *attr,
+			     const char *buf, size_t size)
+{
+	u64 new;
+
+	if (strict_strtoull(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	if (mce_ignore_ce ^ !!new) {
+		if (new) {
+			/* disable ce features */
+			on_each_cpu(mce_disable_ce, (void *)1, 1);
+			mce_ignore_ce = 1;
+		} else {
+			/* enable ce features */
+			mce_ignore_ce = 0;
+			on_each_cpu(mce_enable_ce, (void *)1, 1);
+		}
+	}
+	return size;
+}
+
+static ssize_t set_cmci_disabled(struct sys_device *s,
+				 struct sysdev_attribute *attr,
+				 const char *buf, size_t size)
+{
+	u64 new;
+
+	if (strict_strtoull(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	if (mce_cmci_disabled ^ !!new) {
+		if (new) {
+			/* disable cmci */
+			on_each_cpu(mce_disable_ce, NULL, 1);
+			mce_cmci_disabled = 1;
+		} else {
+			/* enable cmci */
+			mce_cmci_disabled = 0;
+			on_each_cpu(mce_enable_ce, NULL, 1);
+		}
+	}
+	return size;
+}
+
+static ssize_t store_int_with_restart(struct sys_device *s,
+				      struct sysdev_attribute *attr,
+				      const char *buf, size_t size)
+{
+	ssize_t ret = sysdev_store_int(s, attr, buf, size);
+	mce_restart();
+	return ret;
+}
+
+static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
+static SYSDEV_INT_ATTR(tolerant, 0644, tolerant);
+static SYSDEV_INT_ATTR(monarch_timeout, 0644, monarch_timeout);
+static SYSDEV_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce);
+
+static struct sysdev_ext_attribute attr_check_interval = {
+	_SYSDEV_ATTR(check_interval, 0644, sysdev_show_int,
+		     store_int_with_restart),
+	&check_interval
+};
+
+static struct sysdev_ext_attribute attr_ignore_ce = {
+	_SYSDEV_ATTR(ignore_ce, 0644, sysdev_show_int, set_ignore_ce),
+	&mce_ignore_ce
+};
+
+static struct sysdev_ext_attribute attr_cmci_disabled = {
+	_SYSDEV_ATTR(cmci_disabled, 0644, sysdev_show_int, set_cmci_disabled),
+	&mce_cmci_disabled
+};
+
+static struct sysdev_attribute *mce_attrs[] = {
+	&attr_tolerant.attr,
+	&attr_check_interval.attr,
+	&attr_trigger,
+	&attr_monarch_timeout.attr,
+	&attr_dont_log_ce.attr,
+	&attr_ignore_ce.attr,
+	&attr_cmci_disabled.attr,
+	NULL
+};
+
+static cpumask_var_t mce_dev_initialized;
+
+/* Per cpu sysdev init. All of the cpus still share the same ctrl bank: */
+static __cpuinit int mce_create_device(unsigned int cpu)
+{
+	int err;
+	int i, j;
+
+	if (!mce_available(&boot_cpu_data))
+		return -EIO;
+
+	memset(&per_cpu(mce_dev, cpu).kobj, 0, sizeof(struct kobject));
+	per_cpu(mce_dev, cpu).id	= cpu;
+	per_cpu(mce_dev, cpu).cls	= &mce_sysclass;
+
+	err = sysdev_register(&per_cpu(mce_dev, cpu));
+	if (err)
+		return err;
+
+	for (i = 0; mce_attrs[i]; i++) {
+		err = sysdev_create_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+		if (err)
+			goto error;
+	}
+	for (j = 0; j < banks; j++) {
+		err = sysdev_create_file(&per_cpu(mce_dev, cpu),
+					&bank_attrs[j]);
+		if (err)
+			goto error2;
+	}
+	cpumask_set_cpu(cpu, mce_dev_initialized);
+
+	return 0;
+error2:
+	while (--j >= 0)
+		sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[j]);
+error:
+	while (--i >= 0)
+		sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+
+	sysdev_unregister(&per_cpu(mce_dev, cpu));
+
+	return err;
+}
+
+static __cpuinit void mce_remove_device(unsigned int cpu)
+{
+	int i;
+
+	if (!cpumask_test_cpu(cpu, mce_dev_initialized))
+		return;
+
+	for (i = 0; mce_attrs[i]; i++)
+		sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+
+	for (i = 0; i < banks; i++)
+		sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[i]);
+
+	sysdev_unregister(&per_cpu(mce_dev, cpu));
+	cpumask_clear_cpu(cpu, mce_dev_initialized);
+}
+
+/* Make sure there are no machine checks on offlined CPUs. */
+static void mce_disable_cpu(void *h)
+{
+	unsigned long action = *(unsigned long *)h;
+	int i;
+
+	if (!mce_available(&current_cpu_data))
+		return;
+	if (!(action & CPU_TASKS_FROZEN))
+		cmci_clear();
+	for (i = 0; i < banks; i++) {
+		if (!skip_bank_init(i))
+			wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+	}
+}
+
+static void mce_reenable_cpu(void *h)
+{
+	unsigned long action = *(unsigned long *)h;
+	int i;
+
+	if (!mce_available(&current_cpu_data))
+		return;
+
+	if (!(action & CPU_TASKS_FROZEN))
+		cmci_reenable();
+	for (i = 0; i < banks; i++) {
+		if (!skip_bank_init(i))
+			wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
+	}
+}
+
+/* Get notified when a cpu comes on/off. Be hotplug friendly. */
+static int __cpuinit
+mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+	struct timer_list *t = &per_cpu(mce_timer, cpu);
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		mce_create_device(cpu);
+		if (threshold_cpu_callback)
+			threshold_cpu_callback(action, cpu);
+		break;
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
+		if (threshold_cpu_callback)
+			threshold_cpu_callback(action, cpu);
+		mce_remove_device(cpu);
+		break;
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+		del_timer_sync(t);
+		smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
+		break;
+	case CPU_DOWN_FAILED:
+	case CPU_DOWN_FAILED_FROZEN:
+		t->expires = round_jiffies(jiffies +
+						__get_cpu_var(next_interval));
+		add_timer_on(t, cpu);
+		smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
+		break;
+	case CPU_POST_DEAD:
+		/* intentionally ignoring frozen here */
+		cmci_rediscover(cpu);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block mce_cpu_notifier __cpuinitdata = {
+	.notifier_call = mce_cpu_callback,
+};
+
+static __init int mce_init_banks(void)
+{
+	int i;
+
+	bank_attrs = kzalloc(sizeof(struct sysdev_attribute) * banks,
+				GFP_KERNEL);
+	if (!bank_attrs)
+		return -ENOMEM;
+
+	for (i = 0; i < banks; i++) {
+		struct sysdev_attribute *a = &bank_attrs[i];
+
+		a->attr.name	= kasprintf(GFP_KERNEL, "bank%d", i);
+		if (!a->attr.name)
+			goto nomem;
+
+		a->attr.mode	= 0644;
+		a->show		= show_bank;
+		a->store	= set_bank;
+	}
+	return 0;
+
+nomem:
+	while (--i >= 0)
+		kfree(bank_attrs[i].attr.name);
+	kfree(bank_attrs);
+	bank_attrs = NULL;
+
+	return -ENOMEM;
+}
+
+static __init int mce_init_device(void)
+{
+	int err;
+	int i = 0;
+
+	if (!mce_available(&boot_cpu_data))
+		return -EIO;
+
+	zalloc_cpumask_var(&mce_dev_initialized, GFP_KERNEL);
+
+	err = mce_init_banks();
+	if (err)
+		return err;
+
+	err = sysdev_class_register(&mce_sysclass);
+	if (err)
+		return err;
+
+	for_each_online_cpu(i) {
+		err = mce_create_device(i);
+		if (err)
+			return err;
+	}
+
+	register_hotcpu_notifier(&mce_cpu_notifier);
+	misc_register(&mce_log_device);
+
+	return err;
+}
+
+device_initcall(mce_init_device);
+
+#else /* CONFIG_X86_OLD_MCE: */
+
+int nr_mce_banks;
+EXPORT_SYMBOL_GPL(nr_mce_banks);	/* non-fatal.o */
+
+/* This has to be run for each processor */
+void mcheck_init(struct cpuinfo_x86 *c)
+{
+	if (mce_disabled)
+		return;
+
+	switch (c->x86_vendor) {
+	case X86_VENDOR_AMD:
+		amd_mcheck_init(c);
+		break;
+
+	case X86_VENDOR_INTEL:
+		if (c->x86 == 5)
+			intel_p5_mcheck_init(c);
+		if (c->x86 == 6)
+			intel_p6_mcheck_init(c);
+		if (c->x86 == 15)
+			intel_p4_mcheck_init(c);
+		break;
+
+	case X86_VENDOR_CENTAUR:
+		if (c->x86 == 5)
+			winchip_mcheck_init(c);
+		break;
+
+	default:
+		break;
+	}
+	printk(KERN_INFO "mce: CPU supports %d MCE banks\n", nr_mce_banks);
+}
+
+static int __init mcheck_enable(char *str)
+{
+	mce_p5_enabled = 1;
+	return 1;
+}
+__setup("mce", mcheck_enable);
+
+#endif /* CONFIG_X86_OLD_MCE */
+
+/*
+ * Old style boot options parsing. Only for compatibility.
+ */
+static int __init mcheck_disable(char *str)
+{
+	mce_disabled = 1;
+	return 1;
+}
+__setup("nomce", mcheck_disable);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce.h linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce.h
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-#include <linux/init.h>
-#include <asm/mce.h>
-
-void amd_mcheck_init(struct cpuinfo_x86 *c);
-void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
-void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
-void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
-void winchip_mcheck_init(struct cpuinfo_x86 *c);
-
-/* Call the installed machine check handler for this CPU setup. */
-extern void (*machine_check_vector)(struct pt_regs *, long error_code);
-
-extern int nr_mce_banks;
-
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,127 @@
+/*
+ * Machine check injection support.
+ * Copyright 2008 Intel 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; version 2
+ * of the License.
+ *
+ * Authors:
+ * Andi Kleen
+ * Ying Huang
+ */
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp.h>
+#include <asm/mce.h>
+
+/* Update fake mce registers on current CPU. */
+static void inject_mce(struct mce *m)
+{
+	struct mce *i = &per_cpu(injectm, m->extcpu);
+
+	/* Make sure noone reads partially written injectm */
+	i->finished = 0;
+	mb();
+	m->finished = 0;
+	/* First set the fields after finished */
+	i->extcpu = m->extcpu;
+	mb();
+	/* Now write record in order, finished last (except above) */
+	memcpy(i, m, sizeof(struct mce));
+	/* Finally activate it */
+	mb();
+	i->finished = 1;
+}
+
+struct delayed_mce {
+	struct timer_list timer;
+	struct mce m;
+};
+
+/* Inject mce on current CPU */
+static void raise_mce(unsigned long data)
+{
+	struct delayed_mce *dm = (struct delayed_mce *)data;
+	struct mce *m = &dm->m;
+	int cpu = m->extcpu;
+
+	inject_mce(m);
+	if (m->status & MCI_STATUS_UC) {
+		struct pt_regs regs;
+		memset(&regs, 0, sizeof(struct pt_regs));
+		regs.ip = m->ip;
+		regs.cs = m->cs;
+		printk(KERN_INFO "Triggering MCE exception on CPU %d\n", cpu);
+		do_machine_check(&regs, 0);
+		printk(KERN_INFO "MCE exception done on CPU %d\n", cpu);
+	} else {
+		mce_banks_t b;
+		memset(&b, 0xff, sizeof(mce_banks_t));
+		printk(KERN_INFO "Starting machine check poll CPU %d\n", cpu);
+		machine_check_poll(0, &b);
+		mce_notify_irq();
+		printk(KERN_INFO "Finished machine check poll on CPU %d\n",
+		       cpu);
+	}
+	kfree(dm);
+}
+
+/* Error injection interface */
+static ssize_t mce_write(struct file *filp, const char __user *ubuf,
+			 size_t usize, loff_t *off)
+{
+	struct delayed_mce *dm;
+	struct mce m;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	/*
+	 * There are some cases where real MSR reads could slip
+	 * through.
+	 */
+	if (!boot_cpu_has(X86_FEATURE_MCE) || !boot_cpu_has(X86_FEATURE_MCA))
+		return -EIO;
+
+	if ((unsigned long)usize > sizeof(struct mce))
+		usize = sizeof(struct mce);
+	if (copy_from_user(&m, ubuf, usize))
+		return -EFAULT;
+
+	if (m.extcpu >= num_possible_cpus() || !cpu_online(m.extcpu))
+		return -EINVAL;
+
+	dm = kmalloc(sizeof(struct delayed_mce), GFP_KERNEL);
+	if (!dm)
+		return -ENOMEM;
+
+	/*
+	 * Need to give user space some time to set everything up,
+	 * so do it a jiffie or two later everywhere.
+	 * Should we use a hrtimer here for better synchronization?
+	 */
+	memcpy(&dm->m, &m, sizeof(struct mce));
+	setup_timer(&dm->timer, raise_mce, (unsigned long)dm);
+	dm->timer.expires = jiffies + 2;
+	add_timer_on(&dm->timer, m.extcpu);
+	return usize;
+}
+
+static int inject_init(void)
+{
+	printk(KERN_INFO "Machine check injector initialized\n");
+	mce_chrdev_ops.write = mce_write;
+	return 0;
+}
+
+module_init(inject_init);
+/*
+ * Cannot tolerate unloading currently because we cannot
+ * guarantee all openers of mce_chrdev will get a reference to us.
+ */
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_intel_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_intel_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_intel_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,298 +0,0 @@
-/*
- * Intel specific MCE features.
- * Copyright 2004 Zwane Mwaikambo <zwane@linuxpower.ca>
- * Copyright (C) 2008, 2009 Intel Corporation
- * Author: Andi Kleen
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/percpu.h>
-#include <asm/processor.h>
-#include <asm/apic.h>
-#include <asm/msr.h>
-#include <asm/mce.h>
-#include <asm/hw_irq.h>
-#include <asm/idle.h>
-#include <asm/therm_throt.h>
-#include <asm/apic.h>
-
-asmlinkage void smp_thermal_interrupt(void)
-{
-	__u64 msr_val;
-
-	ack_APIC_irq();
-
-	exit_idle();
-	irq_enter();
-
-	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
-	if (therm_throt_process(msr_val & 1))
-		mce_log_therm_throt_event(msr_val);
-
-	inc_irq_stat(irq_thermal_count);
-	irq_exit();
-}
-
-static void intel_init_thermal(struct cpuinfo_x86 *c)
-{
-	u32 l, h;
-	int tm2 = 0;
-	unsigned int cpu = smp_processor_id();
-
-	if (!cpu_has(c, X86_FEATURE_ACPI))
-		return;
-
-	if (!cpu_has(c, X86_FEATURE_ACC))
-		return;
-
-	/* first check if TM1 is already enabled by the BIOS, in which
-	 * case there might be some SMM goo which handles it, so we can't even
-	 * put a handler since it might be delivered via SMI already.
-	 */
-	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-	h = apic_read(APIC_LVTTHMR);
-	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
-		printk(KERN_DEBUG
-		       "CPU%d: Thermal monitoring handled by SMI\n", cpu);
-		return;
-	}
-
-	if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2))
-		tm2 = 1;
-
-	if (h & APIC_VECTOR_MASK) {
-		printk(KERN_DEBUG
-		       "CPU%d: Thermal LVT vector (%#x) already "
-		       "installed\n", cpu, (h & APIC_VECTOR_MASK));
-		return;
-	}
-
-	h = THERMAL_APIC_VECTOR;
-	h |= (APIC_DM_FIXED | APIC_LVT_MASKED);
-	apic_write(APIC_LVTTHMR, h);
-
-	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
-	wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h);
-
-	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
-
-	l = apic_read(APIC_LVTTHMR);
-	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
-	printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
-		cpu, tm2 ? "TM2" : "TM1");
-
-	/* enable thermal throttle processing */
-	atomic_set(&therm_throt_en, 1);
-	return;
-}
-
-/*
- * Support for Intel Correct Machine Check Interrupts. This allows
- * the CPU to raise an interrupt when a corrected machine check happened.
- * Normally we pick those up using a regular polling timer.
- * Also supports reliable discovery of shared banks.
- */
-
-static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
-
-/*
- * cmci_discover_lock protects against parallel discovery attempts
- * which could race against each other.
- */
-static DEFINE_SPINLOCK(cmci_discover_lock);
-
-#define CMCI_THRESHOLD 1
-
-static int cmci_supported(int *banks)
-{
-	u64 cap;
-
-	/*
-	 * Vendor check is not strictly needed, but the initial
-	 * initialization is vendor keyed and this
-	 * makes sure none of the backdoors are entered otherwise.
-	 */
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
-		return 0;
-	if (!cpu_has_apic || lapic_get_maxlvt() < 6)
-		return 0;
-	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	*banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
-	return !!(cap & MCG_CMCI_P);
-}
-
-/*
- * The interrupt handler. This is called on every event.
- * Just call the poller directly to log any events.
- * This could in theory increase the threshold under high load,
- * but doesn't for now.
- */
-static void intel_threshold_interrupt(void)
-{
-	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
-	mce_notify_user();
-}
-
-static void print_update(char *type, int *hdr, int num)
-{
-	if (*hdr == 0)
-		printk(KERN_INFO "CPU %d MCA banks", smp_processor_id());
-	*hdr = 1;
-	printk(KERN_CONT " %s:%d", type, num);
-}
-
-/*
- * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks
- * on this CPU. Use the algorithm recommended in the SDM to discover shared
- * banks.
- */
-static void cmci_discover(int banks, int boot)
-{
-	unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned);
-	unsigned long flags;
-	int hdr = 0;
-	int i;
-
-	spin_lock_irqsave(&cmci_discover_lock, flags);
-	for (i = 0; i < banks; i++) {
-		u64 val;
-
-		if (test_bit(i, owned))
-			continue;
-
-		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
-
-		/* Already owned by someone else? */
-		if (val & CMCI_EN) {
-			if (test_and_clear_bit(i, owned) || boot)
-				print_update("SHD", &hdr, i);
-			__clear_bit(i, __get_cpu_var(mce_poll_banks));
-			continue;
-		}
-
-		val |= CMCI_EN | CMCI_THRESHOLD;
-		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
-		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
-
-		/* Did the enable bit stick? -- the bank supports CMCI */
-		if (val & CMCI_EN) {
-			if (!test_and_set_bit(i, owned) || boot)
-				print_update("CMCI", &hdr, i);
-			__clear_bit(i, __get_cpu_var(mce_poll_banks));
-		} else {
-			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
-		}
-	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
-	if (hdr)
-		printk(KERN_CONT "\n");
-}
-
-/*
- * Just in case we missed an event during initialization check
- * all the CMCI owned banks.
- */
-void cmci_recheck(void)
-{
-	unsigned long flags;
-	int banks;
-
-	if (!mce_available(&current_cpu_data) || !cmci_supported(&banks))
-		return;
-	local_irq_save(flags);
-	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
-	local_irq_restore(flags);
-}
-
-/*
- * Disable CMCI on this CPU for all banks it owns when it goes down.
- * This allows other CPUs to claim the banks on rediscovery.
- */
-void cmci_clear(void)
-{
-	unsigned long flags;
-	int i;
-	int banks;
-	u64 val;
-
-	if (!cmci_supported(&banks))
-		return;
-	spin_lock_irqsave(&cmci_discover_lock, flags);
-	for (i = 0; i < banks; i++) {
-		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
-			continue;
-		/* Disable CMCI */
-		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
-		val &= ~(CMCI_EN|CMCI_THRESHOLD_MASK);
-		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
-		__clear_bit(i, __get_cpu_var(mce_banks_owned));
-	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
-}
-
-/*
- * After a CPU went down cycle through all the others and rediscover
- * Must run in process context.
- */
-void cmci_rediscover(int dying)
-{
-	int banks;
-	int cpu;
-	cpumask_var_t old;
-
-	if (!cmci_supported(&banks))
-		return;
-	if (!alloc_cpumask_var(&old, GFP_KERNEL))
-		return;
-	cpumask_copy(old, &current->cpus_allowed);
-
-	for_each_online_cpu (cpu) {
-		if (cpu == dying)
-			continue;
-		if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
-			continue;
-		/* Recheck banks in case CPUs don't all have the same */
-		if (cmci_supported(&banks))
-			cmci_discover(banks, 0);
-	}
-
-	set_cpus_allowed_ptr(current, old);
-	free_cpumask_var(old);
-}
-
-/*
- * Reenable CMCI on this CPU in case a CPU down failed.
- */
-void cmci_reenable(void)
-{
-	int banks;
-	if (cmci_supported(&banks))
-		cmci_discover(banks, 0);
-}
-
-static void intel_init_cmci(void)
-{
-	int banks;
-
-	if (!cmci_supported(&banks))
-		return;
-
-	mce_threshold_vector = intel_threshold_interrupt;
-	cmci_discover(banks, 1);
-	/*
-	 * For CPU #0 this runs with still disabled APIC, but that's
-	 * ok because only the vector is set up. We still do another
-	 * check for the banks later for CPU #0 just to make sure
-	 * to not miss any events.
-	 */
-	apic_write(APIC_LVTCMCI, THRESHOLD_APIC_VECTOR|APIC_DM_FIXED);
-	cmci_recheck();
-}
-
-void mce_intel_feature_init(struct cpuinfo_x86 *c)
-{
-	intel_init_thermal(c);
-	intel_init_cmci();
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,226 @@
+/*
+ * Intel specific MCE features.
+ * Copyright 2004 Zwane Mwaikambo <zwane@linuxpower.ca>
+ * Copyright (C) 2008, 2009 Intel Corporation
+ * Author: Andi Kleen
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <asm/apic.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/mce.h>
+
+/*
+ * Support for Intel Correct Machine Check Interrupts. This allows
+ * the CPU to raise an interrupt when a corrected machine check happened.
+ * Normally we pick those up using a regular polling timer.
+ * Also supports reliable discovery of shared banks.
+ */
+
+static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
+
+/*
+ * cmci_discover_lock protects against parallel discovery attempts
+ * which could race against each other.
+ */
+static DEFINE_SPINLOCK(cmci_discover_lock);
+
+#define CMCI_THRESHOLD 1
+
+static int cmci_supported(int *banks)
+{
+	u64 cap;
+
+	if (mce_cmci_disabled || mce_ignore_ce)
+		return 0;
+
+	/*
+	 * Vendor check is not strictly needed, but the initial
+	 * initialization is vendor keyed and this
+	 * makes sure none of the backdoors are entered otherwise.
+	 */
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return 0;
+	if (!cpu_has_apic || lapic_get_maxlvt() < 6)
+		return 0;
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
+	*banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
+	return !!(cap & MCG_CMCI_P);
+}
+
+/*
+ * The interrupt handler. This is called on every event.
+ * Just call the poller directly to log any events.
+ * This could in theory increase the threshold under high load,
+ * but doesn't for now.
+ */
+static void intel_threshold_interrupt(void)
+{
+	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
+	mce_notify_irq();
+}
+
+static void print_update(char *type, int *hdr, int num)
+{
+	if (*hdr == 0)
+		printk(KERN_INFO "CPU %d MCA banks", smp_processor_id());
+	*hdr = 1;
+	printk(KERN_CONT " %s:%d", type, num);
+}
+
+/*
+ * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks
+ * on this CPU. Use the algorithm recommended in the SDM to discover shared
+ * banks.
+ */
+static void cmci_discover(int banks, int boot)
+{
+	unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned);
+	unsigned long flags;
+	int hdr = 0;
+	int i;
+
+	spin_lock_irqsave(&cmci_discover_lock, flags);
+	for (i = 0; i < banks; i++) {
+		u64 val;
+
+		if (test_bit(i, owned))
+			continue;
+
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+
+		/* Already owned by someone else? */
+		if (val & CMCI_EN) {
+			if (test_and_clear_bit(i, owned) || boot)
+				print_update("SHD", &hdr, i);
+			__clear_bit(i, __get_cpu_var(mce_poll_banks));
+			continue;
+		}
+
+		val |= CMCI_EN | CMCI_THRESHOLD;
+		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+
+		/* Did the enable bit stick? -- the bank supports CMCI */
+		if (val & CMCI_EN) {
+			if (!test_and_set_bit(i, owned) || boot)
+				print_update("CMCI", &hdr, i);
+			__clear_bit(i, __get_cpu_var(mce_poll_banks));
+		} else {
+			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
+		}
+	}
+	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	if (hdr)
+		printk(KERN_CONT "\n");
+}
+
+/*
+ * Just in case we missed an event during initialization check
+ * all the CMCI owned banks.
+ */
+void cmci_recheck(void)
+{
+	unsigned long flags;
+	int banks;
+
+	if (!mce_available(&current_cpu_data) || !cmci_supported(&banks))
+		return;
+	local_irq_save(flags);
+	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
+	local_irq_restore(flags);
+}
+
+/*
+ * Disable CMCI on this CPU for all banks it owns when it goes down.
+ * This allows other CPUs to claim the banks on rediscovery.
+ */
+void cmci_clear(void)
+{
+	unsigned long flags;
+	int i;
+	int banks;
+	u64 val;
+
+	if (!cmci_supported(&banks))
+		return;
+	spin_lock_irqsave(&cmci_discover_lock, flags);
+	for (i = 0; i < banks; i++) {
+		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
+			continue;
+		/* Disable CMCI */
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		val &= ~(CMCI_EN|CMCI_THRESHOLD_MASK);
+		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		__clear_bit(i, __get_cpu_var(mce_banks_owned));
+	}
+	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+}
+
+/*
+ * After a CPU went down cycle through all the others and rediscover
+ * Must run in process context.
+ */
+void cmci_rediscover(int dying)
+{
+	int banks;
+	int cpu;
+	cpumask_var_t old;
+
+	if (!cmci_supported(&banks))
+		return;
+	if (!alloc_cpumask_var(&old, GFP_KERNEL))
+		return;
+	cpumask_copy(old, &current->cpus_allowed);
+
+	for_each_online_cpu(cpu) {
+		if (cpu == dying)
+			continue;
+		if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
+			continue;
+		/* Recheck banks in case CPUs don't all have the same */
+		if (cmci_supported(&banks))
+			cmci_discover(banks, 0);
+	}
+
+	set_cpus_allowed_ptr(current, old);
+	free_cpumask_var(old);
+}
+
+/*
+ * Reenable CMCI on this CPU in case a CPU down failed.
+ */
+void cmci_reenable(void)
+{
+	int banks;
+	if (cmci_supported(&banks))
+		cmci_discover(banks, 0);
+}
+
+static void intel_init_cmci(void)
+{
+	int banks;
+
+	if (!cmci_supported(&banks))
+		return;
+
+	mce_threshold_vector = intel_threshold_interrupt;
+	cmci_discover(banks, 1);
+	/*
+	 * For CPU #0 this runs with still disabled APIC, but that's
+	 * ok because only the vector is set up. We still do another
+	 * check for the banks later for CPU #0 just to make sure
+	 * to not miss any events.
+	 */
+	apic_write(APIC_LVTCMCI, THRESHOLD_APIC_VECTOR|APIC_DM_FIXED);
+	cmci_recheck();
+}
+
+void mce_intel_feature_init(struct cpuinfo_x86 *c)
+{
+	intel_init_thermal(c);
+	intel_init_cmci();
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,15 @@
+#include <asm/mce.h>
+
+enum severity_level {
+	MCE_NO_SEVERITY,
+	MCE_KEEP_SEVERITY,
+	MCE_SOME_SEVERITY,
+	MCE_AO_SEVERITY,
+	MCE_UC_SEVERITY,
+	MCE_AR_SEVERITY,
+	MCE_PANIC_SEVERITY,
+};
+
+int mce_severity(struct mce *a, int tolerant, char **msg);
+
+extern int mce_ser;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,218 @@
+/*
+ * MCE grading rules.
+ * Copyright 2008, 2009 Intel 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; version 2
+ * of the License.
+ *
+ * Author: Andi Kleen
+ */
+#include <linux/kernel.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <asm/mce.h>
+
+#include "mce-internal.h"
+
+/*
+ * Grade an mce by severity. In general the most severe ones are processed
+ * first. Since there are quite a lot of combinations test the bits in a
+ * table-driven way. The rules are simply processed in order, first
+ * match wins.
+ *
+ * Note this is only used for machine check exceptions, the corrected
+ * errors use much simpler rules. The exceptions still check for the corrected
+ * errors, but only to leave them alone for the CMCI handler (except for
+ * panic situations)
+ */
+
+enum context { IN_KERNEL = 1, IN_USER = 2 };
+enum ser { SER_REQUIRED = 1, NO_SER = 2 };
+
+static struct severity {
+	u64 mask;
+	u64 result;
+	unsigned char sev;
+	unsigned char mcgmask;
+	unsigned char mcgres;
+	unsigned char ser;
+	unsigned char context;
+	unsigned char covered;
+	char *msg;
+} severities[] = {
+#define KERNEL .context = IN_KERNEL
+#define USER .context = IN_USER
+#define SER .ser = SER_REQUIRED
+#define NOSER .ser = NO_SER
+#define SEV(s) .sev = MCE_ ## s ## _SEVERITY
+#define BITCLR(x, s, m, r...) { .mask = x, .result = 0, SEV(s), .msg = m, ## r }
+#define BITSET(x, s, m, r...) { .mask = x, .result = x, SEV(s), .msg = m, ## r }
+#define MCGMASK(x, res, s, m, r...) \
+	{ .mcgmask = x, .mcgres = res, SEV(s), .msg = m, ## r }
+#define MASK(x, y, s, m, r...) \
+	{ .mask = x, .result = y, SEV(s), .msg = m, ## r }
+#define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S)
+#define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR)
+#define MCACOD 0xffff
+
+	BITCLR(MCI_STATUS_VAL, NO, "Invalid"),
+	BITCLR(MCI_STATUS_EN, NO, "Not enabled"),
+	BITSET(MCI_STATUS_PCC, PANIC, "Processor context corrupt"),
+	/* When MCIP is not set something is very confused */
+	MCGMASK(MCG_STATUS_MCIP, 0, PANIC, "MCIP not set in MCA handler"),
+	/* Neither return not error IP -- no chance to recover -> PANIC */
+	MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, 0, PANIC,
+		"Neither restart nor error IP"),
+	MCGMASK(MCG_STATUS_RIPV, 0, PANIC, "In kernel and no restart IP",
+		KERNEL),
+	BITCLR(MCI_STATUS_UC, KEEP, "Corrected error", NOSER),
+	MASK(MCI_STATUS_OVER|MCI_STATUS_UC|MCI_STATUS_EN, MCI_STATUS_UC, SOME,
+	     "Spurious not enabled", SER),
+
+	/* ignore OVER for UCNA */
+	MASK(MCI_UC_SAR, MCI_STATUS_UC, KEEP,
+	     "Uncorrected no action required", SER),
+	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_UC|MCI_STATUS_AR, PANIC,
+	     "Illegal combination (UCNA with AR=1)", SER),
+	MASK(MCI_STATUS_S, 0, KEEP, "Non signalled machine check", SER),
+
+	/* AR add known MCACODs here */
+	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_OVER|MCI_UC_SAR, PANIC,
+	     "Action required with lost events", SER),
+	MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCACOD, MCI_UC_SAR, PANIC,
+	     "Action required; unknown MCACOD", SER),
+
+	/* known AO MCACODs: */
+	MASK(MCI_UC_SAR|MCI_STATUS_OVER|0xfff0, MCI_UC_S|0xc0, AO,
+	     "Action optional: memory scrubbing error", SER),
+	MASK(MCI_UC_SAR|MCI_STATUS_OVER|MCACOD, MCI_UC_S|0x17a, AO,
+	     "Action optional: last level cache writeback error", SER),
+
+	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S, SOME,
+	     "Action optional unknown MCACOD", SER),
+	MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S|MCI_STATUS_OVER, SOME,
+	     "Action optional with lost events", SER),
+	BITSET(MCI_STATUS_UC|MCI_STATUS_OVER, PANIC, "Overflowed uncorrected"),
+	BITSET(MCI_STATUS_UC, UC, "Uncorrected"),
+	BITSET(0, SOME, "No match")	/* always matches. keep at end */
+};
+
+/*
+ * If the EIPV bit is set, it means the saved IP is the
+ * instruction which caused the MCE.
+ */
+static int error_context(struct mce *m)
+{
+	if (m->mcgstatus & MCG_STATUS_EIPV)
+		return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL;
+	/* Unknown, assume kernel */
+	return IN_KERNEL;
+}
+
+int mce_severity(struct mce *a, int tolerant, char **msg)
+{
+	enum context ctx = error_context(a);
+	struct severity *s;
+
+	for (s = severities;; s++) {
+		if ((a->status & s->mask) != s->result)
+			continue;
+		if ((a->mcgstatus & s->mcgmask) != s->mcgres)
+			continue;
+		if (s->ser == SER_REQUIRED && !mce_ser)
+			continue;
+		if (s->ser == NO_SER && mce_ser)
+			continue;
+		if (s->context && ctx != s->context)
+			continue;
+		if (msg)
+			*msg = s->msg;
+		s->covered = 1;
+		if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL) {
+			if (panic_on_oops || tolerant < 1)
+				return MCE_PANIC_SEVERITY;
+		}
+		return s->sev;
+	}
+}
+
+static void *s_start(struct seq_file *f, loff_t *pos)
+{
+	if (*pos >= ARRAY_SIZE(severities))
+		return NULL;
+	return &severities[*pos];
+}
+
+static void *s_next(struct seq_file *f, void *data, loff_t *pos)
+{
+	if (++(*pos) >= ARRAY_SIZE(severities))
+		return NULL;
+	return &severities[*pos];
+}
+
+static void s_stop(struct seq_file *f, void *data)
+{
+}
+
+static int s_show(struct seq_file *f, void *data)
+{
+	struct severity *ser = data;
+	seq_printf(f, "%d\t%s\n", ser->covered, ser->msg);
+	return 0;
+}
+
+static const struct seq_operations severities_seq_ops = {
+	.start	= s_start,
+	.next	= s_next,
+	.stop	= s_stop,
+	.show	= s_show,
+};
+
+static int severities_coverage_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &severities_seq_ops);
+}
+
+static ssize_t severities_coverage_write(struct file *file,
+					 const char __user *ubuf,
+					 size_t count, loff_t *ppos)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(severities); i++)
+		severities[i].covered = 0;
+	return count;
+}
+
+static const struct file_operations severities_coverage_fops = {
+	.open		= severities_coverage_open,
+	.release	= seq_release,
+	.read		= seq_read,
+	.write		= severities_coverage_write,
+};
+
+static int __init severities_debugfs_init(void)
+{
+	struct dentry *dmce = NULL, *fseverities_coverage = NULL;
+
+	dmce = debugfs_create_dir("mce", NULL);
+	if (dmce == NULL)
+		goto err_out;
+	fseverities_coverage = debugfs_create_file("severities-coverage",
+						   0444, dmce, NULL,
+						   &severities_coverage_fops);
+	if (fseverities_coverage == NULL)
+		goto err_out;
+
+	return 0;
+
+err_out:
+	if (fseverities_coverage)
+		debugfs_remove(fseverities_coverage);
+	if (dmce)
+		debugfs_remove(dmce);
+	return -ENOMEM;
+}
+late_initcall(severities_debugfs_init);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/non-fatal.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/non-fatal.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/non-fatal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/non-fatal.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,25 +6,23 @@
  * This file contains routines to check for non-fatal MCEs every 15s
  *
  */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/workqueue.h>
 #include <linux/interrupt.h>
-#include <linux/smp.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/smp.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
-static int firstbank;
+static int		firstbank;
 
-#define MCE_RATE	15*HZ	/* timer rate is 15s */
+#define MCE_RATE	(15*HZ)	/* timer rate is 15s */
 
 static void mce_checkregs(void *info)
 {
@@ -34,23 +32,24 @@
 	for (i = firstbank; i < nr_mce_banks; i++) {
 		rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
 
-		if (high & (1<<31)) {
-			printk(KERN_INFO "MCE: The hardware reports a non "
-				"fatal, correctable incident occurred on "
-				"CPU %d.\n",
+		if (!(high & (1<<31)))
+			continue;
+
+		printk(KERN_INFO "MCE: The hardware reports a non fatal, "
+			"correctable incident occurred on CPU %d.\n",
 				smp_processor_id());
-			printk(KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
 
-			/*
-			 * Scrub the error so we don't pick it up in MCE_RATE
-			 * seconds time.
-			 */
-			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
+		printk(KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
 
-			/* Serialize */
-			wmb();
-			add_taint(TAINT_MACHINE_CHECK);
-		}
+		/*
+		 * Scrub the error so we don't pick it up in MCE_RATE
+		 * seconds time:
+		 */
+		wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
+
+		/* Serialize: */
+		wmb();
+		add_taint(TAINT_MACHINE_CHECK);
 	}
 }
 
@@ -77,16 +76,17 @@
 
 	/* Some Athlons misbehave when we frob bank 0 */
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
-		boot_cpu_data.x86 == 6)
-			firstbank = 1;
+						boot_cpu_data.x86 == 6)
+		firstbank = 1;
 	else
-			firstbank = 0;
+		firstbank = 0;
 
 	/*
 	 * Check for non-fatal errors every MCE_RATE s
 	 */
 	schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE));
 	printk(KERN_INFO "Machine check exception polling timer started.\n");
+
 	return 0;
 }
 module_init(init_nonfatal_mce_checker);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/p4.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/p4.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/p4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/p4.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,21 +1,14 @@
 /*
  * P4 specific Machine Check Exception Reporting
  */
-
-#include <linux/init.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/init.h>
 #include <linux/smp.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
-#include <asm/apic.h>
-
-#include <asm/therm_throt.h>
-
-#include "mce.h"
 
 /* as supported by the P4/Xeon family */
 struct intel_mce_extended_msrs {
@@ -34,98 +27,8 @@
 
 static int mce_num_extended_msrs;
 
-
-#ifdef CONFIG_X86_MCE_P4THERMAL
-static void unexpected_thermal_interrupt(struct pt_regs *regs)
-{
-	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
-			smp_processor_id());
-	add_taint(TAINT_MACHINE_CHECK);
-}
-
-/* P4/Xeon Thermal transition interrupt handler */
-static void intel_thermal_interrupt(struct pt_regs *regs)
-{
-	__u64 msr_val;
-
-	ack_APIC_irq();
-
-	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
-	therm_throt_process(msr_val & 0x1);
-}
-
-/* Thermal interrupt handler for this CPU setup */
-static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
-
-void smp_thermal_interrupt(struct pt_regs *regs)
-{
-	irq_enter();
-	vendor_thermal_interrupt(regs);
-	__get_cpu_var(irq_stat).irq_thermal_count++;
-	irq_exit();
-}
-
-/* P4/Xeon Thermal regulation detect and init */
-static void intel_init_thermal(struct cpuinfo_x86 *c)
-{
-	u32 l, h;
-	unsigned int cpu = smp_processor_id();
-
-	/* Thermal monitoring */
-	if (!cpu_has(c, X86_FEATURE_ACPI))
-		return;	/* -ENODEV */
-
-	/* Clock modulation */
-	if (!cpu_has(c, X86_FEATURE_ACC))
-		return;	/* -ENODEV */
-
-	/* first check if its enabled already, in which case there might
-	 * be some SMM goo which handles it, so we can't even put a handler
-	 * since it might be delivered via SMI already -zwanem.
-	 */
-	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-	h = apic_read(APIC_LVTTHMR);
-	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
-		printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n",
-				cpu);
-		return; /* -EBUSY */
-	}
-
-	/* check whether a vector already exists, temporarily masked? */
-	if (h & APIC_VECTOR_MASK) {
-		printk(KERN_DEBUG "CPU%d: Thermal LVT vector (%#x) already "
-				"installed\n",
-			cpu, (h & APIC_VECTOR_MASK));
-		return; /* -EBUSY */
-	}
-
-	/* The temperature transition interrupt handler setup */
-	h = THERMAL_APIC_VECTOR;		/* our delivery vector */
-	h |= (APIC_DM_FIXED | APIC_LVT_MASKED);	/* we'll mask till we're ready */
-	apic_write(APIC_LVTTHMR, h);
-
-	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
-	wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h);
-
-	/* ok we're good to go... */
-	vendor_thermal_interrupt = intel_thermal_interrupt;
-
-	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
-
-	l = apic_read(APIC_LVTTHMR);
-	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
-	printk(KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu);
-
-	/* enable thermal throttle processing */
-	atomic_set(&therm_throt_en, 1);
-	return;
-}
-#endif /* CONFIG_X86_MCE_P4THERMAL */
-
-
 /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */
-static inline void intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
+static void intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
 {
 	u32 h;
 
@@ -143,9 +46,9 @@
 
 static void intel_machine_check(struct pt_regs *regs, long error_code)
 {
-	int recover = 1;
 	u32 alow, ahigh, high, low;
 	u32 mcgstl, mcgsth;
+	int recover = 1;
 	int i;
 
 	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
@@ -157,7 +60,9 @@
 
 	if (mce_num_extended_msrs > 0) {
 		struct intel_mce_extended_msrs dbg;
+
 		intel_get_extended_msrs(&dbg);
+
 		printk(KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n"
 			"\teax: %08x ebx: %08x ecx: %08x edx: %08x\n"
 			"\tesi: %08x edi: %08x ebp: %08x esp: %08x\n",
@@ -171,6 +76,7 @@
 		if (high & (1<<31)) {
 			char misc[20];
 			char addr[24];
+
 			misc[0] = addr[0] = '\0';
 			if (high & (1<<29))
 				recover |= 1;
@@ -196,6 +102,7 @@
 		panic("Unable to continue");
 
 	printk(KERN_EMERG "Attempting to continue.\n");
+
 	/*
 	 * Do not clear the MSR_IA32_MCi_STATUS if the error is not
 	 * recoverable/continuable.This will allow BIOS to look at the MSRs
@@ -217,7 +124,6 @@
 	wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 }
 
-
 void intel_p4_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/p5.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/p5.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/p5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/p5.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,52 +2,67 @@
  * P5 specific Machine Check Exception Reporting
  * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
 #include <linux/smp.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
+/* By default disabled */
+int mce_p5_enabled __read_mostly;
 
-/* Machine check handler for Pentium class Intel */
+/* Machine check handler for Pentium class Intel CPUs: */
 static void pentium_machine_check(struct pt_regs *regs, long error_code)
 {
 	u32 loaddr, hi, lotype;
+
 	rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
 	rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
-	printk(KERN_EMERG "CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
-	if (lotype&(1<<5))
-		printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
+
+	printk(KERN_EMERG
+		"CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n",
+		smp_processor_id(), loaddr, lotype);
+
+	if (lotype & (1<<5)) {
+		printk(KERN_EMERG
+			"CPU#%d: Possible thermal failure (CPU on fire ?).\n",
+			smp_processor_id());
+	}
+
 	add_taint(TAINT_MACHINE_CHECK);
 }
 
-/* Set up machine check reporting for processors with Intel style MCE */
+/* Set up machine check reporting for processors with Intel style MCE: */
 void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 
-	/*Check for MCE support */
-	if (!cpu_has(c, X86_FEATURE_MCE))
+	/* Default P5 to off as its often misconnected: */
+	if (!mce_p5_enabled)
 		return;
 
-	/* Default P5 to off as its often misconnected */
-	if (mce_disabled != -1)
+	/* Check for MCE support: */
+	if (!cpu_has(c, X86_FEATURE_MCE))
 		return;
+
 	machine_check_vector = pentium_machine_check;
+	/* Make sure the vector pointer is visible before we enable MCEs: */
 	wmb();
 
-	/* Read registers before enabling */
+	/* Read registers before enabling: */
 	rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
 	rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
-	printk(KERN_INFO "Intel old style machine check architecture supported.\n");
+	printk(KERN_INFO
+	       "Intel old style machine check architecture supported.\n");
 
-	/* Enable MCE */
+	/* Enable MCE: */
 	set_in_cr4(X86_CR4_MCE);
-	printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+	printk(KERN_INFO
+	       "Intel old style machine check reporting enabled on CPU#%d.\n",
+	       smp_processor_id());
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/p6.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/p6.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/p6.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/p6.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,25 +2,23 @@
  * P6 specific Machine Check Exception Reporting
  * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
 #include <linux/smp.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 /* Machine Check Handler For PII/PIII */
 static void intel_machine_check(struct pt_regs *regs, long error_code)
 {
-	int recover = 1;
 	u32 alow, ahigh, high, low;
 	u32 mcgstl, mcgsth;
+	int recover = 1;
 	int i;
 
 	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
@@ -35,12 +33,16 @@
 		if (high & (1<<31)) {
 			char misc[20];
 			char addr[24];
-			misc[0] = addr[0] = '\0';
+
+			misc[0] = '\0';
+			addr[0] = '\0';
+
 			if (high & (1<<29))
 				recover |= 1;
 			if (high & (1<<25))
 				recover |= 2;
 			high &= ~(1<<31);
+
 			if (high & (1<<27)) {
 				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
 				snprintf(misc, 20, "[%08x%08x]", ahigh, alow);
@@ -49,6 +51,7 @@
 				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
 				snprintf(addr, 24, " at %08x%08x", ahigh, alow);
 			}
+
 			printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n",
 				smp_processor_id(), i, high, low, misc, addr);
 		}
@@ -63,16 +66,17 @@
 	/*
 	 * Do not clear the MSR_IA32_MCi_STATUS if the error is not
 	 * recoverable/continuable.This will allow BIOS to look at the MSRs
-	 * for errors if the OS could not log the error.
+	 * for errors if the OS could not log the error:
 	 */
 	for (i = 0; i < nr_mce_banks; i++) {
 		unsigned int msr;
+
 		msr = MSR_IA32_MC0_STATUS+i*4;
 		rdmsr(msr, low, high);
 		if (high & (1<<31)) {
-			/* Clear it */
+			/* Clear it: */
 			wrmsr(msr, 0UL, 0UL);
-			/* Serialize */
+			/* Serialize: */
 			wmb();
 			add_taint(TAINT_MACHINE_CHECK);
 		}
@@ -81,7 +85,7 @@
 	wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 }
 
-/* Set up machine check reporting for processors with Intel style MCE */
+/* Set up machine check reporting for processors with Intel style MCE: */
 void intel_p6_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
@@ -97,6 +101,7 @@
 
 	/* Ok machine check is available */
 	machine_check_vector = intel_machine_check;
+	/* Make sure the vector pointer is visible before we enable MCEs: */
 	wmb();
 
 	printk(KERN_INFO "Intel machine check architecture supported.\n");
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
- *
  * Thermal throttle event support code (such as syslog messaging and rate
  * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
+ *
  * This allows consistent reporting of CPU thermal throttle events.
  *
  * Maintains a counter in /sys that keeps track of the number of thermal
@@ -13,43 +13,54 @@
  * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c.
  *          Inspired by Ross Biro's and Al Borchers' counter code.
  */
-
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
 #include <linux/percpu.h>
 #include <linux/sysdev.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/cpu.h>
-#include <asm/cpu.h>
-#include <linux/notifier.h>
-#include <linux/jiffies.h>
-#include <asm/therm_throt.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/apic.h>
+#include <asm/idle.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
 
 /* How long to wait between reporting thermal events */
-#define CHECK_INTERVAL              (300 * HZ)
+#define CHECK_INTERVAL		(300 * HZ)
 
 static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
 static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
-atomic_t therm_throt_en = ATOMIC_INIT(0);
+static DEFINE_PER_CPU(bool, thermal_throttle_active);
+
+static atomic_t therm_throt_en		= ATOMIC_INIT(0);
 
 #ifdef CONFIG_SYSFS
-#define define_therm_throt_sysdev_one_ro(_name)                              \
-        static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
+#define define_therm_throt_sysdev_one_ro(_name)				\
+	static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
 
-#define define_therm_throt_sysdev_show_func(name)                            \
-static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev,        \
-					struct sysdev_attribute *attr,	     \
-                                              char *buf)                     \
-{                                                                            \
-	unsigned int cpu = dev->id;                                          \
-	ssize_t ret;                                                         \
-                                                                             \
-	preempt_disable();              /* CPU hotplug */                    \
-	if (cpu_online(cpu))                                                 \
-		ret = sprintf(buf, "%lu\n",                                  \
-			      per_cpu(thermal_throttle_##name, cpu));        \
-	else                                                                 \
-		ret = 0;                                                     \
-	preempt_enable();                                                    \
-                                                                             \
-	return ret;                                                          \
+#define define_therm_throt_sysdev_show_func(name)			\
+static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev,	\
+					struct sysdev_attribute *attr,	\
+					      char *buf)		\
+{									\
+	unsigned int cpu = dev->id;					\
+	ssize_t ret;							\
+									\
+	preempt_disable();	/* CPU hotplug */			\
+	if (cpu_online(cpu))						\
+		ret = sprintf(buf, "%lu\n",				\
+			      per_cpu(thermal_throttle_##name, cpu));	\
+	else								\
+		ret = 0;						\
+	preempt_enable();						\
+									\
+	return ret;							\
 }
 
 define_therm_throt_sysdev_show_func(count);
@@ -61,8 +72,8 @@
 };
 
 static struct attribute_group thermal_throttle_attr_group = {
-	.attrs = thermal_throttle_attrs,
-	.name = "thermal_throttle"
+	.attrs	= thermal_throttle_attrs,
+	.name	= "thermal_throttle"
 };
 #endif /* CONFIG_SYSFS */
 
@@ -82,38 +93,45 @@
  *          1 : Event should be logged further, and a message has been
  *              printed to the syslog.
  */
-int therm_throt_process(int curr)
+static int therm_throt_process(int curr)
 {
 	unsigned int cpu = smp_processor_id();
 	__u64 tmp_jiffs = get_jiffies_64();
+	bool was_throttled = __get_cpu_var(thermal_throttle_active);
+	bool is_throttled = __get_cpu_var(thermal_throttle_active) = curr;
 
-	if (curr)
+	if (is_throttled)
 		__get_cpu_var(thermal_throttle_count)++;
 
-	if (time_before64(tmp_jiffs, __get_cpu_var(next_check)))
+	if (!(was_throttled ^ is_throttled) &&
+	    time_before64(tmp_jiffs, __get_cpu_var(next_check)))
 		return 0;
 
 	__get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
 
 	/* if we just entered the thermal event */
-	if (curr) {
+	if (is_throttled) {
 		printk(KERN_CRIT "CPU%d: Temperature above threshold, "
-		       "cpu clock throttled (total events = %lu)\n", cpu,
-		       __get_cpu_var(thermal_throttle_count));
+		       "cpu clock throttled (total events = %lu)\n",
+		       cpu, __get_cpu_var(thermal_throttle_count));
 
 		add_taint(TAINT_MACHINE_CHECK);
-	} else {
-		printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu);
+		return 1;
+	}
+	if (was_throttled) {
+		printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
+		return 1;
 	}
 
-	return 1;
+	return 0;
 }
 
 #ifdef CONFIG_SYSFS
-/* Add/Remove thermal_throttle interface for CPU device */
+/* Add/Remove thermal_throttle interface for CPU device: */
 static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
 {
-	return sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group);
+	return sysfs_create_group(&sys_dev->kobj,
+				  &thermal_throttle_attr_group);
 }
 
 static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
@@ -121,19 +139,21 @@
 	sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
 }
 
-/* Mutex protecting device creation against CPU hotplug */
+/* Mutex protecting device creation against CPU hotplug: */
 static DEFINE_MUTEX(therm_cpu_lock);
 
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
-						   unsigned long action,
-						   void *hcpu)
+static __cpuinit int
+thermal_throttle_cpu_callback(struct notifier_block *nfb,
+			      unsigned long action,
+			      void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
 	struct sys_device *sys_dev;
 	int err = 0;
 
 	sys_dev = get_cpu_sysdev(cpu);
+
 	switch (action) {
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
@@ -183,6 +203,94 @@
 
 	return 0;
 }
-
 device_initcall(thermal_throttle_init_device);
+
 #endif /* CONFIG_SYSFS */
+
+/* Thermal transition interrupt handler */
+static void intel_thermal_interrupt(void)
+{
+	__u64 msr_val;
+
+	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
+	if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT))
+		mce_log_therm_throt_event(msr_val);
+}
+
+static void unexpected_thermal_interrupt(void)
+{
+	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
+			smp_processor_id());
+	add_taint(TAINT_MACHINE_CHECK);
+}
+
+static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt;
+
+asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)
+{
+	exit_idle();
+	irq_enter();
+	inc_irq_stat(irq_thermal_count);
+	smp_thermal_vector();
+	irq_exit();
+	/* Ack only at the end to avoid potential reentry */
+	ack_APIC_irq();
+}
+
+void intel_init_thermal(struct cpuinfo_x86 *c)
+{
+	unsigned int cpu = smp_processor_id();
+	int tm2 = 0;
+	u32 l, h;
+
+	/* Thermal monitoring depends on ACPI and clock modulation*/
+	if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
+		return;
+
+	/*
+	 * First check if its enabled already, in which case there might
+	 * be some SMM goo which handles it, so we can't even put a handler
+	 * since it might be delivered via SMI already:
+	 */
+	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+	h = apic_read(APIC_LVTTHMR);
+	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
+		printk(KERN_DEBUG
+		       "CPU%d: Thermal monitoring handled by SMI\n", cpu);
+		return;
+	}
+
+	if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2))
+		tm2 = 1;
+
+	/* Check whether a vector already exists */
+	if (h & APIC_VECTOR_MASK) {
+		printk(KERN_DEBUG
+		       "CPU%d: Thermal LVT vector (%#x) already installed\n",
+		       cpu, (h & APIC_VECTOR_MASK));
+		return;
+	}
+
+	/* We'll mask the thermal vector in the lapic till we're ready: */
+	h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED;
+	apic_write(APIC_LVTTHMR, h);
+
+	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
+	wrmsr(MSR_IA32_THERM_INTERRUPT,
+		l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
+
+	smp_thermal_vector = intel_thermal_interrupt;
+
+	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
+
+	/* Unmask the thermal vector: */
+	l = apic_read(APIC_LVTTHMR);
+	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+	printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
+	       cpu, tm2 ? "TM2" : "TM1");
+
+	/* enable thermal throttle processing */
+	atomic_set(&therm_throt_en, 1);
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/threshold.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/threshold.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/threshold.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/threshold.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 
 void (*mce_threshold_vector)(void) = default_threshold_interrupt;
 
-asmlinkage void mce_threshold_interrupt(void)
+asmlinkage void smp_threshold_interrupt(void)
 {
 	exit_idle();
 	irq_enter();
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/winchip.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/winchip.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mcheck/winchip.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mcheck/winchip.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,19 +2,17 @@
  * IDT Winchip specific Machine Check Exception Reporting
  * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
-/* Machine check handler for WinChip C6 */
+/* Machine check handler for WinChip C6: */
 static void winchip_machine_check(struct pt_regs *regs, long error_code)
 {
 	printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
@@ -25,12 +23,18 @@
 void winchip_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 lo, hi;
+
 	machine_check_vector = winchip_machine_check;
+	/* Make sure the vector pointer is visible before we enable MCEs: */
 	wmb();
+
 	rdmsr(MSR_IDT_FCR1, lo, hi);
 	lo |= (1<<2);	/* Enable EIERRINT (int 18 MCE) */
 	lo &= ~(1<<4);	/* Enable MCE */
 	wrmsr(MSR_IDT_FCR1, lo, hi);
+
 	set_in_cr4(X86_CR4_MCE);
-	printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n");
+
+	printk(KERN_INFO
+	       "Winchip machine check reporting enabled on CPU#0.\n");
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/cleanup.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/cleanup.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/cleanup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/cleanup.c	2009-09-09 18:13:59.000000000 -0400
@@ -808,7 +808,7 @@
 
 	if (!is_cpu(INTEL) || enable_mtrr_cleanup < 1)
 		return 0;
-	rdmsr(MTRRdefType_MSR, def, dummy);
+	rdmsr(MSR_MTRRdefType, def, dummy);
 	def &= 0xff;
 	if (def != MTRR_TYPE_UNCACHABLE)
 		return 0;
@@ -1003,7 +1003,7 @@
 	 */
 	if (!is_cpu(INTEL) || disable_mtrr_trim)
 		return 0;
-	rdmsr(MTRRdefType_MSR, def, dummy);
+	rdmsr(MSR_MTRRdefType, def, dummy);
 	def &= 0xff;
 	if (def != MTRR_TYPE_UNCACHABLE)
 		return 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/generic.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/generic.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,9 +20,9 @@
 };
 
 static struct fixed_range_block fixed_range_blocks[] = {
-	{ MTRRfix64K_00000_MSR, 1 }, /* one  64k MTRR  */
-	{ MTRRfix16K_80000_MSR, 2 }, /* two  16k MTRRs */
-	{ MTRRfix4K_C0000_MSR,  8 }, /* eight 4k MTRRs */
+	{ MSR_MTRRfix64K_00000, 1 }, /* one  64k MTRR  */
+	{ MSR_MTRRfix16K_80000, 2 }, /* two  16k MTRRs */
+	{ MSR_MTRRfix4K_C0000,  8 }, /* eight 4k MTRRs */
 	{}
 };
 
@@ -194,12 +194,12 @@
 
 	k8_check_syscfg_dram_mod_en();
 
-	rdmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
+	rdmsr(MSR_MTRRfix64K_00000, p[0], p[1]);
 
 	for (i = 0; i < 2; i++)
-		rdmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2], p[3 + i * 2]);
+		rdmsr(MSR_MTRRfix16K_80000 + i, p[2 + i * 2], p[3 + i * 2]);
 	for (i = 0; i < 8; i++)
-		rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]);
+		rdmsr(MSR_MTRRfix4K_C0000 + i, p[6 + i * 2], p[7 + i * 2]);
 }
 
 void mtrr_save_fixed_ranges(void *info)
@@ -310,7 +310,7 @@
 
 	vrs = mtrr_state.var_ranges;
 
-	rdmsr(MTRRcap_MSR, lo, dummy);
+	rdmsr(MSR_MTRRcap, lo, dummy);
 	mtrr_state.have_fixed = (lo >> 8) & 1;
 
 	for (i = 0; i < num_var_ranges; i++)
@@ -318,7 +318,7 @@
 	if (mtrr_state.have_fixed)
 		get_fixed_ranges(mtrr_state.fixed_ranges);
 
-	rdmsr(MTRRdefType_MSR, lo, dummy);
+	rdmsr(MSR_MTRRdefType, lo, dummy);
 	mtrr_state.def_type = (lo & 0xff);
 	mtrr_state.enabled = (lo & 0xc00) >> 10;
 
@@ -583,10 +583,10 @@
 	__flush_tlb();
 
 	/*  Save MTRR state */
-	rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
+	rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
 
 	/*  Disable MTRRs, and set the default type to uncached  */
-	mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & ~0xcff, deftype_hi);
+	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
 }
 
 static void post_set(void) __releases(set_atomicity_lock)
@@ -595,7 +595,7 @@
 	__flush_tlb();
 
 	/* Intel (P6) standard MTRRs */
-	mtrr_wrmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
+	mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
 		
 	/*  Enable caches  */
 	write_cr0(read_cr0() & 0xbfffffff);
@@ -707,7 +707,7 @@
 static int generic_have_wrcomb(void)
 {
 	unsigned long config, dummy;
-	rdmsr(MTRRcap_MSR, config, dummy);
+	rdmsr(MSR_MTRRcap, config, dummy);
 	return (config & (1 << 10));
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/main.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/main.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -104,7 +104,7 @@
 	unsigned long config = 0, dummy;
 
 	if (use_intel()) {
-		rdmsr(MTRRcap_MSR, config, dummy);
+		rdmsr(MSR_MTRRcap, config, dummy);
 	} else if (is_cpu(AMD))
 		config = 2;
 	else if (is_cpu(CYRIX) || is_cpu(CENTAUR))
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,21 +5,6 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 
-#define MTRRcap_MSR     0x0fe
-#define MTRRdefType_MSR 0x2ff
-
-#define MTRRfix64K_00000_MSR 0x250
-#define MTRRfix16K_80000_MSR 0x258
-#define MTRRfix16K_A0000_MSR 0x259
-#define MTRRfix4K_C0000_MSR 0x268
-#define MTRRfix4K_C8000_MSR 0x269
-#define MTRRfix4K_D0000_MSR 0x26a
-#define MTRRfix4K_D8000_MSR 0x26b
-#define MTRRfix4K_E0000_MSR 0x26c
-#define MTRRfix4K_E8000_MSR 0x26d
-#define MTRRfix4K_F0000_MSR 0x26e
-#define MTRRfix4K_F8000_MSR 0x26f
-
 #define MTRR_CHANGE_MASK_FIXED     0x01
 #define MTRR_CHANGE_MASK_VARIABLE  0x02
 #define MTRR_CHANGE_MASK_DEFTYPE   0x04
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/state.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/state.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/mtrr/state.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/mtrr/state.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,7 @@
 
 		if (use_intel())
 			/*  Save MTRR state */
-			rdmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
+			rdmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
 		else
 			/* Cyrix ARRs - everything else were excluded at the top */
 			ctxt->ccr3 = getCx86(CX86_CCR3);
@@ -46,7 +46,7 @@
 {
 	if (use_intel())
 		/*  Disable MTRRs, and set the default type to uncached  */
-		mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL,
+		mtrr_wrmsr(MSR_MTRRdefType, ctxt->deftype_lo & 0xf300UL,
 		      ctxt->deftype_hi);
 	else if (is_cpu(CYRIX))
 		/* Cyrix ARRs - everything else were excluded at the top */
@@ -64,7 +64,7 @@
 		/*  Restore MTRRdefType  */
 		if (use_intel())
 			/* Intel (P6) standard MTRRs */
-			mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
+			mtrr_wrmsr(MSR_MTRRdefType, ctxt->deftype_lo, ctxt->deftype_hi);
 		else
 			/* Cyrix ARRs - everything else was excluded at the top */
 			setCx86(CX86_CCR3, ctxt->ccr3);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/perf_counter.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/perf_counter.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/perf_counter.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/perf_counter.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1964 @@
+/*
+ * Performance counter x86 architecture code
+ *
+ *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ *  Copyright (C) 2009 Jaswinder Singh Rajput
+ *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_counter.h>
+#include <linux/capability.h>
+#include <linux/notifier.h>
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
+#include <linux/module.h>
+#include <linux/kdebug.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/highmem.h>
+
+#include <asm/apic.h>
+#include <asm/stacktrace.h>
+#include <asm/nmi.h>
+
+static u64 perf_counter_mask __read_mostly;
+
+struct cpu_hw_counters {
+	struct perf_counter	*counters[X86_PMC_IDX_MAX];
+	unsigned long		used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	unsigned long		active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	unsigned long		interrupts;
+	int			enabled;
+};
+
+/*
+ * struct x86_pmu - generic x86 pmu
+ */
+struct x86_pmu {
+	const char	*name;
+	int		version;
+	int		(*handle_irq)(struct pt_regs *);
+	void		(*disable_all)(void);
+	void		(*enable_all)(void);
+	void		(*enable)(struct hw_perf_counter *, int);
+	void		(*disable)(struct hw_perf_counter *, int);
+	unsigned	eventsel;
+	unsigned	perfctr;
+	u64		(*event_map)(int);
+	u64		(*raw_event)(u64);
+	int		max_events;
+	int		num_counters;
+	int		num_counters_fixed;
+	int		counter_bits;
+	u64		counter_mask;
+	int		apic;
+	u64		max_period;
+	u64		intel_ctrl;
+};
+
+static struct x86_pmu x86_pmu __read_mostly;
+
+static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = {
+	.enabled = 1,
+};
+
+/*
+ * Not sure about some of these
+ */
+static const u64 p6_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0079,
+  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,
+  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0f2e,
+  [PERF_COUNT_HW_CACHE_MISSES]		= 0x012e,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4,
+  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5,
+  [PERF_COUNT_HW_BUS_CYCLES]		= 0x0062,
+};
+
+static u64 p6_pmu_event_map(int event)
+{
+	return p6_perfmon_event_map[event];
+}
+
+/*
+ * Counter setting that is specified not to count anything.
+ * We use this to effectively disable a counter.
+ *
+ * L2_RQSTS with 0 MESI unit mask.
+ */
+#define P6_NOP_COUNTER			0x0000002EULL
+
+static u64 p6_pmu_raw_event(u64 event)
+{
+#define P6_EVNTSEL_EVENT_MASK		0x000000FFULL
+#define P6_EVNTSEL_UNIT_MASK		0x0000FF00ULL
+#define P6_EVNTSEL_EDGE_MASK		0x00040000ULL
+#define P6_EVNTSEL_INV_MASK		0x00800000ULL
+#define P6_EVNTSEL_COUNTER_MASK		0xFF000000ULL
+
+#define P6_EVNTSEL_MASK			\
+	(P6_EVNTSEL_EVENT_MASK |	\
+	 P6_EVNTSEL_UNIT_MASK  |	\
+	 P6_EVNTSEL_EDGE_MASK  |	\
+	 P6_EVNTSEL_INV_MASK   |	\
+	 P6_EVNTSEL_COUNTER_MASK)
+
+	return event & P6_EVNTSEL_MASK;
+}
+
+
+/*
+ * Intel PerfMon v3. Used on Core2 and later.
+ */
+static const u64 intel_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]		= 0x003c,
+  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,
+  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x4f2e,
+  [PERF_COUNT_HW_CACHE_MISSES]		= 0x412e,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4,
+  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5,
+  [PERF_COUNT_HW_BUS_CYCLES]		= 0x013c,
+};
+
+static u64 intel_pmu_event_map(int event)
+{
+	return intel_perfmon_event_map[event];
+}
+
+/*
+ * Generalized hw caching related event table, filled
+ * in on a per model basis. A value of 0 means
+ * 'not supported', -1 means 'event makes no sense on
+ * this CPU', any other value means the raw event
+ * ID.
+ */
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+static u64 __read_mostly hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+
+static const u64 nehalem_hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI            */
+		[ C(RESULT_MISS)   ] = 0x0140, /* L1D_CACHE_LD.I_STATE         */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI            */
+		[ C(RESULT_MISS)   ] = 0x0141, /* L1D_CACHE_ST.I_STATE         */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
+		[ C(RESULT_MISS)   ] = 0x024e, /* L1D_PREFETCH.MISS            */
+	},
+ },
+ [ C(L1I ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                    */
+		[ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                   */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0,
+	},
+ },
+ [ C(LL  ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS               */
+		[ C(RESULT_MISS)   ] = 0x0224, /* L2_RQSTS.LD_MISS             */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS                */
+		[ C(RESULT_MISS)   ] = 0x0824, /* L2_RQSTS.RFO_MISS            */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference                */
+		[ C(RESULT_MISS)   ] = 0x412e, /* LLC Misses                   */
+	},
+ },
+ [ C(DTLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI   (alias)  */
+		[ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.ANY         */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI   (alias)  */
+		[ C(RESULT_MISS)   ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS  */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0,
+	},
+ },
+ [ C(ITLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P           */
+		[ C(RESULT_MISS)   ] = 0x20c8, /* ITLB_MISS_RETIRED            */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+ [ C(BPU ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
+		[ C(RESULT_MISS)   ] = 0x03e8, /* BPU_CLEARS.ANY               */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+};
+
+static const u64 core2_hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI          */
+		[ C(RESULT_MISS)   ] = 0x0140, /* L1D_CACHE_LD.I_STATE       */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI          */
+		[ C(RESULT_MISS)   ] = 0x0141, /* L1D_CACHE_ST.I_STATE       */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x104e, /* L1D_PREFETCH.REQUESTS      */
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(L1I ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0080, /* L1I.READS                  */
+		[ C(RESULT_MISS)   ] = 0x0081, /* L1I.MISSES                 */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(LL  ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI                 */
+		[ C(RESULT_MISS)   ] = 0x4129, /* L2_LD.ISTATE               */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI                 */
+		[ C(RESULT_MISS)   ] = 0x412A, /* L2_ST.ISTATE               */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(DTLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI  (alias) */
+		[ C(RESULT_MISS)   ] = 0x0208, /* DTLB_MISSES.MISS_LD        */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI  (alias) */
+		[ C(RESULT_MISS)   ] = 0x0808, /* DTLB_MISSES.MISS_ST        */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(ITLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P         */
+		[ C(RESULT_MISS)   ] = 0x1282, /* ITLBMISSES                 */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+ [ C(BPU ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY        */
+		[ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED    */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+};
+
+static const u64 atom_hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE.LD               */
+		[ C(RESULT_MISS)   ] = 0,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE.ST               */
+		[ C(RESULT_MISS)   ] = 0,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(L1I ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                  */
+		[ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                 */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(LL  ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI                 */
+		[ C(RESULT_MISS)   ] = 0x4129, /* L2_LD.ISTATE               */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI                 */
+		[ C(RESULT_MISS)   ] = 0x412A, /* L2_ST.ISTATE               */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(DTLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE_LD.MESI  (alias) */
+		[ C(RESULT_MISS)   ] = 0x0508, /* DTLB_MISSES.MISS_LD        */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE_ST.MESI  (alias) */
+		[ C(RESULT_MISS)   ] = 0x0608, /* DTLB_MISSES.MISS_ST        */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(ITLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P         */
+		[ C(RESULT_MISS)   ] = 0x0282, /* ITLB.MISSES                */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+ [ C(BPU ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY        */
+		[ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED    */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+};
+
+static u64 intel_pmu_raw_event(u64 event)
+{
+#define CORE_EVNTSEL_EVENT_MASK		0x000000FFULL
+#define CORE_EVNTSEL_UNIT_MASK		0x0000FF00ULL
+#define CORE_EVNTSEL_EDGE_MASK		0x00040000ULL
+#define CORE_EVNTSEL_INV_MASK		0x00800000ULL
+#define CORE_EVNTSEL_COUNTER_MASK	0xFF000000ULL
+
+#define CORE_EVNTSEL_MASK		\
+	(CORE_EVNTSEL_EVENT_MASK |	\
+	 CORE_EVNTSEL_UNIT_MASK  |	\
+	 CORE_EVNTSEL_EDGE_MASK  |	\
+	 CORE_EVNTSEL_INV_MASK  |	\
+	 CORE_EVNTSEL_COUNTER_MASK)
+
+	return event & CORE_EVNTSEL_MASK;
+}
+
+static const u64 amd_hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
+		[ C(RESULT_MISS)   ] = 0x0041, /* Data Cache Misses          */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */
+		[ C(RESULT_MISS)   ] = 0,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts  */
+		[ C(RESULT_MISS)   ] = 0x0167, /* Data Prefetcher :cancelled */
+	},
+ },
+ [ C(L1I ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0080, /* Instruction cache fetches  */
+		[ C(RESULT_MISS)   ] = 0x0081, /* Instruction cache misses   */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(LL  ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */
+		[ C(RESULT_MISS)   ] = 0x037E, /* L2 Cache Misses : IC+DC     */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback           */
+		[ C(RESULT_MISS)   ] = 0,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(DTLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
+		[ C(RESULT_MISS)   ] = 0x0046, /* L1 DTLB and L2 DLTB Miss   */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0,
+		[ C(RESULT_MISS)   ] = 0,
+	},
+ },
+ [ C(ITLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes        */
+		[ C(RESULT_MISS)   ] = 0x0085, /* Instr. fetch ITLB misses   */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+ [ C(BPU ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c2, /* Retired Branch Instr.      */
+		[ C(RESULT_MISS)   ] = 0x00c3, /* Retired Mispredicted BI    */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+};
+
+/*
+ * AMD Performance Monitor K7 and later.
+ */
+static const u64 amd_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0076,
+  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,
+  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0080,
+  [PERF_COUNT_HW_CACHE_MISSES]		= 0x0081,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4,
+  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5,
+};
+
+static u64 amd_pmu_event_map(int event)
+{
+	return amd_perfmon_event_map[event];
+}
+
+static u64 amd_pmu_raw_event(u64 event)
+{
+#define K7_EVNTSEL_EVENT_MASK	0x7000000FFULL
+#define K7_EVNTSEL_UNIT_MASK	0x00000FF00ULL
+#define K7_EVNTSEL_EDGE_MASK	0x000040000ULL
+#define K7_EVNTSEL_INV_MASK	0x000800000ULL
+#define K7_EVNTSEL_COUNTER_MASK	0x0FF000000ULL
+
+#define K7_EVNTSEL_MASK			\
+	(K7_EVNTSEL_EVENT_MASK |	\
+	 K7_EVNTSEL_UNIT_MASK  |	\
+	 K7_EVNTSEL_EDGE_MASK  |	\
+	 K7_EVNTSEL_INV_MASK   |	\
+	 K7_EVNTSEL_COUNTER_MASK)
+
+	return event & K7_EVNTSEL_MASK;
+}
+
+/*
+ * Propagate counter elapsed time into the generic counter.
+ * Can only be executed on the CPU where the counter is active.
+ * Returns the delta events processed.
+ */
+static u64
+x86_perf_counter_update(struct perf_counter *counter,
+			struct hw_perf_counter *hwc, int idx)
+{
+	int shift = 64 - x86_pmu.counter_bits;
+	u64 prev_raw_count, new_raw_count;
+	s64 delta;
+
+	/*
+	 * Careful: an NMI might modify the previous counter value.
+	 *
+	 * Our tactic to handle this is to first atomically read and
+	 * exchange a new raw count - then add that new-prev delta
+	 * count to the generic counter atomically:
+	 */
+again:
+	prev_raw_count = atomic64_read(&hwc->prev_count);
+	rdmsrl(hwc->counter_base + idx, new_raw_count);
+
+	if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
+					new_raw_count) != prev_raw_count)
+		goto again;
+
+	/*
+	 * Now we have the new raw value and have updated the prev
+	 * timestamp already. We can now calculate the elapsed delta
+	 * (counter-)time and add that to the generic counter.
+	 *
+	 * Careful, not all hw sign-extends above the physical width
+	 * of the count.
+	 */
+	delta = (new_raw_count << shift) - (prev_raw_count << shift);
+	delta >>= shift;
+
+	atomic64_add(delta, &counter->count);
+	atomic64_sub(delta, &hwc->period_left);
+
+	return new_raw_count;
+}
+
+static atomic_t active_counters;
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+static bool reserve_pmc_hardware(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	int i;
+
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		disable_lapic_nmi_watchdog();
+
+	for (i = 0; i < x86_pmu.num_counters; i++) {
+		if (!reserve_perfctr_nmi(x86_pmu.perfctr + i))
+			goto perfctr_fail;
+	}
+
+	for (i = 0; i < x86_pmu.num_counters; i++) {
+		if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
+			goto eventsel_fail;
+	}
+#endif
+
+	return true;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+eventsel_fail:
+	for (i--; i >= 0; i--)
+		release_evntsel_nmi(x86_pmu.eventsel + i);
+
+	i = x86_pmu.num_counters;
+
+perfctr_fail:
+	for (i--; i >= 0; i--)
+		release_perfctr_nmi(x86_pmu.perfctr + i);
+
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		enable_lapic_nmi_watchdog();
+
+	return false;
+#endif
+}
+
+static void release_pmc_hardware(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	int i;
+
+	for (i = 0; i < x86_pmu.num_counters; i++) {
+		release_perfctr_nmi(x86_pmu.perfctr + i);
+		release_evntsel_nmi(x86_pmu.eventsel + i);
+	}
+
+	if (nmi_watchdog == NMI_LOCAL_APIC)
+		enable_lapic_nmi_watchdog();
+#endif
+}
+
+static void hw_perf_counter_destroy(struct perf_counter *counter)
+{
+	if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) {
+		release_pmc_hardware();
+		mutex_unlock(&pmc_reserve_mutex);
+	}
+}
+
+static inline int x86_pmu_initialized(void)
+{
+	return x86_pmu.handle_irq != NULL;
+}
+
+static inline int
+set_ext_hw_attr(struct hw_perf_counter *hwc, struct perf_counter_attr *attr)
+{
+	unsigned int cache_type, cache_op, cache_result;
+	u64 config, val;
+
+	config = attr->config;
+
+	cache_type = (config >>  0) & 0xff;
+	if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
+		return -EINVAL;
+
+	cache_op = (config >>  8) & 0xff;
+	if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
+		return -EINVAL;
+
+	cache_result = (config >> 16) & 0xff;
+	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+		return -EINVAL;
+
+	val = hw_cache_event_ids[cache_type][cache_op][cache_result];
+
+	if (val == 0)
+		return -ENOENT;
+
+	if (val == -1)
+		return -EINVAL;
+
+	hwc->config |= val;
+
+	return 0;
+}
+
+/*
+ * Setup the hardware configuration for a given attr_type
+ */
+static int __hw_perf_counter_init(struct perf_counter *counter)
+{
+	struct perf_counter_attr *attr = &counter->attr;
+	struct hw_perf_counter *hwc = &counter->hw;
+	u64 config;
+	int err;
+
+	if (!x86_pmu_initialized())
+		return -ENODEV;
+
+	err = 0;
+	if (!atomic_inc_not_zero(&active_counters)) {
+		mutex_lock(&pmc_reserve_mutex);
+		if (atomic_read(&active_counters) == 0 && !reserve_pmc_hardware())
+			err = -EBUSY;
+		else
+			atomic_inc(&active_counters);
+		mutex_unlock(&pmc_reserve_mutex);
+	}
+	if (err)
+		return err;
+
+	/*
+	 * Generate PMC IRQs:
+	 * (keep 'enabled' bit clear for now)
+	 */
+	hwc->config = ARCH_PERFMON_EVENTSEL_INT;
+
+	/*
+	 * Count user and OS events unless requested not to.
+	 */
+	if (!attr->exclude_user)
+		hwc->config |= ARCH_PERFMON_EVENTSEL_USR;
+	if (!attr->exclude_kernel)
+		hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
+
+	if (!hwc->sample_period) {
+		hwc->sample_period = x86_pmu.max_period;
+		hwc->last_period = hwc->sample_period;
+		atomic64_set(&hwc->period_left, hwc->sample_period);
+	} else {
+		/*
+		 * If we have a PMU initialized but no APIC
+		 * interrupts, we cannot sample hardware
+		 * counters (user-space has to fall back and
+		 * sample via a hrtimer based software counter):
+		 */
+		if (!x86_pmu.apic)
+			return -EOPNOTSUPP;
+	}
+
+	counter->destroy = hw_perf_counter_destroy;
+
+	/*
+	 * Raw event type provide the config in the event structure
+	 */
+	if (attr->type == PERF_TYPE_RAW) {
+		hwc->config |= x86_pmu.raw_event(attr->config);
+		return 0;
+	}
+
+	if (attr->type == PERF_TYPE_HW_CACHE)
+		return set_ext_hw_attr(hwc, attr);
+
+	if (attr->config >= x86_pmu.max_events)
+		return -EINVAL;
+
+	/*
+	 * The generic map:
+	 */
+	config = x86_pmu.event_map(attr->config);
+
+	if (config == 0)
+		return -ENOENT;
+
+	if (config == -1LL)
+		return -EINVAL;
+
+	hwc->config |= config;
+
+	return 0;
+}
+
+static void p6_pmu_disable_all(void)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	u64 val;
+
+	if (!cpuc->enabled)
+		return;
+
+	cpuc->enabled = 0;
+	barrier();
+
+	/* p6 only has one enable register */
+	rdmsrl(MSR_P6_EVNTSEL0, val);
+	val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+	wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
+static void intel_pmu_disable_all(void)
+{
+	wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+}
+
+static void amd_pmu_disable_all(void)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	int idx;
+
+	if (!cpuc->enabled)
+		return;
+
+	cpuc->enabled = 0;
+	/*
+	 * ensure we write the disable before we start disabling the
+	 * counters proper, so that amd_pmu_enable_counter() does the
+	 * right thing.
+	 */
+	barrier();
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		u64 val;
+
+		if (!test_bit(idx, cpuc->active_mask))
+			continue;
+		rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
+		if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE))
+			continue;
+		val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+		wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
+	}
+}
+
+void hw_perf_disable(void)
+{
+	if (!x86_pmu_initialized())
+		return;
+	return x86_pmu.disable_all();
+}
+
+static void p6_pmu_enable_all(void)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	unsigned long val;
+
+	if (cpuc->enabled)
+		return;
+
+	cpuc->enabled = 1;
+	barrier();
+
+	/* p6 only has one enable register */
+	rdmsrl(MSR_P6_EVNTSEL0, val);
+	val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+	wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
+static void intel_pmu_enable_all(void)
+{
+	wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
+}
+
+static void amd_pmu_enable_all(void)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	int idx;
+
+	if (cpuc->enabled)
+		return;
+
+	cpuc->enabled = 1;
+	barrier();
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		struct perf_counter *counter = cpuc->counters[idx];
+		u64 val;
+
+		if (!test_bit(idx, cpuc->active_mask))
+			continue;
+
+		val = counter->hw.config;
+		val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+		wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
+	}
+}
+
+void hw_perf_enable(void)
+{
+	if (!x86_pmu_initialized())
+		return;
+	x86_pmu.enable_all();
+}
+
+static inline u64 intel_pmu_get_status(void)
+{
+	u64 status;
+
+	rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
+
+	return status;
+}
+
+static inline void intel_pmu_ack_status(u64 ack)
+{
+	wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
+}
+
+static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	(void)checking_wrmsrl(hwc->config_base + idx,
+			      hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
+}
+
+static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	(void)checking_wrmsrl(hwc->config_base + idx, hwc->config);
+}
+
+static inline void
+intel_pmu_disable_fixed(struct hw_perf_counter *hwc, int __idx)
+{
+	int idx = __idx - X86_PMC_IDX_FIXED;
+	u64 ctrl_val, mask;
+
+	mask = 0xfULL << (idx * 4);
+
+	rdmsrl(hwc->config_base, ctrl_val);
+	ctrl_val &= ~mask;
+	(void)checking_wrmsrl(hwc->config_base, ctrl_val);
+}
+
+static inline void
+p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	u64 val = P6_NOP_COUNTER;
+
+	if (cpuc->enabled)
+		val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+
+	(void)checking_wrmsrl(hwc->config_base + idx, val);
+}
+
+static inline void
+intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
+		intel_pmu_disable_fixed(hwc, idx);
+		return;
+	}
+
+	x86_pmu_disable_counter(hwc, idx);
+}
+
+static inline void
+amd_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	x86_pmu_disable_counter(hwc, idx);
+}
+
+static DEFINE_PER_CPU(u64, prev_left[X86_PMC_IDX_MAX]);
+
+/*
+ * Set the next IRQ period, based on the hwc->period_left value.
+ * To be called with the counter disabled in hw:
+ */
+static int
+x86_perf_counter_set_period(struct perf_counter *counter,
+			     struct hw_perf_counter *hwc, int idx)
+{
+	s64 left = atomic64_read(&hwc->period_left);
+	s64 period = hwc->sample_period;
+	int err, ret = 0;
+
+	/*
+	 * If we are way outside a reasoable range then just skip forward:
+	 */
+	if (unlikely(left <= -period)) {
+		left = period;
+		atomic64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	}
+
+	if (unlikely(left <= 0)) {
+		left += period;
+		atomic64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	}
+	/*
+	 * Quirk: certain CPUs dont like it if just 1 event is left:
+	 */
+	if (unlikely(left < 2))
+		left = 2;
+
+	if (left > x86_pmu.max_period)
+		left = x86_pmu.max_period;
+
+	per_cpu(prev_left[idx], smp_processor_id()) = left;
+
+	/*
+	 * The hw counter starts counting from this counter offset,
+	 * mark it to be able to extra future deltas:
+	 */
+	atomic64_set(&hwc->prev_count, (u64)-left);
+
+	err = checking_wrmsrl(hwc->counter_base + idx,
+			     (u64)(-left) & x86_pmu.counter_mask);
+
+	perf_counter_update_userpage(counter);
+
+	return ret;
+}
+
+static inline void
+intel_pmu_enable_fixed(struct hw_perf_counter *hwc, int __idx)
+{
+	int idx = __idx - X86_PMC_IDX_FIXED;
+	u64 ctrl_val, bits, mask;
+	int err;
+
+	/*
+	 * Enable IRQ generation (0x8),
+	 * and enable ring-3 counting (0x2) and ring-0 counting (0x1)
+	 * if requested:
+	 */
+	bits = 0x8ULL;
+	if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
+		bits |= 0x2;
+	if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)
+		bits |= 0x1;
+	bits <<= (idx * 4);
+	mask = 0xfULL << (idx * 4);
+
+	rdmsrl(hwc->config_base, ctrl_val);
+	ctrl_val &= ~mask;
+	ctrl_val |= bits;
+	err = checking_wrmsrl(hwc->config_base, ctrl_val);
+}
+
+static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	u64 val;
+
+	val = hwc->config;
+	if (cpuc->enabled)
+		val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+
+	(void)checking_wrmsrl(hwc->config_base + idx, val);
+}
+
+
+static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
+		intel_pmu_enable_fixed(hwc, idx);
+		return;
+	}
+
+	x86_pmu_enable_counter(hwc, idx);
+}
+
+static void amd_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+
+	if (cpuc->enabled)
+		x86_pmu_enable_counter(hwc, idx);
+}
+
+static int
+fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc)
+{
+	unsigned int event;
+
+	if (!x86_pmu.num_counters_fixed)
+		return -1;
+
+	event = hwc->config & ARCH_PERFMON_EVENT_MASK;
+
+	if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS)))
+		return X86_PMC_IDX_FIXED_INSTRUCTIONS;
+	if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES)))
+		return X86_PMC_IDX_FIXED_CPU_CYCLES;
+	if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_BUS_CYCLES)))
+		return X86_PMC_IDX_FIXED_BUS_CYCLES;
+
+	return -1;
+}
+
+/*
+ * Find a PMC slot for the freshly enabled / scheduled in counter:
+ */
+static int x86_pmu_enable(struct perf_counter *counter)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	struct hw_perf_counter *hwc = &counter->hw;
+	int idx;
+
+	idx = fixed_mode_idx(counter, hwc);
+	if (idx >= 0) {
+		/*
+		 * Try to get the fixed counter, if that is already taken
+		 * then try to get a generic counter:
+		 */
+		if (test_and_set_bit(idx, cpuc->used_mask))
+			goto try_generic;
+
+		hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
+		/*
+		 * We set it so that counter_base + idx in wrmsr/rdmsr maps to
+		 * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
+		 */
+		hwc->counter_base =
+			MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
+		hwc->idx = idx;
+	} else {
+		idx = hwc->idx;
+		/* Try to get the previous generic counter again */
+		if (test_and_set_bit(idx, cpuc->used_mask)) {
+try_generic:
+			idx = find_first_zero_bit(cpuc->used_mask,
+						  x86_pmu.num_counters);
+			if (idx == x86_pmu.num_counters)
+				return -EAGAIN;
+
+			set_bit(idx, cpuc->used_mask);
+			hwc->idx = idx;
+		}
+		hwc->config_base  = x86_pmu.eventsel;
+		hwc->counter_base = x86_pmu.perfctr;
+	}
+
+	perf_counters_lapic_init();
+
+	x86_pmu.disable(hwc, idx);
+
+	cpuc->counters[idx] = counter;
+	set_bit(idx, cpuc->active_mask);
+
+	x86_perf_counter_set_period(counter, hwc, idx);
+	x86_pmu.enable(hwc, idx);
+
+	perf_counter_update_userpage(counter);
+
+	return 0;
+}
+
+static void x86_pmu_unthrottle(struct perf_counter *counter)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	struct hw_perf_counter *hwc = &counter->hw;
+
+	if (WARN_ON_ONCE(hwc->idx >= X86_PMC_IDX_MAX ||
+				cpuc->counters[hwc->idx] != counter))
+		return;
+
+	x86_pmu.enable(hwc, hwc->idx);
+}
+
+void perf_counter_print_debug(void)
+{
+	u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
+	struct cpu_hw_counters *cpuc;
+	unsigned long flags;
+	int cpu, idx;
+
+	if (!x86_pmu.num_counters)
+		return;
+
+	local_irq_save(flags);
+
+	cpu = smp_processor_id();
+	cpuc = &per_cpu(cpu_hw_counters, cpu);
+
+	if (x86_pmu.version >= 2) {
+		rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
+		rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
+		rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
+		rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
+
+		pr_info("\n");
+		pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
+		pr_info("CPU#%d: status:     %016llx\n", cpu, status);
+		pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
+		pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+	}
+	pr_info("CPU#%d: used:       %016llx\n", cpu, *(u64 *)cpuc->used_mask);
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl);
+		rdmsrl(x86_pmu.perfctr  + idx, pmc_count);
+
+		prev_left = per_cpu(prev_left[idx], cpu);
+
+		pr_info("CPU#%d:   gen-PMC%d ctrl:  %016llx\n",
+			cpu, idx, pmc_ctrl);
+		pr_info("CPU#%d:   gen-PMC%d count: %016llx\n",
+			cpu, idx, pmc_count);
+		pr_info("CPU#%d:   gen-PMC%d left:  %016llx\n",
+			cpu, idx, prev_left);
+	}
+	for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) {
+		rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
+
+		pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
+			cpu, idx, pmc_count);
+	}
+	local_irq_restore(flags);
+}
+
+static void x86_pmu_disable(struct perf_counter *counter)
+{
+	struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+	struct hw_perf_counter *hwc = &counter->hw;
+	int idx = hwc->idx;
+
+	/*
+	 * Must be done before we disable, otherwise the nmi handler
+	 * could reenable again:
+	 */
+	clear_bit(idx, cpuc->active_mask);
+	x86_pmu.disable(hwc, idx);
+
+	/*
+	 * Make sure the cleared pointer becomes visible before we
+	 * (potentially) free the counter:
+	 */
+	barrier();
+
+	/*
+	 * Drain the remaining delta count out of a counter
+	 * that we are disabling:
+	 */
+	x86_perf_counter_update(counter, hwc, idx);
+	cpuc->counters[idx] = NULL;
+	clear_bit(idx, cpuc->used_mask);
+
+	perf_counter_update_userpage(counter);
+}
+
+/*
+ * Save and restart an expired counter. Called by NMI contexts,
+ * so it has to be careful about preempting normal counter ops:
+ */
+static int intel_pmu_save_and_restart(struct perf_counter *counter)
+{
+	struct hw_perf_counter *hwc = &counter->hw;
+	int idx = hwc->idx;
+	int ret;
+
+	x86_perf_counter_update(counter, hwc, idx);
+	ret = x86_perf_counter_set_period(counter, hwc, idx);
+
+	if (counter->state == PERF_COUNTER_STATE_ACTIVE)
+		intel_pmu_enable_counter(hwc, idx);
+
+	return ret;
+}
+
+static void intel_pmu_reset(void)
+{
+	unsigned long flags;
+	int idx;
+
+	if (!x86_pmu.num_counters)
+		return;
+
+	local_irq_save(flags);
+
+	printk("clearing PMU state on CPU#%d\n", smp_processor_id());
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		checking_wrmsrl(x86_pmu.eventsel + idx, 0ull);
+		checking_wrmsrl(x86_pmu.perfctr  + idx, 0ull);
+	}
+	for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) {
+		checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
+	}
+
+	local_irq_restore(flags);
+}
+
+static int p6_pmu_handle_irq(struct pt_regs *regs)
+{
+	struct perf_sample_data data;
+	struct cpu_hw_counters *cpuc;
+	struct perf_counter *counter;
+	struct hw_perf_counter *hwc;
+	int idx, handled = 0;
+	u64 val;
+
+	data.regs = regs;
+	data.addr = 0;
+
+	cpuc = &__get_cpu_var(cpu_hw_counters);
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		if (!test_bit(idx, cpuc->active_mask))
+			continue;
+
+		counter = cpuc->counters[idx];
+		hwc = &counter->hw;
+
+		val = x86_perf_counter_update(counter, hwc, idx);
+		if (val & (1ULL << (x86_pmu.counter_bits - 1)))
+			continue;
+
+		/*
+		 * counter overflow
+		 */
+		handled		= 1;
+		data.period	= counter->hw.last_period;
+
+		if (!x86_perf_counter_set_period(counter, hwc, idx))
+			continue;
+
+		if (perf_counter_overflow(counter, 1, &data))
+			p6_pmu_disable_counter(hwc, idx);
+	}
+
+	if (handled)
+		inc_irq_stat(apic_perf_irqs);
+
+	return handled;
+}
+
+/*
+ * This handler is triggered by the local APIC, so the APIC IRQ handling
+ * rules apply:
+ */
+static int intel_pmu_handle_irq(struct pt_regs *regs)
+{
+	struct perf_sample_data data;
+	struct cpu_hw_counters *cpuc;
+	int bit, loops;
+	u64 ack, status;
+
+	data.regs = regs;
+	data.addr = 0;
+
+	cpuc = &__get_cpu_var(cpu_hw_counters);
+
+	perf_disable();
+	status = intel_pmu_get_status();
+	if (!status) {
+		perf_enable();
+		return 0;
+	}
+
+	loops = 0;
+again:
+	if (++loops > 100) {
+		WARN_ONCE(1, "perfcounters: irq loop stuck!\n");
+		perf_counter_print_debug();
+		intel_pmu_reset();
+		perf_enable();
+		return 1;
+	}
+
+	inc_irq_stat(apic_perf_irqs);
+	ack = status;
+	for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+		struct perf_counter *counter = cpuc->counters[bit];
+
+		clear_bit(bit, (unsigned long *) &status);
+		if (!test_bit(bit, cpuc->active_mask))
+			continue;
+
+		if (!intel_pmu_save_and_restart(counter))
+			continue;
+
+		data.period = counter->hw.last_period;
+
+		if (perf_counter_overflow(counter, 1, &data))
+			intel_pmu_disable_counter(&counter->hw, bit);
+	}
+
+	intel_pmu_ack_status(ack);
+
+	/*
+	 * Repeat if there is more work to be done:
+	 */
+	status = intel_pmu_get_status();
+	if (status)
+		goto again;
+
+	perf_enable();
+
+	return 1;
+}
+
+static int amd_pmu_handle_irq(struct pt_regs *regs)
+{
+	struct perf_sample_data data;
+	struct cpu_hw_counters *cpuc;
+	struct perf_counter *counter;
+	struct hw_perf_counter *hwc;
+	int idx, handled = 0;
+	u64 val;
+
+	data.regs = regs;
+	data.addr = 0;
+
+	cpuc = &__get_cpu_var(cpu_hw_counters);
+
+	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		if (!test_bit(idx, cpuc->active_mask))
+			continue;
+
+		counter = cpuc->counters[idx];
+		hwc = &counter->hw;
+
+		val = x86_perf_counter_update(counter, hwc, idx);
+		if (val & (1ULL << (x86_pmu.counter_bits - 1)))
+			continue;
+
+		/*
+		 * counter overflow
+		 */
+		handled		= 1;
+		data.period	= counter->hw.last_period;
+
+		if (!x86_perf_counter_set_period(counter, hwc, idx))
+			continue;
+
+		if (perf_counter_overflow(counter, 1, &data))
+			amd_pmu_disable_counter(hwc, idx);
+	}
+
+	if (handled)
+		inc_irq_stat(apic_perf_irqs);
+
+	return handled;
+}
+
+void smp_perf_pending_interrupt(struct pt_regs *regs)
+{
+	irq_enter();
+	ack_APIC_irq();
+	inc_irq_stat(apic_pending_irqs);
+	perf_counter_do_pending();
+	irq_exit();
+}
+
+void set_perf_counter_pending(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	apic->send_IPI_self(LOCAL_PENDING_VECTOR);
+#endif
+}
+
+void perf_counters_lapic_init(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (!x86_pmu.apic || !x86_pmu_initialized())
+		return;
+
+	/*
+	 * Always use NMI for PMU
+	 */
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+#endif
+}
+
+static int __kprobes
+perf_counter_nmi_handler(struct notifier_block *self,
+			 unsigned long cmd, void *__args)
+{
+	struct die_args *args = __args;
+	struct pt_regs *regs;
+
+	if (!atomic_read(&active_counters))
+		return NOTIFY_DONE;
+
+	switch (cmd) {
+	case DIE_NMI:
+	case DIE_NMI_IPI:
+		break;
+
+	default:
+		return NOTIFY_DONE;
+	}
+
+	regs = args->regs;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+#endif
+	/*
+	 * Can't rely on the handled return value to say it was our NMI, two
+	 * counters could trigger 'simultaneously' raising two back-to-back NMIs.
+	 *
+	 * If the first NMI handles both, the latter will be empty and daze
+	 * the CPU.
+	 */
+	x86_pmu.handle_irq(regs);
+
+	return NOTIFY_STOP;
+}
+
+static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
+	.notifier_call		= perf_counter_nmi_handler,
+	.next			= NULL,
+	.priority		= 1
+};
+
+static struct x86_pmu p6_pmu = {
+	.name			= "p6",
+	.handle_irq		= p6_pmu_handle_irq,
+	.disable_all		= p6_pmu_disable_all,
+	.enable_all		= p6_pmu_enable_all,
+	.enable			= p6_pmu_enable_counter,
+	.disable		= p6_pmu_disable_counter,
+	.eventsel		= MSR_P6_EVNTSEL0,
+	.perfctr		= MSR_P6_PERFCTR0,
+	.event_map		= p6_pmu_event_map,
+	.raw_event		= p6_pmu_raw_event,
+	.max_events		= ARRAY_SIZE(p6_perfmon_event_map),
+	.apic			= 1,
+	.max_period		= (1ULL << 31) - 1,
+	.version		= 0,
+	.num_counters		= 2,
+	/*
+	 * Counters have 40 bits implemented. However they are designed such
+	 * that bits [32-39] are sign extensions of bit 31. As such the
+	 * effective width of a counter for P6-like PMU is 32 bits only.
+	 *
+	 * See IA-32 Intel Architecture Software developer manual Vol 3B
+	 */
+	.counter_bits		= 32,
+	.counter_mask		= (1ULL << 32) - 1,
+};
+
+static struct x86_pmu intel_pmu = {
+	.name			= "Intel",
+	.handle_irq		= intel_pmu_handle_irq,
+	.disable_all		= intel_pmu_disable_all,
+	.enable_all		= intel_pmu_enable_all,
+	.enable			= intel_pmu_enable_counter,
+	.disable		= intel_pmu_disable_counter,
+	.eventsel		= MSR_ARCH_PERFMON_EVENTSEL0,
+	.perfctr		= MSR_ARCH_PERFMON_PERFCTR0,
+	.event_map		= intel_pmu_event_map,
+	.raw_event		= intel_pmu_raw_event,
+	.max_events		= ARRAY_SIZE(intel_perfmon_event_map),
+	.apic			= 1,
+	/*
+	 * Intel PMCs cannot be accessed sanely above 32 bit width,
+	 * so we install an artificial 1<<31 period regardless of
+	 * the generic counter period:
+	 */
+	.max_period		= (1ULL << 31) - 1,
+};
+
+static struct x86_pmu amd_pmu = {
+	.name			= "AMD",
+	.handle_irq		= amd_pmu_handle_irq,
+	.disable_all		= amd_pmu_disable_all,
+	.enable_all		= amd_pmu_enable_all,
+	.enable			= amd_pmu_enable_counter,
+	.disable		= amd_pmu_disable_counter,
+	.eventsel		= MSR_K7_EVNTSEL0,
+	.perfctr		= MSR_K7_PERFCTR0,
+	.event_map		= amd_pmu_event_map,
+	.raw_event		= amd_pmu_raw_event,
+	.max_events		= ARRAY_SIZE(amd_perfmon_event_map),
+	.num_counters		= 4,
+	.counter_bits		= 48,
+	.counter_mask		= (1ULL << 48) - 1,
+	.apic			= 1,
+	/* use highest bit to detect overflow */
+	.max_period		= (1ULL << 47) - 1,
+};
+
+static int p6_pmu_init(void)
+{
+	switch (boot_cpu_data.x86_model) {
+	case 1:
+	case 3:  /* Pentium Pro */
+	case 5:
+	case 6:  /* Pentium II */
+	case 7:
+	case 8:
+	case 11: /* Pentium III */
+		break;
+	case 9:
+	case 13:
+		/* Pentium M */
+		break;
+	default:
+		pr_cont("unsupported p6 CPU model %d ",
+			boot_cpu_data.x86_model);
+		return -ENODEV;
+	}
+
+	x86_pmu = p6_pmu;
+
+	if (!cpu_has_apic) {
+		pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n");
+		pr_info("no hardware sampling interrupt available.\n");
+		x86_pmu.apic = 0;
+	}
+
+	return 0;
+}
+
+static int intel_pmu_init(void)
+{
+	union cpuid10_edx edx;
+	union cpuid10_eax eax;
+	unsigned int unused;
+	unsigned int ebx;
+	int version;
+
+	if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+		/* check for P6 processor family */
+	   if (boot_cpu_data.x86 == 6) {
+		return p6_pmu_init();
+	   } else {
+		return -ENODEV;
+	   }
+	}
+
+	/*
+	 * Check whether the Architectural PerfMon supports
+	 * Branch Misses Retired Event or not.
+	 */
+	cpuid(10, &eax.full, &ebx, &unused, &edx.full);
+	if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED)
+		return -ENODEV;
+
+	version = eax.split.version_id;
+	if (version < 2)
+		return -ENODEV;
+
+	x86_pmu				= intel_pmu;
+	x86_pmu.version			= version;
+	x86_pmu.num_counters		= eax.split.num_counters;
+	x86_pmu.counter_bits		= eax.split.bit_width;
+	x86_pmu.counter_mask		= (1ULL << eax.split.bit_width) - 1;
+
+	/*
+	 * Quirk: v2 perfmon does not report fixed-purpose counters, so
+	 * assume at least 3 counters:
+	 */
+	x86_pmu.num_counters_fixed	= max((int)edx.split.num_counters_fixed, 3);
+
+	/*
+	 * Install the hw-cache-events table:
+	 */
+	switch (boot_cpu_data.x86_model) {
+	case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
+	case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
+	case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
+	case 29: /* six-core 45 nm xeon "Dunnington" */
+		memcpy(hw_cache_event_ids, core2_hw_cache_event_ids,
+		       sizeof(hw_cache_event_ids));
+
+		pr_cont("Core2 events, ");
+		break;
+	default:
+	case 26:
+		memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
+		       sizeof(hw_cache_event_ids));
+
+		pr_cont("Nehalem/Corei7 events, ");
+		break;
+	case 28:
+		memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
+		       sizeof(hw_cache_event_ids));
+
+		pr_cont("Atom events, ");
+		break;
+	}
+	return 0;
+}
+
+static int amd_pmu_init(void)
+{
+	/* Performance-monitoring supported from K7 and later: */
+	if (boot_cpu_data.x86 < 6)
+		return -ENODEV;
+
+	x86_pmu = amd_pmu;
+
+	/* Events are common for all AMDs */
+	memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
+	       sizeof(hw_cache_event_ids));
+
+	return 0;
+}
+
+void __init init_hw_perf_counters(void)
+{
+	int err;
+
+	pr_info("Performance Counters: ");
+
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_INTEL:
+		err = intel_pmu_init();
+		break;
+	case X86_VENDOR_AMD:
+		err = amd_pmu_init();
+		break;
+	default:
+		return;
+	}
+	if (err != 0) {
+		pr_cont("no PMU driver, software counters only.\n");
+		return;
+	}
+
+	pr_cont("%s PMU driver.\n", x86_pmu.name);
+
+	if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) {
+		WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!",
+		     x86_pmu.num_counters, X86_PMC_MAX_GENERIC);
+		x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
+	}
+	perf_counter_mask = (1 << x86_pmu.num_counters) - 1;
+	perf_max_counters = x86_pmu.num_counters;
+
+	if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
+		WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!",
+		     x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED);
+		x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED;
+	}
+
+	perf_counter_mask |=
+		((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
+	x86_pmu.intel_ctrl = perf_counter_mask;
+
+	perf_counters_lapic_init();
+	register_die_notifier(&perf_counter_nmi_notifier);
+
+	pr_info("... version:                 %d\n",     x86_pmu.version);
+	pr_info("... bit width:               %d\n",     x86_pmu.counter_bits);
+	pr_info("... generic counters:        %d\n",     x86_pmu.num_counters);
+	pr_info("... value mask:              %016Lx\n", x86_pmu.counter_mask);
+	pr_info("... max period:              %016Lx\n", x86_pmu.max_period);
+	pr_info("... fixed-purpose counters:  %d\n",     x86_pmu.num_counters_fixed);
+	pr_info("... counter mask:            %016Lx\n", perf_counter_mask);
+}
+
+static inline void x86_pmu_read(struct perf_counter *counter)
+{
+	x86_perf_counter_update(counter, &counter->hw, counter->hw.idx);
+}
+
+static const struct pmu pmu = {
+	.enable		= x86_pmu_enable,
+	.disable	= x86_pmu_disable,
+	.read		= x86_pmu_read,
+	.unthrottle	= x86_pmu_unthrottle,
+};
+
+const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
+{
+	int err;
+
+	err = __hw_perf_counter_init(counter);
+	if (err)
+		return ERR_PTR(err);
+
+	return &pmu;
+}
+
+/*
+ * callchain support
+ */
+
+static inline
+void callchain_store(struct perf_callchain_entry *entry, u64 ip)
+{
+	if (entry->nr < PERF_MAX_STACK_DEPTH)
+		entry->ip[entry->nr++] = ip;
+}
+
+static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry);
+static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry);
+static DEFINE_PER_CPU(int, in_nmi_frame);
+
+
+static void
+backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+	/* Ignore warnings */
+}
+
+static void backtrace_warning(void *data, char *msg)
+{
+	/* Ignore warnings */
+}
+
+static int backtrace_stack(void *data, char *name)
+{
+	per_cpu(in_nmi_frame, smp_processor_id()) =
+			x86_is_stack_id(NMI_STACK, name);
+
+	return 0;
+}
+
+static void backtrace_address(void *data, unsigned long addr, int reliable)
+{
+	struct perf_callchain_entry *entry = data;
+
+	if (per_cpu(in_nmi_frame, smp_processor_id()))
+		return;
+
+	if (reliable)
+		callchain_store(entry, addr);
+}
+
+static const struct stacktrace_ops backtrace_ops = {
+	.warning		= backtrace_warning,
+	.warning_symbol		= backtrace_warning_symbol,
+	.stack			= backtrace_stack,
+	.address		= backtrace_address,
+};
+
+#include "../dumpstack.h"
+
+static void
+perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
+{
+	callchain_store(entry, PERF_CONTEXT_KERNEL);
+	callchain_store(entry, regs->ip);
+
+	dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry);
+}
+
+/*
+ * best effort, GUP based copy_from_user() that assumes IRQ or NMI context
+ */
+static unsigned long
+copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
+{
+	unsigned long offset, addr = (unsigned long)from;
+	int type = in_nmi() ? KM_NMI : KM_IRQ0;
+	unsigned long size, len = 0;
+	struct page *page;
+	void *map;
+	int ret;
+
+	do {
+		ret = __get_user_pages_fast(addr, 1, 0, &page);
+		if (!ret)
+			break;
+
+		offset = addr & (PAGE_SIZE - 1);
+		size = min(PAGE_SIZE - offset, n - len);
+
+		map = kmap_atomic(page, type);
+		memcpy(to, map+offset, size);
+		kunmap_atomic(map, type);
+		put_page(page);
+
+		len  += size;
+		to   += size;
+		addr += size;
+
+	} while (len < n);
+
+	return len;
+}
+
+static int copy_stack_frame(const void __user *fp, struct stack_frame *frame)
+{
+	unsigned long bytes;
+
+	bytes = copy_from_user_nmi(frame, fp, sizeof(*frame));
+
+	return bytes == sizeof(*frame);
+}
+
+static void
+perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
+{
+	struct stack_frame frame;
+	const void __user *fp;
+
+	if (!user_mode(regs))
+		regs = task_pt_regs(current);
+
+	fp = (void __user *)regs->bp;
+
+	callchain_store(entry, PERF_CONTEXT_USER);
+	callchain_store(entry, regs->ip);
+
+	while (entry->nr < PERF_MAX_STACK_DEPTH) {
+		frame.next_frame	     = NULL;
+		frame.return_address = 0;
+
+		if (!copy_stack_frame(fp, &frame))
+			break;
+
+		if ((unsigned long)fp < regs->sp)
+			break;
+
+		callchain_store(entry, frame.return_address);
+		fp = frame.next_frame;
+	}
+}
+
+static void
+perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
+{
+	int is_user;
+
+	if (!regs)
+		return;
+
+	is_user = user_mode(regs);
+
+	if (!current || current->pid == 0)
+		return;
+
+	if (is_user && current->state != TASK_RUNNING)
+		return;
+
+	if (!is_user)
+		perf_callchain_kernel(regs, entry);
+
+	if (current->mm)
+		perf_callchain_user(regs, entry);
+}
+
+struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+{
+	struct perf_callchain_entry *entry;
+
+	if (in_nmi())
+		entry = &__get_cpu_var(nmi_entry);
+	else
+		entry = &__get_cpu_var(irq_entry);
+
+	entry->nr = 0;
+
+	perf_do_callchain(regs, entry);
+
+	return entry;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,8 +19,8 @@
 #include <linux/nmi.h>
 #include <linux/kprobes.h>
 
-#include <asm/genapic.h>
-#include <asm/intel_arch_perfmon.h>
+#include <asm/apic.h>
+#include <asm/perf_counter.h>
 
 struct nmi_watchdog_ctlblk {
 	unsigned int cccr_msr;
@@ -716,11 +716,15 @@
 		wd_ops = &k7_wd_ops;
 		break;
 	case X86_VENDOR_INTEL:
-		/*
-		 * Work around Core Duo (Yonah) errata AE49 where perfctr1
-		 * doesn't have a working enable bit.
+		/* Work around where perfctr1 doesn't have a working enable
+		 * bit as described in the following errata:
+		 * AE49 Core Duo and Intel Core Solo 65 nm
+		 * AN49 Intel Pentium Dual-Core
+		 * AF49 Dual-Core Intel Xeon Processor LV
 		 */
-		if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) {
+		if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) ||
+		    ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 15 &&
+		     boot_cpu_data.x86_mask == 4))) {
 			intel_arch_wd_ops.perfctr = MSR_ARCH_PERFMON_PERFCTR0;
 			intel_arch_wd_ops.evntsel = MSR_ARCH_PERFMON_EVENTSEL0;
 		}
@@ -799,8 +803,3 @@
 	wd_ops->rearm(wd, nmi_hz);
 	return 1;
 }
-
-int lapic_watchdog_ok(void)
-{
-	return wd_ops != NULL;
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/cpuid.c linux-libre-2.6.31-gnu/arch/x86/kernel/cpuid.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/cpuid.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/cpuid.c	2009-09-09 18:13:59.000000000 -0400
@@ -182,6 +182,11 @@
 	.notifier_call = cpuid_class_cpu_callback,
 };
 
+static char *cpuid_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
+}
+
 static int __init cpuid_init(void)
 {
 	int i, err = 0;
@@ -198,6 +203,7 @@
 		err = PTR_ERR(cpuid_class);
 		goto out_chrdev;
 	}
+	cpuid_class->nodename = cpuid_nodename;
 	for_each_online_cpu(i) {
 		err = cpuid_device_create(i);
 		if (err != 0)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/crash.c linux-libre-2.6.31-gnu/arch/x86/kernel/crash.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/crash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/crash.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <asm/cpu.h>
 #include <asm/reboot.h>
 #include <asm/virtext.h>
+#include <asm/iommu.h>
 
 
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
@@ -103,5 +104,10 @@
 #ifdef CONFIG_HPET_TIMER
 	hpet_disable();
 #endif
+
+#ifdef CONFIG_X86_64
+	pci_iommu_shutdown();
+#endif
+
 	crash_save_cpu(regs, safe_smp_processor_id());
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/ds.c linux-libre-2.6.31-gnu/arch/x86/kernel/ds.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/ds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/ds.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,45 +19,61 @@
  * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
  */
 
-
-#include <asm/ds.h>
-
-#include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/slab.h>
+#include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/kernel.h>
+#include <linux/trace_clock.h>
 
+#include <asm/ds.h>
+
+#include "ds_selftest.h"
 
 /*
- * The configuration for a particular DS hardware implementation.
+ * The configuration for a particular DS hardware implementation:
  */
 struct ds_configuration {
-	/* the name of the configuration */
-	const char *name;
-	/* the size of one pointer-typed field in the DS structure and
-	   in the BTS and PEBS buffers in bytes;
-	   this covers the first 8 DS fields related to buffer management. */
-	unsigned char  sizeof_field;
-	/* the size of a BTS/PEBS record in bytes */
-	unsigned char  sizeof_rec[2];
-	/* a series of bit-masks to control various features indexed
-	 * by enum ds_feature */
-	unsigned long ctl[dsf_ctl_max];
+	/* The name of the configuration: */
+	const char		*name;
+
+	/* The size of pointer-typed fields in DS, BTS, and PEBS: */
+	unsigned char		sizeof_ptr_field;
+
+	/* The size of a BTS/PEBS record in bytes: */
+	unsigned char		sizeof_rec[2];
+
+	/* The number of pebs counter reset values in the DS structure. */
+	unsigned char		nr_counter_reset;
+
+	/* Control bit-masks indexed by enum ds_feature: */
+	unsigned long		ctl[dsf_ctl_max];
 };
-static DEFINE_PER_CPU(struct ds_configuration, ds_cfg_array);
+static struct ds_configuration ds_cfg __read_mostly;
 
-#define ds_cfg per_cpu(ds_cfg_array, smp_processor_id())
 
-#define MAX_SIZEOF_DS (12 * 8)	/* maximal size of a DS configuration */
-#define MAX_SIZEOF_BTS (3 * 8)	/* maximal size of a BTS record */
-#define DS_ALIGNMENT (1 << 3)	/* BTS and PEBS buffer alignment */
+/* Maximal size of a DS configuration: */
+#define MAX_SIZEOF_DS		0x80
 
-#define BTS_CONTROL \
- (ds_cfg.ctl[dsf_bts] | ds_cfg.ctl[dsf_bts_kernel] | ds_cfg.ctl[dsf_bts_user] |\
-  ds_cfg.ctl[dsf_bts_overflow])
+/* Maximal size of a BTS record: */
+#define MAX_SIZEOF_BTS		(3 * 8)
+
+/* BTS and PEBS buffer alignment: */
+#define DS_ALIGNMENT		(1 << 3)
+
+/* Number of buffer pointers in DS: */
+#define NUM_DS_PTR_FIELDS	8
 
+/* Size of a pebs reset value in DS: */
+#define PEBS_RESET_FIELD_SIZE	8
+
+/* Mask of control bits in the DS MSR register: */
+#define BTS_CONTROL				  \
+	( ds_cfg.ctl[dsf_bts]			| \
+	  ds_cfg.ctl[dsf_bts_kernel]		| \
+	  ds_cfg.ctl[dsf_bts_user]		| \
+	  ds_cfg.ctl[dsf_bts_overflow] )
 
 /*
  * A BTS or PEBS tracer.
@@ -66,29 +82,36 @@
  * to identify tracers.
  */
 struct ds_tracer {
-	/* the DS context (partially) owned by this tracer */
-	struct ds_context *context;
-	/* the buffer provided on ds_request() and its size in bytes */
-	void *buffer;
-	size_t size;
+	/* The DS context (partially) owned by this tracer. */
+	struct ds_context	*context;
+	/* The buffer provided on ds_request() and its size in bytes. */
+	void			*buffer;
+	size_t			size;
 };
 
 struct bts_tracer {
-	/* the common DS part */
-	struct ds_tracer ds;
-	/* the trace including the DS configuration */
-	struct bts_trace trace;
-	/* buffer overflow notification function */
-	bts_ovfl_callback_t ovfl;
+	/* The common DS part: */
+	struct ds_tracer	ds;
+
+	/* The trace including the DS configuration: */
+	struct bts_trace	trace;
+
+	/* Buffer overflow notification function: */
+	bts_ovfl_callback_t	ovfl;
+
+	/* Active flags affecting trace collection. */
+	unsigned int		flags;
 };
 
 struct pebs_tracer {
-	/* the common DS part */
-	struct ds_tracer ds;
-	/* the trace including the DS configuration */
-	struct pebs_trace trace;
-	/* buffer overflow notification function */
-	pebs_ovfl_callback_t ovfl;
+	/* The common DS part: */
+	struct ds_tracer	ds;
+
+	/* The trace including the DS configuration: */
+	struct pebs_trace	trace;
+
+	/* Buffer overflow notification function: */
+	pebs_ovfl_callback_t	ovfl;
 };
 
 /*
@@ -97,6 +120,7 @@
  *
  * The DS configuration consists of the following fields; different
  * architetures vary in the size of those fields.
+ *
  * - double-word aligned base linear address of the BTS buffer
  * - write pointer into the BTS buffer
  * - end linear address of the BTS buffer (one byte beyond the end of
@@ -135,21 +159,22 @@
 };
 
 enum ds_qualifier {
-	ds_bts  = 0,
+	ds_bts = 0,
 	ds_pebs
 };
 
-static inline unsigned long ds_get(const unsigned char *base,
-				   enum ds_qualifier qual, enum ds_field field)
+static inline unsigned long
+ds_get(const unsigned char *base, enum ds_qualifier qual, enum ds_field field)
 {
-	base += (ds_cfg.sizeof_field * (field + (4 * qual)));
+	base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
 	return *(unsigned long *)base;
 }
 
-static inline void ds_set(unsigned char *base, enum ds_qualifier qual,
-			  enum ds_field field, unsigned long value)
+static inline void
+ds_set(unsigned char *base, enum ds_qualifier qual, enum ds_field field,
+       unsigned long value)
 {
-	base += (ds_cfg.sizeof_field * (field + (4 * qual)));
+	base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
 	(*(unsigned long *)base) = value;
 }
 
@@ -159,7 +184,6 @@
  */
 static DEFINE_SPINLOCK(ds_lock);
 
-
 /*
  * We either support (system-wide) per-cpu or per-thread allocation.
  * We distinguish the two based on the task_struct pointer, where a
@@ -178,12 +202,28 @@
  */
 static atomic_t tracers = ATOMIC_INIT(0);
 
-static inline void get_tracer(struct task_struct *task)
+static inline int get_tracer(struct task_struct *task)
 {
-	if (task)
+	int error;
+
+	spin_lock_irq(&ds_lock);
+
+	if (task) {
+		error = -EPERM;
+		if (atomic_read(&tracers) < 0)
+			goto out;
 		atomic_inc(&tracers);
-	else
+	} else {
+		error = -EPERM;
+		if (atomic_read(&tracers) > 0)
+			goto out;
 		atomic_dec(&tracers);
+	}
+
+	error = 0;
+out:
+	spin_unlock_irq(&ds_lock);
+	return error;
 }
 
 static inline void put_tracer(struct task_struct *task)
@@ -194,14 +234,6 @@
 		atomic_inc(&tracers);
 }
 
-static inline int check_tracer(struct task_struct *task)
-{
-	return task ?
-		(atomic_read(&tracers) >= 0) :
-		(atomic_read(&tracers) <= 0);
-}
-
-
 /*
  * The DS context is either attached to a thread or to a cpu:
  * - in the former case, the thread_struct contains a pointer to the
@@ -213,61 +245,58 @@
  * deallocated when the last user puts the context.
  */
 struct ds_context {
-	/* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */
-	unsigned char ds[MAX_SIZEOF_DS];
-	/* the owner of the BTS and PEBS configuration, respectively */
-	struct bts_tracer *bts_master;
-	struct pebs_tracer *pebs_master;
-	/* use count */
-	unsigned long count;
-	/* a pointer to the context location inside the thread_struct
-	 * or the per_cpu context array */
-	struct ds_context **this;
-	/* a pointer to the task owning this context, or NULL, if the
-	 * context is owned by a cpu */
-	struct task_struct *task;
-};
+	/* The DS configuration; goes into MSR_IA32_DS_AREA: */
+	unsigned char		ds[MAX_SIZEOF_DS];
 
-static DEFINE_PER_CPU(struct ds_context *, system_context_array);
+	/* The owner of the BTS and PEBS configuration, respectively: */
+	struct bts_tracer	*bts_master;
+	struct pebs_tracer	*pebs_master;
 
-#define system_context per_cpu(system_context_array, smp_processor_id())
+	/* Use count: */
+	unsigned long		count;
 
+	/* Pointer to the context pointer field: */
+	struct ds_context	**this;
 
-static inline struct ds_context *ds_get_context(struct task_struct *task)
+	/* The traced task; NULL for cpu tracing: */
+	struct task_struct	*task;
+
+	/* The traced cpu; only valid if task is NULL: */
+	int			cpu;
+};
+
+static DEFINE_PER_CPU(struct ds_context *, cpu_context);
+
+
+static struct ds_context *ds_get_context(struct task_struct *task, int cpu)
 {
 	struct ds_context **p_context =
-		(task ? &task->thread.ds_ctx : &system_context);
+		(task ? &task->thread.ds_ctx : &per_cpu(cpu_context, cpu));
 	struct ds_context *context = NULL;
 	struct ds_context *new_context = NULL;
-	unsigned long irq;
 
 	/* Chances are small that we already have a context. */
 	new_context = kzalloc(sizeof(*new_context), GFP_KERNEL);
 	if (!new_context)
 		return NULL;
 
-	spin_lock_irqsave(&ds_lock, irq);
+	spin_lock_irq(&ds_lock);
 
 	context = *p_context;
-	if (!context) {
+	if (likely(!context)) {
 		context = new_context;
 
 		context->this = p_context;
 		context->task = task;
+		context->cpu = cpu;
 		context->count = 0;
 
-		if (task)
-			set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
-
-		if (!task || (task == current))
-			wrmsrl(MSR_IA32_DS_AREA, (unsigned long)context->ds);
-
 		*p_context = context;
 	}
 
 	context->count++;
 
-	spin_unlock_irqrestore(&ds_lock, irq);
+	spin_unlock_irq(&ds_lock);
 
 	if (context != new_context)
 		kfree(new_context);
@@ -275,8 +304,9 @@
 	return context;
 }
 
-static inline void ds_put_context(struct ds_context *context)
+static void ds_put_context(struct ds_context *context)
 {
+	struct task_struct *task;
 	unsigned long irq;
 
 	if (!context)
@@ -291,17 +321,55 @@
 
 	*(context->this) = NULL;
 
-	if (context->task)
-		clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR);
+	task = context->task;
 
-	if (!context->task || (context->task == current))
-		wrmsrl(MSR_IA32_DS_AREA, 0);
+	if (task)
+		clear_tsk_thread_flag(task, TIF_DS_AREA_MSR);
+
+	/*
+	 * We leave the (now dangling) pointer to the DS configuration in
+	 * the DS_AREA msr. This is as good or as bad as replacing it with
+	 * NULL - the hardware would crash if we enabled tracing.
+	 *
+	 * This saves us some problems with having to write an msr on a
+	 * different cpu while preventing others from doing the same for the
+	 * next context for that same cpu.
+	 */
 
 	spin_unlock_irqrestore(&ds_lock, irq);
 
+	/* The context might still be in use for context switching. */
+	if (task && (task != current))
+		wait_task_context_switch(task);
+
 	kfree(context);
 }
 
+static void ds_install_ds_area(struct ds_context *context)
+{
+	unsigned long ds;
+
+	ds = (unsigned long)context->ds;
+
+	/*
+	 * There is a race between the bts master and the pebs master.
+	 *
+	 * The thread/cpu access is synchronized via get/put_cpu() for
+	 * task tracing and via wrmsr_on_cpu for cpu tracing.
+	 *
+	 * If bts and pebs are collected for the same task or same cpu,
+	 * the same confiuration is written twice.
+	 */
+	if (context->task) {
+		get_cpu();
+		if (context->task == current)
+			wrmsrl(MSR_IA32_DS_AREA, ds);
+		set_tsk_thread_flag(context->task, TIF_DS_AREA_MSR);
+		put_cpu();
+	} else
+		wrmsr_on_cpu(context->cpu, MSR_IA32_DS_AREA,
+			     (u32)((u64)ds), (u32)((u64)ds >> 32));
+}
 
 /*
  * Call the tracer's callback on a buffer overflow.
@@ -332,9 +400,9 @@
  * The remainder of any partially written record is zeroed out.
  *
  * context: the DS context
- * qual: the buffer type
- * record: the data to write
- * size: the size of the data
+ * qual:    the buffer type
+ * record:  the data to write
+ * size:    the size of the data
  */
 static int ds_write(struct ds_context *context, enum ds_qualifier qual,
 		    const void *record, size_t size)
@@ -349,14 +417,14 @@
 		unsigned long write_size, adj_write_size;
 
 		/*
-		 * write as much as possible without producing an
+		 * Write as much as possible without producing an
 		 * overflow interrupt.
 		 *
-		 * interrupt_threshold must either be
+		 * Interrupt_threshold must either be
 		 * - bigger than absolute_maximum or
 		 * - point to a record between buffer_base and absolute_maximum
 		 *
-		 * index points to a valid record.
+		 * Index points to a valid record.
 		 */
 		base   = ds_get(context->ds, qual, ds_buffer_base);
 		index  = ds_get(context->ds, qual, ds_index);
@@ -365,8 +433,10 @@
 
 		write_end = min(end, int_th);
 
-		/* if we are already beyond the interrupt threshold,
-		 * we fill the entire buffer */
+		/*
+		 * If we are already beyond the interrupt threshold,
+		 * we fill the entire buffer.
+		 */
 		if (write_end <= index)
 			write_end = end;
 
@@ -383,7 +453,7 @@
 		adj_write_size = write_size / ds_cfg.sizeof_rec[qual];
 		adj_write_size *= ds_cfg.sizeof_rec[qual];
 
-		/* zero out trailing bytes */
+		/* Zero out trailing bytes. */
 		memset((char *)index + write_size, 0,
 		       adj_write_size - write_size);
 		index += adj_write_size;
@@ -410,7 +480,7 @@
  * Later architectures use 64bit pointers throughout, whereas earlier
  * architectures use 32bit pointers in 32bit mode.
  *
- * We compute the base address for the first 8 fields based on:
+ * We compute the base address for the fields based on:
  * - the field size stored in the DS configuration
  * - the relative field position
  *
@@ -431,23 +501,23 @@
 	bts_to,
 	bts_flags,
 
-	bts_qual = bts_from,
-	bts_jiffies = bts_to,
-	bts_pid = bts_flags,
+	bts_qual		= bts_from,
+	bts_clock		= bts_to,
+	bts_pid			= bts_flags,
 
-	bts_qual_mask = (bts_qual_max - 1),
-	bts_escape = ((unsigned long)-1 & ~bts_qual_mask)
+	bts_qual_mask		= (bts_qual_max - 1),
+	bts_escape		= ((unsigned long)-1 & ~bts_qual_mask)
 };
 
 static inline unsigned long bts_get(const char *base, enum bts_field field)
 {
-	base += (ds_cfg.sizeof_field * field);
+	base += (ds_cfg.sizeof_ptr_field * field);
 	return *(unsigned long *)base;
 }
 
 static inline void bts_set(char *base, enum bts_field field, unsigned long val)
 {
-	base += (ds_cfg.sizeof_field * field);;
+	base += (ds_cfg.sizeof_ptr_field * field);;
 	(*(unsigned long *)base) = val;
 }
 
@@ -463,8 +533,8 @@
  *
  * return: bytes read/written on success; -Eerrno, otherwise
  */
-static int bts_read(struct bts_tracer *tracer, const void *at,
-		    struct bts_struct *out)
+static int
+bts_read(struct bts_tracer *tracer, const void *at, struct bts_struct *out)
 {
 	if (!tracer)
 		return -EINVAL;
@@ -478,8 +548,8 @@
 	memset(out, 0, sizeof(*out));
 	if ((bts_get(at, bts_qual) & ~bts_qual_mask) == bts_escape) {
 		out->qualifier = (bts_get(at, bts_qual) & bts_qual_mask);
-		out->variant.timestamp.jiffies = bts_get(at, bts_jiffies);
-		out->variant.timestamp.pid = bts_get(at, bts_pid);
+		out->variant.event.clock = bts_get(at, bts_clock);
+		out->variant.event.pid = bts_get(at, bts_pid);
 	} else {
 		out->qualifier = bts_branch;
 		out->variant.lbr.from = bts_get(at, bts_from);
@@ -516,8 +586,8 @@
 	case bts_task_arrives:
 	case bts_task_departs:
 		bts_set(raw, bts_qual, (bts_escape | in->qualifier));
-		bts_set(raw, bts_jiffies, in->variant.timestamp.jiffies);
-		bts_set(raw, bts_pid, in->variant.timestamp.pid);
+		bts_set(raw, bts_clock, in->variant.event.clock);
+		bts_set(raw, bts_pid, in->variant.event.pid);
 		break;
 	default:
 		return -EINVAL;
@@ -555,7 +625,8 @@
 			     unsigned int flags) {
 	unsigned long buffer, adj;
 
-	/* adjust the buffer address and size to meet alignment
+	/*
+	 * Adjust the buffer address and size to meet alignment
 	 * constraints:
 	 * - buffer is double-word aligned
 	 * - size is multiple of record size
@@ -577,9 +648,11 @@
 	trace->begin = (void *)buffer;
 	trace->top = trace->begin;
 	trace->end = (void *)(buffer + size);
-	/* The value for 'no threshold' is -1, which will set the
+	/*
+	 * The value for 'no threshold' is -1, which will set the
 	 * threshold outside of the buffer, just like we want it.
 	 */
+	ith *= ds_cfg.sizeof_rec[qual];
 	trace->ith = (void *)(buffer + size - ith);
 
 	trace->flags = flags;
@@ -588,18 +661,27 @@
 
 static int ds_request(struct ds_tracer *tracer, struct ds_trace *trace,
 		      enum ds_qualifier qual, struct task_struct *task,
-		      void *base, size_t size, size_t th, unsigned int flags)
+		      int cpu, void *base, size_t size, size_t th)
 {
 	struct ds_context *context;
 	int error;
+	size_t req_size;
+
+	error = -EOPNOTSUPP;
+	if (!ds_cfg.sizeof_rec[qual])
+		goto out;
 
 	error = -EINVAL;
 	if (!base)
 		goto out;
 
-	/* we require some space to do alignment adjustments below */
+	req_size = ds_cfg.sizeof_rec[qual];
+	/* We might need space for alignment adjustments. */
+	if (!IS_ALIGNED((unsigned long)base, DS_ALIGNMENT))
+		req_size += DS_ALIGNMENT;
+
 	error = -EINVAL;
-	if (size < (DS_ALIGNMENT + ds_cfg.sizeof_rec[qual]))
+	if (size < req_size)
 		goto out;
 
 	if (th != (size_t)-1) {
@@ -614,182 +696,318 @@
 	tracer->size = size;
 
 	error = -ENOMEM;
-	context = ds_get_context(task);
+	context = ds_get_context(task, cpu);
 	if (!context)
 		goto out;
 	tracer->context = context;
 
-	ds_init_ds_trace(trace, qual, base, size, th, flags);
+	/*
+	 * Defer any tracer-specific initialization work for the context until
+	 * context ownership has been clarified.
+	 */
 
 	error = 0;
  out:
 	return error;
 }
 
-struct bts_tracer *ds_request_bts(struct task_struct *task,
-				  void *base, size_t size,
-				  bts_ovfl_callback_t ovfl, size_t th,
-				  unsigned int flags)
+static struct bts_tracer *ds_request_bts(struct task_struct *task, int cpu,
+					 void *base, size_t size,
+					 bts_ovfl_callback_t ovfl, size_t th,
+					 unsigned int flags)
 {
 	struct bts_tracer *tracer;
-	unsigned long irq;
 	int error;
 
+	/* Buffer overflow notification is not yet implemented. */
 	error = -EOPNOTSUPP;
-	if (!ds_cfg.ctl[dsf_bts])
+	if (ovfl)
 		goto out;
 
-	/* buffer overflow notification is not yet implemented */
-	error = -EOPNOTSUPP;
-	if (ovfl)
+	error = get_tracer(task);
+	if (error < 0)
 		goto out;
 
 	error = -ENOMEM;
 	tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
 	if (!tracer)
-		goto out;
+		goto out_put_tracer;
 	tracer->ovfl = ovfl;
 
+	/* Do some more error checking and acquire a tracing context. */
 	error = ds_request(&tracer->ds, &tracer->trace.ds,
-			   ds_bts, task, base, size, th, flags);
+			   ds_bts, task, cpu, base, size, th);
 	if (error < 0)
 		goto out_tracer;
 
-
-	spin_lock_irqsave(&ds_lock, irq);
-
-	error = -EPERM;
-	if (!check_tracer(task))
-		goto out_unlock;
-	get_tracer(task);
+	/* Claim the bts part of the tracing context we acquired above. */
+	spin_lock_irq(&ds_lock);
 
 	error = -EPERM;
 	if (tracer->ds.context->bts_master)
-		goto out_put_tracer;
+		goto out_unlock;
 	tracer->ds.context->bts_master = tracer;
 
-	spin_unlock_irqrestore(&ds_lock, irq);
+	spin_unlock_irq(&ds_lock);
 
+	/*
+	 * Now that we own the bts part of the context, let's complete the
+	 * initialization for that part.
+	 */
+	ds_init_ds_trace(&tracer->trace.ds, ds_bts, base, size, th, flags);
+	ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_bts);
+	ds_install_ds_area(tracer->ds.context);
 
 	tracer->trace.read  = bts_read;
 	tracer->trace.write = bts_write;
 
-	ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_bts);
+	/* Start tracing. */
 	ds_resume_bts(tracer);
 
 	return tracer;
 
- out_put_tracer:
-	put_tracer(task);
  out_unlock:
-	spin_unlock_irqrestore(&ds_lock, irq);
+	spin_unlock_irq(&ds_lock);
 	ds_put_context(tracer->ds.context);
  out_tracer:
 	kfree(tracer);
+ out_put_tracer:
+	put_tracer(task);
  out:
 	return ERR_PTR(error);
 }
 
-struct pebs_tracer *ds_request_pebs(struct task_struct *task,
-				    void *base, size_t size,
-				    pebs_ovfl_callback_t ovfl, size_t th,
-				    unsigned int flags)
+struct bts_tracer *ds_request_bts_task(struct task_struct *task,
+				       void *base, size_t size,
+				       bts_ovfl_callback_t ovfl,
+				       size_t th, unsigned int flags)
+{
+	return ds_request_bts(task, 0, base, size, ovfl, th, flags);
+}
+
+struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size,
+				      bts_ovfl_callback_t ovfl,
+				      size_t th, unsigned int flags)
+{
+	return ds_request_bts(NULL, cpu, base, size, ovfl, th, flags);
+}
+
+static struct pebs_tracer *ds_request_pebs(struct task_struct *task, int cpu,
+					   void *base, size_t size,
+					   pebs_ovfl_callback_t ovfl, size_t th,
+					   unsigned int flags)
 {
 	struct pebs_tracer *tracer;
-	unsigned long irq;
 	int error;
 
-	/* buffer overflow notification is not yet implemented */
+	/* Buffer overflow notification is not yet implemented. */
 	error = -EOPNOTSUPP;
 	if (ovfl)
 		goto out;
 
+	error = get_tracer(task);
+	if (error < 0)
+		goto out;
+
 	error = -ENOMEM;
 	tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
 	if (!tracer)
-		goto out;
+		goto out_put_tracer;
 	tracer->ovfl = ovfl;
 
+	/* Do some more error checking and acquire a tracing context. */
 	error = ds_request(&tracer->ds, &tracer->trace.ds,
-			   ds_pebs, task, base, size, th, flags);
+			   ds_pebs, task, cpu, base, size, th);
 	if (error < 0)
 		goto out_tracer;
 
-	spin_lock_irqsave(&ds_lock, irq);
-
-	error = -EPERM;
-	if (!check_tracer(task))
-		goto out_unlock;
-	get_tracer(task);
+	/* Claim the pebs part of the tracing context we acquired above. */
+	spin_lock_irq(&ds_lock);
 
 	error = -EPERM;
 	if (tracer->ds.context->pebs_master)
-		goto out_put_tracer;
+		goto out_unlock;
 	tracer->ds.context->pebs_master = tracer;
 
-	spin_unlock_irqrestore(&ds_lock, irq);
+	spin_unlock_irq(&ds_lock);
 
+	/*
+	 * Now that we own the pebs part of the context, let's complete the
+	 * initialization for that part.
+	 */
+	ds_init_ds_trace(&tracer->trace.ds, ds_pebs, base, size, th, flags);
 	ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_pebs);
+	ds_install_ds_area(tracer->ds.context);
+
+	/* Start tracing. */
 	ds_resume_pebs(tracer);
 
 	return tracer;
 
- out_put_tracer:
-	put_tracer(task);
  out_unlock:
-	spin_unlock_irqrestore(&ds_lock, irq);
+	spin_unlock_irq(&ds_lock);
 	ds_put_context(tracer->ds.context);
  out_tracer:
 	kfree(tracer);
+ out_put_tracer:
+	put_tracer(task);
  out:
 	return ERR_PTR(error);
 }
 
-void ds_release_bts(struct bts_tracer *tracer)
+struct pebs_tracer *ds_request_pebs_task(struct task_struct *task,
+					 void *base, size_t size,
+					 pebs_ovfl_callback_t ovfl,
+					 size_t th, unsigned int flags)
 {
-	if (!tracer)
-		return;
+	return ds_request_pebs(task, 0, base, size, ovfl, th, flags);
+}
 
-	ds_suspend_bts(tracer);
+struct pebs_tracer *ds_request_pebs_cpu(int cpu, void *base, size_t size,
+					pebs_ovfl_callback_t ovfl,
+					size_t th, unsigned int flags)
+{
+	return ds_request_pebs(NULL, cpu, base, size, ovfl, th, flags);
+}
+
+static void ds_free_bts(struct bts_tracer *tracer)
+{
+	struct task_struct *task;
+
+	task = tracer->ds.context->task;
 
 	WARN_ON_ONCE(tracer->ds.context->bts_master != tracer);
 	tracer->ds.context->bts_master = NULL;
 
-	put_tracer(tracer->ds.context->task);
+	/* Make sure tracing stopped and the tracer is not in use. */
+	if (task && (task != current))
+		wait_task_context_switch(task);
+
 	ds_put_context(tracer->ds.context);
+	put_tracer(task);
 
 	kfree(tracer);
 }
 
+void ds_release_bts(struct bts_tracer *tracer)
+{
+	might_sleep();
+
+	if (!tracer)
+		return;
+
+	ds_suspend_bts(tracer);
+	ds_free_bts(tracer);
+}
+
+int ds_release_bts_noirq(struct bts_tracer *tracer)
+{
+	struct task_struct *task;
+	unsigned long irq;
+	int error;
+
+	if (!tracer)
+		return 0;
+
+	task = tracer->ds.context->task;
+
+	local_irq_save(irq);
+
+	error = -EPERM;
+	if (!task &&
+	    (tracer->ds.context->cpu != smp_processor_id()))
+		goto out;
+
+	error = -EPERM;
+	if (task && (task != current))
+		goto out;
+
+	ds_suspend_bts_noirq(tracer);
+	ds_free_bts(tracer);
+
+	error = 0;
+ out:
+	local_irq_restore(irq);
+	return error;
+}
+
+static void update_task_debugctlmsr(struct task_struct *task,
+				    unsigned long debugctlmsr)
+{
+	task->thread.debugctlmsr = debugctlmsr;
+
+	get_cpu();
+	if (task == current)
+		update_debugctlmsr(debugctlmsr);
+	put_cpu();
+}
+
 void ds_suspend_bts(struct bts_tracer *tracer)
 {
 	struct task_struct *task;
+	unsigned long debugctlmsr;
+	int cpu;
 
 	if (!tracer)
 		return;
 
+	tracer->flags = 0;
+
 	task = tracer->ds.context->task;
+	cpu  = tracer->ds.context->cpu;
 
-	if (!task || (task == current))
-		update_debugctlmsr(get_debugctlmsr() & ~BTS_CONTROL);
+	WARN_ON(!task && irqs_disabled());
 
-	if (task) {
-		task->thread.debugctlmsr &= ~BTS_CONTROL;
+	debugctlmsr = (task ?
+		       task->thread.debugctlmsr :
+		       get_debugctlmsr_on_cpu(cpu));
+	debugctlmsr &= ~BTS_CONTROL;
 
-		if (!task->thread.debugctlmsr)
-			clear_tsk_thread_flag(task, TIF_DEBUGCTLMSR);
-	}
+	if (task)
+		update_task_debugctlmsr(task, debugctlmsr);
+	else
+		update_debugctlmsr_on_cpu(cpu, debugctlmsr);
 }
 
-void ds_resume_bts(struct bts_tracer *tracer)
+int ds_suspend_bts_noirq(struct bts_tracer *tracer)
 {
 	struct task_struct *task;
-	unsigned long control;
+	unsigned long debugctlmsr, irq;
+	int cpu, error = 0;
 
 	if (!tracer)
-		return;
+		return 0;
+
+	tracer->flags = 0;
 
 	task = tracer->ds.context->task;
+	cpu  = tracer->ds.context->cpu;
+
+	local_irq_save(irq);
+
+	error = -EPERM;
+	if (!task && (cpu != smp_processor_id()))
+		goto out;
+
+	debugctlmsr = (task ?
+		       task->thread.debugctlmsr :
+		       get_debugctlmsr());
+	debugctlmsr &= ~BTS_CONTROL;
+
+	if (task)
+		update_task_debugctlmsr(task, debugctlmsr);
+	else
+		update_debugctlmsr(debugctlmsr);
+
+	error = 0;
+ out:
+	local_irq_restore(irq);
+	return error;
+}
+
+static unsigned long ds_bts_control(struct bts_tracer *tracer)
+{
+	unsigned long control;
 
 	control = ds_cfg.ctl[dsf_bts];
 	if (!(tracer->trace.ds.flags & BTS_KERNEL))
@@ -797,41 +1015,149 @@
 	if (!(tracer->trace.ds.flags & BTS_USER))
 		control |= ds_cfg.ctl[dsf_bts_user];
 
-	if (task) {
-		task->thread.debugctlmsr |= control;
-		set_tsk_thread_flag(task, TIF_DEBUGCTLMSR);
-	}
-
-	if (!task || (task == current))
-		update_debugctlmsr(get_debugctlmsr() | control);
+	return control;
 }
 
-void ds_release_pebs(struct pebs_tracer *tracer)
+void ds_resume_bts(struct bts_tracer *tracer)
 {
+	struct task_struct *task;
+	unsigned long debugctlmsr;
+	int cpu;
+
 	if (!tracer)
 		return;
 
-	ds_suspend_pebs(tracer);
+	tracer->flags = tracer->trace.ds.flags;
+
+	task = tracer->ds.context->task;
+	cpu  = tracer->ds.context->cpu;
+
+	WARN_ON(!task && irqs_disabled());
+
+	debugctlmsr = (task ?
+		       task->thread.debugctlmsr :
+		       get_debugctlmsr_on_cpu(cpu));
+	debugctlmsr |= ds_bts_control(tracer);
+
+	if (task)
+		update_task_debugctlmsr(task, debugctlmsr);
+	else
+		update_debugctlmsr_on_cpu(cpu, debugctlmsr);
+}
+
+int ds_resume_bts_noirq(struct bts_tracer *tracer)
+{
+	struct task_struct *task;
+	unsigned long debugctlmsr, irq;
+	int cpu, error = 0;
+
+	if (!tracer)
+		return 0;
+
+	tracer->flags = tracer->trace.ds.flags;
+
+	task = tracer->ds.context->task;
+	cpu  = tracer->ds.context->cpu;
+
+	local_irq_save(irq);
+
+	error = -EPERM;
+	if (!task && (cpu != smp_processor_id()))
+		goto out;
+
+	debugctlmsr = (task ?
+		       task->thread.debugctlmsr :
+		       get_debugctlmsr());
+	debugctlmsr |= ds_bts_control(tracer);
+
+	if (task)
+		update_task_debugctlmsr(task, debugctlmsr);
+	else
+		update_debugctlmsr(debugctlmsr);
+
+	error = 0;
+ out:
+	local_irq_restore(irq);
+	return error;
+}
+
+static void ds_free_pebs(struct pebs_tracer *tracer)
+{
+	struct task_struct *task;
+
+	task = tracer->ds.context->task;
 
 	WARN_ON_ONCE(tracer->ds.context->pebs_master != tracer);
 	tracer->ds.context->pebs_master = NULL;
 
-	put_tracer(tracer->ds.context->task);
 	ds_put_context(tracer->ds.context);
+	put_tracer(task);
 
 	kfree(tracer);
 }
 
+void ds_release_pebs(struct pebs_tracer *tracer)
+{
+	might_sleep();
+
+	if (!tracer)
+		return;
+
+	ds_suspend_pebs(tracer);
+	ds_free_pebs(tracer);
+}
+
+int ds_release_pebs_noirq(struct pebs_tracer *tracer)
+{
+	struct task_struct *task;
+	unsigned long irq;
+	int error;
+
+	if (!tracer)
+		return 0;
+
+	task = tracer->ds.context->task;
+
+	local_irq_save(irq);
+
+	error = -EPERM;
+	if (!task &&
+	    (tracer->ds.context->cpu != smp_processor_id()))
+		goto out;
+
+	error = -EPERM;
+	if (task && (task != current))
+		goto out;
+
+	ds_suspend_pebs_noirq(tracer);
+	ds_free_pebs(tracer);
+
+	error = 0;
+ out:
+	local_irq_restore(irq);
+	return error;
+}
+
 void ds_suspend_pebs(struct pebs_tracer *tracer)
 {
 
 }
 
+int ds_suspend_pebs_noirq(struct pebs_tracer *tracer)
+{
+	return 0;
+}
+
 void ds_resume_pebs(struct pebs_tracer *tracer)
 {
 
 }
 
+int ds_resume_pebs_noirq(struct pebs_tracer *tracer)
+{
+	return 0;
+}
+
 const struct bts_trace *ds_read_bts(struct bts_tracer *tracer)
 {
 	if (!tracer)
@@ -847,8 +1173,12 @@
 		return NULL;
 
 	ds_read_config(tracer->ds.context, &tracer->trace.ds, ds_pebs);
-	tracer->trace.reset_value =
-		*(u64 *)(tracer->ds.context->ds + (ds_cfg.sizeof_field * 8));
+
+	tracer->trace.counters = ds_cfg.nr_counter_reset;
+	memcpy(tracer->trace.counter_reset,
+	       tracer->ds.context->ds +
+	       (NUM_DS_PTR_FIELDS * ds_cfg.sizeof_ptr_field),
+	       ds_cfg.nr_counter_reset * PEBS_RESET_FIELD_SIZE);
 
 	return &tracer->trace;
 }
@@ -873,18 +1203,24 @@
 
 	tracer->trace.ds.top = tracer->trace.ds.begin;
 
-	ds_set(tracer->ds.context->ds, ds_bts, ds_index,
+	ds_set(tracer->ds.context->ds, ds_pebs, ds_index,
 	       (unsigned long)tracer->trace.ds.top);
 
 	return 0;
 }
 
-int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value)
+int ds_set_pebs_reset(struct pebs_tracer *tracer,
+		      unsigned int counter, u64 value)
 {
 	if (!tracer)
 		return -EINVAL;
 
-	*(u64 *)(tracer->ds.context->ds + (ds_cfg.sizeof_field * 8)) = value;
+	if (ds_cfg.nr_counter_reset < counter)
+		return -EINVAL;
+
+	*(u64 *)(tracer->ds.context->ds +
+		 (NUM_DS_PTR_FIELDS * ds_cfg.sizeof_ptr_field) +
+		 (counter * PEBS_RESET_FIELD_SIZE)) = value;
 
 	return 0;
 }
@@ -894,73 +1230,117 @@
 	.ctl[dsf_bts]		= (1 << 2) | (1 << 3),
 	.ctl[dsf_bts_kernel]	= (1 << 5),
 	.ctl[dsf_bts_user]	= (1 << 6),
-
-	.sizeof_field		= sizeof(long),
-	.sizeof_rec[ds_bts]	= sizeof(long) * 3,
-#ifdef __i386__
-	.sizeof_rec[ds_pebs]	= sizeof(long) * 10,
-#else
-	.sizeof_rec[ds_pebs]	= sizeof(long) * 18,
-#endif
+	.nr_counter_reset	= 1,
 };
 static const struct ds_configuration ds_cfg_pentium_m = {
 	.name = "Pentium M",
 	.ctl[dsf_bts]		= (1 << 6) | (1 << 7),
-
-	.sizeof_field		= sizeof(long),
-	.sizeof_rec[ds_bts]	= sizeof(long) * 3,
-#ifdef __i386__
-	.sizeof_rec[ds_pebs]	= sizeof(long) * 10,
-#else
-	.sizeof_rec[ds_pebs]	= sizeof(long) * 18,
-#endif
+	.nr_counter_reset	= 1,
 };
 static const struct ds_configuration ds_cfg_core2_atom = {
 	.name = "Core 2/Atom",
 	.ctl[dsf_bts]		= (1 << 6) | (1 << 7),
 	.ctl[dsf_bts_kernel]	= (1 << 9),
 	.ctl[dsf_bts_user]	= (1 << 10),
-
-	.sizeof_field		= 8,
-	.sizeof_rec[ds_bts]	= 8 * 3,
-	.sizeof_rec[ds_pebs]	= 8 * 18,
+	.nr_counter_reset	= 1,
+};
+static const struct ds_configuration ds_cfg_core_i7 = {
+	.name = "Core i7",
+	.ctl[dsf_bts]		= (1 << 6) | (1 << 7),
+	.ctl[dsf_bts_kernel]	= (1 << 9),
+	.ctl[dsf_bts_user]	= (1 << 10),
+	.nr_counter_reset	= 4,
 };
 
 static void
-ds_configure(const struct ds_configuration *cfg)
+ds_configure(const struct ds_configuration *cfg,
+	     struct cpuinfo_x86 *cpu)
 {
+	unsigned long nr_pebs_fields = 0;
+
+	printk(KERN_INFO "[ds] using %s configuration\n", cfg->name);
+
+#ifdef __i386__
+	nr_pebs_fields = 10;
+#else
+	nr_pebs_fields = 18;
+#endif
+
+	/*
+	 * Starting with version 2, architectural performance
+	 * monitoring supports a format specifier.
+	 */
+	if ((cpuid_eax(0xa) & 0xff) > 1) {
+		unsigned long perf_capabilities, format;
+
+		rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
+
+		format = (perf_capabilities >> 8) & 0xf;
+
+		switch (format) {
+		case 0:
+			nr_pebs_fields = 18;
+			break;
+		case 1:
+			nr_pebs_fields = 22;
+			break;
+		default:
+			printk(KERN_INFO
+			       "[ds] unknown PEBS format: %lu\n", format);
+			nr_pebs_fields = 0;
+			break;
+		}
+	}
+
 	memset(&ds_cfg, 0, sizeof(ds_cfg));
 	ds_cfg = *cfg;
 
-	printk(KERN_INFO "[ds] using %s configuration\n", ds_cfg.name);
+	ds_cfg.sizeof_ptr_field =
+		(cpu_has(cpu, X86_FEATURE_DTES64) ? 8 : 4);
 
-	if (!cpu_has_bts) {
-		ds_cfg.ctl[dsf_bts] = 0;
+	ds_cfg.sizeof_rec[ds_bts]  = ds_cfg.sizeof_ptr_field * 3;
+	ds_cfg.sizeof_rec[ds_pebs] = ds_cfg.sizeof_ptr_field * nr_pebs_fields;
+
+	if (!cpu_has(cpu, X86_FEATURE_BTS)) {
+		ds_cfg.sizeof_rec[ds_bts] = 0;
 		printk(KERN_INFO "[ds] bts not available\n");
 	}
-	if (!cpu_has_pebs)
+	if (!cpu_has(cpu, X86_FEATURE_PEBS)) {
+		ds_cfg.sizeof_rec[ds_pebs] = 0;
 		printk(KERN_INFO "[ds] pebs not available\n");
+	}
 
-	WARN_ON_ONCE(MAX_SIZEOF_DS < (12 * ds_cfg.sizeof_field));
+	printk(KERN_INFO "[ds] sizes: address: %u bit, ",
+	       8 * ds_cfg.sizeof_ptr_field);
+	printk("bts/pebs record: %u/%u bytes\n",
+	       ds_cfg.sizeof_rec[ds_bts], ds_cfg.sizeof_rec[ds_pebs]);
+
+	WARN_ON_ONCE(MAX_PEBS_COUNTERS < ds_cfg.nr_counter_reset);
 }
 
 void __cpuinit ds_init_intel(struct cpuinfo_x86 *c)
 {
+	/* Only configure the first cpu. Others are identical. */
+	if (ds_cfg.name)
+		return;
+
 	switch (c->x86) {
 	case 0x6:
 		switch (c->x86_model) {
 		case 0x9:
 		case 0xd: /* Pentium M */
-			ds_configure(&ds_cfg_pentium_m);
+			ds_configure(&ds_cfg_pentium_m, c);
 			break;
 		case 0xf:
 		case 0x17: /* Core2 */
 		case 0x1c: /* Atom */
-			ds_configure(&ds_cfg_core2_atom);
+			ds_configure(&ds_cfg_core2_atom, c);
+			break;
+		case 0x1a: /* Core i7 */
+			ds_configure(&ds_cfg_core_i7, c);
 			break;
-		case 0x1a: /* i7 */
 		default:
-			/* sorry, don't know about them */
+			/* Sorry, don't know about them. */
 			break;
 		}
 		break;
@@ -969,64 +1349,89 @@
 		case 0x0:
 		case 0x1:
 		case 0x2: /* Netburst */
-			ds_configure(&ds_cfg_netburst);
+			ds_configure(&ds_cfg_netburst, c);
 			break;
 		default:
-			/* sorry, don't know about them */
+			/* Sorry, don't know about them. */
 			break;
 		}
 		break;
 	default:
-		/* sorry, don't know about them */
+		/* Sorry, don't know about them. */
 		break;
 	}
 }
 
+static inline void ds_take_timestamp(struct ds_context *context,
+				     enum bts_qualifier qualifier,
+				     struct task_struct *task)
+{
+	struct bts_tracer *tracer = context->bts_master;
+	struct bts_struct ts;
+
+	/* Prevent compilers from reading the tracer pointer twice. */
+	barrier();
+
+	if (!tracer || !(tracer->flags & BTS_TIMESTAMPS))
+		return;
+
+	memset(&ts, 0, sizeof(ts));
+	ts.qualifier		= qualifier;
+	ts.variant.event.clock	= trace_clock_global();
+	ts.variant.event.pid	= task->pid;
+
+	bts_write(tracer, &ts);
+}
+
 /*
  * Change the DS configuration from tracing prev to tracing next.
  */
 void ds_switch_to(struct task_struct *prev, struct task_struct *next)
 {
-	struct ds_context *prev_ctx = prev->thread.ds_ctx;
-	struct ds_context *next_ctx = next->thread.ds_ctx;
+	struct ds_context *prev_ctx	= prev->thread.ds_ctx;
+	struct ds_context *next_ctx	= next->thread.ds_ctx;
+	unsigned long debugctlmsr	= next->thread.debugctlmsr;
+
+	/* Make sure all data is read before we start. */
+	barrier();
 
 	if (prev_ctx) {
 		update_debugctlmsr(0);
 
-		if (prev_ctx->bts_master &&
-		    (prev_ctx->bts_master->trace.ds.flags & BTS_TIMESTAMPS)) {
-			struct bts_struct ts = {
-				.qualifier = bts_task_departs,
-				.variant.timestamp.jiffies = jiffies_64,
-				.variant.timestamp.pid = prev->pid
-			};
-			bts_write(prev_ctx->bts_master, &ts);
-		}
+		ds_take_timestamp(prev_ctx, bts_task_departs, prev);
 	}
 
 	if (next_ctx) {
-		if (next_ctx->bts_master &&
-		    (next_ctx->bts_master->trace.ds.flags & BTS_TIMESTAMPS)) {
-			struct bts_struct ts = {
-				.qualifier = bts_task_arrives,
-				.variant.timestamp.jiffies = jiffies_64,
-				.variant.timestamp.pid = next->pid
-			};
-			bts_write(next_ctx->bts_master, &ts);
-		}
+		ds_take_timestamp(next_ctx, bts_task_arrives, next);
 
 		wrmsrl(MSR_IA32_DS_AREA, (unsigned long)next_ctx->ds);
 	}
 
-	update_debugctlmsr(next->thread.debugctlmsr);
+	update_debugctlmsr(debugctlmsr);
 }
 
-void ds_copy_thread(struct task_struct *tsk, struct task_struct *father)
+static __init int ds_selftest(void)
 {
-	clear_tsk_thread_flag(tsk, TIF_DS_AREA_MSR);
-	tsk->thread.ds_ctx = NULL;
-}
+	if (ds_cfg.sizeof_rec[ds_bts]) {
+		int error;
 
-void ds_exit_thread(struct task_struct *tsk)
-{
+		error = ds_selftest_bts();
+		if (error) {
+			WARN(1, "[ds] selftest failed. disabling bts.\n");
+			ds_cfg.sizeof_rec[ds_bts] = 0;
+		}
+	}
+
+	if (ds_cfg.sizeof_rec[ds_pebs]) {
+		int error;
+
+		error = ds_selftest_pebs();
+		if (error) {
+			WARN(1, "[ds] selftest failed. disabling pebs.\n");
+			ds_cfg.sizeof_rec[ds_pebs] = 0;
+		}
+	}
+
+	return 0;
 }
+device_initcall(ds_selftest);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/ds_selftest.c linux-libre-2.6.31-gnu/arch/x86/kernel/ds_selftest.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/ds_selftest.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/ds_selftest.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,408 @@
+/*
+ * Debug Store support - selftest
+ *
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ * Markus Metzger <markus.t.metzger@intel.com>, 2009
+ */
+
+#include "ds_selftest.h"
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+
+#include <asm/ds.h>
+
+
+#define BUFFER_SIZE		521	/* Intentionally chose an odd size. */
+#define SMALL_BUFFER_SIZE	24	/* A single bts entry. */
+
+struct ds_selftest_bts_conf {
+	struct bts_tracer *tracer;
+	int error;
+	int (*suspend)(struct bts_tracer *);
+	int (*resume)(struct bts_tracer *);
+};
+
+static int ds_selftest_bts_consistency(const struct bts_trace *trace)
+{
+	int error = 0;
+
+	if (!trace) {
+		printk(KERN_CONT "failed to access trace...");
+		/* Bail out. Other tests are pointless. */
+		return -1;
+	}
+
+	if (!trace->read) {
+		printk(KERN_CONT "bts read not available...");
+		error = -1;
+	}
+
+	/* Do some sanity checks on the trace configuration. */
+	if (!trace->ds.n) {
+		printk(KERN_CONT "empty bts buffer...");
+		error = -1;
+	}
+	if (!trace->ds.size) {
+		printk(KERN_CONT "bad bts trace setup...");
+		error = -1;
+	}
+	if (trace->ds.end !=
+	    (char *)trace->ds.begin + (trace->ds.n * trace->ds.size)) {
+		printk(KERN_CONT "bad bts buffer setup...");
+		error = -1;
+	}
+	/*
+	 * We allow top in [begin; end], since its not clear when the
+	 * overflow adjustment happens: after the increment or before the
+	 * write.
+	 */
+	if ((trace->ds.top < trace->ds.begin) ||
+	    (trace->ds.end < trace->ds.top)) {
+		printk(KERN_CONT "bts top out of bounds...");
+		error = -1;
+	}
+
+	return error;
+}
+
+static int ds_selftest_bts_read(struct bts_tracer *tracer,
+				const struct bts_trace *trace,
+				const void *from, const void *to)
+{
+	const unsigned char *at;
+
+	/*
+	 * Check a few things which do not belong to this test.
+	 * They should be covered by other tests.
+	 */
+	if (!trace)
+		return -1;
+
+	if (!trace->read)
+		return -1;
+
+	if (to < from)
+		return -1;
+
+	if (from < trace->ds.begin)
+		return -1;
+
+	if (trace->ds.end < to)
+		return -1;
+
+	if (!trace->ds.size)
+		return -1;
+
+	/* Now to the test itself. */
+	for (at = from; (void *)at < to; at += trace->ds.size) {
+		struct bts_struct bts;
+		unsigned long index;
+		int error;
+
+		if (((void *)at - trace->ds.begin) % trace->ds.size) {
+			printk(KERN_CONT
+			       "read from non-integer index...");
+			return -1;
+		}
+		index = ((void *)at - trace->ds.begin) / trace->ds.size;
+
+		memset(&bts, 0, sizeof(bts));
+		error = trace->read(tracer, at, &bts);
+		if (error < 0) {
+			printk(KERN_CONT
+			       "error reading bts trace at [%lu] (0x%p)...",
+			       index, at);
+			return error;
+		}
+
+		switch (bts.qualifier) {
+		case BTS_BRANCH:
+			break;
+		default:
+			printk(KERN_CONT
+			       "unexpected bts entry %llu at [%lu] (0x%p)...",
+			       bts.qualifier, index, at);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static void ds_selftest_bts_cpu(void *arg)
+{
+	struct ds_selftest_bts_conf *conf = arg;
+	const struct bts_trace *trace;
+	void *top;
+
+	if (IS_ERR(conf->tracer)) {
+		conf->error = PTR_ERR(conf->tracer);
+		conf->tracer = NULL;
+
+		printk(KERN_CONT
+		       "initialization failed (err: %d)...", conf->error);
+		return;
+	}
+
+	/* We should meanwhile have enough trace. */
+	conf->error = conf->suspend(conf->tracer);
+	if (conf->error < 0)
+		return;
+
+	/* Let's see if we can access the trace. */
+	trace = ds_read_bts(conf->tracer);
+
+	conf->error = ds_selftest_bts_consistency(trace);
+	if (conf->error < 0)
+		return;
+
+	/* If everything went well, we should have a few trace entries. */
+	if (trace->ds.top == trace->ds.begin) {
+		/*
+		 * It is possible but highly unlikely that we got a
+		 * buffer overflow and end up at exactly the same
+		 * position we started from.
+		 * Let's issue a warning, but continue.
+		 */
+		printk(KERN_CONT "no trace/overflow...");
+	}
+
+	/* Let's try to read the trace we collected. */
+	conf->error =
+		ds_selftest_bts_read(conf->tracer, trace,
+				     trace->ds.begin, trace->ds.top);
+	if (conf->error < 0)
+		return;
+
+	/*
+	 * Let's read the trace again.
+	 * Since we suspended tracing, we should get the same result.
+	 */
+	top = trace->ds.top;
+
+	trace = ds_read_bts(conf->tracer);
+	conf->error = ds_selftest_bts_consistency(trace);
+	if (conf->error < 0)
+		return;
+
+	if (top != trace->ds.top) {
+		printk(KERN_CONT "suspend not working...");
+		conf->error = -1;
+		return;
+	}
+
+	/* Let's collect some more trace - see if resume is working. */
+	conf->error = conf->resume(conf->tracer);
+	if (conf->error < 0)
+		return;
+
+	conf->error = conf->suspend(conf->tracer);
+	if (conf->error < 0)
+		return;
+
+	trace = ds_read_bts(conf->tracer);
+
+	conf->error = ds_selftest_bts_consistency(trace);
+	if (conf->error < 0)
+		return;
+
+	if (trace->ds.top == top) {
+		/*
+		 * It is possible but highly unlikely that we got a
+		 * buffer overflow and end up at exactly the same
+		 * position we started from.
+		 * Let's issue a warning and check the full trace.
+		 */
+		printk(KERN_CONT
+		       "no resume progress/overflow...");
+
+		conf->error =
+			ds_selftest_bts_read(conf->tracer, trace,
+					     trace->ds.begin, trace->ds.end);
+	} else if (trace->ds.top < top) {
+		/*
+		 * We had a buffer overflow - the entire buffer should
+		 * contain trace records.
+		 */
+		conf->error =
+			ds_selftest_bts_read(conf->tracer, trace,
+					     trace->ds.begin, trace->ds.end);
+	} else {
+		/*
+		 * It is quite likely that the buffer did not overflow.
+		 * Let's just check the delta trace.
+		 */
+		conf->error =
+			ds_selftest_bts_read(conf->tracer, trace, top,
+					     trace->ds.top);
+	}
+	if (conf->error < 0)
+		return;
+
+	conf->error = 0;
+}
+
+static int ds_suspend_bts_wrap(struct bts_tracer *tracer)
+{
+	ds_suspend_bts(tracer);
+	return 0;
+}
+
+static int ds_resume_bts_wrap(struct bts_tracer *tracer)
+{
+	ds_resume_bts(tracer);
+	return 0;
+}
+
+static void ds_release_bts_noirq_wrap(void *tracer)
+{
+	(void)ds_release_bts_noirq(tracer);
+}
+
+static int ds_selftest_bts_bad_release_noirq(int cpu,
+					     struct bts_tracer *tracer)
+{
+	int error = -EPERM;
+
+	/* Try to release the tracer on the wrong cpu. */
+	get_cpu();
+	if (cpu != smp_processor_id()) {
+		error = ds_release_bts_noirq(tracer);
+		if (error != -EPERM)
+			printk(KERN_CONT "release on wrong cpu...");
+	}
+	put_cpu();
+
+	return error ? 0 : -1;
+}
+
+static int ds_selftest_bts_bad_request_cpu(int cpu, void *buffer)
+{
+	struct bts_tracer *tracer;
+	int error;
+
+	/* Try to request cpu tracing while task tracing is active. */
+	tracer = ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, NULL,
+				    (size_t)-1, BTS_KERNEL);
+	error = PTR_ERR(tracer);
+	if (!IS_ERR(tracer)) {
+		ds_release_bts(tracer);
+		error = 0;
+	}
+
+	if (error != -EPERM)
+		printk(KERN_CONT "cpu/task tracing overlap...");
+
+	return error ? 0 : -1;
+}
+
+static int ds_selftest_bts_bad_request_task(void *buffer)
+{
+	struct bts_tracer *tracer;
+	int error;
+
+	/* Try to request cpu tracing while task tracing is active. */
+	tracer = ds_request_bts_task(current, buffer, BUFFER_SIZE, NULL,
+				    (size_t)-1, BTS_KERNEL);
+	error = PTR_ERR(tracer);
+	if (!IS_ERR(tracer)) {
+		error = 0;
+		ds_release_bts(tracer);
+	}
+
+	if (error != -EPERM)
+		printk(KERN_CONT "task/cpu tracing overlap...");
+
+	return error ? 0 : -1;
+}
+
+int ds_selftest_bts(void)
+{
+	struct ds_selftest_bts_conf conf;
+	unsigned char buffer[BUFFER_SIZE], *small_buffer;
+	unsigned long irq;
+	int cpu;
+
+	printk(KERN_INFO "[ds] bts selftest...");
+	conf.error = 0;
+
+	small_buffer = (unsigned char *)ALIGN((unsigned long)buffer, 8) + 8;
+
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		conf.suspend = ds_suspend_bts_wrap;
+		conf.resume = ds_resume_bts_wrap;
+		conf.tracer =
+			ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE,
+					   NULL, (size_t)-1, BTS_KERNEL);
+		ds_selftest_bts_cpu(&conf);
+		if (conf.error >= 0)
+			conf.error = ds_selftest_bts_bad_request_task(buffer);
+		ds_release_bts(conf.tracer);
+		if (conf.error < 0)
+			goto out;
+
+		conf.suspend = ds_suspend_bts_noirq;
+		conf.resume = ds_resume_bts_noirq;
+		conf.tracer =
+			ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE,
+					   NULL, (size_t)-1, BTS_KERNEL);
+		smp_call_function_single(cpu, ds_selftest_bts_cpu, &conf, 1);
+		if (conf.error >= 0) {
+			conf.error =
+				ds_selftest_bts_bad_release_noirq(cpu,
+								  conf.tracer);
+			/* We must not release the tracer twice. */
+			if (conf.error < 0)
+				conf.tracer = NULL;
+		}
+		if (conf.error >= 0)
+			conf.error = ds_selftest_bts_bad_request_task(buffer);
+		smp_call_function_single(cpu, ds_release_bts_noirq_wrap,
+					 conf.tracer, 1);
+		if (conf.error < 0)
+			goto out;
+	}
+
+	conf.suspend = ds_suspend_bts_wrap;
+	conf.resume = ds_resume_bts_wrap;
+	conf.tracer =
+		ds_request_bts_task(current, buffer, BUFFER_SIZE,
+				    NULL, (size_t)-1, BTS_KERNEL);
+	ds_selftest_bts_cpu(&conf);
+	if (conf.error >= 0)
+		conf.error = ds_selftest_bts_bad_request_cpu(0, buffer);
+	ds_release_bts(conf.tracer);
+	if (conf.error < 0)
+		goto out;
+
+	conf.suspend = ds_suspend_bts_noirq;
+	conf.resume = ds_resume_bts_noirq;
+	conf.tracer =
+		ds_request_bts_task(current, small_buffer, SMALL_BUFFER_SIZE,
+				   NULL, (size_t)-1, BTS_KERNEL);
+	local_irq_save(irq);
+	ds_selftest_bts_cpu(&conf);
+	if (conf.error >= 0)
+		conf.error = ds_selftest_bts_bad_request_cpu(0, buffer);
+	ds_release_bts_noirq(conf.tracer);
+	local_irq_restore(irq);
+	if (conf.error < 0)
+		goto out;
+
+	conf.error = 0;
+ out:
+	put_online_cpus();
+	printk(KERN_CONT "%s.\n", (conf.error ? "failed" : "passed"));
+
+	return conf.error;
+}
+
+int ds_selftest_pebs(void)
+{
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/ds_selftest.h linux-libre-2.6.31-gnu/arch/x86/kernel/ds_selftest.h
--- linux-libre-2.6.30-gnu/arch/x86/kernel/ds_selftest.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/ds_selftest.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,15 @@
+/*
+ * Debug Store support - selftest
+ *
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ * Markus Metzger <markus.t.metzger@intel.com>, 2009
+ */
+
+#ifdef CONFIG_X86_DS_SELFTEST
+extern int ds_selftest_bts(void);
+extern int ds_selftest_pebs(void);
+#else
+static inline int ds_selftest_bts(void) { return 0; }
+static inline int ds_selftest_pebs(void) { return 0; }
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,12 @@
 
 #include "dumpstack.h"
 
+/* Just a stub for now */
+int x86_is_stack_id(int id, char *name)
+{
+	return 0;
+}
+
 void dump_trace(struct task_struct *task, struct pt_regs *regs,
 		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,10 +19,8 @@
 
 #include "dumpstack.h"
 
-static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
-					unsigned *usedp, char **idp)
-{
-	static char ids[][8] = {
+
+static char x86_stack_ids[][8] = {
 		[DEBUG_STACK - 1] = "#DB",
 		[NMI_STACK - 1] = "NMI",
 		[DOUBLEFAULT_STACK - 1] = "#DF",
@@ -33,6 +31,15 @@
 			N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
 #endif
 	};
+
+int x86_is_stack_id(int id, char *name)
+{
+	return x86_stack_ids[id - 1] == name;
+}
+
+static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+					unsigned *usedp, char **idp)
+{
 	unsigned k;
 
 	/*
@@ -61,7 +68,7 @@
 			if (*usedp & (1U << k))
 				break;
 			*usedp |= 1U << k;
-			*idp = ids[k];
+			*idp = x86_stack_ids[k];
 			return (unsigned long *)end;
 		}
 		/*
@@ -81,12 +88,13 @@
 			do {
 				++j;
 				end -= EXCEPTION_STKSZ;
-				ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
+				x86_stack_ids[j][4] = '1' +
+						(j - N_EXCEPTION_STACKS);
 			} while (stack < end - EXCEPTION_STKSZ);
 			if (*usedp & (1U << j))
 				break;
 			*usedp |= 1U << j;
-			*idp = ids[j];
+			*idp = x86_stack_ids[j];
 			return (unsigned long *)end;
 		}
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack.c linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include "dumpstack.h"
 
 int panic_on_unrecovered_nmi;
+int panic_on_io_nmi;
 unsigned int code_bytes = 64;
 int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
 static int die_counter;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack.h linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack.h
--- linux-libre-2.6.30-gnu/arch/x86/kernel/dumpstack.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/dumpstack.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,6 @@
 		unsigned long *sp, unsigned long bp, char *log_lvl);
 
 extern unsigned int code_bytes;
-extern int kstack_depth_to_print;
 
 /* The form of the top of the frame on the stack */
 struct stack_frame {
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/e820.c linux-libre-2.6.31-gnu/arch/x86/kernel/e820.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/e820.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/e820.c	2009-09-09 18:13:59.000000000 -0400
@@ -617,7 +617,7 @@
  */
 __init void e820_setup_gap(void)
 {
-	unsigned long gapstart, gapsize, round;
+	unsigned long gapstart, gapsize;
 	int found;
 
 	gapstart = 0x10000000;
@@ -627,22 +627,16 @@
 #ifdef CONFIG_X86_64
 	if (!found) {
 		gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
-		printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit "
-		       "address range\n"
-		       KERN_ERR "PCI: Unassigned devices with 32bit resource "
-		       "registers may break!\n");
+		printk(KERN_ERR
+	"PCI: Warning: Cannot find a gap in the 32bit address range\n"
+	"PCI: Unassigned devices with 32bit resource registers may break!\n");
 	}
 #endif
 
 	/*
-	 * See how much we want to round up: start off with
-	 * rounding to the next 1MB area.
+	 * e820_reserve_resources_late protect stolen RAM already
 	 */
-	round = 0x100000;
-	while ((gapsize >> 4) > round)
-		round += round;
-	/* Fun with two's complement */
-	pci_mem_start = (gapstart + round) & -round;
+	pci_mem_start = gapstart;
 
 	printk(KERN_INFO
 	       "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
@@ -1371,6 +1365,25 @@
 	}
 }
 
+/* How much should we pad RAM ending depending on where it is? */
+static unsigned long ram_alignment(resource_size_t pos)
+{
+	unsigned long mb = pos >> 20;
+
+	/* To 64kB in the first megabyte */
+	if (!mb)
+		return 64*1024;
+
+	/* To 1MB in the first 16MB */
+	if (mb < 16)
+		return 1024*1024;
+
+	/* To 32MB for anything above that */
+	return 32*1024*1024;
+}
+
+#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
+
 void __init e820_reserve_resources_late(void)
 {
 	int i;
@@ -1382,6 +1395,26 @@
 			insert_resource_expand_to_fit(&iomem_resource, res);
 		res++;
 	}
+
+	/*
+	 * Try to bump up RAM regions to reasonable boundaries to
+	 * avoid stolen RAM:
+	 */
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *entry = &e820.map[i];
+		u64 start, end;
+
+		if (entry->type != E820_RAM)
+			continue;
+		start = entry->addr + entry->size;
+		end = round_up(start, ram_alignment(start)) - 1;
+		if (end > MAX_RESOURCE_SIZE)
+			end = MAX_RESOURCE_SIZE;
+		if (start >= end)
+			continue;
+		reserve_region_with_split(&iomem_resource, start, end,
+					  "RAM buffer");
+	}
 }
 
 char *__init default_machine_specific_memory_setup(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/early-quirks.c linux-libre-2.6.31-gnu/arch/x86/kernel/early-quirks.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/early-quirks.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/early-quirks.c	2009-09-09 18:13:59.000000000 -0400
@@ -97,6 +97,7 @@
 }
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
+#if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
 static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
 {
 	u32 d;
@@ -114,6 +115,7 @@
 	d &= 0xff;
 	return d;
 }
+#endif
 
 static void __init ati_bugs(int num, int slot, int func)
 {
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/efi_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/efi_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/efi_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/efi_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,10 +98,14 @@
 	early_runtime_code_mapping_set_exec(0);
 }
 
-void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size)
+void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
+				 u32 type)
 {
 	unsigned long last_map_pfn;
 
+	if (type == EFI_MEMORY_MAPPED_IO)
+		return ioremap(phys_addr, size);
+
 	last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
 	if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size)
 		return NULL;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/efi.c linux-libre-2.6.31-gnu/arch/x86/kernel/efi.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/efi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/efi.c	2009-09-09 18:13:59.000000000 -0400
@@ -240,10 +240,35 @@
 		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
 		int e820_type;
 
-		if (md->attribute & EFI_MEMORY_WB)
-			e820_type = E820_RAM;
-		else
+		switch (md->type) {
+		case EFI_LOADER_CODE:
+		case EFI_LOADER_DATA:
+		case EFI_BOOT_SERVICES_CODE:
+		case EFI_BOOT_SERVICES_DATA:
+		case EFI_CONVENTIONAL_MEMORY:
+			if (md->attribute & EFI_MEMORY_WB)
+				e820_type = E820_RAM;
+			else
+				e820_type = E820_RESERVED;
+			break;
+		case EFI_ACPI_RECLAIM_MEMORY:
+			e820_type = E820_ACPI;
+			break;
+		case EFI_ACPI_MEMORY_NVS:
+			e820_type = E820_NVS;
+			break;
+		case EFI_UNUSABLE_MEMORY:
+			e820_type = E820_UNUSABLE;
+			break;
+		default:
+			/*
+			 * EFI_RESERVED_TYPE EFI_RUNTIME_SERVICES_CODE
+			 * EFI_RUNTIME_SERVICES_DATA EFI_MEMORY_MAPPED_IO
+			 * EFI_MEMORY_MAPPED_IO_PORT_SPACE EFI_PAL_CODE
+			 */
 			e820_type = E820_RESERVED;
+			break;
+		}
 		e820_add_region(start, size, e820_type);
 	}
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
@@ -329,7 +354,7 @@
 	 */
 	c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
 	if (c16) {
-		for (i = 0; i < sizeof(vendor) && *c16; ++i)
+		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
 		vendor[i] = '\0';
 	} else
@@ -487,7 +512,7 @@
 			&& end_pfn <= max_pfn_mapped))
 			va = __va(md->phys_addr);
 		else
-			va = efi_ioremap(md->phys_addr, size);
+			va = efi_ioremap(md->phys_addr, size, md->type);
 
 		md->virt_addr = (u64) (unsigned long) va;
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/entry_32.S linux-libre-2.6.31-gnu/arch/x86/kernel/entry_32.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/entry_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/entry_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,6 @@
 #include <asm/segment.h>
 #include <asm/smp.h>
 #include <asm/page_types.h>
-#include <asm/desc.h>
 #include <asm/percpu.h>
 #include <asm/dwarf2.h>
 #include <asm/processor-flags.h>
@@ -84,7 +83,7 @@
 #define preempt_stop(clobbers)	DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
 #else
 #define preempt_stop(clobbers)
-#define resume_kernel		restore_nocheck
+#define resume_kernel		restore_all
 #endif
 
 .macro TRACE_IRQS_IRET
@@ -372,7 +371,7 @@
 ENTRY(resume_kernel)
 	DISABLE_INTERRUPTS(CLBR_ANY)
 	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
-	jnz restore_nocheck
+	jnz restore_all
 need_resched:
 	movl TI_flags(%ebp), %ecx	# need_resched set ?
 	testb $_TIF_NEED_RESCHED, %cl
@@ -540,6 +539,8 @@
 	jne syscall_exit_work
 
 restore_all:
+	TRACE_IRQS_IRET
+restore_all_notrace:
 	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
 	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
 	# are returning to the kernel.
@@ -551,8 +552,6 @@
 	CFI_REMEMBER_STATE
 	je ldt_ss			# returning to user-space with LDT SS
 restore_nocheck:
-	TRACE_IRQS_IRET
-restore_nocheck_notrace:
 	RESTORE_REGS 4			# skip orig_eax/error_code
 	CFI_ADJUST_CFA_OFFSET -4
 irq_return:
@@ -588,22 +587,34 @@
 	jne restore_nocheck
 #endif
 
-	/* If returning to userspace with 16bit stack,
-	 * try to fix the higher word of ESP, as the CPU
-	 * won't restore it.
-	 * This is an "official" bug of all the x86-compatible
-	 * CPUs, which we can try to work around to make
-	 * dosemu and wine happy. */
-	movl PT_OLDESP(%esp), %eax
-	movl %esp, %edx
-	call patch_espfix_desc
+/*
+ * Setup and switch to ESPFIX stack
+ *
+ * We're returning to userspace with a 16 bit stack. The CPU will not
+ * restore the high word of ESP for us on executing iret... This is an
+ * "official" bug of all the x86-compatible CPUs, which we can work
+ * around to make dosemu and wine happy. We do this by preloading the
+ * high word of ESP with the high word of the userspace ESP while
+ * compensating for the offset by changing to the ESPFIX segment with
+ * a base address that matches for the difference.
+ */
+	mov %esp, %edx			/* load kernel esp */
+	mov PT_OLDESP(%esp), %eax	/* load userspace esp */
+	mov %dx, %ax			/* eax: new kernel esp */
+	sub %eax, %edx			/* offset (low word is 0) */
+	PER_CPU(gdt_page, %ebx)
+	shr $16, %edx
+	mov %dl, GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx) /* bits 16..23 */
+	mov %dh, GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx) /* bits 24..31 */
 	pushl $__ESPFIX_SS
 	CFI_ADJUST_CFA_OFFSET 4
-	pushl %eax
+	push %eax			/* new kernel esp */
 	CFI_ADJUST_CFA_OFFSET 4
+	/* Disable interrupts, but do not irqtrace this section: we
+	 * will soon execute iret and the tracer was already set to
+	 * the irqstate after the iret */
 	DISABLE_INTERRUPTS(CLBR_EAX)
-	TRACE_IRQS_OFF
-	lss (%esp), %esp
+	lss (%esp), %esp		/* switch to espfix segment */
 	CFI_ADJUST_CFA_OFFSET -8
 	jmp restore_nocheck
 	CFI_ENDPROC
@@ -716,15 +727,24 @@
 PTREGSCALL(vm86old)
 
 .macro FIXUP_ESPFIX_STACK
-	/* since we are on a wrong stack, we cant make it a C code :( */
+/*
+ * Switch back for ESPFIX stack to the normal zerobased stack
+ *
+ * We can't call C functions using the ESPFIX stack. This code reads
+ * the high word of the segment base from the GDT and swiches to the
+ * normal stack and adjusts ESP with the matching offset.
+ */
+	/* fixup the stack */
 	PER_CPU(gdt_page, %ebx)
-	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
-	addl %esp, %eax
+	mov GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx), %al /* bits 16..23 */
+	mov GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx), %ah /* bits 24..31 */
+	shl $16, %eax
+	addl %esp, %eax			/* the adjusted stack pointer */
 	pushl $__KERNEL_DS
 	CFI_ADJUST_CFA_OFFSET 4
 	pushl %eax
 	CFI_ADJUST_CFA_OFFSET 4
-	lss (%esp), %esp
+	lss (%esp), %esp		/* switch to the normal stack segment */
 	CFI_ADJUST_CFA_OFFSET -8
 .endm
 .macro UNWIND_ESPFIX_STACK
@@ -1154,6 +1174,7 @@
 	pushl %edx
 	movl 0xc(%esp), %edx
 	lea 0x4(%ebp), %eax
+	movl (%ebp), %ecx
 	subl $MCOUNT_INSN_SIZE, %edx
 	call prepare_ftrace_return
 	popl %edx
@@ -1168,6 +1189,7 @@
 	pushl %eax
 	pushl %ecx
 	pushl %edx
+	movl %ebp, %eax
 	call ftrace_return_to_handler
 	movl %eax, 0xc(%esp)
 	popl %edx
@@ -1329,7 +1351,7 @@
 	xorl %edx,%edx		# zero error code
 	movl %esp,%eax		# pt_regs pointer
 	call do_nmi
-	jmp restore_nocheck_notrace
+	jmp restore_all_notrace
 	CFI_ENDPROC
 
 nmi_stack_fixup:
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/entry_64.S linux-libre-2.6.31-gnu/arch/x86/kernel/entry_64.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/entry_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/entry_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -135,6 +135,7 @@
 
 	leaq 8(%rbp), %rdi
 	movq 0x38(%rsp), %rsi
+	movq (%rbp), %rdx
 	subq $MCOUNT_INSN_SIZE, %rsi
 
 	call	prepare_ftrace_return
@@ -147,27 +148,15 @@
 GLOBAL(return_to_handler)
 	subq  $80, %rsp
 
+	/* Save the return values */
 	movq %rax, (%rsp)
-	movq %rcx, 8(%rsp)
-	movq %rdx, 16(%rsp)
-	movq %rsi, 24(%rsp)
-	movq %rdi, 32(%rsp)
-	movq %r8, 40(%rsp)
-	movq %r9, 48(%rsp)
-	movq %r10, 56(%rsp)
-	movq %r11, 64(%rsp)
+	movq %rdx, 8(%rsp)
+	movq %rbp, %rdi
 
 	call ftrace_return_to_handler
 
 	movq %rax, 72(%rsp)
-	movq 64(%rsp), %r11
-	movq 56(%rsp), %r10
-	movq 48(%rsp), %r9
-	movq 40(%rsp), %r8
-	movq 32(%rsp), %rdi
-	movq 24(%rsp), %rsi
-	movq 16(%rsp), %rdx
-	movq 8(%rsp), %rcx
+	movq 8(%rsp), %rdx
 	movq (%rsp), %rax
 	addq $72, %rsp
 	retq
@@ -976,6 +965,8 @@
 #ifdef CONFIG_SMP
 apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
 	irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
+apicinterrupt REBOOT_VECTOR \
+	reboot_interrupt smp_reboot_interrupt
 #endif
 
 #ifdef CONFIG_X86_UV
@@ -1007,10 +998,15 @@
 #endif
 
 apicinterrupt THRESHOLD_APIC_VECTOR \
-	threshold_interrupt mce_threshold_interrupt
+	threshold_interrupt smp_threshold_interrupt
 apicinterrupt THERMAL_APIC_VECTOR \
 	thermal_interrupt smp_thermal_interrupt
 
+#ifdef CONFIG_X86_MCE
+apicinterrupt MCE_SELF_VECTOR \
+	mce_self_interrupt smp_mce_self_interrupt
+#endif
+
 #ifdef CONFIG_SMP
 apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
 	call_function_single_interrupt smp_call_function_single_interrupt
@@ -1025,6 +1021,11 @@
 apicinterrupt SPURIOUS_APIC_VECTOR \
 	spurious_interrupt smp_spurious_interrupt
 
+#ifdef CONFIG_PERF_COUNTERS
+apicinterrupt LOCAL_PENDING_VECTOR \
+	perf_pending_interrupt smp_perf_pending_interrupt
+#endif
+
 /*
  * Exception entry points.
  */
@@ -1379,10 +1380,15 @@
 paranoidzeroentry_ist debug do_debug DEBUG_STACK
 paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
 paranoiderrorentry stack_segment do_stack_segment
+#ifdef CONFIG_XEN
+zeroentry xen_debug do_debug
+zeroentry xen_int3 do_int3
+errorentry xen_stack_segment do_stack_segment
+#endif
 errorentry general_protection do_general_protection
 errorentry page_fault do_page_fault
 #ifdef CONFIG_X86_MCE
-paranoidzeroentry machine_check do_machine_check
+paranoidzeroentry machine_check *machine_check_vector(%rip)
 #endif
 
 	/*
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/ftrace.c linux-libre-2.6.31-gnu/arch/x86/kernel/ftrace.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/ftrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/ftrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -408,7 +408,8 @@
  * Hook the return address and push it in the stack of return addrs
  * in current thread info.
  */
-void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
 {
 	unsigned long old;
 	int faulted;
@@ -453,7 +454,8 @@
 		return;
 	}
 
-	if (ftrace_push_return_trace(old, self_addr, &trace.depth) == -EBUSY) {
+	if (ftrace_push_return_trace(old, self_addr, &trace.depth,
+		    frame_pointer) == -EBUSY) {
 		*parent = old;
 		return;
 	}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/head_32.S linux-libre-2.6.31-gnu/arch/x86/kernel/head_32.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/head_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/head_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,6 @@
 #include <asm/segment.h>
 #include <asm/page_types.h>
 #include <asm/pgtable_types.h>
-#include <asm/desc.h>
 #include <asm/cache.h>
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
@@ -262,9 +261,7 @@
  * which will be freed later
  */
 
-#ifndef CONFIG_HOTPLUG_CPU
-.section .init.text,"ax",@progbits
-#endif
+__CPUINIT
 
 #ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
@@ -603,18 +600,11 @@
 #endif
 	iret
 
-.section .cpuinit.data,"wa"
+	__REFDATA
 .align 4
 ENTRY(initial_code)
 	.long i386_start_kernel
 
-.section .text
-/*
- * Real beginning of normal "text" segment
- */
-ENTRY(stext)
-ENTRY(_stext)
-
 /*
  * BSS section
  */
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/head_64.S linux-libre-2.6.31-gnu/arch/x86/kernel/head_64.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/head_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/head_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 #include <linux/linkage.h>
 #include <linux/threads.h>
 #include <linux/init.h>
-#include <asm/desc.h>
 #include <asm/segment.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/hpet.c linux-libre-2.6.31-gnu/arch/x86/kernel/hpet.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/hpet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/hpet.c	2009-09-09 18:13:59.000000000 -0400
@@ -510,7 +510,8 @@
 {
 
 	if (request_irq(dev->irq, hpet_interrupt_handler,
-			IRQF_DISABLED|IRQF_NOBALANCING, dev->name, dev))
+			IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+			dev->name, dev))
 		return -1;
 
 	disable_irq(dev->irq);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/i8253.c linux-libre-2.6.31-gnu/arch/x86/kernel/i8253.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/i8253.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/i8253.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,6 +7,7 @@
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
+#include <linux/timex.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/init_task.c linux-libre-2.6.31-gnu/arch/x86/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
  * Initial thread structure.
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/irq.c linux-libre-2.6.31-gnu/arch/x86/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,8 @@
 #include <asm/io_apic.h>
 #include <asm/irq.h>
 #include <asm/idle.h>
+#include <asm/mce.h>
+#include <asm/hw_irq.h>
 
 atomic_t irq_err_count;
 
@@ -24,9 +26,9 @@
  */
 void ack_bad_irq(unsigned int irq)
 {
-	printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
+	if (printk_ratelimit())
+		pr_err("unexpected IRQ trap at vector %02x\n", irq);
 
-#ifdef CONFIG_X86_LOCAL_APIC
 	/*
 	 * Currently unexpected vectors happen only on SMP and APIC.
 	 * We _must_ ack these because every local APIC has only N
@@ -36,9 +38,7 @@
 	 * completely.
 	 * But only ack when the APIC is enabled -AK
 	 */
-	if (cpu_has_apic)
-		ack_APIC_irq();
-#endif
+	ack_APIC_irq();
 }
 
 #define irq_stats(x)		(&per_cpu(irq_stat, x))
@@ -63,6 +63,14 @@
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
 	seq_printf(p, "  Spurious interrupts\n");
+	seq_printf(p, "%*s: ", prec, "CNT");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
+	seq_printf(p, "  Performance counter interrupts\n");
+	seq_printf(p, "%*s: ", prec, "PND");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
+	seq_printf(p, "  Performance pending work\n");
 #endif
 	if (generic_interrupt_extension) {
 		seq_printf(p, "%*s: ", prec, "PLT");
@@ -89,13 +97,23 @@
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
 	seq_printf(p, "  Thermal event interrupts\n");
-# ifdef CONFIG_X86_64
+# ifdef CONFIG_X86_MCE_THRESHOLD
 	seq_printf(p, "%*s: ", prec, "THR");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
 	seq_printf(p, "  Threshold APIC interrupts\n");
 # endif
 #endif
+#ifdef CONFIG_X86_NEW_MCE
+	seq_printf(p, "%*s: ", prec, "MCE");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(mce_exception_count, j));
+	seq_printf(p, "  Machine check exceptions\n");
+	seq_printf(p, "%*s: ", prec, "MCP");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
+	seq_printf(p, "  Machine check polls\n");
+#endif
 	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
 #if defined(CONFIG_X86_IO_APIC)
 	seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
@@ -166,6 +184,8 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 	sum += irq_stats(cpu)->apic_timer_irqs;
 	sum += irq_stats(cpu)->irq_spurious_count;
+	sum += irq_stats(cpu)->apic_perf_irqs;
+	sum += irq_stats(cpu)->apic_pending_irqs;
 #endif
 	if (generic_interrupt_extension)
 		sum += irq_stats(cpu)->generic_irqs;
@@ -176,9 +196,13 @@
 #endif
 #ifdef CONFIG_X86_MCE
 	sum += irq_stats(cpu)->irq_thermal_count;
-# ifdef CONFIG_X86_64
+# ifdef CONFIG_X86_MCE_THRESHOLD
 	sum += irq_stats(cpu)->irq_threshold_count;
+# endif
 #endif
+#ifdef CONFIG_X86_NEW_MCE
+	sum += per_cpu(mce_exception_count, cpu);
+	sum += per_cpu(mce_poll_count, cpu);
 #endif
 	return sum;
 }
@@ -213,14 +237,11 @@
 	irq = __get_cpu_var(vector_irq)[vector];
 
 	if (!handle_irq(irq, regs)) {
-#ifdef CONFIG_X86_64
-		if (!disable_apic)
-			ack_APIC_irq();
-#endif
+		ack_APIC_irq();
 
 		if (printk_ratelimit())
-			printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
-			       __func__, smp_processor_id(), vector, irq);
+			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
+				__func__, smp_processor_id(), vector, irq);
 	}
 
 	irq_exit();
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/irqinit_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/irqinit_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/irqinit_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/irqinit_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,206 +0,0 @@
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sysdev.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include <asm/atomic.h>
-#include <asm/system.h>
-#include <asm/timer.h>
-#include <asm/pgtable.h>
-#include <asm/desc.h>
-#include <asm/apic.h>
-#include <asm/setup.h>
-#include <asm/i8259.h>
-#include <asm/traps.h>
-
-
-/*
- * Note that on a 486, we don't want to do a SIGFPE on an irq13
- * as the irq is unreliable, and exception 16 works correctly
- * (ie as explained in the intel literature). On a 386, you
- * can't use exception 16 due to bad IBM design, so we have to
- * rely on the less exact irq13.
- *
- * Careful.. Not only is IRQ13 unreliable, but it is also
- * leads to races. IBM designers who came up with it should
- * be shot.
- */
-
-static irqreturn_t math_error_irq(int cpl, void *dev_id)
-{
-	outb(0, 0xF0);
-	if (ignore_fpu_irq || !boot_cpu_data.hard_math)
-		return IRQ_NONE;
-	math_error((void __user *)get_irq_regs()->ip);
-	return IRQ_HANDLED;
-}
-
-/*
- * New motherboards sometimes make IRQ 13 be a PCI interrupt,
- * so allow interrupt sharing.
- */
-static struct irqaction fpu_irq = {
-	.handler = math_error_irq,
-	.name = "fpu",
-};
-
-void __init init_ISA_irqs(void)
-{
-	int i;
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	init_bsp_APIC();
-#endif
-	init_8259A(0);
-
-	/*
-	 * 16 old-style INTA-cycle interrupts:
-	 */
-	for (i = 0; i < NR_IRQS_LEGACY; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-
-		set_irq_chip_and_handler_name(i, &i8259A_chip,
-					      handle_level_irq, "XT");
-	}
-}
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = {
-	.handler = no_action,
-	.name = "cascade",
-};
-
-DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
-	[0 ... IRQ0_VECTOR - 1] = -1,
-	[IRQ0_VECTOR] = 0,
-	[IRQ1_VECTOR] = 1,
-	[IRQ2_VECTOR] = 2,
-	[IRQ3_VECTOR] = 3,
-	[IRQ4_VECTOR] = 4,
-	[IRQ5_VECTOR] = 5,
-	[IRQ6_VECTOR] = 6,
-	[IRQ7_VECTOR] = 7,
-	[IRQ8_VECTOR] = 8,
-	[IRQ9_VECTOR] = 9,
-	[IRQ10_VECTOR] = 10,
-	[IRQ11_VECTOR] = 11,
-	[IRQ12_VECTOR] = 12,
-	[IRQ13_VECTOR] = 13,
-	[IRQ14_VECTOR] = 14,
-	[IRQ15_VECTOR] = 15,
-	[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
-};
-
-int vector_used_by_percpu_irq(unsigned int vector)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu) {
-		if (per_cpu(vector_irq, cpu)[vector] != -1)
-			return 1;
-	}
-
-	return 0;
-}
-
-/* Overridden in paravirt.c */
-void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-
-void __init native_init_IRQ(void)
-{
-	int i;
-
-	/* Execute any quirks before the call gates are initialised: */
-	x86_quirk_pre_intr_init();
-
-	/*
-	 * Cover the whole vector space, no vector can escape
-	 * us. (some of these will be overridden and become
-	 * 'special' SMP interrupts)
-	 */
-	for (i =  FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
-		/* SYSCALL_VECTOR was reserved in trap_init. */
-		if (i != SYSCALL_VECTOR)
-			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
-	}
-
-
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP)
-	/*
-	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
-	 * IPI, driven by wakeup.
-	 */
-	alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
-	/* IPIs for invalidation */
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
-
-	/* IPI for generic function call */
-	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
-	/* IPI for single call function */
-	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
-				 call_function_single_interrupt);
-
-	/* Low priority IPI to cleanup after moving an irq */
-	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
-	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
-	/* self generated IPI for local APIC timer */
-	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
-	/* generic IPI for platform specific use */
-	alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
-
-	/* IPI vectors for APIC spurious and error interrupts */
-	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-#endif
-
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
-	/* thermal monitor LVT interrupt */
-	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-#endif
-
-	if (!acpi_ioapic)
-		setup_irq(2, &irq2);
-
-	/*
-	 * Call quirks after call gates are initialised (usually add in
-	 * the architecture specific gates):
-	 */
-	x86_quirk_intr_init();
-
-	/*
-	 * External FPU? Set up irq13 if so, for
-	 * original braindamaged IBM FERR coupling.
-	 */
-	if (boot_cpu_data.hard_math && !cpu_has_fpu)
-		setup_irq(FPU_IRQ, &fpu_irq);
-
-	irq_ctx_init(smp_processor_id());
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/irqinit_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/irqinit_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/irqinit_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/irqinit_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,177 +0,0 @@
-#include <linux/linkage.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sysdev.h>
-#include <linux/bitops.h>
-#include <linux/acpi.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include <asm/atomic.h>
-#include <asm/system.h>
-#include <asm/hw_irq.h>
-#include <asm/pgtable.h>
-#include <asm/desc.h>
-#include <asm/apic.h>
-#include <asm/i8259.h>
-
-/*
- * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x30-0x3f)
- */
-
-/*
- * The IO-APIC gives us many more interrupt sources. Most of these
- * are unused but an SMP system is supposed to have enough memory ...
- * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
- * across the spectrum, so we really want to be prepared to get all
- * of these. Plus, more powerful systems might have more than 64
- * IO-APIC registers.
- *
- * (these are usually mapped into the 0x30-0xff vector range)
- */
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-
-static struct irqaction irq2 = {
-	.handler = no_action,
-	.name = "cascade",
-};
-DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
-	[0 ... IRQ0_VECTOR - 1] = -1,
-	[IRQ0_VECTOR] = 0,
-	[IRQ1_VECTOR] = 1,
-	[IRQ2_VECTOR] = 2,
-	[IRQ3_VECTOR] = 3,
-	[IRQ4_VECTOR] = 4,
-	[IRQ5_VECTOR] = 5,
-	[IRQ6_VECTOR] = 6,
-	[IRQ7_VECTOR] = 7,
-	[IRQ8_VECTOR] = 8,
-	[IRQ9_VECTOR] = 9,
-	[IRQ10_VECTOR] = 10,
-	[IRQ11_VECTOR] = 11,
-	[IRQ12_VECTOR] = 12,
-	[IRQ13_VECTOR] = 13,
-	[IRQ14_VECTOR] = 14,
-	[IRQ15_VECTOR] = 15,
-	[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
-};
-
-int vector_used_by_percpu_irq(unsigned int vector)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu) {
-		if (per_cpu(vector_irq, cpu)[vector] != -1)
-			return 1;
-	}
-
-	return 0;
-}
-
-static void __init init_ISA_irqs(void)
-{
-	int i;
-
-	init_bsp_APIC();
-	init_8259A(0);
-
-	for (i = 0; i < NR_IRQS_LEGACY; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-
-		/*
-		 * 16 old-style INTA-cycle interrupts:
-		 */
-		set_irq_chip_and_handler_name(i, &i8259A_chip,
-						      handle_level_irq, "XT");
-	}
-}
-
-void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
-
-static void __init smp_intr_init(void)
-{
-#ifdef CONFIG_SMP
-	/*
-	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
-	 * IPI, driven by wakeup.
-	 */
-	alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
-	/* IPIs for invalidation */
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
-
-	/* IPI for generic function call */
-	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
-	/* IPI for generic single function call */
-	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
-			call_function_single_interrupt);
-
-	/* Low priority IPI to cleanup after moving an irq */
-	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
-	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
-#endif
-}
-
-static void __init apic_intr_init(void)
-{
-	smp_intr_init();
-
-	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-	alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
-
-	/* self generated IPI for local APIC timer */
-	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
-	/* generic IPI for platform specific use */
-	alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
-
-	/* IPI vectors for APIC spurious and error interrupts */
-	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
-	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-}
-
-void __init native_init_IRQ(void)
-{
-	int i;
-
-	init_ISA_irqs();
-	/*
-	 * Cover the whole vector space, no vector can escape
-	 * us. (some of these will be overridden and become
-	 * 'special' SMP interrupts)
-	 */
-	for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
-		int vector = FIRST_EXTERNAL_VECTOR + i;
-		if (vector != IA32_SYSCALL_VECTOR)
-			set_intr_gate(vector, interrupt[i]);
-	}
-
-	apic_intr_init();
-
-	if (!acpi_ioapic)
-		setup_irq(2, &irq2);
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/irqinit.c linux-libre-2.6.31-gnu/arch/x86/kernel/irqinit.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/irqinit.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/irqinit.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,275 @@
+#include <linux/linkage.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/kprobes.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sysdev.h>
+#include <linux/bitops.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/timer.h>
+#include <asm/hw_irq.h>
+#include <asm/pgtable.h>
+#include <asm/desc.h>
+#include <asm/apic.h>
+#include <asm/setup.h>
+#include <asm/i8259.h>
+#include <asm/traps.h>
+
+/*
+ * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
+ * (these are usually mapped to vectors 0x30-0x3f)
+ */
+
+/*
+ * The IO-APIC gives us many more interrupt sources. Most of these
+ * are unused but an SMP system is supposed to have enough memory ...
+ * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
+ * across the spectrum, so we really want to be prepared to get all
+ * of these. Plus, more powerful systems might have more than 64
+ * IO-APIC registers.
+ *
+ * (these are usually mapped into the 0x30-0xff vector range)
+ */
+
+#ifdef CONFIG_X86_32
+/*
+ * Note that on a 486, we don't want to do a SIGFPE on an irq13
+ * as the irq is unreliable, and exception 16 works correctly
+ * (ie as explained in the intel literature). On a 386, you
+ * can't use exception 16 due to bad IBM design, so we have to
+ * rely on the less exact irq13.
+ *
+ * Careful.. Not only is IRQ13 unreliable, but it is also
+ * leads to races. IBM designers who came up with it should
+ * be shot.
+ */
+
+static irqreturn_t math_error_irq(int cpl, void *dev_id)
+{
+	outb(0, 0xF0);
+	if (ignore_fpu_irq || !boot_cpu_data.hard_math)
+		return IRQ_NONE;
+	math_error((void __user *)get_irq_regs()->ip);
+	return IRQ_HANDLED;
+}
+
+/*
+ * New motherboards sometimes make IRQ 13 be a PCI interrupt,
+ * so allow interrupt sharing.
+ */
+static struct irqaction fpu_irq = {
+	.handler = math_error_irq,
+	.name = "fpu",
+};
+#endif
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+	.handler = no_action,
+	.name = "cascade",
+};
+
+DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
+	[0 ... IRQ0_VECTOR - 1] = -1,
+	[IRQ0_VECTOR] = 0,
+	[IRQ1_VECTOR] = 1,
+	[IRQ2_VECTOR] = 2,
+	[IRQ3_VECTOR] = 3,
+	[IRQ4_VECTOR] = 4,
+	[IRQ5_VECTOR] = 5,
+	[IRQ6_VECTOR] = 6,
+	[IRQ7_VECTOR] = 7,
+	[IRQ8_VECTOR] = 8,
+	[IRQ9_VECTOR] = 9,
+	[IRQ10_VECTOR] = 10,
+	[IRQ11_VECTOR] = 11,
+	[IRQ12_VECTOR] = 12,
+	[IRQ13_VECTOR] = 13,
+	[IRQ14_VECTOR] = 14,
+	[IRQ15_VECTOR] = 15,
+	[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
+};
+
+int vector_used_by_percpu_irq(unsigned int vector)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		if (per_cpu(vector_irq, cpu)[vector] != -1)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void __init init_ISA_irqs(void)
+{
+	int i;
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+	init_bsp_APIC();
+#endif
+	init_8259A(0);
+
+	/*
+	 * 16 old-style INTA-cycle interrupts:
+	 */
+	for (i = 0; i < NR_IRQS_LEGACY; i++) {
+		struct irq_desc *desc = irq_to_desc(i);
+
+		desc->status = IRQ_DISABLED;
+		desc->action = NULL;
+		desc->depth = 1;
+
+		set_irq_chip_and_handler_name(i, &i8259A_chip,
+					      handle_level_irq, "XT");
+	}
+}
+
+/* Overridden in paravirt.c */
+void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
+
+static void __init smp_intr_init(void)
+{
+#ifdef CONFIG_SMP
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+	/*
+	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+	 * IPI, driven by wakeup.
+	 */
+	alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+
+	/* IPIs for invalidation */
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
+
+	/* IPI for generic function call */
+	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+
+	/* IPI for generic single function call */
+	alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
+			call_function_single_interrupt);
+
+	/* Low priority IPI to cleanup after moving an irq */
+	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
+	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
+
+	/* IPI used for rebooting/stopping */
+	alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt);
+#endif
+#endif /* CONFIG_SMP */
+}
+
+static void __init apic_intr_init(void)
+{
+	smp_intr_init();
+
+#ifdef CONFIG_X86_THERMAL_VECTOR
+	alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+#endif
+#ifdef CONFIG_X86_MCE_THRESHOLD
+	alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
+#endif
+#if defined(CONFIG_X86_NEW_MCE) && defined(CONFIG_X86_LOCAL_APIC)
+	alloc_intr_gate(MCE_SELF_VECTOR, mce_self_interrupt);
+#endif
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+	/* self generated IPI for local APIC timer */
+	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+
+	/* generic IPI for platform specific use */
+	alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
+
+	/* IPI vectors for APIC spurious and error interrupts */
+	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+
+	/* Performance monitoring interrupts: */
+# ifdef CONFIG_PERF_COUNTERS
+	alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
+# endif
+
+#endif
+}
+
+/**
+ * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
+ *
+ * Description:
+ *	Perform any necessary interrupt initialisation prior to setting up
+ *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
+ *	interrupts should be initialised here if the machine emulates a PC
+ *	in any way.
+ **/
+static void __init x86_quirk_pre_intr_init(void)
+{
+#ifdef CONFIG_X86_32
+	if (x86_quirks->arch_pre_intr_init) {
+		if (x86_quirks->arch_pre_intr_init())
+			return;
+	}
+#endif
+	init_ISA_irqs();
+}
+
+void __init native_init_IRQ(void)
+{
+	int i;
+
+	/* Execute any quirks before the call gates are initialised: */
+	x86_quirk_pre_intr_init();
+
+	apic_intr_init();
+
+	/*
+	 * Cover the whole vector space, no vector can escape
+	 * us. (some of these will be overridden and become
+	 * 'special' SMP interrupts)
+	 */
+	for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
+		/* IA32_SYSCALL_VECTOR could be used in trap_init already. */
+		if (!test_bit(i, used_vectors))
+			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
+	}
+
+	if (!acpi_ioapic)
+		setup_irq(2, &irq2);
+
+#ifdef CONFIG_X86_32
+	/*
+	 * Call quirks after call gates are initialised (usually add in
+	 * the architecture specific gates):
+	 */
+	x86_quirk_intr_init();
+
+	/*
+	 * External FPU? Set up irq13 if so, for
+	 * original braindamaged IBM FERR coupling.
+	 */
+	if (boot_cpu_data.hard_math && !cpu_has_fpu)
+		setup_irq(FPU_IRQ, &fpu_irq);
+
+	irq_ctx_init(smp_processor_id());
+#endif
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/kgdb.c linux-libre-2.6.31-gnu/arch/x86/kernel/kgdb.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/kgdb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/kgdb.c	2009-09-09 18:13:59.000000000 -0400
@@ -142,7 +142,7 @@
 	gdb_regs32[GDB_PS]	= *(unsigned long *)(p->thread.sp + 8);
 	gdb_regs32[GDB_CS]	= __KERNEL_CS;
 	gdb_regs32[GDB_SS]	= __KERNEL_DS;
-	gdb_regs[GDB_PC]	= p->thread.ip;
+	gdb_regs[GDB_PC]	= 0;
 	gdb_regs[GDB_R8]	= 0;
 	gdb_regs[GDB_R9]	= 0;
 	gdb_regs[GDB_R10]	= 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/kvm.c linux-libre-2.6.31-gnu/arch/x86/kernel/kvm.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/kvm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/kvm.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/hardirq.h>
+#include <asm/timer.h>
 
 #define MMU_QUEUE_SIZE 1024
 
@@ -195,11 +196,11 @@
 	struct kvm_para_state *state = kvm_para_state();
 
 	mmu_queue_flush(state);
-	paravirt_leave_lazy(paravirt_get_lazy_mode());
+	paravirt_leave_lazy_mmu();
 	state->mode = paravirt_get_lazy_mode();
 }
 
-static void paravirt_ops_setup(void)
+static void __init paravirt_ops_setup(void)
 {
 	pv_info.name = "KVM";
 	pv_info.paravirt_enabled = 1;
@@ -230,6 +231,9 @@
 		pv_mmu_ops.lazy_mode.enter = kvm_enter_lazy_mmu;
 		pv_mmu_ops.lazy_mode.leave = kvm_leave_lazy_mmu;
 	}
+#ifdef CONFIG_X86_IO_APIC
+	no_timer_check = 1;
+#endif
 }
 
 void __init kvm_guest_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/Makefile linux-libre-2.6.31-gnu/arch/x86/kernel/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/kernel/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -24,11 +24,15 @@
 CFLAGS_hpet.o		:= $(nostackp)
 CFLAGS_tsc.o		:= $(nostackp)
 CFLAGS_paravirt.o	:= $(nostackp)
+GCOV_PROFILE_vsyscall_64.o	:= n
+GCOV_PROFILE_hpet.o		:= n
+GCOV_PROFILE_tsc.o		:= n
+GCOV_PROFILE_paravirt.o		:= n
 
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y			+= time_$(BITS).o ioport.o ldt.o dumpstack.o
-obj-y			+= setup.o i8259.o irqinit_$(BITS).o
+obj-y			+= setup.o i8259.o irqinit.o
 obj-$(CONFIG_X86_VISWS)	+= visws_quirks.o
 obj-$(CONFIG_X86_32)	+= probe_roms_32.o
 obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
@@ -44,6 +48,7 @@
 obj-y				+= i387.o xsave.o
 obj-y				+= ptrace.o
 obj-$(CONFIG_X86_DS)		+= ds.o
+obj-$(CONFIG_X86_DS_SELFTEST)		+= ds_selftest.o
 obj-$(CONFIG_X86_32)		+= tls.o
 obj-$(CONFIG_IA32_EMULATION)	+= tls.o
 obj-y				+= step.o
@@ -72,7 +77,7 @@
 obj-$(CONFIG_KEXEC)		+= relocate_kernel_$(BITS).o crash.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump_$(BITS).o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
-obj-$(CONFIG_MODULES)		+= module_$(BITS).o
+obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
 obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault_32.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/mfgpt_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/mfgpt_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/mfgpt_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/mfgpt_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -347,7 +347,7 @@
 
 static struct irqaction mfgptirq  = {
 	.handler = mfgpt_tick,
-	.flags = IRQF_DISABLED | IRQF_NOBALANCING,
+	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
 	.name = "mfgpt-timer"
 };
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/microcode_amd.c linux-libre-2.6.31-gnu/arch/x86/kernel/microcode_amd.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/microcode_amd.c	2012-03-22 19:10:33.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/microcode_amd.c	2012-03-22 20:07:07.000000000 -0400
@@ -13,25 +13,13 @@
  *  Licensed under the terms of the GNU General Public
  *  License version 2. See file COPYING for details.
  */
-#include <linux/platform_device.h>
-#include <linux/capability.h>
-#include <linux/miscdevice.h>
 #include <linux/firmware.h>
-#include <linux/spinlock.h>
-#include <linux/cpumask.h>
 #include <linux/pci_ids.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/cpu.h>
 #include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
 
 #include <asm/microcode.h>
 #include <asm/processor.h>
@@ -79,9 +67,6 @@
 #define UCODE_CONTAINER_SECTION_HDR	8
 #define UCODE_CONTAINER_HEADER_SIZE	12
 
-/* serialize access to the physical write */
-static DEFINE_SPINLOCK(microcode_update_lock);
-
 static struct equiv_cpu_entry *equiv_cpu_table;
 
 static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
@@ -144,9 +129,8 @@
 	return 1;
 }
 
-static void apply_microcode_amd(int cpu)
+static int apply_microcode_amd(int cpu)
 {
-	unsigned long flags;
 	u32 rev, dummy;
 	int cpu_num = raw_smp_processor_id();
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
@@ -156,25 +140,25 @@
 	BUG_ON(cpu_num != cpu);
 
 	if (mc_amd == NULL)
-		return;
+		return 0;
 
-	spin_lock_irqsave(&microcode_update_lock, flags);
 	wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
 	/* get patch id after patching */
 	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
-	spin_unlock_irqrestore(&microcode_update_lock, flags);
 
 	/* check current patch id and patch's id for match */
 	if (rev != mc_amd->hdr.patch_id) {
 		printk(KERN_ERR "microcode: CPU%d: update failed "
 		       "(for patch_level=0x%x)\n", cpu, mc_amd->hdr.patch_id);
-		return;
+		return -1;
 	}
 
 	printk(KERN_INFO "microcode: CPU%d: updated (new patch_level=0x%x)\n",
 	       cpu, rev);
 
 	uci->cpu_sig.rev = rev;
+
+	return 0;
 }
 
 static int get_ucode_data(void *to, const u8 *from, size_t n)
@@ -257,13 +241,12 @@
 
 static void free_equiv_cpu_table(void)
 {
-	if (equiv_cpu_table) {
-		vfree(equiv_cpu_table);
-		equiv_cpu_table = NULL;
-	}
+	vfree(equiv_cpu_table);
+	equiv_cpu_table = NULL;
 }
 
-static int generic_load_microcode(int cpu, const u8 *data, size_t size)
+static enum ucode_state
+generic_load_microcode(int cpu, const u8 *data, size_t size)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	const u8 *ucode_ptr = data;
@@ -272,12 +255,13 @@
 	int new_rev = uci->cpu_sig.rev;
 	unsigned int leftover;
 	unsigned long offset;
+	enum ucode_state state = UCODE_OK;
 
 	offset = install_equiv_cpu_table(ucode_ptr);
 	if (!offset) {
 		printk(KERN_ERR "microcode: failed to create "
 		       "equivalent cpu table\n");
-		return -EINVAL;
+		return UCODE_ERROR;
 	}
 
 	ucode_ptr += offset;
@@ -293,8 +277,7 @@
 
 		mc_header = (struct microcode_header_amd *)mc;
 		if (get_matching_microcode(cpu, mc, new_rev)) {
-			if (new_mc)
-				vfree(new_mc);
+			vfree(new_mc);
 			new_rev = mc_header->patch_id;
 			new_mc  = mc;
 		} else
@@ -306,34 +289,32 @@
 
 	if (new_mc) {
 		if (!leftover) {
-			if (uci->mc)
-				vfree(uci->mc);
+			vfree(uci->mc);
 			uci->mc = new_mc;
 			pr_debug("microcode: CPU%d found a matching microcode "
 				 "update with version 0x%x (current=0x%x)\n",
 				 cpu, new_rev, uci->cpu_sig.rev);
-		} else
+		} else {
 			vfree(new_mc);
-	}
+			state = UCODE_ERROR;
+		}
+	} else
+		state = UCODE_NFOUND;
 
 	free_equiv_cpu_table();
 
-	return (int)leftover;
+	return state;
 }
 
-static int request_microcode_fw(int cpu, struct device *device)
+static enum ucode_state request_microcode_fw(int cpu, struct device *device)
 {
 	const char *fw_name = "/*(DEBLOBBED)*/";
 	const struct firmware *firmware;
-	int ret;
-
-	/* We should bind the task to the CPU */
-	BUG_ON(cpu != raw_smp_processor_id());
+	enum ucode_state ret;
 
-	ret = reject_firmware(&firmware, fw_name, device);
-	if (ret) {
+	if (reject_firmware(&firmware, fw_name, device)) {
 		printk(KERN_ERR "microcode: failed to load file %s\n", fw_name);
-		return ret;
+		return UCODE_NFOUND;
 	}
 
 	ret = generic_load_microcode(cpu, firmware->data, firmware->size);
@@ -343,11 +324,12 @@
 	return ret;
 }
 
-static int request_microcode_user(int cpu, const void __user *buf, size_t size)
+static enum ucode_state
+request_microcode_user(int cpu, const void __user *buf, size_t size)
 {
 	printk(KERN_INFO "microcode: AMD microcode update via "
 	       "/dev/cpu/microcode not supported\n");
-	return -1;
+	return UCODE_ERROR;
 }
 
 static void microcode_fini_cpu_amd(int cpu)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/microcode_core.c linux-libre-2.6.31-gnu/arch/x86/kernel/microcode_core.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/microcode_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/microcode_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,27 +71,18 @@
  *		Thanks to Stuart Swales for pointing out this bug.
  */
 #include <linux/platform_device.h>
-#include <linux/capability.h>
 #include <linux/miscdevice.h>
-#include <linux/firmware.h>
+#include <linux/capability.h>
 #include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/cpumask.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 
 #include <asm/microcode.h>
 #include <asm/processor.h>
-#include <asm/msr.h>
 
 MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
@@ -101,36 +92,110 @@
 
 static struct microcode_ops	*microcode_ops;
 
-/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+/*
+ * Synchronization.
+ *
+ * All non cpu-hotplug-callback call sites use:
+ *
+ * - microcode_mutex to synchronize with each other;
+ * - get/put_online_cpus() to synchronize with
+ *   the cpu-hotplug-callback call sites.
+ *
+ * We guarantee that only a single cpu is being
+ * updated at any particular moment of time.
+ */
 static DEFINE_MUTEX(microcode_mutex);
 
 struct ucode_cpu_info		ucode_cpu_info[NR_CPUS];
 EXPORT_SYMBOL_GPL(ucode_cpu_info);
 
+/*
+ * Operations that are run on a target cpu:
+ */
+
+struct cpu_info_ctx {
+	struct cpu_signature	*cpu_sig;
+	int			err;
+};
+
+static void collect_cpu_info_local(void *arg)
+{
+	struct cpu_info_ctx *ctx = arg;
+
+	ctx->err = microcode_ops->collect_cpu_info(smp_processor_id(),
+						   ctx->cpu_sig);
+}
+
+static int collect_cpu_info_on_target(int cpu, struct cpu_signature *cpu_sig)
+{
+	struct cpu_info_ctx ctx = { .cpu_sig = cpu_sig, .err = 0 };
+	int ret;
+
+	ret = smp_call_function_single(cpu, collect_cpu_info_local, &ctx, 1);
+	if (!ret)
+		ret = ctx.err;
+
+	return ret;
+}
+
+static int collect_cpu_info(int cpu)
+{
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	int ret;
+
+	memset(uci, 0, sizeof(*uci));
+
+	ret = collect_cpu_info_on_target(cpu, &uci->cpu_sig);
+	if (!ret)
+		uci->valid = 1;
+
+	return ret;
+}
+
+struct apply_microcode_ctx {
+	int err;
+};
+
+static void apply_microcode_local(void *arg)
+{
+	struct apply_microcode_ctx *ctx = arg;
+
+	ctx->err = microcode_ops->apply_microcode(smp_processor_id());
+}
+
+static int apply_microcode_on_target(int cpu)
+{
+	struct apply_microcode_ctx ctx = { .err = 0 };
+	int ret;
+
+	ret = smp_call_function_single(cpu, apply_microcode_local, &ctx, 1);
+	if (!ret)
+		ret = ctx.err;
+
+	return ret;
+}
+
 #ifdef CONFIG_MICROCODE_OLD_INTERFACE
 static int do_microcode_update(const void __user *buf, size_t size)
 {
-	cpumask_t old;
 	int error = 0;
 	int cpu;
 
-	old = current->cpus_allowed;
-
 	for_each_online_cpu(cpu) {
 		struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+		enum ucode_state ustate;
 
 		if (!uci->valid)
 			continue;
 
-		set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-		error = microcode_ops->request_microcode_user(cpu, buf, size);
-		if (error < 0)
-			goto out;
-		if (!error)
-			microcode_ops->apply_microcode(cpu);
+		ustate = microcode_ops->request_microcode_user(cpu, buf, size);
+		if (ustate == UCODE_ERROR) {
+			error = -1;
+			break;
+		} else if (ustate == UCODE_OK)
+			apply_microcode_on_target(cpu);
 	}
-out:
-	set_cpus_allowed_ptr(current, &old);
+
 	return error;
 }
 
@@ -143,19 +208,17 @@
 static ssize_t microcode_write(struct file *file, const char __user *buf,
 			       size_t len, loff_t *ppos)
 {
-	ssize_t ret;
+	ssize_t ret = -EINVAL;
 
 	if ((len >> PAGE_SHIFT) > num_physpages) {
-		printk(KERN_ERR "microcode: too much data (max %ld pages)\n",
-		       num_physpages);
-		return -EINVAL;
+		pr_err("microcode: too much data (max %ld pages)\n", num_physpages);
+		return ret;
 	}
 
 	get_online_cpus();
 	mutex_lock(&microcode_mutex);
 
-	ret = do_microcode_update(buf, len);
-	if (!ret)
+	if (do_microcode_update(buf, len) == 0)
 		ret = (ssize_t)len;
 
 	mutex_unlock(&microcode_mutex);
@@ -165,15 +228,16 @@
 }
 
 static const struct file_operations microcode_fops = {
-	.owner		= THIS_MODULE,
-	.write		= microcode_write,
-	.open		= microcode_open,
+	.owner			= THIS_MODULE,
+	.write			= microcode_write,
+	.open			= microcode_open,
 };
 
 static struct miscdevice microcode_dev = {
-	.minor		= MICROCODE_MINOR,
-	.name		= "microcode",
-	.fops		= &microcode_fops,
+	.minor			= MICROCODE_MINOR,
+	.name			= "microcode",
+	.devnode		= "cpu/microcode",
+	.fops			= &microcode_fops,
 };
 
 static int __init microcode_dev_init(void)
@@ -182,9 +246,7 @@
 
 	error = misc_register(&microcode_dev);
 	if (error) {
-		printk(KERN_ERR
-			"microcode: can't misc_register on minor=%d\n",
-			MICROCODE_MINOR);
+		pr_err("microcode: can't misc_register on minor=%d\n", MICROCODE_MINOR);
 		return error;
 	}
 
@@ -205,42 +267,51 @@
 /* fake device for request_firmware */
 static struct platform_device	*microcode_pdev;
 
-static long reload_for_cpu(void *unused)
+static int reload_for_cpu(int cpu)
 {
-	struct ucode_cpu_info *uci = ucode_cpu_info + smp_processor_id();
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	int err = 0;
 
 	mutex_lock(&microcode_mutex);
 	if (uci->valid) {
-		err = microcode_ops->request_microcode_fw(smp_processor_id(),
-							  &microcode_pdev->dev);
-		if (!err)
-			microcode_ops->apply_microcode(smp_processor_id());
+		enum ucode_state ustate;
+
+		ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev);
+		if (ustate == UCODE_OK)
+			apply_microcode_on_target(cpu);
+		else
+			if (ustate == UCODE_ERROR)
+				err = -EINVAL;
 	}
 	mutex_unlock(&microcode_mutex);
+
 	return err;
 }
 
 static ssize_t reload_store(struct sys_device *dev,
 			    struct sysdev_attribute *attr,
-			    const char *buf, size_t sz)
+			    const char *buf, size_t size)
 {
-	char *end;
-	unsigned long val = simple_strtoul(buf, &end, 0);
-	int err = 0;
+	unsigned long val;
 	int cpu = dev->id;
+	int ret = 0;
+	char *end;
 
+	val = simple_strtoul(buf, &end, 0);
 	if (end == buf)
 		return -EINVAL;
+
 	if (val == 1) {
 		get_online_cpus();
 		if (cpu_online(cpu))
-			err = work_on_cpu(cpu, reload_for_cpu, NULL);
+			ret = reload_for_cpu(cpu);
 		put_online_cpus();
 	}
-	if (err)
-		return err;
-	return sz;
+
+	if (!ret)
+		ret = size;
+
+	return ret;
 }
 
 static ssize_t version_show(struct sys_device *dev,
@@ -271,11 +342,11 @@
 };
 
 static struct attribute_group mc_attr_group = {
-	.attrs		= mc_default_attrs,
-	.name		= "microcode",
+	.attrs			= mc_default_attrs,
+	.name			= "microcode",
 };
 
-static void __microcode_fini_cpu(int cpu)
+static void microcode_fini_cpu(int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
@@ -283,103 +354,68 @@
 	uci->valid = 0;
 }
 
-static void microcode_fini_cpu(int cpu)
-{
-	mutex_lock(&microcode_mutex);
-	__microcode_fini_cpu(cpu);
-	mutex_unlock(&microcode_mutex);
-}
-
-static void collect_cpu_info(int cpu)
+static enum ucode_state microcode_resume_cpu(int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
-	memset(uci, 0, sizeof(*uci));
-	if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig))
-		uci->valid = 1;
+	if (!uci->mc)
+		return UCODE_NFOUND;
+
+	pr_debug("microcode: CPU%d updated upon resume\n", cpu);
+	apply_microcode_on_target(cpu);
+
+	return UCODE_OK;
 }
 
-static int microcode_resume_cpu(int cpu)
+static enum ucode_state microcode_init_cpu(int cpu)
 {
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	struct cpu_signature nsig;
+	enum ucode_state ustate;
 
-	pr_debug("microcode: CPU%d resumed\n", cpu);
+	if (collect_cpu_info(cpu))
+		return UCODE_ERROR;
 
-	if (!uci->mc)
-		return 1;
+	/* --dimm. Trigger a delayed update? */
+	if (system_state != SYSTEM_RUNNING)
+		return UCODE_NFOUND;
 
-	/*
-	 * Let's verify that the 'cached' ucode does belong
-	 * to this cpu (a bit of paranoia):
-	 */
-	if (microcode_ops->collect_cpu_info(cpu, &nsig)) {
-		__microcode_fini_cpu(cpu);
-		printk(KERN_ERR "failed to collect_cpu_info for resuming cpu #%d\n",
-				cpu);
-		return -1;
-	}
+	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev);
 
-	if ((nsig.sig != uci->cpu_sig.sig) || (nsig.pf != uci->cpu_sig.pf)) {
-		__microcode_fini_cpu(cpu);
-		printk(KERN_ERR "cached ucode doesn't match the resuming cpu #%d\n",
-				cpu);
-		/* Should we look for a new ucode here? */
-		return 1;
+	if (ustate == UCODE_OK) {
+		pr_debug("microcode: CPU%d updated upon init\n", cpu);
+		apply_microcode_on_target(cpu);
 	}
 
-	return 0;
+	return ustate;
 }
 
-static long microcode_update_cpu(void *unused)
+static enum ucode_state microcode_update_cpu(int cpu)
 {
-	struct ucode_cpu_info *uci = ucode_cpu_info + smp_processor_id();
-	int err = 0;
-
-	/*
-	 * Check if the system resume is in progress (uci->valid != NULL),
-	 * otherwise just request a firmware:
-	 */
-	if (uci->valid) {
-		err = microcode_resume_cpu(smp_processor_id());
-	} else {
-		collect_cpu_info(smp_processor_id());
-		if (uci->valid && system_state == SYSTEM_RUNNING)
-			err = microcode_ops->request_microcode_fw(
-					smp_processor_id(),
-					&microcode_pdev->dev);
-	}
-	if (!err)
-		microcode_ops->apply_microcode(smp_processor_id());
-	return err;
-}
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	enum ucode_state ustate;
 
-static int microcode_init_cpu(int cpu)
-{
-	int err;
-	mutex_lock(&microcode_mutex);
-	err = work_on_cpu(cpu, microcode_update_cpu, NULL);
-	mutex_unlock(&microcode_mutex);
+	if (uci->valid)
+		ustate = microcode_resume_cpu(cpu);
+	else
+		ustate = microcode_init_cpu(cpu);
 
-	return err;
+	return ustate;
 }
 
 static int mc_sysdev_add(struct sys_device *sys_dev)
 {
 	int err, cpu = sys_dev->id;
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
 	if (!cpu_online(cpu))
 		return 0;
 
 	pr_debug("microcode: CPU%d added\n", cpu);
-	memset(uci, 0, sizeof(*uci));
 
 	err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
 	if (err)
 		return err;
 
-	err = microcode_init_cpu(cpu);
+	if (microcode_init_cpu(cpu) == UCODE_ERROR)
+		err = -EINVAL;
 
 	return err;
 }
@@ -400,19 +436,30 @@
 static int mc_sysdev_resume(struct sys_device *dev)
 {
 	int cpu = dev->id;
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
 	if (!cpu_online(cpu))
 		return 0;
 
-	/* only CPU 0 will apply ucode here */
-	microcode_update_cpu(NULL);
+	/*
+	 * All non-bootup cpus are still disabled,
+	 * so only CPU 0 will apply ucode here.
+	 *
+	 * Moreover, there can be no concurrent
+	 * updates from any other places at this point.
+	 */
+	WARN_ON(cpu != 0);
+
+	if (uci->valid && uci->mc)
+		microcode_ops->apply_microcode(cpu);
+
 	return 0;
 }
 
 static struct sysdev_driver mc_sysdev_driver = {
-	.add		= mc_sysdev_add,
-	.remove		= mc_sysdev_remove,
-	.resume		= mc_sysdev_resume,
+	.add			= mc_sysdev_add,
+	.remove			= mc_sysdev_remove,
+	.resume			= mc_sysdev_resume,
 };
 
 static __cpuinit int
@@ -425,15 +472,12 @@
 	switch (action) {
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
-		if (microcode_init_cpu(cpu))
-			printk(KERN_ERR "microcode: failed to init CPU%d\n",
-			       cpu);
+		microcode_update_cpu(cpu);
 	case CPU_DOWN_FAILED:
 	case CPU_DOWN_FAILED_FROZEN:
 		pr_debug("microcode: CPU%d added\n", cpu);
 		if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
-			printk(KERN_ERR "microcode: Failed to create the sysfs "
-				"group for CPU%d\n", cpu);
+			pr_err("microcode: Failed to create group for CPU%d\n", cpu);
 		break;
 	case CPU_DOWN_PREPARE:
 	case CPU_DOWN_PREPARE_FROZEN:
@@ -465,13 +509,10 @@
 		microcode_ops = init_amd_microcode();
 
 	if (!microcode_ops) {
-		printk(KERN_ERR "microcode: no support for this CPU vendor\n");
+		pr_err("microcode: no support for this CPU vendor\n");
 		return -ENODEV;
 	}
 
-	error = microcode_dev_init();
-	if (error)
-		return error;
 	microcode_pdev = platform_device_register_simple("microcode", -1,
 							 NULL, 0);
 	if (IS_ERR(microcode_pdev)) {
@@ -480,23 +521,31 @@
 	}
 
 	get_online_cpus();
+	mutex_lock(&microcode_mutex);
+
 	error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
+
+	mutex_unlock(&microcode_mutex);
 	put_online_cpus();
+
 	if (error) {
-		microcode_dev_exit();
 		platform_device_unregister(microcode_pdev);
 		return error;
 	}
 
+	error = microcode_dev_init();
+	if (error)
+		return error;
+
 	register_hotcpu_notifier(&mc_cpu_notifier);
 
-	printk(KERN_INFO
-	       "Microcode Update Driver: v" MICROCODE_VERSION
+	pr_info("Microcode Update Driver: v" MICROCODE_VERSION
 	       " <tigran@aivazian.fsnet.co.uk>,"
 	       " Peter Oruba\n");
 
 	return 0;
 }
+module_init(microcode_init);
 
 static void __exit microcode_exit(void)
 {
@@ -505,16 +554,17 @@
 	unregister_hotcpu_notifier(&mc_cpu_notifier);
 
 	get_online_cpus();
+	mutex_lock(&microcode_mutex);
+
 	sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
+
+	mutex_unlock(&microcode_mutex);
 	put_online_cpus();
 
 	platform_device_unregister(microcode_pdev);
 
 	microcode_ops = NULL;
 
-	printk(KERN_INFO
-	       "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
+	pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
 }
-
-module_init(microcode_init);
 module_exit(microcode_exit);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/microcode_intel.c linux-libre-2.6.31-gnu/arch/x86/kernel/microcode_intel.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/microcode_intel.c	2012-03-22 19:10:36.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/microcode_intel.c	2012-03-22 20:07:09.000000000 -0400
@@ -70,24 +70,11 @@
  *		Fix sigmatch() macro to handle old CPUs with pf == 0.
  *		Thanks to Stuart Swales for pointing out this bug.
  */
-#include <linux/platform_device.h>
-#include <linux/capability.h>
-#include <linux/miscdevice.h>
 #include <linux/firmware.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/cpumask.h>
 #include <linux/uaccess.h>
-#include <linux/vmalloc.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/cpu.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
+#include <linux/vmalloc.h>
 
 #include <asm/microcode.h>
 #include <asm/processor.h>
@@ -150,13 +137,9 @@
 
 #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
 
-/* serialize access to the physical write to MSR 0x79 */
-static DEFINE_SPINLOCK(microcode_update_lock);
-
 static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
-	unsigned long flags;
 	unsigned int val[2];
 
 	memset(csig, 0, sizeof(*csig));
@@ -176,18 +159,14 @@
 		csig->pf = 1 << ((val[1] >> 18) & 7);
 	}
 
-	/* serialize access to the physical write to MSR 0x79 */
-	spin_lock_irqsave(&microcode_update_lock, flags);
-
 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 	/* see notes above for revision 1.07.  Apparent chip bug */
 	sync_core();
 	/* get the current revision from MSR 0x8B */
 	rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
-	spin_unlock_irqrestore(&microcode_update_lock, flags);
 
-	pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
-			csig->sig, csig->pf, csig->rev);
+	printk(KERN_INFO "microcode: CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n",
+			cpu_num, csig->sig, csig->pf, csig->rev);
 
 	return 0;
 }
@@ -318,11 +297,10 @@
 	return 0;
 }
 
-static void apply_microcode(int cpu)
+static int apply_microcode(int cpu)
 {
 	struct microcode_intel *mc_intel;
 	struct ucode_cpu_info *uci;
-	unsigned long flags;
 	unsigned int val[2];
 	int cpu_num;
 
@@ -334,10 +312,7 @@
 	BUG_ON(cpu_num != cpu);
 
 	if (mc_intel == NULL)
-		return;
-
-	/* serialize access to the physical write to MSR 0x79 */
-	spin_lock_irqsave(&microcode_update_lock, flags);
+		return 0;
 
 	/* write microcode via MSR 0x79 */
 	wrmsr(MSR_IA32_UCODE_WRITE,
@@ -351,30 +326,32 @@
 	/* get the current revision from MSR 0x8B */
 	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 
-	spin_unlock_irqrestore(&microcode_update_lock, flags);
 	if (val[1] != mc_intel->hdr.rev) {
-		printk(KERN_ERR "microcode: CPU%d update from revision "
-				"0x%x to 0x%x failed\n",
-			cpu_num, uci->cpu_sig.rev, val[1]);
-		return;
+		printk(KERN_ERR "microcode: CPU%d update "
+				"to revision 0x%x failed\n",
+			cpu_num, mc_intel->hdr.rev);
+		return -1;
 	}
-	printk(KERN_INFO "microcode: CPU%d updated from revision "
-			 "0x%x to 0x%x, date = %04x-%02x-%02x \n",
-		cpu_num, uci->cpu_sig.rev, val[1],
+	printk(KERN_INFO "microcode: CPU%d updated to revision "
+			 "0x%x, date = %04x-%02x-%02x \n",
+		cpu_num, val[1],
 		mc_intel->hdr.date & 0xffff,
 		mc_intel->hdr.date >> 24,
 		(mc_intel->hdr.date >> 16) & 0xff);
 
 	uci->cpu_sig.rev = val[1];
+
+	return 0;
 }
 
-static int generic_load_microcode(int cpu, void *data, size_t size,
-		int (*get_ucode_data)(void *, const void *, size_t))
+static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
+				int (*get_ucode_data)(void *, const void *, size_t))
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	u8 *ucode_ptr = data, *new_mc = NULL, *mc;
 	int new_rev = uci->cpu_sig.rev;
 	unsigned int leftover = size;
+	enum ucode_state state = UCODE_OK;
 
 	while (leftover) {
 		struct microcode_header_intel mc_header;
@@ -412,11 +389,15 @@
 		leftover  -= mc_size;
 	}
 
-	if (!new_mc)
+	if (leftover) {
+		if (new_mc)
+			vfree(new_mc);
+		state = UCODE_ERROR;
 		goto out;
+	}
 
-	if (leftover) {
-		vfree(new_mc);
+	if (!new_mc) {
+		state = UCODE_NFOUND;
 		goto out;
 	}
 
@@ -427,9 +408,8 @@
 	pr_debug("microcode: CPU%d found a matching microcode update with"
 		 " version 0x%x (current=0x%x)\n",
 			cpu, new_rev, uci->cpu_sig.rev);
-
- out:
-	return (int)leftover;
+out:
+	return state;
 }
 
 static int get_ucode_fw(void *to, const void *from, size_t n)
@@ -438,21 +418,19 @@
 	return 0;
 }
 
-static int request_microcode_fw(int cpu, struct device *device)
+static enum ucode_state request_microcode_fw(int cpu, struct device *device)
 {
 	char name[30];
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	const struct firmware *firmware;
-	int ret;
+	enum ucode_state ret;
 
-	/* We should bind the task to the CPU */
-	BUG_ON(cpu != raw_smp_processor_id());
 	sprintf(name, "/*(DEBLOBBED)*/",
 		c->x86, c->x86_model, c->x86_mask);
-	ret = reject_firmware(&firmware, name, device);
-	if (ret) {
+
+	if (reject_firmware(&firmware, name, device)) {
 		pr_debug("microcode: data file %s load failed\n", name);
-		return ret;
+		return UCODE_NFOUND;
 	}
 
 	ret = generic_load_microcode(cpu, (void *)firmware->data,
@@ -468,11 +446,9 @@
 	return copy_from_user(to, from, n);
 }
 
-static int request_microcode_user(int cpu, const void __user *buf, size_t size)
+static enum ucode_state
+request_microcode_user(int cpu, const void __user *buf, size_t size)
 {
-	/* We should bind the task to the CPU */
-	BUG_ON(cpu != raw_smp_processor_id());
-
 	return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/module_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/module_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/module_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/module_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,152 +0,0 @@
-/*  Kernel module help for i386.
-    Copyright (C) 2001 Rusty Russell.
-
-    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/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/bug.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc_exec(size);
-}
-
-
-/* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-	   table entries. */
-}
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	unsigned int i;
-	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-
-	DEBUGP("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to.  Note that all
-		   undefined symbols have been resolved.  */
-		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
-			+ ELF32_R_SYM(rel[i].r_info);
-
-		switch (ELF32_R_TYPE(rel[i].r_info)) {
-		case R_386_32:
-			/* We add the value into the location given */
-			*location += sym->st_value;
-			break;
-		case R_386_PC32:
-			/* Add the value, subtract its postition */
-			*location += sym->st_value - (uint32_t)location;
-			break;
-		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-			       me->name, ELF32_R_TYPE(rel[i].r_info));
-			return -ENOEXEC;
-		}
-	}
-	return 0;
-}
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
-		*para = NULL;
-	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
-
-	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
-		if (!strcmp(".text", secstrings + s->sh_name))
-			text = s;
-		if (!strcmp(".altinstructions", secstrings + s->sh_name))
-			alt = s;
-		if (!strcmp(".smp_locks", secstrings + s->sh_name))
-			locks = s;
-		if (!strcmp(".parainstructions", secstrings + s->sh_name))
-			para = s;
-	}
-
-	if (alt) {
-		/* patch .altinstructions */
-		void *aseg = (void *)alt->sh_addr;
-		apply_alternatives(aseg, aseg + alt->sh_size);
-	}
-	if (locks && text) {
-		void *lseg = (void *)locks->sh_addr;
-		void *tseg = (void *)text->sh_addr;
-		alternatives_smp_module_add(me, me->name,
-					    lseg, lseg + locks->sh_size,
-					    tseg, tseg + text->sh_size);
-	}
-
-	if (para) {
-		void *pseg = (void *)para->sh_addr;
-		apply_paravirt(pseg, pseg + para->sh_size);
-	}
-
-	return module_bug_finalize(hdr, sechdrs, me);
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-	alternatives_smp_module_del(mod);
-	module_bug_cleanup(mod);
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/module_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/module_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/module_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/module_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,194 +0,0 @@
-/*  Kernel module help for x86-64
-    Copyright (C) 2001 Rusty Russell.
-    Copyright (C) 2002,2003 Andi Kleen, SuSE Labs.
-
-    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/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/bug.h>
-
-#include <asm/system.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-#define DEBUGP(fmt...)
-
-#ifndef CONFIG_UML
-void module_free(struct module *mod, void *module_region)
-{
-	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-	   table entries. */
-}
-
-void *module_alloc(unsigned long size)
-{
-	struct vm_struct *area;
-
-	if (!size)
-		return NULL;
-	size = PAGE_ALIGN(size);
-	if (size > MODULES_LEN)
-		return NULL;
-
-	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
-	if (!area)
-		return NULL;
-
-	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
-}
-#endif
-
-/* We don't need anything special. */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
-			      Elf_Shdr *sechdrs,
-			      char *secstrings,
-			      struct module *mod)
-{
-	return 0;
-}
-
-int apply_relocate_add(Elf64_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	unsigned int i;
-	Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf64_Sym *sym;
-	void *loc;
-	u64 val;
-
-	DEBUGP("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-
-		/* This is the symbol it is referring to.  Note that all
-		   undefined symbols have been resolved.  */
-		sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
-			+ ELF64_R_SYM(rel[i].r_info);
-
-		DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n",
-			(int)ELF64_R_TYPE(rel[i].r_info),
-			sym->st_value, rel[i].r_addend, (u64)loc);
-
-		val = sym->st_value + rel[i].r_addend;
-
-		switch (ELF64_R_TYPE(rel[i].r_info)) {
-		case R_X86_64_NONE:
-			break;
-		case R_X86_64_64:
-			*(u64 *)loc = val;
-			break;
-		case R_X86_64_32:
-			*(u32 *)loc = val;
-			if (val != *(u32 *)loc)
-				goto overflow;
-			break;
-		case R_X86_64_32S:
-			*(s32 *)loc = val;
-			if ((s64)val != *(s32 *)loc)
-				goto overflow;
-			break;
-		case R_X86_64_PC32:
-			val -= (u64)loc;
-			*(u32 *)loc = val;
-#if 0
-			if ((s64)val != *(s32 *)loc)
-				goto overflow;
-#endif
-			break;
-		default:
-			printk(KERN_ERR "module %s: Unknown rela relocation: %llu\n",
-			       me->name, ELF64_R_TYPE(rel[i].r_info));
-			return -ENOEXEC;
-		}
-	}
-	return 0;
-
-overflow:
-	printk(KERN_ERR "overflow in relocation type %d val %Lx\n",
-	       (int)ELF64_R_TYPE(rel[i].r_info), val);
-	printk(KERN_ERR "`%s' likely not compiled with -mcmodel=kernel\n",
-	       me->name);
-	return -ENOEXEC;
-}
-
-int apply_relocate(Elf_Shdr *sechdrs,
-		   const char *strtab,
-		   unsigned int symindex,
-		   unsigned int relsec,
-		   struct module *me)
-{
-	printk(KERN_ERR "non add relocation not supported\n");
-	return -ENOSYS;
-}
-
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
-		*para = NULL;
-	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
-
-	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
-		if (!strcmp(".text", secstrings + s->sh_name))
-			text = s;
-		if (!strcmp(".altinstructions", secstrings + s->sh_name))
-			alt = s;
-		if (!strcmp(".smp_locks", secstrings + s->sh_name))
-			locks = s;
-		if (!strcmp(".parainstructions", secstrings + s->sh_name))
-			para = s;
-	}
-
-	if (alt) {
-		/* patch .altinstructions */
-		void *aseg = (void *)alt->sh_addr;
-		apply_alternatives(aseg, aseg + alt->sh_size);
-	}
-	if (locks && text) {
-		void *lseg = (void *)locks->sh_addr;
-		void *tseg = (void *)text->sh_addr;
-		alternatives_smp_module_add(me, me->name,
-					    lseg, lseg + locks->sh_size,
-					    tseg, tseg + text->sh_size);
-	}
-
-	if (para) {
-		void *pseg = (void *)para->sh_addr;
-		apply_paravirt(pseg, pseg + para->sh_size);
-	}
-
-	return module_bug_finalize(hdr, sechdrs, me);
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-	alternatives_smp_module_del(mod);
-	module_bug_cleanup(mod);
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/module.c linux-libre-2.6.31-gnu/arch/x86/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/module.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,248 @@
+/*  Kernel module help for x86.
+    Copyright (C) 2001 Rusty Russell.
+
+    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/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+	struct vm_struct *area;
+
+	if (!size)
+		return NULL;
+	size = PAGE_ALIGN(size);
+	if (size > MODULES_LEN)
+		return NULL;
+
+	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
+	if (!area)
+		return NULL;
+
+	return __vmalloc_area(area, GFP_KERNEL | __GFP_HIGHMEM,
+					PAGE_KERNEL_EXEC);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+			      Elf_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *mod)
+{
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+int apply_relocate(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	unsigned int i;
+	Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_386_32:
+			/* We add the value into the location given */
+			*location += sym->st_value;
+			break;
+		case R_386_PC32:
+			/* Add the value, subtract its postition */
+			*location += sym->st_value - (uint32_t)location;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+	       me->name);
+	return -ENOEXEC;
+}
+#else /*X86_64*/
+int apply_relocate_add(Elf64_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	unsigned int i;
+	Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf64_Sym *sym;
+	void *loc;
+	u64 val;
+
+	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
+			+ ELF64_R_SYM(rel[i].r_info);
+
+		DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n",
+			(int)ELF64_R_TYPE(rel[i].r_info),
+			sym->st_value, rel[i].r_addend, (u64)loc);
+
+		val = sym->st_value + rel[i].r_addend;
+
+		switch (ELF64_R_TYPE(rel[i].r_info)) {
+		case R_X86_64_NONE:
+			break;
+		case R_X86_64_64:
+			*(u64 *)loc = val;
+			break;
+		case R_X86_64_32:
+			*(u32 *)loc = val;
+			if (val != *(u32 *)loc)
+				goto overflow;
+			break;
+		case R_X86_64_32S:
+			*(s32 *)loc = val;
+			if ((s64)val != *(s32 *)loc)
+				goto overflow;
+			break;
+		case R_X86_64_PC32:
+			val -= (u64)loc;
+			*(u32 *)loc = val;
+#if 0
+			if ((s64)val != *(s32 *)loc)
+				goto overflow;
+#endif
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown rela relocation: %llu\n",
+			       me->name, ELF64_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+
+overflow:
+	printk(KERN_ERR "overflow in relocation type %d val %Lx\n",
+	       (int)ELF64_R_TYPE(rel[i].r_info), val);
+	printk(KERN_ERR "`%s' likely not compiled with -mcmodel=kernel\n",
+	       me->name);
+	return -ENOEXEC;
+}
+
+int apply_relocate(Elf_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	printk(KERN_ERR "non add relocation not supported\n");
+	return -ENOSYS;
+}
+
+#endif
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
+		*para = NULL;
+	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+		if (!strcmp(".text", secstrings + s->sh_name))
+			text = s;
+		if (!strcmp(".altinstructions", secstrings + s->sh_name))
+			alt = s;
+		if (!strcmp(".smp_locks", secstrings + s->sh_name))
+			locks = s;
+		if (!strcmp(".parainstructions", secstrings + s->sh_name))
+			para = s;
+	}
+
+	if (alt) {
+		/* patch .altinstructions */
+		void *aseg = (void *)alt->sh_addr;
+		apply_alternatives(aseg, aseg + alt->sh_size);
+	}
+	if (locks && text) {
+		void *lseg = (void *)locks->sh_addr;
+		void *tseg = (void *)text->sh_addr;
+		alternatives_smp_module_add(me, me->name,
+					    lseg, lseg + locks->sh_size,
+					    tseg, tseg + text->sh_size);
+	}
+
+	if (para) {
+		void *pseg = (void *)para->sh_addr;
+		apply_paravirt(pseg, pseg + para->sh_size);
+	}
+
+	return module_bug_finalize(hdr, sechdrs, me);
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+	alternatives_smp_module_del(mod);
+	module_bug_cleanup(mod);
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/mpparse.c linux-libre-2.6.31-gnu/arch/x86/kernel/mpparse.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/mpparse.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/mpparse.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/smp.h>
+#include <linux/pci.h>
 
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
@@ -870,24 +871,17 @@
 inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
 #endif /* CONFIG_X86_IO_APIC */
 
-static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length,
-		      int count)
+static int
+check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
 {
-	if (!mpc_new_phys) {
-		pr_info("No spare slots, try to append...take your risk, "
-			"new mpc_length %x\n", count);
-	} else {
-		if (count <= mpc_new_length)
-			pr_info("No spare slots, try to append..., "
-				"new mpc_length %x\n", count);
-		else {
-			pr_err("mpc_new_length %lx is too small\n",
-				mpc_new_length);
-			return -1;
-		}
+	int ret = 0;
+
+	if (!mpc_new_phys || count <= mpc_new_length) {
+		WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
+		return -1;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int  __init replace_intsrc_all(struct mpc_table *mpc,
@@ -946,7 +940,7 @@
 		} else {
 			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
 			count += sizeof(struct mpc_intsrc);
-			if (!check_slot(mpc_new_phys, mpc_new_length, count))
+			if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
 				goto out;
 			assign_to_mpc_intsrc(&mp_irqs[i], m);
 			mpc->length = count;
@@ -963,11 +957,14 @@
 	return 0;
 }
 
-static int __initdata enable_update_mptable;
+int enable_update_mptable;
 
 static int __init update_mptable_setup(char *str)
 {
 	enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+	pci_routeirq = 1;
+#endif
 	return 0;
 }
 early_param("update_mptable", update_mptable_setup);
@@ -980,6 +977,9 @@
 static int __init parse_alloc_mptable_opt(char *p)
 {
 	enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+	pci_routeirq = 1;
+#endif
 	alloc_mptable = 1;
 	if (!p)
 		return 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/msr.c linux-libre-2.6.31-gnu/arch/x86/kernel/msr.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/msr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/msr.c	2009-09-09 18:13:59.000000000 -0400
@@ -196,6 +196,11 @@
 	.notifier_call = msr_class_cpu_callback,
 };
 
+static char *msr_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "cpu/%u/msr", MINOR(dev->devt));
+}
+
 static int __init msr_init(void)
 {
 	int i, err = 0;
@@ -212,6 +217,7 @@
 		err = PTR_ERR(msr_class);
 		goto out_chrdev;
 	}
+	msr_class->nodename = msr_nodename;
 	for_each_online_cpu(i) {
 		err = msr_device_create(i);
 		if (err != 0)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/paravirt.c linux-libre-2.6.31-gnu/arch/x86/kernel/paravirt.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/paravirt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/paravirt.c	2009-09-09 18:13:59.000000000 -0400
@@ -248,18 +248,16 @@
 
 static inline void enter_lazy(enum paravirt_lazy_mode mode)
 {
-	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
-	BUG_ON(preemptible());
+	BUG_ON(percpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
 
-	__get_cpu_var(paravirt_lazy_mode) = mode;
+	percpu_write(paravirt_lazy_mode, mode);
 }
 
-void paravirt_leave_lazy(enum paravirt_lazy_mode mode)
+static void leave_lazy(enum paravirt_lazy_mode mode)
 {
-	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != mode);
-	BUG_ON(preemptible());
+	BUG_ON(percpu_read(paravirt_lazy_mode) != mode);
 
-	__get_cpu_var(paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
+	percpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
 }
 
 void paravirt_enter_lazy_mmu(void)
@@ -269,22 +267,36 @@
 
 void paravirt_leave_lazy_mmu(void)
 {
-	paravirt_leave_lazy(PARAVIRT_LAZY_MMU);
+	leave_lazy(PARAVIRT_LAZY_MMU);
 }
 
-void paravirt_enter_lazy_cpu(void)
+void paravirt_start_context_switch(struct task_struct *prev)
 {
+	BUG_ON(preemptible());
+
+	if (percpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
+		arch_leave_lazy_mmu_mode();
+		set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
+	}
 	enter_lazy(PARAVIRT_LAZY_CPU);
 }
 
-void paravirt_leave_lazy_cpu(void)
+void paravirt_end_context_switch(struct task_struct *next)
 {
-	paravirt_leave_lazy(PARAVIRT_LAZY_CPU);
+	BUG_ON(preemptible());
+
+	leave_lazy(PARAVIRT_LAZY_CPU);
+
+	if (test_and_clear_ti_thread_flag(task_thread_info(next), TIF_LAZY_MMU_UPDATES))
+		arch_enter_lazy_mmu_mode();
 }
 
 enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
 {
-	return __get_cpu_var(paravirt_lazy_mode);
+	if (in_interrupt())
+		return PARAVIRT_LAZY_NONE;
+
+	return percpu_read(paravirt_lazy_mode);
 }
 
 void arch_flush_lazy_mmu_mode(void)
@@ -292,7 +304,6 @@
 	preempt_disable();
 
 	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
-		WARN_ON(preempt_count() == 1);
 		arch_leave_lazy_mmu_mode();
 		arch_enter_lazy_mmu_mode();
 	}
@@ -300,19 +311,6 @@
 	preempt_enable();
 }
 
-void arch_flush_lazy_cpu_mode(void)
-{
-	preempt_disable();
-
-	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) {
-		WARN_ON(preempt_count() == 1);
-		arch_leave_lazy_cpu_mode();
-		arch_enter_lazy_cpu_mode();
-	}
-
-	preempt_enable();
-}
-
 struct pv_info pv_info = {
 	.name = "bare hardware",
 	.paravirt_enabled = 0,
@@ -404,10 +402,8 @@
 	.set_iopl_mask = native_set_iopl_mask,
 	.io_delay = native_io_delay,
 
-	.lazy_mode = {
-		.enter = paravirt_nop,
-		.leave = paravirt_nop,
-	},
+	.start_context_switch = paravirt_nop,
+	.end_context_switch = paravirt_nop,
 };
 
 struct pv_apic_ops pv_apic_ops = {
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/pci-calgary_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/pci-calgary_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/pci-calgary_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/pci-calgary_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -186,37 +186,6 @@
 
 static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
 
-/* enable this to stress test the chip's TCE cache */
-#ifdef CONFIG_IOMMU_DEBUG
-static int debugging = 1;
-
-static inline unsigned long verify_bit_range(unsigned long* bitmap,
-	int expected, unsigned long start, unsigned long end)
-{
-	unsigned long idx = start;
-
-	BUG_ON(start >= end);
-
-	while (idx < end) {
-		if (!!test_bit(idx, bitmap) != expected)
-			return idx;
-		++idx;
-	}
-
-	/* all bits have the expected value */
-	return ~0UL;
-}
-#else /* debugging is disabled */
-static int debugging;
-
-static inline unsigned long verify_bit_range(unsigned long* bitmap,
-	int expected, unsigned long start, unsigned long end)
-{
-	return ~0UL;
-}
-
-#endif /* CONFIG_IOMMU_DEBUG */
-
 static inline int translation_enabled(struct iommu_table *tbl)
 {
 	/* only PHBs with translation enabled have an IOMMU table */
@@ -228,7 +197,6 @@
 {
 	unsigned long index;
 	unsigned long end;
-	unsigned long badbit;
 	unsigned long flags;
 
 	index = start_addr >> PAGE_SHIFT;
@@ -243,14 +211,6 @@
 
 	spin_lock_irqsave(&tbl->it_lock, flags);
 
-	badbit = verify_bit_range(tbl->it_map, 0, index, end);
-	if (badbit != ~0UL) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "Calgary: entry already allocated at "
-			       "0x%lx tbl %p dma 0x%lx npages %u\n",
-			       badbit, tbl, start_addr, npages);
-	}
-
 	iommu_area_reserve(tbl->it_map, index, npages);
 
 	spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -326,7 +286,6 @@
 	unsigned int npages)
 {
 	unsigned long entry;
-	unsigned long badbit;
 	unsigned long badend;
 	unsigned long flags;
 
@@ -346,14 +305,6 @@
 
 	spin_lock_irqsave(&tbl->it_lock, flags);
 
-	badbit = verify_bit_range(tbl->it_map, 1, entry, entry + npages);
-	if (badbit != ~0UL) {
-		if (printk_ratelimit())
-			printk(KERN_ERR "Calgary: bit is off at 0x%lx "
-			       "tbl %p dma 0x%Lx entry 0x%lx npages %u\n",
-			       badbit, tbl, dma_addr, entry, npages);
-	}
-
 	iommu_area_free(tbl->it_map, entry, npages);
 
 	spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -1488,9 +1439,8 @@
 		iommu_detected = 1;
 		calgary_detected = 1;
 		printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected.\n");
-		printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d, "
-		       "CONFIG_IOMMU_DEBUG is %s.\n", specified_table_size,
-		       debugging ? "enabled" : "disabled");
+		printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d\n",
+		       specified_table_size);
 
 		/* swiotlb for devices that aren't behind the Calgary. */
 		if (max_pfn > MAX_DMA32_PFN)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/pci-dma.c linux-libre-2.6.31-gnu/arch/x86/kernel/pci-dma.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/pci-dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/pci-dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,8 @@
 /* Set this to 1 if there is a HW IOMMU in the system */
 int iommu_detected __read_mostly = 0;
 
+int iommu_pass_through;
+
 dma_addr_t bad_dma_address __read_mostly = 0;
 EXPORT_SYMBOL(bad_dma_address);
 
@@ -210,6 +212,10 @@
 		if (!strncmp(p, "soft", 4))
 			swiotlb = 1;
 #endif
+		if (!strncmp(p, "pt", 2)) {
+			iommu_pass_through = 1;
+			return 1;
+		}
 
 		gart_parse_options(p);
 
@@ -290,6 +296,8 @@
 void pci_iommu_shutdown(void)
 {
 	gart_iommu_shutdown();
+
+	amd_iommu_shutdown();
 }
 /* Must execute after PCI subsystem */
 fs_initcall(pci_iommu_init);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/pci-gart_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/pci-gart_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/pci-gart_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/pci-gart_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -144,48 +144,21 @@
 }
 
 #ifdef CONFIG_IOMMU_LEAK
-
-#define SET_LEAK(x)							\
-	do {								\
-		if (iommu_leak_tab)					\
-			iommu_leak_tab[x] = __builtin_return_address(0);\
-	} while (0)
-
-#define CLEAR_LEAK(x)							\
-	do {								\
-		if (iommu_leak_tab)					\
-			iommu_leak_tab[x] = NULL;			\
-	} while (0)
-
 /* Debugging aid for drivers that don't free their IOMMU tables */
-static void **iommu_leak_tab;
 static int leak_trace;
 static int iommu_leak_pages = 20;
 
 static void dump_leak(void)
 {
-	int i;
 	static int dump;
 
-	if (dump || !iommu_leak_tab)
+	if (dump)
 		return;
 	dump = 1;
-	show_stack(NULL, NULL);
 
-	/* Very crude. dump some from the end of the table too */
-	printk(KERN_DEBUG "Dumping %d pages from end of IOMMU:\n",
-	       iommu_leak_pages);
-	for (i = 0; i < iommu_leak_pages; i += 2) {
-		printk(KERN_DEBUG "%lu: ", iommu_pages-i);
-		printk_address((unsigned long) iommu_leak_tab[iommu_pages-i],
-				0);
-		printk(KERN_CONT "%c", (i+1)%2 == 0 ? '\n' : ' ');
-	}
-	printk(KERN_DEBUG "\n");
+	show_stack(NULL, NULL);
+	debug_dma_dump_mappings(NULL);
 }
-#else
-# define SET_LEAK(x)
-# define CLEAR_LEAK(x)
 #endif
 
 static void iommu_full(struct device *dev, size_t size, int dir)
@@ -248,7 +221,6 @@
 
 	for (i = 0; i < npages; i++) {
 		iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem);
-		SET_LEAK(iommu_page + i);
 		phys_mem += PAGE_SIZE;
 	}
 	return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK);
@@ -294,7 +266,6 @@
 	npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
 	for (i = 0; i < npages; i++) {
 		iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
-		CLEAR_LEAK(iommu_page + i);
 	}
 	free_iommu(iommu_page, npages);
 }
@@ -377,7 +348,6 @@
 		pages = iommu_num_pages(s->offset, s->length, PAGE_SIZE);
 		while (pages--) {
 			iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr);
-			SET_LEAK(iommu_page);
 			addr += PAGE_SIZE;
 			iommu_page++;
 		}
@@ -688,8 +658,6 @@
 
 	agp_gatt_table = gatt;
 
-	enable_gart_translations();
-
 	error = sysdev_class_register(&gart_sysdev_class);
 	if (!error)
 		error = sysdev_register(&device_gart);
@@ -707,7 +675,7 @@
  nommu:
 	/* Should not happen anymore */
 	printk(KERN_WARNING "PCI-DMA: More than 4GB of RAM and no IOMMU\n"
-	       KERN_WARNING "falling back to iommu=soft.\n");
+	       "falling back to iommu=soft.\n");
 	return -1;
 }
 
@@ -801,11 +769,12 @@
 
 #ifdef CONFIG_IOMMU_LEAK
 	if (leak_trace) {
-		iommu_leak_tab = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
-				  get_order(iommu_pages*sizeof(void *)));
-		if (!iommu_leak_tab)
+		int ret;
+
+		ret = dma_debug_resize_entries(iommu_pages);
+		if (ret)
 			printk(KERN_DEBUG
-			       "PCI-DMA: Cannot allocate leak trace area\n");
+			       "PCI-DMA: Cannot trace all the entries\n");
 	}
 #endif
 
@@ -845,6 +814,14 @@
 	 * the pages as Not-Present:
 	 */
 	wbinvd();
+	
+	/*
+	 * Now all caches are flushed and we can safely enable
+	 * GART hardware.  Doing it early leaves the possibility
+	 * of stale cache entries that can lead to GART PTE
+	 * errors.
+	 */
+	enable_gart_translations();
 
 	/*
 	 * Try to workaround a bug (thanks to BenH):
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/pci-swiotlb.c linux-libre-2.6.31-gnu/arch/x86/kernel/pci-swiotlb.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/pci-swiotlb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/pci-swiotlb.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,7 @@
 	return paddr;
 }
 
-phys_addr_t swiotlb_bus_to_phys(dma_addr_t baddr)
+phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
 {
 	return baddr;
 }
@@ -71,7 +71,8 @@
 {
 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
 #ifdef CONFIG_X86_64
-	if (!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN)
+	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN) ||
+		iommu_pass_through)
 	       swiotlb = 1;
 #endif
 	if (swiotlb_force)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/process_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/process_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/process_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/process_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,8 +9,6 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#include <stdarg.h>
-
 #include <linux/stackprotector.h>
 #include <linux/cpu.h>
 #include <linux/errno.h>
@@ -33,7 +31,6 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
-#include <linux/random.h>
 #include <linux/personality.h>
 #include <linux/tick.h>
 #include <linux/percpu.h>
@@ -290,7 +287,8 @@
 		p->thread.io_bitmap_max = 0;
 	}
 
-	ds_copy_thread(p, current);
+	clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+	p->thread.ds_ctx = NULL;
 
 	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
 	p->thread.debugctlmsr = 0;
@@ -407,7 +405,7 @@
 	 * done before math_state_restore, so the TS bit is up
 	 * to date.
 	 */
-	arch_leave_lazy_cpu_mode();
+	arch_end_context_switch(next_p);
 
 	/* If the task has used fpu the last 5 timeslices, just do a full
 	 * restore of the math state immediately to avoid the trap; the
@@ -497,15 +495,3 @@
 	return 0;
 }
 
-unsigned long arch_align_stack(unsigned long sp)
-{
-	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
-	return sp & ~0xf;
-}
-
-unsigned long arch_randomize_brk(struct mm_struct *mm)
-{
-	unsigned long range_end = mm->brk + 0x02000000;
-	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/process_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/process_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/process_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/process_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,8 +14,6 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#include <stdarg.h>
-
 #include <linux/stackprotector.h>
 #include <linux/cpu.h>
 #include <linux/errno.h>
@@ -32,7 +30,6 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/ptrace.h>
-#include <linux/random.h>
 #include <linux/notifier.h>
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
@@ -335,7 +332,8 @@
 			goto out;
 	}
 
-	ds_copy_thread(p, me);
+	clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+	p->thread.ds_ctx = NULL;
 
 	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
 	p->thread.debugctlmsr = 0;
@@ -428,7 +426,7 @@
 	 * done before math_state_restore, so the TS bit is up
 	 * to date.
 	 */
-	arch_leave_lazy_cpu_mode();
+	arch_end_context_switch(next_p);
 
 	/*
 	 * Switch FS and GS.
@@ -660,15 +658,3 @@
 	return do_arch_prctl(current, code, addr);
 }
 
-unsigned long arch_align_stack(unsigned long sp)
-{
-	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
-		sp -= get_random_int() % 8192;
-	return sp & ~0xf;
-}
-
-unsigned long arch_randomize_brk(struct mm_struct *mm)
-{
-	unsigned long range_end = mm->brk + 0x02000000;
-	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/process.c linux-libre-2.6.31-gnu/arch/x86/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -8,12 +8,15 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/clockchips.h>
+#include <linux/random.h>
 #include <trace/power.h>
 #include <asm/system.h>
 #include <asm/apic.h>
+#include <asm/syscalls.h>
 #include <asm/idle.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
+#include <asm/ds.h>
 
 unsigned long idle_halt;
 EXPORT_SYMBOL(idle_halt);
@@ -45,6 +48,8 @@
 		kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
 		tsk->thread.xstate = NULL;
 	}
+
+	WARN(tsk->thread.ds_ctx, "leaking DS context\n");
 }
 
 void free_thread_info(struct thread_info *ti)
@@ -58,7 +63,7 @@
         task_xstate_cachep =
         	kmem_cache_create("task_xstate", xstate_size,
 				  __alignof__(union thread_xstate),
-				  SLAB_PANIC, NULL);
+				  SLAB_PANIC | SLAB_NOTRACK, NULL);
 }
 
 /*
@@ -83,8 +88,6 @@
 		put_cpu();
 		kfree(bp);
 	}
-
-	ds_exit_thread(current);
 }
 
 void flush_thread(void)
@@ -516,16 +519,12 @@
 		if (!cpumask_test_cpu(cpu, c1e_mask)) {
 			cpumask_set_cpu(cpu, c1e_mask);
 			/*
-			 * Force broadcast so ACPI can not interfere. Needs
-			 * to run with interrupts enabled as it uses
-			 * smp_function_call.
+			 * Force broadcast so ACPI can not interfere.
 			 */
-			local_irq_enable();
 			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
 					   &cpu);
 			printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
 			       cpu);
-			local_irq_disable();
 		}
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
@@ -613,3 +612,16 @@
 }
 early_param("idle", idle_setup);
 
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+		sp -= get_random_int() % 8192;
+	return sp & ~0xf;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+	unsigned long range_end = mm->brk + 0x02000000;
+	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/ptrace.c linux-libre-2.6.31-gnu/arch/x86/kernel/ptrace.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/ptrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/ptrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/audit.h>
 #include <linux/seccomp.h>
 #include <linux/signal.h>
+#include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -578,17 +579,130 @@
 }
 
 #ifdef CONFIG_X86_PTRACE_BTS
+/*
+ * A branch trace store context.
+ *
+ * Contexts may only be installed by ptrace_bts_config() and only for
+ * ptraced tasks.
+ *
+ * Contexts are destroyed when the tracee is detached from the tracer.
+ * The actual destruction work requires interrupts enabled, so the
+ * work is deferred and will be scheduled during __ptrace_unlink().
+ *
+ * Contexts hold an additional task_struct reference on the traced
+ * task, as well as a reference on the tracer's mm.
+ *
+ * Ptrace already holds a task_struct for the duration of ptrace operations,
+ * but since destruction is deferred, it may be executed after both
+ * tracer and tracee exited.
+ */
+struct bts_context {
+	/* The branch trace handle. */
+	struct bts_tracer	*tracer;
+
+	/* The buffer used to store the branch trace and its size. */
+	void			*buffer;
+	unsigned int		size;
+
+	/* The mm that paid for the above buffer. */
+	struct mm_struct	*mm;
+
+	/* The task this context belongs to. */
+	struct task_struct	*task;
+
+	/* The signal to send on a bts buffer overflow. */
+	unsigned int		bts_ovfl_signal;
+
+	/* The work struct to destroy a context. */
+	struct work_struct	work;
+};
+
+static int alloc_bts_buffer(struct bts_context *context, unsigned int size)
+{
+	void *buffer = NULL;
+	int err = -ENOMEM;
+
+	err = account_locked_memory(current->mm, current->signal->rlim, size);
+	if (err < 0)
+		return err;
+
+	buffer = kzalloc(size, GFP_KERNEL);
+	if (!buffer)
+		goto out_refund;
+
+	context->buffer = buffer;
+	context->size = size;
+	context->mm = get_task_mm(current);
+
+	return 0;
+
+ out_refund:
+	refund_locked_memory(current->mm, size);
+	return err;
+}
+
+static inline void free_bts_buffer(struct bts_context *context)
+{
+	if (!context->buffer)
+		return;
+
+	kfree(context->buffer);
+	context->buffer = NULL;
+
+	refund_locked_memory(context->mm, context->size);
+	context->size = 0;
+
+	mmput(context->mm);
+	context->mm = NULL;
+}
+
+static void free_bts_context_work(struct work_struct *w)
+{
+	struct bts_context *context;
+
+	context = container_of(w, struct bts_context, work);
+
+	ds_release_bts(context->tracer);
+	put_task_struct(context->task);
+	free_bts_buffer(context);
+	kfree(context);
+}
+
+static inline void free_bts_context(struct bts_context *context)
+{
+	INIT_WORK(&context->work, free_bts_context_work);
+	schedule_work(&context->work);
+}
+
+static inline struct bts_context *alloc_bts_context(struct task_struct *task)
+{
+	struct bts_context *context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (context) {
+		context->task = task;
+		task->bts = context;
+
+		get_task_struct(task);
+	}
+
+	return context;
+}
+
 static int ptrace_bts_read_record(struct task_struct *child, size_t index,
 				  struct bts_struct __user *out)
 {
+	struct bts_context *context;
 	const struct bts_trace *trace;
 	struct bts_struct bts;
 	const unsigned char *at;
 	int error;
 
-	trace = ds_read_bts(child->bts);
+	context = child->bts;
+	if (!context)
+		return -ESRCH;
+
+	trace = ds_read_bts(context->tracer);
 	if (!trace)
-		return -EPERM;
+		return -ESRCH;
 
 	at = trace->ds.top - ((index + 1) * trace->ds.size);
 	if ((void *)at < trace->ds.begin)
@@ -597,7 +711,7 @@
 	if (!trace->read)
 		return -EOPNOTSUPP;
 
-	error = trace->read(child->bts, at, &bts);
+	error = trace->read(context->tracer, at, &bts);
 	if (error < 0)
 		return error;
 
@@ -611,13 +725,18 @@
 			    long size,
 			    struct bts_struct __user *out)
 {
+	struct bts_context *context;
 	const struct bts_trace *trace;
 	const unsigned char *at;
 	int error, drained = 0;
 
-	trace = ds_read_bts(child->bts);
+	context = child->bts;
+	if (!context)
+		return -ESRCH;
+
+	trace = ds_read_bts(context->tracer);
 	if (!trace)
-		return -EPERM;
+		return -ESRCH;
 
 	if (!trace->read)
 		return -EOPNOTSUPP;
@@ -628,9 +747,8 @@
 	for (at = trace->ds.begin; (void *)at < trace->ds.top;
 	     out++, drained++, at += trace->ds.size) {
 		struct bts_struct bts;
-		int error;
 
-		error = trace->read(child->bts, at, &bts);
+		error = trace->read(context->tracer, at, &bts);
 		if (error < 0)
 			return error;
 
@@ -640,35 +758,18 @@
 
 	memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size);
 
-	error = ds_reset_bts(child->bts);
+	error = ds_reset_bts(context->tracer);
 	if (error < 0)
 		return error;
 
 	return drained;
 }
 
-static int ptrace_bts_allocate_buffer(struct task_struct *child, size_t size)
-{
-	child->bts_buffer = alloc_locked_buffer(size);
-	if (!child->bts_buffer)
-		return -ENOMEM;
-
-	child->bts_size = size;
-
-	return 0;
-}
-
-static void ptrace_bts_free_buffer(struct task_struct *child)
-{
-	free_locked_buffer(child->bts_buffer, child->bts_size);
-	child->bts_buffer = NULL;
-	child->bts_size = 0;
-}
-
 static int ptrace_bts_config(struct task_struct *child,
 			     long cfg_size,
 			     const struct ptrace_bts_config __user *ucfg)
 {
+	struct bts_context *context;
 	struct ptrace_bts_config cfg;
 	unsigned int flags = 0;
 
@@ -678,28 +779,33 @@
 	if (copy_from_user(&cfg, ucfg, sizeof(cfg)))
 		return -EFAULT;
 
-	if (child->bts) {
-		ds_release_bts(child->bts);
-		child->bts = NULL;
-	}
+	context = child->bts;
+	if (!context)
+		context = alloc_bts_context(child);
+	if (!context)
+		return -ENOMEM;
 
 	if (cfg.flags & PTRACE_BTS_O_SIGNAL) {
 		if (!cfg.signal)
 			return -EINVAL;
 
-		child->thread.bts_ovfl_signal = cfg.signal;
 		return -EOPNOTSUPP;
+		context->bts_ovfl_signal = cfg.signal;
 	}
 
-	if ((cfg.flags & PTRACE_BTS_O_ALLOC) &&
-	    (cfg.size != child->bts_size)) {
-		int error;
+	ds_release_bts(context->tracer);
+	context->tracer = NULL;
 
-		ptrace_bts_free_buffer(child);
+	if ((cfg.flags & PTRACE_BTS_O_ALLOC) && (cfg.size != context->size)) {
+		int err;
 
-		error = ptrace_bts_allocate_buffer(child, cfg.size);
-		if (error < 0)
-			return error;
+		free_bts_buffer(context);
+		if (!cfg.size)
+			return 0;
+
+		err = alloc_bts_buffer(context, cfg.size);
+		if (err < 0)
+			return err;
 	}
 
 	if (cfg.flags & PTRACE_BTS_O_TRACE)
@@ -708,15 +814,14 @@
 	if (cfg.flags & PTRACE_BTS_O_SCHED)
 		flags |= BTS_TIMESTAMPS;
 
-	child->bts = ds_request_bts(child, child->bts_buffer, child->bts_size,
-				    /* ovfl = */ NULL, /* th = */ (size_t)-1,
-				    flags);
-	if (IS_ERR(child->bts)) {
-		int error = PTR_ERR(child->bts);
-
-		ptrace_bts_free_buffer(child);
-		child->bts = NULL;
+	context->tracer =
+		ds_request_bts_task(child, context->buffer, context->size,
+				    NULL, (size_t)-1, flags);
+	if (unlikely(IS_ERR(context->tracer))) {
+		int error = PTR_ERR(context->tracer);
 
+		free_bts_buffer(context);
+		context->tracer = NULL;
 		return error;
 	}
 
@@ -727,20 +832,25 @@
 			     long cfg_size,
 			     struct ptrace_bts_config __user *ucfg)
 {
+	struct bts_context *context;
 	const struct bts_trace *trace;
 	struct ptrace_bts_config cfg;
 
+	context = child->bts;
+	if (!context)
+		return -ESRCH;
+
 	if (cfg_size < sizeof(cfg))
 		return -EIO;
 
-	trace = ds_read_bts(child->bts);
+	trace = ds_read_bts(context->tracer);
 	if (!trace)
-		return -EPERM;
+		return -ESRCH;
 
 	memset(&cfg, 0, sizeof(cfg));
-	cfg.size = trace->ds.end - trace->ds.begin;
-	cfg.signal = child->thread.bts_ovfl_signal;
-	cfg.bts_size = sizeof(struct bts_struct);
+	cfg.size	= trace->ds.end - trace->ds.begin;
+	cfg.signal	= context->bts_ovfl_signal;
+	cfg.bts_size	= sizeof(struct bts_struct);
 
 	if (cfg.signal)
 		cfg.flags |= PTRACE_BTS_O_SIGNAL;
@@ -759,80 +869,51 @@
 
 static int ptrace_bts_clear(struct task_struct *child)
 {
+	struct bts_context *context;
 	const struct bts_trace *trace;
 
-	trace = ds_read_bts(child->bts);
+	context = child->bts;
+	if (!context)
+		return -ESRCH;
+
+	trace = ds_read_bts(context->tracer);
 	if (!trace)
-		return -EPERM;
+		return -ESRCH;
 
 	memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size);
 
-	return ds_reset_bts(child->bts);
+	return ds_reset_bts(context->tracer);
 }
 
 static int ptrace_bts_size(struct task_struct *child)
 {
+	struct bts_context *context;
 	const struct bts_trace *trace;
 
-	trace = ds_read_bts(child->bts);
+	context = child->bts;
+	if (!context)
+		return -ESRCH;
+
+	trace = ds_read_bts(context->tracer);
 	if (!trace)
-		return -EPERM;
+		return -ESRCH;
 
 	return (trace->ds.top - trace->ds.begin) / trace->ds.size;
 }
 
-static void ptrace_bts_fork(struct task_struct *tsk)
-{
-	tsk->bts = NULL;
-	tsk->bts_buffer = NULL;
-	tsk->bts_size = 0;
-	tsk->thread.bts_ovfl_signal = 0;
-}
-
-static void ptrace_bts_untrace(struct task_struct *child)
+/*
+ * Called from __ptrace_unlink() after the child has been moved back
+ * to its original parent.
+ */
+void ptrace_bts_untrace(struct task_struct *child)
 {
 	if (unlikely(child->bts)) {
-		ds_release_bts(child->bts);
+		free_bts_context(child->bts);
 		child->bts = NULL;
-
-		/* We cannot update total_vm and locked_vm since
-		   child's mm is already gone. But we can reclaim the
-		   memory. */
-		kfree(child->bts_buffer);
-		child->bts_buffer = NULL;
-		child->bts_size = 0;
 	}
 }
-
-static void ptrace_bts_detach(struct task_struct *child)
-{
-	/*
-	 * Ptrace_detach() races with ptrace_untrace() in case
-	 * the child dies and is reaped by another thread.
-	 *
-	 * We only do the memory accounting at this point and
-	 * leave the buffer deallocation and the bts tracer
-	 * release to ptrace_bts_untrace() which will be called
-	 * later on with tasklist_lock held.
-	 */
-	release_locked_buffer(child->bts_buffer, child->bts_size);
-}
-#else
-static inline void ptrace_bts_fork(struct task_struct *tsk) {}
-static inline void ptrace_bts_detach(struct task_struct *child) {}
-static inline void ptrace_bts_untrace(struct task_struct *child) {}
 #endif /* CONFIG_X86_PTRACE_BTS */
 
-void x86_ptrace_fork(struct task_struct *child, unsigned long clone_flags)
-{
-	ptrace_bts_fork(child);
-}
-
-void x86_ptrace_untrace(struct task_struct *child)
-{
-	ptrace_bts_untrace(child);
-}
-
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -844,7 +925,6 @@
 #ifdef TIF_SYSCALL_EMU
 	clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
 #endif
-	ptrace_bts_detach(child);
 }
 
 #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/pvclock.c linux-libre-2.6.31-gnu/arch/x86/kernel/pvclock.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/pvclock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/pvclock.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,7 +60,7 @@
 		"adc  %5,%%edx ; "
 		: "=A" (product), "=r" (tmp1), "=r" (tmp2)
 		: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
-#elif __x86_64__
+#elif defined(__x86_64__)
 	__asm__ (
 		"mul %%rdx ; shrd $32,%%rdx,%%rax"
 		: "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/quirks.c linux-libre-2.6.31-gnu/arch/x86/kernel/quirks.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/quirks.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/quirks.c	2009-09-09 18:13:59.000000000 -0400
@@ -491,5 +491,42 @@
 		break;
 	}
 }
+#endif
+
+#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
+/* Set correct numa_node information for AMD NB functions */
+static void __init quirk_amd_nb_node(struct pci_dev *dev)
+{
+	struct pci_dev *nb_ht;
+	unsigned int devfn;
+	u32 val;
+
+	devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
+	nb_ht = pci_get_slot(dev->bus, devfn);
+	if (!nb_ht)
+		return;
+
+	pci_read_config_dword(nb_ht, 0x60, &val);
+	set_dev_node(&dev->dev, val & 7);
+	pci_dev_put(dev);
+}
 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_HT,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MAP,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
+			quirk_amd_nb_node);
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/reboot.c linux-libre-2.6.31-gnu/arch/x86/kernel/reboot.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/reboot.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/reboot.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,6 +3,7 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/efi.h>
+#include <linux/dmi.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -17,7 +18,6 @@
 #include <asm/cpu.h>
 
 #ifdef CONFIG_X86_32
-# include <linux/dmi.h>
 # include <linux/ctype.h>
 # include <linux/mc146818rtc.h>
 #else
@@ -192,6 +192,15 @@
 			DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
 		},
 	},
+	{   /* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 360",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"),
+			DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
+		},
+	},
 	{	/* Handle problems with rebooting on Dell 2400's */
 		.callback = set_bios_reboot,
 		.ident = "Dell PowerEdge 2400",
@@ -240,6 +249,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
 		},
 	},
+	{	/* Handle problems with rebooting on CompuLab SBC-FITPC2 */
+		.callback = set_bios_reboot,
+		.ident = "CompuLab SBC-FITPC2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "CompuLab"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
+		},
+	},
 	{ }
 };
 
@@ -387,6 +404,46 @@
 
 #endif /* CONFIG_X86_32 */
 
+/*
+ * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
+ */
+static int __init set_pci_reboot(const struct dmi_system_id *d)
+{
+	if (reboot_type != BOOT_CF9) {
+		reboot_type = BOOT_CF9;
+		printk(KERN_INFO "%s series board detected. "
+		       "Selecting PCI-method for reboots.\n", d->ident);
+	}
+	return 0;
+}
+
+static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
+	{	/* Handle problems with rebooting on Apple MacBook5 */
+		.callback = set_pci_reboot,
+		.ident = "Apple MacBook5",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
+		},
+	},
+	{	/* Handle problems with rebooting on Apple MacBookPro5 */
+		.callback = set_pci_reboot,
+		.ident = "Apple MacBookPro5",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
+		},
+	},
+	{ }
+};
+
+static int __init pci_reboot_init(void)
+{
+	dmi_check_system(pci_reboot_dmi_table);
+	return 0;
+}
+core_initcall(pci_reboot_init);
+
 static inline void kb_wait(void)
 {
 	int i;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/setup.c linux-libre-2.6.31-gnu/arch/x86/kernel/setup.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -112,6 +112,14 @@
 #define ARCH_SETUP
 #endif
 
+/*
+ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
+ * The direct mapping extends to max_pfn_mapped, so that we can directly access
+ * apertures, ACPI and other tables without having to play with fixmaps.
+ */
+unsigned long max_low_pfn_mapped;
+unsigned long max_pfn_mapped;
+
 RESERVE_BRK(dmi_alloc, 65536);
 
 unsigned int boot_cpu_id __read_mostly;
@@ -214,8 +222,8 @@
 unsigned long mmu_cr4_features = X86_CR4_PAE;
 #endif
 
-/* Boot loader ID as an integer, for the benefit of proc_dointvec */
-int bootloader_type;
+/* Boot loader ID and version as integers, for the benefit of proc_dointvec */
+int bootloader_type, bootloader_version;
 
 /*
  * Setup options
@@ -281,6 +289,20 @@
 	return ret;
 }
 
+#ifdef CONFIG_X86_64
+static void __init init_gbpages(void)
+{
+	if (direct_gbpages && cpu_has_gbpages)
+		printk(KERN_INFO "Using GB pages for direct mapping\n");
+	else
+		direct_gbpages = 0;
+}
+#else
+static inline void init_gbpages(void)
+{
+}
+#endif
+
 static void __init reserve_brk(void)
 {
 	if (_brk_end > _brk_start)
@@ -293,15 +315,13 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
-#ifdef CONFIG_X86_32
-
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 static void __init relocate_initrd(void)
 {
 
 	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
 	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
-	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+	u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
 	u64 ramdisk_here;
 	unsigned long slop, clen, mapaddr;
 	char *p, *q;
@@ -357,14 +377,13 @@
 		ramdisk_image, ramdisk_image + ramdisk_size - 1,
 		ramdisk_here, ramdisk_here + ramdisk_size - 1);
 }
-#endif
 
 static void __init reserve_initrd(void)
 {
 	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
 	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
 	u64 ramdisk_end   = ramdisk_image + ramdisk_size;
-	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+	u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
 
 	if (!boot_params.hdr.type_of_loader ||
 	    !ramdisk_image || !ramdisk_size)
@@ -394,14 +413,8 @@
 		return;
 	}
 
-#ifdef CONFIG_X86_32
 	relocate_initrd();
-#else
-	printk(KERN_ERR "initrd extends beyond end of memory "
-	       "(0x%08llx > 0x%08llx)\ndisabling initrd\n",
-	       ramdisk_end, end_of_lowmem);
-	initrd_start = 0;
-#endif
+
 	free_early(ramdisk_image, ramdisk_end);
 }
 #else
@@ -659,6 +672,19 @@
 			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
 		},
 	},
+	{
+	/*
+	 * AMI BIOS with low memory corruption was found on Intel DG45ID board.
+	 * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+	 * match only DMI_BOARD_NAME and see if there is more bad products
+	 * with this vendor.
+	 */
+		.callback = dmi_low_memory_corruption,
+		.ident = "AMI BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
+		},
+	},
 #endif
 	{}
 };
@@ -706,6 +732,12 @@
 #endif
 	saved_video_mode = boot_params.hdr.vid_mode;
 	bootloader_type = boot_params.hdr.type_of_loader;
+	if ((bootloader_type >> 4) == 0xe) {
+		bootloader_type &= 0xf;
+		bootloader_type |= (boot_params.hdr.ext_loader_type+0x10) << 4;
+	}
+	bootloader_version  = bootloader_type & 0xf;
+	bootloader_version |= boot_params.hdr.ext_loader_ver << 4;
 
 #ifdef CONFIG_BLK_DEV_RAM
 	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
@@ -854,14 +886,20 @@
 		max_low_pfn = max_pfn;
 
 	high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+	max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
 #endif
 
 #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
 	setup_bios_corruption_check();
 #endif
 
+	printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
+			max_pfn_mapped<<PAGE_SHIFT);
+
 	reserve_brk();
 
+	init_gbpages();
+
 	/* max_pfn_mapped is updated here */
 	max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
 	max_pfn_mapped = max_low_pfn_mapped;
@@ -997,24 +1035,6 @@
 #ifdef CONFIG_X86_32
 
 /**
- * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
- *
- * Description:
- *	Perform any necessary interrupt initialisation prior to setting up
- *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
- *	interrupts should be initialised here if the machine emulates a PC
- *	in any way.
- **/
-void __init x86_quirk_pre_intr_init(void)
-{
-	if (x86_quirks->arch_pre_intr_init) {
-		if (x86_quirks->arch_pre_intr_init())
-			return;
-	}
-	init_ISA_irqs();
-}
-
-/**
  * x86_quirk_intr_init - post gate setup interrupt initialisation
  *
  * Description:
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/setup_percpu.c linux-libre-2.6.31-gnu/arch/x86/kernel/setup_percpu.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/setup_percpu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/setup_percpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -124,7 +124,7 @@
 }
 
 /*
- * Remap allocator
+ * Large page remap allocator
  *
  * This allocator uses PMD page as unit.  A PMD page is allocated for
  * each cpu and each is remapped into vmalloc area using PMD mapping.
@@ -137,105 +137,185 @@
  * better than only using 4k mappings while still being NUMA friendly.
  */
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-static size_t pcpur_size __initdata;
-static void **pcpur_ptrs __initdata;
+struct pcpul_ent {
+	unsigned int	cpu;
+	void		*ptr;
+};
 
-static struct page * __init pcpur_get_page(unsigned int cpu, int pageno)
+static size_t pcpul_size;
+static struct pcpul_ent *pcpul_map;
+static struct vm_struct pcpul_vm;
+
+static struct page * __init pcpul_get_page(unsigned int cpu, int pageno)
 {
 	size_t off = (size_t)pageno << PAGE_SHIFT;
 
-	if (off >= pcpur_size)
+	if (off >= pcpul_size)
 		return NULL;
 
-	return virt_to_page(pcpur_ptrs[cpu] + off);
+	return virt_to_page(pcpul_map[cpu].ptr + off);
 }
 
-static ssize_t __init setup_pcpu_remap(size_t static_size)
+static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen)
 {
-	static struct vm_struct vm;
-	size_t ptrs_size, dyn_size;
+	size_t map_size, dyn_size;
 	unsigned int cpu;
+	int i, j;
 	ssize_t ret;
 
-	/*
-	 * If large page isn't supported, there's no benefit in doing
-	 * this.  Also, on non-NUMA, embedding is better.
-	 *
-	 * NOTE: disabled for now.
-	 */
-	if (true || !cpu_has_pse || !pcpu_need_numa())
+	if (!chosen) {
+		size_t vm_size = VMALLOC_END - VMALLOC_START;
+		size_t tot_size = nr_cpu_ids * PMD_SIZE;
+
+		/* on non-NUMA, embedding is better */
+		if (!pcpu_need_numa())
+			return -EINVAL;
+
+		/* don't consume more than 20% of vmalloc area */
+		if (tot_size > vm_size / 5) {
+			pr_info("PERCPU: too large chunk size %zuMB for "
+				"large page remap\n", tot_size >> 20);
+			return -EINVAL;
+		}
+	}
+
+	/* need PSE */
+	if (!cpu_has_pse) {
+		pr_warning("PERCPU: lpage allocator requires PSE\n");
 		return -EINVAL;
+	}
 
 	/*
 	 * Currently supports only single page.  Supporting multiple
 	 * pages won't be too difficult if it ever becomes necessary.
 	 */
-	pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
+	pcpul_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
 			       PERCPU_DYNAMIC_RESERVE);
-	if (pcpur_size > PMD_SIZE) {
+	if (pcpul_size > PMD_SIZE) {
 		pr_warning("PERCPU: static data is larger than large page, "
 			   "can't use large page\n");
 		return -EINVAL;
 	}
-	dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE;
+	dyn_size = pcpul_size - static_size - PERCPU_FIRST_CHUNK_RESERVE;
 
 	/* allocate pointer array and alloc large pages */
-	ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0]));
-	pcpur_ptrs = alloc_bootmem(ptrs_size);
+	map_size = PFN_ALIGN(nr_cpu_ids * sizeof(pcpul_map[0]));
+	pcpul_map = alloc_bootmem(map_size);
 
 	for_each_possible_cpu(cpu) {
-		pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE);
-		if (!pcpur_ptrs[cpu])
+		pcpul_map[cpu].cpu = cpu;
+		pcpul_map[cpu].ptr = pcpu_alloc_bootmem(cpu, PMD_SIZE,
+							PMD_SIZE);
+		if (!pcpul_map[cpu].ptr) {
+			pr_warning("PERCPU: failed to allocate large page "
+				   "for cpu%u\n", cpu);
 			goto enomem;
+		}
 
 		/*
-		 * Only use pcpur_size bytes and give back the rest.
+		 * Only use pcpul_size bytes and give back the rest.
 		 *
 		 * Ingo: The 2MB up-rounding bootmem is needed to make
 		 * sure the partial 2MB page is still fully RAM - it's
 		 * not well-specified to have a PAT-incompatible area
 		 * (unmapped RAM, device memory, etc.) in that hole.
 		 */
-		free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size),
-			     PMD_SIZE - pcpur_size);
+		free_bootmem(__pa(pcpul_map[cpu].ptr + pcpul_size),
+			     PMD_SIZE - pcpul_size);
 
-		memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size);
+		memcpy(pcpul_map[cpu].ptr, __per_cpu_load, static_size);
 	}
 
 	/* allocate address and map */
-	vm.flags = VM_ALLOC;
-	vm.size = num_possible_cpus() * PMD_SIZE;
-	vm_area_register_early(&vm, PMD_SIZE);
+	pcpul_vm.flags = VM_ALLOC;
+	pcpul_vm.size = nr_cpu_ids * PMD_SIZE;
+	vm_area_register_early(&pcpul_vm, PMD_SIZE);
 
 	for_each_possible_cpu(cpu) {
-		pmd_t *pmd;
+		pmd_t *pmd, pmd_v;
 
-		pmd = populate_extra_pmd((unsigned long)vm.addr
-					 + cpu * PMD_SIZE);
-		set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpur_ptrs[cpu])),
-				     PAGE_KERNEL_LARGE));
+		pmd = populate_extra_pmd((unsigned long)pcpul_vm.addr +
+					 cpu * PMD_SIZE);
+		pmd_v = pfn_pmd(page_to_pfn(virt_to_page(pcpul_map[cpu].ptr)),
+				PAGE_KERNEL_LARGE);
+		set_pmd(pmd, pmd_v);
 	}
 
 	/* we're ready, commit */
 	pr_info("PERCPU: Remapped at %p with large pages, static data "
-		"%zu bytes\n", vm.addr, static_size);
+		"%zu bytes\n", pcpul_vm.addr, static_size);
 
-	ret = pcpu_setup_first_chunk(pcpur_get_page, static_size,
+	ret = pcpu_setup_first_chunk(pcpul_get_page, static_size,
 				     PERCPU_FIRST_CHUNK_RESERVE, dyn_size,
-				     PMD_SIZE, vm.addr, NULL);
-	goto out_free_ar;
+				     PMD_SIZE, pcpul_vm.addr, NULL);
+
+	/* sort pcpul_map array for pcpu_lpage_remapped() */
+	for (i = 0; i < nr_cpu_ids - 1; i++)
+		for (j = i + 1; j < nr_cpu_ids; j++)
+			if (pcpul_map[i].ptr > pcpul_map[j].ptr) {
+				struct pcpul_ent tmp = pcpul_map[i];
+				pcpul_map[i] = pcpul_map[j];
+				pcpul_map[j] = tmp;
+			}
+
+	return ret;
 
 enomem:
 	for_each_possible_cpu(cpu)
-		if (pcpur_ptrs[cpu])
-			free_bootmem(__pa(pcpur_ptrs[cpu]), PMD_SIZE);
-	ret = -ENOMEM;
-out_free_ar:
-	free_bootmem(__pa(pcpur_ptrs), ptrs_size);
-	return ret;
+		if (pcpul_map[cpu].ptr)
+			free_bootmem(__pa(pcpul_map[cpu].ptr), pcpul_size);
+	free_bootmem(__pa(pcpul_map), map_size);
+	return -ENOMEM;
+}
+
+/**
+ * pcpu_lpage_remapped - determine whether a kaddr is in pcpul recycled area
+ * @kaddr: the kernel address in question
+ *
+ * Determine whether @kaddr falls in the pcpul recycled area.  This is
+ * used by pageattr to detect VM aliases and break up the pcpu PMD
+ * mapping such that the same physical page is not mapped under
+ * different attributes.
+ *
+ * The recycled area is always at the tail of a partially used PMD
+ * page.
+ *
+ * RETURNS:
+ * Address of corresponding remapped pcpu address if match is found;
+ * otherwise, NULL.
+ */
+void *pcpu_lpage_remapped(void *kaddr)
+{
+	void *pmd_addr = (void *)((unsigned long)kaddr & PMD_MASK);
+	unsigned long offset = (unsigned long)kaddr & ~PMD_MASK;
+	int left = 0, right = nr_cpu_ids - 1;
+	int pos;
+
+	/* pcpul in use at all? */
+	if (!pcpul_map)
+		return NULL;
+
+	/* okay, perform binary search */
+	while (left <= right) {
+		pos = (left + right) / 2;
+
+		if (pcpul_map[pos].ptr < pmd_addr)
+			left = pos + 1;
+		else if (pcpul_map[pos].ptr > pmd_addr)
+			right = pos - 1;
+		else {
+			/* it shouldn't be in the area for the first chunk */
+			WARN_ON(offset < pcpul_size);
+
+			return pcpul_vm.addr +
+				pcpul_map[pos].cpu * PMD_SIZE + offset;
+		}
+	}
+
+	return NULL;
 }
 #else
-static ssize_t __init setup_pcpu_remap(size_t static_size)
+static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen)
 {
 	return -EINVAL;
 }
@@ -249,7 +329,7 @@
  * mapping so that it can use PMD mapping without additional TLB
  * pressure.
  */
-static ssize_t __init setup_pcpu_embed(size_t static_size)
+static ssize_t __init setup_pcpu_embed(size_t static_size, bool chosen)
 {
 	size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE;
 
@@ -258,7 +338,7 @@
 	 * this.  Also, embedding allocation doesn't play well with
 	 * NUMA.
 	 */
-	if (!cpu_has_pse || pcpu_need_numa())
+	if (!chosen && (!cpu_has_pse || pcpu_need_numa()))
 		return -EINVAL;
 
 	return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE,
@@ -297,7 +377,7 @@
 	pcpu4k_nr_static_pages = PFN_UP(static_size);
 
 	/* unaligned allocations can't be freed, round up to page size */
-	pages_size = PFN_ALIGN(pcpu4k_nr_static_pages * num_possible_cpus()
+	pages_size = PFN_ALIGN(pcpu4k_nr_static_pages * nr_cpu_ids
 			       * sizeof(pcpu4k_pages[0]));
 	pcpu4k_pages = alloc_bootmem(pages_size);
 
@@ -308,8 +388,11 @@
 			void *ptr;
 
 			ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE);
-			if (!ptr)
+			if (!ptr) {
+				pr_warning("PERCPU: failed to allocate "
+					   "4k page for cpu%u\n", cpu);
 				goto enomem;
+			}
 
 			memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE);
 			pcpu4k_pages[j++] = virt_to_page(ptr);
@@ -333,6 +416,16 @@
 	return ret;
 }
 
+/* for explicit first chunk allocator selection */
+static char pcpu_chosen_alloc[16] __initdata;
+
+static int __init percpu_alloc_setup(char *str)
+{
+	strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1);
+	return 0;
+}
+early_param("percpu_alloc", percpu_alloc_setup);
+
 static inline void setup_percpu_segment(int cpu)
 {
 #ifdef CONFIG_X86_32
@@ -346,11 +439,6 @@
 #endif
 }
 
-/*
- * Great future plan:
- * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
- * Always point %gs to its beginning
- */
 void __init setup_per_cpu_areas(void)
 {
 	size_t static_size = __per_cpu_end - __per_cpu_start;
@@ -367,9 +455,26 @@
 	 * of large page mappings.  Please read comments on top of
 	 * each allocator for details.
 	 */
-	ret = setup_pcpu_remap(static_size);
-	if (ret < 0)
-		ret = setup_pcpu_embed(static_size);
+	ret = -EINVAL;
+	if (strlen(pcpu_chosen_alloc)) {
+		if (strcmp(pcpu_chosen_alloc, "4k")) {
+			if (!strcmp(pcpu_chosen_alloc, "lpage"))
+				ret = setup_pcpu_lpage(static_size, true);
+			else if (!strcmp(pcpu_chosen_alloc, "embed"))
+				ret = setup_pcpu_embed(static_size, true);
+			else
+				pr_warning("PERCPU: unknown allocator %s "
+					   "specified\n", pcpu_chosen_alloc);
+			if (ret < 0)
+				pr_warning("PERCPU: %s allocator failed (%zd), "
+					   "falling back to 4k\n",
+					   pcpu_chosen_alloc, ret);
+		}
+	} else {
+		ret = setup_pcpu_lpage(static_size, false);
+		if (ret < 0)
+			ret = setup_pcpu_embed(static_size, false);
+	}
 	if (ret < 0)
 		ret = setup_pcpu_4k(static_size);
 	if (ret < 0)
@@ -425,6 +530,14 @@
 	early_per_cpu_ptr(x86_cpu_to_node_map) = NULL;
 #endif
 
+#if defined(CONFIG_X86_64) && defined(CONFIG_NUMA)
+	/*
+	 * make sure boot cpu node_number is right, when boot cpu is on the
+	 * node that doesn't have mem installed
+	 */
+	per_cpu(node_number, boot_cpu_id) = cpu_to_node(boot_cpu_id);
+#endif
+
 	/* Setup node to cpumask map */
 	setup_node_to_cpumask_map();
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/signal.c linux-libre-2.6.31-gnu/arch/x86/kernel/signal.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/signal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/signal.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,7 +6,6 @@
  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  *  2000-2002   x86-64 support by Andi Kleen
  */
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -25,11 +24,11 @@
 #include <asm/ucontext.h>
 #include <asm/i387.h>
 #include <asm/vdso.h>
+#include <asm/mce.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/proto.h>
 #include <asm/ia32_unistd.h>
-#include <asm/mce.h>
 #endif /* CONFIG_X86_64 */
 
 #include <asm/syscall.h>
@@ -857,10 +856,10 @@
 void
 do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 {
-#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
+#ifdef CONFIG_X86_NEW_MCE
 	/* notify userspace of pending MCEs */
 	if (thread_info_flags & _TIF_MCE_NOTIFY)
-		mce_notify_user();
+		mce_notify_process();
 #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
 
 	/* deal with pending signal delivery */
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/smpboot.c linux-libre-2.6.31-gnu/arch/x86/kernel/smpboot.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/smpboot.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/smpboot.c	2009-09-09 18:13:59.000000000 -0400
@@ -504,7 +504,7 @@
  * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
  * won't ... remember to clear down the APIC, etc later.
  */
-int __devinit
+int __cpuinit
 wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
 {
 	unsigned long send_status, accept_status = 0;
@@ -538,7 +538,7 @@
 	return (send_status | accept_status);
 }
 
-int __devinit
+static int __cpuinit
 wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
 {
 	unsigned long send_status, accept_status = 0;
@@ -822,10 +822,12 @@
 	/* mark "stuck" area as not stuck */
 	*((volatile unsigned long *)trampoline_base) = 0;
 
-	/*
-	 * Cleanup possible dangling ends...
-	 */
-	smpboot_restore_warm_reset_vector();
+	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
+		/*
+		 * Cleanup possible dangling ends...
+		 */
+		smpboot_restore_warm_reset_vector();
+	}
 
 	return boot_error;
 }
@@ -871,7 +873,7 @@
 
 	err = do_boot_cpu(apicid, cpu);
 
-	zap_low_mappings();
+	zap_low_mappings(false);
 	low_mappings = 0;
 #else
 	err = do_boot_cpu(apicid, cpu);
@@ -990,10 +992,12 @@
 	 */
 	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
 	    !cpu_has_apic) {
-		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
-			boot_cpu_physical_apicid);
-		printk(KERN_ERR "... forcing use of dummy APIC emulation."
+		if (!disable_apic) {
+			pr_err("BIOS bug, local APIC #%d not detected!...\n",
+				boot_cpu_physical_apicid);
+			pr_err("... forcing use of dummy APIC emulation."
 				"(tell your hw vendor)\n");
+		}
 		smpboot_clear_io_apic();
 		arch_disable_smp_support();
 		return -1;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/smp.c linux-libre-2.6.31-gnu/arch/x86/kernel/smp.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/smp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/smp.c	2009-09-09 18:13:59.000000000 -0400
@@ -150,14 +150,40 @@
  * this function calls the 'stop' function on all other CPUs in the system.
  */
 
+asmlinkage void smp_reboot_interrupt(void)
+{
+	ack_APIC_irq();
+	irq_enter();
+	stop_this_cpu(NULL);
+	irq_exit();
+}
+
 static void native_smp_send_stop(void)
 {
 	unsigned long flags;
+	unsigned long wait;
 
 	if (reboot_force)
 		return;
 
-	smp_call_function(stop_this_cpu, NULL, 0);
+	/*
+	 * Use an own vector here because smp_call_function
+	 * does lots of things not suitable in a panic situation.
+	 * On most systems we could also use an NMI here,
+	 * but there are a few systems around where NMI
+	 * is problematic so stay with an non NMI for now
+	 * (this implies we cannot stop CPUs spinning with irq off
+	 * currently)
+	 */
+	if (num_online_cpus() > 1) {
+		apic->send_IPI_allbutself(REBOOT_VECTOR);
+
+		/* Don't wait longer than a second */
+		wait = USEC_PER_SEC;
+		while (num_online_cpus() > 1 && wait--)
+			udelay(1);
+	}
+
 	local_irq_save(flags);
 	disable_local_APIC();
 	local_irq_restore(flags);
@@ -172,6 +198,9 @@
 {
 	ack_APIC_irq();
 	inc_irq_stat(irq_resched_count);
+	/*
+	 * KVM uses this interrupt to force a cpu out of guest mode
+	 */
 }
 
 void smp_call_function_interrupt(struct pt_regs *regs)
@@ -193,19 +222,19 @@
 }
 
 struct smp_ops smp_ops = {
-	.smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
-	.smp_prepare_cpus = native_smp_prepare_cpus,
-	.smp_cpus_done = native_smp_cpus_done,
+	.smp_prepare_boot_cpu	= native_smp_prepare_boot_cpu,
+	.smp_prepare_cpus	= native_smp_prepare_cpus,
+	.smp_cpus_done		= native_smp_cpus_done,
 
-	.smp_send_stop = native_smp_send_stop,
-	.smp_send_reschedule = native_smp_send_reschedule,
+	.smp_send_stop		= native_smp_send_stop,
+	.smp_send_reschedule	= native_smp_send_reschedule,
 
-	.cpu_up = native_cpu_up,
-	.cpu_die = native_cpu_die,
-	.cpu_disable = native_cpu_disable,
-	.play_dead = native_play_dead,
+	.cpu_up			= native_cpu_up,
+	.cpu_die		= native_cpu_die,
+	.cpu_disable		= native_cpu_disable,
+	.play_dead		= native_play_dead,
 
-	.send_call_func_ipi = native_send_call_func_ipi,
+	.send_call_func_ipi	= native_send_call_func_ipi,
 	.send_call_func_single_ipi = native_send_call_func_single_ipi,
 };
 EXPORT_SYMBOL_GPL(smp_ops);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/stacktrace.c linux-libre-2.6.31-gnu/arch/x86/kernel/stacktrace.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/stacktrace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/stacktrace.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,7 +20,7 @@
 
 static int save_stack_stack(void *data, char *name)
 {
-	return -1;
+	return 0;
 }
 
 static void save_stack_address(void *data, unsigned long addr, int reliable)
@@ -77,6 +77,13 @@
 }
 EXPORT_SYMBOL_GPL(save_stack_trace);
 
+void save_stack_trace_bp(struct stack_trace *trace, unsigned long bp)
+{
+	dump_trace(current, NULL, NULL, bp, &save_stack_ops, trace);
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
 	dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/syscall_table_32.S linux-libre-2.6.31-gnu/arch/x86/kernel/syscall_table_32.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/syscall_table_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/syscall_table_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -334,3 +334,5 @@
 	.long sys_inotify_init1
 	.long sys_preadv
 	.long sys_pwritev
+	.long sys_rt_tgsigqueueinfo	/* 335 */
+	.long sys_perf_counter_open
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/tlb_uv.c linux-libre-2.6.31-gnu/arch/x86/kernel/tlb_uv.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/tlb_uv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/tlb_uv.c	2009-09-09 18:13:59.000000000 -0400
@@ -711,25 +711,31 @@
 	unsigned long pa;
 	unsigned long m;
 	unsigned long n;
-	unsigned long mmr_image;
 	struct bau_desc *adp;
 	struct bau_desc *ad2;
 
-	adp = (struct bau_desc *)kmalloc_node(16384, GFP_KERNEL, node);
+	/*
+	 * each bau_desc is 64 bytes; there are 8 (UV_ITEMS_PER_DESCRIPTOR)
+	 * per cpu; and up to 32 (UV_ADP_SIZE) cpu's per blade
+	 */
+	adp = (struct bau_desc *)kmalloc_node(sizeof(struct bau_desc)*
+		UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR, GFP_KERNEL, node);
 	BUG_ON(!adp);
 
 	pa = uv_gpa(adp); /* need the real nasid*/
 	n = pa >> uv_nshift;
 	m = pa & uv_mmask;
 
-	mmr_image = uv_read_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE);
-	if (mmr_image) {
-		uv_write_global_mmr64(pnode, (unsigned long)
-				      UVH_LB_BAU_SB_DESCRIPTOR_BASE,
-				      (n << UV_DESC_BASE_PNODE_SHIFT | m));
-	}
+	uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
+			      (n << UV_DESC_BASE_PNODE_SHIFT | m));
 
-	for (i = 0, ad2 = adp; i < UV_ACTIVATION_DESCRIPTOR_SIZE; i++, ad2++) {
+	/*
+	 * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
+	 * cpu even though we only use the first one; one descriptor can
+	 * describe a broadcast to 256 nodes.
+	 */
+	for (i = 0, ad2 = adp; i < (UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR);
+		i++, ad2++) {
 		memset(ad2, 0, sizeof(struct bau_desc));
 		ad2->header.sw_ack_flag = 1;
 		/*
@@ -738,6 +744,7 @@
 		 * note that base_dest_nodeid is actually a nasid.
 		 */
 		ad2->header.base_dest_nodeid = uv_partition_base_pnode << 1;
+		ad2->header.dest_subnodeid = 0x10; /* the LB */
 		ad2->header.command = UV_NET_ENDPOINT_INTD;
 		ad2->header.int_both = 1;
 		/*
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/traps.c linux-libre-2.6.31-gnu/arch/x86/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -45,6 +45,7 @@
 #include <linux/edac.h>
 #endif
 
+#include <asm/kmemcheck.h>
 #include <asm/stacktrace.h>
 #include <asm/processor.h>
 #include <asm/debugreg.h>
@@ -53,6 +54,7 @@
 #include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
+#include <asm/mce.h>
 
 #include <asm/mach_traps.h>
 
@@ -64,8 +66,6 @@
 #include <asm/setup.h>
 #include <asm/traps.h>
 
-#include "cpu/mcheck/mce.h"
-
 asmlinkage int system_call(void);
 
 /* Do we ignore FPU interrupts ? */
@@ -346,6 +346,9 @@
 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
 	show_registers(regs);
 
+	if (panic_on_io_nmi)
+		panic("NMI IOCK error: Not continuing");
+
 	/* Re-enable the IOCK line, wait for a few seconds */
 	reason = (reason & 0xf) | 8;
 	outb(reason, 0x61);
@@ -534,6 +537,10 @@
 
 	get_debugreg(condition, 6);
 
+	/* Catch kmemcheck conditions first of all! */
+	if (condition & DR_STEP && kmemcheck_trap(regs))
+		return;
+
 	/*
 	 * The processor cleared BTF, so don't mark that we need it set.
 	 */
@@ -798,15 +805,15 @@
 
 	return new_kesp;
 }
-#else
+#endif
+
 asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
 {
 }
 
-asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
+asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
 {
 }
-#endif
 
 /*
  * 'math_state_restore()' saves the current math information in the
@@ -839,9 +846,6 @@
 	}
 
 	clts();				/* Allow maths ops (or we recurse) */
-#ifdef CONFIG_X86_32
-	restore_fpu(tsk);
-#else
 	/*
 	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
 	 */
@@ -850,7 +854,7 @@
 		force_sig(SIGSEGV, tsk);
 		return;
 	}
-#endif
+
 	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
 	tsk->fpu_counter++;
 }
@@ -945,8 +949,13 @@
 #endif
 	set_intr_gate(19, &simd_coprocessor_error);
 
+	/* Reserve all the builtin and the syscall vector: */
+	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
+		set_bit(i, used_vectors);
+
 #ifdef CONFIG_IA32_EMULATION
 	set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
+	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
 #endif
 
 #ifdef CONFIG_X86_32
@@ -963,17 +972,9 @@
 	}
 
 	set_system_trap_gate(SYSCALL_VECTOR, &system_call);
-#endif
-
-	/* Reserve all the builtin and the syscall vector: */
-	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
-		set_bit(i, used_vectors);
-
-#ifdef CONFIG_X86_64
-	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
-#else
 	set_bit(SYSCALL_VECTOR, used_vectors);
 #endif
+
 	/*
 	 * Should be a barrier for any external CPU state:
 	 */
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/tsc.c linux-libre-2.6.31-gnu/arch/x86/kernel/tsc.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/tsc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/tsc.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/delay.h>
 #include <linux/clocksource.h>
 #include <linux/percpu.h>
+#include <linux/timex.h>
 
 #include <asm/hpet.h>
 #include <asm/timer.h>
@@ -274,15 +275,20 @@
  * use the TSC value at the transitions to calculate a pretty
  * good value for the TSC frequencty.
  */
+static inline int pit_verify_msb(unsigned char val)
+{
+	/* Ignore LSB */
+	inb(0x42);
+	return inb(0x42) == val;
+}
+
 static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap)
 {
 	int count;
 	u64 tsc = 0;
 
 	for (count = 0; count < 50000; count++) {
-		/* Ignore LSB */
-		inb(0x42);
-		if (inb(0x42) != val)
+		if (!pit_verify_msb(val))
 			break;
 		tsc = get_cycles();
 	}
@@ -335,8 +341,7 @@
 	 * to do that is to just read back the 16-bit counter
 	 * once from the PIT.
 	 */
-	inb(0x42);
-	inb(0x42);
+	pit_verify_msb(0);
 
 	if (pit_expect_msb(0xff, &tsc, &d1)) {
 		for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
@@ -347,8 +352,19 @@
 			 * Iterate until the error is less than 500 ppm
 			 */
 			delta -= tsc;
-			if (d1+d2 < delta >> 11)
-				goto success;
+			if (d1+d2 >= delta >> 11)
+				continue;
+
+			/*
+			 * Check the PIT one more time to verify that
+			 * all TSC reads were stable wrt the PIT.
+			 *
+			 * This also guarantees serialization of the
+			 * last cycle read ('d2') in pit_expect_msb.
+			 */
+			if (!pit_verify_msb(0xfe - i))
+				break;
+			goto success;
 		}
 	}
 	printk("Fast TSC calibration failed\n");
@@ -384,13 +400,13 @@
 {
 	u64 tsc1, tsc2, delta, ref1, ref2;
 	unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
-	unsigned long flags, latch, ms, fast_calibrate, tsc_khz;
+	unsigned long flags, latch, ms, fast_calibrate, hv_tsc_khz;
 	int hpet = is_hpet_enabled(), i, loopmin;
 
-	tsc_khz = get_hypervisor_tsc_freq();
-	if (tsc_khz) {
+	hv_tsc_khz = get_hypervisor_tsc_freq();
+	if (hv_tsc_khz) {
 		printk(KERN_INFO "TSC: Frequency read from the hypervisor\n");
-		return tsc_khz;
+		return hv_tsc_khz;
 	}
 
 	local_irq_save(flags);
@@ -589,22 +605,26 @@
  */
 
 DEFINE_PER_CPU(unsigned long, cyc2ns);
+DEFINE_PER_CPU(unsigned long long, cyc2ns_offset);
 
 static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
 {
-	unsigned long long tsc_now, ns_now;
+	unsigned long long tsc_now, ns_now, *offset;
 	unsigned long flags, *scale;
 
 	local_irq_save(flags);
 	sched_clock_idle_sleep_event();
 
 	scale = &per_cpu(cyc2ns, cpu);
+	offset = &per_cpu(cyc2ns_offset, cpu);
 
 	rdtscll(tsc_now);
 	ns_now = __cycles_2_ns(tsc_now);
 
-	if (cpu_khz)
+	if (cpu_khz) {
 		*scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+		*offset = ns_now - (tsc_now * *scale >> CYC2NS_SCALE_FACTOR);
+	}
 
 	sched_clock_idle_wakeup_event(0);
 	local_irq_restore(flags);
@@ -631,17 +651,15 @@
 				void *data)
 {
 	struct cpufreq_freqs *freq = data;
-	unsigned long *lpj, dummy;
+	unsigned long *lpj;
 
 	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
 		return 0;
 
-	lpj = &dummy;
-	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+	lpj = &boot_cpu_data.loops_per_jiffy;
 #ifdef CONFIG_SMP
+	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
 		lpj = &cpu_data(freq->cpu).loops_per_jiffy;
-#else
-	lpj = &boot_cpu_data.loops_per_jiffy;
 #endif
 
 	if (!ref_freq) {
@@ -710,7 +728,16 @@
 #ifdef CONFIG_X86_64
 static cycle_t __vsyscall_fn vread_tsc(void)
 {
-	cycle_t ret = (cycle_t)vget_cycles();
+	cycle_t ret;
+
+	/*
+	 * Surround the RDTSC by barriers, to make sure it's not
+	 * speculated to outside the seqlock critical section and
+	 * does not cause time warps:
+	 */
+	rdtsc_barrier();
+	ret = (cycle_t)vget_cycles();
+	rdtsc_barrier();
 
 	return ret >= __vsyscall_gtod_data.clock.cycle_last ?
 		ret : __vsyscall_gtod_data.clock.cycle_last;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/tsc_sync.c linux-libre-2.6.31-gnu/arch/x86/kernel/tsc_sync.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/tsc_sync.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/tsc_sync.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,6 +34,7 @@
  * of a critical section, to be able to prove TSC time-warps:
  */
 static __cpuinitdata raw_spinlock_t sync_lock = __RAW_SPIN_LOCK_UNLOCKED;
+
 static __cpuinitdata cycles_t last_tsc;
 static __cpuinitdata cycles_t max_warp;
 static __cpuinitdata int nr_warps;
@@ -113,13 +114,12 @@
 		return;
 
 	if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
-		printk(KERN_INFO
-		       "Skipping synchronization checks as TSC is reliable.\n");
+		pr_info("Skipping synchronization checks as TSC is reliable.\n");
 		return;
 	}
 
-	printk(KERN_INFO "checking TSC synchronization [CPU#%d -> CPU#%d]:",
-			  smp_processor_id(), cpu);
+	pr_info("checking TSC synchronization [CPU#%d -> CPU#%d]:",
+		smp_processor_id(), cpu);
 
 	/*
 	 * Reset it - in case this is a second bootup:
@@ -143,8 +143,8 @@
 
 	if (nr_warps) {
 		printk("\n");
-		printk(KERN_WARNING "Measured %Ld cycles TSC warp between CPUs,"
-				    " turning off TSC clock.\n", max_warp);
+		pr_warning("Measured %Ld cycles TSC warp between CPUs, "
+			   "turning off TSC clock.\n", max_warp);
 		mark_tsc_unstable("check_tsc_sync_source failed");
 	} else {
 		printk(" passed.\n");
@@ -195,5 +195,3 @@
 	while (atomic_read(&stop_count) != cpus)
 		cpu_relax();
 }
-#undef NR_LOOPS
-
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/vm86_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/vm86_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/vm86_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/vm86_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -287,10 +287,9 @@
 	info->regs.pt.ds = 0;
 	info->regs.pt.es = 0;
 	info->regs.pt.fs = 0;
-
-/* we are clearing gs later just before "jmp resume_userspace",
- * because it is not saved/restored.
- */
+#ifndef CONFIG_X86_32_LAZY_GS
+	info->regs.pt.gs = 0;
+#endif
 
 /*
  * The flags register is also special: we cannot trust that the user
@@ -318,9 +317,9 @@
 	}
 
 /*
- * Save old state, set default return value (%ax) to 0
+ * Save old state, set default return value (%ax) to 0 (VM86_SIGNAL)
  */
-	info->regs32->ax = 0;
+	info->regs32->ax = VM86_SIGNAL;
 	tsk->thread.saved_sp0 = tsk->thread.sp0;
 	tsk->thread.saved_fs = info->regs32->fs;
 	tsk->thread.saved_gs = get_user_gs(info->regs32);
@@ -343,7 +342,9 @@
 	__asm__ __volatile__(
 		"movl %0,%%esp\n\t"
 		"movl %1,%%ebp\n\t"
+#ifdef CONFIG_X86_32_LAZY_GS
 		"mov  %2, %%gs\n\t"
+#endif
 		"jmp resume_userspace"
 		: /* no outputs */
 		:"r" (&info->regs), "r" (task_thread_info(tsk)), "r" (0));
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/vmi_32.c linux-libre-2.6.31-gnu/arch/x86/kernel/vmi_32.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/vmi_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/vmi_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -441,7 +441,7 @@
 	ap.ds = __USER_DS;
 	ap.es = __USER_DS;
 	ap.fs = __KERNEL_PERCPU;
-	ap.gs = 0;
+	ap.gs = __KERNEL_STACK_CANARY;
 
 	ap.eflags = 0;
 
@@ -462,22 +462,28 @@
 }
 #endif
 
-static void vmi_enter_lazy_cpu(void)
+static void vmi_start_context_switch(struct task_struct *prev)
 {
-	paravirt_enter_lazy_cpu();
+	paravirt_start_context_switch(prev);
 	vmi_ops.set_lazy_mode(2);
 }
 
+static void vmi_end_context_switch(struct task_struct *next)
+{
+	vmi_ops.set_lazy_mode(0);
+	paravirt_end_context_switch(next);
+}
+
 static void vmi_enter_lazy_mmu(void)
 {
 	paravirt_enter_lazy_mmu();
 	vmi_ops.set_lazy_mode(1);
 }
 
-static void vmi_leave_lazy(void)
+static void vmi_leave_lazy_mmu(void)
 {
-	paravirt_leave_lazy(paravirt_get_lazy_mode());
 	vmi_ops.set_lazy_mode(0);
+	paravirt_leave_lazy_mmu();
 }
 
 static inline int __init check_vmi_rom(struct vrom_header *rom)
@@ -711,14 +717,14 @@
 	para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
 	para_fill(pv_cpu_ops.io_delay, IODelay);
 
-	para_wrap(pv_cpu_ops.lazy_mode.enter, vmi_enter_lazy_cpu,
+	para_wrap(pv_cpu_ops.start_context_switch, vmi_start_context_switch,
 		  set_lazy_mode, SetLazyMode);
-	para_wrap(pv_cpu_ops.lazy_mode.leave, vmi_leave_lazy,
+	para_wrap(pv_cpu_ops.end_context_switch, vmi_end_context_switch,
 		  set_lazy_mode, SetLazyMode);
 
 	para_wrap(pv_mmu_ops.lazy_mode.enter, vmi_enter_lazy_mmu,
 		  set_lazy_mode, SetLazyMode);
-	para_wrap(pv_mmu_ops.lazy_mode.leave, vmi_leave_lazy,
+	para_wrap(pv_mmu_ops.lazy_mode.leave, vmi_leave_lazy_mmu,
 		  set_lazy_mode, SetLazyMode);
 
 	/* user and kernel flush are just handled with different flags to FlushTLB */
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/vmlinux_32.lds.S linux-libre-2.6.31-gnu/arch/x86/kernel/vmlinux_32.lds.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/vmlinux_32.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/vmlinux_32.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,229 +0,0 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- *
- * Don't define absolute symbols until and unless you know that symbol
- * value is should remain constant even if kernel image is relocated
- * at run time. Absolute symbols are not relocated. If symbol value should
- * change if kernel is relocated, make the symbol section relative and
- * put it inside the section definition.
- */
-
-#define LOAD_OFFSET __PAGE_OFFSET
-
-#include <asm-generic/vmlinux.lds.h>
-#include <asm/thread_info.h>
-#include <asm/page_types.h>
-#include <asm/cache.h>
-#include <asm/boot.h>
-
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(phys_startup_32)
-jiffies = jiffies_64;
-
-PHDRS {
-	text PT_LOAD FLAGS(5);	/* R_E */
-	data PT_LOAD FLAGS(7);	/* RWE */
-	note PT_NOTE FLAGS(0);	/* ___ */
-}
-SECTIONS
-{
-  . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
-  phys_startup_32 = startup_32 - LOAD_OFFSET;
-
-  .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) {
-  	_text = .;			/* Text and read-only data */
-	*(.text.head)
-  } :text = 0x9090
-
-  /* read-only */
-  .text : AT(ADDR(.text) - LOAD_OFFSET) {
-	. = ALIGN(PAGE_SIZE); /* not really needed, already page aligned */
-	*(.text.page_aligned)
-	TEXT_TEXT
-	SCHED_TEXT
-	LOCK_TEXT
-	KPROBES_TEXT
-	IRQENTRY_TEXT
-	*(.fixup)
-	*(.gnu.warning)
-  	_etext = .;			/* End of text section */
-  } :text = 0x9090
-
-  NOTES :text :note
-
-  . = ALIGN(16);		/* Exception table */
-  __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
-  	__start___ex_table = .;
-	 *(__ex_table)
-  	__stop___ex_table = .;
-  } :text = 0x9090
-
-  RODATA
-
-  /* writeable */
-  . = ALIGN(PAGE_SIZE);
-  .data : AT(ADDR(.data) - LOAD_OFFSET) {	/* Data */
-	DATA_DATA
-	CONSTRUCTORS
-	} :data
-
-  . = ALIGN(PAGE_SIZE);
-  .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
-  	__nosave_begin = .;
-	*(.data.nosave)
-  	. = ALIGN(PAGE_SIZE);
-  	__nosave_end = .;
-  }
-
-  . = ALIGN(PAGE_SIZE);
-  .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
-	*(.data.page_aligned)
-	*(.data.idt)
-  }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
-	*(.data.cacheline_aligned)
-  }
-
-  /* rarely changed data like cpu maps */
-  . = ALIGN(32);
-  .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
-	*(.data.read_mostly)
-	_edata = .;		/* End of data section */
-  }
-
-  . = ALIGN(THREAD_SIZE);	/* init_task */
-  .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
-	*(.data.init_task)
-  }
-
-  /* might get freed after init */
-  . = ALIGN(PAGE_SIZE);
-  .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
-  	__smp_locks = .;
-	*(.smp_locks)
-	__smp_locks_end = .;
-  }
-  /* will be freed after init
-   * Following ALIGN() is required to make sure no other data falls on the
-   * same page where __smp_alt_end is pointing as that page might be freed
-   * after boot. Always make sure that ALIGN() directive is present after
-   * the section which contains __smp_alt_end.
-   */
-  . = ALIGN(PAGE_SIZE);
-
-  /* will be freed after init */
-  . = ALIGN(PAGE_SIZE);		/* Init code and data */
-  .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
-  	__init_begin = .;
-	_sinittext = .;
-	INIT_TEXT
-	_einittext = .;
-  }
-  .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
-	INIT_DATA
-  }
-  . = ALIGN(16);
-  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
-  	__setup_start = .;
-	*(.init.setup)
-  	__setup_end = .;
-   }
-  .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
-  	__initcall_start = .;
-	INITCALLS
-  	__initcall_end = .;
-  }
-  .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
-  	__con_initcall_start = .;
-	*(.con_initcall.init)
-  	__con_initcall_end = .;
-  }
-  .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
-	__x86_cpu_dev_start = .;
-	*(.x86_cpu_dev.init)
-	__x86_cpu_dev_end = .;
-  }
-  SECURITY_INIT
-  . = ALIGN(4);
-  .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
-  	__alt_instructions = .;
-	*(.altinstructions)
-	__alt_instructions_end = .;
-  }
-  .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
-	*(.altinstr_replacement)
-  }
-  . = ALIGN(4);
-  .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
-  	__parainstructions = .;
-	*(.parainstructions)
-  	__parainstructions_end = .;
-  }
-  /* .exit.text is discard at runtime, not link time, to deal with references
-     from .altinstructions and .eh_frame */
-  .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
-	EXIT_TEXT
-  }
-  .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
-	EXIT_DATA
-  }
-#if defined(CONFIG_BLK_DEV_INITRD)
-  . = ALIGN(PAGE_SIZE);
-  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
-	__initramfs_start = .;
-	*(.init.ramfs)
-	__initramfs_end = .;
-  }
-#endif
-  PERCPU(PAGE_SIZE)
-  . = ALIGN(PAGE_SIZE);
-  /* freed after init ends here */
-
-  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
-	__init_end = .;
-	__bss_start = .;		/* BSS */
-	*(.bss.page_aligned)
-	*(.bss)
-	. = ALIGN(4);
-	__bss_stop = .;
-  }
-
-  .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
-	. = ALIGN(PAGE_SIZE);
-	__brk_base = . ;
- 	. += 64 * 1024 ;	/* 64k alignment slop space */
-	*(.brk_reservation)	/* areas brk users have reserved */
-	__brk_limit = . ;
-  }
-
-  .end : AT(ADDR(.end) - LOAD_OFFSET) {
-	_end = . ;
-  }
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-	*(.exitcall.exit)
-	*(.discard)
-	}
-
-  STABS_DEBUG
-
-  DWARF_DEBUG
-}
-
-/*
- * Build-time check on the image size:
- */
-ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
-	"kernel image bigger than KERNEL_IMAGE_SIZE")
-
-#ifdef CONFIG_KEXEC
-/* Link time checks */
-#include <asm/kexec.h>
-
-ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
-       "kexec control code size is too big")
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/vmlinux_64.lds.S linux-libre-2.6.31-gnu/arch/x86/kernel/vmlinux_64.lds.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/vmlinux_64.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/vmlinux_64.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,298 +0,0 @@
-/* ld script to make x86-64 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-
-#define LOAD_OFFSET __START_KERNEL_map
-
-#include <asm-generic/vmlinux.lds.h>
-#include <asm/asm-offsets.h>
-#include <asm/page_types.h>
-
-#undef i386	/* in case the preprocessor is a 32bit one */
-
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-OUTPUT_ARCH(i386:x86-64)
-ENTRY(phys_startup_64)
-jiffies_64 = jiffies;
-PHDRS {
-	text PT_LOAD FLAGS(5);	/* R_E */
-	data PT_LOAD FLAGS(7);	/* RWE */
-	user PT_LOAD FLAGS(7);	/* RWE */
-	data.init PT_LOAD FLAGS(7);	/* RWE */
-#ifdef CONFIG_SMP
-	percpu PT_LOAD FLAGS(7);	/* RWE */
-#endif
-	data.init2 PT_LOAD FLAGS(7);	/* RWE */
-	note PT_NOTE FLAGS(0);	/* ___ */
-}
-SECTIONS
-{
-  . = __START_KERNEL;
-  phys_startup_64 = startup_64 - LOAD_OFFSET;
-  .text :  AT(ADDR(.text) - LOAD_OFFSET) {
-	_text = .;			/* Text and read-only data */
-	/* First the code that has to be first for bootstrapping */
-	*(.text.head)
-	_stext = .;
-	/* Then the rest */
-	TEXT_TEXT
-	SCHED_TEXT
-	LOCK_TEXT
-	KPROBES_TEXT
-	IRQENTRY_TEXT
-	*(.fixup)
-	*(.gnu.warning)
-	_etext = .;		/* End of text section */
-  } :text = 0x9090
-
-  NOTES :text :note
-
-  . = ALIGN(16);		/* Exception table */
-  __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
-  	__start___ex_table = .;
-	 *(__ex_table)
-  	__stop___ex_table = .;
-  } :text = 0x9090
-
-  RODATA
-
-  . = ALIGN(PAGE_SIZE);		/* Align data segment to page size boundary */
-				/* Data */
-  .data : AT(ADDR(.data) - LOAD_OFFSET) {
-	DATA_DATA
-	CONSTRUCTORS
-	_edata = .;			/* End of data section */
-	} :data
-
-
-  .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
-	. = ALIGN(PAGE_SIZE);
-	. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-	*(.data.cacheline_aligned)
-  }
-  . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
-  .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
-  	*(.data.read_mostly)
-  }
-
-#define VSYSCALL_ADDR (-10*1024*1024)
-#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095))
-#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095))
-
-#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
-#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
-
-#define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR)
-#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
-
-  . = VSYSCALL_ADDR;
-  .vsyscall_0 :	 AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
-  __vsyscall_0 = VSYSCALL_VIRT_ADDR;
-
-  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .vsyscall_fn : AT(VLOAD(.vsyscall_fn)) { *(.vsyscall_fn) }
-  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data))
-		{ *(.vsyscall_gtod_data) }
-  vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
-  .vsyscall_clock : AT(VLOAD(.vsyscall_clock))
-		{ *(.vsyscall_clock) }
-  vsyscall_clock = VVIRT(.vsyscall_clock);
-
-
-  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
-		{ *(.vsyscall_1) }
-  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2))
-		{ *(.vsyscall_2) }
-
-  .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
-  vgetcpu_mode = VVIRT(.vgetcpu_mode);
-
-  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
-  jiffies = VVIRT(.jiffies);
-
-  .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3))
-		{ *(.vsyscall_3) }
-
-  . = VSYSCALL_VIRT_ADDR + PAGE_SIZE;
-
-#undef VSYSCALL_ADDR
-#undef VSYSCALL_PHYS_ADDR
-#undef VSYSCALL_VIRT_ADDR
-#undef VLOAD_OFFSET
-#undef VLOAD
-#undef VVIRT_OFFSET
-#undef VVIRT
-
-  .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
-	. = ALIGN(THREAD_SIZE);	/* init_task */
-	*(.data.init_task)
-  }:data.init
-
-  .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
-	. = ALIGN(PAGE_SIZE);
-	*(.data.page_aligned)
-  }
-
-  .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
-	/* might get freed after init */
-	. = ALIGN(PAGE_SIZE);
-	__smp_alt_begin = .;
-	__smp_locks = .;
-	*(.smp_locks)
-	__smp_locks_end = .;
-	. = ALIGN(PAGE_SIZE);
-	__smp_alt_end = .;
-  }
-
-  . = ALIGN(PAGE_SIZE);		/* Init code and data */
-  __init_begin = .;	/* paired with __init_end */
-  .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
-	_sinittext = .;
-	INIT_TEXT
-	_einittext = .;
-  }
-  .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
-	__initdata_begin = .;
-	INIT_DATA
-	__initdata_end = .;
-   }
-
-  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
-	. = ALIGN(16);
-	__setup_start = .;
-	*(.init.setup)
-	__setup_end = .;
-  }
-  .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
-	__initcall_start = .;
-	INITCALLS
-	__initcall_end = .;
-  }
-  .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
-	__con_initcall_start = .;
-	*(.con_initcall.init)
-	__con_initcall_end = .;
-  }
-  .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
-	__x86_cpu_dev_start = .;
-	*(.x86_cpu_dev.init)
-	__x86_cpu_dev_end = .;
-  }
-  SECURITY_INIT
-
-  . = ALIGN(8);
-  .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
-	__parainstructions = .;
-       *(.parainstructions)
-	__parainstructions_end = .;
-  }
-
-  .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
-	. = ALIGN(8);
-	__alt_instructions = .;
-	*(.altinstructions)
-	__alt_instructions_end = .;
-  }
-  .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
-	*(.altinstr_replacement)
-  }
-  /* .exit.text is discard at runtime, not link time, to deal with references
-     from .altinstructions and .eh_frame */
-  .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
-	EXIT_TEXT
-  }
-  .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
-	EXIT_DATA
-  }
-
-#ifdef CONFIG_BLK_DEV_INITRD
-  . = ALIGN(PAGE_SIZE);
-  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
-	__initramfs_start = .;
-	*(.init.ramfs)
-	__initramfs_end = .;
-  }
-#endif
-
-#ifdef CONFIG_SMP
-  /*
-   * percpu offsets are zero-based on SMP.  PERCPU_VADDR() changes the
-   * output PHDR, so the next output section - __data_nosave - should
-   * start another section data.init2.  Also, pda should be at the head of
-   * percpu area.  Preallocate it and define the percpu offset symbol
-   * so that it can be accessed as a percpu variable.
-   */
-  . = ALIGN(PAGE_SIZE);
-  PERCPU_VADDR(0, :percpu)
-#else
-  PERCPU(PAGE_SIZE)
-#endif
-
-  . = ALIGN(PAGE_SIZE);
-  __init_end = .;
-
-  .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
-	. = ALIGN(PAGE_SIZE);
-	__nosave_begin = .;
-	*(.data.nosave)
-	. = ALIGN(PAGE_SIZE);
-	__nosave_end = .;
-  } :data.init2 /* use another section data.init2, see PERCPU_VADDR() above */
-
-  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
-	. = ALIGN(PAGE_SIZE);
-	__bss_start = .;		/* BSS */
-	*(.bss.page_aligned)
-	*(.bss)
-	__bss_stop = .;
-  }
-
-  .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
-	. = ALIGN(PAGE_SIZE);
-	__brk_base = . ;
- 	. += 64 * 1024 ;	/* 64k alignment slop space */
-	*(.brk_reservation)	/* areas brk users have reserved */
-	__brk_limit = . ;
-  }
-
-  _end = . ;
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-	*(.exitcall.exit)
-	*(.eh_frame)
-	*(.discard)
-	}
-
-  STABS_DEBUG
-
-  DWARF_DEBUG
-}
-
- /*
-  * Per-cpu symbols which need to be offset from __per_cpu_load
-  * for the boot processor.
-  */
-#define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load
-INIT_PER_CPU(gdt_page);
-INIT_PER_CPU(irq_stack_union);
-
-/*
- * Build-time check on the image size:
- */
-ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
-	"kernel image bigger than KERNEL_IMAGE_SIZE")
-
-#ifdef CONFIG_SMP
-ASSERT((per_cpu__irq_stack_union == 0),
-        "irq_stack_union is not at start of per-cpu area");
-#endif
-
-#ifdef CONFIG_KEXEC
-#include <asm/kexec.h>
-
-ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
-       "kexec control code size is too big")
-#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/vmlinux.lds.S linux-libre-2.6.31-gnu/arch/x86/kernel/vmlinux.lds.S
--- linux-libre-2.6.30-gnu/arch/x86/kernel/vmlinux.lds.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/vmlinux.lds.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,394 @@
+/*
+ * ld script for the x86 kernel
+ *
+ * Historic 32-bit version written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * Modernisation, unification and other changes and fixes:
+ *   Copyright (C) 2007-2009  Sam Ravnborg <sam@ravnborg.org>
+ *
+ *
+ * Don't define absolute symbols until and unless you know that symbol
+ * value is should remain constant even if kernel image is relocated
+ * at run time. Absolute symbols are not relocated. If symbol value should
+ * change if kernel is relocated, make the symbol section relative and
+ * put it inside the section definition.
+ */
+
 #ifdef CONFIG_X86_32
-# include "vmlinux_32.lds.S"
+#define LOAD_OFFSET __PAGE_OFFSET
 #else
-# include "vmlinux_64.lds.S"
+#define LOAD_OFFSET __START_KERNEL_map
+#endif
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page_types.h>
+#include <asm/cache.h>
+#include <asm/boot.h>
+
+#undef i386     /* in case the preprocessor is a 32bit one */
+
+OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT)
+
+#ifdef CONFIG_X86_32
+OUTPUT_ARCH(i386)
+ENTRY(phys_startup_32)
+jiffies = jiffies_64;
+#else
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(phys_startup_64)
+jiffies_64 = jiffies;
+#endif
+
+PHDRS {
+	text PT_LOAD FLAGS(5);          /* R_E */
+	data PT_LOAD FLAGS(7);          /* RWE */
+#ifdef CONFIG_X86_64
+	user PT_LOAD FLAGS(7);          /* RWE */
+#ifdef CONFIG_SMP
+	percpu PT_LOAD FLAGS(7);        /* RWE */
 #endif
+	init PT_LOAD FLAGS(7);          /* RWE */
+#endif
+	note PT_NOTE FLAGS(0);          /* ___ */
+}
+
+SECTIONS
+{
+#ifdef CONFIG_X86_32
+        . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
+        phys_startup_32 = startup_32 - LOAD_OFFSET;
+#else
+        . = __START_KERNEL;
+        phys_startup_64 = startup_64 - LOAD_OFFSET;
+#endif
+
+	/* Text and read-only data */
+
+	/* bootstrapping code */
+	.text.head : AT(ADDR(.text.head) - LOAD_OFFSET) {
+		_text = .;
+		*(.text.head)
+	} :text = 0x9090
+
+	/* The rest of the text */
+	.text :  AT(ADDR(.text) - LOAD_OFFSET) {
+#ifdef CONFIG_X86_32
+		/* not really needed, already page aligned */
+		. = ALIGN(PAGE_SIZE);
+		*(.text.page_aligned)
+#endif
+		. = ALIGN(8);
+		_stext = .;
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		IRQENTRY_TEXT
+		*(.fixup)
+		*(.gnu.warning)
+		/* End of text section */
+		_etext = .;
+	} :text = 0x9090
+
+	NOTES :text :note
+
+	/* Exception table */
+	. = ALIGN(16);
+	__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+		__start___ex_table = .;
+		*(__ex_table)
+		__stop___ex_table = .;
+	} :text = 0x9090
+
+	RO_DATA(PAGE_SIZE)
+
+	/* Data */
+	.data : AT(ADDR(.data) - LOAD_OFFSET) {
+		/* Start of data section */
+		_sdata = .;
+
+		/* init_task */
+		INIT_TASK_DATA(THREAD_SIZE)
+
+#ifdef CONFIG_X86_32
+		/* 32 bit has nosave before _edata */
+		NOSAVE_DATA
+#endif
+
+		PAGE_ALIGNED_DATA(PAGE_SIZE)
+		*(.data.idt)
+
+		CACHELINE_ALIGNED_DATA(CONFIG_X86_L1_CACHE_BYTES)
+
+		DATA_DATA
+		CONSTRUCTORS
+
+		/* rarely changed data like cpu maps */
+		READ_MOSTLY_DATA(CONFIG_X86_INTERNODE_CACHE_BYTES)
+
+		/* End of data section */
+		_edata = .;
+	} :data
+
+#ifdef CONFIG_X86_64
+
+#define VSYSCALL_ADDR (-10*1024*1024)
+#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data) + SIZEOF(.data) + \
+                            PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
+#define VSYSCALL_VIRT_ADDR ((ADDR(.data) + SIZEOF(.data) + \
+                            PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
+
+#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
+#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
+
+#define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR)
+#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
+
+	. = VSYSCALL_ADDR;
+	.vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) {
+		*(.vsyscall_0)
+	} :user
+
+	__vsyscall_0 = VSYSCALL_VIRT_ADDR;
+
+	. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+	.vsyscall_fn : AT(VLOAD(.vsyscall_fn)) {
+		*(.vsyscall_fn)
+	}
+
+	. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+	.vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data)) {
+		*(.vsyscall_gtod_data)
+	}
+
+	vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data);
+	.vsyscall_clock : AT(VLOAD(.vsyscall_clock)) {
+		*(.vsyscall_clock)
+	}
+	vsyscall_clock = VVIRT(.vsyscall_clock);
+
+
+	.vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) {
+		*(.vsyscall_1)
+	}
+	.vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) {
+		*(.vsyscall_2)
+	}
+
+	.vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) {
+		*(.vgetcpu_mode)
+	}
+	vgetcpu_mode = VVIRT(.vgetcpu_mode);
+
+	. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+	.jiffies : AT(VLOAD(.jiffies)) {
+		*(.jiffies)
+	}
+	jiffies = VVIRT(.jiffies);
+
+	.vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) {
+		*(.vsyscall_3)
+	}
+
+	. = VSYSCALL_VIRT_ADDR + PAGE_SIZE;
+
+#undef VSYSCALL_ADDR
+#undef VSYSCALL_PHYS_ADDR
+#undef VSYSCALL_VIRT_ADDR
+#undef VLOAD_OFFSET
+#undef VLOAD
+#undef VVIRT_OFFSET
+#undef VVIRT
+
+#endif /* CONFIG_X86_64 */
+
+	/* Init code and data - will be freed after init */
+	. = ALIGN(PAGE_SIZE);
+	.init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
+		__init_begin = .; /* paired with __init_end */
+	}
+
+#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
+	/*
+	 * percpu offsets are zero-based on SMP.  PERCPU_VADDR() changes the
+	 * output PHDR, so the next output section - .init.text - should
+	 * start another segment - init.
+	 */
+	PERCPU_VADDR(0, :percpu)
+#endif
+
+	.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
+		_sinittext = .;
+		INIT_TEXT
+		_einittext = .;
+	}
+#ifdef CONFIG_X86_64
+	:init
+#endif
+
+	.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
+		INIT_DATA
+	}
+
+	. = ALIGN(16);
+	.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+		__setup_start = .;
+		*(.init.setup)
+		__setup_end = .;
+	}
+	.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+		__initcall_start = .;
+		INITCALLS
+		__initcall_end = .;
+	}
+
+	.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+		__con_initcall_start = .;
+		*(.con_initcall.init)
+		__con_initcall_end = .;
+	}
+
+	.x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
+		__x86_cpu_dev_start = .;
+		*(.x86_cpu_dev.init)
+		__x86_cpu_dev_end = .;
+	}
+
+	SECURITY_INIT
+
+	. = ALIGN(8);
+	.parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
+		__parainstructions = .;
+		*(.parainstructions)
+		__parainstructions_end = .;
+	}
+
+	. = ALIGN(8);
+	.altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+		__alt_instructions = .;
+		*(.altinstructions)
+		__alt_instructions_end = .;
+	}
+
+	.altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
+		*(.altinstr_replacement)
+	}
+
+	/*
+	 * .exit.text is discard at runtime, not link time, to deal with
+	 *  references from .altinstructions and .eh_frame
+	 */
+	.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+		EXIT_TEXT
+	}
+
+	.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
+		EXIT_DATA
+	}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	. = ALIGN(PAGE_SIZE);
+	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+		__initramfs_start = .;
+		*(.init.ramfs)
+		__initramfs_end = .;
+	}
+#endif
+
+#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
+	PERCPU(PAGE_SIZE)
+#endif
+
+	. = ALIGN(PAGE_SIZE);
+
+	/* freed after init ends here */
+	.init.end : AT(ADDR(.init.end) - LOAD_OFFSET) {
+		__init_end = .;
+	}
+
+	/*
+	 * smp_locks might be freed after init
+	 * start/end must be page aligned
+	 */
+	. = ALIGN(PAGE_SIZE);
+	.smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+		__smp_locks = .;
+		*(.smp_locks)
+		__smp_locks_end = .;
+		. = ALIGN(PAGE_SIZE);
+	}
+
+#ifdef CONFIG_X86_64
+	.data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
+		NOSAVE_DATA
+	}
+#endif
+
+	/* BSS */
+	. = ALIGN(PAGE_SIZE);
+	.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+		__bss_start = .;
+		*(.bss.page_aligned)
+		*(.bss)
+		. = ALIGN(4);
+		__bss_stop = .;
+	}
+
+	. = ALIGN(PAGE_SIZE);
+	.brk : AT(ADDR(.brk) - LOAD_OFFSET) {
+		__brk_base = .;
+		. += 64 * 1024;		/* 64k alignment slop space */
+		*(.brk_reservation)	/* areas brk users have reserved */
+		__brk_limit = .;
+	}
+
+	.end : AT(ADDR(.end) - LOAD_OFFSET) {
+		_end = .;
+	}
+
+	/* Sections to be discarded */
+	/DISCARD/ : {
+		*(.exitcall.exit)
+		*(.eh_frame)
+		*(.discard)
+	}
+
+        STABS_DEBUG
+        DWARF_DEBUG
+}
+
+
+#ifdef CONFIG_X86_32
+. = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
+	   "kernel image bigger than KERNEL_IMAGE_SIZE");
+#else
+/*
+ * Per-cpu symbols which need to be offset from __per_cpu_load
+ * for the boot processor.
+ */
+#define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load
+INIT_PER_CPU(gdt_page);
+INIT_PER_CPU(irq_stack_union);
+
+/*
+ * Build-time check on the image size:
+ */
+. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
+	   "kernel image bigger than KERNEL_IMAGE_SIZE");
+
+#ifdef CONFIG_SMP
+. = ASSERT((per_cpu__irq_stack_union == 0),
+           "irq_stack_union is not at start of per-cpu area");
+#endif
+
+#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_KEXEC
+#include <asm/kexec.h>
+
+. = ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
+           "kexec control code size is too big");
+#endif
+
diff -druN linux-libre-2.6.30-gnu/arch/x86/kernel/vsyscall_64.c linux-libre-2.6.31-gnu/arch/x86/kernel/vsyscall_64.c
--- linux-libre-2.6.30-gnu/arch/x86/kernel/vsyscall_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kernel/vsyscall_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -132,15 +132,7 @@
 			return;
 		}
 
-		/*
-		 * Surround the RDTSC by barriers, to make sure it's not
-		 * speculated to outside the seqlock critical section and
-		 * does not cause time warps:
-		 */
-		rdtsc_barrier();
 		now = vread();
-		rdtsc_barrier();
-
 		base = __vsyscall_gtod_data.clock.cycle_last;
 		mask = __vsyscall_gtod_data.clock.mask;
 		mult = __vsyscall_gtod_data.clock.mult;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/i8254.c linux-libre-2.6.31-gnu/arch/x86/kvm/i8254.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/i8254.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/i8254.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,6 +98,40 @@
 	return kvm->arch.vpit->pit_state.channels[channel].gate;
 }
 
+static s64 __kpit_elapsed(struct kvm *kvm)
+{
+	s64 elapsed;
+	ktime_t remaining;
+	struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
+
+	if (!ps->pit_timer.period)
+		return 0;
+
+	/*
+	 * The Counter does not stop when it reaches zero. In
+	 * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to
+	 * the highest count, either FFFF hex for binary counting
+	 * or 9999 for BCD counting, and continues counting.
+	 * Modes 2 and 3 are periodic; the Counter reloads
+	 * itself with the initial count and continues counting
+	 * from there.
+	 */
+	remaining = hrtimer_expires_remaining(&ps->pit_timer.timer);
+	elapsed = ps->pit_timer.period - ktime_to_ns(remaining);
+	elapsed = mod_64(elapsed, ps->pit_timer.period);
+
+	return elapsed;
+}
+
+static s64 kpit_elapsed(struct kvm *kvm, struct kvm_kpit_channel_state *c,
+			int channel)
+{
+	if (channel == 0)
+		return __kpit_elapsed(kvm);
+
+	return ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+}
+
 static int pit_get_count(struct kvm *kvm, int channel)
 {
 	struct kvm_kpit_channel_state *c =
@@ -107,7 +141,7 @@
 
 	WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
 
-	t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+	t = kpit_elapsed(kvm, c, channel);
 	d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
 
 	switch (c->mode) {
@@ -137,7 +171,7 @@
 
 	WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
 
-	t = ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
+	t = kpit_elapsed(kvm, c, channel);
 	d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
 
 	switch (c->mode) {
@@ -193,28 +227,6 @@
 	}
 }
 
-static int __pit_timer_fn(struct kvm_kpit_state *ps)
-{
-	struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
-	struct kvm_kpit_timer *pt = &ps->pit_timer;
-
-	if (!atomic_inc_and_test(&pt->pending))
-		set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
-
-	if (!pt->reinject)
-		atomic_set(&pt->pending, 1);
-
-	if (vcpu0 && waitqueue_active(&vcpu0->wq))
-		wake_up_interruptible(&vcpu0->wq);
-
-	hrtimer_add_expires_ns(&pt->timer, pt->period);
-	pt->scheduled = hrtimer_get_expires_ns(&pt->timer);
-	if (pt->period)
-		ps->channels[0].count_load_time = ktime_get();
-
-	return (pt->period == 0 ? 0 : 1);
-}
-
 int pit_has_pending_timer(struct kvm_vcpu *vcpu)
 {
 	struct kvm_pit *pit = vcpu->kvm->arch.vpit;
@@ -235,21 +247,6 @@
 	spin_unlock(&ps->inject_lock);
 }
 
-static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
-{
-	struct kvm_kpit_state *ps;
-	int restart_timer = 0;
-
-	ps = container_of(data, struct kvm_kpit_state, pit_timer.timer);
-
-	restart_timer = __pit_timer_fn(ps);
-
-	if (restart_timer)
-		return HRTIMER_RESTART;
-	else
-		return HRTIMER_NORESTART;
-}
-
 void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
 {
 	struct kvm_pit *pit = vcpu->kvm->arch.vpit;
@@ -263,15 +260,26 @@
 		hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
 }
 
-static void destroy_pit_timer(struct kvm_kpit_timer *pt)
+static void destroy_pit_timer(struct kvm_timer *pt)
 {
 	pr_debug("pit: execute del timer!\n");
 	hrtimer_cancel(&pt->timer);
 }
 
+static bool kpit_is_periodic(struct kvm_timer *ktimer)
+{
+	struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state,
+						 pit_timer);
+	return ps->is_periodic;
+}
+
+static struct kvm_timer_ops kpit_ops = {
+	.is_periodic = kpit_is_periodic,
+};
+
 static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
 {
-	struct kvm_kpit_timer *pt = &ps->pit_timer;
+	struct kvm_timer *pt = &ps->pit_timer;
 	s64 interval;
 
 	interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
@@ -280,8 +288,14 @@
 
 	/* TODO The new value only affected after the retriggered */
 	hrtimer_cancel(&pt->timer);
-	pt->period = (is_period == 0) ? 0 : interval;
-	pt->timer.function = pit_timer_fn;
+	pt->period = interval;
+	ps->is_periodic = is_period;
+
+	pt->timer.function = kvm_timer_fn;
+	pt->t_ops = &kpit_ops;
+	pt->kvm = ps->pit->kvm;
+	pt->vcpu_id = 0;
+
 	atomic_set(&pt->pending, 0);
 	ps->irq_ack = 1;
 
@@ -298,23 +312,23 @@
 	pr_debug("pit: load_count val is %d, channel is %d\n", val, channel);
 
 	/*
-	 * Though spec said the state of 8254 is undefined after power-up,
-	 * seems some tricky OS like Windows XP depends on IRQ0 interrupt
-	 * when booting up.
-	 * So here setting initialize rate for it, and not a specific number
+	 * The largest possible initial count is 0; this is equivalent
+	 * to 216 for binary counting and 104 for BCD counting.
 	 */
 	if (val == 0)
 		val = 0x10000;
 
-	ps->channels[channel].count_load_time = ktime_get();
 	ps->channels[channel].count = val;
 
-	if (channel != 0)
+	if (channel != 0) {
+		ps->channels[channel].count_load_time = ktime_get();
 		return;
+	}
 
 	/* Two types of timer
 	 * mode 1 is one shot, mode 2 is period, otherwise del timer */
 	switch (ps->channels[0].mode) {
+	case 0:
 	case 1:
         /* FIXME: enhance mode 4 precision */
 	case 4:
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/i8254.h linux-libre-2.6.31-gnu/arch/x86/kvm/i8254.h
--- linux-libre-2.6.30-gnu/arch/x86/kvm/i8254.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/i8254.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,15 +3,6 @@
 
 #include "iodev.h"
 
-struct kvm_kpit_timer {
-	struct hrtimer timer;
-	int irq;
-	s64 period; /* unit: ns */
-	s64 scheduled;
-	atomic_t pending;
-	bool reinject;
-};
-
 struct kvm_kpit_channel_state {
 	u32 count; /* can be 65536 */
 	u16 latched_count;
@@ -30,7 +21,8 @@
 
 struct kvm_kpit_state {
 	struct kvm_kpit_channel_state channels[3];
-	struct kvm_kpit_timer pit_timer;
+	struct kvm_timer pit_timer;
+	bool is_periodic;
 	u32    speaker_data_on;
 	struct mutex lock;
 	struct kvm_pit *pit;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/irq.c linux-libre-2.6.31-gnu/arch/x86/kvm/irq.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 
 #include "irq.h"
 #include "i8254.h"
+#include "x86.h"
 
 /*
  * check if there are pending timer events
@@ -48,6 +49,9 @@
 {
 	struct kvm_pic *s;
 
+	if (!irqchip_in_kernel(v->kvm))
+		return v->arch.interrupt.pending;
+
 	if (kvm_apic_has_interrupt(v) == -1) {	/* LAPIC */
 		if (kvm_apic_accept_pic_intr(v)) {
 			s = pic_irqchip(v->kvm);	/* PIC */
@@ -67,6 +71,9 @@
 	struct kvm_pic *s;
 	int vector;
 
+	if (!irqchip_in_kernel(v->kvm))
+		return v->arch.interrupt.nr;
+
 	vector = kvm_get_apic_interrupt(v);	/* APIC */
 	if (vector == -1) {
 		if (kvm_apic_accept_pic_intr(v)) {
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/Kconfig linux-libre-2.6.31-gnu/arch/x86/kvm/Kconfig
--- linux-libre-2.6.30-gnu/arch/x86/kvm/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,9 @@
 	  Provides support for KVM on Intel processors equipped with the VT
 	  extensions.
 
+	  To compile this as a module, choose M here: the module
+	  will be called kvm-intel.
+
 config KVM_AMD
 	tristate "KVM for AMD processors support"
 	depends on KVM
@@ -57,6 +60,9 @@
 	  Provides support for KVM on AMD processors equipped with the AMD-V
 	  (SVM) extensions.
 
+	  To compile this as a module, choose M here: the module
+	  will be called kvm-amd.
+
 config KVM_TRACE
 	bool "KVM trace support"
 	depends on KVM && SYSFS
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/kvm_timer.h linux-libre-2.6.31-gnu/arch/x86/kvm/kvm_timer.h
--- linux-libre-2.6.30-gnu/arch/x86/kvm/kvm_timer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/kvm_timer.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+
+struct kvm_timer {
+	struct hrtimer timer;
+	s64 period; 				/* unit: ns */
+	atomic_t pending;			/* accumulated triggered timers */
+	bool reinject;
+	struct kvm_timer_ops *t_ops;
+	struct kvm *kvm;
+	int vcpu_id;
+};
+
+struct kvm_timer_ops {
+        bool (*is_periodic)(struct kvm_timer *);
+};
+
+
+enum hrtimer_restart kvm_timer_fn(struct hrtimer *data);
+
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/lapic.c linux-libre-2.6.31-gnu/arch/x86/kvm/lapic.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/lapic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/lapic.c	2009-09-09 18:13:59.000000000 -0400
@@ -196,20 +196,15 @@
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
 
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
+			     int vector, int level, int trig_mode);
+
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (!apic_test_and_set_irr(vec, apic)) {
-		/* a new pending irq is set in IRR */
-		if (trig)
-			apic_set_vector(vec, apic->regs + APIC_TMR);
-		else
-			apic_clear_vector(vec, apic->regs + APIC_TMR);
-		kvm_vcpu_kick(apic->vcpu);
-		return 1;
-	}
-	return 0;
+	return __apic_accept_irq(apic, irq->delivery_mode, irq->vector,
+			irq->level, irq->trig_mode);
 }
 
 static inline int apic_find_highest_isr(struct kvm_lapic *apic)
@@ -250,7 +245,7 @@
 
 int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
 {
-	return kvm_apic_id(apic) == dest;
+	return dest == 0xff || kvm_apic_id(apic) == dest;
 }
 
 int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
@@ -279,37 +274,34 @@
 	return result;
 }
 
-static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
 			   int short_hand, int dest, int dest_mode)
 {
 	int result = 0;
 	struct kvm_lapic *target = vcpu->arch.apic;
 
 	apic_debug("target %p, source %p, dest 0x%x, "
-		   "dest_mode 0x%x, short_hand 0x%x",
+		   "dest_mode 0x%x, short_hand 0x%x\n",
 		   target, source, dest, dest_mode, short_hand);
 
 	ASSERT(!target);
 	switch (short_hand) {
 	case APIC_DEST_NOSHORT:
-		if (dest_mode == 0) {
+		if (dest_mode == 0)
 			/* Physical mode. */
-			if ((dest == 0xFF) || (dest == kvm_apic_id(target)))
-				result = 1;
-		} else
+			result = kvm_apic_match_physical_addr(target, dest);
+		else
 			/* Logical mode. */
 			result = kvm_apic_match_logical_addr(target, dest);
 		break;
 	case APIC_DEST_SELF:
-		if (target == source)
-			result = 1;
+		result = (target == source);
 		break;
 	case APIC_DEST_ALLINC:
 		result = 1;
 		break;
 	case APIC_DEST_ALLBUT:
-		if (target != source)
-			result = 1;
+		result = (target != source);
 		break;
 	default:
 		printk(KERN_WARNING "Bad dest shorthand value %x\n",
@@ -327,20 +319,22 @@
 static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 			     int vector, int level, int trig_mode)
 {
-	int orig_irr, result = 0;
+	int result = 0;
 	struct kvm_vcpu *vcpu = apic->vcpu;
 
 	switch (delivery_mode) {
-	case APIC_DM_FIXED:
 	case APIC_DM_LOWEST:
+		vcpu->arch.apic_arb_prio++;
+	case APIC_DM_FIXED:
 		/* FIXME add logic for vcpu on reset */
 		if (unlikely(!apic_enabled(apic)))
 			break;
 
-		orig_irr = apic_test_and_set_irr(vector, apic);
-		if (orig_irr && trig_mode) {
-			apic_debug("level trig mode repeatedly for vector %d",
-				   vector);
+		result = !apic_test_and_set_irr(vector, apic);
+		if (!result) {
+			if (trig_mode)
+				apic_debug("level trig mode repeatedly for "
+						"vector %d", vector);
 			break;
 		}
 
@@ -349,10 +343,7 @@
 			apic_set_vector(vector, apic->regs + APIC_TMR);
 		} else
 			apic_clear_vector(vector, apic->regs + APIC_TMR);
-
 		kvm_vcpu_kick(vcpu);
-
-		result = (orig_irr == 0);
 		break;
 
 	case APIC_DM_REMRD:
@@ -364,12 +355,14 @@
 		break;
 
 	case APIC_DM_NMI:
+		result = 1;
 		kvm_inject_nmi(vcpu);
 		kvm_vcpu_kick(vcpu);
 		break;
 
 	case APIC_DM_INIT:
 		if (level) {
+			result = 1;
 			if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
 				printk(KERN_DEBUG
 				       "INIT on a runnable vcpu %d\n",
@@ -386,6 +379,7 @@
 		apic_debug("SIPI to vcpu %d vector 0x%02x\n",
 			   vcpu->vcpu_id, vector);
 		if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+			result = 1;
 			vcpu->arch.sipi_vector = vector;
 			vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
 			kvm_vcpu_kick(vcpu);
@@ -408,43 +402,9 @@
 	return result;
 }
 
-static struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
-				       unsigned long bitmap)
-{
-	int last;
-	int next;
-	struct kvm_lapic *apic = NULL;
-
-	last = kvm->arch.round_robin_prev_vcpu;
-	next = last;
-
-	do {
-		if (++next == KVM_MAX_VCPUS)
-			next = 0;
-		if (kvm->vcpus[next] == NULL || !test_bit(next, &bitmap))
-			continue;
-		apic = kvm->vcpus[next]->arch.apic;
-		if (apic && apic_enabled(apic))
-			break;
-		apic = NULL;
-	} while (next != last);
-	kvm->arch.round_robin_prev_vcpu = next;
-
-	if (!apic)
-		printk(KERN_DEBUG "vcpu not ready for apic_round_robin\n");
-
-	return apic;
-}
-
-struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
-		unsigned long bitmap)
+int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2)
 {
-	struct kvm_lapic *apic;
-
-	apic = kvm_apic_round_robin(kvm, vector, bitmap);
-	if (apic)
-		return apic->vcpu;
-	return NULL;
+	return vcpu1->arch.apic_arb_prio - vcpu2->arch.apic_arb_prio;
 }
 
 static void apic_set_eoi(struct kvm_lapic *apic)
@@ -472,47 +432,24 @@
 {
 	u32 icr_low = apic_get_reg(apic, APIC_ICR);
 	u32 icr_high = apic_get_reg(apic, APIC_ICR2);
+	struct kvm_lapic_irq irq;
 
-	unsigned int dest = GET_APIC_DEST_FIELD(icr_high);
-	unsigned int short_hand = icr_low & APIC_SHORT_MASK;
-	unsigned int trig_mode = icr_low & APIC_INT_LEVELTRIG;
-	unsigned int level = icr_low & APIC_INT_ASSERT;
-	unsigned int dest_mode = icr_low & APIC_DEST_MASK;
-	unsigned int delivery_mode = icr_low & APIC_MODE_MASK;
-	unsigned int vector = icr_low & APIC_VECTOR_MASK;
-
-	struct kvm_vcpu *target;
-	struct kvm_vcpu *vcpu;
-	unsigned long lpr_map = 0;
-	int i;
+	irq.vector = icr_low & APIC_VECTOR_MASK;
+	irq.delivery_mode = icr_low & APIC_MODE_MASK;
+	irq.dest_mode = icr_low & APIC_DEST_MASK;
+	irq.level = icr_low & APIC_INT_ASSERT;
+	irq.trig_mode = icr_low & APIC_INT_LEVELTRIG;
+	irq.shorthand = icr_low & APIC_SHORT_MASK;
+	irq.dest_id = GET_APIC_DEST_FIELD(icr_high);
 
 	apic_debug("icr_high 0x%x, icr_low 0x%x, "
 		   "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
 		   "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n",
-		   icr_high, icr_low, short_hand, dest,
-		   trig_mode, level, dest_mode, delivery_mode, vector);
-
-	for (i = 0; i < KVM_MAX_VCPUS; i++) {
-		vcpu = apic->vcpu->kvm->vcpus[i];
-		if (!vcpu)
-			continue;
-
-		if (vcpu->arch.apic &&
-		    apic_match_dest(vcpu, apic, short_hand, dest, dest_mode)) {
-			if (delivery_mode == APIC_DM_LOWEST)
-				set_bit(vcpu->vcpu_id, &lpr_map);
-			else
-				__apic_accept_irq(vcpu->arch.apic, delivery_mode,
-						  vector, level, trig_mode);
-		}
-	}
+		   icr_high, icr_low, irq.shorthand, irq.dest_id,
+		   irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode,
+		   irq.vector);
 
-	if (delivery_mode == APIC_DM_LOWEST) {
-		target = kvm_get_lowest_prio_vcpu(vcpu->kvm, vector, lpr_map);
-		if (target != NULL)
-			__apic_accept_irq(target->arch.apic, delivery_mode,
-					  vector, level, trig_mode);
-	}
+	kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq);
 }
 
 static u32 apic_get_tmcct(struct kvm_lapic *apic)
@@ -527,12 +464,13 @@
 	if (apic_get_reg(apic, APIC_TMICT) == 0)
 		return 0;
 
-	remaining = hrtimer_expires_remaining(&apic->timer.dev);
+	remaining = hrtimer_expires_remaining(&apic->lapic_timer.timer);
 	if (ktime_to_ns(remaining) < 0)
 		remaining = ktime_set(0, 0);
 
-	ns = mod_64(ktime_to_ns(remaining), apic->timer.period);
-	tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
+	ns = mod_64(ktime_to_ns(remaining), apic->lapic_timer.period);
+	tmcct = div64_u64(ns,
+			 (APIC_BUS_CYCLE_NS * apic->divide_count));
 
 	return tmcct;
 }
@@ -619,25 +557,25 @@
 	tdcr = apic_get_reg(apic, APIC_TDCR);
 	tmp1 = tdcr & 0xf;
 	tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
-	apic->timer.divide_count = 0x1 << (tmp2 & 0x7);
+	apic->divide_count = 0x1 << (tmp2 & 0x7);
 
 	apic_debug("timer divide count is 0x%x\n",
-				   apic->timer.divide_count);
+				   apic->divide_count);
 }
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now = apic->timer.dev.base->get_time();
+	ktime_t now = apic->lapic_timer.timer.base->get_time();
 
-	apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
-		    APIC_BUS_CYCLE_NS * apic->timer.divide_count;
-	atomic_set(&apic->timer.pending, 0);
+	apic->lapic_timer.period = apic_get_reg(apic, APIC_TMICT) *
+		    APIC_BUS_CYCLE_NS * apic->divide_count;
+	atomic_set(&apic->lapic_timer.pending, 0);
 
-	if (!apic->timer.period)
+	if (!apic->lapic_timer.period)
 		return;
 
-	hrtimer_start(&apic->timer.dev,
-		      ktime_add_ns(now, apic->timer.period),
+	hrtimer_start(&apic->lapic_timer.timer,
+		      ktime_add_ns(now, apic->lapic_timer.period),
 		      HRTIMER_MODE_ABS);
 
 	apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
@@ -646,9 +584,9 @@
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
 			   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
 			   apic_get_reg(apic, APIC_TMICT),
-			   apic->timer.period,
+			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
-					apic->timer.period)));
+					apic->lapic_timer.period)));
 }
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
@@ -730,7 +668,7 @@
 				apic_set_reg(apic, APIC_LVTT + 0x10 * i,
 					     lvt_val | APIC_LVT_MASKED);
 			}
-			atomic_set(&apic->timer.pending, 0);
+			atomic_set(&apic->lapic_timer.pending, 0);
 
 		}
 		break;
@@ -762,7 +700,7 @@
 		break;
 
 	case APIC_TMICT:
-		hrtimer_cancel(&apic->timer.dev);
+		hrtimer_cancel(&apic->lapic_timer.timer);
 		apic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
 		return;
@@ -802,7 +740,7 @@
 	if (!vcpu->arch.apic)
 		return;
 
-	hrtimer_cancel(&vcpu->arch.apic->timer.dev);
+	hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer);
 
 	if (vcpu->arch.apic->regs_page)
 		__free_page(vcpu->arch.apic->regs_page);
@@ -880,7 +818,7 @@
 	ASSERT(apic != NULL);
 
 	/* Stop the timer in case it's a reset to an active apic */
-	hrtimer_cancel(&apic->timer.dev);
+	hrtimer_cancel(&apic->lapic_timer.timer);
 
 	apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24);
 	apic_set_reg(apic, APIC_LVR, APIC_VERSION);
@@ -905,11 +843,13 @@
 		apic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
 	}
 	update_divide_count(apic);
-	atomic_set(&apic->timer.pending, 0);
+	atomic_set(&apic->lapic_timer.pending, 0);
 	if (vcpu->vcpu_id == 0)
 		vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
 	apic_update_ppr(apic);
 
+	vcpu->arch.apic_arb_prio = 0;
+
 	apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr="
 		   "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
 		   vcpu, kvm_apic_id(apic),
@@ -917,16 +857,14 @@
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_reset);
 
-int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
+bool kvm_apic_present(struct kvm_vcpu *vcpu)
 {
-	struct kvm_lapic *apic = vcpu->arch.apic;
-	int ret = 0;
-
-	if (!apic)
-		return 0;
-	ret = apic_enabled(apic);
+	return vcpu->arch.apic && apic_hw_enabled(vcpu->arch.apic);
+}
 
-	return ret;
+int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
+{
+	return kvm_apic_present(vcpu) && apic_sw_enabled(vcpu->arch.apic);
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_enabled);
 
@@ -936,22 +874,11 @@
  *----------------------------------------------------------------------
  */
 
-/* TODO: make sure __apic_timer_fn runs in current pCPU */
-static int __apic_timer_fn(struct kvm_lapic *apic)
+static bool lapic_is_periodic(struct kvm_timer *ktimer)
 {
-	int result = 0;
-	wait_queue_head_t *q = &apic->vcpu->wq;
-
-	if(!atomic_inc_and_test(&apic->timer.pending))
-		set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
-	if (waitqueue_active(q))
-		wake_up_interruptible(q);
-
-	if (apic_lvtt_period(apic)) {
-		result = 1;
-		hrtimer_add_expires_ns(&apic->timer.dev, apic->timer.period);
-	}
-	return result;
+	struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic,
+					      lapic_timer);
+	return apic_lvtt_period(apic);
 }
 
 int apic_has_pending_timer(struct kvm_vcpu *vcpu)
@@ -959,7 +886,7 @@
 	struct kvm_lapic *lapic = vcpu->arch.apic;
 
 	if (lapic && apic_enabled(lapic) && apic_lvt_enabled(lapic, APIC_LVTT))
-		return atomic_read(&lapic->timer.pending);
+		return atomic_read(&lapic->lapic_timer.pending);
 
 	return 0;
 }
@@ -986,20 +913,9 @@
 		kvm_apic_local_deliver(apic, APIC_LVT0);
 }
 
-static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
-{
-	struct kvm_lapic *apic;
-	int restart_timer = 0;
-
-	apic = container_of(data, struct kvm_lapic, timer.dev);
-
-	restart_timer = __apic_timer_fn(apic);
-
-	if (restart_timer)
-		return HRTIMER_RESTART;
-	else
-		return HRTIMER_NORESTART;
-}
+static struct kvm_timer_ops lapic_timer_ops = {
+	.is_periodic = lapic_is_periodic,
+};
 
 int kvm_create_lapic(struct kvm_vcpu *vcpu)
 {
@@ -1024,8 +940,13 @@
 	memset(apic->regs, 0, PAGE_SIZE);
 	apic->vcpu = vcpu;
 
-	hrtimer_init(&apic->timer.dev, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
-	apic->timer.dev.function = apic_timer_fn;
+	hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_ABS);
+	apic->lapic_timer.timer.function = kvm_timer_fn;
+	apic->lapic_timer.t_ops = &lapic_timer_ops;
+	apic->lapic_timer.kvm = vcpu->kvm;
+	apic->lapic_timer.vcpu_id = vcpu->vcpu_id;
+
 	apic->base_address = APIC_DEFAULT_PHYS_BASE;
 	vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE;
 
@@ -1078,9 +999,9 @@
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (apic && atomic_read(&apic->timer.pending) > 0) {
+	if (apic && atomic_read(&apic->lapic_timer.pending) > 0) {
 		if (kvm_apic_local_deliver(apic, APIC_LVTT))
-			atomic_dec(&apic->timer.pending);
+			atomic_dec(&apic->lapic_timer.pending);
 	}
 }
 
@@ -1106,7 +1027,7 @@
 			     MSR_IA32_APICBASE_BASE;
 	apic_set_reg(apic, APIC_LVR, APIC_VERSION);
 	apic_update_ppr(apic);
-	hrtimer_cancel(&apic->timer.dev);
+	hrtimer_cancel(&apic->lapic_timer.timer);
 	update_divide_count(apic);
 	start_apic_timer(apic);
 }
@@ -1119,7 +1040,7 @@
 	if (!apic)
 		return;
 
-	timer = &apic->timer.dev;
+	timer = &apic->lapic_timer.timer;
 	if (hrtimer_cancel(timer))
 		hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/lapic.h linux-libre-2.6.31-gnu/arch/x86/kvm/lapic.h
--- linux-libre-2.6.30-gnu/arch/x86/kvm/lapic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/lapic.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,18 +2,15 @@
 #define __KVM_X86_LAPIC_H
 
 #include "iodev.h"
+#include "kvm_timer.h"
 
 #include <linux/kvm_host.h>
 
 struct kvm_lapic {
 	unsigned long base_address;
 	struct kvm_io_device dev;
-	struct {
-		atomic_t pending;
-		s64 period;	/* unit: ns */
-		u32 divide_count;
-		struct hrtimer dev;
-	} timer;
+	struct kvm_timer lapic_timer;
+	u32 divide_count;
 	struct kvm_vcpu *vcpu;
 	struct page *regs_page;
 	void *regs;
@@ -34,12 +31,13 @@
 
 int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
 int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
-int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
 
 u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
 void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
 void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
 int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
+bool kvm_apic_present(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/Makefile linux-libre-2.6.31-gnu/arch/x86/kvm/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/kvm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -14,7 +14,7 @@
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
 
 kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \
-	i8254.o
+	i8254.o timer.o
 obj-$(CONFIG_KVM) += kvm.o
 kvm-intel-objs = vmx.o
 obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/mmu.c linux-libre-2.6.31-gnu/arch/x86/kvm/mmu.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/mmu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/mmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -126,6 +126,7 @@
 #define PFERR_PRESENT_MASK (1U << 0)
 #define PFERR_WRITE_MASK (1U << 1)
 #define PFERR_USER_MASK (1U << 2)
+#define PFERR_RSVD_MASK (1U << 3)
 #define PFERR_FETCH_MASK (1U << 4)
 
 #define PT_DIRECTORY_LEVEL 2
@@ -177,7 +178,11 @@
 static u64 __read_mostly shadow_user_mask;
 static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
-static u64 __read_mostly shadow_mt_mask;
+
+static inline u64 rsvd_bits(int s, int e)
+{
+	return ((1ULL << (e - s + 1)) - 1) << s;
+}
 
 void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte)
 {
@@ -193,14 +198,13 @@
 EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes);
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 mt_mask)
+		u64 dirty_mask, u64 nx_mask, u64 x_mask)
 {
 	shadow_user_mask = user_mask;
 	shadow_accessed_mask = accessed_mask;
 	shadow_dirty_mask = dirty_mask;
 	shadow_nx_mask = nx_mask;
 	shadow_x_mask = x_mask;
-	shadow_mt_mask = mt_mask;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
@@ -219,11 +223,6 @@
 	return vcpu->arch.shadow_efer & EFER_NX;
 }
 
-static int is_present_pte(unsigned long pte)
-{
-	return pte & PT_PRESENT_MASK;
-}
-
 static int is_shadow_present_pte(u64 pte)
 {
 	return pte != shadow_trap_nonpresent_pte
@@ -490,16 +489,20 @@
  *
  * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
  * containing more mappings.
+ *
+ * Returns the number of rmap entries before the spte was added or zero if
+ * the spte was not added.
+ *
  */
-static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
+static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
 {
 	struct kvm_mmu_page *sp;
 	struct kvm_rmap_desc *desc;
 	unsigned long *rmapp;
-	int i;
+	int i, count = 0;
 
 	if (!is_rmap_pte(*spte))
-		return;
+		return count;
 	gfn = unalias_gfn(vcpu->kvm, gfn);
 	sp = page_header(__pa(spte));
 	sp->gfns[spte - sp->spt] = gfn;
@@ -516,8 +519,10 @@
 	} else {
 		rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
 		desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
-		while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
+		while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) {
 			desc = desc->more;
+			count += RMAP_EXT;
+		}
 		if (desc->shadow_ptes[RMAP_EXT-1]) {
 			desc->more = mmu_alloc_rmap_desc(vcpu);
 			desc = desc->more;
@@ -526,6 +531,7 @@
 			;
 		desc->shadow_ptes[i] = spte;
 	}
+	return count;
 }
 
 static void rmap_desc_remove_entry(unsigned long *rmapp,
@@ -755,6 +761,19 @@
 	return young;
 }
 
+#define RMAP_RECYCLE_THRESHOLD 1000
+
+static void rmap_recycle(struct kvm_vcpu *vcpu, gfn_t gfn, int lpage)
+{
+	unsigned long *rmapp;
+
+	gfn = unalias_gfn(vcpu->kvm, gfn);
+	rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
+
+	kvm_unmap_rmapp(vcpu->kvm, rmapp);
+	kvm_flush_remote_tlbs(vcpu->kvm);
+}
+
 int kvm_age_hva(struct kvm *kvm, unsigned long hva)
 {
 	return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
@@ -1074,18 +1093,10 @@
 	return NULL;
 }
 
-static void kvm_unlink_unsync_global(struct kvm *kvm, struct kvm_mmu_page *sp)
-{
-	list_del(&sp->oos_link);
-	--kvm->stat.mmu_unsync_global;
-}
-
 static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp)
 {
 	WARN_ON(!sp->unsync);
 	sp->unsync = 0;
-	if (sp->global)
-		kvm_unlink_unsync_global(kvm, sp);
 	--kvm->stat.mmu_unsync;
 }
 
@@ -1248,7 +1259,6 @@
 	pgprintk("%s: adding gfn %lx role %x\n", __func__, gfn, role.word);
 	sp->gfn = gfn;
 	sp->role = role;
-	sp->global = 0;
 	hlist_add_head(&sp->hash_link, bucket);
 	if (!direct) {
 		if (rmap_write_protect(vcpu->kvm, gfn))
@@ -1417,24 +1427,25 @@
  */
 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages)
 {
+	int used_pages;
+
+	used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages;
+	used_pages = max(0, used_pages);
+
 	/*
 	 * If we set the number of mmu pages to be smaller be than the
 	 * number of actived pages , we must to free some mmu pages before we
 	 * change the value
 	 */
 
-	if ((kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages) >
-	    kvm_nr_mmu_pages) {
-		int n_used_mmu_pages = kvm->arch.n_alloc_mmu_pages
-				       - kvm->arch.n_free_mmu_pages;
-
-		while (n_used_mmu_pages > kvm_nr_mmu_pages) {
+	if (used_pages > kvm_nr_mmu_pages) {
+		while (used_pages > kvm_nr_mmu_pages) {
 			struct kvm_mmu_page *page;
 
 			page = container_of(kvm->arch.active_mmu_pages.prev,
 					    struct kvm_mmu_page, link);
 			kvm_mmu_zap_page(kvm, page);
-			n_used_mmu_pages--;
+			used_pages--;
 		}
 		kvm->arch.n_free_mmu_pages = 0;
 	}
@@ -1616,7 +1627,7 @@
 	return mtrr_state->def_type;
 }
 
-static u8 get_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
+u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
 {
 	u8 mtrr;
 
@@ -1626,6 +1637,7 @@
 		mtrr = MTRR_TYPE_WRBACK;
 	return mtrr;
 }
+EXPORT_SYMBOL_GPL(kvm_get_guest_memory_type);
 
 static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
@@ -1646,11 +1658,7 @@
 	++vcpu->kvm->stat.mmu_unsync;
 	sp->unsync = 1;
 
-	if (sp->global) {
-		list_add(&sp->oos_link, &vcpu->kvm->arch.oos_global_pages);
-		++vcpu->kvm->stat.mmu_unsync_global;
-	} else
-		kvm_mmu_mark_parents_unsync(vcpu, sp);
+	kvm_mmu_mark_parents_unsync(vcpu, sp);
 
 	mmu_convert_notrap(sp);
 	return 0;
@@ -1677,21 +1685,11 @@
 static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
 		    unsigned pte_access, int user_fault,
 		    int write_fault, int dirty, int largepage,
-		    int global, gfn_t gfn, pfn_t pfn, bool speculative,
+		    gfn_t gfn, pfn_t pfn, bool speculative,
 		    bool can_unsync)
 {
 	u64 spte;
 	int ret = 0;
-	u64 mt_mask = shadow_mt_mask;
-	struct kvm_mmu_page *sp = page_header(__pa(shadow_pte));
-
-	if (!global && sp->global) {
-		sp->global = 0;
-		if (sp->unsync) {
-			kvm_unlink_unsync_global(vcpu->kvm, sp);
-			kvm_mmu_mark_parents_unsync(vcpu, sp);
-		}
-	}
 
 	/*
 	 * We don't set the accessed bit, since we sometimes want to see
@@ -1711,16 +1709,9 @@
 		spte |= shadow_user_mask;
 	if (largepage)
 		spte |= PT_PAGE_SIZE_MASK;
-	if (mt_mask) {
-		if (!kvm_is_mmio_pfn(pfn)) {
-			mt_mask = get_memory_type(vcpu, gfn) <<
-				kvm_x86_ops->get_mt_mask_shift();
-			mt_mask |= VMX_EPT_IGMT_BIT;
-		} else
-			mt_mask = MTRR_TYPE_UNCACHABLE <<
-				kvm_x86_ops->get_mt_mask_shift();
-		spte |= mt_mask;
-	}
+	if (tdp_enabled)
+		spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn,
+			kvm_is_mmio_pfn(pfn));
 
 	spte |= (u64)pfn << PAGE_SHIFT;
 
@@ -1765,11 +1756,12 @@
 static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
 			 unsigned pt_access, unsigned pte_access,
 			 int user_fault, int write_fault, int dirty,
-			 int *ptwrite, int largepage, int global,
-			 gfn_t gfn, pfn_t pfn, bool speculative)
+			 int *ptwrite, int largepage, gfn_t gfn,
+			 pfn_t pfn, bool speculative)
 {
 	int was_rmapped = 0;
 	int was_writeble = is_writeble_pte(*shadow_pte);
+	int rmap_count;
 
 	pgprintk("%s: spte %llx access %x write_fault %d"
 		 " user_fault %d gfn %lx\n",
@@ -1795,7 +1787,7 @@
 			was_rmapped = 1;
 	}
 	if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault,
-		      dirty, largepage, global, gfn, pfn, speculative, true)) {
+		      dirty, largepage, gfn, pfn, speculative, true)) {
 		if (write_fault)
 			*ptwrite = 1;
 		kvm_x86_ops->tlb_flush(vcpu);
@@ -1811,9 +1803,11 @@
 
 	page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
 	if (!was_rmapped) {
-		rmap_add(vcpu, shadow_pte, gfn, largepage);
+		rmap_count = rmap_add(vcpu, shadow_pte, gfn, largepage);
 		if (!is_rmap_pte(*shadow_pte))
 			kvm_release_pfn_clean(pfn);
+		if (rmap_count > RMAP_RECYCLE_THRESHOLD)
+			rmap_recycle(vcpu, gfn, largepage);
 	} else {
 		if (was_writeble)
 			kvm_release_pfn_dirty(pfn);
@@ -1843,7 +1837,7 @@
 		    || (largepage && iterator.level == PT_DIRECTORY_LEVEL)) {
 			mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL,
 				     0, write, 1, &pt_write,
-				     largepage, 0, gfn, pfn, false);
+				     largepage, gfn, pfn, false);
 			++vcpu->stat.pf_fixed;
 			break;
 		}
@@ -1942,7 +1936,19 @@
 	vcpu->arch.mmu.root_hpa = INVALID_PAGE;
 }
 
-static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
+static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn)
+{
+	int ret = 0;
+
+	if (!kvm_is_visible_gfn(vcpu->kvm, root_gfn)) {
+		set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+static int mmu_alloc_roots(struct kvm_vcpu *vcpu)
 {
 	int i;
 	gfn_t root_gfn;
@@ -1957,13 +1963,15 @@
 		ASSERT(!VALID_PAGE(root));
 		if (tdp_enabled)
 			direct = 1;
+		if (mmu_check_root(vcpu, root_gfn))
+			return 1;
 		sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
 				      PT64_ROOT_LEVEL, direct,
 				      ACC_ALL, NULL);
 		root = __pa(sp->spt);
 		++sp->root_count;
 		vcpu->arch.mmu.root_hpa = root;
-		return;
+		return 0;
 	}
 	direct = !is_paging(vcpu);
 	if (tdp_enabled)
@@ -1980,6 +1988,8 @@
 			root_gfn = vcpu->arch.pdptrs[i] >> PAGE_SHIFT;
 		} else if (vcpu->arch.mmu.root_level == 0)
 			root_gfn = 0;
+		if (mmu_check_root(vcpu, root_gfn))
+			return 1;
 		sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
 				      PT32_ROOT_LEVEL, direct,
 				      ACC_ALL, NULL);
@@ -1988,6 +1998,7 @@
 		vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
 	}
 	vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root);
+	return 0;
 }
 
 static void mmu_sync_roots(struct kvm_vcpu *vcpu)
@@ -2006,7 +2017,7 @@
 	for (i = 0; i < 4; ++i) {
 		hpa_t root = vcpu->arch.mmu.pae_root[i];
 
-		if (root) {
+		if (root && VALID_PAGE(root)) {
 			root &= PT64_BASE_ADDR_MASK;
 			sp = page_header(root);
 			mmu_sync_children(vcpu, sp);
@@ -2014,15 +2025,6 @@
 	}
 }
 
-static void mmu_sync_global(struct kvm_vcpu *vcpu)
-{
-	struct kvm *kvm = vcpu->kvm;
-	struct kvm_mmu_page *sp, *n;
-
-	list_for_each_entry_safe(sp, n, &kvm->arch.oos_global_pages, oos_link)
-		kvm_sync_page(vcpu, sp);
-}
-
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
 {
 	spin_lock(&vcpu->kvm->mmu_lock);
@@ -2030,13 +2032,6 @@
 	spin_unlock(&vcpu->kvm->mmu_lock);
 }
 
-void kvm_mmu_sync_global(struct kvm_vcpu *vcpu)
-{
-	spin_lock(&vcpu->kvm->mmu_lock);
-	mmu_sync_global(vcpu);
-	spin_unlock(&vcpu->kvm->mmu_lock);
-}
-
 static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
 {
 	return vaddr;
@@ -2151,6 +2146,14 @@
 	nonpaging_free(vcpu);
 }
 
+static bool is_rsvd_bits_set(struct kvm_vcpu *vcpu, u64 gpte, int level)
+{
+	int bit7;
+
+	bit7 = (gpte >> 7) & 1;
+	return (gpte & vcpu->arch.mmu.rsvd_bits_mask[bit7][level-1]) != 0;
+}
+
 #define PTTYPE 64
 #include "paging_tmpl.h"
 #undef PTTYPE
@@ -2159,6 +2162,59 @@
 #include "paging_tmpl.h"
 #undef PTTYPE
 
+static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level)
+{
+	struct kvm_mmu *context = &vcpu->arch.mmu;
+	int maxphyaddr = cpuid_maxphyaddr(vcpu);
+	u64 exb_bit_rsvd = 0;
+
+	if (!is_nx(vcpu))
+		exb_bit_rsvd = rsvd_bits(63, 63);
+	switch (level) {
+	case PT32_ROOT_LEVEL:
+		/* no rsvd bits for 2 level 4K page table entries */
+		context->rsvd_bits_mask[0][1] = 0;
+		context->rsvd_bits_mask[0][0] = 0;
+		if (is_cpuid_PSE36())
+			/* 36bits PSE 4MB page */
+			context->rsvd_bits_mask[1][1] = rsvd_bits(17, 21);
+		else
+			/* 32 bits PSE 4MB page */
+			context->rsvd_bits_mask[1][1] = rsvd_bits(13, 21);
+		context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0];
+		break;
+	case PT32E_ROOT_LEVEL:
+		context->rsvd_bits_mask[0][2] =
+			rsvd_bits(maxphyaddr, 63) |
+			rsvd_bits(7, 8) | rsvd_bits(1, 2);	/* PDPTE */
+		context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 62);	/* PDE */
+		context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 62); 	/* PTE */
+		context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 62) |
+			rsvd_bits(13, 20);		/* large page */
+		context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0];
+		break;
+	case PT64_ROOT_LEVEL:
+		context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 8);
+		context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 8);
+		context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 51);
+		context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 51);
+		context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
+		context->rsvd_bits_mask[1][2] = context->rsvd_bits_mask[0][2];
+		context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+			rsvd_bits(maxphyaddr, 51) |
+			rsvd_bits(13, 20);		/* large page */
+		context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0];
+		break;
+	}
+}
+
 static int paging64_init_context_common(struct kvm_vcpu *vcpu, int level)
 {
 	struct kvm_mmu *context = &vcpu->arch.mmu;
@@ -2179,6 +2235,7 @@
 
 static int paging64_init_context(struct kvm_vcpu *vcpu)
 {
+	reset_rsvds_bits_mask(vcpu, PT64_ROOT_LEVEL);
 	return paging64_init_context_common(vcpu, PT64_ROOT_LEVEL);
 }
 
@@ -2186,6 +2243,7 @@
 {
 	struct kvm_mmu *context = &vcpu->arch.mmu;
 
+	reset_rsvds_bits_mask(vcpu, PT32_ROOT_LEVEL);
 	context->new_cr3 = paging_new_cr3;
 	context->page_fault = paging32_page_fault;
 	context->gva_to_gpa = paging32_gva_to_gpa;
@@ -2201,6 +2259,7 @@
 
 static int paging32E_init_context(struct kvm_vcpu *vcpu)
 {
+	reset_rsvds_bits_mask(vcpu, PT32E_ROOT_LEVEL);
 	return paging64_init_context_common(vcpu, PT32E_ROOT_LEVEL);
 }
 
@@ -2221,12 +2280,15 @@
 		context->gva_to_gpa = nonpaging_gva_to_gpa;
 		context->root_level = 0;
 	} else if (is_long_mode(vcpu)) {
+		reset_rsvds_bits_mask(vcpu, PT64_ROOT_LEVEL);
 		context->gva_to_gpa = paging64_gva_to_gpa;
 		context->root_level = PT64_ROOT_LEVEL;
 	} else if (is_pae(vcpu)) {
+		reset_rsvds_bits_mask(vcpu, PT32E_ROOT_LEVEL);
 		context->gva_to_gpa = paging64_gva_to_gpa;
 		context->root_level = PT32E_ROOT_LEVEL;
 	} else {
+		reset_rsvds_bits_mask(vcpu, PT32_ROOT_LEVEL);
 		context->gva_to_gpa = paging32_gva_to_gpa;
 		context->root_level = PT32_ROOT_LEVEL;
 	}
@@ -2290,9 +2352,11 @@
 		goto out;
 	spin_lock(&vcpu->kvm->mmu_lock);
 	kvm_mmu_free_some_pages(vcpu);
-	mmu_alloc_roots(vcpu);
+	r = mmu_alloc_roots(vcpu);
 	mmu_sync_roots(vcpu);
 	spin_unlock(&vcpu->kvm->mmu_lock);
+	if (r)
+		goto out;
 	kvm_x86_ops->set_cr3(vcpu, vcpu->arch.mmu.root_hpa);
 	kvm_mmu_flush_tlb(vcpu);
 out:
@@ -2638,14 +2702,6 @@
 
 static void free_mmu_pages(struct kvm_vcpu *vcpu)
 {
-	struct kvm_mmu_page *sp;
-
-	while (!list_empty(&vcpu->kvm->arch.active_mmu_pages)) {
-		sp = container_of(vcpu->kvm->arch.active_mmu_pages.next,
-				  struct kvm_mmu_page, link);
-		kvm_mmu_zap_page(vcpu->kvm, sp);
-		cond_resched();
-	}
 	free_page((unsigned long)vcpu->arch.mmu.pae_root);
 }
 
@@ -2710,7 +2766,6 @@
 {
 	struct kvm_mmu_page *sp;
 
-	spin_lock(&kvm->mmu_lock);
 	list_for_each_entry(sp, &kvm->arch.active_mmu_pages, link) {
 		int i;
 		u64 *pt;
@@ -2725,7 +2780,6 @@
 				pt[i] &= ~PT_WRITABLE_MASK;
 	}
 	kvm_flush_remote_tlbs(kvm);
-	spin_unlock(&kvm->mmu_lock);
 }
 
 void kvm_mmu_zap_all(struct kvm *kvm)
@@ -3007,11 +3061,13 @@
 				       " in nonleaf level: levels %d gva %lx"
 				       " level %d pte %llx\n", audit_msg,
 				       vcpu->arch.mmu.root_level, va, level, ent);
-
-			audit_mappings_page(vcpu, ent, va, level - 1);
+			else
+				audit_mappings_page(vcpu, ent, va, level - 1);
 		} else {
 			gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va);
-			hpa_t hpa = (hpa_t)gpa_to_pfn(vcpu, gpa) << PAGE_SHIFT;
+			gfn_t gfn = gpa >> PAGE_SHIFT;
+			pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn);
+			hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT;
 
 			if (is_shadow_present_pte(ent)
 			    && (ent & PT64_BASE_ADDR_MASK) != hpa)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/mmu.h linux-libre-2.6.31-gnu/arch/x86/kvm/mmu.h
--- linux-libre-2.6.30-gnu/arch/x86/kvm/mmu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/mmu.h	2009-09-09 18:13:59.000000000 -0400
@@ -75,4 +75,9 @@
 	return vcpu->arch.cr0 & X86_CR0_PG;
 }
 
+static inline int is_present_pte(unsigned long pte)
+{
+	return pte & PT_PRESENT_MASK;
+}
+
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/paging_tmpl.h linux-libre-2.6.31-gnu/arch/x86/kvm/paging_tmpl.h
--- linux-libre-2.6.30-gnu/arch/x86/kvm/paging_tmpl.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/paging_tmpl.h	2009-09-09 18:13:59.000000000 -0400
@@ -123,6 +123,7 @@
 	gfn_t table_gfn;
 	unsigned index, pt_access, pte_access;
 	gpa_t pte_gpa;
+	int rsvd_fault = 0;
 
 	pgprintk("%s: addr %lx\n", __func__, addr);
 walk:
@@ -157,6 +158,10 @@
 		if (!is_present_pte(pte))
 			goto not_present;
 
+		rsvd_fault = is_rsvd_bits_set(vcpu, pte, walker->level);
+		if (rsvd_fault)
+			goto access_error;
+
 		if (write_fault && !is_writeble_pte(pte))
 			if (user_fault || is_write_protection(vcpu))
 				goto access_error;
@@ -209,7 +214,6 @@
 		if (ret)
 			goto walk;
 		pte |= PT_DIRTY_MASK;
-		kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&pte, sizeof(pte), 0);
 		walker->ptes[walker->level - 1] = pte;
 	}
 
@@ -233,6 +237,8 @@
 		walker->error_code |= PFERR_USER_MASK;
 	if (fetch_fault)
 		walker->error_code |= PFERR_FETCH_MASK;
+	if (rsvd_fault)
+		walker->error_code |= PFERR_RSVD_MASK;
 	return 0;
 }
 
@@ -262,8 +268,7 @@
 	kvm_get_pfn(pfn);
 	mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
 		     gpte & PT_DIRTY_MASK, NULL, largepage,
-		     gpte & PT_GLOBAL_MASK, gpte_to_gfn(gpte),
-		     pfn, true);
+		     gpte_to_gfn(gpte), pfn, true);
 }
 
 /*
@@ -276,7 +281,7 @@
 {
 	unsigned access = gw->pt_access;
 	struct kvm_mmu_page *shadow_page;
-	u64 spte, *sptep;
+	u64 spte, *sptep = NULL;
 	int direct;
 	gfn_t table_gfn;
 	int r;
@@ -297,7 +302,6 @@
 				     user_fault, write_fault,
 				     gw->ptes[gw->level-1] & PT_DIRTY_MASK,
 				     ptwrite, largepage,
-				     gw->ptes[gw->level-1] & PT_GLOBAL_MASK,
 				     gw->gfn, pfn, false);
 			break;
 		}
@@ -380,7 +384,7 @@
 		return r;
 
 	/*
-	 * Look up the shadow pte for the faulting address.
+	 * Look up the guest pte for the faulting address.
 	 */
 	r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault,
 			     fetch_fault);
@@ -586,7 +590,7 @@
 		nr_present++;
 		pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
 		set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
-			 is_dirty_pte(gpte), 0, gpte & PT_GLOBAL_MASK, gfn,
+			 is_dirty_pte(gpte), 0, gfn,
 			 spte_to_pfn(sp->spt[i]), true, false);
 	}
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/svm.c linux-libre-2.6.31-gnu/arch/x86/kvm/svm.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/svm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/svm.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 #include "irq.h"
 #include "mmu.h"
 #include "kvm_cache_regs.h"
+#include "x86.h"
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -69,7 +70,6 @@
 static int nested = 0;
 module_param(nested, int, S_IRUGO);
 
-static void kvm_reput_irq(struct vcpu_svm *svm);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
 
 static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override);
@@ -132,24 +132,6 @@
 	return svm_features & feat;
 }
 
-static inline u8 pop_irq(struct kvm_vcpu *vcpu)
-{
-	int word_index = __ffs(vcpu->arch.irq_summary);
-	int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
-	int irq = word_index * BITS_PER_LONG + bit_index;
-
-	clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
-	if (!vcpu->arch.irq_pending[word_index])
-		clear_bit(word_index, &vcpu->arch.irq_summary);
-	return irq;
-}
-
-static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq)
-{
-	set_bit(irq, vcpu->arch.irq_pending);
-	set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
-}
-
 static inline void clgi(void)
 {
 	asm volatile (__ex(SVM_CLGI));
@@ -214,17 +196,31 @@
 	svm->vmcb->control.event_inj_err = error_code;
 }
 
-static bool svm_exception_injected(struct kvm_vcpu *vcpu)
+static int is_external_interrupt(u32 info)
+{
+	info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
+	return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
+}
+
+static u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
+	u32 ret = 0;
 
-	return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
+	if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
+		ret |= X86_SHADOW_INT_STI | X86_SHADOW_INT_MOV_SS;
+	return ret & mask;
 }
 
-static int is_external_interrupt(u32 info)
+static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
 {
-	info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
-	return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	if (mask == 0)
+		svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
+	else
+		svm->vmcb->control.int_state |= SVM_INTERRUPT_SHADOW_MASK;
+
 }
 
 static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
@@ -232,7 +228,9 @@
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	if (!svm->next_rip) {
-		printk(KERN_DEBUG "%s: NOP\n", __func__);
+		if (emulate_instruction(vcpu, vcpu->run, 0, 0, EMULTYPE_SKIP) !=
+				EMULATE_DONE)
+			printk(KERN_DEBUG "%s: NOP\n", __func__);
 		return;
 	}
 	if (svm->next_rip - kvm_rip_read(vcpu) > MAX_INST_SIZE)
@@ -240,9 +238,7 @@
 		       __func__, kvm_rip_read(vcpu), svm->next_rip);
 
 	kvm_rip_write(vcpu, svm->next_rip);
-	svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
-
-	vcpu->arch.interrupt_window_open = (svm->vcpu.arch.hflags & HF_GIF_MASK);
+	svm_set_interrupt_shadow(vcpu, 0);
 }
 
 static int has_svm(void)
@@ -715,6 +711,7 @@
 		svm->vmcb->control.tsc_offset += delta;
 		vcpu->cpu = cpu;
 		kvm_migrate_timers(vcpu);
+		svm->asid_generation = 0;
 	}
 
 	for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
@@ -830,6 +827,15 @@
 		if (!var->unusable)
 			var->type |= 0x1;
 		break;
+	case VCPU_SREG_SS:
+		/* On AMD CPUs sometimes the DB bit in the segment
+		 * descriptor is left as 1, although the whole segment has
+		 * been made unusable. Clear it here to pass an Intel VMX
+		 * entry check when cross vendor migrating.
+		 */
+		if (var->unusable)
+			var->db = 0;
+		break;
 	}
 }
 
@@ -960,15 +966,16 @@
 
 }
 
-static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
+static void update_db_intercept(struct kvm_vcpu *vcpu)
 {
-	int old_debug = vcpu->guest_debug;
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	vcpu->guest_debug = dbg->control;
-
 	svm->vmcb->control.intercept_exceptions &=
 		~((1 << DB_VECTOR) | (1 << BP_VECTOR));
+
+	if (vcpu->arch.singlestep)
+		svm->vmcb->control.intercept_exceptions |= (1 << DB_VECTOR);
+
 	if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
 		if (vcpu->guest_debug &
 		    (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
@@ -979,6 +986,16 @@
 				1 << BP_VECTOR;
 	} else
 		vcpu->guest_debug = 0;
+}
+
+static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
+{
+	int old_debug = vcpu->guest_debug;
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	vcpu->guest_debug = dbg->control;
+
+	update_db_intercept(vcpu);
 
 	if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
 		svm->vmcb->save.dr7 = dbg->arch.debugreg[7];
@@ -993,16 +1010,6 @@
 	return 0;
 }
 
-static int svm_get_irq(struct kvm_vcpu *vcpu)
-{
-	struct vcpu_svm *svm = to_svm(vcpu);
-	u32 exit_int_info = svm->vmcb->control.exit_int_info;
-
-	if (is_external_interrupt(exit_int_info))
-		return exit_int_info & SVM_EVTINJ_VEC_MASK;
-	return -1;
-}
-
 static void load_host_msrs(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_X86_64
@@ -1025,7 +1032,6 @@
 		svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
 	}
 
-	svm->vcpu.cpu = svm_data->cpu;
 	svm->asid_generation = svm_data->asid_generation;
 	svm->vmcb->control.asid = svm_data->next_asid++;
 }
@@ -1107,17 +1113,8 @@
 
 static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
-	u32 exit_int_info = svm->vmcb->control.exit_int_info;
-	struct kvm *kvm = svm->vcpu.kvm;
 	u64 fault_address;
 	u32 error_code;
-	bool event_injection = false;
-
-	if (!irqchip_in_kernel(kvm) &&
-	    is_external_interrupt(exit_int_info)) {
-		event_injection = true;
-		push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
-	}
 
 	fault_address  = svm->vmcb->control.exit_info_2;
 	error_code = svm->vmcb->control.exit_info_1;
@@ -1137,23 +1134,40 @@
 	 */
 	if (npt_enabled)
 		svm_flush_tlb(&svm->vcpu);
-
-	if (!npt_enabled && event_injection)
-		kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+	else {
+		if (kvm_event_needs_reinjection(&svm->vcpu))
+			kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+	}
 	return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
 }
 
 static int db_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
 	if (!(svm->vcpu.guest_debug &
-	      (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
+	      (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) &&
+		!svm->vcpu.arch.singlestep) {
 		kvm_queue_exception(&svm->vcpu, DB_VECTOR);
 		return 1;
 	}
-	kvm_run->exit_reason = KVM_EXIT_DEBUG;
-	kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
-	kvm_run->debug.arch.exception = DB_VECTOR;
-	return 0;
+
+	if (svm->vcpu.arch.singlestep) {
+		svm->vcpu.arch.singlestep = false;
+		if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP))
+			svm->vmcb->save.rflags &=
+				~(X86_EFLAGS_TF | X86_EFLAGS_RF);
+		update_db_intercept(&svm->vcpu);
+	}
+
+	if (svm->vcpu.guest_debug &
+	    (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)){
+		kvm_run->exit_reason = KVM_EXIT_DEBUG;
+		kvm_run->debug.arch.pc =
+			svm->vmcb->save.cs.base + svm->vmcb->save.rip;
+		kvm_run->debug.arch.exception = DB_VECTOR;
+		return 0;
+	}
+
+	return 1;
 }
 
 static int bp_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
@@ -1842,17 +1856,51 @@
 				    struct kvm_run *kvm_run)
 {
 	u16 tss_selector;
+	int reason;
+	int int_type = svm->vmcb->control.exit_int_info &
+		SVM_EXITINTINFO_TYPE_MASK;
+	int int_vec = svm->vmcb->control.exit_int_info & SVM_EVTINJ_VEC_MASK;
+	uint32_t type =
+		svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
+	uint32_t idt_v =
+		svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID;
 
 	tss_selector = (u16)svm->vmcb->control.exit_info_1;
+
 	if (svm->vmcb->control.exit_info_2 &
 	    (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
-		return kvm_task_switch(&svm->vcpu, tss_selector,
-				       TASK_SWITCH_IRET);
-	if (svm->vmcb->control.exit_info_2 &
-	    (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
-		return kvm_task_switch(&svm->vcpu, tss_selector,
-				       TASK_SWITCH_JMP);
-	return kvm_task_switch(&svm->vcpu, tss_selector, TASK_SWITCH_CALL);
+		reason = TASK_SWITCH_IRET;
+	else if (svm->vmcb->control.exit_info_2 &
+		 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
+		reason = TASK_SWITCH_JMP;
+	else if (idt_v)
+		reason = TASK_SWITCH_GATE;
+	else
+		reason = TASK_SWITCH_CALL;
+
+	if (reason == TASK_SWITCH_GATE) {
+		switch (type) {
+		case SVM_EXITINTINFO_TYPE_NMI:
+			svm->vcpu.arch.nmi_injected = false;
+			break;
+		case SVM_EXITINTINFO_TYPE_EXEPT:
+			kvm_clear_exception_queue(&svm->vcpu);
+			break;
+		case SVM_EXITINTINFO_TYPE_INTR:
+			kvm_clear_interrupt_queue(&svm->vcpu);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (reason != TASK_SWITCH_GATE ||
+	    int_type == SVM_EXITINTINFO_TYPE_SOFT ||
+	    (int_type == SVM_EXITINTINFO_TYPE_EXEPT &&
+	     (int_vec == OF_VECTOR || int_vec == BP_VECTOR)))
+		skip_emulated_instruction(&svm->vcpu);
+
+	return kvm_task_switch(&svm->vcpu, tss_selector, reason);
 }
 
 static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
@@ -1862,6 +1910,14 @@
 	return 1;
 }
 
+static int iret_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
+	++svm->vcpu.stat.nmi_window_exits;
+	svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET);
+	svm->vcpu.arch.hflags |= HF_IRET_MASK;
+	return 1;
+}
+
 static int invlpg_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
 	if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0) != EMULATE_DONE)
@@ -1879,8 +1935,14 @@
 
 static int cr8_write_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
+	u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
+	/* instruction emulation calls kvm_set_cr8() */
 	emulate_instruction(&svm->vcpu, NULL, 0, 0, 0);
-	if (irqchip_in_kernel(svm->vcpu.kvm))
+	if (irqchip_in_kernel(svm->vcpu.kvm)) {
+		svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
+		return 1;
+	}
+	if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
 		return 1;
 	kvm_run->exit_reason = KVM_EXIT_SET_TPR;
 	return 0;
@@ -2090,8 +2152,9 @@
 	 * If the user space waits to inject interrupts, exit as soon as
 	 * possible
 	 */
-	if (kvm_run->request_interrupt_window &&
-	    !svm->vcpu.arch.irq_summary) {
+	if (!irqchip_in_kernel(svm->vcpu.kvm) &&
+	    kvm_run->request_interrupt_window &&
+	    !kvm_cpu_has_interrupt(&svm->vcpu)) {
 		++svm->vcpu.stat.irq_window_exits;
 		kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
 		return 0;
@@ -2134,6 +2197,7 @@
 	[SVM_EXIT_VINTR]			= interrupt_window_interception,
 	/* [SVM_EXIT_CR0_SEL_WRITE]		= emulate_on_interception, */
 	[SVM_EXIT_CPUID]			= cpuid_interception,
+	[SVM_EXIT_IRET]                         = iret_interception,
 	[SVM_EXIT_INVD]                         = emulate_on_interception,
 	[SVM_EXIT_HLT]				= halt_interception,
 	[SVM_EXIT_INVLPG]			= invlpg_interception,
@@ -2194,7 +2258,6 @@
 		}
 	}
 
-	kvm_reput_irq(svm);
 
 	if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
 		kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
@@ -2205,7 +2268,7 @@
 
 	if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
 	    exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR &&
-	    exit_code != SVM_EXIT_NPF)
+	    exit_code != SVM_EXIT_NPF && exit_code != SVM_EXIT_TASK_SWITCH)
 		printk(KERN_ERR "%s: unexpected exit_ini_info 0x%x "
 		       "exit_code 0x%x\n",
 		       __func__, svm->vmcb->control.exit_int_info,
@@ -2237,11 +2300,20 @@
 	struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
 
 	svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
-	if (svm->vcpu.cpu != cpu ||
-	    svm->asid_generation != svm_data->asid_generation)
+	/* FIXME: handle wraparound of asid_generation */
+	if (svm->asid_generation != svm_data->asid_generation)
 		new_asid(svm, svm_data);
 }
 
+static void svm_inject_nmi(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
+	vcpu->arch.hflags |= HF_NMI_MASK;
+	svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
+	++vcpu->stat.nmi_injections;
+}
 
 static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
 {
@@ -2257,134 +2329,71 @@
 		((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
 }
 
-static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
+static void svm_queue_irq(struct kvm_vcpu *vcpu, unsigned nr)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	nested_svm_intr(svm);
-
-	svm_inject_irq(svm, irq);
+	svm->vmcb->control.event_inj = nr |
+		SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR;
 }
 
-static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+static void svm_set_irq(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
-	struct vmcb *vmcb = svm->vmcb;
-	int max_irr, tpr;
 
-	if (!irqchip_in_kernel(vcpu->kvm) || vcpu->arch.apic->vapic_addr)
-		return;
+	nested_svm_intr(svm);
 
-	vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
+	svm_queue_irq(vcpu, vcpu->arch.interrupt.nr);
+}
 
-	max_irr = kvm_lapic_find_highest_irr(vcpu);
-	if (max_irr == -1)
-		return;
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
 
-	tpr = kvm_lapic_get_cr8(vcpu) << 4;
+	if (irr == -1)
+		return;
 
-	if (tpr >= (max_irr & 0xf0))
-		vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
+	if (tpr >= irr)
+		svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
 }
 
-static void svm_intr_assist(struct kvm_vcpu *vcpu)
+static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 	struct vmcb *vmcb = svm->vmcb;
-	int intr_vector = -1;
-
-	if ((vmcb->control.exit_int_info & SVM_EVTINJ_VALID) &&
-	    ((vmcb->control.exit_int_info & SVM_EVTINJ_TYPE_MASK) == 0)) {
-		intr_vector = vmcb->control.exit_int_info &
-			      SVM_EVTINJ_VEC_MASK;
-		vmcb->control.exit_int_info = 0;
-		svm_inject_irq(svm, intr_vector);
-		goto out;
-	}
-
-	if (vmcb->control.int_ctl & V_IRQ_MASK)
-		goto out;
-
-	if (!kvm_cpu_has_interrupt(vcpu))
-		goto out;
-
-	if (nested_svm_intr(svm))
-		goto out;
-
-	if (!(svm->vcpu.arch.hflags & HF_GIF_MASK))
-		goto out;
-
-	if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
-	    (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
-	    (vmcb->control.event_inj & SVM_EVTINJ_VALID)) {
-		/* unable to deliver irq, set pending irq */
-		svm_set_vintr(svm);
-		svm_inject_irq(svm, 0x0);
-		goto out;
-	}
-	/* Okay, we can deliver the interrupt: grab it and update PIC state. */
-	intr_vector = kvm_cpu_get_interrupt(vcpu);
-	svm_inject_irq(svm, intr_vector);
-out:
-	update_cr8_intercept(vcpu);
+	return !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) &&
+		!(svm->vcpu.arch.hflags & HF_NMI_MASK);
 }
 
-static void kvm_reput_irq(struct vcpu_svm *svm)
+static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
 {
-	struct vmcb_control_area *control = &svm->vmcb->control;
-
-	if ((control->int_ctl & V_IRQ_MASK)
-	    && !irqchip_in_kernel(svm->vcpu.kvm)) {
-		control->int_ctl &= ~V_IRQ_MASK;
-		push_irq(&svm->vcpu, control->int_vector);
-	}
-
-	svm->vcpu.arch.interrupt_window_open =
-		!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
-		 (svm->vcpu.arch.hflags & HF_GIF_MASK);
+	struct vcpu_svm *svm = to_svm(vcpu);
+	struct vmcb *vmcb = svm->vmcb;
+	return (vmcb->save.rflags & X86_EFLAGS_IF) &&
+		!(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) &&
+		(svm->vcpu.arch.hflags & HF_GIF_MASK);
 }
 
-static void svm_do_inject_vector(struct vcpu_svm *svm)
+static void enable_irq_window(struct kvm_vcpu *vcpu)
 {
-	struct kvm_vcpu *vcpu = &svm->vcpu;
-	int word_index = __ffs(vcpu->arch.irq_summary);
-	int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
-	int irq = word_index * BITS_PER_LONG + bit_index;
-
-	clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
-	if (!vcpu->arch.irq_pending[word_index])
-		clear_bit(word_index, &vcpu->arch.irq_summary);
-	svm_inject_irq(svm, irq);
+	svm_set_vintr(to_svm(vcpu));
+	svm_inject_irq(to_svm(vcpu), 0x0);
 }
 
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
-				       struct kvm_run *kvm_run)
+static void enable_nmi_window(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
-	struct vmcb_control_area *control = &svm->vmcb->control;
 
-	if (nested_svm_intr(svm))
-		return;
-
-	svm->vcpu.arch.interrupt_window_open =
-		(!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
-		 (svm->vmcb->save.rflags & X86_EFLAGS_IF) &&
-		 (svm->vcpu.arch.hflags & HF_GIF_MASK));
-
-	if (svm->vcpu.arch.interrupt_window_open && svm->vcpu.arch.irq_summary)
-		/*
-		 * If interrupts enabled, and not blocked by sti or mov ss. Good.
-		 */
-		svm_do_inject_vector(svm);
+	if ((svm->vcpu.arch.hflags & (HF_NMI_MASK | HF_IRET_MASK))
+	    == HF_NMI_MASK)
+		return; /* IRET will cause a vm exit */
 
-	/*
-	 * Interrupts blocked.  Wait for unblock.
-	 */
-	if (!svm->vcpu.arch.interrupt_window_open &&
-	    (svm->vcpu.arch.irq_summary || kvm_run->request_interrupt_window))
-		svm_set_vintr(svm);
-	else
-		svm_clear_vintr(svm);
+	/* Something prevents NMI from been injected. Single step over
+	   possible problem (IRET or exception injection or interrupt
+	   shadow) */
+	vcpu->arch.singlestep = true;
+	svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
+	update_db_intercept(vcpu);
 }
 
 static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -2407,7 +2416,7 @@
 
 	if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR8_MASK)) {
 		int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
-		kvm_lapic_set_tpr(vcpu, cr8);
+		kvm_set_cr8(vcpu, cr8);
 	}
 }
 
@@ -2416,14 +2425,54 @@
 	struct vcpu_svm *svm = to_svm(vcpu);
 	u64 cr8;
 
-	if (!irqchip_in_kernel(vcpu->kvm))
-		return;
-
 	cr8 = kvm_get_cr8(vcpu);
 	svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
 	svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
 }
 
+static void svm_complete_interrupts(struct vcpu_svm *svm)
+{
+	u8 vector;
+	int type;
+	u32 exitintinfo = svm->vmcb->control.exit_int_info;
+
+	if (svm->vcpu.arch.hflags & HF_IRET_MASK)
+		svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
+
+	svm->vcpu.arch.nmi_injected = false;
+	kvm_clear_exception_queue(&svm->vcpu);
+	kvm_clear_interrupt_queue(&svm->vcpu);
+
+	if (!(exitintinfo & SVM_EXITINTINFO_VALID))
+		return;
+
+	vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
+	type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
+
+	switch (type) {
+	case SVM_EXITINTINFO_TYPE_NMI:
+		svm->vcpu.arch.nmi_injected = true;
+		break;
+	case SVM_EXITINTINFO_TYPE_EXEPT:
+		/* In case of software exception do not reinject an exception
+		   vector, but re-execute and instruction instead */
+		if (kvm_exception_is_soft(vector))
+			break;
+		if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
+			u32 err = svm->vmcb->control.exit_int_info_err;
+			kvm_queue_exception_e(&svm->vcpu, vector, err);
+
+		} else
+			kvm_queue_exception(&svm->vcpu, vector);
+		break;
+	case SVM_EXITINTINFO_TYPE_INTR:
+		kvm_queue_interrupt(&svm->vcpu, vector, false);
+		break;
+	default:
+		break;
+	}
+}
+
 #ifdef CONFIG_X86_64
 #define R "r"
 #else
@@ -2552,6 +2601,8 @@
 	sync_cr8_to_lapic(vcpu);
 
 	svm->next_rip = 0;
+
+	svm_complete_interrupts(svm);
 }
 
 #undef R
@@ -2617,7 +2668,7 @@
 #endif
 }
 
-static int svm_get_mt_mask_shift(void)
+static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
 {
 	return 0;
 }
@@ -2667,17 +2718,21 @@
 	.run = svm_vcpu_run,
 	.handle_exit = handle_exit,
 	.skip_emulated_instruction = skip_emulated_instruction,
+	.set_interrupt_shadow = svm_set_interrupt_shadow,
+	.get_interrupt_shadow = svm_get_interrupt_shadow,
 	.patch_hypercall = svm_patch_hypercall,
-	.get_irq = svm_get_irq,
 	.set_irq = svm_set_irq,
+	.set_nmi = svm_inject_nmi,
 	.queue_exception = svm_queue_exception,
-	.exception_injected = svm_exception_injected,
-	.inject_pending_irq = svm_intr_assist,
-	.inject_pending_vectors = do_interrupt_requests,
+	.interrupt_allowed = svm_interrupt_allowed,
+	.nmi_allowed = svm_nmi_allowed,
+	.enable_nmi_window = enable_nmi_window,
+	.enable_irq_window = enable_irq_window,
+	.update_cr8_intercept = update_cr8_intercept,
 
 	.set_tss_addr = svm_set_tss_addr,
 	.get_tdp_level = get_npt_level,
-	.get_mt_mask_shift = svm_get_mt_mask_shift,
+	.get_mt_mask = svm_get_mt_mask,
 };
 
 static int __init svm_init(void)
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/timer.c linux-libre-2.6.31-gnu/arch/x86/kvm/timer.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/timer.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,46 @@
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+#include <linux/hrtimer.h>
+#include <asm/atomic.h>
+#include "kvm_timer.h"
+
+static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
+{
+	int restart_timer = 0;
+	wait_queue_head_t *q = &vcpu->wq;
+
+	/* FIXME: this code should not know anything about vcpus */
+	if (!atomic_inc_and_test(&ktimer->pending))
+		set_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
+
+	if (!ktimer->reinject)
+		atomic_set(&ktimer->pending, 1);
+
+	if (waitqueue_active(q))
+		wake_up_interruptible(q);
+
+	if (ktimer->t_ops->is_periodic(ktimer)) {
+		hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
+		restart_timer = 1;
+	}
+
+	return restart_timer;
+}
+
+enum hrtimer_restart kvm_timer_fn(struct hrtimer *data)
+{
+	int restart_timer;
+	struct kvm_vcpu *vcpu;
+	struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
+
+	vcpu = ktimer->kvm->vcpus[ktimer->vcpu_id];
+	if (!vcpu)
+		return HRTIMER_NORESTART;
+
+	restart_timer = __kvm_timer_fn(vcpu, ktimer);
+	if (restart_timer)
+		return HRTIMER_RESTART;
+	else
+		return HRTIMER_NORESTART;
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/vmx.c linux-libre-2.6.31-gnu/arch/x86/kvm/vmx.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/vmx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/vmx.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,26 +32,27 @@
 #include <asm/desc.h>
 #include <asm/vmx.h>
 #include <asm/virtext.h>
+#include <asm/mce.h>
 
 #define __ex(x) __kvm_handle_fault_on_reboot(x)
 
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
-static int bypass_guest_pf = 1;
-module_param(bypass_guest_pf, bool, 0);
+static int __read_mostly bypass_guest_pf = 1;
+module_param(bypass_guest_pf, bool, S_IRUGO);
 
-static int enable_vpid = 1;
-module_param(enable_vpid, bool, 0);
+static int __read_mostly enable_vpid = 1;
+module_param_named(vpid, enable_vpid, bool, 0444);
 
-static int flexpriority_enabled = 1;
-module_param(flexpriority_enabled, bool, 0);
+static int __read_mostly flexpriority_enabled = 1;
+module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
 
-static int enable_ept = 1;
-module_param(enable_ept, bool, 0);
+static int __read_mostly enable_ept = 1;
+module_param_named(ept, enable_ept, bool, S_IRUGO);
 
-static int emulate_invalid_guest_state = 0;
-module_param(emulate_invalid_guest_state, bool, 0);
+static int __read_mostly emulate_invalid_guest_state = 0;
+module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 
 struct vmcs {
 	u32 revision_id;
@@ -97,6 +98,7 @@
 	int soft_vnmi_blocked;
 	ktime_t entry_time;
 	s64 vnmi_blocked_time;
+	u32 exit_reason;
 };
 
 static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -111,9 +113,10 @@
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
 static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu);
 
-static struct page *vmx_io_bitmap_a;
-static struct page *vmx_io_bitmap_b;
-static struct page *vmx_msr_bitmap;
+static unsigned long *vmx_io_bitmap_a;
+static unsigned long *vmx_io_bitmap_b;
+static unsigned long *vmx_msr_bitmap_legacy;
+static unsigned long *vmx_msr_bitmap_longmode;
 
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -213,70 +216,78 @@
 		== (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
 }
 
+static inline int is_machine_check(u32 intr_info)
+{
+	return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
+			     INTR_INFO_VALID_MASK)) ==
+		(INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
+}
+
 static inline int cpu_has_vmx_msr_bitmap(void)
 {
-	return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
+	return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
 }
 
 static inline int cpu_has_vmx_tpr_shadow(void)
 {
-	return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
+	return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
 }
 
 static inline int vm_need_tpr_shadow(struct kvm *kvm)
 {
-	return ((cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm)));
+	return (cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm));
 }
 
 static inline int cpu_has_secondary_exec_ctrls(void)
 {
-	return (vmcs_config.cpu_based_exec_ctrl &
-		CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
+	return vmcs_config.cpu_based_exec_ctrl &
+		CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
 }
 
 static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
 {
-	return flexpriority_enabled
-		&& (vmcs_config.cpu_based_2nd_exec_ctrl &
-		    SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+	return vmcs_config.cpu_based_2nd_exec_ctrl &
+		SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+}
+
+static inline bool cpu_has_vmx_flexpriority(void)
+{
+	return cpu_has_vmx_tpr_shadow() &&
+		cpu_has_vmx_virtualize_apic_accesses();
 }
 
 static inline int cpu_has_vmx_invept_individual_addr(void)
 {
-	return (!!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT));
+	return !!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT);
 }
 
 static inline int cpu_has_vmx_invept_context(void)
 {
-	return (!!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT));
+	return !!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT);
 }
 
 static inline int cpu_has_vmx_invept_global(void)
 {
-	return (!!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT));
+	return !!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT);
 }
 
 static inline int cpu_has_vmx_ept(void)
 {
-	return (vmcs_config.cpu_based_2nd_exec_ctrl &
-		SECONDARY_EXEC_ENABLE_EPT);
-}
-
-static inline int vm_need_ept(void)
-{
-	return (cpu_has_vmx_ept() && enable_ept);
+	return vmcs_config.cpu_based_2nd_exec_ctrl &
+		SECONDARY_EXEC_ENABLE_EPT;
 }
 
 static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
 {
-	return ((cpu_has_vmx_virtualize_apic_accesses()) &&
-		(irqchip_in_kernel(kvm)));
+	return flexpriority_enabled &&
+		(cpu_has_vmx_virtualize_apic_accesses()) &&
+		(irqchip_in_kernel(kvm));
 }
 
 static inline int cpu_has_vmx_vpid(void)
 {
-	return (vmcs_config.cpu_based_2nd_exec_ctrl &
-		SECONDARY_EXEC_ENABLE_VPID);
+	return vmcs_config.cpu_based_2nd_exec_ctrl &
+		SECONDARY_EXEC_ENABLE_VPID;
 }
 
 static inline int cpu_has_virtual_nmis(void)
@@ -284,6 +295,11 @@
 	return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
 }
 
+static inline bool report_flexpriority(void)
+{
+	return flexpriority_enabled;
+}
+
 static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
 {
 	int i;
@@ -381,7 +397,7 @@
 
 static inline void ept_sync_context(u64 eptp)
 {
-	if (vm_need_ept()) {
+	if (enable_ept) {
 		if (cpu_has_vmx_invept_context())
 			__invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
 		else
@@ -391,7 +407,7 @@
 
 static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
 {
-	if (vm_need_ept()) {
+	if (enable_ept) {
 		if (cpu_has_vmx_invept_individual_addr())
 			__invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
 					eptp, gpa);
@@ -478,7 +494,7 @@
 {
 	u32 eb;
 
-	eb = (1u << PF_VECTOR) | (1u << UD_VECTOR);
+	eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR);
 	if (!vcpu->fpu_active)
 		eb |= 1u << NM_VECTOR;
 	if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
@@ -488,9 +504,9 @@
 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
 			eb |= 1u << BP_VECTOR;
 	}
-	if (vcpu->arch.rmode.active)
+	if (vcpu->arch.rmode.vm86_active)
 		eb = ~0;
-	if (vm_need_ept())
+	if (enable_ept)
 		eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
 	vmcs_write32(EXCEPTION_BITMAP, eb);
 }
@@ -724,29 +740,50 @@
 
 static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
 {
-	if (vcpu->arch.rmode.active)
+	if (vcpu->arch.rmode.vm86_active)
 		rflags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
 	vmcs_writel(GUEST_RFLAGS, rflags);
 }
 
+static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+{
+	u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+	int ret = 0;
+
+	if (interruptibility & GUEST_INTR_STATE_STI)
+		ret |= X86_SHADOW_INT_STI;
+	if (interruptibility & GUEST_INTR_STATE_MOV_SS)
+		ret |= X86_SHADOW_INT_MOV_SS;
+
+	return ret & mask;
+}
+
+static void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+{
+	u32 interruptibility_old = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+	u32 interruptibility = interruptibility_old;
+
+	interruptibility &= ~(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS);
+
+	if (mask & X86_SHADOW_INT_MOV_SS)
+		interruptibility |= GUEST_INTR_STATE_MOV_SS;
+	if (mask & X86_SHADOW_INT_STI)
+		interruptibility |= GUEST_INTR_STATE_STI;
+
+	if ((interruptibility != interruptibility_old))
+		vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, interruptibility);
+}
+
 static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
 {
 	unsigned long rip;
-	u32 interruptibility;
 
 	rip = kvm_rip_read(vcpu);
 	rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
 	kvm_rip_write(vcpu, rip);
 
-	/*
-	 * We emulated an instruction, so temporary interrupt blocking
-	 * should be removed, if set.
-	 */
-	interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
-	if (interruptibility & 3)
-		vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
-			     interruptibility & ~3);
-	vcpu->arch.interrupt_window_open = 1;
+	/* skipping an emulated instruction also counts */
+	vmx_set_interrupt_shadow(vcpu, 0);
 }
 
 static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
@@ -760,7 +797,7 @@
 		intr_info |= INTR_INFO_DELIVER_CODE_MASK;
 	}
 
-	if (vcpu->arch.rmode.active) {
+	if (vcpu->arch.rmode.vm86_active) {
 		vmx->rmode.irq.pending = true;
 		vmx->rmode.irq.vector = nr;
 		vmx->rmode.irq.rip = kvm_rip_read(vcpu);
@@ -773,8 +810,9 @@
 		return;
 	}
 
-	if (nr == BP_VECTOR || nr == OF_VECTOR) {
-		vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
+	if (kvm_exception_is_soft(nr)) {
+		vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+			     vmx->vcpu.arch.event_exit_inst_len);
 		intr_info |= INTR_TYPE_SOFT_EXCEPTION;
 	} else
 		intr_info |= INTR_TYPE_HARD_EXCEPTION;
@@ -782,11 +820,6 @@
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
 }
 
-static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
-{
-	return false;
-}
-
 /*
  * Swap MSR entry in host/guest MSR entry array.
  */
@@ -812,6 +845,7 @@
 static void setup_msrs(struct vcpu_vmx *vmx)
 {
 	int save_nmsrs;
+	unsigned long *msr_bitmap;
 
 	vmx_load_host_state(vmx);
 	save_nmsrs = 0;
@@ -847,6 +881,15 @@
 		__find_msr_index(vmx, MSR_KERNEL_GS_BASE);
 #endif
 	vmx->msr_offset_efer = __find_msr_index(vmx, MSR_EFER);
+
+	if (cpu_has_vmx_msr_bitmap()) {
+		if (is_long_mode(&vmx->vcpu))
+			msr_bitmap = vmx_msr_bitmap_longmode;
+		else
+			msr_bitmap = vmx_msr_bitmap_legacy;
+
+		vmcs_write64(MSR_BITMAP, __pa(msr_bitmap));
+	}
 }
 
 /*
@@ -1034,13 +1077,6 @@
 	return 0;
 }
 
-static int vmx_get_irq(struct kvm_vcpu *vcpu)
-{
-	if (!vcpu->arch.interrupt.pending)
-		return -1;
-	return vcpu->arch.interrupt.nr;
-}
-
 static __init int cpu_has_kvm_support(void)
 {
 	return cpu_has_vmx();
@@ -1241,7 +1277,7 @@
 	struct page *pages;
 	struct vmcs *vmcs;
 
-	pages = alloc_pages_node(node, GFP_KERNEL, vmcs_config.order);
+	pages = alloc_pages_exact_node(node, GFP_KERNEL, vmcs_config.order);
 	if (!pages)
 		return NULL;
 	vmcs = page_address(pages);
@@ -1294,6 +1330,18 @@
 	if (boot_cpu_has(X86_FEATURE_NX))
 		kvm_enable_efer_bits(EFER_NX);
 
+	if (!cpu_has_vmx_vpid())
+		enable_vpid = 0;
+
+	if (!cpu_has_vmx_ept())
+		enable_ept = 0;
+
+	if (!cpu_has_vmx_flexpriority())
+		flexpriority_enabled = 0;
+
+	if (!cpu_has_vmx_tpr_shadow())
+		kvm_x86_ops->update_cr8_intercept = NULL;
+
 	return alloc_kvm_area();
 }
 
@@ -1324,7 +1372,7 @@
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	vmx->emulation_required = 1;
-	vcpu->arch.rmode.active = 0;
+	vcpu->arch.rmode.vm86_active = 0;
 
 	vmcs_writel(GUEST_TR_BASE, vcpu->arch.rmode.tr.base);
 	vmcs_write32(GUEST_TR_LIMIT, vcpu->arch.rmode.tr.limit);
@@ -1386,7 +1434,7 @@
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	vmx->emulation_required = 1;
-	vcpu->arch.rmode.active = 1;
+	vcpu->arch.rmode.vm86_active = 1;
 
 	vcpu->arch.rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
 	vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
@@ -1485,7 +1533,7 @@
 static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
 {
 	vpid_sync_vcpu_all(to_vmx(vcpu));
-	if (vm_need_ept())
+	if (enable_ept)
 		ept_sync_context(construct_eptp(vcpu->arch.mmu.root_hpa));
 }
 
@@ -1555,10 +1603,10 @@
 
 	vmx_fpu_deactivate(vcpu);
 
-	if (vcpu->arch.rmode.active && (cr0 & X86_CR0_PE))
+	if (vcpu->arch.rmode.vm86_active && (cr0 & X86_CR0_PE))
 		enter_pmode(vcpu);
 
-	if (!vcpu->arch.rmode.active && !(cr0 & X86_CR0_PE))
+	if (!vcpu->arch.rmode.vm86_active && !(cr0 & X86_CR0_PE))
 		enter_rmode(vcpu);
 
 #ifdef CONFIG_X86_64
@@ -1570,7 +1618,7 @@
 	}
 #endif
 
-	if (vm_need_ept())
+	if (enable_ept)
 		ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
 
 	vmcs_writel(CR0_READ_SHADOW, cr0);
@@ -1599,7 +1647,7 @@
 	u64 eptp;
 
 	guest_cr3 = cr3;
-	if (vm_need_ept()) {
+	if (enable_ept) {
 		eptp = construct_eptp(cr3);
 		vmcs_write64(EPT_POINTER, eptp);
 		ept_sync_context(eptp);
@@ -1616,11 +1664,11 @@
 
 static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
-	unsigned long hw_cr4 = cr4 | (vcpu->arch.rmode.active ?
+	unsigned long hw_cr4 = cr4 | (vcpu->arch.rmode.vm86_active ?
 		    KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
 	vcpu->arch.cr4 = cr4;
-	if (vm_need_ept())
+	if (enable_ept)
 		ept_update_paging_mode_cr4(&hw_cr4, vcpu);
 
 	vmcs_writel(CR4_READ_SHADOW, cr4);
@@ -1699,7 +1747,7 @@
 	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
 	u32 ar;
 
-	if (vcpu->arch.rmode.active && seg == VCPU_SREG_TR) {
+	if (vcpu->arch.rmode.vm86_active && seg == VCPU_SREG_TR) {
 		vcpu->arch.rmode.tr.selector = var->selector;
 		vcpu->arch.rmode.tr.base = var->base;
 		vcpu->arch.rmode.tr.limit = var->limit;
@@ -1709,7 +1757,7 @@
 	vmcs_writel(sf->base, var->base);
 	vmcs_write32(sf->limit, var->limit);
 	vmcs_write16(sf->selector, var->selector);
-	if (vcpu->arch.rmode.active && var->s) {
+	if (vcpu->arch.rmode.vm86_active && var->s) {
 		/*
 		 * Hack real-mode segments into vm86 compatibility.
 		 */
@@ -1982,7 +2030,7 @@
 	pfn_t identity_map_pfn;
 	u32 tmp;
 
-	if (!vm_need_ept())
+	if (!enable_ept)
 		return 1;
 	if (unlikely(!kvm->arch.ept_identity_pagetable)) {
 		printk(KERN_ERR "EPT: identity-mapping pagetable "
@@ -2071,7 +2119,7 @@
 	int vpid;
 
 	vmx->vpid = 0;
-	if (!enable_vpid || !cpu_has_vmx_vpid())
+	if (!enable_vpid)
 		return;
 	spin_lock(&vmx_vpid_lock);
 	vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
@@ -2082,9 +2130,9 @@
 	spin_unlock(&vmx_vpid_lock);
 }
 
-static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
+static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap, u32 msr)
 {
-	void *va;
+	int f = sizeof(unsigned long);
 
 	if (!cpu_has_vmx_msr_bitmap())
 		return;
@@ -2094,16 +2142,21 @@
 	 * have the write-low and read-high bitmap offsets the wrong way round.
 	 * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
 	 */
-	va = kmap(msr_bitmap);
 	if (msr <= 0x1fff) {
-		__clear_bit(msr, va + 0x000); /* read-low */
-		__clear_bit(msr, va + 0x800); /* write-low */
+		__clear_bit(msr, msr_bitmap + 0x000 / f); /* read-low */
+		__clear_bit(msr, msr_bitmap + 0x800 / f); /* write-low */
 	} else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
 		msr &= 0x1fff;
-		__clear_bit(msr, va + 0x400); /* read-high */
-		__clear_bit(msr, va + 0xc00); /* write-high */
+		__clear_bit(msr, msr_bitmap + 0x400 / f); /* read-high */
+		__clear_bit(msr, msr_bitmap + 0xc00 / f); /* write-high */
 	}
-	kunmap(msr_bitmap);
+}
+
+static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
+{
+	if (!longmode_only)
+		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy, msr);
+	__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode, msr);
 }
 
 /*
@@ -2121,11 +2174,11 @@
 	u32 exec_control;
 
 	/* I/O */
-	vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
-	vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
+	vmcs_write64(IO_BITMAP_A, __pa(vmx_io_bitmap_a));
+	vmcs_write64(IO_BITMAP_B, __pa(vmx_io_bitmap_b));
 
 	if (cpu_has_vmx_msr_bitmap())
-		vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
+		vmcs_write64(MSR_BITMAP, __pa(vmx_msr_bitmap_legacy));
 
 	vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
 
@@ -2141,7 +2194,7 @@
 				CPU_BASED_CR8_LOAD_EXITING;
 #endif
 	}
-	if (!vm_need_ept())
+	if (!enable_ept)
 		exec_control |= CPU_BASED_CR3_STORE_EXITING |
 				CPU_BASED_CR3_LOAD_EXITING  |
 				CPU_BASED_INVLPG_EXITING;
@@ -2154,7 +2207,7 @@
 				~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
 		if (vmx->vpid == 0)
 			exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
-		if (!vm_need_ept())
+		if (!enable_ept)
 			exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
 		vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
 	}
@@ -2273,7 +2326,7 @@
 		goto out;
 	}
 
-	vmx->vcpu.arch.rmode.active = 0;
+	vmx->vcpu.arch.rmode.vm86_active = 0;
 
 	vmx->soft_vnmi_blocked = 0;
 
@@ -2402,14 +2455,16 @@
 	vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
 }
 
-static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
+static void vmx_inject_irq(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	uint32_t intr;
+	int irq = vcpu->arch.interrupt.nr;
 
 	KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler);
 
 	++vcpu->stat.irq_injections;
-	if (vcpu->arch.rmode.active) {
+	if (vcpu->arch.rmode.vm86_active) {
 		vmx->rmode.irq.pending = true;
 		vmx->rmode.irq.vector = irq;
 		vmx->rmode.irq.rip = kvm_rip_read(vcpu);
@@ -2419,8 +2474,14 @@
 		kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
 		return;
 	}
-	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
-			irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
+	intr = irq | INTR_INFO_VALID_MASK;
+	if (vcpu->arch.interrupt.soft) {
+		intr |= INTR_TYPE_SOFT_INTR;
+		vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+			     vmx->vcpu.arch.event_exit_inst_len);
+	} else
+		intr |= INTR_TYPE_EXT_INTR;
+	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr);
 }
 
 static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
@@ -2441,7 +2502,7 @@
 	}
 
 	++vcpu->stat.nmi_injections;
-	if (vcpu->arch.rmode.active) {
+	if (vcpu->arch.rmode.vm86_active) {
 		vmx->rmode.irq.pending = true;
 		vmx->rmode.irq.vector = NMI_VECTOR;
 		vmx->rmode.irq.rip = kvm_rip_read(vcpu);
@@ -2456,76 +2517,21 @@
 			INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
 }
 
-static void vmx_update_window_states(struct kvm_vcpu *vcpu)
+static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
 {
-	u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
-
-	vcpu->arch.nmi_window_open =
-		!(guest_intr & (GUEST_INTR_STATE_STI |
-				GUEST_INTR_STATE_MOV_SS |
-				GUEST_INTR_STATE_NMI));
 	if (!cpu_has_virtual_nmis() && to_vmx(vcpu)->soft_vnmi_blocked)
-		vcpu->arch.nmi_window_open = 0;
-
-	vcpu->arch.interrupt_window_open =
-		((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
-		 !(guest_intr & (GUEST_INTR_STATE_STI |
-				 GUEST_INTR_STATE_MOV_SS)));
-}
-
-static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
-{
-	int word_index = __ffs(vcpu->arch.irq_summary);
-	int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
-	int irq = word_index * BITS_PER_LONG + bit_index;
+		return 0;
 
-	clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
-	if (!vcpu->arch.irq_pending[word_index])
-		clear_bit(word_index, &vcpu->arch.irq_summary);
-	kvm_queue_interrupt(vcpu, irq);
+	return	!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+			(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS |
+				GUEST_INTR_STATE_NMI));
 }
 
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
-				       struct kvm_run *kvm_run)
+static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
 {
-	vmx_update_window_states(vcpu);
-
-	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
-		vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
-				GUEST_INTR_STATE_STI |
-				GUEST_INTR_STATE_MOV_SS);
-
-	if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
-		if (vcpu->arch.interrupt.pending) {
-			enable_nmi_window(vcpu);
-		} else if (vcpu->arch.nmi_window_open) {
-			vcpu->arch.nmi_pending = false;
-			vcpu->arch.nmi_injected = true;
-		} else {
-			enable_nmi_window(vcpu);
-			return;
-		}
-	}
-	if (vcpu->arch.nmi_injected) {
-		vmx_inject_nmi(vcpu);
-		if (vcpu->arch.nmi_pending)
-			enable_nmi_window(vcpu);
-		else if (vcpu->arch.irq_summary
-			 || kvm_run->request_interrupt_window)
-			enable_irq_window(vcpu);
-		return;
-	}
-
-	if (vcpu->arch.interrupt_window_open) {
-		if (vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending)
-			kvm_do_inject_irq(vcpu);
-
-		if (vcpu->arch.interrupt.pending)
-			vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
-	}
-	if (!vcpu->arch.interrupt_window_open &&
-	    (vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
-		enable_irq_window(vcpu);
+	return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+		!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+			(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
 }
 
 static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -2585,6 +2591,31 @@
 	return 0;
 }
 
+/*
+ * Trigger machine check on the host. We assume all the MSRs are already set up
+ * by the CPU and that we still run on the same CPU as the MCE occurred on.
+ * We pass a fake environment to the machine check handler because we want
+ * the guest to be always treated like user space, no matter what context
+ * it used internally.
+ */
+static void kvm_machine_check(void)
+{
+#if defined(CONFIG_X86_MCE) && defined(CONFIG_X86_64)
+	struct pt_regs regs = {
+		.cs = 3, /* Fake ring 3 no matter what the guest ran on */
+		.flags = X86_EFLAGS_IF,
+	};
+
+	do_machine_check(&regs, 0);
+#endif
+}
+
+static int handle_machine_check(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	/* already handled by vcpu_run */
+	return 1;
+}
+
 static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2596,17 +2627,14 @@
 	vect_info = vmx->idt_vectoring_info;
 	intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 
+	if (is_machine_check(intr_info))
+		return handle_machine_check(vcpu, kvm_run);
+
 	if ((vect_info & VECTORING_INFO_VALID_MASK) &&
 						!is_page_fault(intr_info))
 		printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
 		       "intr info 0x%x\n", __func__, vect_info, intr_info);
 
-	if (!irqchip_in_kernel(vcpu->kvm) && is_external_interrupt(vect_info)) {
-		int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
-		set_bit(irq, vcpu->arch.irq_pending);
-		set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
-	}
-
 	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
 		return 1;  /* already handled by vmx_vcpu_run() */
 
@@ -2628,17 +2656,17 @@
 		error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
 	if (is_page_fault(intr_info)) {
 		/* EPT won't cause page fault directly */
-		if (vm_need_ept())
+		if (enable_ept)
 			BUG();
 		cr2 = vmcs_readl(EXIT_QUALIFICATION);
 		KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
 			    (u32)((u64)cr2 >> 32), handler);
-		if (vcpu->arch.interrupt.pending || vcpu->arch.exception.pending)
+		if (kvm_event_needs_reinjection(vcpu))
 			kvm_mmu_unprotect_page_virt(vcpu, cr2);
 		return kvm_mmu_page_fault(vcpu, cr2, error_code);
 	}
 
-	if (vcpu->arch.rmode.active &&
+	if (vcpu->arch.rmode.vm86_active &&
 	    handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK,
 								error_code)) {
 		if (vcpu->arch.halt_request) {
@@ -2753,13 +2781,18 @@
 			kvm_set_cr4(vcpu, kvm_register_read(vcpu, reg));
 			skip_emulated_instruction(vcpu);
 			return 1;
-		case 8:
-			kvm_set_cr8(vcpu, kvm_register_read(vcpu, reg));
-			skip_emulated_instruction(vcpu);
-			if (irqchip_in_kernel(vcpu->kvm))
-				return 1;
-			kvm_run->exit_reason = KVM_EXIT_SET_TPR;
-			return 0;
+		case 8: {
+				u8 cr8_prev = kvm_get_cr8(vcpu);
+				u8 cr8 = kvm_register_read(vcpu, reg);
+				kvm_set_cr8(vcpu, cr8);
+				skip_emulated_instruction(vcpu);
+				if (irqchip_in_kernel(vcpu->kvm))
+					return 1;
+				if (cr8_prev <= cr8)
+					return 1;
+				kvm_run->exit_reason = KVM_EXIT_SET_TPR;
+				return 0;
+			}
 		};
 		break;
 	case 2: /* clts */
@@ -2957,8 +2990,9 @@
 	 * If the user space waits to inject interrupts, exit as soon as
 	 * possible
 	 */
-	if (kvm_run->request_interrupt_window &&
-	    !vcpu->arch.irq_summary) {
+	if (!irqchip_in_kernel(vcpu->kvm) &&
+	    kvm_run->request_interrupt_window &&
+	    !kvm_cpu_has_interrupt(vcpu)) {
 		kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
 		return 0;
 	}
@@ -2978,9 +3012,15 @@
 	return 1;
 }
 
+static int handle_vmx_insn(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	kvm_queue_exception(vcpu, UD_VECTOR);
+	return 1;
+}
+
 static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-	u64 exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
 	kvm_mmu_invlpg(vcpu, exit_qualification);
 	skip_emulated_instruction(vcpu);
@@ -2996,11 +3036,11 @@
 
 static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-	u64 exit_qualification;
+	unsigned long exit_qualification;
 	enum emulation_result er;
 	unsigned long offset;
 
-	exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 	offset = exit_qualification & 0xffful;
 
 	er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
@@ -3019,22 +3059,41 @@
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	unsigned long exit_qualification;
 	u16 tss_selector;
-	int reason;
+	int reason, type, idt_v;
+
+	idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+	type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
 
 	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
 	reason = (u32)exit_qualification >> 30;
-	if (reason == TASK_SWITCH_GATE && vmx->vcpu.arch.nmi_injected &&
-	    (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
-	    (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK)
-	    == INTR_TYPE_NMI_INTR) {
-		vcpu->arch.nmi_injected = false;
-		if (cpu_has_virtual_nmis())
-			vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
-				      GUEST_INTR_STATE_NMI);
+	if (reason == TASK_SWITCH_GATE && idt_v) {
+		switch (type) {
+		case INTR_TYPE_NMI_INTR:
+			vcpu->arch.nmi_injected = false;
+			if (cpu_has_virtual_nmis())
+				vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+					      GUEST_INTR_STATE_NMI);
+			break;
+		case INTR_TYPE_EXT_INTR:
+		case INTR_TYPE_SOFT_INTR:
+			kvm_clear_interrupt_queue(vcpu);
+			break;
+		case INTR_TYPE_HARD_EXCEPTION:
+		case INTR_TYPE_SOFT_EXCEPTION:
+			kvm_clear_exception_queue(vcpu);
+			break;
+		default:
+			break;
+		}
 	}
 	tss_selector = exit_qualification;
 
+	if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
+		       type != INTR_TYPE_EXT_INTR &&
+		       type != INTR_TYPE_NMI_INTR))
+		skip_emulated_instruction(vcpu);
+
 	if (!kvm_task_switch(vcpu, tss_selector, reason))
 		return 0;
 
@@ -3051,11 +3110,11 @@
 
 static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-	u64 exit_qualification;
+	unsigned long exit_qualification;
 	gpa_t gpa;
 	int gla_validity;
 
-	exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
 	if (exit_qualification & (1 << 6)) {
 		printk(KERN_ERR "EPT: GPA exceeds GAW!\n");
@@ -3067,7 +3126,7 @@
 		printk(KERN_ERR "EPT: Handling EPT violation failed!\n");
 		printk(KERN_ERR "EPT: GPA: 0x%lx, GVA: 0x%lx\n",
 			(long unsigned int)vmcs_read64(GUEST_PHYSICAL_ADDRESS),
-			(long unsigned int)vmcs_read64(GUEST_LINEAR_ADDRESS));
+			vmcs_readl(GUEST_LINEAR_ADDRESS));
 		printk(KERN_ERR "EPT: Exit qualification is 0x%lx\n",
 			(long unsigned int)exit_qualification);
 		kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
@@ -3098,8 +3157,8 @@
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	enum emulation_result err = EMULATE_DONE;
 
-	preempt_enable();
 	local_irq_enable();
+	preempt_enable();
 
 	while (!guest_state_valid(vcpu)) {
 		err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
@@ -3109,7 +3168,7 @@
 
 		if (err != EMULATE_DONE) {
 			kvm_report_emulation_failure(vcpu, "emulation failure");
-			return;
+			break;
 		}
 
 		if (signal_pending(current))
@@ -3118,8 +3177,8 @@
 			schedule();
 	}
 
-	local_irq_disable();
 	preempt_disable();
+	local_irq_disable();
 
 	vmx->invalid_state_emulation_result = err;
 }
@@ -3145,11 +3204,21 @@
 	[EXIT_REASON_HLT]                     = handle_halt,
 	[EXIT_REASON_INVLPG]		      = handle_invlpg,
 	[EXIT_REASON_VMCALL]                  = handle_vmcall,
+	[EXIT_REASON_VMCLEAR]	              = handle_vmx_insn,
+	[EXIT_REASON_VMLAUNCH]                = handle_vmx_insn,
+	[EXIT_REASON_VMPTRLD]                 = handle_vmx_insn,
+	[EXIT_REASON_VMPTRST]                 = handle_vmx_insn,
+	[EXIT_REASON_VMREAD]                  = handle_vmx_insn,
+	[EXIT_REASON_VMRESUME]                = handle_vmx_insn,
+	[EXIT_REASON_VMWRITE]                 = handle_vmx_insn,
+	[EXIT_REASON_VMOFF]                   = handle_vmx_insn,
+	[EXIT_REASON_VMON]                    = handle_vmx_insn,
 	[EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
 	[EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
 	[EXIT_REASON_WBINVD]                  = handle_wbinvd,
 	[EXIT_REASON_TASK_SWITCH]             = handle_task_switch,
 	[EXIT_REASON_EPT_VIOLATION]	      = handle_ept_violation,
+	[EXIT_REASON_MCE_DURING_VMENTRY]      = handle_machine_check,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -3159,10 +3228,10 @@
  * The guest has exited.  See if we can fix it or if we need userspace
  * assistance.
  */
-static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
-	u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	u32 exit_reason = vmx->exit_reason;
 	u32 vectoring_info = vmx->idt_vectoring_info;
 
 	KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)kvm_rip_read(vcpu),
@@ -3178,7 +3247,7 @@
 
 	/* Access CR3 don't cause VMExit in paging mode, so we need
 	 * to sync with guest real CR3. */
-	if (vm_need_ept() && is_paging(vcpu)) {
+	if (enable_ept && is_paging(vcpu)) {
 		vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
 		ept_load_pdptrs(vcpu);
 	}
@@ -3199,9 +3268,8 @@
 		       __func__, vectoring_info, exit_reason);
 
 	if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) {
-		if (vcpu->arch.interrupt_window_open) {
+		if (vmx_interrupt_allowed(vcpu)) {
 			vmx->soft_vnmi_blocked = 0;
-			vcpu->arch.nmi_window_open = 1;
 		} else if (vmx->vnmi_blocked_time > 1000000000LL &&
 			   vcpu->arch.nmi_pending) {
 			/*
@@ -3214,7 +3282,6 @@
 			       "state on VCPU %d after 1 s timeout\n",
 			       __func__, vcpu->vcpu_id);
 			vmx->soft_vnmi_blocked = 0;
-			vmx->vcpu.arch.nmi_window_open = 1;
 		}
 	}
 
@@ -3228,122 +3295,107 @@
 	return 0;
 }
 
-static void update_tpr_threshold(struct kvm_vcpu *vcpu)
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
 {
-	int max_irr, tpr;
-
-	if (!vm_need_tpr_shadow(vcpu->kvm))
-		return;
-
-	if (!kvm_lapic_enabled(vcpu) ||
-	    ((max_irr = kvm_lapic_find_highest_irr(vcpu)) == -1)) {
+	if (irr == -1 || tpr < irr) {
 		vmcs_write32(TPR_THRESHOLD, 0);
 		return;
 	}
 
-	tpr = (kvm_lapic_get_cr8(vcpu) & 0x0f) << 4;
-	vmcs_write32(TPR_THRESHOLD, (max_irr > tpr) ? tpr >> 4 : max_irr >> 4);
+	vmcs_write32(TPR_THRESHOLD, irr);
 }
 
 static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
 {
 	u32 exit_intr_info;
-	u32 idt_vectoring_info;
+	u32 idt_vectoring_info = vmx->idt_vectoring_info;
 	bool unblock_nmi;
 	u8 vector;
 	int type;
 	bool idtv_info_valid;
-	u32 error;
 
 	exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+	vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
+
+	/* Handle machine checks before interrupts are enabled */
+	if ((vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY)
+	    || (vmx->exit_reason == EXIT_REASON_EXCEPTION_NMI
+		&& is_machine_check(exit_intr_info)))
+		kvm_machine_check();
+
+	/* We need to handle NMIs before interrupts are enabled */
+	if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
+	    (exit_intr_info & INTR_INFO_VALID_MASK)) {
+		KVMTRACE_0D(NMI, &vmx->vcpu, handler);
+		asm("int $2");
+	}
+
+	idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
+
 	if (cpu_has_virtual_nmis()) {
 		unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
 		vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
 		/*
-		 * SDM 3: 25.7.1.2
+		 * SDM 3: 27.7.1.2 (September 2008)
 		 * Re-set bit "block by NMI" before VM entry if vmexit caused by
 		 * a guest IRET fault.
+		 * SDM 3: 23.2.2 (September 2008)
+		 * Bit 12 is undefined in any of the following cases:
+		 *  If the VM exit sets the valid bit in the IDT-vectoring
+		 *   information field.
+		 *  If the VM exit is due to a double fault.
 		 */
-		if (unblock_nmi && vector != DF_VECTOR)
+		if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
+		    vector != DF_VECTOR && !idtv_info_valid)
 			vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
 				      GUEST_INTR_STATE_NMI);
 	} else if (unlikely(vmx->soft_vnmi_blocked))
 		vmx->vnmi_blocked_time +=
 			ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
 
-	idt_vectoring_info = vmx->idt_vectoring_info;
-	idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
+	vmx->vcpu.arch.nmi_injected = false;
+	kvm_clear_exception_queue(&vmx->vcpu);
+	kvm_clear_interrupt_queue(&vmx->vcpu);
+
+	if (!idtv_info_valid)
+		return;
+
 	vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
 	type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
-	if (vmx->vcpu.arch.nmi_injected) {
+
+	switch (type) {
+	case INTR_TYPE_NMI_INTR:
+		vmx->vcpu.arch.nmi_injected = true;
 		/*
-		 * SDM 3: 25.7.1.2
-		 * Clear bit "block by NMI" before VM entry if a NMI delivery
-		 * faulted.
+		 * SDM 3: 27.7.1.2 (September 2008)
+		 * Clear bit "block by NMI" before VM entry if a NMI
+		 * delivery faulted.
 		 */
-		if (idtv_info_valid && type == INTR_TYPE_NMI_INTR)
-			vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
-					GUEST_INTR_STATE_NMI);
-		else
-			vmx->vcpu.arch.nmi_injected = false;
-	}
-	kvm_clear_exception_queue(&vmx->vcpu);
-	if (idtv_info_valid && (type == INTR_TYPE_HARD_EXCEPTION ||
-				type == INTR_TYPE_SOFT_EXCEPTION)) {
+		vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+				GUEST_INTR_STATE_NMI);
+		break;
+	case INTR_TYPE_SOFT_EXCEPTION:
+		vmx->vcpu.arch.event_exit_inst_len =
+			vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+		/* fall through */
+	case INTR_TYPE_HARD_EXCEPTION:
 		if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
-			error = vmcs_read32(IDT_VECTORING_ERROR_CODE);
-			kvm_queue_exception_e(&vmx->vcpu, vector, error);
+			u32 err = vmcs_read32(IDT_VECTORING_ERROR_CODE);
+			kvm_queue_exception_e(&vmx->vcpu, vector, err);
 		} else
 			kvm_queue_exception(&vmx->vcpu, vector);
-		vmx->idt_vectoring_info = 0;
-	}
-	kvm_clear_interrupt_queue(&vmx->vcpu);
-	if (idtv_info_valid && type == INTR_TYPE_EXT_INTR) {
-		kvm_queue_interrupt(&vmx->vcpu, vector);
-		vmx->idt_vectoring_info = 0;
-	}
-}
-
-static void vmx_intr_assist(struct kvm_vcpu *vcpu)
-{
-	update_tpr_threshold(vcpu);
-
-	vmx_update_window_states(vcpu);
-
-	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
-		vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
-				GUEST_INTR_STATE_STI |
-				GUEST_INTR_STATE_MOV_SS);
-
-	if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
-		if (vcpu->arch.interrupt.pending) {
-			enable_nmi_window(vcpu);
-		} else if (vcpu->arch.nmi_window_open) {
-			vcpu->arch.nmi_pending = false;
-			vcpu->arch.nmi_injected = true;
-		} else {
-			enable_nmi_window(vcpu);
-			return;
-		}
-	}
-	if (vcpu->arch.nmi_injected) {
-		vmx_inject_nmi(vcpu);
-		if (vcpu->arch.nmi_pending)
-			enable_nmi_window(vcpu);
-		else if (kvm_cpu_has_interrupt(vcpu))
-			enable_irq_window(vcpu);
-		return;
-	}
-	if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) {
-		if (vcpu->arch.interrupt_window_open)
-			kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
-		else
-			enable_irq_window(vcpu);
-	}
-	if (vcpu->arch.interrupt.pending) {
-		vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
-		if (kvm_cpu_has_interrupt(vcpu))
-			enable_irq_window(vcpu);
+		break;
+	case INTR_TYPE_SOFT_INTR:
+		vmx->vcpu.arch.event_exit_inst_len =
+			vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+		/* fall through */
+	case INTR_TYPE_EXT_INTR:
+		kvm_queue_interrupt(&vmx->vcpu, vector,
+			type == INTR_TYPE_SOFT_INTR);
+		break;
+	default:
+		break;
 	}
 }
 
@@ -3381,7 +3433,6 @@
 static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
-	u32 intr_info;
 
 	/* Record the guest's net vcpu time for enforced NMI injections. */
 	if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
@@ -3505,20 +3556,9 @@
 	if (vmx->rmode.irq.pending)
 		fixup_rmode_irq(vmx);
 
-	vmx_update_window_states(vcpu);
-
 	asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
 	vmx->launched = 1;
 
-	intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-
-	/* We need to handle NMIs before interrupts are enabled */
-	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
-	    (intr_info & INTR_INFO_VALID_MASK)) {
-		KVMTRACE_0D(NMI, vcpu, handler);
-		asm("int $2");
-	}
-
 	vmx_complete_interrupts(vmx);
 }
 
@@ -3593,7 +3633,7 @@
 		if (alloc_apic_access_page(kvm) != 0)
 			goto free_vmcs;
 
-	if (vm_need_ept())
+	if (enable_ept)
 		if (alloc_identity_pagetable(kvm) != 0)
 			goto free_vmcs;
 
@@ -3631,9 +3671,32 @@
 	return VMX_EPT_DEFAULT_GAW + 1;
 }
 
-static int vmx_get_mt_mask_shift(void)
+static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
 {
-	return VMX_EPT_MT_EPTE_SHIFT;
+	u64 ret;
+
+	/* For VT-d and EPT combination
+	 * 1. MMIO: always map as UC
+	 * 2. EPT with VT-d:
+	 *   a. VT-d without snooping control feature: can't guarantee the
+	 *	result, try to trust guest.
+	 *   b. VT-d with snooping control feature: snooping control feature of
+	 *	VT-d engine can guarantee the cache correctness. Just set it
+	 *	to WB to keep consistent with host. So the same as item 3.
+	 * 3. EPT without VT-d: always map as WB and set IGMT=1 to keep
+	 *    consistent with host MTRR
+	 */
+	if (is_mmio)
+		ret = MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT;
+	else if (vcpu->kvm->arch.iommu_domain &&
+		!(vcpu->kvm->arch.iommu_flags & KVM_IOMMU_CACHE_COHERENCY))
+		ret = kvm_get_guest_memory_type(vcpu, gfn) <<
+		      VMX_EPT_MT_EPTE_SHIFT;
+	else
+		ret = (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT)
+			| VMX_EPT_IGMT_BIT;
+
+	return ret;
 }
 
 static struct kvm_x86_ops vmx_x86_ops = {
@@ -3644,7 +3707,7 @@
 	.check_processor_compatibility = vmx_check_processor_compat,
 	.hardware_enable = hardware_enable,
 	.hardware_disable = hardware_disable,
-	.cpu_has_accelerated_tpr = cpu_has_vmx_virtualize_apic_accesses,
+	.cpu_has_accelerated_tpr = report_flexpriority,
 
 	.vcpu_create = vmx_create_vcpu,
 	.vcpu_free = vmx_free_vcpu,
@@ -3678,78 +3741,82 @@
 	.tlb_flush = vmx_flush_tlb,
 
 	.run = vmx_vcpu_run,
-	.handle_exit = kvm_handle_exit,
+	.handle_exit = vmx_handle_exit,
 	.skip_emulated_instruction = skip_emulated_instruction,
+	.set_interrupt_shadow = vmx_set_interrupt_shadow,
+	.get_interrupt_shadow = vmx_get_interrupt_shadow,
 	.patch_hypercall = vmx_patch_hypercall,
-	.get_irq = vmx_get_irq,
 	.set_irq = vmx_inject_irq,
+	.set_nmi = vmx_inject_nmi,
 	.queue_exception = vmx_queue_exception,
-	.exception_injected = vmx_exception_injected,
-	.inject_pending_irq = vmx_intr_assist,
-	.inject_pending_vectors = do_interrupt_requests,
+	.interrupt_allowed = vmx_interrupt_allowed,
+	.nmi_allowed = vmx_nmi_allowed,
+	.enable_nmi_window = enable_nmi_window,
+	.enable_irq_window = enable_irq_window,
+	.update_cr8_intercept = update_cr8_intercept,
 
 	.set_tss_addr = vmx_set_tss_addr,
 	.get_tdp_level = get_ept_level,
-	.get_mt_mask_shift = vmx_get_mt_mask_shift,
+	.get_mt_mask = vmx_get_mt_mask,
 };
 
 static int __init vmx_init(void)
 {
-	void *va;
 	int r;
 
-	vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+	vmx_io_bitmap_a = (unsigned long *)__get_free_page(GFP_KERNEL);
 	if (!vmx_io_bitmap_a)
 		return -ENOMEM;
 
-	vmx_io_bitmap_b = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+	vmx_io_bitmap_b = (unsigned long *)__get_free_page(GFP_KERNEL);
 	if (!vmx_io_bitmap_b) {
 		r = -ENOMEM;
 		goto out;
 	}
 
-	vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
-	if (!vmx_msr_bitmap) {
+	vmx_msr_bitmap_legacy = (unsigned long *)__get_free_page(GFP_KERNEL);
+	if (!vmx_msr_bitmap_legacy) {
 		r = -ENOMEM;
 		goto out1;
 	}
 
+	vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL);
+	if (!vmx_msr_bitmap_longmode) {
+		r = -ENOMEM;
+		goto out2;
+	}
+
 	/*
 	 * Allow direct access to the PC debug port (it is often used for I/O
 	 * delays, but the vmexits simply slow things down).
 	 */
-	va = kmap(vmx_io_bitmap_a);
-	memset(va, 0xff, PAGE_SIZE);
-	clear_bit(0x80, va);
-	kunmap(vmx_io_bitmap_a);
+	memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE);
+	clear_bit(0x80, vmx_io_bitmap_a);
 
-	va = kmap(vmx_io_bitmap_b);
-	memset(va, 0xff, PAGE_SIZE);
-	kunmap(vmx_io_bitmap_b);
+	memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE);
 
-	va = kmap(vmx_msr_bitmap);
-	memset(va, 0xff, PAGE_SIZE);
-	kunmap(vmx_msr_bitmap);
+	memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE);
+	memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE);
 
 	set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
 
 	r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
 	if (r)
-		goto out2;
+		goto out3;
 
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_FS_BASE);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_GS_BASE);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_CS);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
+	vmx_disable_intercept_for_msr(MSR_FS_BASE, false);
+	vmx_disable_intercept_for_msr(MSR_GS_BASE, false);
+	vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true);
+	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
+	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
+	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
 
-	if (vm_need_ept()) {
+	if (enable_ept) {
 		bypass_guest_pf = 0;
 		kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
 			VMX_EPT_WRITABLE_MASK);
 		kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
-				VMX_EPT_EXECUTABLE_MASK,
-				VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
+				VMX_EPT_EXECUTABLE_MASK);
 		kvm_enable_tdp();
 	} else
 		kvm_disable_tdp();
@@ -3761,20 +3828,23 @@
 
 	return 0;
 
+out3:
+	free_page((unsigned long)vmx_msr_bitmap_longmode);
 out2:
-	__free_page(vmx_msr_bitmap);
+	free_page((unsigned long)vmx_msr_bitmap_legacy);
 out1:
-	__free_page(vmx_io_bitmap_b);
+	free_page((unsigned long)vmx_io_bitmap_b);
 out:
-	__free_page(vmx_io_bitmap_a);
+	free_page((unsigned long)vmx_io_bitmap_a);
 	return r;
 }
 
 static void __exit vmx_exit(void)
 {
-	__free_page(vmx_msr_bitmap);
-	__free_page(vmx_io_bitmap_b);
-	__free_page(vmx_io_bitmap_a);
+	free_page((unsigned long)vmx_msr_bitmap_legacy);
+	free_page((unsigned long)vmx_msr_bitmap_longmode);
+	free_page((unsigned long)vmx_io_bitmap_b);
+	free_page((unsigned long)vmx_io_bitmap_a);
 
 	kvm_exit();
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/x86.c linux-libre-2.6.31-gnu/arch/x86/kvm/x86.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/x86.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/x86.c	2009-09-09 18:13:59.000000000 -0400
@@ -91,7 +91,6 @@
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "hypercalls", VCPU_STAT(hypercalls) },
 	{ "request_irq", VCPU_STAT(request_irq_exits) },
-	{ "request_nmi", VCPU_STAT(request_nmi_exits) },
 	{ "irq_exits", VCPU_STAT(irq_exits) },
 	{ "host_state_reload", VCPU_STAT(host_state_reload) },
 	{ "efer_reload", VCPU_STAT(efer_reload) },
@@ -108,7 +107,6 @@
 	{ "mmu_recycled", VM_STAT(mmu_recycled) },
 	{ "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
 	{ "mmu_unsync", VM_STAT(mmu_unsync) },
-	{ "mmu_unsync_global", VM_STAT(mmu_unsync_global) },
 	{ "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
 	{ "largepages", VM_STAT(lpages) },
 	{ NULL }
@@ -234,7 +232,8 @@
 		goto out;
 	}
 	for (i = 0; i < ARRAY_SIZE(pdpte); ++i) {
-		if ((pdpte[i] & 1) && (pdpte[i] & 0xfffffff0000001e6ull)) {
+		if (is_present_pte(pdpte[i]) &&
+		    (pdpte[i] & vcpu->arch.mmu.rsvd_bits_mask[0][2])) {
 			ret = 0;
 			goto out;
 		}
@@ -321,7 +320,6 @@
 	kvm_x86_ops->set_cr0(vcpu, cr0);
 	vcpu->arch.cr0 = cr0;
 
-	kvm_mmu_sync_global(vcpu);
 	kvm_mmu_reset_context(vcpu);
 	return;
 }
@@ -370,7 +368,6 @@
 	kvm_x86_ops->set_cr4(vcpu, cr4);
 	vcpu->arch.cr4 = cr4;
 	vcpu->arch.mmu.base_role.cr4_pge = (cr4 & X86_CR4_PGE) && !tdp_enabled;
-	kvm_mmu_sync_global(vcpu);
 	kvm_mmu_reset_context(vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr4);
@@ -523,6 +520,9 @@
 	efer |= vcpu->arch.shadow_efer & EFER_LMA;
 
 	vcpu->arch.shadow_efer = efer;
+
+	vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
+	kvm_mmu_reset_context(vcpu);
 }
 
 void kvm_enable_efer_bits(u64 mask)
@@ -630,14 +630,17 @@
 	unsigned long flags;
 	struct kvm_vcpu_arch *vcpu = &v->arch;
 	void *shared_kaddr;
+	unsigned long this_tsc_khz;
 
 	if ((!vcpu->time_page))
 		return;
 
-	if (unlikely(vcpu->hv_clock_tsc_khz != __get_cpu_var(cpu_tsc_khz))) {
-		kvm_set_time_scale(__get_cpu_var(cpu_tsc_khz), &vcpu->hv_clock);
-		vcpu->hv_clock_tsc_khz = __get_cpu_var(cpu_tsc_khz);
+	this_tsc_khz = get_cpu_var(cpu_tsc_khz);
+	if (unlikely(vcpu->hv_clock_tsc_khz != this_tsc_khz)) {
+		kvm_set_time_scale(this_tsc_khz, &vcpu->hv_clock);
+		vcpu->hv_clock_tsc_khz = this_tsc_khz;
 	}
+	put_cpu_var(cpu_tsc_khz);
 
 	/* Keep irq disabled to prevent changes to the clock */
 	local_irq_save(flags);
@@ -701,11 +704,48 @@
 	return false;
 }
 
+static bool valid_pat_type(unsigned t)
+{
+	return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */
+}
+
+static bool valid_mtrr_type(unsigned t)
+{
+	return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */
+}
+
+static bool mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+	int i;
+
+	if (!msr_mtrr_valid(msr))
+		return false;
+
+	if (msr == MSR_IA32_CR_PAT) {
+		for (i = 0; i < 8; i++)
+			if (!valid_pat_type((data >> (i * 8)) & 0xff))
+				return false;
+		return true;
+	} else if (msr == MSR_MTRRdefType) {
+		if (data & ~0xcff)
+			return false;
+		return valid_mtrr_type(data & 0xff);
+	} else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) {
+		for (i = 0; i < 8 ; i++)
+			if (!valid_mtrr_type((data >> (i * 8)) & 0xff))
+				return false;
+		return true;
+	}
+
+	/* variable MTRRs */
+	return valid_mtrr_type(data & 0xff);
+}
+
 static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
 	u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
 
-	if (!msr_mtrr_valid(msr))
+	if (!mtrr_valid(vcpu, msr, data))
 		return 1;
 
 	if (msr == MSR_MTRRdefType) {
@@ -893,6 +933,9 @@
 	case MSR_IA32_LASTINTFROMIP:
 	case MSR_IA32_LASTINTTOIP:
 	case MSR_VM_HSAVE_PA:
+	case MSR_P6_EVNTSEL0:
+	case MSR_P6_EVNTSEL1:
+	case MSR_K7_EVNTSEL0:
 		data = 0;
 		break;
 	case MSR_MTRRcap:
@@ -1024,6 +1067,7 @@
 	case KVM_CAP_SYNC_MMU:
 	case KVM_CAP_REINJECT_CONTROL:
 	case KVM_CAP_IRQ_INJECT_STATUS:
+	case KVM_CAP_ASSIGN_DEV_IRQ:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -1072,14 +1116,13 @@
 		if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
 			goto out;
 		r = -E2BIG;
-		if (n < num_msrs_to_save)
+		if (n < msr_list.nmsrs)
 			goto out;
 		r = -EFAULT;
 		if (copy_to_user(user_msr_list->indices, &msrs_to_save,
 				 num_msrs_to_save * sizeof(u32)))
 			goto out;
-		if (copy_to_user(user_msr_list->indices
-				 + num_msrs_to_save * sizeof(u32),
+		if (copy_to_user(user_msr_list->indices + num_msrs_to_save,
 				 &emulated_msrs,
 				 ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
 			goto out;
@@ -1241,41 +1284,53 @@
 	entry->flags = 0;
 }
 
+#define F(x) bit(X86_FEATURE_##x)
+
 static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 			 u32 index, int *nent, int maxnent)
 {
-	const u32 kvm_supported_word0_x86_features = bit(X86_FEATURE_FPU) |
-		bit(X86_FEATURE_VME) | bit(X86_FEATURE_DE) |
-		bit(X86_FEATURE_PSE) | bit(X86_FEATURE_TSC) |
-		bit(X86_FEATURE_MSR) | bit(X86_FEATURE_PAE) |
-		bit(X86_FEATURE_CX8) | bit(X86_FEATURE_APIC) |
-		bit(X86_FEATURE_SEP) | bit(X86_FEATURE_PGE) |
-		bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PSE36) |
-		bit(X86_FEATURE_CLFLSH) | bit(X86_FEATURE_MMX) |
-		bit(X86_FEATURE_FXSR) | bit(X86_FEATURE_XMM) |
-		bit(X86_FEATURE_XMM2) | bit(X86_FEATURE_SELFSNOOP);
-	const u32 kvm_supported_word1_x86_features = bit(X86_FEATURE_FPU) |
-		bit(X86_FEATURE_VME) | bit(X86_FEATURE_DE) |
-		bit(X86_FEATURE_PSE) | bit(X86_FEATURE_TSC) |
-		bit(X86_FEATURE_MSR) | bit(X86_FEATURE_PAE) |
-		bit(X86_FEATURE_CX8) | bit(X86_FEATURE_APIC) |
-		bit(X86_FEATURE_PGE) |
-		bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PSE36) |
-		bit(X86_FEATURE_MMX) | bit(X86_FEATURE_FXSR) |
-		bit(X86_FEATURE_SYSCALL) |
-		(is_efer_nx() ? bit(X86_FEATURE_NX) : 0) |
+	unsigned f_nx = is_efer_nx() ? F(NX) : 0;
 #ifdef CONFIG_X86_64
-		bit(X86_FEATURE_LM) |
+	unsigned f_lm = F(LM);
+#else
+	unsigned f_lm = 0;
 #endif
-		bit(X86_FEATURE_FXSR_OPT) |
-		bit(X86_FEATURE_MMXEXT) |
-		bit(X86_FEATURE_3DNOWEXT) |
-		bit(X86_FEATURE_3DNOW);
-	const u32 kvm_supported_word3_x86_features =
-		bit(X86_FEATURE_XMM3) | bit(X86_FEATURE_CX16);
+
+	/* cpuid 1.edx */
+	const u32 kvm_supported_word0_x86_features =
+		F(FPU) | F(VME) | F(DE) | F(PSE) |
+		F(TSC) | F(MSR) | F(PAE) | F(MCE) |
+		F(CX8) | F(APIC) | 0 /* Reserved */ | F(SEP) |
+		F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
+		F(PAT) | F(PSE36) | 0 /* PSN */ | F(CLFLSH) |
+		0 /* Reserved, DS, ACPI */ | F(MMX) |
+		F(FXSR) | F(XMM) | F(XMM2) | F(SELFSNOOP) |
+		0 /* HTT, TM, Reserved, PBE */;
+	/* cpuid 0x80000001.edx */
+	const u32 kvm_supported_word1_x86_features =
+		F(FPU) | F(VME) | F(DE) | F(PSE) |
+		F(TSC) | F(MSR) | F(PAE) | F(MCE) |
+		F(CX8) | F(APIC) | 0 /* Reserved */ | F(SYSCALL) |
+		F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
+		F(PAT) | F(PSE36) | 0 /* Reserved */ |
+		f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
+		F(FXSR) | F(FXSR_OPT) | 0 /* GBPAGES */ | 0 /* RDTSCP */ |
+		0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW);
+	/* cpuid 1.ecx */
+	const u32 kvm_supported_word4_x86_features =
+		F(XMM3) | 0 /* Reserved, DTES64, MONITOR */ |
+		0 /* DS-CPL, VMX, SMX, EST */ |
+		0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ |
+		0 /* Reserved */ | F(CX16) | 0 /* xTPR Update, PDCM */ |
+		0 /* Reserved, DCA */ | F(XMM4_1) |
+		F(XMM4_2) | 0 /* x2APIC */ | F(MOVBE) | F(POPCNT) |
+		0 /* Reserved, XSAVE, OSXSAVE */;
+	/* cpuid 0x80000001.ecx */
 	const u32 kvm_supported_word6_x86_features =
-		bit(X86_FEATURE_LAHF_LM) | bit(X86_FEATURE_CMP_LEGACY) |
-		bit(X86_FEATURE_SVM);
+		F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ |
+		F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
+		F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(SSE5) |
+		0 /* SKINIT */ | 0 /* WDT */;
 
 	/* all calls to cpuid_count() should be made on the same cpu */
 	get_cpu();
@@ -1288,7 +1343,7 @@
 		break;
 	case 1:
 		entry->edx &= kvm_supported_word0_x86_features;
-		entry->ecx &= kvm_supported_word3_x86_features;
+		entry->ecx &= kvm_supported_word4_x86_features;
 		break;
 	/* function 2 entries are STATEFUL. That is, repeated cpuid commands
 	 * may return different values. This forces us to get_cpu() before
@@ -1350,6 +1405,8 @@
 	put_cpu();
 }
 
+#undef F
+
 static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
 				     struct kvm_cpuid_entry2 __user *entries)
 {
@@ -1421,8 +1478,7 @@
 		return -ENXIO;
 	vcpu_load(vcpu);
 
-	set_bit(irq->irq, vcpu->arch.irq_pending);
-	set_bit(irq->irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
+	kvm_queue_interrupt(vcpu, irq->irq, false);
 
 	vcpu_put(vcpu);
 
@@ -1584,8 +1640,7 @@
 		r = -EINVAL;
 	}
 out:
-	if (lapic)
-		kfree(lapic);
+	kfree(lapic);
 	return r;
 }
 
@@ -1606,10 +1661,12 @@
 		return -EINVAL;
 
 	down_write(&kvm->slots_lock);
+	spin_lock(&kvm->mmu_lock);
 
 	kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages);
 	kvm->arch.n_requested_mmu_pages = kvm_nr_mmu_pages;
 
+	spin_unlock(&kvm->mmu_lock);
 	up_write(&kvm->slots_lock);
 	return 0;
 }
@@ -1785,7 +1842,9 @@
 
 	/* If nothing is dirty, don't bother messing with page tables. */
 	if (is_dirty) {
+		spin_lock(&kvm->mmu_lock);
 		kvm_mmu_slot_remove_write_access(kvm, log->slot);
+		spin_unlock(&kvm->mmu_lock);
 		kvm_flush_remote_tlbs(kvm);
 		memslot = &kvm->memslots[log->slot];
 		n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
@@ -2360,7 +2419,7 @@
 			u16 error_code,
 			int emulation_type)
 {
-	int r;
+	int r, shadow_mask;
 	struct decode_cache *c;
 
 	kvm_clear_exception_queue(vcpu);
@@ -2408,7 +2467,16 @@
 		}
 	}
 
+	if (emulation_type & EMULTYPE_SKIP) {
+		kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.decode.eip);
+		return EMULATE_DONE;
+	}
+
 	r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
+	shadow_mask = vcpu->arch.emulate_ctxt.interruptibility;
+
+	if (r == 0)
+		kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask);
 
 	if (vcpu->arch.pio.string)
 		return EMULATE_DO_MMIO;
@@ -2761,7 +2829,7 @@
 	kvm_mmu_set_nonpresent_ptes(0ull, 0ull);
 	kvm_mmu_set_base_ptes(PT_PRESENT_MASK);
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
-			PT_DIRTY_MASK, PT64_NX_MASK, 0, 0);
+			PT_DIRTY_MASK, PT64_NX_MASK, 0);
 
 	for_each_possible_cpu(cpu)
 		per_cpu(cpu_tsc_khz, cpu) = tsc_khz;
@@ -3012,6 +3080,16 @@
 	return best;
 }
 
+int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
+	if (best)
+		return best->eax & 0xff;
+	return 36;
+}
+
 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
 {
 	u32 function, index;
@@ -3048,10 +3126,9 @@
 static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
 					  struct kvm_run *kvm_run)
 {
-	return (!vcpu->arch.irq_summary &&
+	return (!irqchip_in_kernel(vcpu->kvm) && !kvm_cpu_has_interrupt(vcpu) &&
 		kvm_run->request_interrupt_window &&
-		vcpu->arch.interrupt_window_open &&
-		(kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF));
+		kvm_arch_interrupt_allowed(vcpu));
 }
 
 static void post_kvm_run_save(struct kvm_vcpu *vcpu,
@@ -3064,8 +3141,9 @@
 		kvm_run->ready_for_interrupt_injection = 1;
 	else
 		kvm_run->ready_for_interrupt_injection =
-					(vcpu->arch.interrupt_window_open &&
-					 vcpu->arch.irq_summary == 0);
+			kvm_arch_interrupt_allowed(vcpu) &&
+			!kvm_cpu_has_interrupt(vcpu) &&
+			!kvm_event_needs_reinjection(vcpu);
 }
 
 static void vapic_enter(struct kvm_vcpu *vcpu)
@@ -3094,9 +3172,63 @@
 	up_read(&vcpu->kvm->slots_lock);
 }
 
+static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+{
+	int max_irr, tpr;
+
+	if (!kvm_x86_ops->update_cr8_intercept)
+		return;
+
+	if (!vcpu->arch.apic->vapic_addr)
+		max_irr = kvm_lapic_find_highest_irr(vcpu);
+	else
+		max_irr = -1;
+
+	if (max_irr != -1)
+		max_irr >>= 4;
+
+	tpr = kvm_lapic_get_cr8(vcpu);
+
+	kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);
+}
+
+static void inject_pending_irq(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+		kvm_x86_ops->set_interrupt_shadow(vcpu, 0);
+
+	/* try to reinject previous events if any */
+	if (vcpu->arch.nmi_injected) {
+		kvm_x86_ops->set_nmi(vcpu);
+		return;
+	}
+
+	if (vcpu->arch.interrupt.pending) {
+		kvm_x86_ops->set_irq(vcpu);
+		return;
+	}
+
+	/* try to inject new event if pending */
+	if (vcpu->arch.nmi_pending) {
+		if (kvm_x86_ops->nmi_allowed(vcpu)) {
+			vcpu->arch.nmi_pending = false;
+			vcpu->arch.nmi_injected = true;
+			kvm_x86_ops->set_nmi(vcpu);
+		}
+	} else if (kvm_cpu_has_interrupt(vcpu)) {
+		if (kvm_x86_ops->interrupt_allowed(vcpu)) {
+			kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu),
+					    false);
+			kvm_x86_ops->set_irq(vcpu);
+		}
+	}
+}
+
 static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	int r;
+	bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+		kvm_run->request_interrupt_window;
 
 	if (vcpu->requests)
 		if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
@@ -3128,9 +3260,6 @@
 		}
 	}
 
-	clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
-	kvm_inject_pending_timer_irqs(vcpu);
-
 	preempt_disable();
 
 	kvm_x86_ops->prepare_guest_switch(vcpu);
@@ -3138,6 +3267,9 @@
 
 	local_irq_disable();
 
+	clear_bit(KVM_REQ_KICK, &vcpu->requests);
+	smp_mb__after_clear_bit();
+
 	if (vcpu->requests || need_resched() || signal_pending(current)) {
 		local_irq_enable();
 		preempt_enable();
@@ -3145,21 +3277,21 @@
 		goto out;
 	}
 
-	vcpu->guest_mode = 1;
-	/*
-	 * Make sure that guest_mode assignment won't happen after
-	 * testing the pending IRQ vector bitmap.
-	 */
-	smp_wmb();
-
 	if (vcpu->arch.exception.pending)
 		__queue_exception(vcpu);
-	else if (irqchip_in_kernel(vcpu->kvm))
-		kvm_x86_ops->inject_pending_irq(vcpu);
 	else
-		kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
+		inject_pending_irq(vcpu, kvm_run);
 
-	kvm_lapic_sync_to_vapic(vcpu);
+	/* enable NMI/IRQ window open exits if needed */
+	if (vcpu->arch.nmi_pending)
+		kvm_x86_ops->enable_nmi_window(vcpu);
+	else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+		kvm_x86_ops->enable_irq_window(vcpu);
+
+	if (kvm_lapic_enabled(vcpu)) {
+		update_cr8_intercept(vcpu);
+		kvm_lapic_sync_to_vapic(vcpu);
+	}
 
 	up_read(&vcpu->kvm->slots_lock);
 
@@ -3193,7 +3325,7 @@
 	set_debugreg(vcpu->arch.host_dr6, 6);
 	set_debugreg(vcpu->arch.host_dr7, 7);
 
-	vcpu->guest_mode = 0;
+	set_bit(KVM_REQ_KICK, &vcpu->requests);
 	local_irq_enable();
 
 	++vcpu->stat.exits;
@@ -3220,8 +3352,6 @@
 		profile_hit(KVM_PROFILING, (void *)rip);
 	}
 
-	if (vcpu->arch.exception.pending && kvm_x86_ops->exception_injected(vcpu))
-		vcpu->arch.exception.pending = false;
 
 	kvm_lapic_sync_from_vapic(vcpu);
 
@@ -3230,6 +3360,7 @@
 	return r;
 }
 
+
 static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	int r;
@@ -3256,29 +3387,42 @@
 			kvm_vcpu_block(vcpu);
 			down_read(&vcpu->kvm->slots_lock);
 			if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
-				if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
+			{
+				switch(vcpu->arch.mp_state) {
+				case KVM_MP_STATE_HALTED:
 					vcpu->arch.mp_state =
-							KVM_MP_STATE_RUNNABLE;
-			if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
-				r = -EINTR;
+						KVM_MP_STATE_RUNNABLE;
+				case KVM_MP_STATE_RUNNABLE:
+					break;
+				case KVM_MP_STATE_SIPI_RECEIVED:
+				default:
+					r = -EINTR;
+					break;
+				}
+			}
 		}
 
-		if (r > 0) {
-			if (dm_request_for_irq_injection(vcpu, kvm_run)) {
-				r = -EINTR;
-				kvm_run->exit_reason = KVM_EXIT_INTR;
-				++vcpu->stat.request_irq_exits;
-			}
-			if (signal_pending(current)) {
-				r = -EINTR;
-				kvm_run->exit_reason = KVM_EXIT_INTR;
-				++vcpu->stat.signal_exits;
-			}
-			if (need_resched()) {
-				up_read(&vcpu->kvm->slots_lock);
-				kvm_resched(vcpu);
-				down_read(&vcpu->kvm->slots_lock);
-			}
+		if (r <= 0)
+			break;
+
+		clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
+		if (kvm_cpu_has_pending_timer(vcpu))
+			kvm_inject_pending_timer_irqs(vcpu);
+
+		if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+			r = -EINTR;
+			kvm_run->exit_reason = KVM_EXIT_INTR;
+			++vcpu->stat.request_irq_exits;
+		}
+		if (signal_pending(current)) {
+			r = -EINTR;
+			kvm_run->exit_reason = KVM_EXIT_INTR;
+			++vcpu->stat.signal_exits;
+		}
+		if (need_resched()) {
+			up_read(&vcpu->kvm->slots_lock);
+			kvm_resched(vcpu);
+			down_read(&vcpu->kvm->slots_lock);
 		}
 	}
 
@@ -3442,7 +3586,6 @@
 				  struct kvm_sregs *sregs)
 {
 	struct descriptor_table dt;
-	int pending_vec;
 
 	vcpu_load(vcpu);
 
@@ -3472,16 +3615,11 @@
 	sregs->efer = vcpu->arch.shadow_efer;
 	sregs->apic_base = kvm_get_apic_base(vcpu);
 
-	if (irqchip_in_kernel(vcpu->kvm)) {
-		memset(sregs->interrupt_bitmap, 0,
-		       sizeof sregs->interrupt_bitmap);
-		pending_vec = kvm_x86_ops->get_irq(vcpu);
-		if (pending_vec >= 0)
-			set_bit(pending_vec,
-				(unsigned long *)sregs->interrupt_bitmap);
-	} else
-		memcpy(sregs->interrupt_bitmap, vcpu->arch.irq_pending,
-		       sizeof sregs->interrupt_bitmap);
+	memset(sregs->interrupt_bitmap, 0, sizeof sregs->interrupt_bitmap);
+
+	if (vcpu->arch.interrupt.pending && !vcpu->arch.interrupt.soft)
+		set_bit(vcpu->arch.interrupt.nr,
+			(unsigned long *)sregs->interrupt_bitmap);
 
 	vcpu_put(vcpu);
 
@@ -3688,7 +3826,6 @@
 	tss->fs = get_segment_selector(vcpu, VCPU_SREG_FS);
 	tss->gs = get_segment_selector(vcpu, VCPU_SREG_GS);
 	tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR);
-	tss->prev_task_link = get_segment_selector(vcpu, VCPU_SREG_TR);
 }
 
 static int load_state_from_tss32(struct kvm_vcpu *vcpu,
@@ -3785,8 +3922,8 @@
 }
 
 static int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector,
-		       u32 old_tss_base,
-		       struct desc_struct *nseg_desc)
+			      u16 old_tss_sel, u32 old_tss_base,
+			      struct desc_struct *nseg_desc)
 {
 	struct tss_segment_16 tss_segment_16;
 	int ret = 0;
@@ -3805,6 +3942,16 @@
 			   &tss_segment_16, sizeof tss_segment_16))
 		goto out;
 
+	if (old_tss_sel != 0xffff) {
+		tss_segment_16.prev_task_link = old_tss_sel;
+
+		if (kvm_write_guest(vcpu->kvm,
+				    get_tss_base_addr(vcpu, nseg_desc),
+				    &tss_segment_16.prev_task_link,
+				    sizeof tss_segment_16.prev_task_link))
+			goto out;
+	}
+
 	if (load_state_from_tss16(vcpu, &tss_segment_16))
 		goto out;
 
@@ -3814,7 +3961,7 @@
 }
 
 static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector,
-		       u32 old_tss_base,
+		       u16 old_tss_sel, u32 old_tss_base,
 		       struct desc_struct *nseg_desc)
 {
 	struct tss_segment_32 tss_segment_32;
@@ -3834,6 +3981,16 @@
 			   &tss_segment_32, sizeof tss_segment_32))
 		goto out;
 
+	if (old_tss_sel != 0xffff) {
+		tss_segment_32.prev_task_link = old_tss_sel;
+
+		if (kvm_write_guest(vcpu->kvm,
+				    get_tss_base_addr(vcpu, nseg_desc),
+				    &tss_segment_32.prev_task_link,
+				    sizeof tss_segment_32.prev_task_link))
+			goto out;
+	}
+
 	if (load_state_from_tss32(vcpu, &tss_segment_32))
 		goto out;
 
@@ -3887,14 +4044,22 @@
 		kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT);
 	}
 
-	kvm_x86_ops->skip_emulated_instruction(vcpu);
+	/* set back link to prev task only if NT bit is set in eflags
+	   note that old_tss_sel is not used afetr this point */
+	if (reason != TASK_SWITCH_CALL && reason != TASK_SWITCH_GATE)
+		old_tss_sel = 0xffff;
+
+	/* set back link to prev task only if NT bit is set in eflags
+	   note that old_tss_sel is not used afetr this point */
+	if (reason != TASK_SWITCH_CALL && reason != TASK_SWITCH_GATE)
+		old_tss_sel = 0xffff;
 
 	if (nseg_desc.type & 8)
-		ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_base,
-					 &nseg_desc);
+		ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_sel,
+					 old_tss_base, &nseg_desc);
 	else
-		ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_base,
-					 &nseg_desc);
+		ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_sel,
+					 old_tss_base, &nseg_desc);
 
 	if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) {
 		u32 eflags = kvm_x86_ops->get_rflags(vcpu);
@@ -3920,7 +4085,7 @@
 				  struct kvm_sregs *sregs)
 {
 	int mmu_reset_needed = 0;
-	int i, pending_vec, max_bits;
+	int pending_vec, max_bits;
 	struct descriptor_table dt;
 
 	vcpu_load(vcpu);
@@ -3934,7 +4099,13 @@
 
 	vcpu->arch.cr2 = sregs->cr2;
 	mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3;
-	vcpu->arch.cr3 = sregs->cr3;
+
+	down_read(&vcpu->kvm->slots_lock);
+	if (gfn_to_memslot(vcpu->kvm, sregs->cr3 >> PAGE_SHIFT))
+		vcpu->arch.cr3 = sregs->cr3;
+	else
+		set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
+	up_read(&vcpu->kvm->slots_lock);
 
 	kvm_set_cr8(vcpu, sregs->cr8);
 
@@ -3956,25 +4127,14 @@
 	if (mmu_reset_needed)
 		kvm_mmu_reset_context(vcpu);
 
-	if (!irqchip_in_kernel(vcpu->kvm)) {
-		memcpy(vcpu->arch.irq_pending, sregs->interrupt_bitmap,
-		       sizeof vcpu->arch.irq_pending);
-		vcpu->arch.irq_summary = 0;
-		for (i = 0; i < ARRAY_SIZE(vcpu->arch.irq_pending); ++i)
-			if (vcpu->arch.irq_pending[i])
-				__set_bit(i, &vcpu->arch.irq_summary);
-	} else {
-		max_bits = (sizeof sregs->interrupt_bitmap) << 3;
-		pending_vec = find_first_bit(
-			(const unsigned long *)sregs->interrupt_bitmap,
-			max_bits);
-		/* Only pending external irq is handled here */
-		if (pending_vec < max_bits) {
-			kvm_x86_ops->set_irq(vcpu, pending_vec);
-			pr_debug("Set back pending irq %d\n",
-				 pending_vec);
-		}
-		kvm_pic_clear_isr_ack(vcpu->kvm);
+	max_bits = (sizeof sregs->interrupt_bitmap) << 3;
+	pending_vec = find_first_bit(
+		(const unsigned long *)sregs->interrupt_bitmap, max_bits);
+	if (pending_vec < max_bits) {
+		kvm_queue_interrupt(vcpu, pending_vec, false);
+		pr_debug("Set back pending irq %d\n", pending_vec);
+		if (irqchip_in_kernel(vcpu->kvm))
+			kvm_pic_clear_isr_ack(vcpu->kvm);
 	}
 
 	kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
@@ -4308,7 +4468,6 @@
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
-	INIT_LIST_HEAD(&kvm->arch.oos_global_pages);
 	INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 
 	/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
@@ -4411,12 +4570,14 @@
 		}
 	}
 
+	spin_lock(&kvm->mmu_lock);
 	if (!kvm->arch.n_requested_mmu_pages) {
 		unsigned int nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
 		kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
 	}
 
 	kvm_mmu_slot_remove_write_access(kvm, mem->slot);
+	spin_unlock(&kvm->mmu_lock);
 	kvm_flush_remote_tlbs(kvm);
 
 	return 0;
@@ -4425,6 +4586,7 @@
 void kvm_arch_flush_shadow(struct kvm *kvm)
 {
 	kvm_mmu_zap_all(kvm);
+	kvm_reload_remote_mmus(kvm);
 }
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
@@ -4434,28 +4596,24 @@
 	       || vcpu->arch.nmi_pending;
 }
 
-static void vcpu_kick_intr(void *info)
-{
-#ifdef DEBUG
-	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info;
-	printk(KERN_DEBUG "vcpu_kick_intr %p \n", vcpu);
-#endif
-}
-
 void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 {
-	int ipi_pcpu = vcpu->cpu;
-	int cpu = get_cpu();
+	int me;
+	int cpu = vcpu->cpu;
 
 	if (waitqueue_active(&vcpu->wq)) {
 		wake_up_interruptible(&vcpu->wq);
 		++vcpu->stat.halt_wakeup;
 	}
-	/*
-	 * We may be called synchronously with irqs disabled in guest mode,
-	 * So need not to call smp_call_function_single() in that case.
-	 */
-	if (vcpu->guest_mode && vcpu->cpu != cpu)
-		smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0);
+
+	me = get_cpu();
+	if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu))
+		if (!test_and_set_bit(KVM_REQ_KICK, &vcpu->requests))
+			smp_send_reschedule(cpu);
 	put_cpu();
 }
+
+int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+	return kvm_x86_ops->interrupt_allowed(vcpu);
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/x86_emulate.c linux-libre-2.6.31-gnu/arch/x86/kvm/x86_emulate.c
--- linux-libre-2.6.30-gnu/arch/x86/kvm/x86_emulate.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/x86_emulate.c	2009-09-09 18:13:59.000000000 -0400
@@ -59,13 +59,14 @@
 #define SrcImm      (5<<4)	/* Immediate operand. */
 #define SrcImmByte  (6<<4)	/* 8-bit sign-extended immediate operand. */
 #define SrcOne      (7<<4)	/* Implied '1' */
-#define SrcMask     (7<<4)
+#define SrcImmUByte (8<<4)      /* 8-bit unsigned immediate operand. */
+#define SrcMask     (0xf<<4)
 /* Generic ModRM decode. */
-#define ModRM       (1<<7)
+#define ModRM       (1<<8)
 /* Destination is only written; never read. */
-#define Mov         (1<<8)
-#define BitOp       (1<<9)
-#define MemAbs      (1<<10)      /* Memory operand is absolute displacement */
+#define Mov         (1<<9)
+#define BitOp       (1<<10)
+#define MemAbs      (1<<11)      /* Memory operand is absolute displacement */
 #define String      (1<<12)     /* String instruction (rep capable) */
 #define Stack       (1<<13)     /* Stack instruction (push/pop) */
 #define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
@@ -76,6 +77,7 @@
 #define Src2CL      (1<<29)
 #define Src2ImmByte (2<<29)
 #define Src2One     (3<<29)
+#define Src2Imm16   (4<<29)
 #define Src2Mask    (7<<29)
 
 enum {
@@ -135,11 +137,11 @@
 	SrcNone  | ByteOp  | ImplicitOps, SrcNone  | ImplicitOps, /* insb, insw/insd */
 	SrcNone  | ByteOp  | ImplicitOps, SrcNone  | ImplicitOps, /* outsb, outsw/outsd */
 	/* 0x70 - 0x77 */
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+	SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
+	SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
 	/* 0x78 - 0x7F */
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+	SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
+	SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
 	/* 0x80 - 0x87 */
 	Group | Group1_80, Group | Group1_81,
 	Group | Group1_82, Group | Group1_83,
@@ -153,7 +155,8 @@
 	/* 0x90 - 0x97 */
 	DstReg, DstReg, DstReg, DstReg,	DstReg, DstReg, DstReg, DstReg,
 	/* 0x98 - 0x9F */
-	0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
+	0, 0, SrcImm | Src2Imm16, 0,
+	ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
 	/* 0xA0 - 0xA7 */
 	ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
 	ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
@@ -178,7 +181,8 @@
 	0, ImplicitOps | Stack, 0, 0,
 	ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,
 	/* 0xC8 - 0xCF */
-	0, 0, 0, ImplicitOps | Stack, 0, 0, 0, 0,
+	0, 0, 0, ImplicitOps | Stack,
+	ImplicitOps, SrcImmByte, ImplicitOps, ImplicitOps,
 	/* 0xD0 - 0xD7 */
 	ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
 	ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM,
@@ -187,11 +191,11 @@
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xE0 - 0xE7 */
 	0, 0, 0, 0,
-	SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
-	SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
+	ByteOp | SrcImmUByte, SrcImmUByte,
+	ByteOp | SrcImmUByte, SrcImmUByte,
 	/* 0xE8 - 0xEF */
-	ImplicitOps | Stack, SrcImm | ImplicitOps,
-	ImplicitOps, SrcImmByte | ImplicitOps,
+	SrcImm | Stack, SrcImm | ImplicitOps,
+	SrcImm | Src2Imm16, SrcImmByte | ImplicitOps,
 	SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
 	SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
 	/* 0xF0 - 0xF7 */
@@ -230,10 +234,8 @@
 	/* 0x70 - 0x7F */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x80 - 0x8F */
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
-	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+	SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm,
+	SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm,
 	/* 0x90 - 0x9F */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xA0 - 0xA7 */
@@ -1044,10 +1046,14 @@
 		}
 		break;
 	case SrcImmByte:
+	case SrcImmUByte:
 		c->src.type = OP_IMM;
 		c->src.ptr = (unsigned long *)c->eip;
 		c->src.bytes = 1;
-		c->src.val = insn_fetch(s8, 1, c->eip);
+		if ((c->d & SrcMask) == SrcImmByte)
+			c->src.val = insn_fetch(s8, 1, c->eip);
+		else
+			c->src.val = insn_fetch(u8, 1, c->eip);
 		break;
 	case SrcOne:
 		c->src.bytes = 1;
@@ -1072,6 +1078,12 @@
 		c->src2.bytes = 1;
 		c->src2.val = insn_fetch(u8, 1, c->eip);
 		break;
+	case Src2Imm16:
+		c->src2.type = OP_IMM;
+		c->src2.ptr = (unsigned long *)c->eip;
+		c->src2.bytes = 2;
+		c->src2.val = insn_fetch(u16, 2, c->eip);
+		break;
 	case Src2One:
 		c->src2.bytes = 1;
 		c->src2.val = 1;
@@ -1349,6 +1361,20 @@
 	return 0;
 }
 
+static void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask)
+{
+	u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(ctxt->vcpu, mask);
+	/*
+	 * an sti; sti; sequence only disable interrupts for the first
+	 * instruction. So, if the last instruction, be it emulated or
+	 * not, left the system with the INT_STI flag enabled, it
+	 * means that the last instruction is an sti. We should not
+	 * leave the flag on in this case. The same goes for mov ss
+	 */
+	if (!(int_shadow & mask))
+		ctxt->interruptibility = mask;
+}
+
 int
 x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
@@ -1360,6 +1386,8 @@
 	int io_dir_in;
 	int rc = 0;
 
+	ctxt->interruptibility = 0;
+
 	/* Shadow copy of register state. Committed on successful emulation.
 	 * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
 	 * modify them.
@@ -1531,13 +1559,10 @@
 			return -1;
 		}
 		return 0;
-	case 0x70 ... 0x7f: /* jcc (short) */ {
-		int rel = insn_fetch(s8, 1, c->eip);
-
+	case 0x70 ... 0x7f: /* jcc (short) */
 		if (test_cc(c->b, ctxt->eflags))
-			jmp_rel(c, rel);
+			jmp_rel(c, c->src.val);
 		break;
-	}
 	case 0x80 ... 0x83:	/* Grp1 */
 		switch (c->modrm_reg) {
 		case 0:
@@ -1609,6 +1634,9 @@
 		int err;
 
 		sel = c->src.val;
+		if (c->modrm_reg == VCPU_SREG_SS)
+			toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
+
 		if (c->modrm_reg <= 5) {
 			type_bits = (c->modrm_reg == 1) ? 9 : 1;
 			err = kvm_load_segment_descriptor(ctxt->vcpu, sel,
@@ -1769,59 +1797,32 @@
 		break;
 	case 0xe4: 	/* inb */
 	case 0xe5: 	/* in */
-		port = insn_fetch(u8, 1, c->eip);
+		port = c->src.val;
 		io_dir_in = 1;
 		goto do_io;
 	case 0xe6: /* outb */
 	case 0xe7: /* out */
-		port = insn_fetch(u8, 1, c->eip);
+		port = c->src.val;
 		io_dir_in = 0;
 		goto do_io;
 	case 0xe8: /* call (near) */ {
-		long int rel;
-		switch (c->op_bytes) {
-		case 2:
-			rel = insn_fetch(s16, 2, c->eip);
-			break;
-		case 4:
-			rel = insn_fetch(s32, 4, c->eip);
-			break;
-		default:
-			DPRINTF("Call: Invalid op_bytes\n");
-			goto cannot_emulate;
-		}
+		long int rel = c->src.val;
 		c->src.val = (unsigned long) c->eip;
 		jmp_rel(c, rel);
-		c->op_bytes = c->ad_bytes;
 		emulate_push(ctxt);
 		break;
 	}
 	case 0xe9: /* jmp rel */
 		goto jmp;
-	case 0xea: /* jmp far */ {
-		uint32_t eip;
-		uint16_t sel;
-
-		switch (c->op_bytes) {
-		case 2:
-			eip = insn_fetch(u16, 2, c->eip);
-			break;
-		case 4:
-			eip = insn_fetch(u32, 4, c->eip);
-			break;
-		default:
-			DPRINTF("jmp far: Invalid op_bytes\n");
-			goto cannot_emulate;
-		}
-		sel = insn_fetch(u16, 2, c->eip);
-		if (kvm_load_segment_descriptor(ctxt->vcpu, sel, 9, VCPU_SREG_CS) < 0) {
+	case 0xea: /* jmp far */
+		if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, 9,
+					VCPU_SREG_CS) < 0) {
 			DPRINTF("jmp far: Failed to load CS descriptor\n");
 			goto cannot_emulate;
 		}
 
-		c->eip = eip;
+		c->eip = c->src.val;
 		break;
-	}
 	case 0xeb:
 	      jmp:		/* jmp rel short */
 		jmp_rel(c, c->src.val);
@@ -1865,6 +1866,7 @@
 		c->dst.type = OP_NONE;	/* Disable writeback. */
 		break;
 	case 0xfb: /* sti */
+		toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
 		ctxt->eflags |= X86_EFLAGS_IF;
 		c->dst.type = OP_NONE;	/* Disable writeback. */
 		break;
@@ -2039,28 +2041,11 @@
 		if (!test_cc(c->b, ctxt->eflags))
 			c->dst.type = OP_NONE; /* no writeback */
 		break;
-	case 0x80 ... 0x8f: /* jnz rel, etc*/ {
-		long int rel;
-
-		switch (c->op_bytes) {
-		case 2:
-			rel = insn_fetch(s16, 2, c->eip);
-			break;
-		case 4:
-			rel = insn_fetch(s32, 4, c->eip);
-			break;
-		case 8:
-			rel = insn_fetch(s64, 8, c->eip);
-			break;
-		default:
-			DPRINTF("jnz: Invalid op_bytes\n");
-			goto cannot_emulate;
-		}
+	case 0x80 ... 0x8f: /* jnz rel, etc*/
 		if (test_cc(c->b, ctxt->eflags))
-			jmp_rel(c, rel);
+			jmp_rel(c, c->src.val);
 		c->dst.type = OP_NONE;
 		break;
-	}
 	case 0xa3:
 	      bt:		/* bt */
 		c->dst.type = OP_NONE;
diff -druN linux-libre-2.6.30-gnu/arch/x86/kvm/x86.h linux-libre-2.6.31-gnu/arch/x86/kvm/x86.h
--- linux-libre-2.6.30-gnu/arch/x86/kvm/x86.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/kvm/x86.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,9 +8,11 @@
 	vcpu->arch.exception.pending = false;
 }
 
-static inline void kvm_queue_interrupt(struct kvm_vcpu *vcpu, u8 vector)
+static inline void kvm_queue_interrupt(struct kvm_vcpu *vcpu, u8 vector,
+	bool soft)
 {
 	vcpu->arch.interrupt.pending = true;
+	vcpu->arch.interrupt.soft = soft;
 	vcpu->arch.interrupt.nr = vector;
 }
 
@@ -19,4 +21,14 @@
 	vcpu->arch.interrupt.pending = false;
 }
 
+static inline bool kvm_event_needs_reinjection(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.exception.pending || vcpu->arch.interrupt.pending ||
+		vcpu->arch.nmi_injected;
+}
+
+static inline bool kvm_exception_is_soft(unsigned int nr)
+{
+	return (nr == BP_VECTOR) || (nr == OF_VECTOR);
+}
 #endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/lguest/boot.c linux-libre-2.6.31-gnu/arch/x86/lguest/boot.c
--- linux-libre-2.6.30-gnu/arch/x86/lguest/boot.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lguest/boot.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,8 @@
  *
  * So how does the kernel know it's a Guest?  We'll see that later, but let's
  * just say that we end up here where we replace the native functions various
- * "paravirt" structures with our Guest versions, then boot like normal. :*/
+ * "paravirt" structures with our Guest versions, then boot like normal.
+:*/
 
 /*
  * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation.
@@ -74,7 +75,8 @@
  *
  * The Guest in our tale is a simple creature: identical to the Host but
  * behaving in simplified but equivalent ways.  In particular, the Guest is the
- * same kernel as the Host (or at least, built from the same source code). :*/
+ * same kernel as the Host (or at least, built from the same source code).
+:*/
 
 struct lguest_data lguest_data = {
 	.hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF },
@@ -85,35 +87,41 @@
 	.syscall_vec = SYSCALL_VECTOR,
 };
 
-/*G:037 async_hcall() is pretty simple: I'm quite proud of it really.  We have a
+/*G:037
+ * async_hcall() is pretty simple: I'm quite proud of it really.  We have a
  * ring buffer of stored hypercalls which the Host will run though next time we
- * do a normal hypercall.  Each entry in the ring has 4 slots for the hypercall
+ * do a normal hypercall.  Each entry in the ring has 5 slots for the hypercall
  * arguments, and a "hcall_status" word which is 0 if the call is ready to go,
  * and 255 once the Host has finished with it.
  *
  * If we come around to a slot which hasn't been finished, then the table is
  * full and we just make the hypercall directly.  This has the nice side
  * effect of causing the Host to run all the stored calls in the ring buffer
- * which empties it for next time! */
+ * which empties it for next time!
+ */
 static void async_hcall(unsigned long call, unsigned long arg1,
-			unsigned long arg2, unsigned long arg3)
+			unsigned long arg2, unsigned long arg3,
+			unsigned long arg4)
 {
 	/* Note: This code assumes we're uniprocessor. */
 	static unsigned int next_call;
 	unsigned long flags;
 
-	/* Disable interrupts if not already disabled: we don't want an
+	/*
+	 * Disable interrupts if not already disabled: we don't want an
 	 * interrupt handler making a hypercall while we're already doing
-	 * one! */
+	 * one!
+	 */
 	local_irq_save(flags);
 	if (lguest_data.hcall_status[next_call] != 0xFF) {
 		/* Table full, so do normal hcall which will flush table. */
-		kvm_hypercall3(call, arg1, arg2, arg3);
+		kvm_hypercall4(call, arg1, arg2, arg3, arg4);
 	} else {
 		lguest_data.hcalls[next_call].arg0 = call;
 		lguest_data.hcalls[next_call].arg1 = arg1;
 		lguest_data.hcalls[next_call].arg2 = arg2;
 		lguest_data.hcalls[next_call].arg3 = arg3;
+		lguest_data.hcalls[next_call].arg4 = arg4;
 		/* Arguments must all be written before we mark it to go */
 		wmb();
 		lguest_data.hcall_status[next_call] = 0;
@@ -123,8 +131,9 @@
 	local_irq_restore(flags);
 }
 
-/*G:035 Notice the lazy_hcall() above, rather than hcall().  This is our first
- * real optimization trick!
+/*G:035
+ * Notice the lazy_hcall() above, rather than hcall().  This is our first real
+ * optimization trick!
  *
  * When lazy_mode is set, it means we're allowed to defer all hypercalls and do
  * them as a batch when lazy_mode is eventually turned off.  Because hypercalls
@@ -134,16 +143,18 @@
  * lguest_leave_lazy_mode().
  *
  * So, when we're in lazy mode, we call async_hcall() to store the call for
- * future processing: */
+ * future processing:
+ */
 static void lazy_hcall1(unsigned long call,
 		       unsigned long arg1)
 {
 	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
 		kvm_hypercall1(call, arg1);
 	else
-		async_hcall(call, arg1, 0, 0);
+		async_hcall(call, arg1, 0, 0, 0);
 }
 
+/* You can imagine what lazy_hcall2, 3 and 4 look like. :*/
 static void lazy_hcall2(unsigned long call,
 		       unsigned long arg1,
 		       unsigned long arg2)
@@ -151,7 +162,7 @@
 	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
 		kvm_hypercall2(call, arg1, arg2);
 	else
-		async_hcall(call, arg1, arg2, 0);
+		async_hcall(call, arg1, arg2, 0, 0);
 }
 
 static void lazy_hcall3(unsigned long call,
@@ -162,18 +173,40 @@
 	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
 		kvm_hypercall3(call, arg1, arg2, arg3);
 	else
-		async_hcall(call, arg1, arg2, arg3);
+		async_hcall(call, arg1, arg2, arg3, 0);
 }
 
-/* When lazy mode is turned off reset the per-cpu lazy mode variable and then
- * issue the do-nothing hypercall to flush any stored calls. */
-static void lguest_leave_lazy_mode(void)
+#ifdef CONFIG_X86_PAE
+static void lazy_hcall4(unsigned long call,
+		       unsigned long arg1,
+		       unsigned long arg2,
+		       unsigned long arg3,
+		       unsigned long arg4)
+{
+	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
+		kvm_hypercall4(call, arg1, arg2, arg3, arg4);
+	else
+		async_hcall(call, arg1, arg2, arg3, arg4);
+}
+#endif
+
+/*G:036
+ * When lazy mode is turned off reset the per-cpu lazy mode variable and then
+ * issue the do-nothing hypercall to flush any stored calls.
+:*/
+static void lguest_leave_lazy_mmu_mode(void)
 {
-	paravirt_leave_lazy(paravirt_get_lazy_mode());
 	kvm_hypercall0(LHCALL_FLUSH_ASYNC);
+	paravirt_leave_lazy_mmu();
 }
 
-/*G:033
+static void lguest_end_context_switch(struct task_struct *next)
+{
+	kvm_hypercall0(LHCALL_FLUSH_ASYNC);
+	paravirt_end_context_switch(next);
+}
+
+/*G:032
  * After that diversion we return to our first native-instruction
  * replacements: four functions for interrupt control.
  *
@@ -186,49 +219,51 @@
  * check there before it tries to deliver an interrupt.
  */
 
-/* save_flags() is expected to return the processor state (ie. "flags").  The
+/*
+ * save_flags() is expected to return the processor state (ie. "flags").  The
  * flags word contains all kind of stuff, but in practice Linux only cares
- * about the interrupt flag.  Our "save_flags()" just returns that. */
+ * about the interrupt flag.  Our "save_flags()" just returns that.
+ */
 static unsigned long save_fl(void)
 {
 	return lguest_data.irq_enabled;
 }
-PV_CALLEE_SAVE_REGS_THUNK(save_fl);
-
-/* restore_flags() just sets the flags back to the value given. */
-static void restore_fl(unsigned long flags)
-{
-	lguest_data.irq_enabled = flags;
-}
-PV_CALLEE_SAVE_REGS_THUNK(restore_fl);
 
 /* Interrupts go off... */
 static void irq_disable(void)
 {
 	lguest_data.irq_enabled = 0;
 }
+
+/*
+ * Let's pause a moment.  Remember how I said these are called so often?
+ * Jeremy Fitzhardinge optimized them so hard early in 2009 that he had to
+ * break some rules.  In particular, these functions are assumed to save their
+ * own registers if they need to: normal C functions assume they can trash the
+ * eax register.  To use normal C functions, we use
+ * PV_CALLEE_SAVE_REGS_THUNK(), which pushes %eax onto the stack, calls the
+ * C function, then restores it.
+ */
+PV_CALLEE_SAVE_REGS_THUNK(save_fl);
 PV_CALLEE_SAVE_REGS_THUNK(irq_disable);
+/*:*/
 
-/* Interrupts go on... */
-static void irq_enable(void)
-{
-	lguest_data.irq_enabled = X86_EFLAGS_IF;
-}
-PV_CALLEE_SAVE_REGS_THUNK(irq_enable);
+/* These are in i386_head.S */
+extern void lg_irq_enable(void);
+extern void lg_restore_fl(unsigned long flags);
 
-/*:*/
-/*M:003 Note that we don't check for outstanding interrupts when we re-enable
- * them (or when we unmask an interrupt).  This seems to work for the moment,
- * since interrupts are rare and we'll just get the interrupt on the next timer
- * tick, but now we can run with CONFIG_NO_HZ, we should revisit this.  One way
- * would be to put the "irq_enabled" field in a page by itself, and have the
- * Host write-protect it when an interrupt comes in when irqs are disabled.
- * There will then be a page fault as soon as interrupts are re-enabled.
+/*M:003
+ * We could be more efficient in our checking of outstanding interrupts, rather
+ * than using a branch.  One way would be to put the "irq_enabled" field in a
+ * page by itself, and have the Host write-protect it when an interrupt comes
+ * in when irqs are disabled.  There will then be a page fault as soon as
+ * interrupts are re-enabled.
  *
  * A better method is to implement soft interrupt disable generally for x86:
  * instead of disabling interrupts, we set a flag.  If an interrupt does come
  * in, we then disable them for real.  This is uncommon, so we could simply use
- * a hypercall for interrupt control and not worry about efficiency. :*/
+ * a hypercall for interrupt control and not worry about efficiency.
+:*/
 
 /*G:034
  * The Interrupt Descriptor Table (IDT).
@@ -241,10 +276,12 @@
 static void lguest_write_idt_entry(gate_desc *dt,
 				   int entrynum, const gate_desc *g)
 {
-	/* The gate_desc structure is 8 bytes long: we hand it to the Host in
+	/*
+	 * The gate_desc structure is 8 bytes long: we hand it to the Host in
 	 * two 32-bit chunks.  The whole 32-bit kernel used to hand descriptors
 	 * around like this; typesafety wasn't a big concern in Linux's early
-	 * years. */
+	 * years.
+	 */
 	u32 *desc = (u32 *)g;
 	/* Keep the local copy up to date. */
 	native_write_idt_entry(dt, entrynum, g);
@@ -252,9 +289,11 @@
 	kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]);
 }
 
-/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
+/*
+ * Changing to a different IDT is very rare: we keep the IDT up-to-date every
  * time it is written, so we can simply loop through all entries and tell the
- * Host about them. */
+ * Host about them.
+ */
 static void lguest_load_idt(const struct desc_ptr *desc)
 {
 	unsigned int i;
@@ -285,9 +324,11 @@
 		kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b);
 }
 
-/* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
+/*
+ * For a single GDT entry which changes, we do the lazy thing: alter our GDT,
  * then tell the Host to reload the entire thing.  This operation is so rare
- * that this naive implementation is reasonable. */
+ * that this naive implementation is reasonable.
+ */
 static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
 				   const void *desc, int type)
 {
@@ -297,29 +338,36 @@
 		       dt[entrynum].a, dt[entrynum].b);
 }
 
-/* OK, I lied.  There are three "thread local storage" GDT entries which change
+/*
+ * OK, I lied.  There are three "thread local storage" GDT entries which change
  * on every context switch (these three entries are how glibc implements
- * __thread variables).  So we have a hypercall specifically for this case. */
+ * __thread variables).  So we have a hypercall specifically for this case.
+ */
 static void lguest_load_tls(struct thread_struct *t, unsigned int cpu)
 {
-	/* There's one problem which normal hardware doesn't have: the Host
+	/*
+	 * There's one problem which normal hardware doesn't have: the Host
 	 * can't handle us removing entries we're currently using.  So we clear
-	 * the GS register here: if it's needed it'll be reloaded anyway. */
+	 * the GS register here: if it's needed it'll be reloaded anyway.
+	 */
 	lazy_load_gs(0);
 	lazy_hcall2(LHCALL_LOAD_TLS, __pa(&t->tls_array), cpu);
 }
 
-/*G:038 That's enough excitement for now, back to ploughing through each of
- * the different pv_ops structures (we're about 1/3 of the way through).
+/*G:038
+ * That's enough excitement for now, back to ploughing through each of the
+ * different pv_ops structures (we're about 1/3 of the way through).
  *
  * This is the Local Descriptor Table, another weird Intel thingy.  Linux only
  * uses this for some strange applications like Wine.  We don't do anything
- * here, so they'll get an informative and friendly Segmentation Fault. */
+ * here, so they'll get an informative and friendly Segmentation Fault.
+ */
 static void lguest_set_ldt(const void *addr, unsigned entries)
 {
 }
 
-/* This loads a GDT entry into the "Task Register": that entry points to a
+/*
+ * This loads a GDT entry into the "Task Register": that entry points to a
  * structure called the Task State Segment.  Some comments scattered though the
  * kernel code indicate that this used for task switching in ages past, along
  * with blood sacrifice and astrology.
@@ -327,19 +375,21 @@
  * Now there's nothing interesting in here that we don't get told elsewhere.
  * But the native version uses the "ltr" instruction, which makes the Host
  * complain to the Guest about a Segmentation Fault and it'll oops.  So we
- * override the native version with a do-nothing version. */
+ * override the native version with a do-nothing version.
+ */
 static void lguest_load_tr_desc(void)
 {
 }
 
-/* The "cpuid" instruction is a way of querying both the CPU identity
+/*
+ * The "cpuid" instruction is a way of querying both the CPU identity
  * (manufacturer, model, etc) and its features.  It was introduced before the
  * Pentium in 1993 and keeps getting extended by both Intel, AMD and others.
  * As you might imagine, after a decade and a half this treatment, it is now a
  * giant ball of hair.  Its entry in the current Intel manual runs to 28 pages.
  *
  * This instruction even it has its own Wikipedia entry.  The Wikipedia entry
- * has been translated into 4 languages.  I am not making this up!
+ * has been translated into 5 languages.  I am not making this up!
  *
  * We could get funky here and identify ourselves as "GenuineLguest", but
  * instead we just use the real "cpuid" instruction.  Then I pretty much turned
@@ -351,7 +401,8 @@
  * Replacing the cpuid so we can turn features off is great for the kernel, but
  * anyone (including userspace) can just use the raw "cpuid" instruction and
  * the Host won't even notice since it isn't privileged.  So we try not to get
- * too worked up about it. */
+ * too worked up about it.
+ */
 static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
 			 unsigned int *cx, unsigned int *dx)
 {
@@ -359,33 +410,63 @@
 
 	native_cpuid(ax, bx, cx, dx);
 	switch (function) {
-	case 1:	/* Basic feature request. */
-		/* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
+	/*
+	 * CPUID 0 gives the highest legal CPUID number (and the ID string).
+	 * We futureproof our code a little by sticking to known CPUID values.
+	 */
+	case 0:
+		if (*ax > 5)
+			*ax = 5;
+		break;
+
+	/*
+	 * CPUID 1 is a basic feature request.
+	 *
+	 * CX: we only allow kernel to see SSE3, CMPXCHG16B and SSSE3
+	 * DX: SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, TSC, FPU and PAE.
+	 */
+	case 1:
 		*cx &= 0x00002201;
-		/* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, TSC, FPU. */
-		*dx &= 0x07808111;
-		/* The Host can do a nice optimization if it knows that the
+		*dx &= 0x07808151;
+		/*
+		 * The Host can do a nice optimization if it knows that the
 		 * kernel mappings (addresses above 0xC0000000 or whatever
 		 * PAGE_OFFSET is set to) haven't changed.  But Linux calls
 		 * flush_tlb_user() for both user and kernel mappings unless
-		 * the Page Global Enable (PGE) feature bit is set. */
+		 * the Page Global Enable (PGE) feature bit is set.
+		 */
 		*dx |= 0x00002000;
-		/* We also lie, and say we're family id 5.  6 or greater
+		/*
+		 * We also lie, and say we're family id 5.  6 or greater
 		 * leads to a rdmsr in early_init_intel which we can't handle.
-		 * Family ID is returned as bits 8-12 in ax. */
+		 * Family ID is returned as bits 8-12 in ax.
+		 */
 		*ax &= 0xFFFFF0FF;
 		*ax |= 0x00000500;
 		break;
+	/*
+	 * 0x80000000 returns the highest Extended Function, so we futureproof
+	 * like we do above by limiting it to known fields.
+	 */
 	case 0x80000000:
-		/* Futureproof this a little: if they ask how much extended
-		 * processor information there is, limit it to known fields. */
 		if (*ax > 0x80000008)
 			*ax = 0x80000008;
 		break;
+
+	/*
+	 * PAE systems can mark pages as non-executable.  Linux calls this the
+	 * NX bit.  Intel calls it XD (eXecute Disable), AMD EVP (Enhanced
+	 * Virus Protection).  We just switch turn if off here, since we don't
+	 * support it.
+	 */
+	case 0x80000001:
+		*dx &= ~(1 << 20);
+		break;
 	}
 }
 
-/* Intel has four control registers, imaginatively named cr0, cr2, cr3 and cr4.
+/*
+ * Intel has four control registers, imaginatively named cr0, cr2, cr3 and cr4.
  * I assume there's a cr1, but it hasn't bothered us yet, so we'll not bother
  * it.  The Host needs to know when the Guest wants to change them, so we have
  * a whole series of functions like read_cr0() and write_cr0().
@@ -400,7 +481,8 @@
  * name like "FPUTRAP bit" be a little less cryptic?
  *
  * We store cr0 locally because the Host never changes it.  The Guest sometimes
- * wants to read it and we'd prefer not to bother the Host unnecessarily. */
+ * wants to read it and we'd prefer not to bother the Host unnecessarily.
+ */
 static unsigned long current_cr0;
 static void lguest_write_cr0(unsigned long val)
 {
@@ -413,18 +495,22 @@
 	return current_cr0;
 }
 
-/* Intel provided a special instruction to clear the TS bit for people too cool
+/*
+ * Intel provided a special instruction to clear the TS bit for people too cool
  * to use write_cr0() to do it.  This "clts" instruction is faster, because all
- * the vowels have been optimized out. */
+ * the vowels have been optimized out.
+ */
 static void lguest_clts(void)
 {
 	lazy_hcall1(LHCALL_TS, 0);
 	current_cr0 &= ~X86_CR0_TS;
 }
 
-/* cr2 is the virtual address of the last page fault, which the Guest only ever
+/*
+ * cr2 is the virtual address of the last page fault, which the Guest only ever
  * reads.  The Host kindly writes this into our "struct lguest_data", so we
- * just read it out of there. */
+ * just read it out of there.
+ */
 static unsigned long lguest_read_cr2(void)
 {
 	return lguest_data.cr2;
@@ -433,10 +519,12 @@
 /* See lguest_set_pte() below. */
 static bool cr3_changed = false;
 
-/* cr3 is the current toplevel pagetable page: the principle is the same as
+/*
+ * cr3 is the current toplevel pagetable page: the principle is the same as
  * cr0.  Keep a local copy, and tell the Host when it changes.  The only
  * difference is that our local copy is in lguest_data because the Host needs
- * to set it upon our initial hypercall. */
+ * to set it upon our initial hypercall.
+ */
 static void lguest_write_cr3(unsigned long cr3)
 {
 	lguest_data.pgdir = cr3;
@@ -481,7 +569,7 @@
  * cr3 ---> +---------+
  *	    |  	   --------->+---------+
  *	    |	      |	     | PADDR1  |
- *	  Top-level   |	     | PADDR2  |
+ *	  Mid-level   |	     | PADDR2  |
  *	  (PMD) page  |	     | 	       |
  *	    |	      |	   Lower-level |
  *	    |	      |	   (PTE) page  |
@@ -501,41 +589,113 @@
  *    Index into top     Index into second      Offset within page
  *  page directory page    pagetable page
  *
- * The kernel spends a lot of time changing both the top-level page directory
- * and lower-level pagetable pages.  The Guest doesn't know physical addresses,
- * so while it maintains these page tables exactly like normal, it also needs
- * to keep the Host informed whenever it makes a change: the Host will create
- * the real page tables based on the Guests'.
+ * Now, unfortunately, this isn't the whole story: Intel added Physical Address
+ * Extension (PAE) to allow 32 bit systems to use 64GB of memory (ie. 36 bits).
+ * These are held in 64-bit page table entries, so we can now only fit 512
+ * entries in a page, and the neat three-level tree breaks down.
+ *
+ * The result is a four level page table:
+ *
+ * cr3 --> [ 4 Upper  ]
+ *	   [   Level  ]
+ *	   [  Entries ]
+ *	   [(PUD Page)]---> +---------+
+ *	 		    |  	   --------->+---------+
+ *	 		    |	      |	     | PADDR1  |
+ *	 		  Mid-level   |	     | PADDR2  |
+ *	 		  (PMD) page  |	     | 	       |
+ *	 		    |	      |	   Lower-level |
+ *	 		    |	      |	   (PTE) page  |
+ *	 		    |	      |	     |	       |
+ *	 		      ....    	     	 ....
+ *
+ *
+ * And the virtual address is decoded as:
+ *
+ *         1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ *      |<-2->|<--- 9 bits ---->|<---- 9 bits --->|<------ 12 bits ------>|
+ * Index into    Index into mid    Index into lower    Offset within page
+ * top entries   directory page     pagetable page
+ *
+ * It's too hard to switch between these two formats at runtime, so Linux only
+ * supports one or the other depending on whether CONFIG_X86_PAE is set.  Many
+ * distributions turn it on, and not just for people with silly amounts of
+ * memory: the larger PTE entries allow room for the NX bit, which lets the
+ * kernel disable execution of pages and increase security.
+ *
+ * This was a problem for lguest, which couldn't run on these distributions;
+ * then Matias Zabaljauregui figured it all out and implemented it, and only a
+ * handful of puppies were crushed in the process!
+ *
+ * Back to our point: the kernel spends a lot of time changing both the
+ * top-level page directory and lower-level pagetable pages.  The Guest doesn't
+ * know physical addresses, so while it maintains these page tables exactly
+ * like normal, it also needs to keep the Host informed whenever it makes a
+ * change: the Host will create the real page tables based on the Guests'.
  */
 
-/* The Guest calls this to set a second-level entry (pte), ie. to map a page
- * into a process' address space.  We set the entry then tell the Host the
- * toplevel and address this corresponds to.  The Guest uses one pagetable per
- * process, so we need to tell the Host which one we're changing (mm->pgd). */
+/*
+ * The Guest calls this after it has set a second-level entry (pte), ie. to map
+ * a page into a process' address space.  Wetell the Host the toplevel and
+ * address this corresponds to.  The Guest uses one pagetable per process, so
+ * we need to tell the Host which one we're changing (mm->pgd).
+ */
 static void lguest_pte_update(struct mm_struct *mm, unsigned long addr,
 			       pte_t *ptep)
 {
+#ifdef CONFIG_X86_PAE
+	/* PAE needs to hand a 64 bit page table entry, so it uses two args. */
+	lazy_hcall4(LHCALL_SET_PTE, __pa(mm->pgd), addr,
+		    ptep->pte_low, ptep->pte_high);
+#else
 	lazy_hcall3(LHCALL_SET_PTE, __pa(mm->pgd), addr, ptep->pte_low);
+#endif
 }
 
+/* This is the "set and update" combo-meal-deal version. */
 static void lguest_set_pte_at(struct mm_struct *mm, unsigned long addr,
 			      pte_t *ptep, pte_t pteval)
 {
-	*ptep = pteval;
+	native_set_pte(ptep, pteval);
 	lguest_pte_update(mm, addr, ptep);
 }
 
-/* The Guest calls this to set a top-level entry.  Again, we set the entry then
- * tell the Host which top-level page we changed, and the index of the entry we
- * changed. */
+/*
+ * The Guest calls lguest_set_pud to set a top-level entry and lguest_set_pmd
+ * to set a middle-level entry when PAE is activated.
+ *
+ * Again, we set the entry then tell the Host which page we changed,
+ * and the index of the entry we changed.
+ */
+#ifdef CONFIG_X86_PAE
+static void lguest_set_pud(pud_t *pudp, pud_t pudval)
+{
+	native_set_pud(pudp, pudval);
+
+	/* 32 bytes aligned pdpt address and the index. */
+	lazy_hcall2(LHCALL_SET_PGD, __pa(pudp) & 0xFFFFFFE0,
+		   (__pa(pudp) & 0x1F) / sizeof(pud_t));
+}
+
 static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 {
-	*pmdp = pmdval;
+	native_set_pmd(pmdp, pmdval);
 	lazy_hcall2(LHCALL_SET_PMD, __pa(pmdp) & PAGE_MASK,
-		   (__pa(pmdp) & (PAGE_SIZE - 1)) / 4);
+		   (__pa(pmdp) & (PAGE_SIZE - 1)) / sizeof(pmd_t));
 }
+#else
 
-/* There are a couple of legacy places where the kernel sets a PTE, but we
+/* The Guest calls lguest_set_pmd to set a top-level entry when !PAE. */
+static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+	native_set_pmd(pmdp, pmdval);
+	lazy_hcall2(LHCALL_SET_PGD, __pa(pmdp) & PAGE_MASK,
+		   (__pa(pmdp) & (PAGE_SIZE - 1)) / sizeof(pmd_t));
+}
+#endif
+
+/*
+ * There are a couple of legacy places where the kernel sets a PTE, but we
  * don't know the top level any more.  This is useless for us, since we don't
  * know which pagetable is changing or what address, so we just tell the Host
  * to forget all of them.  Fortunately, this is very rare.
@@ -543,15 +703,43 @@
  * ... except in early boot when the kernel sets up the initial pagetables,
  * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell
  * the Host anything changed until we've done the first page table switch,
- * which brings boot back to 0.25 seconds. */
+ * which brings boot back to 0.25 seconds.
+ */
 static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 {
-	*ptep = pteval;
+	native_set_pte(ptep, pteval);
 	if (cr3_changed)
 		lazy_hcall1(LHCALL_FLUSH_TLB, 1);
 }
 
-/* Unfortunately for Lguest, the pv_mmu_ops for page tables were based on
+#ifdef CONFIG_X86_PAE
+/*
+ * With 64-bit PTE values, we need to be careful setting them: if we set 32
+ * bits at a time, the hardware could see a weird half-set entry.  These
+ * versions ensure we update all 64 bits at once.
+ */
+static void lguest_set_pte_atomic(pte_t *ptep, pte_t pte)
+{
+	native_set_pte_atomic(ptep, pte);
+	if (cr3_changed)
+		lazy_hcall1(LHCALL_FLUSH_TLB, 1);
+}
+
+static void lguest_pte_clear(struct mm_struct *mm, unsigned long addr,
+			     pte_t *ptep)
+{
+	native_pte_clear(mm, addr, ptep);
+	lguest_pte_update(mm, addr, ptep);
+}
+
+static void lguest_pmd_clear(pmd_t *pmdp)
+{
+	lguest_set_pmd(pmdp, __pmd(0));
+}
+#endif
+
+/*
+ * Unfortunately for Lguest, the pv_mmu_ops for page tables were based on
  * native page table operations.  On native hardware you can set a new page
  * table entry whenever you want, but if you want to remove one you have to do
  * a TLB flush (a TLB is a little cache of page table entries kept by the CPU).
@@ -560,24 +748,29 @@
  * called when a valid entry is written, not when it's removed (ie. marked not
  * present).  Instead, this is where we come when the Guest wants to remove a
  * page table entry: we tell the Host to set that entry to 0 (ie. the present
- * bit is zero). */
+ * bit is zero).
+ */
 static void lguest_flush_tlb_single(unsigned long addr)
 {
 	/* Simply set it to zero: if it was not, it will fault back in. */
 	lazy_hcall3(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0);
 }
 
-/* This is what happens after the Guest has removed a large number of entries.
+/*
+ * This is what happens after the Guest has removed a large number of entries.
  * This tells the Host that any of the page table entries for userspace might
- * have changed, ie. virtual addresses below PAGE_OFFSET. */
+ * have changed, ie. virtual addresses below PAGE_OFFSET.
+ */
 static void lguest_flush_tlb_user(void)
 {
 	lazy_hcall1(LHCALL_FLUSH_TLB, 0);
 }
 
-/* This is called when the kernel page tables have changed.  That's not very
+/*
+ * This is called when the kernel page tables have changed.  That's not very
  * common (unless the Guest is using highmem, which makes the Guest extremely
- * slow), so it's worth separating this from the user flushing above. */
+ * slow), so it's worth separating this from the user flushing above.
+ */
 static void lguest_flush_tlb_kernel(void)
 {
 	lazy_hcall1(LHCALL_FLUSH_TLB, 1);
@@ -614,30 +807,41 @@
 	.unmask		= enable_lguest_irq,
 };
 
-/* This sets up the Interrupt Descriptor Table (IDT) entry for each hardware
+/*
+ * This sets up the Interrupt Descriptor Table (IDT) entry for each hardware
  * interrupt (except 128, which is used for system calls), and then tells the
  * Linux infrastructure that each interrupt is controlled by our level-based
- * lguest interrupt controller. */
+ * lguest interrupt controller.
+ */
 static void __init lguest_init_IRQ(void)
 {
 	unsigned int i;
 
-	for (i = 0; i < LGUEST_IRQS; i++) {
-		int vector = FIRST_EXTERNAL_VECTOR + i;
-		/* Some systems map "vectors" to interrupts weirdly.  Lguest has
-		 * a straightforward 1 to 1 mapping, so force that here. */
-		__get_cpu_var(vector_irq)[vector] = i;
-		if (vector != SYSCALL_VECTOR)
-			set_intr_gate(vector, interrupt[i]);
+	for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
+		/* Some systems map "vectors" to interrupts weirdly.  Not us! */
+		__get_cpu_var(vector_irq)[i] = i - FIRST_EXTERNAL_VECTOR;
+		if (i != SYSCALL_VECTOR)
+			set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
 	}
-	/* This call is required to set up for 4k stacks, where we have
-	 * separate stacks for hard and soft interrupts. */
+
+	/*
+	 * This call is required to set up for 4k stacks, where we have
+	 * separate stacks for hard and soft interrupts.
+	 */
 	irq_ctx_init(smp_processor_id());
 }
 
+/*
+ * With CONFIG_SPARSE_IRQ, interrupt descriptors are allocated as-needed, so
+ * rather than set them in lguest_init_IRQ we are called here every time an
+ * lguest device needs an interrupt.
+ *
+ * FIXME: irq_to_desc_alloc_node() can fail due to lack of memory, we should
+ * pass that up!
+ */
 void lguest_setup_irq(unsigned int irq)
 {
-	irq_to_desc_alloc_cpu(irq, 0);
+	irq_to_desc_alloc_node(irq, 0);
 	set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
 				      handle_level_irq, "level");
 }
@@ -653,31 +857,39 @@
 	return lguest_data.time.tv_sec;
 }
 
-/* The TSC is an Intel thing called the Time Stamp Counter.  The Host tells us
+/*
+ * The TSC is an Intel thing called the Time Stamp Counter.  The Host tells us
  * what speed it runs at, or 0 if it's unusable as a reliable clock source.
  * This matches what we want here: if we return 0 from this function, the x86
- * TSC clock will give up and not register itself. */
+ * TSC clock will give up and not register itself.
+ */
 static unsigned long lguest_tsc_khz(void)
 {
 	return lguest_data.tsc_khz;
 }
 
-/* If we can't use the TSC, the kernel falls back to our lower-priority
- * "lguest_clock", where we read the time value given to us by the Host. */
+/*
+ * If we can't use the TSC, the kernel falls back to our lower-priority
+ * "lguest_clock", where we read the time value given to us by the Host.
+ */
 static cycle_t lguest_clock_read(struct clocksource *cs)
 {
 	unsigned long sec, nsec;
 
-	/* Since the time is in two parts (seconds and nanoseconds), we risk
+	/*
+	 * Since the time is in two parts (seconds and nanoseconds), we risk
 	 * reading it just as it's changing from 99 & 0.999999999 to 100 and 0,
 	 * and getting 99 and 0.  As Linux tends to come apart under the stress
-	 * of time travel, we must be careful: */
+	 * of time travel, we must be careful:
+	 */
 	do {
 		/* First we read the seconds part. */
 		sec = lguest_data.time.tv_sec;
-		/* This read memory barrier tells the compiler and the CPU that
+		/*
+		 * This read memory barrier tells the compiler and the CPU that
 		 * this can't be reordered: we have to complete the above
-		 * before going on. */
+		 * before going on.
+		 */
 		rmb();
 		/* Now we read the nanoseconds part. */
 		nsec = lguest_data.time.tv_nsec;
@@ -701,9 +913,11 @@
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-/* We also need a "struct clock_event_device": Linux asks us to set it to go
+/*
+ * We also need a "struct clock_event_device": Linux asks us to set it to go
  * off some time in the future.  Actually, James Morris figured all this out, I
- * just applied the patch. */
+ * just applied the patch.
+ */
 static int lguest_clockevent_set_next_event(unsigned long delta,
                                            struct clock_event_device *evt)
 {
@@ -753,8 +967,10 @@
 	.max_delta_ns           = LG_CLOCK_MAX_DELTA,
 };
 
-/* This is the Guest timer interrupt handler (hardware interrupt 0).  We just
- * call the clockevent infrastructure and it does whatever needs doing. */
+/*
+ * This is the Guest timer interrupt handler (hardware interrupt 0).  We just
+ * call the clockevent infrastructure and it does whatever needs doing.
+ */
 static void lguest_time_irq(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned long flags;
@@ -765,10 +981,12 @@
 	local_irq_restore(flags);
 }
 
-/* At some point in the boot process, we get asked to set up our timing
+/*
+ * At some point in the boot process, we get asked to set up our timing
  * infrastructure.  The kernel doesn't expect timer interrupts before this, but
  * we cleverly initialized the "blocked_interrupts" field of "struct
- * lguest_data" so that timer interrupts were blocked until now. */
+ * lguest_data" so that timer interrupts were blocked until now.
+ */
 static void lguest_time_init(void)
 {
 	/* Set up the timer interrupt (0) to go to our simple timer routine */
@@ -792,14 +1010,16 @@
  * to work.  They're pretty simple.
  */
 
-/* The Guest needs to tell the Host what stack it expects traps to use.  For
+/*
+ * The Guest needs to tell the Host what stack it expects traps to use.  For
  * native hardware, this is part of the Task State Segment mentioned above in
  * lguest_load_tr_desc(), but to help hypervisors there's this special call.
  *
  * We tell the Host the segment we want to use (__KERNEL_DS is the kernel data
  * segment), the privilege level (we're privilege level 1, the Host is 0 and
  * will not tolerate us trying to use that), the stack pointer, and the number
- * of pages in the stack. */
+ * of pages in the stack.
+ */
 static void lguest_load_sp0(struct tss_struct *tss,
 			    struct thread_struct *thread)
 {
@@ -813,7 +1033,8 @@
 	/* FIXME: Implement */
 }
 
-/* There are times when the kernel wants to make sure that no memory writes are
+/*
+ * There are times when the kernel wants to make sure that no memory writes are
  * caught in the cache (that they've all reached real hardware devices).  This
  * doesn't matter for the Guest which has virtual hardware.
  *
@@ -827,11 +1048,13 @@
 {
 }
 
-/* If the Guest expects to have an Advanced Programmable Interrupt Controller,
+/*
+ * If the Guest expects to have an Advanced Programmable Interrupt Controller,
  * we play dumb by ignoring writes and returning 0 for reads.  So it's no
  * longer Programmable nor Controlling anything, and I don't think 8 lines of
  * code qualifies for Advanced.  It will also never interrupt anything.  It
- * does, however, allow us to get through the Linux boot code. */
+ * does, however, allow us to get through the Linux boot code.
+ */
 #ifdef CONFIG_X86_LOCAL_APIC
 static void lguest_apic_write(u32 reg, u32 v)
 {
@@ -880,11 +1103,13 @@
 	kvm_hypercall0(LHCALL_HALT);
 }
 
-/* The SHUTDOWN hypercall takes a string to describe what's happening, and
+/*
+ * The SHUTDOWN hypercall takes a string to describe what's happening, and
  * an argument which says whether this to restart (reboot) the Guest or not.
  *
  * Note that the Host always prefers that the Guest speak in physical addresses
- * rather than virtual addresses, so we use __pa() here. */
+ * rather than virtual addresses, so we use __pa() here.
+ */
 static void lguest_power_off(void)
 {
 	kvm_hypercall2(LHCALL_SHUTDOWN, __pa("Power down"),
@@ -915,8 +1140,10 @@
 	 * nice to move it back to lguest_init.  Patch welcome... */
 	atomic_notifier_chain_register(&panic_notifier_list, &paniced);
 
-	/* The Linux bootloader header contains an "e820" memory map: the
-	 * Launcher populated the first entry with our memory limit. */
+	/*
+	 *The Linux bootloader header contains an "e820" memory map: the
+	 * Launcher populated the first entry with our memory limit.
+	 */
 	e820_add_region(boot_params.e820_map[0].addr,
 			  boot_params.e820_map[0].size,
 			  boot_params.e820_map[0].type);
@@ -925,16 +1152,17 @@
 	return "LGUEST";
 }
 
-/* We will eventually use the virtio console device to produce console output,
+/*
+ * We will eventually use the virtio console device to produce console output,
  * but before that is set up we use LHCALL_NOTIFY on normal memory to produce
- * console output. */
+ * console output.
+ */
 static __init int early_put_chars(u32 vtermno, const char *buf, int count)
 {
 	char scratch[17];
 	unsigned int len = count;
 
-	/* We use a nul-terminated string, so we have to make a copy.  Icky,
-	 * huh? */
+	/* We use a nul-terminated string, so we make a copy.  Icky, huh? */
 	if (len > sizeof(scratch) - 1)
 		len = sizeof(scratch) - 1;
 	scratch[len] = '\0';
@@ -945,8 +1173,10 @@
 	return len;
 }
 
-/* Rebooting also tells the Host we're finished, but the RESTART flag tells the
- * Launcher to reboot us. */
+/*
+ * Rebooting also tells the Host we're finished, but the RESTART flag tells the
+ * Launcher to reboot us.
+ */
 static void lguest_restart(char *reason)
 {
 	kvm_hypercall2(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART);
@@ -967,13 +1197,14 @@
  *
  * Our current solution is to allow the paravirt back end to optionally patch
  * over the indirect calls to replace them with something more efficient.  We
- * patch the four most commonly called functions: disable interrupts, enable
- * interrupts, restore interrupts and save interrupts.  We usually have 6 or 10
- * bytes to patch into: the Guest versions of these operations are small enough
- * that we can fit comfortably.
+ * patch two of the simplest of the most commonly called functions: disable
+ * interrupts and save interrupts.  We usually have 6 or 10 bytes to patch
+ * into: the Guest versions of these operations are small enough that we can
+ * fit comfortably.
  *
  * First we need assembly templates of each of the patchable Guest operations,
- * and these are in i386_head.S. */
+ * and these are in i386_head.S.
+ */
 
 /*G:060 We construct a table from the assembler templates: */
 static const struct lguest_insns
@@ -981,14 +1212,14 @@
 	const char *start, *end;
 } lguest_insns[] = {
 	[PARAVIRT_PATCH(pv_irq_ops.irq_disable)] = { lgstart_cli, lgend_cli },
-	[PARAVIRT_PATCH(pv_irq_ops.irq_enable)] = { lgstart_sti, lgend_sti },
-	[PARAVIRT_PATCH(pv_irq_ops.restore_fl)] = { lgstart_popf, lgend_popf },
 	[PARAVIRT_PATCH(pv_irq_ops.save_fl)] = { lgstart_pushf, lgend_pushf },
 };
 
-/* Now our patch routine is fairly simple (based on the native one in
+/*
+ * Now our patch routine is fairly simple (based on the native one in
  * paravirt.c).  If we have a replacement, we copy it in and return how much of
- * the available space we used. */
+ * the available space we used.
+ */
 static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
 			     unsigned long addr, unsigned len)
 {
@@ -1000,8 +1231,7 @@
 
 	insn_len = lguest_insns[type].end - lguest_insns[type].start;
 
-	/* Similarly if we can't fit replacement (shouldn't happen, but let's
-	 * be thorough). */
+	/* Similarly if it can't fit (doesn't happen, but let's be thorough). */
 	if (len < insn_len)
 		return paravirt_patch_default(type, clobber, ibuf, addr, len);
 
@@ -1010,33 +1240,40 @@
 	return insn_len;
 }
 
-/*G:030 Once we get to lguest_init(), we know we're a Guest.  The various
+/*G:029
+ * Once we get to lguest_init(), we know we're a Guest.  The various
  * pv_ops structures in the kernel provide points for (almost) every routine we
- * have to override to avoid privileged instructions. */
+ * have to override to avoid privileged instructions.
+ */
 __init void lguest_init(void)
 {
-	/* We're under lguest, paravirt is enabled, and we're running at
-	 * privilege level 1, not 0 as normal. */
+	/* We're under lguest. */
 	pv_info.name = "lguest";
+	/* Paravirt is enabled. */
 	pv_info.paravirt_enabled = 1;
+	/* We're running at privilege level 1, not 0 as normal. */
 	pv_info.kernel_rpl = 1;
+	/* Everyone except Xen runs with this set. */
+	pv_info.shared_kernel_pmd = 1;
 
-	/* We set up all the lguest overrides for sensitive operations.  These
-	 * are detailed with the operations themselves. */
+	/*
+	 * We set up all the lguest overrides for sensitive operations.  These
+	 * are detailed with the operations themselves.
+	 */
 
-	/* interrupt-related operations */
+	/* Interrupt-related operations */
 	pv_irq_ops.init_IRQ = lguest_init_IRQ;
 	pv_irq_ops.save_fl = PV_CALLEE_SAVE(save_fl);
-	pv_irq_ops.restore_fl = PV_CALLEE_SAVE(restore_fl);
+	pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(lg_restore_fl);
 	pv_irq_ops.irq_disable = PV_CALLEE_SAVE(irq_disable);
-	pv_irq_ops.irq_enable = PV_CALLEE_SAVE(irq_enable);
+	pv_irq_ops.irq_enable = __PV_IS_CALLEE_SAVE(lg_irq_enable);
 	pv_irq_ops.safe_halt = lguest_safe_halt;
 
-	/* init-time operations */
+	/* Setup operations */
 	pv_init_ops.memory_setup = lguest_memory_setup;
 	pv_init_ops.patch = lguest_patch;
 
-	/* Intercepts of various cpu instructions */
+	/* Intercepts of various CPU instructions */
 	pv_cpu_ops.load_gdt = lguest_load_gdt;
 	pv_cpu_ops.cpuid = lguest_cpuid;
 	pv_cpu_ops.load_idt = lguest_load_idt;
@@ -1054,10 +1291,10 @@
 	pv_cpu_ops.write_gdt_entry = lguest_write_gdt_entry;
 	pv_cpu_ops.write_idt_entry = lguest_write_idt_entry;
 	pv_cpu_ops.wbinvd = lguest_wbinvd;
-	pv_cpu_ops.lazy_mode.enter = paravirt_enter_lazy_cpu;
-	pv_cpu_ops.lazy_mode.leave = lguest_leave_lazy_mode;
+	pv_cpu_ops.start_context_switch = paravirt_start_context_switch;
+	pv_cpu_ops.end_context_switch = lguest_end_context_switch;
 
-	/* pagetable management */
+	/* Pagetable management */
 	pv_mmu_ops.write_cr3 = lguest_write_cr3;
 	pv_mmu_ops.flush_tlb_user = lguest_flush_tlb_user;
 	pv_mmu_ops.flush_tlb_single = lguest_flush_tlb_single;
@@ -1065,62 +1302,85 @@
 	pv_mmu_ops.set_pte = lguest_set_pte;
 	pv_mmu_ops.set_pte_at = lguest_set_pte_at;
 	pv_mmu_ops.set_pmd = lguest_set_pmd;
+#ifdef CONFIG_X86_PAE
+	pv_mmu_ops.set_pte_atomic = lguest_set_pte_atomic;
+	pv_mmu_ops.pte_clear = lguest_pte_clear;
+	pv_mmu_ops.pmd_clear = lguest_pmd_clear;
+	pv_mmu_ops.set_pud = lguest_set_pud;
+#endif
 	pv_mmu_ops.read_cr2 = lguest_read_cr2;
 	pv_mmu_ops.read_cr3 = lguest_read_cr3;
 	pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu;
-	pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mode;
+	pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode;
 	pv_mmu_ops.pte_update = lguest_pte_update;
 	pv_mmu_ops.pte_update_defer = lguest_pte_update;
 
 #ifdef CONFIG_X86_LOCAL_APIC
-	/* apic read/write intercepts */
+	/* APIC read/write intercepts */
 	set_lguest_basic_apic_ops();
 #endif
 
-	/* time operations */
+	/* Time operations */
 	pv_time_ops.get_wallclock = lguest_get_wallclock;
 	pv_time_ops.time_init = lguest_time_init;
 	pv_time_ops.get_tsc_khz = lguest_tsc_khz;
 
-	/* Now is a good time to look at the implementations of these functions
-	 * before returning to the rest of lguest_init(). */
+	/*
+	 * Now is a good time to look at the implementations of these functions
+	 * before returning to the rest of lguest_init().
+	 */
 
-	/*G:070 Now we've seen all the paravirt_ops, we return to
+	/*G:070
+	 * Now we've seen all the paravirt_ops, we return to
 	 * lguest_init() where the rest of the fairly chaotic boot setup
-	 * occurs. */
+	 * occurs.
+	 */
 
-	/* The stack protector is a weird thing where gcc places a canary
+	/*
+	 * The stack protector is a weird thing where gcc places a canary
 	 * value on the stack and then checks it on return.  This file is
 	 * compiled with -fno-stack-protector it, so we got this far without
 	 * problems.  The value of the canary is kept at offset 20 from the
 	 * %gs register, so we need to set that up before calling C functions
-	 * in other files. */
+	 * in other files.
+	 */
 	setup_stack_canary_segment(0);
-	/* We could just call load_stack_canary_segment(), but we might as
-	 * call switch_to_new_gdt() which loads the whole table and sets up
-	 * the per-cpu segment descriptor register %fs as well. */
+
+	/*
+	 * We could just call load_stack_canary_segment(), but we might as well
+	 * call switch_to_new_gdt() which loads the whole table and sets up the
+	 * per-cpu segment descriptor register %fs as well.
+	 */
 	switch_to_new_gdt(0);
 
-	/* As described in head_32.S, we map the first 128M of memory. */
+	/* We actually boot with all memory mapped, but let's say 128MB. */
 	max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
 
-	/* The Host<->Guest Switcher lives at the top of our address space, and
+	/*
+	 * The Host<->Guest Switcher lives at the top of our address space, and
 	 * the Host told us how big it is when we made LGUEST_INIT hypercall:
-	 * it put the answer in lguest_data.reserve_mem  */
+	 * it put the answer in lguest_data.reserve_mem
+	 */
 	reserve_top_address(lguest_data.reserve_mem);
 
-	/* If we don't initialize the lock dependency checker now, it crashes
-	 * paravirt_disable_iospace. */
+	/*
+	 * If we don't initialize the lock dependency checker now, it crashes
+	 * paravirt_disable_iospace.
+	 */
 	lockdep_init();
 
-	/* The IDE code spends about 3 seconds probing for disks: if we reserve
+	/*
+	 * The IDE code spends about 3 seconds probing for disks: if we reserve
 	 * all the I/O ports up front it can't get them and so doesn't probe.
 	 * Other device drivers are similar (but less severe).  This cuts the
-	 * kernel boot time on my machine from 4.1 seconds to 0.45 seconds. */
+	 * kernel boot time on my machine from 4.1 seconds to 0.45 seconds.
+	 */
 	paravirt_disable_iospace();
 
-	/* This is messy CPU setup stuff which the native boot code does before
-	 * start_kernel, so we have to do, too: */
+	/*
+	 * This is messy CPU setup stuff which the native boot code does before
+	 * start_kernel, so we have to do, too:
+	 */
 	cpu_detect(&new_cpu_data);
 	/* head.S usually sets up the first capability word, so do it here. */
 	new_cpu_data.x86_capability[0] = cpuid_edx(1);
@@ -1137,22 +1397,28 @@
 	acpi_ht = 0;
 #endif
 
-	/* We set the preferred console to "hvc".  This is the "hypervisor
+	/*
+	 * We set the preferred console to "hvc".  This is the "hypervisor
 	 * virtual console" driver written by the PowerPC people, which we also
-	 * adapted for lguest's use. */
+	 * adapted for lguest's use.
+	 */
 	add_preferred_console("hvc", 0, NULL);
 
 	/* Register our very early console. */
 	virtio_cons_early_init(early_put_chars);
 
-	/* Last of all, we set the power management poweroff hook to point to
+	/*
+	 * Last of all, we set the power management poweroff hook to point to
 	 * the Guest routine to power off, and the reboot hook to our restart
-	 * routine. */
+	 * routine.
+	 */
 	pm_power_off = lguest_power_off;
 	machine_ops.restart = lguest_restart;
 
-	/* Now we're set up, call i386_start_kernel() in head32.c and we proceed
-	 * to boot as normal.  It never returns. */
+	/*
+	 * Now we're set up, call i386_start_kernel() in head32.c and we proceed
+	 * to boot as normal.  It never returns.
+	 */
 	i386_start_kernel();
 }
 /*
diff -druN linux-libre-2.6.30-gnu/arch/x86/lguest/i386_head.S linux-libre-2.6.31-gnu/arch/x86/lguest/i386_head.S
--- linux-libre-2.6.30-gnu/arch/x86/lguest/i386_head.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lguest/i386_head.S	2009-09-09 18:13:59.000000000 -0400
@@ -5,7 +5,8 @@
 #include <asm/thread_info.h>
 #include <asm/processor-flags.h>
 
-/*G:020 Our story starts with the kernel booting into startup_32 in
+/*G:020
+ * Our story starts with the kernel booting into startup_32 in
  * arch/x86/kernel/head_32.S.  It expects a boot header, which is created by
  * the bootloader (the Launcher in our case).
  *
@@ -21,11 +22,14 @@
  * data without remembering to subtract __PAGE_OFFSET!
  *
  * The .section line puts this code in .init.text so it will be discarded after
- * boot. */
+ * boot.
+ */
 .section .init.text, "ax", @progbits
 ENTRY(lguest_entry)
-	/* We make the "initialization" hypercall now to tell the Host about
-	 * us, and also find out where it put our page tables. */
+	/*
+	 * We make the "initialization" hypercall now to tell the Host about
+	 * us, and also find out where it put our page tables.
+	 */
 	movl $LHCALL_LGUEST_INIT, %eax
 	movl $lguest_data - __PAGE_OFFSET, %ebx
 	.byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */
@@ -33,44 +37,119 @@
 	/* Set up the initial stack so we can run C code. */
 	movl $(init_thread_union+THREAD_SIZE),%esp
 
-	/* Jumps are relative, and we're running __PAGE_OFFSET too low at the
-	 * moment. */
+	/* Jumps are relative: we're running __PAGE_OFFSET too low. */
 	jmp lguest_init+__PAGE_OFFSET
 
-/*G:055 We create a macro which puts the assembler code between lgstart_ and
- * lgend_ markers.  These templates are put in the .text section: they can't be
- * discarded after boot as we may need to patch modules, too. */
+/*G:055
+ * We create a macro which puts the assembler code between lgstart_ and lgend_
+ * markers.  These templates are put in the .text section: they can't be
+ * discarded after boot as we may need to patch modules, too.
+ */
 .text
 #define LGUEST_PATCH(name, insns...)			\
 	lgstart_##name:	insns; lgend_##name:;		\
 	.globl lgstart_##name; .globl lgend_##name
 
 LGUEST_PATCH(cli, movl $0, lguest_data+LGUEST_DATA_irq_enabled)
-LGUEST_PATCH(sti, movl $X86_EFLAGS_IF, lguest_data+LGUEST_DATA_irq_enabled)
-LGUEST_PATCH(popf, movl %eax, lguest_data+LGUEST_DATA_irq_enabled)
 LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax)
+
+/*G:033
+ * But using those wrappers is inefficient (we'll see why that doesn't matter
+ * for save_fl and irq_disable later).  If we write our routines carefully in
+ * assembler, we can avoid clobbering any registers and avoid jumping through
+ * the wrapper functions.
+ *
+ * I skipped over our first piece of assembler, but this one is worth studying
+ * in a bit more detail so I'll describe in easy stages.  First, the routine to
+ * enable interrupts:
+ */
+ENTRY(lg_irq_enable)
+	/*
+	 * The reverse of irq_disable, this sets lguest_data.irq_enabled to
+	 * X86_EFLAGS_IF (ie. "Interrupts enabled").
+	 */
+	movl $X86_EFLAGS_IF, lguest_data+LGUEST_DATA_irq_enabled
+	/*
+	 * But now we need to check if the Host wants to know: there might have
+	 * been interrupts waiting to be delivered, in which case it will have
+	 * set lguest_data.irq_pending to X86_EFLAGS_IF.  If it's not zero, we
+	 * jump to send_interrupts, otherwise we're done.
+	 */
+	testl $0, lguest_data+LGUEST_DATA_irq_pending
+	jnz send_interrupts
+	/*
+	 * One cool thing about x86 is that you can do many things without using
+	 * a register.  In this case, the normal path hasn't needed to save or
+	 * restore any registers at all!
+	 */
+	ret
+send_interrupts:
+	/*
+	 * OK, now we need a register: eax is used for the hypercall number,
+	 * which is LHCALL_SEND_INTERRUPTS.
+	 *
+	 * We used not to bother with this pending detection at all, which was
+	 * much simpler.  Sooner or later the Host would realize it had to
+	 * send us an interrupt.  But that turns out to make performance 7
+	 * times worse on a simple tcp benchmark.  So now we do this the hard
+	 * way.
+	 */
+	pushl %eax
+	movl $LHCALL_SEND_INTERRUPTS, %eax
+	/*
+	 * This is a vmcall instruction (same thing that KVM uses).  Older
+	 * assembler versions might not know the "vmcall" instruction, so we
+	 * create one manually here.
+	 */
+	.byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */
+	/* Put eax back the way we found it. */
+	popl %eax
+	ret
+
+/*
+ * Finally, the "popf" or "restore flags" routine.  The %eax register holds the
+ * flags (in practice, either X86_EFLAGS_IF or 0): if it's X86_EFLAGS_IF we're
+ * enabling interrupts again, if it's 0 we're leaving them off.
+ */
+ENTRY(lg_restore_fl)
+	/* This is just "lguest_data.irq_enabled = flags;" */
+	movl %eax, lguest_data+LGUEST_DATA_irq_enabled
+	/*
+	 * Now, if the %eax value has enabled interrupts and
+	 * lguest_data.irq_pending is set, we want to tell the Host so it can
+	 * deliver any outstanding interrupts.  Fortunately, both values will
+	 * be X86_EFLAGS_IF (ie. 512) in that case, and the "testl"
+	 * instruction will AND them together for us.  If both are set, we
+	 * jump to send_interrupts.
+	 */
+	testl lguest_data+LGUEST_DATA_irq_pending, %eax
+	jnz send_interrupts
+	/* Again, the normal path has used no extra registers.  Clever, huh? */
+	ret
 /*:*/
 
 /* These demark the EIP range where host should never deliver interrupts. */
 .global lguest_noirq_start
 .global lguest_noirq_end
 
-/*M:004 When the Host reflects a trap or injects an interrupt into the Guest,
- * it sets the eflags interrupt bit on the stack based on
- * lguest_data.irq_enabled, so the Guest iret logic does the right thing when
- * restoring it.  However, when the Host sets the Guest up for direct traps,
- * such as system calls, the processor is the one to push eflags onto the
- * stack, and the interrupt bit will be 1 (in reality, interrupts are always
- * enabled in the Guest).
+/*M:004
+ * When the Host reflects a trap or injects an interrupt into the Guest, it
+ * sets the eflags interrupt bit on the stack based on lguest_data.irq_enabled,
+ * so the Guest iret logic does the right thing when restoring it.  However,
+ * when the Host sets the Guest up for direct traps, such as system calls, the
+ * processor is the one to push eflags onto the stack, and the interrupt bit
+ * will be 1 (in reality, interrupts are always enabled in the Guest).
  *
  * This turns out to be harmless: the only trap which should happen under Linux
  * with interrupts disabled is Page Fault (due to our lazy mapping of vmalloc
  * regions), which has to be reflected through the Host anyway.  If another
  * trap *does* go off when interrupts are disabled, the Guest will panic, and
- * we'll never get to this iret! :*/
+ * we'll never get to this iret!
+:*/
 
-/*G:045 There is one final paravirt_op that the Guest implements, and glancing
- * at it you can see why I left it to last.  It's *cool*!  It's in *assembler*!
+/*G:045
+ * There is one final paravirt_op that the Guest implements, and glancing at it
+ * you can see why I left it to last.  It's *cool*!  It's in *assembler*!
  *
  * The "iret" instruction is used to return from an interrupt or trap.  The
  * stack looks like this:
@@ -94,15 +173,18 @@
  * return to userspace or wherever.  Our solution to this is to surround the
  * code with lguest_noirq_start: and lguest_noirq_end: labels.  We tell the
  * Host that it is *never* to interrupt us there, even if interrupts seem to be
- * enabled. */
+ * enabled.
+ */
 ENTRY(lguest_iret)
 	pushl	%eax
 	movl	12(%esp), %eax
 lguest_noirq_start:
-	/* Note the %ss: segment prefix here.  Normal data accesses use the
+	/*
+	 * Note the %ss: segment prefix here.  Normal data accesses use the
 	 * "ds" segment, but that will have already been restored for whatever
 	 * we're returning to (such as userspace): we can't trust it.  The %ss:
-	 * prefix makes sure we use the stack segment, which is still valid. */
+	 * prefix makes sure we use the stack segment, which is still valid.
+	 */
 	movl	%eax,%ss:lguest_data+LGUEST_DATA_irq_enabled
 	popl	%eax
 	iret
diff -druN linux-libre-2.6.30-gnu/arch/x86/lguest/Kconfig linux-libre-2.6.31-gnu/arch/x86/lguest/Kconfig
--- linux-libre-2.6.30-gnu/arch/x86/lguest/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lguest/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,6 @@
 	bool "Lguest guest support"
 	select PARAVIRT
 	depends on X86_32
-	depends on !X86_PAE
 	select VIRTIO
 	select VIRTIO_RING
 	select VIRTIO_CONSOLE
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/atomic64_32.c linux-libre-2.6.31-gnu/arch/x86/lib/atomic64_32.c
--- linux-libre-2.6.30-gnu/arch/x86/lib/atomic64_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/lib/atomic64_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,230 @@
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/processor.h>
+#include <asm/cmpxchg.h>
+#include <asm/atomic.h>
+
+static noinline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new)
+{
+	u32 low = new;
+	u32 high = new >> 32;
+
+	asm volatile(
+		LOCK_PREFIX "cmpxchg8b %1\n"
+		     : "+A" (old), "+m" (*ptr)
+		     :  "b" (low),  "c" (high)
+		     );
+	return old;
+}
+
+u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val)
+{
+	return cmpxchg8b(&ptr->counter, old_val, new_val);
+}
+EXPORT_SYMBOL(atomic64_cmpxchg);
+
+/**
+ * atomic64_xchg - xchg atomic64 variable
+ * @ptr:      pointer to type atomic64_t
+ * @new_val:  value to assign
+ *
+ * Atomically xchgs the value of @ptr to @new_val and returns
+ * the old value.
+ */
+u64 atomic64_xchg(atomic64_t *ptr, u64 new_val)
+{
+	/*
+	 * Try first with a (possibly incorrect) assumption about
+	 * what we have there. We'll do two loops most likely,
+	 * but we'll get an ownership MESI transaction straight away
+	 * instead of a read transaction followed by a
+	 * flush-for-ownership transaction:
+	 */
+	u64 old_val, real_val = 0;
+
+	do {
+		old_val = real_val;
+
+		real_val = atomic64_cmpxchg(ptr, old_val, new_val);
+
+	} while (real_val != old_val);
+
+	return old_val;
+}
+EXPORT_SYMBOL(atomic64_xchg);
+
+/**
+ * atomic64_set - set atomic64 variable
+ * @ptr:      pointer to type atomic64_t
+ * @new_val:  value to assign
+ *
+ * Atomically sets the value of @ptr to @new_val.
+ */
+void atomic64_set(atomic64_t *ptr, u64 new_val)
+{
+	atomic64_xchg(ptr, new_val);
+}
+EXPORT_SYMBOL(atomic64_set);
+
+/**
+EXPORT_SYMBOL(atomic64_read);
+ * atomic64_add_return - add and return
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr and returns @delta + *@ptr
+ */
+noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr)
+{
+	/*
+	 * Try first with a (possibly incorrect) assumption about
+	 * what we have there. We'll do two loops most likely,
+	 * but we'll get an ownership MESI transaction straight away
+	 * instead of a read transaction followed by a
+	 * flush-for-ownership transaction:
+	 */
+	u64 old_val, new_val, real_val = 0;
+
+	do {
+		old_val = real_val;
+		new_val = old_val + delta;
+
+		real_val = atomic64_cmpxchg(ptr, old_val, new_val);
+
+	} while (real_val != old_val);
+
+	return new_val;
+}
+EXPORT_SYMBOL(atomic64_add_return);
+
+u64 atomic64_sub_return(u64 delta, atomic64_t *ptr)
+{
+	return atomic64_add_return(-delta, ptr);
+}
+EXPORT_SYMBOL(atomic64_sub_return);
+
+u64 atomic64_inc_return(atomic64_t *ptr)
+{
+	return atomic64_add_return(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_inc_return);
+
+u64 atomic64_dec_return(atomic64_t *ptr)
+{
+	return atomic64_sub_return(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_dec_return);
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr.
+ */
+void atomic64_add(u64 delta, atomic64_t *ptr)
+{
+	atomic64_add_return(delta, ptr);
+}
+EXPORT_SYMBOL(atomic64_add);
+
+/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @delta: integer value to subtract
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically subtracts @delta from @ptr.
+ */
+void atomic64_sub(u64 delta, atomic64_t *ptr)
+{
+	atomic64_add(-delta, ptr);
+}
+EXPORT_SYMBOL(atomic64_sub);
+
+/**
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @delta: integer value to subtract
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically subtracts @delta from @ptr and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+int atomic64_sub_and_test(u64 delta, atomic64_t *ptr)
+{
+	u64 new_val = atomic64_sub_return(delta, ptr);
+
+	return new_val == 0;
+}
+EXPORT_SYMBOL(atomic64_sub_and_test);
+
+/**
+ * atomic64_inc - increment atomic64 variable
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically increments @ptr by 1.
+ */
+void atomic64_inc(atomic64_t *ptr)
+{
+	atomic64_add(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_inc);
+
+/**
+ * atomic64_dec - decrement atomic64 variable
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically decrements @ptr by 1.
+ */
+void atomic64_dec(atomic64_t *ptr)
+{
+	atomic64_sub(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_dec);
+
+/**
+ * atomic64_dec_and_test - decrement and test
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically decrements @ptr by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+int atomic64_dec_and_test(atomic64_t *ptr)
+{
+	return atomic64_sub_and_test(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_dec_and_test);
+
+/**
+ * atomic64_inc_and_test - increment and test
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically increments @ptr by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+int atomic64_inc_and_test(atomic64_t *ptr)
+{
+	return atomic64_sub_and_test(-1, ptr);
+}
+EXPORT_SYMBOL(atomic64_inc_and_test);
+
+/**
+ * atomic64_add_negative - add and test if negative
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+int atomic64_add_negative(u64 delta, atomic64_t *ptr)
+{
+	s64 new_val = atomic64_add_return(delta, ptr);
+
+	return new_val < 0;
+}
+EXPORT_SYMBOL(atomic64_add_negative);
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/clear_page_64.S linux-libre-2.6.31-gnu/arch/x86/lib/clear_page_64.S
--- linux-libre-2.6.30-gnu/arch/x86/lib/clear_page_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lib/clear_page_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -5,15 +5,14 @@
  * Zero a page. 	
  * rdi	page
  */			
-	ALIGN
-clear_page_c:
+ENTRY(clear_page_c)
 	CFI_STARTPROC
 	movl $4096/8,%ecx
 	xorl %eax,%eax
 	rep stosq
 	ret
 	CFI_ENDPROC
-ENDPROC(clear_page)
+ENDPROC(clear_page_c)
 
 ENTRY(clear_page)
 	CFI_STARTPROC
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/copy_user_64.S linux-libre-2.6.31-gnu/arch/x86/lib/copy_user_64.S
--- linux-libre-2.6.30-gnu/arch/x86/lib/copy_user_64.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lib/copy_user_64.S	2009-09-09 18:13:59.000000000 -0400
@@ -75,6 +75,7 @@
 	jae bad_to_user
 	ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
 	CFI_ENDPROC
+ENDPROC(copy_to_user)
 
 /* Standard copy_from_user with segment limit checking */
 ENTRY(copy_from_user)
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/delay.c linux-libre-2.6.31-gnu/arch/x86/lib/delay.c
--- linux-libre-2.6.30-gnu/arch/x86/lib/delay.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lib/delay.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,8 +55,10 @@
 
 	preempt_disable();
 	cpu = smp_processor_id();
+	rdtsc_barrier();
 	rdtscl(bclock);
 	for (;;) {
+		rdtsc_barrier();
 		rdtscl(now);
 		if ((now - bclock) >= loops)
 			break;
@@ -78,6 +80,7 @@
 		if (unlikely(cpu != smp_processor_id())) {
 			loops -= (now - bclock);
 			cpu = smp_processor_id();
+			rdtsc_barrier();
 			rdtscl(bclock);
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/Makefile linux-libre-2.6.31-gnu/arch/x86/lib/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/lib/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lib/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for x86 specific library files.
 #
 
-obj-$(CONFIG_SMP) := msr-on-cpu.o
+obj-$(CONFIG_SMP) := msr.o
 
 lib-y := delay.o
 lib-y += thunk_$(BITS).o
@@ -10,6 +10,7 @@
 lib-y += memcpy_$(BITS).o
 
 ifeq ($(CONFIG_X86_32),y)
+        obj-y += atomic64_32.o
         lib-y += checksum_32.o
         lib-y += strstr_32.o
         lib-y += semaphore_32.o string_32.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/msr.c linux-libre-2.6.31-gnu/arch/x86/lib/msr.c
--- linux-libre-2.6.30-gnu/arch/x86/lib/msr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/lib/msr.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,177 @@
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+#include <asm/msr.h>
+
+struct msr_info {
+	u32 msr_no;
+	struct msr reg;
+	struct msr *msrs;
+	int off;
+	int err;
+};
+
+static void __rdmsr_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+	struct msr *reg;
+	int this_cpu = raw_smp_processor_id();
+
+	if (rv->msrs)
+		reg = &rv->msrs[this_cpu - rv->off];
+	else
+		reg = &rv->reg;
+
+	rdmsr(rv->msr_no, reg->l, reg->h);
+}
+
+static void __wrmsr_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+	struct msr *reg;
+	int this_cpu = raw_smp_processor_id();
+
+	if (rv->msrs)
+		reg = &rv->msrs[this_cpu - rv->off];
+	else
+		reg = &rv->reg;
+
+	wrmsr(rv->msr_no, reg->l, reg->h);
+}
+
+int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
+	*l = rv.reg.l;
+	*h = rv.reg.h;
+
+	return err;
+}
+EXPORT_SYMBOL(rdmsr_on_cpu);
+
+int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	rv.reg.l = l;
+	rv.reg.h = h;
+	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
+
+	return err;
+}
+EXPORT_SYMBOL(wrmsr_on_cpu);
+
+/* rdmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
+{
+	struct msr_info rv;
+	int this_cpu;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.off    = cpumask_first(mask);
+	rv.msrs	  = msrs;
+	rv.msr_no = msr_no;
+
+	this_cpu = get_cpu();
+
+	if (cpumask_test_cpu(this_cpu, mask))
+		__rdmsr_on_cpu(&rv);
+
+	smp_call_function_many(mask, __rdmsr_on_cpu, &rv, 1);
+	put_cpu();
+}
+EXPORT_SYMBOL(rdmsr_on_cpus);
+
+/*
+ * wrmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
+{
+	struct msr_info rv;
+	int this_cpu;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.off    = cpumask_first(mask);
+	rv.msrs   = msrs;
+	rv.msr_no = msr_no;
+
+	this_cpu = get_cpu();
+
+	if (cpumask_test_cpu(this_cpu, mask))
+		__wrmsr_on_cpu(&rv);
+
+	smp_call_function_many(mask, __wrmsr_on_cpu, &rv, 1);
+	put_cpu();
+}
+EXPORT_SYMBOL(wrmsr_on_cpus);
+
+/* These "safe" variants are slower and should be used when the target MSR
+   may not actually exist. */
+static void __rdmsr_safe_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+
+	rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h);
+}
+
+static void __wrmsr_safe_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+
+	rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
+}
+
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
+	*l = rv.reg.l;
+	*h = rv.reg.h;
+
+	return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsr_safe_on_cpu);
+
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	rv.reg.l = l;
+	rv.reg.h = h;
+	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
+
+	return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsr_safe_on_cpu);
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/msr-on-cpu.c linux-libre-2.6.31-gnu/arch/x86/lib/msr-on-cpu.c
--- linux-libre-2.6.30-gnu/arch/x86/lib/msr-on-cpu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lib/msr-on-cpu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,97 +0,0 @@
-#include <linux/module.h>
-#include <linux/preempt.h>
-#include <linux/smp.h>
-#include <asm/msr.h>
-
-struct msr_info {
-	u32 msr_no;
-	u32 l, h;
-	int err;
-};
-
-static void __rdmsr_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-
-	rdmsr(rv->msr_no, rv->l, rv->h);
-}
-
-static void __wrmsr_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-
-	wrmsr(rv->msr_no, rv->l, rv->h);
-}
-
-int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
-	int err;
-	struct msr_info rv;
-
-	rv.msr_no = msr_no;
-	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
-	*l = rv.l;
-	*h = rv.h;
-
-	return err;
-}
-
-int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
-	int err;
-	struct msr_info rv;
-
-	rv.msr_no = msr_no;
-	rv.l = l;
-	rv.h = h;
-	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
-
-	return err;
-}
-
-/* These "safe" variants are slower and should be used when the target MSR
-   may not actually exist. */
-static void __rdmsr_safe_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-
-	rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h);
-}
-
-static void __wrmsr_safe_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-
-	rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h);
-}
-
-int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
-	int err;
-	struct msr_info rv;
-
-	rv.msr_no = msr_no;
-	err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
-	*l = rv.l;
-	*h = rv.h;
-
-	return err ? err : rv.err;
-}
-
-int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
-	int err;
-	struct msr_info rv;
-
-	rv.msr_no = msr_no;
-	rv.l = l;
-	rv.h = h;
-	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
-
-	return err ? err : rv.err;
-}
-
-EXPORT_SYMBOL(rdmsr_on_cpu);
-EXPORT_SYMBOL(wrmsr_on_cpu);
-EXPORT_SYMBOL(rdmsr_safe_on_cpu);
-EXPORT_SYMBOL(wrmsr_safe_on_cpu);
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/usercopy_32.c linux-libre-2.6.31-gnu/arch/x86/lib/usercopy_32.c
--- linux-libre-2.6.30-gnu/arch/x86/lib/usercopy_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lib/usercopy_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -751,7 +751,7 @@
 
 			if (retval == -ENOMEM && is_global_init(current)) {
 				up_read(&current->mm->mmap_sem);
-				congestion_wait(WRITE, HZ/50);
+				congestion_wait(BLK_RW_ASYNC, HZ/50);
 				goto survive;
 			}
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/lib/usercopy_64.c linux-libre-2.6.31-gnu/arch/x86/lib/usercopy_64.c
--- linux-libre-2.6.30-gnu/arch/x86/lib/usercopy_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/lib/usercopy_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -127,7 +127,7 @@
 
 long strnlen_user(const char __user *s, long n)
 {
-	if (!access_ok(VERIFY_READ, s, n))
+	if (!access_ok(VERIFY_READ, s, 1))
 		return 0;
 	return __strnlen_user(s, n);
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/Makefile linux-libre-2.6.31-gnu/arch/x86/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,8 +7,6 @@
         KBUILD_DEFCONFIG := $(ARCH)_defconfig
 endif
 
-core-$(CONFIG_KVM) += arch/x86/kvm/
-
 # BITS is used as extension for files which are available in a 32 bit
 # and a 64 bit version to simplify shared Makefiles.
 # e.g.: obj-y += foo_$(BITS).o
@@ -83,6 +81,11 @@
         endif
 endif
 
+# Don't unroll struct assignments with kmemcheck enabled
+ifeq ($(CONFIG_KMEMCHECK),y)
+	KBUILD_CFLAGS += $(call cc-option,-fno-builtin-memcpy)
+endif
+
 # Stackpointer is addressed different for 32 bit and 64 bit x86
 sp-$(CONFIG_X86_32) := esp
 sp-$(CONFIG_X86_64) := rsp
@@ -118,21 +121,8 @@
 
 libs-y  += arch/x86/lib/
 
-# Sub architecture files that needs linking first
-core-y += $(fcore-y)
-
-# Xen paravirtualization support
-core-$(CONFIG_XEN) += arch/x86/xen/
-
-# lguest paravirtualization support
-core-$(CONFIG_LGUEST_GUEST) += arch/x86/lguest/
-
-core-y += arch/x86/kernel/
-core-y += arch/x86/mm/
-
-core-y += arch/x86/crypto/
-core-y += arch/x86/vdso/
-core-$(CONFIG_IA32_EMULATION) += arch/x86/ia32/
+# See arch/x86/Kbuild for content of core part of the kernel
+core-y += arch/x86/
 
 # drivers-y are linked after core-y
 drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/dump_pagetables.c linux-libre-2.6.31-gnu/arch/x86/mm/dump_pagetables.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/dump_pagetables.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/dump_pagetables.c	2009-09-09 18:13:59.000000000 -0400
@@ -161,13 +161,14 @@
 		   st->current_address >= st->marker[1].start_address) {
 		const char *unit = units;
 		unsigned long delta;
+		int width = sizeof(unsigned long) * 2;
 
 		/*
 		 * Now print the actual finished series
 		 */
-		seq_printf(m, "0x%p-0x%p   ",
-			   (void *)st->start_address,
-			   (void *)st->current_address);
+		seq_printf(m, "0x%0*lx-0x%0*lx   ",
+			   width, st->start_address,
+			   width, st->current_address);
 
 		delta = (st->current_address - st->start_address) >> 10;
 		while (!(delta & 1023) && unit[1]) {
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/fault.c linux-libre-2.6.31-gnu/arch/x86/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,40 +3,18 @@
  *  Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
  *  Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
  */
-#include <linux/interrupt.h>
-#include <linux/mmiotrace.h>
-#include <linux/bootmem.h>
-#include <linux/compiler.h>
-#include <linux/highmem.h>
-#include <linux/kprobes.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/vt_kern.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/errno.h>
-#include <linux/magic.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mman.h>
-#include <linux/tty.h>
-#include <linux/smp.h>
-#include <linux/mm.h>
-
-#include <asm-generic/sections.h>
+#include <linux/magic.h>		/* STACK_END_MAGIC		*/
+#include <linux/sched.h>		/* test_thread_flag(), ...	*/
+#include <linux/kdebug.h>		/* oops_begin/end, ...		*/
+#include <linux/module.h>		/* search_exception_table	*/
+#include <linux/bootmem.h>		/* max_low_pfn			*/
+#include <linux/kprobes.h>		/* __kprobes, ...		*/
+#include <linux/mmiotrace.h>		/* kmmio_handler, ...		*/
+#include <linux/perf_counter.h>		/* perf_swcounter_event		*/
 
-#include <asm/tlbflush.h>
-#include <asm/pgalloc.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/proto.h>
-#include <asm/traps.h>
-#include <asm/desc.h>
+#include <asm/traps.h>			/* dotraplinkage, ...		*/
+#include <asm/pgalloc.h>		/* pgd_*(), ...			*/
+#include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/
 
 /*
  * Page fault error code bits:
@@ -225,12 +203,10 @@
 	if (!pmd_present(*pmd_k))
 		return NULL;
 
-	if (!pmd_present(*pmd)) {
+	if (!pmd_present(*pmd))
 		set_pmd(pmd, *pmd_k);
-		arch_flush_lazy_mmu_mode();
-	} else {
+	else
 		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
-	}
 
 	return pmd_k;
 }
@@ -450,10 +426,11 @@
 }
 
 static const char errata93_warning[] =
-KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
-KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
-KERN_ERR "******* Please consider a BIOS update.\n"
-KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
+KERN_ERR 
+"******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+"******* Working around it, but it may cause SEGVs or burn power.\n"
+"******* Please consider a BIOS update.\n"
+"******* Disabling USB legacy in the BIOS may also help.\n";
 
 /*
  * No vm86 mode in 64-bit mode:
@@ -538,8 +515,6 @@
 static int is_errata93(struct pt_regs *regs, unsigned long address)
 {
 #ifdef CONFIG_X86_64
-	static int once;
-
 	if (address != regs->ip)
 		return 0;
 
@@ -549,10 +524,7 @@
 	address |= 0xffffffffUL << 32;
 	if ((address >= (u64)_stext && address <= (u64)_etext) ||
 	    (address >= MODULES_VADDR && address <= MODULES_END)) {
-		if (!once) {
-			printk(errata93_warning);
-			once = 1;
-		}
+		printk_once(errata93_warning);
 		regs->ip = address;
 		return 1;
 	}
@@ -725,7 +697,7 @@
 	if (!printk_ratelimit())
 		return;
 
-	printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+	printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
 		task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
 		tsk->comm, task_pid_nr(tsk), address,
 		(void *)regs->ip, (void *)regs->sp, error_code);
@@ -981,11 +953,17 @@
 	tsk = current;
 	mm = tsk->mm;
 
-	prefetchw(&mm->mmap_sem);
-
 	/* Get the faulting address: */
 	address = read_cr2();
 
+	/*
+	 * Detect and handle instructions that would cause a page fault for
+	 * both a tracked kernel page and a userspace page.
+	 */
+	if (kmemcheck_active(regs))
+		kmemcheck_hide(regs);
+	prefetchw(&mm->mmap_sem);
+
 	if (unlikely(kmmio_fault(regs, address)))
 		return;
 
@@ -1003,9 +981,13 @@
 	 * protection error (error_code & 9) == 0.
 	 */
 	if (unlikely(fault_in_kernel_space(address))) {
-		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
-		    vmalloc_fault(address) >= 0)
-			return;
+		if (!(error_code & (PF_RSVD | PF_USER | PF_PROT))) {
+			if (vmalloc_fault(address) >= 0)
+				return;
+
+			if (kmemcheck_fault(regs, address, error_code))
+				return;
+		}
 
 		/* Can handle a stale RO->RW TLB: */
 		if (spurious_fault(error_code, address))
@@ -1044,6 +1026,8 @@
 	if (unlikely(error_code & PF_RSVD))
 		pgtable_bad(regs, error_code, address);
 
+	perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
 	/*
 	 * If we're in an interrupt, have no user context or are running
 	 * in an atomic region then we must not take the fault:
@@ -1130,17 +1114,22 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault:
 	 */
-	fault = handle_mm_fault(mm, vma, address, write);
+	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
 
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		mm_fault_error(regs, error_code, address, fault);
 		return;
 	}
 
-	if (fault & VM_FAULT_MAJOR)
+	if (fault & VM_FAULT_MAJOR) {
 		tsk->maj_flt++;
-	else
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+				     regs, address);
+	} else {
 		tsk->min_flt++;
+		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+				     regs, address);
+	}
 
 	check_v8086_mode(regs, address, tsk);
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/gup.c linux-libre-2.6.31-gnu/arch/x86/mm/gup.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/gup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/gup.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,7 +14,7 @@
 static inline pte_t gup_get_pte(pte_t *ptep)
 {
 #ifndef CONFIG_X86_PAE
-	return *ptep;
+	return ACCESS_ONCE(*ptep);
 #else
 	/*
 	 * With get_user_pages_fast, we walk down the pagetables without taking
@@ -219,6 +219,62 @@
 	return 1;
 }
 
+/*
+ * Like get_user_pages_fast() except its IRQ-safe in that it won't fall
+ * back to the regular GUP.
+ */
+int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
+			  struct page **pages)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long addr, len, end;
+	unsigned long next;
+	unsigned long flags;
+	pgd_t *pgdp;
+	int nr = 0;
+
+	start &= PAGE_MASK;
+	addr = start;
+	len = (unsigned long) nr_pages << PAGE_SHIFT;
+	end = start + len;
+	if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
+					(void __user *)start, len)))
+		return 0;
+
+	/*
+	 * XXX: batch / limit 'nr', to avoid large irq off latency
+	 * needs some instrumenting to determine the common sizes used by
+	 * important workloads (eg. DB2), and whether limiting the batch size
+	 * will decrease performance.
+	 *
+	 * It seems like we're in the clear for the moment. Direct-IO is
+	 * the main guy that batches up lots of get_user_pages, and even
+	 * they are limited to 64-at-a-time which is not so many.
+	 */
+	/*
+	 * This doesn't prevent pagetable teardown, but does prevent
+	 * the pagetables and pages from being freed on x86.
+	 *
+	 * So long as we atomically load page table pointers versus teardown
+	 * (which we do on x86, with the above PAE exception), we can follow the
+	 * address down to the the page and take a ref on it.
+	 */
+	local_irq_save(flags);
+	pgdp = pgd_offset(mm, addr);
+	do {
+		pgd_t pgd = *pgdp;
+
+		next = pgd_addr_end(addr, end);
+		if (pgd_none(pgd))
+			break;
+		if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+			break;
+	} while (pgdp++, addr = next, addr != end);
+	local_irq_restore(flags);
+
+	return nr;
+}
+
 /**
  * get_user_pages_fast() - pin user pages in memory
  * @start:	starting user address
@@ -247,10 +303,15 @@
 	start &= PAGE_MASK;
 	addr = start;
 	len = (unsigned long) nr_pages << PAGE_SHIFT;
+
 	end = start + len;
-	if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
-					(void __user *)start, len)))
+	if (end < start)
+		goto slow_irqon;
+
+#ifdef CONFIG_X86_64
+	if (end >> __VIRTUAL_MASK_SHIFT)
 		goto slow_irqon;
+#endif
 
 	/*
 	 * XXX: batch / limit 'nr', to avoid large irq off latency
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/highmem_32.c linux-libre-2.6.31-gnu/arch/x86/mm/highmem_32.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/highmem_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/highmem_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,7 +44,6 @@
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 	BUG_ON(!pte_none(*(kmap_pte-idx)));
 	set_pte(kmap_pte-idx, mk_pte(page, prot));
-	arch_flush_lazy_mmu_mode();
 
 	return (void *)vaddr;
 }
@@ -74,7 +73,6 @@
 #endif
 	}
 
-	arch_flush_lazy_mmu_mode();
 	pagefault_enable();
 }
 
@@ -105,6 +103,7 @@
 EXPORT_SYMBOL(kunmap);
 EXPORT_SYMBOL(kmap_atomic);
 EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_prot);
 
 void __init set_highmem_pages_init(void)
 {
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/init_32.c linux-libre-2.6.31-gnu/arch/x86/mm/init_32.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/init_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/init_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -49,12 +49,9 @@
 #include <asm/paravirt.h>
 #include <asm/setup.h>
 #include <asm/cacheflush.h>
+#include <asm/page_types.h>
 #include <asm/init.h>
 
-unsigned long max_low_pfn_mapped;
-unsigned long max_pfn_mapped;
-
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 unsigned long highstart_pfn, highend_pfn;
 
 static noinline int do_test_wp_bit(void);
@@ -114,7 +111,7 @@
 		pte_t *page_table = NULL;
 
 		if (after_bootmem) {
-#ifdef CONFIG_DEBUG_PAGEALLOC
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
 			page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
 #endif
 			if (!page_table)
@@ -567,7 +564,7 @@
 }
 #endif /* !CONFIG_ACPI_SLEEP */
 
-void zap_low_mappings(void)
+void zap_low_mappings(bool early)
 {
 	int i;
 
@@ -584,64 +581,16 @@
 		set_pgd(swapper_pg_dir+i, __pgd(0));
 #endif
 	}
-	flush_tlb_all();
-}
 
-int nx_enabled;
+	if (early)
+		__flush_tlb();
+	else
+		flush_tlb_all();
+}
 
 pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
-#ifdef CONFIG_X86_PAE
-
-static int disable_nx __initdata;
-
-/*
- * noexec = on|off
- *
- * Control non executable mappings.
- *
- * on      Enable
- * off     Disable
- */
-static int __init noexec_setup(char *str)
-{
-	if (!str || !strcmp(str, "on")) {
-		if (cpu_has_nx) {
-			__supported_pte_mask |= _PAGE_NX;
-			disable_nx = 0;
-		}
-	} else {
-		if (!strcmp(str, "off")) {
-			disable_nx = 1;
-			__supported_pte_mask &= ~_PAGE_NX;
-		} else {
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-early_param("noexec", noexec_setup);
-
-void __init set_nx(void)
-{
-	unsigned int v[4], l, h;
-
-	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
-		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
-
-		if ((v[3] & (1 << 20)) && !disable_nx) {
-			rdmsr(MSR_EFER, l, h);
-			l |= EFER_NX;
-			wrmsr(MSR_EFER, l, h);
-			nx_enabled = 1;
-			__supported_pte_mask |= _PAGE_NX;
-		}
-	}
-}
-#endif
-
 /* user-defined highmem size */
 static unsigned int highmem_pages = -1;
 
@@ -761,15 +710,15 @@
 	highstart_pfn = highend_pfn = max_pfn;
 	if (max_pfn > max_low_pfn)
 		highstart_pfn = max_low_pfn;
-	memory_present(0, 0, highend_pfn);
 	e820_register_active_regions(0, 0, highend_pfn);
+	sparse_memory_present_with_active_regions(0);
 	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
 		pages_to_mb(highend_pfn - highstart_pfn));
 	num_physpages = highend_pfn;
 	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
 #else
-	memory_present(0, 0, max_low_pfn);
 	e820_register_active_regions(0, 0, max_low_pfn);
+	sparse_memory_present_with_active_regions(0);
 	num_physpages = max_low_pfn;
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
 #endif
@@ -1011,7 +960,7 @@
 		test_wp_bit();
 
 	save_pg_dir();
-	zap_low_mappings();
+	zap_low_mappings(true);
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/init_64.c linux-libre-2.6.31-gnu/arch/x86/mm/init_64.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/init_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/init_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,18 +50,8 @@
 #include <asm/cacheflush.h>
 #include <asm/init.h>
 
-/*
- * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
- * The direct mapping extends to max_pfn_mapped, so that we can directly access
- * apertures, ACPI and other tables without having to play with fixmaps.
- */
-unsigned long max_low_pfn_mapped;
-unsigned long max_pfn_mapped;
-
 static unsigned long dma_reserve __initdata;
 
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
 static int __init parse_direct_gbpages_off(char *arg)
 {
 	direct_gbpages = 0;
@@ -85,39 +75,6 @@
 pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
-static int disable_nx __cpuinitdata;
-
-/*
- * noexec=on|off
- * Control non-executable mappings for 64-bit processes.
- *
- * on	Enable (default)
- * off	Disable
- */
-static int __init nonx_setup(char *str)
-{
-	if (!str)
-		return -EINVAL;
-	if (!strncmp(str, "on", 2)) {
-		__supported_pte_mask |= _PAGE_NX;
-		disable_nx = 0;
-	} else if (!strncmp(str, "off", 3)) {
-		disable_nx = 1;
-		__supported_pte_mask &= ~_PAGE_NX;
-	}
-	return 0;
-}
-early_param("noexec", nonx_setup);
-
-void __cpuinit check_efer(void)
-{
-	unsigned long efer;
-
-	rdmsrl(MSR_EFER, efer);
-	if (!(efer & EFER_NX) || disable_nx)
-		__supported_pte_mask &= ~_PAGE_NX;
-}
-
 int force_personality32;
 
 /*
@@ -147,7 +104,7 @@
 	void *ptr;
 
 	if (after_bootmem)
-		ptr = (void *) get_zeroed_page(GFP_ATOMIC);
+		ptr = (void *) get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
 	else
 		ptr = alloc_bootmem_pages(PAGE_SIZE);
 
@@ -324,7 +281,7 @@
 	void *adr;
 
 	if (after_bootmem) {
-		adr = (void *)get_zeroed_page(GFP_ATOMIC);
+		adr = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
 		*phys = __pa(adr);
 
 		return adr;
@@ -570,7 +527,7 @@
 	return phys_pud_init(pud, addr, end, page_size_mask);
 }
 
-unsigned long __init
+unsigned long __meminit
 kernel_physical_mapping_init(unsigned long start,
 			     unsigned long end,
 			     unsigned long page_size_mask)
@@ -628,6 +585,7 @@
 	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
 	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
 }
+#endif
 
 void __init paging_init(void)
 {
@@ -638,11 +596,19 @@
 	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
 	max_zone_pfns[ZONE_NORMAL] = max_pfn;
 
-	memory_present(0, 0, max_pfn);
+	sparse_memory_present_with_active_regions(MAX_NUMNODES);
 	sparse_init();
+
+	/*
+	 * clear the default setting with node 0
+	 * note: don't use nodes_clear here, that is really clearing when
+	 *	 numa support is not compiled in, and later node_set_state
+	 *	 will not set it back.
+	 */
+	node_clear_state(0, N_NORMAL_MEMORY);
+
 	free_area_init_nodes(max_zone_pfns);
 }
-#endif
 
 /*
  * Memory hotplug specific functions
@@ -830,7 +796,7 @@
 		return ret;
 
 #else
-	reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+	reserve_bootmem(phys, len, flags);
 #endif
 
 	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/init.c linux-libre-2.6.31-gnu/arch/x86/mm/init.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/init.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,3 +1,4 @@
+#include <linux/initrd.h>
 #include <linux/ioport.h>
 #include <linux/swap.h>
 
@@ -10,6 +11,10 @@
 #include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/tlbflush.h>
+#include <asm/tlb.h>
+#include <asm/proto.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 unsigned long __initdata e820_table_start;
 unsigned long __meminitdata e820_table_end;
@@ -23,6 +28,69 @@
 #endif
 ;
 
+int nx_enabled;
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+static int disable_nx __cpuinitdata;
+
+/*
+ * noexec = on|off
+ *
+ * Control non-executable mappings for processes.
+ *
+ * on      Enable
+ * off     Disable
+ */
+static int __init noexec_setup(char *str)
+{
+	if (!str)
+		return -EINVAL;
+	if (!strncmp(str, "on", 2)) {
+		__supported_pte_mask |= _PAGE_NX;
+		disable_nx = 0;
+	} else if (!strncmp(str, "off", 3)) {
+		disable_nx = 1;
+		__supported_pte_mask &= ~_PAGE_NX;
+	}
+	return 0;
+}
+early_param("noexec", noexec_setup);
+#endif
+
+#ifdef CONFIG_X86_PAE
+static void __init set_nx(void)
+{
+	unsigned int v[4], l, h;
+
+	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
+		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
+
+		if ((v[3] & (1 << 20)) && !disable_nx) {
+			rdmsr(MSR_EFER, l, h);
+			l |= EFER_NX;
+			wrmsr(MSR_EFER, l, h);
+			nx_enabled = 1;
+			__supported_pte_mask |= _PAGE_NX;
+		}
+	}
+}
+#else
+static inline void set_nx(void)
+{
+}
+#endif
+
+#ifdef CONFIG_X86_64
+void __cpuinit check_efer(void)
+{
+	unsigned long efer;
+
+	rdmsrl(MSR_EFER, efer);
+	if (!(efer & EFER_NX) || disable_nx)
+		__supported_pte_mask &= ~_PAGE_NX;
+}
+#endif
+
 static void __init find_early_table_space(unsigned long end, int use_pse,
 					  int use_gbpages)
 {
@@ -66,12 +134,11 @@
 	 */
 #ifdef CONFIG_X86_32
 	start = 0x7000;
-	e820_table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
-					tables, PAGE_SIZE);
-#else /* CONFIG_X86_64 */
+#else
 	start = 0x8000;
-	e820_table_start = find_e820_area(start, end, tables, PAGE_SIZE);
 #endif
+	e820_table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
+					tables, PAGE_SIZE);
 	if (e820_table_start == -1UL)
 		panic("Cannot find space for the kernel page tables");
 
@@ -111,20 +178,6 @@
 	return nr_range;
 }
 
-#ifdef CONFIG_X86_64
-static void __init init_gbpages(void)
-{
-	if (direct_gbpages && cpu_has_gbpages)
-		printk(KERN_INFO "Using GB pages for direct mapping\n");
-	else
-		direct_gbpages = 0;
-}
-#else
-static inline void init_gbpages(void)
-{
-}
-#endif
-
 /*
  * Setup the direct mapping of the physical memory at PAGE_OFFSET.
  * This runs before bootmem is initialized and gets pages directly from
@@ -144,10 +197,7 @@
 
 	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
 
-	if (!after_bootmem)
-		init_gbpages();
-
-#ifdef CONFIG_DEBUG_PAGEALLOC
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
 	/*
 	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
 	 * This will simplify cpa(), which otherwise needs to support splitting
@@ -159,12 +209,9 @@
 	use_gbpages = direct_gbpages;
 #endif
 
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_X86_PAE
 	set_nx();
 	if (nx_enabled)
 		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
-#endif
 
 	/* Enable PSE if available */
 	if (cpu_has_pse)
@@ -175,7 +222,6 @@
 		set_in_cr4(X86_CR4_PGE);
 		__supported_pte_mask |= _PAGE_GLOBAL;
 	}
-#endif
 
 	if (use_gbpages)
 		page_size_mask |= 1 << PG_LEVEL_1G;
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/iomap_32.c linux-libre-2.6.31-gnu/arch/x86/mm/iomap_32.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/iomap_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/iomap_32.c	2009-09-09 18:13:59.000000000 -0400
@@ -82,7 +82,6 @@
 	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
 		kpte_clear_flush(kmap_pte-idx, vaddr);
 
-	arch_flush_lazy_mmu_mode();
 	pagefault_enable();
 }
 EXPORT_SYMBOL_GPL(iounmap_atomic);
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/error.c linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/error.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/error.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/error.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,228 @@
+#include <linux/interrupt.h>
+#include <linux/kdebug.h>
+#include <linux/kmemcheck.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/stacktrace.h>
+#include <linux/string.h>
+
+#include "error.h"
+#include "shadow.h"
+
+enum kmemcheck_error_type {
+	KMEMCHECK_ERROR_INVALID_ACCESS,
+	KMEMCHECK_ERROR_BUG,
+};
+
+#define SHADOW_COPY_SIZE (1 << CONFIG_KMEMCHECK_SHADOW_COPY_SHIFT)
+
+struct kmemcheck_error {
+	enum kmemcheck_error_type type;
+
+	union {
+		/* KMEMCHECK_ERROR_INVALID_ACCESS */
+		struct {
+			/* Kind of access that caused the error */
+			enum kmemcheck_shadow state;
+			/* Address and size of the erroneous read */
+			unsigned long	address;
+			unsigned int	size;
+		};
+	};
+
+	struct pt_regs		regs;
+	struct stack_trace	trace;
+	unsigned long		trace_entries[32];
+
+	/* We compress it to a char. */
+	unsigned char		shadow_copy[SHADOW_COPY_SIZE];
+	unsigned char		memory_copy[SHADOW_COPY_SIZE];
+};
+
+/*
+ * Create a ring queue of errors to output. We can't call printk() directly
+ * from the kmemcheck traps, since this may call the console drivers and
+ * result in a recursive fault.
+ */
+static struct kmemcheck_error error_fifo[CONFIG_KMEMCHECK_QUEUE_SIZE];
+static unsigned int error_count;
+static unsigned int error_rd;
+static unsigned int error_wr;
+static unsigned int error_missed_count;
+
+static struct kmemcheck_error *error_next_wr(void)
+{
+	struct kmemcheck_error *e;
+
+	if (error_count == ARRAY_SIZE(error_fifo)) {
+		++error_missed_count;
+		return NULL;
+	}
+
+	e = &error_fifo[error_wr];
+	if (++error_wr == ARRAY_SIZE(error_fifo))
+		error_wr = 0;
+	++error_count;
+	return e;
+}
+
+static struct kmemcheck_error *error_next_rd(void)
+{
+	struct kmemcheck_error *e;
+
+	if (error_count == 0)
+		return NULL;
+
+	e = &error_fifo[error_rd];
+	if (++error_rd == ARRAY_SIZE(error_fifo))
+		error_rd = 0;
+	--error_count;
+	return e;
+}
+
+void kmemcheck_error_recall(void)
+{
+	static const char *desc[] = {
+		[KMEMCHECK_SHADOW_UNALLOCATED]		= "unallocated",
+		[KMEMCHECK_SHADOW_UNINITIALIZED]	= "uninitialized",
+		[KMEMCHECK_SHADOW_INITIALIZED]		= "initialized",
+		[KMEMCHECK_SHADOW_FREED]		= "freed",
+	};
+
+	static const char short_desc[] = {
+		[KMEMCHECK_SHADOW_UNALLOCATED]		= 'a',
+		[KMEMCHECK_SHADOW_UNINITIALIZED]	= 'u',
+		[KMEMCHECK_SHADOW_INITIALIZED]		= 'i',
+		[KMEMCHECK_SHADOW_FREED]		= 'f',
+	};
+
+	struct kmemcheck_error *e;
+	unsigned int i;
+
+	e = error_next_rd();
+	if (!e)
+		return;
+
+	switch (e->type) {
+	case KMEMCHECK_ERROR_INVALID_ACCESS:
+		printk(KERN_ERR  "WARNING: kmemcheck: Caught %d-bit read "
+			"from %s memory (%p)\n",
+			8 * e->size, e->state < ARRAY_SIZE(desc) ?
+				desc[e->state] : "(invalid shadow state)",
+			(void *) e->address);
+
+		printk(KERN_INFO);
+		for (i = 0; i < SHADOW_COPY_SIZE; ++i)
+			printk("%02x", e->memory_copy[i]);
+		printk("\n");
+
+		printk(KERN_INFO);
+		for (i = 0; i < SHADOW_COPY_SIZE; ++i) {
+			if (e->shadow_copy[i] < ARRAY_SIZE(short_desc))
+				printk(" %c", short_desc[e->shadow_copy[i]]);
+			else
+				printk(" ?");
+		}
+		printk("\n");
+		printk(KERN_INFO "%*c\n", 2 + 2
+			* (int) (e->address & (SHADOW_COPY_SIZE - 1)), '^');
+		break;
+	case KMEMCHECK_ERROR_BUG:
+		printk(KERN_EMERG "ERROR: kmemcheck: Fatal error\n");
+		break;
+	}
+
+	__show_regs(&e->regs, 1);
+	print_stack_trace(&e->trace, 0);
+}
+
+static void do_wakeup(unsigned long data)
+{
+	while (error_count > 0)
+		kmemcheck_error_recall();
+
+	if (error_missed_count > 0) {
+		printk(KERN_WARNING "kmemcheck: Lost %d error reports because "
+			"the queue was too small\n", error_missed_count);
+		error_missed_count = 0;
+	}
+}
+
+static DECLARE_TASKLET(kmemcheck_tasklet, &do_wakeup, 0);
+
+/*
+ * Save the context of an error report.
+ */
+void kmemcheck_error_save(enum kmemcheck_shadow state,
+	unsigned long address, unsigned int size, struct pt_regs *regs)
+{
+	static unsigned long prev_ip;
+
+	struct kmemcheck_error *e;
+	void *shadow_copy;
+	void *memory_copy;
+
+	/* Don't report several adjacent errors from the same EIP. */
+	if (regs->ip == prev_ip)
+		return;
+	prev_ip = regs->ip;
+
+	e = error_next_wr();
+	if (!e)
+		return;
+
+	e->type = KMEMCHECK_ERROR_INVALID_ACCESS;
+
+	e->state = state;
+	e->address = address;
+	e->size = size;
+
+	/* Save regs */
+	memcpy(&e->regs, regs, sizeof(*regs));
+
+	/* Save stack trace */
+	e->trace.nr_entries = 0;
+	e->trace.entries = e->trace_entries;
+	e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
+	e->trace.skip = 0;
+	save_stack_trace_bp(&e->trace, regs->bp);
+
+	/* Round address down to nearest 16 bytes */
+	shadow_copy = kmemcheck_shadow_lookup(address
+		& ~(SHADOW_COPY_SIZE - 1));
+	BUG_ON(!shadow_copy);
+
+	memcpy(e->shadow_copy, shadow_copy, SHADOW_COPY_SIZE);
+
+	kmemcheck_show_addr(address);
+	memory_copy = (void *) (address & ~(SHADOW_COPY_SIZE - 1));
+	memcpy(e->memory_copy, memory_copy, SHADOW_COPY_SIZE);
+	kmemcheck_hide_addr(address);
+
+	tasklet_hi_schedule_first(&kmemcheck_tasklet);
+}
+
+/*
+ * Save the context of a kmemcheck bug.
+ */
+void kmemcheck_error_save_bug(struct pt_regs *regs)
+{
+	struct kmemcheck_error *e;
+
+	e = error_next_wr();
+	if (!e)
+		return;
+
+	e->type = KMEMCHECK_ERROR_BUG;
+
+	memcpy(&e->regs, regs, sizeof(*regs));
+
+	e->trace.nr_entries = 0;
+	e->trace.entries = e->trace_entries;
+	e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
+	e->trace.skip = 1;
+	save_stack_trace(&e->trace);
+
+	tasklet_hi_schedule_first(&kmemcheck_tasklet);
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/error.h linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/error.h
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/error.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/error.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,15 @@
+#ifndef ARCH__X86__MM__KMEMCHECK__ERROR_H
+#define ARCH__X86__MM__KMEMCHECK__ERROR_H
+
+#include <linux/ptrace.h>
+
+#include "shadow.h"
+
+void kmemcheck_error_save(enum kmemcheck_shadow state,
+	unsigned long address, unsigned int size, struct pt_regs *regs);
+
+void kmemcheck_error_save_bug(struct pt_regs *regs);
+
+void kmemcheck_error_recall(void);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/kmemcheck.c linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/kmemcheck.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/kmemcheck.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/kmemcheck.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,640 @@
+/**
+ * kmemcheck - a heavyweight memory checker for the linux kernel
+ * Copyright (C) 2007, 2008  Vegard Nossum <vegardno@ifi.uio.no>
+ * (With a lot of help from Ingo Molnar and Pekka Enberg.)
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/kmemcheck.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/page-flags.h>
+#include <linux/percpu.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/cacheflush.h>
+#include <asm/kmemcheck.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+#include "error.h"
+#include "opcode.h"
+#include "pte.h"
+#include "selftest.h"
+#include "shadow.h"
+
+
+#ifdef CONFIG_KMEMCHECK_DISABLED_BY_DEFAULT
+#  define KMEMCHECK_ENABLED 0
+#endif
+
+#ifdef CONFIG_KMEMCHECK_ENABLED_BY_DEFAULT
+#  define KMEMCHECK_ENABLED 1
+#endif
+
+#ifdef CONFIG_KMEMCHECK_ONESHOT_BY_DEFAULT
+#  define KMEMCHECK_ENABLED 2
+#endif
+
+int kmemcheck_enabled = KMEMCHECK_ENABLED;
+
+int __init kmemcheck_init(void)
+{
+#ifdef CONFIG_SMP
+	/*
+	 * Limit SMP to use a single CPU. We rely on the fact that this code
+	 * runs before SMP is set up.
+	 */
+	if (setup_max_cpus > 1) {
+		printk(KERN_INFO
+			"kmemcheck: Limiting number of CPUs to 1.\n");
+		setup_max_cpus = 1;
+	}
+#endif
+
+	if (!kmemcheck_selftest()) {
+		printk(KERN_INFO "kmemcheck: self-tests failed; disabling\n");
+		kmemcheck_enabled = 0;
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "kmemcheck: Initialized\n");
+	return 0;
+}
+
+early_initcall(kmemcheck_init);
+
+/*
+ * We need to parse the kmemcheck= option before any memory is allocated.
+ */
+static int __init param_kmemcheck(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	sscanf(str, "%d", &kmemcheck_enabled);
+	return 0;
+}
+
+early_param("kmemcheck", param_kmemcheck);
+
+int kmemcheck_show_addr(unsigned long address)
+{
+	pte_t *pte;
+
+	pte = kmemcheck_pte_lookup(address);
+	if (!pte)
+		return 0;
+
+	set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));
+	__flush_tlb_one(address);
+	return 1;
+}
+
+int kmemcheck_hide_addr(unsigned long address)
+{
+	pte_t *pte;
+
+	pte = kmemcheck_pte_lookup(address);
+	if (!pte)
+		return 0;
+
+	set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
+	__flush_tlb_one(address);
+	return 1;
+}
+
+struct kmemcheck_context {
+	bool busy;
+	int balance;
+
+	/*
+	 * There can be at most two memory operands to an instruction, but
+	 * each address can cross a page boundary -- so we may need up to
+	 * four addresses that must be hidden/revealed for each fault.
+	 */
+	unsigned long addr[4];
+	unsigned long n_addrs;
+	unsigned long flags;
+
+	/* Data size of the instruction that caused a fault. */
+	unsigned int size;
+};
+
+static DEFINE_PER_CPU(struct kmemcheck_context, kmemcheck_context);
+
+bool kmemcheck_active(struct pt_regs *regs)
+{
+	struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context);
+
+	return data->balance > 0;
+}
+
+/* Save an address that needs to be shown/hidden */
+static void kmemcheck_save_addr(unsigned long addr)
+{
+	struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context);
+
+	BUG_ON(data->n_addrs >= ARRAY_SIZE(data->addr));
+	data->addr[data->n_addrs++] = addr;
+}
+
+static unsigned int kmemcheck_show_all(void)
+{
+	struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context);
+	unsigned int i;
+	unsigned int n;
+
+	n = 0;
+	for (i = 0; i < data->n_addrs; ++i)
+		n += kmemcheck_show_addr(data->addr[i]);
+
+	return n;
+}
+
+static unsigned int kmemcheck_hide_all(void)
+{
+	struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context);
+	unsigned int i;
+	unsigned int n;
+
+	n = 0;
+	for (i = 0; i < data->n_addrs; ++i)
+		n += kmemcheck_hide_addr(data->addr[i]);
+
+	return n;
+}
+
+/*
+ * Called from the #PF handler.
+ */
+void kmemcheck_show(struct pt_regs *regs)
+{
+	struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context);
+
+	BUG_ON(!irqs_disabled());
+
+	if (unlikely(data->balance != 0)) {
+		kmemcheck_show_all();
+		kmemcheck_error_save_bug(regs);
+		data->balance = 0;
+		return;
+	}
+
+	/*
+	 * None of the addresses actually belonged to kmemcheck. Note that
+	 * this is not an error.
+	 */
+	if (kmemcheck_show_all() == 0)
+		return;
+
+	++data->balance;
+
+	/*
+	 * The IF needs to be cleared as well, so that the faulting
+	 * instruction can run "uninterrupted". Otherwise, we might take
+	 * an interrupt and start executing that before we've had a chance
+	 * to hide the page again.
+	 *
+	 * NOTE: In the rare case of multiple faults, we must not override
+	 * the original flags:
+	 */
+	if (!(regs->flags & X86_EFLAGS_TF))
+		data->flags = regs->flags;
+
+	regs->flags |= X86_EFLAGS_TF;
+	regs->flags &= ~X86_EFLAGS_IF;
+}
+
+/*
+ * Called from the #DB handler.
+ */
+void kmemcheck_hide(struct pt_regs *regs)
+{
+	struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context);
+	int n;
+
+	BUG_ON(!irqs_disabled());
+
+	if (data->balance == 0)
+		return;
+
+	if (unlikely(data->balance != 1)) {
+		kmemcheck_show_all();
+		kmemcheck_error_save_bug(regs);
+		data->n_addrs = 0;
+		data->balance = 0;
+
+		if (!(data->flags & X86_EFLAGS_TF))
+			regs->flags &= ~X86_EFLAGS_TF;
+		if (data->flags & X86_EFLAGS_IF)
+			regs->flags |= X86_EFLAGS_IF;
+		return;
+	}
+
+	if (kmemcheck_enabled)
+		n = kmemcheck_hide_all();
+	else
+		n = kmemcheck_show_all();
+
+	if (n == 0)
+		return;
+
+	--data->balance;
+
+	data->n_addrs = 0;
+
+	if (!(data->flags & X86_EFLAGS_TF))
+		regs->flags &= ~X86_EFLAGS_TF;
+	if (data->flags & X86_EFLAGS_IF)
+		regs->flags |= X86_EFLAGS_IF;
+}
+
+void kmemcheck_show_pages(struct page *p, unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 0; i < n; ++i) {
+		unsigned long address;
+		pte_t *pte;
+		unsigned int level;
+
+		address = (unsigned long) page_address(&p[i]);
+		pte = lookup_address(address, &level);
+		BUG_ON(!pte);
+		BUG_ON(level != PG_LEVEL_4K);
+
+		set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));
+		set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_HIDDEN));
+		__flush_tlb_one(address);
+	}
+}
+
+bool kmemcheck_page_is_tracked(struct page *p)
+{
+	/* This will also check the "hidden" flag of the PTE. */
+	return kmemcheck_pte_lookup((unsigned long) page_address(p));
+}
+
+void kmemcheck_hide_pages(struct page *p, unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 0; i < n; ++i) {
+		unsigned long address;
+		pte_t *pte;
+		unsigned int level;
+
+		address = (unsigned long) page_address(&p[i]);
+		pte = lookup_address(address, &level);
+		BUG_ON(!pte);
+		BUG_ON(level != PG_LEVEL_4K);
+
+		set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
+		set_pte(pte, __pte(pte_val(*pte) | _PAGE_HIDDEN));
+		__flush_tlb_one(address);
+	}
+}
+
+/* Access may NOT cross page boundary */
+static void kmemcheck_read_strict(struct pt_regs *regs,
+	unsigned long addr, unsigned int size)
+{
+	void *shadow;
+	enum kmemcheck_shadow status;
+
+	shadow = kmemcheck_shadow_lookup(addr);
+	if (!shadow)
+		return;
+
+	kmemcheck_save_addr(addr);
+	status = kmemcheck_shadow_test(shadow, size);
+	if (status == KMEMCHECK_SHADOW_INITIALIZED)
+		return;
+
+	if (kmemcheck_enabled)
+		kmemcheck_error_save(status, addr, size, regs);
+
+	if (kmemcheck_enabled == 2)
+		kmemcheck_enabled = 0;
+
+	/* Don't warn about it again. */
+	kmemcheck_shadow_set(shadow, size);
+}
+
+/* Access may cross page boundary */
+static void kmemcheck_read(struct pt_regs *regs,
+	unsigned long addr, unsigned int size)
+{
+	unsigned long page = addr & PAGE_MASK;
+	unsigned long next_addr = addr + size - 1;
+	unsigned long next_page = next_addr & PAGE_MASK;
+
+	if (likely(page == next_page)) {
+		kmemcheck_read_strict(regs, addr, size);
+		return;
+	}
+
+	/*
+	 * What we do is basically to split the access across the
+	 * two pages and handle each part separately. Yes, this means
+	 * that we may now see reads that are 3 + 5 bytes, for
+	 * example (and if both are uninitialized, there will be two
+	 * reports), but it makes the code a lot simpler.
+	 */
+	kmemcheck_read_strict(regs, addr, next_page - addr);
+	kmemcheck_read_strict(regs, next_page, next_addr - next_page);
+}
+
+static void kmemcheck_write_strict(struct pt_regs *regs,
+	unsigned long addr, unsigned int size)
+{
+	void *shadow;
+
+	shadow = kmemcheck_shadow_lookup(addr);
+	if (!shadow)
+		return;
+
+	kmemcheck_save_addr(addr);
+	kmemcheck_shadow_set(shadow, size);
+}
+
+static void kmemcheck_write(struct pt_regs *regs,
+	unsigned long addr, unsigned int size)
+{
+	unsigned long page = addr & PAGE_MASK;
+	unsigned long next_addr = addr + size - 1;
+	unsigned long next_page = next_addr & PAGE_MASK;
+
+	if (likely(page == next_page)) {
+		kmemcheck_write_strict(regs, addr, size);
+		return;
+	}
+
+	/* See comment in kmemcheck_read(). */
+	kmemcheck_write_strict(regs, addr, next_page - addr);
+	kmemcheck_write_strict(regs, next_page, next_addr - next_page);
+}
+
+/*
+ * Copying is hard. We have two addresses, each of which may be split across
+ * a page (and each page will have different shadow addresses).
+ */
+static void kmemcheck_copy(struct pt_regs *regs,
+	unsigned long src_addr, unsigned long dst_addr, unsigned int size)
+{
+	uint8_t shadow[8];
+	enum kmemcheck_shadow status;
+
+	unsigned long page;
+	unsigned long next_addr;
+	unsigned long next_page;
+
+	uint8_t *x;
+	unsigned int i;
+	unsigned int n;
+
+	BUG_ON(size > sizeof(shadow));
+
+	page = src_addr & PAGE_MASK;
+	next_addr = src_addr + size - 1;
+	next_page = next_addr & PAGE_MASK;
+
+	if (likely(page == next_page)) {
+		/* Same page */
+		x = kmemcheck_shadow_lookup(src_addr);
+		if (x) {
+			kmemcheck_save_addr(src_addr);
+			for (i = 0; i < size; ++i)
+				shadow[i] = x[i];
+		} else {
+			for (i = 0; i < size; ++i)
+				shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
+		}
+	} else {
+		n = next_page - src_addr;
+		BUG_ON(n > sizeof(shadow));
+
+		/* First page */
+		x = kmemcheck_shadow_lookup(src_addr);
+		if (x) {
+			kmemcheck_save_addr(src_addr);
+			for (i = 0; i < n; ++i)
+				shadow[i] = x[i];
+		} else {
+			/* Not tracked */
+			for (i = 0; i < n; ++i)
+				shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
+		}
+
+		/* Second page */
+		x = kmemcheck_shadow_lookup(next_page);
+		if (x) {
+			kmemcheck_save_addr(next_page);
+			for (i = n; i < size; ++i)
+				shadow[i] = x[i - n];
+		} else {
+			/* Not tracked */
+			for (i = n; i < size; ++i)
+				shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
+		}
+	}
+
+	page = dst_addr & PAGE_MASK;
+	next_addr = dst_addr + size - 1;
+	next_page = next_addr & PAGE_MASK;
+
+	if (likely(page == next_page)) {
+		/* Same page */
+		x = kmemcheck_shadow_lookup(dst_addr);
+		if (x) {
+			kmemcheck_save_addr(dst_addr);
+			for (i = 0; i < size; ++i) {
+				x[i] = shadow[i];
+				shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
+			}
+		}
+	} else {
+		n = next_page - dst_addr;
+		BUG_ON(n > sizeof(shadow));
+
+		/* First page */
+		x = kmemcheck_shadow_lookup(dst_addr);
+		if (x) {
+			kmemcheck_save_addr(dst_addr);
+			for (i = 0; i < n; ++i) {
+				x[i] = shadow[i];
+				shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
+			}
+		}
+
+		/* Second page */
+		x = kmemcheck_shadow_lookup(next_page);
+		if (x) {
+			kmemcheck_save_addr(next_page);
+			for (i = n; i < size; ++i) {
+				x[i - n] = shadow[i];
+				shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
+			}
+		}
+	}
+
+	status = kmemcheck_shadow_test(shadow, size);
+	if (status == KMEMCHECK_SHADOW_INITIALIZED)
+		return;
+
+	if (kmemcheck_enabled)
+		kmemcheck_error_save(status, src_addr, size, regs);
+
+	if (kmemcheck_enabled == 2)
+		kmemcheck_enabled = 0;
+}
+
+enum kmemcheck_method {
+	KMEMCHECK_READ,
+	KMEMCHECK_WRITE,
+};
+
+static void kmemcheck_access(struct pt_regs *regs,
+	unsigned long fallback_address, enum kmemcheck_method fallback_method)
+{
+	const uint8_t *insn;
+	const uint8_t *insn_primary;
+	unsigned int size;
+
+	struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context);
+
+	/* Recursive fault -- ouch. */
+	if (data->busy) {
+		kmemcheck_show_addr(fallback_address);
+		kmemcheck_error_save_bug(regs);
+		return;
+	}
+
+	data->busy = true;
+
+	insn = (const uint8_t *) regs->ip;
+	insn_primary = kmemcheck_opcode_get_primary(insn);
+
+	kmemcheck_opcode_decode(insn, &size);
+
+	switch (insn_primary[0]) {
+#ifdef CONFIG_KMEMCHECK_BITOPS_OK
+		/* AND, OR, XOR */
+		/*
+		 * Unfortunately, these instructions have to be excluded from
+		 * our regular checking since they access only some (and not
+		 * all) bits. This clears out "bogus" bitfield-access warnings.
+		 */
+	case 0x80:
+	case 0x81:
+	case 0x82:
+	case 0x83:
+		switch ((insn_primary[1] >> 3) & 7) {
+			/* OR */
+		case 1:
+			/* AND */
+		case 4:
+			/* XOR */
+		case 6:
+			kmemcheck_write(regs, fallback_address, size);
+			goto out;
+
+			/* ADD */
+		case 0:
+			/* ADC */
+		case 2:
+			/* SBB */
+		case 3:
+			/* SUB */
+		case 5:
+			/* CMP */
+		case 7:
+			break;
+		}
+		break;
+#endif
+
+		/* MOVS, MOVSB, MOVSW, MOVSD */
+	case 0xa4:
+	case 0xa5:
+		/*
+		 * These instructions are special because they take two
+		 * addresses, but we only get one page fault.
+		 */
+		kmemcheck_copy(regs, regs->si, regs->di, size);
+		goto out;
+
+		/* CMPS, CMPSB, CMPSW, CMPSD */
+	case 0xa6:
+	case 0xa7:
+		kmemcheck_read(regs, regs->si, size);
+		kmemcheck_read(regs, regs->di, size);
+		goto out;
+	}
+
+	/*
+	 * If the opcode isn't special in any way, we use the data from the
+	 * page fault handler to determine the address and type of memory
+	 * access.
+	 */
+	switch (fallback_method) {
+	case KMEMCHECK_READ:
+		kmemcheck_read(regs, fallback_address, size);
+		goto out;
+	case KMEMCHECK_WRITE:
+		kmemcheck_write(regs, fallback_address, size);
+		goto out;
+	}
+
+out:
+	data->busy = false;
+}
+
+bool kmemcheck_fault(struct pt_regs *regs, unsigned long address,
+	unsigned long error_code)
+{
+	pte_t *pte;
+
+	/*
+	 * XXX: Is it safe to assume that memory accesses from virtual 86
+	 * mode or non-kernel code segments will _never_ access kernel
+	 * memory (e.g. tracked pages)? For now, we need this to avoid
+	 * invoking kmemcheck for PnP BIOS calls.
+	 */
+	if (regs->flags & X86_VM_MASK)
+		return false;
+	if (regs->cs != __KERNEL_CS)
+		return false;
+
+	pte = kmemcheck_pte_lookup(address);
+	if (!pte)
+		return false;
+
+	if (error_code & 2)
+		kmemcheck_access(regs, address, KMEMCHECK_WRITE);
+	else
+		kmemcheck_access(regs, address, KMEMCHECK_READ);
+
+	kmemcheck_show(regs);
+	return true;
+}
+
+bool kmemcheck_trap(struct pt_regs *regs)
+{
+	if (!kmemcheck_active(regs))
+		return false;
+
+	/* We're done. */
+	kmemcheck_hide(regs);
+	return true;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/Makefile linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+obj-y := error.o kmemcheck.o opcode.o pte.o selftest.o shadow.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/opcode.c linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/opcode.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/opcode.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/opcode.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,106 @@
+#include <linux/types.h>
+
+#include "opcode.h"
+
+static bool opcode_is_prefix(uint8_t b)
+{
+	return
+		/* Group 1 */
+		b == 0xf0 || b == 0xf2 || b == 0xf3
+		/* Group 2 */
+		|| b == 0x2e || b == 0x36 || b == 0x3e || b == 0x26
+		|| b == 0x64 || b == 0x65 || b == 0x2e || b == 0x3e
+		/* Group 3 */
+		|| b == 0x66
+		/* Group 4 */
+		|| b == 0x67;
+}
+
+#ifdef CONFIG_X86_64
+static bool opcode_is_rex_prefix(uint8_t b)
+{
+	return (b & 0xf0) == 0x40;
+}
+#else
+static bool opcode_is_rex_prefix(uint8_t b)
+{
+	return false;
+}
+#endif
+
+#define REX_W (1 << 3)
+
+/*
+ * This is a VERY crude opcode decoder. We only need to find the size of the
+ * load/store that caused our #PF and this should work for all the opcodes
+ * that we care about. Moreover, the ones who invented this instruction set
+ * should be shot.
+ */
+void kmemcheck_opcode_decode(const uint8_t *op, unsigned int *size)
+{
+	/* Default operand size */
+	int operand_size_override = 4;
+
+	/* prefixes */
+	for (; opcode_is_prefix(*op); ++op) {
+		if (*op == 0x66)
+			operand_size_override = 2;
+	}
+
+	/* REX prefix */
+	if (opcode_is_rex_prefix(*op)) {
+		uint8_t rex = *op;
+
+		++op;
+		if (rex & REX_W) {
+			switch (*op) {
+			case 0x63:
+				*size = 4;
+				return;
+			case 0x0f:
+				++op;
+
+				switch (*op) {
+				case 0xb6:
+				case 0xbe:
+					*size = 1;
+					return;
+				case 0xb7:
+				case 0xbf:
+					*size = 2;
+					return;
+				}
+
+				break;
+			}
+
+			*size = 8;
+			return;
+		}
+	}
+
+	/* escape opcode */
+	if (*op == 0x0f) {
+		++op;
+
+		/*
+		 * This is move with zero-extend and sign-extend, respectively;
+		 * we don't have to think about 0xb6/0xbe, because this is
+		 * already handled in the conditional below.
+		 */
+		if (*op == 0xb7 || *op == 0xbf)
+			operand_size_override = 2;
+	}
+
+	*size = (*op & 1) ? operand_size_override : 1;
+}
+
+const uint8_t *kmemcheck_opcode_get_primary(const uint8_t *op)
+{
+	/* skip prefixes */
+	while (opcode_is_prefix(*op))
+		++op;
+	if (opcode_is_rex_prefix(*op))
+		++op;
+	return op;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/opcode.h linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/opcode.h
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/opcode.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/opcode.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef ARCH__X86__MM__KMEMCHECK__OPCODE_H
+#define ARCH__X86__MM__KMEMCHECK__OPCODE_H
+
+#include <linux/types.h>
+
+void kmemcheck_opcode_decode(const uint8_t *op, unsigned int *size);
+const uint8_t *kmemcheck_opcode_get_primary(const uint8_t *op);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/pte.c linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/pte.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/pte.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/pte.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+#include <linux/mm.h>
+
+#include <asm/pgtable.h>
+
+#include "pte.h"
+
+pte_t *kmemcheck_pte_lookup(unsigned long address)
+{
+	pte_t *pte;
+	unsigned int level;
+
+	pte = lookup_address(address, &level);
+	if (!pte)
+		return NULL;
+	if (level != PG_LEVEL_4K)
+		return NULL;
+	if (!pte_hidden(*pte))
+		return NULL;
+
+	return pte;
+}
+
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/pte.h linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/pte.h
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/pte.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/pte.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,10 @@
+#ifndef ARCH__X86__MM__KMEMCHECK__PTE_H
+#define ARCH__X86__MM__KMEMCHECK__PTE_H
+
+#include <linux/mm.h>
+
+#include <asm/pgtable.h>
+
+pte_t *kmemcheck_pte_lookup(unsigned long address);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/selftest.c linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/selftest.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/selftest.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/selftest.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,69 @@
+#include <linux/kernel.h>
+
+#include "opcode.h"
+#include "selftest.h"
+
+struct selftest_opcode {
+	unsigned int expected_size;
+	const uint8_t *insn;
+	const char *desc;
+};
+
+static const struct selftest_opcode selftest_opcodes[] = {
+	/* REP MOVS */
+	{1, "\xf3\xa4", 		"rep movsb <mem8>, <mem8>"},
+	{4, "\xf3\xa5",			"rep movsl <mem32>, <mem32>"},
+
+	/* MOVZX / MOVZXD */
+	{1, "\x66\x0f\xb6\x51\xf8",	"movzwq <mem8>, <reg16>"},
+	{1, "\x0f\xb6\x51\xf8",		"movzwq <mem8>, <reg32>"},
+
+	/* MOVSX / MOVSXD */
+	{1, "\x66\x0f\xbe\x51\xf8",	"movswq <mem8>, <reg16>"},
+	{1, "\x0f\xbe\x51\xf8",		"movswq <mem8>, <reg32>"},
+
+#ifdef CONFIG_X86_64
+	/* MOVZX / MOVZXD */
+	{1, "\x49\x0f\xb6\x51\xf8",	"movzbq <mem8>, <reg64>"},
+	{2, "\x49\x0f\xb7\x51\xf8",	"movzbq <mem16>, <reg64>"},
+
+	/* MOVSX / MOVSXD */
+	{1, "\x49\x0f\xbe\x51\xf8",	"movsbq <mem8>, <reg64>"},
+	{2, "\x49\x0f\xbf\x51\xf8",	"movsbq <mem16>, <reg64>"},
+	{4, "\x49\x63\x51\xf8",		"movslq <mem32>, <reg64>"},
+#endif
+};
+
+static bool selftest_opcode_one(const struct selftest_opcode *op)
+{
+	unsigned size;
+
+	kmemcheck_opcode_decode(op->insn, &size);
+
+	if (size == op->expected_size)
+		return true;
+
+	printk(KERN_WARNING "kmemcheck: opcode %s: expected size %d, got %d\n",
+		op->desc, op->expected_size, size);
+	return false;
+}
+
+static bool selftest_opcodes_all(void)
+{
+	bool pass = true;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(selftest_opcodes); ++i)
+		pass = pass && selftest_opcode_one(&selftest_opcodes[i]);
+
+	return pass;
+}
+
+bool kmemcheck_selftest(void)
+{
+	bool pass = true;
+
+	pass = pass && selftest_opcodes_all();
+
+	return pass;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/selftest.h linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/selftest.h
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/selftest.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/selftest.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,6 @@
+#ifndef ARCH_X86_MM_KMEMCHECK_SELFTEST_H
+#define ARCH_X86_MM_KMEMCHECK_SELFTEST_H
+
+bool kmemcheck_selftest(void);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/shadow.c linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/shadow.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/shadow.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/shadow.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,162 @@
+#include <linux/kmemcheck.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "pte.h"
+#include "shadow.h"
+
+/*
+ * Return the shadow address for the given address. Returns NULL if the
+ * address is not tracked.
+ *
+ * We need to be extremely careful not to follow any invalid pointers,
+ * because this function can be called for *any* possible address.
+ */
+void *kmemcheck_shadow_lookup(unsigned long address)
+{
+	pte_t *pte;
+	struct page *page;
+
+	if (!virt_addr_valid(address))
+		return NULL;
+
+	pte = kmemcheck_pte_lookup(address);
+	if (!pte)
+		return NULL;
+
+	page = virt_to_page(address);
+	if (!page->shadow)
+		return NULL;
+	return page->shadow + (address & (PAGE_SIZE - 1));
+}
+
+static void mark_shadow(void *address, unsigned int n,
+	enum kmemcheck_shadow status)
+{
+	unsigned long addr = (unsigned long) address;
+	unsigned long last_addr = addr + n - 1;
+	unsigned long page = addr & PAGE_MASK;
+	unsigned long last_page = last_addr & PAGE_MASK;
+	unsigned int first_n;
+	void *shadow;
+
+	/* If the memory range crosses a page boundary, stop there. */
+	if (page == last_page)
+		first_n = n;
+	else
+		first_n = page + PAGE_SIZE - addr;
+
+	shadow = kmemcheck_shadow_lookup(addr);
+	if (shadow)
+		memset(shadow, status, first_n);
+
+	addr += first_n;
+	n -= first_n;
+
+	/* Do full-page memset()s. */
+	while (n >= PAGE_SIZE) {
+		shadow = kmemcheck_shadow_lookup(addr);
+		if (shadow)
+			memset(shadow, status, PAGE_SIZE);
+
+		addr += PAGE_SIZE;
+		n -= PAGE_SIZE;
+	}
+
+	/* Do the remaining page, if any. */
+	if (n > 0) {
+		shadow = kmemcheck_shadow_lookup(addr);
+		if (shadow)
+			memset(shadow, status, n);
+	}
+}
+
+void kmemcheck_mark_unallocated(void *address, unsigned int n)
+{
+	mark_shadow(address, n, KMEMCHECK_SHADOW_UNALLOCATED);
+}
+
+void kmemcheck_mark_uninitialized(void *address, unsigned int n)
+{
+	mark_shadow(address, n, KMEMCHECK_SHADOW_UNINITIALIZED);
+}
+
+/*
+ * Fill the shadow memory of the given address such that the memory at that
+ * address is marked as being initialized.
+ */
+void kmemcheck_mark_initialized(void *address, unsigned int n)
+{
+	mark_shadow(address, n, KMEMCHECK_SHADOW_INITIALIZED);
+}
+EXPORT_SYMBOL_GPL(kmemcheck_mark_initialized);
+
+void kmemcheck_mark_freed(void *address, unsigned int n)
+{
+	mark_shadow(address, n, KMEMCHECK_SHADOW_FREED);
+}
+
+void kmemcheck_mark_unallocated_pages(struct page *p, unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 0; i < n; ++i)
+		kmemcheck_mark_unallocated(page_address(&p[i]), PAGE_SIZE);
+}
+
+void kmemcheck_mark_uninitialized_pages(struct page *p, unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 0; i < n; ++i)
+		kmemcheck_mark_uninitialized(page_address(&p[i]), PAGE_SIZE);
+}
+
+void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 0; i < n; ++i)
+		kmemcheck_mark_initialized(page_address(&p[i]), PAGE_SIZE);
+}
+
+enum kmemcheck_shadow kmemcheck_shadow_test(void *shadow, unsigned int size)
+{
+	uint8_t *x;
+	unsigned int i;
+
+	x = shadow;
+
+#ifdef CONFIG_KMEMCHECK_PARTIAL_OK
+	/*
+	 * Make sure _some_ bytes are initialized. Gcc frequently generates
+	 * code to access neighboring bytes.
+	 */
+	for (i = 0; i < size; ++i) {
+		if (x[i] == KMEMCHECK_SHADOW_INITIALIZED)
+			return x[i];
+	}
+#else
+	/* All bytes must be initialized. */
+	for (i = 0; i < size; ++i) {
+		if (x[i] != KMEMCHECK_SHADOW_INITIALIZED)
+			return x[i];
+	}
+#endif
+
+	return x[0];
+}
+
+void kmemcheck_shadow_set(void *shadow, unsigned int size)
+{
+	uint8_t *x;
+	unsigned int i;
+
+	x = shadow;
+	for (i = 0; i < size; ++i)
+		x[i] = KMEMCHECK_SHADOW_INITIALIZED;
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/shadow.h linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/shadow.h
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmemcheck/shadow.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmemcheck/shadow.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef ARCH__X86__MM__KMEMCHECK__SHADOW_H
+#define ARCH__X86__MM__KMEMCHECK__SHADOW_H
+
+enum kmemcheck_shadow {
+	KMEMCHECK_SHADOW_UNALLOCATED,
+	KMEMCHECK_SHADOW_UNINITIALIZED,
+	KMEMCHECK_SHADOW_INITIALIZED,
+	KMEMCHECK_SHADOW_FREED,
+};
+
+void *kmemcheck_shadow_lookup(unsigned long address);
+
+enum kmemcheck_shadow kmemcheck_shadow_test(void *shadow, unsigned int size);
+void kmemcheck_shadow_set(void *shadow, unsigned int size);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/kmmio.c linux-libre-2.6.31-gnu/arch/x86/mm/kmmio.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/kmmio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/kmmio.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,7 @@
 	struct list_head list;
 	struct kmmio_fault_page *release_next;
 	unsigned long page; /* location of the fault page */
-	bool old_presence; /* page presence prior to arming */
+	pteval_t old_presence; /* page presence prior to arming */
 	bool armed;
 
 	/*
@@ -97,60 +97,62 @@
 static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
 {
 	struct list_head *head;
-	struct kmmio_fault_page *p;
+	struct kmmio_fault_page *f;
 
 	page &= PAGE_MASK;
 	head = kmmio_page_list(page);
-	list_for_each_entry_rcu(p, head, list) {
-		if (p->page == page)
-			return p;
+	list_for_each_entry_rcu(f, head, list) {
+		if (f->page == page)
+			return f;
 	}
 	return NULL;
 }
 
-static void set_pmd_presence(pmd_t *pmd, bool present, bool *old)
+static void clear_pmd_presence(pmd_t *pmd, bool clear, pmdval_t *old)
 {
 	pmdval_t v = pmd_val(*pmd);
-	*old = !!(v & _PAGE_PRESENT);
-	v &= ~_PAGE_PRESENT;
-	if (present)
-		v |= _PAGE_PRESENT;
+	if (clear) {
+		*old = v & _PAGE_PRESENT;
+		v &= ~_PAGE_PRESENT;
+	} else	/* presume this has been called with clear==true previously */
+		v |= *old;
 	set_pmd(pmd, __pmd(v));
 }
 
-static void set_pte_presence(pte_t *pte, bool present, bool *old)
+static void clear_pte_presence(pte_t *pte, bool clear, pteval_t *old)
 {
 	pteval_t v = pte_val(*pte);
-	*old = !!(v & _PAGE_PRESENT);
-	v &= ~_PAGE_PRESENT;
-	if (present)
-		v |= _PAGE_PRESENT;
+	if (clear) {
+		*old = v & _PAGE_PRESENT;
+		v &= ~_PAGE_PRESENT;
+	} else	/* presume this has been called with clear==true previously */
+		v |= *old;
 	set_pte_atomic(pte, __pte(v));
 }
 
-static int set_page_presence(unsigned long addr, bool present, bool *old)
+static int clear_page_presence(struct kmmio_fault_page *f, bool clear)
 {
 	unsigned int level;
-	pte_t *pte = lookup_address(addr, &level);
+	pte_t *pte = lookup_address(f->page, &level);
 
 	if (!pte) {
-		pr_err("kmmio: no pte for page 0x%08lx\n", addr);
+		pr_err("kmmio: no pte for page 0x%08lx\n", f->page);
 		return -1;
 	}
 
 	switch (level) {
 	case PG_LEVEL_2M:
-		set_pmd_presence((pmd_t *)pte, present, old);
+		clear_pmd_presence((pmd_t *)pte, clear, &f->old_presence);
 		break;
 	case PG_LEVEL_4K:
-		set_pte_presence(pte, present, old);
+		clear_pte_presence(pte, clear, &f->old_presence);
 		break;
 	default:
 		pr_err("kmmio: unexpected page level 0x%x.\n", level);
 		return -1;
 	}
 
-	__flush_tlb_one(addr);
+	__flush_tlb_one(f->page);
 	return 0;
 }
 
@@ -171,9 +173,9 @@
 	WARN_ONCE(f->armed, KERN_ERR "kmmio page already armed.\n");
 	if (f->armed) {
 		pr_warning("kmmio double-arm: page 0x%08lx, ref %d, old %d\n",
-					f->page, f->count, f->old_presence);
+					f->page, f->count, !!f->old_presence);
 	}
-	ret = set_page_presence(f->page, false, &f->old_presence);
+	ret = clear_page_presence(f, true);
 	WARN_ONCE(ret < 0, KERN_ERR "kmmio arming 0x%08lx failed.\n", f->page);
 	f->armed = true;
 	return ret;
@@ -182,8 +184,7 @@
 /** Restore the given page to saved presence state. */
 static void disarm_kmmio_fault_page(struct kmmio_fault_page *f)
 {
-	bool tmp;
-	int ret = set_page_presence(f->page, f->old_presence, &tmp);
+	int ret = clear_page_presence(f, false);
 	WARN_ONCE(ret < 0,
 			KERN_ERR "kmmio disarming 0x%08lx failed.\n", f->page);
 	f->armed = false;
@@ -310,7 +311,12 @@
 	struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx);
 
 	if (!ctx->active) {
-		pr_debug("kmmio: spurious debug trap on CPU %d.\n",
+		/*
+		 * debug traps without an active context are due to either
+		 * something external causing them (f.e. using a debugger while
+		 * mmio tracing enabled), or erroneous behaviour
+		 */
+		pr_warning("kmmio: unexpected debug trap on CPU %d.\n",
 							smp_processor_id());
 		goto out;
 	}
@@ -439,12 +445,12 @@
 						head,
 						struct kmmio_delayed_release,
 						rcu);
-	struct kmmio_fault_page *p = dr->release_list;
-	while (p) {
-		struct kmmio_fault_page *next = p->release_next;
-		BUG_ON(p->count);
-		kfree(p);
-		p = next;
+	struct kmmio_fault_page *f = dr->release_list;
+	while (f) {
+		struct kmmio_fault_page *next = f->release_next;
+		BUG_ON(f->count);
+		kfree(f);
+		f = next;
 	}
 	kfree(dr);
 }
@@ -453,19 +459,19 @@
 {
 	struct kmmio_delayed_release *dr =
 		container_of(head, struct kmmio_delayed_release, rcu);
-	struct kmmio_fault_page *p = dr->release_list;
+	struct kmmio_fault_page *f = dr->release_list;
 	struct kmmio_fault_page **prevp = &dr->release_list;
 	unsigned long flags;
 
 	spin_lock_irqsave(&kmmio_lock, flags);
-	while (p) {
-		if (!p->count) {
-			list_del_rcu(&p->list);
-			prevp = &p->release_next;
+	while (f) {
+		if (!f->count) {
+			list_del_rcu(&f->list);
+			prevp = &f->release_next;
 		} else {
-			*prevp = p->release_next;
+			*prevp = f->release_next;
 		}
-		p = p->release_next;
+		f = f->release_next;
 	}
 	spin_unlock_irqrestore(&kmmio_lock, flags);
 
@@ -528,8 +534,8 @@
 }
 EXPORT_SYMBOL(unregister_kmmio_probe);
 
-static int kmmio_die_notifier(struct notifier_block *nb, unsigned long val,
-								void *args)
+static int
+kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args)
 {
 	struct die_args *arg = args;
 
@@ -544,11 +550,23 @@
 	.notifier_call = kmmio_die_notifier
 };
 
-static int __init init_kmmio(void)
+int kmmio_init(void)
 {
 	int i;
+
 	for (i = 0; i < KMMIO_PAGE_TABLE_SIZE; i++)
 		INIT_LIST_HEAD(&kmmio_page_table[i]);
+
 	return register_die_notifier(&nb_die);
 }
-fs_initcall(init_kmmio); /* should be before device_initcall() */
+
+void kmmio_cleanup(void)
+{
+	int i;
+
+	unregister_die_notifier(&nb_die);
+	for (i = 0; i < KMMIO_PAGE_TABLE_SIZE; i++) {
+		WARN_ONCE(!list_empty(&kmmio_page_table[i]),
+			KERN_ERR "kmmio_page_table not empty at cleanup, any further tracing will leak memory.\n");
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/Makefile linux-libre-2.6.31-gnu/arch/x86/mm/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/mm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,8 @@
 
 obj-$(CONFIG_HIGHMEM)		+= highmem_32.o
 
+obj-$(CONFIG_KMEMCHECK)		+= kmemcheck/
+
 obj-$(CONFIG_MMIOTRACE)		+= mmiotrace.o
 mmiotrace-y			:= kmmio.o pf_in.o mmio-mod.o
 obj-$(CONFIG_MMIOTRACE_TEST)	+= testmmiotrace.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/memtest.c linux-libre-2.6.31-gnu/arch/x86/mm/memtest.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/memtest.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/memtest.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,23 +40,22 @@
 
 static void __init memtest(u64 pattern, u64 start_phys, u64 size)
 {
-	u64 i, count;
-	u64 *start;
+	u64 *p, *start, *end;
 	u64 start_bad, last_bad;
 	u64 start_phys_aligned;
-	size_t incr;
+	const size_t incr = sizeof(pattern);
 
-	incr = sizeof(pattern);
 	start_phys_aligned = ALIGN(start_phys, incr);
-	count = (size - (start_phys_aligned - start_phys))/incr;
 	start = __va(start_phys_aligned);
+	end = start + (size - (start_phys_aligned - start_phys)) / incr;
 	start_bad = 0;
 	last_bad = 0;
 
-	for (i = 0; i < count; i++)
-		start[i] = pattern;
-	for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
-		if (*start == pattern)
+	for (p = start; p < end; p++)
+		*p = pattern;
+
+	for (p = start; p < end; p++, start_phys_aligned += incr) {
+		if (*p == pattern)
 			continue;
 		if (start_phys_aligned == last_bad + incr) {
 			last_bad += incr;
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/mmio-mod.c linux-libre-2.6.31-gnu/arch/x86/mm/mmio-mod.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/mmio-mod.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/mmio-mod.c	2009-09-09 18:13:59.000000000 -0400
@@ -451,6 +451,7 @@
 
 	if (nommiotrace)
 		pr_info(NAME "MMIO tracing disabled.\n");
+	kmmio_init();
 	enter_uniprocessor();
 	spin_lock_irq(&trace_lock);
 	atomic_inc(&mmiotrace_enabled);
@@ -473,6 +474,7 @@
 
 	clear_trace_list(); /* guarantees: no more kmmio callbacks */
 	leave_uniprocessor();
+	kmmio_cleanup();
 	pr_info(NAME "disabled.\n");
 out:
 	mutex_unlock(&mmiotrace_mutex);
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/numa_64.c linux-libre-2.6.31-gnu/arch/x86/mm/numa_64.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/numa_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/numa_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -179,18 +179,25 @@
 }
 
 /* Initialize bootmem allocator for a node */
-void __init setup_node_bootmem(int nodeid, unsigned long start,
-			       unsigned long end)
+void __init
+setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 {
 	unsigned long start_pfn, last_pfn, bootmap_pages, bootmap_size;
+	const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
 	unsigned long bootmap_start, nodedata_phys;
 	void *bootmap;
-	const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
 	int nid;
 
 	if (!end)
 		return;
 
+	/*
+	 * Don't confuse VM with a node that doesn't have the
+	 * minimum amount of memory:
+	 */
+	if (end && (end - start) < NODE_MIN_SIZE)
+		return;
+
 	start = roundup(start, ZONE_ALIGN);
 
 	printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid,
@@ -272,9 +279,6 @@
 		reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start,
 				 bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT);
 
-#ifdef CONFIG_ACPI_NUMA
-	srat_reserve_add_area(nodeid);
-#endif
 	node_set_online(nodeid);
 }
 
@@ -578,21 +582,6 @@
 	return pages;
 }
 
-void __init paging_init(void)
-{
-	unsigned long max_zone_pfns[MAX_NR_ZONES];
-
-	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
-	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
-	max_zone_pfns[ZONE_NORMAL] = max_pfn;
-
-	sparse_memory_present_with_active_regions(MAX_NUMNODES);
-	sparse_init();
-
-	free_area_init_nodes(max_zone_pfns);
-}
-
 static __init int numa_setup(char *opt)
 {
 	if (!opt)
@@ -606,8 +595,6 @@
 #ifdef CONFIG_ACPI_NUMA
 	if (!strncmp(opt, "noacpi", 6))
 		acpi_numa = -1;
-	if (!strncmp(opt, "hotadd=", 7))
-		hotadd_percent = simple_strtoul(opt+7, NULL, 10);
 #endif
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/pageattr.c linux-libre-2.6.31-gnu/arch/x86/mm/pageattr.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/pageattr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/pageattr.c	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
+#include <linux/pfn.h>
 
 #include <asm/e820.h>
 #include <asm/processor.h>
@@ -470,7 +471,7 @@
 
 	if (!debug_pagealloc)
 		spin_unlock(&cpa_lock);
-	base = alloc_pages(GFP_KERNEL, 0);
+	base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
 	if (!debug_pagealloc)
 		spin_lock(&cpa_lock);
 	if (!base)
@@ -590,9 +591,12 @@
 	unsigned int level;
 	pte_t *kpte, old_pte;
 
-	if (cpa->flags & CPA_PAGES_ARRAY)
-		address = (unsigned long)page_address(cpa->pages[cpa->curpage]);
-	else if (cpa->flags & CPA_ARRAY)
+	if (cpa->flags & CPA_PAGES_ARRAY) {
+		struct page *page = cpa->pages[cpa->curpage];
+		if (unlikely(PageHighMem(page)))
+			return 0;
+		address = (unsigned long)page_address(page);
+	} else if (cpa->flags & CPA_ARRAY)
 		address = cpa->vaddr[cpa->curpage];
 	else
 		address = *cpa->vaddr;
@@ -681,8 +685,9 @@
 static int cpa_process_alias(struct cpa_data *cpa)
 {
 	struct cpa_data alias_cpa;
-	int ret = 0;
-	unsigned long temp_cpa_vaddr, vaddr;
+	unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT);
+	unsigned long vaddr, remapped;
+	int ret;
 
 	if (cpa->pfn >= max_pfn_mapped)
 		return 0;
@@ -695,9 +700,12 @@
 	 * No need to redo, when the primary call touched the direct
 	 * mapping already:
 	 */
-	if (cpa->flags & CPA_PAGES_ARRAY)
-		vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]);
-	else if (cpa->flags & CPA_ARRAY)
+	if (cpa->flags & CPA_PAGES_ARRAY) {
+		struct page *page = cpa->pages[cpa->curpage];
+		if (unlikely(PageHighMem(page)))
+			return 0;
+		vaddr = (unsigned long)page_address(page);
+	} else if (cpa->flags & CPA_ARRAY)
 		vaddr = cpa->vaddr[cpa->curpage];
 	else
 		vaddr = *cpa->vaddr;
@@ -706,42 +714,55 @@
 		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) {
 
 		alias_cpa = *cpa;
-		temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
-		alias_cpa.vaddr = &temp_cpa_vaddr;
+		alias_cpa.vaddr = &laddr;
 		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 
-
 		ret = __change_page_attr_set_clr(&alias_cpa, 0);
+		if (ret)
+			return ret;
 	}
 
 #ifdef CONFIG_X86_64
-	if (ret)
-		return ret;
 	/*
-	 * No need to redo, when the primary call touched the high
-	 * mapping already:
-	 */
-	if (within(vaddr, (unsigned long) _text, _brk_end))
-		return 0;
-
-	/*
-	 * If the physical address is inside the kernel map, we need
+	 * If the primary call didn't touch the high mapping already
+	 * and the physical address is inside the kernel map, we need
 	 * to touch the high mapped kernel as well:
 	 */
-	if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn()))
-		return 0;
+	if (!within(vaddr, (unsigned long)_text, _brk_end) &&
+	    within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) {
+		unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
+					       __START_KERNEL_map - phys_base;
+		alias_cpa = *cpa;
+		alias_cpa.vaddr = &temp_cpa_vaddr;
+		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 
-	alias_cpa = *cpa;
-	temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base;
-	alias_cpa.vaddr = &temp_cpa_vaddr;
-	alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+		/*
+		 * The high mapping range is imprecise, so ignore the
+		 * return value.
+		 */
+		__change_page_attr_set_clr(&alias_cpa, 0);
+	}
+#endif
 
 	/*
-	 * The high mapping range is imprecise, so ignore the return value.
+	 * If the PMD page was partially used for per-cpu remapping,
+	 * the recycled area needs to be split and modified.  Because
+	 * the area is always proper subset of a PMD page
+	 * cpa->numpages is guaranteed to be 1 for these areas, so
+	 * there's no need to loop over and check for further remaps.
 	 */
-	__change_page_attr_set_clr(&alias_cpa, 0);
-#endif
-	return ret;
+	remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr);
+	if (remapped) {
+		WARN_ON(cpa->numpages > 1);
+		alias_cpa = *cpa;
+		alias_cpa.vaddr = &remapped;
+		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+		ret = __change_page_attr_set_clr(&alias_cpa, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
@@ -839,13 +860,6 @@
 
 	vm_unmap_aliases();
 
-	/*
-	 * If we're called with lazy mmu updates enabled, the
-	 * in-memory pte state may be stale.  Flush pending updates to
-	 * bring them up to date.
-	 */
-	arch_flush_lazy_mmu_mode();
-
 	cpa.vaddr = addr;
 	cpa.pages = pages;
 	cpa.numpages = numpages;
@@ -890,13 +904,6 @@
 	} else
 		cpa_flush_all(cache);
 
-	/*
-	 * If we've been called with lazy mmu updates enabled, then
-	 * make sure that everything gets flushed out before we
-	 * return.
-	 */
-	arch_flush_lazy_mmu_mode();
-
 out:
 	return ret;
 }
@@ -996,12 +1003,15 @@
 int _set_memory_wc(unsigned long addr, int numpages)
 {
 	int ret;
+	unsigned long addr_copy = addr;
+
 	ret = change_page_attr_set(&addr, numpages,
 				    __pgprot(_PAGE_CACHE_UC_MINUS), 0);
-
 	if (!ret) {
-		ret = change_page_attr_set(&addr, numpages,
-				    __pgprot(_PAGE_CACHE_WC), 0);
+		ret = change_page_attr_set_clr(&addr_copy, numpages,
+					       __pgprot(_PAGE_CACHE_WC),
+					       __pgprot(_PAGE_CACHE_MASK),
+					       0, 0, NULL);
 	}
 	return ret;
 }
@@ -1118,7 +1128,9 @@
 	int free_idx;
 
 	for (i = 0; i < addrinarray; i++) {
-		start = (unsigned long)page_address(pages[i]);
+		if (PageHighMem(pages[i]))
+			continue;
+		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
 		end = start + PAGE_SIZE;
 		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
 			goto err_out;
@@ -1131,7 +1143,9 @@
 err_out:
 	free_idx = i;
 	for (i = 0; i < free_idx; i++) {
-		start = (unsigned long)page_address(pages[i]);
+		if (PageHighMem(pages[i]))
+			continue;
+		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
 		end = start + PAGE_SIZE;
 		free_memtype(start, end);
 	}
@@ -1160,7 +1174,9 @@
 		return retval;
 
 	for (i = 0; i < addrinarray; i++) {
-		start = (unsigned long)page_address(pages[i]);
+		if (PageHighMem(pages[i]))
+			continue;
+		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
 		end = start + PAGE_SIZE;
 		free_memtype(start, end);
 	}
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/pat.c linux-libre-2.6.31-gnu/arch/x86/mm/pat.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/pat.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/pat.c	2009-09-09 18:13:59.000000000 -0400
@@ -623,7 +623,8 @@
 		return ret;
 
 	if (flags != want_flags) {
-		if (strict_prot || !is_new_memtype_allowed(want_flags, flags)) {
+		if (strict_prot ||
+		    !is_new_memtype_allowed(paddr, size, want_flags, flags)) {
 			free_memtype(paddr, paddr + size);
 			printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
 				" for %Lx-%Lx, got %s\n",
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/pgtable.c linux-libre-2.6.31-gnu/arch/x86/mm/pgtable.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/pgtable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/pgtable.c	2009-09-09 18:13:59.000000000 -0400
@@ -4,9 +4,11 @@
 #include <asm/tlb.h>
 #include <asm/fixmap.h>
 
+#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
+
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-	return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	return (pte_t *)__get_free_page(PGALLOC_GFP);
 }
 
 pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -14,16 +16,16 @@
 	struct page *pte;
 
 #ifdef CONFIG_HIGHPTE
-	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+	pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0);
 #else
-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+	pte = alloc_pages(PGALLOC_GFP, 0);
 #endif
 	if (pte)
 		pgtable_page_ctor(pte);
 	return pte;
 }
 
-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 {
 	pgtable_page_dtor(pte);
 	paravirt_release_pte(page_to_pfn(pte));
@@ -31,14 +33,14 @@
 }
 
 #if PAGETABLE_LEVELS > 2
-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
 	paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
 	tlb_remove_page(tlb, virt_to_page(pmd));
 }
 
 #if PAGETABLE_LEVELS > 3
-void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
 {
 	paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
 	tlb_remove_page(tlb, virt_to_page(pud));
@@ -161,7 +163,7 @@
 	bool failed = false;
 
 	for(i = 0; i < PREALLOCATED_PMDS; i++) {
-		pmd_t *pmd = (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+		pmd_t *pmd = (pmd_t *)__get_free_page(PGALLOC_GFP);
 		if (pmd == NULL)
 			failed = true;
 		pmds[i] = pmd;
@@ -228,7 +230,7 @@
 	pmd_t *pmds[PREALLOCATED_PMDS];
 	unsigned long flags;
 
-	pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+	pgd = (pgd_t *)__get_free_page(PGALLOC_GFP);
 
 	if (pgd == NULL)
 		goto out;
@@ -327,7 +329,6 @@
 	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
 	       (int)-reserve);
 	__FIXADDR_TOP = -reserve - PAGE_SIZE;
-	__VMALLOC_RESERVE += reserve;
 #endif
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/srat_64.c linux-libre-2.6.31-gnu/arch/x86/mm/srat_64.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/srat_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/srat_64.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,17 +31,11 @@
 static nodemask_t cpu_nodes_parsed __initdata;
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
 static struct bootnode nodes_add[MAX_NUMNODES];
-static int found_add_area __initdata;
-int hotadd_percent __initdata = 0;
 
 static int num_node_memblks __initdata;
 static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
 static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
 
-/* Too small nodes confuse the VM badly. Usually they result
-   from BIOS bugs. */
-#define NODE_MIN_SIZE (4*1024*1024)
-
 static __init int setup_node(int pxm)
 {
 	return acpi_map_pxm_to_node(pxm);
@@ -66,9 +60,6 @@
 {
 	struct bootnode *nd = &nodes[i];
 
-	if (found_add_area)
-		return;
-
 	if (nd->start < start) {
 		nd->start = start;
 		if (nd->end < nd->start)
@@ -86,11 +77,12 @@
 	int i;
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
 	acpi_numa = -1;
-	found_add_area = 0;
 	for (i = 0; i < MAX_LOCAL_APIC; i++)
 		apicid_to_node[i] = NUMA_NO_NODE;
-	for (i = 0; i < MAX_NUMNODES; i++)
-		nodes_add[i].start = nodes[i].end = 0;
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		nodes[i].start = nodes[i].end = 0;
+		nodes_add[i].start = nodes_add[i].end = 0;
+	}
 	remove_all_active_ranges();
 }
 
@@ -182,24 +174,21 @@
 	       pxm, apic_id, node);
 }
 
-static int update_end_of_memory(unsigned long end) {return -1;}
-static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static inline int save_add_info(void) {return 1;}
 #else
 static inline int save_add_info(void) {return 0;}
 #endif
 /*
- * Update nodes_add and decide if to include add are in the zone.
- * Both SPARSE and RESERVE need nodes_add information.
- * This code supports one contiguous hot add area per node.
+ * Update nodes_add[]
+ * This code supports one contiguous hot add area per node
  */
-static int __init
-reserve_hotadd(int node, unsigned long start, unsigned long end)
+static void __init
+update_nodes_add(int node, unsigned long start, unsigned long end)
 {
 	unsigned long s_pfn = start >> PAGE_SHIFT;
 	unsigned long e_pfn = end >> PAGE_SHIFT;
-	int ret = 0, changed = 0;
+	int changed = 0;
 	struct bootnode *nd = &nodes_add[node];
 
 	/* I had some trouble with strange memory hotadd regions breaking
@@ -210,7 +199,7 @@
 	   mistakes */
 	if ((signed long)(end - start) < NODE_MIN_SIZE) {
 		printk(KERN_ERR "SRAT: Hotplug area too small\n");
-		return -1;
+		return;
 	}
 
 	/* This check might be a bit too strict, but I'm keeping it for now. */
@@ -218,12 +207,7 @@
 		printk(KERN_ERR
 			"SRAT: Hotplug area %lu -> %lu has existing memory\n",
 			s_pfn, e_pfn);
-		return -1;
-	}
-
-	if (!hotadd_enough_memory(&nodes_add[node]))  {
-		printk(KERN_ERR "SRAT: Hotplug area too large\n");
-		return -1;
+		return;
 	}
 
 	/* Looks good */
@@ -245,11 +229,9 @@
 			printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
 	}
 
-	ret = update_end_of_memory(nd->end);
-
 	if (changed)
-	 	printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end);
-	return ret;
+		printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n",
+				 nd->start, nd->end);
 }
 
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
@@ -310,13 +292,10 @@
 	       start, end);
 	e820_register_active_regions(node, start >> PAGE_SHIFT,
 				     end >> PAGE_SHIFT);
-	push_node_boundaries(node, nd->start >> PAGE_SHIFT,
-						nd->end >> PAGE_SHIFT);
 
-	if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) &&
-	    (reserve_hotadd(node, start, end) < 0)) {
-		/* Ignore hotadd region. Undo damage */
-		printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
+	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) {
+		update_nodes_add(node, start, end);
+		/* restore nodes[node] */
 		*nd = oldnode;
 		if ((nd->start | nd->end) == 0)
 			node_clear(node, nodes_parsed);
@@ -345,9 +324,9 @@
 			pxmram = 0;
 	}
 
-	e820ram = max_pfn - absent_pages_in_range(0, max_pfn);
-	/* We seem to lose 3 pages somewhere. Allow a bit of slack. */
-	if ((long)(e820ram - pxmram) >= 1*1024*1024) {
+	e820ram = max_pfn - (e820_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
+	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
+	if ((long)(e820ram - pxmram) >= (1<<(20 - PAGE_SHIFT))) {
 		printk(KERN_ERR
 	"SRAT: PXMs only cover %luMB of your %luMB e820 RAM. Not used.\n",
 			(pxmram << PAGE_SHIFT) >> 20,
@@ -357,17 +336,6 @@
 	return 1;
 }
 
-static void __init unparse_node(int node)
-{
-	int i;
-	node_clear(node, nodes_parsed);
-	node_clear(node, cpu_nodes_parsed);
-	for (i = 0; i < MAX_LOCAL_APIC; i++) {
-		if (apicid_to_node[i] == node)
-			apicid_to_node[i] = NUMA_NO_NODE;
-	}
-}
-
 void __init acpi_numa_arch_fixup(void) {}
 
 /* Use the information discovered above to actually set up the nodes. */
@@ -379,18 +347,8 @@
 		return -1;
 
 	/* First clean up the node list */
-	for (i = 0; i < MAX_NUMNODES; i++) {
+	for (i = 0; i < MAX_NUMNODES; i++)
 		cutoff_node(i, start, end);
-		/*
-		 * don't confuse VM with a node that doesn't have the
-		 * minimum memory.
-		 */
-		if (nodes[i].end &&
-			(nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) {
-			unparse_node(i);
-			node_set_offline(i);
-		}
-	}
 
 	if (!nodes_cover_memory(nodes)) {
 		bad_srat();
@@ -423,7 +381,7 @@
 
 		if (node == NUMA_NO_NODE)
 			continue;
-		if (!node_isset(node, node_possible_map))
+		if (!node_online(node))
 			numa_clear_node(i);
 	}
 	numa_init_array();
@@ -510,26 +468,6 @@
 }
 #endif /* CONFIG_NUMA_EMU */
 
-void __init srat_reserve_add_area(int nodeid)
-{
-	if (found_add_area && nodes_add[nodeid].end) {
-		u64 total_mb;
-
-		printk(KERN_INFO "SRAT: Reserving hot-add memory space "
-				"for node %d at %Lx-%Lx\n",
-			nodeid, nodes_add[nodeid].start, nodes_add[nodeid].end);
-		total_mb = (nodes_add[nodeid].end - nodes_add[nodeid].start)
-					>> PAGE_SHIFT;
-		total_mb *= sizeof(struct page);
-		total_mb >>= 20;
-		printk(KERN_INFO "SRAT: This will cost you %Lu MB of "
-				"pre-allocated memory.\n", (unsigned long long)total_mb);
-		reserve_bootmem_node(NODE_DATA(nodeid), nodes_add[nodeid].start,
-			       nodes_add[nodeid].end - nodes_add[nodeid].start,
-			       BOOTMEM_DEFAULT);
-	}
-}
-
 int __node_distance(int a, int b)
 {
 	int index;
diff -druN linux-libre-2.6.30-gnu/arch/x86/mm/tlb.c linux-libre-2.6.31-gnu/arch/x86/mm/tlb.c
--- linux-libre-2.6.30-gnu/arch/x86/mm/tlb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/mm/tlb.c	2009-09-09 18:13:59.000000000 -0400
@@ -183,18 +183,17 @@
 
 	f->flush_mm = mm;
 	f->flush_va = va;
-	cpumask_andnot(to_cpumask(f->flush_cpumask),
-		       cpumask, cpumask_of(smp_processor_id()));
-
-	/*
-	 * We have to send the IPI only to
-	 * CPUs affected.
-	 */
-	apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
-		      INVALIDATE_TLB_VECTOR_START + sender);
+	if (cpumask_andnot(to_cpumask(f->flush_cpumask), cpumask, cpumask_of(smp_processor_id()))) {
+		/*
+		 * We have to send the IPI only to
+		 * CPUs affected.
+		 */
+		apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
+			      INVALIDATE_TLB_VECTOR_START + sender);
 
-	while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
-		cpu_relax();
+		while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
+			cpu_relax();
+	}
 
 	f->flush_mm = NULL;
 	f->flush_va = 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/oprofile/nmi_int.c linux-libre-2.6.31-gnu/arch/x86/oprofile/nmi_int.c
--- linux-libre-2.6.30-gnu/arch/x86/oprofile/nmi_int.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/oprofile/nmi_int.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,8 +40,9 @@
 
 	switch (val) {
 	case DIE_NMI:
-		if (model->check_ctrs(args->regs, &per_cpu(cpu_msrs, cpu)))
-			ret = NOTIFY_STOP;
+	case DIE_NMI_IPI:
+		model->check_ctrs(args->regs, &per_cpu(cpu_msrs, cpu));
+		ret = NOTIFY_STOP;
 		break;
 	default:
 		break;
@@ -134,7 +135,7 @@
 static struct notifier_block profile_exceptions_nb = {
 	.notifier_call = profile_exceptions_notify,
 	.next = NULL,
-	.priority = 0
+	.priority = 2
 };
 
 static int nmi_setup(void)
@@ -356,14 +357,11 @@
 #define exit_sysfs() do { } while (0)
 #endif /* CONFIG_PM */
 
-static int p4force;
-module_param(p4force, int, 0);
-
 static int __init p4_init(char **cpu_type)
 {
 	__u8 cpu_model = boot_cpu_data.x86_model;
 
-	if (!p4force && (cpu_model > 6 || cpu_model == 5))
+	if (cpu_model > 6 || cpu_model == 5)
 		return 0;
 
 #ifndef CONFIG_SMP
@@ -389,10 +387,25 @@
 	return 0;
 }
 
+static int force_arch_perfmon;
+static int force_cpu_type(const char *str, struct kernel_param *kp)
+{
+	if (!strcmp(str, "arch_perfmon")) {
+		force_arch_perfmon = 1;
+		printk(KERN_INFO "oprofile: forcing architectural perfmon\n");
+	}
+
+	return 0;
+}
+module_param_call(cpu_type, force_cpu_type, NULL, NULL, 0);
+
 static int __init ppro_init(char **cpu_type)
 {
 	__u8 cpu_model = boot_cpu_data.x86_model;
 
+	if (force_arch_perfmon && cpu_has_arch_perfmon)
+		return 0;
+
 	switch (cpu_model) {
 	case 0 ... 2:
 		*cpu_type = "i386/ppro";
@@ -414,6 +427,13 @@
 	case 15: case 23:
 		*cpu_type = "i386/core_2";
 		break;
+	case 26:
+		arch_perfmon_setup_counters();
+		*cpu_type = "i386/core_i7";
+		break;
+	case 28:
+		*cpu_type = "i386/atom";
+		break;
 	default:
 		/* Unknown */
 		return 0;
diff -druN linux-libre-2.6.30-gnu/arch/x86/oprofile/op_model_ppro.c linux-libre-2.6.31-gnu/arch/x86/oprofile/op_model_ppro.c
--- linux-libre-2.6.30-gnu/arch/x86/oprofile/op_model_ppro.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/oprofile/op_model_ppro.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,7 @@
 #include <asm/msr.h>
 #include <asm/apic.h>
 #include <asm/nmi.h>
-#include <asm/intel_arch_perfmon.h>
+#include <asm/perf_counter.h>
 
 #include "op_x86_model.h"
 #include "op_counter.h"
@@ -136,6 +136,13 @@
 	u64 val;
 	int i;
 
+	/*
+	 * This can happen if perf counters are in use when
+	 * we steal the die notifier NMI.
+	 */
+	if (unlikely(!reset_value))
+		goto out;
+
 	for (i = 0 ; i < num_counters; ++i) {
 		if (!reset_value[i])
 			continue;
@@ -146,6 +153,7 @@
 		}
 	}
 
+out:
 	/* Only P6 based Pentium M need to re-unmask the apic vector but it
 	 * doesn't hurt other P6 variant */
 	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
diff -druN linux-libre-2.6.30-gnu/arch/x86/pci/acpi.c linux-libre-2.6.31-gnu/arch/x86/pci/acpi.c
--- linux-libre-2.6.30-gnu/arch/x86/pci/acpi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/pci/acpi.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,15 +38,26 @@
 	struct acpi_resource_address64 addr;
 	acpi_status status;
 
-	if (info->res_num >= PCI_BUS_NUM_RESOURCES)
-		return AE_OK;
-
 	status = resource_to_addr(acpi_res, &addr);
 	if (ACPI_SUCCESS(status))
 		info->res_num++;
 	return AE_OK;
 }
 
+static int
+bus_has_transparent_bridge(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 class = dev->class >> 8;
+
+		if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
+			return true;
+	}
+	return false;
+}
+
 static acpi_status
 setup_resource(struct acpi_resource *acpi_res, void *data)
 {
@@ -56,9 +67,11 @@
 	acpi_status status;
 	unsigned long flags;
 	struct resource *root;
+	int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
+	u64 start, end;
 
-	if (info->res_num >= PCI_BUS_NUM_RESOURCES)
-		return AE_OK;
+	if (bus_has_transparent_bridge(info->bus))
+		max_root_bus_resources -= 3;
 
 	status = resource_to_addr(acpi_res, &addr);
 	if (!ACPI_SUCCESS(status))
@@ -75,11 +88,22 @@
 	} else
 		return AE_OK;
 
+	start = addr.minimum + addr.translation_offset;
+	end = start + addr.address_length - 1;
+	if (info->res_num >= max_root_bus_resources) {
+		printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
+			"from %s for %s due to _CRS returning more than "
+			"%d resource descriptors\n", (unsigned long) start,
+			(unsigned long) end, root->name, info->name,
+			max_root_bus_resources);
+		return AE_OK;
+	}
+
 	res = &info->res[info->res_num];
 	res->name = info->name;
 	res->flags = flags;
-	res->start = addr.minimum + addr.translation_offset;
-	res->end = res->start + addr.address_length - 1;
+	res->start = start;
+	res->end = end;
 	res->child = NULL;
 
 	if (insert_resource(root, res)) {
@@ -94,23 +118,6 @@
 }
 
 static void
-adjust_transparent_bridge_resources(struct pci_bus *bus)
-{
-	struct pci_dev *dev;
-
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		int i;
-		u16 class = dev->class >> 8;
-
-		if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) {
-			for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
-				dev->subordinate->resource[i] =
-						dev->bus->resource[i - 3];
-		}
-	}
-}
-
-static void
 get_current_resources(struct acpi_device *device, int busnum,
 			int domain, struct pci_bus *bus)
 {
@@ -137,8 +144,6 @@
 	info.res_num = 0;
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 				&info);
-	if (info.res_num)
-		adjust_transparent_bridge_resources(bus);
 
 	return;
 
@@ -201,8 +206,15 @@
 		 */
 		memcpy(bus->sysdata, sd, sizeof(*sd));
 		kfree(sd);
-	} else
-		bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
+	} else {
+		bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd);
+		if (bus) {
+			if (pci_probe & PCI_USE__CRS)
+				get_current_resources(device, busnum, domain,
+							bus);
+			bus->subordinate = pci_scan_child_bus(bus);
+		}
+	}
 
 	if (!bus)
 		kfree(sd);
@@ -217,8 +229,6 @@
 #endif
 	}
 
-	if (bus && (pci_probe & PCI_USE__CRS))
-		get_current_resources(device, busnum, domain, bus);
 	return bus;
 }
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/pci/amd_bus.c linux-libre-2.6.31-gnu/arch/x86/pci/amd_bus.c
--- linux-libre-2.6.30-gnu/arch/x86/pci/amd_bus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/pci/amd_bus.c	2009-09-09 18:13:59.000000000 -0400
@@ -100,8 +100,9 @@
 	int j;
 	struct pci_root_info *info;
 
-	/* don't go for it if _CRS is used */
-	if (pci_probe & PCI_USE__CRS)
+	/* don't go for it if _CRS is used already */
+	if (b->resource[0] != &ioport_resource ||
+	    b->resource[1] != &iomem_resource)
 		return;
 
 	/* if only one root bus, don't need to anything */
@@ -116,6 +117,9 @@
 	if (i == pci_root_num)
 		return;
 
+	printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
+			b->number);
+
 	info = &pci_root_info[i];
 	for (j = 0; j < info->res_num; j++) {
 		struct resource *res;
diff -druN linux-libre-2.6.30-gnu/arch/x86/pci/i386.c linux-libre-2.6.31-gnu/arch/x86/pci/i386.c
--- linux-libre-2.6.30-gnu/arch/x86/pci/i386.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/pci/i386.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,6 +35,7 @@
 #include <asm/pat.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
+#include <asm/io_apic.h>
 
 
 static int
@@ -116,7 +117,7 @@
 	struct pci_bus *bus;
 	struct pci_dev *dev;
 	int idx;
-	struct resource *r, *pr;
+	struct resource *r;
 
 	/* Depth-First Search on bus tree */
 	list_for_each_entry(bus, bus_list, node) {
@@ -126,9 +127,8 @@
 				r = &dev->resource[idx];
 				if (!r->flags)
 					continue;
-				pr = pci_find_parent_resource(dev, r);
-				if (!r->start || !pr ||
-				    request_resource(pr, r) < 0) {
+				if (!r->start ||
+				    pci_claim_resource(dev, idx) < 0) {
 					dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx);
 					/*
 					 * Something is wrong with the region.
@@ -149,7 +149,7 @@
 	struct pci_dev *dev = NULL;
 	int idx, disabled;
 	u16 command;
-	struct resource *r, *pr;
+	struct resource *r;
 
 	for_each_pci_dev(dev) {
 		pci_read_config_word(dev, PCI_COMMAND, &command);
@@ -168,8 +168,7 @@
 					(unsigned long long) r->start,
 					(unsigned long long) r->end,
 					r->flags, disabled, pass);
-				pr = pci_find_parent_resource(dev, r);
-				if (!pr || request_resource(pr, r) < 0) {
+				if (pci_claim_resource(dev, idx) < 0) {
 					dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx);
 					/* We'll assign a new address later */
 					r->end -= r->start;
@@ -197,7 +196,7 @@
 static int __init pcibios_assign_resources(void)
 {
 	struct pci_dev *dev = NULL;
-	struct resource *r, *pr;
+	struct resource *r;
 
 	if (!(pci_probe & PCI_ASSIGN_ROMS)) {
 		/*
@@ -209,8 +208,7 @@
 			r = &dev->resource[PCI_ROM_RESOURCE];
 			if (!r->flags || !r->start)
 				continue;
-			pr = pci_find_parent_resource(dev, r);
-			if (!pr || request_resource(pr, r) < 0) {
+			if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
 				r->end -= r->start;
 				r->start = 0;
 			}
@@ -230,6 +228,12 @@
 	pcibios_allocate_resources(1);
 
 	e820_reserve_resources_late();
+	/*
+	 * Insert the IO APIC resources after PCI initialization has
+	 * occured to handle IO APICS that are mapped in on a BAR in
+	 * PCI space, but before trying to assign unassigned pci res.
+	 */
+	ioapic_insert_resources();
 }
 
 /**
diff -druN linux-libre-2.6.30-gnu/arch/x86/pci/irq.c linux-libre-2.6.31-gnu/arch/x86/pci/irq.c
--- linux-libre-2.6.30-gnu/arch/x86/pci/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/pci/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -889,6 +889,9 @@
 		return 0;
 	}
 
+	if (io_apic_assign_pci_irqs)
+		return 0;
+
 	/* Find IRQ routing entry */
 
 	if (!pirq_table)
@@ -1039,56 +1042,15 @@
 		pirq_penalty[dev->irq]++;
 	}
 
+	if (io_apic_assign_pci_irqs)
+		return;
+
 	dev = NULL;
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 		if (!pin)
 			continue;
 
-#ifdef CONFIG_X86_IO_APIC
-		/*
-		 * Recalculate IRQ numbers if we use the I/O APIC.
-		 */
-		if (io_apic_assign_pci_irqs) {
-			int irq;
-
-			/*
-			 * interrupt pins are numbered starting from 1
-			 */
-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
-				PCI_SLOT(dev->devfn), pin - 1);
-			/*
-			 * Busses behind bridges are typically not listed in the
-			 * MP-table.  In this case we have to look up the IRQ
-			 * based on the parent bus, parent slot, and pin number.
-			 * The SMP code detects such bridged busses itself so we
-			 * should get into this branch reliably.
-			 */
-			if (irq < 0 && dev->bus->parent) {
-				/* go back to the bridge */
-				struct pci_dev *bridge = dev->bus->self;
-				int bus;
-
-				pin = pci_swizzle_interrupt_pin(dev, pin);
-				bus = bridge->bus->number;
-				irq = IO_APIC_get_PCI_irq_vector(bus,
-						PCI_SLOT(bridge->devfn), pin - 1);
-				if (irq >= 0)
-					dev_warn(&dev->dev,
-						"using bridge %s INT %c to "
-							"get IRQ %d\n",
-						 pci_name(bridge),
-						 'A' + pin - 1, irq);
-			}
-			if (irq >= 0) {
-				dev_info(&dev->dev,
-					"PCI->APIC IRQ transform: INT %c "
-						"-> IRQ %d\n",
-					'A' + pin - 1, irq);
-				dev->irq = irq;
-			}
-		}
-#endif
 		/*
 		 * Still no IRQ? Try to lookup one...
 		 */
@@ -1183,6 +1145,19 @@
 	pcibios_enable_irq = pirq_enable_irq;
 
 	pcibios_fixup_irqs();
+
+	if (io_apic_assign_pci_irqs && pci_routeirq) {
+		struct pci_dev *dev = NULL;
+		/*
+		 * PCI IRQ routing is set up by pci_enable_device(), but we
+		 * also do it here in case there are still broken drivers that
+		 * don't use pci_enable_device().
+		 */
+		printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+		for_each_pci_dev(dev)
+			pirq_enable_irq(dev);
+	}
+
 	return 0;
 }
 
@@ -1213,16 +1188,23 @@
 static int pirq_enable_irq(struct pci_dev *dev)
 {
 	u8 pin;
-	struct pci_dev *temp_dev;
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+	if (pin && !pcibios_lookup_irq(dev, 1)) {
 		char *msg = "";
 
+		if (!io_apic_assign_pci_irqs && dev->irq)
+			return 0;
+
 		if (io_apic_assign_pci_irqs) {
+#ifdef CONFIG_X86_IO_APIC
+			struct pci_dev *temp_dev;
 			int irq;
+			struct io_apic_irq_attr irq_attr;
 
-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
+			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+						PCI_SLOT(dev->devfn),
+						pin - 1, &irq_attr);
 			/*
 			 * Busses behind bridges are typically not listed in the MP-table.
 			 * In this case we have to look up the IRQ based on the parent bus,
@@ -1235,7 +1217,8 @@
 
 				pin = pci_swizzle_interrupt_pin(dev, pin);
 				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
-						PCI_SLOT(bridge->devfn), pin - 1);
+						PCI_SLOT(bridge->devfn),
+						pin - 1, &irq_attr);
 				if (irq >= 0)
 					dev_warn(&dev->dev, "using bridge %s "
 						 "INT %c to get IRQ %d\n",
@@ -1245,12 +1228,15 @@
 			}
 			dev = temp_dev;
 			if (irq >= 0) {
+				io_apic_set_pci_routing(&dev->dev, irq,
+							 &irq_attr);
+				dev->irq = irq;
 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
-				dev->irq = irq;
 				return 0;
 			} else
 				msg = "; probably buggy MP table";
+#endif
 		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
 			msg = "";
 		else
diff -druN linux-libre-2.6.30-gnu/arch/x86/pci/mmconfig-shared.c linux-libre-2.6.31-gnu/arch/x86/pci/mmconfig-shared.c
--- linux-libre-2.6.30-gnu/arch/x86/pci/mmconfig-shared.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/pci/mmconfig-shared.c	2009-09-09 18:13:59.000000000 -0400
@@ -523,6 +523,69 @@
 
 static int __initdata known_bridge;
 
+static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
+
+/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
+struct acpi_mcfg_allocation *pci_mmcfg_config;
+int pci_mmcfg_config_num;
+
+static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
+{
+	if (!strcmp(mcfg->header.oem_id, "SGI"))
+		acpi_mcfg_64bit_base_addr = TRUE;
+
+	return 0;
+}
+
+static int __init pci_parse_mcfg(struct acpi_table_header *header)
+{
+	struct acpi_table_mcfg *mcfg;
+	unsigned long i;
+	int config_size;
+
+	if (!header)
+		return -EINVAL;
+
+	mcfg = (struct acpi_table_mcfg *)header;
+
+	/* how many config structures do we have */
+	pci_mmcfg_config_num = 0;
+	i = header->length - sizeof(struct acpi_table_mcfg);
+	while (i >= sizeof(struct acpi_mcfg_allocation)) {
+		++pci_mmcfg_config_num;
+		i -= sizeof(struct acpi_mcfg_allocation);
+	};
+	if (pci_mmcfg_config_num == 0) {
+		printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
+		return -ENODEV;
+	}
+
+	config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
+	pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);
+	if (!pci_mmcfg_config) {
+		printk(KERN_WARNING PREFIX
+		       "No memory for MCFG config tables\n");
+		return -ENOMEM;
+	}
+
+	memcpy(pci_mmcfg_config, &mcfg[1], config_size);
+
+	acpi_mcfg_oem_check(mcfg);
+
+	for (i = 0; i < pci_mmcfg_config_num; ++i) {
+		if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
+		    !acpi_mcfg_64bit_base_addr) {
+			printk(KERN_ERR PREFIX
+			       "MMCONFIG not in low 4GB of memory\n");
+			kfree(pci_mmcfg_config);
+			pci_mmcfg_config_num = 0;
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
 static void __init __pci_mmcfg_init(int early)
 {
 	/* MMCONFIG disabled */
@@ -543,7 +606,7 @@
 	}
 
 	if (!known_bridge)
-		acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
+		acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
 
 	pci_mmcfg_reject_broken(early);
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/power/cpu_32.c linux-libre-2.6.31-gnu/arch/x86/power/cpu_32.c
--- linux-libre-2.6.30-gnu/arch/x86/power/cpu_32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/power/cpu_32.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,148 +0,0 @@
-/*
- * Suspend support specific for i386.
- *
- * Distribute under GPLv2
- *
- * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
- * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
- */
-
-#include <linux/module.h>
-#include <linux/suspend.h>
-#include <asm/mtrr.h>
-#include <asm/mce.h>
-#include <asm/xcr.h>
-#include <asm/suspend.h>
-
-static struct saved_context saved_context;
-
-unsigned long saved_context_ebx;
-unsigned long saved_context_esp, saved_context_ebp;
-unsigned long saved_context_esi, saved_context_edi;
-unsigned long saved_context_eflags;
-
-static void __save_processor_state(struct saved_context *ctxt)
-{
-	mtrr_save_fixed_ranges(NULL);
-	kernel_fpu_begin();
-
-	/*
-	 * descriptor tables
-	 */
-	store_gdt(&ctxt->gdt);
-	store_idt(&ctxt->idt);
-	store_tr(ctxt->tr);
-
-	/*
-	 * segment registers
-	 */
-	savesegment(es, ctxt->es);
-	savesegment(fs, ctxt->fs);
-	savesegment(gs, ctxt->gs);
-	savesegment(ss, ctxt->ss);
-
-	/*
-	 * control registers
-	 */
-	ctxt->cr0 = read_cr0();
-	ctxt->cr2 = read_cr2();
-	ctxt->cr3 = read_cr3();
-	ctxt->cr4 = read_cr4_safe();
-}
-
-/* Needed by apm.c */
-void save_processor_state(void)
-{
-	__save_processor_state(&saved_context);
-}
-EXPORT_SYMBOL(save_processor_state);
-
-static void do_fpu_end(void)
-{
-	/*
-	 * Restore FPU regs if necessary.
-	 */
-	kernel_fpu_end();
-}
-
-static void fix_processor_context(void)
-{
-	int cpu = smp_processor_id();
-	struct tss_struct *t = &per_cpu(init_tss, cpu);
-
-	set_tss_desc(cpu, t);	/*
-				 * This just modifies memory; should not be
-				 * necessary. But... This is necessary, because
-				 * 386 hardware has concept of busy TSS or some
-				 * similar stupidity.
-				 */
-
-	load_TR_desc();				/* This does ltr */
-	load_LDT(&current->active_mm->context);	/* This does lldt */
-
-	/*
-	 * Now maybe reload the debug registers
-	 */
-	if (current->thread.debugreg7) {
-		set_debugreg(current->thread.debugreg0, 0);
-		set_debugreg(current->thread.debugreg1, 1);
-		set_debugreg(current->thread.debugreg2, 2);
-		set_debugreg(current->thread.debugreg3, 3);
-		/* no 4 and 5 */
-		set_debugreg(current->thread.debugreg6, 6);
-		set_debugreg(current->thread.debugreg7, 7);
-	}
-
-}
-
-static void __restore_processor_state(struct saved_context *ctxt)
-{
-	/*
-	 * control registers
-	 */
-	/* cr4 was introduced in the Pentium CPU */
-	if (ctxt->cr4)
-		write_cr4(ctxt->cr4);
-	write_cr3(ctxt->cr3);
-	write_cr2(ctxt->cr2);
-	write_cr0(ctxt->cr0);
-
-	/*
-	 * now restore the descriptor tables to their proper values
-	 * ltr is done i fix_processor_context().
-	 */
-	load_gdt(&ctxt->gdt);
-	load_idt(&ctxt->idt);
-
-	/*
-	 * segment registers
-	 */
-	loadsegment(es, ctxt->es);
-	loadsegment(fs, ctxt->fs);
-	loadsegment(gs, ctxt->gs);
-	loadsegment(ss, ctxt->ss);
-
-	/*
-	 * sysenter MSRs
-	 */
-	if (boot_cpu_has(X86_FEATURE_SEP))
-		enable_sep_cpu();
-
-	/*
-	 * restore XCR0 for xsave capable cpu's.
-	 */
-	if (cpu_has_xsave)
-		xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask);
-
-	fix_processor_context();
-	do_fpu_end();
-	mtrr_ap_init();
-	mcheck_init(&boot_cpu_data);
-}
-
-/* Needed by apm.c */
-void restore_processor_state(void)
-{
-	__restore_processor_state(&saved_context);
-}
-EXPORT_SYMBOL(restore_processor_state);
diff -druN linux-libre-2.6.30-gnu/arch/x86/power/cpu_64.c linux-libre-2.6.31-gnu/arch/x86/power/cpu_64.c
--- linux-libre-2.6.30-gnu/arch/x86/power/cpu_64.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/power/cpu_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,174 +0,0 @@
-/*
- * Suspend and hibernation support for x86-64
- *
- * Distribute under GPLv2
- *
- * Copyright (c) 2007 Rafael J. Wysocki <rjw@sisk.pl>
- * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
- * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
- */
-
-#include <linux/smp.h>
-#include <linux/suspend.h>
-#include <asm/proto.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/mtrr.h>
-#include <asm/xcr.h>
-#include <asm/suspend.h>
-
-static void fix_processor_context(void);
-
-struct saved_context saved_context;
-
-/**
- *	__save_processor_state - save CPU registers before creating a
- *		hibernation image and before restoring the memory state from it
- *	@ctxt - structure to store the registers contents in
- *
- *	NOTE: If there is a CPU register the modification of which by the
- *	boot kernel (ie. the kernel used for loading the hibernation image)
- *	might affect the operations of the restored target kernel (ie. the one
- *	saved in the hibernation image), then its contents must be saved by this
- *	function.  In other words, if kernel A is hibernated and different
- *	kernel B is used for loading the hibernation image into memory, the
- *	kernel A's __save_processor_state() function must save all registers
- *	needed by kernel A, so that it can operate correctly after the resume
- *	regardless of what kernel B does in the meantime.
- */
-static void __save_processor_state(struct saved_context *ctxt)
-{
-	kernel_fpu_begin();
-
-	/*
-	 * descriptor tables
-	 */
-	store_gdt((struct desc_ptr *)&ctxt->gdt_limit);
-	store_idt((struct desc_ptr *)&ctxt->idt_limit);
-	store_tr(ctxt->tr);
-
-	/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
-	/*
-	 * segment registers
-	 */
-	asm volatile ("movw %%ds, %0" : "=m" (ctxt->ds));
-	asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
-	asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs));
-	asm volatile ("movw %%gs, %0" : "=m" (ctxt->gs));
-	asm volatile ("movw %%ss, %0" : "=m" (ctxt->ss));
-
-	rdmsrl(MSR_FS_BASE, ctxt->fs_base);
-	rdmsrl(MSR_GS_BASE, ctxt->gs_base);
-	rdmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
-	mtrr_save_fixed_ranges(NULL);
-
-	/*
-	 * control registers
-	 */
-	rdmsrl(MSR_EFER, ctxt->efer);
-	ctxt->cr0 = read_cr0();
-	ctxt->cr2 = read_cr2();
-	ctxt->cr3 = read_cr3();
-	ctxt->cr4 = read_cr4();
-	ctxt->cr8 = read_cr8();
-}
-
-void save_processor_state(void)
-{
-	__save_processor_state(&saved_context);
-}
-
-static void do_fpu_end(void)
-{
-	/*
-	 * Restore FPU regs if necessary
-	 */
-	kernel_fpu_end();
-}
-
-/**
- *	__restore_processor_state - restore the contents of CPU registers saved
- *		by __save_processor_state()
- *	@ctxt - structure to load the registers contents from
- */
-static void __restore_processor_state(struct saved_context *ctxt)
-{
-	/*
-	 * control registers
-	 */
-	wrmsrl(MSR_EFER, ctxt->efer);
-	write_cr8(ctxt->cr8);
-	write_cr4(ctxt->cr4);
-	write_cr3(ctxt->cr3);
-	write_cr2(ctxt->cr2);
-	write_cr0(ctxt->cr0);
-
-	/*
-	 * now restore the descriptor tables to their proper values
-	 * ltr is done i fix_processor_context().
-	 */
-	load_gdt((const struct desc_ptr *)&ctxt->gdt_limit);
-	load_idt((const struct desc_ptr *)&ctxt->idt_limit);
-
-
-	/*
-	 * segment registers
-	 */
-	asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds));
-	asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
-	asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs));
-	load_gs_index(ctxt->gs);
-	asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
-
-	wrmsrl(MSR_FS_BASE, ctxt->fs_base);
-	wrmsrl(MSR_GS_BASE, ctxt->gs_base);
-	wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
-
-	/*
-	 * restore XCR0 for xsave capable cpu's.
-	 */
-	if (cpu_has_xsave)
-		xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask);
-
-	fix_processor_context();
-
-	do_fpu_end();
-	mtrr_ap_init();
-}
-
-void restore_processor_state(void)
-{
-	__restore_processor_state(&saved_context);
-}
-
-static void fix_processor_context(void)
-{
-	int cpu = smp_processor_id();
-	struct tss_struct *t = &per_cpu(init_tss, cpu);
-
-	/*
-	 * This just modifies memory; should not be necessary. But... This
-	 * is necessary, because 386 hardware has concept of busy TSS or some
-	 * similar stupidity.
-	 */
-	set_tss_desc(cpu, t);
-
-	get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
-
-	syscall_init();                         /* This sets MSR_*STAR and related */
-	load_TR_desc();				/* This does ltr */
-	load_LDT(&current->active_mm->context);	/* This does lldt */
-
-	/*
-	 * Now maybe reload the debug registers
-	 */
-	if (current->thread.debugreg7){
-                loaddebug(&current->thread, 0);
-                loaddebug(&current->thread, 1);
-                loaddebug(&current->thread, 2);
-                loaddebug(&current->thread, 3);
-                /* no 4 and 5 */
-                loaddebug(&current->thread, 6);
-                loaddebug(&current->thread, 7);
-	}
-}
diff -druN linux-libre-2.6.30-gnu/arch/x86/power/cpu.c linux-libre-2.6.31-gnu/arch/x86/power/cpu.c
--- linux-libre-2.6.30-gnu/arch/x86/power/cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/x86/power/cpu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,259 @@
+/*
+ * Suspend support specific for i386/x86-64.
+ *
+ * Distribute under GPLv2
+ *
+ * Copyright (c) 2007 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ */
+
+#include <linux/suspend.h>
+#include <linux/smp.h>
+
+#include <asm/pgtable.h>
+#include <asm/proto.h>
+#include <asm/mtrr.h>
+#include <asm/page.h>
+#include <asm/mce.h>
+#include <asm/xcr.h>
+#include <asm/suspend.h>
+
+#ifdef CONFIG_X86_32
+static struct saved_context saved_context;
+
+unsigned long saved_context_ebx;
+unsigned long saved_context_esp, saved_context_ebp;
+unsigned long saved_context_esi, saved_context_edi;
+unsigned long saved_context_eflags;
+#else
+/* CONFIG_X86_64 */
+struct saved_context saved_context;
+#endif
+
+/**
+ *	__save_processor_state - save CPU registers before creating a
+ *		hibernation image and before restoring the memory state from it
+ *	@ctxt - structure to store the registers contents in
+ *
+ *	NOTE: If there is a CPU register the modification of which by the
+ *	boot kernel (ie. the kernel used for loading the hibernation image)
+ *	might affect the operations of the restored target kernel (ie. the one
+ *	saved in the hibernation image), then its contents must be saved by this
+ *	function.  In other words, if kernel A is hibernated and different
+ *	kernel B is used for loading the hibernation image into memory, the
+ *	kernel A's __save_processor_state() function must save all registers
+ *	needed by kernel A, so that it can operate correctly after the resume
+ *	regardless of what kernel B does in the meantime.
+ */
+static void __save_processor_state(struct saved_context *ctxt)
+{
+#ifdef CONFIG_X86_32
+	mtrr_save_fixed_ranges(NULL);
+#endif
+	kernel_fpu_begin();
+
+	/*
+	 * descriptor tables
+	 */
+#ifdef CONFIG_X86_32
+	store_gdt(&ctxt->gdt);
+	store_idt(&ctxt->idt);
+#else
+/* CONFIG_X86_64 */
+	store_gdt((struct desc_ptr *)&ctxt->gdt_limit);
+	store_idt((struct desc_ptr *)&ctxt->idt_limit);
+#endif
+	store_tr(ctxt->tr);
+
+	/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
+	/*
+	 * segment registers
+	 */
+#ifdef CONFIG_X86_32
+	savesegment(es, ctxt->es);
+	savesegment(fs, ctxt->fs);
+	savesegment(gs, ctxt->gs);
+	savesegment(ss, ctxt->ss);
+#else
+/* CONFIG_X86_64 */
+	asm volatile ("movw %%ds, %0" : "=m" (ctxt->ds));
+	asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
+	asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs));
+	asm volatile ("movw %%gs, %0" : "=m" (ctxt->gs));
+	asm volatile ("movw %%ss, %0" : "=m" (ctxt->ss));
+
+	rdmsrl(MSR_FS_BASE, ctxt->fs_base);
+	rdmsrl(MSR_GS_BASE, ctxt->gs_base);
+	rdmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
+	mtrr_save_fixed_ranges(NULL);
+
+	rdmsrl(MSR_EFER, ctxt->efer);
+#endif
+
+	/*
+	 * control registers
+	 */
+	ctxt->cr0 = read_cr0();
+	ctxt->cr2 = read_cr2();
+	ctxt->cr3 = read_cr3();
+#ifdef CONFIG_X86_32
+	ctxt->cr4 = read_cr4_safe();
+#else
+/* CONFIG_X86_64 */
+	ctxt->cr4 = read_cr4();
+	ctxt->cr8 = read_cr8();
+#endif
+}
+
+/* Needed by apm.c */
+void save_processor_state(void)
+{
+	__save_processor_state(&saved_context);
+}
+#ifdef CONFIG_X86_32
+EXPORT_SYMBOL(save_processor_state);
+#endif
+
+static void do_fpu_end(void)
+{
+	/*
+	 * Restore FPU regs if necessary.
+	 */
+	kernel_fpu_end();
+}
+
+static void fix_processor_context(void)
+{
+	int cpu = smp_processor_id();
+	struct tss_struct *t = &per_cpu(init_tss, cpu);
+
+	set_tss_desc(cpu, t);	/*
+				 * This just modifies memory; should not be
+				 * necessary. But... This is necessary, because
+				 * 386 hardware has concept of busy TSS or some
+				 * similar stupidity.
+				 */
+
+#ifdef CONFIG_X86_64
+	get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
+
+	syscall_init();				/* This sets MSR_*STAR and related */
+#endif
+	load_TR_desc();				/* This does ltr */
+	load_LDT(&current->active_mm->context);	/* This does lldt */
+
+	/*
+	 * Now maybe reload the debug registers
+	 */
+	if (current->thread.debugreg7) {
+#ifdef CONFIG_X86_32
+		set_debugreg(current->thread.debugreg0, 0);
+		set_debugreg(current->thread.debugreg1, 1);
+		set_debugreg(current->thread.debugreg2, 2);
+		set_debugreg(current->thread.debugreg3, 3);
+		/* no 4 and 5 */
+		set_debugreg(current->thread.debugreg6, 6);
+		set_debugreg(current->thread.debugreg7, 7);
+#else
+		/* CONFIG_X86_64 */
+		loaddebug(&current->thread, 0);
+		loaddebug(&current->thread, 1);
+		loaddebug(&current->thread, 2);
+		loaddebug(&current->thread, 3);
+		/* no 4 and 5 */
+		loaddebug(&current->thread, 6);
+		loaddebug(&current->thread, 7);
+#endif
+	}
+
+}
+
+/**
+ *	__restore_processor_state - restore the contents of CPU registers saved
+ *		by __save_processor_state()
+ *	@ctxt - structure to load the registers contents from
+ */
+static void __restore_processor_state(struct saved_context *ctxt)
+{
+	/*
+	 * control registers
+	 */
+	/* cr4 was introduced in the Pentium CPU */
+#ifdef CONFIG_X86_32
+	if (ctxt->cr4)
+		write_cr4(ctxt->cr4);
+#else
+/* CONFIG X86_64 */
+	wrmsrl(MSR_EFER, ctxt->efer);
+	write_cr8(ctxt->cr8);
+	write_cr4(ctxt->cr4);
+#endif
+	write_cr3(ctxt->cr3);
+	write_cr2(ctxt->cr2);
+	write_cr0(ctxt->cr0);
+
+	/*
+	 * now restore the descriptor tables to their proper values
+	 * ltr is done i fix_processor_context().
+	 */
+#ifdef CONFIG_X86_32
+	load_gdt(&ctxt->gdt);
+	load_idt(&ctxt->idt);
+#else
+/* CONFIG_X86_64 */
+	load_gdt((const struct desc_ptr *)&ctxt->gdt_limit);
+	load_idt((const struct desc_ptr *)&ctxt->idt_limit);
+#endif
+
+	/*
+	 * segment registers
+	 */
+#ifdef CONFIG_X86_32
+	loadsegment(es, ctxt->es);
+	loadsegment(fs, ctxt->fs);
+	loadsegment(gs, ctxt->gs);
+	loadsegment(ss, ctxt->ss);
+
+	/*
+	 * sysenter MSRs
+	 */
+	if (boot_cpu_has(X86_FEATURE_SEP))
+		enable_sep_cpu();
+#else
+/* CONFIG_X86_64 */
+	asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds));
+	asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
+	asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs));
+	load_gs_index(ctxt->gs);
+	asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
+
+	wrmsrl(MSR_FS_BASE, ctxt->fs_base);
+	wrmsrl(MSR_GS_BASE, ctxt->gs_base);
+	wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
+#endif
+
+	/*
+	 * restore XCR0 for xsave capable cpu's.
+	 */
+	if (cpu_has_xsave)
+		xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask);
+
+	fix_processor_context();
+
+	do_fpu_end();
+	mtrr_ap_init();
+
+#ifdef CONFIG_X86_OLD_MCE
+	mcheck_init(&boot_cpu_data);
+#endif
+}
+
+/* Needed by apm.c */
+void restore_processor_state(void)
+{
+	__restore_processor_state(&saved_context);
+}
+#ifdef CONFIG_X86_32
+EXPORT_SYMBOL(restore_processor_state);
+#endif
diff -druN linux-libre-2.6.30-gnu/arch/x86/power/Makefile linux-libre-2.6.31-gnu/arch/x86/power/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/power/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/power/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 # __restore_processor_state() restores %gs after S3 resume and so should not
 # itself be stack-protected
 nostackp := $(call cc-option, -fno-stack-protector)
-CFLAGS_cpu_$(BITS).o	:= $(nostackp)
+CFLAGS_cpu.o	:= $(nostackp)
 
-obj-$(CONFIG_PM_SLEEP)		+= cpu_$(BITS).o
+obj-$(CONFIG_PM_SLEEP)		+= cpu.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate_$(BITS).o hibernate_asm_$(BITS).o
diff -druN linux-libre-2.6.30-gnu/arch/x86/vdso/Makefile linux-libre-2.6.31-gnu/arch/x86/vdso/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/vdso/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/vdso/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -123,6 +123,7 @@
 		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^)
 
 VDSO_LDFLAGS = -fPIC -shared $(call ld-option, -Wl$(comma)--hash-style=sysv)
+GCOV_PROFILE := n
 
 #
 # Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
diff -druN linux-libre-2.6.30-gnu/arch/x86/vdso/vdso32-setup.c linux-libre-2.6.31-gnu/arch/x86/vdso/vdso32-setup.c
--- linux-libre-2.6.30-gnu/arch/x86/vdso/vdso32-setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/vdso/vdso32-setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -338,6 +338,8 @@
 		}
 	}
 
+	current->mm->context.vdso = (void *)addr;
+
 	if (compat_uses_vma || !compat) {
 		/*
 		 * MAYWRITE to allow gdb to COW and set breakpoints
@@ -358,11 +360,13 @@
 			goto up_fail;
 	}
 
-	current->mm->context.vdso = (void *)addr;
 	current_thread_info()->sysenter_return =
 		VDSO32_SYMBOL(addr, SYSENTER_RETURN);
 
   up_fail:
+	if (ret)
+		current->mm->context.vdso = NULL;
+
 	up_write(&mm->mmap_sem);
 
 	return ret;
diff -druN linux-libre-2.6.30-gnu/arch/x86/vdso/vma.c linux-libre-2.6.31-gnu/arch/x86/vdso/vma.c
--- linux-libre-2.6.30-gnu/arch/x86/vdso/vma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/vdso/vma.c	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/random.h>
+#include <linux/elf.h>
 #include <asm/vsyscall.h>
 #include <asm/vgtod.h>
 #include <asm/proto.h>
@@ -115,15 +116,18 @@
 		goto up_fail;
 	}
 
+	current->mm->context.vdso = (void *)addr;
+
 	ret = install_special_mapping(mm, addr, vdso_size,
 				      VM_READ|VM_EXEC|
 				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
 				      VM_ALWAYSDUMP,
 				      vdso_pages);
-	if (ret)
+	if (ret) {
+		current->mm->context.vdso = NULL;
 		goto up_fail;
+	}
 
-	current->mm->context.vdso = (void *)addr;
 up_fail:
 	up_write(&mm->mmap_sem);
 	return ret;
diff -druN linux-libre-2.6.30-gnu/arch/x86/xen/enlighten.c linux-libre-2.6.31-gnu/arch/x86/xen/enlighten.c
--- linux-libre-2.6.30-gnu/arch/x86/xen/enlighten.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/xen/enlighten.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/start_kernel.h>
 #include <linux/sched.h>
+#include <linux/kprobes.h>
 #include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
@@ -44,6 +45,7 @@
 #include <asm/processor.h>
 #include <asm/proto.h>
 #include <asm/msr-index.h>
+#include <asm/traps.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
@@ -213,6 +215,7 @@
 			  (1 << X86_FEATURE_ACPI));  /* disable ACPI */
 
 	ax = 1;
+	cx = 0;
 	xen_cpuid(&ax, &bx, &cx, &dx);
 
 	/* cpuid claims we support xsave; try enabling it to see what happens */
@@ -240,10 +243,10 @@
 	return HYPERVISOR_get_debugreg(reg);
 }
 
-void xen_leave_lazy(void)
+static void xen_end_context_switch(struct task_struct *next)
 {
-	paravirt_leave_lazy(paravirt_get_lazy_mode());
 	xen_mc_flush();
+	paravirt_end_context_switch(next);
 }
 
 static unsigned long xen_store_tr(void)
@@ -428,11 +431,44 @@
 static int cvt_gate_to_trap(int vector, const gate_desc *val,
 			    struct trap_info *info)
 {
+	unsigned long addr;
+
 	if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT)
 		return 0;
 
 	info->vector = vector;
-	info->address = gate_offset(*val);
+
+	addr = gate_offset(*val);
+#ifdef CONFIG_X86_64
+	/*
+	 * Look for known traps using IST, and substitute them
+	 * appropriately.  The debugger ones are the only ones we care
+	 * about.  Xen will handle faults like double_fault and
+	 * machine_check, so we should never see them.  Warn if
+	 * there's an unexpected IST-using fault handler.
+	 */
+	if (addr == (unsigned long)debug)
+		addr = (unsigned long)xen_debug;
+	else if (addr == (unsigned long)int3)
+		addr = (unsigned long)xen_int3;
+	else if (addr == (unsigned long)stack_segment)
+		addr = (unsigned long)xen_stack_segment;
+	else if (addr == (unsigned long)double_fault ||
+		 addr == (unsigned long)nmi) {
+		/* Don't need to handle these */
+		return 0;
+#ifdef CONFIG_X86_MCE
+	} else if (addr == (unsigned long)machine_check) {
+		return 0;
+#endif
+	} else {
+		/* Some other trap using IST? */
+		if (WARN_ON(val->ist != 0))
+			return 0;
+	}
+#endif	/* CONFIG_X86_64 */
+	info->address = addr;
+
 	info->cs = gate_segment(*val);
 	info->flags = val->dpl;
 	/* interrupt gates clear IF */
@@ -623,10 +659,26 @@
 	xen_mc_issue(PARAVIRT_LAZY_CPU);
 }
 
+static DEFINE_PER_CPU(unsigned long, xen_cr0_value);
+
+static unsigned long xen_read_cr0(void)
+{
+	unsigned long cr0 = percpu_read(xen_cr0_value);
+
+	if (unlikely(cr0 == 0)) {
+		cr0 = native_read_cr0();
+		percpu_write(xen_cr0_value, cr0);
+	}
+
+	return cr0;
+}
+
 static void xen_write_cr0(unsigned long cr0)
 {
 	struct multicall_space mcs;
 
+	percpu_write(xen_cr0_value, cr0);
+
 	/* Only pay attention to cr0.TS; everything else is
 	   ignored. */
 	mcs = xen_mc_entry(0);
@@ -812,7 +864,7 @@
 
 	.clts = xen_clts,
 
-	.read_cr0 = native_read_cr0,
+	.read_cr0 = xen_read_cr0,
 	.write_cr0 = xen_write_cr0,
 
 	.read_cr4 = native_read_cr4,
@@ -860,10 +912,8 @@
 	/* Xen takes care of %gs when switching to usermode for us */
 	.swapgs = paravirt_nop,
 
-	.lazy_mode = {
-		.enter = paravirt_enter_lazy_cpu,
-		.leave = xen_leave_lazy,
-	},
+	.start_context_switch = paravirt_start_context_switch,
+	.end_context_switch = xen_end_context_switch,
 };
 
 static const struct pv_apic_ops xen_apic_ops __initdata = {
@@ -925,10 +975,6 @@
 
 	xen_domain_type = XEN_PV_DOMAIN;
 
-	BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0);
-
-	xen_setup_features();
-
 	/* Install Xen paravirt ops */
 	pv_info = xen_info;
 	pv_init_ops = xen_init_ops;
@@ -937,8 +983,15 @@
 	pv_apic_ops = xen_apic_ops;
 	pv_mmu_ops = xen_mmu_ops;
 
-	xen_init_irq_ops();
+#ifdef CONFIG_X86_64
+	/*
+	 * Setup percpu state.  We only need to do this for 64-bit
+	 * because 32-bit already has %fs set properly.
+	 */
+	load_percpu_segment(0);
+#endif
 
+	xen_init_irq_ops();
 	xen_init_cpuid_mask();
 
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -948,6 +1001,8 @@
 	set_xen_basic_apic_ops();
 #endif
 
+	xen_setup_features();
+
 	if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
 		pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start;
 		pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
@@ -955,13 +1010,6 @@
 
 	machine_ops = xen_machine_ops;
 
-#ifdef CONFIG_X86_64
-	/*
-	 * Setup percpu state.  We only need to do this for 64-bit
-	 * because 32-bit already has %fs set properly.
-	 */
-	load_percpu_segment(0);
-#endif
 	/*
 	 * The only reliable way to retain the initial address of the
 	 * percpu gdt_page is to remember it here, so we can go and
@@ -1012,6 +1060,7 @@
 	/* set up basic CPUID stuff */
 	cpu_detect(&new_cpu_data);
 	new_cpu_data.hard_math = 1;
+	new_cpu_data.wp_works_ok = 1;
 	new_cpu_data.x86_capability[0] = cpuid_edx(1);
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/xen/Makefile linux-libre-2.6.31-gnu/arch/x86/xen/Makefile
--- linux-libre-2.6.30-gnu/arch/x86/xen/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/xen/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -5,6 +5,10 @@
 CFLAGS_REMOVE_irq.o = -pg
 endif
 
+# Make sure early boot has no stackprotector
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_enlighten.o		:= $(nostackp)
+
 obj-y		:= enlighten.o setup.o multicalls.o mmu.o irq.o \
 			time.o xen-asm.o xen-asm_$(BITS).o \
 			grant-table.o suspend.o
diff -druN linux-libre-2.6.30-gnu/arch/x86/xen/mmu.c linux-libre-2.6.31-gnu/arch/x86/xen/mmu.c
--- linux-libre-2.6.30-gnu/arch/x86/xen/mmu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/xen/mmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -452,10 +452,6 @@
 void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
 		    pte_t *ptep, pte_t pteval)
 {
-	/* updates to init_mm may be done without lock */
-	if (mm == &init_mm)
-		preempt_disable();
-
 	ADD_STATS(set_pte_at, 1);
 //	ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep));
 	ADD_STATS(set_pte_at_current, mm == current->mm);
@@ -476,9 +472,7 @@
 	}
 	xen_set_pte(ptep, pteval);
 
-out:
-	if (mm == &init_mm)
-		preempt_enable();
+out:	return;
 }
 
 pte_t xen_ptep_modify_prot_start(struct mm_struct *mm,
@@ -1152,10 +1146,8 @@
 
 	/* If this cpu still has a stale cr3 reference, then make sure
 	   it has been flushed. */
-	if (percpu_read(xen_current_cr3) == __pa(mm->pgd)) {
+	if (percpu_read(xen_current_cr3) == __pa(mm->pgd))
 		load_cr3(swapper_pg_dir);
-		arch_flush_lazy_cpu_mode();
-	}
 }
 
 static void xen_drop_mm_ref(struct mm_struct *mm)
@@ -1168,7 +1160,6 @@
 			load_cr3(swapper_pg_dir);
 		else
 			leave_mm(smp_processor_id());
-		arch_flush_lazy_cpu_mode();
 	}
 
 	/* Get the "official" set of cpus referring to our pagetable. */
@@ -1876,6 +1867,14 @@
 	xen_mark_init_mm_pinned();
 }
 
+static void xen_leave_lazy_mmu(void)
+{
+	preempt_disable();
+	xen_mc_flush();
+	paravirt_leave_lazy_mmu();
+	preempt_enable();
+}
+
 const struct pv_mmu_ops xen_mmu_ops __initdata = {
 	.pagetable_setup_start = xen_pagetable_setup_start,
 	.pagetable_setup_done = xen_pagetable_setup_done,
@@ -1949,7 +1948,7 @@
 
 	.lazy_mode = {
 		.enter = paravirt_enter_lazy_mmu,
-		.leave = xen_leave_lazy,
+		.leave = xen_leave_lazy_mmu,
 	},
 
 	.set_fixmap = xen_set_fixmap,
diff -druN linux-libre-2.6.30-gnu/arch/x86/xen/setup.c linux-libre-2.6.31-gnu/arch/x86/xen/setup.c
--- linux-libre-2.6.30-gnu/arch/x86/xen/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/xen/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,9 +61,9 @@
 	 *  - xen_start_info
 	 * See comment above "struct start_info" in <xen/interface/xen.h>
 	 */
-	e820_add_region(__pa(xen_start_info->mfn_list),
-			xen_start_info->pt_base - xen_start_info->mfn_list,
-			E820_RESERVED);
+	reserve_early(__pa(xen_start_info->mfn_list),
+		      __pa(xen_start_info->pt_base),
+			"XEN START INFO");
 
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 
diff -druN linux-libre-2.6.30-gnu/arch/x86/xen/xen-ops.h linux-libre-2.6.31-gnu/arch/x86/xen/xen-ops.h
--- linux-libre-2.6.30-gnu/arch/x86/xen/xen-ops.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/x86/xen/xen-ops.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,6 @@
 void xen_ident_map_ISA(void);
 void xen_reserve_top(void);
 
-void xen_leave_lazy(void);
 void xen_post_allocator_init(void);
 
 char * __init xen_memory_setup(void);
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/configs/s6105_defconfig linux-libre-2.6.31-gnu/arch/xtensa/configs/s6105_defconfig
--- linux-libre-2.6.30-gnu/arch/xtensa/configs/s6105_defconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/configs/s6105_defconfig	2009-09-09 18:13:59.000000000 -0400
@@ -263,7 +263,54 @@
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
-# CONFIG_NETDEVICES is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_NETDEV_1000=y
+CONFIG_S6GMAC=y
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_ISDN is not set
 # CONFIG_PHONE is not set
 
@@ -304,8 +351,6 @@
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
@@ -387,7 +432,59 @@
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
-# 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 is not set
+# CONFIG_RTC_INTF_PROC is not set
+# CONFIG_RTC_INTF_DEV is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+CONFIG_RTC_DRV_M41T80=y
+# CONFIG_RTC_DRV_M41T80_WDT is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
 # CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/atomic.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/atomic.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/atomic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/atomic.h	2009-09-09 18:13:59.000000000 -0400
@@ -292,7 +292,7 @@
 #define smp_mb__before_atomic_inc()	barrier()
 #define smp_mb__after_atomic_inc()	barrier()
 
-#include <asm-generic/atomic.h>
+#include <asm-generic/atomic-long.h>
 #endif /* __KERNEL__ */
 
 #endif /* _XTENSA_ATOMIC_H */
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/bitsperlong.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/bitsperlong.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/bitsperlong.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/bitsperlong.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/cacheflush.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/cacheflush.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/cacheflush.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/cacheflush.h	2009-09-09 18:13:59.000000000 -0400
@@ -155,5 +155,100 @@
 
 #endif
 
+#define XTENSA_CACHEBLK_LOG2	29
+#define XTENSA_CACHEBLK_SIZE	(1 << XTENSA_CACHEBLK_LOG2)
+#define XTENSA_CACHEBLK_MASK	(7 << XTENSA_CACHEBLK_LOG2)
+
+#if XCHAL_HAVE_CACHEATTR
+static inline u32 xtensa_get_cacheattr(void)
+{
+	u32 r;
+	asm volatile("	rsr %0, CACHEATTR" : "=a"(r));
+	return r;
+}
+
+static inline u32 xtensa_get_dtlb1(u32 addr)
+{
+	u32 r = addr & XTENSA_CACHEBLK_MASK;
+	return r | ((xtensa_get_cacheattr() >> (r >> (XTENSA_CACHEBLK_LOG2-2)))
+			& 0xF);
+}
+#else
+static inline u32 xtensa_get_dtlb1(u32 addr)
+{
+	u32 r;
+	asm volatile("	rdtlb1 %0, %1" : "=a"(r) : "a"(addr));
+	asm volatile("	dsync");
+	return r;
+}
+
+static inline u32 xtensa_get_cacheattr(void)
+{
+	u32 r = 0;
+	u32 a = 0;
+	do {
+		a -= XTENSA_CACHEBLK_SIZE;
+		r = (r << 4) | (xtensa_get_dtlb1(a) & 0xF);
+	} while (a);
+	return r;
+}
+#endif
+
+static inline int xtensa_need_flush_dma_source(u32 addr)
+{
+	return (xtensa_get_dtlb1(addr) & ((1 << XCHAL_CA_BITS) - 1)) >= 4;
+}
+
+static inline int xtensa_need_invalidate_dma_destination(u32 addr)
+{
+	return (xtensa_get_dtlb1(addr) & ((1 << XCHAL_CA_BITS) - 1)) != 2;
+}
+
+static inline void flush_dcache_unaligned(u32 addr, u32 size)
+{
+	u32 cnt;
+	if (size) {
+		cnt = (size + ((XCHAL_DCACHE_LINESIZE - 1) & addr)
+			+ XCHAL_DCACHE_LINESIZE - 1) / XCHAL_DCACHE_LINESIZE;
+		while (cnt--) {
+			asm volatile("	dhwb %0, 0" : : "a"(addr));
+			addr += XCHAL_DCACHE_LINESIZE;
+		}
+		asm volatile("	dsync");
+	}
+}
+
+static inline void invalidate_dcache_unaligned(u32 addr, u32 size)
+{
+	int cnt;
+	if (size) {
+		asm volatile("	dhwbi %0, 0 ;" : : "a"(addr));
+		cnt = (size + ((XCHAL_DCACHE_LINESIZE - 1) & addr)
+			- XCHAL_DCACHE_LINESIZE - 1) / XCHAL_DCACHE_LINESIZE;
+		while (cnt-- > 0) {
+			asm volatile("	dhi %0, %1" : : "a"(addr),
+						"n"(XCHAL_DCACHE_LINESIZE));
+			addr += XCHAL_DCACHE_LINESIZE;
+		}
+		asm volatile("	dhwbi %0, %1" : : "a"(addr),
+						"n"(XCHAL_DCACHE_LINESIZE));
+		asm volatile("	dsync");
+	}
+}
+
+static inline void flush_invalidate_dcache_unaligned(u32 addr, u32 size)
+{
+	u32 cnt;
+	if (size) {
+		cnt = (size + ((XCHAL_DCACHE_LINESIZE - 1) & addr)
+			+ XCHAL_DCACHE_LINESIZE - 1) / XCHAL_DCACHE_LINESIZE;
+		while (cnt--) {
+			asm volatile("	dhwbi %0, 0" : : "a"(addr));
+			addr += XCHAL_DCACHE_LINESIZE;
+		}
+		asm volatile("	dsync");
+	}
+}
+
 #endif /* __KERNEL__ */
 #endif /* _XTENSA_CACHEFLUSH_H */
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/gpio.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/gpio.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -38,14 +38,14 @@
 	return __gpio_cansleep(gpio);
 }
 
-/*
- * Not implemented, yet.
- */
 static inline int gpio_to_irq(unsigned int gpio)
 {
-	return -ENOSYS;
+	return __gpio_to_irq(gpio);
 }
 
+/*
+ * Not implemented, yet.
+ */
 static inline int irq_to_gpio(unsigned int irq)
 {
 	return -EINVAL;
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/irq.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/irq.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,7 @@
 #ifndef _XTENSA_IRQ_H
 #define _XTENSA_IRQ_H
 
+#include <linux/init.h>
 #include <platform/hardware.h>
 #include <variant/core.h>
 
@@ -21,11 +22,20 @@
 static inline void variant_irq_disable(unsigned int irq) { }
 #endif
 
+#ifndef VARIANT_NR_IRQS
+# define VARIANT_NR_IRQS 0
+#endif
 #ifndef PLATFORM_NR_IRQS
 # define PLATFORM_NR_IRQS 0
 #endif
 #define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
-#define NR_IRQS (XTENSA_NR_IRQS + PLATFORM_NR_IRQS)
+#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS)
+
+#if VARIANT_NR_IRQS == 0
+static inline void variant_init_irq(void) { }
+#else
+void variant_init_irq(void) __init;
+#endif
 
 static __inline__ int irq_canonicalize(int irq)
 {
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/kmap_types.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/kmap_types.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/kmap_types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/kmap_types.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,31 +1,6 @@
-/*
- * include/asm-xtensa/kmap_types.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.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
 #ifndef _XTENSA_KMAP_TYPES_H
 #define _XTENSA_KMAP_TYPES_H
 
-enum km_type {
-  KM_BOUNCE_READ,
-  KM_SKB_SUNRPC_DATA,
-  KM_SKB_DATA_SOFTIRQ,
-  KM_USER0,
-  KM_USER1,
-  KM_BIO_SRC_IRQ,
-  KM_BIO_DST_IRQ,
-  KM_PTE0,
-  KM_PTE1,
-  KM_IRQ0,
-  KM_IRQ1,
-  KM_SOFTIRQ0,
-  KM_SOFTIRQ1,
-  KM_TYPE_NR
-};
+#include <asm-generic/kmap_types.h>
 
 #endif	/* _XTENSA_KMAP_TYPES_H */
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/page.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/page.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/page.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/page.h	2009-09-09 18:13:59.000000000 -0400
@@ -129,7 +129,7 @@
 
 #else
 
-# include <asm-generic/page.h>
+# include <asm-generic/getorder.h>
 
 #endif
 
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/thread_info.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/thread_info.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/thread_info.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/thread_info.h	2009-09-09 18:13:59.000000000 -0400
@@ -80,8 +80,6 @@
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 
 #ifndef __ASSEMBLY__
@@ -92,7 +90,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= 1,			\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/include/asm/tlb.h linux-libre-2.6.31-gnu/arch/xtensa/include/asm/tlb.h
--- linux-libre-2.6.30-gnu/arch/xtensa/include/asm/tlb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/include/asm/tlb.h	2009-09-09 18:13:59.000000000 -0400
@@ -42,6 +42,6 @@
 
 #include <asm-generic/tlb.h>
 
-#define __pte_free_tlb(tlb, pte)		pte_free((tlb)->mm, pte)
+#define __pte_free_tlb(tlb, pte, address)	pte_free((tlb)->mm, pte)
 
 #endif	/* _XTENSA_TLB_H */
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/kernel/init_task.c linux-libre-2.6.31-gnu/arch/xtensa/kernel/init_task.c
--- linux-libre-2.6.30-gnu/arch/xtensa/kernel/init_task.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/kernel/init_task.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,10 +23,6 @@
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
 union thread_union init_thread_union
 	__attribute__((__section__(".data.init_task"))) =
 { INIT_THREAD_INFO(init_task) };
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/kernel/irq.c linux-libre-2.6.31-gnu/arch/xtensa/kernel/irq.c
--- linux-libre-2.6.30-gnu/arch/xtensa/kernel/irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/kernel/irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -197,4 +197,6 @@
 	}
 
 	cached_irq_mask = 0;
+
+	variant_init_irq();
 }
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/kernel/module.c linux-libre-2.6.31-gnu/arch/xtensa/kernel/module.c
--- linux-libre-2.6.30-gnu/arch/xtensa/kernel/module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/kernel/module.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,8 +34,6 @@
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
-	/* FIXME: If module_region == mod->init_region, trim exception
-	   table entries. */
 }
 
 int module_frob_arch_sections(Elf32_Ehdr *hdr,
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/kernel/process.c linux-libre-2.6.31-gnu/arch/xtensa/kernel/process.c
--- linux-libre-2.6.30-gnu/arch/xtensa/kernel/process.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/kernel/process.c	2009-09-09 18:13:59.000000000 -0400
@@ -331,11 +331,6 @@
 	if (IS_ERR(filename))
 		goto out;
 	error = do_execve(filename, argv, envp, regs);
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
-		task_unlock(current);
-	}
 	putname(filename);
 out:
 	return error;
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/kernel/traps.c linux-libre-2.6.31-gnu/arch/xtensa/kernel/traps.c
--- linux-libre-2.6.30-gnu/arch/xtensa/kernel/traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/kernel/traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -354,10 +354,10 @@
 
 	for (i = 0; i < 16; i++) {
 		if ((i % 8) == 0)
-			printk ("\n" KERN_INFO "a%02d: ", i);
-		printk("%08lx ", regs->areg[i]);
+			printk(KERN_INFO "a%02d:", i);
+		printk(KERN_CONT " %08lx", regs->areg[i]);
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 
 	printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n",
 	       regs->pc, regs->ps, regs->depc, regs->excvaddr);
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/mm/fault.c linux-libre-2.6.31-gnu/arch/xtensa/mm/fault.c
--- linux-libre-2.6.30-gnu/arch/xtensa/mm/fault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/mm/fault.c	2009-09-09 18:13:59.000000000 -0400
@@ -106,7 +106,7 @@
 	 * the fault.
 	 */
 survive:
-	fault = handle_mm_fault(mm, vma, address, is_write);
+	fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
 			goto out_of_memory;
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/platforms/s6105/device.c linux-libre-2.6.31-gnu/arch/xtensa/platforms/s6105/device.c
--- linux-libre-2.6.30-gnu/arch/xtensa/platforms/s6105/device.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/platforms/s6105/device.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,14 +5,27 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 
 #include <variant/hardware.h>
+#include <variant/dmac.h>
+
+#include <platform/gpio.h>
 
+#define GPIO3_INTNUM		3
 #define UART_INTNUM		4
+#define GMAC_INTNUM		5
+
+static const signed char gpio3_irq_mappings[] = {
+	S6_INTC_GPIO(3),
+	-1
+};
 
 static const signed char uart_irq_mappings[] = {
 	S6_INTC_UART(0),
@@ -20,8 +33,18 @@
 	-1,
 };
 
+static const signed char gmac_irq_mappings[] = {
+	S6_INTC_GMAC_STAT,
+	S6_INTC_GMAC_ERR,
+	S6_INTC_DMA_HOSTTERMCNT(0),
+	S6_INTC_DMA_HOSTTERMCNT(1),
+	-1
+};
+
 const signed char *platform_irq_mappings[NR_IRQS] = {
+	[GPIO3_INTNUM] = gpio3_irq_mappings,
 	[UART_INTNUM] = uart_irq_mappings,
+	[GMAC_INTNUM] = gmac_irq_mappings,
 };
 
 static struct plat_serial8250_port serial_platform_data[] = {
@@ -46,6 +69,66 @@
 	{ },
 };
 
+static struct resource s6_gmac_resource[] = {
+	{
+		.name   = "mem",
+		.start  = (resource_size_t)S6_REG_GMAC,
+		.end    = (resource_size_t)S6_REG_GMAC + 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "dma",
+		.start  = (resource_size_t)
+			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX),
+		.end    = (resource_size_t)
+			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX) + 0x100 - 1,
+		.flags  = IORESOURCE_DMA,
+	},
+	{
+		.name   = "dma",
+		.start  = (resource_size_t)
+			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX),
+		.end    = (resource_size_t)
+			DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX) + 0x100 - 1,
+		.flags  = IORESOURCE_DMA,
+	},
+	{
+		.name   = "io",
+		.start  = (resource_size_t)S6_MEM_GMAC,
+		.end    = (resource_size_t)S6_MEM_GMAC + 0x2000000 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "irq",
+		.start  = (resource_size_t)GMAC_INTNUM,
+		.flags  = IORESOURCE_IRQ,
+	},
+	{
+		.name   = "irq",
+		.start  = (resource_size_t)PHY_POLL,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static int __init prepare_phy_irq(int pin)
+{
+	int irq;
+	if (gpio_request(pin, "s6gmac_phy") < 0)
+		goto fail;
+	if (gpio_direction_input(pin) < 0)
+		goto free;
+	irq = gpio_to_irq(pin);
+	if (irq < 0)
+		goto free;
+	if (set_irq_type(irq, IRQ_TYPE_LEVEL_LOW) < 0)
+		goto free;
+	return irq;
+free:
+	gpio_free(pin);
+fail:
+	return PHY_POLL;
+}
+
 static struct platform_device platform_devices[] = {
 	{
 		.name = "serial8250",
@@ -54,12 +137,23 @@
 			.platform_data = serial_platform_data,
 		},
 	},
+	{
+		.name = "s6gmac",
+		.id = 0,
+		.resource = s6_gmac_resource,
+		.num_resources = ARRAY_SIZE(s6_gmac_resource),
+	},
+	{
+		I2C_BOARD_INFO("m41t62", S6I2C_ADDR_M41T62),
+	},
 };
 
 static int __init device_init(void)
 {
 	int i;
 
+	s6_gmac_resource[5].start = prepare_phy_irq(GPIO_PHY_IRQ);
+
 	for (i = 0; i < ARRAY_SIZE(platform_devices); i++)
 		platform_device_register(&platform_devices[i]);
 	return 0;
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/platforms/s6105/setup.c linux-libre-2.6.31-gnu/arch/xtensa/platforms/s6105/setup.c
--- linux-libre-2.6.30-gnu/arch/xtensa/platforms/s6105/setup.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/platforms/s6105/setup.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,12 +35,21 @@
 {
 	unsigned long reg;
 
+	reg = readl(S6_REG_GREG1 + S6_GREG1_PLLSEL);
+	reg &= ~(S6_GREG1_PLLSEL_GMAC_MASK << S6_GREG1_PLLSEL_GMAC |
+		S6_GREG1_PLLSEL_GMII_MASK << S6_GREG1_PLLSEL_GMII);
+	reg |= S6_GREG1_PLLSEL_GMAC_125MHZ << S6_GREG1_PLLSEL_GMAC |
+		S6_GREG1_PLLSEL_GMII_125MHZ << S6_GREG1_PLLSEL_GMII;
+	writel(reg, S6_REG_GREG1 + S6_GREG1_PLLSEL);
+
 	reg = readl(S6_REG_GREG1 + S6_GREG1_CLKGATE);
 	reg &= ~(1 << S6_GREG1_BLOCK_SB);
+	reg &= ~(1 << S6_GREG1_BLOCK_GMAC);
 	writel(reg, S6_REG_GREG1 + S6_GREG1_CLKGATE);
 
 	reg = readl(S6_REG_GREG1 + S6_GREG1_BLOCKENA);
 	reg |= 1 << S6_GREG1_BLOCK_SB;
+	reg |= 1 << S6_GREG1_BLOCK_GMAC;
 	writel(reg, S6_REG_GREG1 + S6_GREG1_BLOCKENA);
 
 	printk(KERN_NOTICE "S6105 on Stretch S6000 - "
@@ -49,7 +58,7 @@
 
 void __init platform_init(bp_tag_t *first)
 {
-	s6_gpio_init();
+	s6_gpio_init(0);
 	gpio_request(GPIO_LED1_NGREEN, "led1_green");
 	gpio_request(GPIO_LED1_RED, "led1_red");
 	gpio_direction_output(GPIO_LED1_NGREEN, 1);
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/dmac.c linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/dmac.c
--- linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/dmac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/dmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,173 @@
+/*
+ * Authors:	Oskar Schirmer <os@emlix.com>
+ *		Daniel Gloeckner <dg@emlix.com>
+ * (c) 2008 emlix GmbH http://www.emlix.com
+ *
+ * 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/kernel.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <asm/cacheflush.h>
+#include <variant/dmac.h>
+
+/* DMA engine lookup */
+
+struct s6dmac_ctrl s6dmac_ctrl[S6_DMAC_NB];
+
+
+/* DMA control, per engine */
+
+void s6dmac_put_fifo_cache(u32 dmac, int chan, u32 src, u32 dst, u32 size)
+{
+	if (xtensa_need_flush_dma_source(src)) {
+		u32 base = src;
+		u32 span = size;
+		u32 chunk = readl(DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
+		if (chunk && (size > chunk)) {
+			s32 skip =
+				readl(DMA_CHNL(dmac, chan) + S6_DMA_SRCSKIP);
+			u32 gaps = (size+chunk-1)/chunk - 1;
+			if (skip >= 0) {
+				span += gaps * skip;
+			} else if (-skip > chunk) {
+				s32 decr = gaps * (chunk + skip);
+				base += decr;
+				span = chunk - decr;
+			} else {
+				span = max(span + gaps * skip,
+					(chunk + skip) * gaps - skip);
+			}
+		}
+		flush_dcache_unaligned(base, span);
+	}
+	if (xtensa_need_invalidate_dma_destination(dst)) {
+		u32 base = dst;
+		u32 span = size;
+		u32 chunk = readl(DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
+		if (chunk && (size > chunk)) {
+			s32 skip =
+				readl(DMA_CHNL(dmac, chan) + S6_DMA_DSTSKIP);
+			u32 gaps = (size+chunk-1)/chunk - 1;
+			if (skip >= 0) {
+				span += gaps * skip;
+			} else if (-skip > chunk) {
+				s32 decr = gaps * (chunk + skip);
+				base += decr;
+				span = chunk - decr;
+			} else {
+				span = max(span + gaps * skip,
+					(chunk + skip) * gaps - skip);
+			}
+		}
+		invalidate_dcache_unaligned(base, span);
+	}
+	s6dmac_put_fifo(dmac, chan, src, dst, size);
+}
+
+void s6dmac_disable_error_irqs(u32 dmac, u32 mask)
+{
+	unsigned long flags;
+	spinlock_t *spinl = &s6dmac_ctrl[_dmac_addr_index(dmac)].lock;
+	spin_lock_irqsave(spinl, flags);
+	_s6dmac_disable_error_irqs(dmac, mask);
+	spin_unlock_irqrestore(spinl, flags);
+}
+
+u32 s6dmac_int_sources(u32 dmac, u32 channel)
+{
+	u32 mask, ret, tmp;
+	mask = 1 << channel;
+
+	tmp = readl(dmac + S6_DMA_TERMCNTIRQSTAT);
+	tmp &= mask;
+	writel(tmp, dmac + S6_DMA_TERMCNTIRQCLR);
+	ret = tmp >> channel;
+
+	tmp = readl(dmac + S6_DMA_PENDCNTIRQSTAT);
+	tmp &= mask;
+	writel(tmp, dmac + S6_DMA_PENDCNTIRQCLR);
+	ret |= (tmp >> channel) << 1;
+
+	tmp = readl(dmac + S6_DMA_LOWWMRKIRQSTAT);
+	tmp &= mask;
+	writel(tmp, dmac + S6_DMA_LOWWMRKIRQCLR);
+	ret |= (tmp >> channel) << 2;
+
+	tmp = readl(dmac + S6_DMA_INTRAW0);
+	tmp &= (mask << S6_DMA_INT0_OVER) | (mask << S6_DMA_INT0_UNDER);
+	writel(tmp, dmac + S6_DMA_INTCLEAR0);
+
+	if (tmp & (mask << S6_DMA_INT0_UNDER))
+		ret |= 1 << 3;
+	if (tmp & (mask << S6_DMA_INT0_OVER))
+		ret |= 1 << 4;
+
+	tmp = readl(dmac + S6_DMA_MASTERERRINFO);
+	mask <<= S6_DMA_INT1_CHANNEL;
+	if (((tmp >> S6_DMA_MASTERERR_CHAN(0)) & S6_DMA_MASTERERR_CHAN_MASK)
+			== channel)
+		mask |= 1 << S6_DMA_INT1_MASTER;
+	if (((tmp >> S6_DMA_MASTERERR_CHAN(1)) & S6_DMA_MASTERERR_CHAN_MASK)
+			== channel)
+		mask |= 1 << (S6_DMA_INT1_MASTER + 1);
+	if (((tmp >> S6_DMA_MASTERERR_CHAN(2)) & S6_DMA_MASTERERR_CHAN_MASK)
+			== channel)
+		mask |= 1 << (S6_DMA_INT1_MASTER + 2);
+
+	tmp = readl(dmac + S6_DMA_INTRAW1) & mask;
+	writel(tmp, dmac + S6_DMA_INTCLEAR1);
+	ret |= ((tmp >> channel) & 1) << 5;
+	ret |= ((tmp >> S6_DMA_INT1_MASTER) & S6_DMA_INT1_MASTER_MASK) << 6;
+
+	return ret;
+}
+
+void s6dmac_release_chan(u32 dmac, int chan)
+{
+	if (chan >= 0)
+		s6dmac_disable_chan(dmac, chan);
+}
+
+
+/* global init */
+
+static inline void __init dmac_init(u32 dmac, u8 chan_nb)
+{
+	s6dmac_ctrl[S6_DMAC_INDEX(dmac)].dmac = dmac;
+	spin_lock_init(&s6dmac_ctrl[S6_DMAC_INDEX(dmac)].lock);
+	s6dmac_ctrl[S6_DMAC_INDEX(dmac)].chan_nb = chan_nb;
+	writel(S6_DMA_INT1_MASTER_MASK << S6_DMA_INT1_MASTER,
+		dmac + S6_DMA_INTCLEAR1);
+}
+
+static inline void __init dmac_master(u32 dmac,
+	u32 m0start, u32 m0end, u32 m1start, u32 m1end)
+{
+	writel(m0start, dmac + S6_DMA_MASTER0START);
+	writel(m0end - 1, dmac + S6_DMA_MASTER0END);
+	writel(m1start, dmac + S6_DMA_MASTER1START);
+	writel(m1end - 1, dmac + S6_DMA_MASTER1END);
+}
+
+static void __init s6_dmac_init(void)
+{
+	dmac_init(S6_REG_LMSDMA, S6_LMSDMA_NB);
+	dmac_master(S6_REG_LMSDMA,
+		S6_MEM_DDR, S6_MEM_PCIE_APER, S6_MEM_EFI, S6_MEM_GMAC);
+	dmac_init(S6_REG_NIDMA, S6_NIDMA_NB);
+	dmac_init(S6_REG_DPDMA, S6_DPDMA_NB);
+	dmac_master(S6_REG_DPDMA,
+		S6_MEM_DDR, S6_MEM_PCIE_APER, S6_REG_DP, S6_REG_DPDMA);
+	dmac_init(S6_REG_HIFDMA, S6_HIFDMA_NB);
+	dmac_master(S6_REG_HIFDMA,
+		S6_MEM_GMAC, S6_MEM_PCIE_CFG, S6_MEM_PCIE_APER, S6_MEM_AUX);
+}
+
+arch_initcall(s6_dmac_init);
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/gpio.c linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/gpio.c
--- linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -4,15 +4,20 @@
  * Copyright (c) 2009 emlix GmbH
  * Authors:	Oskar Schirmer <os@emlix.com>
  *		Johannes Weiner <jw@emlix.com>
+ *		Daniel Gloeckner <dg@emlix.com>
  */
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/gpio.h>
 
 #include <variant/hardware.h>
 
+#define IRQ_BASE XTENSA_NR_IRQS
+
 #define S6_GPIO_DATA		0x000
 #define S6_GPIO_IS		0x404
 #define S6_GPIO_IBE		0x408
@@ -52,19 +57,175 @@
 	writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off));
 }
 
+static int to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset < 8)
+		return offset + IRQ_BASE;
+	return -EINVAL;
+}
+
 static struct gpio_chip gpiochip = {
 	.owner = THIS_MODULE,
 	.direction_input = direction_input,
 	.get = get,
 	.direction_output = direction_output,
 	.set = set,
+	.to_irq = to_irq,
 	.base = 0,
 	.ngpio = 24,
 	.can_sleep = 0, /* no blocking io needed */
 	.exported = 0, /* no exporting to userspace */
 };
 
-int s6_gpio_init(void)
+int s6_gpio_init(u32 afsel)
 {
+	writeb(afsel, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_AFSEL);
+	writeb(afsel >> 8, S6_REG_GPIO + S6_GPIO_BANK(1) + S6_GPIO_AFSEL);
+	writeb(afsel >> 16, S6_REG_GPIO + S6_GPIO_BANK(2) + S6_GPIO_AFSEL);
 	return gpiochip_add(&gpiochip);
 }
+
+static void ack(unsigned int irq)
+{
+	writeb(1 << (irq - IRQ_BASE), S6_REG_GPIO + S6_GPIO_IC);
+}
+
+static void mask(unsigned int irq)
+{
+	u8 r = readb(S6_REG_GPIO + S6_GPIO_IE);
+	r &= ~(1 << (irq - IRQ_BASE));
+	writeb(r, S6_REG_GPIO + S6_GPIO_IE);
+}
+
+static void unmask(unsigned int irq)
+{
+	u8 m = readb(S6_REG_GPIO + S6_GPIO_IE);
+	m |= 1 << (irq - IRQ_BASE);
+	writeb(m, S6_REG_GPIO + S6_GPIO_IE);
+}
+
+static int set_type(unsigned int irq, unsigned int type)
+{
+	const u8 m = 1 << (irq - IRQ_BASE);
+	irq_flow_handler_t handler;
+	struct irq_desc *desc;
+	u8 reg;
+
+	if (type == IRQ_TYPE_PROBE) {
+		if ((readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_AFSEL) & m)
+		    || (readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IE) & m)
+		    || readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_DIR
+			      + S6_GPIO_MASK(irq - IRQ_BASE)))
+			return 0;
+		type = IRQ_TYPE_EDGE_BOTH;
+	}
+
+	reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IS);
+	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
+		reg |= m;
+		handler = handle_level_irq;
+	} else {
+		reg &= ~m;
+		handler = handle_edge_irq;
+	}
+	writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IS);
+	desc = irq_to_desc(irq);
+	desc->handle_irq = handler;
+
+	reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IEV);
+	if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING))
+		reg |= m;
+	else
+		reg &= ~m;
+	writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IEV);
+
+	reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IBE);
+	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+		reg |= m;
+	else
+		reg &= ~m;
+	writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IBE);
+	return 0;
+}
+
+static struct irq_chip gpioirqs = {
+	.name = "GPIO",
+	.ack = ack,
+	.mask = mask,
+	.unmask = unmask,
+	.set_type = set_type,
+};
+
+static u8 demux_masks[4];
+
+static void demux_irqs(unsigned int irq, struct irq_desc *desc)
+{
+	u8 *mask = get_irq_desc_data(desc);
+	u8 pending;
+	int cirq;
+
+	desc->chip->mask(irq);
+	desc->chip->ack(irq);
+	pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask;
+	cirq = IRQ_BASE - 1;
+	while (pending) {
+		int n = ffs(pending);
+		cirq += n;
+		pending >>= n;
+		generic_handle_irq(cirq);
+	}
+	desc->chip->unmask(irq);
+}
+
+extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS];
+
+void __init variant_init_irq(void)
+{
+	int irq, n;
+	writeb(0, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IE);
+	for (irq = n = 0; irq < XTENSA_NR_IRQS; irq++) {
+		const signed char *mapping = platform_irq_mappings[irq];
+		int alone = 1;
+		u8 mask;
+		if (!mapping)
+			continue;
+		for(mask = 0; *mapping != -1; mapping++)
+			switch (*mapping) {
+			case S6_INTC_GPIO(0):
+				mask |= 1 << 0;
+				break;
+			case S6_INTC_GPIO(1):
+				mask |= 1 << 1;
+				break;
+			case S6_INTC_GPIO(2):
+				mask |= 1 << 2;
+				break;
+			case S6_INTC_GPIO(3):
+				mask |= 0x1f << 3;
+				break;
+			default:
+				alone = 0;
+			}
+		if (mask) {
+			int cirq, i;
+			if (!alone) {
+				printk(KERN_ERR "chained irq chips can't share"
+					" parent irq %i\n", irq);
+				continue;
+			}
+			demux_masks[n] = mask;
+			cirq = IRQ_BASE - 1;
+			do {
+				i = ffs(mask);
+				cirq += i;
+				mask >>= i;
+				set_irq_chip(cirq, &gpioirqs);
+				set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
+			} while (mask);
+			set_irq_data(irq, demux_masks + n);
+			set_irq_chained_handler(irq, demux_irqs);
+			if (++n == ARRAY_SIZE(demux_masks))
+				break;
+		}
+	}
+}
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/include/variant/dmac.h linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/include/variant/dmac.h
--- linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/include/variant/dmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/include/variant/dmac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,387 @@
+/*
+ * include/asm-xtensa/variant-s6000/dmac.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.
+ *
+ * Copyright (C) 2006 Tensilica Inc.
+ * Copyright (C) 2008 Emlix GmbH <info@emlix.com>
+ * Authors:	Fabian Godehardt <fg@emlix.com>
+ *		Oskar Schirmer <os@emlix.com>
+ *		Daniel Gloeckner <dg@emlix.com>
+ */
+
+#ifndef __ASM_XTENSA_S6000_DMAC_H
+#define __ASM_XTENSA_S6000_DMAC_H
+#include <linux/io.h>
+#include <variant/hardware.h>
+
+/* DMA global */
+
+#define S6_DMA_INTSTAT0		0x000
+#define S6_DMA_INTSTAT1		0x004
+#define S6_DMA_INTENABLE0	0x008
+#define S6_DMA_INTENABLE1	0x00C
+#define S6_DMA_INTRAW0		0x010
+#define S6_DMA_INTRAW1		0x014
+#define S6_DMA_INTCLEAR0	0x018
+#define S6_DMA_INTCLEAR1	0x01C
+#define S6_DMA_INTSET0		0x020
+#define S6_DMA_INTSET1		0x024
+#define S6_DMA_INT0_UNDER		0
+#define S6_DMA_INT0_OVER		16
+#define S6_DMA_INT1_CHANNEL		0
+#define S6_DMA_INT1_MASTER		16
+#define S6_DMA_INT1_MASTER_MASK			7
+#define S6_DMA_TERMCNTIRQSTAT	0x028
+#define S6_DMA_TERMCNTIRQCLR	0x02C
+#define S6_DMA_TERMCNTIRQSET	0x030
+#define S6_DMA_PENDCNTIRQSTAT	0x034
+#define S6_DMA_PENDCNTIRQCLR	0x038
+#define S6_DMA_PENDCNTIRQSET	0x03C
+#define S6_DMA_LOWWMRKIRQSTAT	0x040
+#define S6_DMA_LOWWMRKIRQCLR	0x044
+#define S6_DMA_LOWWMRKIRQSET	0x048
+#define S6_DMA_MASTERERRINFO	0x04C
+#define S6_DMA_MASTERERR_CHAN(n)	(4*(n))
+#define S6_DMA_MASTERERR_CHAN_MASK		0xF
+#define S6_DMA_DESCRFIFO0	0x050
+#define S6_DMA_DESCRFIFO1	0x054
+#define S6_DMA_DESCRFIFO2	0x058
+#define S6_DMA_DESCRFIFO2_AUTODISABLE	24
+#define S6_DMA_DESCRFIFO3	0x05C
+#define S6_DMA_MASTER0START	0x060
+#define S6_DMA_MASTER0END	0x064
+#define S6_DMA_MASTER1START	0x068
+#define S6_DMA_MASTER1END	0x06C
+#define S6_DMA_NEXTFREE		0x070
+#define S6_DMA_NEXTFREE_CHAN		0
+#define S6_DMA_NEXTFREE_CHAN_MASK	0x1F
+#define S6_DMA_NEXTFREE_ENA		16
+#define S6_DMA_NEXTFREE_ENA_MASK	((1 << 16) - 1)
+#define S6_DMA_DPORTCTRLGRP(p)	((p) * 4 + 0x074)
+#define S6_DMA_DPORTCTRLGRP_FRAMEREP	0
+#define S6_DMA_DPORTCTRLGRP_NRCHANS	1
+#define S6_DMA_DPORTCTRLGRP_NRCHANS_1		0
+#define S6_DMA_DPORTCTRLGRP_NRCHANS_3		1
+#define S6_DMA_DPORTCTRLGRP_NRCHANS_4		2
+#define S6_DMA_DPORTCTRLGRP_NRCHANS_2		3
+#define S6_DMA_DPORTCTRLGRP_ENA		31
+
+
+/* DMA per channel */
+
+#define DMA_CHNL(dmac, n)	((dmac) + 0x1000 + (n) * 0x100)
+#define DMA_INDEX_CHNL(addr)	(((addr) >> 8) & 0xF)
+#define DMA_MASK_DMAC(addr)	((addr) & 0xFFFF0000)
+#define S6_DMA_CHNCTRL		0x000
+#define S6_DMA_CHNCTRL_ENABLE		0
+#define S6_DMA_CHNCTRL_PAUSE		1
+#define S6_DMA_CHNCTRL_PRIO		2
+#define S6_DMA_CHNCTRL_PRIO_MASK		3
+#define S6_DMA_CHNCTRL_PERIPHXFER	4
+#define S6_DMA_CHNCTRL_PERIPHENA	5
+#define S6_DMA_CHNCTRL_SRCINC		6
+#define S6_DMA_CHNCTRL_DSTINC		7
+#define S6_DMA_CHNCTRL_BURSTLOG		8
+#define S6_DMA_CHNCTRL_BURSTLOG_MASK		7
+#define S6_DMA_CHNCTRL_DESCFIFODEPTH	12
+#define S6_DMA_CHNCTRL_DESCFIFODEPTH_MASK	0x1F
+#define S6_DMA_CHNCTRL_DESCFIFOFULL	17
+#define S6_DMA_CHNCTRL_BWCONSEL		18
+#define S6_DMA_CHNCTRL_BWCONENA		19
+#define S6_DMA_CHNCTRL_PENDGCNTSTAT	20
+#define S6_DMA_CHNCTRL_PENDGCNTSTAT_MASK	0x3F
+#define S6_DMA_CHNCTRL_LOWWMARK		26
+#define S6_DMA_CHNCTRL_LOWWMARK_MASK		0xF
+#define S6_DMA_CHNCTRL_TSTAMP		30
+#define S6_DMA_TERMCNTNB	0x004
+#define S6_DMA_TERMCNTNB_MASK			0xFFFF
+#define S6_DMA_TERMCNTTMO	0x008
+#define S6_DMA_TERMCNTSTAT	0x00C
+#define S6_DMA_TERMCNTSTAT_MASK		0xFF
+#define S6_DMA_CMONCHUNK	0x010
+#define S6_DMA_SRCSKIP		0x014
+#define S6_DMA_DSTSKIP		0x018
+#define S6_DMA_CUR_SRC		0x024
+#define S6_DMA_CUR_DST		0x028
+#define S6_DMA_TIMESTAMP	0x030
+
+/* DMA channel lists */
+
+#define S6_DPDMA_CHAN(stream, channel)	(4 * (stream) + (channel))
+#define S6_DPDMA_NB	16
+
+#define S6_HIFDMA_GMACTX	0
+#define S6_HIFDMA_GMACRX	1
+#define S6_HIFDMA_I2S0		2
+#define S6_HIFDMA_I2S1		3
+#define S6_HIFDMA_EGIB		4
+#define S6_HIFDMA_PCITX		5
+#define S6_HIFDMA_PCIRX		6
+#define S6_HIFDMA_NB	7
+
+#define S6_NIDMA_NB	4
+
+#define S6_LMSDMA_NB	12
+
+/* controller access */
+
+#define S6_DMAC_NB	4
+#define S6_DMAC_INDEX(dmac)	(((unsigned)(dmac) >> 18) % S6_DMAC_NB)
+
+struct s6dmac_ctrl {
+	u32 dmac;
+	spinlock_t lock;
+	u8 chan_nb;
+};
+
+extern struct s6dmac_ctrl s6dmac_ctrl[S6_DMAC_NB];
+
+
+/* DMA control, per channel */
+
+static inline int s6dmac_fifo_full(u32 dmac, int chan)
+{
+	return (readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL)
+		& (1 << S6_DMA_CHNCTRL_DESCFIFOFULL)) && 1;
+}
+
+static inline int s6dmac_termcnt_irq(u32 dmac, int chan)
+{
+	u32 m = 1 << chan;
+	int r = (readl(dmac + S6_DMA_TERMCNTIRQSTAT) & m) && 1;
+	if (r)
+		writel(m, dmac + S6_DMA_TERMCNTIRQCLR);
+	return r;
+}
+
+static inline int s6dmac_pendcnt_irq(u32 dmac, int chan)
+{
+	u32 m = 1 << chan;
+	int r = (readl(dmac + S6_DMA_PENDCNTIRQSTAT) & m) && 1;
+	if (r)
+		writel(m, dmac + S6_DMA_PENDCNTIRQCLR);
+	return r;
+}
+
+static inline int s6dmac_lowwmark_irq(u32 dmac, int chan)
+{
+	int r = (readl(dmac + S6_DMA_LOWWMRKIRQSTAT) & (1 << chan)) ? 1 : 0;
+	if (r)
+		writel(1 << chan, dmac + S6_DMA_LOWWMRKIRQCLR);
+	return r;
+}
+
+static inline u32 s6dmac_pending_count(u32 dmac, int chan)
+{
+	return (readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL)
+			>> S6_DMA_CHNCTRL_PENDGCNTSTAT)
+		& S6_DMA_CHNCTRL_PENDGCNTSTAT_MASK;
+}
+
+static inline void s6dmac_set_terminal_count(u32 dmac, int chan, u32 n)
+{
+	n &= S6_DMA_TERMCNTNB_MASK;
+	n |= readl(DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB)
+	      & ~S6_DMA_TERMCNTNB_MASK;
+	writel(n, DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB);
+}
+
+static inline u32 s6dmac_get_terminal_count(u32 dmac, int chan)
+{
+	return (readl(DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB))
+		& S6_DMA_TERMCNTNB_MASK;
+}
+
+static inline u32 s6dmac_timestamp(u32 dmac, int chan)
+{
+	return readl(DMA_CHNL(dmac, chan) + S6_DMA_TIMESTAMP);
+}
+
+static inline u32 s6dmac_cur_src(u32 dmac, int chan)
+{
+	return readl(DMA_CHNL(dmac, chan) + S6_DMA_CUR_SRC);
+}
+
+static inline u32 s6dmac_cur_dst(u32 dmac, int chan)
+{
+	return readl(DMA_CHNL(dmac, chan) + S6_DMA_CUR_DST);
+}
+
+static inline void s6dmac_disable_chan(u32 dmac, int chan)
+{
+	u32 ctrl;
+	writel(readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL)
+		& ~(1 << S6_DMA_CHNCTRL_ENABLE),
+		DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
+	do
+		ctrl = readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
+	while (ctrl & (1 << S6_DMA_CHNCTRL_ENABLE));
+}
+
+static inline void s6dmac_set_stride_skip(u32 dmac, int chan,
+	int comchunk,		/* 0: disable scatter/gather */
+	int srcskip, int dstskip)
+{
+	writel(comchunk, DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
+	writel(srcskip, DMA_CHNL(dmac, chan) + S6_DMA_SRCSKIP);
+	writel(dstskip, DMA_CHNL(dmac, chan) + S6_DMA_DSTSKIP);
+}
+
+static inline void s6dmac_enable_chan(u32 dmac, int chan,
+	int prio,               /* 0 (highest) .. 3 (lowest) */
+	int periphxfer,         /* <0: disable p.req.line, 0..1: mode */
+	int srcinc, int dstinc, /* 0: dont increment src/dst address */
+	int comchunk,		/* 0: disable scatter/gather */
+	int srcskip, int dstskip,
+	int burstsize,		/* 4 for I2S, 7 for everything else */
+	int bandwidthconserve,  /* <0: disable, 0..1: select */
+	int lowwmark,           /* 0..15 */
+	int timestamp,		/* 0: disable timestamp */
+	int enable)		/* 0: disable for now */
+{
+	writel(1, DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB);
+	writel(0, DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTTMO);
+	writel(lowwmark << S6_DMA_CHNCTRL_LOWWMARK,
+		DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
+	s6dmac_set_stride_skip(dmac, chan, comchunk, srcskip, dstskip);
+	writel(((enable ? 1 : 0) << S6_DMA_CHNCTRL_ENABLE) |
+		(prio << S6_DMA_CHNCTRL_PRIO) |
+		(((periphxfer > 0) ? 1 : 0) << S6_DMA_CHNCTRL_PERIPHXFER) |
+		(((periphxfer < 0) ? 0 : 1) << S6_DMA_CHNCTRL_PERIPHENA) |
+		((srcinc ? 1 : 0) << S6_DMA_CHNCTRL_SRCINC) |
+		((dstinc ? 1 : 0) << S6_DMA_CHNCTRL_DSTINC) |
+		(burstsize << S6_DMA_CHNCTRL_BURSTLOG) |
+		(((bandwidthconserve > 0) ? 1 : 0) << S6_DMA_CHNCTRL_BWCONSEL) |
+		(((bandwidthconserve < 0) ? 0 : 1) << S6_DMA_CHNCTRL_BWCONENA) |
+		(lowwmark << S6_DMA_CHNCTRL_LOWWMARK) |
+		((timestamp ? 1 : 0) << S6_DMA_CHNCTRL_TSTAMP),
+		DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
+}
+
+
+/* DMA control, per engine */
+
+static inline unsigned _dmac_addr_index(u32 dmac)
+{
+	unsigned i = S6_DMAC_INDEX(dmac);
+	if (s6dmac_ctrl[i].dmac != dmac)
+		BUG();
+	return i;
+}
+
+static inline void _s6dmac_disable_error_irqs(u32 dmac, u32 mask)
+{
+	writel(mask, dmac + S6_DMA_TERMCNTIRQCLR);
+	writel(mask, dmac + S6_DMA_PENDCNTIRQCLR);
+	writel(mask, dmac + S6_DMA_LOWWMRKIRQCLR);
+	writel(readl(dmac + S6_DMA_INTENABLE0)
+		& ~((mask << S6_DMA_INT0_UNDER) | (mask << S6_DMA_INT0_OVER)),
+		dmac + S6_DMA_INTENABLE0);
+	writel(readl(dmac + S6_DMA_INTENABLE1) & ~(mask << S6_DMA_INT1_CHANNEL),
+		dmac + S6_DMA_INTENABLE1);
+	writel((mask << S6_DMA_INT0_UNDER) | (mask << S6_DMA_INT0_OVER),
+		dmac + S6_DMA_INTCLEAR0);
+	writel(mask << S6_DMA_INT1_CHANNEL, dmac + S6_DMA_INTCLEAR1);
+}
+
+/*
+ * request channel from specified engine
+ * with chan<0, accept any channel
+ * further parameters see s6dmac_enable_chan
+ * returns < 0 upon error, channel nb otherwise
+ */
+static inline int s6dmac_request_chan(u32 dmac, int chan,
+	int prio,
+	int periphxfer,
+	int srcinc, int dstinc,
+	int comchunk,
+	int srcskip, int dstskip,
+	int burstsize,
+	int bandwidthconserve,
+	int lowwmark,
+	int timestamp,
+	int enable)
+{
+	int r = chan;
+	unsigned long flags;
+	spinlock_t *spinl = &s6dmac_ctrl[_dmac_addr_index(dmac)].lock;
+	spin_lock_irqsave(spinl, flags);
+	if (r < 0) {
+		r = (readl(dmac + S6_DMA_NEXTFREE) >> S6_DMA_NEXTFREE_CHAN)
+			& S6_DMA_NEXTFREE_CHAN_MASK;
+	}
+	if (r >= s6dmac_ctrl[_dmac_addr_index(dmac)].chan_nb) {
+		if (chan < 0)
+			r = -EBUSY;
+		else
+			r = -ENXIO;
+	} else if (((readl(dmac + S6_DMA_NEXTFREE) >> S6_DMA_NEXTFREE_ENA)
+			>> r) & 1) {
+		r = -EBUSY;
+	} else {
+		s6dmac_enable_chan(dmac, r, prio, periphxfer,
+			srcinc, dstinc, comchunk, srcskip, dstskip, burstsize,
+			bandwidthconserve, lowwmark, timestamp, enable);
+	}
+	spin_unlock_irqrestore(spinl, flags);
+	return r;
+}
+
+static inline void s6dmac_put_fifo(u32 dmac, int chan,
+	u32 src, u32 dst, u32 size)
+{
+	unsigned long flags;
+	spinlock_t *spinl = &s6dmac_ctrl[_dmac_addr_index(dmac)].lock;
+	spin_lock_irqsave(spinl, flags);
+	writel(src, dmac + S6_DMA_DESCRFIFO0);
+	writel(dst, dmac + S6_DMA_DESCRFIFO1);
+	writel(size, dmac + S6_DMA_DESCRFIFO2);
+	writel(chan, dmac + S6_DMA_DESCRFIFO3);
+	spin_unlock_irqrestore(spinl, flags);
+}
+
+static inline u32 s6dmac_channel_enabled(u32 dmac, int chan)
+{
+	return readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL) &
+			(1 << S6_DMA_CHNCTRL_ENABLE);
+}
+
+/*
+ * group 1-4 data port channels
+ * with port=0..3, nrch=1-4 channels,
+ * frrep=0/1 (dis- or enable frame repeat)
+ */
+static inline void s6dmac_dp_setup_group(u32 dmac, int port,
+			int nrch, int frrep)
+{
+	const static u8 mask[4] = {0, 3, 1, 2};
+	BUG_ON(dmac != S6_REG_DPDMA);
+	if ((port < 0) || (port > 3) || (nrch < 1) || (nrch > 4))
+		return;
+	writel((mask[nrch - 1] << S6_DMA_DPORTCTRLGRP_NRCHANS)
+		| ((frrep ? 1 : 0) << S6_DMA_DPORTCTRLGRP_FRAMEREP),
+		dmac + S6_DMA_DPORTCTRLGRP(port));
+}
+
+static inline void s6dmac_dp_switch_group(u32 dmac, int port, int enable)
+{
+	u32 tmp;
+	BUG_ON(dmac != S6_REG_DPDMA);
+	tmp = readl(dmac + S6_DMA_DPORTCTRLGRP(port));
+	if (enable)
+		tmp |= (1 << S6_DMA_DPORTCTRLGRP_ENA);
+	else
+		tmp &= ~(1 << S6_DMA_DPORTCTRLGRP_ENA);
+	writel(tmp, dmac + S6_DMA_DPORTCTRLGRP(port));
+}
+
+extern void s6dmac_put_fifo_cache(u32 dmac, int chan,
+	u32 src, u32 dst, u32 size);
+extern void s6dmac_disable_error_irqs(u32 dmac, u32 mask);
+extern u32 s6dmac_int_sources(u32 dmac, u32 channel);
+extern void s6dmac_release_chan(u32 dmac, int chan);
+
+#endif /* __ASM_XTENSA_S6000_DMAC_H */
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/include/variant/gpio.h linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/include/variant/gpio.h
--- linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/include/variant/gpio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/include/variant/gpio.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 #ifndef _XTENSA_VARIANT_S6000_GPIO_H
 #define _XTENSA_VARIANT_S6000_GPIO_H
 
-extern int s6_gpio_init(void);
+extern int s6_gpio_init(u32 afsel);
 
 #endif /* _XTENSA_VARIANT_S6000_GPIO_H */
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/include/variant/irq.h linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/include/variant/irq.h
--- linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/include/variant/irq.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/include/variant/irq.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,9 +1,9 @@
-#ifndef __XTENSA_S6000_IRQ_H
-#define __XTENSA_S6000_IRQ_H
+#ifndef _XTENSA_S6000_IRQ_H
+#define _XTENSA_S6000_IRQ_H
 
 #define NO_IRQ		(-1)
+#define VARIANT_NR_IRQS 8 /* GPIO interrupts */
 
 extern void variant_irq_enable(unsigned int irq);
-extern void variant_irq_disable(unsigned int irq);
 
 #endif /* __XTENSA_S6000_IRQ_H */
diff -druN linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/Makefile linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/Makefile
--- linux-libre-2.6.30-gnu/arch/xtensa/variants/s6000/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/arch/xtensa/variants/s6000/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,4 @@
 # s6000 Makefile
 
-obj-y		+= irq.o gpio.o
+obj-y		+= irq.o gpio.o dmac.o
 obj-$(CONFIG_XTENSA_CALIBRATE_CCOUNT)	+= delay.o
diff -druN linux-libre-2.6.30-gnu/block/as-iosched.c linux-libre-2.6.31-gnu/block/as-iosched.c
--- linux-libre-2.6.30-gnu/block/as-iosched.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/as-iosched.c	2009-09-09 18:13:59.000000000 -0400
@@ -306,8 +306,8 @@
 	data_dir = rq_is_sync(rq1);
 
 	last = ad->last_sector[data_dir];
-	s1 = rq1->sector;
-	s2 = rq2->sector;
+	s1 = blk_rq_pos(rq1);
+	s2 = blk_rq_pos(rq2);
 
 	BUG_ON(data_dir != rq_is_sync(rq2));
 
@@ -566,13 +566,15 @@
 			as_update_thinktime(ad, aic, thinktime);
 
 			/* Calculate read -> read seek distance */
-			if (aic->last_request_pos < rq->sector)
-				seek_dist = rq->sector - aic->last_request_pos;
+			if (aic->last_request_pos < blk_rq_pos(rq))
+				seek_dist = blk_rq_pos(rq) -
+					    aic->last_request_pos;
 			else
-				seek_dist = aic->last_request_pos - rq->sector;
+				seek_dist = aic->last_request_pos -
+					    blk_rq_pos(rq);
 			as_update_seekdist(ad, aic, seek_dist);
 		}
-		aic->last_request_pos = rq->sector + rq->nr_sectors;
+		aic->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
 		set_bit(AS_TASK_IOSTARTED, &aic->state);
 		spin_unlock(&aic->lock);
 	}
@@ -587,7 +589,7 @@
 {
 	unsigned long delay;	/* jiffies */
 	sector_t last = ad->last_sector[ad->batch_data_dir];
-	sector_t next = rq->sector;
+	sector_t next = blk_rq_pos(rq);
 	sector_t delta; /* acceptable close offset (in sectors) */
 	sector_t s;
 
@@ -981,7 +983,7 @@
 	 * This has to be set in order to be correctly updated by
 	 * as_find_next_rq
 	 */
-	ad->last_sector[data_dir] = rq->sector + rq->nr_sectors;
+	ad->last_sector[data_dir] = blk_rq_pos(rq) + blk_rq_sectors(rq);
 
 	if (data_dir == BLK_RW_SYNC) {
 		struct io_context *ioc = RQ_IOC(rq);
@@ -1312,12 +1314,8 @@
 static void as_work_handler(struct work_struct *work)
 {
 	struct as_data *ad = container_of(work, struct as_data, antic_work);
-	struct request_queue *q = ad->q;
-	unsigned long flags;
 
-	spin_lock_irqsave(q->queue_lock, flags);
-	blk_start_queueing(q);
-	spin_unlock_irqrestore(q->queue_lock, flags);
+	blk_run_queue(ad->q);
 }
 
 static int as_may_queue(struct request_queue *q, int rw)
diff -druN linux-libre-2.6.30-gnu/block/blk-barrier.c linux-libre-2.6.31-gnu/block/blk-barrier.c
--- linux-libre-2.6.30-gnu/block/blk-barrier.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-barrier.c	2009-09-09 18:13:59.000000000 -0400
@@ -106,10 +106,7 @@
 	 */
 	q->ordseq = 0;
 	rq = q->orig_bar_rq;
-
-	if (__blk_end_request(rq, q->orderr, blk_rq_bytes(rq)))
-		BUG();
-
+	__blk_end_request_all(rq, q->orderr);
 	return true;
 }
 
@@ -166,7 +163,7 @@
 	 * For an empty barrier, there's no actual BAR request, which
 	 * in turn makes POSTFLUSH unnecessary.  Mask them off.
 	 */
-	if (!rq->hard_nr_sectors) {
+	if (!blk_rq_sectors(rq)) {
 		q->ordered &= ~(QUEUE_ORDERED_DO_BAR |
 				QUEUE_ORDERED_DO_POSTFLUSH);
 		/*
@@ -183,7 +180,7 @@
 	}
 
 	/* stash away the original request */
-	elv_dequeue_request(q, rq);
+	blk_dequeue_request(rq);
 	q->orig_bar_rq = rq;
 	rq = NULL;
 
@@ -221,7 +218,7 @@
 	} else
 		skip |= QUEUE_ORDSEQ_PREFLUSH;
 
-	if ((q->ordered & QUEUE_ORDERED_BY_DRAIN) && q->in_flight)
+	if ((q->ordered & QUEUE_ORDERED_BY_DRAIN) && queue_in_flight(q))
 		rq = NULL;
 	else
 		skip |= QUEUE_ORDSEQ_DRAIN;
@@ -251,10 +248,8 @@
 			 * Queue ordering not supported.  Terminate
 			 * with prejudice.
 			 */
-			elv_dequeue_request(q, rq);
-			if (__blk_end_request(rq, -EOPNOTSUPP,
-					      blk_rq_bytes(rq)))
-				BUG();
+			blk_dequeue_request(rq);
+			__blk_end_request_all(rq, -EOPNOTSUPP);
 			*rqp = NULL;
 			return false;
 		}
@@ -329,7 +324,7 @@
 	/*
 	 * The driver must store the error location in ->bi_sector, if
 	 * it supports it. For non-stacked drivers, this should be copied
-	 * from rq->sector.
+	 * from blk_rq_pos(rq).
 	 */
 	if (error_sector)
 		*error_sector = bio->bi_sector;
@@ -393,10 +388,10 @@
 
 		bio->bi_sector = sector;
 
-		if (nr_sects > q->max_hw_sectors) {
-			bio->bi_size = q->max_hw_sectors << 9;
-			nr_sects -= q->max_hw_sectors;
-			sector += q->max_hw_sectors;
+		if (nr_sects > queue_max_hw_sectors(q)) {
+			bio->bi_size = queue_max_hw_sectors(q) << 9;
+			nr_sects -= queue_max_hw_sectors(q);
+			sector += queue_max_hw_sectors(q);
 		} else {
 			bio->bi_size = nr_sects << 9;
 			nr_sects = 0;
diff -druN linux-libre-2.6.30-gnu/block/blk-core.c linux-libre-2.6.31-gnu/block/blk-core.c
--- linux-libre-2.6.30-gnu/block/blk-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,24 +26,15 @@
 #include <linux/swap.h>
 #include <linux/writeback.h>
 #include <linux/task_io_accounting_ops.h>
-#include <linux/blktrace_api.h>
 #include <linux/fault-inject.h>
-#include <trace/block.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/block.h>
 
 #include "blk.h"
 
-DEFINE_TRACE(block_plug);
-DEFINE_TRACE(block_unplug_io);
-DEFINE_TRACE(block_unplug_timer);
-DEFINE_TRACE(block_getrq);
-DEFINE_TRACE(block_sleeprq);
-DEFINE_TRACE(block_rq_requeue);
-DEFINE_TRACE(block_bio_backmerge);
-DEFINE_TRACE(block_bio_frontmerge);
-DEFINE_TRACE(block_bio_queue);
-DEFINE_TRACE(block_rq_complete);
-DEFINE_TRACE(block_remap);	/* Also used in drivers/md/dm.c */
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_remap);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 
 static int __make_request(struct request_queue *q, struct bio *bio);
 
@@ -68,11 +59,11 @@
 	int rw = rq_data_dir(rq);
 	int cpu;
 
-	if (!blk_fs_request(rq) || !blk_do_io_stat(rq))
+	if (!blk_do_io_stat(rq))
 		return;
 
 	cpu = part_stat_lock();
-	part = disk_map_sector_rcu(rq->rq_disk, rq->sector);
+	part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 
 	if (!new_io)
 		part_stat_inc(cpu, part, merges[rw]);
@@ -127,13 +118,14 @@
 	INIT_LIST_HEAD(&rq->timeout_list);
 	rq->cpu = -1;
 	rq->q = q;
-	rq->sector = rq->hard_sector = (sector_t) -1;
+	rq->__sector = (sector_t) -1;
 	INIT_HLIST_NODE(&rq->hash);
 	RB_CLEAR_NODE(&rq->rb_node);
 	rq->cmd = rq->__cmd;
 	rq->cmd_len = BLK_MAX_CDB;
 	rq->tag = -1;
 	rq->ref_count = 1;
+	rq->start_time = jiffies;
 }
 EXPORT_SYMBOL(blk_rq_init);
 
@@ -184,14 +176,11 @@
 		rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->cmd_type,
 		rq->cmd_flags);
 
-	printk(KERN_INFO "  sector %llu, nr/cnr %lu/%u\n",
-						(unsigned long long)rq->sector,
-						rq->nr_sectors,
-						rq->current_nr_sectors);
-	printk(KERN_INFO "  bio %p, biotail %p, buffer %p, data %p, len %u\n",
-						rq->bio, rq->biotail,
-						rq->buffer, rq->data,
-						rq->data_len);
+	printk(KERN_INFO "  sector %llu, nr/cnr %u/%u\n",
+	       (unsigned long long)blk_rq_pos(rq),
+	       blk_rq_sectors(rq), blk_rq_cur_sectors(rq));
+	printk(KERN_INFO "  bio %p, biotail %p, buffer %p, len %u\n",
+	       rq->bio, rq->biotail, rq->buffer, blk_rq_bytes(rq));
 
 	if (blk_pc_request(rq)) {
 		printk(KERN_INFO "  cdb: ");
@@ -333,24 +322,6 @@
 }
 EXPORT_SYMBOL(blk_unplug);
 
-static void blk_invoke_request_fn(struct request_queue *q)
-{
-	if (unlikely(blk_queue_stopped(q)))
-		return;
-
-	/*
-	 * one level of recursion is ok and is much faster than kicking
-	 * the unplug handling
-	 */
-	if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
-		q->request_fn(q);
-		queue_flag_clear(QUEUE_FLAG_REENTER, q);
-	} else {
-		queue_flag_set(QUEUE_FLAG_PLUGGED, q);
-		kblockd_schedule_work(q, &q->unplug_work);
-	}
-}
-
 /**
  * blk_start_queue - restart a previously stopped queue
  * @q:    The &struct request_queue in question
@@ -365,7 +336,7 @@
 	WARN_ON(!irqs_disabled());
 
 	queue_flag_clear(QUEUE_FLAG_STOPPED, q);
-	blk_invoke_request_fn(q);
+	__blk_run_queue(q);
 }
 EXPORT_SYMBOL(blk_start_queue);
 
@@ -425,12 +396,23 @@
 {
 	blk_remove_plug(q);
 
+	if (unlikely(blk_queue_stopped(q)))
+		return;
+
+	if (elv_queue_empty(q))
+		return;
+
 	/*
 	 * Only recurse once to avoid overrunning the stack, let the unplug
 	 * handling reinvoke the handler shortly if we already got there.
 	 */
-	if (!elv_queue_empty(q))
-		blk_invoke_request_fn(q);
+	if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
+		q->request_fn(q);
+		queue_flag_clear(QUEUE_FLAG_REENTER, q);
+	} else {
+		queue_flag_set(QUEUE_FLAG_PLUGGED, q);
+		kblockd_schedule_work(q, &q->unplug_work);
+	}
 }
 EXPORT_SYMBOL(__blk_run_queue);
 
@@ -440,9 +422,7 @@
  *
  * Description:
  *    Invoke request handling on this queue, if it has pending work to do.
- *    May be used to restart queueing when a request has completed. Also
- *    See @blk_start_queueing.
- *
+ *    May be used to restart queueing when a request has completed.
  */
 void blk_run_queue(struct request_queue *q)
 {
@@ -517,6 +497,11 @@
 
 	q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug;
 	q->backing_dev_info.unplug_io_data = q;
+	q->backing_dev_info.ra_pages =
+			(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
+	q->backing_dev_info.state = 0;
+	q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
+
 	err = bdi_init(&q->backing_dev_info);
 	if (err) {
 		kmem_cache_free(blk_requestq_cachep, q);
@@ -590,13 +575,6 @@
 		return NULL;
 	}
 
-	/*
-	 * if caller didn't supply a lock, they get per-queue locking with
-	 * our embedded lock
-	 */
-	if (!lock)
-		lock = &q->__queue_lock;
-
 	q->request_fn		= rfn;
 	q->prep_rq_fn		= NULL;
 	q->unplug_fn		= generic_unplug_device;
@@ -610,8 +588,6 @@
 
 	q->sg_reserved_size = INT_MAX;
 
-	blk_set_cmd_filter_defaults(&q->cmd_filter);
-
 	/*
 	 * all done
 	 */
@@ -902,26 +878,59 @@
 EXPORT_SYMBOL(blk_get_request);
 
 /**
- * blk_start_queueing - initiate dispatch of requests to device
- * @q:		request queue to kick into gear
+ * blk_make_request - given a bio, allocate a corresponding struct request.
+ * @q: target request queue
+ * @bio:  The bio describing the memory mappings that will be submitted for IO.
+ *        It may be a chained-bio properly constructed by block/bio layer.
+ * @gfp_mask: gfp flags to be used for memory allocation
  *
- * This is basically a helper to remove the need to know whether a queue
- * is plugged or not if someone just wants to initiate dispatch of requests
- * for this queue. Should be used to start queueing on a device outside
- * of ->request_fn() context. Also see @blk_run_queue.
+ * blk_make_request is the parallel of generic_make_request for BLOCK_PC
+ * type commands. Where the struct request needs to be farther initialized by
+ * the caller. It is passed a &struct bio, which describes the memory info of
+ * the I/O transfer.
  *
- * The queue lock must be held with interrupts disabled.
+ * The caller of blk_make_request must make sure that bi_io_vec
+ * are set to describe the memory buffers. That bio_data_dir() will return
+ * the needed direction of the request. (And all bio's in the passed bio-chain
+ * are properly set accordingly)
+ *
+ * If called under none-sleepable conditions, mapped bio buffers must not
+ * need bouncing, by calling the appropriate masked or flagged allocator,
+ * suitable for the target device. Otherwise the call to blk_queue_bounce will
+ * BUG.
+ *
+ * WARNING: When allocating/cloning a bio-chain, careful consideration should be
+ * given to how you allocate bios. In particular, you cannot use __GFP_WAIT for
+ * anything but the first bio in the chain. Otherwise you risk waiting for IO
+ * completion of a bio that hasn't been submitted yet, thus resulting in a
+ * deadlock. Alternatively bios should be allocated using bio_kmalloc() instead
+ * of bio_alloc(), as that avoids the mempool deadlock.
+ * If possible a big IO should be split into smaller parts when allocation
+ * fails. Partial allocation should not be an error, or you risk a live-lock.
  */
-void blk_start_queueing(struct request_queue *q)
+struct request *blk_make_request(struct request_queue *q, struct bio *bio,
+				 gfp_t gfp_mask)
 {
-	if (!blk_queue_plugged(q)) {
-		if (unlikely(blk_queue_stopped(q)))
-			return;
-		q->request_fn(q);
-	} else
-		__generic_unplug_device(q);
+	struct request *rq = blk_get_request(q, bio_data_dir(bio), gfp_mask);
+
+	if (unlikely(!rq))
+		return ERR_PTR(-ENOMEM);
+
+	for_each_bio(bio) {
+		struct bio *bounce_bio = bio;
+		int ret;
+
+		blk_queue_bounce(q, &bounce_bio);
+		ret = blk_rq_append_bio(q, rq, bounce_bio);
+		if (unlikely(ret)) {
+			blk_put_request(rq);
+			return ERR_PTR(ret);
+		}
+	}
+
+	return rq;
 }
-EXPORT_SYMBOL(blk_start_queueing);
+EXPORT_SYMBOL(blk_make_request);
 
 /**
  * blk_requeue_request - put a request back on queue
@@ -942,6 +951,8 @@
 	if (blk_rq_tagged(rq))
 		blk_queue_end_tag(q, rq);
 
+	BUG_ON(blk_queued_rq(rq));
+
 	elv_requeue_request(q, rq);
 }
 EXPORT_SYMBOL(blk_requeue_request);
@@ -977,7 +988,6 @@
 	 * barrier
 	 */
 	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->cmd_flags |= REQ_SOFTBARRIER;
 
 	rq->special = data;
 
@@ -991,7 +1001,7 @@
 
 	drive_stat_acct(rq, 1);
 	__elv_add_request(q, rq, where, 0);
-	blk_start_queueing(q);
+	__blk_run_queue(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_insert_request);
@@ -1113,16 +1123,13 @@
 	if (bio_failfast_driver(bio))
 		req->cmd_flags |= REQ_FAILFAST_DRIVER;
 
-	/*
-	 * REQ_BARRIER implies no merging, but lets make it explicit
-	 */
 	if (unlikely(bio_discard(bio))) {
 		req->cmd_flags |= REQ_DISCARD;
 		if (bio_barrier(bio))
 			req->cmd_flags |= REQ_SOFTBARRIER;
 		req->q->prepare_discard_fn(req->q, req);
 	} else if (unlikely(bio_barrier(bio)))
-		req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
+		req->cmd_flags |= REQ_HARDBARRIER;
 
 	if (bio_sync(bio))
 		req->cmd_flags |= REQ_RW_SYNC;
@@ -1132,9 +1139,8 @@
 		req->cmd_flags |= REQ_NOIDLE;
 
 	req->errors = 0;
-	req->hard_sector = req->sector = bio->bi_sector;
+	req->__sector = bio->bi_sector;
 	req->ioprio = bio_prio(bio);
-	req->start_time = jiffies;
 	blk_rq_bio_prep(req->q, req, bio);
 }
 
@@ -1150,14 +1156,18 @@
 static int __make_request(struct request_queue *q, struct bio *bio)
 {
 	struct request *req;
-	int el_ret, nr_sectors;
+	int el_ret;
+	unsigned int bytes = bio->bi_size;
 	const unsigned short prio = bio_prio(bio);
 	const int sync = bio_sync(bio);
 	const int unplug = bio_unplug(bio);
 	int rw_flags;
 
-	nr_sectors = bio_sectors(bio);
-
+	if (bio_barrier(bio) && bio_has_data(bio) &&
+	    (q->next_ordered == QUEUE_ORDERED_NONE)) {
+		bio_endio(bio, -EOPNOTSUPP);
+		return 0;
+	}
 	/*
 	 * low level driver can indicate that it wants pages above a
 	 * certain limit bounced to low memory (ie for highmem, or even
@@ -1182,7 +1192,7 @@
 
 		req->biotail->bi_next = bio;
 		req->biotail = bio;
-		req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+		req->__data_len += bytes;
 		req->ioprio = ioprio_best(req->ioprio, prio);
 		if (!blk_rq_cpu_valid(req))
 			req->cpu = bio->bi_comp_cpu;
@@ -1208,10 +1218,8 @@
 		 * not touch req->buffer either...
 		 */
 		req->buffer = bio_data(bio);
-		req->current_nr_sectors = bio_cur_sectors(bio);
-		req->hard_cur_sectors = req->current_nr_sectors;
-		req->sector = req->hard_sector = bio->bi_sector;
-		req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+		req->__sector = bio->bi_sector;
+		req->__data_len += bytes;
 		req->ioprio = ioprio_best(req->ioprio, prio);
 		if (!blk_rq_cpu_valid(req))
 			req->cpu = bio->bi_comp_cpu;
@@ -1277,7 +1285,7 @@
 		bio->bi_bdev = bdev->bd_contains;
 
 		trace_block_remap(bdev_get_queue(bio->bi_bdev), bio,
-				    bdev->bd_dev, bio->bi_sector,
+				    bdev->bd_dev,
 				    bio->bi_sector - p->start_sect);
 	}
 }
@@ -1422,11 +1430,11 @@
 			goto end_io;
 		}
 
-		if (unlikely(nr_sectors > q->max_hw_sectors)) {
+		if (unlikely(nr_sectors > queue_max_hw_sectors(q))) {
 			printk(KERN_ERR "bio too big device %s (%u > %u)\n",
-				bdevname(bio->bi_bdev, b),
-				bio_sectors(bio),
-				q->max_hw_sectors);
+			       bdevname(bio->bi_bdev, b),
+			       bio_sectors(bio),
+			       queue_max_hw_sectors(q));
 			goto end_io;
 		}
 
@@ -1446,8 +1454,7 @@
 			goto end_io;
 
 		if (old_sector != -1)
-			trace_block_remap(q, bio, old_dev, bio->bi_sector,
-					    old_sector);
+			trace_block_remap(q, bio, old_dev, old_sector);
 
 		trace_block_bio_queue(q, bio);
 
@@ -1461,11 +1468,6 @@
 			err = -EOPNOTSUPP;
 			goto end_io;
 		}
-		if (bio_barrier(bio) && bio_has_data(bio) &&
-		    (q->next_ordered == QUEUE_ORDERED_NONE)) {
-			err = -EOPNOTSUPP;
-			goto end_io;
-		}
 
 		ret = q->make_request_fn(q, bio);
 	} while (ret);
@@ -1593,8 +1595,8 @@
  */
 int blk_rq_check_limits(struct request_queue *q, struct request *rq)
 {
-	if (rq->nr_sectors > q->max_sectors ||
-	    rq->data_len > q->max_hw_sectors << 9) {
+	if (blk_rq_sectors(rq) > queue_max_sectors(q) ||
+	    blk_rq_bytes(rq) > queue_max_hw_sectors(q) << 9) {
 		printk(KERN_ERR "%s: over max size limit.\n", __func__);
 		return -EIO;
 	}
@@ -1606,8 +1608,8 @@
 	 * limitation.
 	 */
 	blk_recalc_rq_segments(rq);
-	if (rq->nr_phys_segments > q->max_phys_segments ||
-	    rq->nr_phys_segments > q->max_hw_segments) {
+	if (rq->nr_phys_segments > queue_max_phys_segments(q) ||
+	    rq->nr_phys_segments > queue_max_hw_segments(q)) {
 		printk(KERN_ERR "%s: over max segments limit.\n", __func__);
 		return -EIO;
 	}
@@ -1651,40 +1653,15 @@
 }
 EXPORT_SYMBOL_GPL(blk_insert_cloned_request);
 
-/**
- * blkdev_dequeue_request - dequeue request and start timeout timer
- * @req: request to dequeue
- *
- * Dequeue @req and start timeout timer on it.  This hands off the
- * request to the driver.
- *
- * Block internal functions which don't want to start timer should
- * call elv_dequeue_request().
- */
-void blkdev_dequeue_request(struct request *req)
-{
-	elv_dequeue_request(req->q, req);
-
-	/*
-	 * We are now handing the request to the hardware, add the
-	 * timeout handler.
-	 */
-	blk_add_timer(req);
-}
-EXPORT_SYMBOL(blkdev_dequeue_request);
-
 static void blk_account_io_completion(struct request *req, unsigned int bytes)
 {
-	if (!blk_do_io_stat(req))
-		return;
-
-	if (blk_fs_request(req)) {
+	if (blk_do_io_stat(req)) {
 		const int rw = rq_data_dir(req);
 		struct hd_struct *part;
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, req->sector);
+		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 		part_stat_add(cpu, part, sectors[rw], bytes >> 9);
 		part_stat_unlock();
 	}
@@ -1692,22 +1669,19 @@
 
 static void blk_account_io_done(struct request *req)
 {
-	if (!blk_do_io_stat(req))
-		return;
-
 	/*
 	 * Account IO completion.  bar_rq isn't accounted as a normal
 	 * IO on queueing nor completion.  Accounting the containing
 	 * request is enough.
 	 */
-	if (blk_fs_request(req) && req != &req->q->bar_rq) {
+	if (blk_do_io_stat(req) && req != &req->q->bar_rq) {
 		unsigned long duration = jiffies - req->start_time;
 		const int rw = rq_data_dir(req);
 		struct hd_struct *part;
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, req->sector);
+		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 
 		part_stat_inc(cpu, part, ios[rw]);
 		part_stat_add(cpu, part, ticks[rw], duration);
@@ -1719,38 +1693,226 @@
 }
 
 /**
- * __end_that_request_first - end I/O on a request
+ * blk_peek_request - peek at the top of a request queue
+ * @q: request queue to peek at
+ *
+ * Description:
+ *     Return the request at the top of @q.  The returned request
+ *     should be started using blk_start_request() before LLD starts
+ *     processing it.
+ *
+ * Return:
+ *     Pointer to the request at the top of @q if available.  Null
+ *     otherwise.
+ *
+ * Context:
+ *     queue_lock must be held.
+ */
+struct request *blk_peek_request(struct request_queue *q)
+{
+	struct request *rq;
+	int ret;
+
+	while ((rq = __elv_next_request(q)) != NULL) {
+		if (!(rq->cmd_flags & REQ_STARTED)) {
+			/*
+			 * This is the first time the device driver
+			 * sees this request (possibly after
+			 * requeueing).  Notify IO scheduler.
+			 */
+			if (blk_sorted_rq(rq))
+				elv_activate_rq(q, rq);
+
+			/*
+			 * just mark as started even if we don't start
+			 * it, a request that has been delayed should
+			 * not be passed by new incoming requests
+			 */
+			rq->cmd_flags |= REQ_STARTED;
+			trace_block_rq_issue(q, rq);
+		}
+
+		if (!q->boundary_rq || q->boundary_rq == rq) {
+			q->end_sector = rq_end_sector(rq);
+			q->boundary_rq = NULL;
+		}
+
+		if (rq->cmd_flags & REQ_DONTPREP)
+			break;
+
+		if (q->dma_drain_size && blk_rq_bytes(rq)) {
+			/*
+			 * make sure space for the drain appears we
+			 * know we can do this because max_hw_segments
+			 * has been adjusted to be one fewer than the
+			 * device can handle
+			 */
+			rq->nr_phys_segments++;
+		}
+
+		if (!q->prep_rq_fn)
+			break;
+
+		ret = q->prep_rq_fn(q, rq);
+		if (ret == BLKPREP_OK) {
+			break;
+		} else if (ret == BLKPREP_DEFER) {
+			/*
+			 * the request may have been (partially) prepped.
+			 * we need to keep this request in the front to
+			 * avoid resource deadlock.  REQ_STARTED will
+			 * prevent other fs requests from passing this one.
+			 */
+			if (q->dma_drain_size && blk_rq_bytes(rq) &&
+			    !(rq->cmd_flags & REQ_DONTPREP)) {
+				/*
+				 * remove the space for the drain we added
+				 * so that we don't add it again
+				 */
+				--rq->nr_phys_segments;
+			}
+
+			rq = NULL;
+			break;
+		} else if (ret == BLKPREP_KILL) {
+			rq->cmd_flags |= REQ_QUIET;
+			/*
+			 * Mark this request as started so we don't trigger
+			 * any debug logic in the end I/O path.
+			 */
+			blk_start_request(rq);
+			__blk_end_request_all(rq, -EIO);
+		} else {
+			printk(KERN_ERR "%s: bad return=%d\n", __func__, ret);
+			break;
+		}
+	}
+
+	return rq;
+}
+EXPORT_SYMBOL(blk_peek_request);
+
+void blk_dequeue_request(struct request *rq)
+{
+	struct request_queue *q = rq->q;
+
+	BUG_ON(list_empty(&rq->queuelist));
+	BUG_ON(ELV_ON_HASH(rq));
+
+	list_del_init(&rq->queuelist);
+
+	/*
+	 * the time frame between a request being removed from the lists
+	 * and to it is freed is accounted as io that is in progress at
+	 * the driver side.
+	 */
+	if (blk_account_rq(rq))
+		q->in_flight[rq_is_sync(rq)]++;
+}
+
+/**
+ * blk_start_request - start request processing on the driver
+ * @req: request to dequeue
+ *
+ * Description:
+ *     Dequeue @req and start timeout timer on it.  This hands off the
+ *     request to the driver.
+ *
+ *     Block internal functions which don't want to start timer should
+ *     call blk_dequeue_request().
+ *
+ * Context:
+ *     queue_lock must be held.
+ */
+void blk_start_request(struct request *req)
+{
+	blk_dequeue_request(req);
+
+	/*
+	 * We are now handing the request to the hardware, initialize
+	 * resid_len to full count and add the timeout handler.
+	 */
+	req->resid_len = blk_rq_bytes(req);
+	if (unlikely(blk_bidi_rq(req)))
+		req->next_rq->resid_len = blk_rq_bytes(req->next_rq);
+
+	blk_add_timer(req);
+}
+EXPORT_SYMBOL(blk_start_request);
+
+/**
+ * blk_fetch_request - fetch a request from a request queue
+ * @q: request queue to fetch a request from
+ *
+ * Description:
+ *     Return the request at the top of @q.  The request is started on
+ *     return and LLD can start processing it immediately.
+ *
+ * Return:
+ *     Pointer to the request at the top of @q if available.  Null
+ *     otherwise.
+ *
+ * Context:
+ *     queue_lock must be held.
+ */
+struct request *blk_fetch_request(struct request_queue *q)
+{
+	struct request *rq;
+
+	rq = blk_peek_request(q);
+	if (rq)
+		blk_start_request(rq);
+	return rq;
+}
+EXPORT_SYMBOL(blk_fetch_request);
+
+/**
+ * blk_update_request - Special helper function for request stacking drivers
  * @req:      the request being processed
  * @error:    %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete
+ * @nr_bytes: number of bytes to complete @req
  *
  * Description:
- *     Ends I/O on a number of bytes attached to @req, and sets it up
- *     for the next range of segments (if any) in the cluster.
+ *     Ends I/O on a number of bytes attached to @req, but doesn't complete
+ *     the request structure even if @req doesn't have leftover.
+ *     If @req has leftover, sets it up for the next range of segments.
+ *
+ *     This special helper function is only for request stacking drivers
+ *     (e.g. request-based dm) so that they can handle partial completion.
+ *     Actual device drivers should use blk_end_request instead.
+ *
+ *     Passing the result of blk_rq_bytes() as @nr_bytes guarantees
+ *     %false return from this function.
  *
  * Return:
- *     %0 - we are done with this request, call end_that_request_last()
- *     %1 - still buffers pending for this request
+ *     %false - this request doesn't have any more data
+ *     %true  - this request has more data
  **/
-static int __end_that_request_first(struct request *req, int error,
-				    int nr_bytes)
+bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 {
 	int total_bytes, bio_nbytes, next_idx = 0;
 	struct bio *bio;
 
+	if (!req->bio)
+		return false;
+
 	trace_block_rq_complete(req->q, req);
 
 	/*
-	 * for a REQ_TYPE_BLOCK_PC request, we want to carry any eventual
-	 * sense key with us all the way through
+	 * For fs requests, rq is just carrier of independent bio's
+	 * and each partial completion should be handled separately.
+	 * Reset per-request error on each partial completion.
+	 *
+	 * TODO: tj: This is too subtle.  It would be better to let
+	 * low level drivers do what they see fit.
 	 */
-	if (!blk_pc_request(req))
+	if (blk_fs_request(req))
 		req->errors = 0;
 
 	if (error && (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))) {
 		printk(KERN_ERR "end_request: I/O error, dev %s, sector %llu\n",
 				req->rq_disk ? req->rq_disk->disk_name : "?",
-				(unsigned long long)req->sector);
+				(unsigned long long)blk_rq_pos(req));
 	}
 
 	blk_account_io_completion(req, nr_bytes);
@@ -1810,8 +1972,15 @@
 	/*
 	 * completely done
 	 */
-	if (!req->bio)
-		return 0;
+	if (!req->bio) {
+		/*
+		 * Reset counters so that the request stacking driver
+		 * can find how many bytes remain in the request
+		 * later.
+		 */
+		req->__data_len = 0;
+		return false;
+	}
 
 	/*
 	 * if the request wasn't completed, update state
@@ -1823,21 +1992,55 @@
 		bio_iovec(bio)->bv_len -= nr_bytes;
 	}
 
-	blk_recalc_rq_sectors(req, total_bytes >> 9);
+	req->__data_len -= total_bytes;
+	req->buffer = bio_data(req->bio);
+
+	/* update sector only for requests with clear definition of sector */
+	if (blk_fs_request(req) || blk_discard_rq(req))
+		req->__sector += total_bytes >> 9;
+
+	/*
+	 * If total number of sectors is less than the first segment
+	 * size, something has gone terribly wrong.
+	 */
+	if (blk_rq_bytes(req) < blk_rq_cur_bytes(req)) {
+		printk(KERN_ERR "blk: request botched\n");
+		req->__data_len = blk_rq_cur_bytes(req);
+	}
+
+	/* recalculate the number of segments */
 	blk_recalc_rq_segments(req);
-	return 1;
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(blk_update_request);
+
+static bool blk_update_bidi_request(struct request *rq, int error,
+				    unsigned int nr_bytes,
+				    unsigned int bidi_bytes)
+{
+	if (blk_update_request(rq, error, nr_bytes))
+		return true;
+
+	/* Bidi request must be completed as a whole */
+	if (unlikely(blk_bidi_rq(rq)) &&
+	    blk_update_request(rq->next_rq, error, bidi_bytes))
+		return true;
+
+	add_disk_randomness(rq->rq_disk);
+
+	return false;
 }
 
 /*
  * queue lock must be held
  */
-static void end_that_request_last(struct request *req, int error)
+static void blk_finish_request(struct request *req, int error)
 {
 	if (blk_rq_tagged(req))
 		blk_queue_end_tag(req->q, req);
 
-	if (blk_queued_rq(req))
-		elv_dequeue_request(req->q, req);
+	BUG_ON(blk_queued_rq(req));
 
 	if (unlikely(laptop_mode) && blk_fs_request(req))
 		laptop_io_completion();
@@ -1857,117 +2060,62 @@
 }
 
 /**
- * blk_rq_bytes - Returns bytes left to complete in the entire request
- * @rq: the request being processed
- **/
-unsigned int blk_rq_bytes(struct request *rq)
-{
-	if (blk_fs_request(rq))
-		return rq->hard_nr_sectors << 9;
-
-	return rq->data_len;
-}
-EXPORT_SYMBOL_GPL(blk_rq_bytes);
-
-/**
- * blk_rq_cur_bytes - Returns bytes left to complete in the current segment
- * @rq: the request being processed
- **/
-unsigned int blk_rq_cur_bytes(struct request *rq)
-{
-	if (blk_fs_request(rq))
-		return rq->current_nr_sectors << 9;
-
-	if (rq->bio)
-		return rq->bio->bi_size;
-
-	return rq->data_len;
-}
-EXPORT_SYMBOL_GPL(blk_rq_cur_bytes);
-
-/**
- * end_request - end I/O on the current segment of the request
- * @req:	the request being processed
- * @uptodate:	error value or %0/%1 uptodate flag
+ * blk_end_bidi_request - Complete a bidi request
+ * @rq:         the request to complete
+ * @error:      %0 for success, < %0 for error
+ * @nr_bytes:   number of bytes to complete @rq
+ * @bidi_bytes: number of bytes to complete @rq->next_rq
  *
  * Description:
- *     Ends I/O on the current segment of a request. If that is the only
- *     remaining segment, the request is also completed and freed.
+ *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
+ *     Drivers that supports bidi can safely call this member for any
+ *     type of request, bidi or uni.  In the later case @bidi_bytes is
+ *     just ignored.
  *
- *     This is a remnant of how older block drivers handled I/O completions.
- *     Modern drivers typically end I/O on the full request in one go, unless
- *     they have a residual value to account for. For that case this function
- *     isn't really useful, unless the residual just happens to be the
- *     full current segment. In other words, don't use this function in new
- *     code. Use blk_end_request() or __blk_end_request() to end a request.
+ * Return:
+ *     %false - we are done with this request
+ *     %true  - still buffers pending for this request
  **/
-void end_request(struct request *req, int uptodate)
-{
-	int error = 0;
-
-	if (uptodate <= 0)
-		error = uptodate ? uptodate : -EIO;
-
-	__blk_end_request(req, error, req->hard_cur_sectors << 9);
-}
-EXPORT_SYMBOL(end_request);
-
-static int end_that_request_data(struct request *rq, int error,
+static bool blk_end_bidi_request(struct request *rq, int error,
 				 unsigned int nr_bytes, unsigned int bidi_bytes)
 {
-	if (rq->bio) {
-		if (__end_that_request_first(rq, error, nr_bytes))
-			return 1;
+	struct request_queue *q = rq->q;
+	unsigned long flags;
 
-		/* Bidi request must be completed as a whole */
-		if (blk_bidi_rq(rq) &&
-		    __end_that_request_first(rq->next_rq, error, bidi_bytes))
-			return 1;
-	}
+	if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
+		return true;
 
-	return 0;
+	spin_lock_irqsave(q->queue_lock, flags);
+	blk_finish_request(rq, error);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	return false;
 }
 
 /**
- * blk_end_io - Generic end_io function to complete a request.
- * @rq:           the request being processed
- * @error:        %0 for success, < %0 for error
- * @nr_bytes:     number of bytes to complete @rq
- * @bidi_bytes:   number of bytes to complete @rq->next_rq
- * @drv_callback: function called between completion of bios in the request
- *                and completion of the request.
- *                If the callback returns non %0, this helper returns without
- *                completion of the request.
+ * __blk_end_bidi_request - Complete a bidi request with queue lock held
+ * @rq:         the request to complete
+ * @error:      %0 for success, < %0 for error
+ * @nr_bytes:   number of bytes to complete @rq
+ * @bidi_bytes: number of bytes to complete @rq->next_rq
  *
  * Description:
- *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
- *     If @rq has leftover, sets it up for the next range of segments.
+ *     Identical to blk_end_bidi_request() except that queue lock is
+ *     assumed to be locked on entry and remains so on return.
  *
  * Return:
- *     %0 - we are done with this request
- *     %1 - this request is not freed yet, it still has pending buffers.
+ *     %false - we are done with this request
+ *     %true  - still buffers pending for this request
  **/
-static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes,
-		      unsigned int bidi_bytes,
-		      int (drv_callback)(struct request *))
+static bool __blk_end_bidi_request(struct request *rq, int error,
+				   unsigned int nr_bytes, unsigned int bidi_bytes)
 {
-	struct request_queue *q = rq->q;
-	unsigned long flags = 0UL;
-
-	if (end_that_request_data(rq, error, nr_bytes, bidi_bytes))
-		return 1;
-
-	/* Special feature for tricky drivers */
-	if (drv_callback && drv_callback(rq))
-		return 1;
-
-	add_disk_randomness(rq->rq_disk);
+	if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
+		return true;
 
-	spin_lock_irqsave(q->queue_lock, flags);
-	end_that_request_last(rq, error);
-	spin_unlock_irqrestore(q->queue_lock, flags);
+	blk_finish_request(rq, error);
 
-	return 0;
+	return false;
 }
 
 /**
@@ -1981,124 +2129,112 @@
  *     If @rq has leftover, sets it up for the next range of segments.
  *
  * Return:
- *     %0 - we are done with this request
- *     %1 - still buffers pending for this request
+ *     %false - we are done with this request
+ *     %true  - still buffers pending for this request
  **/
-int blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
+bool blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
 {
-	return blk_end_io(rq, error, nr_bytes, 0, NULL);
+	return blk_end_bidi_request(rq, error, nr_bytes, 0);
 }
-EXPORT_SYMBOL_GPL(blk_end_request);
+EXPORT_SYMBOL(blk_end_request);
 
 /**
- * __blk_end_request - Helper function for drivers to complete the request.
- * @rq:       the request being processed
- * @error:    %0 for success, < %0 for error
- * @nr_bytes: number of bytes to complete
+ * blk_end_request_all - Helper function for drives to finish the request.
+ * @rq: the request to finish
+ * @error: %0 for success, < %0 for error
  *
  * Description:
- *     Must be called with queue lock held unlike blk_end_request().
- *
- * Return:
- *     %0 - we are done with this request
- *     %1 - still buffers pending for this request
- **/
-int __blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
+ *     Completely finish @rq.
+ */
+void blk_end_request_all(struct request *rq, int error)
 {
-	if (rq->bio && __end_that_request_first(rq, error, nr_bytes))
-		return 1;
+	bool pending;
+	unsigned int bidi_bytes = 0;
 
-	add_disk_randomness(rq->rq_disk);
+	if (unlikely(blk_bidi_rq(rq)))
+		bidi_bytes = blk_rq_bytes(rq->next_rq);
 
-	end_that_request_last(rq, error);
+	pending = blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes);
+	BUG_ON(pending);
+}
+EXPORT_SYMBOL(blk_end_request_all);
 
-	return 0;
+/**
+ * blk_end_request_cur - Helper function to finish the current request chunk.
+ * @rq: the request to finish the current chunk for
+ * @error: %0 for success, < %0 for error
+ *
+ * Description:
+ *     Complete the current consecutively mapped chunk from @rq.
+ *
+ * Return:
+ *     %false - we are done with this request
+ *     %true  - still buffers pending for this request
+ */
+bool blk_end_request_cur(struct request *rq, int error)
+{
+	return blk_end_request(rq, error, blk_rq_cur_bytes(rq));
 }
-EXPORT_SYMBOL_GPL(__blk_end_request);
+EXPORT_SYMBOL(blk_end_request_cur);
 
 /**
- * blk_end_bidi_request - Helper function for drivers to complete bidi request.
- * @rq:         the bidi request being processed
- * @error:      %0 for success, < %0 for error
- * @nr_bytes:   number of bytes to complete @rq
- * @bidi_bytes: number of bytes to complete @rq->next_rq
+ * __blk_end_request - Helper function for drivers to complete the request.
+ * @rq:       the request being processed
+ * @error:    %0 for success, < %0 for error
+ * @nr_bytes: number of bytes to complete
  *
  * Description:
- *     Ends I/O on a number of bytes attached to @rq and @rq->next_rq.
+ *     Must be called with queue lock held unlike blk_end_request().
  *
  * Return:
- *     %0 - we are done with this request
- *     %1 - still buffers pending for this request
+ *     %false - we are done with this request
+ *     %true  - still buffers pending for this request
  **/
-int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes,
-			 unsigned int bidi_bytes)
+bool __blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
 {
-	return blk_end_io(rq, error, nr_bytes, bidi_bytes, NULL);
+	return __blk_end_bidi_request(rq, error, nr_bytes, 0);
 }
-EXPORT_SYMBOL_GPL(blk_end_bidi_request);
+EXPORT_SYMBOL(__blk_end_request);
 
 /**
- * blk_update_request - Special helper function for request stacking drivers
- * @rq:           the request being processed
- * @error:        %0 for success, < %0 for error
- * @nr_bytes:     number of bytes to complete @rq
+ * __blk_end_request_all - Helper function for drives to finish the request.
+ * @rq: the request to finish
+ * @error: %0 for success, < %0 for error
  *
  * Description:
- *     Ends I/O on a number of bytes attached to @rq, but doesn't complete
- *     the request structure even if @rq doesn't have leftover.
- *     If @rq has leftover, sets it up for the next range of segments.
- *
- *     This special helper function is only for request stacking drivers
- *     (e.g. request-based dm) so that they can handle partial completion.
- *     Actual device drivers should use blk_end_request instead.
+ *     Completely finish @rq.  Must be called with queue lock held.
  */
-void blk_update_request(struct request *rq, int error, unsigned int nr_bytes)
+void __blk_end_request_all(struct request *rq, int error)
 {
-	if (!end_that_request_data(rq, error, nr_bytes, 0)) {
-		/*
-		 * These members are not updated in end_that_request_data()
-		 * when all bios are completed.
-		 * Update them so that the request stacking driver can find
-		 * how many bytes remain in the request later.
-		 */
-		rq->nr_sectors = rq->hard_nr_sectors = 0;
-		rq->current_nr_sectors = rq->hard_cur_sectors = 0;
-	}
+	bool pending;
+	unsigned int bidi_bytes = 0;
+
+	if (unlikely(blk_bidi_rq(rq)))
+		bidi_bytes = blk_rq_bytes(rq->next_rq);
+
+	pending = __blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes);
+	BUG_ON(pending);
 }
-EXPORT_SYMBOL_GPL(blk_update_request);
+EXPORT_SYMBOL(__blk_end_request_all);
 
 /**
- * blk_end_request_callback - Special helper function for tricky drivers
- * @rq:           the request being processed
- * @error:        %0 for success, < %0 for error
- * @nr_bytes:     number of bytes to complete
- * @drv_callback: function called between completion of bios in the request
- *                and completion of the request.
- *                If the callback returns non %0, this helper returns without
- *                completion of the request.
+ * __blk_end_request_cur - Helper function to finish the current request chunk.
+ * @rq: the request to finish the current chunk for
+ * @error: %0 for success, < %0 for error
  *
  * Description:
- *     Ends I/O on a number of bytes attached to @rq.
- *     If @rq has leftover, sets it up for the next range of segments.
- *
- *     This special helper function is used only for existing tricky drivers.
- *     (e.g. cdrom_newpc_intr() of ide-cd)
- *     This interface will be removed when such drivers are rewritten.
- *     Don't use this interface in other places anymore.
+ *     Complete the current consecutively mapped chunk from @rq.  Must
+ *     be called with queue lock held.
  *
  * Return:
- *     %0 - we are done with this request
- *     %1 - this request is not freed yet.
- *          this request still has pending buffers or
- *          the driver doesn't want to finish this request yet.
- **/
-int blk_end_request_callback(struct request *rq, int error,
-			     unsigned int nr_bytes,
-			     int (drv_callback)(struct request *))
+ *     %false - we are done with this request
+ *     %true  - still buffers pending for this request
+ */
+bool __blk_end_request_cur(struct request *rq, int error)
 {
-	return blk_end_io(rq, error, nr_bytes, 0, drv_callback);
+	return __blk_end_request(rq, error, blk_rq_cur_bytes(rq));
 }
-EXPORT_SYMBOL_GPL(blk_end_request_callback);
+EXPORT_SYMBOL(__blk_end_request_cur);
 
 void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
 		     struct bio *bio)
@@ -2111,11 +2247,7 @@
 		rq->nr_phys_segments = bio_phys_segments(q, bio);
 		rq->buffer = bio_data(bio);
 	}
-	rq->current_nr_sectors = bio_cur_sectors(bio);
-	rq->hard_cur_sectors = rq->current_nr_sectors;
-	rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
-	rq->data_len = bio->bi_size;
-
+	rq->__data_len = bio->bi_size;
 	rq->bio = rq->biotail = bio;
 
 	if (bio->bi_bdev)
@@ -2150,6 +2282,106 @@
 }
 EXPORT_SYMBOL_GPL(blk_lld_busy);
 
+/**
+ * blk_rq_unprep_clone - Helper function to free all bios in a cloned request
+ * @rq: the clone request to be cleaned up
+ *
+ * Description:
+ *     Free all bios in @rq for a cloned request.
+ */
+void blk_rq_unprep_clone(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+
+		bio_put(bio);
+	}
+}
+EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);
+
+/*
+ * Copy attributes of the original request to the clone request.
+ * The actual data parts (e.g. ->cmd, ->buffer, ->sense) are not copied.
+ */
+static void __blk_rq_prep_clone(struct request *dst, struct request *src)
+{
+	dst->cpu = src->cpu;
+	dst->cmd_flags = (rq_data_dir(src) | REQ_NOMERGE);
+	dst->cmd_type = src->cmd_type;
+	dst->__sector = blk_rq_pos(src);
+	dst->__data_len = blk_rq_bytes(src);
+	dst->nr_phys_segments = src->nr_phys_segments;
+	dst->ioprio = src->ioprio;
+	dst->extra_len = src->extra_len;
+}
+
+/**
+ * blk_rq_prep_clone - Helper function to setup clone request
+ * @rq: the request to be setup
+ * @rq_src: original request to be cloned
+ * @bs: bio_set that bios for clone are allocated from
+ * @gfp_mask: memory allocation mask for bio
+ * @bio_ctr: setup function to be called for each clone bio.
+ *           Returns %0 for success, non %0 for failure.
+ * @data: private data to be passed to @bio_ctr
+ *
+ * Description:
+ *     Clones bios in @rq_src to @rq, and copies attributes of @rq_src to @rq.
+ *     The actual data parts of @rq_src (e.g. ->cmd, ->buffer, ->sense)
+ *     are not copied, and copying such parts is the caller's responsibility.
+ *     Also, pages which the original bios are pointing to are not copied
+ *     and the cloned bios just point same pages.
+ *     So cloned bios must be completed before original bios, which means
+ *     the caller must complete @rq before @rq_src.
+ */
+int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
+		      struct bio_set *bs, gfp_t gfp_mask,
+		      int (*bio_ctr)(struct bio *, struct bio *, void *),
+		      void *data)
+{
+	struct bio *bio, *bio_src;
+
+	if (!bs)
+		bs = fs_bio_set;
+
+	blk_rq_init(NULL, rq);
+
+	__rq_for_each_bio(bio_src, rq_src) {
+		bio = bio_alloc_bioset(gfp_mask, bio_src->bi_max_vecs, bs);
+		if (!bio)
+			goto free_and_out;
+
+		__bio_clone(bio, bio_src);
+
+		if (bio_integrity(bio_src) &&
+		    bio_integrity_clone(bio, bio_src, gfp_mask, bs))
+			goto free_and_out;
+
+		if (bio_ctr && bio_ctr(bio, bio_src, data))
+			goto free_and_out;
+
+		if (rq->bio) {
+			rq->biotail->bi_next = bio;
+			rq->biotail = bio;
+		} else
+			rq->bio = rq->biotail = bio;
+	}
+
+	__blk_rq_prep_clone(rq, rq_src);
+
+	return 0;
+
+free_and_out:
+	if (bio)
+		bio_free(bio, bs);
+	blk_rq_unprep_clone(rq);
+
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(blk_rq_prep_clone);
+
 int kblockd_schedule_work(struct request_queue *q, struct work_struct *work)
 {
 	return queue_work(kblockd_workqueue, work);
@@ -2158,6 +2390,9 @@
 
 int __init blk_dev_init(void)
 {
+	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
+			sizeof(((struct request *)0)->cmd_flags));
+
 	kblockd_workqueue = create_workqueue("kblockd");
 	if (!kblockd_workqueue)
 		panic("Failed to create kblockd\n");
diff -druN linux-libre-2.6.30-gnu/block/blk-exec.c linux-libre-2.6.31-gnu/block/blk-exec.c
--- linux-libre-2.6.30-gnu/block/blk-exec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-exec.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,7 +51,6 @@
 	int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
 
 	rq->rq_disk = bd_disk;
-	rq->cmd_flags |= REQ_NOMERGE;
 	rq->end_io = done;
 	WARN_ON(irqs_disabled());
 	spin_lock_irq(q->queue_lock);
diff -druN linux-libre-2.6.30-gnu/block/blk.h linux-libre-2.6.31-gnu/block/blk.h
--- linux-libre-2.6.30-gnu/block/blk.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,9 @@
 void init_request_from_bio(struct request *req, struct bio *bio);
 void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
 			struct bio *bio);
+int blk_rq_append_bio(struct request_queue *q, struct request *rq,
+		      struct bio *bio);
+void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
 
 void blk_unplug_work(struct work_struct *work);
@@ -43,6 +46,43 @@
 	clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
 }
 
+/*
+ * Internal elevator interface
+ */
+#define ELV_ON_HASH(rq)		(!hlist_unhashed(&(rq)->hash))
+
+static inline struct request *__elv_next_request(struct request_queue *q)
+{
+	struct request *rq;
+
+	while (1) {
+		while (!list_empty(&q->queue_head)) {
+			rq = list_entry_rq(q->queue_head.next);
+			if (blk_do_ordered(q, &rq))
+				return rq;
+		}
+
+		if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
+			return NULL;
+	}
+}
+
+static inline void elv_activate_rq(struct request_queue *q, struct request *rq)
+{
+	struct elevator_queue *e = q->elevator;
+
+	if (e->ops->elevator_activate_req_fn)
+		e->ops->elevator_activate_req_fn(q, rq);
+}
+
+static inline void elv_deactivate_rq(struct request_queue *q, struct request *rq)
+{
+	struct elevator_queue *e = q->elevator;
+
+	if (e->ops->elevator_deactivate_req_fn)
+		e->ops->elevator_deactivate_req_fn(q, rq);
+}
+
 #ifdef CONFIG_FAIL_IO_TIMEOUT
 int blk_should_fake_timeout(struct request_queue *);
 ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
@@ -64,7 +104,6 @@
 int attempt_back_merge(struct request_queue *q, struct request *rq);
 int attempt_front_merge(struct request_queue *q, struct request *rq);
 void blk_recalc_rq_segments(struct request *rq);
-void blk_recalc_rq_sectors(struct request *rq, int nsect);
 
 void blk_queue_congestion_threshold(struct request_queue *q);
 
@@ -112,9 +151,17 @@
 #endif
 }
 
+/*
+ * Contribute to IO statistics IFF:
+ *
+ *	a) it's attached to a gendisk, and
+ *	b) the queue had IO stats enabled when this request was started, and
+ *	c) it's a file system request or a discard request
+ */
 static inline int blk_do_io_stat(struct request *rq)
 {
-	return rq->rq_disk && blk_rq_io_stat(rq);
+	return rq->rq_disk && blk_rq_io_stat(rq) &&
+	       (blk_fs_request(rq) || blk_discard_rq(rq));
 }
 
 #endif
diff -druN linux-libre-2.6.30-gnu/block/blk-integrity.c linux-libre-2.6.31-gnu/block/blk-integrity.c
--- linux-libre-2.6.30-gnu/block/blk-integrity.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-integrity.c	2009-09-09 18:13:59.000000000 -0400
@@ -340,7 +340,7 @@
 		kobject_uevent(&bi->kobj, KOBJ_ADD);
 
 		bi->flags |= INTEGRITY_FLAG_READ | INTEGRITY_FLAG_WRITE;
-		bi->sector_size = disk->queue->hardsect_size;
+		bi->sector_size = queue_logical_block_size(disk->queue);
 		disk->integrity = bi;
 	} else
 		bi = disk->integrity;
@@ -379,6 +379,7 @@
 
 	kobject_uevent(&bi->kobj, KOBJ_REMOVE);
 	kobject_del(&bi->kobj);
+	kobject_put(&bi->kobj);
 	kmem_cache_free(integrity_cachep, bi);
 	disk->integrity = NULL;
 }
diff -druN linux-libre-2.6.30-gnu/block/blk-ioc.c linux-libre-2.6.31-gnu/block/blk-ioc.c
--- linux-libre-2.6.30-gnu/block/blk-ioc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-ioc.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,9 +35,9 @@
 	if (ioc == NULL)
 		return 1;
 
-	BUG_ON(atomic_read(&ioc->refcount) == 0);
+	BUG_ON(atomic_long_read(&ioc->refcount) == 0);
 
-	if (atomic_dec_and_test(&ioc->refcount)) {
+	if (atomic_long_dec_and_test(&ioc->refcount)) {
 		rcu_read_lock();
 		if (ioc->aic && ioc->aic->dtor)
 			ioc->aic->dtor(ioc->aic);
@@ -90,7 +90,7 @@
 
 	ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
 	if (ret) {
-		atomic_set(&ret->refcount, 1);
+		atomic_long_set(&ret->refcount, 1);
 		atomic_set(&ret->nr_tasks, 1);
 		spin_lock_init(&ret->lock);
 		ret->ioprio_changed = 0;
@@ -151,7 +151,7 @@
 		ret = current_io_context(gfp_flags, node);
 		if (unlikely(!ret))
 			break;
-	} while (!atomic_inc_not_zero(&ret->refcount));
+	} while (!atomic_long_inc_not_zero(&ret->refcount));
 
 	return ret;
 }
@@ -163,8 +163,8 @@
 	struct io_context *dst = *pdst;
 
 	if (src) {
-		BUG_ON(atomic_read(&src->refcount) == 0);
-		atomic_inc(&src->refcount);
+		BUG_ON(atomic_long_read(&src->refcount) == 0);
+		atomic_long_inc(&src->refcount);
 		put_io_context(dst);
 		*pdst = src;
 	}
diff -druN linux-libre-2.6.30-gnu/block/blk-map.c linux-libre-2.6.31-gnu/block/blk-map.c
--- linux-libre-2.6.30-gnu/block/blk-map.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-map.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,11 +20,10 @@
 		rq->biotail->bi_next = bio;
 		rq->biotail = bio;
 
-		rq->data_len += bio->bi_size;
+		rq->__data_len += bio->bi_size;
 	}
 	return 0;
 }
-EXPORT_SYMBOL(blk_rq_append_bio);
 
 static int __blk_rq_unmap_user(struct bio *bio)
 {
@@ -116,7 +115,7 @@
 	struct bio *bio = NULL;
 	int ret;
 
-	if (len > (q->max_hw_sectors << 9))
+	if (len > (queue_max_hw_sectors(q) << 9))
 		return -EINVAL;
 	if (!len)
 		return -EINVAL;
@@ -156,7 +155,7 @@
 	if (!bio_flagged(bio, BIO_USER_MAPPED))
 		rq->cmd_flags |= REQ_COPY_USER;
 
-	rq->buffer = rq->data = NULL;
+	rq->buffer = NULL;
 	return 0;
 unmap_rq:
 	blk_rq_unmap_user(bio);
@@ -235,7 +234,7 @@
 	blk_queue_bounce(q, &bio);
 	bio_get(bio);
 	blk_rq_bio_prep(q, rq, bio);
-	rq->buffer = rq->data = NULL;
+	rq->buffer = NULL;
 	return 0;
 }
 EXPORT_SYMBOL(blk_rq_map_user_iov);
@@ -282,7 +281,8 @@
  *
  * Description:
  *    Data will be mapped directly if possible. Otherwise a bounce
- *    buffer is used.
+ *    buffer is used. Can be called multple times to append multple
+ *    buffers.
  */
 int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
 		    unsigned int len, gfp_t gfp_mask)
@@ -290,8 +290,9 @@
 	int reading = rq_data_dir(rq) == READ;
 	int do_copy = 0;
 	struct bio *bio;
+	int ret;
 
-	if (len > (q->max_hw_sectors << 9))
+	if (len > (queue_max_hw_sectors(q) << 9))
 		return -EINVAL;
 	if (!len || !kbuf)
 		return -EINVAL;
@@ -311,9 +312,15 @@
 	if (do_copy)
 		rq->cmd_flags |= REQ_COPY_USER;
 
-	blk_rq_bio_prep(q, rq, bio);
+	ret = blk_rq_append_bio(q, rq, bio);
+	if (unlikely(ret)) {
+		/* request is too big */
+		bio_put(bio);
+		return ret;
+	}
+
 	blk_queue_bounce(q, &rq->bio);
-	rq->buffer = rq->data = NULL;
+	rq->buffer = NULL;
 	return 0;
 }
 EXPORT_SYMBOL(blk_rq_map_kern);
diff -druN linux-libre-2.6.30-gnu/block/blk-merge.c linux-libre-2.6.31-gnu/block/blk-merge.c
--- linux-libre-2.6.30-gnu/block/blk-merge.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-merge.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,35 +9,6 @@
 
 #include "blk.h"
 
-void blk_recalc_rq_sectors(struct request *rq, int nsect)
-{
-	if (blk_fs_request(rq) || blk_discard_rq(rq)) {
-		rq->hard_sector += nsect;
-		rq->hard_nr_sectors -= nsect;
-
-		/*
-		 * Move the I/O submission pointers ahead if required.
-		 */
-		if ((rq->nr_sectors >= rq->hard_nr_sectors) &&
-		    (rq->sector <= rq->hard_sector)) {
-			rq->sector = rq->hard_sector;
-			rq->nr_sectors = rq->hard_nr_sectors;
-			rq->hard_cur_sectors = bio_cur_sectors(rq->bio);
-			rq->current_nr_sectors = rq->hard_cur_sectors;
-			rq->buffer = bio_data(rq->bio);
-		}
-
-		/*
-		 * if total number of sectors is less than the first segment
-		 * size, something has gone terribly wrong
-		 */
-		if (rq->nr_sectors < rq->current_nr_sectors) {
-			printk(KERN_ERR "blk: request botched\n");
-			rq->nr_sectors = rq->current_nr_sectors;
-		}
-	}
-}
-
 static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
 					     struct bio *bio)
 {
@@ -61,11 +32,12 @@
 			 * never considered part of another segment, since that
 			 * might change with the bounce page.
 			 */
-			high = page_to_pfn(bv->bv_page) > q->bounce_pfn;
+			high = page_to_pfn(bv->bv_page) > queue_bounce_pfn(q);
 			if (high || highprv)
 				goto new_segment;
 			if (cluster) {
-				if (seg_size + bv->bv_len > q->max_segment_size)
+				if (seg_size + bv->bv_len
+				    > queue_max_segment_size(q))
 					goto new_segment;
 				if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv))
 					goto new_segment;
@@ -120,7 +92,7 @@
 		return 0;
 
 	if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
-	    q->max_segment_size)
+	    queue_max_segment_size(q))
 		return 0;
 
 	if (!bio_has_data(bio))
@@ -163,7 +135,7 @@
 		int nbytes = bvec->bv_len;
 
 		if (bvprv && cluster) {
-			if (sg->length + nbytes > q->max_segment_size)
+			if (sg->length + nbytes > queue_max_segment_size(q))
 				goto new_segment;
 
 			if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
@@ -199,8 +171,9 @@
 
 
 	if (unlikely(rq->cmd_flags & REQ_COPY_USER) &&
-	    (rq->data_len & q->dma_pad_mask)) {
-		unsigned int pad_len = (q->dma_pad_mask & ~rq->data_len) + 1;
+	    (blk_rq_bytes(rq) & q->dma_pad_mask)) {
+		unsigned int pad_len =
+			(q->dma_pad_mask & ~blk_rq_bytes(rq)) + 1;
 
 		sg->length += pad_len;
 		rq->extra_len += pad_len;
@@ -233,8 +206,8 @@
 {
 	int nr_phys_segs = bio_phys_segments(q, bio);
 
-	if (req->nr_phys_segments + nr_phys_segs > q->max_hw_segments
-	    || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
+	if (req->nr_phys_segments + nr_phys_segs > queue_max_hw_segments(q) ||
+	    req->nr_phys_segments + nr_phys_segs > queue_max_phys_segments(q)) {
 		req->cmd_flags |= REQ_NOMERGE;
 		if (req == q->last_merge)
 			q->last_merge = NULL;
@@ -255,11 +228,11 @@
 	unsigned short max_sectors;
 
 	if (unlikely(blk_pc_request(req)))
-		max_sectors = q->max_hw_sectors;
+		max_sectors = queue_max_hw_sectors(q);
 	else
-		max_sectors = q->max_sectors;
+		max_sectors = queue_max_sectors(q);
 
-	if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
+	if (blk_rq_sectors(req) + bio_sectors(bio) > max_sectors) {
 		req->cmd_flags |= REQ_NOMERGE;
 		if (req == q->last_merge)
 			q->last_merge = NULL;
@@ -279,12 +252,12 @@
 	unsigned short max_sectors;
 
 	if (unlikely(blk_pc_request(req)))
-		max_sectors = q->max_hw_sectors;
+		max_sectors = queue_max_hw_sectors(q);
 	else
-		max_sectors = q->max_sectors;
+		max_sectors = queue_max_sectors(q);
 
 
-	if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
+	if (blk_rq_sectors(req) + bio_sectors(bio) > max_sectors) {
 		req->cmd_flags |= REQ_NOMERGE;
 		if (req == q->last_merge)
 			q->last_merge = NULL;
@@ -315,7 +288,7 @@
 	/*
 	 * Will it become too large?
 	 */
-	if ((req->nr_sectors + next->nr_sectors) > q->max_sectors)
+	if ((blk_rq_sectors(req) + blk_rq_sectors(next)) > queue_max_sectors(q))
 		return 0;
 
 	total_phys_segments = req->nr_phys_segments + next->nr_phys_segments;
@@ -327,10 +300,10 @@
 		total_phys_segments--;
 	}
 
-	if (total_phys_segments > q->max_phys_segments)
+	if (total_phys_segments > queue_max_phys_segments(q))
 		return 0;
 
-	if (total_phys_segments > q->max_hw_segments)
+	if (total_phys_segments > queue_max_hw_segments(q))
 		return 0;
 
 	/* Merge is OK... */
@@ -345,7 +318,7 @@
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, req->sector);
+		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 
 		part_round_stats(cpu, part);
 		part_dec_in_flight(part);
@@ -366,7 +339,7 @@
 	/*
 	 * not contiguous
 	 */
-	if (req->sector + req->nr_sectors != next->sector)
+	if (blk_rq_pos(req) + blk_rq_sectors(req) != blk_rq_pos(next))
 		return 0;
 
 	if (rq_data_dir(req) != rq_data_dir(next)
@@ -377,6 +350,12 @@
 	if (blk_integrity_rq(req) != blk_integrity_rq(next))
 		return 0;
 
+	/* don't merge requests of different failfast settings */
+	if (blk_failfast_dev(req)	!= blk_failfast_dev(next)	||
+	    blk_failfast_transport(req)	!= blk_failfast_transport(next)	||
+	    blk_failfast_driver(req)	!= blk_failfast_driver(next))
+		return 0;
+
 	/*
 	 * If we are allowed to merge, then append bio list
 	 * from next to rq and release next. merge_requests_fn
@@ -398,7 +377,7 @@
 	req->biotail->bi_next = next->bio;
 	req->biotail = next->biotail;
 
-	req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
+	req->__data_len += blk_rq_bytes(next);
 
 	elv_merge_requests(q, req, next);
 
diff -druN linux-libre-2.6.30-gnu/block/blk-settings.c linux-libre-2.6.31-gnu/block/blk-settings.c
--- linux-libre-2.6.30-gnu/block/blk-settings.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-settings.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,6 +7,7 @@
 #include <linux/bio.h>
 #include <linux/blkdev.h>
 #include <linux/bootmem.h>	/* for max_pfn/max_low_pfn */
+#include <linux/gcd.h>
 
 #include "blk.h"
 
@@ -96,6 +97,31 @@
 EXPORT_SYMBOL_GPL(blk_queue_lld_busy);
 
 /**
+ * blk_set_default_limits - reset limits to default values
+ * @lim:  the queue_limits structure to reset
+ *
+ * Description:
+ *   Returns a queue_limit struct to its default state.  Can be used by
+ *   stacking drivers like DM that stage table swaps and reuse an
+ *   existing device queue.
+ */
+void blk_set_default_limits(struct queue_limits *lim)
+{
+	lim->max_phys_segments = MAX_PHYS_SEGMENTS;
+	lim->max_hw_segments = MAX_HW_SEGMENTS;
+	lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
+	lim->max_segment_size = MAX_SEGMENT_SIZE;
+	lim->max_sectors = lim->max_hw_sectors = SAFE_MAX_SECTORS;
+	lim->logical_block_size = lim->physical_block_size = lim->io_min = 512;
+	lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT);
+	lim->alignment_offset = 0;
+	lim->io_opt = 0;
+	lim->misaligned = 0;
+	lim->no_cluster = 0;
+}
+EXPORT_SYMBOL(blk_set_default_limits);
+
+/**
  * blk_queue_make_request - define an alternate make_request function for a device
  * @q:  the request queue for the device to be affected
  * @mfn: the alternate make_request function
@@ -123,18 +149,8 @@
 	 * set defaults
 	 */
 	q->nr_requests = BLKDEV_MAX_RQ;
-	blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
-	blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
-	blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
-	blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
 
 	q->make_request_fn = mfn;
-	q->backing_dev_info.ra_pages =
-			(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
-	q->backing_dev_info.state = 0;
-	q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
-	blk_queue_max_sectors(q, SAFE_MAX_SECTORS);
-	blk_queue_hardsect_size(q, 512);
 	blk_queue_dma_alignment(q, 511);
 	blk_queue_congestion_threshold(q);
 	q->nr_batching = BLK_BATCH_REQ;
@@ -147,6 +163,15 @@
 	q->unplug_timer.function = blk_unplug_timeout;
 	q->unplug_timer.data = (unsigned long)q;
 
+	blk_set_default_limits(&q->limits);
+
+	/*
+	 * If the caller didn't supply a lock, fall back to our embedded
+	 * per-queue locks
+	 */
+	if (!q->queue_lock)
+		q->queue_lock = &q->__queue_lock;
+
 	/*
 	 * by default assume old behaviour and bounce for any highmem page
 	 */
@@ -179,16 +204,16 @@
 	 */
 	if (b_pfn < (min_t(u64, 0xffffffffUL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
 		dma = 1;
-	q->bounce_pfn = max_low_pfn;
+	q->limits.bounce_pfn = max_low_pfn;
 #else
 	if (b_pfn < blk_max_low_pfn)
 		dma = 1;
-	q->bounce_pfn = b_pfn;
+	q->limits.bounce_pfn = b_pfn;
 #endif
 	if (dma) {
 		init_emergency_isa_pool();
 		q->bounce_gfp = GFP_NOIO | GFP_DMA;
-		q->bounce_pfn = b_pfn;
+		q->limits.bounce_pfn = b_pfn;
 	}
 }
 EXPORT_SYMBOL(blk_queue_bounce_limit);
@@ -211,14 +236,23 @@
 	}
 
 	if (BLK_DEF_MAX_SECTORS > max_sectors)
-		q->max_hw_sectors = q->max_sectors = max_sectors;
+		q->limits.max_hw_sectors = q->limits.max_sectors = max_sectors;
 	else {
-		q->max_sectors = BLK_DEF_MAX_SECTORS;
-		q->max_hw_sectors = max_sectors;
+		q->limits.max_sectors = BLK_DEF_MAX_SECTORS;
+		q->limits.max_hw_sectors = max_sectors;
 	}
 }
 EXPORT_SYMBOL(blk_queue_max_sectors);
 
+void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_sectors)
+{
+	if (BLK_DEF_MAX_SECTORS > max_sectors)
+		q->limits.max_hw_sectors = BLK_DEF_MAX_SECTORS;
+	else
+		q->limits.max_hw_sectors = max_sectors;
+}
+EXPORT_SYMBOL(blk_queue_max_hw_sectors);
+
 /**
  * blk_queue_max_phys_segments - set max phys segments for a request for this queue
  * @q:  the request queue for the device
@@ -238,7 +272,7 @@
 		       __func__, max_segments);
 	}
 
-	q->max_phys_segments = max_segments;
+	q->limits.max_phys_segments = max_segments;
 }
 EXPORT_SYMBOL(blk_queue_max_phys_segments);
 
@@ -262,7 +296,7 @@
 		       __func__, max_segments);
 	}
 
-	q->max_hw_segments = max_segments;
+	q->limits.max_hw_segments = max_segments;
 }
 EXPORT_SYMBOL(blk_queue_max_hw_segments);
 
@@ -283,26 +317,134 @@
 		       __func__, max_size);
 	}
 
-	q->max_segment_size = max_size;
+	q->limits.max_segment_size = max_size;
 }
 EXPORT_SYMBOL(blk_queue_max_segment_size);
 
 /**
- * blk_queue_hardsect_size - set hardware sector size for the queue
+ * blk_queue_logical_block_size - set logical block size for the queue
  * @q:  the request queue for the device
- * @size:  the hardware sector size, in bytes
+ * @size:  the logical block size, in bytes
  *
  * Description:
- *   This should typically be set to the lowest possible sector size
- *   that the hardware can operate on (possible without reverting to
- *   even internal read-modify-write operations). Usually the default
- *   of 512 covers most hardware.
+ *   This should be set to the lowest possible block size that the
+ *   storage device can address.  The default of 512 covers most
+ *   hardware.
  **/
-void blk_queue_hardsect_size(struct request_queue *q, unsigned short size)
+void blk_queue_logical_block_size(struct request_queue *q, unsigned short size)
 {
-	q->hardsect_size = size;
+	q->limits.logical_block_size = size;
+
+	if (q->limits.physical_block_size < size)
+		q->limits.physical_block_size = size;
+
+	if (q->limits.io_min < q->limits.physical_block_size)
+		q->limits.io_min = q->limits.physical_block_size;
 }
-EXPORT_SYMBOL(blk_queue_hardsect_size);
+EXPORT_SYMBOL(blk_queue_logical_block_size);
+
+/**
+ * blk_queue_physical_block_size - set physical block size for the queue
+ * @q:  the request queue for the device
+ * @size:  the physical block size, in bytes
+ *
+ * Description:
+ *   This should be set to the lowest possible sector size that the
+ *   hardware can operate on without reverting to read-modify-write
+ *   operations.
+ */
+void blk_queue_physical_block_size(struct request_queue *q, unsigned short size)
+{
+	q->limits.physical_block_size = size;
+
+	if (q->limits.physical_block_size < q->limits.logical_block_size)
+		q->limits.physical_block_size = q->limits.logical_block_size;
+
+	if (q->limits.io_min < q->limits.physical_block_size)
+		q->limits.io_min = q->limits.physical_block_size;
+}
+EXPORT_SYMBOL(blk_queue_physical_block_size);
+
+/**
+ * blk_queue_alignment_offset - set physical block alignment offset
+ * @q:	the request queue for the device
+ * @offset: alignment offset in bytes
+ *
+ * Description:
+ *   Some devices are naturally misaligned to compensate for things like
+ *   the legacy DOS partition table 63-sector offset.  Low-level drivers
+ *   should call this function for devices whose first sector is not
+ *   naturally aligned.
+ */
+void blk_queue_alignment_offset(struct request_queue *q, unsigned int offset)
+{
+	q->limits.alignment_offset =
+		offset & (q->limits.physical_block_size - 1);
+	q->limits.misaligned = 0;
+}
+EXPORT_SYMBOL(blk_queue_alignment_offset);
+
+/**
+ * blk_limits_io_min - set minimum request size for a device
+ * @limits: the queue limits
+ * @min:  smallest I/O size in bytes
+ *
+ * Description:
+ *   Some devices have an internal block size bigger than the reported
+ *   hardware sector size.  This function can be used to signal the
+ *   smallest I/O the device can perform without incurring a performance
+ *   penalty.
+ */
+void blk_limits_io_min(struct queue_limits *limits, unsigned int min)
+{
+	limits->io_min = min;
+
+	if (limits->io_min < limits->logical_block_size)
+		limits->io_min = limits->logical_block_size;
+
+	if (limits->io_min < limits->physical_block_size)
+		limits->io_min = limits->physical_block_size;
+}
+EXPORT_SYMBOL(blk_limits_io_min);
+
+/**
+ * blk_queue_io_min - set minimum request size for the queue
+ * @q:	the request queue for the device
+ * @min:  smallest I/O size in bytes
+ *
+ * Description:
+ *   Storage devices may report a granularity or preferred minimum I/O
+ *   size which is the smallest request the device can perform without
+ *   incurring a performance penalty.  For disk drives this is often the
+ *   physical block size.  For RAID arrays it is often the stripe chunk
+ *   size.  A properly aligned multiple of minimum_io_size is the
+ *   preferred request size for workloads where a high number of I/O
+ *   operations is desired.
+ */
+void blk_queue_io_min(struct request_queue *q, unsigned int min)
+{
+	blk_limits_io_min(&q->limits, min);
+}
+EXPORT_SYMBOL(blk_queue_io_min);
+
+/**
+ * blk_queue_io_opt - set optimal request size for the queue
+ * @q:	the request queue for the device
+ * @opt:  optimal request size in bytes
+ *
+ * Description:
+ *   Storage devices may report an optimal I/O size, which is the
+ *   device's preferred unit for sustained I/O.  This is rarely reported
+ *   for disk drives.  For RAID arrays it is usually the stripe width or
+ *   the internal track size.  A properly aligned multiple of
+ *   optimal_io_size is the preferred request size for workloads where
+ *   sustained throughput is desired.
+ */
+void blk_queue_io_opt(struct request_queue *q, unsigned int opt)
+{
+	q->limits.io_opt = opt;
+}
+EXPORT_SYMBOL(blk_queue_io_opt);
 
 /*
  * Returns the minimum that is _not_ zero, unless both are zero.
@@ -316,15 +458,8 @@
  **/
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 {
-	/* zero is "infinity" */
-	t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
-	t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
-	t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask, b->seg_boundary_mask);
+	blk_stack_limits(&t->limits, &b->limits, 0);
 
-	t->max_phys_segments = min_not_zero(t->max_phys_segments, b->max_phys_segments);
-	t->max_hw_segments = min_not_zero(t->max_hw_segments, b->max_hw_segments);
-	t->max_segment_size = min_not_zero(t->max_segment_size, b->max_segment_size);
-	t->hardsect_size = max(t->hardsect_size, b->hardsect_size);
 	if (!t->queue_lock)
 		WARN_ON_ONCE(1);
 	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
@@ -337,6 +472,119 @@
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
 /**
+ * blk_stack_limits - adjust queue_limits for stacked devices
+ * @t:	the stacking driver limits (top)
+ * @b:  the underlying queue limits (bottom)
+ * @offset:  offset to beginning of data within component device
+ *
+ * Description:
+ *    Merges two queue_limit structs.  Returns 0 if alignment didn't
+ *    change.  Returns -1 if adding the bottom device caused
+ *    misalignment.
+ */
+int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
+		     sector_t offset)
+{
+	t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
+	t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
+	t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
+
+	t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
+					    b->seg_boundary_mask);
+
+	t->max_phys_segments = min_not_zero(t->max_phys_segments,
+					    b->max_phys_segments);
+
+	t->max_hw_segments = min_not_zero(t->max_hw_segments,
+					  b->max_hw_segments);
+
+	t->max_segment_size = min_not_zero(t->max_segment_size,
+					   b->max_segment_size);
+
+	t->logical_block_size = max(t->logical_block_size,
+				    b->logical_block_size);
+
+	t->physical_block_size = max(t->physical_block_size,
+				     b->physical_block_size);
+
+	t->io_min = max(t->io_min, b->io_min);
+	t->no_cluster |= b->no_cluster;
+
+	/* Bottom device offset aligned? */
+	if (offset &&
+	    (offset & (b->physical_block_size - 1)) != b->alignment_offset) {
+		t->misaligned = 1;
+		return -1;
+	}
+
+	/* If top has no alignment offset, inherit from bottom */
+	if (!t->alignment_offset)
+		t->alignment_offset =
+			b->alignment_offset & (b->physical_block_size - 1);
+
+	/* Top device aligned on logical block boundary? */
+	if (t->alignment_offset & (t->logical_block_size - 1)) {
+		t->misaligned = 1;
+		return -1;
+	}
+
+	/* Find lcm() of optimal I/O size */
+	if (t->io_opt && b->io_opt)
+		t->io_opt = (t->io_opt * b->io_opt) / gcd(t->io_opt, b->io_opt);
+	else if (b->io_opt)
+		t->io_opt = b->io_opt;
+
+	/* Verify that optimal I/O size is a multiple of io_min */
+	if (t->io_min && t->io_opt % t->io_min)
+		return -1;
+
+	return 0;
+}
+EXPORT_SYMBOL(blk_stack_limits);
+
+/**
+ * disk_stack_limits - adjust queue limits for stacked drivers
+ * @disk:  MD/DM gendisk (top)
+ * @bdev:  the underlying block device (bottom)
+ * @offset:  offset to beginning of data within component device
+ *
+ * Description:
+ *    Merges the limits for two queues.  Returns 0 if alignment
+ *    didn't change.  Returns -1 if adding the bottom device caused
+ *    misalignment.
+ */
+void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
+		       sector_t offset)
+{
+	struct request_queue *t = disk->queue;
+	struct request_queue *b = bdev_get_queue(bdev);
+
+	offset += get_start_sect(bdev) << 9;
+
+	if (blk_stack_limits(&t->limits, &b->limits, offset) < 0) {
+		char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE];
+
+		disk_name(disk, 0, top);
+		bdevname(bdev, bottom);
+
+		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
+		       top, bottom);
+	}
+
+	if (!t->queue_lock)
+		WARN_ON_ONCE(1);
+	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
+		unsigned long flags;
+
+		spin_lock_irqsave(t->queue_lock, flags);
+		if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
+			queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
+		spin_unlock_irqrestore(t->queue_lock, flags);
+	}
+}
+EXPORT_SYMBOL(disk_stack_limits);
+
+/**
  * blk_queue_dma_pad - set pad mask
  * @q:     the request queue for the device
  * @mask:  pad mask
@@ -396,11 +644,11 @@
 			       dma_drain_needed_fn *dma_drain_needed,
 			       void *buf, unsigned int size)
 {
-	if (q->max_hw_segments < 2 || q->max_phys_segments < 2)
+	if (queue_max_hw_segments(q) < 2 || queue_max_phys_segments(q) < 2)
 		return -EINVAL;
 	/* make room for appending the drain */
-	--q->max_hw_segments;
-	--q->max_phys_segments;
+	blk_queue_max_hw_segments(q, queue_max_hw_segments(q) - 1);
+	blk_queue_max_phys_segments(q, queue_max_phys_segments(q) - 1);
 	q->dma_drain_needed = dma_drain_needed;
 	q->dma_drain_buffer = buf;
 	q->dma_drain_size = size;
@@ -422,7 +670,7 @@
 		       __func__, mask);
 	}
 
-	q->seg_boundary_mask = mask;
+	q->limits.seg_boundary_mask = mask;
 }
 EXPORT_SYMBOL(blk_queue_segment_boundary);
 
diff -druN linux-libre-2.6.30-gnu/block/blk-sysfs.c linux-libre-2.6.31-gnu/block/blk-sysfs.c
--- linux-libre-2.6.30-gnu/block/blk-sysfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-sysfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,9 +16,9 @@
 };
 
 static ssize_t
-queue_var_show(unsigned int var, char *page)
+queue_var_show(unsigned long var, char *page)
 {
-	return sprintf(page, "%d\n", var);
+	return sprintf(page, "%lu\n", var);
 }
 
 static ssize_t
@@ -77,7 +77,8 @@
 
 static ssize_t queue_ra_show(struct request_queue *q, char *page)
 {
-	int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
+	unsigned long ra_kb = q->backing_dev_info.ra_pages <<
+					(PAGE_CACHE_SHIFT - 10);
 
 	return queue_var_show(ra_kb, (page));
 }
@@ -95,21 +96,36 @@
 
 static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
 {
-	int max_sectors_kb = q->max_sectors >> 1;
+	int max_sectors_kb = queue_max_sectors(q) >> 1;
 
 	return queue_var_show(max_sectors_kb, (page));
 }
 
-static ssize_t queue_hw_sector_size_show(struct request_queue *q, char *page)
+static ssize_t queue_logical_block_size_show(struct request_queue *q, char *page)
 {
-	return queue_var_show(q->hardsect_size, page);
+	return queue_var_show(queue_logical_block_size(q), page);
+}
+
+static ssize_t queue_physical_block_size_show(struct request_queue *q, char *page)
+{
+	return queue_var_show(queue_physical_block_size(q), page);
+}
+
+static ssize_t queue_io_min_show(struct request_queue *q, char *page)
+{
+	return queue_var_show(queue_io_min(q), page);
+}
+
+static ssize_t queue_io_opt_show(struct request_queue *q, char *page)
+{
+	return queue_var_show(queue_io_opt(q), page);
 }
 
 static ssize_t
 queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
 {
 	unsigned long max_sectors_kb,
-			max_hw_sectors_kb = q->max_hw_sectors >> 1,
+		max_hw_sectors_kb = queue_max_hw_sectors(q) >> 1,
 			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
 	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
 
@@ -117,7 +133,7 @@
 		return -EINVAL;
 
 	spin_lock_irq(q->queue_lock);
-	q->max_sectors = max_sectors_kb << 1;
+	q->limits.max_sectors = max_sectors_kb << 1;
 	spin_unlock_irq(q->queue_lock);
 
 	return ret;
@@ -125,7 +141,7 @@
 
 static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
 {
-	int max_hw_sectors_kb = q->max_hw_sectors >> 1;
+	int max_hw_sectors_kb = queue_max_hw_sectors(q) >> 1;
 
 	return queue_var_show(max_hw_sectors_kb, (page));
 }
@@ -174,9 +190,9 @@
 
 static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
 {
-	unsigned int set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
+	bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
 
-	return queue_var_show(set != 0, page);
+	return queue_var_show(set, page);
 }
 
 static ssize_t
@@ -249,7 +265,27 @@
 
 static struct queue_sysfs_entry queue_hw_sector_size_entry = {
 	.attr = {.name = "hw_sector_size", .mode = S_IRUGO },
-	.show = queue_hw_sector_size_show,
+	.show = queue_logical_block_size_show,
+};
+
+static struct queue_sysfs_entry queue_logical_block_size_entry = {
+	.attr = {.name = "logical_block_size", .mode = S_IRUGO },
+	.show = queue_logical_block_size_show,
+};
+
+static struct queue_sysfs_entry queue_physical_block_size_entry = {
+	.attr = {.name = "physical_block_size", .mode = S_IRUGO },
+	.show = queue_physical_block_size_show,
+};
+
+static struct queue_sysfs_entry queue_io_min_entry = {
+	.attr = {.name = "minimum_io_size", .mode = S_IRUGO },
+	.show = queue_io_min_show,
+};
+
+static struct queue_sysfs_entry queue_io_opt_entry = {
+	.attr = {.name = "optimal_io_size", .mode = S_IRUGO },
+	.show = queue_io_opt_show,
 };
 
 static struct queue_sysfs_entry queue_nonrot_entry = {
@@ -283,6 +319,10 @@
 	&queue_max_sectors_entry.attr,
 	&queue_iosched_entry.attr,
 	&queue_hw_sector_size_entry.attr,
+	&queue_logical_block_size_entry.attr,
+	&queue_physical_block_size_entry.attr,
+	&queue_io_min_entry.attr,
+	&queue_io_opt_entry.attr,
 	&queue_nonrot_entry.attr,
 	&queue_nomerges_entry.attr,
 	&queue_rq_affinity_entry.attr,
@@ -383,22 +423,26 @@
 int blk_register_queue(struct gendisk *disk)
 {
 	int ret;
+	struct device *dev = disk_to_dev(disk);
 
 	struct request_queue *q = disk->queue;
 
 	if (WARN_ON(!q))
 		return -ENXIO;
 
-	if (!q->request_fn)
-		return 0;
+	ret = blk_trace_init_sysfs(dev);
+	if (ret)
+		return ret;
 
-	ret = kobject_add(&q->kobj, kobject_get(&disk_to_dev(disk)->kobj),
-			  "%s", "queue");
+	ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
 	if (ret < 0)
 		return ret;
 
 	kobject_uevent(&q->kobj, KOBJ_ADD);
 
+	if (!q->request_fn)
+		return 0;
+
 	ret = elv_register_queue(q);
 	if (ret) {
 		kobject_uevent(&q->kobj, KOBJ_REMOVE);
diff -druN linux-libre-2.6.30-gnu/block/blk-tag.c linux-libre-2.6.31-gnu/block/blk-tag.c
--- linux-libre-2.6.30-gnu/block/blk-tag.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-tag.c	2009-09-09 18:13:59.000000000 -0400
@@ -336,7 +336,7 @@
 int blk_queue_start_tag(struct request_queue *q, struct request *rq)
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
-	unsigned max_depth, offset;
+	unsigned max_depth;
 	int tag;
 
 	if (unlikely((rq->cmd_flags & REQ_QUEUED))) {
@@ -355,13 +355,16 @@
 	 * to starve sync IO on behalf of flooding async IO.
 	 */
 	max_depth = bqt->max_depth;
-	if (rq_is_sync(rq))
-		offset = 0;
-	else
-		offset = max_depth >> 2;
+	if (!rq_is_sync(rq) && max_depth > 1) {
+		max_depth -= 2;
+		if (!max_depth)
+			max_depth = 1;
+		if (q->in_flight[0] > max_depth)
+			return 1;
+	}
 
 	do {
-		tag = find_next_zero_bit(bqt->tag_map, max_depth, offset);
+		tag = find_first_zero_bit(bqt->tag_map, max_depth);
 		if (tag >= max_depth)
 			return 1;
 
@@ -374,7 +377,7 @@
 	rq->cmd_flags |= REQ_QUEUED;
 	rq->tag = tag;
 	bqt->tag_index[tag] = rq;
-	blkdev_dequeue_request(rq);
+	blk_start_request(rq);
 	list_add(&rq->queuelist, &q->tag_busy_list);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/block/blk-timeout.c linux-libre-2.6.31-gnu/block/blk-timeout.c
--- linux-libre-2.6.30-gnu/block/blk-timeout.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/blk-timeout.c	2009-09-09 18:13:59.000000000 -0400
@@ -122,10 +122,8 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
-		} else {
-			if (!next || time_after(next, rq->deadline))
-				next = rq->deadline;
-		}
+		} else if (!next || time_after(next, rq->deadline))
+			next = rq->deadline;
 	}
 
 	/*
@@ -176,16 +174,14 @@
 	BUG_ON(!list_empty(&req->timeout_list));
 	BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags));
 
-	if (req->timeout)
-		req->deadline = jiffies + req->timeout;
-	else {
-		req->deadline = jiffies + q->rq_timeout;
-		/*
-		 * Some LLDs, like scsi, peek at the timeout to prevent
-		 * a command from being retried forever.
-		 */
+	/*
+	 * Some LLDs, like scsi, peek at the timeout to prevent a
+	 * command from being retried forever.
+	 */
+	if (!req->timeout)
 		req->timeout = q->rq_timeout;
-	}
+
+	req->deadline = jiffies + req->timeout;
 	list_add_tail(&req->timeout_list, &q->timeout_list);
 
 	/*
diff -druN linux-libre-2.6.30-gnu/block/bsg.c linux-libre-2.6.31-gnu/block/bsg.c
--- linux-libre-2.6.30-gnu/block/bsg.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/bsg.c	2009-09-09 18:13:59.000000000 -0400
@@ -186,7 +186,7 @@
 		return -EFAULT;
 
 	if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
-		if (blk_verify_command(&q->cmd_filter, rq->cmd, has_write_perm))
+		if (blk_verify_command(rq->cmd, has_write_perm))
 			return -EPERM;
 	} else if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
@@ -315,7 +315,6 @@
 	blk_put_request(rq);
 	if (next_rq) {
 		blk_rq_unmap_user(next_rq->bio);
-		next_rq->bio = NULL;
 		blk_put_request(next_rq);
 	}
 	return ERR_PTR(ret);
@@ -446,15 +445,14 @@
 	}
 
 	if (rq->next_rq) {
-		hdr->dout_resid = rq->data_len;
-		hdr->din_resid = rq->next_rq->data_len;
+		hdr->dout_resid = rq->resid_len;
+		hdr->din_resid = rq->next_rq->resid_len;
 		blk_rq_unmap_user(bidi_bio);
-		rq->next_rq->bio = NULL;
 		blk_put_request(rq->next_rq);
 	} else if (rq_data_dir(rq) == READ)
-		hdr->din_resid = rq->data_len;
+		hdr->din_resid = rq->resid_len;
 	else
-		hdr->dout_resid = rq->data_len;
+		hdr->dout_resid = rq->resid_len;
 
 	/*
 	 * If the request generated a negative error number, return it
@@ -468,7 +466,6 @@
 	blk_rq_unmap_user(bio);
 	if (rq->cmd != rq->__cmd)
 		kfree(rq->cmd);
-	rq->bio = NULL;
 	blk_put_request(rq);
 
 	return ret;
@@ -1065,6 +1062,11 @@
 
 static struct cdev bsg_cdev;
 
+static char *bsg_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev));
+}
+
 static int __init bsg_init(void)
 {
 	int ret, i;
@@ -1085,6 +1087,7 @@
 		ret = PTR_ERR(bsg_class);
 		goto destroy_kmemcache;
 	}
+	bsg_class->nodename = bsg_nodename;
 
 	ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
 	if (ret)
diff -druN linux-libre-2.6.30-gnu/block/cfq-iosched.c linux-libre-2.6.31-gnu/block/cfq-iosched.c
--- linux-libre-2.6.30-gnu/block/cfq-iosched.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/cfq-iosched.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,6 +71,51 @@
 #define CFQ_RB_ROOT	(struct cfq_rb_root) { RB_ROOT, NULL, }
 
 /*
+ * Per process-grouping structure
+ */
+struct cfq_queue {
+	/* reference count */
+	atomic_t ref;
+	/* various state flags, see below */
+	unsigned int flags;
+	/* parent cfq_data */
+	struct cfq_data *cfqd;
+	/* service_tree member */
+	struct rb_node rb_node;
+	/* service_tree key */
+	unsigned long rb_key;
+	/* prio tree member */
+	struct rb_node p_node;
+	/* prio tree root we belong to, if any */
+	struct rb_root *p_root;
+	/* sorted list of pending requests */
+	struct rb_root sort_list;
+	/* if fifo isn't expired, next request to serve */
+	struct request *next_rq;
+	/* requests queued in sort_list */
+	int queued[2];
+	/* currently allocated requests */
+	int allocated[2];
+	/* fifo list of requests in sort_list */
+	struct list_head fifo;
+
+	unsigned long slice_end;
+	long slice_resid;
+	unsigned int slice_dispatch;
+
+	/* pending metadata requests */
+	int meta_pending;
+	/* number of requests that are on the dispatch list or inside driver */
+	int dispatched;
+
+	/* io prio of this group */
+	unsigned short ioprio, org_ioprio;
+	unsigned short ioprio_class, org_ioprio_class;
+
+	pid_t pid;
+};
+
+/*
  * Per block device queue structure
  */
 struct cfq_data {
@@ -122,7 +167,6 @@
 	struct cfq_queue *async_idle_cfqq;
 
 	sector_t last_position;
-	unsigned long last_end_request;
 
 	/*
 	 * tunables, see top of file
@@ -136,51 +180,11 @@
 	unsigned int cfq_slice_idle;
 
 	struct list_head cic_list;
-};
-
-/*
- * Per process-grouping structure
- */
-struct cfq_queue {
-	/* reference count */
-	atomic_t ref;
-	/* various state flags, see below */
-	unsigned int flags;
-	/* parent cfq_data */
-	struct cfq_data *cfqd;
-	/* service_tree member */
-	struct rb_node rb_node;
-	/* service_tree key */
-	unsigned long rb_key;
-	/* prio tree member */
-	struct rb_node p_node;
-	/* prio tree root we belong to, if any */
-	struct rb_root *p_root;
-	/* sorted list of pending requests */
-	struct rb_root sort_list;
-	/* if fifo isn't expired, next request to serve */
-	struct request *next_rq;
-	/* requests queued in sort_list */
-	int queued[2];
-	/* currently allocated requests */
-	int allocated[2];
-	/* fifo list of requests in sort_list */
-	struct list_head fifo;
-
-	unsigned long slice_end;
-	long slice_resid;
-	unsigned int slice_dispatch;
-
-	/* pending metadata requests */
-	int meta_pending;
-	/* number of requests that are on the dispatch list or inside driver */
-	int dispatched;
 
-	/* io prio of this group */
-	unsigned short ioprio, org_ioprio;
-	unsigned short ioprio_class, org_ioprio_class;
-
-	pid_t pid;
+	/*
+	 * Fallback dummy cfqq for extreme OOM conditions
+	 */
+	struct cfq_queue oom_cfqq;
 };
 
 enum cfqq_state_flags {
@@ -349,8 +353,8 @@
 	else if (rq_is_meta(rq2) && !rq_is_meta(rq1))
 		return rq2;
 
-	s1 = rq1->sector;
-	s2 = rq2->sector;
+	s1 = blk_rq_pos(rq1);
+	s2 = blk_rq_pos(rq2);
 
 	last = cfqd->last_position;
 
@@ -579,9 +583,9 @@
 		 * Sort strictly based on sector.  Smallest to the left,
 		 * largest to the right.
 		 */
-		if (sector > cfqq->next_rq->sector)
+		if (sector > blk_rq_pos(cfqq->next_rq))
 			n = &(*p)->rb_right;
-		else if (sector < cfqq->next_rq->sector)
+		else if (sector < blk_rq_pos(cfqq->next_rq))
 			n = &(*p)->rb_left;
 		else
 			break;
@@ -611,8 +615,8 @@
 		return;
 
 	cfqq->p_root = &cfqd->prio_trees[cfqq->org_ioprio];
-	__cfqq = cfq_prio_tree_lookup(cfqd, cfqq->p_root, cfqq->next_rq->sector,
-					 &parent, &p);
+	__cfqq = cfq_prio_tree_lookup(cfqd, cfqq->p_root,
+				      blk_rq_pos(cfqq->next_rq), &parent, &p);
 	if (!__cfqq) {
 		rb_link_node(&cfqq->p_node, parent, p);
 		rb_insert_color(&cfqq->p_node, cfqq->p_root);
@@ -760,7 +764,7 @@
 	cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "activate rq, drv=%d",
 						cfqd->rq_in_driver);
 
-	cfqd->last_position = rq->hard_sector + rq->hard_nr_sectors;
+	cfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq);
 }
 
 static void cfq_deactivate_request(struct request_queue *q, struct request *rq)
@@ -949,10 +953,10 @@
 static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
 					  struct request *rq)
 {
-	if (rq->sector >= cfqd->last_position)
-		return rq->sector - cfqd->last_position;
+	if (blk_rq_pos(rq) >= cfqd->last_position)
+		return blk_rq_pos(rq) - cfqd->last_position;
 	else
-		return cfqd->last_position - rq->sector;
+		return cfqd->last_position - blk_rq_pos(rq);
 }
 
 #define CIC_SEEK_THR	8 * 1024
@@ -996,7 +1000,7 @@
 	if (cfq_rq_close(cfqd, __cfqq->next_rq))
 		return __cfqq;
 
-	if (__cfqq->next_rq->sector < sector)
+	if (blk_rq_pos(__cfqq->next_rq) < sector)
 		node = rb_next(&__cfqq->p_node);
 	else
 		node = rb_prev(&__cfqq->p_node);
@@ -1253,7 +1257,7 @@
 
 	BUG_ON(cfqd->busy_queues);
 
-	cfq_log(cfqd, "forced_dispatch=%d\n", dispatched);
+	cfq_log(cfqd, "forced_dispatch=%d", dispatched);
 	return dispatched;
 }
 
@@ -1282,7 +1286,7 @@
 	if (!cfqd->active_cic) {
 		struct cfq_io_context *cic = RQ_CIC(rq);
 
-		atomic_inc(&cic->ioc->refcount);
+		atomic_long_inc(&cic->ioc->refcount);
 		cfqd->active_cic = cic;
 	}
 }
@@ -1642,6 +1646,26 @@
 	ioc->ioprio_changed = 0;
 }
 
+static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+			  pid_t pid, int is_sync)
+{
+	RB_CLEAR_NODE(&cfqq->rb_node);
+	RB_CLEAR_NODE(&cfqq->p_node);
+	INIT_LIST_HEAD(&cfqq->fifo);
+
+	atomic_set(&cfqq->ref, 0);
+	cfqq->cfqd = cfqd;
+
+	cfq_mark_cfqq_prio_changed(cfqq);
+
+	if (is_sync) {
+		if (!cfq_class_idle(cfqq))
+			cfq_mark_cfqq_idle_window(cfqq);
+		cfq_mark_cfqq_sync(cfqq);
+	}
+	cfqq->pid = pid;
+}
+
 static struct cfq_queue *
 cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
 		     struct io_context *ioc, gfp_t gfp_mask)
@@ -1654,56 +1678,40 @@
 	/* cic always exists here */
 	cfqq = cic_to_cfqq(cic, is_sync);
 
-	if (!cfqq) {
+	/*
+	 * Always try a new alloc if we fell back to the OOM cfqq
+	 * originally, since it should just be a temporary situation.
+	 */
+	if (!cfqq || cfqq == &cfqd->oom_cfqq) {
+		cfqq = NULL;
 		if (new_cfqq) {
 			cfqq = new_cfqq;
 			new_cfqq = NULL;
 		} else if (gfp_mask & __GFP_WAIT) {
-			/*
-			 * Inform the allocator of the fact that we will
-			 * just repeat this allocation if it fails, to allow
-			 * the allocator to do whatever it needs to attempt to
-			 * free memory.
-			 */
 			spin_unlock_irq(cfqd->queue->queue_lock);
 			new_cfqq = kmem_cache_alloc_node(cfq_pool,
-					gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
+					gfp_mask | __GFP_ZERO,
 					cfqd->queue->node);
 			spin_lock_irq(cfqd->queue->queue_lock);
-			goto retry;
+			if (new_cfqq)
+				goto retry;
 		} else {
 			cfqq = kmem_cache_alloc_node(cfq_pool,
 					gfp_mask | __GFP_ZERO,
 					cfqd->queue->node);
-			if (!cfqq)
-				goto out;
 		}
 
-		RB_CLEAR_NODE(&cfqq->rb_node);
-		RB_CLEAR_NODE(&cfqq->p_node);
-		INIT_LIST_HEAD(&cfqq->fifo);
-
-		atomic_set(&cfqq->ref, 0);
-		cfqq->cfqd = cfqd;
-
-		cfq_mark_cfqq_prio_changed(cfqq);
-
-		cfq_init_prio_data(cfqq, ioc);
-
-		if (is_sync) {
-			if (!cfq_class_idle(cfqq))
-				cfq_mark_cfqq_idle_window(cfqq);
-			cfq_mark_cfqq_sync(cfqq);
-		}
-		cfqq->pid = current->pid;
-		cfq_log_cfqq(cfqd, cfqq, "alloced");
+		if (cfqq) {
+			cfq_init_cfqq(cfqd, cfqq, current->pid, is_sync);
+			cfq_init_prio_data(cfqq, ioc);
+			cfq_log_cfqq(cfqd, cfqq, "alloced");
+		} else
+			cfqq = &cfqd->oom_cfqq;
 	}
 
 	if (new_cfqq)
 		kmem_cache_free(cfq_pool, new_cfqq);
 
-out:
-	WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
 	return cfqq;
 }
 
@@ -1736,11 +1744,8 @@
 		cfqq = *async_cfqq;
 	}
 
-	if (!cfqq) {
+	if (!cfqq)
 		cfqq = cfq_find_alloc_queue(cfqd, is_sync, ioc, gfp_mask);
-		if (!cfqq)
-			return NULL;
-	}
 
 	/*
 	 * pin the queue now that it's allocated, scheduler exit will prune it
@@ -1918,10 +1923,10 @@
 
 	if (!cic->last_request_pos)
 		sdist = 0;
-	else if (cic->last_request_pos < rq->sector)
-		sdist = rq->sector - cic->last_request_pos;
+	else if (cic->last_request_pos < blk_rq_pos(rq))
+		sdist = blk_rq_pos(rq) - cic->last_request_pos;
 	else
-		sdist = cic->last_request_pos - rq->sector;
+		sdist = cic->last_request_pos - blk_rq_pos(rq);
 
 	/*
 	 * Don't allow the seek distance to get too large from the
@@ -2071,7 +2076,7 @@
 	cfq_update_io_seektime(cfqd, cic, rq);
 	cfq_update_idle_window(cfqd, cfqq, cic);
 
-	cic->last_request_pos = rq->sector + rq->nr_sectors;
+	cic->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
 
 	if (cfqq == cfqd->active_queue) {
 		/*
@@ -2088,7 +2093,7 @@
 			if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE ||
 			    cfqd->busy_queues > 1) {
 				del_timer(&cfqd->idle_slice_timer);
-				blk_start_queueing(cfqd->queue);
+			__blk_run_queue(cfqd->queue);
 			}
 			cfq_mark_cfqq_must_dispatch(cfqq);
 		}
@@ -2100,7 +2105,7 @@
 		 * this new queue is RT and the current one is BE
 		 */
 		cfq_preempt_queue(cfqd, cfqq);
-		blk_start_queueing(cfqd->queue);
+		__blk_run_queue(cfqd->queue);
 	}
 }
 
@@ -2164,9 +2169,6 @@
 	if (cfq_cfqq_sync(cfqq))
 		cfqd->sync_flight--;
 
-	if (!cfq_class_idle(cfqq))
-		cfqd->last_end_request = now;
-
 	if (sync)
 		RQ_CIC(rq)->last_end_request = now;
 
@@ -2309,12 +2311,8 @@
 		goto queue_fail;
 
 	cfqq = cic_to_cfqq(cic, is_sync);
-	if (!cfqq) {
+	if (!cfqq || cfqq == &cfqd->oom_cfqq) {
 		cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask);
-
-		if (!cfqq)
-			goto queue_fail;
-
 		cic_set_cfqq(cic, cfqq, is_sync);
 	}
 
@@ -2345,7 +2343,7 @@
 	struct request_queue *q = cfqd->queue;
 
 	spin_lock_irq(q->queue_lock);
-	blk_start_queueing(q);
+	__blk_run_queue(cfqd->queue);
 	spin_unlock_irq(q->queue_lock);
 }
 
@@ -2469,6 +2467,14 @@
 	for (i = 0; i < CFQ_PRIO_LISTS; i++)
 		cfqd->prio_trees[i] = RB_ROOT;
 
+	/*
+	 * Our fallback cfqq if cfq_find_alloc_queue() runs into OOM issues.
+	 * Grab a permanent reference to it, so that the normal code flow
+	 * will not attempt to free it.
+	 */
+	cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0);
+	atomic_inc(&cfqd->oom_cfqq.ref);
+
 	INIT_LIST_HEAD(&cfqd->cic_list);
 
 	cfqd->queue = q;
@@ -2479,7 +2485,6 @@
 
 	INIT_WORK(&cfqd->unplug_work, cfq_kick_queue);
 
-	cfqd->last_end_request = jiffies;
 	cfqd->cfq_quantum = cfq_quantum;
 	cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
 	cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1];
diff -druN linux-libre-2.6.30-gnu/block/cmd-filter.c linux-libre-2.6.31-gnu/block/cmd-filter.c
--- linux-libre-2.6.30-gnu/block/cmd-filter.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/cmd-filter.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,233 +0,0 @@
-/*
- * Copyright 2004 Peter M. Jones <pjones@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public Licens
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
- *
- */
-
-#include <linux/list.h>
-#include <linux/genhd.h>
-#include <linux/spinlock.h>
-#include <linux/capability.h>
-#include <linux/bitops.h>
-#include <linux/blkdev.h>
-
-#include <scsi/scsi.h>
-#include <linux/cdrom.h>
-
-int blk_verify_command(struct blk_cmd_filter *filter,
-		       unsigned char *cmd, fmode_t has_write_perm)
-{
-	/* root can do any command. */
-	if (capable(CAP_SYS_RAWIO))
-		return 0;
-
-	/* if there's no filter set, assume we're filtering everything out */
-	if (!filter)
-		return -EPERM;
-
-	/* Anybody who can open the device can do a read-safe command */
-	if (test_bit(cmd[0], filter->read_ok))
-		return 0;
-
-	/* Write-safe commands require a writable open */
-	if (test_bit(cmd[0], filter->write_ok) && has_write_perm)
-		return 0;
-
-	return -EPERM;
-}
-EXPORT_SYMBOL(blk_verify_command);
-
-#if 0
-/* and now, the sysfs stuff */
-static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page,
-			     int rw)
-{
-	char *npage = page;
-	unsigned long *okbits;
-	int i;
-
-	if (rw == READ)
-		okbits = filter->read_ok;
-	else
-		okbits = filter->write_ok;
-
-	for (i = 0; i < BLK_SCSI_MAX_CMDS; i++) {
-		if (test_bit(i, okbits)) {
-			npage += sprintf(npage, "0x%02x", i);
-			if (i < BLK_SCSI_MAX_CMDS - 1)
-				sprintf(npage++, " ");
-		}
-	}
-
-	if (npage != page)
-		npage += sprintf(npage, "\n");
-
-	return npage - page;
-}
-
-static ssize_t rcf_readcmds_show(struct blk_cmd_filter *filter, char *page)
-{
-	return rcf_cmds_show(filter, page, READ);
-}
-
-static ssize_t rcf_writecmds_show(struct blk_cmd_filter *filter,
-				 char *page)
-{
-	return rcf_cmds_show(filter, page, WRITE);
-}
-
-static ssize_t rcf_cmds_store(struct blk_cmd_filter *filter,
-			      const char *page, size_t count, int rw)
-{
-	unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits;
-	int cmd, set;
-	char *p, *status;
-
-	if (rw == READ) {
-		memcpy(&okbits, filter->read_ok, sizeof(okbits));
-		target_okbits = filter->read_ok;
-	} else {
-		memcpy(&okbits, filter->write_ok, sizeof(okbits));
-		target_okbits = filter->write_ok;
-	}
-
-	while ((p = strsep((char **)&page, " ")) != NULL) {
-		set = 1;
-
-		if (p[0] == '+') {
-			p++;
-		} else if (p[0] == '-') {
-			set = 0;
-			p++;
-		}
-
-		cmd = simple_strtol(p, &status, 16);
-
-		/* either of these cases means invalid input, so do nothing. */
-		if ((status == p) || cmd >= BLK_SCSI_MAX_CMDS)
-			return -EINVAL;
-
-		if (set)
-			__set_bit(cmd, okbits);
-		else
-			__clear_bit(cmd, okbits);
-	}
-
-	memcpy(target_okbits, okbits, sizeof(okbits));
-	return count;
-}
-
-static ssize_t rcf_readcmds_store(struct blk_cmd_filter *filter,
-				  const char *page, size_t count)
-{
-	return rcf_cmds_store(filter, page, count, READ);
-}
-
-static ssize_t rcf_writecmds_store(struct blk_cmd_filter *filter,
-				   const char *page, size_t count)
-{
-	return rcf_cmds_store(filter, page, count, WRITE);
-}
-
-struct rcf_sysfs_entry {
-	struct attribute attr;
-	ssize_t (*show)(struct blk_cmd_filter *, char *);
-	ssize_t (*store)(struct blk_cmd_filter *, const char *, size_t);
-};
-
-static struct rcf_sysfs_entry rcf_readcmds_entry = {
-	.attr = { .name = "read_table", .mode = S_IRUGO | S_IWUSR },
-	.show = rcf_readcmds_show,
-	.store = rcf_readcmds_store,
-};
-
-static struct rcf_sysfs_entry rcf_writecmds_entry = {
-	.attr = {.name = "write_table", .mode = S_IRUGO | S_IWUSR },
-	.show = rcf_writecmds_show,
-	.store = rcf_writecmds_store,
-};
-
-static struct attribute *default_attrs[] = {
-	&rcf_readcmds_entry.attr,
-	&rcf_writecmds_entry.attr,
-	NULL,
-};
-
-#define to_rcf(atr) container_of((atr), struct rcf_sysfs_entry, attr)
-
-static ssize_t
-rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
-{
-	struct rcf_sysfs_entry *entry = to_rcf(attr);
-	struct blk_cmd_filter *filter;
-
-	filter = container_of(kobj, struct blk_cmd_filter, kobj);
-	if (entry->show)
-		return entry->show(filter, page);
-
-	return 0;
-}
-
-static ssize_t
-rcf_attr_store(struct kobject *kobj, struct attribute *attr,
-			const char *page, size_t length)
-{
-	struct rcf_sysfs_entry *entry = to_rcf(attr);
-	struct blk_cmd_filter *filter;
-
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
-	if (!entry->store)
-		return -EINVAL;
-
-	filter = container_of(kobj, struct blk_cmd_filter, kobj);
-	return entry->store(filter, page, length);
-}
-
-static struct sysfs_ops rcf_sysfs_ops = {
-	.show = rcf_attr_show,
-	.store = rcf_attr_store,
-};
-
-static struct kobj_type rcf_ktype = {
-	.sysfs_ops = &rcf_sysfs_ops,
-	.default_attrs = default_attrs,
-};
-
-int blk_register_filter(struct gendisk *disk)
-{
-	int ret;
-	struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
-
-	ret = kobject_init_and_add(&filter->kobj, &rcf_ktype,
-				   &disk_to_dev(disk)->kobj,
-				   "%s", "cmd_filter");
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-EXPORT_SYMBOL(blk_register_filter);
-
-void blk_unregister_filter(struct gendisk *disk)
-{
-	struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
-
-	kobject_put(&filter->kobj);
-}
-EXPORT_SYMBOL(blk_unregister_filter);
-#endif
diff -druN linux-libre-2.6.30-gnu/block/compat_ioctl.c linux-libre-2.6.31-gnu/block/compat_ioctl.c
--- linux-libre-2.6.30-gnu/block/compat_ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/compat_ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -568,7 +568,7 @@
 	memcpy(&buts.name, &cbuts.name, 32);
 
 	mutex_lock(&bdev->bd_mutex);
-	ret = do_blk_trace_setup(q, b, bdev->bd_dev, &buts);
+	ret = do_blk_trace_setup(q, b, bdev->bd_dev, bdev, &buts);
 	mutex_unlock(&bdev->bd_mutex);
 	if (ret)
 		return ret;
@@ -763,10 +763,10 @@
 	case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
 		return compat_put_int(arg, block_size(bdev));
 	case BLKSSZGET: /* get block device hardware sector size */
-		return compat_put_int(arg, bdev_hardsect_size(bdev));
+		return compat_put_int(arg, bdev_logical_block_size(bdev));
 	case BLKSECTGET:
 		return compat_put_ushort(arg,
-					 bdev_get_queue(bdev)->max_sectors);
+					 queue_max_sectors(bdev_get_queue(bdev)));
 	case BLKRASET: /* compatible, but no compat_ptr (!) */
 	case BLKFRASET:
 		if (!capable(CAP_SYS_ADMIN))
diff -druN linux-libre-2.6.30-gnu/block/deadline-iosched.c linux-libre-2.6.31-gnu/block/deadline-iosched.c
--- linux-libre-2.6.30-gnu/block/deadline-iosched.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/deadline-iosched.c	2009-09-09 18:13:59.000000000 -0400
@@ -138,7 +138,7 @@
 
 		__rq = elv_rb_find(&dd->sort_list[bio_data_dir(bio)], sector);
 		if (__rq) {
-			BUG_ON(sector != __rq->sector);
+			BUG_ON(sector != blk_rq_pos(__rq));
 
 			if (elv_rq_merge_ok(__rq, bio)) {
 				ret = ELEVATOR_FRONT_MERGE;
diff -druN linux-libre-2.6.30-gnu/block/elevator.c linux-libre-2.6.31-gnu/block/elevator.c
--- linux-libre-2.6.30-gnu/block/elevator.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/elevator.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,17 +33,16 @@
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
-#include <trace/block.h>
 #include <linux/hash.h>
 #include <linux/uaccess.h>
 
+#include <trace/events/block.h>
+
 #include "blk.h"
 
 static DEFINE_SPINLOCK(elv_list_lock);
 static LIST_HEAD(elv_list);
 
-DEFINE_TRACE(block_rq_abort);
-
 /*
  * Merge hash stuff.
  */
@@ -52,11 +51,7 @@
 #define ELV_HASH_FN(sec)	\
 		(hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift))
 #define ELV_HASH_ENTRIES	(1 << elv_hash_shift)
-#define rq_hash_key(rq)		((rq)->sector + (rq)->nr_sectors)
-#define ELV_ON_HASH(rq)		(!hlist_unhashed(&(rq)->hash))
-
-DEFINE_TRACE(block_rq_insert);
-DEFINE_TRACE(block_rq_issue);
+#define rq_hash_key(rq)		(blk_rq_pos(rq) + blk_rq_sectors(rq))
 
 /*
  * Query io scheduler to see if the current process issuing bio may be
@@ -105,6 +100,19 @@
 	if (bio_integrity(bio) != blk_integrity_rq(rq))
 		return 0;
 
+	/*
+	 * Don't merge if failfast settings don't match.
+	 *
+	 * FIXME: The negation in front of each condition is necessary
+	 * because bio and request flags use different bit positions
+	 * and the accessors return those bits directly.  This
+	 * ugliness will soon go away.
+	 */
+	if (!bio_failfast_dev(bio)	 != !blk_failfast_dev(rq)	||
+	    !bio_failfast_transport(bio) != !blk_failfast_transport(rq)	||
+	    !bio_failfast_driver(bio)	 != !blk_failfast_driver(rq))
+		return 0;
+
 	if (!elv_iosched_allow_merge(rq, bio))
 		return 0;
 
@@ -120,9 +128,9 @@
 	 * we can merge and sequence is ok, check if it's possible
 	 */
 	if (elv_rq_merge_ok(__rq, bio)) {
-		if (__rq->sector + __rq->nr_sectors == bio->bi_sector)
+		if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector)
 			ret = ELEVATOR_BACK_MERGE;
-		else if (__rq->sector - bio_sectors(bio) == bio->bi_sector)
+		else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector)
 			ret = ELEVATOR_FRONT_MERGE;
 	}
 
@@ -310,22 +318,6 @@
 }
 EXPORT_SYMBOL(elevator_exit);
 
-static void elv_activate_rq(struct request_queue *q, struct request *rq)
-{
-	struct elevator_queue *e = q->elevator;
-
-	if (e->ops->elevator_activate_req_fn)
-		e->ops->elevator_activate_req_fn(q, rq);
-}
-
-static void elv_deactivate_rq(struct request_queue *q, struct request *rq)
-{
-	struct elevator_queue *e = q->elevator;
-
-	if (e->ops->elevator_deactivate_req_fn)
-		e->ops->elevator_deactivate_req_fn(q, rq);
-}
-
 static inline void __elv_rqhash_del(struct request *rq)
 {
 	hlist_del_init(&rq->hash);
@@ -387,9 +379,9 @@
 		parent = *p;
 		__rq = rb_entry(parent, struct request, rb_node);
 
-		if (rq->sector < __rq->sector)
+		if (blk_rq_pos(rq) < blk_rq_pos(__rq))
 			p = &(*p)->rb_left;
-		else if (rq->sector > __rq->sector)
+		else if (blk_rq_pos(rq) > blk_rq_pos(__rq))
 			p = &(*p)->rb_right;
 		else
 			return __rq;
@@ -417,9 +409,9 @@
 	while (n) {
 		rq = rb_entry(n, struct request, rb_node);
 
-		if (sector < rq->sector)
+		if (sector < blk_rq_pos(rq))
 			n = n->rb_left;
-		else if (sector > rq->sector)
+		else if (sector > blk_rq_pos(rq))
 			n = n->rb_right;
 		else
 			return rq;
@@ -458,14 +450,14 @@
 			break;
 		if (pos->cmd_flags & stop_flags)
 			break;
-		if (rq->sector >= boundary) {
-			if (pos->sector < boundary)
+		if (blk_rq_pos(rq) >= boundary) {
+			if (blk_rq_pos(pos) < boundary)
 				continue;
 		} else {
-			if (pos->sector >= boundary)
+			if (blk_rq_pos(pos) >= boundary)
 				break;
 		}
-		if (rq->sector >= pos->sector)
+		if (blk_rq_pos(rq) >= blk_rq_pos(pos))
 			break;
 	}
 
@@ -563,7 +555,7 @@
 	 * in_flight count again
 	 */
 	if (blk_account_rq(rq)) {
-		q->in_flight--;
+		q->in_flight[rq_is_sync(rq)]--;
 		if (blk_sorted_rq(rq))
 			elv_deactivate_rq(q, rq);
 	}
@@ -592,6 +584,9 @@
  */
 void elv_quiesce_start(struct request_queue *q)
 {
+	if (!q->elevator)
+		return;
+
 	queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
 
 	/*
@@ -599,7 +594,7 @@
 	 */
 	elv_drain_elevator(q);
 	while (q->rq.elvpriv) {
-		blk_start_queueing(q);
+		__blk_run_queue(q);
 		spin_unlock_irq(q->queue_lock);
 		msleep(10);
 		spin_lock_irq(q->queue_lock);
@@ -643,8 +638,7 @@
 		 *   with anything.  There's no point in delaying queue
 		 *   processing.
 		 */
-		blk_remove_plug(q);
-		blk_start_queueing(q);
+		__blk_run_queue(q);
 		break;
 
 	case ELEVATOR_INSERT_SORT:
@@ -703,7 +697,7 @@
 
 	if (unplug_it && blk_queue_plugged(q)) {
 		int nrq = q->rq.count[BLK_RW_SYNC] + q->rq.count[BLK_RW_ASYNC]
-			- q->in_flight;
+				- queue_in_flight(q);
 
 		if (nrq >= q->unplug_thresh)
 			__generic_unplug_device(q);
@@ -759,117 +753,6 @@
 }
 EXPORT_SYMBOL(elv_add_request);
 
-static inline struct request *__elv_next_request(struct request_queue *q)
-{
-	struct request *rq;
-
-	while (1) {
-		while (!list_empty(&q->queue_head)) {
-			rq = list_entry_rq(q->queue_head.next);
-			if (blk_do_ordered(q, &rq))
-				return rq;
-		}
-
-		if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
-			return NULL;
-	}
-}
-
-struct request *elv_next_request(struct request_queue *q)
-{
-	struct request *rq;
-	int ret;
-
-	while ((rq = __elv_next_request(q)) != NULL) {
-		if (!(rq->cmd_flags & REQ_STARTED)) {
-			/*
-			 * This is the first time the device driver
-			 * sees this request (possibly after
-			 * requeueing).  Notify IO scheduler.
-			 */
-			if (blk_sorted_rq(rq))
-				elv_activate_rq(q, rq);
-
-			/*
-			 * just mark as started even if we don't start
-			 * it, a request that has been delayed should
-			 * not be passed by new incoming requests
-			 */
-			rq->cmd_flags |= REQ_STARTED;
-			trace_block_rq_issue(q, rq);
-		}
-
-		if (!q->boundary_rq || q->boundary_rq == rq) {
-			q->end_sector = rq_end_sector(rq);
-			q->boundary_rq = NULL;
-		}
-
-		if (rq->cmd_flags & REQ_DONTPREP)
-			break;
-
-		if (q->dma_drain_size && rq->data_len) {
-			/*
-			 * make sure space for the drain appears we
-			 * know we can do this because max_hw_segments
-			 * has been adjusted to be one fewer than the
-			 * device can handle
-			 */
-			rq->nr_phys_segments++;
-		}
-
-		if (!q->prep_rq_fn)
-			break;
-
-		ret = q->prep_rq_fn(q, rq);
-		if (ret == BLKPREP_OK) {
-			break;
-		} else if (ret == BLKPREP_DEFER) {
-			/*
-			 * the request may have been (partially) prepped.
-			 * we need to keep this request in the front to
-			 * avoid resource deadlock.  REQ_STARTED will
-			 * prevent other fs requests from passing this one.
-			 */
-			if (q->dma_drain_size && rq->data_len &&
-			    !(rq->cmd_flags & REQ_DONTPREP)) {
-				/*
-				 * remove the space for the drain we added
-				 * so that we don't add it again
-				 */
-				--rq->nr_phys_segments;
-			}
-
-			rq = NULL;
-			break;
-		} else if (ret == BLKPREP_KILL) {
-			rq->cmd_flags |= REQ_QUIET;
-			__blk_end_request(rq, -EIO, blk_rq_bytes(rq));
-		} else {
-			printk(KERN_ERR "%s: bad return=%d\n", __func__, ret);
-			break;
-		}
-	}
-
-	return rq;
-}
-EXPORT_SYMBOL(elv_next_request);
-
-void elv_dequeue_request(struct request_queue *q, struct request *rq)
-{
-	BUG_ON(list_empty(&rq->queuelist));
-	BUG_ON(ELV_ON_HASH(rq));
-
-	list_del_init(&rq->queuelist);
-
-	/*
-	 * the time frame between a request being removed from the lists
-	 * and to it is freed is accounted as io that is in progress at
-	 * the driver side.
-	 */
-	if (blk_account_rq(rq))
-		q->in_flight++;
-}
-
 int elv_queue_empty(struct request_queue *q)
 {
 	struct elevator_queue *e = q->elevator;
@@ -939,7 +822,12 @@
 		rq = list_entry_rq(q->queue_head.next);
 		rq->cmd_flags |= REQ_QUIET;
 		trace_block_rq_abort(q, rq);
-		__blk_end_request(rq, -EIO, blk_rq_bytes(rq));
+		/*
+		 * Mark this request as started so we don't trigger
+		 * any debug logic in the end I/O path.
+		 */
+		blk_start_request(rq);
+		__blk_end_request_all(rq, -EIO);
 	}
 }
 EXPORT_SYMBOL(elv_abort_queue);
@@ -952,7 +840,7 @@
 	 * request is released from the driver, io must be done
 	 */
 	if (blk_account_rq(rq)) {
-		q->in_flight--;
+		q->in_flight[rq_is_sync(rq)]--;
 		if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
 			e->ops->elevator_completed_req_fn(q, rq);
 	}
@@ -967,11 +855,11 @@
 		if (!list_empty(&q->queue_head))
 			next = list_entry_rq(q->queue_head.next);
 
-		if (!q->in_flight &&
+		if (!queue_in_flight(q) &&
 		    blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
 		    (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) {
 			blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
-			blk_start_queueing(q);
+			__blk_run_queue(q);
 		}
 	}
 }
@@ -1179,6 +1067,9 @@
 	char elevator_name[ELV_NAME_MAX];
 	struct elevator_type *e;
 
+	if (!q->elevator)
+		return count;
+
 	strlcpy(elevator_name, name, sizeof(elevator_name));
 	strstrip(elevator_name);
 
@@ -1202,10 +1093,15 @@
 ssize_t elv_iosched_show(struct request_queue *q, char *name)
 {
 	struct elevator_queue *e = q->elevator;
-	struct elevator_type *elv = e->elevator_type;
+	struct elevator_type *elv;
 	struct elevator_type *__e;
 	int len = 0;
 
+	if (!q->elevator)
+		return sprintf(name, "none\n");
+
+	elv = e->elevator_type;
+
 	spin_lock(&elv_list_lock);
 	list_for_each_entry(__e, &elv_list, list) {
 		if (!strcmp(elv->elevator_name, __e->elevator_name))
diff -druN linux-libre-2.6.30-gnu/block/genhd.c linux-libre-2.6.31-gnu/block/genhd.c
--- linux-libre-2.6.30-gnu/block/genhd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/genhd.c	2009-09-09 18:13:59.000000000 -0400
@@ -852,11 +852,21 @@
 	return sprintf(buf, "%x\n", disk->flags);
 }
 
+static ssize_t disk_alignment_offset_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+
+	return sprintf(buf, "%d\n", queue_alignment_offset(disk->queue));
+}
+
 static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
 static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL);
 static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
 static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL);
 static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
+static DEVICE_ATTR(alignment_offset, S_IRUGO, disk_alignment_offset_show, NULL);
 static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL);
 static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
 #ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -875,6 +885,7 @@
 	&dev_attr_removable.attr,
 	&dev_attr_ro.attr,
 	&dev_attr_size.attr,
+	&dev_attr_alignment_offset.attr,
 	&dev_attr_capability.attr,
 	&dev_attr_stat.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -985,10 +996,20 @@
 	.name		= "block",
 };
 
+static char *block_nodename(struct device *dev)
+{
+	struct gendisk *disk = dev_to_disk(dev);
+
+	if (disk->nodename)
+		return disk->nodename(disk);
+	return NULL;
+}
+
 static struct device_type disk_type = {
 	.name		= "disk",
 	.groups		= disk_attr_groups,
 	.release	= disk_release,
+	.nodename	= block_nodename,
 };
 
 #ifdef CONFIG_PROC_FS
diff -druN linux-libre-2.6.30-gnu/block/ioctl.c linux-libre-2.6.31-gnu/block/ioctl.c
--- linux-libre-2.6.30-gnu/block/ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -152,10 +152,10 @@
 		bio->bi_private = &wait;
 		bio->bi_sector = start;
 
-		if (len > q->max_hw_sectors) {
-			bio->bi_size = q->max_hw_sectors << 9;
-			len -= q->max_hw_sectors;
-			start += q->max_hw_sectors;
+		if (len > queue_max_hw_sectors(q)) {
+			bio->bi_size = queue_max_hw_sectors(q) << 9;
+			len -= queue_max_hw_sectors(q);
+			start += queue_max_hw_sectors(q);
 		} else {
 			bio->bi_size = len << 9;
 			len = 0;
@@ -311,9 +311,9 @@
 	case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */
 		return put_int(arg, block_size(bdev));
 	case BLKSSZGET: /* get block device hardware sector size */
-		return put_int(arg, bdev_hardsect_size(bdev));
+		return put_int(arg, bdev_logical_block_size(bdev));
 	case BLKSECTGET:
-		return put_ushort(arg, bdev_get_queue(bdev)->max_sectors);
+		return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev)));
 	case BLKRASET:
 	case BLKFRASET:
 		if(!capable(CAP_SYS_ADMIN))
diff -druN linux-libre-2.6.30-gnu/block/Kconfig linux-libre-2.6.31-gnu/block/Kconfig
--- linux-libre-2.6.30-gnu/block/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -23,9 +23,10 @@
 
 if BLOCK
 
-config LBD
-	bool "Support for large block devices and files"
+config LBDAF
+	bool "Support for large (2TB+) block devices and files"
 	depends on !64BIT
+	default y
 	help
 	  Enable block devices or files of size 2TB and larger.
 
@@ -38,16 +39,18 @@
 
 	  The ext4 filesystem requires that this feature be enabled in
 	  order to support filesystems that have the huge_file feature
-	  enabled.    Otherwise, it will refuse to mount any filesystems
-	  that use the huge_file feature, which is enabled by default
-	  by mke2fs.ext4.   The GFS2 filesystem also requires this feature.
+	  enabled.  Otherwise, it will refuse to mount in the read-write
+	  mode any filesystems that use the huge_file feature, which is
+	  enabled by default by mke2fs.ext4.
 
-	  If unsure, say N.
+	  The GFS2 filesystem also requires this feature.
+
+	  If unsure, say Y.
 
 config BLK_DEV_BSG
-	bool "Block layer SG support v4 (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	---help---
+	bool "Block layer SG support v4"
+	default y
+	help
 	  Saying Y here will enable generic SG (SCSI generic) v4 support
 	  for any block device.
 
@@ -57,7 +60,10 @@
 	  protocols (e.g. Task Management Functions and SMP in Serial
 	  Attached SCSI).
 
-	  If unsure, say N.
+	  This option is required by recent UDEV versions to properly
+	  access device serial numbers, etc.
+
+	  If unsure, say Y.
 
 config BLK_DEV_INTEGRITY
 	bool "Block layer data integrity support"
diff -druN linux-libre-2.6.30-gnu/block/Makefile linux-libre-2.6.31-gnu/block/Makefile
--- linux-libre-2.6.30-gnu/block/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -5,7 +5,7 @@
 obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
 			blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \
 			blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
-			ioctl.o genhd.o scsi_ioctl.o cmd-filter.o
+			ioctl.o genhd.o scsi_ioctl.o
 
 obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
 obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
diff -druN linux-libre-2.6.30-gnu/block/scsi_ioctl.c linux-libre-2.6.31-gnu/block/scsi_ioctl.c
--- linux-libre-2.6.30-gnu/block/scsi_ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/block/scsi_ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,11 @@
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_cmnd.h>
 
+struct blk_cmd_filter {
+	unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
+	unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
+} blk_default_cmd_filter;
+
 /* Command group 3 is reserved and should never be used.  */
 const unsigned char scsi_command_size_tbl[8] =
 {
@@ -75,7 +80,7 @@
 
 static int sg_get_reserved_size(struct request_queue *q, int __user *p)
 {
-	unsigned val = min(q->sg_reserved_size, q->max_sectors << 9);
+	unsigned val = min(q->sg_reserved_size, queue_max_sectors(q) << 9);
 
 	return put_user(val, p);
 }
@@ -89,8 +94,8 @@
 
 	if (size < 0)
 		return -EINVAL;
-	if (size > (q->max_sectors << 9))
-		size = q->max_sectors << 9;
+	if (size > (queue_max_sectors(q) << 9))
+		size = queue_max_sectors(q) << 9;
 
 	q->sg_reserved_size = size;
 	return 0;
@@ -105,7 +110,7 @@
 	return put_user(1, p);
 }
 
-void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
+static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
 {
 	/* Basic read-only commands */
 	__set_bit(TEST_UNIT_READY, filter->read_ok);
@@ -187,14 +192,37 @@
 	__set_bit(GPCMD_SET_STREAMING, filter->write_ok);
 	__set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok);
 }
-EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults);
+
+int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm)
+{
+	struct blk_cmd_filter *filter = &blk_default_cmd_filter;
+
+	/* root can do any command. */
+	if (capable(CAP_SYS_RAWIO))
+		return 0;
+
+	/* if there's no filter set, assume we're filtering everything out */
+	if (!filter)
+		return -EPERM;
+
+	/* Anybody who can open the device can do a read-safe command */
+	if (test_bit(cmd[0], filter->read_ok))
+		return 0;
+
+	/* Write-safe commands require a writable open */
+	if (test_bit(cmd[0], filter->write_ok) && has_write_perm)
+		return 0;
+
+	return -EPERM;
+}
+EXPORT_SYMBOL(blk_verify_command);
 
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
 			     struct sg_io_hdr *hdr, fmode_t mode)
 {
 	if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
 		return -EFAULT;
-	if (blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE))
+	if (blk_verify_command(rq->cmd, mode & FMODE_WRITE))
 		return -EPERM;
 
 	/*
@@ -230,7 +258,7 @@
 	hdr->info = 0;
 	if (hdr->masked_status || hdr->host_status || hdr->driver_status)
 		hdr->info |= SG_INFO_CHECK;
-	hdr->resid = rq->data_len;
+	hdr->resid = rq->resid_len;
 	hdr->sb_len_wr = 0;
 
 	if (rq->sense_len && hdr->sbp) {
@@ -264,7 +292,7 @@
 	if (hdr->cmd_len > BLK_MAX_CDB)
 		return -EINVAL;
 
-	if (hdr->dxfer_len > (q->max_hw_sectors << 9))
+	if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
 		return -EIO;
 
 	if (hdr->dxfer_len)
@@ -427,7 +455,7 @@
 	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
 		goto error;
 
-	err = blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE);
+	err = blk_verify_command(rq->cmd, mode & FMODE_WRITE);
 	if (err)
 		goto error;
 
@@ -500,9 +528,6 @@
 
 	rq = blk_get_request(q, WRITE, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
-	rq->data = NULL;
-	rq->data_len = 0;
-	rq->extra_len = 0;
 	rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
 	rq->cmd[0] = cmd;
 	rq->cmd[4] = data;
@@ -648,5 +673,11 @@
 	blk_put_queue(q);
 	return err;
 }
-
 EXPORT_SYMBOL(scsi_cmd_ioctl);
+
+int __init blk_scsi_ioctl_init(void)
+{
+	blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
+	return 0;
+}
+fs_initcall(blk_scsi_ioctl_init);
diff -druN linux-libre-2.6.30-gnu/CREDITS linux-libre-2.6.31-gnu/CREDITS
--- linux-libre-2.6.30-gnu/CREDITS	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/CREDITS	2009-09-09 18:13:59.000000000 -0400
@@ -1253,6 +1253,10 @@
 S: Sterling Heights, Michigan 48313
 S: USA
 
+N: Wolfgang Grandegger
+E: wg@grandegger.com
+D: Controller Area Network (device drivers)
+
 N: William Greathouse
 E: wgreathouse@smva.com
 E: wgreathouse@myfavoritei.com
@@ -1852,7 +1856,7 @@
 D: The Linux Support Team Erlangen
 
 N: Andreas Koensgen
-E: ajk@iehk.rwth-aachen.de
+E: ajk@comnets.uni-bremen.de
 D: 6pack driver for AX.25
 
 N: Harald Koerfgen
@@ -2002,6 +2006,9 @@
 D: Soundblaster driver fixes, ISAPnP quirk
 S: California, USA
 
+N: Jonathan Layes
+D: ARPD support
+
 N: Tom Lees
 E: tom@lpsg.demon.co.uk
 W: http://www.lpsg.demon.co.uk/
@@ -3798,6 +3805,9 @@
 S: 2612 XV Delft
 S: The Netherlands
 
+N: Thomas Woller
+D: CS461x Cirrus Logic sound driver
+
 N: David Woodhouse
 E: dwmw2@infradead.org
 D: JFFS2 file system, Memory Technology Device subsystem,
diff -druN linux-libre-2.6.30-gnu/crypto/algapi.c linux-libre-2.6.31-gnu/crypto/algapi.c
--- linux-libre-2.6.30-gnu/crypto/algapi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/algapi.c	2009-09-09 18:13:59.000000000 -0400
@@ -692,7 +692,7 @@
 }
 EXPORT_SYMBOL_GPL(crypto_enqueue_request);
 
-struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
+void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset)
 {
 	struct list_head *request;
 
@@ -707,7 +707,14 @@
 	request = queue->list.next;
 	list_del(request);
 
-	return list_entry(request, struct crypto_async_request, list);
+	return (char *)list_entry(request, struct crypto_async_request, list) -
+	       offset;
+}
+EXPORT_SYMBOL_GPL(__crypto_dequeue_request);
+
+struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
+{
+	return __crypto_dequeue_request(queue, 0);
 }
 EXPORT_SYMBOL_GPL(crypto_dequeue_request);
 
diff -druN linux-libre-2.6.30-gnu/crypto/algboss.c linux-libre-2.6.31-gnu/crypto/algboss.c
--- linux-libre-2.6.30-gnu/crypto/algboss.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/algboss.c	2009-09-09 18:13:59.000000000 -0400
@@ -280,29 +280,13 @@
 
 static int __init cryptomgr_init(void)
 {
-	int err;
-
-	err = testmgr_init();
-	if (err)
-		return err;
-
-	err = crypto_register_notifier(&cryptomgr_notifier);
-	if (err)
-		goto free_testmgr;
-
-	return 0;
-
-free_testmgr:
-	testmgr_exit();
-	return err;
+	return crypto_register_notifier(&cryptomgr_notifier);
 }
 
 static void __exit cryptomgr_exit(void)
 {
 	int err = crypto_unregister_notifier(&cryptomgr_notifier);
 	BUG_ON(err);
-
-	testmgr_exit();
 }
 
 subsys_initcall(cryptomgr_init);
diff -druN linux-libre-2.6.30-gnu/crypto/api.c linux-libre-2.6.31-gnu/crypto/api.c
--- linux-libre-2.6.30-gnu/crypto/api.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/api.c	2009-09-09 18:13:59.000000000 -0400
@@ -217,14 +217,11 @@
 
 	alg = crypto_alg_lookup(name, type, mask);
 	if (!alg) {
-		char tmp[CRYPTO_MAX_ALG_NAME];
-
-		request_module(name);
+		request_module("%s", name);
 
 		if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
-		      CRYPTO_ALG_NEED_FALLBACK) &&
-		    snprintf(tmp, sizeof(tmp), "%s-all", name) < sizeof(tmp))
-			request_module(tmp);
+		      CRYPTO_ALG_NEED_FALLBACK))
+			request_module("%s-all", name);
 
 		alg = crypto_alg_lookup(name, type, mask);
 	}
@@ -580,20 +577,17 @@
 void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
 {
 	struct crypto_alg *alg;
-	int size;
 
 	if (unlikely(!mem))
 		return;
 
 	alg = tfm->__crt_alg;
-	size = ksize(mem);
 
 	if (!tfm->exit && alg->cra_exit)
 		alg->cra_exit(tfm);
 	crypto_exit_ops(tfm);
 	crypto_mod_put(alg);
-	memset(mem, 0, size);
-	kfree(mem);
+	kzfree(mem);
 }
 EXPORT_SYMBOL_GPL(crypto_destroy_tfm);
 
diff -druN linux-libre-2.6.30-gnu/crypto/async_tx/async_xor.c linux-libre-2.6.31-gnu/crypto/async_tx/async_xor.c
--- linux-libre-2.6.30-gnu/crypto/async_tx/async_xor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/async_tx/async_xor.c	2009-09-09 18:13:59.000000000 -0400
@@ -300,7 +300,7 @@
 
 static int __init async_xor_init(void)
 {
-	#ifdef CONFIG_DMA_ENGINE
+	#ifdef CONFIG_ASYNC_TX_DMA
 	/* To conserve stack space the input src_list (array of page pointers)
 	 * is reused to hold the array of dma addresses passed to the driver.
 	 * This conversion is only possible when dma_addr_t is less than the
diff -druN linux-libre-2.6.30-gnu/crypto/cryptd.c linux-libre-2.6.31-gnu/crypto/cryptd.c
--- linux-libre-2.6.30-gnu/crypto/cryptd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/cryptd.c	2009-09-09 18:13:59.000000000 -0400
@@ -586,20 +586,24 @@
 						  u32 type, u32 mask)
 {
 	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
-	struct crypto_ablkcipher *tfm;
+	struct crypto_tfm *tfm;
 
 	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
 		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
 		return ERR_PTR(-EINVAL);
-	tfm = crypto_alloc_ablkcipher(cryptd_alg_name, type, mask);
+	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+	type |= CRYPTO_ALG_TYPE_BLKCIPHER;
+	mask &= ~CRYPTO_ALG_TYPE_MASK;
+	mask |= (CRYPTO_ALG_GENIV | CRYPTO_ALG_TYPE_BLKCIPHER_MASK);
+	tfm = crypto_alloc_base(cryptd_alg_name, type, mask);
 	if (IS_ERR(tfm))
 		return ERR_CAST(tfm);
-	if (crypto_ablkcipher_tfm(tfm)->__crt_alg->cra_module != THIS_MODULE) {
-		crypto_free_ablkcipher(tfm);
+	if (tfm->__crt_alg->cra_module != THIS_MODULE) {
+		crypto_free_tfm(tfm);
 		return ERR_PTR(-EINVAL);
 	}
 
-	return __cryptd_ablkcipher_cast(tfm);
+	return __cryptd_ablkcipher_cast(__crypto_ablkcipher_cast(tfm));
 }
 EXPORT_SYMBOL_GPL(cryptd_alloc_ablkcipher);
 
diff -druN linux-libre-2.6.30-gnu/crypto/internal.h linux-libre-2.6.31-gnu/crypto/internal.h
--- linux-libre-2.6.30-gnu/crypto/internal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/internal.h	2009-09-09 18:13:59.000000000 -0400
@@ -121,9 +121,6 @@
 int crypto_unregister_notifier(struct notifier_block *nb);
 int crypto_probing_notify(unsigned long val, void *v);
 
-int __init testmgr_init(void);
-void testmgr_exit(void);
-
 static inline void crypto_alg_put(struct crypto_alg *alg)
 {
 	if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
diff -druN linux-libre-2.6.30-gnu/crypto/Kconfig linux-libre-2.6.31-gnu/crypto/Kconfig
--- linux-libre-2.6.30-gnu/crypto/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -241,6 +241,11 @@
 	  key size 256, 384 or 512 bits. This implementation currently
 	  can't handle a sectorsize which is not a multiple of 16 bytes.
 
+config CRYPTO_FPU
+	tristate
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_MANAGER
+
 comment "Hash modes"
 
 config CRYPTO_HMAC
@@ -486,6 +491,7 @@
 	select CRYPTO_AES_X86_64
 	select CRYPTO_CRYPTD
 	select CRYPTO_ALGAPI
+	select CRYPTO_FPU
 	help
 	  Use Intel AES-NI instructions for AES algorithm.
 
@@ -505,6 +511,10 @@
 
 	  See <http://csrc.nist.gov/encryption/aes/> for more information.
 
+	  In addition to AES cipher algorithm support, the
+	  acceleration for some popular block cipher mode is supported
+	  too, including ECB, CBC, CTR, LRW, PCBC, XTS.
+
 config CRYPTO_ANUBIS
 	tristate "Anubis cipher algorithm"
 	select CRYPTO_ALGAPI
diff -druN linux-libre-2.6.30-gnu/crypto/pcompress.c linux-libre-2.6.31-gnu/crypto/pcompress.c
--- linux-libre-2.6.30-gnu/crypto/pcompress.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/pcompress.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/string.h>
 
 #include <crypto/compress.h>
+#include <crypto/internal/compress.h>
 
 #include "internal.h"
 
diff -druN linux-libre-2.6.30-gnu/crypto/tcrypt.c linux-libre-2.6.31-gnu/crypto/tcrypt.c
--- linux-libre-2.6.30-gnu/crypto/tcrypt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/tcrypt.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/timex.h>
 #include <linux/interrupt.h>
 #include "tcrypt.h"
+#include "internal.h"
 
 /*
  * Need slab memory for testing (size in number of pages).
@@ -396,16 +397,16 @@
 	struct scatterlist sg[TVMEMSIZE];
 	struct crypto_hash *tfm;
 	struct hash_desc desc;
-	char output[1024];
+	static char output[1024];
 	int i;
 	int ret;
 
-	printk("\ntesting speed of %s\n", algo);
+	printk(KERN_INFO "\ntesting speed of %s\n", algo);
 
 	tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
 
 	if (IS_ERR(tfm)) {
-		printk("failed to load transform for %s: %ld\n", algo,
+		printk(KERN_ERR "failed to load transform for %s: %ld\n", algo,
 		       PTR_ERR(tfm));
 		return;
 	}
@@ -414,7 +415,7 @@
 	desc.flags = 0;
 
 	if (crypto_hash_digestsize(tfm) > sizeof(output)) {
-		printk("digestsize(%u) > outputbuffer(%zu)\n",
+		printk(KERN_ERR "digestsize(%u) > outputbuffer(%zu)\n",
 		       crypto_hash_digestsize(tfm), sizeof(output));
 		goto out;
 	}
@@ -427,12 +428,14 @@
 
 	for (i = 0; speed[i].blen != 0; i++) {
 		if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) {
-			printk("template (%u) too big for tvmem (%lu)\n",
+			printk(KERN_ERR
+			       "template (%u) too big for tvmem (%lu)\n",
 			       speed[i].blen, TVMEMSIZE * PAGE_SIZE);
 			goto out;
 		}
 
-		printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ",
+		printk(KERN_INFO "test%3u "
+		       "(%5u byte blocks,%5u bytes per update,%4u updates): ",
 		       i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
 
 		if (sec)
@@ -443,7 +446,7 @@
 					       speed[i].plen, output);
 
 		if (ret) {
-			printk("hashing failed ret=%d\n", ret);
+			printk(KERN_ERR "hashing failed ret=%d\n", ret);
 			break;
 		}
 	}
@@ -466,239 +469,255 @@
 
 static inline int tcrypt_test(const char *alg)
 {
-	return alg_test(alg, alg, 0, 0);
+	int ret;
+
+	ret = alg_test(alg, alg, 0, 0);
+	/* non-fips algs return -EINVAL in fips mode */
+	if (fips_enabled && ret == -EINVAL)
+		ret = 0;
+	return ret;
 }
 
-static void do_test(int m)
+static int do_test(int m)
 {
 	int i;
+	int ret = 0;
 
 	switch (m) {
 	case 0:
 		for (i = 1; i < 200; i++)
-			do_test(i);
+			ret += do_test(i);
 		break;
 
 	case 1:
-		tcrypt_test("md5");
+		ret += tcrypt_test("md5");
 		break;
 
 	case 2:
-		tcrypt_test("sha1");
+		ret += tcrypt_test("sha1");
 		break;
 
 	case 3:
-		tcrypt_test("ecb(des)");
-		tcrypt_test("cbc(des)");
+		ret += tcrypt_test("ecb(des)");
+		ret += tcrypt_test("cbc(des)");
 		break;
 
 	case 4:
-		tcrypt_test("ecb(des3_ede)");
-		tcrypt_test("cbc(des3_ede)");
+		ret += tcrypt_test("ecb(des3_ede)");
+		ret += tcrypt_test("cbc(des3_ede)");
 		break;
 
 	case 5:
-		tcrypt_test("md4");
+		ret += tcrypt_test("md4");
 		break;
 
 	case 6:
-		tcrypt_test("sha256");
+		ret += tcrypt_test("sha256");
 		break;
 
 	case 7:
-		tcrypt_test("ecb(blowfish)");
-		tcrypt_test("cbc(blowfish)");
+		ret += tcrypt_test("ecb(blowfish)");
+		ret += tcrypt_test("cbc(blowfish)");
 		break;
 
 	case 8:
-		tcrypt_test("ecb(twofish)");
-		tcrypt_test("cbc(twofish)");
+		ret += tcrypt_test("ecb(twofish)");
+		ret += tcrypt_test("cbc(twofish)");
 		break;
 
 	case 9:
-		tcrypt_test("ecb(serpent)");
+		ret += tcrypt_test("ecb(serpent)");
 		break;
 
 	case 10:
-		tcrypt_test("ecb(aes)");
-		tcrypt_test("cbc(aes)");
-		tcrypt_test("lrw(aes)");
-		tcrypt_test("xts(aes)");
-		tcrypt_test("rfc3686(ctr(aes))");
+		ret += tcrypt_test("ecb(aes)");
+		ret += tcrypt_test("cbc(aes)");
+		ret += tcrypt_test("lrw(aes)");
+		ret += tcrypt_test("xts(aes)");
+		ret += tcrypt_test("ctr(aes)");
+		ret += tcrypt_test("rfc3686(ctr(aes))");
 		break;
 
 	case 11:
-		tcrypt_test("sha384");
+		ret += tcrypt_test("sha384");
 		break;
 
 	case 12:
-		tcrypt_test("sha512");
+		ret += tcrypt_test("sha512");
 		break;
 
 	case 13:
-		tcrypt_test("deflate");
+		ret += tcrypt_test("deflate");
 		break;
 
 	case 14:
-		tcrypt_test("ecb(cast5)");
+		ret += tcrypt_test("ecb(cast5)");
 		break;
 
 	case 15:
-		tcrypt_test("ecb(cast6)");
+		ret += tcrypt_test("ecb(cast6)");
 		break;
 
 	case 16:
-		tcrypt_test("ecb(arc4)");
+		ret += tcrypt_test("ecb(arc4)");
 		break;
 
 	case 17:
-		tcrypt_test("michael_mic");
+		ret += tcrypt_test("michael_mic");
 		break;
 
 	case 18:
-		tcrypt_test("crc32c");
+		ret += tcrypt_test("crc32c");
 		break;
 
 	case 19:
-		tcrypt_test("ecb(tea)");
+		ret += tcrypt_test("ecb(tea)");
 		break;
 
 	case 20:
-		tcrypt_test("ecb(xtea)");
+		ret += tcrypt_test("ecb(xtea)");
 		break;
 
 	case 21:
-		tcrypt_test("ecb(khazad)");
+		ret += tcrypt_test("ecb(khazad)");
 		break;
 
 	case 22:
-		tcrypt_test("wp512");
+		ret += tcrypt_test("wp512");
 		break;
 
 	case 23:
-		tcrypt_test("wp384");
+		ret += tcrypt_test("wp384");
 		break;
 
 	case 24:
-		tcrypt_test("wp256");
+		ret += tcrypt_test("wp256");
 		break;
 
 	case 25:
-		tcrypt_test("ecb(tnepres)");
+		ret += tcrypt_test("ecb(tnepres)");
 		break;
 
 	case 26:
-		tcrypt_test("ecb(anubis)");
-		tcrypt_test("cbc(anubis)");
+		ret += tcrypt_test("ecb(anubis)");
+		ret += tcrypt_test("cbc(anubis)");
 		break;
 
 	case 27:
-		tcrypt_test("tgr192");
+		ret += tcrypt_test("tgr192");
 		break;
 
 	case 28:
 
-		tcrypt_test("tgr160");
+		ret += tcrypt_test("tgr160");
 		break;
 
 	case 29:
-		tcrypt_test("tgr128");
+		ret += tcrypt_test("tgr128");
 		break;
 
 	case 30:
-		tcrypt_test("ecb(xeta)");
+		ret += tcrypt_test("ecb(xeta)");
 		break;
 
 	case 31:
-		tcrypt_test("pcbc(fcrypt)");
+		ret += tcrypt_test("pcbc(fcrypt)");
 		break;
 
 	case 32:
-		tcrypt_test("ecb(camellia)");
-		tcrypt_test("cbc(camellia)");
+		ret += tcrypt_test("ecb(camellia)");
+		ret += tcrypt_test("cbc(camellia)");
 		break;
 	case 33:
-		tcrypt_test("sha224");
+		ret += tcrypt_test("sha224");
 		break;
 
 	case 34:
-		tcrypt_test("salsa20");
+		ret += tcrypt_test("salsa20");
 		break;
 
 	case 35:
-		tcrypt_test("gcm(aes)");
+		ret += tcrypt_test("gcm(aes)");
 		break;
 
 	case 36:
-		tcrypt_test("lzo");
+		ret += tcrypt_test("lzo");
 		break;
 
 	case 37:
-		tcrypt_test("ccm(aes)");
+		ret += tcrypt_test("ccm(aes)");
 		break;
 
 	case 38:
-		tcrypt_test("cts(cbc(aes))");
+		ret += tcrypt_test("cts(cbc(aes))");
 		break;
 
         case 39:
-		tcrypt_test("rmd128");
+		ret += tcrypt_test("rmd128");
 		break;
 
         case 40:
-		tcrypt_test("rmd160");
+		ret += tcrypt_test("rmd160");
 		break;
 
 	case 41:
-		tcrypt_test("rmd256");
+		ret += tcrypt_test("rmd256");
 		break;
 
 	case 42:
-		tcrypt_test("rmd320");
+		ret += tcrypt_test("rmd320");
 		break;
 
 	case 43:
-		tcrypt_test("ecb(seed)");
+		ret += tcrypt_test("ecb(seed)");
 		break;
 
 	case 44:
-		tcrypt_test("zlib");
+		ret += tcrypt_test("zlib");
+		break;
+
+	case 45:
+		ret += tcrypt_test("rfc4309(ccm(aes))");
 		break;
 
 	case 100:
-		tcrypt_test("hmac(md5)");
+		ret += tcrypt_test("hmac(md5)");
 		break;
 
 	case 101:
-		tcrypt_test("hmac(sha1)");
+		ret += tcrypt_test("hmac(sha1)");
 		break;
 
 	case 102:
-		tcrypt_test("hmac(sha256)");
+		ret += tcrypt_test("hmac(sha256)");
 		break;
 
 	case 103:
-		tcrypt_test("hmac(sha384)");
+		ret += tcrypt_test("hmac(sha384)");
 		break;
 
 	case 104:
-		tcrypt_test("hmac(sha512)");
+		ret += tcrypt_test("hmac(sha512)");
 		break;
 
 	case 105:
-		tcrypt_test("hmac(sha224)");
+		ret += tcrypt_test("hmac(sha224)");
 		break;
 
 	case 106:
-		tcrypt_test("xcbc(aes)");
+		ret += tcrypt_test("xcbc(aes)");
 		break;
 
 	case 107:
-		tcrypt_test("hmac(rmd128)");
+		ret += tcrypt_test("hmac(rmd128)");
 		break;
 
 	case 108:
-		tcrypt_test("hmac(rmd160)");
+		ret += tcrypt_test("hmac(rmd160)");
+		break;
+
+	case 150:
+		ret += tcrypt_test("ansi_cprng");
 		break;
 
 	case 200:
@@ -862,6 +881,8 @@
 		test_available();
 		break;
 	}
+
+	return ret;
 }
 
 static int __init tcrypt_mod_init(void)
@@ -875,15 +896,21 @@
 			goto err_free_tv;
 	}
 
-	do_test(mode);
+	err = do_test(mode);
+	if (err) {
+		printk(KERN_ERR "tcrypt: one or more tests failed!\n");
+		goto err_free_tv;
+	}
 
-	/* We intentionaly return -EAGAIN to prevent keeping
-	 * the module. It does all its work from init()
-	 * and doesn't offer any runtime functionality 
+	/* We intentionaly return -EAGAIN to prevent keeping the module,
+	 * unless we're running in fips mode. It does all its work from
+	 * init() and doesn't offer any runtime functionality, but in
+	 * the fips case, checking for a successful load is helpful.
 	 * => we don't need it in the memory, do we?
 	 *                                        -- mludvig
 	 */
-	err = -EAGAIN;
+	if (!fips_enabled)
+		err = -EAGAIN;
 
 err_free_tv:
 	for (i = 0; i < TVMEMSIZE && tvmem[i]; i++)
diff -druN linux-libre-2.6.30-gnu/crypto/testmgr.c linux-libre-2.6.31-gnu/crypto/testmgr.c
--- linux-libre-2.6.30-gnu/crypto/testmgr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/testmgr.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <crypto/rng.h>
 
 #include "internal.h"
 #include "testmgr.h"
@@ -84,10 +85,16 @@
 	unsigned int count;
 };
 
+struct cprng_test_suite {
+	struct cprng_testvec *vecs;
+	unsigned int count;
+};
+
 struct alg_test_desc {
 	const char *alg;
 	int (*test)(const struct alg_test_desc *desc, const char *driver,
 		    u32 type, u32 mask);
+	int fips_allowed;	/* set if alg is allowed in fips mode */
 
 	union {
 		struct aead_test_suite aead;
@@ -95,14 +102,12 @@
 		struct comp_test_suite comp;
 		struct pcomp_test_suite pcomp;
 		struct hash_test_suite hash;
+		struct cprng_test_suite cprng;
 	} suite;
 };
 
 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 
-static char *xbuf[XBUFSIZE];
-static char *axbuf[XBUFSIZE];
-
 static void hexdump(unsigned char *buf, unsigned int len)
 {
 	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
@@ -121,6 +126,33 @@
 	complete(&res->completion);
 }
 
+static int testmgr_alloc_buf(char *buf[XBUFSIZE])
+{
+	int i;
+
+	for (i = 0; i < XBUFSIZE; i++) {
+		buf[i] = (void *)__get_free_page(GFP_KERNEL);
+		if (!buf[i])
+			goto err_free_buf;
+	}
+
+	return 0;
+
+err_free_buf:
+	while (i-- > 0)
+		free_page((unsigned long)buf[i]);
+
+	return -ENOMEM;
+}
+
+static void testmgr_free_buf(char *buf[XBUFSIZE])
+{
+	int i;
+
+	for (i = 0; i < XBUFSIZE; i++)
+		free_page((unsigned long)buf[i]);
+}
+
 static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
 		     unsigned int tcount)
 {
@@ -130,8 +162,12 @@
 	char result[64];
 	struct ahash_request *req;
 	struct tcrypt_result tresult;
-	int ret;
 	void *hash_buff;
+	char *xbuf[XBUFSIZE];
+	int ret = -ENOMEM;
+
+	if (testmgr_alloc_buf(xbuf))
+		goto out_nobuf;
 
 	init_completion(&tresult.completion);
 
@@ -139,17 +175,25 @@
 	if (!req) {
 		printk(KERN_ERR "alg: hash: Failed to allocate request for "
 		       "%s\n", algo);
-		ret = -ENOMEM;
 		goto out_noreq;
 	}
 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				   tcrypt_complete, &tresult);
 
+	j = 0;
 	for (i = 0; i < tcount; i++) {
+		if (template[i].np)
+			continue;
+
+		j++;
 		memset(result, 0, 64);
 
 		hash_buff = xbuf[0];
 
+		ret = -EINVAL;
+		if (WARN_ON(template[i].psize > PAGE_SIZE))
+			goto out;
+
 		memcpy(hash_buff, template[i].plaintext, template[i].psize);
 		sg_init_one(&sg[0], hash_buff, template[i].psize);
 
@@ -159,7 +203,7 @@
 						  template[i].ksize);
 			if (ret) {
 				printk(KERN_ERR "alg: hash: setkey failed on "
-				       "test %d for %s: ret=%d\n", i + 1, algo,
+				       "test %d for %s: ret=%d\n", j, algo,
 				       -ret);
 				goto out;
 			}
@@ -181,14 +225,14 @@
 			/* fall through */
 		default:
 			printk(KERN_ERR "alg: hash: digest failed on test %d "
-			       "for %s: ret=%d\n", i + 1, algo, -ret);
+			       "for %s: ret=%d\n", j, algo, -ret);
 			goto out;
 		}
 
 		if (memcmp(result, template[i].digest,
 			   crypto_ahash_digestsize(tfm))) {
 			printk(KERN_ERR "alg: hash: Test %d failed for %s\n",
-			       i + 1, algo);
+			       j, algo);
 			hexdump(result, crypto_ahash_digestsize(tfm));
 			ret = -EINVAL;
 			goto out;
@@ -203,7 +247,11 @@
 
 			temp = 0;
 			sg_init_table(sg, template[i].np);
+			ret = -EINVAL;
 			for (k = 0; k < template[i].np; k++) {
+				if (WARN_ON(offset_in_page(IDX[k]) +
+					    template[i].tap[k] > PAGE_SIZE))
+					goto out;
 				sg_set_buf(&sg[k],
 					   memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
 						  offset_in_page(IDX[k]),
@@ -265,6 +313,8 @@
 out:
 	ahash_request_free(req);
 out_noreq:
+	testmgr_free_buf(xbuf);
+out_nobuf:
 	return ret;
 }
 
@@ -273,7 +323,7 @@
 {
 	const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm));
 	unsigned int i, j, k, n, temp;
-	int ret = 0;
+	int ret = -ENOMEM;
 	char *q;
 	char *key;
 	struct aead_request *req;
@@ -285,6 +335,13 @@
 	void *input;
 	void *assoc;
 	char iv[MAX_IVLEN];
+	char *xbuf[XBUFSIZE];
+	char *axbuf[XBUFSIZE];
+
+	if (testmgr_alloc_buf(xbuf))
+		goto out_noxbuf;
+	if (testmgr_alloc_buf(axbuf))
+		goto out_noaxbuf;
 
 	if (enc == ENCRYPT)
 		e = "encryption";
@@ -297,7 +354,6 @@
 	if (!req) {
 		printk(KERN_ERR "alg: aead: Failed to allocate request for "
 		       "%s\n", algo);
-		ret = -ENOMEM;
 		goto out;
 	}
 
@@ -314,6 +370,11 @@
 			input = xbuf[0];
 			assoc = axbuf[0];
 
+			ret = -EINVAL;
+			if (WARN_ON(template[i].ilen > PAGE_SIZE ||
+				    template[i].alen > PAGE_SIZE))
+				goto out;
+
 			memcpy(input, template[i].input, template[i].ilen);
 			memcpy(assoc, template[i].assoc, template[i].alen);
 			if (template[i].iv)
@@ -363,6 +424,16 @@
 
 			switch (ret) {
 			case 0:
+				if (template[i].novrfy) {
+					/* verification was supposed to fail */
+					printk(KERN_ERR "alg: aead: %s failed "
+					       "on test %d for %s: ret was 0, "
+					       "expected -EBADMSG\n",
+					       e, j, algo);
+					/* so really, we got a bad message */
+					ret = -EBADMSG;
+					goto out;
+				}
 				break;
 			case -EINPROGRESS:
 			case -EBUSY:
@@ -372,6 +443,10 @@
 					INIT_COMPLETION(result.completion);
 					break;
 				}
+			case -EBADMSG:
+				if (template[i].novrfy)
+					/* verification failure was expected */
+					continue;
 				/* fall through */
 			default:
 				printk(KERN_ERR "alg: aead: %s failed on test "
@@ -459,7 +534,11 @@
 			}
 
 			sg_init_table(asg, template[i].anp);
+			ret = -EINVAL;
 			for (k = 0, temp = 0; k < template[i].anp; k++) {
+				if (WARN_ON(offset_in_page(IDX[k]) +
+					    template[i].atap[k] > PAGE_SIZE))
+					goto out;
 				sg_set_buf(&asg[k],
 					   memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
 						  offset_in_page(IDX[k]),
@@ -481,6 +560,16 @@
 
 			switch (ret) {
 			case 0:
+				if (template[i].novrfy) {
+					/* verification was supposed to fail */
+					printk(KERN_ERR "alg: aead: %s failed "
+					       "on chunk test %d for %s: ret "
+					       "was 0, expected -EBADMSG\n",
+					       e, j, algo);
+					/* so really, we got a bad message */
+					ret = -EBADMSG;
+					goto out;
+				}
 				break;
 			case -EINPROGRESS:
 			case -EBUSY:
@@ -490,6 +579,10 @@
 					INIT_COMPLETION(result.completion);
 					break;
 				}
+			case -EBADMSG:
+				if (template[i].novrfy)
+					/* verification failure was expected */
+					continue;
 				/* fall through */
 			default:
 				printk(KERN_ERR "alg: aead: %s failed on "
@@ -546,6 +639,10 @@
 
 out:
 	aead_request_free(req);
+	testmgr_free_buf(axbuf);
+out_noaxbuf:
+	testmgr_free_buf(xbuf);
+out_noxbuf:
 	return ret;
 }
 
@@ -554,10 +651,14 @@
 {
 	const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
 	unsigned int i, j, k;
-	int ret;
 	char *q;
 	const char *e;
 	void *data;
+	char *xbuf[XBUFSIZE];
+	int ret = -ENOMEM;
+
+	if (testmgr_alloc_buf(xbuf))
+		goto out_nobuf;
 
 	if (enc == ENCRYPT)
 	        e = "encryption";
@@ -571,6 +672,10 @@
 
 		j++;
 
+		ret = -EINVAL;
+		if (WARN_ON(template[i].ilen > PAGE_SIZE))
+			goto out;
+
 		data = xbuf[0];
 		memcpy(data, template[i].input, template[i].ilen);
 
@@ -611,6 +716,8 @@
 	ret = 0;
 
 out:
+	testmgr_free_buf(xbuf);
+out_nobuf:
 	return ret;
 }
 
@@ -620,7 +727,6 @@
 	const char *algo =
 		crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
 	unsigned int i, j, k, n, temp;
-	int ret;
 	char *q;
 	struct ablkcipher_request *req;
 	struct scatterlist sg[8];
@@ -628,6 +734,11 @@
 	struct tcrypt_result result;
 	void *data;
 	char iv[MAX_IVLEN];
+	char *xbuf[XBUFSIZE];
+	int ret = -ENOMEM;
+
+	if (testmgr_alloc_buf(xbuf))
+		goto out_nobuf;
 
 	if (enc == ENCRYPT)
 	        e = "encryption";
@@ -640,7 +751,6 @@
 	if (!req) {
 		printk(KERN_ERR "alg: skcipher: Failed to allocate request "
 		       "for %s\n", algo);
-		ret = -ENOMEM;
 		goto out;
 	}
 
@@ -657,6 +767,10 @@
 		if (!(template[i].np)) {
 			j++;
 
+			ret = -EINVAL;
+			if (WARN_ON(template[i].ilen > PAGE_SIZE))
+				goto out;
+
 			data = xbuf[0];
 			memcpy(data, template[i].input, template[i].ilen);
 
@@ -825,6 +939,8 @@
 
 out:
 	ablkcipher_request_free(req);
+	testmgr_free_buf(xbuf);
+out_nobuf:
 	return ret;
 }
 
@@ -837,7 +953,8 @@
 	int ret;
 
 	for (i = 0; i < ctcount; i++) {
-		int ilen, dlen = COMP_BUF_SIZE;
+		int ilen;
+		unsigned int dlen = COMP_BUF_SIZE;
 
 		memset(result, 0, sizeof (result));
 
@@ -869,7 +986,8 @@
 	}
 
 	for (i = 0; i < dtcount; i++) {
-		int ilen, dlen = COMP_BUF_SIZE;
+		int ilen;
+		unsigned int dlen = COMP_BUF_SIZE;
 
 		memset(result, 0, sizeof (result));
 
@@ -914,24 +1032,25 @@
 	const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm));
 	unsigned int i;
 	char result[COMP_BUF_SIZE];
-	int error;
+	int res;
 
 	for (i = 0; i < ctcount; i++) {
 		struct comp_request req;
+		unsigned int produced = 0;
 
-		error = crypto_compress_setup(tfm, ctemplate[i].params,
-					      ctemplate[i].paramsize);
-		if (error) {
+		res = crypto_compress_setup(tfm, ctemplate[i].params,
+					    ctemplate[i].paramsize);
+		if (res) {
 			pr_err("alg: pcomp: compression setup failed on test "
-			       "%d for %s: error=%d\n", i + 1, algo, error);
-			return error;
+			       "%d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
 
-		error = crypto_compress_init(tfm);
-		if (error) {
+		res = crypto_compress_init(tfm);
+		if (res) {
 			pr_err("alg: pcomp: compression init failed on test "
-			       "%d for %s: error=%d\n", i + 1, algo, error);
-			return error;
+			       "%d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
 
 		memset(result, 0, sizeof(result));
@@ -941,32 +1060,37 @@
 		req.next_out = result;
 		req.avail_out = ctemplate[i].outlen / 2;
 
-		error = crypto_compress_update(tfm, &req);
-		if (error && (error != -EAGAIN || req.avail_in)) {
+		res = crypto_compress_update(tfm, &req);
+		if (res < 0 && (res != -EAGAIN || req.avail_in)) {
 			pr_err("alg: pcomp: compression update failed on test "
-			       "%d for %s: error=%d\n", i + 1, algo, error);
-			return error;
+			       "%d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
+		if (res > 0)
+			produced += res;
 
 		/* Add remaining input data */
 		req.avail_in += (ctemplate[i].inlen + 1) / 2;
 
-		error = crypto_compress_update(tfm, &req);
-		if (error && (error != -EAGAIN || req.avail_in)) {
+		res = crypto_compress_update(tfm, &req);
+		if (res < 0 && (res != -EAGAIN || req.avail_in)) {
 			pr_err("alg: pcomp: compression update failed on test "
-			       "%d for %s: error=%d\n", i + 1, algo, error);
-			return error;
+			       "%d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
+		if (res > 0)
+			produced += res;
 
 		/* Provide remaining output space */
 		req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2;
 
-		error = crypto_compress_final(tfm, &req);
-		if (error) {
+		res = crypto_compress_final(tfm, &req);
+		if (res < 0) {
 			pr_err("alg: pcomp: compression final failed on test "
-			       "%d for %s: error=%d\n", i + 1, algo, error);
-			return error;
+			       "%d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
+		produced += res;
 
 		if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) {
 			pr_err("alg: comp: Compression test %d failed for %s: "
@@ -976,6 +1100,13 @@
 			return -EINVAL;
 		}
 
+		if (produced != ctemplate[i].outlen) {
+			pr_err("alg: comp: Compression test %d failed for %s: "
+			       "returned len = %u (expected %d)\n", i + 1,
+			       algo, produced, ctemplate[i].outlen);
+			return -EINVAL;
+		}
+
 		if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) {
 			pr_err("alg: pcomp: Compression test %d failed for "
 			       "%s\n", i + 1, algo);
@@ -986,21 +1117,21 @@
 
 	for (i = 0; i < dtcount; i++) {
 		struct comp_request req;
+		unsigned int produced = 0;
 
-		error = crypto_decompress_setup(tfm, dtemplate[i].params,
-						dtemplate[i].paramsize);
-		if (error) {
+		res = crypto_decompress_setup(tfm, dtemplate[i].params,
+					      dtemplate[i].paramsize);
+		if (res) {
 			pr_err("alg: pcomp: decompression setup failed on "
-			       "test %d for %s: error=%d\n", i + 1, algo,
-			       error);
-			return error;
+			       "test %d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
 
-		error = crypto_decompress_init(tfm);
-		if (error) {
+		res = crypto_decompress_init(tfm);
+		if (res) {
 			pr_err("alg: pcomp: decompression init failed on test "
-			       "%d for %s: error=%d\n", i + 1, algo, error);
-			return error;
+			       "%d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
 
 		memset(result, 0, sizeof(result));
@@ -1010,35 +1141,38 @@
 		req.next_out = result;
 		req.avail_out = dtemplate[i].outlen / 2;
 
-		error = crypto_decompress_update(tfm, &req);
-		if (error  && (error != -EAGAIN || req.avail_in)) {
+		res = crypto_decompress_update(tfm, &req);
+		if (res < 0 && (res != -EAGAIN || req.avail_in)) {
 			pr_err("alg: pcomp: decompression update failed on "
-			       "test %d for %s: error=%d\n", i + 1, algo,
-			       error);
-			return error;
+			       "test %d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
+		if (res > 0)
+			produced += res;
 
 		/* Add remaining input data */
 		req.avail_in += (dtemplate[i].inlen + 1) / 2;
 
-		error = crypto_decompress_update(tfm, &req);
-		if (error  && (error != -EAGAIN || req.avail_in)) {
+		res = crypto_decompress_update(tfm, &req);
+		if (res < 0 && (res != -EAGAIN || req.avail_in)) {
 			pr_err("alg: pcomp: decompression update failed on "
-			       "test %d for %s: error=%d\n", i + 1, algo,
-			       error);
-			return error;
+			       "test %d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
+		if (res > 0)
+			produced += res;
 
 		/* Provide remaining output space */
 		req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2;
 
-		error = crypto_decompress_final(tfm, &req);
-		if (error  && (error != -EAGAIN || req.avail_in)) {
+		res = crypto_decompress_final(tfm, &req);
+		if (res < 0 && (res != -EAGAIN || req.avail_in)) {
 			pr_err("alg: pcomp: decompression final failed on "
-			       "test %d for %s: error=%d\n", i + 1, algo,
-			       error);
-			return error;
+			       "test %d for %s: error=%d\n", i + 1, algo, res);
+			return res;
 		}
+		if (res > 0)
+			produced += res;
 
 		if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) {
 			pr_err("alg: comp: Decompression test %d failed for "
@@ -1048,6 +1182,13 @@
 			return -EINVAL;
 		}
 
+		if (produced != dtemplate[i].outlen) {
+			pr_err("alg: comp: Decompression test %d failed for "
+			       "%s: returned len = %u (expected %d)\n", i + 1,
+			       algo, produced, dtemplate[i].outlen);
+			return -EINVAL;
+		}
+
 		if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) {
 			pr_err("alg: pcomp: Decompression test %d failed for "
 			       "%s\n", i + 1, algo);
@@ -1059,6 +1200,68 @@
 	return 0;
 }
 
+
+static int test_cprng(struct crypto_rng *tfm, struct cprng_testvec *template,
+		      unsigned int tcount)
+{
+	const char *algo = crypto_tfm_alg_driver_name(crypto_rng_tfm(tfm));
+	int err, i, j, seedsize;
+	u8 *seed;
+	char result[32];
+
+	seedsize = crypto_rng_seedsize(tfm);
+
+	seed = kmalloc(seedsize, GFP_KERNEL);
+	if (!seed) {
+		printk(KERN_ERR "alg: cprng: Failed to allocate seed space "
+		       "for %s\n", algo);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < tcount; i++) {
+		memset(result, 0, 32);
+
+		memcpy(seed, template[i].v, template[i].vlen);
+		memcpy(seed + template[i].vlen, template[i].key,
+		       template[i].klen);
+		memcpy(seed + template[i].vlen + template[i].klen,
+		       template[i].dt, template[i].dtlen);
+
+		err = crypto_rng_reset(tfm, seed, seedsize);
+		if (err) {
+			printk(KERN_ERR "alg: cprng: Failed to reset rng "
+			       "for %s\n", algo);
+			goto out;
+		}
+
+		for (j = 0; j < template[i].loops; j++) {
+			err = crypto_rng_get_bytes(tfm, result,
+						   template[i].rlen);
+			if (err != template[i].rlen) {
+				printk(KERN_ERR "alg: cprng: Failed to obtain "
+				       "the correct amount of random data for "
+				       "%s (requested %d, got %d)\n", algo,
+				       template[i].rlen, err);
+				goto out;
+			}
+		}
+
+		err = memcmp(result, template[i].result,
+			     template[i].rlen);
+		if (err) {
+			printk(KERN_ERR "alg: cprng: Test %d failed for %s\n",
+			       i, algo);
+			hexdump(result, template[i].rlen);
+			err = -EINVAL;
+			goto out;
+		}
+	}
+
+out:
+	kfree(seed);
+	return err;
+}
+
 static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
@@ -1258,11 +1461,42 @@
 	return err;
 }
 
+static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
+			  u32 type, u32 mask)
+{
+	struct crypto_rng *rng;
+	int err;
+
+	rng = crypto_alloc_rng(driver, type, mask);
+	if (IS_ERR(rng)) {
+		printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
+		       "%ld\n", driver, PTR_ERR(rng));
+		return PTR_ERR(rng);
+	}
+
+	err = test_cprng(rng, desc->suite.cprng.vecs, desc->suite.cprng.count);
+
+	crypto_free_rng(rng);
+
+	return err;
+}
+
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
 	{
+		.alg = "ansi_cprng",
+		.test = alg_test_cprng,
+		.fips_allowed = 1,
+		.suite = {
+			.cprng = {
+				.vecs = ansi_cprng_aes_tv_template,
+				.count = ANSI_CPRNG_AES_TEST_VECTORS
+			}
+		}
+	}, {
 		.alg = "cbc(aes)",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
@@ -1338,6 +1572,7 @@
 	}, {
 		.alg = "cbc(des3_ede)",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
@@ -1368,6 +1603,7 @@
 	}, {
 		.alg = "ccm(aes)",
 		.test = alg_test_aead,
+		.fips_allowed = 1,
 		.suite = {
 			.aead = {
 				.enc = {
@@ -1383,6 +1619,7 @@
 	}, {
 		.alg = "crc32c",
 		.test = alg_test_crc32c,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = crc32c_tv_template,
@@ -1390,6 +1627,22 @@
 			}
 		}
 	}, {
+		.alg = "ctr(aes)",
+		.test = alg_test_skcipher,
+		.fips_allowed = 1,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = aes_ctr_enc_tv_template,
+					.count = AES_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = aes_ctr_dec_tv_template,
+					.count = AES_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "cts(cbc(aes))",
 		.test = alg_test_skcipher,
 		.suite = {
@@ -1422,6 +1675,7 @@
 	}, {
 		.alg = "ecb(aes)",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
@@ -1527,6 +1781,7 @@
 	}, {
 		.alg = "ecb(des)",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
@@ -1542,6 +1797,7 @@
 	}, {
 		.alg = "ecb(des3_ede)",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
@@ -1677,6 +1933,7 @@
 	}, {
 		.alg = "gcm(aes)",
 		.test = alg_test_aead,
+		.fips_allowed = 1,
 		.suite = {
 			.aead = {
 				.enc = {
@@ -1719,6 +1976,7 @@
 	}, {
 		.alg = "hmac(sha1)",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = hmac_sha1_tv_template,
@@ -1728,6 +1986,7 @@
 	}, {
 		.alg = "hmac(sha224)",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = hmac_sha224_tv_template,
@@ -1737,6 +1996,7 @@
 	}, {
 		.alg = "hmac(sha256)",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = hmac_sha256_tv_template,
@@ -1746,6 +2006,7 @@
 	}, {
 		.alg = "hmac(sha384)",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = hmac_sha384_tv_template,
@@ -1755,6 +2016,7 @@
 	}, {
 		.alg = "hmac(sha512)",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = hmac_sha512_tv_template,
@@ -1836,15 +2098,32 @@
 	}, {
 		.alg = "rfc3686(ctr(aes))",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
-					.vecs = aes_ctr_enc_tv_template,
-					.count = AES_CTR_ENC_TEST_VECTORS
+					.vecs = aes_ctr_rfc3686_enc_tv_template,
+					.count = AES_CTR_3686_ENC_TEST_VECTORS
 				},
 				.dec = {
-					.vecs = aes_ctr_dec_tv_template,
-					.count = AES_CTR_DEC_TEST_VECTORS
+					.vecs = aes_ctr_rfc3686_dec_tv_template,
+					.count = AES_CTR_3686_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+		.alg = "rfc4309(ccm(aes))",
+		.test = alg_test_aead,
+		.fips_allowed = 1,
+		.suite = {
+			.aead = {
+				.enc = {
+					.vecs = aes_ccm_rfc4309_enc_tv_template,
+					.count = AES_CCM_4309_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = aes_ccm_rfc4309_dec_tv_template,
+					.count = AES_CCM_4309_DEC_TEST_VECTORS
 				}
 			}
 		}
@@ -1898,6 +2177,7 @@
 	}, {
 		.alg = "sha1",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = sha1_tv_template,
@@ -1907,6 +2187,7 @@
 	}, {
 		.alg = "sha224",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = sha224_tv_template,
@@ -1916,6 +2197,7 @@
 	}, {
 		.alg = "sha256",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = sha256_tv_template,
@@ -1925,6 +2207,7 @@
 	}, {
 		.alg = "sha384",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = sha384_tv_template,
@@ -1934,6 +2217,7 @@
 	}, {
 		.alg = "sha512",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = sha512_tv_template,
@@ -2077,60 +2361,36 @@
 		if (i < 0)
 			goto notest;
 
-		return alg_test_cipher(alg_test_descs + i, driver, type, mask);
+		if (fips_enabled && !alg_test_descs[i].fips_allowed)
+			goto non_fips_alg;
+
+		rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
+		goto test_done;
 	}
 
 	i = alg_find_test(alg);
 	if (i < 0)
 		goto notest;
 
+	if (fips_enabled && !alg_test_descs[i].fips_allowed)
+		goto non_fips_alg;
+
 	rc = alg_test_descs[i].test(alg_test_descs + i, driver,
 				      type, mask);
+test_done:
 	if (fips_enabled && rc)
 		panic("%s: %s alg self test failed in fips mode!\n", driver, alg);
 
+	if (fips_enabled && !rc)
+		printk(KERN_INFO "alg: self-tests for %s (%s) passed\n",
+		       driver, alg);
+
 	return rc;
 
 notest:
 	printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
 	return 0;
+non_fips_alg:
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(alg_test);
-
-int __init testmgr_init(void)
-{
-	int i;
-
-	for (i = 0; i < XBUFSIZE; i++) {
-		xbuf[i] = (void *)__get_free_page(GFP_KERNEL);
-		if (!xbuf[i])
-			goto err_free_xbuf;
-	}
-
-	for (i = 0; i < XBUFSIZE; i++) {
-		axbuf[i] = (void *)__get_free_page(GFP_KERNEL);
-		if (!axbuf[i])
-			goto err_free_axbuf;
-	}
-
-	return 0;
-
-err_free_axbuf:
-	for (i = 0; i < XBUFSIZE && axbuf[i]; i++)
-		free_page((unsigned long)axbuf[i]);
-err_free_xbuf:
-	for (i = 0; i < XBUFSIZE && xbuf[i]; i++)
-		free_page((unsigned long)xbuf[i]);
-
-	return -ENOMEM;
-}
-
-void testmgr_exit(void)
-{
-	int i;
-
-	for (i = 0; i < XBUFSIZE; i++)
-		free_page((unsigned long)axbuf[i]);
-	for (i = 0; i < XBUFSIZE; i++)
-		free_page((unsigned long)xbuf[i]);
-}
diff -druN linux-libre-2.6.30-gnu/crypto/testmgr.h linux-libre-2.6.31-gnu/crypto/testmgr.h
--- linux-libre-2.6.30-gnu/crypto/testmgr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/testmgr.h	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,7 @@
 	int np;
 	int anp;
 	unsigned char fail;
+	unsigned char novrfy;	/* ccm dec verification failure expected */
 	unsigned char wk; /* weak key flag */
 	unsigned char klen;
 	unsigned short ilen;
@@ -69,6 +70,18 @@
 	unsigned short rlen;
 };
 
+struct cprng_testvec {
+	char *key;
+	char *dt;
+	char *v;
+	char *result;
+	unsigned char klen;
+	unsigned short dtlen;
+	unsigned short vlen;
+	unsigned short rlen;
+	unsigned short loops;
+};
+
 static char zeroed_string[48];
 
 /*
@@ -2841,12 +2854,16 @@
 #define AES_LRW_DEC_TEST_VECTORS 8
 #define AES_XTS_ENC_TEST_VECTORS 4
 #define AES_XTS_DEC_TEST_VECTORS 4
-#define AES_CTR_ENC_TEST_VECTORS 7
-#define AES_CTR_DEC_TEST_VECTORS 6
+#define AES_CTR_ENC_TEST_VECTORS 3
+#define AES_CTR_DEC_TEST_VECTORS 3
+#define AES_CTR_3686_ENC_TEST_VECTORS 7
+#define AES_CTR_3686_DEC_TEST_VECTORS 6
 #define AES_GCM_ENC_TEST_VECTORS 9
 #define AES_GCM_DEC_TEST_VECTORS 8
 #define AES_CCM_ENC_TEST_VECTORS 7
 #define AES_CCM_DEC_TEST_VECTORS 7
+#define AES_CCM_4309_ENC_TEST_VECTORS 7
+#define AES_CCM_4309_DEC_TEST_VECTORS 10
 
 static struct cipher_testvec aes_enc_tv_template[] = {
 	{ /* From FIPS-197 */
@@ -3983,6 +4000,164 @@
 
 
 static struct cipher_testvec aes_ctr_enc_tv_template[] = {
+	{ /* From NIST Special Publication 800-38A, Appendix F.5 */
+		.key	= "\x2b\x7e\x15\x16\x28\xae\xd2\xa6"
+			  "\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+		.klen	= 16,
+		.iv	= "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.input	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.ilen	= 64,
+		.result	= "\x87\x4d\x61\x91\xb6\x20\xe3\x26"
+			  "\x1b\xef\x68\x64\x99\x0d\xb6\xce"
+			  "\x98\x06\xf6\x6b\x79\x70\xfd\xff"
+			  "\x86\x17\x18\x7b\xb9\xff\xfd\xff"
+			  "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e"
+			  "\x5b\x4f\x09\x02\x0d\xb0\x3e\xab"
+			  "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1"
+			  "\x79\x21\x70\xa0\xf3\x00\x9c\xee",
+		.rlen	= 64,
+	}, {
+		.key	= "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
+			  "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+			  "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+		.klen	= 24,
+		.iv	= "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.input	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.ilen	= 64,
+		.result	= "\x1a\xbc\x93\x24\x17\x52\x1c\xa2"
+			  "\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b"
+			  "\x09\x03\x39\xec\x0a\xa6\xfa\xef"
+			  "\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94"
+			  "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70"
+			  "\xd1\xbd\x1d\x66\x56\x20\xab\xf7"
+			  "\x4f\x78\xa7\xf6\xd2\x98\x09\x58"
+			  "\x5a\x97\xda\xec\x58\xc6\xb0\x50",
+		.rlen	= 64,
+	}, {
+		.key	= "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
+			  "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+			  "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
+			  "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+		.klen	= 32,
+		.iv	= "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.input	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.ilen	= 64,
+		.result	= "\x60\x1e\xc3\x13\x77\x57\x89\xa5"
+			  "\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28"
+			  "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a"
+			  "\xca\x84\xe9\x90\xca\xca\xf5\xc5"
+			  "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c"
+			  "\xe8\x70\x17\xba\x2d\x84\x98\x8d"
+			  "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6"
+			  "\x13\xc2\xdd\x08\x45\x79\x41\xa6",
+		.rlen	= 64,
+	}
+};
+
+static struct cipher_testvec aes_ctr_dec_tv_template[] = {
+	{ /* From NIST Special Publication 800-38A, Appendix F.5 */
+		.key	= "\x2b\x7e\x15\x16\x28\xae\xd2\xa6"
+			  "\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+		.klen	= 16,
+		.iv	= "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.input	= "\x87\x4d\x61\x91\xb6\x20\xe3\x26"
+			  "\x1b\xef\x68\x64\x99\x0d\xb6\xce"
+			  "\x98\x06\xf6\x6b\x79\x70\xfd\xff"
+			  "\x86\x17\x18\x7b\xb9\xff\xfd\xff"
+			  "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e"
+			  "\x5b\x4f\x09\x02\x0d\xb0\x3e\xab"
+			  "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1"
+			  "\x79\x21\x70\xa0\xf3\x00\x9c\xee",
+		.ilen	= 64,
+		.result	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.rlen	= 64,
+	}, {
+		.key	= "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
+			  "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+			  "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+		.klen	= 24,
+		.iv	= "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.input	= "\x1a\xbc\x93\x24\x17\x52\x1c\xa2"
+			  "\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b"
+			  "\x09\x03\x39\xec\x0a\xa6\xfa\xef"
+			  "\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94"
+			  "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70"
+			  "\xd1\xbd\x1d\x66\x56\x20\xab\xf7"
+			  "\x4f\x78\xa7\xf6\xd2\x98\x09\x58"
+			  "\x5a\x97\xda\xec\x58\xc6\xb0\x50",
+		.ilen	= 64,
+		.result	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.rlen	= 64,
+	}, {
+		.key	= "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
+			  "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+			  "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
+			  "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+		.klen	= 32,
+		.iv	= "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.input	= "\x60\x1e\xc3\x13\x77\x57\x89\xa5"
+			  "\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28"
+			  "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a"
+			  "\xca\x84\xe9\x90\xca\xca\xf5\xc5"
+			  "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c"
+			  "\xe8\x70\x17\xba\x2d\x84\x98\x8d"
+			  "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6"
+			  "\x13\xc2\xdd\x08\x45\x79\x41\xa6",
+		.ilen	= 64,
+		.result	= "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
+			  "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+			  "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
+			  "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+			  "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
+			  "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+			  "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
+			  "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+		.rlen	= 64,
+	}
+};
+
+static struct cipher_testvec aes_ctr_rfc3686_enc_tv_template[] = {
 	{ /* From RFC 3686 */
 		.key	= "\xae\x68\x52\xf8\x12\x10\x67\xcc"
 			  "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
@@ -5114,7 +5289,7 @@
 	},
 };
 
-static struct cipher_testvec aes_ctr_dec_tv_template[] = {
+static struct cipher_testvec aes_ctr_rfc3686_dec_tv_template[] = {
 	{ /* From RFC 3686 */
 		.key	= "\xae\x68\x52\xf8\x12\x10\x67\xcc"
 			  "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
@@ -5825,6 +6000,470 @@
 	},
 };
 
+/*
+ * rfc4309 refers to section 8 of rfc3610 for test vectors, but they all
+ * use a 13-byte nonce, we only support an 11-byte nonce. Similarly, all of
+ * Special Publication 800-38C's test vectors also use nonce lengths our
+ * implementation doesn't support. The following are taken from fips cavs
+ * fax files on hand at Red Hat.
+ *
+ * nb: actual key lengths are (klen - 3), the last 3 bytes are actually
+ * part of the nonce which combine w/the iv, but need to be input this way.
+ */
+static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
+	{
+		.key	= "\x83\xac\x54\x66\xc2\xeb\xe5\x05"
+			  "\x2e\x01\xd1\xfc\x5d\x82\x66\x2e"
+			  "\x96\xac\x59",
+		.klen	= 19,
+		.iv	= "\x30\x07\xa1\xe2\xa2\xc7\x55\x24",
+		.alen	= 0,
+		.input	= "\x19\xc8\x81\xf6\xe9\x86\xff\x93"
+			  "\x0b\x78\x67\xe5\xbb\xb7\xfc\x6e"
+			  "\x83\x77\xb3\xa6\x0c\x8c\x9f\x9c"
+			  "\x35\x2e\xad\xe0\x62\xf9\x91\xa1",
+		.ilen	= 32,
+		.result	= "\xab\x6f\xe1\x69\x1d\x19\x99\xa8"
+			  "\x92\xa0\xc4\x6f\x7e\xe2\x8b\xb1"
+			  "\x70\xbb\x8c\xa6\x4c\x6e\x97\x8a"
+			  "\x57\x2b\xbe\x5d\x98\xa6\xb1\x32"
+			  "\xda\x24\xea\xd9\xa1\x39\x98\xfd"
+			  "\xa4\xbe\xd9\xf2\x1a\x6d\x22\xa8",
+		.rlen	= 48,
+	}, {
+		.key	= "\x1e\x2c\x7e\x01\x41\x9a\xef\xc0"
+			  "\x0d\x58\x96\x6e\x5c\xa2\x4b\xd3"
+			  "\x4f\xa3\x19",
+		.klen	= 19,
+		.iv	= "\xd3\x01\x5a\xd8\x30\x60\x15\x56",
+		.assoc	= "\xda\xe6\x28\x9c\x45\x2d\xfd\x63"
+			  "\x5e\xda\x4c\xb6\xe6\xfc\xf9\xb7"
+			  "\x0c\x56\xcb\xe4\xe0\x05\x7a\xe1"
+			  "\x0a\x63\x09\x78\xbc\x2c\x55\xde",
+		.alen	= 32,
+		.input	= "\x87\xa3\x36\xfd\x96\xb3\x93\x78"
+			  "\xa9\x28\x63\xba\x12\xa3\x14\x85"
+			  "\x57\x1e\x06\xc9\x7b\x21\xef\x76"
+			  "\x7f\x38\x7e\x8e\x29\xa4\x3e\x7e",
+		.ilen	= 32,
+		.result	= "\x8a\x1e\x11\xf0\x02\x6b\xe2\x19"
+			  "\xfc\x70\xc4\x6d\x8e\xb7\x99\xab"
+			  "\xc5\x4b\xa2\xac\xd3\xf3\x48\xff"
+			  "\x3b\xb5\xce\x53\xef\xde\xbb\x02"
+			  "\xa9\x86\x15\x6c\x13\xfe\xda\x0a"
+			  "\x22\xb8\x29\x3d\xd8\x39\x9a\x23",
+		.rlen	= 48,
+	}, {
+		.key	= "\xf4\x6b\xc2\x75\x62\xfe\xb4\xe1"
+			  "\xa3\xf0\xff\xdd\x4e\x4b\x12\x75"
+			  "\x53\x14\x73\x66\x8d\x88\xf6\x80"
+			  "\xa0\x20\x35",
+		.klen	= 27,
+		.iv	= "\x26\xf2\x21\x8d\x50\x20\xda\xe2",
+		.assoc	= "\x5b\x9e\x13\x67\x02\x5e\xef\xc1"
+			  "\x6c\xf9\xd7\x1e\x52\x8f\x7a\x47"
+			  "\xe9\xd4\xcf\x20\x14\x6e\xf0\x2d"
+			  "\xd8\x9e\x2b\x56\x10\x23\x56\xe7",
+		.alen	= 32,
+		.ilen	= 0,
+		.result	= "\x36\xea\x7a\x70\x08\xdc\x6a\xbc"
+			  "\xad\x0c\x7a\x63\xf6\x61\xfd\x9b",
+		.rlen	= 16,
+	}, {
+		.key	= "\x56\xdf\x5c\x8f\x26\x3f\x0e\x42"
+			  "\xef\x7a\xd3\xce\xfc\x84\x60\x62"
+			  "\xca\xb4\x40\xaf\x5f\xc9\xc9\x01"
+			  "\xd6\x3c\x8c",
+		.klen	= 27,
+		.iv	= "\x86\x84\xb6\xcd\xef\x09\x2e\x94",
+		.assoc	= "\x02\x65\x78\x3c\xe9\x21\x30\x91"
+			  "\xb1\xb9\xda\x76\x9a\x78\x6d\x95"
+			  "\xf2\x88\x32\xa3\xf2\x50\xcb\x4c"
+			  "\xe3\x00\x73\x69\x84\x69\x87\x79",
+		.alen	= 32,
+		.input	= "\x9f\xd2\x02\x4b\x52\x49\x31\x3c"
+			  "\x43\x69\x3a\x2d\x8e\x70\xad\x7e"
+			  "\xe0\xe5\x46\x09\x80\x89\x13\xb2"
+			  "\x8c\x8b\xd9\x3f\x86\xfb\xb5\x6b",
+		.ilen	= 32,
+		.result	= "\x39\xdf\x7c\x3c\x5a\x29\xb9\x62"
+			  "\x5d\x51\xc2\x16\xd8\xbd\x06\x9f"
+			  "\x9b\x6a\x09\x70\xc1\x51\x83\xc2"
+			  "\x66\x88\x1d\x4f\x9a\xda\xe0\x1e"
+			  "\xc7\x79\x11\x58\xe5\x6b\x20\x40"
+			  "\x7a\xea\x46\x42\x8b\xe4\x6f\xe1",
+		.rlen	= 48,
+	}, {
+		.key	= "\xe0\x8d\x99\x71\x60\xd7\x97\x1a"
+			  "\xbd\x01\x99\xd5\x8a\xdf\x71\x3a"
+			  "\xd3\xdf\x24\x4b\x5e\x3d\x4b\x4e"
+			  "\x30\x7a\xb9\xd8\x53\x0a\x5e\x2b"
+			  "\x1e\x29\x91",
+		.klen	= 35,
+		.iv	= "\xad\x8e\xc1\x53\x0a\xcf\x2d\xbe",
+		.assoc	= "\x19\xb6\x1f\x57\xc4\xf3\xf0\x8b"
+			  "\x78\x2b\x94\x02\x29\x0f\x42\x27"
+			  "\x6b\x75\xcb\x98\x34\x08\x7e\x79"
+			  "\xe4\x3e\x49\x0d\x84\x8b\x22\x87",
+		.alen	= 32,
+		.input	= "\xe1\xd9\xd8\x13\xeb\x3a\x75\x3f"
+			  "\x9d\xbd\x5f\x66\xbe\xdc\xbb\x66"
+			  "\xbf\x17\x99\x62\x4a\x39\x27\x1f"
+			  "\x1d\xdc\x24\xae\x19\x2f\x98\x4c",
+		.ilen	= 32,
+		.result	= "\x19\xb8\x61\x33\x45\x2b\x43\x96"
+			  "\x6f\x51\xd0\x20\x30\x7d\x9b\xc6"
+			  "\x26\x3d\xf8\xc9\x65\x16\xa8\x9f"
+			  "\xf0\x62\x17\x34\xf2\x1e\x8d\x75"
+			  "\x4e\x13\xcc\xc0\xc3\x2a\x54\x2d",
+		.rlen	= 40,
+	}, {
+		.key	= "\x7c\xc8\x18\x3b\x8d\x99\xe0\x7c"
+			  "\x45\x41\xb8\xbd\x5c\xa7\xc2\x32"
+			  "\x8a\xb8\x02\x59\xa4\xfe\xa9\x2c"
+			  "\x09\x75\x9a\x9b\x3c\x9b\x27\x39"
+			  "\xf9\xd9\x4e",
+		.klen	= 35,
+		.iv	= "\x63\xb5\x3d\x9d\x43\xf6\x1e\x50",
+		.assoc	= "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b"
+			  "\x13\x02\x01\x0c\x83\x4c\x96\x35"
+			  "\x8e\xd6\x39\xcf\x7d\x14\x9b\x94"
+			  "\xb0\x39\x36\xe6\x8f\x57\xe0\x13",
+		.alen	= 32,
+		.input	= "\x3b\x6c\x29\x36\xb6\xef\x07\xa6"
+			  "\x83\x72\x07\x4f\xcf\xfa\x66\x89"
+			  "\x5f\xca\xb1\xba\xd5\x8f\x2c\x27"
+			  "\x30\xdb\x75\x09\x93\xd4\x65\xe4",
+		.ilen	= 32,
+		.result	= "\xb0\x88\x5a\x33\xaa\xe5\xc7\x1d"
+			  "\x85\x23\xc7\xc6\x2f\xf4\x1e\x3d"
+			  "\xcc\x63\x44\x25\x07\x78\x4f\x9e"
+			  "\x96\xb8\x88\xeb\xbc\x48\x1f\x06"
+			  "\x39\xaf\x39\xac\xd8\x4a\x80\x39"
+			  "\x7b\x72\x8a\xf7",
+		.rlen	= 44,
+	}, {
+		.key	= "\xab\xd0\xe9\x33\x07\x26\xe5\x83"
+			  "\x8c\x76\x95\xd4\xb6\xdc\xf3\x46"
+			  "\xf9\x8f\xad\xe3\x02\x13\x83\x77"
+			  "\x3f\xb0\xf1\xa1\xa1\x22\x0f\x2b"
+			  "\x24\xa7\x8b",
+		.klen	= 35,
+		.iv	= "\x07\xcb\xcc\x0e\xe6\x33\xbf\xf5",
+		.assoc	= "\xd4\xdb\x30\x1d\x03\xfe\xfd\x5f"
+			  "\x87\xd4\x8c\xb6\xb6\xf1\x7a\x5d"
+			  "\xab\x90\x65\x8d\x8e\xca\x4d\x4f"
+			  "\x16\x0c\x40\x90\x4b\xc7\x36\x73",
+		.alen	= 32,
+		.input	= "\xf5\xc6\x7d\x48\xc1\xb7\xe6\x92"
+			  "\x97\x5a\xca\xc4\xa9\x6d\xf9\x3d"
+			  "\x6c\xde\xbc\xf1\x90\xea\x6a\xb2"
+			  "\x35\x86\x36\xaf\x5c\xfe\x4b\x3a",
+		.ilen	= 32,
+		.result	= "\x83\x6f\x40\x87\x72\xcf\xc1\x13"
+			  "\xef\xbb\x80\x21\x04\x6c\x58\x09"
+			  "\x07\x1b\xfc\xdf\xc0\x3f\x5b\xc7"
+			  "\xe0\x79\xa8\x6e\x71\x7c\x3f\xcf"
+			  "\x5c\xda\xb2\x33\xe5\x13\xe2\x0d"
+			  "\x74\xd1\xef\xb5\x0f\x3a\xb5\xf8",
+		.rlen	= 48,
+	},
+};
+
+static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
+	{
+		.key	= "\xab\x2f\x8a\x74\xb7\x1c\xd2\xb1"
+			  "\xff\x80\x2e\x48\x7d\x82\xf8\xb9"
+			  "\xc6\xfb\x7d",
+		.klen	= 19,
+		.iv	= "\x80\x0d\x13\xab\xd8\xa6\xb2\xd8",
+		.alen	= 0,
+		.input	= "\xd5\xe8\x93\x9f\xc7\x89\x2e\x2b",
+		.ilen	= 8,
+		.result	= "\x00",
+		.rlen	= 0,
+		.novrfy	= 1,
+	}, {
+		.key	= "\xab\x2f\x8a\x74\xb7\x1c\xd2\xb1"
+			  "\xff\x80\x2e\x48\x7d\x82\xf8\xb9"
+			  "\xaf\x94\x87",
+		.klen	= 19,
+		.iv	= "\x78\x35\x82\x81\x7f\x88\x94\x68",
+		.alen	= 0,
+		.input	= "\x41\x3c\xb8\x87\x73\xcb\xf3\xf3",
+		.ilen	= 8,
+		.result	= "\x00",
+		.rlen	= 0,
+	}, {
+		.key	= "\x61\x0e\x8c\xae\xe3\x23\xb6\x38"
+			  "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8"
+			  "\xc6\xfb\x7d",
+		.klen	= 19,
+		.iv	= "\x80\x0d\x13\xab\xd8\xa6\xb2\xd8",
+		.assoc	= "\xf3\x94\x87\x78\x35\x82\x81\x7f"
+			  "\x88\x94\x68\xb1\x78\x6b\x2b\xd6"
+			  "\x04\x1f\x4e\xed\x78\xd5\x33\x66"
+			  "\xd8\x94\x99\x91\x81\x54\x62\x57",
+		.alen	= 32,
+		.input	= "\xf0\x7c\x29\x02\xae\x1c\x2f\x55"
+			  "\xd0\xd1\x3d\x1a\xa3\x6d\xe4\x0a"
+			  "\x86\xb0\x87\x6b\x62\x33\x8c\x34"
+			  "\xce\xab\x57\xcc\x79\x0b\xe0\x6f"
+			  "\x5c\x3e\x48\x1f\x6c\x46\xf7\x51"
+			  "\x8b\x84\x83\x2a\xc1\x05\xb8\xc5",
+		.ilen	= 48,
+		.result	= "\x50\x82\x3e\x07\xe2\x1e\xb6\xfb"
+			  "\x33\xe4\x73\xce\xd2\xfb\x95\x79"
+			  "\xe8\xb4\xb5\x77\x11\x10\x62\x6f"
+			  "\x6a\x82\xd1\x13\xec\xf5\xd0\x48",
+		.rlen	= 32,
+		.novrfy	= 1,
+	}, {
+		.key	= "\x61\x0e\x8c\xae\xe3\x23\xb6\x38"
+			  "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8"
+			  "\x05\xe0\xc9",
+		.klen	= 19,
+		.iv	= "\x0f\xed\x34\xea\x97\xd4\x3b\xdf",
+		.assoc	= "\x49\x5c\x50\x1f\x1d\x94\xcc\x81"
+			  "\xba\xb7\xb6\x03\xaf\xa5\xc1\xa1"
+			  "\xd8\x5c\x42\x68\xe0\x6c\xda\x89"
+			  "\x05\xac\x56\xac\x1b\x2a\xd3\x86",
+		.alen	= 32,
+		.input	= "\x39\xbe\x7d\x15\x62\x77\xf3\x3c"
+			  "\xad\x83\x52\x6d\x71\x03\x25\x1c"
+			  "\xed\x81\x3a\x9a\x16\x7d\x19\x80"
+			  "\x72\x04\x72\xd0\xf6\xff\x05\x0f"
+			  "\xb7\x14\x30\x00\x32\x9e\xa0\xa6"
+			  "\x9e\x5a\x18\xa1\xb8\xfe\xdb\xd3",
+		.ilen	= 48,
+		.result	= "\x75\x05\xbe\xc2\xd9\x1e\xde\x60"
+			  "\x47\x3d\x8c\x7d\xbd\xb5\xd9\xb7"
+			  "\xf2\xae\x61\x05\x8f\x82\x24\x3f"
+			  "\x9c\x67\x91\xe1\x38\x4f\xe4\x0c",
+		.rlen	= 32,
+	}, {
+		.key	= "\x39\xbb\xa7\xbe\x59\x97\x9e\x73"
+			  "\xa2\xbc\x6b\x98\xd7\x75\x7f\xe3"
+			  "\xa4\x48\x93\x39\x26\x71\x4a\xc6"
+			  "\xee\x49\x83",
+		.klen	= 27,
+		.iv	= "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+		.assoc	= "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1"
+			  "\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+			  "\xa4\xf0\x13\x05\xd1\x77\x99\x67"
+			  "\x11\xc4\xc6\xdb\x00\x56\x36\x61",
+		.alen	= 32,
+		.input	= "\x71\x99\xfa\xf4\x44\x12\x68\x9b",
+		.ilen	= 8,
+		.result	= "\x00",
+		.rlen	= 0,
+	}, {
+		.key	= "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+			  "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+			  "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
+			  "\xee\x49\x83",
+		.klen	= 27,
+		.iv	= "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+		.assoc	= "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1"
+			  "\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+			  "\xa4\xf0\x13\x05\xd1\x77\x99\x67"
+			  "\x11\xc4\xc6\xdb\x00\x56\x36\x61",
+		.alen	= 32,
+		.input	= "\xfb\xe5\x5d\x34\xbe\xe5\xe8\xe7"
+			  "\x5a\xef\x2f\xbf\x1f\x7f\xd4\xb2"
+			  "\x66\xca\x61\x1e\x96\x7a\x61\xb3"
+			  "\x1c\x16\x45\x52\xba\x04\x9c\x9f"
+			  "\xb1\xd2\x40\xbc\x52\x7c\x6f\xb1",
+		.ilen	= 40,
+		.result	= "\x85\x34\x66\x42\xc8\x92\x0f\x36"
+			  "\x58\xe0\x6b\x91\x3c\x98\x5c\xbb"
+			  "\x0a\x85\xcc\x02\xad\x7a\x96\xe9"
+			  "\x65\x43\xa4\xc3\x0f\xdc\x55\x81",
+		.rlen	= 32,
+	}, {
+		.key	= "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+			  "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+			  "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
+			  "\xd1\xfc\x57",
+		.klen	= 27,
+		.iv	= "\x9c\xfe\xb8\x9c\xad\x71\xaa\x1f",
+		.assoc	= "\x86\x67\xa5\xa9\x14\x5f\x0d\xc6"
+			  "\xff\x14\xc7\x44\xbf\x6c\x3a\xc3"
+			  "\xff\xb6\x81\xbd\xe2\xd5\x06\xc7"
+			  "\x3c\xa1\x52\x13\x03\x8a\x23\x3a",
+		.alen	= 32,
+		.input	= "\x3f\x66\xb0\x9d\xe5\x4b\x38\x00"
+			  "\xc6\x0e\x6e\xe5\xd6\x98\xa6\x37"
+			  "\x8c\x26\x33\xc6\xb2\xa2\x17\xfa"
+			  "\x64\x19\xc0\x30\xd7\xfc\x14\x6b"
+			  "\xe3\x33\xc2\x04\xb0\x37\xbe\x3f"
+			  "\xa9\xb4\x2d\x68\x03\xa3\x44\xef",
+		.ilen	= 48,
+		.result	= "\x02\x87\x4d\x28\x80\x6e\xb2\xed"
+			  "\x99\x2a\xa8\xca\x04\x25\x45\x90"
+			  "\x1d\xdd\x5a\xd9\xe4\xdb\x9c\x9c"
+			  "\x49\xe9\x01\xfe\xa7\x80\x6d\x6b",
+		.rlen	= 32,
+		.novrfy	= 1,
+	}, {
+		.key	= "\xa4\x4b\x54\x29\x0a\xb8\x6d\x01"
+			  "\x5b\x80\x2a\xcf\x25\xc4\xb7\x5c"
+			  "\x20\x2c\xad\x30\xc2\x2b\x41\xfb"
+			  "\x0e\x85\xbc\x33\xad\x0f\x2b\xff"
+			  "\xee\x49\x83",
+		.klen	= 35,
+		.iv	= "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+		.alen	= 0,
+		.input	= "\x1f\xb8\x8f\xa3\xdd\x54\x00\xf2",
+		.ilen	= 8,
+		.result	= "\x00",
+		.rlen	= 0,
+	}, {
+		.key	= "\x39\xbb\xa7\xbe\x59\x97\x9e\x73"
+			  "\xa2\xbc\x6b\x98\xd7\x75\x7f\xe3"
+			  "\xa4\x48\x93\x39\x26\x71\x4a\xc6"
+			  "\xae\x8f\x11\x4c\xc2\x9c\x4a\xbb"
+			  "\x85\x34\x66",
+		.klen	= 35,
+		.iv	= "\x42\xc8\x92\x0f\x36\x58\xe0\x6b",
+		.alen	= 0,
+		.input	= "\x48\x01\x5e\x02\x24\x04\x66\x47"
+			  "\xa1\xea\x6f\xaf\xe8\xfc\xfb\xdd"
+			  "\xa5\xa9\x87\x8d\x84\xee\x2e\x77"
+			  "\xbb\x86\xb9\xf5\x5c\x6c\xff\xf6"
+			  "\x72\xc3\x8e\xf7\x70\xb1\xb2\x07"
+			  "\xbc\xa8\xa3\xbd\x83\x7c\x1d\x2a",
+		.ilen	= 48,
+		.result	= "\xdc\x56\xf2\x71\xb0\xb1\xa0\x6c"
+			  "\xf0\x97\x3a\xfb\x6d\xe7\x32\x99"
+			  "\x3e\xaf\x70\x5e\xb2\x4d\xea\x39"
+			  "\x89\xd4\x75\x7a\x63\xb1\xda\x93",
+		.rlen	= 32,
+		.novrfy	= 1,
+	}, {
+		.key	= "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+			  "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+			  "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
+			  "\x0d\x1a\x53\x3b\xb5\xe3\xf8\x8b"
+			  "\xcf\x76\x3f",
+		.klen	= 35,
+		.iv	= "\xd9\x95\x75\x8f\x44\x89\x40\x7b",
+		.assoc	= "\x8f\x86\x6c\x4d\x1d\xc5\x39\x88"
+			  "\xc8\xf3\x5c\x52\x10\x63\x6f\x2b"
+			  "\x8a\x2a\xc5\x6f\x30\x23\x58\x7b"
+			  "\xfb\x36\x03\x11\xb4\xd9\xf2\xfe",
+		.alen	= 32,
+		.input	= "\x48\x58\xd6\xf3\xad\x63\x58\xbf"
+			  "\xae\xc7\x5e\xae\x83\x8f\x7b\xe4"
+			  "\x78\x5c\x4c\x67\x71\x89\x94\xbf"
+			  "\x47\xf1\x63\x7e\x1c\x59\xbd\xc5"
+			  "\x7f\x44\x0a\x0c\x01\x18\x07\x92"
+			  "\xe1\xd3\x51\xce\x32\x6d\x0c\x5b",
+		.ilen	= 48,
+		.result	= "\xc2\x54\xc8\xde\x78\x87\x77\x40"
+			  "\x49\x71\xe4\xb7\xe7\xcb\x76\x61"
+			  "\x0a\x41\xb9\xe9\xc0\x76\x54\xab"
+			  "\x04\x49\x3b\x19\x93\x57\x25\x5d",
+		.rlen	= 32,
+	},
+};
+
+/*
+ * ANSI X9.31 Continuous Pseudo-Random Number Generator (AES mode)
+ * test vectors, taken from Appendix B.2.9 and B.2.10:
+ *     http://csrc.nist.gov/groups/STM/cavp/documents/rng/RNGVS.pdf
+ * Only AES-128 is supported at this time.
+ */
+#define ANSI_CPRNG_AES_TEST_VECTORS	6
+
+static struct cprng_testvec ansi_cprng_aes_tv_template[] = {
+	{
+		.key	= "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+			  "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+		.klen	= 16,
+		.dt	= "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+			  "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xf9",
+		.dtlen	= 16,
+		.v	= "\x80\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.vlen	= 16,
+		.result	= "\x59\x53\x1e\xd1\x3b\xb0\xc0\x55"
+			  "\x84\x79\x66\x85\xc1\x2f\x76\x41",
+		.rlen	= 16,
+		.loops	= 1,
+	}, {
+		.key	= "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+			  "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+		.klen	= 16,
+		.dt	= "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+			  "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfa",
+		.dtlen	= 16,
+		.v	= "\xc0\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.vlen	= 16,
+		.result	= "\x7c\x22\x2c\xf4\xca\x8f\xa2\x4c"
+			  "\x1c\x9c\xb6\x41\xa9\xf3\x22\x0d",
+		.rlen	= 16,
+		.loops	= 1,
+	}, {
+		.key	= "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+			  "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+		.klen	= 16,
+		.dt	= "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+			  "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfb",
+		.dtlen	= 16,
+		.v	= "\xe0\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.vlen	= 16,
+		.result	= "\x8a\xaa\x00\x39\x66\x67\x5b\xe5"
+			  "\x29\x14\x28\x81\xa9\x4d\x4e\xc7",
+		.rlen	= 16,
+		.loops	= 1,
+	}, {
+		.key	= "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+			  "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+		.klen	= 16,
+		.dt	= "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+			  "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfc",
+		.dtlen	= 16,
+		.v	= "\xf0\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.vlen	= 16,
+		.result	= "\x88\xdd\xa4\x56\x30\x24\x23\xe5"
+			  "\xf6\x9d\xa5\x7e\x7b\x95\xc7\x3a",
+		.rlen	= 16,
+		.loops	= 1,
+	}, {
+		.key	= "\xf3\xb1\x66\x6d\x13\x60\x72\x42"
+			  "\xed\x06\x1c\xab\xb8\xd4\x62\x02",
+		.klen	= 16,
+		.dt	= "\xe6\xb3\xbe\x78\x2a\x23\xfa\x62"
+			  "\xd7\x1d\x4a\xfb\xb0\xe9\x22\xfd",
+		.dtlen	= 16,
+		.v	= "\xf8\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.vlen	= 16,
+		.result	= "\x05\x25\x92\x46\x61\x79\xd2\xcb"
+			  "\x78\xc4\x0b\x14\x0a\x5a\x9a\xc8",
+		.rlen	= 16,
+		.loops	= 1,
+	}, {	/* Monte Carlo Test */
+		.key	= "\x9f\x5b\x51\x20\x0b\xf3\x34\xb5"
+			  "\xd8\x2b\xe8\xc3\x72\x55\xc8\x48",
+		.klen	= 16,
+		.dt	= "\x63\x76\xbb\xe5\x29\x02\xba\x3b"
+			  "\x67\xc9\x25\xfa\x70\x1f\x11\xac",
+		.dtlen	= 16,
+		.v	= "\x57\x2c\x8e\x76\x87\x26\x47\x97"
+			  "\x7e\x74\xfb\xdd\xc4\x95\x01\xd1",
+		.vlen	= 16,
+		.result	= "\x48\xe9\xbd\x0d\x06\xee\x18\xfb"
+			  "\xe4\x57\x90\xd5\xc3\xfc\x9b\x73",
+		.rlen	= 16,
+		.loops	= 10000,
+	},
+};
+
 /* Cast5 test vectors from RFC 2144 */
 #define CAST5_ENC_TEST_VECTORS	3
 #define CAST5_DEC_TEST_VECTORS	3
diff -druN linux-libre-2.6.30-gnu/crypto/xor.c linux-libre-2.6.31-gnu/crypto/xor.c
--- linux-libre-2.6.30-gnu/crypto/xor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/xor.c	2009-09-09 18:13:59.000000000 -0400
@@ -101,7 +101,12 @@
 	void *b1, *b2;
 	struct xor_block_template *f, *fastest;
 
-	b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
+	/*
+	 * Note: Since the memory is not actually used for _anything_ but to
+	 * test the XOR speed, we don't really want kmemcheck to warn about
+	 * reading uninitialized bytes here.
+	 */
+	b1 = (void *) __get_free_pages(GFP_KERNEL | __GFP_NOTRACK, 2);
 	if (!b1) {
 		printk(KERN_WARNING "xor: Yikes!  No memory available.\n");
 		return -ENOMEM;
diff -druN linux-libre-2.6.30-gnu/crypto/zlib.c linux-libre-2.6.31-gnu/crypto/zlib.c
--- linux-libre-2.6.30-gnu/crypto/zlib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/crypto/zlib.c	2009-09-09 18:13:59.000000000 -0400
@@ -165,15 +165,15 @@
 		return -EINVAL;
 	}
 
+	ret = req->avail_out - stream->avail_out;
 	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
-		 req->avail_in - stream->avail_in,
-		 req->avail_out - stream->avail_out);
+		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
 	req->avail_in = stream->avail_in;
 	req->next_out = stream->next_out;
 	req->avail_out = stream->avail_out;
-	return 0;
+	return ret;
 }
 
 static int zlib_compress_final(struct crypto_pcomp *tfm,
@@ -195,15 +195,15 @@
 		return -EINVAL;
 	}
 
+	ret = req->avail_out - stream->avail_out;
 	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
-		 req->avail_in - stream->avail_in,
-		 req->avail_out - stream->avail_out);
+		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
 	req->avail_in = stream->avail_in;
 	req->next_out = stream->next_out;
 	req->avail_out = stream->avail_out;
-	return 0;
+	return ret;
 }
 
 
@@ -280,15 +280,15 @@
 		return -EINVAL;
 	}
 
+	ret = req->avail_out - stream->avail_out;
 	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
-		 req->avail_in - stream->avail_in,
-		 req->avail_out - stream->avail_out);
+		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
 	req->avail_in = stream->avail_in;
 	req->next_out = stream->next_out;
 	req->avail_out = stream->avail_out;
-	return 0;
+	return ret;
 }
 
 static int zlib_decompress_final(struct crypto_pcomp *tfm,
@@ -328,15 +328,15 @@
 		return -EINVAL;
 	}
 
+	ret = req->avail_out - stream->avail_out;
 	pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
 		 stream->avail_in, stream->avail_out,
-		 req->avail_in - stream->avail_in,
-		 req->avail_out - stream->avail_out);
+		 req->avail_in - stream->avail_in, ret);
 	req->next_in = stream->next_in;
 	req->avail_in = stream->avail_in;
 	req->next_out = stream->next_out;
 	req->avail_out = stream->avail_out;
-	return 0;
+	return ret;
 }
 
 
diff -druN linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-block linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-block
--- linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-block	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-block	2009-09-09 18:13:59.000000000 -0400
@@ -60,3 +60,71 @@
 		Indicates whether the block layer should automatically
 		generate checksums for write requests bound for
 		devices that support receiving integrity metadata.
+
+What:		/sys/block/<disk>/alignment_offset
+Date:		April 2009
+Contact:	Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+		Storage devices may report a physical block size that is
+		bigger than the logical block size (for instance a drive
+		with 4KB physical sectors exposing 512-byte logical
+		blocks to the operating system).  This parameter
+		indicates how many bytes the beginning of the device is
+		offset from the disk's natural alignment.
+
+What:		/sys/block/<disk>/<partition>/alignment_offset
+Date:		April 2009
+Contact:	Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+		Storage devices may report a physical block size that is
+		bigger than the logical block size (for instance a drive
+		with 4KB physical sectors exposing 512-byte logical
+		blocks to the operating system).  This parameter
+		indicates how many bytes the beginning of the partition
+		is offset from the disk's natural alignment.
+
+What:		/sys/block/<disk>/queue/logical_block_size
+Date:		May 2009
+Contact:	Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+		This is the smallest unit the storage device can
+		address.  It is typically 512 bytes.
+
+What:		/sys/block/<disk>/queue/physical_block_size
+Date:		May 2009
+Contact:	Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+		This is the smallest unit a physical storage device can
+		write atomically.  It is usually the same as the logical
+		block size but may be bigger.  One example is SATA
+		drives with 4KB sectors that expose a 512-byte logical
+		block size to the operating system.  For stacked block
+		devices the physical_block_size variable contains the
+		maximum physical_block_size of the component devices.
+
+What:		/sys/block/<disk>/queue/minimum_io_size
+Date:		April 2009
+Contact:	Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+		Storage devices may report a granularity or preferred
+		minimum I/O size which is the smallest request the
+		device can perform without incurring a performance
+		penalty.  For disk drives this is often the physical
+		block size.  For RAID arrays it is often the stripe
+		chunk size.  A properly aligned multiple of
+		minimum_io_size is the preferred request size for
+		workloads where a high number of I/O operations is
+		desired.
+
+What:		/sys/block/<disk>/queue/optimal_io_size
+Date:		April 2009
+Contact:	Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+		Storage devices may report an optimal I/O size, which is
+		the device's preferred unit for sustained I/O.  This is
+		rarely reported for disk drives.  For RAID arrays it is
+		usually the stripe width or the internal track size.  A
+		properly aligned multiple of optimal_io_size is the
+		preferred request size for workloads where sustained
+		throughput is desired.  If no optimal I/O size is
+		reported this file contains 0.
diff -druN linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-bus-pci linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-bus-pci
--- linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-bus-pci	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-bus-pci	2009-09-09 18:13:59.000000000 -0400
@@ -122,3 +122,10 @@
 		This symbolic link appears when a device is a Virtual Function.
 		The symbolic link points to the PCI device sysfs entry of the
 		Physical Function this device associates with.
+
+What:		/sys/bus/pci/slots/.../module
+Date:		June 2009
+Contact:	linux-pci@vger.kernel.org
+Description:
+		This symbolic link points to the PCI hotplug controller driver
+		module that manages the hotplug slot.
diff -druN linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
--- linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,33 @@
+Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/model
+Date:		March 2009
+Kernel Version: 2.6.30
+Contact:	iss_storagedev@hp.com
+Description:	Displays the SCSI INQUIRY page 0 model for logical drive
+		Y of controller X.
+
+Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/rev
+Date:		March 2009
+Kernel Version: 2.6.30
+Contact:	iss_storagedev@hp.com
+Description:	Displays the SCSI INQUIRY page 0 revision for logical
+		drive Y of controller X.
+
+Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/unique_id
+Date:		March 2009
+Kernel Version: 2.6.30
+Contact:	iss_storagedev@hp.com
+Description:	Displays the SCSI INQUIRY page 83 serial number for logical
+		drive Y of controller X.
+
+Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/vendor
+Date:		March 2009
+Kernel Version: 2.6.30
+Contact:	iss_storagedev@hp.com
+Description:	Displays the SCSI INQUIRY page 0 vendor for logical drive
+		Y of controller X.
+
+Where:		/sys/bus/pci/devices/<dev>/ccissX/cXdY/block:cciss!cXdY
+Date:		March 2009
+Kernel Version: 2.6.30
+Contact:	iss_storagedev@hp.com
+Description:	A symbolic link to /sys/block/cciss!cXdY
diff -druN linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-class-mtd linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-class-mtd
--- linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-class-mtd	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-class-mtd	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,125 @@
+What:		/sys/class/mtd/
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		The mtd/ class subdirectory belongs to the MTD subsystem
+		(MTD core).
+
+What:		/sys/class/mtd/mtdX/
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		The /sys/class/mtd/mtd{0,1,2,3,...} directories correspond
+		to each /dev/mtdX character device.  These may represent
+		physical/simulated flash devices, partitions on a flash
+		device, or concatenated flash devices.  They exist regardless
+		of whether CONFIG_MTD_CHAR is actually enabled.
+
+What:		/sys/class/mtd/mtdXro/
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		These directories provide the corresponding read-only device
+		nodes for /sys/class/mtd/mtdX/ .  They are only created
+		(for the benefit of udev) if CONFIG_MTD_CHAR is enabled.
+
+What:		/sys/class/mtd/mtdX/dev
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		Major and minor numbers of the character device corresponding
+		to this MTD device (in <major>:<minor> format).  This is the
+		read-write device so <minor> will be even.
+
+What:		/sys/class/mtd/mtdXro/dev
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		Major and minor numbers of the character device corresponding
+		to the read-only variant of thie MTD device (in
+		<major>:<minor> format).  In this case <minor> will be odd.
+
+What:		/sys/class/mtd/mtdX/erasesize
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		"Major" erase size for the device.  If numeraseregions is
+		zero, this is the eraseblock size for the entire device.
+		Otherwise, the MEMGETREGIONCOUNT/MEMGETREGIONINFO ioctls
+		can be used to determine the actual eraseblock layout.
+
+What:		/sys/class/mtd/mtdX/flags
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		A hexadecimal value representing the device flags, ORed
+		together:
+
+		0x0400: MTD_WRITEABLE - device is writable
+		0x0800: MTD_BIT_WRITEABLE - single bits can be flipped
+		0x1000: MTD_NO_ERASE - no erase necessary
+		0x2000: MTD_POWERUP_LOCK - always locked after reset
+
+What:		/sys/class/mtd/mtdX/name
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		A human-readable ASCII name for the device or partition.
+		This will match the name in /proc/mtd .
+
+What:		/sys/class/mtd/mtdX/numeraseregions
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		For devices that have variable eraseblock sizes, this
+		provides the total number of erase regions.  Otherwise,
+		it will read back as zero.
+
+What:		/sys/class/mtd/mtdX/oobsize
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		Number of OOB bytes per page.
+
+What:		/sys/class/mtd/mtdX/size
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		Total size of the device/partition, in bytes.
+
+What:		/sys/class/mtd/mtdX/type
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		One of the following ASCII strings, representing the device
+		type:
+
+		absent, ram, rom, nor, nand, dataflash, ubi, unknown
+
+What:		/sys/class/mtd/mtdX/writesize
+Date:		April 2009
+KernelVersion:	2.6.29
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		Minimal writable flash unit size.  This will always be
+		a positive integer.
+
+		In the case of NOR flash it is 1 (even though individual
+		bits can be cleared).
+
+		In the case of NAND flash it is one NAND page (or a
+		half page, or a quarter page).
+
+		In the case of ECC NOR, it is the ECC block size.
diff -druN linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-devices-cache_disable linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-devices-cache_disable
--- linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-devices-cache_disable	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-devices-cache_disable	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+What:      /sys/devices/system/cpu/cpu*/cache/index*/cache_disable_X
+Date:      August 2008
+KernelVersion:	2.6.27
+Contact:	mark.langsdorf@amd.com
+Description:	These files exist in every cpu's cache index directories.
+		There are currently 2 cache_disable_# files in each
+		directory.  Reading from these files on a supported
+		processor will return that cache disable index value
+		for that processor and node.  Writing to one of these
+		files will cause the specificed cache index to be disabled.
+
+		Currently, only AMD Family 10h Processors support cache index
+		disable, and only for their L3 caches.  See the BIOS and
+		Kernel Developer's Guide at
+		http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116-Public-GH-BKDG_3.20_2-4-09.pdf
+		for formatting information and other details on the
+		cache index disable.
+Users:    joachim.deguara@amd.com
diff -druN linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-fs-ext4 linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-fs-ext4
--- linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-fs-ext4	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-fs-ext4	2009-09-09 18:13:59.000000000 -0400
@@ -79,3 +79,13 @@
 		This file is read-only and shows the number of
 		kilobytes of data that have been written to this
 		filesystem since it was mounted.
+
+What:		/sys/fs/ext4/<disk>/inode_goal
+Date:		June 2008
+Contact:	"Theodore Ts'o" <tytso@mit.edu>
+Description:
+		Tuning parameter which (if non-zero) controls the goal
+		inode used by the inode allocator in p0reference to
+		all other allocation hueristics.  This is intended for
+		debugging use only, and should be 0 on production
+		systems.
diff -druN linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-pps linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-pps
--- linux-libre-2.6.30-gnu/Documentation/ABI/testing/sysfs-pps	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/ABI/testing/sysfs-pps	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,73 @@
+What:		/sys/class/pps/
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ directory will contain files and
+		directories that will provide a unified interface to
+		the PPS sources.
+
+What:		/sys/class/pps/ppsX/
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ppsX/ directory is related to X-th
+		PPS source into the system. Each directory will
+		contain files to manage and control its PPS source.
+
+What:		/sys/class/pps/ppsX/assert
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ppsX/assert file reports the assert events
+		and the assert sequence number of the X-th source in the form:
+
+			<secs>.<nsec>#<sequence>
+
+		If the source has no assert events the content of this file
+		is empty.
+
+What:		/sys/class/pps/ppsX/clear
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ppsX/clear file reports the clear events
+		and the clear sequence number of the X-th source in the form:
+
+			<secs>.<nsec>#<sequence>
+
+		If the source has no clear events the content of this file
+		is empty.
+
+What:		/sys/class/pps/ppsX/mode
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ppsX/mode file reports the functioning
+		mode of the X-th source in hexadecimal encoding.
+
+		Please, refer to linux/include/linux/pps.h for further
+		info.
+
+What:		/sys/class/pps/ppsX/echo
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ppsX/echo file reports if the X-th does
+		or does not support an "echo" function.
+
+What:		/sys/class/pps/ppsX/name
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ppsX/name file reports the name of the
+		X-th source.
+
+What:		/sys/class/pps/ppsX/path
+Date:		February 2008
+Contact:	Rodolfo Giometti <giometti@linux.it>
+Description:
+		The /sys/class/pps/ppsX/path file reports the path name of
+		the device connected with the X-th source.
+
+		If the source is not connected with any device the content
+		of this file is empty.
diff -druN linux-libre-2.6.30-gnu/Documentation/accounting/getdelays.c linux-libre-2.6.31-gnu/Documentation/accounting/getdelays.c
--- linux-libre-2.6.30-gnu/Documentation/accounting/getdelays.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/accounting/getdelays.c	2009-09-09 18:13:59.000000000 -0400
@@ -246,7 +246,8 @@
 
 int main(int argc, char *argv[])
 {
-	int c, rc, rep_len, aggr_len, len2, cmd_type;
+	int c, rc, rep_len, aggr_len, len2;
+	int cmd_type = TASKSTATS_CMD_ATTR_UNSPEC;
 	__u16 id;
 	__u32 mypid;
 
diff -druN linux-libre-2.6.30-gnu/Documentation/arm/memory.txt linux-libre-2.6.31-gnu/Documentation/arm/memory.txt
--- linux-libre-2.6.30-gnu/Documentation/arm/memory.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/arm/memory.txt	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,8 @@
 				For SA11xx and Xscale, this is used to
 				setup a minicache mapping.
 
+ffff4000	ffffffff	cache aliasing on ARMv6 and later CPUs.
+
 ffff1000	ffff7fff	Reserved.
 				Platforms must not use this address range.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/arm/Samsung-S3C24XX/GPIO.txt linux-libre-2.6.31-gnu/Documentation/arm/Samsung-S3C24XX/GPIO.txt
--- linux-libre-2.6.30-gnu/Documentation/arm/Samsung-S3C24XX/GPIO.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/arm/Samsung-S3C24XX/GPIO.txt	2009-09-09 18:13:59.000000000 -0400
@@ -51,7 +51,7 @@
 -----------
 
   Each pin has an unique number associated with it in regs-gpio.h,
-  eg S3C2410_GPA0 or S3C2410_GPF1. These defines are used to tell
+  eg S3C2410_GPA(0) or S3C2410_GPF(1). These defines are used to tell
   the GPIO functions which pin is to be used.
 
 
@@ -65,11 +65,11 @@
 
   Eg:
 
-     s3c2410_gpio_cfgpin(S3C2410_GPA0, S3C2410_GPA0_ADDR0);
-     s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+     s3c2410_gpio_cfgpin(S3C2410_GPA(0), S3C2410_GPA0_ADDR0);
+     s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
 
-   which would turn GPA0 into the lowest Address line A0, and set
-   GPE8 to be connected to the SDIO/MMC controller's SDDAT1 line.
+   which would turn GPA(0) into the lowest Address line A0, and set
+   GPE(8) to be connected to the SDIO/MMC controller's SDDAT1 line.
 
 
 Reading the current configuration
diff -druN linux-libre-2.6.30-gnu/Documentation/atomic_ops.txt linux-libre-2.6.31-gnu/Documentation/atomic_ops.txt
--- linux-libre-2.6.30-gnu/Documentation/atomic_ops.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/atomic_ops.txt	2009-09-09 18:13:59.000000000 -0400
@@ -229,10 +229,10 @@
 counting, and it works such that once the counter falls to zero it can
 be guaranteed that no other entity can be accessing the object:
 
-static void obj_list_add(struct obj *obj)
+static void obj_list_add(struct obj *obj, struct list_head *head)
 {
 	obj->active = 1;
-	list_add(&obj->list);
+	list_add(&obj->list, head);
 }
 
 static void obj_list_del(struct obj *obj)
diff -druN linux-libre-2.6.30-gnu/Documentation/block/biodoc.txt linux-libre-2.6.31-gnu/Documentation/block/biodoc.txt
--- linux-libre-2.6.30-gnu/Documentation/block/biodoc.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/block/biodoc.txt	2009-09-09 18:13:59.000000000 -0400
@@ -186,7 +186,7 @@
 do not have a corresponding kernel virtual address space mapping) and
 low-memory pages.
 
-Note: Please refer to Documentation/PCI/PCI-DMA-mapping.txt for a discussion
+Note: Please refer to Documentation/DMA-mapping.txt for a discussion
 on PCI high mem DMA aspects and mapping of scatter gather lists, and support
 for 64 bit PCI.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/block/data-integrity.txt linux-libre-2.6.31-gnu/Documentation/block/data-integrity.txt
--- linux-libre-2.6.30-gnu/Documentation/block/data-integrity.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/block/data-integrity.txt	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,7 @@
 scatter-gather lists.
 
 The controller will interleave the buffers on write and split them on
-read.  This means that the Linux can DMA the data buffers to and from
+read.  This means that Linux can DMA the data buffers to and from
 host memory without changes to the page cache.
 
 Also, the 16-bit CRC checksum mandated by both the SCSI and SATA specs
@@ -66,7 +66,7 @@
 
 The IP checksum is weaker than the CRC in terms of detecting bit
 errors.  However, the strength is really in the separation of the data
-buffers and the integrity metadata.  These two distinct buffers much
+buffers and the integrity metadata.  These two distinct buffers must
 match up for an I/O to complete.
 
 The separation of the data and integrity metadata buffers as well as
diff -druN linux-libre-2.6.30-gnu/Documentation/block/deadline-iosched.txt linux-libre-2.6.31-gnu/Documentation/block/deadline-iosched.txt
--- linux-libre-2.6.30-gnu/Documentation/block/deadline-iosched.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/block/deadline-iosched.txt	2009-09-09 18:13:59.000000000 -0400
@@ -58,7 +58,7 @@
 front_merges	(bool)
 ------------
 
-Sometimes it happens that a request enters the io scheduler that is contigious
+Sometimes it happens that a request enters the io scheduler that is contiguous
 with a request that is already on the queue. Either it fits in the back of that
 request, or it fits at the front. That is called either a back merge candidate
 or a front merge candidate. Due to the way files are typically laid out,
diff -druN linux-libre-2.6.30-gnu/Documentation/braille-console.txt linux-libre-2.6.31-gnu/Documentation/braille-console.txt
--- linux-libre-2.6.30-gnu/Documentation/braille-console.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/braille-console.txt	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,7 @@
 
 For simplicity, only one braille console can be enabled, other uses of
 console=brl,... will be discarded.  Also note that it does not interfere with
-the console selection mecanism described in serial-console.txt
+the console selection mechanism described in serial-console.txt
 
 For now, only the VisioBraille device is supported.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/cdrom/packet-writing.txt linux-libre-2.6.31-gnu/Documentation/cdrom/packet-writing.txt
--- linux-libre-2.6.30-gnu/Documentation/cdrom/packet-writing.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/cdrom/packet-writing.txt	2009-09-09 18:13:59.000000000 -0400
@@ -117,7 +117,7 @@
 
 To read pktcdvd device infos in human readable form, do:
 
-	# cat /debug/pktcdvd/pktcdvd[0-7]/info
+	# cat /sys/kernel/debug/pktcdvd/pktcdvd[0-7]/info
 
 For a description of the debugfs interface look into the file:
 
diff -druN linux-libre-2.6.30-gnu/Documentation/cgroups/cpusets.txt linux-libre-2.6.31-gnu/Documentation/cgroups/cpusets.txt
--- linux-libre-2.6.30-gnu/Documentation/cgroups/cpusets.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/cgroups/cpusets.txt	2009-09-09 18:13:59.000000000 -0400
@@ -777,6 +777,18 @@
 # /bin/echo 1-4 > cpus		-> set cpus list to cpus 1,2,3,4
 # /bin/echo 1,2,3,4 > cpus	-> set cpus list to cpus 1,2,3,4
 
+To add a CPU to a cpuset, write the new list of CPUs including the
+CPU to be added. To add 6 to the above cpuset:
+
+# /bin/echo 1-4,6 > cpus	-> set cpus list to cpus 1,2,3,4,6
+
+Similarly to remove a CPU from a cpuset, write the new list of CPUs
+without the CPU to be removed.
+
+To remove all the CPUs:
+
+# /bin/echo "" > cpus		-> clear cpus list
+
 2.3 Setting flags
 -----------------
 
diff -druN linux-libre-2.6.30-gnu/Documentation/cgroups/memory.txt linux-libre-2.6.31-gnu/Documentation/cgroups/memory.txt
--- linux-libre-2.6.30-gnu/Documentation/cgroups/memory.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/cgroups/memory.txt	2009-09-09 18:13:59.000000000 -0400
@@ -152,14 +152,19 @@
 
 usage of mem+swap is limited by memsw.limit_in_bytes.
 
-Note: why 'mem+swap' rather than swap.
+* why 'mem+swap' rather than swap.
 The global LRU(kswapd) can swap out arbitrary pages. Swap-out means
 to move account from memory to swap...there is no change in usage of
-mem+swap.
+mem+swap. In other words, when we want to limit the usage of swap without
+affecting global LRU, mem+swap limit is better than just limiting swap from
+OS point of view.
 
-In other words, when we want to limit the usage of swap without affecting
-global LRU, mem+swap limit is better than just limiting swap from OS point
-of view.
+* What happens when a cgroup hits memory.memsw.limit_in_bytes
+When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out
+in this cgroup. Then, swap-out will not be done by cgroup routine and file
+caches are dropped. But as mentioned above, global LRU can do swapout memory
+from it for sanity of the system's memory management state. You can't forbid
+it by cgroup.
 
 2.5 Reclaim
 
@@ -204,6 +209,7 @@
 
 NOTE: We can use a suffix (k, K, m, M, g or G) to indicate values in kilo,
 mega or gigabytes.
+NOTE: We can write "-1" to reset the *.limit_in_bytes(unlimited).
 
 # cat /cgroups/0/memory.limit_in_bytes
 4194304
diff -druN linux-libre-2.6.30-gnu/Documentation/Changes linux-libre-2.6.31-gnu/Documentation/Changes
--- linux-libre-2.6.30-gnu/Documentation/Changes	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/Changes	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,7 @@
 isdn4k-utils.
 
 o  Gnu C                  3.2                     # gcc --version
-o  Gnu make               3.79.1                  # make --version
+o  Gnu make               3.80                    # make --version
 o  binutils               2.12                    # ld -v
 o  util-linux             2.10o                   # fdformat --version
 o  module-init-tools      0.9.10                  # depmod -V
@@ -48,6 +48,7 @@
 o  oprofile               0.9                     # oprofiled --version
 o  udev                   081                     # udevinfo -V
 o  grub                   0.93                    # grub --version
+o  mcelog		  0.6
 
 Kernel compilation
 ==================
@@ -61,7 +62,7 @@
 Make
 ----
 
-You will need Gnu make 3.79.1 or later to build the kernel.
+You will need Gnu make 3.80 or later to build the kernel.
 
 Binutils
 --------
@@ -71,6 +72,13 @@
 your kernel.  This change does, however, mean that you need a recent
 release of binutils.
 
+Perl
+----
+
+You will need perl 5 and the following modules: Getopt::Long, Getopt::Std,
+File::Basename, and File::Find to build the kernel.
+
+
 System utilities
 ================
 
@@ -276,6 +284,16 @@
 services be protected from the internet-at-large by a firewall where
 that is possible.
 
+mcelog
+------
+
+In Linux 2.6.31+ the i386 kernel needs to run the mcelog utility
+as a regular cronjob similar to the x86-64 kernel to process and log
+machine check events when CONFIG_X86_NEW_MCE is enabled. Machine check
+events are errors reported by the CPU. Processing them is strongly encouraged.
+All x86-64 kernels since 2.6.4 require the mcelog utility to
+process machine checks.
+
 Getting updated software
 ========================
 
@@ -365,6 +383,10 @@
 ----
 o <http://sourceforge.net/projects/fuse>
 
+mcelog
+------
+o <ftp://ftp.kernel.org/pub/linux/utils/cpu/mce/mcelog/>
+
 Networking
 **********
 
diff -druN linux-libre-2.6.30-gnu/Documentation/CodingStyle linux-libre-2.6.31-gnu/Documentation/CodingStyle
--- linux-libre-2.6.30-gnu/Documentation/CodingStyle	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/CodingStyle	2009-09-09 18:13:59.000000000 -0400
@@ -698,8 +698,8 @@
 kernel, which in turn slows the system as a whole down, due to a bigger
 icache footprint for the CPU and simply because there is less memory
 available for the pagecache. Just think about it; a pagecache miss causes a
-disk seek, which easily takes 5 miliseconds. There are a LOT of cpu cycles
-that can go into these 5 miliseconds.
+disk seek, which easily takes 5 milliseconds. There are a LOT of cpu cycles
+that can go into these 5 milliseconds.
 
 A reasonable rule of thumb is to not put inline at functions that have more
 than 3 lines of code in them. An exception to this rule are the cases where
diff -druN linux-libre-2.6.30-gnu/Documentation/connector/cn_test.c linux-libre-2.6.31-gnu/Documentation/connector/cn_test.c
--- linux-libre-2.6.30-gnu/Documentation/connector/cn_test.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/connector/cn_test.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * 	cn_test.c
  * 
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -41,6 +41,12 @@
 	       msg->seq, msg->ack, msg->len, (char *)msg->data);
 }
 
+/*
+ * Do not remove this function even if no one is using it as
+ * this is an example of how to get notifications about new
+ * connector user registration
+ */
+#if 0
 static int cn_test_want_notify(void)
 {
 	struct cn_ctl_msg *ctl;
@@ -117,6 +123,7 @@
 	kfree_skb(skb);
 	return -EINVAL;
 }
+#endif
 
 static u32 cn_test_timer_counter;
 static void cn_test_timer_func(unsigned long __data)
@@ -187,5 +194,5 @@
 module_exit(cn_test_fini);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Connector's test module");
diff -druN linux-libre-2.6.30-gnu/Documentation/connector/ucon.c linux-libre-2.6.31-gnu/Documentation/connector/ucon.c
--- linux-libre-2.6.30-gnu/Documentation/connector/ucon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/connector/ucon.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * 	ucon.c
  *
- * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004+ Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.30-gnu/Documentation/cpu-freq/cpu-drivers.txt linux-libre-2.6.31-gnu/Documentation/cpu-freq/cpu-drivers.txt
--- linux-libre-2.6.30-gnu/Documentation/cpu-freq/cpu-drivers.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/cpu-freq/cpu-drivers.txt	2009-09-09 18:13:59.000000000 -0400
@@ -155,7 +155,7 @@
 - if relation==CPUFREQ_REL_H, try to select a new_freq lower than or equal
   target_freq. ("H for highest, but no higher than")
 
-Here again the frequency table helper might assist you - see section 3
+Here again the frequency table helper might assist you - see section 2
 for details.
 
 
diff -druN linux-libre-2.6.30-gnu/Documentation/cpu-freq/governors.txt linux-libre-2.6.31-gnu/Documentation/cpu-freq/governors.txt
--- linux-libre-2.6.30-gnu/Documentation/cpu-freq/governors.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/cpu-freq/governors.txt	2009-09-09 18:13:59.000000000 -0400
@@ -119,10 +119,6 @@
 what to do about the frequency.  Typically this is set to values of
 around '10000' or more. It's default value is (cmp. with users-guide.txt):
 transition_latency * 1000
-The lowest value you can set is:
-transition_latency * 100 or it may get restricted to a value where it
-makes not sense for the kernel anymore to poll that often which depends
-on your HZ config variable (HZ=1000: max=20000us, HZ=250: max=5000).
 Be aware that transition latency is in ns and sampling_rate is in us, so you
 get the same sysfs value by default.
 Sampling rate should always get adjusted considering the transition latency
@@ -131,14 +127,20 @@
 echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) \
     >ondemand/sampling_rate
 
-show_sampling_rate_(min|max): THIS INTERFACE IS DEPRECATED, DON'T USE IT.
-You can use wider ranges now and the general
-cpuinfo_transition_latency variable (cmp. with user-guide.txt) can be
-used to obtain exactly the same info:
-show_sampling_rate_min = transtition_latency * 500    / 1000
-show_sampling_rate_max = transtition_latency * 500000 / 1000
-(divided by 1000 is to illustrate that sampling rate is in us and
-transition latency is exported ns).
+show_sampling_rate_min:
+The sampling rate is limited by the HW transition latency:
+transition_latency * 100
+Or by kernel restrictions:
+If CONFIG_NO_HZ is set, the limit is 10ms fixed.
+If CONFIG_NO_HZ is not set or no_hz=off boot parameter is used, the
+limits depend on the CONFIG_HZ option:
+HZ=1000: min=20000us  (20ms)
+HZ=250:  min=80000us  (80ms)
+HZ=100:  min=200000us (200ms)
+The highest value of kernel and HW latency restrictions is shown and
+used as the minimum sampling rate.
+
+show_sampling_rate_max: THIS INTERFACE IS DEPRECATED, DON'T USE IT.
 
 up_threshold: defines what the average CPU usage between the samplings
 of 'sampling_rate' needs to be for the kernel to make a decision on
diff -druN linux-libre-2.6.30-gnu/Documentation/cpu-freq/user-guide.txt linux-libre-2.6.31-gnu/Documentation/cpu-freq/user-guide.txt
--- linux-libre-2.6.30-gnu/Documentation/cpu-freq/user-guide.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/cpu-freq/user-guide.txt	2009-09-09 18:13:59.000000000 -0400
@@ -31,7 +31,6 @@
 
 3. How to change the CPU cpufreq policy and/or speed
 3.1 Preferred interface: sysfs
-3.2 Deprecated interfaces
 
 
 
diff -druN linux-libre-2.6.30-gnu/Documentation/dell_rbu.txt linux-libre-2.6.31-gnu/Documentation/dell_rbu.txt
--- linux-libre-2.6.30-gnu/Documentation/dell_rbu.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/dell_rbu.txt	2009-09-09 18:13:59.000000000 -0400
@@ -76,9 +76,9 @@
 
 The /sys/class/firmware/dell_rbu/ entries will remain till the following is
 done.
-echo -1 > /sys/class/firmware/dell_rbu/loading.
+echo -1 > /sys/class/firmware/dell_rbu/loading
 Until this step is completed the driver cannot be unloaded.
-Also echoing either mono ,packet or init in to image_type will free up the
+Also echoing either mono, packet or init in to image_type will free up the
 memory allocated by the driver.
 
 If a user by accident executes steps 1 and 3 above without executing step 2;
diff -druN linux-libre-2.6.30-gnu/Documentation/development-process/5.Posting linux-libre-2.6.31-gnu/Documentation/development-process/5.Posting
--- linux-libre-2.6.30-gnu/Documentation/development-process/5.Posting	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/development-process/5.Posting	2009-09-09 18:13:59.000000000 -0400
@@ -119,7 +119,7 @@
 done.  When done properly, though, it is time well spent.
 
 
-5.4: PATCH FORMATTING
+5.4: PATCH FORMATTING AND CHANGELOGS
 
 So now you have a perfect series of patches for posting, but the work is
 not done quite yet.  Each patch needs to be formatted into a message which
@@ -146,8 +146,33 @@
  - One or more tag lines, with, at a minimum, one Signed-off-by: line from
    the author of the patch.  Tags will be described in more detail below.
 
-The above three items should, normally, be the text used when committing
-the change to a revision control system.  They are followed by:
+The items above, together, form the changelog for the patch.  Writing good
+changelogs is a crucial but often-neglected art; it's worth spending
+another moment discussing this issue.  When writing a changelog, you should
+bear in mind that a number of different people will be reading your words.
+These include subsystem maintainers and reviewers who need to decide
+whether the patch should be included, distributors and other maintainers
+trying to decide whether a patch should be backported to other kernels, bug
+hunters wondering whether the patch is responsible for a problem they are
+chasing, users who want to know how the kernel has changed, and more.  A
+good changelog conveys the needed information to all of these people in the
+most direct and concise way possible.
+
+To that end, the summary line should describe the effects of and motivation
+for the change as well as possible given the one-line constraint.  The
+detailed description can then amplify on those topics and provide any
+needed additional information.  If the patch fixes a bug, cite the commit
+which introduced the bug if possible.  If a problem is associated with
+specific log or compiler output, include that output to help others
+searching for a solution to the same problem.  If the change is meant to
+support other changes coming in later patch, say so.  If internal APIs are
+changed, detail those changes and how other developers should respond.  In
+general, the more you can put yourself into the shoes of everybody who will
+be reading your changelog, the better that changelog (and the kernel as a
+whole) will be.
+
+Needless to say, the changelog should be the text used when committing the
+change to a revision control system.  It will be followed by:
 
  - The patch itself, in the unified ("-u") patch format.  Using the "-p"
    option to diff will associate function names with changes, making the
diff -druN linux-libre-2.6.30-gnu/Documentation/device-mapper/dm-log.txt linux-libre-2.6.31-gnu/Documentation/device-mapper/dm-log.txt
--- linux-libre-2.6.30-gnu/Documentation/device-mapper/dm-log.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/device-mapper/dm-log.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,54 @@
+Device-Mapper Logging
+=====================
+The device-mapper logging code is used by some of the device-mapper
+RAID targets to track regions of the disk that are not consistent.
+A region (or portion of the address space) of the disk may be
+inconsistent because a RAID stripe is currently being operated on or
+a machine died while the region was being altered.  In the case of
+mirrors, a region would be considered dirty/inconsistent while you
+are writing to it because the writes need to be replicated for all
+the legs of the mirror and may not reach the legs at the same time.
+Once all writes are complete, the region is considered clean again.
+
+There is a generic logging interface that the device-mapper RAID
+implementations use to perform logging operations (see
+dm_dirty_log_type in include/linux/dm-dirty-log.h).  Various different
+logging implementations are available and provide different
+capabilities.  The list includes:
+
+Type		Files
+====		=====
+disk		drivers/md/dm-log.c
+core		drivers/md/dm-log.c
+userspace	drivers/md/dm-log-userspace* include/linux/dm-log-userspace.h
+
+The "disk" log type
+-------------------
+This log implementation commits the log state to disk.  This way, the
+logging state survives reboots/crashes.
+
+The "core" log type
+-------------------
+This log implementation keeps the log state in memory.  The log state
+will not survive a reboot or crash, but there may be a small boost in
+performance.  This method can also be used if no storage device is
+available for storing log state.
+
+The "userspace" log type
+------------------------
+This log type simply provides a way to export the log API to userspace,
+so log implementations can be done there.  This is done by forwarding most
+logging requests to userspace, where a daemon receives and processes the
+request.
+
+The structure used for communication between kernel and userspace are
+located in include/linux/dm-log-userspace.h.  Due to the frequency,
+diversity, and 2-way communication nature of the exchanges between
+kernel and userspace, 'connector' is used as the interface for
+communication.
+
+There are currently two userspace log implementations that leverage this
+framework - "clustered_disk" and "clustered_core".  These implementations
+provide a cluster-coherent log for shared-storage.  Device-mapper mirroring
+can be used in a shared-storage environment when the cluster log implementations
+are employed.
diff -druN linux-libre-2.6.30-gnu/Documentation/device-mapper/dm-queue-length.txt linux-libre-2.6.31-gnu/Documentation/device-mapper/dm-queue-length.txt
--- linux-libre-2.6.30-gnu/Documentation/device-mapper/dm-queue-length.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/device-mapper/dm-queue-length.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,39 @@
+dm-queue-length
+===============
+
+dm-queue-length is a path selector module for device-mapper targets,
+which selects a path with the least number of in-flight I/Os.
+The path selector name is 'queue-length'.
+
+Table parameters for each path: [<repeat_count>]
+	<repeat_count>: The number of I/Os to dispatch using the selected
+			path before switching to the next path.
+			If not given, internal default is used. To check
+			the default value, see the activated table.
+
+Status for each path: <status> <fail-count> <in-flight>
+	<status>: 'A' if the path is active, 'F' if the path is failed.
+	<fail-count>: The number of path failures.
+	<in-flight>: The number of in-flight I/Os on the path.
+
+
+Algorithm
+=========
+
+dm-queue-length increments/decrements 'in-flight' when an I/O is
+dispatched/completed respectively.
+dm-queue-length selects a path with the minimum 'in-flight'.
+
+
+Examples
+========
+In case that 2 paths (sda and sdb) are used with repeat_count == 128.
+
+# echo "0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128" \
+  dmsetup create test
+#
+# dmsetup table
+test: 0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128
+#
+# dmsetup status
+test: 0 10 multipath 2 0 0 0 1 1 E 0 2 1 8:0 A 0 0 8:16 A 0 0
diff -druN linux-libre-2.6.30-gnu/Documentation/device-mapper/dm-service-time.txt linux-libre-2.6.31-gnu/Documentation/device-mapper/dm-service-time.txt
--- linux-libre-2.6.30-gnu/Documentation/device-mapper/dm-service-time.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/device-mapper/dm-service-time.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,91 @@
+dm-service-time
+===============
+
+dm-service-time is a path selector module for device-mapper targets,
+which selects a path with the shortest estimated service time for
+the incoming I/O.
+
+The service time for each path is estimated by dividing the total size
+of in-flight I/Os on a path with the performance value of the path.
+The performance value is a relative throughput value among all paths
+in a path-group, and it can be specified as a table argument.
+
+The path selector name is 'service-time'.
+
+Table parameters for each path: [<repeat_count> [<relative_throughput>]]
+	<repeat_count>: The number of I/Os to dispatch using the selected
+			path before switching to the next path.
+			If not given, internal default is used.  To check
+			the default value, see the activated table.
+	<relative_throughput>: The relative throughput value of the path
+			among all paths in the path-group.
+			The valid range is 0-100.
+			If not given, minimum value '1' is used.
+			If '0' is given, the path isn't selected while
+			other paths having a positive value are available.
+
+Status for each path: <status> <fail-count> <in-flight-size> \
+		      <relative_throughput>
+	<status>: 'A' if the path is active, 'F' if the path is failed.
+	<fail-count>: The number of path failures.
+	<in-flight-size>: The size of in-flight I/Os on the path.
+	<relative_throughput>: The relative throughput value of the path
+			among all paths in the path-group.
+
+
+Algorithm
+=========
+
+dm-service-time adds the I/O size to 'in-flight-size' when the I/O is
+dispatched and substracts when completed.
+Basically, dm-service-time selects a path having minimum service time
+which is calculated by:
+
+	('in-flight-size' + 'size-of-incoming-io') / 'relative_throughput'
+
+However, some optimizations below are used to reduce the calculation
+as much as possible.
+
+	1. If the paths have the same 'relative_throughput', skip
+	   the division and just compare the 'in-flight-size'.
+
+	2. If the paths have the same 'in-flight-size', skip the division
+	   and just compare the 'relative_throughput'.
+
+	3. If some paths have non-zero 'relative_throughput' and others
+	   have zero 'relative_throughput', ignore those paths with zero
+	   'relative_throughput'.
+
+If such optimizations can't be applied, calculate service time, and
+compare service time.
+If calculated service time is equal, the path having maximum
+'relative_throughput' may be better.  So compare 'relative_throughput'
+then.
+
+
+Examples
+========
+In case that 2 paths (sda and sdb) are used with repeat_count == 128
+and sda has an average throughput 1GB/s and sdb has 4GB/s,
+'relative_throughput' value may be '1' for sda and '4' for sdb.
+
+# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4" \
+  dmsetup create test
+#
+# dmsetup table
+test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4
+#
+# dmsetup status
+test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 1 8:16 A 0 0 4
+
+
+Or '2' for sda and '8' for sdb would be also true.
+
+# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8" \
+  dmsetup create test
+#
+# dmsetup table
+test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8
+#
+# dmsetup status
+test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 2 8:16 A 0 0 8
diff -druN linux-libre-2.6.30-gnu/Documentation/DMA-API.txt linux-libre-2.6.31-gnu/Documentation/DMA-API.txt
--- linux-libre-2.6.30-gnu/Documentation/DMA-API.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/DMA-API.txt	2009-09-09 18:13:59.000000000 -0400
@@ -676,8 +676,8 @@
 	dma-api/all_errors	This file contains a numeric value. If this
 				value is not equal to zero the debugging code
 				will print a warning for every error it finds
-				into the kernel log. Be carefull with this
-				option. It can easily flood your logs.
+				into the kernel log. Be careful with this
+				option, as it can easily flood your logs.
 
 	dma-api/disabled	This read-only file contains the character 'Y'
 				if the debugging code is disabled. This can
@@ -704,12 +704,24 @@
 				The current number of free dma_debug_entries
 				in the allocator.
 
+	dma-api/driver-filter
+				You can write a name of a driver into this file
+				to limit the debug output to requests from that
+				particular driver. Write an empty string to
+				that file to disable the filter and see
+				all errors again.
+
 If you have this code compiled into your kernel it will be enabled by default.
 If you want to boot without the bookkeeping anyway you can provide
 'dma_debug=off' as a boot parameter. This will disable DMA-API debugging.
 Notice that you can not enable it again at runtime. You have to reboot to do
 so.
 
+If you want to see debug messages only for a special device driver you can
+specify the dma_debug_driver=<drivername> parameter. This will enable the
+driver filter at boot time. The debug code will only print errors for that
+driver afterwards. This filter can be disabled or changed later using debugfs.
+
 When the code disables itself at runtime this is most likely because it ran
 out of dma_debug_entries. These entries are preallocated at boot. The number
 of preallocated entries is defined per architecture. If it is too low for you
diff -druN linux-libre-2.6.30-gnu/Documentation/DocBook/debugobjects.tmpl linux-libre-2.6.31-gnu/Documentation/DocBook/debugobjects.tmpl
--- linux-libre-2.6.30-gnu/Documentation/DocBook/debugobjects.tmpl	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/DocBook/debugobjects.tmpl	2009-09-09 18:13:59.000000000 -0400
@@ -106,7 +106,7 @@
       number of errors are printk'ed including a full stack trace.
     </para>
     <para>
-      The statistics are available via debugfs/debug_objects/stats.
+      The statistics are available via /sys/kernel/debug/debug_objects/stats.
       They provide information about the number of warnings and the
       number of successful fixups along with information about the
       usage of the internal tracking objects and the state of the
diff -druN linux-libre-2.6.30-gnu/Documentation/DocBook/kernel-hacking.tmpl linux-libre-2.6.31-gnu/Documentation/DocBook/kernel-hacking.tmpl
--- linux-libre-2.6.30-gnu/Documentation/DocBook/kernel-hacking.tmpl	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/DocBook/kernel-hacking.tmpl	2009-09-09 18:13:59.000000000 -0400
@@ -449,8 +449,8 @@
    </para>
 
    <programlisting>
-__u32 ipaddress;
-printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
+__be32 ipaddress;
+printk(KERN_INFO "my ip: %pI4\n", &amp;ipaddress);
    </programlisting>
 
    <para>
diff -druN linux-libre-2.6.30-gnu/Documentation/DocBook/mac80211.tmpl linux-libre-2.6.31-gnu/Documentation/DocBook/mac80211.tmpl
--- linux-libre-2.6.30-gnu/Documentation/DocBook/mac80211.tmpl	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/DocBook/mac80211.tmpl	2009-09-09 18:13:59.000000000 -0400
@@ -145,7 +145,6 @@
         interface in STA mode at first!
       </para>
 !Finclude/net/mac80211.h ieee80211_if_init_conf
-!Finclude/net/mac80211.h ieee80211_if_conf
     </chapter>
 
     <chapter id="rx-tx">
@@ -185,8 +184,6 @@
 !Finclude/net/mac80211.h ieee80211_ctstoself_get
 !Finclude/net/mac80211.h ieee80211_ctstoself_duration
 !Finclude/net/mac80211.h ieee80211_generic_frame_duration
-!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb
-!Finclude/net/mac80211.h ieee80211_hdrlen
 !Finclude/net/mac80211.h ieee80211_wake_queue
 !Finclude/net/mac80211.h ieee80211_stop_queue
 !Finclude/net/mac80211.h ieee80211_wake_queues
diff -druN linux-libre-2.6.30-gnu/Documentation/DocBook/Makefile linux-libre-2.6.31-gnu/Documentation/DocBook/Makefile
--- linux-libre-2.6.30-gnu/Documentation/DocBook/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/DocBook/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,8 @@
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
 	    mac80211.xml debugobjects.xml sh.xml regulator.xml \
-	    alsa-driver-api.xml writing-an-alsa-driver.xml
+	    alsa-driver-api.xml writing-an-alsa-driver.xml \
+	    tracepoint.xml
 
 ###
 # The build process is as follows (targets):
diff -druN linux-libre-2.6.30-gnu/Documentation/DocBook/tracepoint.tmpl linux-libre-2.6.31-gnu/Documentation/DocBook/tracepoint.tmpl
--- linux-libre-2.6.30-gnu/Documentation/DocBook/tracepoint.tmpl	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/DocBook/tracepoint.tmpl	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="Tracepoints">
+ <bookinfo>
+  <title>The Linux Kernel Tracepoint API</title>
+
+  <authorgroup>
+   <author>
+    <firstname>Jason</firstname>
+    <surname>Baron</surname>
+    <affiliation>
+     <address>
+      <email>jbaron@redhat.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <legalnotice>
+   <para>
+     This documentation 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.
+   </para>
+
+   <para>
+     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.
+   </para>
+
+   <para>
+     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
+   </para>
+
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+ <toc></toc>
+  <chapter id="intro">
+   <title>Introduction</title>
+   <para>
+     Tracepoints are static probe points that are located in strategic points
+     throughout the kernel. 'Probes' register/unregister with tracepoints
+     via a callback mechanism. The 'probes' are strictly typed functions that
+     are passed a unique set of parameters defined by each tracepoint.
+   </para>
+
+   <para>
+     From this simple callback mechanism, 'probes' can be used to profile, debug,
+     and understand kernel behavior. There are a number of tools that provide a
+     framework for using 'probes'. These tools include Systemtap, ftrace, and
+     LTTng.
+   </para>
+
+   <para>
+     Tracepoints are defined in a number of header files via various macros. Thus,
+     the purpose of this document is to provide a clear accounting of the available
+     tracepoints. The intention is to understand not only what tracepoints are
+     available but also to understand where future tracepoints might be added.
+   </para>
+
+   <para>
+     The API presented has functions of the form:
+     <function>trace_tracepointname(function parameters)</function>. These are the
+     tracepoints callbacks that are found throughout the code. Registering and
+     unregistering probes with these callback sites is covered in the
+     <filename>Documentation/trace/*</filename> directory.
+   </para>
+  </chapter>
+
+  <chapter id="irq">
+   <title>IRQ</title>
+!Iinclude/trace/events/irq.h
+  </chapter>
+
+</book>
diff -druN linux-libre-2.6.30-gnu/Documentation/driver-model/device.txt linux-libre-2.6.31-gnu/Documentation/driver-model/device.txt
--- linux-libre-2.6.30-gnu/Documentation/driver-model/device.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/driver-model/device.txt	2009-09-09 18:13:59.000000000 -0400
@@ -162,3 +162,35 @@
 
 The file name will be 'power' with a mode of 0644 (-rw-r--r--).
 
+Word of warning:  While the kernel allows device_create_file() and
+device_remove_file() to be called on a device at any time, userspace has
+strict expectations on when attributes get created.  When a new device is
+registered in the kernel, a uevent is generated to notify userspace (like
+udev) that a new device is available.  If attributes are added after the
+device is registered, then userspace won't get notified and userspace will
+not know about the new attributes.
+
+This is important for device driver that need to publish additional
+attributes for a device at driver probe time.  If the device driver simply
+calls device_create_file() on the device structure passed to it, then
+userspace will never be notified of the new attributes.  Instead, it should
+probably use class_create() and class->dev_attrs to set up a list of
+desired attributes in the modules_init function, and then in the .probe()
+hook, and then use device_create() to create a new device as a child
+of the probed device.  The new device will generate a new uevent and
+properly advertise the new attributes to userspace.
+
+For example, if a driver wanted to add the following attributes:
+struct device_attribute mydriver_attribs[] = {
+	__ATTR(port_count, 0444, port_count_show),
+	__ATTR(serial_number, 0444, serial_number_show),
+	NULL
+};
+
+Then in the module init function is would do:
+	mydriver_class = class_create(THIS_MODULE, "my_attrs");
+	mydriver_class.dev_attr = mydriver_attribs;
+
+And assuming 'dev' is the struct device passed into the probe hook, the driver
+probe function would do something like:
+	create_device(&mydriver_class, dev, chrdev, &private_data, "my_name");
diff -druN linux-libre-2.6.30-gnu/Documentation/driver-model/devres.txt linux-libre-2.6.31-gnu/Documentation/driver-model/devres.txt
--- linux-libre-2.6.30-gnu/Documentation/driver-model/devres.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/driver-model/devres.txt	2009-09-09 18:13:59.000000000 -0400
@@ -188,7 +188,7 @@
 
   void my_midlayer_destroy_something()
   {
-	devres_release_group(dev, my_midlayer_create_soemthing);
+	devres_release_group(dev, my_midlayer_create_something);
   }
 
 
diff -druN linux-libre-2.6.30-gnu/Documentation/driver-model/driver.txt linux-libre-2.6.31-gnu/Documentation/driver-model/driver.txt
--- linux-libre-2.6.30-gnu/Documentation/driver-model/driver.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/driver-model/driver.txt	2009-09-09 18:13:59.000000000 -0400
@@ -207,8 +207,8 @@
 ~~~~~~~~~~
 struct driver_attribute {
         struct attribute        attr;
-        ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
-        ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
+        ssize_t (*show)(struct device_driver *driver, char *buf);
+        ssize_t (*store)(struct device_driver *, const char * buf, size_t count);
 };
 
 Device drivers can export attributes via their sysfs directories. 
diff -druN linux-libre-2.6.30-gnu/Documentation/edac.txt linux-libre-2.6.31-gnu/Documentation/edac.txt
--- linux-libre-2.6.30-gnu/Documentation/edac.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/edac.txt	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,8 @@
 The bluesmoke project at sourceforge.net is now utilized as a 'staging area'
 for EDAC development, before it is sent upstream to kernel.org
 
-At the bluesmoke/EDAC project site, is a series of quilt patches against
-recent kernels, stored in a SVN respository. For easier downloading, there
+At the bluesmoke/EDAC project site is a series of quilt patches against
+recent kernels, stored in a SVN repository. For easier downloading, there
 is also a tarball snapshot available.
 
 ============================================================================
@@ -73,9 +73,9 @@
 to generate parity.  Some vendors do not do this, and thus the parity bit
 can "float" giving false positives.
 
-In the kernel there is a pci device attribute located in sysfs that is
+In the kernel there is a PCI device attribute located in sysfs that is
 checked by the EDAC PCI scanning code. If that attribute is set,
-PCI parity/error scannining is skipped for that device. The attribute
+PCI parity/error scanning is skipped for that device. The attribute
 is:
 
 	broken_parity_status
diff -druN linux-libre-2.6.30-gnu/Documentation/exception.txt linux-libre-2.6.31-gnu/Documentation/exception.txt
--- linux-libre-2.6.30-gnu/Documentation/exception.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/exception.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,292 +0,0 @@
-     Kernel level exception handling in Linux 2.1.8
-  Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com>
-
-When a process runs in kernel mode, it often has to access user 
-mode memory whose address has been passed by an untrusted program. 
-To protect itself the kernel has to verify this address.
-
-In older versions of Linux this was done with the 
-int verify_area(int type, const void * addr, unsigned long size) 
-function (which has since been replaced by access_ok()).
-
-This function verified that the memory area starting at address 
-'addr' and of size 'size' was accessible for the operation specified
-in type (read or write). To do this, verify_read had to look up the 
-virtual memory area (vma) that contained the address addr. In the 
-normal case (correctly working program), this test was successful. 
-It only failed for a few buggy programs. In some kernel profiling
-tests, this normally unneeded verification used up a considerable
-amount of time.
-
-To overcome this situation, Linus decided to let the virtual memory 
-hardware present in every Linux-capable CPU handle this test.
-
-How does this work?
-
-Whenever the kernel tries to access an address that is currently not 
-accessible, the CPU generates a page fault exception and calls the 
-page fault handler 
-
-void do_page_fault(struct pt_regs *regs, unsigned long error_code)
-
-in arch/i386/mm/fault.c. The parameters on the stack are set up by 
-the low level assembly glue in arch/i386/kernel/entry.S. The parameter
-regs is a pointer to the saved registers on the stack, error_code 
-contains a reason code for the exception.
-
-do_page_fault first obtains the unaccessible address from the CPU 
-control register CR2. If the address is within the virtual address 
-space of the process, the fault probably occurred, because the page 
-was not swapped in, write protected or something similar. However, 
-we are interested in the other case: the address is not valid, there 
-is no vma that contains this address. In this case, the kernel jumps 
-to the bad_area label. 
-
-There it uses the address of the instruction that caused the exception 
-(i.e. regs->eip) to find an address where the execution can continue 
-(fixup). If this search is successful, the fault handler modifies the 
-return address (again regs->eip) and returns. The execution will 
-continue at the address in fixup.
-
-Where does fixup point to?
-
-Since we jump to the contents of fixup, fixup obviously points 
-to executable code. This code is hidden inside the user access macros. 
-I have picked the get_user macro defined in include/asm/uaccess.h as an
-example. The definition is somewhat hard to follow, so let's peek at 
-the code generated by the preprocessor and the compiler. I selected
-the get_user call in drivers/char/console.c for a detailed examination.
-
-The original code in console.c line 1405:
-        get_user(c, buf);
-
-The preprocessor output (edited to become somewhat readable):
-
-(
-  {        
-    long __gu_err = - 14 , __gu_val = 0;        
-    const __typeof__(*( (  buf ) )) *__gu_addr = ((buf));        
-    if (((((0 + current_set[0])->tss.segment) == 0x18 )  || 
-       (((sizeof(*(buf))) <= 0xC0000000UL) && 
-       ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))        
-      do {
-        __gu_err  = 0;        
-        switch ((sizeof(*(buf)))) {        
-          case 1: 
-            __asm__ __volatile__(        
-              "1:      mov" "b" " %2,%" "b" "1\n"        
-              "2:\n"        
-              ".section .fixup,\"ax\"\n"        
-              "3:      movl %3,%0\n"        
-              "        xor" "b" " %" "b" "1,%" "b" "1\n"        
-              "        jmp 2b\n"        
-              ".section __ex_table,\"a\"\n"        
-              "        .align 4\n"        
-              "        .long 1b,3b\n"        
-              ".text"        : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
-                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ; 
-              break;        
-          case 2: 
-            __asm__ __volatile__(
-              "1:      mov" "w" " %2,%" "w" "1\n"        
-              "2:\n"        
-              ".section .fixup,\"ax\"\n"        
-              "3:      movl %3,%0\n"        
-              "        xor" "w" " %" "w" "1,%" "w" "1\n"        
-              "        jmp 2b\n"        
-              ".section __ex_table,\"a\"\n"        
-              "        .align 4\n"        
-              "        .long 1b,3b\n"        
-              ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
-                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )); 
-              break;        
-          case 4: 
-            __asm__ __volatile__(        
-              "1:      mov" "l" " %2,%" "" "1\n"        
-              "2:\n"        
-              ".section .fixup,\"ax\"\n"        
-              "3:      movl %3,%0\n"        
-              "        xor" "l" " %" "" "1,%" "" "1\n"        
-              "        jmp 2b\n"        
-              ".section __ex_table,\"a\"\n"        
-              "        .align 4\n"        "        .long 1b,3b\n"        
-              ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
-                            (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err)); 
-              break;        
-          default: 
-            (__gu_val) = __get_user_bad();        
-        }        
-      } while (0) ;        
-    ((c)) = (__typeof__(*((buf))))__gu_val;        
-    __gu_err;
-  }
-);
-
-WOW! Black GCC/assembly magic. This is impossible to follow, so let's
-see what code gcc generates:
-
- >         xorl %edx,%edx
- >         movl current_set,%eax
- >         cmpl $24,788(%eax)        
- >         je .L1424        
- >         cmpl $-1073741825,64(%esp)
- >         ja .L1423                
- > .L1424:
- >         movl %edx,%eax                        
- >         movl 64(%esp),%ebx
- > #APP
- > 1:      movb (%ebx),%dl                /* this is the actual user access */
- > 2:
- > .section .fixup,"ax"
- > 3:      movl $-14,%eax
- >         xorb %dl,%dl
- >         jmp 2b
- > .section __ex_table,"a"
- >         .align 4
- >         .long 1b,3b
- > .text
- > #NO_APP
- > .L1423:
- >         movzbl %dl,%esi
-
-The optimizer does a good job and gives us something we can actually 
-understand. Can we? The actual user access is quite obvious. Thanks 
-to the unified address space we can just access the address in user 
-memory. But what does the .section stuff do?????
-
-To understand this we have to look at the final kernel:
-
- > objdump --section-headers vmlinux
- > 
- > vmlinux:     file format elf32-i386
- > 
- > Sections:
- > Idx Name          Size      VMA       LMA       File off  Algn
- >   0 .text         00098f40  c0100000  c0100000  00001000  2**4
- >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
- >   1 .fixup        000016bc  c0198f40  c0198f40  00099f40  2**0
- >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
- >   2 .rodata       0000f127  c019a5fc  c019a5fc  0009b5fc  2**2
- >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
- >   3 __ex_table    000015c0  c01a9724  c01a9724  000aa724  2**2
- >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
- >   4 .data         0000ea58  c01abcf0  c01abcf0  000abcf0  2**4
- >                   CONTENTS, ALLOC, LOAD, DATA
- >   5 .bss          00018e21  c01ba748  c01ba748  000ba748  2**2
- >                   ALLOC
- >   6 .comment      00000ec4  00000000  00000000  000ba748  2**0
- >                   CONTENTS, READONLY
- >   7 .note         00001068  00000ec4  00000ec4  000bb60c  2**0
- >                   CONTENTS, READONLY
-
-There are obviously 2 non standard ELF sections in the generated object
-file. But first we want to find out what happened to our code in the
-final kernel executable:
-
- > objdump --disassemble --section=.text vmlinux
- >
- > c017e785 <do_con_write+c1> xorl   %edx,%edx
- > c017e787 <do_con_write+c3> movl   0xc01c7bec,%eax
- > c017e78c <do_con_write+c8> cmpl   $0x18,0x314(%eax)
- > c017e793 <do_con_write+cf> je     c017e79f <do_con_write+db>
- > c017e795 <do_con_write+d1> cmpl   $0xbfffffff,0x40(%esp,1)
- > c017e79d <do_con_write+d9> ja     c017e7a7 <do_con_write+e3>
- > c017e79f <do_con_write+db> movl   %edx,%eax
- > c017e7a1 <do_con_write+dd> movl   0x40(%esp,1),%ebx
- > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
- > c017e7a7 <do_con_write+e3> movzbl %dl,%esi
-
-The whole user memory access is reduced to 10 x86 machine instructions.
-The instructions bracketed in the .section directives are no longer
-in the normal execution path. They are located in a different section 
-of the executable file:
-
- > objdump --disassemble --section=.fixup vmlinux
- > 
- > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
- > c0199ffa <.fixup+10ba> xorb   %dl,%dl
- > c0199ffc <.fixup+10bc> jmp    c017e7a7 <do_con_write+e3>
-
-And finally:
- > objdump --full-contents --section=__ex_table vmlinux
- > 
- >  c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0  ................
- >  c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0  ................
- >  c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0  ................
-
-or in human readable byte order:
-
- >  c01aa7c4 c017c093 c0199fe0 c017c097 c017c099  ................
- >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
-                               ^^^^^^^^^^^^^^^^^
-                               this is the interesting part!
- >  c01aa7e4 c0180a08 c019a001 c0180a0a c019a004  ................
-
-What happened? The assembly directives
-
-.section .fixup,"ax"
-.section __ex_table,"a"
-
-told the assembler to move the following code to the specified
-sections in the ELF object file. So the instructions
-3:      movl $-14,%eax
-        xorb %dl,%dl
-        jmp 2b
-ended up in the .fixup section of the object file and the addresses
-        .long 1b,3b
-ended up in the __ex_table section of the object file. 1b and 3b
-are local labels. The local label 1b (1b stands for next label 1 
-backward) is the address of the instruction that might fault, i.e. 
-in our case the address of the label 1 is c017e7a5:
-the original assembly code: > 1:      movb (%ebx),%dl
-and linked in vmlinux     : > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
-
-The local label 3 (backwards again) is the address of the code to handle
-the fault, in our case the actual value is c0199ff5:
-the original assembly code: > 3:      movl $-14,%eax
-and linked in vmlinux     : > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
-
-The assembly code
- > .section __ex_table,"a"
- >         .align 4
- >         .long 1b,3b
-
-becomes the value pair
- >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
-                               ^this is ^this is
-                               1b       3b 
-c017e7a5,c0199ff5 in the exception table of the kernel.
-
-So, what actually happens if a fault from kernel mode with no suitable
-vma occurs?
-
-1.) access to invalid address:
- > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
-2.) MMU generates exception
-3.) CPU calls do_page_fault
-4.) do page fault calls search_exception_table (regs->eip == c017e7a5);
-5.) search_exception_table looks up the address c017e7a5 in the
-    exception table (i.e. the contents of the ELF section __ex_table) 
-    and returns the address of the associated fault handle code c0199ff5.
-6.) do_page_fault modifies its own return address to point to the fault 
-    handle code and returns.
-7.) execution continues in the fault handling code.
-8.) 8a) EAX becomes -EFAULT (== -14)
-    8b) DL  becomes zero (the value we "read" from user space)
-    8c) execution continues at local label 2 (address of the
-        instruction immediately after the faulting user access).
-
-The steps 8a to 8c in a certain way emulate the faulting instruction.
-
-That's it, mostly. If you look at our example, you might ask why
-we set EAX to -EFAULT in the exception handler code. Well, the
-get_user macro actually returns a value: 0, if the user access was
-successful, -EFAULT on failure. Our original code did not test this
-return value, however the inline assembly code in get_user tries to
-return -EFAULT. GCC selected EAX to return this value.
-
-NOTE:
-Due to the way that the exception table is built and needs to be ordered,
-only use exceptions for code in the .text section.  Any other section
-will cause the exception table to not be sorted correctly, and the
-exceptions will fail.
diff -druN linux-libre-2.6.30-gnu/Documentation/fault-injection/fault-injection.txt linux-libre-2.6.31-gnu/Documentation/fault-injection/fault-injection.txt
--- linux-libre-2.6.30-gnu/Documentation/fault-injection/fault-injection.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/fault-injection/fault-injection.txt	2009-09-09 18:13:59.000000000 -0400
@@ -29,16 +29,16 @@
 fault-inject-debugfs kernel module provides some debugfs entries for runtime
 configuration of fault-injection capabilities.
 
-- /debug/fail*/probability:
+- /sys/kernel/debug/fail*/probability:
 
 	likelihood of failure injection, in percent.
 	Format: <percent>
 
 	Note that one-failure-per-hundred is a very high error rate
 	for some testcases.  Consider setting probability=100 and configure
-	/debug/fail*/interval for such testcases.
+	/sys/kernel/debug/fail*/interval for such testcases.
 
-- /debug/fail*/interval:
+- /sys/kernel/debug/fail*/interval:
 
 	specifies the interval between failures, for calls to
 	should_fail() that pass all the other tests.
@@ -46,18 +46,18 @@
 	Note that if you enable this, by setting interval>1, you will
 	probably want to set probability=100.
 
-- /debug/fail*/times:
+- /sys/kernel/debug/fail*/times:
 
 	specifies how many times failures may happen at most.
 	A value of -1 means "no limit".
 
-- /debug/fail*/space:
+- /sys/kernel/debug/fail*/space:
 
 	specifies an initial resource "budget", decremented by "size"
 	on each call to should_fail(,size).  Failure injection is
 	suppressed until "space" reaches zero.
 
-- /debug/fail*/verbose
+- /sys/kernel/debug/fail*/verbose
 
 	Format: { 0 | 1 | 2 }
 	specifies the verbosity of the messages when failure is
@@ -65,17 +65,17 @@
 	log line per failure; '2' will print a call trace too -- useful
 	to debug the problems revealed by fault injection.
 
-- /debug/fail*/task-filter:
+- /sys/kernel/debug/fail*/task-filter:
 
 	Format: { 'Y' | 'N' }
 	A value of 'N' disables filtering by process (default).
 	Any positive value limits failures to only processes indicated by
 	/proc/<pid>/make-it-fail==1.
 
-- /debug/fail*/require-start:
-- /debug/fail*/require-end:
-- /debug/fail*/reject-start:
-- /debug/fail*/reject-end:
+- /sys/kernel/debug/fail*/require-start:
+- /sys/kernel/debug/fail*/require-end:
+- /sys/kernel/debug/fail*/reject-start:
+- /sys/kernel/debug/fail*/reject-end:
 
 	specifies the range of virtual addresses tested during
 	stacktrace walking.  Failure is injected only if some caller
@@ -84,26 +84,26 @@
 	Default required range is [0,ULONG_MAX) (whole of virtual address space).
 	Default rejected range is [0,0).
 
-- /debug/fail*/stacktrace-depth:
+- /sys/kernel/debug/fail*/stacktrace-depth:
 
 	specifies the maximum stacktrace depth walked during search
 	for a caller within [require-start,require-end) OR
 	[reject-start,reject-end).
 
-- /debug/fail_page_alloc/ignore-gfp-highmem:
+- /sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem:
 
 	Format: { 'Y' | 'N' }
 	default is 'N', setting it to 'Y' won't inject failures into
 	highmem/user allocations.
 
-- /debug/failslab/ignore-gfp-wait:
-- /debug/fail_page_alloc/ignore-gfp-wait:
+- /sys/kernel/debug/failslab/ignore-gfp-wait:
+- /sys/kernel/debug/fail_page_alloc/ignore-gfp-wait:
 
 	Format: { 'Y' | 'N' }
 	default is 'N', setting it to 'Y' will inject failures
 	only into non-sleep allocations (GFP_ATOMIC allocations).
 
-- /debug/fail_page_alloc/min-order:
+- /sys/kernel/debug/fail_page_alloc/min-order:
 
 	specifies the minimum page allocation order to be injected
 	failures.
@@ -166,13 +166,13 @@
 #!/bin/bash
 
 FAILTYPE=failslab
-echo Y > /debug/$FAILTYPE/task-filter
-echo 10 > /debug/$FAILTYPE/probability
-echo 100 > /debug/$FAILTYPE/interval
-echo -1 > /debug/$FAILTYPE/times
-echo 0 > /debug/$FAILTYPE/space
-echo 2 > /debug/$FAILTYPE/verbose
-echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
+echo Y > /sys/kernel/debug/$FAILTYPE/task-filter
+echo 10 > /sys/kernel/debug/$FAILTYPE/probability
+echo 100 > /sys/kernel/debug/$FAILTYPE/interval
+echo -1 > /sys/kernel/debug/$FAILTYPE/times
+echo 0 > /sys/kernel/debug/$FAILTYPE/space
+echo 2 > /sys/kernel/debug/$FAILTYPE/verbose
+echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait
 
 faulty_system()
 {
@@ -217,20 +217,20 @@
 	exit 1
 fi
 
-cat /sys/module/$module/sections/.text > /debug/$FAILTYPE/require-start
-cat /sys/module/$module/sections/.data > /debug/$FAILTYPE/require-end
+cat /sys/module/$module/sections/.text > /sys/kernel/debug/$FAILTYPE/require-start
+cat /sys/module/$module/sections/.data > /sys/kernel/debug/$FAILTYPE/require-end
 
-echo N > /debug/$FAILTYPE/task-filter
-echo 10 > /debug/$FAILTYPE/probability
-echo 100 > /debug/$FAILTYPE/interval
-echo -1 > /debug/$FAILTYPE/times
-echo 0 > /debug/$FAILTYPE/space
-echo 2 > /debug/$FAILTYPE/verbose
-echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
-echo 1 > /debug/$FAILTYPE/ignore-gfp-highmem
-echo 10 > /debug/$FAILTYPE/stacktrace-depth
+echo N > /sys/kernel/debug/$FAILTYPE/task-filter
+echo 10 > /sys/kernel/debug/$FAILTYPE/probability
+echo 100 > /sys/kernel/debug/$FAILTYPE/interval
+echo -1 > /sys/kernel/debug/$FAILTYPE/times
+echo 0 > /sys/kernel/debug/$FAILTYPE/space
+echo 2 > /sys/kernel/debug/$FAILTYPE/verbose
+echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait
+echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-highmem
+echo 10 > /sys/kernel/debug/$FAILTYPE/stacktrace-depth
 
-trap "echo 0 > /debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
+trap "echo 0 > /sys/kernel/debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
 
 echo "Injecting errors into the module $module... (interrupt to stop)"
 sleep 1000000
diff -druN linux-libre-2.6.30-gnu/Documentation/fb/sh7760fb.txt linux-libre-2.6.31-gnu/Documentation/fb/sh7760fb.txt
--- linux-libre-2.6.30-gnu/Documentation/fb/sh7760fb.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/fb/sh7760fb.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 SH7760/SH7763 integrated LCDC Framebuffer driver
 ================================================
 
-0. Overwiew
+0. Overview
 -----------
 The SH7760/SH7763 have an integrated LCD Display controller (LCDC) which
 supports (in theory) resolutions ranging from 1x1 to 1024x1024,
diff -druN linux-libre-2.6.30-gnu/Documentation/fb/vesafb.txt linux-libre-2.6.31-gnu/Documentation/fb/vesafb.txt
--- linux-libre-2.6.30-gnu/Documentation/fb/vesafb.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/fb/vesafb.txt	2009-09-09 18:13:59.000000000 -0400
@@ -95,7 +95,7 @@
 booting linux.  If you are not happy with the 60 Hz refresh rate, you
 have these options:
 
- * configure and load the DOS-Tools for your the graphics board (if
+ * configure and load the DOS-Tools for the graphics board (if
    available) and boot linux with loadlin.
  * use a native driver (matroxfb/atyfb) instead if vesafb.  If none
    is available, write a new one!
diff -druN linux-libre-2.6.30-gnu/Documentation/feature-removal-schedule.txt linux-libre-2.6.31-gnu/Documentation/feature-removal-schedule.txt
--- linux-libre-2.6.30-gnu/Documentation/feature-removal-schedule.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/feature-removal-schedule.txt	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,20 @@
 
 ---------------------------
 
+What:	IRQF_SAMPLE_RANDOM
+Check:	IRQF_SAMPLE_RANDOM
+When:	July 2009
+
+Why:	Many of IRQF_SAMPLE_RANDOM users are technically bogus as entropy
+	sources in the kernel's current entropy model. To resolve this, every
+	input point to the kernel's entropy pool needs to better document the
+	type of entropy source it actually is. This will be replaced with
+	additional add_*_randomness functions in drivers/char/random.c
+
+Who:	Robin Getz <rgetz@blackfin.uclinux.org> & Matt Mackall <mpm@selenic.com>
+
+---------------------------
+
 What:	The ieee80211_regdom module parameter
 When:	March 2010 / desktop catchup
 
@@ -354,16 +368,6 @@
 
 ---------------------------
 
-What:	i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client(),
-	i2c_adapter->client_register(), i2c_adapter->client_unregister
-When:	2.6.30
-Check:	i2c_attach_client i2c_detach_client
-Why:	Deprecated by the new (standard) device driver binding model. Use
-	i2c_driver->probe() and ->remove() instead.
-Who:	Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
 What:	fscher and fscpos drivers
 When:	June 2009
 Why:	Deprecated by the new fschmd driver.
@@ -437,3 +441,30 @@
 	driver but this caused driver conflicts.
 Who:	Jean Delvare <khali@linux-fr.org>
 	Krzysztof Helt <krzysztof.h1@wp.pl>
+
+---------------------------
+
+What:	CONFIG_RFKILL_INPUT
+When:	2.6.33
+Why:	Should be implemented in userspace, policy daemon.
+Who:	Johannes Berg <johannes@sipsolutions.net>
+
+----------------------------
+
+What:	CONFIG_X86_OLD_MCE
+When:	2.6.32
+Why:	Remove the old legacy 32bit machine check code. This has been
+	superseded by the newer machine check code from the 64bit port,
+	but the old version has been kept around for easier testing. Note this
+	doesn't impact the old P5 and WinChip machine check handlers.
+Who:	Andi Kleen <andi@firstfloor.org>
+
+----------------------------
+
+What:	lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
+	exported interface anymore.
+When:	2.6.33
+Why:	cpu_policy_rwsem has a new cleaner definition making it local to
+	cpufreq core and contained inside cpufreq.c. Other dependent
+	drivers should not use it in order to safely avoid lockdep issues.
+Who:	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/00-INDEX linux-libre-2.6.31-gnu/Documentation/filesystems/00-INDEX
--- linux-libre-2.6.30-gnu/Documentation/filesystems/00-INDEX	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/00-INDEX	2009-09-09 18:13:59.000000000 -0400
@@ -66,6 +66,10 @@
 	- info on the Linux implementation of Sys V mandatory file locking.
 ncpfs.txt
 	- info on Novell Netware(tm) filesystem using NCP protocol.
+nfs41-server.txt
+	- info on the Linux server implementation of NFSv4 minor version 1.
+nfs-rdma.txt
+	- how to install and setup the Linux NFS/RDMA client and server software.
 nfsroot.txt
 	- short guide on setting up a diskless box with NFS root filesystem.
 nilfs2.txt
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/9p.txt linux-libre-2.6.31-gnu/Documentation/filesystems/9p.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/9p.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/9p.txt	2009-09-09 18:13:59.000000000 -0400
@@ -123,6 +123,9 @@
 There are user and developer mailing lists available through the v9fs project
 on sourceforge (http://sourceforge.net/projects/v9fs).
 
+A stand-alone version of the module (which should build for any 2.6 kernel)
+is available via (http://github.com/ericvh/9p-sac/tree/master)
+
 News and other information is maintained on SWiK (http://swik.net/v9fs).
 
 Bug reports may be issued through the kernel.org bugzilla 
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/afs.txt linux-libre-2.6.31-gnu/Documentation/filesystems/afs.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/afs.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/afs.txt	2009-09-09 18:13:59.000000000 -0400
@@ -23,15 +23,13 @@
 
  (*) Security (currently only AFS kaserver and KerberosIV tickets).
 
- (*) File reading.
+ (*) File reading and writing.
 
  (*) Automounting.
 
-It does not yet support the following AFS features:
-
- (*) Write support.
+ (*) Local caching (via fscache).
 
- (*) Local caching.
+It does not yet support the following AFS features:
 
  (*) pioctl() system call.
 
@@ -56,7 +54,7 @@
 the masks in the following files:
 
 	/sys/module/af_rxrpc/parameters/debug
-	/sys/module/afs/parameters/debug
+	/sys/module/kafs/parameters/debug
 
 
 =====
@@ -66,9 +64,9 @@
 When inserting the driver modules the root cell must be specified along with a
 list of volume location server IP addresses:
 
-	insmod af_rxrpc.o
-	insmod rxkad.o
-	insmod kafs.o rootcell=cambridge.redhat.com:172.16.18.73:172.16.18.91
+	modprobe af_rxrpc
+	modprobe rxkad
+	modprobe kafs rootcell=cambridge.redhat.com:172.16.18.73:172.16.18.91
 
 The first module is the AF_RXRPC network protocol driver.  This provides the
 RxRPC remote operation protocol and may also be accessed from userspace.  See:
@@ -81,7 +79,7 @@
 Once the module has been loaded, more modules can be added by the following
 procedure:
 
-	echo add grand.central.org 18.7.14.88:128.2.191.224 >/proc/fs/afs/cells
+	echo add grand.central.org 18.9.48.14:128.2.203.61:130.237.48.87 >/proc/fs/afs/cells
 
 Where the parameters to the "add" command are the name of a cell and a list of
 volume location servers within that cell, with the latter separated by colons.
@@ -101,7 +99,7 @@
 specify connection to only volumes of those types.
 
 The name of the cell is optional, and if not given during a mount, then the
-named volume will be looked up in the cell specified during insmod.
+named volume will be looked up in the cell specified during modprobe.
 
 Additional cells can be added through /proc (see later section).
 
@@ -163,14 +161,14 @@
 
 The filesystem maintains an internal database of all the cells it knows and the
 IP addresses of the volume location servers for those cells.  The cell to which
-the system belongs is added to the database when insmod is performed by the
+the system belongs is added to the database when modprobe is performed by the
 "rootcell=" argument or, if compiled in, using a "kafs.rootcell=" argument on
 the kernel command line.
 
 Further cells can be added by commands similar to the following:
 
 	echo add CELLNAME VLADDR[:VLADDR][:VLADDR]... >/proc/fs/afs/cells
-	echo add grand.central.org 18.7.14.88:128.2.191.224 >/proc/fs/afs/cells
+	echo add grand.central.org 18.9.48.14:128.2.203.61:130.237.48.87 >/proc/fs/afs/cells
 
 No other cell database operations are available at this time.
 
@@ -233,7 +231,7 @@
 mount -t afs \%root.afs. /afs
 mount -t afs \%cambridge.redhat.com:root.cell. /afs/cambridge.redhat.com/
 
-echo add grand.central.org 18.7.14.88:128.2.191.224 > /proc/fs/afs/cells
+echo add grand.central.org 18.9.48.14:128.2.203.61:130.237.48.87 > /proc/fs/afs/cells
 mount -t afs "#grand.central.org:root.cell." /afs/grand.central.org/
 mount -t afs "#grand.central.org:root.archive." /afs/grand.central.org/archive
 mount -t afs "#grand.central.org:root.contrib." /afs/grand.central.org/contrib
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/autofs4-mount-control.txt linux-libre-2.6.31-gnu/Documentation/filesystems/autofs4-mount-control.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/autofs4-mount-control.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/autofs4-mount-control.txt	2009-09-09 18:13:59.000000000 -0400
@@ -369,7 +369,7 @@
 possible variations. Both use the path field set to the path of the mount
 point to check and the size field adjusted appropriately. One uses the
 ioctlfd field to identify a specific mount point to check while the other
-variation uses the path and optionaly arg1 set to an autofs mount type.
+variation uses the path and optionally arg1 set to an autofs mount type.
 The call returns 1 if this is a mount point and sets arg1 to the device
 number of the mount and field arg2 to the relevant super block magic
 number (described below) or 0 if it isn't a mountpoint. In both cases
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/caching/netfs-api.txt linux-libre-2.6.31-gnu/Documentation/filesystems/caching/netfs-api.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/caching/netfs-api.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/caching/netfs-api.txt	2009-09-09 18:13:59.000000000 -0400
@@ -184,7 +184,7 @@
      have index children.
 
      If this function is not supplied or if it returns NULL then the first
-     cache in the parent's list will be chosed, or failing that, the first
+     cache in the parent's list will be chosen, or failing that, the first
      cache in the master list.
 
  (4) A function to retrieve an object's key from the netfs [mandatory].
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/debugfs.txt linux-libre-2.6.31-gnu/Documentation/filesystems/debugfs.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/debugfs.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/debugfs.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,158 @@
+Copyright 2009 Jonathan Corbet <corbet@lwn.net>
+
+Debugfs exists as a simple way for kernel developers to make information
+available to user space.  Unlike /proc, which is only meant for information
+about a process, or sysfs, which has strict one-value-per-file rules,
+debugfs has no rules at all.  Developers can put any information they want
+there.  The debugfs filesystem is also intended to not serve as a stable
+ABI to user space; in theory, there are no stability constraints placed on
+files exported there.  The real world is not always so simple, though [1];
+even debugfs interfaces are best designed with the idea that they will need
+to be maintained forever.
+
+Debugfs is typically mounted with a command like:
+
+    mount -t debugfs none /sys/kernel/debug
+
+(Or an equivalent /etc/fstab line). 
+
+Note that the debugfs API is exported GPL-only to modules.
+
+Code using debugfs should include <linux/debugfs.h>.  Then, the first order
+of business will be to create at least one directory to hold a set of
+debugfs files:
+
+    struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
+
+This call, if successful, will make a directory called name underneath the
+indicated parent directory.  If parent is NULL, the directory will be
+created in the debugfs root.  On success, the return value is a struct
+dentry pointer which can be used to create files in the directory (and to
+clean it up at the end).  A NULL return value indicates that something went
+wrong.  If ERR_PTR(-ENODEV) is returned, that is an indication that the
+kernel has been built without debugfs support and none of the functions
+described below will work.
+
+The most general way to create a file within a debugfs directory is with:
+
+    struct dentry *debugfs_create_file(const char *name, mode_t mode,
+				       struct dentry *parent, void *data,
+				       const struct file_operations *fops);
+
+Here, name is the name of the file to create, mode describes the access
+permissions the file should have, parent indicates the directory which
+should hold the file, data will be stored in the i_private field of the
+resulting inode structure, and fops is a set of file operations which
+implement the file's behavior.  At a minimum, the read() and/or write()
+operations should be provided; others can be included as needed.  Again,
+the return value will be a dentry pointer to the created file, NULL for
+error, or ERR_PTR(-ENODEV) if debugfs support is missing.
+
+In a number of cases, the creation of a set of file operations is not
+actually necessary; the debugfs code provides a number of helper functions
+for simple situations.  Files containing a single integer value can be
+created with any of:
+
+    struct dentry *debugfs_create_u8(const char *name, mode_t mode,
+				     struct dentry *parent, u8 *value);
+    struct dentry *debugfs_create_u16(const char *name, mode_t mode,
+				      struct dentry *parent, u16 *value);
+    struct dentry *debugfs_create_u32(const char *name, mode_t mode,
+				      struct dentry *parent, u32 *value);
+    struct dentry *debugfs_create_u64(const char *name, mode_t mode,
+				      struct dentry *parent, u64 *value);
+
+These files support both reading and writing the given value; if a specific
+file should not be written to, simply set the mode bits accordingly.  The
+values in these files are in decimal; if hexadecimal is more appropriate,
+the following functions can be used instead:
+
+    struct dentry *debugfs_create_x8(const char *name, mode_t mode,
+				     struct dentry *parent, u8 *value);
+    struct dentry *debugfs_create_x16(const char *name, mode_t mode,
+				      struct dentry *parent, u16 *value);
+    struct dentry *debugfs_create_x32(const char *name, mode_t mode,
+				      struct dentry *parent, u32 *value);
+
+Note that there is no debugfs_create_x64().
+
+These functions are useful as long as the developer knows the size of the
+value to be exported.  Some types can have different widths on different
+architectures, though, complicating the situation somewhat.  There is a
+function meant to help out in one special case:
+
+    struct dentry *debugfs_create_size_t(const char *name, mode_t mode,
+				         struct dentry *parent, 
+					 size_t *value);
+
+As might be expected, this function will create a debugfs file to represent
+a variable of type size_t.
+
+Boolean values can be placed in debugfs with:
+
+    struct dentry *debugfs_create_bool(const char *name, mode_t mode,
+				       struct dentry *parent, u32 *value);
+
+A read on the resulting file will yield either Y (for non-zero values) or
+N, followed by a newline.  If written to, it will accept either upper- or
+lower-case values, or 1 or 0.  Any other input will be silently ignored.
+
+Finally, a block of arbitrary binary data can be exported with:
+
+    struct debugfs_blob_wrapper {
+	void *data;
+	unsigned long size;
+    };
+
+    struct dentry *debugfs_create_blob(const char *name, mode_t mode,
+				       struct dentry *parent,
+				       struct debugfs_blob_wrapper *blob);
+
+A read of this file will return the data pointed to by the
+debugfs_blob_wrapper structure.  Some drivers use "blobs" as a simple way
+to return several lines of (static) formatted text output.  This function
+can be used to export binary information, but there does not appear to be
+any code which does so in the mainline.  Note that all files created with
+debugfs_create_blob() are read-only.
+
+There are a couple of other directory-oriented helper functions:
+
+    struct dentry *debugfs_rename(struct dentry *old_dir, 
+    				  struct dentry *old_dentry,
+		                  struct dentry *new_dir, 
+				  const char *new_name);
+
+    struct dentry *debugfs_create_symlink(const char *name, 
+                                          struct dentry *parent,
+				      	  const char *target);
+
+A call to debugfs_rename() will give a new name to an existing debugfs
+file, possibly in a different directory.  The new_name must not exist prior
+to the call; the return value is old_dentry with updated information.
+Symbolic links can be created with debugfs_create_symlink().
+
+There is one important thing that all debugfs users must take into account:
+there is no automatic cleanup of any directories created in debugfs.  If a
+module is unloaded without explicitly removing debugfs entries, the result
+will be a lot of stale pointers and no end of highly antisocial behavior.
+So all debugfs users - at least those which can be built as modules - must
+be prepared to remove all files and directories they create there.  A file
+can be removed with:
+
+    void debugfs_remove(struct dentry *dentry);
+
+The dentry value can be NULL, in which case nothing will be removed.
+
+Once upon a time, debugfs users were required to remember the dentry
+pointer for every debugfs file they created so that all files could be
+cleaned up.  We live in more civilized times now, though, and debugfs users
+can call:
+
+    void debugfs_remove_recursive(struct dentry *dentry);
+
+If this function is passed a pointer for the dentry corresponding to the
+top-level directory, the entire hierarchy below that directory will be
+removed.
+
+Notes:
+	[1] http://lwn.net/Articles/309298/
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/ext2.txt linux-libre-2.6.31-gnu/Documentation/filesystems/ext2.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/ext2.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/ext2.txt	2009-09-09 18:13:59.000000000 -0400
@@ -322,7 +322,7 @@
 so 8kB blocks are only allowed on Alpha systems (and other architectures
 which support larger pages).
 
-There is an upper limit of 32768 subdirectories in a single directory.
+There is an upper limit of 32000 subdirectories in a single directory.
 
 There is a "soft" upper limit of about 10-15k files in a single directory
 with the current linear linked-list directory implementation.  This limit
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/ext4.txt linux-libre-2.6.31-gnu/Documentation/filesystems/ext4.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/ext4.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/ext4.txt	2009-09-09 18:13:59.000000000 -0400
@@ -235,6 +235,10 @@
 
 debug			Extra debugging information is sent to syslog.
 
+abort			Simulate the effects of calling ext4_abort() for
+			debugging purposes.  This is normally used while
+			remounting a filesystem which is already mounted.
+
 errors=remount-ro	Remount the filesystem read-only on an error.
 errors=continue		Keep going on a filesystem error.
 errors=panic		Panic and halt the machine if an error occurs.
@@ -294,7 +298,7 @@
 			amount of time (on average) that it takes to
 			finish committing a transaction.  Call this time
 			the "commit time".  If the time that the
-			transactoin has been running is less than the
+			transaction has been running is less than the
 			commit time, ext4 will try sleeping for the
 			commit time to see if other operations will join
 			the transaction.   The commit time is capped by
@@ -328,7 +332,7 @@
 			journal commit, in the default data=ordered
 			mode, the data blocks of the new file are forced
 			to disk before the rename() operation is
-			commited.  This provides roughly the same level
+			committed.  This provides roughly the same level
 			of guarantees as ext3, and avoids the
 			"zero-length" problem that can happen when a
 			system crashes before the delayed allocation
@@ -358,7 +362,7 @@
 In the event of a crash, the journal can be replayed, bringing both data and
 metadata into a consistent state.  This mode is the slowest except when data
 needs to be read from and written to disk at the same time where it
-outperforms all others modes.  Curently ext4 does not have delayed
+outperforms all others modes.  Currently ext4 does not have delayed
 allocation support if this data journalling mode is selected.
 
 References
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/fiemap.txt linux-libre-2.6.31-gnu/Documentation/filesystems/fiemap.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/fiemap.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/fiemap.txt	2009-09-09 18:13:59.000000000 -0400
@@ -204,7 +204,7 @@
 
 int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags);
 
-The struct fieinfo should be passed in as recieved from ioctl_fiemap(). The
+The struct fieinfo should be passed in as received from ioctl_fiemap(). The
 set of fiemap flags which the fs understands should be passed via fs_flags. If
 fiemap_check_flags finds invalid user flags, it will place the bad values in
 fieinfo->fi_flags and return -EBADR. If the file system gets -EBADR, from
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/gfs2-glocks.txt linux-libre-2.6.31-gnu/Documentation/filesystems/gfs2-glocks.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/gfs2-glocks.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/gfs2-glocks.txt	2009-09-09 18:13:59.000000000 -0400
@@ -60,7 +60,7 @@
 go_unlock        | Called on the final local unlock of a lock
 go_dump          | Called to print content of object for debugfs file, or on
                  | error to dump glock to the log.
-go_type;         | The type of the glock, LM_TYPE_.....
+go_type          | The type of the glock, LM_TYPE_.....
 go_min_hold_time | The minimum hold time
 
 The minimum hold time for each lock is the time after a remote lock
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/gfs2.txt linux-libre-2.6.31-gnu/Documentation/filesystems/gfs2.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/gfs2.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/gfs2.txt	2009-09-09 18:13:59.000000000 -0400
@@ -11,18 +11,15 @@
 features of GFS is perfect consistency -- changes made to the file system
 on one machine show up immediately on all other machines in the cluster.
 
-GFS uses interchangable inter-node locking mechanisms.  Different lock
-modules can plug into GFS and each file system selects the appropriate
-lock module at mount time.  Lock modules include:
+GFS uses interchangable inter-node locking mechanisms, the currently
+supported mechanisms are:
 
   lock_nolock -- allows gfs to be used as a local file system
 
   lock_dlm -- uses a distributed lock manager (dlm) for inter-node locking
   The dlm is found at linux/fs/dlm/
 
-In addition to interfacing with an external locking manager, a gfs lock
-module is responsible for interacting with external cluster management
-systems.  Lock_dlm depends on user space cluster management systems found
+Lock_dlm depends on user space cluster management systems found
 at the URL above.
 
 To use gfs as a local file system, no external clustering systems are
@@ -31,13 +28,19 @@
   $ mkfs -t gfs2 -p lock_nolock -j 1 /dev/block_device
   $ mount -t gfs2 /dev/block_device /dir
 
-GFS2 is not on-disk compatible with previous versions of GFS.
+If you are using Fedora, you need to install the gfs2-utils package
+and, for lock_dlm, you will also need to install the cman package
+and write a cluster.conf as per the documentation.
+
+GFS2 is not on-disk compatible with previous versions of GFS, but it
+is pretty close.
 
 The following man pages can be found at the URL above:
-  gfs2_fsck	to repair a filesystem
+  fsck.gfs2	to repair a filesystem
   gfs2_grow	to expand a filesystem online
   gfs2_jadd	to add journals to a filesystem online
   gfs2_tool	to manipulate, examine and tune a filesystem
   gfs2_quota	to examine and change quota values in a filesystem
+  gfs2_convert	to convert a gfs filesystem to gfs2 in-place
   mount.gfs2	to help mount(8) mount a filesystem
   mkfs.gfs2	to make a filesystem
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/isofs.txt linux-libre-2.6.31-gnu/Documentation/filesystems/isofs.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/isofs.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/isofs.txt	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,13 @@
   map=off       Do not map non-Rock Ridge filenames to lower case
   map=normal    Map non-Rock Ridge filenames to lower case
   map=acorn     As map=normal but also apply Acorn extensions if present
-  mode=xxx      Sets the permissions on files to xxx
-  dmode=xxx     Sets the permissions on directories to xxx
+  mode=xxx      Sets the permissions on files to xxx unless Rock Ridge
+		extensions set the permissions otherwise
+  dmode=xxx     Sets the permissions on directories to xxx unless Rock Ridge
+		extensions set the permissions otherwise
+  overriderockperm Set permissions on files and directories according to
+		'mode' and 'dmode' even though Rock Ridge extensions are
+		present.
   nojoliet      Ignore Joliet extensions if they are present.
   norock        Ignore Rock Ridge extensions if they are present.
   hide		Completely strip hidden files from the file system.
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/Locking linux-libre-2.6.31-gnu/Documentation/filesystems/Locking
--- linux-libre-2.6.30-gnu/Documentation/filesystems/Locking	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/Locking	2009-09-09 18:13:59.000000000 -0400
@@ -109,27 +109,28 @@
 
 locking rules:
 	All may block.
-			BKL	s_lock	s_umount
-alloc_inode:		no	no	no
-destroy_inode:		no
-dirty_inode:		no				(must not sleep)
-write_inode:		no
-drop_inode:		no				!!!inode_lock!!!
-delete_inode:		no
-put_super:		yes	yes	no
-write_super:		no	yes	read
-sync_fs:		no	no	read
-freeze_fs:		?
-unfreeze_fs:		?
-statfs:			no	no	no
-remount_fs:		yes	yes	maybe		(see below)
-clear_inode:		no
-umount_begin:		yes	no	no
-show_options:		no				(vfsmount->sem)
-quota_read:		no	no	no		(see below)
-quota_write:		no	no	no		(see below)
+	None have BKL
+			s_umount
+alloc_inode:
+destroy_inode:
+dirty_inode:				(must not sleep)
+write_inode:
+drop_inode:				!!!inode_lock!!!
+delete_inode:
+put_super:		write
+write_super:		read
+sync_fs:		read
+freeze_fs:		read
+unfreeze_fs:		read
+statfs:			no
+remount_fs:		maybe		(see below)
+clear_inode:
+umount_begin:		no
+show_options:		no		(namespace_sem)
+quota_read:		no		(see below)
+quota_write:		no		(see below)
 
-->remount_fs() will have the s_umount lock if it's already mounted.
+->remount_fs() will have the s_umount exclusive lock if it's already mounted.
 When called from get_sb_single, it does NOT have the s_umount lock.
 ->quota_read() and ->quota_write() functions are both guaranteed to
 be the only ones operating on the quota file by the quota code (via
@@ -187,7 +188,7 @@
 write_begin:		no	locks the page		yes
 write_end:		no	yes, unlocks		yes
 perform_write:		no	n/a			yes
-bmap:			yes
+bmap:			no
 invalidatepage:		no	yes
 releasepage:		no	yes
 direct_IO:		no
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/nfs-rdma.txt linux-libre-2.6.31-gnu/Documentation/filesystems/nfs-rdma.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/nfs-rdma.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/nfs-rdma.txt	2009-09-09 18:13:59.000000000 -0400
@@ -100,7 +100,7 @@
     $ sudo cp utils/mount/mount.nfs /sbin/mount.nfs
 
     In this location, mount.nfs will be invoked automatically for NFS mounts
-    by the system mount commmand.
+    by the system mount command.
 
     NOTE: mount.nfs and therefore nfs-utils-1.1.2 or greater is only needed
     on the NFS client machine. You do not need this specific version of
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/nilfs2.txt linux-libre-2.6.31-gnu/Documentation/filesystems/nilfs2.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/nilfs2.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/nilfs2.txt	2009-09-09 18:13:59.000000000 -0400
@@ -39,9 +39,8 @@
 	- extended attributes
 	- POSIX ACLs
 	- quotas
-	- writable snapshots
-	- remote backup (CDP)
-	- data integrity
+	- fsck
+	- resize
 	- defragmentation
 
 Mount options
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/proc.txt linux-libre-2.6.31-gnu/Documentation/filesystems/proc.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/proc.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/proc.txt	2009-09-09 18:13:59.000000000 -0400
@@ -5,11 +5,12 @@
                   Bodo Bauer <bb@ricochet.net>
 
 2.4.x update	  Jorge Nerin <comandante@zaralinux.com>      November 14 2000
-move /proc/sys	  Shen Feng <shen@cn.fujitsu.com>		    April 1 2009
+move /proc/sys	  Shen Feng <shen@cn.fujitsu.com>		  April 1 2009
 ------------------------------------------------------------------------------
 Version 1.3                                              Kernel version 2.2.12
 					      Kernel version 2.4.0-test11-pre4
 ------------------------------------------------------------------------------
+fixes/update part 1.1  Stefani Seibold <stefani@seibold.net>       June 9 2009
 
 Table of Contents
 -----------------
@@ -116,7 +117,7 @@
 subdirectory has the entries listed in Table 1-1.
 
 
-Table 1-1: Process specific entries in /proc 
+Table 1-1: Process specific entries in /proc
 ..............................................................................
  File		Content
  clear_refs	Clears page referenced bits shown in smaps output
@@ -134,46 +135,103 @@
  status		Process status in human readable form
  wchan		If CONFIG_KALLSYMS is set, a pre-decoded wchan
  stack		Report full stack trace, enable via CONFIG_STACKTRACE
- smaps		Extension based on maps, the rss size for each mapped file
+ smaps		a extension based on maps, showing the memory consumption of
+		each mapping
 ..............................................................................
 
 For example, to get the status information of a process, all you have to do is
 read the file /proc/PID/status:
 
-  >cat /proc/self/status 
-  Name:   cat 
-  State:  R (running) 
-  Pid:    5452 
-  PPid:   743 
+  >cat /proc/self/status
+  Name:   cat
+  State:  R (running)
+  Tgid:   5452
+  Pid:    5452
+  PPid:   743
   TracerPid:      0						(2.4)
-  Uid:    501     501     501     501 
-  Gid:    100     100     100     100 
-  Groups: 100 14 16 
-  VmSize:     1112 kB 
-  VmLck:         0 kB 
-  VmRSS:       348 kB 
-  VmData:       24 kB 
-  VmStk:        12 kB 
-  VmExe:         8 kB 
-  VmLib:      1044 kB 
-  SigPnd: 0000000000000000 
-  SigBlk: 0000000000000000 
-  SigIgn: 0000000000000000 
-  SigCgt: 0000000000000000 
-  CapInh: 00000000fffffeff 
-  CapPrm: 0000000000000000 
-  CapEff: 0000000000000000 
-
+  Uid:    501     501     501     501
+  Gid:    100     100     100     100
+  FDSize: 256
+  Groups: 100 14 16
+  VmPeak:     5004 kB
+  VmSize:     5004 kB
+  VmLck:         0 kB
+  VmHWM:       476 kB
+  VmRSS:       476 kB
+  VmData:      156 kB
+  VmStk:        88 kB
+  VmExe:        68 kB
+  VmLib:      1412 kB
+  VmPTE:        20 kb
+  Threads:        1
+  SigQ:   0/28578
+  SigPnd: 0000000000000000
+  ShdPnd: 0000000000000000
+  SigBlk: 0000000000000000
+  SigIgn: 0000000000000000
+  SigCgt: 0000000000000000
+  CapInh: 00000000fffffeff
+  CapPrm: 0000000000000000
+  CapEff: 0000000000000000
+  CapBnd: ffffffffffffffff
+  voluntary_ctxt_switches:        0
+  nonvoluntary_ctxt_switches:     1
 
 This shows you nearly the same information you would get if you viewed it with
 the ps  command.  In  fact,  ps  uses  the  proc  file  system  to  obtain its
-information. The  statm  file  contains  more  detailed  information about the
-process memory usage. Its seven fields are explained in Table 1-2.  The stat
-file contains details information about the process itself.  Its fields are
-explained in Table 1-3.
+information.  But you get a more detailed  view of the  process by reading the
+file /proc/PID/status. It fields are described in table 1-2.
 
+The  statm  file  contains  more  detailed  information about the process
+memory usage. Its seven fields are explained in Table 1-3.  The stat file
+contains details information about the process itself.  Its fields are
+explained in Table 1-4.
 
-Table 1-2: Contents of the statm files (as of 2.6.8-rc3)
+Table 1-2: Contents of the statm files (as of 2.6.30-rc7)
+..............................................................................
+ Field                       Content
+ Name                        filename of the executable
+ State                       state (R is running, S is sleeping, D is sleeping
+                             in an uninterruptible wait, Z is zombie,
+			     T is traced or stopped)
+ Tgid                        thread group ID
+ Pid                         process id
+ PPid                        process id of the parent process
+ TracerPid                   PID of process tracing this process (0 if not)
+ Uid                         Real, effective, saved set, and  file system UIDs
+ Gid                         Real, effective, saved set, and  file system GIDs
+ FDSize                      number of file descriptor slots currently allocated
+ Groups                      supplementary group list
+ VmPeak                      peak virtual memory size
+ VmSize                      total program size
+ VmLck                       locked memory size
+ VmHWM                       peak resident set size ("high water mark")
+ VmRSS                       size of memory portions
+ VmData                      size of data, stack, and text segments
+ VmStk                       size of data, stack, and text segments
+ VmExe                       size of text segment
+ VmLib                       size of shared library code
+ VmPTE                       size of page table entries
+ Threads                     number of threads
+ SigQ                        number of signals queued/max. number for queue
+ SigPnd                      bitmap of pending signals for the thread
+ ShdPnd                      bitmap of shared pending signals for the process
+ SigBlk                      bitmap of blocked signals
+ SigIgn                      bitmap of ignored signals
+ SigCgt                      bitmap of catched signals
+ CapInh                      bitmap of inheritable capabilities
+ CapPrm                      bitmap of permitted capabilities
+ CapEff                      bitmap of effective capabilities
+ CapBnd                      bitmap of capabilities bounding set
+ Cpus_allowed                mask of CPUs on which this process may run
+ Cpus_allowed_list           Same as previous, but in "list format"
+ Mems_allowed                mask of memory nodes allowed to this process
+ Mems_allowed_list           Same as previous, but in "list format"
+ voluntary_ctxt_switches     number of voluntary context switches
+ nonvoluntary_ctxt_switches  number of non voluntary context switches
+..............................................................................
+
+Table 1-3: Contents of the statm files (as of 2.6.8-rc3)
 ..............................................................................
  Field    Content
  size     total program size (pages)		(same as VmSize in status)
@@ -188,7 +246,7 @@
 ..............................................................................
 
 
-Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
+Table 1-4: Contents of the stat files (as of 2.6.30-rc7)
 ..............................................................................
  Field          Content
   pid           process id
@@ -222,10 +280,10 @@
   start_stack   address of the start of the stack
   esp           current value of ESP
   eip           current value of EIP
-  pending       bitmap of pending signals (obsolete)
-  blocked       bitmap of blocked signals (obsolete)
-  sigign        bitmap of ignored signals (obsolete)
-  sigcatch      bitmap of catched signals (obsolete)
+  pending       bitmap of pending signals
+  blocked       bitmap of blocked signals
+  sigign        bitmap of ignored signals
+  sigcatch      bitmap of catched signals
   wchan         address where process went to sleep
   0             (place holder)
   0             (place holder)
@@ -234,19 +292,99 @@
   rt_priority   realtime priority
   policy        scheduling policy (man sched_setscheduler)
   blkio_ticks   time spent waiting for block IO
+  gtime         guest time of the task in jiffies
+  cgtime        guest time of the task children in jiffies
 ..............................................................................
 
+The /proc/PID/map file containing the currently mapped memory regions and
+their access permissions.
+
+The format is:
+
+address           perms offset  dev   inode      pathname
+
+08048000-08049000 r-xp 00000000 03:00 8312       /opt/test
+08049000-0804a000 rw-p 00001000 03:00 8312       /opt/test
+0804a000-0806b000 rw-p 00000000 00:00 0          [heap]
+a7cb1000-a7cb2000 ---p 00000000 00:00 0
+a7cb2000-a7eb2000 rw-p 00000000 00:00 0
+a7eb2000-a7eb3000 ---p 00000000 00:00 0
+a7eb3000-a7ed5000 rw-p 00000000 00:00 0
+a7ed5000-a8008000 r-xp 00000000 03:00 4222       /lib/libc.so.6
+a8008000-a800a000 r--p 00133000 03:00 4222       /lib/libc.so.6
+a800a000-a800b000 rw-p 00135000 03:00 4222       /lib/libc.so.6
+a800b000-a800e000 rw-p 00000000 00:00 0
+a800e000-a8022000 r-xp 00000000 03:00 14462      /lib/libpthread.so.0
+a8022000-a8023000 r--p 00013000 03:00 14462      /lib/libpthread.so.0
+a8023000-a8024000 rw-p 00014000 03:00 14462      /lib/libpthread.so.0
+a8024000-a8027000 rw-p 00000000 00:00 0
+a8027000-a8043000 r-xp 00000000 03:00 8317       /lib/ld-linux.so.2
+a8043000-a8044000 r--p 0001b000 03:00 8317       /lib/ld-linux.so.2
+a8044000-a8045000 rw-p 0001c000 03:00 8317       /lib/ld-linux.so.2
+aff35000-aff4a000 rw-p 00000000 00:00 0          [stack]
+ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
+
+where "address" is the address space in the process that it occupies, "perms"
+is a set of permissions:
+
+ r = read
+ w = write
+ x = execute
+ s = shared
+ p = private (copy on write)
+
+"offset" is the offset into the mapping, "dev" is the device (major:minor), and
+"inode" is the inode  on that device.  0 indicates that  no inode is associated
+with the memory region, as the case would be with BSS (uninitialized data).
+The "pathname" shows the name associated file for this mapping.  If the mapping
+is not associated with a file:
+
+ [heap]                   = the heap of the program
+ [stack]                  = the stack of the main process
+ [vdso]                   = the "virtual dynamic shared object",
+                            the kernel system call handler
+
+ or if empty, the mapping is anonymous.
+
+
+The /proc/PID/smaps is an extension based on maps, showing the memory
+consumption for each of the process's mappings. For each of mappings there
+is a series of lines such as the following:
+
+08048000-080bc000 r-xp 00000000 03:02 13130      /bin/bash
+Size:               1084 kB
+Rss:                 892 kB
+Pss:                 374 kB
+Shared_Clean:        892 kB
+Shared_Dirty:          0 kB
+Private_Clean:         0 kB
+Private_Dirty:         0 kB
+Referenced:          892 kB
+Swap:                  0 kB
+KernelPageSize:        4 kB
+MMUPageSize:           4 kB
+
+The first  of these lines shows  the same information  as is displayed for the
+mapping in /proc/PID/maps.  The remaining lines show  the size of the mapping,
+the amount of the mapping that is currently resident in RAM, the "proportional
+set size” (divide each shared page by the number of processes sharing it), the
+number of clean and dirty shared pages in the mapping, and the number of clean
+and dirty private pages in the mapping.  The "Referenced" indicates the amount
+of memory currently marked as referenced or accessed.
+
+This file is only present if the CONFIG_MMU kernel configuration option is
+enabled.
 
 1.2 Kernel data
 ---------------
 
 Similar to  the  process entries, the kernel data files give information about
 the running kernel. The files used to obtain this information are contained in
-/proc and  are  listed  in Table 1-4. Not all of these will be present in your
+/proc and  are  listed  in Table 1-5. Not all of these will be present in your
 system. It  depends  on the kernel configuration and the loaded modules, which
 files are there, and which are missing.
 
-Table 1-4: Kernel info in /proc
+Table 1-5: Kernel info in /proc
 ..............................................................................
  File        Content                                           
  apm         Advanced power management info                    
@@ -283,6 +421,7 @@
  rtc         Real time clock                                   
  scsi        SCSI info (see text)                              
  slabinfo    Slab pool info                                    
+ softirqs    softirq usage
  stat        Overall statistics                                
  swaps       Swap space utilization                            
  sys         See chapter 2                                     
@@ -366,7 +505,7 @@
   RES, CAL, TLB -- rescheduling, call and TLB flush interrupts are
   sent from one CPU to another per the needs of the OS.  Typically,
   their statistics are used by kernel developers and interested users to
-  determine the occurance of interrupt of the given type.
+  determine the occurrence of interrupts of the given type.
 
 The above IRQ vectors are displayed only when relevent.  For example,
 the threshold vector does not exist on x86_64 platforms.  Others are
@@ -551,7 +690,7 @@
               memory once that memory has been successfully allocated.
 VmallocTotal: total size of vmalloc memory area
  VmallocUsed: amount of vmalloc area which is used
-VmallocChunk: largest contigious block of vmalloc area which is free
+VmallocChunk: largest contiguous block of vmalloc area which is free
 
 ..............................................................................
 
@@ -597,6 +736,25 @@
 0xffffffffa0017000-0xffffffffa0022000   45056 sys_init_module+0xc27/0x1d00 ...
    pages=10 vmalloc N0=10
 
+..............................................................................
+
+softirqs:
+
+Provides counts of softirq handlers serviced since boot time, for each cpu.
+
+> cat /proc/softirqs
+                CPU0       CPU1       CPU2       CPU3
+      HI:          0          0          0          0
+   TIMER:      27166      27120      27097      27034
+  NET_TX:          0          0          0         17
+  NET_RX:         42          0          0         39
+   BLOCK:          0          0        107       1121
+ TASKLET:          0          0          0        290
+   SCHED:      27035      26983      26971      26746
+ HRTIMER:          0          0          0          0
+     RCU:       1678       1769       2178       2250
+
+
 1.3 IDE devices in /proc/ide
 ----------------------------
 
@@ -614,10 +772,10 @@
 
 More detailed  information  can  be  found  in  the  controller  specific
 subdirectories. These  are  named  ide0,  ide1  and  so  on.  Each  of  these
-directories contains the files shown in table 1-5.
+directories contains the files shown in table 1-6.
 
 
-Table 1-5: IDE controller info in  /proc/ide/ide?
+Table 1-6: IDE controller info in  /proc/ide/ide?
 ..............................................................................
  File    Content                                 
  channel IDE channel (0 or 1)                    
@@ -627,11 +785,11 @@
 ..............................................................................
 
 Each device  connected  to  a  controller  has  a separate subdirectory in the
-controllers directory.  The  files  listed in table 1-6 are contained in these
+controllers directory.  The  files  listed in table 1-7 are contained in these
 directories.
 
 
-Table 1-6: IDE device information
+Table 1-7: IDE device information
 ..............................................................................
  File             Content                                    
  cache            The cache                                  
@@ -673,12 +831,12 @@
 1.4 Networking info in /proc/net
 --------------------------------
 
-The subdirectory  /proc/net  follows  the  usual  pattern. Table 1-6 shows the
+The subdirectory  /proc/net  follows  the  usual  pattern. Table 1-8 shows the
 additional values  you  get  for  IP  version 6 if you configure the kernel to
-support this. Table 1-7 lists the files and their meaning.
+support this. Table 1-9 lists the files and their meaning.
 
 
-Table 1-6: IPv6 info in /proc/net 
+Table 1-8: IPv6 info in /proc/net
 ..............................................................................
  File       Content                                               
  udp6       UDP sockets (IPv6)                                    
@@ -693,7 +851,7 @@
 ..............................................................................
 
 
-Table 1-7: Network info in /proc/net 
+Table 1-9: Network info in /proc/net
 ..............................................................................
  File          Content                                                         
  arp           Kernel  ARP table                                               
@@ -817,10 +975,10 @@
 your system.  It  has  one  subdirectory  for  each port, named after the port
 number (0,1,2,...).
 
-These directories contain the four files shown in Table 1-8.
+These directories contain the four files shown in Table 1-10.
 
 
-Table 1-8: Files in /proc/parport 
+Table 1-10: Files in /proc/parport
 ..............................................................................
  File      Content                                                             
  autoprobe Any IEEE-1284 device ID information that has been acquired.         
@@ -838,10 +996,10 @@
 
 Information about  the  available  and actually used tty's can be found in the
 directory /proc/tty.You'll  find  entries  for drivers and line disciplines in
-this directory, as shown in Table 1-9.
+this directory, as shown in Table 1-11.
 
 
-Table 1-9: Files in /proc/tty 
+Table 1-11: Files in /proc/tty
 ..............................................................................
  File          Content                                        
  drivers       list of drivers and their usage                
@@ -883,6 +1041,7 @@
   processes 2915
   procs_running 1
   procs_blocked 0
+  softirq 183433 0 21755 12 39 1137 231 21459 2263
 
 The very first  "cpu" line aggregates the  numbers in all  of the other "cpuN"
 lines.  These numbers identify the amount of time the CPU has spent performing
@@ -918,6 +1077,11 @@
 The   "procs_blocked" line gives  the  number of  processes currently blocked,
 waiting for I/O to complete.
 
+The "softirq" line gives counts of softirqs serviced since boot time, for each
+of the possible system softirqs. The first column is the total of all
+softirqs serviced; each subsequent column is the total for that particular
+softirq.
+
 
 1.9 Ext4 file system parameters
 ------------------------------
@@ -926,9 +1090,9 @@
 /proc/fs/ext4.  Each mounted filesystem will have a directory in
 /proc/fs/ext4 based on its device name (i.e., /proc/fs/ext4/hdc or
 /proc/fs/ext4/dm-0).   The files in each per-device directory are shown
-in Table 1-10, below.
+in Table 1-12, below.
 
-Table 1-10: Files in /proc/fs/ext4/<devname>
+Table 1-12: Files in /proc/fs/ext4/<devname>
 ..............................................................................
  File            Content                                        
  mb_groups       details of multiblock allocator buddy cache of free blocks
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/sysfs-pci.txt linux-libre-2.6.31-gnu/Documentation/filesystems/sysfs-pci.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/sysfs-pci.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/sysfs-pci.txt	2009-09-09 18:13:59.000000000 -0400
@@ -72,7 +72,7 @@
 ROM file, if available.  It's disabled by default, however, so applications
 should write the string "1" to the file to enable it before attempting a read
 call, and disable it following the access by writing "0" to the file.  Note
-that the device must be enabled for a rom read to return data succesfully.
+that the device must be enabled for a rom read to return data successfully.
 In the event a driver is not bound to the device, it can be enabled using the
 'enable' file, documented above.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/sysfs.txt linux-libre-2.6.31-gnu/Documentation/filesystems/sysfs.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/sysfs.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/sysfs.txt	2009-09-09 18:13:59.000000000 -0400
@@ -23,7 +23,8 @@
 Using sysfs
 ~~~~~~~~~~~
 
-sysfs is always compiled in. You can access it by doing:
+sysfs is always compiled in if CONFIG_SYSFS is defined. You can access
+it by doing:
 
     mount -t sysfs sysfs /sys 
 
diff -druN linux-libre-2.6.30-gnu/Documentation/filesystems/vfat.txt linux-libre-2.6.31-gnu/Documentation/filesystems/vfat.txt
--- linux-libre-2.6.30-gnu/Documentation/filesystems/vfat.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/filesystems/vfat.txt	2009-09-09 18:13:59.000000000 -0400
@@ -124,14 +124,19 @@
 flush         -- If set, the filesystem will try to flush to disk more
 		 early than normal. Not set by default.
 
-rodir	      -- FAT has the ATTR_RO (read-only) attribute. But on Windows,
-		 the ATTR_RO of the directory will be just ignored actually,
-		 and is used by only applications as flag. E.g. it's setted
-		 for the customized folder.
+rodir	      -- FAT has the ATTR_RO (read-only) attribute. On Windows,
+		 the ATTR_RO of the directory will just be ignored,
+		 and is used only by applications as a flag (e.g. it's set
+		 for the customized folder).
 
 		 If you want to use ATTR_RO as read-only flag even for
 		 the directory, set this option.
 
+errors=panic|continue|remount-ro
+	      -- specify FAT behavior on critical errors: panic, continue
+		 without doing anything or remount the partition in
+		 read-only mode (default behavior).
+
 <bool>: 0,1,yes,no,true,false
 
 TODO
diff -druN linux-libre-2.6.30-gnu/Documentation/firmware_class/README linux-libre-2.6.31-gnu/Documentation/firmware_class/README
--- linux-libre-2.6.30-gnu/Documentation/firmware_class/README	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/firmware_class/README	2009-09-09 18:13:59.000000000 -0400
@@ -77,7 +77,8 @@
    seconds for the whole load operation.
 
  - request_firmware_nowait() is also provided for convenience in
-   non-user contexts.
+   user contexts to request firmware asynchronously, but can't be called
+   in atomic contexts.
 
 
  about in-kernel persistence:
diff -druN linux-libre-2.6.30-gnu/Documentation/futex-requeue-pi.txt linux-libre-2.6.31-gnu/Documentation/futex-requeue-pi.txt
--- linux-libre-2.6.30-gnu/Documentation/futex-requeue-pi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/futex-requeue-pi.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,131 @@
+Futex Requeue PI
+----------------
+
+Requeueing of tasks from a non-PI futex to a PI futex requires
+special handling in order to ensure the underlying rt_mutex is never
+left without an owner if it has waiters; doing so would break the PI
+boosting logic [see rt-mutex-desgin.txt] For the purposes of
+brevity, this action will be referred to as "requeue_pi" throughout
+this document.  Priority inheritance is abbreviated throughout as
+"PI".
+
+Motivation
+----------
+
+Without requeue_pi, the glibc implementation of
+pthread_cond_broadcast() must resort to waking all the tasks waiting
+on a pthread_condvar and letting them try to sort out which task
+gets to run first in classic thundering-herd formation.  An ideal
+implementation would wake the highest-priority waiter, and leave the
+rest to the natural wakeup inherent in unlocking the mutex
+associated with the condvar.
+
+Consider the simplified glibc calls:
+
+/* caller must lock mutex */
+pthread_cond_wait(cond, mutex)
+{
+	lock(cond->__data.__lock);
+	unlock(mutex);
+	do {
+	   unlock(cond->__data.__lock);
+	   futex_wait(cond->__data.__futex);
+	   lock(cond->__data.__lock);
+	} while(...)
+	unlock(cond->__data.__lock);
+	lock(mutex);
+}
+
+pthread_cond_broadcast(cond)
+{
+	lock(cond->__data.__lock);
+	unlock(cond->__data.__lock);
+	futex_requeue(cond->data.__futex, cond->mutex);
+}
+
+Once pthread_cond_broadcast() requeues the tasks, the cond->mutex
+has waiters. Note that pthread_cond_wait() attempts to lock the
+mutex only after it has returned to user space.  This will leave the
+underlying rt_mutex with waiters, and no owner, breaking the
+previously mentioned PI-boosting algorithms.
+
+In order to support PI-aware pthread_condvar's, the kernel needs to
+be able to requeue tasks to PI futexes.  This support implies that
+upon a successful futex_wait system call, the caller would return to
+user space already holding the PI futex.  The glibc implementation
+would be modified as follows:
+
+
+/* caller must lock mutex */
+pthread_cond_wait_pi(cond, mutex)
+{
+	lock(cond->__data.__lock);
+	unlock(mutex);
+	do {
+	   unlock(cond->__data.__lock);
+	   futex_wait_requeue_pi(cond->__data.__futex);
+	   lock(cond->__data.__lock);
+	} while(...)
+	unlock(cond->__data.__lock);
+        /* the kernel acquired the the mutex for us */
+}
+
+pthread_cond_broadcast_pi(cond)
+{
+	lock(cond->__data.__lock);
+	unlock(cond->__data.__lock);
+	futex_requeue_pi(cond->data.__futex, cond->mutex);
+}
+
+The actual glibc implementation will likely test for PI and make the
+necessary changes inside the existing calls rather than creating new
+calls for the PI cases.  Similar changes are needed for
+pthread_cond_timedwait() and pthread_cond_signal().
+
+Implementation
+--------------
+
+In order to ensure the rt_mutex has an owner if it has waiters, it
+is necessary for both the requeue code, as well as the waiting code,
+to be able to acquire the rt_mutex before returning to user space.
+The requeue code cannot simply wake the waiter and leave it to
+acquire the rt_mutex as it would open a race window between the
+requeue call returning to user space and the waiter waking and
+starting to run.  This is especially true in the uncontended case.
+
+The solution involves two new rt_mutex helper routines,
+rt_mutex_start_proxy_lock() and rt_mutex_finish_proxy_lock(), which
+allow the requeue code to acquire an uncontended rt_mutex on behalf
+of the waiter and to enqueue the waiter on a contended rt_mutex.
+Two new system calls provide the kernel<->user interface to
+requeue_pi: FUTEX_WAIT_REQUEUE_PI and FUTEX_REQUEUE_CMP_PI.
+
+FUTEX_WAIT_REQUEUE_PI is called by the waiter (pthread_cond_wait()
+and pthread_cond_timedwait()) to block on the initial futex and wait
+to be requeued to a PI-aware futex.  The implementation is the
+result of a high-speed collision between futex_wait() and
+futex_lock_pi(), with some extra logic to check for the additional
+wake-up scenarios.
+
+FUTEX_REQUEUE_CMP_PI is called by the waker
+(pthread_cond_broadcast() and pthread_cond_signal()) to requeue and
+possibly wake the waiting tasks. Internally, this system call is
+still handled by futex_requeue (by passing requeue_pi=1).  Before
+requeueing, futex_requeue() attempts to acquire the requeue target
+PI futex on behalf of the top waiter.  If it can, this waiter is
+woken.  futex_requeue() then proceeds to requeue the remaining
+nr_wake+nr_requeue tasks to the PI futex, calling
+rt_mutex_start_proxy_lock() prior to each requeue to prepare the
+task as a waiter on the underlying rt_mutex.  It is possible that
+the lock can be acquired at this stage as well, if so, the next
+waiter is woken to finish the acquisition of the lock.
+
+FUTEX_REQUEUE_PI accepts nr_wake and nr_requeue as arguments, but
+their sum is all that really matters.  futex_requeue() will wake or
+requeue up to nr_wake + nr_requeue tasks.  It will wake only as many
+tasks as it can acquire the lock for, which in the majority of cases
+should be 0 as good programming practice dictates that the caller of
+either pthread_cond_broadcast() or pthread_cond_signal() acquire the
+mutex prior to making the call. FUTEX_REQUEUE_PI requires that
+nr_wake=1.  nr_requeue should be INT_MAX for broadcast and 0 for
+signal.
diff -druN linux-libre-2.6.30-gnu/Documentation/gcov.txt linux-libre-2.6.31-gnu/Documentation/gcov.txt
--- linux-libre-2.6.30-gnu/Documentation/gcov.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/gcov.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,253 @@
+Using gcov with the Linux kernel
+================================
+
+1. Introduction
+2. Preparation
+3. Customization
+4. Files
+5. Modules
+6. Separated build and test machines
+7. Troubleshooting
+Appendix A: sample script: gather_on_build.sh
+Appendix B: sample script: gather_on_test.sh
+
+
+1. Introduction
+===============
+
+gcov profiling kernel support enables the use of GCC's coverage testing
+tool gcov [1] with the Linux kernel. Coverage data of a running kernel
+is exported in gcov-compatible format via the "gcov" debugfs directory.
+To get coverage data for a specific file, change to the kernel build
+directory and use gcov with the -o option as follows (requires root):
+
+# cd /tmp/linux-out
+# gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c
+
+This will create source code files annotated with execution counts
+in the current directory. In addition, graphical gcov front-ends such
+as lcov [2] can be used to automate the process of collecting data
+for the entire kernel and provide coverage overviews in HTML format.
+
+Possible uses:
+
+* debugging (has this line been reached at all?)
+* test improvement (how do I change my test to cover these lines?)
+* minimizing kernel configurations (do I need this option if the
+  associated code is never run?)
+
+--
+
+[1] http://gcc.gnu.org/onlinedocs/gcc/Gcov.html
+[2] http://ltp.sourceforge.net/coverage/lcov.php
+
+
+2. Preparation
+==============
+
+Configure the kernel with:
+
+        CONFIG_DEBUGFS=y
+        CONFIG_GCOV_KERNEL=y
+
+and to get coverage data for the entire kernel:
+
+        CONFIG_GCOV_PROFILE_ALL=y
+
+Note that kernels compiled with profiling flags will be significantly
+larger and run slower. Also CONFIG_GCOV_PROFILE_ALL may not be supported
+on all architectures.
+
+Profiling data will only become accessible once debugfs has been
+mounted:
+
+        mount -t debugfs none /sys/kernel/debug
+
+
+3. Customization
+================
+
+To enable profiling for specific files or directories, add a line
+similar to the following to the respective kernel Makefile:
+
+        For a single file (e.g. main.o):
+                GCOV_PROFILE_main.o := y
+
+        For all files in one directory:
+                GCOV_PROFILE := y
+
+To exclude files from being profiled even when CONFIG_GCOV_PROFILE_ALL
+is specified, use:
+
+                GCOV_PROFILE_main.o := n
+        and:
+                GCOV_PROFILE := n
+
+Only files which are linked to the main kernel image or are compiled as
+kernel modules are supported by this mechanism.
+
+
+4. Files
+========
+
+The gcov kernel support creates the following files in debugfs:
+
+        /sys/kernel/debug/gcov
+                Parent directory for all gcov-related files.
+
+        /sys/kernel/debug/gcov/reset
+                Global reset file: resets all coverage data to zero when
+                written to.
+
+        /sys/kernel/debug/gcov/path/to/compile/dir/file.gcda
+                The actual gcov data file as understood by the gcov
+                tool. Resets file coverage data to zero when written to.
+
+        /sys/kernel/debug/gcov/path/to/compile/dir/file.gcno
+                Symbolic link to a static data file required by the gcov
+                tool. This file is generated by gcc when compiling with
+                option -ftest-coverage.
+
+
+5. Modules
+==========
+
+Kernel modules may contain cleanup code which is only run during
+module unload time. The gcov mechanism provides a means to collect
+coverage data for such code by keeping a copy of the data associated
+with the unloaded module. This data remains available through debugfs.
+Once the module is loaded again, the associated coverage counters are
+initialized with the data from its previous instantiation.
+
+This behavior can be deactivated by specifying the gcov_persist kernel
+parameter:
+
+        gcov_persist=0
+
+At run-time, a user can also choose to discard data for an unloaded
+module by writing to its data file or the global reset file.
+
+
+6. Separated build and test machines
+====================================
+
+The gcov kernel profiling infrastructure is designed to work out-of-the
+box for setups where kernels are built and run on the same machine. In
+cases where the kernel runs on a separate machine, special preparations
+must be made, depending on where the gcov tool is used:
+
+a) gcov is run on the TEST machine
+
+The gcov tool version on the test machine must be compatible with the
+gcc version used for kernel build. Also the following files need to be
+copied from build to test machine:
+
+from the source tree:
+  - all C source files + headers
+
+from the build tree:
+  - all C source files + headers
+  - all .gcda and .gcno files
+  - all links to directories
+
+It is important to note that these files need to be placed into the
+exact same file system location on the test machine as on the build
+machine. If any of the path components is symbolic link, the actual
+directory needs to be used instead (due to make's CURDIR handling).
+
+b) gcov is run on the BUILD machine
+
+The following files need to be copied after each test case from test
+to build machine:
+
+from the gcov directory in sysfs:
+  - all .gcda files
+  - all links to .gcno files
+
+These files can be copied to any location on the build machine. gcov
+must then be called with the -o option pointing to that directory.
+
+Example directory setup on the build machine:
+
+  /tmp/linux:    kernel source tree
+  /tmp/out:      kernel build directory as specified by make O=
+  /tmp/coverage: location of the files copied from the test machine
+
+  [user@build] cd /tmp/out
+  [user@build] gcov -o /tmp/coverage/tmp/out/init main.c
+
+
+7. Troubleshooting
+==================
+
+Problem:  Compilation aborts during linker step.
+Cause:    Profiling flags are specified for source files which are not
+          linked to the main kernel or which are linked by a custom
+          linker procedure.
+Solution: Exclude affected source files from profiling by specifying
+          GCOV_PROFILE := n or GCOV_PROFILE_basename.o := n in the
+          corresponding Makefile.
+
+Problem:  Files copied from sysfs appear empty or incomplete.
+Cause:    Due to the way seq_file works, some tools such as cp or tar
+          may not correctly copy files from sysfs.
+Solution: Use 'cat' to read .gcda files and 'cp -d' to copy links.
+          Alternatively use the mechanism shown in Appendix B.
+
+
+Appendix A: gather_on_build.sh
+==============================
+
+Sample script to gather coverage meta files on the build machine
+(see 6a):
+#!/bin/bash
+
+KSRC=$1
+KOBJ=$2
+DEST=$3
+
+if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then
+  echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2
+  exit 1
+fi
+
+KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
+KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
+
+find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \
+                 -perm /u+r,g+r | tar cfz $DEST -P -T -
+
+if [ $? -eq 0 ] ; then
+  echo "$DEST successfully created, copy to test system and unpack with:"
+  echo "  tar xfz $DEST -P"
+else
+  echo "Could not create file $DEST"
+fi
+
+
+Appendix B: gather_on_test.sh
+=============================
+
+Sample script to gather coverage data files on the test machine
+(see 6b):
+
+#!/bin/bash -e
+
+DEST=$1
+GCDA=/sys/kernel/debug/gcov
+
+if [ -z "$DEST" ] ; then
+  echo "Usage: $0 <output.tar.gz>" >&2
+  exit 1
+fi
+
+TEMPDIR=$(mktemp -d)
+echo Collecting data..
+find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \;
+find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \;
+find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \;
+tar czf $DEST -C $TEMPDIR sys
+rm -rf $TEMPDIR
+
+echo "$DEST successfully created, copy to build system and unpack with:"
+echo "  tar xfz $DEST"
diff -druN linux-libre-2.6.30-gnu/Documentation/gpio.txt linux-libre-2.6.31-gnu/Documentation/gpio.txt
--- linux-libre-2.6.30-gnu/Documentation/gpio.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/gpio.txt	2009-09-09 18:13:59.000000000 -0400
@@ -458,7 +458,7 @@
 value instead of just showing a gpio state summary.  Plus, it could be
 present on production systems without debugging support.
 
-Given approprate hardware documentation for the system, userspace could
+Given appropriate hardware documentation for the system, userspace could
 know for example that GPIO #23 controls the write protect line used to
 protect boot loader segments in flash memory.  System upgrade procedures
 may need to temporarily remove that protection, first importing a GPIO,
diff -druN linux-libre-2.6.30-gnu/Documentation/hwmon/f71882fg linux-libre-2.6.31-gnu/Documentation/hwmon/f71882fg
--- linux-libre-2.6.30-gnu/Documentation/hwmon/f71882fg	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/hwmon/f71882fg	2009-09-09 18:13:59.000000000 -0400
@@ -2,14 +2,18 @@
 ======================
 
 Supported chips:
-  * Fintek F71882FG and F71883FG
-    Prefix: 'f71882fg'
+  * Fintek F71858FG
+    Prefix: 'f71858fg'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Available from the Fintek website
   * Fintek F71862FG and F71863FG
     Prefix: 'f71862fg'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Available from the Fintek website
+  * Fintek F71882FG and F71883FG
+    Prefix: 'f71882fg'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Available from the Fintek website
   * Fintek F8000
     Prefix: 'f8000'
     Addresses scanned: none, address read from Super I/O config space
@@ -66,13 +70,13 @@
 
 Three different fan control modes are supported; the mode number is written
 to the pwm#_enable file. Note that not all modes are supported on all
-chips, and some modes may only be available in RPM / PWM mode on the F8000.
+chips, and some modes may only be available in RPM / PWM mode.
 Writing an unsupported mode will result in an invalid parameter error.
 
 * 1: Manual mode
   You ask for a specific PWM duty cycle / DC voltage or a specific % of
   fan#_full_speed by writing to the pwm# file. This mode is only
-  available on the F8000 if the fan channel is in RPM mode.
+  available on the F71858FG / F8000 if the fan channel is in RPM mode.
 
 * 2: Normal auto mode
   You can define a number of temperature/fan speed trip points, which % the
diff -druN linux-libre-2.6.30-gnu/Documentation/hwmon/ibmaem linux-libre-2.6.31-gnu/Documentation/hwmon/ibmaem
--- linux-libre-2.6.30-gnu/Documentation/hwmon/ibmaem	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/hwmon/ibmaem	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
 Supported systems:
   * Any recent IBM System X server with AEM support.
     This includes the x3350, x3550, x3650, x3655, x3755, x3850 M2,
-    x3950 M2, and certain HS2x/LS2x/QS2x blades.  The IPMI host interface
+    x3950 M2, and certain HC10/HS2x/LS2x/QS2x blades.  The IPMI host interface
     driver ("ipmi-si") needs to be loaded for this driver to do anything.
     Prefix: 'ibmaem'
     Datasheet: Not available
diff -druN linux-libre-2.6.30-gnu/Documentation/hwmon/sysfs-interface linux-libre-2.6.31-gnu/Documentation/hwmon/sysfs-interface
--- linux-libre-2.6.30-gnu/Documentation/hwmon/sysfs-interface	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/hwmon/sysfs-interface	2009-09-09 18:13:59.000000000 -0400
@@ -70,6 +70,7 @@
 [0-*]	denotes any positive number starting from 0
 [1-*]	denotes any positive number starting from 1
 RO	read only value
+WO	write only value
 RW	read/write value
 
 Read/write values may be read-only for some chips, depending on the
@@ -295,6 +296,24 @@
 		user-space.
 		RO
 
+temp[1-*]_lowest
+		Historical minimum temperature
+		Unit: millidegree Celsius
+		RO
+
+temp[1-*]_highest
+		Historical maximum temperature
+		Unit: millidegree Celsius
+		RO
+
+temp[1-*]_reset_history
+		Reset temp_lowest and temp_highest
+		WO
+
+temp_reset_history
+		Reset temp_lowest and temp_highest for all sensors
+		WO
+
 Some chips measure temperature using external thermistors and an ADC, and
 report the temperature measurement as a voltage. Converting this voltage
 back to a temperature (or the other way around for limits) requires
diff -druN linux-libre-2.6.30-gnu/Documentation/hwmon/tmp401 linux-libre-2.6.31-gnu/Documentation/hwmon/tmp401
--- linux-libre-2.6.30-gnu/Documentation/hwmon/tmp401	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/hwmon/tmp401	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+Kernel driver tmp401
+====================
+
+Supported chips:
+  * Texas Instruments TMP401
+    Prefix: 'tmp401'
+    Addresses scanned: I2C 0x4c
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp401.html
+  * Texas Instruments TMP411
+    Prefix: 'tmp411'
+    Addresses scanned: I2C 0x4c
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp411.html
+
+Authors:
+         Hans de Goede <hdegoede@redhat.com>
+	 Andre Prendel <andre.prendel@gmx.de>
+
+Description
+-----------
+
+This driver implements support for Texas Instruments TMP401 and
+TMP411 chips. These chips implements one remote and one local
+temperature sensor. Temperature is measured in degrees
+Celsius. Resolution of the remote sensor is 0.0625 degree. Local
+sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not
+supported by the driver so far, so using the default resolution of 0.5
+degree).
+
+The driver provides the common sysfs-interface for temperatures (see
+/Documentation/hwmon/sysfs-interface under Temperatures).
+
+The TMP411 chip is compatible with TMP401. It provides some additional
+features.
+
+* Minimum and Maximum temperature measured since power-on, chip-reset
+
+  Exported via sysfs attributes tempX_lowest and tempX_highest.
+
+* Reset of historical minimum/maximum temperature measurements
+
+  Exported via sysfs attribute temp_reset_history. Writing 1 to this
+  file triggers a reset.
diff -druN linux-libre-2.6.30-gnu/Documentation/hwmon/w83627ehf linux-libre-2.6.31-gnu/Documentation/hwmon/w83627ehf
--- linux-libre-2.6.30-gnu/Documentation/hwmon/w83627ehf	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/hwmon/w83627ehf	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,10 @@
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet:
         http://www.nuvoton.com.tw/NR/rdonlyres/7885623D-A487-4CF9-A47F-30C5F73D6FE6/0/W83627DHG.pdf
+  * Winbond W83627DHG-P
+    Prefix: 'w83627dhg'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: not available
   * Winbond W83667HG
     Prefix: 'w83667hg'
     Addresses scanned: ISA address retrieved from Super I/O registers
@@ -28,8 +32,8 @@
 -----------
 
 This driver implements support for the Winbond W83627EHF, W83627EHG,
-W83627DHG and W83667HG super I/O chips. We will refer to them collectively
-as Winbond chips.
+W83627DHG, W83627DHG-P and W83667HG super I/O chips. We will refer to them
+collectively as Winbond chips.
 
 The chips implement three temperature sensors, five fan rotation
 speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
@@ -135,3 +139,6 @@
 The DHG also supports PECI, where the DHG queries Intel CPU temperatures, and
 the ICH8 southbridge gets that data via PECI from the DHG, so that the
 southbridge drives the fans. And the DHG supports SST, a one-wire serial bus.
+
+The DHG-P has an additional automatic fan speed control mode named Smart Fan
+(TM) III+. This mode is not yet supported by the driver.
diff -druN linux-libre-2.6.30-gnu/Documentation/i2c/busses/i2c-ocores linux-libre-2.6.31-gnu/Documentation/i2c/busses/i2c-ocores
--- linux-libre-2.6.30-gnu/Documentation/i2c/busses/i2c-ocores	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/i2c/busses/i2c-ocores	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,8 @@
 dev.platform_data of the device should also point to a struct
 ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the
 distance between registers and the input clock speed.
+There is also a possibility to attach a list of i2c_board_info which
+the i2c-ocores driver will add to the bus upon creation.
 
 E.G. something like:
 
@@ -36,9 +38,24 @@
 	},
 };
 
+/* optional board info */
+struct i2c_board_info ocores_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("tsc2003", 0x48),
+		.platform_data = &tsc2003_platform_data,
+		.irq = TSC_IRQ
+	},
+	{
+		I2C_BOARD_INFO("adv7180", 0x42 >> 1),
+		.irq = ADV_IRQ
+	}
+};
+
 static struct ocores_i2c_platform_data myi2c_data = {
 	.regstep	= 2,		/* two bytes between registers */
 	.clock_khz	= 50000,	/* input clock of 50MHz */
+	.devices	= ocores_i2c_board_info, /* optional table of devices */
+	.num_devices	= ARRAY_SIZE(ocores_i2c_board_info), /* table size */
 };
 
 static struct platform_device myi2c = {
diff -druN linux-libre-2.6.30-gnu/Documentation/i2c/busses/i2c-viapro linux-libre-2.6.31-gnu/Documentation/i2c/busses/i2c-viapro
--- linux-libre-2.6.30-gnu/Documentation/i2c/busses/i2c-viapro	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/i2c/busses/i2c-viapro	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,9 @@
   * VIA Technologies, Inc. VX800/VX820
     Datasheet: available on http://linux.via.com.tw
 
+  * VIA Technologies, Inc. VX855/VX875
+    Datasheet: Availability unknown
+
 Authors:
 	Kyösti Mälkki <kmalkki@cc.hut.fi>,
 	Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -53,6 +56,7 @@
  device 1106:3287   (VT8251)
  device 1106:8324   (CX700)
  device 1106:8353   (VX800/VX820)
+ device 1106:8409   (VX855/VX875)
 
 If none of these show up, you should look in the BIOS for settings like
 enable ACPI / SMBus or even USB.
diff -druN linux-libre-2.6.30-gnu/Documentation/i2c/instantiating-devices linux-libre-2.6.31-gnu/Documentation/i2c/instantiating-devices
--- linux-libre-2.6.30-gnu/Documentation/i2c/instantiating-devices	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/i2c/instantiating-devices	2009-09-09 18:13:59.000000000 -0400
@@ -165,3 +165,47 @@
 Once again, method 3 should be avoided wherever possible. Explicit device
 instantiation (methods 1 and 2) is much preferred for it is safer and
 faster.
+
+
+Method 4: Instantiate from user-space
+-------------------------------------
+
+In general, the kernel should know which I2C devices are connected and
+what addresses they live at. However, in certain cases, it does not, so a
+sysfs interface was added to let the user provide the information. This
+interface is made of 2 attribute files which are created in every I2C bus
+directory: new_device and delete_device. Both files are write only and you
+must write the right parameters to them in order to properly instantiate,
+respectively delete, an I2C device.
+
+File new_device takes 2 parameters: the name of the I2C device (a string)
+and the address of the I2C device (a number, typically expressed in
+hexadecimal starting with 0x, but can also be expressed in decimal.)
+
+File delete_device takes a single parameter: the address of the I2C
+device. As no two devices can live at the same address on a given I2C
+segment, the address is sufficient to uniquely identify the device to be
+deleted.
+
+Example:
+# echo eeprom 0x50 > /sys/class/i2c-adapter/i2c-3/new_device
+
+While this interface should only be used when in-kernel device declaration
+can't be done, there is a variety of cases where it can be helpful:
+* The I2C driver usually detects devices (method 3 above) but the bus
+  segment your device lives on doesn't have the proper class bit set and
+  thus detection doesn't trigger.
+* The I2C driver usually detects devices, but your device lives at an
+  unexpected address.
+* The I2C driver usually detects devices, but your device is not detected,
+  either because the detection routine is too strict, or because your
+  device is not officially supported yet but you know it is compatible.
+* You are developing a driver on a test board, where you soldered the I2C
+  device yourself.
+
+This interface is a replacement for the force_* module parameters some I2C
+drivers implement. Being implemented in i2c-core rather than in each
+device driver individually, it is much more efficient, and also has the
+advantage that you do not have to reload the driver to change a setting.
+You can also instantiate the device before the driver is loaded or even
+available, and you don't need to know what driver the device needs.
diff -druN linux-libre-2.6.30-gnu/Documentation/i2c/writing-clients linux-libre-2.6.31-gnu/Documentation/i2c/writing-clients
--- linux-libre-2.6.30-gnu/Documentation/i2c/writing-clients	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/i2c/writing-clients	2009-09-09 18:13:59.000000000 -0400
@@ -126,19 +126,9 @@
 that can't be distinguished by protocol probing, or which need some board
 specific information to operate correctly.
 
-Accordingly, the I2C stack now has two models for associating I2C devices
-with their drivers:  the original "legacy" model, and a newer one that's
-fully compatible with the Linux 2.6 driver model.  These models do not mix,
-since the "legacy" model requires drivers to create "i2c_client" device
-objects after SMBus style probing, while the Linux driver model expects
-drivers to be given such device objects in their probe() routines.
-
-The legacy model is deprecated now and will soon be removed, so we no
-longer document it here.
-
 
-Standard Driver Model Binding ("New Style")
--------------------------------------------
+Device/Driver Binding
+---------------------
 
 System infrastructure, typically board-specific initialization code or
 boot firmware, reports what I2C devices exist.  For example, there may be
@@ -201,7 +191,7 @@
 devices on a PC's SMBus.  In that case, you may want to let your driver
 detect supported devices automatically.  This is how the legacy model
 was working, and is now available as an extension to the standard
-driver model (so that we can finally get rid of the legacy model.)
+driver model.
 
 You simply have to define a detect callback which will attempt to
 identify supported devices (returning 0 for supported ones and -ENODEV
diff -druN linux-libre-2.6.30-gnu/Documentation/ide/ide.txt linux-libre-2.6.31-gnu/Documentation/ide/ide.txt
--- linux-libre-2.6.30-gnu/Documentation/ide/ide.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/ide/ide.txt	2009-09-09 18:13:59.000000000 -0400
@@ -216,6 +216,8 @@
 
 * "noflush=[interface_number.device_number]" to disable flush requests
 
+* "nohpa=[interface_number.device_number]" to disable Host Protected Area
+
 * "noprobe=[interface_number.device_number]" to skip probing
 
 * "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit
diff -druN linux-libre-2.6.30-gnu/Documentation/input/input.txt linux-libre-2.6.31-gnu/Documentation/input/input.txt
--- linux-libre-2.6.30-gnu/Documentation/input/input.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/input/input.txt	2009-09-09 18:13:59.000000000 -0400
@@ -278,7 +278,7 @@
 };
 
   'time' is the timestamp, it returns the time at which the event happened.
-Type is for example EV_REL for relative moment, REL_KEY for a keypress or
+Type is for example EV_REL for relative moment, EV_KEY for a keypress or
 release. More types are defined in include/linux/input.h.
 
   'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
diff -druN linux-libre-2.6.30-gnu/Documentation/input/rotary-encoder.txt linux-libre-2.6.31-gnu/Documentation/input/rotary-encoder.txt
--- linux-libre-2.6.30-gnu/Documentation/input/rotary-encoder.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/input/rotary-encoder.txt	2009-09-09 18:13:59.000000000 -0400
@@ -67,7 +67,12 @@
 struct rotary_encoder_platform_data is declared in
 include/linux/rotary-encoder.h and needs to be filled with the number of
 steps the encoder has and can carry information about externally inverted
-signals (because of used invertig buffer or other reasons).
+signals (because of an inverting buffer or other reasons). The encoder
+can be set up to deliver input information as either an absolute or relative
+axes. For relative axes the input event returns +/-1 for each step. For
+absolute axes the position of the encoder can either roll over between zero
+and the number of steps or will clamp at the maximum and zero depending on
+the configuration.
 
 Because GPIO to IRQ mapping is platform specific, this information must
 be given in seperately to the driver. See the example below.
@@ -85,6 +90,8 @@
 static struct rotary_encoder_platform_data my_rotary_encoder_info = {
 	.steps		= 24,
 	.axis		= ABS_X,
+	.relative_axis	= false,
+	.rollover	= false,
 	.gpio_a		= GPIO_ROTARY_A,
 	.gpio_b		= GPIO_ROTARY_B,
 	.inverted_a	= 0,
diff -druN linux-libre-2.6.30-gnu/Documentation/ioctl/ioctl-number.txt linux-libre-2.6.31-gnu/Documentation/ioctl/ioctl-number.txt
--- linux-libre-2.6.30-gnu/Documentation/ioctl/ioctl-number.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/ioctl/ioctl-number.txt	2009-09-09 18:13:59.000000000 -0400
@@ -139,6 +139,7 @@
 'm'	all	linux/synclink.h	conflict!
 'm'	00-1F	net/irda/irmod.h	conflict!
 'n'	00-7F	linux/ncp_fs.h
+'n'	80-8F	linux/nilfs2_fs.h	NILFS2
 'n'	E0-FF	video/matrox.h          matroxfb
 'o'	00-1F	fs/ocfs2/ocfs2_fs.h	OCFS2
 'o'     00-03   include/mtd/ubi-user.h  conflict! (OCFS2 and UBI overlaps)
@@ -149,6 +150,8 @@
 'p'	40-7F	linux/nvram.h
 'p'	80-9F				user-space parport
 					<mailto:tim@cyberelk.net>
+'p'	a1-a4	linux/pps.h		LinuxPPS
+					<mailto:giometti@linux.it>
 'q'	00-1F	linux/serio.h
 'q'	80-FF				Internet PhoneJACK, Internet LineJACK
 					<http://www.quicknet.net>
diff -druN linux-libre-2.6.30-gnu/Documentation/isdn/00-INDEX linux-libre-2.6.31-gnu/Documentation/isdn/00-INDEX
--- linux-libre-2.6.30-gnu/Documentation/isdn/00-INDEX	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/isdn/00-INDEX	2009-09-09 18:13:59.000000000 -0400
@@ -14,39 +14,37 @@
 	- general info on what you need and what to do for Linux ISDN.
 README.FAQ
 	- general info for FAQ.
+README.HiSax
+	- info on the HiSax driver which replaces the old teles.
+README.act2000
+	- info on driver for IBM ACT-2000 card.
 README.audio
 	- info for running audio over ISDN.
+README.avmb1
+	- info on driver for AVM-B1 ISDN card.
+README.concap
+	- info on "CONCAP" encapsulation protocol interface used for X.25.
+README.diversion
+	- info on module for isdn diversion services.
 README.fax
 	- info for using Fax over ISDN.
 README.gigaset
-	- info on the drivers for Siemens Gigaset ISDN adapters.
-README.icn
-	- info on the ICN-ISDN-card and its driver.
-README.HiSax
-	- info on the HiSax driver which replaces the old teles.
+	- info on the drivers for Siemens Gigaset ISDN adapters
 README.hfc-pci
 	- info on hfc-pci based cards.
+README.hysdn
+        - info on driver for Hypercope active HYSDN cards
+README.icn
+	- info on the ICN-ISDN-card and its driver.
+README.mISDN
+	- info on the Modular ISDN subsystem (mISDN)
 README.pcbit
 	- info on the PCBIT-D ISDN adapter and driver.
-README.syncppp
-	- info on running Sync PPP over ISDN.
-syncPPP.FAQ
-	- frequently asked questions about running PPP over ISDN.
-README.avmb1
-	- info on driver for AVM-B1 ISDN card.
-README.act2000
-	- info on driver for IBM ACT-2000 card.
-README.eicon
-	- info on driver for Eicon active cards.
-README.concap
-	- info on "CONCAP" encapsulation protocol interface used for X.25.
-README.diversion
-	- info on module for isdn diversion services.
 README.sc
 	- info on driver for Spellcaster cards.
+README.syncppp
+	- info on running Sync PPP over ISDN.
 README.x25
 	- info for running X.25 over ISDN.
-README.hysdn
-	- info on driver for Hypercope active HYSDN cards
-README.mISDN
-	- info on the Modular ISDN subsystem (mISDN).
+syncPPP.FAQ
+	- frequently asked questions about running PPP over ISDN.
diff -druN linux-libre-2.6.30-gnu/Documentation/isdn/INTERFACE.CAPI linux-libre-2.6.31-gnu/Documentation/isdn/INTERFACE.CAPI
--- linux-libre-2.6.30-gnu/Documentation/isdn/INTERFACE.CAPI	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/isdn/INTERFACE.CAPI	2009-09-09 18:13:59.000000000 -0400
@@ -45,7 +45,7 @@
 device.
 
 If the device becomes unusable for any reason (shutdown, disconnect ...), the
-driver has to call capi_ctr_reseted(). This will prevent further calls to the
+driver has to call capi_ctr_down(). This will prevent further calls to the
 callback functions by Kernel CAPI.
 
 
@@ -114,20 +114,36 @@
 int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata)
 	(optional) pointer to a callback function for sending firmware and
 	configuration data to the device
+	Return value: 0 on success, error code on error
+	Called in process context.
 
 void (*reset_ctr)(struct capi_ctr *ctrlr)
-	pointer to a callback function for performing a reset on the device,
-	releasing all registered applications
+	(optional) pointer to a callback function for performing a reset on
+	the device, releasing all registered applications
+	Called in process context.
 
 void (*register_appl)(struct capi_ctr *ctrlr, u16 applid,
 			capi_register_params *rparam)
 void (*release_appl)(struct capi_ctr *ctrlr, u16 applid)
 	pointers to callback functions for registration and deregistration of
 	applications with the device
+	Calls to these functions are serialized by Kernel CAPI so that only
+	one call to any of them is active at any time.
 
 u16  (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb)
 	pointer to a callback function for sending a CAPI message to the
 	device
+	Return value: CAPI error code
+	If the method returns 0 (CAPI_NOERROR) the driver has taken ownership
+	of the skb and the caller may no longer access it. If it returns a
+	non-zero (error) value then ownership of the skb returns to the caller
+	who may reuse or free it.
+	The return value should only be used to signal problems with respect
+	to accepting or queueing the message. Errors occurring during the
+	actual processing of the message should be signaled with an
+	appropriate reply message.
+	Calls to this function are not serialized by Kernel CAPI, ie. it must
+	be prepared to be re-entered.
 
 char *(*procinfo)(struct capi_ctr *ctrlr)
 	pointer to a callback function returning the entry for the device in
@@ -138,6 +154,8 @@
 	system entry, /proc/capi/controllers/<n>; will be called with a
 	pointer to the device's capi_ctr structure as the last (data) argument
 
+Note: Callback functions are never called in interrupt context.
+
 - to be filled in before calling capi_ctr_ready():
 
 u8 manu[CAPI_MANUFACTURER_LEN]
@@ -153,6 +171,45 @@
 	value to return for CAPI_GET_SERIAL
 
 
+4.3 The _cmsg Structure
+
+(declared in <linux/isdn/capiutil.h>)
+
+The _cmsg structure stores the contents of a CAPI 2.0 message in an easily
+accessible form. It contains members for all possible CAPI 2.0 parameters, of
+which only those appearing in the message type currently being processed are
+actually used. Unused members should be set to zero.
+
+Members are named after the CAPI 2.0 standard names of the parameters they
+represent. See <linux/isdn/capiutil.h> for the exact spelling. Member data
+types are:
+
+u8          for CAPI parameters of type 'byte'
+
+u16         for CAPI parameters of type 'word'
+
+u32         for CAPI parameters of type 'dword'
+
+_cstruct    for CAPI parameters of type 'struct' not containing any
+	    variably-sized (struct) subparameters (eg. 'Called Party Number')
+	    The member is a pointer to a buffer containing the parameter in
+	    CAPI encoding (length + content). It may also be NULL, which will
+	    be taken to represent an empty (zero length) parameter.
+
+_cmstruct   for CAPI parameters of type 'struct' containing 'struct'
+	    subparameters ('Additional Info' and 'B Protocol')
+	    The representation is a single byte containing one of the values:
+	    CAPI_DEFAULT: the parameter is empty
+	    CAPI_COMPOSE: the values of the subparameters are stored
+	    individually in the corresponding _cmsg structure members
+
+Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert
+messages between their transport encoding described in the CAPI 2.0 standard
+and their _cmsg structure representation. Note that capi_cmsg2message() does
+not know or check the size of its destination buffer. The caller must make
+sure it is big enough to accomodate the resulting CAPI message.
+
+
 5. Lower Layer Interface Functions
 
 (declared in <linux/isdn/capilli.h>)
@@ -166,7 +223,7 @@
 	register/unregister a device (controller) with Kernel CAPI
 
 void capi_ctr_ready(struct capi_ctr *ctrlr)
-void capi_ctr_reseted(struct capi_ctr *ctrlr)
+void capi_ctr_down(struct capi_ctr *ctrlr)
 	signal controller ready/not ready
 
 void capi_ctr_suspend_output(struct capi_ctr *ctrlr)
@@ -211,3 +268,32 @@
 							(u32)
 CAPIMSG_DATALEN(m)	CAPIMSG_SETDATALEN(m, len)	Data Length (u16)
 
+
+Library functions for working with _cmsg structures
+(from <linux/isdn/capiutil.h>):
+
+unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)
+	Assembles a CAPI 2.0 message from the parameters in *cmsg, storing the
+	result in *msg.
+
+unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)
+	Disassembles the CAPI 2.0 message in *msg, storing the parameters in
+	*cmsg.
+
+unsigned capi_cmsg_header(_cmsg *cmsg, u16 ApplId, u8 Command, u8 Subcommand,
+			  u16 Messagenumber, u32 Controller)
+	Fills the header part and address field of the _cmsg structure *cmsg
+	with the given values, zeroing the remainder of the structure so only
+	parameters with non-default values need to be changed before sending
+	the message.
+
+void capi_cmsg_answer(_cmsg *cmsg)
+	Sets the low bit of the Subcommand field in *cmsg, thereby converting
+	_REQ to _CONF and _IND to _RESP.
+
+char *capi_cmd2str(u8 Command, u8 Subcommand)
+	Returns the CAPI 2.0 message name corresponding to the given command
+	and subcommand values, as a static ASCII string. The return value may
+	be NULL if the command/subcommand is not one of those defined in the
+	CAPI 2.0 standard.
+
diff -druN linux-libre-2.6.30-gnu/Documentation/isdn/README.gigaset linux-libre-2.6.31-gnu/Documentation/isdn/README.gigaset
--- linux-libre-2.6.30-gnu/Documentation/isdn/README.gigaset	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/isdn/README.gigaset	2009-09-09 18:13:59.000000000 -0400
@@ -149,10 +149,8 @@
      configuration files and chat scripts in the gigaset-VERSION/ppp directory
      in the driver packages from http://sourceforge.net/projects/gigaset307x/.
      Please note that the USB drivers are not able to change the state of the
-     control lines (the M105 driver can be configured to use some undocumented
-     control requests, if you really need the control lines, though). This means
-     you must use "Stupid Mode" if you are using wvdial or you should use the
-     nocrtscts option of pppd.
+     control lines. This means you must use "Stupid Mode" if you are using
+     wvdial or you should use the nocrtscts option of pppd.
      You must also assure that the ppp_async module is loaded with the parameter
      flag_time=0. You can do this e.g. by adding a line like
 
@@ -190,20 +188,19 @@
      You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
      setting (ttyGxy is ttyGU0 or ttyGB0).
 
-2.6. M105 Undocumented USB Requests
-     ------------------------------
-
-     The Gigaset M105 USB data box understands a couple of useful, but
-     undocumented USB commands. These requests are not used in normal
-     operation (for wireless access to the base), but are needed for access
-     to the M105's own configuration mode (registration to the base, baudrate
-     and line format settings, device status queries) via the gigacontr
-     utility. Their use is controlled by the kernel configuration option
-     "Support for undocumented USB requests" (CONFIG_GIGASET_UNDOCREQ). If you
-     encounter error code -ENOTTY when trying to use some features of the
-     M105, try setting that option to "y" via 'make {x,menu}config' and
-     recompiling the driver.
+2.6. Unregistered Wireless Devices (M101/M105)
+     -----------------------------------------
+     The main purpose of the ser_gigaset and usb_gigaset drivers is to allow
+     the M101 and M105 wireless devices to be used as ISDN devices for ISDN
+     connections through a Gigaset base. Therefore they assume that the device
+     is registered to a DECT base.
 
+     If the M101/M105 device is not registered to a base, initialization of
+     the device fails, and a corresponding error message is logged by the
+     driver. In that situation, a restricted set of functions is available
+     which includes, in particular, those necessary for registering the device
+     to a base or for switching it between Fixed Part and Portable Part
+     modes.
 
 3.   Troubleshooting
      ---------------
@@ -234,11 +231,12 @@
         Select Unimodem mode for all DECT data adapters. (see section 2.4.)
 
      Problem:
-        You want to configure your USB DECT data adapter (M105) but gigacontr
-        reports an error: "/dev/ttyGU0: Inappropriate ioctl for device".
+	Messages like this:
+	    usb_gigaset 3-2:1.0: Could not initialize the device.
+	appear in your syslog.
      Solution:
-        Recompile the usb_gigaset driver with the kernel configuration option
-        CONFIG_GIGASET_UNDOCREQ set to 'y'. (see section 2.6.)
+	Check whether your M10x wireless device is correctly registered to the
+	Gigaset base. (see section 2.6.)
 
 3.2. Telling the driver to provide more information
      ----------------------------------------------
diff -druN linux-libre-2.6.30-gnu/Documentation/ja_JP/SubmitChecklist linux-libre-2.6.31-gnu/Documentation/ja_JP/SubmitChecklist
--- linux-libre-2.6.30-gnu/Documentation/ja_JP/SubmitChecklist	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/ja_JP/SubmitChecklist	2009-09-09 18:13:59.000000000 -0400
@@ -75,7 +75,7 @@
     ビルドした上、動作確認を行ってください。
 
 14: もしパッチがディスクのI/O性能などに影響を与えるようであれば、
-    'CONFIG_LBD'オプションを有効にした場合と無効にした場合の両方で
+    'CONFIG_LBDAF'オプションを有効にした場合と無効にした場合の両方で
     テストを実施してみてください。
 
 15: lockdepの機能を全て有効にした上で、全てのコードパスを評価してください。
diff -druN linux-libre-2.6.30-gnu/Documentation/kbuild/kconfig.txt linux-libre-2.6.31-gnu/Documentation/kbuild/kconfig.txt
--- linux-libre-2.6.30-gnu/Documentation/kbuild/kconfig.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/kbuild/kconfig.txt	2009-09-09 18:13:59.000000000 -0400
@@ -35,48 +35,26 @@
 
 (Yes, we need something better here.)
 
-
-======================================================================
-menuconfig
---------------------------------------------------
-
-SEARCHING for CONFIG symbols
-
-Searching in menuconfig:
-
-	The Search function searches for kernel configuration symbol
-	names, so you have to know something close to what you are
-	looking for.
-
-	Example:
-		/hotplug
-		This lists all config symbols that contain "hotplug",
-		e.g., HOTPLUG, HOTPLUG_CPU, MEMORY_HOTPLUG.
-
-	For search help, enter / followed TAB-TAB-TAB (to highlight
-	<Help>) and Enter.  This will tell you that you can also use
-	regular expressions (regexes) in the search string, so if you
-	are not interested in MEMORY_HOTPLUG, you could try
-
-		/^hotplug
-
-
 ______________________________________________________________________
-Color Themes for 'menuconfig'
+Environment variables for '*config'
 
-It is possible to select different color themes using the variable
-MENUCONFIG_COLOR.  To select a theme use:
+KCONFIG_CONFIG
+--------------------------------------------------
+This environment variable can be used to specify a default kernel config
+file name to override the default name of ".config".
 
-	make MENUCONFIG_COLOR=<theme> menuconfig
+KCONFIG_OVERWRITECONFIG
+--------------------------------------------------
+If you set KCONFIG_OVERWRITECONFIG in the environment, Kconfig will not
+break symlinks when .config is a symlink to somewhere else.
 
-Available themes are:
-  mono       => selects colors suitable for monochrome displays
-  blackbg    => selects a color scheme with black background
-  classic    => theme with blue background. The classic look
-  bluetitle  => a LCD friendly version of classic. (default)
+KCONFIG_NOTIMESTAMP
+--------------------------------------------------
+If this environment variable exists and is non-null, the timestamp line
+in generated .config files is omitted.
 
 ______________________________________________________________________
-Environment variables in 'menuconfig'
+Environment variables for '{allyes/allmod/allno/rand}config'
 
 KCONFIG_ALLCONFIG
 --------------------------------------------------
@@ -95,8 +73,7 @@
 This enables you to create "miniature" config (miniconfig) or custom
 config files containing just the config symbols that you are interested
 in.  Then the kernel config system generates the full .config file,
-including dependencies of your miniconfig file, based on the miniconfig
-file.
+including symbols of your miniconfig file.
 
 This 'KCONFIG_ALLCONFIG' file is a config file which contains
 (usually a subset of all) preset config symbols.  These variable
@@ -113,26 +90,14 @@
 disable the options that are explicitly listed in the specified
 mini-config files.
 
+______________________________________________________________________
+Environment variables for 'silentoldconfig'
+
 KCONFIG_NOSILENTUPDATE
 --------------------------------------------------
 If this variable has a non-blank value, it prevents silent kernel
 config udpates (requires explicit updates).
 
-KCONFIG_CONFIG
---------------------------------------------------
-This environment variable can be used to specify a default kernel config
-file name to override the default name of ".config".
-
-KCONFIG_OVERWRITECONFIG
---------------------------------------------------
-If you set KCONFIG_OVERWRITECONFIG in the environment, Kconfig will not
-break symlinks when .config is a symlink to somewhere else.
-
-KCONFIG_NOTIMESTAMP
---------------------------------------------------
-If this environment variable exists and is non-null, the timestamp line
-in generated .config files is omitted.
-
 KCONFIG_AUTOCONFIG
 --------------------------------------------------
 This environment variable can be set to specify the path & name of the
@@ -143,15 +108,54 @@
 This environment variable can be set to specify the path & name of the
 "autoconf.h" (header) file.  Its default value is "include/linux/autoconf.h".
 
+
+======================================================================
+menuconfig
+--------------------------------------------------
+
+SEARCHING for CONFIG symbols
+
+Searching in menuconfig:
+
+	The Search function searches for kernel configuration symbol
+	names, so you have to know something close to what you are
+	looking for.
+
+	Example:
+		/hotplug
+		This lists all config symbols that contain "hotplug",
+		e.g., HOTPLUG, HOTPLUG_CPU, MEMORY_HOTPLUG.
+
+	For search help, enter / followed TAB-TAB-TAB (to highlight
+	<Help>) and Enter.  This will tell you that you can also use
+	regular expressions (regexes) in the search string, so if you
+	are not interested in MEMORY_HOTPLUG, you could try
+
+		/^hotplug
+
 ______________________________________________________________________
-menuconfig User Interface Options
-----------------------------------------------------------------------
+User interface options for 'menuconfig'
+
+MENUCONFIG_COLOR
+--------------------------------------------------
+It is possible to select different color themes using the variable
+MENUCONFIG_COLOR.  To select a theme use:
+
+	make MENUCONFIG_COLOR=<theme> menuconfig
+
+Available themes are:
+  mono       => selects colors suitable for monochrome displays
+  blackbg    => selects a color scheme with black background
+  classic    => theme with blue background. The classic look
+  bluetitle  => a LCD friendly version of classic. (default)
+
 MENUCONFIG_MODE
 --------------------------------------------------
 This mode shows all sub-menus in one large tree.
 
 Example:
-	MENUCONFIG_MODE=single_menu make menuconfig
+	make MENUCONFIG_MODE=single_menu menuconfig
+
 
 ======================================================================
 xconfig
diff -druN linux-libre-2.6.30-gnu/Documentation/kbuild/modules.txt linux-libre-2.6.31-gnu/Documentation/kbuild/modules.txt
--- linux-libre-2.6.30-gnu/Documentation/kbuild/modules.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/kbuild/modules.txt	2009-09-09 18:13:59.000000000 -0400
@@ -275,7 +275,7 @@
 
 		KERNELDIR := /lib/modules/`uname -r`/build
 		all::
-			$(MAKE) -C $KERNELDIR M=`pwd` $@
+			$(MAKE) -C $(KERNELDIR) M=`pwd` $@
 
 		# Module specific targets
 		genbin:
diff -druN linux-libre-2.6.30-gnu/Documentation/kdump/kdump.txt linux-libre-2.6.31-gnu/Documentation/kdump/kdump.txt
--- linux-libre-2.6.30-gnu/Documentation/kdump/kdump.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/kdump/kdump.txt	2009-09-09 18:13:59.000000000 -0400
@@ -108,7 +108,7 @@
 
 2) Or use the system kernel binary itself as dump-capture kernel and there is
    no need to build a separate dump-capture kernel. This is possible
-   only with the architecutres which support a relocatable kernel. As
+   only with the architectures which support a relocatable kernel. As
    of today, i386, x86_64, ppc64 and ia64 architectures support relocatable
    kernel.
 
@@ -222,7 +222,7 @@
 ----------------------------------------------------------
 
 - No specific options are required to create a dump-capture kernel
-  for ia64, other than those specified in the arch idependent section
+  for ia64, other than those specified in the arch independent section
   above. This means that it is possible to use the system kernel
   as a dump-capture kernel if desired.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/kernel-parameters.txt linux-libre-2.6.31-gnu/Documentation/kernel-parameters.txt
--- linux-libre-2.6.30-gnu/Documentation/kernel-parameters.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/kernel-parameters.txt	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,7 @@
 	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
 	FB	The frame buffer device is enabled.
+	GCOV	GCOV profiling is enabled.
 	HW	Appropriate hardware is enabled.
 	IA-64	IA-64 architecture is enabled.
 	IMA     Integrity measurement architecture is enabled.
@@ -56,7 +57,6 @@
 	ISAPNP	ISA PnP code is enabled.
 	ISDN	Appropriate ISDN support is enabled.
 	JOY	Appropriate joystick support is enabled.
-	KMEMTRACE kmemtrace is enabled.
 	LIBATA  Libata driver is enabled
 	LP	Printer support is enabled.
 	LOOP	Loopback device support is enabled.
@@ -229,14 +229,6 @@
 			to assume that this machine's pmtimer latches its value
 			and always returns good values.
 
- 	acpi.power_nocheck=	[HW,ACPI]
- 			Format: 1/0 enable/disable the check of power state.
- 			On some bogus BIOS the _PSC object/_STA object of
- 			power resource can't return the correct device power
- 			state. In such case it is unneccessary to check its
- 			power state again in power transition.
- 			1 : disable the power state check
-
 	acpi_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
 			Format: { level | edge | high | low }
 
@@ -329,11 +321,6 @@
 				    flushed before they will be reused, which
 				    is a lot of faster
 
-	amd_iommu_size= [HW,X86-64]
-			Define the size of the aperture for the AMD IOMMU
-			driver. Possible values are:
-			'32M', '64M' (default), '128M', '256M', '512M', '1G'
-
 	amijoy.map=	[HW,JOY] Amiga joystick support
 			Map of devices attached to JOY0DAT and JOY1DAT
 			Format: <a>,<b>
@@ -497,6 +484,13 @@
 			Also note the kernel might malfunction if you disable
 			some critical bits.
 
+	cmo_free_hint=	[PPC] Format: { yes | no }
+			Specify whether pages are marked as being inactive
+			when they are freed.  This is used in CMO environments
+			to determine OS memory pressure for page stealing by
+			a hypervisor.
+			Default: yes
+
 	code_bytes	[X86] How many bytes of object code to print
 			in an oops report.
 			Range: 0 - 8192
@@ -545,6 +539,10 @@
 			console=brl,ttyS0
 		For now, only VisioBraille is supported.
 
+	consoleblank=	[KNL] The console blank (screen saver) timeout in
+			seconds. Defaults to 10*60 = 10mins. A value of 0
+			disables the blank timer.
+
 	coredump_filter=
 			[KNL] Change the default value for
 			/proc/<pid>/coredump_filter.
@@ -646,6 +644,13 @@
 			DMA-API debugging code disables itself because the
 			architectural default is too low.
 
+	dma_debug_driver=<driver_name>
+			With this option the DMA-API debugging driver
+			filter feature can be enabled at boot time. Just
+			pass the driver to filter for as the parameter.
+			The filter can be disabled or changed to another
+			driver later using sysfs.
+
 	dscc4.setup=	[NET]
 
 	dtc3181e=	[HW,SCSI]
@@ -752,12 +757,25 @@
 			ia64_pal_cache_flush instead of SAL_CACHE_FLUSH.
 
 	ftrace=[tracer]
-			[ftrace] will set and start the specified tracer
+			[FTRACE] will set and start the specified tracer
 			as early as possible in order to facilitate early
 			boot debugging.
 
 	ftrace_dump_on_oops
-			[ftrace] will dump the trace buffers on oops.
+			[FTRACE] will dump the trace buffers on oops.
+
+	ftrace_filter=[function-list]
+			[FTRACE] Limit the functions traced by the function
+			tracer at boot up. function-list is a comma separated
+			list of functions. This list can be changed at run
+			time by the set_ftrace_filter file in the debugfs
+			tracing directory. 
+
+	ftrace_notrace=[function-list]
+			[FTRACE] Do not trace the functions specified in
+			function-list. This list can be changed at run time
+			by the set_ftrace_notrace file in the debugfs
+			tracing directory.
 
 	gamecon.map[2|3]=
 			[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
@@ -771,6 +789,12 @@
 			Format: off | on
 			default: on
 
+	gcov_persist=	[GCOV] When non-zero (default), profiling data for
+			kernel modules is saved and remains accessible via
+			debugfs, even when the module is unloaded/reloaded.
+			When zero, profiling data is discarded and associated
+			debugfs files are removed at module unload time.
+
 	gdth=		[HW,SCSI]
 			See header of drivers/scsi/gdth.c.
 
@@ -873,11 +897,8 @@
 
 	ide-core.nodma=	[HW] (E)IDE subsystem
 			Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc
-			.vlb_clock .pci_clock .noflush .noprobe .nowerr .cdrom
-			.chs .ignore_cable are additional options
-			See Documentation/ide/ide.txt.
-
-	idebus=		[HW] (E)IDE subsystem - VLB/PCI bus speed
+			.vlb_clock .pci_clock .noflush .nohpa .noprobe .nowerr
+			.cdrom .chs .ignore_cable are additional options
 			See Documentation/ide/ide.txt.
 
 	ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
@@ -914,6 +935,12 @@
 			Formt: { "sha1" | "md5" }
 			default: "sha1"
 
+	ima_tcb		[IMA]
+			Load a policy which meets the needs of the Trusted
+			Computing Base.  This means IMA will measure all
+			programs exec'd, files mmap'd for exec, and all files
+			opened for read by uid=0.
+
 	in2000=		[HW,SCSI]
 			See header of drivers/scsi/in2000.c.
 
@@ -971,6 +998,7 @@
 		nomerge
 		forcesac
 		soft
+		pt	[x86, IA64]
 
 	io7=		[HW] IO7 for Marvel based alpha systems
 			See comment before marvel_specify_io7 in
@@ -1054,24 +1082,19 @@
 			use the HighMem zone if it exists, and the Normal
 			zone if it does not.
 
-	kmemtrace.enable=	[KNL,KMEMTRACE] Format: { yes | no }
-				Controls whether kmemtrace is enabled
-				at boot-time.
-
-	kmemtrace.subbufs=n	[KNL,KMEMTRACE] Overrides the number of
-			subbufs kmemtrace's relay channel has. Set this
-			higher than default (KMEMTRACE_N_SUBBUFS in code) if
-			you experience buffer overruns.
-
 	kgdboc=		[HW] kgdb over consoles.
 			Requires a tty driver that supports console polling.
-			(only serial suported for now)
+			(only serial supported for now)
 			Format: <serial_device>[,baud]
 
 	kmac=		[MIPS] korina ethernet MAC address.
 			Configure the RouterBoard 532 series on-chip
 			Ethernet adapter MAC address.
 
+	kmemleak=	[KNL] Boot-time kmemleak enable/disable
+			Valid arguments: on, off
+			Default: on
+
 	kstack=N	[X86] Print N words from the kernel stack
 			in oops dumps.
 
@@ -1092,6 +1115,10 @@
 			libata.dma=4	  Compact Flash DMA only 
 			Combinations also work, so libata.dma=3 enables DMA
 			for disks and CDROMs, but not CFs.
+	
+	libata.ignore_hpa=	[LIBATA] Ignore HPA limit
+			libata.ignore_hpa=0	  keep BIOS limits (default)
+			libata.ignore_hpa=1	  ignore limits, using full disk
 
 	libata.noacpi	[LIBATA] Disables use of ACPI in libata suspend/resume
 			when set.
@@ -1339,6 +1366,27 @@
 	min_addr=nn[KMG]	[KNL,BOOT,ia64] All physical memory below this
 			physical address is ignored.
 
+	mini2440=	[ARM,HW,KNL]
+			Format:[0..2][b][c][t]
+			Default: "0tb"
+			MINI2440 configuration specification:
+			0 - The attached screen is the 3.5" TFT
+			1 - The attached screen is the 7" TFT
+			2 - The VGA Shield is attached (1024x768)
+			Leaving out the screen size parameter will not load
+			the TFT driver, and the framebuffer will be left
+			unconfigured.
+			b - Enable backlight. The TFT backlight pin will be
+			linked to the kernel VESA blanking code and a GPIO
+			LED. This parameter is not necessary when using the
+			VGA shield.
+			c - Enable the s3c camera interface.
+			t - Reserved for enabling touchscreen support. The
+			touchscreen support is not enabled in the mainstream
+			kernel as of 2.6.30, a preliminary port can be found
+			in the "bleeding edge" mini2440 support kernel at
+			http://repo.or.cz/w/linux-2.6/mini2440.git
+
 	mminit_loglevel=
 			[KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
 			parameter allows control of the logging verbosity for
@@ -1380,6 +1428,16 @@
 	mtdparts=	[MTD]
 			See drivers/mtd/cmdlinepart.c.
 
+	onenand.bdry=	[HW,MTD] Flex-OneNAND Boundary Configuration
+
+			Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock]
+
+			boundary - index of last SLC block on Flex-OneNAND.
+				   The remaining blocks are configured as MLC blocks.
+			lock	 - Configure if Flex-OneNAND boundary should be locked.
+				   Once locked, the boundary cannot be changed.
+				   1 indicates lock status, 0 indicates unlock status.
+
 	mtdset=		[ARM]
 			ARM/S3C2412 JIVE boot control
 
@@ -1390,7 +1448,7 @@
 			('y', default) or cooked coordinates ('n')
 
 	mtrr_chunk_size=nn[KMG] [X86]
-			used for mtrr cleanup. It is largest continous chunk
+			used for mtrr cleanup. It is largest continuous chunk
 			that could hold holes aka. UC entries.
 
 	mtrr_gran_size=nn[KMG] [X86]
@@ -1575,6 +1633,9 @@
 	noinitrd	[RAM] Tells the kernel not to load any configured
 			initial RAM disk.
 
+	nointremap	[X86-64, Intel-IOMMU] Do not enable interrupt
+			remapping.
+
 	nointroute	[IA-64]
 
 	nojitter	[IA64] Disables jitter checking for ITC timers.
@@ -1660,6 +1721,14 @@
 	oprofile.timer=	[HW]
 			Use timer interrupt instead of performance counters
 
+	oprofile.cpu_type=	Force an oprofile cpu type
+			This might be useful if you have an older oprofile
+			userland or if you want common events.
+			Format: { arch_perfmon }
+			arch_perfmon: [X86] Force use of architectural
+				perfmon on Intel CPUs instead of the
+				CPU specific event set.
+
 	osst=		[HW,SCSI] SCSI Tape Driver
 			Format: <buffer_size>,<write_threshold>
 			See also Documentation/scsi/st.txt.
@@ -1735,6 +1804,9 @@
 				root domains (aka PCI segments, in ACPI-speak).
 		nommconf	[X86] Disable use of MMCONFIG for PCI
 				Configuration
+		check_enable_amd_mmconf [X86] check for and enable
+				properly configured MMIO access to PCI
+				config space on AMD family 10h CPU
 		nomsi		[MSI] If the PCI_MSI kernel config parameter is
 				enabled, this kernel boot option can be used to
 				disable the use of MSI interrupts system-wide.
@@ -1824,6 +1896,12 @@
 				PAGE_SIZE is used as alignment.
 				PCI-PCI bridge can be specified, if resource
 				windows need to be expanded.
+		ecrc=		Enable/disable PCIe ECRC (transaction layer
+				end-to-end CRC checking).
+				bios: Use BIOS/firmware settings. This is the
+				the default.
+				off: Turn ECRC off
+				on: Turn ECRC on.
 
 	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
 			Management.
@@ -1841,6 +1919,12 @@
 			Format: { 0 | 1 }
 			See arch/parisc/kernel/pdc_chassis.c
 
+	percpu_alloc=	[X86] Select which percpu first chunk allocator to use.
+			Allowed values are one of "lpage", "embed" and "4k".
+			See comments in arch/x86/kernel/setup_percpu.c for
+			details on each allocator.  This parameter is primarily
+			for debugging and performance comparison.
+
 	pf.		[PARIDE]
 			See Documentation/blockdev/paride.txt.
 
@@ -2393,7 +2477,8 @@
 
 	tp720=		[HW,PS2]
 
-	trace_buf_size=nn[KMG] [ftrace] will set tracing buffer size.
+	trace_buf_size=nn[KMG]
+			[FTRACE] will set tracing buffer size.
 
 	trix=		[HW,OSS] MediaTrix AudioTrix Pro
 			Format:
diff -druN linux-libre-2.6.30-gnu/Documentation/kmemcheck.txt linux-libre-2.6.31-gnu/Documentation/kmemcheck.txt
--- linux-libre-2.6.30-gnu/Documentation/kmemcheck.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/kmemcheck.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,773 @@
+GETTING STARTED WITH KMEMCHECK
+==============================
+
+Vegard Nossum <vegardno@ifi.uio.no>
+
+
+Contents
+========
+0. Introduction
+1. Downloading
+2. Configuring and compiling
+3. How to use
+3.1. Booting
+3.2. Run-time enable/disable
+3.3. Debugging
+3.4. Annotating false positives
+4. Reporting errors
+5. Technical description
+
+
+0. Introduction
+===============
+
+kmemcheck is a debugging feature for the Linux Kernel. More specifically, it
+is a dynamic checker that detects and warns about some uses of uninitialized
+memory.
+
+Userspace programmers might be familiar with Valgrind's memcheck. The main
+difference between memcheck and kmemcheck is that memcheck works for userspace
+programs only, and kmemcheck works for the kernel only. The implementations
+are of course vastly different. Because of this, kmemcheck is not as accurate
+as memcheck, but it turns out to be good enough in practice to discover real
+programmer errors that the compiler is not able to find through static
+analysis.
+
+Enabling kmemcheck on a kernel will probably slow it down to the extent that
+the machine will not be usable for normal workloads such as e.g. an
+interactive desktop. kmemcheck will also cause the kernel to use about twice
+as much memory as normal. For this reason, kmemcheck is strictly a debugging
+feature.
+
+
+1. Downloading
+==============
+
+kmemcheck can only be downloaded using git. If you want to write patches
+against the current code, you should use the kmemcheck development branch of
+the tip tree. It is also possible to use the linux-next tree, which also
+includes the latest version of kmemcheck.
+
+Assuming that you've already cloned the linux-2.6.git repository, all you
+have to do is add the -tip tree as a remote, like this:
+
+	$ git remote add tip git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git
+
+To actually download the tree, fetch the remote:
+
+	$ git fetch tip
+
+And to check out a new local branch with the kmemcheck code:
+
+	$ git checkout -b kmemcheck tip/kmemcheck
+
+General instructions for the -tip tree can be found here:
+http://people.redhat.com/mingo/tip.git/readme.txt
+
+
+2. Configuring and compiling
+============================
+
+kmemcheck only works for the x86 (both 32- and 64-bit) platform. A number of
+configuration variables must have specific settings in order for the kmemcheck
+menu to even appear in "menuconfig". These are:
+
+  o CONFIG_CC_OPTIMIZE_FOR_SIZE=n
+
+	This option is located under "General setup" / "Optimize for size".
+
+	Without this, gcc will use certain optimizations that usually lead to
+	false positive warnings from kmemcheck. An example of this is a 16-bit
+	field in a struct, where gcc may load 32 bits, then discard the upper
+	16 bits. kmemcheck sees only the 32-bit load, and may trigger a
+	warning for the upper 16 bits (if they're uninitialized).
+
+  o CONFIG_SLAB=y or CONFIG_SLUB=y
+
+	This option is located under "General setup" / "Choose SLAB
+	allocator".
+
+  o CONFIG_FUNCTION_TRACER=n
+
+	This option is located under "Kernel hacking" / "Tracers" / "Kernel
+	Function Tracer"
+
+	When function tracing is compiled in, gcc emits a call to another
+	function at the beginning of every function. This means that when the
+	page fault handler is called, the ftrace framework will be called
+	before kmemcheck has had a chance to handle the fault. If ftrace then
+	modifies memory that was tracked by kmemcheck, the result is an
+	endless recursive page fault.
+
+  o CONFIG_DEBUG_PAGEALLOC=n
+
+	This option is located under "Kernel hacking" / "Debug page memory
+	allocations".
+
+In addition, I highly recommend turning on CONFIG_DEBUG_INFO=y. This is also
+located under "Kernel hacking". With this, you will be able to get line number
+information from the kmemcheck warnings, which is extremely valuable in
+debugging a problem. This option is not mandatory, however, because it slows
+down the compilation process and produces a much bigger kernel image.
+
+Now the kmemcheck menu should be visible (under "Kernel hacking" / "kmemcheck:
+trap use of uninitialized memory"). Here follows a description of the
+kmemcheck configuration variables:
+
+  o CONFIG_KMEMCHECK
+
+	This must be enabled in order to use kmemcheck at all...
+
+  o CONFIG_KMEMCHECK_[DISABLED | ENABLED | ONESHOT]_BY_DEFAULT
+
+	This option controls the status of kmemcheck at boot-time. "Enabled"
+	will enable kmemcheck right from the start, "disabled" will boot the
+	kernel as normal (but with the kmemcheck code compiled in, so it can
+	be enabled at run-time after the kernel has booted), and "one-shot" is
+	a special mode which will turn kmemcheck off automatically after
+	detecting the first use of uninitialized memory.
+
+	If you are using kmemcheck to actively debug a problem, then you
+	probably want to choose "enabled" here.
+
+	The one-shot mode is mostly useful in automated test setups because it
+	can prevent floods of warnings and increase the chances of the machine
+	surviving in case something is really wrong. In other cases, the one-
+	shot mode could actually be counter-productive because it would turn
+	itself off at the very first error -- in the case of a false positive
+	too -- and this would come in the way of debugging the specific
+	problem you were interested in.
+
+	If you would like to use your kernel as normal, but with a chance to
+	enable kmemcheck in case of some problem, it might be a good idea to
+	choose "disabled" here. When kmemcheck is disabled, most of the run-
+	time overhead is not incurred, and the kernel will be almost as fast
+	as normal.
+
+  o CONFIG_KMEMCHECK_QUEUE_SIZE
+
+	Select the maximum number of error reports to store in an internal
+	(fixed-size) buffer. Since errors can occur virtually anywhere and in
+	any context, we need a temporary storage area which is guaranteed not
+	to generate any other page faults when accessed. The queue will be
+	emptied as soon as a tasklet may be scheduled. If the queue is full,
+	new error reports will be lost.
+
+	The default value of 64 is probably fine. If some code produces more
+	than 64 errors within an irqs-off section, then the code is likely to
+	produce many, many more, too, and these additional reports seldom give
+	any more information (the first report is usually the most valuable
+	anyway).
+
+	This number might have to be adjusted if you are not using serial
+	console or similar to capture the kernel log. If you are using the
+	"dmesg" command to save the log, then getting a lot of kmemcheck
+	warnings might overflow the kernel log itself, and the earlier reports
+	will get lost in that way instead. Try setting this to 10 or so on
+	such a setup.
+
+  o CONFIG_KMEMCHECK_SHADOW_COPY_SHIFT
+
+	Select the number of shadow bytes to save along with each entry of the
+	error-report queue. These bytes indicate what parts of an allocation
+	are initialized, uninitialized, etc. and will be displayed when an
+	error is detected to help the debugging of a particular problem.
+
+	The number entered here is actually the logarithm of the number of
+	bytes that will be saved. So if you pick for example 5 here, kmemcheck
+	will save 2^5 = 32 bytes.
+
+	The default value should be fine for debugging most problems. It also
+	fits nicely within 80 columns.
+
+  o CONFIG_KMEMCHECK_PARTIAL_OK
+
+	This option (when enabled) works around certain GCC optimizations that
+	produce 32-bit reads from 16-bit variables where the upper 16 bits are
+	thrown away afterwards.
+
+	The default value (enabled) is recommended. This may of course hide
+	some real errors, but disabling it would probably produce a lot of
+	false positives.
+
+  o CONFIG_KMEMCHECK_BITOPS_OK
+
+	This option silences warnings that would be generated for bit-field
+	accesses where not all the bits are initialized at the same time. This
+	may also hide some real bugs.
+
+	This option is probably obsolete, or it should be replaced with
+	the kmemcheck-/bitfield-annotations for the code in question. The
+	default value is therefore fine.
+
+Now compile the kernel as usual.
+
+
+3. How to use
+=============
+
+3.1. Booting
+============
+
+First some information about the command-line options. There is only one
+option specific to kmemcheck, and this is called "kmemcheck". It can be used
+to override the default mode as chosen by the CONFIG_KMEMCHECK_*_BY_DEFAULT
+option. Its possible settings are:
+
+  o kmemcheck=0 (disabled)
+  o kmemcheck=1 (enabled)
+  o kmemcheck=2 (one-shot mode)
+
+If SLUB debugging has been enabled in the kernel, it may take precedence over
+kmemcheck in such a way that the slab caches which are under SLUB debugging
+will not be tracked by kmemcheck. In order to ensure that this doesn't happen
+(even though it shouldn't by default), use SLUB's boot option "slub_debug",
+like this: slub_debug=-
+
+In fact, this option may also be used for fine-grained control over SLUB vs.
+kmemcheck. For example, if the command line includes "kmemcheck=1
+slub_debug=,dentry", then SLUB debugging will be used only for the "dentry"
+slab cache, and with kmemcheck tracking all the other caches. This is advanced
+usage, however, and is not generally recommended.
+
+
+3.2. Run-time enable/disable
+============================
+
+When the kernel has booted, it is possible to enable or disable kmemcheck at
+run-time. WARNING: This feature is still experimental and may cause false
+positive warnings to appear. Therefore, try not to use this. If you find that
+it doesn't work properly (e.g. you see an unreasonable amount of warnings), I
+will be happy to take bug reports.
+
+Use the file /proc/sys/kernel/kmemcheck for this purpose, e.g.:
+
+	$ echo 0 > /proc/sys/kernel/kmemcheck # disables kmemcheck
+
+The numbers are the same as for the kmemcheck= command-line option.
+
+
+3.3. Debugging
+==============
+
+A typical report will look something like this:
+
+WARNING: kmemcheck: Caught 32-bit read from uninitialized memory (ffff88003e4a2024)
+80000000000000000000000000000000000000000088ffff0000000000000000
+ i i i i u u u u i i i i i i i i u u u u u u u u u u u u u u u u
+         ^
+
+Pid: 1856, comm: ntpdate Not tainted 2.6.29-rc5 #264 945P-A
+RIP: 0010:[<ffffffff8104ede8>]  [<ffffffff8104ede8>] __dequeue_signal+0xc8/0x190
+RSP: 0018:ffff88003cdf7d98  EFLAGS: 00210002
+RAX: 0000000000000030 RBX: ffff88003d4ea968 RCX: 0000000000000009
+RDX: ffff88003e5d6018 RSI: ffff88003e5d6024 RDI: ffff88003cdf7e84
+RBP: ffff88003cdf7db8 R08: ffff88003e5d6000 R09: 0000000000000000
+R10: 0000000000000080 R11: 0000000000000000 R12: 000000000000000e
+R13: ffff88003cdf7e78 R14: ffff88003d530710 R15: ffff88003d5a98c8
+FS:  0000000000000000(0000) GS:ffff880001982000(0063) knlGS:00000
+CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
+CR2: ffff88003f806ea0 CR3: 000000003c036000 CR4: 00000000000006a0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000ffff4ff0 DR7: 0000000000000400
+ [<ffffffff8104f04e>] dequeue_signal+0x8e/0x170
+ [<ffffffff81050bd8>] get_signal_to_deliver+0x98/0x390
+ [<ffffffff8100b87d>] do_notify_resume+0xad/0x7d0
+ [<ffffffff8100c7b5>] int_signal+0x12/0x17
+ [<ffffffffffffffff>] 0xffffffffffffffff
+
+The single most valuable information in this report is the RIP (or EIP on 32-
+bit) value. This will help us pinpoint exactly which instruction that caused
+the warning.
+
+If your kernel was compiled with CONFIG_DEBUG_INFO=y, then all we have to do
+is give this address to the addr2line program, like this:
+
+	$ addr2line -e vmlinux -i ffffffff8104ede8
+	arch/x86/include/asm/string_64.h:12
+	include/asm-generic/siginfo.h:287
+	kernel/signal.c:380
+	kernel/signal.c:410
+
+The "-e vmlinux" tells addr2line which file to look in. IMPORTANT: This must
+be the vmlinux of the kernel that produced the warning in the first place! If
+not, the line number information will almost certainly be wrong.
+
+The "-i" tells addr2line to also print the line numbers of inlined functions.
+In this case, the flag was very important, because otherwise, it would only
+have printed the first line, which is just a call to memcpy(), which could be
+called from a thousand places in the kernel, and is therefore not very useful.
+These inlined functions would not show up in the stack trace above, simply
+because the kernel doesn't load the extra debugging information. This
+technique can of course be used with ordinary kernel oopses as well.
+
+In this case, it's the caller of memcpy() that is interesting, and it can be
+found in include/asm-generic/siginfo.h, line 287:
+
+281 static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
+282 {
+283         if (from->si_code < 0)
+284                 memcpy(to, from, sizeof(*to));
+285         else
+286                 /* _sigchld is currently the largest know union member */
+287                 memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
+288 }
+
+Since this was a read (kmemcheck usually warns about reads only, though it can
+warn about writes to unallocated or freed memory as well), it was probably the
+"from" argument which contained some uninitialized bytes. Following the chain
+of calls, we move upwards to see where "from" was allocated or initialized,
+kernel/signal.c, line 380:
+
+359 static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+360 {
+...
+367         list_for_each_entry(q, &list->list, list) {
+368                 if (q->info.si_signo == sig) {
+369                         if (first)
+370                                 goto still_pending;
+371                         first = q;
+...
+377         if (first) {
+378 still_pending:
+379                 list_del_init(&first->list);
+380                 copy_siginfo(info, &first->info);
+381                 __sigqueue_free(first);
+...
+392         }
+393 }
+
+Here, it is &first->info that is being passed on to copy_siginfo(). The
+variable "first" was found on a list -- passed in as the second argument to
+collect_signal(). We  continue our journey through the stack, to figure out
+where the item on "list" was allocated or initialized. We move to line 410:
+
+395 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
+396                         siginfo_t *info)
+397 {
+...
+410                 collect_signal(sig, pending, info);
+...
+414 }
+
+Now we need to follow the "pending" pointer, since that is being passed on to
+collect_signal() as "list". At this point, we've run out of lines from the
+"addr2line" output. Not to worry, we just paste the next addresses from the
+kmemcheck stack dump, i.e.:
+
+ [<ffffffff8104f04e>] dequeue_signal+0x8e/0x170
+ [<ffffffff81050bd8>] get_signal_to_deliver+0x98/0x390
+ [<ffffffff8100b87d>] do_notify_resume+0xad/0x7d0
+ [<ffffffff8100c7b5>] int_signal+0x12/0x17
+
+	$ addr2line -e vmlinux -i ffffffff8104f04e ffffffff81050bd8 \
+		ffffffff8100b87d ffffffff8100c7b5
+	kernel/signal.c:446
+	kernel/signal.c:1806
+	arch/x86/kernel/signal.c:805
+	arch/x86/kernel/signal.c:871
+	arch/x86/kernel/entry_64.S:694
+
+Remember that since these addresses were found on the stack and not as the
+RIP value, they actually point to the _next_ instruction (they are return
+addresses). This becomes obvious when we look at the code for line 446:
+
+422 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+423 {
+...
+431                 signr = __dequeue_signal(&tsk->signal->shared_pending,
+432                                          mask, info);
+433                 /*
+434                  * itimer signal ?
+435                  *
+436                  * itimers are process shared and we restart periodic
+437                  * itimers in the signal delivery path to prevent DoS
+438                  * attacks in the high resolution timer case. This is
+439                  * compliant with the old way of self restarting
+440                  * itimers, as the SIGALRM is a legacy signal and only
+441                  * queued once. Changing the restart behaviour to
+442                  * restart the timer in the signal dequeue path is
+443                  * reducing the timer noise on heavy loaded !highres
+444                  * systems too.
+445                  */
+446                 if (unlikely(signr == SIGALRM)) {
+...
+489 }
+
+So instead of looking at 446, we should be looking at 431, which is the line
+that executes just before 446. Here we see that what we are looking for is
+&tsk->signal->shared_pending.
+
+Our next task is now to figure out which function that puts items on this
+"shared_pending" list. A crude, but efficient tool, is git grep:
+
+	$ git grep -n 'shared_pending' kernel/
+	...
+	kernel/signal.c:828:    pending = group ? &t->signal->shared_pending : &t->pending;
+	kernel/signal.c:1339:   pending = group ? &t->signal->shared_pending : &t->pending;
+	...
+
+There were more results, but none of them were related to list operations,
+and these were the only assignments. We inspect the line numbers more closely
+and find that this is indeed where items are being added to the list:
+
+816 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+817                         int group)
+818 {
+...
+828         pending = group ? &t->signal->shared_pending : &t->pending;
+...
+851         q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
+852                                              (is_si_special(info) ||
+853                                               info->si_code >= 0)));
+854         if (q) {
+855                 list_add_tail(&q->list, &pending->list);
+...
+890 }
+
+and:
+
+1309 int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)
+1310 {
+....
+1339         pending = group ? &t->signal->shared_pending : &t->pending;
+1340         list_add_tail(&q->list, &pending->list);
+....
+1347 }
+
+In the first case, the list element we are looking for, "q", is being returned
+from the function __sigqueue_alloc(), which looks like an allocation function.
+Let's take a look at it:
+
+187 static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
+188                                          int override_rlimit)
+189 {
+190         struct sigqueue *q = NULL;
+191         struct user_struct *user;
+192 
+193         /*
+194          * We won't get problems with the target's UID changing under us
+195          * because changing it requires RCU be used, and if t != current, the
+196          * caller must be holding the RCU readlock (by way of a spinlock) and
+197          * we use RCU protection here
+198          */
+199         user = get_uid(__task_cred(t)->user);
+200         atomic_inc(&user->sigpending);
+201         if (override_rlimit ||
+202             atomic_read(&user->sigpending) <=
+203                         t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
+204                 q = kmem_cache_alloc(sigqueue_cachep, flags);
+205         if (unlikely(q == NULL)) {
+206                 atomic_dec(&user->sigpending);
+207                 free_uid(user);
+208         } else {
+209                 INIT_LIST_HEAD(&q->list);
+210                 q->flags = 0;
+211                 q->user = user;
+212         }
+213 
+214         return q;
+215 }
+
+We see that this function initializes q->list, q->flags, and q->user. It seems
+that now is the time to look at the definition of "struct sigqueue", e.g.:
+
+14 struct sigqueue {
+15         struct list_head list;
+16         int flags;
+17         siginfo_t info;
+18         struct user_struct *user;
+19 };
+
+And, you might remember, it was a memcpy() on &first->info that caused the
+warning, so this makes perfect sense. It also seems reasonable to assume that
+it is the caller of __sigqueue_alloc() that has the responsibility of filling
+out (initializing) this member.
+
+But just which fields of the struct were uninitialized? Let's look at
+kmemcheck's report again:
+
+WARNING: kmemcheck: Caught 32-bit read from uninitialized memory (ffff88003e4a2024)
+80000000000000000000000000000000000000000088ffff0000000000000000
+ i i i i u u u u i i i i i i i i u u u u u u u u u u u u u u u u
+         ^
+
+These first two lines are the memory dump of the memory object itself, and the
+shadow bytemap, respectively. The memory object itself is in this case
+&first->info. Just beware that the start of this dump is NOT the start of the
+object itself! The position of the caret (^) corresponds with the address of
+the read (ffff88003e4a2024).
+
+The shadow bytemap dump legend is as follows:
+
+  i - initialized
+  u - uninitialized
+  a - unallocated (memory has been allocated by the slab layer, but has not
+      yet been handed off to anybody)
+  f - freed (memory has been allocated by the slab layer, but has been freed
+      by the previous owner)
+
+In order to figure out where (relative to the start of the object) the
+uninitialized memory was located, we have to look at the disassembly. For
+that, we'll need the RIP address again:
+
+RIP: 0010:[<ffffffff8104ede8>]  [<ffffffff8104ede8>] __dequeue_signal+0xc8/0x190
+
+	$ objdump -d --no-show-raw-insn vmlinux | grep -C 8 ffffffff8104ede8:
+	ffffffff8104edc8:       mov    %r8,0x8(%r8)
+	ffffffff8104edcc:       test   %r10d,%r10d
+	ffffffff8104edcf:       js     ffffffff8104ee88 <__dequeue_signal+0x168>
+	ffffffff8104edd5:       mov    %rax,%rdx
+	ffffffff8104edd8:       mov    $0xc,%ecx
+	ffffffff8104eddd:       mov    %r13,%rdi
+	ffffffff8104ede0:       mov    $0x30,%eax
+	ffffffff8104ede5:       mov    %rdx,%rsi
+	ffffffff8104ede8:       rep movsl %ds:(%rsi),%es:(%rdi)
+	ffffffff8104edea:       test   $0x2,%al
+	ffffffff8104edec:       je     ffffffff8104edf0 <__dequeue_signal+0xd0>
+	ffffffff8104edee:       movsw  %ds:(%rsi),%es:(%rdi)
+	ffffffff8104edf0:       test   $0x1,%al
+	ffffffff8104edf2:       je     ffffffff8104edf5 <__dequeue_signal+0xd5>
+	ffffffff8104edf4:       movsb  %ds:(%rsi),%es:(%rdi)
+	ffffffff8104edf5:       mov    %r8,%rdi
+	ffffffff8104edf8:       callq  ffffffff8104de60 <__sigqueue_free>
+
+As expected, it's the "rep movsl" instruction from the memcpy() that causes
+the warning. We know about REP MOVSL that it uses the register RCX to count
+the number of remaining iterations. By taking a look at the register dump
+again (from the kmemcheck report), we can figure out how many bytes were left
+to copy:
+
+RAX: 0000000000000030 RBX: ffff88003d4ea968 RCX: 0000000000000009
+
+By looking at the disassembly, we also see that %ecx is being loaded with the
+value $0xc just before (ffffffff8104edd8), so we are very lucky. Keep in mind
+that this is the number of iterations, not bytes. And since this is a "long"
+operation, we need to multiply by 4 to get the number of bytes. So this means
+that the uninitialized value was encountered at 4 * (0xc - 0x9) = 12 bytes
+from the start of the object.
+
+We can now try to figure out which field of the "struct siginfo" that was not
+initialized. This is the beginning of the struct:
+
+40 typedef struct siginfo {
+41         int si_signo;
+42         int si_errno;
+43         int si_code;
+44                 
+45         union {
+..
+92         } _sifields;
+93 } siginfo_t;
+
+On 64-bit, the int is 4 bytes long, so it must the the union member that has
+not been initialized. We can verify this using gdb:
+
+	$ gdb vmlinux
+	...
+	(gdb) p &((struct siginfo *) 0)->_sifields
+	$1 = (union {...} *) 0x10
+
+Actually, it seems that the union member is located at offset 0x10 -- which
+means that gcc has inserted 4 bytes of padding between the members si_code
+and _sifields. We can now get a fuller picture of the memory dump:
+
+         _----------------------------=> si_code
+        /        _--------------------=> (padding)
+       |        /        _------------=> _sifields(._kill._pid)
+       |       |        /        _----=> _sifields(._kill._uid)
+       |       |       |        / 
+-------|-------|-------|-------|
+80000000000000000000000000000000000000000088ffff0000000000000000
+ i i i i u u u u i i i i i i i i u u u u u u u u u u u u u u u u
+
+This allows us to realize another important fact: si_code contains the value
+0x80. Remember that x86 is little endian, so the first 4 bytes "80000000" are
+really the number 0x00000080. With a bit of research, we find that this is
+actually the constant SI_KERNEL defined in include/asm-generic/siginfo.h:
+
+144 #define SI_KERNEL       0x80            /* sent by the kernel from somewhere     */
+
+This macro is used in exactly one place in the x86 kernel: In send_signal()
+in kernel/signal.c:
+
+816 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+817                         int group)
+818 {
+...
+828         pending = group ? &t->signal->shared_pending : &t->pending;
+...
+851         q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
+852                                              (is_si_special(info) ||
+853                                               info->si_code >= 0)));
+854         if (q) {
+855                 list_add_tail(&q->list, &pending->list);
+856                 switch ((unsigned long) info) {
+...
+865                 case (unsigned long) SEND_SIG_PRIV:
+866                         q->info.si_signo = sig;
+867                         q->info.si_errno = 0;
+868                         q->info.si_code = SI_KERNEL;
+869                         q->info.si_pid = 0;
+870                         q->info.si_uid = 0;
+871                         break;
+...
+890 }
+
+Not only does this match with the .si_code member, it also matches the place
+we found earlier when looking for where siginfo_t objects are enqueued on the
+"shared_pending" list.
+
+So to sum up: It seems that it is the padding introduced by the compiler
+between two struct fields that is uninitialized, and this gets reported when
+we do a memcpy() on the struct. This means that we have identified a false
+positive warning.
+
+Normally, kmemcheck will not report uninitialized accesses in memcpy() calls
+when both the source and destination addresses are tracked. (Instead, we copy
+the shadow bytemap as well). In this case, the destination address clearly
+was not tracked. We can dig a little deeper into the stack trace from above:
+
+	arch/x86/kernel/signal.c:805
+	arch/x86/kernel/signal.c:871
+	arch/x86/kernel/entry_64.S:694
+
+And we clearly see that the destination siginfo object is located on the
+stack:
+
+782 static void do_signal(struct pt_regs *regs)
+783 {
+784         struct k_sigaction ka;
+785         siginfo_t info;
+...
+804         signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+...
+854 }
+
+And this &info is what eventually gets passed to copy_siginfo() as the
+destination argument.
+
+Now, even though we didn't find an actual error here, the example is still a
+good one, because it shows how one would go about to find out what the report
+was all about.
+
+
+3.4. Annotating false positives
+===============================
+
+There are a few different ways to make annotations in the source code that
+will keep kmemcheck from checking and reporting certain allocations. Here
+they are:
+
+  o __GFP_NOTRACK_FALSE_POSITIVE
+
+	This flag can be passed to kmalloc() or kmem_cache_alloc() (therefore
+	also to other functions that end up calling one of these) to indicate
+	that the allocation should not be tracked because it would lead to
+	a false positive report. This is a "big hammer" way of silencing
+	kmemcheck; after all, even if the false positive pertains to 
+	particular field in a struct, for example, we will now lose the
+	ability to find (real) errors in other parts of the same struct.
+
+	Example:
+
+	    /* No warnings will ever trigger on accessing any part of x */
+	    x = kmalloc(sizeof *x, GFP_KERNEL | __GFP_NOTRACK_FALSE_POSITIVE);
+
+  o kmemcheck_bitfield_begin(name)/kmemcheck_bitfield_end(name) and
+	kmemcheck_annotate_bitfield(ptr, name)
+
+	The first two of these three macros can be used inside struct
+	definitions to signal, respectively, the beginning and end of a
+	bitfield. Additionally, this will assign the bitfield a name, which
+	is given as an argument to the macros.
+
+	Having used these markers, one can later use
+	kmemcheck_annotate_bitfield() at the point of allocation, to indicate
+	which parts of the allocation is part of a bitfield.
+
+	Example:
+
+	    struct foo {
+		int x;
+
+		kmemcheck_bitfield_begin(flags);
+		int flag_a:1;
+		int flag_b:1;
+		kmemcheck_bitfield_end(flags);
+
+		int y;
+	    };
+
+	    struct foo *x = kmalloc(sizeof *x);
+
+	    /* No warnings will trigger on accessing the bitfield of x */
+	    kmemcheck_annotate_bitfield(x, flags);
+
+	Note that kmemcheck_annotate_bitfield() can be used even before the
+	return value of kmalloc() is checked -- in other words, passing NULL
+	as the first argument is legal (and will do nothing).
+
+
+4. Reporting errors
+===================
+
+As we have seen, kmemcheck will produce false positive reports. Therefore, it
+is not very wise to blindly post kmemcheck warnings to mailing lists and
+maintainers. Instead, I encourage maintainers and developers to find errors
+in their own code. If you get a warning, you can try to work around it, try
+to figure out if it's a real error or not, or simply ignore it. Most
+developers know their own code and will quickly and efficiently determine the
+root cause of a kmemcheck report. This is therefore also the most efficient
+way to work with kmemcheck.
+
+That said, we (the kmemcheck maintainers) will always be on the lookout for
+false positives that we can annotate and silence. So whatever you find,
+please drop us a note privately! Kernel configs and steps to reproduce (if
+available) are of course a great help too.
+
+Happy hacking!
+
+
+5. Technical description
+========================
+
+kmemcheck works by marking memory pages non-present. This means that whenever
+somebody attempts to access the page, a page fault is generated. The page
+fault handler notices that the page was in fact only hidden, and so it calls
+on the kmemcheck code to make further investigations.
+
+When the investigations are completed, kmemcheck "shows" the page by marking
+it present (as it would be under normal circumstances). This way, the
+interrupted code can continue as usual.
+
+But after the instruction has been executed, we should hide the page again, so
+that we can catch the next access too! Now kmemcheck makes use of a debugging
+feature of the processor, namely single-stepping. When the processor has
+finished the one instruction that generated the memory access, a debug
+exception is raised. From here, we simply hide the page again and continue
+execution, this time with the single-stepping feature turned off.
+
+kmemcheck requires some assistance from the memory allocator in order to work.
+The memory allocator needs to
+
+  1. Tell kmemcheck about newly allocated pages and pages that are about to
+     be freed. This allows kmemcheck to set up and tear down the shadow memory
+     for the pages in question. The shadow memory stores the status of each
+     byte in the allocation proper, e.g. whether it is initialized or
+     uninitialized.
+
+  2. Tell kmemcheck which parts of memory should be marked uninitialized.
+     There are actually a few more states, such as "not yet allocated" and
+     "recently freed".
+
+If a slab cache is set up using the SLAB_NOTRACK flag, it will never return
+memory that can take page faults because of kmemcheck.
+
+If a slab cache is NOT set up using the SLAB_NOTRACK flag, callers can still
+request memory with the __GFP_NOTRACK or __GFP_NOTRACK_FALSE_POSITIVE flags.
+This does not prevent the page faults from occurring, however, but marks the
+object in question as being initialized so that no warnings will ever be
+produced for this object.
+
+Currently, the SLAB and SLUB allocators are supported by kmemcheck.
diff -druN linux-libre-2.6.30-gnu/Documentation/kmemleak.txt linux-libre-2.6.31-gnu/Documentation/kmemleak.txt
--- linux-libre-2.6.30-gnu/Documentation/kmemleak.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/kmemleak.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,151 @@
+Kernel Memory Leak Detector
+===========================
+
+Introduction
+------------
+
+Kmemleak provides a way of detecting possible kernel memory leaks in a
+way similar to a tracing garbage collector
+(http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29#Tracing_garbage_collectors),
+with the difference that the orphan objects are not freed but only
+reported via /sys/kernel/debug/kmemleak. A similar method is used by the
+Valgrind tool (memcheck --leak-check) to detect the memory leaks in
+user-space applications.
+
+Usage
+-----
+
+CONFIG_DEBUG_KMEMLEAK in "Kernel hacking" has to be enabled. A kernel
+thread scans the memory every 10 minutes (by default) and prints the
+number of new unreferenced objects found. To display the details of all
+the possible memory leaks:
+
+  # mount -t debugfs nodev /sys/kernel/debug/
+  # cat /sys/kernel/debug/kmemleak
+
+To trigger an intermediate memory scan:
+
+  # echo scan > /sys/kernel/debug/kmemleak
+
+Note that the orphan objects are listed in the order they were allocated
+and one object at the beginning of the list may cause other subsequent
+objects to be reported as orphan.
+
+Memory scanning parameters can be modified at run-time by writing to the
+/sys/kernel/debug/kmemleak file. The following parameters are supported:
+
+  off		- disable kmemleak (irreversible)
+  stack=on	- enable the task stacks scanning (default)
+  stack=off	- disable the tasks stacks scanning
+  scan=on	- start the automatic memory scanning thread (default)
+  scan=off	- stop the automatic memory scanning thread
+  scan=<secs>	- set the automatic memory scanning period in seconds
+		  (default 600, 0 to stop the automatic scanning)
+  scan		- trigger a memory scan
+
+Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on
+the kernel command line.
+
+Memory may be allocated or freed before kmemleak is initialised and
+these actions are stored in an early log buffer. The size of this buffer
+is configured via the CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE option.
+
+Basic Algorithm
+---------------
+
+The memory allocations via kmalloc, vmalloc, kmem_cache_alloc and
+friends are traced and the pointers, together with additional
+information like size and stack trace, are stored in a prio search tree.
+The corresponding freeing function calls are tracked and the pointers
+removed from the kmemleak data structures.
+
+An allocated block of memory is considered orphan if no pointer to its
+start address or to any location inside the block can be found by
+scanning the memory (including saved registers). This means that there
+might be no way for the kernel to pass the address of the allocated
+block to a freeing function and therefore the block is considered a
+memory leak.
+
+The scanning algorithm steps:
+
+  1. mark all objects as white (remaining white objects will later be
+     considered orphan)
+  2. scan the memory starting with the data section and stacks, checking
+     the values against the addresses stored in the prio search tree. If
+     a pointer to a white object is found, the object is added to the
+     gray list
+  3. scan the gray objects for matching addresses (some white objects
+     can become gray and added at the end of the gray list) until the
+     gray set is finished
+  4. the remaining white objects are considered orphan and reported via
+     /sys/kernel/debug/kmemleak
+
+Some allocated memory blocks have pointers stored in the kernel's
+internal data structures and they cannot be detected as orphans. To
+avoid this, kmemleak can also store the number of values pointing to an
+address inside the block address range that need to be found so that the
+block is not considered a leak. One example is __vmalloc().
+
+Kmemleak API
+------------
+
+See the include/linux/kmemleak.h header for the functions prototype.
+
+kmemleak_init		 - initialize kmemleak
+kmemleak_alloc		 - notify of a memory block allocation
+kmemleak_free		 - notify of a memory block freeing
+kmemleak_not_leak	 - mark an object as not a leak
+kmemleak_ignore		 - do not scan or report an object as leak
+kmemleak_scan_area	 - add scan areas inside a memory block
+kmemleak_no_scan	 - do not scan a memory block
+kmemleak_erase		 - erase an old value in a pointer variable
+kmemleak_alloc_recursive - as kmemleak_alloc but checks the recursiveness
+kmemleak_free_recursive	 - as kmemleak_free but checks the recursiveness
+
+Dealing with false positives/negatives
+--------------------------------------
+
+The false negatives are real memory leaks (orphan objects) but not
+reported by kmemleak because values found during the memory scanning
+point to such objects. To reduce the number of false negatives, kmemleak
+provides the kmemleak_ignore, kmemleak_scan_area, kmemleak_no_scan and
+kmemleak_erase functions (see above). The task stacks also increase the
+amount of false negatives and their scanning is not enabled by default.
+
+The false positives are objects wrongly reported as being memory leaks
+(orphan). For objects known not to be leaks, kmemleak provides the
+kmemleak_not_leak function. The kmemleak_ignore could also be used if
+the memory block is known not to contain other pointers and it will no
+longer be scanned.
+
+Some of the reported leaks are only transient, especially on SMP
+systems, because of pointers temporarily stored in CPU registers or
+stacks. Kmemleak defines MSECS_MIN_AGE (defaulting to 1000) representing
+the minimum age of an object to be reported as a memory leak.
+
+Limitations and Drawbacks
+-------------------------
+
+The main drawback is the reduced performance of memory allocation and
+freeing. To avoid other penalties, the memory scanning is only performed
+when the /sys/kernel/debug/kmemleak file is read. Anyway, this tool is
+intended for debugging purposes where the performance might not be the
+most important requirement.
+
+To keep the algorithm simple, kmemleak scans for values pointing to any
+address inside a block's address range. This may lead to an increased
+number of false negatives. However, it is likely that a real memory leak
+will eventually become visible.
+
+Another source of false negatives is the data stored in non-pointer
+values. In a future version, kmemleak could only scan the pointer
+members in the allocated structures. This feature would solve many of
+the false negative cases described above.
+
+The tool can report false positives. These are cases where an allocated
+block doesn't need to be freed (some cases in the init_call functions),
+the pointer is calculated by other methods than the usual container_of
+macro or the pointer is stored in a location not scanned by kmemleak.
+
+Page allocations and ioremap are not tracked. Only the ARM and x86
+architectures are currently supported.
diff -druN linux-libre-2.6.30-gnu/Documentation/kobject.txt linux-libre-2.6.31-gnu/Documentation/kobject.txt
--- linux-libre-2.6.30-gnu/Documentation/kobject.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/kobject.txt	2009-09-09 18:13:59.000000000 -0400
@@ -132,7 +132,7 @@
     const char *kobject_name(const struct kobject * kobj);
 
 There is a helper function to both initialize and add the kobject to the
-kernel at the same time, called supprisingly enough kobject_init_and_add():
+kernel at the same time, called surprisingly enough kobject_init_and_add():
 
     int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
                              struct kobject *parent, const char *fmt, ...);
diff -druN linux-libre-2.6.30-gnu/Documentation/kprobes.txt linux-libre-2.6.31-gnu/Documentation/kprobes.txt
--- linux-libre-2.6.30-gnu/Documentation/kprobes.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/kprobes.txt	2009-09-09 18:13:59.000000000 -0400
@@ -507,9 +507,9 @@
 Appendix A: The kprobes debugfs interface
 
 With recent kernels (> 2.6.20) the list of registered kprobes is visible
-under the /debug/kprobes/ directory (assuming debugfs is mounted at /debug).
+under the /sys/kernel/debug/kprobes/ directory (assuming debugfs is mounted at //sys/kernel/debug).
 
-/debug/kprobes/list: Lists all registered probes on the system
+/sys/kernel/debug/kprobes/list: Lists all registered probes on the system
 
 c015d71a  k  vfs_read+0x0
 c011a316  j  do_fork+0x0
@@ -525,7 +525,7 @@
 such probes are marked with [GONE]. If the probe is temporarily disabled,
 such probes are marked with [DISABLED].
 
-/debug/kprobes/enabled: Turn kprobes ON/OFF forcibly.
+/sys/kernel/debug/kprobes/enabled: Turn kprobes ON/OFF forcibly.
 
 Provides a knob to globally and forcibly turn registered kprobes ON or OFF.
 By default, all kprobes are enabled. By echoing "0" to this file, all
diff -druN linux-libre-2.6.30-gnu/Documentation/laptops/acer-wmi.txt linux-libre-2.6.31-gnu/Documentation/laptops/acer-wmi.txt
--- linux-libre-2.6.30-gnu/Documentation/laptops/acer-wmi.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/laptops/acer-wmi.txt	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 acer-wmi until Acer fix their ACPI-WMI implementation on them, so has been
 blacklisted until that happens.
 
-Please see the website for the current list of known working hardare:
+Please see the website for the current list of known working hardware:
 
 http://code.google.com/p/aceracpi/wiki/SupportedHardware
 
diff -druN linux-libre-2.6.30-gnu/Documentation/laptops/sony-laptop.txt linux-libre-2.6.31-gnu/Documentation/laptops/sony-laptop.txt
--- linux-libre-2.6.30-gnu/Documentation/laptops/sony-laptop.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/laptops/sony-laptop.txt	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,7 @@
 /sys/class/backlight/sony/
 directory. You will be able to query and set the current screen
 brightness:
-	brightness		get/set screen brightness (an iteger
+	brightness		get/set screen brightness (an integer
 				between 0 and 7)
 	actual_brightness	reading from this file will query the HW
 				to get real brightness value
diff -druN linux-libre-2.6.30-gnu/Documentation/laptops/thinkpad-acpi.txt linux-libre-2.6.31-gnu/Documentation/laptops/thinkpad-acpi.txt
--- linux-libre-2.6.30-gnu/Documentation/laptops/thinkpad-acpi.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/laptops/thinkpad-acpi.txt	2009-09-09 18:13:59.000000000 -0400
@@ -36,8 +36,6 @@
 	- Bluetooth enable and disable
 	- video output switching, expansion control
 	- ThinkLight on and off
-	- limited docking and undocking
-	- UltraBay eject
 	- CMOS/UCMS control
 	- LED control
 	- ACPI sounds
@@ -506,7 +504,7 @@
 In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW
 events for switches:
 
-SW_RFKILL_ALL	T60 and later hardare rfkill rocker switch
+SW_RFKILL_ALL	T60 and later hardware rfkill rocker switch
 SW_TABLET_MODE	Tablet ThinkPads HKEY events 0x5009 and 0x500A
 
 Non hot-key ACPI HKEY event map:
@@ -729,131 +727,6 @@
 It is impossible to know if the status returned through sysfs is valid.
 
 
-Docking / undocking -- /proc/acpi/ibm/dock
-------------------------------------------
-
-Docking and undocking (e.g. with the X4 UltraBase) requires some
-actions to be taken by the operating system to safely make or break
-the electrical connections with the dock.
-
-The docking feature of this driver generates the following ACPI events:
-
-	ibm/dock GDCK 00000003 00000001 -- eject request
-	ibm/dock GDCK 00000003 00000002 -- undocked
-	ibm/dock GDCK 00000000 00000003 -- docked
-
-NOTE: These events will only be generated if the laptop was docked
-when originally booted. This is due to the current lack of support for
-hot plugging of devices in the Linux ACPI framework. If the laptop was
-booted while not in the dock, the following message is shown in the
-logs:
-
-	Mar 17 01:42:34 aero kernel: thinkpad_acpi: dock device not present
-
-In this case, no dock-related events are generated but the dock and
-undock commands described below still work. They can be executed
-manually or triggered by Fn key combinations (see the example acpid
-configuration files included in the driver tarball package available
-on the web site).
-
-When the eject request button on the dock is pressed, the first event
-above is generated. The handler for this event should issue the
-following command:
-
-	echo undock > /proc/acpi/ibm/dock
-
-After the LED on the dock goes off, it is safe to eject the laptop.
-Note: if you pressed this key by mistake, go ahead and eject the
-laptop, then dock it back in. Otherwise, the dock may not function as
-expected.
-
-When the laptop is docked, the third event above is generated. The
-handler for this event should issue the following command to fully
-enable the dock:
-
-	echo dock > /proc/acpi/ibm/dock
-
-The contents of the /proc/acpi/ibm/dock file shows the current status
-of the dock, as provided by the ACPI framework.
-
-The docking support in this driver does not take care of enabling or
-disabling any other devices you may have attached to the dock. For
-example, a CD drive plugged into the UltraBase needs to be disabled or
-enabled separately. See the provided example acpid configuration files
-for how this can be accomplished.
-
-There is no support yet for PCI devices that may be attached to a
-docking station, e.g. in the ThinkPad Dock II. The driver currently
-does not recognize, enable or disable such devices. This means that
-the only docking stations currently supported are the X-series
-UltraBase docks and "dumb" port replicators like the Mini Dock (the
-latter don't need any ACPI support, actually).
-
-
-UltraBay eject -- /proc/acpi/ibm/bay
-------------------------------------
-
-Inserting or ejecting an UltraBay device requires some actions to be
-taken by the operating system to safely make or break the electrical
-connections with the device.
-
-This feature generates the following ACPI events:
-
-	ibm/bay MSTR 00000003 00000000 -- eject request
-	ibm/bay MSTR 00000001 00000000 -- eject lever inserted
-
-NOTE: These events will only be generated if the UltraBay was present
-when the laptop was originally booted (on the X series, the UltraBay
-is in the dock, so it may not be present if the laptop was undocked).
-This is due to the current lack of support for hot plugging of devices
-in the Linux ACPI framework. If the laptop was booted without the
-UltraBay, the following message is shown in the logs:
-
-	Mar 17 01:42:34 aero kernel: thinkpad_acpi: bay device not present
-
-In this case, no bay-related events are generated but the eject
-command described below still works. It can be executed manually or
-triggered by a hot key combination.
-
-Sliding the eject lever generates the first event shown above. The
-handler for this event should take whatever actions are necessary to
-shut down the device in the UltraBay (e.g. call idectl), then issue
-the following command:
-
-	echo eject > /proc/acpi/ibm/bay
-
-After the LED on the UltraBay goes off, it is safe to pull out the
-device.
-
-When the eject lever is inserted, the second event above is
-generated. The handler for this event should take whatever actions are
-necessary to enable the UltraBay device (e.g. call idectl).
-
-The contents of the /proc/acpi/ibm/bay file shows the current status
-of the UltraBay, as provided by the ACPI framework.
-
-EXPERIMENTAL warm eject support on the 600e/x, A22p and A3x (To use
-this feature, you need to supply the experimental=1 parameter when
-loading the module):
-
-These models do not have a button near the UltraBay device to request
-a hot eject but rather require the laptop to be put to sleep
-(suspend-to-ram) before the bay device is ejected or inserted).
-The sequence of steps to eject the device is as follows:
-
-	echo eject > /proc/acpi/ibm/bay
-	put the ThinkPad to sleep
-	remove the drive
-	resume from sleep
-	cat /proc/acpi/ibm/bay should show that the drive was removed
-
-On the A3x, both the UltraBay 2000 and UltraBay Plus devices are
-supported. Use "eject2" instead of "eject" for the second bay.
-
-Note: the UltraBay eject support on the 600e/x, A22p and A3x is
-EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
-
-
 CMOS/UCMS control
 -----------------
 
@@ -920,7 +793,7 @@
 	echo '<LED number> off' >/proc/acpi/ibm/led
 	echo '<LED number> blink' >/proc/acpi/ibm/led
 
-The <LED number> range is 0 to 7. The set of LEDs that can be
+The <LED number> range is 0 to 15. The set of LEDs that can be
 controlled varies from model to model. Here is the common ThinkPad
 mapping:
 
@@ -932,6 +805,11 @@
 	5 - UltraBase battery slot
 	6 - (unknown)
 	7 - standby
+	8 - dock status 1
+	9 - dock status 2
+	10, 11 - (unknown)
+	12 - thinkvantage
+	13, 14, 15 - (unknown)
 
 All of the above can be turned on and off and can be made to blink.
 
@@ -940,10 +818,12 @@
 The ThinkPad LED sysfs interface is described in detail by the LED class
 documentation, in Documentation/leds-class.txt.
 
-The leds are named (in LED ID order, from 0 to 7):
+The LEDs are named (in LED ID order, from 0 to 12):
 "tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt",
 "tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt",
-"tpacpi::unknown_led", "tpacpi::standby".
+"tpacpi::unknown_led", "tpacpi::standby", "tpacpi::dock_status1",
+"tpacpi::dock_status2", "tpacpi::unknown_led2", "tpacpi::unknown_led3",
+"tpacpi::thinkvantage".
 
 Due to limitations in the sysfs LED class, if the status of the LED
 indicators cannot be read due to an error, thinkpad-acpi will report it as
@@ -958,6 +838,12 @@
 "timer" trigger, and leave the delay_on and delay_off parameters set to
 zero (to request hardware acceleration autodetection).
 
+LEDs that are known not to exist in a given ThinkPad model are not
+made available through the sysfs interface.  If you have a dock and you
+notice there are LEDs listed for your ThinkPad that do not exist (and
+are not in the dock), or if you notice that there are missing LEDs,
+a report to ibm-acpi-devel@lists.sourceforge.net is appreciated.
+
 
 ACPI sounds -- /proc/acpi/ibm/beep
 ----------------------------------
@@ -1156,17 +1042,19 @@
 display backlight brightness control methods have 16 levels, ranging
 from 0 to 15.
 
-There are two interfaces to the firmware for direct brightness control,
-EC and UCMS (or CMOS).  To select which one should be used, use the
-brightness_mode module parameter: brightness_mode=1 selects EC mode,
-brightness_mode=2 selects UCMS mode, brightness_mode=3 selects EC
-mode with NVRAM backing (so that brightness changes are remembered
-across shutdown/reboot).
+For IBM ThinkPads, there are two interfaces to the firmware for direct
+brightness control, EC and UCMS (or CMOS).  To select which one should be
+used, use the brightness_mode module parameter: brightness_mode=1 selects
+EC mode, brightness_mode=2 selects UCMS mode, brightness_mode=3 selects EC
+mode with NVRAM backing (so that brightness changes are remembered across
+shutdown/reboot).
 
 The driver tries to select which interface to use from a table of
 defaults for each ThinkPad model.  If it makes a wrong choice, please
 report this as a bug, so that we can fix it.
 
+Lenovo ThinkPads only support brightness_mode=2 (UCMS).
+
 When display backlight brightness controls are available through the
 standard ACPI interface, it is best to use it instead of this direct
 ThinkPad-specific interface.  The driver will disable its native
@@ -1254,7 +1142,7 @@
 
 procfs: /proc/acpi/ibm/fan
 sysfs device attributes: (hwmon "thinkpad") fan1_input, pwm1,
-			  pwm1_enable
+			  pwm1_enable, fan2_input
 sysfs hwmon driver attributes: fan_watchdog
 
 NOTE NOTE NOTE: fan control operations are disabled by default for
@@ -1267,6 +1155,9 @@
 to work on later R, T, X and Z series ThinkPads but may show a bogus
 value on other models.
 
+Some Lenovo ThinkPads support a secondary fan.  This fan cannot be
+controlled separately, it shares the main fan control.
+
 Fan levels:
 
 Most ThinkPad fans work in "levels" at the firmware interface.  Level 0
@@ -1397,6 +1288,11 @@
 	which can take up to two minutes.  May return rubbish on older
 	ThinkPads.
 
+hwmon device attribute fan2_input:
+	Fan tachometer reading, in RPM, for the secondary fan.
+	Available only on some ThinkPads.  If the secondary fan is
+	not installed, will always read 0.
+
 hwmon driver attribute fan_watchdog:
 	Fan safety watchdog timer interval, in seconds.  Minimum is
 	1 second, maximum is 120 seconds.  0 disables the watchdog.
@@ -1555,3 +1451,7 @@
 0x020300:	hotkey enable/disable support removed, attributes
 		hotkey_bios_enabled and hotkey_enable deprecated and
 		marked for removal.
+
+0x020400:	Marker for 16 LEDs support.  Also, LEDs that are known
+		to not exist in a given model are not registered with
+		the LED sysfs class anymore.
diff -druN linux-libre-2.6.30-gnu/Documentation/leds-lp3944.txt linux-libre-2.6.31-gnu/Documentation/leds-lp3944.txt
--- linux-libre-2.6.30-gnu/Documentation/leds-lp3944.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/leds-lp3944.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,50 @@
+Kernel driver lp3944
+====================
+
+  * National Semiconductor LP3944 Fun-light Chip
+    Prefix: 'lp3944'
+    Addresses scanned: None (see the Notes section below)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LP/LP3944.html
+
+Authors:
+        Antonio Ospite <ospite@studenti.unina.it>
+
+
+Description
+-----------
+The LP3944 is a helper chip that can drive up to 8 leds, with two programmable
+DIM modes; it could even be used as a gpio expander but this driver assumes it
+is used as a led controller.
+
+The DIM modes are used to set _blink_ patterns for leds, the pattern is
+specified supplying two parameters:
+  - period: from 0s to 1.6s
+  - duty cycle: percentage of the period the led is on, from 0 to 100
+
+Setting a led in DIM0 or DIM1 mode makes it blink according to the pattern.
+See the datasheet for details.
+
+LP3944 can be found on Motorola A910 smartphone, where it drives the rgb
+leds, the camera flash light and the lcds power.
+
+
+Notes
+-----
+The chip is used mainly in embedded contexts, so this driver expects it is
+registered using the i2c_board_info mechanism.
+
+To register the chip at address 0x60 on adapter 0, set the platform data
+according to include/linux/leds-lp3944.h, set the i2c board info:
+
+	static struct i2c_board_info __initdata a910_i2c_board_info[] = {
+		{
+			I2C_BOARD_INFO("lp3944", 0x60),
+			.platform_data = &a910_lp3944_leds,
+		},
+	};
+
+and register it in the platform init function
+
+	i2c_register_board_info(0, a910_i2c_board_info,
+			ARRAY_SIZE(a910_i2c_board_info));
diff -druN linux-libre-2.6.30-gnu/Documentation/lguest/lguest.c linux-libre-2.6.31-gnu/Documentation/lguest/lguest.c
--- linux-libre-2.6.30-gnu/Documentation/lguest/lguest.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/lguest/lguest.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,9 @@
-/*P:100 This is the Launcher code, a simple program which lays out the
- * "physical" memory for the new Guest by mapping the kernel image and
- * the virtual devices, then opens /dev/lguest to tell the kernel
- * about the Guest and control it. :*/
+/*P:100
+ * This is the Launcher code, a simple program which lays out the "physical"
+ * memory for the new Guest by mapping the kernel image and the virtual
+ * devices, then opens /dev/lguest to tell the kernel about the Guest and
+ * control it.
+:*/
 #define _LARGEFILE64_SOURCE
 #define _GNU_SOURCE
 #include <stdio.h>
@@ -16,6 +18,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <sys/eventfd.h>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <errno.h>
@@ -45,13 +48,15 @@
 #include "linux/virtio_rng.h"
 #include "linux/virtio_ring.h"
 #include "asm/bootparam.h"
-/*L:110 We can ignore the 39 include files we need for this program, but I do
- * want to draw attention to the use of kernel-style types.
+/*L:110
+ * We can ignore the 42 include files we need for this program, but I do want
+ * to draw attention to the use of kernel-style types.
  *
  * As Linus said, "C is a Spartan language, and so should your naming be."  I
  * like these abbreviations, so we define them here.  Note that u64 is always
  * unsigned long long, which works on all Linux systems: this means that we can
- * use %llu in printf for any u64. */
+ * use %llu in printf for any u64.
+ */
 typedef unsigned long long u64;
 typedef uint32_t u32;
 typedef uint16_t u16;
@@ -59,7 +64,6 @@
 /*:*/
 
 #define PAGE_PRESENT 0x7 	/* Present, RW, Execute */
-#define NET_PEERNUM 1
 #define BRIDGE_PFX "bridge:"
 #ifndef SIOCBRADDIF
 #define SIOCBRADDIF	0x89a2		/* add interface to bridge      */
@@ -69,38 +73,27 @@
 /* This will occupy 3 pages: it must be a power of 2. */
 #define VIRTQUEUE_NUM 256
 
-/*L:120 verbose is both a global flag and a macro.  The C preprocessor allows
- * this, and although I wouldn't recommend it, it works quite nicely here. */
+/*L:120
+ * verbose is both a global flag and a macro.  The C preprocessor allows
+ * this, and although I wouldn't recommend it, it works quite nicely here.
+ */
 static bool verbose;
 #define verbose(args...) \
 	do { if (verbose) printf(args); } while(0)
 /*:*/
 
-/* File descriptors for the Waker. */
-struct {
-	int pipe[2];
-	int lguest_fd;
-} waker_fds;
-
 /* The pointer to the start of guest memory. */
 static void *guest_base;
 /* The maximum guest physical address allowed, and maximum possible. */
 static unsigned long guest_limit, guest_max;
-/* The pipe for signal hander to write to. */
-static int timeoutpipe[2];
-static unsigned int timeout_usec = 500;
+/* The /dev/lguest file descriptor. */
+static int lguest_fd;
 
 /* a per-cpu variable indicating whose vcpu is currently running */
 static unsigned int __thread cpu_id;
 
 /* This is our list of devices. */
-struct device_list
-{
-	/* Summary information about the devices in our list: ready to pass to
-	 * select() to ask which need servicing.*/
-	fd_set infds;
-	int max_infd;
-
+struct device_list {
 	/* Counter to assign interrupt numbers. */
 	unsigned int next_irq;
 
@@ -112,8 +105,7 @@
 
 	/* A single linked list of devices. */
 	struct device *dev;
-	/* And a pointer to the last device for easy append and also for
-	 * configuration appending. */
+	/* And a pointer to the last device for easy append. */
 	struct device *lastdev;
 };
 
@@ -121,35 +113,32 @@
 static struct device_list devices;
 
 /* The device structure describes a single device. */
-struct device
-{
+struct device {
 	/* The linked-list pointer. */
 	struct device *next;
 
-	/* The this device's descriptor, as mapped into the Guest. */
+	/* The device's descriptor, as mapped into the Guest. */
 	struct lguest_device_desc *desc;
 
+	/* We can't trust desc values once Guest has booted: we use these. */
+	unsigned int feature_len;
+	unsigned int num_vq;
+
 	/* The name of this device, for --verbose. */
 	const char *name;
 
-	/* If handle_input is set, it wants to be called when this file
-	 * descriptor is ready. */
-	int fd;
-	bool (*handle_input)(int fd, struct device *me);
-
 	/* Any queues attached to this device */
 	struct virtqueue *vq;
 
-	/* Handle status being finalized (ie. feature bits stable). */
-	void (*ready)(struct device *me);
+	/* Is it operational */
+	bool running;
 
 	/* Device-specific data. */
 	void *priv;
 };
 
 /* The virtqueue structure describes a queue attached to a device. */
-struct virtqueue
-{
+struct virtqueue {
 	struct virtqueue *next;
 
 	/* Which device owns me. */
@@ -164,31 +153,41 @@
 	/* Last available index we saw. */
 	u16 last_avail_idx;
 
-	/* The routine to call when the Guest pings us, or timeout. */
-	void (*handle_output)(int fd, struct virtqueue *me, bool timeout);
+	/* How many are used since we sent last irq? */
+	unsigned int pending_used;
 
-	/* Outstanding buffers */
-	unsigned int inflight;
+	/* Eventfd where Guest notifications arrive. */
+	int eventfd;
 
-	/* Is this blocked awaiting a timer? */
-	bool blocked;
+	/* Function for the thread which is servicing this virtqueue. */
+	void (*service)(struct virtqueue *vq);
+	pid_t thread;
 };
 
 /* Remember the arguments to the program so we can "reboot" */
 static char **main_args;
 
-/* Since guest is UP and we don't run at the same time, we don't need barriers.
- * But I include them in the code in case others copy it. */
-#define wmb()
+/* The original tty settings to restore on exit. */
+static struct termios orig_term;
 
-/* Convert an iovec element to the given type.
+/*
+ * We have to be careful with barriers: our devices are all run in separate
+ * threads and so we need to make sure that changes visible to the Guest happen
+ * in precise order.
+ */
+#define wmb() __asm__ __volatile__("" : : : "memory")
+#define mb() __asm__ __volatile__("" : : : "memory")
+
+/*
+ * Convert an iovec element to the given type.
  *
  * This is a fairly ugly trick: we need to know the size of the type and
  * alignment requirement to check the pointer is kosher.  It's also nice to
  * have the name of the type in case we report failure.
  *
  * Typing those three things all the time is cumbersome and error prone, so we
- * have a macro which sets them all up and passes to the real function. */
+ * have a macro which sets them all up and passes to the real function.
+ */
 #define convert(iov, type) \
 	((type *)_convert((iov), sizeof(type), __alignof__(type), #type))
 
@@ -205,8 +204,10 @@
 /* Wrapper for the last available index.  Makes it easier to change. */
 #define lg_last_avail(vq)	((vq)->last_avail_idx)
 
-/* The virtio configuration space is defined to be little-endian.  x86 is
- * little-endian too, but it's nice to be explicit so we have these helpers. */
+/*
+ * The virtio configuration space is defined to be little-endian.  x86 is
+ * little-endian too, but it's nice to be explicit so we have these helpers.
+ */
 #define cpu_to_le16(v16) (v16)
 #define cpu_to_le32(v32) (v32)
 #define cpu_to_le64(v64) (v64)
@@ -245,14 +246,15 @@
 static u8 *get_feature_bits(struct device *dev)
 {
 	return (u8 *)(dev->desc + 1)
-		+ dev->desc->num_vq * sizeof(struct lguest_vqconfig);
+		+ dev->num_vq * sizeof(struct lguest_vqconfig);
 }
 
-/*L:100 The Launcher code itself takes us out into userspace, that scary place
- * where pointers run wild and free!  Unfortunately, like most userspace
- * programs, it's quite boring (which is why everyone likes to hack on the
- * kernel!).  Perhaps if you make up an Lguest Drinking Game at this point, it
- * will get you through this section.  Or, maybe not.
+/*L:100
+ * The Launcher code itself takes us out into userspace, that scary place where
+ * pointers run wild and free!  Unfortunately, like most userspace programs,
+ * it's quite boring (which is why everyone likes to hack on the kernel!).
+ * Perhaps if you make up an Lguest Drinking Game at this point, it will get
+ * you through this section.  Or, maybe not.
  *
  * The Launcher sets up a big chunk of memory to be the Guest's "physical"
  * memory and stores it in "guest_base".  In other words, Guest physical ==
@@ -260,7 +262,8 @@
  *
  * This can be tough to get your head around, but usually it just means that we
  * use these trivial conversion functions when the Guest gives us it's
- * "physical" addresses: */
+ * "physical" addresses:
+ */
 static void *from_guest_phys(unsigned long addr)
 {
 	return guest_base + addr;
@@ -275,7 +278,8 @@
  * Loading the Kernel.
  *
  * We start with couple of simple helper routines.  open_or_die() avoids
- * error-checking code cluttering the callers: */
+ * error-checking code cluttering the callers:
+ */
 static int open_or_die(const char *name, int flags)
 {
 	int fd = open(name, flags);
@@ -290,12 +294,19 @@
 	int fd = open_or_die("/dev/zero", O_RDONLY);
 	void *addr;
 
-	/* We use a private mapping (ie. if we write to the page, it will be
-	 * copied). */
+	/*
+	 * We use a private mapping (ie. if we write to the page, it will be
+	 * copied).
+	 */
 	addr = mmap(NULL, getpagesize() * num,
 		    PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
 	if (addr == MAP_FAILED)
 		err(1, "Mmaping %u pages of /dev/zero", num);
+
+	/*
+	 * One neat mmap feature is that you can close the fd, and it
+	 * stays mapped.
+	 */
 	close(fd);
 
 	return addr;
@@ -312,20 +323,24 @@
 	return addr;
 }
 
-/* This routine is used to load the kernel or initrd.  It tries mmap, but if
+/*
+ * This routine is used to load the kernel or initrd.  It tries mmap, but if
  * that fails (Plan 9's kernel file isn't nicely aligned on page boundaries),
- * it falls back to reading the memory in. */
+ * it falls back to reading the memory in.
+ */
 static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
 {
 	ssize_t r;
 
-	/* We map writable even though for some segments are marked read-only.
+	/*
+	 * We map writable even though for some segments are marked read-only.
 	 * The kernel really wants to be writable: it patches its own
 	 * instructions.
 	 *
 	 * MAP_PRIVATE means that the page won't be copied until a write is
 	 * done to it.  This allows us to share untouched memory between
-	 * Guests. */
+	 * Guests.
+	 */
 	if (mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC,
 		 MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
 		return;
@@ -336,7 +351,8 @@
 		err(1, "Reading offset %lu len %lu gave %zi", offset, len, r);
 }
 
-/* This routine takes an open vmlinux image, which is in ELF, and maps it into
+/*
+ * This routine takes an open vmlinux image, which is in ELF, and maps it into
  * the Guest memory.  ELF = Embedded Linking Format, which is the format used
  * by all modern binaries on Linux including the kernel.
  *
@@ -344,23 +360,28 @@
  * address.  We use the physical address; the Guest will map itself to the
  * virtual address.
  *
- * We return the starting address. */
+ * We return the starting address.
+ */
 static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
 {
 	Elf32_Phdr phdr[ehdr->e_phnum];
 	unsigned int i;
 
-	/* Sanity checks on the main ELF header: an x86 executable with a
-	 * reasonable number of correctly-sized program headers. */
+	/*
+	 * Sanity checks on the main ELF header: an x86 executable with a
+	 * reasonable number of correctly-sized program headers.
+	 */
 	if (ehdr->e_type != ET_EXEC
 	    || ehdr->e_machine != EM_386
 	    || ehdr->e_phentsize != sizeof(Elf32_Phdr)
 	    || ehdr->e_phnum < 1 || ehdr->e_phnum > 65536U/sizeof(Elf32_Phdr))
 		errx(1, "Malformed elf header");
 
-	/* An ELF executable contains an ELF header and a number of "program"
+	/*
+	 * An ELF executable contains an ELF header and a number of "program"
 	 * headers which indicate which parts ("segments") of the program to
-	 * load where. */
+	 * load where.
+	 */
 
 	/* We read in all the program headers at once: */
 	if (lseek(elf_fd, ehdr->e_phoff, SEEK_SET) < 0)
@@ -368,8 +389,10 @@
 	if (read(elf_fd, phdr, sizeof(phdr)) != sizeof(phdr))
 		err(1, "Reading program headers");
 
-	/* Try all the headers: there are usually only three.  A read-only one,
-	 * a read-write one, and a "note" section which we don't load. */
+	/*
+	 * Try all the headers: there are usually only three.  A read-only one,
+	 * a read-write one, and a "note" section which we don't load.
+	 */
 	for (i = 0; i < ehdr->e_phnum; i++) {
 		/* If this isn't a loadable segment, we ignore it */
 		if (phdr[i].p_type != PT_LOAD)
@@ -387,13 +410,15 @@
 	return ehdr->e_entry;
 }
 
-/*L:150 A bzImage, unlike an ELF file, is not meant to be loaded.  You're
- * supposed to jump into it and it will unpack itself.  We used to have to
- * perform some hairy magic because the unpacking code scared me.
+/*L:150
+ * A bzImage, unlike an ELF file, is not meant to be loaded.  You're supposed
+ * to jump into it and it will unpack itself.  We used to have to perform some
+ * hairy magic because the unpacking code scared me.
  *
  * Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote
  * a small patch to jump over the tricky bits in the Guest, so now we just read
- * the funky header so we know where in the file to load, and away we go! */
+ * the funky header so we know where in the file to load, and away we go!
+ */
 static unsigned long load_bzimage(int fd)
 {
 	struct boot_params boot;
@@ -401,8 +426,10 @@
 	/* Modern bzImages get loaded at 1M. */
 	void *p = from_guest_phys(0x100000);
 
-	/* Go back to the start of the file and read the header.  It should be
-	 * a Linux boot header (see Documentation/x86/i386/boot.txt) */
+	/*
+	 * Go back to the start of the file and read the header.  It should be
+	 * a Linux boot header (see Documentation/x86/i386/boot.txt)
+	 */
 	lseek(fd, 0, SEEK_SET);
 	read(fd, &boot, sizeof(boot));
 
@@ -421,9 +448,11 @@
 	return boot.hdr.code32_start;
 }
 
-/*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels
+/*L:140
+ * Loading the kernel is easy when it's a "vmlinux", but most kernels
  * come wrapped up in the self-decompressing "bzImage" format.  With a little
- * work, we can load those, too. */
+ * work, we can load those, too.
+ */
 static unsigned long load_kernel(int fd)
 {
 	Elf32_Ehdr hdr;
@@ -440,24 +469,28 @@
 	return load_bzimage(fd);
 }
 
-/* This is a trivial little helper to align pages.  Andi Kleen hated it because
+/*
+ * This is a trivial little helper to align pages.  Andi Kleen hated it because
  * it calls getpagesize() twice: "it's dumb code."
  *
  * Kernel guys get really het up about optimization, even when it's not
- * necessary.  I leave this code as a reaction against that. */
+ * necessary.  I leave this code as a reaction against that.
+ */
 static inline unsigned long page_align(unsigned long addr)
 {
 	/* Add upwards and truncate downwards. */
 	return ((addr + getpagesize()-1) & ~(getpagesize()-1));
 }
 
-/*L:180 An "initial ram disk" is a disk image loaded into memory along with
- * the kernel which the kernel can use to boot from without needing any
- * drivers.  Most distributions now use this as standard: the initrd contains
- * the code to load the appropriate driver modules for the current machine.
+/*L:180
+ * An "initial ram disk" is a disk image loaded into memory along with the
+ * kernel which the kernel can use to boot from without needing any drivers.
+ * Most distributions now use this as standard: the initrd contains the code to
+ * load the appropriate driver modules for the current machine.
  *
  * Importantly, James Morris works for RedHat, and Fedora uses initrds for its
- * kernels.  He sent me this (and tells me when I break it). */
+ * kernels.  He sent me this (and tells me when I break it).
+ */
 static unsigned long load_initrd(const char *name, unsigned long mem)
 {
 	int ifd;
@@ -469,12 +502,16 @@
 	if (fstat(ifd, &st) < 0)
 		err(1, "fstat() on initrd '%s'", name);
 
-	/* We map the initrd at the top of memory, but mmap wants it to be
-	 * page-aligned, so we round the size up for that. */
+	/*
+	 * We map the initrd at the top of memory, but mmap wants it to be
+	 * page-aligned, so we round the size up for that.
+	 */
 	len = page_align(st.st_size);
 	map_at(ifd, from_guest_phys(mem - len), 0, st.st_size);
-	/* Once a file is mapped, you can close the file descriptor.  It's a
-	 * little odd, but quite useful. */
+	/*
+	 * Once a file is mapped, you can close the file descriptor.  It's a
+	 * little odd, but quite useful.
+	 */
 	close(ifd);
 	verbose("mapped initrd %s size=%lu @ %p\n", name, len, (void*)mem-len);
 
@@ -483,8 +520,10 @@
 }
 /*:*/
 
-/* Simple routine to roll all the commandline arguments together with spaces
- * between them. */
+/*
+ * Simple routine to roll all the commandline arguments together with spaces
+ * between them.
+ */
 static void concat(char *dst, char *args[])
 {
 	unsigned int i, len = 0;
@@ -501,104 +540,26 @@
 	dst[len] = '\0';
 }
 
-/*L:185 This is where we actually tell the kernel to initialize the Guest.  We
+/*L:185
+ * This is where we actually tell the kernel to initialize the Guest.  We
  * saw the arguments it expects when we looked at initialize() in lguest_user.c:
  * the base of Guest "physical" memory, the top physical page to allow and the
- * entry point for the Guest. */
-static int tell_kernel(unsigned long start)
+ * entry point for the Guest.
+ */
+static void tell_kernel(unsigned long start)
 {
 	unsigned long args[] = { LHREQ_INITIALIZE,
 				 (unsigned long)guest_base,
 				 guest_limit / getpagesize(), start };
-	int fd;
-
 	verbose("Guest: %p - %p (%#lx)\n",
 		guest_base, guest_base + guest_limit, guest_limit);
-	fd = open_or_die("/dev/lguest", O_RDWR);
-	if (write(fd, args, sizeof(args)) < 0)
+	lguest_fd = open_or_die("/dev/lguest", O_RDWR);
+	if (write(lguest_fd, args, sizeof(args)) < 0)
 		err(1, "Writing to /dev/lguest");
-
-	/* We return the /dev/lguest file descriptor to control this Guest */
-	return fd;
 }
 /*:*/
 
-static void add_device_fd(int fd)
-{
-	FD_SET(fd, &devices.infds);
-	if (fd > devices.max_infd)
-		devices.max_infd = fd;
-}
-
 /*L:200
- * The Waker.
- *
- * With console, block and network devices, we can have lots of input which we
- * need to process.  We could try to tell the kernel what file descriptors to
- * watch, but handing a file descriptor mask through to the kernel is fairly
- * icky.
- *
- * Instead, we clone off a thread which watches the file descriptors and writes
- * the LHREQ_BREAK command to the /dev/lguest file descriptor to tell the Host
- * stop running the Guest.  This causes the Launcher to return from the
- * /dev/lguest read with -EAGAIN, where it will write to /dev/lguest to reset
- * the LHREQ_BREAK and wake us up again.
- *
- * This, of course, is merely a different *kind* of icky.
- *
- * Given my well-known antipathy to threads, I'd prefer to use processes.  But
- * it's easier to share Guest memory with threads, and trivial to share the
- * devices.infds as the Launcher changes it.
- */
-static int waker(void *unused)
-{
-	/* Close the write end of the pipe: only the Launcher has it open. */
-	close(waker_fds.pipe[1]);
-
-	for (;;) {
-		fd_set rfds = devices.infds;
-		unsigned long args[] = { LHREQ_BREAK, 1 };
-		unsigned int maxfd = devices.max_infd;
-
-		/* We also listen to the pipe from the Launcher. */
-		FD_SET(waker_fds.pipe[0], &rfds);
-		if (waker_fds.pipe[0] > maxfd)
-			maxfd = waker_fds.pipe[0];
-
-		/* Wait until input is ready from one of the devices. */
-		select(maxfd+1, &rfds, NULL, NULL, NULL);
-
-		/* Message from Launcher? */
-		if (FD_ISSET(waker_fds.pipe[0], &rfds)) {
-			char c;
-			/* If this fails, then assume Launcher has exited.
-			 * Don't do anything on exit: we're just a thread! */
-			if (read(waker_fds.pipe[0], &c, 1) != 1)
-				_exit(0);
-			continue;
-		}
-
-		/* Send LHREQ_BREAK command to snap the Launcher out of it. */
-		pwrite(waker_fds.lguest_fd, args, sizeof(args), cpu_id);
-	}
-	return 0;
-}
-
-/* This routine just sets up a pipe to the Waker process. */
-static void setup_waker(int lguest_fd)
-{
-	/* This pipe is closed when Launcher dies, telling Waker. */
-	if (pipe(waker_fds.pipe) != 0)
-		err(1, "Creating pipe for Waker");
-
-	/* Waker also needs to know the lguest fd */
-	waker_fds.lguest_fd = lguest_fd;
-
-	if (clone(waker, malloc(4096) + 4096, CLONE_VM | SIGCHLD, NULL) == -1)
-		err(1, "Creating Waker");
-}
-
-/*
  * Device Handling.
  *
  * When the Guest gives us a buffer, it sends an array of addresses and sizes.
@@ -609,65 +570,125 @@
 static void *_check_pointer(unsigned long addr, unsigned int size,
 			    unsigned int line)
 {
-	/* We have to separately check addr and addr+size, because size could
-	 * be huge and addr + size might wrap around. */
+	/*
+	 * We have to separately check addr and addr+size, because size could
+	 * be huge and addr + size might wrap around.
+	 */
 	if (addr >= guest_limit || addr + size >= guest_limit)
 		errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr);
-	/* We return a pointer for the caller's convenience, now we know it's
-	 * safe to use. */
+	/*
+	 * We return a pointer for the caller's convenience, now we know it's
+	 * safe to use.
+	 */
 	return from_guest_phys(addr);
 }
 /* A macro which transparently hands the line number to the real function. */
 #define check_pointer(addr,size) _check_pointer(addr, size, __LINE__)
 
-/* Each buffer in the virtqueues is actually a chain of descriptors.  This
+/*
+ * Each buffer in the virtqueues is actually a chain of descriptors.  This
  * function returns the next descriptor in the chain, or vq->vring.num if we're
- * at the end. */
-static unsigned next_desc(struct virtqueue *vq, unsigned int i)
+ * at the end.
+ */
+static unsigned next_desc(struct vring_desc *desc,
+			  unsigned int i, unsigned int max)
 {
 	unsigned int next;
 
 	/* If this descriptor says it doesn't chain, we're done. */
-	if (!(vq->vring.desc[i].flags & VRING_DESC_F_NEXT))
-		return vq->vring.num;
+	if (!(desc[i].flags & VRING_DESC_F_NEXT))
+		return max;
 
 	/* Check they're not leading us off end of descriptors. */
-	next = vq->vring.desc[i].next;
+	next = desc[i].next;
 	/* Make sure compiler knows to grab that: we don't want it changing! */
 	wmb();
 
-	if (next >= vq->vring.num)
+	if (next >= max)
 		errx(1, "Desc next is %u", next);
 
 	return next;
 }
 
-/* This looks in the virtqueue and for the first available buffer, and converts
+/*
+ * This actually sends the interrupt for this virtqueue, if we've used a
+ * buffer.
+ */
+static void trigger_irq(struct virtqueue *vq)
+{
+	unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
+
+	/* Don't inform them if nothing used. */
+	if (!vq->pending_used)
+		return;
+	vq->pending_used = 0;
+
+	/* If they don't want an interrupt, don't send one, unless empty. */
+	if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+	    && lg_last_avail(vq) != vq->vring.avail->idx)
+		return;
+
+	/* Send the Guest an interrupt tell them we used something up. */
+	if (write(lguest_fd, buf, sizeof(buf)) != 0)
+		err(1, "Triggering irq %i", vq->config.irq);
+}
+
+/*
+ * This looks in the virtqueue for the first available buffer, and converts
  * it to an iovec for convenient access.  Since descriptors consist of some
  * number of output then some number of input descriptors, it's actually two
  * iovecs, but we pack them into one and note how many of each there were.
  *
- * This function returns the descriptor number found, or vq->vring.num (which
- * is never a valid descriptor number) if none was found. */
-static unsigned get_vq_desc(struct virtqueue *vq,
-			    struct iovec iov[],
-			    unsigned int *out_num, unsigned int *in_num)
+ * This function waits if necessary, and returns the descriptor number found.
+ */
+static unsigned wait_for_vq_desc(struct virtqueue *vq,
+				 struct iovec iov[],
+				 unsigned int *out_num, unsigned int *in_num)
 {
-	unsigned int i, head;
-	u16 last_avail;
+	unsigned int i, head, max;
+	struct vring_desc *desc;
+	u16 last_avail = lg_last_avail(vq);
+
+	/* There's nothing available? */
+	while (last_avail == vq->vring.avail->idx) {
+		u64 event;
+
+		/*
+		 * Since we're about to sleep, now is a good time to tell the
+		 * Guest about what we've used up to now.
+		 */
+		trigger_irq(vq);
+
+		/* OK, now we need to know about added descriptors. */
+		vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+
+		/*
+		 * They could have slipped one in as we were doing that: make
+		 * sure it's written, then check again.
+		 */
+		mb();
+		if (last_avail != vq->vring.avail->idx) {
+			vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+			break;
+		}
+
+		/* Nothing new?  Wait for eventfd to tell us they refilled. */
+		if (read(vq->eventfd, &event, sizeof(event)) != sizeof(event))
+			errx(1, "Event read failed?");
+
+		/* We don't need to be notified again. */
+		vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+	}
 
 	/* Check it isn't doing very strange things with descriptor numbers. */
-	last_avail = lg_last_avail(vq);
 	if ((u16)(vq->vring.avail->idx - last_avail) > vq->vring.num)
 		errx(1, "Guest moved used index from %u to %u",
 		     last_avail, vq->vring.avail->idx);
 
-	/* If there's nothing new since last we looked, return invalid. */
-	if (vq->vring.avail->idx == last_avail)
-		return vq->vring.num;
-
-	/* Grab the next descriptor number they're advertising, and increment
-	 * the index we've seen. */
+	/*
+	 * Grab the next descriptor number they're advertising, and increment
+	 * the index we've seen.
+	 */
 	head = vq->vring.avail->ring[last_avail % vq->vring.num];
 	lg_last_avail(vq)++;
 
@@ -678,87 +699,84 @@
 	/* When we start there are none of either input nor output. */
 	*out_num = *in_num = 0;
 
+	max = vq->vring.num;
+	desc = vq->vring.desc;
 	i = head;
+
+	/*
+	 * If this is an indirect entry, then this buffer contains a descriptor
+	 * table which we handle as if it's any normal descriptor chain.
+	 */
+	if (desc[i].flags & VRING_DESC_F_INDIRECT) {
+		if (desc[i].len % sizeof(struct vring_desc))
+			errx(1, "Invalid size for indirect buffer table");
+
+		max = desc[i].len / sizeof(struct vring_desc);
+		desc = check_pointer(desc[i].addr, desc[i].len);
+		i = 0;
+	}
+
 	do {
 		/* Grab the first descriptor, and check it's OK. */
-		iov[*out_num + *in_num].iov_len = vq->vring.desc[i].len;
+		iov[*out_num + *in_num].iov_len = desc[i].len;
 		iov[*out_num + *in_num].iov_base
-			= check_pointer(vq->vring.desc[i].addr,
-					vq->vring.desc[i].len);
+			= check_pointer(desc[i].addr, desc[i].len);
 		/* If this is an input descriptor, increment that count. */
-		if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE)
+		if (desc[i].flags & VRING_DESC_F_WRITE)
 			(*in_num)++;
 		else {
-			/* If it's an output descriptor, they're all supposed
-			 * to come before any input descriptors. */
+			/*
+			 * If it's an output descriptor, they're all supposed
+			 * to come before any input descriptors.
+			 */
 			if (*in_num)
 				errx(1, "Descriptor has out after in");
 			(*out_num)++;
 		}
 
 		/* If we've got too many, that implies a descriptor loop. */
-		if (*out_num + *in_num > vq->vring.num)
+		if (*out_num + *in_num > max)
 			errx(1, "Looped descriptor");
-	} while ((i = next_desc(vq, i)) != vq->vring.num);
+	} while ((i = next_desc(desc, i, max)) != max);
 
-	vq->inflight++;
 	return head;
 }
 
-/* After we've used one of their buffers, we tell them about it.  We'll then
- * want to send them an interrupt, using trigger_irq(). */
+/*
+ * After we've used one of their buffers, we tell the Guest about it.  Sometime
+ * later we'll want to send them an interrupt using trigger_irq(); note that
+ * wait_for_vq_desc() does that for us if it has to wait.
+ */
 static void add_used(struct virtqueue *vq, unsigned int head, int len)
 {
 	struct vring_used_elem *used;
 
-	/* The virtqueue contains a ring of used buffers.  Get a pointer to the
-	 * next entry in that used ring. */
+	/*
+	 * The virtqueue contains a ring of used buffers.  Get a pointer to the
+	 * next entry in that used ring.
+	 */
 	used = &vq->vring.used->ring[vq->vring.used->idx % vq->vring.num];
 	used->id = head;
 	used->len = len;
 	/* Make sure buffer is written before we update index. */
 	wmb();
 	vq->vring.used->idx++;
-	vq->inflight--;
-}
-
-/* This actually sends the interrupt for this virtqueue */
-static void trigger_irq(int fd, struct virtqueue *vq)
-{
-	unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
-
-	/* If they don't want an interrupt, don't send one, unless empty. */
-	if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
-	    && vq->inflight)
-		return;
-
-	/* Send the Guest an interrupt tell them we used something up. */
-	if (write(fd, buf, sizeof(buf)) != 0)
-		err(1, "Triggering irq %i", vq->config.irq);
+	vq->pending_used++;
 }
 
 /* And here's the combo meal deal.  Supersize me! */
-static void add_used_and_trigger(int fd, struct virtqueue *vq,
-				 unsigned int head, int len)
+static void add_used_and_trigger(struct virtqueue *vq, unsigned head, int len)
 {
 	add_used(vq, head, len);
-	trigger_irq(fd, vq);
+	trigger_irq(vq);
 }
 
 /*
  * The Console
  *
- * Here is the input terminal setting we save, and the routine to restore them
- * on exit so the user gets their terminal back. */
-static struct termios orig_term;
-static void restore_term(void)
-{
-	tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
-}
-
-/* We associate some data with the console for our exit hack. */
-struct console_abort
-{
+ * We associate some data with the console for our exit hack.
+ */
+struct console_abort {
 	/* How many times have they hit ^C? */
 	int count;
 	/* When did they start? */
@@ -766,282 +784,360 @@
 };
 
 /* This is the routine which handles console input (ie. stdin). */
-static bool handle_console_input(int fd, struct device *dev)
+static void console_input(struct virtqueue *vq)
 {
 	int len;
 	unsigned int head, in_num, out_num;
-	struct iovec iov[dev->vq->vring.num];
-	struct console_abort *abort = dev->priv;
-
-	/* First we need a console buffer from the Guests's input virtqueue. */
-	head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
-
-	/* If they're not ready for input, stop listening to this file
-	 * descriptor.  We'll start again once they add an input buffer. */
-	if (head == dev->vq->vring.num)
-		return false;
+	struct console_abort *abort = vq->dev->priv;
+	struct iovec iov[vq->vring.num];
 
+	/* Make sure there's a descriptor available. */
+	head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
 	if (out_num)
 		errx(1, "Output buffers in console in queue?");
 
-	/* This is why we convert to iovecs: the readv() call uses them, and so
-	 * it reads straight into the Guest's buffer. */
-	len = readv(dev->fd, iov, in_num);
+	/* Read into it.  This is where we usually wait. */
+	len = readv(STDIN_FILENO, iov, in_num);
 	if (len <= 0) {
-		/* This implies that the console is closed, is /dev/null, or
-		 * something went terribly wrong. */
+		/* Ran out of input? */
 		warnx("Failed to get console input, ignoring console.");
-		/* Put the input terminal back. */
-		restore_term();
-		/* Remove callback from input vq, so it doesn't restart us. */
-		dev->vq->handle_output = NULL;
-		/* Stop listening to this fd: don't call us again. */
-		return false;
+		/*
+		 * For simplicity, dying threads kill the whole Launcher.  So
+		 * just nap here.
+		 */
+		for (;;)
+			pause();
 	}
 
-	/* Tell the Guest about the new input. */
-	add_used_and_trigger(fd, dev->vq, head, len);
+	/* Tell the Guest we used a buffer. */
+	add_used_and_trigger(vq, head, len);
 
-	/* Three ^C within one second?  Exit.
+	/*
+	 * Three ^C within one second?  Exit.
 	 *
-	 * This is such a hack, but works surprisingly well.  Each ^C has to be
-	 * in a buffer by itself, so they can't be too fast.  But we check that
-	 * we get three within about a second, so they can't be too slow. */
-	if (len == 1 && ((char *)iov[0].iov_base)[0] == 3) {
-		if (!abort->count++)
-			gettimeofday(&abort->start, NULL);
-		else if (abort->count == 3) {
-			struct timeval now;
-			gettimeofday(&now, NULL);
-			if (now.tv_sec <= abort->start.tv_sec+1) {
-				unsigned long args[] = { LHREQ_BREAK, 0 };
-				/* Close the fd so Waker will know it has to
-				 * exit. */
-				close(waker_fds.pipe[1]);
-				/* Just in case Waker is blocked in BREAK, send
-				 * unbreak now. */
-				write(fd, args, sizeof(args));
-				exit(2);
-			}
-			abort->count = 0;
-		}
-	} else
-		/* Any other key resets the abort counter. */
+	 * This is such a hack, but works surprisingly well.  Each ^C has to
+	 * be in a buffer by itself, so they can't be too fast.  But we check
+	 * that we get three within about a second, so they can't be too
+	 * slow.
+	 */
+	if (len != 1 || ((char *)iov[0].iov_base)[0] != 3) {
 		abort->count = 0;
+		return;
+	}
 
-	/* Everything went OK! */
-	return true;
+	abort->count++;
+	if (abort->count == 1)
+		gettimeofday(&abort->start, NULL);
+	else if (abort->count == 3) {
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		/* Kill all Launcher processes with SIGINT, like normal ^C */
+		if (now.tv_sec <= abort->start.tv_sec+1)
+			kill(0, SIGINT);
+		abort->count = 0;
+	}
 }
 
-/* Handling output for console is simple: we just get all the output buffers
- * and write them to stdout. */
-static void handle_console_output(int fd, struct virtqueue *vq, bool timeout)
+/* This is the routine which handles console output (ie. stdout). */
+static void console_output(struct virtqueue *vq)
 {
 	unsigned int head, out, in;
-	int len;
 	struct iovec iov[vq->vring.num];
 
-	/* Keep getting output buffers from the Guest until we run out. */
-	while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
-		if (in)
-			errx(1, "Input buffers in output queue?");
-		len = writev(STDOUT_FILENO, iov, out);
-		add_used_and_trigger(fd, vq, head, len);
+	/* We usually wait in here, for the Guest to give us something. */
+	head = wait_for_vq_desc(vq, iov, &out, &in);
+	if (in)
+		errx(1, "Input buffers in console output queue?");
+
+	/* writev can return a partial write, so we loop here. */
+	while (!iov_empty(iov, out)) {
+		int len = writev(STDOUT_FILENO, iov, out);
+		if (len <= 0)
+			err(1, "Write to stdout gave %i", len);
+		iov_consume(iov, out, len);
 	}
+
+	/*
+	 * We're finished with that buffer: if we're going to sleep,
+	 * wait_for_vq_desc() will prod the Guest with an interrupt.
+	 */
+	add_used(vq, head, 0);
 }
 
-/* This is called when we no longer want to hear about Guest changes to a
- * virtqueue.  This is more efficient in high-traffic cases, but it means we
- * have to set a timer to check if any more changes have occurred. */
-static void block_vq(struct virtqueue *vq)
-{
-	struct itimerval itm;
+/*
+ * The Network
+ *
+ * Handling output for network is also simple: we get all the output buffers
+ * and write them to /dev/net/tun.
+ */
+struct net_info {
+	int tunfd;
+};
 
-	vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
-	vq->blocked = true;
+static void net_output(struct virtqueue *vq)
+{
+	struct net_info *net_info = vq->dev->priv;
+	unsigned int head, out, in;
+	struct iovec iov[vq->vring.num];
 
-	itm.it_interval.tv_sec = 0;
-	itm.it_interval.tv_usec = 0;
-	itm.it_value.tv_sec = 0;
-	itm.it_value.tv_usec = timeout_usec;
+	/* We usually wait in here for the Guest to give us a packet. */
+	head = wait_for_vq_desc(vq, iov, &out, &in);
+	if (in)
+		errx(1, "Input buffers in net output queue?");
+	/*
+	 * Send the whole thing through to /dev/net/tun.  It expects the exact
+	 * same format: what a coincidence!
+	 */
+	if (writev(net_info->tunfd, iov, out) < 0)
+		errx(1, "Write to tun failed?");
 
-	setitimer(ITIMER_REAL, &itm, NULL);
+	/*
+	 * Done with that one; wait_for_vq_desc() will send the interrupt if
+	 * all packets are processed.
+	 */
+	add_used(vq, head, 0);
 }
 
 /*
- * The Network
+ * Handling network input is a bit trickier, because I've tried to optimize it.
  *
- * Handling output for network is also simple: we get all the output buffers
- * and write them (ignoring the first element) to this device's file descriptor
- * (/dev/net/tun).
+ * First we have a helper routine which tells is if from this file descriptor
+ * (ie. the /dev/net/tun device) will block:
  */
-static void handle_net_output(int fd, struct virtqueue *vq, bool timeout)
+static bool will_block(int fd)
+{
+	fd_set fdset;
+	struct timeval zero = { 0, 0 };
+	FD_ZERO(&fdset);
+	FD_SET(fd, &fdset);
+	return select(fd+1, &fdset, NULL, NULL, &zero) != 1;
+}
+
+/*
+ * This handles packets coming in from the tun device to our Guest.  Like all
+ * service routines, it gets called again as soon as it returns, so you don't
+ * see a while(1) loop here.
+ */
+static void net_input(struct virtqueue *vq)
 {
-	unsigned int head, out, in, num = 0;
 	int len;
+	unsigned int head, out, in;
 	struct iovec iov[vq->vring.num];
-	static int last_timeout_num;
+	struct net_info *net_info = vq->dev->priv;
 
-	/* Keep getting output buffers from the Guest until we run out. */
-	while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
-		if (in)
-			errx(1, "Input buffers in output queue?");
-		len = writev(vq->dev->fd, iov, out);
-		if (len < 0)
-			err(1, "Writing network packet to tun");
-		add_used_and_trigger(fd, vq, head, len);
-		num++;
-	}
+	/*
+	 * Get a descriptor to write an incoming packet into.  This will also
+	 * send an interrupt if they're out of descriptors.
+	 */
+	head = wait_for_vq_desc(vq, iov, &out, &in);
+	if (out)
+		errx(1, "Output buffers in net input queue?");
 
-	/* Block further kicks and set up a timer if we saw anything. */
-	if (!timeout && num)
-		block_vq(vq);
+	/*
+	 * If it looks like we'll block reading from the tun device, send them
+	 * an interrupt.
+	 */
+	if (vq->pending_used && will_block(net_info->tunfd))
+		trigger_irq(vq);
 
-	/* We never quite know how long should we wait before we check the
-	 * queue again for more packets.  We start at 500 microseconds, and if
-	 * we get fewer packets than last time, we assume we made the timeout
-	 * too small and increase it by 10 microseconds.  Otherwise, we drop it
-	 * by one microsecond every time.  It seems to work well enough. */
-	if (timeout) {
-		if (num < last_timeout_num)
-			timeout_usec += 10;
-		else if (timeout_usec > 1)
-			timeout_usec--;
-		last_timeout_num = num;
-	}
+	/*
+	 * Read in the packet.  This is where we normally wait (when there's no
+	 * incoming network traffic).
+	 */
+	len = readv(net_info->tunfd, iov, in);
+	if (len <= 0)
+		err(1, "Failed to read from tun.");
+
+	/*
+	 * Mark that packet buffer as used, but don't interrupt here.  We want
+	 * to wait until we've done as much work as we can.
+	 */
+	add_used(vq, head, len);
 }
+/*:*/
 
-/* This is where we handle a packet coming in from the tun device to our
- * Guest. */
-static bool handle_tun_input(int fd, struct device *dev)
+/* This is the helper to create threads: run the service routine in a loop. */
+static int do_thread(void *_vq)
 {
-	unsigned int head, in_num, out_num;
-	int len;
-	struct iovec iov[dev->vq->vring.num];
+	struct virtqueue *vq = _vq;
 
-	/* First we need a network buffer from the Guests's recv virtqueue. */
-	head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
-	if (head == dev->vq->vring.num) {
-		/* Now, it's expected that if we try to send a packet too
-		 * early, the Guest won't be ready yet.  Wait until the device
-		 * status says it's ready. */
-		/* FIXME: Actually want DRIVER_ACTIVE here. */
+	for (;;)
+		vq->service(vq);
+	return 0;
+}
 
-		/* Now tell it we want to know if new things appear. */
-		dev->vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
-		wmb();
+/*
+ * When a child dies, we kill our entire process group with SIGTERM.  This
+ * also has the side effect that the shell restores the console for us!
+ */
+static void kill_launcher(int signal)
+{
+	kill(0, SIGTERM);
+}
 
-		/* We'll turn this back on if input buffers are registered. */
-		return false;
-	} else if (out_num)
-		errx(1, "Output buffers in network recv queue?");
+static void reset_device(struct device *dev)
+{
+	struct virtqueue *vq;
 
-	/* Read the packet from the device directly into the Guest's buffer. */
-	len = readv(dev->fd, iov, in_num);
-	if (len <= 0)
-		err(1, "reading network");
+	verbose("Resetting device %s\n", dev->name);
 
-	/* Tell the Guest about the new packet. */
-	add_used_and_trigger(fd, dev->vq, head, len);
+	/* Clear any features they've acked. */
+	memset(get_feature_bits(dev) + dev->feature_len, 0, dev->feature_len);
 
-	verbose("tun input packet len %i [%02x %02x] (%s)\n", len,
-		((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1],
-		head != dev->vq->vring.num ? "sent" : "discarded");
+	/* We're going to be explicitly killing threads, so ignore them. */
+	signal(SIGCHLD, SIG_IGN);
 
-	/* All good. */
-	return true;
+	/* Zero out the virtqueues, get rid of their threads */
+	for (vq = dev->vq; vq; vq = vq->next) {
+		if (vq->thread != (pid_t)-1) {
+			kill(vq->thread, SIGTERM);
+			waitpid(vq->thread, NULL, 0);
+			vq->thread = (pid_t)-1;
+		}
+		memset(vq->vring.desc, 0,
+		       vring_size(vq->config.num, LGUEST_VRING_ALIGN));
+		lg_last_avail(vq) = 0;
+	}
+	dev->running = false;
+
+	/* Now we care if threads die. */
+	signal(SIGCHLD, (void *)kill_launcher);
 }
 
-/*L:215 This is the callback attached to the network and console input
- * virtqueues: it ensures we try again, in case we stopped console or net
- * delivery because Guest didn't have any buffers. */
-static void enable_fd(int fd, struct virtqueue *vq, bool timeout)
+/*L:216
+ * This actually creates the thread which services the virtqueue for a device.
+ */
+static void create_thread(struct virtqueue *vq)
 {
-	add_device_fd(vq->dev->fd);
-	/* Snap the Waker out of its select loop. */
-	write(waker_fds.pipe[1], "", 1);
+	/*
+	 * Create stack for thread.  Since the stack grows upwards, we point
+	 * the stack pointer to the end of this region.
+	 */
+	char *stack = malloc(32768);
+	unsigned long args[] = { LHREQ_EVENTFD,
+				 vq->config.pfn*getpagesize(), 0 };
+
+	/* Create a zero-initialized eventfd. */
+	vq->eventfd = eventfd(0, 0);
+	if (vq->eventfd < 0)
+		err(1, "Creating eventfd");
+	args[2] = vq->eventfd;
+
+	/*
+	 * Attach an eventfd to this virtqueue: it will go off when the Guest
+	 * does an LHCALL_NOTIFY for this vq.
+	 */
+	if (write(lguest_fd, &args, sizeof(args)) != 0)
+		err(1, "Attaching eventfd");
+
+	/*
+	 * CLONE_VM: because it has to access the Guest memory, and SIGCHLD so
+	 * we get a signal if it dies.
+	 */
+	vq->thread = clone(do_thread, stack + 32768, CLONE_VM | SIGCHLD, vq);
+	if (vq->thread == (pid_t)-1)
+		err(1, "Creating clone");
+
+	/* We close our local copy now the child has it. */
+	close(vq->eventfd);
 }
 
-static void net_enable_fd(int fd, struct virtqueue *vq, bool timeout)
+static void start_device(struct device *dev)
 {
-	/* We don't need to know again when Guest refills receive buffer. */
-	vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
-	enable_fd(fd, vq, timeout);
+	unsigned int i;
+	struct virtqueue *vq;
+
+	verbose("Device %s OK: offered", dev->name);
+	for (i = 0; i < dev->feature_len; i++)
+		verbose(" %02x", get_feature_bits(dev)[i]);
+	verbose(", accepted");
+	for (i = 0; i < dev->feature_len; i++)
+		verbose(" %02x", get_feature_bits(dev)
+			[dev->feature_len+i]);
+
+	for (vq = dev->vq; vq; vq = vq->next) {
+		if (vq->service)
+			create_thread(vq);
+	}
+	dev->running = true;
 }
 
-/* When the Guest tells us they updated the status field, we handle it. */
-static void update_device_status(struct device *dev)
+static void cleanup_devices(void)
 {
-	struct virtqueue *vq;
+	struct device *dev;
 
-	/* This is a reset. */
-	if (dev->desc->status == 0) {
-		verbose("Resetting device %s\n", dev->name);
+	for (dev = devices.dev; dev; dev = dev->next)
+		reset_device(dev);
 
-		/* Clear any features they've acked. */
-		memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
-		       dev->desc->feature_len);
+	/* If we saved off the original terminal settings, restore them now. */
+	if (orig_term.c_lflag & (ISIG|ICANON|ECHO))
+		tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
+}
 
-		/* Zero out the virtqueues. */
-		for (vq = dev->vq; vq; vq = vq->next) {
-			memset(vq->vring.desc, 0,
-			       vring_size(vq->config.num, LGUEST_VRING_ALIGN));
-			lg_last_avail(vq) = 0;
-		}
-	} else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
+/* When the Guest tells us they updated the status field, we handle it. */
+static void update_device_status(struct device *dev)
+{
+	/* A zero status is a reset, otherwise it's a set of flags. */
+	if (dev->desc->status == 0)
+		reset_device(dev);
+	else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
 		warnx("Device %s configuration FAILED", dev->name);
+		if (dev->running)
+			reset_device(dev);
 	} else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
-		unsigned int i;
-
-		verbose("Device %s OK: offered", dev->name);
-		for (i = 0; i < dev->desc->feature_len; i++)
-			verbose(" %02x", get_feature_bits(dev)[i]);
-		verbose(", accepted");
-		for (i = 0; i < dev->desc->feature_len; i++)
-			verbose(" %02x", get_feature_bits(dev)
-				[dev->desc->feature_len+i]);
-
-		if (dev->ready)
-			dev->ready(dev);
+		if (!dev->running)
+			start_device(dev);
 	}
 }
 
-/* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */
-static void handle_output(int fd, unsigned long addr)
+/*L:215
+ * This is the generic routine we call when the Guest uses LHCALL_NOTIFY.  In
+ * particular, it's used to notify us of device status changes during boot.
+ */
+static void handle_output(unsigned long addr)
 {
 	struct device *i;
-	struct virtqueue *vq;
 
-	/* Check each device and virtqueue. */
+	/* Check each device. */
 	for (i = devices.dev; i; i = i->next) {
-		/* Notifications to device descriptors update device status. */
+		struct virtqueue *vq;
+
+		/*
+		 * Notifications to device descriptors mean they updated the
+		 * device status.
+		 */
 		if (from_guest_phys(addr) == i->desc) {
 			update_device_status(i);
 			return;
 		}
 
-		/* Notifications to virtqueues mean output has occurred. */
+		/*
+		 * Devices *can* be used before status is set to DRIVER_OK.
+		 * The original plan was that they would never do this: they
+		 * would always finish setting up their status bits before
+		 * actually touching the virtqueues.  In practice, we allowed
+		 * them to, and they do (eg. the disk probes for partition
+		 * tables as part of initialization).
+		 *
+		 * If we see this, we start the device: once it's running, we
+		 * expect the device to catch all the notifications.
+		 */
 		for (vq = i->vq; vq; vq = vq->next) {
-			if (vq->config.pfn != addr/getpagesize())
+			if (addr != vq->config.pfn*getpagesize())
 				continue;
-
-			/* Guest should acknowledge (and set features!)  before
-			 * using the device. */
-			if (i->desc->status == 0) {
-				warnx("%s gave early output", i->name);
-				return;
-			}
-
-			if (strcmp(vq->dev->name, "console") != 0)
-				verbose("Output to %s\n", vq->dev->name);
-			if (vq->handle_output)
-				vq->handle_output(fd, vq, false);
+			if (i->running)
+				errx(1, "Notification on running %s", i->name);
+			/* This just calls create_thread() for each virtqueue */
+			start_device(i);
 			return;
 		}
 	}
 
-	/* Early console write is done using notify on a nul-terminated string
-	 * in Guest memory. */
+	/*
+	 * Early console write is done using notify on a nul-terminated string
+	 * in Guest memory.  It's also great for hacking debugging messages
+	 * into a Guest.
+	 */
 	if (addr >= guest_limit)
 		errx(1, "Bad NOTIFY %#lx", addr);
 
@@ -1049,71 +1145,6 @@
 	      strnlen(from_guest_phys(addr), guest_limit - addr));
 }
 
-static void handle_timeout(int fd)
-{
-	char buf[32];
-	struct device *i;
-	struct virtqueue *vq;
-
-	/* Clear the pipe */
-	read(timeoutpipe[0], buf, sizeof(buf));
-
-	/* Check each device and virtqueue: flush blocked ones. */
-	for (i = devices.dev; i; i = i->next) {
-		for (vq = i->vq; vq; vq = vq->next) {
-			if (!vq->blocked)
-				continue;
-
-			vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
-			vq->blocked = false;
-			if (vq->handle_output)
-				vq->handle_output(fd, vq, true);
-		}
-	}
-}
-
-/* This is called when the Waker wakes us up: check for incoming file
- * descriptors. */
-static void handle_input(int fd)
-{
-	/* select() wants a zeroed timeval to mean "don't wait". */
-	struct timeval poll = { .tv_sec = 0, .tv_usec = 0 };
-
-	for (;;) {
-		struct device *i;
-		fd_set fds = devices.infds;
-		int num;
-
-		num = select(devices.max_infd+1, &fds, NULL, NULL, &poll);
-		/* Could get interrupted */
-		if (num < 0)
-			continue;
-		/* If nothing is ready, we're done. */
-		if (num == 0)
-			break;
-
-		/* Otherwise, call the device(s) which have readable file
-		 * descriptors and a method of handling them.  */
-		for (i = devices.dev; i; i = i->next) {
-			if (i->handle_input && FD_ISSET(i->fd, &fds)) {
-				if (i->handle_input(fd, i))
-					continue;
-
-				/* If handle_input() returns false, it means we
-				 * should no longer service it.  Networking and
-				 * console do this when there's no input
-				 * buffers to deliver into.  Console also uses
-				 * it when it discovers that stdin is closed. */
-				FD_CLR(i->fd, &devices.infds);
-			}
-		}
-
-		/* Is this the timeout fd? */
-		if (FD_ISSET(timeoutpipe[0], &fds))
-			handle_timeout(fd);
-	}
-}
-
 /*L:190
  * Device Setup
  *
@@ -1122,20 +1153,24 @@
  * routines to allocate and manage them.
  */
 
-/* The layout of the device page is a "struct lguest_device_desc" followed by a
+/*
+ * The layout of the device page is a "struct lguest_device_desc" followed by a
  * number of virtqueue descriptors, then two sets of feature bits, then an
  * array of configuration bytes.  This routine returns the configuration
- * pointer. */
+ * pointer.
+ */
 static u8 *device_config(const struct device *dev)
 {
 	return (void *)(dev->desc + 1)
-		+ dev->desc->num_vq * sizeof(struct lguest_vqconfig)
-		+ dev->desc->feature_len * 2;
+		+ dev->num_vq * sizeof(struct lguest_vqconfig)
+		+ dev->feature_len * 2;
 }
 
-/* This routine allocates a new "struct lguest_device_desc" from descriptor
+/*
+ * This routine allocates a new "struct lguest_device_desc" from descriptor
  * table page just above the Guest's normal memory.  It returns a pointer to
- * that descriptor. */
+ * that descriptor.
+ */
 static struct lguest_device_desc *new_dev_desc(u16 type)
 {
 	struct lguest_device_desc d = { .type = type };
@@ -1156,10 +1191,12 @@
 	return memcpy(p, &d, sizeof(d));
 }
 
-/* Each device descriptor is followed by the description of its virtqueues.  We
- * specify how many descriptors the virtqueue is to have. */
+/*
+ * Each device descriptor is followed by the description of its virtqueues.  We
+ * specify how many descriptors the virtqueue is to have.
+ */
 static void add_virtqueue(struct device *dev, unsigned int num_descs,
-			  void (*handle_output)(int, struct virtqueue *, bool))
+			  void (*service)(struct virtqueue *))
 {
 	unsigned int pages;
 	struct virtqueue **i, *vq = malloc(sizeof(*vq));
@@ -1174,8 +1211,13 @@
 	vq->next = NULL;
 	vq->last_avail_idx = 0;
 	vq->dev = dev;
-	vq->inflight = 0;
-	vq->blocked = false;
+
+	/*
+	 * This is the routine the service thread will run, and its Process ID
+	 * once it's running.
+	 */
+	vq->service = service;
+	vq->thread = (pid_t)-1;
 
 	/* Initialize the configuration. */
 	vq->config.num = num_descs;
@@ -1185,33 +1227,31 @@
 	/* Initialize the vring. */
 	vring_init(&vq->vring, num_descs, p, LGUEST_VRING_ALIGN);
 
-	/* Append virtqueue to this device's descriptor.  We use
+	/*
+	 * Append virtqueue to this device's descriptor.  We use
 	 * device_config() to get the end of the device's current virtqueues;
 	 * we check that we haven't added any config or feature information
-	 * yet, otherwise we'd be overwriting them. */
+	 * yet, otherwise we'd be overwriting them.
+	 */
 	assert(dev->desc->config_len == 0 && dev->desc->feature_len == 0);
 	memcpy(device_config(dev), &vq->config, sizeof(vq->config));
+	dev->num_vq++;
 	dev->desc->num_vq++;
 
 	verbose("Virtqueue page %#lx\n", to_guest_phys(p));
 
-	/* Add to tail of list, so dev->vq is first vq, dev->vq->next is
-	 * second.  */
+	/*
+	 * Add to tail of list, so dev->vq is first vq, dev->vq->next is
+	 * second.
+	 */
 	for (i = &dev->vq; *i; i = &(*i)->next);
 	*i = vq;
-
-	/* Set the routine to call when the Guest does something to this
-	 * virtqueue. */
-	vq->handle_output = handle_output;
-
-	/* As an optimization, set the advisory "Don't Notify Me" flag if we
-	 * don't have a handler */
-	if (!handle_output)
-		vq->vring.used->flags = VRING_USED_F_NO_NOTIFY;
 }
 
-/* The first half of the feature bitmask is for us to advertise features.  The
- * second half is for the Guest to accept features. */
+/*
+ * The first half of the feature bitmask is for us to advertise features.  The
+ * second half is for the Guest to accept features.
+ */
 static void add_feature(struct device *dev, unsigned bit)
 {
 	u8 *features = get_feature_bits(dev);
@@ -1219,15 +1259,17 @@
 	/* We can't extend the feature bits once we've added config bytes */
 	if (dev->desc->feature_len <= bit / CHAR_BIT) {
 		assert(dev->desc->config_len == 0);
-		dev->desc->feature_len = (bit / CHAR_BIT) + 1;
+		dev->feature_len = dev->desc->feature_len = (bit/CHAR_BIT) + 1;
 	}
 
 	features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT));
 }
 
-/* This routine sets the configuration fields for an existing device's
+/*
+ * This routine sets the configuration fields for an existing device's
  * descriptor.  It only works for the last device, but that's OK because that's
- * how we use it. */
+ * how we use it.
+ */
 static void set_config(struct device *dev, unsigned len, const void *conf)
 {
 	/* Check we haven't overflowed our single page. */
@@ -1237,33 +1279,36 @@
 	/* Copy in the config information, and store the length. */
 	memcpy(device_config(dev), conf, len);
 	dev->desc->config_len = len;
+
+	/* Size must fit in config_len field (8 bits)! */
+	assert(dev->desc->config_len == len);
 }
 
-/* This routine does all the creation and setup of a new device, including
- * calling new_dev_desc() to allocate the descriptor and device memory.
+/*
+ * This routine does all the creation and setup of a new device, including
+ * calling new_dev_desc() to allocate the descriptor and device memory.  We
+ * don't actually start the service threads until later.
  *
- * See what I mean about userspace being boring? */
-static struct device *new_device(const char *name, u16 type, int fd,
-				 bool (*handle_input)(int, struct device *))
+ * See what I mean about userspace being boring?
+ */
+static struct device *new_device(const char *name, u16 type)
 {
 	struct device *dev = malloc(sizeof(*dev));
 
 	/* Now we populate the fields one at a time. */
-	dev->fd = fd;
-	/* If we have an input handler for this file descriptor, then we add it
-	 * to the device_list's fdset and maxfd. */
-	if (handle_input)
-		add_device_fd(dev->fd);
 	dev->desc = new_dev_desc(type);
-	dev->handle_input = handle_input;
 	dev->name = name;
 	dev->vq = NULL;
-	dev->ready = NULL;
+	dev->feature_len = 0;
+	dev->num_vq = 0;
+	dev->running = false;
 
-	/* Append to device list.  Prepending to a single-linked list is
+	/*
+	 * Append to device list.  Prepending to a single-linked list is
 	 * easier, but the user expects the devices to be arranged on the bus
 	 * in command-line order.  The first network device on the command line
-	 * is eth0, the first block device /dev/vda, etc. */
+	 * is eth0, the first block device /dev/vda, etc.
+	 */
 	if (devices.lastdev)
 		devices.lastdev->next = dev;
 	else
@@ -1273,8 +1318,10 @@
 	return dev;
 }
 
-/* Our first setup routine is the console.  It's a fairly simple device, but
- * UNIX tty handling makes it uglier than it could be. */
+/*
+ * Our first setup routine is the console.  It's a fairly simple device, but
+ * UNIX tty handling makes it uglier than it could be.
+ */
 static void setup_console(void)
 {
 	struct device *dev;
@@ -1282,51 +1329,35 @@
 	/* If we can save the initial standard input settings... */
 	if (tcgetattr(STDIN_FILENO, &orig_term) == 0) {
 		struct termios term = orig_term;
-		/* Then we turn off echo, line buffering and ^C etc.  We want a
-		 * raw input stream to the Guest. */
+		/*
+		 * Then we turn off echo, line buffering and ^C etc: We want a
+		 * raw input stream to the Guest.
+		 */
 		term.c_lflag &= ~(ISIG|ICANON|ECHO);
 		tcsetattr(STDIN_FILENO, TCSANOW, &term);
-		/* If we exit gracefully, the original settings will be
-		 * restored so the user can see what they're typing. */
-		atexit(restore_term);
 	}
 
-	dev = new_device("console", VIRTIO_ID_CONSOLE,
-			 STDIN_FILENO, handle_console_input);
+	dev = new_device("console", VIRTIO_ID_CONSOLE);
+
 	/* We store the console state in dev->priv, and initialize it. */
 	dev->priv = malloc(sizeof(struct console_abort));
 	((struct console_abort *)dev->priv)->count = 0;
 
-	/* The console needs two virtqueues: the input then the output.  When
+	/*
+	 * The console needs two virtqueues: the input then the output.  When
 	 * they put something the input queue, we make sure we're listening to
 	 * stdin.  When they put something in the output queue, we write it to
-	 * stdout. */
-	add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
-	add_virtqueue(dev, VIRTQUEUE_NUM, handle_console_output);
+	 * stdout.
+	 */
+	add_virtqueue(dev, VIRTQUEUE_NUM, console_input);
+	add_virtqueue(dev, VIRTQUEUE_NUM, console_output);
 
-	verbose("device %u: console\n", devices.device_num++);
+	verbose("device %u: console\n", ++devices.device_num);
 }
 /*:*/
 
-static void timeout_alarm(int sig)
-{
-	write(timeoutpipe[1], "", 1);
-}
-
-static void setup_timeout(void)
-{
-	if (pipe(timeoutpipe) != 0)
-		err(1, "Creating timeout pipe");
-
-	if (fcntl(timeoutpipe[1], F_SETFL,
-		  fcntl(timeoutpipe[1], F_GETFL) | O_NONBLOCK) != 0)
-		err(1, "Making timeout pipe nonblocking");
-
-	add_device_fd(timeoutpipe[0]);
-	signal(SIGALRM, timeout_alarm);
-}
-
-/*M:010 Inter-guest networking is an interesting area.  Simplest is to have a
+/*M:010
+ * Inter-guest networking is an interesting area.  Simplest is to have a
  * --sharenet=<name> option which opens or creates a named pipe.  This can be
  * used to send packets to another guest in a 1:1 manner.
  *
@@ -1340,7 +1371,8 @@
  * multiple inter-guest channels behind one interface, although it would
  * require some manner of hotplugging new virtio channels.
  *
- * Finally, we could implement a virtio network switch in the kernel. :*/
+ * Finally, we could implement a virtio network switch in the kernel.
+:*/
 
 static u32 str2ip(const char *ipaddr)
 {
@@ -1365,11 +1397,13 @@
 	mac[5] = m[5];
 }
 
-/* This code is "adapted" from libbridge: it attaches the Host end of the
+/*
+ * This code is "adapted" from libbridge: it attaches the Host end of the
  * network device to the bridge device specified by the command line.
  *
  * This is yet another James Morris contribution (I'm an IP-level guy, so I
- * dislike bridging), and I just try not to break it. */
+ * dislike bridging), and I just try not to break it.
+ */
 static void add_to_bridge(int fd, const char *if_name, const char *br_name)
 {
 	int ifidx;
@@ -1389,9 +1423,11 @@
 		err(1, "can't add %s to bridge %s", if_name, br_name);
 }
 
-/* This sets up the Host end of the network device with an IP address, brings
+/*
+ * This sets up the Host end of the network device with an IP address, brings
  * it up so packets will flow, the copies the MAC address into the hwaddr
- * pointer. */
+ * pointer.
+ */
 static void configure_device(int fd, const char *tapif, u32 ipaddr)
 {
 	struct ifreq ifr;
@@ -1418,10 +1454,12 @@
 	/* Start with this zeroed.  Messy but sure. */
 	memset(&ifr, 0, sizeof(ifr));
 
-	/* We open the /dev/net/tun device and tell it we want a tap device.  A
+	/*
+	 * We open the /dev/net/tun device and tell it we want a tap device.  A
 	 * tap device is like a tun device, only somehow different.  To tell
 	 * the truth, I completely blundered my way through this code, but it
-	 * works now! */
+	 * works now!
+	 */
 	netfd = open_or_die("/dev/net/tun", O_RDWR);
 	ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
 	strcpy(ifr.ifr_name, "tap%d");
@@ -1432,39 +1470,46 @@
 		  TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0)
 		err(1, "Could not set features for tun device");
 
-	/* We don't need checksums calculated for packets coming in this
-	 * device: trust us! */
+	/*
+	 * We don't need checksums calculated for packets coming in this
+	 * device: trust us!
+	 */
 	ioctl(netfd, TUNSETNOCSUM, 1);
 
 	memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
 	return netfd;
 }
 
-/*L:195 Our network is a Host<->Guest network.  This can either use bridging or
+/*L:195
+ * Our network is a Host<->Guest network.  This can either use bridging or
  * routing, but the principle is the same: it uses the "tun" device to inject
  * packets into the Host as if they came in from a normal network card.  We
- * just shunt packets between the Guest and the tun device. */
+ * just shunt packets between the Guest and the tun device.
+ */
 static void setup_tun_net(char *arg)
 {
 	struct device *dev;
-	int netfd, ipfd;
+	struct net_info *net_info = malloc(sizeof(*net_info));
+	int ipfd;
 	u32 ip = INADDR_ANY;
 	bool bridging = false;
 	char tapif[IFNAMSIZ], *p;
 	struct virtio_net_config conf;
 
-	netfd = get_tun_device(tapif);
+	net_info->tunfd = get_tun_device(tapif);
 
 	/* First we create a new network device. */
-	dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
+	dev = new_device("net", VIRTIO_ID_NET);
+	dev->priv = net_info;
 
-	/* Network devices need a receive and a send queue, just like
-	 * console. */
-	add_virtqueue(dev, VIRTQUEUE_NUM, net_enable_fd);
-	add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
+	/* Network devices need a recv and a send queue, just like console. */
+	add_virtqueue(dev, VIRTQUEUE_NUM, net_input);
+	add_virtqueue(dev, VIRTQUEUE_NUM, net_output);
 
-	/* We need a socket to perform the magic network ioctls to bring up the
-	 * tap interface, connect to the bridge etc.  Any socket will do! */
+	/*
+	 * We need a socket to perform the magic network ioctls to bring up the
+	 * tap interface, connect to the bridge etc.  Any socket will do!
+	 */
 	ipfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
 	if (ipfd < 0)
 		err(1, "opening IP socket");
@@ -1502,6 +1547,8 @@
 	add_feature(dev, VIRTIO_NET_F_HOST_TSO4);
 	add_feature(dev, VIRTIO_NET_F_HOST_TSO6);
 	add_feature(dev, VIRTIO_NET_F_HOST_ECN);
+	/* We handle indirect ring entries */
+	add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC);
 	set_config(dev, sizeof(conf), &conf);
 
 	/* We don't need the socket any more; setup is done. */
@@ -1516,93 +1563,100 @@
 		verbose("device %u: tun %s: %s\n",
 			devices.device_num, tapif, arg);
 }
-
-/* Our block (disk) device should be really simple: the Guest asks for a block
- * number and we read or write that position in the file.  Unfortunately, that
- * was amazingly slow: the Guest waits until the read is finished before
- * running anything else, even if it could have been doing useful work.
- *
- * We could use async I/O, except it's reputed to suck so hard that characters
- * actually go missing from your code when you try to use it.
- *
- * So we farm the I/O out to thread, and communicate with it via a pipe. */
+/*:*/
 
 /* This hangs off device->priv. */
-struct vblk_info
-{
+struct vblk_info {
 	/* The size of the file. */
 	off64_t len;
 
 	/* The file descriptor for the file. */
 	int fd;
 
-	/* IO thread listens on this file descriptor [0]. */
-	int workpipe[2];
-
-	/* IO thread writes to this file descriptor to mark it done, then
-	 * Launcher triggers interrupt to Guest. */
-	int done_fd;
 };
 
 /*L:210
  * The Disk
  *
- * Remember that the block device is handled by a separate I/O thread.  We head
- * straight into the core of that thread here:
+ * The disk only has one virtqueue, so it only has one thread.  It is really
+ * simple: the Guest asks for a block number and we read or write that position
+ * in the file.
+ *
+ * Before we serviced each virtqueue in a separate thread, that was unacceptably
+ * slow: the Guest waits until the read is finished before running anything
+ * else, even if it could have been doing useful work.
+ *
+ * We could have used async I/O, except it's reputed to suck so hard that
+ * characters actually go missing from your code when you try to use it.
  */
-static bool service_io(struct device *dev)
+static void blk_request(struct virtqueue *vq)
 {
-	struct vblk_info *vblk = dev->priv;
+	struct vblk_info *vblk = vq->dev->priv;
 	unsigned int head, out_num, in_num, wlen;
 	int ret;
 	u8 *in;
 	struct virtio_blk_outhdr *out;
-	struct iovec iov[dev->vq->vring.num];
+	struct iovec iov[vq->vring.num];
 	off64_t off;
 
-	/* See if there's a request waiting.  If not, nothing to do. */
-	head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
-	if (head == dev->vq->vring.num)
-		return false;
+	/*
+	 * Get the next request, where we normally wait.  It triggers the
+	 * interrupt to acknowledge previously serviced requests (if any).
+	 */
+	head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
 
-	/* Every block request should contain at least one output buffer
+	/*
+	 * Every block request should contain at least one output buffer
 	 * (detailing the location on disk and the type of request) and one
-	 * input buffer (to hold the result). */
+	 * input buffer (to hold the result).
+	 */
 	if (out_num == 0 || in_num == 0)
 		errx(1, "Bad virtblk cmd %u out=%u in=%u",
 		     head, out_num, in_num);
 
 	out = convert(&iov[0], struct virtio_blk_outhdr);
 	in = convert(&iov[out_num+in_num-1], u8);
+	/*
+	 * For historical reasons, block operations are expressed in 512 byte
+	 * "sectors".
+	 */
 	off = out->sector * 512;
 
-	/* The block device implements "barriers", where the Guest indicates
+	/*
+	 * The block device implements "barriers", where the Guest indicates
 	 * that it wants all previous writes to occur before this write.  We
 	 * don't have a way of asking our kernel to do a barrier, so we just
-	 * synchronize all the data in the file.  Pretty poor, no? */
+	 * synchronize all the data in the file.  Pretty poor, no?
+	 */
 	if (out->type & VIRTIO_BLK_T_BARRIER)
 		fdatasync(vblk->fd);
 
-	/* In general the virtio block driver is allowed to try SCSI commands.
-	 * It'd be nice if we supported eject, for example, but we don't. */
+	/*
+	 * In general the virtio block driver is allowed to try SCSI commands.
+	 * It'd be nice if we supported eject, for example, but we don't.
+	 */
 	if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
 		fprintf(stderr, "Scsi commands unsupported\n");
 		*in = VIRTIO_BLK_S_UNSUPP;
 		wlen = sizeof(*in);
 	} else if (out->type & VIRTIO_BLK_T_OUT) {
-		/* Write */
-
-		/* Move to the right location in the block file.  This can fail
-		 * if they try to write past end. */
+		/*
+		 * Write
+		 *
+		 * Move to the right location in the block file.  This can fail
+		 * if they try to write past end.
+		 */
 		if (lseek64(vblk->fd, off, SEEK_SET) != off)
 			err(1, "Bad seek to sector %llu", out->sector);
 
 		ret = writev(vblk->fd, iov+1, out_num-1);
 		verbose("WRITE to sector %llu: %i\n", out->sector, ret);
 
-		/* Grr... Now we know how long the descriptor they sent was, we
+		/*
+		 * Grr... Now we know how long the descriptor they sent was, we
 		 * make sure they didn't try to write over the end of the block
-		 * file (possibly extending it). */
+		 * file (possibly extending it).
+		 */
 		if (ret > 0 && off + ret > vblk->len) {
 			/* Trim it back to the correct length */
 			ftruncate64(vblk->fd, vblk->len);
@@ -1612,10 +1666,12 @@
 		wlen = sizeof(*in);
 		*in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
 	} else {
-		/* Read */
-
-		/* Move to the right location in the block file.  This can fail
-		 * if they try to read past end. */
+		/*
+		 * Read
+		 *
+		 * Move to the right location in the block file.  This can fail
+		 * if they try to read past end.
+		 */
 		if (lseek64(vblk->fd, off, SEEK_SET) != off)
 			err(1, "Bad seek to sector %llu", out->sector);
 
@@ -1630,90 +1686,31 @@
 		}
 	}
 
-	/* OK, so we noted that it was pretty poor to use an fdatasync as a
+	/*
+	 * OK, so we noted that it was pretty poor to use an fdatasync as a
 	 * barrier.  But Christoph Hellwig points out that we need a sync
 	 * *afterwards* as well: "Barriers specify no reordering to the front
-	 * or the back."  And Jens Axboe confirmed it, so here we are: */
+	 * or the back."  And Jens Axboe confirmed it, so here we are:
+	 */
 	if (out->type & VIRTIO_BLK_T_BARRIER)
 		fdatasync(vblk->fd);
 
-	/* We can't trigger an IRQ, because we're not the Launcher.  It does
-	 * that when we tell it we're done. */
-	add_used(dev->vq, head, wlen);
-	return true;
-}
-
-/* This is the thread which actually services the I/O. */
-static int io_thread(void *_dev)
-{
-	struct device *dev = _dev;
-	struct vblk_info *vblk = dev->priv;
-	char c;
-
-	/* Close other side of workpipe so we get 0 read when main dies. */
-	close(vblk->workpipe[1]);
-	/* Close the other side of the done_fd pipe. */
-	close(dev->fd);
-
-	/* When this read fails, it means Launcher died, so we follow. */
-	while (read(vblk->workpipe[0], &c, 1) == 1) {
-		/* We acknowledge each request immediately to reduce latency,
-		 * rather than waiting until we've done them all.  I haven't
-		 * measured to see if it makes any difference.
-		 *
-		 * That would be an interesting test, wouldn't it?  You could
-		 * also try having more than one I/O thread. */
-		while (service_io(dev))
-			write(vblk->done_fd, &c, 1);
-	}
-	return 0;
-}
-
-/* Now we've seen the I/O thread, we return to the Launcher to see what happens
- * when that thread tells us it's completed some I/O. */
-static bool handle_io_finish(int fd, struct device *dev)
-{
-	char c;
-
-	/* If the I/O thread died, presumably it printed the error, so we
-	 * simply exit. */
-	if (read(dev->fd, &c, 1) != 1)
-		exit(1);
-
-	/* It did some work, so trigger the irq. */
-	trigger_irq(fd, dev->vq);
-	return true;
-}
-
-/* When the Guest submits some I/O, we just need to wake the I/O thread. */
-static void handle_virtblk_output(int fd, struct virtqueue *vq, bool timeout)
-{
-	struct vblk_info *vblk = vq->dev->priv;
-	char c = 0;
-
-	/* Wake up I/O thread and tell it to go to work! */
-	if (write(vblk->workpipe[1], &c, 1) != 1)
-		/* Presumably it indicated why it died. */
-		exit(1);
+	/* Finished that request. */
+	add_used(vq, head, wlen);
 }
 
 /*L:198 This actually sets up a virtual block device. */
 static void setup_block_file(const char *filename)
 {
-	int p[2];
 	struct device *dev;
 	struct vblk_info *vblk;
-	void *stack;
 	struct virtio_blk_config conf;
 
-	/* This is the pipe the I/O thread will use to tell us I/O is done. */
-	pipe(p);
-
-	/* The device responds to return from I/O thread. */
-	dev = new_device("block", VIRTIO_ID_BLOCK, p[0], handle_io_finish);
+	/* Creat the device. */
+	dev = new_device("block", VIRTIO_ID_BLOCK);
 
 	/* The device has one virtqueue, where the Guest places requests. */
-	add_virtqueue(dev, VIRTQUEUE_NUM, handle_virtblk_output);
+	add_virtqueue(dev, VIRTQUEUE_NUM, blk_request);
 
 	/* Allocate the room for our own bookkeeping */
 	vblk = dev->priv = malloc(sizeof(*vblk));
@@ -1728,64 +1725,50 @@
 	/* Tell Guest how many sectors this device has. */
 	conf.capacity = cpu_to_le64(vblk->len / 512);
 
-	/* Tell Guest not to put in too many descriptors at once: two are used
-	 * for the in and out elements. */
+	/*
+	 * Tell Guest not to put in too many descriptors at once: two are used
+	 * for the in and out elements.
+	 */
 	add_feature(dev, VIRTIO_BLK_F_SEG_MAX);
 	conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2);
 
-	set_config(dev, sizeof(conf), &conf);
-
-	/* The I/O thread writes to this end of the pipe when done. */
-	vblk->done_fd = p[1];
-
-	/* This is the second pipe, which is how we tell the I/O thread about
-	 * more work. */
-	pipe(vblk->workpipe);
-
-	/* Create stack for thread and run it.  Since stack grows upwards, we
-	 * point the stack pointer to the end of this region. */
-	stack = malloc(32768);
-	/* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from
-	 * becoming a zombie. */
-	if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1)
-		err(1, "Creating clone");
-
-	/* We don't need to keep the I/O thread's end of the pipes open. */
-	close(vblk->done_fd);
-	close(vblk->workpipe[0]);
+	/* Don't try to put whole struct: we have 8 bit limit. */
+	set_config(dev, offsetof(struct virtio_blk_config, geometry), &conf);
 
 	verbose("device %u: virtblock %llu sectors\n",
-		devices.device_num, le64_to_cpu(conf.capacity));
+		++devices.device_num, le64_to_cpu(conf.capacity));
 }
 
-/* Our random number generator device reads from /dev/random into the Guest's
+/*L:211
+ * Our random number generator device reads from /dev/random into the Guest's
  * input buffers.  The usual case is that the Guest doesn't want random numbers
  * and so has no buffers although /dev/random is still readable, whereas
  * console is the reverse.
  *
- * The same logic applies, however. */
-static bool handle_rng_input(int fd, struct device *dev)
+ * The same logic applies, however.
+ */
+struct rng_info {
+	int rfd;
+};
+
+static void rng_input(struct virtqueue *vq)
 {
 	int len;
 	unsigned int head, in_num, out_num, totlen = 0;
-	struct iovec iov[dev->vq->vring.num];
+	struct rng_info *rng_info = vq->dev->priv;
+	struct iovec iov[vq->vring.num];
 
 	/* First we need a buffer from the Guests's virtqueue. */
-	head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
-
-	/* If they're not ready for input, stop listening to this file
-	 * descriptor.  We'll start again once they add an input buffer. */
-	if (head == dev->vq->vring.num)
-		return false;
-
+	head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
 	if (out_num)
 		errx(1, "Output buffers in rng?");
 
-	/* This is why we convert to iovecs: the readv() call uses them, and so
-	 * it reads straight into the Guest's buffer.  We loop to make sure we
-	 * fill it. */
+	/*
+	 * Just like the console write, we loop to cover the whole iovec.
+	 * In this case, short reads actually happen quite a bit.
+	 */
 	while (!iov_empty(iov, in_num)) {
-		len = readv(dev->fd, iov, in_num);
+		len = readv(rng_info->rfd, iov, in_num);
 		if (len <= 0)
 			err(1, "Read from /dev/random gave %i", len);
 		iov_consume(iov, in_num, len);
@@ -1793,25 +1776,26 @@
 	}
 
 	/* Tell the Guest about the new input. */
-	add_used_and_trigger(fd, dev->vq, head, totlen);
-
-	/* Everything went OK! */
-	return true;
+	add_used(vq, head, totlen);
 }
 
-/* And this creates a "hardware" random number device for the Guest. */
+/*L:199
+ * This creates a "hardware" random number device for the Guest.
+ */
 static void setup_rng(void)
 {
 	struct device *dev;
-	int fd;
+	struct rng_info *rng_info = malloc(sizeof(*rng_info));
 
-	fd = open_or_die("/dev/random", O_RDONLY);
+	/* Our device's privat info simply contains the /dev/random fd. */
+	rng_info->rfd = open_or_die("/dev/random", O_RDONLY);
 
-	/* The device responds to return from I/O thread. */
-	dev = new_device("rng", VIRTIO_ID_RNG, fd, handle_rng_input);
+	/* Create the new device. */
+	dev = new_device("rng", VIRTIO_ID_RNG);
+	dev->priv = rng_info;
 
 	/* The device has one virtqueue, where the Guest places inbufs. */
-	add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
+	add_virtqueue(dev, VIRTQUEUE_NUM, rng_input);
 
 	verbose("device %u: rng\n", devices.device_num++);
 }
@@ -1822,22 +1806,27 @@
 {
 	unsigned int i;
 
-	/* Since we don't track all open fds, we simply close everything beyond
-	 * stderr. */
+	/*
+	 * Since we don't track all open fds, we simply close everything beyond
+	 * stderr.
+	 */
 	for (i = 3; i < FD_SETSIZE; i++)
 		close(i);
 
-	/* The exec automatically gets rid of the I/O and Waker threads. */
+	/* Reset all the devices (kills all threads). */
+	cleanup_devices();
+
 	execv(main_args[0], main_args);
 	err(1, "Could not exec %s", main_args[0]);
 }
 
-/*L:220 Finally we reach the core of the Launcher which runs the Guest, serves
- * its input and output, and finally, lays it to rest. */
-static void __attribute__((noreturn)) run_guest(int lguest_fd)
+/*L:220
+ * Finally we reach the core of the Launcher which runs the Guest, serves
+ * its input and output, and finally, lays it to rest.
+ */
+static void __attribute__((noreturn)) run_guest(void)
 {
 	for (;;) {
-		unsigned long args[] = { LHREQ_BREAK, 0 };
 		unsigned long notify_addr;
 		int readval;
 
@@ -1848,8 +1837,7 @@
 		/* One unsigned long means the Guest did HCALL_NOTIFY */
 		if (readval == sizeof(notify_addr)) {
 			verbose("Notify on address %#lx\n", notify_addr);
-			handle_output(lguest_fd, notify_addr);
-			continue;
+			handle_output(notify_addr);
 		/* ENOENT means the Guest died.  Reading tells us why. */
 		} else if (errno == ENOENT) {
 			char reason[1024] = { 0 };
@@ -1858,19 +1846,9 @@
 		/* ERESTART means that we need to reboot the guest */
 		} else if (errno == ERESTART) {
 			restart_guest();
-		/* EAGAIN means a signal (timeout).
-		 * Anything else means a bug or incompatible change. */
-		} else if (errno != EAGAIN)
+		/* Anything else means a bug or incompatible change. */
+		} else
 			err(1, "Running guest failed");
-
-		/* Only service input on thread for CPU 0. */
-		if (cpu_id != 0)
-			continue;
-
-		/* Service input, then unset the BREAK to release the Waker. */
-		handle_input(lguest_fd);
-		if (pwrite(lguest_fd, args, sizeof(args), cpu_id) < 0)
-			err(1, "Resetting break");
 	}
 }
 /*L:240
@@ -1880,7 +1858,7 @@
  *
  * Are you ready?  Take a deep breath and join me in the core of the Host, in
  * "make Host".
- :*/
+:*/
 
 static struct option opts[] = {
 	{ "verbose", 0, NULL, 'v' },
@@ -1901,11 +1879,10 @@
 /*L:105 The main routine is where the real work begins: */
 int main(int argc, char *argv[])
 {
-	/* Memory, top-level pagetable, code startpoint and size of the
-	 * (optional) initrd. */
+	/* Memory, code startpoint and size of the (optional) initrd. */
 	unsigned long mem = 0, start, initrd_size = 0;
-	/* Two temporaries and the /dev/lguest file descriptor. */
-	int i, c, lguest_fd;
+	/* Two temporaries. */
+	int i, c;
 	/* The boot information for the Guest. */
 	struct boot_params *boot;
 	/* If they specify an initrd file to load. */
@@ -1913,33 +1890,33 @@
 
 	/* Save the args: we "reboot" by execing ourselves again. */
 	main_args = argv;
-	/* We don't "wait" for the children, so prevent them from becoming
-	 * zombies. */
-	signal(SIGCHLD, SIG_IGN);
 
-	/* First we initialize the device list.  Since console and network
-	 * device receive input from a file descriptor, we keep an fdset
-	 * (infds) and the maximum fd number (max_infd) with the head of the
-	 * list.  We also keep a pointer to the last device.  Finally, we keep
-	 * the next interrupt number to use for devices (1: remember that 0 is
-	 * used by the timer). */
-	FD_ZERO(&devices.infds);
-	devices.max_infd = -1;
+	/*
+	 * First we initialize the device list.  We keep a pointer to the last
+	 * device, and the next interrupt number to use for devices (1:
+	 * remember that 0 is used by the timer).
+	 */
 	devices.lastdev = NULL;
 	devices.next_irq = 1;
 
+	/* We're CPU 0.  In fact, that's the only CPU possible right now. */
 	cpu_id = 0;
-	/* We need to know how much memory so we can set up the device
+
+	/*
+	 * We need to know how much memory so we can set up the device
 	 * descriptor and memory pages for the devices as we parse the command
 	 * line.  So we quickly look through the arguments to find the amount
-	 * of memory now. */
+	 * of memory now.
+	 */
 	for (i = 1; i < argc; i++) {
 		if (argv[i][0] != '-') {
 			mem = atoi(argv[i]) * 1024 * 1024;
-			/* We start by mapping anonymous pages over all of
+			/*
+			 * We start by mapping anonymous pages over all of
 			 * guest-physical memory range.  This fills it with 0,
 			 * and ensures that the Guest won't be killed when it
-			 * tries to access it. */
+			 * tries to access it.
+			 */
 			guest_base = map_zeroed_pages(mem / getpagesize()
 						      + DEVICE_PAGES);
 			guest_limit = mem;
@@ -1972,8 +1949,10 @@
 			usage();
 		}
 	}
-	/* After the other arguments we expect memory and kernel image name,
-	 * followed by command line arguments for the kernel. */
+	/*
+	 * After the other arguments we expect memory and kernel image name,
+	 * followed by command line arguments for the kernel.
+	 */
 	if (optind + 2 > argc)
 		usage();
 
@@ -1982,9 +1961,6 @@
 	/* We always have a console device */
 	setup_console();
 
-	/* We can timeout waiting for Guest network transmit. */
-	setup_timeout();
-
 	/* Now we load the kernel */
 	start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
 
@@ -1994,20 +1970,26 @@
 	/* Map the initrd image if requested (at top of physical memory) */
 	if (initrd_name) {
 		initrd_size = load_initrd(initrd_name, mem);
-		/* These are the location in the Linux boot header where the
-		 * start and size of the initrd are expected to be found. */
+		/*
+		 * These are the location in the Linux boot header where the
+		 * start and size of the initrd are expected to be found.
+		 */
 		boot->hdr.ramdisk_image = mem - initrd_size;
 		boot->hdr.ramdisk_size = initrd_size;
 		/* The bootloader type 0xFF means "unknown"; that's OK. */
 		boot->hdr.type_of_loader = 0xFF;
 	}
 
-	/* The Linux boot header contains an "E820" memory map: ours is a
-	 * simple, single region. */
+	/*
+	 * The Linux boot header contains an "E820" memory map: ours is a
+	 * simple, single region.
+	 */
 	boot->e820_entries = 1;
 	boot->e820_map[0] = ((struct e820entry) { 0, mem, E820_RAM });
-	/* The boot header contains a command line pointer: we put the command
-	 * line after the boot header. */
+	/*
+	 * The boot header contains a command line pointer: we put the command
+	 * line after the boot header.
+	 */
 	boot->hdr.cmd_line_ptr = to_guest_phys(boot + 1);
 	/* We use a simple helper to copy the arguments separated by spaces. */
 	concat((char *)(boot + 1), argv+optind+2);
@@ -2021,17 +2003,20 @@
 	/* Tell the entry path not to try to reload segment registers. */
 	boot->hdr.loadflags |= KEEP_SEGMENTS;
 
-	/* We tell the kernel to initialize the Guest: this returns the open
-	 * /dev/lguest file descriptor. */
-	lguest_fd = tell_kernel(start);
+	/*
+	 * We tell the kernel to initialize the Guest: this returns the open
+	 * /dev/lguest file descriptor.
+	 */
+	tell_kernel(start);
 
-	/* We clone off a thread, which wakes the Launcher whenever one of the
-	 * input file descriptors needs attention.  We call this the Waker, and
-	 * we'll cover it in a moment. */
-	setup_waker(lguest_fd);
+	/* Ensure that we terminate if a device-servicing child dies. */
+	signal(SIGCHLD, kill_launcher);
+
+	/* If we exit via err(), this kills all the threads, restores tty. */
+	atexit(cleanup_devices);
 
 	/* Finally, run the Guest.  This doesn't return. */
-	run_guest(lguest_fd);
+	run_guest();
 }
 /*:*/
 
diff -druN linux-libre-2.6.30-gnu/Documentation/lguest/lguest.txt linux-libre-2.6.31-gnu/Documentation/lguest/lguest.txt
--- linux-libre-2.6.30-gnu/Documentation/lguest/lguest.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/lguest/lguest.txt	2009-09-09 18:13:59.000000000 -0400
@@ -37,7 +37,6 @@
      "Paravirtualized guest support" = Y
         "Lguest guest support" = Y
      "High Memory Support" = off/4GB
-     "PAE (Physical Address Extension) Support" = N
      "Alignment value to which kernel should be aligned" = 0x100000
         (CONFIG_PARAVIRT=y, CONFIG_LGUEST_GUEST=y, CONFIG_HIGHMEM64G=n and
          CONFIG_PHYSICAL_ALIGN=0x100000)
diff -druN linux-libre-2.6.30-gnu/Documentation/lguest/Makefile linux-libre-2.6.31-gnu/Documentation/lguest/Makefile
--- linux-libre-2.6.30-gnu/Documentation/lguest/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/lguest/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,5 @@
 # This creates the demonstration utility "lguest" which runs a Linux guest.
-CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include -I../../arch/x86/include -U_FORTIFY_SOURCE
-LDLIBS:=-lz
+CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include -I../../arch/x86/include -U_FORTIFY_SOURCE
 
 all: lguest
 
diff -druN linux-libre-2.6.30-gnu/Documentation/local_ops.txt linux-libre-2.6.31-gnu/Documentation/local_ops.txt
--- linux-libre-2.6.30-gnu/Documentation/local_ops.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/local_ops.txt	2009-09-09 18:13:59.000000000 -0400
@@ -34,7 +34,7 @@
 
 It can be done by slightly modifying the standard atomic operations : only
 their UP variant must be kept. It typically means removing LOCK prefix (on
-i386 and x86_64) and any SMP sychronization barrier. If the architecture does
+i386 and x86_64) and any SMP synchronization barrier. If the architecture does
 not have a different behavior between SMP and UP, including asm-generic/local.h
 in your architecture's local.h is sufficient.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/lockdep-design.txt linux-libre-2.6.31-gnu/Documentation/lockdep-design.txt
--- linux-libre-2.6.30-gnu/Documentation/lockdep-design.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/lockdep-design.txt	2009-09-09 18:13:59.000000000 -0400
@@ -30,9 +30,9 @@
 The validator tracks lock-class usage history into 4n + 1 separate state bits:
 
 - 'ever held in STATE context'
-- 'ever head as readlock in STATE context'
-- 'ever head with STATE enabled'
-- 'ever head as readlock with STATE enabled'
+- 'ever held as readlock in STATE context'
+- 'ever held with STATE enabled'
+- 'ever held as readlock with STATE enabled'
 
 Where STATE can be either one of (kernel/lockdep_states.h)
  - hardirq
diff -druN linux-libre-2.6.30-gnu/Documentation/memory-barriers.txt linux-libre-2.6.31-gnu/Documentation/memory-barriers.txt
--- linux-libre-2.6.30-gnu/Documentation/memory-barriers.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/memory-barriers.txt	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,7 @@
 
      - Locking functions.
      - Interrupt disabling functions.
+     - Sleep and wake-up functions.
      - Miscellaneous functions.
 
  (*) Inter-CPU locking barrier effects.
@@ -1217,6 +1218,132 @@
 other means.
 
 
+SLEEP AND WAKE-UP FUNCTIONS
+---------------------------
+
+Sleeping and waking on an event flagged in global data can be viewed as an
+interaction between two pieces of data: the task state of the task waiting for
+the event and the global data used to indicate the event.  To make sure that
+these appear to happen in the right order, the primitives to begin the process
+of going to sleep, and the primitives to initiate a wake up imply certain
+barriers.
+
+Firstly, the sleeper normally follows something like this sequence of events:
+
+	for (;;) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (event_indicated)
+			break;
+		schedule();
+	}
+
+A general memory barrier is interpolated automatically by set_current_state()
+after it has altered the task state:
+
+	CPU 1
+	===============================
+	set_current_state();
+	  set_mb();
+	    STORE current->state
+	    <general barrier>
+	LOAD event_indicated
+
+set_current_state() may be wrapped by:
+
+	prepare_to_wait();
+	prepare_to_wait_exclusive();
+
+which therefore also imply a general memory barrier after setting the state.
+The whole sequence above is available in various canned forms, all of which
+interpolate the memory barrier in the right place:
+
+	wait_event();
+	wait_event_interruptible();
+	wait_event_interruptible_exclusive();
+	wait_event_interruptible_timeout();
+	wait_event_killable();
+	wait_event_timeout();
+	wait_on_bit();
+	wait_on_bit_lock();
+
+
+Secondly, code that performs a wake up normally follows something like this:
+
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+or:
+
+	event_indicated = 1;
+	wake_up_process(event_daemon);
+
+A write memory barrier is implied by wake_up() and co. if and only if they wake
+something up.  The barrier occurs before the task state is cleared, and so sits
+between the STORE to indicate the event and the STORE to set TASK_RUNNING:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	set_current_state();		STORE event_indicated
+	  set_mb();			wake_up();
+	    STORE current->state	  <write barrier>
+	    <general barrier>		  STORE current->state
+	LOAD event_indicated
+
+The available waker functions include:
+
+	complete();
+	wake_up();
+	wake_up_all();
+	wake_up_bit();
+	wake_up_interruptible();
+	wake_up_interruptible_all();
+	wake_up_interruptible_nr();
+	wake_up_interruptible_poll();
+	wake_up_interruptible_sync();
+	wake_up_interruptible_sync_poll();
+	wake_up_locked();
+	wake_up_locked_poll();
+	wake_up_nr();
+	wake_up_poll();
+	wake_up_process();
+
+
+[!] Note that the memory barriers implied by the sleeper and the waker do _not_
+order multiple stores before the wake-up with respect to loads of those stored
+values after the sleeper has called set_current_state().  For instance, if the
+sleeper does:
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (event_indicated)
+		break;
+	__set_current_state(TASK_RUNNING);
+	do_something(my_data);
+
+and the waker does:
+
+	my_data = value;
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+there's no guarantee that the change to event_indicated will be perceived by
+the sleeper as coming after the change to my_data.  In such a circumstance, the
+code on both sides must interpolate its own memory barriers between the
+separate data accesses.  Thus the above sleeper ought to do:
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (event_indicated) {
+		smp_rmb();
+		do_something(my_data);
+	}
+
+and the waker should do:
+
+	my_data = value;
+	smp_wmb();
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+
 MISCELLANEOUS FUNCTIONS
 -----------------------
 
@@ -1366,7 +1493,7 @@
 
 Under normal operation, memory operation reordering is generally not going to
 be a problem as a single-threaded linear piece of code will still appear to
-work correctly, even if it's in an SMP kernel.  There are, however, three
+work correctly, even if it's in an SMP kernel.  There are, however, four
 circumstances in which reordering definitely _could_ be a problem:
 
  (*) Interprocessor interaction.
diff -druN linux-libre-2.6.30-gnu/Documentation/memory-hotplug.txt linux-libre-2.6.31-gnu/Documentation/memory-hotplug.txt
--- linux-libre-2.6.30-gnu/Documentation/memory-hotplug.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/memory-hotplug.txt	2009-09-09 18:13:59.000000000 -0400
@@ -73,13 +73,13 @@
 (see Section 4.).
 
 Logical Memory Hotplug phase is to change memory state into
-avaiable/unavailable for users. Amount of memory from user's view is
+available/unavailable for users. Amount of memory from user's view is
 changed by this phase. The kernel makes all memory in it as free pages
 when a memory range is available.
 
 In this document, this phase is described as online/offline.
 
-Logical Memory Hotplug phase is triggred by write of sysfs file by system
+Logical Memory Hotplug phase is triggered by write of sysfs file by system
 administrator. For the hot-add case, it must be executed after Physical Hotplug
 phase by hand.
 (However, if you writes udev's hotplug scripts for memory hotplug, these
@@ -334,7 +334,7 @@
   Generated if MEMORY_GOING_ONLINE fails.
 
 MEMORY_ONLINE
-  Generated when memory has succesfully brought online. The callback may
+  Generated when memory has successfully brought online. The callback may
   allocate pages from the new memory.
 
 MEMORY_GOING_OFFLINE
@@ -359,7 +359,7 @@
 struct memory_notify {
        unsigned long start_pfn;
        unsigned long nr_pages;
-       int status_cahnge_nid;
+       int status_change_nid;
 }
 
 start_pfn is start_pfn of online/offline memory.
diff -druN linux-libre-2.6.30-gnu/Documentation/mn10300/ABI.txt linux-libre-2.6.31-gnu/Documentation/mn10300/ABI.txt
--- linux-libre-2.6.30-gnu/Documentation/mn10300/ABI.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/mn10300/ABI.txt	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,7 @@
 passed in D0:D1. If the first argument is not a 64-bit value, but the second
 is, the second will be passed entirely on the stack and D1 will be unused.
 
-Arguments smaller than 32-bits are not coelesced within a register or a stack
+Arguments smaller than 32-bits are not coalesced within a register or a stack
 word. For example, two byte-sized arguments will always be passed in separate
 registers or word-sized stack slots.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/mtd/nand_ecc.txt linux-libre-2.6.31-gnu/Documentation/mtd/nand_ecc.txt
--- linux-libre-2.6.30-gnu/Documentation/mtd/nand_ecc.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/mtd/nand_ecc.txt	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,7 @@
            cp5  cp5  cp5  cp5  cp4  cp4  cp4  cp4
 
 This figure represents a sector of 256 bytes.
-cp is my abbreviaton for column parity, rp for row parity.
+cp is my abbreviation for column parity, rp for row parity.
 
 Let's start to explain column parity.
 cp0 is the parity that belongs to all bit0, bit2, bit4, bit6.
@@ -560,7 +560,7 @@
 linux code 1 million times, this took about 1 second on my system.
 (using time to measure the performance). After this iteration I was back
 to 0.075 sec. Actually I had to decide to start measuring over 10
-million interations in order not to loose too much accuracy. This one
+million iterations in order not to lose too much accuracy. This one
 definitely seemed to be the jackpot!
 
 There is a little bit more room for improvement though. There are three
@@ -571,8 +571,8 @@
 need to correct by adding:
     rp4 ^= rp4_6;
     rp6 ^= rp4_6
-Furthermore there are 4 sequential assingments to rp8. This can be
-encoded slightly more efficient by saving tmppar before those 4 lines
+Furthermore there are 4 sequential assignments to rp8. This can be
+encoded slightly more efficiently by saving tmppar before those 4 lines
 and later do rp8 = rp8 ^ tmppar ^ notrp8;
 (where notrp8 is the value of rp8 before those 4 lines).
 Again a use of the commutative property of xor.
@@ -622,7 +622,7 @@
 Analysis 7
 ==========
 
-Acutally this made things worse. Not very much, but I don't want to move
+Actually this made things worse. Not very much, but I don't want to move
 into the wrong direction. Maybe something to investigate later. Could
 have to do with caching again.
 
@@ -642,7 +642,7 @@
 This makes things worse. Let's stick with attempt 6 and continue from there.
 Although it seems that the code within the loop cannot be optimised
 further there is still room to optimize the generation of the ecc codes.
-We can simply calcualate the total parity. If this is 0 then rp4 = rp5
+We can simply calculate the total parity. If this is 0 then rp4 = rp5
 etc. If the parity is 1, then rp4 = !rp5;
 But if rp4 = rp5 we do not need rp5 etc. We can just write the even bits
 in the result byte and then do something like
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/6pack.txt linux-libre-2.6.31-gnu/Documentation/networking/6pack.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/6pack.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/6pack.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 This is the 6pack-mini-HOWTO, written by
 
 Andreas Könsgen DG3KQ
-Internet: ajk@iehk.rwth-aachen.de
+Internet: ajk@comnets.uni-bremen.de
 AMPR-net: dg3kq@db0pra.ampr.org
 AX.25:    dg3kq@db0ach.#nrw.deu.eu
 
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/bonding.txt linux-libre-2.6.31-gnu/Documentation/networking/bonding.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/bonding.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/bonding.txt	2009-09-09 18:13:59.000000000 -0400
@@ -221,7 +221,7 @@
 
 		- Any slave's 802.3ad association state changes
 
-		- The bond's adminstrative state changes to up
+		- The bond's administrative state changes to up
 
 	count or 2
 
@@ -369,7 +369,7 @@
 		When this policy is used in conjuction with the mii
 		monitor, devices which assert link up prior to being
 		able to actually transmit and receive are particularly
-		susecptible to loss of the gratuitous ARP, and an
+		susceptible to loss of the gratuitous ARP, and an
 		appropriate updelay setting may be required.
 
 	follow or 2
@@ -1794,7 +1794,7 @@
 generally referred to as "trunk failover."  This is a feature of the
 switch that causes the link state of a particular switch port to be set
 down (or up) when the state of another switch port goes down (or up).
-It's purpose is to propogate link failures from logically "exterior" ports
+Its purpose is to propagate link failures from logically "exterior" ports
 to the logically "interior" ports that bonding is able to monitor via
 miimon.  Availability and configuration for trunk failover varies by
 switch, but this can be a viable alternative to the ARP monitor when using
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/can.txt linux-libre-2.6.31-gnu/Documentation/networking/can.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/can.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/can.txt	2009-09-09 18:13:59.000000000 -0400
@@ -36,10 +36,15 @@
     6.2 local loopback of sent frames
     6.3 CAN controller hardware filters
     6.4 The virtual CAN driver (vcan)
-    6.5 currently supported CAN hardware
-    6.6 todo
+    6.5 The CAN network device driver interface
+      6.5.1 Netlink interface to set/get devices properties
+      6.5.2 Setting the CAN bit-timing
+      6.5.3 Starting and stopping the CAN network device
+    6.6 supported CAN hardware
 
-  7 Credits
+  7 Socket CAN resources
+
+  8 Credits
 
 ============================================================================
 
@@ -234,6 +239,8 @@
   the user application using the common CAN filter mechanisms. Inside
   this filter definition the (interested) type of errors may be
   selected. The reception of error frames is disabled by default.
+  The format of the CAN error frame is briefly decribed in the Linux
+  header file "include/linux/can/error.h".
 
 4. How to use Socket CAN
 ------------------------
@@ -327,7 +334,7 @@
             return 1;
     }
 
-    /* paraniod check ... */
+    /* paranoid check ... */
     if (nbytes < sizeof(struct can_frame)) {
             fprintf(stderr, "read: incomplete CAN frame\n");
             return 1;
@@ -605,61 +612,213 @@
   removal of vcan network devices can be managed with the ip(8) tool:
 
   - Create a virtual CAN network interface:
-       ip link add type vcan
+       $ ip link add type vcan
 
   - Create a virtual CAN network interface with a specific name 'vcan42':
-       ip link add dev vcan42 type vcan
+       $ ip link add dev vcan42 type vcan
 
   - Remove a (virtual CAN) network interface 'vcan42':
-       ip link del vcan42
+       $ ip link del vcan42
 
-  The tool 'vcan' from the SocketCAN SVN repository on BerliOS is obsolete.
+  6.5 The CAN network device driver interface
 
-  Virtual CAN network device creation in older Kernels:
-  In Linux Kernel versions < 2.6.24 the vcan driver creates 4 vcan
-  netdevices at module load time by default. This value can be changed
-  with the module parameter 'numdev'. E.g. 'modprobe vcan numdev=8'
+  The CAN network device driver interface provides a generic interface
+  to setup, configure and monitor CAN network devices. The user can then
+  configure the CAN device, like setting the bit-timing parameters, via
+  the netlink interface using the program "ip" from the "IPROUTE2"
+  utility suite. The following chapter describes briefly how to use it.
+  Furthermore, the interface uses a common data structure and exports a
+  set of common functions, which all real CAN network device drivers
+  should use. Please have a look to the SJA1000 or MSCAN driver to
+  understand how to use them. The name of the module is can-dev.ko.
 
-  6.5 currently supported CAN hardware
+  6.5.1 Netlink interface to set/get devices properties
 
-  On the project website http://developer.berlios.de/projects/socketcan
-  there are different drivers available:
+  The CAN device must be configured via netlink interface. The supported
+  netlink message types are defined and briefly described in
+  "include/linux/can/netlink.h". CAN link support for the program "ip"
+  of the IPROUTE2 utility suite is avaiable and it can be used as shown
+  below:
 
-    vcan:    Virtual CAN interface driver (if no real hardware is available)
-    sja1000: Philips SJA1000 CAN controller (recommended)
-    i82527:  Intel i82527 CAN controller
-    mscan:   Motorola/Freescale CAN controller (e.g. inside SOC MPC5200)
-    ccan:    CCAN controller core (e.g. inside SOC h7202)
-    slcan:   For a bunch of CAN adaptors that are attached via a
-             serial line ASCII protocol (for serial / USB adaptors)
+  - Setting CAN device properties:
 
-  Additionally the different CAN adaptors (ISA/PCI/PCMCIA/USB/Parport)
-  from PEAK Systemtechnik support the CAN netdevice driver model
-  since Linux driver v6.0: http://www.peak-system.com/linux/index.htm
+    $ ip link set can0 type can help
+    Usage: ip link set DEVICE type can
+    	[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
+    	[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1
+     	  phase-seg2 PHASE-SEG2 [ sjw SJW ] ]
 
-  Please check the Mailing Lists on the berlios OSS project website.
+    	[ loopback { on | off } ]
+    	[ listen-only { on | off } ]
+    	[ triple-sampling { on | off } ]
 
-  6.6 todo
+    	[ restart-ms TIME-MS ]
+    	[ restart ]
 
-  The configuration interface for CAN network drivers is still an open
-  issue that has not been finalized in the socketcan project. Also the
-  idea of having a library module (candev.ko) that holds functions
-  that are needed by all CAN netdevices is not ready to ship.
-  Your contribution is welcome.
+    	Where: BITRATE       := { 1..1000000 }
+    	       SAMPLE-POINT  := { 0.000..0.999 }
+    	       TQ            := { NUMBER }
+    	       PROP-SEG      := { 1..8 }
+    	       PHASE-SEG1    := { 1..8 }
+    	       PHASE-SEG2    := { 1..8 }
+    	       SJW           := { 1..4 }
+    	       RESTART-MS    := { 0 | NUMBER }
 
-7. Credits
+  - Display CAN device details and statistics:
+
+    $ ip -details -statistics link show can0
+    2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP qlen 10
+      link/can
+      can <TRIPLE-SAMPLING> state ERROR-ACTIVE restart-ms 100
+      bitrate 125000 sample_point 0.875
+      tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
+      sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
+      clock 8000000
+      re-started bus-errors arbit-lost error-warn error-pass bus-off
+      41         17457      0          41         42         41
+      RX: bytes  packets  errors  dropped overrun mcast
+      140859     17608    17457   0       0       0
+      TX: bytes  packets  errors  dropped carrier collsns
+      861        112      0       41      0       0
+
+  More info to the above output:
+
+    "<TRIPLE-SAMPLING>"
+	Shows the list of selected CAN controller modes: LOOPBACK,
+	LISTEN-ONLY, or TRIPLE-SAMPLING.
+
+    "state ERROR-ACTIVE"
+	The current state of the CAN controller: "ERROR-ACTIVE",
+	"ERROR-WARNING", "ERROR-PASSIVE", "BUS-OFF" or "STOPPED"
+
+    "restart-ms 100"
+	Automatic restart delay time. If set to a non-zero value, a
+	restart of the CAN controller will be triggered automatically
+	in case of a bus-off condition after the specified delay time
+	in milliseconds. By default it's off.
+
+    "bitrate 125000 sample_point 0.875"
+	Shows the real bit-rate in bits/sec and the sample-point in the
+	range 0.000..0.999. If the calculation of bit-timing parameters
+	is enabled in the kernel (CONFIG_CAN_CALC_BITTIMING=y), the
+	bit-timing can be defined by setting the "bitrate" argument.
+	Optionally the "sample-point" can be specified. By default it's
+	0.000 assuming CIA-recommended sample-points.
+
+    "tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1"
+	Shows the time quanta in ns, propagation segment, phase buffer
+	segment 1 and 2 and the synchronisation jump width in units of
+	tq. They allow to define the CAN bit-timing in a hardware
+	independent format as proposed by the Bosch CAN 2.0 spec (see
+	chapter 8 of http://www.semiconductors.bosch.de/pdf/can2spec.pdf).
+
+    "sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
+     clock 8000000"
+	Shows the bit-timing constants of the CAN controller, here the
+	"sja1000". The minimum and maximum values of the time segment 1
+	and 2, the synchronisation jump width in units of tq, the
+	bitrate pre-scaler and the CAN system clock frequency in Hz.
+	These constants could be used for user-defined (non-standard)
+	bit-timing calculation algorithms in user-space.
+
+    "re-started bus-errors arbit-lost error-warn error-pass bus-off"
+	Shows the number of restarts, bus and arbitration lost errors,
+	and the state changes to the error-warning, error-passive and
+	bus-off state. RX overrun errors are listed in the "overrun"
+	field of the standard network statistics.
+
+  6.5.2 Setting the CAN bit-timing
+
+  The CAN bit-timing parameters can always be defined in a hardware
+  independent format as proposed in the Bosch CAN 2.0 specification
+  specifying the arguments "tq", "prop_seg", "phase_seg1", "phase_seg2"
+  and "sjw":
+
+    $ ip link set canX type can tq 125 prop-seg 6 \
+				phase-seg1 7 phase-seg2 2 sjw 1
+
+  If the kernel option CONFIG_CAN_CALC_BITTIMING is enabled, CIA
+  recommended CAN bit-timing parameters will be calculated if the bit-
+  rate is specified with the argument "bitrate":
+
+    $ ip link set canX type can bitrate 125000
+
+  Note that this works fine for the most common CAN controllers with
+  standard bit-rates but may *fail* for exotic bit-rates or CAN system
+  clock frequencies. Disabling CONFIG_CAN_CALC_BITTIMING saves some
+  space and allows user-space tools to solely determine and set the
+  bit-timing parameters. The CAN controller specific bit-timing
+  constants can be used for that purpose. They are listed by the
+  following command:
+
+    $ ip -details link show can0
+    ...
+      sja1000: clock 8000000 tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
+
+  6.5.3 Starting and stopping the CAN network device
+
+  A CAN network device is started or stopped as usual with the command
+  "ifconfig canX up/down" or "ip link set canX up/down". Be aware that
+  you *must* define proper bit-timing parameters for real CAN devices
+  before you can start it to avoid error-prone default settings:
+
+    $ ip link set canX up type can bitrate 125000
+
+  A device may enter the "bus-off" state if too much errors occurred on
+  the CAN bus. Then no more messages are received or sent. An automatic
+  bus-off recovery can be enabled by setting the "restart-ms" to a
+  non-zero value, e.g.:
+
+    $ ip link set canX type can restart-ms 100
+
+  Alternatively, the application may realize the "bus-off" condition
+  by monitoring CAN error frames and do a restart when appropriate with
+  the command:
+
+    $ ip link set canX type can restart
+
+  Note that a restart will also create a CAN error frame (see also
+  chapter 3.4).
+
+  6.6 Supported CAN hardware
+
+  Please check the "Kconfig" file in "drivers/net/can" to get an actual
+  list of the support CAN hardware. On the Socket CAN project website
+  (see chapter 7) there might be further drivers available, also for
+  older kernel versions.
+
+7. Socket CAN resources
+-----------------------
+
+  You can find further resources for Socket CAN like user space tools,
+  support for old kernel versions, more drivers, mailing lists, etc.
+  at the BerliOS OSS project website for Socket CAN:
+
+    http://developer.berlios.de/projects/socketcan
+
+  If you have questions, bug fixes, etc., don't hesitate to post them to
+  the Socketcan-Users mailing list. But please search the archives first.
+
+8. Credits
 ----------
 
-  Oliver Hartkopp (PF_CAN core, filters, drivers, bcm)
+  Oliver Hartkopp (PF_CAN core, filters, drivers, bcm, SJA1000 driver)
   Urs Thuermann (PF_CAN core, kernel integration, socket interfaces, raw, vcan)
   Jan Kizka (RT-SocketCAN core, Socket-API reconciliation)
-  Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews)
+  Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews,
+                       CAN device driver interface, MSCAN driver)
   Robert Schwebel (design reviews, PTXdist integration)
   Marc Kleine-Budde (design reviews, Kernel 2.6 cleanups, drivers)
   Benedikt Spranger (reviews)
   Thomas Gleixner (LKML reviews, coding style, posting hints)
-  Andrey Volkov (kernel subtree structure, ioctls, mscan driver)
+  Andrey Volkov (kernel subtree structure, ioctls, MSCAN driver)
   Matthias Brukner (first SJA1000 CAN netdevice implementation Q2/2003)
   Klaus Hitschler (PEAK driver integration)
   Uwe Koppe (CAN netdevices with PF_PACKET approach)
   Michael Schulze (driver layer loopback requirement, RT CAN drivers review)
+  Pavel Pisa (Bit-timing calculation)
+  Sascha Hauer (SJA1000 platform driver)
+  Sebastian Haas (SJA1000 EMS PCI driver)
+  Markus Plessing (SJA1000 EMS PCI driver)
+  Per Dalen (SJA1000 Kvaser PCI driver)
+  Sam Ravnborg (reviews, coding style, kbuild help)
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/dm9000.txt linux-libre-2.6.31-gnu/Documentation/networking/dm9000.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/dm9000.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/dm9000.txt	2009-09-09 18:13:59.000000000 -0400
@@ -129,7 +129,7 @@
 ----------------------
 
 The driver keeps track of the link state and informs the network core
-about link (carrier) availablilty. This is managed by several methods
+about link (carrier) availability. This is managed by several methods
 depending on the version of the chip and on which PHY is being used.
 
 For the internal PHY, the original (and currently default) method is
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/ieee802154.txt linux-libre-2.6.31-gnu/Documentation/networking/ieee802154.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/ieee802154.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/networking/ieee802154.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,76 @@
+
+		Linux IEEE 802.15.4 implementation
+
+
+Introduction
+============
+
+The Linux-ZigBee project goal is to provide complete implementation
+of IEEE 802.15.4 / ZigBee / 6LoWPAN protocols. IEEE 802.15.4 is a stack
+of protocols for organizing Low-Rate Wireless Personal Area Networks.
+
+Currently only IEEE 802.15.4 layer is implemented. We have choosen
+to use plain Berkeley socket API, the generic Linux networking stack
+to transfer IEEE 802.15.4 messages and a special protocol over genetlink
+for configuration/management
+
+
+Socket API
+==========
+
+int sd = socket(PF_IEEE802154, SOCK_DGRAM, 0);
+.....
+
+The address family, socket addresses etc. are defined in the
+include/net/ieee802154/af_ieee802154.h header or in the special header
+in our userspace package (see either linux-zigbee sourceforge download page
+or git tree at git://linux-zigbee.git.sourceforge.net/gitroot/linux-zigbee).
+
+One can use SOCK_RAW for passing raw data towards device xmit function. YMMV.
+
+
+MLME - MAC Level Management
+============================
+
+Most of IEEE 802.15.4 MLME interfaces are directly mapped on netlink commands.
+See the include/net/ieee802154/nl802154.h header. Our userspace tools package
+(see above) provides CLI configuration utility for radio interfaces and simple
+coordinator for IEEE 802.15.4 networks as an example users of MLME protocol.
+
+
+Kernel side
+=============
+
+Like with WiFi, there are several types of devices implementing IEEE 802.15.4.
+1) 'HardMAC'. The MAC layer is implemented in the device itself, the device
+   exports MLME and data API.
+2) 'SoftMAC' or just radio. These types of devices are just radio transceivers
+   possibly with some kinds of acceleration like automatic CRC computation and
+   comparation, automagic ACK handling, address matching, etc.
+
+Those types of devices require different approach to be hooked into Linux kernel.
+
+
+HardMAC
+=======
+
+See the header include/net/ieee802154/netdevice.h. You have to implement Linux
+net_device, with .type = ARPHRD_IEEE802154. Data is exchanged with socket family
+code via plain sk_buffs. The control block of sk_buffs will contain additional
+info as described in the struct ieee802154_mac_cb.
+
+To hook the MLME interface you have to populate the ml_priv field of your
+net_device with a pointer to struct ieee802154_mlme_ops instance. All fields are
+required.
+
+We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c
+
+
+SoftMAC
+=======
+
+We are going to provide intermediate layer impelementing IEEE 802.15.4 MAC
+in software. This is currently WIP.
+
+See header include/net/ieee802154/mac802154.h and several drivers in
+drivers/ieee802154/
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/ip-sysctl.txt linux-libre-2.6.31-gnu/Documentation/networking/ip-sysctl.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/ip-sysctl.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/ip-sysctl.txt	2009-09-09 18:13:59.000000000 -0400
@@ -168,7 +168,16 @@
 	Allows TCP to send "duplicate" SACKs.
 
 tcp_ecn - BOOLEAN
-	Enable Explicit Congestion Notification in TCP.
+	Enable Explicit Congestion Notification (ECN) in TCP. ECN is only
+	used when both ends of the TCP flow support it. It is useful to
+	avoid losses due to congestion (when the bottleneck router supports
+	ECN).
+	Possible values are:
+		0 disable ECN
+		1 ECN enabled
+		2 Only server-side ECN enabled. If the other end does
+		  not support ECN, behavior is like with ECN disabled.
+	Default: 2
 
 tcp_fack - BOOLEAN
 	Enable FACK congestion avoidance and fast retransmission.
@@ -1048,6 +1057,13 @@
 	address.
 	Default: FALSE (enable IPv6 operation)
 
+	When this value is changed from 1 to 0 (IPv6 is being enabled),
+	it will dynamically create a link-local address on the given
+	interface and start Duplicate Address Detection, if necessary.
+
+	When this value is changed from 0 to 1 (IPv6 is being disabled),
+	it will dynamically delete all address on the given interface.
+
 accept_dad - INTEGER
 	Whether to accept DAD (Duplicate Address Detection).
 	0: Disable DAD
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/ipv6.txt linux-libre-2.6.31-gnu/Documentation/networking/ipv6.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/ipv6.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/ipv6.txt	2009-09-09 18:13:59.000000000 -0400
@@ -33,3 +33,40 @@
 
 		A reboot is required to enable IPv6.
 
+autoconf
+
+	Specifies whether to enable IPv6 address autoconfiguration
+	on all interfaces.  This might be used when one does not wish
+	for addresses to be automatically generated from prefixes
+	received in Router Advertisements.
+
+	The possible values and their effects are:
+
+	0
+		IPv6 address autoconfiguration is disabled on all interfaces.
+
+		Only the IPv6 loopback address (::1) and link-local addresses
+		will be added to interfaces.
+
+	1
+		IPv6 address autoconfiguration is enabled on all interfaces.
+
+		This is the default value.
+
+disable_ipv6
+
+	Specifies whether to disable IPv6 on all interfaces.
+	This might be used when no IPv6 addresses are desired.
+
+	The possible values and their effects are:
+
+	0
+		IPv6 is enabled on all interfaces.
+
+		This is the default value.
+
+	1
+		IPv6 is disabled on all interfaces.
+
+		No IPv6 addresses will be added to interfaces.
+
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/l2tp.txt linux-libre-2.6.31-gnu/Documentation/networking/l2tp.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/l2tp.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/l2tp.txt	2009-09-09 18:13:59.000000000 -0400
@@ -158,7 +158,7 @@
         }
         return 0;
 
-Miscellanous
+Miscellaneous
 ============
 
 The PPPoL2TP driver was developed as part of the OpenL2TP project by
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/mac80211-injection.txt linux-libre-2.6.31-gnu/Documentation/networking/mac80211-injection.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/mac80211-injection.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/mac80211-injection.txt	2009-09-09 18:13:59.000000000 -0400
@@ -12,38 +12,22 @@
 The radiotap format is discussed in
 ./Documentation/networking/radiotap-headers.txt.
 
-Despite 13 radiotap argument types are currently defined, most only make sense
+Despite many radiotap parameters being currently defined, most only make sense
 to appear on received packets.  The following information is parsed from the
 radiotap headers and used to control injection:
 
- * IEEE80211_RADIOTAP_RATE
-
-   rate in 500kbps units, automatic if invalid or not present
-
-
- * IEEE80211_RADIOTAP_ANTENNA
-
-   antenna to use, automatic if not present
-
-
- * IEEE80211_RADIOTAP_DBM_TX_POWER
-
-   transmit power in dBm, automatic if not present
-
-
  * IEEE80211_RADIOTAP_FLAGS
 
    IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated
    IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available
    IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
-			      current fragmentation threshold. Note that
-			      this flag is only reliable when software
-			      fragmentation is enabled)
+			      current fragmentation threshold.
+
 
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
 
-Here is an example valid radiotap header defining these three parameters
+Here is an example valid radiotap header defining some parameters
 
 	0x00, 0x00, // <-- radiotap version
 	0x0b, 0x00, // <- radiotap header length
@@ -72,8 +56,8 @@
 ...
 	r = pcap_inject(ppcap, u8aSendBuffer, nLength);
 
-You can also find sources for a complete inject test applet here:
+You can also find a link to a complete inject application here:
 
-http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer
+http://wireless.kernel.org/en/users/Documentation/packetspammer
 
 Andy Green <andy@warmcat.com>
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/netdevices.txt linux-libre-2.6.31-gnu/Documentation/networking/netdevices.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/netdevices.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/netdevices.txt	2009-09-09 18:13:59.000000000 -0400
@@ -74,7 +74,7 @@
 	for this and return NETDEV_TX_LOCKED when the spin lock fails.
 	The locking there should also properly protect against 
 	set_multicast_list. Note that the use of NETIF_F_LLTX is deprecated.
-	Dont use it for new drivers.
+	Don't use it for new drivers.
 
 	Context: Process with BHs disabled or BH (timer),
 	         will be called with interrupts disabled by netconsole.
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/operstates.txt linux-libre-2.6.31-gnu/Documentation/networking/operstates.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/operstates.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/operstates.txt	2009-09-09 18:13:59.000000000 -0400
@@ -38,9 +38,6 @@
 ifinfomsg::if_flags & IFF_DORMANT:
  Driver has signaled netif_dormant_on()
 
-These interface flags can also be queried without netlink using the
-SIOCGIFFLAGS ioctl.
-
 TLV IFLA_OPERSTATE
 
 contains RFC2863 state of the interface in numeric representation:
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/packet_mmap.txt linux-libre-2.6.31-gnu/Documentation/networking/packet_mmap.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/packet_mmap.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/packet_mmap.txt	2009-09-09 18:13:59.000000000 -0400
@@ -4,16 +4,18 @@
 
 This file documents the CONFIG_PACKET_MMAP option available with the PACKET
 socket interface on 2.4 and 2.6 kernels. This type of sockets is used for 
-capture network traffic with utilities like tcpdump or any other that uses 
-the libpcap library. 
-
-You can find the latest version of this document at
+capture network traffic with utilities like tcpdump or any other that needs
+raw access to network interface.
 
+You can find the latest version of this document at:
     http://pusa.uv.es/~ulisses/packet_mmap/
 
-Please send me your comments to
+Howto can be found at:
+    http://wiki.gnu-log.net (packet_mmap)
 
+Please send your comments to
     Ulisses Alonso Camaró <uaca@i.hate.spam.alumni.uv.es>
+    Johann Baudy <johann.baudy@gnu-log.net>
 
 -------------------------------------------------------------------------------
 + Why use PACKET_MMAP
@@ -25,19 +27,24 @@
 timestamp (like libpcap always does).
 
 In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size 
-configurable circular buffer mapped in user space. This way reading packets just 
-needs to wait for them, most of the time there is no need to issue a single 
-system call. By using a shared buffer between the kernel and the user 
-also has the benefit of minimizing packet copies.
+configurable circular buffer mapped in user space that can be used to either
+send or receive packets. This way reading packets just needs to wait for them,
+most of the time there is no need to issue a single system call. Concerning
+transmission, multiple packets can be sent through one system call to get the
+highest bandwidth.
+By using a shared buffer between the kernel and the user also has the benefit
+of minimizing packet copies.
 
-It's fine to use PACKET_MMAP to improve the performance of the capture process, 
-but it isn't everything. At least, if you are capturing at high speeds (this 
-is relative to the cpu speed), you should check if the device driver of your 
-network interface card supports some sort of interrupt load mitigation or 
-(even better) if it supports NAPI, also make sure it is enabled.
+It's fine to use PACKET_MMAP to improve the performance of the capture and
+transmission process, but it isn't everything. At least, if you are capturing
+at high speeds (this is relative to the cpu speed), you should check if the
+device driver of your network interface card supports some sort of interrupt
+load mitigation or (even better) if it supports NAPI, also make sure it is
+enabled. For transmission, check the MTU (Maximum Transmission Unit) used and
+supported by devices of your network.
 
 --------------------------------------------------------------------------------
-+ How to use CONFIG_PACKET_MMAP
++ How to use CONFIG_PACKET_MMAP to improve capture process
 --------------------------------------------------------------------------------
 
 From the user standpoint, you should use the higher level libpcap library, which
@@ -57,7 +64,7 @@
 support.
 
 --------------------------------------------------------------------------------
-+ How to use CONFIG_PACKET_MMAP directly
++ How to use CONFIG_PACKET_MMAP directly to improve capture process
 --------------------------------------------------------------------------------
 
 From the system calls stand point, the use of PACKET_MMAP involves
@@ -66,6 +73,7 @@
 
 [setup]     socket() -------> creation of the capture socket
             setsockopt() ---> allocation of the circular buffer (ring)
+                              option: PACKET_RX_RING
             mmap() ---------> mapping of the allocated buffer to the
                               user process
 
@@ -97,13 +105,75 @@
 the use of this buffer.
 
 --------------------------------------------------------------------------------
++ How to use CONFIG_PACKET_MMAP directly to improve transmission process
+--------------------------------------------------------------------------------
+Transmission process is similar to capture as shown below.
+
+[setup]          socket() -------> creation of the transmission socket
+                 setsockopt() ---> allocation of the circular buffer (ring)
+                                   option: PACKET_TX_RING
+                 bind() ---------> bind transmission socket with a network interface
+                 mmap() ---------> mapping of the allocated buffer to the
+                                   user process
+
+[transmission]   poll() ---------> wait for free packets (optional)
+                 send() ---------> send all packets that are set as ready in
+                                   the ring
+                                   The flag MSG_DONTWAIT can be used to return
+                                   before end of transfer.
+
+[shutdown]  close() --------> destruction of the transmission socket and
+                              deallocation of all associated resources.
+
+Binding the socket to your network interface is mandatory (with zero copy) to
+know the header size of frames used in the circular buffer.
+
+As capture, each frame contains two parts:
+
+ --------------------
+| struct tpacket_hdr | Header. It contains the status of
+|                    | of this frame
+|--------------------|
+| data buffer        |
+.                    .  Data that will be sent over the network interface.
+.                    .
+ --------------------
+
+ bind() associates the socket to your network interface thanks to
+ sll_ifindex parameter of struct sockaddr_ll.
+
+ Initialization example:
+
+ struct sockaddr_ll my_addr;
+ struct ifreq s_ifr;
+ ...
+
+ strncpy (s_ifr.ifr_name, "eth0", sizeof(s_ifr.ifr_name));
+
+ /* get interface index of eth0 */
+ ioctl(this->socket, SIOCGIFINDEX, &s_ifr);
+
+ /* fill sockaddr_ll struct to prepare binding */
+ my_addr.sll_family = AF_PACKET;
+ my_addr.sll_protocol = ETH_P_ALL;
+ my_addr.sll_ifindex =  s_ifr.ifr_ifindex;
+
+ /* bind socket to eth0 */
+ bind(this->socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_ll));
+
+ A complete tutorial is available at: http://wiki.gnu-log.net/
+
+--------------------------------------------------------------------------------
 + PACKET_MMAP settings
 --------------------------------------------------------------------------------
 
 
 To setup PACKET_MMAP from user level code is done with a call like
 
+ - Capture process
      setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req))
+ - Transmission process
+     setsockopt(fd, SOL_PACKET, PACKET_TX_RING, (void *) &req, sizeof(req))
 
 The most significant argument in the previous call is the req parameter, 
 this parameter must to have the following structure:
@@ -117,11 +187,11 @@
     };
 
 This structure is defined in /usr/include/linux/if_packet.h and establishes a 
-circular buffer (ring) of unswappable memory mapped in the capture process. 
+circular buffer (ring) of unswappable memory.
 Being mapped in the capture process allows reading the captured frames and 
 related meta-information like timestamps without requiring a system call.
 
-Captured frames are grouped in blocks. Each block is a physically contiguous 
+Frames are grouped in blocks. Each block is a physically contiguous
 region of memory and holds tp_block_size/tp_frame_size frames. The total number 
 of blocks is tp_block_nr. Note that tp_frame_nr is a redundant parameter because
 
@@ -336,6 +406,7 @@
 to be used for the kernel, If not, there is a frame the user can read 
 and the following flags apply:
 
++++ Capture process:
      from include/linux/if_packet.h
 
      #define TP_STATUS_COPY          2 
@@ -391,6 +462,37 @@
 It doesn't incur in a race condition to first check the status value and 
 then poll for frames.
 
+
+++ Transmission process
+Those defines are also used for transmission:
+
+     #define TP_STATUS_AVAILABLE        0 // Frame is available
+     #define TP_STATUS_SEND_REQUEST     1 // Frame will be sent on next send()
+     #define TP_STATUS_SENDING          2 // Frame is currently in transmission
+     #define TP_STATUS_WRONG_FORMAT     4 // Frame format is not correct
+
+First, the kernel initializes all frames to TP_STATUS_AVAILABLE. To send a
+packet, the user fills a data buffer of an available frame, sets tp_len to
+current data buffer size and sets its status field to TP_STATUS_SEND_REQUEST.
+This can be done on multiple frames. Once the user is ready to transmit, it
+calls send(). Then all buffers with status equal to TP_STATUS_SEND_REQUEST are
+forwarded to the network device. The kernel updates each status of sent
+frames with TP_STATUS_SENDING until the end of transfer.
+At the end of each transfer, buffer status returns to TP_STATUS_AVAILABLE.
+
+    header->tp_len = in_i_size;
+    header->tp_status = TP_STATUS_SEND_REQUEST;
+    retval = send(this->socket, NULL, 0, 0);
+
+The user can also use poll() to check if a buffer is available:
+(status == TP_STATUS_SENDING)
+
+    struct pollfd pfd;
+    pfd.fd = fd;
+    pfd.revents = 0;
+    pfd.events = POLLOUT;
+    retval = poll(&pfd, 1, timeout);
+
 --------------------------------------------------------------------------------
 + THANKS
 --------------------------------------------------------------------------------
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/phonet.txt linux-libre-2.6.31-gnu/Documentation/networking/phonet.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/phonet.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/phonet.txt	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,7 @@
 On Linux, the link-layer header includes the pn_media byte (see below).
 The next 7 bytes are part of the network-layer header.
 
-The device ID is split: the 6 higher-order bits consitute the device
+The device ID is split: the 6 higher-order bits constitute the device
 address, while the 2 lower-order bits are used for multiplexing, as are
 the 8-bit object identifiers. As such, Phonet can be considered as a
 network layer with 6 bits of address space and 10 bits for transport
diff -druN linux-libre-2.6.30-gnu/Documentation/networking/regulatory.txt linux-libre-2.6.31-gnu/Documentation/networking/regulatory.txt
--- linux-libre-2.6.30-gnu/Documentation/networking/regulatory.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/networking/regulatory.txt	2009-09-09 18:13:59.000000000 -0400
@@ -89,7 +89,7 @@
 Device drivers who provide their own built regulatory domain
 do not need a callback as the channels registered by them are
 the only ones that will be allowed and therefore *additional*
-cannels cannot be enabled.
+channels cannot be enabled.
 
 Example code - drivers hinting an alpha2:
 ------------------------------------------
diff -druN linux-libre-2.6.30-gnu/Documentation/PCI/pcieaer-howto.txt linux-libre-2.6.31-gnu/Documentation/PCI/pcieaer-howto.txt
--- linux-libre-2.6.30-gnu/Documentation/PCI/pcieaer-howto.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/PCI/pcieaer-howto.txt	2009-09-09 18:13:59.000000000 -0400
@@ -61,6 +61,10 @@
 walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
 when booting kernel. Note that forceload=n by default.
 
+nosourceid, another parameter of type bool, can be used when broken
+hardware (mostly chipsets) has root ports that cannot obtain the reporting
+source ID. nosourceid=n by default.
+
 2.3 AER error output
 When a PCI-E AER error is captured, an error message will be outputed to
 console. If it's a correctable error, it is outputed as a warning.
@@ -246,3 +250,24 @@
 A: It could call the helper functions to enable AER in devices and
 cleanup uncorrectable status register. Pls. refer to section 3.3.
 
+
+4. Software error injection
+
+Debugging PCIE AER error recovery code is quite difficult because it
+is hard to trigger real hardware errors. Software based error
+injection can be used to fake various kinds of PCIE errors.
+
+First you should enable PCIE AER software error injection in kernel
+configuration, that is, following item should be in your .config.
+
+CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m
+
+After reboot with new kernel or insert the module, a device file named
+/dev/aer_inject should be created.
+
+Then, you need a user space tool named aer-inject, which can be gotten
+from:
+    http://www.kernel.org/pub/linux/utils/pci/aer-inject/
+
+More information about aer-inject can be found in the document comes
+with its source code.
diff -druN linux-libre-2.6.30-gnu/Documentation/power/devices.txt linux-libre-2.6.31-gnu/Documentation/power/devices.txt
--- linux-libre-2.6.30-gnu/Documentation/power/devices.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/power/devices.txt	2009-09-09 18:13:59.000000000 -0400
@@ -75,9 +75,6 @@
 struct bus_type {
 	...
 	int  (*suspend)(struct device *dev, pm_message_t state);
-	int  (*suspend_late)(struct device *dev, pm_message_t state);
-
-	int  (*resume_early)(struct device *dev);
 	int  (*resume)(struct device *dev);
 };
 
@@ -226,20 +223,7 @@
 
 	This call should handle parts of device suspend logic that require
 	sleeping.  It probably does work to quiesce the device which hasn't
-	been abstracted into class.suspend() or bus.suspend_late().
-
-   3	bus.suspend_late(dev, message) is called with IRQs disabled, and
-	with only one CPU active.  Until the bus.resume_early() phase
-	completes (see later), IRQs are not enabled again.  This method
-	won't be exposed by all busses; for message based busses like USB,
-	I2C, or SPI, device interactions normally require IRQs.  This bus
-	call may be morphed into a driver call with bus-specific parameters.
-
-	This call might save low level hardware state that might otherwise
-	be lost in the upcoming low power state, and actually put the
-	device into a low power state ... so that in some cases the device
-	may stay partly usable until this late.  This "late" call may also
-	help when coping with hardware that behaves badly.
+	been abstracted into class.suspend().
 
 The pm_message_t parameter is currently used to refine those semantics
 (described later).
@@ -351,19 +335,11 @@
 
 The phases are seen by driver notifications issued in this order:
 
-   1	bus.resume_early(dev) is called with IRQs disabled, and with
-   	only one CPU active.  As with bus.suspend_late(), this method
-	won't be supported on busses that require IRQs in order to
-	interact with devices.
-
-	This reverses the effects of bus.suspend_late().
-
-   2	bus.resume(dev) is called next.  This may be morphed into a device
-   	driver call with bus-specific parameters; implementations may sleep.
-
-	This reverses the effects of bus.suspend().
+   1	bus.resume(dev) reverses the effects of bus.suspend().  This may
+	be morphed into a device driver call with bus-specific parameters;
+	implementations may sleep.
 
-   3	class.resume(dev) is called for devices associated with a class
+   2	class.resume(dev) is called for devices associated with a class
 	that has such a method.  Implementations may sleep.
 
 	This reverses the effects of class.suspend(), and would usually
diff -druN linux-libre-2.6.30-gnu/Documentation/power/regulator/consumer.txt linux-libre-2.6.31-gnu/Documentation/power/regulator/consumer.txt
--- linux-libre-2.6.30-gnu/Documentation/power/regulator/consumer.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/power/regulator/consumer.txt	2009-09-09 18:13:59.000000000 -0400
@@ -178,5 +178,5 @@
 int regulator_unregister_notifier(struct regulator *regulator,
 				struct notifier_block *nb);
 
-Regulators use the kernel notifier framework to send event to thier interested
+Regulators use the kernel notifier framework to send event to their interested
 consumers.
diff -druN linux-libre-2.6.30-gnu/Documentation/power/regulator/overview.txt linux-libre-2.6.31-gnu/Documentation/power/regulator/overview.txt
--- linux-libre-2.6.30-gnu/Documentation/power/regulator/overview.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/power/regulator/overview.txt	2009-09-09 18:13:59.000000000 -0400
@@ -119,7 +119,7 @@
                    battery power, USB power)
 
                    Regulator Domains: is the new current limit within the
-                   regulator operating parameters for input/ouput voltage.
+                   regulator operating parameters for input/output voltage.
 
                    If the regulator request passes all the constraint tests
                    then the new regulator value is applied.
diff -druN linux-libre-2.6.30-gnu/Documentation/power/s2ram.txt linux-libre-2.6.31-gnu/Documentation/power/s2ram.txt
--- linux-libre-2.6.30-gnu/Documentation/power/s2ram.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/power/s2ram.txt	2009-09-09 18:13:59.000000000 -0400
@@ -63,7 +63,7 @@
 survive a reboot.
 
 Consequence is that after a resume (even if it is successful) your system
-clock will have a value corresponding to the magic mumber instead of the
+clock will have a value corresponding to the magic number instead of the
 correct date/time! It is therefore advisable to use a program like ntp-date
 or rdate to reset the correct date/time from an external time source when
 using this trace option.
diff -druN linux-libre-2.6.30-gnu/Documentation/power/userland-swsusp.txt linux-libre-2.6.31-gnu/Documentation/power/userland-swsusp.txt
--- linux-libre-2.6.30-gnu/Documentation/power/userland-swsusp.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/power/userland-swsusp.txt	2009-09-09 18:13:59.000000000 -0400
@@ -109,7 +109,7 @@
 still frozen when the device is being closed).
 
 Currently it is assumed that the userland utilities reading/writing the
-snapshot image from/to the kernel will use a swap parition, called the resume
+snapshot image from/to the kernel will use a swap partition, called the resume
 partition, or a swap file as storage space (if a swap file is used, the resume
 partition is the partition that holds this file).  However, this is not really
 required, as they can use, for example, a special (blank) suspend partition or
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/booting-without-of.txt linux-libre-2.6.31-gnu/Documentation/powerpc/booting-without-of.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/booting-without-of.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/booting-without-of.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1238,1122 +1238,7 @@
 defined; this list will expand as more and more SOC-containing
 platforms are moved over to use the flattened-device-tree model.
 
-   a) PHY nodes
-
-   Required properties:
-
-    - device_type : Should be "ethernet-phy"
-    - interrupts : <a b> where a is the interrupt number and b is a
-      field that represents an encoding of the sense and level
-      information for the interrupt.  This should be encoded based on
-      the information in section 2) depending on the type of interrupt
-      controller you have.
-    - interrupt-parent : the phandle for the interrupt controller that
-      services interrupts for this device.
-    - reg : The ID number for the phy, usually a small integer
-    - linux,phandle :  phandle for this node; likely referenced by an
-      ethernet controller node.
-
-
-   Example:
-
-	ethernet-phy@0 {
-		linux,phandle = <2452000>
-		interrupt-parent = <40000>;
-		interrupts = <35 1>;
-		reg = <0>;
-		device_type = "ethernet-phy";
-	};
-
-
-   b) Interrupt controllers
-
-   Some SOC devices contain interrupt controllers that are different
-   from the standard Open PIC specification.  The SOC device nodes for
-   these types of controllers should be specified just like a standard
-   OpenPIC controller.  Sense and level information should be encoded
-   as specified in section 2) of this chapter for each device that
-   specifies an interrupt.
-
-   Example :
-
-	pic@40000 {
-		linux,phandle = <40000>;
-		interrupt-controller;
-		#address-cells = <0>;
-		reg = <40000 40000>;
-		compatible = "chrp,open-pic";
-		device_type = "open-pic";
-	};
-
-    c) 4xx/Axon EMAC ethernet nodes
-
-    The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
-    the Axon bridge.  To operate this needs to interact with a ths
-    special McMAL DMA controller, and sometimes an RGMII or ZMII
-    interface.  In addition to the nodes and properties described
-    below, the node for the OPB bus on which the EMAC sits must have a
-    correct clock-frequency property.
-
-      i) The EMAC node itself
-
-    Required properties:
-    - device_type       : "network"
-
-    - compatible        : compatible list, contains 2 entries, first is
-			  "ibm,emac-CHIP" where CHIP is the host ASIC (440gx,
-			  405gp, Axon) and second is either "ibm,emac" or
-			  "ibm,emac4".  For Axon, thus, we have: "ibm,emac-axon",
-			  "ibm,emac4"
-    - interrupts        : <interrupt mapping for EMAC IRQ and WOL IRQ>
-    - interrupt-parent  : optional, if needed for interrupt mapping
-    - reg               : <registers mapping>
-    - local-mac-address : 6 bytes, MAC address
-    - mal-device        : phandle of the associated McMAL node
-    - mal-tx-channel    : 1 cell, index of the tx channel on McMAL associated
-			  with this EMAC
-    - mal-rx-channel    : 1 cell, index of the rx channel on McMAL associated
-			  with this EMAC
-    - cell-index        : 1 cell, hardware index of the EMAC cell on a given
-			  ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on
-			  each Axon chip)
-    - max-frame-size    : 1 cell, maximum frame size supported in bytes
-    - rx-fifo-size      : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec
-			  operations.
-			  For Axon, 2048
-    - tx-fifo-size      : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec
-			  operations.
-			  For Axon, 2048.
-    - fifo-entry-size   : 1 cell, size of a fifo entry (used to calculate
-			  thresholds).
-			  For Axon, 0x00000010
-    - mal-burst-size    : 1 cell, MAL burst size (used to calculate thresholds)
-			  in bytes.
-			  For Axon, 0x00000100 (I think ...)
-    - phy-mode          : string, mode of operations of the PHY interface.
-			  Supported values are: "mii", "rmii", "smii", "rgmii",
-			  "tbi", "gmii", rtbi", "sgmii".
-			  For Axon on CAB, it is "rgmii"
-    - mdio-device       : 1 cell, required iff using shared MDIO registers
-			  (440EP).  phandle of the EMAC to use to drive the
-			  MDIO lines for the PHY used by this EMAC.
-    - zmii-device       : 1 cell, required iff connected to a ZMII.  phandle of
-			  the ZMII device node
-    - zmii-channel      : 1 cell, required iff connected to a ZMII.  Which ZMII
-			  channel or 0xffffffff if ZMII is only used for MDIO.
-    - rgmii-device      : 1 cell, required iff connected to an RGMII. phandle
-			  of the RGMII device node.
-			  For Axon: phandle of plb5/plb4/opb/rgmii
-    - rgmii-channel     : 1 cell, required iff connected to an RGMII.  Which
-			  RGMII channel is used by this EMAC.
-			  Fox Axon: present, whatever value is appropriate for each
-			  EMAC, that is the content of the current (bogus) "phy-port"
-			  property.
-
-    Optional properties:
-    - phy-address       : 1 cell, optional, MDIO address of the PHY. If absent,
-			  a search is performed.
-    - phy-map           : 1 cell, optional, bitmap of addresses to probe the PHY
-			  for, used if phy-address is absent. bit 0x00000001 is
-			  MDIO address 0.
-			  For Axon it can be absent, thouugh my current driver
-			  doesn't handle phy-address yet so for now, keep
-			  0x00ffffff in it.
-    - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
-			  operations (if absent the value is the same as
-			  rx-fifo-size).  For Axon, either absent or 2048.
-    - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec
-			  operations (if absent the value is the same as
-			  tx-fifo-size). For Axon, either absent or 2048.
-    - tah-device        : 1 cell, optional. If connected to a TAH engine for
-			  offload, phandle of the TAH device node.
-    - tah-channel       : 1 cell, optional. If appropriate, channel used on the
-			  TAH engine.
-
-    Example:
-
-	EMAC0: ethernet@40000800 {
-		device_type = "network";
-		compatible = "ibm,emac-440gp", "ibm,emac";
-		interrupt-parent = <&UIC1>;
-		interrupts = <1c 4 1d 4>;
-		reg = <40000800 70>;
-		local-mac-address = [00 04 AC E3 1B 1E];
-		mal-device = <&MAL0>;
-		mal-tx-channel = <0 1>;
-		mal-rx-channel = <0>;
-		cell-index = <0>;
-		max-frame-size = <5dc>;
-		rx-fifo-size = <1000>;
-		tx-fifo-size = <800>;
-		phy-mode = "rmii";
-		phy-map = <00000001>;
-		zmii-device = <&ZMII0>;
-		zmii-channel = <0>;
-	};
-
-      ii) McMAL node
-
-    Required properties:
-    - device_type        : "dma-controller"
-    - compatible         : compatible list, containing 2 entries, first is
-			   "ibm,mcmal-CHIP" where CHIP is the host ASIC (like
-			   emac) and the second is either "ibm,mcmal" or
-			   "ibm,mcmal2".
-			   For Axon, "ibm,mcmal-axon","ibm,mcmal2"
-    - interrupts         : <interrupt mapping for the MAL interrupts sources:
-                           5 sources: tx_eob, rx_eob, serr, txde, rxde>.
-                           For Axon: This is _different_ from the current
-			   firmware.  We use the "delayed" interrupts for txeob
-			   and rxeob. Thus we end up with mapping those 5 MPIC
-			   interrupts, all level positive sensitive: 10, 11, 32,
-			   33, 34 (in decimal)
-    - dcr-reg            : < DCR registers range >
-    - dcr-parent         : if needed for dcr-reg
-    - num-tx-chans       : 1 cell, number of Tx channels
-    - num-rx-chans       : 1 cell, number of Rx channels
-
-      iii) ZMII node
-
-    Required properties:
-    - compatible         : compatible list, containing 2 entries, first is
-			   "ibm,zmii-CHIP" where CHIP is the host ASIC (like
-			   EMAC) and the second is "ibm,zmii".
-			   For Axon, there is no ZMII node.
-    - reg                : <registers mapping>
-
-      iv) RGMII node
-
-    Required properties:
-    - compatible         : compatible list, containing 2 entries, first is
-			   "ibm,rgmii-CHIP" where CHIP is the host ASIC (like
-			   EMAC) and the second is "ibm,rgmii".
-                           For Axon, "ibm,rgmii-axon","ibm,rgmii"
-    - reg                : <registers mapping>
-    - revision           : as provided by the RGMII new version register if
-			   available.
-			   For Axon: 0x0000012a
-
-   d) Xilinx IP cores
-
-   The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
-   in Xilinx Spartan and Virtex FPGAs.  The devices cover the whole range
-   of standard device types (network, serial, etc.) and miscellanious
-   devices (gpio, LCD, spi, etc).  Also, since these devices are
-   implemented within the fpga fabric every instance of the device can be
-   synthesised with different options that change the behaviour.
-
-   Each IP-core has a set of parameters which the FPGA designer can use to
-   control how the core is synthesized.  Historically, the EDK tool would
-   extract the device parameters relevant to device drivers and copy them
-   into an 'xparameters.h' in the form of #define symbols.  This tells the
-   device drivers how the IP cores are configured, but it requres the kernel
-   to be recompiled every time the FPGA bitstream is resynthesized.
-
-   The new approach is to export the parameters into the device tree and
-   generate a new device tree each time the FPGA bitstream changes.  The
-   parameters which used to be exported as #defines will now become
-   properties of the device node.  In general, device nodes for IP-cores
-   will take the following form:
-
-	(name): (generic-name)@(base-address) {
-		compatible = "xlnx,(ip-core-name)-(HW_VER)"
-			     [, (list of compatible devices), ...];
-		reg = <(baseaddr) (size)>;
-		interrupt-parent = <&interrupt-controller-phandle>;
-		interrupts = < ... >;
-		xlnx,(parameter1) = "(string-value)";
-		xlnx,(parameter2) = <(int-value)>;
-	};
-
-	(generic-name):   an open firmware-style name that describes the
-			generic class of device.  Preferably, this is one word, such
-			as 'serial' or 'ethernet'.
-	(ip-core-name):	the name of the ip block (given after the BEGIN
-			directive in system.mhs).  Should be in lowercase
-			and all underscores '_' converted to dashes '-'.
-	(name):		is derived from the "PARAMETER INSTANCE" value.
-	(parameter#):	C_* parameters from system.mhs.  The C_ prefix is
-			dropped from the parameter name, the name is converted
-			to lowercase and all underscore '_' characters are
-			converted to dashes '-'.
-	(baseaddr):	the baseaddr parameter value (often named C_BASEADDR).
-	(HW_VER):	from the HW_VER parameter.
-	(size):		the address range size (often C_HIGHADDR - C_BASEADDR + 1).
-
-   Typically, the compatible list will include the exact IP core version
-   followed by an older IP core version which implements the same
-   interface or any other device with the same interface.
-
-   'reg', 'interrupt-parent' and 'interrupts' are all optional properties.
-
-   For example, the following block from system.mhs:
-
-	BEGIN opb_uartlite
-		PARAMETER INSTANCE = opb_uartlite_0
-		PARAMETER HW_VER = 1.00.b
-		PARAMETER C_BAUDRATE = 115200
-		PARAMETER C_DATA_BITS = 8
-		PARAMETER C_ODD_PARITY = 0
-		PARAMETER C_USE_PARITY = 0
-		PARAMETER C_CLK_FREQ = 50000000
-		PARAMETER C_BASEADDR = 0xEC100000
-		PARAMETER C_HIGHADDR = 0xEC10FFFF
-		BUS_INTERFACE SOPB = opb_7
-		PORT OPB_Clk = CLK_50MHz
-		PORT Interrupt = opb_uartlite_0_Interrupt
-		PORT RX = opb_uartlite_0_RX
-		PORT TX = opb_uartlite_0_TX
-		PORT OPB_Rst = sys_bus_reset_0
-	END
-
-   becomes the following device tree node:
-
-	opb_uartlite_0: serial@ec100000 {
-		device_type = "serial";
-		compatible = "xlnx,opb-uartlite-1.00.b";
-		reg = <ec100000 10000>;
-		interrupt-parent = <&opb_intc_0>;
-		interrupts = <1 0>; // got this from the opb_intc parameters
-		current-speed = <d#115200>;	// standard serial device prop
-		clock-frequency = <d#50000000>;	// standard serial device prop
-		xlnx,data-bits = <8>;
-		xlnx,odd-parity = <0>;
-		xlnx,use-parity = <0>;
-	};
-
-   Some IP cores actually implement 2 or more logical devices.  In
-   this case, the device should still describe the whole IP core with
-   a single node and add a child node for each logical device.  The
-   ranges property can be used to translate from parent IP-core to the
-   registers of each device.  In addition, the parent node should be
-   compatible with the bus type 'xlnx,compound', and should contain
-   #address-cells and #size-cells, as with any other bus.  (Note: this
-   makes the assumption that both logical devices have the same bus
-   binding.  If this is not true, then separate nodes should be used
-   for each logical device).  The 'cell-index' property can be used to
-   enumerate logical devices within an IP core.  For example, the
-   following is the system.mhs entry for the dual ps2 controller found
-   on the ml403 reference design.
-
-	BEGIN opb_ps2_dual_ref
-		PARAMETER INSTANCE = opb_ps2_dual_ref_0
-		PARAMETER HW_VER = 1.00.a
-		PARAMETER C_BASEADDR = 0xA9000000
-		PARAMETER C_HIGHADDR = 0xA9001FFF
-		BUS_INTERFACE SOPB = opb_v20_0
-		PORT Sys_Intr1 = ps2_1_intr
-		PORT Sys_Intr2 = ps2_2_intr
-		PORT Clkin1 = ps2_clk_rx_1
-		PORT Clkin2 = ps2_clk_rx_2
-		PORT Clkpd1 = ps2_clk_tx_1
-		PORT Clkpd2 = ps2_clk_tx_2
-		PORT Rx1 = ps2_d_rx_1
-		PORT Rx2 = ps2_d_rx_2
-		PORT Txpd1 = ps2_d_tx_1
-		PORT Txpd2 = ps2_d_tx_2
-	END
-
-   It would result in the following device tree nodes:
-
-	opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "xlnx,compound";
-		ranges = <0 a9000000 2000>;
-		// If this device had extra parameters, then they would
-		// go here.
-		ps2@0 {
-			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
-			reg = <0 40>;
-			interrupt-parent = <&opb_intc_0>;
-			interrupts = <3 0>;
-			cell-index = <0>;
-		};
-		ps2@1000 {
-			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
-			reg = <1000 40>;
-			interrupt-parent = <&opb_intc_0>;
-			interrupts = <3 0>;
-			cell-index = <0>;
-		};
-	};
-
-   Also, the system.mhs file defines bus attachments from the processor
-   to the devices.  The device tree structure should reflect the bus
-   attachments.  Again an example; this system.mhs fragment:
-
-	BEGIN ppc405_virtex4
-		PARAMETER INSTANCE = ppc405_0
-		PARAMETER HW_VER = 1.01.a
-		BUS_INTERFACE DPLB = plb_v34_0
-		BUS_INTERFACE IPLB = plb_v34_0
-	END
-
-	BEGIN opb_intc
-		PARAMETER INSTANCE = opb_intc_0
-		PARAMETER HW_VER = 1.00.c
-		PARAMETER C_BASEADDR = 0xD1000FC0
-		PARAMETER C_HIGHADDR = 0xD1000FDF
-		BUS_INTERFACE SOPB = opb_v20_0
-	END
-
-	BEGIN opb_uart16550
-		PARAMETER INSTANCE = opb_uart16550_0
-		PARAMETER HW_VER = 1.00.d
-		PARAMETER C_BASEADDR = 0xa0000000
-		PARAMETER C_HIGHADDR = 0xa0001FFF
-		BUS_INTERFACE SOPB = opb_v20_0
-	END
-
-	BEGIN plb_v34
-		PARAMETER INSTANCE = plb_v34_0
-		PARAMETER HW_VER = 1.02.a
-	END
-
-	BEGIN plb_bram_if_cntlr
-		PARAMETER INSTANCE = plb_bram_if_cntlr_0
-		PARAMETER HW_VER = 1.00.b
-		PARAMETER C_BASEADDR = 0xFFFF0000
-		PARAMETER C_HIGHADDR = 0xFFFFFFFF
-		BUS_INTERFACE SPLB = plb_v34_0
-	END
-
-	BEGIN plb2opb_bridge
-		PARAMETER INSTANCE = plb2opb_bridge_0
-		PARAMETER HW_VER = 1.01.a
-		PARAMETER C_RNG0_BASEADDR = 0x20000000
-		PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF
-		PARAMETER C_RNG1_BASEADDR = 0x60000000
-		PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF
-		PARAMETER C_RNG2_BASEADDR = 0x80000000
-		PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF
-		PARAMETER C_RNG3_BASEADDR = 0xC0000000
-		PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF
-		BUS_INTERFACE SPLB = plb_v34_0
-		BUS_INTERFACE MOPB = opb_v20_0
-	END
-
-   Gives this device tree (some properties removed for clarity):
-
-	plb@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "xlnx,plb-v34-1.02.a";
-		device_type = "ibm,plb";
-		ranges; // 1:1 translation
-
-		plb_bram_if_cntrl_0: bram@ffff0000 {
-			reg = <ffff0000 10000>;
-		}
-
-		opb@20000000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <20000000 20000000 20000000
-				  60000000 60000000 20000000
-				  80000000 80000000 40000000
-				  c0000000 c0000000 20000000>;
-
-			opb_uart16550_0: serial@a0000000 {
-				reg = <a00000000 2000>;
-			};
-
-			opb_intc_0: interrupt-controller@d1000fc0 {
-				reg = <d1000fc0 20>;
-			};
-		};
-	};
-
-   That covers the general approach to binding xilinx IP cores into the
-   device tree.  The following are bindings for specific devices:
-
-      i) Xilinx ML300 Framebuffer
-
-      Simple framebuffer device from the ML300 reference design (also on the
-      ML403 reference design as well as others).
-
-      Optional properties:
-       - resolution = <xres yres> : pixel resolution of framebuffer.  Some
-                                    implementations use a different resolution.
-                                    Default is <d#640 d#480>
-       - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory.
-                                           Default is <d#1024 d#480>.
-       - rotate-display (empty) : rotate display 180 degrees.
-
-      ii) Xilinx SystemACE
-
-      The Xilinx SystemACE device is used to program FPGAs from an FPGA
-      bitstream stored on a CF card.  It can also be used as a generic CF
-      interface device.
-
-      Optional properties:
-       - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
-
-      iii) Xilinx EMAC and Xilinx TEMAC
-
-      Xilinx Ethernet devices.  In addition to general xilinx properties
-      listed above, nodes for these devices should include a phy-handle
-      property, and may include other common network device properties
-      like local-mac-address.
-
-      iv) Xilinx Uartlite
-
-      Xilinx uartlite devices are simple fixed speed serial ports.
-
-      Required properties:
-       - current-speed : Baud rate of uartlite
-
-      v) Xilinx hwicap
-
-		Xilinx hwicap devices provide access to the configuration logic
-		of the FPGA through the Internal Configuration Access Port
-		(ICAP).  The ICAP enables partial reconfiguration of the FPGA,
-		readback of the configuration information, and some control over
-		'warm boots' of the FPGA fabric.
-
-		Required properties:
-		- xlnx,family : The family of the FPGA, necessary since the
-                      capabilities of the underlying ICAP hardware
-                      differ between different families.  May be
-                      'virtex2p', 'virtex4', or 'virtex5'.
-
-      vi) Xilinx Uart 16550
-
-      Xilinx UART 16550 devices are very similar to the NS16550 but with
-      different register spacing and an offset from the base address.
-
-      Required properties:
-       - clock-frequency : Frequency of the clock input
-       - reg-offset : A value of 3 is required
-       - reg-shift : A value of 2 is required
-
-    e) USB EHCI controllers
-
-    Required properties:
-      - compatible : should be "usb-ehci".
-      - reg : should contain at least address and length of the standard EHCI
-        register set for the device. Optional platform-dependent registers
-        (debug-port or other) can be also specified here, but only after
-        definition of standard EHCI registers.
-      - interrupts : one EHCI interrupt should be described here.
-    If device registers are implemented in big endian mode, the device
-    node should have "big-endian-regs" property.
-    If controller implementation operates with big endian descriptors,
-    "big-endian-desc" property should be specified.
-    If both big endian registers and descriptors are used by the controller
-    implementation, "big-endian" property can be specified instead of having
-    both "big-endian-regs" and "big-endian-desc".
-
-     Example (Sequoia 440EPx):
-	    ehci@e0000300 {
-		   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
-		   interrupt-parent = <&UIC0>;
-		   interrupts = <1a 4>;
-		   reg = <0 e0000300 90 0 e0000390 70>;
-		   big-endian;
-	   };
-
-   f) MDIO on GPIOs
-
-   Currently defined compatibles:
-   - virtual,gpio-mdio
-
-   MDC and MDIO lines connected to GPIO controllers are listed in the
-   gpios property as described in section VIII.1 in the following order:
-
-   MDC, MDIO.
-
-   Example:
-
-	mdio {
-		compatible = "virtual,mdio-gpio";
-		#address-cells = <1>;
-		#size-cells = <0>;
-		gpios = <&qe_pio_a 11
-			 &qe_pio_c 6>;
-	};
-
-    g) SPI (Serial Peripheral Interface) busses
-
-    SPI busses can be described with a node for the SPI master device
-    and a set of child nodes for each SPI slave on the bus.  For this
-    discussion, it is assumed that the system's SPI controller is in
-    SPI master mode.  This binding does not describe SPI controllers
-    in slave mode.
-
-    The SPI master node requires the following properties:
-    - #address-cells  - number of cells required to define a chip select
-			address on the SPI bus.
-    - #size-cells     - should be zero.
-    - compatible      - name of SPI bus controller following generic names
-			recommended practice.
-    No other properties are required in the SPI bus node.  It is assumed
-    that a driver for an SPI bus device will understand that it is an SPI bus.
-    However, the binding does not attempt to define the specific method for
-    assigning chip select numbers.  Since SPI chip select configuration is
-    flexible and non-standardized, it is left out of this binding with the
-    assumption that board specific platform code will be used to manage
-    chip selects.  Individual drivers can define additional properties to
-    support describing the chip select layout.
-
-    SPI slave nodes must be children of the SPI master node and can
-    contain the following properties.
-    - reg             - (required) chip select address of device.
-    - compatible      - (required) name of SPI device following generic names
-			recommended practice
-    - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
-    - spi-cpol        - (optional) Empty property indicating device requires
-			inverse clock polarity (CPOL) mode
-    - spi-cpha        - (optional) Empty property indicating device requires
-			shifted clock phase (CPHA) mode
-    - spi-cs-high     - (optional) Empty property indicating device requires
-			chip select active high
-
-    SPI example for an MPC5200 SPI bus:
-		spi@f00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-			reg = <0xf00 0x20>;
-			interrupts = <2 13 0 2 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
-
-			ethernet-switch@0 {
-				compatible = "micrel,ks8995m";
-				spi-max-frequency = <1000000>;
-				reg = <0>;
-			};
-
-			codec@1 {
-				compatible = "ti,tlv320aic26";
-				spi-max-frequency = <100000>;
-				reg = <1>;
-			};
-		};
-
-VII - Marvell Discovery mv64[345]6x System Controller chips
-===========================================================
-
-The Marvell mv64[345]60 series of system controller chips contain
-many of the peripherals needed to implement a complete computer
-system.  In this section, we define device tree nodes to describe
-the system controller chip itself and each of the peripherals
-which it contains.  Compatible string values for each node are
-prefixed with the string "marvell,", for Marvell Technology Group Ltd.
-
-1) The /system-controller node
-
-  This node is used to represent the system-controller and must be
-  present when the system uses a system controller chip. The top-level
-  system-controller node contains information that is global to all
-  devices within the system controller chip. The node name begins
-  with "system-controller" followed by the unit address, which is
-  the base address of the memory-mapped register set for the system
-  controller chip.
-
-  Required properties:
-
-    - ranges : Describes the translation of system controller addresses
-      for memory mapped registers.
-    - clock-frequency: Contains the main clock frequency for the system
-      controller chip.
-    - reg : This property defines the address and size of the
-      memory-mapped registers contained within the system controller
-      chip.  The address specified in the "reg" property should match
-      the unit address of the system-controller node.
-    - #address-cells : Address representation for system controller
-      devices.  This field represents the number of cells needed to
-      represent the address of the memory-mapped registers of devices
-      within the system controller chip.
-    - #size-cells : Size representation for for the memory-mapped
-      registers within the system controller chip.
-    - #interrupt-cells : Defines the width of cells used to represent
-      interrupts.
-
-  Optional properties:
-
-    - model : The specific model of the system controller chip.  Such
-      as, "mv64360", "mv64460", or "mv64560".
-    - compatible : A string identifying the compatibility identifiers
-      of the system controller chip.
-
-  The system-controller node contains child nodes for each system
-  controller device that the platform uses.  Nodes should not be created
-  for devices which exist on the system controller chip but are not used
-
-  Example Marvell Discovery mv64360 system-controller node:
-
-    system-controller@f1000000 { /* Marvell Discovery mv64360 */
-	    #address-cells = <1>;
-	    #size-cells = <1>;
-	    model = "mv64360";                      /* Default */
-	    compatible = "marvell,mv64360";
-	    clock-frequency = <133333333>;
-	    reg = <0xf1000000 0x10000>;
-	    virtual-reg = <0xf1000000>;
-	    ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
-		    0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
-		    0xa0000000 0xa0000000 0x4000000 /* User FLASH */
-		    0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
-		    0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
-
-	    [ child node definitions... ]
-    }
-
-2) Child nodes of /system-controller
-
-   a) Marvell Discovery MDIO bus
-
-   The MDIO is a bus to which the PHY devices are connected.  For each
-   device that exists on this bus, a child node should be created.  See
-   the definition of the PHY node below for an example of how to define
-   a PHY.
-
-   Required properties:
-     - #address-cells : Should be <1>
-     - #size-cells : Should be <0>
-     - device_type : Should be "mdio"
-     - compatible : Should be "marvell,mv64360-mdio"
-
-   Example:
-
-     mdio {
-	     #address-cells = <1>;
-	     #size-cells = <0>;
-	     device_type = "mdio";
-	     compatible = "marvell,mv64360-mdio";
-
-	     ethernet-phy@0 {
-		     ......
-	     };
-     };
-
-
-   b) Marvell Discovery ethernet controller
-
-   The Discover ethernet controller is described with two levels
-   of nodes.  The first level describes an ethernet silicon block
-   and the second level describes up to 3 ethernet nodes within
-   that block.  The reason for the multiple levels is that the
-   registers for the node are interleaved within a single set
-   of registers.  The "ethernet-block" level describes the
-   shared register set, and the "ethernet" nodes describe ethernet
-   port-specific properties.
-
-   Ethernet block node
-
-   Required properties:
-     - #address-cells : <1>
-     - #size-cells : <0>
-     - compatible : "marvell,mv64360-eth-block"
-     - reg : Offset and length of the register set for this block
-
-   Example Discovery Ethernet block node:
-     ethernet-block@2000 {
-	     #address-cells = <1>;
-	     #size-cells = <0>;
-	     compatible = "marvell,mv64360-eth-block";
-	     reg = <0x2000 0x2000>;
-	     ethernet@0 {
-		     .......
-	     };
-     };
-
-   Ethernet port node
-
-   Required properties:
-     - device_type : Should be "network".
-     - compatible : Should be "marvell,mv64360-eth".
-     - reg : Should be <0>, <1>, or <2>, according to which registers
-       within the silicon block the device uses.
-     - interrupts : <a> where a is the interrupt number for the port.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-     - phy : the phandle for the PHY connected to this ethernet
-       controller.
-     - local-mac-address : 6 bytes, MAC address
-
-   Example Discovery Ethernet port node:
-     ethernet@0 {
-	     device_type = "network";
-	     compatible = "marvell,mv64360-eth";
-	     reg = <0>;
-	     interrupts = <32>;
-	     interrupt-parent = <&PIC>;
-	     phy = <&PHY0>;
-	     local-mac-address = [ 00 00 00 00 00 00 ];
-     };
-
-
-
-   c) Marvell Discovery PHY nodes
-
-   Required properties:
-     - device_type : Should be "ethernet-phy"
-     - interrupts : <a> where a is the interrupt number for this phy.
-     - interrupt-parent : the phandle for the interrupt controller that
-       services interrupts for this device.
-     - reg : The ID number for the phy, usually a small integer
-
-   Example Discovery PHY node:
-     ethernet-phy@1 {
-	     device_type = "ethernet-phy";
-	     compatible = "broadcom,bcm5421";
-	     interrupts = <76>;      /* GPP 12 */
-	     interrupt-parent = <&PIC>;
-	     reg = <1>;
-     };
-
-
-   d) Marvell Discovery SDMA nodes
-
-   Represent DMA hardware associated with the MPSC (multiprotocol
-   serial controllers).
-
-   Required properties:
-     - compatible : "marvell,mv64360-sdma"
-     - reg : Offset and length of the register set for this device
-     - interrupts : <a> where a is the interrupt number for the DMA
-       device.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery SDMA node:
-     sdma@4000 {
-	     compatible = "marvell,mv64360-sdma";
-	     reg = <0x4000 0xc18>;
-	     virtual-reg = <0xf1004000>;
-	     interrupts = <36>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   e) Marvell Discovery BRG nodes
-
-   Represent baud rate generator hardware associated with the MPSC
-   (multiprotocol serial controllers).
-
-   Required properties:
-     - compatible : "marvell,mv64360-brg"
-     - reg : Offset and length of the register set for this device
-     - clock-src : A value from 0 to 15 which selects the clock
-       source for the baud rate generator.  This value corresponds
-       to the CLKS value in the BRGx configuration register.  See
-       the mv64x60 User's Manual.
-     - clock-frequence : The frequency (in Hz) of the baud rate
-       generator's input clock.
-     - current-speed : The current speed setting (presumably by
-       firmware) of the baud rate generator.
-
-   Example Discovery BRG node:
-     brg@b200 {
-	     compatible = "marvell,mv64360-brg";
-	     reg = <0xb200 0x8>;
-	     clock-src = <8>;
-	     clock-frequency = <133333333>;
-	     current-speed = <9600>;
-     };
-
-
-   f) Marvell Discovery CUNIT nodes
-
-   Represent the Serial Communications Unit device hardware.
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery CUNIT node:
-     cunit@f200 {
-	     reg = <0xf200 0x200>;
-     };
-
-
-   g) Marvell Discovery MPSCROUTING nodes
-
-   Represent the Discovery's MPSC routing hardware
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery CUNIT node:
-     mpscrouting@b500 {
-	     reg = <0xb400 0xc>;
-     };
-
-
-   h) Marvell Discovery MPSCINTR nodes
-
-   Represent the Discovery's MPSC DMA interrupt hardware registers
-   (SDMA cause and mask registers).
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery MPSCINTR node:
-     mpsintr@b800 {
-	     reg = <0xb800 0x100>;
-     };
-
-
-   i) Marvell Discovery MPSC nodes
-
-   Represent the Discovery's MPSC (Multiprotocol Serial Controller)
-   serial port.
-
-   Required properties:
-     - device_type : "serial"
-     - compatible : "marvell,mv64360-mpsc"
-     - reg : Offset and length of the register set for this device
-     - sdma : the phandle for the SDMA node used by this port
-     - brg : the phandle for the BRG node used by this port
-     - cunit : the phandle for the CUNIT node used by this port
-     - mpscrouting : the phandle for the MPSCROUTING node used by this port
-     - mpscintr : the phandle for the MPSCINTR node used by this port
-     - cell-index : the hardware index of this cell in the MPSC core
-     - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
-       register
-     - interrupts : <a> where a is the interrupt number for the MPSC.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery MPSCINTR node:
-     mpsc@8000 {
-	     device_type = "serial";
-	     compatible = "marvell,mv64360-mpsc";
-	     reg = <0x8000 0x38>;
-	     virtual-reg = <0xf1008000>;
-	     sdma = <&SDMA0>;
-	     brg = <&BRG0>;
-	     cunit = <&CUNIT>;
-	     mpscrouting = <&MPSCROUTING>;
-	     mpscintr = <&MPSCINTR>;
-	     cell-index = <0>;
-	     max_idle = <40>;
-	     interrupts = <40>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   j) Marvell Discovery Watch Dog Timer nodes
-
-   Represent the Discovery's watchdog timer hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-wdt"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery Watch Dog Timer node:
-     wdt@b410 {
-	     compatible = "marvell,mv64360-wdt";
-	     reg = <0xb410 0x8>;
-     };
-
-
-   k) Marvell Discovery I2C nodes
-
-   Represent the Discovery's I2C hardware
-
-   Required properties:
-     - device_type : "i2c"
-     - compatible : "marvell,mv64360-i2c"
-     - reg : Offset and length of the register set for this device
-     - interrupts : <a> where a is the interrupt number for the I2C.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery I2C node:
-	     compatible = "marvell,mv64360-i2c";
-	     reg = <0xc000 0x20>;
-	     virtual-reg = <0xf100c000>;
-	     interrupts = <37>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
-
-   Represent the Discovery's PIC hardware
-
-   Required properties:
-     - #interrupt-cells : <1>
-     - #address-cells : <0>
-     - compatible : "marvell,mv64360-pic"
-     - reg : Offset and length of the register set for this device
-     - interrupt-controller
-
-   Example Discovery PIC node:
-     pic {
-	     #interrupt-cells = <1>;
-	     #address-cells = <0>;
-	     compatible = "marvell,mv64360-pic";
-	     reg = <0x0 0x88>;
-	     interrupt-controller;
-     };
-
-
-   m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
-
-   Represent the Discovery's MPP hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-mpp"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery MPP node:
-     mpp@f000 {
-	     compatible = "marvell,mv64360-mpp";
-	     reg = <0xf000 0x10>;
-     };
-
-
-   n) Marvell Discovery GPP (General Purpose Pins) nodes
-
-   Represent the Discovery's GPP hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-gpp"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery GPP node:
-     gpp@f000 {
-	     compatible = "marvell,mv64360-gpp";
-	     reg = <0xf100 0x20>;
-     };
-
-
-   o) Marvell Discovery PCI host bridge node
-
-   Represents the Discovery's PCI host bridge device.  The properties
-   for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
-   1275-1994.  A typical value for the compatible property is
-   "marvell,mv64360-pci".
-
-   Example Discovery PCI host bridge node
-     pci@80000000 {
-	     #address-cells = <3>;
-	     #size-cells = <2>;
-	     #interrupt-cells = <1>;
-	     device_type = "pci";
-	     compatible = "marvell,mv64360-pci";
-	     reg = <0xcf8 0x8>;
-	     ranges = <0x01000000 0x0        0x0
-			     0x88000000 0x0 0x01000000
-		       0x02000000 0x0 0x80000000
-			     0x80000000 0x0 0x08000000>;
-	     bus-range = <0 255>;
-	     clock-frequency = <66000000>;
-	     interrupt-parent = <&PIC>;
-	     interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-	     interrupt-map = <
-		     /* IDSEL 0x0a */
-		     0x5000 0 0 1 &PIC 80
-		     0x5000 0 0 2 &PIC 81
-		     0x5000 0 0 3 &PIC 91
-		     0x5000 0 0 4 &PIC 93
-
-		     /* IDSEL 0x0b */
-		     0x5800 0 0 1 &PIC 91
-		     0x5800 0 0 2 &PIC 93
-		     0x5800 0 0 3 &PIC 80
-		     0x5800 0 0 4 &PIC 81
-
-		     /* IDSEL 0x0c */
-		     0x6000 0 0 1 &PIC 91
-		     0x6000 0 0 2 &PIC 93
-		     0x6000 0 0 3 &PIC 80
-		     0x6000 0 0 4 &PIC 81
-
-		     /* IDSEL 0x0d */
-		     0x6800 0 0 1 &PIC 93
-		     0x6800 0 0 2 &PIC 80
-		     0x6800 0 0 3 &PIC 81
-		     0x6800 0 0 4 &PIC 91
-	     >;
-     };
-
-
-   p) Marvell Discovery CPU Error nodes
-
-   Represent the Discovery's CPU error handler device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-cpu-error"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery CPU Error node:
-     cpu-error@0070 {
-	     compatible = "marvell,mv64360-cpu-error";
-	     reg = <0x70 0x10 0x128 0x28>;
-	     interrupts = <3>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   q) Marvell Discovery SRAM Controller nodes
-
-   Represent the Discovery's SRAM controller device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-sram-ctrl"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery SRAM Controller node:
-     sram-ctrl@0380 {
-	     compatible = "marvell,mv64360-sram-ctrl";
-	     reg = <0x380 0x80>;
-	     interrupts = <13>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   r) Marvell Discovery PCI Error Handler nodes
-
-   Represent the Discovery's PCI error handler device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-pci-error"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery PCI Error Handler node:
-     pci-error@1d40 {
-	     compatible = "marvell,mv64360-pci-error";
-	     reg = <0x1d40 0x40 0xc28 0x4>;
-	     interrupts = <12>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-   s) Marvell Discovery Memory Controller nodes
-
-   Represent the Discovery's memory controller device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-mem-ctrl"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery Memory Controller node:
-     mem-ctrl@1400 {
-	     compatible = "marvell,mv64360-mem-ctrl";
-	     reg = <0x1400 0x60>;
-	     interrupts = <17>;
-	     interrupt-parent = <&PIC>;
-     };
-
-
-VIII - Specifying interrupt information for devices
+VII - Specifying interrupt information for devices
 ===================================================
 
 The device tree represents the busses and devices of a hardware
@@ -2439,56 +1324,7 @@
 	2 =  high to low edge sensitive type enabled
 	3 =  low to high edge sensitive type enabled
 
-IX - Specifying GPIO information for devices
-============================================
-
-1) gpios property
------------------
-
-Nodes that makes use of GPIOs should define them using `gpios' property,
-format of which is: <&gpio-controller1-phandle gpio1-specifier
-		     &gpio-controller2-phandle gpio2-specifier
-		     0 /* holes are permitted, means no GPIO 3 */
-		     &gpio-controller4-phandle gpio4-specifier
-		     ...>;
-
-Note that gpio-specifier length is controller dependent.
-
-gpio-specifier may encode: bank, pin position inside the bank,
-whether pin is open-drain and whether pin is logically inverted.
-
-Example of the node using GPIOs:
-
-	node {
-		gpios = <&qe_pio_e 18 0>;
-	};
-
-In this example gpio-specifier is "18 0" and encodes GPIO pin number,
-and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
-
-2) gpio-controller nodes
-------------------------
-
-Every GPIO controller node must have #gpio-cells property defined,
-this information will be used to translate gpio-specifiers.
-
-Example of two SOC GPIO banks defined as gpio-controller nodes:
-
-	qe_pio_a: gpio-controller@1400 {
-		#gpio-cells = <2>;
-		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
-		reg = <0x1400 0x18>;
-		gpio-controller;
-	};
-
-	qe_pio_e: gpio-controller@1460 {
-		#gpio-cells = <2>;
-		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
-		reg = <0x1460 0x18>;
-		gpio-controller;
-	};
-
-X - Specifying Device Power Management Information (sleep property)
+VIII - Specifying Device Power Management Information (sleep property)
 ===================================================================
 
 Devices on SOCs often have mechanisms for placing devices into low-power
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/4xx/emac.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/4xx/emac.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/4xx/emac.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/4xx/emac.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,148 @@
+    4xx/Axon EMAC ethernet nodes
+
+    The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
+    the Axon bridge.  To operate this needs to interact with a ths
+    special McMAL DMA controller, and sometimes an RGMII or ZMII
+    interface.  In addition to the nodes and properties described
+    below, the node for the OPB bus on which the EMAC sits must have a
+    correct clock-frequency property.
+
+      i) The EMAC node itself
+
+    Required properties:
+    - device_type       : "network"
+
+    - compatible        : compatible list, contains 2 entries, first is
+			  "ibm,emac-CHIP" where CHIP is the host ASIC (440gx,
+			  405gp, Axon) and second is either "ibm,emac" or
+			  "ibm,emac4".  For Axon, thus, we have: "ibm,emac-axon",
+			  "ibm,emac4"
+    - interrupts        : <interrupt mapping for EMAC IRQ and WOL IRQ>
+    - interrupt-parent  : optional, if needed for interrupt mapping
+    - reg               : <registers mapping>
+    - local-mac-address : 6 bytes, MAC address
+    - mal-device        : phandle of the associated McMAL node
+    - mal-tx-channel    : 1 cell, index of the tx channel on McMAL associated
+			  with this EMAC
+    - mal-rx-channel    : 1 cell, index of the rx channel on McMAL associated
+			  with this EMAC
+    - cell-index        : 1 cell, hardware index of the EMAC cell on a given
+			  ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on
+			  each Axon chip)
+    - max-frame-size    : 1 cell, maximum frame size supported in bytes
+    - rx-fifo-size      : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec
+			  operations.
+			  For Axon, 2048
+    - tx-fifo-size      : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec
+			  operations.
+			  For Axon, 2048.
+    - fifo-entry-size   : 1 cell, size of a fifo entry (used to calculate
+			  thresholds).
+			  For Axon, 0x00000010
+    - mal-burst-size    : 1 cell, MAL burst size (used to calculate thresholds)
+			  in bytes.
+			  For Axon, 0x00000100 (I think ...)
+    - phy-mode          : string, mode of operations of the PHY interface.
+			  Supported values are: "mii", "rmii", "smii", "rgmii",
+			  "tbi", "gmii", rtbi", "sgmii".
+			  For Axon on CAB, it is "rgmii"
+    - mdio-device       : 1 cell, required iff using shared MDIO registers
+			  (440EP).  phandle of the EMAC to use to drive the
+			  MDIO lines for the PHY used by this EMAC.
+    - zmii-device       : 1 cell, required iff connected to a ZMII.  phandle of
+			  the ZMII device node
+    - zmii-channel      : 1 cell, required iff connected to a ZMII.  Which ZMII
+			  channel or 0xffffffff if ZMII is only used for MDIO.
+    - rgmii-device      : 1 cell, required iff connected to an RGMII. phandle
+			  of the RGMII device node.
+			  For Axon: phandle of plb5/plb4/opb/rgmii
+    - rgmii-channel     : 1 cell, required iff connected to an RGMII.  Which
+			  RGMII channel is used by this EMAC.
+			  Fox Axon: present, whatever value is appropriate for each
+			  EMAC, that is the content of the current (bogus) "phy-port"
+			  property.
+
+    Optional properties:
+    - phy-address       : 1 cell, optional, MDIO address of the PHY. If absent,
+			  a search is performed.
+    - phy-map           : 1 cell, optional, bitmap of addresses to probe the PHY
+			  for, used if phy-address is absent. bit 0x00000001 is
+			  MDIO address 0.
+			  For Axon it can be absent, though my current driver
+			  doesn't handle phy-address yet so for now, keep
+			  0x00ffffff in it.
+    - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
+			  operations (if absent the value is the same as
+			  rx-fifo-size).  For Axon, either absent or 2048.
+    - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec
+			  operations (if absent the value is the same as
+			  tx-fifo-size). For Axon, either absent or 2048.
+    - tah-device        : 1 cell, optional. If connected to a TAH engine for
+			  offload, phandle of the TAH device node.
+    - tah-channel       : 1 cell, optional. If appropriate, channel used on the
+			  TAH engine.
+
+    Example:
+
+	EMAC0: ethernet@40000800 {
+		device_type = "network";
+		compatible = "ibm,emac-440gp", "ibm,emac";
+		interrupt-parent = <&UIC1>;
+		interrupts = <1c 4 1d 4>;
+		reg = <40000800 70>;
+		local-mac-address = [00 04 AC E3 1B 1E];
+		mal-device = <&MAL0>;
+		mal-tx-channel = <0 1>;
+		mal-rx-channel = <0>;
+		cell-index = <0>;
+		max-frame-size = <5dc>;
+		rx-fifo-size = <1000>;
+		tx-fifo-size = <800>;
+		phy-mode = "rmii";
+		phy-map = <00000001>;
+		zmii-device = <&ZMII0>;
+		zmii-channel = <0>;
+	};
+
+      ii) McMAL node
+
+    Required properties:
+    - device_type        : "dma-controller"
+    - compatible         : compatible list, containing 2 entries, first is
+			   "ibm,mcmal-CHIP" where CHIP is the host ASIC (like
+			   emac) and the second is either "ibm,mcmal" or
+			   "ibm,mcmal2".
+			   For Axon, "ibm,mcmal-axon","ibm,mcmal2"
+    - interrupts         : <interrupt mapping for the MAL interrupts sources:
+                           5 sources: tx_eob, rx_eob, serr, txde, rxde>.
+                           For Axon: This is _different_ from the current
+			   firmware.  We use the "delayed" interrupts for txeob
+			   and rxeob. Thus we end up with mapping those 5 MPIC
+			   interrupts, all level positive sensitive: 10, 11, 32,
+			   33, 34 (in decimal)
+    - dcr-reg            : < DCR registers range >
+    - dcr-parent         : if needed for dcr-reg
+    - num-tx-chans       : 1 cell, number of Tx channels
+    - num-rx-chans       : 1 cell, number of Rx channels
+
+      iii) ZMII node
+
+    Required properties:
+    - compatible         : compatible list, containing 2 entries, first is
+			   "ibm,zmii-CHIP" where CHIP is the host ASIC (like
+			   EMAC) and the second is "ibm,zmii".
+			   For Axon, there is no ZMII node.
+    - reg                : <registers mapping>
+
+      iv) RGMII node
+
+    Required properties:
+    - compatible         : compatible list, containing 2 entries, first is
+			   "ibm,rgmii-CHIP" where CHIP is the host ASIC (like
+			   EMAC) and the second is "ibm,rgmii".
+                           For Axon, "ibm,rgmii-axon","ibm,rgmii"
+    - reg                : <registers mapping>
+    - revision           : as provided by the RGMII new version register if
+			   available.
+			   For Axon: 0x0000012a
+
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/can/sja1000.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/can/sja1000.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/can/sja1000.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/can/sja1000.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,53 @@
+Memory mapped SJA1000 CAN controller from NXP (formerly Philips)
+
+Required properties:
+
+- compatible : should be "nxp,sja1000".
+
+- reg : should specify the chip select, address offset and size required
+	to map the registers of the SJA1000. The size is usually 0x80.
+
+- interrupts: property with a value describing the interrupt source
+	(number and sensitivity) required for the SJA1000.
+
+Optional properties:
+
+- nxp,external-clock-frequency : Frequency of the external oscillator
+	clock in Hz. Note that the internal clock frequency used by the
+	SJA1000 is half of that value. If not specified, a default value
+	of 16000000 (16 MHz) is used.
+
+- nxp,tx-output-mode : operation mode of the TX output control logic:
+	<0x0> : bi-phase output mode
+	<0x1> : normal output mode (default)
+	<0x2> : test output mode
+	<0x3> : clock output mode
+
+- nxp,tx-output-config : TX output pin configuration:
+	<0x01> : TX0 invert
+	<0x02> : TX0 pull-down (default)
+	<0x04> : TX0 pull-up
+	<0x06> : TX0 push-pull
+	<0x08> : TX1 invert
+	<0x10> : TX1 pull-down
+	<0x20> : TX1 pull-up
+	<0x30> : TX1 push-pull
+
+- nxp,clock-out-frequency : clock frequency in Hz on the CLKOUT pin.
+	If not specified or if the specified value is 0, the CLKOUT pin
+	will be disabled.
+
+- nxp,no-comparator-bypass : Allows to disable the CAN input comperator.
+
+For futher information, please have a look to the SJA1000 data sheet.
+
+Examples:
+
+can@3,100 {
+	compatible = "nxp,sja1000";
+	reg = <3 0x100 0x80>;
+	interrupts = <2 0>;
+	interrupt-parent = <&mpic>;
+	nxp,external-clock-frequency = <16000000>;
+};
+
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/ecm.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/ecm.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/ecm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/ecm.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,64 @@
+=====================================================================
+E500 LAW & Coherency Module Device Tree Binding
+Copyright (C) 2009 Freescale Semiconductor Inc.
+=====================================================================
+
+Local Access Window (LAW) Node
+
+The LAW node represents the region of CCSR space where local access
+windows are configured.  For ECM based devices this is the first 4k
+of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
+number of local access windows as specified by fsl,num-laws.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,ecm-law"
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+  - fsl,num-laws
+      Usage: required
+      Value type: <u32>
+      Definition: The value specifies the number of local access
+          windows for this device.
+
+=====================================================================
+
+E500 Coherency Module Node
+
+The E500 LAW node represents the region of CCSR space where ECM config
+and error reporting registers exist, this is the second 4k (0x1000)
+of CCSR space.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,CHIP-ecm", "fsl,ecm" where
+      CHIP is the processor (mpc8572, mpc8544, etc.)
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+   - interrupts
+      Usage: required
+      Value type: <prop-encoded-array>
+
+   - interrupt-parent
+      Usage: required
+      Value type: <phandle>
+
+=====================================================================
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/board.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/board.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/board.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/board.txt	2009-09-09 18:13:59.000000000 -0400
@@ -38,7 +38,7 @@
 - reg : Should contain the address and the length of the GPIO bank
   register.
 - #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional paramters (currently unused).
+  second cell is used to specify optional parameters (currently unused).
 - gpio-controller : Marks the port as GPIO controller.
 
 Example:
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/cpm.txt	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,7 @@
 	reg = <119c0 30>;
      }
 
-* Properties common to mulitple CPM/QE devices
+* Properties common to multiple CPM/QE devices
 
 - fsl,cpm-command : This value is ORed with the opcode and command flag
                     to specify the device on which a CPM command operates.
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,7 @@
   "fsl,cpm1-pario-bank-c", "fsl,cpm1-pario-bank-d",
   "fsl,cpm1-pario-bank-e", "fsl,cpm2-pario-bank"
 - #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional paramters (currently unused).
+  second cell is used to specify optional parameters (currently unused).
 - gpio-controller : Marks the port as GPIO controller.
 
 Example of three SOC GPIO banks defined as gpio-controller nodes:
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe.txt	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,9 @@
 - model : precise model of the QE, Can be "QE", "CPM", or "CPM2"
 - reg : offset and length of the device registers.
 - bus-frequency : the clock frequency for QUICC Engine.
+- fsl,qe-num-riscs: define how many RISC engines the QE has.
+- fsl,qe-num-snums: define how many serial number(SNUM) the QE can use for the
+  threads.
 
 Recommended properties
 - brg-frequency : the internal clock source frequency for baud-rate
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/esdhc.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/esdhc.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/esdhc.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/esdhc.txt	2009-09-09 18:13:59.000000000 -0400
@@ -5,17 +5,18 @@
 
 Required properties:
   - compatible : should be
-    "fsl,<chip>-esdhc", "fsl,mpc8379-esdhc" for MPC83xx processors.
-    "fsl,<chip>-esdhc", "fsl,mpc8536-esdhc" for MPC85xx processors.
+    "fsl,<chip>-esdhc", "fsl,esdhc"
   - reg : should contain eSDHC registers location and length.
   - interrupts : should contain eSDHC interrupt.
   - interrupt-parent : interrupt source phandle.
   - clock-frequency : specifies eSDHC base clock frequency.
+  - sdhci,1-bit-only : (optional) specifies that a controller can
+    only handle 1-bit data transfers.
 
 Example:
 
 sdhci@2e000 {
-	compatible = "fsl,mpc8378-esdhc", "fsl,mpc8379-esdhc";
+	compatible = "fsl,mpc8378-esdhc", "fsl,esdhc";
 	reg = <0x2e000 0x1000>;
 	interrupts = <42 0x8>;
 	interrupt-parent = <&ipic>;
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/mcm.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/mcm.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/mcm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/mcm.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,64 @@
+=====================================================================
+MPX LAW & Coherency Module Device Tree Binding
+Copyright (C) 2009 Freescale Semiconductor Inc.
+=====================================================================
+
+Local Access Window (LAW) Node
+
+The LAW node represents the region of CCSR space where local access
+windows are configured.  For MCM based devices this is the first 4k
+of CCSR space that includes CCSRBAR, ALTCBAR, ALTCAR, BPTR, and some
+number of local access windows as specified by fsl,num-laws.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,mcm-law"
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+  - fsl,num-laws
+      Usage: required
+      Value type: <u32>
+      Definition: The value specifies the number of local access
+          windows for this device.
+
+=====================================================================
+
+MPX Coherency Module Node
+
+The MPX LAW node represents the region of CCSR space where MCM config
+and error reporting registers exist, this is the second 4k (0x1000)
+of CCSR space.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,CHIP-mcm", "fsl,mcm" where
+      CHIP is the processor (mpc8641, mpc8610, etc.)
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  The value specifies the
+          physical address offset and length of the CCSR space
+          registers.
+
+   - interrupts
+      Usage: required
+      Value type: <prop-encoded-array>
+
+   - interrupt-parent
+      Usage: required
+      Value type: <phandle>
+
+=====================================================================
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/msi-pic.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 * Freescale MSI interrupt controller
 
-Reguired properities:
+Required properties:
 - compatible : compatible list, contains 2 entries,
   first is "fsl,CHIP-msi", where CHIP is the processor(mpc8610, mpc8572,
   etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/pmc.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/pmc.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/fsl/pmc.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/fsl/pmc.txt	2009-09-09 18:13:59.000000000 -0400
@@ -15,8 +15,8 @@
   compatible; all statements below that apply to "fsl,mpc8548-pmc" also
   apply to "fsl,mpc8641d-pmc".
 
-  Compatibility does not include bit assigments in SCCR/PMCDR/DEVDISR; these
-  bit assigments are indicated via the sleep specifier in each device's
+  Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
+  bit assignments are indicated via the sleep specifier in each device's
   sleep property.
 
 - reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/gpio/gpio.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/gpio/gpio.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/gpio/gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/gpio/gpio.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,50 @@
+Specifying GPIO information for devices
+============================================
+
+1) gpios property
+-----------------
+
+Nodes that makes use of GPIOs should define them using `gpios' property,
+format of which is: <&gpio-controller1-phandle gpio1-specifier
+		     &gpio-controller2-phandle gpio2-specifier
+		     0 /* holes are permitted, means no GPIO 3 */
+		     &gpio-controller4-phandle gpio4-specifier
+		     ...>;
+
+Note that gpio-specifier length is controller dependent.
+
+gpio-specifier may encode: bank, pin position inside the bank,
+whether pin is open-drain and whether pin is logically inverted.
+
+Example of the node using GPIOs:
+
+	node {
+		gpios = <&qe_pio_e 18 0>;
+	};
+
+In this example gpio-specifier is "18 0" and encodes GPIO pin number,
+and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
+
+2) gpio-controller nodes
+------------------------
+
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+Example of two SOC GPIO banks defined as gpio-controller nodes:
+
+	qe_pio_a: gpio-controller@1400 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
+		reg = <0x1400 0x18>;
+		gpio-controller;
+	};
+
+	qe_pio_e: gpio-controller@1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+	};
+
+
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/gpio/led.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/gpio/led.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/gpio/led.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/gpio/led.txt	2009-09-09 18:13:59.000000000 -0400
@@ -16,10 +16,17 @@
   string defining the trigger assigned to the LED.  Current triggers are:
     "backlight" - LED will act as a back-light, controlled by the framebuffer
 		  system
-    "default-on" - LED will turn on
+    "default-on" - LED will turn on, but see "default-state" below
     "heartbeat" - LED "double" flashes at a load average based rate
     "ide-disk" - LED indicates disk activity
     "timer" - LED flashes at a fixed, configurable rate
+- default-state:  (optional) The initial state of the LED.  Valid
+  values are "on", "off", and "keep".  If the LED is already on or off
+  and the default-state property is set the to same value, then no
+  glitch should be produced where the LED momentarily turns off (or
+  on).  The "keep" setting will keep the LED at whatever its current
+  state is, without producing a glitch.  The default is off if this
+  property is not present.
 
 Examples:
 
@@ -30,14 +37,22 @@
 		gpios = <&mcu_pio 0 1>; /* Active low */
 		linux,default-trigger = "ide-disk";
 	};
+
+	fault {
+		gpios = <&mcu_pio 1 0>;
+		/* Keep LED on if BIOS detected hardware fault */
+		default-state = "keep";
+	};
 };
 
 run-control {
 	compatible = "gpio-leds";
 	red {
 		gpios = <&mpc8572 6 0>;
+		default-state = "off";
 	};
 	green {
 		gpios = <&mpc8572 7 0>;
+		default-state = "on";
 	};
 }
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/gpio/mdio.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/gpio/mdio.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/gpio/mdio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/gpio/mdio.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,19 @@
+MDIO on GPIOs
+
+Currently defined compatibles:
+- virtual,gpio-mdio
+
+MDC and MDIO lines connected to GPIO controllers are listed in the
+gpios property as described in section VIII.1 in the following order:
+
+MDC, MDIO.
+
+Example:
+
+mdio {
+	compatible = "virtual,mdio-gpio";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpios = <&qe_pio_a 11
+		 &qe_pio_c 6>;
+};
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/marvell.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/marvell.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/marvell.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/marvell.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,521 @@
+Marvell Discovery mv64[345]6x System Controller chips
+===========================================================
+
+The Marvell mv64[345]60 series of system controller chips contain
+many of the peripherals needed to implement a complete computer
+system.  In this section, we define device tree nodes to describe
+the system controller chip itself and each of the peripherals
+which it contains.  Compatible string values for each node are
+prefixed with the string "marvell,", for Marvell Technology Group Ltd.
+
+1) The /system-controller node
+
+  This node is used to represent the system-controller and must be
+  present when the system uses a system controller chip. The top-level
+  system-controller node contains information that is global to all
+  devices within the system controller chip. The node name begins
+  with "system-controller" followed by the unit address, which is
+  the base address of the memory-mapped register set for the system
+  controller chip.
+
+  Required properties:
+
+    - ranges : Describes the translation of system controller addresses
+      for memory mapped registers.
+    - clock-frequency: Contains the main clock frequency for the system
+      controller chip.
+    - reg : This property defines the address and size of the
+      memory-mapped registers contained within the system controller
+      chip.  The address specified in the "reg" property should match
+      the unit address of the system-controller node.
+    - #address-cells : Address representation for system controller
+      devices.  This field represents the number of cells needed to
+      represent the address of the memory-mapped registers of devices
+      within the system controller chip.
+    - #size-cells : Size representation for for the memory-mapped
+      registers within the system controller chip.
+    - #interrupt-cells : Defines the width of cells used to represent
+      interrupts.
+
+  Optional properties:
+
+    - model : The specific model of the system controller chip.  Such
+      as, "mv64360", "mv64460", or "mv64560".
+    - compatible : A string identifying the compatibility identifiers
+      of the system controller chip.
+
+  The system-controller node contains child nodes for each system
+  controller device that the platform uses.  Nodes should not be created
+  for devices which exist on the system controller chip but are not used
+
+  Example Marvell Discovery mv64360 system-controller node:
+
+    system-controller@f1000000 { /* Marvell Discovery mv64360 */
+	    #address-cells = <1>;
+	    #size-cells = <1>;
+	    model = "mv64360";                      /* Default */
+	    compatible = "marvell,mv64360";
+	    clock-frequency = <133333333>;
+	    reg = <0xf1000000 0x10000>;
+	    virtual-reg = <0xf1000000>;
+	    ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
+		    0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
+		    0xa0000000 0xa0000000 0x4000000 /* User FLASH */
+		    0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
+		    0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+
+	    [ child node definitions... ]
+    }
+
+2) Child nodes of /system-controller
+
+   a) Marvell Discovery MDIO bus
+
+   The MDIO is a bus to which the PHY devices are connected.  For each
+   device that exists on this bus, a child node should be created.  See
+   the definition of the PHY node below for an example of how to define
+   a PHY.
+
+   Required properties:
+     - #address-cells : Should be <1>
+     - #size-cells : Should be <0>
+     - device_type : Should be "mdio"
+     - compatible : Should be "marvell,mv64360-mdio"
+
+   Example:
+
+     mdio {
+	     #address-cells = <1>;
+	     #size-cells = <0>;
+	     device_type = "mdio";
+	     compatible = "marvell,mv64360-mdio";
+
+	     ethernet-phy@0 {
+		     ......
+	     };
+     };
+
+
+   b) Marvell Discovery ethernet controller
+
+   The Discover ethernet controller is described with two levels
+   of nodes.  The first level describes an ethernet silicon block
+   and the second level describes up to 3 ethernet nodes within
+   that block.  The reason for the multiple levels is that the
+   registers for the node are interleaved within a single set
+   of registers.  The "ethernet-block" level describes the
+   shared register set, and the "ethernet" nodes describe ethernet
+   port-specific properties.
+
+   Ethernet block node
+
+   Required properties:
+     - #address-cells : <1>
+     - #size-cells : <0>
+     - compatible : "marvell,mv64360-eth-block"
+     - reg : Offset and length of the register set for this block
+
+   Example Discovery Ethernet block node:
+     ethernet-block@2000 {
+	     #address-cells = <1>;
+	     #size-cells = <0>;
+	     compatible = "marvell,mv64360-eth-block";
+	     reg = <0x2000 0x2000>;
+	     ethernet@0 {
+		     .......
+	     };
+     };
+
+   Ethernet port node
+
+   Required properties:
+     - device_type : Should be "network".
+     - compatible : Should be "marvell,mv64360-eth".
+     - reg : Should be <0>, <1>, or <2>, according to which registers
+       within the silicon block the device uses.
+     - interrupts : <a> where a is the interrupt number for the port.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+     - phy : the phandle for the PHY connected to this ethernet
+       controller.
+     - local-mac-address : 6 bytes, MAC address
+
+   Example Discovery Ethernet port node:
+     ethernet@0 {
+	     device_type = "network";
+	     compatible = "marvell,mv64360-eth";
+	     reg = <0>;
+	     interrupts = <32>;
+	     interrupt-parent = <&PIC>;
+	     phy = <&PHY0>;
+	     local-mac-address = [ 00 00 00 00 00 00 ];
+     };
+
+
+
+   c) Marvell Discovery PHY nodes
+
+   Required properties:
+     - device_type : Should be "ethernet-phy"
+     - interrupts : <a> where a is the interrupt number for this phy.
+     - interrupt-parent : the phandle for the interrupt controller that
+       services interrupts for this device.
+     - reg : The ID number for the phy, usually a small integer
+
+   Example Discovery PHY node:
+     ethernet-phy@1 {
+	     device_type = "ethernet-phy";
+	     compatible = "broadcom,bcm5421";
+	     interrupts = <76>;      /* GPP 12 */
+	     interrupt-parent = <&PIC>;
+	     reg = <1>;
+     };
+
+
+   d) Marvell Discovery SDMA nodes
+
+   Represent DMA hardware associated with the MPSC (multiprotocol
+   serial controllers).
+
+   Required properties:
+     - compatible : "marvell,mv64360-sdma"
+     - reg : Offset and length of the register set for this device
+     - interrupts : <a> where a is the interrupt number for the DMA
+       device.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery SDMA node:
+     sdma@4000 {
+	     compatible = "marvell,mv64360-sdma";
+	     reg = <0x4000 0xc18>;
+	     virtual-reg = <0xf1004000>;
+	     interrupts = <36>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   e) Marvell Discovery BRG nodes
+
+   Represent baud rate generator hardware associated with the MPSC
+   (multiprotocol serial controllers).
+
+   Required properties:
+     - compatible : "marvell,mv64360-brg"
+     - reg : Offset and length of the register set for this device
+     - clock-src : A value from 0 to 15 which selects the clock
+       source for the baud rate generator.  This value corresponds
+       to the CLKS value in the BRGx configuration register.  See
+       the mv64x60 User's Manual.
+     - clock-frequence : The frequency (in Hz) of the baud rate
+       generator's input clock.
+     - current-speed : The current speed setting (presumably by
+       firmware) of the baud rate generator.
+
+   Example Discovery BRG node:
+     brg@b200 {
+	     compatible = "marvell,mv64360-brg";
+	     reg = <0xb200 0x8>;
+	     clock-src = <8>;
+	     clock-frequency = <133333333>;
+	     current-speed = <9600>;
+     };
+
+
+   f) Marvell Discovery CUNIT nodes
+
+   Represent the Serial Communications Unit device hardware.
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery CUNIT node:
+     cunit@f200 {
+	     reg = <0xf200 0x200>;
+     };
+
+
+   g) Marvell Discovery MPSCROUTING nodes
+
+   Represent the Discovery's MPSC routing hardware
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery CUNIT node:
+     mpscrouting@b500 {
+	     reg = <0xb400 0xc>;
+     };
+
+
+   h) Marvell Discovery MPSCINTR nodes
+
+   Represent the Discovery's MPSC DMA interrupt hardware registers
+   (SDMA cause and mask registers).
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery MPSCINTR node:
+     mpsintr@b800 {
+	     reg = <0xb800 0x100>;
+     };
+
+
+   i) Marvell Discovery MPSC nodes
+
+   Represent the Discovery's MPSC (Multiprotocol Serial Controller)
+   serial port.
+
+   Required properties:
+     - device_type : "serial"
+     - compatible : "marvell,mv64360-mpsc"
+     - reg : Offset and length of the register set for this device
+     - sdma : the phandle for the SDMA node used by this port
+     - brg : the phandle for the BRG node used by this port
+     - cunit : the phandle for the CUNIT node used by this port
+     - mpscrouting : the phandle for the MPSCROUTING node used by this port
+     - mpscintr : the phandle for the MPSCINTR node used by this port
+     - cell-index : the hardware index of this cell in the MPSC core
+     - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
+       register
+     - interrupts : <a> where a is the interrupt number for the MPSC.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery MPSCINTR node:
+     mpsc@8000 {
+	     device_type = "serial";
+	     compatible = "marvell,mv64360-mpsc";
+	     reg = <0x8000 0x38>;
+	     virtual-reg = <0xf1008000>;
+	     sdma = <&SDMA0>;
+	     brg = <&BRG0>;
+	     cunit = <&CUNIT>;
+	     mpscrouting = <&MPSCROUTING>;
+	     mpscintr = <&MPSCINTR>;
+	     cell-index = <0>;
+	     max_idle = <40>;
+	     interrupts = <40>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   j) Marvell Discovery Watch Dog Timer nodes
+
+   Represent the Discovery's watchdog timer hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-wdt"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery Watch Dog Timer node:
+     wdt@b410 {
+	     compatible = "marvell,mv64360-wdt";
+	     reg = <0xb410 0x8>;
+     };
+
+
+   k) Marvell Discovery I2C nodes
+
+   Represent the Discovery's I2C hardware
+
+   Required properties:
+     - device_type : "i2c"
+     - compatible : "marvell,mv64360-i2c"
+     - reg : Offset and length of the register set for this device
+     - interrupts : <a> where a is the interrupt number for the I2C.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery I2C node:
+	     compatible = "marvell,mv64360-i2c";
+	     reg = <0xc000 0x20>;
+	     virtual-reg = <0xf100c000>;
+	     interrupts = <37>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
+
+   Represent the Discovery's PIC hardware
+
+   Required properties:
+     - #interrupt-cells : <1>
+     - #address-cells : <0>
+     - compatible : "marvell,mv64360-pic"
+     - reg : Offset and length of the register set for this device
+     - interrupt-controller
+
+   Example Discovery PIC node:
+     pic {
+	     #interrupt-cells = <1>;
+	     #address-cells = <0>;
+	     compatible = "marvell,mv64360-pic";
+	     reg = <0x0 0x88>;
+	     interrupt-controller;
+     };
+
+
+   m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
+
+   Represent the Discovery's MPP hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-mpp"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery MPP node:
+     mpp@f000 {
+	     compatible = "marvell,mv64360-mpp";
+	     reg = <0xf000 0x10>;
+     };
+
+
+   n) Marvell Discovery GPP (General Purpose Pins) nodes
+
+   Represent the Discovery's GPP hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-gpp"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery GPP node:
+     gpp@f000 {
+	     compatible = "marvell,mv64360-gpp";
+	     reg = <0xf100 0x20>;
+     };
+
+
+   o) Marvell Discovery PCI host bridge node
+
+   Represents the Discovery's PCI host bridge device.  The properties
+   for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
+   1275-1994.  A typical value for the compatible property is
+   "marvell,mv64360-pci".
+
+   Example Discovery PCI host bridge node
+     pci@80000000 {
+	     #address-cells = <3>;
+	     #size-cells = <2>;
+	     #interrupt-cells = <1>;
+	     device_type = "pci";
+	     compatible = "marvell,mv64360-pci";
+	     reg = <0xcf8 0x8>;
+	     ranges = <0x01000000 0x0        0x0
+			     0x88000000 0x0 0x01000000
+		       0x02000000 0x0 0x80000000
+			     0x80000000 0x0 0x08000000>;
+	     bus-range = <0 255>;
+	     clock-frequency = <66000000>;
+	     interrupt-parent = <&PIC>;
+	     interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+	     interrupt-map = <
+		     /* IDSEL 0x0a */
+		     0x5000 0 0 1 &PIC 80
+		     0x5000 0 0 2 &PIC 81
+		     0x5000 0 0 3 &PIC 91
+		     0x5000 0 0 4 &PIC 93
+
+		     /* IDSEL 0x0b */
+		     0x5800 0 0 1 &PIC 91
+		     0x5800 0 0 2 &PIC 93
+		     0x5800 0 0 3 &PIC 80
+		     0x5800 0 0 4 &PIC 81
+
+		     /* IDSEL 0x0c */
+		     0x6000 0 0 1 &PIC 91
+		     0x6000 0 0 2 &PIC 93
+		     0x6000 0 0 3 &PIC 80
+		     0x6000 0 0 4 &PIC 81
+
+		     /* IDSEL 0x0d */
+		     0x6800 0 0 1 &PIC 93
+		     0x6800 0 0 2 &PIC 80
+		     0x6800 0 0 3 &PIC 81
+		     0x6800 0 0 4 &PIC 91
+	     >;
+     };
+
+
+   p) Marvell Discovery CPU Error nodes
+
+   Represent the Discovery's CPU error handler device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-cpu-error"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery CPU Error node:
+     cpu-error@0070 {
+	     compatible = "marvell,mv64360-cpu-error";
+	     reg = <0x70 0x10 0x128 0x28>;
+	     interrupts = <3>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   q) Marvell Discovery SRAM Controller nodes
+
+   Represent the Discovery's SRAM controller device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-sram-ctrl"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery SRAM Controller node:
+     sram-ctrl@0380 {
+	     compatible = "marvell,mv64360-sram-ctrl";
+	     reg = <0x380 0x80>;
+	     interrupts = <13>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   r) Marvell Discovery PCI Error Handler nodes
+
+   Represent the Discovery's PCI error handler device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-pci-error"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery PCI Error Handler node:
+     pci-error@1d40 {
+	     compatible = "marvell,mv64360-pci-error";
+	     reg = <0x1d40 0x40 0xc28 0x4>;
+	     interrupts = <12>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
+   s) Marvell Discovery Memory Controller nodes
+
+   Represent the Discovery's memory controller device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-mem-ctrl"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery Memory Controller node:
+     mem-ctrl@1400 {
+	     compatible = "marvell,mv64360-mem-ctrl";
+	     reg = <0x1400 0x60>;
+	     interrupts = <17>;
+	     interrupt-parent = <&PIC>;
+     };
+
+
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/phy.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/phy.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/phy.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+PHY nodes
+
+Required properties:
+
+ - device_type : Should be "ethernet-phy"
+ - interrupts : <a b> where a is the interrupt number and b is a
+   field that represents an encoding of the sense and level
+   information for the interrupt.  This should be encoded based on
+   the information in section 2) depending on the type of interrupt
+   controller you have.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+ - reg : The ID number for the phy, usually a small integer
+ - linux,phandle :  phandle for this node; likely referenced by an
+   ethernet controller node.
+
+Example:
+
+ethernet-phy@0 {
+	linux,phandle = <2452000>
+	interrupt-parent = <40000>;
+	interrupts = <35 1>;
+	reg = <0>;
+	device_type = "ethernet-phy";
+};
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/spi-bus.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/spi-bus.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/spi-bus.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/spi-bus.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,57 @@
+SPI (Serial Peripheral Interface) busses
+
+SPI busses can be described with a node for the SPI master device
+and a set of child nodes for each SPI slave on the bus.  For this
+discussion, it is assumed that the system's SPI controller is in
+SPI master mode.  This binding does not describe SPI controllers
+in slave mode.
+
+The SPI master node requires the following properties:
+- #address-cells  - number of cells required to define a chip select
+    		address on the SPI bus.
+- #size-cells     - should be zero.
+- compatible      - name of SPI bus controller following generic names
+    		recommended practice.
+No other properties are required in the SPI bus node.  It is assumed
+that a driver for an SPI bus device will understand that it is an SPI bus.
+However, the binding does not attempt to define the specific method for
+assigning chip select numbers.  Since SPI chip select configuration is
+flexible and non-standardized, it is left out of this binding with the
+assumption that board specific platform code will be used to manage
+chip selects.  Individual drivers can define additional properties to
+support describing the chip select layout.
+
+SPI slave nodes must be children of the SPI master node and can
+contain the following properties.
+- reg             - (required) chip select address of device.
+- compatible      - (required) name of SPI device following generic names
+    		recommended practice
+- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
+- spi-cpol        - (optional) Empty property indicating device requires
+    		inverse clock polarity (CPOL) mode
+- spi-cpha        - (optional) Empty property indicating device requires
+    		shifted clock phase (CPHA) mode
+- spi-cs-high     - (optional) Empty property indicating device requires
+    		chip select active high
+
+SPI example for an MPC5200 SPI bus:
+	spi@f00 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+		reg = <0xf00 0x20>;
+		interrupts = <2 13 0 2 14 0>;
+		interrupt-parent = <&mpc5200_pic>;
+
+		ethernet-switch@0 {
+			compatible = "micrel,ks8995m";
+			spi-max-frequency = <1000000>;
+			reg = <0>;
+		};
+
+		codec@1 {
+			compatible = "ti,tlv320aic26";
+			spi-max-frequency = <100000>;
+			reg = <1>;
+		};
+	};
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/usb-ehci.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/usb-ehci.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/usb-ehci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/usb-ehci.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+USB EHCI controllers
+
+Required properties:
+  - compatible : should be "usb-ehci".
+  - reg : should contain at least address and length of the standard EHCI
+    register set for the device. Optional platform-dependent registers
+    (debug-port or other) can be also specified here, but only after
+    definition of standard EHCI registers.
+  - interrupts : one EHCI interrupt should be described here.
+If device registers are implemented in big endian mode, the device
+node should have "big-endian-regs" property.
+If controller implementation operates with big endian descriptors,
+"big-endian-desc" property should be specified.
+If both big endian registers and descriptors are used by the controller
+implementation, "big-endian" property can be specified instead of having
+both "big-endian-regs" and "big-endian-desc".
+
+Example (Sequoia 440EPx):
+    ehci@e0000300 {
+	   compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+	   interrupt-parent = <&UIC0>;
+	   interrupts = <1a 4>;
+	   reg = <0 e0000300 90 0 e0000390 70>;
+	   big-endian;
+   };
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/xilinx.txt linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/xilinx.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/dts-bindings/xilinx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/dts-bindings/xilinx.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,295 @@
+   d) Xilinx IP cores
+
+   The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
+   in Xilinx Spartan and Virtex FPGAs.  The devices cover the whole range
+   of standard device types (network, serial, etc.) and miscellaneous
+   devices (gpio, LCD, spi, etc).  Also, since these devices are
+   implemented within the fpga fabric every instance of the device can be
+   synthesised with different options that change the behaviour.
+
+   Each IP-core has a set of parameters which the FPGA designer can use to
+   control how the core is synthesized.  Historically, the EDK tool would
+   extract the device parameters relevant to device drivers and copy them
+   into an 'xparameters.h' in the form of #define symbols.  This tells the
+   device drivers how the IP cores are configured, but it requres the kernel
+   to be recompiled every time the FPGA bitstream is resynthesized.
+
+   The new approach is to export the parameters into the device tree and
+   generate a new device tree each time the FPGA bitstream changes.  The
+   parameters which used to be exported as #defines will now become
+   properties of the device node.  In general, device nodes for IP-cores
+   will take the following form:
+
+	(name): (generic-name)@(base-address) {
+		compatible = "xlnx,(ip-core-name)-(HW_VER)"
+			     [, (list of compatible devices), ...];
+		reg = <(baseaddr) (size)>;
+		interrupt-parent = <&interrupt-controller-phandle>;
+		interrupts = < ... >;
+		xlnx,(parameter1) = "(string-value)";
+		xlnx,(parameter2) = <(int-value)>;
+	};
+
+	(generic-name):   an open firmware-style name that describes the
+			generic class of device.  Preferably, this is one word, such
+			as 'serial' or 'ethernet'.
+	(ip-core-name):	the name of the ip block (given after the BEGIN
+			directive in system.mhs).  Should be in lowercase
+			and all underscores '_' converted to dashes '-'.
+	(name):		is derived from the "PARAMETER INSTANCE" value.
+	(parameter#):	C_* parameters from system.mhs.  The C_ prefix is
+			dropped from the parameter name, the name is converted
+			to lowercase and all underscore '_' characters are
+			converted to dashes '-'.
+	(baseaddr):	the baseaddr parameter value (often named C_BASEADDR).
+	(HW_VER):	from the HW_VER parameter.
+	(size):		the address range size (often C_HIGHADDR - C_BASEADDR + 1).
+
+   Typically, the compatible list will include the exact IP core version
+   followed by an older IP core version which implements the same
+   interface or any other device with the same interface.
+
+   'reg', 'interrupt-parent' and 'interrupts' are all optional properties.
+
+   For example, the following block from system.mhs:
+
+	BEGIN opb_uartlite
+		PARAMETER INSTANCE = opb_uartlite_0
+		PARAMETER HW_VER = 1.00.b
+		PARAMETER C_BAUDRATE = 115200
+		PARAMETER C_DATA_BITS = 8
+		PARAMETER C_ODD_PARITY = 0
+		PARAMETER C_USE_PARITY = 0
+		PARAMETER C_CLK_FREQ = 50000000
+		PARAMETER C_BASEADDR = 0xEC100000
+		PARAMETER C_HIGHADDR = 0xEC10FFFF
+		BUS_INTERFACE SOPB = opb_7
+		PORT OPB_Clk = CLK_50MHz
+		PORT Interrupt = opb_uartlite_0_Interrupt
+		PORT RX = opb_uartlite_0_RX
+		PORT TX = opb_uartlite_0_TX
+		PORT OPB_Rst = sys_bus_reset_0
+	END
+
+   becomes the following device tree node:
+
+	opb_uartlite_0: serial@ec100000 {
+		device_type = "serial";
+		compatible = "xlnx,opb-uartlite-1.00.b";
+		reg = <ec100000 10000>;
+		interrupt-parent = <&opb_intc_0>;
+		interrupts = <1 0>; // got this from the opb_intc parameters
+		current-speed = <d#115200>;	// standard serial device prop
+		clock-frequency = <d#50000000>;	// standard serial device prop
+		xlnx,data-bits = <8>;
+		xlnx,odd-parity = <0>;
+		xlnx,use-parity = <0>;
+	};
+
+   Some IP cores actually implement 2 or more logical devices.  In
+   this case, the device should still describe the whole IP core with
+   a single node and add a child node for each logical device.  The
+   ranges property can be used to translate from parent IP-core to the
+   registers of each device.  In addition, the parent node should be
+   compatible with the bus type 'xlnx,compound', and should contain
+   #address-cells and #size-cells, as with any other bus.  (Note: this
+   makes the assumption that both logical devices have the same bus
+   binding.  If this is not true, then separate nodes should be used
+   for each logical device).  The 'cell-index' property can be used to
+   enumerate logical devices within an IP core.  For example, the
+   following is the system.mhs entry for the dual ps2 controller found
+   on the ml403 reference design.
+
+	BEGIN opb_ps2_dual_ref
+		PARAMETER INSTANCE = opb_ps2_dual_ref_0
+		PARAMETER HW_VER = 1.00.a
+		PARAMETER C_BASEADDR = 0xA9000000
+		PARAMETER C_HIGHADDR = 0xA9001FFF
+		BUS_INTERFACE SOPB = opb_v20_0
+		PORT Sys_Intr1 = ps2_1_intr
+		PORT Sys_Intr2 = ps2_2_intr
+		PORT Clkin1 = ps2_clk_rx_1
+		PORT Clkin2 = ps2_clk_rx_2
+		PORT Clkpd1 = ps2_clk_tx_1
+		PORT Clkpd2 = ps2_clk_tx_2
+		PORT Rx1 = ps2_d_rx_1
+		PORT Rx2 = ps2_d_rx_2
+		PORT Txpd1 = ps2_d_tx_1
+		PORT Txpd2 = ps2_d_tx_2
+	END
+
+   It would result in the following device tree nodes:
+
+	opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "xlnx,compound";
+		ranges = <0 a9000000 2000>;
+		// If this device had extra parameters, then they would
+		// go here.
+		ps2@0 {
+			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+			reg = <0 40>;
+			interrupt-parent = <&opb_intc_0>;
+			interrupts = <3 0>;
+			cell-index = <0>;
+		};
+		ps2@1000 {
+			compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+			reg = <1000 40>;
+			interrupt-parent = <&opb_intc_0>;
+			interrupts = <3 0>;
+			cell-index = <0>;
+		};
+	};
+
+   Also, the system.mhs file defines bus attachments from the processor
+   to the devices.  The device tree structure should reflect the bus
+   attachments.  Again an example; this system.mhs fragment:
+
+	BEGIN ppc405_virtex4
+		PARAMETER INSTANCE = ppc405_0
+		PARAMETER HW_VER = 1.01.a
+		BUS_INTERFACE DPLB = plb_v34_0
+		BUS_INTERFACE IPLB = plb_v34_0
+	END
+
+	BEGIN opb_intc
+		PARAMETER INSTANCE = opb_intc_0
+		PARAMETER HW_VER = 1.00.c
+		PARAMETER C_BASEADDR = 0xD1000FC0
+		PARAMETER C_HIGHADDR = 0xD1000FDF
+		BUS_INTERFACE SOPB = opb_v20_0
+	END
+
+	BEGIN opb_uart16550
+		PARAMETER INSTANCE = opb_uart16550_0
+		PARAMETER HW_VER = 1.00.d
+		PARAMETER C_BASEADDR = 0xa0000000
+		PARAMETER C_HIGHADDR = 0xa0001FFF
+		BUS_INTERFACE SOPB = opb_v20_0
+	END
+
+	BEGIN plb_v34
+		PARAMETER INSTANCE = plb_v34_0
+		PARAMETER HW_VER = 1.02.a
+	END
+
+	BEGIN plb_bram_if_cntlr
+		PARAMETER INSTANCE = plb_bram_if_cntlr_0
+		PARAMETER HW_VER = 1.00.b
+		PARAMETER C_BASEADDR = 0xFFFF0000
+		PARAMETER C_HIGHADDR = 0xFFFFFFFF
+		BUS_INTERFACE SPLB = plb_v34_0
+	END
+
+	BEGIN plb2opb_bridge
+		PARAMETER INSTANCE = plb2opb_bridge_0
+		PARAMETER HW_VER = 1.01.a
+		PARAMETER C_RNG0_BASEADDR = 0x20000000
+		PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF
+		PARAMETER C_RNG1_BASEADDR = 0x60000000
+		PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF
+		PARAMETER C_RNG2_BASEADDR = 0x80000000
+		PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF
+		PARAMETER C_RNG3_BASEADDR = 0xC0000000
+		PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF
+		BUS_INTERFACE SPLB = plb_v34_0
+		BUS_INTERFACE MOPB = opb_v20_0
+	END
+
+   Gives this device tree (some properties removed for clarity):
+
+	plb@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "xlnx,plb-v34-1.02.a";
+		device_type = "ibm,plb";
+		ranges; // 1:1 translation
+
+		plb_bram_if_cntrl_0: bram@ffff0000 {
+			reg = <ffff0000 10000>;
+		}
+
+		opb@20000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <20000000 20000000 20000000
+				  60000000 60000000 20000000
+				  80000000 80000000 40000000
+				  c0000000 c0000000 20000000>;
+
+			opb_uart16550_0: serial@a0000000 {
+				reg = <a00000000 2000>;
+			};
+
+			opb_intc_0: interrupt-controller@d1000fc0 {
+				reg = <d1000fc0 20>;
+			};
+		};
+	};
+
+   That covers the general approach to binding xilinx IP cores into the
+   device tree.  The following are bindings for specific devices:
+
+      i) Xilinx ML300 Framebuffer
+
+      Simple framebuffer device from the ML300 reference design (also on the
+      ML403 reference design as well as others).
+
+      Optional properties:
+       - resolution = <xres yres> : pixel resolution of framebuffer.  Some
+                                    implementations use a different resolution.
+                                    Default is <d#640 d#480>
+       - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory.
+                                           Default is <d#1024 d#480>.
+       - rotate-display (empty) : rotate display 180 degrees.
+
+      ii) Xilinx SystemACE
+
+      The Xilinx SystemACE device is used to program FPGAs from an FPGA
+      bitstream stored on a CF card.  It can also be used as a generic CF
+      interface device.
+
+      Optional properties:
+       - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
+
+      iii) Xilinx EMAC and Xilinx TEMAC
+
+      Xilinx Ethernet devices.  In addition to general xilinx properties
+      listed above, nodes for these devices should include a phy-handle
+      property, and may include other common network device properties
+      like local-mac-address.
+
+      iv) Xilinx Uartlite
+
+      Xilinx uartlite devices are simple fixed speed serial ports.
+
+      Required properties:
+       - current-speed : Baud rate of uartlite
+
+      v) Xilinx hwicap
+
+		Xilinx hwicap devices provide access to the configuration logic
+		of the FPGA through the Internal Configuration Access Port
+		(ICAP).  The ICAP enables partial reconfiguration of the FPGA,
+		readback of the configuration information, and some control over
+		'warm boots' of the FPGA fabric.
+
+		Required properties:
+		- xlnx,family : The family of the FPGA, necessary since the
+                      capabilities of the underlying ICAP hardware
+                      differ between different families.  May be
+                      'virtex2p', 'virtex4', or 'virtex5'.
+
+      vi) Xilinx Uart 16550
+
+      Xilinx UART 16550 devices are very similar to the NS16550 but with
+      different register spacing and an offset from the base address.
+
+      Required properties:
+       - clock-frequency : Frequency of the clock input
+       - reg-offset : A value of 3 is required
+       - reg-shift : A value of 2 is required
+
+
diff -druN linux-libre-2.6.30-gnu/Documentation/powerpc/qe_firmware.txt linux-libre-2.6.31-gnu/Documentation/powerpc/qe_firmware.txt
--- linux-libre-2.6.30-gnu/Documentation/powerpc/qe_firmware.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/powerpc/qe_firmware.txt	2009-09-09 18:13:59.000000000 -0400
@@ -225,7 +225,7 @@
      soc.major = 1
      soc.minor = 0
 
-'padding' is neccessary for structure alignment.  This field ensures that the
+'padding' is necessary for structure alignment.  This field ensures that the
 'extended_modes' field is aligned on a 64-bit boundary.
 
 'extended_modes' is a bitfield that defines special functionality which has an
diff -druN linux-libre-2.6.30-gnu/Documentation/pps/pps.txt linux-libre-2.6.31-gnu/Documentation/pps/pps.txt
--- linux-libre-2.6.30-gnu/Documentation/pps/pps.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/pps/pps.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,172 @@
+
+			PPS - Pulse Per Second
+			----------------------
+
+(C) Copyright 2007 Rodolfo Giometti <giometti@enneenne.com>
+
+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.
+
+
+
+Overview
+--------
+
+LinuxPPS provides a programming interface (API) to define in the
+system several PPS sources.
+
+PPS means "pulse per second" and a PPS source is just a device which
+provides a high precision signal each second so that an application
+can use it to adjust system clock time.
+
+A PPS source can be connected to a serial port (usually to the Data
+Carrier Detect pin) or to a parallel port (ACK-pin) or to a special
+CPU's GPIOs (this is the common case in embedded systems) but in each
+case when a new pulse arrives the system must apply to it a timestamp
+and record it for userland.
+
+Common use is the combination of the NTPD as userland program, with a
+GPS receiver as PPS source, to obtain a wallclock-time with
+sub-millisecond synchronisation to UTC.
+
+
+RFC considerations
+------------------
+
+While implementing a PPS API as RFC 2783 defines and using an embedded
+CPU GPIO-Pin as physical link to the signal, I encountered a deeper
+problem:
+
+   At startup it needs a file descriptor as argument for the function
+   time_pps_create().
+
+This implies that the source has a /dev/... entry. This assumption is
+ok for the serial and parallel port, where you can do something
+useful besides(!) the gathering of timestamps as it is the central
+task for a PPS-API. But this assumption does not work for a single
+purpose GPIO line. In this case even basic file-related functionality
+(like read() and write()) makes no sense at all and should not be a
+precondition for the use of a PPS-API.
+
+The problem can be simply solved if you consider that a PPS source is
+not always connected with a GPS data source.
+
+So your programs should check if the GPS data source (the serial port
+for instance) is a PPS source too, and if not they should provide the
+possibility to open another device as PPS source.
+
+In LinuxPPS the PPS sources are simply char devices usually mapped
+into files /dev/pps0, /dev/pps1, etc..
+
+
+Coding example
+--------------
+
+To register a PPS source into the kernel you should define a struct
+pps_source_info_s as follows:
+
+    static struct pps_source_info pps_ktimer_info = {
+	    .name         = "ktimer",
+	    .path         = "",
+	    .mode         = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
+			    PPS_ECHOASSERT | \
+			    PPS_CANWAIT | PPS_TSFMT_TSPEC,
+	    .echo         = pps_ktimer_echo,
+	    .owner        = THIS_MODULE,
+    };
+
+and then calling the function pps_register_source() in your
+intialization routine as follows:
+
+    source = pps_register_source(&pps_ktimer_info,
+			PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
+
+The pps_register_source() prototype is:
+
+  int pps_register_source(struct pps_source_info_s *info, int default_params)
+
+where "info" is a pointer to a structure that describes a particular
+PPS source, "default_params" tells the system what the initial default
+parameters for the device should be (it is obvious that these parameters
+must be a subset of ones defined in the struct
+pps_source_info_s which describe the capabilities of the driver).
+
+Once you have registered a new PPS source into the system you can
+signal an assert event (for example in the interrupt handler routine)
+just using:
+
+    pps_event(source, &ts, PPS_CAPTUREASSERT, ptr)
+
+where "ts" is the event's timestamp.
+
+The same function may also run the defined echo function
+(pps_ktimer_echo(), passing to it the "ptr" pointer) if the user
+asked for that... etc..
+
+Please see the file drivers/pps/clients/ktimer.c for example code.
+
+
+SYSFS support
+-------------
+
+If the SYSFS filesystem is enabled in the kernel it provides a new class:
+
+   $ ls /sys/class/pps/
+   pps0/  pps1/  pps2/
+
+Every directory is the ID of a PPS sources defined in the system and
+inside you find several files:
+
+   $ ls /sys/class/pps/pps0/
+   assert	clear  echo  mode  name  path  subsystem@  uevent
+
+Inside each "assert" and "clear" file you can find the timestamp and a
+sequence number:
+
+   $ cat /sys/class/pps/pps0/assert
+   1170026870.983207967#8
+
+Where before the "#" is the timestamp in seconds; after it is the
+sequence number. Other files are:
+
+* echo: reports if the PPS source has an echo function or not;
+
+* mode: reports available PPS functioning modes;
+
+* name: reports the PPS source's name;
+
+* path: reports the PPS source's device path, that is the device the
+  PPS source is connected to (if it exists).
+
+
+Testing the PPS support
+-----------------------
+
+In order to test the PPS support even without specific hardware you can use
+the ktimer driver (see the client subsection in the PPS configuration menu)
+and the userland tools provided into Documentaion/pps/ directory.
+
+Once you have enabled the compilation of ktimer just modprobe it (if
+not statically compiled):
+
+   # modprobe ktimer
+
+and the run ppstest as follow:
+
+   $ ./ppstest /dev/pps0
+   trying PPS source "/dev/pps1"
+   found PPS source "/dev/pps1"
+   ok, found 1 source(s), now start fetching data...
+   source 0 - assert 1186592699.388832443, sequence: 364 - clear  0.000000000, sequence: 0
+   source 0 - assert 1186592700.388931295, sequence: 365 - clear  0.000000000, sequence: 0
+   source 0 - assert 1186592701.389032765, sequence: 366 - clear  0.000000000, sequence: 0
+
+Please, note that to compile userland programs you need the file timepps.h
+(see Documentation/pps/).
diff -druN linux-libre-2.6.30-gnu/Documentation/rbtree.txt linux-libre-2.6.31-gnu/Documentation/rbtree.txt
--- linux-libre-2.6.30-gnu/Documentation/rbtree.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/rbtree.txt	2009-09-09 18:13:59.000000000 -0400
@@ -131,8 +131,8 @@
   	}
 
   	/* Add new node and rebalance tree. */
-  	rb_link_node(data->node, parent, new);
-  	rb_insert_color(data->node, root);
+  	rb_link_node(&data->node, parent, new);
+  	rb_insert_color(&data->node, root);
 
 	return TRUE;
   }
@@ -146,10 +146,10 @@
 
 Example:
 
-  struct mytype *data = mysearch(mytree, "walrus");
+  struct mytype *data = mysearch(&mytree, "walrus");
 
   if (data) {
-  	rb_erase(data->node, mytree);
+  	rb_erase(&data->node, &mytree);
   	myfree(data);
   }
 
@@ -188,5 +188,5 @@
 
   struct rb_node *node;
   for (node = rb_first(&mytree); node; node = rb_next(node))
-  	printk("key=%s\n", rb_entry(node, int, keystring));
+	printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring);
 
diff -druN linux-libre-2.6.30-gnu/Documentation/RCU/rculist_nulls.txt linux-libre-2.6.31-gnu/Documentation/RCU/rculist_nulls.txt
--- linux-libre-2.6.30-gnu/Documentation/RCU/rculist_nulls.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/RCU/rculist_nulls.txt	2009-09-09 18:13:59.000000000 -0400
@@ -83,11 +83,12 @@
 obj = kmem_cache_alloc(...);
 lock_chain(); // typically a spin_lock()
 obj->key = key;
-atomic_inc(&obj->refcnt);
 /*
  * we need to make sure obj->key is updated before obj->next
+ * or obj->refcnt
  */
 smp_wmb();
+atomic_set(&obj->refcnt, 1);
 hlist_add_head_rcu(&obj->obj_node, list);
 unlock_chain(); // typically a spin_unlock()
 
@@ -118,7 +119,7 @@
 the lookup met the end of chain. If final 'nulls' value
 is not the slot number, then we must restart the lookup at
 the beginning. If the object was moved to the same chain,
-then the reader doesnt care : It might eventually
+then the reader doesn't care : It might eventually
 scan the list again without harm.
 
 
@@ -159,6 +160,10 @@
 obj = kmem_cache_alloc(cachep);
 lock_chain(); // typically a spin_lock()
 obj->key = key;
+/*
+ * changes to obj->key must be visible before refcnt one
+ */
+smp_wmb();
 atomic_set(&obj->refcnt, 1);
 /*
  * insert obj in RCU way (readers might be traversing chain)
diff -druN linux-libre-2.6.30-gnu/Documentation/RCU/trace.txt linux-libre-2.6.31-gnu/Documentation/RCU/trace.txt
--- linux-libre-2.6.30-gnu/Documentation/RCU/trace.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/RCU/trace.txt	2009-09-09 18:13:59.000000000 -0400
@@ -192,23 +192,24 @@
 The output of "cat rcu/rcudata" looks as follows:
 
 rcu:
-  0 c=4011 g=4012 pq=1 pqc=4011 qp=0 rpfq=1 rp=3c2a dt=23301/73 dn=2 df=1882 of=0 ri=2126 ql=2 b=10
-  1 c=4011 g=4012 pq=1 pqc=4011 qp=0 rpfq=3 rp=39a6 dt=78073/1 dn=2 df=1402 of=0 ri=1875 ql=46 b=10
-  2 c=4010 g=4010 pq=1 pqc=4010 qp=0 rpfq=-5 rp=1d12 dt=16646/0 dn=2 df=3140 of=0 ri=2080 ql=0 b=10
-  3 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=2b50 dt=21159/1 dn=2 df=2230 of=0 ri=1923 ql=72 b=10
-  4 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=1644 dt=5783/1 dn=2 df=3348 of=0 ri=2805 ql=7 b=10
-  5 c=4012 g=4013 pq=0 pqc=4011 qp=1 rpfq=3 rp=1aac dt=5879/1 dn=2 df=3140 of=0 ri=2066 ql=10 b=10
-  6 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=ed8 dt=5847/1 dn=2 df=3797 of=0 ri=1266 ql=10 b=10
-  7 c=4012 g=4013 pq=1 pqc=4012 qp=1 rpfq=3 rp=1fa2 dt=6199/1 dn=2 df=2795 of=0 ri=2162 ql=28 b=10
+rcu:
+  0 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=10951/1 dn=0 df=1101 of=0 ri=36 ql=0 b=10
+  1 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=16117/1 dn=0 df=1015 of=0 ri=0 ql=0 b=10
+  2 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1445/1 dn=0 df=1839 of=0 ri=0 ql=0 b=10
+  3 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=6681/1 dn=0 df=1545 of=0 ri=0 ql=0 b=10
+  4 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1003/1 dn=0 df=1992 of=0 ri=0 ql=0 b=10
+  5 c=17829 g=17830 pq=1 pqc=17829 qp=1 dt=3887/1 dn=0 df=3331 of=0 ri=4 ql=2 b=10
+  6 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=859/1 dn=0 df=3224 of=0 ri=0 ql=0 b=10
+  7 c=17829 g=17830 pq=0 pqc=17829 qp=1 dt=3761/1 dn=0 df=1818 of=0 ri=0 ql=2 b=10
 rcu_bh:
-  0 c=-268 g=-268 pq=1 pqc=-268 qp=0 rpfq=-145 rp=21d6 dt=23301/73 dn=2 df=0 of=0 ri=0 ql=0 b=10
-  1 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-170 rp=20ce dt=78073/1 dn=2 df=26 of=0 ri=5 ql=0 b=10
-  2 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-83 rp=fbd dt=16646/0 dn=2 df=28 of=0 ri=4 ql=0 b=10
-  3 c=-268 g=-268 pq=1 pqc=-268 qp=0 rpfq=-105 rp=178c dt=21159/1 dn=2 df=28 of=0 ri=2 ql=0 b=10
-  4 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-30 rp=b54 dt=5783/1 dn=2 df=32 of=0 ri=0 ql=0 b=10
-  5 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-29 rp=df5 dt=5879/1 dn=2 df=30 of=0 ri=3 ql=0 b=10
-  6 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-28 rp=788 dt=5847/1 dn=2 df=32 of=0 ri=0 ql=0 b=10
-  7 c=-268 g=-268 pq=1 pqc=-268 qp=1 rpfq=-53 rp=1098 dt=6199/1 dn=2 df=30 of=0 ri=3 ql=0 b=10
+  0 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=10951/1 dn=0 df=0 of=0 ri=0 ql=0 b=10
+  1 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=16117/1 dn=0 df=13 of=0 ri=0 ql=0 b=10
+  2 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1445/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+  3 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=6681/1 dn=0 df=9 of=0 ri=0 ql=0 b=10
+  4 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1003/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+  5 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3887/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+  6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
+  7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1 dn=0 df=15 of=0 ri=0 ql=0 b=10
 
 The first section lists the rcu_data structures for rcu, the second for
 rcu_bh.  Each section has one line per CPU, or eight for this 8-CPU system.
@@ -253,12 +254,6 @@
 o	"qp" indicates that RCU still expects a quiescent state from
 	this CPU.
 
-o	"rpfq" is the number of rcu_pending() calls on this CPU required
-	to induce this CPU to invoke force_quiescent_state().
-
-o	"rp" is low-order four hex digits of the count of how many times
-	rcu_pending() has been invoked on this CPU.
-
 o	"dt" is the current value of the dyntick counter that is incremented
 	when entering or leaving dynticks idle state, either by the
 	scheduler or by irq.  The number after the "/" is the interrupt
@@ -305,6 +300,9 @@
 	of RCU callbacks is ready to invoke, then the remainder will
 	be deferred.
 
+There is also an rcu/rcudata.csv file with the same information in
+comma-separated-variable spreadsheet format.
+
 
 The output of "cat rcu/rcugp" looks as follows:
 
@@ -411,3 +409,63 @@
 		For example, the first entry at the lowest level shows
 		"^0", indicating that it corresponds to bit zero in
 		the first entry at the middle level.
+
+
+The output of "cat rcu/rcu_pending" looks as follows:
+
+rcu:
+  0 np=255892 qsp=53936 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741
+  1 np=261224 qsp=54638 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792
+  2 np=237496 qsp=49664 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629
+  3 np=236249 qsp=48766 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723
+  4 np=221310 qsp=46850 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110
+  5 np=237332 qsp=48449 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456
+  6 np=219995 qsp=46718 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834
+  7 np=249893 qsp=49390 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888
+rcu_bh:
+  0 np=146741 qsp=1419 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314
+  1 np=155792 qsp=12597 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180
+  2 np=136629 qsp=18680 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936
+  3 np=137723 qsp=2843 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863
+  4 np=123110 qsp=12433 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671
+  5 np=137456 qsp=4210 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235
+  6 np=120834 qsp=9902 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
+  7 np=144888 qsp=26336 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
+
+As always, this is once again split into "rcu" and "rcu_bh" portions.
+The fields are as follows:
+
+o	"np" is the number of times that __rcu_pending() has been invoked
+	for the corresponding flavor of RCU.
+
+o	"qsp" is the number of times that the RCU was waiting for a
+	quiescent state from this CPU.
+
+o	"cbr" is the number of times that this CPU had RCU callbacks
+	that had passed through a grace period, and were thus ready
+	to be invoked.
+
+o	"cng" is the number of times that this CPU needed another
+	grace period while RCU was idle.
+
+o	"gpc" is the number of times that an old grace period had
+	completed, but this CPU was not yet aware of it.
+
+o	"gps" is the number of times that a new grace period had started,
+	but this CPU was not yet aware of it.
+
+o	"nf" is the number of times that this CPU suspected that the
+	current grace period had run for too long, and thus needed to
+	be forced.
+
+	Please note that "forcing" consists of sending resched IPIs
+	to holdout CPUs.  If that CPU really still is in an old RCU
+	read-side critical section, then we really do have to wait for it.
+	The assumption behing "forcing" is that the CPU is not still in
+	an old RCU read-side critical section, but has not yet responded
+	for some other reason.
+
+o	"nn" is the number of times that this CPU needed nothing.  Alert
+	readers will note that the rcu "nn" number for a given CPU very
+	closely matches the rcu_bh "np" number for that same CPU.  This
+	is due to short-circuit evaluation in rcu_pending().
diff -druN linux-libre-2.6.30-gnu/Documentation/rfkill.txt linux-libre-2.6.31-gnu/Documentation/rfkill.txt
--- linux-libre-2.6.30-gnu/Documentation/rfkill.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/rfkill.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1,575 +1,139 @@
-rfkill - RF switch subsystem support
-====================================
-
-1 Introduction
-2 Implementation details
-3 Kernel driver guidelines
-3.1 wireless device drivers
-3.2 platform/switch drivers
-3.3 input device drivers
-4 Kernel API
-5 Userspace support
-
-
-1. Introduction:
-
-The rfkill switch subsystem exists to add a generic interface to circuitry that
-can enable or disable the signal output of a wireless *transmitter* of any
-type.  By far, the most common use is to disable radio-frequency transmitters.
-
-Note that disabling the signal output means that the the transmitter is to be
-made to not emit any energy when "blocked".  rfkill is not about blocking data
-transmissions, it is about blocking energy emission.
-
-The rfkill subsystem offers support for keys and switches often found on
-laptops to enable wireless devices like WiFi and Bluetooth, so that these keys
-and switches actually perform an action in all wireless devices of a given type
-attached to the system.
-
-The buttons to enable and disable the wireless transmitters are important in
-situations where the user is for example using his laptop on a location where
-radio-frequency transmitters _must_ be disabled (e.g. airplanes).
-
-Because of this requirement, userspace support for the keys should not be made
-mandatory.  Because userspace might want to perform some additional smarter
-tasks when the key is pressed, rfkill provides userspace the possibility to
-take over the task to handle the key events.
-
-===============================================================================
-2: Implementation details
-
-The rfkill subsystem is composed of various components: the rfkill class, the
-rfkill-input module (an input layer handler), and some specific input layer
-events.
-
-The rfkill class provides kernel drivers with an interface that allows them to
-know when they should enable or disable a wireless network device transmitter.
-This is enabled by the CONFIG_RFKILL Kconfig option.
-
-The rfkill class support makes sure userspace will be notified of all state
-changes on rfkill devices through uevents.  It provides a notification chain
-for interested parties in the kernel to also get notified of rfkill state
-changes in other drivers.  It creates several sysfs entries which can be used
-by userspace.  See section "Userspace support".
-
-The rfkill-input module provides the kernel with the ability to implement a
-basic response when the user presses a key or button (or toggles a switch)
-related to rfkill functionality.  It is an in-kernel implementation of default
-policy of reacting to rfkill-related input events and neither mandatory nor
-required for wireless drivers to operate.  It is enabled by the
-CONFIG_RFKILL_INPUT Kconfig option.
-
-rfkill-input is a rfkill-related events input layer handler.  This handler will
-listen to all rfkill key events and will change the rfkill state of the
-wireless devices accordingly.  With this option enabled userspace could either
-do nothing or simply perform monitoring tasks.
-
-The rfkill-input module also provides EPO (emergency power-off) functionality
-for all wireless transmitters.  This function cannot be overridden, and it is
-always active.  rfkill EPO is related to *_RFKILL_ALL input layer events.
-
-
-Important terms for the rfkill subsystem:
-
-In order to avoid confusion, we avoid the term "switch" in rfkill when it is
-referring to an electronic control circuit that enables or disables a
-transmitter.  We reserve it for the physical device a human manipulates
-(which is an input device, by the way):
-
-rfkill switch:
-
-	A physical device a human manipulates.  Its state can be perceived by
-	the kernel either directly (through a GPIO pin, ACPI GPE) or by its
-	effect on a rfkill line of a wireless device.
-
-rfkill controller:
-
-	A hardware circuit that controls the state of a rfkill line, which a
-	kernel driver can interact with *to modify* that state (i.e. it has
-	either write-only or read/write access).
-
-rfkill line:
-
-	An input channel (hardware or software) of a wireless device, which
-	causes a wireless transmitter to stop emitting energy (BLOCK) when it
-	is active.  Point of view is extremely important here: rfkill lines are
-	always seen from the PoV of a wireless device (and its driver).
-
-soft rfkill line/software rfkill line:
-
-	A rfkill line the wireless device driver can directly change the state
-	of.  Related to rfkill_state RFKILL_STATE_SOFT_BLOCKED.
-
-hard rfkill line/hardware rfkill line:
-
-	A rfkill line that works fully in hardware or firmware, and that cannot
-	be overridden by the kernel driver.  The hardware device or the
-	firmware just exports its status to the driver, but it is read-only.
-	Related to rfkill_state RFKILL_STATE_HARD_BLOCKED.
-
-The enum rfkill_state describes the rfkill state of a transmitter:
-
-When a rfkill line or rfkill controller is in the RFKILL_STATE_UNBLOCKED state,
-the wireless transmitter (radio TX circuit for example) is *enabled*.  When the
-it is in the RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the
-wireless transmitter is to be *blocked* from operating.
-
-RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change
-that state.  RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio()
-will not be able to change the state and will return with a suitable error if
-attempts are made to set the state to RFKILL_STATE_UNBLOCKED.
-
-RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is
-locked in the BLOCKED state by a hardwire rfkill line (typically an input pin
-that, when active, forces the transmitter to be disabled) which the driver
-CANNOT override.
-
-Full rfkill functionality requires two different subsystems to cooperate: the
-input layer and the rfkill class.  The input layer issues *commands* to the
-entire system requesting that devices registered to the rfkill class change
-state.  The way this interaction happens is not complex, but it is not obvious
-either:
-
-Kernel Input layer:
-
-	* Generates KEY_WWAN, KEY_WLAN, KEY_BLUETOOTH, SW_RFKILL_ALL, and
-	  other such events when the user presses certain keys, buttons, or
-	  toggles certain physical switches.
-
-	THE INPUT LAYER IS NEVER USED TO PROPAGATE STATUS, NOTIFICATIONS OR THE
-	KIND OF STUFF AN ON-SCREEN-DISPLAY APPLICATION WOULD REPORT.  It is
-	used to issue *commands* for the system to change behaviour, and these
-	commands may or may not be carried out by some kernel driver or
-	userspace application.  It follows that doing user feedback based only
-	on input events is broken, as there is no guarantee that an input event
-	will be acted upon.
-
-	Most wireless communication device drivers implementing rfkill
-	functionality MUST NOT generate these events, and have no reason to
-	register themselves with the input layer.  Doing otherwise is a common
-	misconception.  There is an API to propagate rfkill status change
-	information, and it is NOT the input layer.
-
-rfkill class:
-
-	* Calls a hook in a driver to effectively change the wireless
-	  transmitter state;
-	* Keeps track of the wireless transmitter state (with help from
-	  the driver);
-	* Generates userspace notifications (uevents) and a call to a
-	  notification chain (kernel) when there is a wireless transmitter
-	  state change;
-	* Connects a wireless communications driver with the common rfkill
-	  control system, which, for example, allows actions such as
-	  "switch all bluetooth devices offline" to be carried out by
-	  userspace or by rfkill-input.
-
-	THE RFKILL CLASS NEVER ISSUES INPUT EVENTS.  THE RFKILL CLASS DOES
-	NOT LISTEN TO INPUT EVENTS.  NO DRIVER USING THE RFKILL CLASS SHALL
-	EVER LISTEN TO, OR ACT ON RFKILL INPUT EVENTS.  Doing otherwise is
-	a layering violation.
-
-	Most wireless data communication drivers in the kernel have just to
-	implement the rfkill class API to work properly.  Interfacing to the
-	input layer is not often required (and is very often a *bug*) on
-	wireless drivers.
-
-	Platform drivers often have to attach to the input layer to *issue*
-	(but never to listen to) rfkill events for rfkill switches, and also to
-	the rfkill class to export a control interface for the platform rfkill
-	controllers to the rfkill subsystem.  This does NOT mean the rfkill
-	switch is attached to a rfkill class (doing so is almost always wrong).
-	It just means the same kernel module is the driver for different
-	devices (rfkill switches and rfkill controllers).
-
-
-Userspace input handlers (uevents) or kernel input handlers (rfkill-input):
-
-	* Implements the policy of what should happen when one of the input
-	  layer events related to rfkill operation is received.
-	* Uses the sysfs interface (userspace) or private rfkill API calls
-	  to tell the devices registered with the rfkill class to change
-	  their state (i.e. translates the input layer event into real
-	  action).
-
-	* rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
-	  (power off all transmitters) in a special way: it ignores any
-	  overrides and local state cache and forces all transmitters to the
-	  RFKILL_STATE_SOFT_BLOCKED state (including those which are already
-	  supposed to be BLOCKED).
-	* rfkill EPO will remain active until rfkill-input receives an
-	  EV_SW SW_RFKILL_ALL 1 event.  While the EPO is active, transmitters
-	  are locked in the blocked state (rfkill will refuse to unblock them).
-	* rfkill-input implements different policies that the user can
-	  select for handling EV_SW SW_RFKILL_ALL 1.  It will unlock rfkill,
-	  and either do nothing (leave transmitters blocked, but now unlocked),
-	  restore the transmitters to their state before the EPO, or unblock
-	  them all.
-
-Userspace uevent handler or kernel platform-specific drivers hooked to the
-rfkill notifier chain:
-
-	* Taps into the rfkill notifier chain or to KOBJ_CHANGE uevents,
-	  in order to know when a device that is registered with the rfkill
-	  class changes state;
-	* Issues feedback notifications to the user;
-	* In the rare platforms where this is required, synthesizes an input
-	  event to command all *OTHER* rfkill devices to also change their
-	  statues when a specific rfkill device changes state.
-
-
-===============================================================================
-3: Kernel driver guidelines
-
-Remember: point-of-view is everything for a driver that connects to the rfkill
-subsystem.  All the details below must be measured/perceived from the point of
-view of the specific driver being modified.
-
-The first thing one needs to know is whether his driver should be talking to
-the rfkill class or to the input layer.  In rare cases (platform drivers), it
-could happen that you need to do both, as platform drivers often handle a
-variety of devices in the same driver.
-
-Do not mistake input devices for rfkill controllers.  The only type of "rfkill
-switch" device that is to be registered with the rfkill class are those
-directly controlling the circuits that cause a wireless transmitter to stop
-working (or the software equivalent of them), i.e. what we call a rfkill
-controller.  Every other kind of "rfkill switch" is just an input device and
-MUST NOT be registered with the rfkill class.
-
-A driver should register a device with the rfkill class when ALL of the
-following conditions are met (they define a rfkill controller):
-
-1. The device is/controls a data communications wireless transmitter;
-
-2. The kernel can interact with the hardware/firmware to CHANGE the wireless
-   transmitter state (block/unblock TX operation);
-
-3. The transmitter can be made to not emit any energy when "blocked":
-   rfkill is not about blocking data transmissions, it is about blocking
-   energy emission;
-
-A driver should register a device with the input subsystem to issue
-rfkill-related events (KEY_WLAN, KEY_BLUETOOTH, KEY_WWAN, KEY_WIMAX,
-SW_RFKILL_ALL, etc) when ALL of the folowing conditions are met:
-
-1. It is directly related to some physical device the user interacts with, to
-   command the O.S./firmware/hardware to enable/disable a data communications
-   wireless transmitter.
-
-   Examples of the physical device are: buttons, keys and switches the user
-   will press/touch/slide/switch to enable or disable the wireless
-   communication device.
-
-2. It is NOT slaved to another device, i.e. there is no other device that
-   issues rfkill-related input events in preference to this one.
-
-   Please refer to the corner cases and examples section for more details.
-
-When in doubt, do not issue input events.  For drivers that should generate
-input events in some platforms, but not in others (e.g. b43), the best solution
-is to NEVER generate input events in the first place.  That work should be
-deferred to a platform-specific kernel module (which will know when to generate
-events through the rfkill notifier chain) or to userspace.  This avoids the
-usual maintenance problems with DMI whitelisting.
-
-
-Corner cases and examples:
-====================================
-
-1. If the device is an input device that, because of hardware or firmware,
-causes wireless transmitters to be blocked regardless of the kernel's will, it
-is still just an input device, and NOT to be registered with the rfkill class.
-
-2. If the wireless transmitter switch control is read-only, it is an input
-device and not to be registered with the rfkill class (and maybe not to be made
-an input layer event source either, see below).
-
-3. If there is some other device driver *closer* to the actual hardware the
-user interacted with (the button/switch/key) to issue an input event, THAT is
-the device driver that should be issuing input events.
-
-E.g:
-  [RFKILL slider switch] -- [GPIO hardware] -- [WLAN card rf-kill input]
-                           (platform driver)    (wireless card driver)
-
-The user is closer to the RFKILL slide switch plaform driver, so the driver
-which must issue input events is the platform driver looking at the GPIO
-hardware, and NEVER the wireless card driver (which is just a slave).  It is
-very likely that there are other leaves than just the WLAN card rf-kill input
-(e.g. a bluetooth card, etc)...
-
-On the other hand, some embedded devices do this:
-
-  [RFKILL slider switch] -- [WLAN card rf-kill input]
-                             (wireless card driver)
-
-In this situation, the wireless card driver *could* register itself as an input
-device and issue rf-kill related input events... but in order to AVOID the need
-for DMI whitelisting, the wireless card driver does NOT do it.  Userspace (HAL)
-or a platform driver (that exists only on these embedded devices) will do the
-dirty job of issuing the input events.
-
-
-COMMON MISTAKES in kernel drivers, related to rfkill:
-====================================
-
-1. NEVER confuse input device keys and buttons with input device switches.
-
-  1a. Switches are always set or reset.  They report the current state
-      (on position or off position).
-
-  1b. Keys and buttons are either in the pressed or not-pressed state, and
-      that's it.  A "button" that latches down when you press it, and
-      unlatches when you press it again is in fact a switch as far as input
-      devices go.
-
-Add the SW_* events you need for switches, do NOT try to emulate a button using
-KEY_* events just because there is no such SW_* event yet.  Do NOT try to use,
-for example, KEY_BLUETOOTH when you should be using SW_BLUETOOTH instead.
-
-2. Input device switches (sources of EV_SW events) DO store their current state
-(so you *must* initialize it by issuing a gratuitous input layer event on
-driver start-up and also when resuming from sleep), and that state CAN be
-queried from userspace through IOCTLs.  There is no sysfs interface for this,
-but that doesn't mean you should break things trying to hook it to the rfkill
-class to get a sysfs interface :-)
-
-3. Do not issue *_RFKILL_ALL events by default, unless you are sure it is the
-correct event for your switch/button.  These events are emergency power-off
-events when they are trying to turn the transmitters off.  An example of an
-input device which SHOULD generate *_RFKILL_ALL events is the wireless-kill
-switch in a laptop which is NOT a hotkey, but a real sliding/rocker switch.
-An example of an input device which SHOULD NOT generate *_RFKILL_ALL events by
-default, is any sort of hot key that is type-specific (e.g. the one for WLAN).
-
-
-3.1 Guidelines for wireless device drivers
-------------------------------------------
-
-(in this text, rfkill->foo means the foo field of struct rfkill).
-
-1. Each independent transmitter in a wireless device (usually there is only one
-transmitter per device) should have a SINGLE rfkill class attached to it.
-
-2. If the device does not have any sort of hardware assistance to allow the
-driver to rfkill the device, the driver should emulate it by taking all actions
-required to silence the transmitter.
-
-3. If it is impossible to silence the transmitter (i.e. it still emits energy,
-even if it is just in brief pulses, when there is no data to transmit and there
-is no hardware support to turn it off) do NOT lie to the users.  Do not attach
-it to a rfkill class.  The rfkill subsystem does not deal with data
-transmission, it deals with energy emission.  If the transmitter is emitting
-energy, it is not blocked in rfkill terms.
-
-4. It doesn't matter if the device has multiple rfkill input lines affecting
-the same transmitter, their combined state is to be exported as a single state
-per transmitter (see rule 1).
-
-This rule exists because users of the rfkill subsystem expect to get (and set,
-when possible) the overall transmitter rfkill state, not of a particular rfkill
-line.
-
-5. The wireless device driver MUST NOT leave the transmitter enabled during
-suspend and hibernation unless:
-
-	5.1. The transmitter has to be enabled for some sort of functionality
-	like wake-on-wireless-packet or autonomous packed forwarding in a mesh
-	network, and that functionality is enabled for this suspend/hibernation
-	cycle.
-
-AND
-
-	5.2. The device was not on a user-requested BLOCKED state before
-	the suspend (i.e. the driver must NOT unblock a device, not even
-	to support wake-on-wireless-packet or remain in the mesh).
-
-In other words, there is absolutely no allowed scenario where a driver can
-automatically take action to unblock a rfkill controller (obviously, this deals
-with scenarios where soft-blocking or both soft and hard blocking is happening.
-Scenarios where hardware rfkill lines are the only ones blocking the
-transmitter are outside of this rule, since the wireless device driver does not
-control its input hardware rfkill lines in the first place).
-
-6. During resume, rfkill will try to restore its previous state.
-
-7. After a rfkill class is suspended, it will *not* call rfkill->toggle_radio
-until it is resumed.
-
-
-Example of a WLAN wireless driver connected to the rfkill subsystem:
---------------------------------------------------------------------
-
-A certain WLAN card has one input pin that causes it to block the transmitter
-and makes the status of that input pin available (only for reading!) to the
-kernel driver.  This is a hard rfkill input line (it cannot be overridden by
-the kernel driver).
-
-The card also has one PCI register that, if manipulated by the driver, causes
-it to block the transmitter.  This is a soft rfkill input line.
-
-It has also a thermal protection circuitry that shuts down its transmitter if
-the card overheats, and makes the status of that protection available (only for
-reading!) to the kernel driver.  This is also a hard rfkill input line.
-
-If either one of these rfkill lines are active, the transmitter is blocked by
-the hardware and forced offline.
-
-The driver should allocate and attach to its struct device *ONE* instance of
-the rfkill class (there is only one transmitter).
+rfkill - RF kill switch support
+===============================
 
-It can implement the get_state() hook, and return RFKILL_STATE_HARD_BLOCKED if
-either one of its two hard rfkill input lines are active.  If the two hard
-rfkill lines are inactive, it must return RFKILL_STATE_SOFT_BLOCKED if its soft
-rfkill input line is active.  Only if none of the rfkill input lines are
-active, will it return RFKILL_STATE_UNBLOCKED.
+1. Introduction
+2. Implementation details
+3. Kernel API
+4. Userspace support
 
-Since the device has a hardware rfkill line, it IS subject to state changes
-external to rfkill.  Therefore, the driver must make sure that it calls
-rfkill_force_state() to keep the status always up-to-date, and it must do a
-rfkill_force_state() on resume from sleep.
 
-Every time the driver gets a notification from the card that one of its rfkill
-lines changed state (polling might be needed on badly designed cards that don't
-generate interrupts for such events), it recomputes the rfkill state as per
-above, and calls rfkill_force_state() to update it.
-
-The driver should implement the toggle_radio() hook, that:
+1. Introduction
 
-1. Returns an error if one of the hardware rfkill lines are active, and the
-caller asked for RFKILL_STATE_UNBLOCKED.
+The rfkill subsystem provides a generic interface to disabling any radio
+transmitter in the system. When a transmitter is blocked, it shall not
+radiate any power.
 
-2. Activates the soft rfkill line if the caller asked for state
-RFKILL_STATE_SOFT_BLOCKED.  It should do this even if one of the hard rfkill
-lines are active, effectively double-blocking the transmitter.
+The subsystem also provides the ability to react on button presses and
+disable all transmitters of a certain type (or all). This is intended for
+situations where transmitters need to be turned off, for example on
+aircraft.
 
-3. Deactivates the soft rfkill line if none of the hardware rfkill lines are
-active and the caller asked for RFKILL_STATE_UNBLOCKED.
+The rfkill subsystem has a concept of "hard" and "soft" block, which
+differ little in their meaning (block == transmitters off) but rather in
+whether they can be changed or not:
+ - hard block: read-only radio block that cannot be overriden by software
+ - soft block: writable radio block (need not be readable) that is set by
+               the system software.
 
-===============================================================================
-4: Kernel API
 
-To build a driver with rfkill subsystem support, the driver should depend on
-(or select) the Kconfig symbol RFKILL; it should _not_ depend on RKFILL_INPUT.
+2. Implementation details
 
-The hardware the driver talks to may be write-only (where the current state
-of the hardware is unknown), or read-write (where the hardware can be queried
-about its current state).
+The rfkill subsystem is composed of three main components:
+ * the rfkill core,
+ * the deprecated rfkill-input module (an input layer handler, being
+   replaced by userspace policy code) and
+ * the rfkill drivers.
 
-The rfkill class will call the get_state hook of a device every time it needs
-to know the *real* current state of the hardware.  This can happen often, but
-it does not do any polling, so it is not enough on hardware that is subject
-to state changes outside of the rfkill subsystem.
+The rfkill core provides API for kernel drivers to register their radio
+transmitter with the kernel, methods for turning it on and off and, letting
+the system know about hardware-disabled states that may be implemented on
+the device.
 
-Therefore, calling rfkill_force_state() when a state change happens is
-mandatory when the device has a hardware rfkill line, or when something else
-like the firmware could cause its state to be changed without going through the
-rfkill class.
+The rfkill core code also notifies userspace of state changes, and provides
+ways for userspace to query the current states. See the "Userspace support"
+section below.
 
-Some hardware provides events when its status changes.  In these cases, it is
-best for the driver to not provide a get_state hook, and instead register the
-rfkill class *already* with the correct status, and keep it updated using
-rfkill_force_state() when it gets an event from the hardware.
+When the device is hard-blocked (either by a call to rfkill_set_hw_state()
+or from query_hw_block) set_block() will be invoked for additional software
+block, but drivers can ignore the method call since they can use the return
+value of the function rfkill_set_hw_state() to sync the software state
+instead of keeping track of calls to set_block(). In fact, drivers should
+use the return value of rfkill_set_hw_state() unless the hardware actually
+keeps track of soft and hard block separately.
 
-rfkill_force_state() must be used on the device resume handlers to update the
-rfkill status, should there be any chance of the device status changing during
-the sleep.
 
-There is no provision for a statically-allocated rfkill struct.  You must
-use rfkill_allocate() to allocate one.
+3. Kernel API
 
-You should:
-	- rfkill_allocate()
-	- modify rfkill fields (flags, name)
-	- modify state to the current hardware state (THIS IS THE ONLY TIME
-	  YOU CAN ACCESS state DIRECTLY)
-	- rfkill_register()
 
-The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through
-a suitable return of get_state() or through rfkill_force_state().
+Drivers for radio transmitters normally implement an rfkill driver.
 
-When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch
-it to a different state is through a suitable return of get_state() or through
-rfkill_force_state().
+Platform drivers might implement input devices if the rfkill button is just
+that, a button. If that button influences the hardware then you need to
+implement an rfkill driver instead. This also applies if the platform provides
+a way to turn on/off the transmitter(s).
 
-If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED
-when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should
-not return an error.  Instead, it should try to double-block the transmitter,
-so that its state will change from RFKILL_STATE_HARD_BLOCKED to
-RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease.
+For some platforms, it is possible that the hardware state changes during
+suspend/hibernation, in which case it will be necessary to update the rfkill
+core with the current state is at resume time.
 
-Please refer to the source for more documentation.
+To create an rfkill driver, driver's Kconfig needs to have
 
-===============================================================================
-5: Userspace support
+	depends on RFKILL || !RFKILL
 
-rfkill devices issue uevents (with an action of "change"), with the following
-environment variables set:
+to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL
+case allows the driver to be built when rfkill is not configured, which which
+case all rfkill API can still be used but will be provided by static inlines
+which compile to almost nothing.
 
-RFKILL_NAME
-RFKILL_STATE
-RFKILL_TYPE
+Calling rfkill_set_hw_state() when a state change happens is required from
+rfkill drivers that control devices that can be hard-blocked unless they also
+assign the poll_hw_block() callback (then the rfkill core will poll the
+device). Don't do this unless you cannot get the event in any other way.
 
-The ABI for these variables is defined by the sysfs attributes.  It is best
-to take a quick look at the source to make sure of the possible values.
 
-It is expected that HAL will trap those, and bridge them to DBUS, etc.  These
-events CAN and SHOULD be used to give feedback to the user about the rfkill
-status of the system.
 
-Input devices may issue events that are related to rfkill.  These are the
-various KEY_* events and SW_* events supported by rfkill-input.c.
+5. Userspace support
 
-******IMPORTANT******
-When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL
-SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it
-has set to true the user_claim attribute for that particular switch.  This rule
-is *absolute*; do NOT violate it.
-******IMPORTANT******
+The recommended userspace interface to use is /dev/rfkill, which is a misc
+character device that allows userspace to obtain and set the state of rfkill
+devices and sets of devices. It also notifies userspace about device addition
+and removal. The API is a simple read/write API that is defined in
+linux/rfkill.h, with one ioctl that allows turning off the deprecated input
+handler in the kernel for the transition period.
 
-Userspace must not assume it is the only source of control for rfkill switches.
-Their state CAN and WILL change due to firmware actions, direct user actions,
-and the rfkill-input EPO override for *_RFKILL_ALL.
+Except for the one ioctl, communication with the kernel is done via read()
+and write() of instances of 'struct rfkill_event'. In this structure, the
+soft and hard block are properly separated (unlike sysfs, see below) and
+userspace is able to get a consistent snapshot of all rfkill devices in the
+system. Also, it is possible to switch all rfkill drivers (or all drivers of
+a specified type) into a state which also updates the default state for
+hotplugged devices.
 
-When rfkill-input is not active, userspace must initiate a rfkill status
-change by writing to the "state" attribute in order for anything to happen.
+After an application opens /dev/rfkill, it can read the current state of
+all devices, and afterwards can poll the descriptor for hotplug or state
+change events.
 
-Take particular care to implement EV_SW SW_RFKILL_ALL properly.  When that
-switch is set to OFF, *every* rfkill device *MUST* be immediately put into the
-RFKILL_STATE_SOFT_BLOCKED state, no questions asked.
+Applications must ignore operations (the "op" field) they do not handle,
+this allows the API to be extended in the future.
 
-The following sysfs entries will be created:
+Additionally, each rfkill device is registered in sysfs and there has the
+following attributes:
 
 	name: Name assigned by driver to this key (interface or driver name).
-	type: Name of the key type ("wlan", "bluetooth", etc).
+	type: Driver type string ("wlan", "bluetooth", etc).
+	persistent: Whether the soft blocked state is initialised from
+	            non-volatile storage at startup.
 	state: Current state of the transmitter
 		0: RFKILL_STATE_SOFT_BLOCKED
-			transmitter is forced off, but one can override it
-			by a write to the state attribute;
+			transmitter is turned off by software
 		1: RFKILL_STATE_UNBLOCKED
-			transmiter is NOT forced off, and may operate if
-			all other conditions for such operation are met
-			(such as interface is up and configured, etc);
+			transmitter is (potentially) active
 		2: RFKILL_STATE_HARD_BLOCKED
 			transmitter is forced off by something outside of
-			the driver's control.  One cannot set a device to
-			this state through writes to the state attribute;
-	claim: 1: Userspace handles events, 0: Kernel handles events
-
-Both the "state" and "claim" entries are also writable. For the "state" entry
-this means that when 1 or 0 is written, the device rfkill state (if not yet in
-the requested state), will be will be toggled accordingly.
+			the driver's control.
+	       This file is deprecated because it can only properly show
+	       three of the four possible states, soft-and-hard-blocked is
+	       missing.
+	claim: 0: Kernel handles events
+	       This file is deprecated because there no longer is a way to
+	       claim just control over a single rfkill instance.
 
-For the "claim" entry writing 1 to it means that the kernel no longer handles
-key events even though RFKILL_INPUT input was enabled. When "claim" has been
-set to 0, userspace should make sure that it listens for the input events or
-check the sysfs "state" entry regularly to correctly perform the required tasks
-when the rkfill key is pressed.
+rfkill devices also issue uevents (with an action of "change"), with the
+following environment variables set:
 
-A note about input devices and EV_SW events:
+RFKILL_NAME
+RFKILL_STATE
+RFKILL_TYPE
 
-In order to know the current state of an input device switch (like
-SW_RFKILL_ALL), you will need to use an IOCTL.  That information is not
-available through sysfs in a generic way at this time, and it is not available
-through the rfkill class AT ALL.
+The contents of these variables corresponds to the "name", "state" and
+"type" sysfs files explained above.
diff -druN linux-libre-2.6.30-gnu/Documentation/robust-futex-ABI.txt linux-libre-2.6.31-gnu/Documentation/robust-futex-ABI.txt
--- linux-libre-2.6.30-gnu/Documentation/robust-futex-ABI.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/robust-futex-ABI.txt	2009-09-09 18:13:59.000000000 -0400
@@ -135,7 +135,7 @@
 protocol on 'lock entry' insertion and removal:
 
 On insertion:
- 1) set the 'list_op_pending' word to the address of the 'lock word'
+ 1) set the 'list_op_pending' word to the address of the 'lock entry'
     to be inserted,
  2) acquire the futex lock,
  3) add the lock entry, with its thread id (TID) in the bottom 29 bits
@@ -143,7 +143,7 @@
  4) clear the 'list_op_pending' word.
 
 On removal:
- 1) set the 'list_op_pending' word to the address of the 'lock word'
+ 1) set the 'list_op_pending' word to the address of the 'lock entry'
     to be removed,
  2) remove the lock entry for this lock from the 'head' list,
  2) release the futex lock, and
diff -druN linux-libre-2.6.30-gnu/Documentation/s390/Debugging390.txt linux-libre-2.6.31-gnu/Documentation/s390/Debugging390.txt
--- linux-libre-2.6.30-gnu/Documentation/s390/Debugging390.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/s390/Debugging390.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1984,7 +1984,7 @@
 
 break *0x400618
 
-heres a really useful one for large programs
+Here's a really useful one for large programs
 rbr
 Set a breakpoint for all functions matching REGEXP
 e.g.
@@ -2211,7 +2211,7 @@
 #5  0x51692c in readline_internal () at readline.c:521
 #6  0x5164fe in readline (prompt=0x7ffff810 "\177ÿøx\177ÿ÷Ø\177ÿøxÀ")
     at readline.c:349
-#7  0x4d7a8a in command_line_input (prrompt=0x564420 "(gdb) ", repeat=1,
+#7  0x4d7a8a in command_line_input (prompt=0x564420 "(gdb) ", repeat=1,
     annotation_suffix=0x4d6b44 "prompt") at top.c:2091
 #8  0x4d6cf0 in command_loop () at top.c:1345
 #9  0x4e25bc in main (argc=1, argv=0x7ffffdf4) at main.c:635
diff -druN linux-libre-2.6.30-gnu/Documentation/scheduler/sched-nice-design.txt linux-libre-2.6.31-gnu/Documentation/scheduler/sched-nice-design.txt
--- linux-libre-2.6.30-gnu/Documentation/scheduler/sched-nice-design.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/scheduler/sched-nice-design.txt	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,7 @@
 within the constraints of HZ and jiffies and their nasty design level
 coupling to timeslices and granularity it was not really viable.
 
-The second (less frequent but still periodically occuring) complaint
+The second (less frequent but still periodically occurring) complaint
 about Linux's nice level support was its assymetry around the origo
 (which you can see demonstrated in the picture above), or more
 accurately: the fact that nice level behavior depended on the _absolute_
diff -druN linux-libre-2.6.30-gnu/Documentation/scheduler/sched-rt-group.txt linux-libre-2.6.31-gnu/Documentation/scheduler/sched-rt-group.txt
--- linux-libre-2.6.30-gnu/Documentation/scheduler/sched-rt-group.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/scheduler/sched-rt-group.txt	2009-09-09 18:13:59.000000000 -0400
@@ -4,6 +4,7 @@
 CONTENTS
 ========
 
+0. WARNING
 1. Overview
   1.1 The problem
   1.2 The solution
@@ -14,6 +15,23 @@
 3. Future plans
 
 
+0. WARNING
+==========
+
+ Fiddling with these settings can result in an unstable system, the knobs are
+ root only and assumes root knows what he is doing.
+
+Most notable:
+
+ * very small values in sched_rt_period_us can result in an unstable
+   system when the period is smaller than either the available hrtimer
+   resolution, or the time it takes to handle the budget refresh itself.
+
+ * very small values in sched_rt_runtime_us can result in an unstable
+   system when the runtime is so small the system has difficulty making
+   forward progress (NOTE: the migration thread and kstopmachine both
+   are real-time processes).
+
 1. Overview
 ===========
 
@@ -55,7 +73,7 @@
 realtime tasks have explicitly allocated the CPU time they need to perform
 their tasks, buffer underruns in the graphics or audio can be eliminated.
 
-NOTE: the above example is not fully implemented as of yet (2.6.25). We still
+NOTE: the above example is not fully implemented yet. We still
 lack an EDF scheduler to make non-uniform periods usable.
 
 
@@ -122,14 +140,15 @@
 
 .o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups")
 
-This uses the /cgroup virtual file system and "/cgroup/<cgroup>/cpu.rt_runtime_us"
-to control the CPU time reserved for each control group instead.
+This uses the /cgroup virtual file system and
+"/cgroup/<cgroup>/cpu.rt_runtime_us" to control the CPU time reserved for each
+control group instead.
 
 For more information on working with control groups, you should read
 Documentation/cgroups/cgroups.txt as well.
 
-Group settings are checked against the following limits in order to keep the configuration
-schedulable:
+Group settings are checked against the following limits in order to keep the
+configuration schedulable:
 
    \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period
 
@@ -169,9 +188,9 @@
 
 Implementing SCHED_EDF might take a while to complete. Priority Inheritance is
 the biggest challenge as the current linux PI infrastructure is geared towards
-the limited static priority levels 0-139. With deadline scheduling you need to
+the limited static priority levels 0-99. With deadline scheduling you need to
 do deadline inheritance (since priority is inversely proportional to the
-deadline delta (deadline - now).
+deadline delta (deadline - now)).
 
 This means the whole PI machinery will have to be reworked - and that is one of
 the most complex pieces of code we have.
diff -druN linux-libre-2.6.30-gnu/Documentation/scsi/aic79xx.txt linux-libre-2.6.31-gnu/Documentation/scsi/aic79xx.txt
--- linux-libre-2.6.30-gnu/Documentation/scsi/aic79xx.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/scsi/aic79xx.txt	2009-09-09 18:13:59.000000000 -0400
@@ -194,7 +194,7 @@
           - Packetized SCSI Protocol at 160MB/s and 320MB/s
           - Quick Arbitration Selection (QAS)
           - Retained Training Information (Rev B. ASIC only)
-        - Interrupt Coalessing
+        - Interrupt Coalescing
         - Initiator Mode (target mode not currently 
           supported)
         - Support for the PCI-X standard up to 133MHz
diff -druN linux-libre-2.6.30-gnu/Documentation/scsi/ncr53c8xx.txt linux-libre-2.6.31-gnu/Documentation/scsi/ncr53c8xx.txt
--- linux-libre-2.6.30-gnu/Documentation/scsi/ncr53c8xx.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/scsi/ncr53c8xx.txt	2009-09-09 18:13:59.000000000 -0400
@@ -206,7 +206,7 @@
 The 896 and the 895A allows handling of the phase mismatch context from 
 SCRIPTS (avoids the phase mismatch interrupt that stops the SCSI processor 
 until the C code has saved the context of the transfer).
-Implementing this without using LOAD/STORE instructions would be painfull 
+Implementing this without using LOAD/STORE instructions would be painful 
 and I didn't even want to try it.
 
 The 896 chip supports 64 bit PCI transactions and addressing, while the 
@@ -240,7 +240,7 @@
 In order to really gain advantage of this feature, devices must have 
 a reasonable cache size (No miracle is to be expected for a low-end 
 hard disk with 128 KB or less).
-Some kown SCSI devices do not properly support tagged command queuing.
+Some known SCSI devices do not properly support tagged command queuing.
 Generally, firmware revisions that fix this kind of problems are available 
 at respective vendor web/ftp sites.
 All I can say is that the hard disks I use on my machines behave well with 
diff -druN linux-libre-2.6.30-gnu/Documentation/scsi/scsi_fc_transport.txt linux-libre-2.6.31-gnu/Documentation/scsi/scsi_fc_transport.txt
--- linux-libre-2.6.30-gnu/Documentation/scsi/scsi_fc_transport.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/scsi/scsi_fc_transport.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,11 @@
                              SCSI FC Tansport
                  =============================================
 
-Date:  4/12/2007
+Date:  11/18/2008
 Kernel Revisions for features:
   rports : <<TBS>>
-  vports : 2.6.22 (? TBD)
+  vports : 2.6.22
+  bsg support : 2.6.30 (?TBD?)
 
 
 Introduction
@@ -15,6 +16,7 @@
   drivers/scsi/scsi_transport_fc.c
   include/scsi/scsi_transport_fc.h
   include/scsi/scsi_netlink_fc.h
+  include/scsi/scsi_bsg_fc.h
 
 This file is found at Documentation/scsi/scsi_fc_transport.txt
 
@@ -472,6 +474,14 @@
 fc_vport_terminate(struct fc_vport *vport)
 
 
+FC BSG support (CT & ELS passthru, and more)
+========================================================================
+<< To Be Supplied >>
+
+
+
+
+
 Credits
 =======
 The following people have contributed to this document:
diff -druN linux-libre-2.6.30-gnu/Documentation/scsi/scsi_mid_low_api.txt linux-libre-2.6.31-gnu/Documentation/scsi/scsi_mid_low_api.txt
--- linux-libre-2.6.30-gnu/Documentation/scsi/scsi_mid_low_api.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/scsi/scsi_mid_low_api.txt	2009-09-09 18:13:59.000000000 -0400
@@ -1271,6 +1271,11 @@
     hostdata[0]  - area reserved for LLD at end of struct Scsi_Host. Size
                    is set by the second argument (named 'xtr_bytes') to
                    scsi_host_alloc() or scsi_register().
+    vendor_id    - a unique value that identifies the vendor supplying
+                   the LLD for the Scsi_Host.  Used most often in validating
+                   vendor-specific message requests.  Value consists of an
+                   identifier type and a vendor-specific value.
+                   See scsi_netlink.h for a description of valid formats.
 
 The scsi_host structure is defined in include/scsi/scsi_host.h
 
diff -druN linux-libre-2.6.30-gnu/Documentation/scsi/sym53c8xx_2.txt linux-libre-2.6.31-gnu/Documentation/scsi/sym53c8xx_2.txt
--- linux-libre-2.6.30-gnu/Documentation/scsi/sym53c8xx_2.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/scsi/sym53c8xx_2.txt	2009-09-09 18:13:59.000000000 -0400
@@ -206,7 +206,7 @@
 In order to really gain advantage of this feature, devices must have 
 a reasonable cache size (No miracle is to be expected for a low-end 
 hard disk with 128 KB or less).
-Some kown old SCSI devices do not properly support tagged command queuing.
+Some known old SCSI devices do not properly support tagged command queuing.
 Generally, firmware revisions that fix this kind of problems are available 
 at respective vendor web/ftp sites.
 All I can say is that I never have had problem with tagged queuing using 
diff -druN linux-libre-2.6.30-gnu/Documentation/SM501.txt linux-libre-2.6.31-gnu/Documentation/SM501.txt
--- linux-libre-2.6.30-gnu/Documentation/SM501.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/SM501.txt	2009-09-09 18:13:59.000000000 -0400
@@ -5,7 +5,7 @@
 
 The Silicon Motion SM501 multimedia companion chip is a multifunction device
 which may provide numerous interfaces including USB host controller USB gadget,
-Asyncronous Serial ports, Audio functions and a dual display video interface.
+asynchronous serial ports, audio functions, and a dual display video interface.
 The device may be connected by PCI or local bus with varying functions enabled.
 
 Core
diff -druN linux-libre-2.6.30-gnu/Documentation/Smack.txt linux-libre-2.6.31-gnu/Documentation/Smack.txt
--- linux-libre-2.6.30-gnu/Documentation/Smack.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/Smack.txt	2009-09-09 18:13:59.000000000 -0400
@@ -184,8 +184,9 @@
 other than a letter or digit, are reserved for use by the Smack development
 team. Smack labels are unstructured, case sensitive, and the only operation
 ever performed on them is comparison for equality. Smack labels cannot
-contain unprintable characters or the "/" (slash) character. Smack labels
-cannot begin with a '-', which is reserved for special options.
+contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
+(quote) and '"' (double-quote) characters.
+Smack labels cannot begin with a '-', which is reserved for special options.
 
 There are some predefined labels:
 
@@ -523,3 +524,18 @@
 
 These mount options apply to all file system types.
 
+Smack auditing
+
+If you want Smack auditing of security events, you need to set CONFIG_AUDIT
+in your kernel configuration.
+By default, all denied events will be audited. You can change this behavior by
+writing a single character to the /smack/logging file :
+0 : no logging
+1 : log denied (default)
+2 : log accepted
+3 : log denied & accepted
+
+Events are logged as 'key=value' pairs, for each event you at least will get
+the subjet, the object, the rights requested, the action, the kernel function
+that triggered the event, plus other pairs depending on the type of event
+audited.
diff -druN linux-libre-2.6.30-gnu/Documentation/sound/alsa/ALSA-Configuration.txt linux-libre-2.6.31-gnu/Documentation/sound/alsa/ALSA-Configuration.txt
--- linux-libre-2.6.30-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2012-03-22 19:24:02.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2012-03-22 20:18:34.000000000 -0400
@@ -460,6 +460,25 @@
 
     The power-management is supported.
 
+  Module snd-ctxfi
+  ----------------
+
+    Module for Creative Sound Blaster X-Fi boards (20k1 / 20k2 chips)
+	* Creative Sound Blaster X-Fi Titanium Fatal1ty Champion Series
+	* Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series
+	* Creative Sound Blaster X-Fi Titanium Professional Audio
+	* Creative Sound Blaster X-Fi Titanium
+	* Creative Sound Blaster X-Fi Elite Pro
+	* Creative Sound Blaster X-Fi Platinum
+	* Creative Sound Blaster X-Fi Fatal1ty
+	* Creative Sound Blaster X-Fi XtremeGamer
+	* Creative Sound Blaster X-Fi XtremeMusic
+
+    reference_rate	- reference sample rate, 44100 or 48000 (default)
+    multiple		- multiple to ref. sample rate, 1 or 2 (default)
+
+    This module supports multiple cards.
+
   Module snd-darla20
   ------------------
 
@@ -754,7 +773,7 @@
     single_cmd  - Use single immediate commands to communicate with
 		codecs (for debugging only)
     enable_msi	- Enable Message Signaled Interrupt (MSI) (default = off)
-    power_save	- Automatic power-saving timtout (in second, 0 =
+    power_save	- Automatic power-saving timeout (in second, 0 =
 		disable)
     power_save_controller - Reset HD-audio controller in power-saving mode
 		(default = on)
@@ -925,6 +944,7 @@
 			* Onkyo SE-90PCI
 			* Onkyo SE-200PCI
 			* ESI Juli@
+			* ESI Maya44
 			* Hercules Fortissimo IV
 			* EGO-SYS WaveTerminal 192M
 
@@ -933,7 +953,7 @@
 		  prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192,
 		  juli, aureon51, aureon71, universe, ap192, k8x800,
 		  phase22, phase28, ms300, av710, se200pci, se90pci,
-		  fortissimo4, sn25p, WT192M
+		  fortissimo4, sn25p, WT192M, maya44
 
     This module supports multiple cards and autoprobe.
 
@@ -1093,6 +1113,13 @@
     This module supports multiple cards.
     The driver requires the firmware loader support on kernel.
 
+  Module snd-lx6464es
+  -------------------
+
+    Module for Digigram LX6464ES boards
+
+    This module supports multiple cards.
+
   Module snd-maestro3
   -------------------
 
@@ -1543,13 +1570,15 @@
   Module snd-sc6000
   -----------------
 
-    Module for Gallant SC-6000 soundcard.
+    Module for Gallant SC-6000 soundcard and later models: SC-6600
+    and SC-7000.
 
     port	- Port # (0x220 or 0x240)
     mss_port	- MSS Port # (0x530 or 0xe80)
     irq		- IRQ # (5,7,9,10,11)
     mpu_irq	- MPU-401 IRQ # (5,7,9,10) ,0 - no MPU-401 irq
     dma		- DMA # (1,3,0)
+    joystick	- Enable gameport - 0 = disable (default), 1 = enable
 
     This module supports multiple cards.
 
@@ -1850,7 +1879,8 @@
   -------------------
 
     Module for sound cards based on the Asus AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX.
+    i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), Essence ST
+    (Deluxe) and Essence STX.
 
     This module supports autoprobe and multiple cards.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/sound/alsa/hda_codec.txt linux-libre-2.6.31-gnu/Documentation/sound/alsa/hda_codec.txt
--- linux-libre-2.6.30-gnu/Documentation/sound/alsa/hda_codec.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sound/alsa/hda_codec.txt	2009-09-09 18:13:59.000000000 -0400
@@ -114,7 +114,7 @@
 
 There are variants of cached read/write, snd_hda_codec_write_cache(),
 snd_hda_sequence_write_cache().  These are used for recording the
-register states for the power-mangement resume.  When no PM is needed,
+register states for the power-management resume.  When no PM is needed,
 these are equivalent with non-cached version.
 
 To retrieve the number of sub nodes connected to the given node, use
diff -druN linux-libre-2.6.30-gnu/Documentation/sound/alsa/HD-Audio-Models.txt linux-libre-2.6.31-gnu/Documentation/sound/alsa/HD-Audio-Models.txt
--- linux-libre-2.6.30-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,7 @@
   acer		Acer TravelMate
   will		Will laptops (PB V7900)
   replacer	Replacer 672V
+  favorit100	Maxdata Favorit 100XS
   basic		fixed pin assignment (old default model)
   test		for testing/debugging purpose, almost all controls can
 		adjusted.  Appearing only when compiled with
@@ -85,10 +86,11 @@
   eeepc-p703	ASUS Eeepc P703 P900A
   eeepc-p901	ASUS Eeepc P901 S101
   fujitsu	FSC Amilo
+  lifebook	Fujitsu Lifebook S6420
   auto		auto-config reading BIOS (default)
 
-ALC662/663
-==========
+ALC662/663/272
+==============
   3stack-dig	3-stack (2-channel) with SPDIF
   3stack-6ch	 3-stack (6-channel)
   3stack-6ch-dig 3-stack (6-channel) with SPDIF
@@ -107,6 +109,9 @@
   asus-mode4	ASUS
   asus-mode5	ASUS
   asus-mode6	ASUS
+  dell		Dell with ALC272
+  dell-zm1	Dell ZM1 with ALC272
+  samsung-nc10	Samsung NC10 mini notebook
   auto		auto-config reading BIOS (default)
 
 ALC882/885
@@ -118,6 +123,7 @@
   asus-a7j	ASUS A7J
   asus-a7m	ASUS A7M
   macpro	MacPro support
+  mb5		Macbook 5,1
   mbp3		Macbook Pro rev3
   imac24	iMac 24'' with jack detection
   w2jc		ASUS W2JC
@@ -133,10 +139,13 @@
   acer		Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
   acer-aspire	Acer Aspire 9810
   acer-aspire-4930g Acer Aspire 4930G
+  acer-aspire-6530g Acer Aspire 6530G
+  acer-aspire-8930g Acer Aspire 8930G
   medion	Medion Laptops
   medion-md2	Medion MD2
   targa-dig	Targa/MSI
-  targa-2ch-dig	Targs/MSI with 2-channel
+  targa-2ch-dig	Targa/MSI with 2-channel
+  targa-8ch-dig Targa/MSI with 8-channel (MSI GX620)
   laptop-eapd   3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
   lenovo-101e	Lenovo 101E
   lenovo-nb0763	Lenovo NB0763
@@ -150,6 +159,9 @@
   fujitsu-pi2515 Fujitsu AMILO Pi2515
   fujitsu-xa3530 Fujitsu AMILO XA3530
   3stack-6ch-intel Intel DG33* boards
+  asus-p5q	ASUS P5Q-EM boards
+  mb31		MacBook 3,1
+  sony-vaio-tt  Sony VAIO TT
   auto		auto-config reading BIOS (default)
 
 ALC861/660
@@ -228,6 +240,7 @@
   laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
   ultra		2-channel with EAPD (Samsung Ultra tablet PC)
   samsung	2-channel with EAPD (Samsung R65)
+  samsung-p50	2-channel with HP-automute (Samsung P50)
 
 AD1988/AD1988B/AD1989A/AD1989B
 ==============================
@@ -348,6 +361,7 @@
   hp-m4		HP mini 1000
   hp-dv5	HP dv series
   hp-hdx	HP HDX series
+  hp-dv4-1222nr	HP dv4-1222nr (with LED support)
   auto		BIOS setup (default)
 
 STAC92HD73*
diff -druN linux-libre-2.6.30-gnu/Documentation/sound/alsa/HD-Audio.txt linux-libre-2.6.31-gnu/Documentation/sound/alsa/HD-Audio.txt
--- linux-libre-2.6.30-gnu/Documentation/sound/alsa/HD-Audio.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sound/alsa/HD-Audio.txt	2009-09-09 18:13:59.000000000 -0400
@@ -16,7 +16,7 @@
 The HD-audio component consists of two parts: the controller chip and 
 the codec chips on the HD-audio bus.  Linux provides a single driver
 for all controllers, snd-hda-intel.  Although the driver name contains
-a word of a well-known harware vendor, it's not specific to it but for
+a word of a well-known hardware vendor, it's not specific to it but for
 all controller chips by other companies.  Since the HD-audio
 controllers are supposed to be compatible, the single snd-hda-driver
 should work in most cases.  But, not surprisingly, there are known
diff -druN linux-libre-2.6.30-gnu/Documentation/sound/alsa/Procfile.txt linux-libre-2.6.31-gnu/Documentation/sound/alsa/Procfile.txt
--- linux-libre-2.6.30-gnu/Documentation/sound/alsa/Procfile.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sound/alsa/Procfile.txt	2009-09-09 18:13:59.000000000 -0400
@@ -88,26 +88,39 @@
 	substreams, etc.
 
 card*/pcm*/xrun_debug
-	This file appears when CONFIG_SND_DEBUG=y.
-	This shows the status of xrun (= buffer overrun/xrun) debug of
-	ALSA PCM middle layer, as an integer from 0 to 2.  The value
-	can be changed by writing to this file, such as
+	This file appears when CONFIG_SND_DEBUG=y and
+	CONFIG_PCM_XRUN_DEBUG=y.
+	This shows the status of xrun (= buffer overrun/xrun) and
+	invalid PCM position debug/check of ALSA PCM middle layer.
+	It takes an integer value, can be changed by writing to this
+	file, such as
 
-		 # cat 2 > /proc/asound/card0/pcm0p/xrun_debug
+		 # cat 5 > /proc/asound/card0/pcm0p/xrun_debug
 
-	When this value is greater than 0, the driver will show the
-	messages to kernel log when an xrun is detected.  The debug
-	message is shown also when the invalid H/W pointer is detected
-	at the update of periods (usually called from the interrupt
+	The value consists of the following bit flags:
+	  bit 0 = Enable XRUN/jiffies debug messages
+	  bit 1 = Show stack trace at XRUN / jiffies check
+	  bit 2 = Enable additional jiffies check
+	  bit 3 = Log hwptr update at each period interrupt
+	  bit 4 = Log hwptr update at each snd_pcm_update_hw_ptr()
+
+	When the bit 0 is set, the driver will show the messages to
+	kernel log when an xrun is detected.  The debug message is
+	shown also when the invalid H/W pointer is detected at the
+	update of periods (usually called from the interrupt
 	handler).
 
-	When this value is greater than 1, the driver will show the
-	stack trace additionally.  This may help the debugging.
+	When the bit 1 is set, the driver will show the stack trace
+	additionally.  This may help the debugging.
 
-	Since 2.6.30, this option also enables the hwptr check using
+	Since 2.6.30, this option can enable the hwptr check using
 	jiffies.  This detects spontaneous invalid pointer callback
 	values, but can be lead to too much corrections for a (mostly
 	buggy) hardware that doesn't give smooth pointer updates.
+	This feature is enabled via the bit 2.
+
+	Bits 3 and 4 are for logging the hwptr records.  Note that
+	these will give flood of kernel messages.
 
 card*/pcm*/sub*/info
 	The general information of this PCM sub-stream.
diff -druN linux-libre-2.6.30-gnu/Documentation/sound/alsa/README.maya44 linux-libre-2.6.31-gnu/Documentation/sound/alsa/README.maya44
--- linux-libre-2.6.30-gnu/Documentation/sound/alsa/README.maya44	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/sound/alsa/README.maya44	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,163 @@
+NOTE: The following is the original document of Rainer's patch that the
+current maya44 code based on.  Some contents might be obsoleted, but I
+keep here as reference -- tiwai
+
+----------------------------------------------------------------
+ 
+STATE OF DEVELOPMENT:
+
+This driver is being developed on the initiative of Piotr Makowski (oponek@gmail.com) and financed by Lars Bergmann.
+Development is carried out by Rainer Zimmermann (mail@lightshed.de).
+
+ESI provided a sample Maya44 card for the development work.
+
+However, unfortunately it has turned out difficult to get detailed programming information, so I (Rainer Zimmermann) had to find out some card-specific information by experiment and conjecture. Some information (in particular, several GPIO bits) is still missing.
+
+This is the first testing version of the Maya44 driver released to the alsa-devel mailing list (Feb 5, 2008).
+
+
+The following functions work, as tested by Rainer Zimmermann and Piotr Makowski:
+
+- playback and capture at all sampling rates
+- input/output level
+- crossmixing
+- line/mic switch
+- phantom power switch
+- analogue monitor a.k.a bypass
+
+
+The following functions *should* work, but are not fully tested:
+
+- Channel 3+4 analogue - S/PDIF input switching
+- S/PDIF output
+- all inputs/outputs on the M/IO/DIO extension card
+- internal/external clock selection
+
+
+*In particular, we would appreciate testing of these functions by anyone who has access to an M/IO/DIO extension card.*
+
+
+Things that do not seem to work:
+
+- The level meters ("multi track") in 'alsamixer' do not seem to react to signals in (if this is a bug, it would probably be in the existing ICE1724 code).
+
+- Ardour 2.1 seems to work only via JACK, not using ALSA directly or via OSS. This still needs to be tracked down.
+
+
+DRIVER DETAILS:
+
+the following files were added:
+
+pci/ice1724/maya44.c        - Maya44 specific code
+pci/ice1724/maya44.h
+pci/ice1724/ice1724.patch
+pci/ice1724/ice1724.h.patch - PROPOSED patch to ice1724.h (see SAMPLING RATES)
+i2c/other/wm8776.c  - low-level access routines for Wolfson WM8776 codecs 
+include/wm8776.h
+
+
+Note that the wm8776.c code is meant to be card-independent and does not actually register the codec with the ALSA infrastructure.
+This is done in maya44.c, mainly because some of the WM8776 controls are used in Maya44-specific ways, and should be named appropriately.
+
+
+the following files were created in pci/ice1724, simply #including the corresponding file from the alsa-kernel tree:
+
+wtm.h
+vt1720_mobo.h
+revo.h
+prodigy192.h
+pontis.h
+phase.h
+maya44.h
+juli.h
+aureon.h
+amp.h
+envy24ht.h
+se.h
+prodigy_hifi.h
+
+
+*I hope this is the correct way to do things.*
+
+
+SAMPLING RATES:
+
+The Maya44 card (or more exactly, the Wolfson WM8776 codecs) allow a maximum sampling rate of 192 kHz for playback and 92 kHz for capture.
+
+As the ICE1724 chip only allows one global sampling rate, this is handled as follows:
+
+* setting the sampling rate on any open PCM device on the maya44 card will always set the *global* sampling rate for all playback and capture channels.
+
+* In the current state of the driver, setting rates of up to 192 kHz is permitted even for capture devices.
+
+*AVOID CAPTURING AT RATES ABOVE 96kHz*, even though it may appear to work. The codec cannot actually capture at such rates, meaning poor quality.
+
+
+I propose some additional code for limiting the sampling rate when setting on a capture pcm device. However because of the global sampling rate, this logic would be somewhat problematic.
+
+The proposed code (currently deactivated) is in ice1712.h.patch, ice1724.c and maya44.c (in pci/ice1712).
+
+
+SOUND DEVICES:
+
+PCM devices correspond to inputs/outputs as follows (assuming Maya44 is card #0):
+
+hw:0,0 input - stereo, analog input 1+2
+hw:0,0 output - stereo, analog output 1+2
+hw:0,1 input - stereo, analog input 3+4 OR S/PDIF input
+hw:0,1 output - stereo, analog output 3+4 (and SPDIF out)
+
+
+NAMING OF MIXER CONTROLS:
+
+(for more information about the signal flow, please refer to the block diagram on p.24 of the ESI Maya44 manual, or in the ESI windows software).
+
+
+PCM: (digital) output level for channel 1+2
+PCM 1: same for channel 3+4
+
+Mic Phantom+48V: switch for +48V phantom power for electrostatic microphones on input 1/2.
+    Make sure this is not turned on while any other source is connected to input 1/2.
+    It might damage the source and/or the maya44 card.
+
+Mic/Line input: if switch is is on, input jack 1/2 is microphone input (mono), otherwise line input (stereo).
+
+Bypass: analogue bypass from ADC input to output for channel 1+2. Same as "Monitor" in the windows driver.
+Bypass 1: same for channel 3+4.
+
+Crossmix: cross-mixer from channels 1+2 to channels 3+4
+Crossmix 1: cross-mixer from channels 3+4 to channels 1+2
+
+IEC958 Output: switch for S/PDIF output.
+    This is not supported by the ESI windows driver.
+    S/PDIF should output the same signal as channel 3+4. [untested!]
+
+
+Digitial output selectors:
+
+    These switches allow a direct digital routing from the ADCs to the DACs.
+    Each switch determines where the digital input data to one of the DACs comes from.
+    They are not supported by the ESI windows driver.
+    For normal operation, they should all be set to "PCM out".
+
+H/W: Output source channel 1
+H/W 1: Output source channel 2
+H/W 2: Output source channel 3
+H/W 3: Output source channel 4
+
+H/W 4 ... H/W 9: unknown function, left in to enable testing.
+    Possibly some of these control S/PDIF output(s).
+    If these turn out to be unused, they will go away in later driver versions.
+
+Selectable values for each of the digital output selectors are:
+   "PCM out" -> DAC output of the corresponding channel (default setting)
+   "Input 1"...
+   "Input 4" -> direct routing from ADC output of the selected input channel
+
+
+--------
+
+Feb 14, 2008
+Rainer Zimmermann
+mail@lightshed.de
+
diff -druN linux-libre-2.6.30-gnu/Documentation/sound/alsa/soc/dapm.txt linux-libre-2.6.31-gnu/Documentation/sound/alsa/soc/dapm.txt
--- linux-libre-2.6.30-gnu/Documentation/sound/alsa/soc/dapm.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sound/alsa/soc/dapm.txt	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,7 @@
  o Mic        - Mic (and optional Jack)
  o Line       - Line Input/Output (and optional Jack)
  o Speaker    - Speaker
+ o Supply     - Power or clock supply widget used by other widgets.
  o Pre        - Special PRE widget (exec before all others)
  o Post       - Special POST widget (exec after all others)
 
diff -druN linux-libre-2.6.30-gnu/Documentation/spi/spidev_test.c linux-libre-2.6.31-gnu/Documentation/spi/spidev_test.c
--- linux-libre-2.6.30-gnu/Documentation/spi/spidev_test.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/spi/spidev_test.c	2009-09-09 18:13:59.000000000 -0400
@@ -99,11 +99,13 @@
 			{ "lsb",     0, 0, 'L' },
 			{ "cs-high", 0, 0, 'C' },
 			{ "3wire",   0, 0, '3' },
+			{ "no-cs",   0, 0, 'N' },
+			{ "ready",   0, 0, 'R' },
 			{ NULL, 0, 0, 0 },
 		};
 		int c;
 
-		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3", lopts, NULL);
+		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
 
 		if (c == -1)
 			break;
@@ -139,6 +141,12 @@
 		case '3':
 			mode |= SPI_3WIRE;
 			break;
+		case 'N':
+			mode |= SPI_NO_CS;
+			break;
+		case 'R':
+			mode |= SPI_READY;
+			break;
 		default:
 			print_usage(argv[0]);
 			break;
diff -druN linux-libre-2.6.30-gnu/Documentation/SubmitChecklist linux-libre-2.6.31-gnu/Documentation/SubmitChecklist
--- linux-libre-2.6.30-gnu/Documentation/SubmitChecklist	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/SubmitChecklist	2009-09-09 18:13:59.000000000 -0400
@@ -54,7 +54,7 @@
     CONFIG_PREEMPT.
 
 14: If the patch affects IO/Disk, etc: has been tested with and without
-    CONFIG_LBD.
+    CONFIG_LBDAF.
 
 15: All codepaths have been exercised with all lockdep features enabled.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/SubmittingPatches linux-libre-2.6.31-gnu/Documentation/SubmittingPatches
--- linux-libre-2.6.30-gnu/Documentation/SubmittingPatches	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/SubmittingPatches	2009-09-09 18:13:59.000000000 -0400
@@ -91,6 +91,10 @@
 things like "update driver X", "bug fix for driver X", or "this patch
 includes updates for subsystem X.  Please apply."
 
+The maintainer will thank you if you write your patch description in a
+form which can be easily pulled into Linux's source code management
+system, git, as a "commit log".  See #15, below.
+
 If your description starts to get long, that's a sign that you probably
 need to split up your patch.  See #3, next.
 
@@ -183,8 +187,9 @@
 copy the maintainer when you change their code.
 
 For small patches you may want to CC the Trivial Patch Monkey
-trivial@kernel.org managed by Jesper Juhl; which collects "trivial"
-patches. Trivial patches must qualify for one of the following rules:
+trivial@kernel.org which collects "trivial" patches. Have a look
+into the MAINTAINERS file for its current manager.
+Trivial patches must qualify for one of the following rules:
  Spelling fixes in documentation
  Spelling fixes which could break grep(1)
  Warning fixes (cluttering with useless warnings is bad)
@@ -196,7 +201,6 @@
  since people copy, as long as it's trivial)
  Any fix by the author/maintainer of the file (ie. patch monkey
  in re-transmission mode)
-URL: <http://www.kernel.org/pub/linux/kernel/people/juhl/trivial/>
 
 
 
@@ -405,7 +409,14 @@
 have been included in the discussion
 
 
-14) Using Tested-by: and Reviewed-by:
+14) Using Reported-by:, Tested-by: and Reviewed-by:
+
+If this patch fixes a problem reported by somebody else, consider adding a
+Reported-by: tag to credit the reporter for their contribution.  Please
+note that this tag should not be added without the reporter's permission,
+especially if the problem was not reported in a public forum.  That said,
+if we diligently credit our bug reporters, they will, hopefully, be
+inspired to help us again in the future.
 
 A Tested-by: tag indicates that the patch has been successfully tested (in
 some environment) by the person named.  This tag informs maintainers that
@@ -444,7 +455,7 @@
 reviewers and to inform maintainers of the degree of review which has been
 done on the patch.  Reviewed-by: tags, when supplied by reviewers known to
 understand the subject area and to perform thorough reviews, will normally
-increase the liklihood of your patch getting into the kernel.
+increase the likelihood of your patch getting into the kernel.
 
 
 15) The canonical patch format
@@ -485,12 +496,33 @@
 phrase" for every patch in a whole patch series (where a "patch
 series" is an ordered sequence of multiple, related patches).
 
-Bear in mind that the "summary phrase" of your email becomes
-a globally-unique identifier for that patch.  It propagates
-all the way into the git changelog.  The "summary phrase" may
-later be used in developer discussions which refer to the patch.
-People will want to google for the "summary phrase" to read
-discussion regarding that patch.
+Bear in mind that the "summary phrase" of your email becomes a
+globally-unique identifier for that patch.  It propagates all the way
+into the git changelog.  The "summary phrase" may later be used in
+developer discussions which refer to the patch.  People will want to
+google for the "summary phrase" to read discussion regarding that
+patch.  It will also be the only thing that people may quickly see
+when, two or three months later, they are going through perhaps
+thousands of patches using tools such as "gitk" or "git log
+--oneline".
+
+For these reasons, the "summary" must be no more than 70-75
+characters, and it must describe both what the patch changes, as well
+as why the patch might be necessary.  It is challenging to be both
+succinct and descriptive, but that is what a well-written summary
+should do.
+
+The "summary phrase" may be prefixed by tags enclosed in square
+brackets: "Subject: [PATCH tag] <summary phrase>".  The tags are not
+considered part of the summary phrase, but describe how the patch
+should be treated.  Common tags might include a version descriptor if
+the multiple versions of the patch have been sent out in response to
+comments (i.e., "v1, v2, v3"), or "RFC" to indicate a request for
+comments.  If there are four patches in a patch series the individual
+patches may be numbered like this: 1/4, 2/4, 3/4, 4/4.  This assures
+that developers understand the order in which the patches should be
+applied and that they have reviewed or applied all of the patches in
+the patch series.
 
 A couple of example Subjects:
 
@@ -510,19 +542,31 @@
 The explanation body will be committed to the permanent source
 changelog, so should make sense to a competent reader who has long
 since forgotten the immediate details of the discussion that might
-have led to this patch.
+have led to this patch.  Including symptoms of the failure which the
+patch addresses (kernel log messages, oops messages, etc.) is
+especially useful for people who might be searching the commit logs
+looking for the applicable patch.  If a patch fixes a compile failure,
+it may not be necessary to include _all_ of the compile failures; just
+enough that it is likely that someone searching for the patch can find
+it.  As in the "summary phrase", it is important to be both succinct as
+well as descriptive.
 
 The "---" marker line serves the essential purpose of marking for patch
 handling tools where the changelog message ends.
 
 One good use for the additional comments after the "---" marker is for
-a diffstat, to show what files have changed, and the number of inserted
-and deleted lines per file.  A diffstat is especially useful on bigger
-patches.  Other comments relevant only to the moment or the maintainer,
-not suitable for the permanent changelog, should also go here.
-Use diffstat options "-p 1 -w 70" so that filenames are listed from the
-top of the kernel source tree and don't use too much horizontal space
-(easily fit in 80 columns, maybe with some indentation).
+a diffstat, to show what files have changed, and the number of
+inserted and deleted lines per file.  A diffstat is especially useful
+on bigger patches.  Other comments relevant only to the moment or the
+maintainer, not suitable for the permanent changelog, should also go
+here.  A good example of such comments might be "patch changelogs"
+which describe what has changed between the v1 and v2 version of the
+patch.
+
+If you are going to include a diffstat after the "---" marker, please
+use diffstat options "-p 1 -w 70" so that filenames are listed from
+the top of the kernel source tree and don't use too much horizontal
+space (easily fit in 80 columns, maybe with some indentation).
 
 See more details on the proper patch format in the following
 references.
diff -druN linux-libre-2.6.30-gnu/Documentation/sysctl/kernel.txt linux-libre-2.6.31-gnu/Documentation/sysctl/kernel.txt
--- linux-libre-2.6.30-gnu/Documentation/sysctl/kernel.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sysctl/kernel.txt	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 - kstack_depth_to_print       [ X86 only ]
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/debugging-modules.txt
+- modules_disabled
 - msgmax
 - msgmnb
 - msgmni
@@ -184,6 +185,16 @@
 
 ==============================================================
 
+modules_disabled:
+
+A toggle value indicating if modules are allowed to be loaded
+in an otherwise modular kernel.  This toggle defaults to off
+(0), but can be set true (1).  Once true, modules can be
+neither loaded nor unloaded, and the toggle cannot be set back
+to false.
+
+==============================================================
+
 osrelease, ostype & version:
 
 # cat osrelease
diff -druN linux-libre-2.6.30-gnu/Documentation/sysctl/vm.txt linux-libre-2.6.31-gnu/Documentation/sysctl/vm.txt
--- linux-libre-2.6.30-gnu/Documentation/sysctl/vm.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sysctl/vm.txt	2009-09-09 18:13:59.000000000 -0400
@@ -233,8 +233,8 @@
 for page allocation or should be reclaimed.
 
 In this example, if normal pages (index=2) are required to this DMA zone and
-pages_high is used for watermark, the kernel judges this zone should not be
-used because pages_free(1355) is smaller than watermark + protection[2]
+watermark[WMARK_HIGH] is used for watermark, the kernel judges this zone should
+not be used because pages_free(1355) is smaller than watermark + protection[2]
 (4 + 2004 = 2008). If this protection value is 0, this zone would be used for
 normal page requirement. If requirement is DMA zone(index=0), protection[0]
 (=0) is used.
@@ -280,9 +280,10 @@
 min_free_kbytes:
 
 This is used to force the Linux VM to keep a minimum number
-of kilobytes free.  The VM uses this number to compute a pages_min
-value for each lowmem zone in the system.  Each lowmem zone gets
-a number of reserved free pages based proportionally on its size.
+of kilobytes free.  The VM uses this number to compute a
+watermark[WMARK_MIN] value for each lowmem zone in the system.
+Each lowmem zone gets a number of reserved free pages based
+proportionally on its size.
 
 Some minimal amount of memory is needed to satisfy PF_MEMALLOC
 allocations; if you set this to lower than 1024KB, your system will
@@ -314,10 +315,14 @@
 
 This is available only on NUMA kernels.
 
-A percentage of the total pages in each zone.  Zone reclaim will only
-occur if more than this percentage of pages are file backed and unmapped.
-This is to insure that a minimal amount of local pages is still available for
-file I/O even if the node is overallocated.
+This is a percentage of the total pages in each zone. Zone reclaim will
+only occur if more than this percentage of pages are in a state that
+zone_reclaim_mode allows to be reclaimed.
+
+If zone_reclaim_mode has the value 4 OR'd, then the percentage is compared
+against all file-backed unmapped pages including swapcache pages and tmpfs
+files. Otherwise, only unmapped pages backed by normal files but not tmpfs
+files and similar are considered.
 
 The default is 1 percent.
 
@@ -358,7 +363,7 @@
 The current number of pdflush threads.  This value is read-only.
 The value changes according to the number of dirty pages in the system.
 
-When neccessary, additional pdflush threads are created, one per second, up to
+When necessary, additional pdflush threads are created, one per second, up to
 nr_pdflush_threads_max.
 
 ==============================================================
@@ -565,7 +570,7 @@
 
 This control is used to define how aggressive the kernel will swap
 memory pages.  Higher values will increase agressiveness, lower values
-descrease the amount of swap.
+decrease the amount of swap.
 
 The default value is 60.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/sysrq.txt linux-libre-2.6.31-gnu/Documentation/sysrq.txt
--- linux-libre-2.6.30-gnu/Documentation/sysrq.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/sysrq.txt	2009-09-09 18:13:59.000000000 -0400
@@ -66,7 +66,8 @@
 'b'     - Will immediately reboot the system without syncing or unmounting
           your disks.
 
-'c'	- Will perform a kexec reboot in order to take a crashdump.
+'c'	- Will perform a system crash by a NULL pointer dereference.
+          A crashdump will be taken if configured.
 
 'd'	- Shows all locks that are held.
 
@@ -141,8 +142,8 @@
 re'B'oot is good when you're unable to shut down. But you should also 'S'ync
 and 'U'mount first.
 
-'C'rashdump can be used to manually trigger a crashdump when the system is hung.
-The kernel needs to have been built with CONFIG_KEXEC enabled.
+'C'rash can be used to manually trigger a crashdump when the system is hung.
+Note that this just triggers a crash if there is no dump mechanism available.
 
 'S'ync is great when your system is locked up, it allows you to sync your
 disks and will certainly lessen the chance of data loss and fscking. Note
diff -druN linux-libre-2.6.30-gnu/Documentation/timers/hpet.txt linux-libre-2.6.31-gnu/Documentation/timers/hpet.txt
--- linux-libre-2.6.30-gnu/Documentation/timers/hpet.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/timers/hpet.txt	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
 
 Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
 and up to 32 comparators.  Normally three or more comparators are provided,
-each of which can generate oneshot interupts and at least one of which has
+each of which can generate oneshot interrupts and at least one of which has
 additional hardware to support periodic interrupts.  The comparators are
 also called "timers", which can be misleading since usually timers are
 independent of each other ... these share a counter, complicating resets.
diff -druN linux-libre-2.6.30-gnu/Documentation/timers/timer_stats.txt linux-libre-2.6.31-gnu/Documentation/timers/timer_stats.txt
--- linux-libre-2.6.30-gnu/Documentation/timers/timer_stats.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/timers/timer_stats.txt	2009-09-09 18:13:59.000000000 -0400
@@ -62,7 +62,7 @@
 
 The first column is the number of events, the second column the pid, the third
 column is the name of the process. The forth column shows the function which
-initialized the timer and in parantheses the callback function which was
+initialized the timer and in parenthesis the callback function which was
 executed on expiry.
 
     Thomas, Ingo
diff -druN linux-libre-2.6.30-gnu/Documentation/trace/events.txt linux-libre-2.6.31-gnu/Documentation/trace/events.txt
--- linux-libre-2.6.30-gnu/Documentation/trace/events.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/trace/events.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,90 @@
+			     Event Tracing
+
+		Documentation written by Theodore Ts'o
+			Updated by Li Zefan
+
+1. Introduction
+===============
+
+Tracepoints (see Documentation/trace/tracepoints.txt) can be used
+without creating custom kernel modules to register probe functions
+using the event tracing infrastructure.
+
+Not all tracepoints can be traced using the event tracing system;
+the kernel developer must provide code snippets which define how the
+tracing information is saved into the tracing buffer, and how the
+tracing information should be printed.
+
+2. Using Event Tracing
+======================
+
+2.1 Via the 'set_event' interface
+---------------------------------
+
+The events which are available for tracing can be found in the file
+/debug/tracing/available_events.
+
+To enable a particular event, such as 'sched_wakeup', simply echo it
+to /debug/tracing/set_event. For example:
+
+	# echo sched_wakeup >> /debug/tracing/set_event
+
+[ Note: '>>' is necessary, otherwise it will firstly disable
+  all the events. ]
+
+To disable an event, echo the event name to the set_event file prefixed
+with an exclamation point:
+
+	# echo '!sched_wakeup' >> /debug/tracing/set_event
+
+To disable all events, echo an empty line to the set_event file:
+
+	# echo > /debug/tracing/set_event
+
+To enable all events, echo '*:*' or '*:' to the set_event file:
+
+	# echo *:* > /debug/tracing/set_event
+
+The events are organized into subsystems, such as ext4, irq, sched,
+etc., and a full event name looks like this: <subsystem>:<event>.  The
+subsystem name is optional, but it is displayed in the available_events
+file.  All of the events in a subsystem can be specified via the syntax
+"<subsystem>:*"; for example, to enable all irq events, you can use the
+command:
+
+	# echo 'irq:*' > /debug/tracing/set_event
+
+2.2 Via the 'enable' toggle
+---------------------------
+
+The events available are also listed in /debug/tracing/events/ hierarchy
+of directories.
+
+To enable event 'sched_wakeup':
+
+	# echo 1 > /debug/tracing/events/sched/sched_wakeup/enable
+
+To disable it:
+
+	# echo 0 > /debug/tracing/events/sched/sched_wakeup/enable
+
+To enable all events in sched subsystem:
+
+	# echo 1 > /debug/tracing/events/sched/enable
+
+To eanble all events:
+
+	# echo 1 > /debug/tracing/events/enable
+
+When reading one of these enable files, there are four results:
+
+ 0 - all events this file affects are disabled
+ 1 - all events this file affects are enabled
+ X - there is a mixture of events enabled and disabled
+ ? - this file does not affect any event
+
+3. Defining an event-enabled tracepoint
+=======================================
+
+See The example provided in samples/trace_events
+
diff -druN linux-libre-2.6.30-gnu/Documentation/trace/ftrace.txt linux-libre-2.6.31-gnu/Documentation/trace/ftrace.txt
--- linux-libre-2.6.30-gnu/Documentation/trace/ftrace.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/trace/ftrace.txt	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,6 @@
                (dual licensed under the GPL v2)
 Reviewers:   Elias Oltmanns, Randy Dunlap, Andrew Morton,
 	     John Kacur, and David Teigland.
-
 Written for: 2.6.28-rc2
 
 Introduction
@@ -33,13 +32,26 @@
 Ftrace uses the debugfs file system to hold the control files as
 well as the files to display output.
 
-To mount the debugfs system:
+When debugfs is configured into the kernel (which selecting any ftrace
+option will do) the directory /sys/kernel/debug will be created. To mount
+this directory, you can add to your /etc/fstab file:
 
-  # mkdir /debug
-  # mount -t debugfs nodev /debug
+ debugfs       /sys/kernel/debug          debugfs defaults        0       0
 
-( Note: it is more common to mount at /sys/kernel/debug, but for
-  simplicity this document will use /debug)
+Or you can mount it at run time with:
+
+ mount -t debugfs nodev /sys/kernel/debug
+
+For quicker access to that directory you may want to make a soft link to
+it:
+
+ ln -s /sys/kernel/debug /debug
+
+Any selected ftrace option will also create a directory called tracing
+within the debugfs. The rest of the document will assume that you are in
+the ftrace directory (cd /sys/kernel/debug/tracing) and will only concentrate
+on the files within that directory and not distract from the content with
+the extended "/sys/kernel/debug/tracing" path name.
 
 That's it! (assuming that you have ftrace configured into your kernel)
 
@@ -179,7 +191,7 @@
 
 	Function call tracer to trace all kernel functions.
 
-  "function_graph_tracer"
+  "function_graph"
 
 	Similar to the function tracer except that the
 	function tracer probes the functions on their entry
@@ -389,18 +401,18 @@
 The trace_options file is used to control what gets printed in
 the trace output. To see what is available, simply cat the file:
 
-  cat /debug/tracing/trace_options
+  cat trace_options
   print-parent nosym-offset nosym-addr noverbose noraw nohex nobin \
   noblock nostacktrace nosched-tree nouserstacktrace nosym-userobj
 
 To disable one of the options, echo in the option prepended with
 "no".
 
-  echo noprint-parent > /debug/tracing/trace_options
+  echo noprint-parent > trace_options
 
 To enable an option, leave off the "no".
 
-  echo sym-offset > /debug/tracing/trace_options
+  echo sym-offset > trace_options
 
 Here are the available options:
 
@@ -476,11 +488,11 @@
 This tracer simply records schedule switches. Here is an example
 of how to use it.
 
- # echo sched_switch > /debug/tracing/current_tracer
- # echo 1 > /debug/tracing/tracing_enabled
+ # echo sched_switch > current_tracer
+ # echo 1 > tracing_enabled
  # sleep 1
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/trace
+ # echo 0 > tracing_enabled
+ # cat trace
 
 # tracer: sched_switch
 #
@@ -518,9 +530,18 @@
 values starting at 100 (nice -20). Below is a quick chart to map
 the kernel priority to user land priorities.
 
-  Kernel priority: 0 to 99    ==> user RT priority 99 to 0
-  Kernel priority: 100 to 139 ==> user nice -20 to 19
-  Kernel priority: 140        ==> idle task priority
+   Kernel Space                     User Space
+ ===============================================================
+   0(high) to  98(low)     user RT priority 99(high) to 1(low)
+                           with SCHED_RR or SCHED_FIFO
+ ---------------------------------------------------------------
+  99                       sched_priority is not used in scheduling
+                           decisions(it must be specified as 0)
+ ---------------------------------------------------------------
+ 100(high) to 139(low)     user nice -20(high) to 19(low)
+ ---------------------------------------------------------------
+ 140                       idle task priority
+ ---------------------------------------------------------------
 
 The task states are:
 
@@ -574,13 +595,13 @@
 To reset the maximum, echo 0 into tracing_max_latency. Here is
 an example:
 
- # echo irqsoff > /debug/tracing/current_tracer
- # echo 0 > /debug/tracing/tracing_max_latency
- # echo 1 > /debug/tracing/tracing_enabled
+ # echo irqsoff > current_tracer
+ # echo 0 > tracing_max_latency
+ # echo 1 > tracing_enabled
  # ls -ltr
  [...]
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/latency_trace
+ # echo 0 > tracing_enabled
+ # cat latency_trace
 # tracer: irqsoff
 #
 irqsoff latency trace v1.1.5 on 2.6.26
@@ -681,13 +702,13 @@
 which preemption was disabled. The control of preemptoff tracer
 is much like the irqsoff tracer.
 
- # echo preemptoff > /debug/tracing/current_tracer
- # echo 0 > /debug/tracing/tracing_max_latency
- # echo 1 > /debug/tracing/tracing_enabled
+ # echo preemptoff > current_tracer
+ # echo 0 > tracing_max_latency
+ # echo 1 > tracing_enabled
  # ls -ltr
  [...]
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/latency_trace
+ # echo 0 > tracing_enabled
+ # cat latency_trace
 # tracer: preemptoff
 #
 preemptoff latency trace v1.1.5 on 2.6.26-rc8
@@ -828,13 +849,13 @@
 Again, using this trace is much like the irqsoff and preemptoff
 tracers.
 
- # echo preemptirqsoff > /debug/tracing/current_tracer
- # echo 0 > /debug/tracing/tracing_max_latency
- # echo 1 > /debug/tracing/tracing_enabled
+ # echo preemptirqsoff > current_tracer
+ # echo 0 > tracing_max_latency
+ # echo 1 > tracing_enabled
  # ls -ltr
  [...]
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/latency_trace
+ # echo 0 > tracing_enabled
+ # cat latency_trace
 # tracer: preemptirqsoff
 #
 preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8
@@ -990,12 +1011,12 @@
 Instead of performing an 'ls', we will run 'sleep 1' under
 'chrt' which changes the priority of the task.
 
- # echo wakeup > /debug/tracing/current_tracer
- # echo 0 > /debug/tracing/tracing_max_latency
- # echo 1 > /debug/tracing/tracing_enabled
+ # echo wakeup > current_tracer
+ # echo 0 > tracing_max_latency
+ # echo 1 > tracing_enabled
  # chrt -f 5 sleep 1
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/latency_trace
+ # echo 0 > tracing_enabled
+ # cat latency_trace
 # tracer: wakeup
 #
 wakeup latency trace v1.1.5 on 2.6.26-rc8
@@ -1105,11 +1126,11 @@
 ftrace_enabled is set; otherwise this tracer is a nop.
 
  # sysctl kernel.ftrace_enabled=1
- # echo function > /debug/tracing/current_tracer
- # echo 1 > /debug/tracing/tracing_enabled
+ # echo function > current_tracer
+ # echo 1 > tracing_enabled
  # usleep 1
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/trace
+ # echo 0 > tracing_enabled
+ # cat trace
 # tracer: function
 #
 #           TASK-PID   CPU#    TIMESTAMP  FUNCTION
@@ -1146,7 +1167,7 @@
 [...]
 int main(int argc, char *argv[]) {
 	[...]
-	trace_fd = open("/debug/tracing/tracing_enabled", O_WRONLY);
+	trace_fd = open(tracing_file("tracing_enabled"), O_WRONLY);
 	[...]
 	if (condition_hit()) {
 		write(trace_fd, "0", 1);
@@ -1154,26 +1175,20 @@
 	[...]
 }
 
-Note: Here we hard coded the path name. The debugfs mount is not
-guaranteed to be at /debug (and is more commonly at
-/sys/kernel/debug). For simple one time traces, the above is
-sufficent. For anything else, a search through /proc/mounts may
-be needed to find where the debugfs file-system is mounted.
-
 
 Single thread tracing
 ---------------------
 
-By writing into /debug/tracing/set_ftrace_pid you can trace a
+By writing into set_ftrace_pid you can trace a
 single thread. For example:
 
-# cat /debug/tracing/set_ftrace_pid
+# cat set_ftrace_pid
 no pid
-# echo 3111 > /debug/tracing/set_ftrace_pid
-# cat /debug/tracing/set_ftrace_pid
+# echo 3111 > set_ftrace_pid
+# cat set_ftrace_pid
 3111
-# echo function > /debug/tracing/current_tracer
-# cat /debug/tracing/trace | head
+# echo function > current_tracer
+# cat trace | head
  # tracer: function
  #
  #           TASK-PID    CPU#    TIMESTAMP  FUNCTION
@@ -1184,8 +1199,8 @@
      yum-updatesd-3111  [003]  1637.254683: lock_hrtimer_base <-hrtimer_try_to_cancel
      yum-updatesd-3111  [003]  1637.254685: fget_light <-do_sys_poll
      yum-updatesd-3111  [003]  1637.254686: pipe_poll <-do_sys_poll
-# echo -1 > /debug/tracing/set_ftrace_pid
-# cat /debug/tracing/trace |head
+# echo -1 > set_ftrace_pid
+# cat trace |head
  # tracer: function
  #
  #           TASK-PID    CPU#    TIMESTAMP  FUNCTION
@@ -1207,6 +1222,51 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#define _STR(x) #x
+#define STR(x) _STR(x)
+#define MAX_PATH 256
+
+const char *find_debugfs(void)
+{
+       static char debugfs[MAX_PATH+1];
+       static int debugfs_found;
+       char type[100];
+       FILE *fp;
+
+       if (debugfs_found)
+               return debugfs;
+
+       if ((fp = fopen("/proc/mounts","r")) == NULL) {
+               perror("/proc/mounts");
+               return NULL;
+       }
+
+       while (fscanf(fp, "%*s %"
+                     STR(MAX_PATH)
+                     "s %99s %*s %*d %*d\n",
+                     debugfs, type) == 2) {
+               if (strcmp(type, "debugfs") == 0)
+                       break;
+       }
+       fclose(fp);
+
+       if (strcmp(type, "debugfs") != 0) {
+               fprintf(stderr, "debugfs not mounted");
+               return NULL;
+       }
+
+       debugfs_found = 1;
+
+       return debugfs;
+}
+
+const char *tracing_file(const char *file_name)
+{
+       static char trace_file[MAX_PATH+1];
+       snprintf(trace_file, MAX_PATH, "%s/%s", find_debugfs(), file_name);
+       return trace_file;
+}
+
 int main (int argc, char **argv)
 {
         if (argc < 1)
@@ -1217,12 +1277,12 @@
                 char line[64];
                 int s;
 
-                ffd = open("/debug/tracing/current_tracer", O_WRONLY);
+                ffd = open(tracing_file("current_tracer"), O_WRONLY);
                 if (ffd < 0)
                         exit(-1);
                 write(ffd, "nop", 3);
 
-                fd = open("/debug/tracing/set_ftrace_pid", O_WRONLY);
+                fd = open(tracing_file("set_ftrace_pid"), O_WRONLY);
                 s = sprintf(line, "%d\n", getpid());
                 write(fd, line, s);
 
@@ -1374,22 +1434,22 @@
   tracing_cpu_mask file) or you might sometimes see unordered
   function calls while cpu tracing switch.
 
-	hide: echo nofuncgraph-cpu > /debug/tracing/trace_options
-	show: echo funcgraph-cpu > /debug/tracing/trace_options
+	hide: echo nofuncgraph-cpu > trace_options
+	show: echo funcgraph-cpu > trace_options
 
 - The duration (function's time of execution) is displayed on
   the closing bracket line of a function or on the same line
   than the current function in case of a leaf one. It is default
   enabled.
 
-	hide: echo nofuncgraph-duration > /debug/tracing/trace_options
-	show: echo funcgraph-duration > /debug/tracing/trace_options
+	hide: echo nofuncgraph-duration > trace_options
+	show: echo funcgraph-duration > trace_options
 
 - The overhead field precedes the duration field in case of
   reached duration thresholds.
 
-	hide: echo nofuncgraph-overhead > /debug/tracing/trace_options
-	show: echo funcgraph-overhead > /debug/tracing/trace_options
+	hide: echo nofuncgraph-overhead > trace_options
+	show: echo funcgraph-overhead > trace_options
 	depends on: funcgraph-duration
 
   ie:
@@ -1418,8 +1478,8 @@
 - The task/pid field displays the thread cmdline and pid which
   executed the function. It is default disabled.
 
-	hide: echo nofuncgraph-proc > /debug/tracing/trace_options
-	show: echo funcgraph-proc > /debug/tracing/trace_options
+	hide: echo nofuncgraph-proc > trace_options
+	show: echo funcgraph-proc > trace_options
 
   ie:
 
@@ -1442,8 +1502,8 @@
   system clock since it started. A snapshot of this time is
   given on each entry/exit of functions
 
-	hide: echo nofuncgraph-abstime > /debug/tracing/trace_options
-	show: echo funcgraph-abstime > /debug/tracing/trace_options
+	hide: echo nofuncgraph-abstime > trace_options
+	show: echo funcgraph-abstime > trace_options
 
   ie:
 
@@ -1540,7 +1600,7 @@
 
    available_filter_functions
 
- # cat /debug/tracing/available_filter_functions
+ # cat available_filter_functions
 put_prev_task_idle
 kmem_cache_create
 pick_next_task_rt
@@ -1552,12 +1612,12 @@
 If I am only interested in sys_nanosleep and hrtimer_interrupt:
 
  # echo sys_nanosleep hrtimer_interrupt \
-		> /debug/tracing/set_ftrace_filter
- # echo ftrace > /debug/tracing/current_tracer
- # echo 1 > /debug/tracing/tracing_enabled
+		> set_ftrace_filter
+ # echo ftrace > current_tracer
+ # echo 1 > tracing_enabled
  # usleep 1
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/trace
+ # echo 0 > tracing_enabled
+ # cat trace
 # tracer: ftrace
 #
 #           TASK-PID   CPU#    TIMESTAMP  FUNCTION
@@ -1568,7 +1628,7 @@
 
 To see which functions are being traced, you can cat the file:
 
- # cat /debug/tracing/set_ftrace_filter
+ # cat set_ftrace_filter
 hrtimer_interrupt
 sys_nanosleep
 
@@ -1588,7 +1648,7 @@
       otherwise the shell may expand the parameters into names
       of files in the local directory.
 
- # echo 'hrtimer_*' > /debug/tracing/set_ftrace_filter
+ # echo 'hrtimer_*' > set_ftrace_filter
 
 Produces:
 
@@ -1609,7 +1669,7 @@
 
 Notice that we lost the sys_nanosleep.
 
- # cat /debug/tracing/set_ftrace_filter
+ # cat set_ftrace_filter
 hrtimer_run_queues
 hrtimer_run_pending
 hrtimer_init
@@ -1635,17 +1695,17 @@
 To clear out a filter so that all functions will be recorded
 again:
 
- # echo > /debug/tracing/set_ftrace_filter
- # cat /debug/tracing/set_ftrace_filter
+ # echo > set_ftrace_filter
+ # cat set_ftrace_filter
  #
 
 Again, now we want to append.
 
- # echo sys_nanosleep > /debug/tracing/set_ftrace_filter
- # cat /debug/tracing/set_ftrace_filter
+ # echo sys_nanosleep > set_ftrace_filter
+ # cat set_ftrace_filter
 sys_nanosleep
- # echo 'hrtimer_*' >> /debug/tracing/set_ftrace_filter
- # cat /debug/tracing/set_ftrace_filter
+ # echo 'hrtimer_*' >> set_ftrace_filter
+ # cat set_ftrace_filter
 hrtimer_run_queues
 hrtimer_run_pending
 hrtimer_init
@@ -1668,7 +1728,7 @@
 The set_ftrace_notrace prevents those functions from being
 traced.
 
- # echo '*preempt*' '*lock*' > /debug/tracing/set_ftrace_notrace
+ # echo '*preempt*' '*lock*' > set_ftrace_notrace
 
 Produces:
 
@@ -1758,13 +1818,13 @@
 trace_pipe is consumed. This means that subsequent reads will be
 different. The trace is live.
 
- # echo function > /debug/tracing/current_tracer
- # cat /debug/tracing/trace_pipe > /tmp/trace.out &
+ # echo function > current_tracer
+ # cat trace_pipe > /tmp/trace.out &
 [1] 4153
- # echo 1 > /debug/tracing/tracing_enabled
+ # echo 1 > tracing_enabled
  # usleep 1
- # echo 0 > /debug/tracing/tracing_enabled
- # cat /debug/tracing/trace
+ # echo 0 > tracing_enabled
+ # cat trace
 # tracer: function
 #
 #           TASK-PID   CPU#    TIMESTAMP  FUNCTION
@@ -1800,7 +1860,7 @@
 CPU. To know the full size, multiply the number of possible CPUS
 with the number of entries.
 
- # cat /debug/tracing/buffer_size_kb
+ # cat buffer_size_kb
 1408 (units kilobytes)
 
 Note, to modify this, you must have tracing completely disabled.
@@ -1808,21 +1868,21 @@
 current_tracer is not set to "nop", an EINVAL error will be
 returned.
 
- # echo nop > /debug/tracing/current_tracer
- # echo 10000 > /debug/tracing/buffer_size_kb
- # cat /debug/tracing/buffer_size_kb
+ # echo nop > current_tracer
+ # echo 10000 > buffer_size_kb
+ # cat buffer_size_kb
 10000 (units kilobytes)
 
 The number of pages which will be allocated is limited to a
 percentage of available memory. Allocating too much will produce
 an error.
 
- # echo 1000000000000 > /debug/tracing/buffer_size_kb
+ # echo 1000000000000 > buffer_size_kb
 -bash: echo: write error: Cannot allocate memory
- # cat /debug/tracing/buffer_size_kb
+ # cat buffer_size_kb
 85
 
 -----------
 
 More details can be found in the source code, in the
-kernel/tracing/*.c files.
+kernel/trace/*.c files.
diff -druN linux-libre-2.6.30-gnu/Documentation/trace/kmemtrace.txt linux-libre-2.6.31-gnu/Documentation/trace/kmemtrace.txt
--- linux-libre-2.6.30-gnu/Documentation/trace/kmemtrace.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/trace/kmemtrace.txt	2009-09-09 18:13:59.000000000 -0400
@@ -64,7 +64,7 @@
 CONFIG_KMEMTRACE).
 
 2) Get the userspace tool and build it:
-$ git-clone git://repo.or.cz/kmemtrace-user.git		# current repository
+$ git clone git://repo.or.cz/kmemtrace-user.git		# current repository
 $ cd kmemtrace-user/
 $ ./autogen.sh
 $ ./configure
diff -druN linux-libre-2.6.30-gnu/Documentation/trace/mmiotrace.txt linux-libre-2.6.31-gnu/Documentation/trace/mmiotrace.txt
--- linux-libre-2.6.30-gnu/Documentation/trace/mmiotrace.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/trace/mmiotrace.txt	2009-09-09 18:13:59.000000000 -0400
@@ -32,41 +32,41 @@
 Usage Quick Reference
 ---------------------
 
-$ mount -t debugfs debugfs /debug
-$ echo mmiotrace > /debug/tracing/current_tracer
-$ cat /debug/tracing/trace_pipe > mydump.txt &
+$ mount -t debugfs debugfs /sys/kernel/debug
+$ echo mmiotrace > /sys/kernel/debug/tracing/current_tracer
+$ cat /sys/kernel/debug/tracing/trace_pipe > mydump.txt &
 Start X or whatever.
-$ echo "X is up" > /debug/tracing/trace_marker
-$ echo nop > /debug/tracing/current_tracer
+$ echo "X is up" > /sys/kernel/debug/tracing/trace_marker
+$ echo nop > /sys/kernel/debug/tracing/current_tracer
 Check for lost events.
 
 
 Usage
 -----
 
-Make sure debugfs is mounted to /debug. If not, (requires root privileges)
-$ mount -t debugfs debugfs /debug
+Make sure debugfs is mounted to /sys/kernel/debug. If not, (requires root privileges)
+$ mount -t debugfs debugfs /sys/kernel/debug
 
 Check that the driver you are about to trace is not loaded.
 
 Activate mmiotrace (requires root privileges):
-$ echo mmiotrace > /debug/tracing/current_tracer
+$ echo mmiotrace > /sys/kernel/debug/tracing/current_tracer
 
 Start storing the trace:
-$ cat /debug/tracing/trace_pipe > mydump.txt &
+$ cat /sys/kernel/debug/tracing/trace_pipe > mydump.txt &
 The 'cat' process should stay running (sleeping) in the background.
 
 Load the driver you want to trace and use it. Mmiotrace will only catch MMIO
 accesses to areas that are ioremapped while mmiotrace is active.
 
 During tracing you can place comments (markers) into the trace by
-$ echo "X is up" > /debug/tracing/trace_marker
+$ echo "X is up" > /sys/kernel/debug/tracing/trace_marker
 This makes it easier to see which part of the (huge) trace corresponds to
 which action. It is recommended to place descriptive markers about what you
 do.
 
 Shut down mmiotrace (requires root privileges):
-$ echo nop > /debug/tracing/current_tracer
+$ echo nop > /sys/kernel/debug/tracing/current_tracer
 The 'cat' process exits. If it does not, kill it by issuing 'fg' command and
 pressing ctrl+c.
 
@@ -78,10 +78,10 @@
 events were lost, the trace is incomplete. You should enlarge the buffers and
 try again. Buffers are enlarged by first seeing how large the current buffers
 are:
-$ cat /debug/tracing/buffer_size_kb
+$ cat /sys/kernel/debug/tracing/buffer_size_kb
 gives you a number. Approximately double this number and write it back, for
 instance:
-$ echo 128000 > /debug/tracing/buffer_size_kb
+$ echo 128000 > /sys/kernel/debug/tracing/buffer_size_kb
 Then start again from the top.
 
 If you are doing a trace for a driver project, e.g. Nouveau, you should also
diff -druN linux-libre-2.6.30-gnu/Documentation/trace/power.txt linux-libre-2.6.31-gnu/Documentation/trace/power.txt
--- linux-libre-2.6.30-gnu/Documentation/trace/power.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/trace/power.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,17 @@
+The power tracer collects detailed information about C-state and P-state
+transitions, instead of just looking at the high-level "average"
+information.
+
+There is a helper script found in scrips/tracing/power.pl in the kernel
+sources which can be used to parse this information and create a
+Scalable Vector Graphics (SVG) picture from the trace data.
+
+To use this tracer:
+
+	echo 0 > /sys/kernel/debug/tracing/tracing_enabled
+	echo power > /sys/kernel/debug/tracing/current_tracer
+	echo 1 > /sys/kernel/debug/tracing/tracing_enabled
+	sleep 1
+	echo 0 > /sys/kernel/debug/tracing/tracing_enabled
+	cat /sys/kernel/debug/tracing/trace | \
+		perl scripts/tracing/power.pl > out.sv
diff -druN linux-libre-2.6.30-gnu/Documentation/usb/anchors.txt linux-libre-2.6.31-gnu/Documentation/usb/anchors.txt
--- linux-libre-2.6.30-gnu/Documentation/usb/anchors.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/usb/anchors.txt	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,7 @@
 
 An association of URBs to an anchor is made by an explicit
 call to usb_anchor_urb(). The association is maintained until
-an URB is finished by (successfull) completion. Thus disassociation
+an URB is finished by (successful) completion. Thus disassociation
 is automatic. A function is provided to forcibly finish (kill)
 all URBs associated with an anchor.
 Furthermore, disassociation can be made with usb_unanchor_urb()
@@ -76,4 +76,4 @@
 Returns the oldest anchored URB of an anchor. The URB is unanchored
 and returned with a reference. As you may mix URBs to several
 destinations in one anchor you have no guarantee the chronologically
-first submitted URB is returned.
\ No newline at end of file
+first submitted URB is returned.
diff -druN linux-libre-2.6.30-gnu/Documentation/usb/callbacks.txt linux-libre-2.6.31-gnu/Documentation/usb/callbacks.txt
--- linux-libre-2.6.30-gnu/Documentation/usb/callbacks.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/usb/callbacks.txt	2009-09-09 18:13:59.000000000 -0400
@@ -65,7 +65,7 @@
 otherwise -ENODEV or -ENXIO. Other error codes should be used only if a
 genuine error occurred during initialisation which prevented a driver
 from accepting a device that would else have been accepted.
-You are strongly encouraged to use usbcore'sfacility,
+You are strongly encouraged to use usbcore's facility,
 usb_set_intfdata(), to associate a data structure with an interface, so
 that you know which internal state and identity you associate with a
 particular interface. The device will not be suspended and you may do IO
diff -druN linux-libre-2.6.30-gnu/Documentation/usb/WUSB-Design-overview.txt linux-libre-2.6.31-gnu/Documentation/usb/WUSB-Design-overview.txt
--- linux-libre-2.6.30-gnu/Documentation/usb/WUSB-Design-overview.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/usb/WUSB-Design-overview.txt	2009-09-09 18:13:59.000000000 -0400
@@ -84,7 +84,7 @@
 
       *UWB*: the Ultra-Wide-Band stack -- manages the radio and
       associated spectrum to allow for devices sharing it. Allows to
-      control bandwidth assingment, beaconing, scanning, etc
+      control bandwidth assignment, beaconing, scanning, etc
 
     *
 
@@ -184,7 +184,7 @@
 [/uwb_rc_neh_grok()/]. Notifications are handled to the UWB daemon, that
 is chartered, among other things, to keep the tab of how the UWB radio
 neighborhood looks, creating and destroying devices as they show up or
-dissapear.
+disappear.
 
 Command execution is very simple: a command block is sent and a event
 block or reply is expected back. For sending/receiving command/events, a
@@ -333,7 +333,7 @@
 
 *Device life cycle and keep alives*
 
-Everytime there is a succesful transfer to/from a device, we update a
+Every time there is a successful transfer to/from a device, we update a
 per-device activity timestamp. If not, every now and then we check and
 if the activity timestamp gets old, we ping the device by sending it a
 Keep Alive IE; it responds with a /DN_Alive/ pong during the DNTS (this
@@ -411,7 +411,7 @@
 called and we assign the status bits and release the xfer resources.
 
 In dequeue() we are basically cancelling/aborting the transfer. We issue
-a xfer abort request to the HC, cancell all the URBs we had submitted
+a xfer abort request to the HC, cancel all the URBs we had submitted
 and not yet done and when all that is done, the xfer callback will be
 called--this will call the URB callback.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.cx23885 linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.cx23885
--- linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.cx23885	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.cx23885	2009-09-09 18:13:59.000000000 -0400
@@ -16,3 +16,8 @@
  15 -> TeVii S470                                          [d470:9022]
  16 -> DVBWorld DVB-S2 2005                                [0001:2005]
  17 -> NetUP Dual DVB-S2 CI                                [1b55:2a2c]
+ 18 -> Hauppauge WinTV-HVR1270                             [0070:2211]
+ 19 -> Hauppauge WinTV-HVR1275                             [0070:2215]
+ 20 -> Hauppauge WinTV-HVR1255                             [0070:2251]
+ 21 -> Hauppauge WinTV-HVR1210                             [0070:2291,0070:2295]
+ 22 -> Mygica X8506 DMB-TH                                 [14f1:8651]
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.cx88 linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.cx88
--- linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.cx88	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.cx88	2009-09-09 18:13:59.000000000 -0400
@@ -6,8 +6,8 @@
   5 -> Leadtek Winfast 2000XP Expert                       [107d:6611,107d:6613]
   6 -> AverTV Studio 303 (M126)                            [1461:000b]
   7 -> MSI TV-@nywhere Master                              [1462:8606]
-  8 -> Leadtek Winfast DV2000                              [107d:6620]
-  9 -> Leadtek PVR 2000                                    [107d:663b,107d:663c,107d:6632]
+  8 -> Leadtek Winfast DV2000                              [107d:6620,107d:6621]
+  9 -> Leadtek PVR 2000                                    [107d:663b,107d:663c,107d:6632,107d:6630,107d:6638,107d:6631,107d:6637,107d:663d]
  10 -> IODATA GV-VCP3/PCI                                  [10fc:d003]
  11 -> Prolink PlayTV PVR
  12 -> ASUS PVR-416                                        [1043:4823,1461:c111]
@@ -59,7 +59,7 @@
  58 -> Pinnacle PCTV HD 800i                               [11bd:0051]
  59 -> DViCO FusionHDTV 5 PCI nano                         [18ac:d530]
  60 -> Pinnacle Hybrid PCTV                                [12ab:1788]
- 61 -> Winfast TV2000 XP Global                            [107d:6f18]
+ 61 -> Leadtek TV2000 XP Global                            [107d:6f18,107d:6618]
  62 -> PowerColor RA330                                    [14f1:ea3d]
  63 -> Geniatech X8000-MT DVBT                             [14f1:8852]
  64 -> DViCO FusionHDTV DVB-T PRO                          [18ac:db30]
@@ -78,3 +78,5 @@
  77 -> TBS 8910 DVB-S                                      [8910:8888]
  78 -> Prof 6200 DVB-S                                     [b022:3022]
  79 -> Terratec Cinergy HT PCI MKII                        [153b:1177]
+ 80 -> Hauppauge WinTV-IR Only                             [0070:9290]
+ 81 -> Leadtek WinFast DTV1800 Hybrid                      [107d:6654]
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.em28xx linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.em28xx
--- linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.em28xx	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.em28xx	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
   0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
-  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
+  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
   2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
   3 -> Pinnacle PCTV USB 2                      (em2820/em2840) [2304:0208]
   4 -> Hauppauge WinTV USB 2                    (em2820/em2840) [2040:4200,2040:4201]
@@ -17,10 +17,10 @@
  16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b]
  17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
  18 -> Hauppauge WinTV HVR 900 (R2)             (em2880)        [2040:6502]
- 19 -> PointNix Intra-Oral Camera               (em2860)
+ 19 -> EM2860/SAA711X Reference Design          (em2860)
  20 -> AMD ATI TV Wonder HD 600                 (em2880)        [0438:b002]
  21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800)        [eb1a:2801]
- 22 -> Unknown EM2750/EM2751 webcam grabber     (em2750)        [eb1a:2750,eb1a:2751]
+ 22 -> EM2710/EM2750/EM2751 webcam grabber      (em2750)        [eb1a:2750,eb1a:2751]
  23 -> Huaqi DLCW-130                           (em2750)
  24 -> D-Link DUB-T210 TV Tuner                 (em2820/em2840) [2001:f112]
  25 -> Gadmei UTV310                            (em2820/em2840)
@@ -61,3 +61,9 @@
  63 -> Kaiomy TVnPC U2                          (em2860)        [eb1a:e303]
  64 -> Easy Cap Capture DC-60                   (em2860)
  65 -> IO-DATA GV-MVP/SZ                        (em2820/em2840) [04bb:0515]
+ 66 -> Empire dual TV                           (em2880)
+ 67 -> Terratec Grabby                          (em2860)        [0ccd:0096]
+ 68 -> Terratec AV350                           (em2860)        [0ccd:0084]
+ 69 -> KWorld ATSC 315U HDTV TV Box             (em2882)        [eb1a:a313]
+ 70 -> Evga inDtube                             (em2882)
+ 71 -> Silvercrest Webcam 1.3mpix               (em2820/em2840)
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.saa7134 linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.saa7134
--- linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.saa7134	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.saa7134	2009-09-09 18:13:59.000000000 -0400
@@ -124,10 +124,10 @@
 123 -> Beholder BeholdTV 407                    [0000:4070]
 124 -> Beholder BeholdTV 407 FM                 [0000:4071]
 125 -> Beholder BeholdTV 409                    [0000:4090]
-126 -> Beholder BeholdTV 505 FM/RDS             [0000:5051,0000:505B,5ace:5050]
-127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
+126 -> Beholder BeholdTV 505 FM                 [5ace:5050]
+127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090]
 128 -> Beholder BeholdTV Columbus TVFM          [0000:5201]
-129 -> Beholder BeholdTV 607 / BeholdTV 609     [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
+129 -> Beholder BeholdTV 607 FM                 [5ace:6070]
 130 -> Beholder BeholdTV M6                     [5ace:6190]
 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
 132 -> Genius TVGO AM11MCE
@@ -143,7 +143,7 @@
 142 -> Beholder BeholdTV H6                     [5ace:6290]
 143 -> Beholder BeholdTV M63                    [5ace:6191]
 144 -> Beholder BeholdTV M6 Extra               [5ace:6193]
-145 -> AVerMedia MiniPCI DVB-T Hybrid M103      [1461:f636]
+145 -> AVerMedia MiniPCI DVB-T Hybrid M103      [1461:f636,1461:f736]
 146 -> ASUSTeK P7131 Analog
 147 -> Asus Tiger 3in1                          [1043:4878]
 148 -> Encore ENLTV-FM v5.3                     [1a7f:2008]
@@ -153,5 +153,17 @@
 152 -> Asus Tiger Rev:1.00                      [1043:4857]
 153 -> Kworld Plus TV Analog Lite PCI           [17de:7128]
 154 -> Avermedia AVerTV GO 007 FM Plus          [1461:f31d]
-155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid  [0070:6706,0070:6708]
-156 -> Hauppauge WinTV-HVR1110r3                [0070:6707,0070:6709,0070:670a]
+155 -> Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid  [0070:6706,0070:6708]
+156 -> Hauppauge WinTV-HVR1120 DVB-T/Hybrid     [0070:6707,0070:6709,0070:670a]
+157 -> Avermedia AVerTV Studio 507UA            [1461:a11b]
+158 -> AVerMedia Cardbus TV/Radio (E501R)       [1461:b7e9]
+159 -> Beholder BeholdTV 505 RDS                [0000:505B]
+160 -> Beholder BeholdTV 507 RDS                [0000:5071]
+161 -> Beholder BeholdTV 507 RDS                [0000:507B]
+162 -> Beholder BeholdTV 607 FM                 [5ace:6071]
+163 -> Beholder BeholdTV 609 FM                 [5ace:6090]
+164 -> Beholder BeholdTV 609 FM                 [5ace:6091]
+165 -> Beholder BeholdTV 607 RDS                [5ace:6072]
+166 -> Beholder BeholdTV 607 RDS                [5ace:6073]
+167 -> Beholder BeholdTV 609 RDS                [5ace:6092]
+168 -> Beholder BeholdTV 609 RDS                [5ace:6093]
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.tuner linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.tuner
--- linux-libre-2.6.30-gnu/Documentation/video4linux/CARDLIST.tuner	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/CARDLIST.tuner	2009-09-09 18:13:59.000000000 -0400
@@ -76,3 +76,5 @@
 tuner=76 - Xceive 5000 tuner
 tuner=77 - TCL tuner MF02GIP-5N-E
 tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
+tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
+tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/cx18.txt linux-libre-2.6.31-gnu/Documentation/video4linux/cx18.txt
--- linux-libre-2.6.30-gnu/Documentation/video4linux/cx18.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/cx18.txt	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,7 @@
 2) Some people have problems getting the i2c bus to work.
    The symptom is that the eeprom cannot be read and the card is
    unusable. This is probably fixed, but if you have problems
-   then post to the video4linux or ivtv-users mailinglist.
+   then post to the video4linux or ivtv-users mailing list.
 
 3) VBI (raw or sliced) has not yet been implemented.
 
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/gspca.txt linux-libre-2.6.31-gnu/Documentation/video4linux/gspca.txt
--- linux-libre-2.6.30-gnu/Documentation/video4linux/gspca.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/gspca.txt	2009-09-09 18:13:59.000000000 -0400
@@ -44,7 +44,9 @@
 zc3xx		0458:700c	Genius VideoCam V3
 zc3xx		0458:700f	Genius VideoCam Web V2
 sonixj		0458:7025	Genius Eye 311Q
+sn9c20x		0458:7029	Genius Look 320s
 sonixj		0458:702e	Genius Slim 310 NB
+sn9c20x		045e:00f4	LifeCam VX-6000 (SN9C20x + OV9650)
 sonixj		045e:00f5	MicroSoft VX3000
 sonixj		045e:00f7	MicroSoft VX1000
 ov519		045e:028c	Micro$oft xbox cam
@@ -163,10 +165,11 @@
 zc3xx		055f:d003	Mustek WCam300A
 zc3xx		055f:d004	Mustek WCam300 AN
 conex		0572:0041	Creative Notebook cx11646
-ov519		05a9:0519	OmniVision
+ov519		05a9:0519	OV519 Microphone
 ov519		05a9:0530	OmniVision
-ov519		05a9:4519	OmniVision
+ov519		05a9:4519	Webcam Classic
 ov519		05a9:8519	OmniVision
+ov519		05a9:a518	D-Link DSB-C310 Webcam
 sunplus		05da:1018	Digital Dream Enigma 1.3
 stk014		05e1:0893	Syntek DV4000
 spca561		060b:a001	Maxell Compact Pc PM3
@@ -178,6 +181,7 @@
 ov534		06f8:3002	Hercules Blog Webcam
 ov534		06f8:3003	Hercules Dualpix HD Weblog
 sonixj		06f8:3004	Hercules Classic Silver
+sonixj		06f8:3008	Hercules Deluxe Optical Glass
 spca508		0733:0110	ViewQuest VQ110
 spca508		0130:0130	Clone Digital Webcam 11043
 spca501		0733:0401	Intel Create and Share
@@ -209,6 +213,7 @@
 sunplus		08ca:2060	Aiptek PocketDV5300
 tv8532		0923:010f	ICM532 cams
 mars		093a:050f	Mars-Semi Pc-Camera
+mr97310a	093a:010f	Sakar Digital no. 77379
 pac207		093a:2460	Qtec Webcam 100
 pac207		093a:2461	HP Webcam
 pac207		093a:2463	Philips SPC 220 NC
@@ -265,6 +270,11 @@
 sonixj		0c45:60fb	Surfer NoName
 sonixj		0c45:60fc	LG-LIC300
 sonixj		0c45:60fe	Microdia Audio
+sonixj		0c45:6100	PC Camera (SN9C128)
+sonixj		0c45:610a	PC Camera (SN9C128)
+sonixj		0c45:610b	PC Camera (SN9C128)
+sonixj		0c45:610c	PC Camera (SN9C128)
+sonixj		0c45:610e	PC Camera (SN9C128)
 sonixj		0c45:6128	Microdia/Sonix SNP325
 sonixj		0c45:612a	Avant Camera
 sonixj		0c45:612c	Typhoon Rasy Cam 1.3MPix
@@ -274,6 +284,28 @@
 sonixj		0c45:613b	Surfer SN-206
 sonixj		0c45:613c	Sonix Pccam168
 sonixj		0c45:6143	Sonix Pccam168
+sn9c20x		0c45:6240	PC Camera (SN9C201 + MT9M001)
+sn9c20x		0c45:6242	PC Camera (SN9C201 + MT9M111)
+sn9c20x		0c45:6248	PC Camera (SN9C201 + OV9655)
+sn9c20x		0c45:624e	PC Camera (SN9C201 + SOI968)
+sn9c20x		0c45:624f	PC Camera (SN9C201 + OV9650)
+sn9c20x		0c45:6251	PC Camera (SN9C201 + OV9650)
+sn9c20x		0c45:6253	PC Camera (SN9C201 + OV9650)
+sn9c20x		0c45:6260	PC Camera (SN9C201 + OV7670)
+sn9c20x		0c45:6270	PC Camera (SN9C201 + MT9V011/MT9V111/MT9V112)
+sn9c20x		0c45:627b	PC Camera (SN9C201 + OV7660)
+sn9c20x		0c45:627c	PC Camera (SN9C201 + HV7131R)
+sn9c20x		0c45:627f	PC Camera (SN9C201 + OV9650)
+sn9c20x		0c45:6280	PC Camera (SN9C202 + MT9M001)
+sn9c20x		0c45:6282	PC Camera (SN9C202 + MT9M111)
+sn9c20x		0c45:6288	PC Camera (SN9C202 + OV9655)
+sn9c20x		0c45:628e	PC Camera (SN9C202 + SOI968)
+sn9c20x		0c45:628f	PC Camera (SN9C202 + OV9650)
+sn9c20x		0c45:62a0	PC Camera (SN9C202 + OV7670)
+sn9c20x		0c45:62b0	PC Camera (SN9C202 + MT9V011/MT9V111/MT9V112)
+sn9c20x		0c45:62b3	PC Camera (SN9C202 + OV9655)
+sn9c20x		0c45:62bb	PC Camera (SN9C202 + OV7660)
+sn9c20x		0c45:62bc	PC Camera (SN9C202 + HV7131R)
 sunplus		0d64:0303	Sunplus FashionCam DXG
 etoms		102c:6151	Qcam Sangha CIF
 etoms		102c:6251	Qcam xxxxxx VGA
@@ -282,6 +314,7 @@
 zc3xx		10fd:8050	Typhoon Webshot II USB 300k
 ov534		1415:2000	Sony HD Eye for PS3 (SLEH 00201)
 pac207		145f:013a	Trust WB-1300N
+sn9c20x		145f:013d	Trust WB-3600R
 vc032x		15b8:6001	HP 2.0 Megapixel
 vc032x		15b8:6002	HP 2.0 Megapixel rz406aa
 spca501		1776:501c	Arowana 300K CMOS Camera
@@ -292,4 +325,11 @@
 spca508		8086:0110	Intel Easy PC Camera
 spca500		8086:0630	Intel Pocket PC Camera
 spca506		99fa:8988	Grandtec V.cap
+sn9c20x		a168:0610	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x		a168:0611	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x		a168:0613	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x		a168:0618	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x		a168:0614	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
+sn9c20x		a168:0615	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
+sn9c20x		a168:0617	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
 spca561		abcd:cdee	Petcam
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/pxa_camera.txt linux-libre-2.6.31-gnu/Documentation/video4linux/pxa_camera.txt
--- linux-libre-2.6.30-gnu/Documentation/video4linux/pxa_camera.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/pxa_camera.txt	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,55 @@
 
      Once the last buffer is filled in, the QCI interface stops.
 
+  c) Capture global finite state machine schema
+
+      +----+                             +---+  +----+
+      | DQ |                             | Q |  | DQ |
+      |    v                             |   v  |    v
+    +-----------+                     +------------------------+
+    |   STOP    |                     | Wait for capture start |
+    +-----------+         Q           +------------------------+
++-> | QCI: stop | ------------------> | QCI: run               | <------------+
+|   | DMA: stop |                     | DMA: stop              |              |
+|   +-----------+             +-----> +------------------------+              |
+|                            /                            |                   |
+|                           /             +---+  +----+   |                   |
+|capture list empty        /              | Q |  | DQ |   | QCI Irq EOF       |
+|                         /               |   v  |    v   v                   |
+|   +--------------------+             +----------------------+               |
+|   | DMA hotlink missed |             |    Capture running   |               |
+|   +--------------------+             +----------------------+               |
+|   | QCI: run           |     +-----> | QCI: run             | <-+           |
+|   | DMA: stop          |    /        | DMA: run             |   |           |
+|   +--------------------+   /         +----------------------+   | Other     |
+|     ^                     /DMA still            |               | channels  |
+|     | capture list       /  running             | DMA Irq End   | not       |
+|     | not empty         /                       |               | finished  |
+|     |                  /                        v               | yet       |
+|   +----------------------+           +----------------------+   |           |
+|   |  Videobuf released   |           |  Channel completed   |   |           |
+|   +----------------------+           +----------------------+   |           |
++-- | QCI: run             |           | QCI: run             | --+           |
+    | DMA: run             |           | DMA: run             |               |
+    +----------------------+           +----------------------+               |
+               ^                      /           |                           |
+               |          no overrun /            | overrun                   |
+               |                    /             v                           |
+    +--------------------+         /   +----------------------+               |
+    |  Frame completed   |        /    |     Frame overran    |               |
+    +--------------------+ <-----+     +----------------------+ restart frame |
+    | QCI: run           |             | QCI: stop            | --------------+
+    | DMA: run           |             | DMA: stop            |
+    +--------------------+             +----------------------+
+
+    Legend: - each box is a FSM state
+            - each arrow is the condition to transition to another state
+            - an arrow with a comment is a mandatory transition (no condition)
+            - arrow "Q" means : a buffer was enqueued
+            - arrow "DQ" means : a buffer was dequeued
+            - "QCI: stop" means the QCI interface is not enabled
+            - "DMA: stop" means all 3 DMA channels are stopped
+            - "DMA: run" means at least 1 DMA channel is still running
 
 DMA usage
 ---------
diff -druN linux-libre-2.6.30-gnu/Documentation/video4linux/v4l2-framework.txt linux-libre-2.6.31-gnu/Documentation/video4linux/v4l2-framework.txt
--- linux-libre-2.6.30-gnu/Documentation/video4linux/v4l2-framework.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/video4linux/v4l2-framework.txt	2009-09-09 18:13:59.000000000 -0400
@@ -89,6 +89,11 @@
 up before calling v4l2_device_register then it will be untouched. If dev is
 NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register.
 
+You can use v4l2_device_set_name() to set the name based on a driver name and
+a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1,
+etc. If the name ends with a digit, then it will insert a dash: cx18-0,
+cx18-1, etc. This function returns the instance number.
+
 The first 'dev' argument is normally the struct device pointer of a pci_dev,
 usb_interface or platform_device. It is rare for dev to be NULL, but it happens
 with ISA devices or when one device creates multiple PCI devices, thus making
@@ -385,6 +390,30 @@
 To see which chip variants are supported you can look in the i2c driver code
 for the i2c_device_id table. This lists all the possibilities.
 
+There are two more helper functions:
+
+v4l2_i2c_new_subdev_cfg: this function adds new irq and platform_data
+arguments and has both 'addr' and 'probed_addrs' arguments: if addr is not
+0 then that will be used (non-probing variant), otherwise the probed_addrs
+are probed.
+
+For example: this will probe for address 0x10:
+
+struct v4l2_subdev *sd = v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter,
+	       "module_foo", "chipid", 0, NULL, 0, I2C_ADDRS(0x10));
+
+v4l2_i2c_new_subdev_board uses an i2c_board_info struct which is passed
+to the i2c driver and replaces the irq, platform_data and addr arguments.
+
+If the subdev supports the s_config core ops, then that op is called with
+the irq and platform_data arguments after the subdev was setup. The older
+v4l2_i2c_new_(probed_)subdev functions will call s_config as well, but with
+irq set to 0 and platform_data set to NULL.
+
+Note that in the next kernel release the functions v4l2_i2c_new_subdev,
+v4l2_i2c_new_probed_subdev and v4l2_i2c_new_probed_subdev_addr will all be
+replaced by a single v4l2_i2c_new_subdev that is identical to
+v4l2_i2c_new_subdev_cfg but without the irq and platform_data arguments.
 
 struct video_device
 -------------------
diff -druN linux-libre-2.6.30-gnu/Documentation/vm/balance linux-libre-2.6.31-gnu/Documentation/vm/balance
--- linux-libre-2.6.30-gnu/Documentation/vm/balance	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/vm/balance	2009-09-09 18:13:59.000000000 -0400
@@ -75,15 +75,15 @@
 alleviate memory pressure on any zone in the page's node that has fallen below
 its watermark.
 
-pages_min/pages_low/pages_high/low_on_memory/zone_wake_kswapd: These are 
-per-zone fields, used to determine when a zone needs to be balanced. When
-the number of pages falls below pages_min, the hysteric field low_on_memory
-gets set. This stays set till the number of free pages becomes pages_high.
-When low_on_memory is set, page allocation requests will try to free some
-pages in the zone (providing GFP_WAIT is set in the request). Orthogonal
-to this, is the decision to poke kswapd to free some zone pages. That
-decision is not hysteresis based, and is done when the number of free
-pages is below pages_low; in which case zone_wake_kswapd is also set.
+watemark[WMARK_MIN/WMARK_LOW/WMARK_HIGH]/low_on_memory/zone_wake_kswapd: These
+are per-zone fields, used to determine when a zone needs to be balanced. When
+the number of pages falls below watermark[WMARK_MIN], the hysteric field
+low_on_memory gets set. This stays set till the number of free pages becomes
+watermark[WMARK_HIGH]. When low_on_memory is set, page allocation requests will
+try to free some pages in the zone (providing GFP_WAIT is set in the request).
+Orthogonal to this, is the decision to poke kswapd to free some zone pages.
+That decision is not hysteresis based, and is done when the number of free
+pages is below watermark[WMARK_LOW]; in which case zone_wake_kswapd is also set.
 
 
 (Good) Ideas that I have heard:
diff -druN linux-libre-2.6.30-gnu/Documentation/vm/Makefile linux-libre-2.6.31-gnu/Documentation/vm/Makefile
--- linux-libre-2.6.30-gnu/Documentation/vm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/vm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
 obj- := dummy.o
 
 # List of programs to build
-hostprogs-y := slabinfo
+hostprogs-y := slabinfo page-types
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
diff -druN linux-libre-2.6.30-gnu/Documentation/vm/pagemap.txt linux-libre-2.6.31-gnu/Documentation/vm/pagemap.txt
--- linux-libre-2.6.30-gnu/Documentation/vm/pagemap.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/vm/pagemap.txt	2009-09-09 18:13:59.000000000 -0400
@@ -12,9 +12,9 @@
    value for each virtual page, containing the following data (from
    fs/proc/task_mmu.c, above pagemap_read):
 
-    * Bits 0-55  page frame number (PFN) if present
+    * Bits 0-54  page frame number (PFN) if present
     * Bits 0-4   swap type if swapped
-    * Bits 5-55  swap offset if swapped
+    * Bits 5-54  swap offset if swapped
     * Bits 55-60 page shift (page size = 1<<page shift)
     * Bit  61    reserved for future use
     * Bit  62    page swapped
@@ -36,7 +36,7 @@
  * /proc/kpageflags.  This file contains a 64-bit set of flags for each
    page, indexed by PFN.
 
-   The flags are (from fs/proc/proc_misc, above kpageflags_read):
+   The flags are (from fs/proc/page.c, above kpageflags_read):
 
      0. LOCKED
      1. ERROR
@@ -49,6 +49,68 @@
      8. WRITEBACK
      9. RECLAIM
     10. BUDDY
+    11. MMAP
+    12. ANON
+    13. SWAPCACHE
+    14. SWAPBACKED
+    15. COMPOUND_HEAD
+    16. COMPOUND_TAIL
+    16. HUGE
+    18. UNEVICTABLE
+    20. NOPAGE
+
+Short descriptions to the page flags:
+
+ 0. LOCKED
+    page is being locked for exclusive access, eg. by undergoing read/write IO
+
+ 7. SLAB
+    page is managed by the SLAB/SLOB/SLUB/SLQB kernel memory allocator
+    When compound page is used, SLUB/SLQB will only set this flag on the head
+    page; SLOB will not flag it at all.
+
+10. BUDDY
+    a free memory block managed by the buddy system allocator
+    The buddy system organizes free memory in blocks of various orders.
+    An order N block has 2^N physically contiguous pages, with the BUDDY flag
+    set for and _only_ for the first page.
+
+15. COMPOUND_HEAD
+16. COMPOUND_TAIL
+    A compound page with order N consists of 2^N physically contiguous pages.
+    A compound page with order 2 takes the form of "HTTT", where H donates its
+    head page and T donates its tail page(s).  The major consumers of compound
+    pages are hugeTLB pages (Documentation/vm/hugetlbpage.txt), the SLUB etc.
+    memory allocators and various device drivers. However in this interface,
+    only huge/giga pages are made visible to end users.
+17. HUGE
+    this is an integral part of a HugeTLB page
+
+20. NOPAGE
+    no page frame exists at the requested address
+
+    [IO related page flags]
+ 1. ERROR     IO error occurred
+ 3. UPTODATE  page has up-to-date data
+              ie. for file backed page: (in-memory data revision >= on-disk one)
+ 4. DIRTY     page has been written to, hence contains new data
+              ie. for file backed page: (in-memory data revision >  on-disk one)
+ 8. WRITEBACK page is being synced to disk
+
+    [LRU related page flags]
+ 5. LRU         page is in one of the LRU lists
+ 6. ACTIVE      page is in the active LRU list
+18. UNEVICTABLE page is in the unevictable (non-)LRU list
+                It is somehow pinned and not a candidate for LRU page reclaims,
+		eg. ramfs pages, shmctl(SHM_LOCK) and mlock() memory segments
+ 2. REFERENCED  page has been referenced since last LRU list enqueue/requeue
+ 9. RECLAIM     page will be reclaimed soon after its pageout IO completed
+11. MMAP        a memory mapped page
+12. ANON        a memory mapped page that is not part of a file
+13. SWAPCACHE   page is mapped to swap space, ie. has an associated swap entry
+14. SWAPBACKED  page is backed by swap/RAM
+
+The page-types tool in this directory can be used to query the above flags.
 
 Using pagemap to do something useful:
 
diff -druN linux-libre-2.6.30-gnu/Documentation/vm/page-types.c linux-libre-2.6.31-gnu/Documentation/vm/page-types.c
--- linux-libre-2.6.30-gnu/Documentation/vm/page-types.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/vm/page-types.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,698 @@
+/*
+ * page-types: Tool for querying page flags
+ *
+ * Copyright (C) 2009 Intel corporation
+ * Copyright (C) 2009 Wu Fengguang <fengguang.wu@intel.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <getopt.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+
+
+/*
+ * kernel page flags
+ */
+
+#define KPF_BYTES		8
+#define PROC_KPAGEFLAGS		"/proc/kpageflags"
+
+/* copied from kpageflags_read() */
+#define KPF_LOCKED		0
+#define KPF_ERROR		1
+#define KPF_REFERENCED		2
+#define KPF_UPTODATE		3
+#define KPF_DIRTY		4
+#define KPF_LRU			5
+#define KPF_ACTIVE		6
+#define KPF_SLAB		7
+#define KPF_WRITEBACK		8
+#define KPF_RECLAIM		9
+#define KPF_BUDDY		10
+
+/* [11-20] new additions in 2.6.31 */
+#define KPF_MMAP		11
+#define KPF_ANON		12
+#define KPF_SWAPCACHE		13
+#define KPF_SWAPBACKED		14
+#define KPF_COMPOUND_HEAD	15
+#define KPF_COMPOUND_TAIL	16
+#define KPF_HUGE		17
+#define KPF_UNEVICTABLE		18
+#define KPF_NOPAGE		20
+
+/* [32-] kernel hacking assistances */
+#define KPF_RESERVED		32
+#define KPF_MLOCKED		33
+#define KPF_MAPPEDTODISK	34
+#define KPF_PRIVATE		35
+#define KPF_PRIVATE_2		36
+#define KPF_OWNER_PRIVATE	37
+#define KPF_ARCH		38
+#define KPF_UNCACHED		39
+
+/* [48-] take some arbitrary free slots for expanding overloaded flags
+ * not part of kernel API
+ */
+#define KPF_READAHEAD		48
+#define KPF_SLOB_FREE		49
+#define KPF_SLUB_FROZEN		50
+#define KPF_SLUB_DEBUG		51
+
+#define KPF_ALL_BITS		((uint64_t)~0ULL)
+#define KPF_HACKERS_BITS	(0xffffULL << 32)
+#define KPF_OVERLOADED_BITS	(0xffffULL << 48)
+#define BIT(name)		(1ULL << KPF_##name)
+#define BITS_COMPOUND		(BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL))
+
+static char *page_flag_names[] = {
+	[KPF_LOCKED]		= "L:locked",
+	[KPF_ERROR]		= "E:error",
+	[KPF_REFERENCED]	= "R:referenced",
+	[KPF_UPTODATE]		= "U:uptodate",
+	[KPF_DIRTY]		= "D:dirty",
+	[KPF_LRU]		= "l:lru",
+	[KPF_ACTIVE]		= "A:active",
+	[KPF_SLAB]		= "S:slab",
+	[KPF_WRITEBACK]		= "W:writeback",
+	[KPF_RECLAIM]		= "I:reclaim",
+	[KPF_BUDDY]		= "B:buddy",
+
+	[KPF_MMAP]		= "M:mmap",
+	[KPF_ANON]		= "a:anonymous",
+	[KPF_SWAPCACHE]		= "s:swapcache",
+	[KPF_SWAPBACKED]	= "b:swapbacked",
+	[KPF_COMPOUND_HEAD]	= "H:compound_head",
+	[KPF_COMPOUND_TAIL]	= "T:compound_tail",
+	[KPF_HUGE]		= "G:huge",
+	[KPF_UNEVICTABLE]	= "u:unevictable",
+	[KPF_NOPAGE]		= "n:nopage",
+
+	[KPF_RESERVED]		= "r:reserved",
+	[KPF_MLOCKED]		= "m:mlocked",
+	[KPF_MAPPEDTODISK]	= "d:mappedtodisk",
+	[KPF_PRIVATE]		= "P:private",
+	[KPF_PRIVATE_2]		= "p:private_2",
+	[KPF_OWNER_PRIVATE]	= "O:owner_private",
+	[KPF_ARCH]		= "h:arch",
+	[KPF_UNCACHED]		= "c:uncached",
+
+	[KPF_READAHEAD]		= "I:readahead",
+	[KPF_SLOB_FREE]		= "P:slob_free",
+	[KPF_SLUB_FROZEN]	= "A:slub_frozen",
+	[KPF_SLUB_DEBUG]	= "E:slub_debug",
+};
+
+
+/*
+ * data structures
+ */
+
+static int		opt_raw;	/* for kernel developers */
+static int		opt_list;	/* list pages (in ranges) */
+static int		opt_no_summary;	/* don't show summary */
+static pid_t		opt_pid;	/* process to walk */
+
+#define MAX_ADDR_RANGES	1024
+static int		nr_addr_ranges;
+static unsigned long	opt_offset[MAX_ADDR_RANGES];
+static unsigned long	opt_size[MAX_ADDR_RANGES];
+
+#define MAX_BIT_FILTERS	64
+static int		nr_bit_filters;
+static uint64_t		opt_mask[MAX_BIT_FILTERS];
+static uint64_t		opt_bits[MAX_BIT_FILTERS];
+
+static int		page_size;
+
+#define PAGES_BATCH	(64 << 10)	/* 64k pages */
+static int		kpageflags_fd;
+static uint64_t		kpageflags_buf[KPF_BYTES * PAGES_BATCH];
+
+#define HASH_SHIFT	13
+#define HASH_SIZE	(1 << HASH_SHIFT)
+#define HASH_MASK	(HASH_SIZE - 1)
+#define HASH_KEY(flags)	(flags & HASH_MASK)
+
+static unsigned long	total_pages;
+static unsigned long	nr_pages[HASH_SIZE];
+static uint64_t 	page_flags[HASH_SIZE];
+
+
+/*
+ * helper functions
+ */
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define min_t(type, x, y) ({			\
+	type __min1 = (x);			\
+	type __min2 = (y);			\
+	__min1 < __min2 ? __min1 : __min2; })
+
+unsigned long pages2mb(unsigned long pages)
+{
+	return (pages * page_size) >> 20;
+}
+
+void fatal(const char *x, ...)
+{
+	va_list ap;
+
+	va_start(ap, x);
+	vfprintf(stderr, x, ap);
+	va_end(ap);
+	exit(EXIT_FAILURE);
+}
+
+
+/*
+ * page flag names
+ */
+
+char *page_flag_name(uint64_t flags)
+{
+	static char buf[65];
+	int present;
+	int i, j;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+		present = (flags >> i) & 1;
+		if (!page_flag_names[i]) {
+			if (present)
+				fatal("unkown flag bit %d\n", i);
+			continue;
+		}
+		buf[j++] = present ? page_flag_names[i][0] : '_';
+	}
+
+	return buf;
+}
+
+char *page_flag_longname(uint64_t flags)
+{
+	static char buf[1024];
+	int i, n;
+
+	for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+		if (!page_flag_names[i])
+			continue;
+		if ((flags >> i) & 1)
+			n += snprintf(buf + n, sizeof(buf) - n, "%s,",
+					page_flag_names[i] + 2);
+	}
+	if (n)
+		n--;
+	buf[n] = '\0';
+
+	return buf;
+}
+
+
+/*
+ * page list and summary
+ */
+
+void show_page_range(unsigned long offset, uint64_t flags)
+{
+	static uint64_t      flags0;
+	static unsigned long index;
+	static unsigned long count;
+
+	if (flags == flags0 && offset == index + count) {
+		count++;
+		return;
+	}
+
+	if (count)
+		printf("%lu\t%lu\t%s\n",
+				index, count, page_flag_name(flags0));
+
+	flags0 = flags;
+	index  = offset;
+	count  = 1;
+}
+
+void show_page(unsigned long offset, uint64_t flags)
+{
+	printf("%lu\t%s\n", offset, page_flag_name(flags));
+}
+
+void show_summary(void)
+{
+	int i;
+
+	printf("             flags\tpage-count       MB"
+		"  symbolic-flags\t\t\tlong-symbolic-flags\n");
+
+	for (i = 0; i < ARRAY_SIZE(nr_pages); i++) {
+		if (nr_pages[i])
+			printf("0x%016llx\t%10lu %8lu  %s\t%s\n",
+				(unsigned long long)page_flags[i],
+				nr_pages[i],
+				pages2mb(nr_pages[i]),
+				page_flag_name(page_flags[i]),
+				page_flag_longname(page_flags[i]));
+	}
+
+	printf("             total\t%10lu %8lu\n",
+			total_pages, pages2mb(total_pages));
+}
+
+
+/*
+ * page flag filters
+ */
+
+int bit_mask_ok(uint64_t flags)
+{
+	int i;
+
+	for (i = 0; i < nr_bit_filters; i++) {
+		if (opt_bits[i] == KPF_ALL_BITS) {
+			if ((flags & opt_mask[i]) == 0)
+				return 0;
+		} else {
+			if ((flags & opt_mask[i]) != opt_bits[i])
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+uint64_t expand_overloaded_flags(uint64_t flags)
+{
+	/* SLOB/SLUB overload several page flags */
+	if (flags & BIT(SLAB)) {
+		if (flags & BIT(PRIVATE))
+			flags ^= BIT(PRIVATE) | BIT(SLOB_FREE);
+		if (flags & BIT(ACTIVE))
+			flags ^= BIT(ACTIVE) | BIT(SLUB_FROZEN);
+		if (flags & BIT(ERROR))
+			flags ^= BIT(ERROR) | BIT(SLUB_DEBUG);
+	}
+
+	/* PG_reclaim is overloaded as PG_readahead in the read path */
+	if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM))
+		flags ^= BIT(RECLAIM) | BIT(READAHEAD);
+
+	return flags;
+}
+
+uint64_t well_known_flags(uint64_t flags)
+{
+	/* hide flags intended only for kernel hacker */
+	flags &= ~KPF_HACKERS_BITS;
+
+	/* hide non-hugeTLB compound pages */
+	if ((flags & BITS_COMPOUND) && !(flags & BIT(HUGE)))
+		flags &= ~BITS_COMPOUND;
+
+	return flags;
+}
+
+
+/*
+ * page frame walker
+ */
+
+int hash_slot(uint64_t flags)
+{
+	int k = HASH_KEY(flags);
+	int i;
+
+	/* Explicitly reserve slot 0 for flags 0: the following logic
+	 * cannot distinguish an unoccupied slot from slot (flags==0).
+	 */
+	if (flags == 0)
+		return 0;
+
+	/* search through the remaining (HASH_SIZE-1) slots */
+	for (i = 1; i < ARRAY_SIZE(page_flags); i++, k++) {
+		if (!k || k >= ARRAY_SIZE(page_flags))
+			k = 1;
+		if (page_flags[k] == 0) {
+			page_flags[k] = flags;
+			return k;
+		}
+		if (page_flags[k] == flags)
+			return k;
+	}
+
+	fatal("hash table full: bump up HASH_SHIFT?\n");
+	exit(EXIT_FAILURE);
+}
+
+void add_page(unsigned long offset, uint64_t flags)
+{
+	flags = expand_overloaded_flags(flags);
+
+	if (!opt_raw)
+		flags = well_known_flags(flags);
+
+	if (!bit_mask_ok(flags))
+		return;
+
+	if (opt_list == 1)
+		show_page_range(offset, flags);
+	else if (opt_list == 2)
+		show_page(offset, flags);
+
+	nr_pages[hash_slot(flags)]++;
+	total_pages++;
+}
+
+void walk_pfn(unsigned long index, unsigned long count)
+{
+	unsigned long batch;
+	unsigned long n;
+	unsigned long i;
+
+	if (index > ULONG_MAX / KPF_BYTES)
+		fatal("index overflow: %lu\n", index);
+
+	lseek(kpageflags_fd, index * KPF_BYTES, SEEK_SET);
+
+	while (count) {
+		batch = min_t(unsigned long, count, PAGES_BATCH);
+		n = read(kpageflags_fd, kpageflags_buf, batch * KPF_BYTES);
+		if (n == 0)
+			break;
+		if (n < 0) {
+			perror(PROC_KPAGEFLAGS);
+			exit(EXIT_FAILURE);
+		}
+
+		if (n % KPF_BYTES != 0)
+			fatal("partial read: %lu bytes\n", n);
+		n = n / KPF_BYTES;
+
+		for (i = 0; i < n; i++)
+			add_page(index + i, kpageflags_buf[i]);
+
+		index += batch;
+		count -= batch;
+	}
+}
+
+void walk_addr_ranges(void)
+{
+	int i;
+
+	kpageflags_fd = open(PROC_KPAGEFLAGS, O_RDONLY);
+	if (kpageflags_fd < 0) {
+		perror(PROC_KPAGEFLAGS);
+		exit(EXIT_FAILURE);
+	}
+
+	if (!nr_addr_ranges)
+		walk_pfn(0, ULONG_MAX);
+
+	for (i = 0; i < nr_addr_ranges; i++)
+		walk_pfn(opt_offset[i], opt_size[i]);
+
+	close(kpageflags_fd);
+}
+
+
+/*
+ * user interface
+ */
+
+const char *page_flag_type(uint64_t flag)
+{
+	if (flag & KPF_HACKERS_BITS)
+		return "(r)";
+	if (flag & KPF_OVERLOADED_BITS)
+		return "(o)";
+	return "   ";
+}
+
+void usage(void)
+{
+	int i, j;
+
+	printf(
+"page-types [options]\n"
+"            -r|--raw                  Raw mode, for kernel developers\n"
+"            -a|--addr    addr-spec    Walk a range of pages\n"
+"            -b|--bits    bits-spec    Walk pages with specified bits\n"
+#if 0 /* planned features */
+"            -p|--pid     pid          Walk process address space\n"
+"            -f|--file    filename     Walk file address space\n"
+#endif
+"            -l|--list                 Show page details in ranges\n"
+"            -L|--list-each            Show page details one by one\n"
+"            -N|--no-summary           Don't show summay info\n"
+"            -h|--help                 Show this usage message\n"
+"addr-spec:\n"
+"            N                         one page at offset N (unit: pages)\n"
+"            N+M                       pages range from N to N+M-1\n"
+"            N,M                       pages range from N to M-1\n"
+"            N,                        pages range from N to end\n"
+"            ,M                        pages range from 0 to M\n"
+"bits-spec:\n"
+"            bit1,bit2                 (flags & (bit1|bit2)) != 0\n"
+"            bit1,bit2=bit1            (flags & (bit1|bit2)) == bit1\n"
+"            bit1,~bit2                (flags & (bit1|bit2)) == bit1\n"
+"            =bit1,bit2                flags == (bit1|bit2)\n"
+"bit-names:\n"
+	);
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+		if (!page_flag_names[i])
+			continue;
+		printf("%16s%s", page_flag_names[i] + 2,
+				 page_flag_type(1ULL << i));
+		if (++j > 3) {
+			j = 0;
+			putchar('\n');
+		}
+	}
+	printf("\n                                   "
+		"(r) raw mode bits  (o) overloaded bits\n");
+}
+
+unsigned long long parse_number(const char *str)
+{
+	unsigned long long n;
+
+	n = strtoll(str, NULL, 0);
+
+	if (n == 0 && str[0] != '0')
+		fatal("invalid name or number: %s\n", str);
+
+	return n;
+}
+
+void parse_pid(const char *str)
+{
+	opt_pid = parse_number(str);
+}
+
+void parse_file(const char *name)
+{
+}
+
+void add_addr_range(unsigned long offset, unsigned long size)
+{
+	if (nr_addr_ranges >= MAX_ADDR_RANGES)
+		fatal("too much addr ranges\n");
+
+	opt_offset[nr_addr_ranges] = offset;
+	opt_size[nr_addr_ranges] = size;
+	nr_addr_ranges++;
+}
+
+void parse_addr_range(const char *optarg)
+{
+	unsigned long offset;
+	unsigned long size;
+	char *p;
+
+	p = strchr(optarg, ',');
+	if (!p)
+		p = strchr(optarg, '+');
+
+	if (p == optarg) {
+		offset = 0;
+		size   = parse_number(p + 1);
+	} else if (p) {
+		offset = parse_number(optarg);
+		if (p[1] == '\0')
+			size = ULONG_MAX;
+		else {
+			size = parse_number(p + 1);
+			if (*p == ',') {
+				if (size < offset)
+					fatal("invalid range: %lu,%lu\n",
+							offset, size);
+				size -= offset;
+			}
+		}
+	} else {
+		offset = parse_number(optarg);
+		size   = 1;
+	}
+
+	add_addr_range(offset, size);
+}
+
+void add_bits_filter(uint64_t mask, uint64_t bits)
+{
+	if (nr_bit_filters >= MAX_BIT_FILTERS)
+		fatal("too much bit filters\n");
+
+	opt_mask[nr_bit_filters] = mask;
+	opt_bits[nr_bit_filters] = bits;
+	nr_bit_filters++;
+}
+
+uint64_t parse_flag_name(const char *str, int len)
+{
+	int i;
+
+	if (!*str || !len)
+		return 0;
+
+	if (len <= 8 && !strncmp(str, "compound", len))
+		return BITS_COMPOUND;
+
+	for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+		if (!page_flag_names[i])
+			continue;
+		if (!strncmp(str, page_flag_names[i] + 2, len))
+			return 1ULL << i;
+	}
+
+	return parse_number(str);
+}
+
+uint64_t parse_flag_names(const char *str, int all)
+{
+	const char *p    = str;
+	uint64_t   flags = 0;
+
+	while (1) {
+		if (*p == ',' || *p == '=' || *p == '\0') {
+			if ((*str != '~') || (*str == '~' && all && *++str))
+				flags |= parse_flag_name(str, p - str);
+			if (*p != ',')
+				break;
+			str = p + 1;
+		}
+		p++;
+	}
+
+	return flags;
+}
+
+void parse_bits_mask(const char *optarg)
+{
+	uint64_t mask;
+	uint64_t bits;
+	const char *p;
+
+	p = strchr(optarg, '=');
+	if (p == optarg) {
+		mask = KPF_ALL_BITS;
+		bits = parse_flag_names(p + 1, 0);
+	} else if (p) {
+		mask = parse_flag_names(optarg, 0);
+		bits = parse_flag_names(p + 1, 0);
+	} else if (strchr(optarg, '~')) {
+		mask = parse_flag_names(optarg, 1);
+		bits = parse_flag_names(optarg, 0);
+	} else {
+		mask = parse_flag_names(optarg, 0);
+		bits = KPF_ALL_BITS;
+	}
+
+	add_bits_filter(mask, bits);
+}
+
+
+struct option opts[] = {
+	{ "raw"       , 0, NULL, 'r' },
+	{ "pid"       , 1, NULL, 'p' },
+	{ "file"      , 1, NULL, 'f' },
+	{ "addr"      , 1, NULL, 'a' },
+	{ "bits"      , 1, NULL, 'b' },
+	{ "list"      , 0, NULL, 'l' },
+	{ "list-each" , 0, NULL, 'L' },
+	{ "no-summary", 0, NULL, 'N' },
+	{ "help"      , 0, NULL, 'h' },
+	{ NULL        , 0, NULL, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+	int c;
+
+	page_size = getpagesize();
+
+	while ((c = getopt_long(argc, argv,
+				"rp:f:a:b:lLNh", opts, NULL)) != -1) {
+		switch (c) {
+		case 'r':
+			opt_raw = 1;
+			break;
+		case 'p':
+			parse_pid(optarg);
+			break;
+		case 'f':
+			parse_file(optarg);
+			break;
+		case 'a':
+			parse_addr_range(optarg);
+			break;
+		case 'b':
+			parse_bits_mask(optarg);
+			break;
+		case 'l':
+			opt_list = 1;
+			break;
+		case 'L':
+			opt_list = 2;
+			break;
+		case 'N':
+			opt_no_summary = 1;
+			break;
+		case 'h':
+			usage();
+			exit(0);
+		default:
+			usage();
+			exit(1);
+		}
+	}
+
+	if (opt_list == 1)
+		printf("offset\tcount\tflags\n");
+	if (opt_list == 2)
+		printf("offset\tflags\n");
+
+	walk_addr_ranges();
+
+	if (opt_list == 1)
+		show_page_range(0, 0);  /* drain the buffer */
+
+	if (opt_no_summary)
+		return 0;
+
+	if (opt_list)
+		printf("\n\n");
+
+	show_summary();
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/Documentation/watchdog/hpwdt.txt linux-libre-2.6.31-gnu/Documentation/watchdog/hpwdt.txt
--- linux-libre-2.6.30-gnu/Documentation/watchdog/hpwdt.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/watchdog/hpwdt.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,95 @@
+Last reviewed: 06/02/2009
+
+                     HP iLO2 NMI Watchdog Driver
+              NMI sourcing for iLO2 based ProLiant Servers
+                     Documentation and Driver by
+              Thomas Mingarelli <thomas.mingarelli@hp.com>
+
+ The HP iLO2 NMI Watchdog driver is a kernel module that provides basic
+ watchdog functionality and the added benefit of NMI sourcing. Both the
+ watchdog functionality and the NMI sourcing capability need to be enabled
+ by the user. Remember that the two modes are not dependant on one another.
+ A user can have the NMI sourcing without the watchdog timer and vice-versa.
+
+ Watchdog functionality is enabled like any other common watchdog driver. That
+ is, an application needs to be started that kicks off the watchdog timer. A
+ basic application exists in the Documentation/watchdog/src directory called
+ watchdog-test.c. Simply compile the C file and kick it off. If the system
+ gets into a bad state and hangs, the HP ProLiant iLO 2 timer register will
+ not be updated in a timely fashion and a hardware system reset (also known as
+ an Automatic Server Recovery (ASR)) event will occur.
+
+ The hpwdt driver also has four (4) module parameters. They are the following:
+
+ soft_margin - allows the user to set the watchdog timer value
+ allow_kdump - allows the user to save off a kernel dump image after an NMI
+ nowayout    - basic watchdog parameter that does not allow the timer to
+               be restarted or an impending ASR to be escaped.
+ priority    - determines whether or not the hpwdt driver is first on the
+               die_notify list to handle NMIs or last. The default value
+               for this module parameter is 0 or LAST. If the user wants to
+               enable NMI sourcing then reload the hpwdt driver with
+               priority=1 (and boot with nmi_watchdog=0).
+
+ NOTE: More information about watchdog drivers in general, including the ioctl
+       interface to /dev/watchdog can be found in
+       Documentation/watchdog/watchdog-api.txt and Documentation/IPMI.txt.
+
+ The priority parameter was introduced due to other kernel software that relied
+ on handling NMIs (like oprofile). Keeping hpwdt's priority at 0 (or LAST)
+ enables the users of NMIs for non critical events to be work as expected.
+
+ The NMI sourcing capability is disabled by default due to the inability to
+ distinguish between "NMI Watchdog Ticks" and "HW generated NMI events" in the
+ Linux kernel. What this means is that the hpwdt nmi handler code is called
+ each time the NMI signal fires off. This could amount to several thousands of
+ NMIs in a matter of seconds. If a user sees the Linux kernel's "dazed and
+ confused" message in the logs or if the system gets into a hung state, then
+ the hpwdt driver can be reloaded with the "priority" module parameter set
+ (priority=1).
+
+ 1. If the kernel has not been booted with nmi_watchdog turned off then
+    edit /boot/grub/menu.lst and place the nmi_watchdog=0 at the end of the
+    currently booting kernel line.
+ 2. reboot the sever
+ 3. Once the system comes up perform a rmmod hpwdt
+ 4. insmod /lib/modules/`uname -r`/kernel/drivers/char/watchdog/hpwdt.ko priority=1
+
+ Now, the hpwdt can successfully receive and source the NMI and provide a log
+ message that details the reason for the NMI (as determined by the HP BIOS).
+
+ Below is a list of NMIs the HP BIOS understands along with the associated
+ code (reason):
+
+	No source found                00h
+
+	Uncorrectable Memory Error     01h
+
+	ASR NMI                        1Bh
+
+	PCI Parity Error               20h
+
+	NMI Button Press               27h
+
+	SB_BUS_NMI                     28h
+
+	ILO Doorbell NMI               29h
+
+	ILO IOP NMI                    2Ah
+
+	ILO Watchdog NMI               2Bh
+
+	Proc Throt NMI                 2Ch
+
+	Front Side Bus NMI             2Dh
+
+	PCI Express Error              2Fh
+
+	DMA controller NMI             30h
+
+	Hypertransport/CSI Error       31h
+
+
+
+ -- Tom Mingarelli
+    (thomas.mingarelli@hp.com)
diff -druN linux-libre-2.6.30-gnu/Documentation/x86/00-INDEX linux-libre-2.6.31-gnu/Documentation/x86/00-INDEX
--- linux-libre-2.6.30-gnu/Documentation/x86/00-INDEX	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/x86/00-INDEX	2009-09-09 18:13:59.000000000 -0400
@@ -2,3 +2,5 @@
 	- this file
 mtrr.txt
 	- how to use x86 Memory Type Range Registers to increase performance
+exception-tables.txt
+	- why and how Linux kernel uses exception tables on x86
diff -druN linux-libre-2.6.30-gnu/Documentation/x86/boot.txt linux-libre-2.6.31-gnu/Documentation/x86/boot.txt
--- linux-libre-2.6.30-gnu/Documentation/x86/boot.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/x86/boot.txt	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,10 @@
 Protocol 2.09:	(Kernel 2.6.26) Added a field of 64-bit physical
 		pointer to single linked list of struct	setup_data.
 
+Protocol 2.10:	(Kernel 2.6.31) Added a protocol for relaxed alignment
+		beyond the kernel_alignment added, new init_size and
+		pref_address fields.  Added extended boot loader IDs.
+
 **** MEMORY LAYOUT
 
 The traditional memory map for the kernel loader, used for Image or
@@ -168,12 +172,13 @@
 021C/4	2.00+	ramdisk_size	initrd size (set by boot loader)
 0220/4	2.00+	bootsect_kludge	DO NOT USE - for bootsect.S use only
 0224/2	2.01+	heap_end_ptr	Free memory after setup end
-0226/2	N/A	pad1		Unused
+0226/1	2.02+(3 ext_loader_ver	Extended boot loader version
+0227/1	2.02+(3	ext_loader_type	Extended boot loader ID
 0228/4	2.02+	cmd_line_ptr	32-bit pointer to the kernel command line
 022C/4	2.03+	ramdisk_max	Highest legal initrd address
 0230/4	2.05+	kernel_alignment Physical addr alignment required for kernel
 0234/1	2.05+	relocatable_kernel Whether kernel is relocatable or not
-0235/1	N/A	pad2		Unused
+0235/1	2.10+	min_alignment	Minimum alignment, as a power of two
 0236/2	N/A	pad3		Unused
 0238/4	2.06+	cmdline_size	Maximum size of the kernel command line
 023C/4	2.07+	hardware_subarch Hardware subarchitecture
@@ -182,6 +187,8 @@
 024C/4	2.08+	payload_length	Length of kernel payload
 0250/8	2.09+	setup_data	64-bit physical pointer to linked list
 				of struct setup_data
+0258/8	2.10+	pref_address	Preferred loading address
+0260/4	2.10+	init_size	Linear memory required during initialization
 
 (1) For backwards compatibility, if the setup_sects field contains 0, the
     real value is 4.
@@ -190,6 +197,8 @@
     field are unusable, which means the size of a bzImage kernel
     cannot be determined.
 
+(3) Ignored, but safe to set, for boot protocols 2.02-2.09.
+
 If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
 the boot protocol version is "old".  Loading an old kernel, the
 following parameters should be assumed:
@@ -343,18 +352,32 @@
   0xTV here, where T is an identifier for the boot loader and V is
   a version number.  Otherwise, enter 0xFF here.
 
+  For boot loader IDs above T = 0xD, write T = 0xE to this field and
+  write the extended ID minus 0x10 to the ext_loader_type field.
+  Similarly, the ext_loader_ver field can be used to provide more than
+  four bits for the bootloader version.
+
+  For example, for T = 0x15, V = 0x234, write:
+
+  type_of_loader  <- 0xE4
+  ext_loader_type <- 0x05
+  ext_loader_ver  <- 0x23
+
   Assigned boot loader ids:
 	0  LILO			(0x00 reserved for pre-2.00 bootloader)
 	1  Loadlin
 	2  bootsect-loader	(0x20, all other values reserved)
-	3  SYSLINUX
-	4  EtherBoot
+	3  Syslinux
+	4  Etherboot/gPXE
 	5  ELILO
 	7  GRUB
-	8  U-BOOT
+	8  U-Boot
 	9  Xen
 	A  Gujin
 	B  Qemu
+	C  Arcturus Networks uCbootloader
+	E  Extended		(see ext_loader_type)
+	F  Special		(0xFF = undefined)
 
   Please contact <hpa@zytor.com> if you need a bootloader ID
   value assigned.
@@ -453,6 +476,35 @@
   Set this field to the offset (from the beginning of the real-mode
   code) of the end of the setup stack/heap, minus 0x0200.
 
+Field name:	ext_loader_ver
+Type:		write (optional)
+Offset/size:	0x226/1
+Protocol:	2.02+
+
+  This field is used as an extension of the version number in the
+  type_of_loader field.  The total version number is considered to be
+  (type_of_loader & 0x0f) + (ext_loader_ver << 4).
+
+  The use of this field is boot loader specific.  If not written, it
+  is zero.
+
+  Kernels prior to 2.6.31 did not recognize this field, but it is safe
+  to write for protocol version 2.02 or higher.
+
+Field name:	ext_loader_type
+Type:		write (obligatory if (type_of_loader & 0xf0) == 0xe0)
+Offset/size:	0x227/1
+Protocol:	2.02+
+
+  This field is used as an extension of the type number in
+  type_of_loader field.  If the type in type_of_loader is 0xE, then
+  the actual type is (ext_loader_type + 0x10).
+
+  This field is ignored if the type in type_of_loader is not 0xE.
+
+  Kernels prior to 2.6.31 did not recognize this field, but it is safe
+  to write for protocol version 2.02 or higher.
+
 Field name:	cmd_line_ptr
 Type:		write (obligatory)
 Offset/size:	0x228/4
@@ -482,11 +534,19 @@
   0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
 
 Field name:	kernel_alignment
-Type:		read (reloc)
+Type:		read/modify (reloc)
 Offset/size:	0x230/4
-Protocol:	2.05+
+Protocol:	2.05+ (read), 2.10+ (modify)
 
-  Alignment unit required by the kernel (if relocatable_kernel is true.)
+  Alignment unit required by the kernel (if relocatable_kernel is
+  true.)  A relocatable kernel that is loaded at an alignment
+  incompatible with the value in this field will be realigned during
+  kernel initialization.
+
+  Starting with protocol version 2.10, this reflects the kernel
+  alignment preferred for optimal performance; it is possible for the
+  loader to modify this field to permit a lesser alignment.  See the
+  min_alignment and pref_address field below.
 
 Field name:	relocatable_kernel
 Type:		read (reloc)
@@ -498,6 +558,22 @@
   After loading, the boot loader must set the code32_start field to
   point to the loaded code, or to a boot loader hook.
 
+Field name:	min_alignment
+Type:		read (reloc)
+Offset/size:	0x235/1
+Protocol:	2.10+
+
+  This field, if nonzero, indicates as a power of two the minimum
+  alignment required, as opposed to preferred, by the kernel to boot.
+  If a boot loader makes use of this field, it should update the
+  kernel_alignment field with the alignment unit desired; typically:
+
+	kernel_alignment = 1 << min_alignment
+
+  There may be a considerable performance cost with an excessively
+  misaligned kernel.  Therefore, a loader should typically try each
+  power-of-two alignment from kernel_alignment down to this alignment.
+
 Field name:	cmdline_size
 Type:		read
 Offset/size:	0x238/4
@@ -582,6 +658,36 @@
   sure to consider the case where the linked list already contains
   entries.
 
+Field name:	pref_address
+Type:		read (reloc)
+Offset/size:	0x258/8
+Protocol:	2.10+
+
+  This field, if nonzero, represents a preferred load address for the
+  kernel.  A relocating bootloader should attempt to load at this
+  address if possible.
+
+  A non-relocatable kernel will unconditionally move itself and to run
+  at this address.
+
+Field name:	init_size
+Type:		read
+Offset/size:	0x25c/4
+
+  This field indicates the amount of linear contiguous memory starting
+  at the kernel runtime start address that the kernel needs before it
+  is capable of examining its memory map.  This is not the same thing
+  as the total amount of memory the kernel needs to boot, but it can
+  be used by a relocating boot loader to help select a safe load
+  address for the kernel.
+
+  The kernel runtime start address is determined by the following algorithm:
+
+  if (relocatable_kernel)
+	runtime_start = align_up(load_address, kernel_alignment)
+  else
+	runtime_start = pref_address
+
 
 **** THE IMAGE CHECKSUM
 
diff -druN linux-libre-2.6.30-gnu/Documentation/x86/exception-tables.txt linux-libre-2.6.31-gnu/Documentation/x86/exception-tables.txt
--- linux-libre-2.6.30-gnu/Documentation/x86/exception-tables.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/Documentation/x86/exception-tables.txt	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,292 @@
+     Kernel level exception handling in Linux
+  Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com>
+
+When a process runs in kernel mode, it often has to access user
+mode memory whose address has been passed by an untrusted program.
+To protect itself the kernel has to verify this address.
+
+In older versions of Linux this was done with the
+int verify_area(int type, const void * addr, unsigned long size)
+function (which has since been replaced by access_ok()).
+
+This function verified that the memory area starting at address
+'addr' and of size 'size' was accessible for the operation specified
+in type (read or write). To do this, verify_read had to look up the
+virtual memory area (vma) that contained the address addr. In the
+normal case (correctly working program), this test was successful.
+It only failed for a few buggy programs. In some kernel profiling
+tests, this normally unneeded verification used up a considerable
+amount of time.
+
+To overcome this situation, Linus decided to let the virtual memory
+hardware present in every Linux-capable CPU handle this test.
+
+How does this work?
+
+Whenever the kernel tries to access an address that is currently not
+accessible, the CPU generates a page fault exception and calls the
+page fault handler
+
+void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+
+in arch/x86/mm/fault.c. The parameters on the stack are set up by
+the low level assembly glue in arch/x86/kernel/entry_32.S. The parameter
+regs is a pointer to the saved registers on the stack, error_code
+contains a reason code for the exception.
+
+do_page_fault first obtains the unaccessible address from the CPU
+control register CR2. If the address is within the virtual address
+space of the process, the fault probably occurred, because the page
+was not swapped in, write protected or something similar. However,
+we are interested in the other case: the address is not valid, there
+is no vma that contains this address. In this case, the kernel jumps
+to the bad_area label.
+
+There it uses the address of the instruction that caused the exception
+(i.e. regs->eip) to find an address where the execution can continue
+(fixup). If this search is successful, the fault handler modifies the
+return address (again regs->eip) and returns. The execution will
+continue at the address in fixup.
+
+Where does fixup point to?
+
+Since we jump to the contents of fixup, fixup obviously points
+to executable code. This code is hidden inside the user access macros.
+I have picked the get_user macro defined in arch/x86/include/asm/uaccess.h
+as an example. The definition is somewhat hard to follow, so let's peek at
+the code generated by the preprocessor and the compiler. I selected
+the get_user call in drivers/char/sysrq.c for a detailed examination.
+
+The original code in sysrq.c line 587:
+        get_user(c, buf);
+
+The preprocessor output (edited to become somewhat readable):
+
+(
+  {
+    long __gu_err = - 14 , __gu_val = 0;
+    const __typeof__(*( (  buf ) )) *__gu_addr = ((buf));
+    if (((((0 + current_set[0])->tss.segment) == 0x18 )  ||
+       (((sizeof(*(buf))) <= 0xC0000000UL) &&
+       ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
+      do {
+        __gu_err  = 0;
+        switch ((sizeof(*(buf)))) {
+          case 1:
+            __asm__ __volatile__(
+              "1:      mov" "b" " %2,%" "b" "1\n"
+              "2:\n"
+              ".section .fixup,\"ax\"\n"
+              "3:      movl %3,%0\n"
+              "        xor" "b" " %" "b" "1,%" "b" "1\n"
+              "        jmp 2b\n"
+              ".section __ex_table,\"a\"\n"
+              "        .align 4\n"
+              "        .long 1b,3b\n"
+              ".text"        : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
+                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ;
+              break;
+          case 2:
+            __asm__ __volatile__(
+              "1:      mov" "w" " %2,%" "w" "1\n"
+              "2:\n"
+              ".section .fixup,\"ax\"\n"
+              "3:      movl %3,%0\n"
+              "        xor" "w" " %" "w" "1,%" "w" "1\n"
+              "        jmp 2b\n"
+              ".section __ex_table,\"a\"\n"
+              "        .align 4\n"
+              "        .long 1b,3b\n"
+              ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
+                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  ));
+              break;
+          case 4:
+            __asm__ __volatile__(
+              "1:      mov" "l" " %2,%" "" "1\n"
+              "2:\n"
+              ".section .fixup,\"ax\"\n"
+              "3:      movl %3,%0\n"
+              "        xor" "l" " %" "" "1,%" "" "1\n"
+              "        jmp 2b\n"
+              ".section __ex_table,\"a\"\n"
+              "        .align 4\n"        "        .long 1b,3b\n"
+              ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
+                            (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err));
+              break;
+          default:
+            (__gu_val) = __get_user_bad();
+        }
+      } while (0) ;
+    ((c)) = (__typeof__(*((buf))))__gu_val;
+    __gu_err;
+  }
+);
+
+WOW! Black GCC/assembly magic. This is impossible to follow, so let's
+see what code gcc generates:
+
+ >         xorl %edx,%edx
+ >         movl current_set,%eax
+ >         cmpl $24,788(%eax)
+ >         je .L1424
+ >         cmpl $-1073741825,64(%esp)
+ >         ja .L1423
+ > .L1424:
+ >         movl %edx,%eax
+ >         movl 64(%esp),%ebx
+ > #APP
+ > 1:      movb (%ebx),%dl                /* this is the actual user access */
+ > 2:
+ > .section .fixup,"ax"
+ > 3:      movl $-14,%eax
+ >         xorb %dl,%dl
+ >         jmp 2b
+ > .section __ex_table,"a"
+ >         .align 4
+ >         .long 1b,3b
+ > .text
+ > #NO_APP
+ > .L1423:
+ >         movzbl %dl,%esi
+
+The optimizer does a good job and gives us something we can actually
+understand. Can we? The actual user access is quite obvious. Thanks
+to the unified address space we can just access the address in user
+memory. But what does the .section stuff do?????
+
+To understand this we have to look at the final kernel:
+
+ > objdump --section-headers vmlinux
+ >
+ > vmlinux:     file format elf32-i386
+ >
+ > Sections:
+ > Idx Name          Size      VMA       LMA       File off  Algn
+ >   0 .text         00098f40  c0100000  c0100000  00001000  2**4
+ >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
+ >   1 .fixup        000016bc  c0198f40  c0198f40  00099f40  2**0
+ >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
+ >   2 .rodata       0000f127  c019a5fc  c019a5fc  0009b5fc  2**2
+ >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
+ >   3 __ex_table    000015c0  c01a9724  c01a9724  000aa724  2**2
+ >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
+ >   4 .data         0000ea58  c01abcf0  c01abcf0  000abcf0  2**4
+ >                   CONTENTS, ALLOC, LOAD, DATA
+ >   5 .bss          00018e21  c01ba748  c01ba748  000ba748  2**2
+ >                   ALLOC
+ >   6 .comment      00000ec4  00000000  00000000  000ba748  2**0
+ >                   CONTENTS, READONLY
+ >   7 .note         00001068  00000ec4  00000ec4  000bb60c  2**0
+ >                   CONTENTS, READONLY
+
+There are obviously 2 non standard ELF sections in the generated object
+file. But first we want to find out what happened to our code in the
+final kernel executable:
+
+ > objdump --disassemble --section=.text vmlinux
+ >
+ > c017e785 <do_con_write+c1> xorl   %edx,%edx
+ > c017e787 <do_con_write+c3> movl   0xc01c7bec,%eax
+ > c017e78c <do_con_write+c8> cmpl   $0x18,0x314(%eax)
+ > c017e793 <do_con_write+cf> je     c017e79f <do_con_write+db>
+ > c017e795 <do_con_write+d1> cmpl   $0xbfffffff,0x40(%esp,1)
+ > c017e79d <do_con_write+d9> ja     c017e7a7 <do_con_write+e3>
+ > c017e79f <do_con_write+db> movl   %edx,%eax
+ > c017e7a1 <do_con_write+dd> movl   0x40(%esp,1),%ebx
+ > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
+ > c017e7a7 <do_con_write+e3> movzbl %dl,%esi
+
+The whole user memory access is reduced to 10 x86 machine instructions.
+The instructions bracketed in the .section directives are no longer
+in the normal execution path. They are located in a different section
+of the executable file:
+
+ > objdump --disassemble --section=.fixup vmlinux
+ >
+ > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
+ > c0199ffa <.fixup+10ba> xorb   %dl,%dl
+ > c0199ffc <.fixup+10bc> jmp    c017e7a7 <do_con_write+e3>
+
+And finally:
+ > objdump --full-contents --section=__ex_table vmlinux
+ >
+ >  c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0  ................
+ >  c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0  ................
+ >  c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0  ................
+
+or in human readable byte order:
+
+ >  c01aa7c4 c017c093 c0199fe0 c017c097 c017c099  ................
+ >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
+                               ^^^^^^^^^^^^^^^^^
+                               this is the interesting part!
+ >  c01aa7e4 c0180a08 c019a001 c0180a0a c019a004  ................
+
+What happened? The assembly directives
+
+.section .fixup,"ax"
+.section __ex_table,"a"
+
+told the assembler to move the following code to the specified
+sections in the ELF object file. So the instructions
+3:      movl $-14,%eax
+        xorb %dl,%dl
+        jmp 2b
+ended up in the .fixup section of the object file and the addresses
+        .long 1b,3b
+ended up in the __ex_table section of the object file. 1b and 3b
+are local labels. The local label 1b (1b stands for next label 1
+backward) is the address of the instruction that might fault, i.e.
+in our case the address of the label 1 is c017e7a5:
+the original assembly code: > 1:      movb (%ebx),%dl
+and linked in vmlinux     : > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
+
+The local label 3 (backwards again) is the address of the code to handle
+the fault, in our case the actual value is c0199ff5:
+the original assembly code: > 3:      movl $-14,%eax
+and linked in vmlinux     : > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
+
+The assembly code
+ > .section __ex_table,"a"
+ >         .align 4
+ >         .long 1b,3b
+
+becomes the value pair
+ >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
+                               ^this is ^this is
+                               1b       3b
+c017e7a5,c0199ff5 in the exception table of the kernel.
+
+So, what actually happens if a fault from kernel mode with no suitable
+vma occurs?
+
+1.) access to invalid address:
+ > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
+2.) MMU generates exception
+3.) CPU calls do_page_fault
+4.) do page fault calls search_exception_table (regs->eip == c017e7a5);
+5.) search_exception_table looks up the address c017e7a5 in the
+    exception table (i.e. the contents of the ELF section __ex_table)
+    and returns the address of the associated fault handle code c0199ff5.
+6.) do_page_fault modifies its own return address to point to the fault
+    handle code and returns.
+7.) execution continues in the fault handling code.
+8.) 8a) EAX becomes -EFAULT (== -14)
+    8b) DL  becomes zero (the value we "read" from user space)
+    8c) execution continues at local label 2 (address of the
+        instruction immediately after the faulting user access).
+
+The steps 8a to 8c in a certain way emulate the faulting instruction.
+
+That's it, mostly. If you look at our example, you might ask why
+we set EAX to -EFAULT in the exception handler code. Well, the
+get_user macro actually returns a value: 0, if the user access was
+successful, -EFAULT on failure. Our original code did not test this
+return value, however the inline assembly code in get_user tries to
+return -EFAULT. GCC selected EAX to return this value.
+
+NOTE:
+Due to the way that the exception table is built and needs to be ordered,
+only use exceptions for code in the .text section.  Any other section
+will cause the exception table to not be sorted correctly, and the
+exceptions will fail.
diff -druN linux-libre-2.6.30-gnu/Documentation/x86/x86_64/boot-options.txt linux-libre-2.6.31-gnu/Documentation/x86/x86_64/boot-options.txt
--- linux-libre-2.6.30-gnu/Documentation/x86/x86_64/boot-options.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/x86/x86_64/boot-options.txt	2009-09-09 18:13:59.000000000 -0400
@@ -5,21 +5,51 @@
 
 Machine check
 
-   mce=off disable machine check
-   mce=bootlog Enable logging of machine checks left over from booting.
-               Disabled by default on AMD because some BIOS leave bogus ones.
-               If your BIOS doesn't do that it's a good idea to enable though
-               to make sure you log even machine check events that result
-               in a reboot. On Intel systems it is enabled by default.
+   Please see Documentation/x86/x86_64/machinecheck for sysfs runtime tunables.
+
+   mce=off
+		Disable machine check
+   mce=no_cmci
+		Disable CMCI(Corrected Machine Check Interrupt) that
+		Intel processor supports.  Usually this disablement is
+		not recommended, but it might be handy if your hardware
+		is misbehaving.
+		Note that you'll get more problems without CMCI than with
+		due to the shared banks, i.e. you might get duplicated
+		error logs.
+   mce=dont_log_ce
+		Don't make logs for corrected errors.  All events reported
+		as corrected are silently cleared by OS.
+		This option will be useful if you have no interest in any
+		of corrected errors.
+   mce=ignore_ce
+		Disable features for corrected errors, e.g. polling timer
+		and CMCI.  All events reported as corrected are not cleared
+		by OS and remained in its error banks.
+		Usually this disablement is not recommended, however if
+		there is an agent checking/clearing corrected errors
+		(e.g. BIOS or hardware monitoring applications), conflicting
+		with OS's error handling, and you cannot deactivate the agent,
+		then this option will be a help.
+   mce=bootlog
+		Enable logging of machine checks left over from booting.
+		Disabled by default on AMD because some BIOS leave bogus ones.
+		If your BIOS doesn't do that it's a good idea to enable though
+		to make sure you log even machine check events that result
+		in a reboot. On Intel systems it is enabled by default.
    mce=nobootlog
 		Disable boot machine check logging.
-   mce=tolerancelevel (number)
+   mce=tolerancelevel[,monarchtimeout] (number,number)
+		tolerance levels:
 		0: always panic on uncorrected errors, log corrected errors
 		1: panic or SIGBUS on uncorrected errors, log corrected errors
 		2: SIGBUS or log uncorrected errors, log corrected errors
 		3: never panic or SIGBUS, log all errors (for testing only)
 		Default is 1
 		Can be also set using sysfs which is preferable.
+		monarchtimeout:
+		Sets the time in us to wait for other CPUs on machine checks. 0
+		to disable.
 
    nomce (for compatibility with i386): same as mce=off
 
@@ -150,11 +180,6 @@
 		Otherwise, the remaining system RAM is allocated to an
 		additional node.
 
-  numa=hotadd=percent
-		Only allow hotadd memory to preallocate page structures upto
-		percent of already available memory.
-		numa=hotadd=0 will disable hotadd memory.
-
 ACPI
 
   acpi=off	Don't enable ACPI
diff -druN linux-libre-2.6.30-gnu/Documentation/x86/x86_64/machinecheck linux-libre-2.6.31-gnu/Documentation/x86/x86_64/machinecheck
--- linux-libre-2.6.30-gnu/Documentation/x86/x86_64/machinecheck	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/x86/x86_64/machinecheck	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,9 @@
 	the polling interval.  When the poller stops finding MCEs, it
 	triggers an exponential backoff (poll less often) on the polling
 	interval. The check_interval variable is both the initial and
-	maximum polling interval.
+	maximum polling interval. 0 means no polling for corrected machine
+	check errors (but some corrected errors might be still reported
+	in other ways)
 
 tolerant
 	Tolerance level. When a machine check exception occurs for a non
@@ -67,6 +69,10 @@
 	Program to run when a machine check event is detected.
 	This is an alternative to running mcelog regularly from cron
 	and allows to detect events faster.
+monarch_timeout
+	How long to wait for the other CPUs to machine check too on a
+	exception. 0 to disable waiting for other CPUs.
+	Unit: us
 
 TBD document entries for AMD threshold interrupt configuration
 
diff -druN linux-libre-2.6.30-gnu/Documentation/x86/x86_64/mm.txt linux-libre-2.6.31-gnu/Documentation/x86/x86_64/mm.txt
--- linux-libre-2.6.30-gnu/Documentation/x86/x86_64/mm.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/Documentation/x86/x86_64/mm.txt	2009-09-09 18:13:59.000000000 -0400
@@ -6,10 +6,11 @@
 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
 hole caused by [48:63] sign extension
 ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
-ffff880000000000 - ffffc0ffffffffff (=57 TB) direct mapping of all phys. memory
-ffffc10000000000 - ffffc1ffffffffff (=40 bits) hole
-ffffc20000000000 - ffffe1ffffffffff (=45 bits) vmalloc/ioremap space
-ffffe20000000000 - ffffe2ffffffffff (=40 bits) virtual memory map (1TB)
+ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
+ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
+ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
+ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
+ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
 ... unused hole ...
 ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
 ffffffffa0000000 - fffffffffff00000 (=1536 MB) module mapping space
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/ac.c linux-libre-2.6.31-gnu/drivers/acpi/ac.c
--- linux-libre-2.6.30-gnu/drivers/acpi/ac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/ac.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,6 +61,7 @@
 static int acpi_ac_add(struct acpi_device *device);
 static int acpi_ac_remove(struct acpi_device *device, int type);
 static int acpi_ac_resume(struct acpi_device *device);
+static void acpi_ac_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id ac_device_ids[] = {
 	{"ACPI0003", 0},
@@ -72,10 +73,12 @@
 	.name = "ac",
 	.class = ACPI_AC_CLASS,
 	.ids = ac_device_ids,
+	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
 	.ops = {
 		.add = acpi_ac_add,
 		.remove = acpi_ac_remove,
 		.resume = acpi_ac_resume,
+		.notify = acpi_ac_notify,
 		},
 };
 
@@ -220,16 +223,14 @@
                                    Driver Model
    -------------------------------------------------------------------------- */
 
-static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
+static void acpi_ac_notify(struct acpi_device *device, u32 event)
 {
-	struct acpi_ac *ac = data;
-	struct acpi_device *device = NULL;
+	struct acpi_ac *ac = acpi_driver_data(device);
 
 
 	if (!ac)
 		return;
 
-	device = ac->device;
 	switch (event) {
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -253,7 +254,6 @@
 static int acpi_ac_add(struct acpi_device *device)
 {
 	int result = 0;
-	acpi_status status = AE_OK;
 	struct acpi_ac *ac = NULL;
 
 
@@ -286,13 +286,6 @@
 	ac->charger.get_property = get_ac_property;
 	power_supply_register(&ac->device->dev, &ac->charger);
 #endif
-	status = acpi_install_notify_handler(device->handle,
-					     ACPI_ALL_NOTIFY, acpi_ac_notify,
-					     ac);
-	if (ACPI_FAILURE(status)) {
-		result = -ENODEV;
-		goto end;
-	}
 
 	printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
@@ -328,7 +321,6 @@
 
 static int acpi_ac_remove(struct acpi_device *device, int type)
 {
-	acpi_status status = AE_OK;
 	struct acpi_ac *ac = NULL;
 
 
@@ -337,8 +329,6 @@
 
 	ac = acpi_driver_data(device);
 
-	status = acpi_remove_notify_handler(device->handle,
-					    ACPI_ALL_NOTIFY, acpi_ac_notify);
 #ifdef CONFIG_ACPI_SYSFS_POWER
 	if (ac->charger.dev)
 		power_supply_unregister(&ac->charger);
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/acevents.h linux-libre-2.6.31-gnu/drivers/acpi/acpica/acevents.h
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/acevents.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/acevents.h	2009-09-09 18:13:59.000000000 -0400
@@ -139,7 +139,7 @@
 acpi_status
 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 			       u32 function,
-			       acpi_physical_address address,
+			       u32 region_offset,
 			       u32 bit_width, acpi_integer * value);
 
 acpi_status
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/acglobal.h linux-libre-2.6.31-gnu/drivers/acpi/acpica/acglobal.h
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/acglobal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/acglobal.h	2009-09-09 18:13:59.000000000 -0400
@@ -362,9 +362,6 @@
 extern u8 acpi_gbl_abort_method;
 extern u8 acpi_gbl_db_terminate_threads;
 
-ACPI_EXTERN int optind;
-ACPI_EXTERN char *optarg;
-
 ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
 ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
 ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/aclocal.h linux-libre-2.6.31-gnu/drivers/acpi/acpica/aclocal.h
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/aclocal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/aclocal.h	2009-09-09 18:13:59.000000000 -0400
@@ -205,6 +205,7 @@
 #define ANOBJ_METHOD_LOCAL              0x08	/* Node is a method local */
 #define ANOBJ_SUBTREE_HAS_INI           0x10	/* Used to optimize device initialization */
 #define ANOBJ_EVALUATED                 0x20	/* Set on first evaluation of node */
+#define ANOBJ_ALLOCATED_BUFFER          0x40	/* Method AML buffer is dynamic (install_method) */
 
 #define ANOBJ_IS_EXTERNAL               0x08	/* i_aSL only: This object created via External() */
 #define ANOBJ_METHOD_NO_RETVAL          0x10	/* i_aSL only: Method has no return value */
@@ -788,11 +789,14 @@
 /* For control registers, both ignored and reserved bits must be preserved */
 
 /*
- * The ACPI spec says to ignore PM1_CTL.SCI_EN (bit 0)
- * but we need to be able to write ACPI_BITREG_SCI_ENABLE directly
- * as a BIOS workaround on some machines.
+ * For PM1 control, the SCI enable bit (bit 0, SCI_EN) is defined by the
+ * ACPI specification to be a "preserved" bit - "OSPM always preserves this
+ * bit position", section 4.7.3.2.1. However, on some machines the OS must
+ * write a one to this bit after resume for the machine to work properly.
+ * To enable this, we no longer attempt to preserve this bit. No machines
+ * are known to fail if the bit is not preserved. (May 2009)
  */
-#define ACPI_PM1_CONTROL_IGNORED_BITS           0x0200	/* Bits 9 */
+#define ACPI_PM1_CONTROL_IGNORED_BITS           0x0200	/* Bit 9 */
 #define ACPI_PM1_CONTROL_RESERVED_BITS          0xC1F8	/* Bits 14-15, 3-8 */
 #define ACPI_PM1_CONTROL_PRESERVED_BITS \
 	       (ACPI_PM1_CONTROL_IGNORED_BITS | ACPI_PM1_CONTROL_RESERVED_BITS)
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/acnamesp.h linux-libre-2.6.31-gnu/drivers/acpi/acpica/acnamesp.h
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/acnamesp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/acnamesp.h	2009-09-09 18:13:59.000000000 -0400
@@ -99,10 +99,19 @@
 		       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(struct acpi_namespace_node
+						  *parent,
+						  struct acpi_namespace_node
 						  *child);
 
+struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type,
+							struct
+							acpi_namespace_node
+							*parent,
+							struct
+							acpi_namespace_node
+							*child);
+
 /*
  * nsparse - table parsing
  */
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/acobject.h linux-libre-2.6.31-gnu/drivers/acpi/acpica/acobject.h
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/acobject.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/acobject.h	2009-09-09 18:13:59.000000000 -0400
@@ -97,6 +97,7 @@
 #define AOPOBJ_OBJECT_INITIALIZED   0x08
 #define AOPOBJ_SETUP_COMPLETE       0x10
 #define AOPOBJ_SINGLE_DATUM         0x20
+#define AOPOBJ_INVALID              0x40	/* Used if host OS won't allow an op_region address */
 
 /******************************************************************************
  *
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/amlcode.h linux-libre-2.6.31-gnu/drivers/acpi/acpica/amlcode.h
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/amlcode.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/amlcode.h	2009-09-09 18:13:59.000000000 -0400
@@ -483,7 +483,7 @@
 
 #define AML_METHOD_ARG_COUNT        0x07
 #define AML_METHOD_SERIALIZED       0x08
-#define AML_METHOD_SYNCH_LEVEL      0xF0
+#define AML_METHOD_SYNC_LEVEL       0xF0
 
 /* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/dsobject.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/dsobject.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/dsobject.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/dsobject.c	2009-09-09 18:13:59.000000000 -0400
@@ -734,7 +734,8 @@
 
 			/* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */
 
-			obj_desc->reference.value = opcode - AML_LOCAL_OP;
+			obj_desc->reference.value =
+			    ((u32)opcode) - AML_LOCAL_OP;
 			obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
 
 #ifndef ACPI_NO_METHOD_EXECUTION
@@ -754,7 +755,7 @@
 
 			/* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */
 
-			obj_desc->reference.value = opcode - AML_ARG_OP;
+			obj_desc->reference.value = ((u32)opcode) - AML_ARG_OP;
 			obj_desc->reference.class = ACPI_REFCLASS_ARG;
 
 #ifndef ACPI_NO_METHOD_EXECUTION
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/dsopcode.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/dsopcode.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/dsopcode.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/dsopcode.c	2009-09-09 18:13:59.000000000 -0400
@@ -397,6 +397,30 @@
 	status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
 					   extra_desc->extra.aml_length,
 					   extra_desc->extra.aml_start);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Validate the region address/length via the host OS */
+
+	status = acpi_os_validate_address(obj_desc->region.space_id,
+					  obj_desc->region.address,
+					  (acpi_size) obj_desc->region.length,
+					  acpi_ut_get_node_name(node));
+
+	if (ACPI_FAILURE(status)) {
+		/*
+		 * Invalid address/length. We will emit an error message and mark
+		 * the region as invalid, so that it will cause an additional error if
+		 * it is ever used. Then return AE_OK.
+		 */
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During address validation of OpRegion [%4.4s]",
+				node->name.ascii));
+		obj_desc->common.flags |= AOPOBJ_INVALID;
+		status = AE_OK;
+	}
+
 	return_ACPI_STATUS(status);
 }
 
@@ -1386,14 +1410,19 @@
 
 	case AML_BREAK_POINT_OP:
 
-		/* Call up to the OS service layer to handle this */
-
-		status =
-		    acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
-				   "Executed AML Breakpoint opcode");
+		/*
+		 * Set the single-step flag. This will cause the debugger (if present)
+		 * to break to the console within the AML debugger at the start of the
+		 * next AML instruction.
+		 */
+		ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE);
+		ACPI_DEBUGGER_EXEC(acpi_os_printf
+				   ("**break** Executed AML BreakPoint opcode\n"));
 
-		/* If and when it returns, all done. */
+		/* Call to the OSL in case OS wants a piece of the action */
 
+		status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
+					"Executed AML Breakpoint opcode");
 		break;
 
 	case AML_BREAK_OP:
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/dswstate.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/dswstate.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/dswstate.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/dswstate.c	2009-09-09 18:13:59.000000000 -0400
@@ -102,7 +102,7 @@
 	/* Return object of the top element and clean that top element result stack */
 
 	walk_state->result_count--;
-	index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
+	index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
 
 	*object = state->results.obj_desc[index];
 	if (!*object) {
@@ -186,7 +186,7 @@
 
 	/* Assign the address of object to the top free element of result stack */
 
-	index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
+	index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
 	state->results.obj_desc[index] = object;
 	walk_state->result_count++;
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/evregion.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/evregion.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/evregion.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/evregion.c	2009-09-09 18:13:59.000000000 -0400
@@ -275,7 +275,7 @@
  *
  * PARAMETERS:  region_obj          - Internal region object
  *              Function            - Read or Write operation
- *              Address             - Where in the space to read or write
+ *              region_offset       - Where in the region to read or write
  *              bit_width           - Field width in bits (8, 16, 32, or 64)
  *              Value               - Pointer to in or out value, must be
  *                                    full 64-bit acpi_integer
@@ -290,7 +290,7 @@
 acpi_status
 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 			       u32 function,
-			       acpi_physical_address address,
+			       u32 region_offset,
 			       u32 bit_width, acpi_integer * value)
 {
 	acpi_status status;
@@ -396,7 +396,8 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
 			  &region_obj->region.handler->address_space, handler,
-			  ACPI_FORMAT_NATIVE_UINT(address),
+			  ACPI_FORMAT_NATIVE_UINT(region_obj->region.address +
+						  region_offset),
 			  acpi_ut_get_region_name(region_obj->region.
 						  space_id)));
 
@@ -412,8 +413,9 @@
 
 	/* Call the handler */
 
-	status = handler(function, address, bit_width, value,
-			 handler_desc->address_space.context,
+	status = handler(function,
+			 (region_obj->region.address + region_offset),
+			 bit_width, value, handler_desc->address_space.context,
 			 region_obj2->extra.region_context);
 
 	if (ACPI_FAILURE(status)) {
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/evxfevnt.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/evxfevnt.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/evxfevnt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/evxfevnt.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,7 +51,7 @@
 ACPI_MODULE_NAME("evxfevnt")
 
 /* Local prototypes */
-acpi_status
+static acpi_status
 acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 		       struct acpi_gpe_block_info *gpe_block, void *context);
 
@@ -785,7 +785,7 @@
  *              block device. NULL if the GPE is one of the FADT-defined GPEs.
  *
  ******************************************************************************/
-acpi_status
+static acpi_status
 acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 		       struct acpi_gpe_block_info *gpe_block, void *context)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/exconfig.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/exconfig.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/exconfig.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/exconfig.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,6 +47,7 @@
 #include "acnamesp.h"
 #include "actables.h"
 #include "acdispat.h"
+#include "acevents.h"
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("exconfig")
@@ -57,6 +58,10 @@
 		  struct acpi_namespace_node *parent_node,
 		  union acpi_operand_object **ddb_handle);
 
+static acpi_status
+acpi_ex_region_read(union acpi_operand_object *obj_desc,
+		    u32 length, u8 *buffer);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ex_add_table
@@ -91,6 +96,7 @@
 
 	/* Init the table handle */
 
+	obj_desc->common.flags |= AOPOBJ_DATA_VALID;
 	obj_desc->reference.class = ACPI_REFCLASS_TABLE;
 	*ddb_handle = obj_desc;
 
@@ -229,6 +235,8 @@
 				       walk_state);
 		if (ACPI_FAILURE(status)) {
 			(void)acpi_ex_unload_table(ddb_handle);
+
+			acpi_ut_remove_reference(ddb_handle);
 			return_ACPI_STATUS(status);
 		}
 	}
@@ -254,6 +262,47 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ex_region_read
+ *
+ * PARAMETERS:  obj_desc        - Region descriptor
+ *              Length          - Number of bytes to read
+ *              Buffer          - Pointer to where to put the data
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Read data from an operation region. The read starts from the
+ *              beginning of the region.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
+{
+	acpi_status status;
+	acpi_integer value;
+	u32 region_offset = 0;
+	u32 i;
+
+	/* Bytewise reads */
+
+	for (i = 0; i < length; i++) {
+		status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
+							region_offset, 8,
+							&value);
+		if (ACPI_FAILURE(status)) {
+			return status;
+		}
+
+		*buffer = (u8)value;
+		buffer++;
+		region_offset++;
+	}
+
+	return AE_OK;
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ex_load_op
  *
  * PARAMETERS:  obj_desc        - Region or Buffer/Field where the table will be
@@ -314,18 +363,23 @@
 			}
 		}
 
-		/*
-		 * Map the table header and get the actual table length. The region
-		 * length is not guaranteed to be the same as the table length.
-		 */
-		table = acpi_os_map_memory(obj_desc->region.address,
-					   sizeof(struct acpi_table_header));
+		/* Get the table header first so we can get the table length */
+
+		table = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
 		if (!table) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
 
+		status =
+		    acpi_ex_region_read(obj_desc,
+					sizeof(struct acpi_table_header),
+					ACPI_CAST_PTR(u8, table));
 		length = table->length;
-		acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+		ACPI_FREE(table);
+
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
 
 		/* Must have at least an ACPI table header */
 
@@ -334,10 +388,19 @@
 		}
 
 		/*
-		 * The memory region is not guaranteed to remain stable and we must
-		 * copy the table to a local buffer. For example, the memory region
-		 * is corrupted after suspend on some machines. Dynamically loaded
-		 * tables are usually small, so this overhead is minimal.
+		 * The original implementation simply mapped the table, with no copy.
+		 * However, the memory region is not guaranteed to remain stable and
+		 * we must copy the table to a local buffer. For example, the memory
+		 * region is corrupted after suspend on some machines. Dynamically
+		 * loaded tables are usually small, so this overhead is minimal.
+		 *
+		 * The latest implementation (5/2009) does not use a mapping at all.
+		 * We use the low-level operation region interface to read the table
+		 * instead of the obvious optimization of using a direct mapping.
+		 * This maintains a consistent use of operation regions across the
+		 * entire subsystem. This is important if additional processing must
+		 * be performed in the (possibly user-installed) operation region
+		 * handler. For example, acpi_exec and ASLTS depend on this.
 		 */
 
 		/* Allocate a buffer for the table */
@@ -347,17 +410,16 @@
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
 
-		/* Map the entire table and copy it */
+		/* Read the entire table */
 
-		table = acpi_os_map_memory(obj_desc->region.address, length);
-		if (!table) {
+		status = acpi_ex_region_read(obj_desc, length,
+					     ACPI_CAST_PTR(u8,
+							   table_desc.pointer));
+		if (ACPI_FAILURE(status)) {
 			ACPI_FREE(table_desc.pointer);
-			return_ACPI_STATUS(AE_NO_MEMORY);
+			return_ACPI_STATUS(status);
 		}
 
-		ACPI_MEMCPY(table_desc.pointer, table, length);
-		acpi_os_unmap_memory(table, length);
-
 		table_desc.address = obj_desc->region.address;
 		break;
 
@@ -454,6 +516,10 @@
 		return_ACPI_STATUS(status);
 	}
 
+	/* Remove the reference by added by acpi_ex_store above */
+
+	acpi_ut_remove_reference(ddb_handle);
+
 	/* Invoke table handler if present */
 
 	if (acpi_gbl_table_handler) {
@@ -495,13 +561,18 @@
 
 	/*
 	 * Validate the handle
-	 * Although the handle is partially validated in acpi_ex_reconfiguration(),
+	 * Although the handle is partially validated in acpi_ex_reconfiguration()
 	 * when it calls acpi_ex_resolve_operands(), the handle is more completely
 	 * validated here.
+	 *
+	 * Handle must be a valid operand object of type reference. Also, the
+	 * ddb_handle must still be marked valid (table has not been previously
+	 * unloaded)
 	 */
 	if ((!ddb_handle) ||
 	    (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
-	    (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE)) {
+	    (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) ||
+	    (!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -509,6 +580,12 @@
 
 	table_index = table_desc->reference.value;
 
+	/* Ensure the table is still loaded */
+
+	if (!acpi_tb_is_table_loaded(table_index)) {
+		return_ACPI_STATUS(AE_NOT_EXIST);
+	}
+
 	/* Invoke table handler if present */
 
 	if (acpi_gbl_table_handler) {
@@ -530,8 +607,10 @@
 	(void)acpi_tb_release_owner_id(table_index);
 	acpi_tb_set_table_loaded_flag(table_index, FALSE);
 
-	/* Table unloaded, remove a reference to the ddb_handle object */
-
-	acpi_ut_remove_reference(ddb_handle);
+	/*
+	 * Invalidate the handle. We do this because the handle may be stored
+	 * in a named object and may not be actually deleted until much later.
+	 */
+	ddb_handle->common.flags &= ~AOPOBJ_DATA_VALID;
 	return_ACPI_STATUS(AE_OK);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/excreate.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/excreate.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/excreate.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/excreate.c	2009-09-09 18:13:59.000000000 -0400
@@ -502,7 +502,7 @@
 		 * ACPI 2.0: sync_level = sync_level in method declaration
 		 */
 		obj_desc->method.sync_level = (u8)
-		    ((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4);
+		    ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
 	}
 
 	/* Attach the new object to the method Node */
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/exdump.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/exdump.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/exdump.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/exdump.c	2009-09-09 18:13:59.000000000 -0400
@@ -120,9 +120,11 @@
 	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(event.os_semaphore), "OsSemaphore"}
 };
 
-static struct acpi_exdump_info acpi_ex_dump_method[8] = {
+static struct acpi_exdump_info acpi_ex_dump_method[9] = {
 	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL},
-	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "ParamCount"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.method_flags), "Method Flags"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count),
+	 "Parameter Count"},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.sync_level), "Sync Level"},
 	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.mutex), "Mutex"},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"},
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/exfldio.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/exfldio.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/exfldio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/exfldio.c	2009-09-09 18:13:59.000000000 -0400
@@ -113,6 +113,12 @@
 		}
 	}
 
+	/* Exit if Address/Length have been disallowed by the host OS */
+
+	if (rgn_desc->common.flags & AOPOBJ_INVALID) {
+		return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
+	}
+
 	/*
 	 * Exit now for SMBus address space, it has a non-linear address space
 	 * and the request cannot be directly validated
@@ -222,7 +228,7 @@
 {
 	acpi_status status;
 	union acpi_operand_object *rgn_desc;
-	acpi_physical_address address;
+	u32 region_offset;
 
 	ACPI_FUNCTION_TRACE(ex_access_region);
 
@@ -243,7 +249,7 @@
 	 * 3) The current offset into the field
 	 */
 	rgn_desc = obj_desc->common_field.region_obj;
-	address = rgn_desc->region.address +
+	region_offset =
 	    obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
 
 	if ((function & ACPI_IO_MASK) == ACPI_READ) {
@@ -260,16 +266,18 @@
 			      obj_desc->common_field.access_byte_width,
 			      obj_desc->common_field.base_byte_offset,
 			      field_datum_byte_offset, ACPI_CAST_PTR(void,
-								     address)));
+								     (rgn_desc->
+								      region.
+								      address +
+								      region_offset))));
 
 	/* Invoke the appropriate address_space/op_region handler */
 
-	status = acpi_ev_address_space_dispatch(rgn_desc, function,
-						address,
-						ACPI_MUL_8(obj_desc->
-							   common_field.
-							   access_byte_width),
-						value);
+	status =
+	    acpi_ev_address_space_dispatch(rgn_desc, function, region_offset,
+					   ACPI_MUL_8(obj_desc->common_field.
+						      access_byte_width),
+					   value);
 
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_NOT_IMPLEMENTED) {
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/exmutex.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/exmutex.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/exmutex.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/exmutex.c	2009-09-09 18:13:59.000000000 -0400
@@ -83,6 +83,15 @@
 
 	if (obj_desc->mutex.prev) {
 		(obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
+
+		/*
+		 * Migrate the previous sync level associated with this mutex to the
+		 * previous mutex on the list so that it may be preserved. This handles
+		 * the case where several mutexes have been acquired at the same level,
+		 * but are not released in opposite order.
+		 */
+		(obj_desc->mutex.prev)->mutex.original_sync_level =
+		    obj_desc->mutex.original_sync_level;
 	} else {
 		thread->acquired_mutex_list = obj_desc->mutex.next;
 	}
@@ -349,6 +358,7 @@
 		      struct acpi_walk_state *walk_state)
 {
 	acpi_status status = AE_OK;
+	u8 previous_sync_level;
 
 	ACPI_FUNCTION_TRACE(ex_release_mutex);
 
@@ -373,11 +383,12 @@
 	     walk_state->thread->thread_id)
 	    && (obj_desc != 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,
+			    "Thread %p cannot release Mutex [%4.4s] acquired by thread %p",
+			    ACPI_CAST_PTR(void, walk_state->thread->thread_id),
 			    acpi_ut_get_node_name(obj_desc->mutex.node),
-			    (unsigned long)obj_desc->mutex.owner_thread->
-			    thread_id));
+			    ACPI_CAST_PTR(void,
+					  obj_desc->mutex.owner_thread->
+					  thread_id)));
 		return_ACPI_STATUS(AE_AML_NOT_OWNER);
 	}
 
@@ -391,10 +402,14 @@
 	}
 
 	/*
-	 * The sync level of the mutex must be less than or equal to the current
-	 * sync level
+	 * The sync level of the mutex must be equal to the current sync level. In
+	 * other words, the current level means that at least one mutex at that
+	 * level is currently being held. Attempting to release a mutex of a
+	 * different level can only mean that the mutex ordering rule is being
+	 * violated. This behavior is clarified in ACPI 4.0 specification.
 	 */
-	if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
+	if (obj_desc->mutex.sync_level !=
+	    walk_state->thread->current_sync_level) {
 		ACPI_ERROR((AE_INFO,
 			    "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d",
 			    acpi_ut_get_node_name(obj_desc->mutex.node),
@@ -403,14 +418,24 @@
 		return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
 	}
 
+	/*
+	 * Get the previous sync_level from the head of the acquired mutex list.
+	 * This handles the case where several mutexes at the same level have been
+	 * acquired, but are not released in reverse order.
+	 */
+	previous_sync_level =
+	    walk_state->thread->acquired_mutex_list->mutex.original_sync_level;
+
 	status = acpi_ex_release_mutex_object(obj_desc);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
 
 	if (obj_desc->mutex.acquisition_depth == 0) {
 
-		/* Restore the original sync_level */
+		/* Restore the previous sync_level */
 
-		walk_state->thread->current_sync_level =
-		    obj_desc->mutex.original_sync_level;
+		walk_state->thread->current_sync_level = previous_sync_level;
 	}
 	return_ACPI_STATUS(status);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/exstore.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/exstore.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/exstore.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/exstore.c	2009-09-09 18:13:59.000000000 -0400
@@ -193,10 +193,12 @@
 
 		case ACPI_REFCLASS_TABLE:
 
+			/* Case for ddb_handle */
+
 			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
 					      "Table Index 0x%X\n",
 					      source_desc->reference.value));
-			break;
+			return;
 
 		default:
 			break;
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/exstorob.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/exstorob.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/exstorob.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/exstorob.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,6 +70,12 @@
 
 	ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
 
+	/* If Source and Target are the same, just return */
+
+	if (source_desc == target_desc) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
 	/* We know that source_desc is a buffer by now */
 
 	buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
@@ -161,6 +167,12 @@
 
 	ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
 
+	/* If Source and Target are the same, just return */
+
+	if (source_desc == target_desc) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
 	/* We know that source_desc is a string by now */
 
 	buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/hwregs.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/hwregs.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/hwregs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/hwregs.c	2009-09-09 18:13:59.000000000 -0400
@@ -81,9 +81,9 @@
 
 	ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %0llX\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
 			  ACPI_BITMASK_ALL_FIXED_STATUS,
-			  acpi_gbl_xpm1a_status.address));
+			  ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
 
 	lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsalloc.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsalloc.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsalloc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsalloc.c	2009-09-09 18:13:59.000000000 -0400
@@ -334,9 +334,7 @@
 
 		/* Get the next node in this scope (NULL if none) */
 
-		child_node =
-		    acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
-					  child_node);
+		child_node = acpi_ns_get_next_node(parent_node, child_node);
 		if (child_node) {
 
 			/* Found a child node - detach any attached object */
@@ -345,8 +343,7 @@
 
 			/* Check if this node has any children */
 
-			if (acpi_ns_get_next_node
-			    (ACPI_TYPE_ANY, child_node, NULL)) {
+			if (child_node->child) {
 				/*
 				 * There is at least one child of this node,
 				 * visit the node
@@ -432,9 +429,7 @@
 		 * Get the next child of this parent node. When child_node is NULL,
 		 * the first child of the parent is returned
 		 */
-		child_node =
-		    acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
-					  child_node);
+		child_node = acpi_ns_get_next_node(parent_node, child_node);
 
 		if (deletion_node) {
 			acpi_ns_delete_children(deletion_node);
@@ -452,8 +447,7 @@
 
 			/* Check if this node has any children */
 
-			if (acpi_ns_get_next_node
-			    (ACPI_TYPE_ANY, child_node, NULL)) {
+			if (child_node->child) {
 				/*
 				 * There is at least one child of this node,
 				 * visit the node
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsnames.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsnames.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsnames.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsnames.c	2009-09-09 18:13:59.000000000 -0400
@@ -149,7 +149,7 @@
 
 	name_buffer = ACPI_ALLOCATE_ZEROED(size);
 	if (!name_buffer) {
-		ACPI_ERROR((AE_INFO, "Allocation failure"));
+		ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
 		return_PTR(NULL);
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsobject.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsobject.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsobject.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsobject.c	2009-09-09 18:13:59.000000000 -0400
@@ -213,6 +213,15 @@
 		return_VOID;
 	}
 
+	if (node->flags & ANOBJ_ALLOCATED_BUFFER) {
+
+		/* Free the dynamic aml buffer */
+
+		if (obj_desc->common.type == ACPI_TYPE_METHOD) {
+			ACPI_FREE(obj_desc->method.aml_start);
+		}
+	}
+
 	/* Clear the entry in all cases */
 
 	node->object = NULL;
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nspredef.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nspredef.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nspredef.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nspredef.c	2009-09-09 18:13:59.000000000 -0400
@@ -144,7 +144,7 @@
 
 	pathname = acpi_ns_get_external_pathname(node);
 	if (!pathname) {
-		pathname = ACPI_CAST_PTR(char, predefined->info.name);
+		return AE_OK;	/* Could not get pathname, ignore */
 	}
 
 	/*
@@ -230,10 +230,7 @@
 	}
 
       exit:
-	if (pathname != predefined->info.name) {
-		ACPI_FREE(pathname);
-	}
-
+	ACPI_FREE(pathname);
 	return (status);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nssearch.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nssearch.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nssearch.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nssearch.c	2009-09-09 18:13:59.000000000 -0400
@@ -45,6 +45,10 @@
 #include "accommon.h"
 #include "acnamesp.h"
 
+#ifdef ACPI_ASL_COMPILER
+#include "amlcode.h"
+#endif
+
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nssearch")
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nswalk.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nswalk.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nswalk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nswalk.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,8 +52,7 @@
  *
  * FUNCTION:    acpi_ns_get_next_node
  *
- * PARAMETERS:  Type                - Type of node to be searched for
- *              parent_node         - Parent node whose children we are
+ * PARAMETERS:  parent_node         - Parent node whose children we are
  *                                    getting
  *              child_node          - Previous child that was found.
  *                                    The NEXT child will be returned
@@ -66,27 +65,68 @@
  *              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(struct acpi_namespace_node
+						  *parent_node,
+						  struct acpi_namespace_node
 						  *child_node)
 {
-	struct acpi_namespace_node *next_node = NULL;
-
 	ACPI_FUNCTION_ENTRY();
 
 	if (!child_node) {
 
 		/* It's really the parent's _scope_ that we want */
 
-		next_node = parent_node->child;
+		return parent_node->child;
 	}
 
-	else {
-		/* Start search at the NEXT node */
-
-		next_node = acpi_ns_get_next_valid_node(child_node);
+	/*
+	 * Get the next node.
+	 *
+	 * If we are at the end of this peer list, return NULL
+	 */
+	if (child_node->flags & ANOBJ_END_OF_PEER_LIST) {
+		return NULL;
 	}
 
+	/* Otherwise just return the next peer */
+
+	return child_node->peer;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_get_next_node_typed
+ *
+ * PARAMETERS:  Type                - Type of node to be searched for
+ *              parent_node         - Parent node whose children we are
+ *                                    getting
+ *              child_node          - Previous child that was found.
+ *                                    The NEXT child will be returned
+ *
+ * RETURN:      struct acpi_namespace_node - Pointer to the NEXT child or NULL if
+ *                                    none is found.
+ *
+ * DESCRIPTION: Return the next peer node within the namespace.  If Handle
+ *              is valid, Scope is ignored.  Otherwise, the first node
+ *              within Scope is returned.
+ *
+ ******************************************************************************/
+
+struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type,
+							struct
+							acpi_namespace_node
+							*parent_node,
+							struct
+							acpi_namespace_node
+							*child_node)
+{
+	struct acpi_namespace_node *next_node = NULL;
+
+	ACPI_FUNCTION_ENTRY();
+
+	next_node = acpi_ns_get_next_node(parent_node, child_node);
+
+
 	/* If any type is OK, we are done */
 
 	if (type == ACPI_TYPE_ANY) {
@@ -186,9 +226,7 @@
 		/* Get the next node in this scope.  Null if not found */
 
 		status = AE_OK;
-		child_node =
-		    acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
-					  child_node);
+		child_node = acpi_ns_get_next_node(parent_node, child_node);
 		if (child_node) {
 
 			/* Found next child, get the type if we are not searching for ANY */
@@ -269,8 +307,7 @@
 			 * function has specified that the maximum depth has been reached.
 			 */
 			if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
-				if (acpi_ns_get_next_node
-				    (ACPI_TYPE_ANY, child_node, NULL)) {
+				if (child_node->child) {
 
 					/* There is at least one child of this node, visit it */
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsxfname.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsxfname.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsxfname.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsxfname.c	2009-09-09 18:13:59.000000000 -0400
@@ -45,6 +45,8 @@
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
+#include "acparser.h"
+#include "amlcode.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsxfname")
@@ -358,3 +360,151 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_get_object_info)
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_install_method
+ *
+ * PARAMETERS:  Buffer         - An ACPI table containing one control method
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a control method into the namespace. If the method
+ *              name already exists in the namespace, it is overwritten. The
+ *              input buffer must contain a valid DSDT or SSDT containing a
+ *              single control method.
+ *
+ ******************************************************************************/
+acpi_status acpi_install_method(u8 *buffer)
+{
+	struct acpi_table_header *table =
+	    ACPI_CAST_PTR(struct acpi_table_header, buffer);
+	u8 *aml_buffer;
+	u8 *aml_start;
+	char *path;
+	struct acpi_namespace_node *node;
+	union acpi_operand_object *method_obj;
+	struct acpi_parse_state parser_state;
+	u32 aml_length;
+	u16 opcode;
+	u8 method_flags;
+	acpi_status status;
+
+	/* Parameter validation */
+
+	if (!buffer) {
+		return AE_BAD_PARAMETER;
+	}
+
+	/* Table must be a DSDT or SSDT */
+
+	if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) &&
+	    !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) {
+		return AE_BAD_HEADER;
+	}
+
+	/* First AML opcode in the table must be a control method */
+
+	parser_state.aml = buffer + sizeof(struct acpi_table_header);
+	opcode = acpi_ps_peek_opcode(&parser_state);
+	if (opcode != AML_METHOD_OP) {
+		return AE_BAD_PARAMETER;
+	}
+
+	/* Extract method information from the raw AML */
+
+	parser_state.aml += acpi_ps_get_opcode_size(opcode);
+	parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
+	path = acpi_ps_get_next_namestring(&parser_state);
+	method_flags = *parser_state.aml++;
+	aml_start = parser_state.aml;
+	aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
+
+	/*
+	 * Allocate resources up-front. We don't want to have to delete a new
+	 * node from the namespace if we cannot allocate memory.
+	 */
+	aml_buffer = ACPI_ALLOCATE(aml_length);
+	if (!aml_buffer) {
+		return AE_NO_MEMORY;
+	}
+
+	method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
+	if (!method_obj) {
+		ACPI_FREE(aml_buffer);
+		return AE_NO_MEMORY;
+	}
+
+	/* Lock namespace for acpi_ns_lookup, we may be creating a new node */
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		goto error_exit;
+	}
+
+	/* The lookup either returns an existing node or creates a new one */
+
+	status =
+	    acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
+			   ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
+			   NULL, &node);
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
+	if (ACPI_FAILURE(status)) {	/* ns_lookup */
+		if (status != AE_ALREADY_EXISTS) {
+			goto error_exit;
+		}
+
+		/* Node existed previously, make sure it is a method node */
+
+		if (node->type != ACPI_TYPE_METHOD) {
+			status = AE_TYPE;
+			goto error_exit;
+		}
+	}
+
+	/* Copy the method AML to the local buffer */
+
+	ACPI_MEMCPY(aml_buffer, aml_start, aml_length);
+
+	/* Initialize the method object with the new method's information */
+
+	method_obj->method.aml_start = aml_buffer;
+	method_obj->method.aml_length = aml_length;
+
+	method_obj->method.param_count = (u8)
+	    (method_flags & AML_METHOD_ARG_COUNT);
+
+	method_obj->method.method_flags = (u8)
+	    (method_flags & ~AML_METHOD_ARG_COUNT);
+
+	if (method_flags & AML_METHOD_SERIALIZED) {
+		method_obj->method.sync_level = (u8)
+		    ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
+	}
+
+	/*
+	 * Now that it is complete, we can attach the new method object to
+	 * the method Node (detaches/deletes any existing object)
+	 */
+	status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD);
+
+	/*
+	 * Flag indicates AML buffer is dynamic, must be deleted later.
+	 * Must be set only after attach above.
+	 */
+	node->flags |= ANOBJ_ALLOCATED_BUFFER;
+
+	/* Remove local reference to the method object */
+
+	acpi_ut_remove_reference(method_obj);
+	return status;
+
+error_exit:
+
+	ACPI_FREE(aml_buffer);
+	ACPI_FREE(method_obj);
+	return status;
+}
+ACPI_EXPORT_SYMBOL(acpi_install_method)
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsxfobj.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsxfobj.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/nsxfobj.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/nsxfobj.c	2009-09-09 18:13:59.000000000 -0400
@@ -162,6 +162,7 @@
 acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
 {
 	struct acpi_namespace_node *node;
+	struct acpi_namespace_node *parent_node;
 	acpi_status status;
 
 	if (!ret_handle) {
@@ -189,12 +190,12 @@
 
 	/* Get the parent entry */
 
-	*ret_handle =
-	    acpi_ns_convert_entry_to_handle(acpi_ns_get_parent_node(node));
+	parent_node = acpi_ns_get_parent_node(node);
+	*ret_handle = acpi_ns_convert_entry_to_handle(parent_node);
 
 	/* Return exception if parent is null */
 
-	if (!acpi_ns_get_parent_node(node)) {
+	if (!parent_node) {
 		status = AE_NULL_ENTRY;
 	}
 
@@ -268,7 +269,7 @@
 
 	/* Internal function does the real work */
 
-	node = acpi_ns_get_next_node(type, parent_node, child_node);
+	node = acpi_ns_get_next_node_typed(type, parent_node, child_node);
 	if (!node) {
 		status = AE_NOT_FOUND;
 		goto unlock_and_exit;
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/rscalc.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/rscalc.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/rscalc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/rscalc.c	2009-09-09 18:13:59.000000000 -0400
@@ -547,7 +547,7 @@
 
 		if (!package_element ||
 		    (package_element->common.type != ACPI_TYPE_PACKAGE)) {
-			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
 
 		/*
@@ -593,9 +593,6 @@
 			} else {
 				temp_size_needed +=
 				    acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
-				if (!temp_size_needed) {
-					return_ACPI_STATUS(AE_BAD_PARAMETER);
-				}
 			}
 		} else {
 			/*
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/rsxface.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/rsxface.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/rsxface.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/rsxface.c	2009-09-09 18:13:59.000000000 -0400
@@ -338,13 +338,17 @@
 	switch (resource->type) {
 	case ACPI_RESOURCE_TYPE_ADDRESS16:
 
-		address16 = (struct acpi_resource_address16 *)&resource->data;
+		address16 =
+		    ACPI_CAST_PTR(struct acpi_resource_address16,
+				  &resource->data);
 		ACPI_COPY_ADDRESS(out, address16);
 		break;
 
 	case ACPI_RESOURCE_TYPE_ADDRESS32:
 
-		address32 = (struct acpi_resource_address32 *)&resource->data;
+		address32 =
+		    ACPI_CAST_PTR(struct acpi_resource_address32,
+				  &resource->data);
 		ACPI_COPY_ADDRESS(out, address32);
 		break;
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/tbfadt.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/tbfadt.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/tbfadt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/tbfadt.c	2009-09-09 18:13:59.000000000 -0400
@@ -284,9 +284,9 @@
 	if (length > sizeof(struct acpi_table_fadt)) {
 		ACPI_WARNING((AE_INFO,
 			      "FADT (revision %u) is longer than ACPI 2.0 version, "
-			      "truncating length 0x%X to 0x%zX",
-			      table->revision, (unsigned)length,
-			      sizeof(struct acpi_table_fadt)));
+			      "truncating length 0x%X to 0x%X",
+			      table->revision, length,
+			      (u32)sizeof(struct acpi_table_fadt)));
 	}
 
 	/* Clear the entire local FADT */
@@ -441,7 +441,7 @@
 								   &acpi_gbl_FADT,
 								   fadt_info_table
 								   [i].length),
-						     address32);
+						     (u64) address32);
 		}
 	}
 }
@@ -469,7 +469,6 @@
 static void acpi_tb_validate_fadt(void)
 {
 	char *name;
-	u32 *address32;
 	struct acpi_generic_address *address64;
 	u8 length;
 	u32 i;
@@ -505,15 +504,12 @@
 
 	for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
 		/*
-		 * Generate pointers to the 32-bit and 64-bit addresses, get the
-		 * register length (width), and the register name
+		 * Generate pointer to the 64-bit address, get the register
+		 * length (width) and the register name
 		 */
 		address64 = ACPI_ADD_PTR(struct acpi_generic_address,
 					 &acpi_gbl_FADT,
 					 fadt_info_table[i].address64);
-		address32 =
-		    ACPI_ADD_PTR(u32, &acpi_gbl_FADT,
-				 fadt_info_table[i].address32);
 		length =
 		    *ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
 				  fadt_info_table[i].length);
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/tbinstal.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/tbinstal.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/tbinstal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/tbinstal.c	2009-09-09 18:13:59.000000000 -0400
@@ -472,7 +472,7 @@
 	 * lock may block, and also since the execution of a namespace walk
 	 * must be allowed to use the interpreter.
 	 */
-	acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
+	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
 	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
 
 	acpi_ns_delete_namespace_by_owner(owner_id);
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/utcopy.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/utcopy.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/utcopy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/utcopy.c	2009-09-09 18:13:59.000000000 -0400
@@ -676,6 +676,7 @@
 {
 	u16 reference_count;
 	union acpi_operand_object *next_object;
+	acpi_status status;
 
 	/* Save fields from destination that we don't want to overwrite */
 
@@ -768,6 +769,28 @@
 		}
 		break;
 
+		/*
+		 * For Mutex and Event objects, we cannot simply copy the underlying
+		 * OS object. We must create a new one.
+		 */
+	case ACPI_TYPE_MUTEX:
+
+		status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex);
+		if (ACPI_FAILURE(status)) {
+			return status;
+		}
+		break;
+
+	case ACPI_TYPE_EVENT:
+
+		status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
+						  &dest_desc->event.
+						  os_semaphore);
+		if (ACPI_FAILURE(status)) {
+			return status;
+		}
+		break;
+
 	default:
 		/* Nothing to do for other simple objects */
 		break;
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/utdebug.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/utdebug.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/utdebug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/utdebug.c	2009-09-09 18:13:59.000000000 -0400
@@ -179,9 +179,9 @@
 	if (thread_id != acpi_gbl_prev_thread_id) {
 		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);
+			    ("\n**** Context Switch from TID %p to TID %p ****\n\n",
+			     ACPI_CAST_PTR(void, acpi_gbl_prev_thread_id),
+			     ACPI_CAST_PTR(void, thread_id));
 		}
 
 		acpi_gbl_prev_thread_id = thread_id;
@@ -194,7 +194,7 @@
 	acpi_os_printf("%8s-%04ld ", module_name, line_number);
 
 	if (ACPI_LV_THREADS & acpi_dbg_level) {
-		acpi_os_printf("[%04lX] ", (unsigned long)thread_id);
+		acpi_os_printf("[%p] ", ACPI_CAST_PTR(void, thread_id));
 	}
 
 	acpi_os_printf("[%02ld] %-22.22s: ",
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/utdelete.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/utdelete.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/utdelete.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/utdelete.c	2009-09-09 18:13:59.000000000 -0400
@@ -75,6 +75,7 @@
 	union acpi_operand_object *handler_desc;
 	union acpi_operand_object *second_desc;
 	union acpi_operand_object *next_desc;
+	union acpi_operand_object **last_obj_ptr;
 
 	ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object);
 
@@ -223,6 +224,26 @@
 			 */
 			handler_desc = object->region.handler;
 			if (handler_desc) {
+				next_desc =
+				    handler_desc->address_space.region_list;
+				last_obj_ptr =
+				    &handler_desc->address_space.region_list;
+
+				/* Remove the region object from the handler's list */
+
+				while (next_desc) {
+					if (next_desc == object) {
+						*last_obj_ptr =
+						    next_desc->region.next;
+						break;
+					}
+
+					/* Walk the linked list of handler */
+
+					last_obj_ptr = &next_desc->region.next;
+					next_desc = next_desc->region.next;
+				}
+
 				if (handler_desc->address_space.handler_flags &
 				    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/utmisc.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/utmisc.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/utmisc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/utmisc.c	2009-09-09 18:13:59.000000000 -0400
@@ -1033,11 +1033,12 @@
 {
 	va_list args;
 
-	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
+	acpi_os_printf("ACPI Error: ");
 
 	va_start(args, format);
 	acpi_os_vprintf(format, args);
-	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+	acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
+		       line_number);
 	va_end(args);
 }
 
@@ -1047,12 +1048,12 @@
 {
 	va_list args;
 
-	acpi_os_printf("ACPI Exception (%s-%04d): %s, ", module_name,
-		       line_number, acpi_format_exception(status));
+	acpi_os_printf("ACPI Exception: %s, ", acpi_format_exception(status));
 
 	va_start(args, format);
 	acpi_os_vprintf(format, args);
-	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+	acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
+		       line_number);
 	va_end(args);
 }
 
@@ -1061,11 +1062,12 @@
 {
 	va_list args;
 
-	acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
+	acpi_os_printf("ACPI Warning: ");
 
 	va_start(args, format);
 	acpi_os_vprintf(format, args);
-	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+	acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name,
+		       line_number);
 	va_end(args);
 }
 
@@ -1074,10 +1076,6 @@
 {
 	va_list args;
 
-	/*
-	 * Removed module_name, line_number, and acpica version, not needed
-	 * for info output
-	 */
 	acpi_os_printf("ACPI: ");
 
 	va_start(args, format);
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpica/utmutex.c linux-libre-2.6.31-gnu/drivers/acpi/acpica/utmutex.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpica/utmutex.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpica/utmutex.c	2009-09-09 18:13:59.000000000 -0400
@@ -230,17 +230,18 @@
 			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
 					ACPI_ERROR((AE_INFO,
-						    "Mutex [%s] already acquired by this thread [%X]",
+						    "Mutex [%s] already acquired by this thread [%p]",
 						    acpi_ut_get_mutex_name
 						    (mutex_id),
-						    this_thread_id));
+						    ACPI_CAST_PTR(void,
+								  this_thread_id)));
 
 					return (AE_ALREADY_ACQUIRED);
 				}
 
 				ACPI_ERROR((AE_INFO,
-					    "Invalid acquire order: Thread %X owns [%s], wants [%s]",
-					    this_thread_id,
+					    "Invalid acquire order: Thread %p owns [%s], wants [%s]",
+					    ACPI_CAST_PTR(void, this_thread_id),
 					    acpi_ut_get_mutex_name(i),
 					    acpi_ut_get_mutex_name(mutex_id)));
 
@@ -251,24 +252,24 @@
 #endif
 
 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-			  "Thread %lX attempting to acquire Mutex [%s]\n",
-			  (unsigned long)this_thread_id,
+			  "Thread %p attempting to acquire Mutex [%s]\n",
+			  ACPI_CAST_PTR(void, this_thread_id),
 			  acpi_ut_get_mutex_name(mutex_id)));
 
 	status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
 				       ACPI_WAIT_FOREVER);
 	if (ACPI_SUCCESS(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-				  "Thread %lX acquired Mutex [%s]\n",
-				  (unsigned long)this_thread_id,
+				  "Thread %p acquired Mutex [%s]\n",
+				  ACPI_CAST_PTR(void, this_thread_id),
 				  acpi_ut_get_mutex_name(mutex_id)));
 
 		acpi_gbl_mutex_info[mutex_id].use_count++;
 		acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
 	} else {
 		ACPI_EXCEPTION((AE_INFO, status,
-				"Thread %lX could not acquire Mutex [%X]",
-				(unsigned long)this_thread_id, mutex_id));
+				"Thread %p could not acquire Mutex [%X]",
+				ACPI_CAST_PTR(void, this_thread_id), mutex_id));
 	}
 
 	return (status);
@@ -293,9 +294,8 @@
 	ACPI_FUNCTION_NAME(ut_release_mutex);
 
 	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,
+	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n",
+			  ACPI_CAST_PTR(void, this_thread_id),
 			  acpi_ut_get_mutex_name(mutex_id)));
 
 	if (mutex_id > ACPI_MAX_MUTEX) {
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/acpi_memhotplug.c linux-libre-2.6.31-gnu/drivers/acpi/acpi_memhotplug.c
--- linux-libre-2.6.30-gnu/drivers/acpi/acpi_memhotplug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/acpi_memhotplug.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,9 @@
 
 #define _COMPONENT		ACPI_MEMORY_DEVICE_COMPONENT
 
+#undef PREFIX
+#define 	PREFIX		"ACPI:memory_hp:"
+
 ACPI_MODULE_NAME("acpi_memhotplug");
 MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
 MODULE_DESCRIPTION("Hotplug Mem Driver");
@@ -153,6 +156,7 @@
 	acpi_handle phandle;
 	struct acpi_device *device = NULL;
 	struct acpi_device *pdevice = NULL;
+	int result;
 
 
 	if (!acpi_bus_get_device(handle, &device) && device)
@@ -165,9 +169,9 @@
 	}
 
 	/* Get the parent device */
-	status = acpi_bus_get_device(phandle, &pdevice);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Cannot get acpi bus device"));
+	result = acpi_bus_get_device(phandle, &pdevice);
+	if (result) {
+		printk(KERN_WARNING PREFIX "Cannot get acpi bus device");
 		return -EINVAL;
 	}
 
@@ -175,9 +179,9 @@
 	 * Now add the notified device.  This creates the acpi_device
 	 * and invokes .add function
 	 */
-	status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Cannot add acpi bus"));
+	result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
+	if (result) {
+		printk(KERN_WARNING PREFIX "Cannot add acpi bus");
 		return -EINVAL;
 	}
 
@@ -238,7 +242,12 @@
 			num_enabled++;
 			continue;
 		}
-
+		/*
+		 * If the memory block size is zero, please ignore it.
+		 * Don't try to do the following memory hotplug flowchart.
+		 */
+		if (!info->length)
+			continue;
 		if (node < 0)
 			node = memory_add_physaddr_to_nid(info->start_addr);
 
@@ -253,8 +262,15 @@
 		mem_device->state = MEMORY_INVALID_STATE;
 		return -EINVAL;
 	}
-
-	return result;
+	/*
+	 * Sometimes the memory device will contain several memory blocks.
+	 * When one memory block is hot-added to the system memory, it will
+	 * be regarded as a success.
+	 * Otherwise if the last memory block can't be hot-added to the system
+	 * memory, it will be failure and the memory device can't be bound with
+	 * driver.
+	 */
+	return 0;
 }
 
 static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/battery.c linux-libre-2.6.31-gnu/drivers/acpi/battery.c
--- linux-libre-2.6.30-gnu/drivers/acpi/battery.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/battery.c	2009-09-09 18:13:59.000000000 -0400
@@ -796,13 +796,12 @@
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
-static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
+static void acpi_battery_notify(struct acpi_device *device, u32 event)
 {
-	struct acpi_battery *battery = data;
-	struct acpi_device *device;
+	struct acpi_battery *battery = acpi_driver_data(device);
+
 	if (!battery)
 		return;
-	device = battery->device;
 	acpi_battery_update(battery);
 	acpi_bus_generate_proc_event(device, event,
 				     acpi_battery_present(battery));
@@ -819,7 +818,6 @@
 static int acpi_battery_add(struct acpi_device *device)
 {
 	int result = 0;
-	acpi_status status = 0;
 	struct acpi_battery *battery = NULL;
 	if (!device)
 		return -EINVAL;
@@ -834,22 +832,12 @@
 	acpi_battery_update(battery);
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	result = acpi_battery_add_fs(device);
-	if (result)
-		goto end;
 #endif
-	status = acpi_install_notify_handler(device->handle,
-					     ACPI_ALL_NOTIFY,
-					     acpi_battery_notify, battery);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler"));
-		result = -ENODEV;
-		goto end;
-	}
-	printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
-	       ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
-	       device->status.battery_present ? "present" : "absent");
-      end:
-	if (result) {
+	if (!result) {
+		printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
+			ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
+			device->status.battery_present ? "present" : "absent");
+	} else {
 #ifdef CONFIG_ACPI_PROCFS_POWER
 		acpi_battery_remove_fs(device);
 #endif
@@ -860,15 +848,11 @@
 
 static int acpi_battery_remove(struct acpi_device *device, int type)
 {
-	acpi_status status = 0;
 	struct acpi_battery *battery = NULL;
 
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 	battery = acpi_driver_data(device);
-	status = acpi_remove_notify_handler(device->handle,
-					    ACPI_ALL_NOTIFY,
-					    acpi_battery_notify);
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_battery_remove_fs(device);
 #endif
@@ -896,10 +880,12 @@
 	.name = "battery",
 	.class = ACPI_BATTERY_CLASS,
 	.ids = battery_device_ids,
+	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
 	.ops = {
 		.add = acpi_battery_add,
 		.resume = acpi_battery_resume,
 		.remove = acpi_battery_remove,
+		.notify = acpi_battery_notify,
 		},
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/blacklist.c linux-libre-2.6.31-gnu/drivers/acpi/blacklist.c
--- linux-libre-2.6.30-gnu/drivers/acpi/blacklist.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/blacklist.c	2009-09-09 18:13:59.000000000 -0400
@@ -192,6 +192,22 @@
 		     DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
 		},
 	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Sony VGN-NS10J_S",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Sony VGN-SR290J",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"),
+		},
+	},
 
 	/*
 	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/bus.c linux-libre-2.6.31-gnu/drivers/acpi/bus.c
--- linux-libre-2.6.30-gnu/drivers/acpi/bus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/bus.c	2009-09-09 18:13:59.000000000 -0400
@@ -450,18 +450,16 @@
                              Notification Handling
    -------------------------------------------------------------------------- */
 
-static int
-acpi_bus_check_device(struct acpi_device *device, int *status_changed)
+static void acpi_bus_check_device(acpi_handle handle)
 {
-	acpi_status status = 0;
+	struct acpi_device *device;
+	acpi_status status;
 	struct acpi_device_status old_status;
 
-
+	if (acpi_bus_get_device(handle, &device))
+		return;
 	if (!device)
-		return -EINVAL;
-
-	if (status_changed)
-		*status_changed = 0;
+		return;
 
 	old_status = device->status;
 
@@ -471,22 +469,15 @@
 	 */
 	if (device->parent && !device->parent->status.present) {
 		device->status = device->parent->status;
-		if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) {
-			if (status_changed)
-				*status_changed = 1;
-		}
-		return 0;
+		return;
 	}
 
 	status = acpi_bus_get_status(device);
 	if (ACPI_FAILURE(status))
-		return -ENODEV;
+		return;
 
 	if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
-		return 0;
-
-	if (status_changed)
-		*status_changed = 1;
+		return;
 
 	/*
 	 * Device Insertion/Removal
@@ -498,33 +489,17 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
 		/* TBD: Handle device removal */
 	}
-
-	return 0;
 }
 
-static int acpi_bus_check_scope(struct acpi_device *device)
+static void acpi_bus_check_scope(acpi_handle handle)
 {
-	int result = 0;
-	int status_changed = 0;
-
-
-	if (!device)
-		return -EINVAL;
-
 	/* Status Change? */
-	result = acpi_bus_check_device(device, &status_changed);
-	if (result)
-		return result;
-
-	if (!status_changed)
-		return 0;
+	acpi_bus_check_device(handle);
 
 	/*
 	 * TBD: Enumerate child devices within this device's scope and
 	 *       run acpi_bus_check_device()'s on them.
 	 */
-
-	return 0;
 }
 
 static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
@@ -547,22 +522,19 @@
  */
 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 {
-	int result = 0;
 	struct acpi_device *device = NULL;
+	struct acpi_driver *driver;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
+			  type, handle));
 
 	blocking_notifier_call_chain(&acpi_bus_notify_list,
 		type, (void *)handle);
 
-	if (acpi_bus_get_device(handle, &device))
-		return;
-
 	switch (type) {
 
 	case ACPI_NOTIFY_BUS_CHECK:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received BUS CHECK notification for device [%s]\n",
-				  device->pnp.bus_id));
-		result = acpi_bus_check_scope(device);
+		acpi_bus_check_scope(handle);
 		/*
 		 * TBD: We'll need to outsource certain events to non-ACPI
 		 *      drivers via the device manager (device.c).
@@ -570,10 +542,7 @@
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received DEVICE CHECK notification for device [%s]\n",
-				  device->pnp.bus_id));
-		result = acpi_bus_check_device(device, NULL);
+		acpi_bus_check_device(handle);
 		/*
 		 * TBD: We'll need to outsource certain events to non-ACPI
 		 *      drivers via the device manager (device.c).
@@ -581,44 +550,26 @@
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received DEVICE WAKE notification for device [%s]\n",
-				  device->pnp.bus_id));
 		/* TBD */
 		break;
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received EJECT REQUEST notification for device [%s]\n",
-				  device->pnp.bus_id));
 		/* TBD */
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received DEVICE CHECK LIGHT notification for device [%s]\n",
-				  device->pnp.bus_id));
 		/* TBD: Exactly what does 'light' mean? */
 		break;
 
 	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received FREQUENCY MISMATCH notification for device [%s]\n",
-				  device->pnp.bus_id));
 		/* TBD */
 		break;
 
 	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received BUS MODE MISMATCH notification for device [%s]\n",
-				  device->pnp.bus_id));
 		/* TBD */
 		break;
 
 	case ACPI_NOTIFY_POWER_FAULT:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received POWER FAULT notification for device [%s]\n",
-				  device->pnp.bus_id));
 		/* TBD */
 		break;
 
@@ -629,7 +580,13 @@
 		break;
 	}
 
-	return;
+	acpi_bus_get_device(handle, &device);
+	if (device) {
+		driver = device->driver;
+		if (driver && driver->ops.notify &&
+		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
+			driver->ops.notify(device, type);
+	}
 }
 
 /* --------------------------------------------------------------------------
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/glue.c linux-libre-2.6.31-gnu/drivers/acpi/glue.c
--- linux-libre-2.6.30-gnu/drivers/acpi/glue.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/glue.c	2009-09-09 18:13:59.000000000 -0400
@@ -140,46 +140,6 @@
 
 EXPORT_SYMBOL(acpi_get_physical_device);
 
-/* ToDo: When a PCI bridge is found, return the PCI device behind the bridge
- *       This should work in general, but did not on a Lenovo T61 for the
- *	 graphics card. But this must be fixed when the PCI device is
- *       bound and the kernel device struct is attached to the acpi device
- * Note: A success call will increase reference count by one
- *       Do call put_device(dev) on the returned device then
- */
-struct device *acpi_get_physical_pci_device(acpi_handle handle)
-{
-	struct device *dev;
-	long long device_id;
-	acpi_status status;
-
-	status =
-		acpi_evaluate_integer(handle, "_ADR", NULL, &device_id);
-
-	if (ACPI_FAILURE(status))
-		return NULL;
-
-	/* We need to attempt to determine whether the _ADR refers to a
-	   PCI device or not. There's no terribly good way to do this,
-	   so the best we can hope for is to assume that there'll never
-	   be a device in the host bridge */
-	if (device_id >= 0x10000) {
-		/* It looks like a PCI device. Does it exist? */
-		dev = acpi_get_physical_device(handle);
-	} else {
-		/* It doesn't look like a PCI device. Does its parent
-		   exist? */
-		acpi_handle phandle;
-		if (acpi_get_parent(handle, &phandle))
-			return NULL;
-		dev = acpi_get_physical_device(phandle);
-	}
-	if (!dev)
-		return NULL;
-	return dev;
-}
-EXPORT_SYMBOL(acpi_get_physical_pci_device);
-
 static int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
 	struct acpi_device *acpi_dev;
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/Kconfig linux-libre-2.6.31-gnu/drivers/acpi/Kconfig
--- linux-libre-2.6.30-gnu/drivers/acpi/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -266,6 +266,7 @@
 
 config ACPI_PCI_SLOT
 	tristate "PCI slot detection driver"
+	depends on SYSFS
 	default n
 	help
 	  This driver creates entries in /sys/bus/pci/slots/ for all PCI
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/osl.c linux-libre-2.6.31-gnu/drivers/acpi/osl.c
--- linux-libre-2.6.30-gnu/drivers/acpi/osl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/osl.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,6 +79,7 @@
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
+static struct workqueue_struct *kacpi_hotplug_wq;
 
 struct acpi_res_list {
 	resource_size_t start;
@@ -188,12 +189,39 @@
 	return AE_OK;
 }
 
+static void bind_to_cpu0(struct work_struct *work)
+{
+	set_cpus_allowed(current, cpumask_of_cpu(0));
+	kfree(work);
+}
+
+static void bind_workqueue(struct workqueue_struct *wq)
+{
+	struct work_struct *work;
+
+	work = kzalloc(sizeof(struct work_struct), GFP_KERNEL);
+	INIT_WORK(work, bind_to_cpu0);
+	queue_work(wq, work);
+}
+
 acpi_status acpi_os_initialize1(void)
 {
+	/*
+	 * On some machines, a software-initiated SMI causes corruption unless
+	 * the SMI runs on CPU 0.  An SMI can be initiated by any AML, but
+	 * typically it's done in GPE-related methods that are run via
+	 * workqueues, so we can avoid the known corruption cases by binding
+	 * the workqueues to CPU 0.
+	 */
 	kacpid_wq = create_singlethread_workqueue("kacpid");
+	bind_workqueue(kacpid_wq);
 	kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
+	bind_workqueue(kacpi_notify_wq);
+	kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug");
+	bind_workqueue(kacpi_hotplug_wq);
 	BUG_ON(!kacpid_wq);
 	BUG_ON(!kacpi_notify_wq);
+	BUG_ON(!kacpi_hotplug_wq);
 	return AE_OK;
 }
 
@@ -206,6 +234,7 @@
 
 	destroy_workqueue(kacpid_wq);
 	destroy_workqueue(kacpi_notify_wq);
+	destroy_workqueue(kacpi_hotplug_wq);
 
 	return AE_OK;
 }
@@ -716,6 +745,7 @@
 	acpi_status status = AE_OK;
 	struct acpi_os_dpc *dpc;
 	struct workqueue_struct *queue;
+	work_func_t func;
 	int ret;
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 			  "Scheduling function [%p(%p)] for deferred execution.\n",
@@ -740,15 +770,17 @@
 	dpc->function = function;
 	dpc->context = context;
 
-	if (!hp) {
-		INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-		queue = (type == OSL_NOTIFY_HANDLER) ?
-			kacpi_notify_wq : kacpid_wq;
-		ret = queue_work(queue, &dpc->work);
-	} else {
-		INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred);
-		ret = schedule_work(&dpc->work);
-	}
+	/*
+	 * We can't run hotplug code in keventd_wq/kacpid_wq/kacpid_notify_wq
+	 * because the hotplug code may call driver .remove() functions,
+	 * which invoke flush_scheduled_work/acpi_os_wait_events_complete
+	 * to flush these workqueues.
+	 */
+	queue = hp ? kacpi_hotplug_wq :
+		(type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
+	func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred;
+	INIT_WORK(&dpc->work, func);
+	ret = queue_work(queue, &dpc->work);
 
 	if (!ret) {
 		printk(KERN_ERR PREFIX
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/pci_bind.c linux-libre-2.6.31-gnu/drivers/acpi/pci_bind.c
--- linux-libre-2.6.30-gnu/drivers/acpi/pci_bind.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/pci_bind.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,12 +24,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
@@ -38,310 +33,76 @@
 #define _COMPONENT		ACPI_PCI_COMPONENT
 ACPI_MODULE_NAME("pci_bind");
 
-struct acpi_pci_data {
-	struct acpi_pci_id id;
-	struct pci_bus *bus;
-	struct pci_dev *dev;
-};
-
-static int acpi_pci_unbind(struct acpi_device *device);
-
-static void acpi_pci_data_handler(acpi_handle handle, u32 function,
-				  void *context)
-{
-
-	/* TBD: Anything we need to do here? */
-
-	return;
-}
-
-/**
- * acpi_get_pci_id
- * ------------------
- * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)
- * to resolve PCI information for ACPI-PCI devices defined in the namespace.
- * This typically occurs when resolving PCI operation region information.
- */
-acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id)
+static int acpi_pci_unbind(struct acpi_device *device)
 {
-	int result = 0;
-	acpi_status status = AE_OK;
-	struct acpi_device *device = NULL;
-	struct acpi_pci_data *data = NULL;
-
-
-	if (!id)
-		return AE_BAD_PARAMETER;
-
-	result = acpi_bus_get_device(handle, &device);
-	if (result) {
-		printk(KERN_ERR PREFIX
-			    "Invalid ACPI Bus context for device %s\n",
-			    acpi_device_bid(device));
-		return AE_NOT_EXIST;
-	}
-
-	status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data);
-	if (ACPI_FAILURE(status) || !data) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"Invalid ACPI-PCI context for device %s",
-				acpi_device_bid(device)));
-		return status;
-	}
+	struct pci_dev *dev;
 
-	*id = data->id;
+	dev = acpi_get_pci_dev(device->handle);
+	if (!dev || !dev->subordinate)
+		goto out;
 
-	/*
-	   id->segment = data->id.segment;
-	   id->bus = data->id.bus;
-	   id->device = data->id.device;
-	   id->function = data->id.function;
-	 */
+	acpi_pci_irq_del_prt(dev->subordinate);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "Device %s has PCI address %04x:%02x:%02x.%d\n",
-			  acpi_device_bid(device), id->segment, id->bus,
-			  id->device, id->function));
+	device->ops.bind = NULL;
+	device->ops.unbind = NULL;
 
-	return AE_OK;
+out:
+	pci_dev_put(dev);
+	return 0;
 }
 
-EXPORT_SYMBOL(acpi_get_pci_id);
-
-int acpi_pci_bind(struct acpi_device *device)
+static int acpi_pci_bind(struct acpi_device *device)
 {
-	int result = 0;
 	acpi_status status;
-	struct acpi_pci_data *data;
-	struct acpi_pci_data *pdata;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	acpi_handle handle;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
 
-	if (!device || !device->parent)
-		return -EINVAL;
-
-	data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
-	if (ACPI_FAILURE(status)) {
-		kfree(data);
-		return -ENODEV;
-	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
-			  (char *)buffer.pointer));
-
-	/* 
-	 * Segment & Bus
-	 * -------------
-	 * These are obtained via the parent device's ACPI-PCI context.
-	 */
-	status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
-			       (void **)&pdata);
-	if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"Invalid ACPI-PCI context for parent device %s",
-				acpi_device_bid(device->parent)));
-		result = -ENODEV;
-		goto end;
-	}
-	data->id.segment = pdata->id.segment;
-	data->id.bus = pdata->bus->number;
-
-	/*
-	 * Device & Function
-	 * -----------------
-	 * These are simply obtained from the device's _ADR method.  Note
-	 * that a value of zero is valid.
-	 */
-	data->id.device = device->pnp.bus_address >> 16;
-	data->id.function = device->pnp.bus_address & 0xFFFF;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n",
-			  data->id.segment, data->id.bus, data->id.device,
-			  data->id.function));
-
-	/*
-	 * TBD: Support slot devices (e.g. function=0xFFFF).
-	 */
-
-	/* 
-	 * Locate PCI Device
-	 * -----------------
-	 * Locate matching device in PCI namespace.  If it doesn't exist
-	 * this typically means that the device isn't currently inserted
-	 * (e.g. docking station, port replicator, etc.).
-	 */
-	data->dev = pci_get_slot(pdata->bus,
-				PCI_DEVFN(data->id.device, data->id.function));
-	if (!data->dev) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Device %04x:%02x:%02x.%d not present in PCI namespace\n",
-				  data->id.segment, data->id.bus,
-				  data->id.device, data->id.function));
-		result = -ENODEV;
-		goto end;
-	}
-	if (!data->dev->bus) {
-		printk(KERN_ERR PREFIX
-			    "Device %04x:%02x:%02x.%d has invalid 'bus' field\n",
-			    data->id.segment, data->id.bus,
-			    data->id.device, data->id.function);
-		result = -ENODEV;
-		goto end;
-	}
+	dev = acpi_get_pci_dev(device->handle);
+	if (!dev)
+		return 0;
 
 	/*
-	 * PCI Bridge?
-	 * -----------
-	 * If so, set the 'bus' field and install the 'bind' function to 
-	 * facilitate callbacks for all of its children.
+	 * Install the 'bind' function to facilitate callbacks for
+	 * children of the P2P bridge.
 	 */
-	if (data->dev->subordinate) {
+	if (dev->subordinate) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Device %04x:%02x:%02x.%d is a PCI bridge\n",
-				  data->id.segment, data->id.bus,
-				  data->id.device, data->id.function));
-		data->bus = data->dev->subordinate;
+				  pci_domain_nr(dev->bus), dev->bus->number,
+				  PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)));
 		device->ops.bind = acpi_pci_bind;
 		device->ops.unbind = acpi_pci_unbind;
 	}
 
 	/*
-	 * Attach ACPI-PCI Context
-	 * -----------------------
-	 * Thus binding the ACPI and PCI devices.
-	 */
-	status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"Unable to attach ACPI-PCI context to device %s",
-				acpi_device_bid(device)));
-		result = -ENODEV;
-		goto end;
-	}
-
-	/*
-	 * PCI Routing Table
-	 * -----------------
-	 * Evaluate and parse _PRT, if exists.  This code is independent of 
-	 * PCI bridges (above) to allow parsing of _PRT objects within the
-	 * scope of non-bridge devices.  Note that _PRTs within the scope of
-	 * a PCI bridge assume the bridge's subordinate bus number.
+	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
+	 * _PRT objects within the scope of non-bridge devices.  Note that
+	 * _PRTs within the scope of a PCI bridge assume the bridge's
+	 * subordinate bus number.
 	 *
 	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
 	 */
 	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_SUCCESS(status)) {
-		if (data->bus)	/* PCI-PCI bridge */
-			acpi_pci_irq_add_prt(device->handle, data->id.segment,
-					     data->bus->number);
-		else		/* non-bridge PCI device */
-			acpi_pci_irq_add_prt(device->handle, data->id.segment,
-					     data->id.bus);
-	}
-
-      end:
-	kfree(buffer.pointer);
-	if (result) {
-		pci_dev_put(data->dev);
-		kfree(data);
-	}
-	return result;
-}
-
-static int acpi_pci_unbind(struct acpi_device *device)
-{
-	int result = 0;
-	acpi_status status;
-	struct acpi_pci_data *data;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
-
-	if (!device || !device->parent)
-		return -EINVAL;
-
-	status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
 	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
-			  (char *) buffer.pointer));
-	kfree(buffer.pointer);
+		goto out;
 
-	status =
-	    acpi_get_data(device->handle, acpi_pci_data_handler,
-			  (void **)&data);
-	if (ACPI_FAILURE(status)) {
-		result = -ENODEV;
-		goto end;
-	}
+	if (dev->subordinate)
+		bus = dev->subordinate;
+	else
+		bus = dev->bus;
 
-	status = acpi_detach_data(device->handle, acpi_pci_data_handler);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"Unable to detach data from device %s",
-				acpi_device_bid(device)));
-		result = -ENODEV;
-		goto end;
-	}
-	if (data->dev->subordinate) {
-		acpi_pci_irq_del_prt(data->id.segment, data->bus->number);
-	}
-	pci_dev_put(data->dev);
-	kfree(data);
+	acpi_pci_irq_add_prt(device->handle, bus);
 
-      end:
-	return result;
+out:
+	pci_dev_put(dev);
+	return 0;
 }
 
-int
-acpi_pci_bind_root(struct acpi_device *device,
-		   struct acpi_pci_id *id, struct pci_bus *bus)
+int acpi_pci_bind_root(struct acpi_device *device)
 {
-	int result = 0;
-	acpi_status status;
-	struct acpi_pci_data *data = NULL;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
-	if (!device || !id || !bus) {
-		return -EINVAL;
-	}
-
-	data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->id = *id;
-	data->bus = bus;
 	device->ops.bind = acpi_pci_bind;
 	device->ops.unbind = acpi_pci_unbind;
 
-	status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
-	if (ACPI_FAILURE(status)) {
-		kfree (data);
-		return -ENODEV;
-	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
-			"%04x:%02x\n", (char *)buffer.pointer,
-			id->segment, id->bus));
-
-	status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"Unable to attach ACPI-PCI context to device %s",
-				(char *)buffer.pointer));
-		result = -ENODEV;
-		goto end;
-	}
-
-      end:
-	kfree(buffer.pointer);
-	if (result != 0)
-		kfree(data);
-
-	return result;
+	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/pci_irq.c linux-libre-2.6.31-gnu/drivers/acpi/pci_irq.c
--- linux-libre-2.6.30-gnu/drivers/acpi/pci_irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/pci_irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -182,7 +182,7 @@
 	}
 }
 
-static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
+static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus,
 				  struct acpi_pci_routing_table *prt)
 {
 	struct acpi_prt_entry *entry;
@@ -196,8 +196,8 @@
 	 * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert
 	 * it here.
 	 */
-	entry->id.segment = segment;
-	entry->id.bus = bus;
+	entry->id.segment = pci_domain_nr(bus);
+	entry->id.bus = bus->number;
 	entry->id.device = (prt->address >> 16) & 0xFFFF;
 	entry->pin = prt->pin + 1;
 
@@ -242,7 +242,7 @@
 	return 0;
 }
 
-int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
+int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -271,7 +271,7 @@
 
 	entry = buffer.pointer;
 	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
+		acpi_pci_irq_add_entry(handle, bus, entry);
 		entry = (struct acpi_pci_routing_table *)
 		    ((unsigned long)entry + entry->length);
 	}
@@ -280,16 +280,17 @@
 	return 0;
 }
 
-void acpi_pci_irq_del_prt(int segment, int bus)
+void acpi_pci_irq_del_prt(struct pci_bus *bus)
 {
 	struct acpi_prt_entry *entry, *tmp;
 
 	printk(KERN_DEBUG
 	       "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
-	       segment, bus);
+	       pci_domain_nr(bus), bus->number);
 	spin_lock(&acpi_prt_lock);
 	list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
-		if (segment == entry->id.segment && bus == entry->id.bus) {
+		if (pci_domain_nr(bus) == entry->id.segment
+			&& bus->number == entry->id.bus) {
 			list_del(&entry->list);
 			kfree(entry);
 		}
@@ -401,7 +402,8 @@
 		/* Interrupt Line values above 0xF are forbidden */
 		if (dev->irq > 0 && (dev->irq <= 0xF)) {
 			printk(" - using IRQ %d\n", dev->irq);
-			acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
+			acpi_register_gsi(&dev->dev, dev->irq,
+					  ACPI_LEVEL_SENSITIVE,
 					  ACPI_ACTIVE_LOW);
 			return 0;
 		} else {
@@ -410,7 +412,7 @@
 		}
 	}
 
-	rc = acpi_register_gsi(gsi, triggering, polarity);
+	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/pci_root.c linux-libre-2.6.31-gnu/drivers/acpi/pci_root.c
--- linux-libre-2.6.30-gnu/drivers/acpi/pci_root.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/pci_root.c	2009-09-09 18:13:59.000000000 -0400
@@ -63,9 +63,10 @@
 
 struct acpi_pci_root {
 	struct list_head node;
-	struct acpi_device * device;
-	struct acpi_pci_id id;
+	struct acpi_device *device;
 	struct pci_bus *bus;
+	u16 segment;
+	u8 bus_nr;
 
 	u32 osc_support_set;	/* _OSC state of support bits */
 	u32 osc_control_set;	/* _OSC state of control bits */
@@ -82,7 +83,7 @@
 int acpi_pci_register_driver(struct acpi_pci_driver *driver)
 {
 	int n = 0;
-	struct list_head *entry;
+	struct acpi_pci_root *root;
 
 	struct acpi_pci_driver **pptr = &sub_driver;
 	while (*pptr)
@@ -92,9 +93,7 @@
 	if (!driver->add)
 		return 0;
 
-	list_for_each(entry, &acpi_pci_roots) {
-		struct acpi_pci_root *root;
-		root = list_entry(entry, struct acpi_pci_root, node);
+	list_for_each_entry(root, &acpi_pci_roots, node) {
 		driver->add(root->device->handle);
 		n++;
 	}
@@ -106,7 +105,7 @@
 
 void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 {
-	struct list_head *entry;
+	struct acpi_pci_root *root;
 
 	struct acpi_pci_driver **pptr = &sub_driver;
 	while (*pptr) {
@@ -120,28 +119,48 @@
 	if (!driver->remove)
 		return;
 
-	list_for_each(entry, &acpi_pci_roots) {
-		struct acpi_pci_root *root;
-		root = list_entry(entry, struct acpi_pci_root, node);
+	list_for_each_entry(root, &acpi_pci_roots, node)
 		driver->remove(root->device->handle);
-	}
 }
 
 EXPORT_SYMBOL(acpi_pci_unregister_driver);
 
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
 {
-	struct acpi_pci_root *tmp;
+	struct acpi_pci_root *root;
 	
-	list_for_each_entry(tmp, &acpi_pci_roots, node) {
-		if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus))
-			return tmp->device->handle;
-	}
+	list_for_each_entry(root, &acpi_pci_roots, node)
+		if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus))
+			return root->device->handle;
 	return NULL;		
 }
 
 EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
 
+/**
+ * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
+ * @handle - the ACPI CA node in question.
+ *
+ * Note: we could make this API take a struct acpi_device * instead, but
+ * for now, it's more convenient to operate on an acpi_handle.
+ */
+int acpi_is_root_bridge(acpi_handle handle)
+{
+	int ret;
+	struct acpi_device *device;
+
+	ret = acpi_bus_get_device(handle, &device);
+	if (ret)
+		return 0;
+
+	ret = acpi_match_device_ids(device, root_device_ids);
+	if (ret)
+		return 0;
+	else
+		return 1;
+}
+EXPORT_SYMBOL_GPL(acpi_is_root_bridge);
+
 static acpi_status
 get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
 {
@@ -161,19 +180,22 @@
 	return AE_OK;
 }
 
-static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
+static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
+					     unsigned long long *bus)
 {
 	acpi_status status;
+	int busnum;
 
-	*busnum = -1;
+	busnum = -1;
 	status =
 	    acpi_walk_resources(handle, METHOD_NAME__CRS,
-				get_root_bridge_busnr_callback, busnum);
+				get_root_bridge_busnr_callback, &busnum);
 	if (ACPI_FAILURE(status))
 		return status;
 	/* Check if we really get a bus number from _CRS */
-	if (*busnum == -1)
+	if (busnum == -1)
 		return AE_ERROR;
+	*bus = busnum;
 	return AE_OK;
 }
 
@@ -298,6 +320,7 @@
 static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
 {
 	struct acpi_pci_root *root;
+
 	list_for_each_entry(root, &acpi_pci_roots, node) {
 		if (root->device->handle == handle)
 			return root;
@@ -305,6 +328,87 @@
 	return NULL;
 }
 
+struct acpi_handle_node {
+	struct list_head node;
+	acpi_handle handle;
+};
+
+/**
+ * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev
+ * @handle: the handle in question
+ *
+ * Given an ACPI CA handle, the desired PCI device is located in the
+ * list of PCI devices.
+ *
+ * If the device is found, its reference count is increased and this
+ * function returns a pointer to its data structure.  The caller must
+ * decrement the reference count by calling pci_dev_put().
+ * If no device is found, %NULL is returned.
+ */
+struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
+{
+	int dev, fn;
+	unsigned long long adr;
+	acpi_status status;
+	acpi_handle phandle;
+	struct pci_bus *pbus;
+	struct pci_dev *pdev = NULL;
+	struct acpi_handle_node *node, *tmp;
+	struct acpi_pci_root *root;
+	LIST_HEAD(device_list);
+
+	/*
+	 * Walk up the ACPI CA namespace until we reach a PCI root bridge.
+	 */
+	phandle = handle;
+	while (!acpi_is_root_bridge(phandle)) {
+		node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
+		if (!node)
+			goto out;
+
+		INIT_LIST_HEAD(&node->node);
+		node->handle = phandle;
+		list_add(&node->node, &device_list);
+
+		status = acpi_get_parent(phandle, &phandle);
+		if (ACPI_FAILURE(status))
+			goto out;
+	}
+
+	root = acpi_pci_find_root(phandle);
+	if (!root)
+		goto out;
+
+	pbus = root->bus;
+
+	/*
+	 * Now, walk back down the PCI device tree until we return to our
+	 * original handle. Assumes that everything between the PCI root
+	 * bridge and the device we're looking for must be a P2P bridge.
+	 */
+	list_for_each_entry(node, &device_list, node) {
+		acpi_handle hnd = node->handle;
+		status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
+		if (ACPI_FAILURE(status))
+			goto out;
+		dev = (adr >> 16) & 0xffff;
+		fn  = adr & 0xffff;
+
+		pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
+		if (!pdev || hnd == handle)
+			break;
+
+		pbus = pdev->subordinate;
+		pci_dev_put(pdev);
+	}
+out:
+	list_for_each_entry_safe(node, tmp, &device_list, node)
+		kfree(node);
+
+	return pdev;
+}
+EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
+
 /**
  * acpi_pci_osc_control_set - commit requested control to Firmware
  * @handle: acpi_handle for the target ACPI object
@@ -363,31 +467,46 @@
 
 static int __devinit acpi_pci_root_add(struct acpi_device *device)
 {
-	int result = 0;
-	struct acpi_pci_root *root = NULL;
-	struct acpi_pci_root *tmp;
-	acpi_status status = AE_OK;
-	unsigned long long value = 0;
-	acpi_handle handle = NULL;
+	unsigned long long segment, bus;
+	acpi_status status;
+	int result;
+	struct acpi_pci_root *root;
+	acpi_handle handle;
 	struct acpi_device *child;
 	u32 flags, base_flags;
 
+	segment = 0;
+	status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
+				       &segment);
+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+		printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
+		return -ENODEV;
+	}
 
-	if (!device)
-		return -EINVAL;
+	/* Check _CRS first, then _BBN.  If no _BBN, default to zero. */
+	bus = 0;
+	status = try_get_root_bridge_busnr(device->handle, &bus);
+	if (ACPI_FAILURE(status)) {
+		status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,					       NULL, &bus);
+		if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+			printk(KERN_ERR PREFIX
+			     "no bus number in _CRS and can't evaluate _BBN\n");
+			return -ENODEV;
+		}
+	}
 
 	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
 	if (!root)
 		return -ENOMEM;
-	INIT_LIST_HEAD(&root->node);
 
+	INIT_LIST_HEAD(&root->node);
 	root->device = device;
+	root->segment = segment & 0xFFFF;
+	root->bus_nr = bus & 0xFF;
 	strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
 	device->driver_data = root;
 
-	device->ops.bind = acpi_pci_bind;
-
 	/*
 	 * All supported architectures that use ACPI have support for
 	 * PCI domains, so we indicate this in _OSC support capabilities.
@@ -395,79 +514,6 @@
 	flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
 	acpi_pci_osc_support(root, flags);
 
-	/* 
-	 * Segment
-	 * -------
-	 * Obtained via _SEG, if exists, otherwise assumed to be zero (0).
-	 */
-	status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
-				       &value);
-	switch (status) {
-	case AE_OK:
-		root->id.segment = (u16) value;
-		break;
-	case AE_NOT_FOUND:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Assuming segment 0 (no _SEG)\n"));
-		root->id.segment = 0;
-		break;
-	default:
-		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG"));
-		result = -ENODEV;
-		goto end;
-	}
-
-	/* 
-	 * Bus
-	 * ---
-	 * Obtained via _BBN, if exists, otherwise assumed to be zero (0).
-	 */
-	status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL,
-				       &value);
-	switch (status) {
-	case AE_OK:
-		root->id.bus = (u16) value;
-		break;
-	case AE_NOT_FOUND:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n"));
-		root->id.bus = 0;
-		break;
-	default:
-		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN"));
-		result = -ENODEV;
-		goto end;
-	}
-
-	/* Some systems have wrong _BBN */
-	list_for_each_entry(tmp, &acpi_pci_roots, node) {
-		if ((tmp->id.segment == root->id.segment)
-		    && (tmp->id.bus == root->id.bus)) {
-			int bus = 0;
-			acpi_status status;
-
-			printk(KERN_ERR PREFIX
-				    "Wrong _BBN value, reboot"
-				    " and use option 'pci=noacpi'\n");
-
-			status = try_get_root_bridge_busnr(device->handle, &bus);
-			if (ACPI_FAILURE(status))
-				break;
-			if (bus != root->id.bus) {
-				printk(KERN_INFO PREFIX
-				       "PCI _CRS %d overrides _BBN 0\n", bus);
-				root->id.bus = bus;
-			}
-			break;
-		}
-	}
-	/*
-	 * Device & Function
-	 * -----------------
-	 * Obtained from _ADR (which has already been evaluated for us).
-	 */
-	root->id.device = device->pnp.bus_address >> 16;
-	root->id.function = device->pnp.bus_address & 0xFFFF;
-
 	/*
 	 * TBD: Need PCI interface for enumeration/configuration of roots.
 	 */
@@ -477,7 +523,7 @@
 
 	printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
-	       root->id.segment, root->id.bus);
+	       root->segment, root->bus_nr);
 
 	/*
 	 * Scan the Root Bridge
@@ -486,11 +532,11 @@
 	 * PCI namespace does not get created until this call is made (and 
 	 * thus the root bridge's pci_dev does not exist).
 	 */
-	root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
+	root->bus = pci_acpi_scan_root(device, segment, bus);
 	if (!root->bus) {
 		printk(KERN_ERR PREFIX
 			    "Bus %04x:%02x not present in PCI namespace\n",
-			    root->id.segment, root->id.bus);
+			    root->segment, root->bus_nr);
 		result = -ENODEV;
 		goto end;
 	}
@@ -500,7 +546,7 @@
 	 * -----------------------
 	 * Thus binding the ACPI and PCI devices.
 	 */
-	result = acpi_pci_bind_root(device, &root->id, root->bus);
+	result = acpi_pci_bind_root(device);
 	if (result)
 		goto end;
 
@@ -511,8 +557,7 @@
 	 */
 	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
 	if (ACPI_SUCCESS(status))
-		result = acpi_pci_irq_add_prt(device->handle, root->id.segment,
-					      root->id.bus);
+		result = acpi_pci_irq_add_prt(device->handle, root->bus);
 
 	/*
 	 * Scan and bind all _ADR-Based Devices
@@ -531,42 +576,28 @@
 	if (flags != base_flags)
 		acpi_pci_osc_support(root, flags);
 
-      end:
-	if (result) {
-		if (!list_empty(&root->node))
-			list_del(&root->node);
-		kfree(root);
-	}
+	return 0;
 
+end:
+	if (!list_empty(&root->node))
+		list_del(&root->node);
+	kfree(root);
 	return result;
 }
 
 static int acpi_pci_root_start(struct acpi_device *device)
 {
-	struct acpi_pci_root *root;
-
+	struct acpi_pci_root *root = acpi_driver_data(device);
 
-	list_for_each_entry(root, &acpi_pci_roots, node) {
-		if (root->device == device) {
-			pci_bus_add_devices(root->bus);
-			return 0;
-		}
-	}
-	return -ENODEV;
+	pci_bus_add_devices(root->bus);
+	return 0;
 }
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
-	struct acpi_pci_root *root = NULL;
-
-
-	if (!device || !acpi_driver_data(device))
-		return -EINVAL;
-
-	root = acpi_driver_data(device);
+	struct acpi_pci_root *root = acpi_driver_data(device);
 
 	kfree(root);
-
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/power.c linux-libre-2.6.31-gnu/drivers/acpi/power.c
--- linux-libre-2.6.30-gnu/drivers/acpi/power.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/power.c	2009-09-09 18:13:59.000000000 -0400
@@ -194,7 +194,7 @@
 
 static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
 {
-	int result = 0, state;
+	int result = 0;
 	int found = 0;
 	acpi_status status = AE_OK;
 	struct acpi_power_resource *resource = NULL;
@@ -236,18 +236,6 @@
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	if (!acpi_power_nocheck) {
-		/*
-		 * If acpi_power_nocheck is set, it is unnecessary to check
-		 * the power state after power transition.
-		 */
-		result = acpi_power_get_state(resource->device->handle,
-				&state);
-		if (result)
-			return result;
-		if (state != ACPI_POWER_RESOURCE_STATE_ON)
-			return -ENOEXEC;
-	}
 	/* Update the power resource's _device_ power state */
 	resource->device->power.state = ACPI_STATE_D0;
 
@@ -258,7 +246,7 @@
 
 static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
 {
-	int result = 0, state;
+	int result = 0;
 	acpi_status status = AE_OK;
 	struct acpi_power_resource *resource = NULL;
 	struct list_head *node, *next;
@@ -293,18 +281,6 @@
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	if (!acpi_power_nocheck) {
-		/*
-		 * If acpi_power_nocheck is set, it is unnecessary to check
-		 * the power state after power transition.
-		 */
-		result = acpi_power_get_state(handle, &state);
-		if (result)
-			return result;
-		if (state != ACPI_POWER_RESOURCE_STATE_OFF)
-			return -ENOEXEC;
-	}
-
 	/* Update the power resource's _device_ power state */
 	resource->device->power.state = ACPI_STATE_D3;
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/processor_core.c linux-libre-2.6.31-gnu/drivers/acpi/processor_core.c
--- linux-libre-2.6.30-gnu/drivers/acpi/processor_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/processor_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,7 +89,7 @@
 
 static const struct acpi_device_id processor_device_ids[] = {
 	{ACPI_PROCESSOR_OBJECT_HID, 0},
-	{ACPI_PROCESSOR_HID, 0},
+	{"ACPI0007", 0},
 	{"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, processor_device_ids);
@@ -596,7 +596,21 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "No bus mastering arbitration control\n"));
 
-	if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) {
+	if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) {
+		/* Declared with "Processor" statement; match ProcessorID */
+		status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_ERR PREFIX "Evaluating processor object\n");
+			return -ENODEV;
+		}
+
+		/*
+		 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
+		 *      >>> 'acpi_get_processor_id(acpi_id, &id)' in
+		 *      arch/xxx/acpi.c
+		 */
+		pr->acpi_id = object.processor.proc_id;
+	} else {
 		/*
 		 * Declared with "Device" statement; match _UID.
 		 * Note that we don't handle string _UIDs yet.
@@ -611,20 +625,6 @@
 		}
 		device_declaration = 1;
 		pr->acpi_id = value;
-	} else {
-		/* Declared with "Processor" statement; match ProcessorID */
-		status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
-		if (ACPI_FAILURE(status)) {
-			printk(KERN_ERR PREFIX "Evaluating processor object\n");
-			return -ENODEV;
-		}
-
-		/*
-		 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
-		 *      >>> 'acpi_get_processor_id(acpi_id, &id)' in
-		 *      arch/xxx/acpi.c
-		 */
-		pr->acpi_id = object.processor.proc_id;
 	}
 	cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id);
 
@@ -649,7 +649,16 @@
 			return -ENODEV;
 		}
 	}
-
+	/*
+	 * On some boxes several processors use the same processor bus id.
+	 * But they are located in different scope. For example:
+	 * \_SB.SCK0.CPU0
+	 * \_SB.SCK1.CPU0
+	 * Rename the processor device bus id. And the new bus id will be
+	 * generated as the following format:
+	 * CPU+CPU ID.
+	 */
+	sprintf(acpi_device_bid(device), "CPU%X", pr->id);
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
 			  pr->acpi_id));
 
@@ -731,6 +740,8 @@
 	/* _PDC call should be done before doing anything else (if reqd.). */
 	arch_acpi_processor_init_pdc(pr);
 	acpi_processor_set_pdc(pr);
+	arch_acpi_processor_cleanup_pdc(pr);
+
 #ifdef CONFIG_CPU_FREQ
 	acpi_processor_ppc_has_changed(pr);
 #endif
@@ -1140,6 +1151,9 @@
 {
 	int result = 0;
 
+	if (acpi_disabled)
+		return 0;
+
 	memset(&errata, 0, sizeof(errata));
 
 #ifdef CONFIG_SMP
@@ -1186,6 +1200,9 @@
 
 static void __exit acpi_processor_exit(void)
 {
+	if (acpi_disabled)
+		return;
+
 	acpi_processor_ppc_exit();
 
 	acpi_thermal_cpufreq_exit();
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/processor_idle.c linux-libre-2.6.31-gnu/drivers/acpi/processor_idle.c
--- linux-libre-2.6.30-gnu/drivers/acpi/processor_idle.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/processor_idle.c	2009-09-09 18:13:59.000000000 -0400
@@ -139,7 +139,7 @@
  * are affected too. We pick the most conservative approach: we assume
  * that the local APIC stops in both C2 and C3.
  */
-static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+static void lapic_timer_check_state(int state, struct acpi_processor *pr,
 				   struct acpi_processor_cx *cx)
 {
 	struct acpi_processor_power *pwr = &pr->power;
@@ -162,8 +162,9 @@
 		pr->power.timer_broadcast_on_state = state;
 }
 
-static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
+static void lapic_timer_propagate_broadcast(void *arg)
 {
+	struct acpi_processor *pr = (struct acpi_processor *) arg;
 	unsigned long reason;
 
 	reason = pr->power.timer_broadcast_on_state < INT_MAX ?
@@ -173,7 +174,7 @@
 }
 
 /* Power(C) State timer broadcast control */
-static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 				       struct acpi_processor_cx *cx,
 				       int broadcast)
 {
@@ -190,10 +191,10 @@
 
 #else
 
-static void acpi_timer_check_state(int state, struct acpi_processor *pr,
+static void lapic_timer_check_state(int state, struct acpi_processor *pr,
 				   struct acpi_processor_cx *cstate) { }
-static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { }
-static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { }
+static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 				       struct acpi_processor_cx *cx,
 				       int broadcast)
 {
@@ -515,7 +516,8 @@
 static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
 					   struct acpi_processor_cx *cx)
 {
-	static int bm_check_flag;
+	static int bm_check_flag = -1;
+	static int bm_control_flag = -1;
 
 
 	if (!cx->address)
@@ -545,12 +547,14 @@
 	}
 
 	/* All the logic here assumes flags.bm_check is same across all CPUs */
-	if (!bm_check_flag) {
+	if (bm_check_flag == -1) {
 		/* Determine whether bm_check is needed based on CPU  */
 		acpi_processor_power_init_bm_check(&(pr->flags), pr->id);
 		bm_check_flag = pr->flags.bm_check;
+		bm_control_flag = pr->flags.bm_control;
 	} else {
 		pr->flags.bm_check = bm_check_flag;
+		pr->flags.bm_control = bm_control_flag;
 	}
 
 	if (pr->flags.bm_check) {
@@ -614,29 +618,26 @@
 		switch (cx->type) {
 		case ACPI_STATE_C1:
 			cx->valid = 1;
-			acpi_timer_check_state(i, pr, cx);
 			break;
 
 		case ACPI_STATE_C2:
 			acpi_processor_power_verify_c2(cx);
-			if (cx->valid)
-				acpi_timer_check_state(i, pr, cx);
 			break;
 
 		case ACPI_STATE_C3:
 			acpi_processor_power_verify_c3(pr, cx);
-			if (cx->valid)
-				acpi_timer_check_state(i, pr, cx);
 			break;
 		}
-		if (cx->valid)
-			tsc_check_state(cx->type);
+		if (!cx->valid)
+			continue;
 
-		if (cx->valid)
-			working++;
+		lapic_timer_check_state(i, pr, cx);
+		tsc_check_state(cx->type);
+		working++;
 	}
 
-	acpi_propagate_timer_broadcast(pr);
+	smp_call_function_single(pr->id, lapic_timer_propagate_broadcast,
+				 pr, 1);
 
 	return (working);
 }
@@ -839,7 +840,7 @@
 		return 0;
 	}
 
-	acpi_state_timer_broadcast(pr, cx, 1);
+	lapic_timer_state_broadcast(pr, cx, 1);
 	kt1 = ktime_get_real();
 	acpi_idle_do_entry(cx);
 	kt2 = ktime_get_real();
@@ -847,7 +848,7 @@
 
 	local_irq_enable();
 	cx->usage++;
-	acpi_state_timer_broadcast(pr, cx, 0);
+	lapic_timer_state_broadcast(pr, cx, 0);
 
 	return idle_time;
 }
@@ -892,7 +893,7 @@
 	 * Must be done before busmaster disable as we might need to
 	 * access HPET !
 	 */
-	acpi_state_timer_broadcast(pr, cx, 1);
+	lapic_timer_state_broadcast(pr, cx, 1);
 
 	if (cx->type == ACPI_STATE_C3)
 		ACPI_FLUSH_CPU_CACHE();
@@ -914,7 +915,7 @@
 
 	cx->usage++;
 
-	acpi_state_timer_broadcast(pr, cx, 0);
+	lapic_timer_state_broadcast(pr, cx, 0);
 	cx->time += sleep_ticks;
 	return idle_time;
 }
@@ -981,7 +982,7 @@
 	 * Must be done before busmaster disable as we might need to
 	 * access HPET !
 	 */
-	acpi_state_timer_broadcast(pr, cx, 1);
+	lapic_timer_state_broadcast(pr, cx, 1);
 
 	kt1 = ktime_get_real();
 	/*
@@ -1026,7 +1027,7 @@
 
 	cx->usage++;
 
-	acpi_state_timer_broadcast(pr, cx, 0);
+	lapic_timer_state_broadcast(pr, cx, 0);
 	cx->time += sleep_ticks;
 	return idle_time;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/processor_thermal.c linux-libre-2.6.31-gnu/drivers/acpi/processor_thermal.c
--- linux-libre-2.6.30-gnu/drivers/acpi/processor_thermal.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/processor_thermal.c	2009-09-09 18:13:59.000000000 -0400
@@ -66,7 +66,7 @@
 		if (pr->limit.thermal.tx > tx)
 			tx = pr->limit.thermal.tx;
 
-		result = acpi_processor_set_throttling(pr, tx);
+		result = acpi_processor_set_throttling(pr, tx, false);
 		if (result)
 			goto end;
 	}
@@ -421,12 +421,12 @@
 
 	if (state <= max_pstate) {
 		if (pr->flags.throttling && pr->throttling.state)
-			result = acpi_processor_set_throttling(pr, 0);
+			result = acpi_processor_set_throttling(pr, 0, false);
 		cpufreq_set_cur_state(pr->id, state);
 	} else {
 		cpufreq_set_cur_state(pr->id, max_pstate);
 		result = acpi_processor_set_throttling(pr,
-				state - max_pstate);
+				state - max_pstate, false);
 	}
 	return result;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/processor_throttling.c linux-libre-2.6.31-gnu/drivers/acpi/processor_throttling.c
--- linux-libre-2.6.30-gnu/drivers/acpi/processor_throttling.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/processor_throttling.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,7 +62,8 @@
 #define THROTTLING_POSTCHANGE      (2)
 
 static int acpi_processor_get_throttling(struct acpi_processor *pr);
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+						int state, bool force);
 
 static int acpi_processor_update_tsd_coord(void)
 {
@@ -361,7 +362,7 @@
 		 */
 		target_state = throttling_limit;
 	}
-	return acpi_processor_set_throttling(pr, target_state);
+	return acpi_processor_set_throttling(pr, target_state, false);
 }
 
 /*
@@ -839,10 +840,10 @@
 	if (ret >= 0) {
 		state = acpi_get_throttling_state(pr, value);
 		if (state == -1) {
-			ACPI_WARNING((AE_INFO,
-				"Invalid throttling state, reset"));
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"Invalid throttling state, reset\n"));
 			state = 0;
-			ret = acpi_processor_set_throttling(pr, state);
+			ret = acpi_processor_set_throttling(pr, state, true);
 			if (ret)
 				return ret;
 		}
@@ -915,7 +916,7 @@
 }
 
 static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
-					      int state)
+					      int state, bool force)
 {
 	u32 value = 0;
 	u32 duty_mask = 0;
@@ -930,7 +931,7 @@
 	if (!pr->flags.throttling)
 		return -ENODEV;
 
-	if (state == pr->throttling.state)
+	if (!force && (state == pr->throttling.state))
 		return 0;
 
 	if (state < pr->throttling_platform_limit)
@@ -988,7 +989,7 @@
 }
 
 static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
-					     int state)
+					     int state, bool force)
 {
 	int ret;
 	acpi_integer value;
@@ -1002,7 +1003,7 @@
 	if (!pr->flags.throttling)
 		return -ENODEV;
 
-	if (state == pr->throttling.state)
+	if (!force && (state == pr->throttling.state))
 		return 0;
 
 	if (state < pr->throttling_platform_limit)
@@ -1018,7 +1019,8 @@
 	return 0;
 }
 
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+						int state, bool force)
 {
 	cpumask_var_t saved_mask;
 	int ret = 0;
@@ -1070,7 +1072,7 @@
 		/* FIXME: use work_on_cpu() */
 		set_cpus_allowed_ptr(current, cpumask_of(pr->id));
 		ret = p_throttling->acpi_processor_set_throttling(pr,
-						t_state.target_state);
+						t_state.target_state, force);
 	} else {
 		/*
 		 * When the T-state coordination is SW_ALL or HW_ALL,
@@ -1103,7 +1105,7 @@
 			set_cpus_allowed_ptr(current, cpumask_of(i));
 			ret = match_pr->throttling.
 				acpi_processor_set_throttling(
-				match_pr, t_state.target_state);
+				match_pr, t_state.target_state, force);
 		}
 	}
 	/*
@@ -1201,7 +1203,7 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Disabling throttling (was T%d)\n",
 				  pr->throttling.state));
-		result = acpi_processor_set_throttling(pr, 0);
+		result = acpi_processor_set_throttling(pr, 0, false);
 		if (result)
 			goto end;
 	}
@@ -1307,7 +1309,7 @@
 	if (strcmp(tmpbuf, charp) != 0)
 		return -EINVAL;
 
-	result = acpi_processor_set_throttling(pr, state_val);
+	result = acpi_processor_set_throttling(pr, state_val, false);
 	if (result)
 		return result;
 
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/scan.c linux-libre-2.6.31-gnu/drivers/acpi/scan.c
--- linux-libre-2.6.30-gnu/drivers/acpi/scan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/scan.c	2009-09-09 18:13:59.000000000 -0400
@@ -95,7 +95,7 @@
 }
 static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
 
-static int acpi_bus_hot_remove_device(void *context)
+static void acpi_bus_hot_remove_device(void *context)
 {
 	struct acpi_device *device;
 	acpi_handle handle = context;
@@ -104,10 +104,10 @@
 	acpi_status status = AE_OK;
 
 	if (acpi_bus_get_device(handle, &device))
-		return 0;
+		return;
 
 	if (!device)
-		return 0;
+		return;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 		"Hot-removing device %s...\n", dev_name(&device->dev)));
@@ -115,7 +115,7 @@
 	if (acpi_bus_trim(device, 1)) {
 		printk(KERN_ERR PREFIX
 				"Removing device failed\n");
-		return -1;
+		return;
 	}
 
 	/* power off device */
@@ -142,9 +142,10 @@
 	 */
 	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
 	if (ACPI_FAILURE(status))
-		return -ENODEV;
+		printk(KERN_WARNING PREFIX
+				"Eject device failed\n");
 
-	return 0;
+	return;
 }
 
 static ssize_t
@@ -155,7 +156,6 @@
 	acpi_status status;
 	acpi_object_type type = 0;
 	struct acpi_device *acpi_device = to_acpi_device(d);
-	struct task_struct *task;
 
 	if ((!count) || (buf[0] != '1')) {
 		return -EINVAL;
@@ -172,11 +172,7 @@
 		goto err;
 	}
 
-	/* remove the device in another thread to fix the deadlock issue */
-	task = kthread_run(acpi_bus_hot_remove_device,
-				acpi_device->handle, "acpi_hot_remove_device");
-	if (IS_ERR(task))
-		ret = PTR_ERR(task);
+	acpi_os_hotplug_execute(acpi_bus_hot_remove_device, acpi_device->handle);
 err:
 	return ret;
 }
@@ -198,12 +194,12 @@
 	int result;
 
 	result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
-	if(result)
+	if (result)
 		goto end;
 
 	result = sprintf(buf, "%s\n", (char*)path.pointer);
 	kfree(path.pointer);
-  end:
+end:
 	return result;
 }
 static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
@@ -217,21 +213,21 @@
 	/*
 	 * Devices gotten from FADT don't have a "path" attribute
 	 */
-	if(dev->handle) {
+	if (dev->handle) {
 		result = device_create_file(&dev->dev, &dev_attr_path);
-		if(result)
+		if (result)
 			goto end;
 	}
 
-	if(dev->flags.hardware_id) {
+	if (dev->flags.hardware_id) {
 		result = device_create_file(&dev->dev, &dev_attr_hid);
-		if(result)
+		if (result)
 			goto end;
 	}
 
-	if (dev->flags.hardware_id || dev->flags.compatible_ids){
+	if (dev->flags.hardware_id || dev->flags.compatible_ids) {
 		result = device_create_file(&dev->dev, &dev_attr_modalias);
-		if(result)
+		if (result)
 			goto end;
 	}
 
@@ -242,7 +238,7 @@
 	status = acpi_get_handle(dev->handle, "_EJ0", &temp);
 	if (ACPI_SUCCESS(status))
 		result = device_create_file(&dev->dev, &dev_attr_eject);
-  end:
+end:
 	return result;
 }
 
@@ -262,9 +258,9 @@
 	if (dev->flags.hardware_id || dev->flags.compatible_ids)
 		device_remove_file(&dev->dev, &dev_attr_modalias);
 
-	if(dev->flags.hardware_id)
+	if (dev->flags.hardware_id)
 		device_remove_file(&dev->dev, &dev_attr_hid);
-	if(dev->handle)
+	if (dev->handle)
 		device_remove_file(&dev->dev, &dev_attr_path);
 }
 /* --------------------------------------------------------------------------
@@ -512,7 +508,7 @@
 			break;
 		}
 	}
-	if(!found) {
+	if (!found) {
 		acpi_device_bus_id = new_bus_id;
 		strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device");
 		acpi_device_bus_id->instance_no = 0;
@@ -530,22 +526,21 @@
 	if (device->parent)
 		device->dev.parent = &parent->dev;
 	device->dev.bus = &acpi_bus_type;
-	device_initialize(&device->dev);
 	device->dev.release = &acpi_device_release;
-	result = device_add(&device->dev);
-	if(result) {
-		dev_err(&device->dev, "Error adding device\n");
+	result = device_register(&device->dev);
+	if (result) {
+		dev_err(&device->dev, "Error registering device\n");
 		goto end;
 	}
 
 	result = acpi_device_setup_files(device);
-	if(result)
+	if (result)
 		printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n",
 		       dev_name(&device->dev));
 
 	device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
 	return 0;
-  end:
+end:
 	mutex_lock(&acpi_device_lock);
 	if (device->parent)
 		list_del(&device->node);
@@ -577,7 +572,7 @@
  * @device: the device to add and initialize
  * @driver: driver for the device
  *
- * Used to initialize a device via its device driver.  Called whenever a 
+ * Used to initialize a device via its device driver.  Called whenever a
  * driver is bound to a device.  Invokes the driver's add() ops.
  */
 static int
@@ -585,7 +580,6 @@
 {
 	int result = 0;
 
-
 	if (!device || !driver)
 		return -EINVAL;
 
@@ -802,7 +796,7 @@
 	if (!acpi_match_device_ids(device, button_device_ids))
 		device->wakeup.flags.run_wake = 1;
 
-      end:
+end:
 	if (ACPI_FAILURE(status))
 		device->flags.wake_capable = 0;
 	return 0;
@@ -1070,7 +1064,7 @@
 		break;
 	}
 
-	/* 
+	/*
 	 * \_SB
 	 * ----
 	 * Fix for the system root bus device -- the only root-level device.
@@ -1320,7 +1314,7 @@
 			device->parent->ops.bind(device);
 	}
 
-      end:
+end:
 	if (!result)
 		*child = device;
 	else {
@@ -1464,7 +1458,6 @@
 
 	return result;
 }
-
 EXPORT_SYMBOL(acpi_bus_add);
 
 int acpi_bus_start(struct acpi_device *device)
@@ -1484,7 +1477,6 @@
 	}
 	return result;
 }
-
 EXPORT_SYMBOL(acpi_bus_start);
 
 int acpi_bus_trim(struct acpi_device *start, int rmdevice)
@@ -1542,7 +1534,6 @@
 }
 EXPORT_SYMBOL_GPL(acpi_bus_trim);
 
-
 static int acpi_bus_scan_fixed(struct acpi_device *root)
 {
 	int result = 0;
@@ -1610,6 +1601,6 @@
 	if (result)
 		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
 
-      Done:
+Done:
 	return result;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/sleep.c linux-libre-2.6.31-gnu/drivers/acpi/sleep.c
--- linux-libre-2.6.30-gnu/drivers/acpi/sleep.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/sleep.c	2009-09-09 18:13:59.000000000 -0400
@@ -397,6 +397,14 @@
 		},
 	},
 	{
+	.callback = init_set_sci_en_on_resume,
+	.ident = "Hewlett-Packard HP G7000 Notebook PC",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"),
+		},
+	},
+	{
 	.callback = init_old_suspend_ordering,
 	.ident = "Panasonic CF51-2L",
 	.matches = {
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/system.c linux-libre-2.6.31-gnu/drivers/acpi/system.c
--- linux-libre-2.6.30-gnu/drivers/acpi/system.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/system.c	2009-09-09 18:13:59.000000000 -0400
@@ -121,7 +121,7 @@
 	table_attr->attr.size = 0;
 	table_attr->attr.read = acpi_table_show;
 	table_attr->attr.attr.name = table_attr->name;
-	table_attr->attr.attr.mode = 0444;
+	table_attr->attr.attr.mode = 0400;
 
 	return;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/video.c linux-libre-2.6.31-gnu/drivers/acpi/video.c
--- linux-libre-2.6.30-gnu/drivers/acpi/video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/video.c	2009-09-09 18:13:59.000000000 -0400
@@ -76,6 +76,7 @@
 static int brightness_switch_enabled = 1;
 module_param(brightness_switch_enabled, bool, 0644);
 
+static int register_count = 0;
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device, int type);
 static int acpi_video_resume(struct acpi_device *device);
@@ -586,6 +587,14 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
 		},
 	},
+	{
+	 .callback = video_set_bqc_offset,
+	 .ident = "Acer Aspire 7720",
+	 .matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
+		},
+	},
 	{}
 };
 
@@ -976,6 +985,11 @@
 		device->backlight->props.max_brightness = device->brightness->count-3;
 		kfree(name);
 
+		result = sysfs_create_link(&device->backlight->dev.kobj,
+					   &device->dev->dev.kobj, "device");
+		if (result)
+			printk(KERN_ERR PREFIX "Create sysfs link\n");
+
 		device->cdev = thermal_cooling_device_register("LCD",
 					device->dev, &video_cooling_ops);
 		if (IS_ERR(device->cdev))
@@ -1054,15 +1068,15 @@
 static int acpi_video_bus_check(struct acpi_video_bus *video)
 {
 	acpi_status status = -ENOENT;
-	struct device *dev;
+	struct pci_dev *dev;
 
 	if (!video)
 		return -EINVAL;
 
-	dev = acpi_get_physical_pci_device(video->device->handle);
+	dev = acpi_get_pci_dev(video->device->handle);
 	if (!dev)
 		return -ENODEV;
-	put_device(dev);
+	pci_dev_put(dev);
 
 	/* Since there is no HID, CID and so on for VGA driver, we have
 	 * to check well known required nodes.
@@ -1990,7 +2004,11 @@
 	status = acpi_remove_notify_handler(device->dev->handle,
 					    ACPI_DEVICE_NOTIFY,
 					    acpi_video_device_notify);
-	backlight_device_unregister(device->backlight);
+	if (device->backlight) {
+		sysfs_remove_link(&device->backlight->dev.kobj, "device");
+		backlight_device_unregister(device->backlight);
+		device->backlight = NULL;
+	}
 	if (device->cdev) {
 		sysfs_remove_link(&device->dev->dev.kobj,
 				  "thermal_cooling");
@@ -2318,6 +2336,13 @@
 int acpi_video_register(void)
 {
 	int result = 0;
+	if (register_count) {
+		/*
+		 * if the function of acpi_video_register is already called,
+		 * don't register the acpi_vide_bus again and return no error.
+		 */
+		return 0;
+	}
 
 	acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
 	if (!acpi_video_dir)
@@ -2329,10 +2354,35 @@
 		return -ENODEV;
 	}
 
+	/*
+	 * When the acpi_video_bus is loaded successfully, increase
+	 * the counter reference.
+	 */
+	register_count = 1;
+
 	return 0;
 }
 EXPORT_SYMBOL(acpi_video_register);
 
+void acpi_video_unregister(void)
+{
+	if (!register_count) {
+		/*
+		 * If the acpi video bus is already unloaded, don't
+		 * unload it again and return directly.
+		 */
+		return;
+	}
+	acpi_bus_unregister_driver(&acpi_video_bus);
+
+	remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
+
+	register_count = 0;
+
+	return;
+}
+EXPORT_SYMBOL(acpi_video_unregister);
+
 /*
  * This is kind of nasty. Hardware using Intel chipsets may require
  * the video opregion code to be run first in order to initialise
@@ -2350,16 +2400,12 @@
 	return acpi_video_register();
 }
 
-void acpi_video_exit(void)
+static void __exit acpi_video_exit(void)
 {
-
-	acpi_bus_unregister_driver(&acpi_video_bus);
-
-	remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
+	acpi_video_unregister();
 
 	return;
 }
-EXPORT_SYMBOL(acpi_video_exit);
 
 module_init(acpi_video_init);
 module_exit(acpi_video_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/acpi/video_detect.c linux-libre-2.6.31-gnu/drivers/acpi/video_detect.c
--- linux-libre-2.6.30-gnu/drivers/acpi/video_detect.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/acpi/video_detect.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,7 @@
  * assinged
  *
  * After PCI devices are glued with ACPI devices
- * acpi_get_physical_pci_device() can be called to identify ACPI graphics
+ * acpi_get_pci_dev() can be called to identify ACPI graphics
  * devices for which a real graphics card is plugged in
  *
  * Now acpi_video_get_capabilities() can be called to check which
@@ -36,6 +36,7 @@
 
 #include <linux/acpi.h>
 #include <linux/dmi.h>
+#include <linux/pci.h>
 
 ACPI_MODULE_NAME("video");
 #define _COMPONENT		ACPI_VIDEO_COMPONENT
@@ -109,7 +110,7 @@
 find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 	long *cap = context;
-	struct device *dev;
+	struct pci_dev *dev;
 	struct acpi_device *acpi_dev;
 
 	const struct acpi_device_id video_ids[] = {
@@ -120,10 +121,10 @@
 		return AE_OK;
 
 	if (!acpi_match_device_ids(acpi_dev, video_ids)) {
-		dev = acpi_get_physical_pci_device(handle);
+		dev = acpi_get_pci_dev(handle);
 		if (!dev)
 			return AE_OK;
-		put_device(dev);
+		pci_dev_put(dev);
 		*cap |= acpi_is_video_device(acpi_dev);
 	}
 	return AE_OK;
diff -druN linux-libre-2.6.30-gnu/drivers/amba/bus.c linux-libre-2.6.31-gnu/drivers/amba/bus.c
--- linux-libre-2.6.30-gnu/drivers/amba/bus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/amba/bus.c	2009-09-09 18:13:59.000000000 -0400
@@ -207,6 +207,16 @@
 	void __iomem *tmp;
 	int i, ret;
 
+	device_initialize(&dev->dev);
+
+	/*
+	 * Copy from device_add
+	 */
+	if (dev->dev.init_name) {
+		dev_set_name(&dev->dev, "%s", dev->dev.init_name);
+		dev->dev.init_name = NULL;
+	}
+
 	dev->dev.release = amba_device_release;
 	dev->dev.bus = &amba_bustype;
 	dev->dev.dma_mask = &dev->dma_mask;
@@ -240,7 +250,7 @@
 		goto err_release;
 	}
 
-	ret = device_register(&dev->dev);
+	ret = device_add(&dev->dev);
 	if (ret)
 		goto err_release;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ata/ahci.c linux-libre-2.6.31-gnu/drivers/ata/ahci.c
--- linux-libre-2.6.30-gnu/drivers/ata/ahci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/ahci.c	2009-09-09 18:13:59.000000000 -0400
@@ -77,8 +77,6 @@
 			      size_t size);
 static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
 					ssize_t size);
-#define MAX_SLOTS 8
-#define MAX_RETRY 15
 
 enum {
 	AHCI_PCI_BAR		= 5,
@@ -221,6 +219,8 @@
 	AHCI_HFLAG_SECT255		= (1 << 8), /* max 255 sectors */
 	AHCI_HFLAG_YES_NCQ		= (1 << 9), /* force NCQ cap on */
 	AHCI_HFLAG_NO_SUSPEND		= (1 << 10), /* don't suspend */
+	AHCI_HFLAG_SRST_TOUT_IS_OFFLINE	= (1 << 11), /* treat SRST timeout as
+							link offline */
 
 	/* ap->flags bits */
 
@@ -231,6 +231,10 @@
 
 	ICH_MAP				= 0x90, /* ICH MAP register */
 
+	/* em constants */
+	EM_MAX_SLOTS			= 8,
+	EM_MAX_RETRY			= 5,
+
 	/* em_ctl bits */
 	EM_CTL_RST			= (1 << 9), /* Reset */
 	EM_CTL_TM			= (1 << 8), /* Transmit Message */
@@ -282,8 +286,8 @@
 	unsigned int		ncq_saw_dmas:1;
 	unsigned int		ncq_saw_sdb:1;
 	u32 			intr_mask;	/* interrupts to enable */
-	struct ahci_em_priv	em_priv[MAX_SLOTS];/* enclosure management info
-					 	 * per PM slot */
+	/* enclosure management info per PM slot */
+	struct ahci_em_priv	em_priv[EM_MAX_SLOTS];
 };
 
 static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
@@ -313,7 +317,6 @@
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static int ahci_port_resume(struct ata_port *ap);
 static void ahci_dev_config(struct ata_device *dev);
-static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
 static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
 			       u32 opts);
 #ifdef CONFIG_PM
@@ -404,14 +407,14 @@
 #define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
 
 static const struct ata_port_info ahci_port_info[] = {
-	/* board_ahci */
+	[board_ahci] =
 	{
 		.flags		= AHCI_FLAG_COMMON,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
-	/* board_ahci_vt8251 */
+	[board_ahci_vt8251] =
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
@@ -419,7 +422,7 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_vt8251_ops,
 	},
-	/* board_ahci_ign_iferr */
+	[board_ahci_ign_iferr] =
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
 		.flags		= AHCI_FLAG_COMMON,
@@ -427,17 +430,16 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
-	/* board_ahci_sb600 */
+	[board_ahci_sb600] =
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
-				 AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
-				 AHCI_HFLAG_SECT255),
+				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255),
 		.flags		= AHCI_FLAG_COMMON,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_sb600_ops,
 	},
-	/* board_ahci_mv */
+	[board_ahci_mv] =
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
@@ -447,7 +449,7 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
-	/* board_ahci_sb700, for SB700 and SB800 */
+	[board_ahci_sb700] =	/* for SB700 and SB800 */
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),
 		.flags		= AHCI_FLAG_COMMON,
@@ -455,7 +457,7 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_sb600_ops,
 	},
-	/* board_ahci_mcp65 */
+	[board_ahci_mcp65] =
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_YES_NCQ),
 		.flags		= AHCI_FLAG_COMMON,
@@ -463,7 +465,7 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
-	/* board_ahci_nopmp */
+	[board_ahci_nopmp] =
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_PMP),
 		.flags		= AHCI_FLAG_COMMON,
@@ -513,11 +515,16 @@
 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
 	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
+	{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
 	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
+	{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
+	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
+	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
+	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -1141,12 +1148,12 @@
 			emp = &pp->em_priv[link->pmp];
 
 			/* EM Transmit bit maybe busy during init */
-			for (i = 0; i < MAX_RETRY; i++) {
+			for (i = 0; i < EM_MAX_RETRY; i++) {
 				rc = ahci_transmit_led_message(ap,
 							       emp->led_state,
 							       4);
 				if (rc == -EBUSY)
-					udelay(100);
+					msleep(1);
 				else
 					break;
 			}
@@ -1340,7 +1347,7 @@
 
 	/* get the slot number from the message */
 	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
-	if (pmp < MAX_SLOTS)
+	if (pmp < EM_MAX_SLOTS)
 		emp = &pp->em_priv[pmp];
 	else
 		return -EINVAL;
@@ -1408,7 +1415,7 @@
 
 	/* get the slot number from the message */
 	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
-	if (pmp < MAX_SLOTS)
+	if (pmp < EM_MAX_SLOTS)
 		emp = &pp->em_priv[pmp];
 	else
 		return -EINVAL;
@@ -1658,6 +1665,7 @@
 			     int (*check_ready)(struct ata_link *link))
 {
 	struct ata_port *ap = link->ap;
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	const char *reason = NULL;
 	unsigned long now, msecs;
 	struct ata_taskfile tf;
@@ -1696,12 +1704,21 @@
 
 	/* wait for link to become ready */
 	rc = ata_wait_after_reset(link, deadline, check_ready);
-	/* link occupied, -ENODEV too is an error */
-	if (rc) {
+	if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) {
+		/*
+		 * Workaround for cases where link online status can't
+		 * be trusted.  Treat device readiness timeout as link
+		 * offline.
+		 */
+		ata_link_printk(link, KERN_INFO,
+				"device not ready, treating as offline\n");
+		*class = ATA_DEV_NONE;
+	} else if (rc) {
+		/* link occupied, -ENODEV too is an error */
 		reason = "device not ready";
 		goto fail;
-	}
-	*class = ahci_dev_classify(ap);
+	} else
+		*class = ahci_dev_classify(ap);
 
 	DPRINTK("EXIT, class=%u\n", *class);
 	return 0;
@@ -1768,7 +1785,8 @@
 		irq_sts = readl(port_mmio + PORT_IRQ_STAT);
 		if (irq_sts & PORT_IRQ_BAD_PMP) {
 			ata_link_printk(link, KERN_WARNING,
-					"failed due to HW bug, retry pmp=0\n");
+					"applying SB600 PMP SRST workaround "
+					"and retrying\n");
 			rc = ahci_do_softreset(link, class, 0, deadline,
 					       ahci_check_ready);
 		}
@@ -2584,6 +2602,51 @@
 	}
 }
 
+/*
+ * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older
+ * BIOS.  The oldest version known to be broken is 0901 and working is
+ * 1501 which was released on 2007-10-26.  Force 32bit DMA on anything
+ * older than 1501.  Please read bko#9412 for more info.
+ */
+static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev)
+{
+	static const struct dmi_system_id sysids[] = {
+		{
+			.ident = "ASUS M2A-VM",
+			.matches = {
+				DMI_MATCH(DMI_BOARD_VENDOR,
+					  "ASUSTeK Computer INC."),
+				DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"),
+			},
+		},
+		{ }
+	};
+	const char *cutoff_mmdd = "10/26";
+	const char *date;
+	int year;
+
+	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) ||
+	    !dmi_check_system(sysids))
+		return false;
+
+	/*
+	 * Argh.... both version and date are free form strings.
+	 * Let's hope they're using the same date format across
+	 * different versions.
+	 */
+	date = dmi_get_system_info(DMI_BIOS_DATE);
+	year = dmi_get_year(DMI_BIOS_DATE);
+	if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' &&
+	    (year > 2007 ||
+	     (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0)))
+		return false;
+
+	dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, "
+		   "forcing 32bit DMA, update BIOS\n");
+
+	return true;
+}
+
 static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
 {
 	static const struct dmi_system_id broken_systems[] = {
@@ -2676,6 +2739,56 @@
 	return !ver || strcmp(ver, dmi->driver_data) < 0;
 }
 
+static bool ahci_broken_online(struct pci_dev *pdev)
+{
+#define ENCODE_BUSDEVFN(bus, slot, func)			\
+	(void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
+	static const struct dmi_system_id sysids[] = {
+		/*
+		 * There are several gigabyte boards which use
+		 * SIMG5723s configured as hardware RAID.  Certain
+		 * 5723 firmware revisions shipped there keep the link
+		 * online but fail to answer properly to SRST or
+		 * IDENTIFY when no device is attached downstream
+		 * causing libata to retry quite a few times leading
+		 * to excessive detection delay.
+		 *
+		 * As these firmwares respond to the second reset try
+		 * with invalid device signature, considering unknown
+		 * sig as offline works around the problem acceptably.
+		 */
+		{
+			.ident = "EP45-DQ6",
+			.matches = {
+				DMI_MATCH(DMI_BOARD_VENDOR,
+					  "Gigabyte Technology Co., Ltd."),
+				DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
+			},
+			.driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
+		},
+		{
+			.ident = "EP45-DS5",
+			.matches = {
+				DMI_MATCH(DMI_BOARD_VENDOR,
+					  "Gigabyte Technology Co., Ltd."),
+				DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
+			},
+			.driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
+		},
+		{ }	/* terminate list */
+	};
+#undef ENCODE_BUSDEVFN
+	const struct dmi_system_id *dmi = dmi_first_match(sysids);
+	unsigned int val;
+
+	if (!dmi)
+		return false;
+
+	val = (unsigned long)dmi->driver_data;
+
+	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
+}
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
@@ -2744,6 +2857,10 @@
 	if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
 		hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
 
+	/* apply ASUS M2A_VM quirk */
+	if (ahci_asus_m2a_vm_32bit_only(pdev))
+		hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;
+
 	if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
 		pci_enable_msi(pdev);
 
@@ -2787,6 +2904,12 @@
 			   "BIOS update required for suspend/resume\n");
 	}
 
+	if (ahci_broken_online(pdev)) {
+		hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
+		dev_info(&pdev->dev,
+			 "online status unreliable, applying workaround\n");
+	}
+
 	/* CAP.NP sometimes indicate the index of the last enabled
 	 * port, at other times, that of the last possible port, so
 	 * determining the maximum port number requires looking at
diff -druN linux-libre-2.6.30-gnu/drivers/ata/ata_piix.c linux-libre-2.6.31-gnu/drivers/ata/ata_piix.c
--- linux-libre-2.6.30-gnu/drivers/ata/ata_piix.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/ata_piix.c	2009-09-09 18:13:59.000000000 -0400
@@ -223,10 +223,8 @@
 	/* ICH8 Mobile PATA Controller */
 	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 
-	/* NOTE: The following PCI ids must be kept in sync with the
-	 * list in drivers/pci/quirks.c.
-	 */
-
+	/* SATA ports */
+	
 	/* 82801EB (ICH5) */
 	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	/* 82801EB (ICH5) */
@@ -598,9 +596,12 @@
 	{ 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */
 	{ 0x27DF, 0x1025, 0x0102 },	/* ICH7 on Acer 5602aWLMi */
 	{ 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */
+	{ 0x27DF, 0x1028, 0x02b0 },	/* ICH7 on unknown Dell */
 	{ 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */
 	{ 0x27DF, 0x103C, 0x30A1 },	/* ICH7 on HP Compaq nc2400 */
+	{ 0x27DF, 0x103C, 0x361a },	/* ICH7 on unkown HP  */
 	{ 0x27DF, 0x1071, 0xD221 },	/* ICH7 on Hercules EC-900 */
+	{ 0x27DF, 0x152D, 0x0778 },	/* ICH7 on unknown Intel */
 	{ 0x24CA, 0x1025, 0x0061 },	/* ICH4 on ACER Aspire 2023WLMi */
 	{ 0x24CA, 0x1025, 0x003d },	/* ICH4 on ACER TM290 */
 	{ 0x266F, 0x1025, 0x0066 },	/* ICH6 on ACER Aspire 1694WLMi */
@@ -663,6 +664,8 @@
 	return ata_sff_prereset(link, deadline);
 }
 
+static DEFINE_SPINLOCK(piix_lock);
+
 /**
  *	piix_set_piomode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
@@ -676,8 +679,9 @@
 
 static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	unsigned long flags;
+	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	unsigned int is_slave	= (adev->devno != 0);
 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
@@ -707,6 +711,8 @@
 	if (adev->class == ATA_DEV_ATA)
 		control |= 4;	/* PPE enable */
 
+	spin_lock_irqsave(&piix_lock, flags);
+
 	/* PIO configuration clears DTE unconditionally.  It will be
 	 * programmed in set_dmamode which is guaranteed to be called
 	 * after set_piomode if any DMA mode is available.
@@ -746,6 +752,8 @@
 		udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
 		pci_write_config_byte(dev, 0x48, udma_enable);
 	}
+
+	spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
@@ -763,6 +771,7 @@
 static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich)
 {
 	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
+	unsigned long flags;
 	u8 master_port		= ap->port_no ? 0x42 : 0x40;
 	u16 master_data;
 	u8 speed		= adev->dma_mode;
@@ -776,6 +785,8 @@
 			    { 2, 1 },
 			    { 2, 3 }, };
 
+	spin_lock_irqsave(&piix_lock, flags);
+
 	pci_read_config_word(dev, master_port, &master_data);
 	if (ap->udma_mask)
 		pci_read_config_byte(dev, 0x48, &udma_enable);
@@ -866,6 +877,8 @@
 	/* Don't scribble on 0x48 if the controller does not support UDMA */
 	if (ap->udma_mask)
 		pci_write_config_byte(dev, 0x48, udma_enable);
+
+	spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
@@ -1509,8 +1522,8 @@
 		dev_printk(KERN_DEBUG, &pdev->dev,
 			   "version " DRV_VERSION "\n");
 
-	/* no hotplugging support (FIXME) */
-	if (!in_module_init)
+	/* no hotplugging support for later devices (FIXME) */
+	if (!in_module_init && ent->driver_data >= ich5_sata)
 		return -ENODEV;
 
 	if (piix_broken_system_poweroff(pdev)) {
@@ -1591,6 +1604,7 @@
 		host->ports[1]->mwdma_mask = 0;
 		host->ports[1]->udma_mask = 0;
 	}
+	host->flags |= ATA_HOST_PARALLEL_SCAN;
 
 	pci_set_master(pdev);
 	return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
diff -druN linux-libre-2.6.30-gnu/drivers/ata/Kconfig linux-libre-2.6.31-gnu/drivers/ata/Kconfig
--- linux-libre-2.6.30-gnu/drivers/ata/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -535,6 +535,15 @@
 
 	  If unsure, say N.
 
+config PATA_PALMLD
+	tristate "Palm LifeDrive PATA support"
+	depends on MACH_PALMLD
+	help
+	  This option enables support for Palm LifeDrive's internal ATA
+	  port via the new ATA layer.
+
+	  If unsure, say N.
+
 config PATA_PCMCIA
 	tristate "PCMCIA PATA support"
 	depends on PCMCIA
@@ -670,6 +679,14 @@
 
 	  If unsure, say N.
 
+config PATA_AT91
+	tristate "PATA support for AT91SAM9260"
+	depends on ARM && ARCH_AT91
+	help
+	  This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
+
+	  If unsure, say N.
+
 config PATA_OF_PLATFORM
 	tristate "OpenFirmware platform device PATA support"
 	depends on PATA_PLATFORM && PPC_OF
diff -druN linux-libre-2.6.30-gnu/drivers/ata/libata-acpi.c linux-libre-2.6.31-gnu/drivers/ata/libata-acpi.c
--- linux-libre-2.6.30-gnu/drivers/ata/libata-acpi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/libata-acpi.c	2009-09-09 18:13:59.000000000 -0400
@@ -748,9 +748,9 @@
 /**
  * ata_acpi_exec_tfs - get then write drive taskfile settings
  * @dev: target ATA device
- * @nr_executed: out paramter for the number of executed commands
+ * @nr_executed: out parameter for the number of executed commands
  *
- * Evaluate _GTF and excute returned taskfiles.
+ * Evaluate _GTF and execute returned taskfiles.
  *
  * LOCKING:
  * EH context.
diff -druN linux-libre-2.6.30-gnu/drivers/ata/libata-core.c linux-libre-2.6.31-gnu/drivers/ata/libata-core.c
--- linux-libre-2.6.30-gnu/drivers/ata/libata-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/libata-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -125,19 +125,19 @@
 
 static int atapi_enabled = 1;
 module_param(atapi_enabled, int, 0444);
-MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
+MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on [default])");
 
 static int atapi_dmadir = 0;
 module_param(atapi_dmadir, int, 0444);
-MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)");
+MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off [default], 1=on)");
 
 int atapi_passthru16 = 1;
 module_param(atapi_passthru16, int, 0444);
-MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devices; on by default (0=off, 1=on)");
+MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devices (0=off, 1=on [default])");
 
 int libata_fua = 0;
 module_param_named(fua, libata_fua, int, 0444);
-MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
+MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)");
 
 static int ata_ignore_hpa;
 module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644);
@@ -153,11 +153,11 @@
 
 int libata_noacpi = 0;
 module_param_named(noacpi, libata_noacpi, int, 0444);
-MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in probe/suspend/resume when set");
+MODULE_PARM_DESC(noacpi, "Disable the use of ACPI in probe/suspend/resume (0=off [default], 1=on)");
 
 int libata_allow_tpm = 0;
 module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
-MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands");
+MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)");
 
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
@@ -1515,6 +1515,7 @@
 
 		return rc;
 	}
+	dev->n_native_sectors = native_sectors;
 
 	/* nothing to do? */
 	if (native_sectors <= sectors || !ata_ignore_hpa) {
@@ -1993,11 +1994,17 @@
  *	Check if the current speed of the device requires IORDY. Used
  *	by various controllers for chip configuration.
  */
-
 unsigned int ata_pio_need_iordy(const struct ata_device *adev)
 {
-	/* Controller doesn't support  IORDY. Probably a pointless check
-	   as the caller should know this */
+	/* Don't set IORDY if we're preparing for reset.  IORDY may
+	 * lead to controller lock up on certain controllers if the
+	 * port is not occupied.  See bko#11703 for details.
+	 */
+	if (adev->link->ap->pflags & ATA_PFLAG_RESETTING)
+		return 0;
+	/* Controller doesn't support IORDY.  Probably a pointless
+	 * check as the caller should know this.
+	 */
 	if (adev->link->ap->flags & ATA_FLAG_NO_IORDY)
 		return 0;
 	/* CF spec. r4.1 Table 22 says no iordy on PIO5 and PIO6.  */
@@ -2020,7 +2027,6 @@
  *	Compute the highest mode possible if we are not using iordy. Return
  *	-1 if no iordy mode is available.
  */
-
 static u32 ata_pio_mask_no_iordy(const struct ata_device *adev)
 {
 	/* If we have no drive specific rule, then PIO 2 is non IORDY */
@@ -3387,17 +3393,27 @@
 
 static int ata_dev_set_mode(struct ata_device *dev)
 {
+	struct ata_port *ap = dev->link->ap;
 	struct ata_eh_context *ehc = &dev->link->eh_context;
+	const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER;
 	const char *dev_err_whine = "";
 	int ign_dev_err = 0;
-	unsigned int err_mask;
+	unsigned int err_mask = 0;
 	int rc;
 
 	dev->flags &= ~ATA_DFLAG_PIO;
 	if (dev->xfer_shift == ATA_SHIFT_PIO)
 		dev->flags |= ATA_DFLAG_PIO;
 
-	err_mask = ata_dev_set_xfermode(dev);
+	if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id))
+		dev_err_whine = " (SET_XFERMODE skipped)";
+	else {
+		if (nosetxfer)
+			ata_dev_printk(dev, KERN_WARNING,
+				       "NOSETXFER but PATA detected - can't "
+				       "skip SETXFER, might malfunction\n");
+		err_mask = ata_dev_set_xfermode(dev);
+	}
 
 	if (err_mask & ~AC_ERR_DEV)
 		goto fail;
@@ -4084,6 +4100,7 @@
 		       unsigned int readid_flags)
 {
 	u64 n_sectors = dev->n_sectors;
+	u64 n_native_sectors = dev->n_native_sectors;
 	int rc;
 
 	if (!ata_dev_enabled(dev))
@@ -4113,16 +4130,30 @@
 	/* verify n_sectors hasn't changed */
 	if (dev->class == ATA_DEV_ATA && n_sectors &&
 	    dev->n_sectors != n_sectors) {
-		ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
+		ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
 			       "%llu != %llu\n",
 			       (unsigned long long)n_sectors,
 			       (unsigned long long)dev->n_sectors);
-
-		/* restore original n_sectors */
-		dev->n_sectors = n_sectors;
-
-		rc = -ENODEV;
-		goto fail;
+		/*
+		 * Something could have caused HPA to be unlocked
+		 * involuntarily.  If n_native_sectors hasn't changed
+		 * and the new size matches it, keep the device.
+		 */
+		if (dev->n_native_sectors == n_native_sectors &&
+		    dev->n_sectors > n_sectors &&
+		    dev->n_sectors == n_native_sectors) {
+			ata_dev_printk(dev, KERN_WARNING,
+				       "new n_sectors matches native, probably "
+				       "late HPA unlock, continuing\n");
+			/* keep using the old n_sectors */
+			dev->n_sectors = n_sectors;
+		} else {
+			/* restore original n_[native]_sectors and fail */
+			dev->n_native_sectors = n_native_sectors;
+			dev->n_sectors = n_sectors;
+			rc = -ENODEV;
+			goto fail;
+		}
 	}
 
 	return 0;
@@ -4271,6 +4302,9 @@
 	{ "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA },
 	{ "MAXTOR 6L080L4",	"A93.0500",	ATA_HORKAGE_BROKEN_HPA },
 
+	/* this one allows HPA unlocking but fails IOs on the area */
+	{ "OCZ-VERTEX",		    "1.30",	ATA_HORKAGE_BROKEN_HPA },
+
 	/* Devices which report 1 sector over size HPA */
 	{ "ST340823A",		NULL,		ATA_HORKAGE_HPA_SIZE, },
 	{ "ST320413A",		NULL,		ATA_HORKAGE_HPA_SIZE, },
@@ -4292,6 +4326,12 @@
 	/* Devices which aren't very happy with higher link speeds */
 	{ "WD My Book",			NULL,	ATA_HORKAGE_1_5_GBPS, },
 
+	/*
+	 * Devices which choke on SETXFER.  Applies only if both the
+	 * device and controller are SATA.
+	 */
+	{ "PIONEER DVD-RW  DVRTD08",	"1.00",	ATA_HORKAGE_NOSETXFER },
+
 	/* End Marker */
 	{ }
 };
@@ -5031,7 +5071,6 @@
 {
 	int nr_done = 0;
 	u32 done_mask;
-	int i;
 
 	done_mask = ap->qc_active ^ qc_active;
 
@@ -5041,16 +5080,16 @@
 		return -EINVAL;
 	}
 
-	for (i = 0; i < ATA_MAX_QUEUE; i++) {
+	while (done_mask) {
 		struct ata_queued_cmd *qc;
+		unsigned int tag = __ffs(done_mask);
 
-		if (!(done_mask & (1 << i)))
-			continue;
-
-		if ((qc = ata_qc_from_tag(ap, i))) {
+		qc = ata_qc_from_tag(ap, tag);
+		if (qc) {
 			ata_qc_complete(qc);
 			nr_done++;
 		}
+		done_mask &= ~(1 << tag);
 	}
 
 	return nr_done;
diff -druN linux-libre-2.6.30-gnu/drivers/ata/libata-eh.c linux-libre-2.6.31-gnu/drivers/ata/libata-eh.c
--- linux-libre-2.6.30-gnu/drivers/ata/libata-eh.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/libata-eh.c	2009-09-09 18:13:59.000000000 -0400
@@ -2327,7 +2327,7 @@
 	struct ata_port *ap = link->ap;
 	struct ata_link *slave = ap->slave_link;
 	struct ata_eh_context *ehc = &link->eh_context;
-	struct ata_eh_context *sehc = &slave->eh_context;
+	struct ata_eh_context *sehc = slave ? &slave->eh_context : NULL;
 	unsigned int *classes = ehc->classes;
 	unsigned int lflags = link->flags;
 	int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
@@ -2517,6 +2517,10 @@
 
 			ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
 			rc = ata_do_reset(link, reset, classes, deadline, true);
+			if (rc) {
+				failed_link = link;
+				goto fail;
+			}
 		}
 	} else {
 		if (verbose)
@@ -2864,7 +2868,7 @@
 /**
  *	ata_set_mode - Program timings and issue SET FEATURES - XFER
  *	@link: link on which timings will be programmed
- *	@r_failed_dev: out paramter for failed device
+ *	@r_failed_dev: out parameter for failed device
  *
  *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
  *	ata_set_mode() fails, pointer to the failing device is
diff -druN linux-libre-2.6.30-gnu/drivers/ata/libata-scsi.c linux-libre-2.6.31-gnu/drivers/ata/libata-scsi.c
--- linux-libre-2.6.30-gnu/drivers/ata/libata-scsi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/libata-scsi.c	2009-09-09 18:13:59.000000000 -0400
@@ -1084,7 +1084,7 @@
 	if (likely(!blk_pc_request(rq)))
 		return 0;
 
-	if (!rq->data_len || (rq->cmd_flags & REQ_RW))
+	if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_RW))
 		return 0;
 
 	return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC;
diff -druN linux-libre-2.6.30-gnu/drivers/ata/libata-sff.c linux-libre-2.6.31-gnu/drivers/ata/libata-sff.c
--- linux-libre-2.6.30-gnu/drivers/ata/libata-sff.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/libata-sff.c	2009-09-09 18:13:59.000000000 -0400
@@ -727,17 +727,23 @@
 	else
 		iowrite16_rep(data_addr, buf, words);
 
-	/* Transfer trailing 1 byte, if any. */
+	/* Transfer trailing byte, if any. */
 	if (unlikely(buflen & 0x01)) {
-		__le16 align_buf[1] = { 0 };
-		unsigned char *trailing_buf = buf + buflen - 1;
+		unsigned char pad[2];
 
+		/* Point buf to the tail of buffer */
+		buf += buflen - 1;
+
+		/*
+		 * Use io*16_rep() accessors here as well to avoid pointlessly
+		 * swapping bytes to and fro on the big endian machines...
+		 */
 		if (rw == READ) {
-			align_buf[0] = cpu_to_le16(ioread16(data_addr));
-			memcpy(trailing_buf, align_buf, 1);
+			ioread16_rep(data_addr, pad, 1);
+			*buf = pad[0];
 		} else {
-			memcpy(align_buf, trailing_buf, 1);
-			iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+			pad[0] = *buf;
+			iowrite16_rep(data_addr, pad, 1);
 		}
 		words++;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/ata/Makefile linux-libre-2.6.31-gnu/drivers/ata/Makefile
--- linux-libre-2.6.30-gnu/drivers/ata/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,7 @@
 obj-$(CONFIG_PATA_MARVELL)	+= pata_marvell.o
 obj-$(CONFIG_PATA_MPIIX)	+= pata_mpiix.o
 obj-$(CONFIG_PATA_OLDPIIX)	+= pata_oldpiix.o
+obj-$(CONFIG_PATA_PALMLD)	+= pata_palmld.o
 obj-$(CONFIG_PATA_PCMCIA)	+= pata_pcmcia.o
 obj-$(CONFIG_PATA_PDC2027X)	+= pata_pdc2027x.o
 obj-$(CONFIG_PATA_PDC_OLD)	+= pata_pdc202xx_old.o
@@ -71,6 +72,7 @@
 obj-$(CONFIG_PATA_BF54X)	+= pata_bf54x.o
 obj-$(CONFIG_PATA_OCTEON_CF)	+= pata_octeon_cf.o
 obj-$(CONFIG_PATA_PLATFORM)	+= pata_platform.o
+obj-$(CONFIG_PATA_AT91)	+= pata_at91.o
 obj-$(CONFIG_PATA_OF_PLATFORM)	+= pata_of_platform.o
 obj-$(CONFIG_PATA_ICSIDE)	+= pata_icside.o
 # Should be last but two libata driver
diff -druN linux-libre-2.6.30-gnu/drivers/ata/pata_at91.c linux-libre-2.6.31-gnu/drivers/ata/pata_at91.c
--- linux-libre-2.6.30-gnu/drivers/ata/pata_at91.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/ata/pata_at91.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,358 @@
+/*
+ * PATA driver for AT91SAM9260 Static Memory Controller
+ * with CompactFlash interface in True IDE mode
+ *
+ * Copyright (C) 2009 Matyukevich Sergey
+ *
+ * Based on:
+ *      * generic platform driver by Paul Mundt: drivers/ata/pata_platform.c
+ *      * pata_at32 driver by Kristoffer Nyborg Gregertsen
+ *      * at91_ide driver by Stanislaw Gruszka
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
+#include <linux/ata.h>
+#include <linux/clk.h>
+#include <linux/libata.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+
+#include <mach/at91sam9_smc.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+
+
+#define DRV_NAME "pata_at91"
+#define DRV_VERSION "0.1"
+
+#define CF_IDE_OFFSET	    0x00c00000
+#define CF_ALT_IDE_OFFSET   0x00e00000
+#define CF_IDE_RES_SIZE     0x08
+
+struct at91_ide_info {
+	unsigned long mode;
+	unsigned int cs;
+
+	struct clk *mck;
+
+	void __iomem *ide_addr;
+	void __iomem *alt_addr;
+};
+
+static const struct ata_timing initial_timing =
+	{XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
+
+static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)
+{
+	unsigned long mul;
+
+	/*
+	* cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] =
+	*     x * (f / 1_000_000_000) =
+	*     x * ((f * 65536) / 1_000_000_000) / 65536 =
+	*     x * (((f / 10_000) * 65536) / 100_000) / 65536 =
+	*/
+
+	mul = (mck_hz / 10000) << 16;
+	mul /= 100000;
+
+	return (ns * mul + 65536) >> 16;    /* rounding */
+}
+
+static void set_smc_mode(struct at91_ide_info *info)
+{
+	at91_sys_write(AT91_SMC_MODE(info->cs), info->mode);
+	return;
+}
+
+static void set_smc_timing(struct device *dev,
+		struct at91_ide_info *info, const struct ata_timing *ata)
+{
+	unsigned long read_cycle, write_cycle, active, recover;
+	unsigned long nrd_setup, nrd_pulse, nrd_recover;
+	unsigned long nwe_setup, nwe_pulse;
+
+	unsigned long ncs_write_setup, ncs_write_pulse;
+	unsigned long ncs_read_setup, ncs_read_pulse;
+
+	unsigned long mck_hz;
+
+	read_cycle  = ata->cyc8b;
+	nrd_setup   = ata->setup;
+	nrd_pulse   = ata->act8b;
+	nrd_recover = ata->rec8b;
+
+	mck_hz = clk_get_rate(info->mck);
+
+	read_cycle  = calc_mck_cycles(read_cycle, mck_hz);
+	nrd_setup   = calc_mck_cycles(nrd_setup, mck_hz);
+	nrd_pulse   = calc_mck_cycles(nrd_pulse, mck_hz);
+	nrd_recover = calc_mck_cycles(nrd_recover, mck_hz);
+
+	active  = nrd_setup + nrd_pulse;
+	recover = read_cycle - active;
+
+	/* Need at least two cycles recovery */
+	if (recover < 2)
+		read_cycle = active + 2;
+
+	/* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */
+	ncs_read_setup = 1;
+	ncs_read_pulse = read_cycle - 2;
+
+	/* Write timings same as read timings */
+	write_cycle = read_cycle;
+	nwe_setup = nrd_setup;
+	nwe_pulse = nrd_pulse;
+	ncs_write_setup = ncs_read_setup;
+	ncs_write_pulse = ncs_read_pulse;
+
+	dev_dbg(dev, "ATA timings: nrd_setup = %lu nrd_pulse = %lu nrd_cycle = %lu\n",
+			nrd_setup, nrd_pulse, read_cycle);
+	dev_dbg(dev, "ATA timings: nwe_setup = %lu nwe_pulse = %lu nwe_cycle = %lu\n",
+			nwe_setup, nwe_pulse, write_cycle);
+	dev_dbg(dev, "ATA timings: ncs_read_setup = %lu ncs_read_pulse = %lu\n",
+			ncs_read_setup, ncs_read_pulse);
+	dev_dbg(dev, "ATA timings: ncs_write_setup = %lu ncs_write_pulse = %lu\n",
+			ncs_write_setup, ncs_write_pulse);
+
+	at91_sys_write(AT91_SMC_SETUP(info->cs),
+			AT91_SMC_NWESETUP_(nwe_setup) |
+			AT91_SMC_NRDSETUP_(nrd_setup) |
+			AT91_SMC_NCS_WRSETUP_(ncs_write_setup) |
+			AT91_SMC_NCS_RDSETUP_(ncs_read_setup));
+
+	at91_sys_write(AT91_SMC_PULSE(info->cs),
+			AT91_SMC_NWEPULSE_(nwe_pulse) |
+			AT91_SMC_NRDPULSE_(nrd_pulse) |
+			AT91_SMC_NCS_WRPULSE_(ncs_write_pulse) |
+			AT91_SMC_NCS_RDPULSE_(ncs_read_pulse));
+
+	at91_sys_write(AT91_SMC_CYCLE(info->cs),
+			AT91_SMC_NWECYCLE_(write_cycle) |
+			AT91_SMC_NRDCYCLE_(read_cycle));
+
+	return;
+}
+
+static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct at91_ide_info *info = ap->host->private_data;
+	struct ata_timing timing;
+	int ret;
+
+	/* Compute ATA timing and set it to SMC */
+	ret = ata_timing_compute(adev, adev->pio_mode, &timing, 1000, 0);
+	if (ret) {
+		dev_warn(ap->dev, "Failed to compute ATA timing %d, \
+				set PIO_0 timing\n", ret);
+		set_smc_timing(ap->dev, info, &initial_timing);
+	} else {
+		set_smc_timing(ap->dev, info, &timing);
+	}
+
+	/* Setup SMC mode */
+	set_smc_mode(info);
+
+	return;
+}
+
+static unsigned int pata_at91_data_xfer_noirq(struct ata_device *dev,
+		unsigned char *buf, unsigned int buflen, int rw)
+{
+	struct at91_ide_info *info = dev->link->ap->host->private_data;
+	unsigned int consumed;
+	unsigned long flags;
+	unsigned int mode;
+
+	local_irq_save(flags);
+	mode = at91_sys_read(AT91_SMC_MODE(info->cs));
+
+	/* set 16bit mode before writing data */
+	at91_sys_write(AT91_SMC_MODE(info->cs),
+			(mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_16);
+
+	consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
+
+	/* restore 8bit mode after data is written */
+	at91_sys_write(AT91_SMC_MODE(info->cs),
+			(mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_8);
+
+	local_irq_restore(flags);
+	return consumed;
+}
+
+static struct scsi_host_template pata_at91_sht = {
+	ATA_PIO_SHT(DRV_NAME),
+};
+
+static struct ata_port_operations pata_at91_port_ops = {
+	.inherits	= &ata_sff_port_ops,
+
+	.sff_data_xfer	= pata_at91_data_xfer_noirq,
+	.set_piomode	= pata_at91_set_piomode,
+	.cable_detect	= ata_cable_40wire,
+	.port_start	= ATA_OP_NULL,
+};
+
+static int __devinit pata_at91_probe(struct platform_device *pdev)
+{
+	struct at91_cf_data *board = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct at91_ide_info *info;
+	struct resource *mem_res;
+	struct ata_host *host;
+	struct ata_port *ap;
+
+	int irq_flags = 0;
+	int irq = 0;
+	int ret;
+
+	/*  get platform resources: IO/CTL memories and irq/rst pins */
+
+	if (pdev->num_resources != 1) {
+		dev_err(&pdev->dev, "invalid number of resources\n");
+		return -EINVAL;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!mem_res) {
+		dev_err(dev, "failed to get mem resource\n");
+		return -EINVAL;
+	}
+
+	irq = board->irq_pin;
+
+	/* init ata host */
+
+	host = ata_host_alloc(dev, 1);
+
+	if (!host)
+		return -ENOMEM;
+
+	ap = host->ports[0];
+	ap->ops = &pata_at91_port_ops;
+	ap->flags |= ATA_FLAG_SLAVE_POSS;
+	ap->pio_mask = ATA_PIO4;
+
+	if (!irq) {
+		ap->flags |= ATA_FLAG_PIO_POLLING;
+		ata_port_desc(ap, "no IRQ, using PIO polling");
+	}
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+
+	if (!info) {
+		dev_err(dev, "failed to allocate memory for private data\n");
+		return -ENOMEM;
+	}
+
+	info->mck = clk_get(NULL, "mck");
+
+	if (IS_ERR(info->mck)) {
+		dev_err(dev, "failed to get access to mck clock\n");
+		return -ENODEV;
+	}
+
+	info->cs    = board->chipselect;
+	info->mode  = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
+		AT91_SMC_EXNWMODE_READY | AT91_SMC_BAT_SELECT |
+		AT91_SMC_DBW_8 | AT91_SMC_TDF_(0);
+
+	info->ide_addr = devm_ioremap(dev,
+			mem_res->start + CF_IDE_OFFSET, CF_IDE_RES_SIZE);
+
+	if (!info->ide_addr) {
+		dev_err(dev, "failed to map IO base\n");
+		ret = -ENOMEM;
+		goto err_put;
+	}
+
+	info->alt_addr = devm_ioremap(dev,
+			mem_res->start + CF_ALT_IDE_OFFSET, CF_IDE_RES_SIZE);
+
+	if (!info->alt_addr) {
+		dev_err(dev, "failed to map CTL base\n");
+		ret = -ENOMEM;
+		goto err_put;
+	}
+
+	ap->ioaddr.cmd_addr = info->ide_addr;
+	ap->ioaddr.ctl_addr = info->alt_addr + 0x06;
+	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
+
+	ata_sff_std_ports(&ap->ioaddr);
+
+	ata_port_desc(ap, "mmio cmd 0x%llx ctl 0x%llx",
+			(unsigned long long)mem_res->start + CF_IDE_OFFSET,
+			(unsigned long long)mem_res->start + CF_ALT_IDE_OFFSET);
+
+	host->private_data = info;
+
+	return ata_host_activate(host, irq ? gpio_to_irq(irq) : 0,
+			irq ? ata_sff_interrupt : NULL,
+			irq_flags, &pata_at91_sht);
+
+err_put:
+	clk_put(info->mck);
+	return ret;
+}
+
+static int __devexit pata_at91_remove(struct platform_device *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct at91_ide_info *info;
+
+	if (!host)
+		return 0;
+	info = host->private_data;
+
+	ata_host_detach(host);
+
+	if (!info)
+		return 0;
+
+	clk_put(info->mck);
+
+	return 0;
+}
+
+static struct platform_driver pata_at91_driver = {
+	.probe		= pata_at91_probe,
+	.remove		= __devexit_p(pata_at91_remove),
+	.driver 	= {
+		.name		= DRV_NAME,
+		.owner		= THIS_MODULE,
+	},
+};
+
+static int __init pata_at91_init(void)
+{
+	return platform_driver_register(&pata_at91_driver);
+}
+
+static void __exit pata_at91_exit(void)
+{
+	platform_driver_unregister(&pata_at91_driver);
+}
+
+
+module_init(pata_at91_init);
+module_exit(pata_at91_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for CF in True IDE mode on AT91SAM9260 SoC");
+MODULE_AUTHOR("Matyukevich Sergey");
+MODULE_VERSION(DRV_VERSION);
+
diff -druN linux-libre-2.6.30-gnu/drivers/ata/pata_atiixp.c linux-libre-2.6.31-gnu/drivers/ata/pata_atiixp.c
--- linux-libre-2.6.30-gnu/drivers/ata/pata_atiixp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/pata_atiixp.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,7 @@
 /*
  * pata_atiixp.c 	- ATI PATA for new ATA layer
  *			  (C) 2005 Red Hat Inc
+ *			  (C) 2009 Bartlomiej Zolnierkiewicz
  *
  * Based on
  *
@@ -61,20 +62,19 @@
 
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	int dn = 2 * ap->port_no + adev->devno;
-
-	/* Check this is correct - the order is odd in both drivers */
 	int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
-	u16 pio_mode_data, pio_timing_data;
+	u32 pio_timing_data;
+	u16 pio_mode_data;
 
 	pci_read_config_word(pdev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
 	pio_mode_data &= ~(0x7 << (4 * dn));
 	pio_mode_data |= pio << (4 * dn);
 	pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
 
-	pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+	pci_read_config_dword(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
 	pio_timing_data &= ~(0xFF << timing_shift);
 	pio_timing_data |= (pio_timings[pio] << timing_shift);
-	pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+	pci_write_config_dword(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
 }
 
 /**
@@ -119,16 +119,17 @@
 		udma_mode_data |= dma << (4 * dn);
 		pci_write_config_word(pdev, ATIIXP_IDE_UDMA_MODE, udma_mode_data);
 	} else {
-		u16 mwdma_timing_data;
-		/* Check this is correct - the order is odd in both drivers */
 		int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
+		u32 mwdma_timing_data;
 
 		dma -= XFER_MW_DMA_0;
 
-		pci_read_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, &mwdma_timing_data);
+		pci_read_config_dword(pdev, ATIIXP_IDE_MWDMA_TIMING,
+				      &mwdma_timing_data);
 		mwdma_timing_data &= ~(0xFF << timing_shift);
 		mwdma_timing_data |= (mwdma_timings[dma] << timing_shift);
-		pci_write_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, mwdma_timing_data);
+		pci_write_config_dword(pdev, ATIIXP_IDE_MWDMA_TIMING,
+				       mwdma_timing_data);
 	}
 	/*
 	 *	We must now look at the PIO mode situation. We may need to
diff -druN linux-libre-2.6.30-gnu/drivers/ata/pata_mpc52xx.c linux-libre-2.6.31-gnu/drivers/ata/pata_mpc52xx.c
--- linux-libre-2.6.30-gnu/drivers/ata/pata_mpc52xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/pata_mpc52xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -694,7 +694,7 @@
 	struct bcom_task *dmatsk = NULL;
 
 	/* Get ipb frequency */
-	ipb_freq = mpc52xx_find_ipb_freq(op->node);
+	ipb_freq = mpc5xxx_get_bus_frequency(op->node);
 	if (!ipb_freq) {
 		dev_err(&op->dev, "could not determine IPB bus frequency\n");
 		return -ENODEV;
diff -druN linux-libre-2.6.30-gnu/drivers/ata/pata_octeon_cf.c linux-libre-2.6.31-gnu/drivers/ata/pata_octeon_cf.c
--- linux-libre-2.6.30-gnu/drivers/ata/pata_octeon_cf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/pata_octeon_cf.c	2009-09-09 18:13:59.000000000 -0400
@@ -653,7 +653,8 @@
 
 		ap = host->ports[i];
 		ocd = ap->dev->platform_data;
-		if (!ap || (ap->flags & ATA_FLAG_DISABLED))
+
+		if (ap->flags & ATA_FLAG_DISABLED)
 			continue;
 
 		ocd = ap->dev->platform_data;
diff -druN linux-libre-2.6.30-gnu/drivers/ata/pata_palmld.c linux-libre-2.6.31-gnu/drivers/ata/pata_palmld.c
--- linux-libre-2.6.30-gnu/drivers/ata/pata_palmld.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/ata/pata_palmld.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,150 @@
+/*
+ * drivers/ata/pata_palmld.c
+ *
+ * Driver for IDE channel in Palm LifeDrive
+ *
+ * Based on research of:
+ *		Alex Osborne <ato@meshy.org>
+ *
+ * Rewrite for mainline:
+ *		Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Rewritten version based on pata_ixp4xx_cf.c:
+ * ixp4xx PATA/Compact Flash driver
+ * Copyright (C) 2006-07 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/libata.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <scsi/scsi_host.h>
+#include <mach/palmld.h>
+
+#define DRV_NAME "pata_palmld"
+
+static struct scsi_host_template palmld_sht = {
+	ATA_PIO_SHT(DRV_NAME),
+};
+
+static struct ata_port_operations palmld_port_ops = {
+	.inherits		= &ata_sff_port_ops,
+	.sff_data_xfer		= ata_sff_data_xfer_noirq,
+	.cable_detect		= ata_cable_40wire,
+};
+
+static __devinit int palmld_pata_probe(struct platform_device *pdev)
+{
+	struct ata_host *host;
+	struct ata_port *ap;
+	void __iomem *mem;
+	int ret;
+
+	/* allocate host */
+	host = ata_host_alloc(&pdev->dev, 1);
+	if (!host)
+		return -ENOMEM;
+
+	/* remap drive's physical memory address */
+	mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000);
+	if (!mem)
+		return -ENOMEM;
+
+	/* request and activate power GPIO, IRQ GPIO */
+	ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR");
+	if (ret)
+		goto err1;
+	ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_PWEN, 1);
+	if (ret)
+		goto err2;
+
+	ret = gpio_request(GPIO_NR_PALMLD_IDE_RESET, "HDD RST");
+	if (ret)
+		goto err2;
+	ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_RESET, 0);
+	if (ret)
+		goto err3;
+
+	/* reset the drive */
+	gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 0);
+	msleep(30);
+	gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 1);
+	msleep(30);
+
+	/* setup the ata port */
+	ap = host->ports[0];
+	ap->ops	= &palmld_port_ops;
+	ap->pio_mask = ATA_PIO4;
+	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_PIO_POLLING;
+
+	/* memory mapping voodoo */
+	ap->ioaddr.cmd_addr = mem + 0x10;
+	ap->ioaddr.altstatus_addr = mem + 0xe;
+	ap->ioaddr.ctl_addr = mem + 0xe;
+
+	/* start the port */
+	ata_sff_std_ports(&ap->ioaddr);
+
+	/* activate host */
+	return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING,
+					&palmld_sht);
+
+err3:
+	gpio_free(GPIO_NR_PALMLD_IDE_RESET);
+err2:
+	gpio_free(GPIO_NR_PALMLD_IDE_PWEN);
+err1:
+	return ret;
+}
+
+static __devexit int palmld_pata_remove(struct platform_device *dev)
+{
+	struct ata_host *host = platform_get_drvdata(dev);
+
+	ata_host_detach(host);
+
+	/* power down the HDD */
+	gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0);
+
+	gpio_free(GPIO_NR_PALMLD_IDE_RESET);
+	gpio_free(GPIO_NR_PALMLD_IDE_PWEN);
+
+	return 0;
+}
+
+static struct platform_driver palmld_pata_platform_driver = {
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+	},
+	.probe		= palmld_pata_probe,
+	.remove		= __devexit_p(palmld_pata_remove),
+};
+
+static int __init palmld_pata_init(void)
+{
+	return platform_driver_register(&palmld_pata_platform_driver);
+}
+
+static void __exit palmld_pata_exit(void)
+{
+	platform_driver_unregister(&palmld_pata_platform_driver);
+}
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PalmLD PATA driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+
+module_init(palmld_pata_init);
+module_exit(palmld_pata_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/ata/pata_pcmcia.c linux-libre-2.6.31-gnu/drivers/ata/pata_pcmcia.c
--- linux-libre-2.6.30-gnu/drivers/ata/pata_pcmcia.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/pata_pcmcia.c	2009-09-09 18:13:59.000000000 -0400
@@ -411,6 +411,7 @@
 	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
 	PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
 	PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
+	PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
 	PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
 	PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
 	PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
diff -druN linux-libre-2.6.30-gnu/drivers/ata/sata_fsl.c linux-libre-2.6.31-gnu/drivers/ata/sata_fsl.c
--- linux-libre-2.6.30-gnu/drivers/ata/sata_fsl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/sata_fsl.c	2009-09-09 18:13:59.000000000 -0400
@@ -1378,6 +1378,37 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int sata_fsl_suspend(struct of_device *op, pm_message_t state)
+{
+	struct ata_host *host = dev_get_drvdata(&op->dev);
+	return ata_host_suspend(host, state);
+}
+
+static int sata_fsl_resume(struct of_device *op)
+{
+	struct ata_host *host = dev_get_drvdata(&op->dev);
+	struct sata_fsl_host_priv *host_priv = host->private_data;
+	int ret;
+	void __iomem *hcr_base = host_priv->hcr_base;
+	struct ata_port *ap = host->ports[0];
+	struct sata_fsl_port_priv *pp = ap->private_data;
+
+	ret = sata_fsl_init_controller(host);
+	if (ret) {
+		dev_printk(KERN_ERR, &op->dev,
+			"Error initialize hardware\n");
+		return ret;
+	}
+
+	/* Recovery the CHBA register in host controller cmd register set */
+	iowrite32(pp->cmdslot_paddr & 0xffffffff, hcr_base + CHBA);
+
+	ata_host_resume(host);
+	return 0;
+}
+#endif
+
 static struct of_device_id fsl_sata_match[] = {
 	{
 		.compatible = "fsl,pq-sata",
@@ -1392,6 +1423,10 @@
 	.match_table	= fsl_sata_match,
 	.probe		= sata_fsl_probe,
 	.remove		= sata_fsl_remove,
+#ifdef CONFIG_PM
+	.suspend	= sata_fsl_suspend,
+	.resume		= sata_fsl_resume,
+#endif
 };
 
 static int __init sata_fsl_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/ata/sata_mv.c linux-libre-2.6.31-gnu/drivers/ata/sata_mv.c
--- linux-libre-2.6.30-gnu/drivers/ata/sata_mv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/sata_mv.c	2009-09-09 18:13:59.000000000 -0400
@@ -2514,7 +2514,7 @@
 	char *when = "idle";
 
 	ata_ehi_clear_desc(ehi);
-	if (!ap || (ap->flags & ATA_FLAG_DISABLED)) {
+	if (ap->flags & ATA_FLAG_DISABLED) {
 		when = "disabled";
 	} else if (edma_was_enabled) {
 		when = "EDMA enabled";
diff -druN linux-libre-2.6.30-gnu/drivers/ata/sata_nv.c linux-libre-2.6.31-gnu/drivers/ata/sata_nv.c
--- linux-libre-2.6.30-gnu/drivers/ata/sata_nv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/sata_nv.c	2009-09-09 18:13:59.000000000 -0400
@@ -305,8 +305,8 @@
 static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
 static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
 
-static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
-				   unsigned long deadline);
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
+			unsigned long deadline);
 static void nv_nf2_freeze(struct ata_port *ap);
 static void nv_nf2_thaw(struct ata_port *ap);
 static void nv_ck804_freeze(struct ata_port *ap);
@@ -406,49 +406,82 @@
 	.slave_configure	= nv_swncq_slave_config,
 };
 
-static struct ata_port_operations nv_common_ops = {
+/*
+ * NV SATA controllers have various different problems with hardreset
+ * protocol depending on the specific controller and device.
+ *
+ * GENERIC:
+ *
+ *  bko11195 reports that link doesn't come online after hardreset on
+ *  generic nv's and there have been several other similar reports on
+ *  linux-ide.
+ *
+ *  bko12351#c23 reports that warmplug on MCP61 doesn't work with
+ *  softreset.
+ *
+ * NF2/3:
+ *
+ *  bko3352 reports nf2/3 controllers can't determine device signature
+ *  reliably after hardreset.  The following thread reports detection
+ *  failure on cold boot with the standard debouncing timing.
+ *
+ *  http://thread.gmane.org/gmane.linux.ide/34098
+ *
+ *  bko12176 reports that hardreset fails to bring up the link during
+ *  boot on nf2.
+ *
+ * CK804:
+ *
+ *  For initial probing after boot and hot plugging, hardreset mostly
+ *  works fine on CK804 but curiously, reprobing on the initial port
+ *  by rescanning or rmmod/insmod fails to acquire the initial D2H Reg
+ *  FIS in somewhat undeterministic way.
+ *
+ * SWNCQ:
+ *
+ *  bko12351 reports that when SWNCQ is enabled, for hotplug to work,
+ *  hardreset should be used and hardreset can't report proper
+ *  signature, which suggests that mcp5x is closer to nf2 as long as
+ *  reset quirkiness is concerned.
+ *
+ *  bko12703 reports that boot probing fails for intel SSD with
+ *  hardreset.  Link fails to come online.  Softreset works fine.
+ *
+ * The failures are varied but the following patterns seem true for
+ * all flavors.
+ *
+ * - Softreset during boot always works.
+ *
+ * - Hardreset during boot sometimes fails to bring up the link on
+ *   certain comibnations and device signature acquisition is
+ *   unreliable.
+ *
+ * - Hardreset is often necessary after hotplug.
+ *
+ * So, preferring softreset for boot probing and error handling (as
+ * hardreset might bring down the link) but using hardreset for
+ * post-boot probing should work around the above issues in most
+ * cases.  Define nv_hardreset() which only kicks in for post-boot
+ * probing and use it for all variants.
+ */
+static struct ata_port_operations nv_generic_ops = {
 	.inherits		= &ata_bmdma_port_ops,
 	.lost_interrupt		= ATA_OP_NULL,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
+	.hardreset		= nv_hardreset,
 };
 
-/* OSDL bz11195 reports that link doesn't come online after hardreset
- * on generic nv's and there have been several other similar reports
- * on linux-ide.  Disable hardreset for generic nv's.
- */
-static struct ata_port_operations nv_generic_ops = {
-	.inherits		= &nv_common_ops,
-	.hardreset		= ATA_OP_NULL,
-};
-
-/* nf2 is ripe with hardreset related problems.
- *
- * kernel bz#3352 reports nf2/3 controllers can't determine device
- * signature reliably.  The following thread reports detection failure
- * on cold boot with the standard debouncing timing.
- *
- * http://thread.gmane.org/gmane.linux.ide/34098
- *
- * And bz#12176 reports that hardreset simply doesn't work on nf2.
- * Give up on it and just don't do hardreset.
- */
 static struct ata_port_operations nv_nf2_ops = {
 	.inherits		= &nv_generic_ops,
 	.freeze			= nv_nf2_freeze,
 	.thaw			= nv_nf2_thaw,
 };
 
-/* For initial probing after boot and hot plugging, hardreset mostly
- * works fine on CK804 but curiously, reprobing on the initial port by
- * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
- * in somewhat undeterministic way.  Use noclassify hardreset.
- */
 static struct ata_port_operations nv_ck804_ops = {
-	.inherits		= &nv_common_ops,
+	.inherits		= &nv_generic_ops,
 	.freeze			= nv_ck804_freeze,
 	.thaw			= nv_ck804_thaw,
-	.hardreset		= nv_noclassify_hardreset,
 	.host_stop		= nv_ck804_host_stop,
 };
 
@@ -476,19 +509,8 @@
 	.host_stop		= nv_adma_host_stop,
 };
 
-/* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to
- * work, hardreset should be used and hardreset can't report proper
- * signature, which suggests that mcp5x is closer to nf2 as long as
- * reset quirkiness is concerned.  Define separate ops for mcp5x with
- * nv_noclassify_hardreset().
- */
-static struct ata_port_operations nv_mcp5x_ops = {
-	.inherits		= &nv_common_ops,
-	.hardreset		= nv_noclassify_hardreset,
-};
-
 static struct ata_port_operations nv_swncq_ops = {
-	.inherits		= &nv_mcp5x_ops,
+	.inherits		= &nv_generic_ops,
 
 	.qc_defer		= ata_std_qc_defer,
 	.qc_prep		= nv_swncq_qc_prep,
@@ -557,7 +579,7 @@
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
-		.port_ops	= &nv_mcp5x_ops,
+		.port_ops	= &nv_generic_ops,
 		.private_data	= NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
 	},
 	/* SWNCQ */
@@ -580,6 +602,7 @@
 
 static int adma_enabled;
 static int swncq_enabled = 1;
+static int msi_enabled;
 
 static void nv_adma_register_mode(struct ata_port *ap)
 {
@@ -1559,15 +1582,24 @@
 	return 0;
 }
 
-static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
-				   unsigned long deadline)
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
+			unsigned long deadline)
 {
-	bool online;
-	int rc;
+	struct ata_eh_context *ehc = &link->eh_context;
 
-	rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
-				 &online, NULL);
-	return online ? -EAGAIN : rc;
+	/* Do hardreset iff it's post-boot probing, please read the
+	 * comment above port ops for details.
+	 */
+	if (!(link->ap->pflags & ATA_PFLAG_LOADING) &&
+	    !ata_dev_enabled(link->device))
+		sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
+				    NULL, NULL);
+	else if (!(ehc->i.flags & ATA_EHI_QUIET))
+		ata_link_printk(link, KERN_INFO,
+				"nv: skipping hardreset on occupied port\n");
+
+	/* device signature acquisition is unreliable */
+	return -EAGAIN;
 }
 
 static void nv_nf2_freeze(struct ata_port *ap)
@@ -2428,6 +2460,11 @@
 	} else if (type == SWNCQ)
 		nv_swncq_host_init(host);
 
+	if (msi_enabled) {
+		dev_printk(KERN_NOTICE, &pdev->dev, "Using MSI\n");
+		pci_enable_msi(pdev);
+	}
+
 	pci_set_master(pdev);
 	return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
 				 IRQF_SHARED, ipriv->sht);
@@ -2527,4 +2564,6 @@
 MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
 module_param_named(swncq, swncq_enabled, bool, 0444);
 MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
+module_param_named(msi, msi_enabled, bool, 0444);
+MODULE_PARM_DESC(msi, "Enable use of MSI (Default: false)");
 
diff -druN linux-libre-2.6.30-gnu/drivers/ata/sata_sil.c linux-libre-2.6.31-gnu/drivers/ata/sata_sil.c
--- linux-libre-2.6.30-gnu/drivers/ata/sata_sil.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/sata_sil.c	2009-09-09 18:13:59.000000000 -0400
@@ -183,7 +183,7 @@
 };
 
 static struct ata_port_operations sil_ops = {
-	.inherits		= &ata_bmdma_port_ops,
+	.inherits		= &ata_bmdma32_port_ops,
 	.dev_config		= sil_dev_config,
 	.set_mode		= sil_set_mode,
 	.bmdma_setup            = sil_bmdma_setup,
@@ -532,7 +532,7 @@
 		struct ata_port *ap = host->ports[i];
 		u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
 
-		if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
+		if (unlikely(ap->flags & ATA_FLAG_DISABLED))
 			continue;
 
 		/* turn off SATA_IRQ if not supported */
diff -druN linux-libre-2.6.30-gnu/drivers/ata/sata_sx4.c linux-libre-2.6.31-gnu/drivers/ata/sata_sx4.c
--- linux-libre-2.6.30-gnu/drivers/ata/sata_sx4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ata/sata_sx4.c	2009-09-09 18:13:59.000000000 -0400
@@ -193,6 +193,7 @@
 					  PDC_TIMER_MASK_INT,
 };
 
+#define ECC_ERASE_BUF_SZ (128 * 1024)
 
 struct pdc_port_priv {
 	u8			dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
@@ -1280,7 +1281,6 @@
 {
 	int speed, size, length;
 	u32 addr, spd0, pci_status;
-	u32 tmp = 0;
 	u32 time_period = 0;
 	u32 tcount = 0;
 	u32 ticks = 0;
@@ -1395,14 +1395,17 @@
 	pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
 			  PDC_DIMM_SPD_TYPE, &spd0);
 	if (spd0 == 0x02) {
+		void *buf;
 		VPRINTK("Start ECC initialization\n");
 		addr = 0;
 		length = size * 1024 * 1024;
+		buf = kzalloc(ECC_ERASE_BUF_SZ, GFP_KERNEL);
 		while (addr < length) {
-			pdc20621_put_to_dimm(host, (void *) &tmp, addr,
-					     sizeof(u32));
-			addr += sizeof(u32);
+			pdc20621_put_to_dimm(host, buf, addr,
+					     ECC_ERASE_BUF_SZ);
+			addr += ECC_ERASE_BUF_SZ;
 		}
+		kfree(buf);
 		VPRINTK("Finish ECC initialization\n");
 	}
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/base/bus.c linux-libre-2.6.31-gnu/drivers/base/bus.c
--- linux-libre-2.6.30-gnu/drivers/base/bus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/bus.c	2009-09-09 18:13:59.000000000 -0400
@@ -279,7 +279,7 @@
  *
  * NOTE: The device that returns a non-zero value is not retained
  * in any way, nor is its refcount incremented. If the caller needs
- * to retain this data, it should do, and increment the reference
+ * to retain this data, it should do so, and increment the reference
  * count in the supplied callback.
  */
 int bus_for_each_dev(struct bus_type *bus, struct device *start,
diff -druN linux-libre-2.6.30-gnu/drivers/base/core.c linux-libre-2.6.31-gnu/drivers/base/core.c
--- linux-libre-2.6.30-gnu/drivers/base/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/kallsyms.h>
 #include <linux/semaphore.h>
 #include <linux/mutex.h>
+#include <linux/async.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -161,10 +162,18 @@
 	struct device *dev = to_dev(kobj);
 	int retval = 0;
 
-	/* add the major/minor if present */
+	/* add device node properties if present */
 	if (MAJOR(dev->devt)) {
+		const char *tmp;
+		const char *name;
+
 		add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
 		add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
+		name = device_get_nodename(dev, &tmp);
+		if (name) {
+			add_uevent_var(env, "DEVNAME=%s", name);
+			kfree(tmp);
+		}
 	}
 
 	if (dev->type && dev->type->name)
@@ -874,7 +883,7 @@
 	 * the name, and force the use of dev_name()
 	 */
 	if (dev->init_name) {
-		dev_set_name(dev, dev->init_name);
+		dev_set_name(dev, "%s", dev->init_name);
 		dev->init_name = NULL;
 	}
 
@@ -1128,6 +1137,47 @@
 }
 
 /**
+ * device_get_nodename - path of device node file
+ * @dev: device
+ * @tmp: possibly allocated string
+ *
+ * Return the relative path of a possible device node.
+ * Non-default names may need to allocate a memory to compose
+ * a name. This memory is returned in tmp and needs to be
+ * freed by the caller.
+ */
+const char *device_get_nodename(struct device *dev, const char **tmp)
+{
+	char *s;
+
+	*tmp = NULL;
+
+	/* the device type may provide a specific name */
+	if (dev->type && dev->type->nodename)
+		*tmp = dev->type->nodename(dev);
+	if (*tmp)
+		return *tmp;
+
+	/* the class may provide a specific name */
+	if (dev->class && dev->class->nodename)
+		*tmp = dev->class->nodename(dev);
+	if (*tmp)
+		return *tmp;
+
+	/* return name without allocation, tmp == NULL */
+	if (strchr(dev_name(dev), '!') == NULL)
+		return dev_name(dev);
+
+	/* replace '!' in the name with '/' */
+	*tmp = kstrdup(dev_name(dev), GFP_KERNEL);
+	if (!*tmp)
+		return NULL;
+	while ((s = strchr(*tmp, '!')))
+		s[0] = '/';
+	return *tmp;
+}
+
+/**
  * device_for_each_child - device child iterator.
  * @parent: parent struct device.
  * @data: data for the callback.
@@ -1271,7 +1321,7 @@
 	if (!root)
 		return ERR_PTR(err);
 
-	err = dev_set_name(&root->dev, name);
+	err = dev_set_name(&root->dev, "%s", name);
 	if (err) {
 		kfree(root);
 		return ERR_PTR(err);
@@ -1665,4 +1715,5 @@
 	kobject_put(sysfs_dev_char_kobj);
 	kobject_put(sysfs_dev_block_kobj);
 	kobject_put(dev_kobj);
+	async_synchronize_full();
 }
diff -druN linux-libre-2.6.30-gnu/drivers/base/dd.c linux-libre-2.6.31-gnu/drivers/base/dd.c
--- linux-libre-2.6.30-gnu/drivers/base/dd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/dd.c	2009-09-09 18:13:59.000000000 -0400
@@ -226,7 +226,7 @@
  * pair is found, break out and return.
  *
  * Returns 1 if the device was bound to a driver;
- * 0 if no matching device was found;
+ * 0 if no matching driver was found;
  * -ENODEV if the device is not registered.
  *
  * When called for a USB interface, @dev->parent->sem must be held.
@@ -320,6 +320,10 @@
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);
+		if (dev->bus)
+			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+						     BUS_NOTIFY_UNBOUND_DRIVER,
+						     dev);
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/base/devres.c linux-libre-2.6.31-gnu/drivers/base/devres.c
--- linux-libre-2.6.30-gnu/drivers/base/devres.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/devres.c	2009-09-09 18:13:59.000000000 -0400
@@ -428,6 +428,9 @@
 {
 	unsigned long flags;
 
+	/* Looks like an uninitialized device structure */
+	if (WARN_ON(dev->devres_head.next == NULL))
+		return -ENODEV;
 	spin_lock_irqsave(&dev->devres_lock, flags);
 	return release_nodes(dev, dev->devres_head.next, &dev->devres_head,
 			     flags);
diff -druN linux-libre-2.6.30-gnu/drivers/base/firmware_class.c linux-libre-2.6.31-gnu/drivers/base/firmware_class.c
--- linux-libre-2.6.30-gnu/drivers/base/firmware_class.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/firmware_class.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 #include <linux/bitops.h>
 #include <linux/mutex.h>
 #include <linux/kthread.h>
-
+#include <linux/highmem.h>
 #include <linux/firmware.h>
 #include "base.h"
 
@@ -40,12 +40,15 @@
 static DEFINE_MUTEX(fw_lock);
 
 struct firmware_priv {
-	char fw_id[FIRMWARE_NAME_MAX];
+	char *fw_id;
 	struct completion completion;
 	struct bin_attribute attr_data;
 	struct firmware *fw;
 	unsigned long status;
-	int alloc_size;
+	struct page **pages;
+	int nr_pages;
+	int page_array_size;
+	const char *vdata;
 	struct timer_list timeout;
 };
 
@@ -122,6 +125,10 @@
 	return sprintf(buf, "%d\n", loading);
 }
 
+/* Some architectures don't have PAGE_KERNEL_RO */
+#ifndef PAGE_KERNEL_RO
+#define PAGE_KERNEL_RO PAGE_KERNEL
+#endif
 /**
  * firmware_loading_store - set value in the 'loading' control file
  * @dev: device pointer
@@ -141,6 +148,7 @@
 {
 	struct firmware_priv *fw_priv = dev_get_drvdata(dev);
 	int loading = simple_strtol(buf, NULL, 10);
+	int i;
 
 	switch (loading) {
 	case 1:
@@ -151,13 +159,29 @@
 		}
 		vfree(fw_priv->fw->data);
 		fw_priv->fw->data = NULL;
+		for (i = 0; i < fw_priv->nr_pages; i++)
+			__free_page(fw_priv->pages[i]);
+		kfree(fw_priv->pages);
+		fw_priv->pages = NULL;
+		fw_priv->page_array_size = 0;
+		fw_priv->nr_pages = 0;
 		fw_priv->fw->size = 0;
-		fw_priv->alloc_size = 0;
 		set_bit(FW_STATUS_LOADING, &fw_priv->status);
 		mutex_unlock(&fw_lock);
 		break;
 	case 0:
 		if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
+			vfree(fw_priv->fw->data);
+			fw_priv->fw->data = vmap(fw_priv->pages,
+						 fw_priv->nr_pages,
+						 0, PAGE_KERNEL_RO);
+			if (!fw_priv->fw->data) {
+				dev_err(dev, "%s: vmap() failed\n", __func__);
+				goto err;
+			}
+			/* Pages will be freed by vfree() */
+			fw_priv->page_array_size = 0;
+			fw_priv->nr_pages = 0;
 			complete(&fw_priv->completion);
 			clear_bit(FW_STATUS_LOADING, &fw_priv->status);
 			break;
@@ -167,6 +191,7 @@
 		dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
 		/* fallthrough */
 	case -1:
+	err:
 		fw_load_abort(fw_priv);
 		break;
 	}
@@ -191,8 +216,30 @@
 		ret_count = -ENODEV;
 		goto out;
 	}
-	ret_count = memory_read_from_buffer(buffer, count, &offset,
-						fw->data, fw->size);
+	if (offset > fw->size) {
+		ret_count = 0;
+		goto out;
+	}
+	if (count > fw->size - offset)
+		count = fw->size - offset;
+
+	ret_count = count;
+
+	while (count) {
+		void *page_data;
+		int page_nr = offset >> PAGE_SHIFT;
+		int page_ofs = offset & (PAGE_SIZE-1);
+		int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
+
+		page_data = kmap(fw_priv->pages[page_nr]);
+
+		memcpy(buffer, page_data + page_ofs, page_cnt);
+
+		kunmap(fw_priv->pages[page_nr]);
+		buffer += page_cnt;
+		offset += page_cnt;
+		count -= page_cnt;
+	}
 out:
 	mutex_unlock(&fw_lock);
 	return ret_count;
@@ -201,27 +248,39 @@
 static int
 fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 {
-	u8 *new_data;
-	int new_size = fw_priv->alloc_size;
+	int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
 
-	if (min_size <= fw_priv->alloc_size)
-		return 0;
+	/* If the array of pages is too small, grow it... */
+	if (fw_priv->page_array_size < pages_needed) {
+		int new_array_size = max(pages_needed,
+					 fw_priv->page_array_size * 2);
+		struct page **new_pages;
 
-	new_size = ALIGN(min_size, PAGE_SIZE);
-	new_data = vmalloc(new_size);
-	if (!new_data) {
-		printk(KERN_ERR "%s: unable to alloc buffer\n", __func__);
-		/* Make sure that we don't keep incomplete data */
-		fw_load_abort(fw_priv);
-		return -ENOMEM;
+		new_pages = kmalloc(new_array_size * sizeof(void *),
+				    GFP_KERNEL);
+		if (!new_pages) {
+			fw_load_abort(fw_priv);
+			return -ENOMEM;
+		}
+		memcpy(new_pages, fw_priv->pages,
+		       fw_priv->page_array_size * sizeof(void *));
+		memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
+		       (new_array_size - fw_priv->page_array_size));
+		kfree(fw_priv->pages);
+		fw_priv->pages = new_pages;
+		fw_priv->page_array_size = new_array_size;
 	}
-	fw_priv->alloc_size = new_size;
-	if (fw_priv->fw->data) {
-		memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size);
-		vfree(fw_priv->fw->data);
+
+	while (fw_priv->nr_pages < pages_needed) {
+		fw_priv->pages[fw_priv->nr_pages] =
+			alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+
+		if (!fw_priv->pages[fw_priv->nr_pages]) {
+			fw_load_abort(fw_priv);
+			return -ENOMEM;
+		}
+		fw_priv->nr_pages++;
 	}
-	fw_priv->fw->data = new_data;
-	BUG_ON(min_size > fw_priv->alloc_size);
 	return 0;
 }
 
@@ -258,10 +317,25 @@
 	if (retval)
 		goto out;
 
-	memcpy((u8 *)fw->data + offset, buffer, count);
-
-	fw->size = max_t(size_t, offset + count, fw->size);
 	retval = count;
+
+	while (count) {
+		void *page_data;
+		int page_nr = offset >> PAGE_SHIFT;
+		int page_ofs = offset & (PAGE_SIZE - 1);
+		int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
+
+		page_data = kmap(fw_priv->pages[page_nr]);
+
+		memcpy(page_data + page_ofs, buffer, page_cnt);
+
+		kunmap(fw_priv->pages[page_nr]);
+		buffer += page_cnt;
+		offset += page_cnt;
+		count -= page_cnt;
+	}
+
+	fw->size = max_t(size_t, offset, fw->size);
 out:
 	mutex_unlock(&fw_lock);
 	return retval;
@@ -277,7 +351,12 @@
 static void fw_dev_release(struct device *dev)
 {
 	struct firmware_priv *fw_priv = dev_get_drvdata(dev);
+	int i;
 
+	for (i = 0; i < fw_priv->nr_pages; i++)
+		__free_page(fw_priv->pages[i]);
+	kfree(fw_priv->pages);
+	kfree(fw_priv->fw_id);
 	kfree(fw_priv);
 	kfree(dev);
 
@@ -309,13 +388,19 @@
 
 	init_completion(&fw_priv->completion);
 	fw_priv->attr_data = firmware_attr_data_tmpl;
-	strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
+	fw_priv->fw_id = kstrdup(fw_name, GFP_KERNEL);
+	if (!fw_priv->fw_id) {
+		dev_err(device, "%s: Firmware name allocation failed\n",
+			__func__);
+		retval = -ENOMEM;
+		goto error_kfree;
+	}
 
 	fw_priv->timeout.function = firmware_class_timeout;
 	fw_priv->timeout.data = (u_long) fw_priv;
 	init_timer(&fw_priv->timeout);
 
-	dev_set_name(f_dev, dev_name(device));
+	dev_set_name(f_dev, "%s", dev_name(device));
 	f_dev->parent = device;
 	f_dev->class = &firmware_class;
 	dev_set_drvdata(f_dev, fw_priv);
@@ -323,14 +408,15 @@
 	retval = device_register(f_dev);
 	if (retval) {
 		dev_err(device, "%s: device_register failed\n", __func__);
-		goto error_kfree;
+		put_device(f_dev);
+		return retval;
 	}
 	*dev_p = f_dev;
 	return 0;
 
 error_kfree:
-	kfree(fw_priv);
 	kfree(f_dev);
+	kfree(fw_priv);
 	return retval;
 }
 
@@ -538,8 +624,9 @@
  * @cont: function will be called asynchronously when the firmware
  *	request is over.
  *
- *	Asynchronous variant of request_firmware() for contexts where
- *	it is not possible to sleep.
+ *	Asynchronous variant of request_firmware() for user contexts where
+ *	it is not possible to sleep for long time. It can't be called
+ *	in atomic contexts.
  **/
 int
 request_firmware_nowait(
diff -druN linux-libre-2.6.30-gnu/drivers/base/node.c linux-libre-2.6.31-gnu/drivers/base/node.c
--- linux-libre-2.6.30-gnu/drivers/base/node.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/node.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,10 +72,8 @@
 		       "Node %d Inactive(anon): %8lu kB\n"
 		       "Node %d Active(file):   %8lu kB\n"
 		       "Node %d Inactive(file): %8lu kB\n"
-#ifdef CONFIG_UNEVICTABLE_LRU
 		       "Node %d Unevictable:    %8lu kB\n"
 		       "Node %d Mlocked:        %8lu kB\n"
-#endif
 #ifdef CONFIG_HIGHMEM
 		       "Node %d HighTotal:      %8lu kB\n"
 		       "Node %d HighFree:       %8lu kB\n"
@@ -105,10 +103,8 @@
 		       nid, K(node_page_state(nid, NR_INACTIVE_ANON)),
 		       nid, K(node_page_state(nid, NR_ACTIVE_FILE)),
 		       nid, K(node_page_state(nid, NR_INACTIVE_FILE)),
-#ifdef CONFIG_UNEVICTABLE_LRU
 		       nid, K(node_page_state(nid, NR_UNEVICTABLE)),
 		       nid, K(node_page_state(nid, NR_MLOCK)),
-#endif
 #ifdef CONFIG_HIGHMEM
 		       nid, K(i.totalhigh),
 		       nid, K(i.freehigh),
diff -druN linux-libre-2.6.30-gnu/drivers/base/platform.c linux-libre-2.6.31-gnu/drivers/base/platform.c
--- linux-libre-2.6.30-gnu/drivers/base/platform.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -69,7 +69,8 @@
  * @name: resource name
  */
 struct resource *platform_get_resource_byname(struct platform_device *dev,
-					      unsigned int type, char *name)
+					      unsigned int type,
+					      const char *name)
 {
 	int i;
 
@@ -88,7 +89,7 @@
  * @dev: platform device
  * @name: IRQ name
  */
-int platform_get_irq_byname(struct platform_device *dev, char *name)
+int platform_get_irq_byname(struct platform_device *dev, const char *name)
 {
 	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ,
 							  name);
@@ -244,7 +245,7 @@
 	if (pdev->id != -1)
 		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
 	else
-		dev_set_name(&pdev->dev, pdev->name);
+		dev_set_name(&pdev->dev, "%s", pdev->name);
 
 	for (i = 0; i < pdev->num_resources; i++) {
 		struct resource *p, *r = &pdev->resource[i];
@@ -469,22 +470,6 @@
 	drv->shutdown(dev);
 }
 
-static int platform_drv_suspend(struct device *_dev, pm_message_t state)
-{
-	struct platform_driver *drv = to_platform_driver(_dev->driver);
-	struct platform_device *dev = to_platform_device(_dev);
-
-	return drv->suspend(dev, state);
-}
-
-static int platform_drv_resume(struct device *_dev)
-{
-	struct platform_driver *drv = to_platform_driver(_dev->driver);
-	struct platform_device *dev = to_platform_device(_dev);
-
-	return drv->resume(dev);
-}
-
 /**
  * platform_driver_register
  * @drv: platform driver structure
@@ -498,10 +483,7 @@
 		drv->driver.remove = platform_drv_remove;
 	if (drv->shutdown)
 		drv->driver.shutdown = platform_drv_shutdown;
-	if (drv->suspend)
-		drv->driver.suspend = platform_drv_suspend;
-	if (drv->resume)
-		drv->driver.resume = platform_drv_resume;
+
 	return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -633,10 +615,12 @@
 
 static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
 {
+	struct platform_driver *pdrv = to_platform_driver(dev->driver);
+	struct platform_device *pdev = to_platform_device(dev);
 	int ret = 0;
 
-	if (dev->driver && dev->driver->suspend)
-		ret = dev->driver->suspend(dev, mesg);
+	if (dev->driver && pdrv->suspend)
+		ret = pdrv->suspend(pdev, mesg);
 
 	return ret;
 }
@@ -667,10 +651,12 @@
 
 static int platform_legacy_resume(struct device *dev)
 {
+	struct platform_driver *pdrv = to_platform_driver(dev->driver);
+	struct platform_device *pdev = to_platform_device(dev);
 	int ret = 0;
 
-	if (dev->driver && dev->driver->resume)
-		ret = dev->driver->resume(dev);
+	if (dev->driver && pdrv->resume)
+		ret = pdrv->resume(pdev);
 
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/base/power/main.c linux-libre-2.6.31-gnu/drivers/base/power/main.c
--- linux-libre-2.6.30-gnu/drivers/base/power/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/power/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -315,13 +315,13 @@
 /*------------------------- Resume routines -------------------------*/
 
 /**
- *	resume_device_noirq - Power on one device (early resume).
+ *	device_resume_noirq - Power on one device (early resume).
  *	@dev:	Device.
  *	@state: PM transition of the system being carried out.
  *
  *	Must be called with interrupts disabled.
  */
-static int resume_device_noirq(struct device *dev, pm_message_t state)
+static int device_resume_noirq(struct device *dev, pm_message_t state)
 {
 	int error = 0;
 
@@ -334,9 +334,6 @@
 	if (dev->bus->pm) {
 		pm_dev_dbg(dev, state, "EARLY ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
-	} else if (dev->bus->resume_early) {
-		pm_dev_dbg(dev, state, "legacy EARLY ");
-		error = dev->bus->resume_early(dev);
 	}
  End:
 	TRACE_RESUME(error);
@@ -344,16 +341,16 @@
 }
 
 /**
- *	dpm_power_up - Power on all regular (non-sysdev) devices.
+ *	dpm_resume_noirq - Power on all regular (non-sysdev) devices.
  *	@state: PM transition of the system being carried out.
  *
- *	Execute the appropriate "noirq resume" callback for all devices marked
- *	as DPM_OFF_IRQ.
+ *	Call the "noirq" resume handlers for all devices marked as
+ *	DPM_OFF_IRQ and enable device drivers to receive interrupts.
  *
  *	Must be called under dpm_list_mtx.  Device drivers should not receive
  *	interrupts while it's being executed.
  */
-static void dpm_power_up(pm_message_t state)
+void dpm_resume_noirq(pm_message_t state)
 {
 	struct device *dev;
 
@@ -363,33 +360,21 @@
 			int error;
 
 			dev->power.status = DPM_OFF;
-			error = resume_device_noirq(dev, state);
+			error = device_resume_noirq(dev, state);
 			if (error)
 				pm_dev_err(dev, state, " early", error);
 		}
 	mutex_unlock(&dpm_list_mtx);
-}
-
-/**
- *	device_power_up - Turn on all devices that need special attention.
- *	@state: PM transition of the system being carried out.
- *
- *	Call the "early" resume handlers and enable device drivers to receive
- *	interrupts.
- */
-void device_power_up(pm_message_t state)
-{
-	dpm_power_up(state);
 	resume_device_irqs();
 }
-EXPORT_SYMBOL_GPL(device_power_up);
+EXPORT_SYMBOL_GPL(dpm_resume_noirq);
 
 /**
- *	resume_device - Restore state for one device.
+ *	device_resume - Restore state for one device.
  *	@dev:	Device.
  *	@state: PM transition of the system being carried out.
  */
-static int resume_device(struct device *dev, pm_message_t state)
+static int device_resume(struct device *dev, pm_message_t state)
 {
 	int error = 0;
 
@@ -414,9 +399,6 @@
 		if (dev->type->pm) {
 			pm_dev_dbg(dev, state, "type ");
 			error = pm_op(dev, dev->type->pm, state);
-		} else if (dev->type->resume) {
-			pm_dev_dbg(dev, state, "legacy type ");
-			error = dev->type->resume(dev);
 		}
 		if (error)
 			goto End;
@@ -462,7 +444,7 @@
 			dev->power.status = DPM_RESUMING;
 			mutex_unlock(&dpm_list_mtx);
 
-			error = resume_device(dev, state);
+			error = device_resume(dev, state);
 
 			mutex_lock(&dpm_list_mtx);
 			if (error)
@@ -480,11 +462,11 @@
 }
 
 /**
- *	complete_device - Complete a PM transition for given device
+ *	device_complete - Complete a PM transition for given device
  *	@dev:	Device.
  *	@state: PM transition of the system being carried out.
  */
-static void complete_device(struct device *dev, pm_message_t state)
+static void device_complete(struct device *dev, pm_message_t state)
 {
 	down(&dev->sem);
 
@@ -527,7 +509,7 @@
 			dev->power.status = DPM_ON;
 			mutex_unlock(&dpm_list_mtx);
 
-			complete_device(dev, state);
+			device_complete(dev, state);
 
 			mutex_lock(&dpm_list_mtx);
 		}
@@ -540,19 +522,19 @@
 }
 
 /**
- *	device_resume - Restore state of each device in system.
+ *	dpm_resume_end - Restore state of each device in system.
  *	@state: PM transition of the system being carried out.
  *
  *	Resume all the devices, unlock them all, and allow new
  *	devices to be registered once again.
  */
-void device_resume(pm_message_t state)
+void dpm_resume_end(pm_message_t state)
 {
 	might_sleep();
 	dpm_resume(state);
 	dpm_complete(state);
 }
-EXPORT_SYMBOL_GPL(device_resume);
+EXPORT_SYMBOL_GPL(dpm_resume_end);
 
 
 /*------------------------- Suspend routines -------------------------*/
@@ -577,13 +559,13 @@
 }
 
 /**
- *	suspend_device_noirq - Shut down one device (late suspend).
+ *	device_suspend_noirq - Shut down one device (late suspend).
  *	@dev:	Device.
  *	@state: PM transition of the system being carried out.
  *
  *	This is called with interrupts off and only a single CPU running.
  */
-static int suspend_device_noirq(struct device *dev, pm_message_t state)
+static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
 	int error = 0;
 
@@ -593,24 +575,20 @@
 	if (dev->bus->pm) {
 		pm_dev_dbg(dev, state, "LATE ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
-	} else if (dev->bus->suspend_late) {
-		pm_dev_dbg(dev, state, "legacy LATE ");
-		error = dev->bus->suspend_late(dev, state);
-		suspend_report_result(dev->bus->suspend_late, error);
 	}
 	return error;
 }
 
 /**
- *	device_power_down - Shut down special devices.
+ *	dpm_suspend_noirq - Power down all regular (non-sysdev) devices.
  *	@state: PM transition of the system being carried out.
  *
- *	Prevent device drivers from receiving interrupts and call the "late"
+ *	Prevent device drivers from receiving interrupts and call the "noirq"
  *	suspend handlers.
  *
  *	Must be called under dpm_list_mtx.
  */
-int device_power_down(pm_message_t state)
+int dpm_suspend_noirq(pm_message_t state)
 {
 	struct device *dev;
 	int error = 0;
@@ -618,7 +596,7 @@
 	suspend_device_irqs();
 	mutex_lock(&dpm_list_mtx);
 	list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
-		error = suspend_device_noirq(dev, state);
+		error = device_suspend_noirq(dev, state);
 		if (error) {
 			pm_dev_err(dev, state, " late", error);
 			break;
@@ -627,17 +605,17 @@
 	}
 	mutex_unlock(&dpm_list_mtx);
 	if (error)
-		device_power_up(resume_event(state));
+		dpm_resume_noirq(resume_event(state));
 	return error;
 }
-EXPORT_SYMBOL_GPL(device_power_down);
+EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
 
 /**
- *	suspend_device - Save state of one device.
+ *	device_suspend - Save state of one device.
  *	@dev:	Device.
  *	@state: PM transition of the system being carried out.
  */
-static int suspend_device(struct device *dev, pm_message_t state)
+static int device_suspend(struct device *dev, pm_message_t state)
 {
 	int error = 0;
 
@@ -660,10 +638,6 @@
 		if (dev->type->pm) {
 			pm_dev_dbg(dev, state, "type ");
 			error = pm_op(dev, dev->type->pm, state);
-		} else if (dev->type->suspend) {
-			pm_dev_dbg(dev, state, "legacy type ");
-			error = dev->type->suspend(dev, state);
-			suspend_report_result(dev->type->suspend, error);
 		}
 		if (error)
 			goto End;
@@ -704,7 +678,7 @@
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
 
-		error = suspend_device(dev, state);
+		error = device_suspend(dev, state);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
@@ -723,11 +697,11 @@
 }
 
 /**
- *	prepare_device - Execute the ->prepare() callback(s) for given device.
+ *	device_prepare - Execute the ->prepare() callback(s) for given device.
  *	@dev:	Device.
  *	@state: PM transition of the system being carried out.
  */
-static int prepare_device(struct device *dev, pm_message_t state)
+static int device_prepare(struct device *dev, pm_message_t state)
 {
 	int error = 0;
 
@@ -781,13 +755,14 @@
 		dev->power.status = DPM_PREPARING;
 		mutex_unlock(&dpm_list_mtx);
 
-		error = prepare_device(dev, state);
+		error = device_prepare(dev, state);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
 			dev->power.status = DPM_ON;
 			if (error == -EAGAIN) {
 				put_device(dev);
+				error = 0;
 				continue;
 			}
 			printk(KERN_ERR "PM: Failed to prepare device %s "
@@ -807,12 +782,12 @@
 }
 
 /**
- *	device_suspend - Save state and stop all devices in system.
+ *	dpm_suspend_start - Save state and stop all devices in system.
  *	@state: PM transition of the system being carried out.
  *
  *	Prepare and suspend all devices.
  */
-int device_suspend(pm_message_t state)
+int dpm_suspend_start(pm_message_t state)
 {
 	int error;
 
@@ -822,7 +797,7 @@
 		error = dpm_suspend(state);
 	return error;
 }
-EXPORT_SYMBOL_GPL(device_suspend);
+EXPORT_SYMBOL_GPL(dpm_suspend_start);
 
 void __suspend_report_result(const char *function, void *fn, int ret)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/base/sys.c linux-libre-2.6.31-gnu/drivers/base/sys.c
--- linux-libre-2.6.30-gnu/drivers/base/sys.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/base/sys.c	2009-09-09 18:13:59.000000000 -0400
@@ -131,6 +131,8 @@
 
 int sysdev_class_register(struct sysdev_class *cls)
 {
+	int retval;
+
 	pr_debug("Registering sysdev class '%s'\n", cls->name);
 
 	INIT_LIST_HEAD(&cls->drivers);
@@ -138,7 +140,11 @@
 	cls->kset.kobj.parent = &system_kset->kobj;
 	cls->kset.kobj.ktype = &ktype_sysdev_class;
 	cls->kset.kobj.kset = system_kset;
-	kobject_set_name(&cls->kset.kobj, cls->name);
+
+	retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name);
+	if (retval)
+		return retval;
+
 	return kset_register(&cls->kset);
 }
 
@@ -269,9 +275,9 @@
 				drv->add(sysdev);
 		}
 		mutex_unlock(&sysdev_drivers_lock);
+		kobject_uevent(&sysdev->kobj, KOBJ_ADD);
 	}
 
-	kobject_uevent(&sysdev->kobj, KOBJ_ADD);
 	return error;
 }
 
@@ -343,11 +349,15 @@
 	/* First, call the class-specific one */
 	if (cls->resume)
 		cls->resume(dev);
+	WARN_ONCE(!irqs_disabled(),
+		"Interrupts enabled after %pF\n", cls->resume);
 
 	/* Call auxillary drivers next. */
 	list_for_each_entry(drv, &cls->drivers, entry) {
 		if (drv->resume)
 			drv->resume(dev);
+		WARN_ONCE(!irqs_disabled(),
+			"Interrupts enabled after %pF\n", drv->resume);
 	}
 }
 
@@ -377,6 +387,9 @@
 	if (ret)
 		return ret;
 
+	WARN_ONCE(!irqs_disabled(),
+		"Interrupts enabled while suspending system devices\n");
+
 	pr_debug("Suspending System Devices\n");
 
 	list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
@@ -393,6 +406,9 @@
 					if (ret)
 						goto aux_driver;
 				}
+				WARN_ONCE(!irqs_disabled(),
+					"Interrupts enabled after %pF\n",
+					drv->suspend);
 			}
 
 			/* Now call the generic one */
@@ -400,6 +416,9 @@
 				ret = cls->suspend(sysdev, state);
 				if (ret)
 					goto cls_driver;
+				WARN_ONCE(!irqs_disabled(),
+					"Interrupts enabled after %pF\n",
+					cls->suspend);
 			}
 		}
 	}
@@ -452,6 +471,9 @@
 {
 	struct sysdev_class *cls;
 
+	WARN_ONCE(!irqs_disabled(),
+		"Interrupts enabled while resuming system devices\n");
+
 	pr_debug("Resuming System Devices\n");
 
 	list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
diff -druN linux-libre-2.6.30-gnu/drivers/block/amiflop.c linux-libre-2.6.31-gnu/drivers/block/amiflop.c
--- linux-libre-2.6.30-gnu/drivers/block/amiflop.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/amiflop.c	2009-09-09 18:13:59.000000000 -0400
@@ -112,8 +112,6 @@
 MODULE_LICENSE("GPL");
 
 static struct request_queue *floppy_queue;
-#define QUEUE (floppy_queue)
-#define CURRENT elv_next_request(floppy_queue)
 
 /*
  *  Macros
@@ -1335,64 +1333,60 @@
 
 static void redo_fd_request(void)
 {
+	struct request *rq;
 	unsigned int cnt, block, track, sector;
 	int drive;
 	struct amiga_floppy_struct *floppy;
 	char *data;
 	unsigned long flags;
+	int err;
 
- repeat:
-	if (!CURRENT) {
+next_req:
+	rq = blk_fetch_request(floppy_queue);
+	if (!rq) {
 		/* Nothing left to do */
 		return;
 	}
 
-	floppy = CURRENT->rq_disk->private_data;
+	floppy = rq->rq_disk->private_data;
 	drive = floppy - unit;
 
+next_segment:
 	/* Here someone could investigate to be more efficient */
-	for (cnt = 0; cnt < CURRENT->current_nr_sectors; cnt++) { 
+	for (cnt = 0, err = 0; cnt < blk_rq_cur_sectors(rq); cnt++) {
 #ifdef DEBUG
 		printk("fd: sector %ld + %d requested for %s\n",
-		       CURRENT->sector,cnt,
-		       (rq_data_dir(CURRENT) == READ) ? "read" : "write");
+		       blk_rq_pos(rq), cnt,
+		       (rq_data_dir(rq) == READ) ? "read" : "write");
 #endif
-		block = CURRENT->sector + cnt;
+		block = blk_rq_pos(rq) + cnt;
 		if ((int)block > floppy->blocks) {
-			end_request(CURRENT, 0);
-			goto repeat;
+			err = -EIO;
+			break;
 		}
 
 		track = block / (floppy->dtype->sects * floppy->type->sect_mult);
 		sector = block % (floppy->dtype->sects * floppy->type->sect_mult);
-		data = CURRENT->buffer + 512 * cnt;
+		data = rq->buffer + 512 * cnt;
 #ifdef DEBUG
 		printk("access to track %d, sector %d, with buffer at "
 		       "0x%08lx\n", track, sector, data);
 #endif
 
-		if ((rq_data_dir(CURRENT) != READ) && (rq_data_dir(CURRENT) != WRITE)) {
-			printk(KERN_WARNING "do_fd_request: unknown command\n");
-			end_request(CURRENT, 0);
-			goto repeat;
-		}
 		if (get_track(drive, track) == -1) {
-			end_request(CURRENT, 0);
-			goto repeat;
+			err = -EIO;
+			break;
 		}
 
-		switch (rq_data_dir(CURRENT)) {
-		case READ:
+		if (rq_data_dir(rq) == READ) {
 			memcpy(data, floppy->trackbuf + sector * 512, 512);
-			break;
-
-		case WRITE:
+		} else {
 			memcpy(floppy->trackbuf + sector * 512, data, 512);
 
 			/* keep the drive spinning while writes are scheduled */
 			if (!fd_motor_on(drive)) {
-				end_request(CURRENT, 0);
-				goto repeat;
+				err = -EIO;
+				break;
 			}
 			/*
 			 * setup a callback to write the track buffer
@@ -1404,14 +1398,12 @@
 		        /* reset the timer */
 			mod_timer (flush_track_timer + drive, jiffies + 1);
 			local_irq_restore(flags);
-			break;
 		}
 	}
-	CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
-	CURRENT->sector += CURRENT->current_nr_sectors;
 
-	end_request(CURRENT, 1);
-	goto repeat;
+	if (__blk_end_request_cur(rq, err))
+		goto next_segment;
+	goto next_req;
 }
 
 static void do_fd_request(struct request_queue * q)
@@ -1653,7 +1645,7 @@
 {
 	int drive,drives,nomem;
 
-	printk(KERN_INFO "FD: probing units\n" KERN_INFO "found ");
+	printk(KERN_INFO "FD: probing units\nfound ");
 	drives=0;
 	nomem=0;
 	for(drive=0;drive<FD_MAX_UNITS;drive++) {
diff -druN linux-libre-2.6.30-gnu/drivers/block/aoe/aoeblk.c linux-libre-2.6.31-gnu/drivers/block/aoe/aoeblk.c
--- linux-libre-2.6.30-gnu/drivers/block/aoe/aoeblk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/aoe/aoeblk.c	2009-09-09 18:13:59.000000000 -0400
@@ -264,9 +264,12 @@
 		goto err_disk;
 	}
 
-	blk_queue_make_request(&d->blkq, aoeblk_make_request);
-	if (bdi_init(&d->blkq.backing_dev_info))
+	d->blkq = blk_alloc_queue(GFP_KERNEL);
+	if (!d->blkq)
 		goto err_mempool;
+	blk_queue_make_request(d->blkq, aoeblk_make_request);
+	if (bdi_init(&d->blkq->backing_dev_info))
+		goto err_blkq;
 	spin_lock_irqsave(&d->lock, flags);
 	gd->major = AOE_MAJOR;
 	gd->first_minor = d->sysminor * AOE_PARTITIONS;
@@ -276,7 +279,7 @@
 	snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
 		d->aoemajor, d->aoeminor);
 
-	gd->queue = &d->blkq;
+	gd->queue = d->blkq;
 	d->gd = gd;
 	d->flags &= ~DEVFL_GDALLOC;
 	d->flags |= DEVFL_UP;
@@ -287,6 +290,9 @@
 	aoedisk_add_sysfs(d);
 	return;
 
+err_blkq:
+	blk_cleanup_queue(d->blkq);
+	d->blkq = NULL;
 err_mempool:
 	mempool_destroy(d->bufpool);
 err_disk:
diff -druN linux-libre-2.6.30-gnu/drivers/block/aoe/aoechr.c linux-libre-2.6.31-gnu/drivers/block/aoe/aoechr.c
--- linux-libre-2.6.30-gnu/drivers/block/aoe/aoechr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/aoe/aoechr.c	2009-09-09 18:13:59.000000000 -0400
@@ -266,6 +266,11 @@
 	.owner = THIS_MODULE,
 };
 
+static char *aoe_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev));
+}
+
 int __init
 aoechr_init(void)
 {
@@ -283,6 +288,8 @@
 		unregister_chrdev(AOE_MAJOR, "aoechr");
 		return PTR_ERR(aoe_class);
 	}
+	aoe_class->nodename = aoe_nodename;
+
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
 		device_create(aoe_class, NULL,
 			      MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
diff -druN linux-libre-2.6.30-gnu/drivers/block/aoe/aoecmd.c linux-libre-2.6.31-gnu/drivers/block/aoe/aoecmd.c
--- linux-libre-2.6.30-gnu/drivers/block/aoe/aoecmd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/aoe/aoecmd.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,13 +34,6 @@
 		skb_reset_mac_header(skb);
 		skb_reset_network_header(skb);
 		skb->protocol = __constant_htons(ETH_P_AOE);
-		skb->priority = 0;
-		skb->next = skb->prev = NULL;
-
-		/* tell the network layer not to perform IP checksums
-		 * or to get the NIC to do it
-		 */
-		skb->ip_summed = CHECKSUM_NONE;
 	}
 	return skb;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/block/aoe/aoedev.c linux-libre-2.6.31-gnu/drivers/block/aoe/aoedev.c
--- linux-libre-2.6.30-gnu/drivers/block/aoe/aoedev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/aoe/aoedev.c	2009-09-09 18:13:59.000000000 -0400
@@ -113,6 +113,7 @@
 	if (d->bufpool)
 		mempool_destroy(d->bufpool);
 	skbpoolfree(d);
+	blk_cleanup_queue(d->blkq);
 	kfree(d);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/aoe/aoe.h linux-libre-2.6.31-gnu/drivers/block/aoe/aoe.h
--- linux-libre-2.6.30-gnu/drivers/block/aoe/aoe.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/aoe/aoe.h	2009-09-09 18:13:59.000000000 -0400
@@ -155,7 +155,7 @@
 	u16 fw_ver;		/* version of blade's firmware */
 	struct work_struct work;/* disk create work struct */
 	struct gendisk *gd;
-	struct request_queue blkq;
+	struct request_queue *blkq;
 	struct hd_geometry geo; 
 	sector_t ssize;
 	struct timer_list timer;
diff -druN linux-libre-2.6.30-gnu/drivers/block/ataflop.c linux-libre-2.6.31-gnu/drivers/block/ataflop.c
--- linux-libre-2.6.30-gnu/drivers/block/ataflop.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/ataflop.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,9 +79,7 @@
 #undef DEBUG
 
 static struct request_queue *floppy_queue;
-
-#define QUEUE (floppy_queue)
-#define CURRENT elv_next_request(floppy_queue)
+static struct request *fd_request;
 
 /* Disk types: DD, HD, ED */
 static struct atari_disk_type {
@@ -376,6 +374,12 @@
 static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
 static DEFINE_TIMER(fd_timer, check_change, 0, 0);
 	
+static void fd_end_request_cur(int err)
+{
+	if (!__blk_end_request_cur(fd_request, err))
+		fd_request = NULL;
+}
+
 static inline void start_motor_off_timer(void)
 {
 	mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY);
@@ -606,15 +610,15 @@
 		return;
 	}
 
-	if (!CURRENT)
+	if (!fd_request)
 		return;
 
-	CURRENT->errors++;
-	if (CURRENT->errors >= MAX_ERRORS) {
+	fd_request->errors++;
+	if (fd_request->errors >= MAX_ERRORS) {
 		printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
-		end_request(CURRENT, 0);
+		fd_end_request_cur(-EIO);
 	}
-	else if (CURRENT->errors == RECALIBRATE_ERRORS) {
+	else if (fd_request->errors == RECALIBRATE_ERRORS) {
 		printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
 		if (SelectedDrive != -1)
 			SUD.track = -1;
@@ -725,16 +729,14 @@
 	    if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
 		if (ReqCmd == READ) {
 		    copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
-		    if (++ReqCnt < CURRENT->current_nr_sectors) {
+		    if (++ReqCnt < blk_rq_cur_sectors(fd_request)) {
 			/* read next sector */
 			setup_req_params( drive );
 			goto repeat;
 		    }
 		    else {
 			/* all sectors finished */
-			CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
-			CURRENT->sector += CURRENT->current_nr_sectors;
-			end_request(CURRENT, 1);
+			fd_end_request_cur(0);
 			redo_fd_request();
 			return;
 		    }
@@ -1132,16 +1134,14 @@
 		}
 	}
   
-	if (++ReqCnt < CURRENT->current_nr_sectors) {
+	if (++ReqCnt < blk_rq_cur_sectors(fd_request)) {
 		/* read next sector */
 		setup_req_params( SelectedDrive );
 		do_fd_action( SelectedDrive );
 	}
 	else {
 		/* all sectors finished */
-		CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
-		CURRENT->sector += CURRENT->current_nr_sectors;
-		end_request(CURRENT, 1);
+		fd_end_request_cur(0);
 		redo_fd_request();
 	}
 	return;
@@ -1382,7 +1382,7 @@
 	ReqData = ReqBuffer + 512 * ReqCnt;
 
 	if (UseTrackbuffer)
-		read_track = (ReqCmd == READ && CURRENT->errors == 0);
+		read_track = (ReqCmd == READ && fd_request->errors == 0);
 	else
 		read_track = 0;
 
@@ -1396,25 +1396,27 @@
 	int drive, type;
 	struct atari_floppy_struct *floppy;
 
-	DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n",
-		CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "",
-		CURRENT ? CURRENT->sector : 0 ));
+	DPRINT(("redo_fd_request: fd_request=%p dev=%s fd_request->sector=%ld\n",
+		fd_request, fd_request ? fd_request->rq_disk->disk_name : "",
+		fd_request ? blk_rq_pos(fd_request) : 0 ));
 
 	IsFormatting = 0;
 
 repeat:
+	if (!fd_request) {
+		fd_request = blk_fetch_request(floppy_queue);
+		if (!fd_request)
+			goto the_end;
+	}
 
-	if (!CURRENT)
-		goto the_end;
-
-	floppy = CURRENT->rq_disk->private_data;
+	floppy = fd_request->rq_disk->private_data;
 	drive = floppy - unit;
 	type = floppy->type;
 	
 	if (!UD.connected) {
 		/* drive not connected */
 		printk(KERN_ERR "Unknown Device: fd%d\n", drive );
-		end_request(CURRENT, 0);
+		fd_end_request_cur(-EIO);
 		goto repeat;
 	}
 		
@@ -1430,12 +1432,12 @@
 		/* user supplied disk type */
 		if (--type >= NUM_DISK_MINORS) {
 			printk(KERN_WARNING "fd%d: invalid disk format", drive );
-			end_request(CURRENT, 0);
+			fd_end_request_cur(-EIO);
 			goto repeat;
 		}
 		if (minor2disktype[type].drive_types > DriveType)  {
 			printk(KERN_WARNING "fd%d: unsupported disk format", drive );
-			end_request(CURRENT, 0);
+			fd_end_request_cur(-EIO);
 			goto repeat;
 		}
 		type = minor2disktype[type].index;
@@ -1444,8 +1446,8 @@
 		UD.autoprobe = 0;
 	}
 	
-	if (CURRENT->sector + 1 > UDT->blocks) {
-		end_request(CURRENT, 0);
+	if (blk_rq_pos(fd_request) + 1 > UDT->blocks) {
+		fd_end_request_cur(-EIO);
 		goto repeat;
 	}
 
@@ -1453,9 +1455,9 @@
 	del_timer( &motor_off_timer );
 		
 	ReqCnt = 0;
-	ReqCmd = rq_data_dir(CURRENT);
-	ReqBlock = CURRENT->sector;
-	ReqBuffer = CURRENT->buffer;
+	ReqCmd = rq_data_dir(fd_request);
+	ReqBlock = blk_rq_pos(fd_request);
+	ReqBuffer = fd_request->buffer;
 	setup_req_params( drive );
 	do_fd_action( drive );
 
@@ -1625,7 +1627,7 @@
 				drive, dtp->blocks, dtp->spt, dtp->stretch);
 
 		/* sanity check */
-		if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 ||
+		if (setprm.track != dtp->blocks/dtp->spt/2 ||
 		    setprm.head != 2) {
 			redo_fd_request();
 			return -EINVAL;
diff -druN linux-libre-2.6.30-gnu/drivers/block/brd.c linux-libre-2.6.31-gnu/drivers/block/brd.c
--- linux-libre-2.6.30-gnu/drivers/block/brd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/brd.c	2009-09-09 18:13:59.000000000 -0400
@@ -407,12 +407,7 @@
 	rd_size = simple_strtol(str, NULL, 0);
 	return 1;
 }
-static int __init ramdisk_size2(char *str)
-{
-	return ramdisk_size(str);
-}
-__setup("ramdisk=", ramdisk_size);
-__setup("ramdisk_size=", ramdisk_size2);
+__setup("ramdisk_size=", ramdisk_size);
 #endif
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/block/cciss.c linux-libre-2.6.31-gnu/drivers/block/cciss.c
--- linux-libre-2.6.30-gnu/drivers/block/cciss.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/cciss.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -38,7 +39,6 @@
 #include <linux/hdreg.h>
 #include <linux/spinlock.h>
 #include <linux/compat.h>
-#include <linux/blktrace_api.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -180,11 +180,13 @@
 					   __u32);
 static void start_io(ctlr_info_t *h);
 static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
-		   unsigned int use_unit_num, unsigned int log_unit,
 		   __u8 page_code, unsigned char *scsi3addr, int cmd_type);
 static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
-			   unsigned int use_unit_num, unsigned int log_unit,
-			   __u8 page_code, int cmd_type);
+			__u8 page_code, unsigned char scsi3addr[],
+			int cmd_type);
+static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c,
+	int attempt_retry);
+static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c);
 
 static void fail_all_cmds(unsigned long ctlr);
 static int scan_thread(void *data);
@@ -225,8 +227,18 @@
 
 static inline void removeQ(CommandList_struct *c)
 {
-	if (WARN_ON(hlist_unhashed(&c->list)))
+	/*
+	 * After kexec/dump some commands might still
+	 * be in flight, which the firmware will try
+	 * to complete. Resetting the firmware doesn't work
+	 * with old fw revisions, so we have to mark
+	 * them off as 'stale' to prevent the driver from
+	 * falling over.
+	 */
+	if (WARN_ON(hlist_unhashed(&c->list))) {
+		c->cmd_type = CMD_MSG_STALE;
 		return;
+	}
 
 	hlist_del_init(&c->list);
 }
@@ -437,6 +449,194 @@
 }
 #endif				/* CONFIG_PROC_FS */
 
+#define MAX_PRODUCT_NAME_LEN 19
+
+#define to_hba(n) container_of(n, struct ctlr_info, dev)
+#define to_drv(n) container_of(n, drive_info_struct, dev)
+
+static struct device_type cciss_host_type = {
+	.name		= "cciss_host",
+};
+
+static ssize_t dev_show_unique_id(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	drive_info_struct *drv = to_drv(dev);
+	struct ctlr_info *h = to_hba(drv->dev.parent);
+	__u8 sn[16];
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+	if (h->busy_configuring)
+		ret = -EBUSY;
+	else
+		memcpy(sn, drv->serial_no, sizeof(sn));
+	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+
+	if (ret)
+		return ret;
+	else
+		return snprintf(buf, 16 * 2 + 2,
+				"%02X%02X%02X%02X%02X%02X%02X%02X"
+				"%02X%02X%02X%02X%02X%02X%02X%02X\n",
+				sn[0], sn[1], sn[2], sn[3],
+				sn[4], sn[5], sn[6], sn[7],
+				sn[8], sn[9], sn[10], sn[11],
+				sn[12], sn[13], sn[14], sn[15]);
+}
+DEVICE_ATTR(unique_id, S_IRUGO, dev_show_unique_id, NULL);
+
+static ssize_t dev_show_vendor(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	drive_info_struct *drv = to_drv(dev);
+	struct ctlr_info *h = to_hba(drv->dev.parent);
+	char vendor[VENDOR_LEN + 1];
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+	if (h->busy_configuring)
+		ret = -EBUSY;
+	else
+		memcpy(vendor, drv->vendor, VENDOR_LEN + 1);
+	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+
+	if (ret)
+		return ret;
+	else
+		return snprintf(buf, sizeof(vendor) + 1, "%s\n", drv->vendor);
+}
+DEVICE_ATTR(vendor, S_IRUGO, dev_show_vendor, NULL);
+
+static ssize_t dev_show_model(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	drive_info_struct *drv = to_drv(dev);
+	struct ctlr_info *h = to_hba(drv->dev.parent);
+	char model[MODEL_LEN + 1];
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+	if (h->busy_configuring)
+		ret = -EBUSY;
+	else
+		memcpy(model, drv->model, MODEL_LEN + 1);
+	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+
+	if (ret)
+		return ret;
+	else
+		return snprintf(buf, sizeof(model) + 1, "%s\n", drv->model);
+}
+DEVICE_ATTR(model, S_IRUGO, dev_show_model, NULL);
+
+static ssize_t dev_show_rev(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	drive_info_struct *drv = to_drv(dev);
+	struct ctlr_info *h = to_hba(drv->dev.parent);
+	char rev[REV_LEN + 1];
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+	if (h->busy_configuring)
+		ret = -EBUSY;
+	else
+		memcpy(rev, drv->rev, REV_LEN + 1);
+	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+
+	if (ret)
+		return ret;
+	else
+		return snprintf(buf, sizeof(rev) + 1, "%s\n", drv->rev);
+}
+DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL);
+
+static struct attribute *cciss_dev_attrs[] = {
+	&dev_attr_unique_id.attr,
+	&dev_attr_model.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_rev.attr,
+	NULL
+};
+
+static struct attribute_group cciss_dev_attr_group = {
+	.attrs = cciss_dev_attrs,
+};
+
+static struct attribute_group *cciss_dev_attr_groups[] = {
+	&cciss_dev_attr_group,
+	NULL
+};
+
+static struct device_type cciss_dev_type = {
+	.name		= "cciss_device",
+	.groups		= cciss_dev_attr_groups,
+};
+
+static struct bus_type cciss_bus_type = {
+	.name		= "cciss",
+};
+
+
+/*
+ * Initialize sysfs entry for each controller.  This sets up and registers
+ * the 'cciss#' directory for each individual controller under
+ * /sys/bus/pci/devices/<dev>/.
+ */
+static int cciss_create_hba_sysfs_entry(struct ctlr_info *h)
+{
+	device_initialize(&h->dev);
+	h->dev.type = &cciss_host_type;
+	h->dev.bus = &cciss_bus_type;
+	dev_set_name(&h->dev, "%s", h->devname);
+	h->dev.parent = &h->pdev->dev;
+
+	return device_add(&h->dev);
+}
+
+/*
+ * Remove sysfs entries for an hba.
+ */
+static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h)
+{
+	device_del(&h->dev);
+}
+
+/*
+ * Initialize sysfs for each logical drive.  This sets up and registers
+ * the 'c#d#' directory for each individual logical drive under
+ * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from
+ * /sys/block/cciss!c#d# to this entry.
+ */
+static int cciss_create_ld_sysfs_entry(struct ctlr_info *h,
+				       drive_info_struct *drv,
+				       int drv_index)
+{
+	device_initialize(&drv->dev);
+	drv->dev.type = &cciss_dev_type;
+	drv->dev.bus = &cciss_bus_type;
+	dev_set_name(&drv->dev, "c%dd%d", h->ctlr, drv_index);
+	drv->dev.parent = &h->dev;
+	return device_add(&drv->dev);
+}
+
+/*
+ * Remove sysfs entries for a logical drive.
+ */
+static void cciss_destroy_ld_sysfs_entry(drive_info_struct *drv)
+{
+	device_del(&drv->dev);
+}
+
 /*
  * For operations that cannot sleep, a command block is allocated at init,
  * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
@@ -1299,7 +1499,6 @@
 {
 	CommandList_struct *cmd = rq->completion_data;
 	ctlr_info_t *h = hba[cmd->ctlr];
-	unsigned int nr_bytes;
 	unsigned long flags;
 	u64bit temp64;
 	int i, ddir;
@@ -1321,15 +1520,11 @@
 	printk("Done with %p\n", rq);
 #endif				/* CCISS_DEBUG */
 
-	/*
-	 * Store the full size and set the residual count for pc requests
-	 */
-	nr_bytes = blk_rq_bytes(rq);
+	/* set the residual count for pc requests */
 	if (blk_pc_request(rq))
-		rq->data_len = cmd->err_info->ResidualCnt;
+		rq->resid_len = cmd->err_info->ResidualCnt;
 
-	if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, nr_bytes))
-		BUG();
+	blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO);
 
 	spin_lock_irqsave(&h->lock, flags);
 	cmd_free(h, cmd, 1);
@@ -1337,6 +1532,56 @@
 	spin_unlock_irqrestore(&h->lock, flags);
 }
 
+static void log_unit_to_scsi3addr(ctlr_info_t *h, unsigned char scsi3addr[],
+	uint32_t log_unit)
+{
+	log_unit = h->drv[log_unit].LunID & 0x03fff;
+	memset(&scsi3addr[4], 0, 4);
+	memcpy(&scsi3addr[0], &log_unit, 4);
+	scsi3addr[3] |= 0x40;
+}
+
+/* This function gets the SCSI vendor, model, and revision of a logical drive
+ * via the inquiry page 0.  Model, vendor, and rev are set to empty strings if
+ * they cannot be read.
+ */
+static void cciss_get_device_descr(int ctlr, int logvol, int withirq,
+				   char *vendor, char *model, char *rev)
+{
+	int rc;
+	InquiryData_struct *inq_buf;
+	unsigned char scsi3addr[8];
+
+	*vendor = '\0';
+	*model = '\0';
+	*rev = '\0';
+
+	inq_buf = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+	if (!inq_buf)
+		return;
+
+	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
+	if (withirq)
+		rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf,
+			     sizeof(InquiryData_struct), 0,
+				scsi3addr, TYPE_CMD);
+	else
+		rc = sendcmd(CISS_INQUIRY, ctlr, inq_buf,
+			     sizeof(InquiryData_struct), 0,
+				scsi3addr, TYPE_CMD);
+	if (rc == IO_OK) {
+		memcpy(vendor, &inq_buf->data_byte[8], VENDOR_LEN);
+		vendor[VENDOR_LEN] = '\0';
+		memcpy(model, &inq_buf->data_byte[16], MODEL_LEN);
+		model[MODEL_LEN] = '\0';
+		memcpy(rev, &inq_buf->data_byte[32], REV_LEN);
+		rev[REV_LEN] = '\0';
+	}
+
+	kfree(inq_buf);
+	return;
+}
+
 /* This function gets the serial number of a logical drive via
  * inquiry page 0x83.  Serial no. is 16 bytes.  If the serial
  * number cannot be had, for whatever reason, 16 bytes of 0xff
@@ -1348,6 +1593,7 @@
 #define PAGE_83_INQ_BYTES 64
 	int rc;
 	unsigned char *buf;
+	unsigned char scsi3addr[8];
 
 	if (buflen > 16)
 		buflen = 16;
@@ -1356,12 +1602,13 @@
 	if (!buf)
 		return;
 	memset(serial_no, 0, buflen);
+	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
 	if (withirq)
 		rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf,
-			PAGE_83_INQ_BYTES, 1, logvol, 0x83, TYPE_CMD);
+			PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
 	else
 		rc = sendcmd(CISS_INQUIRY, ctlr, buf,
-			PAGE_83_INQ_BYTES, 1, logvol, 0x83, NULL, TYPE_CMD);
+			PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD);
 	if (rc == IO_OK)
 		memcpy(serial_no, &buf[8], buflen);
 	kfree(buf);
@@ -1377,7 +1624,7 @@
 	disk->first_minor = drv_index << NWD_SHIFT;
 	disk->fops = &cciss_fops;
 	disk->private_data = &h->drv[drv_index];
-	disk->driverfs_dev = &h->pdev->dev;
+	disk->driverfs_dev = &h->drv[drv_index].dev;
 
 	/* Set up queue information */
 	blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
@@ -1394,8 +1641,8 @@
 
 	disk->queue->queuedata = h;
 
-	blk_queue_hardsect_size(disk->queue,
-				h->drv[drv_index].block_size);
+	blk_queue_logical_block_size(disk->queue,
+				     h->drv[drv_index].block_size);
 
 	/* Make sure all queue data is written out before */
 	/* setting h->drv[drv_index].queue, as setting this */
@@ -1468,6 +1715,8 @@
 	drvinfo->block_size = block_size;
 	drvinfo->nr_blocks = total_size + 1;
 
+	cciss_get_device_descr(ctlr, drv_index, 1, drvinfo->vendor,
+				drvinfo->model, drvinfo->rev);
 	cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no,
 			sizeof(drvinfo->serial_no));
 
@@ -1517,6 +1766,9 @@
 	h->drv[drv_index].cylinders = drvinfo->cylinders;
 	h->drv[drv_index].raid_level = drvinfo->raid_level;
 	memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16);
+	memcpy(h->drv[drv_index].vendor, drvinfo->vendor, VENDOR_LEN + 1);
+	memcpy(h->drv[drv_index].model, drvinfo->model, MODEL_LEN + 1);
+	memcpy(h->drv[drv_index].rev, drvinfo->rev, REV_LEN + 1);
 
 	++h->num_luns;
 	disk = h->gendisk[drv_index];
@@ -1591,6 +1843,8 @@
 		}
 	}
 	h->drv[drv_index].LunID = lunid;
+	if (cciss_create_ld_sysfs_entry(h, &h->drv[drv_index], drv_index))
+		goto err_free_disk;
 
 	/* Don't need to mark this busy because nobody */
 	/* else knows about this disk yet to contend */
@@ -1598,6 +1852,11 @@
 	h->drv[drv_index].busy_configuring = 0;
 	wmb();
 	return drv_index;
+
+err_free_disk:
+	put_disk(h->gendisk[drv_index]);
+	h->gendisk[drv_index] = NULL;
+	return -1;
 }
 
 /* This is for the special case of a controller which
@@ -1668,8 +1927,8 @@
 		goto mem_msg;
 
 	return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
-				      sizeof(ReportLunData_struct), 0,
-				      0, 0, TYPE_CMD);
+				      sizeof(ReportLunData_struct),
+				      0, CTLR_LUNID, TYPE_CMD);
 
 	if (return_code == IO_OK)
 		listlength = be32_to_cpu(*(__be32 *) ld_buff->LUNListLength);
@@ -1718,6 +1977,7 @@
 			h->drv[i].busy_configuring = 1;
 			spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 			return_code = deregister_disk(h, i, 1);
+			cciss_destroy_ld_sysfs_entry(&h->drv[i]);
 			h->drv[i].busy_configuring = 0;
 		}
 	}
@@ -1877,11 +2137,9 @@
 	return 0;
 }
 
-static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num,	/* 0: address the controller,
-															   1: address logical volume log_unit,
-															   2: periph device address is scsi3addr */
-		    unsigned int log_unit, __u8 page_code,
-		    unsigned char *scsi3addr, int cmd_type)
+static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
+		size_t size, __u8 page_code, unsigned char *scsi3addr,
+		int cmd_type)
 {
 	ctlr_info_t *h = hba[ctlr];
 	u64bit buff_dma_handle;
@@ -1897,27 +2155,12 @@
 		c->Header.SGTotal = 0;
 	}
 	c->Header.Tag.lower = c->busaddr;
+	memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8);
 
 	c->Request.Type.Type = cmd_type;
 	if (cmd_type == TYPE_CMD) {
 		switch (cmd) {
 		case CISS_INQUIRY:
-			/* If the logical unit number is 0 then, this is going
-			   to controller so It's a physical command
-			   mode = 0 target = 0.  So we have nothing to write.
-			   otherwise, if use_unit_num == 1,
-			   mode = 1(volume set addressing) target = LUNID
-			   otherwise, if use_unit_num == 2,
-			   mode = 0(periph dev addr) target = scsi3addr */
-			if (use_unit_num == 1) {
-				c->Header.LUN.LogDev.VolId =
-				    h->drv[log_unit].LunID;
-				c->Header.LUN.LogDev.Mode = 1;
-			} else if (use_unit_num == 2) {
-				memcpy(c->Header.LUN.LunAddrBytes, scsi3addr,
-				       8);
-				c->Header.LUN.LogDev.Mode = 0;
-			}
 			/* are we trying to read a vital product page */
 			if (page_code != 0) {
 				c->Request.CDB[1] = 0x01;
@@ -1947,8 +2190,6 @@
 			break;
 
 		case CCISS_READ_CAPACITY:
-			c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
-			c->Header.LUN.LogDev.Mode = 1;
 			c->Request.CDBLen = 10;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
 			c->Request.Type.Direction = XFER_READ;
@@ -1956,8 +2197,6 @@
 			c->Request.CDB[0] = cmd;
 			break;
 		case CCISS_READ_CAPACITY_16:
-			c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
-			c->Header.LUN.LogDev.Mode = 1;
 			c->Request.CDBLen = 16;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
 			c->Request.Type.Direction = XFER_READ;
@@ -1979,6 +2218,12 @@
 			c->Request.CDB[0] = BMIC_WRITE;
 			c->Request.CDB[6] = BMIC_CACHE_FLUSH;
 			break;
+		case TEST_UNIT_READY:
+			c->Request.CDBLen = 6;
+			c->Request.Type.Attribute = ATTR_SIMPLE;
+			c->Request.Type.Direction = XFER_NONE;
+			c->Request.Timeout = 0;
+			break;
 		default:
 			printk(KERN_WARNING
 			       "cciss%d:  Unknown Command 0x%c\n", ctlr, cmd);
@@ -1997,13 +2242,13 @@
 			memcpy(&c->Request.CDB[4], buff, 8);
 			break;
 		case 1:	/* RESET message */
-			c->Request.CDBLen = 12;
+			c->Request.CDBLen = 16;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
-			c->Request.Type.Direction = XFER_WRITE;
+			c->Request.Type.Direction = XFER_NONE;
 			c->Request.Timeout = 0;
 			memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
 			c->Request.CDB[0] = cmd;	/* reset */
-			c->Request.CDB[1] = 0x04;	/* reset a LUN */
+			c->Request.CDB[1] = 0x03;	/* reset a target */
 			break;
 		case 3:	/* No-Op message */
 			c->Request.CDBLen = 1;
@@ -2035,114 +2280,152 @@
 	return status;
 }
 
-static int sendcmd_withirq(__u8 cmd,
-			   int ctlr,
-			   void *buff,
-			   size_t size,
-			   unsigned int use_unit_num,
-			   unsigned int log_unit, __u8 page_code, int cmd_type)
+static int check_target_status(ctlr_info_t *h, CommandList_struct *c)
 {
-	ctlr_info_t *h = hba[ctlr];
-	CommandList_struct *c;
+	switch (c->err_info->ScsiStatus) {
+	case SAM_STAT_GOOD:
+		return IO_OK;
+	case SAM_STAT_CHECK_CONDITION:
+		switch (0xf & c->err_info->SenseInfo[2]) {
+		case 0: return IO_OK; /* no sense */
+		case 1: return IO_OK; /* recovered error */
+		default:
+			printk(KERN_WARNING "cciss%d: cmd 0x%02x "
+				"check condition, sense key = 0x%02x\n",
+				h->ctlr, c->Request.CDB[0],
+				c->err_info->SenseInfo[2]);
+		}
+		break;
+	default:
+		printk(KERN_WARNING "cciss%d: cmd 0x%02x"
+			"scsi status = 0x%02x\n", h->ctlr,
+			c->Request.CDB[0], c->err_info->ScsiStatus);
+		break;
+	}
+	return IO_ERROR;
+}
+
+static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c)
+{
+	int return_status = IO_OK;
+
+	if (c->err_info->CommandStatus == CMD_SUCCESS)
+		return IO_OK;
+
+	switch (c->err_info->CommandStatus) {
+	case CMD_TARGET_STATUS:
+		return_status = check_target_status(h, c);
+		break;
+	case CMD_DATA_UNDERRUN:
+	case CMD_DATA_OVERRUN:
+		/* expected for inquiry and report lun commands */
+		break;
+	case CMD_INVALID:
+		printk(KERN_WARNING "cciss: cmd 0x%02x is "
+		       "reported invalid\n", c->Request.CDB[0]);
+		return_status = IO_ERROR;
+		break;
+	case CMD_PROTOCOL_ERR:
+		printk(KERN_WARNING "cciss: cmd 0x%02x has "
+		       "protocol error \n", c->Request.CDB[0]);
+		return_status = IO_ERROR;
+		break;
+	case CMD_HARDWARE_ERR:
+		printk(KERN_WARNING "cciss: cmd 0x%02x had "
+		       " hardware error\n", c->Request.CDB[0]);
+		return_status = IO_ERROR;
+		break;
+	case CMD_CONNECTION_LOST:
+		printk(KERN_WARNING "cciss: cmd 0x%02x had "
+		       "connection lost\n", c->Request.CDB[0]);
+		return_status = IO_ERROR;
+		break;
+	case CMD_ABORTED:
+		printk(KERN_WARNING "cciss: cmd 0x%02x was "
+		       "aborted\n", c->Request.CDB[0]);
+		return_status = IO_ERROR;
+		break;
+	case CMD_ABORT_FAILED:
+		printk(KERN_WARNING "cciss: cmd 0x%02x reports "
+		       "abort failed\n", c->Request.CDB[0]);
+		return_status = IO_ERROR;
+		break;
+	case CMD_UNSOLICITED_ABORT:
+		printk(KERN_WARNING
+		       "cciss%d: unsolicited abort 0x%02x\n", h->ctlr,
+			c->Request.CDB[0]);
+		return_status = IO_NEEDS_RETRY;
+		break;
+	default:
+		printk(KERN_WARNING "cciss: cmd 0x%02x returned "
+		       "unknown status %x\n", c->Request.CDB[0],
+		       c->err_info->CommandStatus);
+		return_status = IO_ERROR;
+	}
+	return return_status;
+}
+
+static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c,
+	int attempt_retry)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
 	u64bit buff_dma_handle;
 	unsigned long flags;
-	int return_status;
-	DECLARE_COMPLETION_ONSTACK(wait);
+	int return_status = IO_OK;
 
-	if ((c = cmd_alloc(h, 0)) == NULL)
-		return -ENOMEM;
-	return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
-				 log_unit, page_code, NULL, cmd_type);
-	if (return_status != IO_OK) {
-		cmd_free(h, c, 0);
-		return return_status;
-	}
-      resend_cmd2:
+resend_cmd2:
 	c->waiting = &wait;
-
 	/* Put the request on the tail of the queue and send it */
-	spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
 	addQ(&h->reqQ, c);
 	h->Qdepth++;
 	start_io(h);
-	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 
 	wait_for_completion(&wait);
 
-	if (c->err_info->CommandStatus != 0) {	/* an error has occurred */
-		switch (c->err_info->CommandStatus) {
-		case CMD_TARGET_STATUS:
-			printk(KERN_WARNING "cciss: cmd %p has "
-			       " completed with errors\n", c);
-			if (c->err_info->ScsiStatus) {
-				printk(KERN_WARNING "cciss: cmd %p "
-				       "has SCSI Status = %x\n",
-				       c, c->err_info->ScsiStatus);
-			}
+	if (c->err_info->CommandStatus == 0 || !attempt_retry)
+		goto command_done;
 
-			break;
-		case CMD_DATA_UNDERRUN:
-		case CMD_DATA_OVERRUN:
-			/* expected for inquire and report lun commands */
-			break;
-		case CMD_INVALID:
-			printk(KERN_WARNING "cciss: Cmd %p is "
-			       "reported invalid\n", c);
-			return_status = IO_ERROR;
-			break;
-		case CMD_PROTOCOL_ERR:
-			printk(KERN_WARNING "cciss: cmd %p has "
-			       "protocol error \n", c);
-			return_status = IO_ERROR;
-			break;
-		case CMD_HARDWARE_ERR:
-			printk(KERN_WARNING "cciss: cmd %p had "
-			       " hardware error\n", c);
-			return_status = IO_ERROR;
-			break;
-		case CMD_CONNECTION_LOST:
-			printk(KERN_WARNING "cciss: cmd %p had "
-			       "connection lost\n", c);
-			return_status = IO_ERROR;
-			break;
-		case CMD_ABORTED:
-			printk(KERN_WARNING "cciss: cmd %p was "
-			       "aborted\n", c);
-			return_status = IO_ERROR;
-			break;
-		case CMD_ABORT_FAILED:
-			printk(KERN_WARNING "cciss: cmd %p reports "
-			       "abort failed\n", c);
-			return_status = IO_ERROR;
-			break;
-		case CMD_UNSOLICITED_ABORT:
-			printk(KERN_WARNING
-			       "cciss%d: unsolicited abort %p\n", ctlr, c);
-			if (c->retry_count < MAX_CMD_RETRIES) {
-				printk(KERN_WARNING
-				       "cciss%d: retrying %p\n", ctlr, c);
-				c->retry_count++;
-				/* erase the old error information */
-				memset(c->err_info, 0,
-				       sizeof(ErrorInfo_struct));
-				return_status = IO_OK;
-				INIT_COMPLETION(wait);
-				goto resend_cmd2;
-			}
-			return_status = IO_ERROR;
-			break;
-		default:
-			printk(KERN_WARNING "cciss: cmd %p returned "
-			       "unknown status %x\n", c,
-			       c->err_info->CommandStatus);
-			return_status = IO_ERROR;
-		}
+	return_status = process_sendcmd_error(h, c);
+
+	if (return_status == IO_NEEDS_RETRY &&
+		c->retry_count < MAX_CMD_RETRIES) {
+		printk(KERN_WARNING "cciss%d: retrying 0x%02x\n", h->ctlr,
+			c->Request.CDB[0]);
+		c->retry_count++;
+		/* erase the old error information */
+		memset(c->err_info, 0, sizeof(ErrorInfo_struct));
+		return_status = IO_OK;
+		INIT_COMPLETION(wait);
+		goto resend_cmd2;
 	}
+
+command_done:
 	/* unlock the buffers from DMA */
 	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
 	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
 	pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
 			 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
+	return return_status;
+}
+
+static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
+			   __u8 page_code, unsigned char scsi3addr[],
+			int cmd_type)
+{
+	ctlr_info_t *h = hba[ctlr];
+	CommandList_struct *c;
+	int return_status;
+
+	c = cmd_alloc(h, 0);
+	if (!c)
+		return -ENOMEM;
+	return_status = fill_cmd(c, cmd, ctlr, buff, size, page_code,
+		scsi3addr, cmd_type);
+	if (return_status == IO_OK)
+		return_status = sendcmd_withirq_core(h, c, 1);
+
 	cmd_free(h, c, 0);
 	return return_status;
 }
@@ -2155,15 +2438,17 @@
 {
 	int return_code;
 	unsigned long t;
+	unsigned char scsi3addr[8];
 
 	memset(inq_buff, 0, sizeof(InquiryData_struct));
+	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
 	if (withirq)
 		return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
-					      inq_buff, sizeof(*inq_buff), 1,
-					      logvol, 0xC1, TYPE_CMD);
+					      inq_buff, sizeof(*inq_buff),
+					      0xC1, scsi3addr, TYPE_CMD);
 	else
 		return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
-				      sizeof(*inq_buff), 1, logvol, 0xC1, NULL,
+				      sizeof(*inq_buff), 0xC1, scsi3addr,
 				      TYPE_CMD);
 	if (return_code == IO_OK) {
 		if (inq_buff->data_byte[8] == 0xFF) {
@@ -2204,6 +2489,7 @@
 {
 	ReadCapdata_struct *buf;
 	int return_code;
+	unsigned char scsi3addr[8];
 
 	buf = kzalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
 	if (!buf) {
@@ -2211,14 +2497,15 @@
 		return;
 	}
 
+	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
 	if (withirq)
 		return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
 				ctlr, buf, sizeof(ReadCapdata_struct),
-					1, logvol, 0, TYPE_CMD);
+					0, scsi3addr, TYPE_CMD);
 	else
 		return_code = sendcmd(CCISS_READ_CAPACITY,
 				ctlr, buf, sizeof(ReadCapdata_struct),
-					1, logvol, 0, NULL, TYPE_CMD);
+					0, scsi3addr, TYPE_CMD);
 	if (return_code == IO_OK) {
 		*total_size = be32_to_cpu(*(__be32 *) buf->total_size);
 		*block_size = be32_to_cpu(*(__be32 *) buf->block_size);
@@ -2238,6 +2525,7 @@
 {
 	ReadCapdata_struct_16 *buf;
 	int return_code;
+	unsigned char scsi3addr[8];
 
 	buf = kzalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
 	if (!buf) {
@@ -2245,15 +2533,16 @@
 		return;
 	}
 
+	log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol);
 	if (withirq) {
 		return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
 			ctlr, buf, sizeof(ReadCapdata_struct_16),
-				1, logvol, 0, TYPE_CMD);
+				0, scsi3addr, TYPE_CMD);
 	}
 	else {
 		return_code = sendcmd(CCISS_READ_CAPACITY_16,
 			ctlr, buf, sizeof(ReadCapdata_struct_16),
-				1, logvol, 0, NULL, TYPE_CMD);
+				0, scsi3addr, TYPE_CMD);
 	}
 	if (return_code == IO_OK) {
 		*total_size = be64_to_cpu(*(__be64 *) buf->total_size);
@@ -2303,7 +2592,7 @@
 	cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
 			       inq_buff, drv);
 
-	blk_queue_hardsect_size(drv->queue, drv->block_size);
+	blk_queue_logical_block_size(drv->queue, drv->block_size);
 	set_capacity(disk, drv->nr_blocks);
 
 	kfree(inq_buff);
@@ -2333,86 +2622,21 @@
 	return 1;
 }
 
-static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
-{
-	/* We get in here if sendcmd() is polling for completions
-	   and gets some command back that it wasn't expecting --
-	   something other than that which it just sent down.
-	   Ordinarily, that shouldn't happen, but it can happen when
-	   the scsi tape stuff gets into error handling mode, and
-	   starts using sendcmd() to try to abort commands and
-	   reset tape drives.  In that case, sendcmd may pick up
-	   completions of commands that were sent to logical drives
-	   through the block i/o system, or cciss ioctls completing, etc.
-	   In that case, we need to save those completions for later
-	   processing by the interrupt handler.
-	 */
-
-#ifdef CONFIG_CISS_SCSI_TAPE
-	struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects;
-
-	/* If it's not the scsi tape stuff doing error handling, (abort */
-	/* or reset) then we don't expect anything weird. */
-	if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) {
-#endif
-		printk(KERN_WARNING "cciss cciss%d: SendCmd "
-		       "Invalid command list address returned! (%lx)\n",
-		       ctlr, complete);
-		/* not much we can do. */
-#ifdef CONFIG_CISS_SCSI_TAPE
-		return 1;
-	}
-
-	/* We've sent down an abort or reset, but something else
-	   has completed */
-	if (srl->ncompletions >= (hba[ctlr]->nr_cmds + 2)) {
-		/* Uh oh.  No room to save it for later... */
-		printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, "
-		       "reject list overflow, command lost!\n", ctlr);
-		return 1;
-	}
-	/* Save it for later */
-	srl->complete[srl->ncompletions] = complete;
-	srl->ncompletions++;
-#endif
-	return 0;
-}
-
-/*
- * Send a command to the controller, and wait for it to complete.
- * Only used at init time.
+/* Send command c to controller h and poll for it to complete.
+ * Turns interrupts off on the board.  Used at driver init time
+ * and during SCSI error recovery.
  */
-static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num,	/* 0: address the controller,
-												   1: address logical volume log_unit,
-												   2: periph device address is scsi3addr */
-		   unsigned int log_unit,
-		   __u8 page_code, unsigned char *scsi3addr, int cmd_type)
+static int sendcmd_core(ctlr_info_t *h, CommandList_struct *c)
 {
-	CommandList_struct *c;
 	int i;
 	unsigned long complete;
-	ctlr_info_t *info_p = hba[ctlr];
+	int status = IO_ERROR;
 	u64bit buff_dma_handle;
-	int status, done = 0;
 
-	if ((c = cmd_alloc(info_p, 1)) == NULL) {
-		printk(KERN_WARNING "cciss: unable to get memory");
-		return IO_ERROR;
-	}
-	status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
-			  log_unit, page_code, scsi3addr, cmd_type);
-	if (status != IO_OK) {
-		cmd_free(info_p, c, 1);
-		return status;
-	}
-      resend_cmd1:
-	/*
-	 * Disable interrupt
-	 */
-#ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "cciss: turning intr off\n");
-#endif				/* CCISS_DEBUG */
-	info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);
+resend_cmd1:
+
+	/* Disable interrupt on the board. */
+	h->access.set_intr_mask(h, CCISS_INTR_OFF);
 
 	/* Make sure there is room in the command FIFO */
 	/* Actually it should be completely empty at this time */
@@ -2420,21 +2644,15 @@
 	/* tape side of the driver. */
 	for (i = 200000; i > 0; i--) {
 		/* if fifo isn't full go */
-		if (!(info_p->access.fifo_full(info_p))) {
-
+		if (!(h->access.fifo_full(h)))
 			break;
-		}
 		udelay(10);
 		printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
-		       " waiting!\n", ctlr);
+		       " waiting!\n", h->ctlr);
 	}
-	/*
-	 * Send the cmd
-	 */
-	info_p->access.submit_command(info_p, c);
-	done = 0;
+	h->access.submit_command(h, c); /* Send the cmd */
 	do {
-		complete = pollcomplete(ctlr);
+		complete = pollcomplete(h->ctlr);
 
 #ifdef CCISS_DEBUG
 		printk(KERN_DEBUG "cciss: command completed\n");
@@ -2443,97 +2661,102 @@
 		if (complete == 1) {
 			printk(KERN_WARNING
 			       "cciss cciss%d: SendCmd Timeout out, "
-			       "No command list address returned!\n", ctlr);
+			       "No command list address returned!\n", h->ctlr);
 			status = IO_ERROR;
-			done = 1;
 			break;
 		}
 
-		/* This will need to change for direct lookup completions */
-		if ((complete & CISS_ERROR_BIT)
-		    && (complete & ~CISS_ERROR_BIT) == c->busaddr) {
-			/* if data overrun or underun on Report command
-			   ignore it
-			 */
-			if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||
-			     (c->Request.CDB[0] == CISS_REPORT_PHYS) ||
-			     (c->Request.CDB[0] == CISS_INQUIRY)) &&
-			    ((c->err_info->CommandStatus ==
-			      CMD_DATA_OVERRUN) ||
-			     (c->err_info->CommandStatus == CMD_DATA_UNDERRUN)
-			    )) {
-				complete = c->busaddr;
-			} else {
-				if (c->err_info->CommandStatus ==
-				    CMD_UNSOLICITED_ABORT) {
-					printk(KERN_WARNING "cciss%d: "
-					       "unsolicited abort %p\n",
-					       ctlr, c);
-					if (c->retry_count < MAX_CMD_RETRIES) {
-						printk(KERN_WARNING
-						       "cciss%d: retrying %p\n",
-						       ctlr, c);
-						c->retry_count++;
-						/* erase the old error */
-						/* information */
-						memset(c->err_info, 0,
-						       sizeof
-						       (ErrorInfo_struct));
-						goto resend_cmd1;
-					} else {
-						printk(KERN_WARNING
-						       "cciss%d: retried %p too "
-						       "many times\n", ctlr, c);
-						status = IO_ERROR;
-						goto cleanup1;
-					}
-				} else if (c->err_info->CommandStatus ==
-					   CMD_UNABORTABLE) {
-					printk(KERN_WARNING
-					       "cciss%d: command could not be aborted.\n",
-					       ctlr);
-					status = IO_ERROR;
-					goto cleanup1;
-				}
-				printk(KERN_WARNING "ciss ciss%d: sendcmd"
-				       " Error %x \n", ctlr,
-				       c->err_info->CommandStatus);
-				printk(KERN_WARNING "ciss ciss%d: sendcmd"
-				       " offensive info\n"
-				       "  size %x\n   num %x   value %x\n",
-				       ctlr,
-				       c->err_info->MoreErrInfo.Invalid_Cmd.
-				       offense_size,
-				       c->err_info->MoreErrInfo.Invalid_Cmd.
-				       offense_num,
-				       c->err_info->MoreErrInfo.Invalid_Cmd.
-				       offense_value);
-				status = IO_ERROR;
-				goto cleanup1;
-			}
+		/* Make sure it's the command we're expecting. */
+		if ((complete & ~CISS_ERROR_BIT) != c->busaddr) {
+			printk(KERN_WARNING "cciss%d: Unexpected command "
+				"completion.\n", h->ctlr);
+			continue;
 		}
-		/* This will need changing for direct lookup completions */
-		if (complete != c->busaddr) {
-			if (add_sendcmd_reject(cmd, ctlr, complete) != 0) {
-				BUG();	/* we are pretty much hosed if we get here. */
+
+		/* It is our command.  If no error, we're done. */
+		if (!(complete & CISS_ERROR_BIT)) {
+			status = IO_OK;
+			break;
+		}
+
+		/* There is an error... */
+
+		/* if data overrun or underun on Report command ignore it */
+		if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||
+		     (c->Request.CDB[0] == CISS_REPORT_PHYS) ||
+		     (c->Request.CDB[0] == CISS_INQUIRY)) &&
+			((c->err_info->CommandStatus == CMD_DATA_OVERRUN) ||
+			 (c->err_info->CommandStatus == CMD_DATA_UNDERRUN))) {
+			complete = c->busaddr;
+			status = IO_OK;
+			break;
+		}
+
+		if (c->err_info->CommandStatus == CMD_UNSOLICITED_ABORT) {
+			printk(KERN_WARNING "cciss%d: unsolicited abort %p\n",
+				h->ctlr, c);
+			if (c->retry_count < MAX_CMD_RETRIES) {
+				printk(KERN_WARNING "cciss%d: retrying %p\n",
+				   h->ctlr, c);
+				c->retry_count++;
+				/* erase the old error information */
+				memset(c->err_info, 0, sizeof(c->err_info));
+				goto resend_cmd1;
 			}
-			continue;
-		} else
-			done = 1;
-	} while (!done);
+			printk(KERN_WARNING "cciss%d: retried %p too many "
+				"times\n", h->ctlr, c);
+			status = IO_ERROR;
+			break;
+		}
+
+		if (c->err_info->CommandStatus == CMD_UNABORTABLE) {
+			printk(KERN_WARNING "cciss%d: command could not be "
+				"aborted.\n", h->ctlr);
+			status = IO_ERROR;
+			break;
+		}
+
+		if (c->err_info->CommandStatus == CMD_TARGET_STATUS) {
+			status = check_target_status(h, c);
+			break;
+		}
+
+		printk(KERN_WARNING "cciss%d: sendcmd error\n", h->ctlr);
+		printk(KERN_WARNING "cmd = 0x%02x, CommandStatus = 0x%02x\n",
+			c->Request.CDB[0], c->err_info->CommandStatus);
+		status = IO_ERROR;
+		break;
+
+	} while (1);
 
-      cleanup1:
 	/* unlock the data buffer from DMA */
 	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
 	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
-	pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
+	pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
 			 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
-#ifdef CONFIG_CISS_SCSI_TAPE
-	/* if we saved some commands for later, process them now. */
-	if (info_p->scsi_rejects.ncompletions > 0)
-		do_cciss_intr(0, info_p);
-#endif
-	cmd_free(info_p, c, 1);
+	return status;
+}
+
+/*
+ * Send a command to the controller, and wait for it to complete.
+ * Used at init time, and during SCSI error recovery.
+ */
+static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
+	__u8 page_code, unsigned char *scsi3addr, int cmd_type)
+{
+	CommandList_struct *c;
+	int status;
+
+	c = cmd_alloc(hba[ctlr], 1);
+	if (!c) {
+		printk(KERN_WARNING "cciss: unable to get memory");
+		return IO_ERROR;
+	}
+	status = fill_cmd(c, cmd, ctlr, buff, size, page_code,
+		scsi3addr, cmd_type);
+	if (status == IO_OK)
+		status = sendcmd_core(hba[ctlr], c);
+	cmd_free(hba[ctlr], c, 1);
 	return status;
 }
 
@@ -2691,7 +2914,7 @@
 			printk(KERN_WARNING "cciss: cmd %p has"
 			       " completed with data underrun "
 			       "reported\n", cmd);
-			cmd->rq->data_len = cmd->err_info->ResidualCnt;
+			cmd->rq->resid_len = cmd->err_info->ResidualCnt;
 		}
 		break;
 	case CMD_DATA_OVERRUN:
@@ -2806,7 +3029,7 @@
 		goto startio;
 
       queue:
-	creq = elv_next_request(q);
+	creq = blk_peek_request(q);
 	if (!creq)
 		goto startio;
 
@@ -2815,7 +3038,7 @@
 	if ((c = cmd_alloc(h, 1)) == NULL)
 		goto full;
 
-	blkdev_dequeue_request(creq);
+	blk_start_request(creq);
 
 	spin_unlock_irq(q->queue_lock);
 
@@ -2840,10 +3063,10 @@
 	c->Request.Timeout = 0;	// Don't time out
 	c->Request.CDB[0] =
 	    (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
-	start_blk = creq->sector;
+	start_blk = blk_rq_pos(creq);
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
-	       (int)creq->nr_sectors);
+	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",
+	       (int)blk_rq_pos(creq), (int)blk_rq_sectors(creq));
 #endif				/* CCISS_DEBUG */
 
 	sg_init_table(tmp_sg, MAXSGENTRIES);
@@ -2869,8 +3092,8 @@
 		h->maxSG = seg;
 
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "cciss: Submitting %lu sectors in %d segments\n",
-	       creq->nr_sectors, seg);
+	printk(KERN_DEBUG "cciss: Submitting %u sectors in %d segments\n",
+	       blk_rq_sectors(creq), seg);
 #endif				/* CCISS_DEBUG */
 
 	c->Header.SGList = c->Header.SGTotal = seg;
@@ -2882,8 +3105,8 @@
 			c->Request.CDB[4] = (start_blk >> 8) & 0xff;
 			c->Request.CDB[5] = start_blk & 0xff;
 			c->Request.CDB[6] = 0;	// (sect >> 24) & 0xff; MSB
-			c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
-			c->Request.CDB[8] = creq->nr_sectors & 0xff;
+			c->Request.CDB[7] = (blk_rq_sectors(creq) >> 8) & 0xff;
+			c->Request.CDB[8] = blk_rq_sectors(creq) & 0xff;
 			c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
 		} else {
 			u32 upper32 = upper_32_bits(start_blk);
@@ -2898,10 +3121,10 @@
 			c->Request.CDB[7]= (start_blk >> 16) & 0xff;
 			c->Request.CDB[8]= (start_blk >>  8) & 0xff;
 			c->Request.CDB[9]= start_blk & 0xff;
-			c->Request.CDB[10]= (creq->nr_sectors >>  24) & 0xff;
-			c->Request.CDB[11]= (creq->nr_sectors >>  16) & 0xff;
-			c->Request.CDB[12]= (creq->nr_sectors >>  8) & 0xff;
-			c->Request.CDB[13]= creq->nr_sectors & 0xff;
+			c->Request.CDB[10]= (blk_rq_sectors(creq) >> 24) & 0xff;
+			c->Request.CDB[11]= (blk_rq_sectors(creq) >> 16) & 0xff;
+			c->Request.CDB[12]= (blk_rq_sectors(creq) >>  8) & 0xff;
+			c->Request.CDB[13]= blk_rq_sectors(creq) & 0xff;
 			c->Request.CDB[14] = c->Request.CDB[15] = 0;
 		}
 	} else if (blk_pc_request(creq)) {
@@ -2931,44 +3154,18 @@
 
 static inline unsigned long get_next_completion(ctlr_info_t *h)
 {
-#ifdef CONFIG_CISS_SCSI_TAPE
-	/* Any rejects from sendcmd() lying around? Process them first */
-	if (h->scsi_rejects.ncompletions == 0)
-		return h->access.command_completed(h);
-	else {
-		struct sendcmd_reject_list *srl;
-		int n;
-		srl = &h->scsi_rejects;
-		n = --srl->ncompletions;
-		/* printk("cciss%d: processing saved reject\n", h->ctlr); */
-		printk("p");
-		return srl->complete[n];
-	}
-#else
 	return h->access.command_completed(h);
-#endif
 }
 
 static inline int interrupt_pending(ctlr_info_t *h)
 {
-#ifdef CONFIG_CISS_SCSI_TAPE
-	return (h->access.intr_pending(h)
-		|| (h->scsi_rejects.ncompletions > 0));
-#else
 	return h->access.intr_pending(h);
-#endif
 }
 
 static inline long interrupt_not_for_us(ctlr_info_t *h)
 {
-#ifdef CONFIG_CISS_SCSI_TAPE
-	return (((h->access.intr_pending(h) == 0) ||
-		 (h->interrupts_enabled == 0))
-		&& (h->scsi_rejects.ncompletions == 0));
-#else
 	return (((h->access.intr_pending(h) == 0) ||
 		 (h->interrupts_enabled == 0)));
-#endif
 }
 
 static irqreturn_t do_cciss_intr(int irq, void *dev_id)
@@ -3723,12 +3920,15 @@
 	INIT_HLIST_HEAD(&hba[i]->reqQ);
 
 	if (cciss_pci_init(hba[i], pdev) != 0)
-		goto clean1;
+		goto clean0;
 
 	sprintf(hba[i]->devname, "cciss%d", i);
 	hba[i]->ctlr = i;
 	hba[i]->pdev = pdev;
 
+	if (cciss_create_hba_sysfs_entry(hba[i]))
+		goto clean0;
+
 	/* configure PCI DMA stuff */
 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
 		dac = 1;
@@ -3787,15 +3987,6 @@
 		printk(KERN_ERR "cciss: out of memory");
 		goto clean4;
 	}
-#ifdef CONFIG_CISS_SCSI_TAPE
-	hba[i]->scsi_rejects.complete =
-	    kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) *
-		    (hba[i]->nr_cmds + 5), GFP_KERNEL);
-	if (hba[i]->scsi_rejects.complete == NULL) {
-		printk(KERN_ERR "cciss: out of memory");
-		goto clean4;
-	}
-#endif
 	spin_lock_init(&hba[i]->lock);
 
 	/* Initialize the pdev driver private data.
@@ -3828,7 +4019,7 @@
 	}
 
 	return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff,
-		sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD);
+		sizeof(InquiryData_struct), 0, CTLR_LUNID, TYPE_CMD);
 	if (return_code == IO_OK) {
 		hba[i]->firm_ver[0] = inq_buff->data_byte[32];
 		hba[i]->firm_ver[1] = inq_buff->data_byte[33];
@@ -3855,9 +4046,6 @@
 
 clean4:
 	kfree(inq_buff);
-#ifdef CONFIG_CISS_SCSI_TAPE
-	kfree(hba[i]->scsi_rejects.complete);
-#endif
 	kfree(hba[i]->cmd_pool_bits);
 	if (hba[i]->cmd_pool)
 		pci_free_consistent(hba[i]->pdev,
@@ -3872,6 +4060,8 @@
 clean2:
 	unregister_blkdev(hba[i]->major, hba[i]->devname);
 clean1:
+	cciss_destroy_hba_sysfs_entry(hba[i]);
+clean0:
 	hba[i]->busy_initializing = 0;
 	/* cleanup any queues that may have been initialized */
 	for (j=0; j <= hba[i]->highest_lun; j++){
@@ -3907,8 +4097,8 @@
 	/* sendcmd will turn off interrupt, and send the flush...
 	 * To write all data in the battery backed cache to disks */
 	memset(flush_buf, 0, 4);
-	return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
-			      TYPE_CMD);
+	return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0,
+		CTLR_LUNID, TYPE_CMD);
 	if (return_code == IO_OK) {
 		printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
 	} else {
@@ -3973,15 +4163,13 @@
 	pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
 			    hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
 	kfree(hba[i]->cmd_pool_bits);
-#ifdef CONFIG_CISS_SCSI_TAPE
-	kfree(hba[i]->scsi_rejects.complete);
-#endif
 	/*
 	 * Deliberately omit pci_disable_device(): it does something nasty to
 	 * Smart Array controllers that pci_enable_device does not undo
 	 */
 	pci_release_regions(pdev);
 	pci_set_drvdata(pdev, NULL);
+	cciss_destroy_hba_sysfs_entry(hba[i]);
 	free_hba(i);
 }
 
@@ -3999,6 +4187,8 @@
  */
 static int __init cciss_init(void)
 {
+	int err;
+
 	/*
 	 * The hardware requires that commands are aligned on a 64-bit
 	 * boundary. Given that we use pci_alloc_consistent() to allocate an
@@ -4008,8 +4198,20 @@
 
 	printk(KERN_INFO DRIVER_NAME "\n");
 
+	err = bus_register(&cciss_bus_type);
+	if (err)
+		return err;
+
 	/* Register for our PCI devices */
-	return pci_register_driver(&cciss_pci_driver);
+	err = pci_register_driver(&cciss_pci_driver);
+	if (err)
+		goto err_bus_register;
+
+	return 0;
+
+err_bus_register:
+	bus_unregister(&cciss_bus_type);
+	return err;
 }
 
 static void __exit cciss_cleanup(void)
@@ -4026,6 +4228,7 @@
 		}
 	}
 	remove_proc_entry("driver/cciss", NULL);
+	bus_unregister(&cciss_bus_type);
 }
 
 static void fail_all_cmds(unsigned long ctlr)
@@ -4054,7 +4257,8 @@
 	while (!hlist_empty(&h->cmpQ)) {
 		c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
 		removeQ(c);
-		c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+		if (c->cmd_type != CMD_MSG_STALE)
+			c->err_info->CommandStatus = CMD_HARDWARE_ERR;
 		if (c->cmd_type == CMD_RWREQ) {
 			complete_command(h, c, 0);
 		} else if (c->cmd_type == CMD_IOCTL_PEND)
diff -druN linux-libre-2.6.30-gnu/drivers/block/cciss_cmd.h linux-libre-2.6.31-gnu/drivers/block/cciss_cmd.h
--- linux-libre-2.6.30-gnu/drivers/block/cciss_cmd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/cciss_cmd.h	2009-09-09 18:13:59.000000000 -0400
@@ -217,6 +217,8 @@
   LogDevAddr_struct  LogDev;
 } LUNAddr_struct;
 
+#define CTLR_LUNID "\0\0\0\0\0\0\0\0"
+
 typedef struct _CommandListHeader_struct {
   BYTE              ReplyQueue;
   BYTE              SGList;
@@ -272,6 +274,7 @@
 #define CMD_SCSI	0x03
 #define CMD_MSG_DONE	0x04
 #define CMD_MSG_TIMEOUT 0x05
+#define CMD_MSG_STALE	0xff
 
 /* This structure needs to be divisible by 8 for new
  * indexing method.
diff -druN linux-libre-2.6.30-gnu/drivers/block/cciss.h linux-libre-2.6.31-gnu/drivers/block/cciss.h
--- linux-libre-2.6.30-gnu/drivers/block/cciss.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/cciss.h	2009-09-09 18:13:59.000000000 -0400
@@ -11,6 +11,11 @@
 
 #define IO_OK		0
 #define IO_ERROR	1
+#define IO_NEEDS_RETRY  3
+
+#define VENDOR_LEN	8
+#define MODEL_LEN	16
+#define REV_LEN		4
 
 struct ctlr_info;
 typedef struct ctlr_info ctlr_info_t;
@@ -34,23 +39,20 @@
 	int 	cylinders;
 	int	raid_level; /* set to -1 to indicate that
 			     * the drive is not in use/configured
-			    */
-	int	busy_configuring; /*This is set when the drive is being removed
-				   *to prevent it from being opened or it's queue
-				   *from being started.
-				  */
-	__u8 serial_no[16]; /* from inquiry page 0x83, */
-			    /* not necc. null terminated. */
+			     */
+	int	busy_configuring; /* This is set when a drive is being removed
+				   * to prevent it from being opened or it's
+				   * queue from being started.
+				   */
+	struct	device dev;
+	__u8 serial_no[16]; /* from inquiry page 0x83,
+			     * not necc. null terminated.
+			     */
+	char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */
+	char model[MODEL_LEN + 1];   /* SCSI model string */
+	char rev[REV_LEN + 1];       /* SCSI revision string */
 } drive_info_struct;
 
-#ifdef CONFIG_CISS_SCSI_TAPE
-
-struct sendcmd_reject_list {
-	int ncompletions;
-	unsigned long *complete; /* array of NR_CMDS tags */
-};
-
-#endif
 struct ctlr_info 
 {
 	int	ctlr;
@@ -118,11 +120,11 @@
 	void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
 	/* list of block side commands the scsi error handling sucked up */
 	/* and saved for later processing */
-	struct sendcmd_reject_list scsi_rejects;
 #endif
 	unsigned char alive;
 	struct completion *rescan_wait;
 	struct task_struct *cciss_scan_thread;
+	struct device dev;
 };
 
 /*  Defining the diffent access_menthods */
diff -druN linux-libre-2.6.30-gnu/drivers/block/cciss_scsi.c linux-libre-2.6.31-gnu/drivers/block/cciss_scsi.c
--- linux-libre-2.6.30-gnu/drivers/block/cciss_scsi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/cciss_scsi.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,20 +44,13 @@
 #define CCISS_ABORT_MSG 0x00
 #define CCISS_RESET_MSG 0x01
 
-/* some prototypes... */ 
-static int sendcmd(
-	__u8	cmd,
-	int	ctlr,
-	void	*buff,
-	size_t	size,
-	unsigned int use_unit_num, /* 0: address the controller,
-				      1: address logical volume log_unit, 
-				      2: address is in scsi3addr */
-	unsigned int log_unit,
-	__u8	page_code,
-	unsigned char *scsi3addr,
+static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
+	size_t size,
+	__u8 page_code, unsigned char *scsi3addr,
 	int cmd_type);
 
+static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool);
+static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool);
 
 static int cciss_scsi_proc_info(
 		struct Scsi_Host *sh,
@@ -1575,6 +1568,75 @@
 	CPQ_TAPE_UNLOCK(ctlr, flags);
 }
 
+static int wait_for_device_to_become_ready(ctlr_info_t *h,
+	unsigned char lunaddr[])
+{
+	int rc;
+	int count = 0;
+	int waittime = HZ;
+	CommandList_struct *c;
+
+	c = cmd_alloc(h, 1);
+	if (!c) {
+		printk(KERN_WARNING "cciss%d: out of memory in "
+			"wait_for_device_to_become_ready.\n", h->ctlr);
+		return IO_ERROR;
+	}
+
+	/* Send test unit ready until device ready, or give up. */
+	while (count < 20) {
+
+		/* Wait for a bit.  do this first, because if we send
+		 * the TUR right away, the reset will just abort it.
+		 */
+		schedule_timeout_uninterruptible(waittime);
+		count++;
+
+		/* Increase wait time with each try, up to a point. */
+		if (waittime < (HZ * 30))
+			waittime = waittime * 2;
+
+		/* Send the Test Unit Ready */
+		rc = fill_cmd(c, TEST_UNIT_READY, h->ctlr, NULL, 0, 0,
+			lunaddr, TYPE_CMD);
+		if (rc == 0)
+			rc = sendcmd_withirq_core(h, c, 0);
+
+		(void) process_sendcmd_error(h, c);
+
+		if (rc != 0)
+			goto retry_tur;
+
+		if (c->err_info->CommandStatus == CMD_SUCCESS)
+			break;
+
+		if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
+			c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
+			if (c->err_info->SenseInfo[2] == NO_SENSE)
+				break;
+			if (c->err_info->SenseInfo[2] == UNIT_ATTENTION) {
+				unsigned char asc;
+				asc = c->err_info->SenseInfo[12];
+				check_for_unit_attention(h, c);
+				if (asc == POWER_OR_RESET)
+					break;
+			}
+		}
+retry_tur:
+		printk(KERN_WARNING "cciss%d: Waiting %d secs "
+			"for device to become ready.\n",
+			h->ctlr, waittime / HZ);
+		rc = 1; /* device not ready. */
+	}
+
+	if (rc)
+		printk("cciss%d: giving up on device.\n", h->ctlr);
+	else
+		printk(KERN_WARNING "cciss%d: device is ready.\n", h->ctlr);
+
+	cmd_free(h, c, 1);
+	return rc;
+}
 
 /* Need at least one of these error handlers to keep ../scsi/hosts.c from 
  * complaining.  Doing a host- or bus-reset can't do anything good here. 
@@ -1591,6 +1653,7 @@
 {
 	int rc;
 	CommandList_struct *cmd_in_trouble;
+	unsigned char lunaddr[8];
 	ctlr_info_t **c;
 	int ctlr;
 
@@ -1600,19 +1663,15 @@
 		return FAILED;
 	ctlr = (*c)->ctlr;
 	printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr);
-
 	/* find the command that's giving us trouble */
 	cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble;
-	if (cmd_in_trouble == NULL) { /* paranoia */
+	if (cmd_in_trouble == NULL) /* paranoia */
 		return FAILED;
-	}
+	memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8);
 	/* send a reset to the SCSI LUN which the command was sent to */
-	rc = sendcmd(CCISS_RESET_MSG, ctlr, NULL, 0, 2, 0, 0, 
-		(unsigned char *) &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 
+	rc = sendcmd_withirq(CCISS_RESET_MSG, ctlr, NULL, 0, 0, lunaddr,
 		TYPE_MSG);
-	/* sendcmd turned off interrupts on the board, turn 'em back on. */
-	(*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
-	if (rc == 0)
+	if (rc == 0 && wait_for_device_to_become_ready(*c, lunaddr) == 0)
 		return SUCCESS;
 	printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr);
 	return FAILED;
@@ -1622,6 +1681,7 @@
 {
 	int rc;
 	CommandList_struct *cmd_to_abort;
+	unsigned char lunaddr[8];
 	ctlr_info_t **c;
 	int ctlr;
 
@@ -1636,12 +1696,9 @@
 	cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble;
 	if (cmd_to_abort == NULL) /* paranoia */
 		return FAILED;
-	rc = sendcmd(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag, 
-		0, 2, 0, 0, 
-		(unsigned char *) &cmd_to_abort->Header.LUN.LunAddrBytes[0], 
-		TYPE_MSG);
-	/* sendcmd turned off interrupts on the board, turn 'em back on. */
-	(*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
+	memcpy(lunaddr, &cmd_to_abort->Header.LUN.LunAddrBytes[0], 8);
+	rc = sendcmd_withirq(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag,
+		0, 0, lunaddr, TYPE_MSG);
 	if (rc == 0)
 		return SUCCESS;
 	return FAILED;
diff -druN linux-libre-2.6.30-gnu/drivers/block/cpqarray.c linux-libre-2.6.31-gnu/drivers/block/cpqarray.c
--- linux-libre-2.6.30-gnu/drivers/block/cpqarray.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/cpqarray.c	2009-09-09 18:13:59.000000000 -0400
@@ -474,7 +474,7 @@
 		disk->fops = &ida_fops;
 		if (j && !drv->nr_blks)
 			continue;
-		blk_queue_hardsect_size(hba[i]->queue, drv->blk_size);
+		blk_queue_logical_block_size(hba[i]->queue, drv->blk_size);
 		set_capacity(disk, drv->nr_blks);
 		disk->queue = hba[i]->queue;
 		disk->private_data = drv;
@@ -903,7 +903,7 @@
 		goto startio;
 
 queue_next:
-	creq = elv_next_request(q);
+	creq = blk_peek_request(q);
 	if (!creq)
 		goto startio;
 
@@ -912,17 +912,18 @@
 	if ((c = cmd_alloc(h,1)) == NULL)
 		goto startio;
 
-	blkdev_dequeue_request(creq);
+	blk_start_request(creq);
 
 	c->ctlr = h->ctlr;
 	c->hdr.unit = (drv_info_t *)(creq->rq_disk->private_data) - h->drv;
 	c->hdr.size = sizeof(rblk_t) >> 2;
 	c->size += sizeof(rblk_t);
 
-	c->req.hdr.blk = creq->sector;
+	c->req.hdr.blk = blk_rq_pos(creq);
 	c->rq = creq;
 DBGPX(
-	printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors);
+	printk("sector=%d, nr_sectors=%u\n",
+	       blk_rq_pos(creq), blk_rq_sectors(creq));
 );
 	sg_init_table(tmp_sg, SG_MAX);
 	seg = blk_rq_map_sg(q, creq, tmp_sg);
@@ -940,9 +941,9 @@
 						 tmp_sg[i].offset,
 						 tmp_sg[i].length, dir);
 	}
-DBGPX(	printk("Submitting %d sectors in %d segments\n", creq->nr_sectors, seg); );
+DBGPX(	printk("Submitting %u sectors in %d segments\n", blk_rq_sectors(creq), seg); );
 	c->req.hdr.sg_cnt = seg;
-	c->req.hdr.blk_cnt = creq->nr_sectors;
+	c->req.hdr.blk_cnt = blk_rq_sectors(creq);
 	c->req.hdr.cmd = (rq_data_dir(creq) == READ) ? IDA_READ : IDA_WRITE;
 	c->type = CMD_RWREQ;
 
@@ -1024,8 +1025,7 @@
 				cmd->req.sg[i].size, ddir);
 
 	DBGPX(printk("Done with %p\n", rq););
-	if (__blk_end_request(rq, error, blk_rq_bytes(rq)))
-		BUG();
+	__blk_end_request_all(rq, error);
 }
 
 /*
@@ -1546,7 +1546,7 @@
 		drv_info_t *drv = &host->drv[i];
 		if (i && !drv->nr_blks)
 			continue;
-		blk_queue_hardsect_size(host->queue, drv->blk_size);
+		blk_queue_logical_block_size(host->queue, drv->blk_size);
 		set_capacity(disk, drv->nr_blks);
 		disk->queue = host->queue;
 		disk->private_data = drv;
diff -druN linux-libre-2.6.30-gnu/drivers/block/DAC960.c linux-libre-2.6.31-gnu/drivers/block/DAC960.c
--- linux-libre-2.6.30-gnu/drivers/block/DAC960.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/DAC960.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/proc_fs.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
@@ -3321,7 +3322,7 @@
 	DAC960_Command_T *Command;
 
    while(1) {
-	Request = elv_next_request(req_q);
+	Request = blk_peek_request(req_q);
 	if (!Request)
 		return 1;
 
@@ -3338,10 +3339,10 @@
 	}
 	Command->Completion = Request->end_io_data;
 	Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
-	Command->BlockNumber = Request->sector;
-	Command->BlockCount = Request->nr_sectors;
+	Command->BlockNumber = blk_rq_pos(Request);
+	Command->BlockCount = blk_rq_sectors(Request);
 	Command->Request = Request;
-	blkdev_dequeue_request(Request);
+	blk_start_request(Request);
 	Command->SegmentCount = blk_rq_map_sg(req_q,
 		  Command->Request, Command->cmd_sglist);
 	/* pci_map_sg MAY change the value of SegCount */
@@ -3431,7 +3432,7 @@
    * successfully as possible.
    */
   Command->SegmentCount = 1;
-  Command->BlockNumber = Request->sector;
+  Command->BlockNumber = blk_rq_pos(Request);
   Command->BlockCount = 1;
   DAC960_QueueReadWriteCommand(Command);
   return;
diff -druN linux-libre-2.6.30-gnu/drivers/block/floppy.c linux-libre-2.6.31-gnu/drivers/block/floppy.c
--- linux-libre-2.6.30-gnu/drivers/block/floppy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/floppy.c	2009-09-09 18:13:59.000000000 -0400
@@ -931,7 +931,7 @@
 	del_timer(&fd_timeout);
 	cont = NULL;
 	clear_bit(0, &fdc_busy);
-	if (elv_next_request(floppy_queue))
+	if (current_req || blk_peek_request(floppy_queue))
 		do_fd_request(floppy_queue);
 	spin_unlock_irqrestore(&floppy_lock, flags);
 	wake_up(&fdc_wait);
@@ -2303,7 +2303,7 @@
 
 	/* current_count_sectors can be zero if transfer failed */
 	if (error)
-		nr_sectors = req->current_nr_sectors;
+		nr_sectors = blk_rq_cur_sectors(req);
 	if (__blk_end_request(req, error, nr_sectors << 9))
 		return;
 
@@ -2332,7 +2332,7 @@
 	if (uptodate) {
 		/* maintain values for invalidation on geometry
 		 * change */
-		block = current_count_sectors + req->sector;
+		block = current_count_sectors + blk_rq_pos(req);
 		INFBOUND(DRS->maxblock, block);
 		if (block > _floppy->sect)
 			DRS->maxtrack = 1;
@@ -2346,10 +2346,10 @@
 			/* record write error information */
 			DRWE->write_errors++;
 			if (DRWE->write_errors == 1) {
-				DRWE->first_error_sector = req->sector;
+				DRWE->first_error_sector = blk_rq_pos(req);
 				DRWE->first_error_generation = DRS->generation;
 			}
-			DRWE->last_error_sector = req->sector;
+			DRWE->last_error_sector = blk_rq_pos(req);
 			DRWE->last_error_generation = DRS->generation;
 		}
 		spin_lock_irqsave(q->queue_lock, flags);
@@ -2503,24 +2503,23 @@
 
 	max_sector = transfer_size(ssize,
 				   min(max_sector, max_sector_2),
-				   current_req->nr_sectors);
+				   blk_rq_sectors(current_req));
 
 	if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
-	    buffer_max > fsector_t + current_req->nr_sectors)
+	    buffer_max > fsector_t + blk_rq_sectors(current_req))
 		current_count_sectors = min_t(int, buffer_max - fsector_t,
-					      current_req->nr_sectors);
+					      blk_rq_sectors(current_req));
 
 	remaining = current_count_sectors << 9;
 #ifdef FLOPPY_SANITY_CHECK
-	if ((remaining >> 9) > current_req->nr_sectors &&
-	    CT(COMMAND) == FD_WRITE) {
+	if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) {
 		DPRINT("in copy buffer\n");
 		printk("current_count_sectors=%ld\n", current_count_sectors);
 		printk("remaining=%d\n", remaining >> 9);
-		printk("current_req->nr_sectors=%ld\n",
-		       current_req->nr_sectors);
+		printk("current_req->nr_sectors=%u\n",
+		       blk_rq_sectors(current_req));
 		printk("current_req->current_nr_sectors=%u\n",
-		       current_req->current_nr_sectors);
+		       blk_rq_cur_sectors(current_req));
 		printk("max_sector=%d\n", max_sector);
 		printk("ssize=%d\n", ssize);
 	}
@@ -2530,7 +2529,7 @@
 
 	dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
 
-	size = current_req->current_nr_sectors << 9;
+	size = blk_rq_cur_bytes(current_req);
 
 	rq_for_each_segment(bv, current_req, iter) {
 		if (!remaining)
@@ -2648,10 +2647,10 @@
 
 	max_sector = _floppy->sect * _floppy->head;
 
-	TRACK = (int)current_req->sector / max_sector;
-	fsector_t = (int)current_req->sector % max_sector;
+	TRACK = (int)blk_rq_pos(current_req) / max_sector;
+	fsector_t = (int)blk_rq_pos(current_req) % max_sector;
 	if (_floppy->track && TRACK >= _floppy->track) {
-		if (current_req->current_nr_sectors & 1) {
+		if (blk_rq_cur_sectors(current_req) & 1) {
 			current_count_sectors = 1;
 			return 1;
 		} else
@@ -2669,7 +2668,7 @@
 		if (fsector_t >= max_sector) {
 			current_count_sectors =
 			    min_t(int, _floppy->sect - fsector_t,
-				  current_req->nr_sectors);
+				  blk_rq_sectors(current_req));
 			return 1;
 		}
 		SIZECODE = 2;
@@ -2720,7 +2719,7 @@
 
 	in_sector_offset = (fsector_t % _floppy->sect) % ssize;
 	aligned_sector_t = fsector_t - in_sector_offset;
-	max_size = current_req->nr_sectors;
+	max_size = blk_rq_sectors(current_req);
 	if ((raw_cmd->track == buffer_track) &&
 	    (current_drive == buffer_drive) &&
 	    (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
@@ -2729,10 +2728,10 @@
 			copy_buffer(1, max_sector, buffer_max);
 			return 1;
 		}
-	} else if (in_sector_offset || current_req->nr_sectors < ssize) {
+	} else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) {
 		if (CT(COMMAND) == FD_WRITE) {
-			if (fsector_t + current_req->nr_sectors > ssize &&
-			    fsector_t + current_req->nr_sectors < ssize + ssize)
+			if (fsector_t + blk_rq_sectors(current_req) > ssize &&
+			    fsector_t + blk_rq_sectors(current_req) < ssize + ssize)
 				max_size = ssize + ssize;
 			else
 				max_size = ssize;
@@ -2776,7 +2775,7 @@
 		    (indirect * 2 > direct * 3 &&
 		     *errors < DP->max_errors.read_track && ((!probing
 		       || (DP->read_track & (1 << DRS->probed_format)))))) {
-			max_size = current_req->nr_sectors;
+			max_size = blk_rq_sectors(current_req);
 		} else {
 			raw_cmd->kernel_data = current_req->buffer;
 			raw_cmd->length = current_count_sectors << 9;
@@ -2801,7 +2800,7 @@
 	    fsector_t > buffer_max ||
 	    fsector_t < buffer_min ||
 	    ((CT(COMMAND) == FD_READ ||
-	      (!in_sector_offset && current_req->nr_sectors >= ssize)) &&
+	      (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) &&
 	     max_sector > 2 * max_buffer_sectors + buffer_min &&
 	     max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
 	    /* not enough space */
@@ -2879,8 +2878,8 @@
 				printk("write\n");
 			return 0;
 		}
-	} else if (raw_cmd->length > current_req->nr_sectors << 9 ||
-		   current_count_sectors > current_req->nr_sectors) {
+	} else if (raw_cmd->length > blk_rq_bytes(current_req) ||
+		   current_count_sectors > blk_rq_sectors(current_req)) {
 		DPRINT("buffer overrun in direct transfer\n");
 		return 0;
 	} else if (raw_cmd->length < current_count_sectors << 9) {
@@ -2913,7 +2912,7 @@
 			struct request *req;
 
 			spin_lock_irq(floppy_queue->queue_lock);
-			req = elv_next_request(floppy_queue);
+			req = blk_fetch_request(floppy_queue);
 			spin_unlock_irq(floppy_queue->queue_lock);
 			if (!req) {
 				do_floppy = NULL;
@@ -2990,8 +2989,9 @@
 	if (usage_count == 0) {
 		printk("warning: usage count=0, current_req=%p exiting\n",
 		       current_req);
-		printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
-		       current_req->cmd_type, current_req->cmd_flags);
+		printk("sect=%ld type=%x flags=%x\n",
+		       (long)blk_rq_pos(current_req), current_req->cmd_type,
+		       current_req->cmd_flags);
 		return;
 	}
 	if (test_bit(0, &fdc_busy)) {
@@ -3327,7 +3327,10 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		mutex_lock(&open_lock);
-		LOCK_FDC(drive, 1);
+		if (lock_fdc(drive, 1)) {
+			mutex_unlock(&open_lock);
+			return -EINTR;
+		}
 		floppy_type[type] = *g;
 		floppy_type[type].name = "user format";
 		for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
@@ -4148,6 +4151,24 @@
 {
 }
 
+static int floppy_resume(struct platform_device *dev)
+{
+	int fdc;
+
+	for (fdc = 0; fdc < N_FDC; fdc++)
+		if (FDCS->address != -1)
+			user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
+
+	return 0;
+}
+
+static struct platform_driver floppy_driver = {
+	.resume = floppy_resume,
+	.driver = {
+		.name = "floppy",
+	},
+};
+
 static struct platform_device floppy_device[N_DRIVE];
 
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
@@ -4196,10 +4217,14 @@
 	if (err)
 		goto out_put_disk;
 
+	err = platform_driver_register(&floppy_driver);
+	if (err)
+		goto out_unreg_blkdev;
+
 	floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
 	if (!floppy_queue) {
 		err = -ENOMEM;
-		goto out_unreg_blkdev;
+		goto out_unreg_driver;
 	}
 	blk_queue_max_sectors(floppy_queue, 64);
 
@@ -4346,6 +4371,8 @@
 out_unreg_region:
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 	blk_cleanup_queue(floppy_queue);
+out_unreg_driver:
+	platform_driver_unregister(&floppy_driver);
 out_unreg_blkdev:
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 out_put_disk:
@@ -4566,6 +4593,7 @@
 
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
+	platform_driver_unregister(&floppy_driver);
 
 	for (drive = 0; drive < N_DRIVE; drive++) {
 		del_timer_sync(&motor_off_timer[drive]);
diff -druN linux-libre-2.6.30-gnu/drivers/block/hd.c linux-libre-2.6.31-gnu/drivers/block/hd.c
--- linux-libre-2.6.30-gnu/drivers/block/hd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/hd.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,10 +98,7 @@
 
 static DEFINE_SPINLOCK(hd_lock);
 static struct request_queue *hd_queue;
-
-#define MAJOR_NR HD_MAJOR
-#define QUEUE (hd_queue)
-#define CURRENT elv_next_request(hd_queue)
+static struct request *hd_req;
 
 #define TIMEOUT_VALUE	(6*HZ)
 #define	HD_DELAY	0
@@ -195,11 +192,24 @@
 	NR_HD = hdind+1;
 }
 
+static bool hd_end_request(int err, unsigned int bytes)
+{
+	if (__blk_end_request(hd_req, err, bytes))
+		return true;
+	hd_req = NULL;
+	return false;
+}
+
+static bool hd_end_request_cur(int err)
+{
+	return hd_end_request(err, blk_rq_cur_bytes(hd_req));
+}
+
 static void dump_status(const char *msg, unsigned int stat)
 {
 	char *name = "hd?";
-	if (CURRENT)
-		name = CURRENT->rq_disk->disk_name;
+	if (hd_req)
+		name = hd_req->rq_disk->disk_name;
 
 #ifdef VERBOSE_ERRORS
 	printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
@@ -227,8 +237,8 @@
 		if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
 			printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
 				inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
-			if (CURRENT)
-				printk(", sector=%ld", CURRENT->sector);
+			if (hd_req)
+				printk(", sector=%ld", blk_rq_pos(hd_req));
 		}
 		printk("\n");
 	}
@@ -406,11 +416,12 @@
  */
 static void bad_rw_intr(void)
 {
-	struct request *req = CURRENT;
+	struct request *req = hd_req;
+
 	if (req != NULL) {
 		struct hd_i_struct *disk = req->rq_disk->private_data;
 		if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
-			end_request(req, 0);
+			hd_end_request_cur(-EIO);
 			disk->special_op = disk->recalibrate = 1;
 		} else if (req->errors % RESET_FREQ == 0)
 			reset = 1;
@@ -452,37 +463,30 @@
 	bad_rw_intr();
 	hd_request();
 	return;
+
 ok_to_read:
-	req = CURRENT;
+	req = hd_req;
 	insw(HD_DATA, req->buffer, 256);
-	req->sector++;
-	req->buffer += 512;
-	req->errors = 0;
-	i = --req->nr_sectors;
-	--req->current_nr_sectors;
 #ifdef DEBUG
-	printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
-		req->rq_disk->disk_name, req->sector, req->nr_sectors,
-		req->buffer+512);
+	printk("%s: read: sector %ld, remaining = %u, buffer=%p\n",
+	       req->rq_disk->disk_name, blk_rq_pos(req) + 1,
+	       blk_rq_sectors(req) - 1, req->buffer+512);
 #endif
-	if (req->current_nr_sectors <= 0)
-		end_request(req, 1);
-	if (i > 0) {
+	if (hd_end_request(0, 512)) {
 		SET_HANDLER(&read_intr);
 		return;
 	}
+
 	(void) inb_p(HD_STATUS);
 #if (HD_DELAY > 0)
 	last_req = read_timer();
 #endif
-	if (elv_next_request(QUEUE))
-		hd_request();
-	return;
+	hd_request();
 }
 
 static void write_intr(void)
 {
-	struct request *req = CURRENT;
+	struct request *req = hd_req;
 	int i;
 	int retries = 100000;
 
@@ -492,30 +496,25 @@
 			continue;
 		if (!OK_STATUS(i))
 			break;
-		if ((req->nr_sectors <= 1) || (i & DRQ_STAT))
+		if ((blk_rq_sectors(req) <= 1) || (i & DRQ_STAT))
 			goto ok_to_write;
 	} while (--retries > 0);
 	dump_status("write_intr", i);
 	bad_rw_intr();
 	hd_request();
 	return;
+
 ok_to_write:
-	req->sector++;
-	i = --req->nr_sectors;
-	--req->current_nr_sectors;
-	req->buffer += 512;
-	if (!i || (req->bio && req->current_nr_sectors <= 0))
-		end_request(req, 1);
-	if (i > 0) {
+	if (hd_end_request(0, 512)) {
 		SET_HANDLER(&write_intr);
 		outsw(HD_DATA, req->buffer, 256);
-	} else {
+		return;
+	}
+
 #if (HD_DELAY > 0)
-		last_req = read_timer();
+	last_req = read_timer();
 #endif
-		hd_request();
-	}
-	return;
+	hd_request();
 }
 
 static void recal_intr(void)
@@ -537,18 +536,18 @@
 
 	do_hd = NULL;
 
-	if (!CURRENT)
+	if (!hd_req)
 		return;
 
 	spin_lock_irq(hd_queue->queue_lock);
 	reset = 1;
-	name = CURRENT->rq_disk->disk_name;
+	name = hd_req->rq_disk->disk_name;
 	printk("%s: timeout\n", name);
-	if (++CURRENT->errors >= MAX_ERRORS) {
+	if (++hd_req->errors >= MAX_ERRORS) {
 #ifdef DEBUG
 		printk("%s: too many errors\n", name);
 #endif
-		end_request(CURRENT, 0);
+		hd_end_request_cur(-EIO);
 	}
 	hd_request();
 	spin_unlock_irq(hd_queue->queue_lock);
@@ -563,7 +562,7 @@
 	}
 	if (disk->head > 16) {
 		printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
-		end_request(req, 0);
+		hd_end_request_cur(-EIO);
 	}
 	disk->special_op = 0;
 	return 1;
@@ -590,24 +589,27 @@
 repeat:
 	del_timer(&device_timer);
 
-	req = CURRENT;
-	if (!req) {
-		do_hd = NULL;
-		return;
+	if (!hd_req) {
+		hd_req = blk_fetch_request(hd_queue);
+		if (!hd_req) {
+			do_hd = NULL;
+			return;
+		}
 	}
+	req = hd_req;
 
 	if (reset) {
 		reset_hd();
 		return;
 	}
 	disk = req->rq_disk->private_data;
-	block = req->sector;
-	nsect = req->nr_sectors;
+	block = blk_rq_pos(req);
+	nsect = blk_rq_sectors(req);
 	if (block >= get_capacity(req->rq_disk) ||
 	    ((block+nsect) > get_capacity(req->rq_disk))) {
 		printk("%s: bad access: block=%d, count=%d\n",
 			req->rq_disk->disk_name, block, nsect);
-		end_request(req, 0);
+		hd_end_request_cur(-EIO);
 		goto repeat;
 	}
 
@@ -647,7 +649,7 @@
 			break;
 		default:
 			printk("unknown hd-command\n");
-			end_request(req, 0);
+			hd_end_request_cur(-EIO);
 			break;
 		}
 	}
@@ -708,19 +710,19 @@
 {
 	int drive;
 
-	if (register_blkdev(MAJOR_NR, "hd"))
+	if (register_blkdev(HD_MAJOR, "hd"))
 		return -1;
 
 	hd_queue = blk_init_queue(do_hd_request, &hd_lock);
 	if (!hd_queue) {
-		unregister_blkdev(MAJOR_NR, "hd");
+		unregister_blkdev(HD_MAJOR, "hd");
 		return -ENOMEM;
 	}
 
 	blk_queue_max_sectors(hd_queue, 255);
 	init_timer(&device_timer);
 	device_timer.function = hd_times_out;
-	blk_queue_hardsect_size(hd_queue, 512);
+	blk_queue_logical_block_size(hd_queue, 512);
 
 	if (!NR_HD) {
 		/*
@@ -747,7 +749,7 @@
 		struct hd_i_struct *p = &hd_info[drive];
 		if (!disk)
 			goto Enomem;
-		disk->major = MAJOR_NR;
+		disk->major = HD_MAJOR;
 		disk->first_minor = drive << 6;
 		disk->fops = &hd_fops;
 		sprintf(disk->disk_name, "hd%c", 'a'+drive);
@@ -791,7 +793,7 @@
 	NR_HD = 0;
 out:
 	del_timer(&device_timer);
-	unregister_blkdev(MAJOR_NR, "hd");
+	unregister_blkdev(HD_MAJOR, "hd");
 	blk_cleanup_queue(hd_queue);
 	return -1;
 Enomem:
diff -druN linux-libre-2.6.30-gnu/drivers/block/Kconfig linux-libre-2.6.31-gnu/drivers/block/Kconfig
--- linux-libre-2.6.30-gnu/drivers/block/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -112,7 +112,7 @@
 	  with up to 1 GB of data. This drive will also read standard CD ROM
 	  disks. Select this option to access any disks in your GD ROM drive.
 	  Most users will want to say "Y" here.
-	  You can also build this as a module which will be called gdrom.ko
+	  You can also build this as a module which will be called gdrom.
 
 source "drivers/block/paride/Kconfig"
 
@@ -298,6 +298,22 @@
 
 	  If unsure, say N.
 
+config BLK_DEV_OSD
+	tristate "OSD object-as-blkdev support"
+	depends on SCSI_OSD_ULD
+	---help---
+	  Saying Y or M here will allow the exporting of a single SCSI
+	  OSD (object-based storage) object as a Linux block device.
+
+	  For example, if you create a 2G object on an OSD device,
+	  you can then use this module to present that 2G object as
+	  a Linux block device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called osdblk.
+
+	  If unsure, say N.
+
 config BLK_DEV_SX8
 	tristate "Promise SATA SX8 support"
 	depends on PCI
@@ -412,7 +428,7 @@
 
 config MG_DISK
 	tristate "mGine mflash, gflash support"
-	depends on ARM && ATA && GPIOLIB
+	depends on ARM && GPIOLIB
 	help
 	  mGine mFlash(gFlash) block device driver
 
@@ -438,7 +454,7 @@
 
 config XILINX_SYSACE
 	tristate "Xilinx SystemACE support"
-	depends on 4xx
+	depends on 4xx || MICROBLAZE
 	help
 	  Include support for the Xilinx SystemACE CompactFlash interface
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/loop.c linux-libre-2.6.31-gnu/drivers/block/loop.c
--- linux-libre-2.6.30-gnu/drivers/block/loop.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/loop.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,7 +61,6 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/loop.h>
@@ -511,11 +510,7 @@
  */
 static void loop_add_bio(struct loop_device *lo, struct bio *bio)
 {
-	if (lo->lo_biotail) {
-		lo->lo_biotail->bi_next = bio;
-		lo->lo_biotail = bio;
-	} else
-		lo->lo_bio = lo->lo_biotail = bio;
+	bio_list_add(&lo->lo_bio_list, bio);
 }
 
 /*
@@ -523,16 +518,7 @@
  */
 static struct bio *loop_get_bio(struct loop_device *lo)
 {
-	struct bio *bio;
-
-	if ((bio = lo->lo_bio)) {
-		if (bio == lo->lo_biotail)
-			lo->lo_biotail = NULL;
-		lo->lo_bio = bio->bi_next;
-		bio->bi_next = NULL;
-	}
-
-	return bio;
+	return bio_list_pop(&lo->lo_bio_list);
 }
 
 static int loop_make_request(struct request_queue *q, struct bio *old_bio)
@@ -609,12 +595,13 @@
 
 	set_user_nice(current, -20);
 
-	while (!kthread_should_stop() || lo->lo_bio) {
+	while (!kthread_should_stop() || !bio_list_empty(&lo->lo_bio_list)) {
 
 		wait_event_interruptible(lo->lo_event,
-				lo->lo_bio || kthread_should_stop());
+				!bio_list_empty(&lo->lo_bio_list) ||
+				kthread_should_stop());
 
-		if (!lo->lo_bio)
+		if (bio_list_empty(&lo->lo_bio_list))
 			continue;
 		spin_lock_irq(&lo->lo_lock);
 		bio = loop_get_bio(lo);
@@ -721,10 +708,6 @@
 	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
 		goto out_putf;
 
-	/* new backing store needs to support loop (eg splice_read) */
-	if (!inode->i_fop->splice_read)
-		goto out_putf;
-
 	/* size of the new backing store needs to be the same */
 	if (get_loop_size(lo, file) != get_loop_size(lo, old_file))
 		goto out_putf;
@@ -800,12 +783,7 @@
 	error = -EINVAL;
 	if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
 		const struct address_space_operations *aops = mapping->a_ops;
-		/*
-		 * If we can't read - sorry. If we only can't write - well,
-		 * it's going to be read-only.
-		 */
-		if (!file->f_op->splice_read)
-			goto out_putf;
+
 		if (aops->write_begin)
 			lo_flags |= LO_FLAGS_USE_AOPS;
 		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
@@ -841,7 +819,7 @@
 	lo->old_gfp_mask = mapping_gfp_mask(mapping);
 	mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
 
-	lo->lo_bio = lo->lo_biotail = NULL;
+	bio_list_init(&lo->lo_bio_list);
 
 	/*
 	 * set queue make_request_fn, and add limits based on lower level
diff -druN linux-libre-2.6.30-gnu/drivers/block/Makefile linux-libre-2.6.31-gnu/drivers/block/Makefile
--- linux-libre-2.6.30-gnu/drivers/block/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,7 @@
 obj-$(CONFIG_CDROM_PKTCDVD)	+= pktcdvd.o
 obj-$(CONFIG_MG_DISK)		+= mg_disk.o
 obj-$(CONFIG_SUNVDC)		+= sunvdc.o
+obj-$(CONFIG_BLK_DEV_OSD)	+= osdblk.o
 
 obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
 obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
diff -druN linux-libre-2.6.30-gnu/drivers/block/mg_disk.c linux-libre-2.6.31-gnu/drivers/block/mg_disk.c
--- linux-libre-2.6.30-gnu/drivers/block/mg_disk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/mg_disk.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
-#include <linux/libata.h>
+#include <linux/ata.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
@@ -26,62 +26,184 @@
 
 #define MG_RES_SEC (CONFIG_MG_DISK_RES << 1)
 
+/* name for block device */
+#define MG_DISK_NAME "mgd"
+
+#define MG_DISK_MAJ 0
+#define MG_DISK_MAX_PART 16
+#define MG_SECTOR_SIZE 512
+#define MG_MAX_SECTS 256
+
+/* Register offsets */
+#define MG_BUFF_OFFSET			0x8000
+#define MG_REG_OFFSET			0xC000
+#define MG_REG_FEATURE			(MG_REG_OFFSET + 2)	/* write case */
+#define MG_REG_ERROR			(MG_REG_OFFSET + 2)	/* read case */
+#define MG_REG_SECT_CNT			(MG_REG_OFFSET + 4)
+#define MG_REG_SECT_NUM			(MG_REG_OFFSET + 6)
+#define MG_REG_CYL_LOW			(MG_REG_OFFSET + 8)
+#define MG_REG_CYL_HIGH			(MG_REG_OFFSET + 0xA)
+#define MG_REG_DRV_HEAD			(MG_REG_OFFSET + 0xC)
+#define MG_REG_COMMAND			(MG_REG_OFFSET + 0xE)	/* write case */
+#define MG_REG_STATUS			(MG_REG_OFFSET + 0xE)	/* read  case */
+#define MG_REG_DRV_CTRL			(MG_REG_OFFSET + 0x10)
+#define MG_REG_BURST_CTRL		(MG_REG_OFFSET + 0x12)
+
+/* handy status */
+#define MG_STAT_READY	(ATA_DRDY | ATA_DSC)
+#define MG_READY_OK(s)	(((s) & (MG_STAT_READY | (ATA_BUSY | ATA_DF | \
+				 ATA_ERR))) == MG_STAT_READY)
+
+/* error code for others */
+#define MG_ERR_NONE		0
+#define MG_ERR_TIMEOUT		0x100
+#define MG_ERR_INIT_STAT	0x101
+#define MG_ERR_TRANSLATION	0x102
+#define MG_ERR_CTRL_RST		0x103
+#define MG_ERR_INV_STAT		0x104
+#define MG_ERR_RSTOUT		0x105
+
+#define MG_MAX_ERRORS	6	/* Max read/write errors */
+
+/* command */
+#define MG_CMD_RD 0x20
+#define MG_CMD_WR 0x30
+#define MG_CMD_SLEEP 0x99
+#define MG_CMD_WAKEUP 0xC3
+#define MG_CMD_ID 0xEC
+#define MG_CMD_WR_CONF 0x3C
+#define MG_CMD_RD_CONF 0x40
+
+/* operation mode */
+#define MG_OP_CASCADE (1 << 0)
+#define MG_OP_CASCADE_SYNC_RD (1 << 1)
+#define MG_OP_CASCADE_SYNC_WR (1 << 2)
+#define MG_OP_INTERLEAVE (1 << 3)
+
+/* synchronous */
+#define MG_BURST_LAT_4 (3 << 4)
+#define MG_BURST_LAT_5 (4 << 4)
+#define MG_BURST_LAT_6 (5 << 4)
+#define MG_BURST_LAT_7 (6 << 4)
+#define MG_BURST_LAT_8 (7 << 4)
+#define MG_BURST_LEN_4 (1 << 1)
+#define MG_BURST_LEN_8 (2 << 1)
+#define MG_BURST_LEN_16 (3 << 1)
+#define MG_BURST_LEN_32 (4 << 1)
+#define MG_BURST_LEN_CONT (0 << 1)
+
+/* timeout value (unit: ms) */
+#define MG_TMAX_CONF_TO_CMD	1
+#define MG_TMAX_WAIT_RD_DRQ	10
+#define MG_TMAX_WAIT_WR_DRQ	500
+#define MG_TMAX_RST_TO_BUSY	10
+#define MG_TMAX_HDRST_TO_RDY	500
+#define MG_TMAX_SWRST_TO_RDY	500
+#define MG_TMAX_RSTOUT		3000
+
+#define MG_DEV_MASK (MG_BOOT_DEV | MG_STORAGE_DEV | MG_STORAGE_DEV_SKIP_RST)
+
+/* main structure for mflash driver */
+struct mg_host {
+	struct device *dev;
+
+	struct request_queue *breq;
+	struct request *req;
+	spinlock_t lock;
+	struct gendisk *gd;
+
+	struct timer_list timer;
+	void (*mg_do_intr) (struct mg_host *);
+
+	u16 id[ATA_ID_WORDS];
+
+	u16 cyls;
+	u16 heads;
+	u16 sectors;
+	u32 n_sectors;
+	u32 nres_sectors;
+
+	void __iomem *dev_base;
+	unsigned int irq;
+	unsigned int rst;
+	unsigned int rstout;
+
+	u32 major;
+	u32 error;
+};
+
+/*
+ * Debugging macro and defines
+ */
+#undef DO_MG_DEBUG
+#ifdef DO_MG_DEBUG
+#  define MG_DBG(fmt, args...) \
+	printk(KERN_DEBUG "%s:%d "fmt, __func__, __LINE__, ##args)
+#else /* CONFIG_MG_DEBUG */
+#  define MG_DBG(fmt, args...) do { } while (0)
+#endif /* CONFIG_MG_DEBUG */
+
 static void mg_request(struct request_queue *);
 
+static bool mg_end_request(struct mg_host *host, int err, unsigned int nr_bytes)
+{
+	if (__blk_end_request(host->req, err, nr_bytes))
+		return true;
+
+	host->req = NULL;
+	return false;
+}
+
+static bool mg_end_request_cur(struct mg_host *host, int err)
+{
+	return mg_end_request(host, err, blk_rq_cur_bytes(host->req));
+}
+
 static void mg_dump_status(const char *msg, unsigned int stat,
 		struct mg_host *host)
 {
 	char *name = MG_DISK_NAME;
-	struct request *req;
 
-	if (host->breq) {
-		req = elv_next_request(host->breq);
-		if (req)
-			name = req->rq_disk->disk_name;
-	}
+	if (host->req)
+		name = host->req->rq_disk->disk_name;
 
 	printk(KERN_ERR "%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
-	if (stat & MG_REG_STATUS_BIT_BUSY)
+	if (stat & ATA_BUSY)
 		printk("Busy ");
-	if (stat & MG_REG_STATUS_BIT_READY)
+	if (stat & ATA_DRDY)
 		printk("DriveReady ");
-	if (stat & MG_REG_STATUS_BIT_WRITE_FAULT)
+	if (stat & ATA_DF)
 		printk("WriteFault ");
-	if (stat & MG_REG_STATUS_BIT_SEEK_DONE)
+	if (stat & ATA_DSC)
 		printk("SeekComplete ");
-	if (stat & MG_REG_STATUS_BIT_DATA_REQ)
+	if (stat & ATA_DRQ)
 		printk("DataRequest ");
-	if (stat & MG_REG_STATUS_BIT_CORRECTED_ERROR)
+	if (stat & ATA_CORR)
 		printk("CorrectedError ");
-	if (stat & MG_REG_STATUS_BIT_ERROR)
+	if (stat & ATA_ERR)
 		printk("Error ");
 	printk("}\n");
-	if ((stat & MG_REG_STATUS_BIT_ERROR) == 0) {
+	if ((stat & ATA_ERR) == 0) {
 		host->error = 0;
 	} else {
 		host->error = inb((unsigned long)host->dev_base + MG_REG_ERROR);
 		printk(KERN_ERR "%s: %s: error=0x%02x { ", name, msg,
 				host->error & 0xff);
-		if (host->error & MG_REG_ERR_BBK)
+		if (host->error & ATA_BBK)
 			printk("BadSector ");
-		if (host->error & MG_REG_ERR_UNC)
+		if (host->error & ATA_UNC)
 			printk("UncorrectableError ");
-		if (host->error & MG_REG_ERR_IDNF)
+		if (host->error & ATA_IDNF)
 			printk("SectorIdNotFound ");
-		if (host->error & MG_REG_ERR_ABRT)
+		if (host->error & ATA_ABORTED)
 			printk("DriveStatusError ");
-		if (host->error & MG_REG_ERR_AMNF)
+		if (host->error & ATA_AMNF)
 			printk("AddrMarkNotFound ");
 		printk("}");
-		if (host->error &
-				(MG_REG_ERR_BBK | MG_REG_ERR_UNC |
-				 MG_REG_ERR_IDNF | MG_REG_ERR_AMNF)) {
-			if (host->breq) {
-				req = elv_next_request(host->breq);
-				if (req)
-					printk(", sector=%u", (u32)req->sector);
-			}
-
+		if (host->error & (ATA_BBK | ATA_UNC | ATA_IDNF | ATA_AMNF)) {
+			if (host->req)
+				printk(", sector=%u",
+				       (unsigned int)blk_rq_pos(host->req));
 		}
 		printk("\n");
 	}
@@ -96,16 +218,26 @@
 	host->error = MG_ERR_NONE;
 	expire = jiffies + msecs_to_jiffies(msec);
 
+	/* These 2 times dummy status read prevents reading invalid
+	 * status. A very little time (3 times of mflash operating clk)
+	 * is required for busy bit is set. Use dummy read instead of
+	 * busy wait, because mflash's PLL is machine dependent.
+	 */
+	if (prv_data->use_polling) {
+		status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
+		status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
+	}
+
 	status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
 
 	do {
 		cur_jiffies = jiffies;
-		if (status & MG_REG_STATUS_BIT_BUSY) {
-			if (expect == MG_REG_STATUS_BIT_BUSY)
+		if (status & ATA_BUSY) {
+			if (expect == ATA_BUSY)
 				break;
 		} else {
 			/* Check the error condition! */
-			if (status & MG_REG_STATUS_BIT_ERROR) {
+			if (status & ATA_ERR) {
 				mg_dump_status("mg_wait", status, host);
 				break;
 			}
@@ -114,16 +246,14 @@
 				if (MG_READY_OK(status))
 					break;
 
-			if (expect == MG_REG_STATUS_BIT_DATA_REQ)
-				if (status & MG_REG_STATUS_BIT_DATA_REQ)
+			if (expect == ATA_DRQ)
+				if (status & ATA_DRQ)
 					break;
 		}
 		if (!msec) {
 			mg_dump_status("not ready", status, host);
 			return MG_ERR_INV_STAT;
 		}
-		if (prv_data->use_polling)
-			msleep(1);
 
 		status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
 	} while (time_before(cur_jiffies, expire));
@@ -173,6 +303,42 @@
 	return IRQ_HANDLED;
 }
 
+/* local copy of ata_id_string() */
+static void mg_id_string(const u16 *id, unsigned char *s,
+			 unsigned int ofs, unsigned int len)
+{
+	unsigned int c;
+
+	BUG_ON(len & 1);
+
+	while (len > 0) {
+		c = id[ofs] >> 8;
+		*s = c;
+		s++;
+
+		c = id[ofs] & 0xff;
+		*s = c;
+		s++;
+
+		ofs++;
+		len -= 2;
+	}
+}
+
+/* local copy of ata_id_c_string() */
+static void mg_id_c_string(const u16 *id, unsigned char *s,
+			   unsigned int ofs, unsigned int len)
+{
+	unsigned char *p;
+
+	mg_id_string(id, s, ofs, len - 1);
+
+	p = s + strnlen(s, len - 1);
+	while (p > s && p[-1] == ' ')
+		p--;
+	*p = '\0';
+}
+
 static int mg_get_disk_id(struct mg_host *host)
 {
 	u32 i;
@@ -184,12 +350,10 @@
 	char serial[ATA_ID_SERNO_LEN + 1];
 
 	if (!prv_data->use_polling)
-		outb(MG_REG_CTRL_INTR_DISABLE,
-				(unsigned long)host->dev_base +
-				MG_REG_DRV_CTRL);
+		outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 
 	outb(MG_CMD_ID, (unsigned long)host->dev_base + MG_REG_COMMAND);
-	err = mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, MG_TMAX_WAIT_RD_DRQ);
+	err = mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_RD_DRQ);
 	if (err)
 		return err;
 
@@ -219,9 +383,9 @@
 		host->n_sectors -= host->nres_sectors;
 	}
 
-	ata_id_c_string(id, fwrev, ATA_ID_FW_REV, sizeof(fwrev));
-	ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model));
-	ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
+	mg_id_c_string(id, fwrev, ATA_ID_FW_REV, sizeof(fwrev));
+	mg_id_c_string(id, model, ATA_ID_PROD, sizeof(model));
+	mg_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
 	printk(KERN_INFO "mg_disk: model: %s\n", model);
 	printk(KERN_INFO "mg_disk: firm: %.8s\n", fwrev);
 	printk(KERN_INFO "mg_disk: serial: %s\n", serial);
@@ -229,8 +393,7 @@
 			host->n_sectors, host->nres_sectors);
 
 	if (!prv_data->use_polling)
-		outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base +
-				MG_REG_DRV_CTRL);
+		outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 
 	return err;
 }
@@ -244,7 +407,7 @@
 
 	/* hdd rst low */
 	gpio_set_value(host->rst, 0);
-	err = mg_wait(host, MG_REG_STATUS_BIT_BUSY, MG_TMAX_RST_TO_BUSY);
+	err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY);
 	if (err)
 		return err;
 
@@ -255,17 +418,14 @@
 		return err;
 
 	/* soft reset on */
-	outb(MG_REG_CTRL_RESET |
-			(prv_data->use_polling ? MG_REG_CTRL_INTR_DISABLE :
-			 MG_REG_CTRL_INTR_ENABLE),
+	outb(ATA_SRST | (prv_data->use_polling ? ATA_NIEN : 0),
 			(unsigned long)host->dev_base + MG_REG_DRV_CTRL);
-	err = mg_wait(host, MG_REG_STATUS_BIT_BUSY, MG_TMAX_RST_TO_BUSY);
+	err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY);
 	if (err)
 		return err;
 
 	/* soft reset off */
-	outb(prv_data->use_polling ? MG_REG_CTRL_INTR_DISABLE :
-			MG_REG_CTRL_INTR_ENABLE,
+	outb(prv_data->use_polling ? ATA_NIEN : 0,
 			(unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 	err = mg_wait(host, MG_STAT_READY, MG_TMAX_SWRST_TO_RDY);
 	if (err)
@@ -281,11 +441,10 @@
 
 static void mg_bad_rw_intr(struct mg_host *host)
 {
-	struct request *req = elv_next_request(host->breq);
-	if (req != NULL)
-		if (++req->errors >= MG_MAX_ERRORS ||
-				host->error == MG_ERR_TIMEOUT)
-			end_request(req, 0);
+	if (host->req)
+		if (++host->req->errors >= MG_MAX_ERRORS ||
+		    host->error == MG_ERR_TIMEOUT)
+			mg_end_request_cur(host, -EIO);
 }
 
 static unsigned int mg_out(struct mg_host *host,
@@ -311,113 +470,109 @@
 			MG_REG_CYL_LOW);
 	outb((u8)(sect_num >> 16), (unsigned long)host->dev_base +
 			MG_REG_CYL_HIGH);
-	outb((u8)((sect_num >> 24) | MG_REG_HEAD_LBA_MODE),
+	outb((u8)((sect_num >> 24) | ATA_LBA | ATA_DEVICE_OBS),
 			(unsigned long)host->dev_base + MG_REG_DRV_HEAD);
 	outb(cmd, (unsigned long)host->dev_base + MG_REG_COMMAND);
 	return MG_ERR_NONE;
 }
 
+static void mg_read_one(struct mg_host *host, struct request *req)
+{
+	u16 *buff = (u16 *)req->buffer;
+	u32 i;
+
+	for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
+		*buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET +
+			      (i << 1));
+}
+
 static void mg_read(struct request *req)
 {
-	u32 remains, j;
 	struct mg_host *host = req->rq_disk->private_data;
 
-	remains = req->nr_sectors;
-
-	if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_RD, NULL) !=
-			MG_ERR_NONE)
+	if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req),
+		   MG_CMD_RD, NULL) != MG_ERR_NONE)
 		mg_bad_rw_intr(host);
 
 	MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
-			remains, req->sector, req->buffer);
+	       blk_rq_sectors(req), blk_rq_pos(req), req->buffer);
 
-	while (remains) {
-		if (mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ,
-					MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) {
+	do {
+		if (mg_wait(host, ATA_DRQ,
+			    MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) {
 			mg_bad_rw_intr(host);
 			return;
 		}
-		for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
-			*(u16 *)req->buffer =
-				inw((unsigned long)host->dev_base +
-						MG_BUFF_OFFSET + (j << 1));
-			req->buffer += 2;
-		}
-
-		req->sector++;
-		req->errors = 0;
-		remains = --req->nr_sectors;
-		--req->current_nr_sectors;
 
-		if (req->current_nr_sectors <= 0) {
-			MG_DBG("remain : %d sects\n", remains);
-			end_request(req, 1);
-			if (remains > 0)
-				req = elv_next_request(host->breq);
-		}
+		mg_read_one(host, req);
 
 		outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base +
 				MG_REG_COMMAND);
-	}
+	} while (mg_end_request(host, 0, MG_SECTOR_SIZE));
+}
+
+static void mg_write_one(struct mg_host *host, struct request *req)
+{
+	u16 *buff = (u16 *)req->buffer;
+	u32 i;
+
+	for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
+		outw(*buff++, (unsigned long)host->dev_base + MG_BUFF_OFFSET +
+		     (i << 1));
 }
 
 static void mg_write(struct request *req)
 {
-	u32 remains, j;
 	struct mg_host *host = req->rq_disk->private_data;
+	unsigned int rem = blk_rq_sectors(req);
 
-	remains = req->nr_sectors;
+	if (mg_out(host, blk_rq_pos(req), rem,
+		   MG_CMD_WR, NULL) != MG_ERR_NONE) {
+		mg_bad_rw_intr(host);
+		return;
+	}
 
-	if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_WR, NULL) !=
-			MG_ERR_NONE) {
+	MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
+	       rem, blk_rq_pos(req), req->buffer);
+
+	if (mg_wait(host, ATA_DRQ,
+		    MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
 		mg_bad_rw_intr(host);
 		return;
 	}
 
+	do {
+		mg_write_one(host, req);
 
-	MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
-			remains, req->sector, req->buffer);
-	while (remains) {
-		if (mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ,
+		outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
+				MG_REG_COMMAND);
+
+		rem--;
+		if (rem > 1 && mg_wait(host, ATA_DRQ,
+					MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
+			mg_bad_rw_intr(host);
+			return;
+		} else if (mg_wait(host, MG_STAT_READY,
 					MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
 			mg_bad_rw_intr(host);
 			return;
 		}
-		for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
-			outw(*(u16 *)req->buffer,
-					(unsigned long)host->dev_base +
-					MG_BUFF_OFFSET + (j << 1));
-			req->buffer += 2;
-		}
-		req->sector++;
-		remains = --req->nr_sectors;
-		--req->current_nr_sectors;
-
-		if (req->current_nr_sectors <= 0) {
-			MG_DBG("remain : %d sects\n", remains);
-			end_request(req, 1);
-			if (remains > 0)
-				req = elv_next_request(host->breq);
-		}
-
-		outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
-				MG_REG_COMMAND);
-	}
+	} while (mg_end_request(host, 0, MG_SECTOR_SIZE));
 }
 
 static void mg_read_intr(struct mg_host *host)
 {
+	struct request *req = host->req;
 	u32 i;
-	struct request *req;
 
 	/* check status */
 	do {
 		i = inb((unsigned long)host->dev_base + MG_REG_STATUS);
-		if (i & MG_REG_STATUS_BIT_BUSY)
+		if (i & ATA_BUSY)
 			break;
 		if (!MG_READY_OK(i))
 			break;
-		if (i & MG_REG_STATUS_BIT_DATA_REQ)
+		if (i & ATA_DRQ)
 			goto ok_to_read;
 	} while (0);
 	mg_dump_status("mg_read_intr", i, host);
@@ -426,61 +581,36 @@
 	return;
 
 ok_to_read:
-	/* get current segment of request */
-	req = elv_next_request(host->breq);
-
-	/* read 1 sector */
-	for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) {
-		*(u16 *)req->buffer =
-			inw((unsigned long)host->dev_base + MG_BUFF_OFFSET +
-					(i << 1));
-		req->buffer += 2;
-	}
+	mg_read_one(host, req);
 
-	/* manipulate request */
 	MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
-			req->sector, req->nr_sectors - 1, req->buffer);
-
-	req->sector++;
-	req->errors = 0;
-	i = --req->nr_sectors;
-	--req->current_nr_sectors;
-
-	/* let know if current segment done */
-	if (req->current_nr_sectors <= 0)
-		end_request(req, 1);
-
-	/* set handler if read remains */
-	if (i > 0) {
-		host->mg_do_intr = mg_read_intr;
-		mod_timer(&host->timer, jiffies + 3 * HZ);
-	}
+	       blk_rq_pos(req), blk_rq_sectors(req) - 1, req->buffer);
 
 	/* send read confirm */
 	outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
 
-	/* goto next request */
-	if (!i)
+	if (mg_end_request(host, 0, MG_SECTOR_SIZE)) {
+		/* set handler if read remains */
+		host->mg_do_intr = mg_read_intr;
+		mod_timer(&host->timer, jiffies + 3 * HZ);
+	} else /* goto next request */
 		mg_request(host->breq);
 }
 
 static void mg_write_intr(struct mg_host *host)
 {
-	u32 i, j;
-	u16 *buff;
-	struct request *req;
-
-	/* get current segment of request */
-	req = elv_next_request(host->breq);
+	struct request *req = host->req;
+	u32 i;
+	bool rem;
 
 	/* check status */
 	do {
 		i = inb((unsigned long)host->dev_base + MG_REG_STATUS);
-		if (i & MG_REG_STATUS_BIT_BUSY)
+		if (i & ATA_BUSY)
 			break;
 		if (!MG_READY_OK(i))
 			break;
-		if ((req->nr_sectors <= 1) || (i & MG_REG_STATUS_BIT_DATA_REQ))
+		if ((blk_rq_sectors(req) <= 1) || (i & ATA_DRQ))
 			goto ok_to_write;
 	} while (0);
 	mg_dump_status("mg_write_intr", i, host);
@@ -489,26 +619,11 @@
 	return;
 
 ok_to_write:
-	/* manipulate request */
-	req->sector++;
-	i = --req->nr_sectors;
-	--req->current_nr_sectors;
-	req->buffer += MG_SECTOR_SIZE;
-
-	/* let know if current segment or all done */
-	if (!i || (req->bio && req->current_nr_sectors <= 0))
-		end_request(req, 1);
-
-	/* write 1 sector and set handler if remains */
-	if (i > 0) {
-		buff = (u16 *)req->buffer;
-		for (j = 0; j < MG_STORAGE_BUFFER_SIZE >> 1; j++) {
-			outw(*buff, (unsigned long)host->dev_base +
-					MG_BUFF_OFFSET + (j << 1));
-			buff++;
-		}
+	if ((rem = mg_end_request(host, 0, MG_SECTOR_SIZE))) {
+		/* write 1 sector and set handler if remains */
+		mg_write_one(host, req);
 		MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
-				req->sector, req->nr_sectors, req->buffer);
+		       blk_rq_pos(req), blk_rq_sectors(req), req->buffer);
 		host->mg_do_intr = mg_write_intr;
 		mod_timer(&host->timer, jiffies + 3 * HZ);
 	}
@@ -516,7 +631,7 @@
 	/* send write confirm */
 	outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND);
 
-	if (!i)
+	if (!rem)
 		mg_request(host->breq);
 }
 
@@ -524,49 +639,45 @@
 {
 	struct mg_host *host = (struct mg_host *)data;
 	char *name;
-	struct request *req;
 
 	spin_lock_irq(&host->lock);
 
-	req = elv_next_request(host->breq);
-	if (!req)
+	if (!host->req)
 		goto out_unlock;
 
 	host->mg_do_intr = NULL;
 
-	name = req->rq_disk->disk_name;
+	name = host->req->rq_disk->disk_name;
 	printk(KERN_DEBUG "%s: timeout\n", name);
 
 	host->error = MG_ERR_TIMEOUT;
 	mg_bad_rw_intr(host);
 
-	mg_request(host->breq);
 out_unlock:
+	mg_request(host->breq);
 	spin_unlock_irq(&host->lock);
 }
 
 static void mg_request_poll(struct request_queue *q)
 {
-	struct request *req;
-	struct mg_host *host;
+	struct mg_host *host = q->queuedata;
 
-	while ((req = elv_next_request(q)) != NULL) {
-		host = req->rq_disk->private_data;
-		if (blk_fs_request(req)) {
-			switch (rq_data_dir(req)) {
-			case READ:
-				mg_read(req);
-				break;
-			case WRITE:
-				mg_write(req);
-				break;
-			default:
-				printk(KERN_WARNING "%s:%d unknown command\n",
-						__func__, __LINE__);
-				end_request(req, 0);
+	while (1) {
+		if (!host->req) {
+			host->req = blk_fetch_request(q);
+			if (!host->req)
 				break;
-			}
 		}
+
+		if (unlikely(!blk_fs_request(host->req))) {
+			mg_end_request_cur(host, -EIO);
+			continue;
+		}
+
+		if (rq_data_dir(host->req) == READ)
+			mg_read(host->req);
+		else
+			mg_write(host->req);
 	}
 }
 
@@ -575,9 +686,6 @@
 		unsigned int sect_num,
 		unsigned int sect_cnt)
 {
-	u16 *buff;
-	u32 i;
-
 	switch (rq_data_dir(req)) {
 	case READ:
 		if (mg_out(host, sect_num, sect_cnt, MG_CMD_RD, &mg_read_intr)
@@ -588,37 +696,24 @@
 		break;
 	case WRITE:
 		/* TODO : handler */
-		outb(MG_REG_CTRL_INTR_DISABLE,
-				(unsigned long)host->dev_base +
-				MG_REG_DRV_CTRL);
+		outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 		if (mg_out(host, sect_num, sect_cnt, MG_CMD_WR, &mg_write_intr)
 				!= MG_ERR_NONE) {
 			mg_bad_rw_intr(host);
 			return host->error;
 		}
 		del_timer(&host->timer);
-		mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, MG_TMAX_WAIT_WR_DRQ);
-		outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base +
-				MG_REG_DRV_CTRL);
+		mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ);
+		outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 		if (host->error) {
 			mg_bad_rw_intr(host);
 			return host->error;
 		}
-		buff = (u16 *)req->buffer;
-		for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) {
-			outw(*buff, (unsigned long)host->dev_base +
-					MG_BUFF_OFFSET + (i << 1));
-			buff++;
-		}
+		mg_write_one(host, req);
 		mod_timer(&host->timer, jiffies + 3 * HZ);
 		outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
 				MG_REG_COMMAND);
 		break;
-	default:
-		printk(KERN_WARNING "%s:%d unknown command\n",
-				__func__, __LINE__);
-		end_request(req, 0);
-		break;
 	}
 	return MG_ERR_NONE;
 }
@@ -626,16 +721,17 @@
 /* This function also called from IRQ context */
 static void mg_request(struct request_queue *q)
 {
+	struct mg_host *host = q->queuedata;
 	struct request *req;
-	struct mg_host *host;
 	u32 sect_num, sect_cnt;
 
 	while (1) {
-		req = elv_next_request(q);
-		if (!req)
-			return;
-
-		host = req->rq_disk->private_data;
+		if (!host->req) {
+			host->req = blk_fetch_request(q);
+			if (!host->req)
+				break;
+		}
+		req = host->req;
 
 		/* check unwanted request call */
 		if (host->mg_do_intr)
@@ -643,9 +739,9 @@
 
 		del_timer(&host->timer);
 
-		sect_num = req->sector;
+		sect_num = blk_rq_pos(req);
 		/* deal whole segments */
-		sect_cnt = req->nr_sectors;
+		sect_cnt = blk_rq_sectors(req);
 
 		/* sanity check */
 		if (sect_num >= get_capacity(req->rq_disk) ||
@@ -655,12 +751,14 @@
 					"%s: bad access: sector=%d, count=%d\n",
 					req->rq_disk->disk_name,
 					sect_num, sect_cnt);
-			end_request(req, 0);
+			mg_end_request_cur(host, -EIO);
 			continue;
 		}
 
-		if (!blk_fs_request(req))
-			return;
+		if (unlikely(!blk_fs_request(req))) {
+			mg_end_request_cur(host, -EIO);
+			continue;
+		}
 
 		if (!mg_issue_req(req, host, sect_num, sect_cnt))
 			return;
@@ -690,9 +788,7 @@
 		return -EIO;
 
 	if (!prv_data->use_polling)
-		outb(MG_REG_CTRL_INTR_DISABLE,
-				(unsigned long)host->dev_base +
-				MG_REG_DRV_CTRL);
+		outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 
 	outb(MG_CMD_SLEEP, (unsigned long)host->dev_base + MG_REG_COMMAND);
 	/* wait until mflash deep sleep */
@@ -700,9 +796,7 @@
 
 	if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD)) {
 		if (!prv_data->use_polling)
-			outb(MG_REG_CTRL_INTR_ENABLE,
-					(unsigned long)host->dev_base +
-					MG_REG_DRV_CTRL);
+			outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 		return -EIO;
 	}
 
@@ -725,8 +819,7 @@
 		return -EIO;
 
 	if (!prv_data->use_polling)
-		outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base +
-				MG_REG_DRV_CTRL);
+		outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL);
 
 	return 0;
 }
@@ -877,6 +970,7 @@
 				__func__, __LINE__);
 		goto probe_err_5;
 	}
+	host->breq->queuedata = host;
 
 	/* mflash is random device, thanx for the noop */
 	elevator_exit(host->breq->elevator);
@@ -887,7 +981,7 @@
 		goto probe_err_6;
 	}
 	blk_queue_max_sectors(host->breq, MG_MAX_SECTS);
-	blk_queue_hardsect_size(host->breq, MG_SECTOR_SIZE);
+	blk_queue_logical_block_size(host->breq, MG_SECTOR_SIZE);
 
 	init_timer(&host->timer);
 	host->timer.function = mg_times_out;
diff -druN linux-libre-2.6.30-gnu/drivers/block/nbd.c linux-libre-2.6.31-gnu/drivers/block/nbd.c
--- linux-libre-2.6.30-gnu/drivers/block/nbd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/nbd.c	2009-09-09 18:13:59.000000000 -0400
@@ -110,7 +110,7 @@
 			req, error ? "failed" : "done");
 
 	spin_lock_irqsave(q->queue_lock, flags);
-	__blk_end_request(req, error, req->nr_sectors << 9);
+	__blk_end_request_all(req, error);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -231,19 +231,19 @@
 {
 	int result, flags;
 	struct nbd_request request;
-	unsigned long size = req->nr_sectors << 9;
+	unsigned long size = blk_rq_bytes(req);
 
 	request.magic = htonl(NBD_REQUEST_MAGIC);
 	request.type = htonl(nbd_cmd(req));
-	request.from = cpu_to_be64((u64) req->sector << 9);
+	request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
 	request.len = htonl(size);
 	memcpy(request.handle, &req, sizeof(req));
 
-	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
+	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB)\n",
 			lo->disk->disk_name, req,
 			nbdcmd_to_ascii(nbd_cmd(req)),
-			(unsigned long long)req->sector << 9,
-			req->nr_sectors << 9);
+			(unsigned long long)blk_rq_pos(req) << 9,
+			blk_rq_bytes(req));
 	result = sock_xmit(lo, 1, &request, sizeof(request),
 			(nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
 	if (result <= 0) {
@@ -533,11 +533,9 @@
 {
 	struct request *req;
 	
-	while ((req = elv_next_request(q)) != NULL) {
+	while ((req = blk_fetch_request(q)) != NULL) {
 		struct nbd_device *lo;
 
-		blkdev_dequeue_request(req);
-
 		spin_unlock_irq(q->queue_lock);
 
 		dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
@@ -580,13 +578,6 @@
 		blk_rq_init(NULL, &sreq);
 		sreq.cmd_type = REQ_TYPE_SPECIAL;
 		nbd_cmd(&sreq) = NBD_CMD_DISC;
-		/*
-		 * Set these to sane values in case server implementation
-		 * fails to check the request type first and also to keep
-		 * debugging output cleaner.
-		 */
-		sreq.sector = 0;
-		sreq.nr_sectors = 0;
 		if (!lo->sock)
 			return -EINVAL;
 		nbd_send_req(lo, &sreq);
diff -druN linux-libre-2.6.30-gnu/drivers/block/osdblk.c linux-libre-2.6.31-gnu/drivers/block/osdblk.c
--- linux-libre-2.6.30-gnu/drivers/block/osdblk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/block/osdblk.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,701 @@
+
+/*
+   osdblk.c -- Export a single SCSI OSD object as a Linux block device
+
+
+   Copyright 2009 Red Hat, 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.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+   Instructions for use
+   --------------------
+
+   1) Map a Linux block device to an existing OSD object.
+
+      In this example, we will use partition id 1234, object id 5678,
+      OSD device /dev/osd1.
+
+      $ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add
+
+
+   2) List all active blkdev<->object mappings.
+
+      In this example, we have performed step #1 twice, creating two blkdevs,
+      mapped to two separate OSD objects.
+
+      $ cat /sys/class/osdblk/list
+      0 174 1234 5678 /dev/osd1
+      1 179 1994 897123 /dev/osd0
+
+      The columns, in order, are:
+      - blkdev unique id
+      - blkdev assigned major
+      - OSD object partition id
+      - OSD object id
+      - OSD device
+
+
+   3) Remove an active blkdev<->object mapping.
+
+      In this example, we remove the mapping with blkdev unique id 1.
+
+      $ echo 1 > /sys/class/osdblk/remove
+
+
+   NOTE:  The actual creation and deletion of OSD objects is outside the scope
+   of this driver.
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_attributes.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#define DRV_NAME "osdblk"
+#define PFX DRV_NAME ": "
+
+/* #define _OSDBLK_DEBUG */
+#ifdef _OSDBLK_DEBUG
+#define OSDBLK_DEBUG(fmt, a...) \
+	printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSDBLK_DEBUG(fmt, a...) \
+	do { if (0) printk(fmt, ##a); } while (0)
+#endif
+
+MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
+MODULE_DESCRIPTION("block device inside an OSD object osdblk.ko");
+MODULE_LICENSE("GPL");
+
+struct osdblk_device;
+
+enum {
+	OSDBLK_MINORS_PER_MAJOR	= 256,		/* max minors per blkdev */
+	OSDBLK_MAX_REQ		= 32,		/* max parallel requests */
+	OSDBLK_OP_TIMEOUT	= 4 * 60,	/* sync OSD req timeout */
+};
+
+struct osdblk_request {
+	struct request		*rq;		/* blk layer request */
+	struct bio		*bio;		/* cloned bio */
+	struct osdblk_device	*osdev;		/* associated blkdev */
+};
+
+struct osdblk_device {
+	int			id;		/* blkdev unique id */
+
+	int			major;		/* blkdev assigned major */
+	struct gendisk		*disk;		/* blkdev's gendisk and rq */
+	struct request_queue	*q;
+
+	struct osd_dev		*osd;		/* associated OSD */
+
+	char			name[32];	/* blkdev name, e.g. osdblk34 */
+
+	spinlock_t		lock;		/* queue lock */
+
+	struct osd_obj_id	obj;		/* OSD partition, obj id */
+	uint8_t			obj_cred[OSD_CAP_LEN]; /* OSD cred */
+
+	struct osdblk_request	req[OSDBLK_MAX_REQ]; /* request table */
+
+	struct list_head	node;
+
+	char			osd_path[0];	/* OSD device path */
+};
+
+static struct class *class_osdblk;		/* /sys/class/osdblk */
+static DEFINE_MUTEX(ctl_mutex);	/* Serialize open/close/setup/teardown */
+static LIST_HEAD(osdblkdev_list);
+
+static struct block_device_operations osdblk_bd_ops = {
+	.owner		= THIS_MODULE,
+};
+
+static const struct osd_attr g_attr_logical_length = ATTR_DEF(
+	OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
+
+static void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN],
+				   const struct osd_obj_id *obj)
+{
+	osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
+}
+
+/* copied from exofs; move to libosd? */
+/*
+ * Perform a synchronous OSD operation.  copied from exofs; move to libosd?
+ */
+static int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential)
+{
+	int ret;
+
+	or->timeout = timeout;
+	ret = osd_finalize_request(or, 0, credential, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request(or);
+
+	/* osd_req_decode_sense(or, ret); */
+	return ret;
+}
+
+/*
+ * Perform an asynchronous OSD operation.  copied from exofs; move to libosd?
+ */
+static int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done,
+		   void *caller_context, u8 *cred)
+{
+	int ret;
+
+	ret = osd_finalize_request(or, 0, cred, NULL);
+	if (ret)
+		return ret;
+
+	ret = osd_execute_request_async(or, async_done, caller_context);
+
+	return ret;
+}
+
+/* copied from exofs; move to libosd? */
+static int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr)
+{
+	struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
+	void *iter = NULL;
+	int nelem;
+
+	do {
+		nelem = 1;
+		osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter);
+		if ((cur_attr.attr_page == attr->attr_page) &&
+		    (cur_attr.attr_id == attr->attr_id)) {
+			attr->len = cur_attr.len;
+			attr->val_ptr = cur_attr.val_ptr;
+			return 0;
+		}
+	} while (iter);
+
+	return -EIO;
+}
+
+static int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out)
+{
+	struct osd_request *or;
+	struct osd_attr attr;
+	int ret;
+
+	/* start request */
+	or = osd_start_request(osdev->osd, GFP_KERNEL);
+	if (!or)
+		return -ENOMEM;
+
+	/* create a get-attributes(length) request */
+	osd_req_get_attributes(or, &osdev->obj);
+
+	osd_req_add_get_attr_list(or, &g_attr_logical_length, 1);
+
+	/* execute op synchronously */
+	ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred);
+	if (ret)
+		goto out;
+
+	/* extract length from returned attribute info */
+	attr = g_attr_logical_length;
+	ret = extract_attr_from_req(or, &attr);
+	if (ret)
+		goto out;
+
+	*size_out = get_unaligned_be64(attr.val_ptr);
+
+out:
+	osd_end_request(or);
+	return ret;
+
+}
+
+static void osdblk_osd_complete(struct osd_request *or, void *private)
+{
+	struct osdblk_request *orq = private;
+	struct osd_sense_info osi;
+	int ret = osd_req_decode_sense(or, &osi);
+
+	if (ret) {
+		ret = -EIO;
+		OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret);
+	}
+
+	/* complete OSD request */
+	osd_end_request(or);
+
+	/* complete request passed to osdblk by block layer */
+	__blk_end_request_all(orq->rq, ret);
+}
+
+static void bio_chain_put(struct bio *chain)
+{
+	struct bio *tmp;
+
+	while (chain) {
+		tmp = chain;
+		chain = chain->bi_next;
+
+		bio_put(tmp);
+	}
+}
+
+static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
+{
+	struct bio *tmp, *new_chain = NULL, *tail = NULL;
+
+	while (old_chain) {
+		tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
+		if (!tmp)
+			goto err_out;
+
+		__bio_clone(tmp, old_chain);
+		tmp->bi_bdev = NULL;
+		gfpmask &= ~__GFP_WAIT;
+		tmp->bi_next = NULL;
+
+		if (!new_chain)
+			new_chain = tail = tmp;
+		else {
+			tail->bi_next = tmp;
+			tail = tmp;
+		}
+
+		old_chain = old_chain->bi_next;
+	}
+
+	return new_chain;
+
+err_out:
+	OSDBLK_DEBUG("bio_chain_clone with err\n");
+	bio_chain_put(new_chain);
+	return NULL;
+}
+
+static void osdblk_rq_fn(struct request_queue *q)
+{
+	struct osdblk_device *osdev = q->queuedata;
+
+	while (1) {
+		struct request *rq;
+		struct osdblk_request *orq;
+		struct osd_request *or;
+		struct bio *bio;
+		bool do_write, do_flush;
+
+		/* peek at request from block layer */
+		rq = blk_fetch_request(q);
+		if (!rq)
+			break;
+
+		/* filter out block requests we don't understand */
+		if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) {
+			blk_end_request_all(rq, 0);
+			continue;
+		}
+
+		/* deduce our operation (read, write, flush) */
+		/* I wish the block layer simplified cmd_type/cmd_flags/cmd[]
+		 * into a clearly defined set of RPC commands:
+		 * read, write, flush, scsi command, power mgmt req,
+		 * driver-specific, etc.
+		 */
+
+		do_flush = (rq->special == (void *) 0xdeadbeefUL);
+		do_write = (rq_data_dir(rq) == WRITE);
+
+		if (!do_flush) { /* osd_flush does not use a bio */
+			/* a bio clone to be passed down to OSD request */
+			bio = bio_chain_clone(rq->bio, GFP_ATOMIC);
+			if (!bio)
+				break;
+		} else
+			bio = NULL;
+
+		/* alloc internal OSD request, for OSD command execution */
+		or = osd_start_request(osdev->osd, GFP_ATOMIC);
+		if (!or) {
+			bio_chain_put(bio);
+			OSDBLK_DEBUG("osd_start_request with err\n");
+			break;
+		}
+
+		orq = &osdev->req[rq->tag];
+		orq->rq = rq;
+		orq->bio = bio;
+		orq->osdev = osdev;
+
+		/* init OSD command: flush, write or read */
+		if (do_flush)
+			osd_req_flush_object(or, &osdev->obj,
+					     OSD_CDB_FLUSH_ALL, 0, 0);
+		else if (do_write)
+			osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
+				      bio, blk_rq_bytes(rq));
+		else
+			osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
+				     bio, blk_rq_bytes(rq));
+
+		OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n",
+			do_flush ? "flush" : do_write ?
+				"write" : "read", blk_rq_bytes(rq),
+			blk_rq_pos(rq) * 512ULL);
+
+		/* begin OSD command execution */
+		if (osd_async_op(or, osdblk_osd_complete, orq,
+				 osdev->obj_cred)) {
+			osd_end_request(or);
+			blk_requeue_request(q, rq);
+			bio_chain_put(bio);
+			OSDBLK_DEBUG("osd_execute_request_async with err\n");
+			break;
+		}
+
+		/* remove the special 'flush' marker, now that the command
+		 * is executing
+		 */
+		rq->special = NULL;
+	}
+}
+
+static void osdblk_prepare_flush(struct request_queue *q, struct request *rq)
+{
+	/* add driver-specific marker, to indicate that this request
+	 * is a flush command
+	 */
+	rq->special = (void *) 0xdeadbeefUL;
+}
+
+static void osdblk_free_disk(struct osdblk_device *osdev)
+{
+	struct gendisk *disk = osdev->disk;
+
+	if (!disk)
+		return;
+
+	if (disk->flags & GENHD_FL_UP)
+		del_gendisk(disk);
+	if (disk->queue)
+		blk_cleanup_queue(disk->queue);
+	put_disk(disk);
+}
+
+static int osdblk_init_disk(struct osdblk_device *osdev)
+{
+	struct gendisk *disk;
+	struct request_queue *q;
+	int rc;
+	u64 obj_size = 0;
+
+	/* contact OSD, request size info about the object being mapped */
+	rc = osdblk_get_obj_size(osdev, &obj_size);
+	if (rc)
+		return rc;
+
+	/* create gendisk info */
+	disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR);
+	if (!disk)
+		return -ENOMEM;
+
+	sprintf(disk->disk_name, DRV_NAME "%d", osdev->id);
+	disk->major = osdev->major;
+	disk->first_minor = 0;
+	disk->fops = &osdblk_bd_ops;
+	disk->private_data = osdev;
+
+	/* init rq */
+	q = blk_init_queue(osdblk_rq_fn, &osdev->lock);
+	if (!q) {
+		put_disk(disk);
+		return -ENOMEM;
+	}
+
+	/* switch queue to TCQ mode; allocate tag map */
+	rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL);
+	if (rc) {
+		blk_cleanup_queue(q);
+		put_disk(disk);
+		return rc;
+	}
+
+	/* Set our limits to the lower device limits, because osdblk cannot
+	 * sleep when allocating a lower-request and therefore cannot be
+	 * bouncing.
+	 */
+	blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
+
+	blk_queue_prep_rq(q, blk_queue_start_tag);
+	blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush);
+
+	disk->queue = q;
+
+	q->queuedata = osdev;
+
+	osdev->disk = disk;
+	osdev->q = q;
+
+	/* finally, announce the disk to the world */
+	set_capacity(disk, obj_size / 512ULL);
+	add_disk(disk);
+
+	printk(KERN_INFO "%s: Added of size 0x%llx\n",
+		disk->disk_name, (unsigned long long)obj_size);
+
+	return 0;
+}
+
+/********************************************************************
+ * /sys/class/osdblk/
+ *                   add	map OSD object to blkdev
+ *                   remove	unmap OSD object
+ *                   list	show mappings
+ *******************************************************************/
+
+static void class_osdblk_release(struct class *cls)
+{
+	kfree(cls);
+}
+
+static ssize_t class_osdblk_list(struct class *c, char *data)
+{
+	int n = 0;
+	struct list_head *tmp;
+
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	list_for_each(tmp, &osdblkdev_list) {
+		struct osdblk_device *osdev;
+
+		osdev = list_entry(tmp, struct osdblk_device, node);
+
+		n += sprintf(data+n, "%d %d %llu %llu %s\n",
+			osdev->id,
+			osdev->major,
+			osdev->obj.partition,
+			osdev->obj.id,
+			osdev->osd_path);
+	}
+
+	mutex_unlock(&ctl_mutex);
+	return n;
+}
+
+static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count)
+{
+	struct osdblk_device *osdev;
+	ssize_t rc;
+	int irc, new_id = 0;
+	struct list_head *tmp;
+
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
+
+	/* new osdblk_device object */
+	osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL);
+	if (!osdev) {
+		rc = -ENOMEM;
+		goto err_out_mod;
+	}
+
+	/* static osdblk_device initialization */
+	spin_lock_init(&osdev->lock);
+	INIT_LIST_HEAD(&osdev->node);
+
+	/* generate unique id: find highest unique id, add one */
+
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	list_for_each(tmp, &osdblkdev_list) {
+		struct osdblk_device *osdev;
+
+		osdev = list_entry(tmp, struct osdblk_device, node);
+		if (osdev->id > new_id)
+			new_id = osdev->id + 1;
+	}
+
+	osdev->id = new_id;
+
+	/* add to global list */
+	list_add_tail(&osdev->node, &osdblkdev_list);
+
+	mutex_unlock(&ctl_mutex);
+
+	/* parse add command */
+	if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id,
+		   osdev->osd_path) != 3) {
+		rc = -EINVAL;
+		goto err_out_slot;
+	}
+
+	/* initialize rest of new object */
+	sprintf(osdev->name, DRV_NAME "%d", osdev->id);
+
+	/* contact requested OSD */
+	osdev->osd = osduld_path_lookup(osdev->osd_path);
+	if (IS_ERR(osdev->osd)) {
+		rc = PTR_ERR(osdev->osd);
+		goto err_out_slot;
+	}
+
+	/* build OSD credential */
+	osdblk_make_credential(osdev->obj_cred, &osdev->obj);
+
+	/* register our block device */
+	irc = register_blkdev(0, osdev->name);
+	if (irc < 0) {
+		rc = irc;
+		goto err_out_osd;
+	}
+
+	osdev->major = irc;
+
+	/* set up and announce blkdev mapping */
+	rc = osdblk_init_disk(osdev);
+	if (rc)
+		goto err_out_blkdev;
+
+	return count;
+
+err_out_blkdev:
+	unregister_blkdev(osdev->major, osdev->name);
+err_out_osd:
+	osduld_put_device(osdev->osd);
+err_out_slot:
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+	list_del_init(&osdev->node);
+	mutex_unlock(&ctl_mutex);
+
+	kfree(osdev);
+err_out_mod:
+	OSDBLK_DEBUG("Error adding device %s\n", buf);
+	module_put(THIS_MODULE);
+	return rc;
+}
+
+static ssize_t class_osdblk_remove(struct class *c, const char *buf,
+					size_t count)
+{
+	struct osdblk_device *osdev = NULL;
+	int target_id, rc;
+	unsigned long ul;
+	struct list_head *tmp;
+
+	rc = strict_strtoul(buf, 10, &ul);
+	if (rc)
+		return rc;
+
+	/* convert to int; abort if we lost anything in the conversion */
+	target_id = (int) ul;
+	if (target_id != ul)
+		return -EINVAL;
+
+	/* remove object from list immediately */
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+	list_for_each(tmp, &osdblkdev_list) {
+		osdev = list_entry(tmp, struct osdblk_device, node);
+		if (osdev->id == target_id) {
+			list_del_init(&osdev->node);
+			break;
+		}
+		osdev = NULL;
+	}
+
+	mutex_unlock(&ctl_mutex);
+
+	if (!osdev)
+		return -ENOENT;
+
+	/* clean up and free blkdev and associated OSD connection */
+	osdblk_free_disk(osdev);
+	unregister_blkdev(osdev->major, osdev->name);
+	osduld_put_device(osdev->osd);
+	kfree(osdev);
+
+	/* release module ref */
+	module_put(THIS_MODULE);
+
+	return count;
+}
+
+static struct class_attribute class_osdblk_attrs[] = {
+	__ATTR(add,	0200, NULL, class_osdblk_add),
+	__ATTR(remove,	0200, NULL, class_osdblk_remove),
+	__ATTR(list,	0444, class_osdblk_list, NULL),
+	__ATTR_NULL
+};
+
+static int osdblk_sysfs_init(void)
+{
+	int ret = 0;
+
+	/*
+	 * create control files in sysfs
+	 * /sys/class/osdblk/...
+	 */
+	class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL);
+	if (!class_osdblk)
+		return -ENOMEM;
+
+	class_osdblk->name = DRV_NAME;
+	class_osdblk->owner = THIS_MODULE;
+	class_osdblk->class_release = class_osdblk_release;
+	class_osdblk->class_attrs = class_osdblk_attrs;
+
+	ret = class_register(class_osdblk);
+	if (ret) {
+		kfree(class_osdblk);
+		class_osdblk = NULL;
+		printk(PFX "failed to create class osdblk\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void osdblk_sysfs_cleanup(void)
+{
+	if (class_osdblk)
+		class_destroy(class_osdblk);
+	class_osdblk = NULL;
+}
+
+static int __init osdblk_init(void)
+{
+	int rc;
+
+	rc = osdblk_sysfs_init();
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static void __exit osdblk_exit(void)
+{
+	osdblk_sysfs_cleanup();
+}
+
+module_init(osdblk_init);
+module_exit(osdblk_exit);
+
diff -druN linux-libre-2.6.30-gnu/drivers/block/paride/pcd.c linux-libre-2.6.31-gnu/drivers/block/paride/pcd.c
--- linux-libre-2.6.30-gnu/drivers/block/paride/pcd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/paride/pcd.c	2009-09-09 18:13:59.000000000 -0400
@@ -719,32 +719,37 @@
 	if (pcd_busy)
 		return;
 	while (1) {
-		pcd_req = elv_next_request(q);
-		if (!pcd_req)
-			return;
+		if (!pcd_req) {
+			pcd_req = blk_fetch_request(q);
+			if (!pcd_req)
+				return;
+		}
 
 		if (rq_data_dir(pcd_req) == READ) {
 			struct pcd_unit *cd = pcd_req->rq_disk->private_data;
 			if (cd != pcd_current)
 				pcd_bufblk = -1;
 			pcd_current = cd;
-			pcd_sector = pcd_req->sector;
-			pcd_count = pcd_req->current_nr_sectors;
+			pcd_sector = blk_rq_pos(pcd_req);
+			pcd_count = blk_rq_cur_sectors(pcd_req);
 			pcd_buf = pcd_req->buffer;
 			pcd_busy = 1;
 			ps_set_intr(do_pcd_read, NULL, 0, nice);
 			return;
-		} else
-			end_request(pcd_req, 0);
+		} else {
+			__blk_end_request_all(pcd_req, -EIO);
+			pcd_req = NULL;
+		}
 	}
 }
 
-static inline void next_request(int success)
+static inline void next_request(int err)
 {
 	unsigned long saved_flags;
 
 	spin_lock_irqsave(&pcd_lock, saved_flags);
-	end_request(pcd_req, success);
+	if (!__blk_end_request_cur(pcd_req, err))
+		pcd_req = NULL;
 	pcd_busy = 0;
 	do_pcd_request(pcd_queue);
 	spin_unlock_irqrestore(&pcd_lock, saved_flags);
@@ -781,7 +786,7 @@
 
 	if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
 		pcd_bufblk = -1;
-		next_request(0);
+		next_request(-EIO);
 		return;
 	}
 
@@ -796,7 +801,7 @@
 	pcd_retries = 0;
 	pcd_transfer();
 	if (!pcd_count) {
-		next_request(1);
+		next_request(0);
 		return;
 	}
 
@@ -815,7 +820,7 @@
 			return;
 		}
 		pcd_bufblk = -1;
-		next_request(0);
+		next_request(-EIO);
 		return;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/paride/pd.c linux-libre-2.6.31-gnu/drivers/block/paride/pd.c
--- linux-libre-2.6.30-gnu/drivers/block/paride/pd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/paride/pd.c	2009-09-09 18:13:59.000000000 -0400
@@ -410,10 +410,12 @@
 				pd_claimed = 0;
 				phase = NULL;
 				spin_lock_irqsave(&pd_lock, saved_flags);
-				end_request(pd_req, res);
-				pd_req = elv_next_request(pd_queue);
-				if (!pd_req)
-					stop = 1;
+				if (!__blk_end_request_cur(pd_req,
+						res == Ok ? 0 : -EIO)) {
+					pd_req = blk_fetch_request(pd_queue);
+					if (!pd_req)
+						stop = 1;
+				}
 				spin_unlock_irqrestore(&pd_lock, saved_flags);
 				if (stop)
 					return;
@@ -443,11 +445,11 @@
 
 	pd_cmd = rq_data_dir(pd_req);
 	if (pd_cmd == READ || pd_cmd == WRITE) {
-		pd_block = pd_req->sector;
-		pd_count = pd_req->current_nr_sectors;
+		pd_block = blk_rq_pos(pd_req);
+		pd_count = blk_rq_cur_sectors(pd_req);
 		if (pd_block + pd_count > get_capacity(pd_req->rq_disk))
 			return Fail;
-		pd_run = pd_req->nr_sectors;
+		pd_run = blk_rq_sectors(pd_req);
 		pd_buf = pd_req->buffer;
 		pd_retries = 0;
 		if (pd_cmd == READ)
@@ -477,8 +479,8 @@
 	if (pd_count)
 		return 0;
 	spin_lock_irqsave(&pd_lock, saved_flags);
-	end_request(pd_req, 1);
-	pd_count = pd_req->current_nr_sectors;
+	__blk_end_request_cur(pd_req, 0);
+	pd_count = blk_rq_cur_sectors(pd_req);
 	pd_buf = pd_req->buffer;
 	spin_unlock_irqrestore(&pd_lock, saved_flags);
 	return 0;
@@ -702,7 +704,7 @@
 {
 	if (pd_req)
 		return;
-	pd_req = elv_next_request(q);
+	pd_req = blk_fetch_request(q);
 	if (!pd_req)
 		return;
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/paride/pf.c linux-libre-2.6.31-gnu/drivers/block/paride/pf.c
--- linux-libre-2.6.30-gnu/drivers/block/paride/pf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/paride/pf.c	2009-09-09 18:13:59.000000000 -0400
@@ -750,12 +750,10 @@
 
 static struct request_queue *pf_queue;
 
-static void pf_end_request(int uptodate)
+static void pf_end_request(int err)
 {
-	if (pf_req) {
-		end_request(pf_req, uptodate);
+	if (pf_req && !__blk_end_request_cur(pf_req, err))
 		pf_req = NULL;
-	}
 }
 
 static void do_pf_request(struct request_queue * q)
@@ -763,17 +761,19 @@
 	if (pf_busy)
 		return;
 repeat:
-	pf_req = elv_next_request(q);
-	if (!pf_req)
-		return;
+	if (!pf_req) {
+		pf_req = blk_fetch_request(q);
+		if (!pf_req)
+			return;
+	}
 
 	pf_current = pf_req->rq_disk->private_data;
-	pf_block = pf_req->sector;
-	pf_run = pf_req->nr_sectors;
-	pf_count = pf_req->current_nr_sectors;
+	pf_block = blk_rq_pos(pf_req);
+	pf_run = blk_rq_sectors(pf_req);
+	pf_count = blk_rq_cur_sectors(pf_req);
 
 	if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
-		pf_end_request(0);
+		pf_end_request(-EIO);
 		goto repeat;
 	}
 
@@ -788,7 +788,7 @@
 		pi_do_claimed(pf_current->pi, do_pf_write);
 	else {
 		pf_busy = 0;
-		pf_end_request(0);
+		pf_end_request(-EIO);
 		goto repeat;
 	}
 }
@@ -805,23 +805,22 @@
 		return 1;
 	if (!pf_count) {
 		spin_lock_irqsave(&pf_spin_lock, saved_flags);
-		pf_end_request(1);
-		pf_req = elv_next_request(pf_queue);
+		pf_end_request(0);
 		spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
 		if (!pf_req)
 			return 1;
-		pf_count = pf_req->current_nr_sectors;
+		pf_count = blk_rq_cur_sectors(pf_req);
 		pf_buf = pf_req->buffer;
 	}
 	return 0;
 }
 
-static inline void next_request(int success)
+static inline void next_request(int err)
 {
 	unsigned long saved_flags;
 
 	spin_lock_irqsave(&pf_spin_lock, saved_flags);
-	pf_end_request(success);
+	pf_end_request(err);
 	pf_busy = 0;
 	do_pf_request(pf_queue);
 	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
@@ -844,7 +843,7 @@
 			pi_do_claimed(pf_current->pi, do_pf_read_start);
 			return;
 		}
-		next_request(0);
+		next_request(-EIO);
 		return;
 	}
 	pf_mask = STAT_DRQ;
@@ -863,7 +862,7 @@
 				pi_do_claimed(pf_current->pi, do_pf_read_start);
 				return;
 			}
-			next_request(0);
+			next_request(-EIO);
 			return;
 		}
 		pi_read_block(pf_current->pi, pf_buf, 512);
@@ -871,7 +870,7 @@
 			break;
 	}
 	pi_disconnect(pf_current->pi);
-	next_request(1);
+	next_request(0);
 }
 
 static void do_pf_write(void)
@@ -890,7 +889,7 @@
 			pi_do_claimed(pf_current->pi, do_pf_write_start);
 			return;
 		}
-		next_request(0);
+		next_request(-EIO);
 		return;
 	}
 
@@ -903,7 +902,7 @@
 				pi_do_claimed(pf_current->pi, do_pf_write_start);
 				return;
 			}
-			next_request(0);
+			next_request(-EIO);
 			return;
 		}
 		pi_write_block(pf_current->pi, pf_buf, 512);
@@ -923,11 +922,11 @@
 			pi_do_claimed(pf_current->pi, do_pf_write_start);
 			return;
 		}
-		next_request(0);
+		next_request(-EIO);
 		return;
 	}
 	pi_disconnect(pf_current->pi);
-	next_request(1);
+	next_request(0);
 }
 
 static int __init pf_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/block/pktcdvd.c linux-libre-2.6.31-gnu/drivers/block/pktcdvd.c
--- linux-libre-2.6.30-gnu/drivers/block/pktcdvd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/pktcdvd.c	2009-09-09 18:13:59.000000000 -0400
@@ -430,7 +430,7 @@
 /********************************************************************
   entries in debugfs
 
-  /debugfs/pktcdvd[0-7]/
+  /sys/kernel/debug/pktcdvd[0-7]/
 			info
 
  *******************************************************************/
@@ -991,13 +991,15 @@
  */
 static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q)
 {
-	if ((pd->settings.size << 9) / CD_FRAMESIZE <= q->max_phys_segments) {
+	if ((pd->settings.size << 9) / CD_FRAMESIZE
+	    <= queue_max_phys_segments(q)) {
 		/*
 		 * The cdrom device can handle one segment/frame
 		 */
 		clear_bit(PACKET_MERGE_SEGS, &pd->flags);
 		return 0;
-	} else if ((pd->settings.size << 9) / PAGE_SIZE <= q->max_phys_segments) {
+	} else if ((pd->settings.size << 9) / PAGE_SIZE
+		   <= queue_max_phys_segments(q)) {
 		/*
 		 * We can handle this case at the expense of some extra memory
 		 * copies during write operations
@@ -1370,8 +1372,10 @@
 	wakeup = (pd->write_congestion_on > 0
 	 		&& pd->bio_queue_size <= pd->write_congestion_off);
 	spin_unlock(&pd->lock);
-	if (wakeup)
-		clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE);
+	if (wakeup) {
+		clear_bdi_congested(&pd->disk->queue->backing_dev_info,
+					BLK_RW_ASYNC);
+	}
 
 	pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
 	pkt_set_state(pkt, PACKET_WAITING_STATE);
@@ -2590,10 +2594,10 @@
 	spin_lock(&pd->lock);
 	if (pd->write_congestion_on > 0
 	    && pd->bio_queue_size >= pd->write_congestion_on) {
-		set_bdi_congested(&q->backing_dev_info, WRITE);
+		set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC);
 		do {
 			spin_unlock(&pd->lock);
-			congestion_wait(WRITE, HZ);
+			congestion_wait(BLK_RW_ASYNC, HZ);
 			spin_lock(&pd->lock);
 		} while(pd->bio_queue_size > pd->write_congestion_off);
 	}
@@ -2657,7 +2661,7 @@
 	struct request_queue *q = pd->disk->queue;
 
 	blk_queue_make_request(q, pkt_make_request);
-	blk_queue_hardsect_size(q, CD_FRAMESIZE);
+	blk_queue_logical_block_size(q, CD_FRAMESIZE);
 	blk_queue_max_sectors(q, PACKET_MAX_SECTORS);
 	blk_queue_merge_bvec(q, pkt_merge_bvec);
 	q->queuedata = pd;
@@ -2853,6 +2857,11 @@
 	.media_changed =	pkt_media_changed,
 };
 
+static char *pktcdvd_nodename(struct gendisk *gd)
+{
+	return kasprintf(GFP_KERNEL, "pktcdvd/%s", gd->disk_name);
+}
+
 /*
  * Set up mapping from pktcdvd device to CD-ROM device.
  */
@@ -2905,6 +2914,7 @@
 	disk->fops = &pktcdvd_ops;
 	disk->flags = GENHD_FL_REMOVABLE;
 	strcpy(disk->disk_name, pd->name);
+	disk->nodename = pktcdvd_nodename;
 	disk->private_data = pd;
 	disk->queue = blk_alloc_queue(GFP_KERNEL);
 	if (!disk->queue)
@@ -3060,6 +3070,7 @@
 static struct miscdevice pkt_misc = {
 	.minor 		= MISC_DYNAMIC_MINOR,
 	.name  		= DRIVER_NAME,
+	.name  		= "pktcdvd/control",
 	.fops  		= &pkt_ctl_fops
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/ps3disk.c linux-libre-2.6.31-gnu/drivers/block/ps3disk.c
--- linux-libre-2.6.30-gnu/drivers/block/ps3disk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/ps3disk.c	2009-09-09 18:13:59.000000000 -0400
@@ -120,7 +120,7 @@
 static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
 				     struct request *req)
 {
-	struct ps3disk_private *priv = dev->sbd.core.driver_data;
+	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	int write = rq_data_dir(req), res;
 	const char *op = write ? "write" : "read";
 	u64 start_sector, sectors;
@@ -134,13 +134,12 @@
 	rq_for_each_segment(bv, req, iter)
 		n++;
 	dev_dbg(&dev->sbd.core,
-		"%s:%u: %s req has %u bvecs for %lu sectors %lu hard sectors\n",
-		__func__, __LINE__, op, n, req->nr_sectors,
-		req->hard_nr_sectors);
+		"%s:%u: %s req has %u bvecs for %u sectors\n",
+		__func__, __LINE__, op, n, blk_rq_sectors(req));
 #endif
 
-	start_sector = req->sector * priv->blocking_factor;
-	sectors = req->nr_sectors * priv->blocking_factor;
+	start_sector = blk_rq_pos(req) * priv->blocking_factor;
+	sectors = blk_rq_sectors(req) * priv->blocking_factor;
 	dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
 		__func__, __LINE__, op, sectors, start_sector);
 
@@ -158,7 +157,7 @@
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
 			__LINE__, op, res);
-		end_request(req, 0);
+		__blk_end_request_all(req, -EIO);
 		return 0;
 	}
 
@@ -169,7 +168,7 @@
 static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
 					struct request *req)
 {
-	struct ps3disk_private *priv = dev->sbd.core.driver_data;
+	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	u64 res;
 
 	dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__);
@@ -180,7 +179,7 @@
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
 			__func__, __LINE__, res);
-		end_request(req, 0);
+		__blk_end_request_all(req, -EIO);
 		return 0;
 	}
 
@@ -195,7 +194,7 @@
 
 	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
 
-	while ((req = elv_next_request(q))) {
+	while ((req = blk_fetch_request(q))) {
 		if (blk_fs_request(req)) {
 			if (ps3disk_submit_request_sg(dev, req))
 				break;
@@ -205,7 +204,7 @@
 				break;
 		} else {
 			blk_dump_rq_flags(req, DEVICE_NAME " bad request");
-			end_request(req, 0);
+			__blk_end_request_all(req, -EIO);
 			continue;
 		}
 	}
@@ -214,7 +213,7 @@
 static void ps3disk_request(struct request_queue *q)
 {
 	struct ps3_storage_device *dev = q->queuedata;
-	struct ps3disk_private *priv = dev->sbd.core.driver_data;
+	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 
 	if (priv->req) {
 		dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__);
@@ -231,7 +230,6 @@
 	struct request *req;
 	int res, read, error;
 	u64 tag, status;
-	unsigned long num_sectors;
 	const char *op;
 
 	res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
@@ -247,7 +245,7 @@
 		return IRQ_HANDLED;
 	}
 
-	priv = dev->sbd.core.driver_data;
+	priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	req = priv->req;
 	if (!req) {
 		dev_dbg(&dev->sbd.core,
@@ -261,11 +259,9 @@
 	if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
 	    req->cmd[0] == REQ_LB_OP_FLUSH) {
 		read = 0;
-		num_sectors = req->hard_cur_sectors;
 		op = "flush";
 	} else {
 		read = !rq_data_dir(req);
-		num_sectors = req->nr_sectors;
 		op = read ? "read" : "write";
 	}
 	if (status) {
@@ -281,7 +277,7 @@
 	}
 
 	spin_lock(&priv->lock);
-	__blk_end_request(req, error, num_sectors << 9);
+	__blk_end_request_all(req, error);
 	priv->req = NULL;
 	ps3disk_do_request(dev, priv->queue);
 	spin_unlock(&priv->lock);
@@ -368,7 +364,7 @@
 
 static int ps3disk_identify(struct ps3_storage_device *dev)
 {
-	struct ps3disk_private *priv = dev->sbd.core.driver_data;
+	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	struct lv1_ata_cmnd_block ata_cmnd;
 	u16 *id = dev->bounce_buf;
 	u64 res;
@@ -449,7 +445,7 @@
 		goto fail;
 	}
 
-	dev->sbd.core.driver_data = priv;
+	ps3_system_bus_set_drvdata(_dev, priv);
 	spin_lock_init(&priv->lock);
 
 	dev->bounce_size = BOUNCE_SIZE;
@@ -481,7 +477,7 @@
 	blk_queue_max_sectors(queue, dev->bounce_size >> 9);
 	blk_queue_segment_boundary(queue, -1UL);
 	blk_queue_dma_alignment(queue, dev->blk_size-1);
-	blk_queue_hardsect_size(queue, dev->blk_size);
+	blk_queue_logical_block_size(queue, dev->blk_size);
 
 	blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH,
 			  ps3disk_prepare_flush);
@@ -527,7 +523,7 @@
 	kfree(dev->bounce_buf);
 fail_free_priv:
 	kfree(priv);
-	dev->sbd.core.driver_data = NULL;
+	ps3_system_bus_set_drvdata(_dev, NULL);
 fail:
 	mutex_lock(&ps3disk_mask_mutex);
 	__clear_bit(devidx, &ps3disk_mask);
@@ -538,7 +534,7 @@
 static int ps3disk_remove(struct ps3_system_bus_device *_dev)
 {
 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
-	struct ps3disk_private *priv = dev->sbd.core.driver_data;
+	struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 
 	mutex_lock(&ps3disk_mask_mutex);
 	__clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS,
@@ -552,7 +548,7 @@
 	ps3stor_teardown(dev);
 	kfree(dev->bounce_buf);
 	kfree(priv);
-	dev->sbd.core.driver_data = NULL;
+	ps3_system_bus_set_drvdata(_dev, NULL);
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/ps3vram.c linux-libre-2.6.31-gnu/drivers/block/ps3vram.c
--- linux-libre-2.6.30-gnu/drivers/block/ps3vram.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/ps3vram.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,8 +14,10 @@
 #include <linux/seq_file.h>
 
 #include <asm/firmware.h>
+#include <asm/iommu.h>
 #include <asm/lv1call.h>
 #include <asm/ps3.h>
+#include <asm/ps3gpu.h>
 
 
 #define DEVICE_NAME		"ps3vram"
@@ -45,8 +47,6 @@
 #define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN	0x0000030c
 #define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY	0x00000104
 
-#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601
-
 #define CACHE_PAGE_PRESENT 1
 #define CACHE_PAGE_DIRTY   2
 
@@ -72,8 +72,7 @@
 	u64 memory_handle;
 	u64 context_handle;
 	u32 *ctrl;
-	u32 *reports;
-	u8 __iomem *ddr_base;
+	void *reports;
 	u8 *xdr_buf;
 
 	u32 *fifo_base;
@@ -81,8 +80,8 @@
 
 	struct ps3vram_cache cache;
 
-	/* Used to serialize cache/DMA operations */
-	struct mutex lock;
+	spinlock_t lock;	/* protecting list of bios */
+	struct bio_list list;
 };
 
 
@@ -103,15 +102,15 @@
 module_param(size, charp, 0);
 MODULE_PARM_DESC(size, "memory size");
 
-static u32 *ps3vram_get_notifier(u32 *reports, int notifier)
+static u32 *ps3vram_get_notifier(void *reports, int notifier)
 {
-	return (void *)reports + DMA_NOTIFIER_OFFSET_BASE +
+	return reports + DMA_NOTIFIER_OFFSET_BASE +
 	       DMA_NOTIFIER_SIZE * notifier;
 }
 
 static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
 	int i;
 
@@ -122,7 +121,7 @@
 static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev,
 				 unsigned int timeout_ms)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
 	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
 
@@ -137,7 +136,7 @@
 
 static void ps3vram_init_ring(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
 	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
 	priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET;
@@ -146,7 +145,7 @@
 static int ps3vram_wait_ring(struct ps3_system_bus_device *dev,
 			     unsigned int timeout_ms)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
 
 	do {
@@ -175,7 +174,7 @@
 
 static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	int status;
 
 	ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET));
@@ -183,20 +182,17 @@
 	priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
 
 	/* asking the HV for a blit will kick the FIFO */
-	status = lv1_gpu_context_attribute(priv->context_handle,
-					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0,
-					   0, 0, 0);
+	status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
 	if (status)
-		dev_err(&dev->core,
-			"%s: lv1_gpu_context_attribute failed %d\n", __func__,
-			status);
+		dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n",
+			__func__, status);
 
 	priv->fifo_ptr = priv->fifo_base;
 }
 
 static void ps3vram_fire_ring(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	int status;
 
 	mutex_lock(&ps3_gpu_mutex);
@@ -205,13 +201,10 @@
 			       (priv->fifo_ptr - priv->fifo_base) * sizeof(u32);
 
 	/* asking the HV for a blit will kick the FIFO */
-	status = lv1_gpu_context_attribute(priv->context_handle,
-					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0,
-					   0, 0, 0);
+	status = lv1_gpu_fb_blit(priv->context_handle, 0, 0, 0, 0);
 	if (status)
-		dev_err(&dev->core,
-			"%s: lv1_gpu_context_attribute failed %d\n", __func__,
-			status);
+		dev_err(&dev->core, "%s: lv1_gpu_fb_blit failed %d\n",
+			__func__, status);
 
 	if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) >
 	    FIFO_SIZE - 1024) {
@@ -225,7 +218,7 @@
 
 static void ps3vram_bind(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
 	ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1);
 	ps3vram_out_ring(priv, 0x31337303);
@@ -248,7 +241,7 @@
 			  unsigned int src_offset, unsigned int dst_offset,
 			  int len, int count)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
 	ps3vram_begin_ring(priv, UPLOAD_SUBCH,
 			   NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
@@ -280,7 +273,7 @@
 			    unsigned int src_offset, unsigned int dst_offset,
 			    int len, int count)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
 	ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
 			   NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
@@ -310,7 +303,7 @@
 
 static void ps3vram_cache_evict(struct ps3_system_bus_device *dev, int entry)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	struct ps3vram_cache *cache = &priv->cache;
 
 	if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY))
@@ -332,7 +325,7 @@
 static void ps3vram_cache_load(struct ps3_system_bus_device *dev, int entry,
 			       unsigned int address)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	struct ps3vram_cache *cache = &priv->cache;
 
 	dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address);
@@ -352,7 +345,7 @@
 
 static void ps3vram_cache_flush(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	struct ps3vram_cache *cache = &priv->cache;
 	int i;
 
@@ -366,7 +359,7 @@
 static unsigned int ps3vram_cache_match(struct ps3_system_bus_device *dev,
 					loff_t address)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	struct ps3vram_cache *cache = &priv->cache;
 	unsigned int base;
 	unsigned int offset;
@@ -400,7 +393,7 @@
 
 static int ps3vram_cache_init(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
 	priv->cache.page_count = CACHE_PAGE_COUNT;
 	priv->cache.page_size = CACHE_PAGE_SIZE;
@@ -419,7 +412,7 @@
 
 static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
 	ps3vram_cache_flush(dev);
 	kfree(priv->cache.tags);
@@ -428,7 +421,7 @@
 static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
 			size_t len, size_t *retlen, u_char *buf)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	unsigned int cached, count;
 
 	dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__,
@@ -449,8 +442,6 @@
 		offset = (unsigned int) (from & (priv->cache.page_size - 1));
 		avail  = priv->cache.page_size - offset;
 
-		mutex_lock(&priv->lock);
-
 		entry = ps3vram_cache_match(dev, from);
 		cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
 
@@ -462,8 +453,6 @@
 			avail = count;
 		memcpy(buf, priv->xdr_buf + cached, avail);
 
-		mutex_unlock(&priv->lock);
-
 		buf += avail;
 		count -= avail;
 		from += avail;
@@ -476,7 +465,7 @@
 static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
 			 size_t len, size_t *retlen, const u_char *buf)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	unsigned int cached, count;
 
 	if (to >= priv->size)
@@ -494,8 +483,6 @@
 		offset = (unsigned int) (to & (priv->cache.page_size - 1));
 		avail  = priv->cache.page_size - offset;
 
-		mutex_lock(&priv->lock);
-
 		entry = ps3vram_cache_match(dev, to);
 		cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
 
@@ -509,8 +496,6 @@
 
 		priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY;
 
-		mutex_unlock(&priv->lock);
-
 		buf += avail;
 		count -= avail;
 		to += avail;
@@ -543,28 +528,26 @@
 
 static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	struct proc_dir_entry *pde;
 
-	pde = proc_create(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops);
-	if (!pde) {
+	pde = proc_create_data(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops,
+			       priv);
+	if (!pde)
 		dev_warn(&dev->core, "failed to create /proc entry\n");
-		return;
-	}
-	pde->data = priv;
 }
 
-static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
+				  struct bio *bio)
 {
-	struct ps3_system_bus_device *dev = q->queuedata;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 	int write = bio_data_dir(bio) == WRITE;
 	const char *op = write ? "write" : "read";
 	loff_t offset = bio->bi_sector << 9;
 	int error = 0;
 	struct bio_vec *bvec;
 	unsigned int i;
-
-	dev_dbg(&dev->core, "%s\n", __func__);
+	struct bio *next;
 
 	bio_for_each_segment(bvec, bio, i) {
 		/* PS3 is ppc64, so we don't handle highmem */
@@ -585,6 +568,7 @@
 
 		if (retlen != len) {
 			dev_err(&dev->core, "Short %s\n", op);
+			error = -EIO;
 			goto out;
 		}
 
@@ -594,7 +578,35 @@
 	dev_dbg(&dev->core, "%s completed\n", op);
 
 out:
+	spin_lock_irq(&priv->lock);
+	bio_list_pop(&priv->list);
+	next = bio_list_peek(&priv->list);
+	spin_unlock_irq(&priv->lock);
+
 	bio_endio(bio, error);
+	return next;
+}
+
+static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+{
+	struct ps3_system_bus_device *dev = q->queuedata;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
+	int busy;
+
+	dev_dbg(&dev->core, "%s\n", __func__);
+
+	spin_lock_irq(&priv->lock);
+	busy = !bio_list_empty(&priv->list);
+	bio_list_add(&priv->list, bio);
+	spin_unlock_irq(&priv->lock);
+
+	if (busy)
+		return 0;
+
+	do {
+		bio = ps3vram_do_bio(dev, bio);
+	} while (bio);
+
 	return 0;
 }
 
@@ -604,8 +616,8 @@
 	int error, status;
 	struct request_queue *queue;
 	struct gendisk *gendisk;
-	u64 ddr_lpar, ctrl_lpar, info_lpar, reports_lpar, ddr_size,
-	    reports_size;
+	u64 ddr_size, ddr_lpar, ctrl_lpar, info_lpar, reports_lpar,
+	    reports_size, xdr_lpar;
 	char *rest;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -614,10 +626,9 @@
 		goto fail;
 	}
 
-	mutex_init(&priv->lock);
-	dev->core.driver_data = priv;
-
-	priv = dev->core.driver_data;
+	spin_lock_init(&priv->lock);
+	bio_list_init(&priv->list);
+	ps3_system_bus_set_drvdata(dev, priv);
 
 	/* Allocate XDR buffer (1MiB aligned) */
 	priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL,
@@ -636,7 +647,7 @@
 	if (ps3_open_hv_device(dev)) {
 		dev_err(&dev->core, "ps3_open_hv_device failed\n");
 		error = -EAGAIN;
-		goto out_close_gpu;
+		goto out_free_xdr_buf;
 	}
 
 	/* Request memory */
@@ -660,7 +671,7 @@
 		dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n",
 			status);
 		error = -ENOMEM;
-		goto out_free_xdr_buf;
+		goto out_close_gpu;
 	}
 
 	/* Request context */
@@ -676,9 +687,11 @@
 	}
 
 	/* Map XDR buffer to RSX */
+	xdr_lpar = ps3_mm_phys_to_lpar(__pa(priv->xdr_buf));
 	status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF,
-				       ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)),
-				       XDR_BUF_SIZE, 0);
+				       xdr_lpar, XDR_BUF_SIZE,
+				       CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
+				       CBE_IOPTE_M);
 	if (status) {
 		dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n",
 			status);
@@ -686,19 +699,11 @@
 		goto out_free_context;
 	}
 
-	priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE);
-
-	if (!priv->ddr_base) {
-		dev_err(&dev->core, "ioremap DDR failed\n");
-		error = -ENOMEM;
-		goto out_free_context;
-	}
-
 	priv->ctrl = ioremap(ctrl_lpar, 64 * 1024);
 	if (!priv->ctrl) {
 		dev_err(&dev->core, "ioremap CTRL failed\n");
 		error = -ENOMEM;
-		goto out_unmap_vram;
+		goto out_unmap_context;
 	}
 
 	priv->reports = ioremap(reports_lpar, reports_size);
@@ -775,8 +780,9 @@
 	iounmap(priv->reports);
 out_unmap_ctrl:
 	iounmap(priv->ctrl);
-out_unmap_vram:
-	iounmap(priv->ddr_base);
+out_unmap_context:
+	lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, xdr_lpar,
+			      XDR_BUF_SIZE, CBE_IOPTE_M);
 out_free_context:
 	lv1_gpu_context_free(priv->context_handle);
 out_free_memory:
@@ -787,14 +793,14 @@
 	free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
 fail_free_priv:
 	kfree(priv);
-	dev->core.driver_data = NULL;
+	ps3_system_bus_set_drvdata(dev, NULL);
 fail:
 	return error;
 }
 
 static int ps3vram_remove(struct ps3_system_bus_device *dev)
 {
-	struct ps3vram_priv *priv = dev->core.driver_data;
+	struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
 
 	del_gendisk(priv->gendisk);
 	put_disk(priv->gendisk);
@@ -803,13 +809,15 @@
 	ps3vram_cache_cleanup(dev);
 	iounmap(priv->reports);
 	iounmap(priv->ctrl);
-	iounmap(priv->ddr_base);
+	lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF,
+			      ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)),
+			      XDR_BUF_SIZE, CBE_IOPTE_M);
 	lv1_gpu_context_free(priv->context_handle);
 	lv1_gpu_memory_free(priv->memory_handle);
 	ps3_close_hv_device(dev);
 	free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
 	kfree(priv);
-	dev->core.driver_data = NULL;
+	ps3_system_bus_set_drvdata(dev, NULL);
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/sunvdc.c linux-libre-2.6.31-gnu/drivers/block/sunvdc.c
--- linux-libre-2.6.30-gnu/drivers/block/sunvdc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/sunvdc.c	2009-09-09 18:13:59.000000000 -0400
@@ -212,11 +212,6 @@
 	vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
 }
 
-static void vdc_end_request(struct request *req, int error, int num_sectors)
-{
-	__blk_end_request(req, error, num_sectors << 9);
-}
-
 static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
 			unsigned int index)
 {
@@ -239,7 +234,7 @@
 
 	rqe->req = NULL;
 
-	vdc_end_request(req, (desc->status ? -EIO : 0), desc->size >> 9);
+	__blk_end_request(req, (desc->status ? -EIO : 0), desc->size);
 
 	if (blk_queue_stopped(port->disk->queue))
 		blk_start_queue(port->disk->queue);
@@ -421,7 +416,7 @@
 		desc->slice = 0;
 	}
 	desc->status = ~0;
-	desc->offset = (req->sector << 9) / port->vdisk_block_size;
+	desc->offset = (blk_rq_pos(req) << 9) / port->vdisk_block_size;
 	desc->size = len;
 	desc->ncookies = err;
 
@@ -446,14 +441,13 @@
 static void do_vdc_request(struct request_queue *q)
 {
 	while (1) {
-		struct request *req = elv_next_request(q);
+		struct request *req = blk_fetch_request(q);
 
 		if (!req)
 			break;
 
-		blkdev_dequeue_request(req);
 		if (__send_request(req) < 0)
-			vdc_end_request(req, -EIO, req->hard_nr_sectors);
+			__blk_end_request_all(req, -EIO);
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/swim3.c linux-libre-2.6.31-gnu/drivers/block/swim3.c
--- linux-libre-2.6.30-gnu/drivers/block/swim3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/swim3.c	2009-09-09 18:13:59.000000000 -0400
@@ -251,6 +251,20 @@
 static int floppy_check_change(struct gendisk *disk);
 static int floppy_revalidate(struct gendisk *disk);
 
+static bool swim3_end_request(int err, unsigned int nr_bytes)
+{
+	if (__blk_end_request(fd_req, err, nr_bytes))
+		return true;
+
+	fd_req = NULL;
+	return false;
+}
+
+static bool swim3_end_request_cur(int err)
+{
+	return swim3_end_request(err, blk_rq_cur_bytes(fd_req));
+}
+
 static void swim3_select(struct floppy_state *fs, int sel)
 {
 	struct swim3 __iomem *sw = fs->swim3;
@@ -310,25 +324,27 @@
 		wake_up(&fs->wait);
 		return;
 	}
-	while (fs->state == idle && (req = elv_next_request(swim3_queue))) {
+	while (fs->state == idle) {
+		if (!fd_req) {
+			fd_req = blk_fetch_request(swim3_queue);
+			if (!fd_req)
+				break;
+		}
+		req = fd_req;
 #if 0
-		printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
+		printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n",
 		       req->rq_disk->disk_name, req->cmd,
-		       (long)req->sector, req->nr_sectors, req->buffer);
-		printk("           errors=%d current_nr_sectors=%ld\n",
-		       req->errors, req->current_nr_sectors);
+		       (long)blk_rq_pos(req), blk_rq_sectors(req), req->buffer);
+		printk("           errors=%d current_nr_sectors=%u\n",
+		       req->errors, blk_rq_cur_sectors(req));
 #endif
 
-		if (req->sector < 0 || req->sector >= fs->total_secs) {
-			end_request(req, 0);
-			continue;
-		}
-		if (req->current_nr_sectors == 0) {
-			end_request(req, 1);
+		if (blk_rq_pos(req) >= fs->total_secs) {
+			swim3_end_request_cur(-EIO);
 			continue;
 		}
 		if (fs->ejected) {
-			end_request(req, 0);
+			swim3_end_request_cur(-EIO);
 			continue;
 		}
 
@@ -336,18 +352,19 @@
 			if (fs->write_prot < 0)
 				fs->write_prot = swim3_readbit(fs, WRITE_PROT);
 			if (fs->write_prot) {
-				end_request(req, 0);
+				swim3_end_request_cur(-EIO);
 				continue;
 			}
 		}
 
-		/* Do not remove the cast. req->sector is now a sector_t and
-		 * can be 64 bits, but it will never go past 32 bits for this
-		 * driver anyway, so we can safely cast it down and not have
-		 * to do a 64/32 division
+		/* Do not remove the cast. blk_rq_pos(req) is now a
+		 * sector_t and can be 64 bits, but it will never go
+		 * past 32 bits for this driver anyway, so we can
+		 * safely cast it down and not have to do a 64/32
+		 * division
 		 */
-		fs->req_cyl = ((long)req->sector) / fs->secpercyl;
-		x = ((long)req->sector) % fs->secpercyl;
+		fs->req_cyl = ((long)blk_rq_pos(req)) / fs->secpercyl;
+		x = ((long)blk_rq_pos(req)) % fs->secpercyl;
 		fs->head = x / fs->secpertrack;
 		fs->req_sector = x % fs->secpertrack + 1;
 		fd_req = req;
@@ -424,7 +441,7 @@
 	struct dbdma_cmd *cp = fs->dma_cmd;
 	struct dbdma_regs __iomem *dr = fs->dma;
 
-	if (fd_req->current_nr_sectors <= 0) {
+	if (blk_rq_cur_sectors(fd_req) <= 0) {
 		printk(KERN_ERR "swim3: transfer 0 sectors?\n");
 		return;
 	}
@@ -432,8 +449,8 @@
 		n = 1;
 	else {
 		n = fs->secpertrack - fs->req_sector + 1;
-		if (n > fd_req->current_nr_sectors)
-			n = fd_req->current_nr_sectors;
+		if (n > blk_rq_cur_sectors(fd_req))
+			n = blk_rq_cur_sectors(fd_req);
 	}
 	fs->scount = n;
 	swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0);
@@ -508,7 +525,7 @@
 		case do_transfer:
 			if (fs->cur_cyl != fs->req_cyl) {
 				if (fs->retries > 5) {
-					end_request(fd_req, 0);
+					swim3_end_request_cur(-EIO);
 					fs->state = idle;
 					return;
 				}
@@ -540,7 +557,7 @@
 	out_8(&sw->intr_enable, 0);
 	fs->cur_cyl = -1;
 	if (fs->retries > 5) {
-		end_request(fd_req, 0);
+		swim3_end_request_cur(-EIO);
 		fs->state = idle;
 		start_request(fs);
 	} else {
@@ -559,7 +576,7 @@
 	out_8(&sw->select, RELAX);
 	out_8(&sw->intr_enable, 0);
 	printk(KERN_ERR "swim3: seek timeout\n");
-	end_request(fd_req, 0);
+	swim3_end_request_cur(-EIO);
 	fs->state = idle;
 	start_request(fs);
 }
@@ -583,7 +600,7 @@
 		return;
 	}
 	printk(KERN_ERR "swim3: seek settle timeout\n");
-	end_request(fd_req, 0);
+	swim3_end_request_cur(-EIO);
 	fs->state = idle;
 	start_request(fs);
 }
@@ -593,8 +610,6 @@
 	struct floppy_state *fs = (struct floppy_state *) data;
 	struct swim3 __iomem *sw = fs->swim3;
 	struct dbdma_regs __iomem *dr = fs->dma;
-	struct dbdma_cmd *cp = fs->dma_cmd;
-	unsigned long s;
 	int n;
 
 	fs->timeout_pending = 0;
@@ -605,17 +620,10 @@
 	out_8(&sw->intr_enable, 0);
 	out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION);
 	out_8(&sw->select, RELAX);
-	if (rq_data_dir(fd_req) == WRITE)
-		++cp;
-	if (ld_le16(&cp->xfer_status) != 0)
-		s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9);
-	else
-		s = 0;
-	fd_req->sector += s;
-	fd_req->current_nr_sectors -= s;
 	printk(KERN_ERR "swim3: timeout %sing sector %ld\n",
-	       (rq_data_dir(fd_req)==WRITE? "writ": "read"), (long)fd_req->sector);
-	end_request(fd_req, 0);
+	       (rq_data_dir(fd_req)==WRITE? "writ": "read"),
+	       (long)blk_rq_pos(fd_req));
+	swim3_end_request_cur(-EIO);
 	fs->state = idle;
 	start_request(fs);
 }
@@ -646,7 +654,7 @@
 				printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");
 				fs->cur_cyl = -1;
 				if (fs->retries > 5) {
-					end_request(fd_req, 0);
+					swim3_end_request_cur(-EIO);
 					fs->state = idle;
 					start_request(fs);
 				} else {
@@ -719,9 +727,7 @@
 		if (intr & ERROR_INTR) {
 			n = fs->scount - 1 - resid / 512;
 			if (n > 0) {
-				fd_req->sector += n;
-				fd_req->current_nr_sectors -= n;
-				fd_req->buffer += n * 512;
+				blk_update_request(fd_req, 0, n << 9);
 				fs->req_sector += n;
 			}
 			if (fs->retries < 5) {
@@ -730,8 +736,8 @@
 			} else {
 				printk("swim3: error %sing block %ld (err=%x)\n",
 				       rq_data_dir(fd_req) == WRITE? "writ": "read",
-				       (long)fd_req->sector, err);
-				end_request(fd_req, 0);
+				       (long)blk_rq_pos(fd_req), err);
+				swim3_end_request_cur(-EIO);
 				fs->state = idle;
 			}
 		} else {
@@ -740,18 +746,12 @@
 				printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
 				printk(KERN_ERR "  state=%d, dir=%x, intr=%x, err=%x\n",
 				       fs->state, rq_data_dir(fd_req), intr, err);
-				end_request(fd_req, 0);
+				swim3_end_request_cur(-EIO);
 				fs->state = idle;
 				start_request(fs);
 				break;
 			}
-			fd_req->sector += fs->scount;
-			fd_req->current_nr_sectors -= fs->scount;
-			fd_req->buffer += fs->scount * 512;
-			if (fd_req->current_nr_sectors <= 0) {
-				end_request(fd_req, 1);
-				fs->state = idle;
-			} else {
+			if (swim3_end_request(0, fs->scount << 9)) {
 				fs->req_sector += fs->scount;
 				if (fs->req_sector > fs->secpertrack) {
 					fs->req_sector -= fs->secpertrack;
@@ -761,7 +761,8 @@
 					}
 				}
 				act(fs);
-			}
+			} else
+				fs->state = idle;
 		}
 		if (fs->state == idle)
 			start_request(fs);
diff -druN linux-libre-2.6.30-gnu/drivers/block/swim.c linux-libre-2.6.31-gnu/drivers/block/swim.c
--- linux-libre-2.6.30-gnu/drivers/block/swim.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/swim.c	2009-09-09 18:13:59.000000000 -0400
@@ -514,7 +514,7 @@
 			ret = swim_read_sector(fs, side, track, sector,
 						buffer);
 			if (try-- == 0)
-				return -1;
+				return -EIO;
 		} while (ret != 512);
 
 		buffer += ret;
@@ -528,45 +528,31 @@
 	struct request *req;
 	struct floppy_state *fs;
 
-	while ((req = elv_next_request(q))) {
+	req = blk_fetch_request(q);
+	while (req) {
+		int err = -EIO;
 
 		fs = req->rq_disk->private_data;
-		if (req->sector < 0 || req->sector >= fs->total_secs) {
-			end_request(req, 0);
-			continue;
-		}
-		if (req->current_nr_sectors == 0) {
-			end_request(req, 1);
-			continue;
-		}
-		if (!fs->disk_in) {
-			end_request(req, 0);
-			continue;
-		}
-		if (rq_data_dir(req) == WRITE) {
-			if (fs->write_protected) {
-				end_request(req, 0);
-				continue;
-			}
-		}
+		if (blk_rq_pos(req) >= fs->total_secs)
+			goto done;
+		if (!fs->disk_in)
+			goto done;
+		if (rq_data_dir(req) == WRITE && fs->write_protected)
+			goto done;
+
 		switch (rq_data_dir(req)) {
 		case WRITE:
 			/* NOT IMPLEMENTED */
-			end_request(req, 0);
 			break;
 		case READ:
-			if (floppy_read_sectors(fs, req->sector,
-						req->current_nr_sectors,
-						req->buffer)) {
-				end_request(req, 0);
-				continue;
-			}
-			req->nr_sectors -= req->current_nr_sectors;
-			req->sector += req->current_nr_sectors;
-			req->buffer += req->current_nr_sectors * 512;
-			end_request(req, 1);
+			err = floppy_read_sectors(fs, blk_rq_pos(req),
+						  blk_rq_cur_sectors(req),
+						  req->buffer);
 			break;
 		}
+	done:
+		if (!__blk_end_request_cur(req, err))
+			req = blk_fetch_request(q);
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/block/sx8.c linux-libre-2.6.31-gnu/drivers/block/sx8.c
--- linux-libre-2.6.30-gnu/drivers/block/sx8.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/sx8.c	2009-09-09 18:13:59.000000000 -0400
@@ -749,8 +749,7 @@
 	struct request *req = crq->rq;
 	int rc;
 
-	rc = __blk_end_request(req, error, blk_rq_bytes(req));
-	assert(rc == 0);
+	__blk_end_request_all(req, error);
 
 	rc = carm_put_request(host, crq);
 	assert(rc == 0);
@@ -811,12 +810,10 @@
 
 	while (1) {
 		DPRINTK("get req\n");
-		rq = elv_next_request(q);
+		rq = blk_fetch_request(q);
 		if (!rq)
 			break;
 
-		blkdev_dequeue_request(rq);
-
 		crq = rq->special;
 		assert(crq != NULL);
 		assert(crq->rq == rq);
@@ -847,7 +844,7 @@
 
 queue_one_request:
 	VPRINTK("get req\n");
-	rq = elv_next_request(q);
+	rq = blk_peek_request(q);
 	if (!rq)
 		return;
 
@@ -858,7 +855,7 @@
 	}
 	crq->rq = rq;
 
-	blkdev_dequeue_request(rq);
+	blk_start_request(rq);
 
 	if (rq_data_dir(rq) == WRITE) {
 		writing = 1;
@@ -904,10 +901,10 @@
 	msg->sg_count	= n_elem;
 	msg->sg_type	= SGT_32BIT;
 	msg->handle	= cpu_to_le32(TAG_ENCODE(crq->tag));
-	msg->lba	= cpu_to_le32(rq->sector & 0xffffffff);
-	tmp		= (rq->sector >> 16) >> 16;
+	msg->lba	= cpu_to_le32(blk_rq_pos(rq) & 0xffffffff);
+	tmp		= (blk_rq_pos(rq) >> 16) >> 16;
 	msg->lba_high	= cpu_to_le16( (u16) tmp );
-	msg->lba_count	= cpu_to_le16(rq->nr_sectors);
+	msg->lba_count	= cpu_to_le16(blk_rq_sectors(rq));
 
 	msg_size = sizeof(struct carm_msg_rw) - sizeof(msg->sg);
 	for (i = 0; i < n_elem; i++) {
diff -druN linux-libre-2.6.30-gnu/drivers/block/ub.c linux-libre-2.6.31-gnu/drivers/block/ub.c
--- linux-libre-2.6.30-gnu/drivers/block/ub.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/ub.c	2009-09-09 18:13:59.000000000 -0400
@@ -360,8 +360,7 @@
 static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_scsi_cmd *cmd, struct ub_request *urq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_end_rq(struct request *rq, unsigned int status,
-    unsigned int cmd_len);
+static void ub_end_rq(struct request *rq, unsigned int status);
 static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_request *urq, struct ub_scsi_cmd *cmd);
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -627,7 +626,7 @@
 	struct ub_lun *lun = q->queuedata;
 	struct request *rq;
 
-	while ((rq = elv_next_request(q)) != NULL) {
+	while ((rq = blk_peek_request(q)) != NULL) {
 		if (ub_request_fn_1(lun, rq) != 0) {
 			blk_stop_queue(q);
 			break;
@@ -643,14 +642,14 @@
 	int n_elem;
 
 	if (atomic_read(&sc->poison)) {
-		blkdev_dequeue_request(rq);
-		ub_end_rq(rq, DID_NO_CONNECT << 16, blk_rq_bytes(rq));
+		blk_start_request(rq);
+		ub_end_rq(rq, DID_NO_CONNECT << 16);
 		return 0;
 	}
 
 	if (lun->changed && !blk_pc_request(rq)) {
-		blkdev_dequeue_request(rq);
-		ub_end_rq(rq, SAM_STAT_CHECK_CONDITION, blk_rq_bytes(rq));
+		blk_start_request(rq);
+		ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
 		return 0;
 	}
 
@@ -660,7 +659,7 @@
 		return -1;
 	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
 
-	blkdev_dequeue_request(rq);
+	blk_start_request(rq);
 
 	urq = &lun->urq;
 	memset(urq, 0, sizeof(struct ub_request));
@@ -702,7 +701,7 @@
 
 drop:
 	ub_put_cmd(lun, cmd);
-	ub_end_rq(rq, DID_ERROR << 16, blk_rq_bytes(rq));
+	ub_end_rq(rq, DID_ERROR << 16);
 	return 0;
 }
 
@@ -723,11 +722,11 @@
 	/*
 	 * build the command
 	 *
-	 * The call to blk_queue_hardsect_size() guarantees that request
+	 * The call to blk_queue_logical_block_size() guarantees that request
 	 * is aligned, but it is given in terms of 512 byte units, always.
 	 */
-	block = rq->sector >> lun->capacity.bshift;
-	nblks = rq->nr_sectors >> lun->capacity.bshift;
+	block = blk_rq_pos(rq) >> lun->capacity.bshift;
+	nblks = blk_rq_sectors(rq) >> lun->capacity.bshift;
 
 	cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10;
 	/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
@@ -739,7 +738,7 @@
 	cmd->cdb[8] = nblks;
 	cmd->cdb_len = 10;
 
-	cmd->len = rq->nr_sectors * 512;
+	cmd->len = blk_rq_bytes(rq);
 }
 
 static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
@@ -747,7 +746,7 @@
 {
 	struct request *rq = urq->rq;
 
-	if (rq->data_len == 0) {
+	if (blk_rq_bytes(rq) == 0) {
 		cmd->dir = UB_DIR_NONE;
 	} else {
 		if (rq_data_dir(rq) == WRITE)
@@ -762,7 +761,7 @@
 	memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
 	cmd->cdb_len = rq->cmd_len;
 
-	cmd->len = rq->data_len;
+	cmd->len = blk_rq_bytes(rq);
 
 	/*
 	 * To reapply this to every URB is not as incorrect as it looks.
@@ -777,16 +776,15 @@
 	struct ub_request *urq = cmd->back;
 	struct request *rq;
 	unsigned int scsi_status;
-	unsigned int cmd_len;
 
 	rq = urq->rq;
 
 	if (cmd->error == 0) {
 		if (blk_pc_request(rq)) {
-			if (cmd->act_len >= rq->data_len)
-				rq->data_len = 0;
+			if (cmd->act_len >= rq->resid_len)
+				rq->resid_len = 0;
 			else
-				rq->data_len -= cmd->act_len;
+				rq->resid_len -= cmd->act_len;
 			scsi_status = 0;
 		} else {
 			if (cmd->act_len != cmd->len) {
@@ -818,17 +816,14 @@
 
 	urq->rq = NULL;
 
-	cmd_len = cmd->len;
 	ub_put_cmd(lun, cmd);
-	ub_end_rq(rq, scsi_status, cmd_len);
+	ub_end_rq(rq, scsi_status);
 	blk_start_queue(lun->disk->queue);
 }
 
-static void ub_end_rq(struct request *rq, unsigned int scsi_status,
-    unsigned int cmd_len)
+static void ub_end_rq(struct request *rq, unsigned int scsi_status)
 {
 	int error;
-	long rqlen;
 
 	if (scsi_status == 0) {
 		error = 0;
@@ -836,12 +831,7 @@
 		error = -EIO;
 		rq->errors = scsi_status;
 	}
-	rqlen = blk_rq_bytes(rq);    /* Oddly enough, this is the residue. */
-	if (__blk_end_request(rq, error, cmd_len)) {
-		printk(KERN_WARNING DRV_NAME
-		    ": __blk_end_request blew, %s-cmd total %u rqlen %ld\n",
-		    blk_pc_request(rq)? "pc": "fs", cmd_len, rqlen);
-	}
+	__blk_end_request_all(rq, error);
 }
 
 static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
@@ -1759,7 +1749,7 @@
 	ub_revalidate(lun->udev, lun);
 
 	/* XXX Support sector size switching like in sr.c */
-	blk_queue_hardsect_size(disk->queue, lun->capacity.bsize);
+	blk_queue_logical_block_size(disk->queue, lun->capacity.bsize);
 	set_capacity(disk, lun->capacity.nsec);
 	// set_disk_ro(sdkp->disk, lun->readonly);
 
@@ -2334,7 +2324,7 @@
 	blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);
 	blk_queue_segment_boundary(q, 0xffffffff);	/* Dubious. */
 	blk_queue_max_sectors(q, UB_MAX_SECTORS);
-	blk_queue_hardsect_size(q, lun->capacity.bsize);
+	blk_queue_logical_block_size(q, lun->capacity.bsize);
 
 	lun->disk = disk;
 	q->queuedata = lun;
diff -druN linux-libre-2.6.30-gnu/drivers/block/viodasd.c linux-libre-2.6.31-gnu/drivers/block/viodasd.c
--- linux-libre-2.6.30-gnu/drivers/block/viodasd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/viodasd.c	2009-09-09 18:13:59.000000000 -0400
@@ -252,7 +252,7 @@
 	struct viodasd_device *d;
 	unsigned long flags;
 
-	start = (u64)req->sector << 9;
+	start = (u64)blk_rq_pos(req) << 9;
 
 	if (rq_data_dir(req) == READ) {
 		direction = DMA_FROM_DEVICE;
@@ -361,19 +361,17 @@
 	 * back later.
 	 */
 	while (num_req_outstanding < VIOMAXREQ) {
-		req = elv_next_request(q);
+		req = blk_fetch_request(q);
 		if (req == NULL)
 			return;
-		/* dequeue the current request from the queue */
-		blkdev_dequeue_request(req);
 		/* check that request contains a valid command */
 		if (!blk_fs_request(req)) {
-			viodasd_end_request(req, -EIO, req->hard_nr_sectors);
+			viodasd_end_request(req, -EIO, blk_rq_sectors(req));
 			continue;
 		}
 		/* Try sending the request */
 		if (send_request(req) != 0)
-			viodasd_end_request(req, -EIO, req->hard_nr_sectors);
+			viodasd_end_request(req, -EIO, blk_rq_sectors(req));
 	}
 }
 
@@ -590,7 +588,7 @@
 		err = vio_lookup_rc(viodasd_err_table, bevent->sub_result);
 		printk(VIOD_KERN_WARNING "read/write error %d:0x%04x (%s)\n",
 				event->xRc, bevent->sub_result, err->msg);
-		num_sect = req->hard_nr_sectors;
+		num_sect = blk_rq_sectors(req);
 	}
 	qlock = req->q->queue_lock;
 	spin_lock_irqsave(qlock, irq_flags);
diff -druN linux-libre-2.6.30-gnu/drivers/block/virtio_blk.c linux-libre-2.6.31-gnu/drivers/block/virtio_blk.c
--- linux-libre-2.6.30-gnu/drivers/block/virtio_blk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/virtio_blk.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,7 @@
 	struct list_head list;
 	struct request *req;
 	struct virtio_blk_outhdr out_hdr;
+	struct virtio_scsi_inhdr in_hdr;
 	u8 status;
 };
 
@@ -50,6 +51,7 @@
 	spin_lock_irqsave(&vblk->lock, flags);
 	while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) {
 		int error;
+
 		switch (vbr->status) {
 		case VIRTIO_BLK_S_OK:
 			error = 0;
@@ -62,7 +64,13 @@
 			break;
 		}
 
-		__blk_end_request(vbr->req, error, blk_rq_bytes(vbr->req));
+		if (blk_pc_request(vbr->req)) {
+			vbr->req->resid_len = vbr->in_hdr.residual;
+			vbr->req->sense_len = vbr->in_hdr.sense_len;
+			vbr->req->errors = vbr->in_hdr.errors;
+		}
+
+		__blk_end_request_all(vbr->req, error);
 		list_del(&vbr->list);
 		mempool_free(vbr, vblk->pool);
 	}
@@ -74,7 +82,7 @@
 static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
 		   struct request *req)
 {
-	unsigned long num, out, in;
+	unsigned long num, out = 0, in = 0;
 	struct virtblk_req *vbr;
 
 	vbr = mempool_alloc(vblk->pool, GFP_ATOMIC);
@@ -85,7 +93,7 @@
 	vbr->req = req;
 	if (blk_fs_request(vbr->req)) {
 		vbr->out_hdr.type = 0;
-		vbr->out_hdr.sector = vbr->req->sector;
+		vbr->out_hdr.sector = blk_rq_pos(vbr->req);
 		vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
 	} else if (blk_pc_request(vbr->req)) {
 		vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD;
@@ -99,18 +107,36 @@
 	if (blk_barrier_rq(vbr->req))
 		vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER;
 
-	sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
-	num = blk_rq_map_sg(q, vbr->req, vblk->sg+1);
-	sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status));
+	sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
 
-	if (rq_data_dir(vbr->req) == WRITE) {
-		vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
-		out = 1 + num;
-		in = 1;
-	} else {
-		vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
-		out = 1;
-		in = 1 + num;
+	/*
+	 * If this is a packet command we need a couple of additional headers.
+	 * Behind the normal outhdr we put a segment with the scsi command
+	 * block, and before the normal inhdr we put the sense data and the
+	 * inhdr with additional status information before the normal inhdr.
+	 */
+	if (blk_pc_request(vbr->req))
+		sg_set_buf(&vblk->sg[out++], vbr->req->cmd, vbr->req->cmd_len);
+
+	num = blk_rq_map_sg(q, vbr->req, vblk->sg + out);
+
+	if (blk_pc_request(vbr->req)) {
+		sg_set_buf(&vblk->sg[num + out + in++], vbr->req->sense, 96);
+		sg_set_buf(&vblk->sg[num + out + in++], &vbr->in_hdr,
+			   sizeof(vbr->in_hdr));
+	}
+
+	sg_set_buf(&vblk->sg[num + out + in++], &vbr->status,
+		   sizeof(vbr->status));
+
+	if (num) {
+		if (rq_data_dir(vbr->req) == WRITE) {
+			vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
+			out += num;
+		} else {
+			vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
+			in += num;
+		}
 	}
 
 	if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) {
@@ -124,12 +150,11 @@
 
 static void do_virtblk_request(struct request_queue *q)
 {
-	struct virtio_blk *vblk = NULL;
+	struct virtio_blk *vblk = q->queuedata;
 	struct request *req;
 	unsigned int issued = 0;
 
-	while ((req = elv_next_request(q)) != NULL) {
-		vblk = req->rq_disk->private_data;
+	while ((req = blk_peek_request(q)) != NULL) {
 		BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems);
 
 		/* If this request fails, stop queue and wait for something to
@@ -138,7 +163,7 @@
 			blk_stop_queue(q);
 			break;
 		}
-		blkdev_dequeue_request(req);
+		blk_start_request(req);
 		issued++;
 	}
 
@@ -146,12 +171,51 @@
 		vblk->vq->vq_ops->kick(vblk->vq);
 }
 
+/* return ATA identify data
+ */
+static int virtblk_identify(struct gendisk *disk, void *argp)
+{
+	struct virtio_blk *vblk = disk->private_data;
+	void *opaque;
+	int err = -ENOMEM;
+
+	opaque = kmalloc(VIRTIO_BLK_ID_BYTES, GFP_KERNEL);
+	if (!opaque)
+		goto out;
+
+	err = virtio_config_buf(vblk->vdev, VIRTIO_BLK_F_IDENTIFY,
+		offsetof(struct virtio_blk_config, identify), opaque,
+		VIRTIO_BLK_ID_BYTES);
+
+	if (err)
+		goto out_kfree;
+
+	if (copy_to_user(argp, opaque, VIRTIO_BLK_ID_BYTES))
+		err = -EFAULT;
+
+out_kfree:
+	kfree(opaque);
+out:
+	return err;
+}
+
 static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
 			 unsigned cmd, unsigned long data)
 {
-	return scsi_cmd_ioctl(bdev->bd_disk->queue,
-			      bdev->bd_disk, mode, cmd,
-			      (void __user *)data);
+	struct gendisk *disk = bdev->bd_disk;
+	struct virtio_blk *vblk = disk->private_data;
+	void __user *argp = (void __user *)data;
+
+	if (cmd == HDIO_GET_IDENTITY)
+		return virtblk_identify(disk, argp);
+
+	/*
+	 * Only allow the generic SCSI ioctls if the host can support it.
+	 */
+	if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
+		return -ENOTTY;
+
+	return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
 }
 
 /* We provide getgeo only to please some old bootloader/partitioning tools */
@@ -190,7 +254,7 @@
 	return index << PART_BITS;
 }
 
-static int virtblk_probe(struct virtio_device *vdev)
+static int __devinit virtblk_probe(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk;
 	int err;
@@ -224,7 +288,7 @@
 	sg_init_table(vblk->sg, vblk->sg_elems);
 
 	/* We expect one virtqueue, for output. */
-	vblk->vq = vdev->config->find_vq(vdev, 0, blk_done);
+	vblk->vq = virtio_find_single_vq(vdev, blk_done, "requests");
 	if (IS_ERR(vblk->vq)) {
 		err = PTR_ERR(vblk->vq);
 		goto out_free_vblk;
@@ -249,6 +313,7 @@
 		goto out_put_disk;
 	}
 
+	vblk->disk->queue->queuedata = vblk;
 	queue_flag_set_unlocked(QUEUE_FLAG_VIRT, vblk->disk->queue);
 
 	if (index < 26) {
@@ -295,6 +360,9 @@
 	blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2);
 	blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2);
 
+	/* No need to bounce any requests */
+	blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY);
+
 	/* No real sector limit. */
 	blk_queue_max_sectors(vblk->disk->queue, -1U);
 
@@ -313,7 +381,7 @@
 				offsetof(struct virtio_blk_config, blk_size),
 				&blk_size);
 	if (!err)
-		blk_queue_hardsect_size(vblk->disk->queue, blk_size);
+		blk_queue_logical_block_size(vblk->disk->queue, blk_size);
 
 	add_disk(vblk->disk);
 	return 0;
@@ -323,14 +391,14 @@
 out_mempool:
 	mempool_destroy(vblk->pool);
 out_free_vq:
-	vdev->config->del_vq(vblk->vq);
+	vdev->config->del_vqs(vdev);
 out_free_vblk:
 	kfree(vblk);
 out:
 	return err;
 }
 
-static void virtblk_remove(struct virtio_device *vdev)
+static void __devexit virtblk_remove(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk = vdev->priv;
 
@@ -344,7 +412,7 @@
 	blk_cleanup_queue(vblk->disk->queue);
 	put_disk(vblk->disk);
 	mempool_destroy(vblk->pool);
-	vdev->config->del_vq(vblk->vq);
+	vdev->config->del_vqs(vdev);
 	kfree(vblk);
 }
 
@@ -356,9 +424,15 @@
 static unsigned int features[] = {
 	VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
 	VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
+	VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY
 };
 
-static struct virtio_driver virtio_blk = {
+/*
+ * virtio_blk causes spurious section mismatch warning by
+ * simultaneously referring to a __devinit and a __devexit function.
+ * Use __refdata to avoid this warning.
+ */
+static struct virtio_driver __refdata virtio_blk = {
 	.feature_table = features,
 	.feature_table_size = ARRAY_SIZE(features),
 	.driver.name =	KBUILD_MODNAME,
diff -druN linux-libre-2.6.30-gnu/drivers/block/xd.c linux-libre-2.6.31-gnu/drivers/block/xd.c
--- linux-libre-2.6.30-gnu/drivers/block/xd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/xd.c	2009-09-09 18:13:59.000000000 -0400
@@ -305,30 +305,25 @@
 	if (xdc_busy)
 		return;
 
-	while ((req = elv_next_request(q)) != NULL) {
-		unsigned block = req->sector;
-		unsigned count = req->nr_sectors;
-		int rw = rq_data_dir(req);
+	req = blk_fetch_request(q);
+	while (req) {
+		unsigned block = blk_rq_pos(req);
+		unsigned count = blk_rq_cur_sectors(req);
 		XD_INFO *disk = req->rq_disk->private_data;
-		int res = 0;
+		int res = -EIO;
 		int retry;
 
-		if (!blk_fs_request(req)) {
-			end_request(req, 0);
-			continue;
-		}
-		if (block + count > get_capacity(req->rq_disk)) {
-			end_request(req, 0);
-			continue;
-		}
-		if (rw != READ && rw != WRITE) {
-			printk("do_xd_request: unknown request\n");
-			end_request(req, 0);
-			continue;
-		}
+		if (!blk_fs_request(req))
+			goto done;
+		if (block + count > get_capacity(req->rq_disk))
+			goto done;
 		for (retry = 0; (retry < XD_RETRIES) && !res; retry++)
-			res = xd_readwrite(rw, disk, req->buffer, block, count);
-		end_request(req, res);	/* wrap up, 0 = fail, 1 = success */
+			res = xd_readwrite(rq_data_dir(req), disk, req->buffer,
+					   block, count);
+	done:
+		/* wrap up, 0 = success, -errno = fail */
+		if (!__blk_end_request_cur(req, res))
+			req = blk_fetch_request(q);
 	}
 }
 
@@ -418,7 +413,7 @@
 				printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write"));
 				xd_recalibrate(drive);
 				spin_lock_irq(&xd_lock);
-				return (0);
+				return -EIO;
 			case 2:
 				if (sense[0] & 0x30) {
 					printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing"));
@@ -439,7 +434,7 @@
 				else
 					printk(" - no valid disk address\n");
 				spin_lock_irq(&xd_lock);
-				return (0);
+				return -EIO;
 		}
 		if (xd_dma_buffer)
 			for (i=0; i < (temp * 0x200); i++)
@@ -448,7 +443,7 @@
 		count -= temp, buffer += temp * 0x200, block += temp;
 	}
 	spin_lock_irq(&xd_lock);
-	return (1);
+	return 0;
 }
 
 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
diff -druN linux-libre-2.6.30-gnu/drivers/block/xen-blkfront.c linux-libre-2.6.31-gnu/drivers/block/xen-blkfront.c
--- linux-libre-2.6.30-gnu/drivers/block/xen-blkfront.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/xen-blkfront.c	2009-09-09 18:13:59.000000000 -0400
@@ -122,7 +122,7 @@
 static int get_id_from_freelist(struct blkfront_info *info)
 {
 	unsigned long free = info->shadow_free;
-	BUG_ON(free > BLK_RING_SIZE);
+	BUG_ON(free >= BLK_RING_SIZE);
 	info->shadow_free = info->shadow[free].req.id;
 	info->shadow[free].req.id = 0x0fffffee; /* debug */
 	return free;
@@ -231,7 +231,7 @@
 	info->shadow[id].request = (unsigned long)req;
 
 	ring_req->id = id;
-	ring_req->sector_number = (blkif_sector_t)req->sector;
+	ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
 	ring_req->handle = info->handle;
 
 	ring_req->operation = rq_data_dir(req) ?
@@ -299,25 +299,25 @@
 
 	queued = 0;
 
-	while ((req = elv_next_request(rq)) != NULL) {
+	while ((req = blk_peek_request(rq)) != NULL) {
 		info = req->rq_disk->private_data;
-		if (!blk_fs_request(req)) {
-			end_request(req, 0);
-			continue;
-		}
 
 		if (RING_FULL(&info->ring))
 			goto wait;
 
-		pr_debug("do_blk_req %p: cmd %p, sec %lx, "
-			 "(%u/%li) buffer:%p [%s]\n",
-			 req, req->cmd, (unsigned long)req->sector,
-			 req->current_nr_sectors,
-			 req->nr_sectors, req->buffer,
-			 rq_data_dir(req) ? "write" : "read");
+		blk_start_request(req);
 
+		if (!blk_fs_request(req)) {
+			__blk_end_request_all(req, -EIO);
+			continue;
+		}
+
+		pr_debug("do_blk_req %p: cmd %p, sec %lx, "
+			 "(%u/%u) buffer:%p [%s]\n",
+			 req, req->cmd, (unsigned long)blk_rq_pos(req),
+			 blk_rq_cur_sectors(req), blk_rq_sectors(req),
+			 req->buffer, rq_data_dir(req) ? "write" : "read");
 
-		blkdev_dequeue_request(req);
 		if (blkif_queue_request(req)) {
 			blk_requeue_request(rq, req);
 wait:
@@ -344,7 +344,7 @@
 	queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
 
 	/* Hard sector size and max sectors impersonate the equiv. hardware. */
-	blk_queue_hardsect_size(rq, sector_size);
+	blk_queue_logical_block_size(rq, sector_size);
 	blk_queue_max_sectors(rq, 512);
 
 	/* Each segment in a request is up to an aligned page in size. */
@@ -551,7 +551,6 @@
 
 	for (i = info->ring.rsp_cons; i != rp; i++) {
 		unsigned long id;
-		int ret;
 
 		bret = RING_GET_RESPONSE(&info->ring, i);
 		id   = bret->id;
@@ -578,8 +577,7 @@
 				dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
 					"request: %x\n", bret->status);
 
-			ret = __blk_end_request(req, error, blk_rq_bytes(req));
-			BUG_ON(ret);
+			__blk_end_request_all(req, error);
 			break;
 		default:
 			BUG();
@@ -755,12 +753,12 @@
 
 	/* Front end dir is a number, which is used as the id. */
 	info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0);
-	dev->dev.driver_data = info;
+	dev_set_drvdata(&dev->dev, info);
 
 	err = talk_to_backend(dev, info);
 	if (err) {
 		kfree(info);
-		dev->dev.driver_data = NULL;
+		dev_set_drvdata(&dev->dev, NULL);
 		return err;
 	}
 
@@ -845,7 +843,7 @@
  */
 static int blkfront_resume(struct xenbus_device *dev)
 {
-	struct blkfront_info *info = dev->dev.driver_data;
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
 	int err;
 
 	dev_dbg(&dev->dev, "blkfront_resume: %s\n", dev->nodename);
@@ -924,7 +922,7 @@
  */
 static void blkfront_closing(struct xenbus_device *dev)
 {
-	struct blkfront_info *info = dev->dev.driver_data;
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
 	unsigned long flags;
 
 	dev_dbg(&dev->dev, "blkfront_closing: %s removed\n", dev->nodename);
@@ -959,7 +957,7 @@
 static void backend_changed(struct xenbus_device *dev,
 			    enum xenbus_state backend_state)
 {
-	struct blkfront_info *info = dev->dev.driver_data;
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
 	struct block_device *bd;
 
 	dev_dbg(&dev->dev, "blkfront:backend_changed.\n");
@@ -999,7 +997,7 @@
 
 static int blkfront_remove(struct xenbus_device *dev)
 {
-	struct blkfront_info *info = dev->dev.driver_data;
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
 
 	dev_dbg(&dev->dev, "blkfront_remove: %s removed\n", dev->nodename);
 
@@ -1012,7 +1010,7 @@
 
 static int blkfront_is_ready(struct xenbus_device *dev)
 {
-	struct blkfront_info *info = dev->dev.driver_data;
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
 
 	return info->is_ready;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/block/xsysace.c linux-libre-2.6.31-gnu/drivers/block/xsysace.c
--- linux-libre-2.6.30-gnu/drivers/block/xsysace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/xsysace.c	2009-09-09 18:13:59.000000000 -0400
@@ -390,9 +390,10 @@
 
 static void ace_dump_regs(struct ace_device *ace)
 {
-	dev_info(ace->dev, "    ctrl:  %.8x  seccnt/cmd: %.4x      ver:%.4x\n"
-		 KERN_INFO "    status:%.8x  mpu_lba:%.8x  busmode:%4x\n"
-		 KERN_INFO "    error: %.8x  cfg_lba:%.8x  fatstat:%.4x\n",
+	dev_info(ace->dev,
+		 "    ctrl:  %.8x  seccnt/cmd: %.4x      ver:%.4x\n"
+		 "    status:%.8x  mpu_lba:%.8x  busmode:%4x\n"
+		 "    error: %.8x  cfg_lba:%.8x  fatstat:%.4x\n",
 		 ace_in32(ace, ACE_CTRL),
 		 ace_in(ace, ACE_SECCNTCMD),
 		 ace_in(ace, ACE_VERSION),
@@ -463,10 +464,11 @@
 {
 	struct request *req;
 
-	while ((req = elv_next_request(q)) != NULL) {
+	while ((req = blk_peek_request(q)) != NULL) {
 		if (blk_fs_request(req))
 			break;
-		end_request(req, 0);
+		blk_start_request(req);
+		__blk_end_request_all(req, -EIO);
 	}
 	return req;
 }
@@ -492,9 +494,13 @@
 		set_capacity(ace->gd, 0);
 		dev_info(ace->dev, "No CF in slot\n");
 
-		/* Drop all pending requests */
-		while ((req = elv_next_request(ace->queue)) != NULL)
-			end_request(req, 0);
+		/* Drop all in-flight and pending requests */
+		if (ace->req) {
+			__blk_end_request_all(ace->req, -EIO);
+			ace->req = NULL;
+		}
+		while ((req = blk_fetch_request(ace->queue)) != NULL)
+			__blk_end_request_all(req, -EIO);
 
 		/* Drop back to IDLE state and notify waiters */
 		ace->fsm_state = ACE_FSM_STATE_IDLE;
@@ -642,19 +648,21 @@
 			ace->fsm_state = ACE_FSM_STATE_IDLE;
 			break;
 		}
+		blk_start_request(req);
 
 		/* Okay, it's a data request, set it up for transfer */
 		dev_dbg(ace->dev,
-			"request: sec=%llx hcnt=%lx, ccnt=%x, dir=%i\n",
-			(unsigned long long) req->sector, req->hard_nr_sectors,
-			req->current_nr_sectors, rq_data_dir(req));
+			"request: sec=%llx hcnt=%x, ccnt=%x, dir=%i\n",
+			(unsigned long long)blk_rq_pos(req),
+			blk_rq_sectors(req), blk_rq_cur_sectors(req),
+			rq_data_dir(req));
 
 		ace->req = req;
 		ace->data_ptr = req->buffer;
-		ace->data_count = req->current_nr_sectors * ACE_BUF_PER_SECTOR;
-		ace_out32(ace, ACE_MPULBA, req->sector & 0x0FFFFFFF);
+		ace->data_count = blk_rq_cur_sectors(req) * ACE_BUF_PER_SECTOR;
+		ace_out32(ace, ACE_MPULBA, blk_rq_pos(req) & 0x0FFFFFFF);
 
-		count = req->hard_nr_sectors;
+		count = blk_rq_sectors(req);
 		if (rq_data_dir(req)) {
 			/* Kick off write request */
 			dev_dbg(ace->dev, "write data\n");
@@ -688,7 +696,7 @@
 			dev_dbg(ace->dev,
 				"CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n",
 				ace->fsm_task, ace->fsm_iter_num,
-				ace->req->current_nr_sectors * 16,
+				blk_rq_cur_sectors(ace->req) * 16,
 				ace->data_count, ace->in_irq);
 			ace_fsm_yield(ace);	/* need to poll CFBSY bit */
 			break;
@@ -697,7 +705,7 @@
 			dev_dbg(ace->dev,
 				"DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n",
 				ace->fsm_task, ace->fsm_iter_num,
-				ace->req->current_nr_sectors * 16,
+				blk_rq_cur_sectors(ace->req) * 16,
 				ace->data_count, ace->in_irq);
 			ace_fsm_yieldirq(ace);
 			break;
@@ -717,14 +725,13 @@
 		}
 
 		/* bio finished; is there another one? */
-		if (__blk_end_request(ace->req, 0,
-					blk_rq_cur_bytes(ace->req))) {
-			/* dev_dbg(ace->dev, "next block; h=%li c=%i\n",
-			 *      ace->req->hard_nr_sectors,
-			 *      ace->req->current_nr_sectors);
+		if (__blk_end_request_cur(ace->req, 0)) {
+			/* dev_dbg(ace->dev, "next block; h=%u c=%u\n",
+			 *      blk_rq_sectors(ace->req),
+			 *      blk_rq_cur_sectors(ace->req));
 			 */
 			ace->data_ptr = ace->req->buffer;
-			ace->data_count = ace->req->current_nr_sectors * 16;
+			ace->data_count = blk_rq_cur_sectors(ace->req) * 16;
 			ace_fsm_yieldirq(ace);
 			break;
 		}
@@ -978,7 +985,7 @@
 	ace->queue = blk_init_queue(ace_request, &ace->lock);
 	if (ace->queue == NULL)
 		goto err_blk_initq;
-	blk_queue_hardsect_size(ace->queue, 512);
+	blk_queue_logical_block_size(ace->queue, 512);
 
 	/*
 	 * Allocate and initialize GD structure
diff -druN linux-libre-2.6.30-gnu/drivers/block/z2ram.c linux-libre-2.6.31-gnu/drivers/block/z2ram.c
--- linux-libre-2.6.30-gnu/drivers/block/z2ram.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/block/z2ram.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,15 +70,18 @@
 static void do_z2_request(struct request_queue *q)
 {
 	struct request *req;
-	while ((req = elv_next_request(q)) != NULL) {
-		unsigned long start = req->sector << 9;
-		unsigned long len  = req->current_nr_sectors << 9;
+
+	req = blk_fetch_request(q);
+	while (req) {
+		unsigned long start = blk_rq_pos(req) << 9;
+		unsigned long len  = blk_rq_cur_bytes(req);
+		int err = 0;
 
 		if (start + len > z2ram_size) {
 			printk( KERN_ERR DEVICE_NAME ": bad access: block=%lu, count=%u\n",
-				req->sector, req->current_nr_sectors);
-			end_request(req, 0);
-			continue;
+				blk_rq_pos(req), blk_rq_cur_sectors(req));
+			err = -EIO;
+			goto done;
 		}
 		while (len) {
 			unsigned long addr = start & Z2RAM_CHUNKMASK;
@@ -93,7 +96,9 @@
 			start += size;
 			len -= size;
 		}
-		end_request(req, 1);
+	done:
+		if (!__blk_end_request_cur(req, err))
+			req = blk_fetch_request(q);
 	}
 }
 
@@ -369,7 +374,7 @@
 static void __exit z2_exit(void)
 {
     int i, j;
-    blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
+    blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT);
     unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
     del_gendisk(z2ram_gendisk);
     put_disk(z2ram_gendisk);
diff -druN linux-libre-2.6.30-gnu/drivers/bluetooth/dtl1_cs.c linux-libre-2.6.31-gnu/drivers/bluetooth/dtl1_cs.c
--- linux-libre-2.6.30-gnu/drivers/bluetooth/dtl1_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/bluetooth/dtl1_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -415,6 +415,8 @@
 		hdev->stat.sco_tx++;
 		nsh.type = 0x83;
 		break;
+	default:
+		return -EILSEQ;
 	};
 
 	nsh.zero = 0;
diff -druN linux-libre-2.6.30-gnu/drivers/bluetooth/hci_ldisc.c linux-libre-2.6.31-gnu/drivers/bluetooth/hci_ldisc.c
--- linux-libre-2.6.30-gnu/drivers/bluetooth/hci_ldisc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/bluetooth/hci_ldisc.c	2009-09-09 18:13:59.000000000 -0400
@@ -277,8 +277,8 @@
 	/* FIXME: why is this needed. Note don't use ldisc_ref here as the
 	   open path is before the ldisc is referencable */
 
-	if (tty->ldisc.ops->flush_buffer)
-		tty->ldisc.ops->flush_buffer(tty);
+	if (tty->ldisc->ops->flush_buffer)
+		tty->ldisc->ops->flush_buffer(tty);
 	tty_driver_flush_buffer(tty);
 
 	return 0;
@@ -463,7 +463,6 @@
 				clear_bit(HCI_UART_PROTO_SET, &hu->flags);
 				return err;
 			}
-			tty->low_latency = 1;
 		} else
 			return -EBUSY;
 		break;
diff -druN linux-libre-2.6.30-gnu/drivers/bluetooth/hci_vhci.c linux-libre-2.6.31-gnu/drivers/bluetooth/hci_vhci.c
--- linux-libre-2.6.30-gnu/drivers/bluetooth/hci_vhci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/bluetooth/hci_vhci.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -40,7 +39,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#define VERSION "1.2"
+#define VERSION "1.3"
 
 static int minor = MISC_DYNAMIC_MINOR;
 
@@ -51,14 +50,8 @@
 
 	wait_queue_head_t read_wait;
 	struct sk_buff_head readq;
-
-	struct fasync_struct *fasync;
 };
 
-#define VHCI_FASYNC	0x0010
-
-static struct miscdevice vhci_miscdev;
-
 static int vhci_open_dev(struct hci_dev *hdev)
 {
 	set_bit(HCI_RUNNING, &hdev->flags);
@@ -105,9 +98,6 @@
 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
 	skb_queue_tail(&data->readq, skb);
 
-	if (data->flags & VHCI_FASYNC)
-		kill_fasync(&data->fasync, SIGIO, POLL_IN);
-
 	wake_up_interruptible(&data->read_wait);
 
 	return 0;
@@ -179,41 +169,31 @@
 static ssize_t vhci_read(struct file *file,
 				char __user *buf, size_t count, loff_t *pos)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	struct vhci_data *data = file->private_data;
 	struct sk_buff *skb;
 	ssize_t ret = 0;
 
-	add_wait_queue(&data->read_wait, &wait);
 	while (count) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
 		skb = skb_dequeue(&data->readq);
-		if (!skb) {
-			if (file->f_flags & O_NONBLOCK) {
-				ret = -EAGAIN;
-				break;
-			}
-
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-
-			schedule();
-			continue;
+		if (skb) {
+			ret = vhci_put_user(data, skb, buf, count);
+			if (ret < 0)
+				skb_queue_head(&data->readq, skb);
+			else
+				kfree_skb(skb);
+			break;
 		}
 
-		if (access_ok(VERIFY_WRITE, buf, count))
-			ret = vhci_put_user(data, skb, buf, count);
-		else
-			ret = -EFAULT;
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			break;
+		}
 
-		kfree_skb(skb);
-		break;
+		ret = wait_event_interruptible(data->read_wait,
+					!skb_queue_empty(&data->readq));
+		if (ret < 0)
+			break;
 	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&data->read_wait, &wait);
 
 	return ret;
 }
@@ -223,9 +203,6 @@
 {
 	struct vhci_data *data = file->private_data;
 
-	if (!access_ok(VERIFY_READ, buf, count))
-		return -EFAULT;
-
 	return vhci_get_user(data, buf, count);
 }
 
@@ -259,11 +236,9 @@
 	skb_queue_head_init(&data->readq);
 	init_waitqueue_head(&data->read_wait);
 
-	lock_kernel();
 	hdev = hci_alloc_dev();
 	if (!hdev) {
 		kfree(data);
-		unlock_kernel();
 		return -ENOMEM;
 	}
 
@@ -284,12 +259,10 @@
 		BT_ERR("Can't register HCI device");
 		kfree(data);
 		hci_free_dev(hdev);
-		unlock_kernel();
 		return -EBUSY;
 	}
 
 	file->private_data = data;
-	unlock_kernel();
 
 	return nonseekable_open(inode, file);
 }
@@ -310,48 +283,25 @@
 	return 0;
 }
 
-static int vhci_fasync(int fd, struct file *file, int on)
-{
-	struct vhci_data *data = file->private_data;
-	int err = 0;
-
-	lock_kernel();
-	err = fasync_helper(fd, file, on, &data->fasync);
-	if (err < 0)
-		goto out;
-
-	if (on)
-		data->flags |= VHCI_FASYNC;
-	else
-		data->flags &= ~VHCI_FASYNC;
-
-out:
-	unlock_kernel();
-	return err;
-}
-
 static const struct file_operations vhci_fops = {
-	.owner		= THIS_MODULE,
 	.read		= vhci_read,
 	.write		= vhci_write,
 	.poll		= vhci_poll,
 	.ioctl		= vhci_ioctl,
 	.open		= vhci_open,
 	.release	= vhci_release,
-	.fasync		= vhci_fasync,
 };
 
 static struct miscdevice vhci_miscdev= {
-	.name		= "vhci",
-	.fops		= &vhci_fops,
+	.name	= "vhci",
+	.fops	= &vhci_fops,
+	.minor	= MISC_DYNAMIC_MINOR,
 };
 
 static int __init vhci_init(void)
 {
 	BT_INFO("Virtual HCI driver ver %s", VERSION);
 
-	vhci_miscdev.minor = minor;
-
 	if (misc_register(&vhci_miscdev) < 0) {
 		BT_ERR("Can't register misc device with minor %d", minor);
 		return -EIO;
@@ -369,9 +319,6 @@
 module_init(vhci_init);
 module_exit(vhci_exit);
 
-module_param(minor, int, 0444);
-MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
-
 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
 MODULE_VERSION(VERSION);
diff -druN linux-libre-2.6.30-gnu/drivers/cdrom/cdrom.c linux-libre-2.6.31-gnu/drivers/cdrom/cdrom.c
--- linux-libre-2.6.30-gnu/drivers/cdrom/cdrom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/cdrom/cdrom.c	2009-09-09 18:13:59.000000000 -0400
@@ -2101,8 +2101,8 @@
 		nr = nframes;
 		if (cdi->cdda_method == CDDA_BPC_SINGLE)
 			nr = 1;
-		if (nr * CD_FRAMESIZE_RAW > (q->max_sectors << 9))
-			nr = (q->max_sectors << 9) / CD_FRAMESIZE_RAW;
+		if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9))
+			nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW;
 
 		len = nr * CD_FRAMESIZE_RAW;
 
diff -druN linux-libre-2.6.30-gnu/drivers/cdrom/gdrom.c linux-libre-2.6.31-gnu/drivers/cdrom/gdrom.c
--- linux-libre-2.6.30-gnu/drivers/cdrom/gdrom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/cdrom/gdrom.c	2009-09-09 18:13:59.000000000 -0400
@@ -584,8 +584,8 @@
 	list_for_each_safe(elem, next, &gdrom_deferred) {
 		req = list_entry(elem, struct request, queuelist);
 		spin_unlock(&gdrom_lock);
-		block = req->sector/GD_TO_BLK + GD_SESSION_OFFSET;
-		block_cnt = req->nr_sectors/GD_TO_BLK;
+		block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET;
+		block_cnt = blk_rq_sectors(req)/GD_TO_BLK;
 		ctrl_outl(PHYSADDR(req->buffer), GDROM_DMA_STARTADDR_REG);
 		ctrl_outl(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG);
 		ctrl_outl(1, GDROM_DMA_DIRECTION_REG);
@@ -632,39 +632,35 @@
 		* before handling ending the request */
 		spin_lock(&gdrom_lock);
 		list_del_init(&req->queuelist);
-		__blk_end_request(req, err, blk_rq_bytes(req));
+		__blk_end_request_all(req, err);
 	}
 	spin_unlock(&gdrom_lock);
 	kfree(read_command);
 }
 
-static void gdrom_request_handler_dma(struct request *req)
-{
-	/* dequeue, add to list of deferred work
-	* and then schedule workqueue */
-	blkdev_dequeue_request(req);
-	list_add_tail(&req->queuelist, &gdrom_deferred);
-	schedule_work(&work);
-}
-
 static void gdrom_request(struct request_queue *rq)
 {
 	struct request *req;
 
-	while ((req = elv_next_request(rq)) != NULL) {
+	while ((req = blk_fetch_request(rq)) != NULL) {
 		if (!blk_fs_request(req)) {
 			printk(KERN_DEBUG "GDROM: Non-fs request ignored\n");
-			end_request(req, 0);
+			__blk_end_request_all(req, -EIO);
+			continue;
 		}
 		if (rq_data_dir(req) != READ) {
 			printk(KERN_NOTICE "GDROM: Read only device -");
 			printk(" write request ignored\n");
-			end_request(req, 0);
+			__blk_end_request_all(req, -EIO);
+			continue;
 		}
-		if (req->nr_sectors)
-			gdrom_request_handler_dma(req);
-		else
-			end_request(req, 0);
+
+		/*
+		 * Add to list of deferred work and then schedule
+		 * workqueue.
+		 */
+		list_add_tail(&req->queuelist, &gdrom_deferred);
+		schedule_work(&work);
 	}
 }
 
@@ -743,7 +739,7 @@
 
 static int __devinit probe_gdrom_setupqueue(void)
 {
-	blk_queue_hardsect_size(gd.gdrom_rq, GDROM_HARD_SECTOR);
+	blk_queue_logical_block_size(gd.gdrom_rq, GDROM_HARD_SECTOR);
 	/* using DMA so memory will need to be contiguous */
 	blk_queue_max_hw_segments(gd.gdrom_rq, 1);
 	/* set a large max size to get most from DMA */
diff -druN linux-libre-2.6.30-gnu/drivers/cdrom/viocd.c linux-libre-2.6.31-gnu/drivers/cdrom/viocd.c
--- linux-libre-2.6.30-gnu/drivers/cdrom/viocd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/cdrom/viocd.c	2009-09-09 18:13:59.000000000 -0400
@@ -282,7 +282,7 @@
 			viopath_targetinst(viopath_hostLp),
 			(u64)req, VIOVERSION << 16,
 			((u64)DEVICE_NR(diskinfo) << 48) | dmaaddr,
-			(u64)req->sector * 512, len, 0);
+			(u64)blk_rq_pos(req) * 512, len, 0);
 	if (hvrc != HvLpEvent_Rc_Good) {
 		printk(VIOCD_KERN_WARNING "hv error on op %d\n", (int)hvrc);
 		return -1;
@@ -291,36 +291,19 @@
 	return 0;
 }
 
-static void viocd_end_request(struct request *req, int error)
-{
-	int nsectors = req->hard_nr_sectors;
-
-	/*
-	 * Make sure it's fully ended, and ensure that we process
-	 * at least one sector.
-	 */
-	if (blk_pc_request(req))
-		nsectors = (req->data_len + 511) >> 9;
-	if (!nsectors)
-		nsectors = 1;
-
-	if (__blk_end_request(req, error, nsectors << 9))
-		BUG();
-}
-
 static int rwreq;
 
 static void do_viocd_request(struct request_queue *q)
 {
 	struct request *req;
 
-	while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) {
+	while ((rwreq == 0) && ((req = blk_fetch_request(q)) != NULL)) {
 		if (!blk_fs_request(req))
-			viocd_end_request(req, -EIO);
+			__blk_end_request_all(req, -EIO);
 		else if (send_request(req) < 0) {
 			printk(VIOCD_KERN_WARNING
 					"unable to send message to OS/400!");
-			viocd_end_request(req, -EIO);
+			__blk_end_request_all(req, -EIO);
 		} else
 			rwreq++;
 	}
@@ -486,8 +469,8 @@
 	case viocdopen:
 		if (event->xRc == 0) {
 			di = &viocd_diskinfo[bevent->disk];
-			blk_queue_hardsect_size(di->viocd_disk->queue,
-					bevent->block_size);
+			blk_queue_logical_block_size(di->viocd_disk->queue,
+						     bevent->block_size);
 			set_capacity(di->viocd_disk,
 					bevent->media_size *
 					bevent->block_size / 512);
@@ -531,9 +514,9 @@
 					"with rc %d:0x%04X: %s\n",
 					req, event->xRc,
 					bevent->sub_result, err->msg);
-			viocd_end_request(req, -EIO);
+			__blk_end_request_all(req, -EIO);
 		} else
-			viocd_end_request(req, 0);
+			__blk_end_request_all(req, 0);
 
 		/* restart handling of incoming requests */
 		spin_unlock_irqrestore(&viocd_reqlock, flags);
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/agp.h linux-libre-2.6.31-gnu/drivers/char/agp/agp.h
--- linux-libre-2.6.30-gnu/drivers/char/agp/agp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/agp.h	2009-09-09 18:13:59.000000000 -0400
@@ -107,7 +107,7 @@
 	void (*agp_enable)(struct agp_bridge_data *, u32);
 	void (*cleanup)(void);
 	void (*tlb_flush)(struct agp_memory *);
-	unsigned long (*mask_memory)(struct agp_bridge_data *, unsigned long, int);
+	unsigned long (*mask_memory)(struct agp_bridge_data *, struct page *, int);
 	void (*cache_flush)(void);
 	int (*create_gatt_table)(struct agp_bridge_data *);
 	int (*free_gatt_table)(struct agp_bridge_data *);
@@ -115,9 +115,9 @@
 	int (*remove_memory)(struct agp_memory *, off_t, int);
 	struct agp_memory *(*alloc_by_type) (size_t, int);
 	void (*free_by_type)(struct agp_memory *);
-	void *(*agp_alloc_page)(struct agp_bridge_data *);
+	struct page *(*agp_alloc_page)(struct agp_bridge_data *);
 	int (*agp_alloc_pages)(struct agp_bridge_data *, struct agp_memory *, size_t);
-	void (*agp_destroy_page)(void *, int flags);
+	void (*agp_destroy_page)(struct page *, int flags);
 	void (*agp_destroy_pages)(struct agp_memory *);
 	int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
 	void (*chipset_flush)(struct agp_bridge_data *);
@@ -278,10 +278,10 @@
 int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
 struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
 void agp_generic_free_by_type(struct agp_memory *curr);
-void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
+struct page *agp_generic_alloc_page(struct agp_bridge_data *bridge);
 int agp_generic_alloc_pages(struct agp_bridge_data *agp_bridge,
 			    struct agp_memory *memory, size_t page_count);
-void agp_generic_destroy_page(void *addr, int flags);
+void agp_generic_destroy_page(struct page *page, int flags);
 void agp_generic_destroy_pages(struct agp_memory *memory);
 void agp_free_key(int key);
 int agp_num_entries(void);
@@ -291,7 +291,7 @@
 void global_cache_flush(void);
 void get_agp_version(struct agp_bridge_data *bridge);
 unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
-	unsigned long addr, int type);
+				      struct page *page, int type);
 int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
 				  int type);
 struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/ali-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/ali-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/ali-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/ali-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -141,37 +141,37 @@
 	}
 }
 
-static void *m1541_alloc_page(struct agp_bridge_data *bridge)
+static struct page *m1541_alloc_page(struct agp_bridge_data *bridge)
 {
-	void *addr = agp_generic_alloc_page(agp_bridge);
+	struct page *page = agp_generic_alloc_page(agp_bridge);
 	u32 temp;
 
-	if (!addr)
+	if (!page)
 		return NULL;
 
 	pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
 	pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
 			(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-			  virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN ));
-	return addr;
+			  phys_to_gart(page_to_phys(page))) | ALI_CACHE_FLUSH_EN ));
+	return page;
 }
 
-static void ali_destroy_page(void * addr, int flags)
+static void ali_destroy_page(struct page *page, int flags)
 {
-	if (addr) {
+	if (page) {
 		if (flags & AGP_PAGE_DESTROY_UNMAP) {
 			global_cache_flush();	/* is this really needed?  --hch */
-			agp_generic_destroy_page(addr, flags);
+			agp_generic_destroy_page(page, flags);
 		} else
-			agp_generic_destroy_page(addr, flags);
+			agp_generic_destroy_page(page, flags);
 	}
 }
 
-static void m1541_destroy_page(void * addr, int flags)
+static void m1541_destroy_page(struct page *page, int flags)
 {
 	u32 temp;
 
-	if (addr == NULL)
+	if (page == NULL)
 		return;
 
 	if (flags & AGP_PAGE_DESTROY_UNMAP) {
@@ -180,9 +180,9 @@
 		pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
 		pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
 				       (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-					 virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
+					 phys_to_gart(page_to_phys(page))) | ALI_CACHE_FLUSH_EN));
 	}
-	agp_generic_destroy_page(addr, flags);
+	agp_generic_destroy_page(page, flags);
 }
 
 
@@ -346,7 +346,7 @@
 			devs[j].chipset_name = "M1641";
 			break;
 		case 0x43:
-			devs[j].chipset_name = "M????";
+			devs[j].chipset_name = "M1621";
 			break;
 		case 0x47:
 			devs[j].chipset_name = "M1647";
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/amd64-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/amd64-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/amd64-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/amd64-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,7 +79,7 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		tmp = agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mask_type);
+			mem->pages[i], mask_type);
 
 		BUG_ON(tmp & 0xffffff0000000ffcULL);
 		pte = (tmp & 0x000000ff00000000ULL) >> 28;
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/amd-k7-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/amd-k7-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/amd-k7-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/amd-k7-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -325,7 +325,7 @@
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
 		writel(agp_generic_mask_memory(agp_bridge,
-			mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+			mem->pages[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 		readl(cur_gatt+GET_GATT_OFF(addr));	/* PCI Posting. */
 	}
 	amd_irongate_tlbflush(mem);
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/ati-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/ati-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/ati-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/ati-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -269,12 +269,17 @@
 	int i, j, num_entries;
 	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
+	int mask_type;
 
 	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
 
-	if (type != 0 || mem->type != 0)
+	mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+	if (mask_type != 0 || type != mem->type)
 		return -EINVAL;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	if ((pg_start + mem->page_count) > num_entries)
 		return -EINVAL;
 
@@ -296,10 +301,11 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		writel(agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
-		readl(cur_gatt+GET_GATT_OFF(addr));	/* PCI Posting. */
+		writel(agp_bridge->driver->mask_memory(agp_bridge,	
+						       mem->pages[i], mem->type),
+		       cur_gatt+GET_GATT_OFF(addr));
 	}
+	readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
@@ -310,17 +316,22 @@
 	int i;
 	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
+	int mask_type;
 
-	if (type != 0 || mem->type != 0)
+	mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+	if (mask_type != 0 || type != mem->type)
 		return -EINVAL;
 
+	if (mem->page_count == 0)
+		return 0;
+
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
 		writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
-		readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
 	}
 
+	readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/backend.c linux-libre-2.6.31-gnu/drivers/char/agp/backend.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/backend.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/backend.c	2009-09-09 18:13:59.000000000 -0400
@@ -141,17 +141,17 @@
 	bridge->version = &agp_current_version;
 
 	if (bridge->driver->needs_scratch_page) {
-		void *addr = bridge->driver->agp_alloc_page(bridge);
+		struct page *page = bridge->driver->agp_alloc_page(bridge);
 
-		if (!addr) {
+		if (!page) {
 			dev_err(&bridge->dev->dev,
 				"can't get memory for scratch page\n");
 			return -ENOMEM;
 		}
 
-		bridge->scratch_page_real = virt_to_gart(addr);
+		bridge->scratch_page_real = phys_to_gart(page_to_phys(page));
 		bridge->scratch_page =
-		    bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
+		    bridge->driver->mask_memory(bridge, page, 0);
 	}
 
 	size_value = bridge->driver->fetch_size();
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/efficeon-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/efficeon-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/efficeon-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/efficeon-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -65,8 +65,9 @@
 };
 
 /* This function does the same thing as mask_memory() for this chipset... */
-static inline unsigned long efficeon_mask_memory(unsigned long addr)
+static inline unsigned long efficeon_mask_memory(struct page *page)
 {
+	unsigned long addr = phys_to_gart(page_to_phys(page));
 	return addr | 0x00000001;
 }
 
@@ -257,7 +258,7 @@
 	last_page = NULL;
 	for (i = 0; i < count; i++) {
 		int index = pg_start + i;
-		unsigned long insert = efficeon_mask_memory(mem->memory[i]);
+		unsigned long insert = efficeon_mask_memory(mem->pages[i]);
 
 		page = (unsigned int *) efficeon_private.l1_table[index >> 10];
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/generic.c linux-libre-2.6.31-gnu/drivers/char/agp/generic.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -95,13 +95,13 @@
 
 void agp_alloc_page_array(size_t size, struct agp_memory *mem)
 {
-	mem->memory = NULL;
+	mem->pages = NULL;
 	mem->vmalloc_flag = false;
 
 	if (size <= 2*PAGE_SIZE)
-		mem->memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
-	if (mem->memory == NULL) {
-		mem->memory = vmalloc(size);
+		mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+	if (mem->pages == NULL) {
+		mem->pages = vmalloc(size);
 		mem->vmalloc_flag = true;
 	}
 }
@@ -110,9 +110,9 @@
 void agp_free_page_array(struct agp_memory *mem)
 {
 	if (mem->vmalloc_flag) {
-		vfree(mem->memory);
+		vfree(mem->pages);
 	} else {
-		kfree(mem->memory);
+		kfree(mem->pages);
 	}
 }
 EXPORT_SYMBOL(agp_free_page_array);
@@ -136,7 +136,7 @@
 
 	agp_alloc_page_array(alloc_size, new);
 
-	if (new->memory == NULL) {
+	if (new->pages == NULL) {
 		agp_free_key(new->key);
 		kfree(new);
 		return NULL;
@@ -162,7 +162,7 @@
 
 	agp_alloc_page_array(PAGE_SIZE * scratch_pages, new);
 
-	if (new->memory == NULL) {
+	if (new->pages == NULL) {
 		agp_free_key(new->key);
 		kfree(new);
 		return NULL;
@@ -206,15 +206,13 @@
 		} else {
 
 			for (i = 0; i < curr->page_count; i++) {
-				curr->memory[i] = (unsigned long)gart_to_virt(
-					curr->memory[i]);
 				curr->bridge->driver->agp_destroy_page(
-					(void *)curr->memory[i],
+					curr->pages[i],
 					AGP_PAGE_DESTROY_UNMAP);
 			}
 			for (i = 0; i < curr->page_count; i++) {
 				curr->bridge->driver->agp_destroy_page(
-					(void *)curr->memory[i],
+					curr->pages[i],
 					AGP_PAGE_DESTROY_FREE);
 			}
 		}
@@ -282,13 +280,13 @@
 	}
 
 	for (i = 0; i < page_count; i++) {
-		void *addr = bridge->driver->agp_alloc_page(bridge);
+		struct page *page = bridge->driver->agp_alloc_page(bridge);
 
-		if (addr == NULL) {
+		if (page == NULL) {
 			agp_free_memory(new);
 			return NULL;
 		}
-		new->memory[i] = virt_to_gart(addr);
+		new->pages[i] = page;
 		new->page_count++;
 	}
 	new->bridge = bridge;
@@ -1134,7 +1132,7 @@
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type),
+		writel(bridge->driver->mask_memory(bridge, mem->pages[i], mask_type),
 		       bridge->gatt_table+j);
 	}
 	readl(bridge->gatt_table+j-1);	/* PCI Posting. */
@@ -1204,7 +1202,7 @@
 		return NULL;
 
 	for (i = 0; i < page_count; i++)
-		new->memory[i] = 0;
+		new->pages[i] = 0;
 	new->page_count = 0;
 	new->type = type;
 	new->num_scratch_pages = pages;
@@ -1237,23 +1235,20 @@
 		get_page(page);
 		atomic_inc(&agp_bridge->current_memory_agp);
 
-		/* set_memory_array_uc() needs virtual address */
-		mem->memory[i] = (unsigned long)page_address(page);
+		mem->pages[i] = page;
 		mem->page_count++;
 	}
 
 #ifdef CONFIG_X86
-	set_memory_array_uc(mem->memory, num_pages);
+	set_pages_array_uc(mem->pages, num_pages);
 #endif
 	ret = 0;
 out:
-	for (i = 0; i < mem->page_count; i++)
-		mem->memory[i] = virt_to_gart((void *)mem->memory[i]);
 	return ret;
 }
 EXPORT_SYMBOL(agp_generic_alloc_pages);
 
-void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
+struct page *agp_generic_alloc_page(struct agp_bridge_data *bridge)
 {
 	struct page * page;
 
@@ -1265,56 +1260,47 @@
 
 	get_page(page);
 	atomic_inc(&agp_bridge->current_memory_agp);
-	return page_address(page);
+	return page;
 }
 EXPORT_SYMBOL(agp_generic_alloc_page);
 
 void agp_generic_destroy_pages(struct agp_memory *mem)
 {
 	int i;
-	void *addr;
 	struct page *page;
 
 	if (!mem)
 		return;
 
-	for (i = 0; i < mem->page_count; i++)
-		mem->memory[i] = (unsigned long)gart_to_virt(mem->memory[i]);
-
 #ifdef CONFIG_X86
-	set_memory_array_wb(mem->memory, mem->page_count);
+	set_pages_array_wb(mem->pages, mem->page_count);
 #endif
 
 	for (i = 0; i < mem->page_count; i++) {
-		addr = (void *)mem->memory[i];
-		page = virt_to_page(addr);
+		page = mem->pages[i];
 
 #ifndef CONFIG_X86
 		unmap_page_from_agp(page);
 #endif
-
 		put_page(page);
-		free_page((unsigned long)addr);
+		__free_page(page);
 		atomic_dec(&agp_bridge->current_memory_agp);
-		mem->memory[i] = 0;
+		mem->pages[i] = NULL;
 	}
 }
 EXPORT_SYMBOL(agp_generic_destroy_pages);
 
-void agp_generic_destroy_page(void *addr, int flags)
+void agp_generic_destroy_page(struct page *page, int flags)
 {
-	struct page *page;
-
-	if (addr == NULL)
+	if (page == NULL)
 		return;
 
-	page = virt_to_page(addr);
 	if (flags & AGP_PAGE_DESTROY_UNMAP)
 		unmap_page_from_agp(page);
 
 	if (flags & AGP_PAGE_DESTROY_FREE) {
 		put_page(page);
-		free_page((unsigned long)addr);
+		__free_page(page);
 		atomic_dec(&agp_bridge->current_memory_agp);
 	}
 }
@@ -1361,8 +1347,9 @@
 EXPORT_SYMBOL(global_cache_flush);
 
 unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
-	unsigned long addr, int type)
+				      struct page *page, int type)
 {
+	unsigned long addr = phys_to_gart(page_to_phys(page));
 	/* memory type is ignored in the generic routine */
 	if (bridge->driver->masks)
 		return addr | bridge->driver->masks[0].mask;
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/hp-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/hp-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/hp-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/hp-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -361,13 +361,11 @@
 	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
 		unsigned long paddr;
 
-		paddr = mem->memory[i];
+		paddr = page_to_phys(mem->pages[i]);
 		for (k = 0;
 		     k < hp->io_pages_per_kpage;
 		     k++, j++, paddr += hp->io_page_size) {
-			hp->gatt[j] =
-				agp_bridge->driver->mask_memory(agp_bridge,
-					paddr, type);
+			hp->gatt[j] = HP_ZX1_PDIR_VALID_BIT | paddr;
 		}
 	}
 
@@ -397,8 +395,9 @@
 
 static unsigned long
 hp_zx1_mask_memory (struct agp_bridge_data *bridge,
-	unsigned long addr, int type)
+		    struct page *page, int type)
 {
+	unsigned long addr = phys_to_gart(page_to_phys(page));
 	return HP_ZX1_PDIR_VALID_BIT | addr;
 }
 
@@ -518,8 +517,9 @@
 	if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa))
 		return AE_OK;
 
-	printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset (ioc=%lx, lba=%lx)\n",
-		(char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
+	printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset "
+		"(ioc=%llx, lba=%llx)\n", (char *)context,
+		sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
 
 	hp_zx1_gart_found = 1;
 	return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/i460-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/i460-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/i460-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/i460-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,6 +60,9 @@
  */
 #define WR_FLUSH_GATT(index)	RD_GATT(index)
 
+static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
+				       unsigned long addr, int type);
+
 static struct {
 	void *gatt;				/* ioremap'd GATT area */
 
@@ -74,6 +77,7 @@
 		unsigned long *alloced_map;	/* bitmap of kernel-pages in use */
 		int refcount;			/* number of kernel pages using the large page */
 		u64 paddr;			/* physical address of large page */
+		struct page *page; 		/* page pointer */
 	} *lp_desc;
 } i460;
 
@@ -294,7 +298,7 @@
 	void *temp;
 
 	pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
-		 mem, pg_start, type, mem->memory[0]);
+		 mem, pg_start, type, page_to_phys(mem->pages[0]));
 
 	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
 		return -EINVAL;
@@ -321,10 +325,9 @@
 
 	io_page_size = 1UL << I460_IO_PAGE_SHIFT;
 	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
-		paddr = mem->memory[i];
+		paddr = phys_to_gart(page_to_phys(mem->pages[i]));
 		for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
-			WR_GATT(j, agp_bridge->driver->mask_memory(agp_bridge,
-				paddr, mem->type));
+			WR_GATT(j, i460_mask_memory(agp_bridge, paddr, mem->type));
 	}
 	WR_FLUSH_GATT(j - 1);
 	return 0;
@@ -364,10 +367,9 @@
 {
 	unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT;
 	size_t map_size;
-	void *lpage;
 
-	lpage = (void *) __get_free_pages(GFP_KERNEL, order);
-	if (!lpage) {
+	lp->page = alloc_pages(GFP_KERNEL, order);
+	if (!lp->page) {
 		printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n");
 		return -ENOMEM;
 	}
@@ -375,12 +377,12 @@
 	map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8;
 	lp->alloced_map = kzalloc(map_size, GFP_KERNEL);
 	if (!lp->alloced_map) {
-		free_pages((unsigned long) lpage, order);
+		__free_pages(lp->page, order);
 		printk(KERN_ERR PFX "Out of memory, we're in trouble...\n");
 		return -ENOMEM;
 	}
 
-	lp->paddr = virt_to_gart(lpage);
+	lp->paddr = phys_to_gart(page_to_phys(lp->page));
 	lp->refcount = 0;
 	atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
 	return 0;
@@ -391,7 +393,7 @@
 	kfree(lp->alloced_map);
 	lp->alloced_map = NULL;
 
-	free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+	__free_pages(lp->page, I460_IO_PAGE_SHIFT - PAGE_SHIFT);
 	atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
 }
 
@@ -439,8 +441,8 @@
 			if (i460_alloc_large_page(lp) < 0)
 				return -ENOMEM;
 			pg = lp - i460.lp_desc;
-			WR_GATT(pg, agp_bridge->driver->mask_memory(agp_bridge,
-				lp->paddr, 0));
+			WR_GATT(pg, i460_mask_memory(agp_bridge,
+						     lp->paddr, 0));
 			WR_FLUSH_GATT(pg);
 		}
 
@@ -448,7 +450,7 @@
 		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
 		     idx++, i++)
 		{
-			mem->memory[i] = lp->paddr + idx*PAGE_SIZE;
+			mem->pages[i] = lp->page;
 			__set_bit(idx, lp->alloced_map);
 			++lp->refcount;
 		}
@@ -463,7 +465,7 @@
 	struct lp_desc *start, *end, *lp;
 	void *temp;
 
-	temp = agp_bridge->driver->current_size;
+	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_8(temp)->num_entries;
 
 	/* Figure out what pg_start means in terms of our large GART pages */
@@ -477,7 +479,7 @@
 		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
 		     idx++, i++)
 		{
-			mem->memory[i] = 0;
+			mem->pages[i] = NULL;
 			__clear_bit(idx, lp->alloced_map);
 			--lp->refcount;
 		}
@@ -521,7 +523,7 @@
  * Let's just hope nobody counts on the allocated AGP memory being there before bind time
  * (I don't think current drivers do)...
  */
-static void *i460_alloc_page (struct agp_bridge_data *bridge)
+static struct page *i460_alloc_page (struct agp_bridge_data *bridge)
 {
 	void *page;
 
@@ -534,7 +536,7 @@
 	return page;
 }
 
-static void i460_destroy_page (void *page, int flags)
+static void i460_destroy_page (struct page *page, int flags)
 {
 	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
 		agp_generic_destroy_page(page, flags);
@@ -544,13 +546,20 @@
 #endif /* I460_LARGE_IO_PAGES */
 
 static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
-	unsigned long addr, int type)
+				       unsigned long addr, int type)
 {
 	/* Make sure the returned address is a valid GATT entry */
 	return bridge->driver->masks[0].mask
 		| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12);
 }
 
+static unsigned long i460_page_mask_memory(struct agp_bridge_data *bridge,
+					   struct page *page, int type)
+{
+	unsigned long addr = phys_to_gart(page_to_phys(page));
+	return i460_mask_memory(bridge, addr, type);
+}
+
 const struct agp_bridge_driver intel_i460_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= i460_sizes,
@@ -560,7 +569,7 @@
 	.fetch_size		= i460_fetch_size,
 	.cleanup		= i460_cleanup,
 	.tlb_flush		= i460_tlb_flush,
-	.mask_memory		= i460_mask_memory,
+	.mask_memory		= i460_page_mask_memory,
 	.masks			= i460_masks,
 	.agp_enable		= agp_generic_enable,
 	.cache_flush		= global_cache_flush,
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/intel-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/intel-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/intel-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/intel-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,11 @@
 #define PCI_DEVICE_ID_INTEL_G45_IG          0x2E22
 #define PCI_DEVICE_ID_INTEL_G41_HB          0x2E30
 #define PCI_DEVICE_ID_INTEL_G41_IG          0x2E32
+#define PCI_DEVICE_ID_INTEL_IGDNG_D_HB	    0x0040
+#define PCI_DEVICE_ID_INTEL_IGDNG_D_IG	    0x0042
+#define PCI_DEVICE_ID_INTEL_IGDNG_M_HB	    0x0044
+#define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB	    0x0062
+#define PCI_DEVICE_ID_INTEL_IGDNG_M_IG	    0x0046
 
 /* cover 915 and 945 variants */
 #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
@@ -75,7 +80,10 @@
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
-		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB)
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB)
 
 extern int agp_memory_reserved;
 
@@ -251,7 +259,7 @@
 }
 
 /* Exists to support ARGB cursors */
-static void *i8xx_alloc_pages(void)
+static struct page *i8xx_alloc_pages(void)
 {
 	struct page *page;
 
@@ -266,17 +274,14 @@
 	}
 	get_page(page);
 	atomic_inc(&agp_bridge->current_memory_agp);
-	return page_address(page);
+	return page;
 }
 
-static void i8xx_destroy_pages(void *addr)
+static void i8xx_destroy_pages(struct page *page)
 {
-	struct page *page;
-
-	if (addr == NULL)
+	if (page == NULL)
 		return;
 
-	page = virt_to_page(addr);
 	set_pages_wb(page, 4);
 	put_page(page);
 	__free_pages(page, 2);
@@ -340,7 +345,7 @@
 			global_cache_flush();
 		for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 			writel(agp_bridge->driver->mask_memory(agp_bridge,
-							       mem->memory[i],
+							       mem->pages[i],
 							       mask_type),
 			       intel_private.registers+I810_PTE_BASE+(j*4));
 		}
@@ -383,37 +388,37 @@
 static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
 {
 	struct agp_memory *new;
-	void *addr;
+	struct page *page;
 
 	switch (pg_count) {
-	case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
+	case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge);
 		break;
 	case 4:
 		/* kludge to get 4 physical pages for ARGB cursor */
-		addr = i8xx_alloc_pages();
+		page = i8xx_alloc_pages();
 		break;
 	default:
 		return NULL;
 	}
 
-	if (addr == NULL)
+	if (page == NULL)
 		return NULL;
 
 	new = agp_create_memory(pg_count);
 	if (new == NULL)
 		return NULL;
 
-	new->memory[0] = virt_to_gart(addr);
+	new->pages[0] = page;
 	if (pg_count == 4) {
 		/* kludge to get 4 physical pages for ARGB cursor */
-		new->memory[1] = new->memory[0] + PAGE_SIZE;
-		new->memory[2] = new->memory[1] + PAGE_SIZE;
-		new->memory[3] = new->memory[2] + PAGE_SIZE;
+		new->pages[1] = new->pages[0] + 1;
+		new->pages[2] = new->pages[1] + 1;
+		new->pages[3] = new->pages[2] + 1;
 	}
 	new->page_count = pg_count;
 	new->num_scratch_pages = pg_count;
 	new->type = AGP_PHYS_MEMORY;
-	new->physical = new->memory[0];
+	new->physical = page_to_phys(new->pages[0]);
 	return new;
 }
 
@@ -445,13 +450,11 @@
 	agp_free_key(curr->key);
 	if (curr->type == AGP_PHYS_MEMORY) {
 		if (curr->page_count == 4)
-			i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
+			i8xx_destroy_pages(curr->pages[0]);
 		else {
-			void *va = gart_to_virt(curr->memory[0]);
-
-			agp_bridge->driver->agp_destroy_page(va,
+			agp_bridge->driver->agp_destroy_page(curr->pages[0],
 							     AGP_PAGE_DESTROY_UNMAP);
-			agp_bridge->driver->agp_destroy_page(va,
+			agp_bridge->driver->agp_destroy_page(curr->pages[0],
 							     AGP_PAGE_DESTROY_FREE);
 		}
 		agp_free_page_array(curr);
@@ -460,8 +463,9 @@
 }
 
 static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
-	unsigned long addr, int type)
+					    struct page *page, int type)
 {
+	unsigned long addr = phys_to_gart(page_to_phys(page));
 	/* Type checking must be done elsewhere */
 	return addr | bridge->driver->masks[type].mask;
 }
@@ -849,7 +853,7 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
-						       mem->memory[i], mask_type),
+						       mem->pages[i], mask_type),
 		       intel_private.registers+I810_PTE_BASE+(j*4));
 	}
 	readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
@@ -1079,7 +1083,7 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mask_type), intel_private.gtt+j);
+						       mem->pages[i], mask_type), intel_private.gtt+j);
 	}
 
 	readl(intel_private.gtt+j-1);
@@ -1194,8 +1198,9 @@
  * this conditional.
  */
 static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
-	unsigned long addr, int type)
+					    struct page *page, int type)
 {
+	dma_addr_t addr = phys_to_gart(page_to_phys(page));
 	/* Shift high bits down */
 	addr |= (addr >> 28) & 0xf0;
 
@@ -1211,6 +1216,9 @@
 	case PCI_DEVICE_ID_INTEL_Q45_HB:
 	case PCI_DEVICE_ID_INTEL_G45_HB:
 	case PCI_DEVICE_ID_INTEL_G41_HB:
+	case PCI_DEVICE_ID_INTEL_IGDNG_D_HB:
+	case PCI_DEVICE_ID_INTEL_IGDNG_M_HB:
+	case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB:
 		*gtt_offset = *gtt_size = MB(2);
 		break;
 	default:
@@ -2186,6 +2194,12 @@
 	    "G45/G43", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
 	    "G41", NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_IGDNG_D_HB, PCI_DEVICE_ID_INTEL_IGDNG_D_IG, 0,
+	    "IGDNG/D", NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_IGDNG_M_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
+	    "IGDNG/M", NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
+	    "IGDNG/MA", NULL, &intel_i965_driver },
 	{ 0, 0, 0, NULL, NULL, NULL }
 };
 
@@ -2387,6 +2401,9 @@
 	ID(PCI_DEVICE_ID_INTEL_Q45_HB),
 	ID(PCI_DEVICE_ID_INTEL_G45_HB),
 	ID(PCI_DEVICE_ID_INTEL_G41_HB),
+	ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB),
+	ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB),
+	ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB),
 	{ }
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/nvidia-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/nvidia-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/nvidia-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/nvidia-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -225,7 +225,7 @@
 	}
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
-			mem->memory[i], mask_type),
+			mem->pages[i], mask_type),
 			agp_bridge->gatt_table+nvidia_private.pg_offset+j);
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/parisc-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/parisc-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/parisc-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/parisc-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,10 @@
 #define AGP8X_MODE_BIT		3
 #define AGP8X_MODE		(1 << AGP8X_MODE_BIT)
 
+static unsigned long
+parisc_agp_mask_memory(struct agp_bridge_data *bridge, unsigned long addr,
+		       int type);
+
 static struct _parisc_agp_info {
 	void __iomem *ioc_regs;
 	void __iomem *lba_regs;
@@ -149,12 +153,12 @@
 	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
 		unsigned long paddr;
 
-		paddr = mem->memory[i];
+		paddr = page_to_phys(mem->pages[i]);
 		for (k = 0;
 		     k < info->io_pages_per_kpage;
 		     k++, j++, paddr += info->io_page_size) {
 			info->gatt[j] =
-				agp_bridge->driver->mask_memory(agp_bridge,
+				parisc_agp_mask_memory(agp_bridge,
 					paddr, type);
 		}
 	}
@@ -185,12 +189,20 @@
 }
 
 static unsigned long
-parisc_agp_mask_memory(struct agp_bridge_data *bridge,
-		    unsigned long addr, int type)
+parisc_agp_mask_memory(struct agp_bridge_data *bridge, unsigned long addr,
+		       int type)
 {
 	return SBA_PDIR_VALID_BIT | addr;
 }
 
+static unsigned long
+parisc_agp_page_mask_memory(struct agp_bridge_data *bridge, struct page *page,
+			    int type)
+{
+	unsigned long addr = phys_to_gart(page_to_phys(page));
+	return SBA_PDIR_VALID_BIT | addr;
+}
+
 static void
 parisc_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
@@ -213,7 +225,7 @@
 	.configure		= parisc_agp_configure,
 	.fetch_size		= parisc_agp_fetch_size,
 	.tlb_flush		= parisc_agp_tlbflush,
-	.mask_memory		= parisc_agp_mask_memory,
+	.mask_memory		= parisc_agp_page_mask_memory,
 	.masks			= parisc_agp_masks,
 	.agp_enable		= parisc_agp_enable,
 	.cache_flush		= global_cache_flush,
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/sgi-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/sgi-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/sgi-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/sgi-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,7 +38,7 @@
 	{0, 0, 0},
 };
 
-static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
+static struct page *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
 {
 	struct page *page;
 	int nid;
@@ -52,7 +52,7 @@
 
 	get_page(page);
 	atomic_inc(&agp_bridge->current_memory_agp);
-	return page_address(page);
+	return page;
 }
 
 /*
@@ -71,8 +71,9 @@
  */
 static unsigned long
 sgi_tioca_mask_memory(struct agp_bridge_data *bridge,
-		      unsigned long addr, int type)
+		      struct page *page, int type)
 {
+	unsigned long addr = phys_to_gart(page_to_phys(page));
 	return tioca_physpage_to_gart(addr);
 }
 
@@ -189,7 +190,7 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		table[j] =
-		    bridge->driver->mask_memory(bridge, mem->memory[i],
+		    bridge->driver->mask_memory(bridge, mem->pages[i],
 						mem->type);
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/sworks-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/sworks-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/sworks-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/sworks-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -349,7 +349,7 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+		writel(agp_bridge->driver->mask_memory(agp_bridge, mem->pages[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	serverworks_tlbflush(mem);
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/char/agp/uninorth-agp.c linux-libre-2.6.31-gnu/drivers/char/agp/uninorth-agp.c
--- linux-libre-2.6.30-gnu/drivers/char/agp/uninorth-agp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/agp/uninorth-agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -146,13 +146,20 @@
 {
 	int i, j, num_entries;
 	void *temp;
+	int mask_type;
 
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_32(temp)->num_entries;
 
-	if (type != 0 || mem->type != 0)
+	if (type != mem->type)
+		return -EINVAL;
+
+	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+	if (mask_type != 0) {
 		/* We know nothing of memory types */
 		return -EINVAL;
+	}
+
 	if ((pg_start + mem->page_count) > num_entries)
 		return -EINVAL;
 
@@ -166,9 +173,9 @@
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		agp_bridge->gatt_table[j] =
-		    cpu_to_le32((mem->memory[i] & 0xFFFFF000UL) | 0x1UL);
-		flush_dcache_range((unsigned long)__va(mem->memory[i]),
-				   (unsigned long)__va(mem->memory[i])+0x1000);
+			cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) | 0x1UL);
+		flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])),
+				   (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000);
 	}
 	(void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]);
 	mb();
@@ -184,13 +191,20 @@
 	int i, num_entries;
 	void *temp;
 	u32 *gp;
+	int mask_type;
 
 	temp = agp_bridge->current_size;
 	num_entries = A_SIZE_32(temp)->num_entries;
 
-	if (type != 0 || mem->type != 0)
+	if (type != mem->type)
+		return -EINVAL;
+
+	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+	if (mask_type != 0) {
 		/* We know nothing of memory types */
 		return -EINVAL;
+	}
+
 	if ((pg_start + mem->page_count) > num_entries)
 		return -EINVAL;
 
@@ -205,9 +219,9 @@
 	}
 
 	for (i = 0; i < mem->page_count; i++) {
-		gp[i] = (mem->memory[i] >> PAGE_SHIFT) | 0x80000000UL;
-		flush_dcache_range((unsigned long)__va(mem->memory[i]),
-				   (unsigned long)__va(mem->memory[i])+0x1000);
+		gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL;
+		flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])),
+				   (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000);
 	}
 	mb();
 	flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
diff -druN linux-libre-2.6.30-gnu/drivers/char/amiserial.c linux-libre-2.6.31-gnu/drivers/char/amiserial.c
--- linux-libre-2.6.30-gnu/drivers/char/amiserial.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/amiserial.c	2009-09-09 18:13:59.000000000 -0400
@@ -81,6 +81,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
 
@@ -779,7 +780,7 @@
 		info->IER |= UART_IER_MSI;
 	}
 	/* TBD:
-	 * Does clearing IER_MSI imply that we should disbale the VBL interrupt ?
+	 * Does clearing IER_MSI imply that we should disable the VBL interrupt ?
 	 */
 
 	/*
diff -druN linux-libre-2.6.30-gnu/drivers/char/bfin_jtag_comm.c linux-libre-2.6.31-gnu/drivers/char/bfin_jtag_comm.c
--- linux-libre-2.6.30-gnu/drivers/char/bfin_jtag_comm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/char/bfin_jtag_comm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,365 @@
+/*
+ * TTY over Blackfin JTAG Communication
+ *
+ * Copyright 2008-2009 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#define DRV_NAME "bfin-jtag-comm"
+#define DEV_NAME "ttyBFJC"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
+
+#include <linux/circ_buf.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <asm/atomic.h>
+
+#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+/* See the Debug/Emulation chapter in the HRM */
+#define EMUDOF   0x00000001	/* EMUDAT_OUT full & valid */
+#define EMUDIF   0x00000002	/* EMUDAT_IN full & valid */
+#define EMUDOOVF 0x00000004	/* EMUDAT_OUT overflow */
+#define EMUDIOVF 0x00000008	/* EMUDAT_IN overflow */
+
+static inline uint32_t bfin_write_emudat(uint32_t emudat)
+{
+	__asm__ __volatile__("emudat = %0;" : : "d"(emudat));
+	return emudat;
+}
+
+static inline uint32_t bfin_read_emudat(void)
+{
+	uint32_t emudat;
+	__asm__ __volatile__("%0 = emudat;" : "=d"(emudat));
+	return emudat;
+}
+
+static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d)
+{
+	return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24));
+}
+
+#define CIRC_SIZE 2048	/* see comment in tty_io.c:do_tty_write() */
+#define CIRC_MASK (CIRC_SIZE - 1)
+#define circ_empty(circ)     ((circ)->head == (circ)->tail)
+#define circ_free(circ)      CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE)
+#define circ_cnt(circ)       CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE)
+#define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK])
+
+static struct tty_driver *bfin_jc_driver;
+static struct task_struct *bfin_jc_kthread;
+static struct tty_struct * volatile bfin_jc_tty;
+static unsigned long bfin_jc_count;
+static DEFINE_MUTEX(bfin_jc_tty_mutex);
+static volatile struct circ_buf bfin_jc_write_buf;
+
+static int
+bfin_jc_emudat_manager(void *arg)
+{
+	uint32_t inbound_len = 0, outbound_len = 0;
+
+	while (!kthread_should_stop()) {
+		/* no one left to give data to, so sleep */
+		if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) {
+			pr_debug("waiting for readers\n");
+			__set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule();
+			__set_current_state(TASK_RUNNING);
+		}
+
+		/* no data available, so just chill */
+		if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) {
+			pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n",
+				inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head);
+			if (inbound_len)
+				schedule();
+			else
+				schedule_timeout_interruptible(HZ);
+			continue;
+		}
+
+		/* if incoming data is ready, eat it */
+		if (bfin_read_DBGSTAT() & EMUDIF) {
+			struct tty_struct *tty;
+			mutex_lock(&bfin_jc_tty_mutex);
+			tty = (struct tty_struct *)bfin_jc_tty;
+			if (tty != NULL) {
+				uint32_t emudat = bfin_read_emudat();
+				if (inbound_len == 0) {
+					pr_debug("incoming length: 0x%08x\n", emudat);
+					inbound_len = emudat;
+				} else {
+					size_t num_chars = (4 <= inbound_len ? 4 : inbound_len);
+					pr_debug("  incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars);
+					inbound_len -= num_chars;
+					tty_insert_flip_string(tty, (unsigned char *)&emudat, num_chars);
+					tty_flip_buffer_push(tty);
+				}
+			}
+			mutex_unlock(&bfin_jc_tty_mutex);
+		}
+
+		/* if outgoing data is ready, post it */
+		if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) {
+			if (outbound_len == 0) {
+				outbound_len = circ_cnt(&bfin_jc_write_buf);
+				bfin_write_emudat(outbound_len);
+				pr_debug("outgoing length: 0x%08x\n", outbound_len);
+			} else {
+				struct tty_struct *tty;
+				int tail = bfin_jc_write_buf.tail;
+				size_t ate = (4 <= outbound_len ? 4 : outbound_len);
+				uint32_t emudat =
+				bfin_write_emudat_chars(
+					circ_byte(&bfin_jc_write_buf, tail + 0),
+					circ_byte(&bfin_jc_write_buf, tail + 1),
+					circ_byte(&bfin_jc_write_buf, tail + 2),
+					circ_byte(&bfin_jc_write_buf, tail + 3)
+				);
+				bfin_jc_write_buf.tail += ate;
+				outbound_len -= ate;
+				mutex_lock(&bfin_jc_tty_mutex);
+				tty = (struct tty_struct *)bfin_jc_tty;
+				if (tty)
+					tty_wakeup(tty);
+				mutex_unlock(&bfin_jc_tty_mutex);
+				pr_debug("  outgoing data: 0x%08x (pushing %zu)\n", emudat, ate);
+			}
+		}
+	}
+
+	__set_current_state(TASK_RUNNING);
+	return 0;
+}
+
+static int
+bfin_jc_open(struct tty_struct *tty, struct file *filp)
+{
+	mutex_lock(&bfin_jc_tty_mutex);
+	pr_debug("open %lu\n", bfin_jc_count);
+	++bfin_jc_count;
+	bfin_jc_tty = tty;
+	wake_up_process(bfin_jc_kthread);
+	mutex_unlock(&bfin_jc_tty_mutex);
+	return 0;
+}
+
+static void
+bfin_jc_close(struct tty_struct *tty, struct file *filp)
+{
+	mutex_lock(&bfin_jc_tty_mutex);
+	pr_debug("close %lu\n", bfin_jc_count);
+	if (--bfin_jc_count == 0)
+		bfin_jc_tty = NULL;
+	wake_up_process(bfin_jc_kthread);
+	mutex_unlock(&bfin_jc_tty_mutex);
+}
+
+/* XXX: we dont handle the put_char() case where we must handle count = 1 */
+static int
+bfin_jc_circ_write(const unsigned char *buf, int count)
+{
+	int i;
+	count = min(count, circ_free(&bfin_jc_write_buf));
+	pr_debug("going to write chunk of %i bytes\n", count);
+	for (i = 0; i < count; ++i)
+		circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i];
+	bfin_jc_write_buf.head += i;
+	return i;
+}
+
+#ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE
+# define acquire_console_sem()
+# define release_console_sem()
+#endif
+static int
+bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	int i;
+	acquire_console_sem();
+	i = bfin_jc_circ_write(buf, count);
+	release_console_sem();
+	wake_up_process(bfin_jc_kthread);
+	return i;
+}
+
+static void
+bfin_jc_flush_chars(struct tty_struct *tty)
+{
+	wake_up_process(bfin_jc_kthread);
+}
+
+static int
+bfin_jc_write_room(struct tty_struct *tty)
+{
+	return circ_free(&bfin_jc_write_buf);
+}
+
+static int
+bfin_jc_chars_in_buffer(struct tty_struct *tty)
+{
+	return circ_cnt(&bfin_jc_write_buf);
+}
+
+static void
+bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	unsigned long expire = jiffies + timeout;
+	while (!circ_empty(&bfin_jc_write_buf)) {
+		if (signal_pending(current))
+			break;
+		if (time_after(jiffies, expire))
+			break;
+	}
+}
+
+static struct tty_operations bfin_jc_ops = {
+	.open            = bfin_jc_open,
+	.close           = bfin_jc_close,
+	.write           = bfin_jc_write,
+	/*.put_char        = bfin_jc_put_char,*/
+	.flush_chars     = bfin_jc_flush_chars,
+	.write_room      = bfin_jc_write_room,
+	.chars_in_buffer = bfin_jc_chars_in_buffer,
+	.wait_until_sent = bfin_jc_wait_until_sent,
+};
+
+static int __init bfin_jc_init(void)
+{
+	int ret;
+
+	bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
+	if (IS_ERR(bfin_jc_kthread))
+		return PTR_ERR(bfin_jc_kthread);
+
+	ret = -ENOMEM;
+
+	bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0;
+	bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL);
+	if (!bfin_jc_write_buf.buf)
+		goto err;
+
+	bfin_jc_driver = alloc_tty_driver(1);
+	if (!bfin_jc_driver)
+		goto err;
+
+	bfin_jc_driver->owner        = THIS_MODULE;
+	bfin_jc_driver->driver_name  = DRV_NAME;
+	bfin_jc_driver->name         = DEV_NAME;
+	bfin_jc_driver->type         = TTY_DRIVER_TYPE_SERIAL;
+	bfin_jc_driver->subtype      = SERIAL_TYPE_NORMAL;
+	bfin_jc_driver->init_termios = tty_std_termios;
+	tty_set_operations(bfin_jc_driver, &bfin_jc_ops);
+
+	ret = tty_register_driver(bfin_jc_driver);
+	if (ret)
+		goto err;
+
+	pr_init(KERN_INFO DRV_NAME ": initialized\n");
+
+	return 0;
+
+ err:
+	put_tty_driver(bfin_jc_driver);
+	kfree(bfin_jc_write_buf.buf);
+	kthread_stop(bfin_jc_kthread);
+	return ret;
+}
+module_init(bfin_jc_init);
+
+static void __exit bfin_jc_exit(void)
+{
+	kthread_stop(bfin_jc_kthread);
+	kfree(bfin_jc_write_buf.buf);
+	tty_unregister_driver(bfin_jc_driver);
+	put_tty_driver(bfin_jc_driver);
+}
+module_exit(bfin_jc_exit);
+
+#if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+static void
+bfin_jc_straight_buffer_write(const char *buf, unsigned count)
+{
+	unsigned ate = 0;
+	while (bfin_read_DBGSTAT() & EMUDOF)
+		continue;
+	bfin_write_emudat(count);
+	while (ate < count) {
+		while (bfin_read_DBGSTAT() & EMUDOF)
+			continue;
+		bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]);
+		ate += 4;
+	}
+}
+#endif
+
+#ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE
+static void
+bfin_jc_console_write(struct console *co, const char *buf, unsigned count)
+{
+	if (bfin_jc_kthread == NULL)
+		bfin_jc_straight_buffer_write(buf, count);
+	else
+		bfin_jc_circ_write(buf, count);
+}
+
+static struct tty_driver *
+bfin_jc_console_device(struct console *co, int *index)
+{
+	*index = co->index;
+	return bfin_jc_driver;
+}
+
+static struct console bfin_jc_console = {
+	.name    = DEV_NAME,
+	.write   = bfin_jc_console_write,
+	.device  = bfin_jc_console_device,
+	.flags   = CON_ANYTIME | CON_PRINTBUFFER,
+	.index   = -1,
+};
+
+static int __init bfin_jc_console_init(void)
+{
+	register_console(&bfin_jc_console);
+	return 0;
+}
+console_initcall(bfin_jc_console_init);
+#endif
+
+#ifdef CONFIG_EARLY_PRINTK
+static void __init
+bfin_jc_early_write(struct console *co, const char *buf, unsigned int count)
+{
+	bfin_jc_straight_buffer_write(buf, count);
+}
+
+static struct __initdata console bfin_jc_early_console = {
+	.name   = "early_BFJC",
+	.write   = bfin_jc_early_write,
+	.flags   = CON_ANYTIME | CON_PRINTBUFFER,
+	.index   = -1,
+};
+
+struct console * __init
+bfin_jc_early_init(unsigned int port, unsigned int cflag)
+{
+	return &bfin_jc_early_console;
+}
+#endif
+
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/char/bsr.c linux-libre-2.6.31-gnu/drivers/char/bsr.c
--- linux-libre-2.6.30-gnu/drivers/char/bsr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/bsr.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/cdev.h>
 #include <linux/list.h>
 #include <linux/mm.h>
+#include <asm/pgtable.h>
 #include <asm/io.h>
 
 /*
@@ -75,12 +76,13 @@
 static int bsr_major;
 
 enum {
-	BSR_8   = 0,
-	BSR_16  = 1,
-	BSR_64  = 2,
-	BSR_128 = 3,
-	BSR_UNKNOWN = 4,
-	BSR_MAX = 5,
+	BSR_8    = 0,
+	BSR_16   = 1,
+	BSR_64   = 2,
+	BSR_128  = 3,
+	BSR_4096 = 4,
+	BSR_UNKNOWN = 5,
+	BSR_MAX  = 6,
 };
 
 static unsigned bsr_types[BSR_MAX];
@@ -117,15 +119,22 @@
 {
 	unsigned long size   = vma->vm_end - vma->vm_start;
 	struct bsr_dev *dev = filp->private_data;
+	int ret;
 
-	if (size > dev->bsr_len || (size & (PAGE_SIZE-1)))
-		return -EINVAL;
-
-	vma->vm_flags |= (VM_IO | VM_DONTEXPAND);
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
-	if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT,
-			       size, vma->vm_page_prot))
+	/* check for the case of a small BSR device and map one 4k page for it*/
+	if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE)
+		ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12,
+				   vma->vm_page_prot);
+	else if (size <= dev->bsr_len)
+		ret = io_remap_pfn_range(vma, vma->vm_start,
+					 dev->bsr_addr >> PAGE_SHIFT,
+					 size, vma->vm_page_prot);
+	else
+		return -EINVAL;
+
+	if (ret)
 		return -EAGAIN;
 
 	return 0;
@@ -205,6 +214,11 @@
 		cur->bsr_stride = bsr_stride[i];
 		cur->bsr_dev    = MKDEV(bsr_major, i + total_bsr_devs);
 
+		/* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */
+		/* we can only map 4k of it, so only advertise the 4k in sysfs */
+		if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE)
+			cur->bsr_len = 4096;
+
 		switch(cur->bsr_bytes) {
 		case 8:
 			cur->bsr_type = BSR_8;
@@ -218,9 +232,11 @@
 		case 128:
 			cur->bsr_type = BSR_128;
 			break;
+		case 4096:
+			cur->bsr_type = BSR_4096;
+			break;
 		default:
 			cur->bsr_type = BSR_UNKNOWN;
-			printk(KERN_INFO "unknown BSR size %d\n",cur->bsr_bytes);
 		}
 
 		cur->bsr_num = bsr_types[cur->bsr_type];
diff -druN linux-libre-2.6.30-gnu/drivers/char/cyclades.c linux-libre-2.6.31-gnu/drivers/char/cyclades.c
--- linux-libre-2.6.30-gnu/drivers/char/cyclades.c	2012-03-22 19:11:18.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/cyclades.c	2012-03-22 20:07:42.000000000 -0400
@@ -604,7 +604,6 @@
 
 #define NR_PORTS	256
 
-#define ZE_V1_NPORTS	64
 #define ZO_V1	0
 #define ZO_V2	1
 #define ZE_V1	2
@@ -634,6 +633,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
@@ -663,18 +663,6 @@
 static void cy_throttle(struct tty_struct *tty);
 static void cy_send_xchar(struct tty_struct *tty, char ch);
 
-#define IS_CYC_Z(card) ((card).num_chips == (unsigned int)-1)
-
-#define Z_FPGA_CHECK(card) \
-	((readl(&((struct RUNTIME_9060 __iomem *) \
-		((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
-
-#define ISZLOADED(card)	(((ZO_V1 == readl(&((struct RUNTIME_9060 __iomem *) \
-			((card).ctl_addr))->mail_box_0)) || \
-			Z_FPGA_CHECK(card)) && \
-			(ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \
-			((card).base_addr+ID_ADDRESS))->signature)))
-
 #ifndef SERIAL_XMIT_SIZE
 #define	SERIAL_XMIT_SIZE	(min(PAGE_SIZE, 4096))
 #endif
@@ -687,8 +675,6 @@
 #define DRIVER_VERSION	0x02010203
 #define RAM_SIZE 0x80000
 
-#define Z_FPGA_LOADED(X)	((readl(&(X)->init_ctrl) & (1<<17)) != 0)
-
 enum zblock_type {
 	ZBLOCK_PRG = 0,
 	ZBLOCK_FPGA = 1
@@ -883,6 +869,29 @@
 static struct timer_list cyz_rx_full_timer[NR_PORTS];
 #endif				/* CONFIG_CYZ_INTR */
 
+static inline bool cy_is_Z(struct cyclades_card *card)
+{
+	return card->num_chips == (unsigned int)-1;
+}
+
+static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr)
+{
+	return readl(&ctl_addr->init_ctrl) & (1 << 17);
+}
+
+static inline bool cyz_fpga_loaded(struct cyclades_card *card)
+{
+	return __cyz_fpga_loaded(card->ctl_addr.p9060);
+}
+
+static inline bool cyz_is_loaded(struct cyclades_card *card)
+{
+	struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
+
+	return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) &&
+			readl(&fw_id->signature) == ZFIRM_ID;
+}
+
 static inline int serial_paranoia_check(struct cyclades_port *info,
 		char *name, const char *routine)
 {
@@ -1395,19 +1404,15 @@
 	unsigned long loc_doorbell;
 
 	firm_id = cinfo->base_addr + ID_ADDRESS;
-	if (!ISZLOADED(*cinfo))
-		return -1;
 	zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 
-	loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *)
-				  (cinfo->ctl_addr))->loc_doorbell);
+	loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
 	if (loc_doorbell) {
 		*cmd = (char)(0xff & loc_doorbell);
 		*channel = readl(&board_ctrl->fwcmd_channel);
 		*param = (__u32) readl(&board_ctrl->fwcmd_param);
-		cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
-			  loc_doorbell, 0xffffffff);
+		cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
 		return 1;
 	}
 	return 0;
@@ -1424,15 +1429,14 @@
 	unsigned int index;
 
 	firm_id = cinfo->base_addr + ID_ADDRESS;
-	if (!ISZLOADED(*cinfo))
+	if (!cyz_is_loaded(cinfo))
 		return -1;
 
 	zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 
 	index = 0;
-	pci_doorbell =
-	    &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
+	pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
 	while ((readl(pci_doorbell) & 0xff) != 0) {
 		if (index++ == 1000)
 			return (int)(readl(pci_doorbell) & 0xff);
@@ -1624,10 +1628,8 @@
 	static struct BOARD_CTRL __iomem *board_ctrl;
 	static struct CH_CTRL __iomem *ch_ctrl;
 	static struct BUF_CTRL __iomem *buf_ctrl;
-	__u32 channel;
+	__u32 channel, param, fw_ver;
 	__u8 cmd;
-	__u32 param;
-	__u32 hw_ver, fw_ver;
 	int special_count;
 	int delta_count;
 
@@ -1635,8 +1637,6 @@
 	zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 	fw_ver = readl(&board_ctrl->fw_version);
-	hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->
-			mail_box_0);
 
 	while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
 		special_count = 0;
@@ -1737,15 +1737,7 @@
 {
 	struct cyclades_card *cinfo = dev_id;
 
-	if (unlikely(cinfo == NULL)) {
-#ifdef CY_DEBUG_INTERRUPTS
-		printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",
-									irq);
-#endif
-		return IRQ_NONE;	/* spurious interrupt */
-	}
-
-	if (unlikely(!ISZLOADED(*cinfo))) {
+	if (unlikely(!cyz_is_loaded(cinfo))) {
 #ifdef CY_DEBUG_INTERRUPTS
 		printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
 				"(IRQ%d).\n", irq);
@@ -1785,7 +1777,6 @@
 	struct tty_struct *tty;
 	struct FIRM_ID __iomem *firm_id;
 	struct ZFW_CTRL __iomem *zfw_ctrl;
-	struct BOARD_CTRL __iomem *board_ctrl;
 	struct BUF_CTRL __iomem *buf_ctrl;
 	unsigned long expires = jiffies + HZ;
 	unsigned int port, card;
@@ -1793,19 +1784,17 @@
 	for (card = 0; card < NR_CARDS; card++) {
 		cinfo = &cy_card[card];
 
-		if (!IS_CYC_Z(*cinfo))
+		if (!cy_is_Z(cinfo))
 			continue;
-		if (!ISZLOADED(*cinfo))
+		if (!cyz_is_loaded(cinfo))
 			continue;
 
 		firm_id = cinfo->base_addr + ID_ADDRESS;
 		zfw_ctrl = cinfo->base_addr +
 				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-		board_ctrl = &(zfw_ctrl->board_ctrl);
 
 	/* Skip first polling cycle to avoid racing conditions with the FW */
 		if (!cinfo->intr_enabled) {
-			cinfo->nports = (int)readl(&board_ctrl->n_channel);
 			cinfo->intr_enabled = 1;
 			continue;
 		}
@@ -1874,7 +1863,7 @@
 
 	set_line_char(info);
 
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -1931,7 +1920,7 @@
 		base_addr = card->base_addr;
 
 		firm_id = base_addr + ID_ADDRESS;
-		if (!ISZLOADED(*card))
+		if (!cyz_is_loaded(card))
 			return -ENODEV;
 
 		zfw_ctrl = card->base_addr +
@@ -2026,7 +2015,7 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -2070,7 +2059,7 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -2126,7 +2115,7 @@
 #endif
 
 		firm_id = base_addr + ID_ADDRESS;
-		if (!ISZLOADED(*card))
+		if (!cyz_is_loaded(card))
 			return;
 
 		zfw_ctrl = card->base_addr +
@@ -2233,7 +2222,7 @@
 #endif
 	info->port.blocked_open++;
 
-	if (!IS_CYC_Z(*cinfo)) {
+	if (!cy_is_Z(cinfo)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = cinfo->bus_index;
@@ -2296,7 +2285,7 @@
 
 		base_addr = cinfo->base_addr;
 		firm_id = base_addr + ID_ADDRESS;
-		if (!ISZLOADED(*cinfo)) {
+		if (!cyz_is_loaded(cinfo)) {
 			__set_current_state(TASK_RUNNING);
 			remove_wait_queue(&info->port.open_wait, &wait);
 			return -EINVAL;
@@ -2397,16 +2386,14 @@
 	   treat it as absent from the system.  This
 	   will make the user pay attention.
 	 */
-	if (IS_CYC_Z(*info->card)) {
+	if (cy_is_Z(info->card)) {
 		struct cyclades_card *cinfo = info->card;
 		struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
 
-		if (!ISZLOADED(*cinfo)) {
-			if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *)
-					 (cinfo->ctl_addr))->mail_box_0)) &&
-					Z_FPGA_CHECK(*cinfo)) &&
-					(ZFIRM_HLT == readl(
-						&firm_id->signature))) {
+		if (!cyz_is_loaded(cinfo)) {
+			if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) &&
+					readl(&firm_id->signature) ==
+					ZFIRM_HLT) {
 				printk(KERN_ERR "cyc:Cyclades-Z Error: you "
 					"need an external power supply for "
 					"this number of ports.\nFirmware "
@@ -2423,18 +2410,13 @@
 		   interrupts should be enabled as soon as the first open
 		   happens to one of its ports. */
 			if (!cinfo->intr_enabled) {
-				struct ZFW_CTRL __iomem *zfw_ctrl;
-				struct BOARD_CTRL __iomem *board_ctrl;
-
-				zfw_ctrl = cinfo->base_addr +
-					(readl(&firm_id->zfwctrl_addr) &
-					 0xfffff);
-
-				board_ctrl = &zfw_ctrl->board_ctrl;
+				u16 intr;
 
 				/* Enable interrupts on the PLX chip */
-				cy_writew(cinfo->ctl_addr + 0x68,
-					readw(cinfo->ctl_addr + 0x68) | 0x0900);
+				intr = readw(&cinfo->ctl_addr.p9060->
+						intr_ctrl_stat) | 0x0900;
+				cy_writew(&cinfo->ctl_addr.p9060->
+						intr_ctrl_stat, intr);
 				/* Enable interrupts on the FW */
 				retval = cyz_issue_cmd(cinfo, 0,
 						C_CM_IRQ_ENBL, 0L);
@@ -2442,8 +2424,6 @@
 					printk(KERN_ERR "cyc:IRQ enable retval "
 						"was %x\n", retval);
 				}
-				cinfo->nports =
-					(int)readl(&board_ctrl->n_channel);
 				cinfo->intr_enabled = 1;
 			}
 		}
@@ -2556,7 +2536,7 @@
 #endif
 	card = info->card;
 	channel = (info->line) - (card->first_line);
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -2601,7 +2581,7 @@
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	spin_unlock_irqrestore(&card->card_lock, flags);
 
-	if (IS_CYC_Z(*card)) {	/* If it is a Z card, flush the on-board
+	if (cy_is_Z(card)) {	/* If it is a Z card, flush the on-board
 					   buffers as well */
 		spin_lock_irqsave(&card->card_lock, flags);
 		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
@@ -2682,7 +2662,7 @@
 
 	spin_lock_irqsave(&card->card_lock, flags);
 
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		int channel = info->line - card->first_line;
 		int index = card->bus_index;
 		void __iomem *base_addr = card->base_addr +
@@ -2902,7 +2882,7 @@
 	channel = (info->line) - (card->first_line);
 
 #ifdef Z_EXT_CHARS_IN_BUFFER
-	if (!IS_CYC_Z(cy_card[card])) {
+	if (!cy_is_Z(card)) {
 #endif				/* Z_EXT_CHARS_IN_BUFFER */
 #ifdef CY_DEBUG_IO
 		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
@@ -2984,7 +2964,6 @@
 	void __iomem *base_addr;
 	int chip, channel, index;
 	unsigned cflag, iflag;
-	unsigned short chip_number;
 	int baud, baud_rate = 0;
 	int i;
 
@@ -3013,9 +2992,8 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	chip_number = channel / 4;
 
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 
 		index = card->bus_index;
 
@@ -3233,21 +3211,17 @@
 	} else {
 		struct FIRM_ID __iomem *firm_id;
 		struct ZFW_CTRL __iomem *zfw_ctrl;
-		struct BOARD_CTRL __iomem *board_ctrl;
 		struct CH_CTRL __iomem *ch_ctrl;
-		struct BUF_CTRL __iomem *buf_ctrl;
 		__u32 sw_flow;
 		int retval;
 
 		firm_id = card->base_addr + ID_ADDRESS;
-		if (!ISZLOADED(*card))
+		if (!cyz_is_loaded(card))
 			return;
 
 		zfw_ctrl = card->base_addr +
 			(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-		board_ctrl = &zfw_ctrl->board_ctrl;
 		ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-		buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
 
 		/* baud rate */
 		baud = tty_get_baud_rate(info->port.tty);
@@ -3457,7 +3431,7 @@
 
 	card = info->card;
 	channel = (info->line) - (card->first_line);
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -3497,7 +3471,7 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -3523,7 +3497,7 @@
 	} else {
 		base_addr = card->base_addr;
 		firm_id = card->base_addr + ID_ADDRESS;
-		if (ISZLOADED(*card)) {
+		if (cyz_is_loaded(card)) {
 			zfw_ctrl = card->base_addr +
 				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
 			board_ctrl = &zfw_ctrl->board_ctrl;
@@ -3566,7 +3540,7 @@
 
 	card = info->card;
 	channel = (info->line) - (card->first_line);
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -3641,7 +3615,7 @@
 		base_addr = card->base_addr;
 
 		firm_id = card->base_addr + ID_ADDRESS;
-		if (ISZLOADED(*card)) {
+		if (cyz_is_loaded(card)) {
 			zfw_ctrl = card->base_addr +
 				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
 			board_ctrl = &zfw_ctrl->board_ctrl;
@@ -3713,7 +3687,7 @@
 	card = info->card;
 
 	spin_lock_irqsave(&card->card_lock, flags);
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		/* Let the transmit ISR take care of this (since it
 		   requires stuffing characters into the output stream).
 		 */
@@ -3782,7 +3756,7 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -3810,7 +3784,7 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -3844,7 +3818,7 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -3867,7 +3841,7 @@
 
 	card = info->card;
 	channel = info->line - card->first_line;
-	if (!IS_CYC_Z(*card)) {
+	if (!cy_is_Z(card)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		index = card->bus_index;
@@ -4121,7 +4095,7 @@
 	card = info->card;
 	channel = info->line - card->first_line;
 
-	if (IS_CYC_Z(*card)) {
+	if (cy_is_Z(card)) {
 		if (ch == STOP_CHAR(tty))
 			cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
 		else if (ch == START_CHAR(tty))
@@ -4154,7 +4128,7 @@
 	card = info->card;
 
 	if (I_IXOFF(tty)) {
-		if (!IS_CYC_Z(*card))
+		if (!cy_is_Z(card))
 			cy_send_xchar(tty, STOP_CHAR(tty));
 		else
 			info->throttle = 1;
@@ -4162,7 +4136,7 @@
 
 	if (tty->termios->c_cflag & CRTSCTS) {
 		channel = info->line - card->first_line;
-		if (!IS_CYC_Z(*card)) {
+		if (!cy_is_Z(card)) {
 			chip = channel >> 2;
 			channel &= 0x03;
 			index = card->bus_index;
@@ -4219,7 +4193,7 @@
 	if (tty->termios->c_cflag & CRTSCTS) {
 		card = info->card;
 		channel = info->line - card->first_line;
-		if (!IS_CYC_Z(*card)) {
+		if (!cy_is_Z(card)) {
 			chip = channel >> 2;
 			channel &= 0x03;
 			index = card->bus_index;
@@ -4263,7 +4237,7 @@
 
 	cinfo = info->card;
 	channel = info->line - cinfo->first_line;
-	if (!IS_CYC_Z(*cinfo)) {
+	if (!cy_is_Z(cinfo)) {
 		index = cinfo->bus_index;
 		chip = channel >> 2;
 		channel &= 0x03;
@@ -4296,7 +4270,7 @@
 	cinfo = info->card;
 	channel = info->line - cinfo->first_line;
 	index = cinfo->bus_index;
-	if (!IS_CYC_Z(*cinfo)) {
+	if (!cy_is_Z(cinfo)) {
 		chip = channel >> 2;
 		channel &= 0x03;
 		base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
@@ -4347,33 +4321,20 @@
 static int __devinit cy_init_card(struct cyclades_card *cinfo)
 {
 	struct cyclades_port *info;
-	u32 uninitialized_var(mailbox);
-	unsigned int nports, port;
+	unsigned int port;
 	unsigned short chip_number;
-	int uninitialized_var(index);
 
 	spin_lock_init(&cinfo->card_lock);
+	cinfo->intr_enabled = 0;
 
-	if (IS_CYC_Z(*cinfo)) {	/* Cyclades-Z */
-		mailbox = readl(&((struct RUNTIME_9060 __iomem *)
-				     cinfo->ctl_addr)->mail_box_0);
-		nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
-		cinfo->intr_enabled = 0;
-		cinfo->nports = 0;	/* Will be correctly set later, after
-					   Z FW is loaded */
-	} else {
-		index = cinfo->bus_index;
-		nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
-	}
-
-	cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
+	cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
+			GFP_KERNEL);
 	if (cinfo->ports == NULL) {
 		printk(KERN_ERR "Cyclades: cannot allocate ports\n");
-		cinfo->nports = 0;
 		return -ENOMEM;
 	}
 
-	for (port = cinfo->first_line; port < cinfo->first_line + nports;
+	for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports;
 			port++) {
 		info = &cinfo->ports[port - cinfo->first_line];
 		tty_port_init(&info->port);
@@ -4387,9 +4348,9 @@
 		init_completion(&info->shutdown_wait);
 		init_waitqueue_head(&info->delta_msr_wait);
 
-		if (IS_CYC_Z(*cinfo)) {
+		if (cy_is_Z(cinfo)) {
 			info->type = PORT_STARTECH;
-			if (mailbox == ZO_V1)
+			if (cinfo->hw_ver == ZO_V1)
 				info->xmit_fifo_size = CYZ_FIFO_SIZE;
 			else
 				info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
@@ -4398,6 +4359,7 @@
 				cyz_rx_restart, (unsigned long)info);
 #endif
 		} else {
+			int index = cinfo->bus_index;
 			info->type = PORT_CIRRUS;
 			info->xmit_fifo_size = CyMAX_CHAR_FIFO;
 			info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
@@ -4430,7 +4392,7 @@
 	}
 
 #ifndef CONFIG_CYZ_INTR
-	if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) {
+	if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) {
 		mod_timer(&cyz_timerlist, jiffies + 1);
 #ifdef CY_PCI_DEBUG
 		printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
@@ -4621,11 +4583,12 @@
 
 		/* set cy_card */
 		cy_card[j].base_addr = cy_isa_address;
-		cy_card[j].ctl_addr = NULL;
+		cy_card[j].ctl_addr.p9050 = NULL;
 		cy_card[j].irq = (int)cy_isa_irq;
 		cy_card[j].bus_index = 0;
 		cy_card[j].first_line = cy_next_channel;
-		cy_card[j].num_chips = cy_isa_nchan / 4;
+		cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+		cy_card[j].nports = cy_isa_nchan;
 		if (cy_init_card(&cy_card[j])) {
 			cy_card[j].base_addr = NULL;
 			free_irq(cy_isa_irq, &cy_card[j]);
@@ -4781,7 +4744,7 @@
 	struct CUSTOM_REG __iomem *cust = base_addr;
 	struct ZFW_CTRL __iomem *pt_zfwctrl;
 	void __iomem *tmp;
-	u32 mailbox, status;
+	u32 mailbox, status, nchan;
 	unsigned int i;
 	int retval;
 
@@ -4793,7 +4756,7 @@
 
 	/* Check whether the firmware is already loaded and running. If
 	   positive, skip this board */
-	if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
+	if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
 		u32 cntval = readl(base_addr + 0x190);
 
 		udelay(100);
@@ -4812,7 +4775,7 @@
 
 	mailbox = readl(&ctl_addr->mail_box_0);
 
-	if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
+	if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) {
 		/* stops CPU and set window to beginning of RAM */
 		cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
 		cy_writel(&cust->cpu_stop, 0);
@@ -4828,7 +4791,7 @@
 				base_addr);
 		if (retval)
 			goto err_rel;
-		if (!Z_FPGA_LOADED(ctl_addr)) {
+		if (!__cyz_fpga_loaded(ctl_addr)) {
 			dev_err(&pdev->dev, "fw upload successful, but fw is "
 					"not loaded\n");
 			goto err_rel;
@@ -4887,7 +4850,7 @@
 				"system before loading the new FW to the "
 				"Cyclades-Z.\n");
 
-			if (Z_FPGA_LOADED(ctl_addr))
+			if (__cyz_fpga_loaded(ctl_addr))
 				plx_init(pdev, irq, ctl_addr);
 
 			retval = -EIO;
@@ -4902,16 +4865,16 @@
 			base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
 			base_addr + readl(&fid->zfwctrl_addr));
 
+	nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
 	dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
-		readl(&pt_zfwctrl->board_ctrl.fw_version),
-		readl(&pt_zfwctrl->board_ctrl.n_channel));
+		readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
 
-	if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
+	if (nchan == 0) {
 		dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
 			"check the connection between the Z host card and the "
 			"serial expanders.\n");
 
-		if (Z_FPGA_LOADED(ctl_addr))
+		if (__cyz_fpga_loaded(ctl_addr))
 			plx_init(pdev, irq, ctl_addr);
 
 		dev_info(&pdev->dev, "Null number of ports detected. Board "
@@ -4932,9 +4895,7 @@
 	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
 			0x00030800UL);
 
-	plx_init(pdev, irq, ctl_addr);
-
-	return 0;
+	return nchan;
 err_rel:
 	release_firmware(fw);
 err:
@@ -4946,7 +4907,7 @@
 {
 	void __iomem *addr0 = NULL, *addr2 = NULL;
 	char *card_name = NULL;
-	u32 mailbox;
+	u32 uninitialized_var(mailbox);
 	unsigned int device_id, nchan = 0, card_no, i;
 	unsigned char plx_ver;
 	int retval, irq;
@@ -5023,11 +4984,12 @@
 		}
 
 		/* Disable interrupts on the PLX before resetting it */
-		cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900);
+		cy_writew(&ctl_addr->intr_ctrl_stat,
+				readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
 
 		plx_init(pdev, irq, addr0);
 
-		mailbox = (u32)readl(&ctl_addr->mail_box_0);
+		mailbox = readl(&ctl_addr->mail_box_0);
 
 		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
 				mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
@@ -5038,12 +5000,8 @@
 
 		if (mailbox == ZE_V1) {
 			card_name = "Cyclades-Ze";
-
-			readl(&ctl_addr->mail_box_0);
-			nchan = ZE_V1_NPORTS;
 		} else {
 			card_name = "Cyclades-8Zo";
-
 #ifdef CY_PCI_DEBUG
 			if (mailbox == ZO_V1) {
 				cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
@@ -5065,15 +5023,12 @@
 			 */
 			if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
 				cy_writel(addr2 + ID_ADDRESS, 0L);
-
-			retval = cyz_load_fw(pdev, addr2, addr0, irq);
-			if (retval)
-				goto err_unmap;
-			/* This must be a Cyclades-8Zo/PCI.  The extendable
-			   version will have a different device_id and will
-			   be allocated its maximum number of ports. */
-			nchan = 8;
 		}
+
+		retval = cyz_load_fw(pdev, addr2, addr0, irq);
+		if (retval <= 0)
+			goto err_unmap;
+		nchan = retval;
 	}
 
 	if ((cy_next_channel + nchan) > NR_PORTS) {
@@ -5103,8 +5058,10 @@
 			dev_err(&pdev->dev, "could not allocate IRQ\n");
 			goto err_unmap;
 		}
-		cy_card[card_no].num_chips = nchan / 4;
+		cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
 	} else {
+		cy_card[card_no].hw_ver = mailbox;
+		cy_card[card_no].num_chips = (unsigned int)-1;
 #ifdef CONFIG_CYZ_INTR
 		/* allocate IRQ only if board has an IRQ */
 		if (irq != 0 && irq != 255) {
@@ -5117,15 +5074,15 @@
 			}
 		}
 #endif				/* CONFIG_CYZ_INTR */
-		cy_card[card_no].num_chips = (unsigned int)-1;
 	}
 
 	/* set cy_card */
 	cy_card[card_no].base_addr = addr2;
-	cy_card[card_no].ctl_addr = addr0;
+	cy_card[card_no].ctl_addr.p9050 = addr0;
 	cy_card[card_no].irq = irq;
 	cy_card[card_no].bus_index = 1;
 	cy_card[card_no].first_line = cy_next_channel;
+	cy_card[card_no].nports = nchan;
 	retval = cy_init_card(&cy_card[card_no]);
 	if (retval)
 		goto err_null;
@@ -5138,17 +5095,20 @@
 		plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
 		switch (plx_ver) {
 		case PLX_9050:
-
 			cy_writeb(addr0 + 0x4c, 0x43);
 			break;
 
 		case PLX_9060:
 		case PLX_9080:
 		default:	/* Old boards, use PLX_9060 */
-			plx_init(pdev, irq, addr0);
-			cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900);
+		{
+			struct RUNTIME_9060 __iomem *ctl_addr = addr0;
+			plx_init(pdev, irq, ctl_addr);
+			cy_writew(&ctl_addr->intr_ctrl_stat,
+				readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
 			break;
 		}
+		}
 	}
 
 	dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
@@ -5179,22 +5139,23 @@
 	unsigned int i;
 
 	/* non-Z with old PLX */
-	if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
+	if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
 			PLX_9050)
-		cy_writeb(cinfo->ctl_addr + 0x4c, 0);
+		cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
 	else
 #ifndef CONFIG_CYZ_INTR
-		if (!IS_CYC_Z(*cinfo))
+		if (!cy_is_Z(cinfo))
 #endif
-		cy_writew(cinfo->ctl_addr + 0x68,
-				readw(cinfo->ctl_addr + 0x68) & ~0x0900);
+		cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
+			readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
+			~0x0900);
 
 	iounmap(cinfo->base_addr);
-	if (cinfo->ctl_addr)
-		iounmap(cinfo->ctl_addr);
+	if (cinfo->ctl_addr.p9050)
+		iounmap(cinfo->ctl_addr.p9050);
 	if (cinfo->irq
 #ifndef CONFIG_CYZ_INTR
-		&& !IS_CYC_Z(*cinfo)
+		&& !cy_is_Z(cinfo)
 #endif /* CONFIG_CYZ_INTR */
 		)
 		free_irq(cinfo->irq, cinfo);
@@ -5240,7 +5201,7 @@
 					(cur_jifs - info->idle_stats.recv_idle)/
 					HZ, info->idle_stats.overruns,
 					/* FIXME: double check locking */
-					(long)info->port.tty->ldisc.ops->num);
+					(long)info->port.tty->ldisc->ops->num);
 			else
 				seq_printf(m, "%3d %8lu %10lu %8lu "
 					"%10lu %8lu %9lu %6ld\n",
@@ -5386,11 +5347,11 @@
 			/* clear interrupt */
 			cy_writeb(card->base_addr + Cy_ClrIntr, 0);
 			iounmap(card->base_addr);
-			if (card->ctl_addr)
-				iounmap(card->ctl_addr);
+			if (card->ctl_addr.p9050)
+				iounmap(card->ctl_addr.p9050);
 			if (card->irq
 #ifndef CONFIG_CYZ_INTR
-				&& !IS_CYC_Z(*card)
+				&& !cy_is_Z(card)
 #endif /* CONFIG_CYZ_INTR */
 				)
 				free_irq(card->irq, card);
diff -druN linux-libre-2.6.30-gnu/drivers/char/dtlk.c linux-libre-2.6.31-gnu/drivers/char/dtlk.c
--- linux-libre-2.6.30-gnu/drivers/char/dtlk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/dtlk.c	2009-09-09 18:13:59.000000000 -0400
@@ -571,7 +571,7 @@
 		portval = inb_p(dtlk_port_tts);
 	} while ((portval & TTS_READABLE) == 0 &&
 		 retries++ < DTLK_MAX_RETRIES);
-	if (retries == DTLK_MAX_RETRIES)
+	if (retries > DTLK_MAX_RETRIES)
 		printk(KERN_ERR "dtlk_read_tts() timeout\n");
 
 	ch = inb_p(dtlk_port_tts);	/* input from TTS port */
@@ -583,7 +583,7 @@
 		portval = inb_p(dtlk_port_tts);
 	} while ((portval & TTS_READABLE) != 0 &&
 		 retries++ < DTLK_MAX_RETRIES);
-	if (retries == DTLK_MAX_RETRIES)
+	if (retries > DTLK_MAX_RETRIES)
 		printk(KERN_ERR "dtlk_read_tts() timeout\n");
 
 	TRACE_RET;
@@ -640,7 +640,7 @@
 		while ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0 &&
 		       retries++ < DTLK_MAX_RETRIES)	/* DT ready? */
 			;
-	if (retries == DTLK_MAX_RETRIES)
+	if (retries > DTLK_MAX_RETRIES)
 		printk(KERN_ERR "dtlk_write_tts() timeout\n");
 
 	outb_p(ch, dtlk_port_tts);	/* output to TTS port */
diff -druN linux-libre-2.6.30-gnu/drivers/char/epca.c linux-libre-2.6.31-gnu/drivers/char/epca.c
--- linux-libre-2.6.30-gnu/drivers/char/epca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/epca.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
@@ -745,7 +746,7 @@
 	return 0;
 }
 
-static void epca_raise_dtr_rts(struct tty_port *port)
+static void epca_dtr_rts(struct tty_port *port, int onoff)
 {
 }
 
@@ -925,7 +926,7 @@
 
 static const struct tty_port_operations epca_port_ops = {
 	.carrier_raised = epca_carrier_raised,
-	.raise_dtr_rts = epca_raise_dtr_rts,
+	.dtr_rts = epca_dtr_rts,
 };
 
 static int info_open(struct tty_struct *tty, struct file *filp)
@@ -1518,7 +1519,7 @@
 		if (event & MODEMCHG_IND) {
 			/* A modem signal change has been indicated */
 			ch->imodem = mstat;
-			if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) {
+			if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) {
 				/* We are now receiving dcd */
 				if (mstat & ch->dcd)
 					wake_up_interruptible(&ch->port.open_wait);
@@ -1765,9 +1766,9 @@
 		 * that the driver will wait on carrier detect.
 		 */
 		if (ts->c_cflag & CLOCAL)
-			clear_bit(ASYNC_CHECK_CD, &ch->port.flags);
+			clear_bit(ASYNCB_CHECK_CD, &ch->port.flags);
 		else
-			set_bit(ASYNC_CHECK_CD, &ch->port.flags);
+			set_bit(ASYNCB_CHECK_CD, &ch->port.flags);
 		mval = ch->m_dtr | ch->m_rts;
 	} /* End CBAUD not detected */
 	iflag = termios2digi_i(ch, ts->c_iflag);
@@ -2114,8 +2115,8 @@
 			tty_wait_until_sent(tty, 0);
 		} else {
 			/* ldisc lock already held in ioctl */
-			if (tty->ldisc.ops->flush_buffer)
-				tty->ldisc.ops->flush_buffer(tty);
+			if (tty->ldisc->ops->flush_buffer)
+				tty->ldisc->ops->flush_buffer(tty);
 		}
 		unlock_kernel();
 		/* Fall Thru */
@@ -2244,7 +2245,8 @@
 			if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
 				tty_hangup(tty);
 				wake_up_interruptible(&ch->port.open_wait);
-				clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags);
+				clear_bit(ASYNCB_NORMAL_ACTIVE,
+						&ch->port.flags);
 			}
 		}
 		tty_kref_put(tty);
diff -druN linux-libre-2.6.30-gnu/drivers/char/hpet.c linux-libre-2.6.31-gnu/drivers/char/hpet.c
--- linux-libre-2.6.30-gnu/drivers/char/hpet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hpet.c	2009-09-09 18:13:59.000000000 -0400
@@ -224,7 +224,7 @@
 			break;
 		}
 
-		gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
+		gsi = acpi_register_gsi(NULL, irq, ACPI_LEVEL_SENSITIVE,
 					ACPI_ACTIVE_LOW);
 		if (gsi > 0)
 			break;
@@ -939,7 +939,7 @@
 		irqp = &res->data.extended_irq;
 
 		for (i = 0; i < irqp->interrupt_count; i++) {
-			irq = acpi_register_gsi(irqp->interrupts[i],
+			irq = acpi_register_gsi(NULL, irqp->interrupts[i],
 				      irqp->triggering, irqp->polarity);
 			if (irq < 0)
 				return AE_ERROR;
diff -druN linux-libre-2.6.30-gnu/drivers/char/hvc_console.c linux-libre-2.6.31-gnu/drivers/char/hvc_console.c
--- linux-libre-2.6.30-gnu/drivers/char/hvc_console.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hvc_console.c	2009-09-09 18:13:59.000000000 -0400
@@ -552,7 +552,7 @@
 	struct hvc_struct *hp = tty->driver_data;
 
 	if (!hp)
-		return -1;
+		return 0;
 	return hp->n_outbuf;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/hvc_iseries.c linux-libre-2.6.31-gnu/drivers/char/hvc_iseries.c
--- linux-libre-2.6.30-gnu/drivers/char/hvc_iseries.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hvc_iseries.c	2009-09-09 18:13:59.000000000 -0400
@@ -241,7 +241,7 @@
 static struct vio_driver hvc_vio_driver = {
 	.id_table	= hvc_driver_table,
 	.probe		= hvc_vio_probe,
-	.remove		= hvc_vio_remove,
+	.remove		= __devexit_p(hvc_vio_remove),
 	.driver		= {
 		.name	= hvc_driver_name,
 		.owner	= THIS_MODULE,
diff -druN linux-libre-2.6.30-gnu/drivers/char/hvc_iucv.c linux-libre-2.6.31-gnu/drivers/char/hvc_iucv.c
--- linux-libre-2.6.30-gnu/drivers/char/hvc_iucv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hvc_iucv.c	2009-09-09 18:13:59.000000000 -0400
@@ -4,7 +4,7 @@
  * This HVC device driver provides terminal access using
  * z/VM IUCV communication paths.
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008, 2009
  *
  * Author(s):	Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
  */
@@ -15,6 +15,7 @@
 #include <asm/ebcdic.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/mempool.h>
 #include <linux/moduleparam.h>
@@ -74,6 +75,7 @@
 	wait_queue_head_t	sndbuf_waitq;	/* wait for send completion */
 	struct list_head	tty_outqueue;	/* outgoing IUCV messages */
 	struct list_head	tty_inqueue;	/* incoming IUCV messages */
+	struct device		*dev;		/* device structure */
 };
 
 struct iucv_tty_buffer {
@@ -542,7 +544,68 @@
 
 	if (sync_wait)
 		wait_event_timeout(priv->sndbuf_waitq,
-				   tty_outqueue_empty(priv), HZ);
+				   tty_outqueue_empty(priv), HZ/10);
+}
+
+/**
+ * hvc_iucv_hangup() - Sever IUCV path and schedule hvc tty hang up
+ * @priv:	Pointer to hvc_iucv_private structure
+ *
+ * This routine severs an existing IUCV communication path and hangs
+ * up the underlying HVC terminal device.
+ * The hang-up occurs only if an IUCV communication path is established;
+ * otherwise there is no need to hang up the terminal device.
+ *
+ * The IUCV HVC hang-up is separated into two steps:
+ * 1. After the IUCV path has been severed, the iucv_state is set to
+ *    IUCV_SEVERED.
+ * 2. Later, when the HVC thread calls hvc_iucv_get_chars(), the
+ *    IUCV_SEVERED state causes the tty hang-up in the HVC layer.
+ *
+ * If the tty has not yet been opened, clean up the hvc_iucv_private
+ * structure to allow re-connects.
+ * If the tty has been opened, let get_chars() return -EPIPE to signal
+ * the HVC layer to hang up the tty and, if so, wake up the HVC thread
+ * to call get_chars()...
+ *
+ * Special notes on hanging up a HVC terminal instantiated as console:
+ * Hang-up:	1. do_tty_hangup() replaces file ops (= hung_up_tty_fops)
+ *		2. do_tty_hangup() calls tty->ops->close() for console_filp
+ *			=> no hangup notifier is called by HVC (default)
+ *		2. hvc_close() returns because of tty_hung_up_p(filp)
+ *			=> no delete notifier is called!
+ * Finally, the back-end is not being notified, thus, the tty session is
+ * kept active (TTY_OPEN) to be ready for re-connects.
+ *
+ * Locking:	spin_lock(&priv->lock) w/o disabling bh
+ */
+static void hvc_iucv_hangup(struct hvc_iucv_private *priv)
+{
+	struct iucv_path *path;
+
+	path = NULL;
+	spin_lock(&priv->lock);
+	if (priv->iucv_state == IUCV_CONNECTED) {
+		path = priv->path;
+		priv->path = NULL;
+		priv->iucv_state = IUCV_SEVERED;
+		if (priv->tty_state == TTY_CLOSED)
+			hvc_iucv_cleanup(priv);
+		else
+			/* console is special (see above) */
+			if (priv->is_console) {
+				hvc_iucv_cleanup(priv);
+				priv->tty_state = TTY_OPENED;
+			} else
+				hvc_kick();
+	}
+	spin_unlock(&priv->lock);
+
+	/* finally sever path (outside of priv->lock due to lock ordering) */
+	if (path) {
+		iucv_path_sever(path, NULL);
+		iucv_path_free(path);
+	}
 }
 
 /**
@@ -735,11 +798,8 @@
  * @ipuser:	User specified data for this path
  *		(AF_IUCV: port/service name and originator port)
  *
- * The function also severs the path (as required by the IUCV protocol) and
- * sets the iucv state to IUCV_SEVERED for the associated struct
- * hvc_iucv_private instance. Later, the IUCV_SEVERED state triggers a tty
- * hangup (hvc_iucv_get_chars() / hvc_iucv_write()).
- * If tty portion of the HVC is closed, clean up the outqueue.
+ * This function calls the hvc_iucv_hangup() function for the
+ * respective IUCV HVC terminal.
  *
  * Locking:	struct hvc_iucv_private->lock
  */
@@ -747,33 +807,7 @@
 {
 	struct hvc_iucv_private *priv = path->private;
 
-	spin_lock(&priv->lock);
-	priv->iucv_state = IUCV_SEVERED;
-
-	/* If the tty has not yet been opened, clean up the hvc_iucv_private
-	 * structure to allow re-connects.
-	 * This is also done for our console device because console hangups
-	 * are handled specially and no notifier is called by HVC.
-	 * The tty session is active (TTY_OPEN) and ready for re-connects...
-	 *
-	 * If it has been opened, let get_chars() return -EPIPE to signal the
-	 * HVC layer to hang up the tty.
-	 * If so, we need to wake up the HVC thread to call get_chars()...
-	 */
-	priv->path = NULL;
-	if (priv->tty_state == TTY_CLOSED)
-		hvc_iucv_cleanup(priv);
-	else
-		if (priv->is_console) {
-			hvc_iucv_cleanup(priv);
-			priv->tty_state = TTY_OPENED;
-		} else
-			hvc_kick();
-	spin_unlock(&priv->lock);
-
-	/* finally sever path (outside of priv->lock due to lock ordering) */
-	iucv_path_sever(path, ipuser);
-	iucv_path_free(path);
+	hvc_iucv_hangup(priv);
 }
 
 /**
@@ -853,6 +887,37 @@
 	destroy_tty_buffer_list(&list_remove);
 }
 
+/**
+ * hvc_iucv_pm_freeze() - Freeze PM callback
+ * @dev:	IUVC HVC terminal device
+ *
+ * Sever an established IUCV communication path and
+ * trigger a hang-up of the underlying HVC terminal.
+ */
+static int hvc_iucv_pm_freeze(struct device *dev)
+{
+	struct hvc_iucv_private *priv = dev_get_drvdata(dev);
+
+	local_bh_disable();
+	hvc_iucv_hangup(priv);
+	local_bh_enable();
+
+	return 0;
+}
+
+/**
+ * hvc_iucv_pm_restore_thaw() - Thaw and restore PM callback
+ * @dev:	IUVC HVC terminal device
+ *
+ * Wake up the HVC thread to trigger hang-up and respective
+ * HVC back-end notifier invocations.
+ */
+static int hvc_iucv_pm_restore_thaw(struct device *dev)
+{
+	hvc_kick();
+	return 0;
+}
+
 
 /* HVC operations */
 static struct hv_ops hvc_iucv_ops = {
@@ -863,6 +928,20 @@
 	.notifier_hangup = hvc_iucv_notifier_hangup,
 };
 
+/* Suspend / resume device operations */
+static struct dev_pm_ops hvc_iucv_pm_ops = {
+	.freeze	  = hvc_iucv_pm_freeze,
+	.thaw	  = hvc_iucv_pm_restore_thaw,
+	.restore  = hvc_iucv_pm_restore_thaw,
+};
+
+/* IUCV HVC device driver */
+static struct device_driver hvc_iucv_driver = {
+	.name = KMSG_COMPONENT,
+	.bus  = &iucv_bus,
+	.pm   = &hvc_iucv_pm_ops,
+};
+
 /**
  * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
  * @id:			hvc_iucv_table index
@@ -897,14 +976,12 @@
 	/* set console flag */
 	priv->is_console = is_console;
 
-	/* finally allocate hvc */
+	/* allocate hvc device */
 	priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /*		  PAGE_SIZE */
 			      HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256);
 	if (IS_ERR(priv->hvc)) {
 		rc = PTR_ERR(priv->hvc);
-		free_page((unsigned long) priv->sndbuf);
-		kfree(priv);
-		return rc;
+		goto out_error_hvc;
 	}
 
 	/* notify HVC thread instead of using polling */
@@ -915,8 +992,45 @@
 	memcpy(priv->srv_name, name, 8);
 	ASCEBC(priv->srv_name, 8);
 
+	/* create and setup device */
+	priv->dev = kzalloc(sizeof(*priv->dev), GFP_KERNEL);
+	if (!priv->dev) {
+		rc = -ENOMEM;
+		goto out_error_dev;
+	}
+	dev_set_name(priv->dev, "hvc_iucv%d", id);
+	dev_set_drvdata(priv->dev, priv);
+	priv->dev->bus = &iucv_bus;
+	priv->dev->parent = iucv_root;
+	priv->dev->driver = &hvc_iucv_driver;
+	priv->dev->release = (void (*)(struct device *)) kfree;
+	rc = device_register(priv->dev);
+	if (rc) {
+		kfree(priv->dev);
+		goto out_error_dev;
+	}
+
 	hvc_iucv_table[id] = priv;
 	return 0;
+
+out_error_dev:
+	hvc_remove(priv->hvc);
+out_error_hvc:
+	free_page((unsigned long) priv->sndbuf);
+	kfree(priv);
+
+	return rc;
+}
+
+/**
+ * hvc_iucv_destroy() - Destroy and free hvc_iucv_private instances
+ */
+static void __init hvc_iucv_destroy(struct hvc_iucv_private *priv)
+{
+	hvc_remove(priv->hvc);
+	device_unregister(priv->dev);
+	free_page((unsigned long) priv->sndbuf);
+	kfree(priv);
 }
 
 /**
@@ -1109,6 +1223,11 @@
 		goto out_error;
 	}
 
+	/* register IUCV HVC device driver */
+	rc = driver_register(&hvc_iucv_driver);
+	if (rc)
+		goto out_error;
+
 	/* parse hvc_iucv_allow string and create z/VM user ID filter list */
 	if (hvc_iucv_filter_string) {
 		rc = hvc_iucv_setup_filter(hvc_iucv_filter_string);
@@ -1183,15 +1302,14 @@
 	iucv_unregister(&hvc_iucv_handler, 0);
 out_error_hvc:
 	for (i = 0; i < hvc_iucv_devices; i++)
-		if (hvc_iucv_table[i]) {
-			if (hvc_iucv_table[i]->hvc)
-				hvc_remove(hvc_iucv_table[i]->hvc);
-			kfree(hvc_iucv_table[i]);
-		}
+		if (hvc_iucv_table[i])
+			hvc_iucv_destroy(hvc_iucv_table[i]);
 out_error_memory:
 	mempool_destroy(hvc_iucv_mempool);
 	kmem_cache_destroy(hvc_iucv_buffer_cache);
 out_error:
+	if (hvc_iucv_filter)
+		kfree(hvc_iucv_filter);
 	hvc_iucv_devices = 0; /* ensure that we do not provide any device */
 	return rc;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/hvcs.c linux-libre-2.6.31-gnu/drivers/char/hvcs.c
--- linux-libre-2.6.30-gnu/drivers/char/hvcs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hvcs.c	2009-09-09 18:13:59.000000000 -0400
@@ -347,7 +347,7 @@
 
 static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
 {
-	return viod->dev.driver_data;
+	return dev_get_drvdata(&viod->dev);
 }
 /* The sysfs interface for the driver and devices */
 
@@ -785,7 +785,7 @@
 	kref_init(&hvcsd->kref);
 
 	hvcsd->vdev = dev;
-	dev->dev.driver_data = hvcsd;
+	dev_set_drvdata(&dev->dev, hvcsd);
 
 	hvcsd->index = index;
 
@@ -831,7 +831,7 @@
 
 static int __devexit hvcs_remove(struct vio_dev *dev)
 {
-	struct hvcs_struct *hvcsd = dev->dev.driver_data;
+	struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
 	unsigned long flags;
 	struct tty_struct *tty;
 
@@ -868,7 +868,7 @@
 static struct vio_driver hvcs_vio_driver = {
 	.id_table	= hvcs_driver_table,
 	.probe		= hvcs_probe,
-	.remove		= hvcs_remove,
+	.remove		= __devexit_p(hvcs_remove),
 	.driver		= {
 		.name	= hvcs_driver_name,
 		.owner	= THIS_MODULE,
diff -druN linux-libre-2.6.30-gnu/drivers/char/hvc_vio.c linux-libre-2.6.31-gnu/drivers/char/hvc_vio.c
--- linux-libre-2.6.30-gnu/drivers/char/hvc_vio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hvc_vio.c	2009-09-09 18:13:59.000000000 -0400
@@ -113,7 +113,7 @@
 static struct vio_driver hvc_vio_driver = {
 	.id_table	= hvc_driver_table,
 	.probe		= hvc_vio_probe,
-	.remove		= hvc_vio_remove,
+	.remove		= __devexit_p(hvc_vio_remove),
 	.driver		= {
 		.name	= hvc_driver_name,
 		.owner	= THIS_MODULE,
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/core.c linux-libre-2.6.31-gnu/drivers/char/hw_random/core.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -153,6 +153,7 @@
 static struct miscdevice rng_miscdev = {
 	.minor		= RNG_MISCDEV_MINOR,
 	.name		= RNG_MODULE_NAME,
+	.devnode	= "hwrng",
 	.fops		= &rng_chrdev_ops,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/intel-rng.c linux-libre-2.6.31-gnu/drivers/char/hw_random/intel-rng.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/intel-rng.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/intel-rng.c	2009-09-09 18:13:59.000000000 -0400
@@ -305,10 +305,11 @@
 	     (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
 	    == BIOS_CNTL_LOCK_ENABLE_MASK) {
 		static __initdata /*const*/ char warning[] =
-			KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
-			KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
-			KERN_WARNING PFX "you are certain that your system has a functional\n"
-			KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
+			KERN_WARNING
+PFX "Firmware space is locked read-only. If you can't or\n"
+PFX "don't want to disable this in firmware setup, and if\n"
+PFX "you are certain that your system has a functional\n"
+PFX "RNG, try using the 'no_fwh_detect' option.\n";
 
 		if (no_fwh_detect)
 			return -ENODEV;
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/Kconfig linux-libre-2.6.31-gnu/drivers/char/hw_random/Kconfig
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -88,7 +88,7 @@
 
 config HW_RANDOM_VIA
 	tristate "VIA HW Random Number Generator support"
-	depends on HW_RANDOM && X86_32
+	depends on HW_RANDOM && X86
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -148,3 +148,28 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called virtio-rng.  If unsure, say N.
+
+config HW_RANDOM_TX4939
+	tristate "TX4939 Random Number Generator support"
+	depends on HW_RANDOM && SOC_TX4939
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on TX4939 SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tx4939-rng.
+
+	  If unsure, say Y.
+
+config HW_RANDOM_MXC_RNGA
+	tristate "Freescale i.MX RNGA Random Number Generator"
+	depends on HW_RANDOM && ARCH_HAS_RNGA
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Freescale i.MX processors.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mxc-rnga.
+
+	  If unsure, say Y.
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/Makefile linux-libre-2.6.31-gnu/drivers/char/hw_random/Makefile
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -15,3 +15,5 @@
 obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
 obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
 obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
+obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
+obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/mxc-rnga.c linux-libre-2.6.31-gnu/drivers/char/hw_random/mxc-rnga.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/mxc-rnga.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/mxc-rnga.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,247 @@
+/*
+ * RNG driver for Freescale RNGA
+ *
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Author: Alan Carvalho de Assis <acassis@gmail.com>
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * This driver is based on other RNG drivers.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+
+/* RNGA Registers */
+#define RNGA_CONTROL			0x00
+#define RNGA_STATUS			0x04
+#define RNGA_ENTROPY			0x08
+#define RNGA_OUTPUT_FIFO		0x0c
+#define RNGA_MODE			0x10
+#define RNGA_VERIFICATION_CONTROL	0x14
+#define RNGA_OSC_CONTROL_COUNTER	0x18
+#define RNGA_OSC1_COUNTER		0x1c
+#define RNGA_OSC2_COUNTER		0x20
+#define RNGA_OSC_COUNTER_STATUS		0x24
+
+/* RNGA Registers Range */
+#define RNG_ADDR_RANGE			0x28
+
+/* RNGA Control Register */
+#define RNGA_CONTROL_SLEEP		0x00000010
+#define RNGA_CONTROL_CLEAR_INT		0x00000008
+#define RNGA_CONTROL_MASK_INTS		0x00000004
+#define RNGA_CONTROL_HIGH_ASSURANCE	0x00000002
+#define RNGA_CONTROL_GO			0x00000001
+
+#define RNGA_STATUS_LEVEL_MASK		0x0000ff00
+
+/* RNGA Status Register */
+#define RNGA_STATUS_OSC_DEAD		0x80000000
+#define RNGA_STATUS_SLEEP		0x00000010
+#define RNGA_STATUS_ERROR_INT		0x00000008
+#define RNGA_STATUS_FIFO_UNDERFLOW	0x00000004
+#define RNGA_STATUS_LAST_READ_STATUS	0x00000002
+#define RNGA_STATUS_SECURITY_VIOLATION	0x00000001
+
+static struct platform_device *rng_dev;
+
+static int mxc_rnga_data_present(struct hwrng *rng)
+{
+	int level;
+	void __iomem *rng_base = (void __iomem *)rng->priv;
+
+	/* how many random numbers is in FIFO? [0-16] */
+	level = ((__raw_readl(rng_base + RNGA_STATUS) &
+			RNGA_STATUS_LEVEL_MASK) >> 8);
+
+	return level > 0 ? 1 : 0;
+}
+
+static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
+{
+	int err;
+	u32 ctrl;
+	void __iomem *rng_base = (void __iomem *)rng->priv;
+
+	/* retrieve a random number from FIFO */
+	*data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO);
+
+	/* some error while reading this random number? */
+	err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT;
+
+	/* if error: clear error interrupt, but doesn't return random number */
+	if (err) {
+		dev_dbg(&rng_dev->dev, "Error while reading random number!\n");
+		ctrl = __raw_readl(rng_base + RNGA_CONTROL);
+		__raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT,
+					rng_base + RNGA_CONTROL);
+		return 0;
+	} else
+		return 4;
+}
+
+static int mxc_rnga_init(struct hwrng *rng)
+{
+	u32 ctrl, osc;
+	void __iomem *rng_base = (void __iomem *)rng->priv;
+
+	/* wake up */
+	ctrl = __raw_readl(rng_base + RNGA_CONTROL);
+	__raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL);
+
+	/* verify if oscillator is working */
+	osc = __raw_readl(rng_base + RNGA_STATUS);
+	if (osc & RNGA_STATUS_OSC_DEAD) {
+		dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n");
+		return -ENODEV;
+	}
+
+	/* go running */
+	ctrl = __raw_readl(rng_base + RNGA_CONTROL);
+	__raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL);
+
+	return 0;
+}
+
+static void mxc_rnga_cleanup(struct hwrng *rng)
+{
+	u32 ctrl;
+	void __iomem *rng_base = (void __iomem *)rng->priv;
+
+	ctrl = __raw_readl(rng_base + RNGA_CONTROL);
+
+	/* stop rnga */
+	__raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL);
+}
+
+static struct hwrng mxc_rnga = {
+	.name = "mxc-rnga",
+	.init = mxc_rnga_init,
+	.cleanup = mxc_rnga_cleanup,
+	.data_present = mxc_rnga_data_present,
+	.data_read = mxc_rnga_data_read
+};
+
+static int __init mxc_rnga_probe(struct platform_device *pdev)
+{
+	int err = -ENODEV;
+	struct clk *clk;
+	struct resource *res, *mem;
+	void __iomem *rng_base = NULL;
+
+	if (rng_dev)
+		return -EBUSY;
+
+	clk = clk_get(&pdev->dev, "rng");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Could not get rng_clk!\n");
+		err = PTR_ERR(clk);
+		goto out;
+	}
+
+	clk_enable(clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENOENT;
+		goto err_region;
+	}
+
+	mem = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (mem == NULL) {
+		err = -EBUSY;
+		goto err_region;
+	}
+
+	rng_base = ioremap(res->start, resource_size(res));
+	if (!rng_base) {
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	mxc_rnga.priv = (unsigned long)rng_base;
+
+	err = hwrng_register(&mxc_rnga);
+	if (err) {
+		dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err);
+		goto err_register;
+	}
+
+	rng_dev = pdev;
+
+	dev_info(&pdev->dev, "MXC RNGA Registered.\n");
+
+	return 0;
+
+err_register:
+	iounmap(rng_base);
+	rng_base = NULL;
+
+err_ioremap:
+	release_mem_region(res->start, resource_size(res));
+
+err_region:
+	clk_disable(clk);
+	clk_put(clk);
+
+out:
+	return err;
+}
+
+static int __exit mxc_rnga_remove(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	void __iomem *rng_base = (void __iomem *)mxc_rnga.priv;
+	struct clk *clk = clk_get(&pdev->dev, "rng");
+
+	hwrng_unregister(&mxc_rnga);
+
+	iounmap(rng_base);
+
+	release_mem_region(res->start, resource_size(res));
+
+	clk_disable(clk);
+	clk_put(clk);
+
+	return 0;
+}
+
+static struct platform_driver mxc_rnga_driver = {
+	.driver = {
+		   .name = "mxc_rnga",
+		   .owner = THIS_MODULE,
+		   },
+	.remove = __exit_p(mxc_rnga_remove),
+};
+
+static int __init mod_init(void)
+{
+	return platform_driver_probe(&mxc_rnga_driver, mxc_rnga_probe);
+}
+
+static void __exit mod_exit(void)
+{
+	platform_driver_unregister(&mxc_rnga_driver);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("H/W RNGA driver for i.MX");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/omap-rng.c linux-libre-2.6.31-gnu/drivers/char/hw_random/omap-rng.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/omap-rng.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/omap-rng.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,7 +89,7 @@
 	.data_read	= omap_rng_data_read,
 };
 
-static int __init omap_rng_probe(struct platform_device *pdev)
+static int __devinit omap_rng_probe(struct platform_device *pdev)
 {
 	struct resource *res, *mem;
 	int ret;
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/timeriomem-rng.c linux-libre-2.6.31-gnu/drivers/char/hw_random/timeriomem-rng.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/timeriomem-rng.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/timeriomem-rng.c	2009-09-09 18:13:59.000000000 -0400
@@ -88,9 +88,9 @@
 	.priv		= 0,
 };
 
-static int __init timeriomem_rng_probe(struct platform_device *pdev)
+static int __devinit timeriomem_rng_probe(struct platform_device *pdev)
 {
-	struct resource *res, *mem;
+	struct resource *res;
 	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -98,21 +98,12 @@
 	if (!res)
 		return -ENOENT;
 
-	mem = request_mem_region(res->start, res->end - res->start + 1,
-				 pdev->name);
-	if (mem == NULL)
-		return -EBUSY;
-
-	dev_set_drvdata(&pdev->dev, mem);
-
 	timeriomem_rng_data = pdev->dev.platform_data;
 
 	timeriomem_rng_data->address = ioremap(res->start,
 						res->end - res->start + 1);
-	if (!timeriomem_rng_data->address) {
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
+	if (!timeriomem_rng_data->address)
+		return -EIO;
 
 	if (timeriomem_rng_data->period != 0
 		&& usecs_to_jiffies(timeriomem_rng_data->period) > 0) {
@@ -125,7 +116,7 @@
 
 	ret = hwrng_register(&timeriomem_rng_ops);
 	if (ret)
-		goto err_register;
+		goto failed;
 
 	dev_info(&pdev->dev, "32bits from 0x%p @ %dus\n",
 			timeriomem_rng_data->address,
@@ -133,24 +124,19 @@
 
 	return 0;
 
-err_register:
+failed:
 	dev_err(&pdev->dev, "problem registering\n");
 	iounmap(timeriomem_rng_data->address);
-err_ioremap:
-	release_resource(mem);
 
 	return ret;
 }
 
 static int __devexit timeriomem_rng_remove(struct platform_device *pdev)
 {
-	struct resource *mem = dev_get_drvdata(&pdev->dev);
-
 	del_timer_sync(&timeriomem_rng_timer);
 	hwrng_unregister(&timeriomem_rng_ops);
 
 	iounmap(timeriomem_rng_data->address);
-	release_resource(mem);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/tx4939-rng.c linux-libre-2.6.31-gnu/drivers/char/hw_random/tx4939-rng.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/tx4939-rng.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/tx4939-rng.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,184 @@
+/*
+ * RNG driver for TX4939 Random Number Generators (RNG)
+ *
+ * Copyright (C) 2009 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+
+#define TX4939_RNG_RCSR		0x00000000
+#define TX4939_RNG_ROR(n)	(0x00000018 + (n) * 8)
+
+#define TX4939_RNG_RCSR_INTE	0x00000008
+#define TX4939_RNG_RCSR_RST	0x00000004
+#define TX4939_RNG_RCSR_FIN	0x00000002
+#define TX4939_RNG_RCSR_ST	0x00000001
+
+struct tx4939_rng {
+	struct hwrng rng;
+	void __iomem *base;
+	u64 databuf[3];
+	unsigned int data_avail;
+};
+
+static void rng_io_start(void)
+{
+#ifndef CONFIG_64BIT
+	/*
+	 * readq is reading a 64-bit register using a 64-bit load.  On
+	 * a 32-bit kernel however interrupts or any other processor
+	 * exception would clobber the upper 32-bit of the processor
+	 * register so interrupts need to be disabled.
+	 */
+	local_irq_disable();
+#endif
+}
+
+static void rng_io_end(void)
+{
+#ifndef CONFIG_64BIT
+	local_irq_enable();
+#endif
+}
+
+static u64 read_rng(void __iomem *base, unsigned int offset)
+{
+	return ____raw_readq(base + offset);
+}
+
+static void write_rng(u64 val, void __iomem *base, unsigned int offset)
+{
+	return ____raw_writeq(val, base + offset);
+}
+
+static int tx4939_rng_data_present(struct hwrng *rng, int wait)
+{
+	struct tx4939_rng *rngdev = container_of(rng, struct tx4939_rng, rng);
+	int i;
+
+	if (rngdev->data_avail)
+		return rngdev->data_avail;
+	for (i = 0; i < 20; i++) {
+		rng_io_start();
+		if (!(read_rng(rngdev->base, TX4939_RNG_RCSR)
+		      & TX4939_RNG_RCSR_ST)) {
+			rngdev->databuf[0] =
+				read_rng(rngdev->base, TX4939_RNG_ROR(0));
+			rngdev->databuf[1] =
+				read_rng(rngdev->base, TX4939_RNG_ROR(1));
+			rngdev->databuf[2] =
+				read_rng(rngdev->base, TX4939_RNG_ROR(2));
+			rngdev->data_avail =
+				sizeof(rngdev->databuf) / sizeof(u32);
+			/* Start RNG */
+			write_rng(TX4939_RNG_RCSR_ST,
+				  rngdev->base, TX4939_RNG_RCSR);
+			wait = 0;
+		}
+		rng_io_end();
+		if (!wait)
+			break;
+		/* 90 bus clock cycles by default for generation */
+		ndelay(90 * 5);
+	}
+	return rngdev->data_avail;
+}
+
+static int tx4939_rng_data_read(struct hwrng *rng, u32 *buffer)
+{
+	struct tx4939_rng *rngdev = container_of(rng, struct tx4939_rng, rng);
+
+	rngdev->data_avail--;
+	*buffer = *((u32 *)&rngdev->databuf + rngdev->data_avail);
+	return sizeof(u32);
+}
+
+static int __init tx4939_rng_probe(struct platform_device *dev)
+{
+	struct tx4939_rng *rngdev;
+	struct resource *r;
+	int i;
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -EBUSY;
+	rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL);
+	if (!rngdev)
+		return -ENOMEM;
+	if (!devm_request_mem_region(&dev->dev, r->start, resource_size(r),
+				     dev_name(&dev->dev)))
+		return -EBUSY;
+	rngdev->base = devm_ioremap(&dev->dev, r->start, resource_size(r));
+	if (!rngdev->base)
+		return -EBUSY;
+
+	rngdev->rng.name = dev_name(&dev->dev);
+	rngdev->rng.data_present = tx4939_rng_data_present;
+	rngdev->rng.data_read = tx4939_rng_data_read;
+
+	rng_io_start();
+	/* Reset RNG */
+	write_rng(TX4939_RNG_RCSR_RST, rngdev->base, TX4939_RNG_RCSR);
+	write_rng(0, rngdev->base, TX4939_RNG_RCSR);
+	/* Start RNG */
+	write_rng(TX4939_RNG_RCSR_ST, rngdev->base, TX4939_RNG_RCSR);
+	rng_io_end();
+	/*
+	 * Drop first two results.  From the datasheet:
+	 * The quality of the random numbers generated immediately
+	 * after reset can be insufficient.  Therefore, do not use
+	 * random numbers obtained from the first and second
+	 * generations; use the ones from the third or subsequent
+	 * generation.
+	 */
+	for (i = 0; i < 2; i++) {
+		rngdev->data_avail = 0;
+		if (!tx4939_rng_data_present(&rngdev->rng, 1))
+			return -EIO;
+	}
+
+	platform_set_drvdata(dev, rngdev);
+	return hwrng_register(&rngdev->rng);
+}
+
+static int __exit tx4939_rng_remove(struct platform_device *dev)
+{
+	struct tx4939_rng *rngdev = platform_get_drvdata(dev);
+
+	hwrng_unregister(&rngdev->rng);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver tx4939_rng_driver = {
+	.driver		= {
+		.name	= "tx4939-rng",
+		.owner	= THIS_MODULE,
+	},
+	.remove = tx4939_rng_remove,
+};
+
+static int __init tx4939rng_init(void)
+{
+	return platform_driver_probe(&tx4939_rng_driver, tx4939_rng_probe);
+}
+
+static void __exit tx4939rng_exit(void)
+{
+	platform_driver_unregister(&tx4939_rng_driver);
+}
+
+module_init(tx4939rng_init);
+module_exit(tx4939rng_exit);
+
+MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for TX4939");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/via-rng.c linux-libre-2.6.31-gnu/drivers/char/hw_random/via-rng.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/via-rng.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/via-rng.c	2009-09-09 18:13:59.000000000 -0400
@@ -132,6 +132,19 @@
 	struct cpuinfo_x86 *c = &cpu_data(0);
 	u32 lo, hi, old_lo;
 
+	/* VIA Nano CPUs don't have the MSR_VIA_RNG anymore.  The RNG
+	 * is always enabled if CPUID rng_en is set.  There is no
+	 * RNG configuration like it used to be the case in this
+	 * register */
+	if ((c->x86 == 6) && (c->x86_model >= 0x0f)) {
+		if (!cpu_has_xstore_enabled) {
+			printk(KERN_ERR PFX "can't enable hardware RNG "
+				"if XSTORE is not enabled\n");
+			return -ENODEV;
+		}
+		return 0;
+	}
+
 	/* Control the RNG via MSR.  Tread lightly and pay very close
 	 * close attention to values written, as the reserved fields
 	 * are documented to be "undefined and unpredictable"; but it
@@ -205,5 +218,5 @@
 module_init(mod_init);
 module_exit(mod_exit);
 
-MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets");
+MODULE_DESCRIPTION("H/W RNG driver for VIA CPU with PadLock");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/char/hw_random/virtio-rng.c linux-libre-2.6.31-gnu/drivers/char/hw_random/virtio-rng.c
--- linux-libre-2.6.30-gnu/drivers/char/hw_random/virtio-rng.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/hw_random/virtio-rng.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,13 +35,13 @@
 
 static void random_recv_done(struct virtqueue *vq)
 {
-	int len;
+	unsigned int len;
 
 	/* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
 	if (!vq->vq_ops->get_buf(vq, &len))
 		return;
 
-	data_left = len / sizeof(random_data[0]);
+	data_left += len;
 	complete(&have_data);
 }
 
@@ -49,7 +49,7 @@
 {
 	struct scatterlist sg;
 
-	sg_init_one(&sg, random_data, RANDOM_DATA_SIZE);
+	sg_init_one(&sg, random_data+data_left, RANDOM_DATA_SIZE-data_left);
 	/* There should always be room for one buffer. */
 	if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0)
 		BUG();
@@ -59,24 +59,32 @@
 /* At least we don't udelay() in a loop like some other drivers. */
 static int virtio_data_present(struct hwrng *rng, int wait)
 {
-	if (data_left)
+	if (data_left >= sizeof(u32))
 		return 1;
 
+again:
 	if (!wait)
 		return 0;
 
 	wait_for_completion(&have_data);
+
+	/* Not enough?  Re-register. */
+	if (unlikely(data_left < sizeof(u32))) {
+		register_buffer();
+		goto again;
+	}
+
 	return 1;
 }
 
 /* virtio_data_present() must have succeeded before this is called. */
 static int virtio_data_read(struct hwrng *rng, u32 *data)
 {
-	BUG_ON(!data_left);
-
-	*data = random_data[--data_left];
+	BUG_ON(data_left < sizeof(u32));
+	data_left -= sizeof(u32);
+	*data = random_data[data_left / 4];
 
-	if (!data_left) {
+	if (data_left < sizeof(u32)) {
 		init_completion(&have_data);
 		register_buffer();
 	}
@@ -94,13 +102,13 @@
 	int err;
 
 	/* We expect a single virtqueue. */
-	vq = vdev->config->find_vq(vdev, 0, random_recv_done);
+	vq = virtio_find_single_vq(vdev, random_recv_done, "input");
 	if (IS_ERR(vq))
 		return PTR_ERR(vq);
 
 	err = hwrng_register(&virtio_hwrng);
 	if (err) {
-		vdev->config->del_vq(vq);
+		vdev->config->del_vqs(vdev);
 		return err;
 	}
 
@@ -112,7 +120,7 @@
 {
 	vdev->config->reset(vdev);
 	hwrng_unregister(&virtio_hwrng);
-	vdev->config->del_vq(vq);
+	vdev->config->del_vqs(vdev);
 }
 
 static struct virtio_device_id id_table[] = {
diff -druN linux-libre-2.6.30-gnu/drivers/char/ip2/i2lib.c linux-libre-2.6.31-gnu/drivers/char/ip2/i2lib.c
--- linux-libre-2.6.30-gnu/drivers/char/ip2/i2lib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/ip2/i2lib.c	2009-09-09 18:13:59.000000000 -0400
@@ -868,11 +868,11 @@
 		amountToMove = count;
 	}
 	// Move the first block
-	pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY,
+	pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
 		 &(pCh->Ibuf[stripIndex]), NULL, amountToMove );
 	// If we needed to wrap, do the second data move
 	if (count > amountToMove) {
-		pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY,
+		pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
 		 pCh->Ibuf, NULL, count - amountToMove );
 	}
 	// Bump and wrap the stripIndex all at once by the amount of data read. This
diff -druN linux-libre-2.6.30-gnu/drivers/char/ip2/ip2main.c linux-libre-2.6.31-gnu/drivers/char/ip2/ip2main.c
--- linux-libre-2.6.30-gnu/drivers/char/ip2/ip2main.c	2012-03-22 19:11:11.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/ip2/ip2main.c	2012-03-22 20:07:36.000000000 -0400
@@ -1315,8 +1315,8 @@
 	if (tty->pgrp)
 		kill_pgrp(tty->pgrp, sig, 1);
 	if (flush || !L_NOFLSH(tty)) {
-		if ( tty->ldisc.ops->flush_buffer )  
-			tty->ldisc.ops->flush_buffer(tty);
+		if ( tty->ldisc->ops->flush_buffer )  
+			tty->ldisc->ops->flush_buffer(tty);
 		i2InputFlush( tty->driver_data );
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/ipmi/ipmi_si_intf.c linux-libre-2.6.31-gnu/drivers/char/ipmi/ipmi_si_intf.c
--- linux-libre-2.6.30-gnu/drivers/char/ipmi/ipmi_si_intf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/ipmi/ipmi_si_intf.c	2009-09-09 18:13:59.000000000 -0400
@@ -2375,14 +2375,14 @@
 		info->io.addr_data, info->io.regsize, info->io.regspacing,
 		info->irq);
 
-	dev->dev.driver_data = (void *) info;
+	dev_set_drvdata(&dev->dev, info);
 
 	return try_smi_init(info);
 }
 
 static int __devexit ipmi_of_remove(struct of_device *dev)
 {
-	cleanup_one_si(dev->dev.driver_data);
+	cleanup_one_si(dev_get_drvdata(&dev->dev));
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/isicom.c linux-libre-2.6.31-gnu/drivers/char/isicom.c
--- linux-libre-2.6.30-gnu/drivers/char/isicom.c	2012-03-22 19:11:21.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/isicom.c	2012-03-22 20:07:45.000000000 -0400
@@ -122,6 +122,7 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
@@ -329,7 +330,7 @@
 
 /* card->lock MUST NOT be held */
 
-static void isicom_raise_dtr_rts(struct tty_port *port)
+static void isicom_dtr_rts(struct tty_port *port, int on)
 {
 	struct isi_port *ip = container_of(port, struct isi_port, port);
 	struct isi_board *card = ip->card;
@@ -339,10 +340,17 @@
 	if (!lock_card(card))
 		return;
 
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0f04, base);
-	InterruptTheCard(base);
-	ip->status |= (ISI_DTR | ISI_RTS);
+	if (on) {
+		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+		outw(0x0f04, base);
+		InterruptTheCard(base);
+		ip->status |= (ISI_DTR | ISI_RTS);
+	} else {
+		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+		outw(0x0C04, base);
+		InterruptTheCard(base);
+		ip->status &= ~(ISI_DTR | ISI_RTS);
+	}
 	unlock_card(card);
 }
 
@@ -1339,7 +1347,7 @@
 
 static const struct tty_port_operations isicom_port_ops = {
 	.carrier_raised		= isicom_carrier_raised,
-	.raise_dtr_rts		= isicom_raise_dtr_rts,
+	.dtr_rts		= isicom_dtr_rts,
 };
 
 static int __devinit reset_card(struct pci_dev *pdev,
@@ -1471,10 +1479,10 @@
 		status = inw(base + 0x4);
 		if (status != 0) {
 			dev_warn(&pdev->dev, "Card%d rejected load header:\n"
-				KERN_WARNING "Address:0x%x\n"
-				KERN_WARNING "Count:0x%x\n"
-				KERN_WARNING "Status:0x%x\n",
-				index + 1, frame->addr, frame->count, status);
+				 "Address:0x%x\n"
+				 "Count:0x%x\n"
+				 "Status:0x%x\n",
+				 index + 1, frame->addr, frame->count, status);
 			goto errrelfw;
 		}
 		outsw(base, frame->data, word_count);
@@ -1519,10 +1527,10 @@
 		status = inw(base + 0x4);
 		if (status != 0) {
 			dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
-				KERN_WARNING "Address:0x%x\n"
-				KERN_WARNING "Count:0x%x\n"
-				KERN_WARNING "Status: 0x%x\n",
-				index + 1, frame->addr, frame->count, status);
+				 "Address:0x%x\n"
+				 "Count:0x%x\n"
+				 "Status: 0x%x\n",
+				 index + 1, frame->addr, frame->count, status);
 			goto errrelfw;
 		}
 
@@ -1586,7 +1594,7 @@
 static int __devinit isicom_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
-	unsigned int signature, index;
+	unsigned int uninitialized_var(signature), index;
 	int retval = -EPERM;
 	struct isi_board *board = NULL;
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/istallion.c linux-libre-2.6.31-gnu/drivers/char/istallion.c
--- linux-libre-2.6.30-gnu/drivers/char/istallion.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/istallion.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -1140,14 +1141,14 @@
 	return (portp->sigs & TIOCM_CD) ? 1 : 0;
 }
 
-static void stli_raise_dtr_rts(struct tty_port *port)
+static void stli_dtr_rts(struct tty_port *port, int on)
 {
 	struct stliport *portp = container_of(port, struct stliport, port);
 	struct stlibrd *brdp = stli_brds[portp->brdnr];
-	stli_mkasysigs(&portp->asig, 1, 1);
+	stli_mkasysigs(&portp->asig, on, on);
 	if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 		sizeof(asysigs_t), 0) < 0)
-			printk(KERN_WARNING "istallion: dtr raise failed.\n");
+			printk(KERN_WARNING "istallion: dtr set failed.\n");
 }
 
 
@@ -3785,7 +3786,7 @@
 	return retval;
 }
 
-static void stli_pciremove(struct pci_dev *pdev)
+static void __devexit stli_pciremove(struct pci_dev *pdev)
 {
 	struct stlibrd *brdp = pci_get_drvdata(pdev);
 
@@ -4417,7 +4418,7 @@
 
 static const struct tty_port_operations stli_port_ops = {
 	.carrier_raised = stli_carrier_raised,
-	.raise_dtr_rts = stli_raise_dtr_rts,
+	.dtr_rts = stli_dtr_rts,
 };
 
 /*****************************************************************************/
diff -druN linux-libre-2.6.30-gnu/drivers/char/Kconfig linux-libre-2.6.31-gnu/drivers/char/Kconfig
--- linux-libre-2.6.30-gnu/drivers/char/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -97,6 +97,19 @@
 	  kind of kernel debugging operations.
 	  When in doubt, say "N".
 
+config BFIN_JTAG_COMM
+	tristate "Blackfin JTAG Communication"
+	depends on BLACKFIN
+	help
+	  Add support for emulating a TTY device over the Blackfin JTAG.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bfin_jtag_comm.
+
+config BFIN_JTAG_COMM_CONSOLE
+	bool "Console on Blackfin JTAG"
+	depends on BFIN_JTAG_COMM=y
+
 config SERIAL_NONSTANDARD
 	bool "Non-standard serial port support"
 	depends on HAS_IOMEM
@@ -679,7 +692,7 @@
 	  this driver.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called hvcs.ko.  Additionally, this module
+	  module will be called hvcs.  Additionally, this module
 	  will depend on arch specific APIs exported from hvcserver.ko
 	  which will also be compiled when this driver is built as a
 	  module.
@@ -794,7 +807,7 @@
 config RTC
 	tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
 	depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \
-			&& !ARM && !SUPERH && !S390 && !AVR32
+			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN
 	---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
@@ -893,7 +906,7 @@
 
 config XILINX_HWICAP
 	tristate "Xilinx HWICAP Support"
-	depends on XILINX_VIRTEX
+	depends on XILINX_VIRTEX || MICROBLAZE
 	help
 	  This option enables support for Xilinx Internal Configuration
 	  Access Port (ICAP) driver.  The ICAP is used on Xilinx Virtex
@@ -1016,10 +1029,6 @@
 
 	  If compiled as a module, it will be called cs5535_gpio.
 
-config GPIO_VR41XX
-	tristate "NEC VR4100 series General-purpose I/O Unit support"
-	depends on CPU_VR41XX
-
 config RAW_DRIVER
 	tristate "RAW driver (/dev/raw/rawN)"
 	depends on BLOCK
diff -druN linux-libre-2.6.30-gnu/drivers/char/keyboard.c linux-libre-2.6.31-gnu/drivers/char/keyboard.c
--- linux-libre-2.6.30-gnu/drivers/char/keyboard.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/keyboard.c	2009-09-09 18:13:59.000000000 -0400
@@ -1123,8 +1123,6 @@
 
 #define HW_RAW(dev)	0
 
-#warning "Cannot generate rawmode keyboard for your architecture yet."
-
 static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
 {
 	if (keycode > 127)
diff -druN linux-libre-2.6.30-gnu/drivers/char/Makefile linux-libre-2.6.31-gnu/drivers/char/Makefile
--- linux-libre-2.6.30-gnu/drivers/char/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
 obj-y				+= misc.o
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o selection.o keyboard.o
+obj-$(CONFIG_BFIN_JTAG_COMM)	+= bfin_jtag_comm.o
 obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
 obj-$(CONFIG_HW_CONSOLE)	+= vt.o defkeymap.o
 obj-$(CONFIG_AUDIT)		+= tty_audit.o
@@ -94,7 +95,6 @@
 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
 obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio.o
-obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o
 obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o
 obj-$(CONFIG_TELCLOCK)		+= tlclk.o
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/mem.c linux-libre-2.6.31-gnu/drivers/char/mem.c
--- linux-libre-2.6.30-gnu/drivers/char/mem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/mem.c	2009-09-09 18:13:59.000000000 -0400
@@ -694,9 +694,8 @@
 		written += chunk - unwritten;
 		if (unwritten)
 			break;
-		/* Consider changing this to just 'signal_pending()' with lots of testing */
-		if (fatal_signal_pending(current))
-			return written ? written : -EINTR;
+		if (signal_pending(current))
+			return written ? written : -ERESTARTSYS;
 		buf += chunk;
 		count -= chunk;
 		cond_resched();
@@ -864,59 +863,58 @@
 	.write =	kmsg_write,
 };
 
-static int memory_open(struct inode * inode, struct file * filp)
-{
-	int ret = 0;
-
-	lock_kernel();
-	switch (iminor(inode)) {
-		case 1:
-			filp->f_op = &mem_fops;
-			filp->f_mapping->backing_dev_info =
-				&directly_mappable_cdev_bdi;
-			break;
+static const struct {
+	unsigned int		minor;
+	char			*name;
+	umode_t			mode;
+	const struct file_operations	*fops;
+	struct backing_dev_info	*dev_info;
+} devlist[] = { /* list of minor devices */
+	{1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops,
+		&directly_mappable_cdev_bdi},
 #ifdef CONFIG_DEVKMEM
-		case 2:
-			filp->f_op = &kmem_fops;
-			filp->f_mapping->backing_dev_info =
-				&directly_mappable_cdev_bdi;
-			break;
+	{2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops,
+		&directly_mappable_cdev_bdi},
 #endif
-		case 3:
-			filp->f_op = &null_fops;
-			break;
+	{3, "null",    S_IRUGO | S_IWUGO,           &null_fops, NULL},
 #ifdef CONFIG_DEVPORT
-		case 4:
-			filp->f_op = &port_fops;
-			break;
+	{4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops, NULL},
 #endif
-		case 5:
-			filp->f_mapping->backing_dev_info = &zero_bdi;
-			filp->f_op = &zero_fops;
-			break;
-		case 7:
-			filp->f_op = &full_fops;
-			break;
-		case 8:
-			filp->f_op = &random_fops;
-			break;
-		case 9:
-			filp->f_op = &urandom_fops;
-			break;
-		case 11:
-			filp->f_op = &kmsg_fops;
-			break;
+	{5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops, &zero_bdi},
+	{7, "full",    S_IRUGO | S_IWUGO,           &full_fops, NULL},
+	{8, "random",  S_IRUGO | S_IWUSR,           &random_fops, NULL},
+	{9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops, NULL},
+	{11,"kmsg",    S_IRUGO | S_IWUSR,           &kmsg_fops, NULL},
 #ifdef CONFIG_CRASH_DUMP
-		case 12:
-			filp->f_op = &oldmem_fops;
-			break;
+	{12,"oldmem",    S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops, NULL},
 #endif
-		default:
-			unlock_kernel();
-			return -ENXIO;
+};
+
+static int memory_open(struct inode *inode, struct file *filp)
+{
+	int ret = 0;
+	int i;
+
+	lock_kernel();
+
+	for (i = 0; i < ARRAY_SIZE(devlist); i++) {
+		if (devlist[i].minor == iminor(inode)) {
+			filp->f_op = devlist[i].fops;
+			if (devlist[i].dev_info) {
+				filp->f_mapping->backing_dev_info =
+					devlist[i].dev_info;
+			}
+
+			break;
+		}
 	}
-	if (filp->f_op && filp->f_op->open)
-		ret = filp->f_op->open(inode,filp);
+
+	if (i == ARRAY_SIZE(devlist))
+		ret = -ENXIO;
+	else
+		if (filp->f_op && filp->f_op->open)
+			ret = filp->f_op->open(inode, filp);
+
 	unlock_kernel();
 	return ret;
 }
@@ -925,30 +923,6 @@
 	.open		= memory_open,	/* just a selector for the real open */
 };
 
-static const struct {
-	unsigned int		minor;
-	char			*name;
-	umode_t			mode;
-	const struct file_operations	*fops;
-} devlist[] = { /* list of minor devices */
-	{1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
-#ifdef CONFIG_DEVKMEM
-	{2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
-#endif
-	{3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
-#ifdef CONFIG_DEVPORT
-	{4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
-#endif
-	{5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
-	{7, "full",    S_IRUGO | S_IWUGO,           &full_fops},
-	{8, "random",  S_IRUGO | S_IWUSR,           &random_fops},
-	{9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops},
-	{11,"kmsg",    S_IRUGO | S_IWUSR,           &kmsg_fops},
-#ifdef CONFIG_CRASH_DUMP
-	{12,"oldmem",    S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
-#endif
-};
-
 static struct class *mem_class;
 
 static int __init chr_dev_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/char/misc.c linux-libre-2.6.31-gnu/drivers/char/misc.c
--- linux-libre-2.6.30-gnu/drivers/char/misc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/misc.c	2009-09-09 18:13:59.000000000 -0400
@@ -168,7 +168,6 @@
 	.open		= misc_open,
 };
 
-
 /**
  *	misc_register	-	register a miscellaneous device
  *	@misc: device structure
@@ -217,8 +216,8 @@
 		misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
 	dev = MKDEV(MISC_MAJOR, misc->minor);
 
-	misc->this_device = device_create(misc_class, misc->parent, dev, NULL,
-					  "%s", misc->name);
+	misc->this_device = device_create(misc_class, misc->parent, dev,
+					  misc, "%s", misc->name);
 	if (IS_ERR(misc->this_device)) {
 		err = PTR_ERR(misc->this_device);
 		goto out;
@@ -264,6 +263,15 @@
 EXPORT_SYMBOL(misc_register);
 EXPORT_SYMBOL(misc_deregister);
 
+static char *misc_nodename(struct device *dev)
+{
+	struct miscdevice *c = dev_get_drvdata(dev);
+
+	if (c->devnode)
+		return kstrdup(c->devnode, GFP_KERNEL);
+	return NULL;
+}
+
 static int __init misc_init(void)
 {
 	int err;
@@ -279,6 +287,7 @@
 	err = -EIO;
 	if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
 		goto fail_printk;
+	misc_class->nodename = misc_nodename;
 	return 0;
 
 fail_printk:
diff -druN linux-libre-2.6.30-gnu/drivers/char/moxa.c linux-libre-2.6.31-gnu/drivers/char/moxa.c
--- linux-libre-2.6.30-gnu/drivers/char/moxa.c	2012-03-22 19:11:24.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/moxa.c	2012-03-22 20:07:48.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/major.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
@@ -1183,6 +1184,11 @@
 		mutex_unlock(&moxa_openlock);
 		return -ENODEV;
 	}
+
+	if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) {
+		mutex_unlock(&moxa_openlock);
+		return -ENODEV;
+	}
 
 	ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
 	ch->port.count++;
diff -druN linux-libre-2.6.30-gnu/drivers/char/mxser.c linux-libre-2.6.31-gnu/drivers/char/mxser.c
--- linux-libre-2.6.30-gnu/drivers/char/mxser.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/mxser.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
@@ -547,14 +548,18 @@
 	return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
 }
 
-static void mxser_raise_dtr_rts(struct tty_port *port)
+static void mxser_dtr_rts(struct tty_port *port, int on)
 {
 	struct mxser_port *mp = container_of(port, struct mxser_port, port);
 	unsigned long flags;
 
 	spin_lock_irqsave(&mp->slock, flags);
-	outb(inb(mp->ioaddr + UART_MCR) |
-		UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+	if (on)
+		outb(inb(mp->ioaddr + UART_MCR) |
+			UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+	else
+		outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS),
+			mp->ioaddr + UART_MCR);
 	spin_unlock_irqrestore(&mp->slock, flags);
 }
 
@@ -1044,8 +1049,6 @@
 	if (retval)
 		return retval;
 
-	/* unmark here for very high baud rate (ex. 921600 bps) used */
-	tty->low_latency = 1;
 	return 0;
 }
 
@@ -2356,7 +2359,7 @@
 
 struct tty_port_operations mxser_port_ops = {
 	.carrier_raised = mxser_carrier_raised,
-	.raise_dtr_rts = mxser_raise_dtr_rts,
+	.dtr_rts = mxser_dtr_rts,
 };
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/char/n_hdlc.c linux-libre-2.6.31-gnu/drivers/char/n_hdlc.c
--- linux-libre-2.6.30-gnu/drivers/char/n_hdlc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/n_hdlc.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,6 @@
  *	Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
  *
  * Original release 01/11/99
- * $Id: n_hdlc.c,v 4.8 2003/05/06 21:18:51 paulkf Exp $
  *
  * This code is released under the GNU General Public License (GPL)
  *
@@ -79,7 +78,6 @@
  */
 
 #define HDLC_MAGIC 0x239e
-#define HDLC_VERSION "$Revision: 4.8 $"
 
 #include <linux/module.h>
 #include <linux/init.h>
@@ -99,6 +97,7 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>	/* used in new tty drivers */
 #include <linux/signal.h>	/* used in new tty drivers */
 #include <linux/if.h>
@@ -114,7 +113,7 @@
 #define MAX_HDLC_FRAME_SIZE 65535 
 #define DEFAULT_RX_BUF_COUNT 10
 #define MAX_RX_BUF_COUNT 60
-#define DEFAULT_TX_BUF_COUNT 1
+#define DEFAULT_TX_BUF_COUNT 3
 
 struct n_hdlc_buf {
 	struct n_hdlc_buf *link;
@@ -199,6 +198,31 @@
 #define tty2n_hdlc(tty)	((struct n_hdlc *) ((tty)->disc_data))
 #define n_hdlc2tty(n_hdlc)	((n_hdlc)->tty)
 
+static void flush_rx_queue(struct tty_struct *tty)
+{
+	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
+	struct n_hdlc_buf *buf;
+
+	while ((buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list)))
+		n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, buf);
+}
+
+static void flush_tx_queue(struct tty_struct *tty)
+{
+	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
+	struct n_hdlc_buf *buf;
+	unsigned long flags;
+
+	while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list)))
+		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf);
+ 	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
+	if (n_hdlc->tbuf) {
+		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf);
+		n_hdlc->tbuf = NULL;
+	}
+	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
+}
+
 static struct tty_ldisc_ops n_hdlc_ldisc = {
 	.owner		= THIS_MODULE,
 	.magic		= TTY_LDISC_MAGIC,
@@ -211,6 +235,7 @@
 	.poll		= n_hdlc_tty_poll,
 	.receive_buf	= n_hdlc_tty_receive,
 	.write_wakeup	= n_hdlc_tty_wakeup,
+	.flush_buffer   = flush_rx_queue,
 };
 
 /**
@@ -341,10 +366,7 @@
 	set_bit(TTY_NO_WRITE_SPLIT,&tty->flags);
 #endif
 	
-	/* Flush any pending characters in the driver and discipline. */
-	if (tty->ldisc.ops->flush_buffer)
-		tty->ldisc.ops->flush_buffer(tty);
-
+	/* flush receive data from driver */
 	tty_driver_flush_buffer(tty);
 		
 	if (debuglevel >= DEBUG_LEVEL_INFO)	
@@ -763,6 +785,14 @@
 		error = put_user(count, (int __user *)arg);
 		break;
 
+	case TCFLSH:
+		switch (arg) {
+		case TCIOFLUSH:
+		case TCOFLUSH:
+			flush_tx_queue(tty);
+		}
+		/* fall through to default */
+
 	default:
 		error = n_tty_ioctl_helper(tty, file, cmd, arg);
 		break;
@@ -919,8 +949,7 @@
 }	/* end of n_hdlc_buf_get() */
 
 static char hdlc_banner[] __initdata =
-	KERN_INFO "HDLC line discipline: version " HDLC_VERSION
-	", maxframe=%u\n";
+	KERN_INFO "HDLC line discipline maxframe=%u\n";
 static char hdlc_register_ok[] __initdata =
 	KERN_INFO "N_HDLC line discipline registered.\n";
 static char hdlc_register_fail[] __initdata =
diff -druN linux-libre-2.6.30-gnu/drivers/char/nozomi.c linux-libre-2.6.31-gnu/drivers/char/nozomi.c
--- linux-libre-2.6.30-gnu/drivers/char/nozomi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/nozomi.c	2009-09-09 18:13:59.000000000 -0400
@@ -828,7 +828,7 @@
 	struct port *port = &dc->port[index];
 	void __iomem *addr = port->dl_addr[port->toggle_dl];
 	struct tty_struct *tty = tty_port_tty_get(&port->port);
-	int i;
+	int i, ret;
 
 	if (unlikely(!tty)) {
 		DBG1("tty not open for port: %d?", index);
@@ -844,12 +844,14 @@
 
 		/* disable interrupt in downlink... */
 		disable_transmit_dl(index, dc);
-		return 0;
+		ret = 0;
+		goto put;
 	}
 
 	if (unlikely(size == 0)) {
 		dev_err(&dc->pdev->dev, "size == 0?\n");
-		return 1;
+		ret = 1;
+		goto put;
 	}
 
 	tty_buffer_request_room(tty, size);
@@ -871,8 +873,10 @@
 	}
 
 	set_bit(index, &dc->flip);
+	ret = 1;
+put:
 	tty_kref_put(tty);
-	return 1;
+	return ret;
 }
 
 /* Debug for interrupts */
@@ -1591,8 +1595,6 @@
 
 	/* Enable interrupt downlink for channel */
 	if (port->port.count == 1) {
-		/* FIXME: is this needed now ? */
-		tty->low_latency = 1;
 		tty->driver_data = port;
 		tty_port_tty_set(&port->port, tty);
 		DBG1("open: %d", port->token_dl);
@@ -1864,16 +1866,14 @@
 {
 	struct port *port = tty->driver_data;
 	struct nozomi *dc = get_dc_by_tty(tty);
-	s32 rval;
+	s32 rval = 0;
 
 	if (unlikely(!dc || !port)) {
-		rval = -ENODEV;
 		goto exit_in_buffer;
 	}
 
 	if (unlikely(!port->port.count)) {
 		dev_err(&dc->pdev->dev, "No tty open?\n");
-		rval = -ENODEV;
 		goto exit_in_buffer;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/n_r3964.c linux-libre-2.6.31-gnu/drivers/char/n_r3964.c
--- linux-libre-2.6.30-gnu/drivers/char/n_r3964.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/n_r3964.c	2009-09-09 18:13:59.000000000 -0400
@@ -58,6 +58,7 @@
 #include <linux/ioport.h>
 #include <linux/in.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/string.h>	/* used in new tty drivers */
@@ -1062,7 +1063,7 @@
 	struct r3964_client_info *pClient;
 	struct r3964_message *pMsg;
 	struct r3964_client_message theMsg;
-	int count;
+	int ret;
 
 	TRACE_L("read()");
 
@@ -1074,8 +1075,8 @@
 		if (pMsg == NULL) {
 			/* no messages available. */
 			if (file->f_flags & O_NONBLOCK) {
-				unlock_kernel();
-				return -EAGAIN;
+				ret = -EAGAIN;
+				goto unlock;
 			}
 			/* block until there is a message: */
 			wait_event_interruptible(pInfo->read_wait,
@@ -1085,29 +1086,31 @@
 		/* If we still haven't got a message, we must have been signalled */
 
 		if (!pMsg) {
-			unlock_kernel();
-			return -EINTR;
+			ret = -EINTR;
+			goto unlock;
 		}
 
 		/* deliver msg to client process: */
 		theMsg.msg_id = pMsg->msg_id;
 		theMsg.arg = pMsg->arg;
 		theMsg.error_code = pMsg->error_code;
-		count = sizeof(struct r3964_client_message);
+		ret = sizeof(struct r3964_client_message);
 
 		kfree(pMsg);
 		TRACE_M("r3964_read - msg kfree %p", pMsg);
 
-		if (copy_to_user(buf, &theMsg, count)) {
-			unlock_kernel();
-			return -EFAULT;
+		if (copy_to_user(buf, &theMsg, ret)) {
+			ret = -EFAULT;
+			goto unlock;
 		}
 
-		TRACE_PS("read - return %d", count);
-		return count;
+		TRACE_PS("read - return %d", ret);
+		goto unlock;
 	}
+	ret = -EPERM;
+unlock:
 	unlock_kernel();
-	return -EPERM;
+	return ret;
 }
 
 static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
diff -druN linux-libre-2.6.30-gnu/drivers/char/n_tty.c linux-libre-2.6.31-gnu/drivers/char/n_tty.c
--- linux-libre-2.6.30-gnu/drivers/char/n_tty.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/n_tty.c	2009-09-09 18:13:59.000000000 -0400
@@ -73,24 +73,6 @@
 #define ECHO_OP_SET_CANON_COL 0x81
 #define ECHO_OP_ERASE_TAB 0x82
 
-static inline unsigned char *alloc_buf(void)
-{
-	gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
-
-	if (PAGE_SIZE != N_TTY_BUF_SIZE)
-		return kmalloc(N_TTY_BUF_SIZE, prio);
-	else
-		return (unsigned char *)__get_free_page(prio);
-}
-
-static inline void free_buf(unsigned char *buf)
-{
-	if (PAGE_SIZE != N_TTY_BUF_SIZE)
-		kfree(buf);
-	else
-		free_page((unsigned long) buf);
-}
-
 static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 			       unsigned char __user *ptr)
 {
@@ -318,8 +300,7 @@
 			if (space < 2)
 				return -1;
 			tty->canon_column = tty->column = 0;
-			tty_put_char(tty, '\r');
-			tty_put_char(tty, c);
+			tty->ops->write(tty, "\r\n", 2);
 			return 2;
 		}
 		tty->canon_column = tty->column;
@@ -1349,9 +1330,6 @@
 
 static void n_tty_write_wakeup(struct tty_struct *tty)
 {
-	/* Write out any echoed characters that are still pending */
-	process_echoes(tty);
-
 	if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
 		kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
 }
@@ -1558,11 +1536,11 @@
 {
 	n_tty_flush_buffer(tty);
 	if (tty->read_buf) {
-		free_buf(tty->read_buf);
+		kfree(tty->read_buf);
 		tty->read_buf = NULL;
 	}
 	if (tty->echo_buf) {
-		free_buf(tty->echo_buf);
+		kfree(tty->echo_buf);
 		tty->echo_buf = NULL;
 	}
 }
@@ -1584,17 +1562,16 @@
 
 	/* These are ugly. Currently a malloc failure here can panic */
 	if (!tty->read_buf) {
-		tty->read_buf = alloc_buf();
+		tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
 		if (!tty->read_buf)
 			return -ENOMEM;
 	}
 	if (!tty->echo_buf) {
-		tty->echo_buf = alloc_buf();
+		tty->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+
 		if (!tty->echo_buf)
 			return -ENOMEM;
 	}
-	memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
-	memset(tty->echo_buf, 0, N_TTY_BUF_SIZE);
 	reset_buffer_flags(tty);
 	tty->column = 0;
 	n_tty_set_termios(tty, NULL);
@@ -1605,6 +1582,7 @@
 
 static inline int input_available_p(struct tty_struct *tty, int amt)
 {
+	tty_flush_to_ldisc(tty);
 	if (tty->icanon) {
 		if (tty->canon_data)
 			return 1;
diff -druN linux-libre-2.6.30-gnu/drivers/char/pcmcia/cm4000_cs.c linux-libre-2.6.31-gnu/drivers/char/pcmcia/cm4000_cs.c
--- linux-libre-2.6.30-gnu/drivers/char/pcmcia/cm4000_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/pcmcia/cm4000_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -1575,7 +1575,8 @@
 		clear_bit(LOCK_IO, &dev->flags);
 		wake_up_interruptible(&dev->ioq);
 
-		return 0;
+		rc = 0;
+		break;
 	case CM_IOCSPTS:
 		{
 			struct ptsreq krnptsreq;
diff -druN linux-libre-2.6.30-gnu/drivers/char/pcmcia/ipwireless/tty.c linux-libre-2.6.31-gnu/drivers/char/pcmcia/ipwireless/tty.c
--- linux-libre-2.6.30-gnu/drivers/char/pcmcia/ipwireless/tty.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/pcmcia/ipwireless/tty.c	2009-09-09 18:13:59.000000000 -0400
@@ -320,10 +320,10 @@
 	struct ipw_tty *tty = linux_tty->driver_data;
 
 	if (!tty)
-		return -ENODEV;
+		return 0;
 
 	if (!tty->open_count)
-		return -EINVAL;
+		return 0;
 
 	return tty->tx_bytes_queued;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/pcmcia/synclink_cs.c linux-libre-2.6.31-gnu/drivers/char/pcmcia/synclink_cs.c
--- linux-libre-2.6.30-gnu/drivers/char/pcmcia/synclink_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/pcmcia/synclink_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -383,7 +383,7 @@
 static void tx_timeout(unsigned long context);
 
 static int carrier_raised(struct tty_port *port);
-static void raise_dtr_rts(struct tty_port *port);
+static void dtr_rts(struct tty_port *port, int onoff);
 
 #if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -513,7 +513,7 @@
 
 static const struct tty_port_operations mgslpc_port_ops = {
 	.carrier_raised = carrier_raised,
-	.raise_dtr_rts = raise_dtr_rts
+	.dtr_rts = dtr_rts
 };
 
 static int mgslpc_probe(struct pcmcia_device *link)
@@ -2528,13 +2528,16 @@
 	return 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int onoff)
 {
 	MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);
 	unsigned long flags;
 
 	spin_lock_irqsave(&info->lock,flags);
-	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	if (onoff)
+		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR;
 	set_signals(info);
 	spin_unlock_irqrestore(&info->lock,flags);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/ppdev.c linux-libre-2.6.31-gnu/drivers/char/ppdev.c
--- linux-libre-2.6.30-gnu/drivers/char/ppdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/ppdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -114,8 +114,7 @@
 
 	if (!(pp->flags & PP_CLAIMED)) {
 		/* Don't have the port claimed */
-		printk (KERN_DEBUG CHRDEV "%x: claim the port first\n",
-			minor);
+		pr_debug(CHRDEV "%x: claim the port first\n", minor);
 		return -EINVAL;
 	}
 
@@ -198,8 +197,7 @@
 
 	if (!(pp->flags & PP_CLAIMED)) {
 		/* Don't have the port claimed */
-		printk (KERN_DEBUG CHRDEV "%x: claim the port first\n",
-			minor);
+		pr_debug(CHRDEV "%x: claim the port first\n", minor);
 		return -EINVAL;
 	}
 
@@ -313,7 +311,7 @@
 	}
 
 	pp->pdev = pdev;
-	printk (KERN_DEBUG "%s: registered pardevice\n", name);
+	pr_debug("%s: registered pardevice\n", name);
 	return 0;
 }
 
@@ -343,8 +341,7 @@
 		int ret;
 
 		if (pp->flags & PP_CLAIMED) {
-			printk (KERN_DEBUG CHRDEV
-				"%x: you've already got it!\n", minor);
+			pr_debug(CHRDEV "%x: you've already got it!\n", minor);
 			return -EINVAL;
 		}
 
@@ -379,7 +376,7 @@
 	    }
 	case PPEXCL:
 		if (pp->pdev) {
-			printk (KERN_DEBUG CHRDEV "%x: too late for PPEXCL; "
+			pr_debug(CHRDEV "%x: too late for PPEXCL; "
 				"already registered\n", minor);
 			if (pp->flags & PP_EXCL)
 				/* But it's not really an error. */
@@ -491,8 +488,7 @@
 	/* Everything else requires the port to be claimed, so check
 	 * that now. */
 	if ((pp->flags & PP_CLAIMED) == 0) {
-		printk (KERN_DEBUG CHRDEV "%x: claim the port first\n",
-			minor);
+		pr_debug(CHRDEV "%x: claim the port first\n", minor);
 		return -EINVAL;
 	}
 
@@ -624,8 +620,7 @@
 		return 0;
 
 	default:
-		printk (KERN_DEBUG CHRDEV "%x: What? (cmd=0x%x)\n", minor,
-			cmd);
+		pr_debug(CHRDEV "%x: What? (cmd=0x%x)\n", minor, cmd);
 		return -EINVAL;
 	}
 
@@ -698,9 +693,8 @@
 	}
 	if (compat_negot) {
 		parport_negotiate (pp->pdev->port, IEEE1284_MODE_COMPAT);
-		printk (KERN_DEBUG CHRDEV
-			"%x: negotiated back to compatibility mode because "
-			"user-space forgot\n", minor);
+		pr_debug(CHRDEV "%x: negotiated back to compatibility "
+			"mode because user-space forgot\n", minor);
 	}
 
 	if (pp->flags & PP_CLAIMED) {
@@ -713,7 +707,7 @@
 		info->phase = pp->saved_state.phase;
 		parport_release (pp->pdev);
 		if (compat_negot != 1) {
-			printk (KERN_DEBUG CHRDEV "%x: released pardevice "
+			pr_debug(CHRDEV "%x: released pardevice "
 				"because user-space forgot\n", minor);
 		}
 	}
@@ -723,8 +717,7 @@
 		parport_unregister_device (pp->pdev);
 		kfree (name);
 		pp->pdev = NULL;
-		printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n",
-			minor);
+		pr_debug(CHRDEV "%x: unregistered pardevice\n", minor);
 	}
 
 	kfree (pp);
diff -druN linux-libre-2.6.30-gnu/drivers/char/ps3flash.c linux-libre-2.6.31-gnu/drivers/char/ps3flash.c
--- linux-libre-2.6.30-gnu/drivers/char/ps3flash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/ps3flash.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,48 +33,64 @@
 
 struct ps3flash_private {
 	struct mutex mutex;	/* Bounce buffer mutex */
+	u64 chunk_sectors;
+	int tag;		/* Start sector of buffer, -1 if invalid */
+	bool dirty;
 };
 
 static struct ps3_storage_device *ps3flash_dev;
 
-static ssize_t ps3flash_read_write_sectors(struct ps3_storage_device *dev,
-					   u64 lpar, u64 start_sector,
-					   u64 sectors, int write)
+static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,
+				       u64 start_sector, int write)
 {
-	u64 res = ps3stor_read_write_sectors(dev, lpar, start_sector, sectors,
+	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
+	u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar,
+					     start_sector, priv->chunk_sectors,
 					     write);
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
 			__LINE__, write ? "write" : "read", res);
 		return -EIO;
 	}
-	return sectors;
+	return 0;
 }
 
-static ssize_t ps3flash_read_sectors(struct ps3_storage_device *dev,
-				     u64 start_sector, u64 sectors,
-				     unsigned int sector_offset)
+static int ps3flash_writeback(struct ps3_storage_device *dev)
 {
-	u64 max_sectors, lpar;
+	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
+	int res;
 
-	max_sectors = dev->bounce_size / dev->blk_size;
-	if (sectors > max_sectors) {
-		dev_dbg(&dev->sbd.core, "%s:%u Limiting sectors to %llu\n",
-			__func__, __LINE__, max_sectors);
-		sectors = max_sectors;
-	}
+	if (!priv->dirty || priv->tag < 0)
+		return 0;
 
-	lpar = dev->bounce_lpar + sector_offset * dev->blk_size;
-	return ps3flash_read_write_sectors(dev, lpar, start_sector, sectors,
-					   0);
+	res = ps3flash_read_write_sectors(dev, priv->tag, 1);
+	if (res)
+		return res;
+
+	priv->dirty = false;
+	return 0;
 }
 
-static ssize_t ps3flash_write_chunk(struct ps3_storage_device *dev,
-				    u64 start_sector)
+static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
 {
-       u64 sectors = dev->bounce_size / dev->blk_size;
-       return ps3flash_read_write_sectors(dev, dev->bounce_lpar, start_sector,
-					  sectors, 1);
+	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
+	int res;
+
+	if (start_sector == priv->tag)
+		return 0;
+
+	res = ps3flash_writeback(dev);
+	if (res)
+		return res;
+
+	priv->tag = -1;
+
+	res = ps3flash_read_write_sectors(dev, start_sector, 0);
+	if (res)
+		return res;
+
+	priv->tag = start_sector;
+	return 0;
 }
 
 static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
@@ -104,18 +120,19 @@
 	return res;
 }
 
-static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
-			     loff_t *pos)
+static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
+			     size_t count, loff_t *pos)
 {
 	struct ps3_storage_device *dev = ps3flash_dev;
-	struct ps3flash_private *priv = dev->sbd.core.driver_data;
-	u64 size, start_sector, end_sector, offset;
-	ssize_t sectors_read;
+	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
+	u64 size, sector, offset;
+	int res;
 	size_t remaining, n;
+	const void *src;
 
 	dev_dbg(&dev->sbd.core,
-		"%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
-		__func__, __LINE__, count, *pos, buf);
+		"%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",
+		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
 
 	size = dev->regions[dev->region_idx].size*dev->blk_size;
 	if (*pos >= size || !count)
@@ -128,61 +145,63 @@
 		count = size - *pos;
 	}
 
-	start_sector = *pos / dev->blk_size;
-	offset = *pos % dev->blk_size;
-	end_sector = DIV_ROUND_UP(*pos + count, dev->blk_size);
+	sector = *pos / dev->bounce_size * priv->chunk_sectors;
+	offset = *pos % dev->bounce_size;
 
 	remaining = count;
 	do {
+		n = min_t(u64, remaining, dev->bounce_size - offset);
+		src = dev->bounce_buf + offset;
+
 		mutex_lock(&priv->mutex);
 
-		sectors_read = ps3flash_read_sectors(dev, start_sector,
-						     end_sector-start_sector,
-						     0);
-		if (sectors_read < 0) {
-			mutex_unlock(&priv->mutex);
+		res = ps3flash_fetch(dev, sector);
+		if (res)
 			goto fail;
-		}
 
-		n = min_t(u64, remaining, sectors_read*dev->blk_size-offset);
 		dev_dbg(&dev->sbd.core,
-			"%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
-			__func__, __LINE__, n, dev->bounce_buf+offset, buf);
-		if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
-			mutex_unlock(&priv->mutex);
-			sectors_read = -EFAULT;
-			goto fail;
+			"%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n",
+			__func__, __LINE__, n, src, userbuf, kernelbuf);
+		if (userbuf) {
+			if (copy_to_user(userbuf, src, n)) {
+				res = -EFAULT;
+				goto fail;
+			}
+			userbuf += n;
+		}
+		if (kernelbuf) {
+			memcpy(kernelbuf, src, n);
+			kernelbuf += n;
 		}
 
 		mutex_unlock(&priv->mutex);
 
 		*pos += n;
-		buf += n;
 		remaining -= n;
-		start_sector += sectors_read;
+		sector += priv->chunk_sectors;
 		offset = 0;
 	} while (remaining > 0);
 
 	return count;
 
 fail:
-	return sectors_read;
+	mutex_unlock(&priv->mutex);
+	return res;
 }
 
-static ssize_t ps3flash_write(struct file *file, const char __user *buf,
-			      size_t count, loff_t *pos)
+static ssize_t ps3flash_write(const char __user *userbuf,
+			      const void *kernelbuf, size_t count, loff_t *pos)
 {
 	struct ps3_storage_device *dev = ps3flash_dev;
-	struct ps3flash_private *priv = dev->sbd.core.driver_data;
-	u64 size, chunk_sectors, start_write_sector, end_write_sector,
-	    end_read_sector, start_read_sector, head, tail, offset;
-	ssize_t res;
+	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
+	u64 size, sector, offset;
+	int res = 0;
 	size_t remaining, n;
-	unsigned int sec_off;
+	void *dst;
 
 	dev_dbg(&dev->sbd.core,
-		"%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
-		__func__, __LINE__, count, *pos, buf);
+		"%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",
+		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
 
 	size = dev->regions[dev->region_idx].size*dev->blk_size;
 	if (*pos >= size || !count)
@@ -195,89 +214,46 @@
 		count = size - *pos;
 	}
 
-	chunk_sectors = dev->bounce_size / dev->blk_size;
-
-	start_write_sector = *pos / dev->bounce_size * chunk_sectors;
+	sector = *pos / dev->bounce_size * priv->chunk_sectors;
 	offset = *pos % dev->bounce_size;
-	end_write_sector = DIV_ROUND_UP(*pos + count, dev->bounce_size) *
-			   chunk_sectors;
-
-	end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size);
-	start_read_sector = (*pos + count) / dev->blk_size;
-
-	/*
-	 * As we have to write in 256 KiB chunks, while we can read in blk_size
-	 * (usually 512 bytes) chunks, we perform the following steps:
-	 *   1. Read from start_write_sector to end_read_sector ("head")
-	 *   2. Read from start_read_sector to end_write_sector ("tail")
-	 *   3. Copy data to buffer
-	 *   4. Write from start_write_sector to end_write_sector
-	 * All of this is complicated by using only one 256 KiB bounce buffer.
-	 */
-
-	head = end_read_sector - start_write_sector;
-	tail = end_write_sector - start_read_sector;
 
 	remaining = count;
 	do {
+		n = min_t(u64, remaining, dev->bounce_size - offset);
+		dst = dev->bounce_buf + offset;
+
 		mutex_lock(&priv->mutex);
 
-		if (end_read_sector >= start_read_sector) {
-			/* Merge head and tail */
-			dev_dbg(&dev->sbd.core,
-				"Merged head and tail: %llu sectors at %llu\n",
-				chunk_sectors, start_write_sector);
-			res = ps3flash_read_sectors(dev, start_write_sector,
-						    chunk_sectors, 0);
-			if (res < 0)
+		if (n != dev->bounce_size)
+			res = ps3flash_fetch(dev, sector);
+		else if (sector != priv->tag)
+			res = ps3flash_writeback(dev);
+		if (res)
+			goto fail;
+
+		dev_dbg(&dev->sbd.core,
+			"%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n",
+			__func__, __LINE__, n, userbuf, kernelbuf, dst);
+		if (userbuf) {
+			if (copy_from_user(dst, userbuf, n)) {
+				res = -EFAULT;
 				goto fail;
-		} else {
-			if (head) {
-				/* Read head */
-				dev_dbg(&dev->sbd.core,
-					"head: %llu sectors at %llu\n", head,
-					start_write_sector);
-				res = ps3flash_read_sectors(dev,
-							    start_write_sector,
-							    head, 0);
-				if (res < 0)
-					goto fail;
-			}
-			if (start_read_sector <
-			    start_write_sector+chunk_sectors) {
-				/* Read tail */
-				dev_dbg(&dev->sbd.core,
-					"tail: %llu sectors at %llu\n", tail,
-					start_read_sector);
-				sec_off = start_read_sector-start_write_sector;
-				res = ps3flash_read_sectors(dev,
-							    start_read_sector,
-							    tail, sec_off);
-				if (res < 0)
-					goto fail;
 			}
+			userbuf += n;
 		}
-
-		n = min_t(u64, remaining, dev->bounce_size-offset);
-		dev_dbg(&dev->sbd.core,
-			"%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
-			__func__, __LINE__, n, buf, dev->bounce_buf+offset);
-		if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
-			res = -EFAULT;
-			goto fail;
+		if (kernelbuf) {
+			memcpy(dst, kernelbuf, n);
+			kernelbuf += n;
 		}
 
-		res = ps3flash_write_chunk(dev, start_write_sector);
-		if (res < 0)
-			goto fail;
+		priv->tag = sector;
+		priv->dirty = true;
 
 		mutex_unlock(&priv->mutex);
 
 		*pos += n;
-		buf += n;
 		remaining -= n;
-		start_write_sector += chunk_sectors;
-		head = 0;
+		sector += priv->chunk_sectors;
 		offset = 0;
 	} while (remaining > 0);
 
@@ -288,6 +264,51 @@
 	return res;
 }
 
+static ssize_t ps3flash_user_read(struct file *file, char __user *buf,
+				  size_t count, loff_t *pos)
+{
+	return ps3flash_read(buf, NULL, count, pos);
+}
+
+static ssize_t ps3flash_user_write(struct file *file, const char __user *buf,
+				   size_t count, loff_t *pos)
+{
+	return ps3flash_write(buf, NULL, count, pos);
+}
+
+static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos)
+{
+	return ps3flash_read(NULL, buf, count, &pos);
+}
+
+static ssize_t ps3flash_kernel_write(const void *buf, size_t count,
+				     loff_t pos)
+{
+	ssize_t res;
+	int wb;
+
+	res = ps3flash_write(NULL, buf, count, &pos);
+	if (res < 0)
+		return res;
+
+	/* Make kernel writes synchronous */
+	wb = ps3flash_writeback(ps3flash_dev);
+	if (wb)
+		return wb;
+
+	return res;
+}
+
+static int ps3flash_flush(struct file *file, fl_owner_t id)
+{
+	return ps3flash_writeback(ps3flash_dev);
+}
+
+static int ps3flash_fsync(struct file *file, struct dentry *dentry,
+			  int datasync)
+{
+	return ps3flash_writeback(ps3flash_dev);
+}
 
 static irqreturn_t ps3flash_interrupt(int irq, void *data)
 {
@@ -312,12 +333,18 @@
 	return IRQ_HANDLED;
 }
 
-
 static const struct file_operations ps3flash_fops = {
 	.owner	= THIS_MODULE,
 	.llseek	= ps3flash_llseek,
-	.read	= ps3flash_read,
-	.write	= ps3flash_write,
+	.read	= ps3flash_user_read,
+	.write	= ps3flash_user_write,
+	.flush	= ps3flash_flush,
+	.fsync	= ps3flash_fsync,
+};
+
+static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = {
+	.read	= ps3flash_kernel_read,
+	.write	= ps3flash_kernel_write,
 };
 
 static struct miscdevice ps3flash_misc = {
@@ -366,11 +393,13 @@
 		goto fail;
 	}
 
-	dev->sbd.core.driver_data = priv;
+	ps3_system_bus_set_drvdata(&dev->sbd, priv);
 	mutex_init(&priv->mutex);
+	priv->tag = -1;
 
 	dev->bounce_size = ps3flash_bounce_buffer.size;
 	dev->bounce_buf = ps3flash_bounce_buffer.address;
+	priv->chunk_sectors = dev->bounce_size / dev->blk_size;
 
 	error = ps3stor_setup(dev, ps3flash_interrupt);
 	if (error)
@@ -386,13 +415,15 @@
 
 	dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
 		 __func__, __LINE__, ps3flash_misc.minor);
+
+	ps3_os_area_flash_register(&ps3flash_kernel_ops);
 	return 0;
 
 fail_teardown:
 	ps3stor_teardown(dev);
 fail_free_priv:
 	kfree(priv);
-	dev->sbd.core.driver_data = NULL;
+	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
 fail:
 	ps3flash_dev = NULL;
 	return error;
@@ -402,10 +433,11 @@
 {
 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
 
+	ps3_os_area_flash_register(NULL);
 	misc_deregister(&ps3flash_misc);
 	ps3stor_teardown(dev);
-	kfree(dev->sbd.core.driver_data);
-	dev->sbd.core.driver_data = NULL;
+	kfree(ps3_system_bus_get_drvdata(&dev->sbd));
+	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
 	ps3flash_dev = NULL;
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/pty.c linux-libre-2.6.31-gnu/drivers/char/pty.c
--- linux-libre-2.6.30-gnu/drivers/char/pty.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/pty.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/sysctl.h>
 #include <linux/device.h>
 #include <linux/uaccess.h>
@@ -30,7 +31,6 @@
 
 #include <asm/system.h>
 
-/* These are global because they are accessed in tty_io.c */
 #ifdef CONFIG_UNIX98_PTYS
 static struct tty_driver *ptm_driver;
 static struct tty_driver *pts_driver;
@@ -76,94 +76,82 @@
  */
 static void pty_unthrottle(struct tty_struct *tty)
 {
-	struct tty_struct *o_tty = tty->link;
+	tty_wakeup(tty->link);
+	set_bit(TTY_THROTTLED, &tty->flags);
+}
 
-	if (!o_tty)
-		return;
+/**
+ *	pty_space	-	report space left for writing
+ *	@to: tty we are writing into
+ *
+ *	The tty buffers allow 64K but we sneak a peak and clip at 8K this
+ *	allows a lot of overspill room for echo and other fun messes to
+ *	be handled properly
+ */
 
-	tty_wakeup(o_tty);
-	set_bit(TTY_THROTTLED, &tty->flags);
+static int pty_space(struct tty_struct *to)
+{
+	int n = 8192 - to->buf.memory_used;
+	if (n < 0)
+		return 0;
+	return n;
 }
 
-/*
- * WSH 05/24/97: modified to
- *   (1) use space in tty->flip instead of a shared temp buffer
- *	 The flip buffers aren't being used for a pty, so there's lots
- *	 of space available.  The buffer is protected by a per-pty
- *	 semaphore that should almost never come under contention.
- *   (2) avoid redundant copying for cases where count >> receive_room
- * N.B. Calls from user space may now return an error code instead of
- * a count.
+/**
+ *	pty_write		-	write to a pty
+ *	@tty: the tty we write from
+ *	@buf: kernel buffer of data
+ *	@count: bytes to write
  *
- * FIXME: Our pty_write method is called with our ldisc lock held but
- * not our partners. We can't just take the other one blindly without
- * risking deadlocks.
+ *	Our "hardware" write method. Data is coming from the ldisc which
+ *	may be in a non sleeping state. We simply throw this at the other
+ *	end of the link as if we were an IRQ handler receiving stuff for
+ *	the other side of the pty/tty pair.
  */
-static int pty_write(struct tty_struct *tty, const unsigned char *buf,
-								int count)
+
+static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
 {
 	struct tty_struct *to = tty->link;
-	int	c;
 
-	if (!to || tty->stopped)
+	if (tty->stopped)
 		return 0;
 
-	c = to->receive_room;
-	if (c > count)
-		c = count;
-	to->ldisc.ops->receive_buf(to, buf, NULL, c);
-
+	if (c > 0) {
+		/* Stuff the data into the input queue of the other end */
+		c = tty_insert_flip_string(to, buf, c);
+		/* And shovel */
+		tty_flip_buffer_push(to);
+		tty_wakeup(tty);
+	}
 	return c;
 }
 
+/**
+ *	pty_write_room	-	write space
+ *	@tty: tty we are writing from
+ *
+ *	Report how many bytes the ldisc can send into the queue for
+ *	the other device.
+ */
+
 static int pty_write_room(struct tty_struct *tty)
 {
-	struct tty_struct *to = tty->link;
-
-	if (!to || tty->stopped)
+	if (tty->stopped)
 		return 0;
-
-	return to->receive_room;
+	return pty_space(tty->link);
 }
 
-/*
- *	WSH 05/24/97:  Modified for asymmetric MASTER/SLAVE behavior
- *	The chars_in_buffer() value is used by the ldisc select() function
- *	to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
- *	The pty driver chars_in_buffer() Master/Slave must behave differently:
- *
- *      The Master side needs to allow typed-ahead commands to accumulate
- *      while being canonicalized, so we report "our buffer" as empty until
- *	some threshold is reached, and then report the count. (Any count >
- *	WAKEUP_CHARS is regarded by select() as "full".)  To avoid deadlock
- *	the count returned must be 0 if no canonical data is available to be
- *	read. (The N_TTY ldisc.chars_in_buffer now knows this.)
+/**
+ *	pty_chars_in_buffer	-	characters currently in our tx queue
+ *	@tty: our tty
  *
- *	The Slave side passes all characters in raw mode to the Master side's
- *	buffer where they can be read immediately, so in this case we can
- *	return the true count in the buffer.
+ *	Report how much we have in the transmit queue. As everything is
+ *	instantly at the other end this is easy to implement.
  */
+
 static int pty_chars_in_buffer(struct tty_struct *tty)
 {
-	struct tty_struct *to = tty->link;
-	int count;
-
-	/* We should get the line discipline lock for "tty->link" */
-	if (!to || !to->ldisc.ops->chars_in_buffer)
-		return 0;
-
-	/* The ldisc must report 0 if no characters available to be read */
-	count = to->ldisc.ops->chars_in_buffer(to);
-
-	if (tty->driver->subtype == PTY_TYPE_SLAVE)
-		return count;
-
-	/* Master side driver ... if the other side's read buffer is less than
-	 * half full, return 0 to allow writers to proceed; otherwise return
-	 * the count.  This leaves a comfortable margin to avoid overflow,
-	 * and still allows half a buffer's worth of typed-ahead commands.
-	 */
-	return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
+	return 0;
 }
 
 /* Set the lock flag on a pty */
@@ -186,10 +174,7 @@
 
 	if (!to)
 		return;
-
-	if (to->ldisc.ops->flush_buffer)
-		to->ldisc.ops->flush_buffer(to);
-
+	/* tty_buffer_flush(to); FIXME */
 	if (to->packet) {
 		spin_lock_irqsave(&tty->ctrl_lock, flags);
 		tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
diff -druN linux-libre-2.6.30-gnu/drivers/char/raw.c linux-libre-2.6.31-gnu/drivers/char/raw.c
--- linux-libre-2.6.30-gnu/drivers/char/raw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/raw.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,7 +71,7 @@
 	err = bd_claim(bdev, raw_open);
 	if (err)
 		goto out1;
-	err = set_blocksize(bdev, bdev_hardsect_size(bdev));
+	err = set_blocksize(bdev, bdev_logical_block_size(bdev));
 	if (err)
 		goto out2;
 	filp->f_flags |= O_DIRECT;
@@ -261,6 +261,11 @@
 
 static struct cdev raw_cdev;
 
+static char *raw_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "raw/%s", dev_name(dev));
+}
+
 static int __init raw_init(void)
 {
 	dev_t dev = MKDEV(RAW_MAJOR, 0);
@@ -284,6 +289,7 @@
 		ret = PTR_ERR(raw_class);
 		goto error_region;
 	}
+	raw_class->nodename = raw_nodename;
 	device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/char/rio/rio_linux.c linux-libre-2.6.31-gnu/drivers/char/rio/rio_linux.c
--- linux-libre-2.6.30-gnu/drivers/char/rio/rio_linux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/rio/rio_linux.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,6 +44,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/riscom8.c linux-libre-2.6.31-gnu/drivers/char/riscom8.c
--- linux-libre-2.6.30-gnu/drivers/char/riscom8.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/riscom8.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,6 +47,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/tty_flip.h>
+#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/rocket.c linux-libre-2.6.31-gnu/drivers/char/rocket.c
--- linux-libre-2.6.30-gnu/drivers/char/rocket.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/rocket.c	2009-09-09 18:13:59.000000000 -0400
@@ -73,6 +73,7 @@
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
@@ -872,11 +873,16 @@
 	return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
 	struct r_port *info = container_of(port, struct r_port, port);
-	sSetDTR(&info->channel);
-	sSetRTS(&info->channel);
+	if (on) {
+		sSetDTR(&info->channel);
+		sSetRTS(&info->channel);
+	} else {
+		sClrDTR(&info->channel);
+		sClrRTS(&info->channel);
+	}
 }
 
 /*
@@ -934,7 +940,7 @@
 	/*
 	 * Info->count is now 1; so it's safe to sleep now.
 	 */
-	if (!test_bit(ASYNC_INITIALIZED, &port->flags)) {
+	if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
 		cp = &info->channel;
 		sSetRxTrigger(cp, TRIG_1);
 		if (sGetChanStatus(cp) & CD_ACT)
@@ -958,7 +964,7 @@
 		sEnRxFIFO(cp);
 		sEnTransmit(cp);
 
-		set_bit(ASYNC_INITIALIZED, &info->port.flags);
+		set_bit(ASYNCB_INITIALIZED, &info->port.flags);
 
 		/*
 		 * Set up the tty->alt_speed kludge
@@ -1641,7 +1647,7 @@
 	/*  Write remaining data into the port's xmit_buf */
 	while (1) {
 		/* Hung up ? */
-		if (!test_bit(ASYNC_NORMAL_ACTIVE, &info->port.flags))
+		if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags))
 			goto end;
 		c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
 		c = min(c, XMIT_BUF_SIZE - info->xmit_head);
@@ -2250,7 +2256,7 @@
 
 static const struct tty_port_operations rocket_port_ops = {
 	.carrier_raised = carrier_raised,
-	.raise_dtr_rts = raise_dtr_rts,
+	.dtr_rts = dtr_rts,
 };
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/char/selection.c linux-libre-2.6.31-gnu/drivers/char/selection.c
--- linux-libre-2.6.30-gnu/drivers/char/selection.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/selection.c	2009-09-09 18:13:59.000000000 -0400
@@ -327,7 +327,7 @@
 		}
 		count = sel_buffer_lth - pasted;
 		count = min(count, tty->receive_room);
-		tty->ldisc.ops->receive_buf(tty, sel_buffer + pasted,
+		tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
 								NULL, count);
 		pasted += count;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/char/serial167.c linux-libre-2.6.31-gnu/drivers/char/serial167.c
--- linux-libre-2.6.30-gnu/drivers/char/serial167.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/serial167.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,6 +52,7 @@
 #include <linux/interrupt.h>
 #include <linux/serial.h>
 #include <linux/serialP.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
diff -druN linux-libre-2.6.30-gnu/drivers/char/specialix.c linux-libre-2.6.31-gnu/drivers/char/specialix.c
--- linux-libre-2.6.30-gnu/drivers/char/specialix.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/specialix.c	2009-09-09 18:13:59.000000000 -0400
@@ -87,6 +87,7 @@
 #include <linux/tty_flip.h>
 #include <linux/mm.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/fcntl.h>
 #include <linux/major.h>
 #include <linux/delay.h>
@@ -1808,10 +1809,10 @@
 		if (clear & TIOCM_DTR)
 			port->MSVR &= ~MSVR_DTR;
 	}
-	spin_lock_irqsave(&bp->lock, flags);
+	spin_lock(&bp->lock);
 	sx_out(bp, CD186x_CAR, port_No(port));
 	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
+	spin_unlock(&bp->lock);
 	spin_unlock_irqrestore(&port->lock, flags);
 	func_exit();
 	return 0;
@@ -1832,11 +1833,11 @@
 	port->break_length = SPECIALIX_TPS / HZ * length;
 	port->COR2 |= COR2_ETC;
 	port->IER  |= IER_TXRDY;
-	spin_lock_irqsave(&bp->lock, flags);
+	spin_lock(&bp->lock);
 	sx_out(bp, CD186x_CAR, port_No(port));
 	sx_out(bp, CD186x_COR2, port->COR2);
 	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
+	spin_unlock(&bp->lock);
 	spin_unlock_irqrestore(&port->lock, flags);
 	sx_wait_CCR(bp);
 	spin_lock_irqsave(&bp->lock, flags);
@@ -2022,9 +2023,9 @@
 	if (sx_crtscts(tty))
 		port->MSVR |= MSVR_DTR;
 	/* Else clause: see remark in "sx_throttle"... */
-	spin_lock_irqsave(&bp->lock, flags);
+	spin_lock(&bp->lock);
 	sx_out(bp, CD186x_CAR, port_No(port));
-	spin_unlock_irqrestore(&bp->lock, flags);
+	spin_unlock(&bp->lock);
 	if (I_IXOFF(tty)) {
 		spin_unlock_irqrestore(&port->lock, flags);
 		sx_wait_CCR(bp);
@@ -2034,9 +2035,9 @@
 		sx_wait_CCR(bp);
 		spin_lock_irqsave(&port->lock, flags);
 	}
-	spin_lock_irqsave(&bp->lock, flags);
+	spin_lock(&bp->lock);
 	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
+	spin_unlock(&bp->lock);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	func_exit();
@@ -2060,10 +2061,10 @@
 
 	spin_lock_irqsave(&port->lock, flags);
 	port->IER &= ~IER_TXRDY;
-	spin_lock_irqsave(&bp->lock, flags);
+	spin_lock(&bp->lock);
 	sx_out(bp, CD186x_CAR, port_No(port));
 	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
+	spin_unlock(&bp->lock);
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	func_exit();
@@ -2088,10 +2089,10 @@
 	spin_lock_irqsave(&port->lock, flags);
 	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
 		port->IER |= IER_TXRDY;
-		spin_lock_irqsave(&bp->lock, flags);
+		spin_lock(&bp->lock);
 		sx_out(bp, CD186x_CAR, port_No(port));
 		sx_out(bp, CD186x_IER, port->IER);
-		spin_unlock_irqrestore(&bp->lock, flags);
+		spin_unlock(&bp->lock);
 	}
 	spin_unlock_irqrestore(&port->lock, flags);
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/stallion.c linux-libre-2.6.31-gnu/drivers/char/stallion.c
--- linux-libre-2.6.30-gnu/drivers/char/stallion.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/stallion.c	2009-09-09 18:13:59.000000000 -0400
@@ -772,11 +772,11 @@
 	return (portp->sigs & TIOCM_CD) ? 1 : 0;
 }
 
-static void stl_raise_dtr_rts(struct tty_port *port)
+static void stl_dtr_rts(struct tty_port *port, int on)
 {
 	struct stlport *portp = container_of(port, struct stlport, port);
 	/* Takes brd_lock internally */
-	stl_setsignals(portp, 1, 1);
+	stl_setsignals(portp, on, on);
 }
 
 /*****************************************************************************/
@@ -2547,7 +2547,7 @@
 
 static const struct tty_port_operations stl_port_ops = {
 	.carrier_raised = stl_carrier_raised,
-	.raise_dtr_rts = stl_raise_dtr_rts,
+	.dtr_rts = stl_dtr_rts,
 };
 
 /*****************************************************************************/
diff -druN linux-libre-2.6.30-gnu/drivers/char/sx.c linux-libre-2.6.31-gnu/drivers/char/sx.c
--- linux-libre-2.6.30-gnu/drivers/char/sx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/sx.c	2009-09-09 18:13:59.000000000 -0400
@@ -216,6 +216,7 @@
 #include <linux/eisa.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/bitops.h>
diff -druN linux-libre-2.6.30-gnu/drivers/char/synclink.c linux-libre-2.6.31-gnu/drivers/char/synclink.c
--- linux-libre-2.6.30-gnu/drivers/char/synclink.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/synclink.c	2009-09-09 18:13:59.000000000 -0400
@@ -81,6 +81,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
@@ -3247,13 +3248,16 @@
 	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
 	struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
 	unsigned long flags;
 
 	spin_lock_irqsave(&info->irq_spinlock,flags);
-	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	if (on)
+		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
  	usc_set_serial_signals(info);
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 }
@@ -4258,7 +4262,7 @@
 
 static const struct tty_port_operations mgsl_port_ops = {
 	.carrier_raised = carrier_raised,
-	.raise_dtr_rts = raise_dtr_rts,
+	.dtr_rts = dtr_rts,
 };
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/synclink_gt.c linux-libre-2.6.31-gnu/drivers/char/synclink_gt.c
--- linux-libre-2.6.30-gnu/drivers/char/synclink_gt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/synclink_gt.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
@@ -214,6 +215,7 @@
 #define set_desc_next(a,b) (a).next   = cpu_to_le32((unsigned int)(b))
 #define set_desc_count(a,b)(a).count  = cpu_to_le16((unsigned short)(b))
 #define set_desc_eof(a,b)  (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0))
+#define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b))
 #define desc_count(a)      (le16_to_cpu((a).count))
 #define desc_status(a)     (le16_to_cpu((a).status))
 #define desc_complete(a)   (le16_to_cpu((a).status) & BIT15)
@@ -297,6 +299,7 @@
 	u32 max_frame_size;       /* as set by device config */
 
 	unsigned int rbuf_fill_level;
+	unsigned int rx_pio;
 	unsigned int if_mode;
 	unsigned int base_clock;
 
@@ -331,6 +334,8 @@
 	struct slgt_desc *rbufs;
 	unsigned int rbuf_current;
 	unsigned int rbuf_index;
+	unsigned int rbuf_fill_index;
+	unsigned short rbuf_fill_count;
 
 	unsigned int tbuf_count;
 	struct slgt_desc *tbufs;
@@ -463,7 +468,6 @@
 static unsigned int tbuf_bytes(struct slgt_info *info);
 static void reset_tbufs(struct slgt_info *info);
 static void tdma_reset(struct slgt_info *info);
-static void tdma_start(struct slgt_info *info);
 static void tx_load(struct slgt_info *info, const char *buf, unsigned int count);
 
 static void get_signals(struct slgt_info *info);
@@ -791,6 +795,18 @@
 	}
 }
 
+static void update_tx_timer(struct slgt_info *info)
+{
+	/*
+	 * use worst case speed of 1200bps to calculate transmit timeout
+	 * based on data in buffers (tbuf_bytes) and FIFO (128 bytes)
+	 */
+	if (info->params.mode == MGSL_MODE_HDLC) {
+		int timeout  = (tbuf_bytes(info) * 7) + 1000;
+		mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout));
+	}
+}
+
 static int write(struct tty_struct *tty,
 		 const unsigned char *buf, int count)
 {
@@ -834,8 +850,18 @@
 		spin_lock_irqsave(&info->lock,flags);
 		if (!info->tx_active)
 		 	tx_start(info);
-		else
-			tdma_start(info);
+		else if (!(rd_reg32(info, TDCSR) & BIT0)) {
+			/* transmit still active but transmit DMA stopped */
+			unsigned int i = info->tbuf_current;
+			if (!i)
+				i = info->tbuf_count;
+			i--;
+			/* if DMA buf unsent must try later after tx idle */
+			if (desc_count(info->tbufs[i]))
+				ret = 0;
+		}
+		if (ret > 0)
+			update_tx_timer(info);
 		spin_unlock_irqrestore(&info->lock,flags);
  	}
 
@@ -1498,10 +1524,9 @@
 	/* save start time for transmit timeout detection */
 	dev->trans_start = jiffies;
 
-	/* start hardware transmitter if necessary */
 	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active)
-	 	tx_start(info);
+	tx_start(info);
+	update_tx_timer(info);
 	spin_unlock_irqrestore(&info->lock,flags);
 
 	return 0;
@@ -2110,6 +2135,40 @@
 	info->pending_bh |= BH_STATUS;
 }
 
+static void isr_rxdata(struct slgt_info *info)
+{
+	unsigned int count = info->rbuf_fill_count;
+	unsigned int i = info->rbuf_fill_index;
+	unsigned short reg;
+
+	while (rd_reg16(info, SSR) & IRQ_RXDATA) {
+		reg = rd_reg16(info, RDR);
+		DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg));
+		if (desc_complete(info->rbufs[i])) {
+			/* all buffers full */
+			rx_stop(info);
+			info->rx_restart = 1;
+			continue;
+		}
+		info->rbufs[i].buf[count++] = (unsigned char)reg;
+		/* async mode saves status byte to buffer for each data byte */
+		if (info->params.mode == MGSL_MODE_ASYNC)
+			info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8);
+		if (count == info->rbuf_fill_level || (reg & BIT10)) {
+			/* buffer full or end of frame */
+			set_desc_count(info->rbufs[i], count);
+			set_desc_status(info->rbufs[i], BIT15 | (reg >> 8));
+			info->rbuf_fill_count = count = 0;
+			if (++i == info->rbuf_count)
+				i = 0;
+			info->pending_bh |= BH_RECEIVE;
+		}
+	}
+
+	info->rbuf_fill_index = i;
+	info->rbuf_fill_count = count;
+}
+
 static void isr_serial(struct slgt_info *info)
 {
 	unsigned short status = rd_reg16(info, SSR);
@@ -2125,6 +2184,8 @@
 			if (info->tx_count)
 				isr_txeom(info, status);
 		}
+		if (info->rx_pio && (status & IRQ_RXDATA))
+			isr_rxdata(info);
 		if ((status & IRQ_RXBREAK) && (status & RXBREAK)) {
 			info->icount.brk++;
 			/* process break detection if tty control allows */
@@ -2141,7 +2202,8 @@
 	} else {
 		if (status & (IRQ_TXIDLE + IRQ_TXUNDER))
 			isr_txeom(info, status);
-
+		if (info->rx_pio && (status & IRQ_RXDATA))
+			isr_rxdata(info);
 		if (status & IRQ_RXIDLE) {
 			if (status & RXIDLE)
 				info->icount.rxidle++;
@@ -2642,6 +2704,10 @@
 			return -EINVAL;
 		}
 		info->rbuf_fill_level = rbuf_fill_level;
+		if (rbuf_fill_level < 128)
+			info->rx_pio = 1; /* PIO mode */
+		else
+			info->rx_pio = 0; /* DMA mode */
 		rx_stop(info); /* restart receiver to use new fill level */
 	}
 
@@ -3099,13 +3165,16 @@
 	return (info->signals & SerialSignal_DCD) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
 	unsigned long flags;
 	struct slgt_info *info = container_of(port, struct slgt_info, port);
 
 	spin_lock_irqsave(&info->lock,flags);
-	info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+	if (on)
+		info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
  	set_signals(info);
 	spin_unlock_irqrestore(&info->lock,flags);
 }
@@ -3419,7 +3488,7 @@
 
 static const struct tty_port_operations slgt_port_ops = {
 	.carrier_raised = carrier_raised,
-	.raise_dtr_rts = raise_dtr_rts,
+	.dtr_rts = dtr_rts,
 };
 
 /*
@@ -3841,15 +3910,27 @@
 	rdma_reset(info);
 	reset_rbufs(info);
 
-	/* set 1st descriptor address */
-	wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
-
-	if (info->params.mode != MGSL_MODE_ASYNC) {
-		/* enable rx DMA and DMA interrupt */
-		wr_reg32(info, RDCSR, (BIT2 + BIT0));
+	if (info->rx_pio) {
+		/* rx request when rx FIFO not empty */
+		wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14));
+		slgt_irq_on(info, IRQ_RXDATA);
+		if (info->params.mode == MGSL_MODE_ASYNC) {
+			/* enable saving of rx status */
+			wr_reg32(info, RDCSR, BIT6);
+		}
 	} else {
-		/* enable saving of rx status, rx DMA and DMA interrupt */
-		wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
+		/* rx request when rx FIFO half full */
+		wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14));
+		/* set 1st descriptor address */
+		wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
+
+		if (info->params.mode != MGSL_MODE_ASYNC) {
+			/* enable rx DMA and DMA interrupt */
+			wr_reg32(info, RDCSR, (BIT2 + BIT0));
+		} else {
+			/* enable saving of rx status, rx DMA and DMA interrupt */
+			wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
+		}
 	}
 
 	slgt_irq_on(info, IRQ_RXOVER);
@@ -3886,50 +3967,19 @@
 			slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE);
 			/* clear tx idle and underrun status bits */
 			wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
-			if (info->params.mode == MGSL_MODE_HDLC)
-				mod_timer(&info->tx_timer, jiffies +
-						msecs_to_jiffies(5000));
 		} else {
 			slgt_irq_off(info, IRQ_TXDATA);
 			slgt_irq_on(info, IRQ_TXIDLE);
 			/* clear tx idle status bit */
 			wr_reg16(info, SSR, IRQ_TXIDLE);
 		}
-		tdma_start(info);
+		/* set 1st descriptor address and start DMA */
+		wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
+		wr_reg32(info, TDCSR, BIT2 + BIT0);
 		info->tx_active = true;
 	}
 }
 
-/*
- * start transmit DMA if inactive and there are unsent buffers
- */
-static void tdma_start(struct slgt_info *info)
-{
-	unsigned int i;
-
-	if (rd_reg32(info, TDCSR) & BIT0)
-		return;
-
-	/* transmit DMA inactive, check for unsent buffers */
-	i = info->tbuf_start;
-	while (!desc_count(info->tbufs[i])) {
-		if (++i == info->tbuf_count)
-			i = 0;
-		if (i == info->tbuf_current)
-			return;
-	}
-	info->tbuf_start = i;
-
-	/* there are unsent buffers, start transmit DMA */
-
-	/* reset needed if previous error condition */
-	tdma_reset(info);
-
-	/* set 1st descriptor address */
-	wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
-	wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
-}
-
 static void tx_stop(struct slgt_info *info)
 {
 	unsigned short val;
@@ -4467,6 +4517,8 @@
 static void reset_rbufs(struct slgt_info *info)
 {
 	free_rbufs(info, 0, info->rbuf_count - 1);
+	info->rbuf_fill_index = 0;
+	info->rbuf_fill_count = 0;
 }
 
 /*
@@ -4942,8 +4994,7 @@
 		info->icount.txtimeout++;
 	}
 	spin_lock_irqsave(&info->lock,flags);
-	info->tx_active = false;
-	info->tx_count = 0;
+	tx_stop(info);
 	spin_unlock_irqrestore(&info->lock,flags);
 
 #if SYNCLINK_GENERIC_HDLC
diff -druN linux-libre-2.6.30-gnu/drivers/char/synclinkmp.c linux-libre-2.6.31-gnu/drivers/char/synclinkmp.c
--- linux-libre-2.6.30-gnu/drivers/char/synclinkmp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/synclinkmp.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,6 +52,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
@@ -3277,13 +3278,16 @@
 	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
 }
 
-static void raise_dtr_rts(struct tty_port *port)
+static void dtr_rts(struct tty_port *port, int on)
 {
 	SLMP_INFO *info = container_of(port, SLMP_INFO, port);
 	unsigned long flags;
 
 	spin_lock_irqsave(&info->lock,flags);
-	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	if (on)
+		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
  	set_signals(info);
 	spin_unlock_irqrestore(&info->lock,flags);
 }
@@ -3746,7 +3750,7 @@
 
 static const struct tty_port_operations port_ops = {
 	.carrier_raised = carrier_raised,
-	.raise_dtr_rts = raise_dtr_rts,
+	.dtr_rts = dtr_rts,
 };
 
 /* Allocate and initialize a device instance structure
diff -druN linux-libre-2.6.30-gnu/drivers/char/sysrq.c linux-libre-2.6.31-gnu/drivers/char/sysrq.c
--- linux-libre-2.6.30-gnu/drivers/char/sysrq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/sysrq.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/kbd_kern.h>
 #include <linux/proc_fs.h>
 #include <linux/quotaops.h>
+#include <linux/perf_counter.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/suspend.h>
@@ -34,7 +35,6 @@
 #include <linux/spinlock.h>
 #include <linux/vt_kern.h>
 #include <linux/workqueue.h>
-#include <linux/kexec.h>
 #include <linux/hrtimer.h>
 #include <linux/oom.h>
 
@@ -120,20 +120,20 @@
 #define sysrq_unraw_op (*(struct sysrq_key_op *)0)
 #endif /* CONFIG_VT */
 
-#ifdef CONFIG_KEXEC
-static void sysrq_handle_crashdump(int key, struct tty_struct *tty)
+static void sysrq_handle_crash(int key, struct tty_struct *tty)
 {
-	crash_kexec(get_irq_regs());
+	char *killer = NULL;
+
+	panic_on_oops = 1;	/* force panic */
+	wmb();
+	*killer = 1;
 }
-static struct sysrq_key_op sysrq_crashdump_op = {
-	.handler	= sysrq_handle_crashdump,
-	.help_msg	= "Crashdump",
-	.action_msg	= "Trigger a crashdump",
+static struct sysrq_key_op sysrq_crash_op = {
+	.handler	= sysrq_handle_crash,
+	.help_msg	= "Crash",
+	.action_msg	= "Trigger a crash",
 	.enable_mask	= SYSRQ_ENABLE_DUMP,
 };
-#else
-#define sysrq_crashdump_op (*(struct sysrq_key_op *)0)
-#endif
 
 static void sysrq_handle_reboot(int key, struct tty_struct *tty)
 {
@@ -243,6 +243,7 @@
 	struct pt_regs *regs = get_irq_regs();
 	if (regs)
 		show_regs(regs);
+	perf_counter_print_debug();
 }
 static struct sysrq_key_op sysrq_showregs_op = {
 	.handler	= sysrq_handle_showregs,
@@ -402,7 +403,7 @@
 	 */
 	NULL,				/* a */
 	&sysrq_reboot_op,		/* b */
-	&sysrq_crashdump_op,		/* c & ibm_emac driver debug */
+	&sysrq_crash_op,		/* c & ibm_emac driver debug */
 	&sysrq_showlocks_op,		/* d */
 	&sysrq_term_op,			/* e */
 	&sysrq_moom_op,			/* f */
diff -druN linux-libre-2.6.30-gnu/drivers/char/tb0219.c linux-libre-2.6.31-gnu/drivers/char/tb0219.c
--- linux-libre-2.6.30-gnu/drivers/char/tb0219.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tb0219.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Driver for TANBAC TB0219 base board.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@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
@@ -28,7 +28,7 @@
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/tb0219.h>
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
 MODULE_LICENSE("GPL");
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/tpm/tpm.c linux-libre-2.6.31-gnu/drivers/char/tpm/tpm.c
--- linux-libre-2.6.30-gnu/drivers/char/tpm/tpm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tpm/tpm.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,6 @@
 #include <linux/poll.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 
 #include "tpm.h"
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/tty_audit.c linux-libre-2.6.31-gnu/drivers/char/tty_audit.c
--- linux-libre-2.6.30-gnu/drivers/char/tty_audit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tty_audit.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,10 +29,7 @@
 	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
 	if (!buf)
 		goto err;
-	if (PAGE_SIZE != N_TTY_BUF_SIZE)
-		buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
-	else
-		buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+	buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
 	if (!buf->data)
 		goto err_buf;
 	atomic_set(&buf->count, 1);
@@ -52,10 +49,7 @@
 static void tty_audit_buf_free(struct tty_audit_buf *buf)
 {
 	WARN_ON(buf->valid != 0);
-	if (PAGE_SIZE != N_TTY_BUF_SIZE)
-		kfree(buf->data);
-	else
-		free_page((unsigned long)buf->data);
+	kfree(buf->data);
 	kfree(buf);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/tty_buffer.c linux-libre-2.6.31-gnu/drivers/char/tty_buffer.c
--- linux-libre-2.6.30-gnu/drivers/char/tty_buffer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tty_buffer.c	2009-09-09 18:13:59.000000000 -0400
@@ -462,6 +462,19 @@
 }
 
 /**
+ *	tty_flush_to_ldisc
+ *	@tty: tty to push
+ *
+ *	Push the terminal flip buffers to the line discipline.
+ *
+ *	Must not be called from IRQ context.
+ */
+void tty_flush_to_ldisc(struct tty_struct *tty)
+{
+	flush_to_ldisc(&tty->buf.work.work);
+}
+
+/**
  *	tty_flip_buffer_push	-	terminal
  *	@tty: tty to push
  *
diff -druN linux-libre-2.6.30-gnu/drivers/char/tty_io.c linux-libre-2.6.31-gnu/drivers/char/tty_io.c
--- linux-libre-2.6.30-gnu/drivers/char/tty_io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tty_io.c	2009-09-09 18:13:59.000000000 -0400
@@ -295,7 +295,7 @@
 	struct tty_driver *p, *res = NULL;
 	int tty_line = 0;
 	int len;
-	char *str;
+	char *str, *stp;
 
 	for (str = name; *str; str++)
 		if ((*str >= '0' && *str <= '9') || *str == ',')
@@ -311,13 +311,14 @@
 	list_for_each_entry(p, &tty_drivers, tty_drivers) {
 		if (strncmp(name, p->name, len) != 0)
 			continue;
-		if (*str == ',')
-			str++;
-		if (*str == '\0')
-			str = NULL;
+		stp = str;
+		if (*stp == ',')
+			stp++;
+		if (*stp == '\0')
+			stp = NULL;
 
 		if (tty_line >= 0 && tty_line <= p->num && p->ops &&
-		    p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
+		    p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) {
 			res = tty_driver_kref_get(p);
 			*line = tty_line;
 			break;
@@ -470,43 +471,6 @@
 EXPORT_SYMBOL_GPL(tty_wakeup);
 
 /**
- *	tty_ldisc_flush	-	flush line discipline queue
- *	@tty: tty
- *
- *	Flush the line discipline queue (if any) for this tty. If there
- *	is no line discipline active this is a no-op.
- */
-
-void tty_ldisc_flush(struct tty_struct *tty)
-{
-	struct tty_ldisc *ld = tty_ldisc_ref(tty);
-	if (ld) {
-		if (ld->ops->flush_buffer)
-			ld->ops->flush_buffer(tty);
-		tty_ldisc_deref(ld);
-	}
-	tty_buffer_flush(tty);
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_flush);
-
-/**
- *	tty_reset_termios	-	reset terminal state
- *	@tty: tty to reset
- *
- *	Restore a terminal to the driver default state
- */
-
-static void tty_reset_termios(struct tty_struct *tty)
-{
-	mutex_lock(&tty->termios_mutex);
-	*tty->termios = tty->driver->init_termios;
-	tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
-	tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
-	mutex_unlock(&tty->termios_mutex);
-}
-
-/**
  *	do_tty_hangup		-	actual handler for hangup events
  *	@work: tty device
  *
@@ -535,7 +499,6 @@
 	struct file *cons_filp = NULL;
 	struct file *filp, *f = NULL;
 	struct task_struct *p;
-	struct tty_ldisc *ld;
 	int    closecount = 0, n;
 	unsigned long flags;
 	int refs = 0;
@@ -566,40 +529,8 @@
 		filp->f_op = &hung_up_tty_fops;
 	}
 	file_list_unlock();
-	/*
-	 * FIXME! What are the locking issues here? This may me overdoing
-	 * things... This question is especially important now that we've
-	 * removed the irqlock.
-	 */
-	ld = tty_ldisc_ref(tty);
-	if (ld != NULL) {
-		/* We may have no line discipline at this point */
-		if (ld->ops->flush_buffer)
-			ld->ops->flush_buffer(tty);
-		tty_driver_flush_buffer(tty);
-		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
-		    ld->ops->write_wakeup)
-			ld->ops->write_wakeup(tty);
-		if (ld->ops->hangup)
-			ld->ops->hangup(tty);
-	}
-	/*
-	 * FIXME: Once we trust the LDISC code better we can wait here for
-	 * ldisc completion and fix the driver call race
-	 */
-	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
-	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
-	/*
-	 * Shutdown the current line discipline, and reset it to
-	 * N_TTY.
-	 */
-	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
-		tty_reset_termios(tty);
-	/* Defer ldisc switch */
-	/* tty_deferred_ldisc_switch(N_TTY);
 
-	  This should get done automatically when the port closes and
-	  tty_release is called */
+	tty_ldisc_hangup(tty);
 
 	read_lock(&tasklist_lock);
 	if (tty->session) {
@@ -628,12 +559,15 @@
 	read_unlock(&tasklist_lock);
 
 	spin_lock_irqsave(&tty->ctrl_lock, flags);
-	tty->flags = 0;
+	clear_bit(TTY_THROTTLED, &tty->flags);
+	clear_bit(TTY_PUSH, &tty->flags);
+	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	put_pid(tty->session);
 	put_pid(tty->pgrp);
 	tty->session = NULL;
 	tty->pgrp = NULL;
 	tty->ctrl_status = 0;
+	set_bit(TTY_HUPPED, &tty->flags);
 	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 
 	/* Account for the p->signal references we killed */
@@ -659,10 +593,7 @@
 	 * can't yet guarantee all that.
 	 */
 	set_bit(TTY_HUPPED, &tty->flags);
-	if (ld) {
-		tty_ldisc_enable(tty);
-		tty_ldisc_deref(ld);
-	}
+	tty_ldisc_enable(tty);
 	unlock_kernel();
 	if (f)
 		fput(f);
@@ -1332,7 +1263,9 @@
 	tty->count++;
 	tty->driver = driver; /* N.B. why do this every time?? */
 
+	mutex_lock(&tty->ldisc_mutex);
 	WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
+	mutex_unlock(&tty->ldisc_mutex);
 
 	return 0;
 }
@@ -2480,6 +2413,24 @@
 	return tty->ops->tiocmset(tty, file, set, clear);
 }
 
+struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
+{
+	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+	    tty->driver->subtype == PTY_TYPE_MASTER)
+		tty = tty->link;
+	return tty;
+}
+EXPORT_SYMBOL(tty_pair_get_tty);
+
+struct tty_struct *tty_pair_get_pty(struct tty_struct *tty)
+{
+	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+	    tty->driver->subtype == PTY_TYPE_MASTER)
+	    return tty;
+	return tty->link;
+}
+EXPORT_SYMBOL(tty_pair_get_pty);
+
 /*
  * Split this up, as gcc can choke on it otherwise..
  */
@@ -2495,11 +2446,7 @@
 	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
 		return -EINVAL;
 
-	real_tty = tty;
-	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-	    tty->driver->subtype == PTY_TYPE_MASTER)
-		real_tty = tty->link;
-
+	real_tty = tty_pair_get_tty(tty);
 
 	/*
 	 * Factor out some common prep work
@@ -2555,7 +2502,7 @@
 	case TIOCGSID:
 		return tiocgsid(tty, real_tty, p);
 	case TIOCGETD:
-		return put_user(tty->ldisc.ops->num, (int __user *)p);
+		return put_user(tty->ldisc->ops->num, (int __user *)p);
 	case TIOCSETD:
 		return tiocsetd(tty, p);
 	/*
@@ -2770,6 +2717,7 @@
 	tty->buf.head = tty->buf.tail = NULL;
 	tty_buffer_init(tty);
 	mutex_init(&tty->termios_mutex);
+	mutex_init(&tty->ldisc_mutex);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
 	INIT_WORK(&tty->hangup_work, do_tty_hangup);
diff -druN linux-libre-2.6.30-gnu/drivers/char/tty_ioctl.c linux-libre-2.6.31-gnu/drivers/char/tty_ioctl.c
--- linux-libre-2.6.30-gnu/drivers/char/tty_ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tty_ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -97,14 +96,19 @@
  *	@tty: terminal
  *
  *	Indicate that a tty should stop transmitting data down the stack.
+ *	Takes the termios mutex to protect against parallel throttle/unthrottle
+ *	and also to ensure the driver can consistently reference its own
+ *	termios data at this point when implementing software flow control.
  */
 
 void tty_throttle(struct tty_struct *tty)
 {
+	mutex_lock(&tty->termios_mutex);
 	/* check TTY_THROTTLED first so it indicates our state */
 	if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
 	    tty->ops->throttle)
 		tty->ops->throttle(tty);
+	mutex_unlock(&tty->termios_mutex);
 }
 EXPORT_SYMBOL(tty_throttle);
 
@@ -113,13 +117,21 @@
  *	@tty: terminal
  *
  *	Indicate that a tty may continue transmitting data down the stack.
+ *	Takes the termios mutex to protect against parallel throttle/unthrottle
+ *	and also to ensure the driver can consistently reference its own
+ *	termios data at this point when implementing software flow control.
+ *
+ *	Drivers should however remember that the stack can issue a throttle,
+ *	then change flow control method, then unthrottle.
  */
 
 void tty_unthrottle(struct tty_struct *tty)
 {
+	mutex_lock(&tty->termios_mutex);
 	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
 	    tty->ops->unthrottle)
 		tty->ops->unthrottle(tty);
+	mutex_unlock(&tty->termios_mutex);
 }
 EXPORT_SYMBOL(tty_unthrottle);
 
@@ -613,9 +625,25 @@
 	return 0;
 }
 
+static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
+{
+	mutex_lock(&tty->termios_mutex);
+	memcpy(kterm, tty->termios, sizeof(struct ktermios));
+	mutex_unlock(&tty->termios_mutex);
+}
+
+static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
+{
+	mutex_lock(&tty->termios_mutex);
+	memcpy(kterm, tty->termios_locked, sizeof(struct ktermios));
+	mutex_unlock(&tty->termios_mutex);
+}
+
 static int get_termio(struct tty_struct *tty, struct termio __user *termio)
 {
-	if (kernel_termios_to_user_termio(termio, tty->termios))
+	struct ktermios kterm;
+	copy_termios(tty, &kterm);
+	if (kernel_termios_to_user_termio(termio, &kterm))
 		return -EFAULT;
 	return 0;
 }
@@ -917,6 +945,7 @@
 	struct tty_struct *real_tty;
 	void __user *p = (void __user *)arg;
 	int ret = 0;
+	struct ktermios kterm;
 
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver->subtype == PTY_TYPE_MASTER)
@@ -952,23 +981,20 @@
 		return set_termios(real_tty, p, TERMIOS_OLD);
 #ifndef TCGETS2
 	case TCGETS:
-		mutex_lock(&real_tty->termios_mutex);
-		if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
+		copy_termios(real_tty, &kterm);
+		if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
 			ret = -EFAULT;
-		mutex_unlock(&real_tty->termios_mutex);
 		return ret;
 #else
 	case TCGETS:
-		mutex_lock(&real_tty->termios_mutex);
-		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
+		copy_termios(real_tty, &kterm);
+		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
 			ret = -EFAULT;
-		mutex_unlock(&real_tty->termios_mutex);
 		return ret;
 	case TCGETS2:
-		mutex_lock(&real_tty->termios_mutex);
-		if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
+		copy_termios(real_tty, &kterm);
+		if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
 			ret = -EFAULT;
-		mutex_unlock(&real_tty->termios_mutex);
 		return ret;
 	case TCSETSF2:
 		return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
@@ -987,46 +1013,51 @@
 		return set_termios(real_tty, p, TERMIOS_TERMIO);
 #ifndef TCGETS2
 	case TIOCGLCKTRMIOS:
-		mutex_lock(&real_tty->termios_mutex);
-		if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
+		copy_termios_locked(real_tty, &kterm);
+		if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
 			ret = -EFAULT;
-		mutex_unlock(&real_tty->termios_mutex);
 		return ret;
 	case TIOCSLCKTRMIOS:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		mutex_lock(&real_tty->termios_mutex);
-		if (user_termios_to_kernel_termios(real_tty->termios_locked,
+		copy_termios_locked(real_tty, &kterm);
+		if (user_termios_to_kernel_termios(&kterm,
 					       (struct termios __user *) arg))
-			ret = -EFAULT;
+			return -EFAULT;
+		mutex_lock(&real_tty->termios_mutex);
+		memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
 		mutex_unlock(&real_tty->termios_mutex);
-		return ret;
+		return 0;
 #else
 	case TIOCGLCKTRMIOS:
-		mutex_lock(&real_tty->termios_mutex);
-		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
+		copy_termios_locked(real_tty, &kterm);
+		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
 			ret = -EFAULT;
-		mutex_unlock(&real_tty->termios_mutex);
 		return ret;
 	case TIOCSLCKTRMIOS:
 		if (!capable(CAP_SYS_ADMIN))
-			ret = -EPERM;
-		mutex_lock(&real_tty->termios_mutex);
-		if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
+			return -EPERM;
+		copy_termios_locked(real_tty, &kterm);
+		if (user_termios_to_kernel_termios_1(&kterm,
 					       (struct termios __user *) arg))
-			ret = -EFAULT;
+			return -EFAULT;
+		mutex_lock(&real_tty->termios_mutex);
+		memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
 		mutex_unlock(&real_tty->termios_mutex);
 		return ret;
 #endif
 #ifdef TCGETX
-	case TCGETX:
+	case TCGETX: {
+		struct termiox ktermx;
 		if (real_tty->termiox == NULL)
 			return -EINVAL;
 		mutex_lock(&real_tty->termios_mutex);
-		if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
-			ret = -EFAULT;
+		memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
 		mutex_unlock(&real_tty->termios_mutex);
+		if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
+			ret = -EFAULT;
 		return ret;
+	}
 	case TCSETX:
 		return set_termiox(real_tty, p, 0);
 	case TCSETXW:
@@ -1035,10 +1066,9 @@
 		return set_termiox(real_tty, p, TERMIOS_FLUSH);
 #endif		
 	case TIOCGSOFTCAR:
-		mutex_lock(&real_tty->termios_mutex);
-		ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
+		copy_termios(real_tty, &kterm);
+		ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
 						(int __user *)arg);
-		mutex_unlock(&real_tty->termios_mutex);
 		return ret;
 	case TIOCSSOFTCAR:
 		if (get_user(arg, (unsigned int __user *) arg))
diff -druN linux-libre-2.6.30-gnu/drivers/char/tty_ldisc.c linux-libre-2.6.31-gnu/drivers/char/tty_ldisc.c
--- linux-libre-2.6.30-gnu/drivers/char/tty_ldisc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tty_ldisc.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,6 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/bitops.h>
@@ -49,6 +48,41 @@
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
 
+static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
+{
+	if (ld)
+		atomic_inc(&ld->users);
+	return ld;
+}
+
+static void put_ldisc(struct tty_ldisc *ld)
+{
+	unsigned long flags;
+
+	if (WARN_ON_ONCE(!ld))
+		return;
+
+	/*
+	 * If this is the last user, free the ldisc, and
+	 * release the ldisc ops.
+	 *
+	 * We really want an "atomic_dec_and_lock_irqsave()",
+	 * but we don't have it, so this does it by hand.
+	 */
+	local_irq_save(flags);
+	if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
+		struct tty_ldisc_ops *ldo = ld->ops;
+
+		ldo->refcount--;
+		module_put(ldo->owner);
+		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+		kfree(ld);
+		return;
+	}
+	local_irq_restore(flags);
+}
+
 /**
  *	tty_register_ldisc	-	install a line discipline
  *	@disc: ldisc number
@@ -115,19 +149,22 @@
 /**
  *	tty_ldisc_try_get	-	try and reference an ldisc
  *	@disc: ldisc number
- *	@ld: tty ldisc structure to complete
  *
  *	Attempt to open and lock a line discipline into place. Return
- *	the line discipline refcounted and assigned in ld. On an error
- *	report the error code back
+ *	the line discipline refcounted or an error.
  */
 
-static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld)
+static struct tty_ldisc *tty_ldisc_try_get(int disc)
 {
 	unsigned long flags;
+	struct tty_ldisc *ld;
 	struct tty_ldisc_ops *ldops;
 	int err = -EINVAL;
-	
+
+	ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
+	if (ld == NULL)
+		return ERR_PTR(-ENOMEM);
+
 	spin_lock_irqsave(&tty_ldisc_lock, flags);
 	ld->ops = NULL;
 	ldops = tty_ldiscs[disc];
@@ -140,17 +177,21 @@
 			/* lock it */
 			ldops->refcount++;
 			ld->ops = ldops;
+			atomic_set(&ld->users, 1);
 			err = 0;
 		}
 	}
 	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	return err;
+	if (err) {
+		kfree(ld);
+		return ERR_PTR(err);
+	}
+	return ld;
 }
 
 /**
  *	tty_ldisc_get		-	take a reference to an ldisc
  *	@disc: ldisc number
- *	@ld: tty line discipline structure to use
  *
  *	Takes a reference to a line discipline. Deals with refcounts and
  *	module locking counts. Returns NULL if the discipline is not available.
@@ -161,52 +202,26 @@
  *		takes tty_ldisc_lock to guard against ldisc races
  */
 
-static int tty_ldisc_get(int disc, struct tty_ldisc *ld)
+static struct tty_ldisc *tty_ldisc_get(int disc)
 {
-	int err;
+	struct tty_ldisc *ld;
 
 	if (disc < N_TTY || disc >= NR_LDISCS)
-		return -EINVAL;
-	err = tty_ldisc_try_get(disc, ld);
-	if (err < 0) {
+		return ERR_PTR(-EINVAL);
+	ld = tty_ldisc_try_get(disc);
+	if (IS_ERR(ld)) {
 		request_module("tty-ldisc-%d", disc);
-		err = tty_ldisc_try_get(disc, ld);
+		ld = tty_ldisc_try_get(disc);
 	}
-	return err;
-}
-
-/**
- *	tty_ldisc_put		-	drop ldisc reference
- *	@disc: ldisc number
- *
- *	Drop a reference to a line discipline. Manage refcounts and
- *	module usage counts
- *
- *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
- */
-
-static void tty_ldisc_put(struct tty_ldisc_ops *ld)
-{
-	unsigned long flags;
-	int disc = ld->num;
-
-	BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	ld = tty_ldiscs[disc];
-	BUG_ON(ld->refcount == 0);
-	ld->refcount--;
-	module_put(ld->owner);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	return ld;
 }
 
-static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
+static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
 {
 	return (*pos < NR_LDISCS) ? pos : NULL;
 }
 
-static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
+static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	(*pos)++;
 	return (*pos < NR_LDISCS) ? pos : NULL;
@@ -219,12 +234,13 @@
 static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
 {
 	int i = *(loff_t *)v;
-	struct tty_ldisc ld;
-	
-	if (tty_ldisc_get(i, &ld) < 0)
+	struct tty_ldisc *ld;
+
+	ld = tty_ldisc_try_get(i);
+	if (IS_ERR(ld))
 		return 0;
-	seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i);
-	tty_ldisc_put(ld.ops);
+	seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i);
+	put_ldisc(ld);
 	return 0;
 }
 
@@ -254,7 +270,7 @@
  *	@ld: line discipline
  *
  *	Install an instance of a line discipline into a tty structure. The
- *	ldisc must have a reference count above zero to ensure it remains/
+ *	ldisc must have a reference count above zero to ensure it remains.
  *	The tty instance refcount starts at zero.
  *
  *	Locking:
@@ -263,8 +279,7 @@
 
 static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
 {
-	ld->refcount = 0;
-	tty->ldisc = *ld;
+	tty->ldisc = ld;
 }
 
 /**
@@ -279,20 +294,17 @@
  *	Locking: takes tty_ldisc_lock
  */
 
-static int tty_ldisc_try(struct tty_struct *tty)
+static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
 {
 	unsigned long flags;
 	struct tty_ldisc *ld;
-	int ret = 0;
 
 	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	ld = &tty->ldisc;
-	if (test_bit(TTY_LDISC, &tty->flags)) {
-		ld->refcount++;
-		ret = 1;
-	}
+	ld = NULL;
+	if (test_bit(TTY_LDISC, &tty->flags))
+		ld = get_ldisc(tty->ldisc);
 	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	return ret;
+	return ld;
 }
 
 /**
@@ -313,12 +325,12 @@
 
 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
 {
+	struct tty_ldisc *ld;
+
 	/* wait_event is a macro */
-	wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
-	WARN_ON(tty->ldisc.refcount == 0);
-	return &tty->ldisc;
+	wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL);
+	return ld;
 }
-
 EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
 
 /**
@@ -334,11 +346,8 @@
 
 struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
 {
-	if (tty_ldisc_try(tty))
-		return &tty->ldisc;
-	return NULL;
+	return tty_ldisc_try(tty);
 }
-
 EXPORT_SYMBOL_GPL(tty_ldisc_ref);
 
 /**
@@ -353,22 +362,15 @@
 
 void tty_ldisc_deref(struct tty_ldisc *ld)
 {
-	unsigned long flags;
-
-	BUG_ON(ld == NULL);
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	if (ld->refcount == 0)
-		printk(KERN_ERR "tty_ldisc_deref: no references.\n");
-	else
-		ld->refcount--;
-	if (ld->refcount == 0)
-		wake_up(&tty_ldisc_wait);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	put_ldisc(ld);
 }
-
 EXPORT_SYMBOL_GPL(tty_ldisc_deref);
 
+static inline void tty_ldisc_put(struct tty_ldisc *ld)
+{
+	put_ldisc(ld);
+}
+
 /**
  *	tty_ldisc_enable	-	allow ldisc use
  *	@tty: terminal to activate ldisc on
@@ -389,6 +391,26 @@
 }
 
 /**
+ *	tty_ldisc_flush	-	flush line discipline queue
+ *	@tty: tty
+ *
+ *	Flush the line discipline queue (if any) for this tty. If there
+ *	is no line discipline active this is a no-op.
+ */
+
+void tty_ldisc_flush(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->ops->flush_buffer)
+			ld->ops->flush_buffer(tty);
+		tty_ldisc_deref(ld);
+	}
+	tty_buffer_flush(tty);
+}
+EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+
+/**
  *	tty_set_termios_ldisc		-	set ldisc field
  *	@tty: tty structure
  *	@num: line discipline number
@@ -407,6 +429,39 @@
 	mutex_unlock(&tty->termios_mutex);
 }
 
+/**
+ *	tty_ldisc_open		-	open a line discipline
+ *	@tty: tty we are opening the ldisc on
+ *	@ld: discipline to open
+ *
+ *	A helper opening method. Also a convenient debugging and check
+ *	point.
+ */
+
+static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
+{
+	WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
+	if (ld->ops->open)
+		return ld->ops->open(tty);
+	return 0;
+}
+
+/**
+ *	tty_ldisc_close		-	close a line discipline
+ *	@tty: tty we are opening the ldisc on
+ *	@ld: discipline to close
+ *
+ *	A helper close method. Also a convenient debugging and check
+ *	point.
+ */
+
+static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
+{
+	WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags));
+	clear_bit(TTY_LDISC_OPEN, &tty->flags);
+	if (ld->ops->close)
+		ld->ops->close(tty);
+}
 
 /**
  *	tty_ldisc_restore	-	helper for tty ldisc change
@@ -420,66 +475,112 @@
 static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 {
 	char buf[64];
-	struct tty_ldisc new_ldisc;
+	struct tty_ldisc *new_ldisc;
+	int r;
 
 	/* There is an outstanding reference here so this is safe */
-	tty_ldisc_get(old->ops->num, old);
+	old = tty_ldisc_get(old->ops->num);
+	WARN_ON(IS_ERR(old));
 	tty_ldisc_assign(tty, old);
 	tty_set_termios_ldisc(tty, old->ops->num);
-	if (old->ops->open && (old->ops->open(tty) < 0)) {
-		tty_ldisc_put(old->ops);
+	if (tty_ldisc_open(tty, old) < 0) {
+		tty_ldisc_put(old);
 		/* This driver is always present */
-		if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
+		new_ldisc = tty_ldisc_get(N_TTY);
+		if (IS_ERR(new_ldisc))
 			panic("n_tty: get");
-		tty_ldisc_assign(tty, &new_ldisc);
+		tty_ldisc_assign(tty, new_ldisc);
 		tty_set_termios_ldisc(tty, N_TTY);
-		if (new_ldisc.ops->open) {
-			int r = new_ldisc.ops->open(tty);
-				if (r < 0)
-				panic("Couldn't open N_TTY ldisc for "
-				      "%s --- error %d.",
-				      tty_name(tty, buf), r);
-		}
+		r = tty_ldisc_open(tty, new_ldisc);
+		if (r < 0)
+			panic("Couldn't open N_TTY ldisc for "
+			      "%s --- error %d.",
+			      tty_name(tty, buf), r);
 	}
 }
 
 /**
+ *	tty_ldisc_halt		-	shut down the line discipline
+ *	@tty: tty device
+ *
+ *	Shut down the line discipline and work queue for this tty device.
+ *	The TTY_LDISC flag being cleared ensures no further references can
+ *	be obtained while the delayed work queue halt ensures that no more
+ *	data is fed to the ldisc.
+ *
+ *	You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
+ *	in order to make sure any currently executing ldisc work is also
+ *	flushed.
+ */
+
+static int tty_ldisc_halt(struct tty_struct *tty)
+{
+	clear_bit(TTY_LDISC, &tty->flags);
+	return cancel_delayed_work(&tty->buf.work);
+}
+
+/**
  *	tty_set_ldisc		-	set line discipline
  *	@tty: the terminal to set
  *	@ldisc: the line discipline
  *
  *	Set the discipline of a tty line. Must be called from a process
- *	context.
+ *	context. The ldisc change logic has to protect itself against any
+ *	overlapping ldisc change (including on the other end of pty pairs),
+ *	the close of one side of a tty/pty pair, and eventually hangup.
  *
- *	Locking: takes tty_ldisc_lock.
- *		 called functions take termios_mutex
+ *	Locking: takes tty_ldisc_lock, termios_mutex
  */
 
 int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
 	int retval;
-	struct tty_ldisc o_ldisc, new_ldisc;
-	int work;
-	unsigned long flags;
+	struct tty_ldisc *o_ldisc, *new_ldisc;
+	int work, o_work = 0;
 	struct tty_struct *o_tty;
 
-restart:
-	/* This is a bit ugly for now but means we can break the 'ldisc
-	   is part of the tty struct' assumption later */
-	retval = tty_ldisc_get(ldisc, &new_ldisc);
-	if (retval)
-		return retval;
+	new_ldisc = tty_ldisc_get(ldisc);
+	if (IS_ERR(new_ldisc))
+		return PTR_ERR(new_ldisc);
+
+	/*
+	 *	We need to look at the tty locking here for pty/tty pairs
+	 *	when both sides try to change in parallel.
+	 */
+
+	o_tty = tty->link;	/* o_tty is the pty side or NULL */
+
+
+	/*
+	 *	Check the no-op case
+	 */
+
+	if (tty->ldisc->ops->num == ldisc) {
+		tty_ldisc_put(new_ldisc);
+		return 0;
+	}
 
 	/*
 	 *	Problem: What do we do if this blocks ?
+	 *	We could deadlock here
 	 */
 
 	tty_wait_until_sent(tty, 0);
 
-	if (tty->ldisc.ops->num == ldisc) {
-		tty_ldisc_put(new_ldisc.ops);
-		return 0;
+	mutex_lock(&tty->ldisc_mutex);
+
+	/*
+	 *	We could be midstream of another ldisc change which has
+	 *	dropped the lock during processing. If so we need to wait.
+	 */
+
+	while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
+		mutex_unlock(&tty->ldisc_mutex);
+		wait_event(tty_ldisc_wait,
+			test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
+		mutex_lock(&tty->ldisc_mutex);
 	}
+	set_bit(TTY_LDISC_CHANGING, &tty->flags);
 
 	/*
 	 *	No more input please, we are switching. The new ldisc
@@ -489,8 +590,6 @@
 	tty->receive_room = 0;
 
 	o_ldisc = tty->ldisc;
-	o_tty = tty->link;
-
 	/*
 	 *	Make sure we don't change while someone holds a
 	 *	reference to the line discipline. The TTY_LDISC bit
@@ -501,108 +600,180 @@
 	 *	with a userspace app continually trying to use the tty in
 	 *	parallel to the change and re-referencing the tty.
 	 */
-	clear_bit(TTY_LDISC, &tty->flags);
-	if (o_tty)
-		clear_bit(TTY_LDISC, &o_tty->flags);
 
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
-		if (tty->ldisc.refcount) {
-			/* Free the new ldisc we grabbed. Must drop the lock
-			   first. */
-			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-			tty_ldisc_put(o_ldisc.ops);
-			/*
-			 * There are several reasons we may be busy, including
-			 * random momentary I/O traffic. We must therefore
-			 * retry. We could distinguish between blocking ops
-			 * and retries if we made tty_ldisc_wait() smarter.
-			 * That is up for discussion.
-			 */
-			if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
-				return -ERESTARTSYS;
-			goto restart;
-		}
-		if (o_tty && o_tty->ldisc.refcount) {
-			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-			tty_ldisc_put(o_tty->ldisc.ops);
-			if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
-				return -ERESTARTSYS;
-			goto restart;
-		}
-	}
-	/*
-	 *	If the TTY_LDISC bit is set, then we are racing against
-	 *	another ldisc change
-	 */
-	if (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
-		struct tty_ldisc *ld;
-		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-		tty_ldisc_put(new_ldisc.ops);
-		ld = tty_ldisc_ref_wait(tty);
-		tty_ldisc_deref(ld);
-		goto restart;
-	}
-	/*
-	 *	This flag is used to avoid two parallel ldisc changes. Once
-	 *	open and close are fine grained locked this may work better
-	 *	as a mutex shared with the open/close/hup paths
-	 */
-	set_bit(TTY_LDISC_CHANGING, &tty->flags);
+	work = tty_ldisc_halt(tty);
 	if (o_tty)
-		set_bit(TTY_LDISC_CHANGING, &o_tty->flags);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	
-	/*
-	 *	From this point on we know nobody has an ldisc
-	 *	usage reference, nor can they obtain one until
-	 *	we say so later on.
-	 */
+		o_work = tty_ldisc_halt(o_tty);
 
-	work = cancel_delayed_work(&tty->buf.work);
 	/*
-	 * Wait for ->hangup_work and ->buf.work handlers to terminate
-	 * MUST NOT hold locks here.
+	 * Wait for ->hangup_work and ->buf.work handlers to terminate.
+	 * We must drop the mutex here in case a hangup is also in process.
 	 */
+
+	mutex_unlock(&tty->ldisc_mutex);
+
 	flush_scheduled_work();
+
+	mutex_lock(&tty->ldisc_mutex);
+	if (test_bit(TTY_HUPPED, &tty->flags)) {
+		/* We were raced by the hangup method. It will have stomped
+		   the ldisc data and closed the ldisc down */
+		clear_bit(TTY_LDISC_CHANGING, &tty->flags);
+		mutex_unlock(&tty->ldisc_mutex);
+		tty_ldisc_put(new_ldisc);
+		return -EIO;
+	}
+
 	/* Shutdown the current discipline. */
-	if (o_ldisc.ops->close)
-		(o_ldisc.ops->close)(tty);
+	tty_ldisc_close(tty, o_ldisc);
 
 	/* Now set up the new line discipline. */
-	tty_ldisc_assign(tty, &new_ldisc);
+	tty_ldisc_assign(tty, new_ldisc);
 	tty_set_termios_ldisc(tty, ldisc);
-	if (new_ldisc.ops->open)
-		retval = (new_ldisc.ops->open)(tty);
+
+	retval = tty_ldisc_open(tty, new_ldisc);
 	if (retval < 0) {
-		tty_ldisc_put(new_ldisc.ops);
-		tty_ldisc_restore(tty, &o_ldisc);
+		/* Back to the old one or N_TTY if we can't */
+		tty_ldisc_put(new_ldisc);
+		tty_ldisc_restore(tty, o_ldisc);
 	}
+
 	/* At this point we hold a reference to the new ldisc and a
 	   a reference to the old ldisc. If we ended up flipping back
 	   to the existing ldisc we have two references to it */
 
-	if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc)
+	if (tty->ldisc->ops->num != o_ldisc->ops->num && tty->ops->set_ldisc)
 		tty->ops->set_ldisc(tty);
 
-	tty_ldisc_put(o_ldisc.ops);
+	tty_ldisc_put(o_ldisc);
 
 	/*
-	 *	Allow ldisc referencing to occur as soon as the driver
-	 *	ldisc callback completes.
+	 *	Allow ldisc referencing to occur again
 	 */
 
 	tty_ldisc_enable(tty);
 	if (o_tty)
 		tty_ldisc_enable(o_tty);
 
-	/* Restart it in case no characters kick it off. Safe if
+	/* Restart the work queue in case no characters kick it off. Safe if
 	   already running */
 	if (work)
 		schedule_delayed_work(&tty->buf.work, 1);
+	if (o_work)
+		schedule_delayed_work(&o_tty->buf.work, 1);
+	mutex_unlock(&tty->ldisc_mutex);
 	return retval;
 }
 
+/**
+ *	tty_reset_termios	-	reset terminal state
+ *	@tty: tty to reset
+ *
+ *	Restore a terminal to the driver default state.
+ */
+
+static void tty_reset_termios(struct tty_struct *tty)
+{
+	mutex_lock(&tty->termios_mutex);
+	*tty->termios = tty->driver->init_termios;
+	tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+	tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
+	mutex_unlock(&tty->termios_mutex);
+}
+
+
+/**
+ *	tty_ldisc_reinit	-	reinitialise the tty ldisc
+ *	@tty: tty to reinit
+ *
+ *	Switch the tty back to N_TTY line discipline and leave the
+ *	ldisc state closed
+ */
+
+static void tty_ldisc_reinit(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld;
+
+	tty_ldisc_close(tty, tty->ldisc);
+	tty_ldisc_put(tty->ldisc);
+	tty->ldisc = NULL;
+	/*
+	 *	Switch the line discipline back
+	 */
+	ld = tty_ldisc_get(N_TTY);
+	BUG_ON(IS_ERR(ld));
+	tty_ldisc_assign(tty, ld);
+	tty_set_termios_ldisc(tty, N_TTY);
+}
+
+/**
+ *	tty_ldisc_hangup		-	hangup ldisc reset
+ *	@tty: tty being hung up
+ *
+ *	Some tty devices reset their termios when they receive a hangup
+ *	event. In that situation we must also switch back to N_TTY properly
+ *	before we reset the termios data.
+ *
+ *	Locking: We can take the ldisc mutex as the rest of the code is
+ *	careful to allow for this.
+ *
+ *	In the pty pair case this occurs in the close() path of the
+ *	tty itself so we must be careful about locking rules.
+ */
+
+void tty_ldisc_hangup(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld;
+
+	/*
+	 * FIXME! What are the locking issues here? This may me overdoing
+	 * things... This question is especially important now that we've
+	 * removed the irqlock.
+	 */
+	ld = tty_ldisc_ref(tty);
+	if (ld != NULL) {
+		/* We may have no line discipline at this point */
+		if (ld->ops->flush_buffer)
+			ld->ops->flush_buffer(tty);
+		tty_driver_flush_buffer(tty);
+		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
+		    ld->ops->write_wakeup)
+			ld->ops->write_wakeup(tty);
+		if (ld->ops->hangup)
+			ld->ops->hangup(tty);
+		tty_ldisc_deref(ld);
+	}
+	/*
+	 * FIXME: Once we trust the LDISC code better we can wait here for
+	 * ldisc completion and fix the driver call race
+	 */
+	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
+	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+	/*
+	 * Shutdown the current line discipline, and reset it to
+	 * N_TTY.
+	 */
+	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
+		/* Make sure the old ldisc is quiescent */
+		tty_ldisc_halt(tty);
+		flush_scheduled_work();
+
+		/* Avoid racing set_ldisc or tty_ldisc_release */
+		mutex_lock(&tty->ldisc_mutex);
+		if (tty->ldisc) {	/* Not yet closed */
+			/* Switch back to N_TTY */
+			tty_ldisc_reinit(tty);
+			/* At this point we have a closed ldisc and we want to
+			   reopen it. We could defer this to the next open but
+			   it means auditing a lot of other paths so this is
+			   a FIXME */
+			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
+			tty_ldisc_enable(tty);
+		}
+		mutex_unlock(&tty->ldisc_mutex);
+		tty_reset_termios(tty);
+	}
+}
 
 /**
  *	tty_ldisc_setup			-	open line discipline
@@ -610,24 +781,23 @@
  *	@o_tty: pair tty for pty/tty pairs
  *
  *	Called during the initial open of a tty/pty pair in order to set up the
- *	line discplines and bind them to the tty.
+ *	line disciplines and bind them to the tty. This has no locking issues
+ *	as the device isn't yet active.
  */
 
 int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
 {
-	struct tty_ldisc *ld = &tty->ldisc;
+	struct tty_ldisc *ld = tty->ldisc;
 	int retval;
 
-	if (ld->ops->open) {
-		retval = (ld->ops->open)(tty);
-		if (retval)
-			return retval;
-	}
-	if (o_tty && o_tty->ldisc.ops->open) {
-		retval = (o_tty->ldisc.ops->open)(o_tty);
+	retval = tty_ldisc_open(tty, ld);
+	if (retval)
+		return retval;
+
+	if (o_tty) {
+		retval = tty_ldisc_open(o_tty, o_tty->ldisc);
 		if (retval) {
-			if (ld->ops->close)
-				(ld->ops->close)(tty);
+			tty_ldisc_close(tty, ld);
 			return retval;
 		}
 		tty_ldisc_enable(o_tty);
@@ -635,71 +805,46 @@
 	tty_ldisc_enable(tty);
 	return 0;
 }
-
 /**
  *	tty_ldisc_release		-	release line discipline
  *	@tty: tty being shut down
  *	@o_tty: pair tty for pty/tty pairs
  *
- *	Called during the final close of a tty/pty pair in order to shut down the
- *	line discpline layer.
+ *	Called during the final close of a tty/pty pair in order to shut down
+ *	the line discpline layer. On exit the ldisc assigned is N_TTY and the
+ *	ldisc has not been opened.
  */
 
 void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 {
-	unsigned long flags;
-	struct tty_ldisc ld;
 	/*
 	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
 	 * kill any delayed work. As this is the final close it does not
 	 * race with the set_ldisc code path.
 	 */
-	clear_bit(TTY_LDISC, &tty->flags);
-	cancel_delayed_work(&tty->buf.work);
-
-	/*
-	 * Wait for ->hangup_work and ->buf.work handlers to terminate
-	 */
 
+	tty_ldisc_halt(tty);
 	flush_scheduled_work();
 
+	mutex_lock(&tty->ldisc_mutex);
 	/*
-	 * Wait for any short term users (we know they are just driver
-	 * side waiters as the file is closing so user count on the file
-	 * side is zero.
-	 */
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	while (tty->ldisc.refcount) {
-		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-		wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
-		spin_lock_irqsave(&tty_ldisc_lock, flags);
-	}
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	/*
-	 * Shutdown the current line discipline, and reset it to N_TTY.
-	 *
-	 * FIXME: this MUST get fixed for the new reflocking
+	 * Now kill off the ldisc
 	 */
-	if (tty->ldisc.ops->close)
-		(tty->ldisc.ops->close)(tty);
-	tty_ldisc_put(tty->ldisc.ops);
+	tty_ldisc_close(tty, tty->ldisc);
+	tty_ldisc_put(tty->ldisc);
+	/* Force an oops if we mess this up */
+	tty->ldisc = NULL;
 
-	/*
-	 *	Switch the line discipline back
-	 */
-	WARN_ON(tty_ldisc_get(N_TTY, &ld));
-	tty_ldisc_assign(tty, &ld);
+	/* Ensure the next open requests the N_TTY ldisc */
 	tty_set_termios_ldisc(tty, N_TTY);
-	if (o_tty) {
-		/* FIXME: could o_tty be in setldisc here ? */
-		clear_bit(TTY_LDISC, &o_tty->flags);
-		if (o_tty->ldisc.ops->close)
-			(o_tty->ldisc.ops->close)(o_tty);
-		tty_ldisc_put(o_tty->ldisc.ops);
-		WARN_ON(tty_ldisc_get(N_TTY, &ld));
-		tty_ldisc_assign(o_tty, &ld);
-		tty_set_termios_ldisc(o_tty, N_TTY);
-	}
+	mutex_unlock(&tty->ldisc_mutex);
+
+	/* This will need doing differently if we need to lock */
+	if (o_tty)
+		tty_ldisc_release(o_tty, NULL);
+
+	/* And the memory resources remaining (buffers, termios) will be
+	   disposed of when the kref hits zero */
 }
 
 /**
@@ -712,10 +857,10 @@
 
 void tty_ldisc_init(struct tty_struct *tty)
 {
-	struct tty_ldisc ld;
-	if (tty_ldisc_get(N_TTY, &ld) < 0)
+	struct tty_ldisc *ld = tty_ldisc_get(N_TTY);
+	if (IS_ERR(ld))
 		panic("n_tty: init_tty");
-	tty_ldisc_assign(tty, &ld);
+	tty_ldisc_assign(tty, ld);
 }
 
 void tty_ldisc_begin(void)
diff -druN linux-libre-2.6.30-gnu/drivers/char/tty_port.c linux-libre-2.6.31-gnu/drivers/char/tty_port.c
--- linux-libre-2.6.30-gnu/drivers/char/tty_port.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/tty_port.c	2009-09-09 18:13:59.000000000 -0400
@@ -137,7 +137,7 @@
 EXPORT_SYMBOL(tty_port_carrier_raised);
 
 /**
- *	tty_port_raise_dtr_rts	-	Riase DTR/RTS
+ *	tty_port_raise_dtr_rts	-	Raise DTR/RTS
  *	@port: tty port
  *
  *	Wrapper for the DTR/RTS raise logic. For the moment this is used
@@ -147,12 +147,28 @@
 
 void tty_port_raise_dtr_rts(struct tty_port *port)
 {
-	if (port->ops->raise_dtr_rts)
-		port->ops->raise_dtr_rts(port);
+	if (port->ops->dtr_rts)
+		port->ops->dtr_rts(port, 1);
 }
 EXPORT_SYMBOL(tty_port_raise_dtr_rts);
 
 /**
+ *	tty_port_lower_dtr_rts	-	Lower DTR/RTS
+ *	@port: tty port
+ *
+ *	Wrapper for the DTR/RTS raise logic. For the moment this is used
+ *	to hide some internal details. This will eventually become entirely
+ *	internal to the tty port.
+ */
+
+void tty_port_lower_dtr_rts(struct tty_port *port)
+{
+	if (port->ops->dtr_rts)
+		port->ops->dtr_rts(port, 0);
+}
+EXPORT_SYMBOL(tty_port_lower_dtr_rts);
+
+/**
  *	tty_port_block_til_ready	-	Waiting logic for tty open
  *	@port: the tty port being opened
  *	@tty: the tty device being bound
@@ -167,7 +183,7 @@
  *		- port flags and counts
  *
  *	The passed tty_port must implement the carrier_raised method if it can
- *	do carrier detect and the raise_dtr_rts method if it supports software
+ *	do carrier detect and the dtr_rts method if it supports software
  *	management of these lines. Note that the dtr/rts raise is done each
  *	iteration as a hangup may have previously dropped them while we wait.
  */
@@ -177,12 +193,13 @@
 {
 	int do_clocal = 0, retval;
 	unsigned long flags;
-	DECLARE_WAITQUEUE(wait, current);
+	DEFINE_WAIT(wait);
 	int cd;
 
 	/* block if port is in the process of being closed */
 	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&port->close_wait);
+		wait_event_interruptible(port->close_wait,
+				!(port->flags & ASYNC_CLOSING));
 		if (port->flags & ASYNC_HUP_NOTIFY)
 			return -EAGAIN;
 		else
@@ -205,7 +222,6 @@
 	   before the next open may complete */
 
 	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
 
 	/* The port lock protects the port counts */
 	spin_lock_irqsave(&port->lock, flags);
@@ -219,7 +235,7 @@
 		if (tty->termios->c_cflag & CBAUD)
 			tty_port_raise_dtr_rts(port);
 
-		set_current_state(TASK_INTERRUPTIBLE);
+		prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
 		/* Check for a hangup or uninitialised port. Return accordingly */
 		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
 			if (port->flags & ASYNC_HUP_NOTIFY)
@@ -240,8 +256,7 @@
 		}
 		schedule();
 	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
+	finish_wait(&port->open_wait, &wait);
 
 	/* Update counts. A parallel hangup will have set count to zero and
 	   we must not mess that up further */
@@ -252,7 +267,7 @@
 	if (retval == 0)
 		port->flags |= ASYNC_NORMAL_ACTIVE;
 	spin_unlock_irqrestore(&port->lock, flags);
-	return 0;
+	return retval;
 	
 }
 EXPORT_SYMBOL(tty_port_block_til_ready);
@@ -292,6 +307,17 @@
 	if (port->flags & ASYNC_INITIALIZED &&
 			port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, port->closing_wait);
+	if (port->drain_delay) {
+		unsigned int bps = tty_get_baud_rate(tty);
+		long timeout;
+
+		if (bps > 1200)
+			timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
+								HZ / 10);
+		else
+			timeout = 2 * HZ;
+		schedule_timeout_interruptible(timeout);
+	}
 	return 1;
 }
 EXPORT_SYMBOL(tty_port_close_start);
@@ -302,6 +328,9 @@
 
 	tty_ldisc_flush(tty);
 
+	if (tty->termios->c_cflag & HUPCL)
+		tty_port_lower_dtr_rts(port);
+
 	spin_lock_irqsave(&port->lock, flags);
 	tty->closing = 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/char/vc_screen.c linux-libre-2.6.31-gnu/drivers/char/vc_screen.c
--- linux-libre-2.6.30-gnu/drivers/char/vc_screen.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/vc_screen.c	2009-09-09 18:13:59.000000000 -0400
@@ -495,11 +495,15 @@
 
 int __init vcs_init(void)
 {
+	unsigned int i;
+
 	if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
 		panic("unable to get major %d for vcs device", VCS_MAJOR);
 	vc_class = class_create(THIS_MODULE, "vc");
 
 	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
 	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+	for (i = 0; i < MIN_NR_CONSOLES; i++)
+		vcs_make_sysfs(i);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/viotape.c linux-libre-2.6.31-gnu/drivers/char/viotape.c
--- linux-libre-2.6.30-gnu/drivers/char/viotape.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/viotape.c	2009-09-09 18:13:59.000000000 -0400
@@ -867,7 +867,7 @@
 	int j;
 	struct device_node *node = vdev->dev.archdata.of_node;
 
-	if (i > VIOTAPE_MAX_TAPE)
+	if (i >= VIOTAPE_MAX_TAPE)
 		return -ENODEV;
 	if (!node)
 		return -ENODEV;
diff -druN linux-libre-2.6.30-gnu/drivers/char/virtio_console.c linux-libre-2.6.31-gnu/drivers/char/virtio_console.c
--- linux-libre-2.6.30-gnu/drivers/char/virtio_console.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/virtio_console.c	2009-09-09 18:13:59.000000000 -0400
@@ -188,6 +188,9 @@
  * Finally we put our input buffer in the input queue, ready to receive. */
 static int __devinit virtcons_probe(struct virtio_device *dev)
 {
+	vq_callback_t *callbacks[] = { hvc_handle_input, NULL};
+	const char *names[] = { "input", "output" };
+	struct virtqueue *vqs[2];
 	int err;
 
 	vdev = dev;
@@ -199,20 +202,15 @@
 		goto fail;
 	}
 
-	/* Find the input queue. */
+	/* Find the queues. */
 	/* FIXME: This is why we want to wean off hvc: we do nothing
 	 * when input comes in. */
-	in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input);
-	if (IS_ERR(in_vq)) {
-		err = PTR_ERR(in_vq);
+	err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names);
+	if (err)
 		goto free;
-	}
 
-	out_vq = vdev->config->find_vq(vdev, 1, NULL);
-	if (IS_ERR(out_vq)) {
-		err = PTR_ERR(out_vq);
-		goto free_in_vq;
-	}
+	in_vq = vqs[0];
+	out_vq = vqs[1];
 
 	/* Start using the new console output. */
 	virtio_cons.get_chars = get_chars;
@@ -233,17 +231,15 @@
 	hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE);
 	if (IS_ERR(hvc)) {
 		err = PTR_ERR(hvc);
-		goto free_out_vq;
+		goto free_vqs;
 	}
 
 	/* Register the input buffer the first time. */
 	add_inbuf();
 	return 0;
 
-free_out_vq:
-	vdev->config->del_vq(out_vq);
-free_in_vq:
-	vdev->config->del_vq(in_vq);
+free_vqs:
+	vdev->config->del_vqs(vdev);
 free:
 	kfree(inbuf);
 fail:
diff -druN linux-libre-2.6.30-gnu/drivers/char/vr41xx_giu.c linux-libre-2.6.31-gnu/drivers/char/vr41xx_giu.c
--- linux-libre-2.6.30-gnu/drivers/char/vr41xx_giu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/vr41xx_giu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,680 +0,0 @@
-/*
- *  Driver for NEC VR4100 series General-purpose I/O Unit.
- *
- *  Copyright (C) 2002 MontaVista Software Inc.
- *	Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-#include <asm/vr41xx/giu.h>
-#include <asm/vr41xx/irq.h>
-#include <asm/vr41xx/vr41xx.h>
-
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
-MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
-MODULE_LICENSE("GPL");
-
-static int major;	/* default is dynamic major device number */
-module_param(major, int, 0);
-MODULE_PARM_DESC(major, "Major device number");
-
-#define GIUIOSELL	0x00
-#define GIUIOSELH	0x02
-#define GIUPIODL	0x04
-#define GIUPIODH	0x06
-#define GIUINTSTATL	0x08
-#define GIUINTSTATH	0x0a
-#define GIUINTENL	0x0c
-#define GIUINTENH	0x0e
-#define GIUINTTYPL	0x10
-#define GIUINTTYPH	0x12
-#define GIUINTALSELL	0x14
-#define GIUINTALSELH	0x16
-#define GIUINTHTSELL	0x18
-#define GIUINTHTSELH	0x1a
-#define GIUPODATL	0x1c
-#define GIUPODATEN	0x1c
-#define GIUPODATH	0x1e
- #define PIOEN0		0x0100
- #define PIOEN1		0x0200
-#define GIUPODAT	0x1e
-#define GIUFEDGEINHL	0x20
-#define GIUFEDGEINHH	0x22
-#define GIUREDGEINHL	0x24
-#define GIUREDGEINHH	0x26
-
-#define GIUUSEUPDN	0x1e0
-#define GIUTERMUPDN	0x1e2
-
-#define GPIO_HAS_PULLUPDOWN_IO		0x0001
-#define GPIO_HAS_OUTPUT_ENABLE		0x0002
-#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
-
-static spinlock_t giu_lock;
-static unsigned long giu_flags;
-static unsigned int giu_nr_pins;
-
-static void __iomem *giu_base;
-
-#define giu_read(offset)		readw(giu_base + (offset))
-#define giu_write(offset, value)	writew((value), giu_base + (offset))
-
-#define GPIO_PIN_OF_IRQ(irq)	((irq) - GIU_IRQ_BASE)
-#define GIUINT_HIGH_OFFSET	16
-#define GIUINT_HIGH_MAX		32
-
-static inline uint16_t giu_set(uint16_t offset, uint16_t set)
-{
-	uint16_t data;
-
-	data = giu_read(offset);
-	data |= set;
-	giu_write(offset, data);
-
-	return data;
-}
-
-static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
-{
-	uint16_t data;
-
-	data = giu_read(offset);
-	data &= ~clear;
-	giu_write(offset, data);
-
-	return data;
-}
-
-static void ack_giuint_low(unsigned int irq)
-{
-	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-static void mask_giuint_low(unsigned int irq)
-{
-	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-static void mask_ack_giuint_low(unsigned int irq)
-{
-	unsigned int pin;
-
-	pin = GPIO_PIN_OF_IRQ(irq);
-	giu_clear(GIUINTENL, 1 << pin);
-	giu_write(GIUINTSTATL, 1 << pin);
-}
-
-static void unmask_giuint_low(unsigned int irq)
-{
-	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
-}
-
-static struct irq_chip giuint_low_irq_chip = {
-	.name		= "GIUINTL",
-	.ack		= ack_giuint_low,
-	.mask		= mask_giuint_low,
-	.mask_ack	= mask_ack_giuint_low,
-	.unmask		= unmask_giuint_low,
-};
-
-static void ack_giuint_high(unsigned int irq)
-{
-	giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_giuint_high(unsigned int irq)
-{
-	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-static void mask_ack_giuint_high(unsigned int irq)
-{
-	unsigned int pin;
-
-	pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
-	giu_clear(GIUINTENH, 1 << pin);
-	giu_write(GIUINTSTATH, 1 << pin);
-}
-
-static void unmask_giuint_high(unsigned int irq)
-{
-	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
-}
-
-static struct irq_chip giuint_high_irq_chip = {
-	.name		= "GIUINTH",
-	.ack		= ack_giuint_high,
-	.mask		= mask_giuint_high,
-	.mask_ack	= mask_ack_giuint_high,
-	.unmask		= unmask_giuint_high,
-};
-
-static int giu_get_irq(unsigned int irq)
-{
-	uint16_t pendl, pendh, maskl, maskh;
-	int i;
-
-	pendl = giu_read(GIUINTSTATL);
-	pendh = giu_read(GIUINTSTATH);
-	maskl = giu_read(GIUINTENL);
-	maskh = giu_read(GIUINTENH);
-
-	maskl &= pendl;
-	maskh &= pendh;
-
-	if (maskl) {
-		for (i = 0; i < 16; i++) {
-			if (maskl & (1 << i))
-				return GIU_IRQ(i);
-		}
-	} else if (maskh) {
-		for (i = 0; i < 16; i++) {
-			if (maskh & (1 << i))
-				return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
-		}
-	}
-
-	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
-	       maskl, pendl, maskh, pendh);
-
-	atomic_inc(&irq_err_count);
-
-	return -EINVAL;
-}
-
-void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
-{
-	uint16_t mask;
-
-	if (pin < GIUINT_HIGH_OFFSET) {
-		mask = 1 << pin;
-		if (trigger != IRQ_TRIGGER_LEVEL) {
-        		giu_set(GIUINTTYPL, mask);
-			if (signal == IRQ_SIGNAL_HOLD)
-				giu_set(GIUINTHTSELL, mask);
-			else
-				giu_clear(GIUINTHTSELL, mask);
-			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-				switch (trigger) {
-				case IRQ_TRIGGER_EDGE_FALLING:
-					giu_set(GIUFEDGEINHL, mask);
-					giu_clear(GIUREDGEINHL, mask);
-					break;
-				case IRQ_TRIGGER_EDGE_RISING:
-					giu_clear(GIUFEDGEINHL, mask);
-					giu_set(GIUREDGEINHL, mask);
-					break;
-				default:
-					giu_set(GIUFEDGEINHL, mask);
-					giu_set(GIUREDGEINHL, mask);
-					break;
-				}
-			}
-			set_irq_chip_and_handler(GIU_IRQ(pin),
-			                         &giuint_low_irq_chip,
-			                         handle_edge_irq);
-		} else {
-			giu_clear(GIUINTTYPL, mask);
-			giu_clear(GIUINTHTSELL, mask);
-			set_irq_chip_and_handler(GIU_IRQ(pin),
-			                         &giuint_low_irq_chip,
-			                         handle_level_irq);
-		}
-		giu_write(GIUINTSTATL, mask);
-	} else if (pin < GIUINT_HIGH_MAX) {
-		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-		if (trigger != IRQ_TRIGGER_LEVEL) {
-			giu_set(GIUINTTYPH, mask);
-			if (signal == IRQ_SIGNAL_HOLD)
-				giu_set(GIUINTHTSELH, mask);
-			else
-				giu_clear(GIUINTHTSELH, mask);
-			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
-				switch (trigger) {
-				case IRQ_TRIGGER_EDGE_FALLING:
-					giu_set(GIUFEDGEINHH, mask);
-					giu_clear(GIUREDGEINHH, mask);
-					break;
-				case IRQ_TRIGGER_EDGE_RISING:
-					giu_clear(GIUFEDGEINHH, mask);
-					giu_set(GIUREDGEINHH, mask);
-					break;
-				default:
-					giu_set(GIUFEDGEINHH, mask);
-					giu_set(GIUREDGEINHH, mask);
-					break;
-				}
-			}
-			set_irq_chip_and_handler(GIU_IRQ(pin),
-			                         &giuint_high_irq_chip,
-			                         handle_edge_irq);
-		} else {
-			giu_clear(GIUINTTYPH, mask);
-			giu_clear(GIUINTHTSELH, mask);
-			set_irq_chip_and_handler(GIU_IRQ(pin),
-			                         &giuint_high_irq_chip,
-			                         handle_level_irq);
-		}
-		giu_write(GIUINTSTATH, mask);
-	}
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
-
-void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
-{
-	uint16_t mask;
-
-	if (pin < GIUINT_HIGH_OFFSET) {
-		mask = 1 << pin;
-		if (level == IRQ_LEVEL_HIGH)
-			giu_set(GIUINTALSELL, mask);
-		else
-			giu_clear(GIUINTALSELL, mask);
-		giu_write(GIUINTSTATL, mask);
-	} else if (pin < GIUINT_HIGH_MAX) {
-		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
-		if (level == IRQ_LEVEL_HIGH)
-			giu_set(GIUINTALSELH, mask);
-		else
-			giu_clear(GIUINTALSELH, mask);
-		giu_write(GIUINTSTATH, mask);
-	}
-}
-EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
-
-gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
-{
-	uint16_t reg, mask;
-
-	if (pin >= giu_nr_pins)
-		return GPIO_DATA_INVAL;
-
-	if (pin < 16) {
-		reg = giu_read(GIUPIODL);
-		mask = (uint16_t)1 << pin;
-	} else if (pin < 32) {
-		reg = giu_read(GIUPIODH);
-		mask = (uint16_t)1 << (pin - 16);
-	} else if (pin < 48) {
-		reg = giu_read(GIUPODATL);
-		mask = (uint16_t)1 << (pin - 32);
-	} else {
-		reg = giu_read(GIUPODATH);
-		mask = (uint16_t)1 << (pin - 48);
-	}
-
-	if (reg & mask)
-		return GPIO_DATA_HIGH;
-
-	return GPIO_DATA_LOW;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
-
-int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
-{
-	uint16_t offset, mask, reg;
-	unsigned long flags;
-
-	if (pin >= giu_nr_pins)
-		return -EINVAL;
-
-	if (pin < 16) {
-		offset = GIUPIODL;
-		mask = (uint16_t)1 << pin;
-	} else if (pin < 32) {
-		offset = GIUPIODH;
-		mask = (uint16_t)1 << (pin - 16);
-	} else if (pin < 48) {
-		offset = GIUPODATL;
-		mask = (uint16_t)1 << (pin - 32);
-	} else {
-		offset = GIUPODATH;
-		mask = (uint16_t)1 << (pin - 48);
-	}
-
-	spin_lock_irqsave(&giu_lock, flags);
-
-	reg = giu_read(offset);
-	if (data == GPIO_DATA_HIGH)
-		reg |= mask;
-	else
-		reg &= ~mask;
-	giu_write(offset, reg);
-
-	spin_unlock_irqrestore(&giu_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
-
-int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
-{
-	uint16_t offset, mask, reg;
-	unsigned long flags;
-
-	if (pin >= giu_nr_pins)
-		return -EINVAL;
-
-	if (pin < 16) {
-		offset = GIUIOSELL;
-		mask = (uint16_t)1 << pin;
-	} else if (pin < 32) {
-		offset = GIUIOSELH;
-		mask = (uint16_t)1 << (pin - 16);
-	} else {
-		if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
-			offset = GIUPODATEN;
-			mask = (uint16_t)1 << (pin - 32);
-		} else {
-			switch (pin) {
-			case 48:
-				offset = GIUPODATH;
-				mask = PIOEN0;
-				break;
-			case 49:
-				offset = GIUPODATH;
-				mask = PIOEN1;
-				break;
-			default:
-				return -EINVAL;
-			}
-		}
-	}
-
-	spin_lock_irqsave(&giu_lock, flags);
-
-	reg = giu_read(offset);
-	if (dir == GPIO_OUTPUT)
-		reg |= mask;
-	else
-		reg &= ~mask;
-	giu_write(offset, reg);
-
-	spin_unlock_irqrestore(&giu_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
-
-int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
-{
-	uint16_t reg, mask;
-	unsigned long flags;
-
-	if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
-		return -EPERM;
-
-	if (pin >= 15)
-		return -EINVAL;
-
-	mask = (uint16_t)1 << pin;
-
-	spin_lock_irqsave(&giu_lock, flags);
-
-	if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
-		reg = giu_read(GIUTERMUPDN);
-		if (pull == GPIO_PULL_UP)
-			reg |= mask;
-		else
-			reg &= ~mask;
-		giu_write(GIUTERMUPDN, reg);
-
-		reg = giu_read(GIUUSEUPDN);
-		reg |= mask;
-		giu_write(GIUUSEUPDN, reg);
-	} else {
-		reg = giu_read(GIUUSEUPDN);
-		reg &= ~mask;
-		giu_write(GIUUSEUPDN, reg);
-	}
-
-	spin_unlock_irqrestore(&giu_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
-
-static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
-                         loff_t *ppos)
-{
-	unsigned int pin;
-	char value = '0';
-
-	pin = iminor(file->f_path.dentry->d_inode);
-	if (pin >= giu_nr_pins)
-		return -EBADF;
-
-	if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
-		value = '1';
-
-	if (len <= 0)
-		return -EFAULT;
-
-	if (put_user(value, buf))
-		return -EFAULT;
-
-	return 1;
-}
-
-static ssize_t gpio_write(struct file *file, const char __user *data,
-                          size_t len, loff_t *ppos)
-{
-	unsigned int pin;
-	size_t i;
-	char c;
-	int retval = 0;
-
-	pin = iminor(file->f_path.dentry->d_inode);
-	if (pin >= giu_nr_pins)
-		return -EBADF;
-
-	for (i = 0; i < len; i++) {
-		if (get_user(c, data + i))
-			return -EFAULT;
-
-		switch (c) {
-		case '0':
-			retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
-			break;
-		case '1':
-			retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
-			break;
-		case 'D':
-			printk(KERN_INFO "GPIO%d: pull down\n", pin);
-			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
-			break;
-		case 'd':
-			printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
-			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
-			break;
-		case 'I':
-			printk(KERN_INFO "GPIO%d: input\n", pin);
-			retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
-			break;
-		case 'O':
-			printk(KERN_INFO "GPIO%d: output\n", pin);
-			retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
-			break;
-		case 'o':
-			printk(KERN_INFO "GPIO%d: output disable\n", pin);
-			retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
-			break;
-		case 'P':
-			printk(KERN_INFO "GPIO%d: pull up\n", pin);
-			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
-			break;
-		case 'p':
-			printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
-			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
-			break;
-		default:
-			break;
-		}
-
-		if (retval < 0)
-			break;
-	}
-
-	return i;
-}
-
-static int gpio_open(struct inode *inode, struct file *file)
-{
-	unsigned int pin;
-
-	cycle_kernel_lock();
-	pin = iminor(inode);
-	if (pin >= giu_nr_pins)
-		return -EBADF;
-
-	return nonseekable_open(inode, file);
-}
-
-static int gpio_release(struct inode *inode, struct file *file)
-{
-	unsigned int pin;
-
-	pin = iminor(inode);
-	if (pin >= giu_nr_pins)
-		return -EBADF;
-
-	return 0;
-}
-
-static const struct file_operations gpio_fops = {
-	.owner		= THIS_MODULE,
-	.read		= gpio_read,
-	.write		= gpio_write,
-	.open		= gpio_open,
-	.release	= gpio_release,
-};
-
-static int __devinit giu_probe(struct platform_device *dev)
-{
-	struct resource *res;
-	unsigned int trigger, i, pin;
-	struct irq_chip *chip;
-	int irq, retval;
-
-	switch (dev->id) {
-	case GPIO_50PINS_PULLUPDOWN:
-		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
-		giu_nr_pins = 50;
-		break;
-	case GPIO_36PINS:
-		giu_nr_pins = 36;
-		break;
-	case GPIO_48PINS_EDGE_SELECT:
-		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
-		giu_nr_pins = 48;
-		break;
-	default:
-		printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
-		return -ENODEV;
-	}
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -EBUSY;
-
-	giu_base = ioremap(res->start, res->end - res->start + 1);
-	if (!giu_base)
-		return -ENOMEM;
-
-	retval = register_chrdev(major, "GIU", &gpio_fops);
-	if (retval < 0) {
-		iounmap(giu_base);
-		giu_base = NULL;
-		return retval;
-	}
-
-	if (major == 0) {
-		major = retval;
-		printk(KERN_INFO "GIU: major number %d\n", major);
-	}
-
-	spin_lock_init(&giu_lock);
-
-	giu_write(GIUINTENL, 0);
-	giu_write(GIUINTENH, 0);
-
-	trigger = giu_read(GIUINTTYPH) << 16;
-	trigger |= giu_read(GIUINTTYPL);
-	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
-		pin = GPIO_PIN_OF_IRQ(i);
-		if (pin < GIUINT_HIGH_OFFSET)
-			chip = &giuint_low_irq_chip;
-		else
-			chip = &giuint_high_irq_chip;
-
-		if (trigger & (1 << pin))
-			set_irq_chip_and_handler(i, chip, handle_edge_irq);
-		else
-			set_irq_chip_and_handler(i, chip, handle_level_irq);
-
-	}
-
-	irq = platform_get_irq(dev, 0);
-	if (irq < 0 || irq >= nr_irqs)
-		return -EBUSY;
-
-	return cascade_irq(irq, giu_get_irq);
-}
-
-static int __devexit giu_remove(struct platform_device *dev)
-{
-	if (giu_base) {
-		iounmap(giu_base);
-		giu_base = NULL;
-	}
-
-	return 0;
-}
-
-static struct platform_driver giu_device_driver = {
-	.probe		= giu_probe,
-	.remove		= __devexit_p(giu_remove),
-	.driver		= {
-		.name	= "GIU",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init vr41xx_giu_init(void)
-{
-	return platform_driver_register(&giu_device_driver);
-}
-
-static void __exit vr41xx_giu_exit(void)
-{
-	platform_driver_unregister(&giu_device_driver);
-}
-
-module_init(vr41xx_giu_init);
-module_exit(vr41xx_giu_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/char/vt.c linux-libre-2.6.31-gnu/drivers/char/vt.c
--- linux-libre-2.6.30-gnu/drivers/char/vt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/vt.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,13 +89,13 @@
 #include <linux/mutex.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
+#include <linux/smp_lock.h>
 #include <linux/tiocl.h>
 #include <linux/kbd_kern.h>
 #include <linux/consolemap.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
-#include <linux/bootmem.h>
 #include <linux/pm.h>
 #include <linux/font.h>
 #include <linux/bitops.h>
@@ -172,8 +172,9 @@
 int console_blanked;
 
 static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
-static int blankinterval = 10*60*HZ;
 static int vesa_off_interval;
+static int blankinterval = 10*60;
+core_param(consoleblank, blankinterval, int, 0444);
 
 static DECLARE_WORK(console_work, console_callback);
 
@@ -769,14 +770,12 @@
 	    visual_init(vc, currcons, 1);
 	    if (!*vc->vc_uni_pagedir_loc)
 		con_set_default_unimap(vc);
-	    if (!vc->vc_kmalloced)
-		vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+	    vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
 	    if (!vc->vc_screenbuf) {
 		kfree(vc);
 		vc_cons[currcons].d = NULL;
 		return -ENOMEM;
 	    }
-	    vc->vc_kmalloced = 1;
 	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
 	    vcs_make_sysfs(currcons);
 	    atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
@@ -912,10 +911,8 @@
 	if (new_scr_end > new_origin)
 		scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
 			    new_scr_end - new_origin);
-	if (vc->vc_kmalloced)
-		kfree(vc->vc_screenbuf);
+	kfree(vc->vc_screenbuf);
 	vc->vc_screenbuf = newscreen;
-	vc->vc_kmalloced = 1;
 	vc->vc_screenbuf_size = new_screen_size;
 	set_origin(vc);
 
@@ -994,8 +991,7 @@
 		vc->vc_sw->con_deinit(vc);
 		put_pid(vc->vt_pid);
 		module_put(vc->vc_sw->owner);
-		if (vc->vc_kmalloced)
-			kfree(vc->vc_screenbuf);
+		kfree(vc->vc_screenbuf);
 		if (currcons >= MIN_NR_CONSOLES)
 			kfree(vc);
 		vc_cons[currcons].d = NULL;
@@ -1486,7 +1482,7 @@
 			update_attr(vc);
 			break;
 		case 9:	/* set blanking interval */
-			blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
+			blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60;
 			poke_blanked_console();
 			break;
 		case 10: /* set bell frequency in Hz */
@@ -2872,18 +2868,14 @@
 
 	if (blankinterval) {
 		blank_state = blank_normal_wait;
-		mod_timer(&console_timer, jiffies + blankinterval);
+		mod_timer(&console_timer, jiffies + (blankinterval * HZ));
 	}
 
-	/*
-	 * kmalloc is not running yet - we use the bootmem allocator.
-	 */
 	for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
-		vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
+		vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
 		INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
 		visual_init(vc, currcons, 1);
-		vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
-		vc->vc_kmalloced = 0;
+		vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
 		vc_init(vc, vc->vc_rows, vc->vc_cols,
 			currcons || !vc->vc_sw->con_save_screen);
 	}
@@ -3681,7 +3673,7 @@
 		return; /* but leave console_blanked != 0 */
 
 	if (blankinterval) {
-		mod_timer(&console_timer, jiffies + blankinterval);
+		mod_timer(&console_timer, jiffies + (blankinterval * HZ));
 		blank_state = blank_normal_wait;
 	}
 
@@ -3715,7 +3707,7 @@
 static void blank_screen_t(unsigned long dummy)
 {
 	if (unlikely(!keventd_up())) {
-		mod_timer(&console_timer, jiffies + blankinterval);
+		mod_timer(&console_timer, jiffies + (blankinterval * HZ));
 		return;
 	}
 	blank_timer_expired = 1;
@@ -3745,7 +3737,7 @@
 	if (console_blanked)
 		unblank_screen();
 	else if (blankinterval) {
-		mod_timer(&console_timer, jiffies + blankinterval);
+		mod_timer(&console_timer, jiffies + (blankinterval * HZ));
 		blank_state = blank_normal_wait;
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/char/vt_ioctl.c linux-libre-2.6.31-gnu/drivers/char/vt_ioctl.c
--- linux-libre-2.6.30-gnu/drivers/char/vt_ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/char/vt_ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/console.h>
 #include <linux/consolemap.h>
 #include <linux/signal.h>
+#include <linux/smp_lock.h>
 #include <linux/timex.h>
 
 #include <asm/io.h>
@@ -396,7 +397,8 @@
 	kbd = kbd_table + console;
 	switch (cmd) {
 	case TIOCLINUX:
-		return tioclinux(tty, arg);
+		ret = tioclinux(tty, arg);
+		break;
 	case KIOCSOUND:
 		if (!perm)
 			goto eperm;
diff -druN linux-libre-2.6.30-gnu/drivers/clocksource/acpi_pm.c linux-libre-2.6.31-gnu/drivers/clocksource/acpi_pm.c
--- linux-libre-2.6.30-gnu/drivers/clocksource/acpi_pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/clocksource/acpi_pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 
 #include <linux/acpi_pmtmr.h>
 #include <linux/clocksource.h>
+#include <linux/timex.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pci.h>
diff -druN linux-libre-2.6.30-gnu/drivers/clocksource/Makefile linux-libre-2.6.31-gnu/drivers/clocksource/Makefile
--- linux-libre-2.6.30-gnu/drivers/clocksource/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/clocksource/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,3 +3,5 @@
 obj-$(CONFIG_X86_PM_TIMER)	+= acpi_pm.o
 obj-$(CONFIG_SCx200HR_TIMER)	+= scx200_hrt.o
 obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
+obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
+obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
diff -druN linux-libre-2.6.30-gnu/drivers/clocksource/sh_cmt.c linux-libre-2.6.31-gnu/drivers/clocksource/sh_cmt.c
--- linux-libre-2.6.30-gnu/drivers/clocksource/sh_cmt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/clocksource/sh_cmt.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/bootmem.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
@@ -29,7 +28,7 @@
 #include <linux/err.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
-#include <linux/sh_cmt.h>
+#include <linux/sh_timer.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
@@ -41,12 +40,14 @@
 	struct platform_device *pdev;
 
 	unsigned long flags;
+	unsigned long flags_suspend;
 	unsigned long match_value;
 	unsigned long next_match_value;
 	unsigned long max_match_value;
 	unsigned long rate;
 	spinlock_t lock;
 	struct clock_event_device ced;
+	struct clocksource cs;
 	unsigned long total_cycles;
 };
 
@@ -59,7 +60,7 @@
 
 static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
 {
-	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	void __iomem *base = p->mapbase;
 	unsigned long offs;
 
@@ -83,7 +84,7 @@
 static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
 				unsigned long value)
 {
-	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	void __iomem *base = p->mapbase;
 	unsigned long offs;
 
@@ -110,23 +111,28 @@
 					int *has_wrapped)
 {
 	unsigned long v1, v2, v3;
+	int o1, o2;
+
+	o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
 
 	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
 	do {
+		o2 = o1;
 		v1 = sh_cmt_read(p, CMCNT);
 		v2 = sh_cmt_read(p, CMCNT);
 		v3 = sh_cmt_read(p, CMCNT);
-	} while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
-			  || (v3 > v1 && v3 < v2)));
+		o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
+			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
 
-	*has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+	*has_wrapped = o1;
 	return v2;
 }
 
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 {
-	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -144,7 +150,7 @@
 
 static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
 {
-	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	int ret;
 
 	/* enable clock */
@@ -153,16 +159,18 @@
 		pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk);
 		return ret;
 	}
-	*rate = clk_get_rate(p->clk) / 8;
 
 	/* make sure channel is disabled */
 	sh_cmt_start_stop_ch(p, 0);
 
 	/* configure channel, periodic mode and maximum timeout */
-	if (p->width == 16)
-		sh_cmt_write(p, CMCSR, 0);
-	else
+	if (p->width == 16) {
+		*rate = clk_get_rate(p->clk) / 512;
+		sh_cmt_write(p, CMCSR, 0x43);
+	} else {
+		*rate = clk_get_rate(p->clk) / 8;
 		sh_cmt_write(p, CMCSR, 0x01a4);
+	}
 
 	sh_cmt_write(p, CMCOR, 0xffffffff);
 	sh_cmt_write(p, CMCNT, 0);
@@ -177,6 +185,9 @@
 	/* disable channel */
 	sh_cmt_start_stop_ch(p, 0);
 
+	/* disable interrupts in CMT block */
+	sh_cmt_write(p, CMCSR, 0);
+
 	/* stop clock */
 	clk_disable(p->clk);
 }
@@ -376,6 +387,68 @@
 	spin_unlock_irqrestore(&p->lock, flags);
 }
 
+static struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs)
+{
+	return container_of(cs, struct sh_cmt_priv, cs);
+}
+
+static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
+{
+	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+	unsigned long flags, raw;
+	unsigned long value;
+	int has_wrapped;
+
+	spin_lock_irqsave(&p->lock, flags);
+	value = p->total_cycles;
+	raw = sh_cmt_get_counter(p, &has_wrapped);
+
+	if (unlikely(has_wrapped))
+		raw += p->match_value;
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	return value + raw;
+}
+
+static int sh_cmt_clocksource_enable(struct clocksource *cs)
+{
+	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+	int ret;
+
+	p->total_cycles = 0;
+
+	ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
+	if (ret)
+		return ret;
+
+	/* TODO: calculate good shift from rate and counter bit width */
+	cs->shift = 0;
+	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+	return 0;
+}
+
+static void sh_cmt_clocksource_disable(struct clocksource *cs)
+{
+	sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
+}
+
+static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
+				       char *name, unsigned long rating)
+{
+	struct clocksource *cs = &p->cs;
+
+	cs->name = name;
+	cs->rating = rating;
+	cs->read = sh_cmt_clocksource_read;
+	cs->enable = sh_cmt_clocksource_enable;
+	cs->disable = sh_cmt_clocksource_disable;
+	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
+	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+	pr_info("sh_cmt: %s used as clock source\n", cs->name);
+	clocksource_register(cs);
+	return 0;
+}
+
 static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
 {
 	return container_of(ced, struct sh_cmt_priv, ced);
@@ -468,9 +541,9 @@
 	clockevents_register_device(ced);
 }
 
-int sh_cmt_register(struct sh_cmt_priv *p, char *name,
-		    unsigned long clockevent_rating,
-		    unsigned long clocksource_rating)
+static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
+			   unsigned long clockevent_rating,
+			   unsigned long clocksource_rating)
 {
 	if (p->width == (sizeof(p->max_match_value) * 8))
 		p->max_match_value = ~0;
@@ -483,12 +556,15 @@
 	if (clockevent_rating)
 		sh_cmt_register_clockevent(p, name, clockevent_rating);
 
+	if (clocksource_rating)
+		sh_cmt_register_clocksource(p, name, clocksource_rating);
+
 	return 0;
 }
 
 static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 {
-	struct sh_cmt_config *cfg = pdev->dev.platform_data;
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
 	int irq, ret;
 	ret = -ENXIO;
@@ -527,7 +603,6 @@
 	p->irqaction.handler = sh_cmt_interrupt;
 	p->irqaction.dev_id = p;
 	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
-	p->irqaction.mask = CPU_MASK_NONE;
 	ret = setup_irq(irq, &p->irqaction);
 	if (ret) {
 		pr_err("sh_cmt: failed to request irq %d\n", irq);
@@ -545,7 +620,7 @@
 	if (resource_size(res) == 6) {
 		p->width = 16;
 		p->overflow_bit = 0x80;
-		p->clear_bits = ~0xc0;
+		p->clear_bits = ~0x80;
 	} else {
 		p->width = 32;
 		p->overflow_bit = 0x8000;
@@ -566,8 +641,14 @@
 static int __devinit sh_cmt_probe(struct platform_device *pdev)
 {
 	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
+	if (p) {
+		pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name);
+		return 0;
+	}
+
 	p = kmalloc(sizeof(*p), GFP_KERNEL);
 	if (p == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
@@ -577,7 +658,6 @@
 	ret = sh_cmt_setup(p, pdev);
 	if (ret) {
 		kfree(p);
-
 		platform_set_drvdata(pdev, NULL);
 	}
 	return ret;
@@ -588,11 +668,38 @@
 	return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
+static int sh_cmt_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+
+	/* save flag state and stop CMT channel */
+	p->flags_suspend = p->flags;
+	sh_cmt_stop(p, p->flags);
+	return 0;
+}
+
+static int sh_cmt_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+
+	/* start CMT channel from saved state */
+	sh_cmt_start(p, p->flags_suspend);
+	return 0;
+}
+
+static struct dev_pm_ops sh_cmt_dev_pm_ops = {
+	.suspend = sh_cmt_suspend,
+	.resume = sh_cmt_resume,
+};
+
 static struct platform_driver sh_cmt_device_driver = {
 	.probe		= sh_cmt_probe,
 	.remove		= __devexit_p(sh_cmt_remove),
 	.driver		= {
 		.name	= "sh_cmt",
+		.pm	= &sh_cmt_dev_pm_ops,
 	}
 };
 
@@ -606,6 +713,7 @@
 	platform_driver_unregister(&sh_cmt_device_driver);
 }
 
+early_platform_init("earlytimer", &sh_cmt_device_driver);
 module_init(sh_cmt_init);
 module_exit(sh_cmt_exit);
 
diff -druN linux-libre-2.6.30-gnu/drivers/clocksource/sh_mtu2.c linux-libre-2.6.31-gnu/drivers/clocksource/sh_mtu2.c
--- linux-libre-2.6.30-gnu/drivers/clocksource/sh_mtu2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/clocksource/sh_mtu2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,356 @@
+/*
+ * SuperH Timer Support - MTU2
+ *
+ *  Copyright (C) 2009 Magnus Damm
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clockchips.h>
+#include <linux/sh_timer.h>
+
+struct sh_mtu2_priv {
+	void __iomem *mapbase;
+	struct clk *clk;
+	struct irqaction irqaction;
+	struct platform_device *pdev;
+	unsigned long rate;
+	unsigned long periodic;
+	struct clock_event_device ced;
+};
+
+static DEFINE_SPINLOCK(sh_mtu2_lock);
+
+#define TSTR -1 /* shared register */
+#define TCR  0 /* channel register */
+#define TMDR 1 /* channel register */
+#define TIOR 2 /* channel register */
+#define TIER 3 /* channel register */
+#define TSR  4 /* channel register */
+#define TCNT 5 /* channel register */
+#define TGR  6 /* channel register */
+
+static unsigned long mtu2_reg_offs[] = {
+	[TCR] = 0,
+	[TMDR] = 1,
+	[TIOR] = 2,
+	[TIER] = 4,
+	[TSR] = 5,
+	[TCNT] = 6,
+	[TGR] = 8,
+};
+
+static inline unsigned long sh_mtu2_read(struct sh_mtu2_priv *p, int reg_nr)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs;
+
+	if (reg_nr == TSTR)
+		return ioread8(base + cfg->channel_offset);
+
+	offs = mtu2_reg_offs[reg_nr];
+
+	if ((reg_nr == TCNT) || (reg_nr == TGR))
+		return ioread16(base + offs);
+	else
+		return ioread8(base + offs);
+}
+
+static inline void sh_mtu2_write(struct sh_mtu2_priv *p, int reg_nr,
+				unsigned long value)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs;
+
+	if (reg_nr == TSTR) {
+		iowrite8(value, base + cfg->channel_offset);
+		return;
+	}
+
+	offs = mtu2_reg_offs[reg_nr];
+
+	if ((reg_nr == TCNT) || (reg_nr == TGR))
+		iowrite16(value, base + offs);
+	else
+		iowrite8(value, base + offs);
+}
+
+static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	unsigned long flags, value;
+
+	/* start stop register shared by multiple timer channels */
+	spin_lock_irqsave(&sh_mtu2_lock, flags);
+	value = sh_mtu2_read(p, TSTR);
+
+	if (start)
+		value |= 1 << cfg->timer_bit;
+	else
+		value &= ~(1 << cfg->timer_bit);
+
+	sh_mtu2_write(p, TSTR, value);
+	spin_unlock_irqrestore(&sh_mtu2_lock, flags);
+}
+
+static int sh_mtu2_enable(struct sh_mtu2_priv *p)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	int ret;
+
+	/* enable clock */
+	ret = clk_enable(p->clk);
+	if (ret) {
+		pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk);
+		return ret;
+	}
+
+	/* make sure channel is disabled */
+	sh_mtu2_start_stop_ch(p, 0);
+
+	p->rate = clk_get_rate(p->clk) / 64;
+	p->periodic = (p->rate + HZ/2) / HZ;
+
+	/* "Periodic Counter Operation" */
+	sh_mtu2_write(p, TCR, 0x23); /* TGRA clear, divide clock by 64 */
+	sh_mtu2_write(p, TIOR, 0);
+	sh_mtu2_write(p, TGR, p->periodic);
+	sh_mtu2_write(p, TCNT, 0);
+	sh_mtu2_write(p, TMDR, 0);
+	sh_mtu2_write(p, TIER, 0x01);
+
+	/* enable channel */
+	sh_mtu2_start_stop_ch(p, 1);
+
+	return 0;
+}
+
+static void sh_mtu2_disable(struct sh_mtu2_priv *p)
+{
+	/* disable channel */
+	sh_mtu2_start_stop_ch(p, 0);
+
+	/* stop clock */
+	clk_disable(p->clk);
+}
+
+static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id)
+{
+	struct sh_mtu2_priv *p = dev_id;
+
+	/* acknowledge interrupt */
+	sh_mtu2_read(p, TSR);
+	sh_mtu2_write(p, TSR, 0xfe);
+
+	/* notify clockevent layer */
+	p->ced.event_handler(&p->ced);
+	return IRQ_HANDLED;
+}
+
+static struct sh_mtu2_priv *ced_to_sh_mtu2(struct clock_event_device *ced)
+{
+	return container_of(ced, struct sh_mtu2_priv, ced);
+}
+
+static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
+				    struct clock_event_device *ced)
+{
+	struct sh_mtu2_priv *p = ced_to_sh_mtu2(ced);
+	int disabled = 0;
+
+	/* deal with old setting first */
+	switch (ced->mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		sh_mtu2_disable(p);
+		disabled = 1;
+		break;
+	default:
+		break;
+	}
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		pr_info("sh_mtu2: %s used for periodic clock events\n",
+			ced->name);
+		sh_mtu2_enable(p);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+		if (!disabled)
+			sh_mtu2_disable(p);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		break;
+	}
+}
+
+static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
+				       char *name, unsigned long rating)
+{
+	struct clock_event_device *ced = &p->ced;
+	int ret;
+
+	memset(ced, 0, sizeof(*ced));
+
+	ced->name = name;
+	ced->features = CLOCK_EVT_FEAT_PERIODIC;
+	ced->rating = rating;
+	ced->cpumask = cpumask_of(0);
+	ced->set_mode = sh_mtu2_clock_event_mode;
+
+	ret = setup_irq(p->irqaction.irq, &p->irqaction);
+	if (ret) {
+		pr_err("sh_mtu2: failed to request irq %d\n",
+		       p->irqaction.irq);
+		return;
+	}
+
+	pr_info("sh_mtu2: %s used for clock events\n", ced->name);
+	clockevents_register_device(ced);
+}
+
+static int sh_mtu2_register(struct sh_mtu2_priv *p, char *name,
+			    unsigned long clockevent_rating)
+{
+	if (clockevent_rating)
+		sh_mtu2_register_clockevent(p, name, clockevent_rating);
+
+	return 0;
+}
+
+static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
+{
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	struct resource *res;
+	int irq, ret;
+	ret = -ENXIO;
+
+	memset(p, 0, sizeof(*p));
+	p->pdev = pdev;
+
+	if (!cfg) {
+		dev_err(&p->pdev->dev, "missing platform data\n");
+		goto err0;
+	}
+
+	platform_set_drvdata(pdev, p);
+
+	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+		goto err0;
+	}
+
+	irq = platform_get_irq(p->pdev, 0);
+	if (irq < 0) {
+		dev_err(&p->pdev->dev, "failed to get irq\n");
+		goto err0;
+	}
+
+	/* map memory, let mapbase point to our channel */
+	p->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (p->mapbase == NULL) {
+		pr_err("sh_mtu2: failed to remap I/O memory\n");
+		goto err0;
+	}
+
+	/* setup data for setup_irq() (too early for request_irq()) */
+	p->irqaction.name = cfg->name;
+	p->irqaction.handler = sh_mtu2_interrupt;
+	p->irqaction.dev_id = p;
+	p->irqaction.irq = irq;
+	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
+
+	/* get hold of clock */
+	p->clk = clk_get(&p->pdev->dev, cfg->clk);
+	if (IS_ERR(p->clk)) {
+		pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk);
+		ret = PTR_ERR(p->clk);
+		goto err1;
+	}
+
+	return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating);
+ err1:
+	iounmap(p->mapbase);
+ err0:
+	return ret;
+}
+
+static int __devinit sh_mtu2_probe(struct platform_device *pdev)
+{
+	struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	int ret;
+
+	if (p) {
+		pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name);
+		return 0;
+	}
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (p == NULL) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	ret = sh_mtu2_setup(p, pdev);
+	if (ret) {
+		kfree(p);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return ret;
+}
+
+static int __devexit sh_mtu2_remove(struct platform_device *pdev)
+{
+	return -EBUSY; /* cannot unregister clockevent */
+}
+
+static struct platform_driver sh_mtu2_device_driver = {
+	.probe		= sh_mtu2_probe,
+	.remove		= __devexit_p(sh_mtu2_remove),
+	.driver		= {
+		.name	= "sh_mtu2",
+	}
+};
+
+static int __init sh_mtu2_init(void)
+{
+	return platform_driver_register(&sh_mtu2_device_driver);
+}
+
+static void __exit sh_mtu2_exit(void)
+{
+	platform_driver_unregister(&sh_mtu2_device_driver);
+}
+
+early_platform_init("earlytimer", &sh_mtu2_device_driver);
+module_init(sh_mtu2_init);
+module_exit(sh_mtu2_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("SuperH MTU2 Timer Driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/drivers/clocksource/sh_tmu.c linux-libre-2.6.31-gnu/drivers/clocksource/sh_tmu.c
--- linux-libre-2.6.30-gnu/drivers/clocksource/sh_tmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/clocksource/sh_tmu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,463 @@
+/*
+ * SuperH Timer Support - TMU
+ *
+ *  Copyright (C) 2009 Magnus Damm
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/sh_timer.h>
+
+struct sh_tmu_priv {
+	void __iomem *mapbase;
+	struct clk *clk;
+	struct irqaction irqaction;
+	struct platform_device *pdev;
+	unsigned long rate;
+	unsigned long periodic;
+	struct clock_event_device ced;
+	struct clocksource cs;
+};
+
+static DEFINE_SPINLOCK(sh_tmu_lock);
+
+#define TSTR -1 /* shared register */
+#define TCOR  0 /* channel register */
+#define TCNT 1 /* channel register */
+#define TCR 2 /* channel register */
+
+static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs;
+
+	if (reg_nr == TSTR)
+		return ioread8(base - cfg->channel_offset);
+
+	offs = reg_nr << 2;
+
+	if (reg_nr == TCR)
+		return ioread16(base + offs);
+	else
+		return ioread32(base + offs);
+}
+
+static inline void sh_tmu_write(struct sh_tmu_priv *p, int reg_nr,
+				unsigned long value)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	void __iomem *base = p->mapbase;
+	unsigned long offs;
+
+	if (reg_nr == TSTR) {
+		iowrite8(value, base - cfg->channel_offset);
+		return;
+	}
+
+	offs = reg_nr << 2;
+
+	if (reg_nr == TCR)
+		iowrite16(value, base + offs);
+	else
+		iowrite32(value, base + offs);
+}
+
+static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	unsigned long flags, value;
+
+	/* start stop register shared by multiple timer channels */
+	spin_lock_irqsave(&sh_tmu_lock, flags);
+	value = sh_tmu_read(p, TSTR);
+
+	if (start)
+		value |= 1 << cfg->timer_bit;
+	else
+		value &= ~(1 << cfg->timer_bit);
+
+	sh_tmu_write(p, TSTR, value);
+	spin_unlock_irqrestore(&sh_tmu_lock, flags);
+}
+
+static int sh_tmu_enable(struct sh_tmu_priv *p)
+{
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	int ret;
+
+	/* enable clock */
+	ret = clk_enable(p->clk);
+	if (ret) {
+		pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk);
+		return ret;
+	}
+
+	/* make sure channel is disabled */
+	sh_tmu_start_stop_ch(p, 0);
+
+	/* maximum timeout */
+	sh_tmu_write(p, TCOR, 0xffffffff);
+	sh_tmu_write(p, TCNT, 0xffffffff);
+
+	/* configure channel to parent clock / 4, irq off */
+	p->rate = clk_get_rate(p->clk) / 4;
+	sh_tmu_write(p, TCR, 0x0000);
+
+	/* enable channel */
+	sh_tmu_start_stop_ch(p, 1);
+
+	return 0;
+}
+
+static void sh_tmu_disable(struct sh_tmu_priv *p)
+{
+	/* disable channel */
+	sh_tmu_start_stop_ch(p, 0);
+
+	/* disable interrupts in TMU block */
+	sh_tmu_write(p, TCR, 0x0000);
+
+	/* stop clock */
+	clk_disable(p->clk);
+}
+
+static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
+			    int periodic)
+{
+	/* stop timer */
+	sh_tmu_start_stop_ch(p, 0);
+
+	/* acknowledge interrupt */
+	sh_tmu_read(p, TCR);
+
+	/* enable interrupt */
+	sh_tmu_write(p, TCR, 0x0020);
+
+	/* reload delta value in case of periodic timer */
+	if (periodic)
+		sh_tmu_write(p, TCOR, delta);
+	else
+		sh_tmu_write(p, TCOR, 0xffffffff);
+
+	sh_tmu_write(p, TCNT, delta);
+
+	/* start timer */
+	sh_tmu_start_stop_ch(p, 1);
+}
+
+static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
+{
+	struct sh_tmu_priv *p = dev_id;
+
+	/* disable or acknowledge interrupt */
+	if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT)
+		sh_tmu_write(p, TCR, 0x0000);
+	else
+		sh_tmu_write(p, TCR, 0x0020);
+
+	/* notify clockevent layer */
+	p->ced.event_handler(&p->ced);
+	return IRQ_HANDLED;
+}
+
+static struct sh_tmu_priv *cs_to_sh_tmu(struct clocksource *cs)
+{
+	return container_of(cs, struct sh_tmu_priv, cs);
+}
+
+static cycle_t sh_tmu_clocksource_read(struct clocksource *cs)
+{
+	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+	return sh_tmu_read(p, TCNT) ^ 0xffffffff;
+}
+
+static int sh_tmu_clocksource_enable(struct clocksource *cs)
+{
+	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+	int ret;
+
+	ret = sh_tmu_enable(p);
+	if (ret)
+		return ret;
+
+	/* TODO: calculate good shift from rate and counter bit width */
+	cs->shift = 10;
+	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+	return 0;
+}
+
+static void sh_tmu_clocksource_disable(struct clocksource *cs)
+{
+	sh_tmu_disable(cs_to_sh_tmu(cs));
+}
+
+static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
+				       char *name, unsigned long rating)
+{
+	struct clocksource *cs = &p->cs;
+
+	cs->name = name;
+	cs->rating = rating;
+	cs->read = sh_tmu_clocksource_read;
+	cs->enable = sh_tmu_clocksource_enable;
+	cs->disable = sh_tmu_clocksource_disable;
+	cs->mask = CLOCKSOURCE_MASK(32);
+	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+	pr_info("sh_tmu: %s used as clock source\n", cs->name);
+	clocksource_register(cs);
+	return 0;
+}
+
+static struct sh_tmu_priv *ced_to_sh_tmu(struct clock_event_device *ced)
+{
+	return container_of(ced, struct sh_tmu_priv, ced);
+}
+
+static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic)
+{
+	struct clock_event_device *ced = &p->ced;
+
+	sh_tmu_enable(p);
+
+	/* TODO: calculate good shift from rate and counter bit width */
+
+	ced->shift = 32;
+	ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
+	ced->max_delta_ns = clockevent_delta2ns(0xffffffff, ced);
+	ced->min_delta_ns = 5000;
+
+	if (periodic) {
+		p->periodic = (p->rate + HZ/2) / HZ;
+		sh_tmu_set_next(p, p->periodic, 1);
+	}
+}
+
+static void sh_tmu_clock_event_mode(enum clock_event_mode mode,
+				    struct clock_event_device *ced)
+{
+	struct sh_tmu_priv *p = ced_to_sh_tmu(ced);
+	int disabled = 0;
+
+	/* deal with old setting first */
+	switch (ced->mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+	case CLOCK_EVT_MODE_ONESHOT:
+		sh_tmu_disable(p);
+		disabled = 1;
+		break;
+	default:
+		break;
+	}
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		pr_info("sh_tmu: %s used for periodic clock events\n",
+			ced->name);
+		sh_tmu_clock_event_start(p, 1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		pr_info("sh_tmu: %s used for oneshot clock events\n",
+			ced->name);
+		sh_tmu_clock_event_start(p, 0);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+		if (!disabled)
+			sh_tmu_disable(p);
+		break;
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	default:
+		break;
+	}
+}
+
+static int sh_tmu_clock_event_next(unsigned long delta,
+				   struct clock_event_device *ced)
+{
+	struct sh_tmu_priv *p = ced_to_sh_tmu(ced);
+
+	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
+
+	/* program new delta value */
+	sh_tmu_set_next(p, delta, 0);
+	return 0;
+}
+
+static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
+				       char *name, unsigned long rating)
+{
+	struct clock_event_device *ced = &p->ced;
+	int ret;
+
+	memset(ced, 0, sizeof(*ced));
+
+	ced->name = name;
+	ced->features = CLOCK_EVT_FEAT_PERIODIC;
+	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
+	ced->rating = rating;
+	ced->cpumask = cpumask_of(0);
+	ced->set_next_event = sh_tmu_clock_event_next;
+	ced->set_mode = sh_tmu_clock_event_mode;
+
+	ret = setup_irq(p->irqaction.irq, &p->irqaction);
+	if (ret) {
+		pr_err("sh_tmu: failed to request irq %d\n",
+		       p->irqaction.irq);
+		return;
+	}
+
+	pr_info("sh_tmu: %s used for clock events\n", ced->name);
+	clockevents_register_device(ced);
+}
+
+static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
+		    unsigned long clockevent_rating,
+		    unsigned long clocksource_rating)
+{
+	if (clockevent_rating)
+		sh_tmu_register_clockevent(p, name, clockevent_rating);
+	else if (clocksource_rating)
+		sh_tmu_register_clocksource(p, name, clocksource_rating);
+
+	return 0;
+}
+
+static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
+{
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	struct resource *res;
+	int irq, ret;
+	ret = -ENXIO;
+
+	memset(p, 0, sizeof(*p));
+	p->pdev = pdev;
+
+	if (!cfg) {
+		dev_err(&p->pdev->dev, "missing platform data\n");
+		goto err0;
+	}
+
+	platform_set_drvdata(pdev, p);
+
+	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+		goto err0;
+	}
+
+	irq = platform_get_irq(p->pdev, 0);
+	if (irq < 0) {
+		dev_err(&p->pdev->dev, "failed to get irq\n");
+		goto err0;
+	}
+
+	/* map memory, let mapbase point to our channel */
+	p->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (p->mapbase == NULL) {
+		pr_err("sh_tmu: failed to remap I/O memory\n");
+		goto err0;
+	}
+
+	/* setup data for setup_irq() (too early for request_irq()) */
+	p->irqaction.name = cfg->name;
+	p->irqaction.handler = sh_tmu_interrupt;
+	p->irqaction.dev_id = p;
+	p->irqaction.irq = irq;
+	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
+
+	/* get hold of clock */
+	p->clk = clk_get(&p->pdev->dev, cfg->clk);
+	if (IS_ERR(p->clk)) {
+		pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk);
+		ret = PTR_ERR(p->clk);
+		goto err1;
+	}
+
+	return sh_tmu_register(p, cfg->name,
+			       cfg->clockevent_rating,
+			       cfg->clocksource_rating);
+ err1:
+	iounmap(p->mapbase);
+ err0:
+	return ret;
+}
+
+static int __devinit sh_tmu_probe(struct platform_device *pdev)
+{
+	struct sh_tmu_priv *p = platform_get_drvdata(pdev);
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	int ret;
+
+	if (p) {
+		pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name);
+		return 0;
+	}
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (p == NULL) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	ret = sh_tmu_setup(p, pdev);
+	if (ret) {
+		kfree(p);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return ret;
+}
+
+static int __devexit sh_tmu_remove(struct platform_device *pdev)
+{
+	return -EBUSY; /* cannot unregister clockevent and clocksource */
+}
+
+static struct platform_driver sh_tmu_device_driver = {
+	.probe		= sh_tmu_probe,
+	.remove		= __devexit_p(sh_tmu_remove),
+	.driver		= {
+		.name	= "sh_tmu",
+	}
+};
+
+static int __init sh_tmu_init(void)
+{
+	return platform_driver_register(&sh_tmu_device_driver);
+}
+
+static void __exit sh_tmu_exit(void)
+{
+	platform_driver_unregister(&sh_tmu_device_driver);
+}
+
+early_platform_init("earlytimer", &sh_tmu_device_driver);
+module_init(sh_tmu_init);
+module_exit(sh_tmu_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("SuperH TMU Timer Driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/drivers/connector/cn_queue.c linux-libre-2.6.31-gnu/drivers/connector/cn_queue.c
--- linux-libre-2.6.30-gnu/drivers/connector/cn_queue.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/connector/cn_queue.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * 	cn_queue.c
  *
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.30-gnu/drivers/connector/connector.c linux-libre-2.6.31-gnu/drivers/connector/connector.c
--- linux-libre-2.6.30-gnu/drivers/connector/connector.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/connector/connector.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * 	connector.c
  *
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
 #include <net/sock.h>
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
 
 static u32 cn_idx = CN_IDX_CONNECTOR;
diff -druN linux-libre-2.6.30-gnu/drivers/connector/Kconfig linux-libre-2.6.31-gnu/drivers/connector/Kconfig
--- linux-libre-2.6.30-gnu/drivers/connector/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/connector/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
 	  of the netlink socket protocol.
 
 	  Connector support can also be built as a module.  If so, the module
-	  will be called cn.ko.
+	  will be called cn.
 
 if CONNECTOR
 
diff -druN linux-libre-2.6.30-gnu/drivers/cpufreq/cpufreq.c linux-libre-2.6.31-gnu/drivers/cpufreq/cpufreq.c
--- linux-libre-2.6.30-gnu/drivers/cpufreq/cpufreq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/cpufreq/cpufreq.c	2009-09-09 18:13:59.000000000 -0400
@@ -761,6 +761,10 @@
  * cpufreq_add_dev - add a CPU device
  *
  * Adds the cpufreq interface for a CPU device.
+ *
+ * The Oracle says: try running cpufreq registration/unregistration concurrently
+ * with with cpu hotplugging and all hell will break loose. Tried to clean this
+ * mess up, but more thorough testing is needed. - Mathieu
  */
 static int cpufreq_add_dev(struct sys_device *sys_dev)
 {
@@ -772,9 +776,6 @@
 	struct sys_device *cpu_sys_dev;
 	unsigned long flags;
 	unsigned int j;
-#ifdef CONFIG_SMP
-	struct cpufreq_policy *managed_policy;
-#endif
 
 	if (cpu_is_offline(cpu))
 		return 0;
@@ -804,15 +805,12 @@
 		goto nomem_out;
 	}
 	if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) {
-		kfree(policy);
 		ret = -ENOMEM;
-		goto nomem_out;
+		goto err_free_policy;
 	}
 	if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) {
-		free_cpumask_var(policy->cpus);
-		kfree(policy);
 		ret = -ENOMEM;
-		goto nomem_out;
+		goto err_free_cpumask;
 	}
 
 	policy->cpu = cpu;
@@ -820,7 +818,8 @@
 
 	/* Initially set CPU itself as the policy_cpu */
 	per_cpu(policy_cpu, cpu) = cpu;
-	lock_policy_rwsem_write(cpu);
+	ret = (lock_policy_rwsem_write(cpu) < 0);
+	WARN_ON(ret);
 
 	init_completion(&policy->kobj_unregister);
 	INIT_WORK(&policy->update, handle_update);
@@ -833,7 +832,7 @@
 	ret = cpufreq_driver->init(policy);
 	if (ret) {
 		dprintk("initialization failed\n");
-		goto err_out;
+		goto err_unlock_policy;
 	}
 	policy->user_policy.min = policy->min;
 	policy->user_policy.max = policy->max;
@@ -852,21 +851,31 @@
 #endif
 
 	for_each_cpu(j, policy->cpus) {
+		struct cpufreq_policy *managed_policy;
+
 		if (cpu == j)
 			continue;
 
 		/* Check for existing affected CPUs.
 		 * They may not be aware of it due to CPU Hotplug.
+		 * cpufreq_cpu_put is called when the device is removed
+		 * in __cpufreq_remove_dev()
 		 */
-		managed_policy = cpufreq_cpu_get(j);		/* FIXME: Where is this released?  What about error paths? */
+		managed_policy = cpufreq_cpu_get(j);
 		if (unlikely(managed_policy)) {
 
 			/* Set proper policy_cpu */
 			unlock_policy_rwsem_write(cpu);
 			per_cpu(policy_cpu, cpu) = managed_policy->cpu;
 
-			if (lock_policy_rwsem_write(cpu) < 0)
-				goto err_out_driver_exit;
+			if (lock_policy_rwsem_write(cpu) < 0) {
+				/* Should not go through policy unlock path */
+				if (cpufreq_driver->exit)
+					cpufreq_driver->exit(policy);
+				ret = -EBUSY;
+				cpufreq_cpu_put(managed_policy);
+				goto err_free_cpumask;
+			}
 
 			spin_lock_irqsave(&cpufreq_driver_lock, flags);
 			cpumask_copy(managed_policy->cpus, policy->cpus);
@@ -878,11 +887,13 @@
 						&managed_policy->kobj,
 						"cpufreq");
 			if (ret)
-				goto err_out_driver_exit;
-
-			cpufreq_debug_enable_ratelimit();
-			ret = 0;
-			goto err_out_driver_exit; /* call driver->exit() */
+				cpufreq_cpu_put(managed_policy);
+			/*
+			 * Success. We only needed to be added to the mask.
+			 * Call driver->exit() because only the cpu parent of
+			 * the kobj needed to call init().
+			 */
+			goto out_driver_exit; /* call driver->exit() */
 		}
 	}
 #endif
@@ -892,29 +903,31 @@
 	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
 				   "cpufreq");
 	if (ret)
-		goto err_out_driver_exit;
+		goto out_driver_exit;
 
 	/* set up files for this cpu device */
 	drv_attr = cpufreq_driver->attr;
 	while ((drv_attr) && (*drv_attr)) {
 		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
 		if (ret)
-			goto err_out_driver_exit;
+			goto err_out_kobj_put;
 		drv_attr++;
 	}
 	if (cpufreq_driver->get) {
 		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
 		if (ret)
-			goto err_out_driver_exit;
+			goto err_out_kobj_put;
 	}
 	if (cpufreq_driver->target) {
 		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
 		if (ret)
-			goto err_out_driver_exit;
+			goto err_out_kobj_put;
 	}
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_cpu(j, policy->cpus) {
+		if (!cpu_online(j))
+			continue;
 		per_cpu(cpufreq_cpu_data, j) = policy;
 		per_cpu(policy_cpu, j) = policy->cpu;
 	}
@@ -922,18 +935,22 @@
 
 	/* symlink affected CPUs */
 	for_each_cpu(j, policy->cpus) {
+		struct cpufreq_policy *managed_policy;
+
 		if (j == cpu)
 			continue;
 		if (!cpu_online(j))
 			continue;
 
 		dprintk("CPU %u already managed, adding link\n", j);
-		cpufreq_cpu_get(cpu);
+		managed_policy = cpufreq_cpu_get(cpu);
 		cpu_sys_dev = get_cpu_sysdev(j);
 		ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
 					"cpufreq");
-		if (ret)
+		if (ret) {
+			cpufreq_cpu_put(managed_policy);
 			goto err_out_unregister;
+		}
 	}
 
 	policy->governor = NULL; /* to assure that the starting sequence is
@@ -965,17 +982,20 @@
 		per_cpu(cpufreq_cpu_data, j) = NULL;
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
+err_out_kobj_put:
 	kobject_put(&policy->kobj);
 	wait_for_completion(&policy->kobj_unregister);
 
-err_out_driver_exit:
+out_driver_exit:
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(policy);
 
-err_out:
+err_unlock_policy:
 	unlock_policy_rwsem_write(cpu);
+err_free_cpumask:
+	free_cpumask_var(policy->cpus);
+err_free_policy:
 	kfree(policy);
-
 nomem_out:
 	module_put(cpufreq_driver->owner);
 module_out:
@@ -1070,8 +1090,6 @@
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-	unlock_policy_rwsem_write(cpu);
-
 	if (cpufreq_driver->target)
 		__cpufreq_governor(data, CPUFREQ_GOV_STOP);
 
@@ -1088,6 +1106,8 @@
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(data);
 
+	unlock_policy_rwsem_write(cpu);
+
 	free_cpumask_var(data->related_cpus);
 	free_cpumask_var(data->cpus);
 	kfree(data);
@@ -1228,9 +1248,9 @@
 
 static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
 {
-	int cpu = sysdev->id;
 	int ret = 0;
-	unsigned int cur_freq = 0;
+
+	int cpu = sysdev->id;
 	struct cpufreq_policy *cpu_policy;
 
 	dprintk("suspending cpu %u\n", cpu);
@@ -1253,42 +1273,9 @@
 
 	if (cpufreq_driver->suspend) {
 		ret = cpufreq_driver->suspend(cpu_policy, pmsg);
-		if (ret) {
+		if (ret)
 			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
 					"step on CPU %u\n", cpu_policy->cpu);
-			goto out;
-		}
-	}
-
-	if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)
-		goto out;
-
-	if (cpufreq_driver->get)
-		cur_freq = cpufreq_driver->get(cpu_policy->cpu);
-
-	if (!cur_freq || !cpu_policy->cur) {
-		printk(KERN_ERR "cpufreq: suspend failed to assert current "
-		       "frequency is what timing core thinks it is.\n");
-		goto out;
-	}
-
-	if (unlikely(cur_freq != cpu_policy->cur)) {
-		struct cpufreq_freqs freqs;
-
-		if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-			dprintk("Warning: CPU frequency is %u, "
-			       "cpufreq assumed %u kHz.\n",
-			       cur_freq, cpu_policy->cur);
-
-		freqs.cpu = cpu;
-		freqs.old = cpu_policy->cur;
-		freqs.new = cur_freq;
-
-		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
-				    CPUFREQ_SUSPENDCHANGE, &freqs);
-		adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
-
-		cpu_policy->cur = cur_freq;
 	}
 
 out:
@@ -1300,14 +1287,17 @@
  *	cpufreq_resume -  restore proper CPU frequency handling after resume
  *
  *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
- *	2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync
- *	3.) schedule call cpufreq_update_policy() ASAP as interrupts are
- *	    restored.
+ *	2.) schedule call cpufreq_update_policy() ASAP as interrupts are
+ *	    restored. It will verify that the current freq is in sync with
+ *	    what we believe it to be. This is a bit later than when it
+ *	    should be, but nonethteless it's better than calling
+ *	    cpufreq_driver->get() here which might re-enable interrupts...
  */
 static int cpufreq_resume(struct sys_device *sysdev)
 {
-	int cpu = sysdev->id;
 	int ret = 0;
+
+	int cpu = sysdev->id;
 	struct cpufreq_policy *cpu_policy;
 
 	dprintk("resuming cpu %u\n", cpu);
@@ -1337,42 +1327,8 @@
 		}
 	}
 
-	if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
-		unsigned int cur_freq = 0;
-
-		if (cpufreq_driver->get)
-			cur_freq = cpufreq_driver->get(cpu_policy->cpu);
-
-		if (!cur_freq || !cpu_policy->cur) {
-			printk(KERN_ERR "cpufreq: resume failed to assert "
-					"current frequency is what timing core "
-					"thinks it is.\n");
-			goto out;
-		}
-
-		if (unlikely(cur_freq != cpu_policy->cur)) {
-			struct cpufreq_freqs freqs;
-
-			if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-				dprintk("Warning: CPU frequency "
-				       "is %u, cpufreq assumed %u kHz.\n",
-				       cur_freq, cpu_policy->cur);
-
-			freqs.cpu = cpu;
-			freqs.old = cpu_policy->cur;
-			freqs.new = cur_freq;
-
-			srcu_notifier_call_chain(
-					&cpufreq_transition_notifier_list,
-					CPUFREQ_RESUMECHANGE, &freqs);
-			adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
-
-			cpu_policy->cur = cur_freq;
-		}
-	}
-
-out:
 	schedule_work(&cpu_policy->update);
+
 fail:
 	cpufreq_cpu_put(cpu_policy);
 	return ret;
diff -druN linux-libre-2.6.30-gnu/drivers/cpufreq/cpufreq_conservative.c linux-libre-2.6.31-gnu/drivers/cpufreq/cpufreq_conservative.c
--- linux-libre-2.6.30-gnu/drivers/cpufreq/cpufreq_conservative.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/cpufreq/cpufreq_conservative.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,27 +42,12 @@
  * this governor will not work.
  * All times here are in uS.
  */
-static unsigned int def_sampling_rate;
 #define MIN_SAMPLING_RATE_RATIO			(2)
-/* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE 			\
-			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
-#define MIN_SAMPLING_RATE			\
-			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
-/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon
- * Define the minimal settable sampling rate to the greater of:
- *   - "HW transition latency" * 100 (same as default sampling / 10)
- *   - MIN_STAT_SAMPLING_RATE
- * To avoid that userspace shoots itself.
-*/
-static unsigned int minimum_sampling_rate(void)
-{
-	return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE);
-}
 
-/* This will also vanish soon with removing sampling_rate_max */
-#define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
+static unsigned int min_sampling_rate;
+
 #define LATENCY_MULTIPLIER			(1000)
+#define MIN_LATENCY_MULTIPLIER			(100)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(10)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
@@ -79,21 +64,20 @@
 	unsigned int requested_freq;
 	int cpu;
 	unsigned int enable:1;
+	/*
+	 * percpu mutex that serializes governor limit change with
+	 * do_dbs_timer invocation. We do not want do_dbs_timer to run
+	 * when user is changing the governor or limits.
+	 */
+	struct mutex timer_mutex;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
 /*
- * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug
- * lock and dbs_mutex. cpu_hotplug lock should always be held before
- * dbs_mutex. If any function that can potentially take cpu_hotplug lock
- * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then
- * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
- * is recursive for the same process. -Venki
- * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it
- * would deadlock with cancel_delayed_work_sync(), which is needed for proper
- * raceless workqueue teardown.
+ * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
+ * different CPUs. It protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
@@ -182,27 +166,14 @@
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
 {
-	static int print_once;
-
-	if (!print_once) {
-		printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
-		       "sysfs file is deprecated - used by: %s\n",
-		       current->comm);
-		print_once = 1;
-	}
-	return sprintf(buf, "%u\n", MAX_SAMPLING_RATE);
+	printk_once(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
+		    "sysfs file is deprecated - used by: %s\n", current->comm);
+	return sprintf(buf, "%u\n", -1U);
 }
 
 static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
 {
-	static int print_once;
-
-	if (!print_once) {
-		printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
-		       "sysfs file is deprecated - used by: %s\n", current->comm);
-		print_once = 1;
-	}
-	return sprintf(buf, "%u\n", MIN_SAMPLING_RATE);
+	return sprintf(buf, "%u\n", min_sampling_rate);
 }
 
 #define define_one_ro(_name)		\
@@ -254,7 +225,7 @@
 		return -EINVAL;
 
 	mutex_lock(&dbs_mutex);
-	dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate());
+	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
 	mutex_unlock(&dbs_mutex);
 
 	return count;
@@ -516,18 +487,12 @@
 
 	delay -= jiffies % delay;
 
-	if (lock_policy_rwsem_write(cpu) < 0)
-		return;
-
-	if (!dbs_info->enable) {
-		unlock_policy_rwsem_write(cpu);
-		return;
-	}
+	mutex_lock(&dbs_info->timer_mutex);
 
 	dbs_check_cpu(dbs_info);
 
 	queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay);
-	unlock_policy_rwsem_write(cpu);
+	mutex_unlock(&dbs_info->timer_mutex);
 }
 
 static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
@@ -563,9 +528,6 @@
 		if ((!cpu_online(cpu)) || (!policy->cur))
 			return -EINVAL;
 
-		if (this_dbs_info->enable) /* Already enabled */
-			break;
-
 		mutex_lock(&dbs_mutex);
 
 		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
@@ -589,6 +551,7 @@
 		this_dbs_info->down_skip = 0;
 		this_dbs_info->requested_freq = policy->cur;
 
+		mutex_init(&this_dbs_info->timer_mutex);
 		dbs_enable++;
 		/*
 		 * Start the timerschedule work, when this governor
@@ -601,27 +564,36 @@
 			if (latency == 0)
 				latency = 1;
 
-			def_sampling_rate =
-				max(latency * LATENCY_MULTIPLIER,
-				    MIN_STAT_SAMPLING_RATE);
-
-			dbs_tuners_ins.sampling_rate = def_sampling_rate;
+			/*
+			 * conservative does not implement micro like ondemand
+			 * governor, thus we are bound to jiffes/HZ
+			 */
+			min_sampling_rate =
+				MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
+			/* Bring kernel and HW constraints together */
+			min_sampling_rate = max(min_sampling_rate,
+					MIN_LATENCY_MULTIPLIER * latency);
+			dbs_tuners_ins.sampling_rate =
+				max(min_sampling_rate,
+				    latency * LATENCY_MULTIPLIER);
 
 			cpufreq_register_notifier(
 					&dbs_cpufreq_notifier_block,
 					CPUFREQ_TRANSITION_NOTIFIER);
 		}
-		dbs_timer_init(this_dbs_info);
-
 		mutex_unlock(&dbs_mutex);
 
+		dbs_timer_init(this_dbs_info);
+
 		break;
 
 	case CPUFREQ_GOV_STOP:
-		mutex_lock(&dbs_mutex);
 		dbs_timer_exit(this_dbs_info);
+
+		mutex_lock(&dbs_mutex);
 		sysfs_remove_group(&policy->kobj, &dbs_attr_group);
 		dbs_enable--;
+		mutex_destroy(&this_dbs_info->timer_mutex);
 
 		/*
 		 * Stop the timerschedule work, when this governor
@@ -637,7 +609,7 @@
 		break;
 
 	case CPUFREQ_GOV_LIMITS:
-		mutex_lock(&dbs_mutex);
+		mutex_lock(&this_dbs_info->timer_mutex);
 		if (policy->max < this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(
 					this_dbs_info->cur_policy,
@@ -646,7 +618,7 @@
 			__cpufreq_driver_target(
 					this_dbs_info->cur_policy,
 					policy->min, CPUFREQ_RELATION_L);
-		mutex_unlock(&dbs_mutex);
+		mutex_unlock(&this_dbs_info->timer_mutex);
 
 		break;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/cpufreq/cpufreq_ondemand.c linux-libre-2.6.31-gnu/drivers/cpufreq/cpufreq_ondemand.c
--- linux-libre-2.6.30-gnu/drivers/cpufreq/cpufreq_ondemand.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/cpufreq/cpufreq_ondemand.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,7 @@
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL	(3)
 #define MICRO_FREQUENCY_UP_THRESHOLD		(95)
+#define MICRO_FREQUENCY_MIN_SAMPLE_RATE		(10000)
 #define MIN_FREQUENCY_UP_THRESHOLD		(11)
 #define MAX_FREQUENCY_UP_THRESHOLD		(100)
 
@@ -45,27 +46,12 @@
  * this governor will not work.
  * All times here are in uS.
  */
-static unsigned int def_sampling_rate;
 #define MIN_SAMPLING_RATE_RATIO			(2)
-/* for correct statistics, we need at least 10 ticks between each measure */
-#define MIN_STAT_SAMPLING_RATE 			\
-			(MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
-#define MIN_SAMPLING_RATE			\
-			(def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
-/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon
- * Define the minimal settable sampling rate to the greater of:
- *   - "HW transition latency" * 100 (same as default sampling / 10)
- *   - MIN_STAT_SAMPLING_RATE
- * To avoid that userspace shoots itself.
-*/
-static unsigned int minimum_sampling_rate(void)
-{
-	return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE);
-}
 
-/* This will also vanish soon with removing sampling_rate_max */
-#define MAX_SAMPLING_RATE			(500 * def_sampling_rate)
+static unsigned int min_sampling_rate;
+
 #define LATENCY_MULTIPLIER			(1000)
+#define MIN_LATENCY_MULTIPLIER			(100)
 #define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
 
 static void do_dbs_timer(struct work_struct *work);
@@ -84,23 +70,21 @@
 	unsigned int freq_lo_jiffies;
 	unsigned int freq_hi_jiffies;
 	int cpu;
-	unsigned int enable:1,
-		sample_type:1;
+	unsigned int sample_type:1;
+	/*
+	 * percpu mutex that serializes governor limit change with
+	 * do_dbs_timer invocation. We do not want do_dbs_timer to run
+	 * when user is changing the governor or limits.
+	 */
+	struct mutex timer_mutex;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
 /*
- * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug
- * lock and dbs_mutex. cpu_hotplug lock should always be held before
- * dbs_mutex. If any function that can potentially take cpu_hotplug lock
- * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then
- * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
- * is recursive for the same process. -Venki
- * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it
- * would deadlock with cancel_delayed_work_sync(), which is needed for proper
- * raceless workqueue teardown.
+ * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
+ * different CPUs. It protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
@@ -206,41 +190,32 @@
 	return freq_hi;
 }
 
+static void ondemand_powersave_bias_init_cpu(int cpu)
+{
+	struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
+	dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
+	dbs_info->freq_lo = 0;
+}
+
 static void ondemand_powersave_bias_init(void)
 {
 	int i;
 	for_each_online_cpu(i) {
-		struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i);
-		dbs_info->freq_table = cpufreq_frequency_get_table(i);
-		dbs_info->freq_lo = 0;
+		ondemand_powersave_bias_init_cpu(i);
 	}
 }
 
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
 {
-	static int print_once;
-
-	if (!print_once) {
-		printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_max "
-		       "sysfs file is deprecated - used by: %s\n",
-		       current->comm);
-		print_once = 1;
-	}
-	return sprintf(buf, "%u\n", MAX_SAMPLING_RATE);
+	printk_once(KERN_INFO "CPUFREQ: ondemand sampling_rate_max "
+	       "sysfs file is deprecated - used by: %s\n", current->comm);
+	return sprintf(buf, "%u\n", -1U);
 }
 
 static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
 {
-	static int print_once;
-
-	if (!print_once) {
-		printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_min "
-		       "sysfs file is deprecated - used by: %s\n",
-		       current->comm);
-		print_once = 1;
-	}
-	return sprintf(buf, "%u\n", MIN_SAMPLING_RATE);
+	return sprintf(buf, "%u\n", min_sampling_rate);
 }
 
 #define define_one_ro(_name)		\
@@ -268,13 +243,11 @@
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
+	if (ret != 1)
+		return -EINVAL;
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1) {
-		mutex_unlock(&dbs_mutex);
-		return -EINVAL;
-	}
-	dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate());
+	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
 	mutex_unlock(&dbs_mutex);
 
 	return count;
@@ -287,13 +260,12 @@
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	mutex_lock(&dbs_mutex);
 	if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
 			input < MIN_FREQUENCY_UP_THRESHOLD) {
-		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
 
+	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.up_threshold = input;
 	mutex_unlock(&dbs_mutex);
 
@@ -391,9 +363,6 @@
 	struct cpufreq_policy *policy;
 	unsigned int j;
 
-	if (!this_dbs_info->enable)
-		return;
-
 	this_dbs_info->freq_lo = 0;
 	policy = this_dbs_info->cur_policy;
 
@@ -521,14 +490,7 @@
 	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
 
 	delay -= jiffies % delay;
-
-	if (lock_policy_rwsem_write(cpu) < 0)
-		return;
-
-	if (!dbs_info->enable) {
-		unlock_policy_rwsem_write(cpu);
-		return;
-	}
+	mutex_lock(&dbs_info->timer_mutex);
 
 	/* Common NORMAL_SAMPLE setup */
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
@@ -545,7 +507,7 @@
 			dbs_info->freq_lo, CPUFREQ_RELATION_H);
 	}
 	queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
-	unlock_policy_rwsem_write(cpu);
+	mutex_unlock(&dbs_info->timer_mutex);
 }
 
 static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
@@ -554,8 +516,6 @@
 	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
 	delay -= jiffies % delay;
 
-	dbs_info->enable = 1;
-	ondemand_powersave_bias_init();
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
 	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
 	queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
@@ -564,7 +524,6 @@
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
 {
-	dbs_info->enable = 0;
 	cancel_delayed_work_sync(&dbs_info->work);
 }
 
@@ -583,19 +542,15 @@
 		if ((!cpu_online(cpu)) || (!policy->cur))
 			return -EINVAL;
 
-		if (this_dbs_info->enable) /* Already enabled */
-			break;
-
 		mutex_lock(&dbs_mutex);
-		dbs_enable++;
 
 		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
 		if (rc) {
-			dbs_enable--;
 			mutex_unlock(&dbs_mutex);
 			return rc;
 		}
 
+		dbs_enable++;
 		for_each_cpu(j, policy->cpus) {
 			struct cpu_dbs_info_s *j_dbs_info;
 			j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -609,6 +564,8 @@
 			}
 		}
 		this_dbs_info->cpu = cpu;
+		ondemand_powersave_bias_init_cpu(cpu);
+		mutex_init(&this_dbs_info->timer_mutex);
 		/*
 		 * Start the timerschedule work, when this governor
 		 * is used for first time
@@ -619,36 +576,38 @@
 			latency = policy->cpuinfo.transition_latency / 1000;
 			if (latency == 0)
 				latency = 1;
-
-			def_sampling_rate =
-				max(latency * LATENCY_MULTIPLIER,
-				    MIN_STAT_SAMPLING_RATE);
-
-			dbs_tuners_ins.sampling_rate = def_sampling_rate;
+			/* Bring kernel and HW constraints together */
+			min_sampling_rate = max(min_sampling_rate,
+					MIN_LATENCY_MULTIPLIER * latency);
+			dbs_tuners_ins.sampling_rate =
+				max(min_sampling_rate,
+				    latency * LATENCY_MULTIPLIER);
 		}
-		dbs_timer_init(this_dbs_info);
-
 		mutex_unlock(&dbs_mutex);
+
+		dbs_timer_init(this_dbs_info);
 		break;
 
 	case CPUFREQ_GOV_STOP:
-		mutex_lock(&dbs_mutex);
 		dbs_timer_exit(this_dbs_info);
+
+		mutex_lock(&dbs_mutex);
 		sysfs_remove_group(&policy->kobj, &dbs_attr_group);
+		mutex_destroy(&this_dbs_info->timer_mutex);
 		dbs_enable--;
 		mutex_unlock(&dbs_mutex);
 
 		break;
 
 	case CPUFREQ_GOV_LIMITS:
-		mutex_lock(&dbs_mutex);
+		mutex_lock(&this_dbs_info->timer_mutex);
 		if (policy->max < this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(this_dbs_info->cur_policy,
 				policy->max, CPUFREQ_RELATION_H);
 		else if (policy->min > this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(this_dbs_info->cur_policy,
 				policy->min, CPUFREQ_RELATION_L);
-		mutex_unlock(&dbs_mutex);
+		mutex_unlock(&this_dbs_info->timer_mutex);
 		break;
 	}
 	return 0;
@@ -678,6 +637,16 @@
 		dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
 		dbs_tuners_ins.down_differential =
 					MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+		/*
+		 * In no_hz/micro accounting case we set the minimum frequency
+		 * not depending on HZ, but fixed (very low). The deferred
+		 * timer might skip some samples if idle/sleeping as needed.
+		*/
+		min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
+	} else {
+		/* For correct statistics, we need 10 ticks for each measure */
+		min_sampling_rate =
+			MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
 	}
 
 	kondemand_wq = create_workqueue("kondemand");
diff -druN linux-libre-2.6.30-gnu/drivers/crypto/hifn_795x.c linux-libre-2.6.31-gnu/drivers/crypto/hifn_795x.c
--- linux-libre-2.6.30-gnu/drivers/crypto/hifn_795x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/crypto/hifn_795x.c	2009-09-09 18:13:59.000000000 -0400
@@ -2564,7 +2564,7 @@
 		hifn_process_queue(dev);
 }
 
-static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int err, i;
 	struct hifn_device *dev;
@@ -2696,7 +2696,7 @@
 	return err;
 }
 
-static void hifn_remove(struct pci_dev *pdev)
+static void __devexit hifn_remove(struct pci_dev *pdev)
 {
 	int i;
 	struct hifn_device *dev;
@@ -2744,7 +2744,7 @@
 	.remove   = __devexit_p(hifn_remove),
 };
 
-static int __devinit hifn_init(void)
+static int __init hifn_init(void)
 {
 	unsigned int freq;
 	int err;
@@ -2789,7 +2789,7 @@
 	return 0;
 }
 
-static void __devexit hifn_fini(void)
+static void __exit hifn_fini(void)
 {
 	pci_unregister_driver(&hifn_pci_driver);
 
diff -druN linux-libre-2.6.30-gnu/drivers/crypto/Kconfig linux-libre-2.6.31-gnu/drivers/crypto/Kconfig
--- linux-libre-2.6.30-gnu/drivers/crypto/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/crypto/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
 
 config CRYPTO_DEV_PADLOCK
 	tristate "Support for VIA PadLock ACE"
-	depends on X86_32 && !UML
+	depends on X86 && !UML
 	select CRYPTO_ALGAPI
 	help
 	  Some VIA processors come with an integrated crypto engine
@@ -34,7 +34,7 @@
 	  Available in VIA C3 and newer CPUs.
 
 	  If unsure say M. The compiled module will be
-	  called padlock-aes.ko
+	  called padlock-aes.
 
 config CRYPTO_DEV_PADLOCK_SHA
 	tristate "PadLock driver for SHA1 and SHA256 algorithms"
@@ -47,7 +47,7 @@
 	  Available in VIA C7 and newer processors.
 
 	  If unsure say M. The compiled module will be
-	  called padlock-sha.ko
+	  called padlock-sha.
 
 config CRYPTO_DEV_GEODE
 	tristate "Support for the Geode LX AES engine"
@@ -79,7 +79,7 @@
 	bool "Monolithic zcrypt module"
 	depends on ZCRYPT="m"
 	help
-	  Select this option if you want to have a single module z90crypt.ko
+	  Select this option if you want to have a single module z90crypt,
 	  that contains all parts of the crypto device driver (ap bus,
 	  request router and all the card drivers).
 
diff -druN linux-libre-2.6.30-gnu/drivers/crypto/padlock-aes.c linux-libre-2.6.31-gnu/drivers/crypto/padlock-aes.c
--- linux-libre-2.6.30-gnu/drivers/crypto/padlock-aes.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/crypto/padlock-aes.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,9 +18,22 @@
 #include <linux/percpu.h>
 #include <linux/smp.h>
 #include <asm/byteorder.h>
+#include <asm/processor.h>
 #include <asm/i387.h>
 #include "padlock.h"
 
+/*
+ * Number of data blocks actually fetched for each xcrypt insn.
+ * Processors with prefetch errata will fetch extra blocks.
+ */
+static unsigned int ecb_fetch_blocks = 2;
+#define MAX_ECB_FETCH_BLOCKS (8)
+#define ecb_fetch_bytes (ecb_fetch_blocks * AES_BLOCK_SIZE)
+
+static unsigned int cbc_fetch_blocks = 1;
+#define MAX_CBC_FETCH_BLOCKS (4)
+#define cbc_fetch_bytes (cbc_fetch_blocks * AES_BLOCK_SIZE)
+
 /* Control word. */
 struct cword {
 	unsigned int __attribute__ ((__packed__))
@@ -154,7 +167,11 @@
 	int cpu = raw_smp_processor_id();
 
 	if (cword != per_cpu(last_cword, cpu))
+#ifndef CONFIG_X86_64
 		asm volatile ("pushfl; popfl");
+#else
+		asm volatile ("pushfq; popfq");
+#endif
 }
 
 static inline void padlock_store_cword(struct cword *cword)
@@ -168,64 +185,111 @@
  * should be used only inside the irq_ts_save/restore() context
  */
 
-static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key,
-				  struct cword *control_word)
+static inline void rep_xcrypt_ecb(const u8 *input, u8 *output, void *key,
+				  struct cword *control_word, int count)
 {
 	asm volatile (".byte 0xf3,0x0f,0xa7,0xc8"	/* rep xcryptecb */
 		      : "+S"(input), "+D"(output)
-		      : "d"(control_word), "b"(key), "c"(1));
+		      : "d"(control_word), "b"(key), "c"(count));
 }
 
-static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword)
+static inline u8 *rep_xcrypt_cbc(const u8 *input, u8 *output, void *key,
+				 u8 *iv, struct cword *control_word, int count)
 {
-	u8 buf[AES_BLOCK_SIZE * 2 + PADLOCK_ALIGNMENT - 1];
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"	/* rep xcryptcbc */
+		      : "+S" (input), "+D" (output), "+a" (iv)
+		      : "d" (control_word), "b" (key), "c" (count));
+	return iv;
+}
+
+static void ecb_crypt_copy(const u8 *in, u8 *out, u32 *key,
+			   struct cword *cword, int count)
+{
+	/*
+	 * Padlock prefetches extra data so we must provide mapped input buffers.
+	 * Assume there are at least 16 bytes of stack already in use.
+	 */
+	u8 buf[AES_BLOCK_SIZE * (MAX_ECB_FETCH_BLOCKS - 1) + PADLOCK_ALIGNMENT - 1];
 	u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
 
-	memcpy(tmp, in, AES_BLOCK_SIZE);
-	padlock_xcrypt(tmp, out, key, cword);
+	memcpy(tmp, in, count * AES_BLOCK_SIZE);
+	rep_xcrypt_ecb(tmp, out, key, cword, count);
 }
 
-static inline void aes_crypt(const u8 *in, u8 *out, u32 *key,
-			     struct cword *cword)
+static u8 *cbc_crypt_copy(const u8 *in, u8 *out, u32 *key,
+			   u8 *iv, struct cword *cword, int count)
 {
-	/* padlock_xcrypt requires at least two blocks of data. */
-	if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) &
-		       (PAGE_SIZE - 1)))) {
-		aes_crypt_copy(in, out, key, cword);
+	/*
+	 * Padlock prefetches extra data so we must provide mapped input buffers.
+	 * Assume there are at least 16 bytes of stack already in use.
+	 */
+	u8 buf[AES_BLOCK_SIZE * (MAX_CBC_FETCH_BLOCKS - 1) + PADLOCK_ALIGNMENT - 1];
+	u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
+
+	memcpy(tmp, in, count * AES_BLOCK_SIZE);
+	return rep_xcrypt_cbc(tmp, out, key, iv, cword, count);
+}
+
+static inline void ecb_crypt(const u8 *in, u8 *out, u32 *key,
+			     struct cword *cword, int count)
+{
+	/* Padlock in ECB mode fetches at least ecb_fetch_bytes of data.
+	 * We could avoid some copying here but it's probably not worth it.
+	 */
+	if (unlikely(((unsigned long)in & PAGE_SIZE) + ecb_fetch_bytes > PAGE_SIZE)) {
+		ecb_crypt_copy(in, out, key, cword, count);
 		return;
 	}
 
-	padlock_xcrypt(in, out, key, cword);
+	rep_xcrypt_ecb(in, out, key, cword, count);
+}
+
+static inline u8 *cbc_crypt(const u8 *in, u8 *out, u32 *key,
+			    u8 *iv, struct cword *cword, int count)
+{
+	/* Padlock in CBC mode fetches at least cbc_fetch_bytes of data. */
+	if (unlikely(((unsigned long)in & PAGE_SIZE) + cbc_fetch_bytes > PAGE_SIZE))
+		return cbc_crypt_copy(in, out, key, iv, cword, count);
+
+	return rep_xcrypt_cbc(in, out, key, iv, cword, count);
 }
 
 static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
 				      void *control_word, u32 count)
 {
-	if (count == 1) {
-		aes_crypt(input, output, key, control_word);
+	u32 initial = count & (ecb_fetch_blocks - 1);
+
+	if (count < ecb_fetch_blocks) {
+		ecb_crypt(input, output, key, control_word, count);
 		return;
 	}
 
-	asm volatile ("test $1, %%cl;"
-		      "je 1f;"
-		      "lea -1(%%ecx), %%eax;"
-		      "mov $1, %%ecx;"
-		      ".byte 0xf3,0x0f,0xa7,0xc8;"	/* rep xcryptecb */
-		      "mov %%eax, %%ecx;"
-		      "1:"
-		      ".byte 0xf3,0x0f,0xa7,0xc8"	/* rep xcryptecb */
+	if (initial)
+		asm volatile (".byte 0xf3,0x0f,0xa7,0xc8"	/* rep xcryptecb */
+			      : "+S"(input), "+D"(output)
+			      : "d"(control_word), "b"(key), "c"(initial));
+
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xc8"	/* rep xcryptecb */
 		      : "+S"(input), "+D"(output)
-		      : "d"(control_word), "b"(key), "c"(count)
-		      : "ax");
+		      : "d"(control_word), "b"(key), "c"(count - initial));
 }
 
 static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
 				     u8 *iv, void *control_word, u32 count)
 {
-	/* rep xcryptcbc */
-	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"
+	u32 initial = count & (cbc_fetch_blocks - 1);
+
+	if (count < cbc_fetch_blocks)
+		return cbc_crypt(input, output, key, iv, control_word, count);
+
+	if (initial)
+		asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"	/* rep xcryptcbc */
+			      : "+S" (input), "+D" (output), "+a" (iv)
+			      : "d" (control_word), "b" (key), "c" (count));
+
+	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"	/* rep xcryptcbc */
 		      : "+S" (input), "+D" (output), "+a" (iv)
-		      : "d" (control_word), "b" (key), "c" (count));
+		      : "d" (control_word), "b" (key), "c" (count-initial));
 	return iv;
 }
 
@@ -236,7 +300,7 @@
 
 	padlock_reset_key(&ctx->cword.encrypt);
 	ts_state = irq_ts_save();
-	aes_crypt(in, out, ctx->E, &ctx->cword.encrypt);
+	ecb_crypt(in, out, ctx->E, &ctx->cword.encrypt, 1);
 	irq_ts_restore(ts_state);
 	padlock_store_cword(&ctx->cword.encrypt);
 }
@@ -248,7 +312,7 @@
 
 	padlock_reset_key(&ctx->cword.encrypt);
 	ts_state = irq_ts_save();
-	aes_crypt(in, out, ctx->D, &ctx->cword.decrypt);
+	ecb_crypt(in, out, ctx->D, &ctx->cword.decrypt, 1);
 	irq_ts_restore(ts_state);
 	padlock_store_cword(&ctx->cword.encrypt);
 }
@@ -441,6 +505,7 @@
 static int __init padlock_init(void)
 {
 	int ret;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 
 	if (!cpu_has_xcrypt) {
 		printk(KERN_NOTICE PFX "VIA PadLock not detected.\n");
@@ -463,6 +528,12 @@
 
 	printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n");
 
+	if (c->x86 == 6 && c->x86_model == 15 && c->x86_mask == 2) {
+		ecb_fetch_blocks = MAX_ECB_FETCH_BLOCKS;
+		cbc_fetch_blocks = MAX_CBC_FETCH_BLOCKS;
+		printk(KERN_NOTICE PFX "VIA Nano stepping 2 detected: enabling workaround.\n");
+	}
+
 out:
 	return ret;
 
diff -druN linux-libre-2.6.30-gnu/drivers/crypto/talitos.c linux-libre-2.6.31-gnu/drivers/crypto/talitos.c
--- linux-libre-2.6.30-gnu/drivers/crypto/talitos.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/crypto/talitos.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,6 +44,8 @@
 #include <crypto/sha.h>
 #include <crypto/aead.h>
 #include <crypto/authenc.h>
+#include <crypto/skcipher.h>
+#include <crypto/scatterwalk.h>
 
 #include "talitos.h"
 
@@ -339,7 +341,8 @@
 				status = error;
 
 		dma_unmap_single(dev, request->dma_desc,
-			sizeof(struct talitos_desc), DMA_BIDIRECTIONAL);
+				 sizeof(struct talitos_desc),
+				 DMA_BIDIRECTIONAL);
 
 		/* copy entries so we can call callback outside lock */
 		saved_req.desc = request->desc;
@@ -413,7 +416,8 @@
 /*
  * user diagnostics; report root cause of error based on execution unit status
  */
-static void report_eu_error(struct device *dev, int ch, struct talitos_desc *desc)
+static void report_eu_error(struct device *dev, int ch,
+			    struct talitos_desc *desc)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int i;
@@ -684,8 +688,8 @@
 	unsigned int authsize;
 };
 
-static int aead_authenc_setauthsize(struct crypto_aead *authenc,
-						 unsigned int authsize)
+static int aead_setauthsize(struct crypto_aead *authenc,
+			    unsigned int authsize)
 {
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
 
@@ -694,8 +698,8 @@
 	return 0;
 }
 
-static int aead_authenc_setkey(struct crypto_aead *authenc,
-					    const u8 *key, unsigned int keylen)
+static int aead_setkey(struct crypto_aead *authenc,
+		       const u8 *key, unsigned int keylen)
 {
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
 	struct rtattr *rta = (void *)key;
@@ -740,7 +744,7 @@
 }
 
 /*
- * ipsec_esp_edesc - s/w-extended ipsec_esp descriptor
+ * talitos_edesc - s/w-extended descriptor
  * @src_nents: number of segments in input scatterlist
  * @dst_nents: number of segments in output scatterlist
  * @dma_len: length of dma mapped link_tbl space
@@ -752,17 +756,67 @@
  * is greater than 1, an integrity check value is concatenated to the end
  * of link_tbl data
  */
-struct ipsec_esp_edesc {
+struct talitos_edesc {
 	int src_nents;
 	int dst_nents;
+	int src_is_chained;
+	int dst_is_chained;
 	int dma_len;
 	dma_addr_t dma_link_tbl;
 	struct talitos_desc desc;
 	struct talitos_ptr link_tbl[0];
 };
 
+static int talitos_map_sg(struct device *dev, struct scatterlist *sg,
+			  unsigned int nents, enum dma_data_direction dir,
+			  int chained)
+{
+	if (unlikely(chained))
+		while (sg) {
+			dma_map_sg(dev, sg, 1, dir);
+			sg = scatterwalk_sg_next(sg);
+		}
+	else
+		dma_map_sg(dev, sg, nents, dir);
+	return nents;
+}
+
+static void talitos_unmap_sg_chain(struct device *dev, struct scatterlist *sg,
+				   enum dma_data_direction dir)
+{
+	while (sg) {
+		dma_unmap_sg(dev, sg, 1, dir);
+		sg = scatterwalk_sg_next(sg);
+	}
+}
+
+static void talitos_sg_unmap(struct device *dev,
+			     struct talitos_edesc *edesc,
+			     struct scatterlist *src,
+			     struct scatterlist *dst)
+{
+	unsigned int src_nents = edesc->src_nents ? : 1;
+	unsigned int dst_nents = edesc->dst_nents ? : 1;
+
+	if (src != dst) {
+		if (edesc->src_is_chained)
+			talitos_unmap_sg_chain(dev, src, DMA_TO_DEVICE);
+		else
+			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
+
+		if (edesc->dst_is_chained)
+			talitos_unmap_sg_chain(dev, dst, DMA_FROM_DEVICE);
+		else
+			dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
+	} else
+		if (edesc->src_is_chained)
+			talitos_unmap_sg_chain(dev, src, DMA_BIDIRECTIONAL);
+		else
+			dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
+}
+
 static void ipsec_esp_unmap(struct device *dev,
-			    struct ipsec_esp_edesc *edesc,
+			    struct talitos_edesc *edesc,
 			    struct aead_request *areq)
 {
 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[6], DMA_FROM_DEVICE);
@@ -772,15 +826,7 @@
 
 	dma_unmap_sg(dev, areq->assoc, 1, DMA_TO_DEVICE);
 
-	if (areq->src != areq->dst) {
-		dma_unmap_sg(dev, areq->src, edesc->src_nents ? : 1,
-			     DMA_TO_DEVICE);
-		dma_unmap_sg(dev, areq->dst, edesc->dst_nents ? : 1,
-			     DMA_FROM_DEVICE);
-	} else {
-		dma_unmap_sg(dev, areq->src, edesc->src_nents ? : 1,
-			     DMA_BIDIRECTIONAL);
-	}
+	talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
 
 	if (edesc->dma_len)
 		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
@@ -795,13 +841,14 @@
 				   int err)
 {
 	struct aead_request *areq = context;
-	struct ipsec_esp_edesc *edesc =
-		 container_of(desc, struct ipsec_esp_edesc, desc);
 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+	struct talitos_edesc *edesc;
 	struct scatterlist *sg;
 	void *icvdata;
 
+	edesc = container_of(desc, struct talitos_edesc, desc);
+
 	ipsec_esp_unmap(dev, edesc, areq);
 
 	/* copy the generated ICV to dst */
@@ -819,17 +866,18 @@
 }
 
 static void ipsec_esp_decrypt_swauth_done(struct device *dev,
-				   struct talitos_desc *desc, void *context,
-				   int err)
+					  struct talitos_desc *desc,
+					  void *context, int err)
 {
 	struct aead_request *req = context;
-	struct ipsec_esp_edesc *edesc =
-		 container_of(desc, struct ipsec_esp_edesc, desc);
 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+	struct talitos_edesc *edesc;
 	struct scatterlist *sg;
 	void *icvdata;
 
+	edesc = container_of(desc, struct talitos_edesc, desc);
+
 	ipsec_esp_unmap(dev, edesc, req);
 
 	if (!err) {
@@ -851,20 +899,20 @@
 }
 
 static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
-				   struct talitos_desc *desc, void *context,
-				   int err)
+					  struct talitos_desc *desc,
+					  void *context, int err)
 {
 	struct aead_request *req = context;
-	struct ipsec_esp_edesc *edesc =
-		 container_of(desc, struct ipsec_esp_edesc, desc);
+	struct talitos_edesc *edesc;
+
+	edesc = container_of(desc, struct talitos_edesc, desc);
 
 	ipsec_esp_unmap(dev, edesc, req);
 
 	/* check ICV auth status */
-	if (!err)
-		if ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
-		    DESC_HDR_LO_ICCR1_PASS)
-			err = -EBADMSG;
+	if (!err && ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
+		     DESC_HDR_LO_ICCR1_PASS))
+		err = -EBADMSG;
 
 	kfree(edesc);
 
@@ -886,7 +934,7 @@
 		link_tbl_ptr->j_extent = 0;
 		link_tbl_ptr++;
 		cryptlen -= sg_dma_len(sg);
-		sg = sg_next(sg);
+		sg = scatterwalk_sg_next(sg);
 	}
 
 	/* adjust (decrease) last one (or two) entry's len to cryptlen */
@@ -910,7 +958,7 @@
 /*
  * fill in and submit ipsec_esp descriptor
  */
-static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
+static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
 		     u8 *giv, u64 seq,
 		     void (*callback) (struct device *dev,
 				       struct talitos_desc *desc,
@@ -952,32 +1000,31 @@
 	desc->ptr[4].len = cpu_to_be16(cryptlen);
 	desc->ptr[4].j_extent = authsize;
 
-	if (areq->src == areq->dst)
-		sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ? : 1,
-				      DMA_BIDIRECTIONAL);
-	else
-		sg_count = dma_map_sg(dev, areq->src, edesc->src_nents ? : 1,
-				      DMA_TO_DEVICE);
+	sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
+				  (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
+							   : DMA_TO_DEVICE,
+				  edesc->src_is_chained);
 
 	if (sg_count == 1) {
 		desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
 	} else {
 		sg_link_tbl_len = cryptlen;
 
-		if ((edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV) &&
-			(edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) {
+		if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
 			sg_link_tbl_len = cryptlen + authsize;
-		}
+
 		sg_count = sg_to_link_tbl(areq->src, sg_count, sg_link_tbl_len,
 					  &edesc->link_tbl[0]);
 		if (sg_count > 1) {
 			desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
 			desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl);
-			dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
-						   edesc->dma_len, DMA_BIDIRECTIONAL);
+			dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+						   edesc->dma_len,
+						   DMA_BIDIRECTIONAL);
 		} else {
 			/* Only one segment now, so no link tbl needed */
-			desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
+			desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->
+								      src));
 		}
 	}
 
@@ -985,10 +1032,11 @@
 	desc->ptr[5].len = cpu_to_be16(cryptlen);
 	desc->ptr[5].j_extent = authsize;
 
-	if (areq->src != areq->dst) {
-		sg_count = dma_map_sg(dev, areq->dst, edesc->dst_nents ? : 1,
-				      DMA_FROM_DEVICE);
-	}
+	if (areq->src != areq->dst)
+		sg_count = talitos_map_sg(dev, areq->dst,
+					  edesc->dst_nents ? : 1,
+					  DMA_FROM_DEVICE,
+					  edesc->dst_is_chained);
 
 	if (sg_count == 1) {
 		desc->ptr[5].ptr = cpu_to_be32(sg_dma_address(areq->dst));
@@ -1033,49 +1081,55 @@
 	return ret;
 }
 
-
 /*
  * derive number of elements in scatterlist
  */
-static int sg_count(struct scatterlist *sg_list, int nbytes)
+static int sg_count(struct scatterlist *sg_list, int nbytes, int *chained)
 {
 	struct scatterlist *sg = sg_list;
 	int sg_nents = 0;
 
-	while (nbytes) {
+	*chained = 0;
+	while (nbytes > 0) {
 		sg_nents++;
 		nbytes -= sg->length;
-		sg = sg_next(sg);
+		if (!sg_is_last(sg) && (sg + 1)->length == 0)
+			*chained = 1;
+		sg = scatterwalk_sg_next(sg);
 	}
 
 	return sg_nents;
 }
 
 /*
- * allocate and map the ipsec_esp extended descriptor
+ * allocate and map the extended descriptor
  */
-static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
-						     int icv_stashing)
+static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
+						 struct scatterlist *src,
+						 struct scatterlist *dst,
+						 unsigned int cryptlen,
+						 unsigned int authsize,
+						 int icv_stashing,
+						 u32 cryptoflags)
 {
-	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
-	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
-	struct ipsec_esp_edesc *edesc;
+	struct talitos_edesc *edesc;
 	int src_nents, dst_nents, alloc_len, dma_len;
-	gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+	int src_chained, dst_chained = 0;
+	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
 		      GFP_ATOMIC;
 
-	if (areq->cryptlen + ctx->authsize > TALITOS_MAX_DATA_LEN) {
-		dev_err(ctx->dev, "cryptlen exceeds h/w max limit\n");
+	if (cryptlen + authsize > TALITOS_MAX_DATA_LEN) {
+		dev_err(dev, "length exceeds h/w max limit\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	src_nents = sg_count(areq->src, areq->cryptlen + ctx->authsize);
+	src_nents = sg_count(src, cryptlen + authsize, &src_chained);
 	src_nents = (src_nents == 1) ? 0 : src_nents;
 
-	if (areq->dst == areq->src) {
+	if (dst == src) {
 		dst_nents = src_nents;
 	} else {
-		dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize);
+		dst_nents = sg_count(dst, cryptlen + authsize, &dst_chained);
 		dst_nents = (dst_nents == 1) ? 0 : dst_nents;
 	}
 
@@ -1084,39 +1138,52 @@
 	 * allowing for two separate entries for ICV and generated ICV (+ 2),
 	 * and the ICV data itself
 	 */
-	alloc_len = sizeof(struct ipsec_esp_edesc);
+	alloc_len = sizeof(struct talitos_edesc);
 	if (src_nents || dst_nents) {
 		dma_len = (src_nents + dst_nents + 2) *
-				 sizeof(struct talitos_ptr) + ctx->authsize;
+				 sizeof(struct talitos_ptr) + authsize;
 		alloc_len += dma_len;
 	} else {
 		dma_len = 0;
-		alloc_len += icv_stashing ? ctx->authsize : 0;
+		alloc_len += icv_stashing ? authsize : 0;
 	}
 
 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
 	if (!edesc) {
-		dev_err(ctx->dev, "could not allocate edescriptor\n");
+		dev_err(dev, "could not allocate edescriptor\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
 	edesc->src_nents = src_nents;
 	edesc->dst_nents = dst_nents;
+	edesc->src_is_chained = src_chained;
+	edesc->dst_is_chained = dst_chained;
 	edesc->dma_len = dma_len;
-	edesc->dma_link_tbl = dma_map_single(ctx->dev, &edesc->link_tbl[0],
+	edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
 					     edesc->dma_len, DMA_BIDIRECTIONAL);
 
 	return edesc;
 }
 
-static int aead_authenc_encrypt(struct aead_request *req)
+static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq,
+					      int icv_stashing)
+{
+	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
+	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+
+	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
+				   areq->cryptlen, ctx->authsize, icv_stashing,
+				   areq->base.flags);
+}
+
+static int aead_encrypt(struct aead_request *req)
 {
 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
-	struct ipsec_esp_edesc *edesc;
+	struct talitos_edesc *edesc;
 
 	/* allocate extended descriptor */
-	edesc = ipsec_esp_edesc_alloc(req, 0);
+	edesc = aead_edesc_alloc(req, 0);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
@@ -1126,70 +1193,67 @@
 	return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_encrypt_done);
 }
 
-
-
-static int aead_authenc_decrypt(struct aead_request *req)
+static int aead_decrypt(struct aead_request *req)
 {
 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
 	unsigned int authsize = ctx->authsize;
 	struct talitos_private *priv = dev_get_drvdata(ctx->dev);
-	struct ipsec_esp_edesc *edesc;
+	struct talitos_edesc *edesc;
 	struct scatterlist *sg;
 	void *icvdata;
 
 	req->cryptlen -= authsize;
 
 	/* allocate extended descriptor */
-	edesc = ipsec_esp_edesc_alloc(req, 1);
+	edesc = aead_edesc_alloc(req, 1);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
 	if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
-	    (((!edesc->src_nents && !edesc->dst_nents) ||
-		priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT))) {
+	    ((!edesc->src_nents && !edesc->dst_nents) ||
+	     priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT)) {
 
 		/* decrypt and check the ICV */
-		edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND |
+		edesc->desc.hdr = ctx->desc_hdr_template |
+				  DESC_HDR_DIR_INBOUND |
 				  DESC_HDR_MODE1_MDEU_CICV;
 
 		/* reset integrity check result bits */
 		edesc->desc.hdr_lo = 0;
 
-		return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_hwauth_done);
-
-	} else {
+		return ipsec_esp(edesc, req, NULL, 0,
+				 ipsec_esp_decrypt_hwauth_done);
 
-		/* Have to check the ICV with software */
+	}
 
-		edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
+	/* Have to check the ICV with software */
+	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
 
-		/* stash incoming ICV for later cmp with ICV generated by the h/w */
-		if (edesc->dma_len)
-			icvdata = &edesc->link_tbl[edesc->src_nents +
-						   edesc->dst_nents + 2];
-		else
-			icvdata = &edesc->link_tbl[0];
+	/* stash incoming ICV for later cmp with ICV generated by the h/w */
+	if (edesc->dma_len)
+		icvdata = &edesc->link_tbl[edesc->src_nents +
+					   edesc->dst_nents + 2];
+	else
+		icvdata = &edesc->link_tbl[0];
 
-		sg = sg_last(req->src, edesc->src_nents ? : 1);
+	sg = sg_last(req->src, edesc->src_nents ? : 1);
 
-		memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
-		       ctx->authsize);
+	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
+	       ctx->authsize);
 
-		return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_swauth_done);
-	}
+	return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_swauth_done);
 }
 
-static int aead_authenc_givencrypt(
-	struct aead_givcrypt_request *req)
+static int aead_givencrypt(struct aead_givcrypt_request *req)
 {
 	struct aead_request *areq = &req->areq;
 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
-	struct ipsec_esp_edesc *edesc;
+	struct talitos_edesc *edesc;
 
 	/* allocate extended descriptor */
-	edesc = ipsec_esp_edesc_alloc(areq, 0);
+	edesc = aead_edesc_alloc(areq, 0);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
@@ -1204,31 +1268,228 @@
 			 ipsec_esp_encrypt_done);
 }
 
+static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen)
+{
+	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+	struct ablkcipher_alg *alg = crypto_ablkcipher_alg(cipher);
+
+	if (keylen > TALITOS_MAX_KEY_SIZE)
+		goto badkey;
+
+	if (keylen < alg->min_keysize || keylen > alg->max_keysize)
+		goto badkey;
+
+	memcpy(&ctx->key, key, keylen);
+	ctx->keylen = keylen;
+
+	return 0;
+
+badkey:
+	crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	return -EINVAL;
+}
+
+static void common_nonsnoop_unmap(struct device *dev,
+				  struct talitos_edesc *edesc,
+				  struct ablkcipher_request *areq)
+{
+	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE);
+	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
+	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], DMA_TO_DEVICE);
+
+	talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
+
+	if (edesc->dma_len)
+		dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len,
+				 DMA_BIDIRECTIONAL);
+}
+
+static void ablkcipher_done(struct device *dev,
+			    struct talitos_desc *desc, void *context,
+			    int err)
+{
+	struct ablkcipher_request *areq = context;
+	struct talitos_edesc *edesc;
+
+	edesc = container_of(desc, struct talitos_edesc, desc);
+
+	common_nonsnoop_unmap(dev, edesc, areq);
+
+	kfree(edesc);
+
+	areq->base.complete(&areq->base, err);
+}
+
+static int common_nonsnoop(struct talitos_edesc *edesc,
+			   struct ablkcipher_request *areq,
+			   u8 *giv,
+			   void (*callback) (struct device *dev,
+					     struct talitos_desc *desc,
+					     void *context, int error))
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+	struct device *dev = ctx->dev;
+	struct talitos_desc *desc = &edesc->desc;
+	unsigned int cryptlen = areq->nbytes;
+	unsigned int ivsize;
+	int sg_count, ret;
+
+	/* first DWORD empty */
+	desc->ptr[0].len = 0;
+	desc->ptr[0].ptr = 0;
+	desc->ptr[0].j_extent = 0;
+
+	/* cipher iv */
+	ivsize = crypto_ablkcipher_ivsize(cipher);
+	map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, giv ?: areq->info, 0,
+			       DMA_TO_DEVICE);
+
+	/* cipher key */
+	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
+			       (char *)&ctx->key, 0, DMA_TO_DEVICE);
+
+	/*
+	 * cipher in
+	 */
+	desc->ptr[3].len = cpu_to_be16(cryptlen);
+	desc->ptr[3].j_extent = 0;
+
+	sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
+				  (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
+							   : DMA_TO_DEVICE,
+				  edesc->src_is_chained);
+
+	if (sg_count == 1) {
+		desc->ptr[3].ptr = cpu_to_be32(sg_dma_address(areq->src));
+	} else {
+		sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen,
+					  &edesc->link_tbl[0]);
+		if (sg_count > 1) {
+			desc->ptr[3].j_extent |= DESC_PTR_LNKTBL_JUMP;
+			desc->ptr[3].ptr = cpu_to_be32(edesc->dma_link_tbl);
+			dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+						   edesc->dma_len,
+						   DMA_BIDIRECTIONAL);
+		} else {
+			/* Only one segment now, so no link tbl needed */
+			desc->ptr[3].ptr = cpu_to_be32(sg_dma_address(areq->
+								      src));
+		}
+	}
+
+	/* cipher out */
+	desc->ptr[4].len = cpu_to_be16(cryptlen);
+	desc->ptr[4].j_extent = 0;
+
+	if (areq->src != areq->dst)
+		sg_count = talitos_map_sg(dev, areq->dst,
+					  edesc->dst_nents ? : 1,
+					  DMA_FROM_DEVICE,
+					  edesc->dst_is_chained);
+
+	if (sg_count == 1) {
+		desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->dst));
+	} else {
+		struct talitos_ptr *link_tbl_ptr =
+			&edesc->link_tbl[edesc->src_nents + 1];
+
+		desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
+		desc->ptr[4].ptr = cpu_to_be32((struct talitos_ptr *)
+					       edesc->dma_link_tbl +
+					       edesc->src_nents + 1);
+		sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
+					  link_tbl_ptr);
+		dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
+					   edesc->dma_len, DMA_BIDIRECTIONAL);
+	}
+
+	/* iv out */
+	map_single_talitos_ptr(dev, &desc->ptr[5], ivsize, ctx->iv, 0,
+			       DMA_FROM_DEVICE);
+
+	/* last DWORD empty */
+	desc->ptr[6].len = 0;
+	desc->ptr[6].ptr = 0;
+	desc->ptr[6].j_extent = 0;
+
+	ret = talitos_submit(dev, desc, callback, areq);
+	if (ret != -EINPROGRESS) {
+		common_nonsnoop_unmap(dev, edesc, areq);
+		kfree(edesc);
+	}
+	return ret;
+}
+
+static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
+						    areq)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, areq->nbytes,
+				   0, 0, areq->base.flags);
+}
+
+static int ablkcipher_encrypt(struct ablkcipher_request *areq)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+	struct talitos_edesc *edesc;
+
+	/* allocate extended descriptor */
+	edesc = ablkcipher_edesc_alloc(areq);
+	if (IS_ERR(edesc))
+		return PTR_ERR(edesc);
+
+	/* set encrypt */
+	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
+
+	return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+}
+
+static int ablkcipher_decrypt(struct ablkcipher_request *areq)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
+	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+	struct talitos_edesc *edesc;
+
+	/* allocate extended descriptor */
+	edesc = ablkcipher_edesc_alloc(areq);
+	if (IS_ERR(edesc))
+		return PTR_ERR(edesc);
+
+	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
+
+	return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+}
+
 struct talitos_alg_template {
-	char name[CRYPTO_MAX_ALG_NAME];
-	char driver_name[CRYPTO_MAX_ALG_NAME];
-	unsigned int blocksize;
-	struct aead_alg aead;
-	struct device *dev;
+	struct crypto_alg alg;
 	__be32 desc_hdr_template;
 };
 
 static struct talitos_alg_template driver_algs[] = {
-	/* single-pass ipsec_esp descriptor */
+	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
 	{
-		.name = "authenc(hmac(sha1),cbc(aes))",
-		.driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
-		.blocksize = AES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
-			.geniv = "<built-in>",
-			.ivsize = AES_BLOCK_SIZE,
-			.maxauthsize = SHA1_DIGEST_SIZE,
-			},
+		.alg = {
+			.cra_name = "authenc(hmac(sha1),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_aead_type,
+			.cra_aead = {
+				.setkey = aead_setkey,
+				.setauthsize = aead_setauthsize,
+				.encrypt = aead_encrypt,
+				.decrypt = aead_decrypt,
+				.givencrypt = aead_givencrypt,
+				.geniv = "<built-in>",
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = SHA1_DIGEST_SIZE,
+			}
+		},
 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
 			             DESC_HDR_SEL0_AESU |
 		                     DESC_HDR_MODE0_AESU_CBC |
@@ -1238,19 +1499,23 @@
 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
 	},
 	{
-		.name = "authenc(hmac(sha1),cbc(des3_ede))",
-		.driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
-		.blocksize = DES3_EDE_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
-			.geniv = "<built-in>",
-			.ivsize = DES3_EDE_BLOCK_SIZE,
-			.maxauthsize = SHA1_DIGEST_SIZE,
-			},
+		.alg = {
+			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_aead_type,
+			.cra_aead = {
+				.setkey = aead_setkey,
+				.setauthsize = aead_setauthsize,
+				.encrypt = aead_encrypt,
+				.decrypt = aead_decrypt,
+				.givencrypt = aead_givencrypt,
+				.geniv = "<built-in>",
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = SHA1_DIGEST_SIZE,
+			}
+		},
 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
 			             DESC_HDR_SEL0_DEU |
 		                     DESC_HDR_MODE0_DEU_CBC |
@@ -1261,19 +1526,23 @@
 		                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
 	},
 	{
-		.name = "authenc(hmac(sha256),cbc(aes))",
-		.driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
-		.blocksize = AES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
-			.geniv = "<built-in>",
-			.ivsize = AES_BLOCK_SIZE,
-			.maxauthsize = SHA256_DIGEST_SIZE,
-			},
+		.alg = {
+			.cra_name = "authenc(hmac(sha256),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_aead_type,
+			.cra_aead = {
+				.setkey = aead_setkey,
+				.setauthsize = aead_setauthsize,
+				.encrypt = aead_encrypt,
+				.decrypt = aead_decrypt,
+				.givencrypt = aead_givencrypt,
+				.geniv = "<built-in>",
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = SHA256_DIGEST_SIZE,
+			}
+		},
 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
 			             DESC_HDR_SEL0_AESU |
 		                     DESC_HDR_MODE0_AESU_CBC |
@@ -1283,19 +1552,23 @@
 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
 	},
 	{
-		.name = "authenc(hmac(sha256),cbc(des3_ede))",
-		.driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
-		.blocksize = DES3_EDE_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
-			.geniv = "<built-in>",
-			.ivsize = DES3_EDE_BLOCK_SIZE,
-			.maxauthsize = SHA256_DIGEST_SIZE,
-			},
+		.alg = {
+			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_aead_type,
+			.cra_aead = {
+				.setkey = aead_setkey,
+				.setauthsize = aead_setauthsize,
+				.encrypt = aead_encrypt,
+				.decrypt = aead_decrypt,
+				.givencrypt = aead_givencrypt,
+				.geniv = "<built-in>",
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = SHA256_DIGEST_SIZE,
+			}
+		},
 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
 			             DESC_HDR_SEL0_DEU |
 		                     DESC_HDR_MODE0_DEU_CBC |
@@ -1306,19 +1579,23 @@
 		                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
 	},
 	{
-		.name = "authenc(hmac(md5),cbc(aes))",
-		.driver_name = "authenc-hmac-md5-cbc-aes-talitos",
-		.blocksize = AES_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
-			.geniv = "<built-in>",
-			.ivsize = AES_BLOCK_SIZE,
-			.maxauthsize = MD5_DIGEST_SIZE,
-			},
+		.alg = {
+			.cra_name = "authenc(hmac(md5),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-md5-cbc-aes-talitos",
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_aead_type,
+			.cra_aead = {
+				.setkey = aead_setkey,
+				.setauthsize = aead_setauthsize,
+				.encrypt = aead_encrypt,
+				.decrypt = aead_decrypt,
+				.givencrypt = aead_givencrypt,
+				.geniv = "<built-in>",
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = MD5_DIGEST_SIZE,
+			}
+		},
 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
 			             DESC_HDR_SEL0_AESU |
 		                     DESC_HDR_MODE0_AESU_CBC |
@@ -1328,19 +1605,23 @@
 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
 	},
 	{
-		.name = "authenc(hmac(md5),cbc(des3_ede))",
-		.driver_name = "authenc-hmac-md5-cbc-3des-talitos",
-		.blocksize = DES3_EDE_BLOCK_SIZE,
-		.aead = {
-			.setkey = aead_authenc_setkey,
-			.setauthsize = aead_authenc_setauthsize,
-			.encrypt = aead_authenc_encrypt,
-			.decrypt = aead_authenc_decrypt,
-			.givencrypt = aead_authenc_givencrypt,
-			.geniv = "<built-in>",
-			.ivsize = DES3_EDE_BLOCK_SIZE,
-			.maxauthsize = MD5_DIGEST_SIZE,
-			},
+		.alg = {
+			.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-md5-cbc-3des-talitos",
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_aead_type,
+			.cra_aead = {
+				.setkey = aead_setkey,
+				.setauthsize = aead_setauthsize,
+				.encrypt = aead_encrypt,
+				.decrypt = aead_decrypt,
+				.givencrypt = aead_givencrypt,
+				.geniv = "<built-in>",
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = MD5_DIGEST_SIZE,
+			}
+		},
 		.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
 			             DESC_HDR_SEL0_DEU |
 		                     DESC_HDR_MODE0_DEU_CBC |
@@ -1349,6 +1630,52 @@
 		                     DESC_HDR_MODE1_MDEU_INIT |
 		                     DESC_HDR_MODE1_MDEU_PAD |
 		                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
+	},
+	/* ABLKCIPHER algorithms. */
+	{
+		.alg = {
+			.cra_name = "cbc(aes)",
+			.cra_driver_name = "cbc-aes-talitos",
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+                                     CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_ablkcipher = {
+				.setkey = ablkcipher_setkey,
+				.encrypt = ablkcipher_encrypt,
+				.decrypt = ablkcipher_decrypt,
+				.geniv = "eseqiv",
+				.min_keysize = AES_MIN_KEY_SIZE,
+				.max_keysize = AES_MAX_KEY_SIZE,
+				.ivsize = AES_BLOCK_SIZE,
+			}
+		},
+		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+				     DESC_HDR_SEL0_AESU |
+				     DESC_HDR_MODE0_AESU_CBC,
+	},
+	{
+		.alg = {
+			.cra_name = "cbc(des3_ede)",
+			.cra_driver_name = "cbc-3des-talitos",
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+                                     CRYPTO_ALG_ASYNC,
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_ablkcipher = {
+				.setkey = ablkcipher_setkey,
+				.encrypt = ablkcipher_encrypt,
+				.decrypt = ablkcipher_decrypt,
+				.geniv = "eseqiv",
+				.min_keysize = DES3_EDE_KEY_SIZE,
+				.max_keysize = DES3_EDE_KEY_SIZE,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+			}
+		},
+		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+			             DESC_HDR_SEL0_DEU |
+		                     DESC_HDR_MODE0_DEU_CBC |
+		                     DESC_HDR_MODE0_DEU_3DES,
 	}
 };
 
@@ -1362,12 +1689,14 @@
 static int talitos_cra_init(struct crypto_tfm *tfm)
 {
 	struct crypto_alg *alg = tfm->__crt_alg;
-	struct talitos_crypto_alg *talitos_alg =
-		 container_of(alg, struct talitos_crypto_alg, crypto_alg);
+	struct talitos_crypto_alg *talitos_alg;
 	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
 
+	talitos_alg =  container_of(alg, struct talitos_crypto_alg, crypto_alg);
+
 	/* update context with ptr to dev */
 	ctx->dev = talitos_alg->dev;
+
 	/* copy descriptor header template value */
 	ctx->desc_hdr_template = talitos_alg->desc_hdr_template;
 
@@ -1453,19 +1782,13 @@
 		return ERR_PTR(-ENOMEM);
 
 	alg = &t_alg->crypto_alg;
+	*alg = template->alg;
 
-	snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name);
-	snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
-		 template->driver_name);
 	alg->cra_module = THIS_MODULE;
 	alg->cra_init = talitos_cra_init;
 	alg->cra_priority = TALITOS_CRA_PRIORITY;
-	alg->cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
-	alg->cra_blocksize = template->blocksize;
 	alg->cra_alignmask = 0;
-	alg->cra_type = &crypto_aead_type;
 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
-	alg->cra_u.aead = template->aead;
 
 	t_alg->desc_hdr_template = template->desc_hdr_template;
 	t_alg->dev = dev;
diff -druN linux-libre-2.6.30-gnu/drivers/dma/at_hdmac.c linux-libre-2.6.31-gnu/drivers/dma/at_hdmac.c
--- linux-libre-2.6.30-gnu/drivers/dma/at_hdmac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/dma/at_hdmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1213 @@
+/*
+ * Driver for the Atmel AHB DMA Controller (aka HDMA or DMAC on AT91 systems)
+ *
+ * Copyright (C) 2008 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 supports the Atmel AHB DMA Controller,
+ *
+ * The driver has currently been tested with the Atmel AT91SAM9RL
+ * and AT91SAM9G45 series.
+ */
+
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "at_hdmac_regs.h"
+
+/*
+ * Glossary
+ * --------
+ *
+ * at_hdmac		: Name of the ATmel AHB DMA Controller
+ * at_dma_ / atdma	: ATmel DMA controller entity related
+ * atc_	/ atchan	: ATmel DMA Channel entity related
+ */
+
+#define	ATC_DEFAULT_CFG		(ATC_FIFOCFG_HALFFIFO)
+#define	ATC_DEFAULT_CTRLA	(0)
+#define	ATC_DEFAULT_CTRLB	(ATC_SIF(0)	\
+				|ATC_DIF(1))
+
+/*
+ * Initial number of descriptors to allocate for each channel. This could
+ * be increased during dma usage.
+ */
+static unsigned int init_nr_desc_per_channel = 64;
+module_param(init_nr_desc_per_channel, uint, 0644);
+MODULE_PARM_DESC(init_nr_desc_per_channel,
+		 "initial descriptors per channel (default: 64)");
+
+
+/* prototypes */
+static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx);
+
+
+/*----------------------------------------------------------------------*/
+
+static struct at_desc *atc_first_active(struct at_dma_chan *atchan)
+{
+	return list_first_entry(&atchan->active_list,
+				struct at_desc, desc_node);
+}
+
+static struct at_desc *atc_first_queued(struct at_dma_chan *atchan)
+{
+	return list_first_entry(&atchan->queue,
+				struct at_desc, desc_node);
+}
+
+/**
+ * atc_alloc_descriptor - allocate and return an initilized descriptor
+ * @chan: the channel to allocate descriptors for
+ * @gfp_flags: GFP allocation flags
+ *
+ * Note: The ack-bit is positioned in the descriptor flag at creation time
+ *       to make initial allocation more convenient. This bit will be cleared
+ *       and control will be given to client at usage time (during
+ *       preparation functions).
+ */
+static struct at_desc *atc_alloc_descriptor(struct dma_chan *chan,
+					    gfp_t gfp_flags)
+{
+	struct at_desc	*desc = NULL;
+	struct at_dma	*atdma = to_at_dma(chan->device);
+	dma_addr_t phys;
+
+	desc = dma_pool_alloc(atdma->dma_desc_pool, gfp_flags, &phys);
+	if (desc) {
+		memset(desc, 0, sizeof(struct at_desc));
+		dma_async_tx_descriptor_init(&desc->txd, chan);
+		/* txd.flags will be overwritten in prep functions */
+		desc->txd.flags = DMA_CTRL_ACK;
+		desc->txd.tx_submit = atc_tx_submit;
+		desc->txd.phys = phys;
+	}
+
+	return desc;
+}
+
+/**
+ * atc_desc_get - get a unsused descriptor from free_list
+ * @atchan: channel we want a new descriptor for
+ */
+static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
+{
+	struct at_desc *desc, *_desc;
+	struct at_desc *ret = NULL;
+	unsigned int i = 0;
+	LIST_HEAD(tmp_list);
+
+	spin_lock_bh(&atchan->lock);
+	list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
+		i++;
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del(&desc->desc_node);
+			ret = desc;
+			break;
+		}
+		dev_dbg(chan2dev(&atchan->chan_common),
+				"desc %p not ACKed\n", desc);
+	}
+	spin_unlock_bh(&atchan->lock);
+	dev_vdbg(chan2dev(&atchan->chan_common),
+		"scanned %u descriptors on freelist\n", i);
+
+	/* no more descriptor available in initial pool: create one more */
+	if (!ret) {
+		ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC);
+		if (ret) {
+			spin_lock_bh(&atchan->lock);
+			atchan->descs_allocated++;
+			spin_unlock_bh(&atchan->lock);
+		} else {
+			dev_err(chan2dev(&atchan->chan_common),
+					"not enough descriptors available\n");
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * atc_desc_put - move a descriptor, including any children, to the free list
+ * @atchan: channel we work on
+ * @desc: descriptor, at the head of a chain, to move to free list
+ */
+static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
+{
+	if (desc) {
+		struct at_desc *child;
+
+		spin_lock_bh(&atchan->lock);
+		list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+			dev_vdbg(chan2dev(&atchan->chan_common),
+					"moving child desc %p to freelist\n",
+					child);
+		list_splice_init(&desc->txd.tx_list, &atchan->free_list);
+		dev_vdbg(chan2dev(&atchan->chan_common),
+			 "moving desc %p to freelist\n", desc);
+		list_add(&desc->desc_node, &atchan->free_list);
+		spin_unlock_bh(&atchan->lock);
+	}
+}
+
+/**
+ * atc_assign_cookie - compute and assign new cookie
+ * @atchan: channel we work on
+ * @desc: descriptor to asign cookie for
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static dma_cookie_t
+atc_assign_cookie(struct at_dma_chan *atchan, struct at_desc *desc)
+{
+	dma_cookie_t cookie = atchan->chan_common.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	atchan->chan_common.cookie = cookie;
+	desc->txd.cookie = cookie;
+
+	return cookie;
+}
+
+/**
+ * atc_dostart - starts the DMA engine for real
+ * @atchan: the channel we want to start
+ * @first: first descriptor in the list we want to begin with
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
+{
+	struct at_dma	*atdma = to_at_dma(atchan->chan_common.device);
+
+	/* ASSERT:  channel is idle */
+	if (atc_chan_is_enabled(atchan)) {
+		dev_err(chan2dev(&atchan->chan_common),
+			"BUG: Attempted to start non-idle channel\n");
+		dev_err(chan2dev(&atchan->chan_common),
+			"  channel: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
+			channel_readl(atchan, SADDR),
+			channel_readl(atchan, DADDR),
+			channel_readl(atchan, CTRLA),
+			channel_readl(atchan, CTRLB),
+			channel_readl(atchan, DSCR));
+
+		/* The tasklet will hopefully advance the queue... */
+		return;
+	}
+
+	vdbg_dump_regs(atchan);
+
+	/* clear any pending interrupt */
+	while (dma_readl(atdma, EBCISR))
+		cpu_relax();
+
+	channel_writel(atchan, SADDR, 0);
+	channel_writel(atchan, DADDR, 0);
+	channel_writel(atchan, CTRLA, 0);
+	channel_writel(atchan, CTRLB, 0);
+	channel_writel(atchan, DSCR, first->txd.phys);
+	dma_writel(atdma, CHER, atchan->mask);
+
+	vdbg_dump_regs(atchan);
+}
+
+/**
+ * atc_chain_complete - finish work for one transaction chain
+ * @atchan: channel we work on
+ * @desc: descriptor at the head of the chain we want do complete
+ *
+ * Called with atchan->lock held and bh disabled */
+static void
+atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
+{
+	dma_async_tx_callback		callback;
+	void				*param;
+	struct dma_async_tx_descriptor	*txd = &desc->txd;
+
+	dev_vdbg(chan2dev(&atchan->chan_common),
+		"descriptor %u complete\n", txd->cookie);
+
+	atchan->completed_cookie = txd->cookie;
+	callback = txd->callback;
+	param = txd->callback_param;
+
+	/* move children to free_list */
+	list_splice_init(&txd->tx_list, &atchan->free_list);
+	/* move myself to free_list */
+	list_move(&desc->desc_node, &atchan->free_list);
+
+	/* unmap dma addresses */
+	if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+			dma_unmap_single(chan2parent(&atchan->chan_common),
+					desc->lli.daddr,
+					desc->len, DMA_FROM_DEVICE);
+		else
+			dma_unmap_page(chan2parent(&atchan->chan_common),
+					desc->lli.daddr,
+					desc->len, DMA_FROM_DEVICE);
+	}
+	if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+			dma_unmap_single(chan2parent(&atchan->chan_common),
+					desc->lli.saddr,
+					desc->len, DMA_TO_DEVICE);
+		else
+			dma_unmap_page(chan2parent(&atchan->chan_common),
+					desc->lli.saddr,
+					desc->len, DMA_TO_DEVICE);
+	}
+
+	/*
+	 * The API requires that no submissions are done from a
+	 * callback, so we don't need to drop the lock here
+	 */
+	if (callback)
+		callback(param);
+
+	dma_run_dependencies(txd);
+}
+
+/**
+ * atc_complete_all - finish work for all transactions
+ * @atchan: channel to complete transactions for
+ *
+ * Eventually submit queued descriptors if any
+ *
+ * Assume channel is idle while calling this function
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_complete_all(struct at_dma_chan *atchan)
+{
+	struct at_desc *desc, *_desc;
+	LIST_HEAD(list);
+
+	dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n");
+
+	BUG_ON(atc_chan_is_enabled(atchan));
+
+	/*
+	 * Submit queued descriptors ASAP, i.e. before we go through
+	 * the completed ones.
+	 */
+	if (!list_empty(&atchan->queue))
+		atc_dostart(atchan, atc_first_queued(atchan));
+	/* empty active_list now it is completed */
+	list_splice_init(&atchan->active_list, &list);
+	/* empty queue list by moving descriptors (if any) to active_list */
+	list_splice_init(&atchan->queue, &atchan->active_list);
+
+	list_for_each_entry_safe(desc, _desc, &list, desc_node)
+		atc_chain_complete(atchan, desc);
+}
+
+/**
+ * atc_cleanup_descriptors - cleanup up finished descriptors in active_list
+ * @atchan: channel to be cleaned up
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_cleanup_descriptors(struct at_dma_chan *atchan)
+{
+	struct at_desc	*desc, *_desc;
+	struct at_desc	*child;
+
+	dev_vdbg(chan2dev(&atchan->chan_common), "cleanup descriptors\n");
+
+	list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) {
+		if (!(desc->lli.ctrla & ATC_DONE))
+			/* This one is currently in progress */
+			return;
+
+		list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+			if (!(child->lli.ctrla & ATC_DONE))
+				/* Currently in progress */
+				return;
+
+		/*
+		 * No descriptors so far seem to be in progress, i.e.
+		 * this chain must be done.
+		 */
+		atc_chain_complete(atchan, desc);
+	}
+}
+
+/**
+ * atc_advance_work - at the end of a transaction, move forward
+ * @atchan: channel where the transaction ended
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_advance_work(struct at_dma_chan *atchan)
+{
+	dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n");
+
+	if (list_empty(&atchan->active_list) ||
+	    list_is_singular(&atchan->active_list)) {
+		atc_complete_all(atchan);
+	} else {
+		atc_chain_complete(atchan, atc_first_active(atchan));
+		/* advance work */
+		atc_dostart(atchan, atc_first_active(atchan));
+	}
+}
+
+
+/**
+ * atc_handle_error - handle errors reported by DMA controller
+ * @atchan: channel where error occurs
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_handle_error(struct at_dma_chan *atchan)
+{
+	struct at_desc *bad_desc;
+	struct at_desc *child;
+
+	/*
+	 * The descriptor currently at the head of the active list is
+	 * broked. Since we don't have any way to report errors, we'll
+	 * just have to scream loudly and try to carry on.
+	 */
+	bad_desc = atc_first_active(atchan);
+	list_del_init(&bad_desc->desc_node);
+
+	/* As we are stopped, take advantage to push queued descriptors
+	 * in active_list */
+	list_splice_init(&atchan->queue, atchan->active_list.prev);
+
+	/* Try to restart the controller */
+	if (!list_empty(&atchan->active_list))
+		atc_dostart(atchan, atc_first_active(atchan));
+
+	/*
+	 * KERN_CRITICAL may seem harsh, but since this only happens
+	 * when someone submits a bad physical address in a
+	 * descriptor, we should consider ourselves lucky that the
+	 * controller flagged an error instead of scribbling over
+	 * random memory locations.
+	 */
+	dev_crit(chan2dev(&atchan->chan_common),
+			"Bad descriptor submitted for DMA!\n");
+	dev_crit(chan2dev(&atchan->chan_common),
+			"  cookie: %d\n", bad_desc->txd.cookie);
+	atc_dump_lli(atchan, &bad_desc->lli);
+	list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
+		atc_dump_lli(atchan, &child->lli);
+
+	/* Pretend the descriptor completed successfully */
+	atc_chain_complete(atchan, bad_desc);
+}
+
+
+/*--  IRQ & Tasklet  ---------------------------------------------------*/
+
+static void atc_tasklet(unsigned long data)
+{
+	struct at_dma_chan *atchan = (struct at_dma_chan *)data;
+
+	/* Channel cannot be enabled here */
+	if (atc_chan_is_enabled(atchan)) {
+		dev_err(chan2dev(&atchan->chan_common),
+			"BUG: channel enabled in tasklet\n");
+		return;
+	}
+
+	spin_lock(&atchan->lock);
+	if (test_and_clear_bit(0, &atchan->error_status))
+		atc_handle_error(atchan);
+	else
+		atc_advance_work(atchan);
+
+	spin_unlock(&atchan->lock);
+}
+
+static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
+{
+	struct at_dma		*atdma = (struct at_dma *)dev_id;
+	struct at_dma_chan	*atchan;
+	int			i;
+	u32			status, pending, imr;
+	int			ret = IRQ_NONE;
+
+	do {
+		imr = dma_readl(atdma, EBCIMR);
+		status = dma_readl(atdma, EBCISR);
+		pending = status & imr;
+
+		if (!pending)
+			break;
+
+		dev_vdbg(atdma->dma_common.dev,
+			"interrupt: status = 0x%08x, 0x%08x, 0x%08x\n",
+			 status, imr, pending);
+
+		for (i = 0; i < atdma->dma_common.chancnt; i++) {
+			atchan = &atdma->chan[i];
+			if (pending & (AT_DMA_CBTC(i) | AT_DMA_ERR(i))) {
+				if (pending & AT_DMA_ERR(i)) {
+					/* Disable channel on AHB error */
+					dma_writel(atdma, CHDR, atchan->mask);
+					/* Give information to tasklet */
+					set_bit(0, &atchan->error_status);
+				}
+				tasklet_schedule(&atchan->tasklet);
+				ret = IRQ_HANDLED;
+			}
+		}
+
+	} while (pending);
+
+	return ret;
+}
+
+
+/*--  DMA Engine API  --------------------------------------------------*/
+
+/**
+ * atc_tx_submit - set the prepared descriptor(s) to be executed by the engine
+ * @desc: descriptor at the head of the transaction chain
+ *
+ * Queue chain if DMA engine is working already
+ *
+ * Cookie increment and adding to active_list or queue must be atomic
+ */
+static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct at_desc		*desc = txd_to_at_desc(tx);
+	struct at_dma_chan	*atchan = to_at_dma_chan(tx->chan);
+	dma_cookie_t		cookie;
+
+	spin_lock_bh(&atchan->lock);
+	cookie = atc_assign_cookie(atchan, desc);
+
+	if (list_empty(&atchan->active_list)) {
+		dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
+				desc->txd.cookie);
+		atc_dostart(atchan, desc);
+		list_add_tail(&desc->desc_node, &atchan->active_list);
+	} else {
+		dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
+				desc->txd.cookie);
+		list_add_tail(&desc->desc_node, &atchan->queue);
+	}
+
+	spin_unlock_bh(&atchan->lock);
+
+	return cookie;
+}
+
+/**
+ * atc_prep_dma_memcpy - prepare a memcpy operation
+ * @chan: the channel to prepare operation on
+ * @dest: operation virtual destination address
+ * @src: operation virtual source address
+ * @len: operation length
+ * @flags: tx descriptor status flags
+ */
+static struct dma_async_tx_descriptor *
+atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags)
+{
+	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	struct at_desc		*desc = NULL;
+	struct at_desc		*first = NULL;
+	struct at_desc		*prev = NULL;
+	size_t			xfer_count;
+	size_t			offset;
+	unsigned int		src_width;
+	unsigned int		dst_width;
+	u32			ctrla;
+	u32			ctrlb;
+
+	dev_vdbg(chan2dev(chan), "prep_dma_memcpy: d0x%x s0x%x l0x%zx f0x%lx\n",
+			dest, src, len, flags);
+
+	if (unlikely(!len)) {
+		dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+		return NULL;
+	}
+
+	ctrla =   ATC_DEFAULT_CTRLA;
+	ctrlb =   ATC_DEFAULT_CTRLB
+		| ATC_SRC_ADDR_MODE_INCR
+		| ATC_DST_ADDR_MODE_INCR
+		| ATC_FC_MEM2MEM;
+
+	/*
+	 * We can be a lot more clever here, but this should take care
+	 * of the most common optimization.
+	 */
+	if (!((src | dest  | len) & 3)) {
+		ctrla |= ATC_SRC_WIDTH_WORD | ATC_DST_WIDTH_WORD;
+		src_width = dst_width = 2;
+	} else if (!((src | dest | len) & 1)) {
+		ctrla |= ATC_SRC_WIDTH_HALFWORD | ATC_DST_WIDTH_HALFWORD;
+		src_width = dst_width = 1;
+	} else {
+		ctrla |= ATC_SRC_WIDTH_BYTE | ATC_DST_WIDTH_BYTE;
+		src_width = dst_width = 0;
+	}
+
+	for (offset = 0; offset < len; offset += xfer_count << src_width) {
+		xfer_count = min_t(size_t, (len - offset) >> src_width,
+				ATC_BTSIZE_MAX);
+
+		desc = atc_desc_get(atchan);
+		if (!desc)
+			goto err_desc_get;
+
+		desc->lli.saddr = src + offset;
+		desc->lli.daddr = dest + offset;
+		desc->lli.ctrla = ctrla | xfer_count;
+		desc->lli.ctrlb = ctrlb;
+
+		desc->txd.cookie = 0;
+		async_tx_ack(&desc->txd);
+
+		if (!first) {
+			first = desc;
+		} else {
+			/* inform the HW lli about chaining */
+			prev->lli.dscr = desc->txd.phys;
+			/* insert the link descriptor to the LD ring */
+			list_add_tail(&desc->desc_node,
+					&first->txd.tx_list);
+		}
+		prev = desc;
+	}
+
+	/* First descriptor of the chain embedds additional information */
+	first->txd.cookie = -EBUSY;
+	first->len = len;
+
+	/* set end-of-link to the last link descriptor of list*/
+	set_desc_eol(desc);
+
+	desc->txd.flags = flags; /* client is in control of this ack */
+
+	return &first->txd;
+
+err_desc_get:
+	atc_desc_put(atchan, first);
+	return NULL;
+}
+
+
+/**
+ * atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
+ * @chan: DMA channel
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @scatterlist
+ * @direction: DMA direction
+ * @flags: tx descriptor status flags
+ */
+static struct dma_async_tx_descriptor *
+atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
+		unsigned long flags)
+{
+	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	struct at_dma_slave	*atslave = chan->private;
+	struct at_desc		*first = NULL;
+	struct at_desc		*prev = NULL;
+	u32			ctrla;
+	u32			ctrlb;
+	dma_addr_t		reg;
+	unsigned int		reg_width;
+	unsigned int		mem_width;
+	unsigned int		i;
+	struct scatterlist	*sg;
+	size_t			total_len = 0;
+
+	dev_vdbg(chan2dev(chan), "prep_slave_sg: %s f0x%lx\n",
+			direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE",
+			flags);
+
+	if (unlikely(!atslave || !sg_len)) {
+		dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+		return NULL;
+	}
+
+	reg_width = atslave->reg_width;
+
+	sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction);
+
+	ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla;
+	ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN;
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		ctrla |=  ATC_DST_WIDTH(reg_width);
+		ctrlb |=  ATC_DST_ADDR_MODE_FIXED
+			| ATC_SRC_ADDR_MODE_INCR
+			| ATC_FC_MEM2PER;
+		reg = atslave->tx_reg;
+		for_each_sg(sgl, sg, sg_len, i) {
+			struct at_desc	*desc;
+			u32		len;
+			u32		mem;
+
+			desc = atc_desc_get(atchan);
+			if (!desc)
+				goto err_desc_get;
+
+			mem = sg_phys(sg);
+			len = sg_dma_len(sg);
+			mem_width = 2;
+			if (unlikely(mem & 3 || len & 3))
+				mem_width = 0;
+
+			desc->lli.saddr = mem;
+			desc->lli.daddr = reg;
+			desc->lli.ctrla = ctrla
+					| ATC_SRC_WIDTH(mem_width)
+					| len >> mem_width;
+			desc->lli.ctrlb = ctrlb;
+
+			if (!first) {
+				first = desc;
+			} else {
+				/* inform the HW lli about chaining */
+				prev->lli.dscr = desc->txd.phys;
+				/* insert the link descriptor to the LD ring */
+				list_add_tail(&desc->desc_node,
+						&first->txd.tx_list);
+			}
+			prev = desc;
+			total_len += len;
+		}
+		break;
+	case DMA_FROM_DEVICE:
+		ctrla |=  ATC_SRC_WIDTH(reg_width);
+		ctrlb |=  ATC_DST_ADDR_MODE_INCR
+			| ATC_SRC_ADDR_MODE_FIXED
+			| ATC_FC_PER2MEM;
+
+		reg = atslave->rx_reg;
+		for_each_sg(sgl, sg, sg_len, i) {
+			struct at_desc	*desc;
+			u32		len;
+			u32		mem;
+
+			desc = atc_desc_get(atchan);
+			if (!desc)
+				goto err_desc_get;
+
+			mem = sg_phys(sg);
+			len = sg_dma_len(sg);
+			mem_width = 2;
+			if (unlikely(mem & 3 || len & 3))
+				mem_width = 0;
+
+			desc->lli.saddr = reg;
+			desc->lli.daddr = mem;
+			desc->lli.ctrla = ctrla
+					| ATC_DST_WIDTH(mem_width)
+					| len >> mem_width;
+			desc->lli.ctrlb = ctrlb;
+
+			if (!first) {
+				first = desc;
+			} else {
+				/* inform the HW lli about chaining */
+				prev->lli.dscr = desc->txd.phys;
+				/* insert the link descriptor to the LD ring */
+				list_add_tail(&desc->desc_node,
+						&first->txd.tx_list);
+			}
+			prev = desc;
+			total_len += len;
+		}
+		break;
+	default:
+		return NULL;
+	}
+
+	/* set end-of-link to the last link descriptor of list*/
+	set_desc_eol(prev);
+
+	/* First descriptor of the chain embedds additional information */
+	first->txd.cookie = -EBUSY;
+	first->len = total_len;
+
+	/* last link descriptor of list is responsible of flags */
+	prev->txd.flags = flags; /* client is in control of this ack */
+
+	return &first->txd;
+
+err_desc_get:
+	dev_err(chan2dev(chan), "not enough descriptors available\n");
+	atc_desc_put(atchan, first);
+	return NULL;
+}
+
+static void atc_terminate_all(struct dma_chan *chan)
+{
+	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	struct at_dma		*atdma = to_at_dma(chan->device);
+	struct at_desc		*desc, *_desc;
+	LIST_HEAD(list);
+
+	/*
+	 * This is only called when something went wrong elsewhere, so
+	 * we don't really care about the data. Just disable the
+	 * channel. We still have to poll the channel enable bit due
+	 * to AHB/HSB limitations.
+	 */
+	spin_lock_bh(&atchan->lock);
+
+	dma_writel(atdma, CHDR, atchan->mask);
+
+	/* confirm that this channel is disabled */
+	while (dma_readl(atdma, CHSR) & atchan->mask)
+		cpu_relax();
+
+	/* active_list entries will end up before queued entries */
+	list_splice_init(&atchan->queue, &list);
+	list_splice_init(&atchan->active_list, &list);
+
+	spin_unlock_bh(&atchan->lock);
+
+	/* Flush all pending and queued descriptors */
+	list_for_each_entry_safe(desc, _desc, &list, desc_node)
+		atc_chain_complete(atchan, desc);
+}
+
+/**
+ * atc_is_tx_complete - poll for transaction completion
+ * @chan: DMA channel
+ * @cookie: transaction identifier to check status of
+ * @done: if not %NULL, updated with last completed transaction
+ * @used: if not %NULL, updated with last used transaction
+ *
+ * If @done and @used are passed in, upon return they reflect the driver
+ * internal state and can be used with dma_async_is_complete() to check
+ * the status of multiple cookies without re-checking hardware state.
+ */
+static enum dma_status
+atc_is_tx_complete(struct dma_chan *chan,
+		dma_cookie_t cookie,
+		dma_cookie_t *done, dma_cookie_t *used)
+{
+	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	dma_cookie_t		last_used;
+	dma_cookie_t		last_complete;
+	enum dma_status		ret;
+
+	dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n",
+			cookie, done ? *done : 0, used ? *used : 0);
+
+	spin_lock_bh(atchan->lock);
+
+	last_complete = atchan->completed_cookie;
+	last_used = chan->cookie;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret != DMA_SUCCESS) {
+		atc_cleanup_descriptors(atchan);
+
+		last_complete = atchan->completed_cookie;
+		last_used = chan->cookie;
+
+		ret = dma_async_is_complete(cookie, last_complete, last_used);
+	}
+
+	spin_unlock_bh(atchan->lock);
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return ret;
+}
+
+/**
+ * atc_issue_pending - try to finish work
+ * @chan: target DMA channel
+ */
+static void atc_issue_pending(struct dma_chan *chan)
+{
+	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+
+	dev_vdbg(chan2dev(chan), "issue_pending\n");
+
+	if (!atc_chan_is_enabled(atchan)) {
+		spin_lock_bh(&atchan->lock);
+		atc_advance_work(atchan);
+		spin_unlock_bh(&atchan->lock);
+	}
+}
+
+/**
+ * atc_alloc_chan_resources - allocate resources for DMA channel
+ * @chan: allocate descriptor resources for this channel
+ * @client: current client requesting the channel be ready for requests
+ *
+ * return - the number of allocated descriptors
+ */
+static int atc_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	struct at_dma		*atdma = to_at_dma(chan->device);
+	struct at_desc		*desc;
+	struct at_dma_slave	*atslave;
+	int			i;
+	u32			cfg;
+	LIST_HEAD(tmp_list);
+
+	dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
+
+	/* ASSERT:  channel is idle */
+	if (atc_chan_is_enabled(atchan)) {
+		dev_dbg(chan2dev(chan), "DMA channel not idle ?\n");
+		return -EIO;
+	}
+
+	cfg = ATC_DEFAULT_CFG;
+
+	atslave = chan->private;
+	if (atslave) {
+		/*
+		 * We need controller-specific data to set up slave
+		 * transfers.
+		 */
+		BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_common.dev);
+
+		/* if cfg configuration specified take it instad of default */
+		if (atslave->cfg)
+			cfg = atslave->cfg;
+	}
+
+	/* have we already been set up?
+	 * reconfigure channel but no need to reallocate descriptors */
+	if (!list_empty(&atchan->free_list))
+		return atchan->descs_allocated;
+
+	/* Allocate initial pool of descriptors */
+	for (i = 0; i < init_nr_desc_per_channel; i++) {
+		desc = atc_alloc_descriptor(chan, GFP_KERNEL);
+		if (!desc) {
+			dev_err(atdma->dma_common.dev,
+				"Only %d initial descriptors\n", i);
+			break;
+		}
+		list_add_tail(&desc->desc_node, &tmp_list);
+	}
+
+	spin_lock_bh(&atchan->lock);
+	atchan->descs_allocated = i;
+	list_splice(&tmp_list, &atchan->free_list);
+	atchan->completed_cookie = chan->cookie = 1;
+	spin_unlock_bh(&atchan->lock);
+
+	/* channel parameters */
+	channel_writel(atchan, CFG, cfg);
+
+	dev_dbg(chan2dev(chan),
+		"alloc_chan_resources: allocated %d descriptors\n",
+		atchan->descs_allocated);
+
+	return atchan->descs_allocated;
+}
+
+/**
+ * atc_free_chan_resources - free all channel resources
+ * @chan: DMA channel
+ */
+static void atc_free_chan_resources(struct dma_chan *chan)
+{
+	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+	struct at_dma		*atdma = to_at_dma(chan->device);
+	struct at_desc		*desc, *_desc;
+	LIST_HEAD(list);
+
+	dev_dbg(chan2dev(chan), "free_chan_resources: (descs allocated=%u)\n",
+		atchan->descs_allocated);
+
+	/* ASSERT:  channel is idle */
+	BUG_ON(!list_empty(&atchan->active_list));
+	BUG_ON(!list_empty(&atchan->queue));
+	BUG_ON(atc_chan_is_enabled(atchan));
+
+	list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
+		dev_vdbg(chan2dev(chan), "  freeing descriptor %p\n", desc);
+		list_del(&desc->desc_node);
+		/* free link descriptor */
+		dma_pool_free(atdma->dma_desc_pool, desc, desc->txd.phys);
+	}
+	list_splice_init(&atchan->free_list, &list);
+	atchan->descs_allocated = 0;
+
+	dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
+}
+
+
+/*--  Module Management  -----------------------------------------------*/
+
+/**
+ * at_dma_off - disable DMA controller
+ * @atdma: the Atmel HDAMC device
+ */
+static void at_dma_off(struct at_dma *atdma)
+{
+	dma_writel(atdma, EN, 0);
+
+	/* disable all interrupts */
+	dma_writel(atdma, EBCIDR, -1L);
+
+	/* confirm that all channels are disabled */
+	while (dma_readl(atdma, CHSR) & atdma->all_chan_mask)
+		cpu_relax();
+}
+
+static int __init at_dma_probe(struct platform_device *pdev)
+{
+	struct at_dma_platform_data *pdata;
+	struct resource		*io;
+	struct at_dma		*atdma;
+	size_t			size;
+	int			irq;
+	int			err;
+	int			i;
+
+	/* get DMA Controller parameters from platform */
+	pdata = pdev->dev.platform_data;
+	if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS)
+		return -EINVAL;
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!io)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	size = sizeof(struct at_dma);
+	size += pdata->nr_channels * sizeof(struct at_dma_chan);
+	atdma = kzalloc(size, GFP_KERNEL);
+	if (!atdma)
+		return -ENOMEM;
+
+	/* discover transaction capabilites from the platform data */
+	atdma->dma_common.cap_mask = pdata->cap_mask;
+	atdma->all_chan_mask = (1 << pdata->nr_channels) - 1;
+
+	size = io->end - io->start + 1;
+	if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
+		err = -EBUSY;
+		goto err_kfree;
+	}
+
+	atdma->regs = ioremap(io->start, size);
+	if (!atdma->regs) {
+		err = -ENOMEM;
+		goto err_release_r;
+	}
+
+	atdma->clk = clk_get(&pdev->dev, "dma_clk");
+	if (IS_ERR(atdma->clk)) {
+		err = PTR_ERR(atdma->clk);
+		goto err_clk;
+	}
+	clk_enable(atdma->clk);
+
+	/* force dma off, just in case */
+	at_dma_off(atdma);
+
+	err = request_irq(irq, at_dma_interrupt, 0, "at_hdmac", atdma);
+	if (err)
+		goto err_irq;
+
+	platform_set_drvdata(pdev, atdma);
+
+	/* create a pool of consistent memory blocks for hardware descriptors */
+	atdma->dma_desc_pool = dma_pool_create("at_hdmac_desc_pool",
+			&pdev->dev, sizeof(struct at_desc),
+			4 /* word alignment */, 0);
+	if (!atdma->dma_desc_pool) {
+		dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
+		err = -ENOMEM;
+		goto err_pool_create;
+	}
+
+	/* clear any pending interrupt */
+	while (dma_readl(atdma, EBCISR))
+		cpu_relax();
+
+	/* initialize channels related values */
+	INIT_LIST_HEAD(&atdma->dma_common.channels);
+	for (i = 0; i < pdata->nr_channels; i++, atdma->dma_common.chancnt++) {
+		struct at_dma_chan	*atchan = &atdma->chan[i];
+
+		atchan->chan_common.device = &atdma->dma_common;
+		atchan->chan_common.cookie = atchan->completed_cookie = 1;
+		atchan->chan_common.chan_id = i;
+		list_add_tail(&atchan->chan_common.device_node,
+				&atdma->dma_common.channels);
+
+		atchan->ch_regs = atdma->regs + ch_regs(i);
+		spin_lock_init(&atchan->lock);
+		atchan->mask = 1 << i;
+
+		INIT_LIST_HEAD(&atchan->active_list);
+		INIT_LIST_HEAD(&atchan->queue);
+		INIT_LIST_HEAD(&atchan->free_list);
+
+		tasklet_init(&atchan->tasklet, atc_tasklet,
+				(unsigned long)atchan);
+		atc_enable_irq(atchan);
+	}
+
+	/* set base routines */
+	atdma->dma_common.device_alloc_chan_resources = atc_alloc_chan_resources;
+	atdma->dma_common.device_free_chan_resources = atc_free_chan_resources;
+	atdma->dma_common.device_is_tx_complete = atc_is_tx_complete;
+	atdma->dma_common.device_issue_pending = atc_issue_pending;
+	atdma->dma_common.dev = &pdev->dev;
+
+	/* set prep routines based on capability */
+	if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
+		atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
+
+	if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
+		atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
+		atdma->dma_common.device_terminate_all = atc_terminate_all;
+	}
+
+	dma_writel(atdma, EN, AT_DMA_ENABLE);
+
+	dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
+	  dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
+	  dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
+	  atdma->dma_common.chancnt);
+
+	dma_async_device_register(&atdma->dma_common);
+
+	return 0;
+
+err_pool_create:
+	platform_set_drvdata(pdev, NULL);
+	free_irq(platform_get_irq(pdev, 0), atdma);
+err_irq:
+	clk_disable(atdma->clk);
+	clk_put(atdma->clk);
+err_clk:
+	iounmap(atdma->regs);
+	atdma->regs = NULL;
+err_release_r:
+	release_mem_region(io->start, size);
+err_kfree:
+	kfree(atdma);
+	return err;
+}
+
+static int __exit at_dma_remove(struct platform_device *pdev)
+{
+	struct at_dma		*atdma = platform_get_drvdata(pdev);
+	struct dma_chan		*chan, *_chan;
+	struct resource		*io;
+
+	at_dma_off(atdma);
+	dma_async_device_unregister(&atdma->dma_common);
+
+	dma_pool_destroy(atdma->dma_desc_pool);
+	platform_set_drvdata(pdev, NULL);
+	free_irq(platform_get_irq(pdev, 0), atdma);
+
+	list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+			device_node) {
+		struct at_dma_chan	*atchan = to_at_dma_chan(chan);
+
+		/* Disable interrupts */
+		atc_disable_irq(atchan);
+		tasklet_disable(&atchan->tasklet);
+
+		tasklet_kill(&atchan->tasklet);
+		list_del(&chan->device_node);
+	}
+
+	clk_disable(atdma->clk);
+	clk_put(atdma->clk);
+
+	iounmap(atdma->regs);
+	atdma->regs = NULL;
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(io->start, io->end - io->start + 1);
+
+	kfree(atdma);
+
+	return 0;
+}
+
+static void at_dma_shutdown(struct platform_device *pdev)
+{
+	struct at_dma	*atdma = platform_get_drvdata(pdev);
+
+	at_dma_off(platform_get_drvdata(pdev));
+	clk_disable(atdma->clk);
+}
+
+static int at_dma_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct at_dma	*atdma = platform_get_drvdata(pdev);
+
+	at_dma_off(platform_get_drvdata(pdev));
+	clk_disable(atdma->clk);
+	return 0;
+}
+
+static int at_dma_resume_early(struct platform_device *pdev)
+{
+	struct at_dma	*atdma = platform_get_drvdata(pdev);
+
+	clk_enable(atdma->clk);
+	dma_writel(atdma, EN, AT_DMA_ENABLE);
+	return 0;
+
+}
+
+static struct platform_driver at_dma_driver = {
+	.remove		= __exit_p(at_dma_remove),
+	.shutdown	= at_dma_shutdown,
+	.suspend_late	= at_dma_suspend_late,
+	.resume_early	= at_dma_resume_early,
+	.driver = {
+		.name	= "at_hdmac",
+	},
+};
+
+static int __init at_dma_init(void)
+{
+	return platform_driver_probe(&at_dma_driver, at_dma_probe);
+}
+module_init(at_dma_init);
+
+static void __exit at_dma_exit(void)
+{
+	platform_driver_unregister(&at_dma_driver);
+}
+module_exit(at_dma_exit);
+
+MODULE_DESCRIPTION("Atmel AHB DMA Controller driver");
+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:at_hdmac");
diff -druN linux-libre-2.6.30-gnu/drivers/dma/at_hdmac_regs.h linux-libre-2.6.31-gnu/drivers/dma/at_hdmac_regs.h
--- linux-libre-2.6.30-gnu/drivers/dma/at_hdmac_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/dma/at_hdmac_regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Header file for the Atmel AHB DMA Controller driver
+ *
+ * Copyright (C) 2008 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.
+ */
+#ifndef AT_HDMAC_REGS_H
+#define	AT_HDMAC_REGS_H
+
+#include <mach/at_hdmac.h>
+
+#define	AT_DMA_MAX_NR_CHANNELS	8
+
+
+#define	AT_DMA_GCFG	0x00	/* Global Configuration Register */
+#define		AT_DMA_IF_BIGEND(i)	(0x1 << (i))	/* AHB-Lite Interface i in Big-endian mode */
+#define		AT_DMA_ARB_CFG	(0x1 << 4)	/* Arbiter mode. */
+#define			AT_DMA_ARB_CFG_FIXED		(0x0 << 4)
+#define			AT_DMA_ARB_CFG_ROUND_ROBIN	(0x1 << 4)
+
+#define	AT_DMA_EN	0x04	/* Controller Enable Register */
+#define		AT_DMA_ENABLE	(0x1 << 0)
+
+#define	AT_DMA_SREQ	0x08	/* Software Single Request Register */
+#define		AT_DMA_SSREQ(x)	(0x1 << ((x) << 1))		/* Request a source single transfer on channel x */
+#define		AT_DMA_DSREQ(x)	(0x1 << (1 + ((x) << 1)))	/* Request a destination single transfer on channel x */
+
+#define	AT_DMA_CREQ	0x0C	/* Software Chunk Transfer Request Register */
+#define		AT_DMA_SCREQ(x)	(0x1 << ((x) << 1))		/* Request a source chunk transfer on channel x */
+#define		AT_DMA_DCREQ(x)	(0x1 << (1 + ((x) << 1)))	/* Request a destination chunk transfer on channel x */
+
+#define	AT_DMA_LAST	0x10	/* Software Last Transfer Flag Register */
+#define		AT_DMA_SLAST(x)	(0x1 << ((x) << 1))		/* This src rq is last tx of buffer on channel x */
+#define		AT_DMA_DLAST(x)	(0x1 << (1 + ((x) << 1)))	/* This dst rq is last tx of buffer on channel x */
+
+#define	AT_DMA_SYNC	0x14	/* Request Synchronization Register */
+#define		AT_DMA_SYR(h)	(0x1 << (h))			/* Synchronize handshake line h */
+
+/* Error, Chained Buffer transfer completed and Buffer transfer completed Interrupt registers */
+#define	AT_DMA_EBCIER	0x18	/* Enable register */
+#define	AT_DMA_EBCIDR	0x1C	/* Disable register */
+#define	AT_DMA_EBCIMR	0x20	/* Mask Register */
+#define	AT_DMA_EBCISR	0x24	/* Status Register */
+#define		AT_DMA_CBTC_OFFSET	8
+#define		AT_DMA_ERR_OFFSET	16
+#define		AT_DMA_BTC(x)	(0x1 << (x))
+#define		AT_DMA_CBTC(x)	(0x1 << (AT_DMA_CBTC_OFFSET + (x)))
+#define		AT_DMA_ERR(x)	(0x1 << (AT_DMA_ERR_OFFSET + (x)))
+
+#define	AT_DMA_CHER	0x28	/* Channel Handler Enable Register */
+#define		AT_DMA_ENA(x)	(0x1 << (x))
+#define		AT_DMA_SUSP(x)	(0x1 << ( 8 + (x)))
+#define		AT_DMA_KEEP(x)	(0x1 << (24 + (x)))
+
+#define	AT_DMA_CHDR	0x2C	/* Channel Handler Disable Register */
+#define		AT_DMA_DIS(x)	(0x1 << (x))
+#define		AT_DMA_RES(x)	(0x1 << ( 8 + (x)))
+
+#define	AT_DMA_CHSR	0x30	/* Channel Handler Status Register */
+#define		AT_DMA_EMPT(x)	(0x1 << (16 + (x)))
+#define		AT_DMA_STAL(x)	(0x1 << (24 + (x)))
+
+
+#define	AT_DMA_CH_REGS_BASE	0x3C	/* Channel registers base address */
+#define	ch_regs(x)	(AT_DMA_CH_REGS_BASE + (x) * 0x28) /* Channel x base addr */
+
+/* Hardware register offset for each channel */
+#define	ATC_SADDR_OFFSET	0x00	/* Source Address Register */
+#define	ATC_DADDR_OFFSET	0x04	/* Destination Address Register */
+#define	ATC_DSCR_OFFSET		0x08	/* Descriptor Address Register */
+#define	ATC_CTRLA_OFFSET	0x0C	/* Control A Register */
+#define	ATC_CTRLB_OFFSET	0x10	/* Control B Register */
+#define	ATC_CFG_OFFSET		0x14	/* Configuration Register */
+#define	ATC_SPIP_OFFSET		0x18	/* Src PIP Configuration Register */
+#define	ATC_DPIP_OFFSET		0x1C	/* Dst PIP Configuration Register */
+
+
+/* Bitfield definitions */
+
+/* Bitfields in DSCR */
+#define	ATC_DSCR_IF(i)		(0x3 & (i))	/* Dsc feched via AHB-Lite Interface i */
+
+/* Bitfields in CTRLA */
+#define	ATC_BTSIZE_MAX		0xFFFFUL	/* Maximum Buffer Transfer Size */
+#define	ATC_BTSIZE(x)		(ATC_BTSIZE_MAX & (x)) /* Buffer Transfer Size */
+/* Chunck Tranfer size definitions are in at_hdmac.h */
+#define	ATC_SRC_WIDTH_MASK	(0x3 << 24)	/* Source Single Transfer Size */
+#define		ATC_SRC_WIDTH(x)	((x) << 24)
+#define		ATC_SRC_WIDTH_BYTE	(0x0 << 24)
+#define		ATC_SRC_WIDTH_HALFWORD	(0x1 << 24)
+#define		ATC_SRC_WIDTH_WORD	(0x2 << 24)
+#define	ATC_DST_WIDTH_MASK	(0x3 << 28)	/* Destination Single Transfer Size */
+#define		ATC_DST_WIDTH(x)	((x) << 28)
+#define		ATC_DST_WIDTH_BYTE	(0x0 << 28)
+#define		ATC_DST_WIDTH_HALFWORD	(0x1 << 28)
+#define		ATC_DST_WIDTH_WORD	(0x2 << 28)
+#define	ATC_DONE		(0x1 << 31)	/* Tx Done (only written back in descriptor) */
+
+/* Bitfields in CTRLB */
+#define	ATC_SIF(i)		(0x3 & (i))	/* Src tx done via AHB-Lite Interface i */
+#define	ATC_DIF(i)		((0x3 & (i)) <<  4)	/* Dst tx done via AHB-Lite Interface i */
+#define	ATC_SRC_PIP		(0x1 <<  8)	/* Source Picture-in-Picture enabled */
+#define	ATC_DST_PIP		(0x1 << 12)	/* Destination Picture-in-Picture enabled */
+#define	ATC_SRC_DSCR_DIS	(0x1 << 16)	/* Src Descriptor fetch disable */
+#define	ATC_DST_DSCR_DIS	(0x1 << 20)	/* Dst Descriptor fetch disable */
+#define	ATC_FC_MASK		(0x7 << 21)	/* Choose Flow Controller */
+#define		ATC_FC_MEM2MEM		(0x0 << 21)	/* Mem-to-Mem (DMA) */
+#define		ATC_FC_MEM2PER		(0x1 << 21)	/* Mem-to-Periph (DMA) */
+#define		ATC_FC_PER2MEM		(0x2 << 21)	/* Periph-to-Mem (DMA) */
+#define		ATC_FC_PER2PER		(0x3 << 21)	/* Periph-to-Periph (DMA) */
+#define		ATC_FC_PER2MEM_PER	(0x4 << 21)	/* Periph-to-Mem (Peripheral) */
+#define		ATC_FC_MEM2PER_PER	(0x5 << 21)	/* Mem-to-Periph (Peripheral) */
+#define		ATC_FC_PER2PER_SRCPER	(0x6 << 21)	/* Periph-to-Periph (Src Peripheral) */
+#define		ATC_FC_PER2PER_DSTPER	(0x7 << 21)	/* Periph-to-Periph (Dst Peripheral) */
+#define	ATC_SRC_ADDR_MODE_MASK	(0x3 << 24)
+#define		ATC_SRC_ADDR_MODE_INCR	(0x0 << 24)	/* Incrementing Mode */
+#define		ATC_SRC_ADDR_MODE_DECR	(0x1 << 24)	/* Decrementing Mode */
+#define		ATC_SRC_ADDR_MODE_FIXED	(0x2 << 24)	/* Fixed Mode */
+#define	ATC_DST_ADDR_MODE_MASK	(0x3 << 28)
+#define		ATC_DST_ADDR_MODE_INCR	(0x0 << 28)	/* Incrementing Mode */
+#define		ATC_DST_ADDR_MODE_DECR	(0x1 << 28)	/* Decrementing Mode */
+#define		ATC_DST_ADDR_MODE_FIXED	(0x2 << 28)	/* Fixed Mode */
+#define	ATC_IEN			(0x1 << 30)	/* BTC interrupt enable (active low) */
+#define	ATC_AUTO		(0x1 << 31)	/* Auto multiple buffer tx enable */
+
+/* Bitfields in CFG */
+/* are in at_hdmac.h */
+
+/* Bitfields in SPIP */
+#define	ATC_SPIP_HOLE(x)	(0xFFFFU & (x))
+#define	ATC_SPIP_BOUNDARY(x)	((0x3FF & (x)) << 16)
+
+/* Bitfields in DPIP */
+#define	ATC_DPIP_HOLE(x)	(0xFFFFU & (x))
+#define	ATC_DPIP_BOUNDARY(x)	((0x3FF & (x)) << 16)
+
+
+/*--  descriptors  -----------------------------------------------------*/
+
+/* LLI == Linked List Item; aka DMA buffer descriptor */
+struct at_lli {
+	/* values that are not changed by hardware */
+	dma_addr_t	saddr;
+	dma_addr_t	daddr;
+	/* value that may get written back: */
+	u32		ctrla;
+	/* more values that are not changed by hardware */
+	u32		ctrlb;
+	dma_addr_t	dscr;	/* chain to next lli */
+};
+
+/**
+ * struct at_desc - software descriptor
+ * @at_lli: hardware lli structure
+ * @txd: support for the async_tx api
+ * @desc_node: node on the channed descriptors list
+ * @len: total transaction bytecount
+ */
+struct at_desc {
+	/* FIRST values the hardware uses */
+	struct at_lli			lli;
+
+	/* THEN values for driver housekeeping */
+	struct dma_async_tx_descriptor	txd;
+	struct list_head		desc_node;
+	size_t				len;
+};
+
+static inline struct at_desc *
+txd_to_at_desc(struct dma_async_tx_descriptor *txd)
+{
+	return container_of(txd, struct at_desc, txd);
+}
+
+
+/*--  Channels  --------------------------------------------------------*/
+
+/**
+ * struct at_dma_chan - internal representation of an Atmel HDMAC channel
+ * @chan_common: common dmaengine channel object members
+ * @device: parent device
+ * @ch_regs: memory mapped register base
+ * @mask: channel index in a mask
+ * @error_status: transmit error status information from irq handler
+ *                to tasklet (use atomic operations)
+ * @tasklet: bottom half to finish transaction work
+ * @lock: serializes enqueue/dequeue operations to descriptors lists
+ * @completed_cookie: identifier for the most recently completed operation
+ * @active_list: list of descriptors dmaengine is being running on
+ * @queue: list of descriptors ready to be submitted to engine
+ * @free_list: list of descriptors usable by the channel
+ * @descs_allocated: records the actual size of the descriptor pool
+ */
+struct at_dma_chan {
+	struct dma_chan		chan_common;
+	struct at_dma		*device;
+	void __iomem		*ch_regs;
+	u8			mask;
+	unsigned long		error_status;
+	struct tasklet_struct	tasklet;
+
+	spinlock_t		lock;
+
+	/* these other elements are all protected by lock */
+	dma_cookie_t		completed_cookie;
+	struct list_head	active_list;
+	struct list_head	queue;
+	struct list_head	free_list;
+	unsigned int		descs_allocated;
+};
+
+#define	channel_readl(atchan, name) \
+	__raw_readl((atchan)->ch_regs + ATC_##name##_OFFSET)
+
+#define	channel_writel(atchan, name, val) \
+	__raw_writel((val), (atchan)->ch_regs + ATC_##name##_OFFSET)
+
+static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
+{
+	return container_of(dchan, struct at_dma_chan, chan_common);
+}
+
+
+/*--  Controller  ------------------------------------------------------*/
+
+/**
+ * struct at_dma - internal representation of an Atmel HDMA Controller
+ * @chan_common: common dmaengine dma_device object members
+ * @ch_regs: memory mapped register base
+ * @clk: dma controller clock
+ * @all_chan_mask: all channels availlable in a mask
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @chan: channels table to store at_dma_chan structures
+ */
+struct at_dma {
+	struct dma_device	dma_common;
+	void __iomem		*regs;
+	struct clk		*clk;
+
+	u8			all_chan_mask;
+
+	struct dma_pool		*dma_desc_pool;
+	/* AT THE END channels table */
+	struct at_dma_chan	chan[0];
+};
+
+#define	dma_readl(atdma, name) \
+	__raw_readl((atdma)->regs + AT_DMA_##name)
+#define	dma_writel(atdma, name, val) \
+	__raw_writel((val), (atdma)->regs + AT_DMA_##name)
+
+static inline struct at_dma *to_at_dma(struct dma_device *ddev)
+{
+	return container_of(ddev, struct at_dma, dma_common);
+}
+
+
+/*--  Helper functions  ------------------------------------------------*/
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+	return &chan->dev->device;
+}
+static struct device *chan2parent(struct dma_chan *chan)
+{
+	return chan->dev->device.parent;
+}
+
+#if defined(VERBOSE_DEBUG)
+static void vdbg_dump_regs(struct at_dma_chan *atchan)
+{
+	struct at_dma	*atdma = to_at_dma(atchan->chan_common.device);
+
+	dev_err(chan2dev(&atchan->chan_common),
+		"  channel %d : imr = 0x%x, chsr = 0x%x\n",
+		atchan->chan_common.chan_id,
+		dma_readl(atdma, EBCIMR),
+		dma_readl(atdma, CHSR));
+
+	dev_err(chan2dev(&atchan->chan_common),
+		"  channel: s0x%x d0x%x ctrl0x%x:0x%x cfg0x%x l0x%x\n",
+		channel_readl(atchan, SADDR),
+		channel_readl(atchan, DADDR),
+		channel_readl(atchan, CTRLA),
+		channel_readl(atchan, CTRLB),
+		channel_readl(atchan, CFG),
+		channel_readl(atchan, DSCR));
+}
+#else
+static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
+#endif
+
+static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
+{
+	dev_printk(KERN_CRIT, chan2dev(&atchan->chan_common),
+			"  desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
+			lli->saddr, lli->daddr,
+			lli->ctrla, lli->ctrlb, lli->dscr);
+}
+
+
+static void atc_setup_irq(struct at_dma_chan *atchan, int on)
+{
+	struct at_dma	*atdma = to_at_dma(atchan->chan_common.device);
+	u32		ebci;
+
+	/* enable interrupts on buffer chain completion & error */
+	ebci =    AT_DMA_CBTC(atchan->chan_common.chan_id)
+		| AT_DMA_ERR(atchan->chan_common.chan_id);
+	if (on)
+		dma_writel(atdma, EBCIER, ebci);
+	else
+		dma_writel(atdma, EBCIDR, ebci);
+}
+
+static inline void atc_enable_irq(struct at_dma_chan *atchan)
+{
+	atc_setup_irq(atchan, 1);
+}
+
+static inline void atc_disable_irq(struct at_dma_chan *atchan)
+{
+	atc_setup_irq(atchan, 0);
+}
+
+
+/**
+ * atc_chan_is_enabled - test if given channel is enabled
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
+{
+	struct at_dma	*atdma = to_at_dma(atchan->chan_common.device);
+
+	return !!(dma_readl(atdma, CHSR) & atchan->mask);
+}
+
+
+/**
+ * set_desc_eol - set end-of-link to descriptor so it will end transfer
+ * @desc: descriptor, signle or at the end of a chain, to end chain on
+ */
+static void set_desc_eol(struct at_desc *desc)
+{
+	desc->lli.ctrlb |= ATC_SRC_DSCR_DIS | ATC_DST_DSCR_DIS;
+	desc->lli.dscr = 0;
+}
+
+#endif /* AT_HDMAC_REGS_H */
diff -druN linux-libre-2.6.30-gnu/drivers/dma/dmatest.c linux-libre-2.6.31-gnu/drivers/dma/dmatest.c
--- linux-libre-2.6.30-gnu/drivers/dma/dmatest.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/dma/dmatest.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,11 @@
 MODULE_PARM_DESC(max_channels,
 		"Maximum number of channels to use (default: all)");
 
+static unsigned int iterations;
+module_param(iterations, uint, S_IRUGO);
+MODULE_PARM_DESC(iterations,
+		"Iterations before stopping test (default: infinite)");
+
 static unsigned int xor_sources = 3;
 module_param(xor_sources, uint, S_IRUGO);
 MODULE_PARM_DESC(xor_sources,
@@ -114,7 +119,7 @@
 			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
 		for ( ; i < start + len; i++)
 			buf[i] = PATTERN_SRC | PATTERN_COPY
-				| (~i & PATTERN_COUNT_MASK);;
+				| (~i & PATTERN_COUNT_MASK);
 		for ( ; i < test_buf_size; i++)
 			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
 		buf++;
@@ -270,7 +275,8 @@
 
 	flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT;
 
-	while (!kthread_should_stop()) {
+	while (!kthread_should_stop()
+	       && !(iterations && total_tests >= iterations)) {
 		struct dma_device *dev = chan->device;
 		struct dma_async_tx_descriptor *tx = NULL;
 		dma_addr_t dma_srcs[src_cnt];
@@ -416,6 +422,13 @@
 err_srcs:
 	pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
 			thread_name, total_tests, failed_tests, ret);
+
+	if (iterations > 0)
+		while (!kthread_should_stop()) {
+			DECLARE_WAIT_QUEUE_HEAD(wait_dmatest_exit);
+			interruptible_sleep_on(&wait_dmatest_exit);
+		}
+
 	return ret;
 }
 
@@ -495,11 +508,11 @@
 
 	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
 		cnt = dmatest_add_threads(dtc, DMA_MEMCPY);
-		thread_count += cnt > 0 ?: 0;
+		thread_count += cnt > 0 ? cnt : 0;
 	}
 	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
 		cnt = dmatest_add_threads(dtc, DMA_XOR);
-		thread_count += cnt > 0 ?: 0;
+		thread_count += cnt > 0 ? cnt : 0;
 	}
 
 	pr_info("dmatest: Started %u threads using %s\n",
diff -druN linux-libre-2.6.30-gnu/drivers/dma/fsldma.c linux-libre-2.6.31-gnu/drivers/dma/fsldma.c
--- linux-libre-2.6.30-gnu/drivers/dma/fsldma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/dma/fsldma.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,11 @@
  *   also fit for MPC8560, MPC8555, MPC8548, MPC8641, and etc.
  *   The support for MPC8349 DMA contorller is also added.
  *
+ * This driver instructs the DMA controller to issue the PCI Read Multiple
+ * command for PCI read operations, instead of using the default PCI Read Line
+ * command. Please be aware that this setting may result in read pre-fetching
+ * on some platforms.
+ *
  * This 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
@@ -49,9 +54,10 @@
 	case FSL_DMA_IP_83XX:
 		/* Set the channel to below modes:
 		 * EOTIE - End-of-transfer interrupt enable
+		 * PRC_RM - PCI read multiple
 		 */
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE,
-				32);
+		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE
+				| FSL_DMA_MR_PRC_RM, 32);
 		break;
 	}
 
@@ -136,15 +142,16 @@
 
 static void dma_start(struct fsl_dma_chan *fsl_chan)
 {
-	u32 mr_set = 0;;
+	u32 mr_set = 0;
 
 	if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
 		DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
 		mr_set |= FSL_DMA_MR_EMP_EN;
-	} else
+	} else if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
 		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
 			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
 				& ~FSL_DMA_MR_EMP_EN, 32);
+	}
 
 	if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
 		mr_set |= FSL_DMA_MR_EMS_EN;
@@ -871,9 +878,9 @@
 
 	switch (new_fsl_chan->feature & FSL_DMA_IP_MASK) {
 	case FSL_DMA_IP_85XX:
-		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
 		new_fsl_chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
 	case FSL_DMA_IP_83XX:
+		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
 		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
 		new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/dma/fsldma.h linux-libre-2.6.31-gnu/drivers/dma/fsldma.h
--- linux-libre-2.6.30-gnu/drivers/dma/fsldma.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/dma/fsldma.h	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,7 @@
 
 /* Special MR definition for MPC8349 */
 #define FSL_DMA_MR_EOTIE	0x00000080
+#define FSL_DMA_MR_PRC_RM	0x00000800
 
 #define FSL_DMA_SR_CH		0x00000020
 #define FSL_DMA_SR_PE		0x00000010
diff -druN linux-libre-2.6.30-gnu/drivers/dma/Kconfig linux-libre-2.6.31-gnu/drivers/dma/Kconfig
--- linux-libre-2.6.30-gnu/drivers/dma/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/dma/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -4,7 +4,7 @@
 
 menuconfig DMADEVICES
 	bool "DMA Engine support"
-	depends on !HIGHMEM64G && HAS_DMA
+	depends on HAS_DMA
 	help
 	  DMA engines can do asynchronous data transfers without
 	  involving the host CPU.  Currently, this framework can be
@@ -46,6 +46,14 @@
 	  Support the Synopsys DesignWare AHB DMA controller.  This
 	  can be integrated in chips such as the Atmel AT32ap7000.
 
+config AT_HDMAC
+	tristate "Atmel AHB DMA support"
+	depends on ARCH_AT91SAM9RL
+	select DMA_ENGINE
+	help
+	  Support the Atmel AHB DMA controller.  This can be integrated in
+	  chips such as the Atmel AT91SAM9RL.
+
 config FSL_DMA
 	tristate "Freescale Elo and Elo Plus DMA support"
 	depends on FSL_SOC
@@ -81,6 +89,14 @@
 	  To avoid bloating the irq_desc[] array we allocate a sufficient
 	  number of IRQ slots and map them dynamically to specific sources.
 
+config TXX9_DMAC
+	tristate "Toshiba TXx9 SoC DMA support"
+	depends on MACH_TX49XX || MACH_TX39XX
+	select DMA_ENGINE
+	help
+	  Support the TXx9 SoC internal DMA controller.  This can be
+	  integrated in chips such as the Toshiba TX4927/38/39.
+
 config DMA_ENGINE
 	bool
 
@@ -100,7 +116,7 @@
 
 config ASYNC_TX_DMA
 	bool "Async_tx: Offload support for the async_tx api"
-	depends on DMA_ENGINE
+	depends on DMA_ENGINE && !HIGHMEM64G
 	help
 	  This allows the async_tx api to take advantage of offload engines for
 	  memcpy, memset, xor, and raid6 p+q operations.  If your platform has
diff -druN linux-libre-2.6.30-gnu/drivers/dma/Makefile linux-libre-2.6.31-gnu/drivers/dma/Makefile
--- linux-libre-2.6.30-gnu/drivers/dma/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/dma/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -7,4 +7,6 @@
 obj-$(CONFIG_FSL_DMA) += fsldma.o
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC) += dw_dmac.o
+obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
 obj-$(CONFIG_MX3_IPU) += ipu/
+obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
diff -druN linux-libre-2.6.30-gnu/drivers/dma/mv_xor.c linux-libre-2.6.31-gnu/drivers/dma/mv_xor.c
--- linux-libre-2.6.30-gnu/drivers/dma/mv_xor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/dma/mv_xor.c	2009-09-09 18:13:59.000000000 -0400
@@ -1176,7 +1176,7 @@
 	if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
 		dma_dev->device_prep_dma_memset = mv_xor_prep_dma_memset;
 	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
-		dma_dev->max_xor = 8;                  ;
+		dma_dev->max_xor = 8;
 		dma_dev->device_prep_dma_xor = mv_xor_prep_dma_xor;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/dma/txx9dmac.c linux-libre-2.6.31-gnu/drivers/dma/txx9dmac.c
--- linux-libre-2.6.30-gnu/drivers/dma/txx9dmac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/dma/txx9dmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1358 @@
+/*
+ * Driver for the TXx9 SoC DMA Controller
+ *
+ * Copyright (C) 2009 Atsushi Nemoto
+ *
+ * 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.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include "txx9dmac.h"
+
+static struct txx9dmac_chan *to_txx9dmac_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct txx9dmac_chan, chan);
+}
+
+static struct txx9dmac_cregs __iomem *__dma_regs(const struct txx9dmac_chan *dc)
+{
+	return dc->ch_regs;
+}
+
+static struct txx9dmac_cregs32 __iomem *__dma_regs32(
+	const struct txx9dmac_chan *dc)
+{
+	return dc->ch_regs;
+}
+
+#define channel64_readq(dc, name) \
+	__raw_readq(&(__dma_regs(dc)->name))
+#define channel64_writeq(dc, name, val) \
+	__raw_writeq((val), &(__dma_regs(dc)->name))
+#define channel64_readl(dc, name) \
+	__raw_readl(&(__dma_regs(dc)->name))
+#define channel64_writel(dc, name, val) \
+	__raw_writel((val), &(__dma_regs(dc)->name))
+
+#define channel32_readl(dc, name) \
+	__raw_readl(&(__dma_regs32(dc)->name))
+#define channel32_writel(dc, name, val) \
+	__raw_writel((val), &(__dma_regs32(dc)->name))
+
+#define channel_readq(dc, name) channel64_readq(dc, name)
+#define channel_writeq(dc, name, val) channel64_writeq(dc, name, val)
+#define channel_readl(dc, name) \
+	(is_dmac64(dc) ? \
+	 channel64_readl(dc, name) : channel32_readl(dc, name))
+#define channel_writel(dc, name, val) \
+	(is_dmac64(dc) ? \
+	 channel64_writel(dc, name, val) : channel32_writel(dc, name, val))
+
+static dma_addr_t channel64_read_CHAR(const struct txx9dmac_chan *dc)
+{
+	if (sizeof(__dma_regs(dc)->CHAR) == sizeof(u64))
+		return channel64_readq(dc, CHAR);
+	else
+		return channel64_readl(dc, CHAR);
+}
+
+static void channel64_write_CHAR(const struct txx9dmac_chan *dc, dma_addr_t val)
+{
+	if (sizeof(__dma_regs(dc)->CHAR) == sizeof(u64))
+		channel64_writeq(dc, CHAR, val);
+	else
+		channel64_writel(dc, CHAR, val);
+}
+
+static void channel64_clear_CHAR(const struct txx9dmac_chan *dc)
+{
+#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
+	channel64_writel(dc, CHAR, 0);
+	channel64_writel(dc, __pad_CHAR, 0);
+#else
+	channel64_writeq(dc, CHAR, 0);
+#endif
+}
+
+static dma_addr_t channel_read_CHAR(const struct txx9dmac_chan *dc)
+{
+	if (is_dmac64(dc))
+		return channel64_read_CHAR(dc);
+	else
+		return channel32_readl(dc, CHAR);
+}
+
+static void channel_write_CHAR(const struct txx9dmac_chan *dc, dma_addr_t val)
+{
+	if (is_dmac64(dc))
+		channel64_write_CHAR(dc, val);
+	else
+		channel32_writel(dc, CHAR, val);
+}
+
+static struct txx9dmac_regs __iomem *__txx9dmac_regs(
+	const struct txx9dmac_dev *ddev)
+{
+	return ddev->regs;
+}
+
+static struct txx9dmac_regs32 __iomem *__txx9dmac_regs32(
+	const struct txx9dmac_dev *ddev)
+{
+	return ddev->regs;
+}
+
+#define dma64_readl(ddev, name) \
+	__raw_readl(&(__txx9dmac_regs(ddev)->name))
+#define dma64_writel(ddev, name, val) \
+	__raw_writel((val), &(__txx9dmac_regs(ddev)->name))
+
+#define dma32_readl(ddev, name) \
+	__raw_readl(&(__txx9dmac_regs32(ddev)->name))
+#define dma32_writel(ddev, name, val) \
+	__raw_writel((val), &(__txx9dmac_regs32(ddev)->name))
+
+#define dma_readl(ddev, name) \
+	(__is_dmac64(ddev) ? \
+	dma64_readl(ddev, name) : dma32_readl(ddev, name))
+#define dma_writel(ddev, name, val) \
+	(__is_dmac64(ddev) ? \
+	dma64_writel(ddev, name, val) : dma32_writel(ddev, name, val))
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+	return &chan->dev->device;
+}
+static struct device *chan2parent(struct dma_chan *chan)
+{
+	return chan->dev->device.parent;
+}
+
+static struct txx9dmac_desc *
+txd_to_txx9dmac_desc(struct dma_async_tx_descriptor *txd)
+{
+	return container_of(txd, struct txx9dmac_desc, txd);
+}
+
+static dma_addr_t desc_read_CHAR(const struct txx9dmac_chan *dc,
+				 const struct txx9dmac_desc *desc)
+{
+	return is_dmac64(dc) ? desc->hwdesc.CHAR : desc->hwdesc32.CHAR;
+}
+
+static void desc_write_CHAR(const struct txx9dmac_chan *dc,
+			    struct txx9dmac_desc *desc, dma_addr_t val)
+{
+	if (is_dmac64(dc))
+		desc->hwdesc.CHAR = val;
+	else
+		desc->hwdesc32.CHAR = val;
+}
+
+#define TXX9_DMA_MAX_COUNT	0x04000000
+
+#define TXX9_DMA_INITIAL_DESC_COUNT	64
+
+static struct txx9dmac_desc *txx9dmac_first_active(struct txx9dmac_chan *dc)
+{
+	return list_entry(dc->active_list.next,
+			  struct txx9dmac_desc, desc_node);
+}
+
+static struct txx9dmac_desc *txx9dmac_last_active(struct txx9dmac_chan *dc)
+{
+	return list_entry(dc->active_list.prev,
+			  struct txx9dmac_desc, desc_node);
+}
+
+static struct txx9dmac_desc *txx9dmac_first_queued(struct txx9dmac_chan *dc)
+{
+	return list_entry(dc->queue.next, struct txx9dmac_desc, desc_node);
+}
+
+static struct txx9dmac_desc *txx9dmac_last_child(struct txx9dmac_desc *desc)
+{
+	if (!list_empty(&desc->txd.tx_list))
+		desc = list_entry(desc->txd.tx_list.prev,
+				  struct txx9dmac_desc, desc_node);
+	return desc;
+}
+
+static dma_cookie_t txx9dmac_tx_submit(struct dma_async_tx_descriptor *tx);
+
+static struct txx9dmac_desc *txx9dmac_desc_alloc(struct txx9dmac_chan *dc,
+						 gfp_t flags)
+{
+	struct txx9dmac_dev *ddev = dc->ddev;
+	struct txx9dmac_desc *desc;
+
+	desc = kzalloc(sizeof(*desc), flags);
+	if (!desc)
+		return NULL;
+	dma_async_tx_descriptor_init(&desc->txd, &dc->chan);
+	desc->txd.tx_submit = txx9dmac_tx_submit;
+	/* txd.flags will be overwritten in prep funcs */
+	desc->txd.flags = DMA_CTRL_ACK;
+	desc->txd.phys = dma_map_single(chan2parent(&dc->chan), &desc->hwdesc,
+					ddev->descsize, DMA_TO_DEVICE);
+	return desc;
+}
+
+static struct txx9dmac_desc *txx9dmac_desc_get(struct txx9dmac_chan *dc)
+{
+	struct txx9dmac_desc *desc, *_desc;
+	struct txx9dmac_desc *ret = NULL;
+	unsigned int i = 0;
+
+	spin_lock_bh(&dc->lock);
+	list_for_each_entry_safe(desc, _desc, &dc->free_list, desc_node) {
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del(&desc->desc_node);
+			ret = desc;
+			break;
+		}
+		dev_dbg(chan2dev(&dc->chan), "desc %p not ACKed\n", desc);
+		i++;
+	}
+	spin_unlock_bh(&dc->lock);
+
+	dev_vdbg(chan2dev(&dc->chan), "scanned %u descriptors on freelist\n",
+		 i);
+	if (!ret) {
+		ret = txx9dmac_desc_alloc(dc, GFP_ATOMIC);
+		if (ret) {
+			spin_lock_bh(&dc->lock);
+			dc->descs_allocated++;
+			spin_unlock_bh(&dc->lock);
+		} else
+			dev_err(chan2dev(&dc->chan),
+				"not enough descriptors available\n");
+	}
+	return ret;
+}
+
+static void txx9dmac_sync_desc_for_cpu(struct txx9dmac_chan *dc,
+				       struct txx9dmac_desc *desc)
+{
+	struct txx9dmac_dev *ddev = dc->ddev;
+	struct txx9dmac_desc *child;
+
+	list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+		dma_sync_single_for_cpu(chan2parent(&dc->chan),
+				child->txd.phys, ddev->descsize,
+				DMA_TO_DEVICE);
+	dma_sync_single_for_cpu(chan2parent(&dc->chan),
+			desc->txd.phys, ddev->descsize,
+			DMA_TO_DEVICE);
+}
+
+/*
+ * Move a descriptor, including any children, to the free list.
+ * `desc' must not be on any lists.
+ */
+static void txx9dmac_desc_put(struct txx9dmac_chan *dc,
+			      struct txx9dmac_desc *desc)
+{
+	if (desc) {
+		struct txx9dmac_desc *child;
+
+		txx9dmac_sync_desc_for_cpu(dc, desc);
+
+		spin_lock_bh(&dc->lock);
+		list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+			dev_vdbg(chan2dev(&dc->chan),
+				 "moving child desc %p to freelist\n",
+				 child);
+		list_splice_init(&desc->txd.tx_list, &dc->free_list);
+		dev_vdbg(chan2dev(&dc->chan), "moving desc %p to freelist\n",
+			 desc);
+		list_add(&desc->desc_node, &dc->free_list);
+		spin_unlock_bh(&dc->lock);
+	}
+}
+
+/* Called with dc->lock held and bh disabled */
+static dma_cookie_t
+txx9dmac_assign_cookie(struct txx9dmac_chan *dc, struct txx9dmac_desc *desc)
+{
+	dma_cookie_t cookie = dc->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	dc->chan.cookie = cookie;
+	desc->txd.cookie = cookie;
+
+	return cookie;
+}
+
+/*----------------------------------------------------------------------*/
+
+static void txx9dmac_dump_regs(struct txx9dmac_chan *dc)
+{
+	if (is_dmac64(dc))
+		dev_err(chan2dev(&dc->chan),
+			"  CHAR: %#llx SAR: %#llx DAR: %#llx CNTR: %#x"
+			" SAIR: %#x DAIR: %#x CCR: %#x CSR: %#x\n",
+			(u64)channel64_read_CHAR(dc),
+			channel64_readq(dc, SAR),
+			channel64_readq(dc, DAR),
+			channel64_readl(dc, CNTR),
+			channel64_readl(dc, SAIR),
+			channel64_readl(dc, DAIR),
+			channel64_readl(dc, CCR),
+			channel64_readl(dc, CSR));
+	else
+		dev_err(chan2dev(&dc->chan),
+			"  CHAR: %#x SAR: %#x DAR: %#x CNTR: %#x"
+			" SAIR: %#x DAIR: %#x CCR: %#x CSR: %#x\n",
+			channel32_readl(dc, CHAR),
+			channel32_readl(dc, SAR),
+			channel32_readl(dc, DAR),
+			channel32_readl(dc, CNTR),
+			channel32_readl(dc, SAIR),
+			channel32_readl(dc, DAIR),
+			channel32_readl(dc, CCR),
+			channel32_readl(dc, CSR));
+}
+
+static void txx9dmac_reset_chan(struct txx9dmac_chan *dc)
+{
+	channel_writel(dc, CCR, TXX9_DMA_CCR_CHRST);
+	if (is_dmac64(dc)) {
+		channel64_clear_CHAR(dc);
+		channel_writeq(dc, SAR, 0);
+		channel_writeq(dc, DAR, 0);
+	} else {
+		channel_writel(dc, CHAR, 0);
+		channel_writel(dc, SAR, 0);
+		channel_writel(dc, DAR, 0);
+	}
+	channel_writel(dc, CNTR, 0);
+	channel_writel(dc, SAIR, 0);
+	channel_writel(dc, DAIR, 0);
+	channel_writel(dc, CCR, 0);
+	mmiowb();
+}
+
+/* Called with dc->lock held and bh disabled */
+static void txx9dmac_dostart(struct txx9dmac_chan *dc,
+			     struct txx9dmac_desc *first)
+{
+	struct txx9dmac_slave *ds = dc->chan.private;
+	u32 sai, dai;
+
+	dev_vdbg(chan2dev(&dc->chan), "dostart %u %p\n",
+		 first->txd.cookie, first);
+	/* ASSERT:  channel is idle */
+	if (channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT) {
+		dev_err(chan2dev(&dc->chan),
+			"BUG: Attempted to start non-idle channel\n");
+		txx9dmac_dump_regs(dc);
+		/* The tasklet will hopefully advance the queue... */
+		return;
+	}
+
+	if (is_dmac64(dc)) {
+		channel64_writel(dc, CNTR, 0);
+		channel64_writel(dc, CSR, 0xffffffff);
+		if (ds) {
+			if (ds->tx_reg) {
+				sai = ds->reg_width;
+				dai = 0;
+			} else {
+				sai = 0;
+				dai = ds->reg_width;
+			}
+		} else {
+			sai = 8;
+			dai = 8;
+		}
+		channel64_writel(dc, SAIR, sai);
+		channel64_writel(dc, DAIR, dai);
+		/* All 64-bit DMAC supports SMPCHN */
+		channel64_writel(dc, CCR, dc->ccr);
+		/* Writing a non zero value to CHAR will assert XFACT */
+		channel64_write_CHAR(dc, first->txd.phys);
+	} else {
+		channel32_writel(dc, CNTR, 0);
+		channel32_writel(dc, CSR, 0xffffffff);
+		if (ds) {
+			if (ds->tx_reg) {
+				sai = ds->reg_width;
+				dai = 0;
+			} else {
+				sai = 0;
+				dai = ds->reg_width;
+			}
+		} else {
+			sai = 4;
+			dai = 4;
+		}
+		channel32_writel(dc, SAIR, sai);
+		channel32_writel(dc, DAIR, dai);
+		if (txx9_dma_have_SMPCHN()) {
+			channel32_writel(dc, CCR, dc->ccr);
+			/* Writing a non zero value to CHAR will assert XFACT */
+			channel32_writel(dc, CHAR, first->txd.phys);
+		} else {
+			channel32_writel(dc, CHAR, first->txd.phys);
+			channel32_writel(dc, CCR, dc->ccr);
+		}
+	}
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
+			     struct txx9dmac_desc *desc)
+{
+	dma_async_tx_callback callback;
+	void *param;
+	struct dma_async_tx_descriptor *txd = &desc->txd;
+	struct txx9dmac_slave *ds = dc->chan.private;
+
+	dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
+		 txd->cookie, desc);
+
+	dc->completed = txd->cookie;
+	callback = txd->callback;
+	param = txd->callback_param;
+
+	txx9dmac_sync_desc_for_cpu(dc, desc);
+	list_splice_init(&txd->tx_list, &dc->free_list);
+	list_move(&desc->desc_node, &dc->free_list);
+
+	if (!ds) {
+		dma_addr_t dmaaddr;
+		if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+			dmaaddr = is_dmac64(dc) ?
+				desc->hwdesc.DAR : desc->hwdesc32.DAR;
+			if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+				dma_unmap_single(chan2parent(&dc->chan),
+					dmaaddr, desc->len, DMA_FROM_DEVICE);
+			else
+				dma_unmap_page(chan2parent(&dc->chan),
+					dmaaddr, desc->len, DMA_FROM_DEVICE);
+		}
+		if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+			dmaaddr = is_dmac64(dc) ?
+				desc->hwdesc.SAR : desc->hwdesc32.SAR;
+			if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+				dma_unmap_single(chan2parent(&dc->chan),
+					dmaaddr, desc->len, DMA_TO_DEVICE);
+			else
+				dma_unmap_page(chan2parent(&dc->chan),
+					dmaaddr, desc->len, DMA_TO_DEVICE);
+		}
+	}
+
+	/*
+	 * The API requires that no submissions are done from a
+	 * callback, so we don't need to drop the lock here
+	 */
+	if (callback)
+		callback(param);
+	dma_run_dependencies(txd);
+}
+
+static void txx9dmac_dequeue(struct txx9dmac_chan *dc, struct list_head *list)
+{
+	struct txx9dmac_dev *ddev = dc->ddev;
+	struct txx9dmac_desc *desc;
+	struct txx9dmac_desc *prev = NULL;
+
+	BUG_ON(!list_empty(list));
+	do {
+		desc = txx9dmac_first_queued(dc);
+		if (prev) {
+			desc_write_CHAR(dc, prev, desc->txd.phys);
+			dma_sync_single_for_device(chan2parent(&dc->chan),
+				prev->txd.phys, ddev->descsize,
+				DMA_TO_DEVICE);
+		}
+		prev = txx9dmac_last_child(desc);
+		list_move_tail(&desc->desc_node, list);
+		/* Make chain-completion interrupt happen */
+		if ((desc->txd.flags & DMA_PREP_INTERRUPT) &&
+		    !txx9dmac_chan_INTENT(dc))
+			break;
+	} while (!list_empty(&dc->queue));
+}
+
+static void txx9dmac_complete_all(struct txx9dmac_chan *dc)
+{
+	struct txx9dmac_desc *desc, *_desc;
+	LIST_HEAD(list);
+
+	/*
+	 * Submit queued descriptors ASAP, i.e. before we go through
+	 * the completed ones.
+	 */
+	list_splice_init(&dc->active_list, &list);
+	if (!list_empty(&dc->queue)) {
+		txx9dmac_dequeue(dc, &dc->active_list);
+		txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+	}
+
+	list_for_each_entry_safe(desc, _desc, &list, desc_node)
+		txx9dmac_descriptor_complete(dc, desc);
+}
+
+static void txx9dmac_dump_desc(struct txx9dmac_chan *dc,
+			       struct txx9dmac_hwdesc *desc)
+{
+	if (is_dmac64(dc)) {
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+		dev_crit(chan2dev(&dc->chan),
+			 "  desc: ch%#llx s%#llx d%#llx c%#x\n",
+			 (u64)desc->CHAR, desc->SAR, desc->DAR, desc->CNTR);
+#else
+		dev_crit(chan2dev(&dc->chan),
+			 "  desc: ch%#llx s%#llx d%#llx c%#x"
+			 " si%#x di%#x cc%#x cs%#x\n",
+			 (u64)desc->CHAR, desc->SAR, desc->DAR, desc->CNTR,
+			 desc->SAIR, desc->DAIR, desc->CCR, desc->CSR);
+#endif
+	} else {
+		struct txx9dmac_hwdesc32 *d = (struct txx9dmac_hwdesc32 *)desc;
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+		dev_crit(chan2dev(&dc->chan),
+			 "  desc: ch%#x s%#x d%#x c%#x\n",
+			 d->CHAR, d->SAR, d->DAR, d->CNTR);
+#else
+		dev_crit(chan2dev(&dc->chan),
+			 "  desc: ch%#x s%#x d%#x c%#x"
+			 " si%#x di%#x cc%#x cs%#x\n",
+			 d->CHAR, d->SAR, d->DAR, d->CNTR,
+			 d->SAIR, d->DAIR, d->CCR, d->CSR);
+#endif
+	}
+}
+
+static void txx9dmac_handle_error(struct txx9dmac_chan *dc, u32 csr)
+{
+	struct txx9dmac_desc *bad_desc;
+	struct txx9dmac_desc *child;
+	u32 errors;
+
+	/*
+	 * The descriptor currently at the head of the active list is
+	 * borked. Since we don't have any way to report errors, we'll
+	 * just have to scream loudly and try to carry on.
+	 */
+	dev_crit(chan2dev(&dc->chan), "Abnormal Chain Completion\n");
+	txx9dmac_dump_regs(dc);
+
+	bad_desc = txx9dmac_first_active(dc);
+	list_del_init(&bad_desc->desc_node);
+
+	/* Clear all error flags and try to restart the controller */
+	errors = csr & (TXX9_DMA_CSR_ABCHC |
+			TXX9_DMA_CSR_CFERR | TXX9_DMA_CSR_CHERR |
+			TXX9_DMA_CSR_DESERR | TXX9_DMA_CSR_SORERR);
+	channel_writel(dc, CSR, errors);
+
+	if (list_empty(&dc->active_list) && !list_empty(&dc->queue))
+		txx9dmac_dequeue(dc, &dc->active_list);
+	if (!list_empty(&dc->active_list))
+		txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+
+	dev_crit(chan2dev(&dc->chan),
+		 "Bad descriptor submitted for DMA! (cookie: %d)\n",
+		 bad_desc->txd.cookie);
+	txx9dmac_dump_desc(dc, &bad_desc->hwdesc);
+	list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
+		txx9dmac_dump_desc(dc, &child->hwdesc);
+	/* Pretend the descriptor completed successfully */
+	txx9dmac_descriptor_complete(dc, bad_desc);
+}
+
+static void txx9dmac_scan_descriptors(struct txx9dmac_chan *dc)
+{
+	dma_addr_t chain;
+	struct txx9dmac_desc *desc, *_desc;
+	struct txx9dmac_desc *child;
+	u32 csr;
+
+	if (is_dmac64(dc)) {
+		chain = channel64_read_CHAR(dc);
+		csr = channel64_readl(dc, CSR);
+		channel64_writel(dc, CSR, csr);
+	} else {
+		chain = channel32_readl(dc, CHAR);
+		csr = channel32_readl(dc, CSR);
+		channel32_writel(dc, CSR, csr);
+	}
+	/* For dynamic chain, we should look at XFACT instead of NCHNC */
+	if (!(csr & (TXX9_DMA_CSR_XFACT | TXX9_DMA_CSR_ABCHC))) {
+		/* Everything we've submitted is done */
+		txx9dmac_complete_all(dc);
+		return;
+	}
+	if (!(csr & TXX9_DMA_CSR_CHNEN))
+		chain = 0;	/* last descriptor of this chain */
+
+	dev_vdbg(chan2dev(&dc->chan), "scan_descriptors: char=%#llx\n",
+		 (u64)chain);
+
+	list_for_each_entry_safe(desc, _desc, &dc->active_list, desc_node) {
+		if (desc_read_CHAR(dc, desc) == chain) {
+			/* This one is currently in progress */
+			if (csr & TXX9_DMA_CSR_ABCHC)
+				goto scan_done;
+			return;
+		}
+
+		list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+			if (desc_read_CHAR(dc, child) == chain) {
+				/* Currently in progress */
+				if (csr & TXX9_DMA_CSR_ABCHC)
+					goto scan_done;
+				return;
+			}
+
+		/*
+		 * No descriptors so far seem to be in progress, i.e.
+		 * this one must be done.
+		 */
+		txx9dmac_descriptor_complete(dc, desc);
+	}
+scan_done:
+	if (csr & TXX9_DMA_CSR_ABCHC) {
+		txx9dmac_handle_error(dc, csr);
+		return;
+	}
+
+	dev_err(chan2dev(&dc->chan),
+		"BUG: All descriptors done, but channel not idle!\n");
+
+	/* Try to continue after resetting the channel... */
+	txx9dmac_reset_chan(dc);
+
+	if (!list_empty(&dc->queue)) {
+		txx9dmac_dequeue(dc, &dc->active_list);
+		txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+	}
+}
+
+static void txx9dmac_chan_tasklet(unsigned long data)
+{
+	int irq;
+	u32 csr;
+	struct txx9dmac_chan *dc;
+
+	dc = (struct txx9dmac_chan *)data;
+	csr = channel_readl(dc, CSR);
+	dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n", csr);
+
+	spin_lock(&dc->lock);
+	if (csr & (TXX9_DMA_CSR_ABCHC | TXX9_DMA_CSR_NCHNC |
+		   TXX9_DMA_CSR_NTRNFC))
+		txx9dmac_scan_descriptors(dc);
+	spin_unlock(&dc->lock);
+	irq = dc->irq;
+
+	enable_irq(irq);
+}
+
+static irqreturn_t txx9dmac_chan_interrupt(int irq, void *dev_id)
+{
+	struct txx9dmac_chan *dc = dev_id;
+
+	dev_vdbg(chan2dev(&dc->chan), "interrupt: status=%#x\n",
+			channel_readl(dc, CSR));
+
+	tasklet_schedule(&dc->tasklet);
+	/*
+	 * Just disable the interrupts. We'll turn them back on in the
+	 * softirq handler.
+	 */
+	disable_irq_nosync(irq);
+
+	return IRQ_HANDLED;
+}
+
+static void txx9dmac_tasklet(unsigned long data)
+{
+	int irq;
+	u32 csr;
+	struct txx9dmac_chan *dc;
+
+	struct txx9dmac_dev *ddev = (struct txx9dmac_dev *)data;
+	u32 mcr;
+	int i;
+
+	mcr = dma_readl(ddev, MCR);
+	dev_vdbg(ddev->chan[0]->dma.dev, "tasklet: mcr=%x\n", mcr);
+	for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) {
+		if ((mcr >> (24 + i)) & 0x11) {
+			dc = ddev->chan[i];
+			csr = channel_readl(dc, CSR);
+			dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n",
+				 csr);
+			spin_lock(&dc->lock);
+			if (csr & (TXX9_DMA_CSR_ABCHC | TXX9_DMA_CSR_NCHNC |
+				   TXX9_DMA_CSR_NTRNFC))
+				txx9dmac_scan_descriptors(dc);
+			spin_unlock(&dc->lock);
+		}
+	}
+	irq = ddev->irq;
+
+	enable_irq(irq);
+}
+
+static irqreturn_t txx9dmac_interrupt(int irq, void *dev_id)
+{
+	struct txx9dmac_dev *ddev = dev_id;
+
+	dev_vdbg(ddev->chan[0]->dma.dev, "interrupt: status=%#x\n",
+			dma_readl(ddev, MCR));
+
+	tasklet_schedule(&ddev->tasklet);
+	/*
+	 * Just disable the interrupts. We'll turn them back on in the
+	 * softirq handler.
+	 */
+	disable_irq_nosync(irq);
+
+	return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+static dma_cookie_t txx9dmac_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct txx9dmac_desc *desc = txd_to_txx9dmac_desc(tx);
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(tx->chan);
+	dma_cookie_t cookie;
+
+	spin_lock_bh(&dc->lock);
+	cookie = txx9dmac_assign_cookie(dc, desc);
+
+	dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u %p\n",
+		 desc->txd.cookie, desc);
+
+	list_add_tail(&desc->desc_node, &dc->queue);
+	spin_unlock_bh(&dc->lock);
+
+	return cookie;
+}
+
+static struct dma_async_tx_descriptor *
+txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags)
+{
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+	struct txx9dmac_dev *ddev = dc->ddev;
+	struct txx9dmac_desc *desc;
+	struct txx9dmac_desc *first;
+	struct txx9dmac_desc *prev;
+	size_t xfer_count;
+	size_t offset;
+
+	dev_vdbg(chan2dev(chan), "prep_dma_memcpy d%#llx s%#llx l%#zx f%#lx\n",
+		 (u64)dest, (u64)src, len, flags);
+
+	if (unlikely(!len)) {
+		dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+		return NULL;
+	}
+
+	prev = first = NULL;
+
+	for (offset = 0; offset < len; offset += xfer_count) {
+		xfer_count = min_t(size_t, len - offset, TXX9_DMA_MAX_COUNT);
+		/*
+		 * Workaround for ERT-TX49H2-033, ERT-TX49H3-020,
+		 * ERT-TX49H4-016 (slightly conservative)
+		 */
+		if (__is_dmac64(ddev)) {
+			if (xfer_count > 0x100 &&
+			    (xfer_count & 0xff) >= 0xfa &&
+			    (xfer_count & 0xff) <= 0xff)
+				xfer_count -= 0x20;
+		} else {
+			if (xfer_count > 0x80 &&
+			    (xfer_count & 0x7f) >= 0x7e &&
+			    (xfer_count & 0x7f) <= 0x7f)
+				xfer_count -= 0x20;
+		}
+
+		desc = txx9dmac_desc_get(dc);
+		if (!desc) {
+			txx9dmac_desc_put(dc, first);
+			return NULL;
+		}
+
+		if (__is_dmac64(ddev)) {
+			desc->hwdesc.SAR = src + offset;
+			desc->hwdesc.DAR = dest + offset;
+			desc->hwdesc.CNTR = xfer_count;
+			txx9dmac_desc_set_nosimple(ddev, desc, 8, 8,
+					dc->ccr | TXX9_DMA_CCR_XFACT);
+		} else {
+			desc->hwdesc32.SAR = src + offset;
+			desc->hwdesc32.DAR = dest + offset;
+			desc->hwdesc32.CNTR = xfer_count;
+			txx9dmac_desc_set_nosimple(ddev, desc, 4, 4,
+					dc->ccr | TXX9_DMA_CCR_XFACT);
+		}
+
+		/*
+		 * The descriptors on tx_list are not reachable from
+		 * the dc->queue list or dc->active_list after a
+		 * submit.  If we put all descriptors on active_list,
+		 * calling of callback on the completion will be more
+		 * complex.
+		 */
+		if (!first) {
+			first = desc;
+		} else {
+			desc_write_CHAR(dc, prev, desc->txd.phys);
+			dma_sync_single_for_device(chan2parent(&dc->chan),
+					prev->txd.phys, ddev->descsize,
+					DMA_TO_DEVICE);
+			list_add_tail(&desc->desc_node,
+					&first->txd.tx_list);
+		}
+		prev = desc;
+	}
+
+	/* Trigger interrupt after last block */
+	if (flags & DMA_PREP_INTERRUPT)
+		txx9dmac_desc_set_INTENT(ddev, prev);
+
+	desc_write_CHAR(dc, prev, 0);
+	dma_sync_single_for_device(chan2parent(&dc->chan),
+			prev->txd.phys, ddev->descsize,
+			DMA_TO_DEVICE);
+
+	first->txd.flags = flags;
+	first->len = len;
+
+	return &first->txd;
+}
+
+static struct dma_async_tx_descriptor *
+txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
+		unsigned long flags)
+{
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+	struct txx9dmac_dev *ddev = dc->ddev;
+	struct txx9dmac_slave *ds = chan->private;
+	struct txx9dmac_desc *prev;
+	struct txx9dmac_desc *first;
+	unsigned int i;
+	struct scatterlist *sg;
+
+	dev_vdbg(chan2dev(chan), "prep_dma_slave\n");
+
+	BUG_ON(!ds || !ds->reg_width);
+	if (ds->tx_reg)
+		BUG_ON(direction != DMA_TO_DEVICE);
+	else
+		BUG_ON(direction != DMA_FROM_DEVICE);
+	if (unlikely(!sg_len))
+		return NULL;
+
+	prev = first = NULL;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		struct txx9dmac_desc *desc;
+		dma_addr_t mem;
+		u32 sai, dai;
+
+		desc = txx9dmac_desc_get(dc);
+		if (!desc) {
+			txx9dmac_desc_put(dc, first);
+			return NULL;
+		}
+
+		mem = sg_dma_address(sg);
+
+		if (__is_dmac64(ddev)) {
+			if (direction == DMA_TO_DEVICE) {
+				desc->hwdesc.SAR = mem;
+				desc->hwdesc.DAR = ds->tx_reg;
+			} else {
+				desc->hwdesc.SAR = ds->rx_reg;
+				desc->hwdesc.DAR = mem;
+			}
+			desc->hwdesc.CNTR = sg_dma_len(sg);
+		} else {
+			if (direction == DMA_TO_DEVICE) {
+				desc->hwdesc32.SAR = mem;
+				desc->hwdesc32.DAR = ds->tx_reg;
+			} else {
+				desc->hwdesc32.SAR = ds->rx_reg;
+				desc->hwdesc32.DAR = mem;
+			}
+			desc->hwdesc32.CNTR = sg_dma_len(sg);
+		}
+		if (direction == DMA_TO_DEVICE) {
+			sai = ds->reg_width;
+			dai = 0;
+		} else {
+			sai = 0;
+			dai = ds->reg_width;
+		}
+		txx9dmac_desc_set_nosimple(ddev, desc, sai, dai,
+					dc->ccr | TXX9_DMA_CCR_XFACT);
+
+		if (!first) {
+			first = desc;
+		} else {
+			desc_write_CHAR(dc, prev, desc->txd.phys);
+			dma_sync_single_for_device(chan2parent(&dc->chan),
+					prev->txd.phys,
+					ddev->descsize,
+					DMA_TO_DEVICE);
+			list_add_tail(&desc->desc_node,
+					&first->txd.tx_list);
+		}
+		prev = desc;
+	}
+
+	/* Trigger interrupt after last block */
+	if (flags & DMA_PREP_INTERRUPT)
+		txx9dmac_desc_set_INTENT(ddev, prev);
+
+	desc_write_CHAR(dc, prev, 0);
+	dma_sync_single_for_device(chan2parent(&dc->chan),
+			prev->txd.phys, ddev->descsize,
+			DMA_TO_DEVICE);
+
+	first->txd.flags = flags;
+	first->len = 0;
+
+	return &first->txd;
+}
+
+static void txx9dmac_terminate_all(struct dma_chan *chan)
+{
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+	struct txx9dmac_desc *desc, *_desc;
+	LIST_HEAD(list);
+
+	dev_vdbg(chan2dev(chan), "terminate_all\n");
+	spin_lock_bh(&dc->lock);
+
+	txx9dmac_reset_chan(dc);
+
+	/* active_list entries will end up before queued entries */
+	list_splice_init(&dc->queue, &list);
+	list_splice_init(&dc->active_list, &list);
+
+	spin_unlock_bh(&dc->lock);
+
+	/* Flush all pending and queued descriptors */
+	list_for_each_entry_safe(desc, _desc, &list, desc_node)
+		txx9dmac_descriptor_complete(dc, desc);
+}
+
+static enum dma_status
+txx9dmac_is_tx_complete(struct dma_chan *chan,
+			dma_cookie_t cookie,
+		dma_cookie_t *done, dma_cookie_t *used)
+{
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+	int ret;
+
+	last_complete = dc->completed;
+	last_used = chan->cookie;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret != DMA_SUCCESS) {
+		spin_lock_bh(&dc->lock);
+		txx9dmac_scan_descriptors(dc);
+		spin_unlock_bh(&dc->lock);
+
+		last_complete = dc->completed;
+		last_used = chan->cookie;
+
+		ret = dma_async_is_complete(cookie, last_complete, last_used);
+	}
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return ret;
+}
+
+static void txx9dmac_chain_dynamic(struct txx9dmac_chan *dc,
+				   struct txx9dmac_desc *prev)
+{
+	struct txx9dmac_dev *ddev = dc->ddev;
+	struct txx9dmac_desc *desc;
+	LIST_HEAD(list);
+
+	prev = txx9dmac_last_child(prev);
+	txx9dmac_dequeue(dc, &list);
+	desc = list_entry(list.next, struct txx9dmac_desc, desc_node);
+	desc_write_CHAR(dc, prev, desc->txd.phys);
+	dma_sync_single_for_device(chan2parent(&dc->chan),
+				   prev->txd.phys, ddev->descsize,
+				   DMA_TO_DEVICE);
+	mmiowb();
+	if (!(channel_readl(dc, CSR) & TXX9_DMA_CSR_CHNEN) &&
+	    channel_read_CHAR(dc) == prev->txd.phys)
+		/* Restart chain DMA */
+		channel_write_CHAR(dc, desc->txd.phys);
+	list_splice_tail(&list, &dc->active_list);
+}
+
+static void txx9dmac_issue_pending(struct dma_chan *chan)
+{
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+
+	spin_lock_bh(&dc->lock);
+
+	if (!list_empty(&dc->active_list))
+		txx9dmac_scan_descriptors(dc);
+	if (!list_empty(&dc->queue)) {
+		if (list_empty(&dc->active_list)) {
+			txx9dmac_dequeue(dc, &dc->active_list);
+			txx9dmac_dostart(dc, txx9dmac_first_active(dc));
+		} else if (txx9_dma_have_SMPCHN()) {
+			struct txx9dmac_desc *prev = txx9dmac_last_active(dc);
+
+			if (!(prev->txd.flags & DMA_PREP_INTERRUPT) ||
+			    txx9dmac_chan_INTENT(dc))
+				txx9dmac_chain_dynamic(dc, prev);
+		}
+	}
+
+	spin_unlock_bh(&dc->lock);
+}
+
+static int txx9dmac_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+	struct txx9dmac_slave *ds = chan->private;
+	struct txx9dmac_desc *desc;
+	int i;
+
+	dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
+
+	/* ASSERT:  channel is idle */
+	if (channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT) {
+		dev_dbg(chan2dev(chan), "DMA channel not idle?\n");
+		return -EIO;
+	}
+
+	dc->completed = chan->cookie = 1;
+
+	dc->ccr = TXX9_DMA_CCR_IMMCHN | TXX9_DMA_CCR_INTENE | CCR_LE;
+	txx9dmac_chan_set_SMPCHN(dc);
+	if (!txx9_dma_have_SMPCHN() || (dc->ccr & TXX9_DMA_CCR_SMPCHN))
+		dc->ccr |= TXX9_DMA_CCR_INTENC;
+	if (chan->device->device_prep_dma_memcpy) {
+		if (ds)
+			return -EINVAL;
+		dc->ccr |= TXX9_DMA_CCR_XFSZ_X8;
+	} else {
+		if (!ds ||
+		    (ds->tx_reg && ds->rx_reg) || (!ds->tx_reg && !ds->rx_reg))
+			return -EINVAL;
+		dc->ccr |= TXX9_DMA_CCR_EXTRQ |
+			TXX9_DMA_CCR_XFSZ(__ffs(ds->reg_width));
+		txx9dmac_chan_set_INTENT(dc);
+	}
+
+	spin_lock_bh(&dc->lock);
+	i = dc->descs_allocated;
+	while (dc->descs_allocated < TXX9_DMA_INITIAL_DESC_COUNT) {
+		spin_unlock_bh(&dc->lock);
+
+		desc = txx9dmac_desc_alloc(dc, GFP_KERNEL);
+		if (!desc) {
+			dev_info(chan2dev(chan),
+				"only allocated %d descriptors\n", i);
+			spin_lock_bh(&dc->lock);
+			break;
+		}
+		txx9dmac_desc_put(dc, desc);
+
+		spin_lock_bh(&dc->lock);
+		i = ++dc->descs_allocated;
+	}
+	spin_unlock_bh(&dc->lock);
+
+	dev_dbg(chan2dev(chan),
+		"alloc_chan_resources allocated %d descriptors\n", i);
+
+	return i;
+}
+
+static void txx9dmac_free_chan_resources(struct dma_chan *chan)
+{
+	struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
+	struct txx9dmac_dev *ddev = dc->ddev;
+	struct txx9dmac_desc *desc, *_desc;
+	LIST_HEAD(list);
+
+	dev_dbg(chan2dev(chan), "free_chan_resources (descs allocated=%u)\n",
+			dc->descs_allocated);
+
+	/* ASSERT:  channel is idle */
+	BUG_ON(!list_empty(&dc->active_list));
+	BUG_ON(!list_empty(&dc->queue));
+	BUG_ON(channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT);
+
+	spin_lock_bh(&dc->lock);
+	list_splice_init(&dc->free_list, &list);
+	dc->descs_allocated = 0;
+	spin_unlock_bh(&dc->lock);
+
+	list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+		dev_vdbg(chan2dev(chan), "  freeing descriptor %p\n", desc);
+		dma_unmap_single(chan2parent(chan), desc->txd.phys,
+				 ddev->descsize, DMA_TO_DEVICE);
+		kfree(desc);
+	}
+
+	dev_vdbg(chan2dev(chan), "free_chan_resources done\n");
+}
+
+/*----------------------------------------------------------------------*/
+
+static void txx9dmac_off(struct txx9dmac_dev *ddev)
+{
+	dma_writel(ddev, MCR, 0);
+	mmiowb();
+}
+
+static int __init txx9dmac_chan_probe(struct platform_device *pdev)
+{
+	struct txx9dmac_chan_platform_data *cpdata = pdev->dev.platform_data;
+	struct platform_device *dmac_dev = cpdata->dmac_dev;
+	struct txx9dmac_platform_data *pdata = dmac_dev->dev.platform_data;
+	struct txx9dmac_chan *dc;
+	int err;
+	int ch = pdev->id % TXX9_DMA_MAX_NR_CHANNELS;
+	int irq;
+
+	dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
+	if (!dc)
+		return -ENOMEM;
+
+	dc->dma.dev = &pdev->dev;
+	dc->dma.device_alloc_chan_resources = txx9dmac_alloc_chan_resources;
+	dc->dma.device_free_chan_resources = txx9dmac_free_chan_resources;
+	dc->dma.device_terminate_all = txx9dmac_terminate_all;
+	dc->dma.device_is_tx_complete = txx9dmac_is_tx_complete;
+	dc->dma.device_issue_pending = txx9dmac_issue_pending;
+	if (pdata && pdata->memcpy_chan == ch) {
+		dc->dma.device_prep_dma_memcpy = txx9dmac_prep_dma_memcpy;
+		dma_cap_set(DMA_MEMCPY, dc->dma.cap_mask);
+	} else {
+		dc->dma.device_prep_slave_sg = txx9dmac_prep_slave_sg;
+		dma_cap_set(DMA_SLAVE, dc->dma.cap_mask);
+		dma_cap_set(DMA_PRIVATE, dc->dma.cap_mask);
+	}
+
+	INIT_LIST_HEAD(&dc->dma.channels);
+	dc->ddev = platform_get_drvdata(dmac_dev);
+	if (dc->ddev->irq < 0) {
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0)
+			return irq;
+		tasklet_init(&dc->tasklet, txx9dmac_chan_tasklet,
+				(unsigned long)dc);
+		dc->irq = irq;
+		err = devm_request_irq(&pdev->dev, dc->irq,
+			txx9dmac_chan_interrupt, 0, dev_name(&pdev->dev), dc);
+		if (err)
+			return err;
+	} else
+		dc->irq = -1;
+	dc->ddev->chan[ch] = dc;
+	dc->chan.device = &dc->dma;
+	list_add_tail(&dc->chan.device_node, &dc->chan.device->channels);
+	dc->chan.cookie = dc->completed = 1;
+
+	if (is_dmac64(dc))
+		dc->ch_regs = &__txx9dmac_regs(dc->ddev)->CHAN[ch];
+	else
+		dc->ch_regs = &__txx9dmac_regs32(dc->ddev)->CHAN[ch];
+	spin_lock_init(&dc->lock);
+
+	INIT_LIST_HEAD(&dc->active_list);
+	INIT_LIST_HEAD(&dc->queue);
+	INIT_LIST_HEAD(&dc->free_list);
+
+	txx9dmac_reset_chan(dc);
+
+	platform_set_drvdata(pdev, dc);
+
+	err = dma_async_device_register(&dc->dma);
+	if (err)
+		return err;
+	dev_dbg(&pdev->dev, "TXx9 DMA Channel (dma%d%s%s)\n",
+		dc->dma.dev_id,
+		dma_has_cap(DMA_MEMCPY, dc->dma.cap_mask) ? " memcpy" : "",
+		dma_has_cap(DMA_SLAVE, dc->dma.cap_mask) ? " slave" : "");
+
+	return 0;
+}
+
+static int __exit txx9dmac_chan_remove(struct platform_device *pdev)
+{
+	struct txx9dmac_chan *dc = platform_get_drvdata(pdev);
+
+	dma_async_device_unregister(&dc->dma);
+	if (dc->irq >= 0)
+		tasklet_kill(&dc->tasklet);
+	dc->ddev->chan[pdev->id % TXX9_DMA_MAX_NR_CHANNELS] = NULL;
+	return 0;
+}
+
+static int __init txx9dmac_probe(struct platform_device *pdev)
+{
+	struct txx9dmac_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *io;
+	struct txx9dmac_dev *ddev;
+	u32 mcr;
+	int err;
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!io)
+		return -EINVAL;
+
+	ddev = devm_kzalloc(&pdev->dev, sizeof(*ddev), GFP_KERNEL);
+	if (!ddev)
+		return -ENOMEM;
+
+	if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io),
+				     dev_name(&pdev->dev)))
+		return -EBUSY;
+
+	ddev->regs = devm_ioremap(&pdev->dev, io->start, resource_size(io));
+	if (!ddev->regs)
+		return -ENOMEM;
+	ddev->have_64bit_regs = pdata->have_64bit_regs;
+	if (__is_dmac64(ddev))
+		ddev->descsize = sizeof(struct txx9dmac_hwdesc);
+	else
+		ddev->descsize = sizeof(struct txx9dmac_hwdesc32);
+
+	/* force dma off, just in case */
+	txx9dmac_off(ddev);
+
+	ddev->irq = platform_get_irq(pdev, 0);
+	if (ddev->irq >= 0) {
+		tasklet_init(&ddev->tasklet, txx9dmac_tasklet,
+				(unsigned long)ddev);
+		err = devm_request_irq(&pdev->dev, ddev->irq,
+			txx9dmac_interrupt, 0, dev_name(&pdev->dev), ddev);
+		if (err)
+			return err;
+	}
+
+	mcr = TXX9_DMA_MCR_MSTEN | MCR_LE;
+	if (pdata && pdata->memcpy_chan >= 0)
+		mcr |= TXX9_DMA_MCR_FIFUM(pdata->memcpy_chan);
+	dma_writel(ddev, MCR, mcr);
+
+	platform_set_drvdata(pdev, ddev);
+	return 0;
+}
+
+static int __exit txx9dmac_remove(struct platform_device *pdev)
+{
+	struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+
+	txx9dmac_off(ddev);
+	if (ddev->irq >= 0)
+		tasklet_kill(&ddev->tasklet);
+	return 0;
+}
+
+static void txx9dmac_shutdown(struct platform_device *pdev)
+{
+	struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+
+	txx9dmac_off(ddev);
+}
+
+static int txx9dmac_suspend_late(struct platform_device *pdev,
+				 pm_message_t mesg)
+{
+	struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+
+	txx9dmac_off(ddev);
+	return 0;
+}
+
+static int txx9dmac_resume_early(struct platform_device *pdev)
+{
+	struct txx9dmac_dev *ddev = platform_get_drvdata(pdev);
+	struct txx9dmac_platform_data *pdata = pdev->dev.platform_data;
+	u32 mcr;
+
+	mcr = TXX9_DMA_MCR_MSTEN | MCR_LE;
+	if (pdata && pdata->memcpy_chan >= 0)
+		mcr |= TXX9_DMA_MCR_FIFUM(pdata->memcpy_chan);
+	dma_writel(ddev, MCR, mcr);
+	return 0;
+
+}
+
+static struct platform_driver txx9dmac_chan_driver = {
+	.remove		= __exit_p(txx9dmac_chan_remove),
+	.driver = {
+		.name	= "txx9dmac-chan",
+	},
+};
+
+static struct platform_driver txx9dmac_driver = {
+	.remove		= __exit_p(txx9dmac_remove),
+	.shutdown	= txx9dmac_shutdown,
+	.suspend_late	= txx9dmac_suspend_late,
+	.resume_early	= txx9dmac_resume_early,
+	.driver = {
+		.name	= "txx9dmac",
+	},
+};
+
+static int __init txx9dmac_init(void)
+{
+	int rc;
+
+	rc = platform_driver_probe(&txx9dmac_driver, txx9dmac_probe);
+	if (!rc) {
+		rc = platform_driver_probe(&txx9dmac_chan_driver,
+					   txx9dmac_chan_probe);
+		if (rc)
+			platform_driver_unregister(&txx9dmac_driver);
+	}
+	return rc;
+}
+module_init(txx9dmac_init);
+
+static void __exit txx9dmac_exit(void)
+{
+	platform_driver_unregister(&txx9dmac_chan_driver);
+	platform_driver_unregister(&txx9dmac_driver);
+}
+module_exit(txx9dmac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TXx9 DMA Controller driver");
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
diff -druN linux-libre-2.6.30-gnu/drivers/dma/txx9dmac.h linux-libre-2.6.31-gnu/drivers/dma/txx9dmac.h
--- linux-libre-2.6.30-gnu/drivers/dma/txx9dmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/dma/txx9dmac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,307 @@
+/*
+ * Driver for the TXx9 SoC DMA Controller
+ *
+ * Copyright (C) 2009 Atsushi Nemoto
+ *
+ * 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.
+ */
+#ifndef TXX9DMAC_H
+#define TXX9DMAC_H
+
+#include <linux/dmaengine.h>
+#include <asm/txx9/dmac.h>
+
+/*
+ * Design Notes:
+ *
+ * This DMAC have four channels and one FIFO buffer.  Each channel can
+ * be configured for memory-memory or device-memory transfer, but only
+ * one channel can do alignment-free memory-memory transfer at a time
+ * while the channel should occupy the FIFO buffer for effective
+ * transfers.
+ *
+ * Instead of dynamically assign the FIFO buffer to channels, I chose
+ * make one dedicated channel for memory-memory transfer.  The
+ * dedicated channel is public.  Other channels are private and used
+ * for slave transfer.  Some devices in the SoC are wired to certain
+ * DMA channel.
+ */
+
+#ifdef CONFIG_MACH_TX49XX
+static inline bool txx9_dma_have_SMPCHN(void)
+{
+	return true;
+}
+#define TXX9_DMA_USE_SIMPLE_CHAIN
+#else
+static inline bool txx9_dma_have_SMPCHN(void)
+{
+	return false;
+}
+#endif
+
+#ifdef __LITTLE_ENDIAN
+#ifdef CONFIG_MACH_TX49XX
+#define CCR_LE	TXX9_DMA_CCR_LE
+#define MCR_LE	0
+#else
+#define CCR_LE	0
+#define MCR_LE	TXX9_DMA_MCR_LE
+#endif
+#else
+#define CCR_LE	0
+#define MCR_LE	0
+#endif
+
+/*
+ * Redefine this macro to handle differences between 32- and 64-bit
+ * addressing, big vs. little endian, etc.
+ */
+#ifdef __BIG_ENDIAN
+#define TXX9_DMA_REG32(name)		u32 __pad_##name; u32 name
+#else
+#define TXX9_DMA_REG32(name)		u32 name; u32 __pad_##name
+#endif
+
+/* Hardware register definitions. */
+struct txx9dmac_cregs {
+#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
+	TXX9_DMA_REG32(CHAR);	/* Chain Address Register */
+#else
+	u64 CHAR;		/* Chain Address Register */
+#endif
+	u64 SAR;		/* Source Address Register */
+	u64 DAR;		/* Destination Address Register */
+	TXX9_DMA_REG32(CNTR);	/* Count Register */
+	TXX9_DMA_REG32(SAIR);	/* Source Address Increment Register */
+	TXX9_DMA_REG32(DAIR);	/* Destination Address Increment Register */
+	TXX9_DMA_REG32(CCR);	/* Channel Control Register */
+	TXX9_DMA_REG32(CSR);	/* Channel Status Register */
+};
+struct txx9dmac_cregs32 {
+	u32 CHAR;
+	u32 SAR;
+	u32 DAR;
+	u32 CNTR;
+	u32 SAIR;
+	u32 DAIR;
+	u32 CCR;
+	u32 CSR;
+};
+
+struct txx9dmac_regs {
+	/* per-channel registers */
+	struct txx9dmac_cregs	CHAN[TXX9_DMA_MAX_NR_CHANNELS];
+	u64	__pad[9];
+	u64	MFDR;		/* Memory Fill Data Register */
+	TXX9_DMA_REG32(MCR);	/* Master Control Register */
+};
+struct txx9dmac_regs32 {
+	struct txx9dmac_cregs32	CHAN[TXX9_DMA_MAX_NR_CHANNELS];
+	u32	__pad[9];
+	u32	MFDR;
+	u32	MCR;
+};
+
+/* bits for MCR */
+#define TXX9_DMA_MCR_EIS(ch)	(0x10000000<<(ch))
+#define TXX9_DMA_MCR_DIS(ch)	(0x01000000<<(ch))
+#define TXX9_DMA_MCR_RSFIF	0x00000080
+#define TXX9_DMA_MCR_FIFUM(ch)	(0x00000008<<(ch))
+#define TXX9_DMA_MCR_LE		0x00000004
+#define TXX9_DMA_MCR_RPRT	0x00000002
+#define TXX9_DMA_MCR_MSTEN	0x00000001
+
+/* bits for CCRn */
+#define TXX9_DMA_CCR_IMMCHN	0x20000000
+#define TXX9_DMA_CCR_USEXFSZ	0x10000000
+#define TXX9_DMA_CCR_LE		0x08000000
+#define TXX9_DMA_CCR_DBINH	0x04000000
+#define TXX9_DMA_CCR_SBINH	0x02000000
+#define TXX9_DMA_CCR_CHRST	0x01000000
+#define TXX9_DMA_CCR_RVBYTE	0x00800000
+#define TXX9_DMA_CCR_ACKPOL	0x00400000
+#define TXX9_DMA_CCR_REQPL	0x00200000
+#define TXX9_DMA_CCR_EGREQ	0x00100000
+#define TXX9_DMA_CCR_CHDN	0x00080000
+#define TXX9_DMA_CCR_DNCTL	0x00060000
+#define TXX9_DMA_CCR_EXTRQ	0x00010000
+#define TXX9_DMA_CCR_INTRQD	0x0000e000
+#define TXX9_DMA_CCR_INTENE	0x00001000
+#define TXX9_DMA_CCR_INTENC	0x00000800
+#define TXX9_DMA_CCR_INTENT	0x00000400
+#define TXX9_DMA_CCR_CHNEN	0x00000200
+#define TXX9_DMA_CCR_XFACT	0x00000100
+#define TXX9_DMA_CCR_SMPCHN	0x00000020
+#define TXX9_DMA_CCR_XFSZ(order)	(((order) << 2) & 0x0000001c)
+#define TXX9_DMA_CCR_XFSZ_1	TXX9_DMA_CCR_XFSZ(0)
+#define TXX9_DMA_CCR_XFSZ_2	TXX9_DMA_CCR_XFSZ(1)
+#define TXX9_DMA_CCR_XFSZ_4	TXX9_DMA_CCR_XFSZ(2)
+#define TXX9_DMA_CCR_XFSZ_8	TXX9_DMA_CCR_XFSZ(3)
+#define TXX9_DMA_CCR_XFSZ_X4	TXX9_DMA_CCR_XFSZ(4)
+#define TXX9_DMA_CCR_XFSZ_X8	TXX9_DMA_CCR_XFSZ(5)
+#define TXX9_DMA_CCR_XFSZ_X16	TXX9_DMA_CCR_XFSZ(6)
+#define TXX9_DMA_CCR_XFSZ_X32	TXX9_DMA_CCR_XFSZ(7)
+#define TXX9_DMA_CCR_MEMIO	0x00000002
+#define TXX9_DMA_CCR_SNGAD	0x00000001
+
+/* bits for CSRn */
+#define TXX9_DMA_CSR_CHNEN	0x00000400
+#define TXX9_DMA_CSR_STLXFER	0x00000200
+#define TXX9_DMA_CSR_XFACT	0x00000100
+#define TXX9_DMA_CSR_ABCHC	0x00000080
+#define TXX9_DMA_CSR_NCHNC	0x00000040
+#define TXX9_DMA_CSR_NTRNFC	0x00000020
+#define TXX9_DMA_CSR_EXTDN	0x00000010
+#define TXX9_DMA_CSR_CFERR	0x00000008
+#define TXX9_DMA_CSR_CHERR	0x00000004
+#define TXX9_DMA_CSR_DESERR	0x00000002
+#define TXX9_DMA_CSR_SORERR	0x00000001
+
+struct txx9dmac_chan {
+	struct dma_chan		chan;
+	struct dma_device	dma;
+	struct txx9dmac_dev	*ddev;
+	void __iomem		*ch_regs;
+	struct tasklet_struct	tasklet;
+	int			irq;
+	u32			ccr;
+
+	spinlock_t		lock;
+
+	/* these other elements are all protected by lock */
+	dma_cookie_t		completed;
+	struct list_head	active_list;
+	struct list_head	queue;
+	struct list_head	free_list;
+
+	unsigned int		descs_allocated;
+};
+
+struct txx9dmac_dev {
+	void __iomem		*regs;
+	struct tasklet_struct	tasklet;
+	int			irq;
+	struct txx9dmac_chan	*chan[TXX9_DMA_MAX_NR_CHANNELS];
+	bool			have_64bit_regs;
+	unsigned int		descsize;
+};
+
+static inline bool __is_dmac64(const struct txx9dmac_dev *ddev)
+{
+	return ddev->have_64bit_regs;
+}
+
+static inline bool is_dmac64(const struct txx9dmac_chan *dc)
+{
+	return __is_dmac64(dc->ddev);
+}
+
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+/* Hardware descriptor definition. (for simple-chain) */
+struct txx9dmac_hwdesc {
+#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
+	TXX9_DMA_REG32(CHAR);
+#else
+	u64 CHAR;
+#endif
+	u64 SAR;
+	u64 DAR;
+	TXX9_DMA_REG32(CNTR);
+};
+struct txx9dmac_hwdesc32 {
+	u32 CHAR;
+	u32 SAR;
+	u32 DAR;
+	u32 CNTR;
+};
+#else
+#define txx9dmac_hwdesc txx9dmac_cregs
+#define txx9dmac_hwdesc32 txx9dmac_cregs32
+#endif
+
+struct txx9dmac_desc {
+	/* FIRST values the hardware uses */
+	union {
+		struct txx9dmac_hwdesc hwdesc;
+		struct txx9dmac_hwdesc32 hwdesc32;
+	};
+
+	/* THEN values for driver housekeeping */
+	struct list_head		desc_node ____cacheline_aligned;
+	struct dma_async_tx_descriptor	txd;
+	size_t				len;
+};
+
+#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
+
+static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
+{
+	return (dc->ccr & TXX9_DMA_CCR_INTENT) != 0;
+}
+
+static inline void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
+{
+	dc->ccr |= TXX9_DMA_CCR_INTENT;
+}
+
+static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
+					    struct txx9dmac_desc *desc)
+{
+}
+
+static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
+{
+	dc->ccr |= TXX9_DMA_CCR_SMPCHN;
+}
+
+static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
+					      struct txx9dmac_desc *desc,
+					      u32 sair, u32 dair, u32 ccr)
+{
+}
+
+#else /* TXX9_DMA_USE_SIMPLE_CHAIN */
+
+static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
+{
+	return true;
+}
+
+static void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
+{
+}
+
+static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
+					    struct txx9dmac_desc *desc)
+{
+	if (__is_dmac64(ddev))
+		desc->hwdesc.CCR |= TXX9_DMA_CCR_INTENT;
+	else
+		desc->hwdesc32.CCR |= TXX9_DMA_CCR_INTENT;
+}
+
+static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
+{
+}
+
+static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
+					      struct txx9dmac_desc *desc,
+					      u32 sai, u32 dai, u32 ccr)
+{
+	if (__is_dmac64(ddev)) {
+		desc->hwdesc.SAIR = sai;
+		desc->hwdesc.DAIR = dai;
+		desc->hwdesc.CCR = ccr;
+	} else {
+		desc->hwdesc32.SAIR = sai;
+		desc->hwdesc32.DAIR = dai;
+		desc->hwdesc32.CCR = ccr;
+	}
+}
+
+#endif /* TXX9_DMA_USE_SIMPLE_CHAIN */
+
+#endif /* TXX9DMAC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/edac/amd64_edac.c linux-libre-2.6.31-gnu/drivers/edac/amd64_edac.c
--- linux-libre-2.6.30-gnu/drivers/edac/amd64_edac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/edac/amd64_edac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3366 @@
+#include "amd64_edac.h"
+#include <asm/k8.h>
+
+static struct edac_pci_ctl_info *amd64_ctl_pci;
+
+static int report_gart_errors;
+module_param(report_gart_errors, int, 0644);
+
+/*
+ * Set by command line parameter. If BIOS has enabled the ECC, this override is
+ * cleared to prevent re-enabling the hardware by this driver.
+ */
+static int ecc_enable_override;
+module_param(ecc_enable_override, int, 0644);
+
+/* Lookup table for all possible MC control instances */
+struct amd64_pvt;
+static struct mem_ctl_info *mci_lookup[MAX_NUMNODES];
+static struct amd64_pvt *pvt_lookup[MAX_NUMNODES];
+
+/*
+ * Memory scrubber control interface. For K8, memory scrubbing is handled by
+ * hardware and can involve L2 cache, dcache as well as the main memory. With
+ * F10, this is extended to L3 cache scrubbing on CPU models sporting that
+ * functionality.
+ *
+ * This causes the "units" for the scrubbing speed to vary from 64 byte blocks
+ * (dram) over to cache lines. This is nasty, so we will use bandwidth in
+ * bytes/sec for the setting.
+ *
+ * Currently, we only do dram scrubbing. If the scrubbing is done in software on
+ * other archs, we might not have access to the caches directly.
+ */
+
+/*
+ * scan the scrub rate mapping table for a close or matching bandwidth value to
+ * issue. If requested is too big, then use last maximum value found.
+ */
+static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw,
+				       u32 min_scrubrate)
+{
+	u32 scrubval;
+	int i;
+
+	/*
+	 * map the configured rate (new_bw) to a value specific to the AMD64
+	 * memory controller and apply to register. Search for the first
+	 * bandwidth entry that is greater or equal than the setting requested
+	 * and program that. If at last entry, turn off DRAM scrubbing.
+	 */
+	for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
+		/*
+		 * skip scrub rates which aren't recommended
+		 * (see F10 BKDG, F3x58)
+		 */
+		if (scrubrates[i].scrubval < min_scrubrate)
+			continue;
+
+		if (scrubrates[i].bandwidth <= new_bw)
+			break;
+
+		/*
+		 * if no suitable bandwidth found, turn off DRAM scrubbing
+		 * entirely by falling back to the last element in the
+		 * scrubrates array.
+		 */
+	}
+
+	scrubval = scrubrates[i].scrubval;
+	if (scrubval)
+		edac_printk(KERN_DEBUG, EDAC_MC,
+			    "Setting scrub rate bandwidth: %u\n",
+			    scrubrates[i].bandwidth);
+	else
+		edac_printk(KERN_DEBUG, EDAC_MC, "Turning scrubbing off.\n");
+
+	pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F);
+
+	return 0;
+}
+
+static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 *bandwidth)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 min_scrubrate = 0x0;
+
+	switch (boot_cpu_data.x86) {
+	case 0xf:
+		min_scrubrate = K8_MIN_SCRUB_RATE_BITS;
+		break;
+	case 0x10:
+		min_scrubrate = F10_MIN_SCRUB_RATE_BITS;
+		break;
+	case 0x11:
+		min_scrubrate = F11_MIN_SCRUB_RATE_BITS;
+		break;
+
+	default:
+		amd64_printk(KERN_ERR, "Unsupported family!\n");
+		break;
+	}
+	return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, *bandwidth,
+			min_scrubrate);
+}
+
+static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 scrubval = 0;
+	int status = -1, i, ret = 0;
+
+	ret = pci_read_config_dword(pvt->misc_f3_ctl, K8_SCRCTRL, &scrubval);
+	if (ret)
+		debugf0("Reading K8_SCRCTRL failed\n");
+
+	scrubval = scrubval & 0x001F;
+
+	edac_printk(KERN_DEBUG, EDAC_MC,
+		    "pci-read, sdram scrub control value: %d \n", scrubval);
+
+	for (i = 0; ARRAY_SIZE(scrubrates); i++) {
+		if (scrubrates[i].scrubval == scrubval) {
+			*bw = scrubrates[i].bandwidth;
+			status = 0;
+			break;
+		}
+	}
+
+	return status;
+}
+
+/* Map from a CSROW entry to the mask entry that operates on it */
+static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow)
+{
+	return csrow >> (pvt->num_dcsm >> 3);
+}
+
+/* return the 'base' address the i'th CS entry of the 'dct' DRAM controller */
+static u32 amd64_get_dct_base(struct amd64_pvt *pvt, int dct, int csrow)
+{
+	if (dct == 0)
+		return pvt->dcsb0[csrow];
+	else
+		return pvt->dcsb1[csrow];
+}
+
+/*
+ * Return the 'mask' address the i'th CS entry. This function is needed because
+ * there number of DCSM registers on Rev E and prior vs Rev F and later is
+ * different.
+ */
+static u32 amd64_get_dct_mask(struct amd64_pvt *pvt, int dct, int csrow)
+{
+	if (dct == 0)
+		return pvt->dcsm0[amd64_map_to_dcs_mask(pvt, csrow)];
+	else
+		return pvt->dcsm1[amd64_map_to_dcs_mask(pvt, csrow)];
+}
+
+
+/*
+ * In *base and *limit, pass back the full 40-bit base and limit physical
+ * addresses for the node given by node_id.  This information is obtained from
+ * DRAM Base (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers. The
+ * base and limit addresses are of type SysAddr, as defined at the start of
+ * section 3.4.4 (p. 70).  They are the lowest and highest physical addresses
+ * in the address range they represent.
+ */
+static void amd64_get_base_and_limit(struct amd64_pvt *pvt, int node_id,
+			       u64 *base, u64 *limit)
+{
+	*base = pvt->dram_base[node_id];
+	*limit = pvt->dram_limit[node_id];
+}
+
+/*
+ * Return 1 if the SysAddr given by sys_addr matches the base/limit associated
+ * with node_id
+ */
+static int amd64_base_limit_match(struct amd64_pvt *pvt,
+					u64 sys_addr, int node_id)
+{
+	u64 base, limit, addr;
+
+	amd64_get_base_and_limit(pvt, node_id, &base, &limit);
+
+	/* The K8 treats this as a 40-bit value.  However, bits 63-40 will be
+	 * all ones if the most significant implemented address bit is 1.
+	 * Here we discard bits 63-40.  See section 3.4.2 of AMD publication
+	 * 24592: AMD x86-64 Architecture Programmer's Manual Volume 1
+	 * Application Programming.
+	 */
+	addr = sys_addr & 0x000000ffffffffffull;
+
+	return (addr >= base) && (addr <= limit);
+}
+
+/*
+ * Attempt to map a SysAddr to a node. On success, return a pointer to the
+ * mem_ctl_info structure for the node that the SysAddr maps to.
+ *
+ * On failure, return NULL.
+ */
+static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
+						u64 sys_addr)
+{
+	struct amd64_pvt *pvt;
+	int node_id;
+	u32 intlv_en, bits;
+
+	/*
+	 * Here we use the DRAM Base (section 3.4.4.1) and DRAM Limit (section
+	 * 3.4.4.2) registers to map the SysAddr to a node ID.
+	 */
+	pvt = mci->pvt_info;
+
+	/*
+	 * The value of this field should be the same for all DRAM Base
+	 * registers.  Therefore we arbitrarily choose to read it from the
+	 * register for node 0.
+	 */
+	intlv_en = pvt->dram_IntlvEn[0];
+
+	if (intlv_en == 0) {
+		for (node_id = 0; ; ) {
+			if (amd64_base_limit_match(pvt, sys_addr, node_id))
+				break;
+
+			if (++node_id >= DRAM_REG_COUNT)
+				goto err_no_match;
+		}
+		goto found;
+	}
+
+	if (unlikely((intlv_en != (0x01 << 8)) &&
+		     (intlv_en != (0x03 << 8)) &&
+		     (intlv_en != (0x07 << 8)))) {
+		amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from "
+			     "IntlvEn field of DRAM Base Register for node 0: "
+			     "This probably indicates a BIOS bug.\n", intlv_en);
+		return NULL;
+	}
+
+	bits = (((u32) sys_addr) >> 12) & intlv_en;
+
+	for (node_id = 0; ; ) {
+		if ((pvt->dram_limit[node_id] & intlv_en) == bits)
+			break;	/* intlv_sel field matches */
+
+		if (++node_id >= DRAM_REG_COUNT)
+			goto err_no_match;
+	}
+
+	/* sanity test for sys_addr */
+	if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) {
+		amd64_printk(KERN_WARNING,
+			  "%s(): sys_addr 0x%lx falls outside base/limit "
+			  "address range for node %d with node interleaving "
+			  "enabled.\n", __func__, (unsigned long)sys_addr,
+			  node_id);
+		return NULL;
+	}
+
+found:
+	return edac_mc_find(node_id);
+
+err_no_match:
+	debugf2("sys_addr 0x%lx doesn't match any node\n",
+		(unsigned long)sys_addr);
+
+	return NULL;
+}
+
+/*
+ * Extract the DRAM CS base address from selected csrow register.
+ */
+static u64 base_from_dct_base(struct amd64_pvt *pvt, int csrow)
+{
+	return ((u64) (amd64_get_dct_base(pvt, 0, csrow) & pvt->dcsb_base)) <<
+				pvt->dcs_shift;
+}
+
+/*
+ * Extract the mask from the dcsb0[csrow] entry in a CPU revision-specific way.
+ */
+static u64 mask_from_dct_mask(struct amd64_pvt *pvt, int csrow)
+{
+	u64 dcsm_bits, other_bits;
+	u64 mask;
+
+	/* Extract bits from DRAM CS Mask. */
+	dcsm_bits = amd64_get_dct_mask(pvt, 0, csrow) & pvt->dcsm_mask;
+
+	other_bits = pvt->dcsm_mask;
+	other_bits = ~(other_bits << pvt->dcs_shift);
+
+	/*
+	 * The extracted bits from DCSM belong in the spaces represented by
+	 * the cleared bits in other_bits.
+	 */
+	mask = (dcsm_bits << pvt->dcs_shift) | other_bits;
+
+	return mask;
+}
+
+/*
+ * @input_addr is an InputAddr associated with the node given by mci. Return the
+ * csrow that input_addr maps to, or -1 on failure (no csrow claims input_addr).
+ */
+static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr)
+{
+	struct amd64_pvt *pvt;
+	int csrow;
+	u64 base, mask;
+
+	pvt = mci->pvt_info;
+
+	/*
+	 * Here we use the DRAM CS Base and DRAM CS Mask registers. For each CS
+	 * base/mask register pair, test the condition shown near the start of
+	 * section 3.5.4 (p. 84, BKDG #26094, K8, revA-E).
+	 */
+	for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) {
+
+		/* This DRAM chip select is disabled on this node */
+		if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0)
+			continue;
+
+		base = base_from_dct_base(pvt, csrow);
+		mask = ~mask_from_dct_mask(pvt, csrow);
+
+		if ((input_addr & mask) == (base & mask)) {
+			debugf2("InputAddr 0x%lx matches csrow %d (node %d)\n",
+				(unsigned long)input_addr, csrow,
+				pvt->mc_node_id);
+
+			return csrow;
+		}
+	}
+
+	debugf2("no matching csrow for InputAddr 0x%lx (MC node %d)\n",
+		(unsigned long)input_addr, pvt->mc_node_id);
+
+	return -1;
+}
+
+/*
+ * Return the base value defined by the DRAM Base register for the node
+ * represented by mci.  This function returns the full 40-bit value despite the
+ * fact that the register only stores bits 39-24 of the value. See section
+ * 3.4.4.1 (BKDG #26094, K8, revA-E)
+ */
+static inline u64 get_dram_base(struct mem_ctl_info *mci)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	return pvt->dram_base[pvt->mc_node_id];
+}
+
+/*
+ * Obtain info from the DRAM Hole Address Register (section 3.4.8, pub #26094)
+ * for the node represented by mci. Info is passed back in *hole_base,
+ * *hole_offset, and *hole_size.  Function returns 0 if info is valid or 1 if
+ * info is invalid. Info may be invalid for either of the following reasons:
+ *
+ * - The revision of the node is not E or greater.  In this case, the DRAM Hole
+ *   Address Register does not exist.
+ *
+ * - The DramHoleValid bit is cleared in the DRAM Hole Address Register,
+ *   indicating that its contents are not valid.
+ *
+ * The values passed back in *hole_base, *hole_offset, and *hole_size are
+ * complete 32-bit values despite the fact that the bitfields in the DHAR
+ * only represent bits 31-24 of the base and offset values.
+ */
+int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
+			     u64 *hole_offset, u64 *hole_size)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u64 base;
+
+	/* only revE and later have the DRAM Hole Address Register */
+	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_E) {
+		debugf1("  revision %d for node %d does not support DHAR\n",
+			pvt->ext_model, pvt->mc_node_id);
+		return 1;
+	}
+
+	/* only valid for Fam10h */
+	if (boot_cpu_data.x86 == 0x10 &&
+	    (pvt->dhar & F10_DRAM_MEM_HOIST_VALID) == 0) {
+		debugf1("  Dram Memory Hoisting is DISABLED on this system\n");
+		return 1;
+	}
+
+	if ((pvt->dhar & DHAR_VALID) == 0) {
+		debugf1("  Dram Memory Hoisting is DISABLED on this node %d\n",
+			pvt->mc_node_id);
+		return 1;
+	}
+
+	/* This node has Memory Hoisting */
+
+	/* +------------------+--------------------+--------------------+-----
+	 * | memory           | DRAM hole          | relocated          |
+	 * | [0, (x - 1)]     | [x, 0xffffffff]    | addresses from     |
+	 * |                  |                    | DRAM hole          |
+	 * |                  |                    | [0x100000000,      |
+	 * |                  |                    |  (0x100000000+     |
+	 * |                  |                    |   (0xffffffff-x))] |
+	 * +------------------+--------------------+--------------------+-----
+	 *
+	 * Above is a diagram of physical memory showing the DRAM hole and the
+	 * relocated addresses from the DRAM hole.  As shown, the DRAM hole
+	 * starts at address x (the base address) and extends through address
+	 * 0xffffffff.  The DRAM Hole Address Register (DHAR) relocates the
+	 * addresses in the hole so that they start at 0x100000000.
+	 */
+
+	base = dhar_base(pvt->dhar);
+
+	*hole_base = base;
+	*hole_size = (0x1ull << 32) - base;
+
+	if (boot_cpu_data.x86 > 0xf)
+		*hole_offset = f10_dhar_offset(pvt->dhar);
+	else
+		*hole_offset = k8_dhar_offset(pvt->dhar);
+
+	debugf1("  DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n",
+		pvt->mc_node_id, (unsigned long)*hole_base,
+		(unsigned long)*hole_offset, (unsigned long)*hole_size);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(amd64_get_dram_hole_info);
+
+/*
+ * Return the DramAddr that the SysAddr given by @sys_addr maps to.  It is
+ * assumed that sys_addr maps to the node given by mci.
+ *
+ * The first part of section 3.4.4 (p. 70) shows how the DRAM Base (section
+ * 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers are used to translate a
+ * SysAddr to a DramAddr. If the DRAM Hole Address Register (DHAR) is enabled,
+ * then it is also involved in translating a SysAddr to a DramAddr. Sections
+ * 3.4.8 and 3.5.8.2 describe the DHAR and how it is used for memory hoisting.
+ * These parts of the documentation are unclear. I interpret them as follows:
+ *
+ * When node n receives a SysAddr, it processes the SysAddr as follows:
+ *
+ * 1. It extracts the DRAMBase and DRAMLimit values from the DRAM Base and DRAM
+ *    Limit registers for node n. If the SysAddr is not within the range
+ *    specified by the base and limit values, then node n ignores the Sysaddr
+ *    (since it does not map to node n). Otherwise continue to step 2 below.
+ *
+ * 2. If the DramHoleValid bit of the DHAR for node n is clear, the DHAR is
+ *    disabled so skip to step 3 below. Otherwise see if the SysAddr is within
+ *    the range of relocated addresses (starting at 0x100000000) from the DRAM
+ *    hole. If not, skip to step 3 below. Else get the value of the
+ *    DramHoleOffset field from the DHAR. To obtain the DramAddr, subtract the
+ *    offset defined by this value from the SysAddr.
+ *
+ * 3. Obtain the base address for node n from the DRAMBase field of the DRAM
+ *    Base register for node n. To obtain the DramAddr, subtract the base
+ *    address from the SysAddr, as shown near the start of section 3.4.4 (p.70).
+ */
+static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
+{
+	u64 dram_base, hole_base, hole_offset, hole_size, dram_addr;
+	int ret = 0;
+
+	dram_base = get_dram_base(mci);
+
+	ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
+				      &hole_size);
+	if (!ret) {
+		if ((sys_addr >= (1ull << 32)) &&
+		    (sys_addr < ((1ull << 32) + hole_size))) {
+			/* use DHAR to translate SysAddr to DramAddr */
+			dram_addr = sys_addr - hole_offset;
+
+			debugf2("using DHAR to translate SysAddr 0x%lx to "
+				"DramAddr 0x%lx\n",
+				(unsigned long)sys_addr,
+				(unsigned long)dram_addr);
+
+			return dram_addr;
+		}
+	}
+
+	/*
+	 * Translate the SysAddr to a DramAddr as shown near the start of
+	 * section 3.4.4 (p. 70).  Although sys_addr is a 64-bit value, the k8
+	 * only deals with 40-bit values.  Therefore we discard bits 63-40 of
+	 * sys_addr below.  If bit 39 of sys_addr is 1 then the bits we
+	 * discard are all 1s.  Otherwise the bits we discard are all 0s.  See
+	 * section 3.4.2 of AMD publication 24592: AMD x86-64 Architecture
+	 * Programmer's Manual Volume 1 Application Programming.
+	 */
+	dram_addr = (sys_addr & 0xffffffffffull) - dram_base;
+
+	debugf2("using DRAM Base register to translate SysAddr 0x%lx to "
+		"DramAddr 0x%lx\n", (unsigned long)sys_addr,
+		(unsigned long)dram_addr);
+	return dram_addr;
+}
+
+/*
+ * @intlv_en is the value of the IntlvEn field from a DRAM Base register
+ * (section 3.4.4.1).  Return the number of bits from a SysAddr that are used
+ * for node interleaving.
+ */
+static int num_node_interleave_bits(unsigned intlv_en)
+{
+	static const int intlv_shift_table[] = { 0, 1, 0, 2, 0, 0, 0, 3 };
+	int n;
+
+	BUG_ON(intlv_en > 7);
+	n = intlv_shift_table[intlv_en];
+	return n;
+}
+
+/* Translate the DramAddr given by @dram_addr to an InputAddr. */
+static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr)
+{
+	struct amd64_pvt *pvt;
+	int intlv_shift;
+	u64 input_addr;
+
+	pvt = mci->pvt_info;
+
+	/*
+	 * See the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E)
+	 * concerning translating a DramAddr to an InputAddr.
+	 */
+	intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]);
+	input_addr = ((dram_addr >> intlv_shift) & 0xffffff000ull) +
+	    (dram_addr & 0xfff);
+
+	debugf2("  Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n",
+		intlv_shift, (unsigned long)dram_addr,
+		(unsigned long)input_addr);
+
+	return input_addr;
+}
+
+/*
+ * Translate the SysAddr represented by @sys_addr to an InputAddr.  It is
+ * assumed that @sys_addr maps to the node given by mci.
+ */
+static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr)
+{
+	u64 input_addr;
+
+	input_addr =
+	    dram_addr_to_input_addr(mci, sys_addr_to_dram_addr(mci, sys_addr));
+
+	debugf2("SysAdddr 0x%lx translates to InputAddr 0x%lx\n",
+		(unsigned long)sys_addr, (unsigned long)input_addr);
+
+	return input_addr;
+}
+
+
+/*
+ * @input_addr is an InputAddr associated with the node represented by mci.
+ * Translate @input_addr to a DramAddr and return the result.
+ */
+static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
+{
+	struct amd64_pvt *pvt;
+	int node_id, intlv_shift;
+	u64 bits, dram_addr;
+	u32 intlv_sel;
+
+	/*
+	 * Near the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E)
+	 * shows how to translate a DramAddr to an InputAddr. Here we reverse
+	 * this procedure. When translating from a DramAddr to an InputAddr, the
+	 * bits used for node interleaving are discarded.  Here we recover these
+	 * bits from the IntlvSel field of the DRAM Limit register (section
+	 * 3.4.4.2) for the node that input_addr is associated with.
+	 */
+	pvt = mci->pvt_info;
+	node_id = pvt->mc_node_id;
+	BUG_ON((node_id < 0) || (node_id > 7));
+
+	intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]);
+
+	if (intlv_shift == 0) {
+		debugf1("    InputAddr 0x%lx translates to DramAddr of "
+			"same value\n",	(unsigned long)input_addr);
+
+		return input_addr;
+	}
+
+	bits = ((input_addr & 0xffffff000ull) << intlv_shift) +
+	    (input_addr & 0xfff);
+
+	intlv_sel = pvt->dram_IntlvSel[node_id] & ((1 << intlv_shift) - 1);
+	dram_addr = bits + (intlv_sel << 12);
+
+	debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx "
+		"(%d node interleave bits)\n", (unsigned long)input_addr,
+		(unsigned long)dram_addr, intlv_shift);
+
+	return dram_addr;
+}
+
+/*
+ * @dram_addr is a DramAddr that maps to the node represented by mci. Convert
+ * @dram_addr to a SysAddr.
+ */
+static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u64 hole_base, hole_offset, hole_size, base, limit, sys_addr;
+	int ret = 0;
+
+	ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
+				      &hole_size);
+	if (!ret) {
+		if ((dram_addr >= hole_base) &&
+		    (dram_addr < (hole_base + hole_size))) {
+			sys_addr = dram_addr + hole_offset;
+
+			debugf1("using DHAR to translate DramAddr 0x%lx to "
+				"SysAddr 0x%lx\n", (unsigned long)dram_addr,
+				(unsigned long)sys_addr);
+
+			return sys_addr;
+		}
+	}
+
+	amd64_get_base_and_limit(pvt, pvt->mc_node_id, &base, &limit);
+	sys_addr = dram_addr + base;
+
+	/*
+	 * The sys_addr we have computed up to this point is a 40-bit value
+	 * because the k8 deals with 40-bit values.  However, the value we are
+	 * supposed to return is a full 64-bit physical address.  The AMD
+	 * x86-64 architecture specifies that the most significant implemented
+	 * address bit through bit 63 of a physical address must be either all
+	 * 0s or all 1s.  Therefore we sign-extend the 40-bit sys_addr to a
+	 * 64-bit value below.  See section 3.4.2 of AMD publication 24592:
+	 * AMD x86-64 Architecture Programmer's Manual Volume 1 Application
+	 * Programming.
+	 */
+	sys_addr |= ~((sys_addr & (1ull << 39)) - 1);
+
+	debugf1("    Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n",
+		pvt->mc_node_id, (unsigned long)dram_addr,
+		(unsigned long)sys_addr);
+
+	return sys_addr;
+}
+
+/*
+ * @input_addr is an InputAddr associated with the node given by mci. Translate
+ * @input_addr to a SysAddr.
+ */
+static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci,
+					 u64 input_addr)
+{
+	return dram_addr_to_sys_addr(mci,
+				     input_addr_to_dram_addr(mci, input_addr));
+}
+
+/*
+ * Find the minimum and maximum InputAddr values that map to the given @csrow.
+ * Pass back these values in *input_addr_min and *input_addr_max.
+ */
+static void find_csrow_limits(struct mem_ctl_info *mci, int csrow,
+			      u64 *input_addr_min, u64 *input_addr_max)
+{
+	struct amd64_pvt *pvt;
+	u64 base, mask;
+
+	pvt = mci->pvt_info;
+	BUG_ON((csrow < 0) || (csrow >= CHIPSELECT_COUNT));
+
+	base = base_from_dct_base(pvt, csrow);
+	mask = mask_from_dct_mask(pvt, csrow);
+
+	*input_addr_min = base & ~mask;
+	*input_addr_max = base | mask | pvt->dcs_mask_notused;
+}
+
+/*
+ * Extract error address from MCA NB Address Low (section 3.6.4.5) and MCA NB
+ * Address High (section 3.6.4.6) register values and return the result. Address
+ * is located in the info structure (nbeah and nbeal), the encoding is device
+ * specific.
+ */
+static u64 extract_error_address(struct mem_ctl_info *mci,
+				 struct amd64_error_info_regs *info)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	return pvt->ops->get_error_address(mci, info);
+}
+
+
+/* Map the Error address to a PAGE and PAGE OFFSET. */
+static inline void error_address_to_page_and_offset(u64 error_address,
+						    u32 *page, u32 *offset)
+{
+	*page = (u32) (error_address >> PAGE_SHIFT);
+	*offset = ((u32) error_address) & ~PAGE_MASK;
+}
+
+/*
+ * @sys_addr is an error address (a SysAddr) extracted from the MCA NB Address
+ * Low (section 3.6.4.5) and MCA NB Address High (section 3.6.4.6) registers
+ * of a node that detected an ECC memory error.  mci represents the node that
+ * the error address maps to (possibly different from the node that detected
+ * the error).  Return the number of the csrow that sys_addr maps to, or -1 on
+ * error.
+ */
+static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr)
+{
+	int csrow;
+
+	csrow = input_addr_to_csrow(mci, sys_addr_to_input_addr(mci, sys_addr));
+
+	if (csrow == -1)
+		amd64_mc_printk(mci, KERN_ERR,
+			     "Failed to translate InputAddr to csrow for "
+			     "address 0x%lx\n", (unsigned long)sys_addr);
+	return csrow;
+}
+
+static int get_channel_from_ecc_syndrome(unsigned short syndrome);
+
+static void amd64_cpu_display_info(struct amd64_pvt *pvt)
+{
+	if (boot_cpu_data.x86 == 0x11)
+		edac_printk(KERN_DEBUG, EDAC_MC, "F11h CPU detected\n");
+	else if (boot_cpu_data.x86 == 0x10)
+		edac_printk(KERN_DEBUG, EDAC_MC, "F10h CPU detected\n");
+	else if (boot_cpu_data.x86 == 0xf)
+		edac_printk(KERN_DEBUG, EDAC_MC, "%s detected\n",
+			(pvt->ext_model >= OPTERON_CPU_REV_F) ?
+			"Rev F or later" : "Rev E or earlier");
+	else
+		/* we'll hardly ever ever get here */
+		edac_printk(KERN_ERR, EDAC_MC, "Unknown cpu!\n");
+}
+
+/*
+ * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
+ * are ECC capable.
+ */
+static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt)
+{
+	int bit;
+	enum dev_type edac_cap = EDAC_FLAG_NONE;
+
+	bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F)
+		? 19
+		: 17;
+
+	if (pvt->dclr0 & BIT(bit))
+		edac_cap = EDAC_FLAG_SECDED;
+
+	return edac_cap;
+}
+
+
+static void f10_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt,
+					 int ganged);
+
+/* Display and decode various NB registers for debug purposes. */
+static void amd64_dump_misc_regs(struct amd64_pvt *pvt)
+{
+	int ganged;
+
+	debugf1("  nbcap:0x%8.08x DctDualCap=%s DualNode=%s 8-Node=%s\n",
+		pvt->nbcap,
+		(pvt->nbcap & K8_NBCAP_DCT_DUAL) ? "True" : "False",
+		(pvt->nbcap & K8_NBCAP_DUAL_NODE) ? "True" : "False",
+		(pvt->nbcap & K8_NBCAP_8_NODE) ? "True" : "False");
+	debugf1("    ECC Capable=%s   ChipKill Capable=%s\n",
+		(pvt->nbcap & K8_NBCAP_SECDED) ? "True" : "False",
+		(pvt->nbcap & K8_NBCAP_CHIPKILL) ? "True" : "False");
+	debugf1("  DramCfg0-low=0x%08x DIMM-ECC=%s Parity=%s Width=%s\n",
+		pvt->dclr0,
+		(pvt->dclr0 & BIT(19)) ?  "Enabled" : "Disabled",
+		(pvt->dclr0 & BIT(8)) ?  "Enabled" : "Disabled",
+		(pvt->dclr0 & BIT(11)) ?  "128b" : "64b");
+	debugf1("    DIMM x4 Present: L0=%s L1=%s L2=%s L3=%s  DIMM Type=%s\n",
+		(pvt->dclr0 & BIT(12)) ?  "Y" : "N",
+		(pvt->dclr0 & BIT(13)) ?  "Y" : "N",
+		(pvt->dclr0 & BIT(14)) ?  "Y" : "N",
+		(pvt->dclr0 & BIT(15)) ?  "Y" : "N",
+		(pvt->dclr0 & BIT(16)) ?  "UN-Buffered" : "Buffered");
+
+
+	debugf1("  online-spare: 0x%8.08x\n", pvt->online_spare);
+
+	if (boot_cpu_data.x86 == 0xf) {
+		debugf1("  dhar: 0x%8.08x Base=0x%08x Offset=0x%08x\n",
+			pvt->dhar, dhar_base(pvt->dhar),
+			k8_dhar_offset(pvt->dhar));
+		debugf1("      DramHoleValid=%s\n",
+			(pvt->dhar & DHAR_VALID) ?  "True" : "False");
+
+		debugf1("  dbam-dkt: 0x%8.08x\n", pvt->dbam0);
+
+		/* everything below this point is Fam10h and above */
+		return;
+
+	} else {
+		debugf1("  dhar: 0x%8.08x Base=0x%08x Offset=0x%08x\n",
+			pvt->dhar, dhar_base(pvt->dhar),
+			f10_dhar_offset(pvt->dhar));
+		debugf1("    DramMemHoistValid=%s DramHoleValid=%s\n",
+			(pvt->dhar & F10_DRAM_MEM_HOIST_VALID) ?
+			"True" : "False",
+			(pvt->dhar & DHAR_VALID) ?
+			"True" : "False");
+	}
+
+	/* Only if NOT ganged does dcl1 have valid info */
+	if (!dct_ganging_enabled(pvt)) {
+		debugf1("  DramCfg1-low=0x%08x DIMM-ECC=%s Parity=%s "
+			"Width=%s\n", pvt->dclr1,
+			(pvt->dclr1 & BIT(19)) ?  "Enabled" : "Disabled",
+			(pvt->dclr1 & BIT(8)) ?  "Enabled" : "Disabled",
+			(pvt->dclr1 & BIT(11)) ?  "128b" : "64b");
+		debugf1("    DIMM x4 Present: L0=%s L1=%s L2=%s L3=%s  "
+			"DIMM Type=%s\n",
+			(pvt->dclr1 & BIT(12)) ?  "Y" : "N",
+			(pvt->dclr1 & BIT(13)) ?  "Y" : "N",
+			(pvt->dclr1 & BIT(14)) ?  "Y" : "N",
+			(pvt->dclr1 & BIT(15)) ?  "Y" : "N",
+			(pvt->dclr1 & BIT(16)) ?  "UN-Buffered" : "Buffered");
+	}
+
+	/*
+	 * Determine if ganged and then dump memory sizes for first controller,
+	 * and if NOT ganged dump info for 2nd controller.
+	 */
+	ganged = dct_ganging_enabled(pvt);
+
+	f10_debug_display_dimm_sizes(0, pvt, ganged);
+
+	if (!ganged)
+		f10_debug_display_dimm_sizes(1, pvt, ganged);
+}
+
+/* Read in both of DBAM registers */
+static void amd64_read_dbam_reg(struct amd64_pvt *pvt)
+{
+	int err = 0;
+	unsigned int reg;
+
+	reg = DBAM0;
+	err = pci_read_config_dword(pvt->dram_f2_ctl, reg, &pvt->dbam0);
+	if (err)
+		goto err_reg;
+
+	if (boot_cpu_data.x86 >= 0x10) {
+		reg = DBAM1;
+		err = pci_read_config_dword(pvt->dram_f2_ctl, reg, &pvt->dbam1);
+
+		if (err)
+			goto err_reg;
+	}
+
+	return;
+
+err_reg:
+	debugf0("Error reading F2x%03x.\n", reg);
+}
+
+/*
+ * NOTE: CPU Revision Dependent code: Rev E and Rev F
+ *
+ * Set the DCSB and DCSM mask values depending on the CPU revision value. Also
+ * set the shift factor for the DCSB and DCSM values.
+ *
+ * ->dcs_mask_notused, RevE:
+ *
+ * To find the max InputAddr for the csrow, start with the base address and set
+ * all bits that are "don't care" bits in the test at the start of section
+ * 3.5.4 (p. 84).
+ *
+ * The "don't care" bits are all set bits in the mask and all bits in the gaps
+ * between bit ranges [35:25] and [19:13]. The value REV_E_DCS_NOTUSED_BITS
+ * represents bits [24:20] and [12:0], which are all bits in the above-mentioned
+ * gaps.
+ *
+ * ->dcs_mask_notused, RevF and later:
+ *
+ * To find the max InputAddr for the csrow, start with the base address and set
+ * all bits that are "don't care" bits in the test at the start of NPT section
+ * 4.5.4 (p. 87).
+ *
+ * The "don't care" bits are all set bits in the mask and all bits in the gaps
+ * between bit ranges [36:27] and [21:13].
+ *
+ * The value REV_F_F1Xh_DCS_NOTUSED_BITS represents bits [26:22] and [12:0],
+ * which are all bits in the above-mentioned gaps.
+ */
+static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt)
+{
+	if (pvt->ext_model >= OPTERON_CPU_REV_F) {
+		pvt->dcsb_base		= REV_F_F1Xh_DCSB_BASE_BITS;
+		pvt->dcsm_mask		= REV_F_F1Xh_DCSM_MASK_BITS;
+		pvt->dcs_mask_notused	= REV_F_F1Xh_DCS_NOTUSED_BITS;
+		pvt->dcs_shift		= REV_F_F1Xh_DCS_SHIFT;
+
+		switch (boot_cpu_data.x86) {
+		case 0xf:
+			pvt->num_dcsm = REV_F_DCSM_COUNT;
+			break;
+
+		case 0x10:
+			pvt->num_dcsm = F10_DCSM_COUNT;
+			break;
+
+		case 0x11:
+			pvt->num_dcsm = F11_DCSM_COUNT;
+			break;
+
+		default:
+			amd64_printk(KERN_ERR, "Unsupported family!\n");
+			break;
+		}
+	} else {
+		pvt->dcsb_base		= REV_E_DCSB_BASE_BITS;
+		pvt->dcsm_mask		= REV_E_DCSM_MASK_BITS;
+		pvt->dcs_mask_notused	= REV_E_DCS_NOTUSED_BITS;
+		pvt->dcs_shift		= REV_E_DCS_SHIFT;
+		pvt->num_dcsm		= REV_E_DCSM_COUNT;
+	}
+}
+
+/*
+ * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask hw registers
+ */
+static void amd64_read_dct_base_mask(struct amd64_pvt *pvt)
+{
+	int cs, reg, err = 0;
+
+	amd64_set_dct_base_and_mask(pvt);
+
+	for (cs = 0; cs < CHIPSELECT_COUNT; cs++) {
+		reg = K8_DCSB0 + (cs * 4);
+		err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
+						&pvt->dcsb0[cs]);
+		if (unlikely(err))
+			debugf0("Reading K8_DCSB0[%d] failed\n", cs);
+		else
+			debugf0("  DCSB0[%d]=0x%08x reg: F2x%x\n",
+				cs, pvt->dcsb0[cs], reg);
+
+		/* If DCT are NOT ganged, then read in DCT1's base */
+		if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
+			reg = F10_DCSB1 + (cs * 4);
+			err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
+							&pvt->dcsb1[cs]);
+			if (unlikely(err))
+				debugf0("Reading F10_DCSB1[%d] failed\n", cs);
+			else
+				debugf0("  DCSB1[%d]=0x%08x reg: F2x%x\n",
+					cs, pvt->dcsb1[cs], reg);
+		} else {
+			pvt->dcsb1[cs] = 0;
+		}
+	}
+
+	for (cs = 0; cs < pvt->num_dcsm; cs++) {
+		reg = K8_DCSM0 + (cs * 4);
+		err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
+					&pvt->dcsm0[cs]);
+		if (unlikely(err))
+			debugf0("Reading K8_DCSM0 failed\n");
+		else
+			debugf0("    DCSM0[%d]=0x%08x reg: F2x%x\n",
+				cs, pvt->dcsm0[cs], reg);
+
+		/* If DCT are NOT ganged, then read in DCT1's mask */
+		if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
+			reg = F10_DCSM1 + (cs * 4);
+			err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
+					&pvt->dcsm1[cs]);
+			if (unlikely(err))
+				debugf0("Reading F10_DCSM1[%d] failed\n", cs);
+			else
+				debugf0("    DCSM1[%d]=0x%08x reg: F2x%x\n",
+					cs, pvt->dcsm1[cs], reg);
+		} else
+			pvt->dcsm1[cs] = 0;
+	}
+}
+
+static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt)
+{
+	enum mem_type type;
+
+	if (boot_cpu_data.x86 >= 0x10 || pvt->ext_model >= OPTERON_CPU_REV_F) {
+		/* Rev F and later */
+		type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2;
+	} else {
+		/* Rev E and earlier */
+		type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR;
+	}
+
+	debugf1("  Memory type is: %s\n",
+		(type == MEM_DDR2) ? "MEM_DDR2" :
+		(type == MEM_RDDR2) ? "MEM_RDDR2" :
+		(type == MEM_DDR) ? "MEM_DDR" : "MEM_RDDR");
+
+	return type;
+}
+
+/*
+ * Read the DRAM Configuration Low register. It differs between CG, D & E revs
+ * and the later RevF memory controllers (DDR vs DDR2)
+ *
+ * Return:
+ *      number of memory channels in operation
+ * Pass back:
+ *      contents of the DCL0_LOW register
+ */
+static int k8_early_channel_count(struct amd64_pvt *pvt)
+{
+	int flag, err = 0;
+
+	err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0);
+	if (err)
+		return err;
+
+	if ((boot_cpu_data.x86_model >> 4) >= OPTERON_CPU_REV_F) {
+		/* RevF (NPT) and later */
+		flag = pvt->dclr0 & F10_WIDTH_128;
+	} else {
+		/* RevE and earlier */
+		flag = pvt->dclr0 & REVE_WIDTH_128;
+	}
+
+	/* not used */
+	pvt->dclr1 = 0;
+
+	return (flag) ? 2 : 1;
+}
+
+/* extract the ERROR ADDRESS for the K8 CPUs */
+static u64 k8_get_error_address(struct mem_ctl_info *mci,
+				struct amd64_error_info_regs *info)
+{
+	return (((u64) (info->nbeah & 0xff)) << 32) +
+			(info->nbeal & ~0x03);
+}
+
+/*
+ * Read the Base and Limit registers for K8 based Memory controllers; extract
+ * fields from the 'raw' reg into separate data fields
+ *
+ * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN
+ */
+static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
+{
+	u32 low;
+	u32 off = dram << 3;	/* 8 bytes between DRAM entries */
+	int err;
+
+	err = pci_read_config_dword(pvt->addr_f1_ctl,
+				    K8_DRAM_BASE_LOW + off, &low);
+	if (err)
+		debugf0("Reading K8_DRAM_BASE_LOW failed\n");
+
+	/* Extract parts into separate data entries */
+	pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8;
+	pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7;
+	pvt->dram_rw_en[dram] = (low & 0x3);
+
+	err = pci_read_config_dword(pvt->addr_f1_ctl,
+				    K8_DRAM_LIMIT_LOW + off, &low);
+	if (err)
+		debugf0("Reading K8_DRAM_LIMIT_LOW failed\n");
+
+	/*
+	 * Extract parts into separate data entries. Limit is the HIGHEST memory
+	 * location of the region, so lower 24 bits need to be all ones
+	 */
+	pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 8) | 0x00FFFFFF;
+	pvt->dram_IntlvSel[dram] = (low >> 8) & 0x7;
+	pvt->dram_DstNode[dram] = (low & 0x7);
+}
+
+static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
+					struct amd64_error_info_regs *info,
+					u64 SystemAddress)
+{
+	struct mem_ctl_info *src_mci;
+	unsigned short syndrome;
+	int channel, csrow;
+	u32 page, offset;
+
+	/* Extract the syndrome parts and form a 16-bit syndrome */
+	syndrome = EXTRACT_HIGH_SYNDROME(info->nbsl) << 8;
+	syndrome |= EXTRACT_LOW_SYNDROME(info->nbsh);
+
+	/* CHIPKILL enabled */
+	if (info->nbcfg & K8_NBCFG_CHIPKILL) {
+		channel = get_channel_from_ecc_syndrome(syndrome);
+		if (channel < 0) {
+			/*
+			 * Syndrome didn't map, so we don't know which of the
+			 * 2 DIMMs is in error. So we need to ID 'both' of them
+			 * as suspect.
+			 */
+			amd64_mc_printk(mci, KERN_WARNING,
+				       "unknown syndrome 0x%x - possible error "
+				       "reporting race\n", syndrome);
+			edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
+			return;
+		}
+	} else {
+		/*
+		 * non-chipkill ecc mode
+		 *
+		 * The k8 documentation is unclear about how to determine the
+		 * channel number when using non-chipkill memory.  This method
+		 * was obtained from email communication with someone at AMD.
+		 * (Wish the email was placed in this comment - norsk)
+		 */
+		channel = ((SystemAddress & BIT(3)) != 0);
+	}
+
+	/*
+	 * Find out which node the error address belongs to. This may be
+	 * different from the node that detected the error.
+	 */
+	src_mci = find_mc_by_sys_addr(mci, SystemAddress);
+	if (src_mci) {
+		amd64_mc_printk(mci, KERN_ERR,
+			     "failed to map error address 0x%lx to a node\n",
+			     (unsigned long)SystemAddress);
+		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
+		return;
+	}
+
+	/* Now map the SystemAddress to a CSROW */
+	csrow = sys_addr_to_csrow(src_mci, SystemAddress);
+	if (csrow < 0) {
+		edac_mc_handle_ce_no_info(src_mci, EDAC_MOD_STR);
+	} else {
+		error_address_to_page_and_offset(SystemAddress, &page, &offset);
+
+		edac_mc_handle_ce(src_mci, page, offset, syndrome, csrow,
+				  channel, EDAC_MOD_STR);
+	}
+}
+
+/*
+ * determrine the number of PAGES in for this DIMM's size based on its DRAM
+ * Address Mapping.
+ *
+ * First step is to calc the number of bits to shift a value of 1 left to
+ * indicate show many pages. Start with the DBAM value as the starting bits,
+ * then proceed to adjust those shift bits, based on CPU rev and the table.
+ * See BKDG on the DBAM
+ */
+static int k8_dbam_map_to_pages(struct amd64_pvt *pvt, int dram_map)
+{
+	int nr_pages;
+
+	if (pvt->ext_model >= OPTERON_CPU_REV_F) {
+		nr_pages = 1 << (revf_quad_ddr2_shift[dram_map] - PAGE_SHIFT);
+	} else {
+		/*
+		 * RevE and less section; this line is tricky. It collapses the
+		 * table used by RevD and later to one that matches revisions CG
+		 * and earlier.
+		 */
+		dram_map -= (pvt->ext_model >= OPTERON_CPU_REV_D) ?
+				(dram_map > 8 ? 4 : (dram_map > 5 ?
+				3 : (dram_map > 2 ? 1 : 0))) : 0;
+
+		/* 25 shift is 32MiB minimum DIMM size in RevE and prior */
+		nr_pages = 1 << (dram_map + 25 - PAGE_SHIFT);
+	}
+
+	return nr_pages;
+}
+
+/*
+ * Get the number of DCT channels in use.
+ *
+ * Return:
+ *	number of Memory Channels in operation
+ * Pass back:
+ *	contents of the DCL0_LOW register
+ */
+static int f10_early_channel_count(struct amd64_pvt *pvt)
+{
+	int err = 0, channels = 0;
+	u32 dbam;
+
+	err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0);
+	if (err)
+		goto err_reg;
+
+	err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1);
+	if (err)
+		goto err_reg;
+
+	/* If we are in 128 bit mode, then we are using 2 channels */
+	if (pvt->dclr0 & F10_WIDTH_128) {
+		debugf0("Data WIDTH is 128 bits - 2 channels\n");
+		channels = 2;
+		return channels;
+	}
+
+	/*
+	 * Need to check if in UN-ganged mode: In such, there are 2 channels,
+	 * but they are NOT in 128 bit mode and thus the above 'dcl0' status bit
+	 * will be OFF.
+	 *
+	 * Need to check DCT0[0] and DCT1[0] to see if only one of them has
+	 * their CSEnable bit on. If so, then SINGLE DIMM case.
+	 */
+	debugf0("Data WIDTH is NOT 128 bits - need more decoding\n");
+
+	/*
+	 * Check DRAM Bank Address Mapping values for each DIMM to see if there
+	 * is more than just one DIMM present in unganged mode. Need to check
+	 * both controllers since DIMMs can be placed in either one.
+	 */
+	channels = 0;
+	err = pci_read_config_dword(pvt->dram_f2_ctl, DBAM0, &dbam);
+	if (err)
+		goto err_reg;
+
+	if (DBAM_DIMM(0, dbam) > 0)
+		channels++;
+	if (DBAM_DIMM(1, dbam) > 0)
+		channels++;
+	if (DBAM_DIMM(2, dbam) > 0)
+		channels++;
+	if (DBAM_DIMM(3, dbam) > 0)
+		channels++;
+
+	/* If more than 2 DIMMs are present, then we have 2 channels */
+	if (channels > 2)
+		channels = 2;
+	else if (channels == 0) {
+		/* No DIMMs on DCT0, so look at DCT1 */
+		err = pci_read_config_dword(pvt->dram_f2_ctl, DBAM1, &dbam);
+		if (err)
+			goto err_reg;
+
+		if (DBAM_DIMM(0, dbam) > 0)
+			channels++;
+		if (DBAM_DIMM(1, dbam) > 0)
+			channels++;
+		if (DBAM_DIMM(2, dbam) > 0)
+			channels++;
+		if (DBAM_DIMM(3, dbam) > 0)
+			channels++;
+
+		if (channels > 2)
+			channels = 2;
+	}
+
+	/* If we found ALL 0 values, then assume just ONE DIMM-ONE Channel */
+	if (channels == 0)
+		channels = 1;
+
+	debugf0("MCT channel count: %d\n", channels);
+
+	return channels;
+
+err_reg:
+	return -1;
+
+}
+
+static int f10_dbam_map_to_pages(struct amd64_pvt *pvt, int dram_map)
+{
+	return 1 << (revf_quad_ddr2_shift[dram_map] - PAGE_SHIFT);
+}
+
+/* Enable extended configuration access via 0xCF8 feature */
+static void amd64_setup(struct amd64_pvt *pvt)
+{
+	u32 reg;
+
+	pci_read_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, &reg);
+
+	pvt->flags.cf8_extcfg = !!(reg & F10_NB_CFG_LOW_ENABLE_EXT_CFG);
+	reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG;
+	pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg);
+}
+
+/* Restore the extended configuration access via 0xCF8 feature */
+static void amd64_teardown(struct amd64_pvt *pvt)
+{
+	u32 reg;
+
+	pci_read_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, &reg);
+
+	reg &= ~F10_NB_CFG_LOW_ENABLE_EXT_CFG;
+	if (pvt->flags.cf8_extcfg)
+		reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG;
+	pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg);
+}
+
+static u64 f10_get_error_address(struct mem_ctl_info *mci,
+			struct amd64_error_info_regs *info)
+{
+	return (((u64) (info->nbeah & 0xffff)) << 32) +
+			(info->nbeal & ~0x01);
+}
+
+/*
+ * Read the Base and Limit registers for F10 based Memory controllers. Extract
+ * fields from the 'raw' reg into separate data fields.
+ *
+ * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN.
+ */
+static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
+{
+	u32 high_offset, low_offset, high_base, low_base, high_limit, low_limit;
+
+	low_offset = K8_DRAM_BASE_LOW + (dram << 3);
+	high_offset = F10_DRAM_BASE_HIGH + (dram << 3);
+
+	/* read the 'raw' DRAM BASE Address register */
+	pci_read_config_dword(pvt->addr_f1_ctl, low_offset, &low_base);
+
+	/* Read from the ECS data register */
+	pci_read_config_dword(pvt->addr_f1_ctl, high_offset, &high_base);
+
+	/* Extract parts into separate data entries */
+	pvt->dram_rw_en[dram] = (low_base & 0x3);
+
+	if (pvt->dram_rw_en[dram] == 0)
+		return;
+
+	pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7;
+
+	pvt->dram_base[dram] = (((((u64) high_base & 0x000000FF) << 32) |
+				((u64) low_base & 0xFFFF0000))) << 8;
+
+	low_offset = K8_DRAM_LIMIT_LOW + (dram << 3);
+	high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3);
+
+	/* read the 'raw' LIMIT registers */
+	pci_read_config_dword(pvt->addr_f1_ctl, low_offset, &low_limit);
+
+	/* Read from the ECS data register for the HIGH portion */
+	pci_read_config_dword(pvt->addr_f1_ctl, high_offset, &high_limit);
+
+	debugf0("  HW Regs: BASE=0x%08x-%08x      LIMIT=  0x%08x-%08x\n",
+		high_base, low_base, high_limit, low_limit);
+
+	pvt->dram_DstNode[dram] = (low_limit & 0x7);
+	pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7;
+
+	/*
+	 * Extract address values and form a LIMIT address. Limit is the HIGHEST
+	 * memory location of the region, so low 24 bits need to be all ones.
+	 */
+	low_limit |= 0x0000FFFF;
+	pvt->dram_limit[dram] =
+		((((u64) high_limit << 32) + (u64) low_limit) << 8) | (0xFF);
+}
+
+static void f10_read_dram_ctl_register(struct amd64_pvt *pvt)
+{
+	int err = 0;
+
+	err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCTL_SEL_LOW,
+				    &pvt->dram_ctl_select_low);
+	if (err) {
+		debugf0("Reading F10_DCTL_SEL_LOW failed\n");
+	} else {
+		debugf0("DRAM_DCTL_SEL_LOW=0x%x  DctSelBaseAddr=0x%x\n",
+			pvt->dram_ctl_select_low, dct_sel_baseaddr(pvt));
+
+		debugf0("  DRAM DCTs are=%s DRAM Is=%s DRAM-Ctl-"
+				"sel-hi-range=%s\n",
+			(dct_ganging_enabled(pvt) ? "GANGED" : "NOT GANGED"),
+			(dct_dram_enabled(pvt) ? "Enabled"   : "Disabled"),
+			(dct_high_range_enabled(pvt) ? "Enabled" : "Disabled"));
+
+		debugf0("  DctDatIntLv=%s MemCleared=%s DctSelIntLvAddr=0x%x\n",
+			(dct_data_intlv_enabled(pvt) ? "Enabled" : "Disabled"),
+			(dct_memory_cleared(pvt) ? "True " : "False "),
+			dct_sel_interleave_addr(pvt));
+	}
+
+	err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCTL_SEL_HIGH,
+				    &pvt->dram_ctl_select_high);
+	if (err)
+		debugf0("Reading F10_DCTL_SEL_HIGH failed\n");
+}
+
+/*
+ * determine channel based on the interleaving mode: F10h BKDG, 2.8.9 Memory
+ * Interleaving Modes.
+ */
+static u32 f10_determine_channel(struct amd64_pvt *pvt, u64 sys_addr,
+				int hi_range_sel, u32 intlv_en)
+{
+	u32 cs, temp, dct_sel_high = (pvt->dram_ctl_select_low >> 1) & 1;
+
+	if (dct_ganging_enabled(pvt))
+		cs = 0;
+	else if (hi_range_sel)
+		cs = dct_sel_high;
+	else if (dct_interleave_enabled(pvt)) {
+		/*
+		 * see F2x110[DctSelIntLvAddr] - channel interleave mode
+		 */
+		if (dct_sel_interleave_addr(pvt) == 0)
+			cs = sys_addr >> 6 & 1;
+		else if ((dct_sel_interleave_addr(pvt) >> 1) & 1) {
+			temp = hweight_long((u32) ((sys_addr >> 16) & 0x1F)) % 2;
+
+			if (dct_sel_interleave_addr(pvt) & 1)
+				cs = (sys_addr >> 9 & 1) ^ temp;
+			else
+				cs = (sys_addr >> 6 & 1) ^ temp;
+		} else if (intlv_en & 4)
+			cs = sys_addr >> 15 & 1;
+		else if (intlv_en & 2)
+			cs = sys_addr >> 14 & 1;
+		else if (intlv_en & 1)
+			cs = sys_addr >> 13 & 1;
+		else
+			cs = sys_addr >> 12 & 1;
+	} else if (dct_high_range_enabled(pvt) && !dct_ganging_enabled(pvt))
+		cs = ~dct_sel_high & 1;
+	else
+		cs = 0;
+
+	return cs;
+}
+
+static inline u32 f10_map_intlv_en_to_shift(u32 intlv_en)
+{
+	if (intlv_en == 1)
+		return 1;
+	else if (intlv_en == 3)
+		return 2;
+	else if (intlv_en == 7)
+		return 3;
+
+	return 0;
+}
+
+/* See F10h BKDG, 2.8.10.2 DctSelBaseOffset Programming */
+static inline u64 f10_get_base_addr_offset(u64 sys_addr, int hi_range_sel,
+						 u32 dct_sel_base_addr,
+						 u64 dct_sel_base_off,
+						 u32 hole_valid, u32 hole_off,
+						 u64 dram_base)
+{
+	u64 chan_off;
+
+	if (hi_range_sel) {
+		if (!(dct_sel_base_addr & 0xFFFFF800) &&
+		   hole_valid && (sys_addr >= 0x100000000ULL))
+			chan_off = hole_off << 16;
+		else
+			chan_off = dct_sel_base_off;
+	} else {
+		if (hole_valid && (sys_addr >= 0x100000000ULL))
+			chan_off = hole_off << 16;
+		else
+			chan_off = dram_base & 0xFFFFF8000000ULL;
+	}
+
+	return (sys_addr & 0x0000FFFFFFFFFFC0ULL) -
+			(chan_off & 0x0000FFFFFF800000ULL);
+}
+
+/* Hack for the time being - Can we get this from BIOS?? */
+#define	CH0SPARE_RANK	0
+#define	CH1SPARE_RANK	1
+
+/*
+ * checks if the csrow passed in is marked as SPARED, if so returns the new
+ * spare row
+ */
+static inline int f10_process_possible_spare(int csrow,
+				u32 cs, struct amd64_pvt *pvt)
+{
+	u32 swap_done;
+	u32 bad_dram_cs;
+
+	/* Depending on channel, isolate respective SPARING info */
+	if (cs) {
+		swap_done = F10_ONLINE_SPARE_SWAPDONE1(pvt->online_spare);
+		bad_dram_cs = F10_ONLINE_SPARE_BADDRAM_CS1(pvt->online_spare);
+		if (swap_done && (csrow == bad_dram_cs))
+			csrow = CH1SPARE_RANK;
+	} else {
+		swap_done = F10_ONLINE_SPARE_SWAPDONE0(pvt->online_spare);
+		bad_dram_cs = F10_ONLINE_SPARE_BADDRAM_CS0(pvt->online_spare);
+		if (swap_done && (csrow == bad_dram_cs))
+			csrow = CH0SPARE_RANK;
+	}
+	return csrow;
+}
+
+/*
+ * Iterate over the DRAM DCT "base" and "mask" registers looking for a
+ * SystemAddr match on the specified 'ChannelSelect' and 'NodeID'
+ *
+ * Return:
+ *	-EINVAL:  NOT FOUND
+ *	0..csrow = Chip-Select Row
+ */
+static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs)
+{
+	struct mem_ctl_info *mci;
+	struct amd64_pvt *pvt;
+	u32 cs_base, cs_mask;
+	int cs_found = -EINVAL;
+	int csrow;
+
+	mci = mci_lookup[nid];
+	if (!mci)
+		return cs_found;
+
+	pvt = mci->pvt_info;
+
+	debugf1("InputAddr=0x%x  channelselect=%d\n", in_addr, cs);
+
+	for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) {
+
+		cs_base = amd64_get_dct_base(pvt, cs, csrow);
+		if (!(cs_base & K8_DCSB_CS_ENABLE))
+			continue;
+
+		/*
+		 * We have an ENABLED CSROW, Isolate just the MASK bits of the
+		 * target: [28:19] and [13:5], which map to [36:27] and [21:13]
+		 * of the actual address.
+		 */
+		cs_base &= REV_F_F1Xh_DCSB_BASE_BITS;
+
+		/*
+		 * Get the DCT Mask, and ENABLE the reserved bits: [18:16] and
+		 * [4:0] to become ON. Then mask off bits [28:0] ([36:8])
+		 */
+		cs_mask = amd64_get_dct_mask(pvt, cs, csrow);
+
+		debugf1("    CSROW=%d CSBase=0x%x RAW CSMask=0x%x\n",
+				csrow, cs_base, cs_mask);
+
+		cs_mask = (cs_mask | 0x0007C01F) & 0x1FFFFFFF;
+
+		debugf1("              Final CSMask=0x%x\n", cs_mask);
+		debugf1("    (InputAddr & ~CSMask)=0x%x "
+				"(CSBase & ~CSMask)=0x%x\n",
+				(in_addr & ~cs_mask), (cs_base & ~cs_mask));
+
+		if ((in_addr & ~cs_mask) == (cs_base & ~cs_mask)) {
+			cs_found = f10_process_possible_spare(csrow, cs, pvt);
+
+			debugf1(" MATCH csrow=%d\n", cs_found);
+			break;
+		}
+	}
+	return cs_found;
+}
+
+/* For a given @dram_range, check if @sys_addr falls within it. */
+static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
+				  u64 sys_addr, int *nid, int *chan_sel)
+{
+	int node_id, cs_found = -EINVAL, high_range = 0;
+	u32 intlv_en, intlv_sel, intlv_shift, hole_off;
+	u32 hole_valid, tmp, dct_sel_base, channel;
+	u64 dram_base, chan_addr, dct_sel_base_off;
+
+	dram_base = pvt->dram_base[dram_range];
+	intlv_en = pvt->dram_IntlvEn[dram_range];
+
+	node_id = pvt->dram_DstNode[dram_range];
+	intlv_sel = pvt->dram_IntlvSel[dram_range];
+
+	debugf1("(dram=%d) Base=0x%llx SystemAddr= 0x%llx Limit=0x%llx\n",
+		dram_range, dram_base, sys_addr, pvt->dram_limit[dram_range]);
+
+	/*
+	 * This assumes that one node's DHAR is the same as all the other
+	 * nodes' DHAR.
+	 */
+	hole_off = (pvt->dhar & 0x0000FF80);
+	hole_valid = (pvt->dhar & 0x1);
+	dct_sel_base_off = (pvt->dram_ctl_select_high & 0xFFFFFC00) << 16;
+
+	debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
+			hole_off, hole_valid, intlv_sel);
+
+	if (intlv_en ||
+	    (intlv_sel != ((sys_addr >> 12) & intlv_en)))
+		return -EINVAL;
+
+	dct_sel_base = dct_sel_baseaddr(pvt);
+
+	/*
+	 * check whether addresses >= DctSelBaseAddr[47:27] are to be used to
+	 * select between DCT0 and DCT1.
+	 */
+	if (dct_high_range_enabled(pvt) &&
+	   !dct_ganging_enabled(pvt) &&
+	   ((sys_addr >> 27) >= (dct_sel_base >> 11)))
+		high_range = 1;
+
+	channel = f10_determine_channel(pvt, sys_addr, high_range, intlv_en);
+
+	chan_addr = f10_get_base_addr_offset(sys_addr, high_range, dct_sel_base,
+					     dct_sel_base_off, hole_valid,
+					     hole_off, dram_base);
+
+	intlv_shift = f10_map_intlv_en_to_shift(intlv_en);
+
+	/* remove Node ID (in case of memory interleaving) */
+	tmp = chan_addr & 0xFC0;
+
+	chan_addr = ((chan_addr >> intlv_shift) & 0xFFFFFFFFF000ULL) | tmp;
+
+	/* remove channel interleave and hash */
+	if (dct_interleave_enabled(pvt) &&
+	   !dct_high_range_enabled(pvt) &&
+	   !dct_ganging_enabled(pvt)) {
+		if (dct_sel_interleave_addr(pvt) != 1)
+			chan_addr = (chan_addr >> 1) & 0xFFFFFFFFFFFFFFC0ULL;
+		else {
+			tmp = chan_addr & 0xFC0;
+			chan_addr = ((chan_addr & 0xFFFFFFFFFFFFC000ULL) >> 1)
+					| tmp;
+		}
+	}
+
+	debugf1("   (ChannelAddrLong=0x%llx) >> 8 becomes InputAddr=0x%x\n",
+		chan_addr, (u32)(chan_addr >> 8));
+
+	cs_found = f10_lookup_addr_in_dct(chan_addr >> 8, node_id, channel);
+
+	if (cs_found >= 0) {
+		*nid = node_id;
+		*chan_sel = channel;
+	}
+	return cs_found;
+}
+
+static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
+				       int *node, int *chan_sel)
+{
+	int dram_range, cs_found = -EINVAL;
+	u64 dram_base, dram_limit;
+
+	for (dram_range = 0; dram_range < DRAM_REG_COUNT; dram_range++) {
+
+		if (!pvt->dram_rw_en[dram_range])
+			continue;
+
+		dram_base = pvt->dram_base[dram_range];
+		dram_limit = pvt->dram_limit[dram_range];
+
+		if ((dram_base <= sys_addr) && (sys_addr <= dram_limit)) {
+
+			cs_found = f10_match_to_this_node(pvt, dram_range,
+							  sys_addr, node,
+							  chan_sel);
+			if (cs_found >= 0)
+				break;
+		}
+	}
+	return cs_found;
+}
+
+/*
+ * This the F10h reference code from AMD to map a @sys_addr to NodeID,
+ * CSROW, Channel.
+ *
+ * The @sys_addr is usually an error address received from the hardware.
+ */
+static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
+				     struct amd64_error_info_regs *info,
+				     u64 sys_addr)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 page, offset;
+	unsigned short syndrome;
+	int nid, csrow, chan = 0;
+
+	csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
+
+	if (csrow >= 0) {
+		error_address_to_page_and_offset(sys_addr, &page, &offset);
+
+		syndrome = EXTRACT_HIGH_SYNDROME(info->nbsl) << 8;
+		syndrome |= EXTRACT_LOW_SYNDROME(info->nbsh);
+
+		/*
+		 * Is CHIPKILL on? If so, then we can attempt to use the
+		 * syndrome to isolate which channel the error was on.
+		 */
+		if (pvt->nbcfg & K8_NBCFG_CHIPKILL)
+			chan = get_channel_from_ecc_syndrome(syndrome);
+
+		if (chan >= 0) {
+			edac_mc_handle_ce(mci, page, offset, syndrome,
+					csrow, chan, EDAC_MOD_STR);
+		} else {
+			/*
+			 * Channel unknown, report all channels on this
+			 * CSROW as failed.
+			 */
+			for (chan = 0; chan < mci->csrows[csrow].nr_channels;
+								chan++) {
+					edac_mc_handle_ce(mci, page, offset,
+							syndrome,
+							csrow, chan,
+							EDAC_MOD_STR);
+			}
+		}
+
+	} else {
+		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
+	}
+}
+
+/*
+ * Input (@index) is the DBAM DIMM value (1 of 4) used as an index into a shift
+ * table (revf_quad_ddr2_shift) which starts at 128MB DIMM size. Index of 0
+ * indicates an empty DIMM slot, as reported by Hardware on empty slots.
+ *
+ * Normalize to 128MB by subracting 27 bit shift.
+ */
+static int map_dbam_to_csrow_size(int index)
+{
+	int mega_bytes = 0;
+
+	if (index > 0 && index <= DBAM_MAX_VALUE)
+		mega_bytes = ((128 << (revf_quad_ddr2_shift[index]-27)));
+
+	return mega_bytes;
+}
+
+/*
+ * debug routine to display the memory sizes of a DIMM (ganged or not) and it
+ * CSROWs as well
+ */
+static void f10_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt,
+					 int ganged)
+{
+	int dimm, size0, size1;
+	u32 dbam;
+	u32 *dcsb;
+
+	debugf1("  dbam%d: 0x%8.08x  CSROW is %s\n", ctrl,
+			ctrl ? pvt->dbam1 : pvt->dbam0,
+			ganged ? "GANGED - dbam1 not used" : "NON-GANGED");
+
+	dbam = ctrl ? pvt->dbam1 : pvt->dbam0;
+	dcsb = ctrl ? pvt->dcsb1 : pvt->dcsb0;
+
+	/* Dump memory sizes for DIMM and its CSROWs */
+	for (dimm = 0; dimm < 4; dimm++) {
+
+		size0 = 0;
+		if (dcsb[dimm*2] & K8_DCSB_CS_ENABLE)
+			size0 = map_dbam_to_csrow_size(DBAM_DIMM(dimm, dbam));
+
+		size1 = 0;
+		if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE)
+			size1 = map_dbam_to_csrow_size(DBAM_DIMM(dimm, dbam));
+
+		debugf1("     CTRL-%d DIMM-%d=%5dMB   CSROW-%d=%5dMB "
+				"CSROW-%d=%5dMB\n",
+				ctrl,
+				dimm,
+				size0 + size1,
+				dimm * 2,
+				size0,
+				dimm * 2 + 1,
+				size1);
+	}
+}
+
+/*
+ * Very early hardware probe on pci_probe thread to determine if this module
+ * supports the hardware.
+ *
+ * Return:
+ *      0 for OK
+ *      1 for error
+ */
+static int f10_probe_valid_hardware(struct amd64_pvt *pvt)
+{
+	int ret = 0;
+
+	/*
+	 * If we are on a DDR3 machine, we don't know yet if
+	 * we support that properly at this time
+	 */
+	if ((pvt->dchr0 & F10_DCHR_Ddr3Mode) ||
+	    (pvt->dchr1 & F10_DCHR_Ddr3Mode)) {
+
+		amd64_printk(KERN_WARNING,
+			"%s() This machine is running with DDR3 memory. "
+			"This is not currently supported. "
+			"DCHR0=0x%x DCHR1=0x%x\n",
+			__func__, pvt->dchr0, pvt->dchr1);
+
+		amd64_printk(KERN_WARNING,
+			"   Contact '%s' module MAINTAINER to help add"
+			" support.\n",
+			EDAC_MOD_STR);
+
+		ret = 1;
+
+	}
+	return ret;
+}
+
+/*
+ * There currently are 3 types type of MC devices for AMD Athlon/Opterons
+ * (as per PCI DEVICE_IDs):
+ *
+ * Family K8: That is the Athlon64 and Opteron CPUs. They all have the same PCI
+ * DEVICE ID, even though there is differences between the different Revisions
+ * (CG,D,E,F).
+ *
+ * Family F10h and F11h.
+ *
+ */
+static struct amd64_family_type amd64_family_types[] = {
+	[K8_CPUS] = {
+		.ctl_name = "RevF",
+		.addr_f1_ctl = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
+		.misc_f3_ctl = PCI_DEVICE_ID_AMD_K8_NB_MISC,
+		.ops = {
+			.early_channel_count = k8_early_channel_count,
+			.get_error_address = k8_get_error_address,
+			.read_dram_base_limit = k8_read_dram_base_limit,
+			.map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow,
+			.dbam_map_to_pages = k8_dbam_map_to_pages,
+		}
+	},
+	[F10_CPUS] = {
+		.ctl_name = "Family 10h",
+		.addr_f1_ctl = PCI_DEVICE_ID_AMD_10H_NB_MAP,
+		.misc_f3_ctl = PCI_DEVICE_ID_AMD_10H_NB_MISC,
+		.ops = {
+			.probe_valid_hardware = f10_probe_valid_hardware,
+			.early_channel_count = f10_early_channel_count,
+			.get_error_address = f10_get_error_address,
+			.read_dram_base_limit = f10_read_dram_base_limit,
+			.read_dram_ctl_register = f10_read_dram_ctl_register,
+			.map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow,
+			.dbam_map_to_pages = f10_dbam_map_to_pages,
+		}
+	},
+	[F11_CPUS] = {
+		.ctl_name = "Family 11h",
+		.addr_f1_ctl = PCI_DEVICE_ID_AMD_11H_NB_MAP,
+		.misc_f3_ctl = PCI_DEVICE_ID_AMD_11H_NB_MISC,
+		.ops = {
+			.probe_valid_hardware = f10_probe_valid_hardware,
+			.early_channel_count = f10_early_channel_count,
+			.get_error_address = f10_get_error_address,
+			.read_dram_base_limit = f10_read_dram_base_limit,
+			.read_dram_ctl_register = f10_read_dram_ctl_register,
+			.map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow,
+			.dbam_map_to_pages = f10_dbam_map_to_pages,
+		}
+	},
+};
+
+static struct pci_dev *pci_get_related_function(unsigned int vendor,
+						unsigned int device,
+						struct pci_dev *related)
+{
+	struct pci_dev *dev = NULL;
+
+	dev = pci_get_device(vendor, device, dev);
+	while (dev) {
+		if ((dev->bus->number == related->bus->number) &&
+		    (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn)))
+			break;
+		dev = pci_get_device(vendor, device, dev);
+	}
+
+	return dev;
+}
+
+/*
+ * syndrome mapping table for ECC ChipKill devices
+ *
+ * The comment in each row is the token (nibble) number that is in error.
+ * The least significant nibble of the syndrome is the mask for the bits
+ * that are in error (need to be toggled) for the particular nibble.
+ *
+ * Each row contains 16 entries.
+ * The first entry (0th) is the channel number for that row of syndromes.
+ * The remaining 15 entries are the syndromes for the respective Error
+ * bit mask index.
+ *
+ * 1st index entry is 0x0001 mask, indicating that the rightmost bit is the
+ * bit in error.
+ * The 2nd index entry is 0x0010 that the second bit is damaged.
+ * The 3rd index entry is 0x0011 indicating that the rightmost 2 bits
+ * are damaged.
+ * Thus so on until index 15, 0x1111, whose entry has the syndrome
+ * indicating that all 4 bits are damaged.
+ *
+ * A search is performed on this table looking for a given syndrome.
+ *
+ * See the AMD documentation for ECC syndromes. This ECC table is valid
+ * across all the versions of the AMD64 processors.
+ *
+ * A fast lookup is to use the LAST four bits of the 16-bit syndrome as a
+ * COLUMN index, then search all ROWS of that column, looking for a match
+ * with the input syndrome. The ROW value will be the token number.
+ *
+ * The 0'th entry on that row, can be returned as the CHANNEL (0 or 1) of this
+ * error.
+ */
+#define NUMBER_ECC_ROWS  36
+static const unsigned short ecc_chipkill_syndromes[NUMBER_ECC_ROWS][16] = {
+	/* Channel 0 syndromes */
+	{/*0*/  0, 0xe821, 0x7c32, 0x9413, 0xbb44, 0x5365, 0xc776, 0x2f57,
+	   0xdd88, 0x35a9, 0xa1ba, 0x499b, 0x66cc, 0x8eed, 0x1afe, 0xf2df },
+	{/*1*/  0, 0x5d31, 0xa612, 0xfb23, 0x9584, 0xc8b5, 0x3396, 0x6ea7,
+	   0xeac8, 0xb7f9, 0x4cda, 0x11eb, 0x7f4c, 0x227d, 0xd95e, 0x846f },
+	{/*2*/  0, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+	   0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f },
+	{/*3*/  0, 0x2021, 0x3032, 0x1013, 0x4044, 0x6065, 0x7076, 0x5057,
+	   0x8088, 0xa0a9, 0xb0ba, 0x909b, 0xc0cc, 0xe0ed, 0xf0fe, 0xd0df },
+	{/*4*/  0, 0x5041, 0xa082, 0xf0c3, 0x9054, 0xc015, 0x30d6, 0x6097,
+	   0xe0a8, 0xb0e9, 0x402a, 0x106b, 0x70fc, 0x20bd, 0xd07e, 0x803f },
+	{/*5*/  0, 0xbe21, 0xd732, 0x6913, 0x2144, 0x9f65, 0xf676, 0x4857,
+	   0x3288, 0x8ca9, 0xe5ba, 0x5b9b, 0x13cc, 0xaded, 0xc4fe, 0x7adf },
+	{/*6*/  0, 0x4951, 0x8ea2, 0xc7f3, 0x5394, 0x1ac5, 0xdd36, 0x9467,
+	   0xa1e8, 0xe8b9, 0x2f4a, 0x661b, 0xf27c, 0xbb2d, 0x7cde, 0x358f },
+	{/*7*/  0, 0x74e1, 0x9872, 0xec93, 0xd6b4, 0xa255, 0x4ec6, 0x3a27,
+	   0x6bd8, 0x1f39, 0xf3aa, 0x874b, 0xbd6c, 0xc98d, 0x251e, 0x51ff },
+	{/*8*/  0, 0x15c1, 0x2a42, 0x3f83, 0xcef4, 0xdb35, 0xe4b6, 0xf177,
+	   0x4758, 0x5299, 0x6d1a, 0x78db, 0x89ac, 0x9c6d, 0xa3ee, 0xb62f },
+	{/*9*/  0, 0x3d01, 0x1602, 0x2b03, 0x8504, 0xb805, 0x9306, 0xae07,
+	   0xca08, 0xf709, 0xdc0a, 0xe10b, 0x4f0c, 0x720d, 0x590e, 0x640f },
+	{/*a*/  0, 0x9801, 0xec02, 0x7403, 0x6b04, 0xf305, 0x8706, 0x1f07,
+	   0xbd08, 0x2509, 0x510a, 0xc90b, 0xd60c, 0x4e0d, 0x3a0e, 0xa20f },
+	{/*b*/  0, 0xd131, 0x6212, 0xb323, 0x3884, 0xe9b5, 0x5a96, 0x8ba7,
+	   0x1cc8, 0xcdf9, 0x7eda, 0xafeb, 0x244c, 0xf57d, 0x465e, 0x976f },
+	{/*c*/  0, 0xe1d1, 0x7262, 0x93b3, 0xb834, 0x59e5, 0xca56, 0x2b87,
+	   0xdc18, 0x3dc9, 0xae7a, 0x4fab, 0x542c, 0x85fd, 0x164e, 0xf79f },
+	{/*d*/  0, 0x6051, 0xb0a2, 0xd0f3, 0x1094, 0x70c5, 0xa036, 0xc067,
+	   0x20e8, 0x40b9, 0x904a, 0x601b, 0x307c, 0x502d, 0x80de, 0xe08f },
+	{/*e*/  0, 0xa4c1, 0xf842, 0x5c83, 0xe6f4, 0x4235, 0x1eb6, 0xba77,
+	   0x7b58, 0xdf99, 0x831a, 0x27db, 0x9dac, 0x396d, 0x65ee, 0xc12f },
+	{/*f*/  0, 0x11c1, 0x2242, 0x3383, 0xc8f4, 0xd935, 0xeab6, 0xfb77,
+	   0x4c58, 0x5d99, 0x6e1a, 0x7fdb, 0x84ac, 0x956d, 0xa6ee, 0xb72f },
+
+	/* Channel 1 syndromes */
+	{/*10*/ 1, 0x45d1, 0x8a62, 0xcfb3, 0x5e34, 0x1be5, 0xd456, 0x9187,
+	   0xa718, 0xe2c9, 0x2d7a, 0x68ab, 0xf92c, 0xbcfd, 0x734e, 0x369f },
+	{/*11*/ 1, 0x63e1, 0xb172, 0xd293, 0x14b4, 0x7755, 0xa5c6, 0xc627,
+	   0x28d8, 0x4b39, 0x99aa, 0xfa4b, 0x3c6c, 0x5f8d, 0x8d1e, 0xeeff },
+	{/*12*/ 1, 0xb741, 0xd982, 0x6ec3, 0x2254, 0x9515, 0xfbd6, 0x4c97,
+	   0x33a8, 0x84e9, 0xea2a, 0x5d6b, 0x11fc, 0xa6bd, 0xc87e, 0x7f3f },
+	{/*13*/ 1, 0xdd41, 0x6682, 0xbbc3, 0x3554, 0xe815, 0x53d6, 0xce97,
+	   0x1aa8, 0xc7e9, 0x7c2a, 0xa1fb, 0x2ffc, 0xf2bd, 0x497e, 0x943f },
+	{/*14*/ 1, 0x2bd1, 0x3d62, 0x16b3, 0x4f34, 0x64e5, 0x7256, 0x5987,
+	   0x8518, 0xaec9, 0xb87a, 0x93ab, 0xca2c, 0xe1fd, 0xf74e, 0xdc9f },
+	{/*15*/ 1, 0x83c1, 0xc142, 0x4283, 0xa4f4, 0x2735, 0x65b6, 0xe677,
+	   0xf858, 0x7b99, 0x391a, 0xbadb, 0x5cac, 0xdf6d, 0x9dee, 0x1e2f },
+	{/*16*/ 1, 0x8fd1, 0xc562, 0x4ab3, 0xa934, 0x26e5, 0x6c56, 0xe387,
+	   0xfe18, 0x71c9, 0x3b7a, 0xb4ab, 0x572c, 0xd8fd, 0x924e, 0x1d9f },
+	{/*17*/ 1, 0x4791, 0x89e2, 0xce73, 0x5264, 0x15f5, 0xdb86, 0x9c17,
+	   0xa3b8, 0xe429, 0x2a5a, 0x6dcb, 0xf1dc, 0xb64d, 0x783e, 0x3faf },
+	{/*18*/ 1, 0x5781, 0xa9c2, 0xfe43, 0x92a4, 0xc525, 0x3b66, 0x6ce7,
+	   0xe3f8, 0xb479, 0x4a3a, 0x1dbb, 0x715c, 0x26dd, 0xd89e, 0x8f1f },
+	{/*19*/ 1, 0xbf41, 0xd582, 0x6ac3, 0x2954, 0x9615, 0xfcd6, 0x4397,
+	   0x3ea8, 0x81e9, 0xeb2a, 0x546b, 0x17fc, 0xa8bd, 0xc27e, 0x7d3f },
+	{/*1a*/ 1, 0x9891, 0xe1e2, 0x7273, 0x6464, 0xf7f5, 0x8586, 0x1617,
+	   0xb8b8, 0x2b29, 0x595a, 0xcacb, 0xdcdc, 0x4f4d, 0x3d3e, 0xaeaf },
+	{/*1b*/ 1, 0xcce1, 0x4472, 0x8893, 0xfdb4, 0x3f55, 0xb9c6, 0x7527,
+	   0x56d8, 0x9a39, 0x12aa, 0xde4b, 0xab6c, 0x678d, 0xef1e, 0x23ff },
+	{/*1c*/ 1, 0xa761, 0xf9b2, 0x5ed3, 0xe214, 0x4575, 0x1ba6, 0xbcc7,
+	   0x7328, 0xd449, 0x8a9a, 0x2dfb, 0x913c, 0x365d, 0x688e, 0xcfef },
+	{/*1d*/ 1, 0xff61, 0x55b2, 0xaad3, 0x7914, 0x8675, 0x2ca6, 0xd3c7,
+	   0x9e28, 0x6149, 0xcb9a, 0x34fb, 0xe73c, 0x185d, 0xb28e, 0x4def },
+	{/*1e*/ 1, 0x5451, 0xa8a2, 0xfcf3, 0x9694, 0xc2c5, 0x3e36, 0x6a67,
+	   0xebe8, 0xbfb9, 0x434a, 0x171b, 0x7d7c, 0x292d, 0xd5de, 0x818f },
+	{/*1f*/ 1, 0x6fc1, 0xb542, 0xda83, 0x19f4, 0x7635, 0xacb6, 0xc377,
+	   0x2e58, 0x4199, 0x9b1a, 0xf4db, 0x37ac, 0x586d, 0x82ee, 0xed2f },
+
+	/* ECC bits are also in the set of tokens and they too can go bad
+	 * first 2 cover channel 0, while the second 2 cover channel 1
+	 */
+	{/*20*/ 0, 0xbe01, 0xd702, 0x6903, 0x2104, 0x9f05, 0xf606, 0x4807,
+	   0x3208, 0x8c09, 0xe50a, 0x5b0b, 0x130c, 0xad0d, 0xc40e, 0x7a0f },
+	{/*21*/ 0, 0x4101, 0x8202, 0xc303, 0x5804, 0x1905, 0xda06, 0x9b07,
+	   0xac08, 0xed09, 0x2e0a, 0x6f0b, 0x640c, 0xb50d, 0x760e, 0x370f },
+	{/*22*/ 1, 0xc441, 0x4882, 0x8cc3, 0xf654, 0x3215, 0xbed6, 0x7a97,
+	   0x5ba8, 0x9fe9, 0x132a, 0xd76b, 0xadfc, 0x69bd, 0xe57e, 0x213f },
+	{/*23*/ 1, 0x7621, 0x9b32, 0xed13, 0xda44, 0xac65, 0x4176, 0x3757,
+	   0x6f88, 0x19a9, 0xf4ba, 0x829b, 0xb5cc, 0xc3ed, 0x2efe, 0x58df }
+};
+
+/*
+ * Given the syndrome argument, scan each of the channel tables for a syndrome
+ * match. Depending on which table it is found, return the channel number.
+ */
+static int get_channel_from_ecc_syndrome(unsigned short syndrome)
+{
+	int row;
+	int column;
+
+	/* Determine column to scan */
+	column = syndrome & 0xF;
+
+	/* Scan all rows, looking for syndrome, or end of table */
+	for (row = 0; row < NUMBER_ECC_ROWS; row++) {
+		if (ecc_chipkill_syndromes[row][column] == syndrome)
+			return ecc_chipkill_syndromes[row][0];
+	}
+
+	debugf0("syndrome(%x) not found\n", syndrome);
+	return -1;
+}
+
+/*
+ * Check for valid error in the NB Status High register. If so, proceed to read
+ * NB Status Low, NB Address Low and NB Address High registers and store data
+ * into error structure.
+ *
+ * Returns:
+ *	- 1: if hardware regs contains valid error info
+ *	- 0: if no valid error is indicated
+ */
+static int amd64_get_error_info_regs(struct mem_ctl_info *mci,
+				     struct amd64_error_info_regs *regs)
+{
+	struct amd64_pvt *pvt;
+	struct pci_dev *misc_f3_ctl;
+	int err = 0;
+
+	pvt = mci->pvt_info;
+	misc_f3_ctl = pvt->misc_f3_ctl;
+
+	err = pci_read_config_dword(misc_f3_ctl, K8_NBSH, &regs->nbsh);
+	if (err)
+		goto err_reg;
+
+	if (!(regs->nbsh & K8_NBSH_VALID_BIT))
+		return 0;
+
+	/* valid error, read remaining error information registers */
+	err = pci_read_config_dword(misc_f3_ctl, K8_NBSL, &regs->nbsl);
+	if (err)
+		goto err_reg;
+
+	err = pci_read_config_dword(misc_f3_ctl, K8_NBEAL, &regs->nbeal);
+	if (err)
+		goto err_reg;
+
+	err = pci_read_config_dword(misc_f3_ctl, K8_NBEAH, &regs->nbeah);
+	if (err)
+		goto err_reg;
+
+	err = pci_read_config_dword(misc_f3_ctl, K8_NBCFG, &regs->nbcfg);
+	if (err)
+		goto err_reg;
+
+	return 1;
+
+err_reg:
+	debugf0("Reading error info register failed\n");
+	return 0;
+}
+
+/*
+ * This function is called to retrieve the error data from hardware and store it
+ * in the info structure.
+ *
+ * Returns:
+ *	- 1: if a valid error is found
+ *	- 0: if no error is found
+ */
+static int amd64_get_error_info(struct mem_ctl_info *mci,
+				struct amd64_error_info_regs *info)
+{
+	struct amd64_pvt *pvt;
+	struct amd64_error_info_regs regs;
+
+	pvt = mci->pvt_info;
+
+	if (!amd64_get_error_info_regs(mci, info))
+		return 0;
+
+	/*
+	 * Here's the problem with the K8's EDAC reporting: There are four
+	 * registers which report pieces of error information. They are shared
+	 * between CEs and UEs. Furthermore, contrary to what is stated in the
+	 * BKDG, the overflow bit is never used! Every error always updates the
+	 * reporting registers.
+	 *
+	 * Can you see the race condition? All four error reporting registers
+	 * must be read before a new error updates them! There is no way to read
+	 * all four registers atomically. The best than can be done is to detect
+	 * that a race has occured and then report the error without any kind of
+	 * precision.
+	 *
+	 * What is still positive is that errors are still reported and thus
+	 * problems can still be detected - just not localized because the
+	 * syndrome and address are spread out across registers.
+	 *
+	 * Grrrrr!!!!!  Here's hoping that AMD fixes this in some future K8 rev.
+	 * UEs and CEs should have separate register sets with proper overflow
+	 * bits that are used! At very least the problem can be fixed by
+	 * honoring the ErrValid bit in 'nbsh' and not updating registers - just
+	 * set the overflow bit - unless the current error is CE and the new
+	 * error is UE which would be the only situation for overwriting the
+	 * current values.
+	 */
+
+	regs = *info;
+
+	/* Use info from the second read - most current */
+	if (unlikely(!amd64_get_error_info_regs(mci, info)))
+		return 0;
+
+	/* clear the error bits in hardware */
+	pci_write_bits32(pvt->misc_f3_ctl, K8_NBSH, 0, K8_NBSH_VALID_BIT);
+
+	/* Check for the possible race condition */
+	if ((regs.nbsh != info->nbsh) ||
+	     (regs.nbsl != info->nbsl) ||
+	     (regs.nbeah != info->nbeah) ||
+	     (regs.nbeal != info->nbeal)) {
+		amd64_mc_printk(mci, KERN_WARNING,
+				"hardware STATUS read access race condition "
+				"detected!\n");
+		return 0;
+	}
+	return 1;
+}
+
+static inline void amd64_decode_gart_tlb_error(struct mem_ctl_info *mci,
+					 struct amd64_error_info_regs *info)
+{
+	u32 err_code;
+	u32 ec_tt;		/* error code transaction type (2b) */
+	u32 ec_ll;		/* error code cache level (2b) */
+
+	err_code = EXTRACT_ERROR_CODE(info->nbsl);
+	ec_ll = EXTRACT_LL_CODE(err_code);
+	ec_tt = EXTRACT_TT_CODE(err_code);
+
+	amd64_mc_printk(mci, KERN_ERR,
+		     "GART TLB event: transaction type(%s), "
+		     "cache level(%s)\n", tt_msgs[ec_tt], ll_msgs[ec_ll]);
+}
+
+static inline void amd64_decode_mem_cache_error(struct mem_ctl_info *mci,
+				      struct amd64_error_info_regs *info)
+{
+	u32 err_code;
+	u32 ec_rrrr;		/* error code memory transaction (4b) */
+	u32 ec_tt;		/* error code transaction type (2b) */
+	u32 ec_ll;		/* error code cache level (2b) */
+
+	err_code = EXTRACT_ERROR_CODE(info->nbsl);
+	ec_ll = EXTRACT_LL_CODE(err_code);
+	ec_tt = EXTRACT_TT_CODE(err_code);
+	ec_rrrr = EXTRACT_RRRR_CODE(err_code);
+
+	amd64_mc_printk(mci, KERN_ERR,
+		     "cache hierarchy error: memory transaction type(%s), "
+		     "transaction type(%s), cache level(%s)\n",
+		     rrrr_msgs[ec_rrrr], tt_msgs[ec_tt], ll_msgs[ec_ll]);
+}
+
+
+/*
+ * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR
+ * ADDRESS and process.
+ */
+static void amd64_handle_ce(struct mem_ctl_info *mci,
+			    struct amd64_error_info_regs *info)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u64 SystemAddress;
+
+	/* Ensure that the Error Address is VALID */
+	if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) {
+		amd64_mc_printk(mci, KERN_ERR,
+			"HW has no ERROR_ADDRESS available\n");
+		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
+		return;
+	}
+
+	SystemAddress = extract_error_address(mci, info);
+
+	amd64_mc_printk(mci, KERN_ERR,
+		"CE ERROR_ADDRESS= 0x%llx\n", SystemAddress);
+
+	pvt->ops->map_sysaddr_to_csrow(mci, info, SystemAddress);
+}
+
+/* Handle any Un-correctable Errors (UEs) */
+static void amd64_handle_ue(struct mem_ctl_info *mci,
+			    struct amd64_error_info_regs *info)
+{
+	int csrow;
+	u64 SystemAddress;
+	u32 page, offset;
+	struct mem_ctl_info *log_mci, *src_mci = NULL;
+
+	log_mci = mci;
+
+	if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) {
+		amd64_mc_printk(mci, KERN_CRIT,
+			"HW has no ERROR_ADDRESS available\n");
+		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
+		return;
+	}
+
+	SystemAddress = extract_error_address(mci, info);
+
+	/*
+	 * Find out which node the error address belongs to. This may be
+	 * different from the node that detected the error.
+	 */
+	src_mci = find_mc_by_sys_addr(mci, SystemAddress);
+	if (!src_mci) {
+		amd64_mc_printk(mci, KERN_CRIT,
+			"ERROR ADDRESS (0x%lx) value NOT mapped to a MC\n",
+			(unsigned long)SystemAddress);
+		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
+		return;
+	}
+
+	log_mci = src_mci;
+
+	csrow = sys_addr_to_csrow(log_mci, SystemAddress);
+	if (csrow < 0) {
+		amd64_mc_printk(mci, KERN_CRIT,
+			"ERROR_ADDRESS (0x%lx) value NOT mapped to 'csrow'\n",
+			(unsigned long)SystemAddress);
+		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
+	} else {
+		error_address_to_page_and_offset(SystemAddress, &page, &offset);
+		edac_mc_handle_ue(log_mci, page, offset, csrow, EDAC_MOD_STR);
+	}
+}
+
+static void amd64_decode_bus_error(struct mem_ctl_info *mci,
+				   struct amd64_error_info_regs *info)
+{
+	u32 err_code, ext_ec;
+	u32 ec_pp;		/* error code participating processor (2p) */
+	u32 ec_to;		/* error code timed out (1b) */
+	u32 ec_rrrr;		/* error code memory transaction (4b) */
+	u32 ec_ii;		/* error code memory or I/O (2b) */
+	u32 ec_ll;		/* error code cache level (2b) */
+
+	ext_ec = EXTRACT_EXT_ERROR_CODE(info->nbsl);
+	err_code = EXTRACT_ERROR_CODE(info->nbsl);
+
+	ec_ll = EXTRACT_LL_CODE(err_code);
+	ec_ii = EXTRACT_II_CODE(err_code);
+	ec_rrrr = EXTRACT_RRRR_CODE(err_code);
+	ec_to = EXTRACT_TO_CODE(err_code);
+	ec_pp = EXTRACT_PP_CODE(err_code);
+
+	amd64_mc_printk(mci, KERN_ERR,
+		"BUS ERROR:\n"
+		"  time-out(%s) mem or i/o(%s)\n"
+		"  participating processor(%s)\n"
+		"  memory transaction type(%s)\n"
+		"  cache level(%s) Error Found by: %s\n",
+		to_msgs[ec_to],
+		ii_msgs[ec_ii],
+		pp_msgs[ec_pp],
+		rrrr_msgs[ec_rrrr],
+		ll_msgs[ec_ll],
+		(info->nbsh & K8_NBSH_ERR_SCRUBER) ?
+			"Scrubber" : "Normal Operation");
+
+	/* If this was an 'observed' error, early out */
+	if (ec_pp == K8_NBSL_PP_OBS)
+		return;		/* We aren't the node involved */
+
+	/* Parse out the extended error code for ECC events */
+	switch (ext_ec) {
+	/* F10 changed to one Extended ECC error code */
+	case F10_NBSL_EXT_ERR_RES:		/* Reserved field */
+	case F10_NBSL_EXT_ERR_ECC:		/* F10 ECC ext err code */
+		break;
+
+	default:
+		amd64_mc_printk(mci, KERN_ERR, "NOT ECC: no special error "
+					       "handling for this error\n");
+		return;
+	}
+
+	if (info->nbsh & K8_NBSH_CECC)
+		amd64_handle_ce(mci, info);
+	else if (info->nbsh & K8_NBSH_UECC)
+		amd64_handle_ue(mci, info);
+
+	/*
+	 * If main error is CE then overflow must be CE.  If main error is UE
+	 * then overflow is unknown.  We'll call the overflow a CE - if
+	 * panic_on_ue is set then we're already panic'ed and won't arrive
+	 * here. Else, then apparently someone doesn't think that UE's are
+	 * catastrophic.
+	 */
+	if (info->nbsh & K8_NBSH_OVERFLOW)
+		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR
+					  "Error Overflow set");
+}
+
+int amd64_process_error_info(struct mem_ctl_info *mci,
+			     struct amd64_error_info_regs *info,
+			     int handle_errors)
+{
+	struct amd64_pvt *pvt;
+	struct amd64_error_info_regs *regs;
+	u32 err_code, ext_ec;
+	int gart_tlb_error = 0;
+
+	pvt = mci->pvt_info;
+
+	/* If caller doesn't want us to process the error, return */
+	if (!handle_errors)
+		return 1;
+
+	regs = info;
+
+	debugf1("NorthBridge ERROR: mci(0x%p)\n", mci);
+	debugf1("  MC node(%d) Error-Address(0x%.8x-%.8x)\n",
+		pvt->mc_node_id, regs->nbeah, regs->nbeal);
+	debugf1("  nbsh(0x%.8x) nbsl(0x%.8x)\n",
+		regs->nbsh, regs->nbsl);
+	debugf1("  Valid Error=%s Overflow=%s\n",
+		(regs->nbsh & K8_NBSH_VALID_BIT) ? "True" : "False",
+		(regs->nbsh & K8_NBSH_OVERFLOW) ? "True" : "False");
+	debugf1("  Err Uncorrected=%s MCA Error Reporting=%s\n",
+		(regs->nbsh & K8_NBSH_UNCORRECTED_ERR) ?
+			"True" : "False",
+		(regs->nbsh & K8_NBSH_ERR_ENABLE) ?
+			"True" : "False");
+	debugf1("  MiscErr Valid=%s ErrAddr Valid=%s PCC=%s\n",
+		(regs->nbsh & K8_NBSH_MISC_ERR_VALID) ?
+			"True" : "False",
+		(regs->nbsh & K8_NBSH_VALID_ERROR_ADDR) ?
+			"True" : "False",
+		(regs->nbsh & K8_NBSH_PCC) ?
+			"True" : "False");
+	debugf1("  CECC=%s UECC=%s Found by Scruber=%s\n",
+		(regs->nbsh & K8_NBSH_CECC) ?
+			"True" : "False",
+		(regs->nbsh & K8_NBSH_UECC) ?
+			"True" : "False",
+		(regs->nbsh & K8_NBSH_ERR_SCRUBER) ?
+			"True" : "False");
+	debugf1("  CORE0=%s CORE1=%s CORE2=%s CORE3=%s\n",
+		(regs->nbsh & K8_NBSH_CORE0) ? "True" : "False",
+		(regs->nbsh & K8_NBSH_CORE1) ? "True" : "False",
+		(regs->nbsh & K8_NBSH_CORE2) ? "True" : "False",
+		(regs->nbsh & K8_NBSH_CORE3) ? "True" : "False");
+
+
+	err_code = EXTRACT_ERROR_CODE(regs->nbsl);
+
+	/* Determine which error type:
+	 *	1) GART errors - non-fatal, developmental events
+	 *	2) MEMORY errors
+	 *	3) BUS errors
+	 *	4) Unknown error
+	 */
+	if (TEST_TLB_ERROR(err_code)) {
+		/*
+		 * GART errors are intended to help graphics driver developers
+		 * to detect bad GART PTEs. It is recommended by AMD to disable
+		 * GART table walk error reporting by default[1] (currently
+		 * being disabled in mce_cpu_quirks()) and according to the
+		 * comment in mce_cpu_quirks(), such GART errors can be
+		 * incorrectly triggered. We may see these errors anyway and
+		 * unless requested by the user, they won't be reported.
+		 *
+		 * [1] section 13.10.1 on BIOS and Kernel Developers Guide for
+		 *     AMD NPT family 0Fh processors
+		 */
+		if (report_gart_errors == 0)
+			return 1;
+
+		/*
+		 * Only if GART error reporting is requested should we generate
+		 * any logs.
+		 */
+		gart_tlb_error = 1;
+
+		debugf1("GART TLB error\n");
+		amd64_decode_gart_tlb_error(mci, info);
+	} else if (TEST_MEM_ERROR(err_code)) {
+		debugf1("Memory/Cache error\n");
+		amd64_decode_mem_cache_error(mci, info);
+	} else if (TEST_BUS_ERROR(err_code)) {
+		debugf1("Bus (Link/DRAM) error\n");
+		amd64_decode_bus_error(mci, info);
+	} else {
+		/* shouldn't reach here! */
+		amd64_mc_printk(mci, KERN_WARNING,
+			     "%s(): unknown MCE error 0x%x\n", __func__,
+			     err_code);
+	}
+
+	ext_ec = EXTRACT_EXT_ERROR_CODE(regs->nbsl);
+	amd64_mc_printk(mci, KERN_ERR,
+		"ExtErr=(0x%x) %s\n", ext_ec, ext_msgs[ext_ec]);
+
+	if (((ext_ec >= F10_NBSL_EXT_ERR_CRC &&
+			ext_ec <= F10_NBSL_EXT_ERR_TGT) ||
+			(ext_ec == F10_NBSL_EXT_ERR_RMW)) &&
+			EXTRACT_LDT_LINK(info->nbsh)) {
+
+		amd64_mc_printk(mci, KERN_ERR,
+			"Error on hypertransport link: %s\n",
+			htlink_msgs[
+			EXTRACT_LDT_LINK(info->nbsh)]);
+	}
+
+	/*
+	 * Check the UE bit of the NB status high register, if set generate some
+	 * logs. If NOT a GART error, then process the event as a NO-INFO event.
+	 * If it was a GART error, skip that process.
+	 */
+	if (regs->nbsh & K8_NBSH_UNCORRECTED_ERR) {
+		amd64_mc_printk(mci, KERN_CRIT, "uncorrected error\n");
+		if (!gart_tlb_error)
+			edac_mc_handle_ue_no_info(mci, "UE bit is set\n");
+	}
+
+	if (regs->nbsh & K8_NBSH_PCC)
+		amd64_mc_printk(mci, KERN_CRIT,
+			"PCC (processor context corrupt) set\n");
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(amd64_process_error_info);
+
+/*
+ * The main polling 'check' function, called FROM the edac core to perform the
+ * error checking and if an error is encountered, error processing.
+ */
+static void amd64_check(struct mem_ctl_info *mci)
+{
+	struct amd64_error_info_regs info;
+
+	if (amd64_get_error_info(mci, &info))
+		amd64_process_error_info(mci, &info, 1);
+}
+
+/*
+ * Input:
+ *	1) struct amd64_pvt which contains pvt->dram_f2_ctl pointer
+ *	2) AMD Family index value
+ *
+ * Ouput:
+ *	Upon return of 0, the following filled in:
+ *
+ *		struct pvt->addr_f1_ctl
+ *		struct pvt->misc_f3_ctl
+ *
+ *	Filled in with related device funcitions of 'dram_f2_ctl'
+ *	These devices are "reserved" via the pci_get_device()
+ *
+ *	Upon return of 1 (error status):
+ *
+ *		Nothing reserved
+ */
+static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, int mc_idx)
+{
+	const struct amd64_family_type *amd64_dev = &amd64_family_types[mc_idx];
+
+	/* Reserve the ADDRESS MAP Device */
+	pvt->addr_f1_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor,
+						    amd64_dev->addr_f1_ctl,
+						    pvt->dram_f2_ctl);
+
+	if (!pvt->addr_f1_ctl) {
+		amd64_printk(KERN_ERR, "error address map device not found: "
+			     "vendor %x device 0x%x (broken BIOS?)\n",
+			     PCI_VENDOR_ID_AMD, amd64_dev->addr_f1_ctl);
+		return 1;
+	}
+
+	/* Reserve the MISC Device */
+	pvt->misc_f3_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor,
+						    amd64_dev->misc_f3_ctl,
+						    pvt->dram_f2_ctl);
+
+	if (!pvt->misc_f3_ctl) {
+		pci_dev_put(pvt->addr_f1_ctl);
+		pvt->addr_f1_ctl = NULL;
+
+		amd64_printk(KERN_ERR, "error miscellaneous device not found: "
+			     "vendor %x device 0x%x (broken BIOS?)\n",
+			     PCI_VENDOR_ID_AMD, amd64_dev->misc_f3_ctl);
+		return 1;
+	}
+
+	debugf1("    Addr Map device PCI Bus ID:\t%s\n",
+		pci_name(pvt->addr_f1_ctl));
+	debugf1("    DRAM MEM-CTL PCI Bus ID:\t%s\n",
+		pci_name(pvt->dram_f2_ctl));
+	debugf1("    Misc device PCI Bus ID:\t%s\n",
+		pci_name(pvt->misc_f3_ctl));
+
+	return 0;
+}
+
+static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt)
+{
+	pci_dev_put(pvt->addr_f1_ctl);
+	pci_dev_put(pvt->misc_f3_ctl);
+}
+
+/*
+ * Retrieve the hardware registers of the memory controller (this includes the
+ * 'Address Map' and 'Misc' device regs)
+ */
+static void amd64_read_mc_registers(struct amd64_pvt *pvt)
+{
+	u64 msr_val;
+	int dram, err = 0;
+
+	/*
+	 * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since
+	 * those are Read-As-Zero
+	 */
+	rdmsrl(MSR_K8_TOP_MEM1, msr_val);
+	pvt->top_mem = msr_val >> 23;
+	debugf0("  TOP_MEM=0x%08llx\n", pvt->top_mem);
+
+	/* check first whether TOP_MEM2 is enabled */
+	rdmsrl(MSR_K8_SYSCFG, msr_val);
+	if (msr_val & (1U << 21)) {
+		rdmsrl(MSR_K8_TOP_MEM2, msr_val);
+		pvt->top_mem2 = msr_val >> 23;
+		debugf0("  TOP_MEM2=0x%08llx\n", pvt->top_mem2);
+	} else
+		debugf0("  TOP_MEM2 disabled.\n");
+
+	amd64_cpu_display_info(pvt);
+
+	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap);
+	if (err)
+		goto err_reg;
+
+	if (pvt->ops->read_dram_ctl_register)
+		pvt->ops->read_dram_ctl_register(pvt);
+
+	for (dram = 0; dram < DRAM_REG_COUNT; dram++) {
+		/*
+		 * Call CPU specific READ function to get the DRAM Base and
+		 * Limit values from the DCT.
+		 */
+		pvt->ops->read_dram_base_limit(pvt, dram);
+
+		/*
+		 * Only print out debug info on rows with both R and W Enabled.
+		 * Normal processing, compiler should optimize this whole 'if'
+		 * debug output block away.
+		 */
+		if (pvt->dram_rw_en[dram] != 0) {
+			debugf1("  DRAM_BASE[%d]: 0x%8.08x-%8.08x "
+				"DRAM_LIMIT:  0x%8.08x-%8.08x\n",
+				dram,
+				(u32)(pvt->dram_base[dram] >> 32),
+				(u32)(pvt->dram_base[dram] & 0xFFFFFFFF),
+				(u32)(pvt->dram_limit[dram] >> 32),
+				(u32)(pvt->dram_limit[dram] & 0xFFFFFFFF));
+			debugf1("        IntlvEn=%s %s %s "
+				"IntlvSel=%d DstNode=%d\n",
+				pvt->dram_IntlvEn[dram] ?
+					"Enabled" : "Disabled",
+				(pvt->dram_rw_en[dram] & 0x2) ? "W" : "!W",
+				(pvt->dram_rw_en[dram] & 0x1) ? "R" : "!R",
+				pvt->dram_IntlvSel[dram],
+				pvt->dram_DstNode[dram]);
+		}
+	}
+
+	amd64_read_dct_base_mask(pvt);
+
+	err = pci_read_config_dword(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar);
+	if (err)
+		goto err_reg;
+
+	amd64_read_dbam_reg(pvt);
+
+	err = pci_read_config_dword(pvt->misc_f3_ctl,
+				F10_ONLINE_SPARE, &pvt->online_spare);
+	if (err)
+		goto err_reg;
+
+	err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0);
+	if (err)
+		goto err_reg;
+
+	err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0);
+	if (err)
+		goto err_reg;
+
+	if (!dct_ganging_enabled(pvt)) {
+		err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_1,
+						&pvt->dclr1);
+		if (err)
+			goto err_reg;
+
+		err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_1,
+						&pvt->dchr1);
+		if (err)
+			goto err_reg;
+	}
+
+	amd64_dump_misc_regs(pvt);
+
+	return;
+
+err_reg:
+	debugf0("Reading an MC register failed\n");
+
+}
+
+/*
+ * NOTE: CPU Revision Dependent code
+ *
+ * Input:
+ *	@csrow_nr ChipSelect Row Number (0..CHIPSELECT_COUNT-1)
+ *	k8 private pointer to -->
+ *			DRAM Bank Address mapping register
+ *			node_id
+ *			DCL register where dual_channel_active is
+ *
+ * The DBAM register consists of 4 sets of 4 bits each definitions:
+ *
+ * Bits:	CSROWs
+ * 0-3		CSROWs 0 and 1
+ * 4-7		CSROWs 2 and 3
+ * 8-11		CSROWs 4 and 5
+ * 12-15	CSROWs 6 and 7
+ *
+ * Values range from: 0 to 15
+ * The meaning of the values depends on CPU revision and dual-channel state,
+ * see relevant BKDG more info.
+ *
+ * The memory controller provides for total of only 8 CSROWs in its current
+ * architecture. Each "pair" of CSROWs normally represents just one DIMM in
+ * single channel or two (2) DIMMs in dual channel mode.
+ *
+ * The following code logic collapses the various tables for CSROW based on CPU
+ * revision.
+ *
+ * Returns:
+ *	The number of PAGE_SIZE pages on the specified CSROW number it
+ *	encompasses
+ *
+ */
+static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt)
+{
+	u32 dram_map, nr_pages;
+
+	/*
+	 * The math on this doesn't look right on the surface because x/2*4 can
+	 * be simplified to x*2 but this expression makes use of the fact that
+	 * it is integral math where 1/2=0. This intermediate value becomes the
+	 * number of bits to shift the DBAM register to extract the proper CSROW
+	 * field.
+	 */
+	dram_map = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF;
+
+	nr_pages = pvt->ops->dbam_map_to_pages(pvt, dram_map);
+
+	/*
+	 * If dual channel then double the memory size of single channel.
+	 * Channel count is 1 or 2
+	 */
+	nr_pages <<= (pvt->channel_count - 1);
+
+	debugf0("  (csrow=%d) DBAM map index= %d\n", csrow_nr, dram_map);
+	debugf0("    nr_pages= %u  channel-count = %d\n",
+		nr_pages, pvt->channel_count);
+
+	return nr_pages;
+}
+
+/*
+ * Initialize the array of csrow attribute instances, based on the values
+ * from pci config hardware registers.
+ */
+static int amd64_init_csrows(struct mem_ctl_info *mci)
+{
+	struct csrow_info *csrow;
+	struct amd64_pvt *pvt;
+	u64 input_addr_min, input_addr_max, sys_addr;
+	int i, err = 0, empty = 1;
+
+	pvt = mci->pvt_info;
+
+	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg);
+	if (err)
+		debugf0("Reading K8_NBCFG failed\n");
+
+	debugf0("NBCFG= 0x%x  CHIPKILL= %s DRAM ECC= %s\n", pvt->nbcfg,
+		(pvt->nbcfg & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled",
+		(pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"
+		);
+
+	for (i = 0; i < CHIPSELECT_COUNT; i++) {
+		csrow = &mci->csrows[i];
+
+		if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) {
+			debugf1("----CSROW %d EMPTY for node %d\n", i,
+				pvt->mc_node_id);
+			continue;
+		}
+
+		debugf1("----CSROW %d VALID for MC node %d\n",
+			i, pvt->mc_node_id);
+
+		empty = 0;
+		csrow->nr_pages = amd64_csrow_nr_pages(i, pvt);
+		find_csrow_limits(mci, i, &input_addr_min, &input_addr_max);
+		sys_addr = input_addr_to_sys_addr(mci, input_addr_min);
+		csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT);
+		sys_addr = input_addr_to_sys_addr(mci, input_addr_max);
+		csrow->last_page = (u32) (sys_addr >> PAGE_SHIFT);
+		csrow->page_mask = ~mask_from_dct_mask(pvt, i);
+		/* 8 bytes of resolution */
+
+		csrow->mtype = amd64_determine_memory_type(pvt);
+
+		debugf1("  for MC node %d csrow %d:\n", pvt->mc_node_id, i);
+		debugf1("    input_addr_min: 0x%lx input_addr_max: 0x%lx\n",
+			(unsigned long)input_addr_min,
+			(unsigned long)input_addr_max);
+		debugf1("    sys_addr: 0x%lx  page_mask: 0x%lx\n",
+			(unsigned long)sys_addr, csrow->page_mask);
+		debugf1("    nr_pages: %u  first_page: 0x%lx "
+			"last_page: 0x%lx\n",
+			(unsigned)csrow->nr_pages,
+			csrow->first_page, csrow->last_page);
+
+		/*
+		 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
+		 */
+		if (pvt->nbcfg & K8_NBCFG_ECC_ENABLE)
+			csrow->edac_mode =
+			    (pvt->nbcfg & K8_NBCFG_CHIPKILL) ?
+			    EDAC_S4ECD4ED : EDAC_SECDED;
+		else
+			csrow->edac_mode = EDAC_NONE;
+	}
+
+	return empty;
+}
+
+/*
+ * Only if 'ecc_enable_override' is set AND BIOS had ECC disabled, do "we"
+ * enable it.
+ */
+static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id);
+	int cpu, idx = 0, err = 0;
+	struct msr msrs[cpumask_weight(cpumask)];
+	u32 value;
+	u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+
+	if (!ecc_enable_override)
+		return;
+
+	memset(msrs, 0, sizeof(msrs));
+
+	amd64_printk(KERN_WARNING,
+		"'ecc_enable_override' parameter is active, "
+		"Enabling AMD ECC hardware now: CAUTION\n");
+
+	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value);
+	if (err)
+		debugf0("Reading K8_NBCTL failed\n");
+
+	/* turn on UECCn and CECCEn bits */
+	pvt->old_nbctl = value & mask;
+	pvt->nbctl_mcgctl_saved = 1;
+
+	value |= mask;
+	pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value);
+
+	rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
+
+	for_each_cpu(cpu, cpumask) {
+		if (msrs[idx].l & K8_MSR_MCGCTL_NBE)
+			set_bit(idx, &pvt->old_mcgctl);
+
+		msrs[idx].l |= K8_MSR_MCGCTL_NBE;
+		idx++;
+	}
+	wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
+
+	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value);
+	if (err)
+		debugf0("Reading K8_NBCFG failed\n");
+
+	debugf0("NBCFG(1)= 0x%x  CHIPKILL= %s ECC_ENABLE= %s\n", value,
+		(value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled",
+		(value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled");
+
+	if (!(value & K8_NBCFG_ECC_ENABLE)) {
+		amd64_printk(KERN_WARNING,
+			"This node reports that DRAM ECC is "
+			"currently Disabled; ENABLING now\n");
+
+		/* Attempt to turn on DRAM ECC Enable */
+		value |= K8_NBCFG_ECC_ENABLE;
+		pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value);
+
+		err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value);
+		if (err)
+			debugf0("Reading K8_NBCFG failed\n");
+
+		if (!(value & K8_NBCFG_ECC_ENABLE)) {
+			amd64_printk(KERN_WARNING,
+				"Hardware rejects Enabling DRAM ECC checking\n"
+				"Check memory DIMM configuration\n");
+		} else {
+			amd64_printk(KERN_DEBUG,
+				"Hardware accepted DRAM ECC Enable\n");
+		}
+	}
+	debugf0("NBCFG(2)= 0x%x  CHIPKILL= %s ECC_ENABLE= %s\n", value,
+		(value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled",
+		(value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled");
+
+	pvt->ctl_error_info.nbcfg = value;
+}
+
+static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt)
+{
+	const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id);
+	int cpu, idx = 0, err = 0;
+	struct msr msrs[cpumask_weight(cpumask)];
+	u32 value;
+	u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+
+	if (!pvt->nbctl_mcgctl_saved)
+		return;
+
+	memset(msrs, 0, sizeof(msrs));
+
+	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value);
+	if (err)
+		debugf0("Reading K8_NBCTL failed\n");
+	value &= ~mask;
+	value |= pvt->old_nbctl;
+
+	/* restore the NB Enable MCGCTL bit */
+	pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value);
+
+	rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
+
+	for_each_cpu(cpu, cpumask) {
+		msrs[idx].l &= ~K8_MSR_MCGCTL_NBE;
+		msrs[idx].l |=
+			test_bit(idx, &pvt->old_mcgctl) << K8_MSR_MCGCTL_NBE;
+		idx++;
+	}
+
+	wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
+}
+
+static void check_mcg_ctl(void *ret)
+{
+	u64 msr_val = 0;
+	u8 nbe;
+
+	rdmsrl(MSR_IA32_MCG_CTL, msr_val);
+	nbe = msr_val & K8_MSR_MCGCTL_NBE;
+
+	debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n",
+		raw_smp_processor_id(), msr_val,
+		(nbe ? "enabled" : "disabled"));
+
+	if (!nbe)
+		*(int *)ret = 0;
+}
+
+/* check MCG_CTL on all the cpus on this node */
+static int amd64_mcg_ctl_enabled_on_cpus(const cpumask_t *mask)
+{
+	int ret = 1;
+	preempt_disable();
+	smp_call_function_many(mask, check_mcg_ctl, &ret, 1);
+	preempt_enable();
+
+	return ret;
+}
+
+/*
+ * EDAC requires that the BIOS have ECC enabled before taking over the
+ * processing of ECC errors. This is because the BIOS can properly initialize
+ * the memory system completely. A command line option allows to force-enable
+ * hardware ECC later in amd64_enable_ecc_error_reporting().
+ */
+static int amd64_check_ecc_enabled(struct amd64_pvt *pvt)
+{
+	u32 value;
+	int err = 0, ret = 0;
+	u8 ecc_enabled = 0;
+
+	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value);
+	if (err)
+		debugf0("Reading K8_NBCTL failed\n");
+
+	ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE);
+
+	ret = amd64_mcg_ctl_enabled_on_cpus(cpumask_of_node(pvt->mc_node_id));
+
+	debugf0("K8_NBCFG=0x%x,  DRAM ECC is %s\n", value,
+			(value & K8_NBCFG_ECC_ENABLE ? "enabled" : "disabled"));
+
+	if (!ecc_enabled || !ret) {
+		if (!ecc_enabled) {
+			amd64_printk(KERN_WARNING, "This node reports that "
+						   "Memory ECC is currently "
+						   "disabled.\n");
+
+			amd64_printk(KERN_WARNING, "bit 0x%lx in register "
+				"F3x%x of the MISC_CONTROL device (%s) "
+				"should be enabled\n", K8_NBCFG_ECC_ENABLE,
+				K8_NBCFG, pci_name(pvt->misc_f3_ctl));
+		}
+		if (!ret) {
+			amd64_printk(KERN_WARNING, "bit 0x%016lx in MSR 0x%08x "
+					"of node %d should be enabled\n",
+					K8_MSR_MCGCTL_NBE, MSR_IA32_MCG_CTL,
+					pvt->mc_node_id);
+		}
+		if (!ecc_enable_override) {
+			amd64_printk(KERN_WARNING, "WARNING: ECC is NOT "
+				"currently enabled by the BIOS. Module "
+				"will NOT be loaded.\n"
+				"    Either Enable ECC in the BIOS, "
+				"or use the 'ecc_enable_override' "
+				"parameter.\n"
+				"    Might be a BIOS bug, if BIOS says "
+				"ECC is enabled\n"
+				"    Use of the override can cause "
+				"unknown side effects.\n");
+			ret = -ENODEV;
+		} else
+			/*
+			 * enable further driver loading if ECC enable is
+			 * overridden.
+			 */
+			ret = 0;
+	} else {
+		amd64_printk(KERN_INFO,
+			"ECC is enabled by BIOS, Proceeding "
+			"with EDAC module initialization\n");
+
+		/* Signal good ECC status */
+		ret = 0;
+
+		/* CLEAR the override, since BIOS controlled it */
+		ecc_enable_override = 0;
+	}
+
+	return ret;
+}
+
+struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) +
+					  ARRAY_SIZE(amd64_inj_attrs) +
+					  1];
+
+struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } };
+
+static void amd64_set_mc_sysfs_attributes(struct mem_ctl_info *mci)
+{
+	unsigned int i = 0, j = 0;
+
+	for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++)
+		sysfs_attrs[i] = amd64_dbg_attrs[i];
+
+	for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++)
+		sysfs_attrs[i] = amd64_inj_attrs[j];
+
+	sysfs_attrs[i] = terminator;
+
+	mci->mc_driver_sysfs_attributes = sysfs_attrs;
+}
+
+static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	mci->mtype_cap		= MEM_FLAG_DDR2 | MEM_FLAG_RDDR2;
+	mci->edac_ctl_cap	= EDAC_FLAG_NONE;
+
+	if (pvt->nbcap & K8_NBCAP_SECDED)
+		mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
+
+	if (pvt->nbcap & K8_NBCAP_CHIPKILL)
+		mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+
+	mci->edac_cap		= amd64_determine_edac_cap(pvt);
+	mci->mod_name		= EDAC_MOD_STR;
+	mci->mod_ver		= EDAC_AMD64_VERSION;
+	mci->ctl_name		= get_amd_family_name(pvt->mc_type_index);
+	mci->dev_name		= pci_name(pvt->dram_f2_ctl);
+	mci->ctl_page_to_phys	= NULL;
+
+	/* IMPORTANT: Set the polling 'check' function in this module */
+	mci->edac_check		= amd64_check;
+
+	/* memory scrubber interface */
+	mci->set_sdram_scrub_rate = amd64_set_scrub_rate;
+	mci->get_sdram_scrub_rate = amd64_get_scrub_rate;
+}
+
+/*
+ * Init stuff for this DRAM Controller device.
+ *
+ * Due to a hardware feature on Fam10h CPUs, the Enable Extended Configuration
+ * Space feature MUST be enabled on ALL Processors prior to actually reading
+ * from the ECS registers. Since the loading of the module can occur on any
+ * 'core', and cores don't 'see' all the other processors ECS data when the
+ * others are NOT enabled. Our solution is to first enable ECS access in this
+ * routine on all processors, gather some data in a amd64_pvt structure and
+ * later come back in a finish-setup function to perform that final
+ * initialization. See also amd64_init_2nd_stage() for that.
+ */
+static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl,
+				    int mc_type_index)
+{
+	struct amd64_pvt *pvt = NULL;
+	int err = 0, ret;
+
+	ret = -ENOMEM;
+	pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
+	if (!pvt)
+		goto err_exit;
+
+	pvt->mc_node_id = get_node_id(dram_f2_ctl);
+
+	pvt->dram_f2_ctl	= dram_f2_ctl;
+	pvt->ext_model		= boot_cpu_data.x86_model >> 4;
+	pvt->mc_type_index	= mc_type_index;
+	pvt->ops		= family_ops(mc_type_index);
+	pvt->old_mcgctl		= 0;
+
+	/*
+	 * We have the dram_f2_ctl device as an argument, now go reserve its
+	 * sibling devices from the PCI system.
+	 */
+	ret = -ENODEV;
+	err = amd64_reserve_mc_sibling_devices(pvt, mc_type_index);
+	if (err)
+		goto err_free;
+
+	ret = -EINVAL;
+	err = amd64_check_ecc_enabled(pvt);
+	if (err)
+		goto err_put;
+
+	/*
+	 * Key operation here: setup of HW prior to performing ops on it. Some
+	 * setup is required to access ECS data. After this is performed, the
+	 * 'teardown' function must be called upon error and normal exit paths.
+	 */
+	if (boot_cpu_data.x86 >= 0x10)
+		amd64_setup(pvt);
+
+	/*
+	 * Save the pointer to the private data for use in 2nd initialization
+	 * stage
+	 */
+	pvt_lookup[pvt->mc_node_id] = pvt;
+
+	return 0;
+
+err_put:
+	amd64_free_mc_sibling_devices(pvt);
+
+err_free:
+	kfree(pvt);
+
+err_exit:
+	return ret;
+}
+
+/*
+ * This is the finishing stage of the init code. Needs to be performed after all
+ * MCs' hardware have been prepped for accessing extended config space.
+ */
+static int amd64_init_2nd_stage(struct amd64_pvt *pvt)
+{
+	int node_id = pvt->mc_node_id;
+	struct mem_ctl_info *mci;
+	int ret, err = 0;
+
+	amd64_read_mc_registers(pvt);
+
+	ret = -ENODEV;
+	if (pvt->ops->probe_valid_hardware) {
+		err = pvt->ops->probe_valid_hardware(pvt);
+		if (err)
+			goto err_exit;
+	}
+
+	/*
+	 * We need to determine how many memory channels there are. Then use
+	 * that information for calculating the size of the dynamic instance
+	 * tables in the 'mci' structure
+	 */
+	pvt->channel_count = pvt->ops->early_channel_count(pvt);
+	if (pvt->channel_count < 0)
+		goto err_exit;
+
+	ret = -ENOMEM;
+	mci = edac_mc_alloc(0, CHIPSELECT_COUNT, pvt->channel_count, node_id);
+	if (!mci)
+		goto err_exit;
+
+	mci->pvt_info = pvt;
+
+	mci->dev = &pvt->dram_f2_ctl->dev;
+	amd64_setup_mci_misc_attributes(mci);
+
+	if (amd64_init_csrows(mci))
+		mci->edac_cap = EDAC_FLAG_NONE;
+
+	amd64_enable_ecc_error_reporting(mci);
+	amd64_set_mc_sysfs_attributes(mci);
+
+	ret = -ENODEV;
+	if (edac_mc_add_mc(mci)) {
+		debugf1("failed edac_mc_add_mc()\n");
+		goto err_add_mc;
+	}
+
+	mci_lookup[node_id] = mci;
+	pvt_lookup[node_id] = NULL;
+	return 0;
+
+err_add_mc:
+	edac_mc_free(mci);
+
+err_exit:
+	debugf0("failure to init 2nd stage: ret=%d\n", ret);
+
+	amd64_restore_ecc_error_reporting(pvt);
+
+	if (boot_cpu_data.x86 > 0xf)
+		amd64_teardown(pvt);
+
+	amd64_free_mc_sibling_devices(pvt);
+
+	kfree(pvt_lookup[pvt->mc_node_id]);
+	pvt_lookup[node_id] = NULL;
+
+	return ret;
+}
+
+
+static int __devinit amd64_init_one_instance(struct pci_dev *pdev,
+				 const struct pci_device_id *mc_type)
+{
+	int ret = 0;
+
+	debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev),
+		get_amd_family_name(mc_type->driver_data));
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0)
+		ret = -EIO;
+	else
+		ret = amd64_probe_one_instance(pdev, mc_type->driver_data);
+
+	if (ret < 0)
+		debugf0("ret=%d\n", ret);
+
+	return ret;
+}
+
+static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)
+{
+	struct mem_ctl_info *mci;
+	struct amd64_pvt *pvt;
+
+	/* Remove from EDAC CORE tracking list */
+	mci = edac_mc_del_mc(&pdev->dev);
+	if (!mci)
+		return;
+
+	pvt = mci->pvt_info;
+
+	amd64_restore_ecc_error_reporting(pvt);
+
+	if (boot_cpu_data.x86 > 0xf)
+		amd64_teardown(pvt);
+
+	amd64_free_mc_sibling_devices(pvt);
+
+	kfree(pvt);
+	mci->pvt_info = NULL;
+
+	mci_lookup[pvt->mc_node_id] = NULL;
+
+	/* Free the EDAC CORE resources */
+	edac_mc_free(mci);
+}
+
+/*
+ * This table is part of the interface for loading drivers for PCI devices. The
+ * PCI core identifies what devices are on a system during boot, and then
+ * inquiry this table to see if this driver is for a given device found.
+ */
+static const struct pci_device_id amd64_pci_table[] __devinitdata = {
+	{
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.class		= 0,
+		.class_mask	= 0,
+		.driver_data	= K8_CPUS
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_10H_NB_DRAM,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.class		= 0,
+		.class_mask	= 0,
+		.driver_data	= F10_CPUS
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_11H_NB_DRAM,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.class		= 0,
+		.class_mask	= 0,
+		.driver_data	= F11_CPUS
+	},
+	{0, }
+};
+MODULE_DEVICE_TABLE(pci, amd64_pci_table);
+
+static struct pci_driver amd64_pci_driver = {
+	.name		= EDAC_MOD_STR,
+	.probe		= amd64_init_one_instance,
+	.remove		= __devexit_p(amd64_remove_one_instance),
+	.id_table	= amd64_pci_table,
+};
+
+static void amd64_setup_pci_device(void)
+{
+	struct mem_ctl_info *mci;
+	struct amd64_pvt *pvt;
+
+	if (amd64_ctl_pci)
+		return;
+
+	mci = mci_lookup[0];
+	if (mci) {
+
+		pvt = mci->pvt_info;
+		amd64_ctl_pci =
+			edac_pci_create_generic_ctl(&pvt->dram_f2_ctl->dev,
+						    EDAC_MOD_STR);
+
+		if (!amd64_ctl_pci) {
+			pr_warning("%s(): Unable to create PCI control\n",
+				   __func__);
+
+			pr_warning("%s(): PCI error report via EDAC not set\n",
+				   __func__);
+			}
+	}
+}
+
+static int __init amd64_edac_init(void)
+{
+	int nb, err = -ENODEV;
+
+	edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n");
+
+	opstate_init();
+
+	if (cache_k8_northbridges() < 0)
+		goto err_exit;
+
+	err = pci_register_driver(&amd64_pci_driver);
+	if (err)
+		return err;
+
+	/*
+	 * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd
+	 * amd64_pvt structs. These will be used in the 2nd stage init function
+	 * to finish initialization of the MC instances.
+	 */
+	for (nb = 0; nb < num_k8_northbridges; nb++) {
+		if (!pvt_lookup[nb])
+			continue;
+
+		err = amd64_init_2nd_stage(pvt_lookup[nb]);
+		if (err)
+			goto err_2nd_stage;
+	}
+
+	amd64_setup_pci_device();
+
+	return 0;
+
+err_2nd_stage:
+	debugf0("2nd stage failed\n");
+
+err_exit:
+	pci_unregister_driver(&amd64_pci_driver);
+
+	return err;
+}
+
+static void __exit amd64_edac_exit(void)
+{
+	if (amd64_ctl_pci)
+		edac_pci_release_generic_ctl(amd64_ctl_pci);
+
+	pci_unregister_driver(&amd64_pci_driver);
+}
+
+module_init(amd64_edac_init);
+module_exit(amd64_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("SoftwareBitMaker: Doug Thompson, "
+		"Dave Peterson, Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for AMD64 memory controllers - "
+		EDAC_AMD64_VERSION);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
diff -druN linux-libre-2.6.30-gnu/drivers/edac/amd64_edac_dbg.c linux-libre-2.6.31-gnu/drivers/edac/amd64_edac_dbg.c
--- linux-libre-2.6.30-gnu/drivers/edac/amd64_edac_dbg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/edac/amd64_edac_dbg.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,255 @@
+#include "amd64_edac.h"
+
+/*
+ * accept a hex value and store it into the virtual error register file, field:
+ * nbeal and nbeah. Assume virtual error values have already been set for: NBSL,
+ * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and
+ * CHANNEL
+ */
+static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data,
+				size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long long value;
+	int ret = 0;
+
+	ret = strict_strtoull(data, 16, &value);
+	if (ret != -EINVAL) {
+		debugf0("received NBEA= 0x%llx\n", value);
+
+		/* place the value into the virtual error packet */
+		pvt->ctl_error_info.nbeal = (u32) value;
+		value >>= 32;
+		pvt->ctl_error_info.nbeah = (u32) value;
+
+		/* Process the Mapping request */
+		/* TODO: Add race prevention */
+		amd64_process_error_info(mci, &pvt->ctl_error_info, 1);
+
+		return count;
+	}
+	return ret;
+}
+
+/* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */
+static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u64 value;
+
+	value = pvt->ctl_error_info.nbeah;
+	value <<= 32;
+	value |= pvt->ctl_error_info.nbeal;
+
+	return sprintf(data, "%llx\n", value);
+}
+
+/* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */
+static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data,
+				size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 16, &value);
+	if (ret != -EINVAL) {
+		debugf0("received NBSL= 0x%lx\n", value);
+
+		pvt->ctl_error_info.nbsl = (u32) value;
+
+		return count;
+	}
+	return ret;
+}
+
+/* display back what the last NBSL value written */
+static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 value;
+
+	value = pvt->ctl_error_info.nbsl;
+
+	return sprintf(data, "%x\n", value);
+}
+
+/* store the NBSH (MCA NB Status High) value user desires */
+static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data,
+				size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 16, &value);
+	if (ret != -EINVAL) {
+		debugf0("received NBSH= 0x%lx\n", value);
+
+		pvt->ctl_error_info.nbsh = (u32) value;
+
+		return count;
+	}
+	return ret;
+}
+
+/* display back what the last NBSH value written */
+static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 value;
+
+	value = pvt->ctl_error_info.nbsh;
+
+	return sprintf(data, "%x\n", value);
+}
+
+/* accept and store the NBCFG (MCA NB Configuration) value user desires */
+static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci,
+					const char *data, size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 16, &value);
+	if (ret != -EINVAL) {
+		debugf0("received NBCFG= 0x%lx\n", value);
+
+		pvt->ctl_error_info.nbcfg = (u32) value;
+
+		return count;
+	}
+	return ret;
+}
+
+/* various show routines for the controls of a MCI */
+static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg);
+}
+
+
+static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	return sprintf(data, "%x\n", pvt->dhar);
+}
+
+
+static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	return sprintf(data, "%x\n", pvt->dbam0);
+}
+
+
+static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	return sprintf(data, "%llx\n", pvt->top_mem);
+}
+
+
+static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+
+	return sprintf(data, "%llx\n", pvt->top_mem2);
+}
+
+static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
+{
+	u64 hole_base = 0;
+	u64 hole_offset = 0;
+	u64 hole_size = 0;
+
+	amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, &hole_size);
+
+	return sprintf(data, "%llx %llx %llx\n", hole_base, hole_offset,
+						 hole_size);
+}
+
+/*
+ * update NUM_DBG_ATTRS in case you add new members
+ */
+struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
+
+	{
+		.attr = {
+			.name = "nbea_ctl",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = amd64_nbea_show,
+		.store = amd64_nbea_store,
+	},
+	{
+		.attr = {
+			.name = "nbsl_ctl",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = amd64_nbsl_show,
+		.store = amd64_nbsl_store,
+	},
+	{
+		.attr = {
+			.name = "nbsh_ctl",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = amd64_nbsh_show,
+		.store = amd64_nbsh_store,
+	},
+	{
+		.attr = {
+			.name = "nbcfg_ctl",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = amd64_nbcfg_show,
+		.store = amd64_nbcfg_store,
+	},
+	{
+		.attr = {
+			.name = "dhar",
+			.mode = (S_IRUGO)
+		},
+		.show = amd64_dhar_show,
+		.store = NULL,
+	},
+	{
+		.attr = {
+			.name = "dbam",
+			.mode = (S_IRUGO)
+		},
+		.show = amd64_dbam_show,
+		.store = NULL,
+	},
+	{
+		.attr = {
+			.name = "topmem",
+			.mode = (S_IRUGO)
+		},
+		.show = amd64_topmem_show,
+		.store = NULL,
+	},
+	{
+		.attr = {
+			.name = "topmem2",
+			.mode = (S_IRUGO)
+		},
+		.show = amd64_topmem2_show,
+		.store = NULL,
+	},
+	{
+		.attr = {
+			.name = "dram_hole",
+			.mode = (S_IRUGO)
+		},
+		.show = amd64_hole_show,
+		.store = NULL,
+	},
+};
diff -druN linux-libre-2.6.30-gnu/drivers/edac/amd64_edac_err_types.c linux-libre-2.6.31-gnu/drivers/edac/amd64_edac_err_types.c
--- linux-libre-2.6.30-gnu/drivers/edac/amd64_edac_err_types.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/edac/amd64_edac_err_types.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,161 @@
+#include "amd64_edac.h"
+
+/*
+ * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only
+ * for DDR2 DRAM mapping.
+ */
+u32 revf_quad_ddr2_shift[] = {
+	0,	/* 0000b NULL DIMM (128mb) */
+	28,	/* 0001b 256mb */
+	29,	/* 0010b 512mb */
+	29,	/* 0011b 512mb */
+	29,	/* 0100b 512mb */
+	30,	/* 0101b 1gb */
+	30,	/* 0110b 1gb */
+	31,	/* 0111b 2gb */
+	31,	/* 1000b 2gb */
+	32,	/* 1001b 4gb */
+	32,	/* 1010b 4gb */
+	33,	/* 1011b 8gb */
+	0,	/* 1100b future */
+	0,	/* 1101b future */
+	0,	/* 1110b future */
+	0	/* 1111b future */
+};
+
+/*
+ * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing
+ * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching-
+ * or higher value'.
+ *
+ *FIXME: Produce a better mapping/linearisation.
+ */
+
+struct scrubrate scrubrates[] = {
+	{ 0x01, 1600000000UL},
+	{ 0x02, 800000000UL},
+	{ 0x03, 400000000UL},
+	{ 0x04, 200000000UL},
+	{ 0x05, 100000000UL},
+	{ 0x06, 50000000UL},
+	{ 0x07, 25000000UL},
+	{ 0x08, 12284069UL},
+	{ 0x09, 6274509UL},
+	{ 0x0A, 3121951UL},
+	{ 0x0B, 1560975UL},
+	{ 0x0C, 781440UL},
+	{ 0x0D, 390720UL},
+	{ 0x0E, 195300UL},
+	{ 0x0F, 97650UL},
+	{ 0x10, 48854UL},
+	{ 0x11, 24427UL},
+	{ 0x12, 12213UL},
+	{ 0x13, 6101UL},
+	{ 0x14, 3051UL},
+	{ 0x15, 1523UL},
+	{ 0x16, 761UL},
+	{ 0x00, 0UL},        /* scrubbing off */
+};
+
+/*
+ * string representation for the different MCA reported error types, see F3x48
+ * or MSR0000_0411.
+ */
+const char *tt_msgs[] = {        /* transaction type */
+	"instruction",
+	"data",
+	"generic",
+	"reserved"
+};
+
+const char *ll_msgs[] = {	/* cache level */
+	"L0",
+	"L1",
+	"L2",
+	"L3/generic"
+};
+
+const char *rrrr_msgs[] = {
+	"generic",
+	"generic read",
+	"generic write",
+	"data read",
+	"data write",
+	"inst fetch",
+	"prefetch",
+	"evict",
+	"snoop",
+	"reserved RRRR= 9",
+	"reserved RRRR= 10",
+	"reserved RRRR= 11",
+	"reserved RRRR= 12",
+	"reserved RRRR= 13",
+	"reserved RRRR= 14",
+	"reserved RRRR= 15"
+};
+
+const char *pp_msgs[] = {	/* participating processor */
+	"local node originated (SRC)",
+	"local node responded to request (RES)",
+	"local node observed as 3rd party (OBS)",
+	"generic"
+};
+
+const char *to_msgs[] = {
+	"no timeout",
+	"timed out"
+};
+
+const char *ii_msgs[] = {	/* memory or i/o */
+	"mem access",
+	"reserved",
+	"i/o access",
+	"generic"
+};
+
+/* Map the 5 bits of Extended Error code to the string table. */
+const char *ext_msgs[] = {	/* extended error */
+	"K8 ECC error/F10 reserved",	/* 0_0000b */
+	"CRC error",			/* 0_0001b */
+	"sync error",			/* 0_0010b */
+	"mst abort",			/* 0_0011b */
+	"tgt abort",			/* 0_0100b */
+	"GART error",			/* 0_0101b */
+	"RMW error",			/* 0_0110b */
+	"Wdog timer error",		/* 0_0111b */
+	"F10-ECC/K8-Chipkill error",	/* 0_1000b */
+	"DEV Error",			/* 0_1001b */
+	"Link Data error",		/* 0_1010b */
+	"Link or L3 Protocol error",	/* 0_1011b */
+	"NB Array error",		/* 0_1100b */
+	"DRAM Parity error",		/* 0_1101b */
+	"Link Retry/GART Table Walk/DEV Table Walk error", /* 0_1110b */
+	"Res 0x0ff error",		/* 0_1111b */
+	"Res 0x100 error",		/* 1_0000b */
+	"Res 0x101 error",		/* 1_0001b */
+	"Res 0x102 error",		/* 1_0010b */
+	"Res 0x103 error",		/* 1_0011b */
+	"Res 0x104 error",		/* 1_0100b */
+	"Res 0x105 error",		/* 1_0101b */
+	"Res 0x106 error",		/* 1_0110b */
+	"Res 0x107 error",		/* 1_0111b */
+	"Res 0x108 error",		/* 1_1000b */
+	"Res 0x109 error",		/* 1_1001b */
+	"Res 0x10A error",		/* 1_1010b */
+	"Res 0x10B error",		/* 1_1011b */
+	"L3 Cache Data error",		/* 1_1100b */
+	"L3 CacheTag error",		/* 1_1101b */
+	"L3 Cache LRU error",		/* 1_1110b */
+	"Res 0x1FF error"		/* 1_1111b */
+};
+
+const char *htlink_msgs[] = {
+	"none",
+	"1",
+	"2",
+	"1 2",
+	"3",
+	"1 3",
+	"2 3",
+	"1 2 3"
+};
diff -druN linux-libre-2.6.30-gnu/drivers/edac/amd64_edac.h linux-libre-2.6.31-gnu/drivers/edac/amd64_edac.h
--- linux-libre-2.6.30-gnu/drivers/edac/amd64_edac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/edac/amd64_edac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,644 @@
+/*
+ * AMD64 class Memory Controller kernel module
+ *
+ * Copyright (c) 2009 SoftwareBitMaker.
+ * Copyright (c) 2009 Advanced Micro Devices, Inc.
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ *	Originally Written by Thayne Harbaugh
+ *
+ *      Changes by Douglas "norsk" Thompson  <dougthompson@xmission.com>:
+ *		- K8 CPU Revision D and greater support
+ *
+ *      Changes by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>:
+ *		- Module largely rewritten, with new (and hopefully correct)
+ *		code for dealing with node and chip select interleaving,
+ *		various code cleanup, and bug fixes
+ *		- Added support for memory hoisting using DRAM hole address
+ *		register
+ *
+ *	Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>:
+ *		-K8 Rev (1207) revision support added, required Revision
+ *		specific mini-driver code to support Rev F as well as
+ *		prior revisions
+ *
+ *	Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>:
+ *		-Family 10h revision support added. New PCI Device IDs,
+ *		indicating new changes. Actual registers modified
+ *		were slight, less than the Rev E to Rev F transition
+ *		but changing the PCI Device ID was the proper thing to
+ *		do, as it provides for almost automactic family
+ *		detection. The mods to Rev F required more family
+ *		information detection.
+ *
+ *	Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>:
+ *		- misc fixes and code cleanups
+ *
+ * This module is based on the following documents
+ * (available from http://www.amd.com/):
+ *
+ *	Title:	BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD
+ *		Opteron Processors
+ *	AMD publication #: 26094
+ *`	Revision: 3.26
+ *
+ *	Title:	BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh
+ *		Processors
+ *	AMD publication #: 32559
+ *	Revision: 3.00
+ *	Issue Date: May 2006
+ *
+ *	Title:	BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h
+ *		Processors
+ *	AMD publication #: 31116
+ *	Revision: 3.00
+ *	Issue Date: September 07, 2007
+ *
+ * Sections in the first 2 documents are no longer in sync with each other.
+ * The Family 10h BKDG was totally re-written from scratch with a new
+ * presentation model.
+ * Therefore, comments that refer to a Document section might be off.
+ */
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/mmzone.h>
+#include <linux/edac.h>
+#include <asm/msr.h>
+#include "edac_core.h"
+
+#define amd64_printk(level, fmt, arg...) \
+	edac_printk(level, "amd64", fmt, ##arg)
+
+#define amd64_mc_printk(mci, level, fmt, arg...) \
+	edac_mc_chipset_printk(mci, level, "amd64", fmt, ##arg)
+
+/*
+ * Throughout the comments in this code, the following terms are used:
+ *
+ *	SysAddr, DramAddr, and InputAddr
+ *
+ *  These terms come directly from the amd64 documentation
+ * (AMD publication #26094).  They are defined as follows:
+ *
+ *     SysAddr:
+ *         This is a physical address generated by a CPU core or a device
+ *         doing DMA.  If generated by a CPU core, a SysAddr is the result of
+ *         a virtual to physical address translation by the CPU core's address
+ *         translation mechanism (MMU).
+ *
+ *     DramAddr:
+ *         A DramAddr is derived from a SysAddr by subtracting an offset that
+ *         depends on which node the SysAddr maps to and whether the SysAddr
+ *         is within a range affected by memory hoisting.  The DRAM Base
+ *         (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers
+ *         determine which node a SysAddr maps to.
+ *
+ *         If the DRAM Hole Address Register (DHAR) is enabled and the SysAddr
+ *         is within the range of addresses specified by this register, then
+ *         a value x from the DHAR is subtracted from the SysAddr to produce a
+ *         DramAddr.  Here, x represents the base address for the node that
+ *         the SysAddr maps to plus an offset due to memory hoisting.  See
+ *         section 3.4.8 and the comments in amd64_get_dram_hole_info() and
+ *         sys_addr_to_dram_addr() below for more information.
+ *
+ *         If the SysAddr is not affected by the DHAR then a value y is
+ *         subtracted from the SysAddr to produce a DramAddr.  Here, y is the
+ *         base address for the node that the SysAddr maps to.  See section
+ *         3.4.4 and the comments in sys_addr_to_dram_addr() below for more
+ *         information.
+ *
+ *     InputAddr:
+ *         A DramAddr is translated to an InputAddr before being passed to the
+ *         memory controller for the node that the DramAddr is associated
+ *         with.  The memory controller then maps the InputAddr to a csrow.
+ *         If node interleaving is not in use, then the InputAddr has the same
+ *         value as the DramAddr.  Otherwise, the InputAddr is produced by
+ *         discarding the bits used for node interleaving from the DramAddr.
+ *         See section 3.4.4 for more information.
+ *
+ *         The memory controller for a given node uses its DRAM CS Base and
+ *         DRAM CS Mask registers to map an InputAddr to a csrow.  See
+ *         sections 3.5.4 and 3.5.5 for more information.
+ */
+
+#define EDAC_AMD64_VERSION		" Ver: 3.2.0 " __DATE__
+#define EDAC_MOD_STR			"amd64_edac"
+
+/* Extended Model from CPUID, for CPU Revision numbers */
+#define OPTERON_CPU_LE_REV_C		0
+#define OPTERON_CPU_REV_D		1
+#define OPTERON_CPU_REV_E		2
+
+/* NPT processors have the following Extended Models */
+#define OPTERON_CPU_REV_F		4
+#define OPTERON_CPU_REV_FA		5
+
+/* Hardware limit on ChipSelect rows per MC and processors per system */
+#define CHIPSELECT_COUNT		8
+#define DRAM_REG_COUNT			8
+
+
+/*
+ * PCI-defined configuration space registers
+ */
+
+
+/*
+ * Function 1 - Address Map
+ */
+#define K8_DRAM_BASE_LOW		0x40
+#define K8_DRAM_LIMIT_LOW		0x44
+#define K8_DHAR				0xf0
+
+#define DHAR_VALID			BIT(0)
+#define F10_DRAM_MEM_HOIST_VALID	BIT(1)
+
+#define DHAR_BASE_MASK			0xff000000
+#define dhar_base(dhar)			(dhar & DHAR_BASE_MASK)
+
+#define K8_DHAR_OFFSET_MASK		0x0000ff00
+#define k8_dhar_offset(dhar)		((dhar & K8_DHAR_OFFSET_MASK) << 16)
+
+#define F10_DHAR_OFFSET_MASK		0x0000ff80
+					/* NOTE: Extra mask bit vs K8 */
+#define f10_dhar_offset(dhar)		((dhar & F10_DHAR_OFFSET_MASK) << 16)
+
+
+/* F10 High BASE/LIMIT registers */
+#define F10_DRAM_BASE_HIGH		0x140
+#define F10_DRAM_LIMIT_HIGH		0x144
+
+
+/*
+ * Function 2 - DRAM controller
+ */
+#define K8_DCSB0			0x40
+#define F10_DCSB1			0x140
+
+#define K8_DCSB_CS_ENABLE		BIT(0)
+#define K8_DCSB_NPT_SPARE		BIT(1)
+#define K8_DCSB_NPT_TESTFAIL		BIT(2)
+
+/*
+ * REV E: select [31:21] and [15:9] from DCSB and the shift amount to form
+ * the address
+ */
+#define REV_E_DCSB_BASE_BITS		(0xFFE0FE00ULL)
+#define REV_E_DCS_SHIFT			4
+#define REV_E_DCSM_COUNT		8
+
+#define REV_F_F1Xh_DCSB_BASE_BITS	(0x1FF83FE0ULL)
+#define REV_F_F1Xh_DCS_SHIFT		8
+
+/*
+ * REV F and later: selects [28:19] and [13:5] from DCSB and the shift amount
+ * to form the address
+ */
+#define REV_F_DCSB_BASE_BITS		(0x1FF83FE0ULL)
+#define REV_F_DCS_SHIFT			8
+#define REV_F_DCSM_COUNT		4
+#define F10_DCSM_COUNT			4
+#define F11_DCSM_COUNT			2
+
+/* DRAM CS Mask Registers */
+#define K8_DCSM0			0x60
+#define F10_DCSM1			0x160
+
+/* REV E: select [29:21] and [15:9] from DCSM */
+#define REV_E_DCSM_MASK_BITS		0x3FE0FE00
+
+/* unused bits [24:20] and [12:0] */
+#define REV_E_DCS_NOTUSED_BITS		0x01F01FFF
+
+/* REV F and later: select [28:19] and [13:5] from DCSM */
+#define REV_F_F1Xh_DCSM_MASK_BITS	0x1FF83FE0
+
+/* unused bits [26:22] and [12:0] */
+#define REV_F_F1Xh_DCS_NOTUSED_BITS	0x07C01FFF
+
+#define DBAM0				0x80
+#define DBAM1				0x180
+
+/* Extract the DIMM 'type' on the i'th DIMM from the DBAM reg value passed */
+#define DBAM_DIMM(i, reg)		((((reg) >> (4*i))) & 0xF)
+
+#define DBAM_MAX_VALUE			11
+
+
+#define F10_DCLR_0			0x90
+#define F10_DCLR_1			0x190
+#define REVE_WIDTH_128			BIT(16)
+#define F10_WIDTH_128			BIT(11)
+
+
+#define F10_DCHR_0			0x94
+#define F10_DCHR_1			0x194
+
+#define F10_DCHR_FOUR_RANK_DIMM		BIT(18)
+#define F10_DCHR_Ddr3Mode		BIT(8)
+#define F10_DCHR_MblMode		BIT(6)
+
+
+#define F10_DCTL_SEL_LOW		0x110
+
+#define dct_sel_baseaddr(pvt)    \
+	((pvt->dram_ctl_select_low) & 0xFFFFF800)
+
+#define dct_sel_interleave_addr(pvt)    \
+	(((pvt->dram_ctl_select_low) >> 6) & 0x3)
+
+enum {
+	F10_DCTL_SEL_LOW_DctSelHiRngEn	= BIT(0),
+	F10_DCTL_SEL_LOW_DctSelIntLvEn	= BIT(2),
+	F10_DCTL_SEL_LOW_DctGangEn	= BIT(4),
+	F10_DCTL_SEL_LOW_DctDatIntLv	= BIT(5),
+	F10_DCTL_SEL_LOW_DramEnable	= BIT(8),
+	F10_DCTL_SEL_LOW_MemCleared	= BIT(10),
+};
+
+#define    dct_high_range_enabled(pvt)    \
+	(pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctSelHiRngEn)
+
+#define dct_interleave_enabled(pvt)	   \
+	(pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctSelIntLvEn)
+
+#define dct_ganging_enabled(pvt)        \
+	(pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctGangEn)
+
+#define dct_data_intlv_enabled(pvt)    \
+	(pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctDatIntLv)
+
+#define dct_dram_enabled(pvt)    \
+	(pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DramEnable)
+
+#define dct_memory_cleared(pvt)    \
+	(pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_MemCleared)
+
+
+#define F10_DCTL_SEL_HIGH		0x114
+
+
+/*
+ * Function 3 - Misc Control
+ */
+#define K8_NBCTL			0x40
+
+/* Correctable ECC error reporting enable */
+#define K8_NBCTL_CECCEn			BIT(0)
+
+/* UnCorrectable ECC error reporting enable */
+#define K8_NBCTL_UECCEn			BIT(1)
+
+#define K8_NBCFG			0x44
+#define K8_NBCFG_CHIPKILL		BIT(23)
+#define K8_NBCFG_ECC_ENABLE		BIT(22)
+
+#define K8_NBSL				0x48
+
+
+#define EXTRACT_HIGH_SYNDROME(x)	(((x) >> 24) & 0xff)
+#define EXTRACT_EXT_ERROR_CODE(x)	(((x) >> 16) & 0x1f)
+
+/* Family F10h: Normalized Extended Error Codes */
+#define F10_NBSL_EXT_ERR_RES		0x0
+#define F10_NBSL_EXT_ERR_CRC		0x1
+#define F10_NBSL_EXT_ERR_SYNC		0x2
+#define F10_NBSL_EXT_ERR_MST		0x3
+#define F10_NBSL_EXT_ERR_TGT		0x4
+#define F10_NBSL_EXT_ERR_GART		0x5
+#define F10_NBSL_EXT_ERR_RMW		0x6
+#define F10_NBSL_EXT_ERR_WDT		0x7
+#define F10_NBSL_EXT_ERR_ECC		0x8
+#define F10_NBSL_EXT_ERR_DEV		0x9
+#define F10_NBSL_EXT_ERR_LINK_DATA	0xA
+
+/* Next two are overloaded values */
+#define F10_NBSL_EXT_ERR_LINK_PROTO	0xB
+#define F10_NBSL_EXT_ERR_L3_PROTO	0xB
+
+#define F10_NBSL_EXT_ERR_NB_ARRAY	0xC
+#define F10_NBSL_EXT_ERR_DRAM_PARITY	0xD
+#define F10_NBSL_EXT_ERR_LINK_RETRY	0xE
+
+/* Next two are overloaded values */
+#define F10_NBSL_EXT_ERR_GART_WALK	0xF
+#define F10_NBSL_EXT_ERR_DEV_WALK	0xF
+
+/* 0x10 to 0x1B: Reserved */
+#define F10_NBSL_EXT_ERR_L3_DATA	0x1C
+#define F10_NBSL_EXT_ERR_L3_TAG		0x1D
+#define F10_NBSL_EXT_ERR_L3_LRU		0x1E
+
+/* K8: Normalized Extended Error Codes */
+#define K8_NBSL_EXT_ERR_ECC		0x0
+#define K8_NBSL_EXT_ERR_CRC		0x1
+#define K8_NBSL_EXT_ERR_SYNC		0x2
+#define K8_NBSL_EXT_ERR_MST		0x3
+#define K8_NBSL_EXT_ERR_TGT		0x4
+#define K8_NBSL_EXT_ERR_GART		0x5
+#define K8_NBSL_EXT_ERR_RMW		0x6
+#define K8_NBSL_EXT_ERR_WDT		0x7
+#define K8_NBSL_EXT_ERR_CHIPKILL_ECC	0x8
+#define K8_NBSL_EXT_ERR_DRAM_PARITY	0xD
+
+#define EXTRACT_ERROR_CODE(x)		((x) & 0xffff)
+#define	TEST_TLB_ERROR(x)		(((x) & 0xFFF0) == 0x0010)
+#define	TEST_MEM_ERROR(x)		(((x) & 0xFF00) == 0x0100)
+#define	TEST_BUS_ERROR(x)		(((x) & 0xF800) == 0x0800)
+#define	EXTRACT_TT_CODE(x)		(((x) >> 2) & 0x3)
+#define	EXTRACT_II_CODE(x)		(((x) >> 2) & 0x3)
+#define	EXTRACT_LL_CODE(x)		(((x) >> 0) & 0x3)
+#define	EXTRACT_RRRR_CODE(x)		(((x) >> 4) & 0xf)
+#define	EXTRACT_TO_CODE(x)		(((x) >> 8) & 0x1)
+#define	EXTRACT_PP_CODE(x)		(((x) >> 9) & 0x3)
+
+/*
+ * The following are for BUS type errors AFTER values have been normalized by
+ * shifting right
+ */
+#define K8_NBSL_PP_SRC			0x0
+#define K8_NBSL_PP_RES			0x1
+#define K8_NBSL_PP_OBS			0x2
+#define K8_NBSL_PP_GENERIC		0x3
+
+
+#define K8_NBSH				0x4C
+
+#define K8_NBSH_VALID_BIT		BIT(31)
+#define K8_NBSH_OVERFLOW		BIT(30)
+#define K8_NBSH_UNCORRECTED_ERR		BIT(29)
+#define K8_NBSH_ERR_ENABLE		BIT(28)
+#define K8_NBSH_MISC_ERR_VALID		BIT(27)
+#define K8_NBSH_VALID_ERROR_ADDR	BIT(26)
+#define K8_NBSH_PCC			BIT(25)
+#define K8_NBSH_CECC			BIT(14)
+#define K8_NBSH_UECC			BIT(13)
+#define K8_NBSH_ERR_SCRUBER		BIT(8)
+#define K8_NBSH_CORE3			BIT(3)
+#define K8_NBSH_CORE2			BIT(2)
+#define K8_NBSH_CORE1			BIT(1)
+#define K8_NBSH_CORE0			BIT(0)
+
+#define EXTRACT_LDT_LINK(x)		(((x) >> 4) & 0x7)
+#define EXTRACT_ERR_CPU_MAP(x)		((x) & 0xF)
+#define EXTRACT_LOW_SYNDROME(x)		(((x) >> 15) & 0xff)
+
+
+#define K8_NBEAL			0x50
+#define K8_NBEAH			0x54
+#define K8_SCRCTRL			0x58
+
+#define F10_NB_CFG_LOW			0x88
+#define	F10_NB_CFG_LOW_ENABLE_EXT_CFG	BIT(14)
+
+#define F10_NB_CFG_HIGH			0x8C
+
+#define F10_ONLINE_SPARE		0xB0
+#define F10_ONLINE_SPARE_SWAPDONE0(x)	((x) & BIT(1))
+#define F10_ONLINE_SPARE_SWAPDONE1(x)	((x) & BIT(3))
+#define F10_ONLINE_SPARE_BADDRAM_CS0(x) (((x) >> 4) & 0x00000007)
+#define F10_ONLINE_SPARE_BADDRAM_CS1(x) (((x) >> 8) & 0x00000007)
+
+#define F10_NB_ARRAY_ADDR		0xB8
+
+#define F10_NB_ARRAY_DRAM_ECC		0x80000000
+
+/* Bits [2:1] are used to select 16-byte section within a 64-byte cacheline  */
+#define SET_NB_ARRAY_ADDRESS(section)	(((section) & 0x3) << 1)
+
+#define F10_NB_ARRAY_DATA		0xBC
+
+#define SET_NB_DRAM_INJECTION_WRITE(word, bits)  \
+					(BIT(((word) & 0xF) + 20) | \
+					BIT(17) |  \
+					((bits) & 0xF))
+
+#define SET_NB_DRAM_INJECTION_READ(word, bits)  \
+					(BIT(((word) & 0xF) + 20) | \
+					BIT(16) |  \
+					((bits) & 0xF))
+
+#define K8_NBCAP			0xE8
+#define K8_NBCAP_CORES			(BIT(12)|BIT(13))
+#define K8_NBCAP_CHIPKILL		BIT(4)
+#define K8_NBCAP_SECDED			BIT(3)
+#define K8_NBCAP_8_NODE			BIT(2)
+#define K8_NBCAP_DUAL_NODE		BIT(1)
+#define K8_NBCAP_DCT_DUAL		BIT(0)
+
+/*
+ * MSR Regs
+ */
+#define K8_MSR_MCGCTL			0x017b
+#define K8_MSR_MCGCTL_NBE		BIT(4)
+
+#define K8_MSR_MC4CTL			0x0410
+#define K8_MSR_MC4STAT			0x0411
+#define K8_MSR_MC4ADDR			0x0412
+
+/* AMD sets the first MC device at device ID 0x18. */
+static inline int get_node_id(struct pci_dev *pdev)
+{
+	return PCI_SLOT(pdev->devfn) - 0x18;
+}
+
+enum amd64_chipset_families {
+	K8_CPUS = 0,
+	F10_CPUS,
+	F11_CPUS,
+};
+
+/*
+ * Structure to hold:
+ *
+ * 1) dynamically read status and error address HW registers
+ * 2) sysfs entered values
+ * 3) MCE values
+ *
+ * Depends on entry into the modules
+ */
+struct amd64_error_info_regs {
+	u32 nbcfg;
+	u32 nbsh;
+	u32 nbsl;
+	u32 nbeah;
+	u32 nbeal;
+};
+
+/* Error injection control structure */
+struct error_injection {
+	u32	section;
+	u32	word;
+	u32	bit_map;
+};
+
+struct amd64_pvt {
+	/* pci_device handles which we utilize */
+	struct pci_dev *addr_f1_ctl;
+	struct pci_dev *dram_f2_ctl;
+	struct pci_dev *misc_f3_ctl;
+
+	int mc_node_id;		/* MC index of this MC node */
+	int ext_model;		/* extended model value of this node */
+
+	struct low_ops *ops;	/* pointer to per PCI Device ID func table */
+
+	int channel_count;
+
+	/* Raw registers */
+	u32 dclr0;		/* DRAM Configuration Low DCT0 reg */
+	u32 dclr1;		/* DRAM Configuration Low DCT1 reg */
+	u32 dchr0;		/* DRAM Configuration High DCT0 reg */
+	u32 dchr1;		/* DRAM Configuration High DCT1 reg */
+	u32 nbcap;		/* North Bridge Capabilities */
+	u32 nbcfg;		/* F10 North Bridge Configuration */
+	u32 ext_nbcfg;		/* Extended F10 North Bridge Configuration */
+	u32 dhar;		/* DRAM Hoist reg */
+	u32 dbam0;		/* DRAM Base Address Mapping reg for DCT0 */
+	u32 dbam1;		/* DRAM Base Address Mapping reg for DCT1 */
+
+	/* DRAM CS Base Address Registers F2x[1,0][5C:40] */
+	u32 dcsb0[CHIPSELECT_COUNT];
+	u32 dcsb1[CHIPSELECT_COUNT];
+
+	/* DRAM CS Mask Registers F2x[1,0][6C:60] */
+	u32 dcsm0[CHIPSELECT_COUNT];
+	u32 dcsm1[CHIPSELECT_COUNT];
+
+	/*
+	 * Decoded parts of DRAM BASE and LIMIT Registers
+	 * F1x[78,70,68,60,58,50,48,40]
+	 */
+	u64 dram_base[DRAM_REG_COUNT];
+	u64 dram_limit[DRAM_REG_COUNT];
+	u8  dram_IntlvSel[DRAM_REG_COUNT];
+	u8  dram_IntlvEn[DRAM_REG_COUNT];
+	u8  dram_DstNode[DRAM_REG_COUNT];
+	u8  dram_rw_en[DRAM_REG_COUNT];
+
+	/*
+	 * The following fields are set at (load) run time, after CPU revision
+	 * has been determined, since the dct_base and dct_mask registers vary
+	 * based on revision
+	 */
+	u32 dcsb_base;		/* DCSB base bits */
+	u32 dcsm_mask;		/* DCSM mask bits */
+	u32 num_dcsm;		/* Number of DCSM registers */
+	u32 dcs_mask_notused;	/* DCSM notused mask bits */
+	u32 dcs_shift;		/* DCSB and DCSM shift value */
+
+	u64 top_mem;		/* top of memory below 4GB */
+	u64 top_mem2;		/* top of memory above 4GB */
+
+	u32 dram_ctl_select_low;	/* DRAM Controller Select Low Reg */
+	u32 dram_ctl_select_high;	/* DRAM Controller Select High Reg */
+	u32 online_spare;               /* On-Line spare Reg */
+
+	/* temp storage for when input is received from sysfs */
+	struct amd64_error_info_regs ctl_error_info;
+
+	/* place to store error injection parameters prior to issue */
+	struct error_injection injection;
+
+	/* Save old hw registers' values before we modified them */
+	u32 nbctl_mcgctl_saved;		/* When true, following 2 are valid */
+	u32 old_nbctl;
+	unsigned long old_mcgctl;	/* per core on this node */
+
+	/* MC Type Index value: socket F vs Family 10h */
+	u32 mc_type_index;
+
+	/* misc settings */
+	struct flags {
+		unsigned long cf8_extcfg:1;
+	} flags;
+};
+
+struct scrubrate {
+       u32 scrubval;           /* bit pattern for scrub rate */
+       u32 bandwidth;          /* bandwidth consumed (bytes/sec) */
+};
+
+extern struct scrubrate scrubrates[23];
+extern u32 revf_quad_ddr2_shift[16];
+extern const char *tt_msgs[4];
+extern const char *ll_msgs[4];
+extern const char *rrrr_msgs[16];
+extern const char *to_msgs[2];
+extern const char *pp_msgs[4];
+extern const char *ii_msgs[4];
+extern const char *ext_msgs[32];
+extern const char *htlink_msgs[8];
+
+#ifdef CONFIG_EDAC_DEBUG
+#define NUM_DBG_ATTRS 9
+#else
+#define NUM_DBG_ATTRS 0
+#endif
+
+#ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION
+#define NUM_INJ_ATTRS 5
+#else
+#define NUM_INJ_ATTRS 0
+#endif
+
+extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS],
+				     amd64_inj_attrs[NUM_INJ_ATTRS];
+
+/*
+ * Each of the PCI Device IDs types have their own set of hardware accessor
+ * functions and per device encoding/decoding logic.
+ */
+struct low_ops {
+	int (*probe_valid_hardware)(struct amd64_pvt *pvt);
+	int (*early_channel_count)(struct amd64_pvt *pvt);
+
+	u64 (*get_error_address)(struct mem_ctl_info *mci,
+			struct amd64_error_info_regs *info);
+	void (*read_dram_base_limit)(struct amd64_pvt *pvt, int dram);
+	void (*read_dram_ctl_register)(struct amd64_pvt *pvt);
+	void (*map_sysaddr_to_csrow)(struct mem_ctl_info *mci,
+					struct amd64_error_info_regs *info,
+					u64 SystemAddr);
+	int (*dbam_map_to_pages)(struct amd64_pvt *pvt, int dram_map);
+};
+
+struct amd64_family_type {
+	const char *ctl_name;
+	u16 addr_f1_ctl;
+	u16 misc_f3_ctl;
+	struct low_ops ops;
+};
+
+static struct amd64_family_type amd64_family_types[];
+
+static inline const char *get_amd_family_name(int index)
+{
+	return amd64_family_types[index].ctl_name;
+}
+
+static inline struct low_ops *family_ops(int index)
+{
+	return &amd64_family_types[index].ops;
+}
+
+/*
+ * For future CPU versions, verify the following as new 'slow' rates appear and
+ * modify the necessary skip values for the supported CPU.
+ */
+#define K8_MIN_SCRUB_RATE_BITS	0x0
+#define F10_MIN_SCRUB_RATE_BITS	0x5
+#define F11_MIN_SCRUB_RATE_BITS	0x6
+
+int amd64_process_error_info(struct mem_ctl_info *mci,
+			     struct amd64_error_info_regs *info,
+			     int handle_errors);
+int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
+			     u64 *hole_offset, u64 *hole_size);
diff -druN linux-libre-2.6.30-gnu/drivers/edac/amd64_edac_inj.c linux-libre-2.6.31-gnu/drivers/edac/amd64_edac_inj.c
--- linux-libre-2.6.30-gnu/drivers/edac/amd64_edac_inj.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/edac/amd64_edac_inj.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,185 @@
+#include "amd64_edac.h"
+
+/*
+ * store error injection section value which refers to one of 4 16-byte sections
+ * within a 64-byte cacheline
+ *
+ * range: 0..3
+ */
+static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
+					  const char *data, size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 10, &value);
+	if (ret != -EINVAL) {
+		pvt->injection.section = (u32) value;
+		return count;
+	}
+	return ret;
+}
+
+/*
+ * store error injection word value which refers to one of 9 16-bit word of the
+ * 16-byte (128-bit + ECC bits) section
+ *
+ * range: 0..8
+ */
+static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
+					const char *data, size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 10, &value);
+	if (ret != -EINVAL) {
+
+		value = (value <= 8) ? value : 0;
+		pvt->injection.word = (u32) value;
+
+		return count;
+	}
+	return ret;
+}
+
+/*
+ * store 16 bit error injection vector which enables injecting errors to the
+ * corresponding bit within the error injection word above. When used during a
+ * DRAM ECC read, it holds the contents of the of the DRAM ECC bits.
+ */
+static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
+					     const char *data, size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 16, &value);
+	if (ret != -EINVAL) {
+
+		pvt->injection.bit_map = (u32) value & 0xFFFF;
+
+		return count;
+	}
+	return ret;
+}
+
+/*
+ * Do a DRAM ECC read. Assemble staged values in the pvt area, format into
+ * fields needed by the injection registers and read the NB Array Data Port.
+ */
+static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
+					const char *data, size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	u32 section, word_bits;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 10, &value);
+	if (ret != -EINVAL) {
+
+		/* Form value to choose 16-byte section of cacheline */
+		section = F10_NB_ARRAY_DRAM_ECC |
+				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
+		pci_write_config_dword(pvt->misc_f3_ctl,
+					F10_NB_ARRAY_ADDR, section);
+
+		word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
+						pvt->injection.bit_map);
+
+		/* Issue 'word' and 'bit' along with the READ request */
+		pci_write_config_dword(pvt->misc_f3_ctl,
+					F10_NB_ARRAY_DATA, word_bits);
+
+		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
+
+		return count;
+	}
+	return ret;
+}
+
+/*
+ * Do a DRAM ECC write. Assemble staged values in the pvt area and format into
+ * fields needed by the injection registers.
+ */
+static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
+					const char *data, size_t count)
+{
+	struct amd64_pvt *pvt = mci->pvt_info;
+	unsigned long value;
+	u32 section, word_bits;
+	int ret = 0;
+
+	ret = strict_strtoul(data, 10, &value);
+	if (ret != -EINVAL) {
+
+		/* Form value to choose 16-byte section of cacheline */
+		section = F10_NB_ARRAY_DRAM_ECC |
+				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
+		pci_write_config_dword(pvt->misc_f3_ctl,
+					F10_NB_ARRAY_ADDR, section);
+
+		word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
+						pvt->injection.bit_map);
+
+		/* Issue 'word' and 'bit' along with the READ request */
+		pci_write_config_dword(pvt->misc_f3_ctl,
+					F10_NB_ARRAY_DATA, word_bits);
+
+		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
+
+		return count;
+	}
+	return ret;
+}
+
+/*
+ * update NUM_INJ_ATTRS in case you add new members
+ */
+struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
+
+	{
+		.attr = {
+			.name = "inject_section",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = NULL,
+		.store = amd64_inject_section_store,
+	},
+	{
+		.attr = {
+			.name = "inject_word",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = NULL,
+		.store = amd64_inject_word_store,
+	},
+	{
+		.attr = {
+			.name = "inject_ecc_vector",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = NULL,
+		.store = amd64_inject_ecc_vector_store,
+	},
+	{
+		.attr = {
+			.name = "inject_write",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = NULL,
+		.store = amd64_inject_write_store,
+	},
+	{
+		.attr = {
+			.name = "inject_read",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = NULL,
+		.store = amd64_inject_read_store,
+	},
+};
diff -druN linux-libre-2.6.30-gnu/drivers/edac/amd8111_edac.c linux-libre-2.6.31-gnu/drivers/edac/amd8111_edac.c
--- linux-libre-2.6.30-gnu/drivers/edac/amd8111_edac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/amd8111_edac.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,7 +37,6 @@
 #define AMD8111_EDAC_MOD_STR	"amd8111_edac"
 
 #define PCI_DEVICE_ID_AMD_8111_PCI	0x7460
-static int edac_dev_idx;
 
 enum amd8111_edac_devs {
 	LPC_BRIDGE = 0,
@@ -377,7 +376,7 @@
 	 * edac_device_ctl_info, but make use of existing
 	 * one instead.
 	*/
-	dev_info->edac_idx = edac_dev_idx++;
+	dev_info->edac_idx = edac_device_alloc_index();
 	dev_info->edac_dev =
 		edac_device_alloc_ctl_info(0, dev_info->ctl_name, 1,
 					   NULL, 0, 0,
diff -druN linux-libre-2.6.30-gnu/drivers/edac/cell_edac.c linux-libre-2.6.31-gnu/drivers/edac/cell_edac.c
--- linux-libre-2.6.30-gnu/drivers/edac/cell_edac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/cell_edac.c	2009-09-09 18:13:59.000000000 -0400
@@ -227,7 +227,7 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= cell_edac_probe,
-	.remove		= cell_edac_remove,
+	.remove		= __devexit_p(cell_edac_remove),
 };
 
 static int __init cell_edac_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/edac/cpc925_edac.c linux-libre-2.6.31-gnu/drivers/edac/cpc925_edac.c
--- linux-libre-2.6.30-gnu/drivers/edac/cpc925_edac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/edac/cpc925_edac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1017 @@
+/*
+ * cpc925_edac.c, EDAC driver for IBM CPC925 Bridge and Memory Controller.
+ *
+ * Copyright (c) 2008 Wind River Systems, Inc.
+ *
+ * Authors:	Cao Qingtao <qingtao.cao@windriver.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/edac.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "edac_core.h"
+#include "edac_module.h"
+
+#define CPC925_EDAC_REVISION	" Ver: 1.0.0 " __DATE__
+#define CPC925_EDAC_MOD_STR	"cpc925_edac"
+
+#define cpc925_printk(level, fmt, arg...) \
+	edac_printk(level, "CPC925", fmt, ##arg)
+
+#define cpc925_mc_printk(mci, level, fmt, arg...) \
+	edac_mc_chipset_printk(mci, level, "CPC925", fmt, ##arg)
+
+/*
+ * CPC925 registers are of 32 bits with bit0 defined at the
+ * most significant bit and bit31 at that of least significant.
+ */
+#define CPC925_BITS_PER_REG	32
+#define CPC925_BIT(nr)		(1UL << (CPC925_BITS_PER_REG - 1 - nr))
+
+/*
+ * EDAC device names for the error detections of
+ * CPU Interface and Hypertransport Link.
+ */
+#define CPC925_CPU_ERR_DEV	"cpu"
+#define CPC925_HT_LINK_DEV	"htlink"
+
+/* Suppose DDR Refresh cycle is 15.6 microsecond */
+#define CPC925_REF_FREQ		0xFA69
+#define CPC925_SCRUB_BLOCK_SIZE 64	/* bytes */
+#define CPC925_NR_CSROWS	8
+
+/*
+ * All registers and bits definitions are taken from
+ * "CPC925 Bridge and Memory Controller User Manual, SA14-2761-02".
+ */
+
+/*
+ * CPU and Memory Controller Registers
+ */
+/************************************************************
+ *	Processor Interface Exception Mask Register (APIMASK)
+ ************************************************************/
+#define REG_APIMASK_OFFSET	0x30070
+enum apimask_bits {
+	APIMASK_DART	= CPC925_BIT(0), /* DART Exception */
+	APIMASK_ADI0	= CPC925_BIT(1), /* Handshake Error on PI0_ADI */
+	APIMASK_ADI1	= CPC925_BIT(2), /* Handshake Error on PI1_ADI */
+	APIMASK_STAT	= CPC925_BIT(3), /* Status Exception */
+	APIMASK_DERR	= CPC925_BIT(4), /* Data Error Exception */
+	APIMASK_ADRS0	= CPC925_BIT(5), /* Addressing Exception on PI0 */
+	APIMASK_ADRS1	= CPC925_BIT(6), /* Addressing Exception on PI1 */
+					 /* BIT(7) Reserved */
+	APIMASK_ECC_UE_H = CPC925_BIT(8), /* UECC upper */
+	APIMASK_ECC_CE_H = CPC925_BIT(9), /* CECC upper */
+	APIMASK_ECC_UE_L = CPC925_BIT(10), /* UECC lower */
+	APIMASK_ECC_CE_L = CPC925_BIT(11), /* CECC lower */
+
+	CPU_MASK_ENABLE = (APIMASK_DART | APIMASK_ADI0 | APIMASK_ADI1 |
+			   APIMASK_STAT | APIMASK_DERR | APIMASK_ADRS0 |
+			   APIMASK_ADRS1),
+	ECC_MASK_ENABLE = (APIMASK_ECC_UE_H | APIMASK_ECC_CE_H |
+			   APIMASK_ECC_UE_L | APIMASK_ECC_CE_L),
+};
+
+/************************************************************
+ *	Processor Interface Exception Register (APIEXCP)
+ ************************************************************/
+#define REG_APIEXCP_OFFSET	0x30060
+enum apiexcp_bits {
+	APIEXCP_DART	= CPC925_BIT(0), /* DART Exception */
+	APIEXCP_ADI0	= CPC925_BIT(1), /* Handshake Error on PI0_ADI */
+	APIEXCP_ADI1	= CPC925_BIT(2), /* Handshake Error on PI1_ADI */
+	APIEXCP_STAT	= CPC925_BIT(3), /* Status Exception */
+	APIEXCP_DERR	= CPC925_BIT(4), /* Data Error Exception */
+	APIEXCP_ADRS0	= CPC925_BIT(5), /* Addressing Exception on PI0 */
+	APIEXCP_ADRS1	= CPC925_BIT(6), /* Addressing Exception on PI1 */
+					 /* BIT(7) Reserved */
+	APIEXCP_ECC_UE_H = CPC925_BIT(8), /* UECC upper */
+	APIEXCP_ECC_CE_H = CPC925_BIT(9), /* CECC upper */
+	APIEXCP_ECC_UE_L = CPC925_BIT(10), /* UECC lower */
+	APIEXCP_ECC_CE_L = CPC925_BIT(11), /* CECC lower */
+
+	CPU_EXCP_DETECTED = (APIEXCP_DART | APIEXCP_ADI0 | APIEXCP_ADI1 |
+			     APIEXCP_STAT | APIEXCP_DERR | APIEXCP_ADRS0 |
+			     APIEXCP_ADRS1),
+	UECC_EXCP_DETECTED = (APIEXCP_ECC_UE_H | APIEXCP_ECC_UE_L),
+	CECC_EXCP_DETECTED = (APIEXCP_ECC_CE_H | APIEXCP_ECC_CE_L),
+	ECC_EXCP_DETECTED = (UECC_EXCP_DETECTED | CECC_EXCP_DETECTED),
+};
+
+/************************************************************
+ *	Memory Bus Configuration Register (MBCR)
+************************************************************/
+#define REG_MBCR_OFFSET		0x2190
+#define MBCR_64BITCFG_SHIFT	23
+#define MBCR_64BITCFG_MASK	(1UL << MBCR_64BITCFG_SHIFT)
+#define MBCR_64BITBUS_SHIFT	22
+#define MBCR_64BITBUS_MASK	(1UL << MBCR_64BITBUS_SHIFT)
+
+/************************************************************
+ *	Memory Bank Mode Register (MBMR)
+************************************************************/
+#define REG_MBMR_OFFSET		0x21C0
+#define MBMR_MODE_MAX_VALUE	0xF
+#define MBMR_MODE_SHIFT		25
+#define MBMR_MODE_MASK		(MBMR_MODE_MAX_VALUE << MBMR_MODE_SHIFT)
+#define MBMR_BBA_SHIFT		24
+#define MBMR_BBA_MASK		(1UL << MBMR_BBA_SHIFT)
+
+/************************************************************
+ *	Memory Bank Boundary Address Register (MBBAR)
+ ************************************************************/
+#define REG_MBBAR_OFFSET	0x21D0
+#define MBBAR_BBA_MAX_VALUE	0xFF
+#define MBBAR_BBA_SHIFT		24
+#define MBBAR_BBA_MASK		(MBBAR_BBA_MAX_VALUE << MBBAR_BBA_SHIFT)
+
+/************************************************************
+ *	Memory Scrub Control Register (MSCR)
+ ************************************************************/
+#define REG_MSCR_OFFSET		0x2400
+#define MSCR_SCRUB_MOD_MASK	0xC0000000 /* scrub_mod - bit0:1*/
+#define MSCR_BACKGR_SCRUB	0x40000000 /* 01 */
+#define MSCR_SI_SHIFT		16 	/* si - bit8:15*/
+#define MSCR_SI_MAX_VALUE	0xFF
+#define MSCR_SI_MASK		(MSCR_SI_MAX_VALUE << MSCR_SI_SHIFT)
+
+/************************************************************
+ *	Memory Scrub Range Start Register (MSRSR)
+ ************************************************************/
+#define REG_MSRSR_OFFSET	0x2410
+
+/************************************************************
+ *	Memory Scrub Range End Register (MSRER)
+ ************************************************************/
+#define REG_MSRER_OFFSET	0x2420
+
+/************************************************************
+ *	Memory Scrub Pattern Register (MSPR)
+ ************************************************************/
+#define REG_MSPR_OFFSET		0x2430
+
+/************************************************************
+ *	Memory Check Control Register (MCCR)
+ ************************************************************/
+#define REG_MCCR_OFFSET		0x2440
+enum mccr_bits {
+	MCCR_ECC_EN	= CPC925_BIT(0), /* ECC high and low check */
+};
+
+/************************************************************
+ *	Memory Check Range End Register (MCRER)
+ ************************************************************/
+#define REG_MCRER_OFFSET	0x2450
+
+/************************************************************
+ *	Memory Error Address Register (MEAR)
+ ************************************************************/
+#define REG_MEAR_OFFSET		0x2460
+#define MEAR_BCNT_MAX_VALUE	0x3
+#define MEAR_BCNT_SHIFT		30
+#define MEAR_BCNT_MASK		(MEAR_BCNT_MAX_VALUE << MEAR_BCNT_SHIFT)
+#define MEAR_RANK_MAX_VALUE	0x7
+#define MEAR_RANK_SHIFT		27
+#define MEAR_RANK_MASK		(MEAR_RANK_MAX_VALUE << MEAR_RANK_SHIFT)
+#define MEAR_COL_MAX_VALUE	0x7FF
+#define MEAR_COL_SHIFT		16
+#define MEAR_COL_MASK		(MEAR_COL_MAX_VALUE << MEAR_COL_SHIFT)
+#define MEAR_BANK_MAX_VALUE	0x3
+#define MEAR_BANK_SHIFT		14
+#define MEAR_BANK_MASK		(MEAR_BANK_MAX_VALUE << MEAR_BANK_SHIFT)
+#define MEAR_ROW_MASK		0x00003FFF
+
+/************************************************************
+ *	Memory Error Syndrome Register (MESR)
+ ************************************************************/
+#define REG_MESR_OFFSET		0x2470
+#define MESR_ECC_SYN_H_MASK	0xFF00
+#define MESR_ECC_SYN_L_MASK	0x00FF
+
+/************************************************************
+ *	Memory Mode Control Register (MMCR)
+ ************************************************************/
+#define REG_MMCR_OFFSET		0x2500
+enum mmcr_bits {
+	MMCR_REG_DIMM_MODE = CPC925_BIT(3),
+};
+
+/*
+ * HyperTransport Link Registers
+ */
+/************************************************************
+ *  Error Handling/Enumeration Scratch Pad Register (ERRCTRL)
+ ************************************************************/
+#define REG_ERRCTRL_OFFSET	0x70140
+enum errctrl_bits {			 /* nonfatal interrupts for */
+	ERRCTRL_SERR_NF	= CPC925_BIT(0), /* system error */
+	ERRCTRL_CRC_NF	= CPC925_BIT(1), /* CRC error */
+	ERRCTRL_RSP_NF	= CPC925_BIT(2), /* Response error */
+	ERRCTRL_EOC_NF	= CPC925_BIT(3), /* End-Of-Chain error */
+	ERRCTRL_OVF_NF	= CPC925_BIT(4), /* Overflow error */
+	ERRCTRL_PROT_NF	= CPC925_BIT(5), /* Protocol error */
+
+	ERRCTRL_RSP_ERR	= CPC925_BIT(6), /* Response error received */
+	ERRCTRL_CHN_FAL = CPC925_BIT(7), /* Sync flooding detected */
+
+	HT_ERRCTRL_ENABLE = (ERRCTRL_SERR_NF | ERRCTRL_CRC_NF |
+			     ERRCTRL_RSP_NF | ERRCTRL_EOC_NF |
+			     ERRCTRL_OVF_NF | ERRCTRL_PROT_NF),
+	HT_ERRCTRL_DETECTED = (ERRCTRL_RSP_ERR | ERRCTRL_CHN_FAL),
+};
+
+/************************************************************
+ *  Link Configuration and Link Control Register (LINKCTRL)
+ ************************************************************/
+#define REG_LINKCTRL_OFFSET	0x70110
+enum linkctrl_bits {
+	LINKCTRL_CRC_ERR	= (CPC925_BIT(22) | CPC925_BIT(23)),
+	LINKCTRL_LINK_FAIL	= CPC925_BIT(27),
+
+	HT_LINKCTRL_DETECTED	= (LINKCTRL_CRC_ERR | LINKCTRL_LINK_FAIL),
+};
+
+/************************************************************
+ *  Link FreqCap/Error/Freq/Revision ID Register (LINKERR)
+ ************************************************************/
+#define REG_LINKERR_OFFSET	0x70120
+enum linkerr_bits {
+	LINKERR_EOC_ERR		= CPC925_BIT(17), /* End-Of-Chain error */
+	LINKERR_OVF_ERR		= CPC925_BIT(18), /* Receive Buffer Overflow */
+	LINKERR_PROT_ERR	= CPC925_BIT(19), /* Protocol error */
+
+	HT_LINKERR_DETECTED	= (LINKERR_EOC_ERR | LINKERR_OVF_ERR |
+				   LINKERR_PROT_ERR),
+};
+
+/************************************************************
+ *	Bridge Control Register (BRGCTRL)
+ ************************************************************/
+#define REG_BRGCTRL_OFFSET	0x70300
+enum brgctrl_bits {
+	BRGCTRL_DETSERR = CPC925_BIT(0), /* SERR on Secondary Bus */
+	BRGCTRL_SECBUSRESET = CPC925_BIT(9), /* Secondary Bus Reset */
+};
+
+/* Private structure for edac memory controller */
+struct cpc925_mc_pdata {
+	void __iomem *vbase;
+	unsigned long total_mem;
+	const char *name;
+	int edac_idx;
+};
+
+/* Private structure for common edac device */
+struct cpc925_dev_info {
+	void __iomem *vbase;
+	struct platform_device *pdev;
+	char *ctl_name;
+	int edac_idx;
+	struct edac_device_ctl_info *edac_dev;
+	void (*init)(struct cpc925_dev_info *dev_info);
+	void (*exit)(struct cpc925_dev_info *dev_info);
+	void (*check)(struct edac_device_ctl_info *edac_dev);
+};
+
+/* Get total memory size from Open Firmware DTB */
+static void get_total_mem(struct cpc925_mc_pdata *pdata)
+{
+	struct device_node *np = NULL;
+	const unsigned int *reg, *reg_end;
+	int len, sw, aw;
+	unsigned long start, size;
+
+	np = of_find_node_by_type(NULL, "memory");
+	if (!np)
+		return;
+
+	aw = of_n_addr_cells(np);
+	sw = of_n_size_cells(np);
+	reg = (const unsigned int *)of_get_property(np, "reg", &len);
+	reg_end = reg + len/4;
+
+	pdata->total_mem = 0;
+	do {
+		start = of_read_number(reg, aw);
+		reg += aw;
+		size = of_read_number(reg, sw);
+		reg += sw;
+		debugf1("%s: start 0x%lx, size 0x%lx\n", __func__,
+			start, size);
+		pdata->total_mem += size;
+	} while (reg < reg_end);
+
+	of_node_put(np);
+	debugf0("%s: total_mem 0x%lx\n", __func__, pdata->total_mem);
+}
+
+static void cpc925_init_csrows(struct mem_ctl_info *mci)
+{
+	struct cpc925_mc_pdata *pdata = mci->pvt_info;
+	struct csrow_info *csrow;
+	int index;
+	u32 mbmr, mbbar, bba;
+	unsigned long row_size, last_nr_pages = 0;
+
+	get_total_mem(pdata);
+
+	for (index = 0; index < mci->nr_csrows; index++) {
+		mbmr = __raw_readl(pdata->vbase + REG_MBMR_OFFSET +
+				   0x20 * index);
+		mbbar = __raw_readl(pdata->vbase + REG_MBBAR_OFFSET +
+				   0x20 + index);
+		bba = (((mbmr & MBMR_BBA_MASK) >> MBMR_BBA_SHIFT) << 8) |
+		       ((mbbar & MBBAR_BBA_MASK) >> MBBAR_BBA_SHIFT);
+
+		if (bba == 0)
+			continue; /* not populated */
+
+		csrow = &mci->csrows[index];
+
+		row_size = bba * (1UL << 28);	/* 256M */
+		csrow->first_page = last_nr_pages;
+		csrow->nr_pages = row_size >> PAGE_SHIFT;
+		csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+		last_nr_pages = csrow->last_page + 1;
+
+		csrow->mtype = MEM_RDDR;
+		csrow->edac_mode = EDAC_SECDED;
+
+		switch (csrow->nr_channels) {
+		case 1: /* Single channel */
+			csrow->grain = 32; /* four-beat burst of 32 bytes */
+			break;
+		case 2: /* Dual channel */
+		default:
+			csrow->grain = 64; /* four-beat burst of 64 bytes */
+			break;
+		}
+
+		switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) {
+		case 6: /* 0110, no way to differentiate X8 VS X16 */
+		case 5:	/* 0101 */
+		case 8: /* 1000 */
+			csrow->dtype = DEV_X16;
+			break;
+		case 7: /* 0111 */
+		case 9: /* 1001 */
+			csrow->dtype = DEV_X8;
+			break;
+		default:
+			csrow->dtype = DEV_UNKNOWN;
+			break;
+		}
+	}
+}
+
+/* Enable memory controller ECC detection */
+static void cpc925_mc_init(struct mem_ctl_info *mci)
+{
+	struct cpc925_mc_pdata *pdata = mci->pvt_info;
+	u32 apimask;
+	u32 mccr;
+
+	/* Enable various ECC error exceptions */
+	apimask = __raw_readl(pdata->vbase + REG_APIMASK_OFFSET);
+	if ((apimask & ECC_MASK_ENABLE) == 0) {
+		apimask |= ECC_MASK_ENABLE;
+		__raw_writel(apimask, pdata->vbase + REG_APIMASK_OFFSET);
+	}
+
+	/* Enable ECC detection */
+	mccr = __raw_readl(pdata->vbase + REG_MCCR_OFFSET);
+	if ((mccr & MCCR_ECC_EN) == 0) {
+		mccr |= MCCR_ECC_EN;
+		__raw_writel(mccr, pdata->vbase + REG_MCCR_OFFSET);
+	}
+}
+
+/* Disable memory controller ECC detection */
+static void cpc925_mc_exit(struct mem_ctl_info *mci)
+{
+	/*
+	 * WARNING:
+	 * We are supposed to clear the ECC error detection bits,
+	 * and it will be no problem to do so. However, once they
+	 * are cleared here if we want to re-install CPC925 EDAC
+	 * module later, setting them up in cpc925_mc_init() will
+	 * trigger machine check exception.
+	 * Also, it's ok to leave ECC error detection bits enabled,
+	 * since they are reset to 1 by default or by boot loader.
+	 */
+
+	return;
+}
+
+/*
+ * Revert DDR column/row/bank addresses into page frame number and
+ * offset in page.
+ *
+ * Suppose memory mode is 0x0111(128-bit mode, identical DIMM pairs),
+ * physical address(PA) bits to column address(CA) bits mappings are:
+ * CA	0   1   2   3   4   5   6   7   8   9   10
+ * PA	59  58  57  56  55  54  53  52  51  50  49
+ *
+ * physical address(PA) bits to bank address(BA) bits mappings are:
+ * BA	0   1
+ * PA	43  44
+ *
+ * physical address(PA) bits to row address(RA) bits mappings are:
+ * RA	0   1   2   3   4   5   6   7   8   9   10   11   12
+ * PA	36  35  34  48  47  46  45  40  41  42  39   38   37
+ */
+static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear,
+		unsigned long *pfn, unsigned long *offset, int *csrow)
+{
+	u32 bcnt, rank, col, bank, row;
+	u32 c;
+	unsigned long pa;
+	int i;
+
+	bcnt = (mear & MEAR_BCNT_MASK) >> MEAR_BCNT_SHIFT;
+	rank = (mear & MEAR_RANK_MASK) >> MEAR_RANK_SHIFT;
+	col = (mear & MEAR_COL_MASK) >> MEAR_COL_SHIFT;
+	bank = (mear & MEAR_BANK_MASK) >> MEAR_BANK_SHIFT;
+	row = mear & MEAR_ROW_MASK;
+
+	*csrow = rank;
+
+#ifdef CONFIG_EDAC_DEBUG
+	if (mci->csrows[rank].first_page == 0) {
+		cpc925_mc_printk(mci, KERN_ERR, "ECC occurs in a "
+			"non-populated csrow, broken hardware?\n");
+		return;
+	}
+#endif
+
+	/* Revert csrow number */
+	pa = mci->csrows[rank].first_page << PAGE_SHIFT;
+
+	/* Revert column address */
+	col += bcnt;
+	for (i = 0; i < 11; i++) {
+		c = col & 0x1;
+		col >>= 1;
+		pa |= c << (14 - i);
+	}
+
+	/* Revert bank address */
+	pa |= bank << 19;
+
+	/* Revert row address, in 4 steps */
+	for (i = 0; i < 3; i++) {
+		c = row & 0x1;
+		row >>= 1;
+		pa |= c << (26 - i);
+	}
+
+	for (i = 0; i < 3; i++) {
+		c = row & 0x1;
+		row >>= 1;
+		pa |= c << (21 + i);
+	}
+
+	for (i = 0; i < 4; i++) {
+		c = row & 0x1;
+		row >>= 1;
+		pa |= c << (18 - i);
+	}
+
+	for (i = 0; i < 3; i++) {
+		c = row & 0x1;
+		row >>= 1;
+		pa |= c << (29 - i);
+	}
+
+	*offset = pa & (PAGE_SIZE - 1);
+	*pfn = pa >> PAGE_SHIFT;
+
+	debugf0("%s: ECC physical address 0x%lx\n", __func__, pa);
+}
+
+static int cpc925_mc_find_channel(struct mem_ctl_info *mci, u16 syndrome)
+{
+	if ((syndrome & MESR_ECC_SYN_H_MASK) == 0)
+		return 0;
+
+	if ((syndrome & MESR_ECC_SYN_L_MASK) == 0)
+		return 1;
+
+	cpc925_mc_printk(mci, KERN_INFO, "Unexpected syndrome value: 0x%x\n",
+			 syndrome);
+	return 1;
+}
+
+/* Check memory controller registers for ECC errors */
+static void cpc925_mc_check(struct mem_ctl_info *mci)
+{
+	struct cpc925_mc_pdata *pdata = mci->pvt_info;
+	u32 apiexcp;
+	u32 mear;
+	u32 mesr;
+	u16 syndrome;
+	unsigned long pfn = 0, offset = 0;
+	int csrow = 0, channel = 0;
+
+	/* APIEXCP is cleared when read */
+	apiexcp = __raw_readl(pdata->vbase + REG_APIEXCP_OFFSET);
+	if ((apiexcp & ECC_EXCP_DETECTED) == 0)
+		return;
+
+	mesr = __raw_readl(pdata->vbase + REG_MESR_OFFSET);
+	syndrome = mesr | (MESR_ECC_SYN_H_MASK | MESR_ECC_SYN_L_MASK);
+
+	mear = __raw_readl(pdata->vbase + REG_MEAR_OFFSET);
+
+	/* Revert column/row addresses into page frame number, etc */
+	cpc925_mc_get_pfn(mci, mear, &pfn, &offset, &csrow);
+
+	if (apiexcp & CECC_EXCP_DETECTED) {
+		cpc925_mc_printk(mci, KERN_INFO, "DRAM CECC Fault\n");
+		channel = cpc925_mc_find_channel(mci, syndrome);
+		edac_mc_handle_ce(mci, pfn, offset, syndrome,
+				  csrow, channel, mci->ctl_name);
+	}
+
+	if (apiexcp & UECC_EXCP_DETECTED) {
+		cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n");
+		edac_mc_handle_ue(mci, pfn, offset, csrow, mci->ctl_name);
+	}
+
+	cpc925_mc_printk(mci, KERN_INFO, "Dump registers:\n");
+	cpc925_mc_printk(mci, KERN_INFO, "APIMASK		0x%08x\n",
+		__raw_readl(pdata->vbase + REG_APIMASK_OFFSET));
+	cpc925_mc_printk(mci, KERN_INFO, "APIEXCP		0x%08x\n",
+		apiexcp);
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Scrub Ctrl	0x%08x\n",
+		__raw_readl(pdata->vbase + REG_MSCR_OFFSET));
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Scrub Rge Start	0x%08x\n",
+		__raw_readl(pdata->vbase + REG_MSRSR_OFFSET));
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Scrub Rge End	0x%08x\n",
+		__raw_readl(pdata->vbase + REG_MSRER_OFFSET));
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Scrub Pattern	0x%08x\n",
+		__raw_readl(pdata->vbase + REG_MSPR_OFFSET));
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Chk Ctrl		0x%08x\n",
+		__raw_readl(pdata->vbase + REG_MCCR_OFFSET));
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Chk Rge End	0x%08x\n",
+		__raw_readl(pdata->vbase + REG_MCRER_OFFSET));
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Err Address	0x%08x\n",
+		mesr);
+	cpc925_mc_printk(mci, KERN_INFO, "Mem Err Syndrome	0x%08x\n",
+		syndrome);
+}
+
+/******************** CPU err device********************************/
+/* Enable CPU Errors detection */
+static void cpc925_cpu_init(struct cpc925_dev_info *dev_info)
+{
+	u32 apimask;
+
+	apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
+	if ((apimask & CPU_MASK_ENABLE) == 0) {
+		apimask |= CPU_MASK_ENABLE;
+		__raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
+	}
+}
+
+/* Disable CPU Errors detection */
+static void cpc925_cpu_exit(struct cpc925_dev_info *dev_info)
+{
+	/*
+	 * WARNING:
+	 * We are supposed to clear the CPU error detection bits,
+	 * and it will be no problem to do so. However, once they
+	 * are cleared here if we want to re-install CPC925 EDAC
+	 * module later, setting them up in cpc925_cpu_init() will
+	 * trigger machine check exception.
+	 * Also, it's ok to leave CPU error detection bits enabled,
+	 * since they are reset to 1 by default.
+	 */
+
+	return;
+}
+
+/* Check for CPU Errors */
+static void cpc925_cpu_check(struct edac_device_ctl_info *edac_dev)
+{
+	struct cpc925_dev_info *dev_info = edac_dev->pvt_info;
+	u32 apiexcp;
+	u32 apimask;
+
+	/* APIEXCP is cleared when read */
+	apiexcp = __raw_readl(dev_info->vbase + REG_APIEXCP_OFFSET);
+	if ((apiexcp & CPU_EXCP_DETECTED) == 0)
+		return;
+
+	apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
+	cpc925_printk(KERN_INFO, "Processor Interface Fault\n"
+				 "Processor Interface register dump:\n");
+	cpc925_printk(KERN_INFO, "APIMASK		0x%08x\n", apimask);
+	cpc925_printk(KERN_INFO, "APIEXCP		0x%08x\n", apiexcp);
+
+	edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
+}
+
+/******************** HT Link err device****************************/
+/* Enable HyperTransport Link Error detection */
+static void cpc925_htlink_init(struct cpc925_dev_info *dev_info)
+{
+	u32 ht_errctrl;
+
+	ht_errctrl = __raw_readl(dev_info->vbase + REG_ERRCTRL_OFFSET);
+	if ((ht_errctrl & HT_ERRCTRL_ENABLE) == 0) {
+		ht_errctrl |= HT_ERRCTRL_ENABLE;
+		__raw_writel(ht_errctrl, dev_info->vbase + REG_ERRCTRL_OFFSET);
+	}
+}
+
+/* Disable HyperTransport Link Error detection */
+static void cpc925_htlink_exit(struct cpc925_dev_info *dev_info)
+{
+	u32 ht_errctrl;
+
+	ht_errctrl = __raw_readl(dev_info->vbase + REG_ERRCTRL_OFFSET);
+	ht_errctrl &= ~HT_ERRCTRL_ENABLE;
+	__raw_writel(ht_errctrl, dev_info->vbase + REG_ERRCTRL_OFFSET);
+}
+
+/* Check for HyperTransport Link errors */
+static void cpc925_htlink_check(struct edac_device_ctl_info *edac_dev)
+{
+	struct cpc925_dev_info *dev_info = edac_dev->pvt_info;
+	u32 brgctrl = __raw_readl(dev_info->vbase + REG_BRGCTRL_OFFSET);
+	u32 linkctrl = __raw_readl(dev_info->vbase + REG_LINKCTRL_OFFSET);
+	u32 errctrl = __raw_readl(dev_info->vbase + REG_ERRCTRL_OFFSET);
+	u32 linkerr = __raw_readl(dev_info->vbase + REG_LINKERR_OFFSET);
+
+	if (!((brgctrl & BRGCTRL_DETSERR) ||
+	      (linkctrl & HT_LINKCTRL_DETECTED) ||
+	      (errctrl & HT_ERRCTRL_DETECTED) ||
+	      (linkerr & HT_LINKERR_DETECTED)))
+		return;
+
+	cpc925_printk(KERN_INFO, "HT Link Fault\n"
+				 "HT register dump:\n");
+	cpc925_printk(KERN_INFO, "Bridge Ctrl			0x%08x\n",
+		      brgctrl);
+	cpc925_printk(KERN_INFO, "Link Config Ctrl		0x%08x\n",
+		      linkctrl);
+	cpc925_printk(KERN_INFO, "Error Enum and Ctrl		0x%08x\n",
+		      errctrl);
+	cpc925_printk(KERN_INFO, "Link Error			0x%08x\n",
+		      linkerr);
+
+	/* Clear by write 1 */
+	if (brgctrl & BRGCTRL_DETSERR)
+		__raw_writel(BRGCTRL_DETSERR,
+				dev_info->vbase + REG_BRGCTRL_OFFSET);
+
+	if (linkctrl & HT_LINKCTRL_DETECTED)
+		__raw_writel(HT_LINKCTRL_DETECTED,
+				dev_info->vbase + REG_LINKCTRL_OFFSET);
+
+	/* Initiate Secondary Bus Reset to clear the chain failure */
+	if (errctrl & ERRCTRL_CHN_FAL)
+		__raw_writel(BRGCTRL_SECBUSRESET,
+				dev_info->vbase + REG_BRGCTRL_OFFSET);
+
+	if (errctrl & ERRCTRL_RSP_ERR)
+		__raw_writel(ERRCTRL_RSP_ERR,
+				dev_info->vbase + REG_ERRCTRL_OFFSET);
+
+	if (linkerr & HT_LINKERR_DETECTED)
+		__raw_writel(HT_LINKERR_DETECTED,
+				dev_info->vbase + REG_LINKERR_OFFSET);
+
+	edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
+}
+
+static struct cpc925_dev_info cpc925_devs[] = {
+	{
+	.ctl_name = CPC925_CPU_ERR_DEV,
+	.init = cpc925_cpu_init,
+	.exit = cpc925_cpu_exit,
+	.check = cpc925_cpu_check,
+	},
+	{
+	.ctl_name = CPC925_HT_LINK_DEV,
+	.init = cpc925_htlink_init,
+	.exit = cpc925_htlink_exit,
+	.check = cpc925_htlink_check,
+	},
+	{0}, /* Terminated by NULL */
+};
+
+/*
+ * Add CPU Err detection and HyperTransport Link Err detection
+ * as common "edac_device", they have no corresponding device
+ * nodes in the Open Firmware DTB and we have to add platform
+ * devices for them. Also, they will share the MMIO with that
+ * of memory controller.
+ */
+static void cpc925_add_edac_devices(void __iomem *vbase)
+{
+	struct cpc925_dev_info *dev_info;
+
+	if (!vbase) {
+		cpc925_printk(KERN_ERR, "MMIO not established yet\n");
+		return;
+	}
+
+	for (dev_info = &cpc925_devs[0]; dev_info->init; dev_info++) {
+		dev_info->vbase = vbase;
+		dev_info->pdev = platform_device_register_simple(
+					dev_info->ctl_name, 0, NULL, 0);
+		if (IS_ERR(dev_info->pdev)) {
+			cpc925_printk(KERN_ERR,
+				"Can't register platform device for %s\n",
+				dev_info->ctl_name);
+			continue;
+		}
+
+		/*
+		 * Don't have to allocate private structure but
+		 * make use of cpc925_devs[] instead.
+		 */
+		dev_info->edac_idx = edac_device_alloc_index();
+		dev_info->edac_dev =
+			edac_device_alloc_ctl_info(0, dev_info->ctl_name,
+				1, NULL, 0, 0, NULL, 0, dev_info->edac_idx);
+		if (!dev_info->edac_dev) {
+			cpc925_printk(KERN_ERR, "No memory for edac device\n");
+			goto err1;
+		}
+
+		dev_info->edac_dev->pvt_info = dev_info;
+		dev_info->edac_dev->dev = &dev_info->pdev->dev;
+		dev_info->edac_dev->ctl_name = dev_info->ctl_name;
+		dev_info->edac_dev->mod_name = CPC925_EDAC_MOD_STR;
+		dev_info->edac_dev->dev_name = dev_name(&dev_info->pdev->dev);
+
+		if (edac_op_state == EDAC_OPSTATE_POLL)
+			dev_info->edac_dev->edac_check = dev_info->check;
+
+		if (dev_info->init)
+			dev_info->init(dev_info);
+
+		if (edac_device_add_device(dev_info->edac_dev) > 0) {
+			cpc925_printk(KERN_ERR,
+				"Unable to add edac device for %s\n",
+				dev_info->ctl_name);
+			goto err2;
+		}
+
+		debugf0("%s: Successfully added edac device for %s\n",
+			__func__, dev_info->ctl_name);
+
+		continue;
+
+err2:
+		if (dev_info->exit)
+			dev_info->exit(dev_info);
+		edac_device_free_ctl_info(dev_info->edac_dev);
+err1:
+		platform_device_unregister(dev_info->pdev);
+	}
+}
+
+/*
+ * Delete the common "edac_device" for CPU Err Detection
+ * and HyperTransport Link Err Detection
+ */
+static void cpc925_del_edac_devices(void)
+{
+	struct cpc925_dev_info *dev_info;
+
+	for (dev_info = &cpc925_devs[0]; dev_info->init; dev_info++) {
+		if (dev_info->edac_dev) {
+			edac_device_del_device(dev_info->edac_dev->dev);
+			edac_device_free_ctl_info(dev_info->edac_dev);
+			platform_device_unregister(dev_info->pdev);
+		}
+
+		if (dev_info->exit)
+			dev_info->exit(dev_info);
+
+		debugf0("%s: Successfully deleted edac device for %s\n",
+			__func__, dev_info->ctl_name);
+	}
+}
+
+/* Convert current back-ground scrub rate into byte/sec bandwith */
+static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+{
+	struct cpc925_mc_pdata *pdata = mci->pvt_info;
+	u32 mscr;
+	u8 si;
+
+	mscr = __raw_readl(pdata->vbase + REG_MSCR_OFFSET);
+	si = (mscr & MSCR_SI_MASK) >> MSCR_SI_SHIFT;
+
+	debugf0("%s, Mem Scrub Ctrl Register 0x%x\n", __func__, mscr);
+
+	if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) ||
+	    (si == 0)) {
+		cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n");
+		*bw = 0;
+	} else
+		*bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si;
+
+	return 0;
+}
+
+/* Return 0 for single channel; 1 for dual channel */
+static int cpc925_mc_get_channels(void __iomem *vbase)
+{
+	int dual = 0;
+	u32 mbcr;
+
+	mbcr = __raw_readl(vbase + REG_MBCR_OFFSET);
+
+	/*
+	 * Dual channel only when 128-bit wide physical bus
+	 * and 128-bit configuration.
+	 */
+	if (((mbcr & MBCR_64BITCFG_MASK) == 0) &&
+	    ((mbcr & MBCR_64BITBUS_MASK) == 0))
+		dual = 1;
+
+	debugf0("%s: %s channel\n", __func__,
+		(dual > 0) ? "Dual" : "Single");
+
+	return dual;
+}
+
+static int __devinit cpc925_probe(struct platform_device *pdev)
+{
+	static int edac_mc_idx;
+	struct mem_ctl_info *mci;
+	void __iomem *vbase;
+	struct cpc925_mc_pdata *pdata;
+	struct resource *r;
+	int res = 0, nr_channels;
+
+	debugf0("%s: %s platform device found!\n", __func__, pdev->name);
+
+	if (!devres_open_group(&pdev->dev, cpc925_probe, GFP_KERNEL)) {
+		res = -ENOMEM;
+		goto out;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		cpc925_printk(KERN_ERR, "Unable to get resource\n");
+		res = -ENOENT;
+		goto err1;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev,
+				     r->start,
+				     r->end - r->start + 1,
+				     pdev->name)) {
+		cpc925_printk(KERN_ERR, "Unable to request mem region\n");
+		res = -EBUSY;
+		goto err1;
+	}
+
+	vbase = devm_ioremap(&pdev->dev, r->start, r->end - r->start + 1);
+	if (!vbase) {
+		cpc925_printk(KERN_ERR, "Unable to ioremap device\n");
+		res = -ENOMEM;
+		goto err2;
+	}
+
+	nr_channels = cpc925_mc_get_channels(vbase);
+	mci = edac_mc_alloc(sizeof(struct cpc925_mc_pdata),
+			CPC925_NR_CSROWS, nr_channels + 1, edac_mc_idx);
+	if (!mci) {
+		cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
+		res = -ENOMEM;
+		goto err2;
+	}
+
+	pdata = mci->pvt_info;
+	pdata->vbase = vbase;
+	pdata->edac_idx = edac_mc_idx++;
+	pdata->name = pdev->name;
+
+	mci->dev = &pdev->dev;
+	platform_set_drvdata(pdev, mci);
+	mci->dev_name = dev_name(&pdev->dev);
+	mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+	mci->edac_cap = EDAC_FLAG_SECDED;
+	mci->mod_name = CPC925_EDAC_MOD_STR;
+	mci->mod_ver = CPC925_EDAC_REVISION;
+	mci->ctl_name = pdev->name;
+
+	if (edac_op_state == EDAC_OPSTATE_POLL)
+		mci->edac_check = cpc925_mc_check;
+
+	mci->ctl_page_to_phys = NULL;
+	mci->scrub_mode = SCRUB_SW_SRC;
+	mci->set_sdram_scrub_rate = NULL;
+	mci->get_sdram_scrub_rate = cpc925_get_sdram_scrub_rate;
+
+	cpc925_init_csrows(mci);
+
+	/* Setup memory controller registers */
+	cpc925_mc_init(mci);
+
+	if (edac_mc_add_mc(mci) > 0) {
+		cpc925_mc_printk(mci, KERN_ERR, "Failed edac_mc_add_mc()\n");
+		goto err3;
+	}
+
+	cpc925_add_edac_devices(vbase);
+
+	/* get this far and it's successful */
+	debugf0("%s: success\n", __func__);
+
+	res = 0;
+	goto out;
+
+err3:
+	cpc925_mc_exit(mci);
+	edac_mc_free(mci);
+err2:
+	devm_release_mem_region(&pdev->dev, r->start, r->end-r->start+1);
+err1:
+	devres_release_group(&pdev->dev, cpc925_probe);
+out:
+	return res;
+}
+
+static int cpc925_remove(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+	/*
+	 * Delete common edac devices before edac mc, because
+	 * the former share the MMIO of the latter.
+	 */
+	cpc925_del_edac_devices();
+	cpc925_mc_exit(mci);
+
+	edac_mc_del_mc(&pdev->dev);
+	edac_mc_free(mci);
+
+	return 0;
+}
+
+static struct platform_driver cpc925_edac_driver = {
+	.probe = cpc925_probe,
+	.remove = cpc925_remove,
+	.driver = {
+		   .name = "cpc925_edac",
+	}
+};
+
+static int __init cpc925_edac_init(void)
+{
+	int ret = 0;
+
+	printk(KERN_INFO "IBM CPC925 EDAC driver " CPC925_EDAC_REVISION "\n");
+	printk(KERN_INFO "\t(c) 2008 Wind River Systems, Inc\n");
+
+	/* Only support POLL mode so far */
+	edac_op_state = EDAC_OPSTATE_POLL;
+
+	ret = platform_driver_register(&cpc925_edac_driver);
+	if (ret) {
+		printk(KERN_WARNING "Failed to register %s\n",
+			CPC925_EDAC_MOD_STR);
+	}
+
+	return ret;
+}
+
+static void __exit cpc925_edac_exit(void)
+{
+	platform_driver_unregister(&cpc925_edac_driver);
+}
+
+module_init(cpc925_edac_init);
+module_exit(cpc925_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
+MODULE_DESCRIPTION("IBM CPC925 Bridge and MC EDAC kernel module");
diff -druN linux-libre-2.6.30-gnu/drivers/edac/e752x_edac.c linux-libre-2.6.31-gnu/drivers/edac/e752x_edac.c
--- linux-libre-2.6.30-gnu/drivers/edac/e752x_edac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/e752x_edac.c	2009-09-09 18:13:59.000000000 -0400
@@ -1084,7 +1084,7 @@
 	struct pci_dev *dev = pvt->dev_d0f1;
 	int enable = 1;
 
-	/* Allow module paramter override, else see if CPU supports parity */
+	/* Allow module parameter override, else see if CPU supports parity */
 	if (sysbus_parity != -1) {
 		enable = sysbus_parity;
 	} else if (cpu_id[0] &&
diff -druN linux-libre-2.6.30-gnu/drivers/edac/edac_core.h linux-libre-2.6.31-gnu/drivers/edac/edac_core.h
--- linux-libre-2.6.30-gnu/drivers/edac/edac_core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/edac_core.h	2009-09-09 18:13:59.000000000 -0400
@@ -76,10 +76,11 @@
 extern int edac_debug_level;
 
 #ifndef CONFIG_EDAC_DEBUG_VERBOSE
-#define edac_debug_printk(level, fmt, arg...)                            \
-	do {                                                             \
-		if (level <= edac_debug_level)                           \
-			edac_printk(KERN_DEBUG, EDAC_DEBUG, fmt, ##arg); \
+#define edac_debug_printk(level, fmt, arg...)                           \
+	do {                                                            \
+		if (level <= edac_debug_level)                          \
+			edac_printk(KERN_DEBUG, EDAC_DEBUG,		\
+				    "%s: " fmt, __func__, ##arg);	\
 	} while (0)
 #else  /* CONFIG_EDAC_DEBUG_VERBOSE */
 #define edac_debug_printk(level, fmt, arg...)                            \
@@ -149,6 +150,8 @@
 	MEM_FB_DDR2,		/* fully buffered DDR2 */
 	MEM_RDDR2,		/* Registered DDR2 RAM */
 	MEM_XDR,		/* Rambus XDR */
+	MEM_DDR3,		/* DDR3 RAM */
+	MEM_RDDR3,		/* Registered DDR3 RAM */
 };
 
 #define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
@@ -166,6 +169,8 @@
 #define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
 #define MEM_FLAG_RDDR2          BIT(MEM_RDDR2)
 #define MEM_FLAG_XDR            BIT(MEM_XDR)
+#define MEM_FLAG_DDR3		 BIT(MEM_DDR3)
+#define MEM_FLAG_RDDR3		 BIT(MEM_RDDR3)
 
 /* chipset Error Detection and Correction capabilities and mode */
 enum edac_type {
@@ -840,6 +845,7 @@
 				int inst_nr, int block_nr, const char *msg);
 extern void edac_device_handle_ce(struct edac_device_ctl_info *edac_dev,
 				int inst_nr, int block_nr, const char *msg);
+extern int edac_device_alloc_index(void);
 
 /*
  * edac_pci APIs
diff -druN linux-libre-2.6.30-gnu/drivers/edac/edac_device.c linux-libre-2.6.31-gnu/drivers/edac/edac_device.c
--- linux-libre-2.6.30-gnu/drivers/edac/edac_device.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/edac_device.c	2009-09-09 18:13:59.000000000 -0400
@@ -490,6 +490,20 @@
 	mutex_unlock(&device_ctls_mutex);
 }
 
+/*
+ * edac_device_alloc_index: Allocate a unique device index number
+ *
+ * Return:
+ *	allocated index number
+ */
+int edac_device_alloc_index(void)
+{
+	static atomic_t device_indexes = ATOMIC_INIT(0);
+
+	return atomic_inc_return(&device_indexes) - 1;
+}
+EXPORT_SYMBOL_GPL(edac_device_alloc_index);
+
 /**
  * edac_device_add_device: Insert the 'edac_dev' structure into the
  * edac_device global list and create sysfs entries associated with
diff -druN linux-libre-2.6.30-gnu/drivers/edac/edac_mc_sysfs.c linux-libre-2.6.31-gnu/drivers/edac/edac_mc_sysfs.c
--- linux-libre-2.6.30-gnu/drivers/edac/edac_mc_sysfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/edac_mc_sysfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -94,7 +94,9 @@
 	[MEM_DDR2] = "Unbuffered-DDR2",
 	[MEM_FB_DDR2] = "FullyBuffered-DDR2",
 	[MEM_RDDR2] = "Registered-DDR2",
-	[MEM_XDR] = "XDR"
+	[MEM_XDR] = "XDR",
+	[MEM_DDR3] = "Unbuffered-DDR3",
+	[MEM_RDDR3] = "Registered-DDR3"
 };
 
 static const char *dev_types[] = {
diff -druN linux-libre-2.6.30-gnu/drivers/edac/Kconfig linux-libre-2.6.31-gnu/drivers/edac/Kconfig
--- linux-libre-2.6.30-gnu/drivers/edac/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -5,7 +5,7 @@
 #
 
 menuconfig EDAC
-	bool "EDAC - error detection and reporting"
+	bool "EDAC (Error Detection And Correction) reporting"
 	depends on HAS_IOMEM
 	depends on X86 || PPC
 	help
@@ -49,7 +49,6 @@
 
 config EDAC_MM_EDAC
 	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
-	default y
 	help
 	  Some systems are able to detect and correct errors in main
 	  memory.  EDAC can report statistics on memory error
@@ -58,6 +57,31 @@
 	  occurred so that a particular failing memory module can be
 	  replaced.  If unsure, select 'Y'.
 
+config EDAC_AMD64
+	tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
+	depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI
+	help
+	  Support for error detection and correction on the AMD 64
+	  Families of Memory Controllers (K8, F10h and F11h)
+
+config EDAC_AMD64_ERROR_INJECTION
+	bool "Sysfs Error Injection facilities"
+	depends on EDAC_AMD64
+	help
+	  Recent Opterons (Family 10h and later) provide for Memory Error
+	  Injection into the ECC detection circuits. The amd64_edac module
+	  allows the operator/user to inject Uncorrectable and Correctable
+	  errors into DRAM.
+
+	  When enabled, in each of the respective memory controller directories
+	  (/sys/devices/system/edac/mc/mcX), there are 3 input files:
+
+	  - inject_section (0..3, 16-byte section of 64-byte cacheline),
+	  - inject_word (0..8, 16-bit word of 16-byte section),
+	  - inject_ecc_vector (hex ecc vector: select bits of inject word)
+
+	  In addition, there are two control files, inject_read and inject_write,
+	  which trigger the DRAM ECC Read and Write respectively.
 
 config EDAC_AMD76X
 	tristate "AMD 76x (760, 762, 768)"
@@ -208,4 +232,13 @@
 	  Note, add more Kconfig dependency if it's adopted
 	  on some machine other than Maple.
 
+config EDAC_CPC925
+	tristate "IBM CPC925 Memory Controller (PPC970FX)"
+	depends on EDAC_MM_EDAC && PPC64
+	help
+	  Support for error detection and correction on the
+	  IBM CPC925 Bridge and Memory Controller, which is
+	  a companion chip to the PowerPC 970 family of
+	  processors.
+
 endif # EDAC
diff -druN linux-libre-2.6.30-gnu/drivers/edac/Makefile linux-libre-2.6.31-gnu/drivers/edac/Makefile
--- linux-libre-2.6.30-gnu/drivers/edac/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 endif
 
 obj-$(CONFIG_EDAC_AMD76X)		+= amd76x_edac.o
+obj-$(CONFIG_EDAC_CPC925)		+= cpc925_edac.o
 obj-$(CONFIG_EDAC_I5000)		+= i5000_edac.o
 obj-$(CONFIG_EDAC_I5100)		+= i5100_edac.o
 obj-$(CONFIG_EDAC_I5400)		+= i5400_edac.o
@@ -30,6 +31,13 @@
 obj-$(CONFIG_EDAC_X38)			+= x38_edac.o
 obj-$(CONFIG_EDAC_I82860)		+= i82860_edac.o
 obj-$(CONFIG_EDAC_R82600)		+= r82600_edac.o
+
+amd64_edac_mod-y :=  amd64_edac_err_types.o amd64_edac.o
+amd64_edac_mod-$(CONFIG_EDAC_DEBUG) += amd64_edac_dbg.o
+amd64_edac_mod-$(CONFIG_EDAC_AMD64_ERROR_INJECTION) += amd64_edac_inj.o
+
+obj-$(CONFIG_EDAC_AMD64)		+= amd64_edac_mod.o
+
 obj-$(CONFIG_EDAC_PASEMI)		+= pasemi_edac.o
 obj-$(CONFIG_EDAC_MPC85XX)		+= mpc85xx_edac.o
 obj-$(CONFIG_EDAC_MV64X60)		+= mv64x60_edac.o
diff -druN linux-libre-2.6.30-gnu/drivers/edac/mpc85xx_edac.c linux-libre-2.6.31-gnu/drivers/edac/mpc85xx_edac.c
--- linux-libre-2.6.30-gnu/drivers/edac/mpc85xx_edac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/mpc85xx_edac.c	2009-09-09 18:13:59.000000000 -0400
@@ -757,6 +757,9 @@
 		case DSC_SDTYPE_DDR2:
 			mtype = MEM_RDDR2;
 			break;
+		case DSC_SDTYPE_DDR3:
+			mtype = MEM_RDDR3;
+			break;
 		default:
 			mtype = MEM_UNKNOWN;
 			break;
@@ -769,6 +772,9 @@
 		case DSC_SDTYPE_DDR2:
 			mtype = MEM_DDR2;
 			break;
+		case DSC_SDTYPE_DDR3:
+			mtype = MEM_DDR3;
+			break;
 		default:
 			mtype = MEM_UNKNOWN;
 			break;
diff -druN linux-libre-2.6.30-gnu/drivers/edac/mpc85xx_edac.h linux-libre-2.6.31-gnu/drivers/edac/mpc85xx_edac.h
--- linux-libre-2.6.30-gnu/drivers/edac/mpc85xx_edac.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/mpc85xx_edac.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,7 @@
 
 #define DSC_SDTYPE_DDR		0x02000000
 #define DSC_SDTYPE_DDR2		0x03000000
+#define DSC_SDTYPE_DDR3		0x07000000
 #define DSC_X32_EN	0x00000020
 
 /* Err_Int_En */
diff -druN linux-libre-2.6.30-gnu/drivers/edac/x38_edac.c linux-libre-2.6.31-gnu/drivers/edac/x38_edac.c
--- linux-libre-2.6.30-gnu/drivers/edac/x38_edac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/edac/x38_edac.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,7 @@
 /* Intel X38 register addresses - device 0 function 0 - DRAM Controller */
 
 #define X38_MCHBAR_LOW	0x48	/* MCH Memory Mapped Register BAR */
-#define X38_MCHBAR_HIGH	0x4b
+#define X38_MCHBAR_HIGH	0x4c
 #define X38_MCHBAR_MASK	0xfffffc000ULL	/* bits 35:14 */
 #define X38_MMR_WINDOW_SIZE	16384
 
diff -druN linux-libre-2.6.30-gnu/drivers/eisa/eisa.ids linux-libre-2.6.31-gnu/drivers/eisa/eisa.ids
--- linux-libre-2.6.30-gnu/drivers/eisa/eisa.ids	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/eisa/eisa.ids	2009-09-09 18:13:59.000000000 -0400
@@ -1140,6 +1140,11 @@
 NON0401 "c't Universal Ethernet Adapter"
 NON0501 "c't Universal 16-Bit Sound Adapter"
 NON0601 "c't Universal 8-Bit Adapter"
+NPI0120 "Network Peripherals NP-EISA-1 FDDI Interface"
+NPI0221 "Network Peripherals NP-EISA-2 FDDI Interface"
+NPI0223 "Network Peripherals NP-EISA-2E Enhanced FDDI Interface"
+NPI0301 "Network Peripherals NP-EISA-3 FDDI Interface"
+NPI0303 "Network Peripherals NP-EISA-3E Enhanced FDDI Interface"
 NSS0011 "Newport Systems Solutions WNIC Adapter"
 NVL0701 "Novell NE3200 Bus Master Ethernet"
 NVL0702 "Novell NE3200T Bus Master Ethernet"
diff -druN linux-libre-2.6.30-gnu/drivers/eisa/pci_eisa.c linux-libre-2.6.31-gnu/drivers/eisa/pci_eisa.c
--- linux-libre-2.6.30-gnu/drivers/eisa/pci_eisa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/eisa/pci_eisa.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,11 +31,11 @@
 	}
 
 	pci_eisa_root.dev              = &pdev->dev;
-	pci_eisa_root.dev->driver_data = &pci_eisa_root;
 	pci_eisa_root.res	       = pdev->bus->resource[0];
 	pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
 	pci_eisa_root.slots	       = EISA_MAX_SLOTS;
 	pci_eisa_root.dma_mask         = pdev->dma_mask;
+	dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root);
 
 	if (eisa_root_register (&pci_eisa_root)) {
 		printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
diff -druN linux-libre-2.6.30-gnu/drivers/eisa/virtual_root.c linux-libre-2.6.31-gnu/drivers/eisa/virtual_root.c
--- linux-libre-2.6.30-gnu/drivers/eisa/virtual_root.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/eisa/virtual_root.c	2009-09-09 18:13:59.000000000 -0400
@@ -57,7 +57,7 @@
 
 	eisa_bus_root.force_probe = force_probe;
 	
-	eisa_root_dev.dev.driver_data = &eisa_bus_root;
+	dev_set_drvdata(&eisa_root_dev.dev, &eisa_bus_root);
 
 	if (eisa_root_register (&eisa_bus_root)) {
 		/* A real bridge may have been registered before
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/core-card.c linux-libre-2.6.31-gnu/drivers/firewire/core-card.c
--- linux-libre-2.6.30-gnu/drivers/firewire/core-card.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/core-card.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,567 @@
+/*
+ * 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/bug.h>
+#include <linux/completion.h>
+#include <linux/crc-itu-t.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+#include "core.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 matches
+	 * 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 void allocate_broadcast_channel(struct fw_card *card, int generation)
+{
+	int channel, bandwidth = 0;
+
+	fw_iso_resource_manage(card, generation, 1ULL << 31, &channel,
+			       &bandwidth, true, card->bm_transaction_data);
+	if (channel == 31) {
+		card->broadcast_channel_allocated = true;
+		device_for_each_child(card->device, (void *)(long)generation,
+				      fw_device_set_broadcast_channel);
+	}
+}
+
+static const char gap_count_table[] = {
+	63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
+};
+
+void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
+{
+	int scheduled;
+
+	fw_card_get(card);
+	scheduled = schedule_delayed_work(&card->work, delay);
+	if (!scheduled)
+		fw_card_put(card);
+}
+
+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_device;
+	struct fw_node *root_node;
+	unsigned long flags;
+	int root_id, new_root_id, irm_id, local_id;
+	int gap_count, generation, grace, rcode;
+	bool do_reset = false;
+	bool root_device_is_running;
+	bool root_device_is_cmc;
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	if (card->local_node == NULL) {
+		spin_unlock_irqrestore(&card->lock, flags);
+		goto out_put_card;
+	}
+
+	generation = card->generation;
+	root_node = card->root_node;
+	fw_node_get(root_node);
+	root_device = root_node->data;
+	root_device_is_running = root_device &&
+			atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
+	root_device_is_cmc = root_device && root_device->cmc;
+	root_id  = root_node->node_id;
+	irm_id   = card->irm_node->node_id;
+	local_id = card->local_node->node_id;
+
+	grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
+
+	if (is_next_generation(generation, card->bm_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.
+		 */
+
+		if (!card->irm_node->link_on) {
+			new_root_id = local_id;
+			fw_notify("IRM has link off, making local node (%02x) root.\n",
+				  new_root_id);
+			goto pick_me;
+		}
+
+		card->bm_transaction_data[0] = cpu_to_be32(0x3f);
+		card->bm_transaction_data[1] = cpu_to_be32(local_id);
+
+		spin_unlock_irqrestore(&card->lock, flags);
+
+		rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
+				irm_id, generation, SCODE_100,
+				CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
+				card->bm_transaction_data,
+				sizeof(card->bm_transaction_data));
+
+		if (rcode == RCODE_GENERATION)
+			/* Another bus reset, BM work has been rescheduled. */
+			goto out;
+
+		if (rcode == RCODE_COMPLETE &&
+		    card->bm_transaction_data[0] != cpu_to_be32(0x3f)) {
+
+			/* Somebody else is BM.  Only act as IRM. */
+			if (local_id == irm_id)
+				allocate_broadcast_channel(card, generation);
+
+			goto out;
+		}
+
+		spin_lock_irqsave(&card->lock, flags);
+
+		if (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 = local_id;
+			fw_notify("BM lock failed, making local node (%02x) root.\n",
+				  new_root_id);
+			goto pick_me;
+		}
+	} else if (card->bm_generation != generation) {
+		/*
+		 * We weren't BM in the last generation, and the last
+		 * bus reset is less than 125ms ago.  Reschedule this job.
+		 */
+		spin_unlock_irqrestore(&card->lock, flags);
+		fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));
+		goto out;
+	}
+
+	/*
+	 * 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_device == NULL) {
+		/*
+		 * Either link_on is false, or we failed to read the
+		 * config rom.  In either case, pick another root.
+		 */
+		new_root_id = local_id;
+	} else if (!root_device_is_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);
+		goto out;
+	} else if (root_device_is_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 = local_id;
+	}
+
+ pick_me:
+	/*
+	 * Pick a gap count from 1394a table E-1.  The table doesn't cover
+	 * the typically much larger 1394b beta repeater delays though.
+	 */
+	if (!card->beta_repeaters_present &&
+	    root_node->max_hops < ARRAY_SIZE(gap_count_table))
+		gap_count = gap_count_table[root_node->max_hops];
+	else
+		gap_count = 63;
+
+	/*
+	 * Finally, figure out if we should do a reset or not.  If we have
+	 * done less than 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 = true;
+
+	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);
+		/* Will allocate broadcast channel after the reset. */
+	} else {
+		if (local_id == irm_id)
+			allocate_broadcast_channel(card, generation);
+	}
+
+ out:
+	fw_node_put(root_node);
+ out_put_card:
+	fw_card_put(card);
+}
+
+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);
+
+	card->index = atomic_inc_return(&index);
+	card->driver = driver;
+	card->device = device;
+	card->current_tlabel = 0;
+	card->tlabel_mask = 0;
+	card->color = 0;
+	card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;
+
+	kref_init(&card->kref);
+	init_completion(&card->done);
+	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;
+	int ret;
+
+	card->max_receive = max_receive;
+	card->link_speed = link_speed;
+	card->guid = guid;
+
+	mutex_lock(&card_mutex);
+	config_rom = generate_config_rom(card, &length);
+	list_add_tail(&card->link, &card_list);
+	mutex_unlock(&card_mutex);
+
+	ret = card->driver->enable(card, config_rom, length);
+	if (ret < 0) {
+		mutex_lock(&card_mutex);
+		list_del(&card->link);
+		mutex_unlock(&card_mutex);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(fw_card_add);
+
+
+/*
+ * The next few functions implement a dummy driver that is used 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 (and failed) by the dummy driver
+ * instead of calling into the module.  Only functions for iso context
+ * shutdown still need to be provided by the card driver.
+ */
+
+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 const struct fw_card_driver dummy_driver_template = {
+	.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_card_release(struct kref *kref)
+{
+	struct fw_card *card = container_of(kref, struct fw_card, kref);
+
+	complete(&card->done);
+}
+
+void fw_core_remove_card(struct fw_card *card)
+{
+	struct fw_card_driver dummy_driver = dummy_driver_template;
+
+	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_init(&card->link);
+	mutex_unlock(&card_mutex);
+
+	/* Switch off most of the card driver interface. */
+	dummy_driver.free_iso_context	= card->driver->free_iso_context;
+	dummy_driver.stop_iso		= card->driver->stop_iso;
+	card->driver = &dummy_driver;
+
+	fw_destroy_nodes(card);
+
+	/* Wait for all users, especially device workqueue jobs, to finish. */
+	fw_card_put(card);
+	wait_for_completion(&card->done);
+
+	WARN_ON(!list_empty(&card->transaction_list));
+	del_timer_sync(&card->flush_timer);
+}
+EXPORT_SYMBOL(fw_core_remove_card);
+
+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 -druN linux-libre-2.6.30-gnu/drivers/firewire/core-cdev.c linux-libre-2.6.31-gnu/drivers/firewire/core-cdev.c
--- linux-libre-2.6.30-gnu/drivers/firewire/core-cdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/core-cdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1460 @@
+/*
+ * 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/compat.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-cdev.h>
+#include <linux/idr.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/preempt.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <asm/system.h>
+
+#include "core.h"
+
+struct client {
+	u32 version;
+	struct fw_device *device;
+
+	spinlock_t lock;
+	bool in_shutdown;
+	struct idr resource_idr;
+	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;
+	struct kref kref;
+};
+
+static inline void client_get(struct client *client)
+{
+	kref_get(&client->kref);
+}
+
+static void client_release(struct kref *kref)
+{
+	struct client *client = container_of(kref, struct client, kref);
+
+	fw_device_put(client->device);
+	kfree(client);
+}
+
+static void client_put(struct client *client)
+{
+	kref_put(&client->kref, client_release);
+}
+
+struct client_resource;
+typedef void (*client_resource_release_fn_t)(struct client *,
+					     struct client_resource *);
+struct client_resource {
+	client_resource_release_fn_t release;
+	int handle;
+};
+
+struct address_handler_resource {
+	struct client_resource resource;
+	struct fw_address_handler handler;
+	__u64 closure;
+	struct client *client;
+};
+
+struct outbound_transaction_resource {
+	struct client_resource resource;
+	struct fw_transaction transaction;
+};
+
+struct inbound_transaction_resource {
+	struct client_resource resource;
+	struct fw_request *request;
+	void *data;
+	size_t length;
+};
+
+struct descriptor_resource {
+	struct client_resource resource;
+	struct fw_descriptor descriptor;
+	u32 data[0];
+};
+
+struct iso_resource {
+	struct client_resource resource;
+	struct client *client;
+	/* Schedule work and access todo only with client->lock held. */
+	struct delayed_work work;
+	enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,
+	      ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo;
+	int generation;
+	u64 channels;
+	s32 bandwidth;
+	__be32 transaction_data[2];
+	struct iso_resource_event *e_alloc, *e_dealloc;
+};
+
+static void schedule_iso_resource(struct iso_resource *);
+static void release_iso_resource(struct client *, struct client_resource *);
+
+/*
+ * dequeue_event() just kfree()'s the event, so the event has to be
+ * the first field in a struct XYZ_event.
+ */
+struct event {
+	struct { void *data; size_t size; } v[2];
+	struct list_head link;
+};
+
+struct bus_reset_event {
+	struct event event;
+	struct fw_cdev_event_bus_reset reset;
+};
+
+struct outbound_transaction_event {
+	struct event event;
+	struct client *client;
+	struct outbound_transaction_resource r;
+	struct fw_cdev_event_response response;
+};
+
+struct inbound_transaction_event {
+	struct event event;
+	struct fw_cdev_event_request request;
+};
+
+struct iso_interrupt_event {
+	struct event event;
+	struct fw_cdev_event_iso_interrupt interrupt;
+};
+
+struct iso_resource_event {
+	struct event event;
+	struct fw_cdev_event_iso_resource resource;
+};
+
+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;
+
+	device = fw_device_get_by_devt(inode->i_rdev);
+	if (device == NULL)
+		return -ENODEV;
+
+	if (fw_device_is_shutdown(device)) {
+		fw_device_put(device);
+		return -ENODEV;
+	}
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (client == NULL) {
+		fw_device_put(device);
+		return -ENOMEM;
+	}
+
+	client->device = device;
+	spin_lock_init(&client->lock);
+	idr_init(&client->resource_idr);
+	INIT_LIST_HEAD(&client->event_list);
+	init_waitqueue_head(&client->wait);
+	kref_init(&client->kref);
+
+	file->private_data = client;
+
+	mutex_lock(&device->client_list_mutex);
+	list_add_tail(&client->link, &device->client_list);
+	mutex_unlock(&device->client_list_mutex);
+
+	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);
+	if (client->in_shutdown)
+		kfree(event);
+	else
+		list_add_tail(&event->link, &client->event_list);
+	spin_unlock_irqrestore(&client->lock, flags);
+
+	wake_up_interruptible(&client->wait);
+}
+
+static int dequeue_event(struct client *client,
+			 char __user *buffer, size_t count)
+{
+	struct event *event;
+	size_t size, total;
+	int i, ret;
+
+	ret = wait_event_interruptible(client->wait,
+			!list_empty(&client->event_list) ||
+			fw_device_is_shutdown(client->device));
+	if (ret < 0)
+		return ret;
+
+	if (list_empty(&client->event_list) &&
+		       fw_device_is_shutdown(client->device))
+		return -ENODEV;
+
+	spin_lock_irq(&client->lock);
+	event = list_first_entry(&client->event_list, struct event, link);
+	list_del(&event->link);
+	spin_unlock_irq(&client->lock);
+
+	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)) {
+			ret = -EFAULT;
+			goto out;
+		}
+		total += size;
+	}
+	ret = total;
+
+ out:
+	kfree(event);
+
+	return ret;
+}
+
+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;
+
+	spin_lock_irq(&card->lock);
+
+	event->closure	     = client->bus_reset_closure;
+	event->type          = FW_CDEV_EVENT_BUS_RESET;
+	event->generation    = client->device->generation;
+	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;
+
+	spin_unlock_irq(&card->lock);
+}
+
+static void for_each_client(struct fw_device *device,
+			    void (*callback)(struct client *client))
+{
+	struct client *c;
+
+	mutex_lock(&device->client_list_mutex);
+	list_for_each_entry(c, &device->client_list, link)
+		callback(c);
+	mutex_unlock(&device->client_list_mutex);
+}
+
+static int schedule_reallocations(int id, void *p, void *data)
+{
+	struct client_resource *r = p;
+
+	if (r->release == release_iso_resource)
+		schedule_iso_resource(container_of(r,
+					struct iso_resource, resource));
+	return 0;
+}
+
+static void queue_bus_reset_event(struct client *client)
+{
+	struct bus_reset_event *e;
+
+	e = kzalloc(sizeof(*e), GFP_KERNEL);
+	if (e == NULL) {
+		fw_notify("Out of memory when allocating bus reset event\n");
+		return;
+	}
+
+	fill_bus_reset_event(&e->reset, client);
+
+	queue_event(client, &e->event,
+		    &e->reset, sizeof(e->reset), NULL, 0);
+
+	spin_lock_irq(&client->lock);
+	idr_for_each(&client->resource_idr, schedule_reallocations, client);
+	spin_unlock_irq(&client->lock);
+}
+
+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;
+	unsigned long ret = 0;
+
+	client->version = get_info->version;
+	get_info->version = FW_CDEV_VERSION;
+	get_info->card = client->device->card->index;
+
+	down_read(&fw_device_rwsem);
+
+	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;
+
+		ret = copy_to_user(uptr, client->device->config_rom,
+				   min(want, have));
+	}
+	get_info->rom_length = client->device->config_rom_length * 4;
+
+	up_read(&fw_device_rwsem);
+
+	if (ret != 0)
+		return -EFAULT;
+
+	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;
+	}
+
+	return 0;
+}
+
+static int add_client_resource(struct client *client,
+			       struct client_resource *resource, gfp_t gfp_mask)
+{
+	unsigned long flags;
+	int ret;
+
+ retry:
+	if (idr_pre_get(&client->resource_idr, gfp_mask) == 0)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&client->lock, flags);
+	if (client->in_shutdown)
+		ret = -ECANCELED;
+	else
+		ret = idr_get_new(&client->resource_idr, resource,
+				  &resource->handle);
+	if (ret >= 0) {
+		client_get(client);
+		if (resource->release == release_iso_resource)
+			schedule_iso_resource(container_of(resource,
+						struct iso_resource, resource));
+	}
+	spin_unlock_irqrestore(&client->lock, flags);
+
+	if (ret == -EAGAIN)
+		goto retry;
+
+	return ret < 0 ? ret : 0;
+}
+
+static int release_client_resource(struct client *client, u32 handle,
+				   client_resource_release_fn_t release,
+				   struct client_resource **resource)
+{
+	struct client_resource *r;
+
+	spin_lock_irq(&client->lock);
+	if (client->in_shutdown)
+		r = NULL;
+	else
+		r = idr_find(&client->resource_idr, handle);
+	if (r && r->release == release)
+		idr_remove(&client->resource_idr, handle);
+	spin_unlock_irq(&client->lock);
+
+	if (!(r && r->release == release))
+		return -EINVAL;
+
+	if (resource)
+		*resource = r;
+	else
+		r->release(client, r);
+
+	client_put(client);
+
+	return 0;
+}
+
+static void release_transaction(struct client *client,
+				struct client_resource *resource)
+{
+	struct outbound_transaction_resource *r = container_of(resource,
+			struct outbound_transaction_resource, resource);
+
+	fw_cancel_transaction(client->device->card, &r->transaction);
+}
+
+static void complete_transaction(struct fw_card *card, int rcode,
+				 void *payload, size_t length, void *data)
+{
+	struct outbound_transaction_event *e = data;
+	struct fw_cdev_event_response *rsp = &e->response;
+	struct client *client = e->client;
+	unsigned long flags;
+
+	if (length < rsp->length)
+		rsp->length = length;
+	if (rcode == RCODE_COMPLETE)
+		memcpy(rsp->data, payload, rsp->length);
+
+	spin_lock_irqsave(&client->lock, flags);
+	/*
+	 * 1. If called while in shutdown, the idr tree must be left untouched.
+	 *    The idr handle will be removed and the client reference will be
+	 *    dropped later.
+	 * 2. If the call chain was release_client_resource ->
+	 *    release_transaction -> complete_transaction (instead of a normal
+	 *    conclusion of the transaction), i.e. if this resource was already
+	 *    unregistered from the idr, the client reference will be dropped
+	 *    by release_client_resource and we must not drop it here.
+	 */
+	if (!client->in_shutdown &&
+	    idr_find(&client->resource_idr, e->r.resource.handle)) {
+		idr_remove(&client->resource_idr, e->r.resource.handle);
+		/* Drop the idr's reference */
+		client_put(client);
+	}
+	spin_unlock_irqrestore(&client->lock, flags);
+
+	rsp->type = FW_CDEV_EVENT_RESPONSE;
+	rsp->rcode = rcode;
+
+	/*
+	 * In the case that sizeof(*rsp) doesn't align with the position of the
+	 * data, and the read is short, preserve an extra copy of the data
+	 * to stay compatible with a pre-2.6.27 bug.  Since the bug is harmless
+	 * for short reads and some apps depended on it, this is both safe
+	 * and prudent for compatibility.
+	 */
+	if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data))
+		queue_event(client, &e->event, rsp, sizeof(*rsp),
+			    rsp->data, rsp->length);
+	else
+		queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
+			    NULL, 0);
+
+	/* Drop the transaction callback's reference */
+	client_put(client);
+}
+
+static int init_request(struct client *client,
+			struct fw_cdev_send_request *request,
+			int destination_id, int speed)
+{
+	struct outbound_transaction_event *e;
+	int ret;
+
+	if (request->tcode != TCODE_STREAM_DATA &&
+	    (request->length > 4096 || request->length > 512 << speed))
+		return -EIO;
+
+	e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
+	if (e == NULL)
+		return -ENOMEM;
+
+	e->client = client;
+	e->response.length = request->length;
+	e->response.closure = request->closure;
+
+	if (request->data &&
+	    copy_from_user(e->response.data,
+			   u64_to_uptr(request->data), request->length)) {
+		ret = -EFAULT;
+		goto failed;
+	}
+
+	e->r.resource.release = release_transaction;
+	ret = add_client_resource(client, &e->r.resource, GFP_KERNEL);
+	if (ret < 0)
+		goto failed;
+
+	/* Get a reference for the transaction callback */
+	client_get(client);
+
+	fw_send_request(client->device->card, &e->r.transaction,
+			request->tcode, destination_id, request->generation,
+			speed, request->offset, e->response.data,
+			request->length, complete_transaction, e);
+	return 0;
+
+ failed:
+	kfree(e);
+
+	return ret;
+}
+
+static int ioctl_send_request(struct client *client, void *buffer)
+{
+	struct fw_cdev_send_request *request = buffer;
+
+	switch (request->tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+	case TCODE_WRITE_BLOCK_REQUEST:
+	case TCODE_READ_QUADLET_REQUEST:
+	case TCODE_READ_BLOCK_REQUEST:
+	case TCODE_LOCK_MASK_SWAP:
+	case TCODE_LOCK_COMPARE_SWAP:
+	case TCODE_LOCK_FETCH_ADD:
+	case TCODE_LOCK_LITTLE_ADD:
+	case TCODE_LOCK_BOUNDED_ADD:
+	case TCODE_LOCK_WRAP_ADD:
+	case TCODE_LOCK_VENDOR_DEPENDENT:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return init_request(client, request, client->device->node_id,
+			    client->device->max_speed);
+}
+
+static void release_request(struct client *client,
+			    struct client_resource *resource)
+{
+	struct inbound_transaction_resource *r = container_of(resource,
+			struct inbound_transaction_resource, resource);
+
+	fw_send_response(client->device->card, r->request,
+			 RCODE_CONFLICT_ERROR);
+	kfree(r);
+}
+
+static void handle_request(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 address_handler_resource *handler = callback_data;
+	struct inbound_transaction_resource *r;
+	struct inbound_transaction_event *e;
+	int ret;
+
+	r = kmalloc(sizeof(*r), GFP_ATOMIC);
+	e = kmalloc(sizeof(*e), GFP_ATOMIC);
+	if (r == NULL || e == NULL)
+		goto failed;
+
+	r->request = request;
+	r->data    = payload;
+	r->length  = length;
+
+	r->resource.release = release_request;
+	ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
+	if (ret < 0)
+		goto failed;
+
+	e->request.type    = FW_CDEV_EVENT_REQUEST;
+	e->request.tcode   = tcode;
+	e->request.offset  = offset;
+	e->request.length  = length;
+	e->request.handle  = r->resource.handle;
+	e->request.closure = handler->closure;
+
+	queue_event(handler->client, &e->event,
+		    &e->request, sizeof(e->request), payload, length);
+	return;
+
+ failed:
+	kfree(r);
+	kfree(e);
+	fw_send_response(card, request, RCODE_CONFLICT_ERROR);
+}
+
+static void release_address_handler(struct client *client,
+				    struct client_resource *resource)
+{
+	struct address_handler_resource *r =
+	    container_of(resource, struct address_handler_resource, resource);
+
+	fw_core_remove_address_handler(&r->handler);
+	kfree(r);
+}
+
+static int ioctl_allocate(struct client *client, void *buffer)
+{
+	struct fw_cdev_allocate *request = buffer;
+	struct address_handler_resource *r;
+	struct fw_address_region region;
+	int ret;
+
+	r = kmalloc(sizeof(*r), GFP_KERNEL);
+	if (r == NULL)
+		return -ENOMEM;
+
+	region.start = request->offset;
+	region.end = request->offset + request->length;
+	r->handler.length = request->length;
+	r->handler.address_callback = handle_request;
+	r->handler.callback_data = r;
+	r->closure = request->closure;
+	r->client = client;
+
+	ret = fw_core_add_address_handler(&r->handler, &region);
+	if (ret < 0) {
+		kfree(r);
+		return ret;
+	}
+
+	r->resource.release = release_address_handler;
+	ret = add_client_resource(client, &r->resource, GFP_KERNEL);
+	if (ret < 0) {
+		release_address_handler(client, &r->resource);
+		return ret;
+	}
+	request->handle = r->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,
+				       release_address_handler, NULL);
+}
+
+static int ioctl_send_response(struct client *client, void *buffer)
+{
+	struct fw_cdev_send_response *request = buffer;
+	struct client_resource *resource;
+	struct inbound_transaction_resource *r;
+
+	if (release_client_resource(client, request->handle,
+				    release_request, &resource) < 0)
+		return -EINVAL;
+
+	r = container_of(resource, struct inbound_transaction_resource,
+			 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);
+}
+
+static void release_descriptor(struct client *client,
+			       struct client_resource *resource)
+{
+	struct descriptor_resource *r =
+		container_of(resource, struct descriptor_resource, resource);
+
+	fw_core_remove_descriptor(&r->descriptor);
+	kfree(r);
+}
+
+static int ioctl_add_descriptor(struct client *client, void *buffer)
+{
+	struct fw_cdev_add_descriptor *request = buffer;
+	struct descriptor_resource *r;
+	int ret;
+
+	/* Access policy: Allow this ioctl only on local nodes' device files. */
+	if (!client->device->is_local)
+		return -ENOSYS;
+
+	if (request->length > 256)
+		return -EINVAL;
+
+	r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL);
+	if (r == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(r->data,
+			   u64_to_uptr(request->data), request->length * 4)) {
+		ret = -EFAULT;
+		goto failed;
+	}
+
+	r->descriptor.length    = request->length;
+	r->descriptor.immediate = request->immediate;
+	r->descriptor.key       = request->key;
+	r->descriptor.data      = r->data;
+
+	ret = fw_core_add_descriptor(&r->descriptor);
+	if (ret < 0)
+		goto failed;
+
+	r->resource.release = release_descriptor;
+	ret = add_client_resource(client, &r->resource, GFP_KERNEL);
+	if (ret < 0) {
+		fw_core_remove_descriptor(&r->descriptor);
+		goto failed;
+	}
+	request->handle = r->resource.handle;
+
+	return 0;
+ failed:
+	kfree(r);
+
+	return ret;
+}
+
+static int ioctl_remove_descriptor(struct client *client, void *buffer)
+{
+	struct fw_cdev_remove_descriptor *request = buffer;
+
+	return release_client_resource(client, request->handle,
+				       release_descriptor, 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_event *e;
+
+	e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC);
+	if (e == NULL)
+		return;
+
+	e->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
+	e->interrupt.closure   = client->iso_closure;
+	e->interrupt.cycle     = cycle;
+	e->interrupt.header_length = header_length;
+	memcpy(e->interrupt.header, header, header_length);
+	queue_event(client, &e->event, &e->interrupt,
+		    sizeof(e->interrupt) + header_length, NULL, 0);
+}
+
+static int ioctl_create_iso_context(struct client *client, void *buffer)
+{
+	struct fw_cdev_create_iso_context *request = buffer;
+	struct fw_iso_context *context;
+
+	/* We only support one context at this time. */
+	if (client->iso_context != NULL)
+		return -EBUSY;
+
+	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;
+	}
+
+	context =  fw_iso_context_create(client->device->card,
+					 request->type,
+					 request->channel,
+					 request->speed,
+					 request->header_size,
+					 iso_callback, client);
+	if (IS_ERR(context))
+		return PTR_ERR(context);
+
+	client->iso_closure = request->closure;
+	client->iso_context = context;
+
+	/* We only support one context at this time. */
+	request->handle = 0;
+
+	return 0;
+}
+
+/* Macros for decoding the iso packet control header. */
+#define GET_PAYLOAD_LENGTH(v)	((v) & 0xffff)
+#define GET_INTERRUPT(v)	(((v) >> 16) & 0x01)
+#define GET_SKIP(v)		(((v) >> 17) & 0x01)
+#define GET_TAG(v)		(((v) >> 18) & 0x03)
+#define GET_SY(v)		(((v) >> 20) & 0x0f)
+#define GET_HEADER_LENGTH(v)	(((v) >> 24) & 0xff)
+
+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;
+	u32 control;
+	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;
+	}
+
+	p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets);
+
+	if (!access_ok(VERIFY_READ, p, request->size))
+		return -EFAULT;
+
+	end = (void __user *)p + request->size;
+	count = 0;
+	while (p < end) {
+		if (get_user(control, &p->control))
+			return -EFAULT;
+		u.packet.payload_length = GET_PAYLOAD_LENGTH(control);
+		u.packet.interrupt = GET_INTERRUPT(control);
+		u.packet.skip = GET_SKIP(control);
+		u.packet.tag = GET_TAG(control);
+		u.packet.sy = GET_SY(control);
+		u.packet.header_length = GET_HEADER_LENGTH(control);
+
+		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 (client->iso_context == NULL || 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 (client->iso_context == NULL || request->handle != 0)
+		return -EINVAL;
+
+	return fw_iso_context_stop(client->iso_context);
+}
+
+static int ioctl_get_cycle_timer(struct client *client, void *buffer)
+{
+	struct fw_cdev_get_cycle_timer *request = buffer;
+	struct fw_card *card = client->device->card;
+	unsigned long long bus_time;
+	struct timeval tv;
+	unsigned long flags;
+
+	preempt_disable();
+	local_irq_save(flags);
+
+	bus_time = card->driver->get_bus_time(card);
+	do_gettimeofday(&tv);
+
+	local_irq_restore(flags);
+	preempt_enable();
+
+	request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
+	request->cycle_timer = bus_time & 0xffffffff;
+	return 0;
+}
+
+static void iso_resource_work(struct work_struct *work)
+{
+	struct iso_resource_event *e;
+	struct iso_resource *r =
+			container_of(work, struct iso_resource, work.work);
+	struct client *client = r->client;
+	int generation, channel, bandwidth, todo;
+	bool skip, free, success;
+
+	spin_lock_irq(&client->lock);
+	generation = client->device->generation;
+	todo = r->todo;
+	/* Allow 1000ms grace period for other reallocations. */
+	if (todo == ISO_RES_ALLOC &&
+	    time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
+		if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3)))
+			client_get(client);
+		skip = true;
+	} else {
+		/* We could be called twice within the same generation. */
+		skip = todo == ISO_RES_REALLOC &&
+		       r->generation == generation;
+	}
+	free = todo == ISO_RES_DEALLOC ||
+	       todo == ISO_RES_ALLOC_ONCE ||
+	       todo == ISO_RES_DEALLOC_ONCE;
+	r->generation = generation;
+	spin_unlock_irq(&client->lock);
+
+	if (skip)
+		goto out;
+
+	bandwidth = r->bandwidth;
+
+	fw_iso_resource_manage(client->device->card, generation,
+			r->channels, &channel, &bandwidth,
+			todo == ISO_RES_ALLOC ||
+			todo == ISO_RES_REALLOC ||
+			todo == ISO_RES_ALLOC_ONCE,
+			r->transaction_data);
+	/*
+	 * Is this generation outdated already?  As long as this resource sticks
+	 * in the idr, it will be scheduled again for a newer generation or at
+	 * shutdown.
+	 */
+	if (channel == -EAGAIN &&
+	    (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC))
+		goto out;
+
+	success = channel >= 0 || bandwidth > 0;
+
+	spin_lock_irq(&client->lock);
+	/*
+	 * Transit from allocation to reallocation, except if the client
+	 * requested deallocation in the meantime.
+	 */
+	if (r->todo == ISO_RES_ALLOC)
+		r->todo = ISO_RES_REALLOC;
+	/*
+	 * Allocation or reallocation failure?  Pull this resource out of the
+	 * idr and prepare for deletion, unless the client is shutting down.
+	 */
+	if (r->todo == ISO_RES_REALLOC && !success &&
+	    !client->in_shutdown &&
+	    idr_find(&client->resource_idr, r->resource.handle)) {
+		idr_remove(&client->resource_idr, r->resource.handle);
+		client_put(client);
+		free = true;
+	}
+	spin_unlock_irq(&client->lock);
+
+	if (todo == ISO_RES_ALLOC && channel >= 0)
+		r->channels = 1ULL << channel;
+
+	if (todo == ISO_RES_REALLOC && success)
+		goto out;
+
+	if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) {
+		e = r->e_alloc;
+		r->e_alloc = NULL;
+	} else {
+		e = r->e_dealloc;
+		r->e_dealloc = NULL;
+	}
+	e->resource.handle	= r->resource.handle;
+	e->resource.channel	= channel;
+	e->resource.bandwidth	= bandwidth;
+
+	queue_event(client, &e->event,
+		    &e->resource, sizeof(e->resource), NULL, 0);
+
+	if (free) {
+		cancel_delayed_work(&r->work);
+		kfree(r->e_alloc);
+		kfree(r->e_dealloc);
+		kfree(r);
+	}
+ out:
+	client_put(client);
+}
+
+static void schedule_iso_resource(struct iso_resource *r)
+{
+	client_get(r->client);
+	if (!schedule_delayed_work(&r->work, 0))
+		client_put(r->client);
+}
+
+static void release_iso_resource(struct client *client,
+				 struct client_resource *resource)
+{
+	struct iso_resource *r =
+		container_of(resource, struct iso_resource, resource);
+
+	spin_lock_irq(&client->lock);
+	r->todo = ISO_RES_DEALLOC;
+	schedule_iso_resource(r);
+	spin_unlock_irq(&client->lock);
+}
+
+static int init_iso_resource(struct client *client,
+		struct fw_cdev_allocate_iso_resource *request, int todo)
+{
+	struct iso_resource_event *e1, *e2;
+	struct iso_resource *r;
+	int ret;
+
+	if ((request->channels == 0 && request->bandwidth == 0) ||
+	    request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL ||
+	    request->bandwidth < 0)
+		return -EINVAL;
+
+	r  = kmalloc(sizeof(*r), GFP_KERNEL);
+	e1 = kmalloc(sizeof(*e1), GFP_KERNEL);
+	e2 = kmalloc(sizeof(*e2), GFP_KERNEL);
+	if (r == NULL || e1 == NULL || e2 == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	INIT_DELAYED_WORK(&r->work, iso_resource_work);
+	r->client	= client;
+	r->todo		= todo;
+	r->generation	= -1;
+	r->channels	= request->channels;
+	r->bandwidth	= request->bandwidth;
+	r->e_alloc	= e1;
+	r->e_dealloc	= e2;
+
+	e1->resource.closure	= request->closure;
+	e1->resource.type	= FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
+	e2->resource.closure	= request->closure;
+	e2->resource.type	= FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
+
+	if (todo == ISO_RES_ALLOC) {
+		r->resource.release = release_iso_resource;
+		ret = add_client_resource(client, &r->resource, GFP_KERNEL);
+		if (ret < 0)
+			goto fail;
+	} else {
+		r->resource.release = NULL;
+		r->resource.handle = -1;
+		schedule_iso_resource(r);
+	}
+	request->handle = r->resource.handle;
+
+	return 0;
+ fail:
+	kfree(r);
+	kfree(e1);
+	kfree(e2);
+
+	return ret;
+}
+
+static int ioctl_allocate_iso_resource(struct client *client, void *buffer)
+{
+	struct fw_cdev_allocate_iso_resource *request = buffer;
+
+	return init_iso_resource(client, request, ISO_RES_ALLOC);
+}
+
+static int ioctl_deallocate_iso_resource(struct client *client, void *buffer)
+{
+	struct fw_cdev_deallocate *request = buffer;
+
+	return release_client_resource(client, request->handle,
+				       release_iso_resource, NULL);
+}
+
+static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer)
+{
+	struct fw_cdev_allocate_iso_resource *request = buffer;
+
+	return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE);
+}
+
+static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer)
+{
+	struct fw_cdev_allocate_iso_resource *request = buffer;
+
+	return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE);
+}
+
+/*
+ * Returns a speed code:  Maximum speed to or from this device,
+ * limited by the device's link speed, the local node's link speed,
+ * and all PHY port speeds between the two links.
+ */
+static int ioctl_get_speed(struct client *client, void *buffer)
+{
+	return client->device->max_speed;
+}
+
+static int ioctl_send_broadcast_request(struct client *client, void *buffer)
+{
+	struct fw_cdev_send_request *request = buffer;
+
+	switch (request->tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+	case TCODE_WRITE_BLOCK_REQUEST:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Security policy: Only allow accesses to Units Space. */
+	if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END)
+		return -EACCES;
+
+	return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100);
+}
+
+static int ioctl_send_stream_packet(struct client *client, void *buffer)
+{
+	struct fw_cdev_send_stream_packet *p = buffer;
+	struct fw_cdev_send_request request;
+	int dest;
+
+	if (p->speed > client->device->card->link_speed ||
+	    p->length > 1024 << p->speed)
+		return -EIO;
+
+	if (p->tag > 3 || p->channel > 63 || p->sy > 15)
+		return -EINVAL;
+
+	dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy);
+	request.tcode		= TCODE_STREAM_DATA;
+	request.length		= p->length;
+	request.closure		= p->closure;
+	request.data		= p->data;
+	request.generation	= p->generation;
+
+	return init_request(client, &request, dest, p->speed);
+}
+
+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,
+	ioctl_get_cycle_timer,
+	ioctl_allocate_iso_resource,
+	ioctl_deallocate_iso_resource,
+	ioctl_allocate_iso_resource_once,
+	ioctl_deallocate_iso_resource_once,
+	ioctl_get_speed,
+	ioctl_send_broadcast_request,
+	ioctl_send_stream_packet,
+};
+
+static int dispatch_ioctl(struct client *client,
+			  unsigned int cmd, void __user *arg)
+{
+	char buffer[256];
+	int ret;
+
+	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;
+	}
+
+	ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer);
+	if (ret < 0)
+		return ret;
+
+	if (_IOC_DIR(cmd) & _IOC_READ) {
+		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
+		    copy_to_user(arg, buffer, _IOC_SIZE(cmd)))
+			return -EFAULT;
+	}
+
+	return ret;
+}
+
+static long fw_device_op_ioctl(struct file *file,
+			       unsigned int cmd, unsigned long arg)
+{
+	struct client *client = file->private_data;
+
+	if (fw_device_is_shutdown(client->device))
+		return -ENODEV;
+
+	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;
+
+	if (fw_device_is_shutdown(client->device))
+		return -ENODEV;
+
+	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, ret;
+
+	if (fw_device_is_shutdown(client->device))
+		return -ENODEV;
+
+	/* 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;
+
+	ret = fw_iso_buffer_init(&client->buffer, client->device->card,
+				 page_count, direction);
+	if (ret < 0)
+		return ret;
+
+	ret = fw_iso_buffer_map(&client->buffer, vma);
+	if (ret < 0)
+		fw_iso_buffer_destroy(&client->buffer, client->device->card);
+
+	return ret;
+}
+
+static int shutdown_resource(int id, void *p, void *data)
+{
+	struct client_resource *r = p;
+	struct client *client = data;
+
+	r->release(client, r);
+	client_put(client);
+
+	return 0;
+}
+
+static int fw_device_op_release(struct inode *inode, struct file *file)
+{
+	struct client *client = file->private_data;
+	struct event *e, *next_e;
+
+	mutex_lock(&client->device->client_list_mutex);
+	list_del(&client->link);
+	mutex_unlock(&client->device->client_list_mutex);
+
+	if (client->iso_context)
+		fw_iso_context_destroy(client->iso_context);
+
+	if (client->buffer.pages)
+		fw_iso_buffer_destroy(&client->buffer, client->device->card);
+
+	/* Freeze client->resource_idr and client->event_list */
+	spin_lock_irq(&client->lock);
+	client->in_shutdown = true;
+	spin_unlock_irq(&client->lock);
+
+	idr_for_each(&client->resource_idr, shutdown_resource, client);
+	idr_remove_all(&client->resource_idr);
+	idr_destroy(&client->resource_idr);
+
+	list_for_each_entry_safe(e, next_e, &client->event_list, link)
+		kfree(e);
+
+	client_put(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 -druN linux-libre-2.6.30-gnu/drivers/firewire/core-device.c linux-libre-2.6.31-gnu/drivers/firewire/core-device.c
--- linux-libre-2.6.30-gnu/drivers/firewire/core-device.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/core-device.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1228 @@
+/*
+ * 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/ctype.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/idr.h>
+#include <linux/jiffies.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rwsem.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+
+#include "core.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 bool is_fw_unit(struct device *dev);
+
+static int match_unit_directory(u32 *directory, u32 match_flags,
+				const struct ieee1394_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_id)
+			match |= IEEE1394_MATCH_VENDOR_ID;
+		if (key == CSR_MODEL && value == id->model_id)
+			match |= IEEE1394_MATCH_MODEL_ID;
+		if (key == CSR_SPECIFIER_ID && value == id->specifier_id)
+			match |= IEEE1394_MATCH_SPECIFIER_ID;
+		if (key == CSR_VERSION && value == id->version)
+			match |= IEEE1394_MATCH_VERSION;
+	}
+
+	return (match & match_flags) == match_flags;
+}
+
+static int fw_unit_match(struct device *dev, struct device_driver *drv)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_device *device;
+	const struct ieee1394_device_id *id;
+
+	/* We only allow binding to fw_units. */
+	if (!is_fw_unit(dev))
+		return 0;
+
+	device = fw_parent_device(unit);
+	id = container_of(drv, struct fw_driver, driver)->id_table;
+
+	for (; id->match_flags != 0; id++) {
+		if (match_unit_directory(unit->directory, id->match_flags, id))
+			return 1;
+
+		/* Also check vendor ID in the root directory. */
+		if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
+		    match_unit_directory(&device->config_rom[5],
+				IEEE1394_MATCH_VENDOR_ID, id) &&
+		    match_unit_directory(unit->directory, id->match_flags
+				& ~IEEE1394_MATCH_VENDOR_ID, id))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
+{
+	struct fw_device *device = fw_parent_device(unit);
+	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, struct kobj_uevent_env *env)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	char modalias[64];
+
+	get_modalias(unit, modalias, sizeof(modalias));
+
+	if (add_uevent_var(env, "MODALIAS=%s", modalias))
+		return -ENOMEM;
+
+	return 0;
+}
+
+struct bus_type fw_bus_type = {
+	.name = "firewire",
+	.match = fw_unit_match,
+};
+EXPORT_SYMBOL(fw_bus_type);
+
+int fw_device_enable_phys_dma(struct fw_device *device)
+{
+	int generation = device->generation;
+
+	/* device->node_id, accessed below, must not be older than generation */
+	smp_rmb();
+
+	return device->card->driver->enable_phys_dma(device->card,
+						     device->node_id,
+						     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, ret = -ENOENT;
+
+	down_read(&fw_device_rwsem);
+
+	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) {
+			ret = snprintf(buf, buf ? PAGE_SIZE : 0,
+				       "0x%06x\n", value);
+			break;
+		}
+
+	up_read(&fw_device_rwsem);
+
+	return ret;
+}
+
+#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, ret = -ENOENT;
+	char *b;
+
+	down_read(&fw_device_rwsem);
+
+	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)
+		goto out;
+
+	length = min(block[0] >> 16, 256U);
+	if (length < 3)
+		goto out;
+
+	if (block[1] != 0 || block[2] != 0)
+		/* Unknown encoding. */
+		goto out;
+
+	if (buf == NULL) {
+		ret = length * 4;
+		goto out;
+	}
+
+	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");
+	ret = b + 2 - buf;
+ out:
+	up_read(&fw_device_rwsem);
+
+	return ret;
+}
+
+#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;
+	}
+
+	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);
+	size_t length;
+
+	down_read(&fw_device_rwsem);
+	length = device->config_rom_length * 4;
+	memcpy(buf, device->config_rom, length);
+	up_read(&fw_device_rwsem);
+
+	return length;
+}
+
+static ssize_t guid_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct fw_device *device = fw_device(dev);
+	int ret;
+
+	down_read(&fw_device_rwsem);
+	ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
+		       device->config_rom[3], device->config_rom[4]);
+	up_read(&fw_device_rwsem);
+
+	return ret;
+}
+
+static int units_sprintf(char *buf, u32 *directory)
+{
+	struct fw_csr_iterator ci;
+	int key, value;
+	int specifier_id = 0;
+	int version = 0;
+
+	fw_csr_iterator_init(&ci, 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 sprintf(buf, "0x%06x:0x%06x ", specifier_id, version);
+}
+
+static ssize_t units_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct fw_device *device = fw_device(dev);
+	struct fw_csr_iterator ci;
+	int key, value, i = 0;
+
+	down_read(&fw_device_rwsem);
+	fw_csr_iterator_init(&ci, &device->config_rom[5]);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		if (key != (CSR_UNIT | CSR_DIRECTORY))
+			continue;
+		i += units_sprintf(&buf[i], ci.p + value - 1);
+		if (i >= PAGE_SIZE - (8 + 1 + 8 + 1))
+			break;
+	}
+	up_read(&fw_device_rwsem);
+
+	if (i)
+		buf[i - 1] = '\n';
+
+	return i;
+}
+
+static struct device_attribute fw_device_attributes[] = {
+	__ATTR_RO(config_rom),
+	__ATTR_RO(guid),
+	__ATTR_RO(units),
+	__ATTR_NULL,
+};
+
+static int read_rom(struct fw_device *device,
+		    int generation, int index, u32 *data)
+{
+	int rcode;
+
+	/* device->node_id, accessed below, must not be older than generation */
+	smp_rmb();
+
+	rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
+			device->node_id, generation, device->max_speed,
+			(CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
+			data, 4);
+	be32_to_cpus(data);
+
+	return rcode;
+}
+
+#define READ_BIB_ROM_SIZE	256
+#define READ_BIB_STACK_SIZE	16
+
+/*
+ * Read the bus info block, perform a speed probe, and read all of the rest of
+ * the config ROM.  We do all this with a cached bus generation.  If the bus
+ * generation changes under us, read_bus_info_block will fail and get retried.
+ * It's better to start all over in this case because the node from which we
+ * are reading the ROM may have changed the ROM during the reset.
+ */
+static int read_bus_info_block(struct fw_device *device, int generation)
+{
+	u32 *rom, *stack, *old_rom, *new_rom;
+	u32 sp, key;
+	int i, end, length, ret = -1;
+
+	rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
+		      sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
+	if (rom == NULL)
+		return -ENOMEM;
+
+	stack = &rom[READ_BIB_ROM_SIZE];
+
+	device->max_speed = SCODE_100;
+
+	/* First read the bus info block. */
+	for (i = 0; i < 5; i++) {
+		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+			goto out;
+		/*
+		 * 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)
+			goto out;
+	}
+
+	device->max_speed = device->node->max_speed;
+
+	/*
+	 * Determine the speed of
+	 *   - devices with link speed less than PHY speed,
+	 *   - devices with 1394b PHY (unless only connected to 1394a PHYs),
+	 *   - all devices if there are 1394b repeaters.
+	 * Note, we cannot use the bus info block's link_spd as starting point
+	 * because some buggy firmwares set it lower than necessary and because
+	 * 1394-1995 nodes do not have the field.
+	 */
+	if ((rom[2] & 0x7) < device->max_speed ||
+	    device->max_speed == SCODE_BETA ||
+	    device->card->beta_repeaters_present) {
+		u32 dummy;
+
+		/* for S1600 and S3200 */
+		if (device->max_speed == SCODE_BETA)
+			device->max_speed = device->card->link_speed;
+
+		while (device->max_speed > SCODE_100) {
+			if (read_rom(device, generation, 0, &dummy) ==
+			    RCODE_COMPLETE)
+				break;
+			device->max_speed--;
+		}
+	}
+
+	/*
+	 * 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 >= READ_BIB_ROM_SIZE)
+			/*
+			 * The reference points outside the standard
+			 * config rom area, something's fishy.
+			 */
+			goto out;
+
+		/* Read header quadlet for the block to get the length. */
+		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+			goto out;
+		end = i + (rom[i] >> 16) + 1;
+		i++;
+		if (end > READ_BIB_ROM_SIZE)
+			/*
+			 * This block extends outside standard config
+			 * area (and the array we're reading it
+			 * into).  That's broken, so ignore this
+			 * device.
+			 */
+			goto out;
+
+		/*
+		 * 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, generation, i, &rom[i]) !=
+			    RCODE_COMPLETE)
+				goto out;
+			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+			    sp < READ_BIB_STACK_SIZE)
+				stack[sp++] = i + rom[i];
+			i++;
+		}
+		if (length < i)
+			length = i;
+	}
+
+	old_rom = device->config_rom;
+	new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
+	if (new_rom == NULL)
+		goto out;
+
+	down_write(&fw_device_rwsem);
+	device->config_rom = new_rom;
+	device->config_rom_length = length;
+	up_write(&fw_device_rwsem);
+
+	kfree(old_rom);
+	ret = 0;
+	device->max_rec	= rom[2] >> 12 & 0xf;
+	device->cmc	= rom[2] >> 30 & 1;
+	device->irmc	= rom[2] >> 31 & 1;
+ out:
+	kfree(rom);
+
+	return ret;
+}
+
+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 bool 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;
+		dev_set_name(&unit->device, "%s.%d", dev_name(&device->device), i++);
+
+		BUILD_BUG_ON(ARRAY_SIZE(unit->attribute_group.attrs) <
+				ARRAY_SIZE(fw_unit_attributes) +
+				ARRAY_SIZE(config_rom_attributes));
+		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;
+}
+
+/*
+ * fw_device_rwsem acts as dual purpose mutex:
+ *   - serializes accesses to fw_device_idr,
+ *   - serializes accesses to fw_device.config_rom/.config_rom_length and
+ *     fw_unit.directory, unless those accesses happen at safe occasions
+ */
+DECLARE_RWSEM(fw_device_rwsem);
+
+DEFINE_IDR(fw_device_idr);
+int fw_cdev_major;
+
+struct fw_device *fw_device_get_by_devt(dev_t devt)
+{
+	struct fw_device *device;
+
+	down_read(&fw_device_rwsem);
+	device = idr_find(&fw_device_idr, MINOR(devt));
+	if (device)
+		fw_device_get(device);
+	up_read(&fw_device_rwsem);
+
+	return device;
+}
+
+/*
+ * 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)
+#define SHUTDOWN_DELAY	(2 * HZ)
+
+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);
+
+	if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY)
+	    && !list_empty(&device->card->link)) {
+		schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
+		return;
+	}
+
+	if (atomic_cmpxchg(&device->state,
+			   FW_DEVICE_GONE,
+			   FW_DEVICE_SHUTDOWN) != FW_DEVICE_GONE)
+		return;
+
+	fw_device_cdev_remove(device);
+	device_for_each_child(&device->device, NULL, shutdown_unit);
+	device_unregister(&device->device);
+
+	down_write(&fw_device_rwsem);
+	idr_remove(&fw_device_idr, minor);
+	up_write(&fw_device_rwsem);
+
+	fw_device_put(device);
+}
+
+static void fw_device_release(struct device *dev)
+{
+	struct fw_device *device = fw_device(dev);
+	struct fw_card *card = device->card;
+	unsigned long flags;
+
+	/*
+	 * Take the card lock so we don't set this to NULL while a
+	 * FW_NODE_UPDATED callback is being handled or while the
+	 * bus manager work looks at this node.
+	 */
+	spin_lock_irqsave(&card->lock, flags);
+	device->node->data = NULL;
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	fw_node_put(device->node);
+	kfree(device->config_rom);
+	kfree(device);
+	fw_card_put(card);
+}
+
+static struct device_type fw_device_type = {
+	.release = fw_device_release,
+};
+
+static bool is_fw_device(struct device *dev)
+{
+	return dev->type == &fw_device_type;
+}
+
+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);
+}
+
+/*
+ * If a device was pending for deletion because its node went away but its
+ * bus info block and root directory header matches that of a newly discovered
+ * device, revive the existing fw_device.
+ * The newly allocated fw_device becomes obsolete instead.
+ */
+static int lookup_existing_device(struct device *dev, void *data)
+{
+	struct fw_device *old = fw_device(dev);
+	struct fw_device *new = data;
+	struct fw_card *card = new->card;
+	int match = 0;
+
+	if (!is_fw_device(dev))
+		return 0;
+
+	down_read(&fw_device_rwsem); /* serialize config_rom access */
+	spin_lock_irq(&card->lock);  /* serialize node access */
+
+	if (memcmp(old->config_rom, new->config_rom, 6 * 4) == 0 &&
+	    atomic_cmpxchg(&old->state,
+			   FW_DEVICE_GONE,
+			   FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
+		struct fw_node *current_node = new->node;
+		struct fw_node *obsolete_node = old->node;
+
+		new->node = obsolete_node;
+		new->node->data = new;
+		old->node = current_node;
+		old->node->data = old;
+
+		old->max_speed = new->max_speed;
+		old->node_id = current_node->node_id;
+		smp_wmb();  /* update node_id before generation */
+		old->generation = card->generation;
+		old->config_rom_retries = 0;
+		fw_notify("rediscovered device %s\n", dev_name(dev));
+
+		PREPARE_DELAYED_WORK(&old->work, fw_device_update);
+		schedule_delayed_work(&old->work, 0);
+
+		if (current_node == card->root_node)
+			fw_schedule_bm_work(card, 0);
+
+		match = 1;
+	}
+
+	spin_unlock_irq(&card->lock);
+	up_read(&fw_device_rwsem);
+
+	return match;
+}
+
+enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, };
+
+static void set_broadcast_channel(struct fw_device *device, int generation)
+{
+	struct fw_card *card = device->card;
+	__be32 data;
+	int rcode;
+
+	if (!card->broadcast_channel_allocated)
+		return;
+
+	/*
+	 * The Broadcast_Channel Valid bit is required by nodes which want to
+	 * transmit on this channel.  Such transmissions are practically
+	 * exclusive to IP over 1394 (RFC 2734).  IP capable nodes are required
+	 * to be IRM capable and have a max_rec of 8 or more.  We use this fact
+	 * to narrow down to which nodes we send Broadcast_Channel updates.
+	 */
+	if (!device->irmc || device->max_rec < 8)
+		return;
+
+	/*
+	 * Some 1394-1995 nodes crash if this 1394a-2000 register is written.
+	 * Perform a read test first.
+	 */
+	if (device->bc_implemented == BC_UNKNOWN) {
+		rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST,
+				device->node_id, generation, device->max_speed,
+				CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL,
+				&data, 4);
+		switch (rcode) {
+		case RCODE_COMPLETE:
+			if (data & cpu_to_be32(1 << 31)) {
+				device->bc_implemented = BC_IMPLEMENTED;
+				break;
+			}
+			/* else fall through to case address error */
+		case RCODE_ADDRESS_ERROR:
+			device->bc_implemented = BC_UNIMPLEMENTED;
+		}
+	}
+
+	if (device->bc_implemented == BC_IMPLEMENTED) {
+		data = cpu_to_be32(BROADCAST_CHANNEL_INITIAL |
+				   BROADCAST_CHANNEL_VALID);
+		fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,
+				device->node_id, generation, device->max_speed,
+				CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL,
+				&data, 4);
+	}
+}
+
+int fw_device_set_broadcast_channel(struct device *dev, void *gen)
+{
+	if (is_fw_device(dev))
+		set_broadcast_channel(fw_device(dev), (long)gen);
+
+	return 0;
+}
+
+static void fw_device_init(struct work_struct *work)
+{
+	struct fw_device *device =
+		container_of(work, struct fw_device, work.work);
+	struct device *revived_dev;
+	int minor, ret;
+
+	/*
+	 * 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, device->generation) < 0) {
+		if (device->config_rom_retries < MAX_RETRIES &&
+		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
+			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)
+				fw_schedule_bm_work(device->card, 0);
+			fw_device_release(&device->device);
+		}
+		return;
+	}
+
+	revived_dev = device_find_child(device->card->device,
+					device, lookup_existing_device);
+	if (revived_dev) {
+		put_device(revived_dev);
+		fw_device_release(&device->device);
+
+		return;
+	}
+
+	device_initialize(&device->device);
+
+	fw_device_get(device);
+	down_write(&fw_device_rwsem);
+	ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ?
+	      idr_get_new(&fw_device_idr, device, &minor) :
+	      -ENOMEM;
+	up_write(&fw_device_rwsem);
+
+	if (ret < 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);
+	dev_set_name(&device->device, "fw%d", minor);
+
+	BUILD_BUG_ON(ARRAY_SIZE(device->attribute_group.attrs) <
+			ARRAY_SIZE(fw_device_attributes) +
+			ARRAY_SIZE(config_rom_attributes));
+	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_GONE) {
+		PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+		schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
+	} else {
+		if (device->config_rom_retries)
+			fw_notify("created device %s: GUID %08x%08x, S%d00, "
+				  "%d config ROM retries\n",
+				  dev_name(&device->device),
+				  device->config_rom[3], device->config_rom[4],
+				  1 << device->max_speed,
+				  device->config_rom_retries);
+		else
+			fw_notify("created device %s: GUID %08x%08x, S%d00\n",
+				  dev_name(&device->device),
+				  device->config_rom[3], device->config_rom[4],
+				  1 << device->max_speed);
+		device->config_rom_retries = 0;
+
+		set_broadcast_channel(device, device->generation);
+	}
+
+	/*
+	 * 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)
+		fw_schedule_bm_work(device->card, 0);
+
+	return;
+
+ error_with_cdev:
+	down_write(&fw_device_rwsem);
+	idr_remove(&fw_device_idr, minor);
+	up_write(&fw_device_rwsem);
+ error:
+	fw_device_put(device);		/* fw_device_idr's reference */
+
+	put_device(&device->device);	/* our reference */
+}
+
+enum {
+	REREAD_BIB_ERROR,
+	REREAD_BIB_GONE,
+	REREAD_BIB_UNCHANGED,
+	REREAD_BIB_CHANGED,
+};
+
+/* Reread and compare bus info block and header of root directory */
+static int reread_bus_info_block(struct fw_device *device, int generation)
+{
+	u32 q;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
+			return REREAD_BIB_ERROR;
+
+		if (i == 0 && q == 0)
+			return REREAD_BIB_GONE;
+
+		if (q != device->config_rom[i])
+			return REREAD_BIB_CHANGED;
+	}
+
+	return REREAD_BIB_UNCHANGED;
+}
+
+static void fw_device_refresh(struct work_struct *work)
+{
+	struct fw_device *device =
+		container_of(work, struct fw_device, work.work);
+	struct fw_card *card = device->card;
+	int node_id = device->node_id;
+
+	switch (reread_bus_info_block(device, device->generation)) {
+	case REREAD_BIB_ERROR:
+		if (device->config_rom_retries < MAX_RETRIES / 2 &&
+		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
+			device->config_rom_retries++;
+			schedule_delayed_work(&device->work, RETRY_DELAY / 2);
+
+			return;
+		}
+		goto give_up;
+
+	case REREAD_BIB_GONE:
+		goto gone;
+
+	case REREAD_BIB_UNCHANGED:
+		if (atomic_cmpxchg(&device->state,
+				   FW_DEVICE_INITIALIZING,
+				   FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
+			goto gone;
+
+		fw_device_update(work);
+		device->config_rom_retries = 0;
+		goto out;
+
+	case REREAD_BIB_CHANGED:
+		break;
+	}
+
+	/*
+	 * Something changed.  We keep things simple and don't investigate
+	 * further.  We just destroy all previous units and create new ones.
+	 */
+	device_for_each_child(&device->device, NULL, shutdown_unit);
+
+	if (read_bus_info_block(device, device->generation) < 0) {
+		if (device->config_rom_retries < MAX_RETRIES &&
+		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
+			device->config_rom_retries++;
+			schedule_delayed_work(&device->work, RETRY_DELAY);
+
+			return;
+		}
+		goto give_up;
+	}
+
+	create_units(device);
+
+	/* Userspace may want to re-read attributes. */
+	kobject_uevent(&device->device.kobj, KOBJ_CHANGE);
+
+	if (atomic_cmpxchg(&device->state,
+			   FW_DEVICE_INITIALIZING,
+			   FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
+		goto gone;
+
+	fw_notify("refreshed device %s\n", dev_name(&device->device));
+	device->config_rom_retries = 0;
+	goto out;
+
+ give_up:
+	fw_notify("giving up on refresh of device %s\n", dev_name(&device->device));
+ gone:
+	atomic_set(&device->state, FW_DEVICE_GONE);
+	PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+	schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
+ out:
+	if (node_id == card->root_node->node_id)
+		fw_schedule_bm_work(card, 0);
+}
+
+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;
+ create:
+		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().
+		 *
+		 * Attention:  A lot of things, even fw_device_get(),
+		 * cannot be done before fw_device_init() finished!
+		 * You can basically just check device->state and
+		 * schedule work until then, but only while holding
+		 * card->lock.
+		 */
+		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;
+		device->is_local = node == card->local_node;
+		mutex_init(&device->client_list_mutex);
+		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_INITIATED_RESET:
+		device = node->data;
+		if (device == NULL)
+			goto create;
+
+		device->node_id = node->node_id;
+		smp_wmb();  /* update node_id before generation */
+		device->generation = card->generation;
+		if (atomic_cmpxchg(&device->state,
+			    FW_DEVICE_RUNNING,
+			    FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
+			PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
+			schedule_delayed_work(&device->work,
+				device->is_local ? 0 : INITIAL_DELAY);
+		}
+		break;
+
+	case FW_NODE_UPDATED:
+		if (!node->link_on || node->data == NULL)
+			break;
+
+		device = node->data;
+		device->node_id = node->node_id;
+		smp_wmb();  /* update node_id before generation */
+		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_GONE) == FW_DEVICE_RUNNING) {
+			PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+			schedule_delayed_work(&device->work,
+				list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
+		}
+		break;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/core.h linux-libre-2.6.31-gnu/drivers/firewire/core.h
--- linux-libre-2.6.30-gnu/drivers/firewire/core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/core.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,207 @@
+#ifndef _FIREWIRE_CORE_H
+#define _FIREWIRE_CORE_H
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/idr.h>
+#include <linux/mm_types.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <asm/atomic.h>
+
+struct device;
+struct fw_card;
+struct fw_device;
+struct fw_iso_buffer;
+struct fw_iso_context;
+struct fw_iso_packet;
+struct fw_node;
+struct fw_packet;
+
+
+/* -card */
+
+/* bitfields 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 BANDWIDTH_AVAILABLE_INITIAL	4915
+#define BROADCAST_CHANNEL_INITIAL	(1 << 31 | 31)
+#define BROADCAST_CHANNEL_VALID		(1 << 30)
+
+struct fw_card_driver {
+	/*
+	 * 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, int channel, 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);
+};
+
+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);
+int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
+int fw_compute_block_crc(u32 *block);
+void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
+
+
+/* -cdev */
+
+extern const struct file_operations fw_device_ops;
+
+void fw_device_cdev_update(struct fw_device *device);
+void fw_device_cdev_remove(struct fw_device *device);
+
+
+/* -device */
+
+extern struct rw_semaphore fw_device_rwsem;
+extern struct idr fw_device_idr;
+extern int fw_cdev_major;
+
+struct fw_device *fw_device_get_by_devt(dev_t devt);
+int fw_device_set_broadcast_channel(struct device *dev, void *gen);
+void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
+
+
+/* -iso */
+
+int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
+void fw_iso_resource_manage(struct fw_card *card, int generation,
+			    u64 channels_mask, int *channel, int *bandwidth,
+			    bool allocate, __be32 buffer[2]);
+
+
+/* -topology */
+
+enum {
+	FW_NODE_CREATED,
+	FW_NODE_UPDATED,
+	FW_NODE_DESTROYED,
+	FW_NODE_LINK_ON,
+	FW_NODE_LINK_OFF,
+	FW_NODE_INITIATED_RESET,
+};
+
+struct fw_node {
+	u16 node_id;
+	u8 color;
+	u8 port_count;
+	u8 link_on:1;
+	u8 initiated_reset:1;
+	u8 b_path:1;
+	u8 phy_speed:2;	/* As in the self ID packet. */
+	u8 max_speed:2;	/* Minimum of all phy-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_node *ports[0];
+};
+
+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_core_handle_bus_reset(struct fw_card *card, int node_id,
+			      int generation, int self_id_count, u32 *self_ids);
+void fw_destroy_nodes(struct fw_card *card);
+
+/*
+ * Check whether new_generation is the immediate successor of old_generation.
+ * Take counter roll-over at 255 (as per OHCI) into account.
+ */
+static inline bool is_next_generation(int new_generation, int old_generation)
+{
+	return (new_generation & 0xff) == ((old_generation + 1) & 0xff);
+}
+
+
+/* -transaction */
+
+#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
+
+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);
+void fw_fill_response(struct fw_packet *response, u32 *request_header,
+		      int rcode, void *payload, size_t length);
+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);
+
+#endif /* _FIREWIRE_CORE_H */
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/core-iso.c linux-libre-2.6.31-gnu/drivers/firewire/core-iso.c
--- linux-libre-2.6.30-gnu/drivers/firewire/core-iso.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/core-iso.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,338 @@
+/*
+ * Isochronous I/O functionality:
+ *   - Isochronous DMA context management
+ *   - Isochronous bus resource management (channels, bandwidth), client side
+ *
+ * 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/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+
+#include <asm/byteorder.h>
+
+#include "core.h"
+
+/*
+ * Isochronous DMA context management
+ */
+
+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;
+	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(card->device, 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, direction);
+		__free_page(buffer->pages[j]);
+	}
+	kfree(buffer->pages);
+ out:
+	buffer->pages = NULL;
+
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(fw_iso_buffer_init);
+
+int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma)
+{
+	unsigned long uaddr;
+	int i, err;
+
+	uaddr = vma->vm_start;
+	for (i = 0; i < buffer->page_count; i++) {
+		err = vm_insert_page(vma, uaddr, buffer->pages[i]);
+		if (err)
+			return err;
+
+		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, buffer->direction);
+		__free_page(buffer->pages[i]);
+	}
+
+	kfree(buffer->pages);
+	buffer->pages = NULL;
+}
+EXPORT_SYMBOL(fw_iso_buffer_destroy);
+
+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, channel, 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);
+
+/*
+ * Isochronous bus resource management (channels, bandwidth), client side
+ */
+
+static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
+			    int bandwidth, bool allocate, __be32 data[2])
+{
+	int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
+
+	/*
+	 * On a 1394a IRM with low contention, try < 1 is enough.
+	 * On a 1394-1995 IRM, we need at least try < 2.
+	 * Let's just do try < 5.
+	 */
+	for (try = 0; try < 5; try++) {
+		new = allocate ? old - bandwidth : old + bandwidth;
+		if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL)
+			break;
+
+		data[0] = cpu_to_be32(old);
+		data[1] = cpu_to_be32(new);
+		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
+				irm_id, generation, SCODE_100,
+				CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
+				data, 8)) {
+		case RCODE_GENERATION:
+			/* A generation change frees all bandwidth. */
+			return allocate ? -EAGAIN : bandwidth;
+
+		case RCODE_COMPLETE:
+			if (be32_to_cpup(data) == old)
+				return bandwidth;
+
+			old = be32_to_cpup(data);
+			/* Fall through. */
+		}
+	}
+
+	return -EIO;
+}
+
+static int manage_channel(struct fw_card *card, int irm_id, int generation,
+		u32 channels_mask, u64 offset, bool allocate, __be32 data[2])
+{
+	__be32 c, all, old;
+	int i, retry = 5;
+
+	old = all = allocate ? cpu_to_be32(~0) : 0;
+
+	for (i = 0; i < 32; i++) {
+		if (!(channels_mask & 1 << i))
+			continue;
+
+		c = cpu_to_be32(1 << (31 - i));
+		if ((old & c) != (all & c))
+			continue;
+
+		data[0] = old;
+		data[1] = old ^ c;
+		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
+					   irm_id, generation, SCODE_100,
+					   offset, data, 8)) {
+		case RCODE_GENERATION:
+			/* A generation change frees all channels. */
+			return allocate ? -EAGAIN : i;
+
+		case RCODE_COMPLETE:
+			if (data[0] == old)
+				return i;
+
+			old = data[0];
+
+			/* Is the IRM 1394a-2000 compliant? */
+			if ((data[0] & c) == (data[1] & c))
+				continue;
+
+			/* 1394-1995 IRM, fall through to retry. */
+		default:
+			if (retry--)
+				i--;
+		}
+	}
+
+	return -EIO;
+}
+
+static void deallocate_channel(struct fw_card *card, int irm_id,
+			       int generation, int channel, __be32 buffer[2])
+{
+	u32 mask;
+	u64 offset;
+
+	mask = channel < 32 ? 1 << channel : 1 << (channel - 32);
+	offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
+				CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO;
+
+	manage_channel(card, irm_id, generation, mask, offset, false, buffer);
+}
+
+/**
+ * fw_iso_resource_manage - Allocate or deallocate a channel and/or bandwidth
+ *
+ * In parameters: card, generation, channels_mask, bandwidth, allocate
+ * Out parameters: channel, bandwidth
+ * This function blocks (sleeps) during communication with the IRM.
+ *
+ * Allocates or deallocates at most one channel out of channels_mask.
+ * channels_mask is a bitfield with MSB for channel 63 and LSB for channel 0.
+ * (Note, the IRM's CHANNELS_AVAILABLE is a big-endian bitfield with MSB for
+ * channel 0 and LSB for channel 63.)
+ * Allocates or deallocates as many bandwidth allocation units as specified.
+ *
+ * Returns channel < 0 if no channel was allocated or deallocated.
+ * Returns bandwidth = 0 if no bandwidth was allocated or deallocated.
+ *
+ * If generation is stale, deallocations succeed but allocations fail with
+ * channel = -EAGAIN.
+ *
+ * If channel allocation fails, no bandwidth will be allocated either.
+ * If bandwidth allocation fails, no channel will be allocated either.
+ * But deallocations of channel and bandwidth are tried independently
+ * of each other's success.
+ */
+void fw_iso_resource_manage(struct fw_card *card, int generation,
+			    u64 channels_mask, int *channel, int *bandwidth,
+			    bool allocate, __be32 buffer[2])
+{
+	u32 channels_hi = channels_mask;	/* channels 31...0 */
+	u32 channels_lo = channels_mask >> 32;	/* channels 63...32 */
+	int irm_id, ret, c = -EINVAL;
+
+	spin_lock_irq(&card->lock);
+	irm_id = card->irm_node->node_id;
+	spin_unlock_irq(&card->lock);
+
+	if (channels_hi)
+		c = manage_channel(card, irm_id, generation, channels_hi,
+				CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI,
+				allocate, buffer);
+	if (channels_lo && c < 0) {
+		c = manage_channel(card, irm_id, generation, channels_lo,
+				CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO,
+				allocate, buffer);
+		if (c >= 0)
+			c += 32;
+	}
+	*channel = c;
+
+	if (allocate && channels_mask != 0 && c < 0)
+		*bandwidth = 0;
+
+	if (*bandwidth == 0)
+		return;
+
+	ret = manage_bandwidth(card, irm_id, generation, *bandwidth,
+			       allocate, buffer);
+	if (ret < 0)
+		*bandwidth = 0;
+
+	if (allocate && ret < 0 && c >= 0) {
+		deallocate_channel(card, irm_id, generation, c, buffer);
+		*channel = ret;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/core-topology.c linux-libre-2.6.31-gnu/drivers/firewire/core-topology.c
--- linux-libre-2.6.30-gnu/drivers/firewire/core-topology.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/core-topology.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,572 @@
+/*
+ * 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/bug.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+#include "core.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)
+
+#define SELFID_PORT_CHILD	0x3
+#define SELFID_PORT_PARENT	0x2
+#define SELFID_PORT_NCONN	0x1
+#define SELFID_PORT_NONE	0x0
+
+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->initiated_reset = SELF_ID_PHY_INITIATOR(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] == NULL)
+			continue;
+
+		if (node->ports[i]->max_hops > max_child_hops)
+			max_child_hops = node->ports[i]->max_hops;
+
+		if (node->ports[i]->max_depth > depths[0]) {
+			depths[1] = depths[0];
+			depths[0] = node->ports[i]->max_depth;
+		} else if (node->ports[i]->max_depth > depths[1])
+			depths[1] = node->ports[i]->max_depth;
+	}
+
+	node->max_depth = depths[0] + 1;
+	node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2);
+}
+
+static inline struct fw_node *fw_node(struct list_head *l)
+{
+	return list_entry(l, struct fw_node, link);
+}
+
+/**
+ * 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 function 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;
+	bool beta_repeaters_present;
+
+	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);
+	beta_repeaters_present = false;
+
+	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;
+		/*
+		 * When the stack is empty, this yields an invalid value,
+		 * but that pointer will never be dereferenced.
+		 */
+		child = fw_node(h);
+
+		node = fw_node_create(q, port_count, card->color);
+		if (node == NULL) {
+			fw_error("Out of memory while building topology.\n");
+			return NULL;
+		}
+
+		if (phy_id == (card->node_id & 0x3f))
+			local_node = node;
+
+		if (SELF_ID_CONTENDER(q))
+			irm_node = node;
+
+		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] = child;
+				/*
+				 * Fix up parent reference for this
+				 * child node.
+				 */
+				child->ports[child->color] = 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 (node->phy_speed == SCODE_BETA &&
+		    parent_count + child_port_count > 1)
+			beta_repeaters_present = true;
+
+		/*
+		 * If PHYs report different gap counts, set an invalid count
+		 * which will force a gap count reconfiguration and a reset.
+		 */
+		if (SELF_ID_GAP_COUNT(q) != gap_count)
+			gap_count = 0;
+
+		update_hop_count(node);
+
+		sid = next_sid;
+		phy_id++;
+	}
+
+	card->root_node = node;
+	card->irm_node = irm_node;
+	card->gap_count = gap_count;
+	card->beta_repeaters_present = beta_repeaters_present;
+
+	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];
+			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);
+
+	/* Topology has changed - reset bus manager retry counter */
+	card->bm_retries = 0;
+}
+
+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);
+
+	/* Topology has changed - reset bus manager retry counter */
+	card->bm_retries = 0;
+}
+
+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);
+	card->local_node = NULL;
+	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];
+	node0->ports[port] = tree;
+	for (i = 0; i < tree->port_count; i++) {
+		if (tree->ports[i] == node1) {
+			tree->ports[i] = 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, *next1;
+	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) {
+		WARN_ON(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 if (node1->initiated_reset && node1->link_on)
+			event = FW_NODE_INITIATED_RESET;
+		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] && node1->ports[i]) {
+				/*
+				 * This port didn't change, queue the
+				 * connected node for further
+				 * investigation.
+				 */
+				if (node0->ports[i]->color == card->color)
+					continue;
+				list_add_tail(&node0->ports[i]->link, &list0);
+				list_add_tail(&node1->ports[i]->link, &list1);
+			} else if (node0->ports[i]) {
+				/*
+				 * 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],
+						 report_lost_node);
+				node0->ports[i] = NULL;
+			} else if (node1->ports[i]) {
+				/*
+				 * 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],
+						 report_found_node);
+			}
+		}
+
+		node0 = fw_node(node0->link.next);
+		next1 = fw_node(node1->link.next);
+		fw_node_put(node1);
+		node1 = next1;
+	}
+}
+
+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;
+
+	/*
+	 * If the selfID buffer is not the immediate successor of the
+	 * previously processed one, we cannot reliably compare the
+	 * old and new topologies.
+	 */
+	if (!is_next_generation(generation, card->generation) &&
+	    card->local_node != NULL) {
+		fw_notify("skipped bus generations, destroying all nodes\n");
+		fw_destroy_nodes(card);
+		card->bm_retries = 0;
+	}
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	card->broadcast_channel_allocated = false;
+	card->node_id = node_id;
+	/*
+	 * Update node_id before generation to prevent anybody from using
+	 * a stale node_id together with a current generation.
+	 */
+	smp_wmb();
+	card->generation = generation;
+	card->reset_jiffies = jiffies;
+	fw_schedule_bm_work(card, 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 -druN linux-libre-2.6.30-gnu/drivers/firewire/core-transaction.c linux-libre-2.6.31-gnu/drivers/firewire/core-transaction.c
--- linux-libre-2.6.30-gnu/drivers/firewire/core-transaction.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/core-transaction.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,978 @@
+/*
+ * 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/bug.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/idr.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+
+#include <asm/byteorder.h>
+
+#include "core.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 HEADER_DESTINATION_IS_BROADCAST(q) \
+	(((q) & HEADER_DESTINATION(0x3f)) == HEADER_DESTINATION(0x3f))
+
+#define PHY_PACKET_CONFIG	0x0
+#define PHY_PACKET_LINK_ON	0x1
+#define PHY_PACKET_SELF_ID	0x2
+
+#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)
+{
+	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 &= ~(1ULL << t->tlabel);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	if (&t->link != &card->transaction_list) {
+		t->callback(card, rcode, NULL, 0, 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);
+}
+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);
+		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);
+		break;
+	case ACK_DATA_ERROR:
+		close_transaction(t, card, RCODE_DATA_ERROR);
+		break;
+	case ACK_TYPE_ERROR:
+		close_transaction(t, card, RCODE_TYPE_ERROR);
+		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);
+		break;
+	}
+}
+
+static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
+		int destination_id, int source_id, int generation, int speed,
+		unsigned long long offset, void *payload, size_t length)
+{
+	int ext_tcode;
+
+	if (tcode == TCODE_STREAM_DATA) {
+		packet->header[0] =
+			HEADER_DATA_LENGTH(length) |
+			destination_id |
+			HEADER_TCODE(TCODE_STREAM_DATA);
+		packet->header_length = 4;
+		packet->payload = payload;
+		packet->payload_length = length;
+
+		goto common;
+	}
+
+	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(destination_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;
+	}
+ common:
+	packet->speed = speed;
+	packet->generation = generation;
+	packet->ack = 0;
+	packet->payload_bus = 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, instead 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
+ *
+ * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller
+ * needs to synthesize @destination_id with fw_stream_packet_destination_id().
+ */
+void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
+		     int destination_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;
+
+	/*
+	 * 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);
+
+	tlabel = card->current_tlabel;
+	if (card->tlabel_mask & (1ULL << tlabel)) {
+		spin_unlock_irqrestore(&card->lock, flags);
+		callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
+		return;
+	}
+
+	card->current_tlabel = (card->current_tlabel + 1) & 0x3f;
+	card->tlabel_mask |= (1ULL << tlabel);
+
+	t->node_id = destination_id;
+	t->tlabel = tlabel;
+	t->callback = callback;
+	t->callback_data = callback_data;
+
+	fw_fill_request(&t->packet, tcode, t->tlabel,
+			destination_id, card->node_id, generation,
+			speed, offset, payload, length);
+	t->packet.callback = transmit_complete_callback;
+
+	list_add_tail(&t->link, &card->transaction_list);
+
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	card->driver->send_request(card, &t->packet);
+}
+EXPORT_SYMBOL(fw_send_request);
+
+struct transaction_callback_data {
+	struct completion done;
+	void *payload;
+	int rcode;
+};
+
+static void transaction_callback(struct fw_card *card, int rcode,
+				 void *payload, size_t length, void *data)
+{
+	struct transaction_callback_data *d = data;
+
+	if (rcode == RCODE_COMPLETE)
+		memcpy(d->payload, payload, length);
+	d->rcode = rcode;
+	complete(&d->done);
+}
+
+/**
+ * fw_run_transaction - send request and sleep until transaction is completed
+ *
+ * Returns the RCODE.
+ */
+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
+		       int generation, int speed, unsigned long long offset,
+		       void *payload, size_t length)
+{
+	struct transaction_callback_data d;
+	struct fw_transaction t;
+
+	init_completion(&d.done);
+	d.payload = payload;
+	fw_send_request(card, &t, tcode, destination_id, generation, speed,
+			offset, payload, length, transaction_callback, &d);
+	wait_for_completion(&d.done);
+
+	return d.rcode;
+}
+EXPORT_SYMBOL(fw_run_transaction);
+
+static DEFINE_MUTEX(phy_config_mutex);
+static DECLARE_COMPLETION(phy_config_done);
+
+static void transmit_phy_packet_callback(struct fw_packet *packet,
+					 struct fw_card *card, int status)
+{
+	complete(&phy_config_done);
+}
+
+static struct fw_packet phy_config_packet = {
+	.header_length	= 8,
+	.payload_length	= 0,
+	.speed		= SCODE_100,
+	.callback	= transmit_phy_packet_callback,
+};
+
+void fw_send_phy_config(struct fw_card *card,
+			int node_id, int generation, int gap_count)
+{
+	long timeout = DIV_ROUND_UP(HZ, 10);
+	u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
+		   PHY_CONFIG_ROOT_ID(node_id) |
+		   PHY_CONFIG_GAP_COUNT(gap_count);
+
+	mutex_lock(&phy_config_mutex);
+
+	phy_config_packet.header[0] = data;
+	phy_config_packet.header[1] = ~data;
+	phy_config_packet.generation = generation;
+	INIT_COMPLETION(phy_config_done);
+
+	card->driver->send_request(card, &phy_config_packet);
+	wait_for_completion_timeout(&phy_config_done, timeout);
+
+	mutex_unlock(&phy_config_mutex);
+}
+
+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_high_memory_region =
+	{ .start = 0x000100000000ULL, .end = 0xffffe0000000ULL,  };
+EXPORT_SYMBOL(fw_high_memory_region);
+
+#if 0
+const struct fw_address_region fw_low_memory_region =
+	{ .start = 0x000000000000ULL, .end = 0x000100000000ULL,  };
+const struct fw_address_region fw_private_region =
+	{ .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL,  };
+const struct fw_address_region fw_csr_region =
+	{ .start = CSR_REGISTER_BASE,
+	  .end   = CSR_REGISTER_BASE | CSR_CONFIG_ROM_END,  };
+const struct fw_address_region fw_unit_space_region =
+	{ .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
+#endif  /*  0  */
+
+/**
+ * fw_core_add_address_handler - register for incoming requests
+ * @handler: callback
+ * @region: region in the IEEE 1212 node space address range
+ *
+ * region->start, ->end, and handler->length have to be quadlet-aligned.
+ *
+ * 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.
+ *
+ * Return value:  0 on success, non-zero otherwise.
+ * The start offset of the handler's address region is determined by
+ * fw_core_add_address_handler() and is returned in handler->offset.
+ */
+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;
+
+	if (region->start & 0xffff000000000003ULL ||
+	    region->end   & 0xffff000000000003ULL ||
+	    region->start >= region->end ||
+	    handler->length & 3 ||
+	    handler->length == 0)
+		return -EINVAL;
+
+	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);
+
+/**
+ * fw_core_remove_address_handler - unregister an address handler
+ */
+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;
+	}
+
+	response->payload_bus = 0;
+}
+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:
+		fw_error("ERROR - corrupt request received - %08x %08x %08x\n",
+			 p->header[0], p->header[1], p->header[2]);
+		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)
+{
+	/* unified transaction or broadcast transaction: don't respond */
+	if (request->ack != ACK_PENDING ||
+	    HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) {
+		kfree(request);
+		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->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[1]);
+
+	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;
+	}
+
+	/*
+	 * The response handler may be executed while the request handler
+	 * is still pending.  Cancel the request handler.
+	 */
+	card->driver->cancel_packet(card, &t->packet);
+
+	t->callback(card, rcode, data, data_length, t->callback_data);
+}
+EXPORT_SYMBOL(fw_core_handle_response);
+
+static const struct fw_address_region topology_map_region =
+	{ .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP,
+	  .end   = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, };
+
+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;
+	__be32 *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,
+};
+
+static const struct fw_address_region registers_region =
+	{ .start = CSR_REGISTER_BASE,
+	  .end   = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
+
+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;
+	int rcode = RCODE_COMPLETE;
+
+	switch (reg) {
+	case CSR_CYCLE_TIME:
+	case CSR_BUS_TIME:
+		if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) {
+			rcode = 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);
+		break;
+
+	case CSR_BROADCAST_CHANNEL:
+		if (tcode == TCODE_READ_QUADLET_REQUEST)
+			*data = cpu_to_be32(card->broadcast_channel);
+		else if (tcode == TCODE_WRITE_QUADLET_REQUEST)
+			card->broadcast_channel =
+			    (be32_to_cpu(*data) & BROADCAST_CHANNEL_VALID) |
+			    BROADCAST_CHANNEL_INITIAL;
+		else
+			rcode = RCODE_TYPE_ERROR;
+		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:
+		rcode = RCODE_ADDRESS_ERROR;
+		break;
+	}
+
+	fw_send_response(card, request, rcode);
+}
+
+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 ret;
+
+	ret = bus_register(&fw_bus_type);
+	if (ret < 0)
+		return ret;
+
+	fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops);
+	if (fw_cdev_major < 0) {
+		bus_unregister(&fw_bus_type);
+		return fw_cdev_major;
+	}
+
+	fw_core_add_address_handler(&topology_map, &topology_map_region);
+	fw_core_add_address_handler(&registers, &registers_region);
+	fw_core_add_descriptor(&vendor_id_descriptor);
+	fw_core_add_descriptor(&model_id_descriptor);
+
+	return 0;
+}
+
+static void __exit fw_core_cleanup(void)
+{
+	unregister_chrdev(fw_cdev_major, "firewire");
+	bus_unregister(&fw_bus_type);
+	idr_destroy(&fw_device_idr);
+}
+
+module_init(fw_core_init);
+module_exit(fw_core_cleanup);
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-card.c linux-libre-2.6.31-gnu/drivers/firewire/fw-card.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-card.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-card.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,558 +0,0 @@
-/*
- * 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/completion.h>
-#include <linux/crc-itu-t.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/kref.h>
-#include <linux/module.h>
-#include <linux/mutex.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 matches
-	 * 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;
-}
-
-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);
-}
-
-static int set_broadcast_channel(struct device *dev, void *data)
-{
-	fw_device_set_broadcast_channel(fw_device(dev), (long)data);
-	return 0;
-}
-
-static void allocate_broadcast_channel(struct fw_card *card, int generation)
-{
-	int channel, bandwidth = 0;
-
-	fw_iso_resource_manage(card, generation, 1ULL << 31,
-			       &channel, &bandwidth, true);
-	if (channel == 31) {
-		card->broadcast_channel_allocated = true;
-		device_for_each_child(card->device, (void *)(long)generation,
-				      set_broadcast_channel);
-	}
-}
-
-static const char gap_count_table[] = {
-	63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
-};
-
-void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
-{
-	int scheduled;
-
-	fw_card_get(card);
-	scheduled = schedule_delayed_work(&card->work, delay);
-	if (!scheduled)
-		fw_card_put(card);
-}
-
-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_device;
-	struct fw_node *root_node;
-	unsigned long flags;
-	int root_id, new_root_id, irm_id, local_id;
-	int gap_count, generation, grace, rcode;
-	bool do_reset = false;
-	bool root_device_is_running;
-	bool root_device_is_cmc;
-	__be32 lock_data[2];
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (card->local_node == NULL) {
-		spin_unlock_irqrestore(&card->lock, flags);
-		goto out_put_card;
-	}
-
-	generation = card->generation;
-	root_node = card->root_node;
-	fw_node_get(root_node);
-	root_device = root_node->data;
-	root_device_is_running = root_device &&
-			atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
-	root_device_is_cmc = root_device && root_device->cmc;
-	root_id  = root_node->node_id;
-	irm_id   = card->irm_node->node_id;
-	local_id = card->local_node->node_id;
-
-	grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
-
-	if (is_next_generation(generation, card->bm_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.
-		 */
-
-		if (!card->irm_node->link_on) {
-			new_root_id = local_id;
-			fw_notify("IRM has link off, making local node (%02x) root.\n",
-				  new_root_id);
-			goto pick_me;
-		}
-
-		lock_data[0] = cpu_to_be32(0x3f);
-		lock_data[1] = cpu_to_be32(local_id);
-
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
-				irm_id, generation, SCODE_100,
-				CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
-				lock_data, sizeof(lock_data));
-
-		if (rcode == RCODE_GENERATION)
-			/* Another bus reset, BM work has been rescheduled. */
-			goto out;
-
-		if (rcode == RCODE_COMPLETE &&
-		    lock_data[0] != cpu_to_be32(0x3f)) {
-
-			/* Somebody else is BM.  Only act as IRM. */
-			if (local_id == irm_id)
-				allocate_broadcast_channel(card, generation);
-
-			goto out;
-		}
-
-		spin_lock_irqsave(&card->lock, flags);
-
-		if (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 = local_id;
-			fw_notify("BM lock failed, making local node (%02x) root.\n",
-				  new_root_id);
-			goto pick_me;
-		}
-	} else if (card->bm_generation != generation) {
-		/*
-		 * We weren't BM in the last generation, and the last
-		 * bus reset is less than 125ms ago.  Reschedule this job.
-		 */
-		spin_unlock_irqrestore(&card->lock, flags);
-		fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));
-		goto out;
-	}
-
-	/*
-	 * 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_device == NULL) {
-		/*
-		 * Either link_on is false, or we failed to read the
-		 * config rom.  In either case, pick another root.
-		 */
-		new_root_id = local_id;
-	} else if (!root_device_is_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);
-		goto out;
-	} else if (root_device_is_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 = local_id;
-	}
-
- pick_me:
-	/*
-	 * Pick a gap count from 1394a table E-1.  The table doesn't cover
-	 * the typically much larger 1394b beta repeater delays though.
-	 */
-	if (!card->beta_repeaters_present &&
-	    root_node->max_hops < ARRAY_SIZE(gap_count_table))
-		gap_count = gap_count_table[root_node->max_hops];
-	else
-		gap_count = 63;
-
-	/*
-	 * Finally, figure out if we should do a reset or not.  If we have
-	 * done less than 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 = true;
-
-	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);
-		/* Will allocate broadcast channel after the reset. */
-	} else {
-		if (local_id == irm_id)
-			allocate_broadcast_channel(card, generation);
-	}
-
- out:
-	fw_node_put(root_node);
- out_put_card:
-	fw_card_put(card);
-}
-
-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);
-
-	card->index = atomic_inc_return(&index);
-	card->driver = driver;
-	card->device = device;
-	card->current_tlabel = 0;
-	card->tlabel_mask = 0;
-	card->color = 0;
-	card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;
-
-	kref_init(&card->kref);
-	init_completion(&card->done);
-	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;
-	int ret;
-
-	card->max_receive = max_receive;
-	card->link_speed = link_speed;
-	card->guid = guid;
-
-	mutex_lock(&card_mutex);
-	config_rom = generate_config_rom(card, &length);
-	list_add_tail(&card->link, &card_list);
-	mutex_unlock(&card_mutex);
-
-	ret = card->driver->enable(card, config_rom, length);
-	if (ret < 0) {
-		mutex_lock(&card_mutex);
-		list_del(&card->link);
-		mutex_unlock(&card_mutex);
-	}
-
-	return ret;
-}
-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 = {
-	.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_card_release(struct kref *kref)
-{
-	struct fw_card *card = container_of(kref, struct fw_card, kref);
-
-	complete(&card->done);
-}
-
-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_init(&card->link);
-	mutex_unlock(&card_mutex);
-
-	/* Set up the dummy driver. */
-	card->driver = &dummy_driver;
-
-	fw_destroy_nodes(card);
-
-	/* Wait for all users, especially device workqueue jobs, to finish. */
-	fw_card_put(card);
-	wait_for_completion(&card->done);
-
-	WARN_ON(!list_empty(&card->transaction_list));
-	del_timer_sync(&card->flush_timer);
-}
-EXPORT_SYMBOL(fw_core_remove_card);
-
-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 -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-cdev.c linux-libre-2.6.31-gnu/drivers/firewire/fw-cdev.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-cdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-cdev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1463 +0,0 @@
-/*
- * 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/compat.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/firewire-cdev.h>
-#include <linux/idr.h>
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/kref.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-#include <linux/preempt.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "fw-device.h"
-#include "fw-topology.h"
-#include "fw-transaction.h"
-
-struct client {
-	u32 version;
-	struct fw_device *device;
-
-	spinlock_t lock;
-	bool in_shutdown;
-	struct idr resource_idr;
-	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;
-	struct kref kref;
-};
-
-static inline void client_get(struct client *client)
-{
-	kref_get(&client->kref);
-}
-
-static void client_release(struct kref *kref)
-{
-	struct client *client = container_of(kref, struct client, kref);
-
-	fw_device_put(client->device);
-	kfree(client);
-}
-
-static void client_put(struct client *client)
-{
-	kref_put(&client->kref, client_release);
-}
-
-struct client_resource;
-typedef void (*client_resource_release_fn_t)(struct client *,
-					     struct client_resource *);
-struct client_resource {
-	client_resource_release_fn_t release;
-	int handle;
-};
-
-struct address_handler_resource {
-	struct client_resource resource;
-	struct fw_address_handler handler;
-	__u64 closure;
-	struct client *client;
-};
-
-struct outbound_transaction_resource {
-	struct client_resource resource;
-	struct fw_transaction transaction;
-};
-
-struct inbound_transaction_resource {
-	struct client_resource resource;
-	struct fw_request *request;
-	void *data;
-	size_t length;
-};
-
-struct descriptor_resource {
-	struct client_resource resource;
-	struct fw_descriptor descriptor;
-	u32 data[0];
-};
-
-struct iso_resource {
-	struct client_resource resource;
-	struct client *client;
-	/* Schedule work and access todo only with client->lock held. */
-	struct delayed_work work;
-	enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,
-	      ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo;
-	int generation;
-	u64 channels;
-	s32 bandwidth;
-	struct iso_resource_event *e_alloc, *e_dealloc;
-};
-
-static void schedule_iso_resource(struct iso_resource *);
-static void release_iso_resource(struct client *, struct client_resource *);
-
-/*
- * dequeue_event() just kfree()'s the event, so the event has to be
- * the first field in a struct XYZ_event.
- */
-struct event {
-	struct { void *data; size_t size; } v[2];
-	struct list_head link;
-};
-
-struct bus_reset_event {
-	struct event event;
-	struct fw_cdev_event_bus_reset reset;
-};
-
-struct outbound_transaction_event {
-	struct event event;
-	struct client *client;
-	struct outbound_transaction_resource r;
-	struct fw_cdev_event_response response;
-};
-
-struct inbound_transaction_event {
-	struct event event;
-	struct fw_cdev_event_request request;
-};
-
-struct iso_interrupt_event {
-	struct event event;
-	struct fw_cdev_event_iso_interrupt interrupt;
-};
-
-struct iso_resource_event {
-	struct event event;
-	struct fw_cdev_event_iso_resource resource;
-};
-
-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;
-
-	device = fw_device_get_by_devt(inode->i_rdev);
-	if (device == NULL)
-		return -ENODEV;
-
-	if (fw_device_is_shutdown(device)) {
-		fw_device_put(device);
-		return -ENODEV;
-	}
-
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (client == NULL) {
-		fw_device_put(device);
-		return -ENOMEM;
-	}
-
-	client->device = device;
-	spin_lock_init(&client->lock);
-	idr_init(&client->resource_idr);
-	INIT_LIST_HEAD(&client->event_list);
-	init_waitqueue_head(&client->wait);
-	kref_init(&client->kref);
-
-	file->private_data = client;
-
-	mutex_lock(&device->client_list_mutex);
-	list_add_tail(&client->link, &device->client_list);
-	mutex_unlock(&device->client_list_mutex);
-
-	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);
-	if (client->in_shutdown)
-		kfree(event);
-	else
-		list_add_tail(&event->link, &client->event_list);
-	spin_unlock_irqrestore(&client->lock, flags);
-
-	wake_up_interruptible(&client->wait);
-}
-
-static int dequeue_event(struct client *client,
-			 char __user *buffer, size_t count)
-{
-	struct event *event;
-	size_t size, total;
-	int i, ret;
-
-	ret = wait_event_interruptible(client->wait,
-			!list_empty(&client->event_list) ||
-			fw_device_is_shutdown(client->device));
-	if (ret < 0)
-		return ret;
-
-	if (list_empty(&client->event_list) &&
-		       fw_device_is_shutdown(client->device))
-		return -ENODEV;
-
-	spin_lock_irq(&client->lock);
-	event = list_first_entry(&client->event_list, struct event, link);
-	list_del(&event->link);
-	spin_unlock_irq(&client->lock);
-
-	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)) {
-			ret = -EFAULT;
-			goto out;
-		}
-		total += size;
-	}
-	ret = total;
-
- out:
-	kfree(event);
-
-	return ret;
-}
-
-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;
-
-	spin_lock_irq(&card->lock);
-
-	event->closure	     = client->bus_reset_closure;
-	event->type          = FW_CDEV_EVENT_BUS_RESET;
-	event->generation    = client->device->generation;
-	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;
-
-	spin_unlock_irq(&card->lock);
-}
-
-static void for_each_client(struct fw_device *device,
-			    void (*callback)(struct client *client))
-{
-	struct client *c;
-
-	mutex_lock(&device->client_list_mutex);
-	list_for_each_entry(c, &device->client_list, link)
-		callback(c);
-	mutex_unlock(&device->client_list_mutex);
-}
-
-static int schedule_reallocations(int id, void *p, void *data)
-{
-	struct client_resource *r = p;
-
-	if (r->release == release_iso_resource)
-		schedule_iso_resource(container_of(r,
-					struct iso_resource, resource));
-	return 0;
-}
-
-static void queue_bus_reset_event(struct client *client)
-{
-	struct bus_reset_event *e;
-
-	e = kzalloc(sizeof(*e), GFP_KERNEL);
-	if (e == NULL) {
-		fw_notify("Out of memory when allocating bus reset event\n");
-		return;
-	}
-
-	fill_bus_reset_event(&e->reset, client);
-
-	queue_event(client, &e->event,
-		    &e->reset, sizeof(e->reset), NULL, 0);
-
-	spin_lock_irq(&client->lock);
-	idr_for_each(&client->resource_idr, schedule_reallocations, client);
-	spin_unlock_irq(&client->lock);
-}
-
-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;
-	unsigned long ret = 0;
-
-	client->version = get_info->version;
-	get_info->version = FW_CDEV_VERSION;
-	get_info->card = client->device->card->index;
-
-	down_read(&fw_device_rwsem);
-
-	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;
-
-		ret = copy_to_user(uptr, client->device->config_rom,
-				   min(want, have));
-	}
-	get_info->rom_length = client->device->config_rom_length * 4;
-
-	up_read(&fw_device_rwsem);
-
-	if (ret != 0)
-		return -EFAULT;
-
-	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;
-	}
-
-	return 0;
-}
-
-static int add_client_resource(struct client *client,
-			       struct client_resource *resource, gfp_t gfp_mask)
-{
-	unsigned long flags;
-	int ret;
-
- retry:
-	if (idr_pre_get(&client->resource_idr, gfp_mask) == 0)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&client->lock, flags);
-	if (client->in_shutdown)
-		ret = -ECANCELED;
-	else
-		ret = idr_get_new(&client->resource_idr, resource,
-				  &resource->handle);
-	if (ret >= 0) {
-		client_get(client);
-		if (resource->release == release_iso_resource)
-			schedule_iso_resource(container_of(resource,
-						struct iso_resource, resource));
-	}
-	spin_unlock_irqrestore(&client->lock, flags);
-
-	if (ret == -EAGAIN)
-		goto retry;
-
-	return ret < 0 ? ret : 0;
-}
-
-static int release_client_resource(struct client *client, u32 handle,
-				   client_resource_release_fn_t release,
-				   struct client_resource **resource)
-{
-	struct client_resource *r;
-
-	spin_lock_irq(&client->lock);
-	if (client->in_shutdown)
-		r = NULL;
-	else
-		r = idr_find(&client->resource_idr, handle);
-	if (r && r->release == release)
-		idr_remove(&client->resource_idr, handle);
-	spin_unlock_irq(&client->lock);
-
-	if (!(r && r->release == release))
-		return -EINVAL;
-
-	if (resource)
-		*resource = r;
-	else
-		r->release(client, r);
-
-	client_put(client);
-
-	return 0;
-}
-
-static void release_transaction(struct client *client,
-				struct client_resource *resource)
-{
-	struct outbound_transaction_resource *r = container_of(resource,
-			struct outbound_transaction_resource, resource);
-
-	fw_cancel_transaction(client->device->card, &r->transaction);
-}
-
-static void complete_transaction(struct fw_card *card, int rcode,
-				 void *payload, size_t length, void *data)
-{
-	struct outbound_transaction_event *e = data;
-	struct fw_cdev_event_response *rsp = &e->response;
-	struct client *client = e->client;
-	unsigned long flags;
-
-	if (length < rsp->length)
-		rsp->length = length;
-	if (rcode == RCODE_COMPLETE)
-		memcpy(rsp->data, payload, rsp->length);
-
-	spin_lock_irqsave(&client->lock, flags);
-	/*
-	 * 1. If called while in shutdown, the idr tree must be left untouched.
-	 *    The idr handle will be removed and the client reference will be
-	 *    dropped later.
-	 * 2. If the call chain was release_client_resource ->
-	 *    release_transaction -> complete_transaction (instead of a normal
-	 *    conclusion of the transaction), i.e. if this resource was already
-	 *    unregistered from the idr, the client reference will be dropped
-	 *    by release_client_resource and we must not drop it here.
-	 */
-	if (!client->in_shutdown &&
-	    idr_find(&client->resource_idr, e->r.resource.handle)) {
-		idr_remove(&client->resource_idr, e->r.resource.handle);
-		/* Drop the idr's reference */
-		client_put(client);
-	}
-	spin_unlock_irqrestore(&client->lock, flags);
-
-	rsp->type = FW_CDEV_EVENT_RESPONSE;
-	rsp->rcode = rcode;
-
-	/*
-	 * In the case that sizeof(*rsp) doesn't align with the position of the
-	 * data, and the read is short, preserve an extra copy of the data
-	 * to stay compatible with a pre-2.6.27 bug.  Since the bug is harmless
-	 * for short reads and some apps depended on it, this is both safe
-	 * and prudent for compatibility.
-	 */
-	if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data))
-		queue_event(client, &e->event, rsp, sizeof(*rsp),
-			    rsp->data, rsp->length);
-	else
-		queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
-			    NULL, 0);
-
-	/* Drop the transaction callback's reference */
-	client_put(client);
-}
-
-static int init_request(struct client *client,
-			struct fw_cdev_send_request *request,
-			int destination_id, int speed)
-{
-	struct outbound_transaction_event *e;
-	int ret;
-
-	if (request->tcode != TCODE_STREAM_DATA &&
-	    (request->length > 4096 || request->length > 512 << speed))
-		return -EIO;
-
-	e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
-	if (e == NULL)
-		return -ENOMEM;
-
-	e->client = client;
-	e->response.length = request->length;
-	e->response.closure = request->closure;
-
-	if (request->data &&
-	    copy_from_user(e->response.data,
-			   u64_to_uptr(request->data), request->length)) {
-		ret = -EFAULT;
-		goto failed;
-	}
-
-	e->r.resource.release = release_transaction;
-	ret = add_client_resource(client, &e->r.resource, GFP_KERNEL);
-	if (ret < 0)
-		goto failed;
-
-	/* Get a reference for the transaction callback */
-	client_get(client);
-
-	fw_send_request(client->device->card, &e->r.transaction,
-			request->tcode, destination_id, request->generation,
-			speed, request->offset, e->response.data,
-			request->length, complete_transaction, e);
-	return 0;
-
- failed:
-	kfree(e);
-
-	return ret;
-}
-
-static int ioctl_send_request(struct client *client, void *buffer)
-{
-	struct fw_cdev_send_request *request = buffer;
-
-	switch (request->tcode) {
-	case TCODE_WRITE_QUADLET_REQUEST:
-	case TCODE_WRITE_BLOCK_REQUEST:
-	case TCODE_READ_QUADLET_REQUEST:
-	case TCODE_READ_BLOCK_REQUEST:
-	case TCODE_LOCK_MASK_SWAP:
-	case TCODE_LOCK_COMPARE_SWAP:
-	case TCODE_LOCK_FETCH_ADD:
-	case TCODE_LOCK_LITTLE_ADD:
-	case TCODE_LOCK_BOUNDED_ADD:
-	case TCODE_LOCK_WRAP_ADD:
-	case TCODE_LOCK_VENDOR_DEPENDENT:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return init_request(client, request, client->device->node_id,
-			    client->device->max_speed);
-}
-
-static void release_request(struct client *client,
-			    struct client_resource *resource)
-{
-	struct inbound_transaction_resource *r = container_of(resource,
-			struct inbound_transaction_resource, resource);
-
-	fw_send_response(client->device->card, r->request,
-			 RCODE_CONFLICT_ERROR);
-	kfree(r);
-}
-
-static void handle_request(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 address_handler_resource *handler = callback_data;
-	struct inbound_transaction_resource *r;
-	struct inbound_transaction_event *e;
-	int ret;
-
-	r = kmalloc(sizeof(*r), GFP_ATOMIC);
-	e = kmalloc(sizeof(*e), GFP_ATOMIC);
-	if (r == NULL || e == NULL)
-		goto failed;
-
-	r->request = request;
-	r->data    = payload;
-	r->length  = length;
-
-	r->resource.release = release_request;
-	ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
-	if (ret < 0)
-		goto failed;
-
-	e->request.type    = FW_CDEV_EVENT_REQUEST;
-	e->request.tcode   = tcode;
-	e->request.offset  = offset;
-	e->request.length  = length;
-	e->request.handle  = r->resource.handle;
-	e->request.closure = handler->closure;
-
-	queue_event(handler->client, &e->event,
-		    &e->request, sizeof(e->request), payload, length);
-	return;
-
- failed:
-	kfree(r);
-	kfree(e);
-	fw_send_response(card, request, RCODE_CONFLICT_ERROR);
-}
-
-static void release_address_handler(struct client *client,
-				    struct client_resource *resource)
-{
-	struct address_handler_resource *r =
-	    container_of(resource, struct address_handler_resource, resource);
-
-	fw_core_remove_address_handler(&r->handler);
-	kfree(r);
-}
-
-static int ioctl_allocate(struct client *client, void *buffer)
-{
-	struct fw_cdev_allocate *request = buffer;
-	struct address_handler_resource *r;
-	struct fw_address_region region;
-	int ret;
-
-	r = kmalloc(sizeof(*r), GFP_KERNEL);
-	if (r == NULL)
-		return -ENOMEM;
-
-	region.start = request->offset;
-	region.end = request->offset + request->length;
-	r->handler.length = request->length;
-	r->handler.address_callback = handle_request;
-	r->handler.callback_data = r;
-	r->closure = request->closure;
-	r->client = client;
-
-	ret = fw_core_add_address_handler(&r->handler, &region);
-	if (ret < 0) {
-		kfree(r);
-		return ret;
-	}
-
-	r->resource.release = release_address_handler;
-	ret = add_client_resource(client, &r->resource, GFP_KERNEL);
-	if (ret < 0) {
-		release_address_handler(client, &r->resource);
-		return ret;
-	}
-	request->handle = r->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,
-				       release_address_handler, NULL);
-}
-
-static int ioctl_send_response(struct client *client, void *buffer)
-{
-	struct fw_cdev_send_response *request = buffer;
-	struct client_resource *resource;
-	struct inbound_transaction_resource *r;
-
-	if (release_client_resource(client, request->handle,
-				    release_request, &resource) < 0)
-		return -EINVAL;
-
-	r = container_of(resource, struct inbound_transaction_resource,
-			 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);
-}
-
-static void release_descriptor(struct client *client,
-			       struct client_resource *resource)
-{
-	struct descriptor_resource *r =
-		container_of(resource, struct descriptor_resource, resource);
-
-	fw_core_remove_descriptor(&r->descriptor);
-	kfree(r);
-}
-
-static int ioctl_add_descriptor(struct client *client, void *buffer)
-{
-	struct fw_cdev_add_descriptor *request = buffer;
-	struct fw_card *card = client->device->card;
-	struct descriptor_resource *r;
-	int ret;
-
-	/* Access policy: Allow this ioctl only on local nodes' device files. */
-	spin_lock_irq(&card->lock);
-	ret = client->device->node_id != card->local_node->node_id;
-	spin_unlock_irq(&card->lock);
-	if (ret)
-		return -ENOSYS;
-
-	if (request->length > 256)
-		return -EINVAL;
-
-	r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL);
-	if (r == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(r->data,
-			   u64_to_uptr(request->data), request->length * 4)) {
-		ret = -EFAULT;
-		goto failed;
-	}
-
-	r->descriptor.length    = request->length;
-	r->descriptor.immediate = request->immediate;
-	r->descriptor.key       = request->key;
-	r->descriptor.data      = r->data;
-
-	ret = fw_core_add_descriptor(&r->descriptor);
-	if (ret < 0)
-		goto failed;
-
-	r->resource.release = release_descriptor;
-	ret = add_client_resource(client, &r->resource, GFP_KERNEL);
-	if (ret < 0) {
-		fw_core_remove_descriptor(&r->descriptor);
-		goto failed;
-	}
-	request->handle = r->resource.handle;
-
-	return 0;
- failed:
-	kfree(r);
-
-	return ret;
-}
-
-static int ioctl_remove_descriptor(struct client *client, void *buffer)
-{
-	struct fw_cdev_remove_descriptor *request = buffer;
-
-	return release_client_resource(client, request->handle,
-				       release_descriptor, 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_event *e;
-
-	e = kzalloc(sizeof(*e) + header_length, GFP_ATOMIC);
-	if (e == NULL)
-		return;
-
-	e->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
-	e->interrupt.closure   = client->iso_closure;
-	e->interrupt.cycle     = cycle;
-	e->interrupt.header_length = header_length;
-	memcpy(e->interrupt.header, header, header_length);
-	queue_event(client, &e->event, &e->interrupt,
-		    sizeof(e->interrupt) + header_length, NULL, 0);
-}
-
-static int ioctl_create_iso_context(struct client *client, void *buffer)
-{
-	struct fw_cdev_create_iso_context *request = buffer;
-	struct fw_iso_context *context;
-
-	/* We only support one context at this time. */
-	if (client->iso_context != NULL)
-		return -EBUSY;
-
-	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;
-	}
-
-	context =  fw_iso_context_create(client->device->card,
-					 request->type,
-					 request->channel,
-					 request->speed,
-					 request->header_size,
-					 iso_callback, client);
-	if (IS_ERR(context))
-		return PTR_ERR(context);
-
-	client->iso_closure = request->closure;
-	client->iso_context = context;
-
-	/* We only support one context at this time. */
-	request->handle = 0;
-
-	return 0;
-}
-
-/* Macros for decoding the iso packet control header. */
-#define GET_PAYLOAD_LENGTH(v)	((v) & 0xffff)
-#define GET_INTERRUPT(v)	(((v) >> 16) & 0x01)
-#define GET_SKIP(v)		(((v) >> 17) & 0x01)
-#define GET_TAG(v)		(((v) >> 18) & 0x03)
-#define GET_SY(v)		(((v) >> 20) & 0x0f)
-#define GET_HEADER_LENGTH(v)	(((v) >> 24) & 0xff)
-
-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;
-	u32 control;
-	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;
-	}
-
-	p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets);
-
-	if (!access_ok(VERIFY_READ, p, request->size))
-		return -EFAULT;
-
-	end = (void __user *)p + request->size;
-	count = 0;
-	while (p < end) {
-		if (get_user(control, &p->control))
-			return -EFAULT;
-		u.packet.payload_length = GET_PAYLOAD_LENGTH(control);
-		u.packet.interrupt = GET_INTERRUPT(control);
-		u.packet.skip = GET_SKIP(control);
-		u.packet.tag = GET_TAG(control);
-		u.packet.sy = GET_SY(control);
-		u.packet.header_length = GET_HEADER_LENGTH(control);
-
-		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 (client->iso_context == NULL || 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 (client->iso_context == NULL || request->handle != 0)
-		return -EINVAL;
-
-	return fw_iso_context_stop(client->iso_context);
-}
-
-static int ioctl_get_cycle_timer(struct client *client, void *buffer)
-{
-	struct fw_cdev_get_cycle_timer *request = buffer;
-	struct fw_card *card = client->device->card;
-	unsigned long long bus_time;
-	struct timeval tv;
-	unsigned long flags;
-
-	preempt_disable();
-	local_irq_save(flags);
-
-	bus_time = card->driver->get_bus_time(card);
-	do_gettimeofday(&tv);
-
-	local_irq_restore(flags);
-	preempt_enable();
-
-	request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
-	request->cycle_timer = bus_time & 0xffffffff;
-	return 0;
-}
-
-static void iso_resource_work(struct work_struct *work)
-{
-	struct iso_resource_event *e;
-	struct iso_resource *r =
-			container_of(work, struct iso_resource, work.work);
-	struct client *client = r->client;
-	int generation, channel, bandwidth, todo;
-	bool skip, free, success;
-
-	spin_lock_irq(&client->lock);
-	generation = client->device->generation;
-	todo = r->todo;
-	/* Allow 1000ms grace period for other reallocations. */
-	if (todo == ISO_RES_ALLOC &&
-	    time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
-		if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3)))
-			client_get(client);
-		skip = true;
-	} else {
-		/* We could be called twice within the same generation. */
-		skip = todo == ISO_RES_REALLOC &&
-		       r->generation == generation;
-	}
-	free = todo == ISO_RES_DEALLOC ||
-	       todo == ISO_RES_ALLOC_ONCE ||
-	       todo == ISO_RES_DEALLOC_ONCE;
-	r->generation = generation;
-	spin_unlock_irq(&client->lock);
-
-	if (skip)
-		goto out;
-
-	bandwidth = r->bandwidth;
-
-	fw_iso_resource_manage(client->device->card, generation,
-			r->channels, &channel, &bandwidth,
-			todo == ISO_RES_ALLOC ||
-			todo == ISO_RES_REALLOC ||
-			todo == ISO_RES_ALLOC_ONCE);
-	/*
-	 * Is this generation outdated already?  As long as this resource sticks
-	 * in the idr, it will be scheduled again for a newer generation or at
-	 * shutdown.
-	 */
-	if (channel == -EAGAIN &&
-	    (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC))
-		goto out;
-
-	success = channel >= 0 || bandwidth > 0;
-
-	spin_lock_irq(&client->lock);
-	/*
-	 * Transit from allocation to reallocation, except if the client
-	 * requested deallocation in the meantime.
-	 */
-	if (r->todo == ISO_RES_ALLOC)
-		r->todo = ISO_RES_REALLOC;
-	/*
-	 * Allocation or reallocation failure?  Pull this resource out of the
-	 * idr and prepare for deletion, unless the client is shutting down.
-	 */
-	if (r->todo == ISO_RES_REALLOC && !success &&
-	    !client->in_shutdown &&
-	    idr_find(&client->resource_idr, r->resource.handle)) {
-		idr_remove(&client->resource_idr, r->resource.handle);
-		client_put(client);
-		free = true;
-	}
-	spin_unlock_irq(&client->lock);
-
-	if (todo == ISO_RES_ALLOC && channel >= 0)
-		r->channels = 1ULL << channel;
-
-	if (todo == ISO_RES_REALLOC && success)
-		goto out;
-
-	if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) {
-		e = r->e_alloc;
-		r->e_alloc = NULL;
-	} else {
-		e = r->e_dealloc;
-		r->e_dealloc = NULL;
-	}
-	e->resource.handle	= r->resource.handle;
-	e->resource.channel	= channel;
-	e->resource.bandwidth	= bandwidth;
-
-	queue_event(client, &e->event,
-		    &e->resource, sizeof(e->resource), NULL, 0);
-
-	if (free) {
-		cancel_delayed_work(&r->work);
-		kfree(r->e_alloc);
-		kfree(r->e_dealloc);
-		kfree(r);
-	}
- out:
-	client_put(client);
-}
-
-static void schedule_iso_resource(struct iso_resource *r)
-{
-	client_get(r->client);
-	if (!schedule_delayed_work(&r->work, 0))
-		client_put(r->client);
-}
-
-static void release_iso_resource(struct client *client,
-				 struct client_resource *resource)
-{
-	struct iso_resource *r =
-		container_of(resource, struct iso_resource, resource);
-
-	spin_lock_irq(&client->lock);
-	r->todo = ISO_RES_DEALLOC;
-	schedule_iso_resource(r);
-	spin_unlock_irq(&client->lock);
-}
-
-static int init_iso_resource(struct client *client,
-		struct fw_cdev_allocate_iso_resource *request, int todo)
-{
-	struct iso_resource_event *e1, *e2;
-	struct iso_resource *r;
-	int ret;
-
-	if ((request->channels == 0 && request->bandwidth == 0) ||
-	    request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL ||
-	    request->bandwidth < 0)
-		return -EINVAL;
-
-	r  = kmalloc(sizeof(*r), GFP_KERNEL);
-	e1 = kmalloc(sizeof(*e1), GFP_KERNEL);
-	e2 = kmalloc(sizeof(*e2), GFP_KERNEL);
-	if (r == NULL || e1 == NULL || e2 == NULL) {
-		ret = -ENOMEM;
-		goto fail;
-	}
-
-	INIT_DELAYED_WORK(&r->work, iso_resource_work);
-	r->client	= client;
-	r->todo		= todo;
-	r->generation	= -1;
-	r->channels	= request->channels;
-	r->bandwidth	= request->bandwidth;
-	r->e_alloc	= e1;
-	r->e_dealloc	= e2;
-
-	e1->resource.closure	= request->closure;
-	e1->resource.type	= FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
-	e2->resource.closure	= request->closure;
-	e2->resource.type	= FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
-
-	if (todo == ISO_RES_ALLOC) {
-		r->resource.release = release_iso_resource;
-		ret = add_client_resource(client, &r->resource, GFP_KERNEL);
-		if (ret < 0)
-			goto fail;
-	} else {
-		r->resource.release = NULL;
-		r->resource.handle = -1;
-		schedule_iso_resource(r);
-	}
-	request->handle = r->resource.handle;
-
-	return 0;
- fail:
-	kfree(r);
-	kfree(e1);
-	kfree(e2);
-
-	return ret;
-}
-
-static int ioctl_allocate_iso_resource(struct client *client, void *buffer)
-{
-	struct fw_cdev_allocate_iso_resource *request = buffer;
-
-	return init_iso_resource(client, request, ISO_RES_ALLOC);
-}
-
-static int ioctl_deallocate_iso_resource(struct client *client, void *buffer)
-{
-	struct fw_cdev_deallocate *request = buffer;
-
-	return release_client_resource(client, request->handle,
-				       release_iso_resource, NULL);
-}
-
-static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer)
-{
-	struct fw_cdev_allocate_iso_resource *request = buffer;
-
-	return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE);
-}
-
-static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer)
-{
-	struct fw_cdev_allocate_iso_resource *request = buffer;
-
-	return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE);
-}
-
-/*
- * Returns a speed code:  Maximum speed to or from this device,
- * limited by the device's link speed, the local node's link speed,
- * and all PHY port speeds between the two links.
- */
-static int ioctl_get_speed(struct client *client, void *buffer)
-{
-	return client->device->max_speed;
-}
-
-static int ioctl_send_broadcast_request(struct client *client, void *buffer)
-{
-	struct fw_cdev_send_request *request = buffer;
-
-	switch (request->tcode) {
-	case TCODE_WRITE_QUADLET_REQUEST:
-	case TCODE_WRITE_BLOCK_REQUEST:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Security policy: Only allow accesses to Units Space. */
-	if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END)
-		return -EACCES;
-
-	return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100);
-}
-
-static int ioctl_send_stream_packet(struct client *client, void *buffer)
-{
-	struct fw_cdev_send_stream_packet *p = buffer;
-	struct fw_cdev_send_request request;
-	int dest;
-
-	if (p->speed > client->device->card->link_speed ||
-	    p->length > 1024 << p->speed)
-		return -EIO;
-
-	if (p->tag > 3 || p->channel > 63 || p->sy > 15)
-		return -EINVAL;
-
-	dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy);
-	request.tcode		= TCODE_STREAM_DATA;
-	request.length		= p->length;
-	request.closure		= p->closure;
-	request.data		= p->data;
-	request.generation	= p->generation;
-
-	return init_request(client, &request, dest, p->speed);
-}
-
-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,
-	ioctl_get_cycle_timer,
-	ioctl_allocate_iso_resource,
-	ioctl_deallocate_iso_resource,
-	ioctl_allocate_iso_resource_once,
-	ioctl_deallocate_iso_resource_once,
-	ioctl_get_speed,
-	ioctl_send_broadcast_request,
-	ioctl_send_stream_packet,
-};
-
-static int dispatch_ioctl(struct client *client,
-			  unsigned int cmd, void __user *arg)
-{
-	char buffer[256];
-	int ret;
-
-	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;
-	}
-
-	ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer);
-	if (ret < 0)
-		return ret;
-
-	if (_IOC_DIR(cmd) & _IOC_READ) {
-		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
-		    copy_to_user(arg, buffer, _IOC_SIZE(cmd)))
-			return -EFAULT;
-	}
-
-	return ret;
-}
-
-static long fw_device_op_ioctl(struct file *file,
-			       unsigned int cmd, unsigned long arg)
-{
-	struct client *client = file->private_data;
-
-	if (fw_device_is_shutdown(client->device))
-		return -ENODEV;
-
-	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;
-
-	if (fw_device_is_shutdown(client->device))
-		return -ENODEV;
-
-	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, ret;
-
-	if (fw_device_is_shutdown(client->device))
-		return -ENODEV;
-
-	/* 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;
-
-	ret = fw_iso_buffer_init(&client->buffer, client->device->card,
-				 page_count, direction);
-	if (ret < 0)
-		return ret;
-
-	ret = fw_iso_buffer_map(&client->buffer, vma);
-	if (ret < 0)
-		fw_iso_buffer_destroy(&client->buffer, client->device->card);
-
-	return ret;
-}
-
-static int shutdown_resource(int id, void *p, void *data)
-{
-	struct client_resource *r = p;
-	struct client *client = data;
-
-	r->release(client, r);
-	client_put(client);
-
-	return 0;
-}
-
-static int fw_device_op_release(struct inode *inode, struct file *file)
-{
-	struct client *client = file->private_data;
-	struct event *e, *next_e;
-
-	mutex_lock(&client->device->client_list_mutex);
-	list_del(&client->link);
-	mutex_unlock(&client->device->client_list_mutex);
-
-	if (client->iso_context)
-		fw_iso_context_destroy(client->iso_context);
-
-	if (client->buffer.pages)
-		fw_iso_buffer_destroy(&client->buffer, client->device->card);
-
-	/* Freeze client->resource_idr and client->event_list */
-	spin_lock_irq(&client->lock);
-	client->in_shutdown = true;
-	spin_unlock_irq(&client->lock);
-
-	idr_for_each(&client->resource_idr, shutdown_resource, client);
-	idr_remove_all(&client->resource_idr);
-	idr_destroy(&client->resource_idr);
-
-	list_for_each_entry_safe(e, next_e, &client->event_list, link)
-		kfree(e);
-
-	client_put(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 -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-device.c linux-libre-2.6.31-gnu/drivers/firewire/fw-device.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-device.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-device.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1122 +0,0 @@
-/*
- * 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/ctype.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/idr.h>
-#include <linux/jiffies.h>
-#include <linux/kobject.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/rwsem.h>
-#include <linux/semaphore.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/workqueue.h>
-
-#include <asm/system.h>
-
-#include "fw-device.h"
-#include "fw-topology.h"
-#include "fw-transaction.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, struct kobj_uevent_env *env)
-{
-	struct fw_unit *unit = fw_unit(dev);
-	char modalias[64];
-
-	get_modalias(unit, modalias, sizeof(modalias));
-
-	if (add_uevent_var(env, "MODALIAS=%s", modalias))
-		return -ENOMEM;
-
-	return 0;
-}
-
-struct bus_type fw_bus_type = {
-	.name = "firewire",
-	.match = fw_unit_match,
-};
-EXPORT_SYMBOL(fw_bus_type);
-
-int fw_device_enable_phys_dma(struct fw_device *device)
-{
-	int generation = device->generation;
-
-	/* device->node_id, accessed below, must not be older than generation */
-	smp_rmb();
-
-	return device->card->driver->enable_phys_dma(device->card,
-						     device->node_id,
-						     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, ret = -ENOENT;
-
-	down_read(&fw_device_rwsem);
-
-	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) {
-			ret = snprintf(buf, buf ? PAGE_SIZE : 0,
-				       "0x%06x\n", value);
-			break;
-		}
-
-	up_read(&fw_device_rwsem);
-
-	return ret;
-}
-
-#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, ret = -ENOENT;
-	char *b;
-
-	down_read(&fw_device_rwsem);
-
-	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)
-		goto out;
-
-	length = min(block[0] >> 16, 256U);
-	if (length < 3)
-		goto out;
-
-	if (block[1] != 0 || block[2] != 0)
-		/* Unknown encoding. */
-		goto out;
-
-	if (buf == NULL) {
-		ret = length * 4;
-		goto out;
-	}
-
-	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");
-	ret = b + 2 - buf;
- out:
-	up_read(&fw_device_rwsem);
-
-	return ret;
-}
-
-#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);
-	size_t length;
-
-	down_read(&fw_device_rwsem);
-	length = device->config_rom_length * 4;
-	memcpy(buf, device->config_rom, length);
-	up_read(&fw_device_rwsem);
-
-	return length;
-}
-
-static ssize_t guid_show(struct device *dev,
-			 struct device_attribute *attr, char *buf)
-{
-	struct fw_device *device = fw_device(dev);
-	int ret;
-
-	down_read(&fw_device_rwsem);
-	ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
-		       device->config_rom[3], device->config_rom[4]);
-	up_read(&fw_device_rwsem);
-
-	return ret;
-}
-
-static struct device_attribute fw_device_attributes[] = {
-	__ATTR_RO(config_rom),
-	__ATTR_RO(guid),
-	__ATTR_NULL,
-};
-
-static int read_rom(struct fw_device *device,
-		    int generation, int index, u32 *data)
-{
-	int rcode;
-
-	/* device->node_id, accessed below, must not be older than generation */
-	smp_rmb();
-
-	rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
-			device->node_id, generation, device->max_speed,
-			(CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
-			data, 4);
-	be32_to_cpus(data);
-
-	return rcode;
-}
-
-#define READ_BIB_ROM_SIZE	256
-#define READ_BIB_STACK_SIZE	16
-
-/*
- * Read the bus info block, perform a speed probe, and read all of the rest of
- * the config ROM.  We do all this with a cached bus generation.  If the bus
- * generation changes under us, read_bus_info_block will fail and get retried.
- * It's better to start all over in this case because the node from which we
- * are reading the ROM may have changed the ROM during the reset.
- */
-static int read_bus_info_block(struct fw_device *device, int generation)
-{
-	u32 *rom, *stack, *old_rom, *new_rom;
-	u32 sp, key;
-	int i, end, length, ret = -1;
-
-	rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
-		      sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
-	if (rom == NULL)
-		return -ENOMEM;
-
-	stack = &rom[READ_BIB_ROM_SIZE];
-
-	device->max_speed = SCODE_100;
-
-	/* First read the bus info block. */
-	for (i = 0; i < 5; i++) {
-		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
-			goto out;
-		/*
-		 * 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)
-			goto out;
-	}
-
-	device->max_speed = device->node->max_speed;
-
-	/*
-	 * Determine the speed of
-	 *   - devices with link speed less than PHY speed,
-	 *   - devices with 1394b PHY (unless only connected to 1394a PHYs),
-	 *   - all devices if there are 1394b repeaters.
-	 * Note, we cannot use the bus info block's link_spd as starting point
-	 * because some buggy firmwares set it lower than necessary and because
-	 * 1394-1995 nodes do not have the field.
-	 */
-	if ((rom[2] & 0x7) < device->max_speed ||
-	    device->max_speed == SCODE_BETA ||
-	    device->card->beta_repeaters_present) {
-		u32 dummy;
-
-		/* for S1600 and S3200 */
-		if (device->max_speed == SCODE_BETA)
-			device->max_speed = device->card->link_speed;
-
-		while (device->max_speed > SCODE_100) {
-			if (read_rom(device, generation, 0, &dummy) ==
-			    RCODE_COMPLETE)
-				break;
-			device->max_speed--;
-		}
-	}
-
-	/*
-	 * 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 >= READ_BIB_ROM_SIZE)
-			/*
-			 * The reference points outside the standard
-			 * config rom area, something's fishy.
-			 */
-			goto out;
-
-		/* Read header quadlet for the block to get the length. */
-		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
-			goto out;
-		end = i + (rom[i] >> 16) + 1;
-		i++;
-		if (end > READ_BIB_ROM_SIZE)
-			/*
-			 * This block extends outside standard config
-			 * area (and the array we're reading it
-			 * into).  That's broken, so ignore this
-			 * device.
-			 */
-			goto out;
-
-		/*
-		 * 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, generation, i, &rom[i]) !=
-			    RCODE_COMPLETE)
-				goto out;
-			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
-			    sp < READ_BIB_STACK_SIZE)
-				stack[sp++] = i + rom[i];
-			i++;
-		}
-		if (length < i)
-			length = i;
-	}
-
-	old_rom = device->config_rom;
-	new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
-	if (new_rom == NULL)
-		goto out;
-
-	down_write(&fw_device_rwsem);
-	device->config_rom = new_rom;
-	device->config_rom_length = length;
-	up_write(&fw_device_rwsem);
-
-	kfree(old_rom);
-	ret = 0;
-	device->cmc = rom[2] >> 30 & 1;
- out:
-	kfree(rom);
-
-	return ret;
-}
-
-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;
-		dev_set_name(&unit->device, "%s.%d", dev_name(&device->device), 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;
-}
-
-/*
- * fw_device_rwsem acts as dual purpose mutex:
- *   - serializes accesses to fw_device_idr,
- *   - serializes accesses to fw_device.config_rom/.config_rom_length and
- *     fw_unit.directory, unless those accesses happen at safe occasions
- */
-DECLARE_RWSEM(fw_device_rwsem);
-
-DEFINE_IDR(fw_device_idr);
-int fw_cdev_major;
-
-struct fw_device *fw_device_get_by_devt(dev_t devt)
-{
-	struct fw_device *device;
-
-	down_read(&fw_device_rwsem);
-	device = idr_find(&fw_device_idr, MINOR(devt));
-	if (device)
-		fw_device_get(device);
-	up_read(&fw_device_rwsem);
-
-	return device;
-}
-
-/*
- * 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)
-#define SHUTDOWN_DELAY	(2 * HZ)
-
-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);
-
-	if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY)
-	    && !list_empty(&device->card->link)) {
-		schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
-		return;
-	}
-
-	if (atomic_cmpxchg(&device->state,
-			   FW_DEVICE_GONE,
-			   FW_DEVICE_SHUTDOWN) != FW_DEVICE_GONE)
-		return;
-
-	fw_device_cdev_remove(device);
-	device_for_each_child(&device->device, NULL, shutdown_unit);
-	device_unregister(&device->device);
-
-	down_write(&fw_device_rwsem);
-	idr_remove(&fw_device_idr, minor);
-	up_write(&fw_device_rwsem);
-
-	fw_device_put(device);
-}
-
-static void fw_device_release(struct device *dev)
-{
-	struct fw_device *device = fw_device(dev);
-	struct fw_card *card = device->card;
-	unsigned long flags;
-
-	/*
-	 * Take the card lock so we don't set this to NULL while a
-	 * FW_NODE_UPDATED callback is being handled or while the
-	 * bus manager work looks at this node.
-	 */
-	spin_lock_irqsave(&card->lock, flags);
-	device->node->data = NULL;
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	fw_node_put(device->node);
-	kfree(device->config_rom);
-	kfree(device);
-	fw_card_put(card);
-}
-
-static struct device_type fw_device_type = {
-	.release = fw_device_release,
-};
-
-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);
-}
-
-/*
- * If a device was pending for deletion because its node went away but its
- * bus info block and root directory header matches that of a newly discovered
- * device, revive the existing fw_device.
- * The newly allocated fw_device becomes obsolete instead.
- */
-static int lookup_existing_device(struct device *dev, void *data)
-{
-	struct fw_device *old = fw_device(dev);
-	struct fw_device *new = data;
-	struct fw_card *card = new->card;
-	int match = 0;
-
-	down_read(&fw_device_rwsem); /* serialize config_rom access */
-	spin_lock_irq(&card->lock);  /* serialize node access */
-
-	if (memcmp(old->config_rom, new->config_rom, 6 * 4) == 0 &&
-	    atomic_cmpxchg(&old->state,
-			   FW_DEVICE_GONE,
-			   FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
-		struct fw_node *current_node = new->node;
-		struct fw_node *obsolete_node = old->node;
-
-		new->node = obsolete_node;
-		new->node->data = new;
-		old->node = current_node;
-		old->node->data = old;
-
-		old->max_speed = new->max_speed;
-		old->node_id = current_node->node_id;
-		smp_wmb();  /* update node_id before generation */
-		old->generation = card->generation;
-		old->config_rom_retries = 0;
-		fw_notify("rediscovered device %s\n", dev_name(dev));
-
-		PREPARE_DELAYED_WORK(&old->work, fw_device_update);
-		schedule_delayed_work(&old->work, 0);
-
-		if (current_node == card->root_node)
-			fw_schedule_bm_work(card, 0);
-
-		match = 1;
-	}
-
-	spin_unlock_irq(&card->lock);
-	up_read(&fw_device_rwsem);
-
-	return match;
-}
-
-enum { BC_UNKNOWN = 0, BC_UNIMPLEMENTED, BC_IMPLEMENTED, };
-
-void fw_device_set_broadcast_channel(struct fw_device *device, int generation)
-{
-	struct fw_card *card = device->card;
-	__be32 data;
-	int rcode;
-
-	if (!card->broadcast_channel_allocated)
-		return;
-
-	if (device->bc_implemented == BC_UNKNOWN) {
-		rcode = fw_run_transaction(card, TCODE_READ_QUADLET_REQUEST,
-				device->node_id, generation, device->max_speed,
-				CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL,
-				&data, 4);
-		switch (rcode) {
-		case RCODE_COMPLETE:
-			if (data & cpu_to_be32(1 << 31)) {
-				device->bc_implemented = BC_IMPLEMENTED;
-				break;
-			}
-			/* else fall through to case address error */
-		case RCODE_ADDRESS_ERROR:
-			device->bc_implemented = BC_UNIMPLEMENTED;
-		}
-	}
-
-	if (device->bc_implemented == BC_IMPLEMENTED) {
-		data = cpu_to_be32(BROADCAST_CHANNEL_INITIAL |
-				   BROADCAST_CHANNEL_VALID);
-		fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,
-				device->node_id, generation, device->max_speed,
-				CSR_REGISTER_BASE + CSR_BROADCAST_CHANNEL,
-				&data, 4);
-	}
-}
-
-static void fw_device_init(struct work_struct *work)
-{
-	struct fw_device *device =
-		container_of(work, struct fw_device, work.work);
-	struct device *revived_dev;
-	int minor, ret;
-
-	/*
-	 * 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, device->generation) < 0) {
-		if (device->config_rom_retries < MAX_RETRIES &&
-		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
-			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)
-				fw_schedule_bm_work(device->card, 0);
-			fw_device_release(&device->device);
-		}
-		return;
-	}
-
-	revived_dev = device_find_child(device->card->device,
-					device, lookup_existing_device);
-	if (revived_dev) {
-		put_device(revived_dev);
-		fw_device_release(&device->device);
-
-		return;
-	}
-
-	device_initialize(&device->device);
-
-	fw_device_get(device);
-	down_write(&fw_device_rwsem);
-	ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ?
-	      idr_get_new(&fw_device_idr, device, &minor) :
-	      -ENOMEM;
-	up_write(&fw_device_rwsem);
-
-	if (ret < 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);
-	dev_set_name(&device->device, "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_GONE) {
-		PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
-		schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
-	} else {
-		if (device->config_rom_retries)
-			fw_notify("created device %s: GUID %08x%08x, S%d00, "
-				  "%d config ROM retries\n",
-				  dev_name(&device->device),
-				  device->config_rom[3], device->config_rom[4],
-				  1 << device->max_speed,
-				  device->config_rom_retries);
-		else
-			fw_notify("created device %s: GUID %08x%08x, S%d00\n",
-				  dev_name(&device->device),
-				  device->config_rom[3], device->config_rom[4],
-				  1 << device->max_speed);
-		device->config_rom_retries = 0;
-
-		fw_device_set_broadcast_channel(device, device->generation);
-	}
-
-	/*
-	 * 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)
-		fw_schedule_bm_work(device->card, 0);
-
-	return;
-
- error_with_cdev:
-	down_write(&fw_device_rwsem);
-	idr_remove(&fw_device_idr, minor);
-	up_write(&fw_device_rwsem);
- error:
-	fw_device_put(device);		/* fw_device_idr's reference */
-
-	put_device(&device->device);	/* our reference */
-}
-
-enum {
-	REREAD_BIB_ERROR,
-	REREAD_BIB_GONE,
-	REREAD_BIB_UNCHANGED,
-	REREAD_BIB_CHANGED,
-};
-
-/* Reread and compare bus info block and header of root directory */
-static int reread_bus_info_block(struct fw_device *device, int generation)
-{
-	u32 q;
-	int i;
-
-	for (i = 0; i < 6; i++) {
-		if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
-			return REREAD_BIB_ERROR;
-
-		if (i == 0 && q == 0)
-			return REREAD_BIB_GONE;
-
-		if (q != device->config_rom[i])
-			return REREAD_BIB_CHANGED;
-	}
-
-	return REREAD_BIB_UNCHANGED;
-}
-
-static void fw_device_refresh(struct work_struct *work)
-{
-	struct fw_device *device =
-		container_of(work, struct fw_device, work.work);
-	struct fw_card *card = device->card;
-	int node_id = device->node_id;
-
-	switch (reread_bus_info_block(device, device->generation)) {
-	case REREAD_BIB_ERROR:
-		if (device->config_rom_retries < MAX_RETRIES / 2 &&
-		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
-			device->config_rom_retries++;
-			schedule_delayed_work(&device->work, RETRY_DELAY / 2);
-
-			return;
-		}
-		goto give_up;
-
-	case REREAD_BIB_GONE:
-		goto gone;
-
-	case REREAD_BIB_UNCHANGED:
-		if (atomic_cmpxchg(&device->state,
-				   FW_DEVICE_INITIALIZING,
-				   FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
-			goto gone;
-
-		fw_device_update(work);
-		device->config_rom_retries = 0;
-		goto out;
-
-	case REREAD_BIB_CHANGED:
-		break;
-	}
-
-	/*
-	 * Something changed.  We keep things simple and don't investigate
-	 * further.  We just destroy all previous units and create new ones.
-	 */
-	device_for_each_child(&device->device, NULL, shutdown_unit);
-
-	if (read_bus_info_block(device, device->generation) < 0) {
-		if (device->config_rom_retries < MAX_RETRIES &&
-		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
-			device->config_rom_retries++;
-			schedule_delayed_work(&device->work, RETRY_DELAY);
-
-			return;
-		}
-		goto give_up;
-	}
-
-	create_units(device);
-
-	if (atomic_cmpxchg(&device->state,
-			   FW_DEVICE_INITIALIZING,
-			   FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
-		goto gone;
-
-	fw_notify("refreshed device %s\n", dev_name(&device->device));
-	device->config_rom_retries = 0;
-	goto out;
-
- give_up:
-	fw_notify("giving up on refresh of device %s\n", dev_name(&device->device));
- gone:
-	atomic_set(&device->state, FW_DEVICE_GONE);
-	PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
-	schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
- out:
-	if (node_id == card->root_node->node_id)
-		fw_schedule_bm_work(card, 0);
-}
-
-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;
- create:
-		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().
-		 *
-		 * Attention:  A lot of things, even fw_device_get(),
-		 * cannot be done before fw_device_init() finished!
-		 * You can basically just check device->state and
-		 * schedule work until then, but only while holding
-		 * card->lock.
-		 */
-		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;
-		mutex_init(&device->client_list_mutex);
-		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_INITIATED_RESET:
-		device = node->data;
-		if (device == NULL)
-			goto create;
-
-		device->node_id = node->node_id;
-		smp_wmb();  /* update node_id before generation */
-		device->generation = card->generation;
-		if (atomic_cmpxchg(&device->state,
-			    FW_DEVICE_RUNNING,
-			    FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
-			PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
-			schedule_delayed_work(&device->work,
-				node == card->local_node ? 0 : INITIAL_DELAY);
-		}
-		break;
-
-	case FW_NODE_UPDATED:
-		if (!node->link_on || node->data == NULL)
-			break;
-
-		device = node->data;
-		device->node_id = node->node_id;
-		smp_wmb();  /* update node_id before generation */
-		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_GONE) == FW_DEVICE_RUNNING) {
-			PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
-			schedule_delayed_work(&device->work,
-				list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
-		}
-		break;
-	}
-}
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-device.h linux-libre-2.6.31-gnu/drivers/firewire/fw-device.h
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-device.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-device.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,202 +0,0 @@
-/*
- * 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/device.h>
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/rwsem.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#include <asm/atomic.h>
-
-enum fw_device_state {
-	FW_DEVICE_INITIALIZING,
-	FW_DEVICE_RUNNING,
-	FW_DEVICE_GONE,
-	FW_DEVICE_SHUTDOWN,
-};
-
-struct fw_attribute_group {
-	struct attribute_group *groups[2];
-	struct attribute_group group;
-	struct attribute *attrs[11];
-};
-
-struct fw_node;
-struct fw_card;
-
-/*
- * Note, fw_device.generation always has to be read before fw_device.node_id.
- * Use SMP memory barriers to ensure this.  Otherwise requests will be sent
- * to an outdated node_id if the generation was updated in the meantime due
- * to a bus reset.
- *
- * Likewise, fw-core will take care to update .node_id before .generation so
- * that whenever fw_device.generation is current WRT the actual bus generation,
- * fw_device.node_id is guaranteed to be current too.
- *
- * The same applies to fw_device.card->node_id vs. fw_device.generation.
- *
- * fw_device.config_rom and fw_device.config_rom_length may be accessed during
- * the lifetime of any fw_unit belonging to the fw_device, before device_del()
- * was called on the last fw_unit.  Alternatively, they may be accessed while
- * holding fw_device_rwsem.
- */
-struct fw_device {
-	atomic_t state;
-	struct fw_node *node;
-	int node_id;
-	int generation;
-	unsigned max_speed;
-	struct fw_card *card;
-	struct device device;
-
-	struct mutex client_list_mutex;
-	struct list_head client_list;
-
-	u32 *config_rom;
-	size_t config_rom_length;
-	int config_rom_retries;
-	unsigned cmc:1;
-	unsigned bc_implemented:2;
-
-	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;
-}
-
-static inline struct fw_device *fw_device_get(struct fw_device *device)
-{
-	get_device(&device->device);
-
-	return device;
-}
-
-static inline void fw_device_put(struct fw_device *device)
-{
-	put_device(&device->device);
-}
-
-struct fw_device *fw_device_get_by_devt(dev_t devt);
-int fw_device_enable_phys_dma(struct fw_device *device);
-void fw_device_set_broadcast_channel(struct fw_device *device, int generation);
-
-void fw_device_cdev_update(struct fw_device *device);
-void fw_device_cdev_remove(struct fw_device *device);
-
-extern struct rw_semaphore fw_device_rwsem;
-extern struct idr fw_device_idr;
-extern int fw_cdev_major;
-
-/*
- * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
- */
-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);
-}
-
-static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
-{
-	get_device(&unit->device);
-
-	return unit;
-}
-
-static inline void fw_unit_put(struct fw_unit *unit)
-{
-	put_device(&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 CSR_DIRECTORY_ID	0x20
-
-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 -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-iso.c linux-libre-2.6.31-gnu/drivers/firewire/fw-iso.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-iso.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-iso.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,327 +0,0 @@
-/*
- * Isochronous I/O functionality:
- *   - Isochronous DMA context management
- *   - Isochronous bus resource management (channels, bandwidth), client side
- *
- * 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/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/firewire-constants.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
-
-#include "fw-topology.h"
-#include "fw-transaction.h"
-
-/*
- * Isochronous DMA context management
- */
-
-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;
-	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(card->device, 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 -ENOMEM;
-}
-
-int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma)
-{
-	unsigned long uaddr;
-	int i, err;
-
-	uaddr = vma->vm_start;
-	for (i = 0; i < buffer->page_count; i++) {
-		err = vm_insert_page(vma, uaddr, buffer->pages[i]);
-		if (err)
-			return err;
-
-		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, channel, 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;
-}
-
-void fw_iso_context_destroy(struct fw_iso_context *ctx)
-{
-	struct fw_card *card = ctx->card;
-
-	card->driver->free_iso_context(ctx);
-}
-
-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);
-}
-
-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);
-}
-
-int fw_iso_context_stop(struct fw_iso_context *ctx)
-{
-	return ctx->card->driver->stop_iso(ctx);
-}
-
-/*
- * Isochronous bus resource management (channels, bandwidth), client side
- */
-
-static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
-			    int bandwidth, bool allocate)
-{
-	__be32 data[2];
-	int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
-
-	/*
-	 * On a 1394a IRM with low contention, try < 1 is enough.
-	 * On a 1394-1995 IRM, we need at least try < 2.
-	 * Let's just do try < 5.
-	 */
-	for (try = 0; try < 5; try++) {
-		new = allocate ? old - bandwidth : old + bandwidth;
-		if (new < 0 || new > BANDWIDTH_AVAILABLE_INITIAL)
-			break;
-
-		data[0] = cpu_to_be32(old);
-		data[1] = cpu_to_be32(new);
-		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
-				irm_id, generation, SCODE_100,
-				CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
-				data, sizeof(data))) {
-		case RCODE_GENERATION:
-			/* A generation change frees all bandwidth. */
-			return allocate ? -EAGAIN : bandwidth;
-
-		case RCODE_COMPLETE:
-			if (be32_to_cpup(data) == old)
-				return bandwidth;
-
-			old = be32_to_cpup(data);
-			/* Fall through. */
-		}
-	}
-
-	return -EIO;
-}
-
-static int manage_channel(struct fw_card *card, int irm_id, int generation,
-			  u32 channels_mask, u64 offset, bool allocate)
-{
-	__be32 data[2], c, all, old;
-	int i, retry = 5;
-
-	old = all = allocate ? cpu_to_be32(~0) : 0;
-
-	for (i = 0; i < 32; i++) {
-		if (!(channels_mask & 1 << i))
-			continue;
-
-		c = cpu_to_be32(1 << (31 - i));
-		if ((old & c) != (all & c))
-			continue;
-
-		data[0] = old;
-		data[1] = old ^ c;
-		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
-					   irm_id, generation, SCODE_100,
-					   offset, data, sizeof(data))) {
-		case RCODE_GENERATION:
-			/* A generation change frees all channels. */
-			return allocate ? -EAGAIN : i;
-
-		case RCODE_COMPLETE:
-			if (data[0] == old)
-				return i;
-
-			old = data[0];
-
-			/* Is the IRM 1394a-2000 compliant? */
-			if ((data[0] & c) == (data[1] & c))
-				continue;
-
-			/* 1394-1995 IRM, fall through to retry. */
-		default:
-			if (retry--)
-				i--;
-		}
-	}
-
-	return -EIO;
-}
-
-static void deallocate_channel(struct fw_card *card, int irm_id,
-			       int generation, int channel)
-{
-	u32 mask;
-	u64 offset;
-
-	mask = channel < 32 ? 1 << channel : 1 << (channel - 32);
-	offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
-				CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO;
-
-	manage_channel(card, irm_id, generation, mask, offset, false);
-}
-
-/**
- * fw_iso_resource_manage - Allocate or deallocate a channel and/or bandwidth
- *
- * In parameters: card, generation, channels_mask, bandwidth, allocate
- * Out parameters: channel, bandwidth
- * This function blocks (sleeps) during communication with the IRM.
- *
- * Allocates or deallocates at most one channel out of channels_mask.
- * channels_mask is a bitfield with MSB for channel 63 and LSB for channel 0.
- * (Note, the IRM's CHANNELS_AVAILABLE is a big-endian bitfield with MSB for
- * channel 0 and LSB for channel 63.)
- * Allocates or deallocates as many bandwidth allocation units as specified.
- *
- * Returns channel < 0 if no channel was allocated or deallocated.
- * Returns bandwidth = 0 if no bandwidth was allocated or deallocated.
- *
- * If generation is stale, deallocations succeed but allocations fail with
- * channel = -EAGAIN.
- *
- * If channel allocation fails, no bandwidth will be allocated either.
- * If bandwidth allocation fails, no channel will be allocated either.
- * But deallocations of channel and bandwidth are tried independently
- * of each other's success.
- */
-void fw_iso_resource_manage(struct fw_card *card, int generation,
-			    u64 channels_mask, int *channel, int *bandwidth,
-			    bool allocate)
-{
-	u32 channels_hi = channels_mask;	/* channels 31...0 */
-	u32 channels_lo = channels_mask >> 32;	/* channels 63...32 */
-	int irm_id, ret, c = -EINVAL;
-
-	spin_lock_irq(&card->lock);
-	irm_id = card->irm_node->node_id;
-	spin_unlock_irq(&card->lock);
-
-	if (channels_hi)
-		c = manage_channel(card, irm_id, generation, channels_hi,
-		    CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate);
-	if (channels_lo && c < 0) {
-		c = manage_channel(card, irm_id, generation, channels_lo,
-		    CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate);
-		if (c >= 0)
-			c += 32;
-	}
-	*channel = c;
-
-	if (allocate && channels_mask != 0 && c < 0)
-		*bandwidth = 0;
-
-	if (*bandwidth == 0)
-		return;
-
-	ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate);
-	if (ret < 0)
-		*bandwidth = 0;
-
-	if (allocate && ret < 0 && c >= 0) {
-		deallocate_channel(card, irm_id, generation, c);
-		*channel = ret;
-	}
-}
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-ohci.c linux-libre-2.6.31-gnu/drivers/firewire/fw-ohci.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-ohci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-ohci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2629 +0,0 @@
-/*
- * 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/compiler.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-
-#include <asm/page.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/pmac_feature.h>
-#endif
-
-#include "fw-ohci.h"
-#include "fw-transaction.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);
-
-/*
- * A buffer that contains a block of DMA-able coherent memory used for
- * storing a portion of a DMA descriptor program.
- */
-struct descriptor_buffer {
-	struct list_head list;
-	dma_addr_t buffer_bus;
-	size_t buffer_size;
-	size_t used;
-	struct descriptor buffer[0];
-};
-
-struct context {
-	struct fw_ohci *ohci;
-	u32 regs;
-	int total_allocation;
-
-	/*
-	 * List of page-sized buffers for storing DMA descriptors.
-	 * Head of list contains buffers in use and tail of list contains
-	 * free buffers.
-	 */
-	struct list_head buffer_list;
-
-	/*
-	 * Pointer to a buffer inside buffer_list that contains the tail
-	 * end of the current DMA program.
-	 */
-	struct descriptor_buffer *buffer_tail;
-
-	/*
-	 * The descriptor containing the branch address of the first
-	 * descriptor that has not yet been filled by the device.
-	 */
-	struct descriptor *last;
-
-	/*
-	 * The last descriptor in the DMA program.  It contains the branch
-	 * address that must be updated upon appending a new descriptor.
-	 */
-	struct descriptor *prev;
-
-	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;
-	int excess_bytes;
-	void *header;
-	size_t header_length;
-};
-
-#define CONFIG_ROM_SIZE 1024
-
-struct fw_ohci {
-	struct fw_card card;
-
-	__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;	/* for timestamping incoming requests */
-	u32 bus_seconds;
-
-	bool use_dualbuffer;
-	bool old_uninorth;
-	bool bus_reset_packet_quirk;
-
-	/*
-	 * 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;
-	u64 ir_context_channels;
-	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	0xf
-#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
-
-static char ohci_driver_name[] = KBUILD_MODNAME;
-
-#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
-
-#define OHCI_PARAM_DEBUG_AT_AR		1
-#define OHCI_PARAM_DEBUG_SELFIDS	2
-#define OHCI_PARAM_DEBUG_IRQS		4
-#define OHCI_PARAM_DEBUG_BUSRESETS	8 /* only effective before chip init */
-
-static int param_debug;
-module_param_named(debug, param_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
-	", AT/AR events = "	__stringify(OHCI_PARAM_DEBUG_AT_AR)
-	", self-IDs = "		__stringify(OHCI_PARAM_DEBUG_SELFIDS)
-	", IRQs = "		__stringify(OHCI_PARAM_DEBUG_IRQS)
-	", busReset events = "	__stringify(OHCI_PARAM_DEBUG_BUSRESETS)
-	", or a combination, or all = -1)");
-
-static void log_irqs(u32 evt)
-{
-	if (likely(!(param_debug &
-			(OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
-		return;
-
-	if (!(param_debug & OHCI_PARAM_DEBUG_IRQS) &&
-	    !(evt & OHCI1394_busReset))
-		return;
-
-	fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
-	    evt & OHCI1394_selfIDComplete	? " selfID"		: "",
-	    evt & OHCI1394_RQPkt		? " AR_req"		: "",
-	    evt & OHCI1394_RSPkt		? " AR_resp"		: "",
-	    evt & OHCI1394_reqTxComplete	? " AT_req"		: "",
-	    evt & OHCI1394_respTxComplete	? " AT_resp"		: "",
-	    evt & OHCI1394_isochRx		? " IR"			: "",
-	    evt & OHCI1394_isochTx		? " IT"			: "",
-	    evt & OHCI1394_postedWriteErr	? " postedWriteErr"	: "",
-	    evt & OHCI1394_cycleTooLong		? " cycleTooLong"	: "",
-	    evt & OHCI1394_cycle64Seconds	? " cycle64Seconds"	: "",
-	    evt & OHCI1394_regAccessFail	? " regAccessFail"	: "",
-	    evt & OHCI1394_busReset		? " busReset"		: "",
-	    evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
-		    OHCI1394_RSPkt | OHCI1394_reqTxComplete |
-		    OHCI1394_respTxComplete | OHCI1394_isochRx |
-		    OHCI1394_isochTx | OHCI1394_postedWriteErr |
-		    OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds |
-		    OHCI1394_regAccessFail | OHCI1394_busReset)
-						? " ?"			: "");
-}
-
-static const char *speed[] = {
-	[0] = "S100", [1] = "S200", [2] = "S400",    [3] = "beta",
-};
-static const char *power[] = {
-	[0] = "+0W",  [1] = "+15W", [2] = "+30W",    [3] = "+45W",
-	[4] = "-3W",  [5] = " ?W",  [6] = "-3..-6W", [7] = "-3..-10W",
-};
-static const char port[] = { '.', '-', 'p', 'c', };
-
-static char _p(u32 *s, int shift)
-{
-	return port[*s >> shift & 3];
-}
-
-static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
-{
-	if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
-		return;
-
-	fw_notify("%d selfIDs, generation %d, local node ID %04x\n",
-		  self_id_count, generation, node_id);
-
-	for (; self_id_count--; ++s)
-		if ((*s & 1 << 23) == 0)
-			fw_notify("selfID 0: %08x, phy %d [%c%c%c] "
-			    "%s gc=%d %s %s%s%s\n",
-			    *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2),
-			    speed[*s >> 14 & 3], *s >> 16 & 63,
-			    power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "",
-			    *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : "");
-		else
-			fw_notify("selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n",
-			    *s, *s >> 24 & 63,
-			    _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10),
-			    _p(s,  8), _p(s,  6), _p(s,  4), _p(s,  2));
-}
-
-static const char *evts[] = {
-	[0x00] = "evt_no_status",	[0x01] = "-reserved-",
-	[0x02] = "evt_long_packet",	[0x03] = "evt_missing_ack",
-	[0x04] = "evt_underrun",	[0x05] = "evt_overrun",
-	[0x06] = "evt_descriptor_read",	[0x07] = "evt_data_read",
-	[0x08] = "evt_data_write",	[0x09] = "evt_bus_reset",
-	[0x0a] = "evt_timeout",		[0x0b] = "evt_tcode_err",
-	[0x0c] = "-reserved-",		[0x0d] = "-reserved-",
-	[0x0e] = "evt_unknown",		[0x0f] = "evt_flushed",
-	[0x10] = "-reserved-",		[0x11] = "ack_complete",
-	[0x12] = "ack_pending ",	[0x13] = "-reserved-",
-	[0x14] = "ack_busy_X",		[0x15] = "ack_busy_A",
-	[0x16] = "ack_busy_B",		[0x17] = "-reserved-",
-	[0x18] = "-reserved-",		[0x19] = "-reserved-",
-	[0x1a] = "-reserved-",		[0x1b] = "ack_tardy",
-	[0x1c] = "-reserved-",		[0x1d] = "ack_data_error",
-	[0x1e] = "ack_type_error",	[0x1f] = "-reserved-",
-	[0x20] = "pending/cancelled",
-};
-static const char *tcodes[] = {
-	[0x0] = "QW req",		[0x1] = "BW req",
-	[0x2] = "W resp",		[0x3] = "-reserved-",
-	[0x4] = "QR req",		[0x5] = "BR req",
-	[0x6] = "QR resp",		[0x7] = "BR resp",
-	[0x8] = "cycle start",		[0x9] = "Lk req",
-	[0xa] = "async stream packet",	[0xb] = "Lk resp",
-	[0xc] = "-reserved-",		[0xd] = "-reserved-",
-	[0xe] = "link internal",	[0xf] = "-reserved-",
-};
-static const char *phys[] = {
-	[0x0] = "phy config packet",	[0x1] = "link-on packet",
-	[0x2] = "self-id packet",	[0x3] = "-reserved-",
-};
-
-static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
-{
-	int tcode = header[0] >> 4 & 0xf;
-	char specific[12];
-
-	if (likely(!(param_debug & OHCI_PARAM_DEBUG_AT_AR)))
-		return;
-
-	if (unlikely(evt >= ARRAY_SIZE(evts)))
-			evt = 0x1f;
-
-	if (evt == OHCI1394_evt_bus_reset) {
-		fw_notify("A%c evt_bus_reset, generation %d\n",
-		    dir, (header[2] >> 16) & 0xff);
-		return;
-	}
-
-	if (header[0] == ~header[1]) {
-		fw_notify("A%c %s, %s, %08x\n",
-		    dir, evts[evt], phys[header[0] >> 30 & 0x3], header[0]);
-		return;
-	}
-
-	switch (tcode) {
-	case 0x0: case 0x6: case 0x8:
-		snprintf(specific, sizeof(specific), " = %08x",
-			 be32_to_cpu((__force __be32)header[3]));
-		break;
-	case 0x1: case 0x5: case 0x7: case 0x9: case 0xb:
-		snprintf(specific, sizeof(specific), " %x,%x",
-			 header[3] >> 16, header[3] & 0xffff);
-		break;
-	default:
-		specific[0] = '\0';
-	}
-
-	switch (tcode) {
-	case 0xe: case 0xa:
-		fw_notify("A%c %s, %s\n", dir, evts[evt], tcodes[tcode]);
-		break;
-	case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
-		fw_notify("A%c spd %x tl %02x, "
-		    "%04x -> %04x, %s, "
-		    "%s, %04x%08x%s\n",
-		    dir, speed, header[0] >> 10 & 0x3f,
-		    header[1] >> 16, header[0] >> 16, evts[evt],
-		    tcodes[tcode], header[1] & 0xffff, header[2], specific);
-		break;
-	default:
-		fw_notify("A%c spd %x tl %02x, "
-		    "%04x -> %04x, %s, "
-		    "%s%s\n",
-		    dir, speed, header[0] >> 10 & 0x3f,
-		    header[1] >> 16, header[0] >> 16, evts[evt],
-		    tcodes[tcode], specific);
-	}
-}
-
-#else
-
-#define log_irqs(evt)
-#define log_selfids(node_id, generation, self_id_count, sid)
-#define log_ar_at_event(dir, speed, header, evt)
-
-#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
-
-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));
-	flush_writes(ohci);
-	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 uninitialized_var(ab_bus);
-	size_t offset;
-
-	ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC);
-	if (ab == NULL)
-		return -ENOMEM;
-
-	ab->next = NULL;
-	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;
-
-	ctx->last_buffer->descriptor.branch_address = cpu_to_le32(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 void ar_context_release(struct ar_context *ctx)
-{
-	struct ar_buffer *ab, *ab_next;
-	size_t offset;
-	dma_addr_t ab_bus;
-
-	for (ab = ctx->current_buffer; ab; ab = ab_next) {
-		ab_next = ab->next;
-		offset = offsetof(struct ar_buffer, data);
-		ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
-		dma_free_coherent(ctx->ohci->card.device, PAGE_SIZE,
-				  ab, ab_bus);
-	}
-}
-
-#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
-#define cond_le32_to_cpu(v) \
-	(ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v))
-#else
-#define cond_le32_to_cpu(v) le32_to_cpu(v)
-#endif
-
-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;
-	int evt;
-
-	p.header[0] = cond_le32_to_cpu(buffer[0]);
-	p.header[1] = cond_le32_to_cpu(buffer[1]);
-	p.header[2] = cond_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] = cond_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] = cond_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;
-
-	default:
-		/* FIXME: Stop context, discard everything, and restart? */
-		p.header_length = 0;
-		p.payload_length = 0;
-	}
-
-	p.payload = (void *) buffer + p.header_length;
-
-	/* FIXME: What to do about evt_* errors? */
-	length = (p.header_length + p.payload_length + 3) / 4;
-	status = cond_le32_to_cpu(buffer[length]);
-	evt    = (status >> 16) & 0x1f;
-
-	p.ack        = evt - 16;
-	p.speed      = (status >> 21) & 0x7;
-	p.timestamp  = status & 0xffff;
-	p.generation = ohci->request_generation;
-
-	log_ar_at_event('R', p.speed, p.header, evt);
-
-	/*
-	 * 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.
-	 *
-	 * Alas some chips sometimes emit bus reset packets with a
-	 * wrong generation.  We set the correct generation for these
-	 * at a slightly incorrect time (in bus_reset_tasklet).
-	 */
-	if (evt == OHCI1394_evt_bus_reset) {
-		if (!ohci->bus_reset_packet_quirk)
-			ohci->request_generation = (p.header[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;
-		dma_addr_t start_bus;
-		void *start;
-
-		/*
-		 * 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);
-		start = buffer = ab;
-		start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
-
-		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);
-
-		dma_free_coherent(ohci->card.device, PAGE_SIZE,
-				  start, start_bus);
-		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;
-
-	return 0;
-}
-
-static void ar_context_run(struct ar_context *ctx)
-{
-	struct ar_buffer *ab = ctx->current_buffer;
-	dma_addr_t ab_bus;
-	size_t offset;
-
-	offset = offsetof(struct ar_buffer, data);
-	ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
-
-	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab_bus | 1);
-	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
-	flush_writes(ctx->ohci);
-}
-
-static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
-{
-	int b, key;
-
-	b   = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2;
-	key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8;
-
-	/* figure out which descriptor the branch address goes in */
-	if (z == 2 && (b == 3 || key == 2))
-		return d;
-	else
-		return d + z - 1;
-}
-
-static void context_tasklet(unsigned long data)
-{
-	struct context *ctx = (struct context *) data;
-	struct descriptor *d, *last;
-	u32 address;
-	int z;
-	struct descriptor_buffer *desc;
-
-	desc = list_entry(ctx->buffer_list.next,
-			struct descriptor_buffer, list);
-	last = ctx->last;
-	while (last->branch_address != 0) {
-		struct descriptor_buffer *old_desc = desc;
-		address = le32_to_cpu(last->branch_address);
-		z = address & 0xf;
-		address &= ~0xf;
-
-		/* If the branch address points to a buffer outside of the
-		 * current buffer, advance to the next buffer. */
-		if (address < desc->buffer_bus ||
-				address >= desc->buffer_bus + desc->used)
-			desc = list_entry(desc->list.next,
-					struct descriptor_buffer, list);
-		d = desc->buffer + (address - desc->buffer_bus) / sizeof(*d);
-		last = find_branch_descriptor(d, z);
-
-		if (!ctx->callback(ctx, d, last))
-			break;
-
-		if (old_desc != desc) {
-			/* If we've advanced to the next buffer, move the
-			 * previous buffer to the free list. */
-			unsigned long flags;
-			old_desc->used = 0;
-			spin_lock_irqsave(&ctx->ohci->lock, flags);
-			list_move_tail(&old_desc->list, &ctx->buffer_list);
-			spin_unlock_irqrestore(&ctx->ohci->lock, flags);
-		}
-		ctx->last = last;
-	}
-}
-
-/*
- * Allocate a new buffer and add it to the list of free buffers for this
- * context.  Must be called with ohci->lock held.
- */
-static int context_add_buffer(struct context *ctx)
-{
-	struct descriptor_buffer *desc;
-	dma_addr_t uninitialized_var(bus_addr);
-	int offset;
-
-	/*
-	 * 16MB of descriptors should be far more than enough for any DMA
-	 * program.  This will catch run-away userspace or DoS attacks.
-	 */
-	if (ctx->total_allocation >= 16*1024*1024)
-		return -ENOMEM;
-
-	desc = dma_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE,
-			&bus_addr, GFP_ATOMIC);
-	if (!desc)
-		return -ENOMEM;
-
-	offset = (void *)&desc->buffer - (void *)desc;
-	desc->buffer_size = PAGE_SIZE - offset;
-	desc->buffer_bus = bus_addr + offset;
-	desc->used = 0;
-
-	list_add_tail(&desc->list, &ctx->buffer_list);
-	ctx->total_allocation += PAGE_SIZE;
-
-	return 0;
-}
-
-static int context_init(struct context *ctx, struct fw_ohci *ohci,
-			u32 regs, descriptor_callback_t callback)
-{
-	ctx->ohci = ohci;
-	ctx->regs = regs;
-	ctx->total_allocation = 0;
-
-	INIT_LIST_HEAD(&ctx->buffer_list);
-	if (context_add_buffer(ctx) < 0)
-		return -ENOMEM;
-
-	ctx->buffer_tail = list_entry(ctx->buffer_list.next,
-			struct descriptor_buffer, list);
-
-	tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx);
-	ctx->callback = callback;
-
-	/*
-	 * 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.
-	 */
-	memset(ctx->buffer_tail->buffer, 0, sizeof(*ctx->buffer_tail->buffer));
-	ctx->buffer_tail->buffer->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST);
-	ctx->buffer_tail->buffer->transfer_status = cpu_to_le16(0x8011);
-	ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer);
-	ctx->last = ctx->buffer_tail->buffer;
-	ctx->prev = ctx->buffer_tail->buffer;
-
-	return 0;
-}
-
-static void context_release(struct context *ctx)
-{
-	struct fw_card *card = &ctx->ohci->card;
-	struct descriptor_buffer *desc, *tmp;
-
-	list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list)
-		dma_free_coherent(card->device, PAGE_SIZE, desc,
-			desc->buffer_bus -
-			((void *)&desc->buffer - (void *)desc));
-}
-
-/* Must be called with ohci->lock held */
-static struct descriptor *context_get_descriptors(struct context *ctx,
-						  int z, dma_addr_t *d_bus)
-{
-	struct descriptor *d = NULL;
-	struct descriptor_buffer *desc = ctx->buffer_tail;
-
-	if (z * sizeof(*d) > desc->buffer_size)
-		return NULL;
-
-	if (z * sizeof(*d) > desc->buffer_size - desc->used) {
-		/* No room for the descriptor in this buffer, so advance to the
-		 * next one. */
-
-		if (desc->list.next == &ctx->buffer_list) {
-			/* If there is no free buffer next in the list,
-			 * allocate one. */
-			if (context_add_buffer(ctx) < 0)
-				return NULL;
-		}
-		desc = list_entry(desc->list.next,
-				struct descriptor_buffer, list);
-		ctx->buffer_tail = desc;
-	}
-
-	d = desc->buffer + desc->used / sizeof(*d);
-	memset(d, 0, z * sizeof(*d));
-	*d_bus = desc->buffer_bus + desc->used;
-
-	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->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;
-	struct descriptor_buffer *desc = ctx->buffer_tail;
-
-	d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d);
-
-	desc->used += (z + extra) * sizeof(*d);
-	ctx->prev->branch_address = cpu_to_le32(d_bus | z);
-	ctx->prev = find_branch_descriptor(d, z);
-
-	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)
-			return;
-
-		mdelay(1);
-	}
-	fw_error("Error: DMA context still active (0x%08x)\n", reg);
-}
-
-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, uninitialized_var(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];
-	switch (packet->header_length) {
-	case 16:
-	case 12:
-		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);
-		break;
-
-	case 8:
-		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);
-		break;
-
-	case 4:
-		header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
-					(packet->speed << 16));
-		header[1] = cpu_to_le32(packet->header[0] & 0xffff0000);
-		d[0].req_count = cpu_to_le16(8);
-		break;
-
-	default:
-		/* BUG(); */
-		packet->ack = RCODE_SEND_ERROR;
-		return -1;
-	}
-
-	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(ohci->card.device, payload_bus)) {
-			packet->ack = RCODE_SEND_ERROR;
-			return -1;
-		}
-		packet->payload_bus = payload_bus;
-
-		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);
-
-	/*
-	 * If the controller and packet generations don't match, we need to
-	 * bail out and try again.  If IntEvent.busReset is set, the AT context
-	 * is halted, so appending to the context and trying to run it is
-	 * futile.  Most controllers do the right thing and just flush the AT
-	 * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
-	 * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
-	 * up stalling out.  So we just bail out in software and try again
-	 * later, and everyone is happy.
-	 * FIXME: Document how the locking works.
-	 */
-	if (ohci->generation != packet->generation ||
-	    reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
-		if (packet->payload_length > 0)
-			dma_unmap_single(ohci->card.device, payload_bus,
-					 packet->payload_length, DMA_TO_DEVICE);
-		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;
-	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;
-
-	if (packet->payload_bus)
-		dma_unmap_single(ohci->card.device, packet->payload_bus,
-				 packet->payload_length, DMA_TO_DEVICE);
-
-	evt = le16_to_cpu(last->transfer_status) & 0x1f;
-	packet->timestamp = le16_to_cpu(last->res_count);
-
-	log_ar_at_event('T', packet->speed, packet->header, evt);
-
-	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 ret;
-
-	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;
-	}
-
-	ret = at_context_queue_packet(ctx, packet);
-	spin_unlock_irqrestore(&ctx->ohci->lock, flags);
-
-	if (ret < 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;
-	void *free_rom = NULL;
-	dma_addr_t free_rom_bus = 0;
-
-	reg = reg_read(ohci, OHCI1394_NodeID);
-	if (!(reg & OHCI1394_NodeID_idValid)) {
-		fw_notify("node ID not valid, new bus reset in progress\n");
-		return;
-	}
-	if ((reg & OHCI1394_NodeID_nodeNumber) == 63) {
-		fw_notify("malconfigured bus\n");
-		return;
-	}
-	ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
-			       OHCI1394_NodeID_nodeNumber);
-
-	reg = reg_read(ohci, OHCI1394_SelfIDCount);
-	if (reg & OHCI1394_SelfIDCount_selfIDError) {
-		fw_notify("inconsistent self IDs\n");
-		return;
-	}
-	/*
-	 * 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 >> 3) & 0x3ff;
-	if (self_id_count == 0) {
-		fw_notify("inconsistent self IDs\n");
-		return;
-	}
-	generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
-	rmb();
-
-	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_notify("inconsistent self IDs\n");
-			return;
-		}
-		ohci->self_id_buffer[j] =
-				cond_le32_to_cpu(ohci->self_id_cpu[i]);
-	}
-	rmb();
-
-	/*
-	 * 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);
-
-	if (ohci->bus_reset_packet_quirk)
-		ohci->request_generation = generation;
-
-	/*
-	 * 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) {
-		if (ohci->next_config_rom != ohci->config_rom) {
-			free_rom      = ohci->config_rom;
-			free_rom_bus  = 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);
-	}
-
-#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
-	reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
-	reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
-#endif
-
-	spin_unlock_irqrestore(&ohci->lock, flags);
-
-	if (free_rom)
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  free_rom, free_rom_bus);
-
-	log_selfids(ohci->node_id, generation,
-		    self_id_count, ohci->self_id_buffer);
-
-	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 || !~event)
-		return IRQ_NONE;
-
-	/* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
-	reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
-	log_irqs(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 (unlikely(event & OHCI1394_regAccessFail))
-		fw_error("Register access failure - "
-			 "please notify linux1394-devel@lists.sf.net\n");
-
-	if (unlikely(event & OHCI1394_postedWriteErr))
-		fw_error("PCI posted write error\n");
-
-	if (unlikely(event & OHCI1394_cycleTooLong)) {
-		if (printk_ratelimit())
-			fw_notify("isochronous cycle too long\n");
-		reg_write(ohci, OHCI1394_LinkControlSet,
-			  OHCI1394_LinkControl_cycleMaster);
-	}
-
-	if (event & OHCI1394_cycle64Seconds) {
-		cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-		if ((cycle_time & 0x80000000) == 0)
-			ohci->bus_seconds++;
-	}
-
-	return IRQ_HANDLED;
-}
-
-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 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);
-	u32 lps;
-	int i;
-
-	if (software_reset(ohci)) {
-		fw_error("Failed to reset ohci card.\n");
-		return -EBUSY;
-	}
-
-	/*
-	 * 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.  However, with some cards (well, at least
-	 * a JMicron PCIe card), we have to try again sometimes.
-	 */
-	reg_write(ohci, OHCI1394_HCControlSet,
-		  OHCI1394_HCControl_LPS |
-		  OHCI1394_HCControl_postedWriteEnable);
-	flush_writes(ohci);
-
-	for (lps = 0, i = 0; !lps && i < 3; i++) {
-		msleep(50);
-		lps = reg_read(ohci, OHCI1394_HCControlSet) &
-		      OHCI1394_HCControl_LPS;
-	}
-
-	if (!lps) {
-		fw_error("Failed to set Link Power Status\n");
-		return -EIO;
-	}
-
-	reg_write(ohci, OHCI1394_HCControlClear,
-		  OHCI1394_HCControl_noByteSwapData);
-
-	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
-	reg_write(ohci, OHCI1394_LinkControlClear,
-		  OHCI1394_LinkControl_rcvPhyPkt);
-	reg_write(ohci, OHCI1394_LinkControlSet,
-		  OHCI1394_LinkControl_rcvSelfID |
-		  OHCI1394_LinkControl_cycleTimerEnable |
-		  OHCI1394_LinkControl_cycleMaster);
-
-	reg_write(ohci, OHCI1394_ATRetries,
-		  OHCI1394_MAX_AT_REQ_RETRIES |
-		  (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
-		  (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
-
-	ar_context_run(&ohci->ar_request_ctx);
-	ar_context_run(&ohci->ar_response_ctx);
-
-	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_postedWriteErr | OHCI1394_cycleTooLong |
-		  OHCI1394_cycle64Seconds | OHCI1394_regAccessFail |
-		  OHCI1394_masterIntEnable);
-	if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
-		reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
-
-	/* Activate link_on bit and contender bit in our self ID packets.*/
-	if (ohci_update_phy_reg(card, 4, 0,
-				PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
-		return -EIO;
-
-	/*
-	 * 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.
-	 */
-
-	if (config_rom) {
-		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);
-	} else {
-		/*
-		 * In the suspend case, config_rom is NULL, which
-		 * means that we just reuse the old config rom.
-		 */
-		ohci->next_config_rom = ohci->config_rom;
-		ohci->next_config_rom_bus = ohci->config_rom_bus;
-	}
-
-	ohci->next_header = be32_to_cpu(ohci->next_config_rom[0]);
-	ohci->next_config_rom[0] = 0;
-	reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
-	reg_write(ohci, OHCI1394_BusOptions,
-		  be32_to_cpu(ohci->next_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 ret = -EBUSY;
-	__be32 *next_config_rom;
-	dma_addr_t uninitialized_var(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);
-		ret = 0;
-	}
-
-	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 (ret == 0)
-		fw_core_initiate_bus_reset(&ohci->card, 1);
-	else
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  next_config_rom, next_config_rom_bus);
-
-	return ret;
-}
-
-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 ret = -ENOENT;
-
-	tasklet_disable(&ctx->tasklet);
-
-	if (packet->ack != 0)
-		goto out;
-
-	if (packet->payload_bus)
-		dma_unmap_single(ohci->card.device, packet->payload_bus,
-				 packet->payload_length, DMA_TO_DEVICE);
-
-	log_ar_at_event('T', packet->speed, packet->header, 0x20);
-	driver_data->packet = NULL;
-	packet->ack = RCODE_CANCELLED;
-	packet->callback(packet, &ohci->card, packet->ack);
-	ret = 0;
- out:
-	tasklet_enable(&ctx->tasklet);
-
-	return ret;
-}
-
-static int ohci_enable_phys_dma(struct fw_card *card,
-				int node_id, int generation)
-{
-#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
-	return 0;
-#else
-	struct fw_ohci *ohci = fw_ohci(card);
-	unsigned long flags;
-	int n, ret = 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) {
-		ret = -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 ret;
-#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
-}
-
-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 void copy_iso_headers(struct iso_context *ctx, void *p)
-{
-	int i = ctx->header_length;
-
-	if (i + ctx->base.header_size > PAGE_SIZE)
-		return;
-
-	/*
-	 * 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.
-	 */
-	if (ctx->base.header_size > 0)
-		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
-	if (ctx->base.header_size > 4)
-		*(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p);
-	if (ctx->base.header_size > 8)
-		memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8);
-	ctx->header_length += ctx->base.header_size;
-}
-
-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;
-
-	if (db->first_res_count != 0 && db->second_res_count != 0) {
-		if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
-			/* This descriptor isn't done yet, stop iteration. */
-			return 0;
-		}
-		ctx->excess_bytes -= le16_to_cpu(db->second_req_count);
-	}
-
-	header_length = le16_to_cpu(db->first_req_count) -
-		le16_to_cpu(db->first_res_count);
-
-	p = db + 1;
-	end = p + header_length;
-	while (p < end) {
-		copy_iso_headers(ctx, p);
-		ctx->excess_bytes +=
-			(le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff;
-		p += max(ctx->base.header_size, (size_t)8);
-	}
-
-	ctx->excess_bytes -= le16_to_cpu(db->second_req_count) -
-		le16_to_cpu(db->second_res_count);
-
-	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_ir_packet_per_buffer(struct context *context,
-				       struct descriptor *d,
-				       struct descriptor *last)
-{
-	struct iso_context *ctx =
-		container_of(context, struct iso_context, context);
-	struct descriptor *pd;
-	__le32 *ir_header;
-	void *p;
-
-	for (pd = d; pd <= last; pd++) {
-		if (pd->transfer_status)
-			break;
-	}
-	if (pd > last)
-		/* Descriptor(s) not done yet, stop iteration */
-		return 0;
-
-	p = last + 1;
-	copy_iso_headers(ctx, p);
-
-	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
-		ir_header = (__le32 *) p;
-		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, int channel, size_t header_size)
-{
-	struct fw_ohci *ohci = fw_ohci(card);
-	struct iso_context *ctx, *list;
-	descriptor_callback_t callback;
-	u64 *channels, dont_care = ~0ULL;
-	u32 *mask, regs;
-	unsigned long flags;
-	int index, ret = -ENOMEM;
-
-	if (type == FW_ISO_CONTEXT_TRANSMIT) {
-		channels = &dont_care;
-		mask = &ohci->it_context_mask;
-		list = ohci->it_context_list;
-		callback = handle_it_packet;
-	} else {
-		channels = &ohci->ir_context_channels;
-		mask = &ohci->ir_context_mask;
-		list = ohci->ir_context_list;
-		if (ohci->use_dualbuffer)
-			callback = handle_ir_dualbuffer_packet;
-		else
-			callback = handle_ir_packet_per_buffer;
-	}
-
-	spin_lock_irqsave(&ohci->lock, flags);
-	index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
-	if (index >= 0) {
-		*channels &= ~(1ULL << channel);
-		*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;
-
-	ret = context_init(&ctx->context, ohci, regs, callback);
-	if (ret < 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(ret);
-}
-
-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_ISOCH_HEADER;
-		if (ohci->use_dualbuffer)
-			control |= IR_CONTEXT_DUAL_BUFFER_MODE;
-		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;
-		ohci->ir_context_channels |= 1ULL << base->channel;
-	}
-
-	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..
-	 */
-
-	p = packet;
-	z = 2;
-
-	/*
-	 * The OHCI controller puts the isochronous header and trailer in the
-	 * buffer, so we need at least 8 bytes.
-	 */
-	packet_count = p->header_length / ctx->base.header_size;
-	header_size = packet_count * max(ctx->base.header_size, (size_t)8);
-
-	/* 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: 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(max(ctx->base.header_size, (size_t)8));
-		if (p->skip && rest == p->payload_length) {
-			db->control |= cpu_to_le16(DESCRIPTOR_WAIT);
-			db->first_req_count = db->first_size;
-		} else {
-			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 (p->skip && rest == p->payload_length)
-			length = 4;
-		else 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;
-		if (offset == 0)
-			page++;
-	}
-
-	return 0;
-}
-
-static int ohci_queue_iso_receive_packet_per_buffer(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 = NULL, *pd = NULL;
-	struct fw_iso_packet *p = packet;
-	dma_addr_t d_bus, page_bus;
-	u32 z, header_z, rest;
-	int i, j, length;
-	int page, offset, packet_count, header_size, payload_per_buffer;
-
-	/*
-	 * The OHCI controller puts the isochronous header and trailer in the
-	 * buffer, so we need at least 8 bytes.
-	 */
-	packet_count = p->header_length / ctx->base.header_size;
-	header_size  = max(ctx->base.header_size, (size_t)8);
-
-	/* Get header size in number of descriptors. */
-	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
-	page     = payload >> PAGE_SHIFT;
-	offset   = payload & ~PAGE_MASK;
-	payload_per_buffer = p->payload_length / packet_count;
-
-	for (i = 0; i < packet_count; i++) {
-		/* d points to the header descriptor */
-		z = DIV_ROUND_UP(payload_per_buffer + offset, PAGE_SIZE) + 1;
-		d = context_get_descriptors(&ctx->context,
-				z + header_z, &d_bus);
-		if (d == NULL)
-			return -ENOMEM;
-
-		d->control      = cpu_to_le16(DESCRIPTOR_STATUS |
-					      DESCRIPTOR_INPUT_MORE);
-		if (p->skip && i == 0)
-			d->control |= cpu_to_le16(DESCRIPTOR_WAIT);
-		d->req_count    = cpu_to_le16(header_size);
-		d->res_count    = d->req_count;
-		d->transfer_status = 0;
-		d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d)));
-
-		rest = payload_per_buffer;
-		for (j = 1; j < z; j++) {
-			pd = d + j;
-			pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
-						  DESCRIPTOR_INPUT_MORE);
-
-			if (offset + rest < PAGE_SIZE)
-				length = rest;
-			else
-				length = PAGE_SIZE - offset;
-			pd->req_count = cpu_to_le16(length);
-			pd->res_count = pd->req_count;
-			pd->transfer_status = 0;
-
-			page_bus = page_private(buffer->pages[page]);
-			pd->data_address = cpu_to_le32(page_bus + offset);
-
-			offset = (offset + length) & ~PAGE_MASK;
-			rest -= length;
-			if (offset == 0)
-				page++;
-		}
-		pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
-					  DESCRIPTOR_INPUT_LAST |
-					  DESCRIPTOR_BRANCH_ALWAYS);
-		if (p->interrupt && i == packet_count - 1)
-			pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
-
-		context_append(&ctx->context, d, z, header_z);
-	}
-
-	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);
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&ctx->context.ohci->lock, flags);
-	if (base->type == FW_ISO_CONTEXT_TRANSMIT)
-		ret = ohci_queue_iso_transmit(base, packet, buffer, payload);
-	else if (ctx->context.ohci->use_dualbuffer)
-		ret = ohci_queue_iso_receive_dualbuffer(base, packet,
-							buffer, payload);
-	else
-		ret = ohci_queue_iso_receive_packet_per_buffer(base, packet,
-							buffer, payload);
-	spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
-
-	return ret;
-}
-
-static const struct fw_card_driver ohci_driver = {
-	.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,
-};
-
-#ifdef CONFIG_PPC_PMAC
-static void ohci_pmac_on(struct pci_dev *dev)
-{
-	if (machine_is(powermac)) {
-		struct device_node *ofn = pci_device_to_OF_node(dev);
-
-		if (ofn) {
-			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
-		}
-	}
-}
-
-static void ohci_pmac_off(struct pci_dev *dev)
-{
-	if (machine_is(powermac)) {
-		struct device_node *ofn = pci_device_to_OF_node(dev);
-
-		if (ofn) {
-			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
-			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
-		}
-	}
-}
-#else
-#define ohci_pmac_on(dev)
-#define ohci_pmac_off(dev)
-#endif /* CONFIG_PPC_PMAC */
-
-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, version;
-	u64 guid;
-	int err;
-	size_t size;
-
-	ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
-	if (ohci == NULL) {
-		err = -ENOMEM;
-		goto fail;
-	}
-
-	fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
-
-	ohci_pmac_on(dev);
-
-	err = pci_enable_device(dev);
-	if (err) {
-		fw_error("Failed to enable OHCI hardware\n");
-		goto fail_free;
-	}
-
-	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;
-	}
-
-	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
-	ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
-
-/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
-#if !defined(CONFIG_X86_32)
-	/* dual-buffer mode is broken with descriptor addresses above 2G */
-	if (dev->vendor == PCI_VENDOR_ID_TI &&
-	    dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
-		ohci->use_dualbuffer = false;
-#endif
-
-#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
-	ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
-			     dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
-#endif
-	ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
-
-	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,
-		     OHCI1394_AsReqTrContextControlSet, handle_at_packet);
-
-	context_init(&ohci->at_response_ctx, ohci,
-		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
-
-	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_channels = ~0ULL;
-	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) {
-		err = -ENOMEM;
-		goto fail_contexts;
-	}
-
-	/* 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) {
-		err = -ENOMEM;
-		goto fail_contexts;
-	}
-
-	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)
-		goto fail_self_id;
-
-	fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
-		  dev_name(&dev->dev), version >> 16, 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_contexts:
-	kfree(ohci->ir_context_list);
-	kfree(ohci->it_context_list);
-	context_release(&ohci->at_response_ctx);
-	context_release(&ohci->at_request_ctx);
-	ar_context_release(&ohci->ar_response_ctx);
-	ar_context_release(&ohci->ar_request_ctx);
-	pci_iounmap(dev, ohci->registers);
- fail_iomem:
-	pci_release_region(dev, 0);
- fail_disable:
-	pci_disable_device(dev);
- fail_free:
-	kfree(&ohci->card);
-	ohci_pmac_off(dev);
- fail:
-	if (err == -ENOMEM)
-		fw_error("Out of memory\n");
-
-	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);
-
-	if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom)
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  ohci->next_config_rom, ohci->next_config_rom_bus);
-	if (ohci->config_rom)
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  ohci->config_rom, ohci->config_rom_bus);
-	dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
-			  ohci->self_id_cpu, ohci->self_id_bus);
-	ar_context_release(&ohci->ar_request_ctx);
-	ar_context_release(&ohci->ar_response_ctx);
-	context_release(&ohci->at_request_ctx);
-	context_release(&ohci->at_response_ctx);
-	kfree(ohci->it_context_list);
-	kfree(ohci->ir_context_list);
-	pci_iounmap(dev, ohci->registers);
-	pci_release_region(dev, 0);
-	pci_disable_device(dev);
-	kfree(&ohci->card);
-	ohci_pmac_off(dev);
-
-	fw_notify("Removed fw-ohci device.\n");
-}
-
-#ifdef CONFIG_PM
-static int pci_suspend(struct pci_dev *dev, pm_message_t state)
-{
-	struct fw_ohci *ohci = pci_get_drvdata(dev);
-	int err;
-
-	software_reset(ohci);
-	free_irq(dev->irq, ohci);
-	err = pci_save_state(dev);
-	if (err) {
-		fw_error("pci_save_state failed\n");
-		return err;
-	}
-	err = pci_set_power_state(dev, pci_choose_state(dev, state));
-	if (err)
-		fw_error("pci_set_power_state failed with %d\n", err);
-	ohci_pmac_off(dev);
-
-	return 0;
-}
-
-static int pci_resume(struct pci_dev *dev)
-{
-	struct fw_ohci *ohci = pci_get_drvdata(dev);
-	int err;
-
-	ohci_pmac_on(dev);
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
-	err = pci_enable_device(dev);
-	if (err) {
-		fw_error("pci_enable_device failed\n");
-		return err;
-	}
-
-	return ohci_enable(&ohci->card, NULL, 0);
-}
-#endif
-
-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,
-#ifdef CONFIG_PM
-	.resume		= pci_resume,
-	.suspend	= pci_suspend,
-#endif
-};
-
-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 -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-ohci.h linux-libre-2.6.31-gnu/drivers/firewire/fw-ohci.h
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-ohci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-ohci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,157 +0,0 @@
-#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_SelfIDCount_selfIDError	0x80000000
-#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_NodeID_nodeNumber          0x0000003f
-#define   OHCI1394_NodeID_busNumber           0x0000ffc0
-#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_regAccessFail		0x00040000
-#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 -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-sbp2.c linux-libre-2.6.31-gnu/drivers/firewire/fw-sbp2.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-sbp2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-sbp2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1644 +0,0 @@
-/*
- * 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/blkdev.h>
-#include <linux/bug.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/scatterlist.h>
-#include <linux/string.h>
-#include <linux/stringify.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <asm/system.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-
-#include "fw-device.h"
-#include "fw-topology.h"
-#include "fw-transaction.h"
-
-/*
- * So far only bridges from Oxford Semiconductor are known to support
- * concurrent logins. Depending on firmware, four or two concurrent logins
- * are possible on OXFW911 and newer Oxsemi bridges.
- *
- * Concurrent logins are useful together with cluster filesystems.
- */
-static int sbp2_param_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
-MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
-		 "(default = Y, use N for concurrent initiators)");
-
-/*
- * Flags for firmware oddities
- *
- * - 128kB max transfer
- *   Limit transfer size. Necessary for some old bridges.
- *
- * - 36 byte inquiry
- *   When scsi_mod probes the device, let the inquiry command look like that
- *   from MS Windows.
- *
- * - skip mode page 8
- *   Suppress sending of mode_sense for mode page 8 if the device pretends to
- *   support the SCSI Primary Block commands instead of Reduced Block Commands.
- *
- * - fix capacity
- *   Tell sd_mod to correct the last sector number reported by read_capacity.
- *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
- *   Don't use this with devices which don't have this bug.
- *
- * - delay inquiry
- *   Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
- *
- * - power condition
- *   Set the power condition field in the START STOP UNIT commands sent by
- *   sd_mod on suspend, resume, and shutdown (if manage_start_stop is on).
- *   Some disks need this to spin down or to resume properly.
- *
- * - override internal blacklist
- *   Instead of adding to the built-in blacklist, use only the workarounds
- *   specified in the module load parameter.
- *   Useful if a blacklist entry interfered with a non-broken device.
- */
-#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_DELAY_INQUIRY	0x10
-#define SBP2_INQUIRY_DELAY		12
-#define SBP2_WORKAROUND_POWER_CONDITION	0x20
-#define SBP2_WORKAROUND_OVERRIDE	0x100
-
-static int sbp2_param_workarounds;
-module_param_named(workarounds, sbp2_param_workarounds, int, 0644);
-MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
-	", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
-	", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
-	", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
-	", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
-	", delay inquiry = "      __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
-	", set power condition in start stop unit = "
-				  __stringify(SBP2_WORKAROUND_POWER_CONDITION)
-	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
-	", or a combination)");
-
-/* 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";
-
-/*
- * We create one struct sbp2_logical_unit per SBP-2 Logical Unit Number Entry
- * and one struct scsi_device per sbp2_logical_unit.
- */
-struct sbp2_logical_unit {
-	struct sbp2_target *tgt;
-	struct list_head link;
-	struct fw_address_handler address_handler;
-	struct list_head orb_list;
-
-	u64 command_block_agent_address;
-	u16 lun;
-	int login_id;
-
-	/*
-	 * The generation is updated once we've logged in or reconnected
-	 * to the logical unit.  Thus, I/O to the device will automatically
-	 * fail and get retried if it happens in a window where the device
-	 * is not ready, e.g. after a bus reset but before we reconnect.
-	 */
-	int generation;
-	int retries;
-	struct delayed_work work;
-	bool has_sdev;
-	bool blocked;
-};
-
-/*
- * We create one struct sbp2_target per IEEE 1212 Unit Directory
- * and one struct Scsi_Host per sbp2_target.
- */
-struct sbp2_target {
-	struct kref kref;
-	struct fw_unit *unit;
-	const char *bus_id;
-	struct list_head lu_list;
-
-	u64 management_agent_address;
-	u64 guid;
-	int directory_id;
-	int node_id;
-	int address_high;
-	unsigned int workarounds;
-	unsigned int mgt_orb_timeout;
-	unsigned int max_payload;
-
-	int dont_block;	/* counter for each logical unit */
-	int blocked;	/* ditto */
-};
-
-/* Impossible login_id, to detect logout attempt before successful login */
-#define INVALID_LOGIN_ID 0x10000
-
-/*
- * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
- * provided in the config rom. Most devices do provide a value, which
- * we'll use for login management orbs, but with some sane limits.
- */
-#define SBP2_MIN_LOGIN_ORB_TIMEOUT	5000U	/* Timeout in ms */
-#define SBP2_MAX_LOGIN_ORB_TIMEOUT	40000U	/* Timeout in ms */
-#define SBP2_ORB_TIMEOUT		2000U	/* Timeout in ms */
-#define SBP2_ORB_NULL			0x80000000
-#define SBP2_RETRY_LIMIT		0xf		/* 15 retries */
-#define SBP2_CYCLE_LIMIT		(0xc8 << 12)	/* 200 125us cycles */
-
-/*
- * The default maximum s/g segment size of a FireWire controller is
- * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
- * be quadlet-aligned, we set the length limit to 0xffff & ~3.
- */
-#define SBP2_MAX_SEG_SIZE		0xfffc
-
-/* Unit directory keys */
-#define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
-#define SBP2_CSR_FIRMWARE_REVISION	0x3c
-#define SBP2_CSR_LOGICAL_UNIT_NUMBER	0x14
-#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY	0xd4
-
-/* 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 {
-	__be32 high;
-	__be32 low;
-};
-
-struct sbp2_orb {
-	struct fw_transaction t;
-	struct kref kref;
-	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(v)		((v) ? 1 << 28 : 0)
-#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;
-		__be32 misc;
-		__be32 length;
-		struct sbp2_pointer status_fifo;
-	} request;
-	__be32 response[4];
-	dma_addr_t response_bus;
-	struct completion done;
-	struct sbp2_status status;
-};
-
-struct sbp2_login_response {
-	__be32 misc;
-	struct sbp2_pointer command_block_agent;
-	__be32 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		((1) << 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;
-		__be32 misc;
-		u8 command_block[12];
-	} request;
-	struct scsi_cmnd *cmd;
-	scsi_done_fn_t done;
-	struct sbp2_logical_unit *lu;
-
-	struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
-	dma_addr_t page_table_bus;
-};
-
-#define SBP2_ROM_VALUE_WILDCARD ~0         /* match all */
-#define SBP2_ROM_VALUE_MISSING  0xff000000 /* not present in the unit dir. */
-
-/*
- * 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.
- */
-static const struct {
-	u32 firmware_revision;
-	u32 model;
-	unsigned int 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 |
-					  SBP2_WORKAROUND_POWER_CONDITION,
-	},
-	/* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
-		.firmware_revision	= 0x002800,
-		.model			= 0x000000,
-		.workarounds		= SBP2_WORKAROUND_DELAY_INQUIRY |
-					  SBP2_WORKAROUND_POWER_CONDITION,
-	},
-	/* Initio bridges, actually only needed for some older ones */ {
-		.firmware_revision	= 0x000200,
-		.model			= SBP2_ROM_VALUE_WILDCARD,
-		.workarounds		= SBP2_WORKAROUND_INQUIRY_36,
-	},
-	/* PL-3507 bridge with Prolific firmware */ {
-		.firmware_revision	= 0x012800,
-		.model			= SBP2_ROM_VALUE_WILDCARD,
-		.workarounds		= SBP2_WORKAROUND_POWER_CONDITION,
-	},
-	/* Symbios bridge */ {
-		.firmware_revision	= 0xa0b800,
-		.model			= SBP2_ROM_VALUE_WILDCARD,
-		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
-	},
-	/* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ {
-		.firmware_revision	= 0x002600,
-		.model			= SBP2_ROM_VALUE_WILDCARD,
-		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
-	},
-	/*
-	 * iPod 2nd generation: needs 128k max transfer size workaround
-	 * iPod 3rd generation: needs fix capacity workaround
-	 */
-	{
-		.firmware_revision	= 0x0a2700,
-		.model			= 0x000000,
-		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS |
-					  SBP2_WORKAROUND_FIX_CAPACITY,
-	},
-	/* iPod 4th generation */ {
-		.firmware_revision	= 0x0a2700,
-		.model			= 0x000021,
-		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
-	},
-	/* iPod mini */ {
-		.firmware_revision	= 0x0a2700,
-		.model			= 0x000022,
-		.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 free_orb(struct kref *kref)
-{
-	struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref);
-
-	kfree(orb);
-}
-
-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_logical_unit *lu = 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, &lu->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 != &lu->orb_list)
-		orb->callback(orb, &status);
-	else
-		fw_error("status write for unknown orb\n");
-
-	kref_put(&orb->kref, free_orb);
-
-	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;
-
-	/*
-	 * This is a little tricky.  We can get the status write for
-	 * the orb before we get this callback.  The status write
-	 * handler above will assume the orb pointer transaction was
-	 * successful and set the rcode to RCODE_COMPLETE for the orb.
-	 * So this callback only sets the rcode if it hasn't already
-	 * been set and only does the cleanup if the transaction
-	 * failed and we didn't already get a status write.
-	 */
-	spin_lock_irqsave(&card->lock, flags);
-
-	if (orb->rcode == -1)
-		orb->rcode = rcode;
-	if (orb->rcode != RCODE_COMPLETE) {
-		list_del(&orb->link);
-		spin_unlock_irqrestore(&card->lock, flags);
-		orb->callback(orb, NULL);
-	} else {
-		spin_unlock_irqrestore(&card->lock, flags);
-	}
-
-	kref_put(&orb->kref, free_orb);
-}
-
-static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
-			  int node_id, int generation, u64 offset)
-{
-	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-	unsigned long flags;
-
-	orb->pointer.high = 0;
-	orb->pointer.low = cpu_to_be32(orb->request_bus);
-
-	spin_lock_irqsave(&device->card->lock, flags);
-	list_add_tail(&orb->link, &lu->orb_list);
-	spin_unlock_irqrestore(&device->card->lock, flags);
-
-	/* Take a ref for the orb list and for the transaction callback. */
-	kref_get(&orb->kref);
-	kref_get(&orb->kref);
-
-	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
-			node_id, generation, device->max_speed, offset,
-			&orb->pointer, sizeof(orb->pointer),
-			complete_transaction, orb);
-}
-
-static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
-{
-	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-	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(&lu->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 =
-		container_of(base_orb, struct sbp2_management_orb, base);
-
-	if (status)
-		memcpy(&orb->status, status, sizeof(*status));
-	complete(&orb->done);
-}
-
-static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
-				    int generation, int function,
-				    int lun_or_login_id, void *response)
-{
-	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-	struct sbp2_management_orb *orb;
-	unsigned int timeout;
-	int retval = -ENOMEM;
-
-	if (function == SBP2_LOGOUT_REQUEST && fw_device_is_shutdown(device))
-		return 0;
-
-	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
-	if (orb == NULL)
-		return -ENOMEM;
-
-	kref_init(&orb->base.kref);
-	orb->response_bus =
-		dma_map_single(device->card->device, &orb->response,
-			       sizeof(orb->response), DMA_FROM_DEVICE);
-	if (dma_mapping_error(device->card->device, orb->response_bus))
-		goto fail_mapping_response;
-
-	orb->request.response.high = 0;
-	orb->request.response.low  = cpu_to_be32(orb->response_bus);
-
-	orb->request.misc = cpu_to_be32(
-		MANAGEMENT_ORB_NOTIFY |
-		MANAGEMENT_ORB_FUNCTION(function) |
-		MANAGEMENT_ORB_LUN(lun_or_login_id));
-	orb->request.length = cpu_to_be32(
-		MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)));
-
-	orb->request.status_fifo.high =
-		cpu_to_be32(lu->address_handler.offset >> 32);
-	orb->request.status_fifo.low  =
-		cpu_to_be32(lu->address_handler.offset);
-
-	if (function == SBP2_LOGIN_REQUEST) {
-		/* Ask for 2^2 == 4 seconds reconnect grace period */
-		orb->request.misc |= cpu_to_be32(
-			MANAGEMENT_ORB_RECONNECT(2) |
-			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login));
-		timeout = lu->tgt->mgt_orb_timeout;
-	} else {
-		timeout = SBP2_ORB_TIMEOUT;
-	}
-
-	init_completion(&orb->done);
-	orb->base.callback = complete_management_orb;
-
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(device->card->device, orb->base.request_bus))
-		goto fail_mapping_request;
-
-	sbp2_send_orb(&orb->base, lu, node_id, generation,
-		      lu->tgt->management_agent_address);
-
-	wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout));
-
-	retval = -EIO;
-	if (sbp2_cancel_orbs(lu) == 0) {
-		fw_error("%s: orb reply timed out, rcode=0x%02x\n",
-			 lu->tgt->bus_id, orb->base.rcode);
-		goto out;
-	}
-
-	if (orb->base.rcode != RCODE_COMPLETE) {
-		fw_error("%s: management write failed, rcode 0x%02x\n",
-			 lu->tgt->bus_id, orb->base.rcode);
-		goto out;
-	}
-
-	if (STATUS_GET_RESPONSE(orb->status) != 0 ||
-	    STATUS_GET_SBP_STATUS(orb->status) != 0) {
-		fw_error("%s: error status: %d:%d\n", lu->tgt->bus_id,
-			 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);
- fail_mapping_request:
-	dma_unmap_single(device->card->device, orb->response_bus,
-			 sizeof(orb->response), DMA_FROM_DEVICE);
- fail_mapping_response:
-	if (response)
-		memcpy(response, orb->response, sizeof(orb->response));
-	kref_put(&orb->base.kref, free_orb);
-
-	return retval;
-}
-
-static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
-{
-	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-	__be32 d = 0;
-
-	fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
-			   lu->tgt->node_id, lu->generation, device->max_speed,
-			   lu->command_block_agent_address + SBP2_AGENT_RESET,
-			   &d, sizeof(d));
-}
-
-static void complete_agent_reset_write_no_wait(struct fw_card *card,
-		int rcode, void *payload, size_t length, void *data)
-{
-	kfree(data);
-}
-
-static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
-{
-	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-	struct fw_transaction *t;
-	static __be32 d;
-
-	t = kmalloc(sizeof(*t), GFP_ATOMIC);
-	if (t == NULL)
-		return;
-
-	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
-			lu->tgt->node_id, lu->generation, device->max_speed,
-			lu->command_block_agent_address + SBP2_AGENT_RESET,
-			&d, sizeof(d), complete_agent_reset_write_no_wait, t);
-}
-
-static inline void sbp2_allow_block(struct sbp2_logical_unit *lu)
-{
-	/*
-	 * We may access dont_block without taking card->lock here:
-	 * All callers of sbp2_allow_block() and all callers of sbp2_unblock()
-	 * are currently serialized against each other.
-	 * And a wrong result in sbp2_conditionally_block()'s access of
-	 * dont_block is rather harmless, it simply misses its first chance.
-	 */
-	--lu->tgt->dont_block;
-}
-
-/*
- * Blocks lu->tgt if all of the following conditions are met:
- *   - Login, INQUIRY, and high-level SCSI setup of all of the target's
- *     logical units have been finished (indicated by dont_block == 0).
- *   - lu->generation is stale.
- *
- * Note, scsi_block_requests() must be called while holding card->lock,
- * otherwise it might foil sbp2_[conditionally_]unblock()'s attempt to
- * unblock the target.
- */
-static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
-{
-	struct sbp2_target *tgt = lu->tgt;
-	struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
-	struct Scsi_Host *shost =
-		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	if (!tgt->dont_block && !lu->blocked &&
-	    lu->generation != card->generation) {
-		lu->blocked = true;
-		if (++tgt->blocked == 1)
-			scsi_block_requests(shost);
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/*
- * Unblocks lu->tgt as soon as all its logical units can be unblocked.
- * Note, it is harmless to run scsi_unblock_requests() outside the
- * card->lock protected section.  On the other hand, running it inside
- * the section might clash with shost->host_lock.
- */
-static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
-{
-	struct sbp2_target *tgt = lu->tgt;
-	struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
-	struct Scsi_Host *shost =
-		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	unsigned long flags;
-	bool unblock = false;
-
-	spin_lock_irqsave(&card->lock, flags);
-	if (lu->blocked && lu->generation == card->generation) {
-		lu->blocked = false;
-		unblock = --tgt->blocked == 0;
-	}
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	if (unblock)
-		scsi_unblock_requests(shost);
-}
-
-/*
- * Prevents future blocking of tgt and unblocks it.
- * Note, it is harmless to run scsi_unblock_requests() outside the
- * card->lock protected section.  On the other hand, running it inside
- * the section might clash with shost->host_lock.
- */
-static void sbp2_unblock(struct sbp2_target *tgt)
-{
-	struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
-	struct Scsi_Host *shost =
-		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	++tgt->dont_block;
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	scsi_unblock_requests(shost);
-}
-
-static int sbp2_lun2int(u16 lun)
-{
-	struct scsi_lun eight_bytes_lun;
-
-	memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun));
-	eight_bytes_lun.scsi_lun[0] = (lun >> 8) & 0xff;
-	eight_bytes_lun.scsi_lun[1] = lun & 0xff;
-
-	return scsilun_to_int(&eight_bytes_lun);
-}
-
-static void sbp2_release_target(struct kref *kref)
-{
-	struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
-	struct sbp2_logical_unit *lu, *next;
-	struct Scsi_Host *shost =
-		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	struct scsi_device *sdev;
-	struct fw_device *device = fw_device(tgt->unit->device.parent);
-
-	/* prevent deadlocks */
-	sbp2_unblock(tgt);
-
-	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
-		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
-		if (sdev) {
-			scsi_remove_device(sdev);
-			scsi_device_put(sdev);
-		}
-		if (lu->login_id != INVALID_LOGIN_ID) {
-			int generation, node_id;
-			/*
-			 * tgt->node_id may be obsolete here if we failed
-			 * during initial login or after a bus reset where
-			 * the topology changed.
-			 */
-			generation = device->generation;
-			smp_rmb(); /* node_id vs. generation */
-			node_id    = device->node_id;
-			sbp2_send_management_orb(lu, node_id, generation,
-						 SBP2_LOGOUT_REQUEST,
-						 lu->login_id, NULL);
-		}
-		fw_core_remove_address_handler(&lu->address_handler);
-		list_del(&lu->link);
-		kfree(lu);
-	}
-	scsi_remove_host(shost);
-	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
-
-	fw_unit_put(tgt->unit);
-	scsi_host_put(shost);
-	fw_device_put(device);
-}
-
-static struct workqueue_struct *sbp2_wq;
-
-static void sbp2_target_put(struct sbp2_target *tgt)
-{
-	kref_put(&tgt->kref, sbp2_release_target);
-}
-
-/*
- * Always get the target's kref when scheduling work on one its units.
- * Each workqueue job is responsible to call sbp2_target_put() upon return.
- */
-static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
-{
-	kref_get(&lu->tgt->kref);
-	if (!queue_delayed_work(sbp2_wq, &lu->work, delay))
-		sbp2_target_put(lu->tgt);
-}
-
-/*
- * Write retransmit retry values into the BUSY_TIMEOUT register.
- * - The single-phase retry protocol is supported by all SBP-2 devices, but the
- *   default retry_limit value is 0 (i.e. never retry transmission). We write a
- *   saner value after logging into the device.
- * - The dual-phase retry protocol is optional to implement, and if not
- *   supported, writes to the dual-phase portion of the register will be
- *   ignored. We try to write the original 1394-1995 default here.
- * - In the case of devices that are also SBP-3-compliant, all writes are
- *   ignored, as the register is read-only, but contains single-phase retry of
- *   15, which is what we're trying to set for all SBP-2 device anyway, so this
- *   write attempt is safe and yields more consistent behavior for all devices.
- *
- * See section 8.3.2.3.5 of the 1394-1995 spec, section 6.2 of the SBP-2 spec,
- * and section 6.4 of the SBP-3 spec for further details.
- */
-static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
-{
-	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-	__be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
-
-	fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
-			   lu->tgt->node_id, lu->generation, device->max_speed,
-			   CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT,
-			   &d, sizeof(d));
-}
-
-static void sbp2_reconnect(struct work_struct *work);
-
-static void sbp2_login(struct work_struct *work)
-{
-	struct sbp2_logical_unit *lu =
-		container_of(work, struct sbp2_logical_unit, work.work);
-	struct sbp2_target *tgt = lu->tgt;
-	struct fw_device *device = fw_device(tgt->unit->device.parent);
-	struct Scsi_Host *shost;
-	struct scsi_device *sdev;
-	struct sbp2_login_response response;
-	int generation, node_id, local_node_id;
-
-	if (fw_device_is_shutdown(device))
-		goto out;
-
-	generation    = device->generation;
-	smp_rmb();    /* node IDs must not be older than generation */
-	node_id       = device->node_id;
-	local_node_id = device->card->node_id;
-
-	/* If this is a re-login attempt, log out, or we might be rejected. */
-	if (lu->has_sdev)
-		sbp2_send_management_orb(lu, device->node_id, generation,
-				SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
-
-	if (sbp2_send_management_orb(lu, node_id, generation,
-				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
-		if (lu->retries++ < 5) {
-			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-		} else {
-			fw_error("%s: failed to login to LUN %04x\n",
-				 tgt->bus_id, lu->lun);
-			/* Let any waiting I/O fail from now on. */
-			sbp2_unblock(lu->tgt);
-		}
-		goto out;
-	}
-
-	tgt->node_id	  = node_id;
-	tgt->address_high = local_node_id << 16;
-	smp_wmb();	  /* node IDs must not be older than generation */
-	lu->generation	  = generation;
-
-	lu->command_block_agent_address =
-		((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff)
-		      << 32) | be32_to_cpu(response.command_block_agent.low);
-	lu->login_id = be32_to_cpu(response.misc) & 0xffff;
-
-	fw_notify("%s: logged in to LUN %04x (%d retries)\n",
-		  tgt->bus_id, lu->lun, lu->retries);
-
-	/* set appropriate retry limit(s) in BUSY_TIMEOUT register */
-	sbp2_set_busy_timeout(lu);
-
-	PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
-	sbp2_agent_reset(lu);
-
-	/* This was a re-login. */
-	if (lu->has_sdev) {
-		sbp2_cancel_orbs(lu);
-		sbp2_conditionally_unblock(lu);
-		goto out;
-	}
-
-	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
-		ssleep(SBP2_INQUIRY_DELAY);
-
-	shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	sdev = __scsi_add_device(shost, 0, 0, sbp2_lun2int(lu->lun), lu);
-	/*
-	 * FIXME:  We are unable to perform reconnects while in sbp2_login().
-	 * Therefore __scsi_add_device() will get into trouble if a bus reset
-	 * happens in parallel.  It will either fail or leave us with an
-	 * unusable sdev.  As a workaround we check for this and retry the
-	 * whole login and SCSI probing.
-	 */
-
-	/* Reported error during __scsi_add_device() */
-	if (IS_ERR(sdev))
-		goto out_logout_login;
-
-	/* Unreported error during __scsi_add_device() */
-	smp_rmb(); /* get current card generation */
-	if (generation != device->card->generation) {
-		scsi_remove_device(sdev);
-		scsi_device_put(sdev);
-		goto out_logout_login;
-	}
-
-	/* No error during __scsi_add_device() */
-	lu->has_sdev = true;
-	scsi_device_put(sdev);
-	sbp2_allow_block(lu);
-	goto out;
-
- out_logout_login:
-	smp_rmb(); /* generation may have changed */
-	generation = device->generation;
-	smp_rmb(); /* node_id must not be older than generation */
-
-	sbp2_send_management_orb(lu, device->node_id, generation,
-				 SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
-	/*
-	 * If a bus reset happened, sbp2_update will have requeued
-	 * lu->work already.  Reset the work from reconnect to login.
-	 */
-	PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- out:
-	sbp2_target_put(tgt);
-}
-
-static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
-{
-	struct sbp2_logical_unit *lu;
-
-	lu = kmalloc(sizeof(*lu), GFP_KERNEL);
-	if (!lu)
-		return -ENOMEM;
-
-	lu->address_handler.length           = 0x100;
-	lu->address_handler.address_callback = sbp2_status_write;
-	lu->address_handler.callback_data    = lu;
-
-	if (fw_core_add_address_handler(&lu->address_handler,
-					&fw_high_memory_region) < 0) {
-		kfree(lu);
-		return -ENOMEM;
-	}
-
-	lu->tgt      = tgt;
-	lu->lun      = lun_entry & 0xffff;
-	lu->login_id = INVALID_LOGIN_ID;
-	lu->retries  = 0;
-	lu->has_sdev = false;
-	lu->blocked  = false;
-	++tgt->dont_block;
-	INIT_LIST_HEAD(&lu->orb_list);
-	INIT_DELAYED_WORK(&lu->work, sbp2_login);
-
-	list_add_tail(&lu->link, &tgt->lu_list);
-	return 0;
-}
-
-static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory)
-{
-	struct fw_csr_iterator ci;
-	int key, value;
-
-	fw_csr_iterator_init(&ci, directory);
-	while (fw_csr_iterator_next(&ci, &key, &value))
-		if (key == SBP2_CSR_LOGICAL_UNIT_NUMBER &&
-		    sbp2_add_logical_unit(tgt, value) < 0)
-			return -ENOMEM;
-	return 0;
-}
-
-static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
-			      u32 *model, u32 *firmware_revision)
-{
-	struct fw_csr_iterator ci;
-	int key, value;
-	unsigned int timeout;
-
-	fw_csr_iterator_init(&ci, directory);
-	while (fw_csr_iterator_next(&ci, &key, &value)) {
-		switch (key) {
-
-		case CSR_DEPENDENT_INFO | CSR_OFFSET:
-			tgt->management_agent_address =
-					CSR_REGISTER_BASE + 4 * value;
-			break;
-
-		case CSR_DIRECTORY_ID:
-			tgt->directory_id = value;
-			break;
-
-		case CSR_MODEL:
-			*model = value;
-			break;
-
-		case SBP2_CSR_FIRMWARE_REVISION:
-			*firmware_revision = value;
-			break;
-
-		case SBP2_CSR_UNIT_CHARACTERISTICS:
-			/* the timeout value is stored in 500ms units */
-			timeout = ((unsigned int) value >> 8 & 0xff) * 500;
-			timeout = max(timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT);
-			tgt->mgt_orb_timeout =
-				  min(timeout, SBP2_MAX_LOGIN_ORB_TIMEOUT);
-
-			if (timeout > tgt->mgt_orb_timeout)
-				fw_notify("%s: config rom contains %ds "
-					  "management ORB timeout, limiting "
-					  "to %ds\n", tgt->bus_id,
-					  timeout / 1000,
-					  tgt->mgt_orb_timeout / 1000);
-			break;
-
-		case SBP2_CSR_LOGICAL_UNIT_NUMBER:
-			if (sbp2_add_logical_unit(tgt, value) < 0)
-				return -ENOMEM;
-			break;
-
-		case SBP2_CSR_LOGICAL_UNIT_DIRECTORY:
-			/* Adjust for the increment in the iterator */
-			if (sbp2_scan_logical_unit_dir(tgt, ci.p - 1 + value) < 0)
-				return -ENOMEM;
-			break;
-		}
-	}
-	return 0;
-}
-
-static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
-				  u32 firmware_revision)
-{
-	int i;
-	unsigned int w = sbp2_param_workarounds;
-
-	if (w)
-		fw_notify("Please notify linux1394-devel@lists.sourceforge.net "
-			  "if you need the workarounds parameter for %s\n",
-			  tgt->bus_id);
-
-	if (w & SBP2_WORKAROUND_OVERRIDE)
-		goto out;
-
-	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 != SBP2_ROM_VALUE_WILDCARD)
-			continue;
-
-		w |= sbp2_workarounds_table[i].workarounds;
-		break;
-	}
- out:
-	if (w)
-		fw_notify("Workarounds for %s: 0x%x "
-			  "(firmware_revision 0x%06x, model_id 0x%06x)\n",
-			  tgt->bus_id, w, firmware_revision, model);
-	tgt->workarounds = w;
-}
-
-static struct scsi_host_template scsi_driver_template;
-
-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_target *tgt;
-	struct sbp2_logical_unit *lu;
-	struct Scsi_Host *shost;
-	u32 model, firmware_revision;
-
-	if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
-		BUG_ON(dma_set_max_seg_size(device->card->device,
-					    SBP2_MAX_SEG_SIZE));
-
-	shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
-	if (shost == NULL)
-		return -ENOMEM;
-
-	tgt = (struct sbp2_target *)shost->hostdata;
-	unit->device.driver_data = tgt;
-	tgt->unit = unit;
-	kref_init(&tgt->kref);
-	INIT_LIST_HEAD(&tgt->lu_list);
-	tgt->bus_id = dev_name(&unit->device);
-	tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
-
-	if (fw_device_enable_phys_dma(device) < 0)
-		goto fail_shost_put;
-
-	if (scsi_add_host(shost, &unit->device) < 0)
-		goto fail_shost_put;
-
-	fw_device_get(device);
-	fw_unit_get(unit);
-
-	/* implicit directory ID */
-	tgt->directory_id = ((unit->directory - device->config_rom) * 4
-			     + CSR_CONFIG_ROM) & 0xffffff;
-
-	firmware_revision = SBP2_ROM_VALUE_MISSING;
-	model		  = SBP2_ROM_VALUE_MISSING;
-
-	if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
-			       &firmware_revision) < 0)
-		goto fail_tgt_put;
-
-	sbp2_init_workarounds(tgt, model, firmware_revision);
-
-	/*
-	 * At S100 we can do 512 bytes per packet, at S200 1024 bytes,
-	 * and so on up to 4096 bytes.  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.
-	 */
-	tgt->max_payload = min(device->max_speed + 7, 10U);
-	tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1);
-
-	/* Do the login in a workqueue so we can easily reschedule retries. */
-	list_for_each_entry(lu, &tgt->lu_list, link)
-		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-	return 0;
-
- fail_tgt_put:
-	sbp2_target_put(tgt);
-	return -ENOMEM;
-
- fail_shost_put:
-	scsi_host_put(shost);
-	return -ENOMEM;
-}
-
-static int sbp2_remove(struct device *dev)
-{
-	struct fw_unit *unit = fw_unit(dev);
-	struct sbp2_target *tgt = unit->device.driver_data;
-
-	sbp2_target_put(tgt);
-	return 0;
-}
-
-static void sbp2_reconnect(struct work_struct *work)
-{
-	struct sbp2_logical_unit *lu =
-		container_of(work, struct sbp2_logical_unit, work.work);
-	struct sbp2_target *tgt = lu->tgt;
-	struct fw_device *device = fw_device(tgt->unit->device.parent);
-	int generation, node_id, local_node_id;
-
-	if (fw_device_is_shutdown(device))
-		goto out;
-
-	generation    = device->generation;
-	smp_rmb();    /* node IDs must not be older than generation */
-	node_id       = device->node_id;
-	local_node_id = device->card->node_id;
-
-	if (sbp2_send_management_orb(lu, node_id, generation,
-				     SBP2_RECONNECT_REQUEST,
-				     lu->login_id, NULL) < 0) {
-		/*
-		 * If reconnect was impossible even though we are in the
-		 * current generation, fall back and try to log in again.
-		 *
-		 * We could check for "Function rejected" status, but
-		 * looking at the bus generation as simpler and more general.
-		 */
-		smp_rmb(); /* get current card generation */
-		if (generation == device->card->generation ||
-		    lu->retries++ >= 5) {
-			fw_error("%s: failed to reconnect\n", tgt->bus_id);
-			lu->retries = 0;
-			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
-		}
-		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-		goto out;
-	}
-
-	tgt->node_id      = node_id;
-	tgt->address_high = local_node_id << 16;
-	smp_wmb();	  /* node IDs must not be older than generation */
-	lu->generation	  = generation;
-
-	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
-		  tgt->bus_id, lu->lun, lu->retries);
-
-	sbp2_agent_reset(lu);
-	sbp2_cancel_orbs(lu);
-	sbp2_conditionally_unblock(lu);
- out:
-	sbp2_target_put(tgt);
-}
-
-static void sbp2_update(struct fw_unit *unit)
-{
-	struct sbp2_target *tgt = unit->device.driver_data;
-	struct sbp2_logical_unit *lu;
-
-	fw_device_enable_phys_dma(fw_device(unit->device.parent));
-
-	/*
-	 * Fw-core serializes sbp2_update() against sbp2_remove().
-	 * Iteration over tgt->lu_list is therefore safe here.
-	 */
-	list_for_each_entry(lu, &tgt->lu_list, link) {
-		sbp2_conditionally_block(lu);
-		lu->retries = 0;
-		sbp2_queue_work(lu, 0);
-	}
-}
-
-#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 void sbp2_unmap_scatterlist(struct device *card_device,
-				   struct sbp2_command_orb *orb)
-{
-	if (scsi_sg_count(orb->cmd))
-		dma_unmap_sg(card_device, scsi_sglist(orb->cmd),
-			     scsi_sg_count(orb->cmd),
-			     orb->cmd->sc_data_direction);
-
-	if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT))
-		dma_unmap_single(card_device, orb->page_table_bus,
-				 sizeof(orb->page_table), DMA_TO_DEVICE);
-}
-
-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 =
-		container_of(base_orb, struct sbp2_command_orb, base);
-	struct fw_device *device = fw_device(orb->lu->tgt->unit->device.parent);
-	int result;
-
-	if (status != NULL) {
-		if (STATUS_GET_DEAD(*status))
-			sbp2_agent_reset_no_wait(orb->lu);
-
-		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;
-		sbp2_conditionally_block(orb->lu);
-	}
-
-	dma_unmap_single(device->card->device, orb->base.request_bus,
-			 sizeof(orb->request), DMA_TO_DEVICE);
-	sbp2_unmap_scatterlist(device->card->device, orb);
-
-	orb->cmd->result = result;
-	orb->done(orb->cmd);
-}
-
-static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
-		struct fw_device *device, struct sbp2_logical_unit *lu)
-{
-	struct scatterlist *sg = scsi_sglist(orb->cmd);
-	int i, n;
-
-	n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
-		       orb->cmd->sc_data_direction);
-	if (n == 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 (n == 1) {
-		orb->request.data_descriptor.high =
-			cpu_to_be32(lu->tgt->address_high);
-		orb->request.data_descriptor.low  =
-			cpu_to_be32(sg_dma_address(sg));
-		orb->request.misc |=
-			cpu_to_be32(COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)));
-		return 0;
-	}
-
-	for_each_sg(sg, sg, n, i) {
-		orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
-		orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg));
-	}
-
-	orb->page_table_bus =
-		dma_map_single(device->card->device, orb->page_table,
-			       sizeof(orb->page_table), DMA_TO_DEVICE);
-	if (dma_mapping_error(device->card->device, orb->page_table_bus))
-		goto fail_page_table;
-
-	/*
-	 * 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->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
-	orb->request.data_descriptor.low  = cpu_to_be32(orb->page_table_bus);
-	orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
-					 COMMAND_ORB_DATA_SIZE(n));
-
-	return 0;
-
- fail_page_table:
-	dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
-		     scsi_sg_count(orb->cmd), 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_logical_unit *lu = cmd->device->hostdata;
-	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-	struct sbp2_command_orb *orb;
-	int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
-
-	/*
-	 * Bidirectional commands are not yet implemented, and unknown
-	 * transfer direction not handled.
-	 */
-	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
-		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
-		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");
-		return SCSI_MLQUEUE_HOST_BUSY;
-	}
-
-	/* Initialize rcode to something not RCODE_COMPLETE. */
-	orb->base.rcode = -1;
-	kref_init(&orb->base.kref);
-
-	orb->lu   = lu;
-	orb->done = done;
-	orb->cmd  = cmd;
-
-	orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
-	orb->request.misc = cpu_to_be32(
-		COMMAND_ORB_MAX_PAYLOAD(lu->tgt->max_payload) |
-		COMMAND_ORB_SPEED(device->max_speed) |
-		COMMAND_ORB_NOTIFY);
-
-	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
-		orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
-
-	generation = device->generation;
-	smp_rmb();    /* sbp2_map_scatterlist looks at tgt->address_high */
-
-	if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
-		goto out;
-
-	memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
-
-	orb->base.callback = complete_command_orb;
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(device->card->device, orb->base.request_bus)) {
-		sbp2_unmap_scatterlist(device->card->device, orb);
-		goto out;
-	}
-
-	sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation,
-		      lu->command_block_agent_address + SBP2_ORB_POINTER);
-	retval = 0;
- out:
-	kref_put(&orb->base.kref, free_orb);
-	return retval;
-}
-
-static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
-{
-	struct sbp2_logical_unit *lu = sdev->hostdata;
-
-	/* (Re-)Adding logical units via the SCSI stack is not supported. */
-	if (!lu)
-		return -ENOSYS;
-
-	sdev->allow_restart = 1;
-
-	/* SBP-2 requires quadlet alignment of the data buffers. */
-	blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
-
-	if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
-		sdev->inquiry_len = 36;
-
-	return 0;
-}
-
-static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
-{
-	struct sbp2_logical_unit *lu = sdev->hostdata;
-
-	sdev->use_10_for_rw = 1;
-
-	if (sbp2_param_exclusive_login)
-		sdev->manage_start_stop = 1;
-
-	if (sdev->type == TYPE_ROM)
-		sdev->use_10_for_ms = 1;
-
-	if (sdev->type == TYPE_DISK &&
-	    lu->tgt->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
-		sdev->skip_ms_page_8 = 1;
-
-	if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
-		sdev->fix_capacity = 1;
-
-	if (lu->tgt->workarounds & SBP2_WORKAROUND_POWER_CONDITION)
-		sdev->start_stop_pwr_cond = 1;
-
-	if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
-		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
-
-	blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
-
-	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_logical_unit *lu = cmd->device->hostdata;
-
-	fw_notify("%s: sbp2_scsi_abort\n", lu->tgt->bus_id);
-	sbp2_agent_reset(lu);
-	sbp2_cancel_orbs(lu);
-
-	return SUCCESS;
-}
-
-/*
- * Format of /sys/bus/scsi/devices/.../ieee1394_id:
- * u64 EUI-64 : u24 directory_ID : u16 LUN  (all printed in hexadecimal)
- *
- * This is the concatenation of target port identifier and logical unit
- * identifier as per SAM-2...SAM-4 annex A.
- */
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	struct scsi_device *sdev = to_scsi_device(dev);
-	struct sbp2_logical_unit *lu;
-
-	if (!sdev)
-		return 0;
-
-	lu = sdev->hostdata;
-
-	return sprintf(buf, "%016llx:%06x:%04x\n",
-			(unsigned long long)lu->tgt->guid,
-			lu->tgt->directory_id, lu->lun);
-}
-
-static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
-
-static struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
-	&dev_attr_ieee1394_id,
-	NULL
-};
-
-static struct scsi_host_template scsi_driver_template = {
-	.module			= THIS_MODULE,
-	.name			= "SBP-2 IEEE-1394",
-	.proc_name		= 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,
-	.sdev_attrs		= sbp2_scsi_sysfs_attrs,
-};
-
-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)
-{
-	sbp2_wq = create_singlethread_workqueue(KBUILD_MODNAME);
-	if (!sbp2_wq)
-		return -ENOMEM;
-
-	return driver_register(&sbp2_driver.driver);
-}
-
-static void __exit sbp2_cleanup(void)
-{
-	driver_unregister(&sbp2_driver.driver);
-	destroy_workqueue(sbp2_wq);
-}
-
-module_init(sbp2_init);
-module_exit(sbp2_cleanup);
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-topology.c linux-libre-2.6.31-gnu/drivers/firewire/fw-topology.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-topology.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-topology.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,558 +0,0 @@
-/*
- * 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 <asm/bug.h>
-#include <asm/system.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->initiated_reset = SELF_ID_PHY_INITIATOR(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] == NULL)
-			continue;
-
-		if (node->ports[i]->max_hops > max_child_hops)
-			max_child_hops = node->ports[i]->max_hops;
-
-		if (node->ports[i]->max_depth > depths[0]) {
-			depths[1] = depths[0];
-			depths[0] = node->ports[i]->max_depth;
-		} else if (node->ports[i]->max_depth > depths[1])
-			depths[1] = node->ports[i]->max_depth;
-	}
-
-	node->max_depth = depths[0] + 1;
-	node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2);
-}
-
-static inline struct fw_node *fw_node(struct list_head *l)
-{
-	return list_entry(l, struct fw_node, link);
-}
-
-/**
- * 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 function 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;
-	bool beta_repeaters_present;
-
-	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);
-	beta_repeaters_present = false;
-
-	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;
-		/*
-		 * When the stack is empty, this yields an invalid value,
-		 * but that pointer will never be dereferenced.
-		 */
-		child = fw_node(h);
-
-		node = fw_node_create(q, port_count, card->color);
-		if (node == NULL) {
-			fw_error("Out of memory while building topology.\n");
-			return NULL;
-		}
-
-		if (phy_id == (card->node_id & 0x3f))
-			local_node = node;
-
-		if (SELF_ID_CONTENDER(q))
-			irm_node = node;
-
-		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] = child;
-				/*
-				 * Fix up parent reference for this
-				 * child node.
-				 */
-				child->ports[child->color] = 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 (node->phy_speed == SCODE_BETA &&
-		    parent_count + child_port_count > 1)
-			beta_repeaters_present = true;
-
-		/*
-		 * If PHYs report different gap counts, set an invalid count
-		 * which will force a gap count reconfiguration and a reset.
-		 */
-		if (SELF_ID_GAP_COUNT(q) != gap_count)
-			gap_count = 0;
-
-		update_hop_count(node);
-
-		sid = next_sid;
-		phy_id++;
-	}
-
-	card->root_node = node;
-	card->irm_node = irm_node;
-	card->gap_count = gap_count;
-	card->beta_repeaters_present = beta_repeaters_present;
-
-	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];
-			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);
-
-	/* Topology has changed - reset bus manager retry counter */
-	card->bm_retries = 0;
-}
-
-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);
-
-	/* Topology has changed - reset bus manager retry counter */
-	card->bm_retries = 0;
-}
-
-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);
-	card->local_node = NULL;
-	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];
-	node0->ports[port] = tree;
-	for (i = 0; i < tree->port_count; i++) {
-		if (tree->ports[i] == node1) {
-			tree->ports[i] = 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, *next1;
-	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) {
-		WARN_ON(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 if (node1->initiated_reset && node1->link_on)
-			event = FW_NODE_INITIATED_RESET;
-		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] && node1->ports[i]) {
-				/*
-				 * This port didn't change, queue the
-				 * connected node for further
-				 * investigation.
-				 */
-				if (node0->ports[i]->color == card->color)
-					continue;
-				list_add_tail(&node0->ports[i]->link, &list0);
-				list_add_tail(&node1->ports[i]->link, &list1);
-			} else if (node0->ports[i]) {
-				/*
-				 * 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],
-						 report_lost_node);
-				node0->ports[i] = NULL;
-			} else if (node1->ports[i]) {
-				/*
-				 * 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],
-						 report_found_node);
-			}
-		}
-
-		node0 = fw_node(node0->link.next);
-		next1 = fw_node(node1->link.next);
-		fw_node_put(node1);
-		node1 = next1;
-	}
-}
-
-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;
-
-	/*
-	 * If the selfID buffer is not the immediate successor of the
-	 * previously processed one, we cannot reliably compare the
-	 * old and new topologies.
-	 */
-	if (!is_next_generation(generation, card->generation) &&
-	    card->local_node != NULL) {
-		fw_notify("skipped bus generations, destroying all nodes\n");
-		fw_destroy_nodes(card);
-		card->bm_retries = 0;
-	}
-
-	spin_lock_irqsave(&card->lock, flags);
-
-	card->broadcast_channel_allocated = false;
-	card->node_id = node_id;
-	/*
-	 * Update node_id before generation to prevent anybody from using
-	 * a stale node_id together with a current generation.
-	 */
-	smp_wmb();
-	card->generation = generation;
-	card->reset_jiffies = jiffies;
-	fw_schedule_bm_work(card, 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 -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-topology.h linux-libre-2.6.31-gnu/drivers/firewire/fw-topology.h
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-topology.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-topology.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- * 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
-
-#include <linux/list.h>
-#include <linux/slab.h>
-
-#include <asm/atomic.h>
-
-enum {
-	FW_NODE_CREATED,
-	FW_NODE_UPDATED,
-	FW_NODE_DESTROYED,
-	FW_NODE_LINK_ON,
-	FW_NODE_LINK_OFF,
-	FW_NODE_INITIATED_RESET,
-};
-
-struct fw_node {
-	u16 node_id;
-	u8 color;
-	u8 port_count;
-	u8 link_on : 1;
-	u8 initiated_reset : 1;
-	u8 b_path : 1;
-	u8 phy_speed : 2; /* As in the self ID packet. */
-	u8 max_speed : 2; /* Minimum of all phy-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_node *ports[0];
-};
-
-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);
-}
-
-struct fw_card;
-void fw_destroy_nodes(struct fw_card *card);
-
-int fw_compute_block_crc(u32 *block);
-
-#endif /* __fw_topology_h */
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-transaction.c linux-libre-2.6.31-gnu/drivers/firewire/fw-transaction.c
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-transaction.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-transaction.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,970 +0,0 @@
-/*
- * 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/completion.h>
-#include <linux/idr.h>
-#include <linux/kernel.h>
-#include <linux/kref.h>
-#include <linux/module.h>
-#include <linux/mutex.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 "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 HEADER_DESTINATION_IS_BROADCAST(q) \
-	(((q) & HEADER_DESTINATION(0x3f)) == HEADER_DESTINATION(0x3f))
-
-#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)
-{
-	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, NULL, 0, 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);
-}
-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);
-		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);
-		break;
-	case ACK_DATA_ERROR:
-		close_transaction(t, card, RCODE_DATA_ERROR);
-		break;
-	case ACK_TYPE_ERROR:
-		close_transaction(t, card, RCODE_TYPE_ERROR);
-		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);
-		break;
-	}
-}
-
-static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
-		int destination_id, int source_id, int generation, int speed,
-		unsigned long long offset, void *payload, size_t length)
-{
-	int ext_tcode;
-
-	if (tcode == TCODE_STREAM_DATA) {
-		packet->header[0] =
-			HEADER_DATA_LENGTH(length) |
-			destination_id |
-			HEADER_TCODE(TCODE_STREAM_DATA);
-		packet->header_length = 4;
-		packet->payload = payload;
-		packet->payload_length = length;
-
-		goto common;
-	}
-
-	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(destination_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;
-	}
- common:
-	packet->speed = speed;
-	packet->generation = generation;
-	packet->ack = 0;
-	packet->payload_bus = 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, instead 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
- *
- * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller
- * needs to synthesize @destination_id with fw_stream_packet_destination_id().
- */
-void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
-		     int destination_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;
-
-	/*
-	 * 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);
-
-	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);
-
-	t->node_id = destination_id;
-	t->tlabel = tlabel;
-	t->callback = callback;
-	t->callback_data = callback_data;
-
-	fw_fill_request(&t->packet, tcode, t->tlabel,
-			destination_id, card->node_id, generation,
-			speed, offset, payload, length);
-	t->packet.callback = transmit_complete_callback;
-
-	list_add_tail(&t->link, &card->transaction_list);
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	card->driver->send_request(card, &t->packet);
-}
-EXPORT_SYMBOL(fw_send_request);
-
-struct transaction_callback_data {
-	struct completion done;
-	void *payload;
-	int rcode;
-};
-
-static void transaction_callback(struct fw_card *card, int rcode,
-				 void *payload, size_t length, void *data)
-{
-	struct transaction_callback_data *d = data;
-
-	if (rcode == RCODE_COMPLETE)
-		memcpy(d->payload, payload, length);
-	d->rcode = rcode;
-	complete(&d->done);
-}
-
-/**
- * fw_run_transaction - send request and sleep until transaction is completed
- *
- * Returns the RCODE.
- */
-int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
-		       int generation, int speed, unsigned long long offset,
-		       void *payload, size_t length)
-{
-	struct transaction_callback_data d;
-	struct fw_transaction t;
-
-	init_completion(&d.done);
-	d.payload = payload;
-	fw_send_request(card, &t, tcode, destination_id, generation, speed,
-			offset, payload, length, transaction_callback, &d);
-	wait_for_completion(&d.done);
-
-	return d.rcode;
-}
-EXPORT_SYMBOL(fw_run_transaction);
-
-static DEFINE_MUTEX(phy_config_mutex);
-static DECLARE_COMPLETION(phy_config_done);
-
-static void transmit_phy_packet_callback(struct fw_packet *packet,
-					 struct fw_card *card, int status)
-{
-	complete(&phy_config_done);
-}
-
-static struct fw_packet phy_config_packet = {
-	.header_length	= 8,
-	.payload_length	= 0,
-	.speed		= SCODE_100,
-	.callback	= transmit_phy_packet_callback,
-};
-
-void fw_send_phy_config(struct fw_card *card,
-			int node_id, int generation, int gap_count)
-{
-	long timeout = DIV_ROUND_UP(HZ, 10);
-	u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
-		   PHY_CONFIG_ROOT_ID(node_id) |
-		   PHY_CONFIG_GAP_COUNT(gap_count);
-
-	mutex_lock(&phy_config_mutex);
-
-	phy_config_packet.header[0] = data;
-	phy_config_packet.header[1] = ~data;
-	phy_config_packet.generation = generation;
-	INIT_COMPLETION(phy_config_done);
-
-	card->driver->send_request(card, &phy_config_packet);
-	wait_for_completion_timeout(&phy_config_done, timeout);
-
-	mutex_unlock(&phy_config_mutex);
-}
-
-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_high_memory_region =
-	{ .start = 0x000100000000ULL, .end = 0xffffe0000000ULL,  };
-EXPORT_SYMBOL(fw_high_memory_region);
-
-#if 0
-const struct fw_address_region fw_low_memory_region =
-	{ .start = 0x000000000000ULL, .end = 0x000100000000ULL,  };
-const struct fw_address_region fw_private_region =
-	{ .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL,  };
-const struct fw_address_region fw_csr_region =
-	{ .start = CSR_REGISTER_BASE,
-	  .end   = CSR_REGISTER_BASE | CSR_CONFIG_ROM_END,  };
-const struct fw_address_region fw_unit_space_region =
-	{ .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
-#endif  /*  0  */
-
-/**
- * fw_core_add_address_handler - register for incoming requests
- * @handler: callback
- * @region: region in the IEEE 1212 node space address range
- *
- * region->start, ->end, and handler->length have to be quadlet-aligned.
- *
- * 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.
- *
- * Return value:  0 on success, non-zero otherwise.
- * The start offset of the handler's address region is determined by
- * fw_core_add_address_handler() and is returned in handler->offset.
- */
-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;
-
-	if (region->start & 0xffff000000000003ULL ||
-	    region->end   & 0xffff000000000003ULL ||
-	    region->start >= region->end ||
-	    handler->length & 3 ||
-	    handler->length == 0)
-		return -EINVAL;
-
-	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);
-
-/**
- * fw_core_remove_address_handler - unregister an address handler
- */
-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;
-	}
-
-	response->payload_bus = 0;
-}
-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:
-		fw_error("ERROR - corrupt request received - %08x %08x %08x\n",
-			 p->header[0], p->header[1], p->header[2]);
-		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)
-{
-	/* unified transaction or broadcast transaction: don't respond */
-	if (request->ack != ACK_PENDING ||
-	    HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) {
-		kfree(request);
-		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->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[1]);
-
-	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;
-	}
-
-	/*
-	 * The response handler may be executed while the request handler
-	 * is still pending.  Cancel the request handler.
-	 */
-	card->driver->cancel_packet(card, &t->packet);
-
-	t->callback(card, rcode, data, data_length, t->callback_data);
-}
-EXPORT_SYMBOL(fw_core_handle_response);
-
-static const struct fw_address_region topology_map_region =
-	{ .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP,
-	  .end   = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, };
-
-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;
-	__be32 *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,
-};
-
-static const struct fw_address_region registers_region =
-	{ .start = CSR_REGISTER_BASE,
-	  .end   = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
-
-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;
-	int rcode = RCODE_COMPLETE;
-
-	switch (reg) {
-	case CSR_CYCLE_TIME:
-	case CSR_BUS_TIME:
-		if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) {
-			rcode = 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);
-		break;
-
-	case CSR_BROADCAST_CHANNEL:
-		if (tcode == TCODE_READ_QUADLET_REQUEST)
-			*data = cpu_to_be32(card->broadcast_channel);
-		else if (tcode == TCODE_WRITE_QUADLET_REQUEST)
-			card->broadcast_channel =
-			    (be32_to_cpu(*data) & BROADCAST_CHANNEL_VALID) |
-			    BROADCAST_CHANNEL_INITIAL;
-		else
-			rcode = RCODE_TYPE_ERROR;
-		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:
-		rcode = RCODE_ADDRESS_ERROR;
-		break;
-	}
-
-	fw_send_response(card, request, rcode);
-}
-
-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 ret;
-
-	ret = bus_register(&fw_bus_type);
-	if (ret < 0)
-		return ret;
-
-	fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops);
-	if (fw_cdev_major < 0) {
-		bus_unregister(&fw_bus_type);
-		return fw_cdev_major;
-	}
-
-	fw_core_add_address_handler(&topology_map, &topology_map_region);
-	fw_core_add_address_handler(&registers, &registers_region);
-	fw_core_add_descriptor(&vendor_id_descriptor);
-	fw_core_add_descriptor(&model_id_descriptor);
-
-	return 0;
-}
-
-static void __exit fw_core_cleanup(void)
-{
-	unregister_chrdev(fw_cdev_major, "firewire");
-	bus_unregister(&fw_bus_type);
-	idr_destroy(&fw_device_idr);
-}
-
-module_init(fw_core_init);
-module_exit(fw_core_cleanup);
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/fw-transaction.h linux-libre-2.6.31-gnu/drivers/firewire/fw-transaction.h
--- linux-libre-2.6.30-gnu/drivers/firewire/fw-transaction.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/fw-transaction.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,446 +0,0 @@
-/*
- * 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/completion.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/firewire-constants.h>
-#include <linux/kref.h>
-#include <linux/list.h>
-#include <linux/spinlock_types.h>
-#include <linux/timer.h>
-#include <linux/types.h>
-#include <linux/workqueue.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 BANDWIDTH_AVAILABLE_INITIAL	4915
-#define BROADCAST_CHANNEL_INITIAL	(1 << 31 | 31)
-#define BROADCAST_CHANNEL_VALID		(1 << 30)
-
-#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
-#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-
-static inline void fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
-{
-	u32    *dst = _dst;
-	__be32 *src = _src;
-	int i;
-
-	for (i = 0; i < size / 4; i++)
-		dst[i] = be32_to_cpu(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);
-
-/*
- * Important note:  The callback must guarantee that either fw_send_response()
- * or kfree() is called on the @request.
- */
-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);
-
-struct fw_packet {
-	int speed;
-	int generation;
-	u32 header[4];
-	size_t header_length;
-	void *payload;
-	size_t payload_length;
-	dma_addr_t payload_bus;
-	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;
-};
-
-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_high_memory_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;
-	struct completion done;
-
-	int node_id;
-	int generation;
-	int current_tlabel, tlabel_mask;
-	struct list_head transaction_list;
-	struct timer_list flush_timer;
-	unsigned long reset_jiffies;
-
-	unsigned long long guid;
-	unsigned max_receive;
-	int link_speed;
-	int config_rom_generation;
-
-	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;
-	u8 color; /* must be u8 to match the definition in struct fw_node */
-	int gap_count;
-	bool beta_repeaters_present;
-
-	int index;
-
-	struct list_head link;
-
-	/* Work struct for BM duties. */
-	struct delayed_work work;
-	int bm_retries;
-	int bm_generation;
-
-	bool broadcast_channel_allocated;
-	u32 broadcast_channel;
-	u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];
-};
-
-static inline struct fw_card *fw_card_get(struct fw_card *card)
-{
-	kref_get(&card->kref);
-
-	return card;
-}
-
-void fw_card_release(struct kref *kref);
-
-static inline void fw_card_put(struct fw_card *card)
-{
-	kref_put(&card->kref, fw_card_release);
-}
-
-extern void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
-
-/*
- * Check whether new_generation is the immediate successor of old_generation.
- * Take counter roll-over at 255 (as per to OHCI) into account.
- */
-static inline bool is_next_generation(int new_generation, int old_generation)
-{
-	return (new_generation & 0xff) == ((old_generation + 1) & 0xff);
-}
-
-/*
- * 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);
-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);
-void fw_iso_context_destroy(struct fw_iso_context *ctx);
-
-void fw_iso_resource_manage(struct fw_card *card, int generation,
-		u64 channels_mask, int *channel, int *bandwidth, bool allocate);
-
-struct fw_card_driver {
-	/*
-	 * 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, int channel, 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 destination_id, int generation, int speed,
-		unsigned long long offset, void *payload, 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);
-int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
-		       int generation, int speed, unsigned long long offset,
-		       void *payload, size_t length);
-void fw_send_phy_config(struct fw_card *card,
-			int node_id, int generation, int gap_count);
-
-static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
-{
-	return tag << 14 | channel << 8 | sy;
-}
-
-/*
- * 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);
-
-extern int fw_irm_set_broadcast_channel_register(struct device *dev,
-						 void *data);
-
-#endif /* __fw_transaction_h */
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/Kconfig linux-libre-2.6.31-gnu/drivers/firewire/Kconfig
--- linux-libre-2.6.30-gnu/drivers/firewire/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,28 +1,29 @@
-comment "A new alternative FireWire stack is available with EXPERIMENTAL=y"
-	depends on EXPERIMENTAL=n
-
-comment "Enable only one of the two stacks, unless you know what you are doing"
-	depends on EXPERIMENTAL
+comment "You can enable one or both FireWire driver stacks."
+comment "See the help texts for more information."
 
 config FIREWIRE
-	tristate "New FireWire stack, EXPERIMENTAL"
-	depends on EXPERIMENTAL
+	tristate "FireWire driver stack"
 	select CRC_ITU_T
 	help
-	  This is the "Juju" FireWire stack, a new alternative implementation
-	  designed for robustness and simplicity.  You can build either this
-	  stack, or the old stack (the ieee1394 driver, ohci1394 etc.) or both.
-	  Please read http://ieee1394.wiki.kernel.org/index.php/Juju_Migration
-	  before you enable the new stack.
+	  This is the new-generation IEEE 1394 (FireWire) driver stack
+	  a.k.a. Juju, a new implementation designed for robustness and
+	  simplicity.
+	  See http://ieee1394.wiki.kernel.org/index.php/Juju_Migration
+	  for information about migration from the older Linux 1394 stack
+	  to the new driver stack.
 
 	  To compile this driver as a module, say M here: the module will be
 	  called firewire-core.
 
 	  This module functionally replaces ieee1394, raw1394, and video1394.
 	  To access it from application programs, you generally need at least
-	  libraw1394 version 2.  IIDC/DCAM applications also need libdc1394
-	  version 2.  No libraries are required to access storage devices
-	  through the firewire-sbp2 driver.
+	  libraw1394 v2.  IIDC/DCAM applications need libdc1394 v2.
+	  No libraries are required to access storage devices through the
+	  firewire-sbp2 driver.
+
+	  NOTE:
+	  FireWire audio devices currently require the old drivers (ieee1394,
+	  ohci1394, raw1394).
 
 config FIREWIRE_OHCI
 	tristate "OHCI-1394 controllers"
@@ -37,11 +38,9 @@
 	  stack.
 
 	  NOTE:
-
-	  You should only build either firewire-ohci or the old ohci1394 driver,
-	  but not both.  If you nevertheless want to install both, you should
-	  configure them only as modules and blacklist the driver(s) which you
-	  don't want to have auto-loaded.  Add either
+	  If you want to install firewire-ohci and ohci1394 together, you
+	  should configure them only as modules and blacklist the driver(s)
+	  which you don't want to have auto-loaded.  Add either
 
 	      blacklist firewire-ohci
 	  or
@@ -50,12 +49,7 @@
 	      blacklist dv1394
 
 	  to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf
-	  depending on your distribution.  The latter two modules should be
-	  blacklisted together with ohci1394 because they depend on ohci1394.
-
-	  If you have an old modprobe which doesn't implement the blacklist
-	  directive, use "install modulename /bin/true" for the modules to be
-	  blacklisted.
+	  depending on your distribution.
 
 config FIREWIRE_OHCI_DEBUG
 	bool
@@ -77,3 +71,17 @@
 
 	  You should also enable support for disks, CD-ROMs, etc. in the SCSI
 	  configuration section.
+
+config FIREWIRE_NET
+	tristate "IP networking over 1394 (EXPERIMENTAL)"
+	depends on FIREWIRE && INET && EXPERIMENTAL
+	help
+	  This enables IPv4 over IEEE 1394, providing IP connectivity with
+	  other implementations of RFC 2734 as found on several operating
+	  systems.  Multicast support is currently limited.
+
+	  NOTE, this driver is not stable yet!
+
+	  To compile this driver as a module, say M here:  The module will be
+	  called firewire-net.  It replaces eth1394 of the classic IEEE 1394
+	  stack.
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/Makefile linux-libre-2.6.31-gnu/drivers/firewire/Makefile
--- linux-libre-2.6.30-gnu/drivers/firewire/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firewire/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,11 +2,13 @@
 # Makefile for the Linux IEEE 1394 implementation
 #
 
-firewire-core-y += fw-card.o fw-topology.o fw-transaction.o fw-iso.o \
-                   fw-device.o fw-cdev.o
-firewire-ohci-y += fw-ohci.o
-firewire-sbp2-y += fw-sbp2.o
+firewire-core-y += core-card.o core-cdev.o core-device.o \
+                   core-iso.o core-topology.o core-transaction.o
+firewire-ohci-y += ohci.o
+firewire-sbp2-y += sbp2.o
+firewire-net-y  += net.o
 
-obj-$(CONFIG_FIREWIRE) += firewire-core.o
+obj-$(CONFIG_FIREWIRE)      += firewire-core.o
 obj-$(CONFIG_FIREWIRE_OHCI) += firewire-ohci.o
 obj-$(CONFIG_FIREWIRE_SBP2) += firewire-sbp2.o
+obj-$(CONFIG_FIREWIRE_NET)  += firewire-net.o
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/net.c linux-libre-2.6.31-gnu/drivers/firewire/net.c
--- linux-libre-2.6.30-gnu/drivers/firewire/net.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/net.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1655 @@
+/*
+ * IPv4 over IEEE 1394, per RFC 2734
+ *
+ * Copyright (C) 2009 Jay Fenlason <fenlason@redhat.com>
+ *
+ * based on eth1394 by Ben Collins et al
+ */
+
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/highmem.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/jiffies.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/unaligned.h>
+#include <net/arp.h>
+
+#define FWNET_MAX_FRAGMENTS	25	/* arbitrary limit */
+#define FWNET_ISO_PAGE_COUNT	(PAGE_SIZE < 16 * 1024 ? 4 : 2)
+
+#define IEEE1394_BROADCAST_CHANNEL	31
+#define IEEE1394_ALL_NODES		(0xffc0 | 0x003f)
+#define IEEE1394_MAX_PAYLOAD_S100	512
+#define FWNET_NO_FIFO_ADDR		(~0ULL)
+
+#define IANA_SPECIFIER_ID		0x00005eU
+#define RFC2734_SW_VERSION		0x000001U
+
+#define IEEE1394_GASP_HDR_SIZE	8
+
+#define RFC2374_UNFRAG_HDR_SIZE	4
+#define RFC2374_FRAG_HDR_SIZE	8
+#define RFC2374_FRAG_OVERHEAD	4
+
+#define RFC2374_HDR_UNFRAG	0	/* unfragmented		*/
+#define RFC2374_HDR_FIRSTFRAG	1	/* first fragment	*/
+#define RFC2374_HDR_LASTFRAG	2	/* last fragment	*/
+#define RFC2374_HDR_INTFRAG	3	/* interior fragment	*/
+
+#define RFC2734_HW_ADDR_LEN	16
+
+struct rfc2734_arp {
+	__be16 hw_type;		/* 0x0018	*/
+	__be16 proto_type;	/* 0x0806       */
+	u8 hw_addr_len;		/* 16		*/
+	u8 ip_addr_len;		/* 4		*/
+	__be16 opcode;		/* ARP Opcode	*/
+	/* Above is exactly the same format as struct arphdr */
+
+	__be64 s_uniq_id;	/* Sender's 64bit EUI			*/
+	u8 max_rec;		/* Sender's max packet size		*/
+	u8 sspd;		/* Sender's max speed			*/
+	__be16 fifo_hi;		/* hi 16bits of sender's FIFO addr	*/
+	__be32 fifo_lo;		/* lo 32bits of sender's FIFO addr	*/
+	__be32 sip;		/* Sender's IP Address			*/
+	__be32 tip;		/* IP Address of requested hw addr	*/
+} __attribute__((packed));
+
+/* This header format is specific to this driver implementation. */
+#define FWNET_ALEN	8
+#define FWNET_HLEN	10
+struct fwnet_header {
+	u8 h_dest[FWNET_ALEN];	/* destination address */
+	__be16 h_proto;		/* packet type ID field */
+} __attribute__((packed));
+
+/* IPv4 and IPv6 encapsulation header */
+struct rfc2734_header {
+	u32 w0;
+	u32 w1;
+};
+
+#define fwnet_get_hdr_lf(h)		(((h)->w0 & 0xc0000000) >> 30)
+#define fwnet_get_hdr_ether_type(h)	(((h)->w0 & 0x0000ffff))
+#define fwnet_get_hdr_dg_size(h)	(((h)->w0 & 0x0fff0000) >> 16)
+#define fwnet_get_hdr_fg_off(h)		(((h)->w0 & 0x00000fff))
+#define fwnet_get_hdr_dgl(h)		(((h)->w1 & 0xffff0000) >> 16)
+
+#define fwnet_set_hdr_lf(lf)		((lf)  << 30)
+#define fwnet_set_hdr_ether_type(et)	(et)
+#define fwnet_set_hdr_dg_size(dgs)	((dgs) << 16)
+#define fwnet_set_hdr_fg_off(fgo)	(fgo)
+
+#define fwnet_set_hdr_dgl(dgl)		((dgl) << 16)
+
+static inline void fwnet_make_uf_hdr(struct rfc2734_header *hdr,
+		unsigned ether_type)
+{
+	hdr->w0 = fwnet_set_hdr_lf(RFC2374_HDR_UNFRAG)
+		  | fwnet_set_hdr_ether_type(ether_type);
+}
+
+static inline void fwnet_make_ff_hdr(struct rfc2734_header *hdr,
+		unsigned ether_type, unsigned dg_size, unsigned dgl)
+{
+	hdr->w0 = fwnet_set_hdr_lf(RFC2374_HDR_FIRSTFRAG)
+		  | fwnet_set_hdr_dg_size(dg_size)
+		  | fwnet_set_hdr_ether_type(ether_type);
+	hdr->w1 = fwnet_set_hdr_dgl(dgl);
+}
+
+static inline void fwnet_make_sf_hdr(struct rfc2734_header *hdr,
+		unsigned lf, unsigned dg_size, unsigned fg_off, unsigned dgl)
+{
+	hdr->w0 = fwnet_set_hdr_lf(lf)
+		  | fwnet_set_hdr_dg_size(dg_size)
+		  | fwnet_set_hdr_fg_off(fg_off);
+	hdr->w1 = fwnet_set_hdr_dgl(dgl);
+}
+
+/* This list keeps track of what parts of the datagram have been filled in */
+struct fwnet_fragment_info {
+	struct list_head fi_link;
+	u16 offset;
+	u16 len;
+};
+
+struct fwnet_partial_datagram {
+	struct list_head pd_link;
+	struct list_head fi_list;
+	struct sk_buff *skb;
+	/* FIXME Why not use skb->data? */
+	char *pbuf;
+	u16 datagram_label;
+	u16 ether_type;
+	u16 datagram_size;
+};
+
+static DEFINE_MUTEX(fwnet_device_mutex);
+static LIST_HEAD(fwnet_device_list);
+
+struct fwnet_device {
+	struct list_head dev_link;
+	spinlock_t lock;
+	enum {
+		FWNET_BROADCAST_ERROR,
+		FWNET_BROADCAST_RUNNING,
+		FWNET_BROADCAST_STOPPED,
+	} broadcast_state;
+	struct fw_iso_context *broadcast_rcv_context;
+	struct fw_iso_buffer broadcast_rcv_buffer;
+	void **broadcast_rcv_buffer_ptrs;
+	unsigned broadcast_rcv_next_ptr;
+	unsigned num_broadcast_rcv_ptrs;
+	unsigned rcv_buffer_size;
+	/*
+	 * This value is the maximum unfragmented datagram size that can be
+	 * sent by the hardware.  It already has the GASP overhead and the
+	 * unfragmented datagram header overhead calculated into it.
+	 */
+	unsigned broadcast_xmt_max_payload;
+	u16 broadcast_xmt_datagramlabel;
+
+	/*
+	 * The CSR address that remote nodes must send datagrams to for us to
+	 * receive them.
+	 */
+	struct fw_address_handler handler;
+	u64 local_fifo;
+
+	/* List of packets to be sent */
+	struct list_head packet_list;
+	/*
+	 * List of packets that were broadcasted.  When we get an ISO interrupt
+	 * one of them has been sent
+	 */
+	struct list_head broadcasted_list;
+	/* List of packets that have been sent but not yet acked */
+	struct list_head sent_list;
+
+	struct list_head peer_list;
+	struct fw_card *card;
+	struct net_device *netdev;
+};
+
+struct fwnet_peer {
+	struct list_head peer_link;
+	struct fwnet_device *dev;
+	u64 guid;
+	u64 fifo;
+
+	/* guarded by dev->lock */
+	struct list_head pd_list; /* received partial datagrams */
+	unsigned pdg_size;        /* pd_list size */
+
+	u16 datagram_label;       /* outgoing datagram label */
+	unsigned max_payload;     /* includes RFC2374_FRAG_HDR_SIZE overhead */
+	int node_id;
+	int generation;
+	unsigned speed;
+};
+
+/* This is our task struct. It's used for the packet complete callback.  */
+struct fwnet_packet_task {
+	/*
+	 * ptask can actually be on dev->packet_list, dev->broadcasted_list,
+	 * or dev->sent_list depending on its current state.
+	 */
+	struct list_head pt_link;
+	struct fw_transaction transaction;
+	struct rfc2734_header hdr;
+	struct sk_buff *skb;
+	struct fwnet_device *dev;
+
+	int outstanding_pkts;
+	unsigned max_payload;
+	u64 fifo_addr;
+	u16 dest_node;
+	u8 generation;
+	u8 speed;
+};
+
+/*
+ * saddr == NULL means use device source address.
+ * daddr == NULL means leave destination address (eg unresolved arp).
+ */
+static int fwnet_header_create(struct sk_buff *skb, struct net_device *net,
+			unsigned short type, const void *daddr,
+			const void *saddr, unsigned len)
+{
+	struct fwnet_header *h;
+
+	h = (struct fwnet_header *)skb_push(skb, sizeof(*h));
+	put_unaligned_be16(type, &h->h_proto);
+
+	if (net->flags & (IFF_LOOPBACK | IFF_NOARP)) {
+		memset(h->h_dest, 0, net->addr_len);
+
+		return net->hard_header_len;
+	}
+
+	if (daddr) {
+		memcpy(h->h_dest, daddr, net->addr_len);
+
+		return net->hard_header_len;
+	}
+
+	return -net->hard_header_len;
+}
+
+static int fwnet_header_rebuild(struct sk_buff *skb)
+{
+	struct fwnet_header *h = (struct fwnet_header *)skb->data;
+
+	if (get_unaligned_be16(&h->h_proto) == ETH_P_IP)
+		return arp_find((unsigned char *)&h->h_dest, skb);
+
+	fw_notify("%s: unable to resolve type %04x addresses\n",
+		  skb->dev->name, be16_to_cpu(h->h_proto));
+	return 0;
+}
+
+static int fwnet_header_cache(const struct neighbour *neigh,
+			      struct hh_cache *hh)
+{
+	struct net_device *net;
+	struct fwnet_header *h;
+
+	if (hh->hh_type == cpu_to_be16(ETH_P_802_3))
+		return -1;
+	net = neigh->dev;
+	h = (struct fwnet_header *)((u8 *)hh->hh_data + 16 - sizeof(*h));
+	h->h_proto = hh->hh_type;
+	memcpy(h->h_dest, neigh->ha, net->addr_len);
+	hh->hh_len = FWNET_HLEN;
+
+	return 0;
+}
+
+/* Called by Address Resolution module to notify changes in address. */
+static void fwnet_header_cache_update(struct hh_cache *hh,
+		const struct net_device *net, const unsigned char *haddr)
+{
+	memcpy((u8 *)hh->hh_data + 16 - FWNET_HLEN, haddr, net->addr_len);
+}
+
+static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+{
+	memcpy(haddr, skb->dev->dev_addr, FWNET_ALEN);
+
+	return FWNET_ALEN;
+}
+
+static const struct header_ops fwnet_header_ops = {
+	.create         = fwnet_header_create,
+	.rebuild        = fwnet_header_rebuild,
+	.cache		= fwnet_header_cache,
+	.cache_update	= fwnet_header_cache_update,
+	.parse          = fwnet_header_parse,
+};
+
+/* FIXME: is this correct for all cases? */
+static bool fwnet_frag_overlap(struct fwnet_partial_datagram *pd,
+			       unsigned offset, unsigned len)
+{
+	struct fwnet_fragment_info *fi;
+	unsigned end = offset + len;
+
+	list_for_each_entry(fi, &pd->fi_list, fi_link)
+		if (offset < fi->offset + fi->len && end > fi->offset)
+			return true;
+
+	return false;
+}
+
+/* Assumes that new fragment does not overlap any existing fragments */
+static struct fwnet_fragment_info *fwnet_frag_new(
+	struct fwnet_partial_datagram *pd, unsigned offset, unsigned len)
+{
+	struct fwnet_fragment_info *fi, *fi2, *new;
+	struct list_head *list;
+
+	list = &pd->fi_list;
+	list_for_each_entry(fi, &pd->fi_list, fi_link) {
+		if (fi->offset + fi->len == offset) {
+			/* The new fragment can be tacked on to the end */
+			/* Did the new fragment plug a hole? */
+			fi2 = list_entry(fi->fi_link.next,
+					 struct fwnet_fragment_info, fi_link);
+			if (fi->offset + fi->len == fi2->offset) {
+				/* glue fragments together */
+				fi->len += len + fi2->len;
+				list_del(&fi2->fi_link);
+				kfree(fi2);
+			} else {
+				fi->len += len;
+			}
+
+			return fi;
+		}
+		if (offset + len == fi->offset) {
+			/* The new fragment can be tacked on to the beginning */
+			/* Did the new fragment plug a hole? */
+			fi2 = list_entry(fi->fi_link.prev,
+					 struct fwnet_fragment_info, fi_link);
+			if (fi2->offset + fi2->len == fi->offset) {
+				/* glue fragments together */
+				fi2->len += fi->len + len;
+				list_del(&fi->fi_link);
+				kfree(fi);
+
+				return fi2;
+			}
+			fi->offset = offset;
+			fi->len += len;
+
+			return fi;
+		}
+		if (offset > fi->offset + fi->len) {
+			list = &fi->fi_link;
+			break;
+		}
+		if (offset + len < fi->offset) {
+			list = fi->fi_link.prev;
+			break;
+		}
+	}
+
+	new = kmalloc(sizeof(*new), GFP_ATOMIC);
+	if (!new) {
+		fw_error("out of memory\n");
+		return NULL;
+	}
+
+	new->offset = offset;
+	new->len = len;
+	list_add(&new->fi_link, list);
+
+	return new;
+}
+
+static struct fwnet_partial_datagram *fwnet_pd_new(struct net_device *net,
+		struct fwnet_peer *peer, u16 datagram_label, unsigned dg_size,
+		void *frag_buf, unsigned frag_off, unsigned frag_len)
+{
+	struct fwnet_partial_datagram *new;
+	struct fwnet_fragment_info *fi;
+
+	new = kmalloc(sizeof(*new), GFP_ATOMIC);
+	if (!new)
+		goto fail;
+
+	INIT_LIST_HEAD(&new->fi_list);
+	fi = fwnet_frag_new(new, frag_off, frag_len);
+	if (fi == NULL)
+		goto fail_w_new;
+
+	new->datagram_label = datagram_label;
+	new->datagram_size = dg_size;
+	new->skb = dev_alloc_skb(dg_size + net->hard_header_len + 15);
+	if (new->skb == NULL)
+		goto fail_w_fi;
+
+	skb_reserve(new->skb, (net->hard_header_len + 15) & ~15);
+	new->pbuf = skb_put(new->skb, dg_size);
+	memcpy(new->pbuf + frag_off, frag_buf, frag_len);
+	list_add_tail(&new->pd_link, &peer->pd_list);
+
+	return new;
+
+fail_w_fi:
+	kfree(fi);
+fail_w_new:
+	kfree(new);
+fail:
+	fw_error("out of memory\n");
+
+	return NULL;
+}
+
+static struct fwnet_partial_datagram *fwnet_pd_find(struct fwnet_peer *peer,
+						    u16 datagram_label)
+{
+	struct fwnet_partial_datagram *pd;
+
+	list_for_each_entry(pd, &peer->pd_list, pd_link)
+		if (pd->datagram_label == datagram_label)
+			return pd;
+
+	return NULL;
+}
+
+
+static void fwnet_pd_delete(struct fwnet_partial_datagram *old)
+{
+	struct fwnet_fragment_info *fi, *n;
+
+	list_for_each_entry_safe(fi, n, &old->fi_list, fi_link)
+		kfree(fi);
+
+	list_del(&old->pd_link);
+	dev_kfree_skb_any(old->skb);
+	kfree(old);
+}
+
+static bool fwnet_pd_update(struct fwnet_peer *peer,
+		struct fwnet_partial_datagram *pd, void *frag_buf,
+		unsigned frag_off, unsigned frag_len)
+{
+	if (fwnet_frag_new(pd, frag_off, frag_len) == NULL)
+		return false;
+
+	memcpy(pd->pbuf + frag_off, frag_buf, frag_len);
+
+	/*
+	 * Move list entry to beginnig of list so that oldest partial
+	 * datagrams percolate to the end of the list
+	 */
+	list_move_tail(&pd->pd_link, &peer->pd_list);
+
+	return true;
+}
+
+static bool fwnet_pd_is_complete(struct fwnet_partial_datagram *pd)
+{
+	struct fwnet_fragment_info *fi;
+
+	fi = list_entry(pd->fi_list.next, struct fwnet_fragment_info, fi_link);
+
+	return fi->len == pd->datagram_size;
+}
+
+/* caller must hold dev->lock */
+static struct fwnet_peer *fwnet_peer_find_by_guid(struct fwnet_device *dev,
+						  u64 guid)
+{
+	struct fwnet_peer *peer;
+
+	list_for_each_entry(peer, &dev->peer_list, peer_link)
+		if (peer->guid == guid)
+			return peer;
+
+	return NULL;
+}
+
+/* caller must hold dev->lock */
+static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev,
+						int node_id, int generation)
+{
+	struct fwnet_peer *peer;
+
+	list_for_each_entry(peer, &dev->peer_list, peer_link)
+		if (peer->node_id    == node_id &&
+		    peer->generation == generation)
+			return peer;
+
+	return NULL;
+}
+
+/* See IEEE 1394-2008 table 6-4, table 8-8, table 16-18. */
+static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed)
+{
+	max_rec = min(max_rec, speed + 8);
+	max_rec = min(max_rec, 0xbU); /* <= 4096 */
+	if (max_rec < 8) {
+		fw_notify("max_rec %x out of range\n", max_rec);
+		max_rec = 8;
+	}
+
+	return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE;
+}
+
+
+static int fwnet_finish_incoming_packet(struct net_device *net,
+					struct sk_buff *skb, u16 source_node_id,
+					bool is_broadcast, u16 ether_type)
+{
+	struct fwnet_device *dev;
+	static const __be64 broadcast_hw = cpu_to_be64(~0ULL);
+	int status;
+	__be64 guid;
+
+	dev = netdev_priv(net);
+	/* Write metadata, and then pass to the receive level */
+	skb->dev = net;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;  /* don't check it */
+
+	/*
+	 * Parse the encapsulation header. This actually does the job of
+	 * converting to an ethernet frame header, as well as arp
+	 * conversion if needed. ARP conversion is easier in this
+	 * direction, since we are using ethernet as our backend.
+	 */
+	/*
+	 * If this is an ARP packet, convert it. First, we want to make
+	 * use of some of the fields, since they tell us a little bit
+	 * about the sending machine.
+	 */
+	if (ether_type == ETH_P_ARP) {
+		struct rfc2734_arp *arp1394;
+		struct arphdr *arp;
+		unsigned char *arp_ptr;
+		u64 fifo_addr;
+		u64 peer_guid;
+		unsigned sspd;
+		u16 max_payload;
+		struct fwnet_peer *peer;
+		unsigned long flags;
+
+		arp1394   = (struct rfc2734_arp *)skb->data;
+		arp       = (struct arphdr *)skb->data;
+		arp_ptr   = (unsigned char *)(arp + 1);
+		peer_guid = get_unaligned_be64(&arp1394->s_uniq_id);
+		fifo_addr = (u64)get_unaligned_be16(&arp1394->fifo_hi) << 32
+				| get_unaligned_be32(&arp1394->fifo_lo);
+
+		sspd = arp1394->sspd;
+		/* Sanity check.  OS X 10.3 PPC reportedly sends 131. */
+		if (sspd > SCODE_3200) {
+			fw_notify("sspd %x out of range\n", sspd);
+			sspd = SCODE_3200;
+		}
+		max_payload = fwnet_max_payload(arp1394->max_rec, sspd);
+
+		spin_lock_irqsave(&dev->lock, flags);
+		peer = fwnet_peer_find_by_guid(dev, peer_guid);
+		if (peer) {
+			peer->fifo = fifo_addr;
+
+			if (peer->speed > sspd)
+				peer->speed = sspd;
+			if (peer->max_payload > max_payload)
+				peer->max_payload = max_payload;
+		}
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		if (!peer) {
+			fw_notify("No peer for ARP packet from %016llx\n",
+				  (unsigned long long)peer_guid);
+			goto failed_proto;
+		}
+
+		/*
+		 * Now that we're done with the 1394 specific stuff, we'll
+		 * need to alter some of the data.  Believe it or not, all
+		 * that needs to be done is sender_IP_address needs to be
+		 * moved, the destination hardware address get stuffed
+		 * in and the hardware address length set to 8.
+		 *
+		 * IMPORTANT: The code below overwrites 1394 specific data
+		 * needed above so keep the munging of the data for the
+		 * higher level IP stack last.
+		 */
+
+		arp->ar_hln = 8;
+		/* skip over sender unique id */
+		arp_ptr += arp->ar_hln;
+		/* move sender IP addr */
+		put_unaligned(arp1394->sip, (u32 *)arp_ptr);
+		/* skip over sender IP addr */
+		arp_ptr += arp->ar_pln;
+
+		if (arp->ar_op == htons(ARPOP_REQUEST))
+			memset(arp_ptr, 0, sizeof(u64));
+		else
+			memcpy(arp_ptr, net->dev_addr, sizeof(u64));
+	}
+
+	/* Now add the ethernet header. */
+	guid = cpu_to_be64(dev->card->guid);
+	if (dev_hard_header(skb, net, ether_type,
+			   is_broadcast ? &broadcast_hw : &guid,
+			   NULL, skb->len) >= 0) {
+		struct fwnet_header *eth;
+		u16 *rawp;
+		__be16 protocol;
+
+		skb_reset_mac_header(skb);
+		skb_pull(skb, sizeof(*eth));
+		eth = (struct fwnet_header *)skb_mac_header(skb);
+		if (*eth->h_dest & 1) {
+			if (memcmp(eth->h_dest, net->broadcast,
+				   net->addr_len) == 0)
+				skb->pkt_type = PACKET_BROADCAST;
+#if 0
+			else
+				skb->pkt_type = PACKET_MULTICAST;
+#endif
+		} else {
+			if (memcmp(eth->h_dest, net->dev_addr, net->addr_len))
+				skb->pkt_type = PACKET_OTHERHOST;
+		}
+		if (ntohs(eth->h_proto) >= 1536) {
+			protocol = eth->h_proto;
+		} else {
+			rawp = (u16 *)skb->data;
+			if (*rawp == 0xffff)
+				protocol = htons(ETH_P_802_3);
+			else
+				protocol = htons(ETH_P_802_2);
+		}
+		skb->protocol = protocol;
+	}
+	status = netif_rx(skb);
+	if (status == NET_RX_DROP) {
+		net->stats.rx_errors++;
+		net->stats.rx_dropped++;
+	} else {
+		net->stats.rx_packets++;
+		net->stats.rx_bytes += skb->len;
+	}
+	if (netif_queue_stopped(net))
+		netif_wake_queue(net);
+
+	return 0;
+
+ failed_proto:
+	net->stats.rx_errors++;
+	net->stats.rx_dropped++;
+
+	dev_kfree_skb_any(skb);
+	if (netif_queue_stopped(net))
+		netif_wake_queue(net);
+
+	net->last_rx = jiffies;
+
+	return 0;
+}
+
+static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
+				 int source_node_id, int generation,
+				 bool is_broadcast)
+{
+	struct sk_buff *skb;
+	struct net_device *net = dev->netdev;
+	struct rfc2734_header hdr;
+	unsigned lf;
+	unsigned long flags;
+	struct fwnet_peer *peer;
+	struct fwnet_partial_datagram *pd;
+	int fg_off;
+	int dg_size;
+	u16 datagram_label;
+	int retval;
+	u16 ether_type;
+
+	hdr.w0 = be32_to_cpu(buf[0]);
+	lf = fwnet_get_hdr_lf(&hdr);
+	if (lf == RFC2374_HDR_UNFRAG) {
+		/*
+		 * An unfragmented datagram has been received by the ieee1394
+		 * bus. Build an skbuff around it so we can pass it to the
+		 * high level network layer.
+		 */
+		ether_type = fwnet_get_hdr_ether_type(&hdr);
+		buf++;
+		len -= RFC2374_UNFRAG_HDR_SIZE;
+
+		skb = dev_alloc_skb(len + net->hard_header_len + 15);
+		if (unlikely(!skb)) {
+			fw_error("out of memory\n");
+			net->stats.rx_dropped++;
+
+			return -1;
+		}
+		skb_reserve(skb, (net->hard_header_len + 15) & ~15);
+		memcpy(skb_put(skb, len), buf, len);
+
+		return fwnet_finish_incoming_packet(net, skb, source_node_id,
+						    is_broadcast, ether_type);
+	}
+	/* A datagram fragment has been received, now the fun begins. */
+	hdr.w1 = ntohl(buf[1]);
+	buf += 2;
+	len -= RFC2374_FRAG_HDR_SIZE;
+	if (lf == RFC2374_HDR_FIRSTFRAG) {
+		ether_type = fwnet_get_hdr_ether_type(&hdr);
+		fg_off = 0;
+	} else {
+		ether_type = 0;
+		fg_off = fwnet_get_hdr_fg_off(&hdr);
+	}
+	datagram_label = fwnet_get_hdr_dgl(&hdr);
+	dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
+	if (!peer)
+		goto bad_proto;
+
+	pd = fwnet_pd_find(peer, datagram_label);
+	if (pd == NULL) {
+		while (peer->pdg_size >= FWNET_MAX_FRAGMENTS) {
+			/* remove the oldest */
+			fwnet_pd_delete(list_first_entry(&peer->pd_list,
+				struct fwnet_partial_datagram, pd_link));
+			peer->pdg_size--;
+		}
+		pd = fwnet_pd_new(net, peer, datagram_label,
+				  dg_size, buf, fg_off, len);
+		if (pd == NULL) {
+			retval = -ENOMEM;
+			goto bad_proto;
+		}
+		peer->pdg_size++;
+	} else {
+		if (fwnet_frag_overlap(pd, fg_off, len) ||
+		    pd->datagram_size != dg_size) {
+			/*
+			 * Differing datagram sizes or overlapping fragments,
+			 * discard old datagram and start a new one.
+			 */
+			fwnet_pd_delete(pd);
+			pd = fwnet_pd_new(net, peer, datagram_label,
+					  dg_size, buf, fg_off, len);
+			if (pd == NULL) {
+				retval = -ENOMEM;
+				peer->pdg_size--;
+				goto bad_proto;
+			}
+		} else {
+			if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) {
+				/*
+				 * Couldn't save off fragment anyway
+				 * so might as well obliterate the
+				 * datagram now.
+				 */
+				fwnet_pd_delete(pd);
+				peer->pdg_size--;
+				goto bad_proto;
+			}
+		}
+	} /* new datagram or add to existing one */
+
+	if (lf == RFC2374_HDR_FIRSTFRAG)
+		pd->ether_type = ether_type;
+
+	if (fwnet_pd_is_complete(pd)) {
+		ether_type = pd->ether_type;
+		peer->pdg_size--;
+		skb = skb_get(pd->skb);
+		fwnet_pd_delete(pd);
+
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		return fwnet_finish_incoming_packet(net, skb, source_node_id,
+						    false, ether_type);
+	}
+	/*
+	 * Datagram is not complete, we're done for the
+	 * moment.
+	 */
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+
+ bad_proto:
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (netif_queue_stopped(net))
+		netif_wake_queue(net);
+
+	return 0;
+}
+
+static void fwnet_receive_packet(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 fwnet_device *dev = callback_data;
+	int rcode;
+
+	if (destination == IEEE1394_ALL_NODES) {
+		kfree(r);
+
+		return;
+	}
+
+	if (offset != dev->handler.offset)
+		rcode = RCODE_ADDRESS_ERROR;
+	else if (tcode != TCODE_WRITE_BLOCK_REQUEST)
+		rcode = RCODE_TYPE_ERROR;
+	else if (fwnet_incoming_packet(dev, payload, length,
+				       source, generation, false) != 0) {
+		fw_error("Incoming packet failure\n");
+		rcode = RCODE_CONFLICT_ERROR;
+	} else
+		rcode = RCODE_COMPLETE;
+
+	fw_send_response(card, r, rcode);
+}
+
+static void fwnet_receive_broadcast(struct fw_iso_context *context,
+		u32 cycle, size_t header_length, void *header, void *data)
+{
+	struct fwnet_device *dev;
+	struct fw_iso_packet packet;
+	struct fw_card *card;
+	__be16 *hdr_ptr;
+	__be32 *buf_ptr;
+	int retval;
+	u32 length;
+	u16 source_node_id;
+	u32 specifier_id;
+	u32 ver;
+	unsigned long offset;
+	unsigned long flags;
+
+	dev = data;
+	card = dev->card;
+	hdr_ptr = header;
+	length = be16_to_cpup(hdr_ptr);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	offset = dev->rcv_buffer_size * dev->broadcast_rcv_next_ptr;
+	buf_ptr = dev->broadcast_rcv_buffer_ptrs[dev->broadcast_rcv_next_ptr++];
+	if (dev->broadcast_rcv_next_ptr == dev->num_broadcast_rcv_ptrs)
+		dev->broadcast_rcv_next_ptr = 0;
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	specifier_id =    (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8
+			| (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24;
+	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
+	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
+
+	if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) {
+		buf_ptr += 2;
+		length -= IEEE1394_GASP_HDR_SIZE;
+		fwnet_incoming_packet(dev, buf_ptr, length,
+				      source_node_id, -1, true);
+	}
+
+	packet.payload_length = dev->rcv_buffer_size;
+	packet.interrupt = 1;
+	packet.skip = 0;
+	packet.tag = 3;
+	packet.sy = 0;
+	packet.header_length = IEEE1394_GASP_HDR_SIZE;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	retval = fw_iso_context_queue(dev->broadcast_rcv_context, &packet,
+				      &dev->broadcast_rcv_buffer, offset);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (retval < 0)
+		fw_error("requeue failed\n");
+}
+
+static struct kmem_cache *fwnet_packet_task_cache;
+
+static int fwnet_send_packet(struct fwnet_packet_task *ptask);
+
+static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
+{
+	struct fwnet_device *dev;
+	unsigned long flags;
+
+	dev = ptask->dev;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	list_del(&ptask->pt_link);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	ptask->outstanding_pkts--; /* FIXME access inside lock */
+
+	if (ptask->outstanding_pkts > 0) {
+		u16 dg_size;
+		u16 fg_off;
+		u16 datagram_label;
+		u16 lf;
+		struct sk_buff *skb;
+
+		/* Update the ptask to point to the next fragment and send it */
+		lf = fwnet_get_hdr_lf(&ptask->hdr);
+		switch (lf) {
+		case RFC2374_HDR_LASTFRAG:
+		case RFC2374_HDR_UNFRAG:
+		default:
+			fw_error("Outstanding packet %x lf %x, header %x,%x\n",
+				 ptask->outstanding_pkts, lf, ptask->hdr.w0,
+				 ptask->hdr.w1);
+			BUG();
+
+		case RFC2374_HDR_FIRSTFRAG:
+			/* Set frag type here for future interior fragments */
+			dg_size = fwnet_get_hdr_dg_size(&ptask->hdr);
+			fg_off = ptask->max_payload - RFC2374_FRAG_HDR_SIZE;
+			datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
+			break;
+
+		case RFC2374_HDR_INTFRAG:
+			dg_size = fwnet_get_hdr_dg_size(&ptask->hdr);
+			fg_off = fwnet_get_hdr_fg_off(&ptask->hdr)
+				  + ptask->max_payload - RFC2374_FRAG_HDR_SIZE;
+			datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
+			break;
+		}
+		skb = ptask->skb;
+		skb_pull(skb, ptask->max_payload);
+		if (ptask->outstanding_pkts > 1) {
+			fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
+					  dg_size, fg_off, datagram_label);
+		} else {
+			fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_LASTFRAG,
+					  dg_size, fg_off, datagram_label);
+			ptask->max_payload = skb->len + RFC2374_FRAG_HDR_SIZE;
+		}
+		fwnet_send_packet(ptask);
+	} else {
+		dev_kfree_skb_any(ptask->skb);
+		kmem_cache_free(fwnet_packet_task_cache, ptask);
+	}
+}
+
+static void fwnet_write_complete(struct fw_card *card, int rcode,
+				 void *payload, size_t length, void *data)
+{
+	struct fwnet_packet_task *ptask;
+
+	ptask = data;
+
+	if (rcode == RCODE_COMPLETE)
+		fwnet_transmit_packet_done(ptask);
+	else
+		fw_error("fwnet_write_complete: failed: %x\n", rcode);
+		/* ??? error recovery */
+}
+
+static int fwnet_send_packet(struct fwnet_packet_task *ptask)
+{
+	struct fwnet_device *dev;
+	unsigned tx_len;
+	struct rfc2734_header *bufhdr;
+	unsigned long flags;
+
+	dev = ptask->dev;
+	tx_len = ptask->max_payload;
+	switch (fwnet_get_hdr_lf(&ptask->hdr)) {
+	case RFC2374_HDR_UNFRAG:
+		bufhdr = (struct rfc2734_header *)
+				skb_push(ptask->skb, RFC2374_UNFRAG_HDR_SIZE);
+		put_unaligned_be32(ptask->hdr.w0, &bufhdr->w0);
+		break;
+
+	case RFC2374_HDR_FIRSTFRAG:
+	case RFC2374_HDR_INTFRAG:
+	case RFC2374_HDR_LASTFRAG:
+		bufhdr = (struct rfc2734_header *)
+				skb_push(ptask->skb, RFC2374_FRAG_HDR_SIZE);
+		put_unaligned_be32(ptask->hdr.w0, &bufhdr->w0);
+		put_unaligned_be32(ptask->hdr.w1, &bufhdr->w1);
+		break;
+
+	default:
+		BUG();
+	}
+	if (ptask->dest_node == IEEE1394_ALL_NODES) {
+		u8 *p;
+		int generation;
+		int node_id;
+
+		/* ptask->generation may not have been set yet */
+		generation = dev->card->generation;
+		smp_rmb();
+		node_id = dev->card->node_id;
+
+		p = skb_push(ptask->skb, 8);
+		put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
+		put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
+						| RFC2734_SW_VERSION, &p[4]);
+
+		/* We should not transmit if broadcast_channel.valid == 0. */
+		fw_send_request(dev->card, &ptask->transaction,
+				TCODE_STREAM_DATA,
+				fw_stream_packet_destination_id(3,
+						IEEE1394_BROADCAST_CHANNEL, 0),
+				generation, SCODE_100, 0ULL, ptask->skb->data,
+				tx_len + 8, fwnet_write_complete, ptask);
+
+		/* FIXME race? */
+		spin_lock_irqsave(&dev->lock, flags);
+		list_add_tail(&ptask->pt_link, &dev->broadcasted_list);
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		return 0;
+	}
+
+	fw_send_request(dev->card, &ptask->transaction,
+			TCODE_WRITE_BLOCK_REQUEST, ptask->dest_node,
+			ptask->generation, ptask->speed, ptask->fifo_addr,
+			ptask->skb->data, tx_len, fwnet_write_complete, ptask);
+
+	/* FIXME race? */
+	spin_lock_irqsave(&dev->lock, flags);
+	list_add_tail(&ptask->pt_link, &dev->sent_list);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	dev->netdev->trans_start = jiffies;
+
+	return 0;
+}
+
+static int fwnet_broadcast_start(struct fwnet_device *dev)
+{
+	struct fw_iso_context *context;
+	int retval;
+	unsigned num_packets;
+	unsigned max_receive;
+	struct fw_iso_packet packet;
+	unsigned long offset;
+	unsigned u;
+
+	if (dev->local_fifo == FWNET_NO_FIFO_ADDR) {
+		/* outside OHCI posted write area? */
+		static const struct fw_address_region region = {
+			.start = 0xffff00000000ULL,
+			.end   = CSR_REGISTER_BASE,
+		};
+
+		dev->handler.length = 4096;
+		dev->handler.address_callback = fwnet_receive_packet;
+		dev->handler.callback_data = dev;
+
+		retval = fw_core_add_address_handler(&dev->handler, &region);
+		if (retval < 0)
+			goto failed_initial;
+
+		dev->local_fifo = dev->handler.offset;
+	}
+
+	max_receive = 1U << (dev->card->max_receive + 1);
+	num_packets = (FWNET_ISO_PAGE_COUNT * PAGE_SIZE) / max_receive;
+
+	if (!dev->broadcast_rcv_context) {
+		void **ptrptr;
+
+		context = fw_iso_context_create(dev->card,
+		    FW_ISO_CONTEXT_RECEIVE, IEEE1394_BROADCAST_CHANNEL,
+		    dev->card->link_speed, 8, fwnet_receive_broadcast, dev);
+		if (IS_ERR(context)) {
+			retval = PTR_ERR(context);
+			goto failed_context_create;
+		}
+
+		retval = fw_iso_buffer_init(&dev->broadcast_rcv_buffer,
+		    dev->card, FWNET_ISO_PAGE_COUNT, DMA_FROM_DEVICE);
+		if (retval < 0)
+			goto failed_buffer_init;
+
+		ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL);
+		if (!ptrptr) {
+			retval = -ENOMEM;
+			goto failed_ptrs_alloc;
+		}
+
+		dev->broadcast_rcv_buffer_ptrs = ptrptr;
+		for (u = 0; u < FWNET_ISO_PAGE_COUNT; u++) {
+			void *ptr;
+			unsigned v;
+
+			ptr = kmap(dev->broadcast_rcv_buffer.pages[u]);
+			for (v = 0; v < num_packets / FWNET_ISO_PAGE_COUNT; v++)
+				*ptrptr++ = (void *)
+						((char *)ptr + v * max_receive);
+		}
+		dev->broadcast_rcv_context = context;
+	} else {
+		context = dev->broadcast_rcv_context;
+	}
+
+	packet.payload_length = max_receive;
+	packet.interrupt = 1;
+	packet.skip = 0;
+	packet.tag = 3;
+	packet.sy = 0;
+	packet.header_length = IEEE1394_GASP_HDR_SIZE;
+	offset = 0;
+
+	for (u = 0; u < num_packets; u++) {
+		retval = fw_iso_context_queue(context, &packet,
+				&dev->broadcast_rcv_buffer, offset);
+		if (retval < 0)
+			goto failed_rcv_queue;
+
+		offset += max_receive;
+	}
+	dev->num_broadcast_rcv_ptrs = num_packets;
+	dev->rcv_buffer_size = max_receive;
+	dev->broadcast_rcv_next_ptr = 0U;
+	retval = fw_iso_context_start(context, -1, 0,
+			FW_ISO_CONTEXT_MATCH_ALL_TAGS); /* ??? sync */
+	if (retval < 0)
+		goto failed_rcv_queue;
+
+	/* FIXME: adjust it according to the min. speed of all known peers? */
+	dev->broadcast_xmt_max_payload = IEEE1394_MAX_PAYLOAD_S100
+			- IEEE1394_GASP_HDR_SIZE - RFC2374_UNFRAG_HDR_SIZE;
+	dev->broadcast_state = FWNET_BROADCAST_RUNNING;
+
+	return 0;
+
+ failed_rcv_queue:
+	kfree(dev->broadcast_rcv_buffer_ptrs);
+	dev->broadcast_rcv_buffer_ptrs = NULL;
+ failed_ptrs_alloc:
+	fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer, dev->card);
+ failed_buffer_init:
+	fw_iso_context_destroy(context);
+	dev->broadcast_rcv_context = NULL;
+ failed_context_create:
+	fw_core_remove_address_handler(&dev->handler);
+ failed_initial:
+	dev->local_fifo = FWNET_NO_FIFO_ADDR;
+
+	return retval;
+}
+
+/* ifup */
+static int fwnet_open(struct net_device *net)
+{
+	struct fwnet_device *dev = netdev_priv(net);
+	int ret;
+
+	if (dev->broadcast_state == FWNET_BROADCAST_ERROR) {
+		ret = fwnet_broadcast_start(dev);
+		if (ret)
+			return ret;
+	}
+	netif_start_queue(net);
+
+	return 0;
+}
+
+/* ifdown */
+static int fwnet_stop(struct net_device *net)
+{
+	netif_stop_queue(net);
+
+	/* Deallocate iso context for use by other applications? */
+
+	return 0;
+}
+
+static int fwnet_tx(struct sk_buff *skb, struct net_device *net)
+{
+	struct fwnet_header hdr_buf;
+	struct fwnet_device *dev = netdev_priv(net);
+	__be16 proto;
+	u16 dest_node;
+	unsigned max_payload;
+	u16 dg_size;
+	u16 *datagram_label_ptr;
+	struct fwnet_packet_task *ptask;
+	struct fwnet_peer *peer;
+	unsigned long flags;
+
+	ptask = kmem_cache_alloc(fwnet_packet_task_cache, GFP_ATOMIC);
+	if (ptask == NULL)
+		goto fail;
+
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		goto fail;
+
+	/*
+	 * Make a copy of the driver-specific header.
+	 * We might need to rebuild the header on tx failure.
+	 */
+	memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
+	skb_pull(skb, sizeof(hdr_buf));
+
+	proto = hdr_buf.h_proto;
+	dg_size = skb->len;
+
+	/* serialize access to peer, including peer->datagram_label */
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/*
+	 * Set the transmission type for the packet.  ARP packets and IP
+	 * broadcast packets are sent via GASP.
+	 */
+	if (memcmp(hdr_buf.h_dest, net->broadcast, FWNET_ALEN) == 0
+	    || proto == htons(ETH_P_ARP)
+	    || (proto == htons(ETH_P_IP)
+		&& IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
+		max_payload        = dev->broadcast_xmt_max_payload;
+		datagram_label_ptr = &dev->broadcast_xmt_datagramlabel;
+
+		ptask->fifo_addr   = FWNET_NO_FIFO_ADDR;
+		ptask->generation  = 0;
+		ptask->dest_node   = IEEE1394_ALL_NODES;
+		ptask->speed       = SCODE_100;
+	} else {
+		__be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest);
+		u8 generation;
+
+		peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
+		if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR)
+			goto fail_unlock;
+
+		generation         = peer->generation;
+		dest_node          = peer->node_id;
+		max_payload        = peer->max_payload;
+		datagram_label_ptr = &peer->datagram_label;
+
+		ptask->fifo_addr   = peer->fifo;
+		ptask->generation  = generation;
+		ptask->dest_node   = dest_node;
+		ptask->speed       = peer->speed;
+	}
+
+	/* If this is an ARP packet, convert it */
+	if (proto == htons(ETH_P_ARP)) {
+		struct arphdr *arp = (struct arphdr *)skb->data;
+		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
+		struct rfc2734_arp *arp1394 = (struct rfc2734_arp *)skb->data;
+		__be32 ipaddr;
+
+		ipaddr = get_unaligned((__be32 *)(arp_ptr + FWNET_ALEN));
+
+		arp1394->hw_addr_len    = RFC2734_HW_ADDR_LEN;
+		arp1394->max_rec        = dev->card->max_receive;
+		arp1394->sspd		= dev->card->link_speed;
+
+		put_unaligned_be16(dev->local_fifo >> 32,
+				   &arp1394->fifo_hi);
+		put_unaligned_be32(dev->local_fifo & 0xffffffff,
+				   &arp1394->fifo_lo);
+		put_unaligned(ipaddr, &arp1394->sip);
+	}
+
+	ptask->hdr.w0 = 0;
+	ptask->hdr.w1 = 0;
+	ptask->skb = skb;
+	ptask->dev = dev;
+
+	/* Does it all fit in one packet? */
+	if (dg_size <= max_payload) {
+		fwnet_make_uf_hdr(&ptask->hdr, ntohs(proto));
+		ptask->outstanding_pkts = 1;
+		max_payload = dg_size + RFC2374_UNFRAG_HDR_SIZE;
+	} else {
+		u16 datagram_label;
+
+		max_payload -= RFC2374_FRAG_OVERHEAD;
+		datagram_label = (*datagram_label_ptr)++;
+		fwnet_make_ff_hdr(&ptask->hdr, ntohs(proto), dg_size,
+				  datagram_label);
+		ptask->outstanding_pkts = DIV_ROUND_UP(dg_size, max_payload);
+		max_payload += RFC2374_FRAG_HDR_SIZE;
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	ptask->max_payload = max_payload;
+	fwnet_send_packet(ptask);
+
+	return NETDEV_TX_OK;
+
+ fail_unlock:
+	spin_unlock_irqrestore(&dev->lock, flags);
+ fail:
+	if (ptask)
+		kmem_cache_free(fwnet_packet_task_cache, ptask);
+
+	if (skb != NULL)
+		dev_kfree_skb(skb);
+
+	net->stats.tx_dropped++;
+	net->stats.tx_errors++;
+
+	/*
+	 * FIXME: According to a patch from 2003-02-26, "returning non-zero
+	 * causes serious problems" here, allegedly.  Before that patch,
+	 * -ERRNO was returned which is not appropriate under Linux 2.6.
+	 * Perhaps more needs to be done?  Stop the queue in serious
+	 * conditions and restart it elsewhere?
+	 */
+	return NETDEV_TX_OK;
+}
+
+static int fwnet_change_mtu(struct net_device *net, int new_mtu)
+{
+	if (new_mtu < 68)
+		return -EINVAL;
+
+	net->mtu = new_mtu;
+	return 0;
+}
+
+static void fwnet_get_drvinfo(struct net_device *net,
+			      struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, KBUILD_MODNAME);
+	strcpy(info->bus_info, "ieee1394");
+}
+
+static struct ethtool_ops fwnet_ethtool_ops = {
+	.get_drvinfo = fwnet_get_drvinfo,
+};
+
+static const struct net_device_ops fwnet_netdev_ops = {
+	.ndo_open       = fwnet_open,
+	.ndo_stop	= fwnet_stop,
+	.ndo_start_xmit = fwnet_tx,
+	.ndo_change_mtu = fwnet_change_mtu,
+};
+
+static void fwnet_init_dev(struct net_device *net)
+{
+	net->header_ops		= &fwnet_header_ops;
+	net->netdev_ops		= &fwnet_netdev_ops;
+	net->watchdog_timeo	= 2 * HZ;
+	net->flags		= IFF_BROADCAST | IFF_MULTICAST;
+	net->features		= NETIF_F_HIGHDMA;
+	net->addr_len		= FWNET_ALEN;
+	net->hard_header_len	= FWNET_HLEN;
+	net->type		= ARPHRD_IEEE1394;
+	net->tx_queue_len	= 10;
+	SET_ETHTOOL_OPS(net, &fwnet_ethtool_ops);
+}
+
+/* caller must hold fwnet_device_mutex */
+static struct fwnet_device *fwnet_dev_find(struct fw_card *card)
+{
+	struct fwnet_device *dev;
+
+	list_for_each_entry(dev, &fwnet_device_list, dev_link)
+		if (dev->card == card)
+			return dev;
+
+	return NULL;
+}
+
+static int fwnet_add_peer(struct fwnet_device *dev,
+			  struct fw_unit *unit, struct fw_device *device)
+{
+	struct fwnet_peer *peer;
+
+	peer = kmalloc(sizeof(*peer), GFP_KERNEL);
+	if (!peer)
+		return -ENOMEM;
+
+	dev_set_drvdata(&unit->device, peer);
+
+	peer->dev = dev;
+	peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
+	peer->fifo = FWNET_NO_FIFO_ADDR;
+	INIT_LIST_HEAD(&peer->pd_list);
+	peer->pdg_size = 0;
+	peer->datagram_label = 0;
+	peer->speed = device->max_speed;
+	peer->max_payload = fwnet_max_payload(device->max_rec, peer->speed);
+
+	peer->generation = device->generation;
+	smp_rmb();
+	peer->node_id = device->node_id;
+
+	spin_lock_irq(&dev->lock);
+	list_add_tail(&peer->peer_link, &dev->peer_list);
+	spin_unlock_irq(&dev->lock);
+
+	return 0;
+}
+
+static int fwnet_probe(struct device *_dev)
+{
+	struct fw_unit *unit = fw_unit(_dev);
+	struct fw_device *device = fw_parent_device(unit);
+	struct fw_card *card = device->card;
+	struct net_device *net;
+	bool allocated_netdev = false;
+	struct fwnet_device *dev;
+	unsigned max_mtu;
+	int ret;
+
+	mutex_lock(&fwnet_device_mutex);
+
+	dev = fwnet_dev_find(card);
+	if (dev) {
+		net = dev->netdev;
+		goto have_dev;
+	}
+
+	net = alloc_netdev(sizeof(*dev), "firewire%d", fwnet_init_dev);
+	if (net == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	allocated_netdev = true;
+	SET_NETDEV_DEV(net, card->device);
+	dev = netdev_priv(net);
+
+	spin_lock_init(&dev->lock);
+	dev->broadcast_state = FWNET_BROADCAST_ERROR;
+	dev->broadcast_rcv_context = NULL;
+	dev->broadcast_xmt_max_payload = 0;
+	dev->broadcast_xmt_datagramlabel = 0;
+
+	dev->local_fifo = FWNET_NO_FIFO_ADDR;
+
+	INIT_LIST_HEAD(&dev->packet_list);
+	INIT_LIST_HEAD(&dev->broadcasted_list);
+	INIT_LIST_HEAD(&dev->sent_list);
+	INIT_LIST_HEAD(&dev->peer_list);
+
+	dev->card = card;
+	dev->netdev = net;
+
+	/*
+	 * Use the RFC 2734 default 1500 octets or the maximum payload
+	 * as initial MTU
+	 */
+	max_mtu = (1 << (card->max_receive + 1))
+		  - sizeof(struct rfc2734_header) - IEEE1394_GASP_HDR_SIZE;
+	net->mtu = min(1500U, max_mtu);
+
+	/* Set our hardware address while we're at it */
+	put_unaligned_be64(card->guid, net->dev_addr);
+	put_unaligned_be64(~0ULL, net->broadcast);
+	ret = register_netdev(net);
+	if (ret) {
+		fw_error("Cannot register the driver\n");
+		goto out;
+	}
+
+	list_add_tail(&dev->dev_link, &fwnet_device_list);
+	fw_notify("%s: IPv4 over FireWire on device %016llx\n",
+		  net->name, (unsigned long long)card->guid);
+ have_dev:
+	ret = fwnet_add_peer(dev, unit, device);
+	if (ret && allocated_netdev) {
+		unregister_netdev(net);
+		list_del(&dev->dev_link);
+	}
+ out:
+	if (ret && allocated_netdev)
+		free_netdev(net);
+
+	mutex_unlock(&fwnet_device_mutex);
+
+	return ret;
+}
+
+static void fwnet_remove_peer(struct fwnet_peer *peer)
+{
+	struct fwnet_partial_datagram *pd, *pd_next;
+
+	spin_lock_irq(&peer->dev->lock);
+	list_del(&peer->peer_link);
+	spin_unlock_irq(&peer->dev->lock);
+
+	list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link)
+		fwnet_pd_delete(pd);
+
+	kfree(peer);
+}
+
+static int fwnet_remove(struct device *_dev)
+{
+	struct fwnet_peer *peer = dev_get_drvdata(_dev);
+	struct fwnet_device *dev = peer->dev;
+	struct net_device *net;
+	struct fwnet_packet_task *ptask, *pt_next;
+
+	mutex_lock(&fwnet_device_mutex);
+
+	fwnet_remove_peer(peer);
+
+	if (list_empty(&dev->peer_list)) {
+		net = dev->netdev;
+		unregister_netdev(net);
+
+		if (dev->local_fifo != FWNET_NO_FIFO_ADDR)
+			fw_core_remove_address_handler(&dev->handler);
+		if (dev->broadcast_rcv_context) {
+			fw_iso_context_stop(dev->broadcast_rcv_context);
+			fw_iso_buffer_destroy(&dev->broadcast_rcv_buffer,
+					      dev->card);
+			fw_iso_context_destroy(dev->broadcast_rcv_context);
+		}
+		list_for_each_entry_safe(ptask, pt_next,
+					 &dev->packet_list, pt_link) {
+			dev_kfree_skb_any(ptask->skb);
+			kmem_cache_free(fwnet_packet_task_cache, ptask);
+		}
+		list_for_each_entry_safe(ptask, pt_next,
+					 &dev->broadcasted_list, pt_link) {
+			dev_kfree_skb_any(ptask->skb);
+			kmem_cache_free(fwnet_packet_task_cache, ptask);
+		}
+		list_for_each_entry_safe(ptask, pt_next,
+					 &dev->sent_list, pt_link) {
+			dev_kfree_skb_any(ptask->skb);
+			kmem_cache_free(fwnet_packet_task_cache, ptask);
+		}
+		list_del(&dev->dev_link);
+
+		free_netdev(net);
+	}
+
+	mutex_unlock(&fwnet_device_mutex);
+
+	return 0;
+}
+
+/*
+ * FIXME abort partially sent fragmented datagrams,
+ * discard partially received fragmented datagrams
+ */
+static void fwnet_update(struct fw_unit *unit)
+{
+	struct fw_device *device = fw_parent_device(unit);
+	struct fwnet_peer *peer = dev_get_drvdata(&unit->device);
+	int generation;
+
+	generation = device->generation;
+
+	spin_lock_irq(&peer->dev->lock);
+	peer->node_id    = device->node_id;
+	peer->generation = generation;
+	spin_unlock_irq(&peer->dev->lock);
+}
+
+static const struct ieee1394_device_id fwnet_id_table[] = {
+	{
+		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
+				IEEE1394_MATCH_VERSION,
+		.specifier_id = IANA_SPECIFIER_ID,
+		.version      = RFC2734_SW_VERSION,
+	},
+	{ }
+};
+
+static struct fw_driver fwnet_driver = {
+	.driver = {
+		.owner  = THIS_MODULE,
+		.name   = "net",
+		.bus    = &fw_bus_type,
+		.probe  = fwnet_probe,
+		.remove = fwnet_remove,
+	},
+	.update   = fwnet_update,
+	.id_table = fwnet_id_table,
+};
+
+static const u32 rfc2374_unit_directory_data[] = {
+	0x00040000,	/* directory_length		*/
+	0x1200005e,	/* unit_specifier_id: IANA	*/
+	0x81000003,	/* textual descriptor offset	*/
+	0x13000001,	/* unit_sw_version: RFC 2734	*/
+	0x81000005,	/* textual descriptor offset	*/
+	0x00030000,	/* descriptor_length		*/
+	0x00000000,	/* text				*/
+	0x00000000,	/* minimal ASCII, en		*/
+	0x49414e41,	/* I A N A			*/
+	0x00030000,	/* descriptor_length		*/
+	0x00000000,	/* text				*/
+	0x00000000,	/* minimal ASCII, en		*/
+	0x49507634,	/* I P v 4			*/
+};
+
+static struct fw_descriptor rfc2374_unit_directory = {
+	.length = ARRAY_SIZE(rfc2374_unit_directory_data),
+	.key    = (CSR_DIRECTORY | CSR_UNIT) << 24,
+	.data   = rfc2374_unit_directory_data
+};
+
+static int __init fwnet_init(void)
+{
+	int err;
+
+	err = fw_core_add_descriptor(&rfc2374_unit_directory);
+	if (err)
+		return err;
+
+	fwnet_packet_task_cache = kmem_cache_create("packet_task",
+			sizeof(struct fwnet_packet_task), 0, 0, NULL);
+	if (!fwnet_packet_task_cache) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = driver_register(&fwnet_driver.driver);
+	if (!err)
+		return 0;
+
+	kmem_cache_destroy(fwnet_packet_task_cache);
+out:
+	fw_core_remove_descriptor(&rfc2374_unit_directory);
+
+	return err;
+}
+module_init(fwnet_init);
+
+static void __exit fwnet_cleanup(void)
+{
+	driver_unregister(&fwnet_driver.driver);
+	kmem_cache_destroy(fwnet_packet_task_cache);
+	fw_core_remove_descriptor(&rfc2374_unit_directory);
+}
+module_exit(fwnet_cleanup);
+
+MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>");
+MODULE_DESCRIPTION("IPv4 over IEEE1394 as per RFC 2734");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table);
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/ohci.c linux-libre-2.6.31-gnu/drivers/firewire/ohci.c
--- linux-libre-2.6.30-gnu/drivers/firewire/ohci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/ohci.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2650 @@
+/*
+ * 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/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+#include <asm/page.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/pmac_feature.h>
+#endif
+
+#include "core.h"
+#include "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);
+
+/*
+ * A buffer that contains a block of DMA-able coherent memory used for
+ * storing a portion of a DMA descriptor program.
+ */
+struct descriptor_buffer {
+	struct list_head list;
+	dma_addr_t buffer_bus;
+	size_t buffer_size;
+	size_t used;
+	struct descriptor buffer[0];
+};
+
+struct context {
+	struct fw_ohci *ohci;
+	u32 regs;
+	int total_allocation;
+
+	/*
+	 * List of page-sized buffers for storing DMA descriptors.
+	 * Head of list contains buffers in use and tail of list contains
+	 * free buffers.
+	 */
+	struct list_head buffer_list;
+
+	/*
+	 * Pointer to a buffer inside buffer_list that contains the tail
+	 * end of the current DMA program.
+	 */
+	struct descriptor_buffer *buffer_tail;
+
+	/*
+	 * The descriptor containing the branch address of the first
+	 * descriptor that has not yet been filled by the device.
+	 */
+	struct descriptor *last;
+
+	/*
+	 * The last descriptor in the DMA program.  It contains the branch
+	 * address that must be updated upon appending a new descriptor.
+	 */
+	struct descriptor *prev;
+
+	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;
+	int excess_bytes;
+	void *header;
+	size_t header_length;
+};
+
+#define CONFIG_ROM_SIZE 1024
+
+struct fw_ohci {
+	struct fw_card card;
+
+	__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;	/* for timestamping incoming requests */
+	atomic_t bus_seconds;
+
+	bool use_dualbuffer;
+	bool old_uninorth;
+	bool bus_reset_packet_quirk;
+
+	/*
+	 * 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;
+	u64 ir_context_channels;
+	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	0xf
+#define OHCI1394_MAX_AT_RESP_RETRIES	0x2
+#define OHCI1394_MAX_PHYS_RESP_RETRIES	0x8
+
+#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
+
+static char ohci_driver_name[] = KBUILD_MODNAME;
+
+#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
+
+#define OHCI_PARAM_DEBUG_AT_AR		1
+#define OHCI_PARAM_DEBUG_SELFIDS	2
+#define OHCI_PARAM_DEBUG_IRQS		4
+#define OHCI_PARAM_DEBUG_BUSRESETS	8 /* only effective before chip init */
+
+static int param_debug;
+module_param_named(debug, param_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
+	", AT/AR events = "	__stringify(OHCI_PARAM_DEBUG_AT_AR)
+	", self-IDs = "		__stringify(OHCI_PARAM_DEBUG_SELFIDS)
+	", IRQs = "		__stringify(OHCI_PARAM_DEBUG_IRQS)
+	", busReset events = "	__stringify(OHCI_PARAM_DEBUG_BUSRESETS)
+	", or a combination, or all = -1)");
+
+static void log_irqs(u32 evt)
+{
+	if (likely(!(param_debug &
+			(OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
+		return;
+
+	if (!(param_debug & OHCI_PARAM_DEBUG_IRQS) &&
+	    !(evt & OHCI1394_busReset))
+		return;
+
+	fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
+	    evt & OHCI1394_selfIDComplete	? " selfID"		: "",
+	    evt & OHCI1394_RQPkt		? " AR_req"		: "",
+	    evt & OHCI1394_RSPkt		? " AR_resp"		: "",
+	    evt & OHCI1394_reqTxComplete	? " AT_req"		: "",
+	    evt & OHCI1394_respTxComplete	? " AT_resp"		: "",
+	    evt & OHCI1394_isochRx		? " IR"			: "",
+	    evt & OHCI1394_isochTx		? " IT"			: "",
+	    evt & OHCI1394_postedWriteErr	? " postedWriteErr"	: "",
+	    evt & OHCI1394_cycleTooLong		? " cycleTooLong"	: "",
+	    evt & OHCI1394_cycle64Seconds	? " cycle64Seconds"	: "",
+	    evt & OHCI1394_regAccessFail	? " regAccessFail"	: "",
+	    evt & OHCI1394_busReset		? " busReset"		: "",
+	    evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
+		    OHCI1394_RSPkt | OHCI1394_reqTxComplete |
+		    OHCI1394_respTxComplete | OHCI1394_isochRx |
+		    OHCI1394_isochTx | OHCI1394_postedWriteErr |
+		    OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds |
+		    OHCI1394_regAccessFail | OHCI1394_busReset)
+						? " ?"			: "");
+}
+
+static const char *speed[] = {
+	[0] = "S100", [1] = "S200", [2] = "S400",    [3] = "beta",
+};
+static const char *power[] = {
+	[0] = "+0W",  [1] = "+15W", [2] = "+30W",    [3] = "+45W",
+	[4] = "-3W",  [5] = " ?W",  [6] = "-3..-6W", [7] = "-3..-10W",
+};
+static const char port[] = { '.', '-', 'p', 'c', };
+
+static char _p(u32 *s, int shift)
+{
+	return port[*s >> shift & 3];
+}
+
+static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
+{
+	if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
+		return;
+
+	fw_notify("%d selfIDs, generation %d, local node ID %04x\n",
+		  self_id_count, generation, node_id);
+
+	for (; self_id_count--; ++s)
+		if ((*s & 1 << 23) == 0)
+			fw_notify("selfID 0: %08x, phy %d [%c%c%c] "
+			    "%s gc=%d %s %s%s%s\n",
+			    *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2),
+			    speed[*s >> 14 & 3], *s >> 16 & 63,
+			    power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "",
+			    *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : "");
+		else
+			fw_notify("selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n",
+			    *s, *s >> 24 & 63,
+			    _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10),
+			    _p(s,  8), _p(s,  6), _p(s,  4), _p(s,  2));
+}
+
+static const char *evts[] = {
+	[0x00] = "evt_no_status",	[0x01] = "-reserved-",
+	[0x02] = "evt_long_packet",	[0x03] = "evt_missing_ack",
+	[0x04] = "evt_underrun",	[0x05] = "evt_overrun",
+	[0x06] = "evt_descriptor_read",	[0x07] = "evt_data_read",
+	[0x08] = "evt_data_write",	[0x09] = "evt_bus_reset",
+	[0x0a] = "evt_timeout",		[0x0b] = "evt_tcode_err",
+	[0x0c] = "-reserved-",		[0x0d] = "-reserved-",
+	[0x0e] = "evt_unknown",		[0x0f] = "evt_flushed",
+	[0x10] = "-reserved-",		[0x11] = "ack_complete",
+	[0x12] = "ack_pending ",	[0x13] = "-reserved-",
+	[0x14] = "ack_busy_X",		[0x15] = "ack_busy_A",
+	[0x16] = "ack_busy_B",		[0x17] = "-reserved-",
+	[0x18] = "-reserved-",		[0x19] = "-reserved-",
+	[0x1a] = "-reserved-",		[0x1b] = "ack_tardy",
+	[0x1c] = "-reserved-",		[0x1d] = "ack_data_error",
+	[0x1e] = "ack_type_error",	[0x1f] = "-reserved-",
+	[0x20] = "pending/cancelled",
+};
+static const char *tcodes[] = {
+	[0x0] = "QW req",		[0x1] = "BW req",
+	[0x2] = "W resp",		[0x3] = "-reserved-",
+	[0x4] = "QR req",		[0x5] = "BR req",
+	[0x6] = "QR resp",		[0x7] = "BR resp",
+	[0x8] = "cycle start",		[0x9] = "Lk req",
+	[0xa] = "async stream packet",	[0xb] = "Lk resp",
+	[0xc] = "-reserved-",		[0xd] = "-reserved-",
+	[0xe] = "link internal",	[0xf] = "-reserved-",
+};
+static const char *phys[] = {
+	[0x0] = "phy config packet",	[0x1] = "link-on packet",
+	[0x2] = "self-id packet",	[0x3] = "-reserved-",
+};
+
+static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
+{
+	int tcode = header[0] >> 4 & 0xf;
+	char specific[12];
+
+	if (likely(!(param_debug & OHCI_PARAM_DEBUG_AT_AR)))
+		return;
+
+	if (unlikely(evt >= ARRAY_SIZE(evts)))
+			evt = 0x1f;
+
+	if (evt == OHCI1394_evt_bus_reset) {
+		fw_notify("A%c evt_bus_reset, generation %d\n",
+		    dir, (header[2] >> 16) & 0xff);
+		return;
+	}
+
+	if (header[0] == ~header[1]) {
+		fw_notify("A%c %s, %s, %08x\n",
+		    dir, evts[evt], phys[header[0] >> 30 & 0x3], header[0]);
+		return;
+	}
+
+	switch (tcode) {
+	case 0x0: case 0x6: case 0x8:
+		snprintf(specific, sizeof(specific), " = %08x",
+			 be32_to_cpu((__force __be32)header[3]));
+		break;
+	case 0x1: case 0x5: case 0x7: case 0x9: case 0xb:
+		snprintf(specific, sizeof(specific), " %x,%x",
+			 header[3] >> 16, header[3] & 0xffff);
+		break;
+	default:
+		specific[0] = '\0';
+	}
+
+	switch (tcode) {
+	case 0xe: case 0xa:
+		fw_notify("A%c %s, %s\n", dir, evts[evt], tcodes[tcode]);
+		break;
+	case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
+		fw_notify("A%c spd %x tl %02x, "
+		    "%04x -> %04x, %s, "
+		    "%s, %04x%08x%s\n",
+		    dir, speed, header[0] >> 10 & 0x3f,
+		    header[1] >> 16, header[0] >> 16, evts[evt],
+		    tcodes[tcode], header[1] & 0xffff, header[2], specific);
+		break;
+	default:
+		fw_notify("A%c spd %x tl %02x, "
+		    "%04x -> %04x, %s, "
+		    "%s%s\n",
+		    dir, speed, header[0] >> 10 & 0x3f,
+		    header[1] >> 16, header[0] >> 16, evts[evt],
+		    tcodes[tcode], specific);
+	}
+}
+
+#else
+
+#define log_irqs(evt)
+#define log_selfids(node_id, generation, self_id_count, sid)
+#define log_ar_at_event(dir, speed, header, evt)
+
+#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
+
+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));
+	flush_writes(ohci);
+	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 uninitialized_var(ab_bus);
+	size_t offset;
+
+	ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC);
+	if (ab == NULL)
+		return -ENOMEM;
+
+	ab->next = NULL;
+	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;
+
+	ctx->last_buffer->descriptor.branch_address = cpu_to_le32(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 void ar_context_release(struct ar_context *ctx)
+{
+	struct ar_buffer *ab, *ab_next;
+	size_t offset;
+	dma_addr_t ab_bus;
+
+	for (ab = ctx->current_buffer; ab; ab = ab_next) {
+		ab_next = ab->next;
+		offset = offsetof(struct ar_buffer, data);
+		ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+		dma_free_coherent(ctx->ohci->card.device, PAGE_SIZE,
+				  ab, ab_bus);
+	}
+}
+
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
+#define cond_le32_to_cpu(v) \
+	(ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v))
+#else
+#define cond_le32_to_cpu(v) le32_to_cpu(v)
+#endif
+
+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;
+	int evt;
+
+	p.header[0] = cond_le32_to_cpu(buffer[0]);
+	p.header[1] = cond_le32_to_cpu(buffer[1]);
+	p.header[2] = cond_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] = cond_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] = cond_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;
+
+	default:
+		/* FIXME: Stop context, discard everything, and restart? */
+		p.header_length = 0;
+		p.payload_length = 0;
+	}
+
+	p.payload = (void *) buffer + p.header_length;
+
+	/* FIXME: What to do about evt_* errors? */
+	length = (p.header_length + p.payload_length + 3) / 4;
+	status = cond_le32_to_cpu(buffer[length]);
+	evt    = (status >> 16) & 0x1f;
+
+	p.ack        = evt - 16;
+	p.speed      = (status >> 21) & 0x7;
+	p.timestamp  = status & 0xffff;
+	p.generation = ohci->request_generation;
+
+	log_ar_at_event('R', p.speed, p.header, evt);
+
+	/*
+	 * 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.
+	 *
+	 * Alas some chips sometimes emit bus reset packets with a
+	 * wrong generation.  We set the correct generation for these
+	 * at a slightly incorrect time (in bus_reset_tasklet).
+	 */
+	if (evt == OHCI1394_evt_bus_reset) {
+		if (!ohci->bus_reset_packet_quirk)
+			ohci->request_generation = (p.header[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;
+		dma_addr_t start_bus;
+		void *start;
+
+		/*
+		 * 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);
+		start = buffer = ab;
+		start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+
+		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);
+
+		dma_free_coherent(ohci->card.device, PAGE_SIZE,
+				  start, start_bus);
+		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;
+
+	return 0;
+}
+
+static void ar_context_run(struct ar_context *ctx)
+{
+	struct ar_buffer *ab = ctx->current_buffer;
+	dma_addr_t ab_bus;
+	size_t offset;
+
+	offset = offsetof(struct ar_buffer, data);
+	ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+
+	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab_bus | 1);
+	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
+	flush_writes(ctx->ohci);
+}
+
+static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
+{
+	int b, key;
+
+	b   = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2;
+	key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8;
+
+	/* figure out which descriptor the branch address goes in */
+	if (z == 2 && (b == 3 || key == 2))
+		return d;
+	else
+		return d + z - 1;
+}
+
+static void context_tasklet(unsigned long data)
+{
+	struct context *ctx = (struct context *) data;
+	struct descriptor *d, *last;
+	u32 address;
+	int z;
+	struct descriptor_buffer *desc;
+
+	desc = list_entry(ctx->buffer_list.next,
+			struct descriptor_buffer, list);
+	last = ctx->last;
+	while (last->branch_address != 0) {
+		struct descriptor_buffer *old_desc = desc;
+		address = le32_to_cpu(last->branch_address);
+		z = address & 0xf;
+		address &= ~0xf;
+
+		/* If the branch address points to a buffer outside of the
+		 * current buffer, advance to the next buffer. */
+		if (address < desc->buffer_bus ||
+				address >= desc->buffer_bus + desc->used)
+			desc = list_entry(desc->list.next,
+					struct descriptor_buffer, list);
+		d = desc->buffer + (address - desc->buffer_bus) / sizeof(*d);
+		last = find_branch_descriptor(d, z);
+
+		if (!ctx->callback(ctx, d, last))
+			break;
+
+		if (old_desc != desc) {
+			/* If we've advanced to the next buffer, move the
+			 * previous buffer to the free list. */
+			unsigned long flags;
+			old_desc->used = 0;
+			spin_lock_irqsave(&ctx->ohci->lock, flags);
+			list_move_tail(&old_desc->list, &ctx->buffer_list);
+			spin_unlock_irqrestore(&ctx->ohci->lock, flags);
+		}
+		ctx->last = last;
+	}
+}
+
+/*
+ * Allocate a new buffer and add it to the list of free buffers for this
+ * context.  Must be called with ohci->lock held.
+ */
+static int context_add_buffer(struct context *ctx)
+{
+	struct descriptor_buffer *desc;
+	dma_addr_t uninitialized_var(bus_addr);
+	int offset;
+
+	/*
+	 * 16MB of descriptors should be far more than enough for any DMA
+	 * program.  This will catch run-away userspace or DoS attacks.
+	 */
+	if (ctx->total_allocation >= 16*1024*1024)
+		return -ENOMEM;
+
+	desc = dma_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE,
+			&bus_addr, GFP_ATOMIC);
+	if (!desc)
+		return -ENOMEM;
+
+	offset = (void *)&desc->buffer - (void *)desc;
+	desc->buffer_size = PAGE_SIZE - offset;
+	desc->buffer_bus = bus_addr + offset;
+	desc->used = 0;
+
+	list_add_tail(&desc->list, &ctx->buffer_list);
+	ctx->total_allocation += PAGE_SIZE;
+
+	return 0;
+}
+
+static int context_init(struct context *ctx, struct fw_ohci *ohci,
+			u32 regs, descriptor_callback_t callback)
+{
+	ctx->ohci = ohci;
+	ctx->regs = regs;
+	ctx->total_allocation = 0;
+
+	INIT_LIST_HEAD(&ctx->buffer_list);
+	if (context_add_buffer(ctx) < 0)
+		return -ENOMEM;
+
+	ctx->buffer_tail = list_entry(ctx->buffer_list.next,
+			struct descriptor_buffer, list);
+
+	tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx);
+	ctx->callback = callback;
+
+	/*
+	 * 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.
+	 */
+	memset(ctx->buffer_tail->buffer, 0, sizeof(*ctx->buffer_tail->buffer));
+	ctx->buffer_tail->buffer->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST);
+	ctx->buffer_tail->buffer->transfer_status = cpu_to_le16(0x8011);
+	ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer);
+	ctx->last = ctx->buffer_tail->buffer;
+	ctx->prev = ctx->buffer_tail->buffer;
+
+	return 0;
+}
+
+static void context_release(struct context *ctx)
+{
+	struct fw_card *card = &ctx->ohci->card;
+	struct descriptor_buffer *desc, *tmp;
+
+	list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list)
+		dma_free_coherent(card->device, PAGE_SIZE, desc,
+			desc->buffer_bus -
+			((void *)&desc->buffer - (void *)desc));
+}
+
+/* Must be called with ohci->lock held */
+static struct descriptor *context_get_descriptors(struct context *ctx,
+						  int z, dma_addr_t *d_bus)
+{
+	struct descriptor *d = NULL;
+	struct descriptor_buffer *desc = ctx->buffer_tail;
+
+	if (z * sizeof(*d) > desc->buffer_size)
+		return NULL;
+
+	if (z * sizeof(*d) > desc->buffer_size - desc->used) {
+		/* No room for the descriptor in this buffer, so advance to the
+		 * next one. */
+
+		if (desc->list.next == &ctx->buffer_list) {
+			/* If there is no free buffer next in the list,
+			 * allocate one. */
+			if (context_add_buffer(ctx) < 0)
+				return NULL;
+		}
+		desc = list_entry(desc->list.next,
+				struct descriptor_buffer, list);
+		ctx->buffer_tail = desc;
+	}
+
+	d = desc->buffer + desc->used / sizeof(*d);
+	memset(d, 0, z * sizeof(*d));
+	*d_bus = desc->buffer_bus + desc->used;
+
+	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->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;
+	struct descriptor_buffer *desc = ctx->buffer_tail;
+
+	d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d);
+
+	desc->used += (z + extra) * sizeof(*d);
+	ctx->prev->branch_address = cpu_to_le32(d_bus | z);
+	ctx->prev = find_branch_descriptor(d, z);
+
+	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)
+			return;
+
+		mdelay(1);
+	}
+	fw_error("Error: DMA context still active (0x%08x)\n", reg);
+}
+
+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, uninitialized_var(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];
+	switch (packet->header_length) {
+	case 16:
+	case 12:
+		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);
+		break;
+
+	case 8:
+		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);
+		break;
+
+	case 4:
+		header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
+					(packet->speed << 16));
+		header[1] = cpu_to_le32(packet->header[0] & 0xffff0000);
+		d[0].req_count = cpu_to_le16(8);
+		break;
+
+	default:
+		/* BUG(); */
+		packet->ack = RCODE_SEND_ERROR;
+		return -1;
+	}
+
+	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(ohci->card.device, payload_bus)) {
+			packet->ack = RCODE_SEND_ERROR;
+			return -1;
+		}
+		packet->payload_bus = payload_bus;
+
+		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);
+
+	/*
+	 * If the controller and packet generations don't match, we need to
+	 * bail out and try again.  If IntEvent.busReset is set, the AT context
+	 * is halted, so appending to the context and trying to run it is
+	 * futile.  Most controllers do the right thing and just flush the AT
+	 * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
+	 * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
+	 * up stalling out.  So we just bail out in software and try again
+	 * later, and everyone is happy.
+	 * FIXME: Document how the locking works.
+	 */
+	if (ohci->generation != packet->generation ||
+	    reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+		if (packet->payload_length > 0)
+			dma_unmap_single(ohci->card.device, payload_bus,
+					 packet->payload_length, DMA_TO_DEVICE);
+		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;
+	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;
+
+	if (packet->payload_bus)
+		dma_unmap_single(ohci->card.device, packet->payload_bus,
+				 packet->payload_length, DMA_TO_DEVICE);
+
+	evt = le16_to_cpu(last->transfer_status) & 0x1f;
+	packet->timestamp = le16_to_cpu(last->res_count);
+
+	log_ar_at_event('T', packet->speed, packet->header, evt);
+
+	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 ret;
+
+	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;
+	}
+
+	ret = at_context_queue_packet(ctx, packet);
+	spin_unlock_irqrestore(&ctx->ohci->lock, flags);
+
+	if (ret < 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;
+	void *free_rom = NULL;
+	dma_addr_t free_rom_bus = 0;
+
+	reg = reg_read(ohci, OHCI1394_NodeID);
+	if (!(reg & OHCI1394_NodeID_idValid)) {
+		fw_notify("node ID not valid, new bus reset in progress\n");
+		return;
+	}
+	if ((reg & OHCI1394_NodeID_nodeNumber) == 63) {
+		fw_notify("malconfigured bus\n");
+		return;
+	}
+	ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
+			       OHCI1394_NodeID_nodeNumber);
+
+	reg = reg_read(ohci, OHCI1394_SelfIDCount);
+	if (reg & OHCI1394_SelfIDCount_selfIDError) {
+		fw_notify("inconsistent self IDs\n");
+		return;
+	}
+	/*
+	 * 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 >> 3) & 0x3ff;
+	if (self_id_count == 0) {
+		fw_notify("inconsistent self IDs\n");
+		return;
+	}
+	generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
+	rmb();
+
+	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_notify("inconsistent self IDs\n");
+			return;
+		}
+		ohci->self_id_buffer[j] =
+				cond_le32_to_cpu(ohci->self_id_cpu[i]);
+	}
+	rmb();
+
+	/*
+	 * 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);
+
+	if (ohci->bus_reset_packet_quirk)
+		ohci->request_generation = generation;
+
+	/*
+	 * 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) {
+		if (ohci->next_config_rom != ohci->config_rom) {
+			free_rom      = ohci->config_rom;
+			free_rom_bus  = 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);
+	}
+
+#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
+	reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
+	reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
+#endif
+
+	spin_unlock_irqrestore(&ohci->lock, flags);
+
+	if (free_rom)
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  free_rom, free_rom_bus);
+
+	log_selfids(ohci->node_id, generation,
+		    self_id_count, ohci->self_id_buffer);
+
+	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 || !~event)
+		return IRQ_NONE;
+
+	/* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
+	reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
+	log_irqs(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 (unlikely(event & OHCI1394_regAccessFail))
+		fw_error("Register access failure - "
+			 "please notify linux1394-devel@lists.sf.net\n");
+
+	if (unlikely(event & OHCI1394_postedWriteErr))
+		fw_error("PCI posted write error\n");
+
+	if (unlikely(event & OHCI1394_cycleTooLong)) {
+		if (printk_ratelimit())
+			fw_notify("isochronous cycle too long\n");
+		reg_write(ohci, OHCI1394_LinkControlSet,
+			  OHCI1394_LinkControl_cycleMaster);
+	}
+
+	if (event & OHCI1394_cycle64Seconds) {
+		cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+		if ((cycle_time & 0x80000000) == 0)
+			atomic_inc(&ohci->bus_seconds);
+	}
+
+	return IRQ_HANDLED;
+}
+
+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 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);
+	u32 lps;
+	int i;
+
+	if (software_reset(ohci)) {
+		fw_error("Failed to reset ohci card.\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * 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.  However, with some cards (well, at least
+	 * a JMicron PCIe card), we have to try again sometimes.
+	 */
+	reg_write(ohci, OHCI1394_HCControlSet,
+		  OHCI1394_HCControl_LPS |
+		  OHCI1394_HCControl_postedWriteEnable);
+	flush_writes(ohci);
+
+	for (lps = 0, i = 0; !lps && i < 3; i++) {
+		msleep(50);
+		lps = reg_read(ohci, OHCI1394_HCControlSet) &
+		      OHCI1394_HCControl_LPS;
+	}
+
+	if (!lps) {
+		fw_error("Failed to set Link Power Status\n");
+		return -EIO;
+	}
+
+	reg_write(ohci, OHCI1394_HCControlClear,
+		  OHCI1394_HCControl_noByteSwapData);
+
+	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
+	reg_write(ohci, OHCI1394_LinkControlClear,
+		  OHCI1394_LinkControl_rcvPhyPkt);
+	reg_write(ohci, OHCI1394_LinkControlSet,
+		  OHCI1394_LinkControl_rcvSelfID |
+		  OHCI1394_LinkControl_cycleTimerEnable |
+		  OHCI1394_LinkControl_cycleMaster);
+
+	reg_write(ohci, OHCI1394_ATRetries,
+		  OHCI1394_MAX_AT_REQ_RETRIES |
+		  (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
+		  (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
+
+	ar_context_run(&ohci->ar_request_ctx);
+	ar_context_run(&ohci->ar_response_ctx);
+
+	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_postedWriteErr | OHCI1394_cycleTooLong |
+		  OHCI1394_cycle64Seconds | OHCI1394_regAccessFail |
+		  OHCI1394_masterIntEnable);
+	if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
+		reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
+
+	/* Activate link_on bit and contender bit in our self ID packets.*/
+	if (ohci_update_phy_reg(card, 4, 0,
+				PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
+		return -EIO;
+
+	/*
+	 * 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.
+	 */
+
+	if (config_rom) {
+		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);
+	} else {
+		/*
+		 * In the suspend case, config_rom is NULL, which
+		 * means that we just reuse the old config rom.
+		 */
+		ohci->next_config_rom = ohci->config_rom;
+		ohci->next_config_rom_bus = ohci->config_rom_bus;
+	}
+
+	ohci->next_header = be32_to_cpu(ohci->next_config_rom[0]);
+	ohci->next_config_rom[0] = 0;
+	reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
+	reg_write(ohci, OHCI1394_BusOptions,
+		  be32_to_cpu(ohci->next_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 ret = -EBUSY;
+	__be32 *next_config_rom;
+	dma_addr_t uninitialized_var(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);
+		ret = 0;
+	}
+
+	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 (ret == 0)
+		fw_core_initiate_bus_reset(&ohci->card, 1);
+	else
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  next_config_rom, next_config_rom_bus);
+
+	return ret;
+}
+
+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 ret = -ENOENT;
+
+	tasklet_disable(&ctx->tasklet);
+
+	if (packet->ack != 0)
+		goto out;
+
+	if (packet->payload_bus)
+		dma_unmap_single(ohci->card.device, packet->payload_bus,
+				 packet->payload_length, DMA_TO_DEVICE);
+
+	log_ar_at_event('T', packet->speed, packet->header, 0x20);
+	driver_data->packet = NULL;
+	packet->ack = RCODE_CANCELLED;
+	packet->callback(packet, &ohci->card, packet->ack);
+	ret = 0;
+ out:
+	tasklet_enable(&ctx->tasklet);
+
+	return ret;
+}
+
+static int ohci_enable_phys_dma(struct fw_card *card,
+				int node_id, int generation)
+{
+#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
+	return 0;
+#else
+	struct fw_ohci *ohci = fw_ohci(card);
+	unsigned long flags;
+	int n, ret = 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) {
+		ret = -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 ret;
+#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
+}
+
+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)atomic_read(&ohci->bus_seconds) << 32) | cycle_time;
+
+	return bus_time;
+}
+
+static void copy_iso_headers(struct iso_context *ctx, void *p)
+{
+	int i = ctx->header_length;
+
+	if (i + ctx->base.header_size > PAGE_SIZE)
+		return;
+
+	/*
+	 * 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.
+	 */
+	if (ctx->base.header_size > 0)
+		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
+	if (ctx->base.header_size > 4)
+		*(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p);
+	if (ctx->base.header_size > 8)
+		memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8);
+	ctx->header_length += ctx->base.header_size;
+}
+
+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;
+
+	if (db->first_res_count != 0 && db->second_res_count != 0) {
+		if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
+			/* This descriptor isn't done yet, stop iteration. */
+			return 0;
+		}
+		ctx->excess_bytes -= le16_to_cpu(db->second_req_count);
+	}
+
+	header_length = le16_to_cpu(db->first_req_count) -
+		le16_to_cpu(db->first_res_count);
+
+	p = db + 1;
+	end = p + header_length;
+	while (p < end) {
+		copy_iso_headers(ctx, p);
+		ctx->excess_bytes +=
+			(le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff;
+		p += max(ctx->base.header_size, (size_t)8);
+	}
+
+	ctx->excess_bytes -= le16_to_cpu(db->second_req_count) -
+		le16_to_cpu(db->second_res_count);
+
+	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_ir_packet_per_buffer(struct context *context,
+				       struct descriptor *d,
+				       struct descriptor *last)
+{
+	struct iso_context *ctx =
+		container_of(context, struct iso_context, context);
+	struct descriptor *pd;
+	__le32 *ir_header;
+	void *p;
+
+	for (pd = d; pd <= last; pd++) {
+		if (pd->transfer_status)
+			break;
+	}
+	if (pd > last)
+		/* Descriptor(s) not done yet, stop iteration */
+		return 0;
+
+	p = last + 1;
+	copy_iso_headers(ctx, p);
+
+	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
+		ir_header = (__le32 *) p;
+		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, int channel, size_t header_size)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+	struct iso_context *ctx, *list;
+	descriptor_callback_t callback;
+	u64 *channels, dont_care = ~0ULL;
+	u32 *mask, regs;
+	unsigned long flags;
+	int index, ret = -ENOMEM;
+
+	if (type == FW_ISO_CONTEXT_TRANSMIT) {
+		channels = &dont_care;
+		mask = &ohci->it_context_mask;
+		list = ohci->it_context_list;
+		callback = handle_it_packet;
+	} else {
+		channels = &ohci->ir_context_channels;
+		mask = &ohci->ir_context_mask;
+		list = ohci->ir_context_list;
+		if (ohci->use_dualbuffer)
+			callback = handle_ir_dualbuffer_packet;
+		else
+			callback = handle_ir_packet_per_buffer;
+	}
+
+	spin_lock_irqsave(&ohci->lock, flags);
+	index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
+	if (index >= 0) {
+		*channels &= ~(1ULL << channel);
+		*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;
+
+	ret = context_init(&ctx->context, ohci, regs, callback);
+	if (ret < 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(ret);
+}
+
+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_ISOCH_HEADER;
+		if (ohci->use_dualbuffer)
+			control |= IR_CONTEXT_DUAL_BUFFER_MODE;
+		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;
+		ohci->ir_context_channels |= 1ULL << base->channel;
+	}
+
+	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..
+	 */
+
+	p = packet;
+	z = 2;
+
+	/*
+	 * The OHCI controller puts the isochronous header and trailer in the
+	 * buffer, so we need at least 8 bytes.
+	 */
+	packet_count = p->header_length / ctx->base.header_size;
+	header_size = packet_count * max(ctx->base.header_size, (size_t)8);
+
+	/* 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: 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(max(ctx->base.header_size, (size_t)8));
+		if (p->skip && rest == p->payload_length) {
+			db->control |= cpu_to_le16(DESCRIPTOR_WAIT);
+			db->first_req_count = db->first_size;
+		} else {
+			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 (p->skip && rest == p->payload_length)
+			length = 4;
+		else 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;
+		if (offset == 0)
+			page++;
+	}
+
+	return 0;
+}
+
+static int ohci_queue_iso_receive_packet_per_buffer(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 = NULL, *pd = NULL;
+	struct fw_iso_packet *p = packet;
+	dma_addr_t d_bus, page_bus;
+	u32 z, header_z, rest;
+	int i, j, length;
+	int page, offset, packet_count, header_size, payload_per_buffer;
+
+	/*
+	 * The OHCI controller puts the isochronous header and trailer in the
+	 * buffer, so we need at least 8 bytes.
+	 */
+	packet_count = p->header_length / ctx->base.header_size;
+	header_size  = max(ctx->base.header_size, (size_t)8);
+
+	/* Get header size in number of descriptors. */
+	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
+	page     = payload >> PAGE_SHIFT;
+	offset   = payload & ~PAGE_MASK;
+	payload_per_buffer = p->payload_length / packet_count;
+
+	for (i = 0; i < packet_count; i++) {
+		/* d points to the header descriptor */
+		z = DIV_ROUND_UP(payload_per_buffer + offset, PAGE_SIZE) + 1;
+		d = context_get_descriptors(&ctx->context,
+				z + header_z, &d_bus);
+		if (d == NULL)
+			return -ENOMEM;
+
+		d->control      = cpu_to_le16(DESCRIPTOR_STATUS |
+					      DESCRIPTOR_INPUT_MORE);
+		if (p->skip && i == 0)
+			d->control |= cpu_to_le16(DESCRIPTOR_WAIT);
+		d->req_count    = cpu_to_le16(header_size);
+		d->res_count    = d->req_count;
+		d->transfer_status = 0;
+		d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d)));
+
+		rest = payload_per_buffer;
+		for (j = 1; j < z; j++) {
+			pd = d + j;
+			pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
+						  DESCRIPTOR_INPUT_MORE);
+
+			if (offset + rest < PAGE_SIZE)
+				length = rest;
+			else
+				length = PAGE_SIZE - offset;
+			pd->req_count = cpu_to_le16(length);
+			pd->res_count = pd->req_count;
+			pd->transfer_status = 0;
+
+			page_bus = page_private(buffer->pages[page]);
+			pd->data_address = cpu_to_le32(page_bus + offset);
+
+			offset = (offset + length) & ~PAGE_MASK;
+			rest -= length;
+			if (offset == 0)
+				page++;
+		}
+		pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
+					  DESCRIPTOR_INPUT_LAST |
+					  DESCRIPTOR_BRANCH_ALWAYS);
+		if (p->interrupt && i == packet_count - 1)
+			pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
+
+		context_append(&ctx->context, d, z, header_z);
+	}
+
+	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);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&ctx->context.ohci->lock, flags);
+	if (base->type == FW_ISO_CONTEXT_TRANSMIT)
+		ret = ohci_queue_iso_transmit(base, packet, buffer, payload);
+	else if (ctx->context.ohci->use_dualbuffer)
+		ret = ohci_queue_iso_receive_dualbuffer(base, packet,
+							buffer, payload);
+	else
+		ret = ohci_queue_iso_receive_packet_per_buffer(base, packet,
+							buffer, payload);
+	spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
+
+	return ret;
+}
+
+static const struct fw_card_driver ohci_driver = {
+	.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,
+};
+
+#ifdef CONFIG_PPC_PMAC
+static void ohci_pmac_on(struct pci_dev *dev)
+{
+	if (machine_is(powermac)) {
+		struct device_node *ofn = pci_device_to_OF_node(dev);
+
+		if (ofn) {
+			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
+			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+		}
+	}
+}
+
+static void ohci_pmac_off(struct pci_dev *dev)
+{
+	if (machine_is(powermac)) {
+		struct device_node *ofn = pci_device_to_OF_node(dev);
+
+		if (ofn) {
+			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
+		}
+	}
+}
+#else
+#define ohci_pmac_on(dev)
+#define ohci_pmac_off(dev)
+#endif /* CONFIG_PPC_PMAC */
+
+#define PCI_VENDOR_ID_AGERE		PCI_VENDOR_ID_ATT
+#define PCI_DEVICE_ID_AGERE_FW643	0x5901
+
+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, version;
+	u64 guid;
+	int err;
+	size_t size;
+
+	ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
+	if (ohci == NULL) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
+
+	ohci_pmac_on(dev);
+
+	err = pci_enable_device(dev);
+	if (err) {
+		fw_error("Failed to enable OHCI hardware\n");
+		goto fail_free;
+	}
+
+	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;
+	}
+
+	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
+	ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
+
+	/* dual-buffer mode is broken if more than one IR context is active */
+	if (dev->vendor == PCI_VENDOR_ID_AGERE &&
+	    dev->device == PCI_DEVICE_ID_AGERE_FW643)
+		ohci->use_dualbuffer = false;
+
+	/* dual-buffer mode is broken */
+	if (dev->vendor == PCI_VENDOR_ID_RICOH &&
+	    dev->device == PCI_DEVICE_ID_RICOH_R5C832)
+		ohci->use_dualbuffer = false;
+
+/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
+#if !defined(CONFIG_X86_32)
+	/* dual-buffer mode is broken with descriptor addresses above 2G */
+	if (dev->vendor == PCI_VENDOR_ID_TI &&
+	    dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
+		ohci->use_dualbuffer = false;
+#endif
+
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
+	ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
+			     dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
+#endif
+	ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
+
+	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,
+		     OHCI1394_AsReqTrContextControlSet, handle_at_packet);
+
+	context_init(&ohci->at_response_ctx, ohci,
+		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
+
+	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_channels = ~0ULL;
+	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) {
+		err = -ENOMEM;
+		goto fail_contexts;
+	}
+
+	/* 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) {
+		err = -ENOMEM;
+		goto fail_contexts;
+	}
+
+	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)
+		goto fail_self_id;
+
+	fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
+		  dev_name(&dev->dev), version >> 16, 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_contexts:
+	kfree(ohci->ir_context_list);
+	kfree(ohci->it_context_list);
+	context_release(&ohci->at_response_ctx);
+	context_release(&ohci->at_request_ctx);
+	ar_context_release(&ohci->ar_response_ctx);
+	ar_context_release(&ohci->ar_request_ctx);
+	pci_iounmap(dev, ohci->registers);
+ fail_iomem:
+	pci_release_region(dev, 0);
+ fail_disable:
+	pci_disable_device(dev);
+ fail_free:
+	kfree(&ohci->card);
+	ohci_pmac_off(dev);
+ fail:
+	if (err == -ENOMEM)
+		fw_error("Out of memory\n");
+
+	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);
+
+	if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom)
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  ohci->next_config_rom, ohci->next_config_rom_bus);
+	if (ohci->config_rom)
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  ohci->config_rom, ohci->config_rom_bus);
+	dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
+			  ohci->self_id_cpu, ohci->self_id_bus);
+	ar_context_release(&ohci->ar_request_ctx);
+	ar_context_release(&ohci->ar_response_ctx);
+	context_release(&ohci->at_request_ctx);
+	context_release(&ohci->at_response_ctx);
+	kfree(ohci->it_context_list);
+	kfree(ohci->ir_context_list);
+	pci_iounmap(dev, ohci->registers);
+	pci_release_region(dev, 0);
+	pci_disable_device(dev);
+	kfree(&ohci->card);
+	ohci_pmac_off(dev);
+
+	fw_notify("Removed fw-ohci device.\n");
+}
+
+#ifdef CONFIG_PM
+static int pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	struct fw_ohci *ohci = pci_get_drvdata(dev);
+	int err;
+
+	software_reset(ohci);
+	free_irq(dev->irq, ohci);
+	err = pci_save_state(dev);
+	if (err) {
+		fw_error("pci_save_state failed\n");
+		return err;
+	}
+	err = pci_set_power_state(dev, pci_choose_state(dev, state));
+	if (err)
+		fw_error("pci_set_power_state failed with %d\n", err);
+	ohci_pmac_off(dev);
+
+	return 0;
+}
+
+static int pci_resume(struct pci_dev *dev)
+{
+	struct fw_ohci *ohci = pci_get_drvdata(dev);
+	int err;
+
+	ohci_pmac_on(dev);
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+	err = pci_enable_device(dev);
+	if (err) {
+		fw_error("pci_enable_device failed\n");
+		return err;
+	}
+
+	return ohci_enable(&ohci->card, NULL, 0);
+}
+#endif
+
+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,
+#ifdef CONFIG_PM
+	.resume		= pci_resume,
+	.suspend	= pci_suspend,
+#endif
+};
+
+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 -druN linux-libre-2.6.30-gnu/drivers/firewire/ohci.h linux-libre-2.6.31-gnu/drivers/firewire/ohci.h
--- linux-libre-2.6.30-gnu/drivers/firewire/ohci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/ohci.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,157 @@
+#ifndef _FIREWIRE_OHCI_H
+#define _FIREWIRE_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_SelfIDCount_selfIDError	0x80000000
+#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_NodeID_nodeNumber          0x0000003f
+#define   OHCI1394_NodeID_busNumber           0x0000ffc0
+#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_regAccessFail		0x00040000
+#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 /* _FIREWIRE_OHCI_H */
diff -druN linux-libre-2.6.30-gnu/drivers/firewire/sbp2.c linux-libre-2.6.31-gnu/drivers/firewire/sbp2.c
--- linux-libre-2.6.30-gnu/drivers/firewire/sbp2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/firewire/sbp2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1664 @@
+/*
+ * 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/blkdev.h>
+#include <linux/bug.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/workqueue.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+/*
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
+ *
+ * Concurrent logins are useful together with cluster filesystems.
+ */
+static int sbp2_param_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+		 "(default = Y, use N for concurrent initiators)");
+
+/*
+ * Flags for firmware oddities
+ *
+ * - 128kB max transfer
+ *   Limit transfer size. Necessary for some old bridges.
+ *
+ * - 36 byte inquiry
+ *   When scsi_mod probes the device, let the inquiry command look like that
+ *   from MS Windows.
+ *
+ * - skip mode page 8
+ *   Suppress sending of mode_sense for mode page 8 if the device pretends to
+ *   support the SCSI Primary Block commands instead of Reduced Block Commands.
+ *
+ * - fix capacity
+ *   Tell sd_mod to correct the last sector number reported by read_capacity.
+ *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
+ *   Don't use this with devices which don't have this bug.
+ *
+ * - delay inquiry
+ *   Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
+ *
+ * - power condition
+ *   Set the power condition field in the START STOP UNIT commands sent by
+ *   sd_mod on suspend, resume, and shutdown (if manage_start_stop is on).
+ *   Some disks need this to spin down or to resume properly.
+ *
+ * - override internal blacklist
+ *   Instead of adding to the built-in blacklist, use only the workarounds
+ *   specified in the module load parameter.
+ *   Useful if a blacklist entry interfered with a non-broken device.
+ */
+#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_DELAY_INQUIRY	0x10
+#define SBP2_INQUIRY_DELAY		12
+#define SBP2_WORKAROUND_POWER_CONDITION	0x20
+#define SBP2_WORKAROUND_OVERRIDE	0x100
+
+static int sbp2_param_workarounds;
+module_param_named(workarounds, sbp2_param_workarounds, int, 0644);
+MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
+	", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
+	", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
+	", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
+	", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
+	", delay inquiry = "      __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
+	", set power condition in start stop unit = "
+				  __stringify(SBP2_WORKAROUND_POWER_CONDITION)
+	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
+	", or a combination)");
+
+/* 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";
+
+/*
+ * We create one struct sbp2_logical_unit per SBP-2 Logical Unit Number Entry
+ * and one struct scsi_device per sbp2_logical_unit.
+ */
+struct sbp2_logical_unit {
+	struct sbp2_target *tgt;
+	struct list_head link;
+	struct fw_address_handler address_handler;
+	struct list_head orb_list;
+
+	u64 command_block_agent_address;
+	u16 lun;
+	int login_id;
+
+	/*
+	 * The generation is updated once we've logged in or reconnected
+	 * to the logical unit.  Thus, I/O to the device will automatically
+	 * fail and get retried if it happens in a window where the device
+	 * is not ready, e.g. after a bus reset but before we reconnect.
+	 */
+	int generation;
+	int retries;
+	struct delayed_work work;
+	bool has_sdev;
+	bool blocked;
+};
+
+/*
+ * We create one struct sbp2_target per IEEE 1212 Unit Directory
+ * and one struct Scsi_Host per sbp2_target.
+ */
+struct sbp2_target {
+	struct kref kref;
+	struct fw_unit *unit;
+	const char *bus_id;
+	struct list_head lu_list;
+
+	u64 management_agent_address;
+	u64 guid;
+	int directory_id;
+	int node_id;
+	int address_high;
+	unsigned int workarounds;
+	unsigned int mgt_orb_timeout;
+	unsigned int max_payload;
+
+	int dont_block;	/* counter for each logical unit */
+	int blocked;	/* ditto */
+};
+
+static struct fw_device *target_device(struct sbp2_target *tgt)
+{
+	return fw_parent_device(tgt->unit);
+}
+
+/* Impossible login_id, to detect logout attempt before successful login */
+#define INVALID_LOGIN_ID 0x10000
+
+/*
+ * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
+ * provided in the config rom. Most devices do provide a value, which
+ * we'll use for login management orbs, but with some sane limits.
+ */
+#define SBP2_MIN_LOGIN_ORB_TIMEOUT	5000U	/* Timeout in ms */
+#define SBP2_MAX_LOGIN_ORB_TIMEOUT	40000U	/* Timeout in ms */
+#define SBP2_ORB_TIMEOUT		2000U	/* Timeout in ms */
+#define SBP2_ORB_NULL			0x80000000
+#define SBP2_RETRY_LIMIT		0xf		/* 15 retries */
+#define SBP2_CYCLE_LIMIT		(0xc8 << 12)	/* 200 125us cycles */
+
+/*
+ * There is no transport protocol limit to the CDB length,  but we implement
+ * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
+ */
+#define SBP2_MAX_CDB_SIZE		16
+
+/*
+ * The default maximum s/g segment size of a FireWire controller is
+ * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
+ * be quadlet-aligned, we set the length limit to 0xffff & ~3.
+ */
+#define SBP2_MAX_SEG_SIZE		0xfffc
+
+/* Unit directory keys */
+#define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
+#define SBP2_CSR_FIRMWARE_REVISION	0x3c
+#define SBP2_CSR_LOGICAL_UNIT_NUMBER	0x14
+#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY	0xd4
+
+/* 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 {
+	__be32 high;
+	__be32 low;
+};
+
+struct sbp2_orb {
+	struct fw_transaction t;
+	struct kref kref;
+	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(v)		((v) ? 1 << 28 : 0)
+#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;
+		__be32 misc;
+		__be32 length;
+		struct sbp2_pointer status_fifo;
+	} request;
+	__be32 response[4];
+	dma_addr_t response_bus;
+	struct completion done;
+	struct sbp2_status status;
+};
+
+struct sbp2_login_response {
+	__be32 misc;
+	struct sbp2_pointer command_block_agent;
+	__be32 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		((1) << 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;
+		__be32 misc;
+		u8 command_block[SBP2_MAX_CDB_SIZE];
+	} request;
+	struct scsi_cmnd *cmd;
+	scsi_done_fn_t done;
+	struct sbp2_logical_unit *lu;
+
+	struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
+	dma_addr_t page_table_bus;
+};
+
+#define SBP2_ROM_VALUE_WILDCARD ~0         /* match all */
+#define SBP2_ROM_VALUE_MISSING  0xff000000 /* not present in the unit dir. */
+
+/*
+ * 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.
+ */
+static const struct {
+	u32 firmware_revision;
+	u32 model;
+	unsigned int 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 |
+					  SBP2_WORKAROUND_POWER_CONDITION,
+	},
+	/* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
+		.firmware_revision	= 0x002800,
+		.model			= 0x000000,
+		.workarounds		= SBP2_WORKAROUND_DELAY_INQUIRY |
+					  SBP2_WORKAROUND_POWER_CONDITION,
+	},
+	/* Initio bridges, actually only needed for some older ones */ {
+		.firmware_revision	= 0x000200,
+		.model			= SBP2_ROM_VALUE_WILDCARD,
+		.workarounds		= SBP2_WORKAROUND_INQUIRY_36,
+	},
+	/* PL-3507 bridge with Prolific firmware */ {
+		.firmware_revision	= 0x012800,
+		.model			= SBP2_ROM_VALUE_WILDCARD,
+		.workarounds		= SBP2_WORKAROUND_POWER_CONDITION,
+	},
+	/* Symbios bridge */ {
+		.firmware_revision	= 0xa0b800,
+		.model			= SBP2_ROM_VALUE_WILDCARD,
+		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
+	},
+	/* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ {
+		.firmware_revision	= 0x002600,
+		.model			= SBP2_ROM_VALUE_WILDCARD,
+		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
+	},
+	/*
+	 * iPod 2nd generation: needs 128k max transfer size workaround
+	 * iPod 3rd generation: needs fix capacity workaround
+	 */
+	{
+		.firmware_revision	= 0x0a2700,
+		.model			= 0x000000,
+		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS |
+					  SBP2_WORKAROUND_FIX_CAPACITY,
+	},
+	/* iPod 4th generation */ {
+		.firmware_revision	= 0x0a2700,
+		.model			= 0x000021,
+		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
+	},
+	/* iPod mini */ {
+		.firmware_revision	= 0x0a2700,
+		.model			= 0x000022,
+		.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 free_orb(struct kref *kref)
+{
+	struct sbp2_orb *orb = container_of(kref, struct sbp2_orb, kref);
+
+	kfree(orb);
+}
+
+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_logical_unit *lu = 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, &lu->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 != &lu->orb_list) {
+		orb->callback(orb, &status);
+		kref_put(&orb->kref, free_orb);
+	} 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;
+
+	/*
+	 * This is a little tricky.  We can get the status write for
+	 * the orb before we get this callback.  The status write
+	 * handler above will assume the orb pointer transaction was
+	 * successful and set the rcode to RCODE_COMPLETE for the orb.
+	 * So this callback only sets the rcode if it hasn't already
+	 * been set and only does the cleanup if the transaction
+	 * failed and we didn't already get a status write.
+	 */
+	spin_lock_irqsave(&card->lock, flags);
+
+	if (orb->rcode == -1)
+		orb->rcode = rcode;
+	if (orb->rcode != RCODE_COMPLETE) {
+		list_del(&orb->link);
+		spin_unlock_irqrestore(&card->lock, flags);
+		orb->callback(orb, NULL);
+	} else {
+		spin_unlock_irqrestore(&card->lock, flags);
+	}
+
+	kref_put(&orb->kref, free_orb);
+}
+
+static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
+			  int node_id, int generation, u64 offset)
+{
+	struct fw_device *device = target_device(lu->tgt);
+	unsigned long flags;
+
+	orb->pointer.high = 0;
+	orb->pointer.low = cpu_to_be32(orb->request_bus);
+
+	spin_lock_irqsave(&device->card->lock, flags);
+	list_add_tail(&orb->link, &lu->orb_list);
+	spin_unlock_irqrestore(&device->card->lock, flags);
+
+	/* Take a ref for the orb list and for the transaction callback. */
+	kref_get(&orb->kref);
+	kref_get(&orb->kref);
+
+	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
+			node_id, generation, device->max_speed, offset,
+			&orb->pointer, sizeof(orb->pointer),
+			complete_transaction, orb);
+}
+
+static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
+{
+	struct fw_device *device = target_device(lu->tgt);
+	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(&lu->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 =
+		container_of(base_orb, struct sbp2_management_orb, base);
+
+	if (status)
+		memcpy(&orb->status, status, sizeof(*status));
+	complete(&orb->done);
+}
+
+static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+				    int generation, int function,
+				    int lun_or_login_id, void *response)
+{
+	struct fw_device *device = target_device(lu->tgt);
+	struct sbp2_management_orb *orb;
+	unsigned int timeout;
+	int retval = -ENOMEM;
+
+	if (function == SBP2_LOGOUT_REQUEST && fw_device_is_shutdown(device))
+		return 0;
+
+	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
+	if (orb == NULL)
+		return -ENOMEM;
+
+	kref_init(&orb->base.kref);
+	orb->response_bus =
+		dma_map_single(device->card->device, &orb->response,
+			       sizeof(orb->response), DMA_FROM_DEVICE);
+	if (dma_mapping_error(device->card->device, orb->response_bus))
+		goto fail_mapping_response;
+
+	orb->request.response.high = 0;
+	orb->request.response.low  = cpu_to_be32(orb->response_bus);
+
+	orb->request.misc = cpu_to_be32(
+		MANAGEMENT_ORB_NOTIFY |
+		MANAGEMENT_ORB_FUNCTION(function) |
+		MANAGEMENT_ORB_LUN(lun_or_login_id));
+	orb->request.length = cpu_to_be32(
+		MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)));
+
+	orb->request.status_fifo.high =
+		cpu_to_be32(lu->address_handler.offset >> 32);
+	orb->request.status_fifo.low  =
+		cpu_to_be32(lu->address_handler.offset);
+
+	if (function == SBP2_LOGIN_REQUEST) {
+		/* Ask for 2^2 == 4 seconds reconnect grace period */
+		orb->request.misc |= cpu_to_be32(
+			MANAGEMENT_ORB_RECONNECT(2) |
+			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login));
+		timeout = lu->tgt->mgt_orb_timeout;
+	} else {
+		timeout = SBP2_ORB_TIMEOUT;
+	}
+
+	init_completion(&orb->done);
+	orb->base.callback = complete_management_orb;
+
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(device->card->device, orb->base.request_bus))
+		goto fail_mapping_request;
+
+	sbp2_send_orb(&orb->base, lu, node_id, generation,
+		      lu->tgt->management_agent_address);
+
+	wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout));
+
+	retval = -EIO;
+	if (sbp2_cancel_orbs(lu) == 0) {
+		fw_error("%s: orb reply timed out, rcode=0x%02x\n",
+			 lu->tgt->bus_id, orb->base.rcode);
+		goto out;
+	}
+
+	if (orb->base.rcode != RCODE_COMPLETE) {
+		fw_error("%s: management write failed, rcode 0x%02x\n",
+			 lu->tgt->bus_id, orb->base.rcode);
+		goto out;
+	}
+
+	if (STATUS_GET_RESPONSE(orb->status) != 0 ||
+	    STATUS_GET_SBP_STATUS(orb->status) != 0) {
+		fw_error("%s: error status: %d:%d\n", lu->tgt->bus_id,
+			 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);
+ fail_mapping_request:
+	dma_unmap_single(device->card->device, orb->response_bus,
+			 sizeof(orb->response), DMA_FROM_DEVICE);
+ fail_mapping_response:
+	if (response)
+		memcpy(response, orb->response, sizeof(orb->response));
+	kref_put(&orb->base.kref, free_orb);
+
+	return retval;
+}
+
+static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
+{
+	struct fw_device *device = target_device(lu->tgt);
+	__be32 d = 0;
+
+	fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
+			   lu->tgt->node_id, lu->generation, device->max_speed,
+			   lu->command_block_agent_address + SBP2_AGENT_RESET,
+			   &d, sizeof(d));
+}
+
+static void complete_agent_reset_write_no_wait(struct fw_card *card,
+		int rcode, void *payload, size_t length, void *data)
+{
+	kfree(data);
+}
+
+static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
+{
+	struct fw_device *device = target_device(lu->tgt);
+	struct fw_transaction *t;
+	static __be32 d;
+
+	t = kmalloc(sizeof(*t), GFP_ATOMIC);
+	if (t == NULL)
+		return;
+
+	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
+			lu->tgt->node_id, lu->generation, device->max_speed,
+			lu->command_block_agent_address + SBP2_AGENT_RESET,
+			&d, sizeof(d), complete_agent_reset_write_no_wait, t);
+}
+
+static inline void sbp2_allow_block(struct sbp2_logical_unit *lu)
+{
+	/*
+	 * We may access dont_block without taking card->lock here:
+	 * All callers of sbp2_allow_block() and all callers of sbp2_unblock()
+	 * are currently serialized against each other.
+	 * And a wrong result in sbp2_conditionally_block()'s access of
+	 * dont_block is rather harmless, it simply misses its first chance.
+	 */
+	--lu->tgt->dont_block;
+}
+
+/*
+ * Blocks lu->tgt if all of the following conditions are met:
+ *   - Login, INQUIRY, and high-level SCSI setup of all of the target's
+ *     logical units have been finished (indicated by dont_block == 0).
+ *   - lu->generation is stale.
+ *
+ * Note, scsi_block_requests() must be called while holding card->lock,
+ * otherwise it might foil sbp2_[conditionally_]unblock()'s attempt to
+ * unblock the target.
+ */
+static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
+{
+	struct sbp2_target *tgt = lu->tgt;
+	struct fw_card *card = target_device(tgt)->card;
+	struct Scsi_Host *shost =
+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+	if (!tgt->dont_block && !lu->blocked &&
+	    lu->generation != card->generation) {
+		lu->blocked = true;
+		if (++tgt->blocked == 1)
+			scsi_block_requests(shost);
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+}
+
+/*
+ * Unblocks lu->tgt as soon as all its logical units can be unblocked.
+ * Note, it is harmless to run scsi_unblock_requests() outside the
+ * card->lock protected section.  On the other hand, running it inside
+ * the section might clash with shost->host_lock.
+ */
+static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
+{
+	struct sbp2_target *tgt = lu->tgt;
+	struct fw_card *card = target_device(tgt)->card;
+	struct Scsi_Host *shost =
+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	unsigned long flags;
+	bool unblock = false;
+
+	spin_lock_irqsave(&card->lock, flags);
+	if (lu->blocked && lu->generation == card->generation) {
+		lu->blocked = false;
+		unblock = --tgt->blocked == 0;
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	if (unblock)
+		scsi_unblock_requests(shost);
+}
+
+/*
+ * Prevents future blocking of tgt and unblocks it.
+ * Note, it is harmless to run scsi_unblock_requests() outside the
+ * card->lock protected section.  On the other hand, running it inside
+ * the section might clash with shost->host_lock.
+ */
+static void sbp2_unblock(struct sbp2_target *tgt)
+{
+	struct fw_card *card = target_device(tgt)->card;
+	struct Scsi_Host *shost =
+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+	++tgt->dont_block;
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	scsi_unblock_requests(shost);
+}
+
+static int sbp2_lun2int(u16 lun)
+{
+	struct scsi_lun eight_bytes_lun;
+
+	memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun));
+	eight_bytes_lun.scsi_lun[0] = (lun >> 8) & 0xff;
+	eight_bytes_lun.scsi_lun[1] = lun & 0xff;
+
+	return scsilun_to_int(&eight_bytes_lun);
+}
+
+static void sbp2_release_target(struct kref *kref)
+{
+	struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
+	struct sbp2_logical_unit *lu, *next;
+	struct Scsi_Host *shost =
+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	struct scsi_device *sdev;
+	struct fw_device *device = target_device(tgt);
+
+	/* prevent deadlocks */
+	sbp2_unblock(tgt);
+
+	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
+		if (sdev) {
+			scsi_remove_device(sdev);
+			scsi_device_put(sdev);
+		}
+		if (lu->login_id != INVALID_LOGIN_ID) {
+			int generation, node_id;
+			/*
+			 * tgt->node_id may be obsolete here if we failed
+			 * during initial login or after a bus reset where
+			 * the topology changed.
+			 */
+			generation = device->generation;
+			smp_rmb(); /* node_id vs. generation */
+			node_id    = device->node_id;
+			sbp2_send_management_orb(lu, node_id, generation,
+						 SBP2_LOGOUT_REQUEST,
+						 lu->login_id, NULL);
+		}
+		fw_core_remove_address_handler(&lu->address_handler);
+		list_del(&lu->link);
+		kfree(lu);
+	}
+	scsi_remove_host(shost);
+	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
+
+	fw_unit_put(tgt->unit);
+	scsi_host_put(shost);
+	fw_device_put(device);
+}
+
+static struct workqueue_struct *sbp2_wq;
+
+static void sbp2_target_put(struct sbp2_target *tgt)
+{
+	kref_put(&tgt->kref, sbp2_release_target);
+}
+
+/*
+ * Always get the target's kref when scheduling work on one its units.
+ * Each workqueue job is responsible to call sbp2_target_put() upon return.
+ */
+static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
+{
+	kref_get(&lu->tgt->kref);
+	if (!queue_delayed_work(sbp2_wq, &lu->work, delay))
+		sbp2_target_put(lu->tgt);
+}
+
+/*
+ * Write retransmit retry values into the BUSY_TIMEOUT register.
+ * - The single-phase retry protocol is supported by all SBP-2 devices, but the
+ *   default retry_limit value is 0 (i.e. never retry transmission). We write a
+ *   saner value after logging into the device.
+ * - The dual-phase retry protocol is optional to implement, and if not
+ *   supported, writes to the dual-phase portion of the register will be
+ *   ignored. We try to write the original 1394-1995 default here.
+ * - In the case of devices that are also SBP-3-compliant, all writes are
+ *   ignored, as the register is read-only, but contains single-phase retry of
+ *   15, which is what we're trying to set for all SBP-2 device anyway, so this
+ *   write attempt is safe and yields more consistent behavior for all devices.
+ *
+ * See section 8.3.2.3.5 of the 1394-1995 spec, section 6.2 of the SBP-2 spec,
+ * and section 6.4 of the SBP-3 spec for further details.
+ */
+static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
+{
+	struct fw_device *device = target_device(lu->tgt);
+	__be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
+
+	fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
+			   lu->tgt->node_id, lu->generation, device->max_speed,
+			   CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT,
+			   &d, sizeof(d));
+}
+
+static void sbp2_reconnect(struct work_struct *work);
+
+static void sbp2_login(struct work_struct *work)
+{
+	struct sbp2_logical_unit *lu =
+		container_of(work, struct sbp2_logical_unit, work.work);
+	struct sbp2_target *tgt = lu->tgt;
+	struct fw_device *device = target_device(tgt);
+	struct Scsi_Host *shost;
+	struct scsi_device *sdev;
+	struct sbp2_login_response response;
+	int generation, node_id, local_node_id;
+
+	if (fw_device_is_shutdown(device))
+		goto out;
+
+	generation    = device->generation;
+	smp_rmb();    /* node IDs must not be older than generation */
+	node_id       = device->node_id;
+	local_node_id = device->card->node_id;
+
+	/* If this is a re-login attempt, log out, or we might be rejected. */
+	if (lu->has_sdev)
+		sbp2_send_management_orb(lu, device->node_id, generation,
+				SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
+
+	if (sbp2_send_management_orb(lu, node_id, generation,
+				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
+		if (lu->retries++ < 5) {
+			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+		} else {
+			fw_error("%s: failed to login to LUN %04x\n",
+				 tgt->bus_id, lu->lun);
+			/* Let any waiting I/O fail from now on. */
+			sbp2_unblock(lu->tgt);
+		}
+		goto out;
+	}
+
+	tgt->node_id	  = node_id;
+	tgt->address_high = local_node_id << 16;
+	smp_wmb();	  /* node IDs must not be older than generation */
+	lu->generation	  = generation;
+
+	lu->command_block_agent_address =
+		((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff)
+		      << 32) | be32_to_cpu(response.command_block_agent.low);
+	lu->login_id = be32_to_cpu(response.misc) & 0xffff;
+
+	fw_notify("%s: logged in to LUN %04x (%d retries)\n",
+		  tgt->bus_id, lu->lun, lu->retries);
+
+	/* set appropriate retry limit(s) in BUSY_TIMEOUT register */
+	sbp2_set_busy_timeout(lu);
+
+	PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
+	sbp2_agent_reset(lu);
+
+	/* This was a re-login. */
+	if (lu->has_sdev) {
+		sbp2_cancel_orbs(lu);
+		sbp2_conditionally_unblock(lu);
+		goto out;
+	}
+
+	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
+		ssleep(SBP2_INQUIRY_DELAY);
+
+	shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	sdev = __scsi_add_device(shost, 0, 0, sbp2_lun2int(lu->lun), lu);
+	/*
+	 * FIXME:  We are unable to perform reconnects while in sbp2_login().
+	 * Therefore __scsi_add_device() will get into trouble if a bus reset
+	 * happens in parallel.  It will either fail or leave us with an
+	 * unusable sdev.  As a workaround we check for this and retry the
+	 * whole login and SCSI probing.
+	 */
+
+	/* Reported error during __scsi_add_device() */
+	if (IS_ERR(sdev))
+		goto out_logout_login;
+
+	/* Unreported error during __scsi_add_device() */
+	smp_rmb(); /* get current card generation */
+	if (generation != device->card->generation) {
+		scsi_remove_device(sdev);
+		scsi_device_put(sdev);
+		goto out_logout_login;
+	}
+
+	/* No error during __scsi_add_device() */
+	lu->has_sdev = true;
+	scsi_device_put(sdev);
+	sbp2_allow_block(lu);
+	goto out;
+
+ out_logout_login:
+	smp_rmb(); /* generation may have changed */
+	generation = device->generation;
+	smp_rmb(); /* node_id must not be older than generation */
+
+	sbp2_send_management_orb(lu, device->node_id, generation,
+				 SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
+	/*
+	 * If a bus reset happened, sbp2_update will have requeued
+	 * lu->work already.  Reset the work from reconnect to login.
+	 */
+	PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+ out:
+	sbp2_target_put(tgt);
+}
+
+static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
+{
+	struct sbp2_logical_unit *lu;
+
+	lu = kmalloc(sizeof(*lu), GFP_KERNEL);
+	if (!lu)
+		return -ENOMEM;
+
+	lu->address_handler.length           = 0x100;
+	lu->address_handler.address_callback = sbp2_status_write;
+	lu->address_handler.callback_data    = lu;
+
+	if (fw_core_add_address_handler(&lu->address_handler,
+					&fw_high_memory_region) < 0) {
+		kfree(lu);
+		return -ENOMEM;
+	}
+
+	lu->tgt      = tgt;
+	lu->lun      = lun_entry & 0xffff;
+	lu->login_id = INVALID_LOGIN_ID;
+	lu->retries  = 0;
+	lu->has_sdev = false;
+	lu->blocked  = false;
+	++tgt->dont_block;
+	INIT_LIST_HEAD(&lu->orb_list);
+	INIT_DELAYED_WORK(&lu->work, sbp2_login);
+
+	list_add_tail(&lu->link, &tgt->lu_list);
+	return 0;
+}
+
+static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory)
+{
+	struct fw_csr_iterator ci;
+	int key, value;
+
+	fw_csr_iterator_init(&ci, directory);
+	while (fw_csr_iterator_next(&ci, &key, &value))
+		if (key == SBP2_CSR_LOGICAL_UNIT_NUMBER &&
+		    sbp2_add_logical_unit(tgt, value) < 0)
+			return -ENOMEM;
+	return 0;
+}
+
+static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
+			      u32 *model, u32 *firmware_revision)
+{
+	struct fw_csr_iterator ci;
+	int key, value;
+	unsigned int timeout;
+
+	fw_csr_iterator_init(&ci, directory);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		switch (key) {
+
+		case CSR_DEPENDENT_INFO | CSR_OFFSET:
+			tgt->management_agent_address =
+					CSR_REGISTER_BASE + 4 * value;
+			break;
+
+		case CSR_DIRECTORY_ID:
+			tgt->directory_id = value;
+			break;
+
+		case CSR_MODEL:
+			*model = value;
+			break;
+
+		case SBP2_CSR_FIRMWARE_REVISION:
+			*firmware_revision = value;
+			break;
+
+		case SBP2_CSR_UNIT_CHARACTERISTICS:
+			/* the timeout value is stored in 500ms units */
+			timeout = ((unsigned int) value >> 8 & 0xff) * 500;
+			timeout = max(timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT);
+			tgt->mgt_orb_timeout =
+				  min(timeout, SBP2_MAX_LOGIN_ORB_TIMEOUT);
+
+			if (timeout > tgt->mgt_orb_timeout)
+				fw_notify("%s: config rom contains %ds "
+					  "management ORB timeout, limiting "
+					  "to %ds\n", tgt->bus_id,
+					  timeout / 1000,
+					  tgt->mgt_orb_timeout / 1000);
+			break;
+
+		case SBP2_CSR_LOGICAL_UNIT_NUMBER:
+			if (sbp2_add_logical_unit(tgt, value) < 0)
+				return -ENOMEM;
+			break;
+
+		case SBP2_CSR_LOGICAL_UNIT_DIRECTORY:
+			/* Adjust for the increment in the iterator */
+			if (sbp2_scan_logical_unit_dir(tgt, ci.p - 1 + value) < 0)
+				return -ENOMEM;
+			break;
+		}
+	}
+	return 0;
+}
+
+static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
+				  u32 firmware_revision)
+{
+	int i;
+	unsigned int w = sbp2_param_workarounds;
+
+	if (w)
+		fw_notify("Please notify linux1394-devel@lists.sourceforge.net "
+			  "if you need the workarounds parameter for %s\n",
+			  tgt->bus_id);
+
+	if (w & SBP2_WORKAROUND_OVERRIDE)
+		goto out;
+
+	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 != SBP2_ROM_VALUE_WILDCARD)
+			continue;
+
+		w |= sbp2_workarounds_table[i].workarounds;
+		break;
+	}
+ out:
+	if (w)
+		fw_notify("Workarounds for %s: 0x%x "
+			  "(firmware_revision 0x%06x, model_id 0x%06x)\n",
+			  tgt->bus_id, w, firmware_revision, model);
+	tgt->workarounds = w;
+}
+
+static struct scsi_host_template scsi_driver_template;
+
+static int sbp2_probe(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_device *device = fw_parent_device(unit);
+	struct sbp2_target *tgt;
+	struct sbp2_logical_unit *lu;
+	struct Scsi_Host *shost;
+	u32 model, firmware_revision;
+
+	if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
+		BUG_ON(dma_set_max_seg_size(device->card->device,
+					    SBP2_MAX_SEG_SIZE));
+
+	shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
+	if (shost == NULL)
+		return -ENOMEM;
+
+	tgt = (struct sbp2_target *)shost->hostdata;
+	dev_set_drvdata(&unit->device, tgt);
+	tgt->unit = unit;
+	kref_init(&tgt->kref);
+	INIT_LIST_HEAD(&tgt->lu_list);
+	tgt->bus_id = dev_name(&unit->device);
+	tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
+
+	if (fw_device_enable_phys_dma(device) < 0)
+		goto fail_shost_put;
+
+	shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
+
+	if (scsi_add_host(shost, &unit->device) < 0)
+		goto fail_shost_put;
+
+	fw_device_get(device);
+	fw_unit_get(unit);
+
+	/* implicit directory ID */
+	tgt->directory_id = ((unit->directory - device->config_rom) * 4
+			     + CSR_CONFIG_ROM) & 0xffffff;
+
+	firmware_revision = SBP2_ROM_VALUE_MISSING;
+	model		  = SBP2_ROM_VALUE_MISSING;
+
+	if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
+			       &firmware_revision) < 0)
+		goto fail_tgt_put;
+
+	sbp2_init_workarounds(tgt, model, firmware_revision);
+
+	/*
+	 * At S100 we can do 512 bytes per packet, at S200 1024 bytes,
+	 * and so on up to 4096 bytes.  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.
+	 */
+	tgt->max_payload = min(device->max_speed + 7, 10U);
+	tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1);
+
+	/* Do the login in a workqueue so we can easily reschedule retries. */
+	list_for_each_entry(lu, &tgt->lu_list, link)
+		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+	return 0;
+
+ fail_tgt_put:
+	sbp2_target_put(tgt);
+	return -ENOMEM;
+
+ fail_shost_put:
+	scsi_host_put(shost);
+	return -ENOMEM;
+}
+
+static int sbp2_remove(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
+
+	sbp2_target_put(tgt);
+	return 0;
+}
+
+static void sbp2_reconnect(struct work_struct *work)
+{
+	struct sbp2_logical_unit *lu =
+		container_of(work, struct sbp2_logical_unit, work.work);
+	struct sbp2_target *tgt = lu->tgt;
+	struct fw_device *device = target_device(tgt);
+	int generation, node_id, local_node_id;
+
+	if (fw_device_is_shutdown(device))
+		goto out;
+
+	generation    = device->generation;
+	smp_rmb();    /* node IDs must not be older than generation */
+	node_id       = device->node_id;
+	local_node_id = device->card->node_id;
+
+	if (sbp2_send_management_orb(lu, node_id, generation,
+				     SBP2_RECONNECT_REQUEST,
+				     lu->login_id, NULL) < 0) {
+		/*
+		 * If reconnect was impossible even though we are in the
+		 * current generation, fall back and try to log in again.
+		 *
+		 * We could check for "Function rejected" status, but
+		 * looking at the bus generation as simpler and more general.
+		 */
+		smp_rmb(); /* get current card generation */
+		if (generation == device->card->generation ||
+		    lu->retries++ >= 5) {
+			fw_error("%s: failed to reconnect\n", tgt->bus_id);
+			lu->retries = 0;
+			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+		}
+		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+		goto out;
+	}
+
+	tgt->node_id      = node_id;
+	tgt->address_high = local_node_id << 16;
+	smp_wmb();	  /* node IDs must not be older than generation */
+	lu->generation	  = generation;
+
+	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
+		  tgt->bus_id, lu->lun, lu->retries);
+
+	sbp2_agent_reset(lu);
+	sbp2_cancel_orbs(lu);
+	sbp2_conditionally_unblock(lu);
+ out:
+	sbp2_target_put(tgt);
+}
+
+static void sbp2_update(struct fw_unit *unit)
+{
+	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
+	struct sbp2_logical_unit *lu;
+
+	fw_device_enable_phys_dma(fw_parent_device(unit));
+
+	/*
+	 * Fw-core serializes sbp2_update() against sbp2_remove().
+	 * Iteration over tgt->lu_list is therefore safe here.
+	 */
+	list_for_each_entry(lu, &tgt->lu_list, link) {
+		sbp2_conditionally_block(lu);
+		lu->retries = 0;
+		sbp2_queue_work(lu, 0);
+	}
+}
+
+#define SBP2_UNIT_SPEC_ID_ENTRY	0x0000609e
+#define SBP2_SW_VERSION_ENTRY	0x00010483
+
+static const struct ieee1394_device_id sbp2_id_table[] = {
+	{
+		.match_flags  = IEEE1394_MATCH_SPECIFIER_ID |
+				IEEE1394_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 void sbp2_unmap_scatterlist(struct device *card_device,
+				   struct sbp2_command_orb *orb)
+{
+	if (scsi_sg_count(orb->cmd))
+		dma_unmap_sg(card_device, scsi_sglist(orb->cmd),
+			     scsi_sg_count(orb->cmd),
+			     orb->cmd->sc_data_direction);
+
+	if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT))
+		dma_unmap_single(card_device, orb->page_table_bus,
+				 sizeof(orb->page_table), DMA_TO_DEVICE);
+}
+
+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 =
+		container_of(base_orb, struct sbp2_command_orb, base);
+	struct fw_device *device = target_device(orb->lu->tgt);
+	int result;
+
+	if (status != NULL) {
+		if (STATUS_GET_DEAD(*status))
+			sbp2_agent_reset_no_wait(orb->lu);
+
+		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;
+		sbp2_conditionally_block(orb->lu);
+	}
+
+	dma_unmap_single(device->card->device, orb->base.request_bus,
+			 sizeof(orb->request), DMA_TO_DEVICE);
+	sbp2_unmap_scatterlist(device->card->device, orb);
+
+	orb->cmd->result = result;
+	orb->done(orb->cmd);
+}
+
+static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
+		struct fw_device *device, struct sbp2_logical_unit *lu)
+{
+	struct scatterlist *sg = scsi_sglist(orb->cmd);
+	int i, n;
+
+	n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
+		       orb->cmd->sc_data_direction);
+	if (n == 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 (n == 1) {
+		orb->request.data_descriptor.high =
+			cpu_to_be32(lu->tgt->address_high);
+		orb->request.data_descriptor.low  =
+			cpu_to_be32(sg_dma_address(sg));
+		orb->request.misc |=
+			cpu_to_be32(COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)));
+		return 0;
+	}
+
+	for_each_sg(sg, sg, n, i) {
+		orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
+		orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg));
+	}
+
+	orb->page_table_bus =
+		dma_map_single(device->card->device, orb->page_table,
+			       sizeof(orb->page_table), DMA_TO_DEVICE);
+	if (dma_mapping_error(device->card->device, orb->page_table_bus))
+		goto fail_page_table;
+
+	/*
+	 * 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->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
+	orb->request.data_descriptor.low  = cpu_to_be32(orb->page_table_bus);
+	orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
+					 COMMAND_ORB_DATA_SIZE(n));
+
+	return 0;
+
+ fail_page_table:
+	dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
+		     scsi_sg_count(orb->cmd), 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_logical_unit *lu = cmd->device->hostdata;
+	struct fw_device *device = target_device(lu->tgt);
+	struct sbp2_command_orb *orb;
+	int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
+
+	/*
+	 * Bidirectional commands are not yet implemented, and unknown
+	 * transfer direction not handled.
+	 */
+	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
+		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
+		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");
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	/* Initialize rcode to something not RCODE_COMPLETE. */
+	orb->base.rcode = -1;
+	kref_init(&orb->base.kref);
+
+	orb->lu   = lu;
+	orb->done = done;
+	orb->cmd  = cmd;
+
+	orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
+	orb->request.misc = cpu_to_be32(
+		COMMAND_ORB_MAX_PAYLOAD(lu->tgt->max_payload) |
+		COMMAND_ORB_SPEED(device->max_speed) |
+		COMMAND_ORB_NOTIFY);
+
+	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+		orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
+
+	generation = device->generation;
+	smp_rmb();    /* sbp2_map_scatterlist looks at tgt->address_high */
+
+	if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
+		goto out;
+
+	memcpy(orb->request.command_block, cmd->cmnd, cmd->cmd_len);
+
+	orb->base.callback = complete_command_orb;
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(device->card->device, orb->base.request_bus)) {
+		sbp2_unmap_scatterlist(device->card->device, orb);
+		goto out;
+	}
+
+	sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation,
+		      lu->command_block_agent_address + SBP2_ORB_POINTER);
+	retval = 0;
+ out:
+	kref_put(&orb->base.kref, free_orb);
+	return retval;
+}
+
+static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
+{
+	struct sbp2_logical_unit *lu = sdev->hostdata;
+
+	/* (Re-)Adding logical units via the SCSI stack is not supported. */
+	if (!lu)
+		return -ENOSYS;
+
+	sdev->allow_restart = 1;
+
+	/* SBP-2 requires quadlet alignment of the data buffers. */
+	blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
+
+	if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+		sdev->inquiry_len = 36;
+
+	return 0;
+}
+
+static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
+{
+	struct sbp2_logical_unit *lu = sdev->hostdata;
+
+	sdev->use_10_for_rw = 1;
+
+	if (sbp2_param_exclusive_login)
+		sdev->manage_start_stop = 1;
+
+	if (sdev->type == TYPE_ROM)
+		sdev->use_10_for_ms = 1;
+
+	if (sdev->type == TYPE_DISK &&
+	    lu->tgt->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
+		sdev->skip_ms_page_8 = 1;
+
+	if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
+		sdev->fix_capacity = 1;
+
+	if (lu->tgt->workarounds & SBP2_WORKAROUND_POWER_CONDITION)
+		sdev->start_stop_pwr_cond = 1;
+
+	if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
+
+	blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
+
+	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_logical_unit *lu = cmd->device->hostdata;
+
+	fw_notify("%s: sbp2_scsi_abort\n", lu->tgt->bus_id);
+	sbp2_agent_reset(lu);
+	sbp2_cancel_orbs(lu);
+
+	return SUCCESS;
+}
+
+/*
+ * Format of /sys/bus/scsi/devices/.../ieee1394_id:
+ * u64 EUI-64 : u24 directory_ID : u16 LUN  (all printed in hexadecimal)
+ *
+ * This is the concatenation of target port identifier and logical unit
+ * identifier as per SAM-2...SAM-4 annex A.
+ */
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct sbp2_logical_unit *lu;
+
+	if (!sdev)
+		return 0;
+
+	lu = sdev->hostdata;
+
+	return sprintf(buf, "%016llx:%06x:%04x\n",
+			(unsigned long long)lu->tgt->guid,
+			lu->tgt->directory_id, lu->lun);
+}
+
+static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
+
+static struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
+	&dev_attr_ieee1394_id,
+	NULL
+};
+
+static struct scsi_host_template scsi_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "SBP-2 IEEE-1394",
+	.proc_name		= 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,
+	.sdev_attrs		= sbp2_scsi_sysfs_attrs,
+};
+
+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)
+{
+	sbp2_wq = create_singlethread_workqueue(KBUILD_MODNAME);
+	if (!sbp2_wq)
+		return -ENOMEM;
+
+	return driver_register(&sbp2_driver.driver);
+}
+
+static void __exit sbp2_cleanup(void)
+{
+	driver_unregister(&sbp2_driver.driver);
+	destroy_workqueue(sbp2_wq);
+}
+
+module_init(sbp2_init);
+module_exit(sbp2_cleanup);
diff -druN linux-libre-2.6.30-gnu/drivers/firmware/dmi_scan.c linux-libre-2.6.31-gnu/drivers/firmware/dmi_scan.c
--- linux-libre-2.6.30-gnu/drivers/firmware/dmi_scan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firmware/dmi_scan.c	2009-09-09 18:13:59.000000000 -0400
@@ -596,6 +596,7 @@
 
 	return year;
 }
+EXPORT_SYMBOL(dmi_get_year);
 
 /**
  *	dmi_walk - Walk the DMI table and get called back for every record
diff -druN linux-libre-2.6.30-gnu/drivers/firmware/memmap.c linux-libre-2.6.31-gnu/drivers/firmware/memmap.c
--- linux-libre-2.6.30-gnu/drivers/firmware/memmap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firmware/memmap.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,8 +31,12 @@
  * information is necessary as for the resource tree.
  */
 struct firmware_map_entry {
-	resource_size_t		start;	/* start of the memory range */
-	resource_size_t		end;	/* end of the memory range (incl.) */
+	/*
+	 * start and end must be u64 rather than resource_size_t, because e820
+	 * resources can lie at addresses above 4G.
+	 */
+	u64			start;	/* start of the memory range */
+	u64			end;	/* end of the memory range (incl.) */
 	const char		*type;	/* type of the memory range */
 	struct list_head	list;	/* entry for the linked list */
 	struct kobject		kobj;   /* kobject for each entry */
@@ -101,7 +105,7 @@
  * Common implementation of firmware_map_add() and firmware_map_add_early()
  * which expects a pre-allocated struct firmware_map_entry.
  **/
-static int firmware_map_add_entry(resource_size_t start, resource_size_t end,
+static int firmware_map_add_entry(u64 start, u64 end,
 				  const char *type,
 				  struct firmware_map_entry *entry)
 {
@@ -132,8 +136,7 @@
  *
  * Returns 0 on success, or -ENOMEM if no memory could be allocated.
  **/
-int firmware_map_add(resource_size_t start, resource_size_t end,
-		     const char *type)
+int firmware_map_add(u64 start, u64 end, const char *type)
 {
 	struct firmware_map_entry *entry;
 
@@ -157,8 +160,7 @@
  *
  * Returns 0 on success, or -ENOMEM if no memory could be allocated.
  **/
-int __init firmware_map_add_early(resource_size_t start, resource_size_t end,
-				  const char *type)
+int __init firmware_map_add_early(u64 start, u64 end, const char *type)
 {
 	struct firmware_map_entry *entry;
 
diff -druN linux-libre-2.6.30-gnu/drivers/firmware/pcdp.c linux-libre-2.6.31-gnu/drivers/firmware/pcdp.c
--- linux-libre-2.6.30-gnu/drivers/firmware/pcdp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/firmware/pcdp.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,10 +28,10 @@
 	char parity;
 
 	mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
-	p += sprintf(p, "uart8250,%s,0x%lx",
+	p += sprintf(p, "uart8250,%s,0x%llx",
 		mmio ? "mmio" : "io", uart->addr.address);
 	if (uart->baud) {
-		p += sprintf(p, ",%lu", uart->baud);
+		p += sprintf(p, ",%llu", uart->baud);
 		if (uart->bits) {
 			switch (uart->parity) {
 			    case 0x2: parity = 'e'; break;
diff -druN linux-libre-2.6.30-gnu/drivers/gpio/Kconfig linux-libre-2.6.31-gnu/drivers/gpio/Kconfig
--- linux-libre-2.6.30-gnu/drivers/gpio/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpio/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -67,12 +67,24 @@
 
 comment "Memory mapped GPIO expanders:"
 
+config GPIO_PL061
+	bool "PrimeCell PL061 GPIO support"
+	depends on ARM_AMBA
+	help
+	  Say yes here to support the PrimeCell PL061 GPIO device
+
 config GPIO_XILINX
 	bool "Xilinx GPIO support"
-	depends on PPC_OF
+	depends on PPC_OF || MICROBLAZE
 	help
 	  Say yes here to support the Xilinx FPGA GPIO device
 
+config GPIO_VR41XX
+	tristate "NEC VR4100 series General-purpose I/O Uint support"
+	depends on CPU_VR41XX
+	help
+	  Say yes here to support the NEC VR4100 series General-purpose I/O Uint
+
 comment "I2C GPIO expanders:"
 
 config GPIO_MAX732X
diff -druN linux-libre-2.6.30-gnu/drivers/gpio/Makefile linux-libre-2.6.31-gnu/drivers/gpio/Makefile
--- linux-libre-2.6.30-gnu/drivers/gpio/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpio/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,8 @@
 obj-$(CONFIG_GPIO_MCP23S08)	+= mcp23s08.o
 obj-$(CONFIG_GPIO_PCA953X)	+= pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
+obj-$(CONFIG_GPIO_PL061)	+= pl061.o
 obj-$(CONFIG_GPIO_TWL4030)	+= twl4030-gpio.o
 obj-$(CONFIG_GPIO_XILINX)	+= xilinx_gpio.o
 obj-$(CONFIG_GPIO_BT8XX)	+= bt8xxgpio.o
+obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o
diff -druN linux-libre-2.6.30-gnu/drivers/gpio/max7301.c linux-libre-2.6.31-gnu/drivers/gpio/max7301.c
--- linux-libre-2.6.30-gnu/drivers/gpio/max7301.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpio/max7301.c	2009-09-09 18:13:59.000000000 -0400
@@ -287,7 +287,7 @@
 	return ret;
 }
 
-static int max7301_remove(struct spi_device *spi)
+static int __devexit max7301_remove(struct spi_device *spi)
 {
 	struct max7301 *ts;
 	int ret;
diff -druN linux-libre-2.6.30-gnu/drivers/gpio/pca953x.c linux-libre-2.6.31-gnu/drivers/gpio/pca953x.c
--- linux-libre-2.6.30-gnu/drivers/gpio/pca953x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpio/pca953x.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,10 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
+#ifdef CONFIG_OF_GPIO
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#endif
 
 #include <asm/gpio.h>
 
@@ -32,6 +36,7 @@
 	{ "pca9539", 16, },
 	{ "pca9554", 8, },
 	{ "pca9555", 16, },
+	{ "pca9556", 8, },
 	{ "pca9557", 8, },
 
 	{ "max7310", 8, },
@@ -49,7 +54,9 @@
 	uint16_t reg_direction;
 
 	struct i2c_client *client;
+	struct pca953x_platform_data *dyn_pdata;
 	struct gpio_chip gpio_chip;
+	char **names;
 };
 
 static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
@@ -192,7 +199,56 @@
 	gc->label = chip->client->name;
 	gc->dev = &chip->client->dev;
 	gc->owner = THIS_MODULE;
+	gc->names = chip->names;
+}
+
+/*
+ * Handlers for alternative sources of platform_data
+ */
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static struct pca953x_platform_data *
+pca953x_get_alt_pdata(struct i2c_client *client)
+{
+	struct pca953x_platform_data *pdata;
+	struct device_node *node;
+	const uint16_t *val;
+
+	node = dev_archdata_get_node(&client->dev.archdata);
+	if (node == NULL)
+		return NULL;
+
+	pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
+	if (pdata == NULL) {
+		dev_err(&client->dev, "Unable to allocate platform_data\n");
+		return NULL;
+	}
+
+	pdata->gpio_base = -1;
+	val = of_get_property(node, "linux,gpio-base", NULL);
+	if (val) {
+		if (*val < 0)
+			dev_warn(&client->dev,
+				 "invalid gpio-base in device tree\n");
+		else
+			pdata->gpio_base = *val;
+	}
+
+	val = of_get_property(node, "polarity", NULL);
+	if (val)
+		pdata->invert = *val;
+
+	return pdata;
+}
+#else
+static struct pca953x_platform_data *
+pca953x_get_alt_pdata(struct i2c_client *client)
+{
+	return NULL;
 }
+#endif
 
 static int __devinit pca953x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
@@ -201,20 +257,32 @@
 	struct pca953x_chip *chip;
 	int ret;
 
+	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
 	pdata = client->dev.platform_data;
 	if (pdata == NULL) {
-		dev_dbg(&client->dev, "no platform data\n");
-		return -EINVAL;
+		pdata = pca953x_get_alt_pdata(client);
+		/*
+		 * Unlike normal platform_data, this is allocated
+		 * dynamically and must be freed in the driver
+		 */
+		chip->dyn_pdata = pdata;
 	}
 
-	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
+	if (pdata == NULL) {
+		dev_dbg(&client->dev, "no platform data\n");
+		ret = -EINVAL;
+		goto out_failed;
+	}
 
 	chip->client = client;
 
 	chip->gpio_start = pdata->gpio_base;
 
+	chip->names = pdata->names;
+
 	/* initialize cached registers from their original values.
 	 * we can't share this chip with another i2c master.
 	 */
@@ -249,6 +317,7 @@
 	return 0;
 
 out_failed:
+	kfree(chip->dyn_pdata);
 	kfree(chip);
 	return ret;
 }
@@ -276,6 +345,7 @@
 		return ret;
 	}
 
+	kfree(chip->dyn_pdata);
 	kfree(chip);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpio/pl061.c linux-libre-2.6.31-gnu/drivers/gpio/pl061.c
--- linux-libre-2.6.30-gnu/drivers/gpio/pl061.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpio/pl061.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ *  linux/drivers/gpio/pl061.c
+ *
+ *  Copyright (C) 2008, 2009 Provigent Ltd.
+ *
+ * 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.
+ *
+ * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
+ *
+ * Data sheet: ARM DDI 0190B, September 2000
+ */
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl061.h>
+
+#define GPIODIR 0x400
+#define GPIOIS  0x404
+#define GPIOIBE 0x408
+#define GPIOIEV 0x40C
+#define GPIOIE  0x410
+#define GPIORIS 0x414
+#define GPIOMIS 0x418
+#define GPIOIC  0x41C
+
+#define PL061_GPIO_NR	8
+
+struct pl061_gpio {
+	/* We use a list of pl061_gpio structs for each trigger IRQ in the main
+	 * interrupts controller of the system. We need this to support systems
+	 * in which more that one PL061s are connected to the same IRQ. The ISR
+	 * interates through this list to find the source of the interrupt.
+	 */
+	struct list_head	list;
+
+	/* Each of the two spinlocks protects a different set of hardware
+	 * regiters and data structurs. This decouples the code of the IRQ from
+	 * the GPIO code. This also makes the case of a GPIO routine call from
+	 * the IRQ code simpler.
+	 */
+	spinlock_t		lock;		/* GPIO registers */
+	spinlock_t		irq_lock;	/* IRQ registers */
+
+	void __iomem		*base;
+	unsigned		irq_base;
+	struct gpio_chip	gc;
+};
+
+static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+	unsigned long flags;
+	unsigned char gpiodir;
+
+	if (offset >= gc->ngpio)
+		return -EINVAL;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	gpiodir = readb(chip->base + GPIODIR);
+	gpiodir &= ~(1 << offset);
+	writeb(gpiodir, chip->base + GPIODIR);
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
+		int value)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+	unsigned long flags;
+	unsigned char gpiodir;
+
+	if (offset >= gc->ngpio)
+		return -EINVAL;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+	gpiodir = readb(chip->base + GPIODIR);
+	gpiodir |= 1 << offset;
+	writeb(gpiodir, chip->base + GPIODIR);
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+	return !!readb(chip->base + (1 << (offset + 2)));
+}
+
+static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+}
+
+static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+	if (chip->irq_base == (unsigned) -1)
+		return -EINVAL;
+
+	return chip->irq_base + offset;
+}
+
+/*
+ * PL061 GPIO IRQ
+ */
+static void pl061_irq_disable(unsigned irq)
+{
+	struct pl061_gpio *chip = get_irq_chip_data(irq);
+	int offset = irq - chip->irq_base;
+	unsigned long flags;
+	u8 gpioie;
+
+	spin_lock_irqsave(&chip->irq_lock, flags);
+	gpioie = readb(chip->base + GPIOIE);
+	gpioie &= ~(1 << offset);
+	writeb(gpioie, chip->base + GPIOIE);
+	spin_unlock_irqrestore(&chip->irq_lock, flags);
+}
+
+static void pl061_irq_enable(unsigned irq)
+{
+	struct pl061_gpio *chip = get_irq_chip_data(irq);
+	int offset = irq - chip->irq_base;
+	unsigned long flags;
+	u8 gpioie;
+
+	spin_lock_irqsave(&chip->irq_lock, flags);
+	gpioie = readb(chip->base + GPIOIE);
+	gpioie |= 1 << offset;
+	writeb(gpioie, chip->base + GPIOIE);
+	spin_unlock_irqrestore(&chip->irq_lock, flags);
+}
+
+static int pl061_irq_type(unsigned irq, unsigned trigger)
+{
+	struct pl061_gpio *chip = get_irq_chip_data(irq);
+	int offset = irq - chip->irq_base;
+	unsigned long flags;
+	u8 gpiois, gpioibe, gpioiev;
+
+	if (offset < 0 || offset > PL061_GPIO_NR)
+		return -EINVAL;
+
+	spin_lock_irqsave(&chip->irq_lock, flags);
+
+	gpioiev = readb(chip->base + GPIOIEV);
+
+	gpiois = readb(chip->base + GPIOIS);
+	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+		gpiois |= 1 << offset;
+		if (trigger & IRQ_TYPE_LEVEL_HIGH)
+			gpioiev |= 1 << offset;
+		else
+			gpioiev &= ~(1 << offset);
+	} else
+		gpiois &= ~(1 << offset);
+	writeb(gpiois, chip->base + GPIOIS);
+
+	gpioibe = readb(chip->base + GPIOIBE);
+	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+		gpioibe |= 1 << offset;
+	else {
+		gpioibe &= ~(1 << offset);
+		if (trigger & IRQ_TYPE_EDGE_RISING)
+			gpioiev |= 1 << offset;
+		else
+			gpioiev &= ~(1 << offset);
+	}
+	writeb(gpioibe, chip->base + GPIOIBE);
+
+	writeb(gpioiev, chip->base + GPIOIEV);
+
+	spin_unlock_irqrestore(&chip->irq_lock, flags);
+
+	return 0;
+}
+
+static struct irq_chip pl061_irqchip = {
+	.name		= "GPIO",
+	.enable		= pl061_irq_enable,
+	.disable	= pl061_irq_disable,
+	.set_type	= pl061_irq_type,
+};
+
+static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct list_head *chip_list = get_irq_chip_data(irq);
+	struct list_head *ptr;
+	struct pl061_gpio *chip;
+
+	desc->chip->ack(irq);
+	list_for_each(ptr, chip_list) {
+		unsigned long pending;
+		int offset;
+
+		chip = list_entry(ptr, struct pl061_gpio, list);
+		pending = readb(chip->base + GPIOMIS);
+		writeb(pending, chip->base + GPIOIC);
+
+		if (pending == 0)
+			continue;
+
+		for_each_bit(offset, &pending, PL061_GPIO_NR)
+			generic_handle_irq(pl061_to_irq(&chip->gc, offset));
+	}
+	desc->chip->unmask(irq);
+}
+
+static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)
+{
+	struct pl061_platform_data *pdata;
+	struct pl061_gpio *chip;
+	struct list_head *chip_list;
+	int ret, irq, i;
+	static DECLARE_BITMAP(init_irq, NR_IRQS);
+
+	pdata = dev->dev.platform_data;
+	if (pdata == NULL)
+		return -ENODEV;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	if (!request_mem_region(dev->res.start,
+				resource_size(&dev->res), "pl061")) {
+		ret = -EBUSY;
+		goto free_mem;
+	}
+
+	chip->base = ioremap(dev->res.start, resource_size(&dev->res));
+	if (chip->base == NULL) {
+		ret = -ENOMEM;
+		goto release_region;
+	}
+
+	spin_lock_init(&chip->lock);
+	spin_lock_init(&chip->irq_lock);
+	INIT_LIST_HEAD(&chip->list);
+
+	chip->gc.direction_input = pl061_direction_input;
+	chip->gc.direction_output = pl061_direction_output;
+	chip->gc.get = pl061_get_value;
+	chip->gc.set = pl061_set_value;
+	chip->gc.to_irq = pl061_to_irq;
+	chip->gc.base = pdata->gpio_base;
+	chip->gc.ngpio = PL061_GPIO_NR;
+	chip->gc.label = dev_name(&dev->dev);
+	chip->gc.dev = &dev->dev;
+	chip->gc.owner = THIS_MODULE;
+
+	chip->irq_base = pdata->irq_base;
+
+	ret = gpiochip_add(&chip->gc);
+	if (ret)
+		goto iounmap;
+
+	/*
+	 * irq_chip support
+	 */
+
+	if (chip->irq_base == (unsigned) -1)
+		return 0;
+
+	writeb(0, chip->base + GPIOIE); /* disable irqs */
+	irq = dev->irq[0];
+	if (irq < 0) {
+		ret = -ENODEV;
+		goto iounmap;
+	}
+	set_irq_chained_handler(irq, pl061_irq_handler);
+	if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
+		chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
+		if (chip_list == NULL) {
+			clear_bit(irq, init_irq);
+			ret = -ENOMEM;
+			goto iounmap;
+		}
+		INIT_LIST_HEAD(chip_list);
+		set_irq_chip_data(irq, chip_list);
+	} else
+		chip_list = get_irq_chip_data(irq);
+	list_add(&chip->list, chip_list);
+
+	for (i = 0; i < PL061_GPIO_NR; i++) {
+		if (pdata->directions & (1 << i))
+			pl061_direction_output(&chip->gc, i,
+					pdata->values & (1 << i));
+		else
+			pl061_direction_input(&chip->gc, i);
+
+		set_irq_chip(i+chip->irq_base, &pl061_irqchip);
+		set_irq_handler(i+chip->irq_base, handle_simple_irq);
+		set_irq_flags(i+chip->irq_base, IRQF_VALID);
+		set_irq_chip_data(i+chip->irq_base, chip);
+	}
+
+	return 0;
+
+iounmap:
+	iounmap(chip->base);
+release_region:
+	release_mem_region(dev->res.start, resource_size(&dev->res));
+free_mem:
+	kfree(chip);
+
+	return ret;
+}
+
+static struct amba_id pl061_ids[] __initdata = {
+	{
+		.id	= 0x00041061,
+		.mask	= 0x000fffff,
+	},
+	{ 0, 0 },
+};
+
+static struct amba_driver pl061_gpio_driver = {
+	.drv = {
+		.name	= "pl061_gpio",
+	},
+	.id_table	= pl061_ids,
+	.probe		= pl061_probe,
+};
+
+static int __init pl061_gpio_init(void)
+{
+	return amba_driver_register(&pl061_gpio_driver);
+}
+subsys_initcall(pl061_gpio_init);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("PL061 GPIO driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/gpio/vr41xx_giu.c linux-libre-2.6.31-gnu/drivers/gpio/vr41xx_giu.c
--- linux-libre-2.6.30-gnu/drivers/gpio/vr41xx_giu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpio/vr41xx_giu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,585 @@
+/*
+ *  Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2002 MontaVista Software Inc.
+ *	Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@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 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/errno.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/irq.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+#define GIUIOSELL	0x00
+#define GIUIOSELH	0x02
+#define GIUPIODL	0x04
+#define GIUPIODH	0x06
+#define GIUINTSTATL	0x08
+#define GIUINTSTATH	0x0a
+#define GIUINTENL	0x0c
+#define GIUINTENH	0x0e
+#define GIUINTTYPL	0x10
+#define GIUINTTYPH	0x12
+#define GIUINTALSELL	0x14
+#define GIUINTALSELH	0x16
+#define GIUINTHTSELL	0x18
+#define GIUINTHTSELH	0x1a
+#define GIUPODATL	0x1c
+#define GIUPODATEN	0x1c
+#define GIUPODATH	0x1e
+ #define PIOEN0		0x0100
+ #define PIOEN1		0x0200
+#define GIUPODAT	0x1e
+#define GIUFEDGEINHL	0x20
+#define GIUFEDGEINHH	0x22
+#define GIUREDGEINHL	0x24
+#define GIUREDGEINHH	0x26
+
+#define GIUUSEUPDN	0x1e0
+#define GIUTERMUPDN	0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO		0x0001
+#define GPIO_HAS_OUTPUT_ENABLE		0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
+
+enum {
+	GPIO_INPUT,
+	GPIO_OUTPUT,
+};
+
+static DEFINE_SPINLOCK(giu_lock);
+static unsigned long giu_flags;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset)		readw(giu_base + (offset))
+#define giu_write(offset, value)	writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq)	((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET	16
+#define GIUINT_HIGH_MAX		32
+
+static inline u16 giu_set(u16 offset, u16 set)
+{
+	u16 data;
+
+	data = giu_read(offset);
+	data |= set;
+	giu_write(offset, data);
+
+	return data;
+}
+
+static inline u16 giu_clear(u16 offset, u16 clear)
+{
+	u16 data;
+
+	data = giu_read(offset);
+	data &= ~clear;
+	giu_write(offset, data);
+
+	return data;
+}
+
+static void ack_giuint_low(unsigned int irq)
+{
+	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void mask_giuint_low(unsigned int irq)
+{
+	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void mask_ack_giuint_low(unsigned int irq)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(irq);
+	giu_clear(GIUINTENL, 1 << pin);
+	giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void unmask_giuint_low(unsigned int irq)
+{
+	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static struct irq_chip giuint_low_irq_chip = {
+	.name		= "GIUINTL",
+	.ack		= ack_giuint_low,
+	.mask		= mask_giuint_low,
+	.mask_ack	= mask_ack_giuint_low,
+	.unmask		= unmask_giuint_low,
+};
+
+static void ack_giuint_high(unsigned int irq)
+{
+	giu_write(GIUINTSTATH,
+		  1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_giuint_high(unsigned int irq)
+{
+	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void mask_ack_giuint_high(unsigned int irq)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+	giu_clear(GIUINTENH, 1 << pin);
+	giu_write(GIUINTSTATH, 1 << pin);
+}
+
+static void unmask_giuint_high(unsigned int irq)
+{
+	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static struct irq_chip giuint_high_irq_chip = {
+	.name		= "GIUINTH",
+	.ack		= ack_giuint_high,
+	.mask		= mask_giuint_high,
+	.mask_ack	= mask_ack_giuint_high,
+	.unmask		= unmask_giuint_high,
+};
+
+static int giu_get_irq(unsigned int irq)
+{
+	u16 pendl, pendh, maskl, maskh;
+	int i;
+
+	pendl = giu_read(GIUINTSTATL);
+	pendh = giu_read(GIUINTSTATH);
+	maskl = giu_read(GIUINTENL);
+	maskh = giu_read(GIUINTENH);
+
+	maskl &= pendl;
+	maskh &= pendh;
+
+	if (maskl) {
+		for (i = 0; i < 16; i++) {
+			if (maskl & (1 << i))
+				return GIU_IRQ(i);
+		}
+	} else if (maskh) {
+		for (i = 0; i < 16; i++) {
+			if (maskh & (1 << i))
+				return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
+		}
+	}
+
+	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+	       maskl, pendl, maskh, pendh);
+
+	atomic_inc(&irq_err_count);
+
+	return -EINVAL;
+}
+
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+			    irq_signal_t signal)
+{
+	u16 mask;
+
+	if (pin < GIUINT_HIGH_OFFSET) {
+		mask = 1 << pin;
+		if (trigger != IRQ_TRIGGER_LEVEL) {
+			giu_set(GIUINTTYPL, mask);
+			if (signal == IRQ_SIGNAL_HOLD)
+				giu_set(GIUINTHTSELL, mask);
+			else
+				giu_clear(GIUINTHTSELL, mask);
+			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+				switch (trigger) {
+				case IRQ_TRIGGER_EDGE_FALLING:
+					giu_set(GIUFEDGEINHL, mask);
+					giu_clear(GIUREDGEINHL, mask);
+					break;
+				case IRQ_TRIGGER_EDGE_RISING:
+					giu_clear(GIUFEDGEINHL, mask);
+					giu_set(GIUREDGEINHL, mask);
+					break;
+				default:
+					giu_set(GIUFEDGEINHL, mask);
+					giu_set(GIUREDGEINHL, mask);
+					break;
+				}
+			}
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_low_irq_chip,
+						 handle_edge_irq);
+		} else {
+			giu_clear(GIUINTTYPL, mask);
+			giu_clear(GIUINTHTSELL, mask);
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_low_irq_chip,
+						 handle_level_irq);
+		}
+		giu_write(GIUINTSTATL, mask);
+	} else if (pin < GIUINT_HIGH_MAX) {
+		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+		if (trigger != IRQ_TRIGGER_LEVEL) {
+			giu_set(GIUINTTYPH, mask);
+			if (signal == IRQ_SIGNAL_HOLD)
+				giu_set(GIUINTHTSELH, mask);
+			else
+				giu_clear(GIUINTHTSELH, mask);
+			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
+				switch (trigger) {
+				case IRQ_TRIGGER_EDGE_FALLING:
+					giu_set(GIUFEDGEINHH, mask);
+					giu_clear(GIUREDGEINHH, mask);
+					break;
+				case IRQ_TRIGGER_EDGE_RISING:
+					giu_clear(GIUFEDGEINHH, mask);
+					giu_set(GIUREDGEINHH, mask);
+					break;
+				default:
+					giu_set(GIUFEDGEINHH, mask);
+					giu_set(GIUREDGEINHH, mask);
+					break;
+				}
+			}
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_high_irq_chip,
+						 handle_edge_irq);
+		} else {
+			giu_clear(GIUINTTYPH, mask);
+			giu_clear(GIUINTHTSELH, mask);
+			set_irq_chip_and_handler(GIU_IRQ(pin),
+						 &giuint_high_irq_chip,
+						 handle_level_irq);
+		}
+		giu_write(GIUINTSTATH, mask);
+	}
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
+{
+	u16 mask;
+
+	if (pin < GIUINT_HIGH_OFFSET) {
+		mask = 1 << pin;
+		if (level == IRQ_LEVEL_HIGH)
+			giu_set(GIUINTALSELL, mask);
+		else
+			giu_clear(GIUINTALSELL, mask);
+		giu_write(GIUINTSTATL, mask);
+	} else if (pin < GIUINT_HIGH_MAX) {
+		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+		if (level == IRQ_LEVEL_HIGH)
+			giu_set(GIUINTALSELH, mask);
+		else
+			giu_clear(GIUINTALSELH, mask);
+		giu_write(GIUINTSTATH, mask);
+	}
+}
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
+
+static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
+{
+	u16 offset, mask, reg;
+	unsigned long flags;
+
+	if (pin >= chip->ngpio)
+		return -EINVAL;
+
+	if (pin < 16) {
+		offset = GIUIOSELL;
+		mask = 1 << pin;
+	} else if (pin < 32) {
+		offset = GIUIOSELH;
+		mask = 1 << (pin - 16);
+	} else {
+		if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
+			offset = GIUPODATEN;
+			mask = 1 << (pin - 32);
+		} else {
+			switch (pin) {
+			case 48:
+				offset = GIUPODATH;
+				mask = PIOEN0;
+				break;
+			case 49:
+				offset = GIUPODATH;
+				mask = PIOEN1;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+	}
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	reg = giu_read(offset);
+	if (dir == GPIO_OUTPUT)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	giu_write(offset, reg);
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+
+	return 0;
+}
+
+int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
+{
+	u16 reg, mask;
+	unsigned long flags;
+
+	if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
+		return -EPERM;
+
+	if (pin >= 15)
+		return -EINVAL;
+
+	mask = 1 << pin;
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
+		reg = giu_read(GIUTERMUPDN);
+		if (pull == GPIO_PULL_UP)
+			reg |= mask;
+		else
+			reg &= ~mask;
+		giu_write(GIUTERMUPDN, reg);
+
+		reg = giu_read(GIUUSEUPDN);
+		reg |= mask;
+		giu_write(GIUUSEUPDN, reg);
+	} else {
+		reg = giu_read(GIUUSEUPDN);
+		reg &= ~mask;
+		giu_write(GIUUSEUPDN, reg);
+	}
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
+
+static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+	u16 reg, mask;
+
+	if (pin >= chip->ngpio)
+		return -EINVAL;
+
+	if (pin < 16) {
+		reg = giu_read(GIUPIODL);
+		mask = 1 << pin;
+	} else if (pin < 32) {
+		reg = giu_read(GIUPIODH);
+		mask = 1 << (pin - 16);
+	} else if (pin < 48) {
+		reg = giu_read(GIUPODATL);
+		mask = 1 << (pin - 32);
+	} else {
+		reg = giu_read(GIUPODATH);
+		mask = 1 << (pin - 48);
+	}
+
+	if (reg & mask)
+		return 1;
+
+	return 0;
+}
+
+static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
+			    int value)
+{
+	u16 offset, mask, reg;
+	unsigned long flags;
+
+	if (pin >= chip->ngpio)
+		return;
+
+	if (pin < 16) {
+		offset = GIUPIODL;
+		mask = 1 << pin;
+	} else if (pin < 32) {
+		offset = GIUPIODH;
+		mask = 1 << (pin - 16);
+	} else if (pin < 48) {
+		offset = GIUPODATL;
+		mask = 1 << (pin - 32);
+	} else {
+		offset = GIUPODATH;
+		mask = 1 << (pin - 48);
+	}
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	reg = giu_read(offset);
+	if (value)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	giu_write(offset, reg);
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+}
+
+
+static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return giu_set_direction(chip, offset, GPIO_INPUT);
+}
+
+static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				int value)
+{
+	vr41xx_gpio_set(chip, offset, value);
+
+	return giu_set_direction(chip, offset, GPIO_OUTPUT);
+}
+
+static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	return GIU_IRQ_BASE + offset;
+}
+
+static struct gpio_chip vr41xx_gpio_chip = {
+	.label			= "vr41xx",
+	.owner			= THIS_MODULE,
+	.direction_input	= vr41xx_gpio_direction_input,
+	.get			= vr41xx_gpio_get,
+	.direction_output	= vr41xx_gpio_direction_output,
+	.set			= vr41xx_gpio_set,
+	.to_irq			= vr41xx_gpio_to_irq,
+};
+
+static int __devinit giu_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	unsigned int trigger, i, pin;
+	struct irq_chip *chip;
+	int irq, retval;
+
+	switch (pdev->id) {
+	case GPIO_50PINS_PULLUPDOWN:
+		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
+		vr41xx_gpio_chip.ngpio = 50;
+		break;
+	case GPIO_36PINS:
+		vr41xx_gpio_chip.ngpio = 36;
+		break;
+	case GPIO_48PINS_EDGE_SELECT:
+		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+		vr41xx_gpio_chip.ngpio = 48;
+		break;
+	default:
+		dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EBUSY;
+
+	giu_base = ioremap(res->start, res->end - res->start + 1);
+	if (!giu_base)
+		return -ENOMEM;
+
+	vr41xx_gpio_chip.dev = &pdev->dev;
+
+	retval = gpiochip_add(&vr41xx_gpio_chip);
+
+	giu_write(GIUINTENL, 0);
+	giu_write(GIUINTENH, 0);
+
+	trigger = giu_read(GIUINTTYPH) << 16;
+	trigger |= giu_read(GIUINTTYPL);
+	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+		pin = GPIO_PIN_OF_IRQ(i);
+		if (pin < GIUINT_HIGH_OFFSET)
+			chip = &giuint_low_irq_chip;
+		else
+			chip = &giuint_high_irq_chip;
+
+		if (trigger & (1 << pin))
+			set_irq_chip_and_handler(i, chip, handle_edge_irq);
+		else
+			set_irq_chip_and_handler(i, chip, handle_level_irq);
+
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0 || irq >= nr_irqs)
+		return -EBUSY;
+
+	return cascade_irq(irq, giu_get_irq);
+}
+
+static int __devexit giu_remove(struct platform_device *pdev)
+{
+	if (giu_base) {
+		iounmap(giu_base);
+		giu_base = NULL;
+	}
+
+	return 0;
+}
+
+static struct platform_driver giu_device_driver = {
+	.probe		= giu_probe,
+	.remove		= __devexit_p(giu_remove),
+	.driver		= {
+		.name	= "GIU",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init vr41xx_giu_init(void)
+{
+	return platform_driver_register(&giu_device_driver);
+}
+
+static void __exit vr41xx_giu_exit(void)
+{
+	platform_driver_unregister(&giu_device_driver);
+}
+
+module_init(vr41xx_giu_init);
+module_exit(vr41xx_giu_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_agpsupport.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_agpsupport.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_agpsupport.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_agpsupport.c	2009-09-09 18:13:59.000000000 -0400
@@ -203,7 +203,7 @@
 
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
-	if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
+	if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
 		return -ENOMEM;
 
 	memset(entry, 0, sizeof(*entry));
@@ -211,7 +211,7 @@
 	pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
 	type = (u32) request->type;
 	if (!(memory = drm_alloc_agp(dev, pages, type))) {
-		drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+		kfree(entry);
 		return -ENOMEM;
 	}
 
@@ -369,7 +369,7 @@
 	list_del(&entry->head);
 
 	drm_free_agp(entry->memory, entry->pages);
-	drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+	kfree(entry);
 	return 0;
 }
 EXPORT_SYMBOL(drm_agp_free);
@@ -397,13 +397,13 @@
 {
 	struct drm_agp_head *head = NULL;
 
-	if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
+	if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
 		return NULL;
 	memset((void *)head, 0, sizeof(*head));
 	head->bridge = agp_find_bridge(dev->pdev);
 	if (!head->bridge) {
 		if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
-			drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+			kfree(head);
 			return NULL;
 		}
 		agp_copy_info(head->bridge, &head->agp_info);
@@ -412,7 +412,7 @@
 		agp_copy_info(head->bridge, &head->agp_info);
 	}
 	if (head->agp_info.chipset == NOT_SUPPORTED) {
-		drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+		kfree(head);
 		return NULL;
 	}
 	INIT_LIST_HEAD(&head->memory);
@@ -482,7 +482,7 @@
 	}
 
 	for (i = 0; i < num_pages; i++)
-		mem->memory[i] = phys_to_gart(page_to_phys(pages[i]));
+		mem->pages[i] = pages[i];
 	mem->page_count = num_pages;
 
 	mem->is_flushed = true;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_auth.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_auth.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_auth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_auth.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,7 +79,7 @@
 	struct drm_device *dev = master->minor->dev;
 	DRM_DEBUG("%d\n", magic);
 
-	entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 	memset(entry, 0, sizeof(*entry));
@@ -120,7 +120,7 @@
 	list_del(&pt->head);
 	mutex_unlock(&dev->struct_mutex);
 
-	drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+	kfree(pt);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_bufs.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_bufs.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_bufs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_bufs.c	2009-09-09 18:13:59.000000000 -0400
@@ -151,7 +151,7 @@
 	unsigned long user_token;
 	int ret;
 
-	map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
+	map = kmalloc(sizeof(*map), GFP_KERNEL);
 	if (!map)
 		return -ENOMEM;
 
@@ -165,7 +165,7 @@
 	 * when processes fork.
 	 */
 	if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+		kfree(map);
 		return -EINVAL;
 	}
 	DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
@@ -179,7 +179,7 @@
 		map->size = PAGE_ALIGN(map->size);
 
 	if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+		kfree(map);
 		return -EINVAL;
 	}
 	map->mtrr = -1;
@@ -191,7 +191,7 @@
 #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
 		if (map->offset + (map->size-1) < map->offset ||
 		    map->offset < virt_to_phys(high_memory)) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			return -EINVAL;
 		}
 #endif
@@ -212,7 +212,7 @@
 				list->map->size = map->size;
 			}
 
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			*maplist = list;
 			return 0;
 		}
@@ -227,7 +227,7 @@
 		if (map->type == _DRM_REGISTERS) {
 			map->handle = ioremap(map->offset, map->size);
 			if (!map->handle) {
-				drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+				kfree(map);
 				return -ENOMEM;
 			}
 		}
@@ -243,7 +243,7 @@
 				list->map->size = map->size;
 			}
 
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			*maplist = list;
 			return 0;
 		}
@@ -251,7 +251,7 @@
 		DRM_DEBUG("%lu %d %p\n",
 			  map->size, drm_order(map->size), map->handle);
 		if (!map->handle) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			return -ENOMEM;
 		}
 		map->offset = (unsigned long)map->handle;
@@ -259,7 +259,7 @@
 			/* Prevent a 2nd X Server from creating a 2nd lock */
 			if (dev->primary->master->lock.hw_lock != NULL) {
 				vfree(map->handle);
-				drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+				kfree(map);
 				return -EBUSY;
 			}
 			dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle;	/* Pointer to lock */
@@ -270,7 +270,7 @@
 		int valid = 0;
 
 		if (!drm_core_has_AGP(dev)) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			return -EINVAL;
 		}
 #ifdef __alpha__
@@ -303,7 +303,7 @@
 			}
 		}
 		if (!list_empty(&dev->agp->memory) && !valid) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			return -EPERM;
 		}
 		DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n",
@@ -316,7 +316,7 @@
 	}
 	case _DRM_SCATTER_GATHER:
 		if (!dev->sg) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			return -EINVAL;
 		}
 		map->offset += (unsigned long)dev->sg->virtual;
@@ -328,7 +328,7 @@
 		 * need to point to a 64bit variable first. */
 		dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
 		if (!dmah) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 			return -ENOMEM;
 		}
 		map->handle = dmah->vaddr;
@@ -336,15 +336,15 @@
 		kfree(dmah);
 		break;
 	default:
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+		kfree(map);
 		return -EINVAL;
 	}
 
-	list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
+	list = kmalloc(sizeof(*list), GFP_KERNEL);
 	if (!list) {
 		if (map->type == _DRM_REGISTERS)
 			iounmap(map->handle);
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+		kfree(map);
 		return -EINVAL;
 	}
 	memset(list, 0, sizeof(*list));
@@ -362,8 +362,8 @@
 	if (ret) {
 		if (map->type == _DRM_REGISTERS)
 			iounmap(map->handle);
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+		kfree(map);
+		kfree(list);
 		mutex_unlock(&dev->struct_mutex);
 		return ret;
 	}
@@ -371,7 +371,8 @@
 	list->user_token = list->hash.key << PAGE_SHIFT;
 	mutex_unlock(&dev->struct_mutex);
 
-	list->master = dev->primary->master;
+	if (!(map->flags & _DRM_DRIVER))
+		list->master = dev->primary->master;
 	*maplist = list;
 	return 0;
 	}
@@ -447,7 +448,7 @@
 			list_del(&r_list->head);
 			drm_ht_remove_key(&dev->map_hash,
 					  r_list->user_token >> PAGE_SHIFT);
-			drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+			kfree(r_list);
 			found = 1;
 			break;
 		}
@@ -490,7 +491,7 @@
 		DRM_ERROR("tried to rmmap GEM object\n");
 		break;
 	}
-	drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+	kfree(map);
 
 	return 0;
 }
@@ -581,24 +582,16 @@
 				drm_pci_free(dev, entry->seglist[i]);
 			}
 		}
-		drm_free(entry->seglist,
-			 entry->seg_count *
-			 sizeof(*entry->seglist), DRM_MEM_SEGS);
+		kfree(entry->seglist);
 
 		entry->seg_count = 0;
 	}
 
 	if (entry->buf_count) {
 		for (i = 0; i < entry->buf_count; i++) {
-			if (entry->buflist[i].dev_private) {
-				drm_free(entry->buflist[i].dev_private,
-					 entry->buflist[i].dev_priv_size,
-					 DRM_MEM_BUFS);
-			}
+			kfree(entry->buflist[i].dev_private);
 		}
-		drm_free(entry->buflist,
-			 entry->buf_count *
-			 sizeof(*entry->buflist), DRM_MEM_BUFS);
+		kfree(entry->buflist);
 
 		entry->buf_count = 0;
 	}
@@ -697,8 +690,7 @@
 		return -EINVAL;
 	}
 
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
+	entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
 	if (!entry->buflist) {
 		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
@@ -728,7 +720,7 @@
 		buf->file_priv = NULL;
 
 		buf->dev_priv_size = dev->driver->dev_priv_size;
-		buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+		buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL);
 		if (!buf->dev_private) {
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
@@ -748,10 +740,9 @@
 
 	DRM_DEBUG("byte_count: %d\n", byte_count);
 
-	temp_buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist), DRM_MEM_BUFS);
+	temp_buflist = krealloc(dma->buflist,
+				(dma->buf_count + entry->buf_count) *
+				sizeof(*dma->buflist), GFP_KERNEL);
 	if (!temp_buflist) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
@@ -853,8 +844,7 @@
 		return -EINVAL;
 	}
 
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
+	entry->buflist = kmalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
 	if (!entry->buflist) {
 		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
@@ -862,11 +852,9 @@
 	}
 	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
 
-	entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
-				   DRM_MEM_SEGS);
+	entry->seglist = kmalloc(count * sizeof(*entry->seglist), GFP_KERNEL);
 	if (!entry->seglist) {
-		drm_free(entry->buflist,
-			 count * sizeof(*entry->buflist), DRM_MEM_BUFS);
+		kfree(entry->buflist);
 		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
@@ -876,13 +864,11 @@
 	/* Keep the original pagelist until we know all the allocations
 	 * have succeeded
 	 */
-	temp_pagelist = drm_alloc((dma->page_count + (count << page_order))
-				  * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+	temp_pagelist = kmalloc((dma->page_count + (count << page_order)) *
+			       sizeof(*dma->pagelist), GFP_KERNEL);
 	if (!temp_pagelist) {
-		drm_free(entry->buflist,
-			 count * sizeof(*entry->buflist), DRM_MEM_BUFS);
-		drm_free(entry->seglist,
-			 count * sizeof(*entry->seglist), DRM_MEM_SEGS);
+		kfree(entry->buflist);
+		kfree(entry->seglist);
 		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
@@ -906,9 +892,7 @@
 			entry->buf_count = count;
 			entry->seg_count = count;
 			drm_cleanup_buf_error(dev, entry);
-			drm_free(temp_pagelist,
-				 (dma->page_count + (count << page_order))
-				 * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+			kfree(temp_pagelist);
 			mutex_unlock(&dev->struct_mutex);
 			atomic_dec(&dev->buf_alloc);
 			return -ENOMEM;
@@ -939,18 +923,14 @@
 			buf->file_priv = NULL;
 
 			buf->dev_priv_size = dev->driver->dev_priv_size;
-			buf->dev_private = drm_alloc(buf->dev_priv_size,
-						     DRM_MEM_BUFS);
+			buf->dev_private = kmalloc(buf->dev_priv_size,
+						  GFP_KERNEL);
 			if (!buf->dev_private) {
 				/* Set count correctly so we free the proper amount. */
 				entry->buf_count = count;
 				entry->seg_count = count;
 				drm_cleanup_buf_error(dev, entry);
-				drm_free(temp_pagelist,
-					 (dma->page_count +
-					  (count << page_order))
-					 * sizeof(*dma->pagelist),
-					 DRM_MEM_PAGES);
+				kfree(temp_pagelist);
 				mutex_unlock(&dev->struct_mutex);
 				atomic_dec(&dev->buf_alloc);
 				return -ENOMEM;
@@ -963,16 +943,13 @@
 		byte_count += PAGE_SIZE << page_order;
 	}
 
-	temp_buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist), DRM_MEM_BUFS);
+	temp_buflist = krealloc(dma->buflist,
+				(dma->buf_count + entry->buf_count) *
+				sizeof(*dma->buflist), GFP_KERNEL);
 	if (!temp_buflist) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
-		drm_free(temp_pagelist,
-			 (dma->page_count + (count << page_order))
-			 * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+		kfree(temp_pagelist);
 		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;
@@ -987,9 +964,7 @@
 	 * with the new one.
 	 */
 	if (dma->page_count) {
-		drm_free(dma->pagelist,
-			 dma->page_count * sizeof(*dma->pagelist),
-			 DRM_MEM_PAGES);
+		kfree(dma->pagelist);
 	}
 	dma->pagelist = temp_pagelist;
 
@@ -1085,8 +1060,8 @@
 		return -EINVAL;
 	}
 
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
+	entry->buflist = kmalloc(count * sizeof(*entry->buflist),
+				GFP_KERNEL);
 	if (!entry->buflist) {
 		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
@@ -1117,7 +1092,7 @@
 		buf->file_priv = NULL;
 
 		buf->dev_priv_size = dev->driver->dev_priv_size;
-		buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+		buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL);
 		if (!buf->dev_private) {
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
@@ -1138,10 +1113,9 @@
 
 	DRM_DEBUG("byte_count: %d\n", byte_count);
 
-	temp_buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist), DRM_MEM_BUFS);
+	temp_buflist = krealloc(dma->buflist,
+				(dma->buf_count + entry->buf_count) *
+				sizeof(*dma->buflist), GFP_KERNEL);
 	if (!temp_buflist) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
@@ -1247,8 +1221,8 @@
 		return -EINVAL;
 	}
 
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
+	entry->buflist = kmalloc(count * sizeof(*entry->buflist),
+				GFP_KERNEL);
 	if (!entry->buflist) {
 		mutex_unlock(&dev->struct_mutex);
 		atomic_dec(&dev->buf_alloc);
@@ -1278,7 +1252,7 @@
 		buf->file_priv = NULL;
 
 		buf->dev_priv_size = dev->driver->dev_priv_size;
-		buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+		buf->dev_private = kmalloc(buf->dev_priv_size, GFP_KERNEL);
 		if (!buf->dev_private) {
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
@@ -1298,10 +1272,9 @@
 
 	DRM_DEBUG("byte_count: %d\n", byte_count);
 
-	temp_buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist), DRM_MEM_BUFS);
+	temp_buflist = krealloc(dma->buflist,
+				(dma->buf_count + entry->buf_count) *
+				sizeof(*dma->buflist), GFP_KERNEL);
 	if (!temp_buflist) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_context.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_context.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_context.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_context.c	2009-09-09 18:13:59.000000000 -0400
@@ -341,7 +341,7 @@
 			}
 	}
 
-	ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);
+	ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL);
 	if (!ctx_entry) {
 		DRM_DEBUG("out of memory\n");
 		return -ENOMEM;
@@ -456,7 +456,7 @@
 		list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
 			if (pos->handle == ctx->handle) {
 				list_del(&pos->head);
-				drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+				kfree(pos);
 				--dev->ctx_count;
 			}
 		}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_crtc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_crtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -258,31 +258,6 @@
 EXPORT_SYMBOL(drm_mode_object_find);
 
 /**
- * drm_crtc_from_fb - find the CRTC structure associated with an fb
- * @dev: DRM device
- * @fb: framebuffer in question
- *
- * LOCKING:
- * Caller must hold mode_config lock.
- *
- * Find CRTC in the mode_config structure that matches @fb.
- *
- * RETURNS:
- * Pointer to the CRTC or NULL if it wasn't found.
- */
-struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
-				  struct drm_framebuffer *fb)
-{
-	struct drm_crtc *crtc;
-
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (crtc->fb == fb)
-			return crtc;
-	}
-	return NULL;
-}
-
-/**
  * drm_framebuffer_init - initialize a framebuffer
  * @dev: DRM device
  *
@@ -328,11 +303,20 @@
 {
 	struct drm_device *dev = fb->dev;
 	struct drm_crtc *crtc;
+	struct drm_mode_set set;
+	int ret;
 
 	/* remove from any CRTC */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (crtc->fb == fb)
-			crtc->fb = NULL;
+		if (crtc->fb == fb) {
+			/* should turn off the crtc */
+			memset(&set, 0, sizeof(struct drm_mode_set));
+			set.crtc = crtc;
+			set.fb = NULL;
+			ret = crtc->funcs->set_config(&set);
+			if (ret)
+				DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
+		}
 	}
 
 	drm_mode_object_put(dev, &fb->base);
@@ -1461,7 +1445,7 @@
 		goto out;
 	}
 
-	if (crtc_req->count_connectors > 0 && !mode && !fb) {
+	if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
 		DRM_DEBUG("Count connectors is %d but no mode or fb set\n",
 			  crtc_req->count_connectors);
 		ret = -EINVAL;
@@ -1511,7 +1495,7 @@
 	set.mode = mode;
 	set.connectors = connector_set;
 	set.num_connectors = crtc_req->count_connectors;
-	set.fb =fb;
+	set.fb = fb;
 	ret = crtc->funcs->set_config(&set);
 
 out:
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_crtc_helper.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_crtc_helper.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_crtc_helper.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_crtc_helper.c	2009-09-09 18:13:59.000000000 -0400
@@ -706,8 +706,8 @@
 	struct drm_encoder **save_encoders, *new_encoder;
 	struct drm_framebuffer *old_fb = NULL;
 	bool save_enabled;
-	bool mode_changed = false;
-	bool fb_changed = false;
+	bool mode_changed = false; /* if true do a full mode set */
+	bool fb_changed = false; /* if true and !mode_changed just do a flip */
 	struct drm_connector *connector;
 	int count = 0, ro, fail = 0;
 	struct drm_crtc_helper_funcs *crtc_funcs;
@@ -758,6 +758,8 @@
 		if (set->crtc->fb == NULL) {
 			DRM_DEBUG("crtc has no fb, full mode set\n");
 			mode_changed = true;
+		} else if (set->fb == NULL) {
+			mode_changed = true;
 		} else if ((set->fb->bits_per_pixel !=
 			 set->crtc->fb->bits_per_pixel) ||
 			 set->fb->depth != set->crtc->fb->depth)
@@ -1090,6 +1092,8 @@
 		if (ret == false)
 			DRM_ERROR("failed to set mode on crtc %p\n", crtc);
 	}
+	/* disable the unused connectors while restoring the modesetting */
+	drm_helper_disable_unused_functions(dev);
 	return 0;
 }
 EXPORT_SYMBOL(drm_helper_resume_force_mode);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_debugfs.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_debugfs.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_debugfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_debugfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -100,15 +100,17 @@
 		    (dev->driver->driver_features & features) != features)
 			continue;
 
-		tmp = drm_alloc(sizeof(struct drm_info_node),
-				_DRM_DRIVER);
+		tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
+		if (tmp == NULL) {
+			ret = -1;
+			goto fail;
+		}
 		ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
 					  root, tmp, &drm_debugfs_fops);
 		if (!ent) {
-			DRM_ERROR("Cannot create /debugfs/dri/%s/%s\n",
+			DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n",
 				  name, files[i].name);
-			drm_free(tmp, sizeof(struct drm_info_node),
-				 _DRM_DRIVER);
+			kfree(tmp);
 			ret = -1;
 			goto fail;
 		}
@@ -133,9 +135,9 @@
  * \param minor device minor number
  * \param root DRI debugfs dir entry.
  *
- * Create the DRI debugfs root entry "/debugfs/dri", the device debugfs root entry
- * "/debugfs/dri/%minor%/", and each entry in debugfs_list as
- * "/debugfs/dri/%minor%/%name%".
+ * Create the DRI debugfs root entry "/sys/kernel/debug/dri", the device debugfs root entry
+ * "/sys/kernel/debug/dri/%minor%/", and each entry in debugfs_list as
+ * "/sys/kernel/debug/dri/%minor%/%name%".
  */
 int drm_debugfs_init(struct drm_minor *minor, int minor_id,
 		     struct dentry *root)
@@ -148,7 +150,7 @@
 	sprintf(name, "%d", minor_id);
 	minor->debugfs_root = debugfs_create_dir(name, root);
 	if (!minor->debugfs_root) {
-		DRM_ERROR("Cannot create /debugfs/dri/%s\n", name);
+		DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s\n", name);
 		return -1;
 	}
 
@@ -165,7 +167,7 @@
 		ret = dev->driver->debugfs_init(minor);
 		if (ret) {
 			DRM_ERROR("DRM: Driver failed to initialize "
-				  "/debugfs/dri.\n");
+				  "/sys/kernel/debug/dri.\n");
 			return ret;
 		}
 	}
@@ -196,8 +198,7 @@
 			if (tmp->info_ent == &files[i]) {
 				debugfs_remove(tmp->dent);
 				list_del(pos);
-				drm_free(tmp, sizeof(struct drm_info_node),
-					 _DRM_DRIVER);
+				kfree(tmp);
 			}
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_dma.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_dma.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,7 @@
 {
 	int i;
 
-	dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER);
+	dev->dma = kmalloc(sizeof(*dev->dma), GFP_KERNEL);
 	if (!dev->dma)
 		return -ENOMEM;
 
@@ -88,36 +88,19 @@
 					drm_pci_free(dev, dma->bufs[i].seglist[j]);
 				}
 			}
-			drm_free(dma->bufs[i].seglist,
-				 dma->bufs[i].seg_count
-				 * sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS);
+			kfree(dma->bufs[i].seglist);
 		}
 		if (dma->bufs[i].buf_count) {
 			for (j = 0; j < dma->bufs[i].buf_count; j++) {
-				if (dma->bufs[i].buflist[j].dev_private) {
-					drm_free(dma->bufs[i].buflist[j].
-						 dev_private,
-						 dma->bufs[i].buflist[j].
-						 dev_priv_size, DRM_MEM_BUFS);
-				}
+				kfree(dma->bufs[i].buflist[j].dev_private);
 			}
-			drm_free(dma->bufs[i].buflist,
-				 dma->bufs[i].buf_count *
-				 sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS);
+			kfree(dma->bufs[i].buflist);
 		}
 	}
 
-	if (dma->buflist) {
-		drm_free(dma->buflist,
-			 dma->buf_count * sizeof(*dma->buflist), DRM_MEM_BUFS);
-	}
-
-	if (dma->pagelist) {
-		drm_free(dma->pagelist,
-			 dma->page_count * sizeof(*dma->pagelist),
-			 DRM_MEM_PAGES);
-	}
-	drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
+	kfree(dma->buflist);
+	kfree(dma->pagelist);
+	kfree(dev->dma);
 	dev->dma = NULL;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_drawable.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_drawable.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_drawable.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_drawable.c	2009-09-09 18:13:59.000000000 -0400
@@ -85,9 +85,8 @@
 		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 		return -EINVAL;
 	}
-	drm_free(info->rects, info->num_rects * sizeof(struct drm_clip_rect),
-			DRM_MEM_BUFS);
-	drm_free(info, sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
+	kfree(info->rects);
+	kfree(info);
 
 	idr_remove(&dev->drw_idr, draw->handle);
 
@@ -106,12 +105,12 @@
 
 	info = idr_find(&dev->drw_idr, update->handle);
 	if (!info) {
-		info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
+		info = kzalloc(sizeof(*info), GFP_KERNEL);
 		if (!info)
 			return -ENOMEM;
 		if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) {
 			DRM_ERROR("No such drawable %d\n", update->handle);
-			drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+			kfree(info);
 			return -EINVAL;
 		}
 	}
@@ -121,8 +120,9 @@
 		if (update->num == 0)
 			rects = NULL;
 		else if (update->num != info->num_rects) {
-			rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
-					 DRM_MEM_BUFS);
+			rects = kmalloc(update->num *
+					sizeof(struct drm_clip_rect),
+					GFP_KERNEL);
 		} else
 			rects = info->rects;
 
@@ -145,8 +145,7 @@
 		spin_lock_irqsave(&dev->drw_lock, irqflags);
 
 		if (rects != info->rects) {
-			drm_free(info->rects, info->num_rects *
-				 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+			kfree(info->rects);
 		}
 
 		info->rects = rects;
@@ -166,8 +165,7 @@
 
 error:
 	if (rects != info->rects)
-		drm_free(rects, update->num * sizeof(struct drm_clip_rect),
-			 DRM_MEM_BUFS);
+		kfree(rects);
 
 	return err;
 }
@@ -186,9 +184,8 @@
 	struct drm_drawable_info *info = p;
 
 	if (info) {
-		drm_free(info->rects, info->num_rects *
-			 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
-		drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+		kfree(info->rects);
+		kfree(info);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_drv.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_drv.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_drv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_drv.c	2009-09-09 18:13:59.000000000 -0400
@@ -189,7 +189,7 @@
 			if (entry->bound)
 				drm_unbind_agp(entry->memory);
 			drm_free_agp(entry->memory, entry->pages);
-			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+			kfree(entry);
 		}
 		INIT_LIST_HEAD(&dev->agp->memory);
 
@@ -208,21 +208,15 @@
 	/* Clear vma list (only built for debugging) */
 	list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
 		list_del(&vma->head);
-		drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
+		kfree(vma);
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
 		for (i = 0; i < dev->queue_count; i++) {
-			if (dev->queuelist[i]) {
-				drm_free(dev->queuelist[i],
-					 sizeof(*dev->queuelist[0]),
-					 DRM_MEM_QUEUES);
-				dev->queuelist[i] = NULL;
-			}
+			kfree(dev->queuelist[i]);
+			dev->queuelist[i] = NULL;
 		}
-		drm_free(dev->queuelist,
-			 dev->queue_slots * sizeof(*dev->queuelist),
-			 DRM_MEM_QUEUES);
+		kfree(dev->queuelist);
 		dev->queuelist = NULL;
 	}
 	dev->queue_count = 0;
@@ -339,13 +333,11 @@
 
 	drm_debugfs_root = debugfs_create_dir("dri", NULL);
 	if (!drm_debugfs_root) {
-		DRM_ERROR("Cannot create /debugfs/dri\n");
+		DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
 		ret = -1;
 		goto err_p3;
 	}
 
-	drm_mem_init();
-
 	DRM_INFO("Initialized %s %d.%d.%d %s\n",
 		 CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_edid.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_edid.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_edid.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_edid.c	2009-09-09 18:13:59.000000000 -0400
@@ -252,16 +252,18 @@
 {
 	struct drm_display_mode *mode;
 	int hsize = t->hsize * 8 + 248, vsize;
+	unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
+		>> EDID_TIMING_ASPECT_SHIFT;
 
 	mode = drm_mode_create(dev);
 	if (!mode)
 		return NULL;
 
-	if (t->aspect_ratio == 0)
+	if (aspect_ratio == 0)
 		vsize = (hsize * 10) / 16;
-	else if (t->aspect_ratio == 1)
+	else if (aspect_ratio == 1)
 		vsize = (hsize * 3) / 4;
-	else if (t->aspect_ratio == 2)
+	else if (aspect_ratio == 2)
 		vsize = (hsize * 4) / 5;
 	else
 		vsize = (hsize * 9) / 16;
@@ -288,17 +290,24 @@
 {
 	struct drm_display_mode *mode;
 	struct detailed_pixel_timing *pt = &timing->data.pixel_data;
+	unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
+	unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
+	unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
+	unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
+	unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
+	unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
+	unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+	unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
 
 	/* ignore tiny modes */
-	if (((pt->hactive_hi << 8) | pt->hactive_lo) < 64 ||
-	    ((pt->vactive_hi << 8) | pt->hactive_lo) < 64)
+	if (hactive < 64 || vactive < 64)
 		return NULL;
 
-	if (pt->stereo) {
+	if (pt->misc & DRM_EDID_PT_STEREO) {
 		printk(KERN_WARNING "stereo mode not supported\n");
 		return NULL;
 	}
-	if (!pt->separate_sync) {
+	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
 		printk(KERN_WARNING "integrated sync not supported\n");
 		return NULL;
 	}
@@ -310,41 +319,36 @@
 	mode->type = DRM_MODE_TYPE_DRIVER;
 
 	if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
-		timing->pixel_clock = 1088;
+		timing->pixel_clock = cpu_to_le16(1088);
 
-	mode->clock = timing->pixel_clock * 10;
+	mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
 
-	mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo;
-	mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) |
-					      pt->hsync_offset_lo);
-	mode->hsync_end = mode->hsync_start +
-		((pt->hsync_pulse_width_hi << 8) |
-		 pt->hsync_pulse_width_lo);
-	mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
+	mode->hdisplay = hactive;
+	mode->hsync_start = mode->hdisplay + hsync_offset;
+	mode->hsync_end = mode->hsync_start + hsync_pulse_width;
+	mode->htotal = mode->hdisplay + hblank;
 
-	mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
-	mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) |
-					      pt->vsync_offset_lo);
-	mode->vsync_end = mode->vsync_start +
-		((pt->vsync_pulse_width_hi << 4) |
-		 pt->vsync_pulse_width_lo);
-	mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
+	mode->vdisplay = vactive;
+	mode->vsync_start = mode->vdisplay + vsync_offset;
+	mode->vsync_end = mode->vsync_start + vsync_pulse_width;
+	mode->vtotal = mode->vdisplay + vblank;
 
 	drm_mode_set_name(mode);
 
-	if (pt->interlaced)
+	if (pt->misc & DRM_EDID_PT_INTERLACED)
 		mode->flags |= DRM_MODE_FLAG_INTERLACE;
 
 	if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
-		pt->hsync_positive = 1;
-		pt->vsync_positive = 1;
+		pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
 	}
 
-	mode->flags |= pt->hsync_positive ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
-	mode->flags |= pt->vsync_positive ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+	mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
+		DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+	mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+		DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
 
-	mode->width_mm = pt->width_mm_lo | (pt->width_mm_hi << 8);
-	mode->height_mm = pt->height_mm_lo | (pt->height_mm_hi << 8);
+	mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
+	mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
 
 	if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
 		mode->width_mm *= 10;
@@ -465,7 +469,7 @@
 		struct drm_display_mode *newmode;
 
 		/* If std timings bytes are 1, 1 it's empty */
-		if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1)
+		if (t->hsize == 1 && t->vfreq_aspect == 1)
 			continue;
 
 		newmode = drm_mode_std(dev, &edid->standard_timings[i]);
@@ -498,54 +502,50 @@
 		struct detailed_non_pixel *data = &timing->data.other_data;
 		struct drm_display_mode *newmode;
 
-		/* EDID up to and including 1.2 may put monitor info here */
-		if (edid->version == 1 && edid->revision < 3)
-			continue;
+		/* X server check is version 1.1 or higher */
+		if (edid->version == 1 && edid->revision >= 1 &&
+		    !timing->pixel_clock) {
+			/* Other timing or info */
+			switch (data->type) {
+			case EDID_DETAIL_MONITOR_SERIAL:
+				break;
+			case EDID_DETAIL_MONITOR_STRING:
+				break;
+			case EDID_DETAIL_MONITOR_RANGE:
+				/* Get monitor range data */
+				break;
+			case EDID_DETAIL_MONITOR_NAME:
+				break;
+			case EDID_DETAIL_MONITOR_CPDATA:
+				break;
+			case EDID_DETAIL_STD_MODES:
+				/* Five modes per detailed section */
+				for (j = 0; j < 5; i++) {
+					struct std_timing *std;
+					struct drm_display_mode *newmode;
 
-		/* Detailed mode timing */
-		if (timing->pixel_clock) {
+					std = &data->data.timings[j];
+					newmode = drm_mode_std(dev, std);
+					if (newmode) {
+						drm_mode_probed_add(connector, newmode);
+						modes++;
+					}
+				}
+				break;
+			default:
+				break;
+			}
+		} else {
 			newmode = drm_mode_detailed(dev, edid, timing, quirks);
 			if (!newmode)
 				continue;
 
 			/* First detailed mode is preferred */
-			if (i == 0 && edid->preferred_timing)
+			if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
 				newmode->type |= DRM_MODE_TYPE_PREFERRED;
 			drm_mode_probed_add(connector, newmode);
 
 			modes++;
-			continue;
-		}
-
-		/* Other timing or info */
-		switch (data->type) {
-		case EDID_DETAIL_MONITOR_SERIAL:
-			break;
-		case EDID_DETAIL_MONITOR_STRING:
-			break;
-		case EDID_DETAIL_MONITOR_RANGE:
-			/* Get monitor range data */
-			break;
-		case EDID_DETAIL_MONITOR_NAME:
-			break;
-		case EDID_DETAIL_MONITOR_CPDATA:
-			break;
-		case EDID_DETAIL_STD_MODES:
-			/* Five modes per detailed section */
-			for (j = 0; j < 5; i++) {
-				struct std_timing *std;
-				struct drm_display_mode *newmode;
-
-				std = &data->data.timings[j];
-				newmode = drm_mode_std(dev, std);
-				if (newmode) {
-					drm_mode_probed_add(connector, newmode);
-					modes++;
-				}
-			}
-			break;
-		default:
-			break;
 		}
 	}
 
@@ -589,85 +589,13 @@
 }
 EXPORT_SYMBOL(drm_do_probe_ddc_edid);
 
-/**
- * Get EDID information.
- *
- * \param adapter : i2c device adaptor.
- * \param buf     : EDID data buffer to be filled
- * \param len     : EDID data buffer length
- * \return 0 on success or -1 on failure.
- *
- * Initialize DDC, then fetch EDID information
- * by calling drm_do_probe_ddc_edid function.
- */
-static int drm_ddc_read(struct i2c_adapter *adapter,
-			unsigned char *buf, int len)
-{
-	struct i2c_algo_bit_data *algo_data = adapter->algo_data;
-	int i, j;
-	int ret = -1;
-
-	algo_data->setscl(algo_data->data, 1);
-
-	for (i = 0; i < 1; i++) {
-		/* For some old monitors we need the
-		 * following process to initialize/stop DDC
-		 */
-		algo_data->setsda(algo_data->data, 1);
-		msleep(13);
-
-		algo_data->setscl(algo_data->data, 1);
-		for (j = 0; j < 5; j++) {
-			msleep(10);
-			if (algo_data->getscl(algo_data->data))
-				break;
-		}
-		if (j == 5)
-			continue;
-
-		algo_data->setsda(algo_data->data, 0);
-		msleep(15);
-		algo_data->setscl(algo_data->data, 0);
-		msleep(15);
-		algo_data->setsda(algo_data->data, 1);
-		msleep(15);
-
-		/* Do the real work */
-		ret = drm_do_probe_ddc_edid(adapter, buf, len);
-		algo_data->setsda(algo_data->data, 0);
-		algo_data->setscl(algo_data->data, 0);
-		msleep(15);
-
-		algo_data->setscl(algo_data->data, 1);
-		for (j = 0; j < 10; j++) {
-			msleep(10);
-			if (algo_data->getscl(algo_data->data))
-				break;
-		}
-
-		algo_data->setsda(algo_data->data, 1);
-		msleep(15);
-		algo_data->setscl(algo_data->data, 0);
-		algo_data->setsda(algo_data->data, 0);
-		if (ret == 0)
-			break;
-	}
-	/* Release the DDC lines when done or the Apple Cinema HD display
-	 * will switch off
-	 */
-	algo_data->setsda(algo_data->data, 1);
-	algo_data->setscl(algo_data->data, 1);
-
-	return ret;
-}
-
 static int drm_ddc_read_edid(struct drm_connector *connector,
 			     struct i2c_adapter *adapter,
 			     char *buf, int len)
 {
 	int ret;
 
-	ret = drm_ddc_read(adapter, buf, len);
+	ret = drm_do_probe_ddc_edid(adapter, buf, len);
 	if (ret != 0) {
 		dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
 			 drm_get_connector_name(connector));
@@ -839,22 +767,22 @@
 	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
 		edid_fixup_preferred(connector, quirks);
 
-	connector->display_info.serration_vsync = edid->serration_vsync;
-	connector->display_info.sync_on_green = edid->sync_on_green;
-	connector->display_info.composite_sync = edid->composite_sync;
-	connector->display_info.separate_syncs = edid->separate_syncs;
-	connector->display_info.blank_to_black = edid->blank_to_black;
-	connector->display_info.video_level = edid->video_level;
-	connector->display_info.digital = edid->digital;
+	connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0;
+	connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0;
+	connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0;
+	connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0;
+	connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0;
+	connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5;
+	connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0;
 	connector->display_info.width_mm = edid->width_cm * 10;
 	connector->display_info.height_mm = edid->height_cm * 10;
 	connector->display_info.gamma = edid->gamma;
-	connector->display_info.gtf_supported = edid->default_gtf;
-	connector->display_info.standard_color = edid->standard_color;
-	connector->display_info.display_type = edid->display_type;
-	connector->display_info.active_off_supported = edid->pm_active_off;
-	connector->display_info.suspend_supported = edid->pm_suspend;
-	connector->display_info.standby_supported = edid->pm_standby;
+	connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0;
+	connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0;
+	connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3;
+	connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0;
+	connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0;
+	connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0;
 	connector->display_info.gamma = edid->gamma;
 
 	return num_modes;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_fops.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_fops.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_fops.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_fops.c	2009-09-09 18:13:59.000000000 -0400
@@ -240,7 +240,7 @@
 
 	DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
 
-	priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
@@ -328,7 +328,7 @@
 
 	return 0;
       out_free:
-	drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+	kfree(priv);
 	filp->private_data = NULL;
 	return ret;
 }
@@ -471,7 +471,7 @@
 				drm_ctxbitmap_free(dev, pos->handle);
 
 				list_del(&pos->head);
-				drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+				kfree(pos);
 				--dev->ctx_count;
 			}
 		}
@@ -516,7 +516,7 @@
 
 	if (dev->driver->postclose)
 		dev->driver->postclose(dev, file_priv);
-	drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES);
+	kfree(file_priv);
 
 	/* ========================================================
 	 * End inline drm_release
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_gem.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_gem.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_gem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_gem.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,7 +89,7 @@
 	atomic_set(&dev->gtt_count, 0);
 	atomic_set(&dev->gtt_memory, 0);
 
-	mm = drm_calloc(1, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+	mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
 	if (!mm) {
 		DRM_ERROR("out of memory\n");
 		return -ENOMEM;
@@ -98,14 +98,14 @@
 	dev->mm_private = mm;
 
 	if (drm_ht_create(&mm->offset_hash, 19)) {
-		drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+		kfree(mm);
 		return -ENOMEM;
 	}
 
 	if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
 			DRM_FILE_PAGE_OFFSET_SIZE)) {
 		drm_ht_remove(&mm->offset_hash);
-		drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+		kfree(mm);
 		return -ENOMEM;
 	}
 
@@ -119,7 +119,7 @@
 
 	drm_mm_takedown(&mm->offset_manager);
 	drm_ht_remove(&mm->offset_hash);
-	drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
+	kfree(mm);
 	dev->mm_private = NULL;
 }
 
@@ -133,27 +133,30 @@
 
 	BUG_ON((size & (PAGE_SIZE - 1)) != 0);
 
-	obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+	if (!obj)
+		goto free;
 
 	obj->dev = dev;
 	obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
-	if (IS_ERR(obj->filp)) {
-		kfree(obj);
-		return NULL;
-	}
+	if (IS_ERR(obj->filp))
+		goto free;
 
 	kref_init(&obj->refcount);
 	kref_init(&obj->handlecount);
 	obj->size = size;
 	if (dev->driver->gem_init_object != NULL &&
 	    dev->driver->gem_init_object(obj) != 0) {
-		fput(obj->filp);
-		kfree(obj);
-		return NULL;
+		goto fput;
 	}
 	atomic_inc(&dev->object_count);
 	atomic_add(obj->size, &dev->object_memory);
 	return obj;
+fput:
+	fput(obj->filp);
+free:
+	kfree(obj);
+	return NULL;
 }
 EXPORT_SYMBOL(drm_gem_object_alloc);
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_hashtab.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_hashtab.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_hashtab.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_hashtab.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,8 +46,7 @@
 	ht->table = NULL;
 	ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
 	if (!ht->use_vmalloc) {
-		ht->table = drm_calloc(ht->size, sizeof(*ht->table),
-				       DRM_MEM_HASHTAB);
+		ht->table = kcalloc(ht->size, sizeof(*ht->table), GFP_KERNEL);
 	}
 	if (!ht->table) {
 		ht->use_vmalloc = 1;
@@ -62,6 +61,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(drm_ht_create);
 
 void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
 {
@@ -156,6 +156,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(drm_ht_just_insert_please);
 
 int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
 		     struct drm_hash_item **item)
@@ -169,6 +170,7 @@
 	*item = hlist_entry(list, struct drm_hash_item, head);
 	return 0;
 }
+EXPORT_SYMBOL(drm_ht_find_item);
 
 int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 {
@@ -197,8 +199,8 @@
 		if (ht->use_vmalloc)
 			vfree(ht->table);
 		else
-			drm_free(ht->table, ht->size * sizeof(*ht->table),
-				 DRM_MEM_HASHTAB);
+			kfree(ht->table);
 		ht->table = NULL;
 	}
 }
+EXPORT_SYMBOL(drm_ht_remove);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_ioctl.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_ioctl.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -93,7 +93,7 @@
 
 	master->unique_len = u->unique_len;
 	master->unique_size = u->unique_len + 1;
-	master->unique = drm_alloc(master->unique_size, DRM_MEM_DRIVER);
+	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
 	if (!master->unique)
 		return -ENOMEM;
 	if (copy_from_user(master->unique, u->unique, master->unique_len))
@@ -101,9 +101,8 @@
 
 	master->unique[master->unique_len] = '\0';
 
-	dev->devname =
-	    drm_alloc(strlen(dev->driver->pci_driver.name) +
-		      strlen(master->unique) + 2, DRM_MEM_DRIVER);
+	dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
+			       strlen(master->unique) + 2, GFP_KERNEL);
 	if (!dev->devname)
 		return -ENOMEM;
 
@@ -138,7 +137,7 @@
 
 	master->unique_len = 40;
 	master->unique_size = master->unique_len;
-	master->unique = drm_alloc(master->unique_size, DRM_MEM_DRIVER);
+	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
 	if (master->unique == NULL)
 		return -ENOMEM;
 
@@ -152,9 +151,8 @@
 	else
 		master->unique_len = len;
 
-	dev->devname =
-	    drm_alloc(strlen(dev->driver->pci_driver.name) + master->unique_len +
-		      2, DRM_MEM_DRIVER);
+	dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
+			       master->unique_len + 2, GFP_KERNEL);
 	if (dev->devname == NULL)
 		return -ENOMEM;
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_irq.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_irq.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -104,21 +104,13 @@
 
 	vblank_disable_fn((unsigned long)dev);
 
-	drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
-		 DRM_MEM_DRIVER);
-	drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
-		 dev->num_crtcs, DRM_MEM_DRIVER);
-	drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
-		 dev->num_crtcs, DRM_MEM_DRIVER);
-	drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
-		 dev->num_crtcs, DRM_MEM_DRIVER);
-	drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
-		 DRM_MEM_DRIVER);
-	drm_free(dev->last_vblank_wait,
-		 sizeof(*dev->last_vblank_wait) * dev->num_crtcs,
-		 DRM_MEM_DRIVER);
-	drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
-		 dev->num_crtcs, DRM_MEM_DRIVER);
+	kfree(dev->vbl_queue);
+	kfree(dev->_vblank_count);
+	kfree(dev->vblank_refcount);
+	kfree(dev->vblank_enabled);
+	kfree(dev->last_vblank);
+	kfree(dev->last_vblank_wait);
+	kfree(dev->vblank_inmodeset);
 
 	dev->num_crtcs = 0;
 }
@@ -132,37 +124,33 @@
 	spin_lock_init(&dev->vbl_lock);
 	dev->num_crtcs = num_crtcs;
 
-	dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
-				   DRM_MEM_DRIVER);
+	dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs,
+				 GFP_KERNEL);
 	if (!dev->vbl_queue)
 		goto err;
 
-	dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
-				      DRM_MEM_DRIVER);
+	dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL);
 	if (!dev->_vblank_count)
 		goto err;
 
-	dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
-					 DRM_MEM_DRIVER);
+	dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs,
+				       GFP_KERNEL);
 	if (!dev->vblank_refcount)
 		goto err;
 
-	dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
-					 DRM_MEM_DRIVER);
+	dev->vblank_enabled = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
 	if (!dev->vblank_enabled)
 		goto err;
 
-	dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
+	dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
 	if (!dev->last_vblank)
 		goto err;
 
-	dev->last_vblank_wait = drm_calloc(num_crtcs, sizeof(u32),
-					   DRM_MEM_DRIVER);
+	dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL);
 	if (!dev->last_vblank_wait)
 		goto err;
 
-	dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int),
-					 DRM_MEM_DRIVER);
+	dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL);
 	if (!dev->vblank_inmodeset)
 		goto err;
 
@@ -578,7 +566,7 @@
 
 	ret = drm_vblank_get(dev, crtc);
 	if (ret) {
-		DRM_ERROR("failed to acquire vblank counter, %d\n", ret);
+		DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
 		return ret;
 	}
 	seq = drm_vblank_count(dev, crtc);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_memory.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_memory.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_memory.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_memory.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,15 +36,6 @@
 #include <linux/highmem.h>
 #include "drmP.h"
 
-#ifdef DEBUG_MEMORY
-#include "drm_memory_debug.h"
-#else
-
-/** No-op. */
-void drm_mem_init(void)
-{
-}
-
 /**
  * Called when "/proc/dri/%dev%/mem" is read.
  *
@@ -64,28 +55,15 @@
 	return 0;
 }
 
-/** Wrapper around kmalloc() and kfree() */
-void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
-{
-	void *pt;
-
-	if (!(pt = kmalloc(size, GFP_KERNEL)))
-		return NULL;
-	if (oldpt && oldsize) {
-		memcpy(pt, oldpt, oldsize);
-		kfree(oldpt);
-	}
-	return pt;
-}
-
 #if __OS_HAS_AGP
 static void *agp_remap(unsigned long offset, unsigned long size,
 		       struct drm_device * dev)
 {
-	unsigned long *phys_addr_map, i, num_pages =
+	unsigned long i, num_pages =
 	    PAGE_ALIGN(size) / PAGE_SIZE;
 	struct drm_agp_mem *agpmem;
 	struct page **page_map;
+	struct page **phys_page_map;
 	void *addr;
 
 	size = PAGE_ALIGN(size);
@@ -112,10 +90,9 @@
 	if (!page_map)
 		return NULL;
 
-	phys_addr_map =
-	    agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+	phys_page_map = (agpmem->memory->pages + (offset - agpmem->bound) / PAGE_SIZE);
 	for (i = 0; i < num_pages; ++i)
-		page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+		page_map[i] = phys_page_map[i];
 	addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
 	vfree(page_map);
 
@@ -157,8 +134,6 @@
 
 #endif				/* agp */
 
-#endif				/* debug_memory */
-
 void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
 {
 	if (drm_core_has_AGP(dev) &&
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_mm.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_mm.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_mm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_mm.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,8 +42,11 @@
  */
 
 #include "drmP.h"
+#include "drm_mm.h"
 #include <linux/slab.h>
 
+#define MM_UNUSED_TARGET 4
+
 unsigned long drm_mm_tail_space(struct drm_mm *mm)
 {
 	struct list_head *tail_node;
@@ -74,16 +77,62 @@
 	return 0;
 }
 
+static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
+{
+	struct drm_mm_node *child;
+
+	if (atomic)
+		child = kmalloc(sizeof(*child), GFP_ATOMIC);
+	else
+		child = kmalloc(sizeof(*child), GFP_KERNEL);
+
+	if (unlikely(child == NULL)) {
+		spin_lock(&mm->unused_lock);
+		if (list_empty(&mm->unused_nodes))
+			child = NULL;
+		else {
+			child =
+			    list_entry(mm->unused_nodes.next,
+				       struct drm_mm_node, fl_entry);
+			list_del(&child->fl_entry);
+			--mm->num_unused;
+		}
+		spin_unlock(&mm->unused_lock);
+	}
+	return child;
+}
+
+int drm_mm_pre_get(struct drm_mm *mm)
+{
+	struct drm_mm_node *node;
+
+	spin_lock(&mm->unused_lock);
+	while (mm->num_unused < MM_UNUSED_TARGET) {
+		spin_unlock(&mm->unused_lock);
+		node = kmalloc(sizeof(*node), GFP_KERNEL);
+		spin_lock(&mm->unused_lock);
+
+		if (unlikely(node == NULL)) {
+			int ret = (mm->num_unused < 2) ? -ENOMEM : 0;
+			spin_unlock(&mm->unused_lock);
+			return ret;
+		}
+		++mm->num_unused;
+		list_add_tail(&node->fl_entry, &mm->unused_nodes);
+	}
+	spin_unlock(&mm->unused_lock);
+	return 0;
+}
+EXPORT_SYMBOL(drm_mm_pre_get);
 
 static int drm_mm_create_tail_node(struct drm_mm *mm,
-			    unsigned long start,
-			    unsigned long size)
+				   unsigned long start,
+				   unsigned long size, int atomic)
 {
 	struct drm_mm_node *child;
 
-	child = (struct drm_mm_node *)
-		drm_alloc(sizeof(*child), DRM_MEM_MM);
-	if (!child)
+	child = drm_mm_kmalloc(mm, atomic);
+	if (unlikely(child == NULL))
 		return -ENOMEM;
 
 	child->free = 1;
@@ -97,8 +146,7 @@
 	return 0;
 }
 
-
-int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
+int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size, int atomic)
 {
 	struct list_head *tail_node;
 	struct drm_mm_node *entry;
@@ -106,20 +154,21 @@
 	tail_node = mm->ml_entry.prev;
 	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
 	if (!entry->free) {
-		return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
+		return drm_mm_create_tail_node(mm, entry->start + entry->size,
+					       size, atomic);
 	}
 	entry->size += size;
 	return 0;
 }
 
 static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
-					    unsigned long size)
+						 unsigned long size,
+						 int atomic)
 {
 	struct drm_mm_node *child;
 
-	child = (struct drm_mm_node *)
-		drm_alloc(sizeof(*child), DRM_MEM_MM);
-	if (!child)
+	child = drm_mm_kmalloc(parent->mm, atomic);
+	if (unlikely(child == NULL))
 		return NULL;
 
 	INIT_LIST_HEAD(&child->fl_entry);
@@ -138,45 +187,45 @@
 }
 
 
-
-struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
-				unsigned long size, unsigned alignment)
+struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
+					     unsigned long size,
+					     unsigned alignment,
+					     int atomic)
 {
 
 	struct drm_mm_node *align_splitoff = NULL;
-	struct drm_mm_node *child;
 	unsigned tmp = 0;
 
 	if (alignment)
-		tmp = parent->start % alignment;
+		tmp = node->start % alignment;
 
 	if (tmp) {
-		align_splitoff = drm_mm_split_at_start(parent, alignment - tmp);
-		if (!align_splitoff)
+		align_splitoff =
+		    drm_mm_split_at_start(node, alignment - tmp, atomic);
+		if (unlikely(align_splitoff == NULL))
 			return NULL;
 	}
 
-	if (parent->size == size) {
-		list_del_init(&parent->fl_entry);
-		parent->free = 0;
-		return parent;
+	if (node->size == size) {
+		list_del_init(&node->fl_entry);
+		node->free = 0;
 	} else {
-		child = drm_mm_split_at_start(parent, size);
+		node = drm_mm_split_at_start(node, size, atomic);
 	}
 
 	if (align_splitoff)
 		drm_mm_put_block(align_splitoff);
 
-	return child;
+	return node;
 }
-EXPORT_SYMBOL(drm_mm_get_block);
+EXPORT_SYMBOL(drm_mm_get_block_generic);
 
 /*
  * Put a block. Merge with the previous and / or next block if they are free.
  * Otherwise add to the free stack.
  */
 
-void drm_mm_put_block(struct drm_mm_node * cur)
+void drm_mm_put_block(struct drm_mm_node *cur)
 {
 
 	struct drm_mm *mm = cur->mm;
@@ -188,21 +237,27 @@
 	int merged = 0;
 
 	if (cur_head->prev != root_head) {
-		prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
+		prev_node =
+		    list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
 		if (prev_node->free) {
 			prev_node->size += cur->size;
 			merged = 1;
 		}
 	}
 	if (cur_head->next != root_head) {
-		next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
+		next_node =
+		    list_entry(cur_head->next, struct drm_mm_node, ml_entry);
 		if (next_node->free) {
 			if (merged) {
 				prev_node->size += next_node->size;
 				list_del(&next_node->ml_entry);
 				list_del(&next_node->fl_entry);
-				drm_free(next_node, sizeof(*next_node),
-					 DRM_MEM_MM);
+				if (mm->num_unused < MM_UNUSED_TARGET) {
+					list_add(&next_node->fl_entry,
+						 &mm->unused_nodes);
+					++mm->num_unused;
+				} else
+					kfree(next_node);
 			} else {
 				next_node->size += cur->size;
 				next_node->start = cur->start;
@@ -215,14 +270,19 @@
 		list_add(&cur->fl_entry, &mm->fl_entry);
 	} else {
 		list_del(&cur->ml_entry);
-		drm_free(cur, sizeof(*cur), DRM_MEM_MM);
+		if (mm->num_unused < MM_UNUSED_TARGET) {
+			list_add(&cur->fl_entry, &mm->unused_nodes);
+			++mm->num_unused;
+		} else
+			kfree(cur);
 	}
 }
+
 EXPORT_SYMBOL(drm_mm_put_block);
 
-struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
-				  unsigned long size,
-				  unsigned alignment, int best_match)
+struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
+				       unsigned long size,
+				       unsigned alignment, int best_match)
 {
 	struct list_head *list;
 	const struct list_head *free_stack = &mm->fl_entry;
@@ -247,7 +307,6 @@
 				wasted += alignment - tmp;
 		}
 
-
 		if (entry->size >= size + wasted) {
 			if (!best_match)
 				return entry;
@@ -260,6 +319,7 @@
 
 	return best;
 }
+EXPORT_SYMBOL(drm_mm_search_free);
 
 int drm_mm_clean(struct drm_mm * mm)
 {
@@ -267,14 +327,17 @@
 
 	return (head->next->next == head);
 }
-EXPORT_SYMBOL(drm_mm_search_free);
+EXPORT_SYMBOL(drm_mm_clean);
 
 int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
 	INIT_LIST_HEAD(&mm->ml_entry);
 	INIT_LIST_HEAD(&mm->fl_entry);
+	INIT_LIST_HEAD(&mm->unused_nodes);
+	mm->num_unused = 0;
+	spin_lock_init(&mm->unused_lock);
 
-	return drm_mm_create_tail_node(mm, start, size);
+	return drm_mm_create_tail_node(mm, start, size, 0);
 }
 EXPORT_SYMBOL(drm_mm_init);
 
@@ -282,6 +345,7 @@
 {
 	struct list_head *bnode = mm->fl_entry.next;
 	struct drm_mm_node *entry;
+	struct drm_mm_node *next;
 
 	entry = list_entry(bnode, struct drm_mm_node, fl_entry);
 
@@ -293,7 +357,16 @@
 
 	list_del(&entry->fl_entry);
 	list_del(&entry->ml_entry);
+	kfree(entry);
 
-	drm_free(entry, sizeof(*entry), DRM_MEM_MM);
+	spin_lock(&mm->unused_lock);
+	list_for_each_entry_safe(entry, next, &mm->unused_nodes, fl_entry) {
+		list_del(&entry->fl_entry);
+		kfree(entry);
+		--mm->num_unused;
+	}
+	spin_unlock(&mm->unused_lock);
+
+	BUG_ON(mm->num_unused != 0);
 }
 EXPORT_SYMBOL(drm_mm_takedown);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_modes.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_modes.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_modes.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_modes.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,7 @@
 #include "drm.h"
 #include "drm_crtc.h"
 
+#define DRM_MODESET_DEBUG	"drm_mode"
 /**
  * drm_mode_debug_printmodeline - debug print a mode
  * @dev: DRM device
@@ -50,12 +51,13 @@
  */
 void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
 {
-	DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
-		  mode->base.id, mode->name, mode->vrefresh, mode->clock,
-		  mode->hdisplay, mode->hsync_start,
-		  mode->hsync_end, mode->htotal,
-		  mode->vdisplay, mode->vsync_start,
-		  mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+	DRM_DEBUG_MODE(DRM_MODESET_DEBUG,
+		"Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
+		mode->base.id, mode->name, mode->vrefresh, mode->clock,
+		mode->hdisplay, mode->hsync_start,
+		mode->hsync_end, mode->htotal,
+		mode->vdisplay, mode->vsync_start,
+		mode->vsync_end, mode->vtotal, mode->type, mode->flags);
 }
 EXPORT_SYMBOL(drm_mode_debug_printmodeline);
 
@@ -401,7 +403,9 @@
 			list_del(&mode->head);
 			if (verbose) {
 				drm_mode_debug_printmodeline(mode);
-				DRM_DEBUG("Not using %s mode %d\n", mode->name, mode->status);
+				DRM_DEBUG_MODE(DRM_MODESET_DEBUG,
+					"Not using %s mode %d\n",
+					mode->name, mode->status);
 			}
 			drm_mode_destroy(dev, mode);
 		}
@@ -562,6 +566,8 @@
 				found_it = 1;
 				/* if equal delete the probed mode */
 				mode->status = pmode->status;
+				/* Merge type bits together */
+				mode->type |= pmode->type;
 				list_del(&pmode->head);
 				drm_mode_destroy(connector->dev, pmode);
 				break;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_pci.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_pci.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,17 +55,6 @@
 	unsigned long addr;
 	size_t sz;
 #endif
-#ifdef DRM_DEBUG_MEMORY
-	int area = DRM_MEM_DMA;
-
-	spin_lock(&drm_mem_lock);
-	if ((drm_ram_used >> PAGE_SHIFT)
-	    > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
-		spin_unlock(&drm_mem_lock);
-		return 0;
-	}
-	spin_unlock(&drm_mem_lock);
-#endif
 
 	/* pci_alloc_consistent only guarantees alignment to the smallest
 	 * PAGE_SIZE order which is greater than or equal to the requested size.
@@ -86,27 +75,11 @@
 	dmah->size = size;
 	dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
 
-#ifdef DRM_DEBUG_MEMORY
 	if (dmah->vaddr == NULL) {
-		spin_lock(&drm_mem_lock);
-		++drm_mem_stats[area].fail_count;
-		spin_unlock(&drm_mem_lock);
 		kfree(dmah);
 		return NULL;
 	}
 
-	spin_lock(&drm_mem_lock);
-	++drm_mem_stats[area].succeed_count;
-	drm_mem_stats[area].bytes_allocated += size;
-	drm_ram_used += size;
-	spin_unlock(&drm_mem_lock);
-#else
-	if (dmah->vaddr == NULL) {
-		kfree(dmah);
-		return NULL;
-	}
-#endif
-
 	memset(dmah->vaddr, 0, size);
 
 	/* XXX - Is virt_to_page() legal for consistent mem? */
@@ -132,17 +105,8 @@
 	unsigned long addr;
 	size_t sz;
 #endif
-#ifdef DRM_DEBUG_MEMORY
-	int area = DRM_MEM_DMA;
-	int alloc_count;
-	int free_count;
-#endif
 
-	if (!dmah->vaddr) {
-#ifdef DRM_DEBUG_MEMORY
-		DRM_MEM_ERROR(area, "Attempt to free address 0\n");
-#endif
-	} else {
+	if (dmah->vaddr) {
 		/* XXX - Is virt_to_page() legal for consistent mem? */
 		/* Unreserve */
 		for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
@@ -152,21 +116,6 @@
 		dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
 				  dmah->busaddr);
 	}
-
-#ifdef DRM_DEBUG_MEMORY
-	spin_lock(&drm_mem_lock);
-	free_count = ++drm_mem_stats[area].free_count;
-	alloc_count = drm_mem_stats[area].succeed_count;
-	drm_mem_stats[area].bytes_freed += size;
-	drm_ram_used -= size;
-	spin_unlock(&drm_mem_lock);
-	if (free_count > alloc_count) {
-		DRM_MEM_ERROR(area,
-			      "Excess frees: %d frees, %d allocs\n",
-			      free_count, alloc_count);
-	}
-#endif
-
 }
 
 /**
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_proc.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_proc.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_proc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_proc.c	2009-09-09 18:13:59.000000000 -0400
@@ -105,13 +105,12 @@
 		    (dev->driver->driver_features & features) != features)
 			continue;
 
-		tmp = drm_alloc(sizeof(struct drm_info_node), _DRM_DRIVER);
+		tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
 		ent = create_proc_entry(files[i].name, S_IFREG | S_IRUGO, root);
 		if (!ent) {
 			DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
 				  name, files[i].name);
-			drm_free(tmp, sizeof(struct drm_info_node),
-				 _DRM_DRIVER);
+			kfree(tmp);
 			ret = -1;
 			goto fail;
 		}
@@ -192,8 +191,7 @@
 				remove_proc_entry(files[i].name,
 						  minor->proc_root);
 				list_del(pos);
-				drm_free(tmp, sizeof(struct drm_info_node),
-					 _DRM_DRIVER);
+				kfree(tmp);
 			}
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_scatter.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_scatter.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_scatter.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_scatter.c	2009-09-09 18:13:59.000000000 -0400
@@ -58,11 +58,9 @@
 
 	vfree(entry->virtual);
 
-	drm_free(entry->busaddr,
-		 entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
-	drm_free(entry->pagelist,
-		 entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
-	drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+	kfree(entry->busaddr);
+	kfree(entry->pagelist);
+	kfree(entry);
 }
 
 #ifdef _LP64
@@ -84,7 +82,7 @@
 	if (dev->sg)
 		return -EINVAL;
 
-	entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -93,34 +91,27 @@
 	DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
 
 	entry->pages = pages;
-	entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
-				    DRM_MEM_PAGES);
+	entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL);
 	if (!entry->pagelist) {
-		drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+		kfree(entry);
 		return -ENOMEM;
 	}
 
 	memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
 
-	entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr),
-				   DRM_MEM_PAGES);
+	entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL);
 	if (!entry->busaddr) {
-		drm_free(entry->pagelist,
-			 entry->pages * sizeof(*entry->pagelist),
-			 DRM_MEM_PAGES);
-		drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+		kfree(entry->pagelist);
+		kfree(entry);
 		return -ENOMEM;
 	}
 	memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
 
 	entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
 	if (!entry->virtual) {
-		drm_free(entry->busaddr,
-			 entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
-		drm_free(entry->pagelist,
-			 entry->pages * sizeof(*entry->pagelist),
-			 DRM_MEM_PAGES);
-		drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+		kfree(entry->busaddr);
+		kfree(entry->pagelist);
+		kfree(entry);
 		return -ENOMEM;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_sman.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_sman.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_sman.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_sman.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,9 +48,7 @@
 {
 	drm_ht_remove(&sman->user_hash_tab);
 	drm_ht_remove(&sman->owner_hash_tab);
-	if (sman->mm)
-		drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm),
-			 DRM_MEM_MM);
+	kfree(sman->mm);
 }
 
 EXPORT_SYMBOL(drm_sman_takedown);
@@ -61,8 +59,9 @@
 {
 	int ret = 0;
 
-	sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
-						DRM_MEM_MM);
+	sman->mm = (struct drm_sman_mm *) kcalloc(num_managers,
+						  sizeof(*sman->mm),
+						  GFP_KERNEL);
 	if (!sman->mm) {
 		ret = -ENOMEM;
 		goto out;
@@ -78,7 +77,7 @@
 
 	drm_ht_remove(&sman->owner_hash_tab);
 out1:
-	drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM);
+	kfree(sman->mm);
 out:
 	return ret;
 }
@@ -110,7 +109,7 @@
 {
 	struct drm_mm *mm = (struct drm_mm *) private;
 	drm_mm_takedown(mm);
-	drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+	kfree(mm);
 }
 
 static unsigned long drm_sman_mm_offset(void *private, void *ref)
@@ -130,7 +129,7 @@
 	BUG_ON(manager >= sman->num_managers);
 
 	sman_mm = &sman->mm[manager];
-	mm = drm_calloc(1, sizeof(*mm), DRM_MEM_MM);
+	mm = kzalloc(sizeof(*mm), GFP_KERNEL);
 	if (!mm) {
 		return -ENOMEM;
 	}
@@ -138,7 +137,7 @@
 	ret = drm_mm_init(mm, start, size);
 
 	if (ret) {
-		drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+		kfree(mm);
 		return ret;
 	}
 
@@ -176,7 +175,7 @@
 				      owner_hash);
 	}
 
-	owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM);
+	owner_item = kzalloc(sizeof(*owner_item), GFP_KERNEL);
 	if (!owner_item)
 		goto out;
 
@@ -189,7 +188,7 @@
 	return owner_item;
 
 out1:
-	drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+	kfree(owner_item);
 out:
 	return NULL;
 }
@@ -212,7 +211,7 @@
 		return NULL;
 	}
 
-	memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM);
+	memblock = kzalloc(sizeof(*memblock), GFP_KERNEL);
 
 	if (!memblock)
 		goto out;
@@ -237,7 +236,7 @@
 out2:
 	drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
 out1:
-	drm_free(memblock, sizeof(*memblock), DRM_MEM_MM);
+	kfree(memblock);
 out:
 	sman_mm->free(sman_mm->private, tmp);
 
@@ -253,7 +252,7 @@
 	list_del(&item->owner_list);
 	drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
 	item->mm->free(item->mm->private, item->mm_info);
-	drm_free(item, sizeof(*item), DRM_MEM_MM);
+	kfree(item);
 }
 
 int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
@@ -277,7 +276,7 @@
 {
 	list_del(&owner_item->sman_list);
 	drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
-	drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+	kfree(owner_item);
 }
 
 int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_stub.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_stub.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_stub.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_stub.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,7 +51,22 @@
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 struct dentry *drm_debugfs_root;
+void drm_ut_debug_printk(unsigned int request_level,
+			 const char *prefix,
+			 const char *function_name,
+			 const char *format, ...)
+{
+	va_list args;
 
+	if (drm_debug & request_level) {
+		if (function_name)
+			printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
+		va_start(args, format);
+		vprintk(format, args);
+		va_end(args);
+	}
+}
+EXPORT_SYMBOL(drm_ut_debug_printk);
 static int drm_minor_get_id(struct drm_device *dev, int type)
 {
 	int new_id;
@@ -92,7 +107,7 @@
 {
 	struct drm_master *master;
 
-	master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER);
+	master = kzalloc(sizeof(*master), GFP_KERNEL);
 	if (!master)
 		return NULL;
 
@@ -134,7 +149,7 @@
 	}
 
 	if (master->unique) {
-		drm_free(master->unique, master->unique_size, DRM_MEM_DRIVER);
+		kfree(master->unique);
 		master->unique = NULL;
 		master->unique_len = 0;
 	}
@@ -142,12 +157,12 @@
 	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
 		list_del(&pt->head);
 		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
-		drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+		kfree(pt);
 	}
 
 	drm_ht_remove(&master->magiclist);
 
-	drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
+	kfree(master);
 }
 
 void drm_master_put(struct drm_master **master)
@@ -328,7 +343,7 @@
 #if defined(CONFIG_DEBUG_FS)
 	ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
 	if (ret) {
-		DRM_ERROR("DRM: Failed to initialize /debugfs/dri.\n");
+		DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
 		goto err_g2;
 	}
 #endif
@@ -375,7 +390,7 @@
 
 	DRM_DEBUG("\n");
 
-	dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return -ENOMEM;
 
@@ -428,7 +443,7 @@
 err_g2:
 	pci_disable_device(pdev);
 err_g1:
-	drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+	kfree(dev);
 	return ret;
 }
 EXPORT_SYMBOL(drm_get_dev);
@@ -474,7 +489,7 @@
  */
 void drm_put_dev(struct drm_device *dev)
 {
-	struct drm_driver *driver = dev->driver;
+	struct drm_driver *driver;
 	struct drm_map_list *r_list, *list_temp;
 
 	DRM_DEBUG("\n");
@@ -483,6 +498,7 @@
 		DRM_ERROR("cleanup called no dev\n");
 		return;
 	}
+	driver = dev->driver;
 
 	drm_vblank_cleanup(dev);
 
@@ -501,7 +517,7 @@
 		dev->driver->unload(dev);
 
 	if (drm_core_has_AGP(dev) && dev->agp) {
-		drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
+		kfree(dev->agp);
 		dev->agp = NULL;
 	}
 
@@ -520,10 +536,9 @@
 	drm_put_minor(&dev->primary);
 
 	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname) + 1,
-			 DRM_MEM_DRIVER);
+		kfree(dev->devname);
 		dev->devname = NULL;
 	}
-	drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+	kfree(dev);
 }
 EXPORT_SYMBOL(drm_put_dev);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_sysfs.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_sysfs.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_sysfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_sysfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,44 +22,50 @@
 #define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
 #define to_drm_connector(d) container_of(d, struct drm_connector, kdev)
 
+static struct device_type drm_sysfs_device_minor = {
+	.name = "drm_minor"
+};
+
 /**
- * drm_sysfs_suspend - DRM class suspend hook
+ * drm_class_suspend - DRM class suspend hook
  * @dev: Linux device to suspend
  * @state: power state to enter
  *
  * Just figures out what the actual struct drm_device associated with
  * @dev is and calls its suspend hook, if present.
  */
-static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+static int drm_class_suspend(struct device *dev, pm_message_t state)
 {
-	struct drm_minor *drm_minor = to_drm_minor(dev);
-	struct drm_device *drm_dev = drm_minor->dev;
-
-	if (drm_minor->type == DRM_MINOR_LEGACY &&
-	    !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
-	    drm_dev->driver->suspend)
-		return drm_dev->driver->suspend(drm_dev, state);
+	if (dev->type == &drm_sysfs_device_minor) {
+		struct drm_minor *drm_minor = to_drm_minor(dev);
+		struct drm_device *drm_dev = drm_minor->dev;
 
+		if (drm_minor->type == DRM_MINOR_LEGACY &&
+		    !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
+		    drm_dev->driver->suspend)
+			return drm_dev->driver->suspend(drm_dev, state);
+	}
 	return 0;
 }
 
 /**
- * drm_sysfs_resume - DRM class resume hook
+ * drm_class_resume - DRM class resume hook
  * @dev: Linux device to resume
  *
  * Just figures out what the actual struct drm_device associated with
  * @dev is and calls its resume hook, if present.
  */
-static int drm_sysfs_resume(struct device *dev)
+static int drm_class_resume(struct device *dev)
 {
-	struct drm_minor *drm_minor = to_drm_minor(dev);
-	struct drm_device *drm_dev = drm_minor->dev;
-
-	if (drm_minor->type == DRM_MINOR_LEGACY &&
-	    !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
-	    drm_dev->driver->resume)
-		return drm_dev->driver->resume(drm_dev);
+	if (dev->type == &drm_sysfs_device_minor) {
+		struct drm_minor *drm_minor = to_drm_minor(dev);
+		struct drm_device *drm_dev = drm_minor->dev;
 
+		if (drm_minor->type == DRM_MINOR_LEGACY &&
+		    !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
+		    drm_dev->driver->resume)
+			return drm_dev->driver->resume(drm_dev);
+	}
 	return 0;
 }
 
@@ -70,6 +76,11 @@
 		       CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
 }
 
+static char *drm_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
+}
+
 static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
 
 /**
@@ -94,13 +105,15 @@
 		goto err_out;
 	}
 
-	class->suspend = drm_sysfs_suspend;
-	class->resume = drm_sysfs_resume;
+	class->suspend = drm_class_suspend;
+	class->resume = drm_class_resume;
 
 	err = class_create_file(class, &class_attr_version);
 	if (err)
 		goto err_out_class;
 
+	class->nodename = drm_nodename;
+
 	return class;
 
 err_out_class:
@@ -473,6 +486,7 @@
 	minor->kdev.class = drm_class;
 	minor->kdev.release = drm_sysfs_device_release;
 	minor->kdev.devt = minor->device;
+	minor->kdev.type = &drm_sysfs_device_minor;
 	if (minor->type == DRM_MINOR_CONTROL)
 		minor_str = "controlD%d";
         else if (minor->type == DRM_MINOR_RENDER)
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_vm.c linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_vm.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/drm_vm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/drm_vm.c	2009-09-09 18:13:59.000000000 -0400
@@ -144,14 +144,14 @@
 		 * Get the page, inc the use count, and return it
 		 */
 		offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
-		page = virt_to_page(__va(agpmem->memory->memory[offset]));
+		page = agpmem->memory->pages[offset];
 		get_page(page);
 		vmf->page = page;
 
 		DRM_DEBUG
 		    ("baddr = 0x%llx page = 0x%p, offset = 0x%llx, count=%d\n",
 		     (unsigned long long)baddr,
-		     __va(agpmem->memory->memory[offset]),
+		     agpmem->memory->pages[offset],
 		     (unsigned long long)offset,
 		     page_count(page));
 		return 0;
@@ -227,7 +227,7 @@
 			found_maps++;
 		if (pt->vma == vma) {
 			list_del(&pt->head);
-			drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+			kfree(pt);
 		}
 	}
 
@@ -273,7 +273,7 @@
 				DRM_ERROR("tried to rmmap GEM object\n");
 				break;
 			}
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			kfree(map);
 		}
 	}
 	mutex_unlock(&dev->struct_mutex);
@@ -414,7 +414,7 @@
 		  vma->vm_start, vma->vm_end - vma->vm_start);
 	atomic_inc(&dev->vma_count);
 
-	vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
+	vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL);
 	if (vma_entry) {
 		vma_entry->vma = vma;
 		vma_entry->pid = current->pid;
@@ -454,7 +454,7 @@
 	list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
 		if (pt->vma == vma) {
 			list_del(&pt->head);
-			drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+			kfree(pt);
 			break;
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i810/i810_dma.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i810/i810_dma.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i810/i810_dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i810/i810_dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -227,8 +227,7 @@
 			/* Need to rewrite hardware status page */
 			I810_WRITE(0x02080, 0x1ffff000);
 		}
-		drm_free(dev->dev_private, sizeof(drm_i810_private_t),
-			 DRM_MEM_DRIVER);
+		kfree(dev->dev_private);
 		dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
@@ -439,8 +438,7 @@
 	switch (init->func) {
 	case I810_INIT_DMA_1_4:
 		DRM_INFO("Using v1.4 init.\n");
-		dev_priv = drm_alloc(sizeof(drm_i810_private_t),
-				     DRM_MEM_DRIVER);
+		dev_priv = kmalloc(sizeof(drm_i810_private_t), GFP_KERNEL);
 		if (dev_priv == NULL)
 			return -ENOMEM;
 		retcode = i810_dma_initialize(dev, dev_priv, init);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i830/i830_dma.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i830/i830_dma.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i830/i830_dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i830/i830_dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -232,8 +232,7 @@
 			I830_WRITE(0x02080, 0x1ffff000);
 		}
 
-		drm_free(dev->dev_private, sizeof(drm_i830_private_t),
-			 DRM_MEM_DRIVER);
+		kfree(dev->dev_private);
 		dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
@@ -459,8 +458,7 @@
 
 	switch (init->func) {
 	case I830_INIT_DMA:
-		dev_priv = drm_alloc(sizeof(drm_i830_private_t),
-				     DRM_MEM_DRIVER);
+		dev_priv = kmalloc(sizeof(drm_i830_private_t), GFP_KERNEL);
 		if (dev_priv == NULL)
 			return -ENOMEM;
 		retcode = i830_dma_initialize(dev, dev_priv, init);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_ch7017.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_ch7017.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_ch7017.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_ch7017.c	2009-09-09 18:13:59.000000000 -0400
@@ -176,19 +176,20 @@
 
 static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
 {
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	u8 out_buf[2];
 	u8 in_buf[2];
 
 	struct i2c_msg msgs[] = {
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = 0,
 			.len = 1,
 			.buf = out_buf,
 		},
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = I2C_M_RD,
 			.len = 1,
 			.buf = in_buf,
@@ -208,10 +209,11 @@
 
 static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
 {
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	uint8_t out_buf[2];
 	struct i2c_msg msg = {
-		.addr = i2cbus->slave_addr,
+		.addr = dvo->slave_addr,
 		.flags = 0,
 		.len = 2,
 		.buf = out_buf,
@@ -228,8 +230,9 @@
 
 /** Probes for a CH7017 on the given bus and slave address. */
 static bool ch7017_init(struct intel_dvo_device *dvo,
-			struct intel_i2c_chan *i2cbus)
+			struct i2c_adapter *adapter)
 {
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	struct ch7017_priv *priv;
 	uint8_t val;
 
@@ -237,8 +240,7 @@
 	if (priv == NULL)
 		return false;
 
-	dvo->i2c_bus = i2cbus;
-	dvo->i2c_bus->slave_addr = dvo->slave_addr;
+	dvo->i2c_bus = adapter;
 	dvo->dev_priv = priv;
 
 	if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
@@ -248,7 +250,7 @@
 	    val != CH7018_DEVICE_ID_VALUE &&
 	    val != CH7019_DEVICE_ID_VALUE) {
 		DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n",
-			  val, i2cbus->adapter.name,i2cbus->slave_addr);
+			  val, i2cbus->adapter.name,dvo->slave_addr);
 		goto fail;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_ch7xxx.c	2009-09-09 18:13:59.000000000 -0400
@@ -123,19 +123,20 @@
 static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
 	struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	u8 out_buf[2];
 	u8 in_buf[2];
 
 	struct i2c_msg msgs[] = {
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = 0,
 			.len = 1,
 			.buf = out_buf,
 		},
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = I2C_M_RD,
 			.len = 1,
 			.buf = in_buf,
@@ -152,7 +153,7 @@
 
 	if (!ch7xxx->quiet) {
 		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
 }
@@ -161,10 +162,11 @@
 static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
 	struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	uint8_t out_buf[2];
 	struct i2c_msg msg = {
-		.addr = i2cbus->slave_addr,
+		.addr = dvo->slave_addr,
 		.flags = 0,
 		.len = 2,
 		.buf = out_buf,
@@ -178,14 +180,14 @@
 
 	if (!ch7xxx->quiet) {
 		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
 	return false;
 }
 
 static bool ch7xxx_init(struct intel_dvo_device *dvo,
-			struct intel_i2c_chan *i2cbus)
+			struct i2c_adapter *adapter)
 {
 	/* this will detect the CH7xxx chip on the specified i2c bus */
 	struct ch7xxx_priv *ch7xxx;
@@ -196,8 +198,7 @@
 	if (ch7xxx == NULL)
 		return false;
 
-	dvo->i2c_bus = i2cbus;
-	dvo->i2c_bus->slave_addr = dvo->slave_addr;
+	dvo->i2c_bus = adapter;
 	dvo->dev_priv = ch7xxx;
 	ch7xxx->quiet = true;
 
@@ -207,7 +208,7 @@
 	name = ch7xxx_get_id(vendor);
 	if (!name) {
 		DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
-			  vendor, i2cbus->adapter.name, i2cbus->slave_addr);
+			  vendor, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 
@@ -217,7 +218,7 @@
 
 	if (device != CH7xxx_DID) {
 		DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
-			  vendor, i2cbus->adapter.name, i2cbus->slave_addr);
+			  vendor, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo.h linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo.h	2009-09-09 18:13:59.000000000 -0400
@@ -37,7 +37,7 @@
 	/* GPIO register used for i2c bus to control this device */
 	u32 gpio;
 	int slave_addr;
-	struct intel_i2c_chan *i2c_bus;
+	struct i2c_adapter *i2c_bus;
 
 	const struct intel_dvo_dev_ops *dev_ops;
 	void *dev_priv;
@@ -52,7 +52,7 @@
 	 * Returns NULL if the device does not exist.
 	 */
 	bool (*init)(struct intel_dvo_device *dvo,
-		     struct intel_i2c_chan *i2cbus);
+		     struct i2c_adapter *i2cbus);
 
 	/*
 	 * Called to allow the output a chance to create properties after the
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_ivch.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_ivch.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_ivch.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_ivch.c	2009-09-09 18:13:59.000000000 -0400
@@ -169,13 +169,14 @@
 static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
 {
 	struct ivch_priv *priv = dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	u8 out_buf[1];
 	u8 in_buf[2];
 
 	struct i2c_msg msgs[] = {
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = I2C_M_RD,
 			.len = 0,
 		},
@@ -186,7 +187,7 @@
 			.buf = out_buf,
 		},
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = I2C_M_RD | I2C_M_NOSTART,
 			.len = 2,
 			.buf = in_buf,
@@ -202,7 +203,7 @@
 
 	if (!priv->quiet) {
 		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
 }
@@ -211,10 +212,11 @@
 static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
 {
 	struct ivch_priv *priv = dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	u8 out_buf[3];
 	struct i2c_msg msg = {
-		.addr = i2cbus->slave_addr,
+		.addr = dvo->slave_addr,
 		.flags = 0,
 		.len = 3,
 		.buf = out_buf,
@@ -229,7 +231,7 @@
 
 	if (!priv->quiet) {
 		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
 	return false;
@@ -237,7 +239,7 @@
 
 /** Probes the given bus and slave address for an ivch */
 static bool ivch_init(struct intel_dvo_device *dvo,
-		      struct intel_i2c_chan *i2cbus)
+		      struct i2c_adapter *adapter)
 {
 	struct ivch_priv *priv;
 	uint16_t temp;
@@ -246,8 +248,7 @@
 	if (priv == NULL)
 		return false;
 
-	dvo->i2c_bus = i2cbus;
-	dvo->i2c_bus->slave_addr = dvo->slave_addr;
+	dvo->i2c_bus = adapter;
 	dvo->dev_priv = priv;
 	priv->quiet = true;
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_sil164.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_sil164.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_sil164.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_sil164.c	2009-09-09 18:13:59.000000000 -0400
@@ -76,19 +76,20 @@
 static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
 	struct sil164_priv *sil = dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	u8 out_buf[2];
 	u8 in_buf[2];
 
 	struct i2c_msg msgs[] = {
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = 0,
 			.len = 1,
 			.buf = out_buf,
 		},
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = I2C_M_RD,
 			.len = 1,
 			.buf = in_buf,
@@ -105,7 +106,7 @@
 
 	if (!sil->quiet) {
 		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
 }
@@ -113,10 +114,11 @@
 static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
 	struct sil164_priv *sil= dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	uint8_t out_buf[2];
 	struct i2c_msg msg = {
-		.addr = i2cbus->slave_addr,
+		.addr = dvo->slave_addr,
 		.flags = 0,
 		.len = 2,
 		.buf = out_buf,
@@ -130,7 +132,7 @@
 
 	if (!sil->quiet) {
 		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
 	return false;
@@ -138,7 +140,7 @@
 
 /* Silicon Image 164 driver for chip on i2c bus */
 static bool sil164_init(struct intel_dvo_device *dvo,
-			struct intel_i2c_chan *i2cbus)
+			struct i2c_adapter *adapter)
 {
 	/* this will detect the SIL164 chip on the specified i2c bus */
 	struct sil164_priv *sil;
@@ -148,8 +150,7 @@
 	if (sil == NULL)
 		return false;
 
-	dvo->i2c_bus = i2cbus;
-	dvo->i2c_bus->slave_addr = dvo->slave_addr;
+	dvo->i2c_bus = adapter;
 	dvo->dev_priv = sil;
 	sil->quiet = true;
 
@@ -158,7 +159,7 @@
 
 	if (ch != (SIL164_VID & 0xff)) {
 		DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
-			  ch, i2cbus->adapter.name, i2cbus->slave_addr);
+			  ch, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 
@@ -167,7 +168,7 @@
 
 	if (ch != (SIL164_DID & 0xff)) {
 		DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
-			  ch, i2cbus->adapter.name, i2cbus->slave_addr);
+			  ch, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 	sil->quiet = false;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_tfp410.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_tfp410.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/dvo_tfp410.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/dvo_tfp410.c	2009-09-09 18:13:59.000000000 -0400
@@ -101,19 +101,20 @@
 static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
 	struct tfp410_priv *tfp = dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	u8 out_buf[2];
 	u8 in_buf[2];
 
 	struct i2c_msg msgs[] = {
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = 0,
 			.len = 1,
 			.buf = out_buf,
 		},
 		{
-			.addr = i2cbus->slave_addr,
+			.addr = dvo->slave_addr,
 			.flags = I2C_M_RD,
 			.len = 1,
 			.buf = in_buf,
@@ -130,7 +131,7 @@
 
 	if (!tfp->quiet) {
 		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
 }
@@ -138,10 +139,11 @@
 static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
 	struct tfp410_priv *tfp = dvo->dev_priv;
-	struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
 	uint8_t out_buf[2];
 	struct i2c_msg msg = {
-		.addr = i2cbus->slave_addr,
+		.addr = dvo->slave_addr,
 		.flags = 0,
 		.len = 2,
 		.buf = out_buf,
@@ -155,7 +157,7 @@
 
 	if (!tfp->quiet) {
 		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-			  addr, i2cbus->adapter.name, i2cbus->slave_addr);
+			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
 	return false;
@@ -174,7 +176,7 @@
 
 /* Ti TFP410 driver for chip on i2c bus */
 static bool tfp410_init(struct intel_dvo_device *dvo,
-			struct intel_i2c_chan *i2cbus)
+			struct i2c_adapter *adapter)
 {
 	/* this will detect the tfp410 chip on the specified i2c bus */
 	struct tfp410_priv *tfp;
@@ -184,20 +186,19 @@
 	if (tfp == NULL)
 		return false;
 
-	dvo->i2c_bus = i2cbus;
-	dvo->i2c_bus->slave_addr = dvo->slave_addr;
+	dvo->i2c_bus = adapter;
 	dvo->dev_priv = tfp;
 	tfp->quiet = true;
 
 	if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) {
 		DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n",
-			  id, i2cbus->adapter.name, i2cbus->slave_addr);
+			  id, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 
 	if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) {
 		DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n",
-			  id, i2cbus->adapter.name, i2cbus->slave_addr);
+			  id, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 	tfp->quiet = false;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_dma.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_dma.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,8 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
+#define I915_DRV	"i915_drv"
+
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
  * the head pointer changes, so that EBUSY only happens if the ring
@@ -99,7 +101,7 @@
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 
 	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-	DRM_DEBUG("Enabled hardware status page\n");
+	DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
 	return 0;
 }
 
@@ -185,7 +187,8 @@
 		master_priv->sarea_priv = (drm_i915_sarea_t *)
 			((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
 	} else {
-		DRM_DEBUG("sarea not found assuming DRI2 userspace\n");
+		DRM_DEBUG_DRIVER(I915_DRV,
+				"sarea not found assuming DRI2 userspace\n");
 	}
 
 	if (init->ring_size != 0) {
@@ -235,7 +238,7 @@
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	DRM_DEBUG("%s\n", __func__);
+	DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
 
 	if (dev_priv->ring.map.handle == NULL) {
 		DRM_ERROR("can not ioremap virtual address for"
@@ -248,13 +251,14 @@
 		DRM_ERROR("Can not find hardware status page\n");
 		return -EINVAL;
 	}
-	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+	DRM_DEBUG_DRIVER(I915_DRV, "hw status page @ %p\n",
+				dev_priv->hw_status_page);
 
 	if (dev_priv->status_gfx_addr != 0)
 		I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
 	else
 		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
-	DRM_DEBUG("Enabled hardware status page\n");
+	DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
 
 	return 0;
 }
@@ -548,10 +552,10 @@
 	if (!master_priv->sarea_priv)
 		return -EINVAL;
 
-	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-		  __func__,
-		  dev_priv->current_page,
-		  master_priv->sarea_priv->pf_current_page);
+	DRM_DEBUG_DRIVER(I915_DRV, "%s: page=%d pfCurrentPage=%d\n",
+			  __func__,
+			 dev_priv->current_page,
+			 master_priv->sarea_priv->pf_current_page);
 
 	i915_kernel_lost_context(dev);
 
@@ -629,8 +633,9 @@
 		return -EINVAL;
 	}
 
-	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
-		  batch->start, batch->used, batch->num_cliprects);
+	DRM_DEBUG_DRIVER(I915_DRV,
+			"i915 batchbuffer, start %x used %d cliprects %d\n",
+			batch->start, batch->used, batch->num_cliprects);
 
 	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
@@ -638,9 +643,9 @@
 		return -EINVAL;
 
 	if (batch->num_cliprects) {
-		cliprects = drm_calloc(batch->num_cliprects,
-				       sizeof(struct drm_clip_rect),
-				       DRM_MEM_DRIVER);
+		cliprects = kcalloc(batch->num_cliprects,
+				    sizeof(struct drm_clip_rect),
+				    GFP_KERNEL);
 		if (cliprects == NULL)
 			return -ENOMEM;
 
@@ -659,9 +664,7 @@
 		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 
 fail_free:
-	drm_free(cliprects,
-		 batch->num_cliprects * sizeof(struct drm_clip_rect),
-		 DRM_MEM_DRIVER);
+	kfree(cliprects);
 
 	return ret;
 }
@@ -678,15 +681,16 @@
 	void *batch_data;
 	int ret;
 
-	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
-		  cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
+	DRM_DEBUG_DRIVER(I915_DRV,
+			"i915 cmdbuffer, buf %p sz %d cliprects %d\n",
+			cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
 
 	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 	if (cmdbuf->num_cliprects < 0)
 		return -EINVAL;
 
-	batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER);
+	batch_data = kmalloc(cmdbuf->sz, GFP_KERNEL);
 	if (batch_data == NULL)
 		return -ENOMEM;
 
@@ -695,9 +699,8 @@
 		goto fail_batch_free;
 
 	if (cmdbuf->num_cliprects) {
-		cliprects = drm_calloc(cmdbuf->num_cliprects,
-				       sizeof(struct drm_clip_rect),
-				       DRM_MEM_DRIVER);
+		cliprects = kcalloc(cmdbuf->num_cliprects,
+				    sizeof(struct drm_clip_rect), GFP_KERNEL);
 		if (cliprects == NULL)
 			goto fail_batch_free;
 
@@ -720,11 +723,9 @@
 		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 
 fail_clip_free:
-	drm_free(cliprects,
-		 cmdbuf->num_cliprects * sizeof(struct drm_clip_rect),
-		 DRM_MEM_DRIVER);
+	kfree(cliprects);
 fail_batch_free:
-	drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
+	kfree(batch_data);
 
 	return ret;
 }
@@ -734,7 +735,7 @@
 {
 	int ret;
 
-	DRM_DEBUG("%s\n", __func__);
+	DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
 
 	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
@@ -777,7 +778,8 @@
 		value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
 		break;
 	default:
-		DRM_DEBUG("Unknown parameter %d\n", param->param);
+		DRM_DEBUG_DRIVER(I915_DRV, "Unknown parameter %d\n",
+					param->param);
 		return -EINVAL;
 	}
 
@@ -817,7 +819,8 @@
 		dev_priv->fence_reg_start = param->value;
 		break;
 	default:
-		DRM_DEBUG("unknown parameter %d\n", param->param);
+		DRM_DEBUG_DRIVER(I915_DRV, "unknown parameter %d\n",
+					param->param);
 		return -EINVAL;
 	}
 
@@ -843,7 +846,7 @@
 		return 0;
 	}
 
-	printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
+	DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
 
 	dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
 
@@ -865,9 +868,10 @@
 
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-	DRM_DEBUG("load hws HWS_PGA with gfx mem 0x%x\n",
-			dev_priv->status_gfx_addr);
-	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
+	DRM_DEBUG_DRIVER(I915_DRV, "load hws HWS_PGA with gfx mem 0x%x\n",
+				dev_priv->status_gfx_addr);
+	DRM_DEBUG_DRIVER(I915_DRV, "load hws at %p\n",
+				dev_priv->hw_status_page);
 	return 0;
 }
 
@@ -881,8 +885,8 @@
  * some RAM for the framebuffer at early boot.  This code figures out
  * how much was set aside so we can use it for our own purposes.
  */
-static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
-			  unsigned long *preallocated_size)
+static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
+			  uint32_t *preallocated_size)
 {
 	struct pci_dev *bridge_dev;
 	u16 tmp = 0;
@@ -922,7 +926,7 @@
 	 * Some of the preallocated space is taken by the GTT
 	 * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
 	 */
-	if (IS_G4X(dev) || IS_IGD(dev))
+	if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev))
 		overhead = 4096;
 	else
 		overhead = (*aperture_size / 1024) + 4096;
@@ -980,10 +984,11 @@
 	return 0;
 }
 
-static int i915_load_modeset_init(struct drm_device *dev)
+static int i915_load_modeset_init(struct drm_device *dev,
+				  unsigned long prealloc_size,
+				  unsigned long agp_size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long agp_size, prealloc_size;
 	int fb_bar = IS_I9XX(dev) ? 2 : 0;
 	int ret = 0;
 
@@ -998,10 +1003,6 @@
 	if (IS_I965G(dev) || IS_G33(dev))
 		dev_priv->cursor_needs_physical = false;
 
-	ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
-	if (ret)
-		goto out;
-
 	/* Basic memrange allocator for stolen space (aka vram) */
 	drm_mm_init(&dev_priv->vram, 0, prealloc_size);
 
@@ -1058,7 +1059,7 @@
 {
 	struct drm_i915_master_private *master_priv;
 
-	master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+	master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
 	if (!master_priv)
 		return -ENOMEM;
 
@@ -1073,11 +1074,49 @@
 	if (!master_priv)
 		return;
 
-	drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+	kfree(master_priv);
 
 	master->driver_priv = NULL;
 }
 
+static void i915_get_mem_freq(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 tmp;
+
+	if (!IS_IGD(dev))
+		return;
+
+	tmp = I915_READ(CLKCFG);
+
+	switch (tmp & CLKCFG_FSB_MASK) {
+	case CLKCFG_FSB_533:
+		dev_priv->fsb_freq = 533; /* 133*4 */
+		break;
+	case CLKCFG_FSB_800:
+		dev_priv->fsb_freq = 800; /* 200*4 */
+		break;
+	case CLKCFG_FSB_667:
+		dev_priv->fsb_freq =  667; /* 167*4 */
+		break;
+	case CLKCFG_FSB_400:
+		dev_priv->fsb_freq = 400; /* 100*4 */
+		break;
+	}
+
+	switch (tmp & CLKCFG_MEM_MASK) {
+	case CLKCFG_MEM_533:
+		dev_priv->mem_freq = 533;
+		break;
+	case CLKCFG_MEM_667:
+		dev_priv->mem_freq = 667;
+		break;
+	case CLKCFG_MEM_800:
+		dev_priv->mem_freq = 800;
+		break;
+	}
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1094,6 +1133,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	resource_size_t base, size;
 	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+	uint32_t agp_size, prealloc_size;
 
 	/* i915 has 4 more counters */
 	dev->counters += 4;
@@ -1102,12 +1142,10 @@
 	dev->types[8] = _DRM_STAT_SECONDARY;
 	dev->types[9] = _DRM_STAT_DMA;
 
-	dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
+	dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
-	memset(dev_priv, 0, sizeof(drm_i915_private_t));
-
 	dev->dev_private = (void *)dev_priv;
 	dev_priv->dev = dev;
 
@@ -1144,17 +1182,35 @@
 			 "performance may suffer.\n");
 	}
 
-#ifdef CONFIG_HIGHMEM64G
-	/* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
-	dev_priv->has_gem = 0;
-#else
+	ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
+	if (ret)
+		goto out_iomapfree;
+
+	dev_priv->wq = create_workqueue("i915");
+	if (dev_priv->wq == NULL) {
+		DRM_ERROR("Failed to create our workqueue.\n");
+		ret = -ENOMEM;
+		goto out_iomapfree;
+	}
+
 	/* enable GEM by default */
 	dev_priv->has_gem = 1;
-#endif
+
+	if (prealloc_size > agp_size * 3 / 4) {
+		DRM_ERROR("Detected broken video BIOS with %d/%dkB of video "
+			  "memory stolen.\n",
+			  prealloc_size / 1024, agp_size / 1024);
+		DRM_ERROR("Disabling GEM. (try reducing stolen memory or "
+			  "updating the BIOS to fix).\n");
+		dev_priv->has_gem = 0;
+	}
 
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
-	if (IS_GM45(dev))
+	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+	if (IS_G4X(dev) || IS_IGDNG(dev)) {
+		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
 		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
+	}
 
 	i915_gem_load(dev);
 
@@ -1162,9 +1218,11 @@
 	if (!I915_NEED_GFX_HWS(dev)) {
 		ret = i915_init_phys_hws(dev);
 		if (ret != 0)
-			goto out_iomapfree;
+			goto out_workqueue_free;
 	}
 
+	i915_get_mem_freq(dev);
+
 	/* On the 945G/GM, the chipset reports the MSI capability on the
 	 * integrated graphics even though the support isn't actually there
 	 * according to the published specs.  It doesn't appear to function
@@ -1180,6 +1238,7 @@
 		pci_enable_msi(dev->pdev);
 
 	spin_lock_init(&dev_priv->user_irq_lock);
+	spin_lock_init(&dev_priv->error_lock);
 	dev_priv->user_irq_refcount = 0;
 
 	ret = drm_vblank_init(dev, I915_NUM_PIPE);
@@ -1190,24 +1249,28 @@
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = i915_load_modeset_init(dev);
+		ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
 		if (ret < 0) {
 			DRM_ERROR("failed to init modeset\n");
-			goto out_rmmap;
+			goto out_workqueue_free;
 		}
 	}
 
 	/* Must be done after probing outputs */
-	intel_opregion_init(dev, 0);
+	/* FIXME: verify on IGDNG */
+	if (!IS_IGDNG(dev))
+		intel_opregion_init(dev, 0);
 
 	return 0;
 
+out_workqueue_free:
+	destroy_workqueue(dev_priv->wq);
 out_iomapfree:
 	io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
 	iounmap(dev_priv->regs);
 free_priv:
-	drm_free(dev_priv, sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
+	kfree(dev_priv);
 	return ret;
 }
 
@@ -1215,6 +1278,8 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	destroy_workqueue(dev_priv->wq);
+
 	io_mapping_free(dev_priv->mm.gtt_mapping);
 	if (dev_priv->mm.gtt_mtrr >= 0) {
 		mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
@@ -1232,7 +1297,8 @@
 	if (dev_priv->regs != NULL)
 		iounmap(dev_priv->regs);
 
-	intel_opregion_free(dev, 0);
+	if (!IS_IGDNG(dev))
+		intel_opregion_free(dev, 0);
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		intel_modeset_cleanup(dev);
@@ -1246,8 +1312,7 @@
 		i915_gem_lastclose(dev);
 	}
 
-	drm_free(dev->dev_private, sizeof(drm_i915_private_t),
-		 DRM_MEM_DRIVER);
+	kfree(dev->dev_private);
 
 	return 0;
 }
@@ -1256,17 +1321,16 @@
 {
 	struct drm_i915_file_private *i915_file_priv;
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_DRIVER(I915_DRV, "\n");
 	i915_file_priv = (struct drm_i915_file_private *)
-	    drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
+	    kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
 
 	if (!i915_file_priv)
 		return -ENOMEM;
 
 	file_priv->driver_priv = i915_file_priv;
 
-	i915_file_priv->mm.last_gem_seqno = 0;
-	i915_file_priv->mm.last_gem_throttle_seqno = 0;
+	INIT_LIST_HEAD(&i915_file_priv->mm.request_list);
 
 	return 0;
 }
@@ -1303,6 +1367,7 @@
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	i915_gem_release(dev, file_priv);
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		i915_mem_release(dev, file_priv, dev_priv->agp_heap);
 }
@@ -1311,7 +1376,7 @@
 {
 	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
 
-	drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
+	kfree(i915_file_priv);
 }
 
 struct drm_ioctl_desc i915_ioctls[] = {
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_drv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_drv.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,6 +35,7 @@
 
 #include "drm_pciids.h"
 #include <linux/console.h>
+#include "drm_crtc_helper.h"
 
 static unsigned int i915_modeset = -1;
 module_param_named(modeset, i915_modeset, int, 0400);
@@ -57,8 +58,8 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!dev || !dev_priv) {
-		printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
-		printk(KERN_ERR "DRM not initialized, aborting suspend.\n");
+		DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv);
+		DRM_ERROR("DRM not initialized, aborting suspend.\n");
 		return -ENODEV;
 	}
 
@@ -67,8 +68,6 @@
 
 	pci_save_state(dev->pdev);
 
-	i915_save_state(dev);
-
 	/* If KMS is active, we do the leavevt stuff here */
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		if (i915_gem_idle(dev))
@@ -77,6 +76,8 @@
 		drm_irq_uninstall(dev);
 	}
 
+	i915_save_state(dev);
+
 	intel_opregion_free(dev, 1);
 
 	if (state.event == PM_EVENT_SUSPEND) {
@@ -115,6 +116,10 @@
 
 		drm_irq_install(dev);
 	}
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		/* Resume the modeset for every activated CRTC */
+		drm_helper_resume_force_mode(dev);
+	}
 
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_drv.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_drv.h	2009-09-09 18:13:59.000000000 -0400
@@ -126,6 +126,29 @@
 	struct drm_gem_object *obj;
 };
 
+struct sdvo_device_mapping {
+	u8 dvo_port;
+	u8 slave_addr;
+	u8 dvo_wiring;
+	u8 initialized;
+};
+
+struct drm_i915_error_state {
+	u32 eir;
+	u32 pgtbl_er;
+	u32 pipeastat;
+	u32 pipebstat;
+	u32 ipeir;
+	u32 ipehr;
+	u32 instdone;
+	u32 acthd;
+	u32 instpm;
+	u32 instps;
+	u32 instdone1;
+	u32 seqno;
+	struct timeval time;
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 
@@ -143,6 +166,8 @@
 	drm_local_map_t hws_map;
 	struct drm_gem_object *hws_obj;
 
+	struct resource mch_res;
+
 	unsigned int cpp;
 	int back_offset;
 	int front_offset;
@@ -158,6 +183,11 @@
 	/** Cached value of IMR to avoid reads in updating the bitfield */
 	u32 irq_mask_reg;
 	u32 pipestat[2];
+	/** splitted irq regs for graphics and display engine on IGDNG,
+	    irq_mask_reg is still used for display irq. */
+	u32 gt_irq_mask_reg;
+	u32 gt_irq_enable_reg;
+	u32 de_irq_enable_reg;
 
 	u32 hotplug_supported_mask;
 	struct work_struct hotplug_work;
@@ -189,12 +219,21 @@
 	unsigned int lvds_vbt:1;
 	unsigned int int_crt_support:1;
 	unsigned int lvds_use_ssc:1;
+	unsigned int edp_support:1;
 	int lvds_ssc_freq;
 
+	int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */
 	struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
+	unsigned int fsb_freq, mem_freq;
+
+	spinlock_t error_lock;
+	struct drm_i915_error_state *first_error;
+	struct work_struct error_work;
+	struct workqueue_struct *wq;
+
 	/* Register state */
 	u8 saveLBB;
 	u32 saveDSPACNTR;
@@ -285,6 +324,24 @@
 	u8 saveDACMASK;
 	u8 saveCR[37];
 	uint64_t saveFENCE[16];
+	u32 saveCURACNTR;
+	u32 saveCURAPOS;
+	u32 saveCURABASE;
+	u32 saveCURBCNTR;
+	u32 saveCURBPOS;
+	u32 saveCURBBASE;
+	u32 saveCURSIZE;
+	u32 saveDP_B;
+	u32 saveDP_C;
+	u32 saveDP_D;
+	u32 savePIPEA_GMCH_DATA_M;
+	u32 savePIPEB_GMCH_DATA_M;
+	u32 savePIPEA_GMCH_DATA_N;
+	u32 savePIPEB_GMCH_DATA_N;
+	u32 savePIPEA_DP_LINK_M;
+	u32 savePIPEB_DP_LINK_M;
+	u32 savePIPEA_DP_LINK_N;
+	u32 savePIPEB_DP_LINK_N;
 
 	struct {
 		struct drm_mm gtt_space;
@@ -328,6 +385,9 @@
 		 */
 		struct list_head inactive_list;
 
+		/** LRU list of objects with fence regs on them. */
+		struct list_head fence_list;
+
 		/**
 		 * List of breadcrumbs associated with GPU requests currently
 		 * outstanding.
@@ -382,6 +442,7 @@
 		/* storage for physical objects */
 		struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
 	} mm;
+	struct sdvo_device_mapping sdvo_mappings[2];
 } drm_i915_private_t;
 
 /** driver private structure attached to each drm_gem_object */
@@ -394,6 +455,9 @@
 	/** This object's place on the active/flushing/inactive lists */
 	struct list_head list;
 
+	/** This object's place on the fenced object LRU */
+	struct list_head fence_list;
+
 	/**
 	 * This is set if the object is on the active or flushing lists
 	 * (has pending rendering), and is not set if it's on inactive (ready
@@ -435,9 +499,6 @@
 	 */
 	int fence_reg;
 
-	/** Boolean whether this object has a valid gtt offset. */
-	int gtt_bound;
-
 	/** How many users have pinned this object in GTT space */
 	int pin_count;
 
@@ -491,13 +552,16 @@
 	/** Time at which this request was emitted, in jiffies. */
 	unsigned long emitted_jiffies;
 
+	/** global list entry for this request */
 	struct list_head list;
+
+	/** file_priv list entry for this request */
+	struct list_head client_list;
 };
 
 struct drm_i915_file_private {
 	struct {
-		uint32_t last_gem_seqno;
-		uint32_t last_gem_throttle_seqno;
+		struct list_head request_list;
 	} mm;
 };
 
@@ -619,8 +683,11 @@
 int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
 void i915_gem_object_unpin(struct drm_gem_object *obj);
 int i915_gem_object_unbind(struct drm_gem_object *obj);
+void i915_gem_release_mmap(struct drm_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 uint32_t i915_get_gem_seqno(struct drm_device *dev);
+int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
+int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
 void i915_gem_retire_requests(struct drm_device *dev);
 void i915_gem_retire_work_handler(struct work_struct *work);
 void i915_gem_clflush_object(struct drm_gem_object *obj);
@@ -642,6 +709,7 @@
 void i915_gem_free_all_phys_object(struct drm_device *dev);
 int i915_gem_object_get_pages(struct drm_gem_object *obj);
 void i915_gem_object_put_pages(struct drm_gem_object *obj);
+void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
 
 /* i915_gem_tiling.c */
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
@@ -785,7 +853,9 @@
 		       (dev)->pci_device == 0x2E02 || \
 		       (dev)->pci_device == 0x2E12 || \
 		       (dev)->pci_device == 0x2E22 || \
-		       (dev)->pci_device == 0x2E32)
+		       (dev)->pci_device == 0x2E32 || \
+		       (dev)->pci_device == 0x0042 || \
+		       (dev)->pci_device == 0x0046)
 
 #define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
 			(dev)->pci_device == 0x2A12)
@@ -807,21 +877,31 @@
 			(dev)->pci_device == 0x29D2 ||  \
 			(IS_IGD(dev)))
 
+#define IS_IGDNG_D(dev)	((dev)->pci_device == 0x0042)
+#define IS_IGDNG_M(dev)	((dev)->pci_device == 0x0046)
+#define IS_IGDNG(dev)	(IS_IGDNG_D(dev) || IS_IGDNG_M(dev))
+
 #define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
-		      IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
+		      IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \
+		      IS_IGDNG(dev))
 
 #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
 			IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \
-			IS_IGD(dev))
+			IS_IGD(dev) || IS_IGDNG_M(dev))
 
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
+#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \
+				IS_IGDNG(dev))
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
 #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
 						      IS_I915GM(dev)))
-#define SUPPORTS_INTEGRATED_HDMI(dev)	(IS_G4X(dev))
+#define SUPPORTS_INTEGRATED_HDMI(dev)	(IS_G4X(dev) || IS_IGDNG(dev))
+#define SUPPORTS_INTEGRATED_DP(dev)	(IS_G4X(dev) || IS_IGDNG(dev))
+#define SUPPORTS_EDP(dev)		(IS_IGDNG_M(dev))
 #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
+/* dsparb controlled by hw only */
+#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
 
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,6 @@
 static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
 static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
 					   unsigned alignment);
-static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write);
 static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
 static int i915_gem_evict_something(struct drm_device *dev);
 static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
@@ -979,6 +978,7 @@
 i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_set_domain *args = data;
 	struct drm_gem_object *obj;
 	uint32_t read_domains = args->read_domains;
@@ -989,10 +989,10 @@
 		return -ENODEV;
 
 	/* Only handle setting domains to types used by the CPU. */
-	if (write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+	if (write_domain & I915_GEM_GPU_DOMAINS)
 		return -EINVAL;
 
-	if (read_domains & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
+	if (read_domains & I915_GEM_GPU_DOMAINS)
 		return -EINVAL;
 
 	/* Having something in the write domain implies it's in the read
@@ -1007,12 +1007,22 @@
 
 	mutex_lock(&dev->struct_mutex);
 #if WATCH_BUF
-	DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
+	DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n",
 		 obj, obj->size, read_domains, write_domain);
 #endif
 	if (read_domains & I915_GEM_DOMAIN_GTT) {
+		struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
 		ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
 
+		/* Update the LRU on the fence for the CPU access that's
+		 * about to occur.
+		 */
+		if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+			list_move_tail(&obj_priv->fence_list,
+				       &dev_priv->mm.fence_list);
+		}
+
 		/* Silently promote "you're not bound, there was nothing to do"
 		 * to success, since the client was just asking us to
 		 * make sure everything was done.
@@ -1051,7 +1061,7 @@
 	}
 
 #if WATCH_BUF
-	DRM_INFO("%s: sw_finish %d (%p %d)\n",
+	DRM_INFO("%s: sw_finish %d (%p %zd)\n",
 		 __func__, args->handle, obj, obj->size);
 #endif
 	obj_priv = obj->driver_private;
@@ -1156,9 +1166,8 @@
 	}
 
 	/* Need a new fence register? */
-	if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-	    obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj, write);
+	if (obj_priv->tiling_mode != I915_TILING_NONE) {
+		ret = i915_gem_object_get_fence_reg(obj);
 		if (ret) {
 			mutex_unlock(&dev->struct_mutex);
 			return VM_FAULT_SIGBUS;
@@ -1208,8 +1217,7 @@
 
 	/* Set the object up for mmap'ing */
 	list = &obj->map_list;
-	list->map = drm_calloc(1, sizeof(struct drm_map_list),
-			       DRM_MEM_DRIVER);
+	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
 	if (!list->map)
 		return -ENOMEM;
 
@@ -1249,11 +1257,36 @@
 out_free_mm:
 	drm_mm_put_block(list->file_offset_node);
 out_free_list:
-	drm_free(list->map, sizeof(struct drm_map_list), DRM_MEM_DRIVER);
+	kfree(list->map);
 
 	return ret;
 }
 
+/**
+ * i915_gem_release_mmap - remove physical page mappings
+ * @obj: obj in question
+ *
+ * Preserve the reservation of the mmaping with the DRM core code, but
+ * relinquish ownership of the pages back to the system.
+ *
+ * It is vital that we remove the page mapping if we have mapped a tiled
+ * object through the GTT and then lose the fence register due to
+ * resource pressure. Similarly if the object has been moved out of the
+ * aperture, than pages mapped into userspace must be revoked. Removing the
+ * mapping will then trigger a page fault on the next user access, allowing
+ * fixup by i915_gem_fault().
+ */
+void
+i915_gem_release_mmap(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+	if (dev->dev_mapping)
+		unmap_mapping_range(dev->dev_mapping,
+				    obj_priv->mmap_offset, obj->size, 1);
+}
+
 static void
 i915_gem_free_mmap_offset(struct drm_gem_object *obj)
 {
@@ -1271,7 +1304,7 @@
 	}
 
 	if (list->map) {
-		drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
+		kfree(list->map);
 		list->map = NULL;
 	}
 
@@ -1481,15 +1514,20 @@
  * Returned sequence numbers are nonzero on success.
  */
 static uint32_t
-i915_add_request(struct drm_device *dev, uint32_t flush_domains)
+i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
+		 uint32_t flush_domains)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_file_private *i915_file_priv = NULL;
 	struct drm_i915_gem_request *request;
 	uint32_t seqno;
 	int was_empty;
 	RING_LOCALS;
 
-	request = drm_calloc(1, sizeof(*request), DRM_MEM_DRIVER);
+	if (file_priv != NULL)
+		i915_file_priv = file_priv->driver_priv;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
 	if (request == NULL)
 		return 0;
 
@@ -1515,6 +1553,12 @@
 	request->emitted_jiffies = jiffies;
 	was_empty = list_empty(&dev_priv->mm.request_list);
 	list_add_tail(&request->list, &dev_priv->mm.request_list);
+	if (i915_file_priv) {
+		list_add_tail(&request->client_list,
+			      &i915_file_priv->mm.request_list);
+	} else {
+		INIT_LIST_HEAD(&request->client_list);
+	}
 
 	/* Associate any objects on the flushing list matching the write
 	 * domain we're flushing with our flush.
@@ -1536,7 +1580,7 @@
 	}
 
 	if (was_empty && !dev_priv->mm.suspended)
-		schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
 	return seqno;
 }
 
@@ -1664,7 +1708,8 @@
 			i915_gem_retire_request(dev, request);
 
 			list_del(&request->list);
-			drm_free(request, sizeof(*request), DRM_MEM_DRIVER);
+			list_del(&request->client_list);
+			kfree(request);
 		} else
 			break;
 	}
@@ -1684,7 +1729,7 @@
 	i915_gem_retire_requests(dev);
 	if (!dev_priv->mm.suspended &&
 	    !list_empty(&dev_priv->mm.request_list))
-		schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
 	mutex_unlock(&dev->struct_mutex);
 }
 
@@ -1702,7 +1747,10 @@
 	BUG_ON(seqno == 0);
 
 	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
-		ier = I915_READ(IER);
+		if (IS_IGDNG(dev))
+			ier = I915_READ(DEIER) | I915_READ(GTIER);
+		else
+			ier = I915_READ(IER);
 		if (!ier) {
 			DRM_ERROR("something (likely vbetool) disabled "
 				  "interrupts, re-enabling\n");
@@ -1754,8 +1802,7 @@
 	if (flush_domains & I915_GEM_DOMAIN_CPU)
 		drm_agp_chipset_flush(dev);
 
-	if ((invalidate_domains | flush_domains) & ~(I915_GEM_DOMAIN_CPU |
-						     I915_GEM_DOMAIN_GTT)) {
+	if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
 		/*
 		 * read/write caches:
 		 *
@@ -1849,7 +1896,6 @@
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
-	loff_t offset;
 	int ret = 0;
 
 #if WATCH_BUF
@@ -1886,9 +1932,7 @@
 	BUG_ON(obj_priv->active);
 
 	/* blow away mappings if mapped through GTT */
-	offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT;
-	if (dev->dev_mapping)
-		unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1);
+	i915_gem_release_mmap(obj);
 
 	if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
 		i915_gem_clear_fence_reg(obj);
@@ -1977,7 +2021,7 @@
 			i915_gem_flush(dev,
 				       obj->write_domain,
 				       obj->write_domain);
-			i915_add_request(dev, obj->write_domain);
+			i915_add_request(dev, NULL, obj->write_domain);
 
 			obj = NULL;
 			continue;
@@ -1991,7 +2035,7 @@
 		/* If we didn't do any of the above, there's nothing to be done
 		 * and we just can't fit it in.
 		 */
-		return -ENOMEM;
+		return -ENOSPC;
 	}
 	return ret;
 }
@@ -2006,7 +2050,7 @@
 		if (ret != 0)
 			break;
 	}
-	if (ret == -ENOMEM)
+	if (ret == -ENOSPC)
 		return 0;
 	return ret;
 }
@@ -2149,13 +2193,11 @@
 	val |= I830_FENCE_REG_VALID;
 
 	I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
-
 }
 
 /**
  * i915_gem_object_get_fence_reg - set up a fence reg for an object
  * @obj: object to map through a fence reg
- * @write: object is about to be written
  *
  * When mapping objects through the GTT, userspace wants to be able to write
  * to them without having to worry about swizzling if the object is tiled.
@@ -2166,8 +2208,8 @@
  * It then sets up the reg based on the object's properties: address, pitch
  * and tiling format.
  */
-static int
-i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
+int
+i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2176,6 +2218,12 @@
 	struct drm_i915_gem_object *old_obj_priv = NULL;
 	int i, ret, avail;
 
+	/* Just update our place in the LRU if our fence is getting used. */
+	if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+		list_move_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+		return 0;
+	}
+
 	switch (obj_priv->tiling_mode) {
 	case I915_TILING_NONE:
 		WARN(1, "allocating a fence for non-tiled object?\n");
@@ -2197,7 +2245,6 @@
 	}
 
 	/* First try to find a free reg */
-try_again:
 	avail = 0;
 	for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
 		reg = &dev_priv->fence_regs[i];
@@ -2211,67 +2258,62 @@
 
 	/* None available, try to steal one or wait for a user to finish */
 	if (i == dev_priv->num_fence_regs) {
-		uint32_t seqno = dev_priv->mm.next_gem_seqno;
-		loff_t offset;
+		struct drm_gem_object *old_obj = NULL;
 
 		if (avail == 0)
-			return -ENOMEM;
-
-		for (i = dev_priv->fence_reg_start;
-		     i < dev_priv->num_fence_regs; i++) {
-			uint32_t this_seqno;
+			return -ENOSPC;
 
-			reg = &dev_priv->fence_regs[i];
-			old_obj_priv = reg->obj->driver_private;
+		list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
+				    fence_list) {
+			old_obj = old_obj_priv->obj;
 
 			if (old_obj_priv->pin_count)
 				continue;
 
+			/* Take a reference, as otherwise the wait_rendering
+			 * below may cause the object to get freed out from
+			 * under us.
+			 */
+			drm_gem_object_reference(old_obj);
+
 			/* i915 uses fences for GPU access to tiled buffers */
 			if (IS_I965G(dev) || !old_obj_priv->active)
 				break;
 
-			/* find the seqno of the first available fence */
-			this_seqno = old_obj_priv->last_rendering_seqno;
-			if (this_seqno != 0 &&
-			    reg->obj->write_domain == 0 &&
-			    i915_seqno_passed(seqno, this_seqno))
-				seqno = this_seqno;
-		}
-
-		/*
-		 * Now things get ugly... we have to wait for one of the
-		 * objects to finish before trying again.
-		 */
-		if (i == dev_priv->num_fence_regs) {
-			if (seqno == dev_priv->mm.next_gem_seqno) {
-				i915_gem_flush(dev,
-					       I915_GEM_GPU_DOMAINS,
-					       I915_GEM_GPU_DOMAINS);
-				seqno = i915_add_request(dev,
-							 I915_GEM_GPU_DOMAINS);
-				if (seqno == 0)
-					return -ENOMEM;
+			/* This brings the object to the head of the LRU if it
+			 * had been written to.  The only way this should
+			 * result in us waiting longer than the expected
+			 * optimal amount of time is if there was a
+			 * fence-using buffer later that was read-only.
+			 */
+			i915_gem_object_flush_gpu_write_domain(old_obj);
+			ret = i915_gem_object_wait_rendering(old_obj);
+			if (ret != 0) {
+				drm_gem_object_unreference(old_obj);
+				return ret;
 			}
 
-			ret = i915_wait_request(dev, seqno);
-			if (ret)
-				return ret;
-			goto try_again;
+			break;
 		}
 
 		/*
 		 * Zap this virtual mapping so we can set up a fence again
 		 * for this object next time we need it.
 		 */
-		offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT;
-		if (dev->dev_mapping)
-			unmap_mapping_range(dev->dev_mapping, offset,
-					    reg->obj->size, 1);
+		i915_gem_release_mmap(old_obj);
+
+		i = old_obj_priv->fence_reg;
+		reg = &dev_priv->fence_regs[i];
+
 		old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
+		list_del_init(&old_obj_priv->fence_list);
+
+		drm_gem_object_unreference(old_obj);
 	}
 
 	obj_priv->fence_reg = i;
+	list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+
 	reg->obj = obj;
 
 	if (IS_I965G(dev))
@@ -2314,6 +2356,43 @@
 
 	dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
 	obj_priv->fence_reg = I915_FENCE_REG_NONE;
+	list_del_init(&obj_priv->fence_list);
+}
+
+/**
+ * i915_gem_object_put_fence_reg - waits on outstanding fenced access
+ * to the buffer to finish, and then resets the fence register.
+ * @obj: tiled object holding a fence register.
+ *
+ * Zeroes out the fence register itself and clears out the associated
+ * data structures in dev_priv and obj_priv.
+ */
+int
+i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+	if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
+		return 0;
+
+	/* On the i915, GPU access to tiled buffers is via a fence,
+	 * therefore we must wait for any outstanding access to complete
+	 * before clearing the fence.
+	 */
+	if (!IS_I965G(dev)) {
+		int ret;
+
+		i915_gem_object_flush_gpu_write_domain(obj);
+		i915_gem_object_flush_gtt_write_domain(obj);
+		ret = i915_gem_object_wait_rendering(obj);
+		if (ret != 0)
+			return ret;
+	}
+
+	i915_gem_clear_fence_reg (obj);
+
+	return 0;
 }
 
 /**
@@ -2364,7 +2443,7 @@
 		spin_unlock(&dev_priv->mm.active_list_lock);
 		if (lists_empty) {
 			DRM_ERROR("GTT full, but LRU list empty\n");
-			return -ENOMEM;
+			return -ENOSPC;
 		}
 
 		ret = i915_gem_evict_something(dev);
@@ -2377,7 +2456,7 @@
 	}
 
 #if WATCH_BUF
-	DRM_INFO("Binding object of size %d at 0x%08x\n",
+	DRM_INFO("Binding object of size %zd at 0x%08x\n",
 		 obj->size, obj_priv->gtt_offset);
 #endif
 	ret = i915_gem_object_get_pages(obj);
@@ -2409,8 +2488,8 @@
 	 * wasn't in the GTT, there shouldn't be any way it could have been in
 	 * a GPU cache
 	 */
-	BUG_ON(obj->read_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-	BUG_ON(obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
+	BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
+	BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
 
 	return 0;
 }
@@ -2452,7 +2531,7 @@
 
 	/* Queue the GPU write cache flushing we need. */
 	i915_gem_flush(dev, 0, obj->write_domain);
-	seqno = i915_add_request(dev, obj->write_domain);
+	seqno = i915_add_request(dev, NULL, obj->write_domain);
 	obj->write_domain = 0;
 	i915_gem_object_move_to_active(obj, seqno);
 }
@@ -2786,8 +2865,7 @@
 	/* Free the page_cpu_valid mappings which are now stale, whether
 	 * or not we've got I915_GEM_DOMAIN_CPU.
 	 */
-	drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE,
-		 DRM_MEM_DRIVER);
+	kfree(obj_priv->page_cpu_valid);
 	obj_priv->page_cpu_valid = NULL;
 }
 
@@ -2829,8 +2907,8 @@
 	 * newly adding I915_GEM_DOMAIN_CPU
 	 */
 	if (obj_priv->page_cpu_valid == NULL) {
-		obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE,
-						      DRM_MEM_DRIVER);
+		obj_priv->page_cpu_valid = kzalloc(obj->size / PAGE_SIZE,
+						   GFP_KERNEL);
 		if (obj_priv->page_cpu_valid == NULL)
 			return -ENOMEM;
 	} else if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0)
@@ -3035,20 +3113,12 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int nbox = exec->num_cliprects;
 	int i = 0, count;
-	uint32_t	exec_start, exec_len;
+	uint32_t exec_start, exec_len;
 	RING_LOCALS;
 
 	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
 	exec_len = (uint32_t) exec->batch_len;
 
-	if ((exec_start | exec_len) & 0x7) {
-		DRM_ERROR("alignment\n");
-		return -EINVAL;
-	}
-
-	if (!exec_start)
-		return -EINVAL;
-
 	count = nbox ? nbox : 1;
 
 	for (i = 0; i < count; i++) {
@@ -3089,6 +3159,10 @@
 /* Throttle our rendering by waiting until the ring has completed our requests
  * emitted over 20 msec ago.
  *
+ * Note that if we were to use the current jiffies each time around the loop,
+ * we wouldn't escape the function with any frames outstanding if the time to
+ * render a frame was over 20ms.
+ *
  * This should get us reasonable parallelism between CPU and GPU but also
  * relatively low latency when blocking on a particular request to finish.
  */
@@ -3097,15 +3171,25 @@
 {
 	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
 	int ret = 0;
-	uint32_t seqno;
+	unsigned long recent_enough = jiffies - msecs_to_jiffies(20);
 
 	mutex_lock(&dev->struct_mutex);
-	seqno = i915_file_priv->mm.last_gem_throttle_seqno;
-	i915_file_priv->mm.last_gem_throttle_seqno =
-		i915_file_priv->mm.last_gem_seqno;
-	if (seqno)
-		ret = i915_wait_request(dev, seqno);
+	while (!list_empty(&i915_file_priv->mm.request_list)) {
+		struct drm_i915_gem_request *request;
+
+		request = list_first_entry(&i915_file_priv->mm.request_list,
+					   struct drm_i915_gem_request,
+					   client_list);
+
+		if (time_after_eq(request->emitted_jiffies, recent_enough))
+			break;
+
+		ret = i915_wait_request(dev, request->seqno);
+		if (ret != 0)
+			break;
+	}
 	mutex_unlock(&dev->struct_mutex);
+
 	return ret;
 }
 
@@ -3182,12 +3266,29 @@
 	return ret;
 }
 
+static int
+i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec,
+			   uint64_t exec_offset)
+{
+	uint32_t exec_start, exec_len;
+
+	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+	exec_len = (uint32_t) exec->batch_len;
+
+	if ((exec_start | exec_len) & 0x7)
+		return -EINVAL;
+
+	if (!exec_start)
+		return -EINVAL;
+
+	return 0;
+}
+
 int
 i915_gem_execbuffer(struct drm_device *dev, void *data,
 		    struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
 	struct drm_i915_gem_execbuffer *args = data;
 	struct drm_i915_gem_exec_object *exec_list = NULL;
 	struct drm_gem_object **object_list = NULL;
@@ -3230,8 +3331,8 @@
 	}
 
 	if (args->num_cliprects != 0) {
-		cliprects = drm_calloc(args->num_cliprects, sizeof(*cliprects),
-				       DRM_MEM_DRIVER);
+		cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects),
+				    GFP_KERNEL);
 		if (cliprects == NULL)
 			goto pre_mutex_err;
 
@@ -3312,7 +3413,7 @@
 			break;
 
 		/* error other than GTT full, or we've already tried again */
-		if (ret != -ENOMEM || pin_tries >= 1) {
+		if (ret != -ENOSPC || pin_tries >= 1) {
 			if (ret != -ERESTARTSYS)
 				DRM_ERROR("Failed to pin buffers %d\n", ret);
 			goto err;
@@ -3331,8 +3432,20 @@
 
 	/* Set the pending read domains for the batch buffer to COMMAND */
 	batch_obj = object_list[args->buffer_count-1];
-	batch_obj->pending_read_domains = I915_GEM_DOMAIN_COMMAND;
-	batch_obj->pending_write_domain = 0;
+	if (batch_obj->pending_write_domain) {
+		DRM_ERROR("Attempting to use self-modifying batch buffer\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	batch_obj->pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
+
+	/* Sanity check the batch buffer, prior to moving objects */
+	exec_offset = exec_list[args->buffer_count - 1].offset;
+	ret = i915_gem_check_execbuffer (args, exec_offset);
+	if (ret != 0) {
+		DRM_ERROR("execbuf with invalid offset/length\n");
+		goto err;
+	}
 
 	i915_verify_inactive(dev, __FILE__, __LINE__);
 
@@ -3363,7 +3476,8 @@
 			       dev->invalidate_domains,
 			       dev->flush_domains);
 		if (dev->flush_domains)
-			(void)i915_add_request(dev, dev->flush_domains);
+			(void)i915_add_request(dev, file_priv,
+					       dev->flush_domains);
 	}
 
 	for (i = 0; i < args->buffer_count; i++) {
@@ -3381,8 +3495,6 @@
 	}
 #endif
 
-	exec_offset = exec_list[args->buffer_count - 1].offset;
-
 #if WATCH_EXEC
 	i915_gem_dump_object(batch_obj,
 			      args->batch_len,
@@ -3412,9 +3524,8 @@
 	 * *some* interrupts representing completion of buffers that we can
 	 * wait on when trying to clear up gtt space).
 	 */
-	seqno = i915_add_request(dev, flush_domains);
+	seqno = i915_add_request(dev, file_priv, flush_domains);
 	BUG_ON(seqno == 0);
-	i915_file_priv->mm.last_gem_seqno = seqno;
 	for (i = 0; i < args->buffer_count; i++) {
 		struct drm_gem_object *obj = object_list[i];
 
@@ -3474,8 +3585,7 @@
 pre_mutex_err:
 	drm_free_large(object_list);
 	drm_free_large(exec_list);
-	drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects,
-		 DRM_MEM_DRIVER);
+	kfree(cliprects);
 
 	return ret;
 }
@@ -3500,10 +3610,8 @@
 	 * Pre-965 chips need a fence register set up in order to
 	 * properly handle tiled surfaces.
 	 */
-	if (!IS_I965G(dev) &&
-	    obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-	    obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj, true);
+	if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
+		ret = i915_gem_object_get_fence_reg(obj);
 		if (ret != 0) {
 			if (ret != -EBUSY && ret != -ERESTARTSYS)
 				DRM_ERROR("Failure to install fence: %d\n",
@@ -3520,8 +3628,7 @@
 		atomic_inc(&dev->pin_count);
 		atomic_add(obj->size, &dev->pin_memory);
 		if (!obj_priv->active &&
-		    (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-					   I915_GEM_DOMAIN_GTT)) == 0 &&
+		    (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0 &&
 		    !list_empty(&obj_priv->list))
 			list_del_init(&obj_priv->list);
 	}
@@ -3548,8 +3655,7 @@
 	 */
 	if (obj_priv->pin_count == 0) {
 		if (!obj_priv->active &&
-		    (obj->write_domain & ~(I915_GEM_DOMAIN_CPU |
-					   I915_GEM_DOMAIN_GTT)) == 0)
+		    (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
 			list_move_tail(&obj_priv->list,
 				       &dev_priv->mm.inactive_list);
 		atomic_dec(&dev->pin_count);
@@ -3653,15 +3759,14 @@
 	struct drm_gem_object *obj;
 	struct drm_i915_gem_object *obj_priv;
 
-	mutex_lock(&dev->struct_mutex);
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
 	if (obj == NULL) {
 		DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
 			  args->handle);
-		mutex_unlock(&dev->struct_mutex);
 		return -EBADF;
 	}
 
+	mutex_lock(&dev->struct_mutex);
 	/* Update the active list for the hardware's current position.
 	 * Otherwise this only updates on a delayed timer or when irqs are
 	 * actually unmasked, and our working set ends up being larger than
@@ -3695,7 +3800,7 @@
 {
 	struct drm_i915_gem_object *obj_priv;
 
-	obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
+	obj_priv = kzalloc(sizeof(*obj_priv), GFP_KERNEL);
 	if (obj_priv == NULL)
 		return -ENOMEM;
 
@@ -3714,6 +3819,7 @@
 	obj_priv->obj = obj;
 	obj_priv->fence_reg = I915_FENCE_REG_NONE;
 	INIT_LIST_HEAD(&obj_priv->list);
+	INIT_LIST_HEAD(&obj_priv->fence_list);
 
 	return 0;
 }
@@ -3733,9 +3839,9 @@
 
 	i915_gem_free_mmap_offset(obj);
 
-	drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
+	kfree(obj_priv->page_cpu_valid);
 	kfree(obj_priv->bit_17);
-	drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
+	kfree(obj->driver_private);
 }
 
 /** Unbinds all objects that are on the given buffer list. */
@@ -3800,9 +3906,8 @@
 
 	/* Flush the GPU along with all non-CPU write domains
 	 */
-	i915_gem_flush(dev, ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT),
-		       ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT));
-	seqno = i915_add_request(dev, ~I915_GEM_DOMAIN_CPU);
+	i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
 
 	if (seqno == 0) {
 		mutex_unlock(&dev->struct_mutex);
@@ -4127,15 +4232,11 @@
 i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv)
 {
-	int ret;
-
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return 0;
 
-	ret = i915_gem_idle(dev);
 	drm_irq_uninstall(dev);
-
-	return ret;
+	return i915_gem_idle(dev);
 }
 
 void
@@ -4154,6 +4255,7 @@
 void
 i915_gem_load(struct drm_device *dev)
 {
+	int i;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
 	spin_lock_init(&dev_priv->mm.active_list_lock);
@@ -4161,6 +4263,7 @@
 	INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
 	INIT_LIST_HEAD(&dev_priv->mm.request_list);
+	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
 	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
 			  i915_gem_retire_work_handler);
 	dev_priv->mm.next_gem_seqno = 1;
@@ -4173,6 +4276,18 @@
 	else
 		dev_priv->num_fence_regs = 8;
 
+	/* Initialize fence registers to zero */
+	if (IS_I965G(dev)) {
+		for (i = 0; i < 16; i++)
+			I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0);
+	} else {
+		for (i = 0; i < 8; i++)
+			I915_WRITE(FENCE_REG_830_0 + (i * 4), 0);
+		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+			for (i = 0; i < 8; i++)
+				I915_WRITE(FENCE_REG_945_8 + (i * 4), 0);
+	}
+
 	i915_gem_detect_bit_6_swizzle(dev);
 }
 
@@ -4190,7 +4305,7 @@
 	if (dev_priv->mm.phys_objs[id - 1] || !size)
 		return 0;
 
-	phys_obj = drm_calloc(1, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
+	phys_obj = kzalloc(sizeof(struct drm_i915_gem_phys_object), GFP_KERNEL);
 	if (!phys_obj)
 		return -ENOMEM;
 
@@ -4209,7 +4324,7 @@
 
 	return 0;
 kfree_obj:
-	drm_free(phys_obj, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
+	kfree(phys_obj);
 	return ret;
 }
 
@@ -4269,6 +4384,8 @@
 	}
 	drm_clflush_pages(obj_priv->pages, page_count);
 	drm_agp_chipset_flush(dev);
+
+	i915_gem_object_put_pages(obj);
 out:
 	obj_priv->phys_obj->cur_obj = NULL;
 	obj_priv->phys_obj = NULL;
@@ -4326,6 +4443,8 @@
 		kunmap_atomic(src, KM_USER0);
 	}
 
+	i915_gem_object_put_pages(obj);
+
 	return 0;
 out:
 	return ret;
@@ -4352,3 +4471,17 @@
 	drm_agp_chipset_flush(dev);
 	return 0;
 }
+
+void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv)
+{
+	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+
+	/* Clean up our request list when the client is going away, so that
+	 * later retire_requests won't dereference our soon-to-be-gone
+	 * file_priv.
+	 */
+	mutex_lock(&dev->struct_mutex);
+	while (!list_empty(&i915_file_priv->mm.request_list))
+		list_del_init(i915_file_priv->mm.request_list.next);
+	mutex_unlock(&dev->struct_mutex);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem_debug.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem_debug.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -87,7 +87,7 @@
 			chunk_len = page_len - chunk;
 			if (chunk_len > 128)
 				chunk_len = 128;
-			i915_gem_dump_page(obj_priv->page_list[page],
+			i915_gem_dump_page(obj_priv->pages[page],
 					   chunk, chunk + chunk_len,
 					   obj_priv->gtt_offset +
 					   page * PAGE_SIZE,
@@ -143,7 +143,7 @@
 	uint32_t *backing_map = NULL;
 	int bad_count = 0;
 
-	DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n",
+	DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n",
 		 __func__, obj, obj_priv->gtt_offset, handle,
 		 obj->size / 1024);
 
@@ -157,7 +157,7 @@
 	for (page = 0; page < obj->size / PAGE_SIZE; page++) {
 		int i;
 
-		backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0);
+		backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0);
 
 		if (backing_map == NULL) {
 			DRM_ERROR("failed to map backing page\n");
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem_debugfs.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem_debugfs.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem_debugfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem_debugfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -75,11 +75,10 @@
 	case ACTIVE_LIST:
 		seq_printf(m, "Active:\n");
 		lock = &dev_priv->mm.active_list_lock;
-		spin_lock(lock);
 		head = &dev_priv->mm.active_list;
 		break;
 	case INACTIVE_LIST:
-		seq_printf(m, "Inctive:\n");
+		seq_printf(m, "Inactive:\n");
 		head = &dev_priv->mm.inactive_list;
 		break;
 	case FLUSHING_LIST:
@@ -91,6 +90,8 @@
 		return 0;
 	}
 
+	if (lock)
+		spin_lock(lock);
 	list_for_each_entry(obj_priv, head, list)
 	{
 		struct drm_gem_object *obj = obj_priv->obj;
@@ -104,7 +105,10 @@
 		if (obj->name)
 			seq_printf(m, " (name: %d)", obj->name);
 		if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-			seq_printf(m, " (fence: %d\n", obj_priv->fence_reg);
+			seq_printf(m, " (fence: %d)", obj_priv->fence_reg);
+		if (obj_priv->gtt_space != NULL)
+			seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset);
+
 		seq_printf(m, "\n");
 	}
 
@@ -318,11 +322,46 @@
 	seq_printf(m, "RingTail :  %08x\n", tail);
 	seq_printf(m, "RingMask :  %08x\n", mask);
 	seq_printf(m, "RingSize :  %08lx\n", dev_priv->ring.Size);
-	seq_printf(m, "Acthd :  %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
+	seq_printf(m, "Acthd :     %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
 
 	return 0;
 }
 
+static int i915_error_state(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_error_state *error;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->error_lock, flags);
+	if (!dev_priv->first_error) {
+		seq_printf(m, "no error state collected\n");
+		goto out;
+	}
+
+	error = dev_priv->first_error;
+
+	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
+		   error->time.tv_usec);
+	seq_printf(m, "EIR: 0x%08x\n", error->eir);
+	seq_printf(m, "  PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
+	seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir);
+	seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr);
+	seq_printf(m, "  INSTDONE: 0x%08x\n", error->instdone);
+	seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd);
+	if (IS_I965G(dev)) {
+		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps);
+		seq_printf(m, "  INSTDONE1: 0x%08x\n", error->instdone1);
+	}
+
+out:
+	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+
+	return 0;
+}
 
 static struct drm_info_list i915_gem_debugfs_list[] = {
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
@@ -336,6 +375,7 @@
 	{"i915_ringbuffer_data", i915_ringbuffer_data, 0},
 	{"i915_ringbuffer_info", i915_ringbuffer_info, 0},
 	{"i915_batchbuffers", i915_batchbuffer_info, 0},
+	{"i915_error_state", i915_error_state, 0},
 };
 #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,8 @@
  *
  */
 
+#include <linux/acpi.h>
+#include <linux/pnp.h>
 #include "linux/string.h"
 #include "linux/bitops.h"
 #include "drmP.h"
@@ -81,6 +83,145 @@
  * to match what the GPU expects.
  */
 
+#define MCHBAR_I915 0x44
+#define MCHBAR_I965 0x48
+#define MCHBAR_SIZE (4*4096)
+
+#define DEVEN_REG 0x54
+#define   DEVEN_MCHBAR_EN (1 << 28)
+
+/* Allocate space for the MCH regs if needed, return nonzero on error */
+static int
+intel_alloc_mchbar_resource(struct drm_device *dev)
+{
+	struct pci_dev *bridge_dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp_lo, temp_hi = 0;
+	u64 mchbar_addr;
+	int ret = 0;
+
+	bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+	if (!bridge_dev) {
+		DRM_DEBUG("no bridge dev?!\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (IS_I965G(dev))
+		pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
+	pci_read_config_dword(bridge_dev, reg, &temp_lo);
+	mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
+
+	/* If ACPI doesn't have it, assume we need to allocate it ourselves */
+#ifdef CONFIG_PNP
+	if (mchbar_addr &&
+	    pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
+		ret = 0;
+		goto out_put;
+	}
+#endif
+
+	/* Get some space for it */
+	ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
+				     MCHBAR_SIZE, MCHBAR_SIZE,
+				     PCIBIOS_MIN_MEM,
+				     0,   pcibios_align_resource,
+				     bridge_dev);
+	if (ret) {
+		DRM_DEBUG("failed bus alloc: %d\n", ret);
+		dev_priv->mch_res.start = 0;
+		goto out_put;
+	}
+
+	if (IS_I965G(dev))
+		pci_write_config_dword(bridge_dev, reg + 4,
+				       upper_32_bits(dev_priv->mch_res.start));
+
+	pci_write_config_dword(bridge_dev, reg,
+			       lower_32_bits(dev_priv->mch_res.start));
+out_put:
+	pci_dev_put(bridge_dev);
+out:
+	return ret;
+}
+
+/* Setup MCHBAR if possible, return true if we should disable it again */
+static bool
+intel_setup_mchbar(struct drm_device *dev)
+{
+	struct pci_dev *bridge_dev;
+	int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp;
+	bool need_disable = false, enabled;
+
+	bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+	if (!bridge_dev) {
+		DRM_DEBUG("no bridge dev?!\n");
+		goto out;
+	}
+
+	if (IS_I915G(dev) || IS_I915GM(dev)) {
+		pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
+		enabled = !!(temp & DEVEN_MCHBAR_EN);
+	} else {
+		pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+		enabled = temp & 1;
+	}
+
+	/* If it's already enabled, don't have to do anything */
+	if (enabled)
+		goto out_put;
+
+	if (intel_alloc_mchbar_resource(dev))
+		goto out_put;
+
+	need_disable = true;
+
+	/* Space is allocated or reserved, so enable it. */
+	if (IS_I915G(dev) || IS_I915GM(dev)) {
+		pci_write_config_dword(bridge_dev, DEVEN_REG,
+				       temp | DEVEN_MCHBAR_EN);
+	} else {
+		pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+		pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
+	}
+out_put:
+	pci_dev_put(bridge_dev);
+out:
+	return need_disable;
+}
+
+static void
+intel_teardown_mchbar(struct drm_device *dev, bool disable)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct pci_dev *bridge_dev;
+	int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp;
+
+	bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+	if (!bridge_dev) {
+		DRM_DEBUG("no bridge dev?!\n");
+		return;
+	}
+
+	if (disable) {
+		if (IS_I915G(dev) || IS_I915GM(dev)) {
+			pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
+			temp &= ~DEVEN_MCHBAR_EN;
+			pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
+		} else {
+			pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+			temp &= ~1;
+			pci_write_config_dword(bridge_dev, mchbar_reg, temp);
+		}
+	}
+
+	if (dev_priv->mch_res.start)
+		release_resource(&dev_priv->mch_res);
+}
+
 /**
  * Detects bit 6 swizzling of address lookup between IGD access and CPU
  * access through main memory.
@@ -91,6 +232,7 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+	bool need_disable;
 
 	if (!IS_I9XX(dev)) {
 		/* As far as we know, the 865 doesn't have these bit 6
@@ -101,6 +243,9 @@
 	} else if (IS_MOBILE(dev)) {
 		uint32_t dcc;
 
+		/* Try to make sure MCHBAR is enabled before poking at it */
+		need_disable = intel_setup_mchbar(dev);
+
 		/* On mobile 9xx chipsets, channel interleave by the CPU is
 		 * determined by DCC.  For single-channel, neither the CPU
 		 * nor the GPU do swizzling.  For dual channel interleaved,
@@ -140,6 +285,8 @@
 			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 		}
+
+		intel_teardown_mchbar(dev, need_disable);
 	} else {
 		/* The 965, G33, and newer, have a very flexible memory
 		 * configuration.  It will enable dual-channel mode
@@ -170,6 +317,13 @@
 		}
 	}
 
+	/* FIXME: check with memory config on IGDNG */
+	if (IS_IGDNG(dev)) {
+		DRM_ERROR("disable tiling on IGDNG...\n");
+		swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+		swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+	}
+
 	dev_priv->mm.bit_6_swizzle_x = swizzle_x;
 	dev_priv->mm.bit_6_swizzle_y = swizzle_y;
 }
@@ -256,7 +410,7 @@
 	if (stride & (stride - 1))
 		return false;
 
-	/* We don't handle the aperture area covered by the fence being bigger
+	/* We don't 0handle the aperture area covered by the fence being bigger
 	 * than the object size.
 	 */
 	if (i915_get_fence_size(dev, size) != size)
@@ -265,6 +419,33 @@
 	return true;
 }
 
+static bool
+i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+	if (obj_priv->gtt_space == NULL)
+		return true;
+
+	if (tiling_mode == I915_TILING_NONE)
+		return true;
+
+	if (!IS_I965G(dev)) {
+		if (obj_priv->gtt_offset & (obj->size - 1))
+			return false;
+		if (IS_I9XX(dev)) {
+			if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
+				return false;
+		} else {
+			if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
+				return false;
+		}
+	}
+
+	return true;
+}
+
 /**
  * Sets the tiling mode of an object, returning the required swizzling of
  * bit 6 of addresses in the object.
@@ -277,6 +458,7 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_gem_object *obj;
 	struct drm_i915_gem_object *obj_priv;
+	int ret = 0;
 
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
 	if (obj == NULL)
@@ -284,14 +466,15 @@
 	obj_priv = obj->driver_private;
 
 	if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
+		mutex_lock(&dev->struct_mutex);
 		drm_gem_object_unreference(obj);
+		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
-	mutex_lock(&dev->struct_mutex);
-
 	if (args->tiling_mode == I915_TILING_NONE) {
 		args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+		args->stride = 0;
 	} else {
 		if (args->tiling_mode == I915_TILING_X)
 			args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
@@ -314,32 +497,44 @@
 		if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
 			args->tiling_mode = I915_TILING_NONE;
 			args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+			args->stride = 0;
 		}
 	}
-	if (args->tiling_mode != obj_priv->tiling_mode) {
-		int ret;
 
-		/* Unbind the object, as switching tiling means we're
-		 * switching the cache organization due to fencing, probably.
+	mutex_lock(&dev->struct_mutex);
+	if (args->tiling_mode != obj_priv->tiling_mode ||
+	    args->stride != obj_priv->stride) {
+		/* We need to rebind the object if its current allocation
+		 * no longer meets the alignment restrictions for its new
+		 * tiling mode. Otherwise we can just leave it alone, but
+		 * need to ensure that any fence register is cleared.
 		 */
-		ret = i915_gem_object_unbind(obj);
+		if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
+		    ret = i915_gem_object_unbind(obj);
+		else
+		    ret = i915_gem_object_put_fence_reg(obj);
 		if (ret != 0) {
 			WARN(ret != -ERESTARTSYS,
-			     "failed to unbind object for tiling switch");
+			     "failed to reset object for tiling switch");
 			args->tiling_mode = obj_priv->tiling_mode;
-			mutex_unlock(&dev->struct_mutex);
-			drm_gem_object_unreference(obj);
-
-			return ret;
+			args->stride = obj_priv->stride;
+			goto err;
 		}
+
+		/* If we've changed tiling, GTT-mappings of the object
+		 * need to re-fault to ensure that the correct fence register
+		 * setup is in place.
+		 */
+		i915_gem_release_mmap(obj);
+
 		obj_priv->tiling_mode = args->tiling_mode;
+		obj_priv->stride = args->stride;
 	}
-	obj_priv->stride = args->stride;
-
+err:
 	drm_gem_object_unreference(obj);
 	mutex_unlock(&dev->struct_mutex);
 
-	return 0;
+	return ret;
 }
 
 /**
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
  *
  */
 
+#include <linux/sysrq.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
@@ -41,9 +42,10 @@
  * we leave them always unmasked in IMR and then control enabling them through
  * PIPESTAT alone.
  */
-#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
-				   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |  \
-				   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT |		 \
+				   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+				   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \
+				   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 
 /** Interrupts that we mask and unmask at runtime. */
 #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
@@ -58,6 +60,47 @@
 					 DRM_I915_VBLANK_PIPE_B)
 
 void
+igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
+		dev_priv->gt_irq_mask_reg &= ~mask;
+		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
+		(void) I915_READ(GTIMR);
+	}
+}
+
+static inline void
+igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
+		dev_priv->gt_irq_mask_reg |= mask;
+		I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
+		(void) I915_READ(GTIMR);
+	}
+}
+
+/* For display hotplug interrupt */
+void
+igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	if ((dev_priv->irq_mask_reg & mask) != 0) {
+		dev_priv->irq_mask_reg &= ~mask;
+		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
+		(void) I915_READ(DEIMR);
+	}
+}
+
+static inline void
+igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
+{
+	if ((dev_priv->irq_mask_reg & mask) != mask) {
+		dev_priv->irq_mask_reg |= mask;
+		I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
+		(void) I915_READ(DEIMR);
+	}
+}
+
+void
 i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
 	if ((dev_priv->irq_mask_reg & mask) != 0) {
@@ -147,7 +190,7 @@
 	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
 
 	if (!i915_pipe_enabled(dev, pipe)) {
-		DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+		DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
 		return 0;
 	}
 
@@ -176,7 +219,7 @@
 	int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
 
 	if (!i915_pipe_enabled(dev, pipe)) {
-		DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+		DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
 		return 0;
 	}
 
@@ -191,11 +234,257 @@
 	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
 						    hotplug_work);
 	struct drm_device *dev = dev_priv->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *connector;
 
+	if (mode_config->num_connector) {
+		list_for_each_entry(connector, &mode_config->connector_list, head) {
+			struct intel_output *intel_output = to_intel_output(connector);
+	
+			if (intel_output->hot_plug)
+				(*intel_output->hot_plug) (intel_output);
+		}
+	}
 	/* Just fire off a uevent and let userspace tell us what to do */
 	drm_sysfs_hotplug_event(dev);
 }
 
+irqreturn_t igdng_irq_handler(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int ret = IRQ_NONE;
+	u32 de_iir, gt_iir;
+	u32 new_de_iir, new_gt_iir;
+	struct drm_i915_master_private *master_priv;
+
+	de_iir = I915_READ(DEIIR);
+	gt_iir = I915_READ(GTIIR);
+
+	for (;;) {
+		if (de_iir == 0 && gt_iir == 0)
+			break;
+
+		ret = IRQ_HANDLED;
+
+		I915_WRITE(DEIIR, de_iir);
+		new_de_iir = I915_READ(DEIIR);
+		I915_WRITE(GTIIR, gt_iir);
+		new_gt_iir = I915_READ(GTIIR);
+
+		if (dev->primary->master) {
+			master_priv = dev->primary->master->driver_priv;
+			if (master_priv->sarea_priv)
+				master_priv->sarea_priv->last_dispatch =
+					READ_BREADCRUMB(dev_priv);
+		}
+
+		if (gt_iir & GT_USER_INTERRUPT) {
+			dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
+			DRM_WAKEUP(&dev_priv->irq_queue);
+		}
+
+		de_iir = new_de_iir;
+		gt_iir = new_gt_iir;
+	}
+
+	return ret;
+}
+
+/**
+ * i915_error_work_func - do process context error handling work
+ * @work: work struct
+ *
+ * Fire an error uevent so userspace can see that a hang or error
+ * was detected.
+ */
+static void i915_error_work_func(struct work_struct *work)
+{
+	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
+						    error_work);
+	struct drm_device *dev = dev_priv->dev;
+	char *event_string = "ERROR=1";
+	char *envp[] = { event_string, NULL };
+
+	DRM_DEBUG("generating error event\n");
+
+	kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp);
+}
+
+/**
+ * i915_capture_error_state - capture an error record for later analysis
+ * @dev: drm device
+ *
+ * Should be called when an error is detected (either a hang or an error
+ * interrupt) to capture error state from the time of the error.  Fills
+ * out a structure which becomes available in debugfs for user level tools
+ * to pick up.
+ */
+static void i915_capture_error_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_error_state *error;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->error_lock, flags);
+	if (dev_priv->first_error)
+		goto out;
+
+	error = kmalloc(sizeof(*error), GFP_ATOMIC);
+	if (!error) {
+		DRM_DEBUG("out ot memory, not capturing error state\n");
+		goto out;
+	}
+
+	error->eir = I915_READ(EIR);
+	error->pgtbl_er = I915_READ(PGTBL_ER);
+	error->pipeastat = I915_READ(PIPEASTAT);
+	error->pipebstat = I915_READ(PIPEBSTAT);
+	error->instpm = I915_READ(INSTPM);
+	if (!IS_I965G(dev)) {
+		error->ipeir = I915_READ(IPEIR);
+		error->ipehr = I915_READ(IPEHR);
+		error->instdone = I915_READ(INSTDONE);
+		error->acthd = I915_READ(ACTHD);
+	} else {
+		error->ipeir = I915_READ(IPEIR_I965);
+		error->ipehr = I915_READ(IPEHR_I965);
+		error->instdone = I915_READ(INSTDONE_I965);
+		error->instps = I915_READ(INSTPS);
+		error->instdone1 = I915_READ(INSTDONE1);
+		error->acthd = I915_READ(ACTHD_I965);
+	}
+
+	do_gettimeofday(&error->time);
+
+	dev_priv->first_error = error;
+
+out:
+	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+}
+
+/**
+ * i915_handle_error - handle an error interrupt
+ * @dev: drm device
+ *
+ * Do some basic checking of regsiter state at error interrupt time and
+ * dump it to the syslog.  Also call i915_capture_error_state() to make
+ * sure we get a record and make it available in debugfs.  Fire a uevent
+ * so userspace knows something bad happened (should trigger collection
+ * of a ring dump etc.).
+ */
+static void i915_handle_error(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 eir = I915_READ(EIR);
+	u32 pipea_stats = I915_READ(PIPEASTAT);
+	u32 pipeb_stats = I915_READ(PIPEBSTAT);
+
+	i915_capture_error_state(dev);
+
+	printk(KERN_ERR "render error detected, EIR: 0x%08x\n",
+	       eir);
+
+	if (IS_G4X(dev)) {
+		if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
+			u32 ipeir = I915_READ(IPEIR_I965);
+
+			printk(KERN_ERR "  IPEIR: 0x%08x\n",
+			       I915_READ(IPEIR_I965));
+			printk(KERN_ERR "  IPEHR: 0x%08x\n",
+			       I915_READ(IPEHR_I965));
+			printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+			       I915_READ(INSTDONE_I965));
+			printk(KERN_ERR "  INSTPS: 0x%08x\n",
+			       I915_READ(INSTPS));
+			printk(KERN_ERR "  INSTDONE1: 0x%08x\n",
+			       I915_READ(INSTDONE1));
+			printk(KERN_ERR "  ACTHD: 0x%08x\n",
+			       I915_READ(ACTHD_I965));
+			I915_WRITE(IPEIR_I965, ipeir);
+			(void)I915_READ(IPEIR_I965);
+		}
+		if (eir & GM45_ERROR_PAGE_TABLE) {
+			u32 pgtbl_err = I915_READ(PGTBL_ER);
+			printk(KERN_ERR "page table error\n");
+			printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
+			       pgtbl_err);
+			I915_WRITE(PGTBL_ER, pgtbl_err);
+			(void)I915_READ(PGTBL_ER);
+		}
+	}
+
+	if (IS_I9XX(dev)) {
+		if (eir & I915_ERROR_PAGE_TABLE) {
+			u32 pgtbl_err = I915_READ(PGTBL_ER);
+			printk(KERN_ERR "page table error\n");
+			printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
+			       pgtbl_err);
+			I915_WRITE(PGTBL_ER, pgtbl_err);
+			(void)I915_READ(PGTBL_ER);
+		}
+	}
+
+	if (eir & I915_ERROR_MEMORY_REFRESH) {
+		printk(KERN_ERR "memory refresh error\n");
+		printk(KERN_ERR "PIPEASTAT: 0x%08x\n",
+		       pipea_stats);
+		printk(KERN_ERR "PIPEBSTAT: 0x%08x\n",
+		       pipeb_stats);
+		/* pipestat has already been acked */
+	}
+	if (eir & I915_ERROR_INSTRUCTION) {
+		printk(KERN_ERR "instruction error\n");
+		printk(KERN_ERR "  INSTPM: 0x%08x\n",
+		       I915_READ(INSTPM));
+		if (!IS_I965G(dev)) {
+			u32 ipeir = I915_READ(IPEIR);
+
+			printk(KERN_ERR "  IPEIR: 0x%08x\n",
+			       I915_READ(IPEIR));
+			printk(KERN_ERR "  IPEHR: 0x%08x\n",
+			       I915_READ(IPEHR));
+			printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+			       I915_READ(INSTDONE));
+			printk(KERN_ERR "  ACTHD: 0x%08x\n",
+			       I915_READ(ACTHD));
+			I915_WRITE(IPEIR, ipeir);
+			(void)I915_READ(IPEIR);
+		} else {
+			u32 ipeir = I915_READ(IPEIR_I965);
+
+			printk(KERN_ERR "  IPEIR: 0x%08x\n",
+			       I915_READ(IPEIR_I965));
+			printk(KERN_ERR "  IPEHR: 0x%08x\n",
+			       I915_READ(IPEHR_I965));
+			printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+			       I915_READ(INSTDONE_I965));
+			printk(KERN_ERR "  INSTPS: 0x%08x\n",
+			       I915_READ(INSTPS));
+			printk(KERN_ERR "  INSTDONE1: 0x%08x\n",
+			       I915_READ(INSTDONE1));
+			printk(KERN_ERR "  ACTHD: 0x%08x\n",
+			       I915_READ(ACTHD_I965));
+			I915_WRITE(IPEIR_I965, ipeir);
+			(void)I915_READ(IPEIR_I965);
+		}
+	}
+
+	I915_WRITE(EIR, eir);
+	(void)I915_READ(EIR);
+	eir = I915_READ(EIR);
+	if (eir) {
+		/*
+		 * some errors might have become stuck,
+		 * mask them.
+		 */
+		DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir);
+		I915_WRITE(EMR, I915_READ(EMR) | eir);
+		I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+	}
+
+	queue_work(dev_priv->wq, &dev_priv->error_work);
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -212,6 +501,9 @@
 
 	atomic_inc(&dev_priv->irq_received);
 
+	if (IS_IGDNG(dev))
+		return igdng_irq_handler(dev);
+
 	iir = I915_READ(IIR);
 
 	if (IS_I965G(dev)) {
@@ -234,15 +526,22 @@
 		pipea_stats = I915_READ(PIPEASTAT);
 		pipeb_stats = I915_READ(PIPEBSTAT);
 
+		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+			i915_handle_error(dev);
+
 		/*
 		 * Clear the PIPE(A|B)STAT regs before the IIR
 		 */
 		if (pipea_stats & 0x8000ffff) {
+			if (pipea_stats &  PIPE_FIFO_UNDERRUN_STATUS)
+				DRM_DEBUG("pipe a underrun\n");
 			I915_WRITE(PIPEASTAT, pipea_stats);
 			irq_received = 1;
 		}
 
 		if (pipeb_stats & 0x8000ffff) {
+			if (pipeb_stats &  PIPE_FIFO_UNDERRUN_STATUS)
+				DRM_DEBUG("pipe b underrun\n");
 			I915_WRITE(PIPEBSTAT, pipeb_stats);
 			irq_received = 1;
 		}
@@ -261,7 +560,8 @@
 			DRM_DEBUG("hotplug event received, stat 0x%08x\n",
 				  hotplug_status);
 			if (hotplug_status & dev_priv->hotplug_supported_mask)
-				schedule_work(&dev_priv->hotplug_work);
+				queue_work(dev_priv->wq,
+					   &dev_priv->hotplug_work);
 
 			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
 			I915_READ(PORT_HOTPLUG_STAT);
@@ -349,8 +649,12 @@
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
-		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
+		if (IS_IGDNG(dev))
+			igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
+		else
+			i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+	}
 	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
 }
 
@@ -361,8 +665,12 @@
 
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
 	BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
-	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
-		i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
+		if (IS_IGDNG(dev))
+			igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
+		else
+			i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+	}
 	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
 }
 
@@ -455,6 +763,9 @@
 	if (!(pipeconf & PIPEACONF_ENABLE))
 		return -EINVAL;
 
+	if (IS_IGDNG(dev))
+		return 0;
+
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
 	if (IS_I965G(dev))
 		i915_enable_pipestat(dev_priv, pipe,
@@ -474,6 +785,9 @@
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
 
+	if (IS_IGDNG(dev))
+		return;
+
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
 	i915_disable_pipestat(dev_priv, pipe,
 			      PIPE_VBLANK_INTERRUPT_ENABLE |
@@ -484,7 +798,9 @@
 void i915_enable_interrupt (struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	opregion_enable_asle(dev);
+
+	if (!IS_IGDNG(dev))
+		opregion_enable_asle(dev);
 	dev_priv->irq_enabled = 1;
 }
 
@@ -545,12 +861,66 @@
 
 /* drm_dma.h hooks
 */
+static void igdng_irq_preinstall(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	I915_WRITE(HWSTAM, 0xeffe);
+
+	/* XXX hotplug from PCH */
+
+	I915_WRITE(DEIMR, 0xffffffff);
+	I915_WRITE(DEIER, 0x0);
+	(void) I915_READ(DEIER);
+
+	/* and GT */
+	I915_WRITE(GTIMR, 0xffffffff);
+	I915_WRITE(GTIER, 0x0);
+	(void) I915_READ(GTIER);
+}
+
+static int igdng_irq_postinstall(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	/* enable kind of interrupts always enabled */
+	u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
+	u32 render_mask = GT_USER_INTERRUPT;
+
+	dev_priv->irq_mask_reg = ~display_mask;
+	dev_priv->de_irq_enable_reg = display_mask;
+
+	/* should always can generate irq */
+	I915_WRITE(DEIIR, I915_READ(DEIIR));
+	I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
+	I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
+	(void) I915_READ(DEIER);
+
+	/* user interrupt should be enabled, but masked initial */
+	dev_priv->gt_irq_mask_reg = 0xffffffff;
+	dev_priv->gt_irq_enable_reg = render_mask;
+
+	I915_WRITE(GTIIR, I915_READ(GTIIR));
+	I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
+	I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
+	(void) I915_READ(GTIER);
+
+	return 0;
+}
+
 void i915_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
 	atomic_set(&dev_priv->irq_received, 0);
 
+	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
+
+	if (IS_IGDNG(dev)) {
+		igdng_irq_preinstall(dev);
+		return;
+	}
+
 	if (I915_HAS_HOTPLUG(dev)) {
 		I915_WRITE(PORT_HOTPLUG_EN, 0);
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -562,17 +932,20 @@
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
 	(void) I915_READ(IER);
-	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
 }
 
 int i915_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+	u32 error_mask;
+
+	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
-	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+	if (IS_IGDNG(dev))
+		return igdng_irq_postinstall(dev);
 
 	/* Unmask the interrupts that we always want on. */
 	dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
@@ -602,6 +975,21 @@
 		i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
 	}
 
+	/*
+	 * Enable some error detection, note the instruction error mask
+	 * bit is reserved, so we leave it masked.
+	 */
+	if (IS_G4X(dev)) {
+		error_mask = ~(GM45_ERROR_PAGE_TABLE |
+			       GM45_ERROR_MEM_PRIV |
+			       GM45_ERROR_CP_PRIV |
+			       I915_ERROR_MEMORY_REFRESH);
+	} else {
+		error_mask = ~(I915_ERROR_PAGE_TABLE |
+			       I915_ERROR_MEMORY_REFRESH);
+	}
+	I915_WRITE(EMR, error_mask);
+
 	/* Disable pipe interrupt enables, clear pending pipe status */
 	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
 	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
@@ -613,11 +1001,24 @@
 	(void) I915_READ(IER);
 
 	opregion_enable_asle(dev);
-	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 
 	return 0;
 }
 
+static void igdng_irq_uninstall(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	I915_WRITE(HWSTAM, 0xffffffff);
+
+	I915_WRITE(DEIMR, 0xffffffff);
+	I915_WRITE(DEIER, 0x0);
+	I915_WRITE(DEIIR, I915_READ(DEIIR));
+
+	I915_WRITE(GTIMR, 0xffffffff);
+	I915_WRITE(GTIER, 0x0);
+	I915_WRITE(GTIIR, I915_READ(GTIIR));
+}
+
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -627,6 +1028,11 @@
 
 	dev_priv->vblank_pipe = 0;
 
+	if (IS_IGDNG(dev)) {
+		igdng_irq_uninstall(dev);
+		return;
+	}
+
 	if (I915_HAS_HOTPLUG(dev)) {
 		I915_WRITE(PORT_HOTPLUG_EN, 0);
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_mem.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_mem.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_mem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_mem.c	2009-09-09 18:13:59.000000000 -0400
@@ -94,8 +94,8 @@
 {
 	/* Maybe cut off the start of an existing block */
 	if (start > p->start) {
-		struct mem_block *newblock =
-		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+		struct mem_block *newblock = kmalloc(sizeof(*newblock),
+						     GFP_KERNEL);
 		if (!newblock)
 			goto out;
 		newblock->start = start;
@@ -111,8 +111,8 @@
 
 	/* Maybe cut off the end of an existing block */
 	if (size < p->size) {
-		struct mem_block *newblock =
-		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+		struct mem_block *newblock = kmalloc(sizeof(*newblock),
+						     GFP_KERNEL);
 		if (!newblock)
 			goto out;
 		newblock->start = start + size;
@@ -169,7 +169,7 @@
 		p->size += q->size;
 		p->next = q->next;
 		p->next->prev = p;
-		drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+		kfree(q);
 	}
 
 	if (p->prev->file_priv == NULL) {
@@ -177,7 +177,7 @@
 		q->size += p->size;
 		q->next = p->next;
 		q->next->prev = q;
-		drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS);
+		kfree(p);
 	}
 }
 
@@ -185,14 +185,14 @@
  */
 static int init_heap(struct mem_block **heap, int start, int size)
 {
-	struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS);
+	struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
 
 	if (!blocks)
 		return -ENOMEM;
 
-	*heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS);
+	*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
 	if (!*heap) {
-		drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS);
+		kfree(blocks);
 		return -ENOMEM;
 	}
 
@@ -233,7 +233,7 @@
 			p->size += q->size;
 			p->next = q->next;
 			p->next->prev = p;
-			drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+			kfree(q);
 		}
 	}
 }
@@ -250,10 +250,10 @@
 	for (p = (*heap)->next; p != *heap;) {
 		struct mem_block *q = p;
 		p = p->next;
-		drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+		kfree(q);
 	}
 
-	drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS);
+	kfree(*heap);
 	*heap = NULL;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_opregion.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_opregion.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_opregion.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_opregion.c	2009-09-09 18:13:59.000000000 -0400
@@ -419,7 +419,7 @@
 		return;
 
 	if (!suspend)
-		acpi_video_exit();
+		acpi_video_unregister();
 
 	opregion->acpi->drdy = 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -206,6 +206,7 @@
 /*
  * Instruction and interrupt control regs
  */
+#define PGTBL_ER	0x02024
 #define PRB0_TAIL	0x02030
 #define PRB0_HEAD	0x02034
 #define PRB0_START	0x02038
@@ -226,11 +227,18 @@
 #define PRB1_HEAD	0x02044 /* 915+ only */
 #define PRB1_START	0x02048 /* 915+ only */
 #define PRB1_CTL	0x0204c /* 915+ only */
+#define IPEIR_I965	0x02064
+#define IPEHR_I965	0x02068
+#define INSTDONE_I965	0x0206c
+#define INSTPS		0x02070 /* 965+ only */
+#define INSTDONE1	0x0207c /* 965+ only */
 #define ACTHD_I965	0x02074
 #define HWS_PGA		0x02080
 #define HWS_ADDRESS_MASK	0xfffff000
 #define HWS_START_ADDRESS_SHIFT	4
 #define IPEIR		0x02088
+#define IPEHR		0x0208c
+#define INSTDONE	0x02090
 #define NOPID		0x02094
 #define HWSTAM		0x02098
 #define SCPD0		0x0209c /* 915+ only */
@@ -258,10 +266,22 @@
 #define EIR		0x020b0
 #define EMR		0x020b4
 #define ESR		0x020b8
+#define   GM45_ERROR_PAGE_TABLE				(1<<5)
+#define   GM45_ERROR_MEM_PRIV				(1<<4)
+#define   I915_ERROR_PAGE_TABLE				(1<<4)
+#define   GM45_ERROR_CP_PRIV				(1<<3)
+#define   I915_ERROR_MEMORY_REFRESH			(1<<1)
+#define   I915_ERROR_INSTRUCTION			(1<<0)
 #define INSTPM	        0x020c0
 #define ACTHD	        0x020c8
 #define FW_BLC		0x020d8
+#define FW_BLC2	 	0x020dc
 #define FW_BLC_SELF	0x020e0 /* 915+ only */
+#define   FW_BLC_SELF_EN (1<<15)
+#define MM_BURST_LENGTH     0x00700000
+#define MM_FIFO_WATERMARK   0x0001F000
+#define LM_BURST_LENGTH     0x00000700
+#define LM_FIFO_WATERMARK   0x0000001F
 #define MI_ARB_STATE	0x020e4 /* 915+ only */
 #define CACHE_MODE_0	0x02120 /* 915+ only */
 #define   CM0_MASK_SHIFT          16
@@ -450,6 +470,13 @@
 #define   PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
 #define   PLL_REF_INPUT_MASK		(3 << 13)
 #define   PLL_LOAD_PULSE_PHASE_SHIFT		9
+/* IGDNG */
+# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT     9
+# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK      (7 << 9)
+# define PLL_REF_SDVO_HDMI_MULTIPLIER(x)	(((x)-1) << 9)
+# define DPLL_FPA1_P1_POST_DIV_SHIFT            0
+# define DPLL_FPA1_P1_POST_DIV_MASK             0xff
+
 /*
  * Parallel to Serial Load Pulse phase selection.
  * Selects the phase for the 10X DPLL clock for the PCIe
@@ -562,6 +589,23 @@
 #define C0DRB3			0x10206
 #define C1DRB3			0x10606
 
+/* Clocking configuration register */
+#define CLKCFG			0x10c00
+#define CLKCFG_FSB_400					(5 << 0)	/* hrawclk 100 */
+#define CLKCFG_FSB_533					(1 << 0)	/* hrawclk 133 */
+#define CLKCFG_FSB_667					(3 << 0)	/* hrawclk 166 */
+#define CLKCFG_FSB_800					(2 << 0)	/* hrawclk 200 */
+#define CLKCFG_FSB_1067					(6 << 0)	/* hrawclk 266 */
+#define CLKCFG_FSB_1333					(7 << 0)	/* hrawclk 333 */
+/* Note, below two are guess */
+#define CLKCFG_FSB_1600					(4 << 0)	/* hrawclk 400 */
+#define CLKCFG_FSB_1600_ALT				(0 << 0)	/* hrawclk 400 */
+#define CLKCFG_FSB_MASK					(7 << 0)
+#define CLKCFG_MEM_533					(1 << 4)
+#define CLKCFG_MEM_667					(2 << 4)
+#define CLKCFG_MEM_800					(3 << 4)
+#define CLKCFG_MEM_MASK					(7 << 4)
+
 /** GM965 GM45 render standby register */
 #define MCHBAR_RENDER_STANDBY	0x111B8
 
@@ -631,8 +675,11 @@
 /* Hotplug control (945+ only) */
 #define PORT_HOTPLUG_EN		0x61110
 #define   HDMIB_HOTPLUG_INT_EN			(1 << 29)
+#define   DPB_HOTPLUG_INT_EN			(1 << 29)
 #define   HDMIC_HOTPLUG_INT_EN			(1 << 28)
+#define   DPC_HOTPLUG_INT_EN			(1 << 28)
 #define   HDMID_HOTPLUG_INT_EN			(1 << 27)
+#define   DPD_HOTPLUG_INT_EN			(1 << 27)
 #define   SDVOB_HOTPLUG_INT_EN			(1 << 26)
 #define   SDVOC_HOTPLUG_INT_EN			(1 << 25)
 #define   TV_HOTPLUG_INT_EN			(1 << 18)
@@ -665,8 +712,11 @@
 
 #define PORT_HOTPLUG_STAT	0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS		(1 << 29)
+#define   DPB_HOTPLUG_INT_STATUS		(1 << 29)
 #define   HDMIC_HOTPLUG_INT_STATUS		(1 << 28)
+#define   DPC_HOTPLUG_INT_STATUS		(1 << 28)
 #define   HDMID_HOTPLUG_INT_STATUS		(1 << 27)
+#define   DPD_HOTPLUG_INT_STATUS		(1 << 27)
 #define   CRT_HOTPLUG_INT_STATUS		(1 << 11)
 #define   TV_HOTPLUG_INT_STATUS			(1 << 10)
 #define   CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
@@ -821,9 +871,25 @@
 #define   HORIZ_INTERP_MASK	(3 << 6)
 #define   HORIZ_AUTO_SCALE	(1 << 5)
 #define   PANEL_8TO6_DITHER_ENABLE (1 << 3)
+#define   PFIT_FILTER_FUZZY	(0 << 24)
+#define   PFIT_SCALING_AUTO	(0 << 26)
+#define   PFIT_SCALING_PROGRAMMED (1 << 26)
+#define   PFIT_SCALING_PILLAR	(2 << 26)
+#define   PFIT_SCALING_LETTER	(3 << 26)
 #define PFIT_PGM_RATIOS	0x61234
 #define   PFIT_VERT_SCALE_MASK			0xfff00000
 #define   PFIT_HORIZ_SCALE_MASK			0x0000fff0
+/* Pre-965 */
+#define		PFIT_VERT_SCALE_SHIFT		20
+#define		PFIT_VERT_SCALE_MASK		0xfff00000
+#define		PFIT_HORIZ_SCALE_SHIFT		4
+#define		PFIT_HORIZ_SCALE_MASK		0x0000fff0
+/* 965+ */
+#define		PFIT_VERT_SCALE_SHIFT_965	16
+#define		PFIT_VERT_SCALE_MASK_965	0x1fff0000
+#define		PFIT_HORIZ_SCALE_SHIFT_965	0
+#define		PFIT_HORIZ_SCALE_MASK_965	0x00001fff
+
 #define PFIT_AUTO_RATIOS 0x61238
 
 /* Backlight control */
@@ -951,15 +1017,15 @@
 # define DAC_A_1_3_V			(0 << 4)
 # define DAC_A_1_1_V			(1 << 4)
 # define DAC_A_0_7_V			(2 << 4)
-# define DAC_A_OFF			(3 << 4)
+# define DAC_A_MASK			(3 << 4)
 # define DAC_B_1_3_V			(0 << 2)
 # define DAC_B_1_1_V			(1 << 2)
 # define DAC_B_0_7_V			(2 << 2)
-# define DAC_B_OFF			(3 << 2)
+# define DAC_B_MASK			(3 << 2)
 # define DAC_C_1_3_V			(0 << 0)
 # define DAC_C_1_1_V			(1 << 0)
 # define DAC_C_0_7_V			(2 << 0)
-# define DAC_C_OFF			(3 << 0)
+# define DAC_C_MASK			(3 << 0)
 
 /**
  * CSC coefficients are stored in a floating point format with 9 bits of
@@ -1328,6 +1394,180 @@
 #define TV_V_CHROMA_0		0x68400
 #define TV_V_CHROMA_42		0x684a8
 
+/* Display Port */
+#define DP_A				0x64000 /* eDP */
+#define DP_B				0x64100
+#define DP_C				0x64200
+#define DP_D				0x64300
+
+#define   DP_PORT_EN			(1 << 31)
+#define   DP_PIPEB_SELECT		(1 << 30)
+
+/* Link training mode - select a suitable mode for each stage */
+#define   DP_LINK_TRAIN_PAT_1		(0 << 28)
+#define   DP_LINK_TRAIN_PAT_2		(1 << 28)
+#define   DP_LINK_TRAIN_PAT_IDLE	(2 << 28)
+#define   DP_LINK_TRAIN_OFF		(3 << 28)
+#define   DP_LINK_TRAIN_MASK		(3 << 28)
+#define   DP_LINK_TRAIN_SHIFT		28
+
+/* Signal voltages. These are mostly controlled by the other end */
+#define   DP_VOLTAGE_0_4		(0 << 25)
+#define   DP_VOLTAGE_0_6		(1 << 25)
+#define   DP_VOLTAGE_0_8		(2 << 25)
+#define   DP_VOLTAGE_1_2		(3 << 25)
+#define   DP_VOLTAGE_MASK		(7 << 25)
+#define   DP_VOLTAGE_SHIFT		25
+
+/* Signal pre-emphasis levels, like voltages, the other end tells us what
+ * they want
+ */
+#define   DP_PRE_EMPHASIS_0		(0 << 22)
+#define   DP_PRE_EMPHASIS_3_5		(1 << 22)
+#define   DP_PRE_EMPHASIS_6		(2 << 22)
+#define   DP_PRE_EMPHASIS_9_5		(3 << 22)
+#define   DP_PRE_EMPHASIS_MASK		(7 << 22)
+#define   DP_PRE_EMPHASIS_SHIFT		22
+
+/* How many wires to use. I guess 3 was too hard */
+#define   DP_PORT_WIDTH_1		(0 << 19)
+#define   DP_PORT_WIDTH_2		(1 << 19)
+#define   DP_PORT_WIDTH_4		(3 << 19)
+#define   DP_PORT_WIDTH_MASK		(7 << 19)
+
+/* Mystic DPCD version 1.1 special mode */
+#define   DP_ENHANCED_FRAMING		(1 << 18)
+
+/* eDP */
+#define   DP_PLL_FREQ_270MHZ		(0 << 16)
+#define   DP_PLL_FREQ_160MHZ		(1 << 16)
+#define   DP_PLL_FREQ_MASK		(3 << 16)
+
+/** locked once port is enabled */
+#define   DP_PORT_REVERSAL		(1 << 15)
+
+/* eDP */
+#define   DP_PLL_ENABLE			(1 << 14)
+
+/** sends the clock on lane 15 of the PEG for debug */
+#define   DP_CLOCK_OUTPUT_ENABLE	(1 << 13)
+
+#define   DP_SCRAMBLING_DISABLE		(1 << 12)
+#define   DP_SCRAMBLING_DISABLE_IGDNG	(1 << 7)
+
+/** limit RGB values to avoid confusing TVs */
+#define   DP_COLOR_RANGE_16_235		(1 << 8)
+
+/** Turn on the audio link */
+#define   DP_AUDIO_OUTPUT_ENABLE	(1 << 6)
+
+/** vs and hs sync polarity */
+#define   DP_SYNC_VS_HIGH		(1 << 4)
+#define   DP_SYNC_HS_HIGH		(1 << 3)
+
+/** A fantasy */
+#define   DP_DETECTED			(1 << 2)
+
+/** The aux channel provides a way to talk to the
+ * signal sink for DDC etc. Max packet size supported
+ * is 20 bytes in each direction, hence the 5 fixed
+ * data registers
+ */
+#define DPA_AUX_CH_CTL			0x64010
+#define DPA_AUX_CH_DATA1		0x64014
+#define DPA_AUX_CH_DATA2		0x64018
+#define DPA_AUX_CH_DATA3		0x6401c
+#define DPA_AUX_CH_DATA4		0x64020
+#define DPA_AUX_CH_DATA5		0x64024
+
+#define DPB_AUX_CH_CTL			0x64110
+#define DPB_AUX_CH_DATA1		0x64114
+#define DPB_AUX_CH_DATA2		0x64118
+#define DPB_AUX_CH_DATA3		0x6411c
+#define DPB_AUX_CH_DATA4		0x64120
+#define DPB_AUX_CH_DATA5		0x64124
+
+#define DPC_AUX_CH_CTL			0x64210
+#define DPC_AUX_CH_DATA1		0x64214
+#define DPC_AUX_CH_DATA2		0x64218
+#define DPC_AUX_CH_DATA3		0x6421c
+#define DPC_AUX_CH_DATA4		0x64220
+#define DPC_AUX_CH_DATA5		0x64224
+
+#define DPD_AUX_CH_CTL			0x64310
+#define DPD_AUX_CH_DATA1		0x64314
+#define DPD_AUX_CH_DATA2		0x64318
+#define DPD_AUX_CH_DATA3		0x6431c
+#define DPD_AUX_CH_DATA4		0x64320
+#define DPD_AUX_CH_DATA5		0x64324
+
+#define   DP_AUX_CH_CTL_SEND_BUSY	    (1 << 31)
+#define   DP_AUX_CH_CTL_DONE		    (1 << 30)
+#define   DP_AUX_CH_CTL_INTERRUPT	    (1 << 29)
+#define   DP_AUX_CH_CTL_TIME_OUT_ERROR	    (1 << 28)
+#define   DP_AUX_CH_CTL_TIME_OUT_400us	    (0 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_600us	    (1 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_800us	    (2 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_1600us	    (3 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_MASK	    (3 << 26)
+#define   DP_AUX_CH_CTL_RECEIVE_ERROR	    (1 << 25)
+#define   DP_AUX_CH_CTL_MESSAGE_SIZE_MASK    (0x1f << 20)
+#define   DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT   20
+#define   DP_AUX_CH_CTL_PRECHARGE_2US_MASK   (0xf << 16)
+#define   DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT  16
+#define   DP_AUX_CH_CTL_AUX_AKSV_SELECT	    (1 << 15)
+#define   DP_AUX_CH_CTL_MANCHESTER_TEST	    (1 << 14)
+#define   DP_AUX_CH_CTL_SYNC_TEST	    (1 << 13)
+#define   DP_AUX_CH_CTL_DEGLITCH_TEST	    (1 << 12)
+#define   DP_AUX_CH_CTL_PRECHARGE_TEST	    (1 << 11)
+#define   DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK    (0x7ff)
+#define   DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT   0
+
+/*
+ * Computing GMCH M and N values for the Display Port link
+ *
+ * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes
+ *
+ * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz)
+ *
+ * The GMCH value is used internally
+ *
+ * bytes_per_pixel is the number of bytes coming out of the plane,
+ * which is after the LUTs, so we want the bytes for our color format.
+ * For our current usage, this is always 3, one byte for R, G and B.
+ */
+#define PIPEA_GMCH_DATA_M			0x70050
+#define PIPEB_GMCH_DATA_M			0x71050
+
+/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
+#define   PIPE_GMCH_DATA_M_TU_SIZE_MASK		(0x3f << 25)
+#define   PIPE_GMCH_DATA_M_TU_SIZE_SHIFT	25
+
+#define   PIPE_GMCH_DATA_M_MASK			(0xffffff)
+
+#define PIPEA_GMCH_DATA_N			0x70054
+#define PIPEB_GMCH_DATA_N			0x71054
+#define   PIPE_GMCH_DATA_N_MASK			(0xffffff)
+
+/*
+ * Computing Link M and N values for the Display Port link
+ *
+ * Link M / N = pixel_clock / ls_clk
+ *
+ * (the DP spec calls pixel_clock the 'strm_clk')
+ *
+ * The Link value is transmitted in the Main Stream
+ * Attributes and VB-ID.
+ */
+
+#define PIPEA_DP_LINK_M				0x70060
+#define PIPEB_DP_LINK_M				0x71060
+#define   PIPEA_DP_LINK_M_MASK			(0xffffff)
+
+#define PIPEA_DP_LINK_N				0x70064
+#define PIPEB_DP_LINK_N				0x71064
+#define   PIPEA_DP_LINK_N_MASK			(0xffffff)
+
 /* Display & cursor control */
 
 /* Pipe A */
@@ -1382,6 +1622,34 @@
 #define   DSPARB_CSTART_SHIFT	7
 #define   DSPARB_BSTART_MASK	(0x7f)
 #define   DSPARB_BSTART_SHIFT	0
+#define   DSPARB_BEND_SHIFT	9 /* on 855 */
+#define   DSPARB_AEND_SHIFT	0
+
+#define DSPFW1			0x70034
+#define DSPFW2			0x70038
+#define DSPFW3			0x7003c
+#define   IGD_SELF_REFRESH_EN	(1<<30)
+
+/* FIFO watermark sizes etc */
+#define I915_FIFO_LINE_SIZE	64
+#define I830_FIFO_LINE_SIZE	32
+#define I945_FIFO_SIZE		127 /* 945 & 965 */
+#define I915_FIFO_SIZE		95
+#define I855GM_FIFO_SIZE	127 /* In cachelines */
+#define I830_FIFO_SIZE		95
+#define I915_MAX_WM		0x3f
+
+#define IGD_DISPLAY_FIFO	512 /* in 64byte unit */
+#define IGD_FIFO_LINE_SIZE	64
+#define IGD_MAX_WM		0x1ff
+#define IGD_DFT_WM		0x3f
+#define IGD_DFT_HPLLOFF_WM	0
+#define IGD_GUARD_WM		10
+#define IGD_CURSOR_FIFO		64
+#define IGD_CURSOR_MAX_WM	0x3f
+#define IGD_CURSOR_DFT_WM	0
+#define IGD_CURSOR_GUARD_WM	5
+
 /*
  * The two pipe frame counter registers are not synchronized, so
  * reading a stable value is somewhat tricky. The following code
@@ -1517,4 +1785,470 @@
 # define VGA_2X_MODE				(1 << 30)
 # define VGA_PIPE_B_SELECT			(1 << 29)
 
+/* IGDNG */
+
+#define CPU_VGACNTRL	0x41000
+
+#define DIGITAL_PORT_HOTPLUG_CNTRL      0x44030
+#define  DIGITAL_PORTA_HOTPLUG_ENABLE           (1 << 4)
+#define  DIGITAL_PORTA_SHORT_PULSE_2MS          (0 << 2)
+#define  DIGITAL_PORTA_SHORT_PULSE_4_5MS        (1 << 2)
+#define  DIGITAL_PORTA_SHORT_PULSE_6MS          (2 << 2)
+#define  DIGITAL_PORTA_SHORT_PULSE_100MS        (3 << 2)
+#define  DIGITAL_PORTA_NO_DETECT                (0 << 0)
+#define  DIGITAL_PORTA_LONG_PULSE_DETECT_MASK   (1 << 1)
+#define  DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK  (1 << 0)
+
+/* refresh rate hardware control */
+#define RR_HW_CTL       0x45300
+#define  RR_HW_LOW_POWER_FRAMES_MASK    0xff
+#define  RR_HW_HIGH_POWER_FRAMES_MASK   0xff00
+
+#define FDI_PLL_BIOS_0  0x46000
+#define FDI_PLL_BIOS_1  0x46004
+#define FDI_PLL_BIOS_2  0x46008
+#define DISPLAY_PORT_PLL_BIOS_0         0x4600c
+#define DISPLAY_PORT_PLL_BIOS_1         0x46010
+#define DISPLAY_PORT_PLL_BIOS_2         0x46014
+
+#define FDI_PLL_FREQ_CTL        0x46030
+#define  FDI_PLL_FREQ_CHANGE_REQUEST    (1<<24)
+#define  FDI_PLL_FREQ_LOCK_LIMIT_MASK   0xfff00
+#define  FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK  0xff
+
+
+#define PIPEA_DATA_M1           0x60030
+#define  TU_SIZE(x)             (((x)-1) << 25) /* default size 64 */
+#define  TU_SIZE_MASK           0x7e000000
+#define  PIPEA_DATA_M1_OFFSET   0
+#define PIPEA_DATA_N1           0x60034
+#define  PIPEA_DATA_N1_OFFSET   0
+
+#define PIPEA_DATA_M2           0x60038
+#define  PIPEA_DATA_M2_OFFSET   0
+#define PIPEA_DATA_N2           0x6003c
+#define  PIPEA_DATA_N2_OFFSET   0
+
+#define PIPEA_LINK_M1           0x60040
+#define  PIPEA_LINK_M1_OFFSET   0
+#define PIPEA_LINK_N1           0x60044
+#define  PIPEA_LINK_N1_OFFSET   0
+
+#define PIPEA_LINK_M2           0x60048
+#define  PIPEA_LINK_M2_OFFSET   0
+#define PIPEA_LINK_N2           0x6004c
+#define  PIPEA_LINK_N2_OFFSET   0
+
+/* PIPEB timing regs are same start from 0x61000 */
+
+#define PIPEB_DATA_M1           0x61030
+#define  PIPEB_DATA_M1_OFFSET   0
+#define PIPEB_DATA_N1           0x61034
+#define  PIPEB_DATA_N1_OFFSET   0
+
+#define PIPEB_DATA_M2           0x61038
+#define  PIPEB_DATA_M2_OFFSET   0
+#define PIPEB_DATA_N2           0x6103c
+#define  PIPEB_DATA_N2_OFFSET   0
+
+#define PIPEB_LINK_M1           0x61040
+#define  PIPEB_LINK_M1_OFFSET   0
+#define PIPEB_LINK_N1           0x61044
+#define  PIPEB_LINK_N1_OFFSET   0
+
+#define PIPEB_LINK_M2           0x61048
+#define  PIPEB_LINK_M2_OFFSET   0
+#define PIPEB_LINK_N2           0x6104c
+#define  PIPEB_LINK_N2_OFFSET   0
+
+/* CPU panel fitter */
+#define PFA_CTL_1               0x68080
+#define PFB_CTL_1               0x68880
+#define  PF_ENABLE              (1<<31)
+#define PFA_WIN_SZ		0x68074
+#define PFB_WIN_SZ		0x68874
+
+/* legacy palette */
+#define LGC_PALETTE_A           0x4a000
+#define LGC_PALETTE_B           0x4a800
+
+/* interrupts */
+#define DE_MASTER_IRQ_CONTROL   (1 << 31)
+#define DE_SPRITEB_FLIP_DONE    (1 << 29)
+#define DE_SPRITEA_FLIP_DONE    (1 << 28)
+#define DE_PLANEB_FLIP_DONE     (1 << 27)
+#define DE_PLANEA_FLIP_DONE     (1 << 26)
+#define DE_PCU_EVENT            (1 << 25)
+#define DE_GTT_FAULT            (1 << 24)
+#define DE_POISON               (1 << 23)
+#define DE_PERFORM_COUNTER      (1 << 22)
+#define DE_PCH_EVENT            (1 << 21)
+#define DE_AUX_CHANNEL_A        (1 << 20)
+#define DE_DP_A_HOTPLUG         (1 << 19)
+#define DE_GSE                  (1 << 18)
+#define DE_PIPEB_VBLANK         (1 << 15)
+#define DE_PIPEB_EVEN_FIELD     (1 << 14)
+#define DE_PIPEB_ODD_FIELD      (1 << 13)
+#define DE_PIPEB_LINE_COMPARE   (1 << 12)
+#define DE_PIPEB_VSYNC          (1 << 11)
+#define DE_PIPEB_FIFO_UNDERRUN  (1 << 8)
+#define DE_PIPEA_VBLANK         (1 << 7)
+#define DE_PIPEA_EVEN_FIELD     (1 << 6)
+#define DE_PIPEA_ODD_FIELD      (1 << 5)
+#define DE_PIPEA_LINE_COMPARE   (1 << 4)
+#define DE_PIPEA_VSYNC          (1 << 3)
+#define DE_PIPEA_FIFO_UNDERRUN  (1 << 0)
+
+#define DEISR   0x44000
+#define DEIMR   0x44004
+#define DEIIR   0x44008
+#define DEIER   0x4400c
+
+/* GT interrupt */
+#define GT_SYNC_STATUS          (1 << 2)
+#define GT_USER_INTERRUPT       (1 << 0)
+
+#define GTISR   0x44010
+#define GTIMR   0x44014
+#define GTIIR   0x44018
+#define GTIER   0x4401c
+
+/* PCH */
+
+/* south display engine interrupt */
+#define SDE_CRT_HOTPLUG         (1 << 11)
+#define SDE_PORTD_HOTPLUG       (1 << 10)
+#define SDE_PORTC_HOTPLUG       (1 << 9)
+#define SDE_PORTB_HOTPLUG       (1 << 8)
+#define SDE_SDVOB_HOTPLUG       (1 << 6)
+
+#define SDEISR  0xc4000
+#define SDEIMR  0xc4004
+#define SDEIIR  0xc4008
+#define SDEIER  0xc400c
+
+/* digital port hotplug */
+#define PCH_PORT_HOTPLUG        0xc4030
+#define PORTD_HOTPLUG_ENABLE            (1 << 20)
+#define PORTD_PULSE_DURATION_2ms        (0)
+#define PORTD_PULSE_DURATION_4_5ms      (1 << 18)
+#define PORTD_PULSE_DURATION_6ms        (2 << 18)
+#define PORTD_PULSE_DURATION_100ms      (3 << 18)
+#define PORTD_HOTPLUG_NO_DETECT         (0)
+#define PORTD_HOTPLUG_SHORT_DETECT      (1 << 16)
+#define PORTD_HOTPLUG_LONG_DETECT       (1 << 17)
+#define PORTC_HOTPLUG_ENABLE            (1 << 12)
+#define PORTC_PULSE_DURATION_2ms        (0)
+#define PORTC_PULSE_DURATION_4_5ms      (1 << 10)
+#define PORTC_PULSE_DURATION_6ms        (2 << 10)
+#define PORTC_PULSE_DURATION_100ms      (3 << 10)
+#define PORTC_HOTPLUG_NO_DETECT         (0)
+#define PORTC_HOTPLUG_SHORT_DETECT      (1 << 8)
+#define PORTC_HOTPLUG_LONG_DETECT       (1 << 9)
+#define PORTB_HOTPLUG_ENABLE            (1 << 4)
+#define PORTB_PULSE_DURATION_2ms        (0)
+#define PORTB_PULSE_DURATION_4_5ms      (1 << 2)
+#define PORTB_PULSE_DURATION_6ms        (2 << 2)
+#define PORTB_PULSE_DURATION_100ms      (3 << 2)
+#define PORTB_HOTPLUG_NO_DETECT         (0)
+#define PORTB_HOTPLUG_SHORT_DETECT      (1 << 0)
+#define PORTB_HOTPLUG_LONG_DETECT       (1 << 1)
+
+#define PCH_GPIOA               0xc5010
+#define PCH_GPIOB               0xc5014
+#define PCH_GPIOC               0xc5018
+#define PCH_GPIOD               0xc501c
+#define PCH_GPIOE               0xc5020
+#define PCH_GPIOF               0xc5024
+
+#define PCH_DPLL_A              0xc6014
+#define PCH_DPLL_B              0xc6018
+
+#define PCH_FPA0                0xc6040
+#define PCH_FPA1                0xc6044
+#define PCH_FPB0                0xc6048
+#define PCH_FPB1                0xc604c
+
+#define PCH_DPLL_TEST           0xc606c
+
+#define PCH_DREF_CONTROL        0xC6200
+#define  DREF_CONTROL_MASK      0x7fc3
+#define  DREF_CPU_SOURCE_OUTPUT_DISABLE         (0<<13)
+#define  DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD      (2<<13)
+#define  DREF_CPU_SOURCE_OUTPUT_NONSPREAD       (3<<13)
+#define  DREF_CPU_SOURCE_OUTPUT_MASK		(3<<13)
+#define  DREF_SSC_SOURCE_DISABLE                (0<<11)
+#define  DREF_SSC_SOURCE_ENABLE                 (2<<11)
+#define  DREF_SSC_SOURCE_MASK			(2<<11)
+#define  DREF_NONSPREAD_SOURCE_DISABLE          (0<<9)
+#define  DREF_NONSPREAD_CK505_ENABLE		(1<<9)
+#define  DREF_NONSPREAD_SOURCE_ENABLE           (2<<9)
+#define  DREF_NONSPREAD_SOURCE_MASK		(2<<9)
+#define  DREF_SUPERSPREAD_SOURCE_DISABLE        (0<<7)
+#define  DREF_SUPERSPREAD_SOURCE_ENABLE         (2<<7)
+#define  DREF_SSC4_DOWNSPREAD                   (0<<6)
+#define  DREF_SSC4_CENTERSPREAD                 (1<<6)
+#define  DREF_SSC1_DISABLE                      (0<<1)
+#define  DREF_SSC1_ENABLE                       (1<<1)
+#define  DREF_SSC4_DISABLE                      (0)
+#define  DREF_SSC4_ENABLE                       (1)
+
+#define PCH_RAWCLK_FREQ         0xc6204
+#define  FDL_TP1_TIMER_SHIFT    12
+#define  FDL_TP1_TIMER_MASK     (3<<12)
+#define  FDL_TP2_TIMER_SHIFT    10
+#define  FDL_TP2_TIMER_MASK     (3<<10)
+#define  RAWCLK_FREQ_MASK       0x3ff
+
+#define PCH_DPLL_TMR_CFG        0xc6208
+
+#define PCH_SSC4_PARMS          0xc6210
+#define PCH_SSC4_AUX_PARMS      0xc6214
+
+/* transcoder */
+
+#define TRANS_HTOTAL_A          0xe0000
+#define  TRANS_HTOTAL_SHIFT     16
+#define  TRANS_HACTIVE_SHIFT    0
+#define TRANS_HBLANK_A          0xe0004
+#define  TRANS_HBLANK_END_SHIFT 16
+#define  TRANS_HBLANK_START_SHIFT 0
+#define TRANS_HSYNC_A           0xe0008
+#define  TRANS_HSYNC_END_SHIFT  16
+#define  TRANS_HSYNC_START_SHIFT 0
+#define TRANS_VTOTAL_A          0xe000c
+#define  TRANS_VTOTAL_SHIFT     16
+#define  TRANS_VACTIVE_SHIFT    0
+#define TRANS_VBLANK_A          0xe0010
+#define  TRANS_VBLANK_END_SHIFT 16
+#define  TRANS_VBLANK_START_SHIFT 0
+#define TRANS_VSYNC_A           0xe0014
+#define  TRANS_VSYNC_END_SHIFT  16
+#define  TRANS_VSYNC_START_SHIFT 0
+
+#define TRANSA_DATA_M1          0xe0030
+#define TRANSA_DATA_N1          0xe0034
+#define TRANSA_DATA_M2          0xe0038
+#define TRANSA_DATA_N2          0xe003c
+#define TRANSA_DP_LINK_M1       0xe0040
+#define TRANSA_DP_LINK_N1       0xe0044
+#define TRANSA_DP_LINK_M2       0xe0048
+#define TRANSA_DP_LINK_N2       0xe004c
+
+#define TRANS_HTOTAL_B          0xe1000
+#define TRANS_HBLANK_B          0xe1004
+#define TRANS_HSYNC_B           0xe1008
+#define TRANS_VTOTAL_B          0xe100c
+#define TRANS_VBLANK_B          0xe1010
+#define TRANS_VSYNC_B           0xe1014
+
+#define TRANSB_DATA_M1          0xe1030
+#define TRANSB_DATA_N1          0xe1034
+#define TRANSB_DATA_M2          0xe1038
+#define TRANSB_DATA_N2          0xe103c
+#define TRANSB_DP_LINK_M1       0xe1040
+#define TRANSB_DP_LINK_N1       0xe1044
+#define TRANSB_DP_LINK_M2       0xe1048
+#define TRANSB_DP_LINK_N2       0xe104c
+
+#define TRANSACONF              0xf0008
+#define TRANSBCONF              0xf1008
+#define  TRANS_DISABLE          (0<<31)
+#define  TRANS_ENABLE           (1<<31)
+#define  TRANS_STATE_MASK       (1<<30)
+#define  TRANS_STATE_DISABLE    (0<<30)
+#define  TRANS_STATE_ENABLE     (1<<30)
+#define  TRANS_FSYNC_DELAY_HB1  (0<<27)
+#define  TRANS_FSYNC_DELAY_HB2  (1<<27)
+#define  TRANS_FSYNC_DELAY_HB3  (2<<27)
+#define  TRANS_FSYNC_DELAY_HB4  (3<<27)
+#define  TRANS_DP_AUDIO_ONLY    (1<<26)
+#define  TRANS_DP_VIDEO_AUDIO   (0<<26)
+#define  TRANS_PROGRESSIVE      (0<<21)
+#define  TRANS_8BPC             (0<<5)
+#define  TRANS_10BPC            (1<<5)
+#define  TRANS_6BPC             (2<<5)
+#define  TRANS_12BPC            (3<<5)
+
+#define FDI_RXA_CHICKEN         0xc200c
+#define FDI_RXB_CHICKEN         0xc2010
+#define  FDI_RX_PHASE_SYNC_POINTER_ENABLE       (1)
+
+/* CPU: FDI_TX */
+#define FDI_TXA_CTL             0x60100
+#define FDI_TXB_CTL             0x61100
+#define  FDI_TX_DISABLE         (0<<31)
+#define  FDI_TX_ENABLE          (1<<31)
+#define  FDI_LINK_TRAIN_PATTERN_1       (0<<28)
+#define  FDI_LINK_TRAIN_PATTERN_2       (1<<28)
+#define  FDI_LINK_TRAIN_PATTERN_IDLE    (2<<28)
+#define  FDI_LINK_TRAIN_NONE            (3<<28)
+#define  FDI_LINK_TRAIN_VOLTAGE_0_4V    (0<<25)
+#define  FDI_LINK_TRAIN_VOLTAGE_0_6V    (1<<25)
+#define  FDI_LINK_TRAIN_VOLTAGE_0_8V    (2<<25)
+#define  FDI_LINK_TRAIN_VOLTAGE_1_2V    (3<<25)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0<<22)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1<<22)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_2X   (2<<22)
+#define  FDI_LINK_TRAIN_PRE_EMPHASIS_3X   (3<<22)
+#define  FDI_DP_PORT_WIDTH_X1           (0<<19)
+#define  FDI_DP_PORT_WIDTH_X2           (1<<19)
+#define  FDI_DP_PORT_WIDTH_X3           (2<<19)
+#define  FDI_DP_PORT_WIDTH_X4           (3<<19)
+#define  FDI_TX_ENHANCE_FRAME_ENABLE    (1<<18)
+/* IGDNG: hardwired to 1 */
+#define  FDI_TX_PLL_ENABLE              (1<<14)
+/* both Tx and Rx */
+#define  FDI_SCRAMBLING_ENABLE          (0<<7)
+#define  FDI_SCRAMBLING_DISABLE         (1<<7)
+
+/* FDI_RX, FDI_X is hard-wired to Transcoder_X */
+#define FDI_RXA_CTL             0xf000c
+#define FDI_RXB_CTL             0xf100c
+#define  FDI_RX_ENABLE          (1<<31)
+#define  FDI_RX_DISABLE         (0<<31)
+/* train, dp width same as FDI_TX */
+#define  FDI_DP_PORT_WIDTH_X8           (7<<19)
+#define  FDI_8BPC                       (0<<16)
+#define  FDI_10BPC                      (1<<16)
+#define  FDI_6BPC                       (2<<16)
+#define  FDI_12BPC                      (3<<16)
+#define  FDI_LINK_REVERSE_OVERWRITE     (1<<15)
+#define  FDI_DMI_LINK_REVERSE_MASK      (1<<14)
+#define  FDI_RX_PLL_ENABLE              (1<<13)
+#define  FDI_FS_ERR_CORRECT_ENABLE      (1<<11)
+#define  FDI_FE_ERR_CORRECT_ENABLE      (1<<10)
+#define  FDI_FS_ERR_REPORT_ENABLE       (1<<9)
+#define  FDI_FE_ERR_REPORT_ENABLE       (1<<8)
+#define  FDI_RX_ENHANCE_FRAME_ENABLE    (1<<6)
+#define  FDI_SEL_RAWCLK                 (0<<4)
+#define  FDI_SEL_PCDCLK                 (1<<4)
+
+#define FDI_RXA_MISC            0xf0010
+#define FDI_RXB_MISC            0xf1010
+#define FDI_RXA_TUSIZE1         0xf0030
+#define FDI_RXA_TUSIZE2         0xf0038
+#define FDI_RXB_TUSIZE1         0xf1030
+#define FDI_RXB_TUSIZE2         0xf1038
+
+/* FDI_RX interrupt register format */
+#define FDI_RX_INTER_LANE_ALIGN         (1<<10)
+#define FDI_RX_SYMBOL_LOCK              (1<<9) /* train 2 */
+#define FDI_RX_BIT_LOCK                 (1<<8) /* train 1 */
+#define FDI_RX_TRAIN_PATTERN_2_FAIL     (1<<7)
+#define FDI_RX_FS_CODE_ERR              (1<<6)
+#define FDI_RX_FE_CODE_ERR              (1<<5)
+#define FDI_RX_SYMBOL_ERR_RATE_ABOVE    (1<<4)
+#define FDI_RX_HDCP_LINK_FAIL           (1<<3)
+#define FDI_RX_PIXEL_FIFO_OVERFLOW      (1<<2)
+#define FDI_RX_CROSS_CLOCK_OVERFLOW     (1<<1)
+#define FDI_RX_SYMBOL_QUEUE_OVERFLOW    (1<<0)
+
+#define FDI_RXA_IIR             0xf0014
+#define FDI_RXA_IMR             0xf0018
+#define FDI_RXB_IIR             0xf1014
+#define FDI_RXB_IMR             0xf1018
+
+#define FDI_PLL_CTL_1           0xfe000
+#define FDI_PLL_CTL_2           0xfe004
+
+/* CRT */
+#define PCH_ADPA                0xe1100
+#define  ADPA_TRANS_SELECT_MASK (1<<30)
+#define  ADPA_TRANS_A_SELECT    0
+#define  ADPA_TRANS_B_SELECT    (1<<30)
+#define  ADPA_CRT_HOTPLUG_MASK  0x03ff0000 /* bit 25-16 */
+#define  ADPA_CRT_HOTPLUG_MONITOR_NONE  (0<<24)
+#define  ADPA_CRT_HOTPLUG_MONITOR_MASK  (3<<24)
+#define  ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
+#define  ADPA_CRT_HOTPLUG_MONITOR_MONO  (2<<24)
+#define  ADPA_CRT_HOTPLUG_ENABLE        (1<<23)
+#define  ADPA_CRT_HOTPLUG_PERIOD_64     (0<<22)
+#define  ADPA_CRT_HOTPLUG_PERIOD_128    (1<<22)
+#define  ADPA_CRT_HOTPLUG_WARMUP_5MS    (0<<21)
+#define  ADPA_CRT_HOTPLUG_WARMUP_10MS   (1<<21)
+#define  ADPA_CRT_HOTPLUG_SAMPLE_2S     (0<<20)
+#define  ADPA_CRT_HOTPLUG_SAMPLE_4S     (1<<20)
+#define  ADPA_CRT_HOTPLUG_VOLTAGE_40    (0<<18)
+#define  ADPA_CRT_HOTPLUG_VOLTAGE_50    (1<<18)
+#define  ADPA_CRT_HOTPLUG_VOLTAGE_60    (2<<18)
+#define  ADPA_CRT_HOTPLUG_VOLTAGE_70    (3<<18)
+#define  ADPA_CRT_HOTPLUG_VOLREF_325MV  (0<<17)
+#define  ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
+#define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
+
+/* or SDVOB */
+#define HDMIB   0xe1140
+#define  PORT_ENABLE    (1 << 31)
+#define  TRANSCODER_A   (0)
+#define  TRANSCODER_B   (1 << 30)
+#define  COLOR_FORMAT_8bpc      (0)
+#define  COLOR_FORMAT_12bpc     (3 << 26)
+#define  SDVOB_HOTPLUG_ENABLE   (1 << 23)
+#define  SDVO_ENCODING          (0)
+#define  TMDS_ENCODING          (2 << 10)
+#define  NULL_PACKET_VSYNC_ENABLE       (1 << 9)
+#define  SDVOB_BORDER_ENABLE    (1 << 7)
+#define  AUDIO_ENABLE           (1 << 6)
+#define  VSYNC_ACTIVE_HIGH      (1 << 4)
+#define  HSYNC_ACTIVE_HIGH      (1 << 3)
+#define  PORT_DETECTED          (1 << 2)
+
+#define HDMIC   0xe1150
+#define HDMID   0xe1160
+
+#define PCH_LVDS	0xe1180
+#define  LVDS_DETECTED	(1 << 1)
+
+#define BLC_PWM_CPU_CTL2	0x48250
+#define  PWM_ENABLE		(1 << 31)
+#define  PWM_PIPE_A		(0 << 29)
+#define  PWM_PIPE_B		(1 << 29)
+#define BLC_PWM_CPU_CTL		0x48254
+
+#define BLC_PWM_PCH_CTL1	0xc8250
+#define  PWM_PCH_ENABLE		(1 << 31)
+#define  PWM_POLARITY_ACTIVE_LOW	(1 << 29)
+#define  PWM_POLARITY_ACTIVE_HIGH	(0 << 29)
+#define  PWM_POLARITY_ACTIVE_LOW2	(1 << 28)
+#define  PWM_POLARITY_ACTIVE_HIGH2	(0 << 28)
+
+#define BLC_PWM_PCH_CTL2	0xc8254
+
+#define PCH_PP_STATUS		0xc7200
+#define PCH_PP_CONTROL		0xc7204
+#define  EDP_FORCE_VDD		(1 << 3)
+#define  EDP_BLC_ENABLE		(1 << 2)
+#define  PANEL_POWER_RESET	(1 << 1)
+#define  PANEL_POWER_OFF	(0 << 0)
+#define  PANEL_POWER_ON		(1 << 0)
+#define PCH_PP_ON_DELAYS	0xc7208
+#define  EDP_PANEL		(1 << 30)
+#define PCH_PP_OFF_DELAYS	0xc720c
+#define PCH_PP_DIVISOR		0xc7210
+
+#define PCH_DP_B		0xe4100
+#define PCH_DPB_AUX_CH_CTL	0xe4110
+#define PCH_DPB_AUX_CH_DATA1	0xe4114
+#define PCH_DPB_AUX_CH_DATA2	0xe4118
+#define PCH_DPB_AUX_CH_DATA3	0xe411c
+#define PCH_DPB_AUX_CH_DATA4	0xe4120
+#define PCH_DPB_AUX_CH_DATA5	0xe4124
+
+#define PCH_DP_C		0xe4200
+#define PCH_DPC_AUX_CH_CTL	0xe4210
+#define PCH_DPC_AUX_CH_DATA1	0xe4214
+#define PCH_DPC_AUX_CH_DATA2	0xe4218
+#define PCH_DPC_AUX_CH_DATA3	0xe421c
+#define PCH_DPC_AUX_CH_DATA4	0xe4220
+#define PCH_DPC_AUX_CH_DATA5	0xe4224
+
+#define PCH_DP_D		0xe4300
+#define PCH_DPD_AUX_CH_CTL	0xe4310
+#define PCH_DPD_AUX_CH_DATA1	0xe4314
+#define PCH_DPD_AUX_CH_DATA2	0xe4318
+#define PCH_DPD_AUX_CH_DATA3	0xe431c
+#define PCH_DPD_AUX_CH_DATA4	0xe4320
+#define PCH_DPD_AUX_CH_DATA5	0xe4324
+
 #endif /* _I915_REG_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_suspend.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_suspend.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/i915_suspend.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/i915_suspend.c	2009-09-09 18:13:59.000000000 -0400
@@ -222,23 +222,12 @@
 	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
 }
 
-int i915_save_state(struct drm_device *dev)
+static void i915_save_modeset_reg(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
-
-	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
-
-	/* Render Standby */
-	if (IS_I965G(dev) && IS_MOBILE(dev))
-		dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
-
-	/* Hardware status page */
-	dev_priv->saveHWS = I915_READ(HWS_PGA);
-
-	/* Display arbitration control */
-	dev_priv->saveDSPARB = I915_READ(DSPARB);
 
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
 	/* Pipe & plane A info */
 	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
 	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
@@ -294,6 +283,131 @@
 	}
 	i915_save_palette(dev, PIPE_B);
 	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+	return;
+}
+static void i915_restore_modeset_reg(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
+
+	/* Pipe & plane A info */
+	/* Prime the clock */
+	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+			   ~DPLL_VCO_ENABLE);
+		DRM_UDELAY(150);
+	}
+	I915_WRITE(FPA0, dev_priv->saveFPA0);
+	I915_WRITE(FPA1, dev_priv->saveFPA1);
+	/* Actually enable it */
+	I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+	DRM_UDELAY(150);
+	if (IS_I965G(dev))
+		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+	DRM_UDELAY(150);
+
+	/* Restore mode */
+	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+	I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+	/* Restore plane info */
+	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+	I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
+	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+	if (IS_I965G(dev)) {
+		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+	}
+
+	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+	i915_restore_palette(dev, PIPE_A);
+	/* Enable the plane */
+	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+	I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
+
+	/* Pipe & plane B info */
+	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+			   ~DPLL_VCO_ENABLE);
+		DRM_UDELAY(150);
+	}
+	I915_WRITE(FPB0, dev_priv->saveFPB0);
+	I915_WRITE(FPB1, dev_priv->saveFPB1);
+	/* Actually enable it */
+	I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+	DRM_UDELAY(150);
+	if (IS_I965G(dev))
+		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+	DRM_UDELAY(150);
+
+	/* Restore mode */
+	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+	I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+	/* Restore plane info */
+	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+	I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
+	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+	if (IS_I965G(dev)) {
+		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+	}
+
+	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+	i915_restore_palette(dev, PIPE_B);
+	/* Enable the plane */
+	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+	I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
+
+	return;
+}
+int i915_save_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+
+	/* Render Standby */
+	if (IS_I965G(dev) && IS_MOBILE(dev))
+		dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
+
+	/* Hardware status page */
+	dev_priv->saveHWS = I915_READ(HWS_PGA);
+
+	/* Display arbitration control */
+	dev_priv->saveDSPARB = I915_READ(DSPARB);
+
+	/* This is only meaningful in non-KMS mode */
+	/* Don't save them in KMS mode */
+	i915_save_modeset_reg(dev);
+	/* Cursor state */
+	dev_priv->saveCURACNTR = I915_READ(CURACNTR);
+	dev_priv->saveCURAPOS = I915_READ(CURAPOS);
+	dev_priv->saveCURABASE = I915_READ(CURABASE);
+	dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
+	dev_priv->saveCURBPOS = I915_READ(CURBPOS);
+	dev_priv->saveCURBBASE = I915_READ(CURBBASE);
+	if (!IS_I9XX(dev))
+		dev_priv->saveCURSIZE = I915_READ(CURSIZE);
 
 	/* CRT state */
 	dev_priv->saveADPA = I915_READ(ADPA);
@@ -312,6 +426,20 @@
 	dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
 	dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
 
+	/* Display Port state */
+	if (SUPPORTS_INTEGRATED_DP(dev)) {
+		dev_priv->saveDP_B = I915_READ(DP_B);
+		dev_priv->saveDP_C = I915_READ(DP_C);
+		dev_priv->saveDP_D = I915_READ(DP_D);
+		dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M);
+		dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M);
+		dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N);
+		dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N);
+		dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M);
+		dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M);
+		dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N);
+		dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N);
+	}
 	/* FIXME: save TV & SDVO state */
 
 	/* FBC state */
@@ -394,91 +522,30 @@
 			for (i = 0; i < 8; i++)
 				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
 	}
-
-	/* Pipe & plane A info */
-	/* Prime the clock */
-	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
-		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
-			   ~DPLL_VCO_ENABLE);
-		DRM_UDELAY(150);
-	}
-	I915_WRITE(FPA0, dev_priv->saveFPA0);
-	I915_WRITE(FPA1, dev_priv->saveFPA1);
-	/* Actually enable it */
-	I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
-	DRM_UDELAY(150);
-	if (IS_I965G(dev))
-		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
-	DRM_UDELAY(150);
-
-	/* Restore mode */
-	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
-	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
-	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
-	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
-	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
-	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
-	I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
-
-	/* Restore plane info */
-	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
-	I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
-	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
-	if (IS_I965G(dev)) {
-		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
-	}
-
-	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
-
-	i915_restore_palette(dev, PIPE_A);
-	/* Enable the plane */
-	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
-	I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
-
-	/* Pipe & plane B info */
-	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
-			   ~DPLL_VCO_ENABLE);
-		DRM_UDELAY(150);
-	}
-	I915_WRITE(FPB0, dev_priv->saveFPB0);
-	I915_WRITE(FPB1, dev_priv->saveFPB1);
-	/* Actually enable it */
-	I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
-	DRM_UDELAY(150);
-	if (IS_I965G(dev))
-		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
-	DRM_UDELAY(150);
-
-	/* Restore mode */
-	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
-	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
-	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
-	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
-	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
-	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
-	I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
-
-	/* Restore plane info */
-	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
-	I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
-	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
-	if (IS_I965G(dev)) {
-		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+	
+	/* Display port ratios (must be done before clock is set) */
+	if (SUPPORTS_INTEGRATED_DP(dev)) {
+		I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M);
+		I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M);
+		I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N);
+		I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N);
+		I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M);
+		I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M);
+		I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N);
+		I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N);
 	}
-
-	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
-
-	i915_restore_palette(dev, PIPE_B);
-	/* Enable the plane */
-	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
-	I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
+	/* This is only meaningful in non-KMS mode */
+	/* Don't restore them in KMS mode */
+	i915_restore_modeset_reg(dev);
+	/* Cursor state */
+	I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
+	I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
+	I915_WRITE(CURABASE, dev_priv->saveCURABASE);
+	I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
+	I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
+	I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
+	if (!IS_I9XX(dev))
+		I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
 
 	/* CRT state */
 	I915_WRITE(ADPA, dev_priv->saveADPA);
@@ -498,6 +565,12 @@
 	I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
 	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
 
+	/* Display Port state */
+	if (SUPPORTS_INTEGRATED_DP(dev)) {
+		I915_WRITE(DP_B, dev_priv->saveDP_B);
+		I915_WRITE(DP_C, dev_priv->saveDP_C);
+		I915_WRITE(DP_D, dev_priv->saveDP_D);
+	}
 	/* FIXME: restore TV & SDVO state */
 
 	/* FBC info */
@@ -525,7 +598,7 @@
 
 	for (i = 0; i < 16; i++) {
 		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
-		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]);
 	}
 	for (i = 0; i < 3; i++)
 		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_bios.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_bios.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,8 @@
 #include "i915_drv.h"
 #include "intel_bios.h"
 
+#define	SLAVE_ADDR1	0x70
+#define	SLAVE_ADDR2	0x72
 
 static void *
 find_section(struct bdb_header *bdb, int section_id)
@@ -57,6 +59,16 @@
 	return NULL;
 }
 
+static u16
+get_blocksize(void *p)
+{
+	u16 *block_ptr, block_size;
+
+	block_ptr = (u16 *)((char *)p - 2);
+	block_size = *block_ptr;
+	return block_size;
+}
+
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
 			struct lvds_dvo_timing *dvo_timing)
@@ -97,9 +109,11 @@
 {
 	struct bdb_lvds_options *lvds_options;
 	struct bdb_lvds_lfp_data *lvds_lfp_data;
+	struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
 	struct bdb_lvds_lfp_data_entry *entry;
 	struct lvds_dvo_timing *dvo_timing;
 	struct drm_display_mode *panel_fixed_mode;
+	int lfp_data_size, dvo_timing_offset;
 
 	/* Defaults if we can't find VBT info */
 	dev_priv->lvds_dither = 0;
@@ -117,13 +131,29 @@
 	if (!lvds_lfp_data)
 		return;
 
+	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
+	if (!lvds_lfp_data_ptrs)
+		return;
+
 	dev_priv->lvds_vbt = 1;
 
-	entry = &lvds_lfp_data->data[lvds_options->panel_type];
-	dvo_timing = &entry->dvo_timing;
+	lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
+		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
+	entry = (struct bdb_lvds_lfp_data_entry *)
+		((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
+						   lvds_options->panel_type));
+	dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
+		lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
 
-	panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
-				      DRM_MEM_DRIVER);
+	/*
+	 * the size of fp_timing varies on the different platform.
+	 * So calculate the DVO timing relative offset in LVDS data
+	 * entry to get the DVO timing entry
+	 */
+	dvo_timing = (struct lvds_dvo_timing *)
+			((unsigned char *)entry + dvo_timing_offset);
+
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
 
 	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
 
@@ -154,8 +184,7 @@
 	if (!dvo_timing)
 		return;
 
-	panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
-				      DRM_MEM_DRIVER);
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
 
 	if (!panel_fixed_mode)
 		return;
@@ -185,14 +214,151 @@
 		dev_priv->lvds_use_ssc = general->enable_ssc;
 
 		if (dev_priv->lvds_use_ssc) {
-		  if (IS_I855(dev_priv->dev))
-		    dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
-		  else
-		    dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
+			if (IS_I85X(dev_priv->dev))
+				dev_priv->lvds_ssc_freq =
+					general->ssc_freq ? 66 : 48;
+			else
+				dev_priv->lvds_ssc_freq =
+					general->ssc_freq ? 100 : 96;
 		}
 	}
 }
 
+static void
+parse_general_definitions(struct drm_i915_private *dev_priv,
+			  struct bdb_header *bdb)
+{
+	struct bdb_general_definitions *general;
+	const int crt_bus_map_table[] = {
+		GPIOB,
+		GPIOA,
+		GPIOC,
+		GPIOD,
+		GPIOE,
+		GPIOF,
+	};
+
+	/* Set sensible defaults in case we can't find the general block
+	   or it is the wrong chipset */
+	dev_priv->crt_ddc_bus = -1;
+
+	general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	if (general) {
+		u16 block_size = get_blocksize(general);
+		if (block_size >= sizeof(*general)) {
+			int bus_pin = general->crt_ddc_gmbus_pin;
+			DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin);
+			if ((bus_pin >= 1) && (bus_pin <= 6)) {
+				dev_priv->crt_ddc_bus =
+					crt_bus_map_table[bus_pin-1];
+			}
+		} else {
+			DRM_DEBUG("BDB_GD too small (%d). Invalid.\n",
+				  block_size);
+		}
+	}
+}
+
+static void
+parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
+		       struct bdb_header *bdb)
+{
+	struct sdvo_device_mapping *p_mapping;
+	struct bdb_general_definitions *p_defs;
+	struct child_device_config *p_child;
+	int i, child_device_num, count;
+	u16	block_size;
+
+	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	if (!p_defs) {
+		DRM_DEBUG("No general definition block is found\n");
+		return;
+	}
+	/* judge whether the size of child device meets the requirements.
+	 * If the child device size obtained from general definition block
+	 * is different with sizeof(struct child_device_config), skip the
+	 * parsing of sdvo device info
+	 */
+	if (p_defs->child_dev_size != sizeof(*p_child)) {
+		/* different child dev size . Ignore it */
+		DRM_DEBUG("different child size is found. Invalid.\n");
+		return;
+	}
+	/* get the block size of general definitions */
+	block_size = get_blocksize(p_defs);
+	/* get the number of child device */
+	child_device_num = (block_size - sizeof(*p_defs)) /
+				sizeof(*p_child);
+	count = 0;
+	for (i = 0; i < child_device_num; i++) {
+		p_child = &(p_defs->devices[i]);
+		if (!p_child->device_type) {
+			/* skip the device block if device type is invalid */
+			continue;
+		}
+		if (p_child->slave_addr != SLAVE_ADDR1 &&
+			p_child->slave_addr != SLAVE_ADDR2) {
+			/*
+			 * If the slave address is neither 0x70 nor 0x72,
+			 * it is not a SDVO device. Skip it.
+			 */
+			continue;
+		}
+		if (p_child->dvo_port != DEVICE_PORT_DVOB &&
+			p_child->dvo_port != DEVICE_PORT_DVOC) {
+			/* skip the incorrect SDVO port */
+			DRM_DEBUG("Incorrect SDVO port. Skip it \n");
+			continue;
+		}
+		DRM_DEBUG("the SDVO device with slave addr %2x is found on "
+				"%s port\n",
+				p_child->slave_addr,
+				(p_child->dvo_port == DEVICE_PORT_DVOB) ?
+					"SDVOB" : "SDVOC");
+		p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
+		if (!p_mapping->initialized) {
+			p_mapping->dvo_port = p_child->dvo_port;
+			p_mapping->slave_addr = p_child->slave_addr;
+			p_mapping->dvo_wiring = p_child->dvo_wiring;
+			p_mapping->initialized = 1;
+		} else {
+			DRM_DEBUG("Maybe one SDVO port is shared by "
+					 "two SDVO device.\n");
+		}
+		if (p_child->slave2_addr) {
+			/* Maybe this is a SDVO device with multiple inputs */
+			/* And the mapping info is not added */
+			DRM_DEBUG("there exists the slave2_addr. Maybe this "
+				"is a SDVO device with multiple inputs.\n");
+		}
+		count++;
+	}
+
+	if (!count) {
+		/* No SDVO device info is found */
+		DRM_DEBUG("No SDVO device info is found in VBT\n");
+	}
+	return;
+}
+
+static void
+parse_driver_features(struct drm_i915_private *dev_priv,
+		       struct bdb_header *bdb)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct bdb_driver_features *driver;
+
+	/* set default for chips without eDP */
+	if (!SUPPORTS_EDP(dev)) {
+		dev_priv->edp_support = 0;
+		return;
+	}
+
+	driver = find_section(bdb, BDB_DRIVER_FEATURES);
+	if (driver && driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
+		dev_priv->edp_support = 1;
+}
+
 /**
  * intel_init_bios - initialize VBIOS settings & find VBT
  * @dev: DRM device
@@ -240,8 +406,11 @@
 
 	/* Grab useful general definitions */
 	parse_general_features(dev_priv, bdb);
+	parse_general_definitions(dev_priv, bdb);
 	parse_lfp_panel_data(dev_priv, bdb);
 	parse_sdvo_panel_data(dev_priv, bdb);
+	parse_sdvo_device_mapping(dev_priv, bdb);
+	parse_driver_features(dev_priv, bdb);
 
 	pci_unmap_rom(pdev, bios);
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_bios.h linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_bios.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_bios.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_bios.h	2009-09-09 18:13:59.000000000 -0400
@@ -135,6 +135,86 @@
 	u8 rsvd11:6; /* finish byte */
 } __attribute__((packed));
 
+/* pre-915 */
+#define GPIO_PIN_DVI_LVDS	0x03 /* "DVI/LVDS DDC GPIO pins" */
+#define GPIO_PIN_ADD_I2C	0x05 /* "ADDCARD I2C GPIO pins" */
+#define GPIO_PIN_ADD_DDC	0x04 /* "ADDCARD DDC GPIO pins" */
+#define GPIO_PIN_ADD_DDC_I2C	0x06 /* "ADDCARD DDC/I2C GPIO pins" */
+
+/* Pre 915 */
+#define DEVICE_TYPE_NONE	0x00
+#define DEVICE_TYPE_CRT		0x01
+#define DEVICE_TYPE_TV		0x09
+#define DEVICE_TYPE_EFP		0x12
+#define DEVICE_TYPE_LFP		0x22
+/* On 915+ */
+#define DEVICE_TYPE_CRT_DPMS		0x6001
+#define DEVICE_TYPE_CRT_DPMS_HOTPLUG	0x4001
+#define DEVICE_TYPE_TV_COMPOSITE	0x0209
+#define DEVICE_TYPE_TV_MACROVISION	0x0289
+#define DEVICE_TYPE_TV_RF_COMPOSITE	0x020c
+#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE	0x0609
+#define DEVICE_TYPE_TV_SCART		0x0209
+#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
+#define DEVICE_TYPE_EFP_HOTPLUG_PWR	0x6012
+#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR	0x6052
+#define DEVICE_TYPE_EFP_DVI_I		0x6053
+#define DEVICE_TYPE_EFP_DVI_D_DUAL	0x6152
+#define DEVICE_TYPE_EFP_DVI_D_HDCP	0x60d2
+#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR	0x6062
+#define DEVICE_TYPE_OPENLDI_DUALPIX	0x6162
+#define DEVICE_TYPE_LFP_PANELLINK	0x5012
+#define DEVICE_TYPE_LFP_CMOS_PWR	0x5042
+#define DEVICE_TYPE_LFP_LVDS_PWR	0x5062
+#define DEVICE_TYPE_LFP_LVDS_DUAL	0x5162
+#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP	0x51e2
+
+#define DEVICE_CFG_NONE		0x00
+#define DEVICE_CFG_12BIT_DVOB	0x01
+#define DEVICE_CFG_12BIT_DVOC	0x02
+#define DEVICE_CFG_24BIT_DVOBC	0x09
+#define DEVICE_CFG_24BIT_DVOCB	0x0a
+#define DEVICE_CFG_DUAL_DVOB	0x11
+#define DEVICE_CFG_DUAL_DVOC	0x12
+#define DEVICE_CFG_DUAL_DVOBC	0x13
+#define DEVICE_CFG_DUAL_LINK_DVOBC	0x19
+#define DEVICE_CFG_DUAL_LINK_DVOCB	0x1a
+
+#define DEVICE_WIRE_NONE	0x00
+#define DEVICE_WIRE_DVOB	0x01
+#define DEVICE_WIRE_DVOC	0x02
+#define DEVICE_WIRE_DVOBC	0x03
+#define DEVICE_WIRE_DVOBB	0x05
+#define DEVICE_WIRE_DVOCC	0x06
+#define DEVICE_WIRE_DVOB_MASTER 0x0d
+#define DEVICE_WIRE_DVOC_MASTER 0x0e
+
+#define DEVICE_PORT_DVOA	0x00 /* none on 845+ */
+#define DEVICE_PORT_DVOB	0x01
+#define DEVICE_PORT_DVOC	0x02
+
+struct child_device_config {
+	u16 handle;
+	u16 device_type;
+	u8  device_id[10]; /* See DEVICE_TYPE_* above */
+	u16 addin_offset;
+	u8  dvo_port; /* See Device_PORT_* above */
+	u8  i2c_pin;
+	u8  slave_addr;
+	u8  ddc_pin;
+	u16 edid_ptr;
+	u8  dvo_cfg; /* See DEVICE_CFG_* above */
+	u8  dvo2_port;
+	u8  i2c2_pin;
+	u8  slave2_addr;
+	u8  ddc2_pin;
+	u8  capabilities;
+	u8  dvo_wiring;/* See DEVICE_WIRE_* above */
+	u8  dvo2_wiring;
+	u16 extended_type;
+	u8  dvo_function;
+} __attribute__((packed));
+
 struct bdb_general_definitions {
 	/* DDC GPIO */
 	u8 crt_ddc_gmbus_pin;
@@ -149,14 +229,19 @@
 	u8 boot_display[2];
 	u8 child_dev_size;
 
-	/* device info */
-	u8 tv_or_lvds_info[33];
-	u8 dev1[33];
-	u8 dev2[33];
-	u8 dev3[33];
-	u8 dev4[33];
-	/* may be another device block here on some platforms */
-};
+	/*
+	 * Device info:
+	 * If TV is present, it'll be at devices[0].
+	 * LVDS will be next, either devices[0] or [1], if present.
+	 * On some platforms the number of device is 6. But could be as few as
+	 * 4 if both TV and LVDS are missing.
+	 * And the device num is related with the size of general definition
+	 * block. It is obtained by using the following formula:
+	 * number = (block_size - sizeof(bdb_general_definitions))/
+	 * 		sizeof(child_device_config);
+	 */
+	struct child_device_config devices[0];
+} __attribute__((packed));
 
 struct bdb_lvds_options {
 	u8 panel_type;
@@ -296,6 +381,51 @@
 } __attribute__((packed));
 
 
+#define BDB_DRIVER_FEATURE_NO_LVDS		0
+#define BDB_DRIVER_FEATURE_INT_LVDS		1
+#define BDB_DRIVER_FEATURE_SDVO_LVDS		2
+#define BDB_DRIVER_FEATURE_EDP			3
+
+struct bdb_driver_features {
+	u8 boot_dev_algorithm:1;
+	u8 block_display_switch:1;
+	u8 allow_display_switch:1;
+	u8 hotplug_dvo:1;
+	u8 dual_view_zoom:1;
+	u8 int15h_hook:1;
+	u8 sprite_in_clone:1;
+	u8 primary_lfp_id:1;
+
+	u16 boot_mode_x;
+	u16 boot_mode_y;
+	u8 boot_mode_bpp;
+	u8 boot_mode_refresh;
+
+	u16 enable_lfp_primary:1;
+	u16 selective_mode_pruning:1;
+	u16 dual_frequency:1;
+	u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
+	u16 nt_clone_support:1;
+	u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+	u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
+	u16 cui_aspect_scaling:1;
+	u16 preserve_aspect_ratio:1;
+	u16 sdvo_device_power_down:1;
+	u16 crt_hotplug:1;
+	u16 lvds_config:2;
+	u16 tv_hotplug:1;
+	u16 hdmi_config:2;
+
+	u8 static_display:1;
+	u8 reserved2:7;
+	u16 legacy_crt_max_x;
+	u16 legacy_crt_max_y;
+	u8 legacy_crt_max_refresh;
+
+	u8 hdmi_termination;
+	u8 custom_vbt_version;
+} __attribute__((packed));
+
 bool intel_init_bios(struct drm_device *dev);
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_crt.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_crt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_crt.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,11 +37,16 @@
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 temp;
+	u32 temp, reg;
 
-	temp = I915_READ(ADPA);
+	if (IS_IGDNG(dev))
+		reg = PCH_ADPA;
+	else
+		reg = ADPA;
+
+	temp = I915_READ(reg);
 	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-	temp |= ADPA_DAC_ENABLE;
+	temp &= ~ADPA_DAC_ENABLE;
 
 	switch(mode) {
 	case DRM_MODE_DPMS_ON:
@@ -58,7 +63,7 @@
 		break;
 	}
 
-	I915_WRITE(ADPA, temp);
+	I915_WRITE(reg, temp);
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -101,17 +106,23 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int dpll_md_reg;
 	u32 adpa, dpll_md;
+	u32 adpa_reg;
 
 	if (intel_crtc->pipe == 0)
 		dpll_md_reg = DPLL_A_MD;
 	else
 		dpll_md_reg = DPLL_B_MD;
 
+	if (IS_IGDNG(dev))
+		adpa_reg = PCH_ADPA;
+	else
+		adpa_reg = ADPA;
+
 	/*
 	 * Disable separate mode multiplier used when cloning SDVO to CRT
 	 * XXX this needs to be adjusted when we really are cloning
 	 */
-	if (IS_I965G(dev)) {
+	if (IS_I965G(dev) && !IS_IGDNG(dev)) {
 		dpll_md = I915_READ(dpll_md_reg);
 		I915_WRITE(dpll_md_reg,
 			   dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
@@ -125,13 +136,57 @@
 
 	if (intel_crtc->pipe == 0) {
 		adpa |= ADPA_PIPE_A_SELECT;
-		I915_WRITE(BCLRPAT_A, 0);
+		if (!IS_IGDNG(dev))
+			I915_WRITE(BCLRPAT_A, 0);
 	} else {
 		adpa |= ADPA_PIPE_B_SELECT;
-		I915_WRITE(BCLRPAT_B, 0);
+		if (!IS_IGDNG(dev))
+			I915_WRITE(BCLRPAT_B, 0);
 	}
 
-	I915_WRITE(ADPA, adpa);
+	I915_WRITE(adpa_reg, adpa);
+}
+
+static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 adpa, temp;
+	bool ret;
+
+	temp = adpa = I915_READ(PCH_ADPA);
+
+	adpa &= ~ADPA_DAC_ENABLE;
+	I915_WRITE(PCH_ADPA, adpa);
+
+	adpa &= ~ADPA_CRT_HOTPLUG_MASK;
+
+	adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
+			ADPA_CRT_HOTPLUG_WARMUP_10MS |
+			ADPA_CRT_HOTPLUG_SAMPLE_4S |
+			ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */
+			ADPA_CRT_HOTPLUG_VOLREF_325MV |
+			ADPA_CRT_HOTPLUG_ENABLE |
+			ADPA_CRT_HOTPLUG_FORCE_TRIGGER);
+
+	DRM_DEBUG("pch crt adpa 0x%x", adpa);
+	I915_WRITE(PCH_ADPA, adpa);
+
+	while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0)
+		;
+
+	/* Check the status to see if both blue and green are on now */
+	adpa = I915_READ(PCH_ADPA);
+	adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK;
+	if ((adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR) ||
+		(adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO))
+		ret = true;
+	else
+		ret = false;
+
+	/* restore origin register */
+	I915_WRITE(PCH_ADPA, temp);
+	return ret;
 }
 
 /**
@@ -148,6 +203,10 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 hotplug_en;
 	int i, tries = 0;
+
+	if (IS_IGDNG(dev))
+		return intel_igdng_crt_detect_hotplug(connector);
+
 	/*
 	 * On 4 series desktop, CRT detect sequence need to be done twice
 	 * to get a reliable result.
@@ -373,8 +432,34 @@
 
 static int intel_crt_get_modes(struct drm_connector *connector)
 {
+	int ret;
 	struct intel_output *intel_output = to_intel_output(connector);
-	return intel_ddc_get_modes(intel_output);
+	struct i2c_adapter *ddcbus;
+	struct drm_device *dev = connector->dev;
+
+
+	ret = intel_ddc_get_modes(intel_output);
+	if (ret || !IS_G4X(dev))
+		goto end;
+
+	ddcbus = intel_output->ddc_bus;
+	/* Try to probe digital port for output in DVI-I -> VGA mode. */
+	intel_output->ddc_bus =
+		intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D");
+
+	if (!intel_output->ddc_bus) {
+		intel_output->ddc_bus = ddcbus;
+		dev_printk(KERN_ERR, &connector->dev->pdev->dev,
+			   "DDC bus registration failed for CRTDDC_D.\n");
+		goto end;
+	}
+	/* Try to get modes by GPIOD port */
+	ret = intel_ddc_get_modes(intel_output);
+	intel_i2c_destroy(ddcbus);
+
+end:
+	return ret;
+
 }
 
 static int intel_crt_set_property(struct drm_connector *connector,
@@ -423,6 +508,8 @@
 {
 	struct drm_connector *connector;
 	struct intel_output *intel_output;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 i2c_reg;
 
 	intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
 	if (!intel_output)
@@ -439,7 +526,15 @@
 					  &intel_output->enc);
 
 	/* Set up the DDC bus. */
-	intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
+	if (IS_IGDNG(dev))
+		i2c_reg = PCH_GPIOA;
+	else {
+		i2c_reg = GPIOA;
+		/* Use VBT information for CRT DDC if available */
+		if (dev_priv->crt_ddc_bus != -1)
+			i2c_reg = dev_priv->crt_ddc_bus;
+	}
+	intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
 	if (!intel_output->ddc_bus) {
 		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
 			   "failed.\n");
@@ -447,6 +542,10 @@
 	}
 
 	intel_output->type = INTEL_OUTPUT_ANALOG;
+	intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+				   (1 << INTEL_ANALOG_CLONE_BIT) |
+				   (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+	intel_output->crtc_mask = (1 << 0) | (1 << 1);
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_display.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_display.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,14 +25,19 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/kernel.h>
 #include "drmP.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
+#include "intel_dp.h"
 
 #include "drm_crtc_helper.h"
 
+#define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
+
 bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
+static void intel_update_watermarks(struct drm_device *dev);
 
 typedef struct {
     /* given values */
@@ -85,7 +90,7 @@
 #define I8XX_P2_SLOW		      4
 #define I8XX_P2_FAST		      2
 #define I8XX_P2_LVDS_SLOW	      14
-#define I8XX_P2_LVDS_FAST	      14 /* No fast option */
+#define I8XX_P2_LVDS_FAST	      7
 #define I8XX_P2_SLOW_LIMIT	 165000
 
 #define I9XX_DOT_MIN		  20000
@@ -127,17 +132,6 @@
 #define I9XX_P2_LVDS_FAST		      7
 #define I9XX_P2_LVDS_SLOW_LIMIT		 112000
 
-#define INTEL_LIMIT_I8XX_DVO_DAC    0
-#define INTEL_LIMIT_I8XX_LVDS	    1
-#define INTEL_LIMIT_I9XX_SDVO_DAC   2
-#define INTEL_LIMIT_I9XX_LVDS	    3
-#define INTEL_LIMIT_G4X_SDVO	    4
-#define INTEL_LIMIT_G4X_HDMI_DAC   5
-#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS   6
-#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS   7
-#define INTEL_LIMIT_IGD_SDVO_DAC    8
-#define INTEL_LIMIT_IGD_LVDS	    9
-
 /*The parameter is for SDVO on G4x platform*/
 #define G4X_DOT_SDVO_MIN           25000
 #define G4X_DOT_SDVO_MAX           270000
@@ -216,15 +210,71 @@
 #define G4X_P2_DUAL_CHANNEL_LVDS_FAST           7
 #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT          0
 
+/*The parameter is for DISPLAY PORT on G4x platform*/
+#define G4X_DOT_DISPLAY_PORT_MIN           161670
+#define G4X_DOT_DISPLAY_PORT_MAX           227000
+#define G4X_N_DISPLAY_PORT_MIN             1
+#define G4X_N_DISPLAY_PORT_MAX             2
+#define G4X_M_DISPLAY_PORT_MIN             97
+#define G4X_M_DISPLAY_PORT_MAX             108
+#define G4X_M1_DISPLAY_PORT_MIN            0x10
+#define G4X_M1_DISPLAY_PORT_MAX            0x12
+#define G4X_M2_DISPLAY_PORT_MIN            0x05
+#define G4X_M2_DISPLAY_PORT_MAX            0x06
+#define G4X_P_DISPLAY_PORT_MIN             10
+#define G4X_P_DISPLAY_PORT_MAX             20
+#define G4X_P1_DISPLAY_PORT_MIN            1
+#define G4X_P1_DISPLAY_PORT_MAX            2
+#define G4X_P2_DISPLAY_PORT_SLOW           10
+#define G4X_P2_DISPLAY_PORT_FAST           10
+#define G4X_P2_DISPLAY_PORT_LIMIT          0
+
+/* IGDNG */
+/* as we calculate clock using (register_value + 2) for
+   N/M1/M2, so here the range value for them is (actual_value-2).
+ */
+#define IGDNG_DOT_MIN         25000
+#define IGDNG_DOT_MAX         350000
+#define IGDNG_VCO_MIN         1760000
+#define IGDNG_VCO_MAX         3510000
+#define IGDNG_N_MIN           1
+#define IGDNG_N_MAX           5
+#define IGDNG_M_MIN           79
+#define IGDNG_M_MAX           118
+#define IGDNG_M1_MIN          12
+#define IGDNG_M1_MAX          23
+#define IGDNG_M2_MIN          5
+#define IGDNG_M2_MAX          9
+#define IGDNG_P_SDVO_DAC_MIN  5
+#define IGDNG_P_SDVO_DAC_MAX  80
+#define IGDNG_P_LVDS_MIN      28
+#define IGDNG_P_LVDS_MAX      112
+#define IGDNG_P1_MIN          1
+#define IGDNG_P1_MAX          8
+#define IGDNG_P2_SDVO_DAC_SLOW 10
+#define IGDNG_P2_SDVO_DAC_FAST 5
+#define IGDNG_P2_LVDS_SLOW    14 /* single channel */
+#define IGDNG_P2_LVDS_FAST    7  /* double channel */
+#define IGDNG_P2_DOT_LIMIT    225000 /* 225Mhz */
+
 static bool
 intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 		    int target, int refclk, intel_clock_t *best_clock);
 static bool
 intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 			int target, int refclk, intel_clock_t *best_clock);
+static bool
+intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
+			int target, int refclk, intel_clock_t *best_clock);
 
-static const intel_limit_t intel_limits[] = {
-    { /* INTEL_LIMIT_I8XX_DVO_DAC */
+static bool
+intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
+		      int target, int refclk, intel_clock_t *best_clock);
+static bool
+intel_find_pll_igdng_dp(const intel_limit_t *, struct drm_crtc *crtc,
+		      int target, int refclk, intel_clock_t *best_clock);
+
+static const intel_limit_t intel_limits_i8xx_dvo = {
         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
         .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
         .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
@@ -236,8 +286,9 @@
 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
 		 .p2_slow = I8XX_P2_SLOW,	.p2_fast = I8XX_P2_FAST },
 	.find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_I8XX_LVDS */
+};
+
+static const intel_limit_t intel_limits_i8xx_lvds = {
         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
         .vco = { .min = I8XX_VCO_MIN,		.max = I8XX_VCO_MAX },
         .n   = { .min = I8XX_N_MIN,		.max = I8XX_N_MAX },
@@ -249,8 +300,9 @@
 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
 		 .p2_slow = I8XX_P2_LVDS_SLOW,	.p2_fast = I8XX_P2_LVDS_FAST },
 	.find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_I9XX_SDVO_DAC */
+};
+	
+static const intel_limit_t intel_limits_i9xx_sdvo = {
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
         .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
         .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
@@ -262,8 +314,9 @@
 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
 	.find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_I9XX_LVDS */
+};
+
+static const intel_limit_t intel_limits_i9xx_lvds = {
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
         .vco = { .min = I9XX_VCO_MIN,		.max = I9XX_VCO_MAX },
         .n   = { .min = I9XX_N_MIN,		.max = I9XX_N_MAX },
@@ -278,9 +331,10 @@
 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_FAST },
 	.find_pll = intel_find_best_PLL,
-    },
+};
+
     /* below parameter and function is for G4X Chipset Family*/
-    { /* INTEL_LIMIT_G4X_SDVO */
+static const intel_limit_t intel_limits_g4x_sdvo = {
 	.dot = { .min = G4X_DOT_SDVO_MIN,	.max = G4X_DOT_SDVO_MAX },
 	.vco = { .min = G4X_VCO_MIN,	        .max = G4X_VCO_MAX},
 	.n   = { .min = G4X_N_SDVO_MIN,	        .max = G4X_N_SDVO_MAX },
@@ -294,8 +348,9 @@
 		 .p2_fast = G4X_P2_SDVO_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_G4X_HDMI_DAC */
+};
+
+static const intel_limit_t intel_limits_g4x_hdmi = {
 	.dot = { .min = G4X_DOT_HDMI_DAC_MIN,	.max = G4X_DOT_HDMI_DAC_MAX },
 	.vco = { .min = G4X_VCO_MIN,	        .max = G4X_VCO_MAX},
 	.n   = { .min = G4X_N_HDMI_DAC_MIN,	.max = G4X_N_HDMI_DAC_MAX },
@@ -309,8 +364,9 @@
 		 .p2_fast = G4X_P2_HDMI_DAC_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */
+};
+
+static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
 	.dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN,
 		 .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX },
 	.vco = { .min = G4X_VCO_MIN,
@@ -332,8 +388,9 @@
 		 .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */
+};
+
+static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
 	.dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN,
 		 .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX },
 	.vco = { .min = G4X_VCO_MIN,
@@ -355,8 +412,32 @@
 		 .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_IGD_SDVO */
+};
+
+static const intel_limit_t intel_limits_g4x_display_port = {
+        .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN,
+                 .max = G4X_DOT_DISPLAY_PORT_MAX },
+        .vco = { .min = G4X_VCO_MIN,
+                 .max = G4X_VCO_MAX},
+        .n   = { .min = G4X_N_DISPLAY_PORT_MIN,
+                 .max = G4X_N_DISPLAY_PORT_MAX },
+        .m   = { .min = G4X_M_DISPLAY_PORT_MIN,
+                 .max = G4X_M_DISPLAY_PORT_MAX },
+        .m1  = { .min = G4X_M1_DISPLAY_PORT_MIN,
+                 .max = G4X_M1_DISPLAY_PORT_MAX },
+        .m2  = { .min = G4X_M2_DISPLAY_PORT_MIN,
+                 .max = G4X_M2_DISPLAY_PORT_MAX },
+        .p   = { .min = G4X_P_DISPLAY_PORT_MIN,
+                 .max = G4X_P_DISPLAY_PORT_MAX },
+        .p1  = { .min = G4X_P1_DISPLAY_PORT_MIN,
+                 .max = G4X_P1_DISPLAY_PORT_MAX},
+        .p2  = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT,
+                 .p2_slow = G4X_P2_DISPLAY_PORT_SLOW,
+                 .p2_fast = G4X_P2_DISPLAY_PORT_FAST },
+        .find_pll = intel_find_pll_g4x_dp,
+};
+
+static const intel_limit_t intel_limits_igd_sdvo = {
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX},
         .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
         .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
@@ -368,8 +449,9 @@
 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
 	.find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_IGD_LVDS */
+};
+
+static const intel_limit_t intel_limits_igd_lvds = {
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
         .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
         .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
@@ -382,10 +464,49 @@
 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_SLOW },
 	.find_pll = intel_find_best_PLL,
-    },
+};
 
+static const intel_limit_t intel_limits_igdng_sdvo = {
+	.dot = { .min = IGDNG_DOT_MIN,          .max = IGDNG_DOT_MAX },
+	.vco = { .min = IGDNG_VCO_MIN,          .max = IGDNG_VCO_MAX },
+	.n   = { .min = IGDNG_N_MIN,            .max = IGDNG_N_MAX },
+	.m   = { .min = IGDNG_M_MIN,            .max = IGDNG_M_MAX },
+	.m1  = { .min = IGDNG_M1_MIN,           .max = IGDNG_M1_MAX },
+	.m2  = { .min = IGDNG_M2_MIN,           .max = IGDNG_M2_MAX },
+	.p   = { .min = IGDNG_P_SDVO_DAC_MIN,   .max = IGDNG_P_SDVO_DAC_MAX },
+	.p1  = { .min = IGDNG_P1_MIN,           .max = IGDNG_P1_MAX },
+	.p2  = { .dot_limit = IGDNG_P2_DOT_LIMIT,
+		 .p2_slow = IGDNG_P2_SDVO_DAC_SLOW,
+		 .p2_fast = IGDNG_P2_SDVO_DAC_FAST },
+	.find_pll = intel_igdng_find_best_PLL,
 };
 
+static const intel_limit_t intel_limits_igdng_lvds = {
+	.dot = { .min = IGDNG_DOT_MIN,          .max = IGDNG_DOT_MAX },
+	.vco = { .min = IGDNG_VCO_MIN,          .max = IGDNG_VCO_MAX },
+	.n   = { .min = IGDNG_N_MIN,            .max = IGDNG_N_MAX },
+	.m   = { .min = IGDNG_M_MIN,            .max = IGDNG_M_MAX },
+	.m1  = { .min = IGDNG_M1_MIN,           .max = IGDNG_M1_MAX },
+	.m2  = { .min = IGDNG_M2_MIN,           .max = IGDNG_M2_MAX },
+	.p   = { .min = IGDNG_P_LVDS_MIN,       .max = IGDNG_P_LVDS_MAX },
+	.p1  = { .min = IGDNG_P1_MIN,           .max = IGDNG_P1_MAX },
+	.p2  = { .dot_limit = IGDNG_P2_DOT_LIMIT,
+		 .p2_slow = IGDNG_P2_LVDS_SLOW,
+		 .p2_fast = IGDNG_P2_LVDS_FAST },
+	.find_pll = intel_igdng_find_best_PLL,
+};
+
+static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc)
+{
+	const intel_limit_t *limit;
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+		limit = &intel_limits_igdng_lvds;
+	else
+		limit = &intel_limits_igdng_sdvo;
+
+	return limit;
+}
+
 static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -396,19 +517,19 @@
 		if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
 		    LVDS_CLKB_POWER_UP)
 			/* LVDS with dual channel */
-			limit = &intel_limits
-					[INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS];
+			limit = &intel_limits_g4x_dual_channel_lvds;
 		else
 			/* LVDS with dual channel */
-			limit = &intel_limits
-					[INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS];
+			limit = &intel_limits_g4x_single_channel_lvds;
 	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
 		   intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
-		limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
+		limit = &intel_limits_g4x_hdmi;
 	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
-		limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
+		limit = &intel_limits_g4x_sdvo;
+	} else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+		limit = &intel_limits_g4x_display_port;
 	} else /* The option is for other outputs */
-		limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+		limit = &intel_limits_i9xx_sdvo;
 
 	return limit;
 }
@@ -418,23 +539,25 @@
 	struct drm_device *dev = crtc->dev;
 	const intel_limit_t *limit;
 
-	if (IS_G4X(dev)) {
+	if (IS_IGDNG(dev))
+		limit = intel_igdng_limit(crtc);
+	else if (IS_G4X(dev)) {
 		limit = intel_g4x_limit(crtc);
 	} else if (IS_I9XX(dev) && !IS_IGD(dev)) {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-			limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
+			limit = &intel_limits_i9xx_lvds;
 		else
-			limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+			limit = &intel_limits_i9xx_sdvo;
 	} else if (IS_IGD(dev)) {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-			limit = &intel_limits[INTEL_LIMIT_IGD_LVDS];
+			limit = &intel_limits_igd_lvds;
 		else
-			limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC];
+			limit = &intel_limits_igd_sdvo;
 	} else {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-			limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
+			limit = &intel_limits_i8xx_lvds;
 		else
-			limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
+			limit = &intel_limits_i8xx_dvo;
 	}
 	return limit;
 }
@@ -480,6 +603,23 @@
     return false;
 }
 
+struct drm_connector *
+intel_pipe_get_output (struct drm_crtc *crtc)
+{
+    struct drm_device *dev = crtc->dev;
+    struct drm_mode_config *mode_config = &dev->mode_config;
+    struct drm_connector *l_entry, *ret = NULL;
+
+    list_for_each_entry(l_entry, &mode_config->connector_list, head) {
+	    if (l_entry->encoder &&
+	        l_entry->encoder->crtc == crtc) {
+		    ret = l_entry;
+		    break;
+	    }
+    }
+    return ret;
+}
+
 #define INTELPllInvalid(s)   do { /* DRM_DEBUG(s); */ return false; } while (0)
 /**
  * Returns whether the given set of divisors are valid for a given refclk with
@@ -526,8 +666,8 @@
 	intel_clock_t clock;
 	int err = target;
 
-	if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
-	    (I915_READ(LVDS) & LVDS_PORT_EN) != 0) {
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	    (I915_READ(LVDS)) != 0) {
 		/*
 		 * For LVDS, if the panel is on, just rely on its current
 		 * settings for dual-channel.  We haven't figured out how to
@@ -630,10 +770,125 @@
 			}
 		}
 	}
+	return found;
+}
+
+static bool
+intel_find_pll_igdng_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
+		      int target, int refclk, intel_clock_t *best_clock)
+{
+	struct drm_device *dev = crtc->dev;
+	intel_clock_t clock;
+	if (target < 200000) {
+		clock.n = 1;
+		clock.p1 = 2;
+		clock.p2 = 10;
+		clock.m1 = 12;
+		clock.m2 = 9;
+	} else {
+		clock.n = 2;
+		clock.p1 = 1;
+		clock.p2 = 10;
+		clock.m1 = 14;
+		clock.m2 = 8;
+	}
+	intel_clock(dev, refclk, &clock);
+	memcpy(best_clock, &clock, sizeof(intel_clock_t));
+	return true;
+}
+
+static bool
+intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
+			int target, int refclk, intel_clock_t *best_clock)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	intel_clock_t clock;
+	int max_n;
+	bool found;
+	int err_most = 47;
+	found = false;
+
+	/* eDP has only 2 clock choice, no n/m/p setting */
+	if (HAS_eDP)
+		return true;
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+		return intel_find_pll_igdng_dp(limit, crtc, target,
+					       refclk, best_clock);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+		if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+		    LVDS_CLKB_POWER_UP)
+			clock.p2 = limit->p2.p2_fast;
+		else
+			clock.p2 = limit->p2.p2_slow;
+	} else {
+		if (target < limit->p2.dot_limit)
+			clock.p2 = limit->p2.p2_slow;
+		else
+			clock.p2 = limit->p2.p2_fast;
+	}
+
+	memset(best_clock, 0, sizeof(*best_clock));
+	max_n = limit->n.max;
+	/* based on hardware requriment prefer smaller n to precision */
+	for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
+		/* based on hardware requirment prefere larger m1,m2, p1 */
+		for (clock.m1 = limit->m1.max;
+		     clock.m1 >= limit->m1.min; clock.m1--) {
+			for (clock.m2 = limit->m2.max;
+			     clock.m2 >= limit->m2.min; clock.m2--) {
+				for (clock.p1 = limit->p1.max;
+				     clock.p1 >= limit->p1.min; clock.p1--) {
+					int this_err;
 
+					intel_clock(dev, refclk, &clock);
+					if (!intel_PLL_is_valid(crtc, &clock))
+						continue;
+					this_err = abs((10000 - (target*10000/clock.dot)));
+					if (this_err < err_most) {
+						*best_clock = clock;
+						err_most = this_err;
+						max_n = clock.n;
+						found = true;
+						/* found on first matching */
+						goto out;
+					}
+				}
+			}
+		}
+	}
+out:
 	return found;
 }
 
+/* DisplayPort has only two frequencies, 162MHz and 270MHz */
+static bool
+intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
+		      int target, int refclk, intel_clock_t *best_clock)
+{
+    intel_clock_t clock;
+    if (target < 200000) {
+	clock.p1 = 2;
+	clock.p2 = 10;
+	clock.n = 2;
+	clock.m1 = 23;
+	clock.m2 = 8;
+    } else {
+	clock.p1 = 1;
+	clock.p2 = 10;
+	clock.n = 1;
+	clock.m1 = 14;
+	clock.m2 = 2;
+    }
+    clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2);
+    clock.p = (clock.p1 * clock.p2);
+    clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p;
+    memcpy(best_clock, &clock, sizeof(intel_clock_t));
+    return true;
+}
+
 void
 intel_wait_for_vblank(struct drm_device *dev)
 {
@@ -698,19 +953,31 @@
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	ret = i915_gem_object_pin(intel_fb->obj, alignment);
+	ret = i915_gem_object_pin(obj, alignment);
 	if (ret != 0) {
 		mutex_unlock(&dev->struct_mutex);
 		return ret;
 	}
 
-	ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
+	ret = i915_gem_object_set_to_gtt_domain(obj, 1);
 	if (ret != 0) {
-		i915_gem_object_unpin(intel_fb->obj);
+		i915_gem_object_unpin(obj);
 		mutex_unlock(&dev->struct_mutex);
 		return ret;
 	}
 
+	/* Pre-i965 needs to install a fence for tiled scan-out */
+	if (!IS_I965G(dev) &&
+	    obj_priv->fence_reg == I915_FENCE_REG_NONE &&
+	    obj_priv->tiling_mode != I915_TILING_NONE) {
+		ret = i915_gem_object_get_fence_reg(obj);
+		if (ret != 0) {
+			i915_gem_object_unpin(obj);
+			mutex_unlock(&dev->struct_mutex);
+			return ret;
+		}
+	}
+
 	dspcntr = I915_READ(dspcntr_reg);
 	/* Mask out pixel format bits in case we change it */
 	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
@@ -730,7 +997,7 @@
 		break;
 	default:
 		DRM_ERROR("Unknown color depth\n");
-		i915_gem_object_unpin(intel_fb->obj);
+		i915_gem_object_unpin(obj);
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
@@ -785,18 +1052,420 @@
 	return 0;
 }
 
+/* Disable the VGA plane that we never use */
+static void i915_disable_vga (struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u8 sr1;
+	u32 vga_reg;
+
+	if (IS_IGDNG(dev))
+		vga_reg = CPU_VGACNTRL;
+	else
+		vga_reg = VGACNTRL;
 
+	if (I915_READ(vga_reg) & VGA_DISP_DISABLE)
+		return;
 
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+	I915_WRITE8(VGA_SR_INDEX, 1);
+	sr1 = I915_READ8(VGA_SR_DATA);
+	I915_WRITE8(VGA_SR_DATA, sr1 | (1 << 5));
+	udelay(100);
+
+	I915_WRITE(vga_reg, VGA_DISP_DISABLE);
+}
+
+static void igdng_disable_pll_edp (struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 dpa_ctl;
+
+	DRM_DEBUG("\n");
+	dpa_ctl = I915_READ(DP_A);
+	dpa_ctl &= ~DP_PLL_ENABLE;
+	I915_WRITE(DP_A, dpa_ctl);
+}
+
+static void igdng_enable_pll_edp (struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 dpa_ctl;
+
+	dpa_ctl = I915_READ(DP_A);
+	dpa_ctl |= DP_PLL_ENABLE;
+	I915_WRITE(DP_A, dpa_ctl);
+	udelay(200);
+}
+
+
+static void igdng_set_pll_edp (struct drm_crtc *crtc, int clock)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 dpa_ctl;
+
+	DRM_DEBUG("eDP PLL enable for clock %d\n", clock);
+	dpa_ctl = I915_READ(DP_A);
+	dpa_ctl &= ~DP_PLL_FREQ_MASK;
+
+	if (clock < 200000) {
+		u32 temp;
+		dpa_ctl |= DP_PLL_FREQ_160MHZ;
+		/* workaround for 160Mhz:
+		   1) program 0x4600c bits 15:0 = 0x8124
+		   2) program 0x46010 bit 0 = 1
+		   3) program 0x46034 bit 24 = 1
+		   4) program 0x64000 bit 14 = 1
+		   */
+		temp = I915_READ(0x4600c);
+		temp &= 0xffff0000;
+		I915_WRITE(0x4600c, temp | 0x8124);
+
+		temp = I915_READ(0x46010);
+		I915_WRITE(0x46010, temp | 1);
+
+		temp = I915_READ(0x46034);
+		I915_WRITE(0x46034, temp | (1 << 24));
+	} else {
+		dpa_ctl |= DP_PLL_FREQ_270MHZ;
+	}
+	I915_WRITE(DP_A, dpa_ctl);
+
+	udelay(500);
+}
+
+static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+	int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+	int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
+	int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
+	int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+	int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
+	int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
+	int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
+	int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
+	int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
+	int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+	int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+	int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+	int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+	int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+	int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+	int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B;
+	int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B;
+	int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B;
+	int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
+	int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
+	int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
+	u32 temp;
+	int tries = 5, j, n;
+
+	/* XXX: When our outputs are all unaware of DPMS modes other than off
+	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+	 */
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		DRM_DEBUG("crtc %d dpms on\n", pipe);
+		if (HAS_eDP) {
+			/* enable eDP PLL */
+			igdng_enable_pll_edp(crtc);
+		} else {
+			/* enable PCH DPLL */
+			temp = I915_READ(pch_dpll_reg);
+			if ((temp & DPLL_VCO_ENABLE) == 0) {
+				I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
+				I915_READ(pch_dpll_reg);
+			}
+
+			/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
+			temp = I915_READ(fdi_rx_reg);
+			I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
+					FDI_SEL_PCDCLK |
+					FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
+			I915_READ(fdi_rx_reg);
+			udelay(200);
+
+			/* Enable CPU FDI TX PLL, always on for IGDNG */
+			temp = I915_READ(fdi_tx_reg);
+			if ((temp & FDI_TX_PLL_ENABLE) == 0) {
+				I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
+				I915_READ(fdi_tx_reg);
+				udelay(100);
+			}
+		}
+
+		/* Enable CPU pipe */
+		temp = I915_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) == 0) {
+			I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+			I915_READ(pipeconf_reg);
+			udelay(100);
+		}
+
+		/* configure and enable CPU plane */
+		temp = I915_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
+		}
+
+		if (!HAS_eDP) {
+			/* enable CPU FDI TX and PCH FDI RX */
+			temp = I915_READ(fdi_tx_reg);
+			temp |= FDI_TX_ENABLE;
+			temp |= FDI_DP_PORT_WIDTH_X4; /* default */
+			temp &= ~FDI_LINK_TRAIN_NONE;
+			temp |= FDI_LINK_TRAIN_PATTERN_1;
+			I915_WRITE(fdi_tx_reg, temp);
+			I915_READ(fdi_tx_reg);
+
+			temp = I915_READ(fdi_rx_reg);
+			temp &= ~FDI_LINK_TRAIN_NONE;
+			temp |= FDI_LINK_TRAIN_PATTERN_1;
+			I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
+			I915_READ(fdi_rx_reg);
+
+			udelay(150);
+
+			/* Train FDI. */
+			/* umask FDI RX Interrupt symbol_lock and bit_lock bit
+			   for train result */
+			temp = I915_READ(fdi_rx_imr_reg);
+			temp &= ~FDI_RX_SYMBOL_LOCK;
+			temp &= ~FDI_RX_BIT_LOCK;
+			I915_WRITE(fdi_rx_imr_reg, temp);
+			I915_READ(fdi_rx_imr_reg);
+			udelay(150);
+
+			temp = I915_READ(fdi_rx_iir_reg);
+			DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+
+			if ((temp & FDI_RX_BIT_LOCK) == 0) {
+				for (j = 0; j < tries; j++) {
+					temp = I915_READ(fdi_rx_iir_reg);
+					DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+					if (temp & FDI_RX_BIT_LOCK)
+						break;
+					udelay(200);
+				}
+				if (j != tries)
+					I915_WRITE(fdi_rx_iir_reg,
+							temp | FDI_RX_BIT_LOCK);
+				else
+					DRM_DEBUG("train 1 fail\n");
+			} else {
+				I915_WRITE(fdi_rx_iir_reg,
+						temp | FDI_RX_BIT_LOCK);
+				DRM_DEBUG("train 1 ok 2!\n");
+			}
+			temp = I915_READ(fdi_tx_reg);
+			temp &= ~FDI_LINK_TRAIN_NONE;
+			temp |= FDI_LINK_TRAIN_PATTERN_2;
+			I915_WRITE(fdi_tx_reg, temp);
+
+			temp = I915_READ(fdi_rx_reg);
+			temp &= ~FDI_LINK_TRAIN_NONE;
+			temp |= FDI_LINK_TRAIN_PATTERN_2;
+			I915_WRITE(fdi_rx_reg, temp);
+
+			udelay(150);
+
+			temp = I915_READ(fdi_rx_iir_reg);
+			DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+
+			if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
+				for (j = 0; j < tries; j++) {
+					temp = I915_READ(fdi_rx_iir_reg);
+					DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+					if (temp & FDI_RX_SYMBOL_LOCK)
+						break;
+					udelay(200);
+				}
+				if (j != tries) {
+					I915_WRITE(fdi_rx_iir_reg,
+							temp | FDI_RX_SYMBOL_LOCK);
+					DRM_DEBUG("train 2 ok 1!\n");
+				} else
+					DRM_DEBUG("train 2 fail\n");
+			} else {
+				I915_WRITE(fdi_rx_iir_reg,
+						temp | FDI_RX_SYMBOL_LOCK);
+				DRM_DEBUG("train 2 ok 2!\n");
+			}
+			DRM_DEBUG("train done\n");
+
+			/* set transcoder timing */
+			I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
+			I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg));
+			I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg));
+
+			I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg));
+			I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
+			I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
+
+			/* enable PCH transcoder */
+			temp = I915_READ(transconf_reg);
+			I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
+			I915_READ(transconf_reg);
+
+			while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
+				;
+
+			/* enable normal */
+
+			temp = I915_READ(fdi_tx_reg);
+			temp &= ~FDI_LINK_TRAIN_NONE;
+			I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
+					FDI_TX_ENHANCE_FRAME_ENABLE);
+			I915_READ(fdi_tx_reg);
+
+			temp = I915_READ(fdi_rx_reg);
+			temp &= ~FDI_LINK_TRAIN_NONE;
+			I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
+					FDI_RX_ENHANCE_FRAME_ENABLE);
+			I915_READ(fdi_rx_reg);
+
+			/* wait one idle pattern time */
+			udelay(100);
+
+		}
+
+		intel_crtc_load_lut(crtc);
+
+	break;
+	case DRM_MODE_DPMS_OFF:
+		DRM_DEBUG("crtc %d dpms off\n", pipe);
+
+		i915_disable_vga(dev);
+
+		/* Disable display plane */
+		temp = I915_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
+			I915_READ(dspbase_reg);
+		}
+
+		/* disable cpu pipe, disable after all planes disabled */
+		temp = I915_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+			I915_READ(pipeconf_reg);
+			n = 0;
+			/* wait for cpu pipe off, pipe state */
+			while ((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0) {
+				n++;
+				if (n < 60) {
+					udelay(500);
+					continue;
+				} else {
+					DRM_DEBUG("pipe %d off delay\n", pipe);
+					break;
+				}
+			}
+		} else
+			DRM_DEBUG("crtc %d is disabled\n", pipe);
+
+		if (HAS_eDP) {
+			igdng_disable_pll_edp(crtc);
+		}
+
+		/* disable CPU FDI tx and PCH FDI rx */
+		temp = I915_READ(fdi_tx_reg);
+		I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
+		I915_READ(fdi_tx_reg);
+
+		temp = I915_READ(fdi_rx_reg);
+		I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
+		I915_READ(fdi_rx_reg);
+
+		udelay(100);
+
+		/* still set train pattern 1 */
+		temp = I915_READ(fdi_tx_reg);
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_1;
+		I915_WRITE(fdi_tx_reg, temp);
+
+		temp = I915_READ(fdi_rx_reg);
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_1;
+		I915_WRITE(fdi_rx_reg, temp);
+
+		udelay(100);
+
+		/* disable PCH transcoder */
+		temp = I915_READ(transconf_reg);
+		if ((temp & TRANS_ENABLE) != 0) {
+			I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE);
+			I915_READ(transconf_reg);
+			n = 0;
+			/* wait for PCH transcoder off, transcoder state */
+			while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) != 0) {
+				n++;
+				if (n < 60) {
+					udelay(500);
+					continue;
+				} else {
+					DRM_DEBUG("transcoder %d off delay\n", pipe);
+					break;
+				}
+			}
+		}
+
+		/* disable PCH DPLL */
+		temp = I915_READ(pch_dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) != 0) {
+			I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
+			I915_READ(pch_dpll_reg);
+		}
+
+		temp = I915_READ(fdi_rx_reg);
+		if ((temp & FDI_RX_PLL_ENABLE) != 0) {
+			temp &= ~FDI_SEL_PCDCLK;
+			temp &= ~FDI_RX_PLL_ENABLE;
+			I915_WRITE(fdi_rx_reg, temp);
+			I915_READ(fdi_rx_reg);
+		}
+
+		/* Disable CPU FDI TX PLL */
+		temp = I915_READ(fdi_tx_reg);
+		if ((temp & FDI_TX_PLL_ENABLE) != 0) {
+			I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
+			I915_READ(fdi_tx_reg);
+			udelay(100);
+		}
+
+		/* Disable PF */
+		temp = I915_READ(pf_ctl_reg);
+		if ((temp & PF_ENABLE) != 0) {
+			I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
+			I915_READ(pf_ctl_reg);
+		}
+		I915_WRITE(pf_win_size, 0);
+
+		/* Wait for the clocks to turn off. */
+		udelay(150);
+		break;
+	}
+}
+
+static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_i915_master_private *master_priv;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
@@ -805,7 +1474,6 @@
 	int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR;
 	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
 	u32 temp;
-	bool enabled;
 
 	/* XXX: When our outputs are all unaware of DPMS modes other than off
 	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
@@ -848,13 +1516,15 @@
 
 		/* Give the overlay scaler a chance to enable if it's on this pipe */
 		//intel_crtc_dpms_video(crtc, true); TODO
+		intel_update_watermarks(dev);
 	break;
 	case DRM_MODE_DPMS_OFF:
+		intel_update_watermarks(dev);
 		/* Give the overlay scaler a chance to disable if it's on this pipe */
 		//intel_crtc_dpms_video(crtc, FALSE); TODO
 
 		/* Disable the VGA plane that we never use */
-		I915_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+		i915_disable_vga(dev);
 
 		/* Disable display plane */
 		temp = I915_READ(dspcntr_reg);
@@ -890,6 +1560,26 @@
 		udelay(150);
 		break;
 	}
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_master_private *master_priv;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	bool enabled;
+
+	if (IS_IGDNG(dev))
+		igdng_crtc_dpms(crtc, mode);
+	else
+		i9xx_crtc_dpms(crtc, mode);
 
 	if (!dev->primary->master)
 		return;
@@ -947,6 +1637,12 @@
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
 {
+	struct drm_device *dev = crtc->dev;
+	if (IS_IGDNG(dev)) {
+		/* FDI link clock is fixed at 2.7G */
+		if (mode->clock * 3 > 27000 * 4)
+			return MODE_CLOCK_HIGH;
+	}
 	return true;
 }
 
@@ -1002,7 +1698,6 @@
 	return 0; /* Silence gcc warning */
 }
 
-
 /**
  * Return the pipe currently connected to the panel fitter,
  * or -1 if the panel fitter is not present or not in use
@@ -1030,6 +1725,520 @@
 	return 1;
 }
 
+struct fdi_m_n {
+	u32        tu;
+	u32        gmch_m;
+	u32        gmch_n;
+	u32        link_m;
+	u32        link_n;
+};
+
+static void
+fdi_reduce_ratio(u32 *num, u32 *den)
+{
+	while (*num > 0xffffff || *den > 0xffffff) {
+		*num >>= 1;
+		*den >>= 1;
+	}
+}
+
+#define DATA_N 0x800000
+#define LINK_N 0x80000
+
+static void
+igdng_compute_m_n(int bytes_per_pixel, int nlanes,
+		int pixel_clock, int link_clock,
+		struct fdi_m_n *m_n)
+{
+	u64 temp;
+
+	m_n->tu = 64; /* default size */
+
+	temp = (u64) DATA_N * pixel_clock;
+	temp = div_u64(temp, link_clock);
+	m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes);
+	m_n->gmch_n = DATA_N;
+	fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
+
+	temp = (u64) LINK_N * pixel_clock;
+	m_n->link_m = div_u64(temp, link_clock);
+	m_n->link_n = LINK_N;
+	fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
+}
+
+
+struct intel_watermark_params {
+	unsigned long fifo_size;
+	unsigned long max_wm;
+	unsigned long default_wm;
+	unsigned long guard_size;
+	unsigned long cacheline_size;
+};
+
+/* IGD has different values for various configs */
+static struct intel_watermark_params igd_display_wm = {
+	IGD_DISPLAY_FIFO,
+	IGD_MAX_WM,
+	IGD_DFT_WM,
+	IGD_GUARD_WM,
+	IGD_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params igd_display_hplloff_wm = {
+	IGD_DISPLAY_FIFO,
+	IGD_MAX_WM,
+	IGD_DFT_HPLLOFF_WM,
+	IGD_GUARD_WM,
+	IGD_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params igd_cursor_wm = {
+	IGD_CURSOR_FIFO,
+	IGD_CURSOR_MAX_WM,
+	IGD_CURSOR_DFT_WM,
+	IGD_CURSOR_GUARD_WM,
+	IGD_FIFO_LINE_SIZE,
+};
+static struct intel_watermark_params igd_cursor_hplloff_wm = {
+	IGD_CURSOR_FIFO,
+	IGD_CURSOR_MAX_WM,
+	IGD_CURSOR_DFT_WM,
+	IGD_CURSOR_GUARD_WM,
+	IGD_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i945_wm_info = {
+	I945_FIFO_SIZE,
+	I915_MAX_WM,
+	1,
+	2,
+	I915_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i915_wm_info = {
+	I915_FIFO_SIZE,
+	I915_MAX_WM,
+	1,
+	2,
+	I915_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i855_wm_info = {
+	I855GM_FIFO_SIZE,
+	I915_MAX_WM,
+	1,
+	2,
+	I830_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i830_wm_info = {
+	I830_FIFO_SIZE,
+	I915_MAX_WM,
+	1,
+	2,
+	I830_FIFO_LINE_SIZE
+};
+
+/**
+ * intel_calculate_wm - calculate watermark level
+ * @clock_in_khz: pixel clock
+ * @wm: chip FIFO params
+ * @pixel_size: display pixel size
+ * @latency_ns: memory latency for the platform
+ *
+ * Calculate the watermark level (the level at which the display plane will
+ * start fetching from memory again).  Each chip has a different display
+ * FIFO size and allocation, so the caller needs to figure that out and pass
+ * in the correct intel_watermark_params structure.
+ *
+ * As the pixel clock runs, the FIFO will be drained at a rate that depends
+ * on the pixel size.  When it reaches the watermark level, it'll start
+ * fetching FIFO line sized based chunks from memory until the FIFO fills
+ * past the watermark point.  If the FIFO drains completely, a FIFO underrun
+ * will occur, and a display engine hang could result.
+ */
+static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
+					struct intel_watermark_params *wm,
+					int pixel_size,
+					unsigned long latency_ns)
+{
+	long entries_required, wm_size;
+
+	entries_required = (clock_in_khz * pixel_size * latency_ns) / 1000000;
+	entries_required /= wm->cacheline_size;
+
+	DRM_DEBUG("FIFO entries required for mode: %d\n", entries_required);
+
+	wm_size = wm->fifo_size - (entries_required + wm->guard_size);
+
+	DRM_DEBUG("FIFO watermark level: %d\n", wm_size);
+
+	/* Don't promote wm_size to unsigned... */
+	if (wm_size > (long)wm->max_wm)
+		wm_size = wm->max_wm;
+	if (wm_size <= 0)
+		wm_size = wm->default_wm;
+	return wm_size;
+}
+
+struct cxsr_latency {
+	int is_desktop;
+	unsigned long fsb_freq;
+	unsigned long mem_freq;
+	unsigned long display_sr;
+	unsigned long display_hpll_disable;
+	unsigned long cursor_sr;
+	unsigned long cursor_hpll_disable;
+};
+
+static struct cxsr_latency cxsr_latency_table[] = {
+	{1, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
+	{1, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
+	{1, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
+
+	{1, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
+	{1, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
+	{1, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
+
+	{1, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
+	{1, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
+	{1, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
+
+	{0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
+	{0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
+	{0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
+
+	{0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
+	{0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
+	{0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
+
+	{0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
+	{0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
+	{0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
+};
+
+static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
+						   int mem)
+{
+	int i;
+	struct cxsr_latency *latency;
+
+	if (fsb == 0 || mem == 0)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
+		latency = &cxsr_latency_table[i];
+		if (is_desktop == latency->is_desktop &&
+			fsb == latency->fsb_freq && mem == latency->mem_freq)
+			break;
+	}
+	if (i >= ARRAY_SIZE(cxsr_latency_table)) {
+		DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
+		return NULL;
+	}
+	return latency;
+}
+
+static void igd_disable_cxsr(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg;
+
+	/* deactivate cxsr */
+	reg = I915_READ(DSPFW3);
+	reg &= ~(IGD_SELF_REFRESH_EN);
+	I915_WRITE(DSPFW3, reg);
+	DRM_INFO("Big FIFO is disabled\n");
+}
+
+static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock,
+			    int pixel_size)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg;
+	unsigned long wm;
+	struct cxsr_latency *latency;
+
+	latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq,
+		dev_priv->mem_freq);
+	if (!latency) {
+		DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
+		igd_disable_cxsr(dev);
+		return;
+	}
+
+	/* Display SR */
+	wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size,
+				latency->display_sr);
+	reg = I915_READ(DSPFW1);
+	reg &= 0x7fffff;
+	reg |= wm << 23;
+	I915_WRITE(DSPFW1, reg);
+	DRM_DEBUG("DSPFW1 register is %x\n", reg);
+
+	/* cursor SR */
+	wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size,
+				latency->cursor_sr);
+	reg = I915_READ(DSPFW3);
+	reg &= ~(0x3f << 24);
+	reg |= (wm & 0x3f) << 24;
+	I915_WRITE(DSPFW3, reg);
+
+	/* Display HPLL off SR */
+	wm = intel_calculate_wm(clock, &igd_display_hplloff_wm,
+		latency->display_hpll_disable, I915_FIFO_LINE_SIZE);
+	reg = I915_READ(DSPFW3);
+	reg &= 0xfffffe00;
+	reg |= wm & 0x1ff;
+	I915_WRITE(DSPFW3, reg);
+
+	/* cursor HPLL off SR */
+	wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size,
+				latency->cursor_hpll_disable);
+	reg = I915_READ(DSPFW3);
+	reg &= ~(0x3f << 16);
+	reg |= (wm & 0x3f) << 16;
+	I915_WRITE(DSPFW3, reg);
+	DRM_DEBUG("DSPFW3 register is %x\n", reg);
+
+	/* activate cxsr */
+	reg = I915_READ(DSPFW3);
+	reg |= IGD_SELF_REFRESH_EN;
+	I915_WRITE(DSPFW3, reg);
+
+	DRM_INFO("Big FIFO is enabled\n");
+
+	return;
+}
+
+/*
+ * Latency for FIFO fetches is dependent on several factors:
+ *   - memory configuration (speed, channels)
+ *   - chipset
+ *   - current MCH state
+ * It can be fairly high in some situations, so here we assume a fairly
+ * pessimal value.  It's a tradeoff between extra memory fetches (if we
+ * set this value too high, the FIFO will fetch frequently to stay full)
+ * and power consumption (set it too low to save power and we might see
+ * FIFO underruns and display "flicker").
+ *
+ * A value of 5us seems to be a good balance; safe for very low end
+ * platforms but not overly aggressive on lower latency configs.
+ */
+const static int latency_ns = 5000;
+
+static int intel_get_fifo_size(struct drm_device *dev, int plane)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t dsparb = I915_READ(DSPARB);
+	int size;
+
+	if (IS_I9XX(dev)) {
+		if (plane == 0)
+			size = dsparb & 0x7f;
+		else
+			size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) -
+				(dsparb & 0x7f);
+	} else if (IS_I85X(dev)) {
+		if (plane == 0)
+			size = dsparb & 0x1ff;
+		else
+			size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) -
+				(dsparb & 0x1ff);
+		size >>= 1; /* Convert to cachelines */
+	} else if (IS_845G(dev)) {
+		size = dsparb & 0x7f;
+		size >>= 2; /* Convert to cachelines */
+	} else {
+		size = dsparb & 0x7f;
+		size >>= 1; /* Convert to cachelines */
+	}
+
+	DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A",
+		  size);
+
+	return size;
+}
+
+static void i965_update_wm(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n");
+
+	/* 965 has limitations... */
+	I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0));
+	I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
+}
+
+static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
+			   int planeb_clock, int sr_hdisplay, int pixel_size)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t fwater_lo;
+	uint32_t fwater_hi;
+	int total_size, cacheline_size, cwm, srwm = 1;
+	int planea_wm, planeb_wm;
+	struct intel_watermark_params planea_params, planeb_params;
+	unsigned long line_time_us;
+	int sr_clock, sr_entries = 0;
+
+	/* Create copies of the base settings for each pipe */
+	if (IS_I965GM(dev) || IS_I945GM(dev))
+		planea_params = planeb_params = i945_wm_info;
+	else if (IS_I9XX(dev))
+		planea_params = planeb_params = i915_wm_info;
+	else
+		planea_params = planeb_params = i855_wm_info;
+
+	/* Grab a couple of global values before we overwrite them */
+	total_size = planea_params.fifo_size;
+	cacheline_size = planea_params.cacheline_size;
+
+	/* Update per-plane FIFO sizes */
+	planea_params.fifo_size = intel_get_fifo_size(dev, 0);
+	planeb_params.fifo_size = intel_get_fifo_size(dev, 1);
+
+	planea_wm = intel_calculate_wm(planea_clock, &planea_params,
+				       pixel_size, latency_ns);
+	planeb_wm = intel_calculate_wm(planeb_clock, &planeb_params,
+				       pixel_size, latency_ns);
+	DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+
+	/*
+	 * Overlay gets an aggressive default since video jitter is bad.
+	 */
+	cwm = 2;
+
+	/* Calc sr entries for one plane configs */
+	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+		/* self-refresh has much higher latency */
+		const static int sr_latency_ns = 6000;
+
+		sr_clock = planea_clock ? planea_clock : planeb_clock;
+		line_time_us = ((sr_hdisplay * 1000) / sr_clock);
+
+		/* Use ns/us then divide to preserve precision */
+		sr_entries = (((sr_latency_ns / line_time_us) + 1) *
+			      pixel_size * sr_hdisplay) / 1000;
+		sr_entries = roundup(sr_entries / cacheline_size, 1);
+		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
+		srwm = total_size - sr_entries;
+		if (srwm < 0)
+			srwm = 1;
+		if (IS_I9XX(dev))
+			I915_WRITE(FW_BLC_SELF, (srwm & 0x3f));
+	}
+
+	DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
+		  planea_wm, planeb_wm, cwm, srwm);
+
+	fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f);
+	fwater_hi = (cwm & 0x1f);
+
+	/* Set request length to 8 cachelines per fetch */
+	fwater_lo = fwater_lo | (1 << 24) | (1 << 8);
+	fwater_hi = fwater_hi | (1 << 8);
+
+	I915_WRITE(FW_BLC, fwater_lo);
+	I915_WRITE(FW_BLC2, fwater_hi);
+}
+
+static void i830_update_wm(struct drm_device *dev, int planea_clock,
+			   int pixel_size)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff;
+	int planea_wm;
+
+	i830_wm_info.fifo_size = intel_get_fifo_size(dev, 0);
+
+	planea_wm = intel_calculate_wm(planea_clock, &i830_wm_info,
+				       pixel_size, latency_ns);
+	fwater_lo |= (3<<8) | planea_wm;
+
+	DRM_DEBUG("Setting FIFO watermarks - A: %d\n", planea_wm);
+
+	I915_WRITE(FW_BLC, fwater_lo);
+}
+
+/**
+ * intel_update_watermarks - update FIFO watermark values based on current modes
+ *
+ * Calculate watermark values for the various WM regs based on current mode
+ * and plane configuration.
+ *
+ * There are several cases to deal with here:
+ *   - normal (i.e. non-self-refresh)
+ *   - self-refresh (SR) mode
+ *   - lines are large relative to FIFO size (buffer can hold up to 2)
+ *   - lines are small relative to FIFO size (buffer can hold more than 2
+ *     lines), so need to account for TLB latency
+ *
+ *   The normal calculation is:
+ *     watermark = dotclock * bytes per pixel * latency
+ *   where latency is platform & configuration dependent (we assume pessimal
+ *   values here).
+ *
+ *   The SR calculation is:
+ *     watermark = (trunc(latency/line time)+1) * surface width *
+ *       bytes per pixel
+ *   where
+ *     line time = htotal / dotclock
+ *   and latency is assumed to be high, as above.
+ *
+ * The final value programmed to the register should always be rounded up,
+ * and include an extra 2 entries to account for clock crossings.
+ *
+ * We don't use the sprite, so we can ignore that.  And on Crestline we have
+ * to set the non-SR watermarks to 8.
+  */
+static void intel_update_watermarks(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+	struct intel_crtc *intel_crtc;
+	int sr_hdisplay = 0;
+	unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
+	int enabled = 0, pixel_size = 0;
+
+	if (DSPARB_HWCONTROL(dev))
+		return;
+
+	/* Get the clock config from both planes */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		intel_crtc = to_intel_crtc(crtc);
+		if (crtc->enabled) {
+			enabled++;
+			if (intel_crtc->plane == 0) {
+				DRM_DEBUG("plane A (pipe %d) clock: %d\n",
+					  intel_crtc->pipe, crtc->mode.clock);
+				planea_clock = crtc->mode.clock;
+			} else {
+				DRM_DEBUG("plane B (pipe %d) clock: %d\n",
+					  intel_crtc->pipe, crtc->mode.clock);
+				planeb_clock = crtc->mode.clock;
+			}
+			sr_hdisplay = crtc->mode.hdisplay;
+			sr_clock = crtc->mode.clock;
+			if (crtc->fb)
+				pixel_size = crtc->fb->bits_per_pixel / 8;
+			else
+				pixel_size = 4; /* by default */
+		}
+	}
+
+	if (enabled <= 0)
+		return;
+
+	/* Single plane configs can enable self refresh */
+	if (enabled == 1 && IS_IGD(dev))
+		igd_enable_cxsr(dev, sr_clock, pixel_size);
+	else if (IS_IGD(dev))
+		igd_disable_cxsr(dev);
+
+	if (IS_I965G(dev))
+		i965_update_wm(dev);
+	else if (IS_I9XX(dev) || IS_MOBILE(dev))
+		i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay,
+			       pixel_size);
+	else
+		i830_update_wm(dev, planea_clock, pixel_size);
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
@@ -1058,11 +2267,24 @@
 	intel_clock_t clock;
 	u32 dpll = 0, fp = 0, dspcntr, pipeconf;
 	bool ok, is_sdvo = false, is_dvo = false;
-	bool is_crt = false, is_lvds = false, is_tv = false;
+	bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
+	bool is_edp = false;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct drm_connector *connector;
 	const intel_limit_t *limit;
 	int ret;
+	struct fdi_m_n m_n = {0};
+	int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1;
+	int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1;
+	int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1;
+	int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1;
+	int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
+	int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
+	int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+	int lvds_reg = LVDS;
+	u32 temp;
+	int sdvo_pixel_multiply;
+	int target_clock;
 
 	drm_vblank_pre_modeset(dev, pipe);
 
@@ -1091,6 +2313,12 @@
 		case INTEL_OUTPUT_ANALOG:
 			is_crt = true;
 			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			is_edp = true;
+			break;
 		}
 
 		num_outputs++;
@@ -1101,9 +2329,12 @@
 		DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
 	} else if (IS_I9XX(dev)) {
 		refclk = 96000;
+		if (IS_IGDNG(dev))
+			refclk = 120000; /* 120Mhz refclk */
 	} else {
 		refclk = 48000;
 	}
+	
 
 	/*
 	 * Returns a set of divisors for the desired target clock with the given
@@ -1114,6 +2345,7 @@
 	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock);
 	if (!ok) {
 		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		drm_vblank_post_modeset(dev, pipe);
 		return -EINVAL;
 	}
 
@@ -1137,12 +2369,39 @@
 		}
 	}
 
+	/* FDI link */
+	if (IS_IGDNG(dev)) {
+		int lane, link_bw;
+		/* eDP doesn't require FDI link, so just set DP M/N
+		   according to current link config */
+		if (is_edp) {
+			struct drm_connector *edp;
+			target_clock = mode->clock;
+			edp = intel_pipe_get_output(crtc);
+			intel_edp_link_config(to_intel_output(edp),
+					&lane, &link_bw);
+		} else {
+			/* DP over FDI requires target mode clock
+			   instead of link clock */
+			if (is_dp)
+				target_clock = mode->clock;
+			else
+				target_clock = adjusted_mode->clock;
+			lane = 4;
+			link_bw = 270000;
+		}
+		igdng_compute_m_n(3, lane, target_clock,
+				  link_bw, &m_n);
+	}
+
 	if (IS_IGD(dev))
 		fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
 	else
 		fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 
-	dpll = DPLL_VGA_MODE_DIS;
+	if (!IS_IGDNG(dev))
+		dpll = DPLL_VGA_MODE_DIS;
+
 	if (IS_I9XX(dev)) {
 		if (is_lvds)
 			dpll |= DPLLB_MODE_LVDS;
@@ -1150,17 +2409,24 @@
 			dpll |= DPLLB_MODE_DAC_SERIAL;
 		if (is_sdvo) {
 			dpll |= DPLL_DVO_HIGH_SPEED;
-			if (IS_I945G(dev) || IS_I945GM(dev)) {
-				int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
+			sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
+			if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
 				dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-			}
+			else if (IS_IGDNG(dev))
+				dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
 		}
+		if (is_dp)
+			dpll |= DPLL_DVO_HIGH_SPEED;
 
 		/* compute bitmask from p1 value */
 		if (IS_IGD(dev))
 			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD;
-		else
+		else {
 			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+			/* also FPA1 */
+			if (IS_IGDNG(dev))
+				dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
+		}
 		switch (clock.p2) {
 		case 5:
 			dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
@@ -1175,7 +2441,7 @@
 			dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 			break;
 		}
-		if (IS_I965G(dev))
+		if (IS_I965G(dev) && !IS_IGDNG(dev))
 			dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
 	} else {
 		if (is_lvds) {
@@ -1207,10 +2473,14 @@
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
 
-	if (pipe == 0)
-		dspcntr |= DISPPLANE_SEL_PIPE_A;
-	else
-		dspcntr |= DISPPLANE_SEL_PIPE_B;
+	/* IGDNG's plane is forced to pipe, bit 24 is to
+	   enable color space conversion */
+	if (!IS_IGDNG(dev)) {
+		if (pipe == 0)
+			dspcntr |= DISPPLANE_SEL_PIPE_A;
+		else
+			dspcntr |= DISPPLANE_SEL_PIPE_B;
+	}
 
 	if (pipe == 0 && !IS_I965G(dev)) {
 		/* Enable pixel doubling when the dot clock is > 90% of the (display)
@@ -1231,14 +2501,21 @@
 
 
 	/* Disable the panel fitter if it was on our pipe */
-	if (intel_panel_fitter_pipe(dev) == pipe)
+	if (!IS_IGDNG(dev) && intel_panel_fitter_pipe(dev) == pipe)
 		I915_WRITE(PFIT_CONTROL, 0);
 
 	DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
 
+	/* assign to IGDNG registers */
+	if (IS_IGDNG(dev)) {
+		fp_reg = pch_fp_reg;
+		dpll_reg = pch_dpll_reg;
+	}
 
-	if (dpll & DPLL_VCO_ENABLE) {
+	if (is_edp) {
+		igdng_disable_pll_edp(crtc);
+	} else if ((dpll & DPLL_VCO_ENABLE)) {
 		I915_WRITE(fp_reg, fp);
 		I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
 		I915_READ(dpll_reg);
@@ -1250,8 +2527,12 @@
 	 * things on.
 	 */
 	if (is_lvds) {
-		u32 lvds = I915_READ(LVDS);
+		u32 lvds;
+
+		if (IS_IGDNG(dev))
+			lvds_reg = PCH_LVDS;
 
+		lvds = I915_READ(lvds_reg);
 		lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
 		/* Set the B0-B3 data pairs corresponding to whether we're going to
 		 * set the DPLLs for dual-channel mode or not.
@@ -1266,27 +2547,31 @@
 		 * panels behave in the two modes.
 		 */
 
-		I915_WRITE(LVDS, lvds);
-		I915_READ(LVDS);
+		I915_WRITE(lvds_reg, lvds);
+		I915_READ(lvds_reg);
 	}
+	if (is_dp)
+		intel_dp_set_m_n(crtc, mode, adjusted_mode);
 
-	I915_WRITE(fp_reg, fp);
-	I915_WRITE(dpll_reg, dpll);
-	I915_READ(dpll_reg);
-	/* Wait for the clocks to stabilize. */
-	udelay(150);
-
-	if (IS_I965G(dev)) {
-		int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
-		I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
-			   ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
-	} else {
-		/* write it again -- the BIOS does, after all */
+	if (!is_edp) {
+		I915_WRITE(fp_reg, fp);
 		I915_WRITE(dpll_reg, dpll);
+		I915_READ(dpll_reg);
+		/* Wait for the clocks to stabilize. */
+		udelay(150);
+
+		if (IS_I965G(dev) && !IS_IGDNG(dev)) {
+			sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
+			I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+					((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+		} else {
+			/* write it again -- the BIOS does, after all */
+			I915_WRITE(dpll_reg, dpll);
+		}
+		I915_READ(dpll_reg);
+		/* Wait for the clocks to stabilize. */
+		udelay(150);
 	}
-	I915_READ(dpll_reg);
-	/* Wait for the clocks to stabilize. */
-	udelay(150);
 
 	I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
 		   ((adjusted_mode->crtc_htotal - 1) << 16));
@@ -1303,9 +2588,29 @@
 	/* pipesrc and dspsize control the size that is scaled from, which should
 	 * always be the user's requested size.
 	 */
-	I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-	I915_WRITE(dsppos_reg, 0);
+	if (!IS_IGDNG(dev)) {
+		I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) |
+				(mode->hdisplay - 1));
+		I915_WRITE(dsppos_reg, 0);
+	}
 	I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+
+	if (IS_IGDNG(dev)) {
+		I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
+		I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
+		I915_WRITE(link_m1_reg, m_n.link_m);
+		I915_WRITE(link_n1_reg, m_n.link_n);
+
+		if (is_edp) {
+			igdng_set_pll_edp(crtc, adjusted_mode->clock);
+		} else {
+			/* enable FDI RX PLL too */
+			temp = I915_READ(fdi_rx_reg);
+			I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
+			udelay(200);
+		}
+	}
+
 	I915_WRITE(pipeconf_reg, pipeconf);
 	I915_READ(pipeconf_reg);
 
@@ -1315,12 +2620,12 @@
 
 	/* Flush the plane changes */
 	ret = intel_pipe_set_base(crtc, x, y, old_fb);
-	if (ret != 0)
-	    return ret;
+
+	intel_update_watermarks(dev);
 
 	drm_vblank_post_modeset(dev, pipe);
 
-	return 0;
+	return ret;
 }
 
 /** Loads the palette/gamma unit for the CRTC with the prepared values */
@@ -1336,6 +2641,11 @@
 	if (!crtc->enabled)
 		return;
 
+	/* use legacy palette for IGDNG */
+	if (IS_IGDNG(dev))
+		palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
+						   LGC_PALETTE_B;
+
 	for (i = 0; i < 256; i++) {
 		I915_WRITE(palreg + 4 * i,
 			   (intel_crtc->lut_r[i] << 16) |
@@ -1464,16 +2774,16 @@
 	uint32_t adder;
 
 	if (x < 0) {
-		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+		temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
 		x = -x;
 	}
 	if (y < 0) {
-		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+		temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
 		y = -y;
 	}
 
-	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
-	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+	temp |= x << CURSOR_X_SHIFT;
+	temp |= y << CURSOR_Y_SHIFT;
 
 	adder = intel_crtc->cursor_addr;
 	I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
@@ -1590,6 +2900,7 @@
 	}
 
 	encoder->crtc = crtc;
+	intel_output->base.encoder = encoder;
 	intel_output->load_detect_temp = true;
 
 	intel_crtc = to_intel_crtc(crtc);
@@ -1625,6 +2936,7 @@
 
 	if (intel_output->load_detect_temp) {
 		encoder->crtc = NULL;
+		intel_output->base.encoder = NULL;
 		intel_output->load_detect_temp = false;
 		crtc->enabled = drm_helper_crtc_in_use(crtc);
 		drm_helper_disable_unused_functions(dev);
@@ -1762,6 +3074,8 @@
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
+	if (intel_crtc->mode_set.mode)
+		drm_mode_destroy(crtc->dev, intel_crtc->mode_set.mode);
 	drm_crtc_cleanup(crtc);
 	kfree(intel_crtc);
 }
@@ -1797,6 +3111,7 @@
 
 	drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
 	intel_crtc->pipe = pipe;
+	intel_crtc->plane = pipe;
 	for (i = 0; i < 256; i++) {
 		intel_crtc->lut_r[i] = i;
 		intel_crtc->lut_g[i] = i;
@@ -1869,7 +3184,7 @@
 
         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct intel_output *intel_output = to_intel_output(connector);
-		if (type_mask & (1 << intel_output->type))
+		if (type_mask & intel_output->clone_mask)
 			index_mask |= (1 << entry);
 		entry++;
 	}
@@ -1888,72 +3203,74 @@
 	if (IS_MOBILE(dev) && !IS_I830(dev))
 		intel_lvds_init(dev);
 
-	if (IS_I9XX(dev)) {
+	if (IS_IGDNG(dev)) {
 		int found;
-		u32 reg;
+
+		if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
+			intel_dp_init(dev, DP_A);
+
+		if (I915_READ(HDMIB) & PORT_DETECTED) {
+			/* check SDVOB */
+			/* found = intel_sdvo_init(dev, HDMIB); */
+			found = 0;
+			if (!found)
+				intel_hdmi_init(dev, HDMIB);
+			if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
+				intel_dp_init(dev, PCH_DP_B);
+		}
+
+		if (I915_READ(HDMIC) & PORT_DETECTED)
+			intel_hdmi_init(dev, HDMIC);
+
+		if (I915_READ(HDMID) & PORT_DETECTED)
+			intel_hdmi_init(dev, HDMID);
+
+		if (I915_READ(PCH_DP_C) & DP_DETECTED)
+			intel_dp_init(dev, PCH_DP_C);
+
+		if (I915_READ(PCH_DP_D) & DP_DETECTED)
+			intel_dp_init(dev, PCH_DP_D);
+
+	} else if (IS_I9XX(dev)) {
+		bool found = false;
 
 		if (I915_READ(SDVOB) & SDVO_DETECTED) {
 			found = intel_sdvo_init(dev, SDVOB);
 			if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
 				intel_hdmi_init(dev, SDVOB);
+
+			if (!found && SUPPORTS_INTEGRATED_DP(dev))
+				intel_dp_init(dev, DP_B);
 		}
 
 		/* Before G4X SDVOC doesn't have its own detect register */
-		if (IS_G4X(dev))
-			reg = SDVOC;
-		else
-			reg = SDVOB;
 
-		if (I915_READ(reg) & SDVO_DETECTED) {
+		if (I915_READ(SDVOB) & SDVO_DETECTED)
 			found = intel_sdvo_init(dev, SDVOC);
-			if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+
+		if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
+
+			if (SUPPORTS_INTEGRATED_HDMI(dev))
 				intel_hdmi_init(dev, SDVOC);
+			if (SUPPORTS_INTEGRATED_DP(dev))
+				intel_dp_init(dev, DP_C);
 		}
+
+		if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
+			intel_dp_init(dev, DP_D);
 	} else
 		intel_dvo_init(dev);
 
-	if (IS_I9XX(dev) && IS_MOBILE(dev))
+	if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev))
 		intel_tv_init(dev);
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct intel_output *intel_output = to_intel_output(connector);
 		struct drm_encoder *encoder = &intel_output->enc;
-		int crtc_mask = 0, clone_mask = 0;
 
-		/* valid crtcs */
-		switch(intel_output->type) {
-		case INTEL_OUTPUT_HDMI:
-			crtc_mask = ((1 << 0)|
-				     (1 << 1));
-			clone_mask = ((1 << INTEL_OUTPUT_HDMI));
-			break;
-		case INTEL_OUTPUT_DVO:
-		case INTEL_OUTPUT_SDVO:
-			crtc_mask = ((1 << 0)|
-				     (1 << 1));
-			clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-				      (1 << INTEL_OUTPUT_DVO) |
-				      (1 << INTEL_OUTPUT_SDVO));
-			break;
-		case INTEL_OUTPUT_ANALOG:
-			crtc_mask = ((1 << 0)|
-				     (1 << 1));
-			clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-				      (1 << INTEL_OUTPUT_DVO) |
-				      (1 << INTEL_OUTPUT_SDVO));
-			break;
-		case INTEL_OUTPUT_LVDS:
-			crtc_mask = (1 << 1);
-			clone_mask = (1 << INTEL_OUTPUT_LVDS);
-			break;
-		case INTEL_OUTPUT_TVOUT:
-			crtc_mask = ((1 << 0) |
-				     (1 << 1));
-			clone_mask = (1 << INTEL_OUTPUT_TVOUT);
-			break;
-		}
-		encoder->possible_crtcs = crtc_mask;
-		encoder->possible_clones = intel_connector_clones(dev, clone_mask);
+		encoder->possible_crtcs = intel_output->crtc_mask;
+		encoder->possible_clones = intel_connector_clones(dev,
+						intel_output->clone_mask);
 	}
 }
 
@@ -2060,6 +3377,9 @@
 	if (IS_I965G(dev)) {
 		dev->mode_config.max_width = 8192;
 		dev->mode_config.max_height = 8192;
+	} else if (IS_I9XX(dev)) {
+		dev->mode_config.max_width = 4096;
+		dev->mode_config.max_height = 4096;
 	} else {
 		dev->mode_config.max_width = 2048;
 		dev->mode_config.max_height = 2048;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dp.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dp.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1330 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include <linux/i2c.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "intel_dp.h"
+
+#define DP_LINK_STATUS_SIZE	6
+#define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
+
+#define DP_LINK_CONFIGURATION_SIZE	9
+
+#define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
+
+struct intel_dp_priv {
+	uint32_t output_reg;
+	uint32_t DP;
+	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
+	uint32_t save_DP;
+	uint8_t  save_link_configuration[DP_LINK_CONFIGURATION_SIZE];
+	bool has_audio;
+	int dpms_mode;
+	uint8_t link_bw;
+	uint8_t lane_count;
+	uint8_t dpcd[4];
+	struct intel_output *intel_output;
+	struct i2c_adapter adapter;
+	struct i2c_algo_dp_aux_data algo;
+};
+
+static void
+intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+		    uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]);
+
+static void
+intel_dp_link_down(struct intel_output *intel_output, uint32_t DP);
+
+void
+intel_edp_link_config (struct intel_output *intel_output,
+		int *lane_num, int *link_bw)
+{
+	struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+
+	*lane_num = dp_priv->lane_count;
+	if (dp_priv->link_bw == DP_LINK_BW_1_62)
+		*link_bw = 162000;
+	else if (dp_priv->link_bw == DP_LINK_BW_2_7)
+		*link_bw = 270000;
+}
+
+static int
+intel_dp_max_lane_count(struct intel_output *intel_output)
+{
+	struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+	int max_lane_count = 4;
+
+	if (dp_priv->dpcd[0] >= 0x11) {
+		max_lane_count = dp_priv->dpcd[2] & 0x1f;
+		switch (max_lane_count) {
+		case 1: case 2: case 4:
+			break;
+		default:
+			max_lane_count = 4;
+		}
+	}
+	return max_lane_count;
+}
+
+static int
+intel_dp_max_link_bw(struct intel_output *intel_output)
+{
+	struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+	int max_link_bw = dp_priv->dpcd[1];
+
+	switch (max_link_bw) {
+	case DP_LINK_BW_1_62:
+	case DP_LINK_BW_2_7:
+		break;
+	default:
+		max_link_bw = DP_LINK_BW_1_62;
+		break;
+	}
+	return max_link_bw;
+}
+
+static int
+intel_dp_link_clock(uint8_t link_bw)
+{
+	if (link_bw == DP_LINK_BW_2_7)
+		return 270000;
+	else
+		return 162000;
+}
+
+/* I think this is a fiction */
+static int
+intel_dp_link_required(int pixel_clock)
+{
+	return pixel_clock * 3;
+}
+
+static int
+intel_dp_mode_valid(struct drm_connector *connector,
+		    struct drm_display_mode *mode)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output));
+	int max_lanes = intel_dp_max_lane_count(intel_output);
+
+	if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes)
+		return MODE_CLOCK_HIGH;
+
+	if (mode->clock < 10000)
+		return MODE_CLOCK_LOW;
+
+	return MODE_OK;
+}
+
+static uint32_t
+pack_aux(uint8_t *src, int src_bytes)
+{
+	int	i;
+	uint32_t v = 0;
+
+	if (src_bytes > 4)
+		src_bytes = 4;
+	for (i = 0; i < src_bytes; i++)
+		v |= ((uint32_t) src[i]) << ((3-i) * 8);
+	return v;
+}
+
+static void
+unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
+{
+	int i;
+	if (dst_bytes > 4)
+		dst_bytes = 4;
+	for (i = 0; i < dst_bytes; i++)
+		dst[i] = src >> ((3-i) * 8);
+}
+
+/* hrawclock is 1/4 the FSB frequency */
+static int
+intel_hrawclk(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t clkcfg;
+
+	clkcfg = I915_READ(CLKCFG);
+	switch (clkcfg & CLKCFG_FSB_MASK) {
+	case CLKCFG_FSB_400:
+		return 100;
+	case CLKCFG_FSB_533:
+		return 133;
+	case CLKCFG_FSB_667:
+		return 166;
+	case CLKCFG_FSB_800:
+		return 200;
+	case CLKCFG_FSB_1067:
+		return 266;
+	case CLKCFG_FSB_1333:
+		return 333;
+	/* these two are just a guess; one of them might be right */
+	case CLKCFG_FSB_1600:
+	case CLKCFG_FSB_1600_ALT:
+		return 400;
+	default:
+		return 133;
+	}
+}
+
+static int
+intel_dp_aux_ch(struct intel_output *intel_output,
+		uint8_t *send, int send_bytes,
+		uint8_t *recv, int recv_size)
+{
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	uint32_t output_reg = dp_priv->output_reg;
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t ch_ctl = output_reg + 0x10;
+	uint32_t ch_data = ch_ctl + 4;
+	int i;
+	int recv_bytes;
+	uint32_t ctl;
+	uint32_t status;
+	uint32_t aux_clock_divider;
+	int try;
+
+	/* The clock divider is based off the hrawclk,
+	 * and would like to run at 2MHz. So, take the
+	 * hrawclk value and divide by 2 and use that
+	 */
+	if (IS_eDP(intel_output))
+		aux_clock_divider = 225; /* eDP input clock at 450Mhz */
+	else if (IS_IGDNG(dev))
+		aux_clock_divider = 62; /* IGDNG: input clock fixed at 125Mhz */
+	else
+		aux_clock_divider = intel_hrawclk(dev) / 2;
+
+	/* Must try at least 3 times according to DP spec */
+	for (try = 0; try < 5; try++) {
+		/* Load the send data into the aux channel data registers */
+		for (i = 0; i < send_bytes; i += 4) {
+			uint32_t    d = pack_aux(send + i, send_bytes - i);;
+	
+			I915_WRITE(ch_data + i, d);
+		}
+	
+		ctl = (DP_AUX_CH_CTL_SEND_BUSY |
+		       DP_AUX_CH_CTL_TIME_OUT_400us |
+		       (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+		       (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+		       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
+		       DP_AUX_CH_CTL_DONE |
+		       DP_AUX_CH_CTL_TIME_OUT_ERROR |
+		       DP_AUX_CH_CTL_RECEIVE_ERROR);
+	
+		/* Send the command and wait for it to complete */
+		I915_WRITE(ch_ctl, ctl);
+		(void) I915_READ(ch_ctl);
+		for (;;) {
+			udelay(100);
+			status = I915_READ(ch_ctl);
+			if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+				break;
+		}
+	
+		/* Clear done status and any errors */
+		I915_WRITE(ch_ctl, (status |
+				DP_AUX_CH_CTL_DONE |
+				DP_AUX_CH_CTL_TIME_OUT_ERROR |
+				DP_AUX_CH_CTL_RECEIVE_ERROR));
+		(void) I915_READ(ch_ctl);
+		if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0)
+			break;
+	}
+
+	if ((status & DP_AUX_CH_CTL_DONE) == 0) {
+		DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status);
+		return -EBUSY;
+	}
+
+	/* Check for timeout or receive error.
+	 * Timeouts occur when the sink is not connected
+	 */
+	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+		DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status);
+		return -EIO;
+	}
+
+	/* Timeouts occur when the device isn't connected, so they're
+	 * "normal" -- don't fill the kernel log with these */
+	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
+		DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status);
+		return -ETIMEDOUT;
+	}
+
+	/* Unload any bytes sent back from the other side */
+	recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
+		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+
+	if (recv_bytes > recv_size)
+		recv_bytes = recv_size;
+	
+	for (i = 0; i < recv_bytes; i += 4) {
+		uint32_t    d = I915_READ(ch_data + i);
+
+		unpack_aux(d, recv + i, recv_bytes - i);
+	}
+
+	return recv_bytes;
+}
+
+/* Write data to the aux channel in native mode */
+static int
+intel_dp_aux_native_write(struct intel_output *intel_output,
+			  uint16_t address, uint8_t *send, int send_bytes)
+{
+	int ret;
+	uint8_t	msg[20];
+	int msg_bytes;
+	uint8_t	ack;
+
+	if (send_bytes > 16)
+		return -1;
+	msg[0] = AUX_NATIVE_WRITE << 4;
+	msg[1] = address >> 8;
+	msg[2] = address & 0xff;
+	msg[3] = send_bytes - 1;
+	memcpy(&msg[4], send, send_bytes);
+	msg_bytes = send_bytes + 4;
+	for (;;) {
+		ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1);
+		if (ret < 0)
+			return ret;
+		if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+			break;
+		else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+			udelay(100);
+		else
+			return -EIO;
+	}
+	return send_bytes;
+}
+
+/* Write a single byte to the aux channel in native mode */
+static int
+intel_dp_aux_native_write_1(struct intel_output *intel_output,
+			    uint16_t address, uint8_t byte)
+{
+	return intel_dp_aux_native_write(intel_output, address, &byte, 1);
+}
+
+/* read bytes from a native aux channel */
+static int
+intel_dp_aux_native_read(struct intel_output *intel_output,
+			 uint16_t address, uint8_t *recv, int recv_bytes)
+{
+	uint8_t msg[4];
+	int msg_bytes;
+	uint8_t reply[20];
+	int reply_bytes;
+	uint8_t ack;
+	int ret;
+
+	msg[0] = AUX_NATIVE_READ << 4;
+	msg[1] = address >> 8;
+	msg[2] = address & 0xff;
+	msg[3] = recv_bytes - 1;
+
+	msg_bytes = 4;
+	reply_bytes = recv_bytes + 1;
+
+	for (;;) {
+		ret = intel_dp_aux_ch(intel_output, msg, msg_bytes,
+				      reply, reply_bytes);
+		if (ret == 0)
+			return -EPROTO;
+		if (ret < 0)
+			return ret;
+		ack = reply[0];
+		if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+			memcpy(recv, reply + 1, ret - 1);
+			return ret - 1;
+		}
+		else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+			udelay(100);
+		else
+			return -EIO;
+	}
+}
+
+static int
+intel_dp_i2c_aux_ch(struct i2c_adapter *adapter,
+		    uint8_t *send, int send_bytes,
+		    uint8_t *recv, int recv_bytes)
+{
+	struct intel_dp_priv *dp_priv = container_of(adapter,
+						     struct intel_dp_priv,
+						     adapter);
+	struct intel_output *intel_output = dp_priv->intel_output;
+
+	return intel_dp_aux_ch(intel_output,
+			       send, send_bytes, recv, recv_bytes);
+}
+
+static int
+intel_dp_i2c_init(struct intel_output *intel_output, const char *name)
+{
+	struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+
+	DRM_ERROR("i2c_init %s\n", name);
+	dp_priv->algo.running = false;
+	dp_priv->algo.address = 0;
+	dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch;
+
+	memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter));
+	dp_priv->adapter.owner = THIS_MODULE;
+	dp_priv->adapter.class = I2C_CLASS_DDC;
+	strncpy (dp_priv->adapter.name, name, sizeof(dp_priv->adapter.name) - 1);
+	dp_priv->adapter.name[sizeof(dp_priv->adapter.name) - 1] = '\0';
+	dp_priv->adapter.algo_data = &dp_priv->algo;
+	dp_priv->adapter.dev.parent = &intel_output->base.kdev;
+	
+	return i2c_dp_aux_add_bus(&dp_priv->adapter);
+}
+
+static bool
+intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct intel_output *intel_output = enc_to_intel_output(encoder);
+	struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+	int lane_count, clock;
+	int max_lane_count = intel_dp_max_lane_count(intel_output);
+	int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0;
+	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+
+	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+		for (clock = 0; clock <= max_clock; clock++) {
+			int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+
+			if (intel_dp_link_required(mode->clock) <= link_avail) {
+				dp_priv->link_bw = bws[clock];
+				dp_priv->lane_count = lane_count;
+				adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+				DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n",
+				       dp_priv->link_bw, dp_priv->lane_count,
+				       adjusted_mode->clock);
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+struct intel_dp_m_n {
+	uint32_t	tu;
+	uint32_t	gmch_m;
+	uint32_t	gmch_n;
+	uint32_t	link_m;
+	uint32_t	link_n;
+};
+
+static void
+intel_reduce_ratio(uint32_t *num, uint32_t *den)
+{
+	while (*num > 0xffffff || *den > 0xffffff) {
+		*num >>= 1;
+		*den >>= 1;
+	}
+}
+
+static void
+intel_dp_compute_m_n(int bytes_per_pixel,
+		     int nlanes,
+		     int pixel_clock,
+		     int link_clock,
+		     struct intel_dp_m_n *m_n)
+{
+	m_n->tu = 64;
+	m_n->gmch_m = pixel_clock * bytes_per_pixel;
+	m_n->gmch_n = link_clock * nlanes;
+	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
+	m_n->link_m = pixel_clock;
+	m_n->link_n = link_clock;
+	intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
+}
+
+void
+intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		 struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *connector;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int lane_count = 4;
+	struct intel_dp_m_n m_n;
+
+	/*
+	 * Find the lane count in the intel_output private
+	 */
+	list_for_each_entry(connector, &mode_config->connector_list, head) {
+		struct intel_output *intel_output = to_intel_output(connector);
+		struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+		if (!connector->encoder || connector->encoder->crtc != crtc)
+			continue;
+
+		if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) {
+			lane_count = dp_priv->lane_count;
+			break;
+		}
+	}
+
+	/*
+	 * Compute the GMCH and Link ratios. The '3' here is
+	 * the number of bytes_per_pixel post-LUT, which we always
+	 * set up for 8-bits of R/G/B, or 3 bytes total.
+	 */
+	intel_dp_compute_m_n(3, lane_count,
+			     mode->clock, adjusted_mode->clock, &m_n);
+
+	if (IS_IGDNG(dev)) {
+		if (intel_crtc->pipe == 0) {
+			I915_WRITE(TRANSA_DATA_M1,
+				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+				   m_n.gmch_m);
+			I915_WRITE(TRANSA_DATA_N1, m_n.gmch_n);
+			I915_WRITE(TRANSA_DP_LINK_M1, m_n.link_m);
+			I915_WRITE(TRANSA_DP_LINK_N1, m_n.link_n);
+		} else {
+			I915_WRITE(TRANSB_DATA_M1,
+				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+				   m_n.gmch_m);
+			I915_WRITE(TRANSB_DATA_N1, m_n.gmch_n);
+			I915_WRITE(TRANSB_DP_LINK_M1, m_n.link_m);
+			I915_WRITE(TRANSB_DP_LINK_N1, m_n.link_n);
+		}
+	} else {
+		if (intel_crtc->pipe == 0) {
+			I915_WRITE(PIPEA_GMCH_DATA_M,
+				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+				   m_n.gmch_m);
+			I915_WRITE(PIPEA_GMCH_DATA_N,
+				   m_n.gmch_n);
+			I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m);
+			I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n);
+		} else {
+			I915_WRITE(PIPEB_GMCH_DATA_M,
+				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+				   m_n.gmch_m);
+			I915_WRITE(PIPEB_GMCH_DATA_N,
+					m_n.gmch_n);
+			I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m);
+			I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n);
+		}
+	}
+}
+
+static void
+intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		  struct drm_display_mode *adjusted_mode)
+{
+	struct intel_output *intel_output = enc_to_intel_output(encoder);
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	struct drm_crtc *crtc = intel_output->enc.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	dp_priv->DP = (DP_LINK_TRAIN_OFF |
+			DP_VOLTAGE_0_4 |
+			DP_PRE_EMPHASIS_0 |
+			DP_SYNC_VS_HIGH |
+			DP_SYNC_HS_HIGH);
+
+	switch (dp_priv->lane_count) {
+	case 1:
+		dp_priv->DP |= DP_PORT_WIDTH_1;
+		break;
+	case 2:
+		dp_priv->DP |= DP_PORT_WIDTH_2;
+		break;
+	case 4:
+		dp_priv->DP |= DP_PORT_WIDTH_4;
+		break;
+	}
+	if (dp_priv->has_audio)
+		dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE;
+
+	memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+	dp_priv->link_configuration[0] = dp_priv->link_bw;
+	dp_priv->link_configuration[1] = dp_priv->lane_count;
+
+	/*
+	 * Check for DPCD version > 1.1,
+	 * enable enahanced frame stuff in that case
+	 */
+	if (dp_priv->dpcd[0] >= 0x11) {
+		dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+		dp_priv->DP |= DP_ENHANCED_FRAMING;
+	}
+
+	if (intel_crtc->pipe == 1)
+		dp_priv->DP |= DP_PIPEB_SELECT;
+
+	if (IS_eDP(intel_output)) {
+		/* don't miss out required setting for eDP */
+		dp_priv->DP |= DP_PLL_ENABLE;
+		if (adjusted_mode->clock < 200000)
+			dp_priv->DP |= DP_PLL_FREQ_160MHZ;
+		else
+			dp_priv->DP |= DP_PLL_FREQ_270MHZ;
+	}
+}
+
+static void igdng_edp_backlight_on (struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp;
+
+	DRM_DEBUG("\n");
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp |= EDP_BLC_ENABLE;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
+static void igdng_edp_backlight_off (struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp;
+
+	DRM_DEBUG("\n");
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp &= ~EDP_BLC_ENABLE;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
+static void
+intel_dp_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct intel_output *intel_output = enc_to_intel_output(encoder);
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t dp_reg = I915_READ(dp_priv->output_reg);
+
+	if (mode != DRM_MODE_DPMS_ON) {
+		if (dp_reg & DP_PORT_EN) {
+			intel_dp_link_down(intel_output, dp_priv->DP);
+			if (IS_eDP(intel_output))
+				igdng_edp_backlight_off(dev);
+		}
+	} else {
+		if (!(dp_reg & DP_PORT_EN)) {
+			intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
+			if (IS_eDP(intel_output))
+				igdng_edp_backlight_on(dev);
+		}
+	}
+	dp_priv->dpms_mode = mode;
+}
+
+/*
+ * Fetch AUX CH registers 0x202 - 0x207 which contain
+ * link status information
+ */
+static bool
+intel_dp_get_link_status(struct intel_output *intel_output,
+			 uint8_t link_status[DP_LINK_STATUS_SIZE])
+{
+	int ret;
+
+	ret = intel_dp_aux_native_read(intel_output,
+				       DP_LANE0_1_STATUS,
+				       link_status, DP_LINK_STATUS_SIZE);
+	if (ret != DP_LINK_STATUS_SIZE)
+		return false;
+	return true;
+}
+
+static uint8_t
+intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+		     int r)
+{
+	return link_status[r - DP_LANE0_1_STATUS];
+}
+
+static void
+intel_dp_save(struct drm_connector *connector)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+	dp_priv->save_DP = I915_READ(dp_priv->output_reg);
+	intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET,
+				 dp_priv->save_link_configuration,
+				 sizeof (dp_priv->save_link_configuration));
+}
+
+static uint8_t
+intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+				 int lane)
+{
+	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int	    s = ((lane & 1) ?
+			 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+			 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+	uint8_t l = intel_dp_link_status(link_status, i);
+
+	return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+
+static uint8_t
+intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+				      int lane)
+{
+	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int	    s = ((lane & 1) ?
+			 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+			 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+	uint8_t l = intel_dp_link_status(link_status, i);
+
+	return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+
+
+#if 0
+static char	*voltage_names[] = {
+	"0.4V", "0.6V", "0.8V", "1.2V"
+};
+static char	*pre_emph_names[] = {
+	"0dB", "3.5dB", "6dB", "9.5dB"
+};
+static char	*link_train_names[] = {
+	"pattern 1", "pattern 2", "idle", "off"
+};
+#endif
+
+/*
+ * These are source-specific values; current Intel hardware supports
+ * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
+ */
+#define I830_DP_VOLTAGE_MAX	    DP_TRAIN_VOLTAGE_SWING_800
+
+static uint8_t
+intel_dp_pre_emphasis_max(uint8_t voltage_swing)
+{
+	switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+	case DP_TRAIN_VOLTAGE_SWING_400:
+		return DP_TRAIN_PRE_EMPHASIS_6;
+	case DP_TRAIN_VOLTAGE_SWING_600:
+		return DP_TRAIN_PRE_EMPHASIS_6;
+	case DP_TRAIN_VOLTAGE_SWING_800:
+		return DP_TRAIN_PRE_EMPHASIS_3_5;
+	case DP_TRAIN_VOLTAGE_SWING_1200:
+	default:
+		return DP_TRAIN_PRE_EMPHASIS_0;
+	}
+}
+
+static void
+intel_get_adjust_train(struct intel_output *intel_output,
+		       uint8_t link_status[DP_LINK_STATUS_SIZE],
+		       int lane_count,
+		       uint8_t train_set[4])
+{
+	uint8_t v = 0;
+	uint8_t p = 0;
+	int lane;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane);
+		uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane);
+
+		if (this_v > v)
+			v = this_v;
+		if (this_p > p)
+			p = this_p;
+	}
+
+	if (v >= I830_DP_VOLTAGE_MAX)
+		v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+
+	if (p >= intel_dp_pre_emphasis_max(v))
+		p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+	for (lane = 0; lane < 4; lane++)
+		train_set[lane] = v | p;
+}
+
+static uint32_t
+intel_dp_signal_levels(uint8_t train_set, int lane_count)
+{
+	uint32_t	signal_levels = 0;
+
+	switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
+	case DP_TRAIN_VOLTAGE_SWING_400:
+	default:
+		signal_levels |= DP_VOLTAGE_0_4;
+		break;
+	case DP_TRAIN_VOLTAGE_SWING_600:
+		signal_levels |= DP_VOLTAGE_0_6;
+		break;
+	case DP_TRAIN_VOLTAGE_SWING_800:
+		signal_levels |= DP_VOLTAGE_0_8;
+		break;
+	case DP_TRAIN_VOLTAGE_SWING_1200:
+		signal_levels |= DP_VOLTAGE_1_2;
+		break;
+	}
+	switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
+	case DP_TRAIN_PRE_EMPHASIS_0:
+	default:
+		signal_levels |= DP_PRE_EMPHASIS_0;
+		break;
+	case DP_TRAIN_PRE_EMPHASIS_3_5:
+		signal_levels |= DP_PRE_EMPHASIS_3_5;
+		break;
+	case DP_TRAIN_PRE_EMPHASIS_6:
+		signal_levels |= DP_PRE_EMPHASIS_6;
+		break;
+	case DP_TRAIN_PRE_EMPHASIS_9_5:
+		signal_levels |= DP_PRE_EMPHASIS_9_5;
+		break;
+	}
+	return signal_levels;
+}
+
+static uint8_t
+intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+		      int lane)
+{
+	int i = DP_LANE0_1_STATUS + (lane >> 1);
+	int s = (lane & 1) * 4;
+	uint8_t l = intel_dp_link_status(link_status, i);
+
+	return (l >> s) & 0xf;
+}
+
+/* Check for clock recovery is done on all channels */
+static bool
+intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+	int lane;
+	uint8_t lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = intel_get_lane_status(link_status, lane);
+		if ((lane_status & DP_LANE_CR_DONE) == 0)
+			return false;
+	}
+	return true;
+}
+
+/* Check to see if channel eq is done on all channels */
+#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
+			 DP_LANE_CHANNEL_EQ_DONE|\
+			 DP_LANE_SYMBOL_LOCKED)
+static bool
+intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+	uint8_t lane_align;
+	uint8_t lane_status;
+	int lane;
+
+	lane_align = intel_dp_link_status(link_status,
+					  DP_LANE_ALIGN_STATUS_UPDATED);
+	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
+		return false;
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = intel_get_lane_status(link_status, lane);
+		if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
+			return false;
+	}
+	return true;
+}
+
+static bool
+intel_dp_set_link_train(struct intel_output *intel_output,
+			uint32_t dp_reg_value,
+			uint8_t dp_train_pat,
+			uint8_t train_set[4],
+			bool first)
+{
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	int ret;
+
+	I915_WRITE(dp_priv->output_reg, dp_reg_value);
+	POSTING_READ(dp_priv->output_reg);
+	if (first)
+		intel_wait_for_vblank(dev);
+
+	intel_dp_aux_native_write_1(intel_output,
+				    DP_TRAINING_PATTERN_SET,
+				    dp_train_pat);
+
+	ret = intel_dp_aux_native_write(intel_output,
+					DP_TRAINING_LANE0_SET, train_set, 4);
+	if (ret != 4)
+		return false;
+
+	return true;
+}
+
+static void
+intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+		    uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE])
+{
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	uint8_t	train_set[4];
+	uint8_t link_status[DP_LINK_STATUS_SIZE];
+	int i;
+	uint8_t voltage;
+	bool clock_recovery = false;
+	bool channel_eq = false;
+	bool first = true;
+	int tries;
+
+	/* Write the link configuration data */
+	intel_dp_aux_native_write(intel_output, 0x100,
+				  link_configuration, DP_LINK_CONFIGURATION_SIZE);
+
+	DP |= DP_PORT_EN;
+	DP &= ~DP_LINK_TRAIN_MASK;
+	memset(train_set, 0, 4);
+	voltage = 0xff;
+	tries = 0;
+	clock_recovery = false;
+	for (;;) {
+		/* Use train_set[0] to set the voltage and pre emphasis values */
+		uint32_t    signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+		DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+
+		if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1,
+					     DP_TRAINING_PATTERN_1, train_set, first))
+			break;
+		first = false;
+		/* Set training pattern 1 */
+
+		udelay(100);
+		if (!intel_dp_get_link_status(intel_output, link_status))
+			break;
+
+		if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) {
+			clock_recovery = true;
+			break;
+		}
+
+		/* Check to see if we've tried the max voltage */
+		for (i = 0; i < dp_priv->lane_count; i++)
+			if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+				break;
+		if (i == dp_priv->lane_count)
+			break;
+
+		/* Check to see if we've tried the same voltage 5 times */
+		if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+			++tries;
+			if (tries == 5)
+				break;
+		} else
+			tries = 0;
+		voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+		/* Compute new train_set as requested by target */
+		intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+	}
+
+	/* channel equalization */
+	tries = 0;
+	channel_eq = false;
+	for (;;) {
+		/* Use train_set[0] to set the voltage and pre emphasis values */
+		uint32_t    signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+		DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+
+		/* channel eq pattern */
+		if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2,
+					     DP_TRAINING_PATTERN_2, train_set,
+					     false))
+			break;
+
+		udelay(400);
+		if (!intel_dp_get_link_status(intel_output, link_status))
+			break;
+
+		if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) {
+			channel_eq = true;
+			break;
+		}
+
+		/* Try 5 times */
+		if (tries > 5)
+			break;
+
+		/* Compute new train_set as requested by target */
+		intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+		++tries;
+	}
+
+	I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF);
+	POSTING_READ(dp_priv->output_reg);
+	intel_dp_aux_native_write_1(intel_output,
+				    DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
+}
+
+static void
+intel_dp_link_down(struct intel_output *intel_output, uint32_t DP)
+{
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+	DRM_DEBUG("\n");
+
+	if (IS_eDP(intel_output)) {
+		DP &= ~DP_PLL_ENABLE;
+		I915_WRITE(dp_priv->output_reg, DP);
+		POSTING_READ(dp_priv->output_reg);
+		udelay(100);
+	}
+
+	DP &= ~DP_LINK_TRAIN_MASK;
+	I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
+	POSTING_READ(dp_priv->output_reg);
+
+	udelay(17000);
+
+	if (IS_eDP(intel_output))
+		DP |= DP_LINK_TRAIN_OFF;
+	I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN);
+	POSTING_READ(dp_priv->output_reg);
+}
+
+static void
+intel_dp_restore(struct drm_connector *connector)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+	if (dp_priv->save_DP & DP_PORT_EN)
+		intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration);
+	else
+		intel_dp_link_down(intel_output,  dp_priv->save_DP);
+}
+
+/*
+ * According to DP spec
+ * 5.1.2:
+ *  1. Read DPCD
+ *  2. Configure link according to Receiver Capabilities
+ *  3. Use Link Training from 2.5.3.3 and 3.5.1.3
+ *  4. Check link status on receipt of hot-plug interrupt
+ */
+
+static void
+intel_dp_check_link_status(struct intel_output *intel_output)
+{
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+	if (!intel_output->enc.crtc)
+		return;
+
+	if (!intel_dp_get_link_status(intel_output, link_status)) {
+		intel_dp_link_down(intel_output, dp_priv->DP);
+		return;
+	}
+
+	if (!intel_channel_eq_ok(link_status, dp_priv->lane_count))
+		intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
+}
+
+static enum drm_connector_status
+igdng_dp_detect(struct drm_connector *connector)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	enum drm_connector_status status;
+
+	status = connector_status_disconnected;
+	if (intel_dp_aux_native_read(intel_output,
+				     0x000, dp_priv->dpcd,
+				     sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
+	{
+		if (dp_priv->dpcd[0] != 0)
+			status = connector_status_connected;
+	}
+	return status;
+}
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
+ *
+ * \return true if DP port is connected.
+ * \return false if DP port is disconnected.
+ */
+static enum drm_connector_status
+intel_dp_detect(struct drm_connector *connector)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+	uint32_t temp, bit;
+	enum drm_connector_status status;
+
+	dp_priv->has_audio = false;
+
+	if (IS_IGDNG(dev))
+		return igdng_dp_detect(connector);
+
+	temp = I915_READ(PORT_HOTPLUG_EN);
+
+	I915_WRITE(PORT_HOTPLUG_EN,
+	       temp |
+	       DPB_HOTPLUG_INT_EN |
+	       DPC_HOTPLUG_INT_EN |
+	       DPD_HOTPLUG_INT_EN);
+
+	POSTING_READ(PORT_HOTPLUG_EN);
+
+	switch (dp_priv->output_reg) {
+	case DP_B:
+		bit = DPB_HOTPLUG_INT_STATUS;
+		break;
+	case DP_C:
+		bit = DPC_HOTPLUG_INT_STATUS;
+		break;
+	case DP_D:
+		bit = DPD_HOTPLUG_INT_STATUS;
+		break;
+	default:
+		return connector_status_unknown;
+	}
+
+	temp = I915_READ(PORT_HOTPLUG_STAT);
+
+	if ((temp & bit) == 0)
+		return connector_status_disconnected;
+
+	status = connector_status_disconnected;
+	if (intel_dp_aux_native_read(intel_output,
+				     0x000, dp_priv->dpcd,
+				     sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
+	{
+		if (dp_priv->dpcd[0] != 0)
+			status = connector_status_connected;
+	}
+	return status;
+}
+
+static int intel_dp_get_modes(struct drm_connector *connector)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	struct drm_device *dev = intel_output->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	/* We should parse the EDID data and find out if it has an audio sink
+	 */
+
+	ret = intel_ddc_get_modes(intel_output);
+	if (ret)
+		return ret;
+
+	/* if eDP has no EDID, try to use fixed panel mode from VBT */
+	if (IS_eDP(intel_output)) {
+		if (dev_priv->panel_fixed_mode != NULL) {
+			struct drm_display_mode *mode;
+			mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
+			drm_mode_probed_add(connector, mode);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void
+intel_dp_destroy (struct drm_connector *connector)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+
+	if (intel_output->i2c_bus)
+		intel_i2c_destroy(intel_output->i2c_bus);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(intel_output);
+}
+
+static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
+	.dpms = intel_dp_dpms,
+	.mode_fixup = intel_dp_mode_fixup,
+	.prepare = intel_encoder_prepare,
+	.mode_set = intel_dp_mode_set,
+	.commit = intel_encoder_commit,
+};
+
+static const struct drm_connector_funcs intel_dp_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.save = intel_dp_save,
+	.restore = intel_dp_restore,
+	.detect = intel_dp_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = intel_dp_destroy,
+};
+
+static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
+	.get_modes = intel_dp_get_modes,
+	.mode_valid = intel_dp_mode_valid,
+	.best_encoder = intel_best_encoder,
+};
+
+static void intel_dp_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs intel_dp_enc_funcs = {
+	.destroy = intel_dp_enc_destroy,
+};
+
+void
+intel_dp_hot_plug(struct intel_output *intel_output)
+{
+	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+	if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
+		intel_dp_check_link_status(intel_output);
+}
+
+void
+intel_dp_init(struct drm_device *dev, int output_reg)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_connector *connector;
+	struct intel_output *intel_output;
+	struct intel_dp_priv *dp_priv;
+	const char *name = NULL;
+
+	intel_output = kcalloc(sizeof(struct intel_output) + 
+			       sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
+	if (!intel_output)
+		return;
+
+	dp_priv = (struct intel_dp_priv *)(intel_output + 1);
+
+	connector = &intel_output->base;
+	drm_connector_init(dev, connector, &intel_dp_connector_funcs,
+			   DRM_MODE_CONNECTOR_DisplayPort);
+	drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
+
+	if (output_reg == DP_A)
+		intel_output->type = INTEL_OUTPUT_EDP;
+	else
+		intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
+
+	if (output_reg == DP_B)
+		intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
+	else if (output_reg == DP_C)
+		intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
+	else if (output_reg == DP_D)
+		intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+
+	if (IS_eDP(intel_output)) {
+		intel_output->crtc_mask = (1 << 1);
+		intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
+	} else
+		intel_output->crtc_mask = (1 << 0) | (1 << 1);
+	connector->interlace_allowed = true;
+	connector->doublescan_allowed = 0;
+
+	dp_priv->intel_output = intel_output;
+	dp_priv->output_reg = output_reg;
+	dp_priv->has_audio = false;
+	dp_priv->dpms_mode = DRM_MODE_DPMS_ON;
+	intel_output->dev_priv = dp_priv;
+
+	drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs);
+
+	drm_mode_connector_attach_encoder(&intel_output->base,
+					  &intel_output->enc);
+	drm_sysfs_connector_add(connector);
+
+	/* Set up the DDC bus. */
+	switch (output_reg) {
+		case DP_A:
+			name = "DPDDC-A";
+			break;
+		case DP_B:
+		case PCH_DP_B:
+			name = "DPDDC-B";
+			break;
+		case DP_C:
+		case PCH_DP_C:
+			name = "DPDDC-C";
+			break;
+		case DP_D:
+		case PCH_DP_D:
+			name = "DPDDC-D";
+			break;
+	}
+
+	intel_dp_i2c_init(intel_output, name);
+
+	intel_output->ddc_bus = &dp_priv->adapter;
+	intel_output->hot_plug = intel_dp_hot_plug;
+
+	if (output_reg == DP_A) {
+		/* initialize panel mode from VBT if available for eDP */
+		if (dev_priv->lfp_lvds_vbt_mode) {
+			dev_priv->panel_fixed_mode =
+				drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+			if (dev_priv->panel_fixed_mode) {
+				dev_priv->panel_fixed_mode->type |=
+					DRM_MODE_TYPE_PREFERRED;
+			}
+		}
+	}
+
+	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
+	 * 0xd.  Failure to do so will result in spurious interrupts being
+	 * generated on the port when a cable is not attached.
+	 */
+	if (IS_G4X(dev) && !IS_GM45(dev)) {
+		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
+		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dp.h linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dp.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dp.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2008 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _INTEL_DP_H_
+#define _INTEL_DP_H_
+
+/* From the VESA DisplayPort spec */
+
+#define AUX_NATIVE_WRITE	0x8
+#define AUX_NATIVE_READ		0x9
+#define AUX_I2C_WRITE		0x0
+#define AUX_I2C_READ		0x1
+#define AUX_I2C_STATUS		0x2
+#define AUX_I2C_MOT		0x4
+
+#define AUX_NATIVE_REPLY_ACK	(0x0 << 4)
+#define AUX_NATIVE_REPLY_NACK	(0x1 << 4)
+#define AUX_NATIVE_REPLY_DEFER	(0x2 << 4)
+#define AUX_NATIVE_REPLY_MASK	(0x3 << 4)
+
+#define AUX_I2C_REPLY_ACK	(0x0 << 6)
+#define AUX_I2C_REPLY_NACK	(0x1 << 6)
+#define AUX_I2C_REPLY_DEFER	(0x2 << 6)
+#define AUX_I2C_REPLY_MASK	(0x3 << 6)
+
+/* AUX CH addresses */
+#define	DP_LINK_BW_SET		0x100
+# define DP_LINK_BW_1_62		    0x06
+# define DP_LINK_BW_2_7			    0x0a
+
+#define DP_LANE_COUNT_SET	0x101
+# define DP_LANE_COUNT_MASK		    0x0f
+# define DP_LANE_COUNT_ENHANCED_FRAME_EN    (1 << 7)
+
+#define DP_TRAINING_PATTERN_SET	0x102
+
+# define DP_TRAINING_PATTERN_DISABLE	    0
+# define DP_TRAINING_PATTERN_1		    1
+# define DP_TRAINING_PATTERN_2		    2
+# define DP_TRAINING_PATTERN_MASK	    0x3
+
+# define DP_LINK_QUAL_PATTERN_DISABLE	    (0 << 2)
+# define DP_LINK_QUAL_PATTERN_D10_2	    (1 << 2)
+# define DP_LINK_QUAL_PATTERN_ERROR_RATE    (2 << 2)
+# define DP_LINK_QUAL_PATTERN_PRBS7	    (3 << 2)
+# define DP_LINK_QUAL_PATTERN_MASK	    (3 << 2)
+
+# define DP_RECOVERED_CLOCK_OUT_EN	    (1 << 4)
+# define DP_LINK_SCRAMBLING_DISABLE	    (1 << 5)
+
+# define DP_SYMBOL_ERROR_COUNT_BOTH	    (0 << 6)
+# define DP_SYMBOL_ERROR_COUNT_DISPARITY    (1 << 6)
+# define DP_SYMBOL_ERROR_COUNT_SYMBOL	    (2 << 6)
+# define DP_SYMBOL_ERROR_COUNT_MASK	    (3 << 6)
+
+#define DP_TRAINING_LANE0_SET		    0x103
+#define DP_TRAINING_LANE1_SET		    0x104
+#define DP_TRAINING_LANE2_SET		    0x105
+#define DP_TRAINING_LANE3_SET		    0x106
+
+# define DP_TRAIN_VOLTAGE_SWING_MASK	    0x3
+# define DP_TRAIN_VOLTAGE_SWING_SHIFT	    0
+# define DP_TRAIN_MAX_SWING_REACHED	    (1 << 2)
+# define DP_TRAIN_VOLTAGE_SWING_400	    (0 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_600	    (1 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_800	    (2 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_1200	    (3 << 0)
+
+# define DP_TRAIN_PRE_EMPHASIS_MASK	    (3 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_0	    (0 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_3_5	    (1 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_6	    (2 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_9_5	    (3 << 3)
+
+# define DP_TRAIN_PRE_EMPHASIS_SHIFT	    3
+# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED  (1 << 5)
+
+#define DP_DOWNSPREAD_CTRL		    0x107
+# define DP_SPREAD_AMP_0_5		    (1 << 4)
+
+#define DP_MAIN_LINK_CHANNEL_CODING_SET	    0x108
+# define DP_SET_ANSI_8B10B		    (1 << 0)
+
+#define DP_LANE0_1_STATUS		    0x202
+#define DP_LANE2_3_STATUS		    0x203
+
+# define DP_LANE_CR_DONE		    (1 << 0)
+# define DP_LANE_CHANNEL_EQ_DONE	    (1 << 1)
+# define DP_LANE_SYMBOL_LOCKED		    (1 << 2)
+
+#define DP_LANE_ALIGN_STATUS_UPDATED	    0x204
+
+#define DP_INTERLANE_ALIGN_DONE		    (1 << 0)
+#define DP_DOWNSTREAM_PORT_STATUS_CHANGED   (1 << 6)
+#define DP_LINK_STATUS_UPDATED		    (1 << 7)
+
+#define DP_SINK_STATUS			    0x205
+
+#define DP_RECEIVE_PORT_0_STATUS	    (1 << 0)
+#define DP_RECEIVE_PORT_1_STATUS	    (1 << 1)
+
+#define DP_ADJUST_REQUEST_LANE0_1	    0x206
+#define DP_ADJUST_REQUEST_LANE2_3	    0x207
+
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK  0x03
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK   0x0c
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT  2
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK  0x30
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK   0xc0
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT  6
+
+struct i2c_algo_dp_aux_data {
+	bool running;
+	u16 address;
+	int (*aux_ch) (struct i2c_adapter *adapter,
+		       uint8_t *send, int send_bytes,
+		       uint8_t *recv, int recv_bytes);
+};
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
+
+#endif /* _INTEL_DP_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dp_i2c.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dp_i2c.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dp_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dp_i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,273 @@
+/*
+ * Copyright © 2009 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include "intel_dp.h"
+#include "drmP.h"
+
+/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
+
+#define MODE_I2C_START	1
+#define MODE_I2C_WRITE	2
+#define MODE_I2C_READ	4
+#define MODE_I2C_STOP	8
+
+static int
+i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
+			    uint8_t write_byte, uint8_t *read_byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	uint16_t address = algo_data->address;
+	uint8_t msg[5];
+	uint8_t reply[2];
+	int msg_bytes;
+	int reply_bytes;
+	int ret;
+
+	/* Set up the command byte */
+	if (mode & MODE_I2C_READ)
+		msg[0] = AUX_I2C_READ << 4;
+	else
+		msg[0] = AUX_I2C_WRITE << 4;
+
+	if (!(mode & MODE_I2C_STOP))
+		msg[0] |= AUX_I2C_MOT << 4;
+
+	msg[1] = address >> 8;
+	msg[2] = address;
+
+	switch (mode) {
+	case MODE_I2C_WRITE:
+		msg[3] = 0;
+		msg[4] = write_byte;
+		msg_bytes = 5;
+		reply_bytes = 1;
+		break;
+	case MODE_I2C_READ:
+		msg[3] = 0;
+		msg_bytes = 4;
+		reply_bytes = 2;
+		break;
+	default:
+		msg_bytes = 3;
+		reply_bytes = 1;
+		break;
+	}
+
+	for (;;) {
+		ret = (*algo_data->aux_ch)(adapter,
+					   msg, msg_bytes,
+					   reply, reply_bytes);
+		if (ret < 0) {
+			DRM_DEBUG("aux_ch failed %d\n", ret);
+			return ret;
+		}
+		switch (reply[0] & AUX_I2C_REPLY_MASK) {
+		case AUX_I2C_REPLY_ACK:
+			if (mode == MODE_I2C_READ) {
+				*read_byte = reply[1];
+			}
+			return reply_bytes - 1;
+		case AUX_I2C_REPLY_NACK:
+			DRM_DEBUG("aux_ch nack\n");
+			return -EREMOTEIO;
+		case AUX_I2C_REPLY_DEFER:
+			DRM_DEBUG("aux_ch defer\n");
+			udelay(100);
+			break;
+		default:
+			DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
+			return -EREMOTEIO;
+		}
+	}
+}
+
+/*
+ * I2C over AUX CH
+ */
+
+/*
+ * Send the address. If the I2C link is running, this 'restarts'
+ * the connection with the new address, this is used for doing
+ * a write followed by a read (as needed for DDC)
+ */
+static int
+i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int mode = MODE_I2C_START;
+	int ret;
+
+	if (reading)
+		mode |= MODE_I2C_READ;
+	else
+		mode |= MODE_I2C_WRITE;
+	algo_data->address = address;
+	algo_data->running = true;
+	ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+	return ret;
+}
+
+/*
+ * Stop the I2C transaction. This closes out the link, sending
+ * a bare address packet with the MOT bit turned off
+ */
+static void
+i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int mode = MODE_I2C_STOP;
+
+	if (reading)
+		mode |= MODE_I2C_READ;
+	else
+		mode |= MODE_I2C_WRITE;
+	if (algo_data->running) {
+		(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+		algo_data->running = false;
+	}
+}
+
+/*
+ * Write a single byte to the current I2C address, the
+ * the I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+
+	if (!algo_data->running)
+		return -EIO;
+
+	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
+	return ret;
+}
+
+/*
+ * Read a single byte from the current I2C address, the
+ * I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+
+	if (!algo_data->running)
+		return -EIO;
+
+	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
+	return ret;
+}
+
+static int
+i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
+		     struct i2c_msg *msgs,
+		     int num)
+{
+	int ret = 0;
+	bool reading = false;
+	int m;
+	int b;
+
+	for (m = 0; m < num; m++) {
+		u16 len = msgs[m].len;
+		u8 *buf = msgs[m].buf;
+		reading = (msgs[m].flags & I2C_M_RD) != 0;
+		ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
+		if (ret < 0)
+			break;
+		if (reading) {
+			for (b = 0; b < len; b++) {
+				ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
+				if (ret < 0)
+					break;
+			}
+		} else {
+			for (b = 0; b < len; b++) {
+				ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
+				if (ret < 0)
+					break;
+			}
+		}
+		if (ret < 0)
+			break;
+	}
+	if (ret >= 0)
+		ret = num;
+	i2c_algo_dp_aux_stop(adapter, reading);
+	DRM_DEBUG("dp_aux_xfer return %d\n", ret);
+	return ret;
+}
+
+static u32
+i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+	       I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm i2c_dp_aux_algo = {
+	.master_xfer	= i2c_algo_dp_aux_xfer,
+	.functionality	= i2c_algo_dp_aux_functionality,
+};
+
+static void
+i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
+{
+	(void) i2c_algo_dp_aux_address(adapter, 0, false);
+	(void) i2c_algo_dp_aux_stop(adapter, false);
+					   
+}
+
+static int
+i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
+{
+	adapter->algo = &i2c_dp_aux_algo;
+	adapter->retries = 3;
+	i2c_dp_aux_reset_bus(adapter);
+	return 0;
+}
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
+{
+	int error;
+	
+	error = i2c_dp_aux_prepare_bus(adapter);
+	if (error)
+		return error;
+	error = i2c_add_adapter(adapter);
+	return error;
+}
+EXPORT_SYMBOL(i2c_dp_aux_add_bus);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_drv.h linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_drv.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_drv.h	2009-09-09 18:13:59.000000000 -0400
@@ -54,6 +54,27 @@
 #define INTEL_OUTPUT_LVDS 4
 #define INTEL_OUTPUT_TVOUT 5
 #define INTEL_OUTPUT_HDMI 6
+#define INTEL_OUTPUT_DISPLAYPORT 7
+#define INTEL_OUTPUT_EDP 8
+
+/* Intel Pipe Clone Bit */
+#define INTEL_HDMIB_CLONE_BIT 1
+#define INTEL_HDMIC_CLONE_BIT 2
+#define INTEL_HDMID_CLONE_BIT 3
+#define INTEL_HDMIE_CLONE_BIT 4
+#define INTEL_HDMIF_CLONE_BIT 5
+#define INTEL_SDVO_NON_TV_CLONE_BIT 6
+#define INTEL_SDVO_TV_CLONE_BIT 7
+#define INTEL_SDVO_LVDS_CLONE_BIT 8
+#define INTEL_ANALOG_CLONE_BIT 9
+#define INTEL_TV_CLONE_BIT 10
+#define INTEL_DP_B_CLONE_BIT 11
+#define INTEL_DP_C_CLONE_BIT 12
+#define INTEL_DP_D_CLONE_BIT 13
+#define INTEL_LVDS_CLONE_BIT 14
+#define INTEL_DVO_TMDS_CLONE_BIT 15
+#define INTEL_DVO_LVDS_CLONE_BIT 16
+#define INTEL_EDP_CLONE_BIT 17
 
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
@@ -65,7 +86,6 @@
 	u32 reg; /* GPIO reg */
 	struct i2c_adapter adapter;
 	struct i2c_algo_bit_data algo;
-        u8 slave_addr;
 };
 
 struct intel_framebuffer {
@@ -79,11 +99,14 @@
 
 	struct drm_encoder enc;
 	int type;
-	struct intel_i2c_chan *i2c_bus; /* for control functions */
-	struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */
+	struct i2c_adapter *i2c_bus;
+	struct i2c_adapter *ddc_bus;
 	bool load_detect_temp;
 	bool needs_tv_clock;
 	void *dev_priv;
+	void (*hot_plug)(struct intel_output *);
+	int crtc_mask;
+	int clone_mask;
 };
 
 struct intel_crtc {
@@ -104,9 +127,9 @@
 #define enc_to_intel_output(x) container_of(x, struct intel_output, enc)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 
-struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
-					const char *name);
-void intel_i2c_destroy(struct intel_i2c_chan *chan);
+struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+				     const char *name);
+void intel_i2c_destroy(struct i2c_adapter *adapter);
 int intel_ddc_get_modes(struct intel_output *intel_output);
 extern bool intel_ddc_probe(struct intel_output *intel_output);
 void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
@@ -116,6 +139,12 @@
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
 extern void intel_lvds_init(struct drm_device *dev);
+extern void intel_dp_init(struct drm_device *dev, int dp_reg);
+void
+intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		 struct drm_display_mode *adjusted_mode);
+extern void intel_edp_link_config (struct intel_output *, int *, int *);
+
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dvo.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dvo.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_dvo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_dvo.c	2009-09-09 18:13:59.000000000 -0400
@@ -384,10 +384,9 @@
 {
 	struct intel_output *intel_output;
 	struct intel_dvo_device *dvo;
-	struct intel_i2c_chan *i2cbus = NULL;
+	struct i2c_adapter *i2cbus = NULL;
 	int ret = 0;
 	int i;
-	int gpio_inited = 0;
 	int encoder_type = DRM_MODE_ENCODER_NONE;
 	intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL);
 	if (!intel_output)
@@ -420,14 +419,11 @@
 		 * It appears that everything is on GPIOE except for panels
 		 * on i830 laptops, which are on GPIOB (DVOA).
 		 */
-		if (gpio_inited != gpio) {
-			if (i2cbus != NULL)
-				intel_i2c_destroy(i2cbus);
-			if (!(i2cbus = intel_i2c_create(dev, gpio,
-				gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
-				continue;
-			}
-			gpio_inited = gpio;
+		if (i2cbus != NULL)
+			intel_i2c_destroy(i2cbus);
+		if (!(i2cbus = intel_i2c_create(dev, gpio,
+			gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
+			continue;
 		}
 
 		if (dvo->dev_ops!= NULL)
@@ -439,14 +435,20 @@
 			continue;
 
 		intel_output->type = INTEL_OUTPUT_DVO;
+		intel_output->crtc_mask = (1 << 0) | (1 << 1);
 		switch (dvo->type) {
 		case INTEL_DVO_CHIP_TMDS:
+			intel_output->clone_mask =
+				(1 << INTEL_DVO_TMDS_CLONE_BIT) |
+				(1 << INTEL_ANALOG_CLONE_BIT);
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_DVII);
 			encoder_type = DRM_MODE_ENCODER_TMDS;
 			break;
 		case INTEL_DVO_CHIP_LVDS:
+			intel_output->clone_mask =
+				(1 << INTEL_DVO_LVDS_CLONE_BIT);
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_LVDS);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_fb.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_fb.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_fb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_fb.c	2009-09-09 18:13:59.000000000 -0400
@@ -207,7 +207,7 @@
 
 	if (var->pixclock != -1) {
 
-		DRM_ERROR("PIXEL CLCOK SET\n");
+		DRM_ERROR("PIXEL CLOCK SET\n");
 		return -EINVAL;
 	} else {
 		struct drm_crtc *crtc;
@@ -453,7 +453,7 @@
 	size = ALIGN(size, PAGE_SIZE);
 	fbo = drm_gem_object_alloc(dev, size);
 	if (!fbo) {
-		printk(KERN_ERR "failed to allocate framebuffer\n");
+		DRM_ERROR("failed to allocate framebuffer\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -504,6 +504,14 @@
 	info->fbops = &intelfb_ops;
 
 	info->fix.line_length = fb->pitch;
+
+	/* setup aperture base/size for vesafb takeover */
+	info->aperture_base = dev->mode_config.fb_base;
+	if (IS_I9XX(dev))
+		info->aperture_size = pci_resource_len(dev->pdev, 2);
+	else
+		info->aperture_size = pci_resource_len(dev->pdev, 0);
+
 	info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset;
 	info->fix.smem_len = size;
 
@@ -602,8 +610,8 @@
 	par->dev = dev;
 
 	/* To allow resizeing without swapping buffers */
-	printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
-	       intel_fb->base.height, obj_priv->gtt_offset, fbo);
+	DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
+		  intel_fb->base.height, obj_priv->gtt_offset, fbo);
 
 	mutex_unlock(&dev->struct_mutex);
 	return 0;
@@ -674,8 +682,12 @@
 	par->crtc_ids[0] = crtc->base.id;
 
 	modeset->num_connectors = conn_count;
-	if (modeset->mode != modeset->crtc->desired_mode)
-		modeset->mode = modeset->crtc->desired_mode;
+	if (modeset->crtc->desired_mode) {
+		if (modeset->mode)
+			drm_mode_destroy(dev, modeset->mode);
+		modeset->mode = drm_mode_duplicate(dev,
+						   modeset->crtc->desired_mode);
+	}
 
 	par->crtc_count = 1;
 
@@ -686,13 +698,13 @@
 	} else
 		intelfb_set_par(info);
 
-	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+	DRM_INFO("fb%d: %s frame buffer device\n", info->node,
 	       info->fix.id);
 
 	/* Switch back to kernel console on panic */
 	kernelfb_mode = *modeset;
 	atomic_notifier_chain_register(&panic_notifier_list, &paniced);
-	printk(KERN_INFO "registered panic notifier\n");
+	DRM_DEBUG("registered panic notifier\n");
 
 	return 0;
 }
@@ -824,8 +836,12 @@
 		par->crtc_ids[crtc_count++] = crtc->base.id;
 
 		modeset->num_connectors = conn_count;
-		if (modeset->mode != modeset->crtc->desired_mode)
-			modeset->mode = modeset->crtc->desired_mode;
+		if (modeset->crtc->desired_mode) {
+			if (modeset->mode)
+				drm_mode_destroy(dev, modeset->mode);
+			modeset->mode = drm_mode_duplicate(dev,
+							   modeset->crtc->desired_mode);
+		}
 	}
 	par->crtc_count = crtc_count;
 
@@ -836,13 +852,13 @@
 	} else
 		intelfb_set_par(info);
 
-	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+	DRM_INFO("fb%d: %s frame buffer device\n", info->node,
 	       info->fix.id);
 
 	/* Switch back to kernel console on panic */
 	kernelfb_mode = *modeset;
 	atomic_notifier_chain_register(&panic_notifier_list, &paniced);
-	printk(KERN_INFO "registered panic notifier\n");
+	DRM_DEBUG("registered panic notifier\n");
 
 	return 0;
 }
@@ -854,12 +870,22 @@
  */
 void intelfb_restore(void)
 {
-	drm_crtc_helper_set_config(&kernelfb_mode);
+	int ret;
+	if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) {
+		DRM_ERROR("Failed to restore crtc configuration: %d\n",
+			  ret);
+	}
 }
 
+static void intelfb_restore_work_fn(struct work_struct *ignored)
+{
+	intelfb_restore();
+}
+static DECLARE_WORK(intelfb_restore_work, intelfb_restore_work_fn);
+
 static void intelfb_sysrq(int dummy1, struct tty_struct *dummy3)
 {
-        intelfb_restore();
+        schedule_work(&intelfb_restore_work);
 }
 
 static struct sysrq_key_op sysrq_intelfb_restore_op = {
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
+#include "drm_edid.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
@@ -128,64 +129,28 @@
 	return true;
 }
 
-static void
-intel_hdmi_sink_detect(struct drm_connector *connector)
-{
-	struct intel_output *intel_output = to_intel_output(connector);
-	struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
-	struct edid *edid = NULL;
-
-	edid = drm_get_edid(&intel_output->base,
-			    &intel_output->ddc_bus->adapter);
-	if (edid != NULL) {
-		hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
-		kfree(edid);
-		intel_output->base.display_info.raw_edid = NULL;
-	}
-}
-
 static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector)
 {
-	struct drm_device *dev = connector->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_output *intel_output = to_intel_output(connector);
 	struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
-	u32 temp, bit;
-
-	temp = I915_READ(PORT_HOTPLUG_EN);
-
-	switch (hdmi_priv->sdvox_reg) {
-	case SDVOB:
-		temp |= HDMIB_HOTPLUG_INT_EN;
-		break;
-	case SDVOC:
-		temp |= HDMIC_HOTPLUG_INT_EN;
-		break;
-	default:
-		return connector_status_unknown;
-	}
-
-	I915_WRITE(PORT_HOTPLUG_EN, temp);
+	struct edid *edid = NULL;
+	enum drm_connector_status status = connector_status_disconnected;
 
-	POSTING_READ(PORT_HOTPLUG_EN);
+	hdmi_priv->has_hdmi_sink = false;
+	edid = drm_get_edid(&intel_output->base,
+			    intel_output->ddc_bus);
 
-	switch (hdmi_priv->sdvox_reg) {
-	case SDVOB:
-		bit = HDMIB_HOTPLUG_INT_STATUS;
-		break;
-	case SDVOC:
-		bit = HDMIC_HOTPLUG_INT_STATUS;
-		break;
-	default:
-		return connector_status_unknown;
+	if (edid) {
+		if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+			status = connector_status_connected;
+			hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+		}
+		intel_output->base.display_info.raw_edid = NULL;
+		kfree(edid);
 	}
 
-	if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) {
-		intel_hdmi_sink_detect(connector);
-		return connector_status_connected;
-	} else
-		return connector_status_disconnected;
+	return status;
 }
 
 static int intel_hdmi_get_modes(struct drm_connector *connector)
@@ -265,13 +230,28 @@
 
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
+	intel_output->crtc_mask = (1 << 0) | (1 << 1);
 
 	/* Set up the DDC bus. */
-	if (sdvox_reg == SDVOB)
+	if (sdvox_reg == SDVOB) {
+		intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
 		intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
-	else
+	} else if (sdvox_reg == SDVOC) {
+		intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
 		intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
-
+	} else if (sdvox_reg == HDMIB) {
+		intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
+		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
+								"HDMIB");
+	} else if (sdvox_reg == HDMIC) {
+		intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
+		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
+								"HDMIC");
+	} else if (sdvox_reg == HDMID) {
+		intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
+		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
+								"HDMID");
+	}
 	if (!intel_output->ddc_bus)
 		goto err_connector;
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_i2c.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -124,6 +124,7 @@
  * @output: driver specific output device
  * @reg: GPIO reg to use
  * @name: name for this bus
+ * @slave_addr: slave address (if fixed)
  *
  * Creates and registers a new i2c bus with the Linux i2c layer, for use
  * in output probing and control (e.g. DDC or SDVO control functions).
@@ -139,8 +140,8 @@
  *   %GPIOH
  * see PRM for details on how these different busses are used.
  */
-struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
-					const char *name)
+struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+				     const char *name)
 {
 	struct intel_i2c_chan *chan;
 
@@ -174,7 +175,7 @@
 	intel_i2c_quirk_set(dev, false);
 	udelay(20);
 
-	return chan;
+	return &chan->adapter;
 
 out_free:
 	kfree(chan);
@@ -187,11 +188,16 @@
  *
  * Unregister the adapter from the i2c layer, then free the structure.
  */
-void intel_i2c_destroy(struct intel_i2c_chan *chan)
+void intel_i2c_destroy(struct i2c_adapter *adapter)
 {
-	if (!chan)
+	struct intel_i2c_chan *chan;
+
+	if (!adapter)
 		return;
 
+	chan = container_of(adapter,
+			    struct intel_i2c_chan,
+			    adapter);
 	i2c_del_adapter(&chan->adapter);
 	kfree(chan);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_lvds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_lvds.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,24 @@
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
+#include <linux/acpi.h>
+
+#define I915_LVDS "i915_lvds"
+
+/*
+ * the following four scaling options are defined.
+ * #define DRM_MODE_SCALE_NON_GPU	0
+ * #define DRM_MODE_SCALE_FULLSCREEN	1
+ * #define DRM_MODE_SCALE_NO_SCALE	2
+ * #define DRM_MODE_SCALE_ASPECT	3
+ */
+
+/* Private structure for the integrated LVDS support */
+struct intel_lvds_priv {
+	int fitting_mode;
+	u32 pfit_control;
+	u32 pfit_pgm_ratios;
+};
 
 /**
  * Sets the backlight level.
@@ -45,10 +63,15 @@
 static void intel_lvds_set_backlight(struct drm_device *dev, int level)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 blc_pwm_ctl;
+	u32 blc_pwm_ctl, reg;
 
-	blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
-	I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
+	if (IS_IGDNG(dev))
+		reg = BLC_PWM_CPU_CTL;
+	else
+		reg = BLC_PWM_CTL;
+
+	blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+	I915_WRITE(reg, (blc_pwm_ctl |
 				 (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
 }
 
@@ -58,8 +81,14 @@
 static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg;
 
-	return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
+	if (IS_IGDNG(dev))
+		reg = BLC_PWM_PCH_CTL2;
+	else
+		reg = BLC_PWM_CTL;
+
+	return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >>
 		BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
 }
 
@@ -69,23 +98,31 @@
 static void intel_lvds_set_power(struct drm_device *dev, bool on)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pp_status;
+	u32 pp_status, ctl_reg, status_reg;
+
+	if (IS_IGDNG(dev)) {
+		ctl_reg = PCH_PP_CONTROL;
+		status_reg = PCH_PP_STATUS;
+	} else {
+		ctl_reg = PP_CONTROL;
+		status_reg = PP_STATUS;
+	}
 
 	if (on) {
-		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
+		I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
 			   POWER_TARGET_ON);
 		do {
-			pp_status = I915_READ(PP_STATUS);
+			pp_status = I915_READ(status_reg);
 		} while ((pp_status & PP_ON) == 0);
 
 		intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
 	} else {
 		intel_lvds_set_backlight(dev, 0);
 
-		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) &
+		I915_WRITE(ctl_reg, I915_READ(ctl_reg) &
 			   ~POWER_TARGET_ON);
 		do {
-			pp_status = I915_READ(PP_STATUS);
+			pp_status = I915_READ(status_reg);
 		} while (pp_status & PP_ON);
 	}
 }
@@ -106,12 +143,28 @@
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
+	u32 pwm_ctl_reg;
 
-	dev_priv->savePP_ON = I915_READ(PP_ON_DELAYS);
-	dev_priv->savePP_OFF = I915_READ(PP_OFF_DELAYS);
-	dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
-	dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
-	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+	if (IS_IGDNG(dev)) {
+		pp_on_reg = PCH_PP_ON_DELAYS;
+		pp_off_reg = PCH_PP_OFF_DELAYS;
+		pp_ctl_reg = PCH_PP_CONTROL;
+		pp_div_reg = PCH_PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CPU_CTL;
+	} else {
+		pp_on_reg = PP_ON_DELAYS;
+		pp_off_reg = PP_OFF_DELAYS;
+		pp_ctl_reg = PP_CONTROL;
+		pp_div_reg = PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CTL;
+	}
+
+	dev_priv->savePP_ON = I915_READ(pp_on_reg);
+	dev_priv->savePP_OFF = I915_READ(pp_off_reg);
+	dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg);
+	dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg);
+	dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg);
 	dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
 				       BACKLIGHT_DUTY_CYCLE_MASK);
 
@@ -127,12 +180,28 @@
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
+	u32 pwm_ctl_reg;
 
-	I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
-	I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON);
-	I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF);
-	I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
-	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+	if (IS_IGDNG(dev)) {
+		pp_on_reg = PCH_PP_ON_DELAYS;
+		pp_off_reg = PCH_PP_OFF_DELAYS;
+		pp_ctl_reg = PCH_PP_CONTROL;
+		pp_div_reg = PCH_PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CPU_CTL;
+	} else {
+		pp_on_reg = PP_ON_DELAYS;
+		pp_off_reg = PP_OFF_DELAYS;
+		pp_ctl_reg = PP_CONTROL;
+		pp_div_reg = PP_DIVISOR;
+		pwm_ctl_reg = BLC_PWM_CTL;
+	}
+
+	I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL);
+	I915_WRITE(pp_on_reg, dev_priv->savePP_ON);
+	I915_WRITE(pp_off_reg, dev_priv->savePP_OFF);
+	I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR);
+	I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL);
 	if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
 		intel_lvds_set_power(dev, true);
 	else
@@ -160,26 +229,45 @@
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
 {
+	/*
+	 * float point operation is not supported . So the PANEL_RATIO_FACTOR
+	 * is defined, which can avoid the float point computation when
+	 * calculating the panel ratio.
+	 */
+#define PANEL_RATIO_FACTOR 8192
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct drm_encoder *tmp_encoder;
+	struct intel_output *intel_output = enc_to_intel_output(encoder);
+	struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
+	u32 pfit_control = 0, pfit_pgm_ratios = 0;
+	int left_border = 0, right_border = 0, top_border = 0;
+	int bottom_border = 0;
+	bool border = 0;
+	int panel_ratio, desired_ratio, vert_scale, horiz_scale;
+	int horiz_ratio, vert_ratio;
+	u32 hsync_width, vsync_width;
+	u32 hblank_width, vblank_width;
+	u32 hsync_pos, vsync_pos;
 
 	/* Should never happen!! */
 	if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
-		printk(KERN_ERR "Can't support LVDS on pipe A\n");
+		DRM_ERROR("Can't support LVDS on pipe A\n");
 		return false;
 	}
 
 	/* Should never happen!! */
 	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) {
 		if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) {
-			printk(KERN_ERR "Can't enable LVDS and another "
+			DRM_ERROR("Can't enable LVDS and another "
 			       "encoder on the same pipe\n");
 			return false;
 		}
 	}
-
+	/* If we don't have a panel mode, there is nothing we can do */
+	if (dev_priv->panel_fixed_mode == NULL)
+		return true;
 	/*
 	 * If we have timings from the BIOS for the panel, put them in
 	 * to the adjusted mode.  The CRTC will be set up for this mode,
@@ -203,6 +291,243 @@
 		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
 	}
 
+	/* Make sure pre-965s set dither correctly */
+	if (!IS_I965G(dev)) {
+		if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
+			pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+	}
+
+	/* Native modes don't need fitting */
+	if (adjusted_mode->hdisplay == mode->hdisplay &&
+			adjusted_mode->vdisplay == mode->vdisplay) {
+		pfit_pgm_ratios = 0;
+		border = 0;
+		goto out;
+	}
+
+	/* 965+ wants fuzzy fitting */
+	if (IS_I965G(dev))
+		pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
+					PFIT_FILTER_FUZZY;
+
+	hsync_width = adjusted_mode->crtc_hsync_end -
+					adjusted_mode->crtc_hsync_start;
+	vsync_width = adjusted_mode->crtc_vsync_end -
+					adjusted_mode->crtc_vsync_start;
+	hblank_width = adjusted_mode->crtc_hblank_end -
+					adjusted_mode->crtc_hblank_start;
+	vblank_width = adjusted_mode->crtc_vblank_end -
+					adjusted_mode->crtc_vblank_start;
+	/*
+	 * Deal with panel fitting options. Figure out how to stretch the
+	 * image based on its aspect ratio & the current panel fitting mode.
+	 */
+	panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR /
+				adjusted_mode->vdisplay;
+	desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR /
+				mode->vdisplay;
+	/*
+	 * Enable automatic panel scaling for non-native modes so that they fill
+	 * the screen.  Should be enabled before the pipe is enabled, according
+	 * to register description and PRM.
+	 * Change the value here to see the borders for debugging
+	 */
+	I915_WRITE(BCLRPAT_A, 0);
+	I915_WRITE(BCLRPAT_B, 0);
+
+	switch (lvds_priv->fitting_mode) {
+	case DRM_MODE_SCALE_NO_SCALE:
+		/*
+		 * For centered modes, we have to calculate border widths &
+		 * heights and modify the values programmed into the CRTC.
+		 */
+		left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2;
+		right_border = left_border;
+		if (mode->hdisplay & 1)
+			right_border++;
+		top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2;
+		bottom_border = top_border;
+		if (mode->vdisplay & 1)
+			bottom_border++;
+		/* Set active & border values */
+		adjusted_mode->crtc_hdisplay = mode->hdisplay;
+		/* Keep the boder be even */
+		if (right_border & 1)
+			right_border++;
+		/* use the border directly instead of border minuse one */
+		adjusted_mode->crtc_hblank_start = mode->hdisplay +
+						right_border;
+		/* keep the blank width constant */
+		adjusted_mode->crtc_hblank_end =
+			adjusted_mode->crtc_hblank_start + hblank_width;
+		/* get the hsync pos relative to hblank start */
+		hsync_pos = (hblank_width - hsync_width) / 2;
+		/* keep the hsync pos be even */
+		if (hsync_pos & 1)
+			hsync_pos++;
+		adjusted_mode->crtc_hsync_start =
+				adjusted_mode->crtc_hblank_start + hsync_pos;
+		/* keep the hsync width constant */
+		adjusted_mode->crtc_hsync_end =
+				adjusted_mode->crtc_hsync_start + hsync_width;
+		adjusted_mode->crtc_vdisplay = mode->vdisplay;
+		/* use the border instead of border minus one */
+		adjusted_mode->crtc_vblank_start = mode->vdisplay +
+						bottom_border;
+		/* keep the vblank width constant */
+		adjusted_mode->crtc_vblank_end =
+				adjusted_mode->crtc_vblank_start + vblank_width;
+		/* get the vsync start postion relative to vblank start */
+		vsync_pos = (vblank_width - vsync_width) / 2;
+		adjusted_mode->crtc_vsync_start =
+				adjusted_mode->crtc_vblank_start + vsync_pos;
+		/* keep the vsync width constant */
+		adjusted_mode->crtc_vsync_end =
+				adjusted_mode->crtc_vblank_start + vsync_width;
+		border = 1;
+		break;
+	case DRM_MODE_SCALE_ASPECT:
+		/* Scale but preserve the spect ratio */
+		pfit_control |= PFIT_ENABLE;
+		if (IS_I965G(dev)) {
+			/* 965+ is easy, it does everything in hw */
+			if (panel_ratio > desired_ratio)
+				pfit_control |= PFIT_SCALING_PILLAR;
+			else if (panel_ratio < desired_ratio)
+				pfit_control |= PFIT_SCALING_LETTER;
+			else
+				pfit_control |= PFIT_SCALING_AUTO;
+		} else {
+			/*
+			 * For earlier chips we have to calculate the scaling
+			 * ratio by hand and program it into the
+			 * PFIT_PGM_RATIO register
+			 */
+			u32 horiz_bits, vert_bits, bits = 12;
+			horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/
+						adjusted_mode->hdisplay;
+			vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/
+						adjusted_mode->vdisplay;
+			horiz_scale = adjusted_mode->hdisplay *
+					PANEL_RATIO_FACTOR / mode->hdisplay;
+			vert_scale = adjusted_mode->vdisplay *
+					PANEL_RATIO_FACTOR / mode->vdisplay;
+
+			/* retain aspect ratio */
+			if (panel_ratio > desired_ratio) { /* Pillar */
+				u32 scaled_width;
+				scaled_width = mode->hdisplay * vert_scale /
+						PANEL_RATIO_FACTOR;
+				horiz_ratio = vert_ratio;
+				pfit_control |= (VERT_AUTO_SCALE |
+						 VERT_INTERP_BILINEAR |
+						 HORIZ_INTERP_BILINEAR);
+				/* Pillar will have left/right borders */
+				left_border = (adjusted_mode->hdisplay -
+						scaled_width) / 2;
+				right_border = left_border;
+				if (mode->hdisplay & 1) /* odd resolutions */
+					right_border++;
+				/* keep the border be even */
+				if (right_border & 1)
+					right_border++;
+				adjusted_mode->crtc_hdisplay = scaled_width;
+				/* use border instead of border minus one */
+				adjusted_mode->crtc_hblank_start =
+					scaled_width + right_border;
+				/* keep the hblank width constant */
+				adjusted_mode->crtc_hblank_end =
+					adjusted_mode->crtc_hblank_start +
+							hblank_width;
+				/*
+				 * get the hsync start pos relative to
+				 * hblank start
+				 */
+				hsync_pos = (hblank_width - hsync_width) / 2;
+				/* keep the hsync_pos be even */
+				if (hsync_pos & 1)
+					hsync_pos++;
+				adjusted_mode->crtc_hsync_start =
+					adjusted_mode->crtc_hblank_start +
+							hsync_pos;
+				/* keept hsync width constant */
+				adjusted_mode->crtc_hsync_end =
+					adjusted_mode->crtc_hsync_start +
+							hsync_width;
+				border = 1;
+			} else if (panel_ratio < desired_ratio) { /* letter */
+				u32 scaled_height = mode->vdisplay *
+					horiz_scale / PANEL_RATIO_FACTOR;
+				vert_ratio = horiz_ratio;
+				pfit_control |= (HORIZ_AUTO_SCALE |
+						 VERT_INTERP_BILINEAR |
+						 HORIZ_INTERP_BILINEAR);
+				/* Letterbox will have top/bottom border */
+				top_border = (adjusted_mode->vdisplay -
+					scaled_height) / 2;
+				bottom_border = top_border;
+				if (mode->vdisplay & 1)
+					bottom_border++;
+				adjusted_mode->crtc_vdisplay = scaled_height;
+				/* use border instead of border minus one */
+				adjusted_mode->crtc_vblank_start =
+					scaled_height + bottom_border;
+				/* keep the vblank width constant */
+				adjusted_mode->crtc_vblank_end =
+					adjusted_mode->crtc_vblank_start +
+							vblank_width;
+				/*
+				 * get the vsync start pos relative to
+				 * vblank start
+				 */
+				vsync_pos = (vblank_width - vsync_width) / 2;
+				adjusted_mode->crtc_vsync_start =
+					adjusted_mode->crtc_vblank_start +
+							vsync_pos;
+				/* keep the vsync width constant */
+				adjusted_mode->crtc_vsync_end =
+					adjusted_mode->crtc_vsync_start +
+							vsync_width;
+				border = 1;
+			} else {
+			/* Aspects match, Let hw scale both directions */
+				pfit_control |= (VERT_AUTO_SCALE |
+						 HORIZ_AUTO_SCALE |
+						 VERT_INTERP_BILINEAR |
+						 HORIZ_INTERP_BILINEAR);
+			}
+			horiz_bits = (1 << bits) * horiz_ratio /
+					PANEL_RATIO_FACTOR;
+			vert_bits = (1 << bits) * vert_ratio /
+					PANEL_RATIO_FACTOR;
+			pfit_pgm_ratios =
+				((vert_bits << PFIT_VERT_SCALE_SHIFT) &
+						PFIT_VERT_SCALE_MASK) |
+				((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) &
+						PFIT_HORIZ_SCALE_MASK);
+		}
+		break;
+
+	case DRM_MODE_SCALE_FULLSCREEN:
+		/*
+		 * Full scaling, even if it changes the aspect ratio.
+		 * Fortunately this is all done for us in hw.
+		 */
+		pfit_control |= PFIT_ENABLE;
+		if (IS_I965G(dev))
+			pfit_control |= PFIT_SCALING_AUTO;
+		else
+			pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+					 VERT_INTERP_BILINEAR |
+					 HORIZ_INTERP_BILINEAR);
+		break;
+	default:
+		break;
+	}
+
+out:
+	lvds_priv->pfit_control = pfit_control;
+	lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
 	/*
 	 * XXX: It would be nice to support lower refresh rates on the
 	 * panels to reduce power consumption, and perhaps match the
@@ -216,8 +541,14 @@
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg;
 
-	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+	if (IS_IGDNG(dev))
+		reg = BLC_PWM_CPU_CTL;
+	else
+		reg = BLC_PWM_CTL;
+
+	dev_priv->saveBLC_PWM_CTL = I915_READ(reg);
 	dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
 				       BACKLIGHT_DUTY_CYCLE_MASK);
 
@@ -242,8 +573,8 @@
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	u32 pfit_control;
+	struct intel_output *intel_output = enc_to_intel_output(encoder);
+	struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
 
 	/*
 	 * The LVDS pin pair will already have been turned on in the
@@ -251,27 +582,17 @@
 	 * settings.
 	 */
 
+	/* No panel fitting yet, fixme */
+	if (IS_IGDNG(dev))
+		return;
+
 	/*
 	 * Enable automatic panel scaling so that non-native modes fill the
 	 * screen.  Should be enabled before the pipe is enabled, according to
 	 * register description and PRM.
 	 */
-	if (mode->hdisplay != adjusted_mode->hdisplay ||
-	    mode->vdisplay != adjusted_mode->vdisplay)
-		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
-				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
-				HORIZ_INTERP_BILINEAR);
-	else
-		pfit_control = 0;
-
-	if (!IS_I965G(dev)) {
-		if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
-			pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-	}
-	else
-		pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
-
-	I915_WRITE(PFIT_CONTROL, pfit_control);
+	I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios);
+	I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control);
 }
 
 /**
@@ -343,6 +664,34 @@
 				   struct drm_property *property,
 				   uint64_t value)
 {
+	struct drm_device *dev = connector->dev;
+	struct intel_output *intel_output =
+			to_intel_output(connector);
+
+	if (property == dev->mode_config.scaling_mode_property &&
+				connector->encoder) {
+		struct drm_crtc *crtc = connector->encoder->crtc;
+		struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
+		if (value == DRM_MODE_SCALE_NON_GPU) {
+			DRM_DEBUG_KMS(I915_LVDS,
+					"non_GPU property is unsupported\n");
+			return 0;
+		}
+		if (lvds_priv->fitting_mode == value) {
+			/* the LVDS scaling property is not changed */
+			return 0;
+		}
+		lvds_priv->fitting_mode = value;
+		if (crtc && crtc->enabled) {
+			/*
+			 * If the CRTC is enabled, the display will be changed
+			 * according to the new panel fitting mode.
+			 */
+			drm_crtc_helper_set_mode(crtc, &crtc->mode,
+				crtc->x, crtc->y, crtc->fb);
+		}
+	}
+
 	return 0;
 }
 
@@ -382,7 +731,8 @@
 
 static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
 {
-	DRM_DEBUG("Skipping LVDS initialization for %s\n", id->ident);
+	DRM_DEBUG_KMS(I915_LVDS,
+		      "Skipping LVDS initialization for %s\n", id->ident);
 	return 1;
 }
 
@@ -392,7 +742,7 @@
 		.callback = intel_no_lvds_dmi_callback,
 		.ident = "Apple Mac Mini (Core series)",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
 		},
 	},
@@ -400,7 +750,7 @@
 		.callback = intel_no_lvds_dmi_callback,
 		.ident = "Apple Mac Mini (Core 2 series)",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
 		},
 	},
@@ -420,12 +770,92 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
 		},
 	},
-
-	/* FIXME: add a check for the Aopen Mini PC */
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "AOpen Mini PC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "AOpen Mini PC MP915",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+			DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Aopen i945GTt-VFA",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
 
+#ifdef CONFIG_ACPI
+/*
+ * check_lid_device -- check whether @handle is an ACPI LID device.
+ * @handle: ACPI device handle
+ * @level : depth in the ACPI namespace tree
+ * @context: the number of LID device when we find the device
+ * @rv: a return value to fill if desired (Not use)
+ */
+static acpi_status
+check_lid_device(acpi_handle handle, u32 level, void *context,
+			void **return_value)
+{
+	struct acpi_device *acpi_dev;
+	int *lid_present = context;
+
+	acpi_dev = NULL;
+	/* Get the acpi device for device handle */
+	if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) {
+		/* If there is no ACPI device for handle, return */
+		return AE_OK;
+	}
+
+	if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7))
+		*lid_present = 1;
+
+	return AE_OK;
+}
+
+/**
+ * check whether there exists the ACPI LID device by enumerating the ACPI
+ * device tree.
+ */
+static int intel_lid_present(void)
+{
+	int lid_present = 0;
+
+	if (acpi_disabled) {
+		/* If ACPI is disabled, there is no ACPI device tree to
+		 * check, so assume the LID device would have been present.
+		 */
+		return 1;
+	}
+
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				ACPI_UINT32_MAX,
+				check_lid_device, &lid_present, NULL);
+
+	return lid_present;
+}
+#else
+static int intel_lid_present(void)
+{
+	/* In the absence of ACPI built in, assume that the LID device would
+	 * have been present.
+	 */
+	return 1;
+}
+#endif
+
 /**
  * intel_lvds_init - setup LVDS connectors on this device
  * @dev: drm device
@@ -441,14 +871,36 @@
 	struct drm_encoder *encoder;
 	struct drm_display_mode *scan; /* *modes, *bios_mode; */
 	struct drm_crtc *crtc;
+	struct intel_lvds_priv *lvds_priv;
 	u32 lvds;
-	int pipe;
+	int pipe, gpio = GPIOC;
 
 	/* Skip init on machines we know falsely report LVDS */
 	if (dmi_check_system(intel_no_lvds))
 		return;
 
-	intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
+	/* Assume that any device without an ACPI LID device also doesn't
+	 * have an integrated LVDS.  We would be better off parsing the BIOS
+	 * to get a reliable indicator, but that code isn't written yet.
+	 *
+	 * In the case of all-in-one desktops using LVDS that we've seen,
+	 * they're using SDVO LVDS.
+	 */
+	if (!intel_lid_present())
+		return;
+
+	if (IS_IGDNG(dev)) {
+		if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
+			return;
+		if (dev_priv->edp_support) {
+			DRM_DEBUG("disable LVDS for eDP support\n");
+			return;
+		}
+		gpio = PCH_GPIOC;
+	}
+
+	intel_output = kzalloc(sizeof(struct intel_output) +
+				sizeof(struct intel_lvds_priv), GFP_KERNEL);
 	if (!intel_output) {
 		return;
 	}
@@ -464,13 +916,26 @@
 	drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
 	intel_output->type = INTEL_OUTPUT_LVDS;
 
+	intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+	intel_output->crtc_mask = (1 << 1);
 	drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
 	drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
 
+	lvds_priv = (struct intel_lvds_priv *)(intel_output + 1);
+	intel_output->dev_priv = lvds_priv;
+	/* create the scaling mode property */
+	drm_mode_create_scaling_mode_property(dev);
+	/*
+	 * the initial panel fitting mode will be FULL_SCREEN.
+	 */
 
+	drm_connector_attach_property(&intel_output->base,
+				      dev->mode_config.scaling_mode_property,
+				      DRM_MODE_SCALE_FULLSCREEN);
+	lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
 	/*
 	 * LVDS discovery:
 	 * 1) check for EDID on DDC
@@ -482,7 +947,7 @@
 	 */
 
 	/* Set up the DDC bus. */
-	intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
+	intel_output->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
 	if (!intel_output->ddc_bus) {
 		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
 			   "failed.\n");
@@ -524,6 +989,11 @@
 	 * on.  If so, assume that whatever is currently programmed is the
 	 * correct mode.
 	 */
+
+	/* IGDNG: FIXME if still fail, not try pipe mode now */
+	if (IS_IGDNG(dev))
+		goto failed;
+
 	lvds = I915_READ(LVDS);
 	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
 	crtc = intel_get_crtc_from_pipe(dev, pipe);
@@ -542,13 +1012,24 @@
 		goto failed;
 
 out:
+	if (IS_IGDNG(dev)) {
+		u32 pwm;
+		/* make sure PWM is enabled */
+		pwm = I915_READ(BLC_PWM_CPU_CTL2);
+		pwm |= (PWM_ENABLE | PWM_PIPE_B);
+		I915_WRITE(BLC_PWM_CPU_CTL2, pwm);
+
+		pwm = I915_READ(BLC_PWM_PCH_CTL1);
+		pwm |= PWM_PCH_ENABLE;
+		I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
+	}
 	drm_sysfs_connector_add(connector);
 	return;
 
 failed:
-	DRM_DEBUG("No LVDS modes found, disabling.\n");
+	DRM_DEBUG_KMS(I915_LVDS, "No LVDS modes found, disabling.\n");
 	if (intel_output->ddc_bus)
 		intel_i2c_destroy(intel_output->ddc_bus);
 	drm_connector_cleanup(connector);
-	kfree(connector);
+	kfree(intel_output);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_modes.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_modes.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_modes.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_modes.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,10 +53,9 @@
 		}
 	};
 
-	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
-	ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
-	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
-
+	intel_i2c_quirk_set(intel_output->base.dev, true);
+	ret = i2c_transfer(intel_output->ddc_bus, msgs, 2);
+	intel_i2c_quirk_set(intel_output->base.dev, false);
 	if (ret == 2)
 		return true;
 
@@ -74,10 +73,9 @@
 	struct edid *edid;
 	int ret = 0;
 
-	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
-	edid = drm_get_edid(&intel_output->base,
-			    &intel_output->ddc_bus->adapter);
-	intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
+	intel_i2c_quirk_set(intel_output->base.dev, true);
+	edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus);
+	intel_i2c_quirk_set(intel_output->base.dev, false);
 	if (edid) {
 		drm_mode_connector_update_edid_property(&intel_output->base,
 							edid);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,15 +31,15 @@
 #include "drm.h"
 #include "drm_crtc.h"
 #include "intel_drv.h"
+#include "drm_edid.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "intel_sdvo_regs.h"
 
 #undef SDVO_DEBUG
-
+#define I915_SDVO	"i915_sdvo"
 struct intel_sdvo_priv {
-	struct intel_i2c_chan *i2c_bus;
-	int slaveaddr;
+	u8 slave_addr;
 
 	/* Register for the SDVO device: SDVOB or SDVOC */
 	int output_device;
@@ -56,6 +56,12 @@
 	/* Pixel clock limitations reported by the SDVO device, in kHz */
 	int pixel_clock_min, pixel_clock_max;
 
+	/*
+	* For multiple function SDVO device,
+	* this is for current attached outputs.
+	*/
+	uint16_t attached_output;
+
 	/**
 	 * This is set if we're going to treat the device as TV-out.
 	 *
@@ -69,12 +75,23 @@
 	 * This is set if we treat the device as HDMI, instead of DVI.
 	 */
 	bool is_hdmi;
+
 	/**
 	 * This is set if we detect output of sdvo device as LVDS.
 	 */
 	bool is_lvds;
 
 	/**
+	 * This is sdvo flags for input timing.
+	 */
+	uint8_t sdvo_flags;
+
+	/**
+	 * This is sdvo fixed pannel mode pointer
+	 */
+	struct drm_display_mode *sdvo_lvds_fixed_mode;
+
+	/**
 	 * Returned SDTV resolutions allowed for the current format, if the
 	 * device reported it.
 	 */
@@ -104,6 +121,9 @@
 	u32 save_SDVOX;
 };
 
+static bool
+intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags);
+
 /**
  * Writes the SDVOB or SDVOC with the given value, but always writes both
  * SDVOB and SDVOC to work around apparent hardware issues (according to
@@ -146,13 +166,13 @@
 
 	struct i2c_msg msgs[] = {
 		{
-			.addr = sdvo_priv->i2c_bus->slave_addr,
+			.addr = sdvo_priv->slave_addr >> 1,
 			.flags = 0,
 			.len = 1,
 			.buf = out_buf,
 		},
 		{
-			.addr = sdvo_priv->i2c_bus->slave_addr,
+			.addr = sdvo_priv->slave_addr >> 1,
 			.flags = I2C_M_RD,
 			.len = 1,
 			.buf = buf,
@@ -162,7 +182,7 @@
 	out_buf[0] = addr;
 	out_buf[1] = 0;
 
-	if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2)
+	if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2)
 	{
 		*ch = buf[0];
 		return true;
@@ -175,10 +195,11 @@
 static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
 				  u8 ch)
 {
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 	u8 out_buf[2];
 	struct i2c_msg msgs[] = {
 		{
-			.addr = intel_output->i2c_bus->slave_addr,
+			.addr = sdvo_priv->slave_addr >> 1,
 			.flags = 0,
 			.len = 2,
 			.buf = out_buf,
@@ -188,7 +209,7 @@
 	out_buf[0] = addr;
 	out_buf[1] = ch;
 
-	if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1)
+	if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1)
 	{
 		return true;
 	}
@@ -277,20 +298,21 @@
 	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 	int i;
 
-	printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
+	DRM_DEBUG_KMS(I915_SDVO, "%s: W: %02X ",
+				SDVO_NAME(sdvo_priv), cmd);
 	for (i = 0; i < args_len; i++)
-		printk(KERN_DEBUG "%02X ", ((u8 *)args)[i]);
+		DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
 	for (; i < 8; i++)
-		printk(KERN_DEBUG "   ");
+		DRM_LOG_KMS("   ");
 	for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
 		if (cmd == sdvo_cmd_names[i].cmd) {
-			printk(KERN_DEBUG "(%s)", sdvo_cmd_names[i].name);
+			DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name);
 			break;
 		}
 	}
 	if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0]))
-		printk(KERN_DEBUG "(%02X)", cmd);
-	printk(KERN_DEBUG "\n");
+		DRM_LOG_KMS("(%02X)", cmd);
+	DRM_LOG_KMS("\n");
 }
 #else
 #define intel_sdvo_debug_write(o, c, a, l)
@@ -329,16 +351,16 @@
 	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 	int i;
 
-	printk(KERN_DEBUG "%s: R: ", SDVO_NAME(sdvo_priv));
+	DRM_DEBUG_KMS(I915_SDVO, "%s: R: ", SDVO_NAME(sdvo_priv));
 	for (i = 0; i < response_len; i++)
-		printk(KERN_DEBUG "%02X ", ((u8 *)response)[i]);
+		DRM_LOG_KMS("%02X ", ((u8 *)response)[i]);
 	for (; i < 8; i++)
-		printk(KERN_DEBUG "   ");
+		DRM_LOG_KMS("   ");
 	if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-		printk(KERN_DEBUG "(%s)", cmd_status_names[status]);
+		DRM_LOG_KMS("(%s)", cmd_status_names[status]);
 	else
-		printk(KERN_DEBUG "(??? %d)", status);
-	printk(KERN_DEBUG "\n");
+		DRM_LOG_KMS("(??? %d)", status);
+	DRM_LOG_KMS("\n");
 }
 #else
 #define intel_sdvo_debug_response(o, r, l, s)
@@ -591,6 +613,7 @@
 					 uint16_t height)
 {
 	struct intel_sdvo_preferred_input_timing_args args;
+	struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
 	uint8_t status;
 
 	memset(&args, 0, sizeof(args));
@@ -598,7 +621,12 @@
 	args.width = width;
 	args.height = height;
 	args.interlace = 0;
-	args.scaled = 0;
+
+	if (sdvo_priv->is_lvds &&
+	   (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width ||
+	    sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height))
+		args.scaled = 1;
+
 	intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
 			     &args, sizeof(args));
 	status = intel_sdvo_read_response(output, NULL, 0);
@@ -943,12 +971,7 @@
 	struct intel_output *output = enc_to_intel_output(encoder);
 	struct intel_sdvo_priv *dev_priv = output->dev_priv;
 
-	if (!dev_priv->is_tv) {
-		/* Make the CRTC code factor in the SDVO pixel multiplier.  The
-		 * SDVO device will be told of the multiplier during mode_set.
-		 */
-		adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode);
-	} else {
+	if (dev_priv->is_tv) {
 		struct intel_sdvo_dtd output_dtd;
 		bool success;
 
@@ -979,6 +1002,47 @@
 			intel_sdvo_get_preferred_input_timing(output,
 							     &input_dtd);
 			intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+			dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
+
+			drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+			mode->clock = adjusted_mode->clock;
+
+			adjusted_mode->clock *=
+				intel_sdvo_get_pixel_multiplier(mode);
+		} else {
+			return false;
+		}
+	} else if (dev_priv->is_lvds) {
+		struct intel_sdvo_dtd output_dtd;
+		bool success;
+
+		drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0);
+		/* Set output timings */
+		intel_sdvo_get_dtd_from_mode(&output_dtd,
+				dev_priv->sdvo_lvds_fixed_mode);
+
+		intel_sdvo_set_target_output(output,
+					     dev_priv->controlled_output);
+		intel_sdvo_set_output_timing(output, &output_dtd);
+
+		/* Set the input timing to the screen. Assume always input 0. */
+		intel_sdvo_set_target_input(output, true, false);
+
+
+		success = intel_sdvo_create_preferred_input_timing(
+				output,
+				mode->clock / 10,
+				mode->hdisplay,
+				mode->vdisplay);
+
+		if (success) {
+			struct intel_sdvo_dtd input_dtd;
+
+			intel_sdvo_get_preferred_input_timing(output,
+							     &input_dtd);
+			intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+			dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
 
 			drm_mode_set_crtcinfo(adjusted_mode, 0);
 
@@ -989,6 +1053,12 @@
 		} else {
 			return false;
 		}
+
+	} else {
+		/* Make the CRTC code factor in the SDVO pixel multiplier.  The
+		 * SDVO device will be told of the multiplier during mode_set.
+		 */
+		adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode);
 	}
 	return true;
 }
@@ -1032,15 +1102,16 @@
 
 	/* We have tried to get input timing in mode_fixup, and filled into
 	   adjusted_mode */
-	if (sdvo_priv->is_tv)
+	if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
 		intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
-	else
+		input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags;
+	} else
 		intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
 
 	/* If it's a TV, we already set the output timing in mode_fixup.
 	 * Otherwise, the output timing is equal to the input timing.
 	 */
-	if (!sdvo_priv->is_tv) {
+	if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) {
 		/* Set the output timing to the screen */
 		intel_sdvo_set_target_output(output,
 					     sdvo_priv->controlled_output);
@@ -1115,6 +1186,8 @@
 		sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
 	}
 
+	if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL)
+		sdvox |= SDVO_STALL_SELECT;
 	intel_sdvo_write_sdvox(output, sdvox);
 }
 
@@ -1275,6 +1348,17 @@
 	if (sdvo_priv->pixel_clock_max < mode->clock)
 		return MODE_CLOCK_HIGH;
 
+	if (sdvo_priv->is_lvds == true) {
+		if (sdvo_priv->sdvo_lvds_fixed_mode == NULL)
+			return MODE_PANEL;
+
+		if (mode->hdisplay > sdvo_priv->sdvo_lvds_fixed_mode->hdisplay)
+			return MODE_PANEL;
+
+		if (mode->vdisplay > sdvo_priv->sdvo_lvds_fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+
 	return MODE_OK;
 }
 
@@ -1361,42 +1445,96 @@
 	intel_sdvo_read_response(intel_output, &response, 2);
 }
 
-static void
-intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
+static bool
+intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
+{
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	int caps = 0;
+
+	if (sdvo_priv->caps.output_flags &
+		(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+		caps++;
+	if (sdvo_priv->caps.output_flags &
+		(SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
+		caps++;
+	if (sdvo_priv->caps.output_flags &
+		(SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1))
+		caps++;
+	if (sdvo_priv->caps.output_flags &
+		(SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
+		caps++;
+	if (sdvo_priv->caps.output_flags &
+		(SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1))
+		caps++;
+
+	if (sdvo_priv->caps.output_flags &
+		(SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1))
+		caps++;
+
+	if (sdvo_priv->caps.output_flags &
+		(SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1))
+		caps++;
+
+	return (caps > 1);
+}
+
+enum drm_connector_status
+intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
 {
 	struct intel_output *intel_output = to_intel_output(connector);
 	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	enum drm_connector_status status = connector_status_connected;
 	struct edid *edid = NULL;
 
-	intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
 	edid = drm_get_edid(&intel_output->base,
-			    &intel_output->ddc_bus->adapter);
+			    intel_output->ddc_bus);
 	if (edid != NULL) {
-		sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid);
+		/* Don't report the output as connected if it's a DVI-I
+		 * connector with a non-digital EDID coming out.
+		 */
+		if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
+			if (edid->input & DRM_EDID_INPUT_DIGITAL)
+				sdvo_priv->is_hdmi =
+					drm_detect_hdmi_monitor(edid);
+			else
+				status = connector_status_disconnected;
+		}
+
 		kfree(edid);
 		intel_output->base.display_info.raw_edid = NULL;
-	}
+
+	} else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+		status = connector_status_disconnected;
+
+	return status;
 }
 
 static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
 {
-	u8 response[2];
+	uint16_t response;
 	u8 status;
 	struct intel_output *intel_output = to_intel_output(connector);
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 
 	intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
 	status = intel_sdvo_read_response(intel_output, &response, 2);
 
-	DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
+	DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8);
 
 	if (status != SDVO_CMD_STATUS_SUCCESS)
 		return connector_status_unknown;
 
-	if ((response[0] != 0) || (response[1] != 0)) {
-		intel_sdvo_hdmi_sink_detect(connector);
-		return connector_status_connected;
-	} else
+	if (response == 0)
 		return connector_status_disconnected;
+
+	if (intel_sdvo_multifunc_encoder(intel_output) &&
+		sdvo_priv->attached_output != response) {
+		if (sdvo_priv->controlled_output != response &&
+			intel_sdvo_output_setup(intel_output, response) != true)
+			return connector_status_unknown;
+		sdvo_priv->attached_output = response;
+	}
+	return intel_sdvo_hdmi_sink_detect(connector, response);
 }
 
 static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
@@ -1548,23 +1686,21 @@
 static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
 {
 	struct intel_output *intel_output = to_intel_output(connector);
-	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	struct drm_display_mode *newmode;
 
 	/*
 	 * Attempt to get the mode list from DDC.
 	 * Assume that the preferred modes are
 	 * arranged in priority order.
 	 */
-	/* set the bus switch and get the modes */
-	intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
 	intel_ddc_get_modes(intel_output);
 	if (list_empty(&connector->probed_modes) == false)
-		return;
+		goto end;
 
 	/* Fetch modes from VBT */
 	if (dev_priv->sdvo_lvds_vbt_mode != NULL) {
-		struct drm_display_mode *newmode;
 		newmode = drm_mode_duplicate(connector->dev,
 					     dev_priv->sdvo_lvds_vbt_mode);
 		if (newmode != NULL) {
@@ -1574,6 +1710,16 @@
 			drm_mode_probed_add(connector, newmode);
 		}
 	}
+
+end:
+	list_for_each_entry(newmode, &connector->probed_modes, head) {
+		if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
+			sdvo_priv->sdvo_lvds_fixed_mode =
+				drm_mode_duplicate(connector->dev, newmode);
+			break;
+		}
+	}
+
 }
 
 static int intel_sdvo_get_modes(struct drm_connector *connector)
@@ -1596,14 +1742,20 @@
 static void intel_sdvo_destroy(struct drm_connector *connector)
 {
 	struct intel_output *intel_output = to_intel_output(connector);
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 
 	if (intel_output->i2c_bus)
 		intel_i2c_destroy(intel_output->i2c_bus);
 	if (intel_output->ddc_bus)
 		intel_i2c_destroy(intel_output->ddc_bus);
 
+	if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
+		drm_mode_destroy(connector->dev,
+				 sdvo_priv->sdvo_lvds_fixed_mode);
+
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
+
 	kfree(intel_output);
 }
 
@@ -1708,7 +1860,7 @@
 
 	list_for_each_entry(connector,
 			&dev->mode_config.connector_list, head) {
-		if (to_intel_output(connector)->ddc_bus == chan) {
+		if (to_intel_output(connector)->ddc_bus == &chan->adapter) {
 			intel_output = to_intel_output(connector);
 			break;
 		}
@@ -1722,7 +1874,7 @@
 	struct intel_output *intel_output;
 	struct intel_sdvo_priv *sdvo_priv;
 	struct i2c_algo_bit_data *algo_data;
-	struct i2c_algorithm *algo;
+	const struct i2c_algorithm *algo;
 
 	algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data;
 	intel_output =
@@ -1732,7 +1884,7 @@
 		return -EINVAL;
 
 	sdvo_priv = intel_output->dev_priv;
-	algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo;
+	algo = intel_output->i2c_bus->algo;
 
 	intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
 	return algo->master_xfer(i2c_adap, msgs, num);
@@ -1742,85 +1894,69 @@
 	.master_xfer	= intel_sdvo_master_xfer,
 };
 
-bool intel_sdvo_init(struct drm_device *dev, int output_device)
+static u8
+intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
 {
-	struct drm_connector *connector;
-	struct intel_output *intel_output;
-	struct intel_sdvo_priv *sdvo_priv;
-	struct intel_i2c_chan *i2cbus = NULL;
-	struct intel_i2c_chan *ddcbus = NULL;
-	int connector_type;
-	u8 ch[0x40];
-	int i;
-	int encoder_type, output_id;
-
-	intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
-	if (!intel_output) {
-		return false;
-	}
-
-	sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
-	intel_output->type = INTEL_OUTPUT_SDVO;
-
-	/* setup the DDC bus. */
-	if (output_device == SDVOB)
-		i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
-	else
-		i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
-
-	if (!i2cbus)
-		goto err_inteloutput;
-
-	sdvo_priv->i2c_bus = i2cbus;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct sdvo_device_mapping *my_mapping, *other_mapping;
 
 	if (output_device == SDVOB) {
-		output_id = 1;
-		sdvo_priv->i2c_bus->slave_addr = 0x38;
+		my_mapping = &dev_priv->sdvo_mappings[0];
+		other_mapping = &dev_priv->sdvo_mappings[1];
 	} else {
-		output_id = 2;
-		sdvo_priv->i2c_bus->slave_addr = 0x39;
+		my_mapping = &dev_priv->sdvo_mappings[1];
+		other_mapping = &dev_priv->sdvo_mappings[0];
 	}
 
-	sdvo_priv->output_device = output_device;
-	intel_output->i2c_bus = i2cbus;
-	intel_output->dev_priv = sdvo_priv;
+	/* If the BIOS described our SDVO device, take advantage of it. */
+	if (my_mapping->slave_addr)
+		return my_mapping->slave_addr;
 
-	/* Read the regs to test if we can talk to the device */
-	for (i = 0; i < 0x40; i++) {
-		if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) {
-			DRM_DEBUG("No SDVO device found on SDVO%c\n",
-				  output_device == SDVOB ? 'B' : 'C');
-			goto err_i2c;
-		}
+	/* If the BIOS only described a different SDVO device, use the
+	 * address that it isn't using.
+	 */
+	if (other_mapping->slave_addr) {
+		if (other_mapping->slave_addr == 0x70)
+			return 0x72;
+		else
+			return 0x70;
 	}
 
-	/* setup the DDC bus. */
+	/* No SDVO device info is found for another DVO port,
+	 * so use mapping assumption we had before BIOS parsing.
+	 */
 	if (output_device == SDVOB)
-		ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
+		return 0x70;
 	else
-		ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
-
-	if (ddcbus == NULL)
-		goto err_i2c;
+		return 0x72;
+}
 
-	intel_sdvo_i2c_bit_algo.functionality =
-		intel_output->i2c_bus->adapter.algo->functionality;
-	ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo;
-	intel_output->ddc_bus = ddcbus;
+static bool
+intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
+{
+	struct drm_connector *connector = &intel_output->base;
+	struct drm_encoder *encoder = &intel_output->enc;
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	bool ret = true, registered = false;
 
-	/* In defaut case sdvo lvds is false */
+	sdvo_priv->is_tv = false;
+	intel_output->needs_tv_clock = false;
 	sdvo_priv->is_lvds = false;
-	intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);
 
-	if (sdvo_priv->caps.output_flags &
+	if (device_is_registered(&connector->kdev)) {
+		drm_sysfs_connector_remove(connector);
+		registered = true;
+	}
+
+	if (flags &
 	    (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
 		if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
 			sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0;
 		else
 			sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1;
 
-		encoder_type = DRM_MODE_ENCODER_TMDS;
-		connector_type = DRM_MODE_CONNECTOR_DVID;
+		encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
+		connector->connector_type = DRM_MODE_CONNECTOR_DVID;
 
 		if (intel_sdvo_get_supp_encode(intel_output,
 					       &sdvo_priv->encode) &&
@@ -1830,66 +1966,148 @@
 			intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI);
 			intel_sdvo_set_colorimetry(intel_output,
 						   SDVO_COLORIMETRY_RGB256);
-			connector_type = DRM_MODE_CONNECTOR_HDMIA;
+			connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
+			intel_output->clone_mask =
+					(1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+					(1 << INTEL_ANALOG_CLONE_BIT);
 		}
-	}
-	else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_SVID0)
-	{
+	} else if (flags & SDVO_OUTPUT_SVID0) {
+
 		sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
-		encoder_type = DRM_MODE_ENCODER_TVDAC;
-		connector_type = DRM_MODE_CONNECTOR_SVIDEO;
+		encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
+		connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
 		sdvo_priv->is_tv = true;
 		intel_output->needs_tv_clock = true;
-	}
-	else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
-	{
+		intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
+	} else if (flags & SDVO_OUTPUT_RGB0) {
+
 		sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
-		encoder_type = DRM_MODE_ENCODER_DAC;
-		connector_type = DRM_MODE_CONNECTOR_VGA;
-	}
-	else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
-	{
+		encoder->encoder_type = DRM_MODE_ENCODER_DAC;
+		connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+		intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+					(1 << INTEL_ANALOG_CLONE_BIT);
+	} else if (flags & SDVO_OUTPUT_RGB1) {
+
 		sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
-		encoder_type = DRM_MODE_ENCODER_DAC;
-		connector_type = DRM_MODE_CONNECTOR_VGA;
-	}
-	else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS0)
-	{
+		encoder->encoder_type = DRM_MODE_ENCODER_DAC;
+		connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+	} else if (flags & SDVO_OUTPUT_LVDS0) {
+
 		sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;
-		encoder_type = DRM_MODE_ENCODER_LVDS;
-		connector_type = DRM_MODE_CONNECTOR_LVDS;
+		encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
+		connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
 		sdvo_priv->is_lvds = true;
-	}
-	else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS1)
-	{
+		intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+					(1 << INTEL_SDVO_LVDS_CLONE_BIT);
+	} else if (flags & SDVO_OUTPUT_LVDS1) {
+
 		sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
-		encoder_type = DRM_MODE_ENCODER_LVDS;
-		connector_type = DRM_MODE_CONNECTOR_LVDS;
+		encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
+		connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
 		sdvo_priv->is_lvds = true;
-	}
-	else
-	{
+		intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+					(1 << INTEL_SDVO_LVDS_CLONE_BIT);
+	} else {
+
 		unsigned char bytes[2];
 
 		sdvo_priv->controlled_output = 0;
-		memcpy (bytes, &sdvo_priv->caps.output_flags, 2);
-		DRM_DEBUG("%s: Unknown SDVO output type (0x%02x%02x)\n",
-			  SDVO_NAME(sdvo_priv),
-			  bytes[0], bytes[1]);
-		encoder_type = DRM_MODE_ENCODER_NONE;
-		connector_type = DRM_MODE_CONNECTOR_Unknown;
+		memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
+		DRM_DEBUG_KMS(I915_SDVO,
+				"%s: Unknown SDVO output type (0x%02x%02x)\n",
+				  SDVO_NAME(sdvo_priv),
+				  bytes[0], bytes[1]);
+		ret = false;
+	}
+	intel_output->crtc_mask = (1 << 0) | (1 << 1);
+
+	if (ret && registered)
+		ret = drm_sysfs_connector_add(connector) == 0 ? true : false;
+
+
+	return ret;
+
+}
+
+bool intel_sdvo_init(struct drm_device *dev, int output_device)
+{
+	struct drm_connector *connector;
+	struct intel_output *intel_output;
+	struct intel_sdvo_priv *sdvo_priv;
+
+	u8 ch[0x40];
+	int i;
+
+	intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
+	if (!intel_output) {
+		return false;
+	}
+
+	sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
+	sdvo_priv->output_device = output_device;
+
+	intel_output->dev_priv = sdvo_priv;
+	intel_output->type = INTEL_OUTPUT_SDVO;
+
+	/* setup the DDC bus. */
+	if (output_device == SDVOB)
+		intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
+	else
+		intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
+
+	if (!intel_output->i2c_bus)
+		goto err_inteloutput;
+
+	sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
+
+	/* Save the bit-banging i2c functionality for use by the DDC wrapper */
+	intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality;
+
+	/* Read the regs to test if we can talk to the device */
+	for (i = 0; i < 0x40; i++) {
+		if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) {
+			DRM_DEBUG_KMS(I915_SDVO,
+					"No SDVO device found on SDVO%c\n",
+					output_device == SDVOB ? 'B' : 'C');
+			goto err_i2c;
+		}
+	}
+
+	/* setup the DDC bus. */
+	if (output_device == SDVOB)
+		intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
+	else
+		intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
+
+	if (intel_output->ddc_bus == NULL)
+		goto err_i2c;
+
+	/* Wrap with our custom algo which switches to DDC mode */
+	intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
+
+	/* In defaut case sdvo lvds is false */
+	intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);
+
+	if (intel_sdvo_output_setup(intel_output,
+				    sdvo_priv->caps.output_flags) != true) {
+		DRM_DEBUG("SDVO output failed to setup on SDVO%c\n",
+			  output_device == SDVOB ? 'B' : 'C');
 		goto err_i2c;
 	}
 
+
 	connector = &intel_output->base;
 	drm_connector_init(dev, connector, &intel_sdvo_connector_funcs,
-			   connector_type);
+			   connector->connector_type);
+
 	drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 
-	drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type);
+	drm_encoder_init(dev, &intel_output->enc,
+			&intel_sdvo_enc_funcs, intel_output->enc.encoder_type);
+
 	drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
 
 	drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
@@ -1905,29 +2123,30 @@
 					       &sdvo_priv->pixel_clock_max);
 
 
-	DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, "
-		  "clock range %dMHz - %dMHz, "
-		  "input 1: %c, input 2: %c, "
-		  "output 1: %c, output 2: %c\n",
-		  SDVO_NAME(sdvo_priv),
-		  sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
-		  sdvo_priv->caps.device_rev_id,
-		  sdvo_priv->pixel_clock_min / 1000,
-		  sdvo_priv->pixel_clock_max / 1000,
-		  (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
-		  (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
-		  /* check currently supported outputs */
-		  sdvo_priv->caps.output_flags &
+	DRM_DEBUG_KMS(I915_SDVO, "%s device VID/DID: %02X:%02X.%02X, "
+			"clock range %dMHz - %dMHz, "
+			"input 1: %c, input 2: %c, "
+			"output 1: %c, output 2: %c\n",
+			SDVO_NAME(sdvo_priv),
+			sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
+			sdvo_priv->caps.device_rev_id,
+			sdvo_priv->pixel_clock_min / 1000,
+			sdvo_priv->pixel_clock_max / 1000,
+			(sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
+			(sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
+			/* check currently supported outputs */
+			sdvo_priv->caps.output_flags &
 			(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
-		  sdvo_priv->caps.output_flags &
+			sdvo_priv->caps.output_flags &
 			(SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
 
 	return true;
 
 err_i2c:
-	if (ddcbus != NULL)
+	if (intel_output->ddc_bus != NULL)
 		intel_i2c_destroy(intel_output->ddc_bus);
-	intel_i2c_destroy(intel_output->i2c_bus);
+	if (intel_output->i2c_bus != NULL)
+		intel_i2c_destroy(intel_output->i2c_bus);
 err_inteloutput:
 	kfree(intel_output);
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -715,6 +715,7 @@
   #define SDVO_HBUF_TX_ONCE	(2 << 6)
   #define SDVO_HBUF_TX_VSYNC	(3 << 6)
 #define SDVO_CMD_GET_AUDIO_TX_INFO	0x9c
+#define SDVO_NEED_TO_STALL  (1 << 7)
 
 struct intel_sdvo_encode{
     u8 dvi_rev;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_tv.c linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/intel_tv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/intel_tv.c	2009-09-09 18:13:59.000000000 -0400
@@ -1383,31 +1383,31 @@
 	/*
 	 * Detect TV by polling)
 	 */
-	if (intel_output->load_detect_temp) {
-		/* TV not currently running, prod it with destructive detect */
-		save_tv_dac = tv_dac;
-		tv_ctl = I915_READ(TV_CTL);
-		save_tv_ctl = tv_ctl;
-		tv_ctl &= ~TV_ENC_ENABLE;
-		tv_ctl &= ~TV_TEST_MODE_MASK;
-		tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
-		tv_dac &= ~TVDAC_SENSE_MASK;
-		tv_dac |= (TVDAC_STATE_CHG_EN |
-			   TVDAC_A_SENSE_CTL |
-			   TVDAC_B_SENSE_CTL |
-			   TVDAC_C_SENSE_CTL |
-			   DAC_CTL_OVERRIDE |
-			   DAC_A_0_7_V |
-			   DAC_B_0_7_V |
-			   DAC_C_0_7_V);
-		I915_WRITE(TV_CTL, tv_ctl);
-		I915_WRITE(TV_DAC, tv_dac);
-		intel_wait_for_vblank(dev);
-		tv_dac = I915_READ(TV_DAC);
-		I915_WRITE(TV_DAC, save_tv_dac);
-		I915_WRITE(TV_CTL, save_tv_ctl);
-		intel_wait_for_vblank(dev);
-	}
+	save_tv_dac = tv_dac;
+	tv_ctl = I915_READ(TV_CTL);
+	save_tv_ctl = tv_ctl;
+	tv_ctl &= ~TV_ENC_ENABLE;
+	tv_ctl &= ~TV_TEST_MODE_MASK;
+	tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
+	tv_dac &= ~TVDAC_SENSE_MASK;
+	tv_dac &= ~DAC_A_MASK;
+	tv_dac &= ~DAC_B_MASK;
+	tv_dac &= ~DAC_C_MASK;
+	tv_dac |= (TVDAC_STATE_CHG_EN |
+		   TVDAC_A_SENSE_CTL |
+		   TVDAC_B_SENSE_CTL |
+		   TVDAC_C_SENSE_CTL |
+		   DAC_CTL_OVERRIDE |
+		   DAC_A_0_7_V |
+		   DAC_B_0_7_V |
+		   DAC_C_0_7_V);
+	I915_WRITE(TV_CTL, tv_ctl);
+	I915_WRITE(TV_DAC, tv_dac);
+	intel_wait_for_vblank(dev);
+	tv_dac = I915_READ(TV_DAC);
+	I915_WRITE(TV_DAC, save_tv_dac);
+	I915_WRITE(TV_CTL, save_tv_ctl);
+	intel_wait_for_vblank(dev);
 	/*
 	 *  A B C
 	 *  0 1 1 Composite
@@ -1490,6 +1490,27 @@
 	{"1920x1080", 1920, 1080},
 };
 
+/*
+ * Chose preferred mode  according to line number of TV format
+ */
+static void
+intel_tv_chose_preferred_modes(struct drm_connector *connector,
+			       struct drm_display_mode *mode_ptr)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
+
+	if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
+		mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
+	else if (tv_mode->nbr_end > 480) {
+		if (tv_mode->progressive == true && tv_mode->nbr_end < 720) {
+			if (mode_ptr->vdisplay == 720)
+				mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
+		} else if (mode_ptr->vdisplay == 1080)
+				mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
+	}
+}
+
 /**
  * Stub get_modes function.
  *
@@ -1544,6 +1565,7 @@
 		mode_ptr->clock = (int) tmp;
 
 		mode_ptr->type = DRM_MODE_TYPE_DRIVER;
+		intel_tv_chose_preferred_modes(connector, mode_ptr);
 		drm_mode_probed_add(connector, mode_ptr);
 		count++;
 	}
@@ -1558,8 +1580,7 @@
 
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
-	drm_free(intel_output, sizeof(struct intel_output) + sizeof(struct intel_tv_priv),
-		 DRM_MEM_DRIVER);
+	kfree(intel_output);
 }
 
 
@@ -1692,11 +1713,12 @@
 	    (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
 		return;
 
-	intel_output = drm_calloc(1, sizeof(struct intel_output) +
-				  sizeof(struct intel_tv_priv), DRM_MEM_DRIVER);
+	intel_output = kzalloc(sizeof(struct intel_output) +
+			       sizeof(struct intel_tv_priv), GFP_KERNEL);
 	if (!intel_output) {
 		return;
 	}
+
 	connector = &intel_output->base;
 
 	drm_connector_init(dev, connector, &intel_tv_connector_funcs,
@@ -1708,6 +1730,8 @@
 	drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
 	tv_priv = (struct intel_tv_priv *)(intel_output + 1);
 	intel_output->type = INTEL_OUTPUT_TVOUT;
+	intel_output->crtc_mask = (1 << 0) | (1 << 1);
+	intel_output->clone_mask = (1 << INTEL_TV_CLONE_BIT);
 	intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));
 	intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
 	intel_output->dev_priv = tv_priv;
@@ -1727,8 +1751,8 @@
 	connector->doublescan_allowed = false;
 
 	/* Create TV properties then attach current values */
-	tv_format_names = drm_alloc(sizeof(char *) * NUM_TV_MODES,
-				    DRM_MEM_DRIVER);
+	tv_format_names = kmalloc(sizeof(char *) * NUM_TV_MODES,
+				  GFP_KERNEL);
 	if (!tv_format_names)
 		goto out;
 	for (i = 0; i < NUM_TV_MODES; i++)
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/Makefile linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/Makefile
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/i915/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/i915/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,8 @@
 	  intel_crt.o \
 	  intel_lvds.o \
 	  intel_bios.o \
+	  intel_dp.o \
+	  intel_dp_i2c.o \
 	  intel_hdmi.o \
 	  intel_sdvo.o \
 	  intel_modes.o \
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/Kconfig linux-libre-2.6.31-gnu/drivers/gpu/drm/Kconfig
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/Kconfig	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/Kconfig	2012-03-22 20:08:07.000000000 -0400
@@ -18,6 +18,14 @@
 	  details.  You should also select and configure AGP
 	  (/dev/agpgart) support.
 
+config DRM_TTM
+	tristate
+	depends on DRM
+	help
+	  GPU memory management subsystem for devices with multiple
+	  GPU memory types. Will be enabled automatically if a device driver
+	  uses it.
+
 config DRM_TDFX
 	tristate "3dfx Banshee/Voodoo3+"
 	depends on DRM && PCI
@@ -38,6 +46,11 @@
 depends on NONFREE
 	tristate "ATI Radeon"
 	depends on DRM && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB
+	select FRAMEBUFFER_CONSOLE if !EMBEDDED
 	help
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  are both PCI and AGP versions.  You don't need to choose this to
@@ -70,6 +83,7 @@
 
 config DRM_I915
 	tristate "i915 driver"
+	depends on AGP_INTEL
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/Makefile linux-libre-2.6.31-gnu/drivers/gpu/drm/Makefile
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 
 obj-$(CONFIG_DRM)	+= drm.o
+obj-$(CONFIG_DRM_TTM)	+= ttm/
 obj-$(CONFIG_DRM_TDFX)	+= tdfx/
 obj-$(CONFIG_DRM_R128)	+= r128/
 obj-$(CONFIG_DRM_RADEON)+= radeon/
@@ -26,4 +27,3 @@
 obj-$(CONFIG_DRM_SIS)   += sis/
 obj-$(CONFIG_DRM_SAVAGE)+= savage/
 obj-$(CONFIG_DRM_VIA)	+=via/
-
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/mga/mga_dma.c linux-libre-2.6.31-gnu/drivers/gpu/drm/mga/mga_dma.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/mga/mga_dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/mga/mga_dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -254,23 +254,20 @@
 	int i;
 	DRM_DEBUG("count=%d\n", dma->buf_count);
 
-	dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+	dev_priv->head = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL);
 	if (dev_priv->head == NULL)
 		return -ENOMEM;
 
-	memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
 	SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
 
 	for (i = 0; i < dma->buf_count; i++) {
 		buf = dma->buflist[i];
 		buf_priv = buf->dev_private;
 
-		entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+		entry = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL);
 		if (entry == NULL)
 			return -ENOMEM;
 
-		memset(entry, 0, sizeof(drm_mga_freelist_t));
-
 		entry->next = dev_priv->head->next;
 		entry->prev = dev_priv->head;
 		SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
@@ -301,7 +298,7 @@
 	entry = dev_priv->head;
 	while (entry) {
 		next = entry->next;
-		drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+		kfree(entry);
 		entry = next;
 	}
 
@@ -399,12 +396,11 @@
 	drm_mga_private_t *dev_priv;
 	int ret;
 
-	dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+	dev_priv = kzalloc(sizeof(drm_mga_private_t), GFP_KERNEL);
 	if (!dev_priv)
 		return -ENOMEM;
 
 	dev->dev_private = (void *)dev_priv;
-	memset(dev_priv, 0, sizeof(drm_mga_private_t));
 
 	dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
 	dev_priv->chipset = flags;
@@ -1150,7 +1146,7 @@
  */
 int mga_driver_unload(struct drm_device * dev)
 {
-	drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+	kfree(dev->dev_private);
 	dev->dev_private = NULL;
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/r128/r128_cce.c linux-libre-2.6.31-gnu/drivers/gpu/drm/r128/r128_cce.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/r128/r128_cce.c	2012-03-22 19:11:32.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/r128/r128_cce.c	2012-03-22 20:07:54.000000000 -0400
@@ -304,12 +304,10 @@
 
 	DRM_DEBUG("\n");
 
-	dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+	dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
-	memset(dev_priv, 0, sizeof(drm_r128_private_t));
-
 	dev_priv->is_pci = init->is_pci;
 
 	if (dev_priv->is_pci && !dev->sg) {
@@ -570,8 +568,7 @@
 					    ("failed to cleanup PCI GART!\n");
 		}
 
-		drm_free(dev->dev_private, sizeof(drm_r128_private_t),
-			 DRM_MEM_DRIVER);
+		kfree(dev->dev_private);
 		dev->dev_private = NULL;
 	}
 
@@ -719,18 +716,17 @@
 	drm_r128_freelist_t *entry;
 	int i;
 
-	dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+	dev_priv->head = kzalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL);
 	if (dev_priv->head == NULL)
 		return -ENOMEM;
 
-	memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
 	dev_priv->head->age = R128_BUFFER_USED;
 
 	for (i = 0; i < dma->buf_count; i++) {
 		buf = dma->buflist[i];
 		buf_priv = buf->dev_private;
 
-		entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+		entry = kmalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL);
 		if (!entry)
 			return -ENOMEM;
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/r128/r128_state.c linux-libre-2.6.31-gnu/drivers/gpu/drm/r128/r128_state.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/r128/r128_state.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/r128/r128_state.c	2009-09-09 18:13:59.000000000 -0400
@@ -910,24 +910,24 @@
 	}
 
 	buffer_size = depth->n * sizeof(u32);
-	buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+	buffer = kmalloc(buffer_size, GFP_KERNEL);
 	if (buffer == NULL)
 		return -ENOMEM;
 	if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
-		drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+		kfree(buffer);
 		return -EFAULT;
 	}
 
 	mask_size = depth->n * sizeof(u8);
 	if (depth->mask) {
-		mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+		mask = kmalloc(mask_size, GFP_KERNEL);
 		if (mask == NULL) {
-			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+			kfree(buffer);
 			return -ENOMEM;
 		}
 		if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
-			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-			drm_free(mask, mask_size, DRM_MEM_BUFS);
+			kfree(buffer);
+			kfree(mask);
 			return -EFAULT;
 		}
 
@@ -954,7 +954,7 @@
 			}
 		}
 
-		drm_free(mask, mask_size, DRM_MEM_BUFS);
+		kfree(mask);
 	} else {
 		for (i = 0; i < count; i++, x++) {
 			BEGIN_RING(6);
@@ -978,7 +978,7 @@
 		}
 	}
 
-	drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+	kfree(buffer);
 
 	return 0;
 }
@@ -1000,54 +1000,54 @@
 
 	xbuf_size = count * sizeof(*x);
 	ybuf_size = count * sizeof(*y);
-	x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+	x = kmalloc(xbuf_size, GFP_KERNEL);
 	if (x == NULL) {
 		return -ENOMEM;
 	}
-	y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+	y = kmalloc(ybuf_size, GFP_KERNEL);
 	if (y == NULL) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		kfree(x);
 		return -ENOMEM;
 	}
 	if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
-		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		kfree(x);
+		kfree(y);
 		return -EFAULT;
 	}
 	if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
-		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		kfree(x);
+		kfree(y);
 		return -EFAULT;
 	}
 
 	buffer_size = depth->n * sizeof(u32);
-	buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+	buffer = kmalloc(buffer_size, GFP_KERNEL);
 	if (buffer == NULL) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
-		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		kfree(x);
+		kfree(y);
 		return -ENOMEM;
 	}
 	if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
-		drm_free(y, ybuf_size, DRM_MEM_BUFS);
-		drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+		kfree(x);
+		kfree(y);
+		kfree(buffer);
 		return -EFAULT;
 	}
 
 	if (depth->mask) {
 		mask_size = depth->n * sizeof(u8);
-		mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+		mask = kmalloc(mask_size, GFP_KERNEL);
 		if (mask == NULL) {
-			drm_free(x, xbuf_size, DRM_MEM_BUFS);
-			drm_free(y, ybuf_size, DRM_MEM_BUFS);
-			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+			kfree(x);
+			kfree(y);
+			kfree(buffer);
 			return -ENOMEM;
 		}
 		if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
-			drm_free(x, xbuf_size, DRM_MEM_BUFS);
-			drm_free(y, ybuf_size, DRM_MEM_BUFS);
-			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-			drm_free(mask, mask_size, DRM_MEM_BUFS);
+			kfree(x);
+			kfree(y);
+			kfree(buffer);
+			kfree(mask);
 			return -EFAULT;
 		}
 
@@ -1074,7 +1074,7 @@
 			}
 		}
 
-		drm_free(mask, mask_size, DRM_MEM_BUFS);
+		kfree(mask);
 	} else {
 		for (i = 0; i < count; i++) {
 			BEGIN_RING(6);
@@ -1098,9 +1098,9 @@
 		}
 	}
 
-	drm_free(x, xbuf_size, DRM_MEM_BUFS);
-	drm_free(y, ybuf_size, DRM_MEM_BUFS);
-	drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+	kfree(x);
+	kfree(y);
+	kfree(buffer);
 
 	return 0;
 }
@@ -1167,23 +1167,23 @@
 
 	xbuf_size = count * sizeof(*x);
 	ybuf_size = count * sizeof(*y);
-	x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+	x = kmalloc(xbuf_size, GFP_KERNEL);
 	if (x == NULL) {
 		return -ENOMEM;
 	}
-	y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+	y = kmalloc(ybuf_size, GFP_KERNEL);
 	if (y == NULL) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		kfree(x);
 		return -ENOMEM;
 	}
 	if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
-		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		kfree(x);
+		kfree(y);
 		return -EFAULT;
 	}
 	if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
-		drm_free(x, xbuf_size, DRM_MEM_BUFS);
-		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		kfree(x);
+		kfree(y);
 		return -EFAULT;
 	}
 
@@ -1210,8 +1210,8 @@
 		ADVANCE_RING();
 	}
 
-	drm_free(x, xbuf_size, DRM_MEM_BUFS);
-	drm_free(y, ybuf_size, DRM_MEM_BUFS);
+	kfree(x);
+	kfree(y);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,694 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/radeon_drm.h>
+#include "radeon_fixed.h"
+#include "radeon.h"
+#include "atom.h"
+#include "atom-bits.h"
+
+static void atombios_overscan_setup(struct drm_crtc *crtc,
+				    struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	SET_CRTC_OVERSCAN_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
+	int a1, a2;
+
+	memset(&args, 0, sizeof(args));
+
+	args.usOverscanRight = 0;
+	args.usOverscanLeft = 0;
+	args.usOverscanBottom = 0;
+	args.usOverscanTop = 0;
+	args.ucCRTC = radeon_crtc->crtc_id;
+
+	switch (radeon_crtc->rmx_type) {
+	case RMX_CENTER:
+		args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+		args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+		args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+		args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		break;
+	case RMX_ASPECT:
+		a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
+		a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
+
+		if (a1 > a2) {
+			args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
+			args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
+		} else if (a2 > a1) {
+			args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
+			args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
+		}
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		break;
+	case RMX_FULL:
+	default:
+		args.usOverscanRight = 0;
+		args.usOverscanLeft = 0;
+		args.usOverscanBottom = 0;
+		args.usOverscanTop = 0;
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		break;
+	}
+}
+
+static void atombios_scaler_setup(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	ENABLE_SCALER_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
+	/* fixme - fill in enc_priv for atom dac */
+	enum radeon_tv_std tv_std = TV_STD_NTSC;
+
+	if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
+		return;
+
+	memset(&args, 0, sizeof(args));
+
+	args.ucScaler = radeon_crtc->crtc_id;
+
+	if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) {
+		switch (tv_std) {
+		case TV_STD_NTSC:
+		default:
+			args.ucTVStandard = ATOM_TV_NTSC;
+			break;
+		case TV_STD_PAL:
+			args.ucTVStandard = ATOM_TV_PAL;
+			break;
+		case TV_STD_PAL_M:
+			args.ucTVStandard = ATOM_TV_PALM;
+			break;
+		case TV_STD_PAL_60:
+			args.ucTVStandard = ATOM_TV_PAL60;
+			break;
+		case TV_STD_NTSC_J:
+			args.ucTVStandard = ATOM_TV_NTSCJ;
+			break;
+		case TV_STD_SCART_PAL:
+			args.ucTVStandard = ATOM_TV_PAL; /* ??? */
+			break;
+		case TV_STD_SECAM:
+			args.ucTVStandard = ATOM_TV_SECAM;
+			break;
+		case TV_STD_PAL_CN:
+			args.ucTVStandard = ATOM_TV_PALCN;
+			break;
+		}
+		args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
+	} else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) {
+		args.ucTVStandard = ATOM_TV_CV;
+		args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
+	} else {
+		switch (radeon_crtc->rmx_type) {
+		case RMX_FULL:
+			args.ucEnable = ATOM_SCALER_EXPANSION;
+			break;
+		case RMX_CENTER:
+			args.ucEnable = ATOM_SCALER_CENTER;
+			break;
+		case RMX_ASPECT:
+			args.ucEnable = ATOM_SCALER_EXPANSION;
+			break;
+		default:
+			if (ASIC_IS_AVIVO(rdev))
+				args.ucEnable = ATOM_SCALER_DISABLE;
+			else
+				args.ucEnable = ATOM_SCALER_CENTER;
+			break;
+		}
+	}
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+	if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
+	    && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
+		atom_rv515_force_tv_scaler(rdev);
+	}
+}
+
+static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int index =
+	    GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
+	ENABLE_CRTC_PS_ALLOCATION args;
+
+	memset(&args, 0, sizeof(args));
+
+	args.ucCRTC = radeon_crtc->crtc_id;
+	args.ucEnable = lock;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void atombios_enable_crtc(struct drm_crtc *crtc, int state)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
+	ENABLE_CRTC_PS_ALLOCATION args;
+
+	memset(&args, 0, sizeof(args));
+
+	args.ucCRTC = radeon_crtc->crtc_id;
+	args.ucEnable = state;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
+	ENABLE_CRTC_PS_ALLOCATION args;
+
+	memset(&args, 0, sizeof(args));
+
+	args.ucCRTC = radeon_crtc->crtc_id;
+	args.ucEnable = state;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
+	BLANK_CRTC_PS_ALLOCATION args;
+
+	memset(&args, 0, sizeof(args));
+
+	args.ucCRTC = radeon_crtc->crtc_id;
+	args.ucBlanking = state;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		if (ASIC_IS_DCE3(rdev))
+			atombios_enable_crtc_memreq(crtc, 1);
+		atombios_enable_crtc(crtc, 1);
+		atombios_blank_crtc(crtc, 0);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		atombios_blank_crtc(crtc, 1);
+		atombios_enable_crtc(crtc, 0);
+		if (ASIC_IS_DCE3(rdev))
+			atombios_enable_crtc_memreq(crtc, 0);
+		break;
+	}
+
+	if (mode != DRM_MODE_DPMS_OFF) {
+		radeon_crtc_load_lut(crtc);
+	}
+}
+
+static void
+atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
+			     SET_CRTC_USING_DTD_TIMING_PARAMETERS * crtc_param)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param;
+	int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
+
+	conv_param.usH_Size = cpu_to_le16(crtc_param->usH_Size);
+	conv_param.usH_Blanking_Time =
+	    cpu_to_le16(crtc_param->usH_Blanking_Time);
+	conv_param.usV_Size = cpu_to_le16(crtc_param->usV_Size);
+	conv_param.usV_Blanking_Time =
+	    cpu_to_le16(crtc_param->usV_Blanking_Time);
+	conv_param.usH_SyncOffset = cpu_to_le16(crtc_param->usH_SyncOffset);
+	conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
+	conv_param.usV_SyncOffset = cpu_to_le16(crtc_param->usV_SyncOffset);
+	conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
+	conv_param.susModeMiscInfo.usAccess =
+	    cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
+	conv_param.ucCRTC = crtc_param->ucCRTC;
+
+	printk("executing set crtc dtd timing\n");
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
+}
+
+void atombios_crtc_set_timing(struct drm_crtc *crtc,
+			      SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *
+			      crtc_param)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param;
+	int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
+
+	conv_param.usH_Total = cpu_to_le16(crtc_param->usH_Total);
+	conv_param.usH_Disp = cpu_to_le16(crtc_param->usH_Disp);
+	conv_param.usH_SyncStart = cpu_to_le16(crtc_param->usH_SyncStart);
+	conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
+	conv_param.usV_Total = cpu_to_le16(crtc_param->usV_Total);
+	conv_param.usV_Disp = cpu_to_le16(crtc_param->usV_Disp);
+	conv_param.usV_SyncStart = cpu_to_le16(crtc_param->usV_SyncStart);
+	conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
+	conv_param.susModeMiscInfo.usAccess =
+	    cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
+	conv_param.ucCRTC = crtc_param->ucCRTC;
+	conv_param.ucOverscanRight = crtc_param->ucOverscanRight;
+	conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft;
+	conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom;
+	conv_param.ucOverscanTop = crtc_param->ucOverscanTop;
+	conv_param.ucReserved = crtc_param->ucReserved;
+
+	printk("executing set crtc timing\n");
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
+}
+
+void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *encoder = NULL;
+	struct radeon_encoder *radeon_encoder = NULL;
+	uint8_t frev, crev;
+	int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
+	SET_PIXEL_CLOCK_PS_ALLOCATION args;
+	PIXEL_CLOCK_PARAMETERS *spc1_ptr;
+	PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
+	PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
+	uint32_t sclock = mode->clock;
+	uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
+	struct radeon_pll *pll;
+	int pll_flags = 0;
+
+	memset(&args, 0, sizeof(args));
+
+	if (ASIC_IS_AVIVO(rdev)) {
+		uint32_t ss_cntl;
+
+		if ((rdev->family == CHIP_RS600) ||
+		    (rdev->family == CHIP_RS690) ||
+		    (rdev->family == CHIP_RS740))
+			pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+				      RADEON_PLL_PREFER_CLOSEST_LOWER);
+
+		if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)	/* range limits??? */
+			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+		else
+			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
+		/* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
+		if (radeon_crtc->crtc_id == 0) {
+			ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
+			WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1);
+		} else {
+			ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);
+			WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1);
+		}
+	} else {
+		pll_flags |= RADEON_PLL_LEGACY;
+
+		if (mode->clock > 200000)	/* range limits??? */
+			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+		else
+			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc == crtc) {
+			if (!ASIC_IS_AVIVO(rdev)) {
+				if (encoder->encoder_type !=
+				    DRM_MODE_ENCODER_DAC)
+					pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+				if (!ASIC_IS_AVIVO(rdev)
+				    && (encoder->encoder_type ==
+					DRM_MODE_ENCODER_LVDS))
+					pll_flags |= RADEON_PLL_USE_REF_DIV;
+			}
+			radeon_encoder = to_radeon_encoder(encoder);
+		}
+	}
+
+	if (radeon_crtc->crtc_id == 0)
+		pll = &rdev->clock.p1pll;
+	else
+		pll = &rdev->clock.p2pll;
+
+	radeon_compute_pll(pll, mode->clock, &sclock, &fb_div, &frac_fb_div,
+			   &ref_div, &post_div, pll_flags);
+
+	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+			      &crev);
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+			spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
+			spc1_ptr->usPixelClock = cpu_to_le16(sclock);
+			spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
+			spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
+			spc1_ptr->ucFracFbDiv = frac_fb_div;
+			spc1_ptr->ucPostDiv = post_div;
+			spc1_ptr->ucPpll =
+			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
+			spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
+			spc1_ptr->ucRefDivSrc = 1;
+			break;
+		case 2:
+			spc2_ptr =
+			    (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
+			spc2_ptr->usPixelClock = cpu_to_le16(sclock);
+			spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
+			spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
+			spc2_ptr->ucFracFbDiv = frac_fb_div;
+			spc2_ptr->ucPostDiv = post_div;
+			spc2_ptr->ucPpll =
+			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
+			spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
+			spc2_ptr->ucRefDivSrc = 1;
+			break;
+		case 3:
+			if (!encoder)
+				return;
+			spc3_ptr =
+			    (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
+			spc3_ptr->usPixelClock = cpu_to_le16(sclock);
+			spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
+			spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
+			spc3_ptr->ucFracFbDiv = frac_fb_div;
+			spc3_ptr->ucPostDiv = post_div;
+			spc3_ptr->ucPpll =
+			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
+			spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
+			spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
+			spc3_ptr->ucEncoderMode =
+			    atombios_get_encoder_mode(encoder);
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+			return;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+		return;
+	}
+
+	printk("executing set pll\n");
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+			   struct drm_framebuffer *old_fb)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_framebuffer *radeon_fb;
+	struct drm_gem_object *obj;
+	struct drm_radeon_gem_object *obj_priv;
+	uint64_t fb_location;
+	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+
+	if (!crtc->fb)
+		return -EINVAL;
+
+	radeon_fb = to_radeon_framebuffer(crtc->fb);
+
+	obj = radeon_fb->obj;
+	obj_priv = obj->driver_private;
+
+	if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
+		return -EINVAL;
+	}
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 15:
+		fb_format =
+		    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
+		    AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
+		break;
+	case 16:
+		fb_format =
+		    AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
+		    AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
+		break;
+	case 24:
+	case 32:
+		fb_format =
+		    AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
+		    AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
+		break;
+	default:
+		DRM_ERROR("Unsupported screen depth %d\n",
+			  crtc->fb->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	radeon_object_get_tiling_flags(obj->driver_private,
+				       &tiling_flags, NULL);
+	if (tiling_flags & RADEON_TILING_MACRO)
+		fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
+
+	if (tiling_flags & RADEON_TILING_MICRO)
+		fb_format |= AVIVO_D1GRPH_TILED;
+
+	if (radeon_crtc->crtc_id == 0)
+		WREG32(AVIVO_D1VGA_CONTROL, 0);
+	else
+		WREG32(AVIVO_D2VGA_CONTROL, 0);
+	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32) fb_location);
+	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
+	       radeon_crtc->crtc_offset, (u32) fb_location);
+	WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
+
+	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
+	WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
+
+	fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
+	WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
+	WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
+
+	WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
+	       crtc->mode.vdisplay);
+	x &= ~3;
+	y &= ~1;
+	WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
+	       (x << 16) | y);
+	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
+	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
+
+	if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
+		WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
+		       AVIVO_D1MODE_INTERLEAVE_EN);
+	else
+		WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+
+	if (old_fb && old_fb != crtc->fb) {
+		radeon_fb = to_radeon_framebuffer(old_fb);
+		radeon_gem_object_unpin(radeon_fb->obj);
+	}
+	return 0;
+}
+
+int atombios_crtc_mode_set(struct drm_crtc *crtc,
+			   struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode,
+			   int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *encoder;
+	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
+
+	/* TODO color tiling */
+	memset(&crtc_timing, 0, sizeof(crtc_timing));
+
+	/* TODO tv */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+	}
+
+	crtc_timing.ucCRTC = radeon_crtc->crtc_id;
+	crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
+	crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
+	crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
+	crtc_timing.usH_SyncWidth =
+	    adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+
+	crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
+	crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
+	crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
+	crtc_timing.usV_SyncWidth =
+	    adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+		crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+		crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
+		crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+		crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
+
+	atombios_crtc_set_pll(crtc, adjusted_mode);
+	atombios_crtc_set_timing(crtc, &crtc_timing);
+
+	if (ASIC_IS_AVIVO(rdev))
+		atombios_crtc_set_base(crtc, x, y, old_fb);
+	else {
+		if (radeon_crtc->crtc_id == 0) {
+			SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing;
+			memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing));
+
+			/* setup FP shadow regs on R4xx */
+			crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id;
+			crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay;
+			crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay;
+			crtc_dtd_timing.usH_Blanking_Time =
+			    adjusted_mode->crtc_hblank_end -
+			    adjusted_mode->crtc_hdisplay;
+			crtc_dtd_timing.usV_Blanking_Time =
+			    adjusted_mode->crtc_vblank_end -
+			    adjusted_mode->crtc_vdisplay;
+			crtc_dtd_timing.usH_SyncOffset =
+			    adjusted_mode->crtc_hsync_start -
+			    adjusted_mode->crtc_hdisplay;
+			crtc_dtd_timing.usV_SyncOffset =
+			    adjusted_mode->crtc_vsync_start -
+			    adjusted_mode->crtc_vdisplay;
+			crtc_dtd_timing.usH_SyncWidth =
+			    adjusted_mode->crtc_hsync_end -
+			    adjusted_mode->crtc_hsync_start;
+			crtc_dtd_timing.usV_SyncWidth =
+			    adjusted_mode->crtc_vsync_end -
+			    adjusted_mode->crtc_vsync_start;
+			/* crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder; */
+			/* crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder; */
+
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+				crtc_dtd_timing.susModeMiscInfo.usAccess |=
+				    ATOM_VSYNC_POLARITY;
+
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+				crtc_dtd_timing.susModeMiscInfo.usAccess |=
+				    ATOM_HSYNC_POLARITY;
+
+			if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
+				crtc_dtd_timing.susModeMiscInfo.usAccess |=
+				    ATOM_COMPOSITESYNC;
+
+			if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+				crtc_dtd_timing.susModeMiscInfo.usAccess |=
+				    ATOM_INTERLACE;
+
+			if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+				crtc_dtd_timing.susModeMiscInfo.usAccess |=
+				    ATOM_DOUBLE_CLOCK_MODE;
+
+			atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing);
+		}
+		radeon_crtc_set_base(crtc, x, y, old_fb);
+		radeon_legacy_atom_set_surface(crtc);
+	}
+	atombios_overscan_setup(crtc, mode, adjusted_mode);
+	atombios_scaler_setup(crtc);
+	radeon_bandwidth_update(rdev);
+	return 0;
+}
+
+static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode)
+{
+	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
+		return false;
+	return true;
+}
+
+static void atombios_crtc_prepare(struct drm_crtc *crtc)
+{
+	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	atombios_lock_crtc(crtc, 1);
+}
+
+static void atombios_crtc_commit(struct drm_crtc *crtc)
+{
+	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+	atombios_lock_crtc(crtc, 0);
+}
+
+static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
+	.dpms = atombios_crtc_dpms,
+	.mode_fixup = atombios_crtc_mode_fixup,
+	.mode_set = atombios_crtc_mode_set,
+	.mode_set_base = atombios_crtc_set_base,
+	.prepare = atombios_crtc_prepare,
+	.commit = atombios_crtc_commit,
+};
+
+void radeon_atombios_init_crtc(struct drm_device *dev,
+			       struct radeon_crtc *radeon_crtc)
+{
+	if (radeon_crtc->crtc_id == 1)
+		radeon_crtc->crtc_offset =
+		    AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
+	drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atombios.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atombios.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atombios.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atombios.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,4785 @@
+/*
+ * Copyright 2006-2007 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/****************************************************************************/
+/*Portion I: Definitions  shared between VBIOS and Driver                   */
+/****************************************************************************/
+
+#ifndef _ATOMBIOS_H
+#define _ATOMBIOS_H
+
+#define ATOM_VERSION_MAJOR                   0x00020000
+#define ATOM_VERSION_MINOR                   0x00000002
+
+#define ATOM_HEADER_VERSION (ATOM_VERSION_MAJOR | ATOM_VERSION_MINOR)
+
+/* Endianness should be specified before inclusion,
+ * default to little endian
+ */
+#ifndef ATOM_BIG_ENDIAN
+#error Endian not specified
+#endif
+
+#ifdef _H2INC
+#ifndef ULONG
+typedef unsigned long ULONG;
+#endif
+
+#ifndef UCHAR
+typedef unsigned char UCHAR;
+#endif
+
+#ifndef USHORT
+typedef unsigned short USHORT;
+#endif
+#endif
+
+#define ATOM_DAC_A            0
+#define ATOM_DAC_B            1
+#define ATOM_EXT_DAC          2
+
+#define ATOM_CRTC1            0
+#define ATOM_CRTC2            1
+
+#define ATOM_DIGA             0
+#define ATOM_DIGB             1
+
+#define ATOM_PPLL1            0
+#define ATOM_PPLL2            1
+
+#define ATOM_SCALER1          0
+#define ATOM_SCALER2          1
+
+#define ATOM_SCALER_DISABLE   0
+#define ATOM_SCALER_CENTER    1
+#define ATOM_SCALER_EXPANSION 2
+#define ATOM_SCALER_MULTI_EX  3
+
+#define ATOM_DISABLE          0
+#define ATOM_ENABLE           1
+#define ATOM_LCD_BLOFF                          (ATOM_DISABLE+2)
+#define ATOM_LCD_BLON                           (ATOM_ENABLE+2)
+#define ATOM_LCD_BL_BRIGHTNESS_CONTROL          (ATOM_ENABLE+3)
+#define ATOM_LCD_SELFTEST_START									(ATOM_DISABLE+5)
+#define ATOM_LCD_SELFTEST_STOP									(ATOM_ENABLE+5)
+#define ATOM_ENCODER_INIT			                  (ATOM_DISABLE+7)
+
+#define ATOM_BLANKING         1
+#define ATOM_BLANKING_OFF     0
+
+#define ATOM_CURSOR1          0
+#define ATOM_CURSOR2          1
+
+#define ATOM_ICON1            0
+#define ATOM_ICON2            1
+
+#define ATOM_CRT1             0
+#define ATOM_CRT2             1
+
+#define ATOM_TV_NTSC          1
+#define ATOM_TV_NTSCJ         2
+#define ATOM_TV_PAL           3
+#define ATOM_TV_PALM          4
+#define ATOM_TV_PALCN         5
+#define ATOM_TV_PALN          6
+#define ATOM_TV_PAL60         7
+#define ATOM_TV_SECAM         8
+#define ATOM_TV_CV            16
+
+#define ATOM_DAC1_PS2         1
+#define ATOM_DAC1_CV          2
+#define ATOM_DAC1_NTSC        3
+#define ATOM_DAC1_PAL         4
+
+#define ATOM_DAC2_PS2         ATOM_DAC1_PS2
+#define ATOM_DAC2_CV          ATOM_DAC1_CV
+#define ATOM_DAC2_NTSC        ATOM_DAC1_NTSC
+#define ATOM_DAC2_PAL         ATOM_DAC1_PAL
+
+#define ATOM_PM_ON            0
+#define ATOM_PM_STANDBY       1
+#define ATOM_PM_SUSPEND       2
+#define ATOM_PM_OFF           3
+
+/* Bit0:{=0:single, =1:dual},
+   Bit1 {=0:666RGB, =1:888RGB},
+   Bit2:3:{Grey level}
+   Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888}*/
+
+#define ATOM_PANEL_MISC_DUAL               0x00000001
+#define ATOM_PANEL_MISC_888RGB             0x00000002
+#define ATOM_PANEL_MISC_GREY_LEVEL         0x0000000C
+#define ATOM_PANEL_MISC_FPDI               0x00000010
+#define ATOM_PANEL_MISC_GREY_LEVEL_SHIFT   2
+#define ATOM_PANEL_MISC_SPATIAL            0x00000020
+#define ATOM_PANEL_MISC_TEMPORAL           0x00000040
+#define ATOM_PANEL_MISC_API_ENABLED        0x00000080
+
+#define MEMTYPE_DDR1              "DDR1"
+#define MEMTYPE_DDR2              "DDR2"
+#define MEMTYPE_DDR3              "DDR3"
+#define MEMTYPE_DDR4              "DDR4"
+
+#define ASIC_BUS_TYPE_PCI         "PCI"
+#define ASIC_BUS_TYPE_AGP         "AGP"
+#define ASIC_BUS_TYPE_PCIE        "PCI_EXPRESS"
+
+/* Maximum size of that FireGL flag string */
+
+#define ATOM_FIREGL_FLAG_STRING     "FGL"	/* Flag used to enable FireGL Support */
+#define ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING  3	/* sizeof( ATOM_FIREGL_FLAG_STRING ) */
+
+#define ATOM_FAKE_DESKTOP_STRING    "DSK"	/* Flag used to enable mobile ASIC on Desktop */
+#define ATOM_MAX_SIZE_OF_FAKE_DESKTOP_STRING  ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING
+
+#define ATOM_M54T_FLAG_STRING       "M54T"	/* Flag used to enable M54T Support */
+#define ATOM_MAX_SIZE_OF_M54T_FLAG_STRING    4	/* sizeof( ATOM_M54T_FLAG_STRING ) */
+
+#define HW_ASSISTED_I2C_STATUS_FAILURE          2
+#define HW_ASSISTED_I2C_STATUS_SUCCESS          1
+
+#pragma pack(1)			/* BIOS data must use byte aligment */
+
+/*  Define offset to location of ROM header. */
+
+#define OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER		0x00000048L
+#define OFFSET_TO_ATOM_ROM_IMAGE_SIZE				    0x00000002L
+
+#define OFFSET_TO_ATOMBIOS_ASIC_BUS_MEM_TYPE    0x94
+#define MAXSIZE_OF_ATOMBIOS_ASIC_BUS_MEM_TYPE   20	/* including the terminator 0x0! */
+#define	OFFSET_TO_GET_ATOMBIOS_STRINGS_NUMBER		0x002f
+#define	OFFSET_TO_GET_ATOMBIOS_STRINGS_START		0x006e
+
+/* Common header for all ROM Data tables.
+  Every table pointed  _ATOM_MASTER_DATA_TABLE has this common header.
+  And the pointer actually points to this header. */
+
+typedef struct _ATOM_COMMON_TABLE_HEADER {
+	USHORT usStructureSize;
+	UCHAR ucTableFormatRevision;	/*Change it when the Parser is not backward compatible */
+	UCHAR ucTableContentRevision;	/*Change it only when the table needs to change but the firmware */
+	/*Image can't be updated, while Driver needs to carry the new table! */
+} ATOM_COMMON_TABLE_HEADER;
+
+typedef struct _ATOM_ROM_HEADER {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR uaFirmWareSignature[4];	/*Signature to distinguish between Atombios and non-atombios,
+					   atombios should init it as "ATOM", don't change the position */
+	USHORT usBiosRuntimeSegmentAddress;
+	USHORT usProtectedModeInfoOffset;
+	USHORT usConfigFilenameOffset;
+	USHORT usCRC_BlockOffset;
+	USHORT usBIOS_BootupMessageOffset;
+	USHORT usInt10Offset;
+	USHORT usPciBusDevInitCode;
+	USHORT usIoBaseAddress;
+	USHORT usSubsystemVendorID;
+	USHORT usSubsystemID;
+	USHORT usPCI_InfoOffset;
+	USHORT usMasterCommandTableOffset;	/*Offset for SW to get all command table offsets, Don't change the position */
+	USHORT usMasterDataTableOffset;	/*Offset for SW to get all data table offsets, Don't change the position */
+	UCHAR ucExtendedFunctionCode;
+	UCHAR ucReserved;
+} ATOM_ROM_HEADER;
+
+/*==============================Command Table Portion==================================== */
+
+#ifdef	UEFI_BUILD
+#define	UTEMP	USHORT
+#define	USHORT	void*
+#endif
+
+typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES {
+	USHORT ASIC_Init;	/* Function Table, used by various SW components,latest version 1.1 */
+	USHORT GetDisplaySurfaceSize;	/* Atomic Table,  Used by Bios when enabling HW ICON */
+	USHORT ASIC_RegistersInit;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
+	USHORT VRAM_BlockVenderDetection;	/* Atomic Table,  used only by Bios */
+	USHORT DIGxEncoderControl;	/* Only used by Bios */
+	USHORT MemoryControllerInit;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
+	USHORT EnableCRTCMemReq;	/* Function Table,directly used by various SW components,latest version 2.1 */
+	USHORT MemoryParamAdjust;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock if needed */
+	USHORT DVOEncoderControl;	/* Function Table,directly used by various SW components,latest version 1.2 */
+	USHORT GPIOPinControl;	/* Atomic Table,  only used by Bios */
+	USHORT SetEngineClock;	/*Function Table,directly used by various SW components,latest version 1.1 */
+	USHORT SetMemoryClock;	/* Function Table,directly used by various SW components,latest version 1.1 */
+	USHORT SetPixelClock;	/*Function Table,directly used by various SW components,latest version 1.2 */
+	USHORT DynamicClockGating;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
+	USHORT ResetMemoryDLL;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
+	USHORT ResetMemoryDevice;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
+	USHORT MemoryPLLInit;
+	USHORT AdjustDisplayPll;	/* only used by Bios */
+	USHORT AdjustMemoryController;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
+	USHORT EnableASIC_StaticPwrMgt;	/* Atomic Table,  only used by Bios */
+	USHORT ASIC_StaticPwrMgtStatusChange;	/* Obsolete, only used by Bios */
+	USHORT DAC_LoadDetection;	/* Atomic Table,  directly used by various SW components,latest version 1.2 */
+	USHORT LVTMAEncoderControl;	/* Atomic Table,directly used by various SW components,latest version 1.3 */
+	USHORT LCD1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT DAC1EncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT DAC2EncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT DVOOutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT CV1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT GetConditionalGoldenSetting;	/* only used by Bios */
+	USHORT TVEncoderControl;	/* Function Table,directly used by various SW components,latest version 1.1 */
+	USHORT TMDSAEncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.3 */
+	USHORT LVDSEncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.3 */
+	USHORT TV1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT EnableScaler;	/* Atomic Table,  used only by Bios */
+	USHORT BlankCRTC;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT EnableCRTC;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT GetPixelClock;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT EnableVGA_Render;	/* Function Table,directly used by various SW components,latest version 1.1 */
+	USHORT EnableVGA_Access;	/* Obsolete ,     only used by Bios */
+	USHORT SetCRTC_Timing;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT SetCRTC_OverScan;	/* Atomic Table,  used by various SW components,latest version 1.1 */
+	USHORT SetCRTC_Replication;	/* Atomic Table,  used only by Bios */
+	USHORT SelectCRTC_Source;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT EnableGraphSurfaces;	/* Atomic Table,  used only by Bios */
+	USHORT UpdateCRTC_DoubleBufferRegisters;
+	USHORT LUT_AutoFill;	/* Atomic Table,  only used by Bios */
+	USHORT EnableHW_IconCursor;	/* Atomic Table,  only used by Bios */
+	USHORT GetMemoryClock;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT GetEngineClock;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT SetCRTC_UsingDTDTiming;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT ExternalEncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 2.1 */
+	USHORT LVTMAOutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT VRAM_BlockDetectionByStrap;	/* Atomic Table,  used only by Bios */
+	USHORT MemoryCleanUp;	/* Atomic Table,  only used by Bios */
+	USHORT ProcessI2cChannelTransaction;	/* Function Table,only used by Bios */
+	USHORT WriteOneByteToHWAssistedI2C;	/* Function Table,indirectly used by various SW components */
+	USHORT ReadHWAssistedI2CStatus;	/* Atomic Table,  indirectly used by various SW components */
+	USHORT SpeedFanControl;	/* Function Table,indirectly used by various SW components,called from ASIC_Init */
+	USHORT PowerConnectorDetection;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT MC_Synchronization;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
+	USHORT ComputeMemoryEnginePLL;	/* Atomic Table,  indirectly used by various SW components,called from SetMemory/EngineClock */
+	USHORT MemoryRefreshConversion;	/* Atomic Table,  indirectly used by various SW components,called from SetMemory or SetEngineClock */
+	USHORT VRAM_GetCurrentInfoBlock;	/* Atomic Table,  used only by Bios */
+	USHORT DynamicMemorySettings;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
+	USHORT MemoryTraining;	/* Atomic Table,  used only by Bios */
+	USHORT EnableSpreadSpectrumOnPPLL;	/* Atomic Table,  directly used by various SW components,latest version 1.2 */
+	USHORT TMDSAOutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT SetVoltage;	/* Function Table,directly and/or indirectly used by various SW components,latest version 1.1 */
+	USHORT DAC1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT DAC2OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
+	USHORT SetupHWAssistedI2CStatus;	/* Function Table,only used by Bios, obsolete soon.Switch to use "ReadEDIDFromHWAssistedI2C" */
+	USHORT ClockSource;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
+	USHORT MemoryDeviceInit;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
+	USHORT EnableYUV;	/* Atomic Table,  indirectly used by various SW components,called from EnableVGARender */
+	USHORT DIG1EncoderControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
+	USHORT DIG2EncoderControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
+	USHORT DIG1TransmitterControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
+	USHORT DIG2TransmitterControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
+	USHORT ProcessAuxChannelTransaction;	/* Function Table,only used by Bios */
+	USHORT DPEncoderService;	/* Function Table,only used by Bios */
+} ATOM_MASTER_LIST_OF_COMMAND_TABLES;
+
+/*  For backward compatible */
+#define ReadEDIDFromHWAssistedI2C                ProcessI2cChannelTransaction
+#define UNIPHYTransmitterControl						     DIG1TransmitterControl
+#define LVTMATransmitterControl							     DIG2TransmitterControl
+#define SetCRTC_DPM_State                        GetConditionalGoldenSetting
+#define SetUniphyInstance                        ASIC_StaticPwrMgtStatusChange
+
+typedef struct _ATOM_MASTER_COMMAND_TABLE {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_MASTER_LIST_OF_COMMAND_TABLES ListOfCommandTables;
+} ATOM_MASTER_COMMAND_TABLE;
+
+/****************************************************************************/
+/*  Structures used in every command table */
+/****************************************************************************/
+typedef struct _ATOM_TABLE_ATTRIBUTE {
+#if ATOM_BIG_ENDIAN
+	USHORT UpdatedByUtility:1;	/* [15]=Table updated by utility flag */
+	USHORT PS_SizeInBytes:7;	/* [14:8]=Size of parameter space in Bytes (multiple of a dword), */
+	USHORT WS_SizeInBytes:8;	/* [7:0]=Size of workspace in Bytes (in multiple of a dword), */
+#else
+	USHORT WS_SizeInBytes:8;	/* [7:0]=Size of workspace in Bytes (in multiple of a dword), */
+	USHORT PS_SizeInBytes:7;	/* [14:8]=Size of parameter space in Bytes (multiple of a dword), */
+	USHORT UpdatedByUtility:1;	/* [15]=Table updated by utility flag */
+#endif
+} ATOM_TABLE_ATTRIBUTE;
+
+typedef union _ATOM_TABLE_ATTRIBUTE_ACCESS {
+	ATOM_TABLE_ATTRIBUTE sbfAccess;
+	USHORT susAccess;
+} ATOM_TABLE_ATTRIBUTE_ACCESS;
+
+/****************************************************************************/
+/*  Common header for all command tables. */
+/*  Every table pointed by _ATOM_MASTER_COMMAND_TABLE has this common header. */
+/*  And the pointer actually points to this header. */
+/****************************************************************************/
+typedef struct _ATOM_COMMON_ROM_COMMAND_TABLE_HEADER {
+	ATOM_COMMON_TABLE_HEADER CommonHeader;
+	ATOM_TABLE_ATTRIBUTE TableAttribute;
+} ATOM_COMMON_ROM_COMMAND_TABLE_HEADER;
+
+/****************************************************************************/
+/*  Structures used by ComputeMemoryEnginePLLTable */
+/****************************************************************************/
+#define COMPUTE_MEMORY_PLL_PARAM        1
+#define COMPUTE_ENGINE_PLL_PARAM        2
+
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS {
+	ULONG ulClock;		/* When returen, it's the re-calculated clock based on given Fb_div Post_Div and ref_div */
+	UCHAR ucAction;		/* 0:reserved //1:Memory //2:Engine */
+	UCHAR ucReserved;	/* may expand to return larger Fbdiv later */
+	UCHAR ucFbDiv;		/* return value */
+	UCHAR ucPostDiv;	/* return value */
+} COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS;
+
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 {
+	ULONG ulClock;		/* When return, [23:0] return real clock */
+	UCHAR ucAction;		/* 0:reserved;COMPUTE_MEMORY_PLL_PARAM:Memory;COMPUTE_ENGINE_PLL_PARAM:Engine. it return ref_div to be written to register */
+	USHORT usFbDiv;		/* return Feedback value to be written to register */
+	UCHAR ucPostDiv;	/* return post div to be written to register */
+} COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2;
+#define COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION   COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS
+
+#define SET_CLOCK_FREQ_MASK                     0x00FFFFFF	/* Clock change tables only take bit [23:0] as the requested clock value */
+#define USE_NON_BUS_CLOCK_MASK                  0x01000000	/* Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) */
+#define USE_MEMORY_SELF_REFRESH_MASK            0x02000000	/* Only applicable to memory clock change, when set, using memory self refresh during clock transition */
+#define SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE   0x04000000	/* Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change */
+#define FIRST_TIME_CHANGE_CLOCK									0x08000000	/* Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup */
+#define SKIP_SW_PROGRAM_PLL											0x10000000	/* Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL */
+#define USE_SS_ENABLED_PIXEL_CLOCK  USE_NON_BUS_CLOCK_MASK
+
+#define b3USE_NON_BUS_CLOCK_MASK                  0x01	/* Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) */
+#define b3USE_MEMORY_SELF_REFRESH                 0x02	/* Only applicable to memory clock change, when set, using memory self refresh during clock transition */
+#define b3SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE   0x04	/* Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change */
+#define b3FIRST_TIME_CHANGE_CLOCK									0x08	/* Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup */
+#define b3SKIP_SW_PROGRAM_PLL											0x10	/* Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL */
+
+typedef struct _ATOM_COMPUTE_CLOCK_FREQ {
+#if ATOM_BIG_ENDIAN
+	ULONG ulComputeClockFlag:8;	/*  =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM */
+	ULONG ulClockFreq:24;	/*  in unit of 10kHz */
+#else
+	ULONG ulClockFreq:24;	/*  in unit of 10kHz */
+	ULONG ulComputeClockFlag:8;	/*  =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM */
+#endif
+} ATOM_COMPUTE_CLOCK_FREQ;
+
+typedef struct _ATOM_S_MPLL_FB_DIVIDER {
+	USHORT usFbDivFrac;
+	USHORT usFbDiv;
+} ATOM_S_MPLL_FB_DIVIDER;
+
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 {
+	union {
+		ATOM_COMPUTE_CLOCK_FREQ ulClock;	/* Input Parameter */
+		ATOM_S_MPLL_FB_DIVIDER ulFbDiv;	/* Output Parameter */
+	};
+	UCHAR ucRefDiv;		/* Output Parameter */
+	UCHAR ucPostDiv;	/* Output Parameter */
+	UCHAR ucCntlFlag;	/* Output Parameter */
+	UCHAR ucReserved;
+} COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3;
+
+/*  ucCntlFlag */
+#define ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN          1
+#define ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE            2
+#define ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE         4
+
+typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER {
+	ATOM_COMPUTE_CLOCK_FREQ ulClock;
+	ULONG ulReserved[2];
+} DYNAMICE_MEMORY_SETTINGS_PARAMETER;
+
+typedef struct _DYNAMICE_ENGINE_SETTINGS_PARAMETER {
+	ATOM_COMPUTE_CLOCK_FREQ ulClock;
+	ULONG ulMemoryClock;
+	ULONG ulReserved;
+} DYNAMICE_ENGINE_SETTINGS_PARAMETER;
+
+/****************************************************************************/
+/*  Structures used by SetEngineClockTable */
+/****************************************************************************/
+typedef struct _SET_ENGINE_CLOCK_PARAMETERS {
+	ULONG ulTargetEngineClock;	/* In 10Khz unit */
+} SET_ENGINE_CLOCK_PARAMETERS;
+
+typedef struct _SET_ENGINE_CLOCK_PS_ALLOCATION {
+	ULONG ulTargetEngineClock;	/* In 10Khz unit */
+	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved;
+} SET_ENGINE_CLOCK_PS_ALLOCATION;
+
+/****************************************************************************/
+/*  Structures used by SetMemoryClockTable */
+/****************************************************************************/
+typedef struct _SET_MEMORY_CLOCK_PARAMETERS {
+	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
+} SET_MEMORY_CLOCK_PARAMETERS;
+
+typedef struct _SET_MEMORY_CLOCK_PS_ALLOCATION {
+	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
+	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved;
+} SET_MEMORY_CLOCK_PS_ALLOCATION;
+
+/****************************************************************************/
+/*  Structures used by ASIC_Init.ctb */
+/****************************************************************************/
+typedef struct _ASIC_INIT_PARAMETERS {
+	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
+	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
+} ASIC_INIT_PARAMETERS;
+
+typedef struct _ASIC_INIT_PS_ALLOCATION {
+	ASIC_INIT_PARAMETERS sASICInitClocks;
+	SET_ENGINE_CLOCK_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this structure */
+} ASIC_INIT_PS_ALLOCATION;
+
+/****************************************************************************/
+/*  Structure used by DynamicClockGatingTable.ctb */
+/****************************************************************************/
+typedef struct _DYNAMIC_CLOCK_GATING_PARAMETERS {
+	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
+	UCHAR ucPadding[3];
+} DYNAMIC_CLOCK_GATING_PARAMETERS;
+#define  DYNAMIC_CLOCK_GATING_PS_ALLOCATION  DYNAMIC_CLOCK_GATING_PARAMETERS
+
+/****************************************************************************/
+/*  Structure used by EnableASIC_StaticPwrMgtTable.ctb */
+/****************************************************************************/
+typedef struct _ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS {
+	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
+	UCHAR ucPadding[3];
+} ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS;
+#define ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION  ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by DAC_LoadDetectionTable.ctb */
+/****************************************************************************/
+typedef struct _DAC_LOAD_DETECTION_PARAMETERS {
+	USHORT usDeviceID;	/* {ATOM_DEVICE_CRTx_SUPPORT,ATOM_DEVICE_TVx_SUPPORT,ATOM_DEVICE_CVx_SUPPORT} */
+	UCHAR ucDacType;	/* {ATOM_DAC_A,ATOM_DAC_B, ATOM_EXT_DAC} */
+	UCHAR ucMisc;		/* Valid only when table revision =1.3 and above */
+} DAC_LOAD_DETECTION_PARAMETERS;
+
+/*  DAC_LOAD_DETECTION_PARAMETERS.ucMisc */
+#define DAC_LOAD_MISC_YPrPb						0x01
+
+typedef struct _DAC_LOAD_DETECTION_PS_ALLOCATION {
+	DAC_LOAD_DETECTION_PARAMETERS sDacload;
+	ULONG Reserved[2];	/*  Don't set this one, allocation for EXT DAC */
+} DAC_LOAD_DETECTION_PS_ALLOCATION;
+
+/****************************************************************************/
+/*  Structures used by DAC1EncoderControlTable.ctb and DAC2EncoderControlTable.ctb */
+/****************************************************************************/
+typedef struct _DAC_ENCODER_CONTROL_PARAMETERS {
+	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+	UCHAR ucDacStandard;	/*  See definition of ATOM_DACx_xxx, For DEC3.0, bit 7 used as internal flag to indicate DAC2 (==1) or DAC1 (==0) */
+	UCHAR ucAction;		/*  0: turn off encoder */
+	/*  1: setup and turn on encoder */
+	/*  7: ATOM_ENCODER_INIT Initialize DAC */
+} DAC_ENCODER_CONTROL_PARAMETERS;
+
+#define DAC_ENCODER_CONTROL_PS_ALLOCATION  DAC_ENCODER_CONTROL_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by DIG1EncoderControlTable */
+/*                     DIG2EncoderControlTable */
+/*                     ExternalEncoderControlTable */
+/****************************************************************************/
+typedef struct _DIG_ENCODER_CONTROL_PARAMETERS {
+	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+	UCHAR ucConfig;
+	/*  [2] Link Select: */
+	/*  =0: PHY linkA if bfLane<3 */
+	/*  =1: PHY linkB if bfLanes<3 */
+	/*  =0: PHY linkA+B if bfLanes=3 */
+	/*  [3] Transmitter Sel */
+	/*  =0: UNIPHY or PCIEPHY */
+	/*  =1: LVTMA */
+	UCHAR ucAction;		/*  =0: turn off encoder */
+	/*  =1: turn on encoder */
+	UCHAR ucEncoderMode;
+	/*  =0: DP   encoder */
+	/*  =1: LVDS encoder */
+	/*  =2: DVI  encoder */
+	/*  =3: HDMI encoder */
+	/*  =4: SDVO encoder */
+	UCHAR ucLaneNum;	/*  how many lanes to enable */
+	UCHAR ucReserved[2];
+} DIG_ENCODER_CONTROL_PARAMETERS;
+#define DIG_ENCODER_CONTROL_PS_ALLOCATION			  DIG_ENCODER_CONTROL_PARAMETERS
+#define EXTERNAL_ENCODER_CONTROL_PARAMETER			DIG_ENCODER_CONTROL_PARAMETERS
+
+/* ucConfig */
+#define ATOM_ENCODER_CONFIG_DPLINKRATE_MASK				0x01
+#define ATOM_ENCODER_CONFIG_DPLINKRATE_1_62GHZ		0x00
+#define ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ		0x01
+#define ATOM_ENCODER_CONFIG_LINK_SEL_MASK				  0x04
+#define ATOM_ENCODER_CONFIG_LINKA								  0x00
+#define ATOM_ENCODER_CONFIG_LINKB								  0x04
+#define ATOM_ENCODER_CONFIG_LINKA_B							  ATOM_TRANSMITTER_CONFIG_LINKA
+#define ATOM_ENCODER_CONFIG_LINKB_A							  ATOM_ENCODER_CONFIG_LINKB
+#define ATOM_ENCODER_CONFIG_TRANSMITTER_SEL_MASK	0x08
+#define ATOM_ENCODER_CONFIG_UNIPHY							  0x00
+#define ATOM_ENCODER_CONFIG_LVTMA								  0x08
+#define ATOM_ENCODER_CONFIG_TRANSMITTER1				  0x00
+#define ATOM_ENCODER_CONFIG_TRANSMITTER2				  0x08
+#define ATOM_ENCODER_CONFIG_DIGB								  0x80	/*  VBIOS Internal use, outside SW should set this bit=0 */
+/*  ucAction */
+/*  ATOM_ENABLE:  Enable Encoder */
+/*  ATOM_DISABLE: Disable Encoder */
+
+/* ucEncoderMode */
+#define ATOM_ENCODER_MODE_DP											0
+#define ATOM_ENCODER_MODE_LVDS										1
+#define ATOM_ENCODER_MODE_DVI											2
+#define ATOM_ENCODER_MODE_HDMI										3
+#define ATOM_ENCODER_MODE_SDVO										4
+#define ATOM_ENCODER_MODE_TV											13
+#define ATOM_ENCODER_MODE_CV											14
+#define ATOM_ENCODER_MODE_CRT											15
+
+typedef struct _ATOM_DIG_ENCODER_CONFIG_V2 {
+#if ATOM_BIG_ENDIAN
+	UCHAR ucReserved1:2;
+	UCHAR ucTransmitterSel:2;	/*  =0: UniphyAB, =1: UniphyCD  =2: UniphyEF */
+	UCHAR ucLinkSel:1;	/*  =0: linkA/C/E =1: linkB/D/F */
+	UCHAR ucReserved:1;
+	UCHAR ucDPLinkRate:1;	/*  =0: 1.62Ghz, =1: 2.7Ghz */
+#else
+	UCHAR ucDPLinkRate:1;	/*  =0: 1.62Ghz, =1: 2.7Ghz */
+	UCHAR ucReserved:1;
+	UCHAR ucLinkSel:1;	/*  =0: linkA/C/E =1: linkB/D/F */
+	UCHAR ucTransmitterSel:2;	/*  =0: UniphyAB, =1: UniphyCD  =2: UniphyEF */
+	UCHAR ucReserved1:2;
+#endif
+} ATOM_DIG_ENCODER_CONFIG_V2;
+
+typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V2 {
+	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+	ATOM_DIG_ENCODER_CONFIG_V2 acConfig;
+	UCHAR ucAction;
+	UCHAR ucEncoderMode;
+	/*  =0: DP   encoder */
+	/*  =1: LVDS encoder */
+	/*  =2: DVI  encoder */
+	/*  =3: HDMI encoder */
+	/*  =4: SDVO encoder */
+	UCHAR ucLaneNum;	/*  how many lanes to enable */
+	UCHAR ucReserved[2];
+} DIG_ENCODER_CONTROL_PARAMETERS_V2;
+
+/* ucConfig */
+#define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_MASK				0x01
+#define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_1_62GHZ		  0x00
+#define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_2_70GHZ		  0x01
+#define ATOM_ENCODER_CONFIG_V2_LINK_SEL_MASK				  0x04
+#define ATOM_ENCODER_CONFIG_V2_LINKA								  0x00
+#define ATOM_ENCODER_CONFIG_V2_LINKB								  0x04
+#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER_SEL_MASK	  0x18
+#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER1				    0x00
+#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER2				    0x08
+#define ATOM_ENCODER_CONFIG_V2_TRANSMITTER3				    0x10
+
+/****************************************************************************/
+/*  Structures used by UNIPHYTransmitterControlTable */
+/*                     LVTMATransmitterControlTable */
+/*                     DVOOutputControlTable */
+/****************************************************************************/
+typedef struct _ATOM_DP_VS_MODE {
+	UCHAR ucLaneSel;
+	UCHAR ucLaneSet;
+} ATOM_DP_VS_MODE;
+
+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS {
+	union {
+		USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+		USHORT usInitInfo;	/*  when init uniphy,lower 8bit is used for connector type defined in objectid.h */
+		ATOM_DP_VS_MODE asMode;	/*  DP Voltage swing mode */
+	};
+	UCHAR ucConfig;
+	/*  [0]=0: 4 lane Link, */
+	/*     =1: 8 lane Link ( Dual Links TMDS ) */
+	/*  [1]=0: InCoherent mode */
+	/*     =1: Coherent Mode */
+	/*  [2] Link Select: */
+	/*  =0: PHY linkA   if bfLane<3 */
+	/*  =1: PHY linkB   if bfLanes<3 */
+	/*  =0: PHY linkA+B if bfLanes=3 */
+	/*  [5:4]PCIE lane Sel */
+	/*  =0: lane 0~3 or 0~7 */
+	/*  =1: lane 4~7 */
+	/*  =2: lane 8~11 or 8~15 */
+	/*  =3: lane 12~15 */
+	UCHAR ucAction;		/*  =0: turn off encoder */
+	/*  =1: turn on encoder */
+	UCHAR ucReserved[4];
+} DIG_TRANSMITTER_CONTROL_PARAMETERS;
+
+#define DIG_TRANSMITTER_CONTROL_PS_ALLOCATION		DIG_TRANSMITTER_CONTROL_PARAMETERS
+
+/* ucInitInfo */
+#define ATOM_TRAMITTER_INITINFO_CONNECTOR_MASK	0x00ff
+
+/* ucConfig */
+#define ATOM_TRANSMITTER_CONFIG_8LANE_LINK			0x01
+#define ATOM_TRANSMITTER_CONFIG_COHERENT				0x02
+#define ATOM_TRANSMITTER_CONFIG_LINK_SEL_MASK		0x04
+#define ATOM_TRANSMITTER_CONFIG_LINKA						0x00
+#define ATOM_TRANSMITTER_CONFIG_LINKB						0x04
+#define ATOM_TRANSMITTER_CONFIG_LINKA_B					0x00
+#define ATOM_TRANSMITTER_CONFIG_LINKB_A					0x04
+
+#define ATOM_TRANSMITTER_CONFIG_ENCODER_SEL_MASK	0x08	/*  only used when ATOM_TRANSMITTER_ACTION_ENABLE */
+#define ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER		0x00	/*  only used when ATOM_TRANSMITTER_ACTION_ENABLE */
+#define ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER		0x08	/*  only used when ATOM_TRANSMITTER_ACTION_ENABLE */
+
+#define ATOM_TRANSMITTER_CONFIG_CLKSRC_MASK			0x30
+#define ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL			0x00
+#define ATOM_TRANSMITTER_CONFIG_CLKSRC_PCIE			0x20
+#define ATOM_TRANSMITTER_CONFIG_CLKSRC_XTALIN		0x30
+#define ATOM_TRANSMITTER_CONFIG_LANE_SEL_MASK		0xc0
+#define ATOM_TRANSMITTER_CONFIG_LANE_0_3				0x00
+#define ATOM_TRANSMITTER_CONFIG_LANE_0_7				0x00
+#define ATOM_TRANSMITTER_CONFIG_LANE_4_7				0x40
+#define ATOM_TRANSMITTER_CONFIG_LANE_8_11				0x80
+#define ATOM_TRANSMITTER_CONFIG_LANE_8_15				0x80
+#define ATOM_TRANSMITTER_CONFIG_LANE_12_15			0xc0
+
+/* ucAction */
+#define ATOM_TRANSMITTER_ACTION_DISABLE					       0
+#define ATOM_TRANSMITTER_ACTION_ENABLE					       1
+#define ATOM_TRANSMITTER_ACTION_LCD_BLOFF				       2
+#define ATOM_TRANSMITTER_ACTION_LCD_BLON				       3
+#define ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL  4
+#define ATOM_TRANSMITTER_ACTION_LCD_SELFTEST_START		 5
+#define ATOM_TRANSMITTER_ACTION_LCD_SELFTEST_STOP			 6
+#define ATOM_TRANSMITTER_ACTION_INIT						       7
+#define ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT	       8
+#define ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT		       9
+#define ATOM_TRANSMITTER_ACTION_SETUP						       10
+#define ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH           11
+
+/*  Following are used for DigTransmitterControlTable ver1.2 */
+typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V2 {
+#if ATOM_BIG_ENDIAN
+	UCHAR ucTransmitterSel:2;	/* bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) */
+	/*         =1 Dig Transmitter 2 ( Uniphy CD ) */
+	/*         =2 Dig Transmitter 3 ( Uniphy EF ) */
+	UCHAR ucReserved:1;
+	UCHAR fDPConnector:1;	/* bit4=0: DP connector  =1: None DP connector */
+	UCHAR ucEncoderSel:1;	/* bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) */
+	UCHAR ucLinkSel:1;	/* bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E */
+	/*     =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F */
+
+	UCHAR fCoherentMode:1;	/* bit1=1: Coherent Mode ( for DVI/HDMI mode ) */
+	UCHAR fDualLinkConnector:1;	/* bit0=1: Dual Link DVI connector */
+#else
+	UCHAR fDualLinkConnector:1;	/* bit0=1: Dual Link DVI connector */
+	UCHAR fCoherentMode:1;	/* bit1=1: Coherent Mode ( for DVI/HDMI mode ) */
+	UCHAR ucLinkSel:1;	/* bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E */
+	/*     =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F */
+	UCHAR ucEncoderSel:1;	/* bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) */
+	UCHAR fDPConnector:1;	/* bit4=0: DP connector  =1: None DP connector */
+	UCHAR ucReserved:1;
+	UCHAR ucTransmitterSel:2;	/* bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) */
+	/*         =1 Dig Transmitter 2 ( Uniphy CD ) */
+	/*         =2 Dig Transmitter 3 ( Uniphy EF ) */
+#endif
+} ATOM_DIG_TRANSMITTER_CONFIG_V2;
+
+/* ucConfig */
+/* Bit0 */
+#define ATOM_TRANSMITTER_CONFIG_V2_DUAL_LINK_CONNECTOR			0x01
+
+/* Bit1 */
+#define ATOM_TRANSMITTER_CONFIG_V2_COHERENT				          0x02
+
+/* Bit2 */
+#define ATOM_TRANSMITTER_CONFIG_V2_LINK_SEL_MASK		        0x04
+#define ATOM_TRANSMITTER_CONFIG_V2_LINKA			            0x00
+#define ATOM_TRANSMITTER_CONFIG_V2_LINKB				            0x04
+
+/*  Bit3 */
+#define ATOM_TRANSMITTER_CONFIG_V2_ENCODER_SEL_MASK	        0x08
+#define ATOM_TRANSMITTER_CONFIG_V2_DIG1_ENCODER		          0x00	/*  only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP */
+#define ATOM_TRANSMITTER_CONFIG_V2_DIG2_ENCODER		          0x08	/*  only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP */
+
+/*  Bit4 */
+#define ATOM_TRASMITTER_CONFIG_V2_DP_CONNECTOR			        0x10
+
+/*  Bit7:6 */
+#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER_SEL_MASK     0xC0
+#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER1			0x00	/* AB */
+#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER2			0x40	/* CD */
+#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER3			0x80	/* EF */
+
+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 {
+	union {
+		USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+		USHORT usInitInfo;	/*  when init uniphy,lower 8bit is used for connector type defined in objectid.h */
+		ATOM_DP_VS_MODE asMode;	/*  DP Voltage swing mode */
+	};
+	ATOM_DIG_TRANSMITTER_CONFIG_V2 acConfig;
+	UCHAR ucAction;		/*  define as ATOM_TRANSMITER_ACTION_XXX */
+	UCHAR ucReserved[4];
+} DIG_TRANSMITTER_CONTROL_PARAMETERS_V2;
+
+/****************************************************************************/
+/*  Structures used by DAC1OuputControlTable */
+/*                     DAC2OuputControlTable */
+/*                     LVTMAOutputControlTable  (Before DEC30) */
+/*                     TMDSAOutputControlTable  (Before DEC30) */
+/****************************************************************************/
+typedef struct _DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS {
+	UCHAR ucAction;		/*  Possible input:ATOM_ENABLE||ATOMDISABLE */
+	/*  When the display is LCD, in addition to above: */
+	/*  ATOM_LCD_BLOFF|| ATOM_LCD_BLON ||ATOM_LCD_BL_BRIGHTNESS_CONTROL||ATOM_LCD_SELFTEST_START|| */
+	/*  ATOM_LCD_SELFTEST_STOP */
+
+	UCHAR aucPadding[3];	/*  padding to DWORD aligned */
+} DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS;
+
+#define DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+
+#define CRT1_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define CRT1_OUTPUT_CONTROL_PS_ALLOCATION  DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define CRT2_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define CRT2_OUTPUT_CONTROL_PS_ALLOCATION  DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define CV1_OUTPUT_CONTROL_PARAMETERS      DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define CV1_OUTPUT_CONTROL_PS_ALLOCATION   DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define TV1_OUTPUT_CONTROL_PARAMETERS      DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define TV1_OUTPUT_CONTROL_PS_ALLOCATION   DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define DFP1_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define DFP1_OUTPUT_CONTROL_PS_ALLOCATION  DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define DFP2_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define DFP2_OUTPUT_CONTROL_PS_ALLOCATION  DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define LCD1_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define LCD1_OUTPUT_CONTROL_PS_ALLOCATION  DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define DVO_OUTPUT_CONTROL_PARAMETERS      DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define DVO_OUTPUT_CONTROL_PS_ALLOCATION   DIG_TRANSMITTER_CONTROL_PS_ALLOCATION
+#define DVO_OUTPUT_CONTROL_PARAMETERS_V3	 DIG_TRANSMITTER_CONTROL_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by BlankCRTCTable */
+/****************************************************************************/
+typedef struct _BLANK_CRTC_PARAMETERS {
+	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucBlanking;	/*  ATOM_BLANKING or ATOM_BLANKINGOFF */
+	USHORT usBlackColorRCr;
+	USHORT usBlackColorGY;
+	USHORT usBlackColorBCb;
+} BLANK_CRTC_PARAMETERS;
+#define BLANK_CRTC_PS_ALLOCATION    BLANK_CRTC_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by EnableCRTCTable */
+/*                     EnableCRTCMemReqTable */
+/*                     UpdateCRTC_DoubleBufferRegistersTable */
+/****************************************************************************/
+typedef struct _ENABLE_CRTC_PARAMETERS {
+	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
+	UCHAR ucPadding[2];
+} ENABLE_CRTC_PARAMETERS;
+#define ENABLE_CRTC_PS_ALLOCATION   ENABLE_CRTC_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by SetCRTC_OverScanTable */
+/****************************************************************************/
+typedef struct _SET_CRTC_OVERSCAN_PARAMETERS {
+	USHORT usOverscanRight;	/*  right */
+	USHORT usOverscanLeft;	/*  left */
+	USHORT usOverscanBottom;	/*  bottom */
+	USHORT usOverscanTop;	/*  top */
+	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucPadding[3];
+} SET_CRTC_OVERSCAN_PARAMETERS;
+#define SET_CRTC_OVERSCAN_PS_ALLOCATION  SET_CRTC_OVERSCAN_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by SetCRTC_ReplicationTable */
+/****************************************************************************/
+typedef struct _SET_CRTC_REPLICATION_PARAMETERS {
+	UCHAR ucH_Replication;	/*  horizontal replication */
+	UCHAR ucV_Replication;	/*  vertical replication */
+	UCHAR usCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucPadding;
+} SET_CRTC_REPLICATION_PARAMETERS;
+#define SET_CRTC_REPLICATION_PS_ALLOCATION  SET_CRTC_REPLICATION_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by SelectCRTC_SourceTable */
+/****************************************************************************/
+typedef struct _SELECT_CRTC_SOURCE_PARAMETERS {
+	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucDevice;		/*  ATOM_DEVICE_CRT1|ATOM_DEVICE_CRT2|.... */
+	UCHAR ucPadding[2];
+} SELECT_CRTC_SOURCE_PARAMETERS;
+#define SELECT_CRTC_SOURCE_PS_ALLOCATION  SELECT_CRTC_SOURCE_PARAMETERS
+
+typedef struct _SELECT_CRTC_SOURCE_PARAMETERS_V2 {
+	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucEncoderID;	/*  DAC1/DAC2/TVOUT/DIG1/DIG2/DVO */
+	UCHAR ucEncodeMode;	/*  Encoding mode, only valid when using DIG1/DIG2/DVO */
+	UCHAR ucPadding;
+} SELECT_CRTC_SOURCE_PARAMETERS_V2;
+
+/* ucEncoderID */
+/* #define ASIC_INT_DAC1_ENCODER_ID                                              0x00 */
+/* #define ASIC_INT_TV_ENCODER_ID                                                                        0x02 */
+/* #define ASIC_INT_DIG1_ENCODER_ID                                                              0x03 */
+/* #define ASIC_INT_DAC2_ENCODER_ID                                                              0x04 */
+/* #define ASIC_EXT_TV_ENCODER_ID                                                                        0x06 */
+/* #define ASIC_INT_DVO_ENCODER_ID                                                                       0x07 */
+/* #define ASIC_INT_DIG2_ENCODER_ID                                                              0x09 */
+/* #define ASIC_EXT_DIG_ENCODER_ID                                                                       0x05 */
+
+/* ucEncodeMode */
+/* #define ATOM_ENCODER_MODE_DP                                                                          0 */
+/* #define ATOM_ENCODER_MODE_LVDS                                                                        1 */
+/* #define ATOM_ENCODER_MODE_DVI                                                                         2 */
+/* #define ATOM_ENCODER_MODE_HDMI                                                                        3 */
+/* #define ATOM_ENCODER_MODE_SDVO                                                                        4 */
+/* #define ATOM_ENCODER_MODE_TV                                                                          13 */
+/* #define ATOM_ENCODER_MODE_CV                                                                          14 */
+/* #define ATOM_ENCODER_MODE_CRT                                                                         15 */
+
+/****************************************************************************/
+/*  Structures used by SetPixelClockTable */
+/*                     GetPixelClockTable */
+/****************************************************************************/
+/* Major revision=1., Minor revision=1 */
+typedef struct _PIXEL_CLOCK_PARAMETERS {
+	USHORT usPixelClock;	/*  in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */
+	/*  0 means disable PPLL */
+	USHORT usRefDiv;	/*  Reference divider */
+	USHORT usFbDiv;		/*  feedback divider */
+	UCHAR ucPostDiv;	/*  post divider */
+	UCHAR ucFracFbDiv;	/*  fractional feedback divider */
+	UCHAR ucPpll;		/*  ATOM_PPLL1 or ATOM_PPL2 */
+	UCHAR ucRefDivSrc;	/*  ATOM_PJITTER or ATO_NONPJITTER */
+	UCHAR ucCRTC;		/*  Which CRTC uses this Ppll */
+	UCHAR ucPadding;
+} PIXEL_CLOCK_PARAMETERS;
+
+/* Major revision=1., Minor revision=2, add ucMiscIfno */
+/* ucMiscInfo: */
+#define MISC_FORCE_REPROG_PIXEL_CLOCK 0x1
+#define MISC_DEVICE_INDEX_MASK        0xF0
+#define MISC_DEVICE_INDEX_SHIFT       4
+
+typedef struct _PIXEL_CLOCK_PARAMETERS_V2 {
+	USHORT usPixelClock;	/*  in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */
+	/*  0 means disable PPLL */
+	USHORT usRefDiv;	/*  Reference divider */
+	USHORT usFbDiv;		/*  feedback divider */
+	UCHAR ucPostDiv;	/*  post divider */
+	UCHAR ucFracFbDiv;	/*  fractional feedback divider */
+	UCHAR ucPpll;		/*  ATOM_PPLL1 or ATOM_PPL2 */
+	UCHAR ucRefDivSrc;	/*  ATOM_PJITTER or ATO_NONPJITTER */
+	UCHAR ucCRTC;		/*  Which CRTC uses this Ppll */
+	UCHAR ucMiscInfo;	/*  Different bits for different purpose, bit [7:4] as device index, bit[0]=Force prog */
+} PIXEL_CLOCK_PARAMETERS_V2;
+
+/* Major revision=1., Minor revision=3, structure/definition change */
+/* ucEncoderMode: */
+/* ATOM_ENCODER_MODE_DP */
+/* ATOM_ENOCDER_MODE_LVDS */
+/* ATOM_ENOCDER_MODE_DVI */
+/* ATOM_ENOCDER_MODE_HDMI */
+/* ATOM_ENOCDER_MODE_SDVO */
+/* ATOM_ENCODER_MODE_TV                                                                          13 */
+/* ATOM_ENCODER_MODE_CV                                                                          14 */
+/* ATOM_ENCODER_MODE_CRT                                                                         15 */
+
+/* ucDVOConfig */
+/* #define DVO_ENCODER_CONFIG_RATE_SEL                                                   0x01 */
+/* #define DVO_ENCODER_CONFIG_DDR_SPEED                                          0x00 */
+/* #define DVO_ENCODER_CONFIG_SDR_SPEED                                          0x01 */
+/* #define DVO_ENCODER_CONFIG_OUTPUT_SEL                                         0x0c */
+/* #define DVO_ENCODER_CONFIG_LOW12BIT                                                   0x00 */
+/* #define DVO_ENCODER_CONFIG_UPPER12BIT                                         0x04 */
+/* #define DVO_ENCODER_CONFIG_24BIT                                                              0x08 */
+
+/* ucMiscInfo: also changed, see below */
+#define PIXEL_CLOCK_MISC_FORCE_PROG_PPLL						0x01
+#define PIXEL_CLOCK_MISC_VGA_MODE										0x02
+#define PIXEL_CLOCK_MISC_CRTC_SEL_MASK							0x04
+#define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1							0x00
+#define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2							0x04
+#define PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK			0x08
+
+typedef struct _PIXEL_CLOCK_PARAMETERS_V3 {
+	USHORT usPixelClock;	/*  in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */
+	/*  0 means disable PPLL. For VGA PPLL,make sure this value is not 0. */
+	USHORT usRefDiv;	/*  Reference divider */
+	USHORT usFbDiv;		/*  feedback divider */
+	UCHAR ucPostDiv;	/*  post divider */
+	UCHAR ucFracFbDiv;	/*  fractional feedback divider */
+	UCHAR ucPpll;		/*  ATOM_PPLL1 or ATOM_PPL2 */
+	UCHAR ucTransmitterId;	/*  graphic encoder id defined in objectId.h */
+	union {
+		UCHAR ucEncoderMode;	/*  encoder type defined as ATOM_ENCODER_MODE_DP/DVI/HDMI/ */
+		UCHAR ucDVOConfig;	/*  when use DVO, need to know SDR/DDR, 12bit or 24bit */
+	};
+	UCHAR ucMiscInfo;	/*  bit[0]=Force program, bit[1]= set pclk for VGA, b[2]= CRTC sel */
+	/*  bit[3]=0:use PPLL for dispclk source, =1: use engine clock for dispclock source */
+} PIXEL_CLOCK_PARAMETERS_V3;
+
+#define PIXEL_CLOCK_PARAMETERS_LAST			PIXEL_CLOCK_PARAMETERS_V2
+#define GET_PIXEL_CLOCK_PS_ALLOCATION		PIXEL_CLOCK_PARAMETERS_LAST
+
+/****************************************************************************/
+/*  Structures used by AdjustDisplayPllTable */
+/****************************************************************************/
+typedef struct _ADJUST_DISPLAY_PLL_PARAMETERS {
+	USHORT usPixelClock;
+	UCHAR ucTransmitterID;
+	UCHAR ucEncodeMode;
+	union {
+		UCHAR ucDVOConfig;	/* if DVO, need passing link rate and output 12bitlow or 24bit */
+		UCHAR ucConfig;	/* if none DVO, not defined yet */
+	};
+	UCHAR ucReserved[3];
+} ADJUST_DISPLAY_PLL_PARAMETERS;
+
+#define ADJUST_DISPLAY_CONFIG_SS_ENABLE       0x10
+
+#define ADJUST_DISPLAY_PLL_PS_ALLOCATION			ADJUST_DISPLAY_PLL_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by EnableYUVTable */
+/****************************************************************************/
+typedef struct _ENABLE_YUV_PARAMETERS {
+	UCHAR ucEnable;		/*  ATOM_ENABLE:Enable YUV or ATOM_DISABLE:Disable YUV (RGB) */
+	UCHAR ucCRTC;		/*  Which CRTC needs this YUV or RGB format */
+	UCHAR ucPadding[2];
+} ENABLE_YUV_PARAMETERS;
+#define ENABLE_YUV_PS_ALLOCATION ENABLE_YUV_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by GetMemoryClockTable */
+/****************************************************************************/
+typedef struct _GET_MEMORY_CLOCK_PARAMETERS {
+	ULONG ulReturnMemoryClock;	/*  current memory speed in 10KHz unit */
+} GET_MEMORY_CLOCK_PARAMETERS;
+#define GET_MEMORY_CLOCK_PS_ALLOCATION  GET_MEMORY_CLOCK_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by GetEngineClockTable */
+/****************************************************************************/
+typedef struct _GET_ENGINE_CLOCK_PARAMETERS {
+	ULONG ulReturnEngineClock;	/*  current engine speed in 10KHz unit */
+} GET_ENGINE_CLOCK_PARAMETERS;
+#define GET_ENGINE_CLOCK_PS_ALLOCATION  GET_ENGINE_CLOCK_PARAMETERS
+
+/****************************************************************************/
+/*  Following Structures and constant may be obsolete */
+/****************************************************************************/
+/* Maxium 8 bytes,the data read in will be placed in the parameter space. */
+/* Read operaion successeful when the paramter space is non-zero, otherwise read operation failed */
+typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS {
+	USHORT usPrescale;	/* Ratio between Engine clock and I2C clock */
+	USHORT usVRAMAddress;	/* Adress in Frame Buffer where to pace raw EDID */
+	USHORT usStatus;	/* When use output: lower byte EDID checksum, high byte hardware status */
+	/* WHen use input:  lower byte as 'byte to read':currently limited to 128byte or 1byte */
+	UCHAR ucSlaveAddr;	/* Read from which slave */
+	UCHAR ucLineNumber;	/* Read from which HW assisted line */
+} READ_EDID_FROM_HW_I2C_DATA_PARAMETERS;
+#define READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION  READ_EDID_FROM_HW_I2C_DATA_PARAMETERS
+
+#define  ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSDATABYTE                  0
+#define  ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSTWODATABYTES              1
+#define  ATOM_WRITE_I2C_FORMAT_PSCOUNTER_PSOFFSET_IDDATABLOCK       2
+#define  ATOM_WRITE_I2C_FORMAT_PSCOUNTER_IDOFFSET_PLUS_IDDATABLOCK  3
+#define  ATOM_WRITE_I2C_FORMAT_IDCOUNTER_IDOFFSET_IDDATABLOCK       4
+
+typedef struct _WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS {
+	USHORT usPrescale;	/* Ratio between Engine clock and I2C clock */
+	USHORT usByteOffset;	/* Write to which byte */
+	/* Upper portion of usByteOffset is Format of data */
+	/* 1bytePS+offsetPS */
+	/* 2bytesPS+offsetPS */
+	/* blockID+offsetPS */
+	/* blockID+offsetID */
+	/* blockID+counterID+offsetID */
+	UCHAR ucData;		/* PS data1 */
+	UCHAR ucStatus;		/* Status byte 1=success, 2=failure, Also is used as PS data2 */
+	UCHAR ucSlaveAddr;	/* Write to which slave */
+	UCHAR ucLineNumber;	/* Write from which HW assisted line */
+} WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS;
+
+#define WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION  WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
+
+typedef struct _SET_UP_HW_I2C_DATA_PARAMETERS {
+	USHORT usPrescale;	/* Ratio between Engine clock and I2C clock */
+	UCHAR ucSlaveAddr;	/* Write to which slave */
+	UCHAR ucLineNumber;	/* Write from which HW assisted line */
+} SET_UP_HW_I2C_DATA_PARAMETERS;
+
+/**************************************************************************/
+#define SPEED_FAN_CONTROL_PS_ALLOCATION   WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
+
+/****************************************************************************/
+/*  Structures used by PowerConnectorDetectionTable */
+/****************************************************************************/
+typedef struct _POWER_CONNECTOR_DETECTION_PARAMETERS {
+	UCHAR ucPowerConnectorStatus;	/* Used for return value 0: detected, 1:not detected */
+	UCHAR ucPwrBehaviorId;
+	USHORT usPwrBudget;	/* how much power currently boot to in unit of watt */
+} POWER_CONNECTOR_DETECTION_PARAMETERS;
+
+typedef struct POWER_CONNECTOR_DETECTION_PS_ALLOCATION {
+	UCHAR ucPowerConnectorStatus;	/* Used for return value 0: detected, 1:not detected */
+	UCHAR ucReserved;
+	USHORT usPwrBudget;	/* how much power currently boot to in unit of watt */
+	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
+} POWER_CONNECTOR_DETECTION_PS_ALLOCATION;
+
+/****************************LVDS SS Command Table Definitions**********************/
+
+/****************************************************************************/
+/*  Structures used by EnableSpreadSpectrumOnPPLLTable */
+/****************************************************************************/
+typedef struct _ENABLE_LVDS_SS_PARAMETERS {
+	USHORT usSpreadSpectrumPercentage;
+	UCHAR ucSpreadSpectrumType;	/* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
+	UCHAR ucSpreadSpectrumStepSize_Delay;	/* bits3:2 SS_STEP_SIZE; bit 6:4 SS_DELAY */
+	UCHAR ucEnable;		/* ATOM_ENABLE or ATOM_DISABLE */
+	UCHAR ucPadding[3];
+} ENABLE_LVDS_SS_PARAMETERS;
+
+/* ucTableFormatRevision=1,ucTableContentRevision=2 */
+typedef struct _ENABLE_LVDS_SS_PARAMETERS_V2 {
+	USHORT usSpreadSpectrumPercentage;
+	UCHAR ucSpreadSpectrumType;	/* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
+	UCHAR ucSpreadSpectrumStep;	/*  */
+	UCHAR ucEnable;		/* ATOM_ENABLE or ATOM_DISABLE */
+	UCHAR ucSpreadSpectrumDelay;
+	UCHAR ucSpreadSpectrumRange;
+	UCHAR ucPadding;
+} ENABLE_LVDS_SS_PARAMETERS_V2;
+
+/* This new structure is based on ENABLE_LVDS_SS_PARAMETERS but expands to SS on PPLL, so other devices can use SS. */
+typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL {
+	USHORT usSpreadSpectrumPercentage;
+	UCHAR ucSpreadSpectrumType;	/*  Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
+	UCHAR ucSpreadSpectrumStep;	/*  */
+	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
+	UCHAR ucSpreadSpectrumDelay;
+	UCHAR ucSpreadSpectrumRange;
+	UCHAR ucPpll;		/*  ATOM_PPLL1/ATOM_PPLL2 */
+} ENABLE_SPREAD_SPECTRUM_ON_PPLL;
+
+#define ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION  ENABLE_SPREAD_SPECTRUM_ON_PPLL
+
+/**************************************************************************/
+
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION {
+	PIXEL_CLOCK_PARAMETERS sPCLKInput;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;	/* Caller doesn't need to init this portion */
+} SET_PIXEL_CLOCK_PS_ALLOCATION;
+
+#define ENABLE_VGA_RENDER_PS_ALLOCATION   SET_PIXEL_CLOCK_PS_ALLOCATION
+
+/****************************************************************************/
+/*  Structures used by ### */
+/****************************************************************************/
+typedef struct _MEMORY_TRAINING_PARAMETERS {
+	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
+} MEMORY_TRAINING_PARAMETERS;
+#define MEMORY_TRAINING_PS_ALLOCATION MEMORY_TRAINING_PARAMETERS
+
+/****************************LVDS and other encoder command table definitions **********************/
+
+/****************************************************************************/
+/*  Structures used by LVDSEncoderControlTable   (Before DCE30) */
+/*                     LVTMAEncoderControlTable  (Before DCE30) */
+/*                     TMDSAEncoderControlTable  (Before DCE30) */
+/****************************************************************************/
+typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS {
+	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+	UCHAR ucMisc;		/*  bit0=0: Enable single link */
+	/*      =1: Enable dual link */
+	/*  Bit1=0: 666RGB */
+	/*      =1: 888RGB */
+	UCHAR ucAction;		/*  0: turn off encoder */
+	/*  1: setup and turn on encoder */
+} LVDS_ENCODER_CONTROL_PARAMETERS;
+
+#define LVDS_ENCODER_CONTROL_PS_ALLOCATION  LVDS_ENCODER_CONTROL_PARAMETERS
+
+#define TMDS1_ENCODER_CONTROL_PARAMETERS    LVDS_ENCODER_CONTROL_PARAMETERS
+#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION TMDS1_ENCODER_CONTROL_PARAMETERS
+
+#define TMDS2_ENCODER_CONTROL_PARAMETERS    TMDS1_ENCODER_CONTROL_PARAMETERS
+#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION TMDS2_ENCODER_CONTROL_PARAMETERS
+
+/* ucTableFormatRevision=1,ucTableContentRevision=2 */
+typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS_V2 {
+	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+	UCHAR ucMisc;		/*  see PANEL_ENCODER_MISC_xx defintions below */
+	UCHAR ucAction;		/*  0: turn off encoder */
+	/*  1: setup and turn on encoder */
+	UCHAR ucTruncate;	/*  bit0=0: Disable truncate */
+	/*      =1: Enable truncate */
+	/*  bit4=0: 666RGB */
+	/*      =1: 888RGB */
+	UCHAR ucSpatial;	/*  bit0=0: Disable spatial dithering */
+	/*      =1: Enable spatial dithering */
+	/*  bit4=0: 666RGB */
+	/*      =1: 888RGB */
+	UCHAR ucTemporal;	/*  bit0=0: Disable temporal dithering */
+	/*      =1: Enable temporal dithering */
+	/*  bit4=0: 666RGB */
+	/*      =1: 888RGB */
+	/*  bit5=0: Gray level 2 */
+	/*      =1: Gray level 4 */
+	UCHAR ucFRC;		/*  bit4=0: 25FRC_SEL pattern E */
+	/*      =1: 25FRC_SEL pattern F */
+	/*  bit6:5=0: 50FRC_SEL pattern A */
+	/*        =1: 50FRC_SEL pattern B */
+	/*        =2: 50FRC_SEL pattern C */
+	/*        =3: 50FRC_SEL pattern D */
+	/*  bit7=0: 75FRC_SEL pattern E */
+	/*      =1: 75FRC_SEL pattern F */
+} LVDS_ENCODER_CONTROL_PARAMETERS_V2;
+
+#define LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2  LVDS_ENCODER_CONTROL_PARAMETERS_V2
+
+#define TMDS1_ENCODER_CONTROL_PARAMETERS_V2    LVDS_ENCODER_CONTROL_PARAMETERS_V2
+#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS1_ENCODER_CONTROL_PARAMETERS_V2
+
+#define TMDS2_ENCODER_CONTROL_PARAMETERS_V2    TMDS1_ENCODER_CONTROL_PARAMETERS_V2
+#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS2_ENCODER_CONTROL_PARAMETERS_V2
+
+#define LVDS_ENCODER_CONTROL_PARAMETERS_V3     LVDS_ENCODER_CONTROL_PARAMETERS_V2
+#define LVDS_ENCODER_CONTROL_PS_ALLOCATION_V3  LVDS_ENCODER_CONTROL_PARAMETERS_V3
+
+#define TMDS1_ENCODER_CONTROL_PARAMETERS_V3    LVDS_ENCODER_CONTROL_PARAMETERS_V3
+#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_V3 TMDS1_ENCODER_CONTROL_PARAMETERS_V3
+
+#define TMDS2_ENCODER_CONTROL_PARAMETERS_V3    LVDS_ENCODER_CONTROL_PARAMETERS_V3
+#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V3 TMDS2_ENCODER_CONTROL_PARAMETERS_V3
+
+/****************************************************************************/
+/*  Structures used by ### */
+/****************************************************************************/
+typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS {
+	UCHAR ucEnable;		/*  Enable or Disable External TMDS encoder */
+	UCHAR ucMisc;		/*  Bit0=0:Enable Single link;=1:Enable Dual link;Bit1 {=0:666RGB, =1:888RGB} */
+	UCHAR ucPadding[2];
+} ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS;
+
+typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION {
+	ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS sXTmdsEncoder;
+	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this portion */
+} ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION;
+
+#define ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2  LVDS_ENCODER_CONTROL_PARAMETERS_V2
+
+typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2 {
+	ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2 sXTmdsEncoder;
+	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this portion */
+} ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2;
+
+typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION {
+	DIG_ENCODER_CONTROL_PARAMETERS sDigEncoder;
+	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
+} EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION;
+
+/****************************************************************************/
+/*  Structures used by DVOEncoderControlTable */
+/****************************************************************************/
+/* ucTableFormatRevision=1,ucTableContentRevision=3 */
+
+/* ucDVOConfig: */
+#define DVO_ENCODER_CONFIG_RATE_SEL							0x01
+#define DVO_ENCODER_CONFIG_DDR_SPEED						0x00
+#define DVO_ENCODER_CONFIG_SDR_SPEED						0x01
+#define DVO_ENCODER_CONFIG_OUTPUT_SEL						0x0c
+#define DVO_ENCODER_CONFIG_LOW12BIT							0x00
+#define DVO_ENCODER_CONFIG_UPPER12BIT						0x04
+#define DVO_ENCODER_CONFIG_24BIT								0x08
+
+typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3 {
+	USHORT usPixelClock;
+	UCHAR ucDVOConfig;
+	UCHAR ucAction;		/* ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT */
+	UCHAR ucReseved[4];
+} DVO_ENCODER_CONTROL_PARAMETERS_V3;
+#define DVO_ENCODER_CONTROL_PS_ALLOCATION_V3	DVO_ENCODER_CONTROL_PARAMETERS_V3
+
+/* ucTableFormatRevision=1 */
+/* ucTableContentRevision=3 structure is not changed but usMisc add bit 1 as another input for */
+/*  bit1=0: non-coherent mode */
+/*      =1: coherent mode */
+
+/* ========================================================================================== */
+/* Only change is here next time when changing encoder parameter definitions again! */
+#define LVDS_ENCODER_CONTROL_PARAMETERS_LAST     LVDS_ENCODER_CONTROL_PARAMETERS_V3
+#define LVDS_ENCODER_CONTROL_PS_ALLOCATION_LAST  LVDS_ENCODER_CONTROL_PARAMETERS_LAST
+
+#define TMDS1_ENCODER_CONTROL_PARAMETERS_LAST    LVDS_ENCODER_CONTROL_PARAMETERS_V3
+#define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_LAST TMDS1_ENCODER_CONTROL_PARAMETERS_LAST
+
+#define TMDS2_ENCODER_CONTROL_PARAMETERS_LAST    LVDS_ENCODER_CONTROL_PARAMETERS_V3
+#define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_LAST TMDS2_ENCODER_CONTROL_PARAMETERS_LAST
+
+#define DVO_ENCODER_CONTROL_PARAMETERS_LAST      DVO_ENCODER_CONTROL_PARAMETERS
+#define DVO_ENCODER_CONTROL_PS_ALLOCATION_LAST   DVO_ENCODER_CONTROL_PS_ALLOCATION
+
+/* ========================================================================================== */
+#define PANEL_ENCODER_MISC_DUAL                0x01
+#define PANEL_ENCODER_MISC_COHERENT            0x02
+#define	PANEL_ENCODER_MISC_TMDS_LINKB					 0x04
+#define	PANEL_ENCODER_MISC_HDMI_TYPE					 0x08
+
+#define PANEL_ENCODER_ACTION_DISABLE           ATOM_DISABLE
+#define PANEL_ENCODER_ACTION_ENABLE            ATOM_ENABLE
+#define PANEL_ENCODER_ACTION_COHERENTSEQ       (ATOM_ENABLE+1)
+
+#define PANEL_ENCODER_TRUNCATE_EN              0x01
+#define PANEL_ENCODER_TRUNCATE_DEPTH           0x10
+#define PANEL_ENCODER_SPATIAL_DITHER_EN        0x01
+#define PANEL_ENCODER_SPATIAL_DITHER_DEPTH     0x10
+#define PANEL_ENCODER_TEMPORAL_DITHER_EN       0x01
+#define PANEL_ENCODER_TEMPORAL_DITHER_DEPTH    0x10
+#define PANEL_ENCODER_TEMPORAL_LEVEL_4         0x20
+#define PANEL_ENCODER_25FRC_MASK               0x10
+#define PANEL_ENCODER_25FRC_E                  0x00
+#define PANEL_ENCODER_25FRC_F                  0x10
+#define PANEL_ENCODER_50FRC_MASK               0x60
+#define PANEL_ENCODER_50FRC_A                  0x00
+#define PANEL_ENCODER_50FRC_B                  0x20
+#define PANEL_ENCODER_50FRC_C                  0x40
+#define PANEL_ENCODER_50FRC_D                  0x60
+#define PANEL_ENCODER_75FRC_MASK               0x80
+#define PANEL_ENCODER_75FRC_E                  0x00
+#define PANEL_ENCODER_75FRC_F                  0x80
+
+/****************************************************************************/
+/*  Structures used by SetVoltageTable */
+/****************************************************************************/
+#define SET_VOLTAGE_TYPE_ASIC_VDDC             1
+#define SET_VOLTAGE_TYPE_ASIC_MVDDC            2
+#define SET_VOLTAGE_TYPE_ASIC_MVDDQ            3
+#define SET_VOLTAGE_TYPE_ASIC_VDDCI            4
+#define SET_VOLTAGE_INIT_MODE                  5
+#define SET_VOLTAGE_GET_MAX_VOLTAGE            6	/* Gets the Max. voltage for the soldered Asic */
+
+#define SET_ASIC_VOLTAGE_MODE_ALL_SOURCE       0x1
+#define SET_ASIC_VOLTAGE_MODE_SOURCE_A         0x2
+#define SET_ASIC_VOLTAGE_MODE_SOURCE_B         0x4
+
+#define	SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE      0x0
+#define	SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL      0x1
+#define	SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK     0x2
+
+typedef struct _SET_VOLTAGE_PARAMETERS {
+	UCHAR ucVoltageType;	/*  To tell which voltage to set up, VDDC/MVDDC/MVDDQ */
+	UCHAR ucVoltageMode;	/*  To set all, to set source A or source B or ... */
+	UCHAR ucVoltageIndex;	/*  An index to tell which voltage level */
+	UCHAR ucReserved;
+} SET_VOLTAGE_PARAMETERS;
+
+typedef struct _SET_VOLTAGE_PARAMETERS_V2 {
+	UCHAR ucVoltageType;	/*  To tell which voltage to set up, VDDC/MVDDC/MVDDQ */
+	UCHAR ucVoltageMode;	/*  Not used, maybe use for state machine for differen power mode */
+	USHORT usVoltageLevel;	/*  real voltage level */
+} SET_VOLTAGE_PARAMETERS_V2;
+
+typedef struct _SET_VOLTAGE_PS_ALLOCATION {
+	SET_VOLTAGE_PARAMETERS sASICSetVoltage;
+	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
+} SET_VOLTAGE_PS_ALLOCATION;
+
+/****************************************************************************/
+/*  Structures used by TVEncoderControlTable */
+/****************************************************************************/
+typedef struct _TV_ENCODER_CONTROL_PARAMETERS {
+	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
+	UCHAR ucTvStandard;	/*  See definition "ATOM_TV_NTSC ..." */
+	UCHAR ucAction;		/*  0: turn off encoder */
+	/*  1: setup and turn on encoder */
+} TV_ENCODER_CONTROL_PARAMETERS;
+
+typedef struct _TV_ENCODER_CONTROL_PS_ALLOCATION {
+	TV_ENCODER_CONTROL_PARAMETERS sTVEncoder;
+	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/*  Don't set this one */
+} TV_ENCODER_CONTROL_PS_ALLOCATION;
+
+/* ==============================Data Table Portion==================================== */
+
+#ifdef	UEFI_BUILD
+#define	UTEMP	USHORT
+#define	USHORT	void*
+#endif
+
+/****************************************************************************/
+/*  Structure used in Data.mtb */
+/****************************************************************************/
+typedef struct _ATOM_MASTER_LIST_OF_DATA_TABLES {
+	USHORT UtilityPipeLine;	/*  Offest for the utility to get parser info,Don't change this position! */
+	USHORT MultimediaCapabilityInfo;	/*  Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios */
+	USHORT MultimediaConfigInfo;	/*  Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios */
+	USHORT StandardVESA_Timing;	/*  Only used by Bios */
+	USHORT FirmwareInfo;	/*  Shared by various SW components,latest version 1.4 */
+	USHORT DAC_Info;	/*  Will be obsolete from R600 */
+	USHORT LVDS_Info;	/*  Shared by various SW components,latest version 1.1 */
+	USHORT TMDS_Info;	/*  Will be obsolete from R600 */
+	USHORT AnalogTV_Info;	/*  Shared by various SW components,latest version 1.1 */
+	USHORT SupportedDevicesInfo;	/*  Will be obsolete from R600 */
+	USHORT GPIO_I2C_Info;	/*  Shared by various SW components,latest version 1.2 will be used from R600 */
+	USHORT VRAM_UsageByFirmware;	/*  Shared by various SW components,latest version 1.3 will be used from R600 */
+	USHORT GPIO_Pin_LUT;	/*  Shared by various SW components,latest version 1.1 */
+	USHORT VESA_ToInternalModeLUT;	/*  Only used by Bios */
+	USHORT ComponentVideoInfo;	/*  Shared by various SW components,latest version 2.1 will be used from R600 */
+	USHORT PowerPlayInfo;	/*  Shared by various SW components,latest version 2.1,new design from R600 */
+	USHORT CompassionateData;	/*  Will be obsolete from R600 */
+	USHORT SaveRestoreInfo;	/*  Only used by Bios */
+	USHORT PPLL_SS_Info;	/*  Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info */
+	USHORT OemInfo;		/*  Defined and used by external SW, should be obsolete soon */
+	USHORT XTMDS_Info;	/*  Will be obsolete from R600 */
+	USHORT MclkSS_Info;	/*  Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used */
+	USHORT Object_Header;	/*  Shared by various SW components,latest version 1.1 */
+	USHORT IndirectIOAccess;	/*  Only used by Bios,this table position can't change at all!! */
+	USHORT MC_InitParameter;	/*  Only used by command table */
+	USHORT ASIC_VDDC_Info;	/*  Will be obsolete from R600 */
+	USHORT ASIC_InternalSS_Info;	/*  New tabel name from R600, used to be called "ASIC_MVDDC_Info" */
+	USHORT TV_VideoMode;	/*  Only used by command table */
+	USHORT VRAM_Info;	/*  Only used by command table, latest version 1.3 */
+	USHORT MemoryTrainingInfo;	/*  Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1 */
+	USHORT IntegratedSystemInfo;	/*  Shared by various SW components */
+	USHORT ASIC_ProfilingInfo;	/*  New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600 */
+	USHORT VoltageObjectInfo;	/*  Shared by various SW components, latest version 1.1 */
+	USHORT PowerSourceInfo;	/*  Shared by various SW components, latest versoin 1.1 */
+} ATOM_MASTER_LIST_OF_DATA_TABLES;
+
+#ifdef	UEFI_BUILD
+#define	USHORT	UTEMP
+#endif
+
+typedef struct _ATOM_MASTER_DATA_TABLE {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables;
+} ATOM_MASTER_DATA_TABLE;
+
+/****************************************************************************/
+/*  Structure used in MultimediaCapabilityInfoTable */
+/****************************************************************************/
+typedef struct _ATOM_MULTIMEDIA_CAPABILITY_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulSignature;	/*  HW info table signature string "$ATI" */
+	UCHAR ucI2C_Type;	/*  I2C type (normal GP_IO, ImpactTV GP_IO, Dedicated I2C pin, etc) */
+	UCHAR ucTV_OutInfo;	/*  Type of TV out supported (3:0) and video out crystal frequency (6:4) and TV data port (7) */
+	UCHAR ucVideoPortInfo;	/*  Provides the video port capabilities */
+	UCHAR ucHostPortInfo;	/*  Provides host port configuration information */
+} ATOM_MULTIMEDIA_CAPABILITY_INFO;
+
+/****************************************************************************/
+/*  Structure used in MultimediaConfigInfoTable */
+/****************************************************************************/
+typedef struct _ATOM_MULTIMEDIA_CONFIG_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulSignature;	/*  MM info table signature sting "$MMT" */
+	UCHAR ucTunerInfo;	/*  Type of tuner installed on the adapter (4:0) and video input for tuner (7:5) */
+	UCHAR ucAudioChipInfo;	/*  List the audio chip type (3:0) product type (4) and OEM revision (7:5) */
+	UCHAR ucProductID;	/*  Defines as OEM ID or ATI board ID dependent on product type setting */
+	UCHAR ucMiscInfo1;	/*  Tuner voltage (1:0) HW teletext support (3:2) FM audio decoder (5:4) reserved (6) audio scrambling (7) */
+	UCHAR ucMiscInfo2;	/*  I2S input config (0) I2S output config (1) I2S Audio Chip (4:2) SPDIF Output Config (5) reserved (7:6) */
+	UCHAR ucMiscInfo3;	/*  Video Decoder Type (3:0) Video In Standard/Crystal (7:4) */
+	UCHAR ucMiscInfo4;	/*  Video Decoder Host Config (2:0) reserved (7:3) */
+	UCHAR ucVideoInput0Info;	/*  Video Input 0 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
+	UCHAR ucVideoInput1Info;	/*  Video Input 1 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
+	UCHAR ucVideoInput2Info;	/*  Video Input 2 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
+	UCHAR ucVideoInput3Info;	/*  Video Input 3 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
+	UCHAR ucVideoInput4Info;	/*  Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
+} ATOM_MULTIMEDIA_CONFIG_INFO;
+
+/****************************************************************************/
+/*  Structures used in FirmwareInfoTable */
+/****************************************************************************/
+
+/*  usBIOSCapability Defintion: */
+/*  Bit 0 = 0: Bios image is not Posted, =1:Bios image is Posted; */
+/*  Bit 1 = 0: Dual CRTC is not supported, =1: Dual CRTC is supported; */
+/*  Bit 2 = 0: Extended Desktop is not supported, =1: Extended Desktop is supported; */
+/*  Others: Reserved */
+#define ATOM_BIOS_INFO_ATOM_FIRMWARE_POSTED         0x0001
+#define ATOM_BIOS_INFO_DUAL_CRTC_SUPPORT            0x0002
+#define ATOM_BIOS_INFO_EXTENDED_DESKTOP_SUPPORT     0x0004
+#define ATOM_BIOS_INFO_MEMORY_CLOCK_SS_SUPPORT      0x0008
+#define ATOM_BIOS_INFO_ENGINE_CLOCK_SS_SUPPORT      0x0010
+#define ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU         0x0020
+#define ATOM_BIOS_INFO_WMI_SUPPORT                  0x0040
+#define ATOM_BIOS_INFO_PPMODE_ASSIGNGED_BY_SYSTEM   0x0080
+#define ATOM_BIOS_INFO_HYPERMEMORY_SUPPORT          0x0100
+#define ATOM_BIOS_INFO_HYPERMEMORY_SIZE_MASK        0x1E00
+#define ATOM_BIOS_INFO_VPOST_WITHOUT_FIRST_MODE_SET 0x2000
+#define ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE  0x4000
+
+#ifndef _H2INC
+
+/* Please don't add or expand this bitfield structure below, this one will retire soon.! */
+typedef struct _ATOM_FIRMWARE_CAPABILITY {
+#if ATOM_BIG_ENDIAN
+	USHORT Reserved:3;
+	USHORT HyperMemory_Size:4;
+	USHORT HyperMemory_Support:1;
+	USHORT PPMode_Assigned:1;
+	USHORT WMI_SUPPORT:1;
+	USHORT GPUControlsBL:1;
+	USHORT EngineClockSS_Support:1;
+	USHORT MemoryClockSS_Support:1;
+	USHORT ExtendedDesktopSupport:1;
+	USHORT DualCRTC_Support:1;
+	USHORT FirmwarePosted:1;
+#else
+	USHORT FirmwarePosted:1;
+	USHORT DualCRTC_Support:1;
+	USHORT ExtendedDesktopSupport:1;
+	USHORT MemoryClockSS_Support:1;
+	USHORT EngineClockSS_Support:1;
+	USHORT GPUControlsBL:1;
+	USHORT WMI_SUPPORT:1;
+	USHORT PPMode_Assigned:1;
+	USHORT HyperMemory_Support:1;
+	USHORT HyperMemory_Size:4;
+	USHORT Reserved:3;
+#endif
+} ATOM_FIRMWARE_CAPABILITY;
+
+typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS {
+	ATOM_FIRMWARE_CAPABILITY sbfAccess;
+	USHORT susAccess;
+} ATOM_FIRMWARE_CAPABILITY_ACCESS;
+
+#else
+
+typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS {
+	USHORT susAccess;
+} ATOM_FIRMWARE_CAPABILITY_ACCESS;
+
+#endif
+
+typedef struct _ATOM_FIRMWARE_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulFirmwareRevision;
+	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
+	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
+	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
+	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
+	UCHAR ucASICMaxTemperature;
+	UCHAR ucPadding[3];	/* Don't use them */
+	ULONG aulReservedForBIOS[3];	/* Don't use them */
+	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
+	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit, the definitions above can't change!!! */
+	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+	USHORT usReferenceClock;	/* In 10Khz unit */
+	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
+	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
+	UCHAR ucDesign_ID;	/* Indicate what is the board design */
+	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
+} ATOM_FIRMWARE_INFO;
+
+typedef struct _ATOM_FIRMWARE_INFO_V1_2 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulFirmwareRevision;
+	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
+	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
+	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
+	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
+	UCHAR ucASICMaxTemperature;
+	UCHAR ucMinAllowedBL_Level;
+	UCHAR ucPadding[2];	/* Don't use them */
+	ULONG aulReservedForBIOS[2];	/* Don't use them */
+	ULONG ulMinPixelClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
+	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */
+	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+	USHORT usReferenceClock;	/* In 10Khz unit */
+	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
+	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
+	UCHAR ucDesign_ID;	/* Indicate what is the board design */
+	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
+} ATOM_FIRMWARE_INFO_V1_2;
+
+typedef struct _ATOM_FIRMWARE_INFO_V1_3 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulFirmwareRevision;
+	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
+	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
+	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
+	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
+	UCHAR ucASICMaxTemperature;
+	UCHAR ucMinAllowedBL_Level;
+	UCHAR ucPadding[2];	/* Don't use them */
+	ULONG aulReservedForBIOS;	/* Don't use them */
+	ULONG ul3DAccelerationEngineClock;	/* In 10Khz unit */
+	ULONG ulMinPixelClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
+	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */
+	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+	USHORT usReferenceClock;	/* In 10Khz unit */
+	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
+	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
+	UCHAR ucDesign_ID;	/* Indicate what is the board design */
+	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
+} ATOM_FIRMWARE_INFO_V1_3;
+
+typedef struct _ATOM_FIRMWARE_INFO_V1_4 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulFirmwareRevision;
+	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
+	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
+	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
+	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
+	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
+	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
+	UCHAR ucASICMaxTemperature;
+	UCHAR ucMinAllowedBL_Level;
+	USHORT usBootUpVDDCVoltage;	/* In MV unit */
+	USHORT usLcdMinPixelClockPLL_Output;	/*  In MHz unit */
+	USHORT usLcdMaxPixelClockPLL_Output;	/*  In MHz unit */
+	ULONG ul3DAccelerationEngineClock;	/* In 10Khz unit */
+	ULONG ulMinPixelClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
+	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
+	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
+	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */
+	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+	USHORT usReferenceClock;	/* In 10Khz unit */
+	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
+	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
+	UCHAR ucDesign_ID;	/* Indicate what is the board design */
+	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
+} ATOM_FIRMWARE_INFO_V1_4;
+
+#define ATOM_FIRMWARE_INFO_LAST  ATOM_FIRMWARE_INFO_V1_4
+
+/****************************************************************************/
+/*  Structures used in IntegratedSystemInfoTable */
+/****************************************************************************/
+#define IGP_CAP_FLAG_DYNAMIC_CLOCK_EN      0x2
+#define IGP_CAP_FLAG_AC_CARD               0x4
+#define IGP_CAP_FLAG_SDVO_CARD             0x8
+#define IGP_CAP_FLAG_POSTDIV_BY_2_MODE     0x10
+
+typedef struct _ATOM_INTEGRATED_SYSTEM_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulBootUpEngineClock;	/* in 10kHz unit */
+	ULONG ulBootUpMemoryClock;	/* in 10kHz unit */
+	ULONG ulMaxSystemMemoryClock;	/* in 10kHz unit */
+	ULONG ulMinSystemMemoryClock;	/* in 10kHz unit */
+	UCHAR ucNumberOfCyclesInPeriodHi;
+	UCHAR ucLCDTimingSel;	/* =0:not valid.!=0 sel this timing descriptor from LCD EDID. */
+	USHORT usReserved1;
+	USHORT usInterNBVoltageLow;	/* An intermidiate PMW value to set the voltage */
+	USHORT usInterNBVoltageHigh;	/* Another intermidiate PMW value to set the voltage */
+	ULONG ulReserved[2];
+
+	USHORT usFSBClock;	/* In MHz unit */
+	USHORT usCapabilityFlag;	/* Bit0=1 indicates the fake HDMI support,Bit1=0/1 for Dynamic clocking dis/enable */
+	/* Bit[3:2]== 0:No PCIE card, 1:AC card, 2:SDVO card */
+	/* Bit[4]==1: P/2 mode, ==0: P/1 mode */
+	USHORT usPCIENBCfgReg7;	/* bit[7:0]=MUX_Sel, bit[9:8]=MUX_SEL_LEVEL2, bit[10]=Lane_Reversal */
+	USHORT usK8MemoryClock;	/* in MHz unit */
+	USHORT usK8SyncStartDelay;	/* in 0.01 us unit */
+	USHORT usK8DataReturnTime;	/* in 0.01 us unit */
+	UCHAR ucMaxNBVoltage;
+	UCHAR ucMinNBVoltage;
+	UCHAR ucMemoryType;	/* [7:4]=1:DDR1;=2:DDR2;=3:DDR3.[3:0] is reserved */
+	UCHAR ucNumberOfCyclesInPeriod;	/* CG.FVTHROT_PWM_CTRL_REG0.NumberOfCyclesInPeriod */
+	UCHAR ucStartingPWM_HighTime;	/* CG.FVTHROT_PWM_CTRL_REG0.StartingPWM_HighTime */
+	UCHAR ucHTLinkWidth;	/* 16 bit vs. 8 bit */
+	UCHAR ucMaxNBVoltageHigh;
+	UCHAR ucMinNBVoltageHigh;
+} ATOM_INTEGRATED_SYSTEM_INFO;
+
+/* Explanation on entries in ATOM_INTEGRATED_SYSTEM_INFO
+ulBootUpMemoryClock:    For Intel IGP,it's the UMA system memory clock
+                        For AMD IGP,it's 0 if no SidePort memory installed or it's the boot-up SidePort memory clock
+ulMaxSystemMemoryClock: For Intel IGP,it's the Max freq from memory SPD if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0
+                        For AMD IGP,for now this can be 0
+ulMinSystemMemoryClock: For Intel IGP,it's 133MHz if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0
+                        For AMD IGP,for now this can be 0
+
+usFSBClock:             For Intel IGP,it's FSB Freq
+                        For AMD IGP,it's HT Link Speed
+
+usK8MemoryClock:        For AMD IGP only. For RevF CPU, set it to 200
+usK8SyncStartDelay:     For AMD IGP only. Memory access latency in K8, required for watermark calculation
+usK8DataReturnTime:     For AMD IGP only. Memory access latency in K8, required for watermark calculation
+
+VC:Voltage Control
+ucMaxNBVoltage:         Voltage regulator dependent PWM value. Low 8 bits of the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all.
+ucMinNBVoltage:         Voltage regulator dependent PWM value. Low 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all.
+
+ucNumberOfCyclesInPeriod:   Indicate how many cycles when PWM duty is 100%. low 8 bits of the value.
+ucNumberOfCyclesInPeriodHi: Indicate how many cycles when PWM duty is 100%. high 8 bits of the value.If the PWM has an inverter,set bit [7]==1,otherwise set it 0
+
+ucMaxNBVoltageHigh:     Voltage regulator dependent PWM value. High 8 bits of  the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all.
+ucMinNBVoltageHigh:     Voltage regulator dependent PWM value. High 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all.
+
+usInterNBVoltageLow:    Voltage regulator dependent PWM value. The value makes the the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all.
+usInterNBVoltageHigh:   Voltage regulator dependent PWM value. The value makes the the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all.
+*/
+
+/*
+The following IGP table is introduced from RS780, which is supposed to be put by SBIOS in FB before IGP VBIOS starts VPOST;
+Then VBIOS will copy the whole structure to its image so all GPU SW components can access this data structure to get whatever they need.
+The enough reservation should allow us to never change table revisions. Whenever needed, a GPU SW component can use reserved portion for new data entries.
+
+SW components can access the IGP system infor structure in the same way as before
+*/
+
+typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ULONG ulBootUpEngineClock;	/* in 10kHz unit */
+	ULONG ulReserved1[2];	/* must be 0x0 for the reserved */
+	ULONG ulBootUpUMAClock;	/* in 10kHz unit */
+	ULONG ulBootUpSidePortClock;	/* in 10kHz unit */
+	ULONG ulMinSidePortClock;	/* in 10kHz unit */
+	ULONG ulReserved2[6];	/* must be 0x0 for the reserved */
+	ULONG ulSystemConfig;	/* see explanation below */
+	ULONG ulBootUpReqDisplayVector;
+	ULONG ulOtherDisplayMisc;
+	ULONG ulDDISlot1Config;
+	ULONG ulDDISlot2Config;
+	UCHAR ucMemoryType;	/* [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved */
+	UCHAR ucUMAChannelNumber;
+	UCHAR ucDockingPinBit;
+	UCHAR ucDockingPinPolarity;
+	ULONG ulDockingPinCFGInfo;
+	ULONG ulCPUCapInfo;
+	USHORT usNumberOfCyclesInPeriod;
+	USHORT usMaxNBVoltage;
+	USHORT usMinNBVoltage;
+	USHORT usBootUpNBVoltage;
+	ULONG ulHTLinkFreq;	/* in 10Khz */
+	USHORT usMinHTLinkWidth;
+	USHORT usMaxHTLinkWidth;
+	USHORT usUMASyncStartDelay;
+	USHORT usUMADataReturnTime;
+	USHORT usLinkStatusZeroTime;
+	USHORT usReserved;
+	ULONG ulHighVoltageHTLinkFreq;	/*  in 10Khz */
+	ULONG ulLowVoltageHTLinkFreq;	/*  in 10Khz */
+	USHORT usMaxUpStreamHTLinkWidth;
+	USHORT usMaxDownStreamHTLinkWidth;
+	USHORT usMinUpStreamHTLinkWidth;
+	USHORT usMinDownStreamHTLinkWidth;
+	ULONG ulReserved3[97];	/* must be 0x0 */
+} ATOM_INTEGRATED_SYSTEM_INFO_V2;
+
+/*
+ulBootUpEngineClock:   Boot-up Engine Clock in 10Khz;
+ulBootUpUMAClock:      Boot-up UMA Clock in 10Khz; it must be 0x0 when UMA is not present
+ulBootUpSidePortClock: Boot-up SidePort Clock in 10Khz; it must be 0x0 when SidePort Memory is not present,this could be equal to or less than maximum supported Sideport memory clock
+
+ulSystemConfig:
+Bit[0]=1: PowerExpress mode =0 Non-PowerExpress mode;
+Bit[1]=1: system boots up at AMD overdrived state or user customized  mode. In this case, driver will just stick to this boot-up mode. No other PowerPlay state
+      =0: system boots up at driver control state. Power state depends on PowerPlay table.
+Bit[2]=1: PWM method is used on NB voltage control. =0: GPIO method is used.
+Bit[3]=1: Only one power state(Performance) will be supported.
+      =0: Multiple power states supported from PowerPlay table.
+Bit[4]=1: CLMC is supported and enabled on current system.
+      =0: CLMC is not supported or enabled on current system. SBIOS need to support HT link/freq change through ATIF interface.
+Bit[5]=1: Enable CDLW for all driver control power states. Max HT width is from SBIOS, while Min HT width is determined by display requirement.
+      =0: CDLW is disabled. If CLMC is enabled case, Min HT width will be set equal to Max HT width. If CLMC disabled case, Max HT width will be applied.
+Bit[6]=1: High Voltage requested for all power states. In this case, voltage will be forced at 1.1v and powerplay table voltage drop/throttling request will be ignored.
+      =0: Voltage settings is determined by powerplay table.
+Bit[7]=1: Enable CLMC as hybrid Mode. CDLD and CILR will be disabled in this case and we're using legacy C1E. This is workaround for CPU(Griffin) performance issue.
+      =0: Enable CLMC as regular mode, CDLD and CILR will be enabled.
+
+ulBootUpReqDisplayVector: This dword is a bit vector indicates what display devices are requested during boot-up. Refer to ATOM_DEVICE_xxx_SUPPORT for the bit vector definitions.
+
+ulOtherDisplayMisc: [15:8]- Bootup LCD Expansion selection; 0-center, 1-full panel size expansion;
+			              [7:0] - BootupTV standard selection; This is a bit vector to indicate what TV standards are supported by the system. Refer to ucTVSuppportedStd definition;
+
+ulDDISlot1Config: Describes the PCIE lane configuration on this DDI PCIE slot (ADD2 card) or connector (Mobile design).
+      [3:0]  - Bit vector to indicate PCIE lane config of the DDI slot/connector on chassis (bit 0=1 lane 3:0; bit 1=1 lane 7:4; bit 2=1 lane 11:8; bit 3=1 lane 15:12)
+			[7:4]  - Bit vector to indicate PCIE lane config of the same DDI slot/connector on docking station (bit 0=1 lane 3:0; bit 1=1 lane 7:4; bit 2=1 lane 11:8; bit 3=1 lane 15:12)
+			[15:8] - Lane configuration attribute;
+      [23:16]- Connector type, possible value:
+               CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D
+               CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D
+               CONNECTOR_OBJECT_ID_HDMI_TYPE_A
+               CONNECTOR_OBJECT_ID_DISPLAYPORT
+			[31:24]- Reserved
+
+ulDDISlot2Config: Same as Slot1.
+ucMemoryType: SidePort memory type, set it to 0x0 when Sideport memory is not installed. Driver needs this info to change sideport memory clock. Not for display in CCC.
+For IGP, Hypermemory is the only memory type showed in CCC.
+
+ucUMAChannelNumber:  how many channels for the UMA;
+
+ulDockingPinCFGInfo: [15:0]-Bus/Device/Function # to CFG to read this Docking Pin; [31:16]-reg offset in CFG to read this pin
+ucDockingPinBit:     which bit in this register to read the pin status;
+ucDockingPinPolarity:Polarity of the pin when docked;
+
+ulCPUCapInfo:        [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, other bits reserved for now and must be 0x0
+
+usNumberOfCyclesInPeriod:Indicate how many cycles when PWM duty is 100%.
+usMaxNBVoltage:Max. voltage control value in either PWM or GPIO mode.
+usMinNBVoltage:Min. voltage control value in either PWM or GPIO mode.
+                    GPIO mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=0
+                    PWM mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=1
+                    GPU SW don't control mode: usMaxNBVoltage & usMinNBVoltage=0 and no care about ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE
+usBootUpNBVoltage:Boot-up voltage regulator dependent PWM value.
+
+ulHTLinkFreq:       Bootup HT link Frequency in 10Khz.
+usMinHTLinkWidth:   Bootup minimum HT link width. If CDLW disabled, this is equal to usMaxHTLinkWidth.
+                    If CDLW enabled, both upstream and downstream width should be the same during bootup.
+usMaxHTLinkWidth:   Bootup maximum HT link width. If CDLW disabled, this is equal to usMinHTLinkWidth.
+                    If CDLW enabled, both upstream and downstream width should be the same during bootup.
+
+usUMASyncStartDelay: Memory access latency, required for watermark calculation
+usUMADataReturnTime: Memory access latency, required for watermark calculation
+usLinkStatusZeroTime:Memory access latency required for watermark calculation, set this to 0x0 for K8 CPU, set a proper value in 0.01 the unit of us
+for Griffin or Greyhound. SBIOS needs to convert to actual time by:
+                     if T0Ttime [5:4]=00b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.1us (0.0 to 1.5us)
+                     if T0Ttime [5:4]=01b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.5us (0.0 to 7.5us)
+                     if T0Ttime [5:4]=10b, then usLinkStatusZeroTime=T0Ttime [3:0]*2.0us (0.0 to 30us)
+                     if T0Ttime [5:4]=11b, and T0Ttime [3:0]=0x0 to 0xa, then usLinkStatusZeroTime=T0Ttime [3:0]*20us (0.0 to 200us)
+
+ulHighVoltageHTLinkFreq:     HT link frequency for power state with low voltage. If boot up runs in HT1, this must be 0.
+                             This must be less than or equal to ulHTLinkFreq(bootup frequency).
+ulLowVoltageHTLinkFreq:      HT link frequency for power state with low voltage or voltage scaling 1.0v~1.1v. If boot up runs in HT1, this must be 0.
+                             This must be less than or equal to ulHighVoltageHTLinkFreq.
+
+usMaxUpStreamHTLinkWidth:    Asymmetric link width support in the future, to replace usMaxHTLinkWidth. Not used for now.
+usMaxDownStreamHTLinkWidth:  same as above.
+usMinUpStreamHTLinkWidth:    Asymmetric link width support in the future, to replace usMinHTLinkWidth. Not used for now.
+usMinDownStreamHTLinkWidth:  same as above.
+*/
+
+#define SYSTEM_CONFIG_POWEREXPRESS_ENABLE                 0x00000001
+#define SYSTEM_CONFIG_RUN_AT_OVERDRIVE_ENGINE             0x00000002
+#define SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE                  0x00000004
+#define SYSTEM_CONFIG_PERFORMANCE_POWERSTATE_ONLY         0x00000008
+#define SYSTEM_CONFIG_CLMC_ENABLED                        0x00000010
+#define SYSTEM_CONFIG_CDLW_ENABLED                        0x00000020
+#define SYSTEM_CONFIG_HIGH_VOLTAGE_REQUESTED              0x00000040
+#define SYSTEM_CONFIG_CLMC_HYBRID_MODE_ENABLED            0x00000080
+
+#define IGP_DDI_SLOT_LANE_CONFIG_MASK                     0x000000FF
+
+#define b0IGP_DDI_SLOT_LANE_MAP_MASK                      0x0F
+#define b0IGP_DDI_SLOT_DOCKING_LANE_MAP_MASK              0xF0
+#define b0IGP_DDI_SLOT_CONFIG_LANE_0_3                    0x01
+#define b0IGP_DDI_SLOT_CONFIG_LANE_4_7                    0x02
+#define b0IGP_DDI_SLOT_CONFIG_LANE_8_11                   0x04
+#define b0IGP_DDI_SLOT_CONFIG_LANE_12_15                  0x08
+
+#define IGP_DDI_SLOT_ATTRIBUTE_MASK                       0x0000FF00
+#define IGP_DDI_SLOT_CONFIG_REVERSED                      0x00000100
+#define b1IGP_DDI_SLOT_CONFIG_REVERSED                    0x01
+
+#define IGP_DDI_SLOT_CONNECTOR_TYPE_MASK                  0x00FF0000
+
+#define ATOM_CRT_INT_ENCODER1_INDEX                       0x00000000
+#define ATOM_LCD_INT_ENCODER1_INDEX                       0x00000001
+#define ATOM_TV_INT_ENCODER1_INDEX                        0x00000002
+#define ATOM_DFP_INT_ENCODER1_INDEX                       0x00000003
+#define ATOM_CRT_INT_ENCODER2_INDEX                       0x00000004
+#define ATOM_LCD_EXT_ENCODER1_INDEX                       0x00000005
+#define ATOM_TV_EXT_ENCODER1_INDEX                        0x00000006
+#define ATOM_DFP_EXT_ENCODER1_INDEX                       0x00000007
+#define ATOM_CV_INT_ENCODER1_INDEX                        0x00000008
+#define ATOM_DFP_INT_ENCODER2_INDEX                       0x00000009
+#define ATOM_CRT_EXT_ENCODER1_INDEX                       0x0000000A
+#define ATOM_CV_EXT_ENCODER1_INDEX                        0x0000000B
+#define ATOM_DFP_INT_ENCODER3_INDEX                       0x0000000C
+#define ATOM_DFP_INT_ENCODER4_INDEX                       0x0000000D
+
+/*  define ASIC internal encoder id ( bit vector ) */
+#define ASIC_INT_DAC1_ENCODER_ID											0x00
+#define ASIC_INT_TV_ENCODER_ID														0x02
+#define ASIC_INT_DIG1_ENCODER_ID													0x03
+#define ASIC_INT_DAC2_ENCODER_ID													0x04
+#define ASIC_EXT_TV_ENCODER_ID														0x06
+#define ASIC_INT_DVO_ENCODER_ID														0x07
+#define ASIC_INT_DIG2_ENCODER_ID													0x09
+#define ASIC_EXT_DIG_ENCODER_ID														0x05
+
+/* define Encoder attribute */
+#define ATOM_ANALOG_ENCODER																0
+#define ATOM_DIGITAL_ENCODER															1
+
+#define ATOM_DEVICE_CRT1_INDEX                            0x00000000
+#define ATOM_DEVICE_LCD1_INDEX                            0x00000001
+#define ATOM_DEVICE_TV1_INDEX                             0x00000002
+#define ATOM_DEVICE_DFP1_INDEX                            0x00000003
+#define ATOM_DEVICE_CRT2_INDEX                            0x00000004
+#define ATOM_DEVICE_LCD2_INDEX                            0x00000005
+#define ATOM_DEVICE_TV2_INDEX                             0x00000006
+#define ATOM_DEVICE_DFP2_INDEX                            0x00000007
+#define ATOM_DEVICE_CV_INDEX                              0x00000008
+#define ATOM_DEVICE_DFP3_INDEX														0x00000009
+#define ATOM_DEVICE_DFP4_INDEX														0x0000000A
+#define ATOM_DEVICE_DFP5_INDEX														0x0000000B
+#define ATOM_DEVICE_RESERVEDC_INDEX                       0x0000000C
+#define ATOM_DEVICE_RESERVEDD_INDEX                       0x0000000D
+#define ATOM_DEVICE_RESERVEDE_INDEX                       0x0000000E
+#define ATOM_DEVICE_RESERVEDF_INDEX                       0x0000000F
+#define ATOM_MAX_SUPPORTED_DEVICE_INFO                    (ATOM_DEVICE_DFP3_INDEX+1)
+#define ATOM_MAX_SUPPORTED_DEVICE_INFO_2                  ATOM_MAX_SUPPORTED_DEVICE_INFO
+#define ATOM_MAX_SUPPORTED_DEVICE_INFO_3                  (ATOM_DEVICE_DFP5_INDEX + 1)
+
+#define ATOM_MAX_SUPPORTED_DEVICE                         (ATOM_DEVICE_RESERVEDF_INDEX+1)
+
+#define ATOM_DEVICE_CRT1_SUPPORT                          (0x1L << ATOM_DEVICE_CRT1_INDEX)
+#define ATOM_DEVICE_LCD1_SUPPORT                          (0x1L << ATOM_DEVICE_LCD1_INDEX)
+#define ATOM_DEVICE_TV1_SUPPORT                           (0x1L << ATOM_DEVICE_TV1_INDEX)
+#define ATOM_DEVICE_DFP1_SUPPORT                          (0x1L << ATOM_DEVICE_DFP1_INDEX)
+#define ATOM_DEVICE_CRT2_SUPPORT                          (0x1L << ATOM_DEVICE_CRT2_INDEX)
+#define ATOM_DEVICE_LCD2_SUPPORT                          (0x1L << ATOM_DEVICE_LCD2_INDEX)
+#define ATOM_DEVICE_TV2_SUPPORT                           (0x1L << ATOM_DEVICE_TV2_INDEX)
+#define ATOM_DEVICE_DFP2_SUPPORT                          (0x1L << ATOM_DEVICE_DFP2_INDEX)
+#define ATOM_DEVICE_CV_SUPPORT                            (0x1L << ATOM_DEVICE_CV_INDEX)
+#define ATOM_DEVICE_DFP3_SUPPORT													(0x1L << ATOM_DEVICE_DFP3_INDEX)
+#define ATOM_DEVICE_DFP4_SUPPORT													(0x1L << ATOM_DEVICE_DFP4_INDEX )
+#define ATOM_DEVICE_DFP5_SUPPORT													(0x1L << ATOM_DEVICE_DFP5_INDEX)
+
+#define ATOM_DEVICE_CRT_SUPPORT \
+	(ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT)
+#define ATOM_DEVICE_DFP_SUPPORT \
+	(ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT | \
+	 ATOM_DEVICE_DFP3_SUPPORT | ATOM_DEVICE_DFP4_SUPPORT | \
+	 ATOM_DEVICE_DFP5_SUPPORT)
+#define ATOM_DEVICE_TV_SUPPORT \
+	(ATOM_DEVICE_TV1_SUPPORT  | ATOM_DEVICE_TV2_SUPPORT)
+#define ATOM_DEVICE_LCD_SUPPORT \
+	(ATOM_DEVICE_LCD1_SUPPORT | ATOM_DEVICE_LCD2_SUPPORT)
+
+#define ATOM_DEVICE_CONNECTOR_TYPE_MASK                   0x000000F0
+#define ATOM_DEVICE_CONNECTOR_TYPE_SHIFT                  0x00000004
+#define ATOM_DEVICE_CONNECTOR_VGA                         0x00000001
+#define ATOM_DEVICE_CONNECTOR_DVI_I                       0x00000002
+#define ATOM_DEVICE_CONNECTOR_DVI_D                       0x00000003
+#define ATOM_DEVICE_CONNECTOR_DVI_A                       0x00000004
+#define ATOM_DEVICE_CONNECTOR_SVIDEO                      0x00000005
+#define ATOM_DEVICE_CONNECTOR_COMPOSITE                   0x00000006
+#define ATOM_DEVICE_CONNECTOR_LVDS                        0x00000007
+#define ATOM_DEVICE_CONNECTOR_DIGI_LINK                   0x00000008
+#define ATOM_DEVICE_CONNECTOR_SCART                       0x00000009
+#define ATOM_DEVICE_CONNECTOR_HDMI_TYPE_A                 0x0000000A
+#define ATOM_DEVICE_CONNECTOR_HDMI_TYPE_B                 0x0000000B
+#define ATOM_DEVICE_CONNECTOR_CASE_1                      0x0000000E
+#define ATOM_DEVICE_CONNECTOR_DISPLAYPORT                 0x0000000F
+
+#define ATOM_DEVICE_DAC_INFO_MASK                         0x0000000F
+#define ATOM_DEVICE_DAC_INFO_SHIFT                        0x00000000
+#define ATOM_DEVICE_DAC_INFO_NODAC                        0x00000000
+#define ATOM_DEVICE_DAC_INFO_DACA                         0x00000001
+#define ATOM_DEVICE_DAC_INFO_DACB                         0x00000002
+#define ATOM_DEVICE_DAC_INFO_EXDAC                        0x00000003
+
+#define ATOM_DEVICE_I2C_ID_NOI2C                          0x00000000
+
+#define ATOM_DEVICE_I2C_LINEMUX_MASK                      0x0000000F
+#define ATOM_DEVICE_I2C_LINEMUX_SHIFT                     0x00000000
+
+#define ATOM_DEVICE_I2C_ID_MASK                           0x00000070
+#define ATOM_DEVICE_I2C_ID_SHIFT                          0x00000004
+#define ATOM_DEVICE_I2C_ID_IS_FOR_NON_MM_USE              0x00000001
+#define ATOM_DEVICE_I2C_ID_IS_FOR_MM_USE                  0x00000002
+#define ATOM_DEVICE_I2C_ID_IS_FOR_SDVO_USE                0x00000003	/* For IGP RS600 */
+#define ATOM_DEVICE_I2C_ID_IS_FOR_DAC_SCL                 0x00000004	/* For IGP RS690 */
+
+#define ATOM_DEVICE_I2C_HARDWARE_CAP_MASK                 0x00000080
+#define ATOM_DEVICE_I2C_HARDWARE_CAP_SHIFT                0x00000007
+#define	ATOM_DEVICE_USES_SOFTWARE_ASSISTED_I2C            0x00000000
+#define	ATOM_DEVICE_USES_HARDWARE_ASSISTED_I2C            0x00000001
+
+/*   usDeviceSupport: */
+/*   Bits0       = 0 - no CRT1 support= 1- CRT1 is supported */
+/*   Bit 1       = 0 - no LCD1 support= 1- LCD1 is supported */
+/*   Bit 2       = 0 - no TV1  support= 1- TV1  is supported */
+/*   Bit 3       = 0 - no DFP1 support= 1- DFP1 is supported */
+/*   Bit 4       = 0 - no CRT2 support= 1- CRT2 is supported */
+/*   Bit 5       = 0 - no LCD2 support= 1- LCD2 is supported */
+/*   Bit 6       = 0 - no TV2  support= 1- TV2  is supported */
+/*   Bit 7       = 0 - no DFP2 support= 1- DFP2 is supported */
+/*   Bit 8       = 0 - no CV   support= 1- CV   is supported */
+/*   Bit 9       = 0 - no DFP3 support= 1- DFP3 is supported */
+/*   Byte1 (Supported Device Info) */
+/*   Bit 0       = = 0 - no CV support= 1- CV is supported */
+/*  */
+/*  */
+
+/*               ucI2C_ConfigID */
+/*     [7:0] - I2C LINE Associate ID */
+/*           = 0   - no I2C */
+/*     [7]               -       HW_Cap        = 1,  [6:0]=HW assisted I2C ID(HW line selection) */
+/*                           =   0,  [6:0]=SW assisted I2C ID */
+/*     [6-4]     - HW_ENGINE_ID  =       1,  HW engine for NON multimedia use */
+/*                           =   2,      HW engine for Multimedia use */
+/*                           =   3-7     Reserved for future I2C engines */
+/*               [3-0] - I2C_LINE_MUX  = A Mux number when it's HW assisted I2C or GPIO ID when it's SW I2C */
+
+typedef struct _ATOM_I2C_ID_CONFIG {
+#if ATOM_BIG_ENDIAN
+	UCHAR bfHW_Capable:1;
+	UCHAR bfHW_EngineID:3;
+	UCHAR bfI2C_LineMux:4;
+#else
+	UCHAR bfI2C_LineMux:4;
+	UCHAR bfHW_EngineID:3;
+	UCHAR bfHW_Capable:1;
+#endif
+} ATOM_I2C_ID_CONFIG;
+
+typedef union _ATOM_I2C_ID_CONFIG_ACCESS {
+	ATOM_I2C_ID_CONFIG sbfAccess;
+	UCHAR ucAccess;
+} ATOM_I2C_ID_CONFIG_ACCESS;
+
+/****************************************************************************/
+/*  Structure used in GPIO_I2C_InfoTable */
+/****************************************************************************/
+typedef struct _ATOM_GPIO_I2C_ASSIGMENT {
+	USHORT usClkMaskRegisterIndex;
+	USHORT usClkEnRegisterIndex;
+	USHORT usClkY_RegisterIndex;
+	USHORT usClkA_RegisterIndex;
+	USHORT usDataMaskRegisterIndex;
+	USHORT usDataEnRegisterIndex;
+	USHORT usDataY_RegisterIndex;
+	USHORT usDataA_RegisterIndex;
+	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
+	UCHAR ucClkMaskShift;
+	UCHAR ucClkEnShift;
+	UCHAR ucClkY_Shift;
+	UCHAR ucClkA_Shift;
+	UCHAR ucDataMaskShift;
+	UCHAR ucDataEnShift;
+	UCHAR ucDataY_Shift;
+	UCHAR ucDataA_Shift;
+	UCHAR ucReserved1;
+	UCHAR ucReserved2;
+} ATOM_GPIO_I2C_ASSIGMENT;
+
+typedef struct _ATOM_GPIO_I2C_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_GPIO_I2C_ASSIGMENT asGPIO_Info[ATOM_MAX_SUPPORTED_DEVICE];
+} ATOM_GPIO_I2C_INFO;
+
+/****************************************************************************/
+/*  Common Structure used in other structures */
+/****************************************************************************/
+
+#ifndef _H2INC
+
+/* Please don't add or expand this bitfield structure below, this one will retire soon.! */
+typedef struct _ATOM_MODE_MISC_INFO {
+#if ATOM_BIG_ENDIAN
+	USHORT Reserved:6;
+	USHORT RGB888:1;
+	USHORT DoubleClock:1;
+	USHORT Interlace:1;
+	USHORT CompositeSync:1;
+	USHORT V_ReplicationBy2:1;
+	USHORT H_ReplicationBy2:1;
+	USHORT VerticalCutOff:1;
+	USHORT VSyncPolarity:1;	/* 0=Active High, 1=Active Low */
+	USHORT HSyncPolarity:1;	/* 0=Active High, 1=Active Low */
+	USHORT HorizontalCutOff:1;
+#else
+	USHORT HorizontalCutOff:1;
+	USHORT HSyncPolarity:1;	/* 0=Active High, 1=Active Low */
+	USHORT VSyncPolarity:1;	/* 0=Active High, 1=Active Low */
+	USHORT VerticalCutOff:1;
+	USHORT H_ReplicationBy2:1;
+	USHORT V_ReplicationBy2:1;
+	USHORT CompositeSync:1;
+	USHORT Interlace:1;
+	USHORT DoubleClock:1;
+	USHORT RGB888:1;
+	USHORT Reserved:6;
+#endif
+} ATOM_MODE_MISC_INFO;
+
+typedef union _ATOM_MODE_MISC_INFO_ACCESS {
+	ATOM_MODE_MISC_INFO sbfAccess;
+	USHORT usAccess;
+} ATOM_MODE_MISC_INFO_ACCESS;
+
+#else
+
+typedef union _ATOM_MODE_MISC_INFO_ACCESS {
+	USHORT usAccess;
+} ATOM_MODE_MISC_INFO_ACCESS;
+
+#endif
+
+/*  usModeMiscInfo- */
+#define ATOM_H_CUTOFF           0x01
+#define ATOM_HSYNC_POLARITY     0x02	/* 0=Active High, 1=Active Low */
+#define ATOM_VSYNC_POLARITY     0x04	/* 0=Active High, 1=Active Low */
+#define ATOM_V_CUTOFF           0x08
+#define ATOM_H_REPLICATIONBY2   0x10
+#define ATOM_V_REPLICATIONBY2   0x20
+#define ATOM_COMPOSITESYNC      0x40
+#define ATOM_INTERLACE          0x80
+#define ATOM_DOUBLE_CLOCK_MODE  0x100
+#define ATOM_RGB888_MODE        0x200
+
+/* usRefreshRate- */
+#define ATOM_REFRESH_43         43
+#define ATOM_REFRESH_47         47
+#define ATOM_REFRESH_56         56
+#define ATOM_REFRESH_60         60
+#define ATOM_REFRESH_65         65
+#define ATOM_REFRESH_70         70
+#define ATOM_REFRESH_72         72
+#define ATOM_REFRESH_75         75
+#define ATOM_REFRESH_85         85
+
+/*  ATOM_MODE_TIMING data are exactly the same as VESA timing data. */
+/*  Translation from EDID to ATOM_MODE_TIMING, use the following formula. */
+/*  */
+/*       VESA_HTOTAL                     =       VESA_ACTIVE + 2* VESA_BORDER + VESA_BLANK */
+/*                                               =       EDID_HA + EDID_HBL */
+/*       VESA_HDISP                      =       VESA_ACTIVE     =       EDID_HA */
+/*       VESA_HSYNC_START        =       VESA_ACTIVE + VESA_BORDER + VESA_FRONT_PORCH */
+/*                                               =       EDID_HA + EDID_HSO */
+/*       VESA_HSYNC_WIDTH        =       VESA_HSYNC_TIME =       EDID_HSPW */
+/*       VESA_BORDER                     =       EDID_BORDER */
+
+/****************************************************************************/
+/*  Structure used in SetCRTC_UsingDTDTimingTable */
+/****************************************************************************/
+typedef struct _SET_CRTC_USING_DTD_TIMING_PARAMETERS {
+	USHORT usH_Size;
+	USHORT usH_Blanking_Time;
+	USHORT usV_Size;
+	USHORT usV_Blanking_Time;
+	USHORT usH_SyncOffset;
+	USHORT usH_SyncWidth;
+	USHORT usV_SyncOffset;
+	USHORT usV_SyncWidth;
+	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
+	UCHAR ucH_Border;	/*  From DFP EDID */
+	UCHAR ucV_Border;
+	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucPadding[3];
+} SET_CRTC_USING_DTD_TIMING_PARAMETERS;
+
+/****************************************************************************/
+/*  Structure used in SetCRTC_TimingTable */
+/****************************************************************************/
+typedef struct _SET_CRTC_TIMING_PARAMETERS {
+	USHORT usH_Total;	/*  horizontal total */
+	USHORT usH_Disp;	/*  horizontal display */
+	USHORT usH_SyncStart;	/*  horozontal Sync start */
+	USHORT usH_SyncWidth;	/*  horizontal Sync width */
+	USHORT usV_Total;	/*  vertical total */
+	USHORT usV_Disp;	/*  vertical display */
+	USHORT usV_SyncStart;	/*  vertical Sync start */
+	USHORT usV_SyncWidth;	/*  vertical Sync width */
+	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
+	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
+	UCHAR ucOverscanRight;	/*  right */
+	UCHAR ucOverscanLeft;	/*  left */
+	UCHAR ucOverscanBottom;	/*  bottom */
+	UCHAR ucOverscanTop;	/*  top */
+	UCHAR ucReserved;
+} SET_CRTC_TIMING_PARAMETERS;
+#define SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION SET_CRTC_TIMING_PARAMETERS
+
+/****************************************************************************/
+/*  Structure used in StandardVESA_TimingTable */
+/*                    AnalogTV_InfoTable */
+/*                    ComponentVideoInfoTable */
+/****************************************************************************/
+typedef struct _ATOM_MODE_TIMING {
+	USHORT usCRTC_H_Total;
+	USHORT usCRTC_H_Disp;
+	USHORT usCRTC_H_SyncStart;
+	USHORT usCRTC_H_SyncWidth;
+	USHORT usCRTC_V_Total;
+	USHORT usCRTC_V_Disp;
+	USHORT usCRTC_V_SyncStart;
+	USHORT usCRTC_V_SyncWidth;
+	USHORT usPixelClock;	/* in 10Khz unit */
+	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
+	USHORT usCRTC_OverscanRight;
+	USHORT usCRTC_OverscanLeft;
+	USHORT usCRTC_OverscanBottom;
+	USHORT usCRTC_OverscanTop;
+	USHORT usReserve;
+	UCHAR ucInternalModeNumber;
+	UCHAR ucRefreshRate;
+} ATOM_MODE_TIMING;
+
+typedef struct _ATOM_DTD_FORMAT {
+	USHORT usPixClk;
+	USHORT usHActive;
+	USHORT usHBlanking_Time;
+	USHORT usVActive;
+	USHORT usVBlanking_Time;
+	USHORT usHSyncOffset;
+	USHORT usHSyncWidth;
+	USHORT usVSyncOffset;
+	USHORT usVSyncWidth;
+	USHORT usImageHSize;
+	USHORT usImageVSize;
+	UCHAR ucHBorder;
+	UCHAR ucVBorder;
+	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
+	UCHAR ucInternalModeNumber;
+	UCHAR ucRefreshRate;
+} ATOM_DTD_FORMAT;
+
+/****************************************************************************/
+/*  Structure used in LVDS_InfoTable */
+/*   * Need a document to describe this table */
+/****************************************************************************/
+#define SUPPORTED_LCD_REFRESHRATE_30Hz          0x0004
+#define SUPPORTED_LCD_REFRESHRATE_40Hz          0x0008
+#define SUPPORTED_LCD_REFRESHRATE_50Hz          0x0010
+#define SUPPORTED_LCD_REFRESHRATE_60Hz          0x0020
+
+/* Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. */
+/* Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL */
+#define	LCDPANEL_CAP_READ_EDID									0x1
+
+/* ucTableFormatRevision=1 */
+/* ucTableContentRevision=1 */
+typedef struct _ATOM_LVDS_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_DTD_FORMAT sLCDTiming;
+	USHORT usModePatchTableOffset;
+	USHORT usSupportedRefreshRate;	/* Refer to panel info table in ATOMBIOS extension Spec. */
+	USHORT usOffDelayInMs;
+	UCHAR ucPowerSequenceDigOntoDEin10Ms;
+	UCHAR ucPowerSequenceDEtoBLOnin10Ms;
+	UCHAR ucLVDS_Misc;	/*  Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} */
+	/*  Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} */
+	/*  Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} */
+	/*  Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} */
+	UCHAR ucPanelDefaultRefreshRate;
+	UCHAR ucPanelIdentification;
+	UCHAR ucSS_Id;
+} ATOM_LVDS_INFO;
+
+/* ucTableFormatRevision=1 */
+/* ucTableContentRevision=2 */
+typedef struct _ATOM_LVDS_INFO_V12 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_DTD_FORMAT sLCDTiming;
+	USHORT usExtInfoTableOffset;
+	USHORT usSupportedRefreshRate;	/* Refer to panel info table in ATOMBIOS extension Spec. */
+	USHORT usOffDelayInMs;
+	UCHAR ucPowerSequenceDigOntoDEin10Ms;
+	UCHAR ucPowerSequenceDEtoBLOnin10Ms;
+	UCHAR ucLVDS_Misc;	/*  Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} */
+	/*  Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} */
+	/*  Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} */
+	/*  Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} */
+	UCHAR ucPanelDefaultRefreshRate;
+	UCHAR ucPanelIdentification;
+	UCHAR ucSS_Id;
+	USHORT usLCDVenderID;
+	USHORT usLCDProductID;
+	UCHAR ucLCDPanel_SpecialHandlingCap;
+	UCHAR ucPanelInfoSize;	/*   start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable */
+	UCHAR ucReserved[2];
+} ATOM_LVDS_INFO_V12;
+
+#define ATOM_LVDS_INFO_LAST  ATOM_LVDS_INFO_V12
+
+typedef struct _ATOM_PATCH_RECORD_MODE {
+	UCHAR ucRecordType;
+	USHORT usHDisp;
+	USHORT usVDisp;
+} ATOM_PATCH_RECORD_MODE;
+
+typedef struct _ATOM_LCD_RTS_RECORD {
+	UCHAR ucRecordType;
+	UCHAR ucRTSValue;
+} ATOM_LCD_RTS_RECORD;
+
+/* !! If the record below exits, it shoud always be the first record for easy use in command table!!! */
+typedef struct _ATOM_LCD_MODE_CONTROL_CAP {
+	UCHAR ucRecordType;
+	USHORT usLCDCap;
+} ATOM_LCD_MODE_CONTROL_CAP;
+
+#define LCD_MODE_CAP_BL_OFF                   1
+#define LCD_MODE_CAP_CRTC_OFF                 2
+#define LCD_MODE_CAP_PANEL_OFF                4
+
+typedef struct _ATOM_FAKE_EDID_PATCH_RECORD {
+	UCHAR ucRecordType;
+	UCHAR ucFakeEDIDLength;
+	UCHAR ucFakeEDIDString[1];	/*  This actually has ucFakeEdidLength elements. */
+} ATOM_FAKE_EDID_PATCH_RECORD;
+
+typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD {
+	UCHAR ucRecordType;
+	USHORT usHSize;
+	USHORT usVSize;
+} ATOM_PANEL_RESOLUTION_PATCH_RECORD;
+
+#define LCD_MODE_PATCH_RECORD_MODE_TYPE       1
+#define LCD_RTS_RECORD_TYPE                   2
+#define LCD_CAP_RECORD_TYPE                   3
+#define LCD_FAKE_EDID_PATCH_RECORD_TYPE       4
+#define LCD_PANEL_RESOLUTION_RECORD_TYPE      5
+#define ATOM_RECORD_END_TYPE                  0xFF
+
+/****************************Spread Spectrum Info Table Definitions **********************/
+
+/* ucTableFormatRevision=1 */
+/* ucTableContentRevision=2 */
+typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT {
+	USHORT usSpreadSpectrumPercentage;
+	UCHAR ucSpreadSpectrumType;	/* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
+	UCHAR ucSS_Step;
+	UCHAR ucSS_Delay;
+	UCHAR ucSS_Id;
+	UCHAR ucRecommandedRef_Div;
+	UCHAR ucSS_Range;	/* it was reserved for V11 */
+} ATOM_SPREAD_SPECTRUM_ASSIGNMENT;
+
+#define ATOM_MAX_SS_ENTRY                      16
+#define ATOM_DP_SS_ID1												 0x0f1	/*  SS modulation freq=30k */
+#define ATOM_DP_SS_ID2												 0x0f2	/*  SS modulation freq=33k */
+
+#define ATOM_SS_DOWN_SPREAD_MODE_MASK          0x00000000
+#define ATOM_SS_DOWN_SPREAD_MODE               0x00000000
+#define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
+#define ATOM_SS_CENTRE_SPREAD_MODE             0x00000001
+#define ATOM_INTERNAL_SS_MASK                  0x00000000
+#define ATOM_EXTERNAL_SS_MASK                  0x00000002
+#define EXEC_SS_STEP_SIZE_SHIFT                2
+#define EXEC_SS_DELAY_SHIFT                    4
+#define ACTIVEDATA_TO_BLON_DELAY_SHIFT         4
+
+typedef struct _ATOM_SPREAD_SPECTRUM_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_SPREAD_SPECTRUM_ASSIGNMENT asSS_Info[ATOM_MAX_SS_ENTRY];
+} ATOM_SPREAD_SPECTRUM_INFO;
+
+/****************************************************************************/
+/*  Structure used in AnalogTV_InfoTable (Top level) */
+/****************************************************************************/
+/* ucTVBootUpDefaultStd definiton: */
+
+/* ATOM_TV_NTSC                1 */
+/* ATOM_TV_NTSCJ               2 */
+/* ATOM_TV_PAL                 3 */
+/* ATOM_TV_PALM                4 */
+/* ATOM_TV_PALCN               5 */
+/* ATOM_TV_PALN                6 */
+/* ATOM_TV_PAL60               7 */
+/* ATOM_TV_SECAM               8 */
+
+/* ucTVSuppportedStd definition: */
+#define NTSC_SUPPORT          0x1
+#define NTSCJ_SUPPORT         0x2
+
+#define PAL_SUPPORT           0x4
+#define PALM_SUPPORT          0x8
+#define PALCN_SUPPORT         0x10
+#define PALN_SUPPORT          0x20
+#define PAL60_SUPPORT         0x40
+#define SECAM_SUPPORT         0x80
+
+#define MAX_SUPPORTED_TV_TIMING    2
+
+typedef struct _ATOM_ANALOG_TV_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR ucTV_SupportedStandard;
+	UCHAR ucTV_BootUpDefaultStandard;
+	UCHAR ucExt_TV_ASIC_ID;
+	UCHAR ucExt_TV_ASIC_SlaveAddr;
+	/*ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING]; */
+	ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING];
+} ATOM_ANALOG_TV_INFO;
+
+/**************************************************************************/
+/*  VRAM usage and their defintions */
+
+/*  One chunk of VRAM used by Bios are for HWICON surfaces,EDID data. */
+/*  Current Mode timing and Dail Timing and/or STD timing data EACH device. They can be broken down as below. */
+/*  All the addresses below are the offsets from the frame buffer start.They all MUST be Dword aligned! */
+/*  To driver: The physical address of this memory portion=mmFB_START(4K aligned)+ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR */
+/*  To Bios:  ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR->MM_INDEX */
+
+#ifndef VESA_MEMORY_IN_64K_BLOCK
+#define VESA_MEMORY_IN_64K_BLOCK        0x100	/* 256*64K=16Mb (Max. VESA memory is 16Mb!) */
+#endif
+
+#define ATOM_EDID_RAW_DATASIZE          256	/* In Bytes */
+#define ATOM_HWICON_SURFACE_SIZE        4096	/* In Bytes */
+#define ATOM_HWICON_INFOTABLE_SIZE      32
+#define MAX_DTD_MODE_IN_VRAM            6
+#define ATOM_DTD_MODE_SUPPORT_TBL_SIZE  (MAX_DTD_MODE_IN_VRAM*28)	/* 28= (SIZEOF ATOM_DTD_FORMAT) */
+#define ATOM_STD_MODE_SUPPORT_TBL_SIZE  (32*8)	/* 32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT) */
+#define DFP_ENCODER_TYPE_OFFSET					0x80
+#define DP_ENCODER_LANE_NUM_OFFSET			0x84
+#define DP_ENCODER_LINK_RATE_OFFSET			0x88
+
+#define ATOM_HWICON1_SURFACE_ADDR       0
+#define ATOM_HWICON2_SURFACE_ADDR       (ATOM_HWICON1_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE)
+#define ATOM_HWICON_INFOTABLE_ADDR      (ATOM_HWICON2_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE)
+#define ATOM_CRT1_EDID_ADDR             (ATOM_HWICON_INFOTABLE_ADDR + ATOM_HWICON_INFOTABLE_SIZE)
+#define ATOM_CRT1_DTD_MODE_TBL_ADDR     (ATOM_CRT1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_CRT1_STD_MODE_TBL_ADDR	    (ATOM_CRT1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_LCD1_EDID_ADDR             (ATOM_CRT1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_LCD1_DTD_MODE_TBL_ADDR     (ATOM_LCD1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_LCD1_STD_MODE_TBL_ADDR	(ATOM_LCD1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_TV1_DTD_MODE_TBL_ADDR      (ATOM_LCD1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_DFP1_EDID_ADDR             (ATOM_TV1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP1_DTD_MODE_TBL_ADDR     (ATOM_DFP1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_DFP1_STD_MODE_TBL_ADDR	    (ATOM_DFP1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_CRT2_EDID_ADDR             (ATOM_DFP1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_CRT2_DTD_MODE_TBL_ADDR     (ATOM_CRT2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_CRT2_STD_MODE_TBL_ADDR	    (ATOM_CRT2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_LCD2_EDID_ADDR             (ATOM_CRT2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_LCD2_DTD_MODE_TBL_ADDR     (ATOM_LCD2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_LCD2_STD_MODE_TBL_ADDR	(ATOM_LCD2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_TV2_EDID_ADDR              (ATOM_LCD2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_TV2_DTD_MODE_TBL_ADDR      (ATOM_TV2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_TV2_STD_MODE_TBL_ADDR	  (ATOM_TV2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_DFP2_EDID_ADDR             (ATOM_TV2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP2_DTD_MODE_TBL_ADDR     (ATOM_DFP2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_DFP2_STD_MODE_TBL_ADDR     (ATOM_DFP2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_CV_EDID_ADDR               (ATOM_DFP2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_CV_DTD_MODE_TBL_ADDR       (ATOM_CV_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_CV_STD_MODE_TBL_ADDR       (ATOM_CV_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_DFP3_EDID_ADDR             (ATOM_CV_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP3_DTD_MODE_TBL_ADDR     (ATOM_DFP3_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_DFP3_STD_MODE_TBL_ADDR     (ATOM_DFP3_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_DFP4_EDID_ADDR             (ATOM_DFP3_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP4_DTD_MODE_TBL_ADDR     (ATOM_DFP4_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_DFP4_STD_MODE_TBL_ADDR     (ATOM_DFP4_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_DFP5_EDID_ADDR             (ATOM_DFP4_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP5_DTD_MODE_TBL_ADDR     (ATOM_DFP5_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_DFP5_STD_MODE_TBL_ADDR     (ATOM_DFP5_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_DP_TRAINING_TBL_ADDR	(ATOM_DFP5_STD_MODE_TBL_ADDR+ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+
+#define ATOM_STACK_STORAGE_START        (ATOM_DP_TRAINING_TBL_ADDR + 256)
+#define ATOM_STACK_STORAGE_END          (ATOM_STACK_STORAGE_START + 512)
+
+/* The size below is in Kb! */
+#define ATOM_VRAM_RESERVE_SIZE         ((((ATOM_STACK_STORAGE_END - ATOM_HWICON1_SURFACE_ADDR)>>10)+4)&0xFFFC)
+
+#define	ATOM_VRAM_OPERATION_FLAGS_MASK         0xC0000000L
+#define ATOM_VRAM_OPERATION_FLAGS_SHIFT        30
+#define	ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION   0x1
+#define	ATOM_VRAM_BLOCK_NEEDS_RESERVATION      0x0
+
+/***********************************************************************************/
+/*  Structure used in VRAM_UsageByFirmwareTable */
+/*  Note1: This table is filled by SetBiosReservationStartInFB in CoreCommSubs.asm */
+/*         at running time. */
+/*  note2: From RV770, the memory is more than 32bit addressable, so we will change */
+/*         ucTableFormatRevision=1,ucTableContentRevision=4, the strcuture remains */
+/*         exactly same as 1.1 and 1.2 (1.3 is never in use), but ulStartAddrUsedByFirmware */
+/*         (in offset to start of memory address) is KB aligned instead of byte aligend. */
+/***********************************************************************************/
+#define ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO			1
+
+typedef struct _ATOM_FIRMWARE_VRAM_RESERVE_INFO {
+	ULONG ulStartAddrUsedByFirmware;
+	USHORT usFirmwareUseInKb;
+	USHORT usReserved;
+} ATOM_FIRMWARE_VRAM_RESERVE_INFO;
+
+typedef struct _ATOM_VRAM_USAGE_BY_FIRMWARE {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_FIRMWARE_VRAM_RESERVE_INFO
+	    asFirmwareVramReserveInfo[ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO];
+} ATOM_VRAM_USAGE_BY_FIRMWARE;
+
+/****************************************************************************/
+/*  Structure used in GPIO_Pin_LUTTable */
+/****************************************************************************/
+typedef struct _ATOM_GPIO_PIN_ASSIGNMENT {
+	USHORT usGpioPin_AIndex;
+	UCHAR ucGpioPinBitShift;
+	UCHAR ucGPIO_ID;
+} ATOM_GPIO_PIN_ASSIGNMENT;
+
+typedef struct _ATOM_GPIO_PIN_LUT {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[1];
+} ATOM_GPIO_PIN_LUT;
+
+/****************************************************************************/
+/*  Structure used in ComponentVideoInfoTable */
+/****************************************************************************/
+#define GPIO_PIN_ACTIVE_HIGH          0x1
+
+#define MAX_SUPPORTED_CV_STANDARDS    5
+
+/*  definitions for ATOM_D_INFO.ucSettings */
+#define ATOM_GPIO_SETTINGS_BITSHIFT_MASK  0x1F	/*  [4:0] */
+#define ATOM_GPIO_SETTINGS_RESERVED_MASK  0x60	/*  [6:5] = must be zeroed out */
+#define ATOM_GPIO_SETTINGS_ACTIVE_MASK    0x80	/*  [7] */
+
+typedef struct _ATOM_GPIO_INFO {
+	USHORT usAOffset;
+	UCHAR ucSettings;
+	UCHAR ucReserved;
+} ATOM_GPIO_INFO;
+
+/*  definitions for ATOM_COMPONENT_VIDEO_INFO.ucMiscInfo (bit vector) */
+#define ATOM_CV_RESTRICT_FORMAT_SELECTION           0x2
+
+/*  definitions for ATOM_COMPONENT_VIDEO_INFO.uc480i/uc480p/uc720p/uc1080i */
+#define ATOM_GPIO_DEFAULT_MODE_EN                   0x80	/* [7]; */
+#define ATOM_GPIO_SETTING_PERMODE_MASK              0x7F	/* [6:0] */
+
+/*  definitions for ATOM_COMPONENT_VIDEO_INFO.ucLetterBoxMode */
+/* Line 3 out put 5V. */
+#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_A       0x01	/* represent gpio 3 state for 16:9 */
+#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_B       0x02	/* represent gpio 4 state for 16:9 */
+#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_SHIFT   0x0
+
+/* Line 3 out put 2.2V */
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_A 0x04	/* represent gpio 3 state for 4:3 Letter box */
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_B 0x08	/* represent gpio 4 state for 4:3 Letter box */
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_SHIFT 0x2
+
+/* Line 3 out put 0V */
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_A        0x10	/* represent gpio 3 state for 4:3 */
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_B        0x20	/* represent gpio 4 state for 4:3 */
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_SHIFT    0x4
+
+#define ATOM_CV_LINE3_ASPECTRATIO_MASK              0x3F	/*  bit [5:0] */
+
+#define ATOM_CV_LINE3_ASPECTRATIO_EXIST             0x80	/* bit 7 */
+
+/* GPIO bit index in gpio setting per mode value, also represend the block no. in gpio blocks. */
+#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_A   3	/* bit 3 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. */
+#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_B   4	/* bit 4 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. */
+
+typedef struct _ATOM_COMPONENT_VIDEO_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usMask_PinRegisterIndex;
+	USHORT usEN_PinRegisterIndex;
+	USHORT usY_PinRegisterIndex;
+	USHORT usA_PinRegisterIndex;
+	UCHAR ucBitShift;
+	UCHAR ucPinActiveState;	/* ucPinActiveState: Bit0=1 active high, =0 active low */
+	ATOM_DTD_FORMAT sReserved;	/*  must be zeroed out */
+	UCHAR ucMiscInfo;
+	UCHAR uc480i;
+	UCHAR uc480p;
+	UCHAR uc720p;
+	UCHAR uc1080i;
+	UCHAR ucLetterBoxMode;
+	UCHAR ucReserved[3];
+	UCHAR ucNumOfWbGpioBlocks;	/* For Component video D-Connector support. If zere, NTSC type connector */
+	ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS];
+	ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS];
+} ATOM_COMPONENT_VIDEO_INFO;
+
+/* ucTableFormatRevision=2 */
+/* ucTableContentRevision=1 */
+typedef struct _ATOM_COMPONENT_VIDEO_INFO_V21 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR ucMiscInfo;
+	UCHAR uc480i;
+	UCHAR uc480p;
+	UCHAR uc720p;
+	UCHAR uc1080i;
+	UCHAR ucReserved;
+	UCHAR ucLetterBoxMode;
+	UCHAR ucNumOfWbGpioBlocks;	/* For Component video D-Connector support. If zere, NTSC type connector */
+	ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS];
+	ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS];
+} ATOM_COMPONENT_VIDEO_INFO_V21;
+
+#define ATOM_COMPONENT_VIDEO_INFO_LAST  ATOM_COMPONENT_VIDEO_INFO_V21
+
+/****************************************************************************/
+/*  Structure used in object_InfoTable */
+/****************************************************************************/
+typedef struct _ATOM_OBJECT_HEADER {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usDeviceSupport;
+	USHORT usConnectorObjectTableOffset;
+	USHORT usRouterObjectTableOffset;
+	USHORT usEncoderObjectTableOffset;
+	USHORT usProtectionObjectTableOffset;	/* only available when Protection block is independent. */
+	USHORT usDisplayPathTableOffset;
+} ATOM_OBJECT_HEADER;
+
+typedef struct _ATOM_DISPLAY_OBJECT_PATH {
+	USHORT usDeviceTag;	/* supported device */
+	USHORT usSize;		/* the size of ATOM_DISPLAY_OBJECT_PATH */
+	USHORT usConnObjectId;	/* Connector Object ID */
+	USHORT usGPUObjectId;	/* GPU ID */
+	USHORT usGraphicObjIds[1];	/* 1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. */
+} ATOM_DISPLAY_OBJECT_PATH;
+
+typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE {
+	UCHAR ucNumOfDispPath;
+	UCHAR ucVersion;
+	UCHAR ucPadding[2];
+	ATOM_DISPLAY_OBJECT_PATH asDispPath[1];
+} ATOM_DISPLAY_OBJECT_PATH_TABLE;
+
+typedef struct _ATOM_OBJECT	/* each object has this structure */
+{
+	USHORT usObjectID;
+	USHORT usSrcDstTableOffset;
+	USHORT usRecordOffset;	/* this pointing to a bunch of records defined below */
+	USHORT usReserved;
+} ATOM_OBJECT;
+
+typedef struct _ATOM_OBJECT_TABLE	/* Above 4 object table offset pointing to a bunch of objects all have this structure */
+{
+	UCHAR ucNumberOfObjects;
+	UCHAR ucPadding[3];
+	ATOM_OBJECT asObjects[1];
+} ATOM_OBJECT_TABLE;
+
+typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT	/* usSrcDstTableOffset pointing to this structure */
+{
+	UCHAR ucNumberOfSrc;
+	USHORT usSrcObjectID[1];
+	UCHAR ucNumberOfDst;
+	USHORT usDstObjectID[1];
+} ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT;
+
+/* Related definitions, all records are differnt but they have a commond header */
+typedef struct _ATOM_COMMON_RECORD_HEADER {
+	UCHAR ucRecordType;	/* An emun to indicate the record type */
+	UCHAR ucRecordSize;	/* The size of the whole record in byte */
+} ATOM_COMMON_RECORD_HEADER;
+
+#define ATOM_I2C_RECORD_TYPE                           1
+#define ATOM_HPD_INT_RECORD_TYPE                       2
+#define ATOM_OUTPUT_PROTECTION_RECORD_TYPE             3
+#define ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE          4
+#define	ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD_TYPE	     5	/* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */
+#define ATOM_ENCODER_FPGA_CONTROL_RECORD_TYPE          6	/* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */
+#define ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE      7
+#define ATOM_JTAG_RECORD_TYPE                          8	/* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */
+#define ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE              9
+#define ATOM_ENCODER_DVO_CF_RECORD_TYPE               10
+#define ATOM_CONNECTOR_CF_RECORD_TYPE                 11
+#define	ATOM_CONNECTOR_HARDCODE_DTD_RECORD_TYPE	      12
+#define ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE  13
+#define ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE				14
+#define ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE					15
+
+/* Must be updated when new record type is added,equal to that record definition! */
+#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_CONNECTOR_CF_RECORD_TYPE
+
+typedef struct _ATOM_I2C_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	ATOM_I2C_ID_CONFIG sucI2cId;
+	UCHAR ucI2CAddr;	/* The slave address, it's 0 when the record is attached to connector for DDC */
+} ATOM_I2C_RECORD;
+
+typedef struct _ATOM_HPD_INT_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucHPDIntGPIOID;	/* Corresponding block in GPIO_PIN_INFO table gives the pin info */
+	UCHAR ucPluggged_PinState;
+} ATOM_HPD_INT_RECORD;
+
+typedef struct _ATOM_OUTPUT_PROTECTION_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucProtectionFlag;
+	UCHAR ucReserved;
+} ATOM_OUTPUT_PROTECTION_RECORD;
+
+typedef struct _ATOM_CONNECTOR_DEVICE_TAG {
+	ULONG ulACPIDeviceEnum;	/* Reserved for now */
+	USHORT usDeviceID;	/* This Id is same as "ATOM_DEVICE_XXX_SUPPORT" */
+	USHORT usPadding;
+} ATOM_CONNECTOR_DEVICE_TAG;
+
+typedef struct _ATOM_CONNECTOR_DEVICE_TAG_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucNumberOfDevice;
+	UCHAR ucReserved;
+	ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[1];	/* This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation */
+} ATOM_CONNECTOR_DEVICE_TAG_RECORD;
+
+typedef struct _ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucConfigGPIOID;
+	UCHAR ucConfigGPIOState;	/* Set to 1 when it's active high to enable external flow in */
+	UCHAR ucFlowinGPIPID;
+	UCHAR ucExtInGPIPID;
+} ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD;
+
+typedef struct _ATOM_ENCODER_FPGA_CONTROL_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucCTL1GPIO_ID;
+	UCHAR ucCTL1GPIOState;	/* Set to 1 when it's active high */
+	UCHAR ucCTL2GPIO_ID;
+	UCHAR ucCTL2GPIOState;	/* Set to 1 when it's active high */
+	UCHAR ucCTL3GPIO_ID;
+	UCHAR ucCTL3GPIOState;	/* Set to 1 when it's active high */
+	UCHAR ucCTLFPGA_IN_ID;
+	UCHAR ucPadding[3];
+} ATOM_ENCODER_FPGA_CONTROL_RECORD;
+
+typedef struct _ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucGPIOID;		/* Corresponding block in GPIO_PIN_INFO table gives the pin info */
+	UCHAR ucTVActiveState;	/* Indicating when the pin==0 or 1 when TV is connected */
+} ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD;
+
+typedef struct _ATOM_JTAG_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucTMSGPIO_ID;
+	UCHAR ucTMSGPIOState;	/* Set to 1 when it's active high */
+	UCHAR ucTCKGPIO_ID;
+	UCHAR ucTCKGPIOState;	/* Set to 1 when it's active high */
+	UCHAR ucTDOGPIO_ID;
+	UCHAR ucTDOGPIOState;	/* Set to 1 when it's active high */
+	UCHAR ucTDIGPIO_ID;
+	UCHAR ucTDIGPIOState;	/* Set to 1 when it's active high */
+	UCHAR ucPadding[2];
+} ATOM_JTAG_RECORD;
+
+/* The following generic object gpio pin control record type will replace JTAG_RECORD/FPGA_CONTROL_RECORD/DVI_EXT_INPUT_RECORD above gradually */
+typedef struct _ATOM_GPIO_PIN_CONTROL_PAIR {
+	UCHAR ucGPIOID;		/*  GPIO_ID, find the corresponding ID in GPIO_LUT table */
+	UCHAR ucGPIO_PinState;	/*  Pin state showing how to set-up the pin */
+} ATOM_GPIO_PIN_CONTROL_PAIR;
+
+typedef struct _ATOM_OBJECT_GPIO_CNTL_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucFlags;		/*  Future expnadibility */
+	UCHAR ucNumberOfPins;	/*  Number of GPIO pins used to control the object */
+	ATOM_GPIO_PIN_CONTROL_PAIR asGpio[1];	/*  the real gpio pin pair determined by number of pins ucNumberOfPins */
+} ATOM_OBJECT_GPIO_CNTL_RECORD;
+
+/* Definitions for GPIO pin state */
+#define GPIO_PIN_TYPE_INPUT             0x00
+#define GPIO_PIN_TYPE_OUTPUT            0x10
+#define GPIO_PIN_TYPE_HW_CONTROL        0x20
+
+/* For GPIO_PIN_TYPE_OUTPUT the following is defined */
+#define GPIO_PIN_OUTPUT_STATE_MASK      0x01
+#define GPIO_PIN_OUTPUT_STATE_SHIFT     0
+#define GPIO_PIN_STATE_ACTIVE_LOW       0x0
+#define GPIO_PIN_STATE_ACTIVE_HIGH      0x1
+
+typedef struct _ATOM_ENCODER_DVO_CF_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	ULONG ulStrengthControl;	/*  DVOA strength control for CF */
+	UCHAR ucPadding[2];
+} ATOM_ENCODER_DVO_CF_RECORD;
+
+/*  value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle */
+#define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA   1
+#define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB   2
+
+typedef struct _ATOM_CONNECTOR_CF_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	USHORT usMaxPixClk;
+	UCHAR ucFlowCntlGpioId;
+	UCHAR ucSwapCntlGpioId;
+	UCHAR ucConnectedDvoBundle;
+	UCHAR ucPadding;
+} ATOM_CONNECTOR_CF_RECORD;
+
+typedef struct _ATOM_CONNECTOR_HARDCODE_DTD_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	ATOM_DTD_FORMAT asTiming;
+} ATOM_CONNECTOR_HARDCODE_DTD_RECORD;
+
+typedef struct _ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;	/* ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE */
+	UCHAR ucSubConnectorType;	/* CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D|X_ID_DUAL_LINK_DVI_D|HDMI_TYPE_A */
+	UCHAR ucReserved;
+} ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD;
+
+typedef struct _ATOM_ROUTER_DDC_PATH_SELECT_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucMuxType;	/* decide the number of ucMuxState, =0, no pin state, =1: single state with complement, >1: multiple state */
+	UCHAR ucMuxControlPin;
+	UCHAR ucMuxState[2];	/* for alligment purpose */
+} ATOM_ROUTER_DDC_PATH_SELECT_RECORD;
+
+typedef struct _ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD {
+	ATOM_COMMON_RECORD_HEADER sheader;
+	UCHAR ucMuxType;
+	UCHAR ucMuxControlPin;
+	UCHAR ucMuxState[2];	/* for alligment purpose */
+} ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD;
+
+/*  define ucMuxType */
+#define ATOM_ROUTER_MUX_PIN_STATE_MASK								0x0f
+#define ATOM_ROUTER_MUX_PIN_SINGLE_STATE_COMPLEMENT		0x01
+
+/****************************************************************************/
+/*  ASIC voltage data table */
+/****************************************************************************/
+typedef struct _ATOM_VOLTAGE_INFO_HEADER {
+	USHORT usVDDCBaseLevel;	/* In number of 50mv unit */
+	USHORT usReserved;	/* For possible extension table offset */
+	UCHAR ucNumOfVoltageEntries;
+	UCHAR ucBytesPerVoltageEntry;
+	UCHAR ucVoltageStep;	/* Indicating in how many mv increament is one step, 0.5mv unit */
+	UCHAR ucDefaultVoltageEntry;
+	UCHAR ucVoltageControlI2cLine;
+	UCHAR ucVoltageControlAddress;
+	UCHAR ucVoltageControlOffset;
+} ATOM_VOLTAGE_INFO_HEADER;
+
+typedef struct _ATOM_VOLTAGE_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_VOLTAGE_INFO_HEADER viHeader;
+	UCHAR ucVoltageEntries[64];	/* 64 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries*ucBytesPerVoltageEntry */
+} ATOM_VOLTAGE_INFO;
+
+typedef struct _ATOM_VOLTAGE_FORMULA {
+	USHORT usVoltageBaseLevel;	/*  In number of 1mv unit */
+	USHORT usVoltageStep;	/*  Indicating in how many mv increament is one step, 1mv unit */
+	UCHAR ucNumOfVoltageEntries;	/*  Number of Voltage Entry, which indicate max Voltage */
+	UCHAR ucFlag;		/*  bit0=0 :step is 1mv =1 0.5mv */
+	UCHAR ucBaseVID;	/*  if there is no lookup table, VID= BaseVID + ( Vol - BaseLevle ) /VoltageStep */
+	UCHAR ucReserved;
+	UCHAR ucVIDAdjustEntries[32];	/*  32 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries */
+} ATOM_VOLTAGE_FORMULA;
+
+typedef struct _ATOM_VOLTAGE_CONTROL {
+	UCHAR ucVoltageControlId;	/* Indicate it is controlled by I2C or GPIO or HW state machine */
+	UCHAR ucVoltageControlI2cLine;
+	UCHAR ucVoltageControlAddress;
+	UCHAR ucVoltageControlOffset;
+	USHORT usGpioPin_AIndex;	/* GPIO_PAD register index */
+	UCHAR ucGpioPinBitShift[9];	/* at most 8 pin support 255 VIDs, termintate with 0xff */
+	UCHAR ucReserved;
+} ATOM_VOLTAGE_CONTROL;
+
+/*  Define ucVoltageControlId */
+#define	VOLTAGE_CONTROLLED_BY_HW							0x00
+#define	VOLTAGE_CONTROLLED_BY_I2C_MASK				0x7F
+#define	VOLTAGE_CONTROLLED_BY_GPIO						0x80
+#define	VOLTAGE_CONTROL_ID_LM64								0x01	/* I2C control, used for R5xx Core Voltage */
+#define	VOLTAGE_CONTROL_ID_DAC								0x02	/* I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI */
+#define	VOLTAGE_CONTROL_ID_VT116xM						0x03	/* I2C control, used for R6xx Core Voltage */
+#define VOLTAGE_CONTROL_ID_DS4402							0x04
+
+typedef struct _ATOM_VOLTAGE_OBJECT {
+	UCHAR ucVoltageType;	/* Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI */
+	UCHAR ucSize;		/* Size of Object */
+	ATOM_VOLTAGE_CONTROL asControl;	/* describ how to control */
+	ATOM_VOLTAGE_FORMULA asFormula;	/* Indicate How to convert real Voltage to VID */
+} ATOM_VOLTAGE_OBJECT;
+
+typedef struct _ATOM_VOLTAGE_OBJECT_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_VOLTAGE_OBJECT asVoltageObj[3];	/* Info for Voltage control */
+} ATOM_VOLTAGE_OBJECT_INFO;
+
+typedef struct _ATOM_LEAKID_VOLTAGE {
+	UCHAR ucLeakageId;
+	UCHAR ucReserved;
+	USHORT usVoltage;
+} ATOM_LEAKID_VOLTAGE;
+
+typedef struct _ATOM_ASIC_PROFILE_VOLTAGE {
+	UCHAR ucProfileId;
+	UCHAR ucReserved;
+	USHORT usSize;
+	USHORT usEfuseSpareStartAddr;
+	USHORT usFuseIndex[8];	/* from LSB to MSB, Max 8bit,end of 0xffff if less than 8 efuse id, */
+	ATOM_LEAKID_VOLTAGE asLeakVol[2];	/* Leakid and relatd voltage */
+} ATOM_ASIC_PROFILE_VOLTAGE;
+
+/* ucProfileId */
+#define	ATOM_ASIC_PROFILE_ID_EFUSE_VOLTAGE			1
+#define	ATOM_ASIC_PROFILE_ID_EFUSE_PERFORMANCE_VOLTAGE			1
+#define	ATOM_ASIC_PROFILE_ID_EFUSE_THERMAL_VOLTAGE					2
+
+typedef struct _ATOM_ASIC_PROFILING_INFO {
+	ATOM_COMMON_TABLE_HEADER asHeader;
+	ATOM_ASIC_PROFILE_VOLTAGE asVoltage;
+} ATOM_ASIC_PROFILING_INFO;
+
+typedef struct _ATOM_POWER_SOURCE_OBJECT {
+	UCHAR ucPwrSrcId;	/*  Power source */
+	UCHAR ucPwrSensorType;	/*  GPIO, I2C or none */
+	UCHAR ucPwrSensId;	/*  if GPIO detect, it is GPIO id,  if I2C detect, it is I2C id */
+	UCHAR ucPwrSensSlaveAddr;	/*  Slave address if I2C detect */
+	UCHAR ucPwrSensRegIndex;	/*  I2C register Index if I2C detect */
+	UCHAR ucPwrSensRegBitMask;	/*  detect which bit is used if I2C detect */
+	UCHAR ucPwrSensActiveState;	/*  high active or low active */
+	UCHAR ucReserve[3];	/*  reserve */
+	USHORT usSensPwr;	/*  in unit of watt */
+} ATOM_POWER_SOURCE_OBJECT;
+
+typedef struct _ATOM_POWER_SOURCE_INFO {
+	ATOM_COMMON_TABLE_HEADER asHeader;
+	UCHAR asPwrbehave[16];
+	ATOM_POWER_SOURCE_OBJECT asPwrObj[1];
+} ATOM_POWER_SOURCE_INFO;
+
+/* Define ucPwrSrcId */
+#define POWERSOURCE_PCIE_ID1						0x00
+#define POWERSOURCE_6PIN_CONNECTOR_ID1	0x01
+#define POWERSOURCE_8PIN_CONNECTOR_ID1	0x02
+#define POWERSOURCE_6PIN_CONNECTOR_ID2	0x04
+#define POWERSOURCE_8PIN_CONNECTOR_ID2	0x08
+
+/* define ucPwrSensorId */
+#define POWER_SENSOR_ALWAYS							0x00
+#define POWER_SENSOR_GPIO								0x01
+#define POWER_SENSOR_I2C								0x02
+
+/**************************************************************************/
+/*  This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design */
+/* Memory SS Info Table */
+/* Define Memory Clock SS chip ID */
+#define ICS91719  1
+#define ICS91720  2
+
+/* Define one structure to inform SW a "block of data" writing to external SS chip via I2C protocol */
+typedef struct _ATOM_I2C_DATA_RECORD {
+	UCHAR ucNunberOfBytes;	/* Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop" */
+	UCHAR ucI2CData[1];	/* I2C data in bytes, should be less than 16 bytes usually */
+} ATOM_I2C_DATA_RECORD;
+
+/* Define one structure to inform SW how many blocks of data writing to external SS chip via I2C protocol, in addition to other information */
+typedef struct _ATOM_I2C_DEVICE_SETUP_INFO {
+	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;	/* I2C line and HW/SW assisted cap. */
+	UCHAR ucSSChipID;	/* SS chip being used */
+	UCHAR ucSSChipSlaveAddr;	/* Slave Address to set up this SS chip */
+	UCHAR ucNumOfI2CDataRecords;	/* number of data block */
+	ATOM_I2C_DATA_RECORD asI2CData[1];
+} ATOM_I2C_DEVICE_SETUP_INFO;
+
+/* ========================================================================================== */
+typedef struct _ATOM_ASIC_MVDD_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[1];
+} ATOM_ASIC_MVDD_INFO;
+
+/* ========================================================================================== */
+#define ATOM_MCLK_SS_INFO         ATOM_ASIC_MVDD_INFO
+
+/* ========================================================================================== */
+/**************************************************************************/
+
+typedef struct _ATOM_ASIC_SS_ASSIGNMENT {
+	ULONG ulTargetClockRange;	/* Clock Out frequence (VCO ), in unit of 10Khz */
+	USHORT usSpreadSpectrumPercentage;	/* in unit of 0.01% */
+	USHORT usSpreadRateInKhz;	/* in unit of kHz, modulation freq */
+	UCHAR ucClockIndication;	/* Indicate which clock source needs SS */
+	UCHAR ucSpreadSpectrumMode;	/* Bit1=0 Down Spread,=1 Center Spread. */
+	UCHAR ucReserved[2];
+} ATOM_ASIC_SS_ASSIGNMENT;
+
+/* Define ucSpreadSpectrumType */
+#define ASIC_INTERNAL_MEMORY_SS			1
+#define ASIC_INTERNAL_ENGINE_SS			2
+#define ASIC_INTERNAL_UVD_SS				3
+
+typedef struct _ATOM_ASIC_INTERNAL_SS_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_ASIC_SS_ASSIGNMENT asSpreadSpectrum[4];
+} ATOM_ASIC_INTERNAL_SS_INFO;
+
+/* ==============================Scratch Pad Definition Portion=============================== */
+#define ATOM_DEVICE_CONNECT_INFO_DEF  0
+#define ATOM_ROM_LOCATION_DEF         1
+#define ATOM_TV_STANDARD_DEF          2
+#define ATOM_ACTIVE_INFO_DEF          3
+#define ATOM_LCD_INFO_DEF             4
+#define ATOM_DOS_REQ_INFO_DEF         5
+#define ATOM_ACC_CHANGE_INFO_DEF      6
+#define ATOM_DOS_MODE_INFO_DEF        7
+#define ATOM_I2C_CHANNEL_STATUS_DEF   8
+#define ATOM_I2C_CHANNEL_STATUS1_DEF  9
+
+/*  BIOS_0_SCRATCH Definition */
+#define ATOM_S0_CRT1_MONO               0x00000001L
+#define ATOM_S0_CRT1_COLOR              0x00000002L
+#define ATOM_S0_CRT1_MASK               (ATOM_S0_CRT1_MONO+ATOM_S0_CRT1_COLOR)
+
+#define ATOM_S0_TV1_COMPOSITE_A         0x00000004L
+#define ATOM_S0_TV1_SVIDEO_A            0x00000008L
+#define ATOM_S0_TV1_MASK_A              (ATOM_S0_TV1_COMPOSITE_A+ATOM_S0_TV1_SVIDEO_A)
+
+#define ATOM_S0_CV_A                    0x00000010L
+#define ATOM_S0_CV_DIN_A                0x00000020L
+#define ATOM_S0_CV_MASK_A               (ATOM_S0_CV_A+ATOM_S0_CV_DIN_A)
+
+#define ATOM_S0_CRT2_MONO               0x00000100L
+#define ATOM_S0_CRT2_COLOR              0x00000200L
+#define ATOM_S0_CRT2_MASK               (ATOM_S0_CRT2_MONO+ATOM_S0_CRT2_COLOR)
+
+#define ATOM_S0_TV1_COMPOSITE           0x00000400L
+#define ATOM_S0_TV1_SVIDEO              0x00000800L
+#define ATOM_S0_TV1_SCART               0x00004000L
+#define ATOM_S0_TV1_MASK                (ATOM_S0_TV1_COMPOSITE+ATOM_S0_TV1_SVIDEO+ATOM_S0_TV1_SCART)
+
+#define ATOM_S0_CV                      0x00001000L
+#define ATOM_S0_CV_DIN                  0x00002000L
+#define ATOM_S0_CV_MASK                 (ATOM_S0_CV+ATOM_S0_CV_DIN)
+
+#define ATOM_S0_DFP1                    0x00010000L
+#define ATOM_S0_DFP2                    0x00020000L
+#define ATOM_S0_LCD1                    0x00040000L
+#define ATOM_S0_LCD2                    0x00080000L
+#define ATOM_S0_TV2                     0x00100000L
+#define ATOM_S0_DFP3			0x00200000L
+#define ATOM_S0_DFP4			0x00400000L
+#define ATOM_S0_DFP5			0x00800000L
+
+#define ATOM_S0_DFP_MASK \
+	(ATOM_S0_DFP1 | ATOM_S0_DFP2 | ATOM_S0_DFP3 | ATOM_S0_DFP4 | ATOM_S0_DFP5)
+
+#define ATOM_S0_FAD_REGISTER_BUG        0x02000000L	/*  If set, indicates we are running a PCIE asic with */
+						    /*  the FAD/HDP reg access bug.  Bit is read by DAL */
+
+#define ATOM_S0_THERMAL_STATE_MASK      0x1C000000L
+#define ATOM_S0_THERMAL_STATE_SHIFT     26
+
+#define ATOM_S0_SYSTEM_POWER_STATE_MASK 0xE0000000L
+#define ATOM_S0_SYSTEM_POWER_STATE_SHIFT 29
+
+#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_AC     1
+#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC     2
+#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3
+
+/* Byte aligned defintion for BIOS usage */
+#define ATOM_S0_CRT1_MONOb0             0x01
+#define ATOM_S0_CRT1_COLORb0            0x02
+#define ATOM_S0_CRT1_MASKb0             (ATOM_S0_CRT1_MONOb0+ATOM_S0_CRT1_COLORb0)
+
+#define ATOM_S0_TV1_COMPOSITEb0         0x04
+#define ATOM_S0_TV1_SVIDEOb0            0x08
+#define ATOM_S0_TV1_MASKb0              (ATOM_S0_TV1_COMPOSITEb0+ATOM_S0_TV1_SVIDEOb0)
+
+#define ATOM_S0_CVb0                    0x10
+#define ATOM_S0_CV_DINb0                0x20
+#define ATOM_S0_CV_MASKb0               (ATOM_S0_CVb0+ATOM_S0_CV_DINb0)
+
+#define ATOM_S0_CRT2_MONOb1             0x01
+#define ATOM_S0_CRT2_COLORb1            0x02
+#define ATOM_S0_CRT2_MASKb1             (ATOM_S0_CRT2_MONOb1+ATOM_S0_CRT2_COLORb1)
+
+#define ATOM_S0_TV1_COMPOSITEb1         0x04
+#define ATOM_S0_TV1_SVIDEOb1            0x08
+#define ATOM_S0_TV1_SCARTb1             0x40
+#define ATOM_S0_TV1_MASKb1              (ATOM_S0_TV1_COMPOSITEb1+ATOM_S0_TV1_SVIDEOb1+ATOM_S0_TV1_SCARTb1)
+
+#define ATOM_S0_CVb1                    0x10
+#define ATOM_S0_CV_DINb1                0x20
+#define ATOM_S0_CV_MASKb1               (ATOM_S0_CVb1+ATOM_S0_CV_DINb1)
+
+#define ATOM_S0_DFP1b2                  0x01
+#define ATOM_S0_DFP2b2                  0x02
+#define ATOM_S0_LCD1b2                  0x04
+#define ATOM_S0_LCD2b2                  0x08
+#define ATOM_S0_TV2b2                   0x10
+#define ATOM_S0_DFP3b2									0x20
+
+#define ATOM_S0_THERMAL_STATE_MASKb3    0x1C
+#define ATOM_S0_THERMAL_STATE_SHIFTb3   2
+
+#define ATOM_S0_SYSTEM_POWER_STATE_MASKb3 0xE0
+#define ATOM_S0_LCD1_SHIFT              18
+
+/*  BIOS_1_SCRATCH Definition */
+#define ATOM_S1_ROM_LOCATION_MASK       0x0000FFFFL
+#define ATOM_S1_PCI_BUS_DEV_MASK        0xFFFF0000L
+
+/*       BIOS_2_SCRATCH Definition */
+#define ATOM_S2_TV1_STANDARD_MASK       0x0000000FL
+#define ATOM_S2_CURRENT_BL_LEVEL_MASK   0x0000FF00L
+#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT  8
+
+#define ATOM_S2_CRT1_DPMS_STATE         0x00010000L
+#define ATOM_S2_LCD1_DPMS_STATE	        0x00020000L
+#define ATOM_S2_TV1_DPMS_STATE          0x00040000L
+#define ATOM_S2_DFP1_DPMS_STATE         0x00080000L
+#define ATOM_S2_CRT2_DPMS_STATE         0x00100000L
+#define ATOM_S2_LCD2_DPMS_STATE         0x00200000L
+#define ATOM_S2_TV2_DPMS_STATE          0x00400000L
+#define ATOM_S2_DFP2_DPMS_STATE         0x00800000L
+#define ATOM_S2_CV_DPMS_STATE           0x01000000L
+#define ATOM_S2_DFP3_DPMS_STATE					0x02000000L
+#define ATOM_S2_DFP4_DPMS_STATE					0x04000000L
+#define ATOM_S2_DFP5_DPMS_STATE					0x08000000L
+
+#define ATOM_S2_DFP_DPM_STATE \
+	(ATOM_S2_DFP1_DPMS_STATE | ATOM_S2_DFP2_DPMS_STATE | \
+	 ATOM_S2_DFP3_DPMS_STATE | ATOM_S2_DFP4_DPMS_STATE | \
+	 ATOM_S2_DFP5_DPMS_STATE)
+
+#define ATOM_S2_DEVICE_DPMS_STATE \
+	(ATOM_S2_CRT1_DPMS_STATE + ATOM_S2_LCD1_DPMS_STATE + \
+	 ATOM_S2_TV1_DPMS_STATE + ATOM_S2_DFP_DPMS_STATE + \
+	 ATOM_S2_CRT2_DPMS_STATE + ATOM_S2_LCD2_DPMS_STATE + \
+	 ATOM_S2_TV2_DPMS_STATE + ATOM_S2_CV_DPMS_STATE)
+
+#define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK       0x0C000000L
+#define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK_SHIFT 26
+#define ATOM_S2_FORCEDLOWPWRMODE_STATE_CHANGE     0x10000000L
+
+#define ATOM_S2_VRI_BRIGHT_ENABLE       0x20000000L
+
+#define ATOM_S2_DISPLAY_ROTATION_0_DEGREE     0x0
+#define ATOM_S2_DISPLAY_ROTATION_90_DEGREE    0x1
+#define ATOM_S2_DISPLAY_ROTATION_180_DEGREE   0x2
+#define ATOM_S2_DISPLAY_ROTATION_270_DEGREE   0x3
+#define ATOM_S2_DISPLAY_ROTATION_DEGREE_SHIFT 30
+#define ATOM_S2_DISPLAY_ROTATION_ANGLE_MASK   0xC0000000L
+
+/* Byte aligned defintion for BIOS usage */
+#define ATOM_S2_TV1_STANDARD_MASKb0     0x0F
+#define ATOM_S2_CURRENT_BL_LEVEL_MASKb1 0xFF
+#define ATOM_S2_CRT1_DPMS_STATEb2       0x01
+#define ATOM_S2_LCD1_DPMS_STATEb2       0x02
+#define ATOM_S2_TV1_DPMS_STATEb2        0x04
+#define ATOM_S2_DFP1_DPMS_STATEb2       0x08
+#define ATOM_S2_CRT2_DPMS_STATEb2       0x10
+#define ATOM_S2_LCD2_DPMS_STATEb2       0x20
+#define ATOM_S2_TV2_DPMS_STATEb2        0x40
+#define ATOM_S2_DFP2_DPMS_STATEb2       0x80
+#define ATOM_S2_CV_DPMS_STATEb3         0x01
+#define ATOM_S2_DFP3_DPMS_STATEb3				0x02
+#define ATOM_S2_DFP4_DPMS_STATEb3				0x04
+#define ATOM_S2_DFP5_DPMS_STATEb3				0x08
+
+#define ATOM_S2_DEVICE_DPMS_MASKw1      0x3FF
+#define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASKb3     0x0C
+#define ATOM_S2_FORCEDLOWPWRMODE_STATE_CHANGEb3   0x10
+#define ATOM_S2_VRI_BRIGHT_ENABLEb3     0x20
+#define ATOM_S2_ROTATION_STATE_MASKb3   0xC0
+
+/*  BIOS_3_SCRATCH Definition */
+#define ATOM_S3_CRT1_ACTIVE             0x00000001L
+#define ATOM_S3_LCD1_ACTIVE             0x00000002L
+#define ATOM_S3_TV1_ACTIVE              0x00000004L
+#define ATOM_S3_DFP1_ACTIVE             0x00000008L
+#define ATOM_S3_CRT2_ACTIVE             0x00000010L
+#define ATOM_S3_LCD2_ACTIVE             0x00000020L
+#define ATOM_S3_TV2_ACTIVE              0x00000040L
+#define ATOM_S3_DFP2_ACTIVE             0x00000080L
+#define ATOM_S3_CV_ACTIVE               0x00000100L
+#define ATOM_S3_DFP3_ACTIVE							0x00000200L
+#define ATOM_S3_DFP4_ACTIVE							0x00000400L
+#define ATOM_S3_DFP5_ACTIVE							0x00000800L
+
+#define ATOM_S3_DEVICE_ACTIVE_MASK      0x000003FFL
+
+#define ATOM_S3_LCD_FULLEXPANSION_ACTIVE         0x00001000L
+#define ATOM_S3_LCD_EXPANSION_ASPEC_RATIO_ACTIVE 0x00002000L
+
+#define ATOM_S3_CRT1_CRTC_ACTIVE        0x00010000L
+#define ATOM_S3_LCD1_CRTC_ACTIVE        0x00020000L
+#define ATOM_S3_TV1_CRTC_ACTIVE         0x00040000L
+#define ATOM_S3_DFP1_CRTC_ACTIVE        0x00080000L
+#define ATOM_S3_CRT2_CRTC_ACTIVE        0x00100000L
+#define ATOM_S3_LCD2_CRTC_ACTIVE        0x00200000L
+#define ATOM_S3_TV2_CRTC_ACTIVE         0x00400000L
+#define ATOM_S3_DFP2_CRTC_ACTIVE        0x00800000L
+#define ATOM_S3_CV_CRTC_ACTIVE          0x01000000L
+#define ATOM_S3_DFP3_CRTC_ACTIVE				0x02000000L
+#define ATOM_S3_DFP4_CRTC_ACTIVE				0x04000000L
+#define ATOM_S3_DFP5_CRTC_ACTIVE				0x08000000L
+
+#define ATOM_S3_DEVICE_CRTC_ACTIVE_MASK 0x0FFF0000L
+#define ATOM_S3_ASIC_GUI_ENGINE_HUNG    0x20000000L
+#define ATOM_S3_ALLOW_FAST_PWR_SWITCH   0x40000000L
+#define ATOM_S3_RQST_GPU_USE_MIN_PWR    0x80000000L
+
+/* Byte aligned defintion for BIOS usage */
+#define ATOM_S3_CRT1_ACTIVEb0           0x01
+#define ATOM_S3_LCD1_ACTIVEb0           0x02
+#define ATOM_S3_TV1_ACTIVEb0            0x04
+#define ATOM_S3_DFP1_ACTIVEb0           0x08
+#define ATOM_S3_CRT2_ACTIVEb0           0x10
+#define ATOM_S3_LCD2_ACTIVEb0           0x20
+#define ATOM_S3_TV2_ACTIVEb0            0x40
+#define ATOM_S3_DFP2_ACTIVEb0           0x80
+#define ATOM_S3_CV_ACTIVEb1             0x01
+#define ATOM_S3_DFP3_ACTIVEb1						0x02
+#define ATOM_S3_DFP4_ACTIVEb1						0x04
+#define ATOM_S3_DFP5_ACTIVEb1						0x08
+
+#define ATOM_S3_ACTIVE_CRTC1w0          0xFFF
+
+#define ATOM_S3_CRT1_CRTC_ACTIVEb2      0x01
+#define ATOM_S3_LCD1_CRTC_ACTIVEb2      0x02
+#define ATOM_S3_TV1_CRTC_ACTIVEb2       0x04
+#define ATOM_S3_DFP1_CRTC_ACTIVEb2      0x08
+#define ATOM_S3_CRT2_CRTC_ACTIVEb2      0x10
+#define ATOM_S3_LCD2_CRTC_ACTIVEb2      0x20
+#define ATOM_S3_TV2_CRTC_ACTIVEb2       0x40
+#define ATOM_S3_DFP2_CRTC_ACTIVEb2      0x80
+#define ATOM_S3_CV_CRTC_ACTIVEb3        0x01
+#define ATOM_S3_DFP3_CRTC_ACTIVEb3			0x02
+#define ATOM_S3_DFP4_CRTC_ACTIVEb3			0x04
+#define ATOM_S3_DFP5_CRTC_ACTIVEb3			0x08
+
+#define ATOM_S3_ACTIVE_CRTC2w1          0xFFF
+
+#define ATOM_S3_ASIC_GUI_ENGINE_HUNGb3	0x20
+#define ATOM_S3_ALLOW_FAST_PWR_SWITCHb3 0x40
+#define ATOM_S3_RQST_GPU_USE_MIN_PWRb3  0x80
+
+/*  BIOS_4_SCRATCH Definition */
+#define ATOM_S4_LCD1_PANEL_ID_MASK      0x000000FFL
+#define ATOM_S4_LCD1_REFRESH_MASK       0x0000FF00L
+#define ATOM_S4_LCD1_REFRESH_SHIFT      8
+
+/* Byte aligned defintion for BIOS usage */
+#define ATOM_S4_LCD1_PANEL_ID_MASKb0	  0x0FF
+#define ATOM_S4_LCD1_REFRESH_MASKb1		  ATOM_S4_LCD1_PANEL_ID_MASKb0
+#define ATOM_S4_VRAM_INFO_MASKb2        ATOM_S4_LCD1_PANEL_ID_MASKb0
+
+/*  BIOS_5_SCRATCH Definition, BIOS_5_SCRATCH is used by Firmware only !!!! */
+#define ATOM_S5_DOS_REQ_CRT1b0          0x01
+#define ATOM_S5_DOS_REQ_LCD1b0          0x02
+#define ATOM_S5_DOS_REQ_TV1b0           0x04
+#define ATOM_S5_DOS_REQ_DFP1b0          0x08
+#define ATOM_S5_DOS_REQ_CRT2b0          0x10
+#define ATOM_S5_DOS_REQ_LCD2b0          0x20
+#define ATOM_S5_DOS_REQ_TV2b0           0x40
+#define ATOM_S5_DOS_REQ_DFP2b0          0x80
+#define ATOM_S5_DOS_REQ_CVb1            0x01
+#define ATOM_S5_DOS_REQ_DFP3b1					0x02
+#define ATOM_S5_DOS_REQ_DFP4b1					0x04
+#define ATOM_S5_DOS_REQ_DFP5b1					0x08
+
+#define ATOM_S5_DOS_REQ_DEVICEw0        0x03FF
+
+#define ATOM_S5_DOS_REQ_CRT1            0x0001
+#define ATOM_S5_DOS_REQ_LCD1            0x0002
+#define ATOM_S5_DOS_REQ_TV1             0x0004
+#define ATOM_S5_DOS_REQ_DFP1            0x0008
+#define ATOM_S5_DOS_REQ_CRT2            0x0010
+#define ATOM_S5_DOS_REQ_LCD2            0x0020
+#define ATOM_S5_DOS_REQ_TV2             0x0040
+#define ATOM_S5_DOS_REQ_DFP2            0x0080
+#define ATOM_S5_DOS_REQ_CV              0x0100
+#define ATOM_S5_DOS_REQ_DFP3						0x0200
+#define ATOM_S5_DOS_REQ_DFP4						0x0400
+#define ATOM_S5_DOS_REQ_DFP5						0x0800
+
+#define ATOM_S5_DOS_FORCE_CRT1b2        ATOM_S5_DOS_REQ_CRT1b0
+#define ATOM_S5_DOS_FORCE_TV1b2         ATOM_S5_DOS_REQ_TV1b0
+#define ATOM_S5_DOS_FORCE_CRT2b2        ATOM_S5_DOS_REQ_CRT2b0
+#define ATOM_S5_DOS_FORCE_CVb3          ATOM_S5_DOS_REQ_CVb1
+#define ATOM_S5_DOS_FORCE_DEVICEw1 \
+	(ATOM_S5_DOS_FORCE_CRT1b2 + ATOM_S5_DOS_FORCE_TV1b2 + \
+	 ATOM_S5_DOS_FORCE_CRT2b2 + (ATOM_S5_DOS_FORCE_CVb3 << 8))
+
+/*  BIOS_6_SCRATCH Definition */
+#define ATOM_S6_DEVICE_CHANGE           0x00000001L
+#define ATOM_S6_SCALER_CHANGE           0x00000002L
+#define ATOM_S6_LID_CHANGE              0x00000004L
+#define ATOM_S6_DOCKING_CHANGE          0x00000008L
+#define ATOM_S6_ACC_MODE                0x00000010L
+#define ATOM_S6_EXT_DESKTOP_MODE        0x00000020L
+#define ATOM_S6_LID_STATE               0x00000040L
+#define ATOM_S6_DOCK_STATE              0x00000080L
+#define ATOM_S6_CRITICAL_STATE          0x00000100L
+#define ATOM_S6_HW_I2C_BUSY_STATE       0x00000200L
+#define ATOM_S6_THERMAL_STATE_CHANGE    0x00000400L
+#define ATOM_S6_INTERRUPT_SET_BY_BIOS   0x00000800L
+#define ATOM_S6_REQ_LCD_EXPANSION_FULL         0x00001000L	/* Normal expansion Request bit for LCD */
+#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO  0x00002000L	/* Aspect ratio expansion Request bit for LCD */
+
+#define ATOM_S6_DISPLAY_STATE_CHANGE    0x00004000L	/* This bit is recycled when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_H_expansion */
+#define ATOM_S6_I2C_STATE_CHANGE        0x00008000L	/* This bit is recycled,when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_V_expansion */
+
+#define ATOM_S6_ACC_REQ_CRT1            0x00010000L
+#define ATOM_S6_ACC_REQ_LCD1            0x00020000L
+#define ATOM_S6_ACC_REQ_TV1             0x00040000L
+#define ATOM_S6_ACC_REQ_DFP1            0x00080000L
+#define ATOM_S6_ACC_REQ_CRT2            0x00100000L
+#define ATOM_S6_ACC_REQ_LCD2            0x00200000L
+#define ATOM_S6_ACC_REQ_TV2             0x00400000L
+#define ATOM_S6_ACC_REQ_DFP2            0x00800000L
+#define ATOM_S6_ACC_REQ_CV              0x01000000L
+#define ATOM_S6_ACC_REQ_DFP3						0x02000000L
+#define ATOM_S6_ACC_REQ_DFP4						0x04000000L
+#define ATOM_S6_ACC_REQ_DFP5						0x08000000L
+
+#define ATOM_S6_ACC_REQ_MASK                0x0FFF0000L
+#define ATOM_S6_SYSTEM_POWER_MODE_CHANGE    0x10000000L
+#define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH    0x20000000L
+#define ATOM_S6_VRI_BRIGHTNESS_CHANGE       0x40000000L
+#define ATOM_S6_CONFIG_DISPLAY_CHANGE_MASK  0x80000000L
+
+/* Byte aligned defintion for BIOS usage */
+#define ATOM_S6_DEVICE_CHANGEb0         0x01
+#define ATOM_S6_SCALER_CHANGEb0         0x02
+#define ATOM_S6_LID_CHANGEb0            0x04
+#define ATOM_S6_DOCKING_CHANGEb0        0x08
+#define ATOM_S6_ACC_MODEb0              0x10
+#define ATOM_S6_EXT_DESKTOP_MODEb0      0x20
+#define ATOM_S6_LID_STATEb0             0x40
+#define ATOM_S6_DOCK_STATEb0            0x80
+#define ATOM_S6_CRITICAL_STATEb1        0x01
+#define ATOM_S6_HW_I2C_BUSY_STATEb1     0x02
+#define ATOM_S6_THERMAL_STATE_CHANGEb1  0x04
+#define ATOM_S6_INTERRUPT_SET_BY_BIOSb1 0x08
+#define ATOM_S6_REQ_LCD_EXPANSION_FULLb1        0x10
+#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIOb1 0x20
+
+#define ATOM_S6_ACC_REQ_CRT1b2          0x01
+#define ATOM_S6_ACC_REQ_LCD1b2          0x02
+#define ATOM_S6_ACC_REQ_TV1b2           0x04
+#define ATOM_S6_ACC_REQ_DFP1b2          0x08
+#define ATOM_S6_ACC_REQ_CRT2b2          0x10
+#define ATOM_S6_ACC_REQ_LCD2b2          0x20
+#define ATOM_S6_ACC_REQ_TV2b2           0x40
+#define ATOM_S6_ACC_REQ_DFP2b2          0x80
+#define ATOM_S6_ACC_REQ_CVb3            0x01
+#define ATOM_S6_ACC_REQ_DFP3b3					0x02
+#define ATOM_S6_ACC_REQ_DFP4b3					0x04
+#define ATOM_S6_ACC_REQ_DFP5b3					0x08
+
+#define ATOM_S6_ACC_REQ_DEVICEw1        ATOM_S5_DOS_REQ_DEVICEw0
+#define ATOM_S6_SYSTEM_POWER_MODE_CHANGEb3 0x10
+#define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCHb3 0x20
+#define ATOM_S6_VRI_BRIGHTNESS_CHANGEb3    0x40
+#define ATOM_S6_CONFIG_DISPLAY_CHANGEb3    0x80
+
+#define ATOM_S6_DEVICE_CHANGE_SHIFT             0
+#define ATOM_S6_SCALER_CHANGE_SHIFT             1
+#define ATOM_S6_LID_CHANGE_SHIFT                2
+#define ATOM_S6_DOCKING_CHANGE_SHIFT            3
+#define ATOM_S6_ACC_MODE_SHIFT                  4
+#define ATOM_S6_EXT_DESKTOP_MODE_SHIFT          5
+#define ATOM_S6_LID_STATE_SHIFT                 6
+#define ATOM_S6_DOCK_STATE_SHIFT                7
+#define ATOM_S6_CRITICAL_STATE_SHIFT            8
+#define ATOM_S6_HW_I2C_BUSY_STATE_SHIFT         9
+#define ATOM_S6_THERMAL_STATE_CHANGE_SHIFT      10
+#define ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT     11
+#define ATOM_S6_REQ_SCALER_SHIFT                12
+#define ATOM_S6_REQ_SCALER_ARATIO_SHIFT         13
+#define ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT      14
+#define ATOM_S6_I2C_STATE_CHANGE_SHIFT          15
+#define ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT  28
+#define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH_SHIFT  29
+#define ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT     30
+#define ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT     31
+
+/*  BIOS_7_SCRATCH Definition, BIOS_7_SCRATCH is used by Firmware only !!!! */
+#define ATOM_S7_DOS_MODE_TYPEb0             0x03
+#define ATOM_S7_DOS_MODE_VGAb0              0x00
+#define ATOM_S7_DOS_MODE_VESAb0             0x01
+#define ATOM_S7_DOS_MODE_EXTb0              0x02
+#define ATOM_S7_DOS_MODE_PIXEL_DEPTHb0      0x0C
+#define ATOM_S7_DOS_MODE_PIXEL_FORMATb0     0xF0
+#define ATOM_S7_DOS_8BIT_DAC_ENb1           0x01
+#define ATOM_S7_DOS_MODE_NUMBERw1           0x0FFFF
+
+#define ATOM_S7_DOS_8BIT_DAC_EN_SHIFT       8
+
+/*  BIOS_8_SCRATCH Definition */
+#define ATOM_S8_I2C_CHANNEL_BUSY_MASK       0x00000FFFF
+#define ATOM_S8_I2C_HW_ENGINE_BUSY_MASK     0x0FFFF0000
+
+#define ATOM_S8_I2C_CHANNEL_BUSY_SHIFT      0
+#define ATOM_S8_I2C_ENGINE_BUSY_SHIFT       16
+
+/*  BIOS_9_SCRATCH Definition */
+#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_MASK
+#define ATOM_S9_I2C_CHANNEL_COMPLETED_MASK  0x0000FFFF
+#endif
+#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_MASK
+#define ATOM_S9_I2C_CHANNEL_ABORTED_MASK    0xFFFF0000
+#endif
+#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT
+#define ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT 0
+#endif
+#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT
+#define ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT   16
+#endif
+
+#define ATOM_FLAG_SET                         0x20
+#define ATOM_FLAG_CLEAR                       0
+#define CLEAR_ATOM_S6_ACC_MODE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_ACC_MODE_SHIFT | ATOM_FLAG_CLEAR)
+#define SET_ATOM_S6_DEVICE_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_DEVICE_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_VRI_BRIGHTNESS_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_SCALER_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_SCALER_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_LID_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_LID_CHANGE_SHIFT | ATOM_FLAG_SET)
+
+#define SET_ATOM_S6_LID_STATE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) |\
+	 ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_LID_STATE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_CLEAR)
+
+#define SET_ATOM_S6_DOCK_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8)| \
+	 ATOM_S6_DOCKING_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_DOCK_STATE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_DOCK_STATE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_CLEAR)
+
+#define SET_ATOM_S6_THERMAL_STATE_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_THERMAL_STATE_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_SYSTEM_POWER_MODE_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_INTERRUPT_SET_BY_BIOS \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT | ATOM_FLAG_SET)
+
+#define SET_ATOM_S6_CRITICAL_STATE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_CRITICAL_STATE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_CLEAR)
+
+#define SET_ATOM_S6_REQ_SCALER \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_REQ_SCALER \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_CLEAR )
+
+#define SET_ATOM_S6_REQ_SCALER_ARATIO \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_SET )
+#define CLEAR_ATOM_S6_REQ_SCALER_ARATIO \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_CLEAR )
+
+#define SET_ATOM_S6_I2C_STATE_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_I2C_STATE_CHANGE_SHIFT | ATOM_FLAG_SET )
+
+#define SET_ATOM_S6_DISPLAY_STATE_CHANGE \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT | ATOM_FLAG_SET )
+
+#define SET_ATOM_S6_DEVICE_RECONFIG \
+	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
+	 ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S0_LCD1 \
+	((ATOM_DEVICE_CONNECT_INFO_DEF << 8 ) | \
+	 ATOM_S0_LCD1_SHIFT | ATOM_FLAG_CLEAR )
+#define SET_ATOM_S7_DOS_8BIT_DAC_EN \
+	((ATOM_DOS_MODE_INFO_DEF << 8) | \
+	 ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_SET )
+#define CLEAR_ATOM_S7_DOS_8BIT_DAC_EN \
+	((ATOM_DOS_MODE_INFO_DEF << 8) | \
+	 ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_CLEAR )
+
+/****************************************************************************/
+/* Portion II: Definitinos only used in Driver */
+/****************************************************************************/
+
+/*  Macros used by driver */
+
+#define	GetIndexIntoMasterTable(MasterOrData, FieldName) (((char *)(&((ATOM_MASTER_LIST_OF_##MasterOrData##_TABLES *)0)->FieldName)-(char *)0)/sizeof(USHORT))
+
+#define GET_COMMAND_TABLE_COMMANDSET_REVISION(TABLE_HEADER_OFFSET) ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableFormatRevision)&0x3F)
+#define GET_COMMAND_TABLE_PARAMETER_REVISION(TABLE_HEADER_OFFSET)  ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableContentRevision)&0x3F)
+
+#define GET_DATA_TABLE_MAJOR_REVISION GET_COMMAND_TABLE_COMMANDSET_REVISION
+#define GET_DATA_TABLE_MINOR_REVISION GET_COMMAND_TABLE_PARAMETER_REVISION
+
+/****************************************************************************/
+/* Portion III: Definitinos only used in VBIOS */
+/****************************************************************************/
+#define ATOM_DAC_SRC					0x80
+#define ATOM_SRC_DAC1					0
+#define ATOM_SRC_DAC2					0x80
+
+#ifdef	UEFI_BUILD
+#define	USHORT	UTEMP
+#endif
+
+typedef struct _MEMORY_PLLINIT_PARAMETERS {
+	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
+	UCHAR ucAction;		/* not define yet */
+	UCHAR ucFbDiv_Hi;	/* Fbdiv Hi byte */
+	UCHAR ucFbDiv;		/* FB value */
+	UCHAR ucPostDiv;	/* Post div */
+} MEMORY_PLLINIT_PARAMETERS;
+
+#define MEMORY_PLLINIT_PS_ALLOCATION  MEMORY_PLLINIT_PARAMETERS
+
+#define	GPIO_PIN_WRITE													0x01
+#define	GPIO_PIN_READ														0x00
+
+typedef struct _GPIO_PIN_CONTROL_PARAMETERS {
+	UCHAR ucGPIO_ID;	/* return value, read from GPIO pins */
+	UCHAR ucGPIOBitShift;	/* define which bit in uGPIOBitVal need to be update */
+	UCHAR ucGPIOBitVal;	/* Set/Reset corresponding bit defined in ucGPIOBitMask */
+	UCHAR ucAction;		/* =GPIO_PIN_WRITE: Read; =GPIO_PIN_READ: Write */
+} GPIO_PIN_CONTROL_PARAMETERS;
+
+typedef struct _ENABLE_SCALER_PARAMETERS {
+	UCHAR ucScaler;		/*  ATOM_SCALER1, ATOM_SCALER2 */
+	UCHAR ucEnable;		/*  ATOM_SCALER_DISABLE or ATOM_SCALER_CENTER or ATOM_SCALER_EXPANSION */
+	UCHAR ucTVStandard;	/*  */
+	UCHAR ucPadding[1];
+} ENABLE_SCALER_PARAMETERS;
+#define ENABLE_SCALER_PS_ALLOCATION ENABLE_SCALER_PARAMETERS
+
+/* ucEnable: */
+#define SCALER_BYPASS_AUTO_CENTER_NO_REPLICATION    0
+#define SCALER_BYPASS_AUTO_CENTER_AUTO_REPLICATION  1
+#define SCALER_ENABLE_2TAP_ALPHA_MODE               2
+#define SCALER_ENABLE_MULTITAP_MODE                 3
+
+typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS {
+	ULONG usHWIconHorzVertPosn;	/*  Hardware Icon Vertical position */
+	UCHAR ucHWIconVertOffset;	/*  Hardware Icon Vertical offset */
+	UCHAR ucHWIconHorzOffset;	/*  Hardware Icon Horizontal offset */
+	UCHAR ucSelection;	/*  ATOM_CURSOR1 or ATOM_ICON1 or ATOM_CURSOR2 or ATOM_ICON2 */
+	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
+} ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS;
+
+typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION {
+	ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS sEnableIcon;
+	ENABLE_CRTC_PARAMETERS sReserved;
+} ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION;
+
+typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS {
+	USHORT usHight;		/*  Image Hight */
+	USHORT usWidth;		/*  Image Width */
+	UCHAR ucSurface;	/*  Surface 1 or 2 */
+	UCHAR ucPadding[3];
+} ENABLE_GRAPH_SURFACE_PARAMETERS;
+
+typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2 {
+	USHORT usHight;		/*  Image Hight */
+	USHORT usWidth;		/*  Image Width */
+	UCHAR ucSurface;	/*  Surface 1 or 2 */
+	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
+	UCHAR ucPadding[2];
+} ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2;
+
+typedef struct _ENABLE_GRAPH_SURFACE_PS_ALLOCATION {
+	ENABLE_GRAPH_SURFACE_PARAMETERS sSetSurface;
+	ENABLE_YUV_PS_ALLOCATION sReserved;	/*  Don't set this one */
+} ENABLE_GRAPH_SURFACE_PS_ALLOCATION;
+
+typedef struct _MEMORY_CLEAN_UP_PARAMETERS {
+	USHORT usMemoryStart;	/* in 8Kb boundry, offset from memory base address */
+	USHORT usMemorySize;	/* 8Kb blocks aligned */
+} MEMORY_CLEAN_UP_PARAMETERS;
+#define MEMORY_CLEAN_UP_PS_ALLOCATION MEMORY_CLEAN_UP_PARAMETERS
+
+typedef struct _GET_DISPLAY_SURFACE_SIZE_PARAMETERS {
+	USHORT usX_Size;	/* When use as input parameter, usX_Size indicates which CRTC */
+	USHORT usY_Size;
+} GET_DISPLAY_SURFACE_SIZE_PARAMETERS;
+
+typedef struct _INDIRECT_IO_ACCESS {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR IOAccessSequence[256];
+} INDIRECT_IO_ACCESS;
+
+#define INDIRECT_READ              0x00
+#define INDIRECT_WRITE             0x80
+
+#define INDIRECT_IO_MM             0
+#define INDIRECT_IO_PLL            1
+#define INDIRECT_IO_MC             2
+#define INDIRECT_IO_PCIE           3
+#define INDIRECT_IO_PCIEP          4
+#define INDIRECT_IO_NBMISC         5
+
+#define INDIRECT_IO_PLL_READ       INDIRECT_IO_PLL   | INDIRECT_READ
+#define INDIRECT_IO_PLL_WRITE      INDIRECT_IO_PLL   | INDIRECT_WRITE
+#define INDIRECT_IO_MC_READ        INDIRECT_IO_MC    | INDIRECT_READ
+#define INDIRECT_IO_MC_WRITE       INDIRECT_IO_MC    | INDIRECT_WRITE
+#define INDIRECT_IO_PCIE_READ      INDIRECT_IO_PCIE  | INDIRECT_READ
+#define INDIRECT_IO_PCIE_WRITE     INDIRECT_IO_PCIE  | INDIRECT_WRITE
+#define INDIRECT_IO_PCIEP_READ     INDIRECT_IO_PCIEP | INDIRECT_READ
+#define INDIRECT_IO_PCIEP_WRITE    INDIRECT_IO_PCIEP | INDIRECT_WRITE
+#define INDIRECT_IO_NBMISC_READ    INDIRECT_IO_NBMISC | INDIRECT_READ
+#define INDIRECT_IO_NBMISC_WRITE   INDIRECT_IO_NBMISC | INDIRECT_WRITE
+
+typedef struct _ATOM_OEM_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
+} ATOM_OEM_INFO;
+
+typedef struct _ATOM_TV_MODE {
+	UCHAR ucVMode_Num;	/* Video mode number */
+	UCHAR ucTV_Mode_Num;	/* Internal TV mode number */
+} ATOM_TV_MODE;
+
+typedef struct _ATOM_BIOS_INT_TVSTD_MODE {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usTV_Mode_LUT_Offset;	/*  Pointer to standard to internal number conversion table */
+	USHORT usTV_FIFO_Offset;	/*  Pointer to FIFO entry table */
+	USHORT usNTSC_Tbl_Offset;	/*  Pointer to SDTV_Mode_NTSC table */
+	USHORT usPAL_Tbl_Offset;	/*  Pointer to SDTV_Mode_PAL table */
+	USHORT usCV_Tbl_Offset;	/*  Pointer to SDTV_Mode_PAL table */
+} ATOM_BIOS_INT_TVSTD_MODE;
+
+typedef struct _ATOM_TV_MODE_SCALER_PTR {
+	USHORT ucFilter0_Offset;	/* Pointer to filter format 0 coefficients */
+	USHORT usFilter1_Offset;	/* Pointer to filter format 0 coefficients */
+	UCHAR ucTV_Mode_Num;
+} ATOM_TV_MODE_SCALER_PTR;
+
+typedef struct _ATOM_STANDARD_VESA_TIMING {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_DTD_FORMAT aModeTimings[16];	/*  16 is not the real array number, just for initial allocation */
+} ATOM_STANDARD_VESA_TIMING;
+
+typedef struct _ATOM_STD_FORMAT {
+	USHORT usSTD_HDisp;
+	USHORT usSTD_VDisp;
+	USHORT usSTD_RefreshRate;
+	USHORT usReserved;
+} ATOM_STD_FORMAT;
+
+typedef struct _ATOM_VESA_TO_EXTENDED_MODE {
+	USHORT usVESA_ModeNumber;
+	USHORT usExtendedModeNumber;
+} ATOM_VESA_TO_EXTENDED_MODE;
+
+typedef struct _ATOM_VESA_TO_INTENAL_MODE_LUT {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	ATOM_VESA_TO_EXTENDED_MODE asVESA_ToExtendedModeInfo[76];
+} ATOM_VESA_TO_INTENAL_MODE_LUT;
+
+/*************** ATOM Memory Related Data Structure ***********************/
+typedef struct _ATOM_MEMORY_VENDOR_BLOCK {
+	UCHAR ucMemoryType;
+	UCHAR ucMemoryVendor;
+	UCHAR ucAdjMCId;
+	UCHAR ucDynClkId;
+	ULONG ulDllResetClkRange;
+} ATOM_MEMORY_VENDOR_BLOCK;
+
+typedef struct _ATOM_MEMORY_SETTING_ID_CONFIG {
+#if ATOM_BIG_ENDIAN
+	ULONG ucMemBlkId:8;
+	ULONG ulMemClockRange:24;
+#else
+	ULONG ulMemClockRange:24;
+	ULONG ucMemBlkId:8;
+#endif
+} ATOM_MEMORY_SETTING_ID_CONFIG;
+
+typedef union _ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS {
+	ATOM_MEMORY_SETTING_ID_CONFIG slAccess;
+	ULONG ulAccess;
+} ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS;
+
+typedef struct _ATOM_MEMORY_SETTING_DATA_BLOCK {
+	ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS ulMemoryID;
+	ULONG aulMemData[1];
+} ATOM_MEMORY_SETTING_DATA_BLOCK;
+
+typedef struct _ATOM_INIT_REG_INDEX_FORMAT {
+	USHORT usRegIndex;	/*  MC register index */
+	UCHAR ucPreRegDataLength;	/*  offset in ATOM_INIT_REG_DATA_BLOCK.saRegDataBuf */
+} ATOM_INIT_REG_INDEX_FORMAT;
+
+typedef struct _ATOM_INIT_REG_BLOCK {
+	USHORT usRegIndexTblSize;	/* size of asRegIndexBuf */
+	USHORT usRegDataBlkSize;	/* size of ATOM_MEMORY_SETTING_DATA_BLOCK */
+	ATOM_INIT_REG_INDEX_FORMAT asRegIndexBuf[1];
+	ATOM_MEMORY_SETTING_DATA_BLOCK asRegDataBuf[1];
+} ATOM_INIT_REG_BLOCK;
+
+#define END_OF_REG_INDEX_BLOCK  0x0ffff
+#define END_OF_REG_DATA_BLOCK   0x00000000
+#define ATOM_INIT_REG_MASK_FLAG 0x80
+#define	CLOCK_RANGE_HIGHEST			0x00ffffff
+
+#define VALUE_DWORD             SIZEOF ULONG
+#define VALUE_SAME_AS_ABOVE     0
+#define VALUE_MASK_DWORD        0x84
+
+#define INDEX_ACCESS_RANGE_BEGIN	    (VALUE_DWORD + 1)
+#define INDEX_ACCESS_RANGE_END		    (INDEX_ACCESS_RANGE_BEGIN + 1)
+#define VALUE_INDEX_ACCESS_SINGLE	    (INDEX_ACCESS_RANGE_END + 1)
+
+typedef struct _ATOM_MC_INIT_PARAM_TABLE {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usAdjustARB_SEQDataOffset;
+	USHORT usMCInitMemTypeTblOffset;
+	USHORT usMCInitCommonTblOffset;
+	USHORT usMCInitPowerDownTblOffset;
+	ULONG ulARB_SEQDataBuf[32];
+	ATOM_INIT_REG_BLOCK asMCInitMemType;
+	ATOM_INIT_REG_BLOCK asMCInitCommon;
+} ATOM_MC_INIT_PARAM_TABLE;
+
+#define _4Mx16              0x2
+#define _4Mx32              0x3
+#define _8Mx16              0x12
+#define _8Mx32              0x13
+#define _16Mx16             0x22
+#define _16Mx32             0x23
+#define _32Mx16             0x32
+#define _32Mx32             0x33
+#define _64Mx8              0x41
+#define _64Mx16             0x42
+
+#define SAMSUNG             0x1
+#define INFINEON            0x2
+#define ELPIDA              0x3
+#define ETRON               0x4
+#define NANYA               0x5
+#define HYNIX               0x6
+#define MOSEL               0x7
+#define WINBOND             0x8
+#define ESMT                0x9
+#define MICRON              0xF
+
+#define QIMONDA             INFINEON
+#define PROMOS              MOSEL
+
+/* ///////////Support for GDDR5 MC uCode to reside in upper 64K of ROM///////////// */
+
+#define UCODE_ROM_START_ADDRESS		0x1c000
+#define	UCODE_SIGNATURE			0x4375434d	/*  'MCuC' - MC uCode */
+
+/* uCode block header for reference */
+
+typedef struct _MCuCodeHeader {
+	ULONG ulSignature;
+	UCHAR ucRevision;
+	UCHAR ucChecksum;
+	UCHAR ucReserved1;
+	UCHAR ucReserved2;
+	USHORT usParametersLength;
+	USHORT usUCodeLength;
+	USHORT usReserved1;
+	USHORT usReserved2;
+} MCuCodeHeader;
+
+/* //////////////////////////////////////////////////////////////////////////////// */
+
+#define ATOM_MAX_NUMBER_OF_VRAM_MODULE	16
+
+#define ATOM_VRAM_MODULE_MEMORY_VENDOR_ID_MASK	0xF
+typedef struct _ATOM_VRAM_MODULE_V1 {
+	ULONG ulReserved;
+	USHORT usEMRSValue;
+	USHORT usMRSValue;
+	USHORT usReserved;
+	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
+	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] reserved; */
+	UCHAR ucMemoryVenderID;	/*  Predefined,never change across designs or memory type/vender */
+	UCHAR ucMemoryDeviceCfg;	/*  [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... */
+	UCHAR ucRow;		/*  Number of Row,in power of 2; */
+	UCHAR ucColumn;		/*  Number of Column,in power of 2; */
+	UCHAR ucBank;		/*  Nunber of Bank; */
+	UCHAR ucRank;		/*  Number of Rank, in power of 2 */
+	UCHAR ucChannelNum;	/*  Number of channel; */
+	UCHAR ucChannelConfig;	/*  [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 */
+	UCHAR ucDefaultMVDDQ_ID;	/*  Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; */
+	UCHAR ucDefaultMVDDC_ID;	/*  Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; */
+	UCHAR ucReserved[2];
+} ATOM_VRAM_MODULE_V1;
+
+typedef struct _ATOM_VRAM_MODULE_V2 {
+	ULONG ulReserved;
+	ULONG ulFlags;		/*  To enable/disable functionalities based on memory type */
+	ULONG ulEngineClock;	/*  Override of default engine clock for particular memory type */
+	ULONG ulMemoryClock;	/*  Override of default memory clock for particular memory type */
+	USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
+	USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
+	USHORT usEMRSValue;
+	USHORT usMRSValue;
+	USHORT usReserved;
+	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
+	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; */
+	UCHAR ucMemoryVenderID;	/*  Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed */
+	UCHAR ucMemoryDeviceCfg;	/*  [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... */
+	UCHAR ucRow;		/*  Number of Row,in power of 2; */
+	UCHAR ucColumn;		/*  Number of Column,in power of 2; */
+	UCHAR ucBank;		/*  Nunber of Bank; */
+	UCHAR ucRank;		/*  Number of Rank, in power of 2 */
+	UCHAR ucChannelNum;	/*  Number of channel; */
+	UCHAR ucChannelConfig;	/*  [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 */
+	UCHAR ucDefaultMVDDQ_ID;	/*  Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; */
+	UCHAR ucDefaultMVDDC_ID;	/*  Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; */
+	UCHAR ucRefreshRateFactor;
+	UCHAR ucReserved[3];
+} ATOM_VRAM_MODULE_V2;
+
+typedef struct _ATOM_MEMORY_TIMING_FORMAT {
+	ULONG ulClkRange;	/*  memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing */
+	union {
+		USHORT usMRS;	/*  mode register */
+		USHORT usDDR3_MR0;
+	};
+	union {
+		USHORT usEMRS;	/*  extended mode register */
+		USHORT usDDR3_MR1;
+	};
+	UCHAR ucCL;		/*  CAS latency */
+	UCHAR ucWL;		/*  WRITE Latency */
+	UCHAR uctRAS;		/*  tRAS */
+	UCHAR uctRC;		/*  tRC */
+	UCHAR uctRFC;		/*  tRFC */
+	UCHAR uctRCDR;		/*  tRCDR */
+	UCHAR uctRCDW;		/*  tRCDW */
+	UCHAR uctRP;		/*  tRP */
+	UCHAR uctRRD;		/*  tRRD */
+	UCHAR uctWR;		/*  tWR */
+	UCHAR uctWTR;		/*  tWTR */
+	UCHAR uctPDIX;		/*  tPDIX */
+	UCHAR uctFAW;		/*  tFAW */
+	UCHAR uctAOND;		/*  tAOND */
+	union {
+		struct {
+			UCHAR ucflag;	/*  flag to control memory timing calculation. bit0= control EMRS2 Infineon */
+			UCHAR ucReserved;
+		};
+		USHORT usDDR3_MR2;
+	};
+} ATOM_MEMORY_TIMING_FORMAT;
+
+typedef struct _ATOM_MEMORY_TIMING_FORMAT_V1 {
+	ULONG ulClkRange;	/*  memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing */
+	USHORT usMRS;		/*  mode register */
+	USHORT usEMRS;		/*  extended mode register */
+	UCHAR ucCL;		/*  CAS latency */
+	UCHAR ucWL;		/*  WRITE Latency */
+	UCHAR uctRAS;		/*  tRAS */
+	UCHAR uctRC;		/*  tRC */
+	UCHAR uctRFC;		/*  tRFC */
+	UCHAR uctRCDR;		/*  tRCDR */
+	UCHAR uctRCDW;		/*  tRCDW */
+	UCHAR uctRP;		/*  tRP */
+	UCHAR uctRRD;		/*  tRRD */
+	UCHAR uctWR;		/*  tWR */
+	UCHAR uctWTR;		/*  tWTR */
+	UCHAR uctPDIX;		/*  tPDIX */
+	UCHAR uctFAW;		/*  tFAW */
+	UCHAR uctAOND;		/*  tAOND */
+	UCHAR ucflag;		/*  flag to control memory timing calculation. bit0= control EMRS2 Infineon */
+/* ///////////////////////GDDR parameters/////////////////////////////////// */
+	UCHAR uctCCDL;		/*  */
+	UCHAR uctCRCRL;		/*  */
+	UCHAR uctCRCWL;		/*  */
+	UCHAR uctCKE;		/*  */
+	UCHAR uctCKRSE;		/*  */
+	UCHAR uctCKRSX;		/*  */
+	UCHAR uctFAW32;		/*  */
+	UCHAR ucReserved1;	/*  */
+	UCHAR ucReserved2;	/*  */
+	UCHAR ucTerminator;
+} ATOM_MEMORY_TIMING_FORMAT_V1;
+
+typedef struct _ATOM_MEMORY_FORMAT {
+	ULONG ulDllDisClock;	/*  memory DLL will be disable when target memory clock is below this clock */
+	union {
+		USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
+		USHORT usDDR3_Reserved;	/*  Not used for DDR3 memory */
+	};
+	union {
+		USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
+		USHORT usDDR3_MR3;	/*  Used for DDR3 memory */
+	};
+	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; */
+	UCHAR ucMemoryVenderID;	/*  Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed */
+	UCHAR ucRow;		/*  Number of Row,in power of 2; */
+	UCHAR ucColumn;		/*  Number of Column,in power of 2; */
+	UCHAR ucBank;		/*  Nunber of Bank; */
+	UCHAR ucRank;		/*  Number of Rank, in power of 2 */
+	UCHAR ucBurstSize;	/*  burst size, 0= burst size=4  1= burst size=8 */
+	UCHAR ucDllDisBit;	/*  position of DLL Enable/Disable bit in EMRS ( Extended Mode Register ) */
+	UCHAR ucRefreshRateFactor;	/*  memory refresh rate in unit of ms */
+	UCHAR ucDensity;	/*  _8Mx32, _16Mx32, _16Mx16, _32Mx16 */
+	UCHAR ucPreamble;	/* [7:4] Write Preamble, [3:0] Read Preamble */
+	UCHAR ucMemAttrib;	/*  Memory Device Addribute, like RDBI/WDBI etc */
+	ATOM_MEMORY_TIMING_FORMAT asMemTiming[5];	/* Memory Timing block sort from lower clock to higher clock */
+} ATOM_MEMORY_FORMAT;
+
+typedef struct _ATOM_VRAM_MODULE_V3 {
+	ULONG ulChannelMapCfg;	/*  board dependent paramenter:Channel combination */
+	USHORT usSize;		/*  size of ATOM_VRAM_MODULE_V3 */
+	USHORT usDefaultMVDDQ;	/*  board dependent parameter:Default Memory Core Voltage */
+	USHORT usDefaultMVDDC;	/*  board dependent parameter:Default Memory IO Voltage */
+	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
+	UCHAR ucChannelNum;	/*  board dependent parameter:Number of channel; */
+	UCHAR ucChannelSize;	/*  board dependent parameter:32bit or 64bit */
+	UCHAR ucVREFI;		/*  board dependnt parameter: EXT or INT +160mv to -140mv */
+	UCHAR ucNPL_RT;		/*  board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */
+	UCHAR ucFlag;		/*  To enable/disable functionalities based on memory type */
+	ATOM_MEMORY_FORMAT asMemory;	/*  describ all of video memory parameters from memory spec */
+} ATOM_VRAM_MODULE_V3;
+
+/* ATOM_VRAM_MODULE_V3.ucNPL_RT */
+#define NPL_RT_MASK															0x0f
+#define BATTERY_ODT_MASK												0xc0
+
+#define ATOM_VRAM_MODULE		 ATOM_VRAM_MODULE_V3
+
+typedef struct _ATOM_VRAM_MODULE_V4 {
+	ULONG ulChannelMapCfg;	/*  board dependent parameter: Channel combination */
+	USHORT usModuleSize;	/*  size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE */
+	USHORT usPrivateReserved;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
+	/*  MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) */
+	USHORT usReserved;
+	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
+	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; */
+	UCHAR ucChannelNum;	/*  Number of channels present in this module config */
+	UCHAR ucChannelWidth;	/*  0 - 32 bits; 1 - 64 bits */
+	UCHAR ucDensity;	/*  _8Mx32, _16Mx32, _16Mx16, _32Mx16 */
+	UCHAR ucFlag;		/*  To enable/disable functionalities based on memory type */
+	UCHAR ucMisc;		/*  bit0: 0 - single rank; 1 - dual rank;   bit2: 0 - burstlength 4, 1 - burstlength 8 */
+	UCHAR ucVREFI;		/*  board dependent parameter */
+	UCHAR ucNPL_RT;		/*  board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */
+	UCHAR ucPreamble;	/*  [7:4] Write Preamble, [3:0] Read Preamble */
+	UCHAR ucMemorySize;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
+	/*  Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros */
+	UCHAR ucReserved[3];
+
+/* compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level */
+	union {
+		USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
+		USHORT usDDR3_Reserved;
+	};
+	union {
+		USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
+		USHORT usDDR3_MR3;	/*  Used for DDR3 memory */
+	};
+	UCHAR ucMemoryVenderID;	/*  Predefined, If not predefined, vendor detection table gets executed */
+	UCHAR ucRefreshRateFactor;	/*  [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) */
+	UCHAR ucReserved2[2];
+	ATOM_MEMORY_TIMING_FORMAT asMemTiming[5];	/* Memory Timing block sort from lower clock to higher clock */
+} ATOM_VRAM_MODULE_V4;
+
+#define VRAM_MODULE_V4_MISC_RANK_MASK       0x3
+#define VRAM_MODULE_V4_MISC_DUAL_RANK       0x1
+#define VRAM_MODULE_V4_MISC_BL_MASK         0x4
+#define VRAM_MODULE_V4_MISC_BL8             0x4
+#define VRAM_MODULE_V4_MISC_DUAL_CS         0x10
+
+typedef struct _ATOM_VRAM_MODULE_V5 {
+	ULONG ulChannelMapCfg;	/*  board dependent parameter: Channel combination */
+	USHORT usModuleSize;	/*  size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE */
+	USHORT usPrivateReserved;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
+	/*  MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) */
+	USHORT usReserved;
+	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
+	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; */
+	UCHAR ucChannelNum;	/*  Number of channels present in this module config */
+	UCHAR ucChannelWidth;	/*  0 - 32 bits; 1 - 64 bits */
+	UCHAR ucDensity;	/*  _8Mx32, _16Mx32, _16Mx16, _32Mx16 */
+	UCHAR ucFlag;		/*  To enable/disable functionalities based on memory type */
+	UCHAR ucMisc;		/*  bit0: 0 - single rank; 1 - dual rank;   bit2: 0 - burstlength 4, 1 - burstlength 8 */
+	UCHAR ucVREFI;		/*  board dependent parameter */
+	UCHAR ucNPL_RT;		/*  board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */
+	UCHAR ucPreamble;	/*  [7:4] Write Preamble, [3:0] Read Preamble */
+	UCHAR ucMemorySize;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
+	/*  Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros */
+	UCHAR ucReserved[3];
+
+/* compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level */
+	USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
+	USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
+	UCHAR ucMemoryVenderID;	/*  Predefined, If not predefined, vendor detection table gets executed */
+	UCHAR ucRefreshRateFactor;	/*  [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) */
+	UCHAR ucFIFODepth;	/*  FIFO depth supposes to be detected during vendor detection, but if we dont do vendor detection we have to hardcode FIFO Depth */
+	UCHAR ucCDR_Bandwidth;	/*  [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth */
+	ATOM_MEMORY_TIMING_FORMAT_V1 asMemTiming[5];	/* Memory Timing block sort from lower clock to higher clock */
+} ATOM_VRAM_MODULE_V5;
+
+typedef struct _ATOM_VRAM_INFO_V2 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR ucNumOfVRAMModule;
+	ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];	/*  just for allocation, real number of blocks is in ucNumOfVRAMModule; */
+} ATOM_VRAM_INFO_V2;
+
+typedef struct _ATOM_VRAM_INFO_V3 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usMemAdjustTblOffset;	/*  offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting */
+	USHORT usMemClkPatchTblOffset;	/*      offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting */
+	USHORT usRerseved;
+	UCHAR aVID_PinsShift[9];	/*  8 bit strap maximum+terminator */
+	UCHAR ucNumOfVRAMModule;
+	ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];	/*  just for allocation, real number of blocks is in ucNumOfVRAMModule; */
+	ATOM_INIT_REG_BLOCK asMemPatch;	/*  for allocation */
+	/*      ATOM_INIT_REG_BLOCK                              aMemAdjust; */
+} ATOM_VRAM_INFO_V3;
+
+#define	ATOM_VRAM_INFO_LAST	     ATOM_VRAM_INFO_V3
+
+typedef struct _ATOM_VRAM_INFO_V4 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usMemAdjustTblOffset;	/*  offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting */
+	USHORT usMemClkPatchTblOffset;	/*      offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting */
+	USHORT usRerseved;
+	UCHAR ucMemDQ7_0ByteRemap;	/*  DQ line byte remap, =0: Memory Data line BYTE0, =1: BYTE1, =2: BYTE2, =3: BYTE3 */
+	ULONG ulMemDQ7_0BitRemap;	/*  each DQ line ( 7~0) use 3bits, like: DQ0=Bit[2:0], DQ1:[5:3], ... DQ7:[23:21] */
+	UCHAR ucReservde[4];
+	UCHAR ucNumOfVRAMModule;
+	ATOM_VRAM_MODULE_V4 aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];	/*  just for allocation, real number of blocks is in ucNumOfVRAMModule; */
+	ATOM_INIT_REG_BLOCK asMemPatch;	/*  for allocation */
+	/*      ATOM_INIT_REG_BLOCK                              aMemAdjust; */
+} ATOM_VRAM_INFO_V4;
+
+typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR aVID_PinsShift[9];	/* 8 bit strap maximum+terminator */
+} ATOM_VRAM_GPIO_DETECTION_INFO;
+
+typedef struct _ATOM_MEMORY_TRAINING_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR ucTrainingLoop;
+	UCHAR ucReserved[3];
+	ATOM_INIT_REG_BLOCK asMemTrainingSetting;
+} ATOM_MEMORY_TRAINING_INFO;
+
+typedef struct SW_I2C_CNTL_DATA_PARAMETERS {
+	UCHAR ucControl;
+	UCHAR ucData;
+	UCHAR ucSatus;
+	UCHAR ucTemp;
+} SW_I2C_CNTL_DATA_PARAMETERS;
+
+#define SW_I2C_CNTL_DATA_PS_ALLOCATION  SW_I2C_CNTL_DATA_PARAMETERS
+
+typedef struct _SW_I2C_IO_DATA_PARAMETERS {
+	USHORT GPIO_Info;
+	UCHAR ucAct;
+	UCHAR ucData;
+} SW_I2C_IO_DATA_PARAMETERS;
+
+#define SW_I2C_IO_DATA_PS_ALLOCATION  SW_I2C_IO_DATA_PARAMETERS
+
+/****************************SW I2C CNTL DEFINITIONS**********************/
+#define SW_I2C_IO_RESET       0
+#define SW_I2C_IO_GET         1
+#define SW_I2C_IO_DRIVE       2
+#define SW_I2C_IO_SET         3
+#define SW_I2C_IO_START       4
+
+#define SW_I2C_IO_CLOCK       0
+#define SW_I2C_IO_DATA        0x80
+
+#define SW_I2C_IO_ZERO        0
+#define SW_I2C_IO_ONE         0x100
+
+#define SW_I2C_CNTL_READ      0
+#define SW_I2C_CNTL_WRITE     1
+#define SW_I2C_CNTL_START     2
+#define SW_I2C_CNTL_STOP      3
+#define SW_I2C_CNTL_OPEN      4
+#define SW_I2C_CNTL_CLOSE     5
+#define SW_I2C_CNTL_WRITE1BIT 6
+
+/* ==============================VESA definition Portion=============================== */
+#define VESA_OEM_PRODUCT_REV			            '01.00'
+#define VESA_MODE_ATTRIBUTE_MODE_SUPPORT	     0xBB	/* refer to VBE spec p.32, no TTY support */
+#define VESA_MODE_WIN_ATTRIBUTE						     7
+#define VESA_WIN_SIZE											     64
+
+typedef struct _PTR_32_BIT_STRUCTURE {
+	USHORT Offset16;
+	USHORT Segment16;
+} PTR_32_BIT_STRUCTURE;
+
+typedef union _PTR_32_BIT_UNION {
+	PTR_32_BIT_STRUCTURE SegmentOffset;
+	ULONG Ptr32_Bit;
+} PTR_32_BIT_UNION;
+
+typedef struct _VBE_1_2_INFO_BLOCK_UPDATABLE {
+	UCHAR VbeSignature[4];
+	USHORT VbeVersion;
+	PTR_32_BIT_UNION OemStringPtr;
+	UCHAR Capabilities[4];
+	PTR_32_BIT_UNION VideoModePtr;
+	USHORT TotalMemory;
+} VBE_1_2_INFO_BLOCK_UPDATABLE;
+
+typedef struct _VBE_2_0_INFO_BLOCK_UPDATABLE {
+	VBE_1_2_INFO_BLOCK_UPDATABLE CommonBlock;
+	USHORT OemSoftRev;
+	PTR_32_BIT_UNION OemVendorNamePtr;
+	PTR_32_BIT_UNION OemProductNamePtr;
+	PTR_32_BIT_UNION OemProductRevPtr;
+} VBE_2_0_INFO_BLOCK_UPDATABLE;
+
+typedef union _VBE_VERSION_UNION {
+	VBE_2_0_INFO_BLOCK_UPDATABLE VBE_2_0_InfoBlock;
+	VBE_1_2_INFO_BLOCK_UPDATABLE VBE_1_2_InfoBlock;
+} VBE_VERSION_UNION;
+
+typedef struct _VBE_INFO_BLOCK {
+	VBE_VERSION_UNION UpdatableVBE_Info;
+	UCHAR Reserved[222];
+	UCHAR OemData[256];
+} VBE_INFO_BLOCK;
+
+typedef struct _VBE_FP_INFO {
+	USHORT HSize;
+	USHORT VSize;
+	USHORT FPType;
+	UCHAR RedBPP;
+	UCHAR GreenBPP;
+	UCHAR BlueBPP;
+	UCHAR ReservedBPP;
+	ULONG RsvdOffScrnMemSize;
+	ULONG RsvdOffScrnMEmPtr;
+	UCHAR Reserved[14];
+} VBE_FP_INFO;
+
+typedef struct _VESA_MODE_INFO_BLOCK {
+/*  Mandatory information for all VBE revisions */
+	USHORT ModeAttributes;	/*                  dw      ?       ; mode attributes */
+	UCHAR WinAAttributes;	/*                    db      ?       ; window A attributes */
+	UCHAR WinBAttributes;	/*                    db      ?       ; window B attributes */
+	USHORT WinGranularity;	/*                    dw      ?       ; window granularity */
+	USHORT WinSize;		/*                    dw      ?       ; window size */
+	USHORT WinASegment;	/*                    dw      ?       ; window A start segment */
+	USHORT WinBSegment;	/*                    dw      ?       ; window B start segment */
+	ULONG WinFuncPtr;	/*                    dd      ?       ; real mode pointer to window function */
+	USHORT BytesPerScanLine;	/*                    dw      ?       ; bytes per scan line */
+
+/* ; Mandatory information for VBE 1.2 and above */
+	USHORT XResolution;	/*                         dw      ?       ; horizontal resolution in pixels or characters */
+	USHORT YResolution;	/*                   dw      ?       ; vertical resolution in pixels or characters */
+	UCHAR XCharSize;	/*                   db      ?       ; character cell width in pixels */
+	UCHAR YCharSize;	/*                   db      ?       ; character cell height in pixels */
+	UCHAR NumberOfPlanes;	/*                   db      ?       ; number of memory planes */
+	UCHAR BitsPerPixel;	/*                   db      ?       ; bits per pixel */
+	UCHAR NumberOfBanks;	/*                   db      ?       ; number of banks */
+	UCHAR MemoryModel;	/*                   db      ?       ; memory model type */
+	UCHAR BankSize;		/*                   db      ?       ; bank size in KB */
+	UCHAR NumberOfImagePages;	/*            db    ?       ; number of images */
+	UCHAR ReservedForPageFunction;	/* db  1       ; reserved for page function */
+
+/* ; Direct Color fields(required for direct/6 and YUV/7 memory models) */
+	UCHAR RedMaskSize;	/*           db      ?       ; size of direct color red mask in bits */
+	UCHAR RedFieldPosition;	/*           db      ?       ; bit position of lsb of red mask */
+	UCHAR GreenMaskSize;	/*           db      ?       ; size of direct color green mask in bits */
+	UCHAR GreenFieldPosition;	/*           db      ?       ; bit position of lsb of green mask */
+	UCHAR BlueMaskSize;	/*           db      ?       ; size of direct color blue mask in bits */
+	UCHAR BlueFieldPosition;	/*           db      ?       ; bit position of lsb of blue mask */
+	UCHAR RsvdMaskSize;	/*           db      ?       ; size of direct color reserved mask in bits */
+	UCHAR RsvdFieldPosition;	/*           db      ?       ; bit position of lsb of reserved mask */
+	UCHAR DirectColorModeInfo;	/*           db      ?       ; direct color mode attributes */
+
+/* ; Mandatory information for VBE 2.0 and above */
+	ULONG PhysBasePtr;	/*           dd      ?       ; physical address for flat memory frame buffer */
+	ULONG Reserved_1;	/*           dd      0       ; reserved - always set to 0 */
+	USHORT Reserved_2;	/*     dw    0       ; reserved - always set to 0 */
+
+/* ; Mandatory information for VBE 3.0 and above */
+	USHORT LinBytesPerScanLine;	/*         dw      ?       ; bytes per scan line for linear modes */
+	UCHAR BnkNumberOfImagePages;	/*         db      ?       ; number of images for banked modes */
+	UCHAR LinNumberOfImagPages;	/*         db      ?       ; number of images for linear modes */
+	UCHAR LinRedMaskSize;	/*         db      ?       ; size of direct color red mask(linear modes) */
+	UCHAR LinRedFieldPosition;	/*         db      ?       ; bit position of lsb of red mask(linear modes) */
+	UCHAR LinGreenMaskSize;	/*         db      ?       ; size of direct color green mask(linear modes) */
+	UCHAR LinGreenFieldPosition;	/*         db      ?       ; bit position of lsb of green mask(linear modes) */
+	UCHAR LinBlueMaskSize;	/*         db      ?       ; size of direct color blue mask(linear modes) */
+	UCHAR LinBlueFieldPosition;	/*         db      ?       ; bit position of lsb of blue mask(linear modes) */
+	UCHAR LinRsvdMaskSize;	/*         db      ?       ; size of direct color reserved mask(linear modes) */
+	UCHAR LinRsvdFieldPosition;	/*         db      ?       ; bit position of lsb of reserved mask(linear modes) */
+	ULONG MaxPixelClock;	/*         dd      ?       ; maximum pixel clock(in Hz) for graphics mode */
+	UCHAR Reserved;		/*         db      190 dup (0) */
+} VESA_MODE_INFO_BLOCK;
+
+/*  BIOS function CALLS */
+#define ATOM_BIOS_EXTENDED_FUNCTION_CODE        0xA0	/*  ATI Extended Function code */
+#define ATOM_BIOS_FUNCTION_COP_MODE             0x00
+#define ATOM_BIOS_FUNCTION_SHORT_QUERY1         0x04
+#define ATOM_BIOS_FUNCTION_SHORT_QUERY2         0x05
+#define ATOM_BIOS_FUNCTION_SHORT_QUERY3         0x06
+#define ATOM_BIOS_FUNCTION_GET_DDC              0x0B
+#define ATOM_BIOS_FUNCTION_ASIC_DSTATE          0x0E
+#define ATOM_BIOS_FUNCTION_DEBUG_PLAY           0x0F
+#define ATOM_BIOS_FUNCTION_STV_STD              0x16
+#define ATOM_BIOS_FUNCTION_DEVICE_DET           0x17
+#define ATOM_BIOS_FUNCTION_DEVICE_SWITCH        0x18
+
+#define ATOM_BIOS_FUNCTION_PANEL_CONTROL        0x82
+#define ATOM_BIOS_FUNCTION_OLD_DEVICE_DET       0x83
+#define ATOM_BIOS_FUNCTION_OLD_DEVICE_SWITCH    0x84
+#define ATOM_BIOS_FUNCTION_HW_ICON              0x8A
+#define ATOM_BIOS_FUNCTION_SET_CMOS             0x8B
+#define SUB_FUNCTION_UPDATE_DISPLAY_INFO        0x8000	/*  Sub function 80 */
+#define SUB_FUNCTION_UPDATE_EXPANSION_INFO      0x8100	/*  Sub function 80 */
+
+#define ATOM_BIOS_FUNCTION_DISPLAY_INFO         0x8D
+#define ATOM_BIOS_FUNCTION_DEVICE_ON_OFF        0x8E
+#define ATOM_BIOS_FUNCTION_VIDEO_STATE          0x8F
+#define ATOM_SUB_FUNCTION_GET_CRITICAL_STATE    0x0300	/*  Sub function 03 */
+#define ATOM_SUB_FUNCTION_GET_LIDSTATE          0x0700	/*  Sub function 7 */
+#define ATOM_SUB_FUNCTION_THERMAL_STATE_NOTICE  0x1400	/*  Notify caller the current thermal state */
+#define ATOM_SUB_FUNCTION_CRITICAL_STATE_NOTICE 0x8300	/*  Notify caller the current critical state */
+#define ATOM_SUB_FUNCTION_SET_LIDSTATE          0x8500	/*  Sub function 85 */
+#define ATOM_SUB_FUNCTION_GET_REQ_DISPLAY_FROM_SBIOS_MODE 0x8900	/*  Sub function 89 */
+#define ATOM_SUB_FUNCTION_INFORM_ADC_SUPPORT    0x9400	/*  Notify caller that ADC is supported */
+
+#define ATOM_BIOS_FUNCTION_VESA_DPMS            0x4F10	/*  Set DPMS */
+#define ATOM_SUB_FUNCTION_SET_DPMS              0x0001	/*  BL: Sub function 01 */
+#define ATOM_SUB_FUNCTION_GET_DPMS              0x0002	/*  BL: Sub function 02 */
+#define ATOM_PARAMETER_VESA_DPMS_ON             0x0000	/*  BH Parameter for DPMS ON. */
+#define ATOM_PARAMETER_VESA_DPMS_STANDBY        0x0100	/*  BH Parameter for DPMS STANDBY */
+#define ATOM_PARAMETER_VESA_DPMS_SUSPEND        0x0200	/*  BH Parameter for DPMS SUSPEND */
+#define ATOM_PARAMETER_VESA_DPMS_OFF            0x0400	/*  BH Parameter for DPMS OFF */
+#define ATOM_PARAMETER_VESA_DPMS_REDUCE_ON      0x0800	/*  BH Parameter for DPMS REDUCE ON (NOT SUPPORTED) */
+
+#define ATOM_BIOS_RETURN_CODE_MASK              0x0000FF00L
+#define ATOM_BIOS_REG_HIGH_MASK                 0x0000FF00L
+#define ATOM_BIOS_REG_LOW_MASK                  0x000000FFL
+
+/*  structure used for VBIOS only */
+
+/* DispOutInfoTable */
+typedef struct _ASIC_TRANSMITTER_INFO {
+	USHORT usTransmitterObjId;
+	USHORT usSupportDevice;
+	UCHAR ucTransmitterCmdTblId;
+	UCHAR ucConfig;
+	UCHAR ucEncoderID;	/* available 1st encoder ( default ) */
+	UCHAR ucOptionEncoderID;	/* available 2nd encoder ( optional ) */
+	UCHAR uc2ndEncoderID;
+	UCHAR ucReserved;
+} ASIC_TRANSMITTER_INFO;
+
+typedef struct _ASIC_ENCODER_INFO {
+	UCHAR ucEncoderID;
+	UCHAR ucEncoderConfig;
+	USHORT usEncoderCmdTblId;
+} ASIC_ENCODER_INFO;
+
+typedef struct _ATOM_DISP_OUT_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT ptrTransmitterInfo;
+	USHORT ptrEncoderInfo;
+	ASIC_TRANSMITTER_INFO asTransmitterInfo[1];
+	ASIC_ENCODER_INFO asEncoderInfo[1];
+} ATOM_DISP_OUT_INFO;
+
+/*  DispDevicePriorityInfo */
+typedef struct _ATOM_DISPLAY_DEVICE_PRIORITY_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT asDevicePriority[16];
+} ATOM_DISPLAY_DEVICE_PRIORITY_INFO;
+
+/* ProcessAuxChannelTransactionTable */
+typedef struct _PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS {
+	USHORT lpAuxRequest;
+	USHORT lpDataOut;
+	UCHAR ucChannelID;
+	union {
+		UCHAR ucReplyStatus;
+		UCHAR ucDelay;
+	};
+	UCHAR ucDataOutLen;
+	UCHAR ucReserved;
+} PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS;
+
+#define PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION			PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS
+
+/* GetSinkType */
+
+typedef struct _DP_ENCODER_SERVICE_PARAMETERS {
+	USHORT ucLinkClock;
+	union {
+		UCHAR ucConfig;	/*  for DP training command */
+		UCHAR ucI2cId;	/*  use for GET_SINK_TYPE command */
+	};
+	UCHAR ucAction;
+	UCHAR ucStatus;
+	UCHAR ucLaneNum;
+	UCHAR ucReserved[2];
+} DP_ENCODER_SERVICE_PARAMETERS;
+
+/*  ucAction */
+#define ATOM_DP_ACTION_GET_SINK_TYPE							0x01
+#define ATOM_DP_ACTION_TRAINING_START							0x02
+#define ATOM_DP_ACTION_TRAINING_COMPLETE					0x03
+#define ATOM_DP_ACTION_TRAINING_PATTERN_SEL				0x04
+#define ATOM_DP_ACTION_SET_VSWING_PREEMP					0x05
+#define ATOM_DP_ACTION_GET_VSWING_PREEMP					0x06
+#define ATOM_DP_ACTION_BLANKING                   0x07
+
+/*  ucConfig */
+#define ATOM_DP_CONFIG_ENCODER_SEL_MASK						0x03
+#define ATOM_DP_CONFIG_DIG1_ENCODER								0x00
+#define ATOM_DP_CONFIG_DIG2_ENCODER								0x01
+#define ATOM_DP_CONFIG_EXTERNAL_ENCODER						0x02
+#define ATOM_DP_CONFIG_LINK_SEL_MASK							0x04
+#define ATOM_DP_CONFIG_LINK_A											0x00
+#define ATOM_DP_CONFIG_LINK_B											0x04
+
+#define DP_ENCODER_SERVICE_PS_ALLOCATION				WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
+
+/*  DP_TRAINING_TABLE */
+#define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR				ATOM_DP_TRAINING_TBL_ADDR
+#define DPCD_SET_SS_CNTL_TBL_ADDR													(ATOM_DP_TRAINING_TBL_ADDR + 8 )
+#define DPCD_SET_LANE_VSWING_PREEMP_TBL_ADDR							(ATOM_DP_TRAINING_TBL_ADDR + 16)
+#define DPCD_SET_TRAINING_PATTERN0_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 24)
+#define DPCD_SET_TRAINING_PATTERN2_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 32)
+#define DPCD_GET_LINKRATE_LANENUM_SS_TBL_ADDR							(ATOM_DP_TRAINING_TBL_ADDR + 40)
+#define	DPCD_GET_LANE_STATUS_ADJUST_TBL_ADDR							(ATOM_DP_TRAINING_TBL_ADDR + 48)
+#define DP_I2C_AUX_DDC_WRITE_START_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 60)
+#define DP_I2C_AUX_DDC_WRITE_TBL_ADDR											(ATOM_DP_TRAINING_TBL_ADDR + 64)
+#define DP_I2C_AUX_DDC_READ_START_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 72)
+#define DP_I2C_AUX_DDC_READ_TBL_ADDR											(ATOM_DP_TRAINING_TBL_ADDR + 76)
+#define DP_I2C_AUX_DDC_READ_END_TBL_ADDR									(ATOM_DP_TRAINING_TBL_ADDR + 80)
+
+typedef struct _PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS {
+	UCHAR ucI2CSpeed;
+	union {
+		UCHAR ucRegIndex;
+		UCHAR ucStatus;
+	};
+	USHORT lpI2CDataOut;
+	UCHAR ucFlag;
+	UCHAR ucTransBytes;
+	UCHAR ucSlaveAddr;
+	UCHAR ucLineNumber;
+} PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS;
+
+#define PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION       PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS
+
+/* ucFlag */
+#define HW_I2C_WRITE        1
+#define HW_I2C_READ         0
+
+/****************************************************************************/
+/* Portion VI: Definitinos being oboselete */
+/****************************************************************************/
+
+/* ========================================================================================== */
+/* Remove the definitions below when driver is ready! */
+typedef struct _ATOM_DAC_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usMaxFrequency;	/*  in 10kHz unit */
+	USHORT usReserved;
+} ATOM_DAC_INFO;
+
+typedef struct _COMPASSIONATE_DATA {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+
+	/* ==============================  DAC1 portion */
+	UCHAR ucDAC1_BG_Adjustment;
+	UCHAR ucDAC1_DAC_Adjustment;
+	USHORT usDAC1_FORCE_Data;
+	/* ==============================  DAC2 portion */
+	UCHAR ucDAC2_CRT2_BG_Adjustment;
+	UCHAR ucDAC2_CRT2_DAC_Adjustment;
+	USHORT usDAC2_CRT2_FORCE_Data;
+	USHORT usDAC2_CRT2_MUX_RegisterIndex;
+	UCHAR ucDAC2_CRT2_MUX_RegisterInfo;	/* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */
+	UCHAR ucDAC2_NTSC_BG_Adjustment;
+	UCHAR ucDAC2_NTSC_DAC_Adjustment;
+	USHORT usDAC2_TV1_FORCE_Data;
+	USHORT usDAC2_TV1_MUX_RegisterIndex;
+	UCHAR ucDAC2_TV1_MUX_RegisterInfo;	/* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */
+	UCHAR ucDAC2_CV_BG_Adjustment;
+	UCHAR ucDAC2_CV_DAC_Adjustment;
+	USHORT usDAC2_CV_FORCE_Data;
+	USHORT usDAC2_CV_MUX_RegisterIndex;
+	UCHAR ucDAC2_CV_MUX_RegisterInfo;	/* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */
+	UCHAR ucDAC2_PAL_BG_Adjustment;
+	UCHAR ucDAC2_PAL_DAC_Adjustment;
+	USHORT usDAC2_TV2_FORCE_Data;
+} COMPASSIONATE_DATA;
+
+/****************************Supported Device Info Table Definitions**********************/
+/*   ucConnectInfo: */
+/*     [7:4] - connector type */
+/*       = 1   - VGA connector */
+/*       = 2   - DVI-I */
+/*       = 3   - DVI-D */
+/*       = 4   - DVI-A */
+/*       = 5   - SVIDEO */
+/*       = 6   - COMPOSITE */
+/*       = 7   - LVDS */
+/*       = 8   - DIGITAL LINK */
+/*       = 9   - SCART */
+/*       = 0xA - HDMI_type A */
+/*       = 0xB - HDMI_type B */
+/*       = 0xE - Special case1 (DVI+DIN) */
+/*       Others=TBD */
+/*     [3:0] - DAC Associated */
+/*       = 0   - no DAC */
+/*       = 1   - DACA */
+/*       = 2   - DACB */
+/*       = 3   - External DAC */
+/*       Others=TBD */
+/*  */
+
+typedef struct _ATOM_CONNECTOR_INFO {
+#if ATOM_BIG_ENDIAN
+	UCHAR bfConnectorType:4;
+	UCHAR bfAssociatedDAC:4;
+#else
+	UCHAR bfAssociatedDAC:4;
+	UCHAR bfConnectorType:4;
+#endif
+} ATOM_CONNECTOR_INFO;
+
+typedef union _ATOM_CONNECTOR_INFO_ACCESS {
+	ATOM_CONNECTOR_INFO sbfAccess;
+	UCHAR ucAccess;
+} ATOM_CONNECTOR_INFO_ACCESS;
+
+typedef struct _ATOM_CONNECTOR_INFO_I2C {
+	ATOM_CONNECTOR_INFO_ACCESS sucConnectorInfo;
+	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
+} ATOM_CONNECTOR_INFO_I2C;
+
+typedef struct _ATOM_SUPPORTED_DEVICES_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usDeviceSupport;
+	ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO];
+} ATOM_SUPPORTED_DEVICES_INFO;
+
+#define NO_INT_SRC_MAPPED       0xFF
+
+typedef struct _ATOM_CONNECTOR_INC_SRC_BITMAP {
+	UCHAR ucIntSrcBitmap;
+} ATOM_CONNECTOR_INC_SRC_BITMAP;
+
+typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usDeviceSupport;
+	ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2];
+	ATOM_CONNECTOR_INC_SRC_BITMAP
+	    asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2];
+} ATOM_SUPPORTED_DEVICES_INFO_2;
+
+typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usDeviceSupport;
+	ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE];
+	ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE];
+} ATOM_SUPPORTED_DEVICES_INFO_2d1;
+
+#define ATOM_SUPPORTED_DEVICES_INFO_LAST ATOM_SUPPORTED_DEVICES_INFO_2d1
+
+typedef struct _ATOM_MISC_CONTROL_INFO {
+	USHORT usFrequency;
+	UCHAR ucPLL_ChargePump;	/*  PLL charge-pump gain control */
+	UCHAR ucPLL_DutyCycle;	/*  PLL duty cycle control */
+	UCHAR ucPLL_VCO_Gain;	/*  PLL VCO gain control */
+	UCHAR ucPLL_VoltageSwing;	/*  PLL driver voltage swing control */
+} ATOM_MISC_CONTROL_INFO;
+
+#define ATOM_MAX_MISC_INFO       4
+
+typedef struct _ATOM_TMDS_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usMaxFrequency;	/*  in 10Khz */
+	ATOM_MISC_CONTROL_INFO asMiscInfo[ATOM_MAX_MISC_INFO];
+} ATOM_TMDS_INFO;
+
+typedef struct _ATOM_ENCODER_ANALOG_ATTRIBUTE {
+	UCHAR ucTVStandard;	/* Same as TV standards defined above, */
+	UCHAR ucPadding[1];
+} ATOM_ENCODER_ANALOG_ATTRIBUTE;
+
+typedef struct _ATOM_ENCODER_DIGITAL_ATTRIBUTE {
+	UCHAR ucAttribute;	/* Same as other digital encoder attributes defined above */
+	UCHAR ucPadding[1];
+} ATOM_ENCODER_DIGITAL_ATTRIBUTE;
+
+typedef union _ATOM_ENCODER_ATTRIBUTE {
+	ATOM_ENCODER_ANALOG_ATTRIBUTE sAlgAttrib;
+	ATOM_ENCODER_DIGITAL_ATTRIBUTE sDigAttrib;
+} ATOM_ENCODER_ATTRIBUTE;
+
+typedef struct _DVO_ENCODER_CONTROL_PARAMETERS {
+	USHORT usPixelClock;
+	USHORT usEncoderID;
+	UCHAR ucDeviceType;	/* Use ATOM_DEVICE_xxx1_Index to indicate device type only. */
+	UCHAR ucAction;		/* ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT */
+	ATOM_ENCODER_ATTRIBUTE usDevAttr;
+} DVO_ENCODER_CONTROL_PARAMETERS;
+
+typedef struct _DVO_ENCODER_CONTROL_PS_ALLOCATION {
+	DVO_ENCODER_CONTROL_PARAMETERS sDVOEncoder;
+	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this portion */
+} DVO_ENCODER_CONTROL_PS_ALLOCATION;
+
+#define ATOM_XTMDS_ASIC_SI164_ID        1
+#define ATOM_XTMDS_ASIC_SI178_ID        2
+#define ATOM_XTMDS_ASIC_TFP513_ID       3
+#define ATOM_XTMDS_SUPPORTED_SINGLELINK 0x00000001
+#define ATOM_XTMDS_SUPPORTED_DUALLINK   0x00000002
+#define ATOM_XTMDS_MVPU_FPGA            0x00000004
+
+typedef struct _ATOM_XTMDS_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	USHORT usSingleLinkMaxFrequency;
+	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;	/* Point the ID on which I2C is used to control external chip */
+	UCHAR ucXtransimitterID;
+	UCHAR ucSupportedLink;	/*  Bit field, bit0=1, single link supported;bit1=1,dual link supported */
+	UCHAR ucSequnceAlterID;	/*  Even with the same external TMDS asic, it's possible that the program seqence alters */
+	/*  due to design. This ID is used to alert driver that the sequence is not "standard"! */
+	UCHAR ucMasterAddress;	/*  Address to control Master xTMDS Chip */
+	UCHAR ucSlaveAddress;	/*  Address to control Slave xTMDS Chip */
+} ATOM_XTMDS_INFO;
+
+typedef struct _DFP_DPMS_STATUS_CHANGE_PARAMETERS {
+	UCHAR ucEnable;		/*  ATOM_ENABLE=On or ATOM_DISABLE=Off */
+	UCHAR ucDevice;		/*  ATOM_DEVICE_DFP1_INDEX.... */
+	UCHAR ucPadding[2];
+} DFP_DPMS_STATUS_CHANGE_PARAMETERS;
+
+/****************************Legacy Power Play Table Definitions **********************/
+
+/* Definitions for ulPowerPlayMiscInfo */
+#define ATOM_PM_MISCINFO_SPLIT_CLOCK                     0x00000000L
+#define ATOM_PM_MISCINFO_USING_MCLK_SRC                  0x00000001L
+#define ATOM_PM_MISCINFO_USING_SCLK_SRC                  0x00000002L
+
+#define ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT            0x00000004L
+#define ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH        0x00000008L
+
+#define ATOM_PM_MISCINFO_LOAD_PERFORMANCE_EN             0x00000010L
+
+#define ATOM_PM_MISCINFO_ENGINE_CLOCK_CONTRL_EN          0x00000020L
+#define ATOM_PM_MISCINFO_MEMORY_CLOCK_CONTRL_EN          0x00000040L
+#define ATOM_PM_MISCINFO_PROGRAM_VOLTAGE                 0x00000080L	/* When this bit set, ucVoltageDropIndex is not an index for GPIO pin, but a voltage ID that SW needs program */
+
+#define ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN      0x00000100L
+#define ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN         0x00000200L
+#define ATOM_PM_MISCINFO_ASIC_SLEEP_MODE_EN              0x00000400L
+#define ATOM_PM_MISCINFO_LOAD_BALANCE_EN                 0x00000800L
+#define ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE     0x00001000L
+#define ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE 0x00002000L
+#define ATOM_PM_MISCINFO_LOW_LCD_REFRESH_RATE            0x00004000L
+
+#define ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE             0x00008000L
+#define ATOM_PM_MISCINFO_OVER_CLOCK_MODE                 0x00010000L
+#define ATOM_PM_MISCINFO_OVER_DRIVE_MODE                 0x00020000L
+#define ATOM_PM_MISCINFO_POWER_SAVING_MODE               0x00040000L
+#define ATOM_PM_MISCINFO_THERMAL_DIODE_MODE              0x00080000L
+
+#define ATOM_PM_MISCINFO_FRAME_MODULATION_MASK           0x00300000L	/* 0-FM Disable, 1-2 level FM, 2-4 level FM, 3-Reserved */
+#define ATOM_PM_MISCINFO_FRAME_MODULATION_SHIFT          20
+
+#define ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE                 0x00400000L
+#define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2      0x00800000L
+#define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4      0x01000000L
+#define ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN            0x02000000L	/* When set, Dynamic */
+#define ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN        0x04000000L	/* When set, Dynamic */
+#define ATOM_PM_MISCINFO_3D_ACCELERATION_EN              0x08000000L	/* When set, This mode is for acceleated 3D mode */
+
+#define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_MASK   0x70000000L	/* 1-Optimal Battery Life Group, 2-High Battery, 3-Balanced, 4-High Performance, 5- Optimal Performance (Default state with Default clocks) */
+#define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_SHIFT  28
+#define ATOM_PM_MISCINFO_ENABLE_BACK_BIAS                0x80000000L
+
+#define ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE            0x00000001L
+#define ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT          0x00000002L
+#define ATOM_PM_MISCINFO2_DYNAMIC_BACK_BIAS_EN           0x00000004L
+#define ATOM_PM_MISCINFO2_FS3D_OVERDRIVE_INFO            0x00000008L
+#define ATOM_PM_MISCINFO2_FORCEDLOWPWR_MODE              0x00000010L
+#define ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN       0x00000020L
+#define ATOM_PM_MISCINFO2_VIDEO_PLAYBACK_CAPABLE         0x00000040L	/* If this bit is set in multi-pp mode, then driver will pack up one with the minior power consumption. */
+								      /* If it's not set in any pp mode, driver will use its default logic to pick a pp mode in video playback */
+#define ATOM_PM_MISCINFO2_NOT_VALID_ON_DC                0x00000080L
+#define ATOM_PM_MISCINFO2_STUTTER_MODE_EN                0x00000100L
+#define ATOM_PM_MISCINFO2_UVD_SUPPORT_MODE               0x00000200L
+
+/* ucTableFormatRevision=1 */
+/* ucTableContentRevision=1 */
+typedef struct _ATOM_POWERMODE_INFO {
+	ULONG ulMiscInfo;	/* The power level should be arranged in ascending order */
+	ULONG ulReserved1;	/*  must set to 0 */
+	ULONG ulReserved2;	/*  must set to 0 */
+	USHORT usEngineClock;
+	USHORT usMemoryClock;
+	UCHAR ucVoltageDropIndex;	/*  index to GPIO table */
+	UCHAR ucSelectedPanel_RefreshRate;	/*  panel refresh rate */
+	UCHAR ucMinTemperature;
+	UCHAR ucMaxTemperature;
+	UCHAR ucNumPciELanes;	/*  number of PCIE lanes */
+} ATOM_POWERMODE_INFO;
+
+/* ucTableFormatRevision=2 */
+/* ucTableContentRevision=1 */
+typedef struct _ATOM_POWERMODE_INFO_V2 {
+	ULONG ulMiscInfo;	/* The power level should be arranged in ascending order */
+	ULONG ulMiscInfo2;
+	ULONG ulEngineClock;
+	ULONG ulMemoryClock;
+	UCHAR ucVoltageDropIndex;	/*  index to GPIO table */
+	UCHAR ucSelectedPanel_RefreshRate;	/*  panel refresh rate */
+	UCHAR ucMinTemperature;
+	UCHAR ucMaxTemperature;
+	UCHAR ucNumPciELanes;	/*  number of PCIE lanes */
+} ATOM_POWERMODE_INFO_V2;
+
+/* ucTableFormatRevision=2 */
+/* ucTableContentRevision=2 */
+typedef struct _ATOM_POWERMODE_INFO_V3 {
+	ULONG ulMiscInfo;	/* The power level should be arranged in ascending order */
+	ULONG ulMiscInfo2;
+	ULONG ulEngineClock;
+	ULONG ulMemoryClock;
+	UCHAR ucVoltageDropIndex;	/*  index to Core (VDDC) votage table */
+	UCHAR ucSelectedPanel_RefreshRate;	/*  panel refresh rate */
+	UCHAR ucMinTemperature;
+	UCHAR ucMaxTemperature;
+	UCHAR ucNumPciELanes;	/*  number of PCIE lanes */
+	UCHAR ucVDDCI_VoltageDropIndex;	/*  index to VDDCI votage table */
+} ATOM_POWERMODE_INFO_V3;
+
+#define ATOM_MAX_NUMBEROF_POWER_BLOCK  8
+
+#define ATOM_PP_OVERDRIVE_INTBITMAP_AUXWIN            0x01
+#define ATOM_PP_OVERDRIVE_INTBITMAP_OVERDRIVE         0x02
+
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_LM63      0x01
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ADM1032   0x02
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ADM1030   0x03
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_MUA6649   0x04
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_LM64      0x05
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_F75375    0x06
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ASC7512   0x07	/*  Andigilog */
+
+typedef struct _ATOM_POWERPLAY_INFO {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR ucOverdriveThermalController;
+	UCHAR ucOverdriveI2cLine;
+	UCHAR ucOverdriveIntBitmap;
+	UCHAR ucOverdriveControllerAddress;
+	UCHAR ucSizeOfPowerModeEntry;
+	UCHAR ucNumOfPowerModeEntries;
+	ATOM_POWERMODE_INFO asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
+} ATOM_POWERPLAY_INFO;
+
+typedef struct _ATOM_POWERPLAY_INFO_V2 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR ucOverdriveThermalController;
+	UCHAR ucOverdriveI2cLine;
+	UCHAR ucOverdriveIntBitmap;
+	UCHAR ucOverdriveControllerAddress;
+	UCHAR ucSizeOfPowerModeEntry;
+	UCHAR ucNumOfPowerModeEntries;
+	ATOM_POWERMODE_INFO_V2 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
+} ATOM_POWERPLAY_INFO_V2;
+
+typedef struct _ATOM_POWERPLAY_INFO_V3 {
+	ATOM_COMMON_TABLE_HEADER sHeader;
+	UCHAR ucOverdriveThermalController;
+	UCHAR ucOverdriveI2cLine;
+	UCHAR ucOverdriveIntBitmap;
+	UCHAR ucOverdriveControllerAddress;
+	UCHAR ucSizeOfPowerModeEntry;
+	UCHAR ucNumOfPowerModeEntries;
+	ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
+} ATOM_POWERPLAY_INFO_V3;
+
+/**************************************************************************/
+
+/*  Following definitions are for compatiblity issue in different SW components. */
+#define ATOM_MASTER_DATA_TABLE_REVISION   0x01
+#define Object_Info												Object_Header
+#define	AdjustARB_SEQ											MC_InitParameter
+#define	VRAM_GPIO_DetectionInfo						VoltageObjectInfo
+#define	ASIC_VDDCI_Info                   ASIC_ProfilingInfo
+#define ASIC_MVDDQ_Info										MemoryTrainingInfo
+#define SS_Info                           PPLL_SS_Info
+#define ASIC_MVDDC_Info                   ASIC_InternalSS_Info
+#define DispDevicePriorityInfo						SaveRestoreInfo
+#define DispOutInfo												TV_VideoMode
+
+#define ATOM_ENCODER_OBJECT_TABLE         ATOM_OBJECT_TABLE
+#define ATOM_CONNECTOR_OBJECT_TABLE       ATOM_OBJECT_TABLE
+
+/* New device naming, remove them when both DAL/VBIOS is ready */
+#define DFP2I_OUTPUT_CONTROL_PARAMETERS    CRT1_OUTPUT_CONTROL_PARAMETERS
+#define DFP2I_OUTPUT_CONTROL_PS_ALLOCATION DFP2I_OUTPUT_CONTROL_PARAMETERS
+
+#define DFP1X_OUTPUT_CONTROL_PARAMETERS    CRT1_OUTPUT_CONTROL_PARAMETERS
+#define DFP1X_OUTPUT_CONTROL_PS_ALLOCATION DFP1X_OUTPUT_CONTROL_PARAMETERS
+
+#define DFP1I_OUTPUT_CONTROL_PARAMETERS    DFP1_OUTPUT_CONTROL_PARAMETERS
+#define DFP1I_OUTPUT_CONTROL_PS_ALLOCATION DFP1_OUTPUT_CONTROL_PS_ALLOCATION
+
+#define ATOM_DEVICE_DFP1I_SUPPORT          ATOM_DEVICE_DFP1_SUPPORT
+#define ATOM_DEVICE_DFP1X_SUPPORT          ATOM_DEVICE_DFP2_SUPPORT
+
+#define ATOM_DEVICE_DFP1I_INDEX            ATOM_DEVICE_DFP1_INDEX
+#define ATOM_DEVICE_DFP1X_INDEX            ATOM_DEVICE_DFP2_INDEX
+
+#define ATOM_DEVICE_DFP2I_INDEX            0x00000009
+#define ATOM_DEVICE_DFP2I_SUPPORT          (0x1L << ATOM_DEVICE_DFP2I_INDEX)
+
+#define ATOM_S0_DFP1I                      ATOM_S0_DFP1
+#define ATOM_S0_DFP1X                      ATOM_S0_DFP2
+
+#define ATOM_S0_DFP2I                      0x00200000L
+#define ATOM_S0_DFP2Ib2                    0x20
+
+#define ATOM_S2_DFP1I_DPMS_STATE           ATOM_S2_DFP1_DPMS_STATE
+#define ATOM_S2_DFP1X_DPMS_STATE           ATOM_S2_DFP2_DPMS_STATE
+
+#define ATOM_S2_DFP2I_DPMS_STATE           0x02000000L
+#define ATOM_S2_DFP2I_DPMS_STATEb3         0x02
+
+#define ATOM_S3_DFP2I_ACTIVEb1             0x02
+
+#define ATOM_S3_DFP1I_ACTIVE               ATOM_S3_DFP1_ACTIVE
+#define ATOM_S3_DFP1X_ACTIVE               ATOM_S3_DFP2_ACTIVE
+
+#define ATOM_S3_DFP2I_ACTIVE               0x00000200L
+
+#define ATOM_S3_DFP1I_CRTC_ACTIVE          ATOM_S3_DFP1_CRTC_ACTIVE
+#define ATOM_S3_DFP1X_CRTC_ACTIVE          ATOM_S3_DFP2_CRTC_ACTIVE
+#define ATOM_S3_DFP2I_CRTC_ACTIVE          0x02000000L
+
+#define ATOM_S3_DFP2I_CRTC_ACTIVEb3        0x02
+#define ATOM_S5_DOS_REQ_DFP2Ib1            0x02
+
+#define ATOM_S5_DOS_REQ_DFP2I              0x0200
+#define ATOM_S6_ACC_REQ_DFP1I              ATOM_S6_ACC_REQ_DFP1
+#define ATOM_S6_ACC_REQ_DFP1X              ATOM_S6_ACC_REQ_DFP2
+
+#define ATOM_S6_ACC_REQ_DFP2Ib3            0x02
+#define ATOM_S6_ACC_REQ_DFP2I              0x02000000L
+
+#define TMDS1XEncoderControl               DVOEncoderControl
+#define DFP1XOutputControl                 DVOOutputControl
+
+#define ExternalDFPOutputControl           DFP1XOutputControl
+#define EnableExternalTMDS_Encoder         TMDS1XEncoderControl
+
+#define DFP1IOutputControl                 TMDSAOutputControl
+#define DFP2IOutputControl                 LVTMAOutputControl
+
+#define DAC1_ENCODER_CONTROL_PARAMETERS    DAC_ENCODER_CONTROL_PARAMETERS
+#define DAC1_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION
+
+#define DAC2_ENCODER_CONTROL_PARAMETERS    DAC_ENCODER_CONTROL_PARAMETERS
+#define DAC2_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION
+
+#define ucDac1Standard  ucDacStandard
+#define ucDac2Standard  ucDacStandard
+
+#define TMDS1EncoderControl TMDSAEncoderControl
+#define TMDS2EncoderControl LVTMAEncoderControl
+
+#define DFP1OutputControl   TMDSAOutputControl
+#define DFP2OutputControl   LVTMAOutputControl
+#define CRT1OutputControl   DAC1OutputControl
+#define CRT2OutputControl   DAC2OutputControl
+
+/* These two lines will be removed for sure in a few days, will follow up with Michael V. */
+#define EnableLVDS_SS   EnableSpreadSpectrumOnPPLL
+#define ENABLE_LVDS_SS_PARAMETERS_V3  ENABLE_SPREAD_SPECTRUM_ON_PPLL
+
+/*********************************************************************************/
+
+#pragma pack()			/*  BIOS data must use byte aligment */
+
+#endif /* _ATOMBIOS_H */
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom-bits.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom-bits.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom-bits.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom-bits.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Stanislaw Skowronek
+ */
+
+#ifndef ATOM_BITS_H
+#define ATOM_BITS_H
+
+static inline uint8_t get_u8(void *bios, int ptr)
+{
+    return ((unsigned char *)bios)[ptr];
+}
+#define U8(ptr) get_u8(ctx->ctx->bios, (ptr))
+#define CU8(ptr) get_u8(ctx->bios, (ptr))
+static inline uint16_t get_u16(void *bios, int ptr)
+{
+    return get_u8(bios ,ptr)|(((uint16_t)get_u8(bios, ptr+1))<<8);
+}
+#define U16(ptr) get_u16(ctx->ctx->bios, (ptr))
+#define CU16(ptr) get_u16(ctx->bios, (ptr))
+static inline uint32_t get_u32(void *bios, int ptr)
+{
+    return get_u16(bios, ptr)|(((uint32_t)get_u16(bios, ptr+2))<<16);
+}
+#define U32(ptr) get_u32(ctx->ctx->bios, (ptr))
+#define CU32(ptr) get_u32(ctx->bios, (ptr))
+#define CSTR(ptr) (((char *)(ctx->bios))+(ptr))
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1215 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Stanislaw Skowronek
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+
+#define ATOM_DEBUG
+
+#include "atom.h"
+#include "atom-names.h"
+#include "atom-bits.h"
+
+#define ATOM_COND_ABOVE		0
+#define ATOM_COND_ABOVEOREQUAL	1
+#define ATOM_COND_ALWAYS	2
+#define ATOM_COND_BELOW		3
+#define ATOM_COND_BELOWOREQUAL	4
+#define ATOM_COND_EQUAL		5
+#define ATOM_COND_NOTEQUAL	6
+
+#define ATOM_PORT_ATI	0
+#define ATOM_PORT_PCI	1
+#define ATOM_PORT_SYSIO	2
+
+#define ATOM_UNIT_MICROSEC	0
+#define ATOM_UNIT_MILLISEC	1
+
+#define PLL_INDEX	2
+#define PLL_DATA	3
+
+typedef struct {
+	struct atom_context *ctx;
+
+	uint32_t *ps, *ws;
+	int ps_shift;
+	uint16_t start;
+} atom_exec_context;
+
+int atom_debug = 0;
+void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
+
+static uint32_t atom_arg_mask[8] =
+    { 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000,
+0xFF000000 };
+static int atom_arg_shift[8] = { 0, 0, 8, 16, 0, 8, 16, 24 };
+
+static int atom_dst_to_src[8][4] = {
+	/* translate destination alignment field to the source alignment encoding */
+	{0, 0, 0, 0},
+	{1, 2, 3, 0},
+	{1, 2, 3, 0},
+	{1, 2, 3, 0},
+	{4, 5, 6, 7},
+	{4, 5, 6, 7},
+	{4, 5, 6, 7},
+	{4, 5, 6, 7},
+};
+static int atom_def_dst[8] = { 0, 0, 1, 2, 0, 1, 2, 3 };
+
+static int debug_depth = 0;
+#ifdef ATOM_DEBUG
+static void debug_print_spaces(int n)
+{
+	while (n--)
+		printk("   ");
+}
+
+#define DEBUG(...) do if (atom_debug) { printk(KERN_DEBUG __VA_ARGS__); } while (0)
+#define SDEBUG(...) do if (atom_debug) { printk(KERN_DEBUG); debug_print_spaces(debug_depth); printk(__VA_ARGS__); } while (0)
+#else
+#define DEBUG(...) do { } while (0)
+#define SDEBUG(...) do { } while (0)
+#endif
+
+static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
+				 uint32_t index, uint32_t data)
+{
+	uint32_t temp = 0xCDCDCDCD;
+	while (1)
+		switch (CU8(base)) {
+		case ATOM_IIO_NOP:
+			base++;
+			break;
+		case ATOM_IIO_READ:
+			temp = ctx->card->reg_read(ctx->card, CU16(base + 1));
+			base += 3;
+			break;
+		case ATOM_IIO_WRITE:
+			ctx->card->reg_write(ctx->card, CU16(base + 1), temp);
+			base += 3;
+			break;
+		case ATOM_IIO_CLEAR:
+			temp &=
+			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
+			      CU8(base + 2));
+			base += 3;
+			break;
+		case ATOM_IIO_SET:
+			temp |=
+			    (0xFFFFFFFF >> (32 - CU8(base + 1))) << CU8(base +
+									2);
+			base += 3;
+			break;
+		case ATOM_IIO_MOVE_INDEX:
+			temp &=
+			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
+			      CU8(base + 2));
+			temp |=
+			    ((index >> CU8(base + 2)) &
+			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
+									  3);
+			base += 4;
+			break;
+		case ATOM_IIO_MOVE_DATA:
+			temp &=
+			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
+			      CU8(base + 2));
+			temp |=
+			    ((data >> CU8(base + 2)) &
+			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
+									  3);
+			base += 4;
+			break;
+		case ATOM_IIO_MOVE_ATTR:
+			temp &=
+			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
+			      CU8(base + 2));
+			temp |=
+			    ((ctx->
+			      io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 -
+									  CU8
+									  (base
+									   +
+									   1))))
+			    << CU8(base + 3);
+			base += 4;
+			break;
+		case ATOM_IIO_END:
+			return temp;
+		default:
+			printk(KERN_INFO "Unknown IIO opcode.\n");
+			return 0;
+		}
+}
+
+static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
+				 int *ptr, uint32_t *saved, int print)
+{
+	uint32_t idx, val = 0xCDCDCDCD, align, arg;
+	struct atom_context *gctx = ctx->ctx;
+	arg = attr & 7;
+	align = (attr >> 3) & 7;
+	switch (arg) {
+	case ATOM_ARG_REG:
+		idx = U16(*ptr);
+		(*ptr) += 2;
+		if (print)
+			DEBUG("REG[0x%04X]", idx);
+		idx += gctx->reg_block;
+		switch (gctx->io_mode) {
+		case ATOM_IO_MM:
+			val = gctx->card->reg_read(gctx->card, idx);
+			break;
+		case ATOM_IO_PCI:
+			printk(KERN_INFO
+			       "PCI registers are not implemented.\n");
+			return 0;
+		case ATOM_IO_SYSIO:
+			printk(KERN_INFO
+			       "SYSIO registers are not implemented.\n");
+			return 0;
+		default:
+			if (!(gctx->io_mode & 0x80)) {
+				printk(KERN_INFO "Bad IO mode.\n");
+				return 0;
+			}
+			if (!gctx->iio[gctx->io_mode & 0x7F]) {
+				printk(KERN_INFO
+				       "Undefined indirect IO read method %d.\n",
+				       gctx->io_mode & 0x7F);
+				return 0;
+			}
+			val =
+			    atom_iio_execute(gctx,
+					     gctx->iio[gctx->io_mode & 0x7F],
+					     idx, 0);
+		}
+		break;
+	case ATOM_ARG_PS:
+		idx = U8(*ptr);
+		(*ptr)++;
+		val = le32_to_cpu(ctx->ps[idx]);
+		if (print)
+			DEBUG("PS[0x%02X,0x%04X]", idx, val);
+		break;
+	case ATOM_ARG_WS:
+		idx = U8(*ptr);
+		(*ptr)++;
+		if (print)
+			DEBUG("WS[0x%02X]", idx);
+		switch (idx) {
+		case ATOM_WS_QUOTIENT:
+			val = gctx->divmul[0];
+			break;
+		case ATOM_WS_REMAINDER:
+			val = gctx->divmul[1];
+			break;
+		case ATOM_WS_DATAPTR:
+			val = gctx->data_block;
+			break;
+		case ATOM_WS_SHIFT:
+			val = gctx->shift;
+			break;
+		case ATOM_WS_OR_MASK:
+			val = 1 << gctx->shift;
+			break;
+		case ATOM_WS_AND_MASK:
+			val = ~(1 << gctx->shift);
+			break;
+		case ATOM_WS_FB_WINDOW:
+			val = gctx->fb_base;
+			break;
+		case ATOM_WS_ATTRIBUTES:
+			val = gctx->io_attr;
+			break;
+		default:
+			val = ctx->ws[idx];
+		}
+		break;
+	case ATOM_ARG_ID:
+		idx = U16(*ptr);
+		(*ptr) += 2;
+		if (print) {
+			if (gctx->data_block)
+				DEBUG("ID[0x%04X+%04X]", idx, gctx->data_block);
+			else
+				DEBUG("ID[0x%04X]", idx);
+		}
+		val = U32(idx + gctx->data_block);
+		break;
+	case ATOM_ARG_FB:
+		idx = U8(*ptr);
+		(*ptr)++;
+		if (print)
+			DEBUG("FB[0x%02X]", idx);
+		printk(KERN_INFO "FB access is not implemented.\n");
+		return 0;
+	case ATOM_ARG_IMM:
+		switch (align) {
+		case ATOM_SRC_DWORD:
+			val = U32(*ptr);
+			(*ptr) += 4;
+			if (print)
+				DEBUG("IMM 0x%08X\n", val);
+			return val;
+		case ATOM_SRC_WORD0:
+		case ATOM_SRC_WORD8:
+		case ATOM_SRC_WORD16:
+			val = U16(*ptr);
+			(*ptr) += 2;
+			if (print)
+				DEBUG("IMM 0x%04X\n", val);
+			return val;
+		case ATOM_SRC_BYTE0:
+		case ATOM_SRC_BYTE8:
+		case ATOM_SRC_BYTE16:
+		case ATOM_SRC_BYTE24:
+			val = U8(*ptr);
+			(*ptr)++;
+			if (print)
+				DEBUG("IMM 0x%02X\n", val);
+			return val;
+		}
+		return 0;
+	case ATOM_ARG_PLL:
+		idx = U8(*ptr);
+		(*ptr)++;
+		if (print)
+			DEBUG("PLL[0x%02X]", idx);
+		val = gctx->card->pll_read(gctx->card, idx);
+		break;
+	case ATOM_ARG_MC:
+		idx = U8(*ptr);
+		(*ptr)++;
+		if (print)
+			DEBUG("MC[0x%02X]", idx);
+		val = gctx->card->mc_read(gctx->card, idx);
+		break;
+	}
+	if (saved)
+		*saved = val;
+	val &= atom_arg_mask[align];
+	val >>= atom_arg_shift[align];
+	if (print)
+		switch (align) {
+		case ATOM_SRC_DWORD:
+			DEBUG(".[31:0] -> 0x%08X\n", val);
+			break;
+		case ATOM_SRC_WORD0:
+			DEBUG(".[15:0] -> 0x%04X\n", val);
+			break;
+		case ATOM_SRC_WORD8:
+			DEBUG(".[23:8] -> 0x%04X\n", val);
+			break;
+		case ATOM_SRC_WORD16:
+			DEBUG(".[31:16] -> 0x%04X\n", val);
+			break;
+		case ATOM_SRC_BYTE0:
+			DEBUG(".[7:0] -> 0x%02X\n", val);
+			break;
+		case ATOM_SRC_BYTE8:
+			DEBUG(".[15:8] -> 0x%02X\n", val);
+			break;
+		case ATOM_SRC_BYTE16:
+			DEBUG(".[23:16] -> 0x%02X\n", val);
+			break;
+		case ATOM_SRC_BYTE24:
+			DEBUG(".[31:24] -> 0x%02X\n", val);
+			break;
+		}
+	return val;
+}
+
+static void atom_skip_src_int(atom_exec_context *ctx, uint8_t attr, int *ptr)
+{
+	uint32_t align = (attr >> 3) & 7, arg = attr & 7;
+	switch (arg) {
+	case ATOM_ARG_REG:
+	case ATOM_ARG_ID:
+		(*ptr) += 2;
+		break;
+	case ATOM_ARG_PLL:
+	case ATOM_ARG_MC:
+	case ATOM_ARG_PS:
+	case ATOM_ARG_WS:
+	case ATOM_ARG_FB:
+		(*ptr)++;
+		break;
+	case ATOM_ARG_IMM:
+		switch (align) {
+		case ATOM_SRC_DWORD:
+			(*ptr) += 4;
+			return;
+		case ATOM_SRC_WORD0:
+		case ATOM_SRC_WORD8:
+		case ATOM_SRC_WORD16:
+			(*ptr) += 2;
+			return;
+		case ATOM_SRC_BYTE0:
+		case ATOM_SRC_BYTE8:
+		case ATOM_SRC_BYTE16:
+		case ATOM_SRC_BYTE24:
+			(*ptr)++;
+			return;
+		}
+		return;
+	}
+}
+
+static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr)
+{
+	return atom_get_src_int(ctx, attr, ptr, NULL, 1);
+}
+
+static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr,
+			     int *ptr, uint32_t *saved, int print)
+{
+	return atom_get_src_int(ctx,
+				arg | atom_dst_to_src[(attr >> 3) &
+						      7][(attr >> 6) & 3] << 3,
+				ptr, saved, print);
+}
+
+static void atom_skip_dst(atom_exec_context *ctx, int arg, uint8_t attr, int *ptr)
+{
+	atom_skip_src_int(ctx,
+			  arg | atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) &
+								 3] << 3, ptr);
+}
+
+static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
+			 int *ptr, uint32_t val, uint32_t saved)
+{
+	uint32_t align =
+	    atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3], old_val =
+	    val, idx;
+	struct atom_context *gctx = ctx->ctx;
+	old_val &= atom_arg_mask[align] >> atom_arg_shift[align];
+	val <<= atom_arg_shift[align];
+	val &= atom_arg_mask[align];
+	saved &= ~atom_arg_mask[align];
+	val |= saved;
+	switch (arg) {
+	case ATOM_ARG_REG:
+		idx = U16(*ptr);
+		(*ptr) += 2;
+		DEBUG("REG[0x%04X]", idx);
+		idx += gctx->reg_block;
+		switch (gctx->io_mode) {
+		case ATOM_IO_MM:
+			if (idx == 0)
+				gctx->card->reg_write(gctx->card, idx,
+						      val << 2);
+			else
+				gctx->card->reg_write(gctx->card, idx, val);
+			break;
+		case ATOM_IO_PCI:
+			printk(KERN_INFO
+			       "PCI registers are not implemented.\n");
+			return;
+		case ATOM_IO_SYSIO:
+			printk(KERN_INFO
+			       "SYSIO registers are not implemented.\n");
+			return;
+		default:
+			if (!(gctx->io_mode & 0x80)) {
+				printk(KERN_INFO "Bad IO mode.\n");
+				return;
+			}
+			if (!gctx->iio[gctx->io_mode & 0xFF]) {
+				printk(KERN_INFO
+				       "Undefined indirect IO write method %d.\n",
+				       gctx->io_mode & 0x7F);
+				return;
+			}
+			atom_iio_execute(gctx, gctx->iio[gctx->io_mode & 0xFF],
+					 idx, val);
+		}
+		break;
+	case ATOM_ARG_PS:
+		idx = U8(*ptr);
+		(*ptr)++;
+		DEBUG("PS[0x%02X]", idx);
+		ctx->ps[idx] = cpu_to_le32(val);
+		break;
+	case ATOM_ARG_WS:
+		idx = U8(*ptr);
+		(*ptr)++;
+		DEBUG("WS[0x%02X]", idx);
+		switch (idx) {
+		case ATOM_WS_QUOTIENT:
+			gctx->divmul[0] = val;
+			break;
+		case ATOM_WS_REMAINDER:
+			gctx->divmul[1] = val;
+			break;
+		case ATOM_WS_DATAPTR:
+			gctx->data_block = val;
+			break;
+		case ATOM_WS_SHIFT:
+			gctx->shift = val;
+			break;
+		case ATOM_WS_OR_MASK:
+		case ATOM_WS_AND_MASK:
+			break;
+		case ATOM_WS_FB_WINDOW:
+			gctx->fb_base = val;
+			break;
+		case ATOM_WS_ATTRIBUTES:
+			gctx->io_attr = val;
+			break;
+		default:
+			ctx->ws[idx] = val;
+		}
+		break;
+	case ATOM_ARG_FB:
+		idx = U8(*ptr);
+		(*ptr)++;
+		DEBUG("FB[0x%02X]", idx);
+		printk(KERN_INFO "FB access is not implemented.\n");
+		return;
+	case ATOM_ARG_PLL:
+		idx = U8(*ptr);
+		(*ptr)++;
+		DEBUG("PLL[0x%02X]", idx);
+		gctx->card->pll_write(gctx->card, idx, val);
+		break;
+	case ATOM_ARG_MC:
+		idx = U8(*ptr);
+		(*ptr)++;
+		DEBUG("MC[0x%02X]", idx);
+		gctx->card->mc_write(gctx->card, idx, val);
+		return;
+	}
+	switch (align) {
+	case ATOM_SRC_DWORD:
+		DEBUG(".[31:0] <- 0x%08X\n", old_val);
+		break;
+	case ATOM_SRC_WORD0:
+		DEBUG(".[15:0] <- 0x%04X\n", old_val);
+		break;
+	case ATOM_SRC_WORD8:
+		DEBUG(".[23:8] <- 0x%04X\n", old_val);
+		break;
+	case ATOM_SRC_WORD16:
+		DEBUG(".[31:16] <- 0x%04X\n", old_val);
+		break;
+	case ATOM_SRC_BYTE0:
+		DEBUG(".[7:0] <- 0x%02X\n", old_val);
+		break;
+	case ATOM_SRC_BYTE8:
+		DEBUG(".[15:8] <- 0x%02X\n", old_val);
+		break;
+	case ATOM_SRC_BYTE16:
+		DEBUG(".[23:16] <- 0x%02X\n", old_val);
+		break;
+	case ATOM_SRC_BYTE24:
+		DEBUG(".[31:24] <- 0x%02X\n", old_val);
+		break;
+	}
+}
+
+static void atom_op_add(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src, saved;
+	int dptr = *ptr;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	SDEBUG("   src: ");
+	src = atom_get_src(ctx, attr, ptr);
+	dst += src;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_and(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src, saved;
+	int dptr = *ptr;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	SDEBUG("   src: ");
+	src = atom_get_src(ctx, attr, ptr);
+	dst &= src;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg)
+{
+	printk("ATOM BIOS beeped!\n");
+}
+
+static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg)
+{
+	int idx = U8((*ptr)++);
+	if (idx < ATOM_TABLE_NAMES_CNT)
+		SDEBUG("   table: %d (%s)\n", idx, atom_table_names[idx]);
+	else
+		SDEBUG("   table: %d\n", idx);
+	if (U16(ctx->ctx->cmd_table + 4 + 2 * idx))
+		atom_execute_table(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
+}
+
+static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t saved;
+	int dptr = *ptr;
+	attr &= 0x38;
+	attr |= atom_def_dst[attr >> 3] << 6;
+	atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, 0, saved);
+}
+
+static void atom_op_compare(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src;
+	SDEBUG("   src1: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
+	SDEBUG("   src2: ");
+	src = atom_get_src(ctx, attr, ptr);
+	ctx->ctx->cs_equal = (dst == src);
+	ctx->ctx->cs_above = (dst > src);
+	SDEBUG("   result: %s %s\n", ctx->ctx->cs_equal ? "EQ" : "NE",
+	       ctx->ctx->cs_above ? "GT" : "LE");
+}
+
+static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t count = U8((*ptr)++);
+	SDEBUG("   count: %d\n", count);
+	if (arg == ATOM_UNIT_MICROSEC)
+		schedule_timeout_uninterruptible(usecs_to_jiffies(count));
+	else
+		schedule_timeout_uninterruptible(msecs_to_jiffies(count));
+}
+
+static void atom_op_div(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src;
+	SDEBUG("   src1: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
+	SDEBUG("   src2: ");
+	src = atom_get_src(ctx, attr, ptr);
+	if (src != 0) {
+		ctx->ctx->divmul[0] = dst / src;
+		ctx->ctx->divmul[1] = dst % src;
+	} else {
+		ctx->ctx->divmul[0] = 0;
+		ctx->ctx->divmul[1] = 0;
+	}
+}
+
+static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg)
+{
+	/* functionally, a nop */
+}
+
+static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
+{
+	int execute = 0, target = U16(*ptr);
+	(*ptr) += 2;
+	switch (arg) {
+	case ATOM_COND_ABOVE:
+		execute = ctx->ctx->cs_above;
+		break;
+	case ATOM_COND_ABOVEOREQUAL:
+		execute = ctx->ctx->cs_above || ctx->ctx->cs_equal;
+		break;
+	case ATOM_COND_ALWAYS:
+		execute = 1;
+		break;
+	case ATOM_COND_BELOW:
+		execute = !(ctx->ctx->cs_above || ctx->ctx->cs_equal);
+		break;
+	case ATOM_COND_BELOWOREQUAL:
+		execute = !ctx->ctx->cs_above;
+		break;
+	case ATOM_COND_EQUAL:
+		execute = ctx->ctx->cs_equal;
+		break;
+	case ATOM_COND_NOTEQUAL:
+		execute = !ctx->ctx->cs_equal;
+		break;
+	}
+	if (arg != ATOM_COND_ALWAYS)
+		SDEBUG("   taken: %s\n", execute ? "yes" : "no");
+	SDEBUG("   target: 0x%04X\n", target);
+	if (execute)
+		*ptr = ctx->start + target;
+}
+
+static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src1, src2, saved;
+	int dptr = *ptr;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	SDEBUG("   src1: ");
+	src1 = atom_get_src(ctx, attr, ptr);
+	SDEBUG("   src2: ");
+	src2 = atom_get_src(ctx, attr, ptr);
+	dst &= src1;
+	dst |= src2;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_move(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t src, saved;
+	int dptr = *ptr;
+	if (((attr >> 3) & 7) != ATOM_SRC_DWORD)
+		atom_get_dst(ctx, arg, attr, ptr, &saved, 0);
+	else {
+		atom_skip_dst(ctx, arg, attr, ptr);
+		saved = 0xCDCDCDCD;
+	}
+	SDEBUG("   src: ");
+	src = atom_get_src(ctx, attr, ptr);
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, src, saved);
+}
+
+static void atom_op_mul(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src;
+	SDEBUG("   src1: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
+	SDEBUG("   src2: ");
+	src = atom_get_src(ctx, attr, ptr);
+	ctx->ctx->divmul[0] = dst * src;
+}
+
+static void atom_op_nop(atom_exec_context *ctx, int *ptr, int arg)
+{
+	/* nothing */
+}
+
+static void atom_op_or(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src, saved;
+	int dptr = *ptr;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	SDEBUG("   src: ");
+	src = atom_get_src(ctx, attr, ptr);
+	dst |= src;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_postcard(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t val = U8((*ptr)++);
+	SDEBUG("POST card output: 0x%02X\n", val);
+}
+
+static void atom_op_repeat(atom_exec_context *ctx, int *ptr, int arg)
+{
+	printk(KERN_INFO "unimplemented!\n");
+}
+
+static void atom_op_restorereg(atom_exec_context *ctx, int *ptr, int arg)
+{
+	printk(KERN_INFO "unimplemented!\n");
+}
+
+static void atom_op_savereg(atom_exec_context *ctx, int *ptr, int arg)
+{
+	printk(KERN_INFO "unimplemented!\n");
+}
+
+static void atom_op_setdatablock(atom_exec_context *ctx, int *ptr, int arg)
+{
+	int idx = U8(*ptr);
+	(*ptr)++;
+	SDEBUG("   block: %d\n", idx);
+	if (!idx)
+		ctx->ctx->data_block = 0;
+	else if (idx == 255)
+		ctx->ctx->data_block = ctx->start;
+	else
+		ctx->ctx->data_block = U16(ctx->ctx->data_table + 4 + 2 * idx);
+	SDEBUG("   base: 0x%04X\n", ctx->ctx->data_block);
+}
+
+static void atom_op_setfbbase(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	SDEBUG("   fb_base: ");
+	ctx->ctx->fb_base = atom_get_src(ctx, attr, ptr);
+}
+
+static void atom_op_setport(atom_exec_context *ctx, int *ptr, int arg)
+{
+	int port;
+	switch (arg) {
+	case ATOM_PORT_ATI:
+		port = U16(*ptr);
+		if (port < ATOM_IO_NAMES_CNT)
+			SDEBUG("   port: %d (%s)\n", port, atom_io_names[port]);
+		else
+			SDEBUG("   port: %d\n", port);
+		if (!port)
+			ctx->ctx->io_mode = ATOM_IO_MM;
+		else
+			ctx->ctx->io_mode = ATOM_IO_IIO | port;
+		(*ptr) += 2;
+		break;
+	case ATOM_PORT_PCI:
+		ctx->ctx->io_mode = ATOM_IO_PCI;
+		(*ptr)++;
+		break;
+	case ATOM_PORT_SYSIO:
+		ctx->ctx->io_mode = ATOM_IO_SYSIO;
+		(*ptr)++;
+		break;
+	}
+}
+
+static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg)
+{
+	ctx->ctx->reg_block = U16(*ptr);
+	(*ptr) += 2;
+	SDEBUG("   base: 0x%04X\n", ctx->ctx->reg_block);
+}
+
+static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++), shift;
+	uint32_t saved, dst;
+	int dptr = *ptr;
+	attr &= 0x38;
+	attr |= atom_def_dst[attr >> 3] << 6;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	shift = U8((*ptr)++);
+	SDEBUG("   shift: %d\n", shift);
+	dst <<= shift;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++), shift;
+	uint32_t saved, dst;
+	int dptr = *ptr;
+	attr &= 0x38;
+	attr |= atom_def_dst[attr >> 3] << 6;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	shift = U8((*ptr)++);
+	SDEBUG("   shift: %d\n", shift);
+	dst >>= shift;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_sub(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src, saved;
+	int dptr = *ptr;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	SDEBUG("   src: ");
+	src = atom_get_src(ctx, attr, ptr);
+	dst -= src;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_switch(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t src, val, target;
+	SDEBUG("   switch: ");
+	src = atom_get_src(ctx, attr, ptr);
+	while (U16(*ptr) != ATOM_CASE_END)
+		if (U8(*ptr) == ATOM_CASE_MAGIC) {
+			(*ptr)++;
+			SDEBUG("   case: ");
+			val =
+			    atom_get_src(ctx, (attr & 0x38) | ATOM_ARG_IMM,
+					 ptr);
+			target = U16(*ptr);
+			if (val == src) {
+				SDEBUG("   target: %04X\n", target);
+				*ptr = ctx->start + target;
+				return;
+			}
+			(*ptr) += 2;
+		} else {
+			printk(KERN_INFO "Bad case.\n");
+			return;
+		}
+	(*ptr) += 2;
+}
+
+static void atom_op_test(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src;
+	SDEBUG("   src1: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1);
+	SDEBUG("   src2: ");
+	src = atom_get_src(ctx, attr, ptr);
+	ctx->ctx->cs_equal = ((dst & src) == 0);
+	SDEBUG("   result: %s\n", ctx->ctx->cs_equal ? "EQ" : "NE");
+}
+
+static void atom_op_xor(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++);
+	uint32_t dst, src, saved;
+	int dptr = *ptr;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	SDEBUG("   src: ");
+	src = atom_get_src(ctx, attr, ptr);
+	dst ^= src;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_debug(atom_exec_context *ctx, int *ptr, int arg)
+{
+	printk(KERN_INFO "unimplemented!\n");
+}
+
+static struct {
+	void (*func) (atom_exec_context *, int *, int);
+	int arg;
+} opcode_table[ATOM_OP_CNT] = {
+	{
+	NULL, 0}, {
+	atom_op_move, ATOM_ARG_REG}, {
+	atom_op_move, ATOM_ARG_PS}, {
+	atom_op_move, ATOM_ARG_WS}, {
+	atom_op_move, ATOM_ARG_FB}, {
+	atom_op_move, ATOM_ARG_PLL}, {
+	atom_op_move, ATOM_ARG_MC}, {
+	atom_op_and, ATOM_ARG_REG}, {
+	atom_op_and, ATOM_ARG_PS}, {
+	atom_op_and, ATOM_ARG_WS}, {
+	atom_op_and, ATOM_ARG_FB}, {
+	atom_op_and, ATOM_ARG_PLL}, {
+	atom_op_and, ATOM_ARG_MC}, {
+	atom_op_or, ATOM_ARG_REG}, {
+	atom_op_or, ATOM_ARG_PS}, {
+	atom_op_or, ATOM_ARG_WS}, {
+	atom_op_or, ATOM_ARG_FB}, {
+	atom_op_or, ATOM_ARG_PLL}, {
+	atom_op_or, ATOM_ARG_MC}, {
+	atom_op_shl, ATOM_ARG_REG}, {
+	atom_op_shl, ATOM_ARG_PS}, {
+	atom_op_shl, ATOM_ARG_WS}, {
+	atom_op_shl, ATOM_ARG_FB}, {
+	atom_op_shl, ATOM_ARG_PLL}, {
+	atom_op_shl, ATOM_ARG_MC}, {
+	atom_op_shr, ATOM_ARG_REG}, {
+	atom_op_shr, ATOM_ARG_PS}, {
+	atom_op_shr, ATOM_ARG_WS}, {
+	atom_op_shr, ATOM_ARG_FB}, {
+	atom_op_shr, ATOM_ARG_PLL}, {
+	atom_op_shr, ATOM_ARG_MC}, {
+	atom_op_mul, ATOM_ARG_REG}, {
+	atom_op_mul, ATOM_ARG_PS}, {
+	atom_op_mul, ATOM_ARG_WS}, {
+	atom_op_mul, ATOM_ARG_FB}, {
+	atom_op_mul, ATOM_ARG_PLL}, {
+	atom_op_mul, ATOM_ARG_MC}, {
+	atom_op_div, ATOM_ARG_REG}, {
+	atom_op_div, ATOM_ARG_PS}, {
+	atom_op_div, ATOM_ARG_WS}, {
+	atom_op_div, ATOM_ARG_FB}, {
+	atom_op_div, ATOM_ARG_PLL}, {
+	atom_op_div, ATOM_ARG_MC}, {
+	atom_op_add, ATOM_ARG_REG}, {
+	atom_op_add, ATOM_ARG_PS}, {
+	atom_op_add, ATOM_ARG_WS}, {
+	atom_op_add, ATOM_ARG_FB}, {
+	atom_op_add, ATOM_ARG_PLL}, {
+	atom_op_add, ATOM_ARG_MC}, {
+	atom_op_sub, ATOM_ARG_REG}, {
+	atom_op_sub, ATOM_ARG_PS}, {
+	atom_op_sub, ATOM_ARG_WS}, {
+	atom_op_sub, ATOM_ARG_FB}, {
+	atom_op_sub, ATOM_ARG_PLL}, {
+	atom_op_sub, ATOM_ARG_MC}, {
+	atom_op_setport, ATOM_PORT_ATI}, {
+	atom_op_setport, ATOM_PORT_PCI}, {
+	atom_op_setport, ATOM_PORT_SYSIO}, {
+	atom_op_setregblock, 0}, {
+	atom_op_setfbbase, 0}, {
+	atom_op_compare, ATOM_ARG_REG}, {
+	atom_op_compare, ATOM_ARG_PS}, {
+	atom_op_compare, ATOM_ARG_WS}, {
+	atom_op_compare, ATOM_ARG_FB}, {
+	atom_op_compare, ATOM_ARG_PLL}, {
+	atom_op_compare, ATOM_ARG_MC}, {
+	atom_op_switch, 0}, {
+	atom_op_jump, ATOM_COND_ALWAYS}, {
+	atom_op_jump, ATOM_COND_EQUAL}, {
+	atom_op_jump, ATOM_COND_BELOW}, {
+	atom_op_jump, ATOM_COND_ABOVE}, {
+	atom_op_jump, ATOM_COND_BELOWOREQUAL}, {
+	atom_op_jump, ATOM_COND_ABOVEOREQUAL}, {
+	atom_op_jump, ATOM_COND_NOTEQUAL}, {
+	atom_op_test, ATOM_ARG_REG}, {
+	atom_op_test, ATOM_ARG_PS}, {
+	atom_op_test, ATOM_ARG_WS}, {
+	atom_op_test, ATOM_ARG_FB}, {
+	atom_op_test, ATOM_ARG_PLL}, {
+	atom_op_test, ATOM_ARG_MC}, {
+	atom_op_delay, ATOM_UNIT_MILLISEC}, {
+	atom_op_delay, ATOM_UNIT_MICROSEC}, {
+	atom_op_calltable, 0}, {
+	atom_op_repeat, 0}, {
+	atom_op_clear, ATOM_ARG_REG}, {
+	atom_op_clear, ATOM_ARG_PS}, {
+	atom_op_clear, ATOM_ARG_WS}, {
+	atom_op_clear, ATOM_ARG_FB}, {
+	atom_op_clear, ATOM_ARG_PLL}, {
+	atom_op_clear, ATOM_ARG_MC}, {
+	atom_op_nop, 0}, {
+	atom_op_eot, 0}, {
+	atom_op_mask, ATOM_ARG_REG}, {
+	atom_op_mask, ATOM_ARG_PS}, {
+	atom_op_mask, ATOM_ARG_WS}, {
+	atom_op_mask, ATOM_ARG_FB}, {
+	atom_op_mask, ATOM_ARG_PLL}, {
+	atom_op_mask, ATOM_ARG_MC}, {
+	atom_op_postcard, 0}, {
+	atom_op_beep, 0}, {
+	atom_op_savereg, 0}, {
+	atom_op_restorereg, 0}, {
+	atom_op_setdatablock, 0}, {
+	atom_op_xor, ATOM_ARG_REG}, {
+	atom_op_xor, ATOM_ARG_PS}, {
+	atom_op_xor, ATOM_ARG_WS}, {
+	atom_op_xor, ATOM_ARG_FB}, {
+	atom_op_xor, ATOM_ARG_PLL}, {
+	atom_op_xor, ATOM_ARG_MC}, {
+	atom_op_shl, ATOM_ARG_REG}, {
+	atom_op_shl, ATOM_ARG_PS}, {
+	atom_op_shl, ATOM_ARG_WS}, {
+	atom_op_shl, ATOM_ARG_FB}, {
+	atom_op_shl, ATOM_ARG_PLL}, {
+	atom_op_shl, ATOM_ARG_MC}, {
+	atom_op_shr, ATOM_ARG_REG}, {
+	atom_op_shr, ATOM_ARG_PS}, {
+	atom_op_shr, ATOM_ARG_WS}, {
+	atom_op_shr, ATOM_ARG_FB}, {
+	atom_op_shr, ATOM_ARG_PLL}, {
+	atom_op_shr, ATOM_ARG_MC}, {
+atom_op_debug, 0},};
+
+void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+{
+	int base = CU16(ctx->cmd_table + 4 + 2 * index);
+	int len, ws, ps, ptr;
+	unsigned char op;
+	atom_exec_context ectx;
+
+	if (!base)
+		return;
+
+	len = CU16(base + ATOM_CT_SIZE_PTR);
+	ws = CU8(base + ATOM_CT_WS_PTR);
+	ps = CU8(base + ATOM_CT_PS_PTR) & ATOM_CT_PS_MASK;
+	ptr = base + ATOM_CT_CODE_PTR;
+
+	SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps);
+
+	/* reset reg block */
+	ctx->reg_block = 0;
+	ectx.ctx = ctx;
+	ectx.ps_shift = ps / 4;
+	ectx.start = base;
+	ectx.ps = params;
+	if (ws)
+		ectx.ws = kzalloc(4 * ws, GFP_KERNEL);
+	else
+		ectx.ws = NULL;
+
+	debug_depth++;
+	while (1) {
+		op = CU8(ptr++);
+		if (op < ATOM_OP_NAMES_CNT)
+			SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1);
+		else
+			SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1);
+
+		if (op < ATOM_OP_CNT && op > 0)
+			opcode_table[op].func(&ectx, &ptr,
+					      opcode_table[op].arg);
+		else
+			break;
+
+		if (op == ATOM_OP_EOT)
+			break;
+	}
+	debug_depth--;
+	SDEBUG("<<\n");
+
+	if (ws)
+		kfree(ectx.ws);
+}
+
+static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
+
+static void atom_index_iio(struct atom_context *ctx, int base)
+{
+	ctx->iio = kzalloc(2 * 256, GFP_KERNEL);
+	while (CU8(base) == ATOM_IIO_START) {
+		ctx->iio[CU8(base + 1)] = base + 2;
+		base += 2;
+		while (CU8(base) != ATOM_IIO_END)
+			base += atom_iio_len[CU8(base)];
+		base += 3;
+	}
+}
+
+struct atom_context *atom_parse(struct card_info *card, void *bios)
+{
+	int base;
+	struct atom_context *ctx =
+	    kzalloc(sizeof(struct atom_context), GFP_KERNEL);
+	char *str;
+	char name[512];
+	int i;
+
+	ctx->card = card;
+	ctx->bios = bios;
+
+	if (CU16(0) != ATOM_BIOS_MAGIC) {
+		printk(KERN_INFO "Invalid BIOS magic.\n");
+		kfree(ctx);
+		return NULL;
+	}
+	if (strncmp
+	    (CSTR(ATOM_ATI_MAGIC_PTR), ATOM_ATI_MAGIC,
+	     strlen(ATOM_ATI_MAGIC))) {
+		printk(KERN_INFO "Invalid ATI magic.\n");
+		kfree(ctx);
+		return NULL;
+	}
+
+	base = CU16(ATOM_ROM_TABLE_PTR);
+	if (strncmp
+	    (CSTR(base + ATOM_ROM_MAGIC_PTR), ATOM_ROM_MAGIC,
+	     strlen(ATOM_ROM_MAGIC))) {
+		printk(KERN_INFO "Invalid ATOM magic.\n");
+		kfree(ctx);
+		return NULL;
+	}
+
+	ctx->cmd_table = CU16(base + ATOM_ROM_CMD_PTR);
+	ctx->data_table = CU16(base + ATOM_ROM_DATA_PTR);
+	atom_index_iio(ctx, CU16(ctx->data_table + ATOM_DATA_IIO_PTR) + 4);
+
+	str = CSTR(CU16(base + ATOM_ROM_MSG_PTR));
+	while (*str && ((*str == '\n') || (*str == '\r')))
+		str++;
+	/* name string isn't always 0 terminated */
+	for (i = 0; i < 511; i++) {
+		name[i] = str[i];
+		if (name[i] < '.' || name[i] > 'z') {
+			name[i] = 0;
+			break;
+		}
+	}
+	printk(KERN_INFO "ATOM BIOS: %s\n", name);
+
+	return ctx;
+}
+
+int atom_asic_init(struct atom_context *ctx)
+{
+	int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
+	uint32_t ps[16];
+	memset(ps, 0, 64);
+
+	ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR));
+	ps[1] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFMCLK_PTR));
+	if (!ps[0] || !ps[1])
+		return 1;
+
+	if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
+		return 1;
+	atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+
+	return 0;
+}
+
+void atom_destroy(struct atom_context *ctx)
+{
+	if (ctx->iio)
+		kfree(ctx->iio);
+	kfree(ctx);
+}
+
+void atom_parse_data_header(struct atom_context *ctx, int index,
+			    uint16_t * size, uint8_t * frev, uint8_t * crev,
+			    uint16_t * data_start)
+{
+	int offset = index * 2 + 4;
+	int idx = CU16(ctx->data_table + offset);
+
+	if (size)
+		*size = CU16(idx);
+	if (frev)
+		*frev = CU8(idx + 2);
+	if (crev)
+		*crev = CU8(idx + 3);
+	*data_start = idx;
+	return;
+}
+
+void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
+			   uint8_t * crev)
+{
+	int offset = index * 2 + 4;
+	int idx = CU16(ctx->cmd_table + offset);
+
+	if (frev)
+		*frev = CU8(idx + 2);
+	if (crev)
+		*crev = CU8(idx + 3);
+	return;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Stanislaw Skowronek
+ */
+
+#ifndef ATOM_H
+#define ATOM_H
+
+#include <linux/types.h>
+#include "drmP.h"
+
+#define ATOM_BIOS_MAGIC		0xAA55
+#define ATOM_ATI_MAGIC_PTR	0x30
+#define ATOM_ATI_MAGIC		" 761295520"
+#define ATOM_ROM_TABLE_PTR	0x48
+
+#define ATOM_ROM_MAGIC		"ATOM"
+#define ATOM_ROM_MAGIC_PTR	4
+
+#define ATOM_ROM_MSG_PTR	0x10
+#define ATOM_ROM_CMD_PTR	0x1E
+#define ATOM_ROM_DATA_PTR	0x20
+
+#define ATOM_CMD_INIT		0
+#define ATOM_CMD_SETSCLK	0x0A
+#define ATOM_CMD_SETMCLK	0x0B
+#define ATOM_CMD_SETPCLK	0x0C
+
+#define ATOM_DATA_FWI_PTR	0xC
+#define ATOM_DATA_IIO_PTR	0x32
+
+#define ATOM_FWI_DEFSCLK_PTR	8
+#define ATOM_FWI_DEFMCLK_PTR	0xC
+#define ATOM_FWI_MAXSCLK_PTR	0x24
+#define ATOM_FWI_MAXMCLK_PTR	0x28
+
+#define ATOM_CT_SIZE_PTR	0
+#define ATOM_CT_WS_PTR		4
+#define ATOM_CT_PS_PTR		5
+#define ATOM_CT_PS_MASK		0x7F
+#define ATOM_CT_CODE_PTR	6
+
+#define ATOM_OP_CNT		123
+#define ATOM_OP_EOT		91
+
+#define ATOM_CASE_MAGIC		0x63
+#define ATOM_CASE_END		0x5A5A
+
+#define ATOM_ARG_REG		0
+#define ATOM_ARG_PS		1
+#define ATOM_ARG_WS		2
+#define ATOM_ARG_FB		3
+#define ATOM_ARG_ID		4
+#define ATOM_ARG_IMM		5
+#define ATOM_ARG_PLL		6
+#define ATOM_ARG_MC		7
+
+#define ATOM_SRC_DWORD		0
+#define ATOM_SRC_WORD0		1
+#define ATOM_SRC_WORD8		2
+#define ATOM_SRC_WORD16		3
+#define ATOM_SRC_BYTE0		4
+#define ATOM_SRC_BYTE8		5
+#define ATOM_SRC_BYTE16		6
+#define ATOM_SRC_BYTE24		7
+
+#define ATOM_WS_QUOTIENT	0x40
+#define ATOM_WS_REMAINDER	0x41
+#define ATOM_WS_DATAPTR		0x42
+#define ATOM_WS_SHIFT		0x43
+#define ATOM_WS_OR_MASK		0x44
+#define ATOM_WS_AND_MASK	0x45
+#define ATOM_WS_FB_WINDOW	0x46
+#define ATOM_WS_ATTRIBUTES	0x47
+
+#define ATOM_IIO_NOP		0
+#define ATOM_IIO_START		1
+#define ATOM_IIO_READ		2
+#define ATOM_IIO_WRITE		3
+#define ATOM_IIO_CLEAR		4
+#define ATOM_IIO_SET		5
+#define ATOM_IIO_MOVE_INDEX	6
+#define ATOM_IIO_MOVE_ATTR	7
+#define ATOM_IIO_MOVE_DATA	8
+#define ATOM_IIO_END		9
+
+#define ATOM_IO_MM		0
+#define ATOM_IO_PCI		1
+#define ATOM_IO_SYSIO		2
+#define ATOM_IO_IIO		0x80
+
+struct card_info {
+	struct drm_device *dev;
+	void (* reg_write)(struct card_info *, uint32_t, uint32_t);   /*  filled by driver */
+        uint32_t (* reg_read)(struct card_info *, uint32_t);          /*  filled by driver */
+	void (* mc_write)(struct card_info *, uint32_t, uint32_t);   /*  filled by driver */
+        uint32_t (* mc_read)(struct card_info *, uint32_t);          /*  filled by driver */
+	void (* pll_write)(struct card_info *, uint32_t, uint32_t);   /*  filled by driver */
+        uint32_t (* pll_read)(struct card_info *, uint32_t);          /*  filled by driver */
+};
+
+struct atom_context {
+	struct card_info *card;
+	void *bios;
+	uint32_t cmd_table, data_table;
+	uint16_t *iio;
+
+	uint16_t data_block;
+	uint32_t fb_base;
+	uint32_t divmul[2];
+	uint16_t io_attr;
+	uint16_t reg_block;
+	uint8_t shift;
+	int cs_equal, cs_above;
+	int io_mode;
+};
+
+extern int atom_debug;
+
+struct atom_context *atom_parse(struct card_info *, void *);
+void atom_execute_table(struct atom_context *, int, uint32_t *);
+int atom_asic_init(struct atom_context *);
+void atom_destroy(struct atom_context *);
+void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
+void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev);
+#include "atom-types.h"
+#include "atombios.h"
+#include "ObjectID.h"
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom-names.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom-names.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom-names.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom-names.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Stanislaw Skowronek
+ */
+
+#ifndef ATOM_NAMES_H
+#define ATOM_NAMES_H
+
+#include "atom.h"
+
+#ifdef ATOM_DEBUG
+
+#define ATOM_OP_NAMES_CNT 123
+static char *atom_op_names[ATOM_OP_NAMES_CNT] = {
+"RESERVED", "MOVE_REG", "MOVE_PS", "MOVE_WS", "MOVE_FB", "MOVE_PLL",
+"MOVE_MC", "AND_REG", "AND_PS", "AND_WS", "AND_FB", "AND_PLL", "AND_MC",
+"OR_REG", "OR_PS", "OR_WS", "OR_FB", "OR_PLL", "OR_MC", "SHIFT_LEFT_REG",
+"SHIFT_LEFT_PS", "SHIFT_LEFT_WS", "SHIFT_LEFT_FB", "SHIFT_LEFT_PLL",
+"SHIFT_LEFT_MC", "SHIFT_RIGHT_REG", "SHIFT_RIGHT_PS", "SHIFT_RIGHT_WS",
+"SHIFT_RIGHT_FB", "SHIFT_RIGHT_PLL", "SHIFT_RIGHT_MC", "MUL_REG",
+"MUL_PS", "MUL_WS", "MUL_FB", "MUL_PLL", "MUL_MC", "DIV_REG", "DIV_PS",
+"DIV_WS", "DIV_FB", "DIV_PLL", "DIV_MC", "ADD_REG", "ADD_PS", "ADD_WS",
+"ADD_FB", "ADD_PLL", "ADD_MC", "SUB_REG", "SUB_PS", "SUB_WS", "SUB_FB",
+"SUB_PLL", "SUB_MC", "SET_ATI_PORT", "SET_PCI_PORT", "SET_SYS_IO_PORT",
+"SET_REG_BLOCK", "SET_FB_BASE", "COMPARE_REG", "COMPARE_PS",
+"COMPARE_WS", "COMPARE_FB", "COMPARE_PLL", "COMPARE_MC", "SWITCH",
+"JUMP", "JUMP_EQUAL", "JUMP_BELOW", "JUMP_ABOVE", "JUMP_BELOW_OR_EQUAL",
+"JUMP_ABOVE_OR_EQUAL", "JUMP_NOT_EQUAL", "TEST_REG", "TEST_PS", "TEST_WS",
+"TEST_FB", "TEST_PLL", "TEST_MC", "DELAY_MILLISEC", "DELAY_MICROSEC",
+"CALL_TABLE", "REPEAT", "CLEAR_REG", "CLEAR_PS", "CLEAR_WS", "CLEAR_FB",
+"CLEAR_PLL", "CLEAR_MC", "NOP", "EOT", "MASK_REG", "MASK_PS", "MASK_WS",
+"MASK_FB", "MASK_PLL", "MASK_MC", "POST_CARD", "BEEP", "SAVE_REG",
+"RESTORE_REG", "SET_DATA_BLOCK", "XOR_REG", "XOR_PS", "XOR_WS", "XOR_FB",
+"XOR_PLL", "XOR_MC", "SHL_REG", "SHL_PS", "SHL_WS", "SHL_FB", "SHL_PLL",
+"SHL_MC", "SHR_REG", "SHR_PS", "SHR_WS", "SHR_FB", "SHR_PLL", "SHR_MC",
+"DEBUG", "CTB_DS",
+};
+
+#define ATOM_TABLE_NAMES_CNT 74
+static char *atom_table_names[ATOM_TABLE_NAMES_CNT] = {
+"ASIC_Init", "GetDisplaySurfaceSize", "ASIC_RegistersInit",
+"VRAM_BlockVenderDetection", "SetClocksRatio", "MemoryControllerInit",
+"GPIO_PinInit", "MemoryParamAdjust", "DVOEncoderControl",
+"GPIOPinControl", "SetEngineClock", "SetMemoryClock", "SetPixelClock",
+"DynamicClockGating", "ResetMemoryDLL", "ResetMemoryDevice",
+"MemoryPLLInit", "EnableMemorySelfRefresh", "AdjustMemoryController",
+"EnableASIC_StaticPwrMgt", "ASIC_StaticPwrMgtStatusChange",
+"DAC_LoadDetection", "TMDS2EncoderControl", "LCD1OutputControl",
+"DAC1EncoderControl", "DAC2EncoderControl", "DVOOutputControl",
+"CV1OutputControl", "SetCRTC_DPM_State", "TVEncoderControl",
+"TMDS1EncoderControl", "LVDSEncoderControl", "TV1OutputControl",
+"EnableScaler", "BlankCRTC", "EnableCRTC", "GetPixelClock",
+"EnableVGA_Render", "EnableVGA_Access", "SetCRTC_Timing",
+"SetCRTC_OverScan", "SetCRTC_Replication", "SelectCRTC_Source",
+"EnableGraphSurfaces", "UpdateCRTC_DoubleBufferRegisters",
+"LUT_AutoFill", "EnableHW_IconCursor", "GetMemoryClock",
+"GetEngineClock", "SetCRTC_UsingDTDTiming", "TVBootUpStdPinDetection",
+"DFP2OutputControl", "VRAM_BlockDetectionByStrap", "MemoryCleanUp",
+"ReadEDIDFromHWAssistedI2C", "WriteOneByteToHWAssistedI2C",
+"ReadHWAssistedI2CStatus", "SpeedFanControl", "PowerConnectorDetection",
+"MC_Synchronization", "ComputeMemoryEnginePLL", "MemoryRefreshConversion",
+"VRAM_GetCurrentInfoBlock", "DynamicMemorySettings", "MemoryTraining",
+"EnableLVDS_SS", "DFP1OutputControl", "SetVoltage", "CRT1OutputControl",
+"CRT2OutputControl", "SetupHWAssistedI2CStatus", "ClockSource",
+"MemoryDeviceInit", "EnableYUV",
+};
+
+#define ATOM_IO_NAMES_CNT 5
+static char *atom_io_names[ATOM_IO_NAMES_CNT] = {
+"MM", "PLL", "MC", "PCIE", "PCIE PORT",
+};
+
+#else
+
+#define ATOM_OP_NAMES_CNT 0
+#define ATOM_TABLE_NAMES_CNT 0
+#define ATOM_IO_NAMES_CNT 0
+
+#endif
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom-types.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom-types.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/atom-types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/atom-types.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Dave Airlie
+ */
+
+#ifndef ATOM_TYPES_H
+#define ATOM_TYPES_H
+
+/* sync atom types to kernel types */
+
+typedef uint16_t USHORT;
+typedef uint32_t ULONG;
+typedef uint8_t UCHAR;
+
+
+#ifndef ATOM_BIG_ENDIAN
+#if defined(__BIG_ENDIAN)
+#define ATOM_BIG_ENDIAN 1
+#else
+#define ATOM_BIG_ENDIAN 0
+#endif
+#endif
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/Kconfig linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/Kconfig
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,34 @@
+config DRM_RADEON_KMS
+	bool "Enable modesetting on radeon by default"
+	depends on DRM_RADEON
+	select DRM_TTM
+	help
+	  Choose this option if you want kernel modesetting enabled by default,
+	  and you have a new enough userspace to support this. Running old
+	  userspaces with this enabled will cause pain.
+
+	  When kernel modesetting is enabled the IOCTL of radeon/drm
+	  driver are considered as invalid and an error message is printed
+	  in the log and they return failure.
+
+	  KMS enabled userspace will use new API to talk with the radeon/drm
+	  driver. The new API provide functions to create/destroy/share/mmap
+	  buffer object which are then managed by the kernel memory manager
+	  (here TTM). In order to submit command to the GPU the userspace
+	  provide a buffer holding the command stream, along this buffer
+	  userspace have to provide a list of buffer object used by the
+	  command stream. The kernel radeon driver will then place buffer
+	  in GPU accessible memory and will update command stream to reflect
+	  the position of the different buffers.
+
+	  The kernel will also perform security check on command stream
+	  provided by the user, we want to catch and forbid any illegal use
+	  of the GPU such as DMA into random system memory or into memory
+	  not owned by the process supplying the command stream. This part
+	  of the code is still incomplete and this why we propose that patch
+	  as a staging driver addition, future security might forbid current
+	  experimental userspace to run.
+
+	  This code support the following hardware : R1XX,R2XX,R3XX,R4XX,R5XX
+	  (radeon up to X1950). Works is underway to provide support for R6XX,
+	  R7XX and newer hardware (radeon from HD2XXX to HD4XXX).
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/Makefile linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/Makefile
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,18 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 ccflags-y := -Iinclude/drm
-radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o r600_cp.o
+radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
+	radeon_irq.o r300_cmdbuf.o r600_cp.o
+
+radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \
+	radeon_atombios.o radeon_agp.o atombios_crtc.o radeon_combios.o \
+	atom.o radeon_fence.o radeon_ttm.o radeon_object.o radeon_gart.o \
+	radeon_legacy_crtc.o radeon_legacy_encoders.o radeon_connectors.o \
+	radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \
+	radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \
+	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
+	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o \
+	radeon_test.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/ObjectID.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/ObjectID.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/ObjectID.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/ObjectID.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,578 @@
+/*
+* Copyright 2006-2007 Advanced Micro Devices, Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+/* based on stg/asic_reg/drivers/inc/asic_reg/ObjectID.h ver 23 */
+
+#ifndef _OBJECTID_H
+#define _OBJECTID_H
+
+#if defined(_X86_)
+#pragma pack(1)
+#endif
+
+/****************************************************/
+/* Graphics Object Type Definition                  */
+/****************************************************/
+#define GRAPH_OBJECT_TYPE_NONE                    0x0
+#define GRAPH_OBJECT_TYPE_GPU                     0x1
+#define GRAPH_OBJECT_TYPE_ENCODER                 0x2
+#define GRAPH_OBJECT_TYPE_CONNECTOR               0x3
+#define GRAPH_OBJECT_TYPE_ROUTER                  0x4
+/* deleted */
+
+/****************************************************/
+/* Encoder Object ID Definition                     */
+/****************************************************/
+#define ENCODER_OBJECT_ID_NONE                    0x00
+
+/* Radeon Class Display Hardware */
+#define ENCODER_OBJECT_ID_INTERNAL_LVDS           0x01
+#define ENCODER_OBJECT_ID_INTERNAL_TMDS1          0x02
+#define ENCODER_OBJECT_ID_INTERNAL_TMDS2          0x03
+#define ENCODER_OBJECT_ID_INTERNAL_DAC1           0x04
+#define ENCODER_OBJECT_ID_INTERNAL_DAC2           0x05	/* TV/CV DAC */
+#define ENCODER_OBJECT_ID_INTERNAL_SDVOA          0x06
+#define ENCODER_OBJECT_ID_INTERNAL_SDVOB          0x07
+
+/* External Third Party Encoders */
+#define ENCODER_OBJECT_ID_SI170B                  0x08
+#define ENCODER_OBJECT_ID_CH7303                  0x09
+#define ENCODER_OBJECT_ID_CH7301                  0x0A
+#define ENCODER_OBJECT_ID_INTERNAL_DVO1           0x0B	/* This belongs to Radeon Class Display Hardware */
+#define ENCODER_OBJECT_ID_EXTERNAL_SDVOA          0x0C
+#define ENCODER_OBJECT_ID_EXTERNAL_SDVOB          0x0D
+#define ENCODER_OBJECT_ID_TITFP513                0x0E
+#define ENCODER_OBJECT_ID_INTERNAL_LVTM1          0x0F	/* not used for Radeon */
+#define ENCODER_OBJECT_ID_VT1623                  0x10
+#define ENCODER_OBJECT_ID_HDMI_SI1930             0x11
+#define ENCODER_OBJECT_ID_HDMI_INTERNAL           0x12
+/* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
+#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1   0x13
+#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1    0x14
+#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1    0x15
+#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2    0x16	/* Shared with CV/TV and CRT */
+#define ENCODER_OBJECT_ID_SI178                   0X17	/* External TMDS (dual link, no HDCP.) */
+#define ENCODER_OBJECT_ID_MVPU_FPGA               0x18	/* MVPU FPGA chip */
+#define ENCODER_OBJECT_ID_INTERNAL_DDI            0x19
+#define ENCODER_OBJECT_ID_VT1625                  0x1A
+#define ENCODER_OBJECT_ID_HDMI_SI1932             0x1B
+#define ENCODER_OBJECT_ID_DP_AN9801               0x1C
+#define ENCODER_OBJECT_ID_DP_DP501                0x1D
+#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY         0x1E
+#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA   0x1F
+#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1        0x20
+#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2        0x21
+
+#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO    0xFF
+
+/****************************************************/
+/* Connector Object ID Definition                   */
+/****************************************************/
+#define CONNECTOR_OBJECT_ID_NONE                  0x00
+#define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I     0x01
+#define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I       0x02
+#define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D     0x03
+#define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D       0x04
+#define CONNECTOR_OBJECT_ID_VGA                   0x05
+#define CONNECTOR_OBJECT_ID_COMPOSITE             0x06
+#define CONNECTOR_OBJECT_ID_SVIDEO                0x07
+#define CONNECTOR_OBJECT_ID_YPbPr                 0x08
+#define CONNECTOR_OBJECT_ID_D_CONNECTOR           0x09
+#define CONNECTOR_OBJECT_ID_9PIN_DIN              0x0A	/* Supports both CV & TV */
+#define CONNECTOR_OBJECT_ID_SCART                 0x0B
+#define CONNECTOR_OBJECT_ID_HDMI_TYPE_A           0x0C
+#define CONNECTOR_OBJECT_ID_HDMI_TYPE_B           0x0D
+#define CONNECTOR_OBJECT_ID_LVDS                  0x0E
+#define CONNECTOR_OBJECT_ID_7PIN_DIN              0x0F
+#define CONNECTOR_OBJECT_ID_PCIE_CONNECTOR        0x10
+#define CONNECTOR_OBJECT_ID_CROSSFIRE             0x11
+#define CONNECTOR_OBJECT_ID_HARDCODE_DVI          0x12
+#define CONNECTOR_OBJECT_ID_DISPLAYPORT           0x13
+
+/* deleted */
+
+/****************************************************/
+/* Router Object ID Definition                      */
+/****************************************************/
+#define ROUTER_OBJECT_ID_NONE											0x00
+#define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL				0x01
+
+/****************************************************/
+/* Graphics Object ENUM ID Definition               */
+/****************************************************/
+#define GRAPH_OBJECT_ENUM_ID1                     0x01
+#define GRAPH_OBJECT_ENUM_ID2                     0x02
+#define GRAPH_OBJECT_ENUM_ID3                     0x03
+#define GRAPH_OBJECT_ENUM_ID4                     0x04
+#define GRAPH_OBJECT_ENUM_ID5                     0x05
+#define GRAPH_OBJECT_ENUM_ID6                     0x06
+
+/****************************************************/
+/* Graphics Object ID Bit definition                */
+/****************************************************/
+#define OBJECT_ID_MASK                            0x00FF
+#define ENUM_ID_MASK                              0x0700
+#define RESERVED1_ID_MASK                         0x0800
+#define OBJECT_TYPE_MASK                          0x7000
+#define RESERVED2_ID_MASK                         0x8000
+
+#define OBJECT_ID_SHIFT                           0x00
+#define ENUM_ID_SHIFT                             0x08
+#define OBJECT_TYPE_SHIFT                         0x0C
+
+/****************************************************/
+/* Graphics Object family definition                */
+/****************************************************/
+#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) \
+	(GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \
+	 GRAPHICS_OBJECT_ID   << OBJECT_ID_SHIFT)
+/****************************************************/
+/* GPU Object ID definition - Shared with BIOS      */
+/****************************************************/
+#define GPU_ENUM_ID1	(GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\
+			 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT)
+
+/****************************************************/
+/* Encoder Object ID definition - Shared with BIOS  */
+/****************************************************/
+/*
+#define ENCODER_INTERNAL_LVDS_ENUM_ID1        0x2101
+#define ENCODER_INTERNAL_TMDS1_ENUM_ID1       0x2102
+#define ENCODER_INTERNAL_TMDS2_ENUM_ID1       0x2103
+#define ENCODER_INTERNAL_DAC1_ENUM_ID1        0x2104
+#define ENCODER_INTERNAL_DAC2_ENUM_ID1        0x2105
+#define ENCODER_INTERNAL_SDVOA_ENUM_ID1       0x2106
+#define ENCODER_INTERNAL_SDVOB_ENUM_ID1       0x2107
+#define ENCODER_SIL170B_ENUM_ID1              0x2108
+#define ENCODER_CH7303_ENUM_ID1               0x2109
+#define ENCODER_CH7301_ENUM_ID1               0x210A
+#define ENCODER_INTERNAL_DVO1_ENUM_ID1        0x210B
+#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1       0x210C
+#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1       0x210D
+#define ENCODER_TITFP513_ENUM_ID1             0x210E
+#define ENCODER_INTERNAL_LVTM1_ENUM_ID1       0x210F
+#define ENCODER_VT1623_ENUM_ID1               0x2110
+#define ENCODER_HDMI_SI1930_ENUM_ID1          0x2111
+#define ENCODER_HDMI_INTERNAL_ENUM_ID1        0x2112
+#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1   0x2113
+#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1    0x2114
+#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1    0x2115
+#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1    0x2116
+#define ENCODER_SI178_ENUM_ID1                   0x2117
+#define ENCODER_MVPU_FPGA_ENUM_ID1               0x2118
+#define ENCODER_INTERNAL_DDI_ENUM_ID1            0x2119
+#define ENCODER_VT1625_ENUM_ID1                  0x211A
+#define ENCODER_HDMI_SI1932_ENUM_ID1             0x211B
+#define ENCODER_ENCODER_DP_AN9801_ENUM_ID1       0x211C
+#define ENCODER_DP_DP501_ENUM_ID1                0x211D
+#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1         0x211E
+*/
+#define ENCODER_INTERNAL_LVDS_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DAC1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DAC2_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOA_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT)
+
+#define ENCODER_SIL170B_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT)
+
+#define ENCODER_CH7303_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT)
+
+#define ENCODER_CH7301_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DVO1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT)
+
+#define ENCODER_TITFP513_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_VT1623_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_SI1930_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_INTERNAL_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) /* Shared with CV/TV and CRT */
+
+#define ENCODER_SI178_ENUM_ID1  \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT)
+
+#define ENCODER_MVPU_FPGA_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DDI_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT)
+
+#define ENCODER_VT1625_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_SI1932_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT)
+
+#define ENCODER_DP_DP501_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT)
+
+#define ENCODER_DP_AN9801_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
+
+/****************************************************/
+/* Connector Object ID definition - Shared with BIOS */
+/****************************************************/
+/*
+#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1        0x3101
+#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1          0x3102
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1        0x3103
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1          0x3104
+#define CONNECTOR_VGA_ENUM_ID1                      0x3105
+#define CONNECTOR_COMPOSITE_ENUM_ID1                0x3106
+#define CONNECTOR_SVIDEO_ENUM_ID1                   0x3107
+#define CONNECTOR_YPbPr_ENUM_ID1                    0x3108
+#define CONNECTOR_D_CONNECTORE_ENUM_ID1             0x3109
+#define CONNECTOR_9PIN_DIN_ENUM_ID1                 0x310A
+#define CONNECTOR_SCART_ENUM_ID1                    0x310B
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1              0x310C
+#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1              0x310D
+#define CONNECTOR_LVDS_ENUM_ID1                     0x310E
+#define CONNECTOR_7PIN_DIN_ENUM_ID1                 0x310F
+#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1           0x3110
+*/
+#define CONNECTOR_LVDS_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_VGA_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_VGA_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_COMPOSITE_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SVIDEO_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_YPbPr_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_D_CONNECTOR_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_9PIN_DIN_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SCART_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_7PIN_DIN_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_CROSSFIRE_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_CROSSFIRE_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HARDCODE_DVI_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HARDCODE_DVI_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID2 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID3 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID4 \
+	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
+	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+/****************************************************/
+/* Router Object ID definition - Shared with BIOS   */
+/****************************************************/
+#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 \
+	(GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\
+	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+	 ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT)
+
+/* deleted */
+
+/****************************************************/
+/* Object Cap definition - Shared with BIOS         */
+/****************************************************/
+#define GRAPHICS_OBJECT_CAP_I2C                 0x00000001L
+#define GRAPHICS_OBJECT_CAP_TABLE_ID            0x00000002L
+
+#define GRAPHICS_OBJECT_I2CCOMMAND_TABLE_ID                   0x01
+#define GRAPHICS_OBJECT_HOTPLUGDETECTIONINTERUPT_TABLE_ID     0x02
+#define GRAPHICS_OBJECT_ENCODER_OUTPUT_PROTECTION_TABLE_ID    0x03
+
+#if defined(_X86_)
+#pragma pack()
+#endif
+
+#endif /*GRAPHICTYPE */
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r100.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r100.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r100.c	2012-03-22 20:08:02.000000000 -0400
@@ -0,0 +1,2270 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include <linux/seq_file.h>
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_microcode.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+/* This files gather functions specifics to:
+ * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+void r100_hdp_reset(struct radeon_device *rdev);
+void r100_gpu_init(struct radeon_device *rdev);
+int r100_gui_wait_for_idle(struct radeon_device *rdev);
+int r100_mc_wait_for_idle(struct radeon_device *rdev);
+void r100_gpu_wait_for_vsync(struct radeon_device *rdev);
+void r100_gpu_wait_for_vsync2(struct radeon_device *rdev);
+int r100_debugfs_mc_info_init(struct radeon_device *rdev);
+
+
+/*
+ * PCI GART
+ */
+void r100_pci_gart_tlb_flush(struct radeon_device *rdev)
+{
+	/* TODO: can we do somethings here ? */
+	/* It seems hw only cache one entry so we should discard this
+	 * entry otherwise if first GPU GART read hit this entry it
+	 * could end up in wrong address. */
+}
+
+int r100_pci_gart_enable(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int r;
+
+	/* Initialize common gart structure */
+	r = radeon_gart_init(rdev);
+	if (r) {
+		return r;
+	}
+	if (rdev->gart.table.ram.ptr == NULL) {
+		rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
+		r = radeon_gart_table_ram_alloc(rdev);
+		if (r) {
+			return r;
+		}
+	}
+	/* discard memory request outside of configured range */
+	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
+	WREG32(RADEON_AIC_CNTL, tmp);
+	/* set address range for PCI address translate */
+	WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location);
+	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	WREG32(RADEON_AIC_HI_ADDR, tmp);
+	/* Enable bus mastering */
+	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+	WREG32(RADEON_BUS_CNTL, tmp);
+	/* set PCI GART page-table base address */
+	WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr);
+	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
+	WREG32(RADEON_AIC_CNTL, tmp);
+	r100_pci_gart_tlb_flush(rdev);
+	rdev->gart.ready = true;
+	return 0;
+}
+
+void r100_pci_gart_disable(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	/* discard memory request outside of configured range */
+	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
+	WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN);
+	WREG32(RADEON_AIC_LO_ADDR, 0);
+	WREG32(RADEON_AIC_HI_ADDR, 0);
+}
+
+int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
+{
+	if (i < 0 || i > rdev->gart.num_gpu_pages) {
+		return -EINVAL;
+	}
+	rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
+	return 0;
+}
+
+int r100_gart_enable(struct radeon_device *rdev)
+{
+	if (rdev->flags & RADEON_IS_AGP) {
+		r100_pci_gart_disable(rdev);
+		return 0;
+	}
+	return r100_pci_gart_enable(rdev);
+}
+
+
+/*
+ * MC
+ */
+void r100_mc_disable_clients(struct radeon_device *rdev)
+{
+	uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl;
+
+	/* FIXME: is this function correct for rs100,rs200,rs300 ? */
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	/* stop display and memory access */
+	ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL);
+	WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE);
+	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS);
+	crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
+
+	r100_gpu_wait_for_vsync(rdev);
+
+	WREG32(RADEON_CRTC_GEN_CNTL,
+	       (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) |
+	       RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN);
+
+	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+
+		r100_gpu_wait_for_vsync2(rdev);
+		WREG32(RADEON_CRTC2_GEN_CNTL,
+		       (crtc2_gen_cntl &
+		        ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) |
+		       RADEON_CRTC2_DISP_REQ_EN_B);
+	}
+
+	udelay(500);
+}
+
+void r100_mc_setup(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int r;
+
+	r = r100_debugfs_mc_info_init(rdev);
+	if (r) {
+		DRM_ERROR("Failed to register debugfs file for R100 MC !\n");
+	}
+	/* Write VRAM size in case we are limiting it */
+	WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+	/* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM,
+	 * if the aperture is 64MB but we have 32MB VRAM
+	 * we report only 32MB VRAM but we have to set MC_FB_LOCATION
+	 * to 64MB, otherwise the gpu accidentially dies */
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
+	tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
+	WREG32(RADEON_MC_FB_LOCATION, tmp);
+
+	/* Enable bus mastering */
+	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+	WREG32(RADEON_BUS_CNTL, tmp);
+
+	if (rdev->flags & RADEON_IS_AGP) {
+		tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+		tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16);
+		tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16);
+		WREG32(RADEON_MC_AGP_LOCATION, tmp);
+		WREG32(RADEON_AGP_BASE, rdev->mc.agp_base);
+	} else {
+		WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF);
+		WREG32(RADEON_AGP_BASE, 0);
+	}
+
+	tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL;
+	tmp |= (7 << 28);
+	WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE);
+	(void)RREG32(RADEON_HOST_PATH_CNTL);
+	WREG32(RADEON_HOST_PATH_CNTL, tmp);
+	(void)RREG32(RADEON_HOST_PATH_CNTL);
+}
+
+int r100_mc_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+
+	r100_gpu_init(rdev);
+	/* Disable gart which also disable out of gart access */
+	r100_pci_gart_disable(rdev);
+
+	/* Setup GPU memory space */
+	rdev->mc.gtt_location = 0xFFFFFFFFUL;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			printk(KERN_WARNING "[drm] Disabling AGP\n");
+			rdev->flags &= ~RADEON_IS_AGP;
+			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+		} else {
+			rdev->mc.gtt_location = rdev->mc.agp_base;
+		}
+	}
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	r100_mc_disable_clients(rdev);
+	if (r100_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	r100_mc_setup(rdev);
+	return 0;
+}
+
+void r100_mc_fini(struct radeon_device *rdev)
+{
+	r100_pci_gart_disable(rdev);
+	radeon_gart_table_ram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Interrupts
+ */
+int r100_irq_set(struct radeon_device *rdev)
+{
+	uint32_t tmp = 0;
+
+	if (rdev->irq.sw_int) {
+		tmp |= RADEON_SW_INT_ENABLE;
+	}
+	if (rdev->irq.crtc_vblank_int[0]) {
+		tmp |= RADEON_CRTC_VBLANK_MASK;
+	}
+	if (rdev->irq.crtc_vblank_int[1]) {
+		tmp |= RADEON_CRTC2_VBLANK_MASK;
+	}
+	WREG32(RADEON_GEN_INT_CNTL, tmp);
+	return 0;
+}
+
+static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
+{
+	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
+	uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
+		RADEON_CRTC2_VBLANK_STAT;
+
+	if (irqs) {
+		WREG32(RADEON_GEN_INT_STATUS, irqs);
+	}
+	return irqs & irq_mask;
+}
+
+int r100_irq_process(struct radeon_device *rdev)
+{
+	uint32_t status;
+
+	status = r100_irq_ack(rdev);
+	if (!status) {
+		return IRQ_NONE;
+	}
+	while (status) {
+		/* SW interrupt */
+		if (status & RADEON_SW_INT_TEST) {
+			radeon_fence_process(rdev);
+		}
+		/* Vertical blank interrupts */
+		if (status & RADEON_CRTC_VBLANK_STAT) {
+			drm_handle_vblank(rdev->ddev, 0);
+		}
+		if (status & RADEON_CRTC2_VBLANK_STAT) {
+			drm_handle_vblank(rdev->ddev, 1);
+		}
+		status = r100_irq_ack(rdev);
+	}
+	return IRQ_HANDLED;
+}
+
+u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc)
+{
+	if (crtc == 0)
+		return RREG32(RADEON_CRTC_CRNT_FRAME);
+	else
+		return RREG32(RADEON_CRTC2_CRNT_FRAME);
+}
+
+
+/*
+ * Fence emission
+ */
+void r100_fence_ring_emit(struct radeon_device *rdev,
+			  struct radeon_fence *fence)
+{
+	/* Who ever call radeon_fence_emit should call ring_lock and ask
+	 * for enough space (today caller are ib schedule and buffer move) */
+	/* Wait until IDLE & CLEAN */
+	radeon_ring_write(rdev, PACKET0(0x1720, 0));
+	radeon_ring_write(rdev, (1 << 16) | (1 << 17));
+	/* Emit fence sequence & fire IRQ */
+	radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
+	radeon_ring_write(rdev, fence->seq);
+	radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0));
+	radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
+}
+
+
+/*
+ * Writeback
+ */
+int r100_wb_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->wb.wb_obj == NULL) {
+		r = radeon_object_create(rdev, NULL, 4096,
+					 true,
+					 RADEON_GEM_DOMAIN_GTT,
+					 false, &rdev->wb.wb_obj);
+		if (r) {
+			DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r);
+			return r;
+		}
+		r = radeon_object_pin(rdev->wb.wb_obj,
+				      RADEON_GEM_DOMAIN_GTT,
+				      &rdev->wb.gpu_addr);
+		if (r) {
+			DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r);
+			return r;
+		}
+		r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
+		if (r) {
+			DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r);
+			return r;
+		}
+	}
+	WREG32(0x774, rdev->wb.gpu_addr);
+	WREG32(0x70C, rdev->wb.gpu_addr + 1024);
+	WREG32(0x770, 0xff);
+	return 0;
+}
+
+void r100_wb_fini(struct radeon_device *rdev)
+{
+	if (rdev->wb.wb_obj) {
+		radeon_object_kunmap(rdev->wb.wb_obj);
+		radeon_object_unpin(rdev->wb.wb_obj);
+		radeon_object_unref(&rdev->wb.wb_obj);
+		rdev->wb.wb = NULL;
+		rdev->wb.wb_obj = NULL;
+	}
+}
+
+int r100_copy_blit(struct radeon_device *rdev,
+		   uint64_t src_offset,
+		   uint64_t dst_offset,
+		   unsigned num_pages,
+		   struct radeon_fence *fence)
+{
+	uint32_t cur_pages;
+	uint32_t stride_bytes = PAGE_SIZE;
+	uint32_t pitch;
+	uint32_t stride_pixels;
+	unsigned ndw;
+	int num_loops;
+	int r = 0;
+
+	/* radeon limited to 16k stride */
+	stride_bytes &= 0x3fff;
+	/* radeon pitch is /64 */
+	pitch = stride_bytes / 64;
+	stride_pixels = stride_bytes / 4;
+	num_loops = DIV_ROUND_UP(num_pages, 8191);
+
+	/* Ask for enough room for blit + flush + fence */
+	ndw = 64 + (10 * num_loops);
+	r = radeon_ring_lock(rdev, ndw);
+	if (r) {
+		DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw);
+		return -EINVAL;
+	}
+	while (num_pages > 0) {
+		cur_pages = num_pages;
+		if (cur_pages > 8191) {
+			cur_pages = 8191;
+		}
+		num_pages -= cur_pages;
+
+		/* pages are in Y direction - height
+		   page width in X direction - width */
+		radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8));
+		radeon_ring_write(rdev,
+				  RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+				  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+				  RADEON_GMC_SRC_CLIPPING |
+				  RADEON_GMC_DST_CLIPPING |
+				  RADEON_GMC_BRUSH_NONE |
+				  (RADEON_COLOR_FORMAT_ARGB8888 << 8) |
+				  RADEON_GMC_SRC_DATATYPE_COLOR |
+				  RADEON_ROP3_S |
+				  RADEON_DP_SRC_SOURCE_MEMORY |
+				  RADEON_GMC_CLR_CMP_CNTL_DIS |
+				  RADEON_GMC_WR_MSK_DIS);
+		radeon_ring_write(rdev, (pitch << 22) | (src_offset >> 10));
+		radeon_ring_write(rdev, (pitch << 22) | (dst_offset >> 10));
+		radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16));
+		radeon_ring_write(rdev, 0);
+		radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16));
+		radeon_ring_write(rdev, num_pages);
+		radeon_ring_write(rdev, num_pages);
+		radeon_ring_write(rdev, cur_pages | (stride_pixels << 16));
+	}
+	radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL);
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev,
+			  RADEON_WAIT_2D_IDLECLEAN |
+			  RADEON_WAIT_HOST_IDLECLEAN |
+			  RADEON_WAIT_DMA_GUI_IDLE);
+	if (fence) {
+		r = radeon_fence_emit(rdev, fence);
+	}
+	radeon_ring_unlock_commit(rdev);
+	return r;
+}
+
+
+/*
+ * CP
+ */
+void r100_ring_start(struct radeon_device *rdev)
+{
+	int r;
+
+	r = radeon_ring_lock(rdev, 2);
+	if (r) {
+		return;
+	}
+	radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0));
+	radeon_ring_write(rdev,
+			  RADEON_ISYNC_ANY2D_IDLE3D |
+			  RADEON_ISYNC_ANY3D_IDLE2D |
+			  RADEON_ISYNC_WAIT_IDLEGUI |
+			  RADEON_ISYNC_CPSCRATCH_IDLEGUI);
+	radeon_ring_unlock_commit(rdev);
+}
+
+#define r100_cp_load_microcode(rdev) \
+  do { \
+    DRM_ERROR("Missing Free microcode!\n"); \
+    return -EINVAL; \
+  } while (0)
+/*(DEBLOBBED)*/
+
+int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
+{
+	unsigned rb_bufsz;
+	unsigned rb_blksz;
+	unsigned max_fetch;
+	unsigned pre_write_timer;
+	unsigned pre_write_limit;
+	unsigned indirect2_start;
+	unsigned indirect1_start;
+	uint32_t tmp;
+	int r;
+
+	if (r100_debugfs_cp_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for CP !\n");
+	}
+	/* Reset CP */
+	tmp = RREG32(RADEON_CP_CSQ_STAT);
+	if ((tmp & (1 << 31))) {
+		DRM_INFO("radeon: cp busy (0x%08X) resetting\n", tmp);
+		WREG32(RADEON_CP_CSQ_MODE, 0);
+		WREG32(RADEON_CP_CSQ_CNTL, 0);
+		WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP);
+		tmp = RREG32(RADEON_RBBM_SOFT_RESET);
+		mdelay(2);
+		WREG32(RADEON_RBBM_SOFT_RESET, 0);
+		tmp = RREG32(RADEON_RBBM_SOFT_RESET);
+		mdelay(2);
+		tmp = RREG32(RADEON_CP_CSQ_STAT);
+		if ((tmp & (1 << 31))) {
+			DRM_INFO("radeon: cp reset failed (0x%08X)\n", tmp);
+		}
+	} else {
+		DRM_INFO("radeon: cp idle (0x%08X)\n", tmp);
+	}
+	/* Align ring size */
+	rb_bufsz = drm_order(ring_size / 8);
+	ring_size = (1 << (rb_bufsz + 1)) * 4;
+	r100_cp_load_microcode(rdev);
+	r = radeon_ring_init(rdev, ring_size);
+	if (r) {
+		return r;
+	}
+	/* Each time the cp read 1024 bytes (16 dword/quadword) update
+	 * the rptr copy in system ram */
+	rb_blksz = 9;
+	/* cp will read 128bytes at a time (4 dwords) */
+	max_fetch = 1;
+	rdev->cp.align_mask = 16 - 1;
+	/* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */
+	pre_write_timer = 64;
+	/* Force CP_RB_WPTR write if written more than one time before the
+	 * delay expire
+	 */
+	pre_write_limit = 0;
+	/* Setup the cp cache like this (cache size is 96 dwords) :
+	 *	RING		0  to 15
+	 *	INDIRECT1	16 to 79
+	 *	INDIRECT2	80 to 95
+	 * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords))
+	 *    indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords))
+	 *    indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords))
+	 * Idea being that most of the gpu cmd will be through indirect1 buffer
+	 * so it gets the bigger cache.
+	 */
+	indirect2_start = 80;
+	indirect1_start = 16;
+	/* cp setup */
+	WREG32(0x718, pre_write_timer | (pre_write_limit << 28));
+	WREG32(RADEON_CP_RB_CNTL,
+#ifdef __BIG_ENDIAN
+	       RADEON_BUF_SWAP_32BIT |
+#endif
+	       REG_SET(RADEON_RB_BUFSZ, rb_bufsz) |
+	       REG_SET(RADEON_RB_BLKSZ, rb_blksz) |
+	       REG_SET(RADEON_MAX_FETCH, max_fetch) |
+	       RADEON_RB_NO_UPDATE);
+	/* Set ring address */
+	DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr);
+	WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr);
+	/* Force read & write ptr to 0 */
+	tmp = RREG32(RADEON_CP_RB_CNTL);
+	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
+	WREG32(RADEON_CP_RB_RPTR_WR, 0);
+	WREG32(RADEON_CP_RB_WPTR, 0);
+	WREG32(RADEON_CP_RB_CNTL, tmp);
+	udelay(10);
+	rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
+	rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR);
+	/* Set cp mode to bus mastering & enable cp*/
+	WREG32(RADEON_CP_CSQ_MODE,
+	       REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
+	       REG_SET(RADEON_INDIRECT1_START, indirect1_start));
+	WREG32(0x718, 0);
+	WREG32(0x744, 0x00004D4D);
+	WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM);
+	radeon_ring_start(rdev);
+	r = radeon_ring_test(rdev);
+	if (r) {
+		DRM_ERROR("radeon: cp isn't working (%d).\n", r);
+		return r;
+	}
+	rdev->cp.ready = true;
+	return 0;
+}
+
+void r100_cp_fini(struct radeon_device *rdev)
+{
+	/* Disable ring */
+	rdev->cp.ready = false;
+	WREG32(RADEON_CP_CSQ_CNTL, 0);
+	radeon_ring_fini(rdev);
+	DRM_INFO("radeon: cp finalized\n");
+}
+
+void r100_cp_disable(struct radeon_device *rdev)
+{
+	/* Disable ring */
+	rdev->cp.ready = false;
+	WREG32(RADEON_CP_CSQ_MODE, 0);
+	WREG32(RADEON_CP_CSQ_CNTL, 0);
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+}
+
+int r100_cp_reset(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	bool reinit_cp;
+	int i;
+
+	reinit_cp = rdev->cp.ready;
+	rdev->cp.ready = false;
+	WREG32(RADEON_CP_CSQ_MODE, 0);
+	WREG32(RADEON_CP_CSQ_CNTL, 0);
+	WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP);
+	(void)RREG32(RADEON_RBBM_SOFT_RESET);
+	udelay(200);
+	WREG32(RADEON_RBBM_SOFT_RESET, 0);
+	/* Wait to prevent race in RBBM_STATUS */
+	mdelay(1);
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RADEON_RBBM_STATUS);
+		if (!(tmp & (1 << 16))) {
+			DRM_INFO("CP reset succeed (RBBM_STATUS=0x%08X)\n",
+				 tmp);
+			if (reinit_cp) {
+				return r100_cp_init(rdev, rdev->cp.ring_size);
+			}
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	tmp = RREG32(RADEON_RBBM_STATUS);
+	DRM_ERROR("Failed to reset CP (RBBM_STATUS=0x%08X)!\n", tmp);
+	return -1;
+}
+
+
+/*
+ * CS functions
+ */
+int r100_cs_parse_packet0(struct radeon_cs_parser *p,
+			  struct radeon_cs_packet *pkt,
+			  const unsigned *auth, unsigned n,
+			  radeon_packet0_check_t check)
+{
+	unsigned reg;
+	unsigned i, j, m;
+	unsigned idx;
+	int r;
+
+	idx = pkt->idx + 1;
+	reg = pkt->reg;
+	/* Check that register fall into register range
+	 * determined by the number of entry (n) in the
+	 * safe register bitmap.
+	 */
+	if (pkt->one_reg_wr) {
+		if ((reg >> 7) > n) {
+			return -EINVAL;
+		}
+	} else {
+		if (((reg + (pkt->count << 2)) >> 7) > n) {
+			return -EINVAL;
+		}
+	}
+	for (i = 0; i <= pkt->count; i++, idx++) {
+		j = (reg >> 7);
+		m = 1 << ((reg >> 2) & 31);
+		if (auth[j] & m) {
+			r = check(p, pkt, idx, reg);
+			if (r) {
+				return r;
+			}
+		}
+		if (pkt->one_reg_wr) {
+			if (!(auth[j] & m)) {
+				break;
+			}
+		} else {
+			reg += 4;
+		}
+	}
+	return 0;
+}
+
+void r100_cs_dump_packet(struct radeon_cs_parser *p,
+			 struct radeon_cs_packet *pkt)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	volatile uint32_t *ib;
+	unsigned i;
+	unsigned idx;
+
+	ib = p->ib->ptr;
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+	idx = pkt->idx;
+	for (i = 0; i <= (pkt->count + 1); i++, idx++) {
+		DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]);
+	}
+}
+
+/**
+ * r100_cs_packet_parse() - parse cp packet and point ib index to next packet
+ * @parser:	parser structure holding parsing context.
+ * @pkt:	where to store packet informations
+ *
+ * Assume that chunk_ib_index is properly set. Will return -EINVAL
+ * if packet is bigger than remaining ib size. or if packets is unknown.
+ **/
+int r100_cs_packet_parse(struct radeon_cs_parser *p,
+			 struct radeon_cs_packet *pkt,
+			 unsigned idx)
+{
+	struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+	uint32_t header;
+
+	if (idx >= ib_chunk->length_dw) {
+		DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+			  idx, ib_chunk->length_dw);
+		return -EINVAL;
+	}
+	header = ib_chunk->kdata[idx];
+	pkt->idx = idx;
+	pkt->type = CP_PACKET_GET_TYPE(header);
+	pkt->count = CP_PACKET_GET_COUNT(header);
+	switch (pkt->type) {
+	case PACKET_TYPE0:
+		pkt->reg = CP_PACKET0_GET_REG(header);
+		pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header);
+		break;
+	case PACKET_TYPE3:
+		pkt->opcode = CP_PACKET3_GET_OPCODE(header);
+		break;
+	case PACKET_TYPE2:
+		pkt->count = -1;
+		break;
+	default:
+		DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
+		return -EINVAL;
+	}
+	if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
+		DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
+			  pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * r100_cs_packet_next_vline() - parse userspace VLINE packet
+ * @parser:		parser structure holding parsing context.
+ *
+ * Userspace sends a special sequence for VLINE waits.
+ * PACKET0 - VLINE_START_END + value
+ * PACKET0 - WAIT_UNTIL +_value
+ * RELOC (P3) - crtc_id in reloc.
+ *
+ * This function parses this and relocates the VLINE START END
+ * and WAIT UNTIL packets to the correct crtc.
+ * It also detects a switched off crtc and nulls out the
+ * wait in that case.
+ */
+int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	struct drm_mode_object *obj;
+	struct drm_crtc *crtc;
+	struct radeon_crtc *radeon_crtc;
+	struct radeon_cs_packet p3reloc, waitreloc;
+	int crtc_id;
+	int r;
+	uint32_t header, h_idx, reg;
+
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+
+	/* parse the wait until */
+	r = r100_cs_packet_parse(p, &waitreloc, p->idx);
+	if (r)
+		return r;
+
+	/* check its a wait until and only 1 count */
+	if (waitreloc.reg != RADEON_WAIT_UNTIL ||
+	    waitreloc.count != 0) {
+		DRM_ERROR("vline wait had illegal wait until segment\n");
+		r = -EINVAL;
+		return r;
+	}
+
+	if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) {
+		DRM_ERROR("vline wait had illegal wait until\n");
+		r = -EINVAL;
+		return r;
+	}
+
+	/* jump over the NOP */
+	r = r100_cs_packet_parse(p, &p3reloc, p->idx);
+	if (r)
+		return r;
+
+	h_idx = p->idx - 2;
+	p->idx += waitreloc.count;
+	p->idx += p3reloc.count;
+
+	header = ib_chunk->kdata[h_idx];
+	crtc_id = ib_chunk->kdata[h_idx + 5];
+	reg = ib_chunk->kdata[h_idx] >> 2;
+	mutex_lock(&p->rdev->ddev->mode_config.mutex);
+	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
+	if (!obj) {
+		DRM_ERROR("cannot find crtc %d\n", crtc_id);
+		r = -EINVAL;
+		goto out;
+	}
+	crtc = obj_to_crtc(obj);
+	radeon_crtc = to_radeon_crtc(crtc);
+	crtc_id = radeon_crtc->crtc_id;
+
+	if (!crtc->enabled) {
+		/* if the CRTC isn't enabled - we need to nop out the wait until */
+		ib_chunk->kdata[h_idx + 2] = PACKET2(0);
+		ib_chunk->kdata[h_idx + 3] = PACKET2(0);
+	} else if (crtc_id == 1) {
+		switch (reg) {
+		case AVIVO_D1MODE_VLINE_START_END:
+			header &= R300_CP_PACKET0_REG_MASK;
+			header |= AVIVO_D2MODE_VLINE_START_END >> 2;
+			break;
+		case RADEON_CRTC_GUI_TRIG_VLINE:
+			header &= R300_CP_PACKET0_REG_MASK;
+			header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2;
+			break;
+		default:
+			DRM_ERROR("unknown crtc reloc\n");
+			r = -EINVAL;
+			goto out;
+		}
+		ib_chunk->kdata[h_idx] = header;
+		ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
+	}
+out:
+	mutex_unlock(&p->rdev->ddev->mode_config.mutex);
+	return r;
+}
+
+/**
+ * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3
+ * @parser:		parser structure holding parsing context.
+ * @data:		pointer to relocation data
+ * @offset_start:	starting offset
+ * @offset_mask:	offset mask (to align start offset on)
+ * @reloc:		reloc informations
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
+			      struct radeon_cs_reloc **cs_reloc)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	struct radeon_cs_chunk *relocs_chunk;
+	struct radeon_cs_packet p3reloc;
+	unsigned idx;
+	int r;
+
+	if (p->chunk_relocs_idx == -1) {
+		DRM_ERROR("No relocation chunk !\n");
+		return -EINVAL;
+	}
+	*cs_reloc = NULL;
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+	relocs_chunk = &p->chunks[p->chunk_relocs_idx];
+	r = r100_cs_packet_parse(p, &p3reloc, p->idx);
+	if (r) {
+		return r;
+	}
+	p->idx += p3reloc.count + 2;
+	if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+		DRM_ERROR("No packet3 for relocation for packet at %d.\n",
+			  p3reloc.idx);
+		r100_cs_dump_packet(p, &p3reloc);
+		return -EINVAL;
+	}
+	idx = ib_chunk->kdata[p3reloc.idx + 1];
+	if (idx >= relocs_chunk->length_dw) {
+		DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
+			  idx, relocs_chunk->length_dw);
+		r100_cs_dump_packet(p, &p3reloc);
+		return -EINVAL;
+	}
+	/* FIXME: we assume reloc size is 4 dwords */
+	*cs_reloc = p->relocs_ptr[(idx / 4)];
+	return 0;
+}
+
+static int r100_packet0_check(struct radeon_cs_parser *p,
+			      struct radeon_cs_packet *pkt)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	struct radeon_cs_reloc *reloc;
+	volatile uint32_t *ib;
+	uint32_t tmp;
+	unsigned reg;
+	unsigned i;
+	unsigned idx;
+	bool onereg;
+	int r;
+	u32 tile_flags = 0;
+
+	ib = p->ib->ptr;
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+	idx = pkt->idx + 1;
+	reg = pkt->reg;
+	onereg = false;
+	if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) {
+		onereg = true;
+	}
+	for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
+		switch (reg) {
+		case RADEON_CRTC_GUI_TRIG_VLINE:
+			r = r100_cs_packet_parse_vline(p);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+						idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			break;
+		/* FIXME: only allow PACKET3 blit? easier to check for out of
+		 * range access */
+		case RADEON_DST_PITCH_OFFSET:
+		case RADEON_SRC_PITCH_OFFSET:
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			tmp = ib_chunk->kdata[idx] & 0x003fffff;
+			tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
+
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= RADEON_DST_TILE_MACRO;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+				if (reg == RADEON_SRC_PITCH_OFFSET) {
+					DRM_ERROR("Cannot src blit from microtiled surface\n");
+					r100_cs_dump_packet(p, pkt);
+					return -EINVAL;
+				}
+				tile_flags |= RADEON_DST_TILE_MICRO;
+			}
+
+			tmp |= tile_flags;
+			ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
+			break;
+		case RADEON_RB3D_DEPTHOFFSET:
+		case RADEON_RB3D_COLOROFFSET:
+		case R300_RB3D_COLOROFFSET0:
+		case R300_ZB_DEPTHOFFSET:
+		case R200_PP_TXOFFSET_0:
+		case R200_PP_TXOFFSET_1:
+		case R200_PP_TXOFFSET_2:
+		case R200_PP_TXOFFSET_3:
+		case R200_PP_TXOFFSET_4:
+		case R200_PP_TXOFFSET_5:
+		case RADEON_PP_TXOFFSET_0:
+		case RADEON_PP_TXOFFSET_1:
+		case RADEON_PP_TXOFFSET_2:
+		case R300_TX_OFFSET_0:
+		case R300_TX_OFFSET_0+4:
+		case R300_TX_OFFSET_0+8:
+		case R300_TX_OFFSET_0+12:
+		case R300_TX_OFFSET_0+16:
+		case R300_TX_OFFSET_0+20:
+		case R300_TX_OFFSET_0+24:
+		case R300_TX_OFFSET_0+28:
+		case R300_TX_OFFSET_0+32:
+		case R300_TX_OFFSET_0+36:
+		case R300_TX_OFFSET_0+40:
+		case R300_TX_OFFSET_0+44:
+		case R300_TX_OFFSET_0+48:
+		case R300_TX_OFFSET_0+52:
+		case R300_TX_OFFSET_0+56:
+		case R300_TX_OFFSET_0+60:
+			/* rn50 has no 3D engine so fail on any 3d setup */
+			if (ASIC_IS_RN50(p->rdev)) {
+				DRM_ERROR("attempt to use RN50 3D engine failed\n");
+				return -EINVAL;
+			}
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+			break;
+		case R300_RB3D_COLORPITCH0:
+		case RADEON_RB3D_COLORPITCH:
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+				tile_flags |= RADEON_COLOR_TILE_ENABLE;
+			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+				tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
+
+			tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+			tmp |= tile_flags;
+			ib[idx] = tmp;
+			break;
+		case RADEON_RB3D_ZPASS_ADDR:
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					  idx, reg);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+			break;
+		default:
+			/* FIXME: we don't want to allow anyothers packet */
+			break;
+		}
+		if (onereg) {
+			/* FIXME: forbid onereg write to register on relocate */
+			break;
+		}
+	}
+	return 0;
+}
+
+int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
+					 struct radeon_cs_packet *pkt,
+					 struct radeon_object *robj)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	unsigned idx;
+
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+	idx = pkt->idx + 1;
+	if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) {
+		DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
+			  "(need %u have %lu) !\n",
+			  ib_chunk->kdata[idx+2] + 1,
+			  radeon_object_size(robj));
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int r100_packet3_check(struct radeon_cs_parser *p,
+			      struct radeon_cs_packet *pkt)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	struct radeon_cs_reloc *reloc;
+	unsigned idx;
+	unsigned i, c;
+	volatile uint32_t *ib;
+	int r;
+
+	ib = p->ib->ptr;
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+	idx = pkt->idx + 1;
+	switch (pkt->opcode) {
+	case PACKET3_3D_LOAD_VBPNTR:
+		c = ib_chunk->kdata[idx++];
+		for (i = 0; i < (c - 1); i += 2, idx += 3) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset);
+		}
+		if (c & 1) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+		}
+		break;
+	case PACKET3_INDX_BUFFER:
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+		r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
+		if (r) {
+			return r;
+		}
+		break;
+	case 0x23:
+		/* FIXME: cleanup */
+		/* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+		break;
+	case PACKET3_3D_DRAW_IMMD:
+		/* triggers drawing using in-packet vertex data */
+	case PACKET3_3D_DRAW_IMMD_2:
+		/* triggers drawing using in-packet vertex data */
+	case PACKET3_3D_DRAW_VBUF_2:
+		/* triggers drawing of vertex buffers setup elsewhere */
+	case PACKET3_3D_DRAW_INDX_2:
+		/* triggers drawing using indices to vertex buffer */
+	case PACKET3_3D_DRAW_VBUF:
+		/* triggers drawing of vertex buffers setup elsewhere */
+	case PACKET3_3D_DRAW_INDX:
+		/* triggers drawing using indices to vertex buffer */
+	case PACKET3_NOP:
+		break;
+	default:
+		DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int r100_cs_parse(struct radeon_cs_parser *p)
+{
+	struct radeon_cs_packet pkt;
+	int r;
+
+	do {
+		r = r100_cs_packet_parse(p, &pkt, p->idx);
+		if (r) {
+			return r;
+		}
+		p->idx += pkt.count + 2;
+		switch (pkt.type) {
+			case PACKET_TYPE0:
+				r = r100_packet0_check(p, &pkt);
+				break;
+			case PACKET_TYPE2:
+				break;
+			case PACKET_TYPE3:
+				r = r100_packet3_check(p, &pkt);
+				break;
+			default:
+				DRM_ERROR("Unknown packet type %d !\n",
+					  pkt.type);
+				return -EINVAL;
+		}
+		if (r) {
+			return r;
+		}
+	} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+	return 0;
+}
+
+
+/*
+ * Global GPU functions
+ */
+void r100_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+
+	if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) {
+		rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+	}
+
+	if (rdev->family == CHIP_RV100 ||
+	    rdev->family == CHIP_RS100 ||
+	    rdev->family == CHIP_RS200) {
+		rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY;
+	}
+}
+
+/* Wait for vertical sync on primary CRTC */
+void r100_gpu_wait_for_vsync(struct radeon_device *rdev)
+{
+	uint32_t crtc_gen_cntl, tmp;
+	int i;
+
+	crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
+	if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) ||
+	    !(crtc_gen_cntl & RADEON_CRTC_EN)) {
+		return;
+	}
+	/* Clear the CRTC_VBLANK_SAVE bit */
+	WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR);
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RADEON_CRTC_STATUS);
+		if (tmp & RADEON_CRTC_VBLANK_SAVE) {
+			return;
+		}
+		DRM_UDELAY(1);
+	}
+}
+
+/* Wait for vertical sync on secondary CRTC */
+void r100_gpu_wait_for_vsync2(struct radeon_device *rdev)
+{
+	uint32_t crtc2_gen_cntl, tmp;
+	int i;
+
+	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+	if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) ||
+	    !(crtc2_gen_cntl & RADEON_CRTC2_EN))
+		return;
+
+	/* Clear the CRTC_VBLANK_SAVE bit */
+	WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR);
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RADEON_CRTC2_STATUS);
+		if (tmp & RADEON_CRTC2_VBLANK_SAVE) {
+			return;
+		}
+		DRM_UDELAY(1);
+	}
+}
+
+int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK;
+		if (tmp >= n) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+int r100_gui_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) {
+		printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !"
+		       " Bad things might happen.\n");
+	}
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RADEON_RBBM_STATUS);
+		if (!(tmp & (1 << 31))) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+int r100_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32(0x0150);
+		if (tmp & (1 << 2)) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+void r100_gpu_init(struct radeon_device *rdev)
+{
+	/* TODO: anythings to do here ? pipes ? */
+	r100_hdp_reset(rdev);
+}
+
+void r100_hdp_reset(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL;
+	tmp |= (7 << 28);
+	WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE);
+	(void)RREG32(RADEON_HOST_PATH_CNTL);
+	udelay(200);
+	WREG32(RADEON_RBBM_SOFT_RESET, 0);
+	WREG32(RADEON_HOST_PATH_CNTL, tmp);
+	(void)RREG32(RADEON_HOST_PATH_CNTL);
+}
+
+int r100_rb2d_reset(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int i;
+
+	WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2);
+	(void)RREG32(RADEON_RBBM_SOFT_RESET);
+	udelay(200);
+	WREG32(RADEON_RBBM_SOFT_RESET, 0);
+	/* Wait to prevent race in RBBM_STATUS */
+	mdelay(1);
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RADEON_RBBM_STATUS);
+		if (!(tmp & (1 << 26))) {
+			DRM_INFO("RB2D reset succeed (RBBM_STATUS=0x%08X)\n",
+				 tmp);
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	tmp = RREG32(RADEON_RBBM_STATUS);
+	DRM_ERROR("Failed to reset RB2D (RBBM_STATUS=0x%08X)!\n", tmp);
+	return -1;
+}
+
+int r100_gpu_reset(struct radeon_device *rdev)
+{
+	uint32_t status;
+
+	/* reset order likely matter */
+	status = RREG32(RADEON_RBBM_STATUS);
+	/* reset HDP */
+	r100_hdp_reset(rdev);
+	/* reset rb2d */
+	if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
+		r100_rb2d_reset(rdev);
+	}
+	/* TODO: reset 3D engine */
+	/* reset CP */
+	status = RREG32(RADEON_RBBM_STATUS);
+	if (status & (1 << 16)) {
+		r100_cp_reset(rdev);
+	}
+	/* Check if GPU is idle */
+	status = RREG32(RADEON_RBBM_STATUS);
+	if (status & (1 << 31)) {
+		DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
+		return -1;
+	}
+	DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status);
+	return 0;
+}
+
+
+/*
+ * VRAM info
+ */
+static void r100_vram_get_type(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	rdev->mc.vram_is_ddr = false;
+	if (rdev->flags & RADEON_IS_IGP)
+		rdev->mc.vram_is_ddr = true;
+	else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR)
+		rdev->mc.vram_is_ddr = true;
+	if ((rdev->family == CHIP_RV100) ||
+	    (rdev->family == CHIP_RS100) ||
+	    (rdev->family == CHIP_RS200)) {
+		tmp = RREG32(RADEON_MEM_CNTL);
+		if (tmp & RV100_HALF_MODE) {
+			rdev->mc.vram_width = 32;
+		} else {
+			rdev->mc.vram_width = 64;
+		}
+		if (rdev->flags & RADEON_SINGLE_CRTC) {
+			rdev->mc.vram_width /= 4;
+			rdev->mc.vram_is_ddr = true;
+		}
+	} else if (rdev->family <= CHIP_RV280) {
+		tmp = RREG32(RADEON_MEM_CNTL);
+		if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) {
+			rdev->mc.vram_width = 128;
+		} else {
+			rdev->mc.vram_width = 64;
+		}
+	} else {
+		/* newer IGPs */
+		rdev->mc.vram_width = 128;
+	}
+}
+
+static u32 r100_get_accessible_vram(struct radeon_device *rdev)
+{
+	u32 aper_size;
+	u8 byte;
+
+	aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
+
+	/* Set HDP_APER_CNTL only on cards that are known not to be broken,
+	 * that is has the 2nd generation multifunction PCI interface
+	 */
+	if (rdev->family == CHIP_RV280 ||
+	    rdev->family >= CHIP_RV350) {
+		WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
+		       ~RADEON_HDP_APER_CNTL);
+		DRM_INFO("Generation 2 PCI interface, using max accessible memory\n");
+		return aper_size * 2;
+	}
+
+	/* Older cards have all sorts of funny issues to deal with. First
+	 * check if it's a multifunction card by reading the PCI config
+	 * header type... Limit those to one aperture size
+	 */
+	pci_read_config_byte(rdev->pdev, 0xe, &byte);
+	if (byte & 0x80) {
+		DRM_INFO("Generation 1 PCI interface in multifunction mode\n");
+		DRM_INFO("Limiting VRAM to one aperture\n");
+		return aper_size;
+	}
+
+	/* Single function older card. We read HDP_APER_CNTL to see how the BIOS
+	 * have set it up. We don't write this as it's broken on some ASICs but
+	 * we expect the BIOS to have done the right thing (might be too optimistic...)
+	 */
+	if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL)
+		return aper_size * 2;
+	return aper_size;
+}
+
+void r100_vram_init_sizes(struct radeon_device *rdev)
+{
+	u64 config_aper_size;
+	u32 accessible;
+
+	config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		uint32_t tom;
+		/* read NB_TOM to get the amount of ram stolen for the GPU */
+		tom = RREG32(RADEON_NB_TOM);
+		rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
+		/* for IGPs we need to keep VRAM where it was put by the BIOS */
+		rdev->mc.vram_location = (tom & 0xffff) << 16;
+		WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+		rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+	} else {
+		rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
+		/* Some production boards of m6 will report 0
+		 * if it's 8 MB
+		 */
+		if (rdev->mc.real_vram_size == 0) {
+			rdev->mc.real_vram_size = 8192 * 1024;
+			WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+		}
+		/* let driver place VRAM */
+		rdev->mc.vram_location = 0xFFFFFFFFUL;
+		 /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 
+		  * Novell bug 204882 + along with lots of ubuntu ones */
+		if (config_aper_size > rdev->mc.real_vram_size)
+			rdev->mc.mc_vram_size = config_aper_size;
+		else
+			rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+	}
+
+	/* work out accessible VRAM */
+	accessible = r100_get_accessible_vram(rdev);
+
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+
+	if (accessible > rdev->mc.aper_size)
+		accessible = rdev->mc.aper_size;
+
+	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+		rdev->mc.mc_vram_size = rdev->mc.aper_size;
+
+	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
+		rdev->mc.real_vram_size = rdev->mc.aper_size;
+}
+
+void r100_vram_info(struct radeon_device *rdev)
+{
+	r100_vram_get_type(rdev);
+
+	r100_vram_init_sizes(rdev);
+}
+
+
+/*
+ * Indirect registers accessor
+ */
+void r100_pll_errata_after_index(struct radeon_device *rdev)
+{
+	if (!(rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS)) {
+		return;
+	}
+	(void)RREG32(RADEON_CLOCK_CNTL_DATA);
+	(void)RREG32(RADEON_CRTC_GEN_CNTL);
+}
+
+static void r100_pll_errata_after_data(struct radeon_device *rdev)
+{
+	/* This workarounds is necessary on RV100, RS100 and RS200 chips
+	 * or the chip could hang on a subsequent access
+	 */
+	if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) {
+		udelay(5000);
+	}
+
+	/* This function is required to workaround a hardware bug in some (all?)
+	 * revisions of the R300.  This workaround should be called after every
+	 * CLOCK_CNTL_INDEX register access.  If not, register reads afterward
+	 * may not be correct.
+	 */
+	if (rdev->pll_errata & CHIP_ERRATA_R300_CG) {
+		uint32_t save, tmp;
+
+		save = RREG32(RADEON_CLOCK_CNTL_INDEX);
+		tmp = save & ~(0x3f | RADEON_PLL_WR_EN);
+		WREG32(RADEON_CLOCK_CNTL_INDEX, tmp);
+		tmp = RREG32(RADEON_CLOCK_CNTL_DATA);
+		WREG32(RADEON_CLOCK_CNTL_INDEX, save);
+	}
+}
+
+uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t data;
+
+	WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f);
+	r100_pll_errata_after_index(rdev);
+	data = RREG32(RADEON_CLOCK_CNTL_DATA);
+	r100_pll_errata_after_data(rdev);
+	return data;
+}
+
+void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN));
+	r100_pll_errata_after_index(rdev);
+	WREG32(RADEON_CLOCK_CNTL_DATA, v);
+	r100_pll_errata_after_data(rdev);
+}
+
+int r100_init(struct radeon_device *rdev)
+{
+	return 0;
+}
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int r100_debugfs_rbbm_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t reg, value;
+	unsigned i;
+
+	seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS));
+	seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C));
+	seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT));
+	for (i = 0; i < 64; i++) {
+		WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100);
+		reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2;
+		WREG32(RADEON_RBBM_CMDFIFO_ADDR, i);
+		value = RREG32(RADEON_RBBM_CMDFIFO_DATA);
+		seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value);
+	}
+	return 0;
+}
+
+static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t rdp, wdp;
+	unsigned count, i, j;
+
+	radeon_ring_free_size(rdev);
+	rdp = RREG32(RADEON_CP_RB_RPTR);
+	wdp = RREG32(RADEON_CP_RB_WPTR);
+	count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask;
+	seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT));
+	seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp);
+	seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp);
+	seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw);
+	seq_printf(m, "%u dwords in ring\n", count);
+	for (j = 0; j <= count; j++) {
+		i = (rdp + j) & rdev->cp.ptr_mask;
+		seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]);
+	}
+	return 0;
+}
+
+
+static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t csq_stat, csq2_stat, tmp;
+	unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr;
+	unsigned i;
+
+	seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT));
+	seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE));
+	csq_stat = RREG32(RADEON_CP_CSQ_STAT);
+	csq2_stat = RREG32(RADEON_CP_CSQ2_STAT);
+	r_rptr = (csq_stat >> 0) & 0x3ff;
+	r_wptr = (csq_stat >> 10) & 0x3ff;
+	ib1_rptr = (csq_stat >> 20) & 0x3ff;
+	ib1_wptr = (csq2_stat >> 0) & 0x3ff;
+	ib2_rptr = (csq2_stat >> 10) & 0x3ff;
+	ib2_wptr = (csq2_stat >> 20) & 0x3ff;
+	seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat);
+	seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat);
+	seq_printf(m, "Ring rptr %u\n", r_rptr);
+	seq_printf(m, "Ring wptr %u\n", r_wptr);
+	seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr);
+	seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr);
+	seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr);
+	seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr);
+	/* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms
+	 * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */
+	seq_printf(m, "Ring fifo:\n");
+	for (i = 0; i < 256; i++) {
+		WREG32(RADEON_CP_CSQ_ADDR, i << 2);
+		tmp = RREG32(RADEON_CP_CSQ_DATA);
+		seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp);
+	}
+	seq_printf(m, "Indirect1 fifo:\n");
+	for (i = 256; i <= 512; i++) {
+		WREG32(RADEON_CP_CSQ_ADDR, i << 2);
+		tmp = RREG32(RADEON_CP_CSQ_DATA);
+		seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp);
+	}
+	seq_printf(m, "Indirect2 fifo:\n");
+	for (i = 640; i < ib1_wptr; i++) {
+		WREG32(RADEON_CP_CSQ_ADDR, i << 2);
+		tmp = RREG32(RADEON_CP_CSQ_DATA);
+		seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp);
+	}
+	return 0;
+}
+
+static int r100_debugfs_mc_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = RREG32(RADEON_CONFIG_MEMSIZE);
+	seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_MC_FB_LOCATION);
+	seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_BUS_CNTL);
+	seq_printf(m, "BUS_CNTL 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_MC_AGP_LOCATION);
+	seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_AGP_BASE);
+	seq_printf(m, "AGP_BASE 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_HOST_PATH_CNTL);
+	seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp);
+	tmp = RREG32(0x01D0);
+	seq_printf(m, "AIC_CTRL 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_AIC_LO_ADDR);
+	seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_AIC_HI_ADDR);
+	seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp);
+	tmp = RREG32(0x01E4);
+	seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp);
+	return 0;
+}
+
+static struct drm_info_list r100_debugfs_rbbm_list[] = {
+	{"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL},
+};
+
+static struct drm_info_list r100_debugfs_cp_list[] = {
+	{"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL},
+	{"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL},
+};
+
+static struct drm_info_list r100_debugfs_mc_info_list[] = {
+	{"r100_mc_info", r100_debugfs_mc_info, 0, NULL},
+};
+#endif
+
+int r100_debugfs_rbbm_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1);
+#else
+	return 0;
+#endif
+}
+
+int r100_debugfs_cp_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2);
+#else
+	return 0;
+#endif
+}
+
+int r100_debugfs_mc_info_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1);
+#else
+	return 0;
+#endif
+}
+
+int r100_set_surface_reg(struct radeon_device *rdev, int reg,
+			 uint32_t tiling_flags, uint32_t pitch,
+			 uint32_t offset, uint32_t obj_size)
+{
+	int surf_index = reg * 16;
+	int flags = 0;
+
+	/* r100/r200 divide by 16 */
+	if (rdev->family < CHIP_R300)
+		flags = pitch / 16;
+	else
+		flags = pitch / 8;
+
+	if (rdev->family <= CHIP_RS200) {
+		if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
+				 == (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
+			flags |= RADEON_SURF_TILE_COLOR_BOTH;
+		if (tiling_flags & RADEON_TILING_MACRO)
+			flags |= RADEON_SURF_TILE_COLOR_MACRO;
+	} else if (rdev->family <= CHIP_RV280) {
+		if (tiling_flags & (RADEON_TILING_MACRO))
+			flags |= R200_SURF_TILE_COLOR_MACRO;
+		if (tiling_flags & RADEON_TILING_MICRO)
+			flags |= R200_SURF_TILE_COLOR_MICRO;
+	} else {
+		if (tiling_flags & RADEON_TILING_MACRO)
+			flags |= R300_SURF_TILE_MACRO;
+		if (tiling_flags & RADEON_TILING_MICRO)
+			flags |= R300_SURF_TILE_MICRO;
+	}
+
+	DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
+	WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
+	WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
+	WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1);
+	return 0;
+}
+
+void r100_clear_surface_reg(struct radeon_device *rdev, int reg)
+{
+	int surf_index = reg * 16;
+	WREG32(RADEON_SURFACE0_INFO + surf_index, 0);
+}
+
+void r100_bandwidth_update(struct radeon_device *rdev)
+{
+	fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff;
+	fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff;
+	fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff;
+	uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
+	fixed20_12 memtcas_ff[8] = {
+		fixed_init(1),
+		fixed_init(2),
+		fixed_init(3),
+		fixed_init(0),
+		fixed_init_half(1),
+		fixed_init_half(2),
+		fixed_init(0),
+	};
+	fixed20_12 memtcas_rs480_ff[8] = {
+		fixed_init(0),
+		fixed_init(1),
+		fixed_init(2),
+		fixed_init(3),
+		fixed_init(0),
+		fixed_init_half(1),
+		fixed_init_half(2),
+		fixed_init_half(3),
+	};
+	fixed20_12 memtcas2_ff[8] = {
+		fixed_init(0),
+		fixed_init(1),
+		fixed_init(2),
+		fixed_init(3),
+		fixed_init(4),
+		fixed_init(5),
+		fixed_init(6),
+		fixed_init(7),
+	};
+	fixed20_12 memtrbs[8] = {
+		fixed_init(1),
+		fixed_init_half(1),
+		fixed_init(2),
+		fixed_init_half(2),
+		fixed_init(3),
+		fixed_init_half(3),
+		fixed_init(4),
+		fixed_init_half(4)
+	};
+	fixed20_12 memtrbs_r4xx[8] = {
+		fixed_init(4),
+		fixed_init(5),
+		fixed_init(6),
+		fixed_init(7),
+		fixed_init(8),
+		fixed_init(9),
+		fixed_init(10),
+		fixed_init(11)
+	};
+	fixed20_12 min_mem_eff;
+	fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
+	fixed20_12 cur_latency_mclk, cur_latency_sclk;
+	fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate,
+		disp_drain_rate2, read_return_rate;
+	fixed20_12 time_disp1_drop_priority;
+	int c;
+	int cur_size = 16;       /* in octawords */
+	int critical_point = 0, critical_point2;
+/* 	uint32_t read_return_rate, time_disp1_drop_priority; */
+	int stop_req, max_stop_req;
+	struct drm_display_mode *mode1 = NULL;
+	struct drm_display_mode *mode2 = NULL;
+	uint32_t pixel_bytes1 = 0;
+	uint32_t pixel_bytes2 = 0;
+
+	if (rdev->mode_info.crtcs[0]->base.enabled) {
+		mode1 = &rdev->mode_info.crtcs[0]->base.mode;
+		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
+	}
+	if (rdev->mode_info.crtcs[1]->base.enabled) {
+		mode2 = &rdev->mode_info.crtcs[1]->base.mode;
+		pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
+	}
+
+	min_mem_eff.full = rfixed_const_8(0);
+	/* get modes */
+	if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) {
+		uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER);
+		mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
+		mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
+		/* check crtc enables */
+		if (mode2)
+			mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
+		if (mode1)
+			mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
+		WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+	}
+
+	/*
+	 * determine is there is enough bw for current mode
+	 */
+	mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
+	temp_ff.full = rfixed_const(100);
+	mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
+	sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
+	sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
+
+	temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
+	temp_ff.full = rfixed_const(temp);
+	mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
+
+	pix_clk.full = 0;
+	pix_clk2.full = 0;
+	peak_disp_bw.full = 0;
+	if (mode1) {
+		temp_ff.full = rfixed_const(1000);
+		pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
+		pix_clk.full = rfixed_div(pix_clk, temp_ff);
+		temp_ff.full = rfixed_const(pixel_bytes1);
+		peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
+	}
+	if (mode2) {
+		temp_ff.full = rfixed_const(1000);
+		pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
+		pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
+		temp_ff.full = rfixed_const(pixel_bytes2);
+		peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
+	}
+
+	mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
+	if (peak_disp_bw.full >= mem_bw.full) {
+		DRM_ERROR("You may not have enough display bandwidth for current mode\n"
+			  "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
+	}
+
+	/*  Get values from the EXT_MEM_CNTL register...converting its contents. */
+	temp = RREG32(RADEON_MEM_TIMING_CNTL);
+	if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */
+		mem_trcd = ((temp >> 2) & 0x3) + 1;
+		mem_trp  = ((temp & 0x3)) + 1;
+		mem_tras = ((temp & 0x70) >> 4) + 1;
+	} else if (rdev->family == CHIP_R300 ||
+		   rdev->family == CHIP_R350) { /* r300, r350 */
+		mem_trcd = (temp & 0x7) + 1;
+		mem_trp = ((temp >> 8) & 0x7) + 1;
+		mem_tras = ((temp >> 11) & 0xf) + 4;
+	} else if (rdev->family == CHIP_RV350 ||
+		   rdev->family <= CHIP_RV380) {
+		/* rv3x0 */
+		mem_trcd = (temp & 0x7) + 3;
+		mem_trp = ((temp >> 8) & 0x7) + 3;
+		mem_tras = ((temp >> 11) & 0xf) + 6;
+	} else if (rdev->family == CHIP_R420 ||
+		   rdev->family == CHIP_R423 ||
+		   rdev->family == CHIP_RV410) {
+		/* r4xx */
+		mem_trcd = (temp & 0xf) + 3;
+		if (mem_trcd > 15)
+			mem_trcd = 15;
+		mem_trp = ((temp >> 8) & 0xf) + 3;
+		if (mem_trp > 15)
+			mem_trp = 15;
+		mem_tras = ((temp >> 12) & 0x1f) + 6;
+		if (mem_tras > 31)
+			mem_tras = 31;
+	} else { /* RV200, R200 */
+		mem_trcd = (temp & 0x7) + 1;
+		mem_trp = ((temp >> 8) & 0x7) + 1;
+		mem_tras = ((temp >> 12) & 0xf) + 4;
+	}
+	/* convert to FF */
+	trcd_ff.full = rfixed_const(mem_trcd);
+	trp_ff.full = rfixed_const(mem_trp);
+	tras_ff.full = rfixed_const(mem_tras);
+
+	/* Get values from the MEM_SDRAM_MODE_REG register...converting its */
+	temp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
+	data = (temp & (7 << 20)) >> 20;
+	if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) {
+		if (rdev->family == CHIP_RS480) /* don't think rs400 */
+			tcas_ff = memtcas_rs480_ff[data];
+		else
+			tcas_ff = memtcas_ff[data];
+	} else
+		tcas_ff = memtcas2_ff[data];
+
+	if (rdev->family == CHIP_RS400 ||
+	    rdev->family == CHIP_RS480) {
+		/* extra cas latency stored in bits 23-25 0-4 clocks */
+		data = (temp >> 23) & 0x7;
+		if (data < 5)
+			tcas_ff.full += rfixed_const(data);
+	}
+
+	if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
+		/* on the R300, Tcas is included in Trbs.
+		 */
+		temp = RREG32(RADEON_MEM_CNTL);
+		data = (R300_MEM_NUM_CHANNELS_MASK & temp);
+		if (data == 1) {
+			if (R300_MEM_USE_CD_CH_ONLY & temp) {
+				temp = RREG32(R300_MC_IND_INDEX);
+				temp &= ~R300_MC_IND_ADDR_MASK;
+				temp |= R300_MC_READ_CNTL_CD_mcind;
+				WREG32(R300_MC_IND_INDEX, temp);
+				temp = RREG32(R300_MC_IND_DATA);
+				data = (R300_MEM_RBS_POSITION_C_MASK & temp);
+			} else {
+				temp = RREG32(R300_MC_READ_CNTL_AB);
+				data = (R300_MEM_RBS_POSITION_A_MASK & temp);
+			}
+		} else {
+			temp = RREG32(R300_MC_READ_CNTL_AB);
+			data = (R300_MEM_RBS_POSITION_A_MASK & temp);
+		}
+		if (rdev->family == CHIP_RV410 ||
+		    rdev->family == CHIP_R420 ||
+		    rdev->family == CHIP_R423)
+			trbs_ff = memtrbs_r4xx[data];
+		else
+			trbs_ff = memtrbs[data];
+		tcas_ff.full += trbs_ff.full;
+	}
+
+	sclk_eff_ff.full = sclk_ff.full;
+
+	if (rdev->flags & RADEON_IS_AGP) {
+		fixed20_12 agpmode_ff;
+		agpmode_ff.full = rfixed_const(radeon_agpmode);
+		temp_ff.full = rfixed_const_666(16);
+		sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff);
+	}
+	/* TODO PCIE lanes may affect this - agpmode == 16?? */
+
+	if (ASIC_IS_R300(rdev)) {
+		sclk_delay_ff.full = rfixed_const(250);
+	} else {
+		if ((rdev->family == CHIP_RV100) ||
+		    rdev->flags & RADEON_IS_IGP) {
+			if (rdev->mc.vram_is_ddr)
+				sclk_delay_ff.full = rfixed_const(41);
+			else
+				sclk_delay_ff.full = rfixed_const(33);
+		} else {
+			if (rdev->mc.vram_width == 128)
+				sclk_delay_ff.full = rfixed_const(57);
+			else
+				sclk_delay_ff.full = rfixed_const(41);
+		}
+	}
+
+	mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff);
+
+	if (rdev->mc.vram_is_ddr) {
+		if (rdev->mc.vram_width == 32) {
+			k1.full = rfixed_const(40);
+			c  = 3;
+		} else {
+			k1.full = rfixed_const(20);
+			c  = 1;
+		}
+	} else {
+		k1.full = rfixed_const(40);
+		c  = 3;
+	}
+
+	temp_ff.full = rfixed_const(2);
+	mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff);
+	temp_ff.full = rfixed_const(c);
+	mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff);
+	temp_ff.full = rfixed_const(4);
+	mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff);
+	mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff);
+	mc_latency_mclk.full += k1.full;
+
+	mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff);
+	mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff);
+
+	/*
+	  HW cursor time assuming worst case of full size colour cursor.
+	*/
+	temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1))));
+	temp_ff.full += trcd_ff.full;
+	if (temp_ff.full < tras_ff.full)
+		temp_ff.full = tras_ff.full;
+	cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff);
+
+	temp_ff.full = rfixed_const(cur_size);
+	cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff);
+	/*
+	  Find the total latency for the display data.
+	*/
+	disp_latency_overhead.full = rfixed_const(80);
+	disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
+	mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
+	mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
+
+	if (mc_latency_mclk.full > mc_latency_sclk.full)
+		disp_latency.full = mc_latency_mclk.full;
+	else
+		disp_latency.full = mc_latency_sclk.full;
+
+	/* setup Max GRPH_STOP_REQ default value */
+	if (ASIC_IS_RV100(rdev))
+		max_stop_req = 0x5c;
+	else
+		max_stop_req = 0x7c;
+
+	if (mode1) {
+		/*  CRTC1
+		    Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
+		    GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
+		*/
+		stop_req = mode1->hdisplay * pixel_bytes1 / 16;
+
+		if (stop_req > max_stop_req)
+			stop_req = max_stop_req;
+
+		/*
+		  Find the drain rate of the display buffer.
+		*/
+		temp_ff.full = rfixed_const((16/pixel_bytes1));
+		disp_drain_rate.full = rfixed_div(pix_clk, temp_ff);
+
+		/*
+		  Find the critical point of the display buffer.
+		*/
+		crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency);
+		crit_point_ff.full += rfixed_const_half(0);
+
+		critical_point = rfixed_trunc(crit_point_ff);
+
+		if (rdev->disp_priority == 2) {
+			critical_point = 0;
+		}
+
+		/*
+		  The critical point should never be above max_stop_req-4.  Setting
+		  GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
+		*/
+		if (max_stop_req - critical_point < 4)
+			critical_point = 0;
+
+		if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) {
+			/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
+			critical_point = 0x10;
+		}
+
+		temp = RREG32(RADEON_GRPH_BUFFER_CNTL);
+		temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
+		temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
+		temp &= ~(RADEON_GRPH_START_REQ_MASK);
+		if ((rdev->family == CHIP_R350) &&
+		    (stop_req > 0x15)) {
+			stop_req -= 0x10;
+		}
+		temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+		temp |= RADEON_GRPH_BUFFER_SIZE;
+		temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
+			  RADEON_GRPH_CRITICAL_AT_SOF |
+			  RADEON_GRPH_STOP_CNTL);
+		/*
+		  Write the result into the register.
+		*/
+		WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
+						       (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+
+#if 0
+		if ((rdev->family == CHIP_RS400) ||
+		    (rdev->family == CHIP_RS480)) {
+			/* attempt to program RS400 disp regs correctly ??? */
+			temp = RREG32(RS400_DISP1_REG_CNTL);
+			temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
+				  RS400_DISP1_STOP_REQ_LEVEL_MASK);
+			WREG32(RS400_DISP1_REQ_CNTL1, (temp |
+						       (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
+						       (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
+			temp = RREG32(RS400_DMIF_MEM_CNTL1);
+			temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
+				  RS400_DISP1_CRITICAL_POINT_STOP_MASK);
+			WREG32(RS400_DMIF_MEM_CNTL1, (temp |
+						      (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
+						      (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
+		}
+#endif
+
+		DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n",
+			  /* 	  (unsigned int)info->SavedReg->grph_buffer_cntl, */
+			  (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL));
+	}
+
+	if (mode2) {
+		u32 grph2_cntl;
+		stop_req = mode2->hdisplay * pixel_bytes2 / 16;
+
+		if (stop_req > max_stop_req)
+			stop_req = max_stop_req;
+
+		/*
+		  Find the drain rate of the display buffer.
+		*/
+		temp_ff.full = rfixed_const((16/pixel_bytes2));
+		disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff);
+
+		grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL);
+		grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK);
+		grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
+		grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK);
+		if ((rdev->family == CHIP_R350) &&
+		    (stop_req > 0x15)) {
+			stop_req -= 0x10;
+		}
+		grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+		grph2_cntl |= RADEON_GRPH_BUFFER_SIZE;
+		grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL   |
+			  RADEON_GRPH_CRITICAL_AT_SOF |
+			  RADEON_GRPH_STOP_CNTL);
+
+		if ((rdev->family == CHIP_RS100) ||
+		    (rdev->family == CHIP_RS200))
+			critical_point2 = 0;
+		else {
+			temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128;
+			temp_ff.full = rfixed_const(temp);
+			temp_ff.full = rfixed_mul(mclk_ff, temp_ff);
+			if (sclk_ff.full < temp_ff.full)
+				temp_ff.full = sclk_ff.full;
+
+			read_return_rate.full = temp_ff.full;
+
+			if (mode1) {
+				temp_ff.full = read_return_rate.full - disp_drain_rate.full;
+				time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff);
+			} else {
+				time_disp1_drop_priority.full = 0;
+			}
+			crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full;
+			crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2);
+			crit_point_ff.full += rfixed_const_half(0);
+
+			critical_point2 = rfixed_trunc(crit_point_ff);
+
+			if (rdev->disp_priority == 2) {
+				critical_point2 = 0;
+			}
+
+			if (max_stop_req - critical_point2 < 4)
+				critical_point2 = 0;
+
+		}
+
+		if (critical_point2 == 0 && rdev->family == CHIP_R300) {
+			/* some R300 cards have problem with this set to 0 */
+			critical_point2 = 0x10;
+		}
+
+		WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
+						  (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+
+		if ((rdev->family == CHIP_RS400) ||
+		    (rdev->family == CHIP_RS480)) {
+#if 0
+			/* attempt to program RS400 disp2 regs correctly ??? */
+			temp = RREG32(RS400_DISP2_REQ_CNTL1);
+			temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK |
+				  RS400_DISP2_STOP_REQ_LEVEL_MASK);
+			WREG32(RS400_DISP2_REQ_CNTL1, (temp |
+						       (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
+						       (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
+			temp = RREG32(RS400_DISP2_REQ_CNTL2);
+			temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK |
+				  RS400_DISP2_CRITICAL_POINT_STOP_MASK);
+			WREG32(RS400_DISP2_REQ_CNTL2, (temp |
+						       (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) |
+						       (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT)));
+#endif
+			WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC);
+			WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000);
+			WREG32(RS400_DMIF_MEM_CNTL1,  0x29CA71DC);
+			WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC);
+		}
+
+		DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n",
+			  (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL));
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r300.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r300.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r300.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r300.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1590 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include <linux/seq_file.h>
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "radeon_drm.h"
+#include "radeon_share.h"
+
+/* r300,r350,rv350,rv370,rv380 depends on : */
+void r100_hdp_reset(struct radeon_device *rdev);
+int r100_cp_reset(struct radeon_device *rdev);
+int r100_rb2d_reset(struct radeon_device *rdev);
+int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
+int r100_pci_gart_enable(struct radeon_device *rdev);
+void r100_pci_gart_disable(struct radeon_device *rdev);
+void r100_mc_setup(struct radeon_device *rdev);
+void r100_mc_disable_clients(struct radeon_device *rdev);
+int r100_gui_wait_for_idle(struct radeon_device *rdev);
+int r100_cs_packet_parse(struct radeon_cs_parser *p,
+			 struct radeon_cs_packet *pkt,
+			 unsigned idx);
+int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
+int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
+			      struct radeon_cs_reloc **cs_reloc);
+int r100_cs_parse_packet0(struct radeon_cs_parser *p,
+			  struct radeon_cs_packet *pkt,
+			  const unsigned *auth, unsigned n,
+			  radeon_packet0_check_t check);
+void r100_cs_dump_packet(struct radeon_cs_parser *p,
+			 struct radeon_cs_packet *pkt);
+int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
+					 struct radeon_cs_packet *pkt,
+					 struct radeon_object *robj);
+
+/* This files gather functions specifics to:
+ * r300,r350,rv350,rv370,rv380
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+void r300_gpu_init(struct radeon_device *rdev);
+int r300_mc_wait_for_idle(struct radeon_device *rdev);
+int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev);
+
+
+/*
+ * rv370,rv380 PCIE GART
+ */
+void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int i;
+
+	/* Workaround HW bug do flush 2 times */
+	for (i = 0; i < 2; i++) {
+		tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
+		WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB);
+		(void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
+		WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
+	}
+	mb();
+}
+
+int rv370_pcie_gart_enable(struct radeon_device *rdev)
+{
+	uint32_t table_addr;
+	uint32_t tmp;
+	int r;
+
+	/* Initialize common gart structure */
+	r = radeon_gart_init(rdev);
+	if (r) {
+		return r;
+	}
+	r = rv370_debugfs_pcie_gart_info_init(rdev);
+	if (r) {
+		DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
+	}
+	rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
+	r = radeon_gart_table_vram_alloc(rdev);
+	if (r) {
+		return r;
+	}
+	/* discard memory request outside of configured range */
+	tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
+	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
+	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location);
+	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 4096;
+	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp);
+	WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
+	WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
+	table_addr = rdev->gart.table_addr;
+	WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr);
+	/* FIXME: setup default page */
+	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_location);
+	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
+	/* Clear error */
+	WREG32_PCIE(0x18, 0);
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
+	tmp |= RADEON_PCIE_TX_GART_EN;
+	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
+	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
+	rv370_pcie_gart_tlb_flush(rdev);
+	DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n",
+		 rdev->mc.gtt_size >> 20, table_addr);
+	rdev->gart.ready = true;
+	return 0;
+}
+
+void rv370_pcie_gart_disable(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
+	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
+	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
+	if (rdev->gart.table.vram.robj) {
+		radeon_object_kunmap(rdev->gart.table.vram.robj);
+		radeon_object_unpin(rdev->gart.table.vram.robj);
+	}
+}
+
+int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
+{
+	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+
+	if (i < 0 || i > rdev->gart.num_gpu_pages) {
+		return -EINVAL;
+	}
+	addr = (lower_32_bits(addr) >> 8) |
+	       ((upper_32_bits(addr) & 0xff) << 24) |
+	       0xc;
+	/* on x86 we want this to be CPU endian, on powerpc
+	 * on powerpc without HW swappers, it'll get swapped on way
+	 * into VRAM - so no need for cpu_to_le32 on VRAM tables */
+	writel(addr, ((void __iomem *)ptr) + (i * 4));
+	return 0;
+}
+
+int r300_gart_enable(struct radeon_device *rdev)
+{
+#if __OS_HAS_AGP
+	if (rdev->flags & RADEON_IS_AGP) {
+		if (rdev->family > CHIP_RV350) {
+			rv370_pcie_gart_disable(rdev);
+		} else {
+			r100_pci_gart_disable(rdev);
+		}
+		return 0;
+	}
+#endif
+	if (rdev->flags & RADEON_IS_PCIE) {
+		rdev->asic->gart_disable = &rv370_pcie_gart_disable;
+		rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
+		rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
+		return rv370_pcie_gart_enable(rdev);
+	}
+	return r100_pci_gart_enable(rdev);
+}
+
+
+/*
+ * MC
+ */
+int r300_mc_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+
+	r300_gpu_init(rdev);
+	r100_pci_gart_disable(rdev);
+	if (rdev->flags & RADEON_IS_PCIE) {
+		rv370_pcie_gart_disable(rdev);
+	}
+
+	/* Setup GPU memory space */
+	rdev->mc.vram_location = 0xFFFFFFFFUL;
+	rdev->mc.gtt_location = 0xFFFFFFFFUL;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			printk(KERN_WARNING "[drm] Disabling AGP\n");
+			rdev->flags &= ~RADEON_IS_AGP;
+			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+		} else {
+			rdev->mc.gtt_location = rdev->mc.agp_base;
+		}
+	}
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	/* Program GPU memory space */
+	r100_mc_disable_clients(rdev);
+	if (r300_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	r100_mc_setup(rdev);
+	return 0;
+}
+
+void r300_mc_fini(struct radeon_device *rdev)
+{
+	if (rdev->flags & RADEON_IS_PCIE) {
+		rv370_pcie_gart_disable(rdev);
+		radeon_gart_table_vram_free(rdev);
+	} else {
+		r100_pci_gart_disable(rdev);
+		radeon_gart_table_ram_free(rdev);
+	}
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Fence emission
+ */
+void r300_fence_ring_emit(struct radeon_device *rdev,
+			  struct radeon_fence *fence)
+{
+	/* Who ever call radeon_fence_emit should call ring_lock and ask
+	 * for enough space (today caller are ib schedule and buffer move) */
+	/* Write SC register so SC & US assert idle */
+	radeon_ring_write(rdev, PACKET0(0x43E0, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(0x43E4, 0));
+	radeon_ring_write(rdev, 0);
+	/* Flush 3D cache */
+	radeon_ring_write(rdev, PACKET0(0x4E4C, 0));
+	radeon_ring_write(rdev, (2 << 0));
+	radeon_ring_write(rdev, PACKET0(0x4F18, 0));
+	radeon_ring_write(rdev, (1 << 0));
+	/* Wait until IDLE & CLEAN */
+	radeon_ring_write(rdev, PACKET0(0x1720, 0));
+	radeon_ring_write(rdev, (1 << 17) | (1 << 16)  | (1 << 9));
+	/* Emit fence sequence & fire IRQ */
+	radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
+	radeon_ring_write(rdev, fence->seq);
+	radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0));
+	radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
+}
+
+
+/*
+ * Global GPU functions
+ */
+int r300_copy_dma(struct radeon_device *rdev,
+		  uint64_t src_offset,
+		  uint64_t dst_offset,
+		  unsigned num_pages,
+		  struct radeon_fence *fence)
+{
+	uint32_t size;
+	uint32_t cur_size;
+	int i, num_loops;
+	int r = 0;
+
+	/* radeon pitch is /64 */
+	size = num_pages << PAGE_SHIFT;
+	num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
+	r = radeon_ring_lock(rdev, num_loops * 4 + 64);
+	if (r) {
+		DRM_ERROR("radeon: moving bo (%d).\n", r);
+		return r;
+	}
+	/* Must wait for 2D idle & clean before DMA or hangs might happen */
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0 ));
+	radeon_ring_write(rdev, (1 << 16));
+	for (i = 0; i < num_loops; i++) {
+		cur_size = size;
+		if (cur_size > 0x1FFFFF) {
+			cur_size = 0x1FFFFF;
+		}
+		size -= cur_size;
+		radeon_ring_write(rdev, PACKET0(0x720, 2));
+		radeon_ring_write(rdev, src_offset);
+		radeon_ring_write(rdev, dst_offset);
+		radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30));
+		src_offset += cur_size;
+		dst_offset += cur_size;
+	}
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE);
+	if (fence) {
+		r = radeon_fence_emit(rdev, fence);
+	}
+	radeon_ring_unlock_commit(rdev);
+	return r;
+}
+
+void r300_ring_start(struct radeon_device *rdev)
+{
+	unsigned gb_tile_config;
+	int r;
+
+	/* Sub pixel 1/12 so we can have 4K rendering according to doc */
+	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
+	switch(rdev->num_gb_pipes) {
+	case 2:
+		gb_tile_config |= R300_PIPE_COUNT_R300;
+		break;
+	case 3:
+		gb_tile_config |= R300_PIPE_COUNT_R420_3P;
+		break;
+	case 4:
+		gb_tile_config |= R300_PIPE_COUNT_R420;
+		break;
+	case 1:
+	default:
+		gb_tile_config |= R300_PIPE_COUNT_RV350;
+		break;
+	}
+
+	r = radeon_ring_lock(rdev, 64);
+	if (r) {
+		return;
+	}
+	radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0));
+	radeon_ring_write(rdev,
+			  RADEON_ISYNC_ANY2D_IDLE3D |
+			  RADEON_ISYNC_ANY3D_IDLE2D |
+			  RADEON_ISYNC_WAIT_IDLEGUI |
+			  RADEON_ISYNC_CPSCRATCH_IDLEGUI);
+	radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0));
+	radeon_ring_write(rdev, gb_tile_config);
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev,
+			  RADEON_WAIT_2D_IDLECLEAN |
+			  RADEON_WAIT_3D_IDLECLEAN);
+	radeon_ring_write(rdev, PACKET0(0x170C, 0));
+	radeon_ring_write(rdev, 1 << 31);
+	radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
+	radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE);
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev,
+			  RADEON_WAIT_2D_IDLECLEAN |
+			  RADEON_WAIT_3D_IDLECLEAN);
+	radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
+	radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE);
+	radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0));
+	radeon_ring_write(rdev,
+			  ((6 << R300_MS_X0_SHIFT) |
+			   (6 << R300_MS_Y0_SHIFT) |
+			   (6 << R300_MS_X1_SHIFT) |
+			   (6 << R300_MS_Y1_SHIFT) |
+			   (6 << R300_MS_X2_SHIFT) |
+			   (6 << R300_MS_Y2_SHIFT) |
+			   (6 << R300_MSBD0_Y_SHIFT) |
+			   (6 << R300_MSBD0_X_SHIFT)));
+	radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0));
+	radeon_ring_write(rdev,
+			  ((6 << R300_MS_X3_SHIFT) |
+			   (6 << R300_MS_Y3_SHIFT) |
+			   (6 << R300_MS_X4_SHIFT) |
+			   (6 << R300_MS_Y4_SHIFT) |
+			   (6 << R300_MS_X5_SHIFT) |
+			   (6 << R300_MS_Y5_SHIFT) |
+			   (6 << R300_MSBD1_SHIFT)));
+	radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0));
+	radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL);
+	radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0));
+	radeon_ring_write(rdev,
+			  R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE);
+	radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0));
+	radeon_ring_write(rdev,
+			  R300_GEOMETRY_ROUND_NEAREST |
+			  R300_COLOR_ROUND_NEAREST);
+	radeon_ring_unlock_commit(rdev);
+}
+
+void r300_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+
+	if (rdev->family == CHIP_R300 &&
+	    (RREG32(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11) {
+		rdev->pll_errata |= CHIP_ERRATA_R300_CG;
+	}
+}
+
+int r300_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32(0x0150);
+		if (tmp & (1 << 4)) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+void r300_gpu_init(struct radeon_device *rdev)
+{
+	uint32_t gb_tile_config, tmp;
+
+	r100_hdp_reset(rdev);
+	/* FIXME: rv380 one pipes ? */
+	if ((rdev->family == CHIP_R300) || (rdev->family == CHIP_R350)) {
+		/* r300,r350 */
+		rdev->num_gb_pipes = 2;
+	} else {
+		/* rv350,rv370,rv380 */
+		rdev->num_gb_pipes = 1;
+	}
+	rdev->num_z_pipes = 1;
+	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
+	switch (rdev->num_gb_pipes) {
+	case 2:
+		gb_tile_config |= R300_PIPE_COUNT_R300;
+		break;
+	case 3:
+		gb_tile_config |= R300_PIPE_COUNT_R420_3P;
+		break;
+	case 4:
+		gb_tile_config |= R300_PIPE_COUNT_R420;
+		break;
+	default:
+	case 1:
+		gb_tile_config |= R300_PIPE_COUNT_RV350;
+		break;
+	}
+	WREG32(R300_GB_TILE_CONFIG, gb_tile_config);
+
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	tmp = RREG32(0x170C);
+	WREG32(0x170C, tmp | (1 << 31));
+
+	WREG32(R300_RB2D_DSTCACHE_MODE,
+	       R300_DC_AUTOFLUSH_ENABLE |
+	       R300_DC_DC_DISABLE_IGNORE_PE);
+
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	if (r300_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized.\n",
+		 rdev->num_gb_pipes, rdev->num_z_pipes);
+}
+
+int r300_ga_reset(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	bool reinit_cp;
+	int i;
+
+	reinit_cp = rdev->cp.ready;
+	rdev->cp.ready = false;
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		WREG32(RADEON_CP_CSQ_MODE, 0);
+		WREG32(RADEON_CP_CSQ_CNTL, 0);
+		WREG32(RADEON_RBBM_SOFT_RESET, 0x32005);
+		(void)RREG32(RADEON_RBBM_SOFT_RESET);
+		udelay(200);
+		WREG32(RADEON_RBBM_SOFT_RESET, 0);
+		/* Wait to prevent race in RBBM_STATUS */
+		mdelay(1);
+		tmp = RREG32(RADEON_RBBM_STATUS);
+		if (tmp & ((1 << 20) | (1 << 26))) {
+			DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)", tmp);
+			/* GA still busy soft reset it */
+			WREG32(0x429C, 0x200);
+			WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0);
+			WREG32(0x43E0, 0);
+			WREG32(0x43E4, 0);
+			WREG32(0x24AC, 0);
+		}
+		/* Wait to prevent race in RBBM_STATUS */
+		mdelay(1);
+		tmp = RREG32(RADEON_RBBM_STATUS);
+		if (!(tmp & ((1 << 20) | (1 << 26)))) {
+			break;
+		}
+	}
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RADEON_RBBM_STATUS);
+		if (!(tmp & ((1 << 20) | (1 << 26)))) {
+			DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n",
+				 tmp);
+			if (reinit_cp) {
+				return r100_cp_init(rdev, rdev->cp.ring_size);
+			}
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	tmp = RREG32(RADEON_RBBM_STATUS);
+	DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp);
+	return -1;
+}
+
+int r300_gpu_reset(struct radeon_device *rdev)
+{
+	uint32_t status;
+
+	/* reset order likely matter */
+	status = RREG32(RADEON_RBBM_STATUS);
+	/* reset HDP */
+	r100_hdp_reset(rdev);
+	/* reset rb2d */
+	if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
+		r100_rb2d_reset(rdev);
+	}
+	/* reset GA */
+	if (status & ((1 << 20) | (1 << 26))) {
+		r300_ga_reset(rdev);
+	}
+	/* reset CP */
+	status = RREG32(RADEON_RBBM_STATUS);
+	if (status & (1 << 16)) {
+		r100_cp_reset(rdev);
+	}
+	/* Check if GPU is idle */
+	status = RREG32(RADEON_RBBM_STATUS);
+	if (status & (1 << 31)) {
+		DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
+		return -1;
+	}
+	DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status);
+	return 0;
+}
+
+
+/*
+ * r300,r350,rv350,rv380 VRAM info
+ */
+void r300_vram_info(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	/* DDR for all card after R300 & IGP */
+	rdev->mc.vram_is_ddr = true;
+	tmp = RREG32(RADEON_MEM_CNTL);
+	if (tmp & R300_MEM_NUM_CHANNELS_MASK) {
+		rdev->mc.vram_width = 128;
+	} else {
+		rdev->mc.vram_width = 64;
+	}
+
+	r100_vram_init_sizes(rdev);
+}
+
+
+/*
+ * PCIE Lanes
+ */
+
+void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
+{
+	uint32_t link_width_cntl, mask;
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return;
+
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		return;
+
+	/* FIXME wait for idle */
+
+	switch (lanes) {
+	case 0:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X0;
+		break;
+	case 1:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X1;
+		break;
+	case 2:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X2;
+		break;
+	case 4:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X4;
+		break;
+	case 8:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X8;
+		break;
+	case 12:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X12;
+		break;
+	case 16:
+	default:
+		mask = RADEON_PCIE_LC_LINK_WIDTH_X16;
+		break;
+	}
+
+	link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+
+	if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) ==
+	    (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT))
+		return;
+
+	link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK |
+			     RADEON_PCIE_LC_RECONFIG_NOW |
+			     RADEON_PCIE_LC_RECONFIG_LATER |
+			     RADEON_PCIE_LC_SHORT_RECONFIG_EN);
+	link_width_cntl |= mask;
+	WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+	WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl |
+						     RADEON_PCIE_LC_RECONFIG_NOW));
+
+	/* wait for lane set to complete */
+	link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+	while (link_width_cntl == 0xffffffff)
+		link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+
+}
+
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
+	seq_printf(m, "PCIE_TX_GART_CNTL 0x%08x\n", tmp);
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_BASE);
+	seq_printf(m, "PCIE_TX_GART_BASE 0x%08x\n", tmp);
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_LO);
+	seq_printf(m, "PCIE_TX_GART_START_LO 0x%08x\n", tmp);
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_HI);
+	seq_printf(m, "PCIE_TX_GART_START_HI 0x%08x\n", tmp);
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_LO);
+	seq_printf(m, "PCIE_TX_GART_END_LO 0x%08x\n", tmp);
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_HI);
+	seq_printf(m, "PCIE_TX_GART_END_HI 0x%08x\n", tmp);
+	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_ERROR);
+	seq_printf(m, "PCIE_TX_GART_ERROR 0x%08x\n", tmp);
+	return 0;
+}
+
+static struct drm_info_list rv370_pcie_gart_info_list[] = {
+	{"rv370_pcie_gart_info", rv370_debugfs_pcie_gart_info, 0, NULL},
+};
+#endif
+
+int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1);
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * CS functions
+ */
+struct r300_cs_track_cb {
+	struct radeon_object	*robj;
+	unsigned		pitch;
+	unsigned		cpp;
+	unsigned		offset;
+};
+
+struct r300_cs_track_array {
+	struct radeon_object	*robj;
+	unsigned		esize;
+};
+
+struct r300_cs_track_texture {
+	struct radeon_object	*robj;
+	unsigned		pitch;
+	unsigned		width;
+	unsigned		height;
+	unsigned		num_levels;
+	unsigned		cpp;
+	unsigned		tex_coord_type;
+	unsigned		txdepth;
+	unsigned		width_11;
+	unsigned		height_11;
+	bool			use_pitch;
+	bool			enabled;
+	bool			roundup_w;
+	bool			roundup_h;
+};
+
+struct r300_cs_track {
+	unsigned			num_cb;
+	unsigned			maxy;
+	unsigned			vtx_size;
+	unsigned			vap_vf_cntl;
+	unsigned			immd_dwords;
+	unsigned			num_arrays;
+	unsigned			max_indx;
+	struct r300_cs_track_array	arrays[11];
+	struct r300_cs_track_cb 	cb[4];
+	struct r300_cs_track_cb 	zb;
+	struct r300_cs_track_texture	textures[16];
+	bool				z_enabled;
+};
+
+static inline void r300_cs_track_texture_print(struct r300_cs_track_texture *t)
+{
+	DRM_ERROR("pitch                      %d\n", t->pitch);
+	DRM_ERROR("width                      %d\n", t->width);
+	DRM_ERROR("height                     %d\n", t->height);
+	DRM_ERROR("num levels                 %d\n", t->num_levels);
+	DRM_ERROR("depth                      %d\n", t->txdepth);
+	DRM_ERROR("bpp                        %d\n", t->cpp);
+	DRM_ERROR("coordinate type            %d\n", t->tex_coord_type);
+	DRM_ERROR("width round to power of 2  %d\n", t->roundup_w);
+	DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
+}
+
+static inline int r300_cs_track_texture_check(struct radeon_device *rdev,
+					      struct r300_cs_track *track)
+{
+	struct radeon_object *robj;
+	unsigned long size;
+	unsigned u, i, w, h;
+
+	for (u = 0; u < 16; u++) {
+		if (!track->textures[u].enabled)
+			continue;
+		robj = track->textures[u].robj;
+		if (robj == NULL) {
+			DRM_ERROR("No texture bound to unit %u\n", u);
+			return -EINVAL;
+		}
+		size = 0;
+		for (i = 0; i <= track->textures[u].num_levels; i++) {
+			if (track->textures[u].use_pitch) {
+				w = track->textures[u].pitch / (1 << i);
+			} else {
+				w = track->textures[u].width / (1 << i);
+				if (rdev->family >= CHIP_RV515)
+					w |= track->textures[u].width_11;
+				if (track->textures[u].roundup_w)
+					w = roundup_pow_of_two(w);
+			}
+			h = track->textures[u].height / (1 << i);
+			if (rdev->family >= CHIP_RV515)
+				h |= track->textures[u].height_11;
+			if (track->textures[u].roundup_h)
+				h = roundup_pow_of_two(h);
+			size += w * h;
+		}
+		size *= track->textures[u].cpp;
+		switch (track->textures[u].tex_coord_type) {
+		case 0:
+			break;
+		case 1:
+			size *= (1 << track->textures[u].txdepth);
+			break;
+		case 2:
+			size *= 6;
+			break;
+		default:
+			DRM_ERROR("Invalid texture coordinate type %u for unit "
+				  "%u\n", track->textures[u].tex_coord_type, u);
+			return -EINVAL;
+		}
+		if (size > radeon_object_size(robj)) {
+			DRM_ERROR("Texture of unit %u needs %lu bytes but is "
+				  "%lu\n", u, size, radeon_object_size(robj));
+			r300_cs_track_texture_print(&track->textures[u]);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track)
+{
+	unsigned i;
+	unsigned long size;
+	unsigned prim_walk;
+	unsigned nverts;
+
+	for (i = 0; i < track->num_cb; i++) {
+		if (track->cb[i].robj == NULL) {
+			DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
+			return -EINVAL;
+		}
+		size = track->cb[i].pitch * track->cb[i].cpp * track->maxy;
+		size += track->cb[i].offset;
+		if (size > radeon_object_size(track->cb[i].robj)) {
+			DRM_ERROR("[drm] Buffer too small for color buffer %d "
+				  "(need %lu have %lu) !\n", i, size,
+				  radeon_object_size(track->cb[i].robj));
+			DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n",
+				  i, track->cb[i].pitch, track->cb[i].cpp,
+				  track->cb[i].offset, track->maxy);
+			return -EINVAL;
+		}
+	}
+	if (track->z_enabled) {
+		if (track->zb.robj == NULL) {
+			DRM_ERROR("[drm] No buffer for z buffer !\n");
+			return -EINVAL;
+		}
+		size = track->zb.pitch * track->zb.cpp * track->maxy;
+		size += track->zb.offset;
+		if (size > radeon_object_size(track->zb.robj)) {
+			DRM_ERROR("[drm] Buffer too small for z buffer "
+				  "(need %lu have %lu) !\n", size,
+				  radeon_object_size(track->zb.robj));
+			return -EINVAL;
+		}
+	}
+	prim_walk = (track->vap_vf_cntl >> 4) & 0x3;
+	nverts = (track->vap_vf_cntl >> 16) & 0xFFFF;
+	switch (prim_walk) {
+	case 1:
+		for (i = 0; i < track->num_arrays; i++) {
+			size = track->arrays[i].esize * track->max_indx * 4;
+			if (track->arrays[i].robj == NULL) {
+				DRM_ERROR("(PW %u) Vertex array %u no buffer "
+					  "bound\n", prim_walk, i);
+				return -EINVAL;
+			}
+			if (size > radeon_object_size(track->arrays[i].robj)) {
+				DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
+					   "have %lu dwords\n", prim_walk, i,
+					   size >> 2,
+					   radeon_object_size(track->arrays[i].robj) >> 2);
+				DRM_ERROR("Max indices %u\n", track->max_indx);
+				return -EINVAL;
+			}
+		}
+		break;
+	case 2:
+		for (i = 0; i < track->num_arrays; i++) {
+			size = track->arrays[i].esize * (nverts - 1) * 4;
+			if (track->arrays[i].robj == NULL) {
+				DRM_ERROR("(PW %u) Vertex array %u no buffer "
+					  "bound\n", prim_walk, i);
+				return -EINVAL;
+			}
+			if (size > radeon_object_size(track->arrays[i].robj)) {
+				DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
+					   "have %lu dwords\n", prim_walk, i, size >> 2,
+					   radeon_object_size(track->arrays[i].robj) >> 2);
+				return -EINVAL;
+			}
+		}
+		break;
+	case 3:
+		size = track->vtx_size * nverts;
+		if (size != track->immd_dwords) {
+			DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n",
+				  track->immd_dwords, size);
+			DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n",
+				  nverts, track->vtx_size);
+			return -EINVAL;
+		}
+		break;
+	default:
+		DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n",
+			  prim_walk);
+		return -EINVAL;
+	}
+	return r300_cs_track_texture_check(rdev, track);
+}
+
+static inline void r300_cs_track_clear(struct r300_cs_track *track)
+{
+	unsigned i;
+
+	track->num_cb = 4;
+	track->maxy = 4096;
+	for (i = 0; i < track->num_cb; i++) {
+		track->cb[i].robj = NULL;
+		track->cb[i].pitch = 8192;
+		track->cb[i].cpp = 16;
+		track->cb[i].offset = 0;
+	}
+	track->z_enabled = true;
+	track->zb.robj = NULL;
+	track->zb.pitch = 8192;
+	track->zb.cpp = 4;
+	track->zb.offset = 0;
+	track->vtx_size = 0x7F;
+	track->immd_dwords = 0xFFFFFFFFUL;
+	track->num_arrays = 11;
+	track->max_indx = 0x00FFFFFFUL;
+	for (i = 0; i < track->num_arrays; i++) {
+		track->arrays[i].robj = NULL;
+		track->arrays[i].esize = 0x7F;
+	}
+	for (i = 0; i < 16; i++) {
+		track->textures[i].pitch = 16536;
+		track->textures[i].width = 16536;
+		track->textures[i].height = 16536;
+		track->textures[i].width_11 = 1 << 11;
+		track->textures[i].height_11 = 1 << 11;
+		track->textures[i].num_levels = 12;
+		track->textures[i].txdepth = 16;
+		track->textures[i].cpp = 64;
+		track->textures[i].tex_coord_type = 1;
+		track->textures[i].robj = NULL;
+		/* CS IB emission code makes sure texture unit are disabled */
+		track->textures[i].enabled = false;
+		track->textures[i].roundup_w = true;
+		track->textures[i].roundup_h = true;
+	}
+}
+
+static const unsigned r300_reg_safe_bm[159] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
+	0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
+	0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
+	0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
+	0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+	0x00000000, 0x0000C100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x0003FC01, 0xFFFFFCF8, 0xFF800B19,
+};
+
+static int r300_packet0_check(struct radeon_cs_parser *p,
+		struct radeon_cs_packet *pkt,
+		unsigned idx, unsigned reg)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	struct radeon_cs_reloc *reloc;
+	struct r300_cs_track *track;
+	volatile uint32_t *ib;
+	uint32_t tmp, tile_flags = 0;
+	unsigned i;
+	int r;
+
+	ib = p->ib->ptr;
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+	track = (struct r300_cs_track*)p->track;
+	switch(reg) {
+	case AVIVO_D1MODE_VLINE_START_END:
+	case RADEON_CRTC_GUI_TRIG_VLINE:
+		r = r100_cs_packet_parse_vline(p);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		break;
+	case RADEON_DST_PITCH_OFFSET:
+	case RADEON_SRC_PITCH_OFFSET:
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		tmp = ib_chunk->kdata[idx] & 0x003fffff;
+		tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
+
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+			tile_flags |= RADEON_DST_TILE_MACRO;
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+			if (reg == RADEON_SRC_PITCH_OFFSET) {
+				DRM_ERROR("Cannot src blit from microtiled surface\n");
+				r100_cs_dump_packet(p, pkt);
+				return -EINVAL;
+			}
+			tile_flags |= RADEON_DST_TILE_MICRO;
+		}
+		tmp |= tile_flags;
+		ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
+		break;
+	case R300_RB3D_COLOROFFSET0:
+	case R300_RB3D_COLOROFFSET1:
+	case R300_RB3D_COLOROFFSET2:
+	case R300_RB3D_COLOROFFSET3:
+		i = (reg - R300_RB3D_COLOROFFSET0) >> 2;
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		track->cb[i].robj = reloc->robj;
+		track->cb[i].offset = ib_chunk->kdata[idx];
+		ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+		break;
+	case R300_ZB_DEPTHOFFSET:
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		track->zb.robj = reloc->robj;
+		track->zb.offset = ib_chunk->kdata[idx];
+		ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+		break;
+	case R300_TX_OFFSET_0:
+	case R300_TX_OFFSET_0+4:
+	case R300_TX_OFFSET_0+8:
+	case R300_TX_OFFSET_0+12:
+	case R300_TX_OFFSET_0+16:
+	case R300_TX_OFFSET_0+20:
+	case R300_TX_OFFSET_0+24:
+	case R300_TX_OFFSET_0+28:
+	case R300_TX_OFFSET_0+32:
+	case R300_TX_OFFSET_0+36:
+	case R300_TX_OFFSET_0+40:
+	case R300_TX_OFFSET_0+44:
+	case R300_TX_OFFSET_0+48:
+	case R300_TX_OFFSET_0+52:
+	case R300_TX_OFFSET_0+56:
+	case R300_TX_OFFSET_0+60:
+		i = (reg - R300_TX_OFFSET_0) >> 2;
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+		track->textures[i].robj = reloc->robj;
+		break;
+	/* Tracked registers */
+	case 0x2084:
+		/* VAP_VF_CNTL */
+		track->vap_vf_cntl = ib_chunk->kdata[idx];
+		break;
+	case 0x20B4:
+		/* VAP_VTX_SIZE */
+		track->vtx_size = ib_chunk->kdata[idx] & 0x7F;
+		break;
+	case 0x2134:
+		/* VAP_VF_MAX_VTX_INDX */
+		track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
+		break;
+	case 0x43E4:
+		/* SC_SCISSOR1 */
+		track->maxy = ((ib_chunk->kdata[idx] >> 13) & 0x1FFF) + 1;
+		if (p->rdev->family < CHIP_RV515) {
+			track->maxy -= 1440;
+		}
+		break;
+	case 0x4E00:
+		/* RB3D_CCTL */
+		track->num_cb = ((ib_chunk->kdata[idx] >> 5) & 0x3) + 1;
+		break;
+	case 0x4E38:
+	case 0x4E3C:
+	case 0x4E40:
+	case 0x4E44:
+		/* RB3D_COLORPITCH0 */
+		/* RB3D_COLORPITCH1 */
+		/* RB3D_COLORPITCH2 */
+		/* RB3D_COLORPITCH3 */
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+				  idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+			tile_flags |= R300_COLOR_TILE_ENABLE;
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+			tile_flags |= R300_COLOR_MICROTILE_ENABLE;
+
+		tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+		tmp |= tile_flags;
+		ib[idx] = tmp;
+
+		i = (reg - 0x4E38) >> 2;
+		track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE;
+		switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) {
+		case 9:
+		case 11:
+		case 12:
+			track->cb[i].cpp = 1;
+			break;
+		case 3:
+		case 4:
+		case 13:
+		case 15:
+			track->cb[i].cpp = 2;
+			break;
+		case 6:
+			track->cb[i].cpp = 4;
+			break;
+		case 10:
+			track->cb[i].cpp = 8;
+			break;
+		case 7:
+			track->cb[i].cpp = 16;
+			break;
+		default:
+			DRM_ERROR("Invalid color buffer format (%d) !\n",
+				  ((ib_chunk->kdata[idx] >> 21) & 0xF));
+			return -EINVAL;
+		}
+		break;
+	case 0x4F00:
+		/* ZB_CNTL */
+		if (ib_chunk->kdata[idx] & 2) {
+			track->z_enabled = true;
+		} else {
+			track->z_enabled = false;
+		}
+		break;
+	case 0x4F10:
+		/* ZB_FORMAT */
+		switch ((ib_chunk->kdata[idx] & 0xF)) {
+		case 0:
+		case 1:
+			track->zb.cpp = 2;
+			break;
+		case 2:
+			track->zb.cpp = 4;
+			break;
+		default:
+			DRM_ERROR("Invalid z buffer format (%d) !\n",
+				  (ib_chunk->kdata[idx] & 0xF));
+			return -EINVAL;
+		}
+		break;
+	case 0x4F24:
+		/* ZB_DEPTHPITCH */
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+				  idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+			tile_flags |= R300_DEPTHMACROTILE_ENABLE;
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+			tile_flags |= R300_DEPTHMICROTILE_TILED;;
+
+		tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+		tmp |= tile_flags;
+		ib[idx] = tmp;
+
+		track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
+		break;
+	case 0x4104:
+		for (i = 0; i < 16; i++) {
+			bool enabled;
+
+			enabled = !!(ib_chunk->kdata[idx] & (1 << i));
+			track->textures[i].enabled = enabled;
+		}
+		break;
+	case 0x44C0:
+	case 0x44C4:
+	case 0x44C8:
+	case 0x44CC:
+	case 0x44D0:
+	case 0x44D4:
+	case 0x44D8:
+	case 0x44DC:
+	case 0x44E0:
+	case 0x44E4:
+	case 0x44E8:
+	case 0x44EC:
+	case 0x44F0:
+	case 0x44F4:
+	case 0x44F8:
+	case 0x44FC:
+		/* TX_FORMAT1_[0-15] */
+		i = (reg - 0x44C0) >> 2;
+		tmp = (ib_chunk->kdata[idx] >> 25) & 0x3;
+		track->textures[i].tex_coord_type = tmp;
+		switch ((ib_chunk->kdata[idx] & 0x1F)) {
+		case 0:
+		case 2:
+		case 5:
+		case 18:
+		case 20:
+		case 21:
+			track->textures[i].cpp = 1;
+			break;
+		case 1:
+		case 3:
+		case 6:
+		case 7:
+		case 10:
+		case 11:
+		case 19:
+		case 22:
+		case 24:
+			track->textures[i].cpp = 2;
+			break;
+		case 4:
+		case 8:
+		case 9:
+		case 12:
+		case 13:
+		case 23:
+		case 25:
+		case 27:
+		case 30:
+			track->textures[i].cpp = 4;
+			break;
+		case 14:
+		case 26:
+		case 28:
+			track->textures[i].cpp = 8;
+			break;
+		case 29:
+			track->textures[i].cpp = 16;
+			break;
+		default:
+			DRM_ERROR("Invalid texture format %u\n",
+				  (ib_chunk->kdata[idx] & 0x1F));
+			return -EINVAL;
+			break;
+		}
+		break;
+	case 0x4400:
+	case 0x4404:
+	case 0x4408:
+	case 0x440C:
+	case 0x4410:
+	case 0x4414:
+	case 0x4418:
+	case 0x441C:
+	case 0x4420:
+	case 0x4424:
+	case 0x4428:
+	case 0x442C:
+	case 0x4430:
+	case 0x4434:
+	case 0x4438:
+	case 0x443C:
+		/* TX_FILTER0_[0-15] */
+		i = (reg - 0x4400) >> 2;
+		tmp = ib_chunk->kdata[idx] & 0x7;;
+		if (tmp == 2 || tmp == 4 || tmp == 6) {
+			track->textures[i].roundup_w = false;
+		}
+		tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;;
+		if (tmp == 2 || tmp == 4 || tmp == 6) {
+			track->textures[i].roundup_h = false;
+		}
+		break;
+	case 0x4500:
+	case 0x4504:
+	case 0x4508:
+	case 0x450C:
+	case 0x4510:
+	case 0x4514:
+	case 0x4518:
+	case 0x451C:
+	case 0x4520:
+	case 0x4524:
+	case 0x4528:
+	case 0x452C:
+	case 0x4530:
+	case 0x4534:
+	case 0x4538:
+	case 0x453C:
+		/* TX_FORMAT2_[0-15] */
+		i = (reg - 0x4500) >> 2;
+		tmp = ib_chunk->kdata[idx] & 0x3FFF;
+		track->textures[i].pitch = tmp + 1;
+		if (p->rdev->family >= CHIP_RV515) {
+			tmp = ((ib_chunk->kdata[idx] >> 15) & 1) << 11;
+			track->textures[i].width_11 = tmp;
+			tmp = ((ib_chunk->kdata[idx] >> 16) & 1) << 11;
+			track->textures[i].height_11 = tmp;
+		}
+		break;
+	case 0x4480:
+	case 0x4484:
+	case 0x4488:
+	case 0x448C:
+	case 0x4490:
+	case 0x4494:
+	case 0x4498:
+	case 0x449C:
+	case 0x44A0:
+	case 0x44A4:
+	case 0x44A8:
+	case 0x44AC:
+	case 0x44B0:
+	case 0x44B4:
+	case 0x44B8:
+	case 0x44BC:
+		/* TX_FORMAT0_[0-15] */
+		i = (reg - 0x4480) >> 2;
+		tmp = ib_chunk->kdata[idx] & 0x7FF;
+		track->textures[i].width = tmp + 1;
+		tmp = (ib_chunk->kdata[idx] >> 11) & 0x7FF;
+		track->textures[i].height = tmp + 1;
+		tmp = (ib_chunk->kdata[idx] >> 26) & 0xF;
+		track->textures[i].num_levels = tmp;
+		tmp = ib_chunk->kdata[idx] & (1 << 31);
+		track->textures[i].use_pitch = !!tmp;
+		tmp = (ib_chunk->kdata[idx] >> 22) & 0xF;
+		track->textures[i].txdepth = tmp;
+		break;
+	case R300_ZB_ZPASS_ADDR:
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+					idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+		break;
+	case 0x4be8:
+		/* valid register only on RV530 */
+		if (p->rdev->family == CHIP_RV530)
+			break;
+		/* fallthrough do not move */
+	default:
+		printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
+		       reg, idx);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int r300_packet3_check(struct radeon_cs_parser *p,
+			      struct radeon_cs_packet *pkt)
+{
+	struct radeon_cs_chunk *ib_chunk;
+	struct radeon_cs_reloc *reloc;
+	struct r300_cs_track *track;
+	volatile uint32_t *ib;
+	unsigned idx;
+	unsigned i, c;
+	int r;
+
+	ib = p->ib->ptr;
+	ib_chunk = &p->chunks[p->chunk_ib_idx];
+	idx = pkt->idx + 1;
+	track = (struct r300_cs_track*)p->track;
+	switch(pkt->opcode) {
+	case PACKET3_3D_LOAD_VBPNTR:
+		c = ib_chunk->kdata[idx++] & 0x1F;
+		track->num_arrays = c;
+		for (i = 0; i < (c - 1); i+=2, idx+=3) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+			track->arrays[i + 0].robj = reloc->robj;
+			track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
+			track->arrays[i + 0].esize &= 0x7F;
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset);
+			track->arrays[i + 1].robj = reloc->robj;
+			track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24;
+			track->arrays[i + 1].esize &= 0x7F;
+		}
+		if (c & 1) {
+			r = r100_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				DRM_ERROR("No reloc for packet3 %d\n",
+					  pkt->opcode);
+				r100_cs_dump_packet(p, pkt);
+				return r;
+			}
+			ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+			track->arrays[i + 0].robj = reloc->robj;
+			track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
+			track->arrays[i + 0].esize &= 0x7F;
+		}
+		break;
+	case PACKET3_INDX_BUFFER:
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+		r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
+		if (r) {
+			return r;
+		}
+		break;
+	/* Draw packet */
+	case PACKET3_3D_DRAW_IMMD:
+		/* Number of dwords is vtx_size * (num_vertices - 1)
+		 * PRIM_WALK must be equal to 3 vertex data in embedded
+		 * in cmd stream */
+		if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) {
+			DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
+			return -EINVAL;
+		}
+		track->vap_vf_cntl = ib_chunk->kdata[idx+1];
+		track->immd_dwords = pkt->count - 1;
+		r = r300_cs_track_check(p->rdev, track);
+		if (r) {
+			return r;
+		}
+		break;
+	case PACKET3_3D_DRAW_IMMD_2:
+		/* Number of dwords is vtx_size * (num_vertices - 1)
+		 * PRIM_WALK must be equal to 3 vertex data in embedded
+		 * in cmd stream */
+		if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) {
+			DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
+			return -EINVAL;
+		}
+		track->vap_vf_cntl = ib_chunk->kdata[idx];
+		track->immd_dwords = pkt->count;
+		r = r300_cs_track_check(p->rdev, track);
+		if (r) {
+			return r;
+		}
+		break;
+	case PACKET3_3D_DRAW_VBUF:
+		track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+		r = r300_cs_track_check(p->rdev, track);
+		if (r) {
+			return r;
+		}
+		break;
+	case PACKET3_3D_DRAW_VBUF_2:
+		track->vap_vf_cntl = ib_chunk->kdata[idx];
+		r = r300_cs_track_check(p->rdev, track);
+		if (r) {
+			return r;
+		}
+		break;
+	case PACKET3_3D_DRAW_INDX:
+		track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+		r = r300_cs_track_check(p->rdev, track);
+		if (r) {
+			return r;
+		}
+		break;
+	case PACKET3_3D_DRAW_INDX_2:
+		track->vap_vf_cntl = ib_chunk->kdata[idx];
+		r = r300_cs_track_check(p->rdev, track);
+		if (r) {
+			return r;
+		}
+		break;
+	case PACKET3_NOP:
+		break;
+	default:
+		DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int r300_cs_parse(struct radeon_cs_parser *p)
+{
+	struct radeon_cs_packet pkt;
+	struct r300_cs_track track;
+	int r;
+
+	r300_cs_track_clear(&track);
+	p->track = &track;
+	do {
+		r = r100_cs_packet_parse(p, &pkt, p->idx);
+		if (r) {
+			return r;
+		}
+		p->idx += pkt.count + 2;
+		switch (pkt.type) {
+		case PACKET_TYPE0:
+			r = r100_cs_parse_packet0(p, &pkt,
+						  p->rdev->config.r300.reg_safe_bm,
+						  p->rdev->config.r300.reg_safe_bm_size,
+						  &r300_packet0_check);
+			break;
+		case PACKET_TYPE2:
+			break;
+		case PACKET_TYPE3:
+			r = r300_packet3_check(p, &pkt);
+			break;
+		default:
+			DRM_ERROR("Unknown packet type %d !\n", pkt.type);
+			return -EINVAL;
+		}
+		if (r) {
+			return r;
+		}
+	} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+	return 0;
+}
+
+int r300_init(struct radeon_device *rdev)
+{
+	rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
+	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r300.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r300.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r300.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r300.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef R300_H
+#define R300_H
+
+struct r300_asic {
+	const unsigned	*reg_safe_bm;
+	unsigned	reg_safe_bm_size;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r300_reg.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r300_reg.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r300_reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r300_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,30 +1,36 @@
-/**************************************************************************
-
-Copyright (C) 2004-2005 Nicolai Haehnle et al.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
+/*
+ * Copyright 2005 Nicolai Haehnle et al.
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Nicolai Haehnle
+ *          Jerome Glisse
+ */
+#ifndef _R300_REG_H_
+#define _R300_REG_H_
 
-**************************************************************************/
+#define R300_SURF_TILE_MACRO (1<<16)
+#define R300_SURF_TILE_MICRO (2<<16)
+#define R300_SURF_TILE_BOTH (3<<16)
 
-#ifndef _R300_REG_H
-#define _R300_REG_H
 
 #define R300_MC_INIT_MISC_LAT_TIMER	0x180
 #	define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT	0
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r420.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r420.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r420.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r420.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include <linux/seq_file.h>
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+/* r420,r423,rv410 depends on : */
+void r100_pci_gart_disable(struct radeon_device *rdev);
+void r100_hdp_reset(struct radeon_device *rdev);
+void r100_mc_setup(struct radeon_device *rdev);
+int r100_gui_wait_for_idle(struct radeon_device *rdev);
+void r100_mc_disable_clients(struct radeon_device *rdev);
+void r300_vram_info(struct radeon_device *rdev);
+int r300_mc_wait_for_idle(struct radeon_device *rdev);
+int rv370_pcie_gart_enable(struct radeon_device *rdev);
+void rv370_pcie_gart_disable(struct radeon_device *rdev);
+
+/* This files gather functions specifics to :
+ * r420,r423,rv410
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+void r420_gpu_init(struct radeon_device *rdev);
+int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
+
+
+/*
+ * MC
+ */
+int r420_mc_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+	if (r420_debugfs_pipes_info_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for pipes !\n");
+	}
+
+	r420_gpu_init(rdev);
+	r100_pci_gart_disable(rdev);
+	if (rdev->flags & RADEON_IS_PCIE) {
+		rv370_pcie_gart_disable(rdev);
+	}
+
+	/* Setup GPU memory space */
+	rdev->mc.vram_location = 0xFFFFFFFFUL;
+	rdev->mc.gtt_location = 0xFFFFFFFFUL;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			printk(KERN_WARNING "[drm] Disabling AGP\n");
+			rdev->flags &= ~RADEON_IS_AGP;
+			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+		} else {
+			rdev->mc.gtt_location = rdev->mc.agp_base;
+		}
+	}
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	/* Program GPU memory space */
+	r100_mc_disable_clients(rdev);
+	if (r300_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	r100_mc_setup(rdev);
+	return 0;
+}
+
+void r420_mc_fini(struct radeon_device *rdev)
+{
+	rv370_pcie_gart_disable(rdev);
+	radeon_gart_table_vram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Global GPU functions
+ */
+void r420_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+void r420_pipes_init(struct radeon_device *rdev)
+{
+	unsigned tmp;
+	unsigned gb_pipe_select;
+	unsigned num_pipes;
+
+	/* GA_ENHANCE workaround TCL deadlock issue */
+	WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
+	/* get max number of pipes */
+	gb_pipe_select = RREG32(0x402C);
+	num_pipes = ((gb_pipe_select >> 12) & 3) + 1;
+	rdev->num_gb_pipes = num_pipes;
+	tmp = 0;
+	switch (num_pipes) {
+	default:
+		/* force to 1 pipe */
+		num_pipes = 1;
+	case 1:
+		tmp = (0 << 1);
+		break;
+	case 2:
+		tmp = (3 << 1);
+		break;
+	case 3:
+		tmp = (6 << 1);
+		break;
+	case 4:
+		tmp = (7 << 1);
+		break;
+	}
+	WREG32(0x42C8, (1 << num_pipes) - 1);
+	/* Sub pixel 1/12 so we can have 4K rendering according to doc */
+	tmp |= (1 << 4) | (1 << 0);
+	WREG32(0x4018, tmp);
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	tmp = RREG32(0x170C);
+	WREG32(0x170C, tmp | (1 << 31));
+
+	WREG32(R300_RB2D_DSTCACHE_MODE,
+	       RREG32(R300_RB2D_DSTCACHE_MODE) |
+	       R300_DC_AUTOFLUSH_ENABLE |
+	       R300_DC_DC_DISABLE_IGNORE_PE);
+
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	if (rdev->family == CHIP_RV530) {
+		tmp = RREG32(RV530_GB_PIPE_SELECT2);
+		if ((tmp & 3) == 3)
+			rdev->num_z_pipes = 2;
+		else
+			rdev->num_z_pipes = 1;
+	} else
+		rdev->num_z_pipes = 1;
+
+	DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n",
+		 rdev->num_gb_pipes, rdev->num_z_pipes);
+}
+
+void r420_gpu_init(struct radeon_device *rdev)
+{
+	r100_hdp_reset(rdev);
+	r420_pipes_init(rdev);
+	if (r300_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+}
+
+
+/*
+ * r420,r423,rv410 VRAM info
+ */
+void r420_vram_info(struct radeon_device *rdev)
+{
+	r300_vram_info(rdev);
+}
+
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int r420_debugfs_pipes_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = RREG32(R400_GB_PIPE_SELECT);
+	seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp);
+	tmp = RREG32(R300_GB_TILE_CONFIG);
+	seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp);
+	tmp = RREG32(R300_DST_PIPE_CONFIG);
+	seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp);
+	return 0;
+}
+
+static struct drm_info_list r420_pipes_info_list[] = {
+	{"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL},
+};
+#endif
+
+int r420_debugfs_pipes_info_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1);
+#else
+	return 0;
+#endif
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r500_reg.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r500_reg.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r500_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r500_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,759 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __R500_REG_H__
+#define __R500_REG_H__
+
+/* pipe config regs */
+#define R300_GA_POLY_MODE				0x4288
+#       define R300_FRONT_PTYPE_POINT                   (0 << 4)
+#       define R300_FRONT_PTYPE_LINE                    (1 << 4)
+#       define R300_FRONT_PTYPE_TRIANGE                 (2 << 4)
+#       define R300_BACK_PTYPE_POINT                    (0 << 7)
+#       define R300_BACK_PTYPE_LINE                     (1 << 7)
+#       define R300_BACK_PTYPE_TRIANGE                  (2 << 7)
+#define R300_GA_ROUND_MODE				0x428c
+#       define R300_GEOMETRY_ROUND_TRUNC                (0 << 0)
+#       define R300_GEOMETRY_ROUND_NEAREST              (1 << 0)
+#       define R300_COLOR_ROUND_TRUNC                   (0 << 2)
+#       define R300_COLOR_ROUND_NEAREST                 (1 << 2)
+#define R300_GB_MSPOS0				        0x4010
+#       define R300_MS_X0_SHIFT                         0
+#       define R300_MS_Y0_SHIFT                         4
+#       define R300_MS_X1_SHIFT                         8
+#       define R300_MS_Y1_SHIFT                         12
+#       define R300_MS_X2_SHIFT                         16
+#       define R300_MS_Y2_SHIFT                         20
+#       define R300_MSBD0_Y_SHIFT                       24
+#       define R300_MSBD0_X_SHIFT                       28
+#define R300_GB_MSPOS1				        0x4014
+#       define R300_MS_X3_SHIFT                         0
+#       define R300_MS_Y3_SHIFT                         4
+#       define R300_MS_X4_SHIFT                         8
+#       define R300_MS_Y4_SHIFT                         12
+#       define R300_MS_X5_SHIFT                         16
+#       define R300_MS_Y5_SHIFT                         20
+#       define R300_MSBD1_SHIFT                         24
+
+#define R300_GA_ENHANCE				        0x4274
+#       define R300_GA_DEADLOCK_CNTL                    (1 << 0)
+#       define R300_GA_FASTSYNC_CNTL                    (1 << 1)
+#define R300_RB3D_DSTCACHE_CTLSTAT              0x4e4c
+#	define R300_RB3D_DC_FLUSH		(2 << 0)
+#	define R300_RB3D_DC_FREE		(2 << 2)
+#	define R300_RB3D_DC_FINISH		(1 << 4)
+#define R300_RB3D_ZCACHE_CTLSTAT			0x4f18
+#       define R300_ZC_FLUSH                            (1 << 0)
+#       define R300_ZC_FREE                             (1 << 1)
+#       define R300_ZC_FLUSH_ALL                        0x3
+#define R400_GB_PIPE_SELECT             0x402c
+#define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
+#define R500_SU_REG_DEST                0x42c8
+#define R300_GB_TILE_CONFIG             0x4018
+#       define R300_ENABLE_TILING       (1 << 0)
+#       define R300_PIPE_COUNT_RV350    (0 << 1)
+#       define R300_PIPE_COUNT_R300     (3 << 1)
+#       define R300_PIPE_COUNT_R420_3P  (6 << 1)
+#       define R300_PIPE_COUNT_R420     (7 << 1)
+#       define R300_TILE_SIZE_8         (0 << 4)
+#       define R300_TILE_SIZE_16        (1 << 4)
+#       define R300_TILE_SIZE_32        (2 << 4)
+#       define R300_SUBPIXEL_1_12       (0 << 16)
+#       define R300_SUBPIXEL_1_16       (1 << 16)
+#define R300_DST_PIPE_CONFIG            0x170c
+#       define R300_PIPE_AUTO_CONFIG    (1 << 31)
+#define R300_RB2D_DSTCACHE_MODE         0x3428
+#       define R300_DC_AUTOFLUSH_ENABLE (1 << 8)
+#       define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17)
+
+#define RADEON_CP_STAT		0x7C0
+#define RADEON_RBBM_CMDFIFO_ADDR	0xE70
+#define RADEON_RBBM_CMDFIFO_DATA	0xE74
+#define RADEON_ISYNC_CNTL		0x1724
+#	define RADEON_ISYNC_ANY2D_IDLE3D	(1 << 0)
+#	define RADEON_ISYNC_ANY3D_IDLE2D	(1 << 1)
+#	define RADEON_ISYNC_TRIG2D_IDLE3D	(1 << 2)
+#	define RADEON_ISYNC_TRIG3D_IDLE2D	(1 << 3)
+#	define RADEON_ISYNC_WAIT_IDLEGUI	(1 << 4)
+#	define RADEON_ISYNC_CPSCRATCH_IDLEGUI	(1 << 5)
+
+#define RS480_NB_MC_INDEX               0x168
+#	define RS480_NB_MC_IND_WR_EN	(1 << 8)
+#define RS480_NB_MC_DATA                0x16c
+
+/*
+ * RS690
+ */
+#define RS690_MCCFG_FB_LOCATION		0x100
+#define		RS690_MC_FB_START_MASK		0x0000FFFF
+#define		RS690_MC_FB_START_SHIFT		0
+#define		RS690_MC_FB_TOP_MASK		0xFFFF0000
+#define		RS690_MC_FB_TOP_SHIFT		16
+#define RS690_MCCFG_AGP_LOCATION	0x101
+#define		RS690_MC_AGP_START_MASK		0x0000FFFF
+#define		RS690_MC_AGP_START_SHIFT	0
+#define		RS690_MC_AGP_TOP_MASK		0xFFFF0000
+#define		RS690_MC_AGP_TOP_SHIFT		16
+#define RS690_MCCFG_AGP_BASE		0x102
+#define RS690_MCCFG_AGP_BASE_2		0x103
+#define RS690_MC_INIT_MISC_LAT_TIMER            0x104
+#define RS690_HDP_FB_LOCATION		0x0134
+#define RS690_MC_INDEX				0x78
+#	define RS690_MC_INDEX_MASK		0x1ff
+#	define RS690_MC_INDEX_WR_EN		(1 << 9)
+#	define RS690_MC_INDEX_WR_ACK		0x7f
+#define RS690_MC_DATA				0x7c
+#define RS690_MC_STATUS                         0x90
+#define RS690_MC_STATUS_IDLE                    (1 << 0)
+#define RS480_AGP_BASE_2		0x0164
+#define RS480_MC_MISC_CNTL              0x18
+#	define RS480_DISABLE_GTW	(1 << 1)
+#	define RS480_GART_INDEX_REG_EN	(1 << 12)
+#	define RS690_BLOCK_GFX_D3_EN	(1 << 14)
+#define RS480_GART_FEATURE_ID           0x2b
+#	define RS480_HANG_EN	        (1 << 11)
+#	define RS480_TLB_ENABLE	        (1 << 18)
+#	define RS480_P2P_ENABLE	        (1 << 19)
+#	define RS480_GTW_LAC_EN	        (1 << 25)
+#	define RS480_2LEVEL_GART	(0 << 30)
+#	define RS480_1LEVEL_GART	(1 << 30)
+#	define RS480_PDC_EN	        (1 << 31)
+#define RS480_GART_BASE                 0x2c
+#define RS480_GART_CACHE_CNTRL          0x2e
+#	define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */
+#define RS480_AGP_ADDRESS_SPACE_SIZE    0x38
+#	define RS480_GART_EN	        (1 << 0)
+#	define RS480_VA_SIZE_32MB	(0 << 1)
+#	define RS480_VA_SIZE_64MB	(1 << 1)
+#	define RS480_VA_SIZE_128MB	(2 << 1)
+#	define RS480_VA_SIZE_256MB	(3 << 1)
+#	define RS480_VA_SIZE_512MB	(4 << 1)
+#	define RS480_VA_SIZE_1GB	(5 << 1)
+#	define RS480_VA_SIZE_2GB	(6 << 1)
+#define RS480_AGP_MODE_CNTL             0x39
+#	define RS480_POST_GART_Q_SIZE	(1 << 18)
+#	define RS480_NONGART_SNOOP	(1 << 19)
+#	define RS480_AGP_RD_BUF_SIZE	(1 << 20)
+#	define RS480_REQ_TYPE_SNOOP_SHIFT 22
+#	define RS480_REQ_TYPE_SNOOP_MASK  0x3
+#	define RS480_REQ_TYPE_SNOOP_DIS	(1 << 24)
+
+#define RS690_AIC_CTRL_SCRATCH		0x3A
+#	define RS690_DIS_OUT_OF_PCI_GART_ACCESS	(1 << 1)
+
+/*
+ * RS600
+ */
+#define RS600_MC_STATUS                         0x0
+#define RS600_MC_STATUS_IDLE                    (1 << 0)
+#define RS600_MC_INDEX                          0x70
+#       define RS600_MC_ADDR_MASK               0xffff
+#       define RS600_MC_IND_SEQ_RBS_0           (1 << 16)
+#       define RS600_MC_IND_SEQ_RBS_1           (1 << 17)
+#       define RS600_MC_IND_SEQ_RBS_2           (1 << 18)
+#       define RS600_MC_IND_SEQ_RBS_3           (1 << 19)
+#       define RS600_MC_IND_AIC_RBS             (1 << 20)
+#       define RS600_MC_IND_CITF_ARB0           (1 << 21)
+#       define RS600_MC_IND_CITF_ARB1           (1 << 22)
+#       define RS600_MC_IND_WR_EN               (1 << 23)
+#define RS600_MC_DATA                           0x74
+#define RS600_MC_STATUS                         0x0
+#       define RS600_MC_IDLE                    (1 << 1)
+#define RS600_MC_FB_LOCATION                    0x4
+#define		RS600_MC_FB_START_MASK		0x0000FFFF
+#define		RS600_MC_FB_START_SHIFT		0
+#define		RS600_MC_FB_TOP_MASK		0xFFFF0000
+#define		RS600_MC_FB_TOP_SHIFT		16
+#define RS600_MC_AGP_LOCATION                   0x5
+#define		RS600_MC_AGP_START_MASK		0x0000FFFF
+#define		RS600_MC_AGP_START_SHIFT	0
+#define		RS600_MC_AGP_TOP_MASK		0xFFFF0000
+#define		RS600_MC_AGP_TOP_SHIFT		16
+#define RS600_MC_AGP_BASE                          0x6
+#define RS600_MC_AGP_BASE_2                        0x7
+#define RS600_MC_CNTL1                          0x9
+#       define RS600_ENABLE_PAGE_TABLES         (1 << 26)
+#define RS600_MC_PT0_CNTL                       0x100
+#       define RS600_ENABLE_PT                  (1 << 0)
+#       define RS600_EFFECTIVE_L2_CACHE_SIZE(x) ((x) << 15)
+#       define RS600_EFFECTIVE_L2_QUEUE_SIZE(x) ((x) << 21)
+#       define RS600_INVALIDATE_ALL_L1_TLBS     (1 << 28)
+#       define RS600_INVALIDATE_L2_CACHE        (1 << 29)
+#define RS600_MC_PT0_CONTEXT0_CNTL              0x102
+#       define RS600_ENABLE_PAGE_TABLE          (1 << 0)
+#       define RS600_PAGE_TABLE_TYPE_FLAT       (0 << 1)
+#define RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR   0x112
+#define RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR  0x114
+#define RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x11c
+#define RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR    0x12c
+#define RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR   0x13c
+#define RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR     0x14c
+#define RS600_MC_PT0_CLIENT0_CNTL               0x16c
+#       define RS600_ENABLE_TRANSLATION_MODE_OVERRIDE       (1 << 0)
+#       define RS600_TRANSLATION_MODE_OVERRIDE              (1 << 1)
+#       define RS600_SYSTEM_ACCESS_MODE_MASK                (3 << 8)
+#       define RS600_SYSTEM_ACCESS_MODE_PA_ONLY             (0 << 8)
+#       define RS600_SYSTEM_ACCESS_MODE_USE_SYS_MAP         (1 << 8)
+#       define RS600_SYSTEM_ACCESS_MODE_IN_SYS              (2 << 8)
+#       define RS600_SYSTEM_ACCESS_MODE_NOT_IN_SYS          (3 << 8)
+#       define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH        (0 << 10)
+#       define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE       (1 << 10)
+#       define RS600_EFFECTIVE_L1_CACHE_SIZE(x) ((x) << 11)
+#       define RS600_ENABLE_FRAGMENT_PROCESSING (1 << 14)
+#       define RS600_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15)
+#       define RS600_INVALIDATE_L1_TLB          (1 << 20)
+/* rs600/rs690/rs740 */
+#	define RS600_BUS_MASTER_DIS		(1 << 14)
+#	define RS600_MSI_REARM		        (1 << 20)
+/* see RS400_MSI_REARM in AIC_CNTL for rs480 */
+
+
+
+#define RV515_MC_FB_LOCATION		0x01
+#define		RV515_MC_FB_START_MASK		0x0000FFFF
+#define		RV515_MC_FB_START_SHIFT		0
+#define		RV515_MC_FB_TOP_MASK		0xFFFF0000
+#define		RV515_MC_FB_TOP_SHIFT		16
+#define RV515_MC_AGP_LOCATION		0x02
+#define		RV515_MC_AGP_START_MASK		0x0000FFFF
+#define		RV515_MC_AGP_START_SHIFT	0
+#define		RV515_MC_AGP_TOP_MASK		0xFFFF0000
+#define		RV515_MC_AGP_TOP_SHIFT		16
+#define RV515_MC_AGP_BASE		0x03
+#define RV515_MC_AGP_BASE_2		0x04
+
+#define R520_MC_FB_LOCATION		0x04
+#define		R520_MC_FB_START_MASK		0x0000FFFF
+#define		R520_MC_FB_START_SHIFT		0
+#define		R520_MC_FB_TOP_MASK		0xFFFF0000
+#define		R520_MC_FB_TOP_SHIFT		16
+#define R520_MC_AGP_LOCATION		0x05
+#define		R520_MC_AGP_START_MASK		0x0000FFFF
+#define		R520_MC_AGP_START_SHIFT		0
+#define		R520_MC_AGP_TOP_MASK		0xFFFF0000
+#define		R520_MC_AGP_TOP_SHIFT		16
+#define R520_MC_AGP_BASE		0x06
+#define R520_MC_AGP_BASE_2		0x07
+
+
+#define AVIVO_MC_INDEX						0x0070
+#define R520_MC_STATUS 0x00
+#define R520_MC_STATUS_IDLE (1<<1)
+#define RV515_MC_STATUS 0x08
+#define RV515_MC_STATUS_IDLE (1<<4)
+#define RV515_MC_INIT_MISC_LAT_TIMER            0x09
+#define AVIVO_MC_DATA						0x0074
+
+#define R520_MC_IND_INDEX 0x70
+#define R520_MC_IND_WR_EN (1 << 24)
+#define R520_MC_IND_DATA  0x74
+
+#define RV515_MC_CNTL          0x5
+#	define RV515_MEM_NUM_CHANNELS_MASK  0x3
+#define R520_MC_CNTL0          0x8
+#	define R520_MEM_NUM_CHANNELS_MASK  (0x3 << 24)
+#	define R520_MEM_NUM_CHANNELS_SHIFT  24
+#	define R520_MC_CHANNEL_SIZE  (1 << 23)
+
+#define AVIVO_CP_DYN_CNTL                              0x000f /* PLL */
+#       define AVIVO_CP_FORCEON                        (1 << 0)
+#define AVIVO_E2_DYN_CNTL                              0x0011 /* PLL */
+#       define AVIVO_E2_FORCEON                        (1 << 0)
+#define AVIVO_IDCT_DYN_CNTL                            0x0013 /* PLL */
+#       define AVIVO_IDCT_FORCEON                      (1 << 0)
+
+#define AVIVO_HDP_FB_LOCATION 0x134
+
+#define AVIVO_VGA_RENDER_CONTROL				0x0300
+#       define AVIVO_VGA_VSTATUS_CNTL_MASK                      (3 << 16)
+#define AVIVO_D1VGA_CONTROL					0x0330
+#       define AVIVO_DVGA_CONTROL_MODE_ENABLE (1<<0)
+#       define AVIVO_DVGA_CONTROL_TIMING_SELECT (1<<8)
+#       define AVIVO_DVGA_CONTROL_SYNC_POLARITY_SELECT (1<<9)
+#       define AVIVO_DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1<<10)
+#       define AVIVO_DVGA_CONTROL_OVERSCAN_COLOR_EN (1<<16)
+#       define AVIVO_DVGA_CONTROL_ROTATE (1<<24)
+#define AVIVO_D2VGA_CONTROL					0x0338
+
+#define AVIVO_EXT1_PPLL_REF_DIV_SRC                             0x400
+#define AVIVO_EXT1_PPLL_REF_DIV                                 0x404
+#define AVIVO_EXT1_PPLL_UPDATE_LOCK                             0x408
+#define AVIVO_EXT1_PPLL_UPDATE_CNTL                             0x40c
+
+#define AVIVO_EXT2_PPLL_REF_DIV_SRC                             0x410
+#define AVIVO_EXT2_PPLL_REF_DIV                                 0x414
+#define AVIVO_EXT2_PPLL_UPDATE_LOCK                             0x418
+#define AVIVO_EXT2_PPLL_UPDATE_CNTL                             0x41c
+
+#define AVIVO_EXT1_PPLL_FB_DIV                                   0x430
+#define AVIVO_EXT2_PPLL_FB_DIV                                   0x434
+
+#define AVIVO_EXT1_PPLL_POST_DIV_SRC                                 0x438
+#define AVIVO_EXT1_PPLL_POST_DIV                                     0x43c
+
+#define AVIVO_EXT2_PPLL_POST_DIV_SRC                                 0x440
+#define AVIVO_EXT2_PPLL_POST_DIV                                     0x444
+
+#define AVIVO_EXT1_PPLL_CNTL                                    0x448
+#define AVIVO_EXT2_PPLL_CNTL                                    0x44c
+
+#define AVIVO_P1PLL_CNTL                                        0x450
+#define AVIVO_P2PLL_CNTL                                        0x454
+#define AVIVO_P1PLL_INT_SS_CNTL                                 0x458
+#define AVIVO_P2PLL_INT_SS_CNTL                                 0x45c
+#define AVIVO_P1PLL_TMDSA_CNTL                                  0x460
+#define AVIVO_P2PLL_LVTMA_CNTL                                  0x464
+
+#define AVIVO_PCLK_CRTC1_CNTL                                   0x480
+#define AVIVO_PCLK_CRTC2_CNTL                                   0x484
+
+#define AVIVO_D1CRTC_H_TOTAL					0x6000
+#define AVIVO_D1CRTC_H_BLANK_START_END                          0x6004
+#define AVIVO_D1CRTC_H_SYNC_A                                   0x6008
+#define AVIVO_D1CRTC_H_SYNC_A_CNTL                              0x600c
+#define AVIVO_D1CRTC_H_SYNC_B                                   0x6010
+#define AVIVO_D1CRTC_H_SYNC_B_CNTL                              0x6014
+
+#define AVIVO_D1CRTC_V_TOTAL					0x6020
+#define AVIVO_D1CRTC_V_BLANK_START_END                          0x6024
+#define AVIVO_D1CRTC_V_SYNC_A                                   0x6028
+#define AVIVO_D1CRTC_V_SYNC_A_CNTL                              0x602c
+#define AVIVO_D1CRTC_V_SYNC_B                                   0x6030
+#define AVIVO_D1CRTC_V_SYNC_B_CNTL                              0x6034
+
+#define AVIVO_D1CRTC_CONTROL                                    0x6080
+#       define AVIVO_CRTC_EN                                    (1 << 0)
+#define AVIVO_D1CRTC_BLANK_CONTROL                              0x6084
+#define AVIVO_D1CRTC_INTERLACE_CONTROL                          0x6088
+#define AVIVO_D1CRTC_INTERLACE_STATUS                           0x608c
+#define AVIVO_D1CRTC_FRAME_COUNT                                0x60a4
+#define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4
+
+/* master controls */
+#define AVIVO_DC_CRTC_MASTER_EN                                 0x60f8
+#define AVIVO_DC_CRTC_TV_CONTROL                                0x60fc
+
+#define AVIVO_D1GRPH_ENABLE                                     0x6100
+#define AVIVO_D1GRPH_CONTROL                                    0x6104
+#       define AVIVO_D1GRPH_CONTROL_DEPTH_8BPP                  (0 << 0)
+#       define AVIVO_D1GRPH_CONTROL_DEPTH_16BPP                 (1 << 0)
+#       define AVIVO_D1GRPH_CONTROL_DEPTH_32BPP                 (2 << 0)
+#       define AVIVO_D1GRPH_CONTROL_DEPTH_64BPP                 (3 << 0)
+
+#       define AVIVO_D1GRPH_CONTROL_8BPP_INDEXED                (0 << 8)
+
+#       define AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555              (0 << 8)
+#       define AVIVO_D1GRPH_CONTROL_16BPP_RGB565                (1 << 8)
+#       define AVIVO_D1GRPH_CONTROL_16BPP_ARGB4444              (2 << 8)
+#       define AVIVO_D1GRPH_CONTROL_16BPP_AI88                  (3 << 8)
+#       define AVIVO_D1GRPH_CONTROL_16BPP_MONO16                (4 << 8)
+
+#       define AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888              (0 << 8)
+#       define AVIVO_D1GRPH_CONTROL_32BPP_ARGB2101010           (1 << 8)
+#       define AVIVO_D1GRPH_CONTROL_32BPP_DIGITAL               (2 << 8)
+#       define AVIVO_D1GRPH_CONTROL_32BPP_8B_ARGB2101010        (3 << 8)
+
+
+#       define AVIVO_D1GRPH_CONTROL_64BPP_ARGB16161616          (0 << 8)
+
+#       define AVIVO_D1GRPH_SWAP_RB                             (1 << 16)
+#       define AVIVO_D1GRPH_TILED                               (1 << 20)
+#       define AVIVO_D1GRPH_MACRO_ADDRESS_MODE                  (1 << 21)
+
+#define AVIVO_D1GRPH_LUT_SEL                                    0x6108
+#define AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS                    0x6110
+#define AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS                  0x6118
+#define AVIVO_D1GRPH_PITCH                                      0x6120
+#define AVIVO_D1GRPH_SURFACE_OFFSET_X                           0x6124
+#define AVIVO_D1GRPH_SURFACE_OFFSET_Y                           0x6128
+#define AVIVO_D1GRPH_X_START                                    0x612c
+#define AVIVO_D1GRPH_Y_START                                    0x6130
+#define AVIVO_D1GRPH_X_END                                      0x6134
+#define AVIVO_D1GRPH_Y_END                                      0x6138
+#define AVIVO_D1GRPH_UPDATE                                     0x6144
+#       define AVIVO_D1GRPH_UPDATE_LOCK                         (1 << 16)
+#define AVIVO_D1GRPH_FLIP_CONTROL                               0x6148
+
+#define AVIVO_D1CUR_CONTROL                     0x6400
+#       define AVIVO_D1CURSOR_EN                (1 << 0)
+#       define AVIVO_D1CURSOR_MODE_SHIFT        8
+#       define AVIVO_D1CURSOR_MODE_MASK         (3 << 8)
+#       define AVIVO_D1CURSOR_MODE_24BPP        2
+#define AVIVO_D1CUR_SURFACE_ADDRESS             0x6408
+#define AVIVO_D1CUR_SIZE                        0x6410
+#define AVIVO_D1CUR_POSITION                    0x6414
+#define AVIVO_D1CUR_HOT_SPOT                    0x6418
+#define AVIVO_D1CUR_UPDATE                      0x6424
+#       define AVIVO_D1CURSOR_UPDATE_LOCK       (1 << 16)
+
+#define AVIVO_DC_LUT_RW_SELECT                  0x6480
+#define AVIVO_DC_LUT_RW_MODE                    0x6484
+#define AVIVO_DC_LUT_RW_INDEX                   0x6488
+#define AVIVO_DC_LUT_SEQ_COLOR                  0x648c
+#define AVIVO_DC_LUT_PWL_DATA                   0x6490
+#define AVIVO_DC_LUT_30_COLOR                   0x6494
+#define AVIVO_DC_LUT_READ_PIPE_SELECT           0x6498
+#define AVIVO_DC_LUT_WRITE_EN_MASK              0x649c
+#define AVIVO_DC_LUT_AUTOFILL                   0x64a0
+
+#define AVIVO_DC_LUTA_CONTROL                   0x64c0
+#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE         0x64c4
+#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN        0x64c8
+#define AVIVO_DC_LUTA_BLACK_OFFSET_RED          0x64cc
+#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE         0x64d0
+#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN        0x64d4
+#define AVIVO_DC_LUTA_WHITE_OFFSET_RED          0x64d8
+
+#define AVIVO_DC_LB_MEMORY_SPLIT                0x6520
+#       define AVIVO_DC_LB_MEMORY_SPLIT_MASK    0x3
+#       define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT   0
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF  0
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q    1
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY        2
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q    3
+#       define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2)
+#       define AVIVO_DC_LB_DISP1_END_ADR_SHIFT  4
+#       define AVIVO_DC_LB_DISP1_END_ADR_MASK   0x7ff
+
+#define AVIVO_D1MODE_DATA_FORMAT                0x6528
+#       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
+#define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652C
+#define AVIVO_D1MODE_VBLANK_STATUS              0x6534
+#       define AVIVO_VBLANK_ACK                 (1 << 4)
+#define AVIVO_D1MODE_VLINE_START_END            0x6538
+#define AVIVO_DxMODE_INT_MASK                   0x6540
+#       define AVIVO_D1MODE_INT_MASK            (1 << 0)
+#       define AVIVO_D2MODE_INT_MASK            (1 << 8)
+#define AVIVO_D1MODE_VIEWPORT_START             0x6580
+#define AVIVO_D1MODE_VIEWPORT_SIZE              0x6584
+#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6588
+#define AVIVO_D1MODE_EXT_OVERSCAN_TOP_BOTTOM    0x658c
+
+#define AVIVO_D1SCL_SCALER_ENABLE               0x6590
+#define AVIVO_D1SCL_SCALER_TAP_CONTROL		0x6594
+#define AVIVO_D1SCL_UPDATE                      0x65cc
+#       define AVIVO_D1SCL_UPDATE_LOCK          (1 << 16)
+
+/* second crtc */
+#define AVIVO_D2CRTC_H_TOTAL					0x6800
+#define AVIVO_D2CRTC_H_BLANK_START_END                          0x6804
+#define AVIVO_D2CRTC_H_SYNC_A                                   0x6808
+#define AVIVO_D2CRTC_H_SYNC_A_CNTL                              0x680c
+#define AVIVO_D2CRTC_H_SYNC_B                                   0x6810
+#define AVIVO_D2CRTC_H_SYNC_B_CNTL                              0x6814
+
+#define AVIVO_D2CRTC_V_TOTAL					0x6820
+#define AVIVO_D2CRTC_V_BLANK_START_END                          0x6824
+#define AVIVO_D2CRTC_V_SYNC_A                                   0x6828
+#define AVIVO_D2CRTC_V_SYNC_A_CNTL                              0x682c
+#define AVIVO_D2CRTC_V_SYNC_B                                   0x6830
+#define AVIVO_D2CRTC_V_SYNC_B_CNTL                              0x6834
+
+#define AVIVO_D2CRTC_CONTROL                                    0x6880
+#define AVIVO_D2CRTC_BLANK_CONTROL                              0x6884
+#define AVIVO_D2CRTC_INTERLACE_CONTROL                          0x6888
+#define AVIVO_D2CRTC_INTERLACE_STATUS                           0x688c
+#define AVIVO_D2CRTC_FRAME_COUNT                                0x68a4
+#define AVIVO_D2CRTC_STEREO_CONTROL                             0x68c4
+
+#define AVIVO_D2GRPH_ENABLE                                     0x6900
+#define AVIVO_D2GRPH_CONTROL                                    0x6904
+#define AVIVO_D2GRPH_LUT_SEL                                    0x6908
+#define AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS                    0x6910
+#define AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS                  0x6918
+#define AVIVO_D2GRPH_PITCH                                      0x6920
+#define AVIVO_D2GRPH_SURFACE_OFFSET_X                           0x6924
+#define AVIVO_D2GRPH_SURFACE_OFFSET_Y                           0x6928
+#define AVIVO_D2GRPH_X_START                                    0x692c
+#define AVIVO_D2GRPH_Y_START                                    0x6930
+#define AVIVO_D2GRPH_X_END                                      0x6934
+#define AVIVO_D2GRPH_Y_END                                      0x6938
+#define AVIVO_D2GRPH_UPDATE                                     0x6944
+#define AVIVO_D2GRPH_FLIP_CONTROL                               0x6948
+
+#define AVIVO_D2CUR_CONTROL                     0x6c00
+#define AVIVO_D2CUR_SURFACE_ADDRESS             0x6c08
+#define AVIVO_D2CUR_SIZE                        0x6c10
+#define AVIVO_D2CUR_POSITION                    0x6c14
+
+#define AVIVO_D2MODE_VBLANK_STATUS              0x6d34
+#define AVIVO_D2MODE_VLINE_START_END            0x6d38
+#define AVIVO_D2MODE_VIEWPORT_START             0x6d80
+#define AVIVO_D2MODE_VIEWPORT_SIZE              0x6d84
+#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6d88
+#define AVIVO_D2MODE_EXT_OVERSCAN_TOP_BOTTOM    0x6d8c
+
+#define AVIVO_D2SCL_SCALER_ENABLE               0x6d90
+#define AVIVO_D2SCL_SCALER_TAP_CONTROL		0x6d94
+
+#define AVIVO_DDIA_BIT_DEPTH_CONTROL				0x7214
+
+#define AVIVO_DACA_ENABLE					0x7800
+#	define AVIVO_DAC_ENABLE				(1 << 0)
+#define AVIVO_DACA_SOURCE_SELECT				0x7804
+#       define AVIVO_DAC_SOURCE_CRTC1                   (0 << 0)
+#       define AVIVO_DAC_SOURCE_CRTC2                   (1 << 0)
+#       define AVIVO_DAC_SOURCE_TV                      (2 << 0)
+
+#define AVIVO_DACA_FORCE_OUTPUT_CNTL				0x783c
+# define AVIVO_DACA_FORCE_OUTPUT_CNTL_FORCE_DATA_EN             (1 << 0)
+# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT            (8)
+# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE             (1 << 0)
+# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN            (1 << 1)
+# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_RED              (1 << 2)
+# define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY       (1 << 24)
+#define AVIVO_DACA_POWERDOWN					0x7850
+# define AVIVO_DACA_POWERDOWN_POWERDOWN                         (1 << 0)
+# define AVIVO_DACA_POWERDOWN_BLUE                              (1 << 8)
+# define AVIVO_DACA_POWERDOWN_GREEN                             (1 << 16)
+# define AVIVO_DACA_POWERDOWN_RED                               (1 << 24)
+
+#define AVIVO_DACB_ENABLE					0x7a00
+#define AVIVO_DACB_SOURCE_SELECT				0x7a04
+#define AVIVO_DACB_FORCE_OUTPUT_CNTL				0x7a3c
+# define AVIVO_DACB_FORCE_OUTPUT_CNTL_FORCE_DATA_EN             (1 << 0)
+# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT            (8)
+# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE             (1 << 0)
+# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN            (1 << 1)
+# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_RED              (1 << 2)
+# define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY       (1 << 24)
+#define AVIVO_DACB_POWERDOWN					0x7a50
+# define AVIVO_DACB_POWERDOWN_POWERDOWN                         (1 << 0)
+# define AVIVO_DACB_POWERDOWN_BLUE                              (1 << 8)
+# define AVIVO_DACB_POWERDOWN_GREEN                             (1 << 16)
+# define AVIVO_DACB_POWERDOWN_RED
+
+#define AVIVO_TMDSA_CNTL                    0x7880
+#   define AVIVO_TMDSA_CNTL_ENABLE               (1 << 0)
+#   define AVIVO_TMDSA_CNTL_HPD_MASK             (1 << 4)
+#   define AVIVO_TMDSA_CNTL_HPD_SELECT           (1 << 8)
+#   define AVIVO_TMDSA_CNTL_SYNC_PHASE           (1 << 12)
+#   define AVIVO_TMDSA_CNTL_PIXEL_ENCODING       (1 << 16)
+#   define AVIVO_TMDSA_CNTL_DUAL_LINK_ENABLE     (1 << 24)
+#   define AVIVO_TMDSA_CNTL_SWAP                 (1 << 28)
+#define AVIVO_TMDSA_SOURCE_SELECT				0x7884
+/* 78a8 appears to be some kind of (reasonably tolerant) clock?
+ * 78d0 definitely hits the transmitter, definitely clock. */
+/* MYSTERY1 This appears to control dithering? */
+#define AVIVO_TMDSA_BIT_DEPTH_CONTROL		0x7894
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN           (1 << 0)
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH        (1 << 4)
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN     (1 << 8)
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH  (1 << 12)
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN    (1 << 16)
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20)
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL        (1 << 24)
+#   define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26)
+#define AVIVO_TMDSA_DCBALANCER_CONTROL                  0x78d0
+#   define AVIVO_TMDSA_DCBALANCER_CONTROL_EN                  (1 << 0)
+#   define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_EN             (1 << 8)
+#   define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_IN_SHIFT       (16)
+#   define AVIVO_TMDSA_DCBALANCER_CONTROL_FORCE               (1 << 24)
+#define AVIVO_TMDSA_DATA_SYNCHRONIZATION                0x78d8
+#   define AVIVO_TMDSA_DATA_SYNCHRONIZATION_DSYNSEL           (1 << 0)
+#   define AVIVO_TMDSA_DATA_SYNCHRONIZATION_PFREQCHG          (1 << 8)
+#define AVIVO_TMDSA_CLOCK_ENABLE            0x7900
+#define AVIVO_TMDSA_TRANSMITTER_ENABLE              0x7904
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX0_ENABLE          (1 << 0)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKC0EN             (1 << 1)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD00EN            (1 << 2)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD01EN            (1 << 3)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD02EN            (1 << 4)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX1_ENABLE          (1 << 8)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD10EN            (1 << 10)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD11EN            (1 << 11)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD12EN            (1 << 12)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX_ENABLE_HPD_MASK  (1 << 16)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK     (1 << 17)
+#   define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK     (1 << 18)
+
+#define AVIVO_TMDSA_TRANSMITTER_CONTROL				0x7910
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_ENABLE	(1 << 0)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_RESET	(1 << 1)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT	(2)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_IDSCKSEL	        (1 << 4)
+#       define AVIVO_TMDSA_TRANSMITTER_CONTROL_BGSLEEP          (1 << 5)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN	(1 << 6)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK	        (1 << 8)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS	(1 << 13)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK	        (1 << 14)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS	(1 << 15)
+#       define AVIVO_TMDSA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT (16)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_BYPASS_PLL	(1 << 28)
+#       define AVIVO_TMDSA_TRANSMITTER_CONTROL_USE_CLK_DATA     (1 << 29)
+#	define AVIVO_TMDSA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL	(1 << 31)
+
+#define AVIVO_LVTMA_CNTL					0x7a80
+#   define AVIVO_LVTMA_CNTL_ENABLE               (1 << 0)
+#   define AVIVO_LVTMA_CNTL_HPD_MASK             (1 << 4)
+#   define AVIVO_LVTMA_CNTL_HPD_SELECT           (1 << 8)
+#   define AVIVO_LVTMA_CNTL_SYNC_PHASE           (1 << 12)
+#   define AVIVO_LVTMA_CNTL_PIXEL_ENCODING       (1 << 16)
+#   define AVIVO_LVTMA_CNTL_DUAL_LINK_ENABLE     (1 << 24)
+#   define AVIVO_LVTMA_CNTL_SWAP                 (1 << 28)
+#define AVIVO_LVTMA_SOURCE_SELECT                               0x7a84
+#define AVIVO_LVTMA_COLOR_FORMAT                                0x7a88
+#define AVIVO_LVTMA_BIT_DEPTH_CONTROL                           0x7a94
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN           (1 << 0)
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH        (1 << 4)
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN     (1 << 8)
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH  (1 << 12)
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN    (1 << 16)
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20)
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL        (1 << 24)
+#   define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26)
+
+
+
+#define AVIVO_LVTMA_DCBALANCER_CONTROL                  0x7ad0
+#   define AVIVO_LVTMA_DCBALANCER_CONTROL_EN                  (1 << 0)
+#   define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_EN             (1 << 8)
+#   define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_IN_SHIFT       (16)
+#   define AVIVO_LVTMA_DCBALANCER_CONTROL_FORCE               (1 << 24)
+
+#define AVIVO_LVTMA_DATA_SYNCHRONIZATION                0x78d8
+#   define AVIVO_LVTMA_DATA_SYNCHRONIZATION_DSYNSEL           (1 << 0)
+#   define AVIVO_LVTMA_DATA_SYNCHRONIZATION_PFREQCHG          (1 << 8)
+#define R500_LVTMA_CLOCK_ENABLE			0x7b00
+#define R600_LVTMA_CLOCK_ENABLE			0x7b04
+
+#define R500_LVTMA_TRANSMITTER_ENABLE              0x7b04
+#define R600_LVTMA_TRANSMITTER_ENABLE              0x7b08
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC0EN             (1 << 1)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD00EN            (1 << 2)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD01EN            (1 << 3)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD02EN            (1 << 4)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD03EN            (1 << 5)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC1EN             (1 << 9)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD10EN            (1 << 10)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD11EN            (1 << 11)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD12EN            (1 << 12)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK     (1 << 17)
+#   define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK     (1 << 18)
+
+#define R500_LVTMA_TRANSMITTER_CONTROL			        0x7b10
+#define R600_LVTMA_TRANSMITTER_CONTROL			        0x7b14
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_ENABLE	  (1 << 0)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_RESET	  (1 << 1)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT (2)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_IDSCKSEL	          (1 << 4)
+#       define AVIVO_LVTMA_TRANSMITTER_CONTROL_BGSLEEP            (1 << 5)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN	  (1 << 6)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK	          (1 << 8)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS	  (1 << 13)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK	          (1 << 14)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS	  (1 << 15)
+#       define AVIVO_LVTMA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT  (16)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_BYPASS_PLL	  (1 << 28)
+#       define AVIVO_LVTMA_TRANSMITTER_CONTROL_USE_CLK_DATA       (1 << 29)
+#	define AVIVO_LVTMA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL (1 << 31)
+
+#define R500_LVTMA_PWRSEQ_CNTL						0x7af0
+#define R600_LVTMA_PWRSEQ_CNTL						0x7af4
+#	define AVIVO_LVTMA_PWRSEQ_EN					    (1 << 0)
+#	define AVIVO_LVTMA_PWRSEQ_PLL_ENABLE_MASK			    (1 << 2)
+#	define AVIVO_LVTMA_PWRSEQ_PLL_RESET_MASK			    (1 << 3)
+#	define AVIVO_LVTMA_PWRSEQ_TARGET_STATE				    (1 << 4)
+#	define AVIVO_LVTMA_SYNCEN					    (1 << 8)
+#	define AVIVO_LVTMA_SYNCEN_OVRD					    (1 << 9)
+#	define AVIVO_LVTMA_SYNCEN_POL					    (1 << 10)
+#	define AVIVO_LVTMA_DIGON					    (1 << 16)
+#	define AVIVO_LVTMA_DIGON_OVRD					    (1 << 17)
+#	define AVIVO_LVTMA_DIGON_POL					    (1 << 18)
+#	define AVIVO_LVTMA_BLON						    (1 << 24)
+#	define AVIVO_LVTMA_BLON_OVRD					    (1 << 25)
+#	define AVIVO_LVTMA_BLON_POL					    (1 << 26)
+
+#define R500_LVTMA_PWRSEQ_STATE                        0x7af4
+#define R600_LVTMA_PWRSEQ_STATE                        0x7af8
+#       define AVIVO_LVTMA_PWRSEQ_STATE_TARGET_STATE_R          (1 << 0)
+#       define AVIVO_LVTMA_PWRSEQ_STATE_DIGON                   (1 << 1)
+#       define AVIVO_LVTMA_PWRSEQ_STATE_SYNCEN                  (1 << 2)
+#       define AVIVO_LVTMA_PWRSEQ_STATE_BLON                    (1 << 3)
+#       define AVIVO_LVTMA_PWRSEQ_STATE_DONE                    (1 << 4)
+#       define AVIVO_LVTMA_PWRSEQ_STATE_STATUS_SHIFT            (8)
+
+#define AVIVO_LVDS_BACKLIGHT_CNTL			0x7af8
+#	define AVIVO_LVDS_BACKLIGHT_CNTL_EN			(1 << 0)
+#	define AVIVO_LVDS_BACKLIGHT_LEVEL_MASK		0x0000ff00
+#	define AVIVO_LVDS_BACKLIGHT_LEVEL_SHIFT		8
+
+#define AVIVO_DVOA_BIT_DEPTH_CONTROL			0x7988
+
+#define AVIVO_GPIO_0                        0x7e30
+#define AVIVO_GPIO_1                        0x7e40
+#define AVIVO_GPIO_2                        0x7e50
+#define AVIVO_GPIO_3                        0x7e60
+
+#define AVIVO_DC_GPIO_HPD_Y                 0x7e9c
+
+#define AVIVO_I2C_STATUS					0x7d30
+#	define AVIVO_I2C_STATUS_DONE				(1 << 0)
+#	define AVIVO_I2C_STATUS_NACK				(1 << 1)
+#	define AVIVO_I2C_STATUS_HALT				(1 << 2)
+#	define AVIVO_I2C_STATUS_GO				(1 << 3)
+#	define AVIVO_I2C_STATUS_MASK				0x7
+/* If radeon_mm_i2c is to be believed, this is HALT, NACK, and maybe
+ * DONE? */
+#	define AVIVO_I2C_STATUS_CMD_RESET			0x7
+#	define AVIVO_I2C_STATUS_CMD_WAIT			(1 << 3)
+#define AVIVO_I2C_STOP						0x7d34
+#define AVIVO_I2C_START_CNTL				0x7d38
+#	define AVIVO_I2C_START						(1 << 8)
+#	define AVIVO_I2C_CONNECTOR0					(0 << 16)
+#	define AVIVO_I2C_CONNECTOR1					(1 << 16)
+#define R520_I2C_START (1<<0)
+#define R520_I2C_STOP (1<<1)
+#define R520_I2C_RX (1<<2)
+#define R520_I2C_EN (1<<8)
+#define R520_I2C_DDC1 (0<<16)
+#define R520_I2C_DDC2 (1<<16)
+#define R520_I2C_DDC3 (2<<16)
+#define R520_I2C_DDC_MASK (3<<16)
+#define AVIVO_I2C_CONTROL2					0x7d3c
+#	define AVIVO_I2C_7D3C_SIZE_SHIFT			8
+#	define AVIVO_I2C_7D3C_SIZE_MASK				(0xf << 8)
+#define AVIVO_I2C_CONTROL3						0x7d40
+/* Reading is done 4 bytes at a time: read the bottom 8 bits from
+ * 7d44, four times in a row.
+ * Writing is a little more complex.  First write DATA with
+ * 0xnnnnnnzz, then 0xnnnnnnyy, where nnnnnn is some non-deterministic
+ * magic number, zz is, I think, the slave address, and yy is the byte
+ * you want to write. */
+#define AVIVO_I2C_DATA						0x7d44
+#define R520_I2C_ADDR_COUNT_MASK (0x7)
+#define R520_I2C_DATA_COUNT_SHIFT (8)
+#define R520_I2C_DATA_COUNT_MASK (0xF00)
+#define AVIVO_I2C_CNTL						0x7d50
+#	define AVIVO_I2C_EN							(1 << 0)
+#	define AVIVO_I2C_RESET						(1 << 8)
+
+#define AVIVO_DISP_INTERRUPT_STATUS                             0x7edc
+#       define AVIVO_D1_VBLANK_INTERRUPT                        (1 << 4)
+#       define AVIVO_D2_VBLANK_INTERRUPT                        (1 << 5)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r520.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r520.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r520.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r520.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "radeon_share.h"
+
+/* r520,rv530,rv560,rv570,r580 depends on : */
+void r100_hdp_reset(struct radeon_device *rdev);
+int rv370_pcie_gart_enable(struct radeon_device *rdev);
+void rv370_pcie_gart_disable(struct radeon_device *rdev);
+void r420_pipes_init(struct radeon_device *rdev);
+void rs600_mc_disable_clients(struct radeon_device *rdev);
+void rs600_disable_vga(struct radeon_device *rdev);
+int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
+int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
+
+/* This files gather functions specifics to:
+ * r520,rv530,rv560,rv570,r580
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+void r520_gpu_init(struct radeon_device *rdev);
+int r520_mc_wait_for_idle(struct radeon_device *rdev);
+
+
+/*
+ * MC
+ */
+int r520_mc_init(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+	if (rv515_debugfs_pipes_info_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for pipes !\n");
+	}
+	if (rv515_debugfs_ga_info_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for pipes !\n");
+	}
+
+	r520_gpu_init(rdev);
+	rv370_pcie_gart_disable(rdev);
+
+	/* Setup GPU memory space */
+	rdev->mc.vram_location = 0xFFFFFFFFUL;
+	rdev->mc.gtt_location = 0xFFFFFFFFUL;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			printk(KERN_WARNING "[drm] Disabling AGP\n");
+			rdev->flags &= ~RADEON_IS_AGP;
+			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+		} else {
+			rdev->mc.gtt_location = rdev->mc.agp_base;
+		}
+	}
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	/* Program GPU memory space */
+	rs600_mc_disable_clients(rdev);
+	if (r520_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	/* Write VRAM size in case we are limiting it */
+	WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16);
+	tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16);
+	WREG32_MC(R520_MC_FB_LOCATION, tmp);
+	WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
+	WREG32(0x310, rdev->mc.vram_location);
+	if (rdev->flags & RADEON_IS_AGP) {
+		tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+		tmp = REG_SET(R520_MC_AGP_TOP, tmp >> 16);
+		tmp |= REG_SET(R520_MC_AGP_START, rdev->mc.gtt_location >> 16);
+		WREG32_MC(R520_MC_AGP_LOCATION, tmp);
+		WREG32_MC(R520_MC_AGP_BASE, rdev->mc.agp_base);
+		WREG32_MC(R520_MC_AGP_BASE_2, 0);
+	} else {
+		WREG32_MC(R520_MC_AGP_LOCATION, 0x0FFFFFFF);
+		WREG32_MC(R520_MC_AGP_BASE, 0);
+		WREG32_MC(R520_MC_AGP_BASE_2, 0);
+	}
+	return 0;
+}
+
+void r520_mc_fini(struct radeon_device *rdev)
+{
+	rv370_pcie_gart_disable(rdev);
+	radeon_gart_table_vram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Global GPU functions
+ */
+void r520_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+int r520_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32_MC(R520_MC_STATUS);
+		if (tmp & R520_MC_STATUS_IDLE) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+void r520_gpu_init(struct radeon_device *rdev)
+{
+	unsigned pipe_select_current, gb_pipe_select, tmp;
+
+	r100_hdp_reset(rdev);
+	rs600_disable_vga(rdev);
+	/*
+	 * DST_PIPE_CONFIG		0x170C
+	 * GB_TILE_CONFIG		0x4018
+	 * GB_FIFO_SIZE			0x4024
+	 * GB_PIPE_SELECT		0x402C
+	 * GB_PIPE_SELECT2              0x4124
+	 *	Z_PIPE_SHIFT			0
+	 *	Z_PIPE_MASK			0x000000003
+	 * GB_FIFO_SIZE2                0x4128
+	 *	SC_SFIFO_SIZE_SHIFT		0
+	 *	SC_SFIFO_SIZE_MASK		0x000000003
+	 *	SC_MFIFO_SIZE_SHIFT		2
+	 *	SC_MFIFO_SIZE_MASK		0x00000000C
+	 *	FG_SFIFO_SIZE_SHIFT		4
+	 *	FG_SFIFO_SIZE_MASK		0x000000030
+	 *	ZB_MFIFO_SIZE_SHIFT		6
+	 *	ZB_MFIFO_SIZE_MASK		0x0000000C0
+	 * GA_ENHANCE			0x4274
+	 * SU_REG_DEST			0x42C8
+	 */
+	/* workaround for RV530 */
+	if (rdev->family == CHIP_RV530) {
+		WREG32(0x4128, 0xFF);
+	}
+	r420_pipes_init(rdev);
+	gb_pipe_select = RREG32(0x402C);
+	tmp = RREG32(0x170C);
+	pipe_select_current = (tmp >> 2) & 3;
+	tmp = (1 << pipe_select_current) |
+	      (((gb_pipe_select >> 8) & 0xF) << 4);
+	WREG32_PLL(0x000D, tmp);
+	if (r520_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+}
+
+
+/*
+ * VRAM info
+ */
+static void r520_vram_get_type(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	rdev->mc.vram_width = 128;
+	rdev->mc.vram_is_ddr = true;
+	tmp = RREG32_MC(R520_MC_CNTL0);
+	switch ((tmp & R520_MEM_NUM_CHANNELS_MASK) >> R520_MEM_NUM_CHANNELS_SHIFT) {
+	case 0:
+		rdev->mc.vram_width = 32;
+		break;
+	case 1:
+		rdev->mc.vram_width = 64;
+		break;
+	case 2:
+		rdev->mc.vram_width = 128;
+		break;
+	case 3:
+		rdev->mc.vram_width = 256;
+		break;
+	default:
+		rdev->mc.vram_width = 128;
+		break;
+	}
+	if (tmp & R520_MC_CHANNEL_SIZE)
+		rdev->mc.vram_width *= 2;
+}
+
+void r520_vram_info(struct radeon_device *rdev)
+{
+	fixed20_12 a;
+
+	r520_vram_get_type(rdev);
+
+	r100_vram_init_sizes(rdev);
+	/* FIXME: we should enforce default clock in case GPU is not in
+	 * default setup
+	 */
+	a.full = rfixed_const(100);
+	rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
+	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+}
+
+void r520_bandwidth_update(struct radeon_device *rdev)
+{
+	rv515_bandwidth_avivo_update(rdev);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r600.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r600.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r600.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r600.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+/* r600,rv610,rv630,rv620,rv635,rv670 depends on : */
+void rs600_mc_disable_clients(struct radeon_device *rdev);
+
+/* This files gather functions specifics to:
+ * r600,rv610,rv630,rv620,rv635,rv670
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+int r600_mc_wait_for_idle(struct radeon_device *rdev);
+void r600_gpu_init(struct radeon_device *rdev);
+
+
+/*
+ * MC
+ */
+int r600_mc_init(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	r600_gpu_init(rdev);
+
+	/* setup the gart before changing location so we can ask to
+	 * discard unmapped mc request
+	 */
+	/* FIXME: disable out of gart access */
+	tmp = rdev->mc.gtt_location / 4096;
+	tmp = REG_SET(R600_LOGICAL_PAGE_NUMBER, tmp);
+	WREG32(R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, tmp);
+	tmp = (rdev->mc.gtt_location + rdev->mc.gtt_size) / 4096;
+	tmp = REG_SET(R600_LOGICAL_PAGE_NUMBER, tmp);
+	WREG32(R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, tmp);
+
+	rs600_mc_disable_clients(rdev);
+	if (r600_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24);
+	tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24);
+	WREG32(R600_MC_VM_FB_LOCATION, tmp);
+	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	tmp = REG_SET(R600_MC_AGP_TOP, tmp >> 22);
+	WREG32(R600_MC_VM_AGP_TOP, tmp);
+	tmp = REG_SET(R600_MC_AGP_BOT, rdev->mc.gtt_location >> 22);
+	WREG32(R600_MC_VM_AGP_BOT, tmp);
+	return 0;
+}
+
+void r600_mc_fini(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+
+/*
+ * Global GPU functions
+ */
+void r600_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+int r600_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+	return 0;
+}
+
+void r600_gpu_init(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+
+/*
+ * VRAM info
+ */
+void r600_vram_get_type(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int chansize;
+
+	rdev->mc.vram_width = 128;
+	rdev->mc.vram_is_ddr = true;
+
+	tmp = RREG32(R600_RAMCFG);
+	if (tmp & R600_CHANSIZE_OVERRIDE) {
+		chansize = 16;
+	} else if (tmp & R600_CHANSIZE) {
+		chansize = 64;
+	} else {
+		chansize = 32;
+	}
+	if (rdev->family == CHIP_R600) {
+		rdev->mc.vram_width = 8 * chansize;
+	} else if (rdev->family == CHIP_RV670) {
+		rdev->mc.vram_width = 4 * chansize;
+	} else if ((rdev->family == CHIP_RV610) ||
+			(rdev->family == CHIP_RV620)) {
+		rdev->mc.vram_width = chansize;
+	} else if ((rdev->family == CHIP_RV630) ||
+			(rdev->family == CHIP_RV635)) {
+		rdev->mc.vram_width = 2 * chansize;
+	}
+}
+
+void r600_vram_info(struct radeon_device *rdev)
+{
+	r600_vram_get_type(rdev);
+	rdev->mc.real_vram_size = RREG32(R600_CONFIG_MEMSIZE);
+	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+
+	/* Could aper size report 0 ? */
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+}
+
+/*
+ * Indirect registers accessor
+ */
+uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t r;
+
+	WREG32(R600_PCIE_PORT_INDEX, ((reg) & 0xff));
+	(void)RREG32(R600_PCIE_PORT_INDEX);
+	r = RREG32(R600_PCIE_PORT_DATA);
+	return r;
+}
+
+void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG32(R600_PCIE_PORT_INDEX, ((reg) & 0xff));
+	(void)RREG32(R600_PCIE_PORT_INDEX);
+	WREG32(R600_PCIE_PORT_DATA, (v));
+	(void)RREG32(R600_PCIE_PORT_DATA);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r600_cp.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r600_cp.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r600_cp.c	2012-03-22 19:11:41.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r600_cp.c	2012-03-22 20:08:05.000000000 -0400
@@ -605,6 +605,7 @@
 		break;
 	case CHIP_RV610:
 	case CHIP_RS780:
+	case CHIP_RS880:
 	case CHIP_RV620:
 		dev_priv->r600_max_pipes = 1;
 		dev_priv->r600_max_tile_pipes = 1;
@@ -739,7 +740,8 @@
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
 		RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE);
 	else
 		RADEON_WRITE(R600_DB_DEBUG, 0);
@@ -757,7 +759,8 @@
 	sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES);
 	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
 		sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) |
 				    R600_FETCH_FIFO_HIWATER(0xa) |
 				    R600_DONE_FIFO_HIWATER(0xe0) |
@@ -800,7 +803,8 @@
 					    R600_NUM_ES_STACK_ENTRIES(0));
 	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
 		/* no vertex cache */
 		sq_config &= ~R600_VC_ENABLE;
 
@@ -857,7 +861,8 @@
 
 	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
 		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY));
 	else
 		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC));
@@ -900,6 +905,7 @@
 		break;
 	case CHIP_RV610:
 	case CHIP_RS780:
+	case CHIP_RS880:
 	case CHIP_RV620:
 		gs_prim_buffer_depth = 32;
 		break;
@@ -945,6 +951,7 @@
 	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
 	case CHIP_RV610:
 	case CHIP_RS780:
+	case CHIP_RS880:
 	case CHIP_RV620:
 		tc_cntl = R600_TC_L2_SIZE(8);
 		break;
@@ -1147,6 +1154,10 @@
 		dev_priv->r700_sc_prim_fifo_size = 0xf9;
 		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
 		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
+		if (dev_priv->r600_sx_max_export_pos_size > 16) {
+			dev_priv->r600_sx_max_export_pos_size -= 16;
+			dev_priv->r600_sx_max_export_smx_size += 16;
+		}
 		break;
 	case CHIP_RV710:
 		dev_priv->r600_max_pipes = 2;
@@ -1168,6 +1179,31 @@
 		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
 		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
 		break;
+	case CHIP_RV740:
+		dev_priv->r600_max_pipes = 4;
+		dev_priv->r600_max_tile_pipes = 4;
+		dev_priv->r600_max_simds = 8;
+		dev_priv->r600_max_backends = 4;
+		dev_priv->r600_max_gprs = 256;
+		dev_priv->r600_max_threads = 248;
+		dev_priv->r600_max_stack_entries = 512;
+		dev_priv->r600_max_hw_contexts = 8;
+		dev_priv->r600_max_gs_threads = 16 * 2;
+		dev_priv->r600_sx_max_export_size = 256;
+		dev_priv->r600_sx_max_export_pos_size = 32;
+		dev_priv->r600_sx_max_export_smx_size = 224;
+		dev_priv->r600_sq_num_cf_insts = 2;
+
+		dev_priv->r700_sx_num_of_sets = 7;
+		dev_priv->r700_sc_prim_fifo_size = 0x100;
+		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
+		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
+
+		if (dev_priv->r600_sx_max_export_pos_size > 16) {
+			dev_priv->r600_sx_max_export_pos_size -= 16;
+			dev_priv->r600_sx_max_export_smx_size += 16;
+		}
+		break;
 	default:
 		break;
 	}
@@ -1316,6 +1352,7 @@
 		break;
 	case CHIP_RV730:
 	case CHIP_RV710:
+	case CHIP_RV740:
 	default:
 		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
 		break;
@@ -1392,6 +1429,7 @@
 	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
 	case CHIP_RV770:
 	case CHIP_RV730:
+	case CHIP_RV740:
 		gs_prim_buffer_depth = 384;
 		break;
 	case CHIP_RV710:
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r600_reg.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r600_reg.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/r600_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/r600_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __R600_REG_H__
+#define __R600_REG_H__
+
+#define R600_PCIE_PORT_INDEX                0x0038
+#define R600_PCIE_PORT_DATA                 0x003c
+
+#define R600_MC_VM_FB_LOCATION			0x2180
+#define		R600_MC_FB_BASE_MASK			0x0000FFFF
+#define		R600_MC_FB_BASE_SHIFT			0
+#define		R600_MC_FB_TOP_MASK			0xFFFF0000
+#define		R600_MC_FB_TOP_SHIFT			16
+#define R600_MC_VM_AGP_TOP			0x2184
+#define		R600_MC_AGP_TOP_MASK			0x0003FFFF
+#define		R600_MC_AGP_TOP_SHIFT			0
+#define R600_MC_VM_AGP_BOT			0x2188
+#define		R600_MC_AGP_BOT_MASK			0x0003FFFF
+#define		R600_MC_AGP_BOT_SHIFT			0
+#define R600_MC_VM_AGP_BASE			0x218c
+#define R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR	0x2190
+#define		R600_LOGICAL_PAGE_NUMBER_MASK		0x000FFFFF
+#define		R600_LOGICAL_PAGE_NUMBER_SHIFT		0
+#define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR	0x2194
+#define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR	0x2198
+
+#define R700_MC_VM_FB_LOCATION			0x2024
+#define		R700_MC_FB_BASE_MASK			0x0000FFFF
+#define		R700_MC_FB_BASE_SHIFT			0
+#define		R700_MC_FB_TOP_MASK			0xFFFF0000
+#define		R700_MC_FB_TOP_SHIFT			16
+#define R700_MC_VM_AGP_TOP			0x2028
+#define		R700_MC_AGP_TOP_MASK			0x0003FFFF
+#define		R700_MC_AGP_TOP_SHIFT			0
+#define R700_MC_VM_AGP_BOT			0x202c
+#define		R700_MC_AGP_BOT_MASK			0x0003FFFF
+#define		R700_MC_AGP_BOT_SHIFT			0
+#define R700_MC_VM_AGP_BASE			0x2030
+#define R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR	0x2034
+#define		R700_LOGICAL_PAGE_NUMBER_MASK		0x000FFFFF
+#define		R700_LOGICAL_PAGE_NUMBER_SHIFT		0
+#define R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR	0x2038
+#define R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR	0x203c
+
+#define R600_RAMCFG				       0x2408
+#       define R600_CHANSIZE                           (1 << 7)
+#       define R600_CHANSIZE_OVERRIDE                  (1 << 10)
+
+
+#define R600_GENERAL_PWRMGT                                        0x618
+#	define R600_OPEN_DRAIN_PADS				   (1 << 11)
+
+#define R600_LOWER_GPIO_ENABLE                                     0x710
+#define R600_CTXSW_VID_LOWER_GPIO_CNTL                             0x718
+#define R600_HIGH_VID_LOWER_GPIO_CNTL                              0x71c
+#define R600_MEDIUM_VID_LOWER_GPIO_CNTL                            0x720
+#define R600_LOW_VID_LOWER_GPIO_CNTL                               0x724
+
+
+
+#define R600_HDP_NONSURFACE_BASE                                0x2c04
+
+#define R600_BUS_CNTL                                           0x5420
+#define R600_CONFIG_CNTL                                        0x5424
+#define R600_CONFIG_MEMSIZE                                     0x5428
+#define R600_CONFIG_F0_BASE                                     0x542C
+#define R600_CONFIG_APER_SIZE                                   0x5430
+
+#define R600_ROM_CNTL                              0x1600
+#       define R600_SCK_OVERWRITE                  (1 << 1)
+#       define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28
+#       define R600_SCK_PRESCALE_CRYSTAL_CLK_MASK  (0xf << 28)
+
+#define R600_CG_SPLL_FUNC_CNTL                     0x600
+#       define R600_SPLL_BYPASS_EN                 (1 << 3)
+#define R600_CG_SPLL_STATUS                        0x60c
+#       define R600_SPLL_CHG_STATUS                (1 << 1)
+
+#define R600_BIOS_0_SCRATCH               0x1724
+#define R600_BIOS_1_SCRATCH               0x1728
+#define R600_BIOS_2_SCRATCH               0x172c
+#define R600_BIOS_3_SCRATCH               0x1730
+#define R600_BIOS_4_SCRATCH               0x1734
+#define R600_BIOS_5_SCRATCH               0x1738
+#define R600_BIOS_6_SCRATCH               0x173c
+#define R600_BIOS_7_SCRATCH               0x1740
+
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_agp.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_agp.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_agp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_agp.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie
+ *    Jerome Glisse <glisse@freedesktop.org>
+ */
+#include "drmP.h"
+#include "drm.h"
+#include "radeon.h"
+#include "radeon_drm.h"
+
+#if __OS_HAS_AGP
+
+struct radeon_agpmode_quirk {
+	u32 hostbridge_vendor;
+	u32 hostbridge_device;
+	u32 chip_vendor;
+	u32 chip_device;
+	u32 subsys_vendor;
+	u32 subsys_device;
+	u32 default_mode;
+};
+
+static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
+	/* Intel E7505 Memory Controller Hub / RV350 AR [Radeon 9600XT] Needs AGPMode 4 (deb #515326) */
+	{ PCI_VENDOR_ID_INTEL, 0x2550, PCI_VENDOR_ID_ATI, 0x4152, 0x1458, 0x4038, 4},
+	/* Intel 82865G/PE/P DRAM Controller/Host-Hub / Mobility 9800 Needs AGPMode 4 (deb #462590) */
+	{ PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x4a4e, PCI_VENDOR_ID_DELL, 0x5106, 4},
+	/* Intel 82865G/PE/P DRAM Controller/Host-Hub / RV280 [Radeon 9200 SE] Needs AGPMode 4 (lp #300304) */
+	{ PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x5964,
+		0x148c, 0x2073, 4},
+	/* Intel 82855PM Processor to I/O Controller / Mobility M6 LY Needs AGPMode 1 (deb #467235) */
+	{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c59,
+		PCI_VENDOR_ID_IBM, 0x052f, 1},
+	/* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */
+	{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e50,
+		PCI_VENDOR_ID_IBM, 0x0550, 1},
+	/* Intel 82855PM host bridge / Mobility M7 needs AGPMode 1 */
+	{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c57,
+		PCI_VENDOR_ID_IBM, 0x0530, 1},
+	/* Intel 82855PM host bridge / FireGL Mobility T2 RV350 Needs AGPMode 2 (fdo #20647) */
+	{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e54,
+		PCI_VENDOR_ID_IBM, 0x054f, 2},
+	/* Intel 82855PM host bridge / Mobility M9+ / VaioPCG-V505DX Needs AGPMode 2 (fdo #17928) */
+	{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61,
+		PCI_VENDOR_ID_SONY, 0x816b, 2},
+	/* Intel 82855PM Processor to I/O Controller / Mobility M9+ Needs AGPMode 8 (phoronix forum) */
+	{ PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61,
+		PCI_VENDOR_ID_SONY, 0x8195, 8},
+	/* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/
+	{ PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59,
+		PCI_VENDOR_ID_DELL, 0x00e3, 2},
+	/* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */
+	{ PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66,
+		PCI_VENDOR_ID_DELL, 0x0149, 1},
+	/* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */
+	{ PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
+		0x1025, 0x0061, 1},
+	/* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #203007) */
+	{ PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
+		0x1025, 0x0064, 1},
+	/* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #141551) */
+	{ PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
+		PCI_VENDOR_ID_ASUSTEK, 0x1942, 1},
+	/* Intel 82852/82855 host bridge / Mobility 9600/9700 Needs AGPMode 1 (deb #510208) */
+	{ PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
+		0x10cf, 0x127f, 1},
+	/* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */
+	{ 0x1849, 0x3189, PCI_VENDOR_ID_ATI, 0x5960,
+		0x1787, 0x5960, 4},
+	/* VIA K8M800 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (fdo #12544) */
+	{ PCI_VENDOR_ID_VIA, 0x0204, PCI_VENDOR_ID_ATI, 0x5960,
+		0x17af, 0x2020, 4},
+	/* VIA KT880 Host Bridge / RV350 [Radeon 9550] Needs AGPMode 4 (fdo #19981) */
+	{ PCI_VENDOR_ID_VIA, 0x0269, PCI_VENDOR_ID_ATI, 0x4153,
+		PCI_VENDOR_ID_ASUSTEK, 0x003c, 4},
+	/* VIA VT8363 Host Bridge / R200 QL [Radeon 8500] Needs AGPMode 2 (lp #141551) */
+	{ PCI_VENDOR_ID_VIA, 0x0305, PCI_VENDOR_ID_ATI, 0x514c,
+		PCI_VENDOR_ID_ATI, 0x013a, 2},
+	/* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 (deb #515512) */
+	{ PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960,
+		PCI_VENDOR_ID_ASUSTEK, 0x004c, 2},
+	/* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 */
+	{ PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960,
+		PCI_VENDOR_ID_ASUSTEK, 0x0054, 2},
+	/* VIA VT8377 Host Bridge / R200 QM [Radeon 9100] Needs AGPMode 4 (deb #461144) */
+	{ PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x514d,
+		0x174b, 0x7149, 4},
+	/* VIA VT8377 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (lp #312693) */
+	{ PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5960,
+		0x1462, 0x0380, 4},
+	/* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (ati ML) */
+	{ PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5964,
+		0x148c, 0x2073, 4},
+	/* ATI Host Bridge / RV280 [M9+] Needs AGPMode 1 (phoronix forum) */
+	{ PCI_VENDOR_ID_ATI, 0xcbb2, PCI_VENDOR_ID_ATI, 0x5c61,
+		PCI_VENDOR_ID_SONY, 0x8175, 1},
+	/* HP Host Bridge / R300 [FireGL X1] Needs AGPMode 2 (fdo #7770) */
+	{ PCI_VENDOR_ID_HP, 0x122e, PCI_VENDOR_ID_ATI, 0x4e47,
+		PCI_VENDOR_ID_ATI, 0x0152, 2},
+	{ 0, 0, 0, 0, 0, 0, 0 },
+};
+#endif
+
+int radeon_agp_init(struct radeon_device *rdev)
+{
+#if __OS_HAS_AGP
+	struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list;
+	struct drm_agp_mode mode;
+	struct drm_agp_info info;
+	uint32_t agp_status;
+	int default_mode;
+	bool is_v3;
+	int ret;
+
+	/* Acquire AGP. */
+	if (!rdev->ddev->agp->acquired) {
+		ret = drm_agp_acquire(rdev->ddev);
+		if (ret) {
+			DRM_ERROR("Unable to acquire AGP: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = drm_agp_info(rdev->ddev, &info);
+	if (ret) {
+		DRM_ERROR("Unable to get AGP info: %d\n", ret);
+		return ret;
+	}
+	mode.mode = info.mode;
+	agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode;
+	is_v3 = !!(agp_status & RADEON_AGPv3_MODE);
+
+	if (is_v3) {
+		default_mode = (agp_status & RADEON_AGPv3_8X_MODE) ? 8 : 4;
+	} else {
+		if (agp_status & RADEON_AGP_4X_MODE) {
+			default_mode = 4;
+		} else if (agp_status & RADEON_AGP_2X_MODE) {
+			default_mode = 2;
+		} else {
+			default_mode = 1;
+		}
+	}
+
+	/* Apply AGPMode Quirks */
+	while (p && p->chip_device != 0) {
+		if (info.id_vendor == p->hostbridge_vendor &&
+		    info.id_device == p->hostbridge_device &&
+		    rdev->pdev->vendor == p->chip_vendor &&
+		    rdev->pdev->device == p->chip_device &&
+		    rdev->pdev->subsystem_vendor == p->subsys_vendor &&
+		    rdev->pdev->subsystem_device == p->subsys_device) {
+			default_mode = p->default_mode;
+		}
+		++p;
+	}
+
+	if (radeon_agpmode > 0) {
+		if ((radeon_agpmode < (is_v3 ? 4 : 1)) ||
+		    (radeon_agpmode > (is_v3 ? 8 : 4)) ||
+		    (radeon_agpmode & (radeon_agpmode - 1))) {
+			DRM_ERROR("Illegal AGP Mode: %d (valid %s), leaving at %d\n",
+				  radeon_agpmode, is_v3 ? "4, 8" : "1, 2, 4",
+				  default_mode);
+			radeon_agpmode = default_mode;
+		} else {
+			DRM_INFO("AGP mode requested: %d\n", radeon_agpmode);
+		}
+	} else {
+		radeon_agpmode = default_mode;
+	}
+
+	mode.mode &= ~RADEON_AGP_MODE_MASK;
+	if (is_v3) {
+		switch (radeon_agpmode) {
+		case 8:
+			mode.mode |= RADEON_AGPv3_8X_MODE;
+			break;
+		case 4:
+		default:
+			mode.mode |= RADEON_AGPv3_4X_MODE;
+			break;
+		}
+	} else {
+		switch (radeon_agpmode) {
+		case 4:
+			mode.mode |= RADEON_AGP_4X_MODE;
+			break;
+		case 2:
+			mode.mode |= RADEON_AGP_2X_MODE;
+			break;
+		case 1:
+		default:
+			mode.mode |= RADEON_AGP_1X_MODE;
+			break;
+		}
+	}
+
+	mode.mode &= ~RADEON_AGP_FW_MODE; /* disable fw */
+	ret = drm_agp_enable(rdev->ddev, mode);
+	if (ret) {
+		DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
+		return ret;
+	}
+
+	rdev->mc.agp_base = rdev->ddev->agp->agp_info.aper_base;
+	rdev->mc.gtt_size = rdev->ddev->agp->agp_info.aper_size << 20;
+
+	/* workaround some hw issues */
+	if (rdev->family < CHIP_R200) {
+		WREG32(RADEON_AGP_CNTL, RREG32(RADEON_AGP_CNTL) | 0x000e0000);
+	}
+	return 0;
+#else
+	return 0;
+#endif
+}
+
+void radeon_agp_fini(struct radeon_device *rdev)
+{
+#if __OS_HAS_AGP
+	if (rdev->flags & RADEON_IS_AGP) {
+		if (rdev->ddev->agp && rdev->ddev->agp->acquired) {
+			drm_agp_release(rdev->ddev);
+		}
+	}
+#endif
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_asic.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_asic.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_asic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,460 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RADEON_ASIC_H__
+#define __RADEON_ASIC_H__
+
+/*
+ * common functions
+ */
+void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
+void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
+
+void radeon_atom_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
+void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock);
+void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
+
+/*
+ * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
+ */
+int r100_init(struct radeon_device *rdev);
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void r100_errata(struct radeon_device *rdev);
+void r100_vram_info(struct radeon_device *rdev);
+int r100_gpu_reset(struct radeon_device *rdev);
+int r100_mc_init(struct radeon_device *rdev);
+void r100_mc_fini(struct radeon_device *rdev);
+u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
+int r100_wb_init(struct radeon_device *rdev);
+void r100_wb_fini(struct radeon_device *rdev);
+int r100_gart_enable(struct radeon_device *rdev);
+void r100_pci_gart_disable(struct radeon_device *rdev);
+void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
+int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
+int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
+void r100_cp_fini(struct radeon_device *rdev);
+void r100_cp_disable(struct radeon_device *rdev);
+void r100_ring_start(struct radeon_device *rdev);
+int r100_irq_set(struct radeon_device *rdev);
+int r100_irq_process(struct radeon_device *rdev);
+void r100_fence_ring_emit(struct radeon_device *rdev,
+			  struct radeon_fence *fence);
+int r100_cs_parse(struct radeon_cs_parser *p);
+void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg);
+int r100_copy_blit(struct radeon_device *rdev,
+		   uint64_t src_offset,
+		   uint64_t dst_offset,
+		   unsigned num_pages,
+		   struct radeon_fence *fence);
+int r100_set_surface_reg(struct radeon_device *rdev, int reg,
+			 uint32_t tiling_flags, uint32_t pitch,
+			 uint32_t offset, uint32_t obj_size);
+int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
+void r100_bandwidth_update(struct radeon_device *rdev);
+
+static struct radeon_asic r100_asic = {
+	.init = &r100_init,
+	.errata = &r100_errata,
+	.vram_info = &r100_vram_info,
+	.gpu_reset = &r100_gpu_reset,
+	.mc_init = &r100_mc_init,
+	.mc_fini = &r100_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &r100_gart_enable,
+	.gart_disable = &r100_pci_gart_disable,
+	.gart_tlb_flush = &r100_pci_gart_tlb_flush,
+	.gart_set_page = &r100_pci_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &r100_ring_start,
+	.irq_set = &r100_irq_set,
+	.irq_process = &r100_irq_process,
+	.get_vblank_counter = &r100_get_vblank_counter,
+	.fence_ring_emit = &r100_fence_ring_emit,
+	.cs_parse = &r100_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = NULL,
+	.copy = &r100_copy_blit,
+	.set_engine_clock = &radeon_legacy_set_engine_clock,
+	.set_memory_clock = NULL,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = &radeon_legacy_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &r100_bandwidth_update,
+};
+
+
+/*
+ * r300,r350,rv350,rv380
+ */
+int r300_init(struct radeon_device *rdev);
+void r300_errata(struct radeon_device *rdev);
+void r300_vram_info(struct radeon_device *rdev);
+int r300_gpu_reset(struct radeon_device *rdev);
+int r300_mc_init(struct radeon_device *rdev);
+void r300_mc_fini(struct radeon_device *rdev);
+void r300_ring_start(struct radeon_device *rdev);
+void r300_fence_ring_emit(struct radeon_device *rdev,
+			  struct radeon_fence *fence);
+int r300_cs_parse(struct radeon_cs_parser *p);
+int r300_gart_enable(struct radeon_device *rdev);
+void rv370_pcie_gart_disable(struct radeon_device *rdev);
+void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
+int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
+uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
+void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
+int r300_copy_dma(struct radeon_device *rdev,
+		  uint64_t src_offset,
+		  uint64_t dst_offset,
+		  unsigned num_pages,
+		  struct radeon_fence *fence);
+
+static struct radeon_asic r300_asic = {
+	.init = &r300_init,
+	.errata = &r300_errata,
+	.vram_info = &r300_vram_info,
+	.gpu_reset = &r300_gpu_reset,
+	.mc_init = &r300_mc_init,
+	.mc_fini = &r300_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &r300_gart_enable,
+	.gart_disable = &r100_pci_gart_disable,
+	.gart_tlb_flush = &r100_pci_gart_tlb_flush,
+	.gart_set_page = &r100_pci_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &r300_ring_start,
+	.irq_set = &r100_irq_set,
+	.irq_process = &r100_irq_process,
+	.get_vblank_counter = &r100_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r300_copy_dma,
+	.copy = &r100_copy_blit,
+	.set_engine_clock = &radeon_legacy_set_engine_clock,
+	.set_memory_clock = NULL,
+	.set_pcie_lanes = &rv370_set_pcie_lanes,
+	.set_clock_gating = &radeon_legacy_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &r100_bandwidth_update,
+};
+
+/*
+ * r420,r423,rv410
+ */
+void r420_errata(struct radeon_device *rdev);
+void r420_vram_info(struct radeon_device *rdev);
+int r420_mc_init(struct radeon_device *rdev);
+void r420_mc_fini(struct radeon_device *rdev);
+static struct radeon_asic r420_asic = {
+	.init = &r300_init,
+	.errata = &r420_errata,
+	.vram_info = &r420_vram_info,
+	.gpu_reset = &r300_gpu_reset,
+	.mc_init = &r420_mc_init,
+	.mc_fini = &r420_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &r300_gart_enable,
+	.gart_disable = &rv370_pcie_gart_disable,
+	.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+	.gart_set_page = &rv370_pcie_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &r300_ring_start,
+	.irq_set = &r100_irq_set,
+	.irq_process = &r100_irq_process,
+	.get_vblank_counter = &r100_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r300_copy_dma,
+	.copy = &r100_copy_blit,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.set_pcie_lanes = &rv370_set_pcie_lanes,
+	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &r100_bandwidth_update,
+};
+
+
+/*
+ * rs400,rs480
+ */
+void rs400_errata(struct radeon_device *rdev);
+void rs400_vram_info(struct radeon_device *rdev);
+int rs400_mc_init(struct radeon_device *rdev);
+void rs400_mc_fini(struct radeon_device *rdev);
+int rs400_gart_enable(struct radeon_device *rdev);
+void rs400_gart_disable(struct radeon_device *rdev);
+void rs400_gart_tlb_flush(struct radeon_device *rdev);
+int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
+uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+static struct radeon_asic rs400_asic = {
+	.init = &r300_init,
+	.errata = &rs400_errata,
+	.vram_info = &rs400_vram_info,
+	.gpu_reset = &r300_gpu_reset,
+	.mc_init = &rs400_mc_init,
+	.mc_fini = &rs400_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &rs400_gart_enable,
+	.gart_disable = &rs400_gart_disable,
+	.gart_tlb_flush = &rs400_gart_tlb_flush,
+	.gart_set_page = &rs400_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &r300_ring_start,
+	.irq_set = &r100_irq_set,
+	.irq_process = &r100_irq_process,
+	.get_vblank_counter = &r100_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r300_copy_dma,
+	.copy = &r100_copy_blit,
+	.set_engine_clock = &radeon_legacy_set_engine_clock,
+	.set_memory_clock = NULL,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = &radeon_legacy_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &r100_bandwidth_update,
+};
+
+
+/*
+ * rs600.
+ */
+int rs600_init(struct radeon_device *dev);
+void rs600_errata(struct radeon_device *rdev);
+void rs600_vram_info(struct radeon_device *rdev);
+int rs600_mc_init(struct radeon_device *rdev);
+void rs600_mc_fini(struct radeon_device *rdev);
+int rs600_irq_set(struct radeon_device *rdev);
+int rs600_irq_process(struct radeon_device *rdev);
+u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
+int rs600_gart_enable(struct radeon_device *rdev);
+void rs600_gart_disable(struct radeon_device *rdev);
+void rs600_gart_tlb_flush(struct radeon_device *rdev);
+int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
+uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rs600_bandwidth_update(struct radeon_device *rdev);
+static struct radeon_asic rs600_asic = {
+	.init = &rs600_init,
+	.errata = &rs600_errata,
+	.vram_info = &rs600_vram_info,
+	.gpu_reset = &r300_gpu_reset,
+	.mc_init = &rs600_mc_init,
+	.mc_fini = &rs600_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &rs600_gart_enable,
+	.gart_disable = &rs600_gart_disable,
+	.gart_tlb_flush = &rs600_gart_tlb_flush,
+	.gart_set_page = &rs600_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &r300_ring_start,
+	.irq_set = &rs600_irq_set,
+	.irq_process = &rs600_irq_process,
+	.get_vblank_counter = &rs600_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r300_copy_dma,
+	.copy = &r100_copy_blit,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.bandwidth_update = &rs600_bandwidth_update,
+};
+
+
+/*
+ * rs690,rs740
+ */
+void rs690_errata(struct radeon_device *rdev);
+void rs690_vram_info(struct radeon_device *rdev);
+int rs690_mc_init(struct radeon_device *rdev);
+void rs690_mc_fini(struct radeon_device *rdev);
+uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rs690_bandwidth_update(struct radeon_device *rdev);
+static struct radeon_asic rs690_asic = {
+	.init = &rs600_init,
+	.errata = &rs690_errata,
+	.vram_info = &rs690_vram_info,
+	.gpu_reset = &r300_gpu_reset,
+	.mc_init = &rs690_mc_init,
+	.mc_fini = &rs690_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &rs400_gart_enable,
+	.gart_disable = &rs400_gart_disable,
+	.gart_tlb_flush = &rs400_gart_tlb_flush,
+	.gart_set_page = &rs400_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &r300_ring_start,
+	.irq_set = &rs600_irq_set,
+	.irq_process = &rs600_irq_process,
+	.get_vblank_counter = &rs600_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r300_copy_dma,
+	.copy = &r300_copy_dma,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &rs690_bandwidth_update,
+};
+
+
+/*
+ * rv515
+ */
+int rv515_init(struct radeon_device *rdev);
+void rv515_errata(struct radeon_device *rdev);
+void rv515_vram_info(struct radeon_device *rdev);
+int rv515_gpu_reset(struct radeon_device *rdev);
+int rv515_mc_init(struct radeon_device *rdev);
+void rv515_mc_fini(struct radeon_device *rdev);
+uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rv515_ring_start(struct radeon_device *rdev);
+uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
+void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rv515_bandwidth_update(struct radeon_device *rdev);
+static struct radeon_asic rv515_asic = {
+	.init = &rv515_init,
+	.errata = &rv515_errata,
+	.vram_info = &rv515_vram_info,
+	.gpu_reset = &rv515_gpu_reset,
+	.mc_init = &rv515_mc_init,
+	.mc_fini = &rv515_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &r300_gart_enable,
+	.gart_disable = &rv370_pcie_gart_disable,
+	.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+	.gart_set_page = &rv370_pcie_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &rv515_ring_start,
+	.irq_set = &rs600_irq_set,
+	.irq_process = &rs600_irq_process,
+	.get_vblank_counter = &rs600_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r300_copy_dma,
+	.copy = &r100_copy_blit,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.set_pcie_lanes = &rv370_set_pcie_lanes,
+	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &rv515_bandwidth_update,
+};
+
+
+/*
+ * r520,rv530,rv560,rv570,r580
+ */
+void r520_errata(struct radeon_device *rdev);
+void r520_vram_info(struct radeon_device *rdev);
+int r520_mc_init(struct radeon_device *rdev);
+void r520_mc_fini(struct radeon_device *rdev);
+void r520_bandwidth_update(struct radeon_device *rdev);
+static struct radeon_asic r520_asic = {
+	.init = &rv515_init,
+	.errata = &r520_errata,
+	.vram_info = &r520_vram_info,
+	.gpu_reset = &rv515_gpu_reset,
+	.mc_init = &r520_mc_init,
+	.mc_fini = &r520_mc_fini,
+	.wb_init = &r100_wb_init,
+	.wb_fini = &r100_wb_fini,
+	.gart_enable = &r300_gart_enable,
+	.gart_disable = &rv370_pcie_gart_disable,
+	.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+	.gart_set_page = &rv370_pcie_gart_set_page,
+	.cp_init = &r100_cp_init,
+	.cp_fini = &r100_cp_fini,
+	.cp_disable = &r100_cp_disable,
+	.ring_start = &rv515_ring_start,
+	.irq_set = &rs600_irq_set,
+	.irq_process = &rs600_irq_process,
+	.get_vblank_counter = &rs600_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r300_copy_dma,
+	.copy = &r100_copy_blit,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.set_pcie_lanes = &rv370_set_pcie_lanes,
+	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &r520_bandwidth_update,
+};
+
+/*
+ * r600,rv610,rv630,rv620,rv635,rv670,rs780,rv770,rv730,rv710
+ */
+uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
+void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1299 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+#include "atom.h"
+#include "atom-bits.h"
+
+/* from radeon_encoder.c */
+extern uint32_t
+radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device,
+		      uint8_t dac);
+extern void radeon_link_encoder_connector(struct drm_device *dev);
+extern void
+radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id,
+			uint32_t supported_device);
+
+/* from radeon_connector.c */
+extern void
+radeon_add_atom_connector(struct drm_device *dev,
+			  uint32_t connector_id,
+			  uint32_t supported_device,
+			  int connector_type,
+			  struct radeon_i2c_bus_rec *i2c_bus,
+			  bool linkb, uint32_t igp_lane_info);
+
+/* from radeon_legacy_encoder.c */
+extern void
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id,
+			  uint32_t supported_device);
+
+union atom_supported_devices {
+	struct _ATOM_SUPPORTED_DEVICES_INFO info;
+	struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2;
+	struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
+};
+
+static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
+							   *dev, uint8_t id)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct atom_context *ctx = rdev->mode_info.atom_context;
+	ATOM_GPIO_I2C_ASSIGMENT gpio;
+	struct radeon_i2c_bus_rec i2c;
+	int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
+	struct _ATOM_GPIO_I2C_INFO *i2c_info;
+	uint16_t data_offset;
+
+	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
+	i2c.valid = false;
+
+	atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
+
+	i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
+
+	gpio = i2c_info->asGPIO_Info[id];
+
+	i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4;
+	i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4;
+	i2c.put_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
+	i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
+	i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
+	i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
+	i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4;
+	i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4;
+	i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
+	i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
+	i2c.put_clk_mask = (1 << gpio.ucClkEnShift);
+	i2c.put_data_mask = (1 << gpio.ucDataEnShift);
+	i2c.get_clk_mask = (1 << gpio.ucClkY_Shift);
+	i2c.get_data_mask = (1 << gpio.ucDataY_Shift);
+	i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
+	i2c.a_data_mask = (1 << gpio.ucDataA_Shift);
+	i2c.valid = true;
+
+	return i2c;
+}
+
+static bool radeon_atom_apply_quirks(struct drm_device *dev,
+				     uint32_t supported_device,
+				     int *connector_type,
+				     struct radeon_i2c_bus_rec *i2c_bus,
+				     uint8_t *line_mux)
+{
+
+	/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
+	if ((dev->pdev->device == 0x791e) &&
+	    (dev->pdev->subsystem_vendor == 0x1043) &&
+	    (dev->pdev->subsystem_device == 0x826d)) {
+		if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+		    (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
+			*connector_type = DRM_MODE_CONNECTOR_DVID;
+	}
+
+	/* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
+	if ((dev->pdev->device == 0x7941) &&
+	    (dev->pdev->subsystem_vendor == 0x147b) &&
+	    (dev->pdev->subsystem_device == 0x2412)) {
+		if (*connector_type == DRM_MODE_CONNECTOR_DVII)
+			return false;
+	}
+
+	/* Falcon NW laptop lists vga ddc line for LVDS */
+	if ((dev->pdev->device == 0x5653) &&
+	    (dev->pdev->subsystem_vendor == 0x1462) &&
+	    (dev->pdev->subsystem_device == 0x0291)) {
+		if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			i2c_bus->valid = false;
+			*line_mux = 53;
+		}
+	}
+
+	/* Funky macbooks */
+	if ((dev->pdev->device == 0x71C5) &&
+	    (dev->pdev->subsystem_vendor == 0x106b) &&
+	    (dev->pdev->subsystem_device == 0x0080)) {
+		if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
+		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+			return false;
+	}
+
+	/* some BIOSes seem to report DAC on HDMI - they hurt me with their lies */
+	if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) ||
+	    (*connector_type == DRM_MODE_CONNECTOR_HDMIB)) {
+		if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
+			return false;
+		}
+	}
+
+	/* ASUS HD 3600 XT board lists the DVI port as HDMI */
+	if ((dev->pdev->device == 0x9598) &&
+	    (dev->pdev->subsystem_vendor == 0x1043) &&
+	    (dev->pdev->subsystem_device == 0x01da)) {
+		if (*connector_type == DRM_MODE_CONNECTOR_HDMIB) {
+			*connector_type = DRM_MODE_CONNECTOR_DVID;
+		}
+	}
+
+	return true;
+}
+
+const int supported_devices_connector_convert[] = {
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_VGA,
+	DRM_MODE_CONNECTOR_DVII,
+	DRM_MODE_CONNECTOR_DVID,
+	DRM_MODE_CONNECTOR_DVIA,
+	DRM_MODE_CONNECTOR_SVIDEO,
+	DRM_MODE_CONNECTOR_Composite,
+	DRM_MODE_CONNECTOR_LVDS,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_HDMIA,
+	DRM_MODE_CONNECTOR_HDMIB,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_9PinDIN,
+	DRM_MODE_CONNECTOR_DisplayPort
+};
+
+const int object_connector_convert[] = {
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_DVII,
+	DRM_MODE_CONNECTOR_DVII,
+	DRM_MODE_CONNECTOR_DVID,
+	DRM_MODE_CONNECTOR_DVID,
+	DRM_MODE_CONNECTOR_VGA,
+	DRM_MODE_CONNECTOR_Composite,
+	DRM_MODE_CONNECTOR_SVIDEO,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_9PinDIN,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_HDMIA,
+	DRM_MODE_CONNECTOR_HDMIB,
+	DRM_MODE_CONNECTOR_HDMIB,
+	DRM_MODE_CONNECTOR_LVDS,
+	DRM_MODE_CONNECTOR_9PinDIN,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_DisplayPort
+};
+
+bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	struct atom_context *ctx = mode_info->atom_context;
+	int index = GetIndexIntoMasterTable(DATA, Object_Header);
+	uint16_t size, data_offset;
+	uint8_t frev, crev, line_mux = 0;
+	ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
+	ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
+	ATOM_OBJECT_HEADER *obj_header;
+	int i, j, path_size, device_support;
+	int connector_type;
+	uint16_t igp_lane_info;
+	bool linkb;
+	struct radeon_i2c_bus_rec ddc_bus;
+
+	atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
+
+	if (data_offset == 0)
+		return false;
+
+	if (crev < 2)
+		return false;
+
+	obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
+	path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
+	    (ctx->bios + data_offset +
+	     le16_to_cpu(obj_header->usDisplayPathTableOffset));
+	con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
+	    (ctx->bios + data_offset +
+	     le16_to_cpu(obj_header->usConnectorObjectTableOffset));
+	device_support = le16_to_cpu(obj_header->usDeviceSupport);
+
+	path_size = 0;
+	for (i = 0; i < path_obj->ucNumOfDispPath; i++) {
+		uint8_t *addr = (uint8_t *) path_obj->asDispPath;
+		ATOM_DISPLAY_OBJECT_PATH *path;
+		addr += path_size;
+		path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
+		path_size += le16_to_cpu(path->usSize);
+		linkb = false;
+
+		if (device_support & le16_to_cpu(path->usDeviceTag)) {
+			uint8_t con_obj_id, con_obj_num, con_obj_type;
+
+			con_obj_id =
+			    (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
+			    >> OBJECT_ID_SHIFT;
+			con_obj_num =
+			    (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
+			    >> ENUM_ID_SHIFT;
+			con_obj_type =
+			    (le16_to_cpu(path->usConnObjectId) &
+			     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
+
+			if ((le16_to_cpu(path->usDeviceTag) ==
+			     ATOM_DEVICE_TV1_SUPPORT)
+			    || (le16_to_cpu(path->usDeviceTag) ==
+				ATOM_DEVICE_TV2_SUPPORT)
+			    || (le16_to_cpu(path->usDeviceTag) ==
+				ATOM_DEVICE_CV_SUPPORT))
+				continue;
+
+			if ((rdev->family == CHIP_RS780) &&
+			    (con_obj_id ==
+			     CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
+				uint16_t igp_offset = 0;
+				ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj;
+
+				index =
+				    GetIndexIntoMasterTable(DATA,
+							    IntegratedSystemInfo);
+
+				atom_parse_data_header(ctx, index, &size, &frev,
+						       &crev, &igp_offset);
+
+				if (crev >= 2) {
+					igp_obj =
+					    (ATOM_INTEGRATED_SYSTEM_INFO_V2
+					     *) (ctx->bios + igp_offset);
+
+					if (igp_obj) {
+						uint32_t slot_config, ct;
+
+						if (con_obj_num == 1)
+							slot_config =
+							    igp_obj->
+							    ulDDISlot1Config;
+						else
+							slot_config =
+							    igp_obj->
+							    ulDDISlot2Config;
+
+						ct = (slot_config >> 16) & 0xff;
+						connector_type =
+						    object_connector_convert
+						    [ct];
+						igp_lane_info =
+						    slot_config & 0xffff;
+					} else
+						continue;
+				} else
+					continue;
+			} else {
+				igp_lane_info = 0;
+				connector_type =
+				    object_connector_convert[con_obj_id];
+			}
+
+			if (connector_type == DRM_MODE_CONNECTOR_Unknown)
+				continue;
+
+			for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2);
+			     j++) {
+				uint8_t enc_obj_id, enc_obj_num, enc_obj_type;
+
+				enc_obj_id =
+				    (le16_to_cpu(path->usGraphicObjIds[j]) &
+				     OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+				enc_obj_num =
+				    (le16_to_cpu(path->usGraphicObjIds[j]) &
+				     ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+				enc_obj_type =
+				    (le16_to_cpu(path->usGraphicObjIds[j]) &
+				     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
+
+				/* FIXME: add support for router objects */
+				if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
+					if (enc_obj_num == 2)
+						linkb = true;
+					else
+						linkb = false;
+
+					radeon_add_atom_encoder(dev,
+								enc_obj_id,
+								le16_to_cpu
+								(path->
+								 usDeviceTag));
+
+				}
+			}
+
+			/* look up gpio for ddc */
+			if ((le16_to_cpu(path->usDeviceTag) &
+			     (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+			    == 0) {
+				for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
+					if (le16_to_cpu(path->usConnObjectId) ==
+					    le16_to_cpu(con_obj->asObjects[j].
+							usObjectID)) {
+						ATOM_COMMON_RECORD_HEADER
+						    *record =
+						    (ATOM_COMMON_RECORD_HEADER
+						     *)
+						    (ctx->bios + data_offset +
+						     le16_to_cpu(con_obj->
+								 asObjects[j].
+								 usRecordOffset));
+						ATOM_I2C_RECORD *i2c_record;
+
+						while (record->ucRecordType > 0
+						       && record->
+						       ucRecordType <=
+						       ATOM_MAX_OBJECT_RECORD_NUMBER) {
+							DRM_ERROR
+							    ("record type %d\n",
+							     record->
+							     ucRecordType);
+							switch (record->
+								ucRecordType) {
+							case ATOM_I2C_RECORD_TYPE:
+								i2c_record =
+								    (ATOM_I2C_RECORD
+								     *) record;
+								line_mux =
+								    i2c_record->
+								    sucI2cId.
+								    bfI2C_LineMux;
+								break;
+							}
+							record =
+							    (ATOM_COMMON_RECORD_HEADER
+							     *) ((char *)record
+								 +
+								 record->
+								 ucRecordSize);
+						}
+						break;
+					}
+				}
+			} else
+				line_mux = 0;
+
+			if ((le16_to_cpu(path->usDeviceTag) ==
+			     ATOM_DEVICE_TV1_SUPPORT)
+			    || (le16_to_cpu(path->usDeviceTag) ==
+				ATOM_DEVICE_TV2_SUPPORT)
+			    || (le16_to_cpu(path->usDeviceTag) ==
+				ATOM_DEVICE_CV_SUPPORT))
+				ddc_bus.valid = false;
+			else
+				ddc_bus = radeon_lookup_gpio(dev, line_mux);
+
+			radeon_add_atom_connector(dev,
+						  le16_to_cpu(path->
+							      usConnObjectId),
+						  le16_to_cpu(path->
+							      usDeviceTag),
+						  connector_type, &ddc_bus,
+						  linkb, igp_lane_info);
+
+		}
+	}
+
+	radeon_link_encoder_connector(dev);
+
+	return true;
+}
+
+struct bios_connector {
+	bool valid;
+	uint8_t line_mux;
+	uint16_t devices;
+	int connector_type;
+	struct radeon_i2c_bus_rec ddc_bus;
+};
+
+bool radeon_get_atom_connector_info_from_supported_devices_table(struct
+								 drm_device
+								 *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	struct atom_context *ctx = mode_info->atom_context;
+	int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo);
+	uint16_t size, data_offset;
+	uint8_t frev, crev;
+	uint16_t device_support;
+	uint8_t dac;
+	union atom_supported_devices *supported_devices;
+	int i, j;
+	struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
+
+	atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
+
+	supported_devices =
+	    (union atom_supported_devices *)(ctx->bios + data_offset);
+
+	device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
+
+	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+		ATOM_CONNECTOR_INFO_I2C ci =
+		    supported_devices->info.asConnInfo[i];
+
+		bios_connectors[i].valid = false;
+
+		if (!(device_support & (1 << i))) {
+			continue;
+		}
+
+		if (i == ATOM_DEVICE_CV_INDEX) {
+			DRM_DEBUG("Skipping Component Video\n");
+			continue;
+		}
+
+		if (i == ATOM_DEVICE_TV1_INDEX) {
+			DRM_DEBUG("Skipping TV Out\n");
+			continue;
+		}
+
+		bios_connectors[i].connector_type =
+		    supported_devices_connector_convert[ci.sucConnectorInfo.
+							sbfAccess.
+							bfConnectorType];
+
+		if (bios_connectors[i].connector_type ==
+		    DRM_MODE_CONNECTOR_Unknown)
+			continue;
+
+		dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
+
+		if ((rdev->family == CHIP_RS690) ||
+		    (rdev->family == CHIP_RS740)) {
+			if ((i == ATOM_DEVICE_DFP2_INDEX)
+			    && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 2))
+				bios_connectors[i].line_mux =
+				    ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1;
+			else if ((i == ATOM_DEVICE_DFP3_INDEX)
+				 && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 1))
+				bios_connectors[i].line_mux =
+				    ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1;
+			else
+				bios_connectors[i].line_mux =
+				    ci.sucI2cId.sbfAccess.bfI2C_LineMux;
+		} else
+			bios_connectors[i].line_mux =
+			    ci.sucI2cId.sbfAccess.bfI2C_LineMux;
+
+		/* give tv unique connector ids */
+		if (i == ATOM_DEVICE_TV1_INDEX) {
+			bios_connectors[i].ddc_bus.valid = false;
+			bios_connectors[i].line_mux = 50;
+		} else if (i == ATOM_DEVICE_TV2_INDEX) {
+			bios_connectors[i].ddc_bus.valid = false;
+			bios_connectors[i].line_mux = 51;
+		} else if (i == ATOM_DEVICE_CV_INDEX) {
+			bios_connectors[i].ddc_bus.valid = false;
+			bios_connectors[i].line_mux = 52;
+		} else
+			bios_connectors[i].ddc_bus =
+			    radeon_lookup_gpio(dev,
+					       bios_connectors[i].line_mux);
+
+		/* Always set the connector type to VGA for CRT1/CRT2. if they are
+		 * shared with a DVI port, we'll pick up the DVI connector when we
+		 * merge the outputs.  Some bioses incorrectly list VGA ports as DVI.
+		 */
+		if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX)
+			bios_connectors[i].connector_type =
+			    DRM_MODE_CONNECTOR_VGA;
+
+		if (!radeon_atom_apply_quirks
+		    (dev, (1 << i), &bios_connectors[i].connector_type,
+		     &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
+			continue;
+
+		bios_connectors[i].valid = true;
+		bios_connectors[i].devices = (1 << i);
+
+		if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)
+			radeon_add_atom_encoder(dev,
+						radeon_get_encoder_id(dev,
+								      (1 << i),
+								      dac),
+						(1 << i));
+		else
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									(1 <<
+									 i),
+									dac),
+						  (1 << i));
+	}
+
+	/* combine shared connectors */
+	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+		if (bios_connectors[i].valid) {
+			for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) {
+				if (bios_connectors[j].valid && (i != j)) {
+					if (bios_connectors[i].line_mux ==
+					    bios_connectors[j].line_mux) {
+						if (((bios_connectors[i].
+						      devices &
+						      (ATOM_DEVICE_DFP_SUPPORT))
+						     && (bios_connectors[j].
+							 devices &
+							 (ATOM_DEVICE_CRT_SUPPORT)))
+						    ||
+						    ((bios_connectors[j].
+						      devices &
+						      (ATOM_DEVICE_DFP_SUPPORT))
+						     && (bios_connectors[i].
+							 devices &
+							 (ATOM_DEVICE_CRT_SUPPORT)))) {
+							bios_connectors[i].
+							    devices |=
+							    bios_connectors[j].
+							    devices;
+							bios_connectors[i].
+							    connector_type =
+							    DRM_MODE_CONNECTOR_DVII;
+							bios_connectors[j].
+							    valid = false;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/* add the connectors */
+	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+		if (bios_connectors[i].valid)
+			radeon_add_atom_connector(dev,
+						  bios_connectors[i].line_mux,
+						  bios_connectors[i].devices,
+						  bios_connectors[i].
+						  connector_type,
+						  &bios_connectors[i].ddc_bus,
+						  false, 0);
+	}
+
+	radeon_link_encoder_connector(dev);
+
+	return true;
+}
+
+union firmware_info {
+	ATOM_FIRMWARE_INFO info;
+	ATOM_FIRMWARE_INFO_V1_2 info_12;
+	ATOM_FIRMWARE_INFO_V1_3 info_13;
+	ATOM_FIRMWARE_INFO_V1_4 info_14;
+};
+
+bool radeon_atom_get_clock_info(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+	union firmware_info *firmware_info;
+	uint8_t frev, crev;
+	struct radeon_pll *p1pll = &rdev->clock.p1pll;
+	struct radeon_pll *p2pll = &rdev->clock.p2pll;
+	struct radeon_pll *spll = &rdev->clock.spll;
+	struct radeon_pll *mpll = &rdev->clock.mpll;
+	uint16_t data_offset;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
+			       &crev, &data_offset);
+
+	firmware_info =
+	    (union firmware_info *)(mode_info->atom_context->bios +
+				    data_offset);
+
+	if (firmware_info) {
+		/* pixel clocks */
+		p1pll->reference_freq =
+		    le16_to_cpu(firmware_info->info.usReferenceClock);
+		p1pll->reference_div = 0;
+
+		p1pll->pll_out_min =
+		    le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
+		p1pll->pll_out_max =
+		    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
+
+		if (p1pll->pll_out_min == 0) {
+			if (ASIC_IS_AVIVO(rdev))
+				p1pll->pll_out_min = 64800;
+			else
+				p1pll->pll_out_min = 20000;
+		}
+
+		p1pll->pll_in_min =
+		    le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
+		p1pll->pll_in_max =
+		    le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);
+
+		*p2pll = *p1pll;
+
+		/* system clock */
+		spll->reference_freq =
+		    le16_to_cpu(firmware_info->info.usReferenceClock);
+		spll->reference_div = 0;
+
+		spll->pll_out_min =
+		    le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output);
+		spll->pll_out_max =
+		    le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output);
+
+		/* ??? */
+		if (spll->pll_out_min == 0) {
+			if (ASIC_IS_AVIVO(rdev))
+				spll->pll_out_min = 64800;
+			else
+				spll->pll_out_min = 20000;
+		}
+
+		spll->pll_in_min =
+		    le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input);
+		spll->pll_in_max =
+		    le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input);
+
+		/* memory clock */
+		mpll->reference_freq =
+		    le16_to_cpu(firmware_info->info.usReferenceClock);
+		mpll->reference_div = 0;
+
+		mpll->pll_out_min =
+		    le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output);
+		mpll->pll_out_max =
+		    le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output);
+
+		/* ??? */
+		if (mpll->pll_out_min == 0) {
+			if (ASIC_IS_AVIVO(rdev))
+				mpll->pll_out_min = 64800;
+			else
+				mpll->pll_out_min = 20000;
+		}
+
+		mpll->pll_in_min =
+		    le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input);
+		mpll->pll_in_max =
+		    le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input);
+
+		rdev->clock.default_sclk =
+		    le32_to_cpu(firmware_info->info.ulDefaultEngineClock);
+		rdev->clock.default_mclk =
+		    le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
+
+		return true;
+	}
+	return false;
+}
+
+struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct
+							      radeon_encoder
+							      *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, TMDS_Info);
+	uint16_t data_offset;
+	struct _ATOM_TMDS_INFO *tmds_info;
+	uint8_t frev, crev;
+	uint16_t maxfreq;
+	int i;
+	struct radeon_encoder_int_tmds *tmds = NULL;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
+			       &crev, &data_offset);
+
+	tmds_info =
+	    (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
+				       data_offset);
+
+	if (tmds_info) {
+		tmds =
+		    kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
+
+		if (!tmds)
+			return NULL;
+
+		maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
+		for (i = 0; i < 4; i++) {
+			tmds->tmds_pll[i].freq =
+			    le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency);
+			tmds->tmds_pll[i].value =
+			    tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f;
+			tmds->tmds_pll[i].value |=
+			    (tmds_info->asMiscInfo[i].
+			     ucPLL_VCO_Gain & 0x3f) << 6;
+			tmds->tmds_pll[i].value |=
+			    (tmds_info->asMiscInfo[i].
+			     ucPLL_DutyCycle & 0xf) << 12;
+			tmds->tmds_pll[i].value |=
+			    (tmds_info->asMiscInfo[i].
+			     ucPLL_VoltageSwing & 0xf) << 16;
+
+			DRM_DEBUG("TMDS PLL From ATOMBIOS %u %x\n",
+				  tmds->tmds_pll[i].freq,
+				  tmds->tmds_pll[i].value);
+
+			if (maxfreq == tmds->tmds_pll[i].freq) {
+				tmds->tmds_pll[i].freq = 0xffffffff;
+				break;
+			}
+		}
+	}
+	return tmds;
+}
+
+union lvds_info {
+	struct _ATOM_LVDS_INFO info;
+	struct _ATOM_LVDS_INFO_V12 info_12;
+};
+
+struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
+							      radeon_encoder
+							      *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
+	uint16_t data_offset;
+	union lvds_info *lvds_info;
+	uint8_t frev, crev;
+	struct radeon_encoder_atom_dig *lvds = NULL;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
+			       &crev, &data_offset);
+
+	lvds_info =
+	    (union lvds_info *)(mode_info->atom_context->bios + data_offset);
+
+	if (lvds_info) {
+		lvds =
+		    kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
+
+		if (!lvds)
+			return NULL;
+
+		lvds->native_mode.dotclock =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
+		lvds->native_mode.panel_xres =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
+		lvds->native_mode.panel_yres =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
+		lvds->native_mode.hblank =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
+		lvds->native_mode.hoverplus =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
+		lvds->native_mode.hsync_width =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
+		lvds->native_mode.vblank =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
+		lvds->native_mode.voverplus =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
+		lvds->native_mode.vsync_width =
+		    le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
+		lvds->panel_pwr_delay =
+		    le16_to_cpu(lvds_info->info.usOffDelayInMs);
+		lvds->lvds_misc = lvds_info->info.ucLVDS_Misc;
+
+		encoder->native_mode = lvds->native_mode;
+	}
+	return lvds;
+}
+
+struct radeon_encoder_primary_dac *
+radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, CompassionateData);
+	uint16_t data_offset;
+	struct _COMPASSIONATE_DATA *dac_info;
+	uint8_t frev, crev;
+	uint8_t bg, dac;
+	struct radeon_encoder_primary_dac *p_dac = NULL;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+
+	dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
+
+	if (dac_info) {
+		p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
+
+		if (!p_dac)
+			return NULL;
+
+		bg = dac_info->ucDAC1_BG_Adjustment;
+		dac = dac_info->ucDAC1_DAC_Adjustment;
+		p_dac->ps2_pdac_adj = (bg << 8) | (dac);
+
+	}
+	return p_dac;
+}
+
+struct radeon_encoder_tv_dac *
+radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, CompassionateData);
+	uint16_t data_offset;
+	struct _COMPASSIONATE_DATA *dac_info;
+	uint8_t frev, crev;
+	uint8_t bg, dac;
+	struct radeon_encoder_tv_dac *tv_dac = NULL;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+
+	dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
+
+	if (dac_info) {
+		tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
+
+		if (!tv_dac)
+			return NULL;
+
+		bg = dac_info->ucDAC2_CRT2_BG_Adjustment;
+		dac = dac_info->ucDAC2_CRT2_DAC_Adjustment;
+		tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
+
+		bg = dac_info->ucDAC2_PAL_BG_Adjustment;
+		dac = dac_info->ucDAC2_PAL_DAC_Adjustment;
+		tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
+
+		bg = dac_info->ucDAC2_NTSC_BG_Adjustment;
+		dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
+		tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
+
+	}
+	return tv_dac;
+}
+
+void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
+{
+	DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating);
+
+	args.ucEnable = enable;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+void radeon_atom_static_pwrmgt_setup(struct radeon_device *rdev, int enable)
+{
+	ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt);
+
+	args.ucEnable = enable;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+void radeon_atom_set_engine_clock(struct radeon_device *rdev,
+				  uint32_t eng_clock)
+{
+	SET_ENGINE_CLOCK_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
+
+	args.ulTargetEngineClock = eng_clock;	/* 10 khz */
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+void radeon_atom_set_memory_clock(struct radeon_device *rdev,
+				  uint32_t mem_clock)
+{
+	SET_MEMORY_CLOCK_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return;
+
+	args.ulTargetMemoryClock = mem_clock;	/* 10 khz */
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t bios_2_scratch, bios_6_scratch;
+
+	if (rdev->family >= CHIP_R600) {
+		bios_2_scratch = RREG32(R600_BIOS_0_SCRATCH);
+		bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
+	} else {
+		bios_2_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
+		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
+	}
+
+	/* let the bios control the backlight */
+	bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
+
+	/* tell the bios not to handle mode switching */
+	bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE);
+
+	if (rdev->family >= CHIP_R600) {
+		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
+		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
+	} else {
+		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
+		WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+	}
+
+}
+
+void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t bios_6_scratch;
+
+	if (rdev->family >= CHIP_R600)
+		bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
+	else
+		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
+
+	if (lock)
+		bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
+	else
+		bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
+
+	if (rdev->family >= CHIP_R600)
+		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
+	else
+		WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+}
+
+/* at some point we may want to break this out into individual functions */
+void
+radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
+				       struct drm_encoder *encoder,
+				       bool connected)
+{
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_connector *radeon_connector =
+	    to_radeon_connector(connector);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch;
+
+	if (rdev->family >= CHIP_R600) {
+		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+		bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
+		bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
+	} else {
+		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
+		bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
+		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
+	}
+
+	if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("TV1 connected\n");
+			bios_3_scratch |= ATOM_S3_TV1_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_TV1;
+		} else {
+			DRM_DEBUG("TV1 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_TV1_MASK;
+			bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("CV connected\n");
+			bios_3_scratch |= ATOM_S3_CV_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_CV;
+		} else {
+			DRM_DEBUG("CV disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_CV_MASK;
+			bios_3_scratch &= ~ATOM_S3_CV_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("LCD1 connected\n");
+			bios_0_scratch |= ATOM_S0_LCD1;
+			bios_3_scratch |= ATOM_S3_LCD1_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1;
+		} else {
+			DRM_DEBUG("LCD1 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_LCD1;
+			bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("CRT1 connected\n");
+			bios_0_scratch |= ATOM_S0_CRT1_COLOR;
+			bios_3_scratch |= ATOM_S3_CRT1_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1;
+		} else {
+			DRM_DEBUG("CRT1 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_CRT1_MASK;
+			bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("CRT2 connected\n");
+			bios_0_scratch |= ATOM_S0_CRT2_COLOR;
+			bios_3_scratch |= ATOM_S3_CRT2_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2;
+		} else {
+			DRM_DEBUG("CRT2 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_CRT2_MASK;
+			bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("DFP1 connected\n");
+			bios_0_scratch |= ATOM_S0_DFP1;
+			bios_3_scratch |= ATOM_S3_DFP1_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1;
+		} else {
+			DRM_DEBUG("DFP1 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_DFP1;
+			bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("DFP2 connected\n");
+			bios_0_scratch |= ATOM_S0_DFP2;
+			bios_3_scratch |= ATOM_S3_DFP2_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2;
+		} else {
+			DRM_DEBUG("DFP2 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_DFP2;
+			bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("DFP3 connected\n");
+			bios_0_scratch |= ATOM_S0_DFP3;
+			bios_3_scratch |= ATOM_S3_DFP3_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3;
+		} else {
+			DRM_DEBUG("DFP3 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_DFP3;
+			bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("DFP4 connected\n");
+			bios_0_scratch |= ATOM_S0_DFP4;
+			bios_3_scratch |= ATOM_S3_DFP4_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4;
+		} else {
+			DRM_DEBUG("DFP4 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_DFP4;
+			bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("DFP5 connected\n");
+			bios_0_scratch |= ATOM_S0_DFP5;
+			bios_3_scratch |= ATOM_S3_DFP5_ACTIVE;
+			bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5;
+		} else {
+			DRM_DEBUG("DFP5 disconnected\n");
+			bios_0_scratch &= ~ATOM_S0_DFP5;
+			bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE;
+			bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5;
+		}
+	}
+
+	if (rdev->family >= CHIP_R600) {
+		WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch);
+		WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
+		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
+	} else {
+		WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
+		WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
+		WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+	}
+}
+
+void
+radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t bios_3_scratch;
+
+	if (rdev->family >= CHIP_R600)
+		bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH);
+	else
+		bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH);
+
+	if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 18);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 24);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 16);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 20);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 17);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 19);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 23);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
+		bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE;
+		bios_3_scratch |= (crtc << 25);
+	}
+
+	if (rdev->family >= CHIP_R600)
+		WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch);
+	else
+		WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch);
+}
+
+void
+radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t bios_2_scratch;
+
+	if (rdev->family >= CHIP_R600)
+		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
+	else
+		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
+
+	if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_CV_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE;
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) {
+		if (on)
+			bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE;
+		else
+			bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE;
+	}
+
+	if (rdev->family >= CHIP_R600)
+		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
+	else
+		WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Jerome Glisse
+ */
+#include <drm/drmP.h>
+#include <drm/radeon_drm.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+
+void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
+			   unsigned sdomain, unsigned ddomain)
+{
+	struct radeon_object *dobj = NULL;
+	struct radeon_object *sobj = NULL;
+	struct radeon_fence *fence = NULL;
+	uint64_t saddr, daddr;
+	unsigned long start_jiffies;
+	unsigned long end_jiffies;
+	unsigned long time;
+	unsigned i, n, size;
+	int r;
+
+	size = bsize;
+	n = 1024;
+	r = radeon_object_create(rdev, NULL, size, true, sdomain, false, &sobj);
+	if (r) {
+		goto out_cleanup;
+	}
+	r = radeon_object_pin(sobj, sdomain, &saddr);
+	if (r) {
+		goto out_cleanup;
+	}
+	r = radeon_object_create(rdev, NULL, size, true, ddomain, false, &dobj);
+	if (r) {
+		goto out_cleanup;
+	}
+	r = radeon_object_pin(dobj, ddomain, &daddr);
+	if (r) {
+		goto out_cleanup;
+	}
+	start_jiffies = jiffies;
+	for (i = 0; i < n; i++) {
+		r = radeon_fence_create(rdev, &fence);
+		if (r) {
+			goto out_cleanup;
+		}
+		r = radeon_copy_dma(rdev, saddr, daddr, size / 4096, fence);
+		if (r) {
+			goto out_cleanup;
+		}
+		r = radeon_fence_wait(fence, false);
+		if (r) {
+			goto out_cleanup;
+		}
+		radeon_fence_unref(&fence);
+	}
+	end_jiffies = jiffies;
+	time = end_jiffies - start_jiffies;
+	time = jiffies_to_msecs(time);
+	if (time > 0) {
+		i = ((n * size) >> 10) / time;
+		printk(KERN_INFO "radeon: dma %u bo moves of %ukb from %d to %d"
+		       " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10,
+		       sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024);
+	}
+	start_jiffies = jiffies;
+	for (i = 0; i < n; i++) {
+		r = radeon_fence_create(rdev, &fence);
+		if (r) {
+			goto out_cleanup;
+		}
+		r = radeon_copy_blit(rdev, saddr, daddr, size / 4096, fence);
+		if (r) {
+			goto out_cleanup;
+		}
+		r = radeon_fence_wait(fence, false);
+		if (r) {
+			goto out_cleanup;
+		}
+		radeon_fence_unref(&fence);
+	}
+	end_jiffies = jiffies;
+	time = end_jiffies - start_jiffies;
+	time = jiffies_to_msecs(time);
+	if (time > 0) {
+		i = ((n * size) >> 10) / time;
+		printk(KERN_INFO "radeon: blit %u bo moves of %ukb from %d to %d"
+		       " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10,
+		       sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024);
+	}
+out_cleanup:
+	if (sobj) {
+		radeon_object_unpin(sobj);
+		radeon_object_unref(&sobj);
+	}
+	if (dobj) {
+		radeon_object_unpin(dobj);
+		radeon_object_unref(&dobj);
+	}
+	if (fence) {
+		radeon_fence_unref(&fence);
+	}
+	if (r) {
+		printk(KERN_WARNING "Error while benchmarking BO move.\n");
+	}
+}
+
+void radeon_benchmark(struct radeon_device *rdev)
+{
+	radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT,
+			      RADEON_GEM_DOMAIN_VRAM);
+	radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM,
+			      RADEON_GEM_DOMAIN_GTT);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_bios.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_bios.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_bios.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_bios.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,390 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "atom.h"
+
+/*
+ * BIOS.
+ */
+static bool radeon_read_bios(struct radeon_device *rdev)
+{
+	uint8_t __iomem *bios;
+	size_t size;
+
+	rdev->bios = NULL;
+	bios = pci_map_rom(rdev->pdev, &size);
+	if (!bios) {
+		return false;
+	}
+
+	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+		pci_unmap_rom(rdev->pdev, bios);
+		return false;
+	}
+	rdev->bios = kmalloc(size, GFP_KERNEL);
+	if (rdev->bios == NULL) {
+		pci_unmap_rom(rdev->pdev, bios);
+		return false;
+	}
+	memcpy(rdev->bios, bios, size);
+	pci_unmap_rom(rdev->pdev, bios);
+	return true;
+}
+
+static bool r700_read_disabled_bios(struct radeon_device *rdev)
+{
+	uint32_t viph_control;
+	uint32_t bus_cntl;
+	uint32_t d1vga_control;
+	uint32_t d2vga_control;
+	uint32_t vga_render_control;
+	uint32_t rom_cntl;
+	uint32_t cg_spll_func_cntl = 0;
+	uint32_t cg_spll_status;
+	bool r;
+
+	viph_control = RREG32(RADEON_VIPH_CONTROL);
+	bus_cntl = RREG32(RADEON_BUS_CNTL);
+	d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+	d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+	vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+	rom_cntl = RREG32(R600_ROM_CNTL);
+
+	/* disable VIP */
+	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+	/* enable the rom */
+	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+	/* Disable VGA mode */
+	WREG32(AVIVO_D1VGA_CONTROL,
+	       (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_D2VGA_CONTROL,
+	       (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_VGA_RENDER_CONTROL,
+	       (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+	if (rdev->family == CHIP_RV730) {
+		cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL);
+
+		/* enable bypass mode */
+		WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl |
+						R600_SPLL_BYPASS_EN));
+
+		/* wait for SPLL_CHG_STATUS to change to 1 */
+		cg_spll_status = 0;
+		while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+			cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+
+		WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE));
+	} else
+		WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE));
+
+	r = radeon_read_bios(rdev);
+
+	/* restore regs */
+	if (rdev->family == CHIP_RV730) {
+		WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl);
+
+		/* wait for SPLL_CHG_STATUS to change to 1 */
+		cg_spll_status = 0;
+		while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+			cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+	}
+	WREG32(RADEON_VIPH_CONTROL, viph_control);
+	WREG32(RADEON_BUS_CNTL, bus_cntl);
+	WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+	WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+	WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+	WREG32(R600_ROM_CNTL, rom_cntl);
+	return r;
+}
+
+static bool r600_read_disabled_bios(struct radeon_device *rdev)
+{
+	uint32_t viph_control;
+	uint32_t bus_cntl;
+	uint32_t d1vga_control;
+	uint32_t d2vga_control;
+	uint32_t vga_render_control;
+	uint32_t rom_cntl;
+	uint32_t general_pwrmgt;
+	uint32_t low_vid_lower_gpio_cntl;
+	uint32_t medium_vid_lower_gpio_cntl;
+	uint32_t high_vid_lower_gpio_cntl;
+	uint32_t ctxsw_vid_lower_gpio_cntl;
+	uint32_t lower_gpio_enable;
+	bool r;
+
+	viph_control = RREG32(RADEON_VIPH_CONTROL);
+	bus_cntl = RREG32(RADEON_BUS_CNTL);
+	d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+	d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+	vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+	rom_cntl = RREG32(R600_ROM_CNTL);
+	general_pwrmgt = RREG32(R600_GENERAL_PWRMGT);
+	low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL);
+	medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL);
+	high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL);
+	ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL);
+	lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE);
+
+	/* disable VIP */
+	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+	/* enable the rom */
+	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+	/* Disable VGA mode */
+	WREG32(AVIVO_D1VGA_CONTROL,
+	       (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_D2VGA_CONTROL,
+	       (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_VGA_RENDER_CONTROL,
+	       (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+	WREG32(R600_ROM_CNTL,
+	       ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) |
+		(1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) |
+		R600_SCK_OVERWRITE));
+
+	WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS));
+	WREG32(R600_LOW_VID_LOWER_GPIO_CNTL,
+	       (low_vid_lower_gpio_cntl & ~0x400));
+	WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL,
+	       (medium_vid_lower_gpio_cntl & ~0x400));
+	WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL,
+	       (high_vid_lower_gpio_cntl & ~0x400));
+	WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL,
+	       (ctxsw_vid_lower_gpio_cntl & ~0x400));
+	WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400));
+
+	r = radeon_read_bios(rdev);
+
+	/* restore regs */
+	WREG32(RADEON_VIPH_CONTROL, viph_control);
+	WREG32(RADEON_BUS_CNTL, bus_cntl);
+	WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+	WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+	WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+	WREG32(R600_ROM_CNTL, rom_cntl);
+	WREG32(R600_GENERAL_PWRMGT, general_pwrmgt);
+	WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl);
+	WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl);
+	WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl);
+	WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl);
+	WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable);
+	return r;
+}
+
+static bool avivo_read_disabled_bios(struct radeon_device *rdev)
+{
+	uint32_t seprom_cntl1;
+	uint32_t viph_control;
+	uint32_t bus_cntl;
+	uint32_t d1vga_control;
+	uint32_t d2vga_control;
+	uint32_t vga_render_control;
+	uint32_t gpiopad_a;
+	uint32_t gpiopad_en;
+	uint32_t gpiopad_mask;
+	bool r;
+
+	seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+	viph_control = RREG32(RADEON_VIPH_CONTROL);
+	bus_cntl = RREG32(RADEON_BUS_CNTL);
+	d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+	d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+	vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+	gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+	gpiopad_en = RREG32(RADEON_GPIOPAD_EN);
+	gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK);
+
+	WREG32(RADEON_SEPROM_CNTL1,
+	       ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+		(0xc << RADEON_SCK_PRESCALE_SHIFT)));
+	WREG32(RADEON_GPIOPAD_A, 0);
+	WREG32(RADEON_GPIOPAD_EN, 0);
+	WREG32(RADEON_GPIOPAD_MASK, 0);
+
+	/* disable VIP */
+	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+	/* enable the rom */
+	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+
+	/* Disable VGA mode */
+	WREG32(AVIVO_D1VGA_CONTROL,
+	       (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_D2VGA_CONTROL,
+	       (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+		AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+	WREG32(AVIVO_VGA_RENDER_CONTROL,
+	       (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+	r = radeon_read_bios(rdev);
+
+	/* restore regs */
+	WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+	WREG32(RADEON_VIPH_CONTROL, viph_control);
+	WREG32(RADEON_BUS_CNTL, bus_cntl);
+	WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+	WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+	WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+	WREG32(RADEON_GPIOPAD_A, gpiopad_a);
+	WREG32(RADEON_GPIOPAD_EN, gpiopad_en);
+	WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask);
+	return r;
+}
+
+static bool legacy_read_disabled_bios(struct radeon_device *rdev)
+{
+	uint32_t seprom_cntl1;
+	uint32_t viph_control;
+	uint32_t bus_cntl;
+	uint32_t crtc_gen_cntl;
+	uint32_t crtc2_gen_cntl;
+	uint32_t crtc_ext_cntl;
+	uint32_t fp2_gen_cntl;
+	bool r;
+
+	seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+	viph_control = RREG32(RADEON_VIPH_CONTROL);
+	bus_cntl = RREG32(RADEON_BUS_CNTL);
+	crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
+	crtc2_gen_cntl = 0;
+	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+	fp2_gen_cntl = 0;
+
+	if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+	}
+
+	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+	}
+
+	WREG32(RADEON_SEPROM_CNTL1,
+	       ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+		(0xc << RADEON_SCK_PRESCALE_SHIFT)));
+
+	/* disable VIP */
+	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+	/* enable the rom */
+	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+
+	/* Turn off mem requests and CRTC for both controllers */
+	WREG32(RADEON_CRTC_GEN_CNTL,
+	       ((crtc_gen_cntl & ~RADEON_CRTC_EN) |
+		(RADEON_CRTC_DISP_REQ_EN_B |
+		 RADEON_CRTC_EXT_DISP_EN)));
+	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+		WREG32(RADEON_CRTC2_GEN_CNTL,
+		       ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) |
+			RADEON_CRTC2_DISP_REQ_EN_B));
+	}
+	/* Turn off CRTC */
+	WREG32(RADEON_CRTC_EXT_CNTL,
+	       ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) |
+		(RADEON_CRTC_SYNC_TRISTAT |
+		 RADEON_CRTC_DISPLAY_DIS)));
+
+	if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+		WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON));
+	}
+
+	r = radeon_read_bios(rdev);
+
+	/* restore regs */
+	WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+	WREG32(RADEON_VIPH_CONTROL, viph_control);
+	WREG32(RADEON_BUS_CNTL, bus_cntl);
+	WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
+	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+	}
+	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+	if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+	}
+	return r;
+}
+
+static bool radeon_read_disabled_bios(struct radeon_device *rdev)
+{
+	if (rdev->family >= CHIP_RV770)
+		return r700_read_disabled_bios(rdev);
+	else if (rdev->family >= CHIP_R600)
+		return r600_read_disabled_bios(rdev);
+	else if (rdev->family >= CHIP_RS600)
+		return avivo_read_disabled_bios(rdev);
+	else
+		return legacy_read_disabled_bios(rdev);
+}
+
+bool radeon_get_bios(struct radeon_device *rdev)
+{
+	bool r;
+	uint16_t tmp;
+
+	r = radeon_read_bios(rdev);
+	if (r == false) {
+		r = radeon_read_disabled_bios(rdev);
+	}
+	if (r == false || rdev->bios == NULL) {
+		DRM_ERROR("Unable to locate a BIOS ROM\n");
+		rdev->bios = NULL;
+		return false;
+	}
+	if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+		goto free_bios;
+	}
+
+	rdev->bios_header_start = RBIOS16(0x48);
+	if (!rdev->bios_header_start) {
+		goto free_bios;
+	}
+	tmp = rdev->bios_header_start + 4;
+	if (!memcmp(rdev->bios + tmp, "ATOM", 4) ||
+	    !memcmp(rdev->bios + tmp, "MOTA", 4)) {
+		rdev->is_atom_bios = true;
+	} else {
+		rdev->is_atom_bios = false;
+	}
+
+	DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM");
+	return true;
+free_bios:
+	kfree(rdev->bios);
+	rdev->bios = NULL;
+	return false;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_clocks.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_clocks.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_clocks.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_clocks.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,833 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "atom.h"
+
+/* 10 khz */
+static uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
+{
+	struct radeon_pll *spll = &rdev->clock.spll;
+	uint32_t fb_div, ref_div, post_div, sclk;
+
+	fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
+	fb_div = (fb_div >> RADEON_SPLL_FB_DIV_SHIFT) & RADEON_SPLL_FB_DIV_MASK;
+	fb_div <<= 1;
+	fb_div *= spll->reference_freq;
+
+	ref_div =
+	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
+	sclk = fb_div / ref_div;
+
+	post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK;
+	if (post_div == 2)
+		sclk >>= 1;
+	else if (post_div == 3)
+		sclk >>= 2;
+	else if (post_div == 4)
+		sclk >>= 4;
+
+	return sclk;
+}
+
+/* 10 khz */
+static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
+{
+	struct radeon_pll *mpll = &rdev->clock.mpll;
+	uint32_t fb_div, ref_div, post_div, mclk;
+
+	fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
+	fb_div = (fb_div >> RADEON_MPLL_FB_DIV_SHIFT) & RADEON_MPLL_FB_DIV_MASK;
+	fb_div <<= 1;
+	fb_div *= mpll->reference_freq;
+
+	ref_div =
+	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
+	mclk = fb_div / ref_div;
+
+	post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7;
+	if (post_div == 2)
+		mclk >>= 1;
+	else if (post_div == 3)
+		mclk >>= 2;
+	else if (post_div == 4)
+		mclk >>= 4;
+
+	return mclk;
+}
+
+void radeon_get_clock_info(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_pll *p1pll = &rdev->clock.p1pll;
+	struct radeon_pll *p2pll = &rdev->clock.p2pll;
+	struct radeon_pll *spll = &rdev->clock.spll;
+	struct radeon_pll *mpll = &rdev->clock.mpll;
+	int ret;
+
+	if (rdev->is_atom_bios)
+		ret = radeon_atom_get_clock_info(dev);
+	else
+		ret = radeon_combios_get_clock_info(dev);
+
+	if (ret) {
+		if (p1pll->reference_div < 2)
+			p1pll->reference_div = 12;
+		if (p2pll->reference_div < 2)
+			p2pll->reference_div = 12;
+		if (spll->reference_div < 2)
+			spll->reference_div =
+			    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
+			    RADEON_M_SPLL_REF_DIV_MASK;
+		if (mpll->reference_div < 2)
+			mpll->reference_div = spll->reference_div;
+	} else {
+		if (ASIC_IS_AVIVO(rdev)) {
+			/* TODO FALLBACK */
+		} else {
+			DRM_INFO("Using generic clock info\n");
+
+			if (rdev->flags & RADEON_IS_IGP) {
+				p1pll->reference_freq = 1432;
+				p2pll->reference_freq = 1432;
+				spll->reference_freq = 1432;
+				mpll->reference_freq = 1432;
+			} else {
+				p1pll->reference_freq = 2700;
+				p2pll->reference_freq = 2700;
+				spll->reference_freq = 2700;
+				mpll->reference_freq = 2700;
+			}
+			p1pll->reference_div =
+			    RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
+			if (p1pll->reference_div < 2)
+				p1pll->reference_div = 12;
+			p2pll->reference_div = p1pll->reference_div;
+
+			if (rdev->family >= CHIP_R420) {
+				p1pll->pll_in_min = 100;
+				p1pll->pll_in_max = 1350;
+				p1pll->pll_out_min = 20000;
+				p1pll->pll_out_max = 50000;
+				p2pll->pll_in_min = 100;
+				p2pll->pll_in_max = 1350;
+				p2pll->pll_out_min = 20000;
+				p2pll->pll_out_max = 50000;
+			} else {
+				p1pll->pll_in_min = 40;
+				p1pll->pll_in_max = 500;
+				p1pll->pll_out_min = 12500;
+				p1pll->pll_out_max = 35000;
+				p2pll->pll_in_min = 40;
+				p2pll->pll_in_max = 500;
+				p2pll->pll_out_min = 12500;
+				p2pll->pll_out_max = 35000;
+			}
+
+			spll->reference_div =
+			    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
+			    RADEON_M_SPLL_REF_DIV_MASK;
+			mpll->reference_div = spll->reference_div;
+			rdev->clock.default_sclk =
+			    radeon_legacy_get_engine_clock(rdev);
+			rdev->clock.default_mclk =
+			    radeon_legacy_get_memory_clock(rdev);
+		}
+	}
+
+	/* pixel clocks */
+	if (ASIC_IS_AVIVO(rdev)) {
+		p1pll->min_post_div = 2;
+		p1pll->max_post_div = 0x7f;
+		p1pll->min_frac_feedback_div = 0;
+		p1pll->max_frac_feedback_div = 9;
+		p2pll->min_post_div = 2;
+		p2pll->max_post_div = 0x7f;
+		p2pll->min_frac_feedback_div = 0;
+		p2pll->max_frac_feedback_div = 9;
+	} else {
+		p1pll->min_post_div = 1;
+		p1pll->max_post_div = 16;
+		p1pll->min_frac_feedback_div = 0;
+		p1pll->max_frac_feedback_div = 0;
+		p2pll->min_post_div = 1;
+		p2pll->max_post_div = 12;
+		p2pll->min_frac_feedback_div = 0;
+		p2pll->max_frac_feedback_div = 0;
+	}
+
+	p1pll->min_ref_div = 2;
+	p1pll->max_ref_div = 0x3ff;
+	p1pll->min_feedback_div = 4;
+	p1pll->max_feedback_div = 0x7ff;
+	p1pll->best_vco = 0;
+
+	p2pll->min_ref_div = 2;
+	p2pll->max_ref_div = 0x3ff;
+	p2pll->min_feedback_div = 4;
+	p2pll->max_feedback_div = 0x7ff;
+	p2pll->best_vco = 0;
+
+	/* system clock */
+	spll->min_post_div = 1;
+	spll->max_post_div = 1;
+	spll->min_ref_div = 2;
+	spll->max_ref_div = 0xff;
+	spll->min_feedback_div = 4;
+	spll->max_feedback_div = 0xff;
+	spll->best_vco = 0;
+
+	/* memory clock */
+	mpll->min_post_div = 1;
+	mpll->max_post_div = 1;
+	mpll->min_ref_div = 2;
+	mpll->max_ref_div = 0xff;
+	mpll->min_feedback_div = 4;
+	mpll->max_feedback_div = 0xff;
+	mpll->best_vco = 0;
+
+}
+
+/* 10 khz */
+static uint32_t calc_eng_mem_clock(struct radeon_device *rdev,
+				   uint32_t req_clock,
+				   int *fb_div, int *post_div)
+{
+	struct radeon_pll *spll = &rdev->clock.spll;
+	int ref_div = spll->reference_div;
+
+	if (!ref_div)
+		ref_div =
+		    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
+		    RADEON_M_SPLL_REF_DIV_MASK;
+
+	if (req_clock < 15000) {
+		*post_div = 8;
+		req_clock *= 8;
+	} else if (req_clock < 30000) {
+		*post_div = 4;
+		req_clock *= 4;
+	} else if (req_clock < 60000) {
+		*post_div = 2;
+		req_clock *= 2;
+	} else
+		*post_div = 1;
+
+	req_clock *= ref_div;
+	req_clock += spll->reference_freq;
+	req_clock /= (2 * spll->reference_freq);
+
+	*fb_div = req_clock & 0xff;
+
+	req_clock = (req_clock & 0xffff) << 1;
+	req_clock *= spll->reference_freq;
+	req_clock /= ref_div;
+	req_clock /= *post_div;
+
+	return req_clock;
+}
+
+/* 10 khz */
+void radeon_legacy_set_engine_clock(struct radeon_device *rdev,
+				    uint32_t eng_clock)
+{
+	uint32_t tmp;
+	int fb_div, post_div;
+
+	/* XXX: wait for idle */
+
+	eng_clock = calc_eng_mem_clock(rdev, eng_clock, &fb_div, &post_div);
+
+	tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
+	tmp &= ~RADEON_DONT_USE_XTALIN;
+	WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
+
+	tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+	tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
+	WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+	udelay(10);
+
+	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
+	tmp |= RADEON_SPLL_SLEEP;
+	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
+
+	udelay(2);
+
+	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
+	tmp |= RADEON_SPLL_RESET;
+	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
+
+	udelay(200);
+
+	tmp = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV);
+	tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT);
+	tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT;
+	WREG32_PLL(RADEON_M_SPLL_REF_FB_DIV, tmp);
+
+	/* XXX: verify on different asics */
+	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
+	tmp &= ~RADEON_SPLL_PVG_MASK;
+	if ((eng_clock * post_div) >= 90000)
+		tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT);
+	else
+		tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT);
+	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
+
+	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
+	tmp &= ~RADEON_SPLL_SLEEP;
+	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
+
+	udelay(2);
+
+	tmp = RREG32_PLL(RADEON_SPLL_CNTL);
+	tmp &= ~RADEON_SPLL_RESET;
+	WREG32_PLL(RADEON_SPLL_CNTL, tmp);
+
+	udelay(200);
+
+	tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+	tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
+	switch (post_div) {
+	case 1:
+	default:
+		tmp |= 1;
+		break;
+	case 2:
+		tmp |= 2;
+		break;
+	case 4:
+		tmp |= 3;
+		break;
+	case 8:
+		tmp |= 4;
+		break;
+	}
+	WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+	udelay(20);
+
+	tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
+	tmp |= RADEON_DONT_USE_XTALIN;
+	WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
+
+	udelay(10);
+}
+
+void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
+{
+	uint32_t tmp;
+
+	if (enable) {
+		if (rdev->flags & RADEON_SINGLE_CRTC) {
+			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+			if ((RREG32(RADEON_CONFIG_CNTL) &
+			     RADEON_CFG_ATI_REV_ID_MASK) >
+			    RADEON_CFG_ATI_REV_A13) {
+				tmp &=
+				    ~(RADEON_SCLK_FORCE_CP |
+				      RADEON_SCLK_FORCE_RB);
+			}
+			tmp &=
+			    ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 |
+			      RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE |
+			      RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE |
+			      RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM |
+			      RADEON_SCLK_FORCE_TDM);
+			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+		} else if (ASIC_IS_R300(rdev)) {
+			if ((rdev->family == CHIP_RS400) ||
+			    (rdev->family == CHIP_RS480)) {
+				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+				tmp &=
+				    ~(RADEON_SCLK_FORCE_DISP2 |
+				      RADEON_SCLK_FORCE_CP |
+				      RADEON_SCLK_FORCE_HDP |
+				      RADEON_SCLK_FORCE_DISP1 |
+				      RADEON_SCLK_FORCE_TOP |
+				      RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP
+				      | RADEON_SCLK_FORCE_IDCT |
+				      RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR
+				      | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX
+				      | R300_SCLK_FORCE_US |
+				      RADEON_SCLK_FORCE_TV_SCLK |
+				      R300_SCLK_FORCE_SU |
+				      RADEON_SCLK_FORCE_OV0);
+				tmp |= RADEON_DYN_STOP_LAT_MASK;
+				tmp |=
+				    RADEON_SCLK_FORCE_TOP |
+				    RADEON_SCLK_FORCE_VIP;
+				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
+				tmp &= ~RADEON_SCLK_MORE_FORCEON;
+				tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
+				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
+
+				tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+				tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
+					RADEON_PIXCLK_DAC_ALWAYS_ONb);
+				WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
+
+				tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+				tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
+					RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+					RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+					R300_DVOCLK_ALWAYS_ONb |
+					RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+					RADEON_PIXCLK_GV_ALWAYS_ONb |
+					R300_PIXCLK_DVO_ALWAYS_ONb |
+					RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+					RADEON_PIXCLK_TMDS_ALWAYS_ONb |
+					R300_PIXCLK_TRANS_ALWAYS_ONb |
+					R300_PIXCLK_TVO_ALWAYS_ONb |
+					R300_P2G2CLK_ALWAYS_ONb |
+					R300_P2G2CLK_ALWAYS_ONb);
+				WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
+			} else if (rdev->family >= CHIP_RV350) {
+				tmp = RREG32_PLL(R300_SCLK_CNTL2);
+				tmp &= ~(R300_SCLK_FORCE_TCL |
+					 R300_SCLK_FORCE_GA |
+					 R300_SCLK_FORCE_CBA);
+				tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT |
+					R300_SCLK_GA_MAX_DYN_STOP_LAT |
+					R300_SCLK_CBA_MAX_DYN_STOP_LAT);
+				WREG32_PLL(R300_SCLK_CNTL2, tmp);
+
+				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+				tmp &=
+				    ~(RADEON_SCLK_FORCE_DISP2 |
+				      RADEON_SCLK_FORCE_CP |
+				      RADEON_SCLK_FORCE_HDP |
+				      RADEON_SCLK_FORCE_DISP1 |
+				      RADEON_SCLK_FORCE_TOP |
+				      RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP
+				      | RADEON_SCLK_FORCE_IDCT |
+				      RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR
+				      | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX
+				      | R300_SCLK_FORCE_US |
+				      RADEON_SCLK_FORCE_TV_SCLK |
+				      R300_SCLK_FORCE_SU |
+				      RADEON_SCLK_FORCE_OV0);
+				tmp |= RADEON_DYN_STOP_LAT_MASK;
+				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
+				tmp &= ~RADEON_SCLK_MORE_FORCEON;
+				tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
+				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
+
+				tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+				tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
+					RADEON_PIXCLK_DAC_ALWAYS_ONb);
+				WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
+
+				tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+				tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
+					RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+					RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+					R300_DVOCLK_ALWAYS_ONb |
+					RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+					RADEON_PIXCLK_GV_ALWAYS_ONb |
+					R300_PIXCLK_DVO_ALWAYS_ONb |
+					RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+					RADEON_PIXCLK_TMDS_ALWAYS_ONb |
+					R300_PIXCLK_TRANS_ALWAYS_ONb |
+					R300_PIXCLK_TVO_ALWAYS_ONb |
+					R300_P2G2CLK_ALWAYS_ONb |
+					R300_P2G2CLK_ALWAYS_ONb);
+				WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
+
+				tmp = RREG32_PLL(RADEON_MCLK_MISC);
+				tmp |= (RADEON_MC_MCLK_DYN_ENABLE |
+					RADEON_IO_MCLK_DYN_ENABLE);
+				WREG32_PLL(RADEON_MCLK_MISC, tmp);
+
+				tmp = RREG32_PLL(RADEON_MCLK_CNTL);
+				tmp |= (RADEON_FORCEON_MCLKA |
+					RADEON_FORCEON_MCLKB);
+
+				tmp &= ~(RADEON_FORCEON_YCLKA |
+					 RADEON_FORCEON_YCLKB |
+					 RADEON_FORCEON_MC);
+
+				/* Some releases of vbios have set DISABLE_MC_MCLKA
+				   and DISABLE_MC_MCLKB bits in the vbios table.  Setting these
+				   bits will cause H/W hang when reading video memory with dynamic clocking
+				   enabled. */
+				if ((tmp & R300_DISABLE_MC_MCLKA) &&
+				    (tmp & R300_DISABLE_MC_MCLKB)) {
+					/* If both bits are set, then check the active channels */
+					tmp = RREG32_PLL(RADEON_MCLK_CNTL);
+					if (rdev->mc.vram_width == 64) {
+						if (RREG32(RADEON_MEM_CNTL) &
+						    R300_MEM_USE_CD_CH_ONLY)
+							tmp &=
+							    ~R300_DISABLE_MC_MCLKB;
+						else
+							tmp &=
+							    ~R300_DISABLE_MC_MCLKA;
+					} else {
+						tmp &= ~(R300_DISABLE_MC_MCLKA |
+							 R300_DISABLE_MC_MCLKB);
+					}
+				}
+
+				WREG32_PLL(RADEON_MCLK_CNTL, tmp);
+			} else {
+				tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+				tmp &= ~(R300_SCLK_FORCE_VAP);
+				tmp |= RADEON_SCLK_FORCE_CP;
+				WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+				udelay(15000);
+
+				tmp = RREG32_PLL(R300_SCLK_CNTL2);
+				tmp &= ~(R300_SCLK_FORCE_TCL |
+					 R300_SCLK_FORCE_GA |
+					 R300_SCLK_FORCE_CBA);
+				WREG32_PLL(R300_SCLK_CNTL2, tmp);
+			}
+		} else {
+			tmp = RREG32_PLL(RADEON_CLK_PWRMGT_CNTL);
+
+			tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK |
+				 RADEON_DISP_DYN_STOP_LAT_MASK |
+				 RADEON_DYN_STOP_MODE_MASK);
+
+			tmp |= (RADEON_ENGIN_DYNCLK_MODE |
+				(0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
+			WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp);
+			udelay(15000);
+
+			tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
+			tmp |= RADEON_SCLK_DYN_START_CNTL;
+			WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
+			udelay(15000);
+
+			/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
+			   to lockup randomly, leave them as set by BIOS.
+			 */
+			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+			/*tmp &= RADEON_SCLK_SRC_SEL_MASK; */
+			tmp &= ~RADEON_SCLK_FORCEON_MASK;
+
+			/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300 */
+			if (((rdev->family == CHIP_RV250) &&
+			     ((RREG32(RADEON_CONFIG_CNTL) &
+			       RADEON_CFG_ATI_REV_ID_MASK) <
+			      RADEON_CFG_ATI_REV_A13))
+			    || ((rdev->family == CHIP_RV100)
+				&&
+				((RREG32(RADEON_CONFIG_CNTL) &
+				  RADEON_CFG_ATI_REV_ID_MASK) <=
+				 RADEON_CFG_ATI_REV_A13))) {
+				tmp |= RADEON_SCLK_FORCE_CP;
+				tmp |= RADEON_SCLK_FORCE_VIP;
+			}
+
+			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+			if ((rdev->family == CHIP_RV200) ||
+			    (rdev->family == CHIP_RV250) ||
+			    (rdev->family == CHIP_RV280)) {
+				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
+				tmp &= ~RADEON_SCLK_MORE_FORCEON;
+
+				/* RV200::A11 A12 RV250::A11 A12 */
+				if (((rdev->family == CHIP_RV200) ||
+				     (rdev->family == CHIP_RV250)) &&
+				    ((RREG32(RADEON_CONFIG_CNTL) &
+				      RADEON_CFG_ATI_REV_ID_MASK) <
+				     RADEON_CFG_ATI_REV_A13)) {
+					tmp |= RADEON_SCLK_MORE_FORCEON;
+				}
+				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
+				udelay(15000);
+			}
+
+			/* RV200::A11 A12, RV250::A11 A12 */
+			if (((rdev->family == CHIP_RV200) ||
+			     (rdev->family == CHIP_RV250)) &&
+			    ((RREG32(RADEON_CONFIG_CNTL) &
+			      RADEON_CFG_ATI_REV_ID_MASK) <
+			     RADEON_CFG_ATI_REV_A13)) {
+				tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL);
+				tmp |= RADEON_TCL_BYPASS_DISABLE;
+				WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
+			}
+			udelay(15000);
+
+			/*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */
+			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+			tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
+				RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+				RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+				RADEON_PIXCLK_GV_ALWAYS_ONb |
+				RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
+				RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+				RADEON_PIXCLK_TMDS_ALWAYS_ONb);
+
+			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
+			udelay(15000);
+
+			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+			tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
+				RADEON_PIXCLK_DAC_ALWAYS_ONb);
+
+			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
+			udelay(15000);
+		}
+	} else {
+		/* Turn everything OFF (ForceON to everything) */
+		if (rdev->flags & RADEON_SINGLE_CRTC) {
+			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+			tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP |
+				RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP
+				| RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE |
+				RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP |
+				RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB |
+				RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM |
+				RADEON_SCLK_FORCE_RB);
+			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+		} else if ((rdev->family == CHIP_RS400) ||
+			   (rdev->family == CHIP_RS480)) {
+			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+			tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
+				RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1
+				| RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
+				R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
+				RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
+				R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
+				R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
+				R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
+			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+			tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
+			tmp |= RADEON_SCLK_MORE_FORCEON;
+			WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
+
+			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
+				 RADEON_PIXCLK_DAC_ALWAYS_ONb |
+				 R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
+			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
+
+			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
+				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+				 RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+				 R300_DVOCLK_ALWAYS_ONb |
+				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+				 RADEON_PIXCLK_GV_ALWAYS_ONb |
+				 R300_PIXCLK_DVO_ALWAYS_ONb |
+				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+				 RADEON_PIXCLK_TMDS_ALWAYS_ONb |
+				 R300_PIXCLK_TRANS_ALWAYS_ONb |
+				 R300_PIXCLK_TVO_ALWAYS_ONb |
+				 R300_P2G2CLK_ALWAYS_ONb |
+				 R300_P2G2CLK_ALWAYS_ONb |
+				 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
+			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
+		} else if (rdev->family >= CHIP_RV350) {
+			/* for RV350/M10, no delays are required. */
+			tmp = RREG32_PLL(R300_SCLK_CNTL2);
+			tmp |= (R300_SCLK_FORCE_TCL |
+				R300_SCLK_FORCE_GA | R300_SCLK_FORCE_CBA);
+			WREG32_PLL(R300_SCLK_CNTL2, tmp);
+
+			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+			tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
+				RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1
+				| RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
+				R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
+				RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
+				R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
+				R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
+				R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
+			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+			tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
+			tmp |= RADEON_SCLK_MORE_FORCEON;
+			WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
+
+			tmp = RREG32_PLL(RADEON_MCLK_CNTL);
+			tmp |= (RADEON_FORCEON_MCLKA |
+				RADEON_FORCEON_MCLKB |
+				RADEON_FORCEON_YCLKA |
+				RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC);
+			WREG32_PLL(RADEON_MCLK_CNTL, tmp);
+
+			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
+				 RADEON_PIXCLK_DAC_ALWAYS_ONb |
+				 R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
+			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
+
+			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
+				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+				 RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+				 R300_DVOCLK_ALWAYS_ONb |
+				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+				 RADEON_PIXCLK_GV_ALWAYS_ONb |
+				 R300_PIXCLK_DVO_ALWAYS_ONb |
+				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+				 RADEON_PIXCLK_TMDS_ALWAYS_ONb |
+				 R300_PIXCLK_TRANS_ALWAYS_ONb |
+				 R300_PIXCLK_TVO_ALWAYS_ONb |
+				 R300_P2G2CLK_ALWAYS_ONb |
+				 R300_P2G2CLK_ALWAYS_ONb |
+				 R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
+			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
+		} else {
+			tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+			tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2);
+			tmp |= RADEON_SCLK_FORCE_SE;
+
+			if (rdev->flags & RADEON_SINGLE_CRTC) {
+				tmp |= (RADEON_SCLK_FORCE_RB |
+					RADEON_SCLK_FORCE_TDM |
+					RADEON_SCLK_FORCE_TAM |
+					RADEON_SCLK_FORCE_PB |
+					RADEON_SCLK_FORCE_RE |
+					RADEON_SCLK_FORCE_VIP |
+					RADEON_SCLK_FORCE_IDCT |
+					RADEON_SCLK_FORCE_TOP |
+					RADEON_SCLK_FORCE_DISP1 |
+					RADEON_SCLK_FORCE_DISP2 |
+					RADEON_SCLK_FORCE_HDP);
+			} else if ((rdev->family == CHIP_R300) ||
+				   (rdev->family == CHIP_R350)) {
+				tmp |= (RADEON_SCLK_FORCE_HDP |
+					RADEON_SCLK_FORCE_DISP1 |
+					RADEON_SCLK_FORCE_DISP2 |
+					RADEON_SCLK_FORCE_TOP |
+					RADEON_SCLK_FORCE_IDCT |
+					RADEON_SCLK_FORCE_VIP);
+			}
+			WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+
+			udelay(16000);
+
+			if ((rdev->family == CHIP_R300) ||
+			    (rdev->family == CHIP_R350)) {
+				tmp = RREG32_PLL(R300_SCLK_CNTL2);
+				tmp |= (R300_SCLK_FORCE_TCL |
+					R300_SCLK_FORCE_GA |
+					R300_SCLK_FORCE_CBA);
+				WREG32_PLL(R300_SCLK_CNTL2, tmp);
+				udelay(16000);
+			}
+
+			if (rdev->flags & RADEON_IS_IGP) {
+				tmp = RREG32_PLL(RADEON_MCLK_CNTL);
+				tmp &= ~(RADEON_FORCEON_MCLKA |
+					 RADEON_FORCEON_YCLKA);
+				WREG32_PLL(RADEON_MCLK_CNTL, tmp);
+				udelay(16000);
+			}
+
+			if ((rdev->family == CHIP_RV200) ||
+			    (rdev->family == CHIP_RV250) ||
+			    (rdev->family == CHIP_RV280)) {
+				tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
+				tmp |= RADEON_SCLK_MORE_FORCEON;
+				WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
+				udelay(16000);
+			}
+
+			tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+			tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
+				 RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+				 RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+				 RADEON_PIXCLK_GV_ALWAYS_ONb |
+				 RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
+				 RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+				 RADEON_PIXCLK_TMDS_ALWAYS_ONb);
+
+			WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
+			udelay(16000);
+
+			tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+			tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
+				 RADEON_PIXCLK_DAC_ALWAYS_ONb);
+			WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
+		}
+	}
+}
+
+static void radeon_apply_clock_quirks(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	/* XXX make sure engine is idle */
+
+	if (rdev->family < CHIP_RS600) {
+		tmp = RREG32_PLL(RADEON_SCLK_CNTL);
+		if (ASIC_IS_R300(rdev) || ASIC_IS_RV100(rdev))
+			tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP;
+		if ((rdev->family == CHIP_RV250)
+		    || (rdev->family == CHIP_RV280))
+			tmp |=
+			    RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2;
+		if ((rdev->family == CHIP_RV350)
+		    || (rdev->family == CHIP_RV380))
+			tmp |= R300_SCLK_FORCE_VAP;
+		if (rdev->family == CHIP_R420)
+			tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX;
+		WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+	} else if (rdev->family < CHIP_R600) {
+		tmp = RREG32_PLL(AVIVO_CP_DYN_CNTL);
+		tmp |= AVIVO_CP_FORCEON;
+		WREG32_PLL(AVIVO_CP_DYN_CNTL, tmp);
+
+		tmp = RREG32_PLL(AVIVO_E2_DYN_CNTL);
+		tmp |= AVIVO_E2_FORCEON;
+		WREG32_PLL(AVIVO_E2_DYN_CNTL, tmp);
+
+		tmp = RREG32_PLL(AVIVO_IDCT_DYN_CNTL);
+		tmp |= AVIVO_IDCT_FORCEON;
+		WREG32_PLL(AVIVO_IDCT_DYN_CNTL, tmp);
+	}
+}
+
+int radeon_static_clocks_init(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	/* XXX make sure engine is idle */
+
+	if (radeon_dynclks != -1) {
+		if (radeon_dynclks)
+			radeon_set_clock_gating(rdev, 1);
+	}
+	radeon_apply_clock_quirks(rdev);
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_combios.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_combios.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_combios.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_combios.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2480 @@
+/*
+ * Copyright 2004 ATI Technologies Inc., Markham, Ontario
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+#ifdef CONFIG_PPC_PMAC
+/* not sure which of these are needed */
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif /* CONFIG_PPC_PMAC */
+
+/* from radeon_encoder.c */
+extern uint32_t
+radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device,
+		      uint8_t dac);
+extern void radeon_link_encoder_connector(struct drm_device *dev);
+
+/* from radeon_connector.c */
+extern void
+radeon_add_legacy_connector(struct drm_device *dev,
+			    uint32_t connector_id,
+			    uint32_t supported_device,
+			    int connector_type,
+			    struct radeon_i2c_bus_rec *i2c_bus);
+
+/* from radeon_legacy_encoder.c */
+extern void
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id,
+			  uint32_t supported_device);
+
+/* old legacy ATI BIOS routines */
+
+/* COMBIOS table offsets */
+enum radeon_combios_table_offset {
+	/* absolute offset tables */
+	COMBIOS_ASIC_INIT_1_TABLE,
+	COMBIOS_BIOS_SUPPORT_TABLE,
+	COMBIOS_DAC_PROGRAMMING_TABLE,
+	COMBIOS_MAX_COLOR_DEPTH_TABLE,
+	COMBIOS_CRTC_INFO_TABLE,
+	COMBIOS_PLL_INFO_TABLE,
+	COMBIOS_TV_INFO_TABLE,
+	COMBIOS_DFP_INFO_TABLE,
+	COMBIOS_HW_CONFIG_INFO_TABLE,
+	COMBIOS_MULTIMEDIA_INFO_TABLE,
+	COMBIOS_TV_STD_PATCH_TABLE,
+	COMBIOS_LCD_INFO_TABLE,
+	COMBIOS_MOBILE_INFO_TABLE,
+	COMBIOS_PLL_INIT_TABLE,
+	COMBIOS_MEM_CONFIG_TABLE,
+	COMBIOS_SAVE_MASK_TABLE,
+	COMBIOS_HARDCODED_EDID_TABLE,
+	COMBIOS_ASIC_INIT_2_TABLE,
+	COMBIOS_CONNECTOR_INFO_TABLE,
+	COMBIOS_DYN_CLK_1_TABLE,
+	COMBIOS_RESERVED_MEM_TABLE,
+	COMBIOS_EXT_TMDS_INFO_TABLE,
+	COMBIOS_MEM_CLK_INFO_TABLE,
+	COMBIOS_EXT_DAC_INFO_TABLE,
+	COMBIOS_MISC_INFO_TABLE,
+	COMBIOS_CRT_INFO_TABLE,
+	COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE,
+	COMBIOS_COMPONENT_VIDEO_INFO_TABLE,
+	COMBIOS_FAN_SPEED_INFO_TABLE,
+	COMBIOS_OVERDRIVE_INFO_TABLE,
+	COMBIOS_OEM_INFO_TABLE,
+	COMBIOS_DYN_CLK_2_TABLE,
+	COMBIOS_POWER_CONNECTOR_INFO_TABLE,
+	COMBIOS_I2C_INFO_TABLE,
+	/* relative offset tables */
+	COMBIOS_ASIC_INIT_3_TABLE,	/* offset from misc info */
+	COMBIOS_ASIC_INIT_4_TABLE,	/* offset from misc info */
+	COMBIOS_DETECTED_MEM_TABLE,	/* offset from misc info */
+	COMBIOS_ASIC_INIT_5_TABLE,	/* offset from misc info */
+	COMBIOS_RAM_RESET_TABLE,	/* offset from mem config */
+	COMBIOS_POWERPLAY_INFO_TABLE,	/* offset from mobile info */
+	COMBIOS_GPIO_INFO_TABLE,	/* offset from mobile info */
+	COMBIOS_LCD_DDC_INFO_TABLE,	/* offset from mobile info */
+	COMBIOS_TMDS_POWER_TABLE,	/* offset from mobile info */
+	COMBIOS_TMDS_POWER_ON_TABLE,	/* offset from tmds power */
+	COMBIOS_TMDS_POWER_OFF_TABLE,	/* offset from tmds power */
+};
+
+enum radeon_combios_ddc {
+	DDC_NONE_DETECTED,
+	DDC_MONID,
+	DDC_DVI,
+	DDC_VGA,
+	DDC_CRT2,
+	DDC_LCD,
+	DDC_GPIO,
+};
+
+enum radeon_combios_connector {
+	CONNECTOR_NONE_LEGACY,
+	CONNECTOR_PROPRIETARY_LEGACY,
+	CONNECTOR_CRT_LEGACY,
+	CONNECTOR_DVI_I_LEGACY,
+	CONNECTOR_DVI_D_LEGACY,
+	CONNECTOR_CTV_LEGACY,
+	CONNECTOR_STV_LEGACY,
+	CONNECTOR_UNSUPPORTED_LEGACY
+};
+
+const int legacy_connector_convert[] = {
+	DRM_MODE_CONNECTOR_Unknown,
+	DRM_MODE_CONNECTOR_DVID,
+	DRM_MODE_CONNECTOR_VGA,
+	DRM_MODE_CONNECTOR_DVII,
+	DRM_MODE_CONNECTOR_DVID,
+	DRM_MODE_CONNECTOR_Composite,
+	DRM_MODE_CONNECTOR_SVIDEO,
+	DRM_MODE_CONNECTOR_Unknown,
+};
+
+static uint16_t combios_get_table_offset(struct drm_device *dev,
+					 enum radeon_combios_table_offset table)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	int rev;
+	uint16_t offset = 0, check_offset;
+
+	switch (table) {
+		/* absolute offset tables */
+	case COMBIOS_ASIC_INIT_1_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0xc);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_BIOS_SUPPORT_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x14);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_DAC_PROGRAMMING_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x2a);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_MAX_COLOR_DEPTH_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x2c);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_CRTC_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x2e);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_PLL_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x30);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_TV_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x32);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_DFP_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x34);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_HW_CONFIG_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x36);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_MULTIMEDIA_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x38);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_TV_STD_PATCH_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x3e);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_LCD_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x40);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_MOBILE_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x42);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_PLL_INIT_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x46);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_MEM_CONFIG_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x48);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_SAVE_MASK_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x4a);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_HARDCODED_EDID_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x4c);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_ASIC_INIT_2_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x4e);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_CONNECTOR_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x50);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_DYN_CLK_1_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x52);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_RESERVED_MEM_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x54);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_EXT_TMDS_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x58);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_MEM_CLK_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x5a);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_EXT_DAC_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x5c);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_MISC_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x5e);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_CRT_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x60);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x62);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_COMPONENT_VIDEO_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x64);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_FAN_SPEED_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x66);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_OVERDRIVE_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x68);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_OEM_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x6a);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_DYN_CLK_2_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x6c);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_POWER_CONNECTOR_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x6e);
+		if (check_offset)
+			offset = check_offset;
+		break;
+	case COMBIOS_I2C_INFO_TABLE:
+		check_offset = RBIOS16(rdev->bios_header_start + 0x70);
+		if (check_offset)
+			offset = check_offset;
+		break;
+		/* relative offset tables */
+	case COMBIOS_ASIC_INIT_3_TABLE:	/* offset from misc info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
+		if (check_offset) {
+			rev = RBIOS8(check_offset);
+			if (rev > 0) {
+				check_offset = RBIOS16(check_offset + 0x3);
+				if (check_offset)
+					offset = check_offset;
+			}
+		}
+		break;
+	case COMBIOS_ASIC_INIT_4_TABLE:	/* offset from misc info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
+		if (check_offset) {
+			rev = RBIOS8(check_offset);
+			if (rev > 0) {
+				check_offset = RBIOS16(check_offset + 0x5);
+				if (check_offset)
+					offset = check_offset;
+			}
+		}
+		break;
+	case COMBIOS_DETECTED_MEM_TABLE:	/* offset from misc info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
+		if (check_offset) {
+			rev = RBIOS8(check_offset);
+			if (rev > 0) {
+				check_offset = RBIOS16(check_offset + 0x7);
+				if (check_offset)
+					offset = check_offset;
+			}
+		}
+		break;
+	case COMBIOS_ASIC_INIT_5_TABLE:	/* offset from misc info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE);
+		if (check_offset) {
+			rev = RBIOS8(check_offset);
+			if (rev == 2) {
+				check_offset = RBIOS16(check_offset + 0x9);
+				if (check_offset)
+					offset = check_offset;
+			}
+		}
+		break;
+	case COMBIOS_RAM_RESET_TABLE:	/* offset from mem config */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE);
+		if (check_offset) {
+			while (RBIOS8(check_offset++));
+			check_offset += 2;
+			if (check_offset)
+				offset = check_offset;
+		}
+		break;
+	case COMBIOS_POWERPLAY_INFO_TABLE:	/* offset from mobile info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
+		if (check_offset) {
+			check_offset = RBIOS16(check_offset + 0x11);
+			if (check_offset)
+				offset = check_offset;
+		}
+		break;
+	case COMBIOS_GPIO_INFO_TABLE:	/* offset from mobile info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
+		if (check_offset) {
+			check_offset = RBIOS16(check_offset + 0x13);
+			if (check_offset)
+				offset = check_offset;
+		}
+		break;
+	case COMBIOS_LCD_DDC_INFO_TABLE:	/* offset from mobile info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
+		if (check_offset) {
+			check_offset = RBIOS16(check_offset + 0x15);
+			if (check_offset)
+				offset = check_offset;
+		}
+		break;
+	case COMBIOS_TMDS_POWER_TABLE:	/* offset from mobile info */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE);
+		if (check_offset) {
+			check_offset = RBIOS16(check_offset + 0x17);
+			if (check_offset)
+				offset = check_offset;
+		}
+		break;
+	case COMBIOS_TMDS_POWER_ON_TABLE:	/* offset from tmds power */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE);
+		if (check_offset) {
+			check_offset = RBIOS16(check_offset + 0x2);
+			if (check_offset)
+				offset = check_offset;
+		}
+		break;
+	case COMBIOS_TMDS_POWER_OFF_TABLE:	/* offset from tmds power */
+		check_offset =
+		    combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE);
+		if (check_offset) {
+			check_offset = RBIOS16(check_offset + 0x4);
+			if (check_offset)
+				offset = check_offset;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return offset;
+
+}
+
+struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
+{
+	struct radeon_i2c_bus_rec i2c;
+
+	i2c.mask_clk_mask = RADEON_GPIO_EN_1;
+	i2c.mask_data_mask = RADEON_GPIO_EN_0;
+	i2c.a_clk_mask = RADEON_GPIO_A_1;
+	i2c.a_data_mask = RADEON_GPIO_A_0;
+	i2c.put_clk_mask = RADEON_GPIO_EN_1;
+	i2c.put_data_mask = RADEON_GPIO_EN_0;
+	i2c.get_clk_mask = RADEON_GPIO_Y_1;
+	i2c.get_data_mask = RADEON_GPIO_Y_0;
+	if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
+	    (ddc_line == RADEON_MDGPIO_EN_REG)) {
+		i2c.mask_clk_reg = ddc_line;
+		i2c.mask_data_reg = ddc_line;
+		i2c.a_clk_reg = ddc_line;
+		i2c.a_data_reg = ddc_line;
+		i2c.put_clk_reg = ddc_line;
+		i2c.put_data_reg = ddc_line;
+		i2c.get_clk_reg = ddc_line + 4;
+		i2c.get_data_reg = ddc_line + 4;
+	} else {
+		i2c.mask_clk_reg = ddc_line;
+		i2c.mask_data_reg = ddc_line;
+		i2c.a_clk_reg = ddc_line;
+		i2c.a_data_reg = ddc_line;
+		i2c.put_clk_reg = ddc_line;
+		i2c.put_data_reg = ddc_line;
+		i2c.get_clk_reg = ddc_line;
+		i2c.get_data_reg = ddc_line;
+	}
+
+	if (ddc_line)
+		i2c.valid = true;
+	else
+		i2c.valid = false;
+
+	return i2c;
+}
+
+bool radeon_combios_get_clock_info(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t pll_info;
+	struct radeon_pll *p1pll = &rdev->clock.p1pll;
+	struct radeon_pll *p2pll = &rdev->clock.p2pll;
+	struct radeon_pll *spll = &rdev->clock.spll;
+	struct radeon_pll *mpll = &rdev->clock.mpll;
+	int8_t rev;
+	uint16_t sclk, mclk;
+
+	if (rdev->bios == NULL)
+		return NULL;
+
+	pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
+	if (pll_info) {
+		rev = RBIOS8(pll_info);
+
+		/* pixel clocks */
+		p1pll->reference_freq = RBIOS16(pll_info + 0xe);
+		p1pll->reference_div = RBIOS16(pll_info + 0x10);
+		p1pll->pll_out_min = RBIOS32(pll_info + 0x12);
+		p1pll->pll_out_max = RBIOS32(pll_info + 0x16);
+
+		if (rev > 9) {
+			p1pll->pll_in_min = RBIOS32(pll_info + 0x36);
+			p1pll->pll_in_max = RBIOS32(pll_info + 0x3a);
+		} else {
+			p1pll->pll_in_min = 40;
+			p1pll->pll_in_max = 500;
+		}
+		*p2pll = *p1pll;
+
+		/* system clock */
+		spll->reference_freq = RBIOS16(pll_info + 0x1a);
+		spll->reference_div = RBIOS16(pll_info + 0x1c);
+		spll->pll_out_min = RBIOS32(pll_info + 0x1e);
+		spll->pll_out_max = RBIOS32(pll_info + 0x22);
+
+		if (rev > 10) {
+			spll->pll_in_min = RBIOS32(pll_info + 0x48);
+			spll->pll_in_max = RBIOS32(pll_info + 0x4c);
+		} else {
+			/* ??? */
+			spll->pll_in_min = 40;
+			spll->pll_in_max = 500;
+		}
+
+		/* memory clock */
+		mpll->reference_freq = RBIOS16(pll_info + 0x26);
+		mpll->reference_div = RBIOS16(pll_info + 0x28);
+		mpll->pll_out_min = RBIOS32(pll_info + 0x2a);
+		mpll->pll_out_max = RBIOS32(pll_info + 0x2e);
+
+		if (rev > 10) {
+			mpll->pll_in_min = RBIOS32(pll_info + 0x5a);
+			mpll->pll_in_max = RBIOS32(pll_info + 0x5e);
+		} else {
+			/* ??? */
+			mpll->pll_in_min = 40;
+			mpll->pll_in_max = 500;
+		}
+
+		/* default sclk/mclk */
+		sclk = RBIOS16(pll_info + 0xa);
+		mclk = RBIOS16(pll_info + 0x8);
+		if (sclk == 0)
+			sclk = 200 * 100;
+		if (mclk == 0)
+			mclk = 200 * 100;
+
+		rdev->clock.default_sclk = sclk;
+		rdev->clock.default_mclk = mclk;
+
+		return true;
+	}
+	return false;
+}
+
+struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
+								       radeon_encoder
+								       *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t dac_info;
+	uint8_t rev, bg, dac;
+	struct radeon_encoder_primary_dac *p_dac = NULL;
+
+	if (rdev->bios == NULL)
+		return NULL;
+
+	/* check CRT table */
+	dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
+	if (dac_info) {
+		p_dac =
+		    kzalloc(sizeof(struct radeon_encoder_primary_dac),
+			    GFP_KERNEL);
+
+		if (!p_dac)
+			return NULL;
+
+		rev = RBIOS8(dac_info) & 0x3;
+		if (rev < 2) {
+			bg = RBIOS8(dac_info + 0x2) & 0xf;
+			dac = (RBIOS8(dac_info + 0x2) >> 4) & 0xf;
+			p_dac->ps2_pdac_adj = (bg << 8) | (dac);
+		} else {
+			bg = RBIOS8(dac_info + 0x2) & 0xf;
+			dac = RBIOS8(dac_info + 0x3) & 0xf;
+			p_dac->ps2_pdac_adj = (bg << 8) | (dac);
+		}
+
+	}
+
+	return p_dac;
+}
+
+static enum radeon_tv_std
+radeon_combios_get_tv_info(struct radeon_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t tv_info;
+	enum radeon_tv_std tv_std = TV_STD_NTSC;
+
+	tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
+	if (tv_info) {
+		if (RBIOS8(tv_info + 6) == 'T') {
+			switch (RBIOS8(tv_info + 7) & 0xf) {
+			case 1:
+				tv_std = TV_STD_NTSC;
+				DRM_INFO("Default TV standard: NTSC\n");
+				break;
+			case 2:
+				tv_std = TV_STD_PAL;
+				DRM_INFO("Default TV standard: PAL\n");
+				break;
+			case 3:
+				tv_std = TV_STD_PAL_M;
+				DRM_INFO("Default TV standard: PAL-M\n");
+				break;
+			case 4:
+				tv_std = TV_STD_PAL_60;
+				DRM_INFO("Default TV standard: PAL-60\n");
+				break;
+			case 5:
+				tv_std = TV_STD_NTSC_J;
+				DRM_INFO("Default TV standard: NTSC-J\n");
+				break;
+			case 6:
+				tv_std = TV_STD_SCART_PAL;
+				DRM_INFO("Default TV standard: SCART-PAL\n");
+				break;
+			default:
+				tv_std = TV_STD_NTSC;
+				DRM_INFO
+				    ("Unknown TV standard; defaulting to NTSC\n");
+				break;
+			}
+
+			switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) {
+			case 0:
+				DRM_INFO("29.498928713 MHz TV ref clk\n");
+				break;
+			case 1:
+				DRM_INFO("28.636360000 MHz TV ref clk\n");
+				break;
+			case 2:
+				DRM_INFO("14.318180000 MHz TV ref clk\n");
+				break;
+			case 3:
+				DRM_INFO("27.000000000 MHz TV ref clk\n");
+				break;
+			default:
+				break;
+			}
+		}
+	}
+	return tv_std;
+}
+
+static const uint32_t default_tvdac_adj[CHIP_LAST] = {
+	0x00000000,		/* r100  */
+	0x00280000,		/* rv100 */
+	0x00000000,		/* rs100 */
+	0x00880000,		/* rv200 */
+	0x00000000,		/* rs200 */
+	0x00000000,		/* r200  */
+	0x00770000,		/* rv250 */
+	0x00290000,		/* rs300 */
+	0x00560000,		/* rv280 */
+	0x00780000,		/* r300  */
+	0x00770000,		/* r350  */
+	0x00780000,		/* rv350 */
+	0x00780000,		/* rv380 */
+	0x01080000,		/* r420  */
+	0x01080000,		/* r423  */
+	0x01080000,		/* rv410 */
+	0x00780000,		/* rs400 */
+	0x00780000,		/* rs480 */
+};
+
+static void radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev,
+						     struct radeon_encoder_tv_dac *tv_dac)
+{
+	tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family];
+	if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250))
+		tv_dac->ps2_tvdac_adj = 0x00880000;
+	tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
+	tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
+	return;
+}
+
+struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
+							     radeon_encoder
+							     *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t dac_info;
+	uint8_t rev, bg, dac;
+	struct radeon_encoder_tv_dac *tv_dac = NULL;
+	int found = 0;
+
+	tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
+	if (!tv_dac)
+		return NULL;
+
+	if (rdev->bios == NULL)
+		goto out;
+
+	/* first check TV table */
+	dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
+	if (dac_info) {
+		rev = RBIOS8(dac_info + 0x3);
+		if (rev > 4) {
+			bg = RBIOS8(dac_info + 0xc) & 0xf;
+			dac = RBIOS8(dac_info + 0xd) & 0xf;
+			tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
+
+			bg = RBIOS8(dac_info + 0xe) & 0xf;
+			dac = RBIOS8(dac_info + 0xf) & 0xf;
+			tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
+
+			bg = RBIOS8(dac_info + 0x10) & 0xf;
+			dac = RBIOS8(dac_info + 0x11) & 0xf;
+			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
+			found = 1;
+		} else if (rev > 1) {
+			bg = RBIOS8(dac_info + 0xc) & 0xf;
+			dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf;
+			tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20);
+
+			bg = RBIOS8(dac_info + 0xd) & 0xf;
+			dac = (RBIOS8(dac_info + 0xd) >> 4) & 0xf;
+			tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20);
+
+			bg = RBIOS8(dac_info + 0xe) & 0xf;
+			dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf;
+			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
+			found = 1;
+		}
+		tv_dac->tv_std = radeon_combios_get_tv_info(encoder);
+	}
+	if (!found) {
+		/* then check CRT table */
+		dac_info =
+		    combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
+		if (dac_info) {
+			rev = RBIOS8(dac_info) & 0x3;
+			if (rev < 2) {
+				bg = RBIOS8(dac_info + 0x3) & 0xf;
+				dac = (RBIOS8(dac_info + 0x3) >> 4) & 0xf;
+				tv_dac->ps2_tvdac_adj =
+				    (bg << 16) | (dac << 20);
+				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
+				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
+				found = 1;
+			} else {
+				bg = RBIOS8(dac_info + 0x4) & 0xf;
+				dac = RBIOS8(dac_info + 0x5) & 0xf;
+				tv_dac->ps2_tvdac_adj =
+				    (bg << 16) | (dac << 20);
+				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
+				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
+				found = 1;
+			}
+		} else {
+			DRM_INFO("No TV DAC info found in BIOS\n");
+		}
+	}
+
+out:
+	if (!found) /* fallback to defaults */
+		radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac);
+
+	return tv_dac;
+}
+
+static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct
+									 radeon_device
+									 *rdev)
+{
+	struct radeon_encoder_lvds *lvds = NULL;
+	uint32_t fp_vert_stretch, fp_horz_stretch;
+	uint32_t ppll_div_sel, ppll_val;
+	uint32_t lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
+
+	lvds = kzalloc(sizeof(struct radeon_encoder_lvds), GFP_KERNEL);
+
+	if (!lvds)
+		return NULL;
+
+	fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH);
+	fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH);
+
+	/* These should be fail-safe defaults, fingers crossed */
+	lvds->panel_pwr_delay = 200;
+	lvds->panel_vcc_delay = 2000;
+
+	lvds->lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	lvds->panel_digon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) & 0xf;
+	lvds->panel_blon_delay = (lvds_ss_gen_cntl >> RADEON_LVDS_PWRSEQ_DELAY2_SHIFT) & 0xf;
+
+	if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE)
+		lvds->native_mode.panel_yres =
+		    ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >>
+		     RADEON_VERT_PANEL_SHIFT) + 1;
+	else
+		lvds->native_mode.panel_yres =
+		    (RREG32(RADEON_CRTC_V_TOTAL_DISP) >> 16) + 1;
+
+	if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE)
+		lvds->native_mode.panel_xres =
+		    (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >>
+		      RADEON_HORZ_PANEL_SHIFT) + 1) * 8;
+	else
+		lvds->native_mode.panel_xres =
+		    ((RREG32(RADEON_CRTC_H_TOTAL_DISP) >> 16) + 1) * 8;
+
+	if ((lvds->native_mode.panel_xres < 640) ||
+	    (lvds->native_mode.panel_yres < 480)) {
+		lvds->native_mode.panel_xres = 640;
+		lvds->native_mode.panel_yres = 480;
+	}
+
+	ppll_div_sel = RREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3;
+	ppll_val = RREG32_PLL(RADEON_PPLL_DIV_0 + ppll_div_sel);
+	if ((ppll_val & 0x000707ff) == 0x1bb)
+		lvds->use_bios_dividers = false;
+	else {
+		lvds->panel_ref_divider =
+		    RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
+		lvds->panel_post_divider = (ppll_val >> 16) & 0x7;
+		lvds->panel_fb_divider = ppll_val & 0x7ff;
+
+		if ((lvds->panel_ref_divider != 0) &&
+		    (lvds->panel_fb_divider > 3))
+			lvds->use_bios_dividers = true;
+	}
+	lvds->panel_vcc_delay = 200;
+
+	DRM_INFO("Panel info derived from registers\n");
+	DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.panel_xres,
+		 lvds->native_mode.panel_yres);
+
+	return lvds;
+}
+
+struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
+							 *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t lcd_info;
+	uint32_t panel_setup;
+	char stmp[30];
+	int tmp, i;
+	struct radeon_encoder_lvds *lvds = NULL;
+
+	if (rdev->bios == NULL)
+		return radeon_legacy_get_lvds_info_from_regs(rdev);
+
+	lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
+
+	if (lcd_info) {
+		lvds = kzalloc(sizeof(struct radeon_encoder_lvds), GFP_KERNEL);
+
+		if (!lvds)
+			return NULL;
+
+		for (i = 0; i < 24; i++)
+			stmp[i] = RBIOS8(lcd_info + i + 1);
+		stmp[24] = 0;
+
+		DRM_INFO("Panel ID String: %s\n", stmp);
+
+		lvds->native_mode.panel_xres = RBIOS16(lcd_info + 0x19);
+		lvds->native_mode.panel_yres = RBIOS16(lcd_info + 0x1b);
+
+		DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.panel_xres,
+			 lvds->native_mode.panel_yres);
+
+		lvds->panel_vcc_delay = RBIOS16(lcd_info + 0x2c);
+		if (lvds->panel_vcc_delay > 2000 || lvds->panel_vcc_delay < 0)
+			lvds->panel_vcc_delay = 2000;
+
+		lvds->panel_pwr_delay = RBIOS8(lcd_info + 0x24);
+		lvds->panel_digon_delay = RBIOS16(lcd_info + 0x38) & 0xf;
+		lvds->panel_blon_delay = (RBIOS16(lcd_info + 0x38) >> 4) & 0xf;
+
+		lvds->panel_ref_divider = RBIOS16(lcd_info + 0x2e);
+		lvds->panel_post_divider = RBIOS8(lcd_info + 0x30);
+		lvds->panel_fb_divider = RBIOS16(lcd_info + 0x31);
+		if ((lvds->panel_ref_divider != 0) &&
+		    (lvds->panel_fb_divider > 3))
+			lvds->use_bios_dividers = true;
+
+		panel_setup = RBIOS32(lcd_info + 0x39);
+		lvds->lvds_gen_cntl = 0xff00;
+		if (panel_setup & 0x1)
+			lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_FORMAT;
+
+		if ((panel_setup >> 4) & 0x1)
+			lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_TYPE;
+
+		switch ((panel_setup >> 8) & 0x7) {
+		case 0:
+			lvds->lvds_gen_cntl |= RADEON_LVDS_NO_FM;
+			break;
+		case 1:
+			lvds->lvds_gen_cntl |= RADEON_LVDS_2_GREY;
+			break;
+		case 2:
+			lvds->lvds_gen_cntl |= RADEON_LVDS_4_GREY;
+			break;
+		default:
+			break;
+		}
+
+		if ((panel_setup >> 16) & 0x1)
+			lvds->lvds_gen_cntl |= RADEON_LVDS_FP_POL_LOW;
+
+		if ((panel_setup >> 17) & 0x1)
+			lvds->lvds_gen_cntl |= RADEON_LVDS_LP_POL_LOW;
+
+		if ((panel_setup >> 18) & 0x1)
+			lvds->lvds_gen_cntl |= RADEON_LVDS_DTM_POL_LOW;
+
+		if ((panel_setup >> 23) & 0x1)
+			lvds->lvds_gen_cntl |= RADEON_LVDS_BL_CLK_SEL;
+
+		lvds->lvds_gen_cntl |= (panel_setup & 0xf0000000);
+
+		for (i = 0; i < 32; i++) {
+			tmp = RBIOS16(lcd_info + 64 + i * 2);
+			if (tmp == 0)
+				break;
+
+			if ((RBIOS16(tmp) == lvds->native_mode.panel_xres) &&
+			    (RBIOS16(tmp + 2) ==
+			     lvds->native_mode.panel_yres)) {
+				lvds->native_mode.hblank =
+				    (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8;
+				lvds->native_mode.hoverplus =
+				    (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) -
+				     1) * 8;
+				lvds->native_mode.hsync_width =
+				    RBIOS8(tmp + 23) * 8;
+
+				lvds->native_mode.vblank = (RBIOS16(tmp + 24) -
+							    RBIOS16(tmp + 26));
+				lvds->native_mode.voverplus =
+				    ((RBIOS16(tmp + 28) & 0x7ff) -
+				     RBIOS16(tmp + 26));
+				lvds->native_mode.vsync_width =
+				    ((RBIOS16(tmp + 28) & 0xf800) >> 11);
+				lvds->native_mode.dotclock =
+				    RBIOS16(tmp + 9) * 10;
+				lvds->native_mode.flags = 0;
+			}
+		}
+		encoder->native_mode = lvds->native_mode;
+	} else {
+		DRM_INFO("No panel info found in BIOS\n");
+		return radeon_legacy_get_lvds_info_from_regs(rdev);
+	}
+	return lvds;
+}
+
+static const struct radeon_tmds_pll default_tmds_pll[CHIP_LAST][4] = {
+	{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_R100  */
+	{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_RV100 */
+	{{0, 0}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_RS100 */
+	{{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_RV200 */
+	{{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_RS200 */
+	{{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}},	/* CHIP_R200  */
+	{{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}},	/* CHIP_RV250 */
+	{{0, 0}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_RS300 */
+	{{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}},	/* CHIP_RV280 */
+	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R300  */
+	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R350  */
+	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RV350 */
+	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RV380 */
+	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R420  */
+	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R423  */
+	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_RV410 */
+	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RS400 */
+	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RS480 */
+};
+
+static struct radeon_encoder_int_tmds
+    *radeon_legacy_get_tmds_info_from_table(struct radeon_device *rdev)
+{
+	int i;
+	struct radeon_encoder_int_tmds *tmds = NULL;
+
+	tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
+
+	if (!tmds)
+		return NULL;
+
+	for (i = 0; i < 4; i++) {
+		tmds->tmds_pll[i].value =
+		    default_tmds_pll[rdev->family][i].value;
+		tmds->tmds_pll[i].freq = default_tmds_pll[rdev->family][i].freq;
+	}
+
+	return tmds;
+}
+
+struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct
+							     radeon_encoder
+							     *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t tmds_info;
+	int i, n;
+	uint8_t ver;
+	struct radeon_encoder_int_tmds *tmds = NULL;
+
+	if (rdev->bios == NULL)
+		return radeon_legacy_get_tmds_info_from_table(rdev);
+
+	tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
+
+	if (tmds_info) {
+		tmds =
+		    kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
+
+		if (!tmds)
+			return NULL;
+
+		ver = RBIOS8(tmds_info);
+		DRM_INFO("DFP table revision: %d\n", ver);
+		if (ver == 3) {
+			n = RBIOS8(tmds_info + 5) + 1;
+			if (n > 4)
+				n = 4;
+			for (i = 0; i < n; i++) {
+				tmds->tmds_pll[i].value =
+				    RBIOS32(tmds_info + i * 10 + 0x08);
+				tmds->tmds_pll[i].freq =
+				    RBIOS16(tmds_info + i * 10 + 0x10);
+				DRM_DEBUG("TMDS PLL From COMBIOS %u %x\n",
+					  tmds->tmds_pll[i].freq,
+					  tmds->tmds_pll[i].value);
+			}
+		} else if (ver == 4) {
+			int stride = 0;
+			n = RBIOS8(tmds_info + 5) + 1;
+			if (n > 4)
+				n = 4;
+			for (i = 0; i < n; i++) {
+				tmds->tmds_pll[i].value =
+				    RBIOS32(tmds_info + stride + 0x08);
+				tmds->tmds_pll[i].freq =
+				    RBIOS16(tmds_info + stride + 0x10);
+				if (i == 0)
+					stride += 10;
+				else
+					stride += 6;
+				DRM_DEBUG("TMDS PLL From COMBIOS %u %x\n",
+					  tmds->tmds_pll[i].freq,
+					  tmds->tmds_pll[i].value);
+			}
+		}
+	} else
+		DRM_INFO("No TMDS info found in BIOS\n");
+	return tmds;
+}
+
+void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t ext_tmds_info;
+	uint8_t ver;
+
+	if (rdev->bios == NULL)
+		return;
+
+	ext_tmds_info =
+	    combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
+	if (ext_tmds_info) {
+		ver = RBIOS8(ext_tmds_info);
+		DRM_INFO("External TMDS Table revision: %d\n", ver);
+		// TODO
+	}
+}
+
+bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_i2c_bus_rec ddc_i2c;
+
+	rdev->mode_info.connector_table = radeon_connector_table;
+	if (rdev->mode_info.connector_table == CT_NONE) {
+#ifdef CONFIG_PPC_PMAC
+		if (machine_is_compatible("PowerBook3,3")) {
+			/* powerbook with VGA */
+			rdev->mode_info.connector_table = CT_POWERBOOK_VGA;
+		} else if (machine_is_compatible("PowerBook3,4") ||
+			   machine_is_compatible("PowerBook3,5")) {
+			/* powerbook with internal tmds */
+			rdev->mode_info.connector_table = CT_POWERBOOK_INTERNAL;
+		} else if (machine_is_compatible("PowerBook5,1") ||
+			   machine_is_compatible("PowerBook5,2") ||
+			   machine_is_compatible("PowerBook5,3") ||
+			   machine_is_compatible("PowerBook5,4") ||
+			   machine_is_compatible("PowerBook5,5")) {
+			/* powerbook with external single link tmds (sil164) */
+			rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL;
+		} else if (machine_is_compatible("PowerBook5,6")) {
+			/* powerbook with external dual or single link tmds */
+			rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL;
+		} else if (machine_is_compatible("PowerBook5,7") ||
+			   machine_is_compatible("PowerBook5,8") ||
+			   machine_is_compatible("PowerBook5,9")) {
+			/* PowerBook6,2 ? */
+			/* powerbook with external dual link tmds (sil1178?) */
+			rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL;
+		} else if (machine_is_compatible("PowerBook4,1") ||
+			   machine_is_compatible("PowerBook4,2") ||
+			   machine_is_compatible("PowerBook4,3") ||
+			   machine_is_compatible("PowerBook6,3") ||
+			   machine_is_compatible("PowerBook6,5") ||
+			   machine_is_compatible("PowerBook6,7")) {
+			/* ibook */
+			rdev->mode_info.connector_table = CT_IBOOK;
+		} else if (machine_is_compatible("PowerMac4,4")) {
+			/* emac */
+			rdev->mode_info.connector_table = CT_EMAC;
+		} else if (machine_is_compatible("PowerMac10,1")) {
+			/* mini with internal tmds */
+			rdev->mode_info.connector_table = CT_MINI_INTERNAL;
+		} else if (machine_is_compatible("PowerMac10,2")) {
+			/* mini with external tmds */
+			rdev->mode_info.connector_table = CT_MINI_EXTERNAL;
+		} else if (machine_is_compatible("PowerMac12,1")) {
+			/* PowerMac8,1 ? */
+			/* imac g5 isight */
+			rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT;
+		} else
+#endif /* CONFIG_PPC_PMAC */
+			rdev->mode_info.connector_table = CT_GENERIC;
+	}
+
+	switch (rdev->mode_info.connector_table) {
+	case CT_GENERIC:
+		DRM_INFO("Connector Table: %d (generic)\n",
+			 rdev->mode_info.connector_table);
+		/* these are the most common settings */
+		if (rdev->flags & RADEON_SINGLE_CRTC) {
+			/* VGA - primary dac */
+			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_CRT1_SUPPORT,
+									1),
+						  ATOM_DEVICE_CRT1_SUPPORT);
+			radeon_add_legacy_connector(dev, 0,
+						    ATOM_DEVICE_CRT1_SUPPORT,
+						    DRM_MODE_CONNECTOR_VGA,
+						    &ddc_i2c);
+		} else if (rdev->flags & RADEON_IS_MOBILITY) {
+			/* LVDS */
+			ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_LCD1_SUPPORT,
+									0),
+						  ATOM_DEVICE_LCD1_SUPPORT);
+			radeon_add_legacy_connector(dev, 0,
+						    ATOM_DEVICE_LCD1_SUPPORT,
+						    DRM_MODE_CONNECTOR_LVDS,
+						    &ddc_i2c);
+
+			/* VGA - primary dac */
+			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_CRT1_SUPPORT,
+									1),
+						  ATOM_DEVICE_CRT1_SUPPORT);
+			radeon_add_legacy_connector(dev, 1,
+						    ATOM_DEVICE_CRT1_SUPPORT,
+						    DRM_MODE_CONNECTOR_VGA,
+						    &ddc_i2c);
+		} else {
+			/* DVI-I - tv dac, int tmds */
+			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_DFP1_SUPPORT,
+									0),
+						  ATOM_DEVICE_DFP1_SUPPORT);
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_CRT2_SUPPORT,
+									2),
+						  ATOM_DEVICE_CRT2_SUPPORT);
+			radeon_add_legacy_connector(dev, 0,
+						    ATOM_DEVICE_DFP1_SUPPORT |
+						    ATOM_DEVICE_CRT2_SUPPORT,
+						    DRM_MODE_CONNECTOR_DVII,
+						    &ddc_i2c);
+
+			/* VGA - primary dac */
+			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_CRT1_SUPPORT,
+									1),
+						  ATOM_DEVICE_CRT1_SUPPORT);
+			radeon_add_legacy_connector(dev, 1,
+						    ATOM_DEVICE_CRT1_SUPPORT,
+						    DRM_MODE_CONNECTOR_VGA,
+						    &ddc_i2c);
+		}
+
+		if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
+			/* TV - tv dac */
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_TV1_SUPPORT,
+									2),
+						  ATOM_DEVICE_TV1_SUPPORT);
+			radeon_add_legacy_connector(dev, 2,
+						    ATOM_DEVICE_TV1_SUPPORT,
+						    DRM_MODE_CONNECTOR_SVIDEO,
+						    &ddc_i2c);
+		}
+		break;
+	case CT_IBOOK:
+		DRM_INFO("Connector Table: %d (ibook)\n",
+			 rdev->mode_info.connector_table);
+		/* LVDS */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_LCD1_SUPPORT,
+								0),
+					  ATOM_DEVICE_LCD1_SUPPORT);
+		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+		/* VGA - TV DAC */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT2_SUPPORT,
+								2),
+					  ATOM_DEVICE_CRT2_SUPPORT);
+		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	case CT_POWERBOOK_EXTERNAL:
+		DRM_INFO("Connector Table: %d (powerbook external tmds)\n",
+			 rdev->mode_info.connector_table);
+		/* LVDS */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_LCD1_SUPPORT,
+								0),
+					  ATOM_DEVICE_LCD1_SUPPORT);
+		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+		/* DVI-I - primary dac, ext tmds */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_DFP2_SUPPORT,
+								0),
+					  ATOM_DEVICE_DFP2_SUPPORT);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT1_SUPPORT,
+								1),
+					  ATOM_DEVICE_CRT1_SUPPORT);
+		radeon_add_legacy_connector(dev, 1,
+					    ATOM_DEVICE_DFP2_SUPPORT |
+					    ATOM_DEVICE_CRT1_SUPPORT,
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	case CT_POWERBOOK_INTERNAL:
+		DRM_INFO("Connector Table: %d (powerbook internal tmds)\n",
+			 rdev->mode_info.connector_table);
+		/* LVDS */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_LCD1_SUPPORT,
+								0),
+					  ATOM_DEVICE_LCD1_SUPPORT);
+		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+		/* DVI-I - primary dac, int tmds */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_DFP1_SUPPORT,
+								0),
+					  ATOM_DEVICE_DFP1_SUPPORT);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT1_SUPPORT,
+								1),
+					  ATOM_DEVICE_CRT1_SUPPORT);
+		radeon_add_legacy_connector(dev, 1,
+					    ATOM_DEVICE_DFP1_SUPPORT |
+					    ATOM_DEVICE_CRT1_SUPPORT,
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	case CT_POWERBOOK_VGA:
+		DRM_INFO("Connector Table: %d (powerbook vga)\n",
+			 rdev->mode_info.connector_table);
+		/* LVDS */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_LCD1_SUPPORT,
+								0),
+					  ATOM_DEVICE_LCD1_SUPPORT);
+		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
+					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c);
+		/* VGA - primary dac */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT1_SUPPORT,
+								1),
+					  ATOM_DEVICE_CRT1_SUPPORT);
+		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	case CT_MINI_EXTERNAL:
+		DRM_INFO("Connector Table: %d (mini external tmds)\n",
+			 rdev->mode_info.connector_table);
+		/* DVI-I - tv dac, ext tmds */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_DFP2_SUPPORT,
+								0),
+					  ATOM_DEVICE_DFP2_SUPPORT);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT2_SUPPORT,
+								2),
+					  ATOM_DEVICE_CRT2_SUPPORT);
+		radeon_add_legacy_connector(dev, 0,
+					    ATOM_DEVICE_DFP2_SUPPORT |
+					    ATOM_DEVICE_CRT2_SUPPORT,
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	case CT_MINI_INTERNAL:
+		DRM_INFO("Connector Table: %d (mini internal tmds)\n",
+			 rdev->mode_info.connector_table);
+		/* DVI-I - tv dac, int tmds */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_DFP1_SUPPORT,
+								0),
+					  ATOM_DEVICE_DFP1_SUPPORT);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT2_SUPPORT,
+								2),
+					  ATOM_DEVICE_CRT2_SUPPORT);
+		radeon_add_legacy_connector(dev, 0,
+					    ATOM_DEVICE_DFP1_SUPPORT |
+					    ATOM_DEVICE_CRT2_SUPPORT,
+					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	case CT_IMAC_G5_ISIGHT:
+		DRM_INFO("Connector Table: %d (imac g5 isight)\n",
+			 rdev->mode_info.connector_table);
+		/* DVI-D - int tmds */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_DFP1_SUPPORT,
+								0),
+					  ATOM_DEVICE_DFP1_SUPPORT);
+		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT,
+					    DRM_MODE_CONNECTOR_DVID, &ddc_i2c);
+		/* VGA - tv dac */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT2_SUPPORT,
+								2),
+					  ATOM_DEVICE_CRT2_SUPPORT);
+		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	case CT_EMAC:
+		DRM_INFO("Connector Table: %d (emac)\n",
+			 rdev->mode_info.connector_table);
+		/* VGA - primary dac */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT1_SUPPORT,
+								1),
+					  ATOM_DEVICE_CRT1_SUPPORT);
+		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+		/* VGA - tv dac */
+		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_CRT2_SUPPORT,
+								2),
+					  ATOM_DEVICE_CRT2_SUPPORT);
+		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
+					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c);
+		/* TV - TV DAC */
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_id(dev,
+								ATOM_DEVICE_TV1_SUPPORT,
+								2),
+					  ATOM_DEVICE_TV1_SUPPORT);
+		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
+					    DRM_MODE_CONNECTOR_SVIDEO,
+					    &ddc_i2c);
+		break;
+	default:
+		DRM_INFO("Connector table: %d (invalid)\n",
+			 rdev->mode_info.connector_table);
+		return false;
+	}
+
+	radeon_link_encoder_connector(dev);
+
+	return true;
+}
+
+static bool radeon_apply_legacy_quirks(struct drm_device *dev,
+				       int bios_index,
+				       enum radeon_combios_connector
+				       *legacy_connector,
+				       struct radeon_i2c_bus_rec *ddc_i2c)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	/* XPRESS DDC quirks */
+	if ((rdev->family == CHIP_RS400 ||
+	     rdev->family == CHIP_RS480) &&
+	    ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
+		*ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+	else if ((rdev->family == CHIP_RS400 ||
+		  rdev->family == CHIP_RS480) &&
+		 ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) {
+		ddc_i2c->valid = true;
+		ddc_i2c->mask_clk_mask = (0x20 << 8);
+		ddc_i2c->mask_data_mask = 0x80;
+		ddc_i2c->a_clk_mask = (0x20 << 8);
+		ddc_i2c->a_data_mask = 0x80;
+		ddc_i2c->put_clk_mask = (0x20 << 8);
+		ddc_i2c->put_data_mask = 0x80;
+		ddc_i2c->get_clk_mask = (0x20 << 8);
+		ddc_i2c->get_data_mask = 0x80;
+		ddc_i2c->mask_clk_reg = RADEON_GPIOPAD_MASK;
+		ddc_i2c->mask_data_reg = RADEON_GPIOPAD_MASK;
+		ddc_i2c->a_clk_reg = RADEON_GPIOPAD_A;
+		ddc_i2c->a_data_reg = RADEON_GPIOPAD_A;
+		ddc_i2c->put_clk_reg = RADEON_GPIOPAD_EN;
+		ddc_i2c->put_data_reg = RADEON_GPIOPAD_EN;
+		ddc_i2c->get_clk_reg = RADEON_LCD_GPIO_Y_REG;
+		ddc_i2c->get_data_reg = RADEON_LCD_GPIO_Y_REG;
+	}
+
+	/* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
+	   one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */
+	if (dev->pdev->device == 0x515e &&
+	    dev->pdev->subsystem_vendor == 0x1014) {
+		if (*legacy_connector == CONNECTOR_CRT_LEGACY &&
+		    ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
+			return false;
+	}
+
+	/* Some RV100 cards with 2 VGA ports show up with DVI+VGA */
+	if (dev->pdev->device == 0x5159 &&
+	    dev->pdev->subsystem_vendor == 0x1002 &&
+	    dev->pdev->subsystem_device == 0x013a) {
+		if (*legacy_connector == CONNECTOR_DVI_I_LEGACY)
+			*legacy_connector = CONNECTOR_CRT_LEGACY;
+
+	}
+
+	/* X300 card with extra non-existent DVI port */
+	if (dev->pdev->device == 0x5B60 &&
+	    dev->pdev->subsystem_vendor == 0x17af &&
+	    dev->pdev->subsystem_device == 0x201e && bios_index == 2) {
+		if (*legacy_connector == CONNECTOR_DVI_I_LEGACY)
+			return false;
+	}
+
+	return true;
+}
+
+bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t conn_info, entry, devices;
+	uint16_t tmp;
+	enum radeon_combios_ddc ddc_type;
+	enum radeon_combios_connector connector;
+	int i = 0;
+	struct radeon_i2c_bus_rec ddc_i2c;
+
+	if (rdev->bios == NULL)
+		return false;
+
+	conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE);
+	if (conn_info) {
+		for (i = 0; i < 4; i++) {
+			entry = conn_info + 2 + i * 2;
+
+			if (!RBIOS16(entry))
+				break;
+
+			tmp = RBIOS16(entry);
+
+			connector = (tmp >> 12) & 0xf;
+
+			ddc_type = (tmp >> 8) & 0xf;
+			switch (ddc_type) {
+			case DDC_MONID:
+				ddc_i2c =
+				    combios_setup_i2c_bus(RADEON_GPIO_MONID);
+				break;
+			case DDC_DVI:
+				ddc_i2c =
+				    combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+				break;
+			case DDC_VGA:
+				ddc_i2c =
+				    combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+				break;
+			case DDC_CRT2:
+				ddc_i2c =
+				    combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+				break;
+			default:
+				break;
+			}
+
+			radeon_apply_legacy_quirks(dev, i, &connector,
+						   &ddc_i2c);
+
+			switch (connector) {
+			case CONNECTOR_PROPRIETARY_LEGACY:
+				if ((tmp >> 4) & 0x1)
+					devices = ATOM_DEVICE_DFP2_SUPPORT;
+				else
+					devices = ATOM_DEVICE_DFP1_SUPPORT;
+				radeon_add_legacy_encoder(dev,
+							  radeon_get_encoder_id
+							  (dev, devices, 0),
+							  devices);
+				radeon_add_legacy_connector(dev, i, devices,
+							    legacy_connector_convert
+							    [connector],
+							    &ddc_i2c);
+				break;
+			case CONNECTOR_CRT_LEGACY:
+				if (tmp & 0x1) {
+					devices = ATOM_DEVICE_CRT2_SUPPORT;
+					radeon_add_legacy_encoder(dev,
+								  radeon_get_encoder_id
+								  (dev,
+								   ATOM_DEVICE_CRT2_SUPPORT,
+								   2),
+								  ATOM_DEVICE_CRT2_SUPPORT);
+				} else {
+					devices = ATOM_DEVICE_CRT1_SUPPORT;
+					radeon_add_legacy_encoder(dev,
+								  radeon_get_encoder_id
+								  (dev,
+								   ATOM_DEVICE_CRT1_SUPPORT,
+								   1),
+								  ATOM_DEVICE_CRT1_SUPPORT);
+				}
+				radeon_add_legacy_connector(dev,
+							    i,
+							    devices,
+							    legacy_connector_convert
+							    [connector],
+							    &ddc_i2c);
+				break;
+			case CONNECTOR_DVI_I_LEGACY:
+				devices = 0;
+				if (tmp & 0x1) {
+					devices |= ATOM_DEVICE_CRT2_SUPPORT;
+					radeon_add_legacy_encoder(dev,
+								  radeon_get_encoder_id
+								  (dev,
+								   ATOM_DEVICE_CRT2_SUPPORT,
+								   2),
+								  ATOM_DEVICE_CRT2_SUPPORT);
+				} else {
+					devices |= ATOM_DEVICE_CRT1_SUPPORT;
+					radeon_add_legacy_encoder(dev,
+								  radeon_get_encoder_id
+								  (dev,
+								   ATOM_DEVICE_CRT1_SUPPORT,
+								   1),
+								  ATOM_DEVICE_CRT1_SUPPORT);
+				}
+				if ((tmp >> 4) & 0x1) {
+					devices |= ATOM_DEVICE_DFP2_SUPPORT;
+					radeon_add_legacy_encoder(dev,
+								  radeon_get_encoder_id
+								  (dev,
+								   ATOM_DEVICE_DFP2_SUPPORT,
+								   0),
+								  ATOM_DEVICE_DFP2_SUPPORT);
+				} else {
+					devices |= ATOM_DEVICE_DFP1_SUPPORT;
+					radeon_add_legacy_encoder(dev,
+								  radeon_get_encoder_id
+								  (dev,
+								   ATOM_DEVICE_DFP1_SUPPORT,
+								   0),
+								  ATOM_DEVICE_DFP1_SUPPORT);
+				}
+				radeon_add_legacy_connector(dev,
+							    i,
+							    devices,
+							    legacy_connector_convert
+							    [connector],
+							    &ddc_i2c);
+				break;
+			case CONNECTOR_DVI_D_LEGACY:
+				if ((tmp >> 4) & 0x1)
+					devices = ATOM_DEVICE_DFP2_SUPPORT;
+				else
+					devices = ATOM_DEVICE_DFP1_SUPPORT;
+				radeon_add_legacy_encoder(dev,
+							  radeon_get_encoder_id
+							  (dev, devices, 0),
+							  devices);
+				radeon_add_legacy_connector(dev, i, devices,
+							    legacy_connector_convert
+							    [connector],
+							    &ddc_i2c);
+				break;
+			case CONNECTOR_CTV_LEGACY:
+			case CONNECTOR_STV_LEGACY:
+				radeon_add_legacy_encoder(dev,
+							  radeon_get_encoder_id
+							  (dev,
+							   ATOM_DEVICE_TV1_SUPPORT,
+							   2),
+							  ATOM_DEVICE_TV1_SUPPORT);
+				radeon_add_legacy_connector(dev, i,
+							    ATOM_DEVICE_TV1_SUPPORT,
+							    legacy_connector_convert
+							    [connector],
+							    &ddc_i2c);
+				break;
+			default:
+				DRM_ERROR("Unknown connector type: %d\n",
+					  connector);
+				continue;
+			}
+
+		}
+	} else {
+		uint16_t tmds_info =
+		    combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
+		if (tmds_info) {
+			DRM_DEBUG("Found DFP table, assuming DVI connector\n");
+
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_CRT1_SUPPORT,
+									1),
+						  ATOM_DEVICE_CRT1_SUPPORT);
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_DFP1_SUPPORT,
+									0),
+						  ATOM_DEVICE_DFP1_SUPPORT);
+
+			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+			radeon_add_legacy_connector(dev,
+						    0,
+						    ATOM_DEVICE_CRT1_SUPPORT |
+						    ATOM_DEVICE_DFP1_SUPPORT,
+						    DRM_MODE_CONNECTOR_DVII,
+						    &ddc_i2c);
+		} else {
+			DRM_DEBUG("No connector info found\n");
+			return false;
+		}
+	}
+
+	if (rdev->flags & RADEON_IS_MOBILITY || rdev->flags & RADEON_IS_IGP) {
+		uint16_t lcd_info =
+		    combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
+		if (lcd_info) {
+			uint16_t lcd_ddc_info =
+			    combios_get_table_offset(dev,
+						     COMBIOS_LCD_DDC_INFO_TABLE);
+
+			radeon_add_legacy_encoder(dev,
+						  radeon_get_encoder_id(dev,
+									ATOM_DEVICE_LCD1_SUPPORT,
+									0),
+						  ATOM_DEVICE_LCD1_SUPPORT);
+
+			if (lcd_ddc_info) {
+				ddc_type = RBIOS8(lcd_ddc_info + 2);
+				switch (ddc_type) {
+				case DDC_MONID:
+					ddc_i2c =
+					    combios_setup_i2c_bus
+					    (RADEON_GPIO_MONID);
+					break;
+				case DDC_DVI:
+					ddc_i2c =
+					    combios_setup_i2c_bus
+					    (RADEON_GPIO_DVI_DDC);
+					break;
+				case DDC_VGA:
+					ddc_i2c =
+					    combios_setup_i2c_bus
+					    (RADEON_GPIO_VGA_DDC);
+					break;
+				case DDC_CRT2:
+					ddc_i2c =
+					    combios_setup_i2c_bus
+					    (RADEON_GPIO_CRT2_DDC);
+					break;
+				case DDC_LCD:
+					ddc_i2c =
+					    combios_setup_i2c_bus
+					    (RADEON_LCD_GPIO_MASK);
+					ddc_i2c.mask_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.mask_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					ddc_i2c.a_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.a_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					ddc_i2c.put_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.put_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					ddc_i2c.get_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.get_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					break;
+				case DDC_GPIO:
+					ddc_i2c =
+					    combios_setup_i2c_bus
+					    (RADEON_MDGPIO_EN_REG);
+					ddc_i2c.mask_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.mask_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					ddc_i2c.a_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.a_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					ddc_i2c.put_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.put_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					ddc_i2c.get_clk_mask =
+					    RBIOS32(lcd_ddc_info + 3);
+					ddc_i2c.get_data_mask =
+					    RBIOS32(lcd_ddc_info + 7);
+					break;
+				default:
+					ddc_i2c.valid = false;
+					break;
+				}
+				DRM_DEBUG("LCD DDC Info Table found!\n");
+			} else
+				ddc_i2c.valid = false;
+
+			radeon_add_legacy_connector(dev,
+						    5,
+						    ATOM_DEVICE_LCD1_SUPPORT,
+						    DRM_MODE_CONNECTOR_LVDS,
+						    &ddc_i2c);
+		}
+	}
+
+	/* check TV table */
+	if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
+		uint32_t tv_info =
+		    combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
+		if (tv_info) {
+			if (RBIOS8(tv_info + 6) == 'T') {
+				radeon_add_legacy_encoder(dev,
+							  radeon_get_encoder_id
+							  (dev,
+							   ATOM_DEVICE_TV1_SUPPORT,
+							   2),
+							  ATOM_DEVICE_TV1_SUPPORT);
+				radeon_add_legacy_connector(dev, 6,
+							    ATOM_DEVICE_TV1_SUPPORT,
+							    DRM_MODE_CONNECTOR_SVIDEO,
+							    &ddc_i2c);
+			}
+		}
+	}
+
+	radeon_link_encoder_connector(dev);
+
+	return true;
+}
+
+static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (offset) {
+		while (RBIOS16(offset)) {
+			uint16_t cmd = ((RBIOS16(offset) & 0xe000) >> 13);
+			uint32_t addr = (RBIOS16(offset) & 0x1fff);
+			uint32_t val, and_mask, or_mask;
+			uint32_t tmp;
+
+			offset += 2;
+			switch (cmd) {
+			case 0:
+				val = RBIOS32(offset);
+				offset += 4;
+				WREG32(addr, val);
+				break;
+			case 1:
+				val = RBIOS32(offset);
+				offset += 4;
+				WREG32(addr, val);
+				break;
+			case 2:
+				and_mask = RBIOS32(offset);
+				offset += 4;
+				or_mask = RBIOS32(offset);
+				offset += 4;
+				tmp = RREG32(addr);
+				tmp &= and_mask;
+				tmp |= or_mask;
+				WREG32(addr, tmp);
+				break;
+			case 3:
+				and_mask = RBIOS32(offset);
+				offset += 4;
+				or_mask = RBIOS32(offset);
+				offset += 4;
+				tmp = RREG32(addr);
+				tmp &= and_mask;
+				tmp |= or_mask;
+				WREG32(addr, tmp);
+				break;
+			case 4:
+				val = RBIOS16(offset);
+				offset += 2;
+				udelay(val);
+				break;
+			case 5:
+				val = RBIOS16(offset);
+				offset += 2;
+				switch (addr) {
+				case 8:
+					while (val--) {
+						if (!
+						    (RREG32_PLL
+						     (RADEON_CLK_PWRMGT_CNTL) &
+						     RADEON_MC_BUSY))
+							break;
+					}
+					break;
+				case 9:
+					while (val--) {
+						if ((RREG32(RADEON_MC_STATUS) &
+						     RADEON_MC_IDLE))
+							break;
+					}
+					break;
+				default:
+					break;
+				}
+				break;
+			default:
+				break;
+			}
+		}
+	}
+}
+
+static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (offset) {
+		while (RBIOS8(offset)) {
+			uint8_t cmd = ((RBIOS8(offset) & 0xc0) >> 6);
+			uint8_t addr = (RBIOS8(offset) & 0x3f);
+			uint32_t val, shift, tmp;
+			uint32_t and_mask, or_mask;
+
+			offset++;
+			switch (cmd) {
+			case 0:
+				val = RBIOS32(offset);
+				offset += 4;
+				WREG32_PLL(addr, val);
+				break;
+			case 1:
+				shift = RBIOS8(offset) * 8;
+				offset++;
+				and_mask = RBIOS8(offset) << shift;
+				and_mask |= ~(0xff << shift);
+				offset++;
+				or_mask = RBIOS8(offset) << shift;
+				offset++;
+				tmp = RREG32_PLL(addr);
+				tmp &= and_mask;
+				tmp |= or_mask;
+				WREG32_PLL(addr, tmp);
+				break;
+			case 2:
+			case 3:
+				tmp = 1000;
+				switch (addr) {
+				case 1:
+					udelay(150);
+					break;
+				case 2:
+					udelay(1000);
+					break;
+				case 3:
+					while (tmp--) {
+						if (!
+						    (RREG32_PLL
+						     (RADEON_CLK_PWRMGT_CNTL) &
+						     RADEON_MC_BUSY))
+							break;
+					}
+					break;
+				case 4:
+					while (tmp--) {
+						if (RREG32_PLL
+						    (RADEON_CLK_PWRMGT_CNTL) &
+						    RADEON_DLL_READY)
+							break;
+					}
+					break;
+				case 5:
+					tmp =
+					    RREG32_PLL(RADEON_CLK_PWRMGT_CNTL);
+					if (tmp & RADEON_CG_NO1_DEBUG_0) {
+#if 0
+						uint32_t mclk_cntl =
+						    RREG32_PLL
+						    (RADEON_MCLK_CNTL);
+						mclk_cntl &= 0xffff0000;
+						/*mclk_cntl |= 0x00001111;*//* ??? */
+						WREG32_PLL(RADEON_MCLK_CNTL,
+							   mclk_cntl);
+						udelay(10000);
+#endif
+						WREG32_PLL
+						    (RADEON_CLK_PWRMGT_CNTL,
+						     tmp &
+						     ~RADEON_CG_NO1_DEBUG_0);
+						udelay(10000);
+					}
+					break;
+				default:
+					break;
+				}
+				break;
+			default:
+				break;
+			}
+		}
+	}
+}
+
+static void combios_parse_ram_reset_table(struct drm_device *dev,
+					  uint16_t offset)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t tmp;
+
+	if (offset) {
+		uint8_t val = RBIOS8(offset);
+		while (val != 0xff) {
+			offset++;
+
+			if (val == 0x0f) {
+				uint32_t channel_complete_mask;
+
+				if (ASIC_IS_R300(rdev))
+					channel_complete_mask =
+					    R300_MEM_PWRUP_COMPLETE;
+				else
+					channel_complete_mask =
+					    RADEON_MEM_PWRUP_COMPLETE;
+				tmp = 20000;
+				while (tmp--) {
+					if ((RREG32(RADEON_MEM_STR_CNTL) &
+					     channel_complete_mask) ==
+					    channel_complete_mask)
+						break;
+				}
+			} else {
+				uint32_t or_mask = RBIOS16(offset);
+				offset += 2;
+
+				tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
+				tmp &= RADEON_SDRAM_MODE_MASK;
+				tmp |= or_mask;
+				WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp);
+
+				or_mask = val << 24;
+				tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
+				tmp &= RADEON_B3MEM_RESET_MASK;
+				tmp |= or_mask;
+				WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp);
+			}
+			val = RBIOS8(offset);
+		}
+	}
+}
+
+static uint32_t combios_detect_ram(struct drm_device *dev, int ram,
+				   int mem_addr_mapping)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t mem_cntl;
+	uint32_t mem_size;
+	uint32_t addr = 0;
+
+	mem_cntl = RREG32(RADEON_MEM_CNTL);
+	if (mem_cntl & RV100_HALF_MODE)
+		ram /= 2;
+	mem_size = ram;
+	mem_cntl &= ~(0xff << 8);
+	mem_cntl |= (mem_addr_mapping & 0xff) << 8;
+	WREG32(RADEON_MEM_CNTL, mem_cntl);
+	RREG32(RADEON_MEM_CNTL);
+
+	/* sdram reset ? */
+
+	/* something like this????  */
+	while (ram--) {
+		addr = ram * 1024 * 1024;
+		/* write to each page */
+		WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER);
+		WREG32(RADEON_MM_DATA, 0xdeadbeef);
+		/* read back and verify */
+		WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER);
+		if (RREG32(RADEON_MM_DATA) != 0xdeadbeef)
+			return 0;
+	}
+
+	return mem_size;
+}
+
+static void combios_write_ram_size(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint8_t rev;
+	uint16_t offset;
+	uint32_t mem_size = 0;
+	uint32_t mem_cntl = 0;
+
+	/* should do something smarter here I guess... */
+	if (rdev->flags & RADEON_IS_IGP)
+		return;
+
+	/* first check detected mem table */
+	offset = combios_get_table_offset(dev, COMBIOS_DETECTED_MEM_TABLE);
+	if (offset) {
+		rev = RBIOS8(offset);
+		if (rev < 3) {
+			mem_cntl = RBIOS32(offset + 1);
+			mem_size = RBIOS16(offset + 5);
+			if (((rdev->flags & RADEON_FAMILY_MASK) < CHIP_R200) &&
+			    ((dev->pdev->device != 0x515e)
+			     && (dev->pdev->device != 0x5969)))
+				WREG32(RADEON_MEM_CNTL, mem_cntl);
+		}
+	}
+
+	if (!mem_size) {
+		offset =
+		    combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE);
+		if (offset) {
+			rev = RBIOS8(offset - 1);
+			if (rev < 1) {
+				if (((rdev->flags & RADEON_FAMILY_MASK) <
+				     CHIP_R200)
+				    && ((dev->pdev->device != 0x515e)
+					&& (dev->pdev->device != 0x5969))) {
+					int ram = 0;
+					int mem_addr_mapping = 0;
+
+					while (RBIOS8(offset)) {
+						ram = RBIOS8(offset);
+						mem_addr_mapping =
+						    RBIOS8(offset + 1);
+						if (mem_addr_mapping != 0x25)
+							ram *= 2;
+						mem_size =
+						    combios_detect_ram(dev, ram,
+								       mem_addr_mapping);
+						if (mem_size)
+							break;
+						offset += 2;
+					}
+				} else
+					mem_size = RBIOS8(offset);
+			} else {
+				mem_size = RBIOS8(offset);
+				mem_size *= 2;	/* convert to MB */
+			}
+		}
+	}
+
+	mem_size *= (1024 * 1024);	/* convert to bytes */
+	WREG32(RADEON_CONFIG_MEMSIZE, mem_size);
+}
+
+void radeon_combios_dyn_clk_setup(struct drm_device *dev, int enable)
+{
+	uint16_t dyn_clk_info =
+	    combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
+
+	if (dyn_clk_info)
+		combios_parse_pll_table(dev, dyn_clk_info);
+}
+
+void radeon_combios_asic_init(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint16_t table;
+
+	/* port hardcoded mac stuff from radeonfb */
+	if (rdev->bios == NULL)
+		return;
+
+	/* ASIC INIT 1 */
+	table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_1_TABLE);
+	if (table)
+		combios_parse_mmio_table(dev, table);
+
+	/* PLL INIT */
+	table = combios_get_table_offset(dev, COMBIOS_PLL_INIT_TABLE);
+	if (table)
+		combios_parse_pll_table(dev, table);
+
+	/* ASIC INIT 2 */
+	table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_2_TABLE);
+	if (table)
+		combios_parse_mmio_table(dev, table);
+
+	if (!(rdev->flags & RADEON_IS_IGP)) {
+		/* ASIC INIT 4 */
+		table =
+		    combios_get_table_offset(dev, COMBIOS_ASIC_INIT_4_TABLE);
+		if (table)
+			combios_parse_mmio_table(dev, table);
+
+		/* RAM RESET */
+		table = combios_get_table_offset(dev, COMBIOS_RAM_RESET_TABLE);
+		if (table)
+			combios_parse_ram_reset_table(dev, table);
+
+		/* ASIC INIT 3 */
+		table =
+		    combios_get_table_offset(dev, COMBIOS_ASIC_INIT_3_TABLE);
+		if (table)
+			combios_parse_mmio_table(dev, table);
+
+		/* write CONFIG_MEMSIZE */
+		combios_write_ram_size(dev);
+	}
+
+	/* DYN CLK 1 */
+	table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
+	if (table)
+		combios_parse_pll_table(dev, table);
+
+}
+
+void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t bios_0_scratch, bios_6_scratch, bios_7_scratch;
+
+	bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
+	bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
+	bios_7_scratch = RREG32(RADEON_BIOS_7_SCRATCH);
+
+	/* let the bios control the backlight */
+	bios_0_scratch &= ~RADEON_DRIVER_BRIGHTNESS_EN;
+
+	/* tell the bios not to handle mode switching */
+	bios_6_scratch |= (RADEON_DISPLAY_SWITCHING_DIS |
+			   RADEON_ACC_MODE_CHANGE);
+
+	/* tell the bios a driver is loaded */
+	bios_7_scratch |= RADEON_DRV_LOADED;
+
+	WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch);
+	WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+	WREG32(RADEON_BIOS_7_SCRATCH, bios_7_scratch);
+}
+
+void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t bios_6_scratch;
+
+	bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
+
+	if (lock)
+		bios_6_scratch |= RADEON_DRIVER_CRITICAL;
+	else
+		bios_6_scratch &= ~RADEON_DRIVER_CRITICAL;
+
+	WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+}
+
+void
+radeon_combios_connected_scratch_regs(struct drm_connector *connector,
+				      struct drm_encoder *encoder,
+				      bool connected)
+{
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_connector *radeon_connector =
+	    to_radeon_connector(connector);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t bios_4_scratch = RREG32(RADEON_BIOS_4_SCRATCH);
+	uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH);
+
+	if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("TV1 connected\n");
+			/* fix me */
+			bios_4_scratch |= RADEON_TV1_ATTACHED_SVIDEO;
+			/*save->bios_4_scratch |= RADEON_TV1_ATTACHED_COMP; */
+			bios_5_scratch |= RADEON_TV1_ON;
+			bios_5_scratch |= RADEON_ACC_REQ_TV1;
+		} else {
+			DRM_DEBUG("TV1 disconnected\n");
+			bios_4_scratch &= ~RADEON_TV1_ATTACHED_MASK;
+			bios_5_scratch &= ~RADEON_TV1_ON;
+			bios_5_scratch &= ~RADEON_ACC_REQ_TV1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("LCD1 connected\n");
+			bios_4_scratch |= RADEON_LCD1_ATTACHED;
+			bios_5_scratch |= RADEON_LCD1_ON;
+			bios_5_scratch |= RADEON_ACC_REQ_LCD1;
+		} else {
+			DRM_DEBUG("LCD1 disconnected\n");
+			bios_4_scratch &= ~RADEON_LCD1_ATTACHED;
+			bios_5_scratch &= ~RADEON_LCD1_ON;
+			bios_5_scratch &= ~RADEON_ACC_REQ_LCD1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("CRT1 connected\n");
+			bios_4_scratch |= RADEON_CRT1_ATTACHED_COLOR;
+			bios_5_scratch |= RADEON_CRT1_ON;
+			bios_5_scratch |= RADEON_ACC_REQ_CRT1;
+		} else {
+			DRM_DEBUG("CRT1 disconnected\n");
+			bios_4_scratch &= ~RADEON_CRT1_ATTACHED_MASK;
+			bios_5_scratch &= ~RADEON_CRT1_ON;
+			bios_5_scratch &= ~RADEON_ACC_REQ_CRT1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("CRT2 connected\n");
+			bios_4_scratch |= RADEON_CRT2_ATTACHED_COLOR;
+			bios_5_scratch |= RADEON_CRT2_ON;
+			bios_5_scratch |= RADEON_ACC_REQ_CRT2;
+		} else {
+			DRM_DEBUG("CRT2 disconnected\n");
+			bios_4_scratch &= ~RADEON_CRT2_ATTACHED_MASK;
+			bios_5_scratch &= ~RADEON_CRT2_ON;
+			bios_5_scratch &= ~RADEON_ACC_REQ_CRT2;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("DFP1 connected\n");
+			bios_4_scratch |= RADEON_DFP1_ATTACHED;
+			bios_5_scratch |= RADEON_DFP1_ON;
+			bios_5_scratch |= RADEON_ACC_REQ_DFP1;
+		} else {
+			DRM_DEBUG("DFP1 disconnected\n");
+			bios_4_scratch &= ~RADEON_DFP1_ATTACHED;
+			bios_5_scratch &= ~RADEON_DFP1_ON;
+			bios_5_scratch &= ~RADEON_ACC_REQ_DFP1;
+		}
+	}
+	if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) &&
+	    (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) {
+		if (connected) {
+			DRM_DEBUG("DFP2 connected\n");
+			bios_4_scratch |= RADEON_DFP2_ATTACHED;
+			bios_5_scratch |= RADEON_DFP2_ON;
+			bios_5_scratch |= RADEON_ACC_REQ_DFP2;
+		} else {
+			DRM_DEBUG("DFP2 disconnected\n");
+			bios_4_scratch &= ~RADEON_DFP2_ATTACHED;
+			bios_5_scratch &= ~RADEON_DFP2_ON;
+			bios_5_scratch &= ~RADEON_ACC_REQ_DFP2;
+		}
+	}
+	WREG32(RADEON_BIOS_4_SCRATCH, bios_4_scratch);
+	WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+}
+
+void
+radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH);
+
+	if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		bios_5_scratch &= ~RADEON_TV1_CRTC_MASK;
+		bios_5_scratch |= (crtc << RADEON_TV1_CRTC_SHIFT);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK;
+		bios_5_scratch |= (crtc << RADEON_CRT1_CRTC_SHIFT);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK;
+		bios_5_scratch |= (crtc << RADEON_CRT2_CRTC_SHIFT);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
+		bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK;
+		bios_5_scratch |= (crtc << RADEON_LCD1_CRTC_SHIFT);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) {
+		bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK;
+		bios_5_scratch |= (crtc << RADEON_DFP1_CRTC_SHIFT);
+	}
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) {
+		bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK;
+		bios_5_scratch |= (crtc << RADEON_DFP2_CRTC_SHIFT);
+	}
+	WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch);
+}
+
+void
+radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
+
+	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
+		if (on)
+			bios_6_scratch |= RADEON_TV_DPMS_ON;
+		else
+			bios_6_scratch &= ~RADEON_TV_DPMS_ON;
+	}
+	if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) {
+		if (on)
+			bios_6_scratch |= RADEON_CRT_DPMS_ON;
+		else
+			bios_6_scratch &= ~RADEON_CRT_DPMS_ON;
+	}
+	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+		if (on)
+			bios_6_scratch |= RADEON_LCD_DPMS_ON;
+		else
+			bios_6_scratch &= ~RADEON_LCD_DPMS_ON;
+	}
+	if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+		if (on)
+			bios_6_scratch |= RADEON_DFP_DPMS_ON;
+		else
+			bios_6_scratch &= ~RADEON_DFP_DPMS_ON;
+	}
+	WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,603 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "drm_edid.h"
+#include "drm_crtc_helper.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+extern void
+radeon_combios_connected_scratch_regs(struct drm_connector *connector,
+				      struct drm_encoder *encoder,
+				      bool connected);
+extern void
+radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
+				       struct drm_encoder *encoder,
+				       bool connected);
+
+static void
+radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status)
+{
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *best_encoder = NULL;
+	struct drm_encoder *encoder = NULL;
+	struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
+	struct drm_mode_object *obj;
+	bool connected;
+	int i;
+
+	best_encoder = connector_funcs->best_encoder(connector);
+
+	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+		if (connector->encoder_ids[i] == 0)
+			break;
+
+		obj = drm_mode_object_find(connector->dev,
+					   connector->encoder_ids[i],
+					   DRM_MODE_OBJECT_ENCODER);
+		if (!obj)
+			continue;
+
+		encoder = obj_to_encoder(obj);
+
+		if ((encoder == best_encoder) && (status == connector_status_connected))
+			connected = true;
+		else
+			connected = false;
+
+		if (rdev->is_atom_bios)
+			radeon_atombios_connected_scratch_regs(connector, encoder, connected);
+		else
+			radeon_combios_connected_scratch_regs(connector, encoder, connected);
+
+	}
+}
+
+struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
+{
+	int enc_id = connector->encoder_ids[0];
+	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
+
+	/* pick the encoder ids */
+	if (enc_id) {
+		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
+		if (!obj)
+			return NULL;
+		encoder = obj_to_encoder(obj);
+		return encoder;
+	}
+	return NULL;
+}
+
+static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_display_mode *mode = NULL;
+	struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
+
+	if (native_mode->panel_xres != 0 &&
+	    native_mode->panel_yres != 0 &&
+	    native_mode->dotclock != 0) {
+		mode = drm_mode_create(dev);
+
+		mode->hdisplay = native_mode->panel_xres;
+		mode->vdisplay = native_mode->panel_yres;
+
+		mode->htotal = mode->hdisplay + native_mode->hblank;
+		mode->hsync_start = mode->hdisplay + native_mode->hoverplus;
+		mode->hsync_end = mode->hsync_start + native_mode->hsync_width;
+		mode->vtotal = mode->vdisplay + native_mode->vblank;
+		mode->vsync_start = mode->vdisplay + native_mode->voverplus;
+		mode->vsync_end = mode->vsync_start + native_mode->vsync_width;
+		mode->clock = native_mode->dotclock;
+		mode->flags = 0;
+
+		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+		drm_mode_set_name(mode);
+
+		DRM_DEBUG("Adding native panel mode %s\n", mode->name);
+	}
+	return mode;
+}
+
+int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property,
+				  uint64_t val)
+{
+	return 0;
+}
+
+
+static int radeon_lvds_get_modes(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_encoder *encoder;
+	int ret = 0;
+	struct drm_display_mode *mode;
+
+	if (radeon_connector->ddc_bus) {
+		ret = radeon_ddc_get_modes(radeon_connector);
+		if (ret > 0) {
+			return ret;
+		}
+	}
+
+	encoder = radeon_best_single_encoder(connector);
+	if (!encoder)
+		return 0;
+
+	/* we have no EDID modes */
+	mode = radeon_fp_native_mode(encoder);
+	if (mode) {
+		ret = 1;
+		drm_mode_probed_add(connector, mode);
+	}
+	return ret;
+}
+
+static int radeon_lvds_mode_valid(struct drm_connector *connector,
+				  struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
+{
+	enum drm_connector_status ret = connector_status_connected;
+	/* check acpi lid status ??? */
+	radeon_connector_update_scratch_regs(connector, ret);
+	return ret;
+}
+
+static void radeon_connector_destroy(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	if (radeon_connector->ddc_bus)
+		radeon_i2c_destroy(radeon_connector->ddc_bus);
+	kfree(radeon_connector->con_priv);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
+	.get_modes = radeon_lvds_get_modes,
+	.mode_valid = radeon_lvds_mode_valid,
+	.best_encoder = radeon_best_single_encoder,
+};
+
+struct drm_connector_funcs radeon_lvds_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = radeon_lvds_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = radeon_connector_destroy,
+	.set_property = radeon_connector_set_property,
+};
+
+static int radeon_vga_get_modes(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	int ret;
+
+	ret = radeon_ddc_get_modes(radeon_connector);
+
+	return ret;
+}
+
+static int radeon_vga_mode_valid(struct drm_connector *connector,
+				  struct drm_display_mode *mode)
+{
+
+	return MODE_OK;
+}
+
+static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_encoder *encoder;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	bool dret;
+	enum drm_connector_status ret = connector_status_disconnected;
+
+	radeon_i2c_do_lock(radeon_connector, 1);
+	dret = radeon_ddc_probe(radeon_connector);
+	radeon_i2c_do_lock(radeon_connector, 0);
+	if (dret)
+		ret = connector_status_connected;
+	else {
+		/* if EDID fails to a load detect */
+		encoder = radeon_best_single_encoder(connector);
+		if (!encoder)
+			ret = connector_status_disconnected;
+		else {
+			encoder_funcs = encoder->helper_private;
+			ret = encoder_funcs->detect(encoder, connector);
+		}
+	}
+
+	radeon_connector_update_scratch_regs(connector, ret);
+	return ret;
+}
+
+struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = {
+	.get_modes = radeon_vga_get_modes,
+	.mode_valid = radeon_vga_mode_valid,
+	.best_encoder = radeon_best_single_encoder,
+};
+
+struct drm_connector_funcs radeon_vga_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = radeon_vga_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = radeon_connector_destroy,
+	.set_property = radeon_connector_set_property,
+};
+
+static int radeon_dvi_get_modes(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	int ret;
+
+	ret = radeon_ddc_get_modes(radeon_connector);
+	/* reset scratch regs here since radeon_dvi_detect doesn't check digital bit */
+	radeon_connector_update_scratch_regs(connector, connector_status_connected);
+	return ret;
+}
+
+static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_encoder *encoder;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct drm_mode_object *obj;
+	int i;
+	enum drm_connector_status ret = connector_status_disconnected;
+	bool dret;
+
+	radeon_i2c_do_lock(radeon_connector, 1);
+	dret = radeon_ddc_probe(radeon_connector);
+	radeon_i2c_do_lock(radeon_connector, 0);
+	if (dret)
+		ret = connector_status_connected;
+	else {
+		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+			if (connector->encoder_ids[i] == 0)
+				break;
+
+			obj = drm_mode_object_find(connector->dev,
+						   connector->encoder_ids[i],
+						   DRM_MODE_OBJECT_ENCODER);
+			if (!obj)
+				continue;
+
+			encoder = obj_to_encoder(obj);
+
+			encoder_funcs = encoder->helper_private;
+			if (encoder_funcs->detect) {
+				ret = encoder_funcs->detect(encoder, connector);
+				if (ret == connector_status_connected) {
+					radeon_connector->use_digital = 0;
+					break;
+				}
+			}
+		}
+	}
+
+	/* updated in get modes as well since we need to know if it's analog or digital */
+	radeon_connector_update_scratch_regs(connector, ret);
+	return ret;
+}
+
+/* okay need to be smart in here about which encoder to pick */
+struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
+{
+	int enc_id = connector->encoder_ids[0];
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
+	int i;
+	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+		if (connector->encoder_ids[i] == 0)
+			break;
+
+		obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
+		if (!obj)
+			continue;
+
+		encoder = obj_to_encoder(obj);
+
+		if (radeon_connector->use_digital) {
+			if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
+				return encoder;
+		} else {
+			if (encoder->encoder_type == DRM_MODE_ENCODER_DAC ||
+			    encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
+				return encoder;
+		}
+	}
+
+	/* see if we have a default encoder  TODO */
+
+	/* then check use digitial */
+	/* pick the first one */
+	if (enc_id) {
+		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
+		if (!obj)
+			return NULL;
+		encoder = obj_to_encoder(obj);
+		return encoder;
+	}
+	return NULL;
+}
+
+struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
+	.get_modes = radeon_dvi_get_modes,
+	.mode_valid = radeon_vga_mode_valid,
+	.best_encoder = radeon_dvi_encoder,
+};
+
+struct drm_connector_funcs radeon_dvi_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = radeon_dvi_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = radeon_connector_set_property,
+	.destroy = radeon_connector_destroy,
+};
+
+void
+radeon_add_atom_connector(struct drm_device *dev,
+			  uint32_t connector_id,
+			  uint32_t supported_device,
+			  int connector_type,
+			  struct radeon_i2c_bus_rec *i2c_bus,
+			  bool linkb,
+			  uint32_t igp_lane_info)
+{
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *radeon_dig_connector;
+	uint32_t subpixel_order = SubPixelNone;
+
+	/* fixme - tv/cv/din */
+	if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
+	    (connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
+	    (connector_type == DRM_MODE_CONNECTOR_Composite) ||
+	    (connector_type == DRM_MODE_CONNECTOR_9PinDIN))
+		return;
+
+	/* see if we already added it */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		radeon_connector = to_radeon_connector(connector);
+		if (radeon_connector->connector_id == connector_id) {
+			radeon_connector->devices |= supported_device;
+			return;
+		}
+	}
+
+	radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
+	if (!radeon_connector)
+		return;
+
+	connector = &radeon_connector->base;
+
+	radeon_connector->connector_id = connector_id;
+	radeon_connector->devices = supported_device;
+	switch (connector_type) {
+	case DRM_MODE_CONNECTOR_VGA:
+		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		break;
+	case DRM_MODE_CONNECTOR_DVIA:
+		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		break;
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_DVID:
+		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
+		if (!radeon_dig_connector)
+			goto failed;
+		radeon_dig_connector->linkb = linkb;
+		radeon_dig_connector->igp_lane_info = igp_lane_info;
+		radeon_connector->con_priv = radeon_dig_connector;
+		drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		subpixel_order = SubPixelHorizontalRGB;
+		break;
+	case DRM_MODE_CONNECTOR_HDMIA:
+	case DRM_MODE_CONNECTOR_HDMIB:
+		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
+		if (!radeon_dig_connector)
+			goto failed;
+		radeon_dig_connector->linkb = linkb;
+		radeon_dig_connector->igp_lane_info = igp_lane_info;
+		radeon_connector->con_priv = radeon_dig_connector;
+		drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		subpixel_order = SubPixelHorizontalRGB;
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
+		if (!radeon_dig_connector)
+			goto failed;
+		radeon_dig_connector->linkb = linkb;
+		radeon_dig_connector->igp_lane_info = igp_lane_info;
+		radeon_connector->con_priv = radeon_dig_connector;
+		drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		subpixel_order = SubPixelHorizontalRGB;
+		break;
+	case DRM_MODE_CONNECTOR_SVIDEO:
+	case DRM_MODE_CONNECTOR_Composite:
+	case DRM_MODE_CONNECTOR_9PinDIN:
+		break;
+	case DRM_MODE_CONNECTOR_LVDS:
+		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
+		if (!radeon_dig_connector)
+			goto failed;
+		radeon_dig_connector->linkb = linkb;
+		radeon_dig_connector->igp_lane_info = igp_lane_info;
+		radeon_connector->con_priv = radeon_dig_connector;
+		drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		subpixel_order = SubPixelHorizontalRGB;
+		break;
+	}
+
+	connector->display_info.subpixel_order = subpixel_order;
+	drm_sysfs_connector_add(connector);
+	return;
+
+failed:
+	if (radeon_connector->ddc_bus)
+		radeon_i2c_destroy(radeon_connector->ddc_bus);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+void
+radeon_add_legacy_connector(struct drm_device *dev,
+			    uint32_t connector_id,
+			    uint32_t supported_device,
+			    int connector_type,
+			    struct radeon_i2c_bus_rec *i2c_bus)
+{
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	uint32_t subpixel_order = SubPixelNone;
+
+	/* fixme - tv/cv/din */
+	if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
+	    (connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
+	    (connector_type == DRM_MODE_CONNECTOR_Composite) ||
+	    (connector_type == DRM_MODE_CONNECTOR_9PinDIN))
+		return;
+
+	/* see if we already added it */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		radeon_connector = to_radeon_connector(connector);
+		if (radeon_connector->connector_id == connector_id) {
+			radeon_connector->devices |= supported_device;
+			return;
+		}
+	}
+
+	radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
+	if (!radeon_connector)
+		return;
+
+	connector = &radeon_connector->base;
+
+	radeon_connector->connector_id = connector_id;
+	radeon_connector->devices = supported_device;
+	switch (connector_type) {
+	case DRM_MODE_CONNECTOR_VGA:
+		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		break;
+	case DRM_MODE_CONNECTOR_DVIA:
+		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		break;
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_DVID:
+		drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		subpixel_order = SubPixelHorizontalRGB;
+		break;
+	case DRM_MODE_CONNECTOR_SVIDEO:
+	case DRM_MODE_CONNECTOR_Composite:
+	case DRM_MODE_CONNECTOR_9PinDIN:
+		break;
+	case DRM_MODE_CONNECTOR_LVDS:
+		drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
+		drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
+		if (i2c_bus->valid) {
+			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
+			if (!radeon_connector->ddc_bus)
+				goto failed;
+		}
+		subpixel_order = SubPixelHorizontalRGB;
+		break;
+	}
+
+	connector->display_info.subpixel_order = subpixel_order;
+	drm_sysfs_connector_add(connector);
+	return;
+
+failed:
+	if (radeon_connector->ddc_bus)
+		radeon_i2c_destroy(radeon_connector->ddc_bus);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_cp.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_cp.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_cp.c	2012-03-22 19:11:35.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_cp.c	2012-03-22 20:07:57.000000000 -0400
@@ -406,6 +406,15 @@
 {
 	uint32_t gb_tile_config, gb_pipe_sel = 0;
 
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
+		uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2);
+		if ((z_pipe_sel & 3) == 3)
+			dev_priv->num_z_pipes = 2;
+		else
+			dev_priv->num_z_pipes = 1;
+	} else
+		dev_priv->num_z_pipes = 1;
+
 	/* RS4xx/RS6xx/R4xx/R5xx */
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
 		gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
@@ -1966,11 +1975,10 @@
 	drm_radeon_private_t *dev_priv;
 	int ret = 0;
 
-	dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
+	dev_priv = kzalloc(sizeof(drm_radeon_private_t), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
-	memset(dev_priv, 0, sizeof(drm_radeon_private_t));
 	dev->dev_private = (void *)dev_priv;
 	dev_priv->flags = flags;
 
@@ -2024,13 +2032,13 @@
 	unsigned long sareapage;
 	int ret;
 
-	master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+	master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
 	if (!master_priv)
 		return -ENOMEM;
 
 	/* prebuild the SAREA */
 	sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
-	ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
+	ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK,
 			 &master_priv->sarea);
 	if (ret) {
 		DRM_ERROR("SAREA setup failed\n");
@@ -2058,7 +2066,7 @@
 	if (master_priv->sarea)
 		drm_rmmap_locked(dev, master_priv->sarea);
 
-	drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+	kfree(master_priv);
 
 	master->driver_priv = NULL;
 }
@@ -2092,7 +2100,7 @@
 
 	drm_rmmap(dev, dev_priv->mmio);
 
-	drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+	kfree(dev_priv);
 
 	dev->dev_private = NULL;
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_cs.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_cs.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2008 Jerome Glisse.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Jerome Glisse <glisse@freedesktop.org>
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+void r100_cs_dump_packet(struct radeon_cs_parser *p,
+			 struct radeon_cs_packet *pkt);
+
+int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
+{
+	struct drm_device *ddev = p->rdev->ddev;
+	struct radeon_cs_chunk *chunk;
+	unsigned i, j;
+	bool duplicate;
+
+	if (p->chunk_relocs_idx == -1) {
+		return 0;
+	}
+	chunk = &p->chunks[p->chunk_relocs_idx];
+	/* FIXME: we assume that each relocs use 4 dwords */
+	p->nrelocs = chunk->length_dw / 4;
+	p->relocs_ptr = kcalloc(p->nrelocs, sizeof(void *), GFP_KERNEL);
+	if (p->relocs_ptr == NULL) {
+		return -ENOMEM;
+	}
+	p->relocs = kcalloc(p->nrelocs, sizeof(struct radeon_cs_reloc), GFP_KERNEL);
+	if (p->relocs == NULL) {
+		return -ENOMEM;
+	}
+	for (i = 0; i < p->nrelocs; i++) {
+		struct drm_radeon_cs_reloc *r;
+
+		duplicate = false;
+		r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4];
+		for (j = 0; j < p->nrelocs; j++) {
+			if (r->handle == p->relocs[j].handle) {
+				p->relocs_ptr[i] = &p->relocs[j];
+				duplicate = true;
+				break;
+			}
+		}
+		if (!duplicate) {
+			p->relocs[i].gobj = drm_gem_object_lookup(ddev,
+								  p->filp,
+								  r->handle);
+			if (p->relocs[i].gobj == NULL) {
+				DRM_ERROR("gem object lookup failed 0x%x\n",
+					  r->handle);
+				return -EINVAL;
+			}
+			p->relocs_ptr[i] = &p->relocs[i];
+			p->relocs[i].robj = p->relocs[i].gobj->driver_private;
+			p->relocs[i].lobj.robj = p->relocs[i].robj;
+			p->relocs[i].lobj.rdomain = r->read_domains;
+			p->relocs[i].lobj.wdomain = r->write_domain;
+			p->relocs[i].handle = r->handle;
+			p->relocs[i].flags = r->flags;
+			INIT_LIST_HEAD(&p->relocs[i].lobj.list);
+			radeon_object_list_add_object(&p->relocs[i].lobj,
+						      &p->validated);
+		}
+	}
+	return radeon_object_list_validate(&p->validated, p->ib->fence);
+}
+
+int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
+{
+	struct drm_radeon_cs *cs = data;
+	uint64_t *chunk_array_ptr;
+	unsigned size, i;
+
+	if (!cs->num_chunks) {
+		return 0;
+	}
+	/* get chunks */
+	INIT_LIST_HEAD(&p->validated);
+	p->idx = 0;
+	p->chunk_ib_idx = -1;
+	p->chunk_relocs_idx = -1;
+	p->chunks_array = kcalloc(cs->num_chunks, sizeof(uint64_t), GFP_KERNEL);
+	if (p->chunks_array == NULL) {
+		return -ENOMEM;
+	}
+	chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
+	if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr,
+			       sizeof(uint64_t)*cs->num_chunks)) {
+		return -EFAULT;
+	}
+	p->nchunks = cs->num_chunks;
+	p->chunks = kcalloc(p->nchunks, sizeof(struct radeon_cs_chunk), GFP_KERNEL);
+	if (p->chunks == NULL) {
+		return -ENOMEM;
+	}
+	for (i = 0; i < p->nchunks; i++) {
+		struct drm_radeon_cs_chunk __user **chunk_ptr = NULL;
+		struct drm_radeon_cs_chunk user_chunk;
+		uint32_t __user *cdata;
+
+		chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i];
+		if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr,
+				       sizeof(struct drm_radeon_cs_chunk))) {
+			return -EFAULT;
+		}
+		p->chunks[i].length_dw = user_chunk.length_dw;
+		p->chunks[i].kdata = NULL;
+		p->chunks[i].chunk_id = user_chunk.chunk_id;
+
+		if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) {
+			p->chunk_relocs_idx = i;
+		}
+		if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) {
+			p->chunk_ib_idx = i;
+			/* zero length IB isn't useful */
+			if (p->chunks[i].length_dw == 0)
+				return -EINVAL;
+		}
+
+		p->chunks[i].length_dw = user_chunk.length_dw;
+		cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
+
+		size = p->chunks[i].length_dw * sizeof(uint32_t);
+		p->chunks[i].kdata = kzalloc(size, GFP_KERNEL);
+		if (p->chunks[i].kdata == NULL) {
+			return -ENOMEM;
+		}
+		if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) {
+			return -EFAULT;
+		}
+	}
+	if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) {
+		DRM_ERROR("cs IB too big: %d\n",
+			  p->chunks[p->chunk_ib_idx].length_dw);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * cs_parser_fini() - clean parser states
+ * @parser:	parser structure holding parsing context.
+ * @error:	error number
+ *
+ * If error is set than unvalidate buffer, otherwise just free memory
+ * used by parsing context.
+ **/
+static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
+{
+	unsigned i;
+
+	if (error) {
+		radeon_object_list_unvalidate(&parser->validated);
+	} else {
+		radeon_object_list_clean(&parser->validated);
+	}
+	for (i = 0; i < parser->nrelocs; i++) {
+		if (parser->relocs[i].gobj) {
+			mutex_lock(&parser->rdev->ddev->struct_mutex);
+			drm_gem_object_unreference(parser->relocs[i].gobj);
+			mutex_unlock(&parser->rdev->ddev->struct_mutex);
+		}
+	}
+	kfree(parser->relocs);
+	kfree(parser->relocs_ptr);
+	for (i = 0; i < parser->nchunks; i++) {
+		kfree(parser->chunks[i].kdata);
+	}
+	kfree(parser->chunks);
+	kfree(parser->chunks_array);
+	radeon_ib_free(parser->rdev, &parser->ib);
+}
+
+int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_cs_parser parser;
+	struct radeon_cs_chunk *ib_chunk;
+	int r;
+
+	mutex_lock(&rdev->cs_mutex);
+	if (rdev->gpu_lockup) {
+		mutex_unlock(&rdev->cs_mutex);
+		return -EINVAL;
+	}
+	/* initialize parser */
+	memset(&parser, 0, sizeof(struct radeon_cs_parser));
+	parser.filp = filp;
+	parser.rdev = rdev;
+	r = radeon_cs_parser_init(&parser, data);
+	if (r) {
+		DRM_ERROR("Failed to initialize parser !\n");
+		radeon_cs_parser_fini(&parser, r);
+		mutex_unlock(&rdev->cs_mutex);
+		return r;
+	}
+	r =  radeon_ib_get(rdev, &parser.ib);
+	if (r) {
+		DRM_ERROR("Failed to get ib !\n");
+		radeon_cs_parser_fini(&parser, r);
+		mutex_unlock(&rdev->cs_mutex);
+		return r;
+	}
+	r = radeon_cs_parser_relocs(&parser);
+	if (r) {
+		DRM_ERROR("Failed to parse relocation !\n");
+		radeon_cs_parser_fini(&parser, r);
+		mutex_unlock(&rdev->cs_mutex);
+		return r;
+	}
+	/* Copy the packet into the IB, the parser will read from the
+	 * input memory (cached) and write to the IB (which can be
+	 * uncached). */
+	ib_chunk = &parser.chunks[parser.chunk_ib_idx];
+	parser.ib->length_dw = ib_chunk->length_dw;
+	memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4);
+	r = radeon_cs_parse(&parser);
+	if (r) {
+		DRM_ERROR("Invalid command stream !\n");
+		radeon_cs_parser_fini(&parser, r);
+		mutex_unlock(&rdev->cs_mutex);
+		return r;
+	}
+	r = radeon_ib_schedule(rdev, parser.ib);
+	if (r) {
+		DRM_ERROR("Faild to schedule IB !\n");
+	}
+	radeon_cs_parser_fini(&parser, r);
+	mutex_unlock(&rdev->cs_mutex);
+	return r;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_cursor.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_cursor.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+#define CURSOR_WIDTH 64
+#define CURSOR_HEIGHT 64
+
+static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
+{
+	struct radeon_device *rdev = crtc->dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	uint32_t cur_lock;
+
+	if (ASIC_IS_AVIVO(rdev)) {
+		cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
+		if (lock)
+			cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
+		else
+			cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
+		WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
+	} else {
+		cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
+		if (lock)
+			cur_lock |= RADEON_CUR_LOCK;
+		else
+			cur_lock &= ~RADEON_CUR_LOCK;
+		WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
+	}
+}
+
+static void radeon_hide_cursor(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_device *rdev = crtc->dev->dev_private;
+
+	if (ASIC_IS_AVIVO(rdev)) {
+		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
+		WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
+	} else {
+		switch (radeon_crtc->crtc_id) {
+		case 0:
+			WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
+			break;
+		case 1:
+			WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
+			break;
+		default:
+			return;
+		}
+		WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN);
+	}
+}
+
+static void radeon_show_cursor(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_device *rdev = crtc->dev->dev_private;
+
+	if (ASIC_IS_AVIVO(rdev)) {
+		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
+		WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
+			     (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
+	} else {
+		switch (radeon_crtc->crtc_id) {
+		case 0:
+			WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
+			break;
+		case 1:
+			WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
+			break;
+		default:
+			return;
+		}
+
+		WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
+					  (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
+			 ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
+	}
+}
+
+static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
+			      uint32_t gpu_addr)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_device *rdev = crtc->dev->dev_private;
+
+	if (ASIC_IS_AVIVO(rdev))
+		WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
+	else {
+		radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
+		/* offset is from DISP(2)_BASE_ADDRESS */
+		WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
+	}
+}
+
+int radeon_crtc_cursor_set(struct drm_crtc *crtc,
+			   struct drm_file *file_priv,
+			   uint32_t handle,
+			   uint32_t width,
+			   uint32_t height)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_gem_object *obj;
+	uint64_t gpu_addr;
+	int ret;
+
+	if (!handle) {
+		/* turn off cursor */
+		radeon_hide_cursor(crtc);
+		obj = NULL;
+		goto unpin;
+	}
+
+	if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
+		DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
+		return -EINVAL;
+	}
+
+	radeon_crtc->cursor_width = width;
+	radeon_crtc->cursor_height = height;
+
+	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	if (!obj) {
+		DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
+		return -EINVAL;
+	}
+
+	ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+	if (ret)
+		goto fail;
+
+	radeon_lock_cursor(crtc, true);
+	/* XXX only 27 bit offset for legacy cursor */
+	radeon_set_cursor(crtc, obj, gpu_addr);
+	radeon_show_cursor(crtc);
+	radeon_lock_cursor(crtc, false);
+
+unpin:
+	if (radeon_crtc->cursor_bo) {
+		radeon_gem_object_unpin(radeon_crtc->cursor_bo);
+		mutex_lock(&crtc->dev->struct_mutex);
+		drm_gem_object_unreference(radeon_crtc->cursor_bo);
+		mutex_unlock(&crtc->dev->struct_mutex);
+	}
+
+	radeon_crtc->cursor_bo = obj;
+	return 0;
+fail:
+	mutex_lock(&crtc->dev->struct_mutex);
+	drm_gem_object_unreference(obj);
+	mutex_unlock(&crtc->dev->struct_mutex);
+
+	return 0;
+}
+
+int radeon_crtc_cursor_move(struct drm_crtc *crtc,
+			    int x, int y)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_device *rdev = crtc->dev->dev_private;
+	int xorigin = 0, yorigin = 0;
+
+	if (x < 0)
+		xorigin = -x + 1;
+	if (y < 0)
+		yorigin = -y + 1;
+	if (xorigin >= CURSOR_WIDTH)
+		xorigin = CURSOR_WIDTH - 1;
+	if (yorigin >= CURSOR_HEIGHT)
+		yorigin = CURSOR_HEIGHT - 1;
+
+	radeon_lock_cursor(crtc, true);
+	if (ASIC_IS_AVIVO(rdev)) {
+		int w = radeon_crtc->cursor_width;
+		int i = 0;
+		struct drm_crtc *crtc_p;
+
+		/* avivo cursor are offset into the total surface */
+		x += crtc->x;
+		y += crtc->y;
+		DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
+
+		/* avivo cursor image can't end on 128 pixel boundry or
+		 * go past the end of the frame if both crtcs are enabled
+		 */
+		list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
+			if (crtc_p->enabled)
+				i++;
+		}
+		if (i > 1) {
+			int cursor_end, frame_end;
+
+			cursor_end = x - xorigin + w;
+			frame_end = crtc->x + crtc->mode.crtc_hdisplay;
+			if (cursor_end >= frame_end) {
+				w = w - (cursor_end - frame_end);
+				if (!(frame_end & 0x7f))
+					w--;
+			} else {
+				if (!(cursor_end & 0x7f))
+					w--;
+			}
+			if (w <= 0)
+				w = 1;
+		}
+
+		WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
+			     ((xorigin ? 0 : x) << 16) |
+			     (yorigin ? 0 : y));
+		WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
+		WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
+		       ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
+	} else {
+		if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
+			y *= 2;
+
+		WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
+		       (RADEON_CUR_LOCK
+			| (xorigin << 16)
+			| yorigin));
+		WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
+		       (RADEON_CUR_LOCK
+			| ((xorigin ? 0 : x) << 16)
+			| (yorigin ? 0 : y)));
+		/* offset is from DISP(2)_BASE_ADDRESS */
+		WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
+								      (yorigin * 256)));
+	}
+	radeon_lock_cursor(crtc, false);
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_device.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_device.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_device.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,843 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include <linux/console.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/radeon_drm.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "radeon_asic.h"
+#include "atom.h"
+
+/*
+ * Clear GPU surface registers.
+ */
+static void radeon_surface_init(struct radeon_device *rdev)
+{
+	/* FIXME: check this out */
+	if (rdev->family < CHIP_R600) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			WREG32(RADEON_SURFACE0_INFO +
+			       i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
+			       0);
+		}
+		/* enable surfaces */
+		WREG32(RADEON_SURFACE_CNTL, 0);
+	}
+}
+
+/*
+ * GPU scratch registers helpers function.
+ */
+static void radeon_scratch_init(struct radeon_device *rdev)
+{
+	int i;
+
+	/* FIXME: check this out */
+	if (rdev->family < CHIP_R300) {
+		rdev->scratch.num_reg = 5;
+	} else {
+		rdev->scratch.num_reg = 7;
+	}
+	for (i = 0; i < rdev->scratch.num_reg; i++) {
+		rdev->scratch.free[i] = true;
+		rdev->scratch.reg[i] = RADEON_SCRATCH_REG0 + (i * 4);
+	}
+}
+
+int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg)
+{
+	int i;
+
+	for (i = 0; i < rdev->scratch.num_reg; i++) {
+		if (rdev->scratch.free[i]) {
+			rdev->scratch.free[i] = false;
+			*reg = rdev->scratch.reg[i];
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
+{
+	int i;
+
+	for (i = 0; i < rdev->scratch.num_reg; i++) {
+		if (rdev->scratch.reg[i] == reg) {
+			rdev->scratch.free[i] = true;
+			return;
+		}
+	}
+}
+
+/*
+ * MC common functions
+ */
+int radeon_mc_setup(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	/* Some chips have an "issue" with the memory controller, the
+	 * location must be aligned to the size. We just align it down,
+	 * too bad if we walk over the top of system memory, we don't
+	 * use DMA without a remapped anyway.
+	 * Affected chips are rv280, all r3xx, and all r4xx, but not IGP
+	 */
+	/* FGLRX seems to setup like this, VRAM a 0, then GART.
+	 */
+	/*
+	 * Note: from R6xx the address space is 40bits but here we only
+	 * use 32bits (still have to see a card which would exhaust 4G
+	 * address space).
+	 */
+	if (rdev->mc.vram_location != 0xFFFFFFFFUL) {
+		/* vram location was already setup try to put gtt after
+		 * if it fits */
+		tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
+		tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
+		if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
+			rdev->mc.gtt_location = tmp;
+		} else {
+			if (rdev->mc.gtt_size >= rdev->mc.vram_location) {
+				printk(KERN_ERR "[drm] GTT too big to fit "
+				       "before or after vram location.\n");
+				return -EINVAL;
+			}
+			rdev->mc.gtt_location = 0;
+		}
+	} else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) {
+		/* gtt location was already setup try to put vram before
+		 * if it fits */
+		if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) {
+			rdev->mc.vram_location = 0;
+		} else {
+			tmp = rdev->mc.gtt_location + rdev->mc.gtt_size;
+			tmp += (rdev->mc.mc_vram_size - 1);
+			tmp &= ~(rdev->mc.mc_vram_size - 1);
+			if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) {
+				rdev->mc.vram_location = tmp;
+			} else {
+				printk(KERN_ERR "[drm] vram too big to fit "
+				       "before or after GTT location.\n");
+				return -EINVAL;
+			}
+		}
+	} else {
+		rdev->mc.vram_location = 0;
+		tmp = rdev->mc.mc_vram_size;
+		tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
+		rdev->mc.gtt_location = tmp;
+	}
+	DRM_INFO("radeon: VRAM %uM\n", rdev->mc.real_vram_size >> 20);
+	DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
+		 rdev->mc.vram_location,
+		 rdev->mc.vram_location + rdev->mc.mc_vram_size - 1);
+	if (rdev->mc.real_vram_size != rdev->mc.mc_vram_size)
+		DRM_INFO("radeon: VRAM less than aperture workaround enabled\n");
+	DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20);
+	DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
+		 rdev->mc.gtt_location,
+		 rdev->mc.gtt_location + rdev->mc.gtt_size - 1);
+	return 0;
+}
+
+
+/*
+ * GPU helpers function.
+ */
+static bool radeon_card_posted(struct radeon_device *rdev)
+{
+	uint32_t reg;
+
+	/* first check CRTCs */
+	if (ASIC_IS_AVIVO(rdev)) {
+		reg = RREG32(AVIVO_D1CRTC_CONTROL) |
+		      RREG32(AVIVO_D2CRTC_CONTROL);
+		if (reg & AVIVO_CRTC_EN) {
+			return true;
+		}
+	} else {
+		reg = RREG32(RADEON_CRTC_GEN_CNTL) |
+		      RREG32(RADEON_CRTC2_GEN_CNTL);
+		if (reg & RADEON_CRTC_EN) {
+			return true;
+		}
+	}
+
+	/* then check MEM_SIZE, in case the crtcs are off */
+	if (rdev->family >= CHIP_R600)
+		reg = RREG32(R600_CONFIG_MEMSIZE);
+	else
+		reg = RREG32(RADEON_CONFIG_MEMSIZE);
+
+	if (reg)
+		return true;
+
+	return false;
+
+}
+
+
+/*
+ * Registers accessors functions.
+ */
+uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	DRM_ERROR("Invalid callback to read register 0x%04X\n", reg);
+	BUG_ON(1);
+	return 0;
+}
+
+void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n",
+		  reg, v);
+	BUG_ON(1);
+}
+
+void radeon_register_accessor_init(struct radeon_device *rdev)
+{
+	rdev->mc_rreg = &radeon_invalid_rreg;
+	rdev->mc_wreg = &radeon_invalid_wreg;
+	rdev->pll_rreg = &radeon_invalid_rreg;
+	rdev->pll_wreg = &radeon_invalid_wreg;
+	rdev->pciep_rreg = &radeon_invalid_rreg;
+	rdev->pciep_wreg = &radeon_invalid_wreg;
+
+	/* Don't change order as we are overridding accessor. */
+	if (rdev->family < CHIP_RV515) {
+		rdev->pcie_reg_mask = 0xff;
+	} else {
+		rdev->pcie_reg_mask = 0x7ff;
+	}
+	/* FIXME: not sure here */
+	if (rdev->family <= CHIP_R580) {
+		rdev->pll_rreg = &r100_pll_rreg;
+		rdev->pll_wreg = &r100_pll_wreg;
+	}
+	if (rdev->family >= CHIP_RV515) {
+		rdev->mc_rreg = &rv515_mc_rreg;
+		rdev->mc_wreg = &rv515_mc_wreg;
+	}
+	if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) {
+		rdev->mc_rreg = &rs400_mc_rreg;
+		rdev->mc_wreg = &rs400_mc_wreg;
+	}
+	if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
+		rdev->mc_rreg = &rs690_mc_rreg;
+		rdev->mc_wreg = &rs690_mc_wreg;
+	}
+	if (rdev->family == CHIP_RS600) {
+		rdev->mc_rreg = &rs600_mc_rreg;
+		rdev->mc_wreg = &rs600_mc_wreg;
+	}
+	if (rdev->family >= CHIP_R600) {
+		rdev->pciep_rreg = &r600_pciep_rreg;
+		rdev->pciep_wreg = &r600_pciep_wreg;
+	}
+}
+
+
+/*
+ * ASIC
+ */
+int radeon_asic_init(struct radeon_device *rdev)
+{
+	radeon_register_accessor_init(rdev);
+	switch (rdev->family) {
+	case CHIP_R100:
+	case CHIP_RV100:
+	case CHIP_RS100:
+	case CHIP_RV200:
+	case CHIP_RS200:
+	case CHIP_R200:
+	case CHIP_RV250:
+	case CHIP_RS300:
+	case CHIP_RV280:
+		rdev->asic = &r100_asic;
+		break;
+	case CHIP_R300:
+	case CHIP_R350:
+	case CHIP_RV350:
+	case CHIP_RV380:
+		rdev->asic = &r300_asic;
+		break;
+	case CHIP_R420:
+	case CHIP_R423:
+	case CHIP_RV410:
+		rdev->asic = &r420_asic;
+		break;
+	case CHIP_RS400:
+	case CHIP_RS480:
+		rdev->asic = &rs400_asic;
+		break;
+	case CHIP_RS600:
+		rdev->asic = &rs600_asic;
+		break;
+	case CHIP_RS690:
+	case CHIP_RS740:
+		rdev->asic = &rs690_asic;
+		break;
+	case CHIP_RV515:
+		rdev->asic = &rv515_asic;
+		break;
+	case CHIP_R520:
+	case CHIP_RV530:
+	case CHIP_RV560:
+	case CHIP_RV570:
+	case CHIP_R580:
+		rdev->asic = &r520_asic;
+		break;
+	case CHIP_R600:
+	case CHIP_RV610:
+	case CHIP_RV630:
+	case CHIP_RV620:
+	case CHIP_RV635:
+	case CHIP_RV670:
+	case CHIP_RS780:
+	case CHIP_RV770:
+	case CHIP_RV730:
+	case CHIP_RV710:
+	default:
+		/* FIXME: not supported yet */
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+/*
+ * Wrapper around modesetting bits.
+ */
+int radeon_clocks_init(struct radeon_device *rdev)
+{
+	int r;
+
+	radeon_get_clock_info(rdev->ddev);
+	r = radeon_static_clocks_init(rdev->ddev);
+	if (r) {
+		return r;
+	}
+	DRM_INFO("Clocks initialized !\n");
+	return 0;
+}
+
+void radeon_clocks_fini(struct radeon_device *rdev)
+{
+}
+
+/* ATOM accessor methods */
+static uint32_t cail_pll_read(struct card_info *info, uint32_t reg)
+{
+	struct radeon_device *rdev = info->dev->dev_private;
+	uint32_t r;
+
+	r = rdev->pll_rreg(rdev, reg);
+	return r;
+}
+
+static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val)
+{
+	struct radeon_device *rdev = info->dev->dev_private;
+
+	rdev->pll_wreg(rdev, reg, val);
+}
+
+static uint32_t cail_mc_read(struct card_info *info, uint32_t reg)
+{
+	struct radeon_device *rdev = info->dev->dev_private;
+	uint32_t r;
+
+	r = rdev->mc_rreg(rdev, reg);
+	return r;
+}
+
+static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val)
+{
+	struct radeon_device *rdev = info->dev->dev_private;
+
+	rdev->mc_wreg(rdev, reg, val);
+}
+
+static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val)
+{
+	struct radeon_device *rdev = info->dev->dev_private;
+
+	WREG32(reg*4, val);
+}
+
+static uint32_t cail_reg_read(struct card_info *info, uint32_t reg)
+{
+	struct radeon_device *rdev = info->dev->dev_private;
+	uint32_t r;
+
+	r = RREG32(reg*4);
+	return r;
+}
+
+static struct card_info atom_card_info = {
+	.dev = NULL,
+	.reg_read = cail_reg_read,
+	.reg_write = cail_reg_write,
+	.mc_read = cail_mc_read,
+	.mc_write = cail_mc_write,
+	.pll_read = cail_pll_read,
+	.pll_write = cail_pll_write,
+};
+
+int radeon_atombios_init(struct radeon_device *rdev)
+{
+	atom_card_info.dev = rdev->ddev;
+	rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios);
+	radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
+	return 0;
+}
+
+void radeon_atombios_fini(struct radeon_device *rdev)
+{
+	kfree(rdev->mode_info.atom_context);
+}
+
+int radeon_combios_init(struct radeon_device *rdev)
+{
+	radeon_combios_initialize_bios_scratch_regs(rdev->ddev);
+	return 0;
+}
+
+void radeon_combios_fini(struct radeon_device *rdev)
+{
+}
+
+int radeon_modeset_init(struct radeon_device *rdev);
+void radeon_modeset_fini(struct radeon_device *rdev);
+
+
+/*
+ * Radeon device.
+ */
+int radeon_device_init(struct radeon_device *rdev,
+		       struct drm_device *ddev,
+		       struct pci_dev *pdev,
+		       uint32_t flags)
+{
+	int r, ret;
+	int dma_bits;
+
+	DRM_INFO("radeon: Initializing kernel modesetting.\n");
+	rdev->shutdown = false;
+	rdev->ddev = ddev;
+	rdev->pdev = pdev;
+	rdev->flags = flags;
+	rdev->family = flags & RADEON_FAMILY_MASK;
+	rdev->is_atom_bios = false;
+	rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT;
+	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+	rdev->gpu_lockup = false;
+	/* mutex initialization are all done here so we
+	 * can recall function without having locking issues */
+	mutex_init(&rdev->cs_mutex);
+	mutex_init(&rdev->ib_pool.mutex);
+	mutex_init(&rdev->cp.mutex);
+	rwlock_init(&rdev->fence_drv.lock);
+
+	if (radeon_agpmode == -1) {
+		rdev->flags &= ~RADEON_IS_AGP;
+		if (rdev->family > CHIP_RV515 ||
+		    rdev->family == CHIP_RV380 ||
+		    rdev->family == CHIP_RV410 ||
+		    rdev->family == CHIP_R423) {
+			DRM_INFO("Forcing AGP to PCIE mode\n");
+			rdev->flags |= RADEON_IS_PCIE;
+		} else {
+			DRM_INFO("Forcing AGP to PCI mode\n");
+			rdev->flags |= RADEON_IS_PCI;
+		}
+	}
+
+	/* Set asic functions */
+	r = radeon_asic_init(rdev);
+	if (r) {
+		return r;
+	}
+	r = radeon_init(rdev);
+	if (r) {
+		return r;
+	}
+
+	/* set DMA mask + need_dma32 flags.
+	 * PCIE - can handle 40-bits.
+	 * IGP - can handle 40-bits (in theory)
+	 * AGP - generally dma32 is safest
+	 * PCI - only dma32
+	 */
+	rdev->need_dma32 = false;
+	if (rdev->flags & RADEON_IS_AGP)
+		rdev->need_dma32 = true;
+	if (rdev->flags & RADEON_IS_PCI)
+		rdev->need_dma32 = true;
+
+	dma_bits = rdev->need_dma32 ? 32 : 40;
+	r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
+	if (r) {
+		printk(KERN_WARNING "radeon: No suitable DMA available.\n");
+	}
+
+	/* Registers mapping */
+	/* TODO: block userspace mapping of io register */
+	rdev->rmmio_base = drm_get_resource_start(rdev->ddev, 2);
+	rdev->rmmio_size = drm_get_resource_len(rdev->ddev, 2);
+	rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size);
+	if (rdev->rmmio == NULL) {
+		return -ENOMEM;
+	}
+	DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
+	DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
+
+	/* Setup errata flags */
+	radeon_errata(rdev);
+	/* Initialize scratch registers */
+	radeon_scratch_init(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
+
+	/* TODO: disable VGA need to use VGA request */
+	/* BIOS*/
+	if (!radeon_get_bios(rdev)) {
+		if (ASIC_IS_AVIVO(rdev))
+			return -EINVAL;
+	}
+	if (rdev->is_atom_bios) {
+		r = radeon_atombios_init(rdev);
+		if (r) {
+			return r;
+		}
+	} else {
+		r = radeon_combios_init(rdev);
+		if (r) {
+			return r;
+		}
+	}
+	/* Reset gpu before posting otherwise ATOM will enter infinite loop */
+	if (radeon_gpu_reset(rdev)) {
+		/* FIXME: what do we want to do here ? */
+	}
+	/* check if cards are posted or not */
+	if (!radeon_card_posted(rdev) && rdev->bios) {
+		DRM_INFO("GPU not posted. posting now...\n");
+		if (rdev->is_atom_bios) {
+			atom_asic_init(rdev->mode_info.atom_context);
+		} else {
+			radeon_combios_asic_init(rdev->ddev);
+		}
+	}
+	/* Initialize clocks */
+	r = radeon_clocks_init(rdev);
+	if (r) {
+		return r;
+	}
+	/* Get vram informations */
+	radeon_vram_info(rdev);
+
+	/* Add an MTRR for the VRAM */
+	rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
+				      MTRR_TYPE_WRCOMB, 1);
+	DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n",
+		 rdev->mc.real_vram_size >> 20,
+		 (unsigned)rdev->mc.aper_size >> 20);
+	DRM_INFO("RAM width %dbits %cDR\n",
+		 rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
+	/* Initialize memory controller (also test AGP) */
+	r = radeon_mc_init(rdev);
+	if (r) {
+		return r;
+	}
+	/* Fence driver */
+	r = radeon_fence_driver_init(rdev);
+	if (r) {
+		return r;
+	}
+	r = radeon_irq_kms_init(rdev);
+	if (r) {
+		return r;
+	}
+	/* Memory manager */
+	r = radeon_object_init(rdev);
+	if (r) {
+		return r;
+	}
+	/* Initialize GART (initialize after TTM so we can allocate
+	 * memory through TTM but finalize after TTM) */
+	r = radeon_gart_enable(rdev);
+	if (!r) {
+		r = radeon_gem_init(rdev);
+	}
+
+	/* 1M ring buffer */
+	if (!r) {
+		r = radeon_cp_init(rdev, 1024 * 1024);
+	}
+	if (!r) {
+		r = radeon_wb_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failled initializing WB (%d).\n", r);
+			return r;
+		}
+	}
+	if (!r) {
+		r = radeon_ib_pool_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
+			return r;
+		}
+	}
+	if (!r) {
+		r = radeon_ib_test(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+			return r;
+		}
+	}
+	ret = r;
+	r = radeon_modeset_init(rdev);
+	if (r) {
+		return r;
+	}
+	if (!ret) {
+		DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
+	}
+	if (radeon_testing) {
+		radeon_test_moves(rdev);
+	}
+	if (radeon_benchmarking) {
+		radeon_benchmark(rdev);
+	}
+	return ret;
+}
+
+void radeon_device_fini(struct radeon_device *rdev)
+{
+	if (rdev == NULL || rdev->rmmio == NULL) {
+		return;
+	}
+	DRM_INFO("radeon: finishing device.\n");
+	rdev->shutdown = true;
+	/* Order matter so becarefull if you rearrange anythings */
+	radeon_modeset_fini(rdev);
+	radeon_ib_pool_fini(rdev);
+	radeon_cp_fini(rdev);
+	radeon_wb_fini(rdev);
+	radeon_gem_fini(rdev);
+	radeon_object_fini(rdev);
+	/* mc_fini must be after object_fini */
+	radeon_mc_fini(rdev);
+#if __OS_HAS_AGP
+	radeon_agp_fini(rdev);
+#endif
+	radeon_irq_kms_fini(rdev);
+	radeon_fence_driver_fini(rdev);
+	radeon_clocks_fini(rdev);
+	if (rdev->is_atom_bios) {
+		radeon_atombios_fini(rdev);
+	} else {
+		radeon_combios_fini(rdev);
+	}
+	kfree(rdev->bios);
+	rdev->bios = NULL;
+	iounmap(rdev->rmmio);
+	rdev->rmmio = NULL;
+}
+
+
+/*
+ * Suspend & resume.
+ */
+int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_crtc *crtc;
+
+	if (dev == NULL || rdev == NULL) {
+		return -ENODEV;
+	}
+	if (state.event == PM_EVENT_PRETHAW) {
+		return 0;
+	}
+	/* unpin the front buffers */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
+		struct radeon_object *robj;
+
+		if (rfb == NULL || rfb->obj == NULL) {
+			continue;
+		}
+		robj = rfb->obj->driver_private;
+		if (robj != rdev->fbdev_robj) {
+			radeon_object_unpin(robj);
+		}
+	}
+	/* evict vram memory */
+	radeon_object_evict_vram(rdev);
+	/* wait for gpu to finish processing current batch */
+	radeon_fence_wait_last(rdev);
+
+	radeon_cp_disable(rdev);
+	radeon_gart_disable(rdev);
+
+	/* evict remaining vram memory */
+	radeon_object_evict_vram(rdev);
+
+	rdev->irq.sw_int = false;
+	radeon_irq_set(rdev);
+
+	pci_save_state(dev->pdev);
+	if (state.event == PM_EVENT_SUSPEND) {
+		/* Shut down the device */
+		pci_disable_device(dev->pdev);
+		pci_set_power_state(dev->pdev, PCI_D3hot);
+	}
+	acquire_console_sem();
+	fb_set_suspend(rdev->fbdev_info, 1);
+	release_console_sem();
+	return 0;
+}
+
+int radeon_resume_kms(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	int r;
+
+	acquire_console_sem();
+	pci_set_power_state(dev->pdev, PCI_D0);
+	pci_restore_state(dev->pdev);
+	if (pci_enable_device(dev->pdev)) {
+		release_console_sem();
+		return -1;
+	}
+	pci_set_master(dev->pdev);
+	/* Reset gpu before posting otherwise ATOM will enter infinite loop */
+	if (radeon_gpu_reset(rdev)) {
+		/* FIXME: what do we want to do here ? */
+	}
+	/* post card */
+	if (rdev->is_atom_bios) {
+		atom_asic_init(rdev->mode_info.atom_context);
+	} else {
+		radeon_combios_asic_init(rdev->ddev);
+	}
+	/* Initialize clocks */
+	r = radeon_clocks_init(rdev);
+	if (r) {
+		release_console_sem();
+		return r;
+	}
+	/* Enable IRQ */
+	rdev->irq.sw_int = true;
+	radeon_irq_set(rdev);
+	/* Initialize GPU Memory Controller */
+	r = radeon_mc_init(rdev);
+	if (r) {
+		goto out;
+	}
+	r = radeon_gart_enable(rdev);
+	if (r) {
+		goto out;
+	}
+	r = radeon_cp_init(rdev, rdev->cp.ring_size);
+	if (r) {
+		goto out;
+	}
+out:
+	fb_set_suspend(rdev->fbdev_info, 0);
+	release_console_sem();
+
+	/* blat the mode back in */
+	drm_helper_resume_force_mode(dev);
+	return 0;
+}
+
+
+/*
+ * Debugfs
+ */
+struct radeon_debugfs {
+	struct drm_info_list	*files;
+	unsigned		num_files;
+};
+static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_NUM_FILES];
+static unsigned _radeon_debugfs_count = 0;
+
+int radeon_debugfs_add_files(struct radeon_device *rdev,
+			     struct drm_info_list *files,
+			     unsigned nfiles)
+{
+	unsigned i;
+
+	for (i = 0; i < _radeon_debugfs_count; i++) {
+		if (_radeon_debugfs[i].files == files) {
+			/* Already registered */
+			return 0;
+		}
+	}
+	if ((_radeon_debugfs_count + nfiles) > RADEON_DEBUGFS_MAX_NUM_FILES) {
+		DRM_ERROR("Reached maximum number of debugfs files.\n");
+		DRM_ERROR("Report so we increase RADEON_DEBUGFS_MAX_NUM_FILES.\n");
+		return -EINVAL;
+	}
+	_radeon_debugfs[_radeon_debugfs_count].files = files;
+	_radeon_debugfs[_radeon_debugfs_count].num_files = nfiles;
+	_radeon_debugfs_count++;
+#if defined(CONFIG_DEBUG_FS)
+	drm_debugfs_create_files(files, nfiles,
+				 rdev->ddev->control->debugfs_root,
+				 rdev->ddev->control);
+	drm_debugfs_create_files(files, nfiles,
+				 rdev->ddev->primary->debugfs_root,
+				 rdev->ddev->primary);
+#endif
+	return 0;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+int radeon_debugfs_init(struct drm_minor *minor)
+{
+	return 0;
+}
+
+void radeon_debugfs_cleanup(struct drm_minor *minor)
+{
+	unsigned i;
+
+	for (i = 0; i < _radeon_debugfs_count; i++) {
+		drm_debugfs_remove_files(_radeon_debugfs[i].files,
+					 _radeon_debugfs[i].num_files, minor);
+	}
+}
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_display.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_display.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_display.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,712 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+#include "atom.h"
+#include <asm/div64.h>
+
+#include "drm_crtc_helper.h"
+#include "drm_edid.h"
+
+static int radeon_ddc_dump(struct drm_connector *connector);
+
+static void avivo_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int i;
+
+	DRM_DEBUG("%d\n", radeon_crtc->crtc_id);
+	WREG32(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0);
+
+	WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
+	WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
+
+	WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff);
+	WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
+	WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
+
+	WREG32(AVIVO_DC_LUT_RW_SELECT, radeon_crtc->crtc_id);
+	WREG32(AVIVO_DC_LUT_RW_MODE, 0);
+	WREG32(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f);
+
+	WREG8(AVIVO_DC_LUT_RW_INDEX, 0);
+	for (i = 0; i < 256; i++) {
+		WREG32(AVIVO_DC_LUT_30_COLOR,
+			     (radeon_crtc->lut_r[i] << 20) |
+			     (radeon_crtc->lut_g[i] << 10) |
+			     (radeon_crtc->lut_b[i] << 0));
+	}
+
+	WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
+}
+
+static void legacy_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int i;
+	uint32_t dac2_cntl;
+
+	dac2_cntl = RREG32(RADEON_DAC_CNTL2);
+	if (radeon_crtc->crtc_id == 0)
+		dac2_cntl &= (uint32_t)~RADEON_DAC2_PALETTE_ACC_CTL;
+	else
+		dac2_cntl |= RADEON_DAC2_PALETTE_ACC_CTL;
+	WREG32(RADEON_DAC_CNTL2, dac2_cntl);
+
+	WREG8(RADEON_PALETTE_INDEX, 0);
+	for (i = 0; i < 256; i++) {
+		WREG32(RADEON_PALETTE_30_DATA,
+			     (radeon_crtc->lut_r[i] << 20) |
+			     (radeon_crtc->lut_g[i] << 10) |
+			     (radeon_crtc->lut_b[i] << 0));
+	}
+}
+
+void radeon_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (!crtc->enabled)
+		return;
+
+	if (ASIC_IS_AVIVO(rdev))
+		avivo_crtc_load_lut(crtc);
+	else
+		legacy_crtc_load_lut(crtc);
+}
+
+/** Sets the color ramps on behalf of RandR */
+void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+			      u16 blue, int regno)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+	if (regno == 0)
+		DRM_DEBUG("gamma set %d\n", radeon_crtc->crtc_id);
+	radeon_crtc->lut_r[regno] = red >> 6;
+	radeon_crtc->lut_g[regno] = green >> 6;
+	radeon_crtc->lut_b[regno] = blue >> 6;
+}
+
+static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
+				  u16 *blue, uint32_t size)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	int i, j;
+
+	if (size != 256) {
+		return;
+	}
+	if (crtc->fb == NULL) {
+		return;
+	}
+
+	if (crtc->fb->depth == 16) {
+		for (i = 0; i < 64; i++) {
+			if (i <= 31) {
+				for (j = 0; j < 8; j++) {
+					radeon_crtc->lut_r[i * 8 + j] = red[i] >> 6;
+					radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 6;
+				}
+			}
+			for (j = 0; j < 4; j++)
+				radeon_crtc->lut_g[i * 4 + j] = green[i] >> 6;
+		}
+	} else {
+		for (i = 0; i < 256; i++) {
+			radeon_crtc->lut_r[i] = red[i] >> 6;
+			radeon_crtc->lut_g[i] = green[i] >> 6;
+			radeon_crtc->lut_b[i] = blue[i] >> 6;
+		}
+	}
+
+	radeon_crtc_load_lut(crtc);
+}
+
+static void radeon_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+	if (radeon_crtc->mode_set.mode) {
+		drm_mode_destroy(crtc->dev, radeon_crtc->mode_set.mode);
+	}
+	drm_crtc_cleanup(crtc);
+	kfree(radeon_crtc);
+}
+
+static const struct drm_crtc_funcs radeon_crtc_funcs = {
+	.cursor_set = radeon_crtc_cursor_set,
+	.cursor_move = radeon_crtc_cursor_move,
+	.gamma_set = radeon_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = radeon_crtc_destroy,
+};
+
+static void radeon_crtc_init(struct drm_device *dev, int index)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc;
+	int i;
+
+	radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
+	if (radeon_crtc == NULL)
+		return;
+
+	drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs);
+
+	drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
+	radeon_crtc->crtc_id = index;
+	rdev->mode_info.crtcs[index] = radeon_crtc;
+
+	radeon_crtc->mode_set.crtc = &radeon_crtc->base;
+	radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
+	radeon_crtc->mode_set.num_connectors = 0;
+
+	for (i = 0; i < 256; i++) {
+		radeon_crtc->lut_r[i] = i << 2;
+		radeon_crtc->lut_g[i] = i << 2;
+		radeon_crtc->lut_b[i] = i << 2;
+	}
+
+	if (rdev->is_atom_bios && (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom))
+		radeon_atombios_init_crtc(dev, radeon_crtc);
+	else
+		radeon_legacy_init_crtc(dev, radeon_crtc);
+}
+
+static const char *encoder_names[34] = {
+	"NONE",
+	"INTERNAL_LVDS",
+	"INTERNAL_TMDS1",
+	"INTERNAL_TMDS2",
+	"INTERNAL_DAC1",
+	"INTERNAL_DAC2",
+	"INTERNAL_SDVOA",
+	"INTERNAL_SDVOB",
+	"SI170B",
+	"CH7303",
+	"CH7301",
+	"INTERNAL_DVO1",
+	"EXTERNAL_SDVOA",
+	"EXTERNAL_SDVOB",
+	"TITFP513",
+	"INTERNAL_LVTM1",
+	"VT1623",
+	"HDMI_SI1930",
+	"HDMI_INTERNAL",
+	"INTERNAL_KLDSCP_TMDS1",
+	"INTERNAL_KLDSCP_DVO1",
+	"INTERNAL_KLDSCP_DAC1",
+	"INTERNAL_KLDSCP_DAC2",
+	"SI178",
+	"MVPU_FPGA",
+	"INTERNAL_DDI",
+	"VT1625",
+	"HDMI_SI1932",
+	"DP_AN9801",
+	"DP_DP501",
+	"INTERNAL_UNIPHY",
+	"INTERNAL_KLDSCP_LVTMA",
+	"INTERNAL_UNIPHY1",
+	"INTERNAL_UNIPHY2",
+};
+
+static const char *connector_names[13] = {
+	"Unknown",
+	"VGA",
+	"DVI-I",
+	"DVI-D",
+	"DVI-A",
+	"Composite",
+	"S-video",
+	"LVDS",
+	"Component",
+	"DIN",
+	"DisplayPort",
+	"HDMI-A",
+	"HDMI-B",
+};
+
+static void radeon_print_display_setup(struct drm_device *dev)
+{
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct drm_encoder *encoder;
+	struct radeon_encoder *radeon_encoder;
+	uint32_t devices;
+	int i = 0;
+
+	DRM_INFO("Radeon Display Connectors\n");
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		radeon_connector = to_radeon_connector(connector);
+		DRM_INFO("Connector %d:\n", i);
+		DRM_INFO("  %s\n", connector_names[connector->connector_type]);
+		if (radeon_connector->ddc_bus)
+			DRM_INFO("  DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+				 radeon_connector->ddc_bus->rec.mask_clk_reg,
+				 radeon_connector->ddc_bus->rec.mask_data_reg,
+				 radeon_connector->ddc_bus->rec.a_clk_reg,
+				 radeon_connector->ddc_bus->rec.a_data_reg,
+				 radeon_connector->ddc_bus->rec.put_clk_reg,
+				 radeon_connector->ddc_bus->rec.put_data_reg,
+				 radeon_connector->ddc_bus->rec.get_clk_reg,
+				 radeon_connector->ddc_bus->rec.get_data_reg);
+		DRM_INFO("  Encoders:\n");
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+			radeon_encoder = to_radeon_encoder(encoder);
+			devices = radeon_encoder->devices & radeon_connector->devices;
+			if (devices) {
+				if (devices & ATOM_DEVICE_CRT1_SUPPORT)
+					DRM_INFO("    CRT1: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_CRT2_SUPPORT)
+					DRM_INFO("    CRT2: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_LCD1_SUPPORT)
+					DRM_INFO("    LCD1: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_DFP1_SUPPORT)
+					DRM_INFO("    DFP1: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_DFP2_SUPPORT)
+					DRM_INFO("    DFP2: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_DFP3_SUPPORT)
+					DRM_INFO("    DFP3: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_DFP4_SUPPORT)
+					DRM_INFO("    DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_DFP5_SUPPORT)
+					DRM_INFO("    DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_TV1_SUPPORT)
+					DRM_INFO("    TV1: %s\n", encoder_names[radeon_encoder->encoder_id]);
+				if (devices & ATOM_DEVICE_CV_SUPPORT)
+					DRM_INFO("    CV: %s\n", encoder_names[radeon_encoder->encoder_id]);
+			}
+		}
+		i++;
+	}
+}
+
+bool radeon_setup_enc_conn(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_connector *drm_connector;
+	bool ret = false;
+
+	if (rdev->bios) {
+		if (rdev->is_atom_bios) {
+			if (rdev->family >= CHIP_R600)
+				ret = radeon_get_atom_connector_info_from_object_table(dev);
+			else
+				ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
+		} else
+			ret = radeon_get_legacy_connector_info_from_bios(dev);
+	} else {
+		if (!ASIC_IS_AVIVO(rdev))
+			ret = radeon_get_legacy_connector_info_from_table(dev);
+	}
+	if (ret) {
+		radeon_print_display_setup(dev);
+		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
+			radeon_ddc_dump(drm_connector);
+	}
+
+	return ret;
+}
+
+int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
+{
+	struct edid *edid;
+	int ret = 0;
+
+	if (!radeon_connector->ddc_bus)
+		return -1;
+	radeon_i2c_do_lock(radeon_connector, 1);
+	edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+	radeon_i2c_do_lock(radeon_connector, 0);
+	if (edid) {
+		/* update digital bits here */
+		if (edid->input & DRM_EDID_INPUT_DIGITAL)
+			radeon_connector->use_digital = 1;
+		else
+			radeon_connector->use_digital = 0;
+		drm_mode_connector_update_edid_property(&radeon_connector->base, edid);
+		ret = drm_add_edid_modes(&radeon_connector->base, edid);
+		kfree(edid);
+		return ret;
+	}
+	drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
+	return -1;
+}
+
+static int radeon_ddc_dump(struct drm_connector *connector)
+{
+	struct edid *edid;
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	int ret = 0;
+
+	if (!radeon_connector->ddc_bus)
+		return -1;
+	radeon_i2c_do_lock(radeon_connector, 1);
+	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	radeon_i2c_do_lock(radeon_connector, 0);
+	if (edid) {
+		kfree(edid);
+	}
+	return ret;
+}
+
+static inline uint32_t radeon_div(uint64_t n, uint32_t d)
+{
+	uint64_t mod;
+
+	n += d / 2;
+
+	mod = do_div(n, d);
+	return n;
+}
+
+void radeon_compute_pll(struct radeon_pll *pll,
+			uint64_t freq,
+			uint32_t *dot_clock_p,
+			uint32_t *fb_div_p,
+			uint32_t *frac_fb_div_p,
+			uint32_t *ref_div_p,
+			uint32_t *post_div_p,
+			int flags)
+{
+	uint32_t min_ref_div = pll->min_ref_div;
+	uint32_t max_ref_div = pll->max_ref_div;
+	uint32_t min_fractional_feed_div = 0;
+	uint32_t max_fractional_feed_div = 0;
+	uint32_t best_vco = pll->best_vco;
+	uint32_t best_post_div = 1;
+	uint32_t best_ref_div = 1;
+	uint32_t best_feedback_div = 1;
+	uint32_t best_frac_feedback_div = 0;
+	uint32_t best_freq = -1;
+	uint32_t best_error = 0xffffffff;
+	uint32_t best_vco_diff = 1;
+	uint32_t post_div;
+
+	DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
+	freq = freq * 1000;
+
+	if (flags & RADEON_PLL_USE_REF_DIV)
+		min_ref_div = max_ref_div = pll->reference_div;
+	else {
+		while (min_ref_div < max_ref_div-1) {
+			uint32_t mid = (min_ref_div + max_ref_div) / 2;
+			uint32_t pll_in = pll->reference_freq / mid;
+			if (pll_in < pll->pll_in_min)
+				max_ref_div = mid;
+			else if (pll_in > pll->pll_in_max)
+				min_ref_div = mid;
+			else
+				break;
+		}
+	}
+
+	if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+		min_fractional_feed_div = pll->min_frac_feedback_div;
+		max_fractional_feed_div = pll->max_frac_feedback_div;
+	}
+
+	for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
+		uint32_t ref_div;
+
+		if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+			continue;
+
+		/* legacy radeons only have a few post_divs */
+		if (flags & RADEON_PLL_LEGACY) {
+			if ((post_div == 5) ||
+			    (post_div == 7) ||
+			    (post_div == 9) ||
+			    (post_div == 10) ||
+			    (post_div == 11) ||
+			    (post_div == 13) ||
+			    (post_div == 14) ||
+			    (post_div == 15))
+				continue;
+		}
+
+		for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) {
+			uint32_t feedback_div, current_freq = 0, error, vco_diff;
+			uint32_t pll_in = pll->reference_freq / ref_div;
+			uint32_t min_feed_div = pll->min_feedback_div;
+			uint32_t max_feed_div = pll->max_feedback_div + 1;
+
+			if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max)
+				continue;
+
+			while (min_feed_div < max_feed_div) {
+				uint32_t vco;
+				uint32_t min_frac_feed_div = min_fractional_feed_div;
+				uint32_t max_frac_feed_div = max_fractional_feed_div + 1;
+				uint32_t frac_feedback_div;
+				uint64_t tmp;
+
+				feedback_div = (min_feed_div + max_feed_div) / 2;
+
+				tmp = (uint64_t)pll->reference_freq * feedback_div;
+				vco = radeon_div(tmp, ref_div);
+
+				if (vco < pll->pll_out_min) {
+					min_feed_div = feedback_div + 1;
+					continue;
+				} else if (vco > pll->pll_out_max) {
+					max_feed_div = feedback_div;
+					continue;
+				}
+
+				while (min_frac_feed_div < max_frac_feed_div) {
+					frac_feedback_div = (min_frac_feed_div + max_frac_feed_div) / 2;
+					tmp = (uint64_t)pll->reference_freq * 10000 * feedback_div;
+					tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
+					current_freq = radeon_div(tmp, ref_div * post_div);
+
+					if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
+						error = freq - current_freq;
+						error = error < 0 ? 0xffffffff : error;
+					} else
+						error = abs(current_freq - freq);
+					vco_diff = abs(vco - best_vco);
+
+					if ((best_vco == 0 && error < best_error) ||
+					    (best_vco != 0 &&
+					     (error < best_error - 100 ||
+					      (abs(error - best_error) < 100 && vco_diff < best_vco_diff)))) {
+						best_post_div = post_div;
+						best_ref_div = ref_div;
+						best_feedback_div = feedback_div;
+						best_frac_feedback_div = frac_feedback_div;
+						best_freq = current_freq;
+						best_error = error;
+						best_vco_diff = vco_diff;
+					} else if (current_freq == freq) {
+						if (best_freq == -1) {
+							best_post_div = post_div;
+							best_ref_div = ref_div;
+							best_feedback_div = feedback_div;
+							best_frac_feedback_div = frac_feedback_div;
+							best_freq = current_freq;
+							best_error = error;
+							best_vco_diff = vco_diff;
+						} else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
+							   ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
+							   ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
+							   ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
+							   ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
+							   ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
+							best_post_div = post_div;
+							best_ref_div = ref_div;
+							best_feedback_div = feedback_div;
+							best_frac_feedback_div = frac_feedback_div;
+							best_freq = current_freq;
+							best_error = error;
+							best_vco_diff = vco_diff;
+						}
+					}
+					if (current_freq < freq)
+						min_frac_feed_div = frac_feedback_div + 1;
+					else
+						max_frac_feed_div = frac_feedback_div;
+				}
+				if (current_freq < freq)
+					min_feed_div = feedback_div + 1;
+				else
+					max_feed_div = feedback_div;
+			}
+		}
+	}
+
+	*dot_clock_p = best_freq / 10000;
+	*fb_div_p = best_feedback_div;
+	*frac_fb_div_p = best_frac_feedback_div;
+	*ref_div_p = best_ref_div;
+	*post_div_p = best_post_div;
+}
+
+static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+	struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
+	struct drm_device *dev = fb->dev;
+
+	if (fb->fbdev)
+		radeonfb_remove(dev, fb);
+
+	if (radeon_fb->obj) {
+		radeon_gem_object_unpin(radeon_fb->obj);
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_unreference(radeon_fb->obj);
+		mutex_unlock(&dev->struct_mutex);
+	}
+	drm_framebuffer_cleanup(fb);
+	kfree(radeon_fb);
+}
+
+static int radeon_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+						  struct drm_file *file_priv,
+						  unsigned int *handle)
+{
+	struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
+
+	return drm_gem_handle_create(file_priv, radeon_fb->obj, handle);
+}
+
+static const struct drm_framebuffer_funcs radeon_fb_funcs = {
+	.destroy = radeon_user_framebuffer_destroy,
+	.create_handle = radeon_user_framebuffer_create_handle,
+};
+
+struct drm_framebuffer *
+radeon_framebuffer_create(struct drm_device *dev,
+			  struct drm_mode_fb_cmd *mode_cmd,
+			  struct drm_gem_object *obj)
+{
+	struct radeon_framebuffer *radeon_fb;
+
+	radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL);
+	if (radeon_fb == NULL) {
+		return NULL;
+	}
+	drm_framebuffer_init(dev, &radeon_fb->base, &radeon_fb_funcs);
+	drm_helper_mode_fill_fb_struct(&radeon_fb->base, mode_cmd);
+	radeon_fb->obj = obj;
+	return &radeon_fb->base;
+}
+
+static struct drm_framebuffer *
+radeon_user_framebuffer_create(struct drm_device *dev,
+			       struct drm_file *file_priv,
+			       struct drm_mode_fb_cmd *mode_cmd)
+{
+	struct drm_gem_object *obj;
+
+	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
+
+	return radeon_framebuffer_create(dev, mode_cmd, obj);
+}
+
+static const struct drm_mode_config_funcs radeon_mode_funcs = {
+	.fb_create = radeon_user_framebuffer_create,
+	.fb_changed = radeonfb_probe,
+};
+
+int radeon_modeset_init(struct radeon_device *rdev)
+{
+	int num_crtc = 2, i;
+	int ret;
+
+	drm_mode_config_init(rdev->ddev);
+	rdev->mode_info.mode_config_initialized = true;
+
+	rdev->ddev->mode_config.funcs = (void *)&radeon_mode_funcs;
+
+	if (ASIC_IS_AVIVO(rdev)) {
+		rdev->ddev->mode_config.max_width = 8192;
+		rdev->ddev->mode_config.max_height = 8192;
+	} else {
+		rdev->ddev->mode_config.max_width = 4096;
+		rdev->ddev->mode_config.max_height = 4096;
+	}
+
+	rdev->ddev->mode_config.fb_base = rdev->mc.aper_base;
+
+	/* allocate crtcs - TODO single crtc */
+	for (i = 0; i < num_crtc; i++) {
+		radeon_crtc_init(rdev->ddev, i);
+	}
+
+	/* okay we should have all the bios connectors */
+	ret = radeon_setup_enc_conn(rdev->ddev);
+	if (!ret) {
+		return ret;
+	}
+	drm_helper_initial_config(rdev->ddev);
+	return 0;
+}
+
+void radeon_modeset_fini(struct radeon_device *rdev)
+{
+	if (rdev->mode_info.mode_config_initialized) {
+		drm_mode_config_cleanup(rdev->ddev);
+		rdev->mode_info.mode_config_initialized = false;
+	}
+}
+
+bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_encoder *encoder;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_encoder *radeon_encoder;
+	bool first = true;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		radeon_encoder = to_radeon_encoder(encoder);
+		if (encoder->crtc != crtc)
+			continue;
+		if (first) {
+			radeon_crtc->rmx_type = radeon_encoder->rmx_type;
+			radeon_crtc->devices = radeon_encoder->devices;
+			memcpy(&radeon_crtc->native_mode,
+				&radeon_encoder->native_mode,
+				sizeof(struct radeon_native_mode));
+			first = false;
+		} else {
+			if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) {
+				/* WARNING: Right now this can't happen but
+				 * in the future we need to check that scaling
+				 * are consistent accross different encoder
+				 * (ie all encoder can work with the same
+				 *  scaling).
+				 */
+				DRM_ERROR("Scaling not consistent accross encoder.\n");
+				return false;
+			}
+		}
+	}
+	if (radeon_crtc->rmx_type != RMX_OFF) {
+		fixed20_12 a, b;
+		a.full = rfixed_const(crtc->mode.vdisplay);
+		b.full = rfixed_const(radeon_crtc->native_mode.panel_xres);
+		radeon_crtc->vsc.full = rfixed_div(a, b);
+		a.full = rfixed_const(crtc->mode.hdisplay);
+		b.full = rfixed_const(radeon_crtc->native_mode.panel_yres);
+		radeon_crtc->hsc.full = rfixed_div(a, b);
+	} else {
+		radeon_crtc->vsc.full = rfixed_const(1);
+		radeon_crtc->hsc.full = rfixed_const(1);
+	}
+	return true;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,12 +35,96 @@
 #include "radeon_drv.h"
 
 #include "drm_pciids.h"
+#include <linux/console.h>
+
+
+#if defined(CONFIG_DRM_RADEON_KMS)
+/*
+ * KMS wrapper.
+ */
+#define KMS_DRIVER_MAJOR	2
+#define KMS_DRIVER_MINOR	0
+#define KMS_DRIVER_PATCHLEVEL	0
+int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
+int radeon_driver_unload_kms(struct drm_device *dev);
+int radeon_driver_firstopen_kms(struct drm_device *dev);
+void radeon_driver_lastclose_kms(struct drm_device *dev);
+int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv);
+void radeon_driver_postclose_kms(struct drm_device *dev,
+				 struct drm_file *file_priv);
+void radeon_driver_preclose_kms(struct drm_device *dev,
+				struct drm_file *file_priv);
+int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
+int radeon_resume_kms(struct drm_device *dev);
+u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc);
+int radeon_enable_vblank_kms(struct drm_device *dev, int crtc);
+void radeon_disable_vblank_kms(struct drm_device *dev, int crtc);
+void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
+int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
+void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
+irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS);
+int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master);
+void radeon_master_destroy_kms(struct drm_device *dev,
+			       struct drm_master *master);
+int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int radeon_gem_object_init(struct drm_gem_object *obj);
+void radeon_gem_object_free(struct drm_gem_object *obj);
+extern struct drm_ioctl_desc radeon_ioctls_kms[];
+extern int radeon_max_kms_ioctl;
+int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
+#if defined(CONFIG_DEBUG_FS)
+int radeon_debugfs_init(struct drm_minor *minor);
+void radeon_debugfs_cleanup(struct drm_minor *minor);
+#endif
+#endif
+
 
 int radeon_no_wb;
+#if defined(CONFIG_DRM_RADEON_KMS)
+int radeon_modeset = -1;
+int radeon_dynclks = -1;
+int radeon_r4xx_atom = 0;
+int radeon_agpmode = 0;
+int radeon_vram_limit = 0;
+int radeon_gart_size = 512; /* default gart size */
+int radeon_benchmarking = 0;
+int radeon_testing = 0;
+int radeon_connector_table = 0;
+#endif
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
 
+#if defined(CONFIG_DRM_RADEON_KMS)
+MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
+module_param_named(modeset, radeon_modeset, int, 0400);
+
+MODULE_PARM_DESC(dynclks, "Disable/Enable dynamic clocks");
+module_param_named(dynclks, radeon_dynclks, int, 0444);
+
+MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx");
+module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444);
+
+MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing");
+module_param_named(vramlimit, radeon_vram_limit, int, 0600);
+
+MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)");
+module_param_named(agpmode, radeon_agpmode, int, 0444);
+
+MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32,64, etc)\n");
+module_param_named(gartsize, radeon_gart_size, int, 0600);
+
+MODULE_PARM_DESC(benchmark, "Run benchmark");
+module_param_named(benchmark, radeon_benchmarking, int, 0444);
+
+MODULE_PARM_DESC(test, "Run tests");
+module_param_named(test, radeon_testing, int, 0444);
+
+MODULE_PARM_DESC(connector_table, "Force connector table");
+module_param_named(connector_table, radeon_connector_table, int, 0444);
+#endif
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -73,7 +157,11 @@
 	radeon_PCI_IDS
 };
 
-static struct drm_driver driver = {
+#if defined(CONFIG_DRM_RADEON_KMS)
+MODULE_DEVICE_TABLE(pci, pciidlist);
+#endif
+
+static struct drm_driver driver_old = {
 	.driver_features =
 	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
 	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
@@ -127,15 +215,137 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+#if defined(CONFIG_DRM_RADEON_KMS)
+static struct drm_driver kms_driver;
+
+static int __devinit
+radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	return drm_get_dev(pdev, ent, &kms_driver);
+}
+
+static void
+radeon_pci_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_put_dev(dev);
+}
+
+static int
+radeon_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	return radeon_suspend_kms(dev, state);
+}
+
+static int
+radeon_pci_resume(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	return radeon_resume_kms(dev);
+}
+
+static struct drm_driver kms_driver = {
+	.driver_features =
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+	    DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_GEM,
+	.dev_priv_size = 0,
+	.load = radeon_driver_load_kms,
+	.firstopen = radeon_driver_firstopen_kms,
+	.open = radeon_driver_open_kms,
+	.preclose = radeon_driver_preclose_kms,
+	.postclose = radeon_driver_postclose_kms,
+	.lastclose = radeon_driver_lastclose_kms,
+	.unload = radeon_driver_unload_kms,
+	.suspend = radeon_suspend_kms,
+	.resume = radeon_resume_kms,
+	.get_vblank_counter = radeon_get_vblank_counter_kms,
+	.enable_vblank = radeon_enable_vblank_kms,
+	.disable_vblank = radeon_disable_vblank_kms,
+	.master_create = radeon_master_create_kms,
+	.master_destroy = radeon_master_destroy_kms,
+#if defined(CONFIG_DEBUG_FS)
+	.debugfs_init = radeon_debugfs_init,
+	.debugfs_cleanup = radeon_debugfs_cleanup,
+#endif
+	.irq_preinstall = radeon_driver_irq_preinstall_kms,
+	.irq_postinstall = radeon_driver_irq_postinstall_kms,
+	.irq_uninstall = radeon_driver_irq_uninstall_kms,
+	.irq_handler = radeon_driver_irq_handler_kms,
+	.reclaim_buffers = drm_core_reclaim_buffers,
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.ioctls = radeon_ioctls_kms,
+	.gem_init_object = radeon_gem_object_init,
+	.gem_free_object = radeon_gem_object_free,
+	.dma_ioctl = radeon_dma_ioctl_kms,
+	.fops = {
+		 .owner = THIS_MODULE,
+		 .open = drm_open,
+		 .release = drm_release,
+		 .ioctl = drm_ioctl,
+		 .mmap = radeon_mmap,
+		 .poll = drm_poll,
+		 .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+		 .compat_ioctl = NULL,
+#endif
+	},
+
+	.pci_driver = {
+		 .name = DRIVER_NAME,
+		 .id_table = pciidlist,
+		 .probe = radeon_pci_probe,
+		 .remove = radeon_pci_remove,
+		 .suspend = radeon_pci_suspend,
+		 .resume = radeon_pci_resume,
+	},
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = KMS_DRIVER_MAJOR,
+	.minor = KMS_DRIVER_MINOR,
+	.patchlevel = KMS_DRIVER_PATCHLEVEL,
+};
+#endif
+
+static struct drm_driver *driver;
+
 static int __init radeon_init(void)
 {
-	driver.num_ioctls = radeon_max_ioctl;
-	return drm_init(&driver);
+	driver = &driver_old;
+	driver->num_ioctls = radeon_max_ioctl;
+#if defined(CONFIG_DRM_RADEON_KMS)
+#ifdef CONFIG_VGA_CONSOLE
+	if (vgacon_text_force() && radeon_modeset == -1) {
+		DRM_INFO("VGACON disable radeon kernel modesetting.\n");
+		driver = &driver_old;
+		driver->driver_features &= ~DRIVER_MODESET;
+		radeon_modeset = 0;
+	}
+#endif
+	/* if enabled by default */
+	if (radeon_modeset == -1) {
+		DRM_INFO("radeon default to kernel modesetting.\n");
+		radeon_modeset = 1;
+	}
+	if (radeon_modeset == 1) {
+		DRM_INFO("radeon kernel modesetting enabled.\n");
+		driver = &kms_driver;
+		driver->driver_features |= DRIVER_MODESET;
+		driver->num_ioctls = radeon_max_kms_ioctl;
+	}
+	/* if the vga console setting is enabled still
+	 * let modprobe override it */
+#endif
+	return drm_init(driver);
 }
 
 static void __exit radeon_exit(void)
 {
-	drm_exit(&driver);
+	drm_exit(driver);
 }
 
 module_init(radeon_init);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_drv.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_drv.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_drv.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_drv.h	2009-09-09 18:13:59.000000000 -0400
@@ -100,9 +100,10 @@
  * 1.28- Add support for VBL on CRTC2
  * 1.29- R500 3D cmd buffer support
  * 1.30- Add support for occlusion queries
+ * 1.31- Add support for num Z pipes from GET_PARAM
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		30
+#define DRIVER_MINOR		31
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -143,9 +144,11 @@
 	CHIP_RV635,
 	CHIP_RV670,
 	CHIP_RS780,
+	CHIP_RS880,
 	CHIP_RV770,
 	CHIP_RV730,
 	CHIP_RV710,
+	CHIP_RV740,
 	CHIP_LAST,
 };
 
@@ -327,6 +330,7 @@
 	resource_size_t fb_aper_offset;
 
 	int num_gb_pipes;
+	int num_z_pipes;
 	int track_flush;
 	drm_local_map_t *mmio;
 
@@ -687,6 +691,7 @@
 
 /* pipe config regs */
 #define R400_GB_PIPE_SELECT             0x402c
+#define RV530_GB_PIPE_SELECT2           0x4124
 #define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
 #define R300_GB_TILE_CONFIG             0x4018
 #       define R300_ENABLE_TILING       (1 << 0)
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_encoders.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_encoders.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_encoders.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_encoders.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1353 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+extern int atom_debug;
+
+uint32_t
+radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t ret = 0;
+
+	switch (supported_device) {
+	case ATOM_DEVICE_CRT1_SUPPORT:
+	case ATOM_DEVICE_TV1_SUPPORT:
+	case ATOM_DEVICE_TV2_SUPPORT:
+	case ATOM_DEVICE_CRT2_SUPPORT:
+	case ATOM_DEVICE_CV_SUPPORT:
+		switch (dac) {
+		case 1: /* dac a */
+			if ((rdev->family == CHIP_RS300) ||
+			    (rdev->family == CHIP_RS400) ||
+			    (rdev->family == CHIP_RS480))
+				ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
+			else if (ASIC_IS_AVIVO(rdev))
+				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
+			else
+				ret = ENCODER_OBJECT_ID_INTERNAL_DAC1;
+			break;
+		case 2: /* dac b */
+			if (ASIC_IS_AVIVO(rdev))
+				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
+			else {
+				/*if (rdev->family == CHIP_R200)
+				  ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+				  else*/
+				ret = ENCODER_OBJECT_ID_INTERNAL_DAC2;
+			}
+			break;
+		case 3: /* external dac */
+			if (ASIC_IS_AVIVO(rdev))
+				ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
+			else
+				ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+			break;
+		}
+		break;
+	case ATOM_DEVICE_LCD1_SUPPORT:
+		if (ASIC_IS_AVIVO(rdev))
+			ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+		else
+			ret = ENCODER_OBJECT_ID_INTERNAL_LVDS;
+		break;
+	case ATOM_DEVICE_DFP1_SUPPORT:
+		if ((rdev->family == CHIP_RS300) ||
+		    (rdev->family == CHIP_RS400) ||
+		    (rdev->family == CHIP_RS480))
+			ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+		else if (ASIC_IS_AVIVO(rdev))
+			ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
+		else
+			ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1;
+		break;
+	case ATOM_DEVICE_LCD2_SUPPORT:
+	case ATOM_DEVICE_DFP2_SUPPORT:
+		if ((rdev->family == CHIP_RS600) ||
+		    (rdev->family == CHIP_RS690) ||
+		    (rdev->family == CHIP_RS740))
+			ret = ENCODER_OBJECT_ID_INTERNAL_DDI;
+		else if (ASIC_IS_AVIVO(rdev))
+			ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
+		else
+			ret = ENCODER_OBJECT_ID_INTERNAL_DVO1;
+		break;
+	case ATOM_DEVICE_DFP3_SUPPORT:
+		ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+		break;
+	}
+
+	return ret;
+}
+
+void
+radeon_link_encoder_connector(struct drm_device *dev)
+{
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct drm_encoder *encoder;
+	struct radeon_encoder *radeon_encoder;
+
+	/* walk the list and link encoders to connectors */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		radeon_connector = to_radeon_connector(connector);
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+			radeon_encoder = to_radeon_encoder(encoder);
+			if (radeon_encoder->devices & radeon_connector->devices)
+				drm_mode_connector_attach_encoder(connector, encoder);
+		}
+	}
+}
+
+static struct drm_connector *
+radeon_get_connector_for_encoder(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		radeon_connector = to_radeon_connector(connector);
+		if (radeon_encoder->devices & radeon_connector->devices)
+			return connector;
+	}
+	return NULL;
+}
+
+/* used for both atom and legacy */
+void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
+			   struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
+
+	if (mode->hdisplay < native_mode->panel_xres ||
+	    mode->vdisplay < native_mode->panel_yres) {
+		if (ASIC_IS_AVIVO(rdev)) {
+			adjusted_mode->hdisplay = native_mode->panel_xres;
+			adjusted_mode->vdisplay = native_mode->panel_yres;
+			adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank;
+			adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus;
+			adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width;
+			adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank;
+			adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus;
+			adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width;
+			/* update crtc values */
+			drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+			/* adjust crtc values */
+			adjusted_mode->crtc_hdisplay = native_mode->panel_xres;
+			adjusted_mode->crtc_vdisplay = native_mode->panel_yres;
+			adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank;
+			adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus;
+			adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width;
+			adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank;
+			adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus;
+			adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width;
+		} else {
+			adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank;
+			adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus;
+			adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width;
+			adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank;
+			adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus;
+			adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width;
+			/* update crtc values */
+			drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+			/* adjust crtc values */
+			adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank;
+			adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus;
+			adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width;
+			adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank;
+			adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus;
+			adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width;
+		}
+		adjusted_mode->flags = native_mode->flags;
+		adjusted_mode->clock = native_mode->dotclock;
+	}
+}
+
+
+static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	if (radeon_encoder->rmx_type != RMX_OFF)
+		radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
+
+	/* hw bug */
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
+	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
+		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
+
+	return true;
+}
+
+static void
+atombios_dac_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DAC_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0, num = 0;
+	/* fixme - fill in enc_priv for atom dac */
+	enum radeon_tv_std tv_std = TV_STD_NTSC;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
+		num = 1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
+		num = 2;
+		break;
+	}
+
+	args.ucAction = action;
+
+	if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
+		args.ucDacStandard = ATOM_DAC1_PS2;
+	else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+		args.ucDacStandard = ATOM_DAC1_CV;
+	else {
+		switch (tv_std) {
+		case TV_STD_PAL:
+		case TV_STD_PAL_M:
+		case TV_STD_SCART_PAL:
+		case TV_STD_SECAM:
+		case TV_STD_PAL_CN:
+			args.ucDacStandard = ATOM_DAC1_PAL;
+			break;
+		case TV_STD_NTSC:
+		case TV_STD_NTSC_J:
+		case TV_STD_PAL_60:
+		default:
+			args.ucDacStandard = ATOM_DAC1_NTSC;
+			break;
+		}
+	}
+	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+static void
+atombios_tv_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	TV_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+	/* fixme - fill in enc_priv for atom dac */
+	enum radeon_tv_std tv_std = TV_STD_NTSC;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
+
+	args.sTVEncoder.ucAction = action;
+
+	if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
+	else {
+		switch (tv_std) {
+		case TV_STD_NTSC:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+			break;
+		case TV_STD_PAL:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL;
+			break;
+		case TV_STD_PAL_M:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PALM;
+			break;
+		case TV_STD_PAL_60:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60;
+			break;
+		case TV_STD_NTSC_J:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ;
+			break;
+		case TV_STD_SCART_PAL:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */
+			break;
+		case TV_STD_SECAM:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM;
+			break;
+		case TV_STD_PAL_CN:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN;
+			break;
+		default:
+			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
+			break;
+		}
+	}
+
+	args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+void
+atombios_external_tmds_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args;
+	int index = 0;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
+
+	args.sXTmdsEncoder.ucEnable = action;
+
+	if (radeon_encoder->pixel_clock > 165000)
+		args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL;
+
+	/*if (pScrn->rgbBits == 8)*/
+	args.sXTmdsEncoder.ucMisc |= (1 << 1);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+static void
+atombios_ddia_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DVO_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
+
+	args.sDVOEncoder.ucAction = action;
+	args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	if (radeon_encoder->pixel_clock > 165000)
+		args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union lvds_encoder_control {
+	LVDS_ENCODER_CONTROL_PS_ALLOCATION    v1;
+	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
+};
+
+static void
+atombios_digital_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	union lvds_encoder_control args;
+	int index = 0;
+	uint8_t frev, crev;
+	struct radeon_encoder_atom_dig *dig;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+
+	connector = radeon_get_connector_for_encoder(encoder);
+	if (!connector)
+		return;
+
+	radeon_connector = to_radeon_connector(connector);
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	dig = radeon_encoder->enc_priv;
+
+	if (!radeon_connector->con_priv)
+		return;
+
+	dig_connector = radeon_connector->con_priv;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
+		break;
+	}
+
+	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+
+	switch (frev) {
+	case 1:
+	case 2:
+		switch (crev) {
+		case 1:
+			args.v1.ucMisc = 0;
+			args.v1.ucAction = action;
+			if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+				if (dig->lvds_misc & (1 << 0))
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				if (dig->lvds_misc & (1 << 1))
+					args.v1.ucMisc |= (1 << 1);
+			} else {
+				if (dig_connector->linkb)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				/*if (pScrn->rgbBits == 8) */
+				args.v1.ucMisc |= (1 << 1);
+			}
+			break;
+		case 2:
+		case 3:
+			args.v2.ucMisc = 0;
+			args.v2.ucAction = action;
+			if (crev == 3) {
+				if (dig->coherent_mode)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
+			}
+			if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+			args.v2.ucTruncate = 0;
+			args.v2.ucSpatial = 0;
+			args.v2.ucTemporal = 0;
+			args.v2.ucFRC = 0;
+			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+				if (dig->lvds_misc & (1 << 0))
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+				if (dig->lvds_misc & (1 << 5)) {
+					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
+					if (dig->lvds_misc & (1 << 1))
+						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
+				}
+				if (dig->lvds_misc & (1 << 6)) {
+					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
+					if (dig->lvds_misc & (1 << 1))
+						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
+					if (((dig->lvds_misc >> 2) & 0x3) == 2)
+						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
+				}
+			} else {
+				if (dig_connector->linkb)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+int
+atombios_get_encoder_mode(struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+
+	connector = radeon_get_connector_for_encoder(encoder);
+	if (!connector)
+		return 0;
+
+	radeon_connector = to_radeon_connector(connector);
+
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_DVII:
+		if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+			return ATOM_ENCODER_MODE_HDMI;
+		else if (radeon_connector->use_digital)
+			return ATOM_ENCODER_MODE_DVI;
+		else
+			return ATOM_ENCODER_MODE_CRT;
+		break;
+	case DRM_MODE_CONNECTOR_DVID:
+	case DRM_MODE_CONNECTOR_HDMIA:
+	case DRM_MODE_CONNECTOR_HDMIB:
+	default:
+		if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+			return ATOM_ENCODER_MODE_HDMI;
+		else
+			return ATOM_ENCODER_MODE_DVI;
+		break;
+	case DRM_MODE_CONNECTOR_LVDS:
+		return ATOM_ENCODER_MODE_LVDS;
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		/*if (radeon_output->MonType == MT_DP)
+		  return ATOM_ENCODER_MODE_DP;
+		  else*/
+		if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
+			return ATOM_ENCODER_MODE_HDMI;
+		else
+			return ATOM_ENCODER_MODE_DVI;
+		break;
+	case CONNECTOR_DVI_A:
+	case CONNECTOR_VGA:
+		return ATOM_ENCODER_MODE_CRT;
+		break;
+	case CONNECTOR_STV:
+	case CONNECTOR_CTV:
+	case CONNECTOR_DIN:
+		/* fix me */
+		return ATOM_ENCODER_MODE_TV;
+		/*return ATOM_ENCODER_MODE_CV;*/
+		break;
+	}
+}
+
+static void
+atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DIG_ENCODER_CONTROL_PS_ALLOCATION args;
+	int index = 0, num = 0;
+	uint8_t frev, crev;
+	struct radeon_encoder_atom_dig *dig;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+
+	connector = radeon_get_connector_for_encoder(encoder);
+	if (!connector)
+		return;
+
+	radeon_connector = to_radeon_connector(connector);
+
+	if (!radeon_connector->con_priv)
+		return;
+
+	dig_connector = radeon_connector->con_priv;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	dig = radeon_encoder->enc_priv;
+
+	memset(&args, 0, sizeof(args));
+
+	if (ASIC_IS_DCE32(rdev)) {
+		if (dig->dig_block)
+			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+		num = dig->dig_block + 1;
+	} else {
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+			num = 1;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+			num = 2;
+			break;
+		}
+	}
+
+	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+
+	args.ucAction = action;
+	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+
+	if (ASIC_IS_DCE32(rdev)) {
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
+			break;
+		}
+	} else {
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+			args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2;
+			break;
+		}
+	}
+
+	if (radeon_encoder->pixel_clock > 165000) {
+		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
+		args.ucLaneNum = 8;
+	} else {
+		if (dig_connector->linkb)
+			args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+		else
+			args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
+		args.ucLaneNum = 4;
+	}
+
+	args.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+union dig_transmitter_control {
+	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
+};
+
+static void
+atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	union dig_transmitter_control args;
+	int index = 0, num = 0;
+	uint8_t frev, crev;
+	struct radeon_encoder_atom_dig *dig;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+
+	connector = radeon_get_connector_for_encoder(encoder);
+	if (!connector)
+		return;
+
+	radeon_connector = to_radeon_connector(connector);
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	dig = radeon_encoder->enc_priv;
+
+	if (!radeon_connector->con_priv)
+		return;
+
+	dig_connector = radeon_connector->con_priv;
+
+	memset(&args, 0, sizeof(args));
+
+	if (ASIC_IS_DCE32(rdev))
+		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+	else {
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+			index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
+			break;
+		}
+	}
+
+	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+
+	args.v1.ucAction = action;
+
+	if (ASIC_IS_DCE32(rdev)) {
+		if (radeon_encoder->pixel_clock > 165000) {
+			args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 2) / 100);
+			args.v2.acConfig.fDualLinkConnector = 1;
+		} else {
+			args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 4) / 100);
+		}
+		if (dig->dig_block)
+			args.v2.acConfig.ucEncoderSel = 1;
+
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			args.v2.acConfig.ucTransmitterSel = 0;
+			num = 0;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			args.v2.acConfig.ucTransmitterSel = 1;
+			num = 1;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			args.v2.acConfig.ucTransmitterSel = 2;
+			num = 2;
+			break;
+		}
+
+		if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+			if (dig->coherent_mode)
+				args.v2.acConfig.fCoherentMode = 1;
+		}
+	} else {
+		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
+		args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock) / 10);
+
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
+			if (rdev->flags & RADEON_IS_IGP) {
+				if (radeon_encoder->pixel_clock > 165000) {
+					args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
+							     ATOM_TRANSMITTER_CONFIG_LINKA_B);
+					if (dig_connector->igp_lane_info & 0x3)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
+					else if (dig_connector->igp_lane_info & 0xc)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
+				} else {
+					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
+					if (dig_connector->igp_lane_info & 0x1)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+					else if (dig_connector->igp_lane_info & 0x2)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
+					else if (dig_connector->igp_lane_info & 0x4)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
+					else if (dig_connector->igp_lane_info & 0x8)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
+				}
+			} else {
+				if (radeon_encoder->pixel_clock > 165000)
+					args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
+							     ATOM_TRANSMITTER_CONFIG_LINKA_B |
+							     ATOM_TRANSMITTER_CONFIG_LANE_0_7);
+				else {
+					if (dig_connector->linkb)
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+					else
+						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+				}
+			}
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
+			if (radeon_encoder->pixel_clock > 165000)
+				args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
+						     ATOM_TRANSMITTER_CONFIG_LINKA_B |
+						     ATOM_TRANSMITTER_CONFIG_LANE_0_7);
+			else {
+				if (dig_connector->linkb)
+					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+				else
+					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
+			}
+			break;
+		}
+
+		if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+			if (dig->coherent_mode)
+				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+		}
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+static void
+atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	ENABLE_YUV_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, EnableYUV);
+	uint32_t temp, reg;
+
+	memset(&args, 0, sizeof(args));
+
+	if (rdev->family >= CHIP_R600)
+		reg = R600_BIOS_3_SCRATCH;
+	else
+		reg = RADEON_BIOS_3_SCRATCH;
+
+	/* XXX: fix up scratch reg handling */
+	temp = RREG32(reg);
+	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
+		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
+			     (radeon_crtc->crtc_id << 18)));
+	else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
+	else
+		WREG32(reg, 0);
+
+	if (enable)
+		args.ucEnable = ATOM_ENABLE;
+	args.ucCRTC = radeon_crtc->crtc_id;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	WREG32(reg, temp);
+}
+
+static void
+radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
+	int index = 0;
+	bool is_dig = false;
+
+	memset(&args, 0, sizeof(args));
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		is_dig = true;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+		else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+		else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
+		break;
+	}
+
+	if (is_dig) {
+		switch (mode) {
+		case DRM_MODE_DPMS_ON:
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
+			break;
+		case DRM_MODE_DPMS_STANDBY:
+		case DRM_MODE_DPMS_SUSPEND:
+		case DRM_MODE_DPMS_OFF:
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
+			break;
+		}
+	} else {
+		switch (mode) {
+		case DRM_MODE_DPMS_ON:
+			args.ucAction = ATOM_ENABLE;
+			break;
+		case DRM_MODE_DPMS_STANDBY:
+		case DRM_MODE_DPMS_SUSPEND:
+		case DRM_MODE_DPMS_OFF:
+			args.ucAction = ATOM_DISABLE;
+			break;
+		}
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+	}
+	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+}
+
+union crtc_sourc_param {
+	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
+	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
+};
+
+static void
+atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	union crtc_sourc_param args;
+	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
+	uint8_t frev, crev;
+
+	memset(&args, 0, sizeof(args));
+
+	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 1:
+		default:
+			if (ASIC_IS_AVIVO(rdev))
+				args.v1.ucCRTC = radeon_crtc->crtc_id;
+			else {
+				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) {
+					args.v1.ucCRTC = radeon_crtc->crtc_id;
+				} else {
+					args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
+				}
+			}
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+				args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+			case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+				if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT)
+					args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+			case ENCODER_OBJECT_ID_INTERNAL_DDI:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+				args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
+				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
+				else
+					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
+				break;
+			}
+			break;
+		case 2:
+			args.v2.ucCRTC = radeon_crtc->crtc_id;
+			args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder);
+			switch (radeon_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				if (ASIC_IS_DCE32(rdev)) {
+					if (radeon_crtc->crtc_id)
+						args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+					else
+						args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+				} else
+					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+				args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else
+					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
+					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+				else
+					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
+				break;
+			}
+			break;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version: %d, %d\n", frev, crev);
+		break;
+	}
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+}
+
+static void
+atombios_apply_encoder_quirks(struct drm_encoder *encoder,
+			      struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+
+	/* Funky macbooks */
+	if ((dev->pdev->device == 0x71C5) &&
+	    (dev->pdev->subsystem_vendor == 0x106b) &&
+	    (dev->pdev->subsystem_device == 0x0080)) {
+		if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) {
+			uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL);
+
+			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN;
+			lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN;
+
+			WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control);
+		}
+	}
+
+	/* set scaler clears this on some chips */
+	if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
+		WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN);
+}
+
+static void
+radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+
+	if (radeon_encoder->enc_priv) {
+		struct radeon_encoder_atom_dig *dig;
+
+		dig = radeon_encoder->enc_priv;
+		dig->dig_block = radeon_crtc->crtc_id;
+	}
+	radeon_encoder->pixel_clock = adjusted_mode->clock;
+
+	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+	atombios_set_encoder_crtc_source(encoder);
+
+	if (ASIC_IS_AVIVO(rdev)) {
+		if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
+			atombios_yuv_setup(encoder, true);
+		else
+			atombios_yuv_setup(encoder, false);
+	}
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		/* disable the encoder and transmitter */
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
+		atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
+
+		/* setup and enable the encoder and transmitter */
+		atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP);
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+		atombios_ddia_setup(encoder, ATOM_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		atombios_external_tmds_setup(encoder, ATOM_ENABLE);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		atombios_dac_setup(encoder, ATOM_ENABLE);
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+			atombios_tv_setup(encoder, ATOM_ENABLE);
+		break;
+	}
+	atombios_apply_encoder_quirks(encoder, adjusted_mode);
+}
+
+static bool
+atombios_dac_load_detect(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
+				       ATOM_DEVICE_CV_SUPPORT |
+				       ATOM_DEVICE_CRT_SUPPORT)) {
+		DAC_LOAD_DETECTION_PS_ALLOCATION args;
+		int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
+		uint8_t frev, crev;
+
+		memset(&args, 0, sizeof(args));
+
+		atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
+
+		args.sDacload.ucMisc = 0;
+
+		if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) ||
+		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1))
+			args.sDacload.ucDacType = ATOM_DAC_A;
+		else
+			args.sDacload.ucDacType = ATOM_DAC_B;
+
+		if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT)
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
+		else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT)
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
+		else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
+			if (crev >= 3)
+				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+		} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
+			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
+			if (crev >= 3)
+				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
+		}
+
+		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+		return true;
+	} else
+		return false;
+}
+
+static enum drm_connector_status
+radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t bios_0_scratch;
+
+	if (!atombios_dac_load_detect(encoder)) {
+		DRM_DEBUG("detect returned false \n");
+		return connector_status_unknown;
+	}
+
+	if (rdev->family >= CHIP_R600)
+		bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+	else
+		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
+
+	DRM_DEBUG("Bios 0 scratch %x\n", bios_0_scratch);
+	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+			return connector_status_connected;
+	} else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+			return connector_status_connected;
+	} else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+			return connector_status_connected;
+	} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
+		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+			return connector_status_connected; /* CTV */
+		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+			return connector_status_connected; /* STV */
+	}
+	return connector_status_disconnected;
+}
+
+static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
+{
+	radeon_atom_output_lock(encoder, true);
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
+{
+	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+	radeon_atom_output_lock(encoder, false);
+}
+
+static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
+	.dpms = radeon_atom_encoder_dpms,
+	.mode_fixup = radeon_atom_mode_fixup,
+	.prepare = radeon_atom_encoder_prepare,
+	.mode_set = radeon_atom_encoder_mode_set,
+	.commit = radeon_atom_encoder_commit,
+	/* no detect for TMDS/LVDS yet */
+};
+
+static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
+	.dpms = radeon_atom_encoder_dpms,
+	.mode_fixup = radeon_atom_mode_fixup,
+	.prepare = radeon_atom_encoder_prepare,
+	.mode_set = radeon_atom_encoder_mode_set,
+	.commit = radeon_atom_encoder_commit,
+	.detect = radeon_atom_dac_detect,
+};
+
+void radeon_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	kfree(radeon_encoder->enc_priv);
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
+
+static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+struct radeon_encoder_atom_dig *
+radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
+{
+	struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
+
+	if (!dig)
+		return NULL;
+
+	/* coherent mode by default */
+	dig->coherent_mode = true;
+
+	return dig;
+}
+
+void
+radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
+{
+	struct drm_encoder *encoder;
+	struct radeon_encoder *radeon_encoder;
+
+	/* see if we already added it */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		radeon_encoder = to_radeon_encoder(encoder);
+		if (radeon_encoder->encoder_id == encoder_id) {
+			radeon_encoder->devices |= supported_device;
+			return;
+		}
+
+	}
+
+	/* add a new one */
+	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
+	if (!radeon_encoder)
+		return;
+
+	encoder = &radeon_encoder->base;
+	encoder->possible_crtcs = 0x3;
+	encoder->possible_clones = 0;
+
+	radeon_encoder->enc_priv = NULL;
+
+	radeon_encoder->encoder_id = encoder_id;
+	radeon_encoder->devices = supported_device;
+	radeon_encoder->rmx_type = RMX_OFF;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+			radeon_encoder->rmx_type = RMX_FULL;
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
+			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+		} else {
+			drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+			radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		}
+		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC);
+		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
+		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
+		radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
+		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
+		break;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_fb.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_fb.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_fb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_fb.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,896 @@
+/*
+ * Copyright © 2007 David Airlie
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     David Airlie
+ */
+    /*
+     *  Modularization
+     */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+struct radeon_fb_device {
+	struct radeon_device		*rdev;
+	struct drm_display_mode		*mode;
+	struct radeon_framebuffer	*rfb;
+	int				crtc_count;
+	/* crtc currently bound to this */
+	uint32_t			crtc_ids[2];
+};
+
+static int radeonfb_setcolreg(unsigned regno,
+			      unsigned red,
+			      unsigned green,
+			      unsigned blue,
+			      unsigned transp,
+			      struct fb_info *info)
+{
+	struct radeon_fb_device *rfbdev = info->par;
+	struct drm_device *dev = rfbdev->rdev->ddev;
+	struct drm_crtc *crtc;
+	int i;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+		struct drm_mode_set *modeset = &radeon_crtc->mode_set;
+		struct drm_framebuffer *fb = modeset->fb;
+
+		for (i = 0; i < rfbdev->crtc_count; i++) {
+			if (crtc->base.id == rfbdev->crtc_ids[i]) {
+				break;
+			}
+		}
+		if (i == rfbdev->crtc_count) {
+			continue;
+		}
+		if (regno > 255) {
+			return 1;
+		}
+		if (fb->depth == 8) {
+			radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno);
+			return 0;
+		}
+
+		if (regno < 16) {
+			switch (fb->depth) {
+			case 15:
+				fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
+					((green & 0xf800) >>  6) |
+					((blue & 0xf800) >> 11);
+				break;
+			case 16:
+				fb->pseudo_palette[regno] = (red & 0xf800) |
+					((green & 0xfc00) >>  5) |
+					((blue  & 0xf800) >> 11);
+				break;
+			case 24:
+			case 32:
+				fb->pseudo_palette[regno] =
+					(((red >> 8) & 0xff) << info->var.red.offset) |
+					(((green >> 8) & 0xff) << info->var.green.offset) |
+					(((blue >> 8) & 0xff) << info->var.blue.offset);
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int radeonfb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct radeon_fb_device *rfbdev = info->par;
+	struct radeon_framebuffer *rfb = rfbdev->rfb;
+	struct drm_framebuffer *fb = &rfb->base;
+	int depth;
+
+	if (var->pixclock == -1 || !var->pixclock) {
+		return -EINVAL;
+	}
+	/* Need to resize the fb object !!! */
+	if (var->xres > fb->width || var->yres > fb->height) {
+		DRM_ERROR("Requested width/height is greater than current fb "
+			   "object %dx%d > %dx%d\n", var->xres, var->yres,
+			   fb->width, fb->height);
+		DRM_ERROR("Need resizing code.\n");
+		return -EINVAL;
+	}
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		depth = (var->green.length == 6) ? 16 : 15;
+		break;
+	case 32:
+		depth = (var->transp.length > 0) ? 32 : 24;
+		break;
+	default:
+		depth = var->bits_per_pixel;
+		break;
+	}
+
+	switch (depth) {
+	case 8:
+		var->red.offset = 0;
+		var->green.offset = 0;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		break;
+#ifdef __LITTLE_ENDIAN
+	case 15:
+		var->red.offset = 10;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		var->transp.length = 1;
+		var->transp.offset = 15;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		break;
+	case 24:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		break;
+#else
+	case 24:
+		var->red.offset = 8;
+		var->green.offset = 16;
+		var->blue.offset = 24;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		break;
+	case 32:
+		var->red.offset = 8;
+		var->green.offset = 16;
+		var->blue.offset = 24;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 8;
+		var->transp.offset = 0;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* this will let fbcon do the mode init */
+static int radeonfb_set_par(struct fb_info *info)
+{
+	struct radeon_fb_device *rfbdev = info->par;
+	struct drm_device *dev = rfbdev->rdev->ddev;
+	struct fb_var_screeninfo *var = &info->var;
+	struct drm_crtc *crtc;
+	int ret;
+	int i;
+
+	if (var->pixclock != -1) {
+		DRM_ERROR("PIXEL CLCOK SET\n");
+		return -EINVAL;
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+		for (i = 0; i < rfbdev->crtc_count; i++) {
+			if (crtc->base.id == rfbdev->crtc_ids[i]) {
+				break;
+			}
+		}
+		if (i == rfbdev->crtc_count) {
+			continue;
+		}
+		if (crtc->fb == radeon_crtc->mode_set.fb) {
+			mutex_lock(&dev->mode_config.mutex);
+			ret = crtc->funcs->set_config(&radeon_crtc->mode_set);
+			mutex_unlock(&dev->mode_config.mutex);
+			if (ret) {
+				return ret;
+			}
+		}
+	}
+	return 0;
+}
+
+static int radeonfb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct radeon_fb_device *rfbdev = info->par;
+	struct drm_device *dev = rfbdev->rdev->ddev;
+	struct drm_mode_set *modeset;
+	struct drm_crtc *crtc;
+	struct radeon_crtc *radeon_crtc;
+	int ret = 0;
+	int i;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		for (i = 0; i < rfbdev->crtc_count; i++) {
+			if (crtc->base.id == rfbdev->crtc_ids[i]) {
+				break;
+			}
+		}
+
+		if (i == rfbdev->crtc_count) {
+			continue;
+		}
+
+		radeon_crtc = to_radeon_crtc(crtc);
+		modeset = &radeon_crtc->mode_set;
+
+		modeset->x = var->xoffset;
+		modeset->y = var->yoffset;
+
+		if (modeset->num_connectors) {
+			mutex_lock(&dev->mode_config.mutex);
+			ret = crtc->funcs->set_config(modeset);
+			mutex_unlock(&dev->mode_config.mutex);
+			if (!ret) {
+				info->var.xoffset = var->xoffset;
+				info->var.yoffset = var->yoffset;
+			}
+		}
+	}
+	return ret;
+}
+
+static void radeonfb_on(struct fb_info *info)
+{
+	struct radeon_fb_device *rfbdev = info->par;
+	struct drm_device *dev = rfbdev->rdev->ddev;
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	int i;
+
+	/*
+	 * For each CRTC in this fb, find all associated encoders
+	 * and turn them off, then turn off the CRTC.
+	 */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+		for (i = 0; i < rfbdev->crtc_count; i++) {
+			if (crtc->base.id == rfbdev->crtc_ids[i]) {
+				break;
+			}
+		}
+
+		mutex_lock(&dev->mode_config.mutex);
+		crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+		mutex_unlock(&dev->mode_config.mutex);
+
+		/* Found a CRTC on this fb, now find encoders */
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+			if (encoder->crtc == crtc) {
+				struct drm_encoder_helper_funcs *encoder_funcs;
+
+				encoder_funcs = encoder->helper_private;
+				mutex_lock(&dev->mode_config.mutex);
+				encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+				mutex_unlock(&dev->mode_config.mutex);
+			}
+		}
+	}
+}
+
+static void radeonfb_off(struct fb_info *info, int dpms_mode)
+{
+	struct radeon_fb_device *rfbdev = info->par;
+	struct drm_device *dev = rfbdev->rdev->ddev;
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	int i;
+
+	/*
+	 * For each CRTC in this fb, find all associated encoders
+	 * and turn them off, then turn off the CRTC.
+	 */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+		for (i = 0; i < rfbdev->crtc_count; i++) {
+			if (crtc->base.id == rfbdev->crtc_ids[i]) {
+				break;
+			}
+		}
+
+		/* Found a CRTC on this fb, now find encoders */
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+			if (encoder->crtc == crtc) {
+				struct drm_encoder_helper_funcs *encoder_funcs;
+
+				encoder_funcs = encoder->helper_private;
+				mutex_lock(&dev->mode_config.mutex);
+				encoder_funcs->dpms(encoder, dpms_mode);
+				mutex_unlock(&dev->mode_config.mutex);
+			}
+		}
+		if (dpms_mode == DRM_MODE_DPMS_OFF) {
+			mutex_lock(&dev->mode_config.mutex);
+			crtc_funcs->dpms(crtc, dpms_mode);
+			mutex_unlock(&dev->mode_config.mutex);
+		}
+	}
+}
+
+int radeonfb_blank(int blank, struct fb_info *info)
+{
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		radeonfb_on(info);
+		break;
+	case FB_BLANK_NORMAL:
+		radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		radeonfb_off(info, DRM_MODE_DPMS_SUSPEND);
+		break;
+	case FB_BLANK_POWERDOWN:
+		radeonfb_off(info, DRM_MODE_DPMS_OFF);
+		break;
+	}
+	return 0;
+}
+
+static struct fb_ops radeonfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = radeonfb_check_var,
+	.fb_set_par = radeonfb_set_par,
+	.fb_setcolreg = radeonfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_pan_display = radeonfb_pan_display,
+	.fb_blank = radeonfb_blank,
+};
+
+/**
+ * Curretly it is assumed that the old framebuffer is reused.
+ *
+ * LOCKING
+ * caller should hold the mode config lock.
+ *
+ */
+int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
+{
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	struct drm_display_mode *mode = crtc->desired_mode;
+
+	fb = crtc->fb;
+	if (fb == NULL) {
+		return 1;
+	}
+	info = fb->fbdev;
+	if (info == NULL) {
+		return 1;
+	}
+	if (mode == NULL) {
+		return 1;
+	}
+	info->var.xres = mode->hdisplay;
+	info->var.right_margin = mode->hsync_start - mode->hdisplay;
+	info->var.hsync_len = mode->hsync_end - mode->hsync_start;
+	info->var.left_margin = mode->htotal - mode->hsync_end;
+	info->var.yres = mode->vdisplay;
+	info->var.lower_margin = mode->vsync_start - mode->vdisplay;
+	info->var.vsync_len = mode->vsync_end - mode->vsync_start;
+	info->var.upper_margin = mode->vtotal - mode->vsync_end;
+	info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100;
+	/* avoid overflow */
+	info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
+
+	return 0;
+}
+EXPORT_SYMBOL(radeonfb_resize);
+
+static struct drm_mode_set panic_mode;
+
+int radeonfb_panic(struct notifier_block *n, unsigned long ununsed,
+		  void *panic_str)
+{
+	DRM_ERROR("panic occurred, switching back to text console\n");
+	drm_crtc_helper_set_config(&panic_mode);
+	return 0;
+}
+EXPORT_SYMBOL(radeonfb_panic);
+
+static struct notifier_block paniced = {
+	.notifier_call = radeonfb_panic,
+};
+
+static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
+{
+	int aligned = width;
+	int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
+	int pitch_mask = 0;
+
+	switch (bpp / 8) {
+	case 1:
+		pitch_mask = align_large ? 255 : 127;
+		break;
+	case 2:
+		pitch_mask = align_large ? 127 : 31;
+		break;
+	case 3:
+	case 4:
+		pitch_mask = align_large ? 63 : 15;
+		break;
+	}
+
+	aligned += pitch_mask;
+	aligned &= ~pitch_mask;
+	return aligned;
+}
+
+int radeonfb_create(struct radeon_device *rdev,
+		    uint32_t fb_width, uint32_t fb_height,
+		    uint32_t surface_width, uint32_t surface_height,
+		    struct radeon_framebuffer **rfb_p)
+{
+	struct fb_info *info;
+	struct radeon_fb_device *rfbdev;
+	struct drm_framebuffer *fb = NULL;
+	struct radeon_framebuffer *rfb;
+	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_gem_object *gobj = NULL;
+	struct radeon_object *robj = NULL;
+	struct device *device = &rdev->pdev->dev;
+	int size, aligned_size, ret;
+	u64 fb_gpuaddr;
+	void *fbptr = NULL;
+	unsigned long tmp;
+	bool fb_tiled = false; /* useful for testing */
+
+	mode_cmd.width = surface_width;
+	mode_cmd.height = surface_height;
+	mode_cmd.bpp = 32;
+	/* need to align pitch with crtc limits */
+	mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
+	mode_cmd.depth = 24;
+
+	size = mode_cmd.pitch * mode_cmd.height;
+	aligned_size = ALIGN(size, PAGE_SIZE);
+
+	ret = radeon_gem_object_create(rdev, aligned_size, 0,
+			RADEON_GEM_DOMAIN_VRAM,
+			false, ttm_bo_type_kernel,
+			false, &gobj);
+	if (ret) {
+		printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
+		       surface_width, surface_height);
+		ret = -ENOMEM;
+		goto out;
+	}
+	robj = gobj->driver_private;
+
+	if (fb_tiled)
+		radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch);
+	mutex_lock(&rdev->ddev->struct_mutex);
+	fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
+	if (fb == NULL) {
+		DRM_ERROR("failed to allocate fb.\n");
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+	ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
+	if (ret) {
+		printk(KERN_ERR "failed to pin framebuffer\n");
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+
+	list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
+
+	rfb = to_radeon_framebuffer(fb);
+	*rfb_p = rfb;
+	rdev->fbdev_rfb = rfb;
+	rdev->fbdev_robj = robj;
+
+	info = framebuffer_alloc(sizeof(struct radeon_fb_device), device);
+	if (info == NULL) {
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+	rfbdev = info->par;
+
+	if (fb_tiled)
+		radeon_object_check_tiling(robj, 0, 0);
+
+	ret = radeon_object_kmap(robj, &fbptr);
+	if (ret) {
+		goto out_unref;
+	}
+
+	memset_io(fbptr, 0, aligned_size);
+
+	strcpy(info->fix.id, "radeondrmfb");
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 1; /* doing it in hw */
+	info->fix.ypanstep = 1; /* doing it in hw */
+	info->fix.ywrapstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->fix.type_aux = 0;
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &radeonfb_ops;
+	info->fix.line_length = fb->pitch;
+	tmp = fb_gpuaddr - rdev->mc.vram_location;
+	info->fix.smem_start = rdev->mc.aper_base + tmp;
+	info->fix.smem_len = size;
+	info->screen_base = fbptr;
+	info->screen_size = size;
+	info->pseudo_palette = fb->pseudo_palette;
+	info->var.xres_virtual = fb->width;
+	info->var.yres_virtual = fb->height;
+	info->var.bits_per_pixel = fb->bits_per_pixel;
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->var.height = -1;
+	info->var.width = -1;
+	info->var.xres = fb_width;
+	info->var.yres = fb_height;
+
+	/* setup aperture base/size for vesafb takeover */
+	info->aperture_base = rdev->ddev->mode_config.fb_base;
+	info->aperture_size = rdev->mc.real_vram_size;
+
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+	info->pixmap.size = 64*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+	if (info->screen_base == NULL) {
+		ret = -ENOSPC;
+		goto out_unref;
+	}
+	DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
+	DRM_INFO("vram apper at 0x%lX\n",  (unsigned long)rdev->mc.aper_base);
+	DRM_INFO("size %lu\n", (unsigned long)size);
+	DRM_INFO("fb depth is %d\n", fb->depth);
+	DRM_INFO("   pitch is %d\n", fb->pitch);
+
+	switch (fb->depth) {
+	case 8:
+		info->var.red.offset = 0;
+		info->var.green.offset = 0;
+		info->var.blue.offset = 0;
+		info->var.red.length = 8; /* 8bit DAC */
+		info->var.green.length = 8;
+		info->var.blue.length = 8;
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		break;
+#ifdef __LITTLE_ENDIAN
+	case 15:
+		info->var.red.offset = 10;
+		info->var.green.offset = 5;
+		info->var.blue.offset = 0;
+		info->var.red.length = 5;
+		info->var.green.length = 5;
+		info->var.blue.length = 5;
+		info->var.transp.offset = 15;
+		info->var.transp.length = 1;
+		break;
+	case 16:
+		info->var.red.offset = 11;
+		info->var.green.offset = 5;
+		info->var.blue.offset = 0;
+		info->var.red.length = 5;
+		info->var.green.length = 6;
+		info->var.blue.length = 5;
+		info->var.transp.offset = 0;
+		break;
+	case 24:
+		info->var.red.offset = 16;
+		info->var.green.offset = 8;
+		info->var.blue.offset = 0;
+		info->var.red.length = 8;
+		info->var.green.length = 8;
+		info->var.blue.length = 8;
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		break;
+	case 32:
+		info->var.red.offset = 16;
+		info->var.green.offset = 8;
+		info->var.blue.offset = 0;
+		info->var.red.length = 8;
+		info->var.green.length = 8;
+		info->var.blue.length = 8;
+		info->var.transp.offset = 24;
+		info->var.transp.length = 8;
+		break;
+#else
+	case 24:
+		info->var.red.offset = 8;
+		info->var.green.offset = 16;
+		info->var.blue.offset = 24;
+		info->var.red.length = 8;
+		info->var.green.length = 8;
+		info->var.blue.length = 8;
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		break;
+	case 32:
+		info->var.red.offset = 8;
+		info->var.green.offset = 16;
+		info->var.blue.offset = 24;
+		info->var.red.length = 8;
+		info->var.green.length = 8;
+		info->var.blue.length = 8;
+		info->var.transp.offset = 0;
+		info->var.transp.length = 8;
+		break;
+	default:
+#endif
+		break;
+	}
+
+	fb->fbdev = info;
+	rfbdev->rfb = rfb;
+	rfbdev->rdev = rdev;
+
+	mutex_unlock(&rdev->ddev->struct_mutex);
+	return 0;
+
+out_unref:
+	if (robj) {
+		radeon_object_kunmap(robj);
+	}
+	if (fb && ret) {
+		list_del(&fb->filp_head);
+		drm_gem_object_unreference(gobj);
+		drm_framebuffer_cleanup(fb);
+		kfree(fb);
+	}
+	drm_gem_object_unreference(gobj);
+	mutex_unlock(&rdev->ddev->struct_mutex);
+out:
+	return ret;
+}
+
+static int radeonfb_single_fb_probe(struct radeon_device *rdev)
+{
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+	unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
+	unsigned int surface_width = 0, surface_height = 0;
+	int new_fb = 0;
+	int crtc_count = 0;
+	int ret, i, conn_count = 0;
+	struct radeon_framebuffer *rfb;
+	struct fb_info *info;
+	struct radeon_fb_device *rfbdev;
+	struct drm_mode_set *modeset = NULL;
+
+	/* first up get a count of crtcs now in use and new min/maxes width/heights */
+	list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
+		if (drm_helper_crtc_in_use(crtc)) {
+			if (crtc->desired_mode) {
+				if (crtc->desired_mode->hdisplay < fb_width)
+					fb_width = crtc->desired_mode->hdisplay;
+
+				if (crtc->desired_mode->vdisplay < fb_height)
+					fb_height = crtc->desired_mode->vdisplay;
+
+				if (crtc->desired_mode->hdisplay > surface_width)
+					surface_width = crtc->desired_mode->hdisplay;
+
+				if (crtc->desired_mode->vdisplay > surface_height)
+					surface_height = crtc->desired_mode->vdisplay;
+			}
+			crtc_count++;
+		}
+	}
+
+	if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
+		/* hmm everyone went away - assume VGA cable just fell out
+		   and will come back later. */
+		return 0;
+	}
+
+	/* do we have an fb already? */
+	if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) {
+		/* create an fb if we don't have one */
+		ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb);
+		if (ret) {
+			return -EINVAL;
+		}
+		new_fb = 1;
+	} else {
+		struct drm_framebuffer *fb;
+		fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head);
+		rfb = to_radeon_framebuffer(fb);
+
+		/* if someone hotplugs something bigger than we have already allocated, we are pwned.
+		   As really we can't resize an fbdev that is in the wild currently due to fbdev
+		   not really being designed for the lower layers moving stuff around under it.
+		   - so in the grand style of things - punt. */
+		if ((fb->width < surface_width) || (fb->height < surface_height)) {
+			DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
+			return -EINVAL;
+		}
+	}
+
+	info = rfb->base.fbdev;
+	rdev->fbdev_info = info;
+	rfbdev = info->par;
+
+	crtc_count = 0;
+	/* okay we need to setup new connector sets in the crtcs */
+	list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
+		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+		modeset = &radeon_crtc->mode_set;
+		modeset->fb = &rfb->base;
+		conn_count = 0;
+		list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) {
+			if (connector->encoder)
+				if (connector->encoder->crtc == modeset->crtc) {
+					modeset->connectors[conn_count] = connector;
+					conn_count++;
+					if (conn_count > RADEONFB_CONN_LIMIT)
+						BUG();
+				}
+		}
+
+		for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++)
+			modeset->connectors[i] = NULL;
+
+
+		rfbdev->crtc_ids[crtc_count++] = crtc->base.id;
+
+		modeset->num_connectors = conn_count;
+		if (modeset->crtc->desired_mode) {
+			if (modeset->mode) {
+				drm_mode_destroy(rdev->ddev, modeset->mode);
+			}
+			modeset->mode = drm_mode_duplicate(rdev->ddev,
+							   modeset->crtc->desired_mode);
+		}
+	}
+	rfbdev->crtc_count = crtc_count;
+
+	if (new_fb) {
+		info->var.pixclock = -1;
+		if (register_framebuffer(info) < 0)
+			return -EINVAL;
+	} else {
+		radeonfb_set_par(info);
+	}
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+	       info->fix.id);
+
+	/* Switch back to kernel console on panic */
+	panic_mode = *modeset;
+	atomic_notifier_chain_register(&panic_notifier_list, &paniced);
+	printk(KERN_INFO "registered panic notifier\n");
+
+	return 0;
+}
+
+int radeonfb_probe(struct drm_device *dev)
+{
+	int ret;
+
+	/* something has changed in the lower levels of hell - deal with it
+	   here */
+
+	/* two modes : a) 1 fb to rule all crtcs.
+	               b) one fb per crtc.
+	   two actions 1) new connected device
+	               2) device removed.
+	   case a/1 : if the fb surface isn't big enough - resize the surface fb.
+	              if the fb size isn't big enough - resize fb into surface.
+		      if everything big enough configure the new crtc/etc.
+	   case a/2 : undo the configuration
+	              possibly resize down the fb to fit the new configuration.
+           case b/1 : see if it is on a new crtc - setup a new fb and add it.
+	   case b/2 : teardown the new fb.
+	*/
+	ret = radeonfb_single_fb_probe(dev->dev_private);
+	return ret;
+}
+EXPORT_SYMBOL(radeonfb_probe);
+
+int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
+{
+	struct fb_info *info;
+	struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb);
+	struct radeon_object *robj;
+
+	if (!fb) {
+		return -EINVAL;
+	}
+	info = fb->fbdev;
+	if (info) {
+		robj = rfb->obj->driver_private;
+		unregister_framebuffer(info);
+		radeon_object_kunmap(robj);
+		radeon_object_unpin(robj);
+		framebuffer_release(info);
+	}
+
+	printk(KERN_INFO "unregistered panic notifier\n");
+	atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
+	memset(&panic_mode, 0, sizeof(struct drm_mode_set));
+	return 0;
+}
+EXPORT_SYMBOL(radeonfb_remove);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_fence.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_fence.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_fence.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2009 Jerome Glisse.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors:
+ *    Jerome Glisse <glisse@freedesktop.org>
+ *    Dave Airlie
+ */
+#include <linux/seq_file.h>
+#include <asm/atomic.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
+{
+	unsigned long irq_flags;
+
+	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+	if (fence->emited) {
+		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+		return 0;
+	}
+	fence->seq = atomic_add_return(1, &rdev->fence_drv.seq);
+	if (!rdev->cp.ready) {
+		/* FIXME: cp is not running assume everythings is done right
+		 * away
+		 */
+		WREG32(rdev->fence_drv.scratch_reg, fence->seq);
+	} else {
+		radeon_fence_ring_emit(rdev, fence);
+	}
+	fence->emited = true;
+	fence->timeout = jiffies + ((2000 * HZ) / 1000);
+	list_del(&fence->list);
+	list_add_tail(&fence->list, &rdev->fence_drv.emited);
+	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+	return 0;
+}
+
+static bool radeon_fence_poll_locked(struct radeon_device *rdev)
+{
+	struct radeon_fence *fence;
+	struct list_head *i, *n;
+	uint32_t seq;
+	bool wake = false;
+
+	if (rdev == NULL) {
+		return true;
+	}
+	if (rdev->shutdown) {
+		return true;
+	}
+	seq = RREG32(rdev->fence_drv.scratch_reg);
+	rdev->fence_drv.last_seq = seq;
+	n = NULL;
+	list_for_each(i, &rdev->fence_drv.emited) {
+		fence = list_entry(i, struct radeon_fence, list);
+		if (fence->seq == seq) {
+			n = i;
+			break;
+		}
+	}
+	/* all fence previous to this one are considered as signaled */
+	if (n) {
+		i = n;
+		do {
+			n = i->prev;
+			list_del(i);
+			list_add_tail(i, &rdev->fence_drv.signaled);
+			fence = list_entry(i, struct radeon_fence, list);
+			fence->signaled = true;
+			i = n;
+		} while (i != &rdev->fence_drv.emited);
+		wake = true;
+	}
+	return wake;
+}
+
+static void radeon_fence_destroy(struct kref *kref)
+{
+	unsigned long irq_flags;
+        struct radeon_fence *fence;
+
+	fence = container_of(kref, struct radeon_fence, kref);
+	write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags);
+	list_del(&fence->list);
+	fence->emited = false;
+	write_unlock_irqrestore(&fence->rdev->fence_drv.lock, irq_flags);
+	kfree(fence);
+}
+
+int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence)
+{
+	unsigned long irq_flags;
+
+	*fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL);
+	if ((*fence) == NULL) {
+		return -ENOMEM;
+	}
+	kref_init(&((*fence)->kref));
+	(*fence)->rdev = rdev;
+	(*fence)->emited = false;
+	(*fence)->signaled = false;
+	(*fence)->seq = 0;
+	INIT_LIST_HEAD(&(*fence)->list);
+
+	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+	list_add_tail(&(*fence)->list, &rdev->fence_drv.created);
+	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+	return 0;
+}
+
+
+bool radeon_fence_signaled(struct radeon_fence *fence)
+{
+	struct radeon_device *rdev = fence->rdev;
+	unsigned long irq_flags;
+	bool signaled = false;
+
+	if (rdev->gpu_lockup) {
+		return true;
+	}
+	if (fence == NULL) {
+		return true;
+	}
+	write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags);
+	signaled = fence->signaled;
+	/* if we are shuting down report all fence as signaled */
+	if (fence->rdev->shutdown) {
+		signaled = true;
+	}
+	if (!fence->emited) {
+		WARN(1, "Querying an unemited fence : %p !\n", fence);
+		signaled = true;
+	}
+	if (!signaled) {
+		radeon_fence_poll_locked(fence->rdev);
+		signaled = fence->signaled;
+	}
+	write_unlock_irqrestore(&fence->rdev->fence_drv.lock, irq_flags);
+	return signaled;
+}
+
+int radeon_fence_wait(struct radeon_fence *fence, bool interruptible)
+{
+	struct radeon_device *rdev;
+	unsigned long cur_jiffies;
+	unsigned long timeout;
+	bool expired = false;
+	int r;
+
+
+	if (fence == NULL) {
+		WARN(1, "Querying an invalid fence : %p !\n", fence);
+		return 0;
+	}
+	rdev = fence->rdev;
+	if (radeon_fence_signaled(fence)) {
+		return 0;
+	}
+retry:
+	cur_jiffies = jiffies;
+	timeout = HZ / 100;
+	if (time_after(fence->timeout, cur_jiffies)) {
+		timeout = fence->timeout - cur_jiffies;
+	}
+	if (interruptible) {
+		r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
+				radeon_fence_signaled(fence), timeout);
+		if (unlikely(r == -ERESTARTSYS)) {
+			return -EBUSY;
+		}
+	} else {
+		r = wait_event_timeout(rdev->fence_drv.queue,
+			 radeon_fence_signaled(fence), timeout);
+	}
+	if (unlikely(!radeon_fence_signaled(fence))) {
+		if (unlikely(r == 0)) {
+			expired = true;
+		}
+		if (unlikely(expired)) {
+			timeout = 1;
+			if (time_after(cur_jiffies, fence->timeout)) {
+				timeout = cur_jiffies - fence->timeout;
+			}
+			timeout = jiffies_to_msecs(timeout);
+			if (timeout > 500) {
+				DRM_ERROR("fence(%p:0x%08X) %lums timeout "
+					  "going to reset GPU\n",
+					  fence, fence->seq, timeout);
+				radeon_gpu_reset(rdev);
+				WREG32(rdev->fence_drv.scratch_reg, fence->seq);
+			}
+		}
+		goto retry;
+	}
+	if (unlikely(expired)) {
+		rdev->fence_drv.count_timeout++;
+		cur_jiffies = jiffies;
+		timeout = 1;
+		if (time_after(cur_jiffies, fence->timeout)) {
+			timeout = cur_jiffies - fence->timeout;
+		}
+		timeout = jiffies_to_msecs(timeout);
+		DRM_ERROR("fence(%p:0x%08X) %lums timeout\n",
+			  fence, fence->seq, timeout);
+		DRM_ERROR("last signaled fence(0x%08X)\n",
+			  rdev->fence_drv.last_seq);
+	}
+	return 0;
+}
+
+int radeon_fence_wait_next(struct radeon_device *rdev)
+{
+	unsigned long irq_flags;
+	struct radeon_fence *fence;
+	int r;
+
+	if (rdev->gpu_lockup) {
+		return 0;
+	}
+	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+	if (list_empty(&rdev->fence_drv.emited)) {
+		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+		return 0;
+	}
+	fence = list_entry(rdev->fence_drv.emited.next,
+			   struct radeon_fence, list);
+	radeon_fence_ref(fence);
+	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+	r = radeon_fence_wait(fence, false);
+	radeon_fence_unref(&fence);
+	return r;
+}
+
+int radeon_fence_wait_last(struct radeon_device *rdev)
+{
+	unsigned long irq_flags;
+	struct radeon_fence *fence;
+	int r;
+
+	if (rdev->gpu_lockup) {
+		return 0;
+	}
+	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+	if (list_empty(&rdev->fence_drv.emited)) {
+		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+		return 0;
+	}
+	fence = list_entry(rdev->fence_drv.emited.prev,
+			   struct radeon_fence, list);
+	radeon_fence_ref(fence);
+	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+	r = radeon_fence_wait(fence, false);
+	radeon_fence_unref(&fence);
+	return r;
+}
+
+struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)
+{
+	kref_get(&fence->kref);
+	return fence;
+}
+
+void radeon_fence_unref(struct radeon_fence **fence)
+{
+	struct radeon_fence *tmp = *fence;
+
+	*fence = NULL;
+	if (tmp) {
+		kref_put(&tmp->kref, &radeon_fence_destroy);
+	}
+}
+
+void radeon_fence_process(struct radeon_device *rdev)
+{
+	unsigned long irq_flags;
+	bool wake;
+
+	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+	wake = radeon_fence_poll_locked(rdev);
+	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+	if (wake) {
+		wake_up_all(&rdev->fence_drv.queue);
+	}
+}
+
+int radeon_fence_driver_init(struct radeon_device *rdev)
+{
+	unsigned long irq_flags;
+	int r;
+
+	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+	r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg);
+	if (r) {
+		DRM_ERROR("Fence failed to get a scratch register.");
+		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+		return r;
+	}
+	WREG32(rdev->fence_drv.scratch_reg, 0);
+	atomic_set(&rdev->fence_drv.seq, 0);
+	INIT_LIST_HEAD(&rdev->fence_drv.created);
+	INIT_LIST_HEAD(&rdev->fence_drv.emited);
+	INIT_LIST_HEAD(&rdev->fence_drv.signaled);
+	rdev->fence_drv.count_timeout = 0;
+	init_waitqueue_head(&rdev->fence_drv.queue);
+	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+	if (radeon_debugfs_fence_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for fence !\n");
+	}
+	return 0;
+}
+
+void radeon_fence_driver_fini(struct radeon_device *rdev)
+{
+	unsigned long irq_flags;
+
+	wake_up_all(&rdev->fence_drv.queue);
+	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+	radeon_scratch_free(rdev, rdev->fence_drv.scratch_reg);
+	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+	DRM_INFO("radeon: fence finalized\n");
+}
+
+
+/*
+ * Fence debugfs
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *)m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_fence *fence;
+
+	seq_printf(m, "Last signaled fence 0x%08X\n",
+		   RREG32(rdev->fence_drv.scratch_reg));
+	if (!list_empty(&rdev->fence_drv.emited)) {
+		   fence = list_entry(rdev->fence_drv.emited.prev,
+				      struct radeon_fence, list);
+		   seq_printf(m, "Last emited fence %p with 0x%08X\n",
+			      fence,  fence->seq);
+	}
+	return 0;
+}
+
+static struct drm_info_list radeon_debugfs_fence_list[] = {
+	{"radeon_fence_info", &radeon_debugfs_fence_info, 0, NULL},
+};
+#endif
+
+int radeon_debugfs_fence_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1);
+#else
+	return 0;
+#endif
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_fixed.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_fixed.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_fixed.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_fixed.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ */
+#ifndef RADEON_FIXED_H
+#define RADEON_FIXED_H
+
+typedef union rfixed {
+	u32 full;
+} fixed20_12;
+
+
+#define rfixed_const(A) (u32)(((A) << 12))/*  + ((B + 0.000122)*4096)) */
+#define rfixed_const_half(A) (u32)(((A) << 12) + 2048)
+#define rfixed_const_666(A) (u32)(((A) << 12) + 2731)
+#define rfixed_const_8(A) (u32)(((A) << 12) + 3277)
+#define rfixed_mul(A, B) ((u64)((u64)(A).full * (B).full + 2048) >> 12)
+#define fixed_init(A) { .full = rfixed_const((A)) }
+#define fixed_init_half(A) { .full = rfixed_const_half((A)) }
+#define rfixed_trunc(A) ((A).full >> 12)
+
+static inline u32 rfixed_div(fixed20_12 A, fixed20_12 B)
+{
+	u64 tmp = ((u64)A.full << 13);
+
+	do_div(tmp, B.full);
+	tmp += 1;
+	tmp /= 2;
+	return lower_32_bits(tmp);
+}
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_gart.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_gart.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_gart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_gart.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+
+/*
+ * Common GART table functions.
+ */
+int radeon_gart_table_ram_alloc(struct radeon_device *rdev)
+{
+	void *ptr;
+
+	ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size,
+				   &rdev->gart.table_addr);
+	if (ptr == NULL) {
+		return -ENOMEM;
+	}
+#ifdef CONFIG_X86
+	if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
+	    rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
+		set_memory_uc((unsigned long)ptr,
+			      rdev->gart.table_size >> PAGE_SHIFT);
+	}
+#endif
+	rdev->gart.table.ram.ptr = ptr;
+	memset((void *)rdev->gart.table.ram.ptr, 0, rdev->gart.table_size);
+	return 0;
+}
+
+void radeon_gart_table_ram_free(struct radeon_device *rdev)
+{
+	if (rdev->gart.table.ram.ptr == NULL) {
+		return;
+	}
+#ifdef CONFIG_X86
+	if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
+	    rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
+		set_memory_wb((unsigned long)rdev->gart.table.ram.ptr,
+			      rdev->gart.table_size >> PAGE_SHIFT);
+	}
+#endif
+	pci_free_consistent(rdev->pdev, rdev->gart.table_size,
+			    (void *)rdev->gart.table.ram.ptr,
+			    rdev->gart.table_addr);
+	rdev->gart.table.ram.ptr = NULL;
+	rdev->gart.table_addr = 0;
+}
+
+int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
+{
+	uint64_t gpu_addr;
+	int r;
+
+	if (rdev->gart.table.vram.robj == NULL) {
+		r = radeon_object_create(rdev, NULL,
+					 rdev->gart.table_size,
+					 true,
+					 RADEON_GEM_DOMAIN_VRAM,
+					 false, &rdev->gart.table.vram.robj);
+		if (r) {
+			return r;
+		}
+	}
+	r = radeon_object_pin(rdev->gart.table.vram.robj,
+			      RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+	if (r) {
+		radeon_object_unref(&rdev->gart.table.vram.robj);
+		return r;
+	}
+	r = radeon_object_kmap(rdev->gart.table.vram.robj,
+			       (void **)&rdev->gart.table.vram.ptr);
+	if (r) {
+		radeon_object_unpin(rdev->gart.table.vram.robj);
+		radeon_object_unref(&rdev->gart.table.vram.robj);
+		DRM_ERROR("radeon: failed to map gart vram table.\n");
+		return r;
+	}
+	rdev->gart.table_addr = gpu_addr;
+	return 0;
+}
+
+void radeon_gart_table_vram_free(struct radeon_device *rdev)
+{
+	if (rdev->gart.table.vram.robj == NULL) {
+		return;
+	}
+	radeon_object_kunmap(rdev->gart.table.vram.robj);
+	radeon_object_unpin(rdev->gart.table.vram.robj);
+	radeon_object_unref(&rdev->gart.table.vram.robj);
+}
+
+
+
+
+/*
+ * Common gart functions.
+ */
+void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
+			int pages)
+{
+	unsigned t;
+	unsigned p;
+	int i, j;
+
+	if (!rdev->gart.ready) {
+		WARN(1, "trying to unbind memory to unitialized GART !\n");
+		return;
+	}
+	t = offset / 4096;
+	p = t / (PAGE_SIZE / 4096);
+	for (i = 0; i < pages; i++, p++) {
+		if (rdev->gart.pages[p]) {
+			pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
+				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+			rdev->gart.pages[p] = NULL;
+			rdev->gart.pages_addr[p] = 0;
+			for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
+				radeon_gart_set_page(rdev, t, 0);
+			}
+		}
+	}
+	mb();
+	radeon_gart_tlb_flush(rdev);
+}
+
+int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
+		     int pages, struct page **pagelist)
+{
+	unsigned t;
+	unsigned p;
+	uint64_t page_base;
+	int i, j;
+
+	if (!rdev->gart.ready) {
+		DRM_ERROR("trying to bind memory to unitialized GART !\n");
+		return -EINVAL;
+	}
+	t = offset / 4096;
+	p = t / (PAGE_SIZE / 4096);
+
+	for (i = 0; i < pages; i++, p++) {
+		/* we need to support large memory configurations */
+		/* assume that unbind have already been call on the range */
+		rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i],
+							0, PAGE_SIZE,
+							PCI_DMA_BIDIRECTIONAL);
+		if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) {
+			/* FIXME: failed to map page (return -ENOMEM?) */
+			radeon_gart_unbind(rdev, offset, pages);
+			return -ENOMEM;
+		}
+		rdev->gart.pages[p] = pagelist[i];
+		page_base = rdev->gart.pages_addr[p];
+		for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
+			radeon_gart_set_page(rdev, t, page_base);
+			page_base += 4096;
+		}
+	}
+	mb();
+	radeon_gart_tlb_flush(rdev);
+	return 0;
+}
+
+int radeon_gart_init(struct radeon_device *rdev)
+{
+	if (rdev->gart.pages) {
+		return 0;
+	}
+	/* We need PAGE_SIZE >= 4096 */
+	if (PAGE_SIZE < 4096) {
+		DRM_ERROR("Page size is smaller than GPU page size!\n");
+		return -EINVAL;
+	}
+	/* Compute table size */
+	rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
+	rdev->gart.num_gpu_pages = rdev->mc.gtt_size / 4096;
+	DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
+		 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
+	/* Allocate pages table */
+	rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages,
+				   GFP_KERNEL);
+	if (rdev->gart.pages == NULL) {
+		radeon_gart_fini(rdev);
+		return -ENOMEM;
+	}
+	rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) *
+					rdev->gart.num_cpu_pages, GFP_KERNEL);
+	if (rdev->gart.pages_addr == NULL) {
+		radeon_gart_fini(rdev);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void radeon_gart_fini(struct radeon_device *rdev)
+{
+	if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) {
+		/* unbind pages */
+		radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
+	}
+	rdev->gart.ready = false;
+	kfree(rdev->gart.pages);
+	kfree(rdev->gart.pages_addr);
+	rdev->gart.pages = NULL;
+	rdev->gart.pages_addr = NULL;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_gem.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_gem.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_gem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+int radeon_gem_object_init(struct drm_gem_object *obj)
+{
+	/* we do nothings here */
+	return 0;
+}
+
+void radeon_gem_object_free(struct drm_gem_object *gobj)
+{
+	struct radeon_object *robj = gobj->driver_private;
+
+	gobj->driver_private = NULL;
+	if (robj) {
+		radeon_object_unref(&robj);
+	}
+}
+
+int radeon_gem_object_create(struct radeon_device *rdev, int size,
+			     int alignment, int initial_domain,
+			     bool discardable, bool kernel,
+			     bool interruptible,
+			     struct drm_gem_object **obj)
+{
+	struct drm_gem_object *gobj;
+	struct radeon_object *robj;
+	int r;
+
+	*obj = NULL;
+	gobj = drm_gem_object_alloc(rdev->ddev, size);
+	if (!gobj) {
+		return -ENOMEM;
+	}
+	/* At least align on page size */
+	if (alignment < PAGE_SIZE) {
+		alignment = PAGE_SIZE;
+	}
+	r = radeon_object_create(rdev, gobj, size, kernel, initial_domain,
+				 interruptible, &robj);
+	if (r) {
+		DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n",
+			  size, initial_domain, alignment);
+		mutex_lock(&rdev->ddev->struct_mutex);
+		drm_gem_object_unreference(gobj);
+		mutex_unlock(&rdev->ddev->struct_mutex);
+		return r;
+	}
+	gobj->driver_private = robj;
+	*obj = gobj;
+	return 0;
+}
+
+int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
+			  uint64_t *gpu_addr)
+{
+	struct radeon_object *robj = obj->driver_private;
+	uint32_t flags;
+
+	switch (pin_domain) {
+	case RADEON_GEM_DOMAIN_VRAM:
+		flags = TTM_PL_FLAG_VRAM;
+		break;
+	case RADEON_GEM_DOMAIN_GTT:
+		flags = TTM_PL_FLAG_TT;
+		break;
+	default:
+		flags = TTM_PL_FLAG_SYSTEM;
+		break;
+	}
+	return radeon_object_pin(robj, flags, gpu_addr);
+}
+
+void radeon_gem_object_unpin(struct drm_gem_object *obj)
+{
+	struct radeon_object *robj = obj->driver_private;
+	radeon_object_unpin(robj);
+}
+
+int radeon_gem_set_domain(struct drm_gem_object *gobj,
+			  uint32_t rdomain, uint32_t wdomain)
+{
+	struct radeon_object *robj;
+	uint32_t domain;
+	int r;
+
+	/* FIXME: reeimplement */
+	robj = gobj->driver_private;
+	/* work out where to validate the buffer to */
+	domain = wdomain;
+	if (!domain) {
+		domain = rdomain;
+	}
+	if (!domain) {
+		/* Do nothings */
+		printk(KERN_WARNING "Set domain withou domain !\n");
+		return 0;
+	}
+	if (domain == RADEON_GEM_DOMAIN_CPU) {
+		/* Asking for cpu access wait for object idle */
+		r = radeon_object_wait(robj);
+		if (r) {
+			printk(KERN_ERR "Failed to wait for object !\n");
+			return r;
+		}
+	}
+	return 0;
+}
+
+int radeon_gem_init(struct radeon_device *rdev)
+{
+	INIT_LIST_HEAD(&rdev->gem.objects);
+	return 0;
+}
+
+void radeon_gem_fini(struct radeon_device *rdev)
+{
+	radeon_object_force_delete(rdev);
+}
+
+
+/*
+ * GEM ioctls.
+ */
+int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_radeon_gem_info *args = data;
+
+	args->vram_size = rdev->mc.real_vram_size;
+	/* FIXME: report somethings that makes sense */
+	args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024);
+	args->gart_size = rdev->mc.gtt_size;
+	return 0;
+}
+
+int radeon_gem_pread_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *filp)
+{
+	/* TODO: implement */
+	DRM_ERROR("unimplemented %s\n", __func__);
+	return -ENOSYS;
+}
+
+int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *filp)
+{
+	/* TODO: implement */
+	DRM_ERROR("unimplemented %s\n", __func__);
+	return -ENOSYS;
+}
+
+int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *filp)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_radeon_gem_create *args = data;
+	struct drm_gem_object *gobj;
+	uint32_t handle;
+	int r;
+
+	/* create a gem object to contain this object in */
+	args->size = roundup(args->size, PAGE_SIZE);
+	r = radeon_gem_object_create(rdev, args->size, args->alignment,
+				     args->initial_domain, false,
+				     false, true, &gobj);
+	if (r) {
+		return r;
+	}
+	r = drm_gem_handle_create(filp, gobj, &handle);
+	if (r) {
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_unreference(gobj);
+		mutex_unlock(&dev->struct_mutex);
+		return r;
+	}
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference(gobj);
+	mutex_unlock(&dev->struct_mutex);
+	args->handle = handle;
+	return 0;
+}
+
+int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp)
+{
+	/* transition the BO to a domain -
+	 * just validate the BO into a certain domain */
+	struct drm_radeon_gem_set_domain *args = data;
+	struct drm_gem_object *gobj;
+	struct radeon_object *robj;
+	int r;
+
+	/* for now if someone requests domain CPU -
+	 * just make sure the buffer is finished with */
+
+	/* just do a BO wait for now */
+	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	if (gobj == NULL) {
+		return -EINVAL;
+	}
+	robj = gobj->driver_private;
+
+	r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
+
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gobj);
+	mutex_unlock(&dev->struct_mutex);
+	return r;
+}
+
+int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp)
+{
+	struct drm_radeon_gem_mmap *args = data;
+	struct drm_gem_object *gobj;
+	struct radeon_object *robj;
+	int r;
+
+	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	if (gobj == NULL) {
+		return -EINVAL;
+	}
+	robj = gobj->driver_private;
+	r = radeon_object_mmap(robj, &args->addr_ptr);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gobj);
+	mutex_unlock(&dev->struct_mutex);
+	return r;
+}
+
+int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp)
+{
+	struct drm_radeon_gem_busy *args = data;
+	struct drm_gem_object *gobj;
+	struct radeon_object *robj;
+	int r;
+	uint32_t cur_placement;
+
+	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	if (gobj == NULL) {
+		return -EINVAL;
+	}
+	robj = gobj->driver_private;
+	r = radeon_object_busy_domain(robj, &cur_placement);
+	switch (cur_placement) {
+	case TTM_PL_VRAM:
+		args->domain = RADEON_GEM_DOMAIN_VRAM;
+		break;
+	case TTM_PL_TT:
+		args->domain = RADEON_GEM_DOMAIN_GTT;
+		break;
+	case TTM_PL_SYSTEM:
+		args->domain = RADEON_GEM_DOMAIN_CPU;
+	default:
+		break;
+	}
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gobj);
+	mutex_unlock(&dev->struct_mutex);
+	return r;
+}
+
+int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *filp)
+{
+	struct drm_radeon_gem_wait_idle *args = data;
+	struct drm_gem_object *gobj;
+	struct radeon_object *robj;
+	int r;
+
+	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	if (gobj == NULL) {
+		return -EINVAL;
+	}
+	robj = gobj->driver_private;
+	r = radeon_object_wait(robj);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gobj);
+	mutex_unlock(&dev->struct_mutex);
+	return r;
+}
+
+int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp)
+{
+	struct drm_radeon_gem_set_tiling *args = data;
+	struct drm_gem_object *gobj;
+	struct radeon_object *robj;
+	int r = 0;
+
+	DRM_DEBUG("%d \n", args->handle);
+	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	if (gobj == NULL)
+		return -EINVAL;
+	robj = gobj->driver_private;
+	radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gobj);
+	mutex_unlock(&dev->struct_mutex);
+	return r;
+}
+
+int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp)
+{
+	struct drm_radeon_gem_get_tiling *args = data;
+	struct drm_gem_object *gobj;
+	struct radeon_object *robj;
+	int r = 0;
+
+	DRM_DEBUG("\n");
+	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	if (gobj == NULL)
+		return -EINVAL;
+	robj = gobj->driver_private;
+	radeon_object_get_tiling_flags(robj, &args->tiling_flags,
+				       &args->pitch);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gobj);
+	mutex_unlock(&dev->struct_mutex);
+	return r;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,916 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RADEON_H__
+#define __RADEON_H__
+
+#include "radeon_object.h"
+
+/* TODO: Here are things that needs to be done :
+ *	- surface allocator & initializer : (bit like scratch reg) should
+ *	  initialize HDP_ stuff on RS600, R600, R700 hw, well anythings
+ *	  related to surface
+ *	- WB : write back stuff (do it bit like scratch reg things)
+ *	- Vblank : look at Jesse's rework and what we should do
+ *	- r600/r700: gart & cp
+ *	- cs : clean cs ioctl use bitmap & things like that.
+ *	- power management stuff
+ *	- Barrier in gart code
+ *	- Unmappabled vram ?
+ *	- TESTING, TESTING, TESTING
+ */
+
+#include <asm/atomic.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#include "radeon_mode.h"
+#include "radeon_reg.h"
+#include "r300.h"
+
+/*
+ * Modules parameters.
+ */
+extern int radeon_no_wb;
+extern int radeon_modeset;
+extern int radeon_dynclks;
+extern int radeon_r4xx_atom;
+extern int radeon_agpmode;
+extern int radeon_vram_limit;
+extern int radeon_gart_size;
+extern int radeon_benchmarking;
+extern int radeon_testing;
+extern int radeon_connector_table;
+
+/*
+ * Copy from radeon_drv.h so we don't have to include both and have conflicting
+ * symbol;
+ */
+#define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
+#define RADEON_IB_POOL_SIZE		16
+#define RADEON_DEBUGFS_MAX_NUM_FILES	32
+#define RADEONFB_CONN_LIMIT		4
+
+enum radeon_family {
+	CHIP_R100,
+	CHIP_RV100,
+	CHIP_RS100,
+	CHIP_RV200,
+	CHIP_RS200,
+	CHIP_R200,
+	CHIP_RV250,
+	CHIP_RS300,
+	CHIP_RV280,
+	CHIP_R300,
+	CHIP_R350,
+	CHIP_RV350,
+	CHIP_RV380,
+	CHIP_R420,
+	CHIP_R423,
+	CHIP_RV410,
+	CHIP_RS400,
+	CHIP_RS480,
+	CHIP_RS600,
+	CHIP_RS690,
+	CHIP_RS740,
+	CHIP_RV515,
+	CHIP_R520,
+	CHIP_RV530,
+	CHIP_RV560,
+	CHIP_RV570,
+	CHIP_R580,
+	CHIP_R600,
+	CHIP_RV610,
+	CHIP_RV630,
+	CHIP_RV620,
+	CHIP_RV635,
+	CHIP_RV670,
+	CHIP_RS780,
+	CHIP_RV770,
+	CHIP_RV730,
+	CHIP_RV710,
+	CHIP_RS880,
+	CHIP_LAST,
+};
+
+enum radeon_chip_flags {
+	RADEON_FAMILY_MASK = 0x0000ffffUL,
+	RADEON_FLAGS_MASK = 0xffff0000UL,
+	RADEON_IS_MOBILITY = 0x00010000UL,
+	RADEON_IS_IGP = 0x00020000UL,
+	RADEON_SINGLE_CRTC = 0x00040000UL,
+	RADEON_IS_AGP = 0x00080000UL,
+	RADEON_HAS_HIERZ = 0x00100000UL,
+	RADEON_IS_PCIE = 0x00200000UL,
+	RADEON_NEW_MEMMAP = 0x00400000UL,
+	RADEON_IS_PCI = 0x00800000UL,
+	RADEON_IS_IGPGART = 0x01000000UL,
+};
+
+
+/*
+ * Errata workarounds.
+ */
+enum radeon_pll_errata {
+	CHIP_ERRATA_R300_CG             = 0x00000001,
+	CHIP_ERRATA_PLL_DUMMYREADS      = 0x00000002,
+	CHIP_ERRATA_PLL_DELAY           = 0x00000004
+};
+
+
+struct radeon_device;
+
+
+/*
+ * BIOS.
+ */
+bool radeon_get_bios(struct radeon_device *rdev);
+
+/*
+ * Clocks
+ */
+
+struct radeon_clock {
+	struct radeon_pll p1pll;
+	struct radeon_pll p2pll;
+	struct radeon_pll spll;
+	struct radeon_pll mpll;
+	/* 10 Khz units */
+	uint32_t default_mclk;
+	uint32_t default_sclk;
+};
+
+/*
+ * Fences.
+ */
+struct radeon_fence_driver {
+	uint32_t			scratch_reg;
+	atomic_t			seq;
+	uint32_t			last_seq;
+	unsigned long			count_timeout;
+	wait_queue_head_t		queue;
+	rwlock_t			lock;
+	struct list_head		created;
+	struct list_head		emited;
+	struct list_head		signaled;
+};
+
+struct radeon_fence {
+	struct radeon_device		*rdev;
+	struct kref			kref;
+	struct list_head		list;
+	/* protected by radeon_fence.lock */
+	uint32_t			seq;
+	unsigned long			timeout;
+	bool				emited;
+	bool				signaled;
+};
+
+int radeon_fence_driver_init(struct radeon_device *rdev);
+void radeon_fence_driver_fini(struct radeon_device *rdev);
+int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence);
+int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence);
+void radeon_fence_process(struct radeon_device *rdev);
+bool radeon_fence_signaled(struct radeon_fence *fence);
+int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
+int radeon_fence_wait_next(struct radeon_device *rdev);
+int radeon_fence_wait_last(struct radeon_device *rdev);
+struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
+void radeon_fence_unref(struct radeon_fence **fence);
+
+/*
+ * Tiling registers
+ */
+struct radeon_surface_reg {
+	struct radeon_object *robj;
+};
+
+#define RADEON_GEM_MAX_SURFACES 8
+
+/*
+ * Radeon buffer.
+ */
+struct radeon_object;
+
+struct radeon_object_list {
+	struct list_head	list;
+	struct radeon_object	*robj;
+	uint64_t		gpu_offset;
+	unsigned		rdomain;
+	unsigned		wdomain;
+	uint32_t                tiling_flags;
+};
+
+int radeon_object_init(struct radeon_device *rdev);
+void radeon_object_fini(struct radeon_device *rdev);
+int radeon_object_create(struct radeon_device *rdev,
+			 struct drm_gem_object *gobj,
+			 unsigned long size,
+			 bool kernel,
+			 uint32_t domain,
+			 bool interruptible,
+			 struct radeon_object **robj_ptr);
+int radeon_object_kmap(struct radeon_object *robj, void **ptr);
+void radeon_object_kunmap(struct radeon_object *robj);
+void radeon_object_unref(struct radeon_object **robj);
+int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
+		      uint64_t *gpu_addr);
+void radeon_object_unpin(struct radeon_object *robj);
+int radeon_object_wait(struct radeon_object *robj);
+int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement);
+int radeon_object_evict_vram(struct radeon_device *rdev);
+int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset);
+void radeon_object_force_delete(struct radeon_device *rdev);
+void radeon_object_list_add_object(struct radeon_object_list *lobj,
+				   struct list_head *head);
+int radeon_object_list_validate(struct list_head *head, void *fence);
+void radeon_object_list_unvalidate(struct list_head *head);
+void radeon_object_list_clean(struct list_head *head);
+int radeon_object_fbdev_mmap(struct radeon_object *robj,
+			     struct vm_area_struct *vma);
+unsigned long radeon_object_size(struct radeon_object *robj);
+void radeon_object_clear_surface_reg(struct radeon_object *robj);
+int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
+			       bool force_drop);
+void radeon_object_set_tiling_flags(struct radeon_object *robj,
+				    uint32_t tiling_flags, uint32_t pitch);
+void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch);
+void radeon_bo_move_notify(struct ttm_buffer_object *bo,
+			   struct ttm_mem_reg *mem);
+void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
+/*
+ * GEM objects.
+ */
+struct radeon_gem {
+	struct list_head	objects;
+};
+
+int radeon_gem_init(struct radeon_device *rdev);
+void radeon_gem_fini(struct radeon_device *rdev);
+int radeon_gem_object_create(struct radeon_device *rdev, int size,
+			     int alignment, int initial_domain,
+			     bool discardable, bool kernel,
+			     bool interruptible,
+			     struct drm_gem_object **obj);
+int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
+			  uint64_t *gpu_addr);
+void radeon_gem_object_unpin(struct drm_gem_object *obj);
+
+
+/*
+ * GART structures, functions & helpers
+ */
+struct radeon_mc;
+
+struct radeon_gart_table_ram {
+	volatile uint32_t		*ptr;
+};
+
+struct radeon_gart_table_vram {
+	struct radeon_object		*robj;
+	volatile uint32_t		*ptr;
+};
+
+union radeon_gart_table {
+	struct radeon_gart_table_ram	ram;
+	struct radeon_gart_table_vram	vram;
+};
+
+struct radeon_gart {
+	dma_addr_t			table_addr;
+	unsigned			num_gpu_pages;
+	unsigned			num_cpu_pages;
+	unsigned			table_size;
+	union radeon_gart_table		table;
+	struct page			**pages;
+	dma_addr_t			*pages_addr;
+	bool				ready;
+};
+
+int radeon_gart_table_ram_alloc(struct radeon_device *rdev);
+void radeon_gart_table_ram_free(struct radeon_device *rdev);
+int radeon_gart_table_vram_alloc(struct radeon_device *rdev);
+void radeon_gart_table_vram_free(struct radeon_device *rdev);
+int radeon_gart_init(struct radeon_device *rdev);
+void radeon_gart_fini(struct radeon_device *rdev);
+void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
+			int pages);
+int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
+		     int pages, struct page **pagelist);
+
+
+/*
+ * GPU MC structures, functions & helpers
+ */
+struct radeon_mc {
+	resource_size_t		aper_size;
+	resource_size_t		aper_base;
+	resource_size_t		agp_base;
+	unsigned		gtt_location;
+	unsigned		gtt_size;
+	unsigned		vram_location;
+	/* for some chips with <= 32MB we need to lie
+	 * about vram size near mc fb location */
+	unsigned		mc_vram_size;
+	unsigned		vram_width;
+	unsigned		real_vram_size;
+	int			vram_mtrr;
+	bool			vram_is_ddr;
+};
+
+int radeon_mc_setup(struct radeon_device *rdev);
+
+
+/*
+ * GPU scratch registers structures, functions & helpers
+ */
+struct radeon_scratch {
+	unsigned		num_reg;
+	bool			free[32];
+	uint32_t		reg[32];
+};
+
+int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg);
+void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg);
+
+
+/*
+ * IRQS.
+ */
+struct radeon_irq {
+	bool		installed;
+	bool		sw_int;
+	/* FIXME: use a define max crtc rather than hardcode it */
+	bool		crtc_vblank_int[2];
+};
+
+int radeon_irq_kms_init(struct radeon_device *rdev);
+void radeon_irq_kms_fini(struct radeon_device *rdev);
+
+
+/*
+ * CP & ring.
+ */
+struct radeon_ib {
+	struct list_head	list;
+	unsigned long		idx;
+	uint64_t		gpu_addr;
+	struct radeon_fence	*fence;
+	volatile uint32_t	*ptr;
+	uint32_t		length_dw;
+};
+
+struct radeon_ib_pool {
+	struct mutex		mutex;
+	struct radeon_object	*robj;
+	struct list_head	scheduled_ibs;
+	struct radeon_ib	ibs[RADEON_IB_POOL_SIZE];
+	bool			ready;
+	DECLARE_BITMAP(alloc_bm, RADEON_IB_POOL_SIZE);
+};
+
+struct radeon_cp {
+	struct radeon_object	*ring_obj;
+	volatile uint32_t	*ring;
+	unsigned		rptr;
+	unsigned		wptr;
+	unsigned		wptr_old;
+	unsigned		ring_size;
+	unsigned		ring_free_dw;
+	int			count_dw;
+	uint64_t		gpu_addr;
+	uint32_t		align_mask;
+	uint32_t		ptr_mask;
+	struct mutex		mutex;
+	bool			ready;
+};
+
+int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib);
+void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
+int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
+int radeon_ib_pool_init(struct radeon_device *rdev);
+void radeon_ib_pool_fini(struct radeon_device *rdev);
+int radeon_ib_test(struct radeon_device *rdev);
+/* Ring access between begin & end cannot sleep */
+void radeon_ring_free_size(struct radeon_device *rdev);
+int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw);
+void radeon_ring_unlock_commit(struct radeon_device *rdev);
+void radeon_ring_unlock_undo(struct radeon_device *rdev);
+int radeon_ring_test(struct radeon_device *rdev);
+int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size);
+void radeon_ring_fini(struct radeon_device *rdev);
+
+
+/*
+ * CS.
+ */
+struct radeon_cs_reloc {
+	struct drm_gem_object		*gobj;
+	struct radeon_object		*robj;
+	struct radeon_object_list	lobj;
+	uint32_t			handle;
+	uint32_t			flags;
+};
+
+struct radeon_cs_chunk {
+	uint32_t		chunk_id;
+	uint32_t		length_dw;
+	uint32_t		*kdata;
+};
+
+struct radeon_cs_parser {
+	struct radeon_device	*rdev;
+	struct drm_file		*filp;
+	/* chunks */
+	unsigned		nchunks;
+	struct radeon_cs_chunk	*chunks;
+	uint64_t		*chunks_array;
+	/* IB */
+	unsigned		idx;
+	/* relocations */
+	unsigned		nrelocs;
+	struct radeon_cs_reloc	*relocs;
+	struct radeon_cs_reloc	**relocs_ptr;
+	struct list_head	validated;
+	/* indices of various chunks */
+	int			chunk_ib_idx;
+	int			chunk_relocs_idx;
+	struct radeon_ib	*ib;
+	void			*track;
+};
+
+struct radeon_cs_packet {
+	unsigned	idx;
+	unsigned	type;
+	unsigned	reg;
+	unsigned	opcode;
+	int		count;
+	unsigned	one_reg_wr;
+};
+
+typedef int (*radeon_packet0_check_t)(struct radeon_cs_parser *p,
+				      struct radeon_cs_packet *pkt,
+				      unsigned idx, unsigned reg);
+typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p,
+				      struct radeon_cs_packet *pkt);
+
+
+/*
+ * AGP
+ */
+int radeon_agp_init(struct radeon_device *rdev);
+void radeon_agp_fini(struct radeon_device *rdev);
+
+
+/*
+ * Writeback
+ */
+struct radeon_wb {
+	struct radeon_object	*wb_obj;
+	volatile uint32_t	*wb;
+	uint64_t		gpu_addr;
+};
+
+/**
+ * struct radeon_pm - power management datas
+ * @max_bandwidth:      maximum bandwidth the gpu has (MByte/s)
+ * @igp_sideport_mclk:  sideport memory clock Mhz (rs690,rs740,rs780,rs880)
+ * @igp_system_mclk:    system clock Mhz (rs690,rs740,rs780,rs880)
+ * @igp_ht_link_clk:    ht link clock Mhz (rs690,rs740,rs780,rs880)
+ * @igp_ht_link_width:  ht link width in bits (rs690,rs740,rs780,rs880)
+ * @k8_bandwidth:       k8 bandwidth the gpu has (MByte/s) (IGP)
+ * @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP)
+ * @ht_bandwidth:       ht bandwidth the gpu has (MByte/s) (IGP)
+ * @core_bandwidth:     core GPU bandwidth the gpu has (MByte/s) (IGP)
+ * @sclk:          	GPU clock Mhz (core bandwith depends of this clock)
+ * @needed_bandwidth:   current bandwidth needs
+ *
+ * It keeps track of various data needed to take powermanagement decision.
+ * Bandwith need is used to determine minimun clock of the GPU and memory.
+ * Equation between gpu/memory clock and available bandwidth is hw dependent
+ * (type of memory, bus size, efficiency, ...)
+ */
+struct radeon_pm {
+	fixed20_12		max_bandwidth;
+	fixed20_12		igp_sideport_mclk;
+	fixed20_12		igp_system_mclk;
+	fixed20_12		igp_ht_link_clk;
+	fixed20_12		igp_ht_link_width;
+	fixed20_12		k8_bandwidth;
+	fixed20_12		sideport_bandwidth;
+	fixed20_12		ht_bandwidth;
+	fixed20_12		core_bandwidth;
+	fixed20_12		sclk;
+	fixed20_12		needed_bandwidth;
+};
+
+
+/*
+ * Benchmarking
+ */
+void radeon_benchmark(struct radeon_device *rdev);
+
+
+/*
+ * Testing
+ */
+void radeon_test_moves(struct radeon_device *rdev);
+
+
+/*
+ * Debugfs
+ */
+int radeon_debugfs_add_files(struct radeon_device *rdev,
+			     struct drm_info_list *files,
+			     unsigned nfiles);
+int radeon_debugfs_fence_init(struct radeon_device *rdev);
+int r100_debugfs_rbbm_init(struct radeon_device *rdev);
+int r100_debugfs_cp_init(struct radeon_device *rdev);
+
+
+/*
+ * ASIC specific functions.
+ */
+struct radeon_asic {
+	int (*init)(struct radeon_device *rdev);
+	void (*errata)(struct radeon_device *rdev);
+	void (*vram_info)(struct radeon_device *rdev);
+	int (*gpu_reset)(struct radeon_device *rdev);
+	int (*mc_init)(struct radeon_device *rdev);
+	void (*mc_fini)(struct radeon_device *rdev);
+	int (*wb_init)(struct radeon_device *rdev);
+	void (*wb_fini)(struct radeon_device *rdev);
+	int (*gart_enable)(struct radeon_device *rdev);
+	void (*gart_disable)(struct radeon_device *rdev);
+	void (*gart_tlb_flush)(struct radeon_device *rdev);
+	int (*gart_set_page)(struct radeon_device *rdev, int i, uint64_t addr);
+	int (*cp_init)(struct radeon_device *rdev, unsigned ring_size);
+	void (*cp_fini)(struct radeon_device *rdev);
+	void (*cp_disable)(struct radeon_device *rdev);
+	void (*ring_start)(struct radeon_device *rdev);
+	int (*irq_set)(struct radeon_device *rdev);
+	int (*irq_process)(struct radeon_device *rdev);
+	u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc);
+	void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence);
+	int (*cs_parse)(struct radeon_cs_parser *p);
+	int (*copy_blit)(struct radeon_device *rdev,
+			 uint64_t src_offset,
+			 uint64_t dst_offset,
+			 unsigned num_pages,
+			 struct radeon_fence *fence);
+	int (*copy_dma)(struct radeon_device *rdev,
+			uint64_t src_offset,
+			uint64_t dst_offset,
+			unsigned num_pages,
+			struct radeon_fence *fence);
+	int (*copy)(struct radeon_device *rdev,
+		    uint64_t src_offset,
+		    uint64_t dst_offset,
+		    unsigned num_pages,
+		    struct radeon_fence *fence);
+	void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock);
+	void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
+	void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
+	void (*set_clock_gating)(struct radeon_device *rdev, int enable);
+	int (*set_surface_reg)(struct radeon_device *rdev, int reg,
+			       uint32_t tiling_flags, uint32_t pitch,
+			       uint32_t offset, uint32_t obj_size);
+	int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
+	void (*bandwidth_update)(struct radeon_device *rdev);
+};
+
+union radeon_asic_config {
+	struct r300_asic	r300;
+};
+
+
+/*
+ * IOCTL.
+ */
+int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp);
+int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *filp);
+int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+int radeon_gem_pread_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp);
+int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp);
+int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp);
+int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *filp);
+int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
+int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp);
+int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp);
+
+
+/*
+ * Core structure, functions and helpers.
+ */
+typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t);
+typedef void (*radeon_wreg_t)(struct radeon_device*, uint32_t, uint32_t);
+
+struct radeon_device {
+	struct drm_device		*ddev;
+	struct pci_dev			*pdev;
+	/* ASIC */
+	union radeon_asic_config	config;
+	enum radeon_family		family;
+	unsigned long			flags;
+	int				usec_timeout;
+	enum radeon_pll_errata		pll_errata;
+	int				num_gb_pipes;
+	int				num_z_pipes;
+	int				disp_priority;
+	/* BIOS */
+	uint8_t				*bios;
+	bool				is_atom_bios;
+	uint16_t			bios_header_start;
+	struct radeon_object		*stollen_vga_memory;
+	struct fb_info			*fbdev_info;
+	struct radeon_object		*fbdev_robj;
+	struct radeon_framebuffer	*fbdev_rfb;
+	/* Register mmio */
+	resource_size_t			rmmio_base;
+	resource_size_t			rmmio_size;
+	void				*rmmio;
+	radeon_rreg_t			mc_rreg;
+	radeon_wreg_t			mc_wreg;
+	radeon_rreg_t			pll_rreg;
+	radeon_wreg_t			pll_wreg;
+	uint32_t                        pcie_reg_mask;
+	radeon_rreg_t			pciep_rreg;
+	radeon_wreg_t			pciep_wreg;
+	struct radeon_clock             clock;
+	struct radeon_mc		mc;
+	struct radeon_gart		gart;
+	struct radeon_mode_info		mode_info;
+	struct radeon_scratch		scratch;
+	struct radeon_mman		mman;
+	struct radeon_fence_driver	fence_drv;
+	struct radeon_cp		cp;
+	struct radeon_ib_pool		ib_pool;
+	struct radeon_irq		irq;
+	struct radeon_asic		*asic;
+	struct radeon_gem		gem;
+	struct radeon_pm		pm;
+	struct mutex			cs_mutex;
+	struct radeon_wb		wb;
+	bool				gpu_lockup;
+	bool				shutdown;
+	bool				suspend;
+	bool				need_dma32;
+	struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
+};
+
+int radeon_device_init(struct radeon_device *rdev,
+		       struct drm_device *ddev,
+		       struct pci_dev *pdev,
+		       uint32_t flags);
+void radeon_device_fini(struct radeon_device *rdev);
+int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
+
+static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	if (reg < 0x10000)
+		return readl(((void __iomem *)rdev->rmmio) + reg);
+	else {
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+	}
+}
+
+static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	if (reg < 0x10000)
+		writel(v, ((void __iomem *)rdev->rmmio) + reg);
+	else {
+		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+		writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+	}
+}
+
+
+/*
+ * Registers read & write functions.
+ */
+#define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
+#define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
+#define RREG32(reg) r100_mm_rreg(rdev, (reg))
+#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
+#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
+#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
+#define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg))
+#define WREG32_PLL(reg, v) rdev->pll_wreg(rdev, (reg), (v))
+#define RREG32_MC(reg) rdev->mc_rreg(rdev, (reg))
+#define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v))
+#define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg))
+#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v))
+#define WREG32_P(reg, val, mask)				\
+	do {							\
+		uint32_t tmp_ = RREG32(reg);			\
+		tmp_ &= (mask);					\
+		tmp_ |= ((val) & ~(mask));			\
+		WREG32(reg, tmp_);				\
+	} while (0)
+#define WREG32_PLL_P(reg, val, mask)				\
+	do {							\
+		uint32_t tmp_ = RREG32_PLL(reg);		\
+		tmp_ &= (mask);					\
+		tmp_ |= ((val) & ~(mask));			\
+		WREG32_PLL(reg, tmp_);				\
+	} while (0)
+
+/*
+ * Indirect registers accessor
+ */
+static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t r;
+
+	WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
+	r = RREG32(RADEON_PCIE_DATA);
+	return r;
+}
+
+static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
+	WREG32(RADEON_PCIE_DATA, (v));
+}
+
+void r100_pll_errata_after_index(struct radeon_device *rdev);
+
+
+/*
+ * ASICs helpers.
+ */
+#define ASIC_IS_RN50(rdev) ((rdev->pdev->device == 0x515e) || \
+			    (rdev->pdev->device == 0x5969))
+#define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \
+		(rdev->family == CHIP_RV200) || \
+		(rdev->family == CHIP_RS100) || \
+		(rdev->family == CHIP_RS200) || \
+		(rdev->family == CHIP_RV250) || \
+		(rdev->family == CHIP_RV280) || \
+		(rdev->family == CHIP_RS300))
+#define ASIC_IS_R300(rdev) ((rdev->family == CHIP_R300)  ||	\
+		(rdev->family == CHIP_RV350) ||			\
+		(rdev->family == CHIP_R350)  ||			\
+		(rdev->family == CHIP_RV380) ||			\
+		(rdev->family == CHIP_R420)  ||			\
+		(rdev->family == CHIP_R423)  ||			\
+		(rdev->family == CHIP_RV410) ||			\
+		(rdev->family == CHIP_RS400) ||			\
+		(rdev->family == CHIP_RS480))
+#define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600))
+#define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
+#define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
+
+
+/*
+ * BIOS helpers.
+ */
+#define RBIOS8(i) (rdev->bios[i])
+#define RBIOS16(i) (RBIOS8(i) | (RBIOS8((i)+1) << 8))
+#define RBIOS32(i) ((RBIOS16(i)) | (RBIOS16((i)+2) << 16))
+
+int radeon_combios_init(struct radeon_device *rdev);
+void radeon_combios_fini(struct radeon_device *rdev);
+int radeon_atombios_init(struct radeon_device *rdev);
+void radeon_atombios_fini(struct radeon_device *rdev);
+
+
+/*
+ * RING helpers.
+ */
+#define CP_PACKET0			0x00000000
+#define		PACKET0_BASE_INDEX_SHIFT	0
+#define		PACKET0_BASE_INDEX_MASK		(0x1ffff << 0)
+#define		PACKET0_COUNT_SHIFT		16
+#define		PACKET0_COUNT_MASK		(0x3fff << 16)
+#define CP_PACKET1			0x40000000
+#define CP_PACKET2			0x80000000
+#define		PACKET2_PAD_SHIFT		0
+#define		PACKET2_PAD_MASK		(0x3fffffff << 0)
+#define CP_PACKET3			0xC0000000
+#define		PACKET3_IT_OPCODE_SHIFT		8
+#define		PACKET3_IT_OPCODE_MASK		(0xff << 8)
+#define		PACKET3_COUNT_SHIFT		16
+#define		PACKET3_COUNT_MASK		(0x3fff << 16)
+/* PACKET3 op code */
+#define		PACKET3_NOP			0x10
+#define		PACKET3_3D_DRAW_VBUF		0x28
+#define		PACKET3_3D_DRAW_IMMD		0x29
+#define		PACKET3_3D_DRAW_INDX		0x2A
+#define		PACKET3_3D_LOAD_VBPNTR		0x2F
+#define		PACKET3_INDX_BUFFER		0x33
+#define		PACKET3_3D_DRAW_VBUF_2		0x34
+#define		PACKET3_3D_DRAW_IMMD_2		0x35
+#define		PACKET3_3D_DRAW_INDX_2		0x36
+#define		PACKET3_BITBLT_MULTI		0x9B
+
+#define PACKET0(reg, n)	(CP_PACKET0 |					\
+			 REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) |	\
+			 REG_SET(PACKET0_COUNT, (n)))
+#define PACKET2(v)	(CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
+#define PACKET3(op, n)	(CP_PACKET3 |					\
+			 REG_SET(PACKET3_IT_OPCODE, (op)) |		\
+			 REG_SET(PACKET3_COUNT, (n)))
+
+#define	PACKET_TYPE0	0
+#define	PACKET_TYPE1	1
+#define	PACKET_TYPE2	2
+#define	PACKET_TYPE3	3
+
+#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
+#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+
+static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
+{
+#if DRM_DEBUG_CODE
+	if (rdev->cp.count_dw <= 0) {
+		DRM_ERROR("radeon: writting more dword to ring than expected !\n");
+	}
+#endif
+	rdev->cp.ring[rdev->cp.wptr++] = v;
+	rdev->cp.wptr &= rdev->cp.ptr_mask;
+	rdev->cp.count_dw--;
+	rdev->cp.ring_free_dw--;
+}
+
+
+/*
+ * ASICs macro.
+ */
+#define radeon_init(rdev) (rdev)->asic->init((rdev))
+#define radeon_cs_parse(p) rdev->asic->cs_parse((p))
+#define radeon_errata(rdev) (rdev)->asic->errata((rdev))
+#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev))
+#define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev))
+#define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev))
+#define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev))
+#define radeon_wb_init(rdev) (rdev)->asic->wb_init((rdev))
+#define radeon_wb_fini(rdev) (rdev)->asic->wb_fini((rdev))
+#define radeon_gart_enable(rdev) (rdev)->asic->gart_enable((rdev))
+#define radeon_gart_disable(rdev) (rdev)->asic->gart_disable((rdev))
+#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev))
+#define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart_set_page((rdev), (i), (p))
+#define radeon_cp_init(rdev,rsize) (rdev)->asic->cp_init((rdev), (rsize))
+#define radeon_cp_fini(rdev) (rdev)->asic->cp_fini((rdev))
+#define radeon_cp_disable(rdev) (rdev)->asic->cp_disable((rdev))
+#define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev))
+#define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev))
+#define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev))
+#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc))
+#define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence))
+#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f))
+#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f))
+#define radeon_copy(rdev, s, d, np, f) (rdev)->asic->copy((rdev), (s), (d), (np), (f))
+#define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
+#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
+#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
+#define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
+#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
+#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
+#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_i2c.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_i2c.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+/**
+ * radeon_ddc_probe
+ *
+ */
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+{
+	u8 out_buf[] = { 0x0, 0x0};
+	u8 buf[2];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr = 0x50,
+			.flags = 0,
+			.len = 1,
+			.buf = out_buf,
+		},
+		{
+			.addr = 0x50,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		return true;
+
+	return false;
+}
+
+
+void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state)
+{
+	struct radeon_device *rdev = radeon_connector->base.dev->dev_private;
+	uint32_t temp;
+	struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec;
+
+	/* RV410 appears to have a bug where the hw i2c in reset
+	 * holds the i2c port in a bad state - switch hw i2c away before
+	 * doing DDC - do this for all r200s/r300s/r400s for safety sake
+	 */
+	if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
+		if (rec->a_clk_reg == RADEON_GPIO_MONID) {
+			WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
+						R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
+		} else {
+			WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
+						R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
+		}
+	}
+	if (lock_state) {
+		temp = RREG32(rec->a_clk_reg);
+		temp &= ~(rec->a_clk_mask);
+		WREG32(rec->a_clk_reg, temp);
+
+		temp = RREG32(rec->a_data_reg);
+		temp &= ~(rec->a_data_mask);
+		WREG32(rec->a_data_reg, temp);
+	}
+
+	temp = RREG32(rec->mask_clk_reg);
+	if (lock_state)
+		temp |= rec->mask_clk_mask;
+	else
+		temp &= ~rec->mask_clk_mask;
+	WREG32(rec->mask_clk_reg, temp);
+	temp = RREG32(rec->mask_clk_reg);
+
+	temp = RREG32(rec->mask_data_reg);
+	if (lock_state)
+		temp |= rec->mask_data_mask;
+	else
+		temp &= ~rec->mask_data_mask;
+	WREG32(rec->mask_data_reg, temp);
+	temp = RREG32(rec->mask_data_reg);
+}
+
+static int get_clock(void *i2c_priv)
+{
+	struct radeon_i2c_chan *i2c = i2c_priv;
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	uint32_t val;
+
+	val = RREG32(rec->get_clk_reg);
+	val &= rec->get_clk_mask;
+
+	return (val != 0);
+}
+
+
+static int get_data(void *i2c_priv)
+{
+	struct radeon_i2c_chan *i2c = i2c_priv;
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	uint32_t val;
+
+	val = RREG32(rec->get_data_reg);
+	val &= rec->get_data_mask;
+	return (val != 0);
+}
+
+static void set_clock(void *i2c_priv, int clock)
+{
+	struct radeon_i2c_chan *i2c = i2c_priv;
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	uint32_t val;
+
+	val = RREG32(rec->put_clk_reg) & (uint32_t)~(rec->put_clk_mask);
+	val |= clock ? 0 : rec->put_clk_mask;
+	WREG32(rec->put_clk_reg, val);
+}
+
+static void set_data(void *i2c_priv, int data)
+{
+	struct radeon_i2c_chan *i2c = i2c_priv;
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	uint32_t val;
+
+	val = RREG32(rec->put_data_reg) & (uint32_t)~(rec->put_data_mask);
+	val |= data ? 0 : rec->put_data_mask;
+	WREG32(rec->put_data_reg, val);
+}
+
+struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
+		struct radeon_i2c_bus_rec *rec,
+		const char *name)
+{
+	struct radeon_i2c_chan *i2c;
+	int ret;
+
+	i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
+	if (i2c == NULL)
+		return NULL;
+
+	i2c->adapter.owner = THIS_MODULE;
+	i2c->adapter.algo_data = &i2c->algo;
+	i2c->dev = dev;
+	i2c->algo.setsda = set_data;
+	i2c->algo.setscl = set_clock;
+	i2c->algo.getsda = get_data;
+	i2c->algo.getscl = get_clock;
+	i2c->algo.udelay = 20;
+	/* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
+	 * make this, 2 jiffies is a lot more reliable */
+	i2c->algo.timeout = 2;
+	i2c->algo.data = i2c;
+	i2c->rec = *rec;
+	i2c_set_adapdata(&i2c->adapter, i2c);
+
+	ret = i2c_bit_add_bus(&i2c->adapter);
+	if (ret) {
+		DRM_INFO("Failed to register i2c %s\n", name);
+		goto out_free;
+	}
+
+	return i2c;
+out_free:
+	kfree(i2c);
+	return NULL;
+
+}
+
+void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
+{
+	if (!i2c)
+		return;
+
+	i2c_del_adapter(&i2c->adapter);
+	kfree(i2c);
+}
+
+struct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
+{
+	return NULL;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon_reg.h"
+#include "radeon_microcode.h"
+#include "radeon.h"
+#include "atom.h"
+
+irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *) arg;
+	struct radeon_device *rdev = dev->dev_private;
+
+	return radeon_irq_process(rdev);
+}
+
+void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	unsigned i;
+
+	/* Disable *all* interrupts */
+	rdev->irq.sw_int = false;
+	for (i = 0; i < 2; i++) {
+		rdev->irq.crtc_vblank_int[i] = false;
+	}
+	radeon_irq_set(rdev);
+	/* Clear bits */
+	radeon_irq_process(rdev);
+}
+
+int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	dev->max_vblank_count = 0x001fffff;
+	rdev->irq.sw_int = true;
+	radeon_irq_set(rdev);
+	return 0;
+}
+
+void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	unsigned i;
+
+	if (rdev == NULL) {
+		return;
+	}
+	/* Disable *all* interrupts */
+	rdev->irq.sw_int = false;
+	for (i = 0; i < 2; i++) {
+		rdev->irq.crtc_vblank_int[i] = false;
+	}
+	radeon_irq_set(rdev);
+}
+
+int radeon_irq_kms_init(struct radeon_device *rdev)
+{
+	int r = 0;
+
+	r = drm_vblank_init(rdev->ddev, 2);
+	if (r) {
+		return r;
+	}
+	drm_irq_install(rdev->ddev);
+	rdev->irq.installed = true;
+	DRM_INFO("radeon: irq initialized.\n");
+	return 0;
+}
+
+void radeon_irq_kms_fini(struct radeon_device *rdev)
+{
+	if (rdev->irq.installed) {
+		rdev->irq.installed = false;
+		drm_irq_uninstall(rdev->ddev);
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_kms.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_kms.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_kms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_kms.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "drm_sarea.h"
+#include "radeon.h"
+#include "radeon_drm.h"
+
+
+/*
+ * Driver load/unload
+ */
+int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
+{
+	struct radeon_device *rdev;
+	int r;
+
+	rdev = kzalloc(sizeof(struct radeon_device), GFP_KERNEL);
+	if (rdev == NULL) {
+		return -ENOMEM;
+	}
+	dev->dev_private = (void *)rdev;
+
+	/* update BUS flag */
+	if (drm_device_is_agp(dev)) {
+		flags |= RADEON_IS_AGP;
+	} else if (drm_device_is_pcie(dev)) {
+		flags |= RADEON_IS_PCIE;
+	} else {
+		flags |= RADEON_IS_PCI;
+	}
+
+	r = radeon_device_init(rdev, dev, dev->pdev, flags);
+	if (r) {
+		DRM_ERROR("Failed to initialize radeon, disabling IOCTL\n");
+		radeon_device_fini(rdev);
+		kfree(rdev);
+		dev->dev_private = NULL;
+		return r;
+	}
+	return 0;
+}
+
+int radeon_driver_unload_kms(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	radeon_device_fini(rdev);
+	kfree(rdev);
+	dev->dev_private = NULL;
+	return 0;
+}
+
+
+/*
+ * Userspace get informations ioctl
+ */
+int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_radeon_info *info;
+	uint32_t *value_ptr;
+	uint32_t value;
+
+	info = data;
+	value_ptr = (uint32_t *)((unsigned long)info->value);
+	switch (info->request) {
+	case RADEON_INFO_DEVICE_ID:
+		value = dev->pci_device;
+		break;
+	case RADEON_INFO_NUM_GB_PIPES:
+		value = rdev->num_gb_pipes;
+		break;
+	case RADEON_INFO_NUM_Z_PIPES:
+		value = rdev->num_z_pipes;
+		break;
+	default:
+		DRM_DEBUG("Invalid request %d\n", info->request);
+		return -EINVAL;
+	}
+	if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) {
+		DRM_ERROR("copy_to_user\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+
+/*
+ * Outdated mess for old drm with Xorg being in charge (void function now).
+ */
+int radeon_driver_firstopen_kms(struct drm_device *dev)
+{
+	return 0;
+}
+
+
+void radeon_driver_lastclose_kms(struct drm_device *dev)
+{
+}
+
+int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
+{
+	return 0;
+}
+
+void radeon_driver_postclose_kms(struct drm_device *dev,
+				 struct drm_file *file_priv)
+{
+}
+
+void radeon_driver_preclose_kms(struct drm_device *dev,
+				struct drm_file *file_priv)
+{
+}
+
+
+/*
+ * VBlank related functions.
+ */
+u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (crtc < 0 || crtc > 1) {
+		DRM_ERROR("Invalid crtc %d\n", crtc);
+		return -EINVAL;
+	}
+
+	return radeon_get_vblank_counter(rdev, crtc);
+}
+
+int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (crtc < 0 || crtc > 1) {
+		DRM_ERROR("Invalid crtc %d\n", crtc);
+		return -EINVAL;
+	}
+
+	rdev->irq.crtc_vblank_int[crtc] = true;
+
+	return radeon_irq_set(rdev);
+}
+
+void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (crtc < 0 || crtc > 1) {
+		DRM_ERROR("Invalid crtc %d\n", crtc);
+		return;
+	}
+
+	rdev->irq.crtc_vblank_int[crtc] = false;
+
+	radeon_irq_set(rdev);
+}
+
+
+/*
+ * For multiple master (like multiple X).
+ */
+struct drm_radeon_master_private {
+	drm_local_map_t *sarea;
+	drm_radeon_sarea_t *sarea_priv;
+};
+
+int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master)
+{
+	struct drm_radeon_master_private *master_priv;
+	unsigned long sareapage;
+	int ret;
+
+	master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
+	if (master_priv == NULL) {
+		return -ENOMEM;
+	}
+	/* prebuild the SAREA */
+	sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
+	ret = drm_addmap(dev, 0, sareapage, _DRM_SHM,
+			 _DRM_CONTAINS_LOCK,
+			 &master_priv->sarea);
+	if (ret) {
+		DRM_ERROR("SAREA setup failed\n");
+		return ret;
+	}
+	master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
+	master_priv->sarea_priv->pfCurrentPage = 0;
+	master->driver_priv = master_priv;
+	return 0;
+}
+
+void radeon_master_destroy_kms(struct drm_device *dev,
+			       struct drm_master *master)
+{
+	struct drm_radeon_master_private *master_priv = master->driver_priv;
+
+	if (master_priv == NULL) {
+		return;
+	}
+	if (master_priv->sarea) {
+		drm_rmmap_locked(dev, master_priv->sarea);
+	}
+	kfree(master_priv);
+	master->driver_priv = NULL;
+}
+
+
+/*
+ * IOCTL.
+ */
+int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	/* Not valid in KMS. */
+	return -EINVAL;
+}
+
+#define KMS_INVALID_IOCTL(name)						\
+int name(struct drm_device *dev, void *data, struct drm_file *file_priv)\
+{									\
+	DRM_ERROR("invalid ioctl with kms %s\n", __func__);		\
+	return -EINVAL;							\
+}
+
+/*
+ * All these ioctls are invalid in kms world.
+ */
+KMS_INVALID_IOCTL(radeon_cp_init_kms)
+KMS_INVALID_IOCTL(radeon_cp_start_kms)
+KMS_INVALID_IOCTL(radeon_cp_stop_kms)
+KMS_INVALID_IOCTL(radeon_cp_reset_kms)
+KMS_INVALID_IOCTL(radeon_cp_idle_kms)
+KMS_INVALID_IOCTL(radeon_cp_resume_kms)
+KMS_INVALID_IOCTL(radeon_engine_reset_kms)
+KMS_INVALID_IOCTL(radeon_fullscreen_kms)
+KMS_INVALID_IOCTL(radeon_cp_swap_kms)
+KMS_INVALID_IOCTL(radeon_cp_clear_kms)
+KMS_INVALID_IOCTL(radeon_cp_vertex_kms)
+KMS_INVALID_IOCTL(radeon_cp_indices_kms)
+KMS_INVALID_IOCTL(radeon_cp_texture_kms)
+KMS_INVALID_IOCTL(radeon_cp_stipple_kms)
+KMS_INVALID_IOCTL(radeon_cp_indirect_kms)
+KMS_INVALID_IOCTL(radeon_cp_vertex2_kms)
+KMS_INVALID_IOCTL(radeon_cp_cmdbuf_kms)
+KMS_INVALID_IOCTL(radeon_cp_getparam_kms)
+KMS_INVALID_IOCTL(radeon_cp_flip_kms)
+KMS_INVALID_IOCTL(radeon_mem_alloc_kms)
+KMS_INVALID_IOCTL(radeon_mem_free_kms)
+KMS_INVALID_IOCTL(radeon_mem_init_heap_kms)
+KMS_INVALID_IOCTL(radeon_irq_emit_kms)
+KMS_INVALID_IOCTL(radeon_irq_wait_kms)
+KMS_INVALID_IOCTL(radeon_cp_setparam_kms)
+KMS_INVALID_IOCTL(radeon_surface_alloc_kms)
+KMS_INVALID_IOCTL(radeon_surface_free_kms)
+
+
+struct drm_ioctl_desc radeon_ioctls_kms[] = {
+	DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
+	/* KMS */
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH),
+};
+int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,982 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/radeon_drm.h>
+#include "radeon_fixed.h"
+#include "radeon.h"
+
+static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
+				       struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	int xres = mode->hdisplay;
+	int yres = mode->vdisplay;
+	bool hscale = true, vscale = true;
+	int hsync_wid;
+	int vsync_wid;
+	int hsync_start;
+	int blank_width;
+	u32 scale, inc, crtc_more_cntl;
+	u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active;
+	u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp;
+	u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp;
+	struct radeon_native_mode *native_mode = &radeon_crtc->native_mode;
+
+	fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
+		(RADEON_VERT_STRETCH_RESERVED |
+		 RADEON_VERT_AUTO_RATIO_INC);
+	fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
+		(RADEON_HORZ_FP_LOOP_STRETCH |
+		 RADEON_HORZ_AUTO_RATIO_INC);
+
+	crtc_more_cntl = 0;
+	if ((rdev->family == CHIP_RS100) ||
+	    (rdev->family == CHIP_RS200)) {
+		/* This is to workaround the asic bug for RMX, some versions
+		   of BIOS dosen't have this register initialized correctly. */
+		crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
+	}
+
+
+	fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
+				| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
+
+	hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
+	if (!hsync_wid)
+		hsync_wid = 1;
+	hsync_start = mode->crtc_hsync_start - 8;
+
+	fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
+			      | ((hsync_wid & 0x3f) << 16)
+			      | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
+				 ? RADEON_CRTC_H_SYNC_POL
+				 : 0));
+
+	fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
+				| ((mode->crtc_vdisplay - 1) << 16));
+
+	vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	if (!vsync_wid)
+		vsync_wid = 1;
+
+	fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
+			      | ((vsync_wid & 0x1f) << 16)
+			      | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
+				 ? RADEON_CRTC_V_SYNC_POL
+				 : 0));
+
+	fp_horz_vert_active = 0;
+
+	if (native_mode->panel_xres == 0 ||
+	    native_mode->panel_yres == 0) {
+		hscale = false;
+		vscale = false;
+	} else {
+		if (xres > native_mode->panel_xres)
+			xres = native_mode->panel_xres;
+		if (yres > native_mode->panel_yres)
+			yres = native_mode->panel_yres;
+
+		if (xres == native_mode->panel_xres)
+			hscale = false;
+		if (yres == native_mode->panel_yres)
+			vscale = false;
+	}
+
+	switch (radeon_crtc->rmx_type) {
+	case RMX_FULL:
+	case RMX_ASPECT:
+		if (!hscale)
+			fp_horz_stretch |= ((xres/8-1) << 16);
+		else {
+			inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
+			scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
+				/ native_mode->panel_xres + 1;
+			fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
+					RADEON_HORZ_STRETCH_BLEND |
+					RADEON_HORZ_STRETCH_ENABLE |
+					((native_mode->panel_xres/8-1) << 16));
+		}
+
+		if (!vscale)
+			fp_vert_stretch |= ((yres-1) << 12);
+		else {
+			inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
+			scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
+				/ native_mode->panel_yres + 1;
+			fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
+					RADEON_VERT_STRETCH_ENABLE |
+					RADEON_VERT_STRETCH_BLEND |
+					((native_mode->panel_yres-1) << 12));
+		}
+		break;
+	case RMX_CENTER:
+		fp_horz_stretch |= ((xres/8-1) << 16);
+		fp_vert_stretch |= ((yres-1) << 12);
+
+		crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
+				RADEON_CRTC_AUTO_VERT_CENTER_EN);
+
+		blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
+		if (blank_width > 110)
+			blank_width = 110;
+
+		fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
+				| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
+
+		hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
+		if (!hsync_wid)
+			hsync_wid = 1;
+
+		fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
+				| ((hsync_wid & 0x3f) << 16)
+				| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
+					? RADEON_CRTC_H_SYNC_POL
+					: 0));
+
+		fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
+				| ((mode->crtc_vdisplay - 1) << 16));
+
+		vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
+		if (!vsync_wid)
+			vsync_wid = 1;
+
+		fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
+					| ((vsync_wid & 0x1f) << 16)
+					| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
+						? RADEON_CRTC_V_SYNC_POL
+						: 0)));
+
+		fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
+				(((native_mode->panel_xres / 8) & 0x1ff) << 16));
+		break;
+	case RMX_OFF:
+	default:
+		fp_horz_stretch |= ((xres/8-1) << 16);
+		fp_vert_stretch |= ((yres-1) << 12);
+		break;
+	}
+
+	WREG32(RADEON_FP_HORZ_STRETCH,      fp_horz_stretch);
+	WREG32(RADEON_FP_VERT_STRETCH,      fp_vert_stretch);
+	WREG32(RADEON_CRTC_MORE_CNTL,       crtc_more_cntl);
+	WREG32(RADEON_FP_HORZ_VERT_ACTIVE,  fp_horz_vert_active);
+	WREG32(RADEON_FP_H_SYNC_STRT_WID,   fp_h_sync_strt_wid);
+	WREG32(RADEON_FP_V_SYNC_STRT_WID,   fp_v_sync_strt_wid);
+	WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
+	WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
+}
+
+void radeon_restore_common_regs(struct drm_device *dev)
+{
+	/* don't need this yet */
+}
+
+static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	int i = 0;
+
+	/* FIXME: Certain revisions of R300 can't recover here.  Not sure of
+	   the cause yet, but this workaround will mask the problem for now.
+	   Other chips usually will pass at the very first test, so the
+	   workaround shouldn't have any effect on them. */
+	for (i = 0;
+	     (i < 10000 &&
+	      RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
+	     i++);
+}
+
+static void radeon_pll_write_update(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	while (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R);
+
+	WREG32_PLL_P(RADEON_PPLL_REF_DIV,
+			   RADEON_PPLL_ATOMIC_UPDATE_W,
+			   ~(RADEON_PPLL_ATOMIC_UPDATE_W));
+}
+
+static void radeon_pll2_wait_for_read_update_complete(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	int i = 0;
+
+
+	/* FIXME: Certain revisions of R300 can't recover here.  Not sure of
+	   the cause yet, but this workaround will mask the problem for now.
+	   Other chips usually will pass at the very first test, so the
+	   workaround shouldn't have any effect on them. */
+	for (i = 0;
+	     (i < 10000 &&
+	      RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
+	     i++);
+}
+
+static void radeon_pll2_write_update(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	while (RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R);
+
+	WREG32_PLL_P(RADEON_P2PLL_REF_DIV,
+			   RADEON_P2PLL_ATOMIC_UPDATE_W,
+			   ~(RADEON_P2PLL_ATOMIC_UPDATE_W));
+}
+
+static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div,
+				       uint16_t fb_div)
+{
+	unsigned int vcoFreq;
+
+	if (!ref_div)
+		return 1;
+
+	vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div;
+
+	/*
+	 * This is horribly crude: the VCO frequency range is divided into
+	 * 3 parts, each part having a fixed PLL gain value.
+	 */
+	if (vcoFreq >= 30000)
+		/*
+		 * [300..max] MHz : 7
+		 */
+		return 7;
+	else if (vcoFreq >= 18000)
+		/*
+		 * [180..300) MHz : 4
+		 */
+		return 4;
+	else
+		/*
+		 * [0..180) MHz : 1
+		 */
+		return 1;
+}
+
+void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t mask;
+
+	if (radeon_crtc->crtc_id)
+		mask = (RADEON_CRTC2_EN |
+			RADEON_CRTC2_DISP_DIS |
+			RADEON_CRTC2_VSYNC_DIS |
+			RADEON_CRTC2_HSYNC_DIS |
+			RADEON_CRTC2_DISP_REQ_EN_B);
+	else
+		mask = (RADEON_CRTC_DISPLAY_DIS |
+			RADEON_CRTC_VSYNC_DIS |
+			RADEON_CRTC_HSYNC_DIS);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		if (radeon_crtc->crtc_id)
+			WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask);
+		else {
+			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
+									 RADEON_CRTC_DISP_REQ_EN_B));
+			WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
+		}
+		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
+		radeon_crtc_load_lut(crtc);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
+		if (radeon_crtc->crtc_id)
+			WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
+		else {
+			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
+										    RADEON_CRTC_DISP_REQ_EN_B));
+			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
+		}
+		break;
+	}
+}
+
+/* properly set crtc bpp when using atombios */
+void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	int format;
+	uint32_t crtc_gen_cntl;
+	uint32_t disp_merge_cntl;
+	uint32_t crtc_pitch;
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 15:      /*  555 */
+		format = 3;
+		break;
+	case 16:      /*  565 */
+		format = 4;
+		break;
+	case 24:      /*  RGB */
+		format = 5;
+		break;
+	case 32:      /* xRGB */
+		format = 6;
+		break;
+	default:
+		return;
+	}
+
+	crtc_pitch  = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) +
+			((crtc->fb->bits_per_pixel * 8) - 1)) /
+		       (crtc->fb->bits_per_pixel * 8));
+	crtc_pitch |= crtc_pitch << 16;
+
+	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
+
+	switch (radeon_crtc->crtc_id) {
+	case 0:
+		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
+		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
+
+		crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
+		crtc_gen_cntl |= (format << 8);
+		crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN;
+		WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
+		break;
+	case 1:
+		disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
+		disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
+		WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
+
+		crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
+		crtc_gen_cntl |= (format << 8);
+		WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl);
+		WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
+		WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
+		break;
+	}
+}
+
+int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+			 struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_framebuffer *radeon_fb;
+	struct drm_gem_object *obj;
+	uint64_t base;
+	uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
+	uint32_t crtc_pitch, pitch_pixels;
+	uint32_t tiling_flags;
+
+	DRM_DEBUG("\n");
+
+	radeon_fb = to_radeon_framebuffer(crtc->fb);
+
+	obj = radeon_fb->obj;
+	if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) {
+		return -EINVAL;
+	}
+	/* if scanout was in GTT this really wouldn't work */
+	/* crtc offset is from display base addr not FB location */
+	radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
+
+	base -= radeon_crtc->legacy_display_base_addr;
+
+	crtc_offset_cntl = 0;
+
+	pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
+	crtc_pitch  = (((pitch_pixels * crtc->fb->bits_per_pixel) +
+			((crtc->fb->bits_per_pixel * 8) - 1)) /
+		       (crtc->fb->bits_per_pixel * 8));
+	crtc_pitch |= crtc_pitch << 16;
+
+	radeon_object_get_tiling_flags(obj->driver_private,
+				       &tiling_flags, NULL);
+	if (tiling_flags & RADEON_TILING_MICRO)
+		DRM_ERROR("trying to scanout microtiled buffer\n");
+
+	if (tiling_flags & RADEON_TILING_MACRO) {
+		if (ASIC_IS_R300(rdev))
+			crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
+					     R300_CRTC_MICRO_TILE_BUFFER_DIS |
+					     R300_CRTC_MACRO_TILE_EN);
+		else
+			crtc_offset_cntl |= RADEON_CRTC_TILE_EN;
+	} else {
+		if (ASIC_IS_R300(rdev))
+			crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN |
+					      R300_CRTC_MICRO_TILE_BUFFER_DIS |
+					      R300_CRTC_MACRO_TILE_EN);
+		else
+			crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
+	}
+
+	if (tiling_flags & RADEON_TILING_MACRO) {
+		if (ASIC_IS_R300(rdev)) {
+			crtc_tile_x0_y0 = x | (y << 16);
+			base &= ~0x7ff;
+		} else {
+			int byteshift = crtc->fb->bits_per_pixel >> 4;
+			int tile_addr = (((y >> 3) * pitch_pixels +  x) >> (8 - byteshift)) << 11;
+			base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
+			crtc_offset_cntl |= (y % 16);
+		}
+	} else {
+		int offset = y * pitch_pixels + x;
+		switch (crtc->fb->bits_per_pixel) {
+		case 15:
+		case 16:
+			offset *= 2;
+			break;
+		case 24:
+			offset *= 3;
+			break;
+		case 32:
+			offset *= 4;
+			break;
+		default:
+			return false;
+		}
+		base += offset;
+	}
+
+	base &= ~7;
+
+	crtc_offset = (u32)base;
+
+	WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr);
+
+	if (ASIC_IS_R300(rdev)) {
+		if (radeon_crtc->crtc_id)
+			WREG32(R300_CRTC2_TILE_X0_Y0, crtc_tile_x0_y0);
+		else
+			WREG32(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0);
+	}
+	WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, crtc_offset_cntl);
+	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
+	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
+
+	if (old_fb && old_fb != crtc->fb) {
+		radeon_fb = to_radeon_framebuffer(old_fb);
+		radeon_gem_object_unpin(radeon_fb->obj);
+	}
+	return 0;
+}
+
+static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	int format;
+	int hsync_start;
+	int hsync_wid;
+	int vsync_wid;
+	uint32_t crtc_h_total_disp;
+	uint32_t crtc_h_sync_strt_wid;
+	uint32_t crtc_v_total_disp;
+	uint32_t crtc_v_sync_strt_wid;
+
+	DRM_DEBUG("\n");
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 15:      /*  555 */
+		format = 3;
+		break;
+	case 16:      /*  565 */
+		format = 4;
+		break;
+	case 24:      /*  RGB */
+		format = 5;
+		break;
+	case 32:      /* xRGB */
+		format = 6;
+		break;
+	default:
+		return false;
+	}
+
+	crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
+			     | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
+
+	hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
+	if (!hsync_wid)
+		hsync_wid = 1;
+	hsync_start = mode->crtc_hsync_start - 8;
+
+	crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
+				| ((hsync_wid & 0x3f) << 16)
+				| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
+				   ? RADEON_CRTC_H_SYNC_POL
+				   : 0));
+
+	/* This works for double scan mode. */
+	crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
+			     | ((mode->crtc_vdisplay - 1) << 16));
+
+	vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	if (!vsync_wid)
+		vsync_wid = 1;
+
+	crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
+				| ((vsync_wid & 0x1f) << 16)
+				| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
+				   ? RADEON_CRTC_V_SYNC_POL
+				   : 0));
+
+	/* TODO -> Dell Server */
+	if (0) {
+		uint32_t disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+		uint32_t tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
+		uint32_t dac2_cntl = RREG32(RADEON_DAC_CNTL2);
+		uint32_t crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+
+		dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
+		dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
+
+		/* For CRT on DAC2, don't turn it on if BIOS didn't
+		   enable it, even it's detected.
+		*/
+		disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
+		tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
+		tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
+
+		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
+		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+	}
+
+	if (radeon_crtc->crtc_id) {
+		uint32_t crtc2_gen_cntl;
+		uint32_t disp2_merge_cntl;
+
+		/* check to see if TV DAC is enabled for another crtc and keep it enabled */
+		if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON)
+			crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
+		else
+			crtc2_gen_cntl = 0;
+
+		crtc2_gen_cntl |= ((format << 8)
+				   | RADEON_CRTC2_VSYNC_DIS
+				   | RADEON_CRTC2_HSYNC_DIS
+				   | RADEON_CRTC2_DISP_DIS
+				   | RADEON_CRTC2_DISP_REQ_EN_B
+				   | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
+				      ? RADEON_CRTC2_DBL_SCAN_EN
+				      : 0)
+				   | ((mode->flags & DRM_MODE_FLAG_CSYNC)
+				      ? RADEON_CRTC2_CSYNC_EN
+				      : 0)
+				   | ((mode->flags & DRM_MODE_FLAG_INTERLACE)
+				      ? RADEON_CRTC2_INTERLACE_EN
+				      : 0));
+
+		disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
+		disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
+
+		WREG32(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl);
+		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+	} else {
+		uint32_t crtc_gen_cntl;
+		uint32_t crtc_ext_cntl;
+		uint32_t disp_merge_cntl;
+
+		crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
+				 | (format << 8)
+				 | RADEON_CRTC_DISP_REQ_EN_B
+				 | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
+				    ? RADEON_CRTC_DBL_SCAN_EN
+				    : 0)
+				 | ((mode->flags & DRM_MODE_FLAG_CSYNC)
+				    ? RADEON_CRTC_CSYNC_EN
+				    : 0)
+				 | ((mode->flags & DRM_MODE_FLAG_INTERLACE)
+				    ? RADEON_CRTC_INTERLACE_EN
+				    : 0));
+
+		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+		crtc_ext_cntl |= (RADEON_XCRT_CNT_EN |
+				  RADEON_CRTC_VSYNC_DIS |
+				  RADEON_CRTC_HSYNC_DIS |
+				  RADEON_CRTC_DISPLAY_DIS);
+
+		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
+		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+
+		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
+		WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
+		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+	}
+
+	WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp);
+	WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid);
+	WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp);
+	WREG32(RADEON_CRTC_V_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_v_sync_strt_wid);
+
+	return true;
+}
+
+static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_encoder *encoder;
+	uint32_t feedback_div = 0;
+	uint32_t frac_fb_div = 0;
+	uint32_t reference_div = 0;
+	uint32_t post_divider = 0;
+	uint32_t freq = 0;
+	uint8_t pll_gain;
+	int pll_flags = RADEON_PLL_LEGACY;
+	bool use_bios_divs = false;
+	/* PLL registers */
+	uint32_t pll_ref_div = 0;
+	uint32_t pll_fb_post_div = 0;
+	uint32_t htotal_cntl = 0;
+
+	struct radeon_pll *pll;
+
+	struct {
+		int divider;
+		int bitvalue;
+	} *post_div, post_divs[]   = {
+		/* From RAGE 128 VR/RAGE 128 GL Register
+		 * Reference Manual (Technical Reference
+		 * Manual P/N RRG-G04100-C Rev. 0.04), page
+		 * 3-17 (PLL_DIV_[3:0]).
+		 */
+		{  1, 0 },              /* VCLK_SRC                 */
+		{  2, 1 },              /* VCLK_SRC/2               */
+		{  4, 2 },              /* VCLK_SRC/4               */
+		{  8, 3 },              /* VCLK_SRC/8               */
+		{  3, 4 },              /* VCLK_SRC/3               */
+		{ 16, 5 },              /* VCLK_SRC/16              */
+		{  6, 6 },              /* VCLK_SRC/6               */
+		{ 12, 7 },              /* VCLK_SRC/12              */
+		{  0, 0 }
+	};
+
+	if (radeon_crtc->crtc_id)
+		pll = &rdev->clock.p2pll;
+	else
+		pll = &rdev->clock.p1pll;
+
+	if (mode->clock > 200000) /* range limits??? */
+		pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+	else
+		pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc == crtc) {
+			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
+				pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+			if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
+				struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+				struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
+				if (lvds) {
+					if (lvds->use_bios_dividers) {
+						pll_ref_div = lvds->panel_ref_divider;
+						pll_fb_post_div   = (lvds->panel_fb_divider |
+								     (lvds->panel_post_divider << 16));
+						htotal_cntl  = 0;
+						use_bios_divs = true;
+					}
+				}
+				pll_flags |= RADEON_PLL_USE_REF_DIV;
+			}
+		}
+	}
+
+	DRM_DEBUG("\n");
+
+	if (!use_bios_divs) {
+		radeon_compute_pll(pll, mode->clock,
+				   &freq, &feedback_div, &frac_fb_div,
+				   &reference_div, &post_divider,
+				   pll_flags);
+
+		for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+			if (post_div->divider == post_divider)
+				break;
+		}
+
+		if (!post_div->divider)
+			post_div = &post_divs[0];
+
+		DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n",
+			  (unsigned)freq,
+			  feedback_div,
+			  reference_div,
+			  post_divider);
+
+		pll_ref_div   = reference_div;
+#if defined(__powerpc__) && (0) /* TODO */
+		/* apparently programming this otherwise causes a hang??? */
+		if (info->MacModel == RADEON_MAC_IBOOK)
+			pll_fb_post_div = 0x000600ad;
+		else
+#endif
+			pll_fb_post_div     = (feedback_div | (post_div->bitvalue << 16));
+
+		htotal_cntl    = mode->htotal & 0x7;
+
+	}
+
+	pll_gain = radeon_compute_pll_gain(pll->reference_freq,
+					   pll_ref_div & 0x3ff,
+					   pll_fb_post_div & 0x7ff);
+
+	if (radeon_crtc->crtc_id) {
+		uint32_t pixclks_cntl = ((RREG32_PLL(RADEON_PIXCLKS_CNTL) &
+					  ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
+					 RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
+
+		WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
+			     RADEON_PIX2CLK_SRC_SEL_CPUCLK,
+			     ~(RADEON_PIX2CLK_SRC_SEL_MASK));
+
+		WREG32_PLL_P(RADEON_P2PLL_CNTL,
+			     RADEON_P2PLL_RESET
+			     | RADEON_P2PLL_ATOMIC_UPDATE_EN
+			     | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT),
+			     ~(RADEON_P2PLL_RESET
+			       | RADEON_P2PLL_ATOMIC_UPDATE_EN
+			       | RADEON_P2PLL_PVG_MASK));
+
+		WREG32_PLL_P(RADEON_P2PLL_REF_DIV,
+			     pll_ref_div,
+			     ~RADEON_P2PLL_REF_DIV_MASK);
+
+		WREG32_PLL_P(RADEON_P2PLL_DIV_0,
+			     pll_fb_post_div,
+			     ~RADEON_P2PLL_FB0_DIV_MASK);
+
+		WREG32_PLL_P(RADEON_P2PLL_DIV_0,
+			     pll_fb_post_div,
+			     ~RADEON_P2PLL_POST0_DIV_MASK);
+
+		radeon_pll2_write_update(dev);
+		radeon_pll2_wait_for_read_update_complete(dev);
+
+		WREG32_PLL(RADEON_HTOTAL2_CNTL, htotal_cntl);
+
+		WREG32_PLL_P(RADEON_P2PLL_CNTL,
+			     0,
+			     ~(RADEON_P2PLL_RESET
+			       | RADEON_P2PLL_SLEEP
+			       | RADEON_P2PLL_ATOMIC_UPDATE_EN));
+
+		DRM_DEBUG("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
+			  (unsigned)pll_ref_div,
+			  (unsigned)pll_fb_post_div,
+			  (unsigned)htotal_cntl,
+			  RREG32_PLL(RADEON_P2PLL_CNTL));
+		DRM_DEBUG("Wrote2: rd=%u, fd=%u, pd=%u\n",
+			  (unsigned)pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
+			  (unsigned)pll_fb_post_div & RADEON_P2PLL_FB0_DIV_MASK,
+			  (unsigned)((pll_fb_post_div &
+				      RADEON_P2PLL_POST0_DIV_MASK) >> 16));
+
+		mdelay(50); /* Let the clock to lock */
+
+		WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
+			     RADEON_PIX2CLK_SRC_SEL_P2PLLCLK,
+			     ~(RADEON_PIX2CLK_SRC_SEL_MASK));
+
+		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
+	} else {
+		if (rdev->flags & RADEON_IS_MOBILITY) {
+			/* A temporal workaround for the occational blanking on certain laptop panels.
+			   This appears to related to the PLL divider registers (fail to lock?).
+			   It occurs even when all dividers are the same with their old settings.
+			   In this case we really don't need to fiddle with PLL registers.
+			   By doing this we can avoid the blanking problem with some panels.
+			*/
+			if ((pll_ref_div == (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) &&
+			    (pll_fb_post_div == (RREG32_PLL(RADEON_PPLL_DIV_3) &
+						 (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) {
+				WREG32_P(RADEON_CLOCK_CNTL_INDEX,
+					 RADEON_PLL_DIV_SEL,
+					 ~(RADEON_PLL_DIV_SEL));
+				r100_pll_errata_after_index(rdev);
+				return;
+			}
+		}
+
+		WREG32_PLL_P(RADEON_VCLK_ECP_CNTL,
+			     RADEON_VCLK_SRC_SEL_CPUCLK,
+			     ~(RADEON_VCLK_SRC_SEL_MASK));
+		WREG32_PLL_P(RADEON_PPLL_CNTL,
+			     RADEON_PPLL_RESET
+			     | RADEON_PPLL_ATOMIC_UPDATE_EN
+			     | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
+			     | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT),
+			     ~(RADEON_PPLL_RESET
+			       | RADEON_PPLL_ATOMIC_UPDATE_EN
+			       | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN
+			       | RADEON_PPLL_PVG_MASK));
+
+		WREG32_P(RADEON_CLOCK_CNTL_INDEX,
+			 RADEON_PLL_DIV_SEL,
+			 ~(RADEON_PLL_DIV_SEL));
+		r100_pll_errata_after_index(rdev);
+
+		if (ASIC_IS_R300(rdev) ||
+		    (rdev->family == CHIP_RS300) ||
+		    (rdev->family == CHIP_RS400) ||
+		    (rdev->family == CHIP_RS480)) {
+			if (pll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
+				/* When restoring console mode, use saved PPLL_REF_DIV
+				 * setting.
+				 */
+				WREG32_PLL_P(RADEON_PPLL_REF_DIV,
+					     pll_ref_div,
+					     0);
+			} else {
+				/* R300 uses ref_div_acc field as real ref divider */
+				WREG32_PLL_P(RADEON_PPLL_REF_DIV,
+					     (pll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
+					     ~R300_PPLL_REF_DIV_ACC_MASK);
+			}
+		} else
+			WREG32_PLL_P(RADEON_PPLL_REF_DIV,
+				     pll_ref_div,
+				     ~RADEON_PPLL_REF_DIV_MASK);
+
+		WREG32_PLL_P(RADEON_PPLL_DIV_3,
+			     pll_fb_post_div,
+			     ~RADEON_PPLL_FB3_DIV_MASK);
+
+		WREG32_PLL_P(RADEON_PPLL_DIV_3,
+			     pll_fb_post_div,
+			     ~RADEON_PPLL_POST3_DIV_MASK);
+
+		radeon_pll_write_update(dev);
+		radeon_pll_wait_for_read_update_complete(dev);
+
+		WREG32_PLL(RADEON_HTOTAL_CNTL, htotal_cntl);
+
+		WREG32_PLL_P(RADEON_PPLL_CNTL,
+			     0,
+			     ~(RADEON_PPLL_RESET
+			       | RADEON_PPLL_SLEEP
+			       | RADEON_PPLL_ATOMIC_UPDATE_EN
+			       | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN));
+
+		DRM_DEBUG("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
+			  pll_ref_div,
+			  pll_fb_post_div,
+			  (unsigned)htotal_cntl,
+			  RREG32_PLL(RADEON_PPLL_CNTL));
+		DRM_DEBUG("Wrote: rd=%d, fd=%d, pd=%d\n",
+			  pll_ref_div & RADEON_PPLL_REF_DIV_MASK,
+			  pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK,
+			  (pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16);
+
+		mdelay(50); /* Let the clock to lock */
+
+		WREG32_PLL_P(RADEON_VCLK_ECP_CNTL,
+			     RADEON_VCLK_SRC_SEL_PPLLCLK,
+			     ~(RADEON_VCLK_SRC_SEL_MASK));
+
+	}
+}
+
+static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
+		return false;
+	return true;
+}
+
+static int radeon_crtc_mode_set(struct drm_crtc *crtc,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode,
+				 int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	/* TODO TV */
+	radeon_crtc_set_base(crtc, x, y, old_fb);
+	radeon_set_crtc_timing(crtc, adjusted_mode);
+	radeon_set_pll(crtc, adjusted_mode);
+	radeon_bandwidth_update(rdev);
+	if (radeon_crtc->crtc_id == 0) {
+		radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
+	} else {
+		if (radeon_crtc->rmx_type != RMX_OFF) {
+			/* FIXME: only first crtc has rmx what should we
+			 * do ?
+			 */
+			DRM_ERROR("Mode need scaling but only first crtc can do that.\n");
+		}
+	}
+	return 0;
+}
+
+static void radeon_crtc_prepare(struct drm_crtc *crtc)
+{
+	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void radeon_crtc_commit(struct drm_crtc *crtc)
+{
+	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
+	.dpms = radeon_crtc_dpms,
+	.mode_fixup = radeon_crtc_mode_fixup,
+	.mode_set = radeon_crtc_mode_set,
+	.mode_set_base = radeon_crtc_set_base,
+	.prepare = radeon_crtc_prepare,
+	.commit = radeon_crtc_commit,
+};
+
+
+void radeon_legacy_init_crtc(struct drm_device *dev,
+			       struct radeon_crtc *radeon_crtc)
+{
+	if (radeon_crtc->crtc_id == 1)
+		radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP;
+	drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1109 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+
+static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
+	int panel_pwr_delay = 2000;
+	DRM_DEBUG("\n");
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			panel_pwr_delay = lvds->panel_pwr_delay;
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			panel_pwr_delay = lvds->panel_pwr_delay;
+		}
+	}
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
+		disp_pwr_man |= RADEON_AUTO_PWRUP_EN;
+		WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man);
+		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
+		lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
+		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
+		udelay(1000);
+
+		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
+		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
+		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
+
+		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
+		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
+		udelay(panel_pwr_delay * 1000);
+		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
+		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
+		lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
+		udelay(panel_pwr_delay * 1000);
+		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
+		break;
+	}
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+	else
+		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+}
+
+static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, true);
+	else
+		radeon_combios_output_lock(encoder, true);
+	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON);
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, false);
+	else
+		radeon_combios_output_lock(encoder, false);
+}
+
+static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
+					struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl;
+
+	DRM_DEBUG("\n");
+
+	lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
+	lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
+
+	lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
+	if ((!rdev->is_atom_bios)) {
+		struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
+		if (lvds) {
+			DRM_DEBUG("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
+			lvds_gen_cntl = lvds->lvds_gen_cntl;
+			lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
+					      (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
+			lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) |
+					     (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
+		} else
+			lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	} else
+		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
+	lvds_gen_cntl &= ~(RADEON_LVDS_ON |
+			   RADEON_LVDS_BLON |
+			   RADEON_LVDS_EN |
+			   RADEON_LVDS_RST_FM);
+
+	if (ASIC_IS_R300(rdev))
+		lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK);
+
+	if (radeon_crtc->crtc_id == 0) {
+		if (ASIC_IS_R300(rdev)) {
+			if (radeon_encoder->rmx_type != RMX_OFF)
+				lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
+		} else
+			lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
+	} else {
+		if (ASIC_IS_R300(rdev))
+			lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2;
+		else
+			lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
+	}
+
+	WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+	WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
+	WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl);
+
+	if (rdev->family == CHIP_RV410)
+		WREG32(RADEON_CLOCK_CNTL_INDEX, 0);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+	else
+		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+}
+
+static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
+					  struct drm_display_mode *mode,
+					  struct drm_display_mode *adjusted_mode)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	if (radeon_encoder->rmx_type != RMX_OFF)
+		radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
+
+	return true;
+}
+
+static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
+	.dpms = radeon_legacy_lvds_dpms,
+	.mode_fixup = radeon_legacy_lvds_mode_fixup,
+	.prepare = radeon_legacy_lvds_prepare,
+	.mode_set = radeon_legacy_lvds_mode_set,
+	.commit = radeon_legacy_lvds_commit,
+};
+
+
+static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder,
+						 struct drm_display_mode *mode,
+						 struct drm_display_mode *adjusted_mode)
+{
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	return true;
+}
+
+static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+	uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL);
+	uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
+
+	DRM_DEBUG("\n");
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
+		dac_cntl &= ~RADEON_DAC_PDWN;
+		dac_macro_cntl &= ~(RADEON_DAC_PDWN_R |
+				    RADEON_DAC_PDWN_G |
+				    RADEON_DAC_PDWN_B);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
+		dac_cntl |= RADEON_DAC_PDWN;
+		dac_macro_cntl |= (RADEON_DAC_PDWN_R |
+				   RADEON_DAC_PDWN_G |
+				   RADEON_DAC_PDWN_B);
+		break;
+	}
+
+	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+	WREG32(RADEON_DAC_CNTL, dac_cntl);
+	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+	else
+		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+}
+
+static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, true);
+	else
+		radeon_combios_output_lock(encoder, true);
+	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, false);
+	else
+		radeon_combios_output_lock(encoder, false);
+}
+
+static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
+					       struct drm_display_mode *mode,
+					       struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl;
+
+	DRM_DEBUG("\n");
+
+	if (radeon_crtc->crtc_id == 0) {
+		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
+			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
+				~(RADEON_DISP_DAC_SOURCE_MASK);
+			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+		} else {
+			dac2_cntl = RREG32(RADEON_DAC_CNTL2)  & ~(RADEON_DAC2_DAC_CLK_SEL);
+			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
+		}
+	} else {
+		if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
+			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
+				~(RADEON_DISP_DAC_SOURCE_MASK);
+			disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2;
+			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+		} else {
+			dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL;
+			WREG32(RADEON_DAC_CNTL2, dac2_cntl);
+		}
+	}
+
+	dac_cntl = (RADEON_DAC_MASK_ALL |
+		    RADEON_DAC_VGA_ADR_EN |
+		    /* TODO 6-bits */
+		    RADEON_DAC_8BIT_EN);
+
+	WREG32_P(RADEON_DAC_CNTL,
+		       dac_cntl,
+		       RADEON_DAC_RANGE_CNTL |
+		       RADEON_DAC_BLANKING);
+
+	if (radeon_encoder->enc_priv) {
+		struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv;
+		dac_macro_cntl = p_dac->ps2_pdac_adj;
+	} else
+		dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
+	dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B;
+	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+	else
+		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+}
+
+static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder,
+								  struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t vclk_ecp_cntl, crtc_ext_cntl;
+	uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
+	enum drm_connector_status found = connector_status_disconnected;
+	bool color = true;
+
+	/* save the regs we need */
+	vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
+	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
+	dac_cntl = RREG32(RADEON_DAC_CNTL);
+	dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL);
+
+	tmp = vclk_ecp_cntl &
+		~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
+	WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
+
+	tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+	WREG32(RADEON_CRTC_EXT_CNTL, tmp);
+
+	tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
+		RADEON_DAC_FORCE_DATA_EN;
+
+	if (color)
+		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
+	else
+		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
+
+	if (ASIC_IS_R300(rdev))
+		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+	else
+		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
+
+	WREG32(RADEON_DAC_EXT_CNTL, tmp);
+
+	tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
+	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
+	WREG32(RADEON_DAC_CNTL, tmp);
+
+	tmp &= ~(RADEON_DAC_PDWN_R |
+		 RADEON_DAC_PDWN_G |
+		 RADEON_DAC_PDWN_B);
+
+	WREG32(RADEON_DAC_MACRO_CNTL, tmp);
+
+	udelay(2000);
+
+	if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
+		found = connector_status_connected;
+
+	/* restore the regs we used */
+	WREG32(RADEON_DAC_CNTL, dac_cntl);
+	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
+	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+	WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
+
+	return found;
+}
+
+static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
+	.dpms = radeon_legacy_primary_dac_dpms,
+	.mode_fixup = radeon_legacy_primary_dac_mode_fixup,
+	.prepare = radeon_legacy_primary_dac_prepare,
+	.mode_set = radeon_legacy_primary_dac_mode_set,
+	.commit = radeon_legacy_primary_dac_commit,
+	.detect = radeon_legacy_primary_dac_detect,
+};
+
+
+static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder,
+					      struct drm_display_mode *mode,
+					      struct drm_display_mode *adjusted_mode)
+{
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	return true;
+}
+
+static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL);
+	DRM_DEBUG("\n");
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+		break;
+	}
+
+	WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+	else
+		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+}
+
+static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, true);
+	else
+		radeon_combios_output_lock(encoder, true);
+	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, true);
+	else
+		radeon_combios_output_lock(encoder, true);
+}
+
+static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
+					    struct drm_display_mode *mode,
+					    struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl;
+	int i;
+
+	DRM_DEBUG("\n");
+
+	tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
+	tmp &= 0xfffff;
+	if (rdev->family == CHIP_RV280) {
+		/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
+		tmp ^= (1 << 22);
+		tmds_pll_cntl ^= (1 << 22);
+	}
+
+	if (radeon_encoder->enc_priv) {
+		struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv;
+
+		for (i = 0; i < 4; i++) {
+			if (tmds->tmds_pll[i].freq == 0)
+				break;
+			if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) {
+				tmp = tmds->tmds_pll[i].value ;
+				break;
+			}
+		}
+	}
+
+	if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) {
+		if (tmp & 0xfff00000)
+			tmds_pll_cntl = tmp;
+		else {
+			tmds_pll_cntl &= 0xfff00000;
+			tmds_pll_cntl |= tmp;
+		}
+	} else
+		tmds_pll_cntl = tmp;
+
+	tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) &
+		~(RADEON_TMDS_TRANSMITTER_PLLRST);
+
+    if (rdev->family == CHIP_R200 ||
+	rdev->family == CHIP_R100 ||
+	ASIC_IS_R300(rdev))
+	    tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
+    else /* RV chips got this bit reversed */
+	    tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN;
+
+    fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) |
+		   (RADEON_FP_CRTC_DONT_SHADOW_VPAR |
+		    RADEON_FP_CRTC_DONT_SHADOW_HEND));
+
+    fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
+
+    if (1) /*  FIXME rgbBits == 8 */
+	    fp_gen_cntl |= RADEON_FP_PANEL_FORMAT;  /* 24 bit format */
+    else
+	    fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
+
+    if (radeon_crtc->crtc_id == 0) {
+	    if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
+		    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
+		    if (radeon_encoder->rmx_type != RMX_OFF)
+			    fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
+		    else
+			    fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
+	    } else
+		    fp_gen_cntl |= RADEON_FP_SEL_CRTC1;
+    } else {
+	    if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
+		    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
+		    fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2;
+	    } else
+		    fp_gen_cntl |= RADEON_FP_SEL_CRTC2;
+    }
+
+    WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl);
+    WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl);
+    WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+	else
+		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+}
+
+static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
+	.dpms = radeon_legacy_tmds_int_dpms,
+	.mode_fixup = radeon_legacy_tmds_int_mode_fixup,
+	.prepare = radeon_legacy_tmds_int_prepare,
+	.mode_set = radeon_legacy_tmds_int_mode_set,
+	.commit = radeon_legacy_tmds_int_commit,
+};
+
+
+static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder,
+					      struct drm_display_mode *mode,
+					      struct drm_display_mode *adjusted_mode)
+{
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	return true;
+}
+
+static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+	DRM_DEBUG("\n");
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN;
+		fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		fp2_gen_cntl |= RADEON_FP2_BLANK_EN;
+		fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		break;
+	}
+
+	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+	else
+		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+}
+
+static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, true);
+	else
+		radeon_combios_output_lock(encoder, true);
+	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, false);
+	else
+		radeon_combios_output_lock(encoder, false);
+}
+
+static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
+					    struct drm_display_mode *mode,
+					    struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t fp2_gen_cntl;
+
+	DRM_DEBUG("\n");
+
+	if (rdev->is_atom_bios) {
+		radeon_encoder->pixel_clock = adjusted_mode->clock;
+		atombios_external_tmds_setup(encoder, ATOM_ENABLE);
+		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+	} else {
+		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+
+		if (1) /*  FIXME rgbBits == 8 */
+			fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */
+		else
+			fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */
+
+		fp2_gen_cntl &= ~(RADEON_FP2_ON |
+				  RADEON_FP2_DVO_EN |
+				  RADEON_FP2_DVO_RATE_SEL_SDR);
+
+		/* XXX: these are oem specific */
+		if (ASIC_IS_R300(rdev)) {
+			if ((dev->pdev->device == 0x4850) &&
+			    (dev->pdev->subsystem_vendor == 0x1028) &&
+			    (dev->pdev->subsystem_device == 0x2001)) /* Dell Inspiron 8600 */
+				fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE;
+			else
+				fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
+
+			/*if (mode->clock > 165000)
+			  fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
+		}
+	}
+
+	if (radeon_crtc->crtc_id == 0) {
+		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
+			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
+			if (radeon_encoder->rmx_type != RMX_OFF)
+				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
+			else
+				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
+		} else
+			fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
+	} else {
+		if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
+			fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
+			fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
+		} else
+			fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
+	}
+
+	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+	else
+		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+}
+
+static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
+	.dpms = radeon_legacy_tmds_ext_dpms,
+	.mode_fixup = radeon_legacy_tmds_ext_mode_fixup,
+	.prepare = radeon_legacy_tmds_ext_prepare,
+	.mode_set = radeon_legacy_tmds_ext_mode_set,
+	.commit = radeon_legacy_tmds_ext_commit,
+};
+
+
+static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder,
+					    struct drm_display_mode *mode,
+					    struct drm_display_mode *adjusted_mode)
+{
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+	return true;
+}
+
+static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
+	/* uint32_t tv_master_cntl = 0; */
+
+	DRM_DEBUG("\n");
+
+	if (rdev->family == CHIP_R200)
+		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+	else {
+		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+		/*  FIXME TV */
+		/* tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); */
+		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
+	}
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		if (rdev->family == CHIP_R200) {
+			fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		} else {
+			crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
+			/* tv_master_cntl |= RADEON_TV_ON; */
+			if (rdev->family == CHIP_R420 ||
+					rdev->family == CHIP_R423 ||
+					rdev->family == CHIP_RV410)
+				tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
+						R420_TV_DAC_GDACPD |
+						R420_TV_DAC_BDACPD |
+						RADEON_TV_DAC_BGSLEEP);
+			else
+				tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
+						RADEON_TV_DAC_GDACPD |
+						RADEON_TV_DAC_BDACPD |
+						RADEON_TV_DAC_BGSLEEP);
+		}
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		if (rdev->family == CHIP_R200)
+			fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
+		else {
+			crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
+			/* tv_master_cntl &= ~RADEON_TV_ON; */
+			if (rdev->family == CHIP_R420 ||
+					rdev->family == CHIP_R423 ||
+					rdev->family == CHIP_RV410)
+				tv_dac_cntl |= (R420_TV_DAC_RDACPD |
+						R420_TV_DAC_GDACPD |
+						R420_TV_DAC_BDACPD |
+						RADEON_TV_DAC_BGSLEEP);
+			else
+				tv_dac_cntl |= (RADEON_TV_DAC_RDACPD |
+						RADEON_TV_DAC_GDACPD |
+						RADEON_TV_DAC_BDACPD |
+						RADEON_TV_DAC_BGSLEEP);
+		}
+		break;
+	}
+
+	if (rdev->family == CHIP_R200) {
+		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+	} else {
+		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+		/* WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); */
+		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+	}
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+	else
+		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+}
+
+static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, true);
+	else
+		radeon_combios_output_lock(encoder, true);
+	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+
+	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	if (rdev->is_atom_bios)
+		radeon_atom_output_lock(encoder, true);
+	else
+		radeon_combios_output_lock(encoder, true);
+}
+
+static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
+	uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0;
+
+	DRM_DEBUG("\n");
+
+	if (rdev->family != CHIP_R200) {
+		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
+		if (rdev->family == CHIP_R420 ||
+				rdev->family == CHIP_R423 ||
+				rdev->family == CHIP_RV410) {
+			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
+					RADEON_TV_DAC_BGADJ_MASK |
+					R420_TV_DAC_DACADJ_MASK |
+					R420_TV_DAC_RDACPD |
+					R420_TV_DAC_GDACPD |
+					R420_TV_DAC_GDACPD |
+					R420_TV_DAC_TVENABLE);
+		} else {
+			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK |
+					RADEON_TV_DAC_BGADJ_MASK |
+					RADEON_TV_DAC_DACADJ_MASK |
+					RADEON_TV_DAC_RDACPD |
+					RADEON_TV_DAC_GDACPD |
+					RADEON_TV_DAC_GDACPD);
+		}
+
+		/*  FIXME TV */
+		if (radeon_encoder->enc_priv) {
+			struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
+			tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
+					RADEON_TV_DAC_NHOLD |
+					RADEON_TV_DAC_STD_PS2 |
+					tv_dac->ps2_tvdac_adj);
+		} else
+			tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
+					RADEON_TV_DAC_NHOLD |
+					RADEON_TV_DAC_STD_PS2);
+
+		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+	}
+
+	if (ASIC_IS_R300(rdev)) {
+		gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
+		disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+	} else if (rdev->family == CHIP_R200)
+		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+	else
+		disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+
+	dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
+
+	if (radeon_crtc->crtc_id == 0) {
+		if (ASIC_IS_R300(rdev)) {
+			disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
+			disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
+		} else if (rdev->family == CHIP_R200) {
+			fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
+					  RADEON_FP2_DVO_RATE_SEL_SDR);
+		} else
+			disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
+	} else {
+		if (ASIC_IS_R300(rdev)) {
+			disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
+			disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+		} else if (rdev->family == CHIP_R200) {
+			fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
+					  RADEON_FP2_DVO_RATE_SEL_SDR);
+			fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
+		} else
+			disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
+	}
+
+	WREG32(RADEON_DAC_CNTL2, dac2_cntl);
+
+	if (ASIC_IS_R300(rdev)) {
+		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+		WREG32(RADEON_DISP_TV_OUT_CNTL, disp_output_cntl);
+	} else if (rdev->family == CHIP_R200)
+		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+	else
+		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+
+	if (rdev->is_atom_bios)
+		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+	else
+		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
+
+}
+
+static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
+							     struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+	uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+	enum drm_connector_status found = connector_status_disconnected;
+	bool color = true;
+
+	/*  FIXME tv */
+
+	/* save the regs we need */
+	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
+	gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
+	disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
+	disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
+	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
+	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
+	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
+
+	tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
+			       | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
+	WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
+
+	if (ASIC_IS_R300(rdev))
+		WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
+
+	tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+	tmp |= RADEON_CRTC2_CRT2_ON |
+		(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+
+	WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
+
+	if (ASIC_IS_R300(rdev)) {
+		tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+		tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+		WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+	} else {
+		tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+		WREG32(RADEON_DISP_HW_DEBUG, tmp);
+	}
+
+	tmp = RADEON_TV_DAC_NBLANK |
+		RADEON_TV_DAC_NHOLD |
+		RADEON_TV_MONITOR_DETECT_EN |
+		RADEON_TV_DAC_STD_PS2;
+
+	WREG32(RADEON_TV_DAC_CNTL, tmp);
+
+	tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
+		RADEON_DAC2_FORCE_DATA_EN;
+
+	if (color)
+		tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
+	else
+		tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
+
+	if (ASIC_IS_R300(rdev))
+		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+	else
+		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
+
+	WREG32(RADEON_DAC_EXT_CNTL, tmp);
+
+	tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
+	WREG32(RADEON_DAC_CNTL2, tmp);
+
+	udelay(10000);
+
+	if (ASIC_IS_R300(rdev)) {
+		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
+			found = connector_status_connected;
+	} else {
+		if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT)
+			found = connector_status_connected;
+	}
+
+	/* restore regs we used */
+	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
+	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+
+	if (ASIC_IS_R300(rdev)) {
+		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+	} else {
+		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+	}
+	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
+
+	/* return found; */
+	return connector_status_disconnected;
+
+}
+
+static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
+	.dpms = radeon_legacy_tv_dac_dpms,
+	.mode_fixup = radeon_legacy_tv_dac_mode_fixup,
+	.prepare = radeon_legacy_tv_dac_prepare,
+	.mode_set = radeon_legacy_tv_dac_mode_set,
+	.commit = radeon_legacy_tv_dac_commit,
+	.detect = radeon_legacy_tv_dac_detect,
+};
+
+
+static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = {
+	.destroy = radeon_enc_destroy,
+};
+
+void
+radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct radeon_encoder *radeon_encoder;
+
+	/* see if we already added it */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		radeon_encoder = to_radeon_encoder(encoder);
+		if (radeon_encoder->encoder_id == encoder_id) {
+			radeon_encoder->devices |= supported_device;
+			return;
+		}
+
+	}
+
+	/* add a new one */
+	radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
+	if (!radeon_encoder)
+		return;
+
+	encoder = &radeon_encoder->base;
+	encoder->possible_crtcs = 0x3;
+	encoder->possible_clones = 0;
+
+	radeon_encoder->enc_priv = NULL;
+
+	radeon_encoder->encoder_id = encoder_id;
+	radeon_encoder->devices = supported_device;
+	radeon_encoder->rmx_type = RMX_OFF;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		encoder->possible_crtcs = 0x1;
+		drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS);
+		drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
+		if (rdev->is_atom_bios)
+			radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
+		else
+			radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder);
+		radeon_encoder->rmx_type = RMX_FULL;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS);
+		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
+		if (rdev->is_atom_bios)
+			radeon_encoder->enc_priv = radeon_atombios_get_tmds_info(radeon_encoder);
+		else
+			radeon_encoder->enc_priv = radeon_combios_get_tmds_info(radeon_encoder);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+		drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
+		drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs);
+		if (rdev->is_atom_bios)
+			radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder);
+		else
+			radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+		drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC);
+		drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs);
+		if (rdev->is_atom_bios)
+			radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder);
+		else
+			radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder);
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
+		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
+		if (!rdev->is_atom_bios)
+			radeon_combios_get_ext_tmds_info(radeon_encoder);
+		break;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_mem.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_mem.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_mem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_mem.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,8 +43,8 @@
 {
 	/* Maybe cut off the start of an existing block */
 	if (start > p->start) {
-		struct mem_block *newblock =
-		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+		struct mem_block *newblock = kmalloc(sizeof(*newblock),
+						     GFP_KERNEL);
 		if (!newblock)
 			goto out;
 		newblock->start = start;
@@ -60,8 +60,8 @@
 
 	/* Maybe cut off the end of an existing block */
 	if (size < p->size) {
-		struct mem_block *newblock =
-		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+		struct mem_block *newblock = kmalloc(sizeof(*newblock),
+						     GFP_KERNEL);
 		if (!newblock)
 			goto out;
 		newblock->start = start + size;
@@ -118,7 +118,7 @@
 		p->size += q->size;
 		p->next = q->next;
 		p->next->prev = p;
-		drm_free(q, sizeof(*q), DRM_MEM_BUFS);
+		kfree(q);
 	}
 
 	if (p->prev->file_priv == NULL) {
@@ -126,7 +126,7 @@
 		q->size += p->size;
 		q->next = p->next;
 		q->next->prev = q;
-		drm_free(p, sizeof(*q), DRM_MEM_BUFS);
+		kfree(p);
 	}
 }
 
@@ -134,14 +134,14 @@
  */
 static int init_heap(struct mem_block **heap, int start, int size)
 {
-	struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
+	struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
 
 	if (!blocks)
 		return -ENOMEM;
 
-	*heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
+	*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
 	if (!*heap) {
-		drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
+		kfree(blocks);
 		return -ENOMEM;
 	}
 
@@ -179,7 +179,7 @@
 			p->size += q->size;
 			p->next = q->next;
 			p->next->prev = p;
-			drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+			kfree(q);
 		}
 	}
 }
@@ -196,10 +196,10 @@
 	for (p = (*heap)->next; p != *heap;) {
 		struct mem_block *q = p;
 		p = p->next;
-		drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+		kfree(q);
 	}
 
-	drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
+	kfree(*heap);
 	*heap = NULL;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_mode.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ *                VA Linux Systems Inc., Fremont, California.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Original Authors:
+ *   Kevin E. Martin, Rickard E. Faith, Alan Hourihane
+ *
+ * Kernel port Author: Dave Airlie
+ */
+
+#ifndef RADEON_MODE_H
+#define RADEON_MODE_H
+
+#include <drm_crtc.h>
+#include <drm_mode.h>
+#include <drm_edid.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+#include "radeon_fixed.h"
+
+struct radeon_device;
+
+#define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base)
+#define to_radeon_connector(x) container_of(x, struct radeon_connector, base)
+#define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base)
+#define to_radeon_framebuffer(x) container_of(x, struct radeon_framebuffer, base)
+
+enum radeon_connector_type {
+	CONNECTOR_NONE,
+	CONNECTOR_VGA,
+	CONNECTOR_DVI_I,
+	CONNECTOR_DVI_D,
+	CONNECTOR_DVI_A,
+	CONNECTOR_STV,
+	CONNECTOR_CTV,
+	CONNECTOR_LVDS,
+	CONNECTOR_DIGITAL,
+	CONNECTOR_SCART,
+	CONNECTOR_HDMI_TYPE_A,
+	CONNECTOR_HDMI_TYPE_B,
+	CONNECTOR_0XC,
+	CONNECTOR_0XD,
+	CONNECTOR_DIN,
+	CONNECTOR_DISPLAY_PORT,
+	CONNECTOR_UNSUPPORTED
+};
+
+enum radeon_dvi_type {
+	DVI_AUTO,
+	DVI_DIGITAL,
+	DVI_ANALOG
+};
+
+enum radeon_rmx_type {
+	RMX_OFF,
+	RMX_FULL,
+	RMX_CENTER,
+	RMX_ASPECT
+};
+
+enum radeon_tv_std {
+	TV_STD_NTSC,
+	TV_STD_PAL,
+	TV_STD_PAL_M,
+	TV_STD_PAL_60,
+	TV_STD_NTSC_J,
+	TV_STD_SCART_PAL,
+	TV_STD_SECAM,
+	TV_STD_PAL_CN,
+};
+
+struct radeon_i2c_bus_rec {
+	bool valid;
+	uint32_t mask_clk_reg;
+	uint32_t mask_data_reg;
+	uint32_t a_clk_reg;
+	uint32_t a_data_reg;
+	uint32_t put_clk_reg;
+	uint32_t put_data_reg;
+	uint32_t get_clk_reg;
+	uint32_t get_data_reg;
+	uint32_t mask_clk_mask;
+	uint32_t mask_data_mask;
+	uint32_t put_clk_mask;
+	uint32_t put_data_mask;
+	uint32_t get_clk_mask;
+	uint32_t get_data_mask;
+	uint32_t a_clk_mask;
+	uint32_t a_data_mask;
+};
+
+struct radeon_tmds_pll {
+    uint32_t freq;
+    uint32_t value;
+};
+
+#define RADEON_MAX_BIOS_CONNECTOR 16
+
+#define RADEON_PLL_USE_BIOS_DIVS        (1 << 0)
+#define RADEON_PLL_NO_ODD_POST_DIV      (1 << 1)
+#define RADEON_PLL_USE_REF_DIV          (1 << 2)
+#define RADEON_PLL_LEGACY               (1 << 3)
+#define RADEON_PLL_PREFER_LOW_REF_DIV   (1 << 4)
+#define RADEON_PLL_PREFER_HIGH_REF_DIV  (1 << 5)
+#define RADEON_PLL_PREFER_LOW_FB_DIV    (1 << 6)
+#define RADEON_PLL_PREFER_HIGH_FB_DIV   (1 << 7)
+#define RADEON_PLL_PREFER_LOW_POST_DIV  (1 << 8)
+#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
+#define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
+#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
+
+struct radeon_pll {
+	uint16_t reference_freq;
+	uint16_t reference_div;
+	uint32_t pll_in_min;
+	uint32_t pll_in_max;
+	uint32_t pll_out_min;
+	uint32_t pll_out_max;
+	uint16_t xclk;
+
+	uint32_t min_ref_div;
+	uint32_t max_ref_div;
+	uint32_t min_post_div;
+	uint32_t max_post_div;
+	uint32_t min_feedback_div;
+	uint32_t max_feedback_div;
+	uint32_t min_frac_feedback_div;
+	uint32_t max_frac_feedback_div;
+	uint32_t best_vco;
+};
+
+struct radeon_i2c_chan {
+	struct drm_device *dev;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+	struct radeon_i2c_bus_rec rec;
+};
+
+/* mostly for macs, but really any system without connector tables */
+enum radeon_connector_table {
+	CT_NONE,
+	CT_GENERIC,
+	CT_IBOOK,
+	CT_POWERBOOK_EXTERNAL,
+	CT_POWERBOOK_INTERNAL,
+	CT_POWERBOOK_VGA,
+	CT_MINI_EXTERNAL,
+	CT_MINI_INTERNAL,
+	CT_IMAC_G5_ISIGHT,
+	CT_EMAC,
+};
+
+struct radeon_mode_info {
+	struct atom_context *atom_context;
+	enum radeon_connector_table connector_table;
+	bool mode_config_initialized;
+	struct radeon_crtc *crtcs[2];
+};
+
+struct radeon_native_mode {
+	/* preferred mode */
+	uint32_t panel_xres, panel_yres;
+	uint32_t hoverplus, hsync_width;
+	uint32_t hblank;
+	uint32_t voverplus, vsync_width;
+	uint32_t vblank;
+	uint32_t dotclock;
+	uint32_t flags;
+};
+
+struct radeon_crtc {
+	struct drm_crtc base;
+	int crtc_id;
+	u16 lut_r[256], lut_g[256], lut_b[256];
+	bool enabled;
+	bool can_tile;
+	uint32_t crtc_offset;
+	struct radeon_framebuffer *fbdev_fb;
+	struct drm_mode_set mode_set;
+	struct drm_gem_object *cursor_bo;
+	uint64_t cursor_addr;
+	int cursor_width;
+	int cursor_height;
+	uint32_t legacy_display_base_addr;
+	uint32_t legacy_cursor_offset;
+	enum radeon_rmx_type rmx_type;
+	uint32_t devices;
+	fixed20_12 vsc;
+	fixed20_12 hsc;
+	struct radeon_native_mode native_mode;
+};
+
+struct radeon_encoder_primary_dac {
+	/* legacy primary dac */
+	uint32_t ps2_pdac_adj;
+};
+
+struct radeon_encoder_lvds {
+	/* legacy lvds */
+	uint16_t panel_vcc_delay;
+	uint8_t  panel_pwr_delay;
+	uint8_t  panel_digon_delay;
+	uint8_t  panel_blon_delay;
+	uint16_t panel_ref_divider;
+	uint8_t  panel_post_divider;
+	uint16_t panel_fb_divider;
+	bool     use_bios_dividers;
+	uint32_t lvds_gen_cntl;
+	/* panel mode */
+	struct radeon_native_mode native_mode;
+};
+
+struct radeon_encoder_tv_dac {
+	/* legacy tv dac */
+	uint32_t ps2_tvdac_adj;
+	uint32_t ntsc_tvdac_adj;
+	uint32_t pal_tvdac_adj;
+
+	enum radeon_tv_std tv_std;
+};
+
+struct radeon_encoder_int_tmds {
+	/* legacy int tmds */
+	struct radeon_tmds_pll tmds_pll[4];
+};
+
+struct radeon_encoder_atom_dig {
+	/* atom dig */
+	bool coherent_mode;
+	int dig_block;
+	/* atom lvds */
+	uint32_t lvds_misc;
+	uint16_t panel_pwr_delay;
+	/* panel mode */
+	struct radeon_native_mode native_mode;
+};
+
+struct radeon_encoder {
+	struct drm_encoder base;
+	uint32_t encoder_id;
+	uint32_t devices;
+	uint32_t flags;
+	uint32_t pixel_clock;
+	enum radeon_rmx_type rmx_type;
+	struct radeon_native_mode native_mode;
+	void *enc_priv;
+};
+
+struct radeon_connector_atom_dig {
+	uint32_t igp_lane_info;
+	bool linkb;
+};
+
+struct radeon_connector {
+	struct drm_connector base;
+	uint32_t connector_id;
+	uint32_t devices;
+	struct radeon_i2c_chan *ddc_bus;
+	int use_digital;
+	void *con_priv;
+};
+
+struct radeon_framebuffer {
+	struct drm_framebuffer base;
+	struct drm_gem_object *obj;
+};
+
+extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
+						 struct radeon_i2c_bus_rec *rec,
+						 const char *name);
+extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
+
+extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
+
+extern void radeon_compute_pll(struct radeon_pll *pll,
+			       uint64_t freq,
+			       uint32_t *dot_clock_p,
+			       uint32_t *fb_div_p,
+			       uint32_t *frac_fb_div_p,
+			       uint32_t *ref_div_p,
+			       uint32_t *post_div_p,
+			       int flags);
+
+struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index);
+struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv);
+struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int with_tv);
+struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index);
+struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index);
+extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action);
+extern int atombios_get_encoder_mode(struct drm_encoder *encoder);
+
+extern void radeon_crtc_load_lut(struct drm_crtc *crtc);
+extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+				   struct drm_framebuffer *old_fb);
+extern int atombios_crtc_mode_set(struct drm_crtc *crtc,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode,
+				   int x, int y,
+				   struct drm_framebuffer *old_fb);
+extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode);
+
+extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+				 struct drm_framebuffer *old_fb);
+extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc);
+
+extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
+				  struct drm_file *file_priv,
+				  uint32_t handle,
+				  uint32_t width,
+				  uint32_t height);
+extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
+				   int x, int y);
+
+extern bool radeon_atom_get_clock_info(struct drm_device *dev);
+extern bool radeon_combios_get_clock_info(struct drm_device *dev);
+extern struct radeon_encoder_atom_dig *
+radeon_atombios_get_lvds_info(struct radeon_encoder *encoder);
+extern struct radeon_encoder_int_tmds *
+radeon_atombios_get_tmds_info(struct radeon_encoder *encoder);
+extern struct radeon_encoder_primary_dac *
+radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder);
+extern struct radeon_encoder_tv_dac *
+radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder);
+extern struct radeon_encoder_lvds *
+radeon_combios_get_lvds_info(struct radeon_encoder *encoder);
+extern struct radeon_encoder_int_tmds *
+radeon_combios_get_tmds_info(struct radeon_encoder *encoder);
+extern void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder);
+extern struct radeon_encoder_tv_dac *
+radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
+extern struct radeon_encoder_primary_dac *
+radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder);
+extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock);
+extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev);
+extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock);
+extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev);
+extern void
+radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc);
+extern void
+radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on);
+extern void
+radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc);
+extern void
+radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on);
+extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+				     u16 blue, int regno);
+struct drm_framebuffer *radeon_framebuffer_create(struct drm_device *dev,
+						  struct drm_mode_fb_cmd *mode_cmd,
+						  struct drm_gem_object *obj);
+
+int radeonfb_probe(struct drm_device *dev);
+
+int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
+bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev);
+bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev);
+void radeon_atombios_init_crtc(struct drm_device *dev,
+			       struct radeon_crtc *radeon_crtc);
+void radeon_legacy_init_crtc(struct drm_device *dev,
+			     struct radeon_crtc *radeon_crtc);
+void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state);
+
+void radeon_get_clock_info(struct drm_device *dev);
+
+extern bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev);
+extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct drm_device *dev);
+
+void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
+			   struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode);
+void radeon_enc_destroy(struct drm_encoder *encoder);
+void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
+void radeon_combios_asic_init(struct drm_device *dev);
+extern int radeon_static_clocks_init(struct drm_device *dev);
+bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
+					struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode);
+void atom_rv515_force_tv_scaler(struct radeon_device *rdev);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_object.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_object.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_object.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,626 @@
+/*
+ * Copyright 2009 Jerome Glisse.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors:
+ *    Jerome Glisse <glisse@freedesktop.org>
+ *    Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ *    Dave Airlie
+ */
+#include <linux/list.h>
+#include <drm/drmP.h>
+#include "radeon_drm.h"
+#include "radeon.h"
+
+struct radeon_object {
+	struct ttm_buffer_object	tobj;
+	struct list_head		list;
+	struct radeon_device		*rdev;
+	struct drm_gem_object		*gobj;
+	struct ttm_bo_kmap_obj		kmap;
+	unsigned			pin_count;
+	uint64_t			gpu_addr;
+	void				*kptr;
+	bool				is_iomem;
+	uint32_t			tiling_flags;
+	uint32_t			pitch;
+	int				surface_reg;
+};
+
+int radeon_ttm_init(struct radeon_device *rdev);
+void radeon_ttm_fini(struct radeon_device *rdev);
+
+/*
+ * To exclude mutual BO access we rely on bo_reserve exclusion, as all
+ * function are calling it.
+ */
+
+static int radeon_object_reserve(struct radeon_object *robj, bool interruptible)
+{
+	return ttm_bo_reserve(&robj->tobj, interruptible, false, false, 0);
+}
+
+static void radeon_object_unreserve(struct radeon_object *robj)
+{
+	ttm_bo_unreserve(&robj->tobj);
+}
+
+static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj)
+{
+	struct radeon_object *robj;
+
+	robj = container_of(tobj, struct radeon_object, tobj);
+	list_del_init(&robj->list);
+	radeon_object_clear_surface_reg(robj);
+	kfree(robj);
+}
+
+static inline void radeon_object_gpu_addr(struct radeon_object *robj)
+{
+	/* Default gpu address */
+	robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL;
+	if (robj->tobj.mem.mm_node == NULL) {
+		return;
+	}
+	robj->gpu_addr = ((u64)robj->tobj.mem.mm_node->start) << PAGE_SHIFT;
+	switch (robj->tobj.mem.mem_type) {
+	case TTM_PL_VRAM:
+		robj->gpu_addr += (u64)robj->rdev->mc.vram_location;
+		break;
+	case TTM_PL_TT:
+		robj->gpu_addr += (u64)robj->rdev->mc.gtt_location;
+		break;
+	default:
+		DRM_ERROR("Unknown placement %d\n", robj->tobj.mem.mem_type);
+		robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL;
+		return;
+	}
+}
+
+static inline uint32_t radeon_object_flags_from_domain(uint32_t domain)
+{
+	uint32_t flags = 0;
+	if (domain & RADEON_GEM_DOMAIN_VRAM) {
+		flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+	}
+	if (domain & RADEON_GEM_DOMAIN_GTT) {
+		flags |= TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
+	}
+	if (domain & RADEON_GEM_DOMAIN_CPU) {
+		flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
+	}
+	if (!flags) {
+		flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
+	}
+	return flags;
+}
+
+int radeon_object_create(struct radeon_device *rdev,
+			 struct drm_gem_object *gobj,
+			 unsigned long size,
+			 bool kernel,
+			 uint32_t domain,
+			 bool interruptible,
+			 struct radeon_object **robj_ptr)
+{
+	struct radeon_object *robj;
+	enum ttm_bo_type type;
+	uint32_t flags;
+	int r;
+
+	if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
+		rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping;
+	}
+	if (kernel) {
+		type = ttm_bo_type_kernel;
+	} else {
+		type = ttm_bo_type_device;
+	}
+	*robj_ptr = NULL;
+	robj = kzalloc(sizeof(struct radeon_object), GFP_KERNEL);
+	if (robj == NULL) {
+		return -ENOMEM;
+	}
+	robj->rdev = rdev;
+	robj->gobj = gobj;
+	robj->surface_reg = -1;
+	INIT_LIST_HEAD(&robj->list);
+
+	flags = radeon_object_flags_from_domain(domain);
+	r = ttm_buffer_object_init(&rdev->mman.bdev, &robj->tobj, size, type, flags,
+				   0, 0, false, NULL, size,
+				   &radeon_ttm_object_object_destroy);
+	if (unlikely(r != 0)) {
+		/* ttm call radeon_ttm_object_object_destroy if error happen */
+		DRM_ERROR("Failed to allocate TTM object (%ld, 0x%08X, %u)\n",
+			  size, flags, 0);
+		return r;
+	}
+	*robj_ptr = robj;
+	if (gobj) {
+		list_add_tail(&robj->list, &rdev->gem.objects);
+	}
+	return 0;
+}
+
+int radeon_object_kmap(struct radeon_object *robj, void **ptr)
+{
+	int r;
+
+	spin_lock(&robj->tobj.lock);
+	if (robj->kptr) {
+		if (ptr) {
+			*ptr = robj->kptr;
+		}
+		spin_unlock(&robj->tobj.lock);
+		return 0;
+	}
+	spin_unlock(&robj->tobj.lock);
+	r = ttm_bo_kmap(&robj->tobj, 0, robj->tobj.num_pages, &robj->kmap);
+	if (r) {
+		return r;
+	}
+	spin_lock(&robj->tobj.lock);
+	robj->kptr = ttm_kmap_obj_virtual(&robj->kmap, &robj->is_iomem);
+	spin_unlock(&robj->tobj.lock);
+	if (ptr) {
+		*ptr = robj->kptr;
+	}
+	return 0;
+}
+
+void radeon_object_kunmap(struct radeon_object *robj)
+{
+	spin_lock(&robj->tobj.lock);
+	if (robj->kptr == NULL) {
+		spin_unlock(&robj->tobj.lock);
+		return;
+	}
+	robj->kptr = NULL;
+	spin_unlock(&robj->tobj.lock);
+	ttm_bo_kunmap(&robj->kmap);
+}
+
+void radeon_object_unref(struct radeon_object **robj)
+{
+	struct ttm_buffer_object *tobj;
+
+	if ((*robj) == NULL) {
+		return;
+	}
+	tobj = &((*robj)->tobj);
+	ttm_bo_unref(&tobj);
+	if (tobj == NULL) {
+		*robj = NULL;
+	}
+}
+
+int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset)
+{
+	*offset = robj->tobj.addr_space_offset;
+	return 0;
+}
+
+int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
+		      uint64_t *gpu_addr)
+{
+	uint32_t flags;
+	uint32_t tmp;
+	int r;
+
+	flags = radeon_object_flags_from_domain(domain);
+	spin_lock(&robj->tobj.lock);
+	if (robj->pin_count) {
+		robj->pin_count++;
+		if (gpu_addr != NULL) {
+			*gpu_addr = robj->gpu_addr;
+		}
+		spin_unlock(&robj->tobj.lock);
+		return 0;
+	}
+	spin_unlock(&robj->tobj.lock);
+	r = radeon_object_reserve(robj, false);
+	if (unlikely(r != 0)) {
+		DRM_ERROR("radeon: failed to reserve object for pinning it.\n");
+		return r;
+	}
+	tmp = robj->tobj.mem.placement;
+	ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM);
+	robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING;
+	r = ttm_buffer_object_validate(&robj->tobj,
+				       robj->tobj.proposed_placement,
+				       false, false);
+	radeon_object_gpu_addr(robj);
+	if (gpu_addr != NULL) {
+		*gpu_addr = robj->gpu_addr;
+	}
+	robj->pin_count = 1;
+	if (unlikely(r != 0)) {
+		DRM_ERROR("radeon: failed to pin object.\n");
+	}
+	radeon_object_unreserve(robj);
+	return r;
+}
+
+void radeon_object_unpin(struct radeon_object *robj)
+{
+	uint32_t flags;
+	int r;
+
+	spin_lock(&robj->tobj.lock);
+	if (!robj->pin_count) {
+		spin_unlock(&robj->tobj.lock);
+		printk(KERN_WARNING "Unpin not necessary for %p !\n", robj);
+		return;
+	}
+	robj->pin_count--;
+	if (robj->pin_count) {
+		spin_unlock(&robj->tobj.lock);
+		return;
+	}
+	spin_unlock(&robj->tobj.lock);
+	r = radeon_object_reserve(robj, false);
+	if (unlikely(r != 0)) {
+		DRM_ERROR("radeon: failed to reserve object for unpinning it.\n");
+		return;
+	}
+	flags = robj->tobj.mem.placement;
+	robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT;
+	r = ttm_buffer_object_validate(&robj->tobj,
+				       robj->tobj.proposed_placement,
+				       false, false);
+	if (unlikely(r != 0)) {
+		DRM_ERROR("radeon: failed to unpin buffer.\n");
+	}
+	radeon_object_unreserve(robj);
+}
+
+int radeon_object_wait(struct radeon_object *robj)
+{
+	int r = 0;
+
+	/* FIXME: should use block reservation instead */
+	r = radeon_object_reserve(robj, true);
+	if (unlikely(r != 0)) {
+		DRM_ERROR("radeon: failed to reserve object for waiting.\n");
+		return r;
+	}
+	spin_lock(&robj->tobj.lock);
+	if (robj->tobj.sync_obj) {
+		r = ttm_bo_wait(&robj->tobj, true, true, false);
+	}
+	spin_unlock(&robj->tobj.lock);
+	radeon_object_unreserve(robj);
+	return r;
+}
+
+int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement)
+{
+	int r = 0;
+
+	r = radeon_object_reserve(robj, true);
+	if (unlikely(r != 0)) {
+		DRM_ERROR("radeon: failed to reserve object for waiting.\n");
+		return r;
+	}
+	spin_lock(&robj->tobj.lock);
+	*cur_placement = robj->tobj.mem.mem_type;
+	if (robj->tobj.sync_obj) {
+		r = ttm_bo_wait(&robj->tobj, true, true, true);
+	}
+	spin_unlock(&robj->tobj.lock);
+	radeon_object_unreserve(robj);
+	return r;
+}
+
+int radeon_object_evict_vram(struct radeon_device *rdev)
+{
+	if (rdev->flags & RADEON_IS_IGP) {
+		/* Useless to evict on IGP chips */
+		return 0;
+	}
+	return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM);
+}
+
+void radeon_object_force_delete(struct radeon_device *rdev)
+{
+	struct radeon_object *robj, *n;
+	struct drm_gem_object *gobj;
+
+	if (list_empty(&rdev->gem.objects)) {
+		return;
+	}
+	DRM_ERROR("Userspace still has active objects !\n");
+	list_for_each_entry_safe(robj, n, &rdev->gem.objects, list) {
+		mutex_lock(&rdev->ddev->struct_mutex);
+		gobj = robj->gobj;
+		DRM_ERROR("Force free for (%p,%p,%lu,%lu)\n",
+			  gobj, robj, (unsigned long)gobj->size,
+			  *((unsigned long *)&gobj->refcount));
+		list_del_init(&robj->list);
+		radeon_object_unref(&robj);
+		gobj->driver_private = NULL;
+		drm_gem_object_unreference(gobj);
+		mutex_unlock(&rdev->ddev->struct_mutex);
+	}
+}
+
+int radeon_object_init(struct radeon_device *rdev)
+{
+	return radeon_ttm_init(rdev);
+}
+
+void radeon_object_fini(struct radeon_device *rdev)
+{
+	radeon_ttm_fini(rdev);
+}
+
+void radeon_object_list_add_object(struct radeon_object_list *lobj,
+				   struct list_head *head)
+{
+	if (lobj->wdomain) {
+		list_add(&lobj->list, head);
+	} else {
+		list_add_tail(&lobj->list, head);
+	}
+}
+
+int radeon_object_list_reserve(struct list_head *head)
+{
+	struct radeon_object_list *lobj;
+	struct list_head *i;
+	int r;
+
+	list_for_each(i, head) {
+		lobj = list_entry(i, struct radeon_object_list, list);
+		if (!lobj->robj->pin_count) {
+			r = radeon_object_reserve(lobj->robj, true);
+			if (unlikely(r != 0)) {
+				DRM_ERROR("radeon: failed to reserve object.\n");
+				return r;
+			}
+		} else {
+		}
+	}
+	return 0;
+}
+
+void radeon_object_list_unreserve(struct list_head *head)
+{
+	struct radeon_object_list *lobj;
+	struct list_head *i;
+
+	list_for_each(i, head) {
+		lobj = list_entry(i, struct radeon_object_list, list);
+		if (!lobj->robj->pin_count) {
+			radeon_object_unreserve(lobj->robj);
+		} else {
+		}
+	}
+}
+
+int radeon_object_list_validate(struct list_head *head, void *fence)
+{
+	struct radeon_object_list *lobj;
+	struct radeon_object *robj;
+	struct radeon_fence *old_fence = NULL;
+	struct list_head *i;
+	int r;
+
+	r = radeon_object_list_reserve(head);
+	if (unlikely(r != 0)) {
+		radeon_object_list_unreserve(head);
+		return r;
+	}
+	list_for_each(i, head) {
+		lobj = list_entry(i, struct radeon_object_list, list);
+		robj = lobj->robj;
+		if (!robj->pin_count) {
+			if (lobj->wdomain) {
+				robj->tobj.proposed_placement =
+					radeon_object_flags_from_domain(lobj->wdomain);
+			} else {
+				robj->tobj.proposed_placement =
+					radeon_object_flags_from_domain(lobj->rdomain);
+			}
+			r = ttm_buffer_object_validate(&robj->tobj,
+						       robj->tobj.proposed_placement,
+						       true, false);
+			if (unlikely(r)) {
+				DRM_ERROR("radeon: failed to validate.\n");
+				return r;
+			}
+			radeon_object_gpu_addr(robj);
+		}
+		lobj->gpu_offset = robj->gpu_addr;
+		lobj->tiling_flags = robj->tiling_flags;
+		if (fence) {
+			old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
+			robj->tobj.sync_obj = radeon_fence_ref(fence);
+			robj->tobj.sync_obj_arg = NULL;
+		}
+		if (old_fence) {
+			radeon_fence_unref(&old_fence);
+		}
+	}
+	return 0;
+}
+
+void radeon_object_list_unvalidate(struct list_head *head)
+{
+	struct radeon_object_list *lobj;
+	struct radeon_fence *old_fence = NULL;
+	struct list_head *i;
+
+	list_for_each(i, head) {
+		lobj = list_entry(i, struct radeon_object_list, list);
+		old_fence = (struct radeon_fence *)lobj->robj->tobj.sync_obj;
+		lobj->robj->tobj.sync_obj = NULL;
+		if (old_fence) {
+			radeon_fence_unref(&old_fence);
+		}
+	}
+	radeon_object_list_unreserve(head);
+}
+
+void radeon_object_list_clean(struct list_head *head)
+{
+	radeon_object_list_unreserve(head);
+}
+
+int radeon_object_fbdev_mmap(struct radeon_object *robj,
+			     struct vm_area_struct *vma)
+{
+	return ttm_fbdev_mmap(vma, &robj->tobj);
+}
+
+unsigned long radeon_object_size(struct radeon_object *robj)
+{
+	return robj->tobj.num_pages << PAGE_SHIFT;
+}
+
+int radeon_object_get_surface_reg(struct radeon_object *robj)
+{
+	struct radeon_device *rdev = robj->rdev;
+	struct radeon_surface_reg *reg;
+	struct radeon_object *old_object;
+	int steal;
+	int i;
+
+	if (!robj->tiling_flags)
+		return 0;
+
+	if (robj->surface_reg >= 0) {
+		reg = &rdev->surface_regs[robj->surface_reg];
+		i = robj->surface_reg;
+		goto out;
+	}
+
+	steal = -1;
+	for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
+
+		reg = &rdev->surface_regs[i];
+		if (!reg->robj)
+			break;
+
+		old_object = reg->robj;
+		if (old_object->pin_count == 0)
+			steal = i;
+	}
+
+	/* if we are all out */
+	if (i == RADEON_GEM_MAX_SURFACES) {
+		if (steal == -1)
+			return -ENOMEM;
+		/* find someone with a surface reg and nuke their BO */
+		reg = &rdev->surface_regs[steal];
+		old_object = reg->robj;
+		/* blow away the mapping */
+		DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
+		ttm_bo_unmap_virtual(&old_object->tobj);
+		old_object->surface_reg = -1;
+		i = steal;
+	}
+
+	robj->surface_reg = i;
+	reg->robj = robj;
+
+out:
+	radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch,
+			       robj->tobj.mem.mm_node->start << PAGE_SHIFT,
+			       robj->tobj.num_pages << PAGE_SHIFT);
+	return 0;
+}
+
+void radeon_object_clear_surface_reg(struct radeon_object *robj)
+{
+	struct radeon_device *rdev = robj->rdev;
+	struct radeon_surface_reg *reg;
+
+	if (robj->surface_reg == -1)
+		return;
+
+	reg = &rdev->surface_regs[robj->surface_reg];
+	radeon_clear_surface_reg(rdev, robj->surface_reg);
+
+	reg->robj = NULL;
+	robj->surface_reg = -1;
+}
+
+void radeon_object_set_tiling_flags(struct radeon_object *robj,
+				    uint32_t tiling_flags, uint32_t pitch)
+{
+	robj->tiling_flags = tiling_flags;
+	robj->pitch = pitch;
+}
+
+void radeon_object_get_tiling_flags(struct radeon_object *robj,
+				    uint32_t *tiling_flags,
+				    uint32_t *pitch)
+{
+	if (tiling_flags)
+		*tiling_flags = robj->tiling_flags;
+	if (pitch)
+		*pitch = robj->pitch;
+}
+
+int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
+			       bool force_drop)
+{
+	if (!(robj->tiling_flags & RADEON_TILING_SURFACE))
+		return 0;
+
+	if (force_drop) {
+		radeon_object_clear_surface_reg(robj);
+		return 0;
+	}
+
+	if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
+		if (!has_moved)
+			return 0;
+
+		if (robj->surface_reg >= 0)
+			radeon_object_clear_surface_reg(robj);
+		return 0;
+	}
+
+	if ((robj->surface_reg >= 0) && !has_moved)
+		return 0;
+
+	return radeon_object_get_surface_reg(robj);
+}
+
+void radeon_bo_move_notify(struct ttm_buffer_object *bo,
+			  struct ttm_mem_reg *mem)
+{
+	struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
+	radeon_object_check_tiling(robj, 0, 1);
+}
+
+void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
+{
+	struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
+	radeon_object_check_tiling(robj, 0, 0);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_object.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_object.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_object.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RADEON_OBJECT_H__
+#define __RADEON_OBJECT_H__
+
+#include <ttm/ttm_bo_api.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <ttm/ttm_module.h>
+
+/*
+ * TTM.
+ */
+struct radeon_mman {
+	struct ttm_global_reference	mem_global_ref;
+	bool				mem_global_referenced;
+	struct ttm_bo_device		bdev;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_reg.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_reg.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3579 @@
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ *                VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@xfree86.org>
+ *   Rickard E. Faith <faith@valinux.com>
+ *   Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ *   1999.
+ *
+ * !!!! FIXME !!!!
+ *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+/* !!!! FIXME !!!!  NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h
+ * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT
+ * ON THE RADEON.  A FULL AUDIT OF THIS CODE IS NEEDED!  */
+#ifndef _RADEON_REG_H_
+#define _RADEON_REG_H_
+
+#include "r300_reg.h"
+#include "r500_reg.h"
+#include "r600_reg.h"
+
+
+#define RADEON_MC_AGP_LOCATION		0x014c
+#define		RADEON_MC_AGP_START_MASK	0x0000FFFF
+#define		RADEON_MC_AGP_START_SHIFT	0
+#define		RADEON_MC_AGP_TOP_MASK		0xFFFF0000
+#define		RADEON_MC_AGP_TOP_SHIFT		16
+#define RADEON_MC_FB_LOCATION		0x0148
+#define		RADEON_MC_FB_START_MASK		0x0000FFFF
+#define		RADEON_MC_FB_START_SHIFT	0
+#define		RADEON_MC_FB_TOP_MASK		0xFFFF0000
+#define		RADEON_MC_FB_TOP_SHIFT		16
+#define RADEON_AGP_BASE_2		0x015c /* r200+ only */
+#define RADEON_AGP_BASE			0x0170
+
+#define ATI_DATATYPE_VQ				0
+#define ATI_DATATYPE_CI4			1
+#define ATI_DATATYPE_CI8			2
+#define ATI_DATATYPE_ARGB1555			3
+#define ATI_DATATYPE_RGB565			4
+#define ATI_DATATYPE_RGB888			5
+#define ATI_DATATYPE_ARGB8888			6
+#define ATI_DATATYPE_RGB332			7
+#define ATI_DATATYPE_Y8				8
+#define ATI_DATATYPE_RGB8			9
+#define ATI_DATATYPE_CI16			10
+#define ATI_DATATYPE_VYUY_422			11
+#define ATI_DATATYPE_YVYU_422			12
+#define ATI_DATATYPE_AYUV_444			14
+#define ATI_DATATYPE_ARGB4444			15
+
+				/* Registers for 2D/Video/Overlay */
+#define RADEON_ADAPTER_ID                   0x0f2c /* PCI */
+#define RADEON_AGP_BASE                     0x0170
+#define RADEON_AGP_CNTL                     0x0174
+#       define RADEON_AGP_APER_SIZE_256MB   (0x00 << 0)
+#       define RADEON_AGP_APER_SIZE_128MB   (0x20 << 0)
+#       define RADEON_AGP_APER_SIZE_64MB    (0x30 << 0)
+#       define RADEON_AGP_APER_SIZE_32MB    (0x38 << 0)
+#       define RADEON_AGP_APER_SIZE_16MB    (0x3c << 0)
+#       define RADEON_AGP_APER_SIZE_8MB     (0x3e << 0)
+#       define RADEON_AGP_APER_SIZE_4MB     (0x3f << 0)
+#       define RADEON_AGP_APER_SIZE_MASK    (0x3f << 0)
+#define RADEON_STATUS_PCI_CONFIG            0x06
+#       define RADEON_CAP_LIST              0x100000
+#define RADEON_CAPABILITIES_PTR_PCI_CONFIG  0x34 /* offset in PCI config*/
+#       define RADEON_CAP_PTR_MASK          0xfc /* mask off reserved bits of CAP_PTR */
+#       define RADEON_CAP_ID_NULL           0x00 /* End of capability list */
+#       define RADEON_CAP_ID_AGP            0x02 /* AGP capability ID */
+#       define RADEON_CAP_ID_EXP            0x10 /* PCI Express */
+#define RADEON_AGP_COMMAND                  0x0f60 /* PCI */
+#define RADEON_AGP_COMMAND_PCI_CONFIG       0x0060 /* offset in PCI config*/
+#       define RADEON_AGP_ENABLE            (1<<8)
+#define RADEON_AGP_PLL_CNTL                 0x000b /* PLL */
+#define RADEON_AGP_STATUS                   0x0f5c /* PCI */
+#       define RADEON_AGP_1X_MODE           0x01
+#       define RADEON_AGP_2X_MODE           0x02
+#       define RADEON_AGP_4X_MODE           0x04
+#       define RADEON_AGP_FW_MODE           0x10
+#       define RADEON_AGP_MODE_MASK         0x17
+#       define RADEON_AGPv3_MODE            0x08
+#       define RADEON_AGPv3_4X_MODE         0x01
+#       define RADEON_AGPv3_8X_MODE         0x02
+#define RADEON_ATTRDR                       0x03c1 /* VGA */
+#define RADEON_ATTRDW                       0x03c0 /* VGA */
+#define RADEON_ATTRX                        0x03c0 /* VGA */
+#define RADEON_AUX_SC_CNTL                  0x1660
+#       define RADEON_AUX1_SC_EN            (1 << 0)
+#       define RADEON_AUX1_SC_MODE_OR       (0 << 1)
+#       define RADEON_AUX1_SC_MODE_NAND     (1 << 1)
+#       define RADEON_AUX2_SC_EN            (1 << 2)
+#       define RADEON_AUX2_SC_MODE_OR       (0 << 3)
+#       define RADEON_AUX2_SC_MODE_NAND     (1 << 3)
+#       define RADEON_AUX3_SC_EN            (1 << 4)
+#       define RADEON_AUX3_SC_MODE_OR       (0 << 5)
+#       define RADEON_AUX3_SC_MODE_NAND     (1 << 5)
+#define RADEON_AUX1_SC_BOTTOM               0x1670
+#define RADEON_AUX1_SC_LEFT                 0x1664
+#define RADEON_AUX1_SC_RIGHT                0x1668
+#define RADEON_AUX1_SC_TOP                  0x166c
+#define RADEON_AUX2_SC_BOTTOM               0x1680
+#define RADEON_AUX2_SC_LEFT                 0x1674
+#define RADEON_AUX2_SC_RIGHT                0x1678
+#define RADEON_AUX2_SC_TOP                  0x167c
+#define RADEON_AUX3_SC_BOTTOM               0x1690
+#define RADEON_AUX3_SC_LEFT                 0x1684
+#define RADEON_AUX3_SC_RIGHT                0x1688
+#define RADEON_AUX3_SC_TOP                  0x168c
+#define RADEON_AUX_WINDOW_HORZ_CNTL         0x02d8
+#define RADEON_AUX_WINDOW_VERT_CNTL         0x02dc
+
+#define RADEON_BASE_CODE                    0x0f0b
+#define RADEON_BIOS_0_SCRATCH               0x0010
+#       define RADEON_FP_PANEL_SCALABLE     (1 << 16)
+#       define RADEON_FP_PANEL_SCALE_EN     (1 << 17)
+#       define RADEON_FP_CHIP_SCALE_EN      (1 << 18)
+#       define RADEON_DRIVER_BRIGHTNESS_EN  (1 << 26)
+#       define RADEON_DISPLAY_ROT_MASK      (3 << 28)
+#       define RADEON_DISPLAY_ROT_00        (0 << 28)
+#       define RADEON_DISPLAY_ROT_90        (1 << 28)
+#       define RADEON_DISPLAY_ROT_180       (2 << 28)
+#       define RADEON_DISPLAY_ROT_270       (3 << 28)
+#define RADEON_BIOS_1_SCRATCH               0x0014
+#define RADEON_BIOS_2_SCRATCH               0x0018
+#define RADEON_BIOS_3_SCRATCH               0x001c
+#define RADEON_BIOS_4_SCRATCH               0x0020
+#       define RADEON_CRT1_ATTACHED_MASK    (3 << 0)
+#       define RADEON_CRT1_ATTACHED_MONO    (1 << 0)
+#       define RADEON_CRT1_ATTACHED_COLOR   (2 << 0)
+#       define RADEON_LCD1_ATTACHED         (1 << 2)
+#       define RADEON_DFP1_ATTACHED         (1 << 3)
+#       define RADEON_TV1_ATTACHED_MASK     (3 << 4)
+#       define RADEON_TV1_ATTACHED_COMP     (1 << 4)
+#       define RADEON_TV1_ATTACHED_SVIDEO   (2 << 4)
+#       define RADEON_CRT2_ATTACHED_MASK    (3 << 8)
+#       define RADEON_CRT2_ATTACHED_MONO    (1 << 8)
+#       define RADEON_CRT2_ATTACHED_COLOR   (2 << 8)
+#       define RADEON_DFP2_ATTACHED         (1 << 11)
+#define RADEON_BIOS_5_SCRATCH               0x0024
+#       define RADEON_LCD1_ON               (1 << 0)
+#       define RADEON_CRT1_ON               (1 << 1)
+#       define RADEON_TV1_ON                (1 << 2)
+#       define RADEON_DFP1_ON               (1 << 3)
+#       define RADEON_CRT2_ON               (1 << 5)
+#       define RADEON_CV1_ON                (1 << 6)
+#       define RADEON_DFP2_ON               (1 << 7)
+#       define RADEON_LCD1_CRTC_MASK        (1 << 8)
+#       define RADEON_LCD1_CRTC_SHIFT       8
+#       define RADEON_CRT1_CRTC_MASK        (1 << 9)
+#       define RADEON_CRT1_CRTC_SHIFT       9
+#       define RADEON_TV1_CRTC_MASK         (1 << 10)
+#       define RADEON_TV1_CRTC_SHIFT        10
+#       define RADEON_DFP1_CRTC_MASK        (1 << 11)
+#       define RADEON_DFP1_CRTC_SHIFT       11
+#       define RADEON_CRT2_CRTC_MASK        (1 << 12)
+#       define RADEON_CRT2_CRTC_SHIFT       12
+#       define RADEON_CV1_CRTC_MASK         (1 << 13)
+#       define RADEON_CV1_CRTC_SHIFT        13
+#       define RADEON_DFP2_CRTC_MASK        (1 << 14)
+#       define RADEON_DFP2_CRTC_SHIFT       14
+#       define RADEON_ACC_REQ_LCD1          (1 << 16)
+#       define RADEON_ACC_REQ_CRT1          (1 << 17)
+#       define RADEON_ACC_REQ_TV1           (1 << 18)
+#       define RADEON_ACC_REQ_DFP1          (1 << 19)
+#       define RADEON_ACC_REQ_CRT2          (1 << 21)
+#       define RADEON_ACC_REQ_TV2           (1 << 22)
+#       define RADEON_ACC_REQ_DFP2          (1 << 23)
+#define RADEON_BIOS_6_SCRATCH               0x0028
+#       define RADEON_ACC_MODE_CHANGE       (1 << 2)
+#       define RADEON_EXT_DESKTOP_MODE      (1 << 3)
+#       define RADEON_LCD_DPMS_ON           (1 << 20)
+#       define RADEON_CRT_DPMS_ON           (1 << 21)
+#       define RADEON_TV_DPMS_ON            (1 << 22)
+#       define RADEON_DFP_DPMS_ON           (1 << 23)
+#       define RADEON_DPMS_MASK             (3 << 24)
+#       define RADEON_DPMS_ON               (0 << 24)
+#       define RADEON_DPMS_STANDBY          (1 << 24)
+#       define RADEON_DPMS_SUSPEND          (2 << 24)
+#       define RADEON_DPMS_OFF              (3 << 24)
+#       define RADEON_SCREEN_BLANKING       (1 << 26)
+#       define RADEON_DRIVER_CRITICAL       (1 << 27)
+#       define RADEON_DISPLAY_SWITCHING_DIS (1 << 30)
+#define RADEON_BIOS_7_SCRATCH               0x002c
+#       define RADEON_SYS_HOTKEY            (1 << 10)
+#       define RADEON_DRV_LOADED            (1 << 12)
+#define RADEON_BIOS_ROM                     0x0f30 /* PCI */
+#define RADEON_BIST                         0x0f0f /* PCI */
+#define RADEON_BRUSH_DATA0                  0x1480
+#define RADEON_BRUSH_DATA1                  0x1484
+#define RADEON_BRUSH_DATA10                 0x14a8
+#define RADEON_BRUSH_DATA11                 0x14ac
+#define RADEON_BRUSH_DATA12                 0x14b0
+#define RADEON_BRUSH_DATA13                 0x14b4
+#define RADEON_BRUSH_DATA14                 0x14b8
+#define RADEON_BRUSH_DATA15                 0x14bc
+#define RADEON_BRUSH_DATA16                 0x14c0
+#define RADEON_BRUSH_DATA17                 0x14c4
+#define RADEON_BRUSH_DATA18                 0x14c8
+#define RADEON_BRUSH_DATA19                 0x14cc
+#define RADEON_BRUSH_DATA2                  0x1488
+#define RADEON_BRUSH_DATA20                 0x14d0
+#define RADEON_BRUSH_DATA21                 0x14d4
+#define RADEON_BRUSH_DATA22                 0x14d8
+#define RADEON_BRUSH_DATA23                 0x14dc
+#define RADEON_BRUSH_DATA24                 0x14e0
+#define RADEON_BRUSH_DATA25                 0x14e4
+#define RADEON_BRUSH_DATA26                 0x14e8
+#define RADEON_BRUSH_DATA27                 0x14ec
+#define RADEON_BRUSH_DATA28                 0x14f0
+#define RADEON_BRUSH_DATA29                 0x14f4
+#define RADEON_BRUSH_DATA3                  0x148c
+#define RADEON_BRUSH_DATA30                 0x14f8
+#define RADEON_BRUSH_DATA31                 0x14fc
+#define RADEON_BRUSH_DATA32                 0x1500
+#define RADEON_BRUSH_DATA33                 0x1504
+#define RADEON_BRUSH_DATA34                 0x1508
+#define RADEON_BRUSH_DATA35                 0x150c
+#define RADEON_BRUSH_DATA36                 0x1510
+#define RADEON_BRUSH_DATA37                 0x1514
+#define RADEON_BRUSH_DATA38                 0x1518
+#define RADEON_BRUSH_DATA39                 0x151c
+#define RADEON_BRUSH_DATA4                  0x1490
+#define RADEON_BRUSH_DATA40                 0x1520
+#define RADEON_BRUSH_DATA41                 0x1524
+#define RADEON_BRUSH_DATA42                 0x1528
+#define RADEON_BRUSH_DATA43                 0x152c
+#define RADEON_BRUSH_DATA44                 0x1530
+#define RADEON_BRUSH_DATA45                 0x1534
+#define RADEON_BRUSH_DATA46                 0x1538
+#define RADEON_BRUSH_DATA47                 0x153c
+#define RADEON_BRUSH_DATA48                 0x1540
+#define RADEON_BRUSH_DATA49                 0x1544
+#define RADEON_BRUSH_DATA5                  0x1494
+#define RADEON_BRUSH_DATA50                 0x1548
+#define RADEON_BRUSH_DATA51                 0x154c
+#define RADEON_BRUSH_DATA52                 0x1550
+#define RADEON_BRUSH_DATA53                 0x1554
+#define RADEON_BRUSH_DATA54                 0x1558
+#define RADEON_BRUSH_DATA55                 0x155c
+#define RADEON_BRUSH_DATA56                 0x1560
+#define RADEON_BRUSH_DATA57                 0x1564
+#define RADEON_BRUSH_DATA58                 0x1568
+#define RADEON_BRUSH_DATA59                 0x156c
+#define RADEON_BRUSH_DATA6                  0x1498
+#define RADEON_BRUSH_DATA60                 0x1570
+#define RADEON_BRUSH_DATA61                 0x1574
+#define RADEON_BRUSH_DATA62                 0x1578
+#define RADEON_BRUSH_DATA63                 0x157c
+#define RADEON_BRUSH_DATA7                  0x149c
+#define RADEON_BRUSH_DATA8                  0x14a0
+#define RADEON_BRUSH_DATA9                  0x14a4
+#define RADEON_BRUSH_SCALE                  0x1470
+#define RADEON_BRUSH_Y_X                    0x1474
+#define RADEON_BUS_CNTL                     0x0030
+#       define RADEON_BUS_MASTER_DIS         (1 << 6)
+#       define RADEON_BUS_BIOS_DIS_ROM       (1 << 12)
+#       define RADEON_BUS_RD_DISCARD_EN      (1 << 24)
+#       define RADEON_BUS_RD_ABORT_EN        (1 << 25)
+#       define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28)
+#       define RADEON_BUS_WRT_BURST          (1 << 29)
+#       define RADEON_BUS_READ_BURST         (1 << 30)
+#define RADEON_BUS_CNTL1                    0x0034
+#       define RADEON_BUS_WAIT_ON_LOCK_EN    (1 << 4)
+
+/* #define RADEON_PCIE_INDEX                   0x0030 */
+/* #define RADEON_PCIE_DATA                    0x0034 */
+#define RADEON_PCIE_LC_LINK_WIDTH_CNTL             0xa2 /* PCIE */
+#       define RADEON_PCIE_LC_LINK_WIDTH_SHIFT     0
+#       define RADEON_PCIE_LC_LINK_WIDTH_MASK      0x7
+#       define RADEON_PCIE_LC_LINK_WIDTH_X0        0
+#       define RADEON_PCIE_LC_LINK_WIDTH_X1        1
+#       define RADEON_PCIE_LC_LINK_WIDTH_X2        2
+#       define RADEON_PCIE_LC_LINK_WIDTH_X4        3
+#       define RADEON_PCIE_LC_LINK_WIDTH_X8        4
+#       define RADEON_PCIE_LC_LINK_WIDTH_X12       5
+#       define RADEON_PCIE_LC_LINK_WIDTH_X16       6
+#       define RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT  4
+#       define RADEON_PCIE_LC_LINK_WIDTH_RD_MASK   0x70
+#       define RADEON_PCIE_LC_RECONFIG_NOW         (1 << 8)
+#       define RADEON_PCIE_LC_RECONFIG_LATER       (1 << 9)
+#       define RADEON_PCIE_LC_SHORT_RECONFIG_EN    (1 << 10)
+
+#define RADEON_CACHE_CNTL                   0x1724
+#define RADEON_CACHE_LINE                   0x0f0c /* PCI */
+#define RADEON_CAPABILITIES_ID              0x0f50 /* PCI */
+#define RADEON_CAPABILITIES_PTR             0x0f34 /* PCI */
+#define RADEON_CLK_PIN_CNTL                 0x0001 /* PLL */
+#       define RADEON_DONT_USE_XTALIN       (1 << 4)
+#       define RADEON_SCLK_DYN_START_CNTL   (1 << 15)
+#define RADEON_CLOCK_CNTL_DATA              0x000c
+#define RADEON_CLOCK_CNTL_INDEX             0x0008
+#       define RADEON_PLL_WR_EN             (1 << 7)
+#       define RADEON_PLL_DIV_SEL           (3 << 8)
+#       define RADEON_PLL2_DIV_SEL_MASK     (~(3 << 8))
+#define RADEON_CLK_PWRMGT_CNTL              0x0014
+#       define RADEON_ENGIN_DYNCLK_MODE     (1 << 12)
+#       define RADEON_ACTIVE_HILO_LAT_MASK  (3 << 13)
+#       define RADEON_ACTIVE_HILO_LAT_SHIFT 13
+#       define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12)
+#       define RADEON_MC_BUSY               (1 << 16)
+#       define RADEON_DLL_READY             (1 << 19)
+#       define RADEON_CG_NO1_DEBUG_0        (1 << 24)
+#       define RADEON_CG_NO1_DEBUG_MASK     (0x1f << 24)
+#       define RADEON_DYN_STOP_MODE_MASK    (7 << 21)
+#       define RADEON_TVPLL_PWRMGT_OFF      (1 << 30)
+#       define RADEON_TVCLK_TURNOFF         (1 << 31)
+#define RADEON_PLL_PWRMGT_CNTL              0x0015 /* PLL */
+#       define RADEON_TCL_BYPASS_DISABLE    (1 << 20)
+#define RADEON_CLR_CMP_CLR_3D               0x1a24
+#define RADEON_CLR_CMP_CLR_DST              0x15c8
+#define RADEON_CLR_CMP_CLR_SRC              0x15c4
+#define RADEON_CLR_CMP_CNTL                 0x15c0
+#       define RADEON_SRC_CMP_EQ_COLOR      (4 <<  0)
+#       define RADEON_SRC_CMP_NEQ_COLOR     (5 <<  0)
+#       define RADEON_CLR_CMP_SRC_SOURCE    (1 << 24)
+#define RADEON_CLR_CMP_MASK                 0x15cc
+#       define RADEON_CLR_CMP_MSK           0xffffffff
+#define RADEON_CLR_CMP_MASK_3D              0x1A28
+#define RADEON_COMMAND                      0x0f04 /* PCI */
+#define RADEON_COMPOSITE_SHADOW_ID          0x1a0c
+#define RADEON_CONFIG_APER_0_BASE           0x0100
+#define RADEON_CONFIG_APER_1_BASE           0x0104
+#define RADEON_CONFIG_APER_SIZE             0x0108
+#define RADEON_CONFIG_BONDS                 0x00e8
+#define RADEON_CONFIG_CNTL                  0x00e0
+#       define RADEON_CFG_ATI_REV_A11       (0   << 16)
+#       define RADEON_CFG_ATI_REV_A12       (1   << 16)
+#       define RADEON_CFG_ATI_REV_A13       (2   << 16)
+#       define RADEON_CFG_ATI_REV_ID_MASK   (0xf << 16)
+#define RADEON_CONFIG_MEMSIZE               0x00f8
+#define RADEON_CONFIG_MEMSIZE_EMBEDDED      0x0114
+#define RADEON_CONFIG_REG_1_BASE            0x010c
+#define RADEON_CONFIG_REG_APER_SIZE         0x0110
+#define RADEON_CONFIG_XSTRAP                0x00e4
+#define RADEON_CONSTANT_COLOR_C             0x1d34
+#       define RADEON_CONSTANT_COLOR_MASK   0x00ffffff
+#       define RADEON_CONSTANT_COLOR_ONE    0x00ffffff
+#       define RADEON_CONSTANT_COLOR_ZERO   0x00000000
+#define RADEON_CRC_CMDFIFO_ADDR             0x0740
+#define RADEON_CRC_CMDFIFO_DOUT             0x0744
+#define RADEON_GRPH_BUFFER_CNTL             0x02f0
+#       define RADEON_GRPH_START_REQ_MASK          (0x7f)
+#       define RADEON_GRPH_START_REQ_SHIFT         0
+#       define RADEON_GRPH_STOP_REQ_MASK           (0x7f<<8)
+#       define RADEON_GRPH_STOP_REQ_SHIFT          8
+#       define RADEON_GRPH_CRITICAL_POINT_MASK     (0x7f<<16)
+#       define RADEON_GRPH_CRITICAL_POINT_SHIFT    16
+#       define RADEON_GRPH_CRITICAL_CNTL           (1<<28)
+#       define RADEON_GRPH_BUFFER_SIZE             (1<<29)
+#       define RADEON_GRPH_CRITICAL_AT_SOF         (1<<30)
+#       define RADEON_GRPH_STOP_CNTL               (1<<31)
+#define RADEON_GRPH2_BUFFER_CNTL            0x03f0
+#       define RADEON_GRPH2_START_REQ_MASK         (0x7f)
+#       define RADEON_GRPH2_START_REQ_SHIFT         0
+#       define RADEON_GRPH2_STOP_REQ_MASK          (0x7f<<8)
+#       define RADEON_GRPH2_STOP_REQ_SHIFT         8
+#       define RADEON_GRPH2_CRITICAL_POINT_MASK    (0x7f<<16)
+#       define RADEON_GRPH2_CRITICAL_POINT_SHIFT   16
+#       define RADEON_GRPH2_CRITICAL_CNTL          (1<<28)
+#       define RADEON_GRPH2_BUFFER_SIZE            (1<<29)
+#       define RADEON_GRPH2_CRITICAL_AT_SOF        (1<<30)
+#       define RADEON_GRPH2_STOP_CNTL              (1<<31)
+#define RADEON_CRTC_CRNT_FRAME              0x0214
+#define RADEON_CRTC_EXT_CNTL                0x0054
+#       define RADEON_CRTC_VGA_XOVERSCAN    (1 <<  0)
+#       define RADEON_VGA_ATI_LINEAR        (1 <<  3)
+#       define RADEON_XCRT_CNT_EN           (1 <<  6)
+#       define RADEON_CRTC_HSYNC_DIS        (1 <<  8)
+#       define RADEON_CRTC_VSYNC_DIS        (1 <<  9)
+#       define RADEON_CRTC_DISPLAY_DIS      (1 << 10)
+#       define RADEON_CRTC_SYNC_TRISTAT     (1 << 11)
+#       define RADEON_CRTC_CRT_ON           (1 << 15)
+#define RADEON_CRTC_EXT_CNTL_DPMS_BYTE      0x0055
+#       define RADEON_CRTC_HSYNC_DIS_BYTE   (1 <<  0)
+#       define RADEON_CRTC_VSYNC_DIS_BYTE   (1 <<  1)
+#       define RADEON_CRTC_DISPLAY_DIS_BYTE (1 <<  2)
+#define RADEON_CRTC_GEN_CNTL                0x0050
+#       define RADEON_CRTC_DBL_SCAN_EN      (1 <<  0)
+#       define RADEON_CRTC_INTERLACE_EN     (1 <<  1)
+#       define RADEON_CRTC_CSYNC_EN         (1 <<  4)
+#       define RADEON_CRTC_ICON_EN          (1 << 15)
+#       define RADEON_CRTC_CUR_EN           (1 << 16)
+#       define RADEON_CRTC_CUR_MODE_MASK    (7 << 20)
+#       define RADEON_CRTC_CUR_MODE_SHIFT   20
+#       define RADEON_CRTC_CUR_MODE_MONO    0
+#       define RADEON_CRTC_CUR_MODE_24BPP   2
+#       define RADEON_CRTC_EXT_DISP_EN      (1 << 24)
+#       define RADEON_CRTC_EN               (1 << 25)
+#       define RADEON_CRTC_DISP_REQ_EN_B    (1 << 26)
+#define RADEON_CRTC2_GEN_CNTL               0x03f8
+#       define RADEON_CRTC2_DBL_SCAN_EN     (1 <<  0)
+#       define RADEON_CRTC2_INTERLACE_EN    (1 <<  1)
+#       define RADEON_CRTC2_SYNC_TRISTAT    (1 <<  4)
+#       define RADEON_CRTC2_HSYNC_TRISTAT   (1 <<  5)
+#       define RADEON_CRTC2_VSYNC_TRISTAT   (1 <<  6)
+#       define RADEON_CRTC2_CRT2_ON         (1 <<  7)
+#       define RADEON_CRTC2_PIX_WIDTH_SHIFT 8
+#       define RADEON_CRTC2_PIX_WIDTH_MASK  (0xf << 8)
+#       define RADEON_CRTC2_ICON_EN         (1 << 15)
+#       define RADEON_CRTC2_CUR_EN          (1 << 16)
+#       define RADEON_CRTC2_CUR_MODE_MASK   (7 << 20)
+#       define RADEON_CRTC2_DISP_DIS        (1 << 23)
+#       define RADEON_CRTC2_EN              (1 << 25)
+#       define RADEON_CRTC2_DISP_REQ_EN_B   (1 << 26)
+#       define RADEON_CRTC2_CSYNC_EN        (1 << 27)
+#       define RADEON_CRTC2_HSYNC_DIS       (1 << 28)
+#       define RADEON_CRTC2_VSYNC_DIS       (1 << 29)
+#define RADEON_CRTC_MORE_CNTL               0x27c
+#       define RADEON_CRTC_AUTO_HORZ_CENTER_EN (1<<2)
+#       define RADEON_CRTC_AUTO_VERT_CENTER_EN (1<<3)
+#       define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4)
+#       define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5)
+#define RADEON_CRTC_GUI_TRIG_VLINE          0x0218
+#define RADEON_CRTC_H_SYNC_STRT_WID         0x0204
+#       define RADEON_CRTC_H_SYNC_STRT_PIX        (0x07  <<  0)
+#       define RADEON_CRTC_H_SYNC_STRT_CHAR       (0x3ff <<  3)
+#       define RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT 3
+#       define RADEON_CRTC_H_SYNC_WID             (0x3f  << 16)
+#       define RADEON_CRTC_H_SYNC_WID_SHIFT       16
+#       define RADEON_CRTC_H_SYNC_POL             (1     << 23)
+#define RADEON_CRTC2_H_SYNC_STRT_WID        0x0304
+#       define RADEON_CRTC2_H_SYNC_STRT_PIX        (0x07  <<  0)
+#       define RADEON_CRTC2_H_SYNC_STRT_CHAR       (0x3ff <<  3)
+#       define RADEON_CRTC2_H_SYNC_STRT_CHAR_SHIFT 3
+#       define RADEON_CRTC2_H_SYNC_WID             (0x3f  << 16)
+#       define RADEON_CRTC2_H_SYNC_WID_SHIFT       16
+#       define RADEON_CRTC2_H_SYNC_POL             (1     << 23)
+#define RADEON_CRTC_H_TOTAL_DISP            0x0200
+#       define RADEON_CRTC_H_TOTAL          (0x03ff << 0)
+#       define RADEON_CRTC_H_TOTAL_SHIFT    0
+#       define RADEON_CRTC_H_DISP           (0x01ff << 16)
+#       define RADEON_CRTC_H_DISP_SHIFT     16
+#define RADEON_CRTC2_H_TOTAL_DISP           0x0300
+#       define RADEON_CRTC2_H_TOTAL         (0x03ff << 0)
+#       define RADEON_CRTC2_H_TOTAL_SHIFT   0
+#       define RADEON_CRTC2_H_DISP          (0x01ff << 16)
+#       define RADEON_CRTC2_H_DISP_SHIFT    16
+
+#define RADEON_CRTC_OFFSET_RIGHT	    0x0220
+#define RADEON_CRTC_OFFSET                  0x0224
+#	define RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET (1<<30)
+#	define RADEON_CRTC_OFFSET__OFFSET_LOCK	   (1<<31)
+
+#define RADEON_CRTC2_OFFSET                 0x0324
+#	define RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET (1<<30)
+#	define RADEON_CRTC2_OFFSET__OFFSET_LOCK	    (1<<31)
+#define RADEON_CRTC_OFFSET_CNTL             0x0228
+#       define RADEON_CRTC_TILE_LINE_SHIFT              0
+#       define RADEON_CRTC_TILE_LINE_RIGHT_SHIFT        4
+#	define R300_CRTC_X_Y_MODE_EN_RIGHT		(1 << 6)
+#	define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_MASK   (3 << 7)
+#	define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_AUTO   (0 << 7)
+#	define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_SINGLE (1 << 7)
+#	define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DOUBLE (2 << 7)
+#	define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DIS    (3 << 7)
+#	define R300_CRTC_X_Y_MODE_EN			(1 << 9)
+#	define R300_CRTC_MICRO_TILE_BUFFER_MASK		(3 << 10)
+#	define R300_CRTC_MICRO_TILE_BUFFER_AUTO		(0 << 10)
+#	define R300_CRTC_MICRO_TILE_BUFFER_SINGLE	(1 << 10)
+#	define R300_CRTC_MICRO_TILE_BUFFER_DOUBLE	(2 << 10)
+#	define R300_CRTC_MICRO_TILE_BUFFER_DIS		(3 << 10)
+#	define R300_CRTC_MICRO_TILE_EN_RIGHT		(1 << 12)
+#	define R300_CRTC_MICRO_TILE_EN			(1 << 13)
+#	define R300_CRTC_MACRO_TILE_EN_RIGHT		(1 << 14)
+#       define R300_CRTC_MACRO_TILE_EN                  (1 << 15)
+#       define RADEON_CRTC_TILE_EN_RIGHT                (1 << 14)
+#       define RADEON_CRTC_TILE_EN                      (1 << 15)
+#       define RADEON_CRTC_OFFSET_FLIP_CNTL             (1 << 16)
+#       define RADEON_CRTC_STEREO_OFFSET_EN             (1 << 17)
+
+#define R300_CRTC_TILE_X0_Y0	            0x0350
+#define R300_CRTC2_TILE_X0_Y0	            0x0358
+
+#define RADEON_CRTC2_OFFSET_CNTL            0x0328
+#       define RADEON_CRTC2_OFFSET_FLIP_CNTL (1 << 16)
+#       define RADEON_CRTC2_TILE_EN         (1 << 15)
+#define RADEON_CRTC_PITCH                   0x022c
+#	define RADEON_CRTC_PITCH__SHIFT		 0
+#	define RADEON_CRTC_PITCH__RIGHT_SHIFT	16
+
+#define RADEON_CRTC2_PITCH                  0x032c
+#define RADEON_CRTC_STATUS                  0x005c
+#       define RADEON_CRTC_VBLANK_SAVE      (1 <<  1)
+#       define RADEON_CRTC_VBLANK_SAVE_CLEAR  (1 <<  1)
+#define RADEON_CRTC2_STATUS                  0x03fc
+#       define RADEON_CRTC2_VBLANK_SAVE      (1 <<  1)
+#       define RADEON_CRTC2_VBLANK_SAVE_CLEAR  (1 <<  1)
+#define RADEON_CRTC_V_SYNC_STRT_WID         0x020c
+#       define RADEON_CRTC_V_SYNC_STRT        (0x7ff <<  0)
+#       define RADEON_CRTC_V_SYNC_STRT_SHIFT  0
+#       define RADEON_CRTC_V_SYNC_WID         (0x1f  << 16)
+#       define RADEON_CRTC_V_SYNC_WID_SHIFT   16
+#       define RADEON_CRTC_V_SYNC_POL         (1     << 23)
+#define RADEON_CRTC2_V_SYNC_STRT_WID        0x030c
+#       define RADEON_CRTC2_V_SYNC_STRT       (0x7ff <<  0)
+#       define RADEON_CRTC2_V_SYNC_STRT_SHIFT 0
+#       define RADEON_CRTC2_V_SYNC_WID        (0x1f  << 16)
+#       define RADEON_CRTC2_V_SYNC_WID_SHIFT  16
+#       define RADEON_CRTC2_V_SYNC_POL        (1     << 23)
+#define RADEON_CRTC_V_TOTAL_DISP            0x0208
+#       define RADEON_CRTC_V_TOTAL          (0x07ff << 0)
+#       define RADEON_CRTC_V_TOTAL_SHIFT    0
+#       define RADEON_CRTC_V_DISP           (0x07ff << 16)
+#       define RADEON_CRTC_V_DISP_SHIFT     16
+#define RADEON_CRTC2_V_TOTAL_DISP           0x0308
+#       define RADEON_CRTC2_V_TOTAL         (0x07ff << 0)
+#       define RADEON_CRTC2_V_TOTAL_SHIFT   0
+#       define RADEON_CRTC2_V_DISP          (0x07ff << 16)
+#       define RADEON_CRTC2_V_DISP_SHIFT    16
+#define RADEON_CRTC_VLINE_CRNT_VLINE        0x0210
+#       define RADEON_CRTC_CRNT_VLINE_MASK  (0x7ff << 16)
+#define RADEON_CRTC2_CRNT_FRAME             0x0314
+#define RADEON_CRTC2_GUI_TRIG_VLINE         0x0318
+#define RADEON_CRTC2_STATUS                 0x03fc
+#define RADEON_CRTC2_VLINE_CRNT_VLINE       0x0310
+#define RADEON_CRTC8_DATA                   0x03d5 /* VGA, 0x3b5 */
+#define RADEON_CRTC8_IDX                    0x03d4 /* VGA, 0x3b4 */
+#define RADEON_CUR_CLR0                     0x026c
+#define RADEON_CUR_CLR1                     0x0270
+#define RADEON_CUR_HORZ_VERT_OFF            0x0268
+#define RADEON_CUR_HORZ_VERT_POSN           0x0264
+#define RADEON_CUR_OFFSET                   0x0260
+#       define RADEON_CUR_LOCK              (1 << 31)
+#define RADEON_CUR2_CLR0                    0x036c
+#define RADEON_CUR2_CLR1                    0x0370
+#define RADEON_CUR2_HORZ_VERT_OFF           0x0368
+#define RADEON_CUR2_HORZ_VERT_POSN          0x0364
+#define RADEON_CUR2_OFFSET                  0x0360
+#       define RADEON_CUR2_LOCK             (1 << 31)
+
+#define RADEON_DAC_CNTL                     0x0058
+#       define RADEON_DAC_RANGE_CNTL        (3 <<  0)
+#       define RADEON_DAC_RANGE_CNTL_PS2    (2 <<  0)
+#       define RADEON_DAC_RANGE_CNTL_MASK   0x03
+#       define RADEON_DAC_BLANKING          (1 <<  2)
+#       define RADEON_DAC_CMP_EN            (1 <<  3)
+#       define RADEON_DAC_CMP_OUTPUT        (1 <<  7)
+#       define RADEON_DAC_8BIT_EN           (1 <<  8)
+#       define RADEON_DAC_TVO_EN            (1 << 10)
+#       define RADEON_DAC_VGA_ADR_EN        (1 << 13)
+#       define RADEON_DAC_PDWN              (1 << 15)
+#       define RADEON_DAC_MASK_ALL          (0xff << 24)
+#define RADEON_DAC_CNTL2                    0x007c
+#       define RADEON_DAC2_TV_CLK_SEL       (0 <<  1)
+#       define RADEON_DAC2_DAC_CLK_SEL      (1 <<  0)
+#       define RADEON_DAC2_DAC2_CLK_SEL     (1 <<  1)
+#       define RADEON_DAC2_PALETTE_ACC_CTL  (1 <<  5)
+#       define RADEON_DAC2_CMP_EN           (1 <<  7)
+#       define RADEON_DAC2_CMP_OUT_R        (1 <<  8)
+#       define RADEON_DAC2_CMP_OUT_G        (1 <<  9)
+#       define RADEON_DAC2_CMP_OUT_B        (1 << 10)
+#       define RADEON_DAC2_CMP_OUTPUT       (1 << 11)
+#define RADEON_DAC_EXT_CNTL                 0x0280
+#       define RADEON_DAC2_FORCE_BLANK_OFF_EN (1 << 0)
+#       define RADEON_DAC2_FORCE_DATA_EN      (1 << 1)
+#       define RADEON_DAC_FORCE_BLANK_OFF_EN  (1 << 4)
+#       define RADEON_DAC_FORCE_DATA_EN       (1 << 5)
+#       define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_R    (0 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_G    (1 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_B    (2 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_RGB  (3 << 6)
+#       define RADEON_DAC_FORCE_DATA_MASK   0x0003ff00
+#       define RADEON_DAC_FORCE_DATA_SHIFT  8
+#define RADEON_DAC_MACRO_CNTL               0x0d04
+#       define RADEON_DAC_PDWN_R            (1 << 16)
+#       define RADEON_DAC_PDWN_G            (1 << 17)
+#       define RADEON_DAC_PDWN_B            (1 << 18)
+#define RADEON_DISP_PWR_MAN                 0x0d08
+#       define RADEON_DISP_PWR_MAN_D3_CRTC_EN      (1 << 0)
+#       define RADEON_DISP_PWR_MAN_D3_CRTC2_EN     (1 << 4)
+#       define RADEON_DISP_PWR_MAN_DPMS_ON  (0 << 8)
+#       define RADEON_DISP_PWR_MAN_DPMS_STANDBY    (1 << 8)
+#       define RADEON_DISP_PWR_MAN_DPMS_SUSPEND    (2 << 8)
+#       define RADEON_DISP_PWR_MAN_DPMS_OFF (3 << 8)
+#       define RADEON_DISP_D3_RST           (1 << 16)
+#       define RADEON_DISP_D3_REG_RST       (1 << 17)
+#       define RADEON_DISP_D3_GRPH_RST      (1 << 18)
+#       define RADEON_DISP_D3_SUBPIC_RST    (1 << 19)
+#       define RADEON_DISP_D3_OV0_RST       (1 << 20)
+#       define RADEON_DISP_D1D2_GRPH_RST    (1 << 21)
+#       define RADEON_DISP_D1D2_SUBPIC_RST  (1 << 22)
+#       define RADEON_DISP_D1D2_OV0_RST     (1 << 23)
+#       define RADEON_DIG_TMDS_ENABLE_RST   (1 << 24)
+#       define RADEON_TV_ENABLE_RST         (1 << 25)
+#       define RADEON_AUTO_PWRUP_EN         (1 << 26)
+#define RADEON_TV_DAC_CNTL                  0x088c
+#       define RADEON_TV_DAC_NBLANK         (1 << 0)
+#       define RADEON_TV_DAC_NHOLD          (1 << 1)
+#       define RADEON_TV_DAC_PEDESTAL       (1 <<  2)
+#       define RADEON_TV_MONITOR_DETECT_EN  (1 <<  4)
+#       define RADEON_TV_DAC_CMPOUT         (1 <<  5)
+#       define RADEON_TV_DAC_STD_MASK       (3 <<  8)
+#       define RADEON_TV_DAC_STD_PAL        (0 <<  8)
+#       define RADEON_TV_DAC_STD_NTSC       (1 <<  8)
+#       define RADEON_TV_DAC_STD_PS2        (2 <<  8)
+#       define RADEON_TV_DAC_STD_RS343      (3 <<  8)
+#       define RADEON_TV_DAC_BGSLEEP        (1 <<  6)
+#       define RADEON_TV_DAC_BGADJ_MASK     (0xf <<  16)
+#       define RADEON_TV_DAC_BGADJ_SHIFT    16
+#       define RADEON_TV_DAC_DACADJ_MASK    (0xf <<  20)
+#       define RADEON_TV_DAC_DACADJ_SHIFT   20
+#       define RADEON_TV_DAC_RDACPD         (1 <<  24)
+#       define RADEON_TV_DAC_GDACPD         (1 <<  25)
+#       define RADEON_TV_DAC_BDACPD         (1 <<  26)
+#       define RADEON_TV_DAC_RDACDET        (1 << 29)
+#       define RADEON_TV_DAC_GDACDET        (1 << 30)
+#       define RADEON_TV_DAC_BDACDET        (1 << 31)
+#       define R420_TV_DAC_DACADJ_MASK      (0x1f <<  20)
+#       define R420_TV_DAC_RDACPD           (1 <<  25)
+#       define R420_TV_DAC_GDACPD           (1 <<  26)
+#       define R420_TV_DAC_BDACPD           (1 <<  27)
+#       define R420_TV_DAC_TVENABLE         (1 <<  28)
+#define RADEON_DISP_HW_DEBUG                0x0d14
+#       define RADEON_CRT2_DISP1_SEL        (1 <<  5)
+#define RADEON_DISP_OUTPUT_CNTL             0x0d64
+#       define RADEON_DISP_DAC_SOURCE_MASK  0x03
+#       define RADEON_DISP_DAC2_SOURCE_MASK  0x0c
+#       define RADEON_DISP_DAC_SOURCE_CRTC2 0x01
+#       define RADEON_DISP_DAC_SOURCE_RMX   0x02
+#       define RADEON_DISP_DAC_SOURCE_LTU   0x03
+#       define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04
+#       define RADEON_DISP_TVDAC_SOURCE_MASK  (0x03 << 2)
+#       define RADEON_DISP_TVDAC_SOURCE_CRTC  0x0
+#       define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01 << 2)
+#       define RADEON_DISP_TVDAC_SOURCE_RMX   (0x02 << 2)
+#       define RADEON_DISP_TVDAC_SOURCE_LTU   (0x03 << 2)
+#       define RADEON_DISP_TRANS_MATRIX_MASK  (0x03 << 4)
+#       define RADEON_DISP_TRANS_MATRIX_ALPHA_MSB (0x00 << 4)
+#       define RADEON_DISP_TRANS_MATRIX_GRAPHICS  (0x01 << 4)
+#       define RADEON_DISP_TRANS_MATRIX_VIDEO     (0x02 << 4)
+#       define RADEON_DISP_TV_SOURCE_CRTC   (1 << 16) /* crtc1 or crtc2 */
+#       define RADEON_DISP_TV_SOURCE_LTU    (0 << 16) /* linear transform unit */
+#define RADEON_DISP_TV_OUT_CNTL             0x0d6c
+#       define RADEON_DISP_TV_PATH_SRC_CRTC2 (1 << 16)
+#       define RADEON_DISP_TV_PATH_SRC_CRTC1 (0 << 16)
+#define RADEON_DAC_CRC_SIG                  0x02cc
+#define RADEON_DAC_DATA                     0x03c9 /* VGA */
+#define RADEON_DAC_MASK                     0x03c6 /* VGA */
+#define RADEON_DAC_R_INDEX                  0x03c7 /* VGA */
+#define RADEON_DAC_W_INDEX                  0x03c8 /* VGA */
+#define RADEON_DDA_CONFIG                   0x02e0
+#define RADEON_DDA_ON_OFF                   0x02e4
+#define RADEON_DEFAULT_OFFSET               0x16e0
+#define RADEON_DEFAULT_PITCH                0x16e4
+#define RADEON_DEFAULT_SC_BOTTOM_RIGHT      0x16e8
+#       define RADEON_DEFAULT_SC_RIGHT_MAX  (0x1fff <<  0)
+#       define RADEON_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16)
+#define RADEON_DESTINATION_3D_CLR_CMP_VAL   0x1820
+#define RADEON_DESTINATION_3D_CLR_CMP_MSK   0x1824
+#define RADEON_DEVICE_ID                    0x0f02 /* PCI */
+#define RADEON_DISP_MISC_CNTL               0x0d00
+#       define RADEON_SOFT_RESET_GRPH_PP    (1 << 0)
+#define RADEON_DISP_MERGE_CNTL		  0x0d60
+#       define RADEON_DISP_ALPHA_MODE_MASK  0x03
+#       define RADEON_DISP_ALPHA_MODE_KEY   0
+#       define RADEON_DISP_ALPHA_MODE_PER_PIXEL 1
+#       define RADEON_DISP_ALPHA_MODE_GLOBAL 2
+#       define RADEON_DISP_RGB_OFFSET_EN    (1 << 8)
+#       define RADEON_DISP_GRPH_ALPHA_MASK  (0xff << 16)
+#       define RADEON_DISP_OV0_ALPHA_MASK   (0xff << 24)
+#	define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9)
+#define RADEON_DISP2_MERGE_CNTL		    0x0d68
+#       define RADEON_DISP2_RGB_OFFSET_EN   (1 << 8)
+#define RADEON_DISP_LIN_TRANS_GRPH_A        0x0d80
+#define RADEON_DISP_LIN_TRANS_GRPH_B        0x0d84
+#define RADEON_DISP_LIN_TRANS_GRPH_C        0x0d88
+#define RADEON_DISP_LIN_TRANS_GRPH_D        0x0d8c
+#define RADEON_DISP_LIN_TRANS_GRPH_E        0x0d90
+#define RADEON_DISP_LIN_TRANS_GRPH_F        0x0d98
+#define RADEON_DP_BRUSH_BKGD_CLR            0x1478
+#define RADEON_DP_BRUSH_FRGD_CLR            0x147c
+#define RADEON_DP_CNTL                      0x16c0
+#       define RADEON_DST_X_LEFT_TO_RIGHT   (1 <<  0)
+#       define RADEON_DST_Y_TOP_TO_BOTTOM   (1 <<  1)
+#       define RADEON_DP_DST_TILE_LINEAR    (0 <<  3)
+#       define RADEON_DP_DST_TILE_MACRO     (1 <<  3)
+#       define RADEON_DP_DST_TILE_MICRO     (2 <<  3)
+#       define RADEON_DP_DST_TILE_BOTH      (3 <<  3)
+#define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR     0x16d0
+#       define RADEON_DST_Y_MAJOR             (1 <<  2)
+#       define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15)
+#       define RADEON_DST_X_DIR_LEFT_TO_RIGHT (1 << 31)
+#define RADEON_DP_DATATYPE                  0x16c4
+#       define RADEON_HOST_BIG_ENDIAN_EN    (1 << 29)
+#define RADEON_DP_GUI_MASTER_CNTL           0x146c
+#       define RADEON_GMC_SRC_PITCH_OFFSET_CNTL   (1    <<  0)
+#       define RADEON_GMC_DST_PITCH_OFFSET_CNTL   (1    <<  1)
+#       define RADEON_GMC_SRC_CLIPPING            (1    <<  2)
+#       define RADEON_GMC_DST_CLIPPING            (1    <<  3)
+#       define RADEON_GMC_BRUSH_DATATYPE_MASK     (0x0f <<  4)
+#       define RADEON_GMC_BRUSH_8X8_MONO_FG_BG    (0    <<  4)
+#       define RADEON_GMC_BRUSH_8X8_MONO_FG_LA    (1    <<  4)
+#       define RADEON_GMC_BRUSH_1X8_MONO_FG_BG    (4    <<  4)
+#       define RADEON_GMC_BRUSH_1X8_MONO_FG_LA    (5    <<  4)
+#       define RADEON_GMC_BRUSH_32x1_MONO_FG_BG   (6    <<  4)
+#       define RADEON_GMC_BRUSH_32x1_MONO_FG_LA   (7    <<  4)
+#       define RADEON_GMC_BRUSH_32x32_MONO_FG_BG  (8    <<  4)
+#       define RADEON_GMC_BRUSH_32x32_MONO_FG_LA  (9    <<  4)
+#       define RADEON_GMC_BRUSH_8x8_COLOR         (10   <<  4)
+#       define RADEON_GMC_BRUSH_1X8_COLOR         (12   <<  4)
+#       define RADEON_GMC_BRUSH_SOLID_COLOR       (13   <<  4)
+#       define RADEON_GMC_BRUSH_NONE              (15   <<  4)
+#       define RADEON_GMC_DST_8BPP_CI             (2    <<  8)
+#       define RADEON_GMC_DST_15BPP               (3    <<  8)
+#       define RADEON_GMC_DST_16BPP               (4    <<  8)
+#       define RADEON_GMC_DST_24BPP               (5    <<  8)
+#       define RADEON_GMC_DST_32BPP               (6    <<  8)
+#       define RADEON_GMC_DST_8BPP_RGB            (7    <<  8)
+#       define RADEON_GMC_DST_Y8                  (8    <<  8)
+#       define RADEON_GMC_DST_RGB8                (9    <<  8)
+#       define RADEON_GMC_DST_VYUY                (11   <<  8)
+#       define RADEON_GMC_DST_YVYU                (12   <<  8)
+#       define RADEON_GMC_DST_AYUV444             (14   <<  8)
+#       define RADEON_GMC_DST_ARGB4444            (15   <<  8)
+#       define RADEON_GMC_DST_DATATYPE_MASK       (0x0f <<  8)
+#       define RADEON_GMC_DST_DATATYPE_SHIFT      8
+#       define RADEON_GMC_SRC_DATATYPE_MASK       (3    << 12)
+#       define RADEON_GMC_SRC_DATATYPE_MONO_FG_BG (0    << 12)
+#       define RADEON_GMC_SRC_DATATYPE_MONO_FG_LA (1    << 12)
+#       define RADEON_GMC_SRC_DATATYPE_COLOR      (3    << 12)
+#       define RADEON_GMC_BYTE_PIX_ORDER          (1    << 14)
+#       define RADEON_GMC_BYTE_MSB_TO_LSB         (0    << 14)
+#       define RADEON_GMC_BYTE_LSB_TO_MSB         (1    << 14)
+#       define RADEON_GMC_CONVERSION_TEMP         (1    << 15)
+#       define RADEON_GMC_CONVERSION_TEMP_6500    (0    << 15)
+#       define RADEON_GMC_CONVERSION_TEMP_9300    (1    << 15)
+#       define RADEON_GMC_ROP3_MASK               (0xff << 16)
+#       define RADEON_DP_SRC_SOURCE_MASK          (7    << 24)
+#       define RADEON_DP_SRC_SOURCE_MEMORY        (2    << 24)
+#       define RADEON_DP_SRC_SOURCE_HOST_DATA     (3    << 24)
+#       define RADEON_GMC_3D_FCN_EN               (1    << 27)
+#       define RADEON_GMC_CLR_CMP_CNTL_DIS        (1    << 28)
+#       define RADEON_GMC_AUX_CLIP_DIS            (1    << 29)
+#       define RADEON_GMC_WR_MSK_DIS              (1    << 30)
+#       define RADEON_GMC_LD_BRUSH_Y_X            (1    << 31)
+#       define RADEON_ROP3_ZERO             0x00000000
+#       define RADEON_ROP3_DSa              0x00880000
+#       define RADEON_ROP3_SDna             0x00440000
+#       define RADEON_ROP3_S                0x00cc0000
+#       define RADEON_ROP3_DSna             0x00220000
+#       define RADEON_ROP3_D                0x00aa0000
+#       define RADEON_ROP3_DSx              0x00660000
+#       define RADEON_ROP3_DSo              0x00ee0000
+#       define RADEON_ROP3_DSon             0x00110000
+#       define RADEON_ROP3_DSxn             0x00990000
+#       define RADEON_ROP3_Dn               0x00550000
+#       define RADEON_ROP3_SDno             0x00dd0000
+#       define RADEON_ROP3_Sn               0x00330000
+#       define RADEON_ROP3_DSno             0x00bb0000
+#       define RADEON_ROP3_DSan             0x00770000
+#       define RADEON_ROP3_ONE              0x00ff0000
+#       define RADEON_ROP3_DPa              0x00a00000
+#       define RADEON_ROP3_PDna             0x00500000
+#       define RADEON_ROP3_P                0x00f00000
+#       define RADEON_ROP3_DPna             0x000a0000
+#       define RADEON_ROP3_D                0x00aa0000
+#       define RADEON_ROP3_DPx              0x005a0000
+#       define RADEON_ROP3_DPo              0x00fa0000
+#       define RADEON_ROP3_DPon             0x00050000
+#       define RADEON_ROP3_PDxn             0x00a50000
+#       define RADEON_ROP3_PDno             0x00f50000
+#       define RADEON_ROP3_Pn               0x000f0000
+#       define RADEON_ROP3_DPno             0x00af0000
+#       define RADEON_ROP3_DPan             0x005f0000
+#define RADEON_DP_GUI_MASTER_CNTL_C         0x1c84
+#define RADEON_DP_MIX                       0x16c8
+#define RADEON_DP_SRC_BKGD_CLR              0x15dc
+#define RADEON_DP_SRC_FRGD_CLR              0x15d8
+#define RADEON_DP_WRITE_MASK                0x16cc
+#define RADEON_DST_BRES_DEC                 0x1630
+#define RADEON_DST_BRES_ERR                 0x1628
+#define RADEON_DST_BRES_INC                 0x162c
+#define RADEON_DST_BRES_LNTH                0x1634
+#define RADEON_DST_BRES_LNTH_SUB            0x1638
+#define RADEON_DST_HEIGHT                   0x1410
+#define RADEON_DST_HEIGHT_WIDTH             0x143c
+#define RADEON_DST_HEIGHT_WIDTH_8           0x158c
+#define RADEON_DST_HEIGHT_WIDTH_BW          0x15b4
+#define RADEON_DST_HEIGHT_Y                 0x15a0
+#define RADEON_DST_LINE_START               0x1600
+#define RADEON_DST_LINE_END                 0x1604
+#define RADEON_DST_LINE_PATCOUNT            0x1608
+#       define RADEON_BRES_CNTL_SHIFT       8
+#define RADEON_DST_OFFSET                   0x1404
+#define RADEON_DST_PITCH                    0x1408
+#define RADEON_DST_PITCH_OFFSET             0x142c
+#define RADEON_DST_PITCH_OFFSET_C           0x1c80
+#       define RADEON_PITCH_SHIFT           21
+#       define RADEON_DST_TILE_LINEAR       (0 << 30)
+#       define RADEON_DST_TILE_MACRO        (1 << 30)
+#       define RADEON_DST_TILE_MICRO        (2 << 30)
+#       define RADEON_DST_TILE_BOTH         (3 << 30)
+#define RADEON_DST_WIDTH                    0x140c
+#define RADEON_DST_WIDTH_HEIGHT             0x1598
+#define RADEON_DST_WIDTH_X                  0x1588
+#define RADEON_DST_WIDTH_X_INCY             0x159c
+#define RADEON_DST_X                        0x141c
+#define RADEON_DST_X_SUB                    0x15a4
+#define RADEON_DST_X_Y                      0x1594
+#define RADEON_DST_Y                        0x1420
+#define RADEON_DST_Y_SUB                    0x15a8
+#define RADEON_DST_Y_X                      0x1438
+
+#define RADEON_FCP_CNTL                     0x0910
+#      define RADEON_FCP0_SRC_PCICLK             0
+#      define RADEON_FCP0_SRC_PCLK               1
+#      define RADEON_FCP0_SRC_PCLKb              2
+#      define RADEON_FCP0_SRC_HREF               3
+#      define RADEON_FCP0_SRC_GND                4
+#      define RADEON_FCP0_SRC_HREFb              5
+#define RADEON_FLUSH_1                      0x1704
+#define RADEON_FLUSH_2                      0x1708
+#define RADEON_FLUSH_3                      0x170c
+#define RADEON_FLUSH_4                      0x1710
+#define RADEON_FLUSH_5                      0x1714
+#define RADEON_FLUSH_6                      0x1718
+#define RADEON_FLUSH_7                      0x171c
+#define RADEON_FOG_3D_TABLE_START           0x1810
+#define RADEON_FOG_3D_TABLE_END             0x1814
+#define RADEON_FOG_3D_TABLE_DENSITY         0x181c
+#define RADEON_FOG_TABLE_INDEX              0x1a14
+#define RADEON_FOG_TABLE_DATA               0x1a18
+#define RADEON_FP_CRTC_H_TOTAL_DISP         0x0250
+#define RADEON_FP_CRTC_V_TOTAL_DISP         0x0254
+#       define RADEON_FP_CRTC_H_TOTAL_MASK      0x000003ff
+#       define RADEON_FP_CRTC_H_DISP_MASK       0x01ff0000
+#       define RADEON_FP_CRTC_V_TOTAL_MASK      0x00000fff
+#       define RADEON_FP_CRTC_V_DISP_MASK       0x0fff0000
+#       define RADEON_FP_H_SYNC_STRT_CHAR_MASK  0x00001ff8
+#       define RADEON_FP_H_SYNC_WID_MASK        0x003f0000
+#       define RADEON_FP_V_SYNC_STRT_MASK       0x00000fff
+#       define RADEON_FP_V_SYNC_WID_MASK        0x001f0000
+#       define RADEON_FP_CRTC_H_TOTAL_SHIFT     0x00000000
+#       define RADEON_FP_CRTC_H_DISP_SHIFT      0x00000010
+#       define RADEON_FP_CRTC_V_TOTAL_SHIFT     0x00000000
+#       define RADEON_FP_CRTC_V_DISP_SHIFT      0x00000010
+#       define RADEON_FP_H_SYNC_STRT_CHAR_SHIFT 0x00000003
+#       define RADEON_FP_H_SYNC_WID_SHIFT       0x00000010
+#       define RADEON_FP_V_SYNC_STRT_SHIFT      0x00000000
+#       define RADEON_FP_V_SYNC_WID_SHIFT       0x00000010
+#define RADEON_FP_GEN_CNTL                  0x0284
+#       define RADEON_FP_FPON                  (1 <<  0)
+#       define RADEON_FP_BLANK_EN              (1 <<  1)
+#       define RADEON_FP_TMDS_EN               (1 <<  2)
+#       define RADEON_FP_PANEL_FORMAT          (1 <<  3)
+#       define RADEON_FP_EN_TMDS               (1 <<  7)
+#       define RADEON_FP_DETECT_SENSE          (1 <<  8)
+#       define R200_FP_SOURCE_SEL_MASK         (3 <<  10)
+#       define R200_FP_SOURCE_SEL_CRTC1        (0 <<  10)
+#       define R200_FP_SOURCE_SEL_CRTC2        (1 <<  10)
+#       define R200_FP_SOURCE_SEL_RMX          (2 <<  10)
+#       define R200_FP_SOURCE_SEL_TRANS        (3 <<  10)
+#       define RADEON_FP_SEL_CRTC1             (0 << 13)
+#       define RADEON_FP_SEL_CRTC2             (1 << 13)
+#       define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15)
+#       define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
+#       define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17)
+#       define RADEON_FP_CRTC_USE_SHADOW_VEND  (1 << 18)
+#       define RADEON_FP_RMX_HVSYNC_CONTROL_EN (1 << 20)
+#       define RADEON_FP_DFP_SYNC_SEL          (1 << 21)
+#       define RADEON_FP_CRTC_LOCK_8DOT        (1 << 22)
+#       define RADEON_FP_CRT_SYNC_SEL          (1 << 23)
+#       define RADEON_FP_USE_SHADOW_EN         (1 << 24)
+#       define RADEON_FP_CRT_SYNC_ALT          (1 << 26)
+#define RADEON_FP2_GEN_CNTL                 0x0288
+#       define RADEON_FP2_BLANK_EN             (1 <<  1)
+#       define RADEON_FP2_ON                   (1 <<  2)
+#       define RADEON_FP2_PANEL_FORMAT         (1 <<  3)
+#       define RADEON_FP2_DETECT_SENSE         (1 <<  8)
+#       define R200_FP2_SOURCE_SEL_MASK        (3 << 10)
+#       define R200_FP2_SOURCE_SEL_CRTC1       (0 << 10)
+#       define R200_FP2_SOURCE_SEL_CRTC2       (1 << 10)
+#       define R200_FP2_SOURCE_SEL_RMX         (2 << 10)
+#       define R200_FP2_SOURCE_SEL_TRANS_UNIT  (3 << 10)
+#       define RADEON_FP2_SRC_SEL_MASK         (3 << 13)
+#       define RADEON_FP2_SRC_SEL_CRTC2        (1 << 13)
+#       define RADEON_FP2_FP_POL               (1 << 16)
+#       define RADEON_FP2_LP_POL               (1 << 17)
+#       define RADEON_FP2_SCK_POL              (1 << 18)
+#       define RADEON_FP2_LCD_CNTL_MASK        (7 << 19)
+#       define RADEON_FP2_PAD_FLOP_EN          (1 << 22)
+#       define RADEON_FP2_CRC_EN               (1 << 23)
+#       define RADEON_FP2_CRC_READ_EN          (1 << 24)
+#       define RADEON_FP2_DVO_EN               (1 << 25)
+#       define RADEON_FP2_DVO_RATE_SEL_SDR     (1 << 26)
+#       define R200_FP2_DVO_RATE_SEL_SDR       (1 << 27)
+#       define R300_FP2_DVO_CLOCK_MODE_SINGLE  (1 << 28)
+#       define R300_FP2_DVO_DUAL_CHANNEL_EN    (1 << 29)
+#define RADEON_FP_H_SYNC_STRT_WID           0x02c4
+#define RADEON_FP_H2_SYNC_STRT_WID          0x03c4
+#define RADEON_FP_HORZ_STRETCH              0x028c
+#define RADEON_FP_HORZ2_STRETCH             0x038c
+#       define RADEON_HORZ_STRETCH_RATIO_MASK 0xffff
+#       define RADEON_HORZ_STRETCH_RATIO_MAX  4096
+#       define RADEON_HORZ_PANEL_SIZE         (0x1ff   << 16)
+#       define RADEON_HORZ_PANEL_SHIFT        16
+#       define RADEON_HORZ_STRETCH_PIXREP     (0      << 25)
+#       define RADEON_HORZ_STRETCH_BLEND      (1      << 26)
+#       define RADEON_HORZ_STRETCH_ENABLE     (1      << 25)
+#       define RADEON_HORZ_AUTO_RATIO         (1      << 27)
+#       define RADEON_HORZ_FP_LOOP_STRETCH    (0x7    << 28)
+#       define RADEON_HORZ_AUTO_RATIO_INC     (1      << 31)
+#define RADEON_FP_HORZ_VERT_ACTIVE          0x0278
+#define RADEON_FP_V_SYNC_STRT_WID           0x02c8
+#define RADEON_FP_VERT_STRETCH              0x0290
+#define RADEON_FP_V2_SYNC_STRT_WID          0x03c8
+#define RADEON_FP_VERT2_STRETCH             0x0390
+#       define RADEON_VERT_PANEL_SIZE          (0xfff << 12)
+#       define RADEON_VERT_PANEL_SHIFT         12
+#       define RADEON_VERT_STRETCH_RATIO_MASK  0xfff
+#       define RADEON_VERT_STRETCH_RATIO_SHIFT 0
+#       define RADEON_VERT_STRETCH_RATIO_MAX   4096
+#       define RADEON_VERT_STRETCH_ENABLE      (1     << 25)
+#       define RADEON_VERT_STRETCH_LINEREP     (0     << 26)
+#       define RADEON_VERT_STRETCH_BLEND       (1     << 26)
+#       define RADEON_VERT_AUTO_RATIO_EN       (1     << 27)
+#	define RADEON_VERT_AUTO_RATIO_INC      (1     << 31)
+#       define RADEON_VERT_STRETCH_RESERVED    0x71000000
+#define RS400_FP_2ND_GEN_CNTL               0x0384
+#       define RS400_FP_2ND_ON              (1 << 0)
+#       define RS400_FP_2ND_BLANK_EN        (1 << 1)
+#       define RS400_TMDS_2ND_EN            (1 << 2)
+#       define RS400_PANEL_FORMAT_2ND       (1 << 3)
+#       define RS400_FP_2ND_EN_TMDS         (1 << 7)
+#       define RS400_FP_2ND_DETECT_SENSE    (1 << 8)
+#       define RS400_FP_2ND_SOURCE_SEL_MASK        (3 << 10)
+#       define RS400_FP_2ND_SOURCE_SEL_CRTC1       (0 << 10)
+#       define RS400_FP_2ND_SOURCE_SEL_CRTC2       (1 << 10)
+#       define RS400_FP_2ND_SOURCE_SEL_RMX         (2 << 10)
+#       define RS400_FP_2ND_DETECT_EN       (1 << 12)
+#       define RS400_HPD_2ND_SEL            (1 << 13)
+#define RS400_FP2_2_GEN_CNTL                0x0388
+#       define RS400_FP2_2_BLANK_EN         (1 << 1)
+#       define RS400_FP2_2_ON               (1 << 2)
+#       define RS400_FP2_2_PANEL_FORMAT     (1 << 3)
+#       define RS400_FP2_2_DETECT_SENSE     (1 << 8)
+#       define RS400_FP2_2_SOURCE_SEL_MASK        (3 << 10)
+#       define RS400_FP2_2_SOURCE_SEL_CRTC1       (0 << 10)
+#       define RS400_FP2_2_SOURCE_SEL_CRTC2       (1 << 10)
+#       define RS400_FP2_2_SOURCE_SEL_RMX         (2 << 10)
+#       define RS400_FP2_2_DVO2_EN          (1 << 25)
+#define RS400_TMDS2_CNTL                    0x0394
+#define RS400_TMDS2_TRANSMITTER_CNTL        0x03a4
+#       define RS400_TMDS2_PLLEN            (1 << 0)
+#       define RS400_TMDS2_PLLRST           (1 << 1)
+
+#define RADEON_GEN_INT_CNTL                 0x0040
+#	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
+#	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
+#	define RADEON_SW_INT_ENABLE		(1 << 25)
+#define RADEON_GEN_INT_STATUS               0x0044
+#	define AVIVO_DISPLAY_INT_STATUS		(1 << 0)
+#	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
+#	define RADEON_CRTC_VBLANK_STAT_ACK	(1 << 0)
+#	define RADEON_CRTC2_VBLANK_STAT		(1 << 9)
+#	define RADEON_CRTC2_VBLANK_STAT_ACK	(1 << 9)
+#	define RADEON_SW_INT_FIRE		(1 << 26)
+#	define RADEON_SW_INT_TEST		(1 << 25)
+#	define RADEON_SW_INT_TEST_ACK		(1 << 25)
+#define RADEON_GENENB                       0x03c3 /* VGA */
+#define RADEON_GENFC_RD                     0x03ca /* VGA */
+#define RADEON_GENFC_WT                     0x03da /* VGA, 0x03ba */
+#define RADEON_GENMO_RD                     0x03cc /* VGA */
+#define RADEON_GENMO_WT                     0x03c2 /* VGA */
+#define RADEON_GENS0                        0x03c2 /* VGA */
+#define RADEON_GENS1                        0x03da /* VGA, 0x03ba */
+#define RADEON_GPIO_MONID                   0x0068 /* DDC interface via I2C */ /* DDC3 */
+#define RADEON_GPIO_MONIDB                  0x006c
+#define RADEON_GPIO_CRT2_DDC                0x006c
+#define RADEON_GPIO_DVI_DDC                 0x0064 /* DDC2 */
+#define RADEON_GPIO_VGA_DDC                 0x0060 /* DDC1 */
+#       define RADEON_GPIO_A_0              (1 <<  0)
+#       define RADEON_GPIO_A_1              (1 <<  1)
+#       define RADEON_GPIO_Y_0              (1 <<  8)
+#       define RADEON_GPIO_Y_1              (1 <<  9)
+#       define RADEON_GPIO_Y_SHIFT_0        8
+#       define RADEON_GPIO_Y_SHIFT_1        9
+#       define RADEON_GPIO_EN_0             (1 << 16)
+#       define RADEON_GPIO_EN_1             (1 << 17)
+#       define RADEON_GPIO_MASK_0           (1 << 24) /*??*/
+#       define RADEON_GPIO_MASK_1           (1 << 25) /*??*/
+#define RADEON_GRPH8_DATA                   0x03cf /* VGA */
+#define RADEON_GRPH8_IDX                    0x03ce /* VGA */
+#define RADEON_GUI_SCRATCH_REG0             0x15e0
+#define RADEON_GUI_SCRATCH_REG1             0x15e4
+#define RADEON_GUI_SCRATCH_REG2             0x15e8
+#define RADEON_GUI_SCRATCH_REG3             0x15ec
+#define RADEON_GUI_SCRATCH_REG4             0x15f0
+#define RADEON_GUI_SCRATCH_REG5             0x15f4
+
+#define RADEON_HEADER                       0x0f0e /* PCI */
+#define RADEON_HOST_DATA0                   0x17c0
+#define RADEON_HOST_DATA1                   0x17c4
+#define RADEON_HOST_DATA2                   0x17c8
+#define RADEON_HOST_DATA3                   0x17cc
+#define RADEON_HOST_DATA4                   0x17d0
+#define RADEON_HOST_DATA5                   0x17d4
+#define RADEON_HOST_DATA6                   0x17d8
+#define RADEON_HOST_DATA7                   0x17dc
+#define RADEON_HOST_DATA_LAST               0x17e0
+#define RADEON_HOST_PATH_CNTL               0x0130
+#	define RADEON_HP_LIN_RD_CACHE_DIS   (1 << 24)
+#	define RADEON_HDP_READ_BUFFER_INVALIDATE   (1 << 27)
+#       define RADEON_HDP_SOFT_RESET        (1 << 26)
+#       define RADEON_HDP_APER_CNTL         (1 << 23)
+#define RADEON_HTOTAL_CNTL                  0x0009 /* PLL */
+#       define RADEON_HTOT_CNTL_VGA_EN      (1 << 28)
+#define RADEON_HTOTAL2_CNTL                 0x002e /* PLL */
+
+       /* Multimedia I2C bus */
+#define RADEON_I2C_CNTL_0		    0x0090
+#define RADEON_I2C_DONE (1<<0)
+#define RADEON_I2C_NACK (1<<1)
+#define RADEON_I2C_HALT (1<<2)
+#define RADEON_I2C_SOFT_RST (1<<5)
+#define RADEON_I2C_DRIVE_EN (1<<6)
+#define RADEON_I2C_DRIVE_SEL (1<<7)
+#define RADEON_I2C_START (1<<8)
+#define RADEON_I2C_STOP (1<<9)
+#define RADEON_I2C_RECEIVE (1<<10)
+#define RADEON_I2C_ABORT (1<<11)
+#define RADEON_I2C_GO (1<<12)
+#define RADEON_I2C_CNTL_1                   0x0094
+#define RADEON_I2C_SEL         (1<<16)
+#define RADEON_I2C_EN          (1<<17)
+#define RADEON_I2C_DATA			    0x0098
+
+#define RADEON_DVI_I2C_CNTL_0		    0x02e0
+#       define R200_DVI_I2C_PIN_SEL(x)      ((x) << 3)
+#       define R200_SEL_DDC1                0 /* 0x60 - VGA_DDC */
+#       define R200_SEL_DDC2                1 /* 0x64 - DVI_DDC */
+#       define R200_SEL_DDC3                2 /* 0x68 - MONID_DDC */
+#define RADEON_DVI_I2C_CNTL_1               0x02e4 /* ? */
+#define RADEON_DVI_I2C_DATA		    0x02e8
+
+#define RADEON_INTERRUPT_LINE               0x0f3c /* PCI */
+#define RADEON_INTERRUPT_PIN                0x0f3d /* PCI */
+#define RADEON_IO_BASE                      0x0f14 /* PCI */
+
+#define RADEON_LATENCY                      0x0f0d /* PCI */
+#define RADEON_LEAD_BRES_DEC                0x1608
+#define RADEON_LEAD_BRES_LNTH               0x161c
+#define RADEON_LEAD_BRES_LNTH_SUB           0x1624
+#define RADEON_LVDS_GEN_CNTL                0x02d0
+#       define RADEON_LVDS_ON               (1   <<  0)
+#       define RADEON_LVDS_DISPLAY_DIS      (1   <<  1)
+#       define RADEON_LVDS_PANEL_TYPE       (1   <<  2)
+#       define RADEON_LVDS_PANEL_FORMAT     (1   <<  3)
+#       define RADEON_LVDS_NO_FM            (0   <<  4)
+#       define RADEON_LVDS_2_GREY           (1   <<  4)
+#       define RADEON_LVDS_4_GREY           (2   <<  4)
+#       define RADEON_LVDS_RST_FM           (1   <<  6)
+#       define RADEON_LVDS_EN               (1   <<  7)
+#       define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8
+#       define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8)
+#       define RADEON_LVDS_BL_MOD_EN        (1   << 16)
+#       define RADEON_LVDS_BL_CLK_SEL       (1   << 17)
+#       define RADEON_LVDS_DIGON            (1   << 18)
+#       define RADEON_LVDS_BLON             (1   << 19)
+#       define RADEON_LVDS_FP_POL_LOW       (1   << 20)
+#       define RADEON_LVDS_LP_POL_LOW       (1   << 21)
+#       define RADEON_LVDS_DTM_POL_LOW      (1   << 22)
+#       define RADEON_LVDS_SEL_CRTC2        (1   << 23)
+#       define RADEON_LVDS_FPDI_EN          (1   << 27)
+#       define RADEON_LVDS_HSYNC_DELAY_SHIFT        28
+#define RADEON_LVDS_PLL_CNTL                0x02d4
+#       define RADEON_HSYNC_DELAY_SHIFT     28
+#       define RADEON_HSYNC_DELAY_MASK      (0xf << 28)
+#       define RADEON_LVDS_PLL_EN           (1   << 16)
+#       define RADEON_LVDS_PLL_RESET        (1   << 17)
+#       define R300_LVDS_SRC_SEL_MASK       (3   << 18)
+#       define R300_LVDS_SRC_SEL_CRTC1      (0   << 18)
+#       define R300_LVDS_SRC_SEL_CRTC2      (1   << 18)
+#       define R300_LVDS_SRC_SEL_RMX        (2   << 18)
+#define RADEON_LVDS_SS_GEN_CNTL             0x02ec
+#       define RADEON_LVDS_PWRSEQ_DELAY1_SHIFT     16
+#       define RADEON_LVDS_PWRSEQ_DELAY2_SHIFT     20
+
+#define RADEON_MAX_LATENCY                  0x0f3f /* PCI */
+#define RADEON_DISPLAY_BASE_ADDR            0x23c
+#define RADEON_DISPLAY2_BASE_ADDR           0x33c
+#define RADEON_OV0_BASE_ADDR                0x43c
+#define RADEON_NB_TOM                       0x15c
+#define R300_MC_INIT_MISC_LAT_TIMER         0x180
+#       define R300_MC_DISP0R_INIT_LAT_SHIFT 8
+#       define R300_MC_DISP0R_INIT_LAT_MASK  0xf
+#       define R300_MC_DISP1R_INIT_LAT_SHIFT 12
+#       define R300_MC_DISP1R_INIT_LAT_MASK  0xf
+#define RADEON_MCLK_CNTL                    0x0012 /* PLL */
+#       define RADEON_MCLKA_SRC_SEL_MASK    0x7
+#       define RADEON_FORCEON_MCLKA         (1 << 16)
+#       define RADEON_FORCEON_MCLKB         (1 << 17)
+#       define RADEON_FORCEON_YCLKA         (1 << 18)
+#       define RADEON_FORCEON_YCLKB         (1 << 19)
+#       define RADEON_FORCEON_MC            (1 << 20)
+#       define RADEON_FORCEON_AIC           (1 << 21)
+#       define R300_DISABLE_MC_MCLKA        (1 << 21)
+#       define R300_DISABLE_MC_MCLKB        (1 << 21)
+#define RADEON_MCLK_MISC                    0x001f /* PLL */
+#       define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1 << 12)
+#       define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13)
+#       define RADEON_MC_MCLK_DYN_ENABLE    (1 << 14)
+#       define RADEON_IO_MCLK_DYN_ENABLE    (1 << 15)
+#define RADEON_LCD_GPIO_MASK                0x01a0
+#define RADEON_GPIOPAD_EN                   0x01a0
+#define RADEON_LCD_GPIO_Y_REG               0x01a4
+#define RADEON_MDGPIO_A_REG                 0x01ac
+#define RADEON_MDGPIO_EN_REG                0x01b0
+#define RADEON_MDGPIO_MASK                  0x0198
+#define RADEON_GPIOPAD_MASK                 0x0198
+#define RADEON_GPIOPAD_A		    0x019c
+#define RADEON_MDGPIO_Y_REG                 0x01b4
+#define RADEON_MEM_ADDR_CONFIG              0x0148
+#define RADEON_MEM_BASE                     0x0f10 /* PCI */
+#define RADEON_MEM_CNTL                     0x0140
+#       define RADEON_MEM_NUM_CHANNELS_MASK 0x01
+#       define RADEON_MEM_USE_B_CH_ONLY     (1 <<  1)
+#       define RV100_HALF_MODE              (1 <<  3)
+#       define R300_MEM_NUM_CHANNELS_MASK   0x03
+#       define R300_MEM_USE_CD_CH_ONLY      (1 <<  2)
+#define RADEON_MEM_TIMING_CNTL              0x0144 /* EXT_MEM_CNTL */
+#define RADEON_MEM_INIT_LAT_TIMER           0x0154
+#define RADEON_MEM_INTF_CNTL                0x014c
+#define RADEON_MEM_SDRAM_MODE_REG           0x0158
+#       define RADEON_SDRAM_MODE_MASK       0xffff0000
+#       define RADEON_B3MEM_RESET_MASK      0x6fffffff
+#       define RADEON_MEM_CFG_TYPE_DDR      (1 << 30)
+#define RADEON_MEM_STR_CNTL                 0x0150
+#       define RADEON_MEM_PWRUP_COMPL_A     (1 <<  0)
+#       define RADEON_MEM_PWRUP_COMPL_B     (1 <<  1)
+#       define R300_MEM_PWRUP_COMPL_C       (1 <<  2)
+#       define R300_MEM_PWRUP_COMPL_D       (1 <<  3)
+#       define RADEON_MEM_PWRUP_COMPLETE    0x03
+#       define R300_MEM_PWRUP_COMPLETE      0x0f
+#define RADEON_MC_STATUS                    0x0150
+#       define RADEON_MC_IDLE               (1 << 2)
+#       define R300_MC_IDLE                 (1 << 4)
+#define RADEON_MEM_VGA_RP_SEL               0x003c
+#define RADEON_MEM_VGA_WP_SEL               0x0038
+#define RADEON_MIN_GRANT                    0x0f3e /* PCI */
+#define RADEON_MM_DATA                      0x0004
+#define RADEON_MM_INDEX                     0x0000
+#	define RADEON_MM_APER		(1 << 31)
+#define RADEON_MPLL_CNTL                    0x000e /* PLL */
+#define RADEON_MPP_TB_CONFIG                0x01c0 /* ? */
+#define RADEON_MPP_GP_CONFIG                0x01c8 /* ? */
+#define RADEON_SEPROM_CNTL1                 0x01c0
+#       define RADEON_SCK_PRESCALE_SHIFT    24
+#       define RADEON_SCK_PRESCALE_MASK     (0xff << 24)
+#define R300_MC_IND_INDEX                   0x01f8
+#       define R300_MC_IND_ADDR_MASK        0x3f
+#       define R300_MC_IND_WR_EN            (1 << 8)
+#define R300_MC_IND_DATA                    0x01fc
+#define R300_MC_READ_CNTL_AB                0x017c
+#       define R300_MEM_RBS_POSITION_A_MASK 0x03
+#define R300_MC_READ_CNTL_CD_mcind	    0x24
+#       define R300_MEM_RBS_POSITION_C_MASK 0x03
+
+#define RADEON_N_VIF_COUNT                  0x0248
+
+#define RADEON_OV0_AUTO_FLIP_CNTL           0x0470
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_NUM        0x00000007
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_SOFT_REPEAT_FIELD   0x00000008
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD        0x00000010
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_IGNORE_REPEAT_FIELD 0x00000020
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE     0x00000040
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_VID_PORT_SELECT     0x00000300
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN  0x00010000
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN     0x00040000
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN      0x00080000
+#       define  RADEON_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE    0x00800000
+
+#define RADEON_OV0_COLOUR_CNTL              0x04E0
+#define RADEON_OV0_DEINTERLACE_PATTERN      0x0474
+#define RADEON_OV0_EXCLUSIVE_HORZ           0x0408
+#       define  RADEON_EXCL_HORZ_START_MASK        0x000000ff
+#       define  RADEON_EXCL_HORZ_END_MASK          0x0000ff00
+#       define  RADEON_EXCL_HORZ_BACK_PORCH_MASK   0x00ff0000
+#       define  RADEON_EXCL_HORZ_EXCLUSIVE_EN      0x80000000
+#define RADEON_OV0_EXCLUSIVE_VERT           0x040C
+#       define  RADEON_EXCL_VERT_START_MASK        0x000003ff
+#       define  RADEON_EXCL_VERT_END_MASK          0x03ff0000
+#define RADEON_OV0_FILTER_CNTL              0x04A0
+#       define RADEON_FILTER_PROGRAMMABLE_COEF            0x0
+#       define RADEON_FILTER_HC_COEF_HORZ_Y               0x1
+#       define RADEON_FILTER_HC_COEF_HORZ_UV              0x2
+#       define RADEON_FILTER_HC_COEF_VERT_Y               0x4
+#       define RADEON_FILTER_HC_COEF_VERT_UV              0x8
+#       define RADEON_FILTER_HARDCODED_COEF               0xf
+#       define RADEON_FILTER_COEF_MASK                    0xf
+
+#define RADEON_OV0_FOUR_TAP_COEF_0          0x04B0
+#define RADEON_OV0_FOUR_TAP_COEF_1          0x04B4
+#define RADEON_OV0_FOUR_TAP_COEF_2          0x04B8
+#define RADEON_OV0_FOUR_TAP_COEF_3          0x04BC
+#define RADEON_OV0_FOUR_TAP_COEF_4          0x04C0
+#define RADEON_OV0_FLAG_CNTL                0x04DC
+#define RADEON_OV0_GAMMA_000_00F            0x0d40
+#define RADEON_OV0_GAMMA_010_01F            0x0d44
+#define RADEON_OV0_GAMMA_020_03F            0x0d48
+#define RADEON_OV0_GAMMA_040_07F            0x0d4c
+#define RADEON_OV0_GAMMA_080_0BF            0x0e00
+#define RADEON_OV0_GAMMA_0C0_0FF            0x0e04
+#define RADEON_OV0_GAMMA_100_13F            0x0e08
+#define RADEON_OV0_GAMMA_140_17F            0x0e0c
+#define RADEON_OV0_GAMMA_180_1BF            0x0e10
+#define RADEON_OV0_GAMMA_1C0_1FF            0x0e14
+#define RADEON_OV0_GAMMA_200_23F            0x0e18
+#define RADEON_OV0_GAMMA_240_27F            0x0e1c
+#define RADEON_OV0_GAMMA_280_2BF            0x0e20
+#define RADEON_OV0_GAMMA_2C0_2FF            0x0e24
+#define RADEON_OV0_GAMMA_300_33F            0x0e28
+#define RADEON_OV0_GAMMA_340_37F            0x0e2c
+#define RADEON_OV0_GAMMA_380_3BF            0x0d50
+#define RADEON_OV0_GAMMA_3C0_3FF            0x0d54
+#define RADEON_OV0_GRAPHICS_KEY_CLR_LOW     0x04EC
+#define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH    0x04F0
+#define RADEON_OV0_H_INC                    0x0480
+#define RADEON_OV0_KEY_CNTL                 0x04F4
+#       define  RADEON_VIDEO_KEY_FN_MASK    0x00000003L
+#       define  RADEON_VIDEO_KEY_FN_FALSE   0x00000000L
+#       define  RADEON_VIDEO_KEY_FN_TRUE    0x00000001L
+#       define  RADEON_VIDEO_KEY_FN_EQ      0x00000002L
+#       define  RADEON_VIDEO_KEY_FN_NE      0x00000003L
+#       define  RADEON_GRAPHIC_KEY_FN_MASK  0x00000030L
+#       define  RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L
+#       define  RADEON_GRAPHIC_KEY_FN_TRUE  0x00000010L
+#       define  RADEON_GRAPHIC_KEY_FN_EQ    0x00000020L
+#       define  RADEON_GRAPHIC_KEY_FN_NE    0x00000030L
+#       define  RADEON_CMP_MIX_MASK         0x00000100L
+#       define  RADEON_CMP_MIX_OR           0x00000000L
+#       define  RADEON_CMP_MIX_AND          0x00000100L
+#define RADEON_OV0_LIN_TRANS_A              0x0d20
+#define RADEON_OV0_LIN_TRANS_B              0x0d24
+#define RADEON_OV0_LIN_TRANS_C              0x0d28
+#define RADEON_OV0_LIN_TRANS_D              0x0d2c
+#define RADEON_OV0_LIN_TRANS_E              0x0d30
+#define RADEON_OV0_LIN_TRANS_F              0x0d34
+#define RADEON_OV0_P1_BLANK_LINES_AT_TOP    0x0430
+#       define  RADEON_P1_BLNK_LN_AT_TOP_M1_MASK   0x00000fffL
+#       define  RADEON_P1_ACTIVE_LINES_M1          0x0fff0000L
+#define RADEON_OV0_P1_H_ACCUM_INIT          0x0488
+#define RADEON_OV0_P1_V_ACCUM_INIT          0x0428
+#       define  RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L
+#       define  RADEON_OV0_P1_V_ACCUM_INIT_MASK    0x01ff8000L
+#define RADEON_OV0_P1_X_START_END           0x0494
+#define RADEON_OV0_P2_X_START_END           0x0498
+#define RADEON_OV0_P23_BLANK_LINES_AT_TOP   0x0434
+#       define  RADEON_P23_BLNK_LN_AT_TOP_M1_MASK  0x000007ffL
+#       define  RADEON_P23_ACTIVE_LINES_M1         0x07ff0000L
+#define RADEON_OV0_P23_H_ACCUM_INIT         0x048C
+#define RADEON_OV0_P23_V_ACCUM_INIT         0x042C
+#define RADEON_OV0_P3_X_START_END           0x049C
+#define RADEON_OV0_REG_LOAD_CNTL            0x0410
+#       define  RADEON_REG_LD_CTL_LOCK                 0x00000001L
+#       define  RADEON_REG_LD_CTL_VBLANK_DURING_LOCK   0x00000002L
+#       define  RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L
+#       define  RADEON_REG_LD_CTL_LOCK_READBACK        0x00000008L
+#       define  RADEON_REG_LD_CTL_FLIP_READBACK        0x00000010L
+#define RADEON_OV0_SCALE_CNTL               0x0420
+#       define  RADEON_SCALER_HORZ_PICK_NEAREST    0x00000004L
+#       define  RADEON_SCALER_VERT_PICK_NEAREST    0x00000008L
+#       define  RADEON_SCALER_SIGNED_UV            0x00000010L
+#       define  RADEON_SCALER_GAMMA_SEL_MASK       0x00000060L
+#       define  RADEON_SCALER_GAMMA_SEL_BRIGHT     0x00000000L
+#       define  RADEON_SCALER_GAMMA_SEL_G22        0x00000020L
+#       define  RADEON_SCALER_GAMMA_SEL_G18        0x00000040L
+#       define  RADEON_SCALER_GAMMA_SEL_G14        0x00000060L
+#       define  RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L
+#       define  RADEON_SCALER_SURFAC_FORMAT        0x00000f00L
+#       define  RADEON_SCALER_SOURCE_15BPP         0x00000300L
+#       define  RADEON_SCALER_SOURCE_16BPP         0x00000400L
+#       define  RADEON_SCALER_SOURCE_32BPP         0x00000600L
+#       define  RADEON_SCALER_SOURCE_YUV9          0x00000900L
+#       define  RADEON_SCALER_SOURCE_YUV12         0x00000A00L
+#       define  RADEON_SCALER_SOURCE_VYUY422       0x00000B00L
+#       define  RADEON_SCALER_SOURCE_YVYU422       0x00000C00L
+#       define  RADEON_SCALER_ADAPTIVE_DEINT       0x00001000L
+#       define  RADEON_SCALER_TEMPORAL_DEINT       0x00002000L
+#       define  RADEON_SCALER_CRTC_SEL             0x00004000L
+#       define  RADEON_SCALER_SMART_SWITCH         0x00008000L
+#       define  RADEON_SCALER_BURST_PER_PLANE      0x007F0000L
+#       define  RADEON_SCALER_DOUBLE_BUFFER        0x01000000L
+#       define  RADEON_SCALER_DIS_LIMIT            0x08000000L
+#       define  RADEON_SCALER_LIN_TRANS_BYPASS     0x10000000L
+#       define  RADEON_SCALER_INT_EMU              0x20000000L
+#       define  RADEON_SCALER_ENABLE               0x40000000L
+#       define  RADEON_SCALER_SOFT_RESET           0x80000000L
+#define RADEON_OV0_STEP_BY                  0x0484
+#define RADEON_OV0_TEST                     0x04F8
+#define RADEON_OV0_V_INC                    0x0424
+#define RADEON_OV0_VID_BUF_PITCH0_VALUE     0x0460
+#define RADEON_OV0_VID_BUF_PITCH1_VALUE     0x0464
+#define RADEON_OV0_VID_BUF0_BASE_ADRS       0x0440
+#       define  RADEON_VIF_BUF0_PITCH_SEL          0x00000001L
+#       define  RADEON_VIF_BUF0_TILE_ADRS          0x00000002L
+#       define  RADEON_VIF_BUF0_BASE_ADRS_MASK     0x03fffff0L
+#       define  RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L
+#define RADEON_OV0_VID_BUF1_BASE_ADRS       0x0444
+#       define  RADEON_VIF_BUF1_PITCH_SEL          0x00000001L
+#       define  RADEON_VIF_BUF1_TILE_ADRS          0x00000002L
+#       define  RADEON_VIF_BUF1_BASE_ADRS_MASK     0x03fffff0L
+#       define  RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L
+#define RADEON_OV0_VID_BUF2_BASE_ADRS       0x0448
+#       define  RADEON_VIF_BUF2_PITCH_SEL          0x00000001L
+#       define  RADEON_VIF_BUF2_TILE_ADRS          0x00000002L
+#       define  RADEON_VIF_BUF2_BASE_ADRS_MASK     0x03fffff0L
+#       define  RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L
+#define RADEON_OV0_VID_BUF3_BASE_ADRS       0x044C
+#define RADEON_OV0_VID_BUF4_BASE_ADRS       0x0450
+#define RADEON_OV0_VID_BUF5_BASE_ADRS       0x0454
+#define RADEON_OV0_VIDEO_KEY_CLR_HIGH       0x04E8
+#define RADEON_OV0_VIDEO_KEY_CLR_LOW        0x04E4
+#define RADEON_OV0_Y_X_START                0x0400
+#define RADEON_OV0_Y_X_END                  0x0404
+#define RADEON_OV1_Y_X_START                0x0600
+#define RADEON_OV1_Y_X_END                  0x0604
+#define RADEON_OVR_CLR                      0x0230
+#define RADEON_OVR_WID_LEFT_RIGHT           0x0234
+#define RADEON_OVR_WID_TOP_BOTTOM           0x0238
+
+/* first capture unit */
+
+#define RADEON_CAP0_BUF0_OFFSET           0x0920
+#define RADEON_CAP0_BUF1_OFFSET           0x0924
+#define RADEON_CAP0_BUF0_EVEN_OFFSET      0x0928
+#define RADEON_CAP0_BUF1_EVEN_OFFSET      0x092C
+
+#define RADEON_CAP0_BUF_PITCH             0x0930
+#define RADEON_CAP0_V_WINDOW              0x0934
+#define RADEON_CAP0_H_WINDOW              0x0938
+#define RADEON_CAP0_VBI0_OFFSET           0x093C
+#define RADEON_CAP0_VBI1_OFFSET           0x0940
+#define RADEON_CAP0_VBI_V_WINDOW          0x0944
+#define RADEON_CAP0_VBI_H_WINDOW          0x0948
+#define RADEON_CAP0_PORT_MODE_CNTL        0x094C
+#define RADEON_CAP0_TRIG_CNTL             0x0950
+#define RADEON_CAP0_DEBUG                 0x0954
+#define RADEON_CAP0_CONFIG                0x0958
+#       define RADEON_CAP0_CONFIG_CONTINUOS          0x00000001
+#       define RADEON_CAP0_CONFIG_START_FIELD_EVEN   0x00000002
+#       define RADEON_CAP0_CONFIG_START_BUF_GET      0x00000004
+#       define RADEON_CAP0_CONFIG_START_BUF_SET      0x00000008
+#       define RADEON_CAP0_CONFIG_BUF_TYPE_ALT       0x00000010
+#       define RADEON_CAP0_CONFIG_BUF_TYPE_FRAME     0x00000020
+#       define RADEON_CAP0_CONFIG_ONESHOT_MODE_FRAME 0x00000040
+#       define RADEON_CAP0_CONFIG_BUF_MODE_DOUBLE    0x00000080
+#       define RADEON_CAP0_CONFIG_BUF_MODE_TRIPLE    0x00000100
+#       define RADEON_CAP0_CONFIG_MIRROR_EN          0x00000200
+#       define RADEON_CAP0_CONFIG_ONESHOT_MIRROR_EN  0x00000400
+#       define RADEON_CAP0_CONFIG_VIDEO_SIGNED_UV    0x00000800
+#       define RADEON_CAP0_CONFIG_ANC_DECODE_EN      0x00001000
+#       define RADEON_CAP0_CONFIG_VBI_EN             0x00002000
+#       define RADEON_CAP0_CONFIG_SOFT_PULL_DOWN_EN  0x00004000
+#       define RADEON_CAP0_CONFIG_VIP_EXTEND_FLAG_EN 0x00008000
+#       define RADEON_CAP0_CONFIG_FAKE_FIELD_EN      0x00010000
+#       define RADEON_CAP0_CONFIG_ODD_ONE_MORE_LINE  0x00020000
+#       define RADEON_CAP0_CONFIG_EVEN_ONE_MORE_LINE 0x00040000
+#       define RADEON_CAP0_CONFIG_HORZ_DIVIDE_2      0x00080000
+#       define RADEON_CAP0_CONFIG_HORZ_DIVIDE_4      0x00100000
+#       define RADEON_CAP0_CONFIG_VERT_DIVIDE_2      0x00200000
+#       define RADEON_CAP0_CONFIG_VERT_DIVIDE_4      0x00400000
+#       define RADEON_CAP0_CONFIG_FORMAT_BROOKTREE   0x00000000
+#       define RADEON_CAP0_CONFIG_FORMAT_CCIR656     0x00800000
+#       define RADEON_CAP0_CONFIG_FORMAT_ZV          0x01000000
+#       define RADEON_CAP0_CONFIG_FORMAT_VIP         0x01800000
+#       define RADEON_CAP0_CONFIG_FORMAT_TRANSPORT   0x02000000
+#       define RADEON_CAP0_CONFIG_HORZ_DECIMATOR     0x04000000
+#       define RADEON_CAP0_CONFIG_VIDEO_IN_YVYU422   0x00000000
+#       define RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422   0x20000000
+#       define RADEON_CAP0_CONFIG_VBI_DIVIDE_2       0x40000000
+#       define RADEON_CAP0_CONFIG_VBI_DIVIDE_4       0x80000000
+#define RADEON_CAP0_ANC_ODD_OFFSET        0x095C
+#define RADEON_CAP0_ANC_EVEN_OFFSET       0x0960
+#define RADEON_CAP0_ANC_H_WINDOW          0x0964
+#define RADEON_CAP0_VIDEO_SYNC_TEST       0x0968
+#define RADEON_CAP0_ONESHOT_BUF_OFFSET    0x096C
+#define RADEON_CAP0_BUF_STATUS            0x0970
+/* #define RADEON_CAP0_DWNSC_XRATIO       0x0978 */
+/* #define RADEON_CAP0_XSHARPNESS                 0x097C */
+#define RADEON_CAP0_VBI2_OFFSET           0x0980
+#define RADEON_CAP0_VBI3_OFFSET           0x0984
+#define RADEON_CAP0_ANC2_OFFSET           0x0988
+#define RADEON_CAP0_ANC3_OFFSET           0x098C
+#define RADEON_VID_BUFFER_CONTROL         0x0900
+
+/* second capture unit */
+
+#define RADEON_CAP1_BUF0_OFFSET           0x0990
+#define RADEON_CAP1_BUF1_OFFSET           0x0994
+#define RADEON_CAP1_BUF0_EVEN_OFFSET      0x0998
+#define RADEON_CAP1_BUF1_EVEN_OFFSET      0x099C
+
+#define RADEON_CAP1_BUF_PITCH             0x09A0
+#define RADEON_CAP1_V_WINDOW              0x09A4
+#define RADEON_CAP1_H_WINDOW              0x09A8
+#define RADEON_CAP1_VBI_ODD_OFFSET        0x09AC
+#define RADEON_CAP1_VBI_EVEN_OFFSET       0x09B0
+#define RADEON_CAP1_VBI_V_WINDOW                  0x09B4
+#define RADEON_CAP1_VBI_H_WINDOW                  0x09B8
+#define RADEON_CAP1_PORT_MODE_CNTL        0x09BC
+#define RADEON_CAP1_TRIG_CNTL             0x09C0
+#define RADEON_CAP1_DEBUG                         0x09C4
+#define RADEON_CAP1_CONFIG                0x09C8
+#define RADEON_CAP1_ANC_ODD_OFFSET        0x09CC
+#define RADEON_CAP1_ANC_EVEN_OFFSET       0x09D0
+#define RADEON_CAP1_ANC_H_WINDOW                  0x09D4
+#define RADEON_CAP1_VIDEO_SYNC_TEST       0x09D8
+#define RADEON_CAP1_ONESHOT_BUF_OFFSET    0x09DC
+#define RADEON_CAP1_BUF_STATUS            0x09E0
+#define RADEON_CAP1_DWNSC_XRATIO                  0x09E8
+#define RADEON_CAP1_XSHARPNESS            0x09EC
+
+/* misc multimedia registers */
+
+#define RADEON_IDCT_RUNS                  0x1F80
+#define RADEON_IDCT_LEVELS                0x1F84
+#define RADEON_IDCT_CONTROL               0x1FBC
+#define RADEON_IDCT_AUTH_CONTROL          0x1F88
+#define RADEON_IDCT_AUTH                  0x1F8C
+
+#define RADEON_P2PLL_CNTL                   0x002a /* P2PLL */
+#       define RADEON_P2PLL_RESET                (1 <<  0)
+#       define RADEON_P2PLL_SLEEP                (1 <<  1)
+#       define RADEON_P2PLL_PVG_MASK             (7 << 11)
+#       define RADEON_P2PLL_PVG_SHIFT            11
+#       define RADEON_P2PLL_ATOMIC_UPDATE_EN     (1 << 16)
+#       define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+#       define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC  (1 << 18)
+#define RADEON_P2PLL_DIV_0                  0x002c
+#       define RADEON_P2PLL_FB0_DIV_MASK    0x07ff
+#       define RADEON_P2PLL_POST0_DIV_MASK  0x00070000
+#define RADEON_P2PLL_REF_DIV                0x002B /* PLL */
+#       define RADEON_P2PLL_REF_DIV_MASK    0x03ff
+#       define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */
+#       define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */
+#       define R300_PPLL_REF_DIV_ACC_MASK   (0x3ff << 18)
+#       define R300_PPLL_REF_DIV_ACC_SHIFT  18
+#define RADEON_PALETTE_DATA                 0x00b4
+#define RADEON_PALETTE_30_DATA              0x00b8
+#define RADEON_PALETTE_INDEX                0x00b0
+#define RADEON_PCI_GART_PAGE                0x017c
+#define RADEON_PIXCLKS_CNTL                 0x002d
+#       define RADEON_PIX2CLK_SRC_SEL_MASK     0x03
+#       define RADEON_PIX2CLK_SRC_SEL_CPUCLK   0x00
+#       define RADEON_PIX2CLK_SRC_SEL_PSCANCLK 0x01
+#       define RADEON_PIX2CLK_SRC_SEL_BYTECLK  0x02
+#       define RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 0x03
+#       define RADEON_PIX2CLK_ALWAYS_ONb       (1<<6)
+#       define RADEON_PIX2CLK_DAC_ALWAYS_ONb   (1<<7)
+#       define RADEON_PIXCLK_TV_SRC_SEL        (1 << 8)
+#       define RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb (1 << 9)
+#       define R300_DVOCLK_ALWAYS_ONb          (1 << 10)
+#       define RADEON_PIXCLK_BLEND_ALWAYS_ONb  (1 << 11)
+#       define RADEON_PIXCLK_GV_ALWAYS_ONb     (1 << 12)
+#       define RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb (1 << 13)
+#       define R300_PIXCLK_DVO_ALWAYS_ONb      (1 << 13)
+#       define RADEON_PIXCLK_LVDS_ALWAYS_ONb   (1 << 14)
+#       define RADEON_PIXCLK_TMDS_ALWAYS_ONb   (1 << 15)
+#       define R300_PIXCLK_TRANS_ALWAYS_ONb    (1 << 16)
+#       define R300_PIXCLK_TVO_ALWAYS_ONb      (1 << 17)
+#       define R300_P2G2CLK_ALWAYS_ONb         (1 << 18)
+#       define R300_P2G2CLK_DAC_ALWAYS_ONb     (1 << 19)
+#       define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23)
+#define RADEON_PLANE_3D_MASK_C              0x1d44
+#define RADEON_PLL_TEST_CNTL                0x0013 /* PLL */
+#       define RADEON_PLL_MASK_READ_B          (1 << 9)
+#define RADEON_PMI_CAP_ID                   0x0f5c /* PCI */
+#define RADEON_PMI_DATA                     0x0f63 /* PCI */
+#define RADEON_PMI_NXT_CAP_PTR              0x0f5d /* PCI */
+#define RADEON_PMI_PMC_REG                  0x0f5e /* PCI */
+#define RADEON_PMI_PMCSR_REG                0x0f60 /* PCI */
+#define RADEON_PMI_REGISTER                 0x0f5c /* PCI */
+#define RADEON_PPLL_CNTL                    0x0002 /* PLL */
+#       define RADEON_PPLL_RESET                (1 <<  0)
+#       define RADEON_PPLL_SLEEP                (1 <<  1)
+#       define RADEON_PPLL_PVG_MASK             (7 << 11)
+#       define RADEON_PPLL_PVG_SHIFT            11
+#       define RADEON_PPLL_ATOMIC_UPDATE_EN     (1 << 16)
+#       define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+#       define RADEON_PPLL_ATOMIC_UPDATE_VSYNC  (1 << 18)
+#define RADEON_PPLL_DIV_0                   0x0004 /* PLL */
+#define RADEON_PPLL_DIV_1                   0x0005 /* PLL */
+#define RADEON_PPLL_DIV_2                   0x0006 /* PLL */
+#define RADEON_PPLL_DIV_3                   0x0007 /* PLL */
+#       define RADEON_PPLL_FB3_DIV_MASK     0x07ff
+#       define RADEON_PPLL_POST3_DIV_MASK   0x00070000
+#define RADEON_PPLL_REF_DIV                 0x0003 /* PLL */
+#       define RADEON_PPLL_REF_DIV_MASK     0x03ff
+#       define RADEON_PPLL_ATOMIC_UPDATE_R  (1 << 15) /* same as _W */
+#       define RADEON_PPLL_ATOMIC_UPDATE_W  (1 << 15) /* same as _R */
+#define RADEON_PWR_MNGMT_CNTL_STATUS        0x0f60 /* PCI */
+
+#define RADEON_RBBM_GUICNTL                 0x172c
+#       define RADEON_HOST_DATA_SWAP_NONE   (0 << 0)
+#       define RADEON_HOST_DATA_SWAP_16BIT  (1 << 0)
+#       define RADEON_HOST_DATA_SWAP_32BIT  (2 << 0)
+#       define RADEON_HOST_DATA_SWAP_HDW    (3 << 0)
+#define RADEON_RBBM_SOFT_RESET              0x00f0
+#       define RADEON_SOFT_RESET_CP         (1 <<  0)
+#       define RADEON_SOFT_RESET_HI         (1 <<  1)
+#       define RADEON_SOFT_RESET_SE         (1 <<  2)
+#       define RADEON_SOFT_RESET_RE         (1 <<  3)
+#       define RADEON_SOFT_RESET_PP         (1 <<  4)
+#       define RADEON_SOFT_RESET_E2         (1 <<  5)
+#       define RADEON_SOFT_RESET_RB         (1 <<  6)
+#       define RADEON_SOFT_RESET_HDP        (1 <<  7)
+#define RADEON_RBBM_STATUS                  0x0e40
+#       define RADEON_RBBM_FIFOCNT_MASK     0x007f
+#       define RADEON_RBBM_ACTIVE           (1 << 31)
+#define RADEON_RB2D_DSTCACHE_CTLSTAT        0x342c
+#       define RADEON_RB2D_DC_FLUSH         (3 << 0)
+#       define RADEON_RB2D_DC_FREE          (3 << 2)
+#       define RADEON_RB2D_DC_FLUSH_ALL     0xf
+#       define RADEON_RB2D_DC_BUSY          (1 << 31)
+#define RADEON_RB2D_DSTCACHE_MODE           0x3428
+#define RADEON_DSTCACHE_CTLSTAT             0x1714
+
+#define RADEON_RB3D_ZCACHE_MODE             0x3250
+#define RADEON_RB3D_ZCACHE_CTLSTAT          0x3254
+#       define RADEON_RB3D_ZC_FLUSH_ALL     0x5
+#define RADEON_RB3D_DSTCACHE_MODE           0x3258
+# define RADEON_RB3D_DC_CACHE_ENABLE            (0)
+# define RADEON_RB3D_DC_2D_CACHE_DISABLE        (1)
+# define RADEON_RB3D_DC_3D_CACHE_DISABLE        (2)
+# define RADEON_RB3D_DC_CACHE_DISABLE           (3)
+# define RADEON_RB3D_DC_2D_CACHE_LINESIZE_128   (1 << 2)
+# define RADEON_RB3D_DC_3D_CACHE_LINESIZE_128   (2 << 2)
+# define RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH      (1 << 8)
+# define RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH      (2 << 8)
+# define R200_RB3D_DC_2D_CACHE_AUTOFREE         (1 << 10)
+# define R200_RB3D_DC_3D_CACHE_AUTOFREE         (2 << 10)
+# define RADEON_RB3D_DC_FORCE_RMW               (1 << 16)
+# define RADEON_RB3D_DC_DISABLE_RI_FILL         (1 << 24)
+# define RADEON_RB3D_DC_DISABLE_RI_READ         (1 << 25)
+
+#define RADEON_RB3D_DSTCACHE_CTLSTAT            0x325C
+# define RADEON_RB3D_DC_FLUSH                   (3 << 0)
+# define RADEON_RB3D_DC_FREE                    (3 << 2)
+# define RADEON_RB3D_DC_FLUSH_ALL               0xf
+# define RADEON_RB3D_DC_BUSY                    (1 << 31)
+
+#define RADEON_REG_BASE                     0x0f18 /* PCI */
+#define RADEON_REGPROG_INF                  0x0f09 /* PCI */
+#define RADEON_REVISION_ID                  0x0f08 /* PCI */
+
+#define RADEON_SC_BOTTOM                    0x164c
+#define RADEON_SC_BOTTOM_RIGHT              0x16f0
+#define RADEON_SC_BOTTOM_RIGHT_C            0x1c8c
+#define RADEON_SC_LEFT                      0x1640
+#define RADEON_SC_RIGHT                     0x1644
+#define RADEON_SC_TOP                       0x1648
+#define RADEON_SC_TOP_LEFT                  0x16ec
+#define RADEON_SC_TOP_LEFT_C                0x1c88
+#       define RADEON_SC_SIGN_MASK_LO       0x8000
+#       define RADEON_SC_SIGN_MASK_HI       0x80000000
+#define RADEON_M_SPLL_REF_FB_DIV            0x000a /* PLL */
+#	define RADEON_M_SPLL_REF_DIV_SHIFT  0
+#	define RADEON_M_SPLL_REF_DIV_MASK   0xff
+#	define RADEON_MPLL_FB_DIV_SHIFT     8
+#	define RADEON_MPLL_FB_DIV_MASK      0xff
+#	define RADEON_SPLL_FB_DIV_SHIFT     16
+#	define RADEON_SPLL_FB_DIV_MASK      0xff
+#define RADEON_SPLL_CNTL                    0x000c /* PLL */
+#       define RADEON_SPLL_SLEEP            (1 << 0)
+#       define RADEON_SPLL_RESET            (1 << 1)
+#       define RADEON_SPLL_PCP_MASK         0x7
+#       define RADEON_SPLL_PCP_SHIFT        8
+#       define RADEON_SPLL_PVG_MASK         0x7
+#       define RADEON_SPLL_PVG_SHIFT        11
+#       define RADEON_SPLL_PDC_MASK         0x3
+#       define RADEON_SPLL_PDC_SHIFT        14
+#define RADEON_SCLK_CNTL                    0x000d /* PLL */
+#       define RADEON_SCLK_SRC_SEL_MASK     0x0007
+#       define RADEON_DYN_STOP_LAT_MASK     0x00007ff8
+#       define RADEON_CP_MAX_DYN_STOP_LAT   0x0008
+#       define RADEON_SCLK_FORCEON_MASK     0xffff8000
+#       define RADEON_SCLK_FORCE_DISP2      (1<<15)
+#       define RADEON_SCLK_FORCE_CP         (1<<16)
+#       define RADEON_SCLK_FORCE_HDP        (1<<17)
+#       define RADEON_SCLK_FORCE_DISP1      (1<<18)
+#       define RADEON_SCLK_FORCE_TOP        (1<<19)
+#       define RADEON_SCLK_FORCE_E2         (1<<20)
+#       define RADEON_SCLK_FORCE_SE         (1<<21)
+#       define RADEON_SCLK_FORCE_IDCT       (1<<22)
+#       define RADEON_SCLK_FORCE_VIP        (1<<23)
+#       define RADEON_SCLK_FORCE_RE         (1<<24)
+#       define RADEON_SCLK_FORCE_PB         (1<<25)
+#       define RADEON_SCLK_FORCE_TAM        (1<<26)
+#       define RADEON_SCLK_FORCE_TDM        (1<<27)
+#       define RADEON_SCLK_FORCE_RB         (1<<28)
+#       define RADEON_SCLK_FORCE_TV_SCLK    (1<<29)
+#       define RADEON_SCLK_FORCE_SUBPIC     (1<<30)
+#       define RADEON_SCLK_FORCE_OV0        (1<<31)
+#       define R300_SCLK_FORCE_VAP          (1<<21)
+#       define R300_SCLK_FORCE_SR           (1<<25)
+#       define R300_SCLK_FORCE_PX           (1<<26)
+#       define R300_SCLK_FORCE_TX           (1<<27)
+#       define R300_SCLK_FORCE_US           (1<<28)
+#       define R300_SCLK_FORCE_SU           (1<<30)
+#define R300_SCLK_CNTL2                     0x1e   /* PLL */
+#       define R300_SCLK_TCL_MAX_DYN_STOP_LAT (1<<10)
+#       define R300_SCLK_GA_MAX_DYN_STOP_LAT  (1<<11)
+#       define R300_SCLK_CBA_MAX_DYN_STOP_LAT (1<<12)
+#       define R300_SCLK_FORCE_TCL          (1<<13)
+#       define R300_SCLK_FORCE_CBA          (1<<14)
+#       define R300_SCLK_FORCE_GA           (1<<15)
+#define RADEON_SCLK_MORE_CNTL               0x0035 /* PLL */
+#       define RADEON_SCLK_MORE_MAX_DYN_STOP_LAT 0x0007
+#       define RADEON_SCLK_MORE_FORCEON     0x0700
+#define RADEON_SDRAM_MODE_REG               0x0158
+#define RADEON_SEQ8_DATA                    0x03c5 /* VGA */
+#define RADEON_SEQ8_IDX                     0x03c4 /* VGA */
+#define RADEON_SNAPSHOT_F_COUNT             0x0244
+#define RADEON_SNAPSHOT_VH_COUNTS           0x0240
+#define RADEON_SNAPSHOT_VIF_COUNT           0x024c
+#define RADEON_SRC_OFFSET                   0x15ac
+#define RADEON_SRC_PITCH                    0x15b0
+#define RADEON_SRC_PITCH_OFFSET             0x1428
+#define RADEON_SRC_SC_BOTTOM                0x165c
+#define RADEON_SRC_SC_BOTTOM_RIGHT          0x16f4
+#define RADEON_SRC_SC_RIGHT                 0x1654
+#define RADEON_SRC_X                        0x1414
+#define RADEON_SRC_X_Y                      0x1590
+#define RADEON_SRC_Y                        0x1418
+#define RADEON_SRC_Y_X                      0x1434
+#define RADEON_STATUS                       0x0f06 /* PCI */
+#define RADEON_SUBPIC_CNTL                  0x0540 /* ? */
+#define RADEON_SUB_CLASS                    0x0f0a /* PCI */
+#define RADEON_SURFACE_CNTL                 0x0b00
+#       define RADEON_SURF_TRANSLATION_DIS  (1 << 8)
+#       define RADEON_NONSURF_AP0_SWP_16BPP (1 << 20)
+#       define RADEON_NONSURF_AP0_SWP_32BPP (1 << 21)
+#       define RADEON_NONSURF_AP1_SWP_16BPP (1 << 22)
+#       define RADEON_NONSURF_AP1_SWP_32BPP (1 << 23)
+#define RADEON_SURFACE0_INFO                0x0b0c
+#       define RADEON_SURF_TILE_COLOR_MACRO (0 << 16)
+#       define RADEON_SURF_TILE_COLOR_BOTH  (1 << 16)
+#       define RADEON_SURF_TILE_DEPTH_32BPP (2 << 16)
+#       define RADEON_SURF_TILE_DEPTH_16BPP (3 << 16)
+#       define R200_SURF_TILE_NONE          (0 << 16)
+#       define R200_SURF_TILE_COLOR_MACRO   (1 << 16)
+#       define R200_SURF_TILE_COLOR_MICRO   (2 << 16)
+#       define R200_SURF_TILE_COLOR_BOTH    (3 << 16)
+#       define R200_SURF_TILE_DEPTH_32BPP   (4 << 16)
+#       define R200_SURF_TILE_DEPTH_16BPP   (5 << 16)
+#       define R300_SURF_TILE_NONE          (0 << 16)
+#       define R300_SURF_TILE_COLOR_MACRO   (1 << 16)
+#       define R300_SURF_TILE_DEPTH_32BPP   (2 << 16)
+#       define RADEON_SURF_AP0_SWP_16BPP    (1 << 20)
+#       define RADEON_SURF_AP0_SWP_32BPP    (1 << 21)
+#       define RADEON_SURF_AP1_SWP_16BPP    (1 << 22)
+#       define RADEON_SURF_AP1_SWP_32BPP    (1 << 23)
+#define RADEON_SURFACE0_LOWER_BOUND         0x0b04
+#define RADEON_SURFACE0_UPPER_BOUND         0x0b08
+#define RADEON_SURFACE1_INFO                0x0b1c
+#define RADEON_SURFACE1_LOWER_BOUND         0x0b14
+#define RADEON_SURFACE1_UPPER_BOUND         0x0b18
+#define RADEON_SURFACE2_INFO                0x0b2c
+#define RADEON_SURFACE2_LOWER_BOUND         0x0b24
+#define RADEON_SURFACE2_UPPER_BOUND         0x0b28
+#define RADEON_SURFACE3_INFO                0x0b3c
+#define RADEON_SURFACE3_LOWER_BOUND         0x0b34
+#define RADEON_SURFACE3_UPPER_BOUND         0x0b38
+#define RADEON_SURFACE4_INFO                0x0b4c
+#define RADEON_SURFACE4_LOWER_BOUND         0x0b44
+#define RADEON_SURFACE4_UPPER_BOUND         0x0b48
+#define RADEON_SURFACE5_INFO                0x0b5c
+#define RADEON_SURFACE5_LOWER_BOUND         0x0b54
+#define RADEON_SURFACE5_UPPER_BOUND         0x0b58
+#define RADEON_SURFACE6_INFO                0x0b6c
+#define RADEON_SURFACE6_LOWER_BOUND         0x0b64
+#define RADEON_SURFACE6_UPPER_BOUND         0x0b68
+#define RADEON_SURFACE7_INFO                0x0b7c
+#define RADEON_SURFACE7_LOWER_BOUND         0x0b74
+#define RADEON_SURFACE7_UPPER_BOUND         0x0b78
+#define RADEON_SW_SEMAPHORE                 0x013c
+
+#define RADEON_TEST_DEBUG_CNTL              0x0120
+#define RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN 0x00000001
+
+#define RADEON_TEST_DEBUG_MUX               0x0124
+#define RADEON_TEST_DEBUG_OUT               0x012c
+#define RADEON_TMDS_PLL_CNTL                0x02a8
+#define RADEON_TMDS_TRANSMITTER_CNTL        0x02a4
+#       define RADEON_TMDS_TRANSMITTER_PLLEN  1
+#       define RADEON_TMDS_TRANSMITTER_PLLRST 2
+#define RADEON_TRAIL_BRES_DEC               0x1614
+#define RADEON_TRAIL_BRES_ERR               0x160c
+#define RADEON_TRAIL_BRES_INC               0x1610
+#define RADEON_TRAIL_X                      0x1618
+#define RADEON_TRAIL_X_SUB                  0x1620
+
+#define RADEON_VCLK_ECP_CNTL                0x0008 /* PLL */
+#       define RADEON_VCLK_SRC_SEL_MASK     0x03
+#       define RADEON_VCLK_SRC_SEL_CPUCLK   0x00
+#       define RADEON_VCLK_SRC_SEL_PSCANCLK 0x01
+#       define RADEON_VCLK_SRC_SEL_BYTECLK  0x02
+#       define RADEON_VCLK_SRC_SEL_PPLLCLK  0x03
+#       define RADEON_PIXCLK_ALWAYS_ONb     (1<<6)
+#       define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7)
+#       define R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF (1<<23)
+
+#define RADEON_VENDOR_ID                    0x0f00 /* PCI */
+#define RADEON_VGA_DDA_CONFIG               0x02e8
+#define RADEON_VGA_DDA_ON_OFF               0x02ec
+#define RADEON_VID_BUFFER_CONTROL           0x0900
+#define RADEON_VIDEOMUX_CNTL                0x0190
+
+/* VIP bus */
+#define RADEON_VIPH_CH0_DATA                0x0c00
+#define RADEON_VIPH_CH1_DATA                0x0c04
+#define RADEON_VIPH_CH2_DATA                0x0c08
+#define RADEON_VIPH_CH3_DATA                0x0c0c
+#define RADEON_VIPH_CH0_ADDR                0x0c10
+#define RADEON_VIPH_CH1_ADDR                0x0c14
+#define RADEON_VIPH_CH2_ADDR                0x0c18
+#define RADEON_VIPH_CH3_ADDR                0x0c1c
+#define RADEON_VIPH_CH0_SBCNT               0x0c20
+#define RADEON_VIPH_CH1_SBCNT               0x0c24
+#define RADEON_VIPH_CH2_SBCNT               0x0c28
+#define RADEON_VIPH_CH3_SBCNT               0x0c2c
+#define RADEON_VIPH_CH0_ABCNT               0x0c30
+#define RADEON_VIPH_CH1_ABCNT               0x0c34
+#define RADEON_VIPH_CH2_ABCNT               0x0c38
+#define RADEON_VIPH_CH3_ABCNT               0x0c3c
+#define RADEON_VIPH_CONTROL                 0x0c40
+#       define RADEON_VIP_BUSY 0
+#       define RADEON_VIP_IDLE 1
+#       define RADEON_VIP_RESET 2
+#       define RADEON_VIPH_EN               (1 << 21)
+#define RADEON_VIPH_DV_LAT                  0x0c44
+#define RADEON_VIPH_BM_CHUNK                0x0c48
+#define RADEON_VIPH_DV_INT                  0x0c4c
+#define RADEON_VIPH_TIMEOUT_STAT            0x0c50
+#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010
+#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK   0x00000010
+#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000
+
+#define RADEON_VIPH_REG_DATA                0x0084
+#define RADEON_VIPH_REG_ADDR                0x0080
+
+
+#define RADEON_WAIT_UNTIL                   0x1720
+#       define RADEON_WAIT_CRTC_PFLIP       (1 << 0)
+#       define RADEON_WAIT_RE_CRTC_VLINE    (1 << 1)
+#       define RADEON_WAIT_FE_CRTC_VLINE    (1 << 2)
+#       define RADEON_WAIT_CRTC_VLINE       (1 << 3)
+#       define RADEON_WAIT_DMA_VID_IDLE     (1 << 8)
+#       define RADEON_WAIT_DMA_GUI_IDLE     (1 << 9)
+#       define RADEON_WAIT_CMDFIFO          (1 << 10) /* wait for CMDFIFO_ENTRIES */
+#       define RADEON_WAIT_OV0_FLIP         (1 << 11)
+#       define RADEON_WAIT_AGP_FLUSH        (1 << 13)
+#       define RADEON_WAIT_2D_IDLE          (1 << 14)
+#       define RADEON_WAIT_3D_IDLE          (1 << 15)
+#       define RADEON_WAIT_2D_IDLECLEAN     (1 << 16)
+#       define RADEON_WAIT_3D_IDLECLEAN     (1 << 17)
+#       define RADEON_WAIT_HOST_IDLECLEAN   (1 << 18)
+#       define RADEON_CMDFIFO_ENTRIES_SHIFT 10
+#       define RADEON_CMDFIFO_ENTRIES_MASK  0x7f
+#       define RADEON_WAIT_VAP_IDLE         (1 << 28)
+#       define RADEON_WAIT_BOTH_CRTC_PFLIP  (1 << 30)
+#       define RADEON_ENG_DISPLAY_SELECT_CRTC0    (0 << 31)
+#       define RADEON_ENG_DISPLAY_SELECT_CRTC1    (1 << 31)
+
+#define RADEON_X_MPLL_REF_FB_DIV            0x000a /* PLL */
+#define RADEON_XCLK_CNTL                    0x000d /* PLL */
+#define RADEON_XDLL_CNTL                    0x000c /* PLL */
+#define RADEON_XPLL_CNTL                    0x000b /* PLL */
+
+
+
+				/* Registers for 3D/TCL */
+#define RADEON_PP_BORDER_COLOR_0            0x1d40
+#define RADEON_PP_BORDER_COLOR_1            0x1d44
+#define RADEON_PP_BORDER_COLOR_2            0x1d48
+#define RADEON_PP_CNTL                      0x1c38
+#       define RADEON_STIPPLE_ENABLE        (1 <<  0)
+#       define RADEON_SCISSOR_ENABLE        (1 <<  1)
+#       define RADEON_PATTERN_ENABLE        (1 <<  2)
+#       define RADEON_SHADOW_ENABLE         (1 <<  3)
+#       define RADEON_TEX_ENABLE_MASK       (0xf << 4)
+#       define RADEON_TEX_0_ENABLE          (1 <<  4)
+#       define RADEON_TEX_1_ENABLE          (1 <<  5)
+#       define RADEON_TEX_2_ENABLE          (1 <<  6)
+#       define RADEON_TEX_3_ENABLE          (1 <<  7)
+#       define RADEON_TEX_BLEND_ENABLE_MASK (0xf << 12)
+#       define RADEON_TEX_BLEND_0_ENABLE    (1 << 12)
+#       define RADEON_TEX_BLEND_1_ENABLE    (1 << 13)
+#       define RADEON_TEX_BLEND_2_ENABLE    (1 << 14)
+#       define RADEON_TEX_BLEND_3_ENABLE    (1 << 15)
+#       define RADEON_PLANAR_YUV_ENABLE     (1 << 20)
+#       define RADEON_SPECULAR_ENABLE       (1 << 21)
+#       define RADEON_FOG_ENABLE            (1 << 22)
+#       define RADEON_ALPHA_TEST_ENABLE     (1 << 23)
+#       define RADEON_ANTI_ALIAS_NONE       (0 << 24)
+#       define RADEON_ANTI_ALIAS_LINE       (1 << 24)
+#       define RADEON_ANTI_ALIAS_POLY       (2 << 24)
+#       define RADEON_ANTI_ALIAS_LINE_POLY  (3 << 24)
+#       define RADEON_BUMP_MAP_ENABLE       (1 << 26)
+#       define RADEON_BUMPED_MAP_T0         (0 << 27)
+#       define RADEON_BUMPED_MAP_T1         (1 << 27)
+#       define RADEON_BUMPED_MAP_T2         (2 << 27)
+#       define RADEON_TEX_3D_ENABLE_0       (1 << 29)
+#       define RADEON_TEX_3D_ENABLE_1       (1 << 30)
+#       define RADEON_MC_ENABLE             (1 << 31)
+#define RADEON_PP_FOG_COLOR                 0x1c18
+#       define RADEON_FOG_COLOR_MASK        0x00ffffff
+#       define RADEON_FOG_VERTEX            (0 << 24)
+#       define RADEON_FOG_TABLE             (1 << 24)
+#       define RADEON_FOG_USE_DEPTH         (0 << 25)
+#       define RADEON_FOG_USE_DIFFUSE_ALPHA (2 << 25)
+#       define RADEON_FOG_USE_SPEC_ALPHA    (3 << 25)
+#define RADEON_PP_LUM_MATRIX                0x1d00
+#define RADEON_PP_MISC                      0x1c14
+#       define RADEON_REF_ALPHA_MASK        0x000000ff
+#       define RADEON_ALPHA_TEST_FAIL       (0 << 8)
+#       define RADEON_ALPHA_TEST_LESS       (1 << 8)
+#       define RADEON_ALPHA_TEST_LEQUAL     (2 << 8)
+#       define RADEON_ALPHA_TEST_EQUAL      (3 << 8)
+#       define RADEON_ALPHA_TEST_GEQUAL     (4 << 8)
+#       define RADEON_ALPHA_TEST_GREATER    (5 << 8)
+#       define RADEON_ALPHA_TEST_NEQUAL     (6 << 8)
+#       define RADEON_ALPHA_TEST_PASS       (7 << 8)
+#       define RADEON_ALPHA_TEST_OP_MASK    (7 << 8)
+#       define RADEON_CHROMA_FUNC_FAIL      (0 << 16)
+#       define RADEON_CHROMA_FUNC_PASS      (1 << 16)
+#       define RADEON_CHROMA_FUNC_NEQUAL    (2 << 16)
+#       define RADEON_CHROMA_FUNC_EQUAL     (3 << 16)
+#       define RADEON_CHROMA_KEY_NEAREST    (0 << 18)
+#       define RADEON_CHROMA_KEY_ZERO       (1 << 18)
+#       define RADEON_SHADOW_ID_AUTO_INC    (1 << 20)
+#       define RADEON_SHADOW_FUNC_EQUAL     (0 << 21)
+#       define RADEON_SHADOW_FUNC_NEQUAL    (1 << 21)
+#       define RADEON_SHADOW_PASS_1         (0 << 22)
+#       define RADEON_SHADOW_PASS_2         (1 << 22)
+#       define RADEON_RIGHT_HAND_CUBE_D3D   (0 << 24)
+#       define RADEON_RIGHT_HAND_CUBE_OGL   (1 << 24)
+#define RADEON_PP_ROT_MATRIX_0              0x1d58
+#define RADEON_PP_ROT_MATRIX_1              0x1d5c
+#define RADEON_PP_TXFILTER_0                0x1c54
+#define RADEON_PP_TXFILTER_1                0x1c6c
+#define RADEON_PP_TXFILTER_2                0x1c84
+#       define RADEON_MAG_FILTER_NEAREST                   (0  <<  0)
+#       define RADEON_MAG_FILTER_LINEAR                    (1  <<  0)
+#       define RADEON_MAG_FILTER_MASK                      (1  <<  0)
+#       define RADEON_MIN_FILTER_NEAREST                   (0  <<  1)
+#       define RADEON_MIN_FILTER_LINEAR                    (1  <<  1)
+#       define RADEON_MIN_FILTER_NEAREST_MIP_NEAREST       (2  <<  1)
+#       define RADEON_MIN_FILTER_NEAREST_MIP_LINEAR        (3  <<  1)
+#       define RADEON_MIN_FILTER_LINEAR_MIP_NEAREST        (6  <<  1)
+#       define RADEON_MIN_FILTER_LINEAR_MIP_LINEAR         (7  <<  1)
+#       define RADEON_MIN_FILTER_ANISO_NEAREST             (8  <<  1)
+#       define RADEON_MIN_FILTER_ANISO_LINEAR              (9  <<  1)
+#       define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 <<  1)
+#       define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR  (11 <<  1)
+#       define RADEON_MIN_FILTER_MASK                      (15 <<  1)
+#       define RADEON_MAX_ANISO_1_TO_1                     (0  <<  5)
+#       define RADEON_MAX_ANISO_2_TO_1                     (1  <<  5)
+#       define RADEON_MAX_ANISO_4_TO_1                     (2  <<  5)
+#       define RADEON_MAX_ANISO_8_TO_1                     (3  <<  5)
+#       define RADEON_MAX_ANISO_16_TO_1                    (4  <<  5)
+#       define RADEON_MAX_ANISO_MASK                       (7  <<  5)
+#       define RADEON_LOD_BIAS_MASK                        (0xff <<  8)
+#       define RADEON_LOD_BIAS_SHIFT                       8
+#       define RADEON_MAX_MIP_LEVEL_MASK                   (0x0f << 16)
+#       define RADEON_MAX_MIP_LEVEL_SHIFT                  16
+#       define RADEON_YUV_TO_RGB                           (1  << 20)
+#       define RADEON_YUV_TEMPERATURE_COOL                 (0  << 21)
+#       define RADEON_YUV_TEMPERATURE_HOT                  (1  << 21)
+#       define RADEON_YUV_TEMPERATURE_MASK                 (1  << 21)
+#       define RADEON_WRAPEN_S                             (1  << 22)
+#       define RADEON_CLAMP_S_WRAP                         (0  << 23)
+#       define RADEON_CLAMP_S_MIRROR                       (1  << 23)
+#       define RADEON_CLAMP_S_CLAMP_LAST                   (2  << 23)
+#       define RADEON_CLAMP_S_MIRROR_CLAMP_LAST            (3  << 23)
+#       define RADEON_CLAMP_S_CLAMP_BORDER                 (4  << 23)
+#       define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER          (5  << 23)
+#       define RADEON_CLAMP_S_CLAMP_GL                     (6  << 23)
+#       define RADEON_CLAMP_S_MIRROR_CLAMP_GL              (7  << 23)
+#       define RADEON_CLAMP_S_MASK                         (7  << 23)
+#       define RADEON_WRAPEN_T                             (1  << 26)
+#       define RADEON_CLAMP_T_WRAP                         (0  << 27)
+#       define RADEON_CLAMP_T_MIRROR                       (1  << 27)
+#       define RADEON_CLAMP_T_CLAMP_LAST                   (2  << 27)
+#       define RADEON_CLAMP_T_MIRROR_CLAMP_LAST            (3  << 27)
+#       define RADEON_CLAMP_T_CLAMP_BORDER                 (4  << 27)
+#       define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER          (5  << 27)
+#       define RADEON_CLAMP_T_CLAMP_GL                     (6  << 27)
+#       define RADEON_CLAMP_T_MIRROR_CLAMP_GL              (7  << 27)
+#       define RADEON_CLAMP_T_MASK                         (7  << 27)
+#       define RADEON_BORDER_MODE_OGL                      (0  << 31)
+#       define RADEON_BORDER_MODE_D3D                      (1  << 31)
+#define RADEON_PP_TXFORMAT_0                0x1c58
+#define RADEON_PP_TXFORMAT_1                0x1c70
+#define RADEON_PP_TXFORMAT_2                0x1c88
+#       define RADEON_TXFORMAT_I8                 (0  <<  0)
+#       define RADEON_TXFORMAT_AI88               (1  <<  0)
+#       define RADEON_TXFORMAT_RGB332             (2  <<  0)
+#       define RADEON_TXFORMAT_ARGB1555           (3  <<  0)
+#       define RADEON_TXFORMAT_RGB565             (4  <<  0)
+#       define RADEON_TXFORMAT_ARGB4444           (5  <<  0)
+#       define RADEON_TXFORMAT_ARGB8888           (6  <<  0)
+#       define RADEON_TXFORMAT_RGBA8888           (7  <<  0)
+#       define RADEON_TXFORMAT_Y8                 (8  <<  0)
+#       define RADEON_TXFORMAT_VYUY422            (10 <<  0)
+#       define RADEON_TXFORMAT_YVYU422            (11 <<  0)
+#       define RADEON_TXFORMAT_DXT1               (12 <<  0)
+#       define RADEON_TXFORMAT_DXT23              (14 <<  0)
+#       define RADEON_TXFORMAT_DXT45              (15 <<  0)
+#       define RADEON_TXFORMAT_FORMAT_MASK        (31 <<  0)
+#       define RADEON_TXFORMAT_FORMAT_SHIFT       0
+#       define RADEON_TXFORMAT_APPLE_YUV_MODE     (1  <<  5)
+#       define RADEON_TXFORMAT_ALPHA_IN_MAP       (1  <<  6)
+#       define RADEON_TXFORMAT_NON_POWER2         (1  <<  7)
+#       define RADEON_TXFORMAT_WIDTH_MASK         (15 <<  8)
+#       define RADEON_TXFORMAT_WIDTH_SHIFT        8
+#       define RADEON_TXFORMAT_HEIGHT_MASK        (15 << 12)
+#       define RADEON_TXFORMAT_HEIGHT_SHIFT       12
+#       define RADEON_TXFORMAT_F5_WIDTH_MASK      (15 << 16)
+#       define RADEON_TXFORMAT_F5_WIDTH_SHIFT     16
+#       define RADEON_TXFORMAT_F5_HEIGHT_MASK     (15 << 20)
+#       define RADEON_TXFORMAT_F5_HEIGHT_SHIFT    20
+#       define RADEON_TXFORMAT_ST_ROUTE_STQ0      (0  << 24)
+#       define RADEON_TXFORMAT_ST_ROUTE_MASK      (3  << 24)
+#       define RADEON_TXFORMAT_ST_ROUTE_STQ1      (1  << 24)
+#       define RADEON_TXFORMAT_ST_ROUTE_STQ2      (2  << 24)
+#       define RADEON_TXFORMAT_ENDIAN_NO_SWAP     (0  << 26)
+#       define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP  (1  << 26)
+#       define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP  (2  << 26)
+#       define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3  << 26)
+#       define RADEON_TXFORMAT_ALPHA_MASK_ENABLE  (1  << 28)
+#       define RADEON_TXFORMAT_CHROMA_KEY_ENABLE  (1  << 29)
+#       define RADEON_TXFORMAT_CUBIC_MAP_ENABLE   (1  << 30)
+#       define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1  << 31)
+#define RADEON_PP_CUBIC_FACES_0             0x1d24
+#define RADEON_PP_CUBIC_FACES_1             0x1d28
+#define RADEON_PP_CUBIC_FACES_2             0x1d2c
+#       define RADEON_FACE_WIDTH_1_SHIFT          0
+#       define RADEON_FACE_HEIGHT_1_SHIFT         4
+#       define RADEON_FACE_WIDTH_1_MASK           (0xf << 0)
+#       define RADEON_FACE_HEIGHT_1_MASK          (0xf << 4)
+#       define RADEON_FACE_WIDTH_2_SHIFT          8
+#       define RADEON_FACE_HEIGHT_2_SHIFT         12
+#       define RADEON_FACE_WIDTH_2_MASK           (0xf << 8)
+#       define RADEON_FACE_HEIGHT_2_MASK          (0xf << 12)
+#       define RADEON_FACE_WIDTH_3_SHIFT          16
+#       define RADEON_FACE_HEIGHT_3_SHIFT         20
+#       define RADEON_FACE_WIDTH_3_MASK           (0xf << 16)
+#       define RADEON_FACE_HEIGHT_3_MASK          (0xf << 20)
+#       define RADEON_FACE_WIDTH_4_SHIFT          24
+#       define RADEON_FACE_HEIGHT_4_SHIFT         28
+#       define RADEON_FACE_WIDTH_4_MASK           (0xf << 24)
+#       define RADEON_FACE_HEIGHT_4_MASK          (0xf << 28)
+
+#define RADEON_PP_TXOFFSET_0                0x1c5c
+#define RADEON_PP_TXOFFSET_1                0x1c74
+#define RADEON_PP_TXOFFSET_2                0x1c8c
+#       define RADEON_TXO_ENDIAN_NO_SWAP     (0 << 0)
+#       define RADEON_TXO_ENDIAN_BYTE_SWAP   (1 << 0)
+#       define RADEON_TXO_ENDIAN_WORD_SWAP   (2 << 0)
+#       define RADEON_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
+#       define RADEON_TXO_MACRO_LINEAR       (0 << 2)
+#       define RADEON_TXO_MACRO_TILE         (1 << 2)
+#       define RADEON_TXO_MICRO_LINEAR       (0 << 3)
+#       define RADEON_TXO_MICRO_TILE_X2      (1 << 3)
+#       define RADEON_TXO_MICRO_TILE_OPT     (2 << 3)
+#       define RADEON_TXO_OFFSET_MASK        0xffffffe0
+#       define RADEON_TXO_OFFSET_SHIFT       5
+
+#define RADEON_PP_CUBIC_OFFSET_T0_0         0x1dd0  /* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T0_1         0x1dd4
+#define RADEON_PP_CUBIC_OFFSET_T0_2         0x1dd8
+#define RADEON_PP_CUBIC_OFFSET_T0_3         0x1ddc
+#define RADEON_PP_CUBIC_OFFSET_T0_4         0x1de0
+#define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T1_1         0x1e04
+#define RADEON_PP_CUBIC_OFFSET_T1_2         0x1e08
+#define RADEON_PP_CUBIC_OFFSET_T1_3         0x1e0c
+#define RADEON_PP_CUBIC_OFFSET_T1_4         0x1e10
+#define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
+#define RADEON_PP_CUBIC_OFFSET_T2_1         0x1e18
+#define RADEON_PP_CUBIC_OFFSET_T2_2         0x1e1c
+#define RADEON_PP_CUBIC_OFFSET_T2_3         0x1e20
+#define RADEON_PP_CUBIC_OFFSET_T2_4         0x1e24
+
+#define RADEON_PP_TEX_SIZE_0                0x1d04  /* NPOT */
+#define RADEON_PP_TEX_SIZE_1                0x1d0c
+#define RADEON_PP_TEX_SIZE_2                0x1d14
+#       define RADEON_TEX_USIZE_MASK        (0x7ff << 0)
+#       define RADEON_TEX_USIZE_SHIFT       0
+#       define RADEON_TEX_VSIZE_MASK        (0x7ff << 16)
+#       define RADEON_TEX_VSIZE_SHIFT       16
+#       define RADEON_SIGNED_RGB_MASK       (1 << 30)
+#       define RADEON_SIGNED_RGB_SHIFT      30
+#       define RADEON_SIGNED_ALPHA_MASK     (1 << 31)
+#       define RADEON_SIGNED_ALPHA_SHIFT    31
+#define RADEON_PP_TEX_PITCH_0               0x1d08  /* NPOT */
+#define RADEON_PP_TEX_PITCH_1               0x1d10  /* NPOT */
+#define RADEON_PP_TEX_PITCH_2               0x1d18  /* NPOT */
+/* note: bits 13-5: 32 byte aligned stride of texture map */
+
+#define RADEON_PP_TXCBLEND_0                0x1c60
+#define RADEON_PP_TXCBLEND_1                0x1c78
+#define RADEON_PP_TXCBLEND_2                0x1c90
+#       define RADEON_COLOR_ARG_A_SHIFT          0
+#       define RADEON_COLOR_ARG_A_MASK           (0x1f << 0)
+#       define RADEON_COLOR_ARG_A_ZERO           (0    << 0)
+#       define RADEON_COLOR_ARG_A_CURRENT_COLOR  (2    << 0)
+#       define RADEON_COLOR_ARG_A_CURRENT_ALPHA  (3    << 0)
+#       define RADEON_COLOR_ARG_A_DIFFUSE_COLOR  (4    << 0)
+#       define RADEON_COLOR_ARG_A_DIFFUSE_ALPHA  (5    << 0)
+#       define RADEON_COLOR_ARG_A_SPECULAR_COLOR (6    << 0)
+#       define RADEON_COLOR_ARG_A_SPECULAR_ALPHA (7    << 0)
+#       define RADEON_COLOR_ARG_A_TFACTOR_COLOR  (8    << 0)
+#       define RADEON_COLOR_ARG_A_TFACTOR_ALPHA  (9    << 0)
+#       define RADEON_COLOR_ARG_A_T0_COLOR       (10   << 0)
+#       define RADEON_COLOR_ARG_A_T0_ALPHA       (11   << 0)
+#       define RADEON_COLOR_ARG_A_T1_COLOR       (12   << 0)
+#       define RADEON_COLOR_ARG_A_T1_ALPHA       (13   << 0)
+#       define RADEON_COLOR_ARG_A_T2_COLOR       (14   << 0)
+#       define RADEON_COLOR_ARG_A_T2_ALPHA       (15   << 0)
+#       define RADEON_COLOR_ARG_A_T3_COLOR       (16   << 0)
+#       define RADEON_COLOR_ARG_A_T3_ALPHA       (17   << 0)
+#       define RADEON_COLOR_ARG_B_SHIFT          5
+#       define RADEON_COLOR_ARG_B_MASK           (0x1f << 5)
+#       define RADEON_COLOR_ARG_B_ZERO           (0    << 5)
+#       define RADEON_COLOR_ARG_B_CURRENT_COLOR  (2    << 5)
+#       define RADEON_COLOR_ARG_B_CURRENT_ALPHA  (3    << 5)
+#       define RADEON_COLOR_ARG_B_DIFFUSE_COLOR  (4    << 5)
+#       define RADEON_COLOR_ARG_B_DIFFUSE_ALPHA  (5    << 5)
+#       define RADEON_COLOR_ARG_B_SPECULAR_COLOR (6    << 5)
+#       define RADEON_COLOR_ARG_B_SPECULAR_ALPHA (7    << 5)
+#       define RADEON_COLOR_ARG_B_TFACTOR_COLOR  (8    << 5)
+#       define RADEON_COLOR_ARG_B_TFACTOR_ALPHA  (9    << 5)
+#       define RADEON_COLOR_ARG_B_T0_COLOR       (10   << 5)
+#       define RADEON_COLOR_ARG_B_T0_ALPHA       (11   << 5)
+#       define RADEON_COLOR_ARG_B_T1_COLOR       (12   << 5)
+#       define RADEON_COLOR_ARG_B_T1_ALPHA       (13   << 5)
+#       define RADEON_COLOR_ARG_B_T2_COLOR       (14   << 5)
+#       define RADEON_COLOR_ARG_B_T2_ALPHA       (15   << 5)
+#       define RADEON_COLOR_ARG_B_T3_COLOR       (16   << 5)
+#       define RADEON_COLOR_ARG_B_T3_ALPHA       (17   << 5)
+#       define RADEON_COLOR_ARG_C_SHIFT          10
+#       define RADEON_COLOR_ARG_C_MASK           (0x1f << 10)
+#       define RADEON_COLOR_ARG_C_ZERO           (0    << 10)
+#       define RADEON_COLOR_ARG_C_CURRENT_COLOR  (2    << 10)
+#       define RADEON_COLOR_ARG_C_CURRENT_ALPHA  (3    << 10)
+#       define RADEON_COLOR_ARG_C_DIFFUSE_COLOR  (4    << 10)
+#       define RADEON_COLOR_ARG_C_DIFFUSE_ALPHA  (5    << 10)
+#       define RADEON_COLOR_ARG_C_SPECULAR_COLOR (6    << 10)
+#       define RADEON_COLOR_ARG_C_SPECULAR_ALPHA (7    << 10)
+#       define RADEON_COLOR_ARG_C_TFACTOR_COLOR  (8    << 10)
+#       define RADEON_COLOR_ARG_C_TFACTOR_ALPHA  (9    << 10)
+#       define RADEON_COLOR_ARG_C_T0_COLOR       (10   << 10)
+#       define RADEON_COLOR_ARG_C_T0_ALPHA       (11   << 10)
+#       define RADEON_COLOR_ARG_C_T1_COLOR       (12   << 10)
+#       define RADEON_COLOR_ARG_C_T1_ALPHA       (13   << 10)
+#       define RADEON_COLOR_ARG_C_T2_COLOR       (14   << 10)
+#       define RADEON_COLOR_ARG_C_T2_ALPHA       (15   << 10)
+#       define RADEON_COLOR_ARG_C_T3_COLOR       (16   << 10)
+#       define RADEON_COLOR_ARG_C_T3_ALPHA       (17   << 10)
+#       define RADEON_COMP_ARG_A                 (1 << 15)
+#       define RADEON_COMP_ARG_A_SHIFT           15
+#       define RADEON_COMP_ARG_B                 (1 << 16)
+#       define RADEON_COMP_ARG_B_SHIFT           16
+#       define RADEON_COMP_ARG_C                 (1 << 17)
+#       define RADEON_COMP_ARG_C_SHIFT           17
+#       define RADEON_BLEND_CTL_MASK             (7 << 18)
+#       define RADEON_BLEND_CTL_ADD              (0 << 18)
+#       define RADEON_BLEND_CTL_SUBTRACT         (1 << 18)
+#       define RADEON_BLEND_CTL_ADDSIGNED        (2 << 18)
+#       define RADEON_BLEND_CTL_BLEND            (3 << 18)
+#       define RADEON_BLEND_CTL_DOT3             (4 << 18)
+#       define RADEON_SCALE_SHIFT                21
+#       define RADEON_SCALE_MASK                 (3 << 21)
+#       define RADEON_SCALE_1X                   (0 << 21)
+#       define RADEON_SCALE_2X                   (1 << 21)
+#       define RADEON_SCALE_4X                   (2 << 21)
+#       define RADEON_CLAMP_TX                   (1 << 23)
+#       define RADEON_T0_EQ_TCUR                 (1 << 24)
+#       define RADEON_T1_EQ_TCUR                 (1 << 25)
+#       define RADEON_T2_EQ_TCUR                 (1 << 26)
+#       define RADEON_T3_EQ_TCUR                 (1 << 27)
+#       define RADEON_COLOR_ARG_MASK             0x1f
+#       define RADEON_COMP_ARG_SHIFT             15
+#define RADEON_PP_TXABLEND_0                0x1c64
+#define RADEON_PP_TXABLEND_1                0x1c7c
+#define RADEON_PP_TXABLEND_2                0x1c94
+#       define RADEON_ALPHA_ARG_A_SHIFT          0
+#       define RADEON_ALPHA_ARG_A_MASK           (0xf << 0)
+#       define RADEON_ALPHA_ARG_A_ZERO           (0   << 0)
+#       define RADEON_ALPHA_ARG_A_CURRENT_ALPHA  (1   << 0)
+#       define RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA  (2   << 0)
+#       define RADEON_ALPHA_ARG_A_SPECULAR_ALPHA (3   << 0)
+#       define RADEON_ALPHA_ARG_A_TFACTOR_ALPHA  (4   << 0)
+#       define RADEON_ALPHA_ARG_A_T0_ALPHA       (5   << 0)
+#       define RADEON_ALPHA_ARG_A_T1_ALPHA       (6   << 0)
+#       define RADEON_ALPHA_ARG_A_T2_ALPHA       (7   << 0)
+#       define RADEON_ALPHA_ARG_A_T3_ALPHA       (8   << 0)
+#       define RADEON_ALPHA_ARG_B_SHIFT          4
+#       define RADEON_ALPHA_ARG_B_MASK           (0xf << 4)
+#       define RADEON_ALPHA_ARG_B_ZERO           (0   << 4)
+#       define RADEON_ALPHA_ARG_B_CURRENT_ALPHA  (1   << 4)
+#       define RADEON_ALPHA_ARG_B_DIFFUSE_ALPHA  (2   << 4)
+#       define RADEON_ALPHA_ARG_B_SPECULAR_ALPHA (3   << 4)
+#       define RADEON_ALPHA_ARG_B_TFACTOR_ALPHA  (4   << 4)
+#       define RADEON_ALPHA_ARG_B_T0_ALPHA       (5   << 4)
+#       define RADEON_ALPHA_ARG_B_T1_ALPHA       (6   << 4)
+#       define RADEON_ALPHA_ARG_B_T2_ALPHA       (7   << 4)
+#       define RADEON_ALPHA_ARG_B_T3_ALPHA       (8   << 4)
+#       define RADEON_ALPHA_ARG_C_SHIFT          8
+#       define RADEON_ALPHA_ARG_C_MASK           (0xf << 8)
+#       define RADEON_ALPHA_ARG_C_ZERO           (0   << 8)
+#       define RADEON_ALPHA_ARG_C_CURRENT_ALPHA  (1   << 8)
+#       define RADEON_ALPHA_ARG_C_DIFFUSE_ALPHA  (2   << 8)
+#       define RADEON_ALPHA_ARG_C_SPECULAR_ALPHA (3   << 8)
+#       define RADEON_ALPHA_ARG_C_TFACTOR_ALPHA  (4   << 8)
+#       define RADEON_ALPHA_ARG_C_T0_ALPHA       (5   << 8)
+#       define RADEON_ALPHA_ARG_C_T1_ALPHA       (6   << 8)
+#       define RADEON_ALPHA_ARG_C_T2_ALPHA       (7   << 8)
+#       define RADEON_ALPHA_ARG_C_T3_ALPHA       (8   << 8)
+#       define RADEON_DOT_ALPHA_DONT_REPLICATE   (1   << 9)
+#       define RADEON_ALPHA_ARG_MASK             0xf
+
+#define RADEON_PP_TFACTOR_0                 0x1c68
+#define RADEON_PP_TFACTOR_1                 0x1c80
+#define RADEON_PP_TFACTOR_2                 0x1c98
+
+#define RADEON_RB3D_BLENDCNTL               0x1c20
+#       define RADEON_COMB_FCN_MASK                    (3  << 12)
+#       define RADEON_COMB_FCN_ADD_CLAMP               (0  << 12)
+#       define RADEON_COMB_FCN_ADD_NOCLAMP             (1  << 12)
+#       define RADEON_COMB_FCN_SUB_CLAMP               (2  << 12)
+#       define RADEON_COMB_FCN_SUB_NOCLAMP             (3  << 12)
+#       define RADEON_SRC_BLEND_GL_ZERO                (32 << 16)
+#       define RADEON_SRC_BLEND_GL_ONE                 (33 << 16)
+#       define RADEON_SRC_BLEND_GL_SRC_COLOR           (34 << 16)
+#       define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
+#       define RADEON_SRC_BLEND_GL_DST_COLOR           (36 << 16)
+#       define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
+#       define RADEON_SRC_BLEND_GL_SRC_ALPHA           (38 << 16)
+#       define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
+#       define RADEON_SRC_BLEND_GL_DST_ALPHA           (40 << 16)
+#       define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
+#       define RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE  (42 << 16)
+#       define RADEON_SRC_BLEND_MASK                   (63 << 16)
+#       define RADEON_DST_BLEND_GL_ZERO                (32 << 24)
+#       define RADEON_DST_BLEND_GL_ONE                 (33 << 24)
+#       define RADEON_DST_BLEND_GL_SRC_COLOR           (34 << 24)
+#       define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
+#       define RADEON_DST_BLEND_GL_DST_COLOR           (36 << 24)
+#       define RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
+#       define RADEON_DST_BLEND_GL_SRC_ALPHA           (38 << 24)
+#       define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
+#       define RADEON_DST_BLEND_GL_DST_ALPHA           (40 << 24)
+#       define RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
+#       define RADEON_DST_BLEND_MASK                   (63 << 24)
+#define RADEON_RB3D_CNTL                    0x1c3c
+#       define RADEON_ALPHA_BLEND_ENABLE       (1  <<  0)
+#       define RADEON_PLANE_MASK_ENABLE        (1  <<  1)
+#       define RADEON_DITHER_ENABLE            (1  <<  2)
+#       define RADEON_ROUND_ENABLE             (1  <<  3)
+#       define RADEON_SCALE_DITHER_ENABLE      (1  <<  4)
+#       define RADEON_DITHER_INIT              (1  <<  5)
+#       define RADEON_ROP_ENABLE               (1  <<  6)
+#       define RADEON_STENCIL_ENABLE           (1  <<  7)
+#       define RADEON_Z_ENABLE                 (1  <<  8)
+#       define RADEON_DEPTH_XZ_OFFEST_ENABLE   (1  <<  9)
+#       define RADEON_RB3D_COLOR_FORMAT_SHIFT  10
+
+#       define RADEON_COLOR_FORMAT_ARGB1555    3
+#       define RADEON_COLOR_FORMAT_RGB565      4
+#       define RADEON_COLOR_FORMAT_ARGB8888    6
+#       define RADEON_COLOR_FORMAT_RGB332      7
+#       define RADEON_COLOR_FORMAT_Y8          8
+#       define RADEON_COLOR_FORMAT_RGB8        9
+#       define RADEON_COLOR_FORMAT_YUV422_VYUY 11
+#       define RADEON_COLOR_FORMAT_YUV422_YVYU 12
+#       define RADEON_COLOR_FORMAT_aYUV444     14
+#       define RADEON_COLOR_FORMAT_ARGB4444    15
+
+#       define RADEON_CLRCMP_FLIP_ENABLE       (1  << 14)
+#define RADEON_RB3D_COLOROFFSET             0x1c40
+#       define RADEON_COLOROFFSET_MASK      0xfffffff0
+#define RADEON_RB3D_COLORPITCH              0x1c48
+#       define RADEON_COLORPITCH_MASK         0x000001ff8
+#       define RADEON_COLOR_TILE_ENABLE       (1 << 16)
+#       define RADEON_COLOR_MICROTILE_ENABLE  (1 << 17)
+#       define RADEON_COLOR_ENDIAN_NO_SWAP    (0 << 18)
+#       define RADEON_COLOR_ENDIAN_WORD_SWAP  (1 << 18)
+#       define RADEON_COLOR_ENDIAN_DWORD_SWAP (2 << 18)
+#define RADEON_RB3D_DEPTHOFFSET             0x1c24
+#define RADEON_RB3D_DEPTHPITCH              0x1c28
+#       define RADEON_DEPTHPITCH_MASK         0x00001ff8
+#       define RADEON_DEPTH_ENDIAN_NO_SWAP    (0 << 18)
+#       define RADEON_DEPTH_ENDIAN_WORD_SWAP  (1 << 18)
+#       define RADEON_DEPTH_ENDIAN_DWORD_SWAP (2 << 18)
+#define RADEON_RB3D_PLANEMASK               0x1d84
+#define RADEON_RB3D_ROPCNTL                 0x1d80
+#       define RADEON_ROP_MASK              (15 << 8)
+#       define RADEON_ROP_CLEAR             (0  << 8)
+#       define RADEON_ROP_NOR               (1  << 8)
+#       define RADEON_ROP_AND_INVERTED      (2  << 8)
+#       define RADEON_ROP_COPY_INVERTED     (3  << 8)
+#       define RADEON_ROP_AND_REVERSE       (4  << 8)
+#       define RADEON_ROP_INVERT            (5  << 8)
+#       define RADEON_ROP_XOR               (6  << 8)
+#       define RADEON_ROP_NAND              (7  << 8)
+#       define RADEON_ROP_AND               (8  << 8)
+#       define RADEON_ROP_EQUIV             (9  << 8)
+#       define RADEON_ROP_NOOP              (10 << 8)
+#       define RADEON_ROP_OR_INVERTED       (11 << 8)
+#       define RADEON_ROP_COPY              (12 << 8)
+#       define RADEON_ROP_OR_REVERSE        (13 << 8)
+#       define RADEON_ROP_OR                (14 << 8)
+#       define RADEON_ROP_SET               (15 << 8)
+#define RADEON_RB3D_STENCILREFMASK          0x1d7c
+#       define RADEON_STENCIL_REF_SHIFT       0
+#       define RADEON_STENCIL_REF_MASK        (0xff << 0)
+#       define RADEON_STENCIL_MASK_SHIFT      16
+#       define RADEON_STENCIL_VALUE_MASK      (0xff << 16)
+#       define RADEON_STENCIL_WRITEMASK_SHIFT 24
+#       define RADEON_STENCIL_WRITE_MASK      (0xff << 24)
+#define RADEON_RB3D_ZSTENCILCNTL            0x1c2c
+#       define RADEON_DEPTH_FORMAT_MASK          (0xf << 0)
+#       define RADEON_DEPTH_FORMAT_16BIT_INT_Z   (0  <<  0)
+#       define RADEON_DEPTH_FORMAT_24BIT_INT_Z   (2  <<  0)
+#       define RADEON_DEPTH_FORMAT_24BIT_FLOAT_Z (3  <<  0)
+#       define RADEON_DEPTH_FORMAT_32BIT_INT_Z   (4  <<  0)
+#       define RADEON_DEPTH_FORMAT_32BIT_FLOAT_Z (5  <<  0)
+#       define RADEON_DEPTH_FORMAT_16BIT_FLOAT_W (7  <<  0)
+#       define RADEON_DEPTH_FORMAT_24BIT_FLOAT_W (9  <<  0)
+#       define RADEON_DEPTH_FORMAT_32BIT_FLOAT_W (11 <<  0)
+#       define RADEON_Z_TEST_NEVER               (0  <<  4)
+#       define RADEON_Z_TEST_LESS                (1  <<  4)
+#       define RADEON_Z_TEST_LEQUAL              (2  <<  4)
+#       define RADEON_Z_TEST_EQUAL               (3  <<  4)
+#       define RADEON_Z_TEST_GEQUAL              (4  <<  4)
+#       define RADEON_Z_TEST_GREATER             (5  <<  4)
+#       define RADEON_Z_TEST_NEQUAL              (6  <<  4)
+#       define RADEON_Z_TEST_ALWAYS              (7  <<  4)
+#       define RADEON_Z_TEST_MASK                (7  <<  4)
+#       define RADEON_STENCIL_TEST_NEVER         (0  << 12)
+#       define RADEON_STENCIL_TEST_LESS          (1  << 12)
+#       define RADEON_STENCIL_TEST_LEQUAL        (2  << 12)
+#       define RADEON_STENCIL_TEST_EQUAL         (3  << 12)
+#       define RADEON_STENCIL_TEST_GEQUAL        (4  << 12)
+#       define RADEON_STENCIL_TEST_GREATER       (5  << 12)
+#       define RADEON_STENCIL_TEST_NEQUAL        (6  << 12)
+#       define RADEON_STENCIL_TEST_ALWAYS        (7  << 12)
+#       define RADEON_STENCIL_TEST_MASK          (0x7 << 12)
+#       define RADEON_STENCIL_FAIL_KEEP          (0  << 16)
+#       define RADEON_STENCIL_FAIL_ZERO          (1  << 16)
+#       define RADEON_STENCIL_FAIL_REPLACE       (2  << 16)
+#       define RADEON_STENCIL_FAIL_INC           (3  << 16)
+#       define RADEON_STENCIL_FAIL_DEC           (4  << 16)
+#       define RADEON_STENCIL_FAIL_INVERT        (5  << 16)
+#       define RADEON_STENCIL_FAIL_MASK          (0x7 << 16)
+#       define RADEON_STENCIL_ZPASS_KEEP         (0  << 20)
+#       define RADEON_STENCIL_ZPASS_ZERO         (1  << 20)
+#       define RADEON_STENCIL_ZPASS_REPLACE      (2  << 20)
+#       define RADEON_STENCIL_ZPASS_INC          (3  << 20)
+#       define RADEON_STENCIL_ZPASS_DEC          (4  << 20)
+#       define RADEON_STENCIL_ZPASS_INVERT       (5  << 20)
+#       define RADEON_STENCIL_ZPASS_MASK         (0x7 << 20)
+#       define RADEON_STENCIL_ZFAIL_KEEP         (0  << 24)
+#       define RADEON_STENCIL_ZFAIL_ZERO         (1  << 24)
+#       define RADEON_STENCIL_ZFAIL_REPLACE      (2  << 24)
+#       define RADEON_STENCIL_ZFAIL_INC          (3  << 24)
+#       define RADEON_STENCIL_ZFAIL_DEC          (4  << 24)
+#       define RADEON_STENCIL_ZFAIL_INVERT       (5  << 24)
+#       define RADEON_STENCIL_ZFAIL_MASK         (0x7 << 24)
+#       define RADEON_Z_COMPRESSION_ENABLE       (1  << 28)
+#       define RADEON_FORCE_Z_DIRTY              (1  << 29)
+#       define RADEON_Z_WRITE_ENABLE             (1  << 30)
+#define RADEON_RE_LINE_PATTERN              0x1cd0
+#       define RADEON_LINE_PATTERN_MASK             0x0000ffff
+#       define RADEON_LINE_REPEAT_COUNT_SHIFT       16
+#       define RADEON_LINE_PATTERN_START_SHIFT      24
+#       define RADEON_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28)
+#       define RADEON_LINE_PATTERN_BIG_BIT_ORDER    (1 << 28)
+#       define RADEON_LINE_PATTERN_AUTO_RESET       (1 << 29)
+#define RADEON_RE_LINE_STATE                0x1cd4
+#       define RADEON_LINE_CURRENT_PTR_SHIFT   0
+#       define RADEON_LINE_CURRENT_COUNT_SHIFT 8
+#define RADEON_RE_MISC                      0x26c4
+#       define RADEON_STIPPLE_COORD_MASK       0x1f
+#       define RADEON_STIPPLE_X_OFFSET_SHIFT   0
+#       define RADEON_STIPPLE_X_OFFSET_MASK    (0x1f << 0)
+#       define RADEON_STIPPLE_Y_OFFSET_SHIFT   8
+#       define RADEON_STIPPLE_Y_OFFSET_MASK    (0x1f << 8)
+#       define RADEON_STIPPLE_LITTLE_BIT_ORDER (0 << 16)
+#       define RADEON_STIPPLE_BIG_BIT_ORDER    (1 << 16)
+#define RADEON_RE_SOLID_COLOR               0x1c1c
+#define RADEON_RE_TOP_LEFT                  0x26c0
+#       define RADEON_RE_LEFT_SHIFT         0
+#       define RADEON_RE_TOP_SHIFT          16
+#define RADEON_RE_WIDTH_HEIGHT              0x1c44
+#       define RADEON_RE_WIDTH_SHIFT        0
+#       define RADEON_RE_HEIGHT_SHIFT       16
+
+#define RADEON_RB3D_ZPASS_DATA 0x3290
+#define RADEON_RB3D_ZPASS_ADDR 0x3294
+
+#define RADEON_SE_CNTL                      0x1c4c
+#       define RADEON_FFACE_CULL_CW          (0 <<  0)
+#       define RADEON_FFACE_CULL_CCW         (1 <<  0)
+#       define RADEON_FFACE_CULL_DIR_MASK    (1 <<  0)
+#       define RADEON_BFACE_CULL             (0 <<  1)
+#       define RADEON_BFACE_SOLID            (3 <<  1)
+#       define RADEON_FFACE_CULL             (0 <<  3)
+#       define RADEON_FFACE_SOLID            (3 <<  3)
+#       define RADEON_FFACE_CULL_MASK        (3 <<  3)
+#       define RADEON_BADVTX_CULL_DISABLE    (1 <<  5)
+#       define RADEON_FLAT_SHADE_VTX_0       (0 <<  6)
+#       define RADEON_FLAT_SHADE_VTX_1       (1 <<  6)
+#       define RADEON_FLAT_SHADE_VTX_2       (2 <<  6)
+#       define RADEON_FLAT_SHADE_VTX_LAST    (3 <<  6)
+#       define RADEON_DIFFUSE_SHADE_SOLID    (0 <<  8)
+#       define RADEON_DIFFUSE_SHADE_FLAT     (1 <<  8)
+#       define RADEON_DIFFUSE_SHADE_GOURAUD  (2 <<  8)
+#       define RADEON_DIFFUSE_SHADE_MASK     (3 <<  8)
+#       define RADEON_ALPHA_SHADE_SOLID      (0 << 10)
+#       define RADEON_ALPHA_SHADE_FLAT       (1 << 10)
+#       define RADEON_ALPHA_SHADE_GOURAUD    (2 << 10)
+#       define RADEON_ALPHA_SHADE_MASK       (3 << 10)
+#       define RADEON_SPECULAR_SHADE_SOLID   (0 << 12)
+#       define RADEON_SPECULAR_SHADE_FLAT    (1 << 12)
+#       define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12)
+#       define RADEON_SPECULAR_SHADE_MASK    (3 << 12)
+#       define RADEON_FOG_SHADE_SOLID        (0 << 14)
+#       define RADEON_FOG_SHADE_FLAT         (1 << 14)
+#       define RADEON_FOG_SHADE_GOURAUD      (2 << 14)
+#       define RADEON_FOG_SHADE_MASK         (3 << 14)
+#       define RADEON_ZBIAS_ENABLE_POINT     (1 << 16)
+#       define RADEON_ZBIAS_ENABLE_LINE      (1 << 17)
+#       define RADEON_ZBIAS_ENABLE_TRI       (1 << 18)
+#       define RADEON_WIDELINE_ENABLE        (1 << 20)
+#       define RADEON_VPORT_XY_XFORM_ENABLE  (1 << 24)
+#       define RADEON_VPORT_Z_XFORM_ENABLE   (1 << 25)
+#       define RADEON_VTX_PIX_CENTER_D3D     (0 << 27)
+#       define RADEON_VTX_PIX_CENTER_OGL     (1 << 27)
+#       define RADEON_ROUND_MODE_TRUNC       (0 << 28)
+#       define RADEON_ROUND_MODE_ROUND       (1 << 28)
+#       define RADEON_ROUND_MODE_ROUND_EVEN  (2 << 28)
+#       define RADEON_ROUND_MODE_ROUND_ODD   (3 << 28)
+#       define RADEON_ROUND_PREC_16TH_PIX    (0 << 30)
+#       define RADEON_ROUND_PREC_8TH_PIX     (1 << 30)
+#       define RADEON_ROUND_PREC_4TH_PIX     (2 << 30)
+#       define RADEON_ROUND_PREC_HALF_PIX    (3 << 30)
+#define R200_RE_CNTL				0x1c50
+#       define R200_STIPPLE_ENABLE		0x1
+#       define R200_SCISSOR_ENABLE		0x2
+#       define R200_PATTERN_ENABLE		0x4
+#       define R200_PERSPECTIVE_ENABLE		0x8
+#       define R200_POINT_SMOOTH		0x20
+#       define R200_VTX_STQ0_D3D		0x00010000
+#       define R200_VTX_STQ1_D3D		0x00040000
+#       define R200_VTX_STQ2_D3D		0x00100000
+#       define R200_VTX_STQ3_D3D		0x00400000
+#       define R200_VTX_STQ4_D3D		0x01000000
+#       define R200_VTX_STQ5_D3D		0x04000000
+#define RADEON_SE_CNTL_STATUS               0x2140
+#       define RADEON_VC_NO_SWAP            (0 << 0)
+#       define RADEON_VC_16BIT_SWAP         (1 << 0)
+#       define RADEON_VC_32BIT_SWAP         (2 << 0)
+#       define RADEON_VC_HALF_DWORD_SWAP    (3 << 0)
+#       define RADEON_TCL_BYPASS            (1 << 8)
+#define RADEON_SE_COORD_FMT                 0x1c50
+#       define RADEON_VTX_XY_PRE_MULT_1_OVER_W0  (1 <<  0)
+#       define RADEON_VTX_Z_PRE_MULT_1_OVER_W0   (1 <<  1)
+#       define RADEON_VTX_ST0_NONPARAMETRIC      (1 <<  8)
+#       define RADEON_VTX_ST1_NONPARAMETRIC      (1 <<  9)
+#       define RADEON_VTX_ST2_NONPARAMETRIC      (1 << 10)
+#       define RADEON_VTX_ST3_NONPARAMETRIC      (1 << 11)
+#       define RADEON_VTX_W0_NORMALIZE           (1 << 12)
+#       define RADEON_VTX_W0_IS_NOT_1_OVER_W0    (1 << 16)
+#       define RADEON_VTX_ST0_PRE_MULT_1_OVER_W0 (1 << 17)
+#       define RADEON_VTX_ST1_PRE_MULT_1_OVER_W0 (1 << 19)
+#       define RADEON_VTX_ST2_PRE_MULT_1_OVER_W0 (1 << 21)
+#       define RADEON_VTX_ST3_PRE_MULT_1_OVER_W0 (1 << 23)
+#       define RADEON_TEX1_W_ROUTING_USE_W0      (0 << 26)
+#       define RADEON_TEX1_W_ROUTING_USE_Q1      (1 << 26)
+#define RADEON_SE_LINE_WIDTH                0x1db8
+#define RADEON_SE_TCL_LIGHT_MODEL_CTL       0x226c
+#       define RADEON_LIGHTING_ENABLE              (1 << 0)
+#       define RADEON_LIGHT_IN_MODELSPACE          (1 << 1)
+#       define RADEON_LOCAL_VIEWER                 (1 << 2)
+#       define RADEON_NORMALIZE_NORMALS            (1 << 3)
+#       define RADEON_RESCALE_NORMALS              (1 << 4)
+#       define RADEON_SPECULAR_LIGHTS              (1 << 5)
+#       define RADEON_DIFFUSE_SPECULAR_COMBINE     (1 << 6)
+#       define RADEON_LIGHT_ALPHA                  (1 << 7)
+#       define RADEON_LOCAL_LIGHT_VEC_GL           (1 << 8)
+#       define RADEON_LIGHT_NO_NORMAL_AMBIENT_ONLY (1 << 9)
+#       define RADEON_LM_SOURCE_STATE_PREMULT      0
+#       define RADEON_LM_SOURCE_STATE_MULT         1
+#       define RADEON_LM_SOURCE_VERTEX_DIFFUSE     2
+#       define RADEON_LM_SOURCE_VERTEX_SPECULAR    3
+#       define RADEON_EMISSIVE_SOURCE_SHIFT        16
+#       define RADEON_AMBIENT_SOURCE_SHIFT         18
+#       define RADEON_DIFFUSE_SOURCE_SHIFT         20
+#       define RADEON_SPECULAR_SOURCE_SHIFT        22
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_RED     0x2220
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN   0x2224
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE    0x2228
+#define RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA   0x222c
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_RED     0x2230
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN   0x2234
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE    0x2238
+#define RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA   0x223c
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED   0x2210
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN 0x2214
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE  0x2218
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA 0x221c
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_RED    0x2240
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN  0x2244
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE   0x2248
+#define RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA  0x224c
+#define RADEON_SE_TCL_MATRIX_SELECT_0       0x225c
+#       define RADEON_MODELVIEW_0_SHIFT        0
+#       define RADEON_MODELVIEW_1_SHIFT        4
+#       define RADEON_MODELVIEW_2_SHIFT        8
+#       define RADEON_MODELVIEW_3_SHIFT        12
+#       define RADEON_IT_MODELVIEW_0_SHIFT     16
+#       define RADEON_IT_MODELVIEW_1_SHIFT     20
+#       define RADEON_IT_MODELVIEW_2_SHIFT     24
+#       define RADEON_IT_MODELVIEW_3_SHIFT     28
+#define RADEON_SE_TCL_MATRIX_SELECT_1       0x2260
+#       define RADEON_MODELPROJECT_0_SHIFT     0
+#       define RADEON_MODELPROJECT_1_SHIFT     4
+#       define RADEON_MODELPROJECT_2_SHIFT     8
+#       define RADEON_MODELPROJECT_3_SHIFT     12
+#       define RADEON_TEXMAT_0_SHIFT           16
+#       define RADEON_TEXMAT_1_SHIFT           20
+#       define RADEON_TEXMAT_2_SHIFT           24
+#       define RADEON_TEXMAT_3_SHIFT           28
+
+
+#define RADEON_SE_TCL_OUTPUT_VTX_FMT        0x2254
+#       define RADEON_TCL_VTX_W0                 (1 <<  0)
+#       define RADEON_TCL_VTX_FP_DIFFUSE         (1 <<  1)
+#       define RADEON_TCL_VTX_FP_ALPHA           (1 <<  2)
+#       define RADEON_TCL_VTX_PK_DIFFUSE         (1 <<  3)
+#       define RADEON_TCL_VTX_FP_SPEC            (1 <<  4)
+#       define RADEON_TCL_VTX_FP_FOG             (1 <<  5)
+#       define RADEON_TCL_VTX_PK_SPEC            (1 <<  6)
+#       define RADEON_TCL_VTX_ST0                (1 <<  7)
+#       define RADEON_TCL_VTX_ST1                (1 <<  8)
+#       define RADEON_TCL_VTX_Q1                 (1 <<  9)
+#       define RADEON_TCL_VTX_ST2                (1 << 10)
+#       define RADEON_TCL_VTX_Q2                 (1 << 11)
+#       define RADEON_TCL_VTX_ST3                (1 << 12)
+#       define RADEON_TCL_VTX_Q3                 (1 << 13)
+#       define RADEON_TCL_VTX_Q0                 (1 << 14)
+#       define RADEON_TCL_VTX_WEIGHT_COUNT_SHIFT 15
+#       define RADEON_TCL_VTX_NORM0              (1 << 18)
+#       define RADEON_TCL_VTX_XY1                (1 << 27)
+#       define RADEON_TCL_VTX_Z1                 (1 << 28)
+#       define RADEON_TCL_VTX_W1                 (1 << 29)
+#       define RADEON_TCL_VTX_NORM1              (1 << 30)
+#       define RADEON_TCL_VTX_Z0                 (1 << 31)
+
+#define RADEON_SE_TCL_OUTPUT_VTX_SEL        0x2258
+#       define RADEON_TCL_COMPUTE_XYZW           (1 << 0)
+#       define RADEON_TCL_COMPUTE_DIFFUSE        (1 << 1)
+#       define RADEON_TCL_COMPUTE_SPECULAR       (1 << 2)
+#       define RADEON_TCL_FORCE_NAN_IF_COLOR_NAN (1 << 3)
+#       define RADEON_TCL_FORCE_INORDER_PROC     (1 << 4)
+#       define RADEON_TCL_TEX_INPUT_TEX_0        0
+#       define RADEON_TCL_TEX_INPUT_TEX_1        1
+#       define RADEON_TCL_TEX_INPUT_TEX_2        2
+#       define RADEON_TCL_TEX_INPUT_TEX_3        3
+#       define RADEON_TCL_TEX_COMPUTED_TEX_0     8
+#       define RADEON_TCL_TEX_COMPUTED_TEX_1     9
+#       define RADEON_TCL_TEX_COMPUTED_TEX_2     10
+#       define RADEON_TCL_TEX_COMPUTED_TEX_3     11
+#       define RADEON_TCL_TEX_0_OUTPUT_SHIFT     16
+#       define RADEON_TCL_TEX_1_OUTPUT_SHIFT     20
+#       define RADEON_TCL_TEX_2_OUTPUT_SHIFT     24
+#       define RADEON_TCL_TEX_3_OUTPUT_SHIFT     28
+
+#define RADEON_SE_TCL_PER_LIGHT_CTL_0       0x2270
+#       define RADEON_LIGHT_0_ENABLE               (1 <<  0)
+#       define RADEON_LIGHT_0_ENABLE_AMBIENT       (1 <<  1)
+#       define RADEON_LIGHT_0_ENABLE_SPECULAR      (1 <<  2)
+#       define RADEON_LIGHT_0_IS_LOCAL             (1 <<  3)
+#       define RADEON_LIGHT_0_IS_SPOT              (1 <<  4)
+#       define RADEON_LIGHT_0_DUAL_CONE            (1 <<  5)
+#       define RADEON_LIGHT_0_ENABLE_RANGE_ATTEN   (1 <<  6)
+#       define RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN (1 <<  7)
+#       define RADEON_LIGHT_0_SHIFT                0
+#       define RADEON_LIGHT_1_ENABLE               (1 << 16)
+#       define RADEON_LIGHT_1_ENABLE_AMBIENT       (1 << 17)
+#       define RADEON_LIGHT_1_ENABLE_SPECULAR      (1 << 18)
+#       define RADEON_LIGHT_1_IS_LOCAL             (1 << 19)
+#       define RADEON_LIGHT_1_IS_SPOT              (1 << 20)
+#       define RADEON_LIGHT_1_DUAL_CONE            (1 << 21)
+#       define RADEON_LIGHT_1_ENABLE_RANGE_ATTEN   (1 << 22)
+#       define RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN (1 << 23)
+#       define RADEON_LIGHT_1_SHIFT                16
+#define RADEON_SE_TCL_PER_LIGHT_CTL_1       0x2274
+#       define RADEON_LIGHT_2_SHIFT            0
+#       define RADEON_LIGHT_3_SHIFT            16
+#define RADEON_SE_TCL_PER_LIGHT_CTL_2       0x2278
+#       define RADEON_LIGHT_4_SHIFT            0
+#       define RADEON_LIGHT_5_SHIFT            16
+#define RADEON_SE_TCL_PER_LIGHT_CTL_3       0x227c
+#       define RADEON_LIGHT_6_SHIFT            0
+#       define RADEON_LIGHT_7_SHIFT            16
+
+#define RADEON_SE_TCL_SHININESS             0x2250
+
+#define RADEON_SE_TCL_TEXTURE_PROC_CTL      0x2268
+#       define RADEON_TEXGEN_TEXMAT_0_ENABLE      (1 << 0)
+#       define RADEON_TEXGEN_TEXMAT_1_ENABLE      (1 << 1)
+#       define RADEON_TEXGEN_TEXMAT_2_ENABLE      (1 << 2)
+#       define RADEON_TEXGEN_TEXMAT_3_ENABLE      (1 << 3)
+#       define RADEON_TEXMAT_0_ENABLE             (1 << 4)
+#       define RADEON_TEXMAT_1_ENABLE             (1 << 5)
+#       define RADEON_TEXMAT_2_ENABLE             (1 << 6)
+#       define RADEON_TEXMAT_3_ENABLE             (1 << 7)
+#       define RADEON_TEXGEN_INPUT_MASK           0xf
+#       define RADEON_TEXGEN_INPUT_TEXCOORD_0     0
+#       define RADEON_TEXGEN_INPUT_TEXCOORD_1     1
+#       define RADEON_TEXGEN_INPUT_TEXCOORD_2     2
+#       define RADEON_TEXGEN_INPUT_TEXCOORD_3     3
+#       define RADEON_TEXGEN_INPUT_OBJ            4
+#       define RADEON_TEXGEN_INPUT_EYE            5
+#       define RADEON_TEXGEN_INPUT_EYE_NORMAL     6
+#       define RADEON_TEXGEN_INPUT_EYE_REFLECT    7
+#       define RADEON_TEXGEN_INPUT_EYE_NORMALIZED 8
+#       define RADEON_TEXGEN_0_INPUT_SHIFT        16
+#       define RADEON_TEXGEN_1_INPUT_SHIFT        20
+#       define RADEON_TEXGEN_2_INPUT_SHIFT        24
+#       define RADEON_TEXGEN_3_INPUT_SHIFT        28
+
+#define RADEON_SE_TCL_UCP_VERT_BLEND_CTL    0x2264
+#       define RADEON_UCP_IN_CLIP_SPACE            (1 <<  0)
+#       define RADEON_UCP_IN_MODEL_SPACE           (1 <<  1)
+#       define RADEON_UCP_ENABLE_0                 (1 <<  2)
+#       define RADEON_UCP_ENABLE_1                 (1 <<  3)
+#       define RADEON_UCP_ENABLE_2                 (1 <<  4)
+#       define RADEON_UCP_ENABLE_3                 (1 <<  5)
+#       define RADEON_UCP_ENABLE_4                 (1 <<  6)
+#       define RADEON_UCP_ENABLE_5                 (1 <<  7)
+#       define RADEON_TCL_FOG_MASK                 (3 <<  8)
+#       define RADEON_TCL_FOG_DISABLE              (0 <<  8)
+#       define RADEON_TCL_FOG_EXP                  (1 <<  8)
+#       define RADEON_TCL_FOG_EXP2                 (2 <<  8)
+#       define RADEON_TCL_FOG_LINEAR               (3 <<  8)
+#       define RADEON_RNG_BASED_FOG                (1 << 10)
+#       define RADEON_LIGHT_TWOSIDE                (1 << 11)
+#       define RADEON_BLEND_OP_COUNT_MASK          (7 << 12)
+#       define RADEON_BLEND_OP_COUNT_SHIFT         12
+#       define RADEON_POSITION_BLEND_OP_ENABLE     (1 << 16)
+#       define RADEON_NORMAL_BLEND_OP_ENABLE       (1 << 17)
+#       define RADEON_VERTEX_BLEND_SRC_0_PRIMARY   (1 << 18)
+#       define RADEON_VERTEX_BLEND_SRC_0_SECONDARY (1 << 18)
+#       define RADEON_VERTEX_BLEND_SRC_1_PRIMARY   (1 << 19)
+#       define RADEON_VERTEX_BLEND_SRC_1_SECONDARY (1 << 19)
+#       define RADEON_VERTEX_BLEND_SRC_2_PRIMARY   (1 << 20)
+#       define RADEON_VERTEX_BLEND_SRC_2_SECONDARY (1 << 20)
+#       define RADEON_VERTEX_BLEND_SRC_3_PRIMARY   (1 << 21)
+#       define RADEON_VERTEX_BLEND_SRC_3_SECONDARY (1 << 21)
+#       define RADEON_VERTEX_BLEND_WGT_MINUS_ONE   (1 << 22)
+#       define RADEON_CULL_FRONT_IS_CW             (0 << 28)
+#       define RADEON_CULL_FRONT_IS_CCW            (1 << 28)
+#       define RADEON_CULL_FRONT                   (1 << 29)
+#       define RADEON_CULL_BACK                    (1 << 30)
+#       define RADEON_FORCE_W_TO_ONE               (1 << 31)
+
+#define RADEON_SE_VPORT_XSCALE              0x1d98
+#define RADEON_SE_VPORT_XOFFSET             0x1d9c
+#define RADEON_SE_VPORT_YSCALE              0x1da0
+#define RADEON_SE_VPORT_YOFFSET             0x1da4
+#define RADEON_SE_VPORT_ZSCALE              0x1da8
+#define RADEON_SE_VPORT_ZOFFSET             0x1dac
+#define RADEON_SE_ZBIAS_FACTOR              0x1db0
+#define RADEON_SE_ZBIAS_CONSTANT            0x1db4
+
+#define RADEON_SE_VTX_FMT                   0x2080
+#       define RADEON_SE_VTX_FMT_XY         0x00000000
+#       define RADEON_SE_VTX_FMT_W0         0x00000001
+#       define RADEON_SE_VTX_FMT_FPCOLOR    0x00000002
+#       define RADEON_SE_VTX_FMT_FPALPHA    0x00000004
+#       define RADEON_SE_VTX_FMT_PKCOLOR    0x00000008
+#       define RADEON_SE_VTX_FMT_FPSPEC     0x00000010
+#       define RADEON_SE_VTX_FMT_FPFOG      0x00000020
+#       define RADEON_SE_VTX_FMT_PKSPEC     0x00000040
+#       define RADEON_SE_VTX_FMT_ST0        0x00000080
+#       define RADEON_SE_VTX_FMT_ST1        0x00000100
+#       define RADEON_SE_VTX_FMT_Q1         0x00000200
+#       define RADEON_SE_VTX_FMT_ST2        0x00000400
+#       define RADEON_SE_VTX_FMT_Q2         0x00000800
+#       define RADEON_SE_VTX_FMT_ST3        0x00001000
+#       define RADEON_SE_VTX_FMT_Q3         0x00002000
+#       define RADEON_SE_VTX_FMT_Q0         0x00004000
+#       define RADEON_SE_VTX_FMT_BLND_WEIGHT_CNT_MASK  0x00038000
+#       define RADEON_SE_VTX_FMT_N0         0x00040000
+#       define RADEON_SE_VTX_FMT_XY1        0x08000000
+#       define RADEON_SE_VTX_FMT_Z1         0x10000000
+#       define RADEON_SE_VTX_FMT_W1         0x20000000
+#       define RADEON_SE_VTX_FMT_N1         0x40000000
+#       define RADEON_SE_VTX_FMT_Z          0x80000000
+
+#define RADEON_SE_VF_CNTL                             0x2084
+#       define RADEON_VF_PRIM_TYPE_POINT_LIST         1
+#       define RADEON_VF_PRIM_TYPE_LINE_LIST          2
+#       define RADEON_VF_PRIM_TYPE_LINE_STRIP         3
+#       define RADEON_VF_PRIM_TYPE_TRIANGLE_LIST      4
+#       define RADEON_VF_PRIM_TYPE_TRIANGLE_FAN       5
+#       define RADEON_VF_PRIM_TYPE_TRIANGLE_STRIP     6
+#       define RADEON_VF_PRIM_TYPE_TRIANGLE_FLAG      7
+#       define RADEON_VF_PRIM_TYPE_RECTANGLE_LIST     8
+#       define RADEON_VF_PRIM_TYPE_POINT_LIST_3       9
+#       define RADEON_VF_PRIM_TYPE_LINE_LIST_3        10
+#       define RADEON_VF_PRIM_TYPE_SPIRIT_LIST        11
+#       define RADEON_VF_PRIM_TYPE_LINE_LOOP          12
+#       define RADEON_VF_PRIM_TYPE_QUAD_LIST          13
+#       define RADEON_VF_PRIM_TYPE_QUAD_STRIP         14
+#       define RADEON_VF_PRIM_TYPE_POLYGON            15
+#       define RADEON_VF_PRIM_WALK_STATE              (0<<4)
+#       define RADEON_VF_PRIM_WALK_INDEX              (1<<4)
+#       define RADEON_VF_PRIM_WALK_LIST               (2<<4)
+#       define RADEON_VF_PRIM_WALK_DATA               (3<<4)
+#       define RADEON_VF_COLOR_ORDER_RGBA             (1<<6)
+#       define RADEON_VF_RADEON_MODE                  (1<<8)
+#       define RADEON_VF_TCL_OUTPUT_CTL_ENA           (1<<9)
+#       define RADEON_VF_PROG_STREAM_ENA              (1<<10)
+#       define RADEON_VF_INDEX_SIZE_SHIFT             11
+#       define RADEON_VF_NUM_VERTICES_SHIFT           16
+
+#define RADEON_SE_PORT_DATA0			0x2000
+
+#define R200_SE_VAP_CNTL			0x2080
+#       define R200_VAP_TCL_ENABLE		0x00000001
+#       define R200_VAP_SINGLE_BUF_STATE_ENABLE	0x00000010
+#       define R200_VAP_FORCE_W_TO_ONE		0x00010000
+#       define R200_VAP_D3D_TEX_DEFAULT		0x00020000
+#       define R200_VAP_VF_MAX_VTX_NUM__SHIFT	18
+#       define R200_VAP_VF_MAX_VTX_NUM		(9 << 18)
+#       define R200_VAP_DX_CLIP_SPACE_DEF	0x00400000
+#define R200_VF_MAX_VTX_INDX			0x210c
+#define R200_VF_MIN_VTX_INDX			0x2110
+#define R200_SE_VTE_CNTL			0x20b0
+#       define R200_VPORT_X_SCALE_ENA			0x00000001
+#       define R200_VPORT_X_OFFSET_ENA			0x00000002
+#       define R200_VPORT_Y_SCALE_ENA			0x00000004
+#       define R200_VPORT_Y_OFFSET_ENA			0x00000008
+#       define R200_VPORT_Z_SCALE_ENA			0x00000010
+#       define R200_VPORT_Z_OFFSET_ENA			0x00000020
+#       define R200_VTX_XY_FMT				0x00000100
+#       define R200_VTX_Z_FMT				0x00000200
+#       define R200_VTX_W0_FMT				0x00000400
+#       define R200_VTX_W0_NORMALIZE			0x00000800
+#       define R200_VTX_ST_DENORMALIZED		0x00001000
+#define R200_SE_VAP_CNTL_STATUS			0x2140
+#       define R200_VC_NO_SWAP			(0 << 0)
+#       define R200_VC_16BIT_SWAP		(1 << 0)
+#       define R200_VC_32BIT_SWAP		(2 << 0)
+#define R200_PP_TXFILTER_0			0x2c00
+#define R200_PP_TXFILTER_1			0x2c20
+#define R200_PP_TXFILTER_2			0x2c40
+#define R200_PP_TXFILTER_3			0x2c60
+#define R200_PP_TXFILTER_4			0x2c80
+#define R200_PP_TXFILTER_5			0x2ca0
+#       define R200_MAG_FILTER_NEAREST		(0  <<  0)
+#       define R200_MAG_FILTER_LINEAR		(1  <<  0)
+#       define R200_MAG_FILTER_MASK		(1  <<  0)
+#       define R200_MIN_FILTER_NEAREST		(0  <<  1)
+#       define R200_MIN_FILTER_LINEAR		(1  <<  1)
+#       define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2  <<  1)
+#       define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3  <<  1)
+#       define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6  <<  1)
+#       define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7  <<  1)
+#       define R200_MIN_FILTER_ANISO_NEAREST	(8  <<  1)
+#       define R200_MIN_FILTER_ANISO_LINEAR	(9  <<  1)
+#       define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 <<  1)
+#       define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 <<  1)
+#       define R200_MIN_FILTER_MASK		(15 <<  1)
+#       define R200_MAX_ANISO_1_TO_1		(0  <<  5)
+#       define R200_MAX_ANISO_2_TO_1		(1  <<  5)
+#       define R200_MAX_ANISO_4_TO_1		(2  <<  5)
+#       define R200_MAX_ANISO_8_TO_1		(3  <<  5)
+#       define R200_MAX_ANISO_16_TO_1		(4  <<  5)
+#       define R200_MAX_ANISO_MASK		(7  <<  5)
+#       define R200_MAX_MIP_LEVEL_MASK		(0x0f << 16)
+#       define R200_MAX_MIP_LEVEL_SHIFT		16
+#       define R200_YUV_TO_RGB			(1  << 20)
+#       define R200_YUV_TEMPERATURE_COOL	(0  << 21)
+#       define R200_YUV_TEMPERATURE_HOT		(1  << 21)
+#       define R200_YUV_TEMPERATURE_MASK	(1  << 21)
+#       define R200_WRAPEN_S			(1  << 22)
+#       define R200_CLAMP_S_WRAP		(0  << 23)
+#       define R200_CLAMP_S_MIRROR		(1  << 23)
+#       define R200_CLAMP_S_CLAMP_LAST		(2  << 23)
+#       define R200_CLAMP_S_MIRROR_CLAMP_LAST	(3  << 23)
+#       define R200_CLAMP_S_CLAMP_BORDER	(4  << 23)
+#       define R200_CLAMP_S_MIRROR_CLAMP_BORDER	(5  << 23)
+#       define R200_CLAMP_S_CLAMP_GL		(6  << 23)
+#       define R200_CLAMP_S_MIRROR_CLAMP_GL	(7  << 23)
+#       define R200_CLAMP_S_MASK		(7  << 23)
+#       define R200_WRAPEN_T			(1  << 26)
+#       define R200_CLAMP_T_WRAP		(0  << 27)
+#       define R200_CLAMP_T_MIRROR		(1  << 27)
+#       define R200_CLAMP_T_CLAMP_LAST		(2  << 27)
+#       define R200_CLAMP_T_MIRROR_CLAMP_LAST	(3  << 27)
+#       define R200_CLAMP_T_CLAMP_BORDER	(4  << 27)
+#       define R200_CLAMP_T_MIRROR_CLAMP_BORDER	(5  << 27)
+#       define R200_CLAMP_T_CLAMP_GL		(6  << 27)
+#       define R200_CLAMP_T_MIRROR_CLAMP_GL	(7  << 27)
+#       define R200_CLAMP_T_MASK		(7  << 27)
+#       define R200_KILL_LT_ZERO		(1  << 30)
+#       define R200_BORDER_MODE_OGL		(0  << 31)
+#       define R200_BORDER_MODE_D3D		(1  << 31)
+#define R200_PP_TXFORMAT_0			0x2c04
+#define R200_PP_TXFORMAT_1			0x2c24
+#define R200_PP_TXFORMAT_2			0x2c44
+#define R200_PP_TXFORMAT_3			0x2c64
+#define R200_PP_TXFORMAT_4			0x2c84
+#define R200_PP_TXFORMAT_5			0x2ca4
+#       define R200_TXFORMAT_I8			(0 << 0)
+#       define R200_TXFORMAT_AI88		(1 << 0)
+#       define R200_TXFORMAT_RGB332		(2 << 0)
+#       define R200_TXFORMAT_ARGB1555		(3 << 0)
+#       define R200_TXFORMAT_RGB565		(4 << 0)
+#       define R200_TXFORMAT_ARGB4444		(5 << 0)
+#       define R200_TXFORMAT_ARGB8888		(6 << 0)
+#       define R200_TXFORMAT_RGBA8888		(7 << 0)
+#       define R200_TXFORMAT_Y8			(8 << 0)
+#       define R200_TXFORMAT_AVYU4444		(9 << 0)
+#       define R200_TXFORMAT_VYUY422		(10 << 0)
+#       define R200_TXFORMAT_YVYU422		(11 << 0)
+#       define R200_TXFORMAT_DXT1		(12 << 0)
+#       define R200_TXFORMAT_DXT23		(14 << 0)
+#       define R200_TXFORMAT_DXT45		(15 << 0)
+#       define R200_TXFORMAT_ABGR8888		(22 << 0)
+#       define R200_TXFORMAT_FORMAT_MASK	(31 <<	0)
+#       define R200_TXFORMAT_FORMAT_SHIFT	0
+#       define R200_TXFORMAT_ALPHA_IN_MAP	(1 << 6)
+#       define R200_TXFORMAT_NON_POWER2		(1 << 7)
+#       define R200_TXFORMAT_WIDTH_MASK		(15 <<	8)
+#       define R200_TXFORMAT_WIDTH_SHIFT	8
+#       define R200_TXFORMAT_HEIGHT_MASK	(15 << 12)
+#       define R200_TXFORMAT_HEIGHT_SHIFT	12
+#       define R200_TXFORMAT_F5_WIDTH_MASK	(15 << 16)	/* cube face 5 */
+#       define R200_TXFORMAT_F5_WIDTH_SHIFT	16
+#       define R200_TXFORMAT_F5_HEIGHT_MASK	(15 << 20)
+#       define R200_TXFORMAT_F5_HEIGHT_SHIFT	20
+#       define R200_TXFORMAT_ST_ROUTE_STQ0	(0 << 24)
+#       define R200_TXFORMAT_ST_ROUTE_STQ1	(1 << 24)
+#       define R200_TXFORMAT_ST_ROUTE_STQ2	(2 << 24)
+#       define R200_TXFORMAT_ST_ROUTE_STQ3	(3 << 24)
+#       define R200_TXFORMAT_ST_ROUTE_STQ4	(4 << 24)
+#       define R200_TXFORMAT_ST_ROUTE_STQ5	(5 << 24)
+#       define R200_TXFORMAT_ST_ROUTE_MASK	(7 << 24)
+#       define R200_TXFORMAT_ST_ROUTE_SHIFT	24
+#       define R200_TXFORMAT_ALPHA_MASK_ENABLE	(1 << 28)
+#       define R200_TXFORMAT_CHROMA_KEY_ENABLE	(1 << 29)
+#       define R200_TXFORMAT_CUBIC_MAP_ENABLE		(1 << 30)
+#define R200_PP_TXFORMAT_X_0                    0x2c08
+#define R200_PP_TXFORMAT_X_1                    0x2c28
+#define R200_PP_TXFORMAT_X_2                    0x2c48
+#define R200_PP_TXFORMAT_X_3                    0x2c68
+#define R200_PP_TXFORMAT_X_4                    0x2c88
+#define R200_PP_TXFORMAT_X_5                    0x2ca8
+
+#define R200_PP_TXSIZE_0			0x2c0c /* NPOT only */
+#define R200_PP_TXSIZE_1			0x2c2c /* NPOT only */
+#define R200_PP_TXSIZE_2			0x2c4c /* NPOT only */
+#define R200_PP_TXSIZE_3			0x2c6c /* NPOT only */
+#define R200_PP_TXSIZE_4			0x2c8c /* NPOT only */
+#define R200_PP_TXSIZE_5			0x2cac /* NPOT only */
+
+#define R200_PP_TXPITCH_0                       0x2c10 /* NPOT only */
+#define R200_PP_TXPITCH_1			0x2c30 /* NPOT only */
+#define R200_PP_TXPITCH_2			0x2c50 /* NPOT only */
+#define R200_PP_TXPITCH_3			0x2c70 /* NPOT only */
+#define R200_PP_TXPITCH_4			0x2c90 /* NPOT only */
+#define R200_PP_TXPITCH_5			0x2cb0 /* NPOT only */
+
+#define R200_PP_TXOFFSET_0			0x2d00
+#       define R200_TXO_ENDIAN_NO_SWAP		(0 << 0)
+#       define R200_TXO_ENDIAN_BYTE_SWAP	(1 << 0)
+#       define R200_TXO_ENDIAN_WORD_SWAP	(2 << 0)
+#       define R200_TXO_ENDIAN_HALFDW_SWAP	(3 << 0)
+#       define R200_TXO_MACRO_LINEAR		(0 << 2)
+#       define R200_TXO_MACRO_TILE		(1 << 2)
+#       define R200_TXO_MICRO_LINEAR		(0 << 3)
+#       define R200_TXO_MICRO_TILE		(1 << 3)
+#       define R200_TXO_OFFSET_MASK		0xffffffe0
+#       define R200_TXO_OFFSET_SHIFT		5
+#define R200_PP_TXOFFSET_1			0x2d18
+#define R200_PP_TXOFFSET_2			0x2d30
+#define R200_PP_TXOFFSET_3			0x2d48
+#define R200_PP_TXOFFSET_4			0x2d60
+#define R200_PP_TXOFFSET_5			0x2d78
+
+#define R200_PP_TFACTOR_0			0x2ee0
+#define R200_PP_TFACTOR_1			0x2ee4
+#define R200_PP_TFACTOR_2			0x2ee8
+#define R200_PP_TFACTOR_3			0x2eec
+#define R200_PP_TFACTOR_4			0x2ef0
+#define R200_PP_TFACTOR_5			0x2ef4
+
+#define R200_PP_TXCBLEND_0			0x2f00
+#       define R200_TXC_ARG_A_ZERO		(0)
+#       define R200_TXC_ARG_A_CURRENT_COLOR	(2)
+#       define R200_TXC_ARG_A_CURRENT_ALPHA	(3)
+#       define R200_TXC_ARG_A_DIFFUSE_COLOR	(4)
+#       define R200_TXC_ARG_A_DIFFUSE_ALPHA	(5)
+#       define R200_TXC_ARG_A_SPECULAR_COLOR	(6)
+#       define R200_TXC_ARG_A_SPECULAR_ALPHA	(7)
+#       define R200_TXC_ARG_A_TFACTOR_COLOR	(8)
+#       define R200_TXC_ARG_A_TFACTOR_ALPHA	(9)
+#       define R200_TXC_ARG_A_R0_COLOR		(10)
+#       define R200_TXC_ARG_A_R0_ALPHA		(11)
+#       define R200_TXC_ARG_A_R1_COLOR		(12)
+#       define R200_TXC_ARG_A_R1_ALPHA		(13)
+#       define R200_TXC_ARG_A_R2_COLOR		(14)
+#       define R200_TXC_ARG_A_R2_ALPHA		(15)
+#       define R200_TXC_ARG_A_R3_COLOR		(16)
+#       define R200_TXC_ARG_A_R3_ALPHA		(17)
+#       define R200_TXC_ARG_A_R4_COLOR		(18)
+#       define R200_TXC_ARG_A_R4_ALPHA		(19)
+#       define R200_TXC_ARG_A_R5_COLOR		(20)
+#       define R200_TXC_ARG_A_R5_ALPHA		(21)
+#       define R200_TXC_ARG_A_TFACTOR1_COLOR	(26)
+#       define R200_TXC_ARG_A_TFACTOR1_ALPHA	(27)
+#       define R200_TXC_ARG_A_MASK		(31 << 0)
+#       define R200_TXC_ARG_A_SHIFT		0
+#       define R200_TXC_ARG_B_ZERO		(0 << 5)
+#       define R200_TXC_ARG_B_CURRENT_COLOR	(2 << 5)
+#       define R200_TXC_ARG_B_CURRENT_ALPHA	(3 << 5)
+#       define R200_TXC_ARG_B_DIFFUSE_COLOR	(4 << 5)
+#       define R200_TXC_ARG_B_DIFFUSE_ALPHA	(5 << 5)
+#       define R200_TXC_ARG_B_SPECULAR_COLOR	(6 << 5)
+#       define R200_TXC_ARG_B_SPECULAR_ALPHA	(7 << 5)
+#       define R200_TXC_ARG_B_TFACTOR_COLOR	(8 << 5)
+#       define R200_TXC_ARG_B_TFACTOR_ALPHA	(9 << 5)
+#       define R200_TXC_ARG_B_R0_COLOR		(10 << 5)
+#       define R200_TXC_ARG_B_R0_ALPHA		(11 << 5)
+#       define R200_TXC_ARG_B_R1_COLOR		(12 << 5)
+#       define R200_TXC_ARG_B_R1_ALPHA		(13 << 5)
+#       define R200_TXC_ARG_B_R2_COLOR		(14 << 5)
+#       define R200_TXC_ARG_B_R2_ALPHA		(15 << 5)
+#       define R200_TXC_ARG_B_R3_COLOR		(16 << 5)
+#       define R200_TXC_ARG_B_R3_ALPHA		(17 << 5)
+#       define R200_TXC_ARG_B_R4_COLOR		(18 << 5)
+#       define R200_TXC_ARG_B_R4_ALPHA		(19 << 5)
+#       define R200_TXC_ARG_B_R5_COLOR		(20 << 5)
+#       define R200_TXC_ARG_B_R5_ALPHA		(21 << 5)
+#       define R200_TXC_ARG_B_TFACTOR1_COLOR	(26 << 5)
+#       define R200_TXC_ARG_B_TFACTOR1_ALPHA	(27 << 5)
+#       define R200_TXC_ARG_B_MASK		(31 << 5)
+#       define R200_TXC_ARG_B_SHIFT		5
+#       define R200_TXC_ARG_C_ZERO		(0 << 10)
+#       define R200_TXC_ARG_C_CURRENT_COLOR	(2 << 10)
+#       define R200_TXC_ARG_C_CURRENT_ALPHA	(3 << 10)
+#       define R200_TXC_ARG_C_DIFFUSE_COLOR	(4 << 10)
+#       define R200_TXC_ARG_C_DIFFUSE_ALPHA	(5 << 10)
+#       define R200_TXC_ARG_C_SPECULAR_COLOR	(6 << 10)
+#       define R200_TXC_ARG_C_SPECULAR_ALPHA	(7 << 10)
+#       define R200_TXC_ARG_C_TFACTOR_COLOR	(8 << 10)
+#       define R200_TXC_ARG_C_TFACTOR_ALPHA	(9 << 10)
+#       define R200_TXC_ARG_C_R0_COLOR		(10 << 10)
+#       define R200_TXC_ARG_C_R0_ALPHA		(11 << 10)
+#       define R200_TXC_ARG_C_R1_COLOR		(12 << 10)
+#       define R200_TXC_ARG_C_R1_ALPHA		(13 << 10)
+#       define R200_TXC_ARG_C_R2_COLOR		(14 << 10)
+#       define R200_TXC_ARG_C_R2_ALPHA		(15 << 10)
+#       define R200_TXC_ARG_C_R3_COLOR		(16 << 10)
+#       define R200_TXC_ARG_C_R3_ALPHA		(17 << 10)
+#       define R200_TXC_ARG_C_R4_COLOR		(18 << 10)
+#       define R200_TXC_ARG_C_R4_ALPHA		(19 << 10)
+#       define R200_TXC_ARG_C_R5_COLOR		(20 << 10)
+#       define R200_TXC_ARG_C_R5_ALPHA		(21 << 10)
+#       define R200_TXC_ARG_C_TFACTOR1_COLOR	(26 << 10)
+#       define R200_TXC_ARG_C_TFACTOR1_ALPHA	(27 << 10)
+#       define R200_TXC_ARG_C_MASK		(31 << 10)
+#       define R200_TXC_ARG_C_SHIFT		10
+#       define R200_TXC_COMP_ARG_A		(1 << 16)
+#       define R200_TXC_COMP_ARG_A_SHIFT	(16)
+#       define R200_TXC_BIAS_ARG_A		(1 << 17)
+#       define R200_TXC_SCALE_ARG_A		(1 << 18)
+#       define R200_TXC_NEG_ARG_A		(1 << 19)
+#       define R200_TXC_COMP_ARG_B		(1 << 20)
+#       define R200_TXC_COMP_ARG_B_SHIFT	(20)
+#       define R200_TXC_BIAS_ARG_B		(1 << 21)
+#       define R200_TXC_SCALE_ARG_B		(1 << 22)
+#       define R200_TXC_NEG_ARG_B		(1 << 23)
+#       define R200_TXC_COMP_ARG_C		(1 << 24)
+#       define R200_TXC_COMP_ARG_C_SHIFT	(24)
+#       define R200_TXC_BIAS_ARG_C		(1 << 25)
+#       define R200_TXC_SCALE_ARG_C		(1 << 26)
+#       define R200_TXC_NEG_ARG_C		(1 << 27)
+#       define R200_TXC_OP_MADD			(0 << 28)
+#       define R200_TXC_OP_CND0			(2 << 28)
+#       define R200_TXC_OP_LERP			(3 << 28)
+#       define R200_TXC_OP_DOT3			(4 << 28)
+#       define R200_TXC_OP_DOT4			(5 << 28)
+#       define R200_TXC_OP_CONDITIONAL		(6 << 28)
+#       define R200_TXC_OP_DOT2_ADD		(7 << 28)
+#       define R200_TXC_OP_MASK			(7 << 28)
+#define R200_PP_TXCBLEND2_0		0x2f04
+#       define R200_TXC_TFACTOR_SEL_SHIFT	0
+#       define R200_TXC_TFACTOR_SEL_MASK	0x7
+#       define R200_TXC_TFACTOR1_SEL_SHIFT	4
+#       define R200_TXC_TFACTOR1_SEL_MASK	(0x7 << 4)
+#       define R200_TXC_SCALE_SHIFT		8
+#       define R200_TXC_SCALE_MASK		(7 << 8)
+#       define R200_TXC_SCALE_1X		(0 << 8)
+#       define R200_TXC_SCALE_2X		(1 << 8)
+#       define R200_TXC_SCALE_4X		(2 << 8)
+#       define R200_TXC_SCALE_8X		(3 << 8)
+#       define R200_TXC_SCALE_INV2		(5 << 8)
+#       define R200_TXC_SCALE_INV4		(6 << 8)
+#       define R200_TXC_SCALE_INV8		(7 << 8)
+#       define R200_TXC_CLAMP_SHIFT		12
+#       define R200_TXC_CLAMP_MASK		(3 << 12)
+#       define R200_TXC_CLAMP_WRAP		(0 << 12)
+#       define R200_TXC_CLAMP_0_1		(1 << 12)
+#       define R200_TXC_CLAMP_8_8		(2 << 12)
+#       define R200_TXC_OUTPUT_REG_MASK		(7 << 16)
+#       define R200_TXC_OUTPUT_REG_NONE		(0 << 16)
+#       define R200_TXC_OUTPUT_REG_R0		(1 << 16)
+#       define R200_TXC_OUTPUT_REG_R1		(2 << 16)
+#       define R200_TXC_OUTPUT_REG_R2		(3 << 16)
+#       define R200_TXC_OUTPUT_REG_R3		(4 << 16)
+#       define R200_TXC_OUTPUT_REG_R4		(5 << 16)
+#       define R200_TXC_OUTPUT_REG_R5		(6 << 16)
+#       define R200_TXC_OUTPUT_MASK_MASK	(7 << 20)
+#       define R200_TXC_OUTPUT_MASK_RGB		(0 << 20)
+#       define R200_TXC_OUTPUT_MASK_RG		(1 << 20)
+#       define R200_TXC_OUTPUT_MASK_RB		(2 << 20)
+#       define R200_TXC_OUTPUT_MASK_R		(3 << 20)
+#       define R200_TXC_OUTPUT_MASK_GB		(4 << 20)
+#       define R200_TXC_OUTPUT_MASK_G		(5 << 20)
+#       define R200_TXC_OUTPUT_MASK_B		(6 << 20)
+#       define R200_TXC_OUTPUT_MASK_NONE	(7 << 20)
+#       define R200_TXC_REPL_NORMAL		0
+#       define R200_TXC_REPL_RED		1
+#       define R200_TXC_REPL_GREEN		2
+#       define R200_TXC_REPL_BLUE		3
+#       define R200_TXC_REPL_ARG_A_SHIFT	26
+#       define R200_TXC_REPL_ARG_A_MASK		(3 << 26)
+#       define R200_TXC_REPL_ARG_B_SHIFT	28
+#       define R200_TXC_REPL_ARG_B_MASK		(3 << 28)
+#       define R200_TXC_REPL_ARG_C_SHIFT	30
+#       define R200_TXC_REPL_ARG_C_MASK		(3 << 30)
+#define R200_PP_TXABLEND_0			0x2f08
+#       define R200_TXA_ARG_A_ZERO		(0)
+#       define R200_TXA_ARG_A_CURRENT_ALPHA	(2) /* guess */
+#       define R200_TXA_ARG_A_CURRENT_BLUE	(3) /* guess */
+#       define R200_TXA_ARG_A_DIFFUSE_ALPHA	(4)
+#       define R200_TXA_ARG_A_DIFFUSE_BLUE	(5)
+#       define R200_TXA_ARG_A_SPECULAR_ALPHA	(6)
+#       define R200_TXA_ARG_A_SPECULAR_BLUE	(7)
+#       define R200_TXA_ARG_A_TFACTOR_ALPHA	(8)
+#       define R200_TXA_ARG_A_TFACTOR_BLUE	(9)
+#       define R200_TXA_ARG_A_R0_ALPHA		(10)
+#       define R200_TXA_ARG_A_R0_BLUE		(11)
+#       define R200_TXA_ARG_A_R1_ALPHA		(12)
+#       define R200_TXA_ARG_A_R1_BLUE		(13)
+#       define R200_TXA_ARG_A_R2_ALPHA		(14)
+#       define R200_TXA_ARG_A_R2_BLUE		(15)
+#       define R200_TXA_ARG_A_R3_ALPHA		(16)
+#       define R200_TXA_ARG_A_R3_BLUE		(17)
+#       define R200_TXA_ARG_A_R4_ALPHA		(18)
+#       define R200_TXA_ARG_A_R4_BLUE		(19)
+#       define R200_TXA_ARG_A_R5_ALPHA		(20)
+#       define R200_TXA_ARG_A_R5_BLUE		(21)
+#       define R200_TXA_ARG_A_TFACTOR1_ALPHA	(26)
+#       define R200_TXA_ARG_A_TFACTOR1_BLUE	(27)
+#       define R200_TXA_ARG_A_MASK		(31 << 0)
+#       define R200_TXA_ARG_A_SHIFT		0
+#       define R200_TXA_ARG_B_ZERO		(0 << 5)
+#       define R200_TXA_ARG_B_CURRENT_ALPHA	(2 << 5) /* guess */
+#       define R200_TXA_ARG_B_CURRENT_BLUE	(3 << 5) /* guess */
+#       define R200_TXA_ARG_B_DIFFUSE_ALPHA	(4 << 5)
+#       define R200_TXA_ARG_B_DIFFUSE_BLUE	(5 << 5)
+#       define R200_TXA_ARG_B_SPECULAR_ALPHA	(6 << 5)
+#       define R200_TXA_ARG_B_SPECULAR_BLUE	(7 << 5)
+#       define R200_TXA_ARG_B_TFACTOR_ALPHA	(8 << 5)
+#       define R200_TXA_ARG_B_TFACTOR_BLUE	(9 << 5)
+#       define R200_TXA_ARG_B_R0_ALPHA		(10 << 5)
+#       define R200_TXA_ARG_B_R0_BLUE		(11 << 5)
+#       define R200_TXA_ARG_B_R1_ALPHA		(12 << 5)
+#       define R200_TXA_ARG_B_R1_BLUE		(13 << 5)
+#       define R200_TXA_ARG_B_R2_ALPHA		(14 << 5)
+#       define R200_TXA_ARG_B_R2_BLUE		(15 << 5)
+#       define R200_TXA_ARG_B_R3_ALPHA		(16 << 5)
+#       define R200_TXA_ARG_B_R3_BLUE		(17 << 5)
+#       define R200_TXA_ARG_B_R4_ALPHA		(18 << 5)
+#       define R200_TXA_ARG_B_R4_BLUE		(19 << 5)
+#       define R200_TXA_ARG_B_R5_ALPHA		(20 << 5)
+#       define R200_TXA_ARG_B_R5_BLUE		(21 << 5)
+#       define R200_TXA_ARG_B_TFACTOR1_ALPHA	(26 << 5)
+#       define R200_TXA_ARG_B_TFACTOR1_BLUE	(27 << 5)
+#       define R200_TXA_ARG_B_MASK		(31 << 5)
+#       define R200_TXA_ARG_B_SHIFT			5
+#       define R200_TXA_ARG_C_ZERO		(0 << 10)
+#       define R200_TXA_ARG_C_CURRENT_ALPHA	(2 << 10) /* guess */
+#       define R200_TXA_ARG_C_CURRENT_BLUE	(3 << 10) /* guess */
+#       define R200_TXA_ARG_C_DIFFUSE_ALPHA	(4 << 10)
+#       define R200_TXA_ARG_C_DIFFUSE_BLUE	(5 << 10)
+#       define R200_TXA_ARG_C_SPECULAR_ALPHA	(6 << 10)
+#       define R200_TXA_ARG_C_SPECULAR_BLUE	(7 << 10)
+#       define R200_TXA_ARG_C_TFACTOR_ALPHA	(8 << 10)
+#       define R200_TXA_ARG_C_TFACTOR_BLUE	(9 << 10)
+#       define R200_TXA_ARG_C_R0_ALPHA		(10 << 10)
+#       define R200_TXA_ARG_C_R0_BLUE		(11 << 10)
+#       define R200_TXA_ARG_C_R1_ALPHA		(12 << 10)
+#       define R200_TXA_ARG_C_R1_BLUE		(13 << 10)
+#       define R200_TXA_ARG_C_R2_ALPHA		(14 << 10)
+#       define R200_TXA_ARG_C_R2_BLUE		(15 << 10)
+#       define R200_TXA_ARG_C_R3_ALPHA		(16 << 10)
+#       define R200_TXA_ARG_C_R3_BLUE		(17 << 10)
+#       define R200_TXA_ARG_C_R4_ALPHA		(18 << 10)
+#       define R200_TXA_ARG_C_R4_BLUE		(19 << 10)
+#       define R200_TXA_ARG_C_R5_ALPHA		(20 << 10)
+#       define R200_TXA_ARG_C_R5_BLUE		(21 << 10)
+#       define R200_TXA_ARG_C_TFACTOR1_ALPHA	(26 << 10)
+#       define R200_TXA_ARG_C_TFACTOR1_BLUE	(27 << 10)
+#       define R200_TXA_ARG_C_MASK		(31 << 10)
+#       define R200_TXA_ARG_C_SHIFT		10
+#       define R200_TXA_COMP_ARG_A		(1 << 16)
+#       define R200_TXA_COMP_ARG_A_SHIFT	(16)
+#       define R200_TXA_BIAS_ARG_A		(1 << 17)
+#       define R200_TXA_SCALE_ARG_A		(1 << 18)
+#       define R200_TXA_NEG_ARG_A		(1 << 19)
+#       define R200_TXA_COMP_ARG_B		(1 << 20)
+#       define R200_TXA_COMP_ARG_B_SHIFT	(20)
+#       define R200_TXA_BIAS_ARG_B		(1 << 21)
+#       define R200_TXA_SCALE_ARG_B		(1 << 22)
+#       define R200_TXA_NEG_ARG_B		(1 << 23)
+#       define R200_TXA_COMP_ARG_C		(1 << 24)
+#       define R200_TXA_COMP_ARG_C_SHIFT	(24)
+#       define R200_TXA_BIAS_ARG_C		(1 << 25)
+#       define R200_TXA_SCALE_ARG_C		(1 << 26)
+#       define R200_TXA_NEG_ARG_C		(1 << 27)
+#       define R200_TXA_OP_MADD			(0 << 28)
+#       define R200_TXA_OP_CND0			(2 << 28)
+#       define R200_TXA_OP_LERP			(3 << 28)
+#       define R200_TXA_OP_CONDITIONAL		(6 << 28)
+#       define R200_TXA_OP_MASK			(7 << 28)
+#define R200_PP_TXABLEND2_0			0x2f0c
+#       define R200_TXA_TFACTOR_SEL_SHIFT	0
+#       define R200_TXA_TFACTOR_SEL_MASK	0x7
+#       define R200_TXA_TFACTOR1_SEL_SHIFT	4
+#       define R200_TXA_TFACTOR1_SEL_MASK	(0x7 << 4)
+#       define R200_TXA_SCALE_SHIFT		8
+#       define R200_TXA_SCALE_MASK		(7 << 8)
+#       define R200_TXA_SCALE_1X		(0 << 8)
+#       define R200_TXA_SCALE_2X		(1 << 8)
+#       define R200_TXA_SCALE_4X		(2 << 8)
+#       define R200_TXA_SCALE_8X		(3 << 8)
+#       define R200_TXA_SCALE_INV2		(5 << 8)
+#       define R200_TXA_SCALE_INV4		(6 << 8)
+#       define R200_TXA_SCALE_INV8		(7 << 8)
+#       define R200_TXA_CLAMP_SHIFT		12
+#       define R200_TXA_CLAMP_MASK		(3 << 12)
+#       define R200_TXA_CLAMP_WRAP		(0 << 12)
+#       define R200_TXA_CLAMP_0_1		(1 << 12)
+#       define R200_TXA_CLAMP_8_8		(2 << 12)
+#       define R200_TXA_OUTPUT_REG_MASK		(7 << 16)
+#       define R200_TXA_OUTPUT_REG_NONE		(0 << 16)
+#       define R200_TXA_OUTPUT_REG_R0		(1 << 16)
+#       define R200_TXA_OUTPUT_REG_R1		(2 << 16)
+#       define R200_TXA_OUTPUT_REG_R2		(3 << 16)
+#       define R200_TXA_OUTPUT_REG_R3		(4 << 16)
+#       define R200_TXA_OUTPUT_REG_R4		(5 << 16)
+#       define R200_TXA_OUTPUT_REG_R5		(6 << 16)
+#       define R200_TXA_DOT_ALPHA		(1 << 20)
+#       define R200_TXA_REPL_NORMAL		0
+#       define R200_TXA_REPL_RED		1
+#       define R200_TXA_REPL_GREEN		2
+#       define R200_TXA_REPL_ARG_A_SHIFT	26
+#       define R200_TXA_REPL_ARG_A_MASK		(3 << 26)
+#       define R200_TXA_REPL_ARG_B_SHIFT	28
+#       define R200_TXA_REPL_ARG_B_MASK		(3 << 28)
+#       define R200_TXA_REPL_ARG_C_SHIFT	30
+#       define R200_TXA_REPL_ARG_C_MASK		(3 << 30)
+
+#define R200_SE_VTX_FMT_0			0x2088
+#       define R200_VTX_XY			0 /* always have xy */
+#       define R200_VTX_Z0			(1<<0)
+#       define R200_VTX_W0			(1<<1)
+#       define R200_VTX_WEIGHT_COUNT_SHIFT	(2)
+#       define R200_VTX_PV_MATRIX_SEL		(1<<5)
+#       define R200_VTX_N0			(1<<6)
+#       define R200_VTX_POINT_SIZE		(1<<7)
+#       define R200_VTX_DISCRETE_FOG		(1<<8)
+#       define R200_VTX_SHININESS_0		(1<<9)
+#       define R200_VTX_SHININESS_1		(1<<10)
+#       define   R200_VTX_COLOR_NOT_PRESENT	0
+#       define   R200_VTX_PK_RGBA		1
+#       define   R200_VTX_FP_RGB		2
+#       define   R200_VTX_FP_RGBA		3
+#       define   R200_VTX_COLOR_MASK		3
+#       define R200_VTX_COLOR_0_SHIFT		11
+#       define R200_VTX_COLOR_1_SHIFT		13
+#       define R200_VTX_COLOR_2_SHIFT		15
+#       define R200_VTX_COLOR_3_SHIFT		17
+#       define R200_VTX_COLOR_4_SHIFT		19
+#       define R200_VTX_COLOR_5_SHIFT		21
+#       define R200_VTX_COLOR_6_SHIFT		23
+#       define R200_VTX_COLOR_7_SHIFT		25
+#       define R200_VTX_XY1			(1<<28)
+#       define R200_VTX_Z1			(1<<29)
+#       define R200_VTX_W1			(1<<30)
+#       define R200_VTX_N1			(1<<31)
+#define R200_SE_VTX_FMT_1			0x208c
+#       define R200_VTX_TEX0_COMP_CNT_SHIFT	0
+#       define R200_VTX_TEX1_COMP_CNT_SHIFT	3
+#       define R200_VTX_TEX2_COMP_CNT_SHIFT	6
+#       define R200_VTX_TEX3_COMP_CNT_SHIFT	9
+#       define R200_VTX_TEX4_COMP_CNT_SHIFT	12
+#       define R200_VTX_TEX5_COMP_CNT_SHIFT	15
+
+#define R200_SE_TCL_OUTPUT_VTX_FMT_0		0x2090
+#define R200_SE_TCL_OUTPUT_VTX_FMT_1		0x2094
+#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL		0x2250
+#       define R200_OUTPUT_XYZW			(1<<0)
+#       define R200_OUTPUT_COLOR_0		(1<<8)
+#       define R200_OUTPUT_COLOR_1		(1<<9)
+#       define R200_OUTPUT_TEX_0		(1<<16)
+#       define R200_OUTPUT_TEX_1		(1<<17)
+#       define R200_OUTPUT_TEX_2		(1<<18)
+#       define R200_OUTPUT_TEX_3		(1<<19)
+#       define R200_OUTPUT_TEX_4		(1<<20)
+#       define R200_OUTPUT_TEX_5		(1<<21)
+#       define R200_OUTPUT_TEX_MASK		(0x3f<<16)
+#       define R200_OUTPUT_DISCRETE_FOG		(1<<24)
+#       define R200_OUTPUT_PT_SIZE		(1<<25)
+#       define R200_FORCE_INORDER_PROC		(1<<31)
+#define R200_PP_CNTL_X				0x2cc4
+#define R200_PP_TXMULTI_CTL_0			0x2c1c
+#define R200_SE_VTX_STATE_CNTL			0x2180
+#       define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16)
+
+				/* Registers for CP and Microcode Engine */
+#define RADEON_CP_ME_RAM_ADDR               0x07d4
+#define RADEON_CP_ME_RAM_RADDR              0x07d8
+#define RADEON_CP_ME_RAM_DATAH              0x07dc
+#define RADEON_CP_ME_RAM_DATAL              0x07e0
+
+#define RADEON_CP_RB_BASE                   0x0700
+#define RADEON_CP_RB_CNTL                   0x0704
+#	define RADEON_RB_BUFSZ_SHIFT		0
+#	define RADEON_RB_BUFSZ_MASK		(0x3f << 0)
+#	define RADEON_RB_BLKSZ_SHIFT		8
+#	define RADEON_RB_BLKSZ_MASK		(0x3f << 8)
+#	define RADEON_BUF_SWAP_32BIT		(1 << 17)
+#	define RADEON_MAX_FETCH_SHIFT		18
+#	define RADEON_MAX_FETCH_MASK		(0x3 << 18)
+#	define RADEON_RB_NO_UPDATE		(1 << 27)
+#	define RADEON_RB_RPTR_WR_ENA		(1 << 31)
+#define RADEON_CP_RB_RPTR_ADDR              0x070c
+#define RADEON_CP_RB_RPTR                   0x0710
+#define RADEON_CP_RB_WPTR                   0x0714
+#define RADEON_CP_RB_RPTR_WR                0x071c
+
+#define RADEON_CP_IB_BASE                   0x0738
+#define RADEON_CP_IB_BUFSZ                  0x073c
+
+#define RADEON_CP_CSQ_CNTL                  0x0740
+#       define RADEON_CSQ_CNT_PRIMARY_MASK     (0xff << 0)
+#       define RADEON_CSQ_PRIDIS_INDDIS        (0    << 28)
+#       define RADEON_CSQ_PRIPIO_INDDIS        (1    << 28)
+#       define RADEON_CSQ_PRIBM_INDDIS         (2    << 28)
+#       define RADEON_CSQ_PRIPIO_INDBM         (3    << 28)
+#       define RADEON_CSQ_PRIBM_INDBM          (4    << 28)
+#       define RADEON_CSQ_PRIPIO_INDPIO        (15   << 28)
+
+#define R300_CP_RESYNC_ADDR                 0x778
+#define R300_CP_RESYNC_DATA                 0x77c
+
+#define RADEON_CP_CSQ_STAT                  0x07f8
+#       define RADEON_CSQ_RPTR_PRIMARY_MASK    (0xff <<  0)
+#       define RADEON_CSQ_WPTR_PRIMARY_MASK    (0xff <<  8)
+#       define RADEON_CSQ_RPTR_INDIRECT_MASK   (0xff << 16)
+#       define RADEON_CSQ_WPTR_INDIRECT_MASK   (0xff << 24)
+#define RADEON_CP_CSQ2_STAT                  0x07fc
+#define RADEON_CP_CSQ_ADDR                  0x07f0
+#define RADEON_CP_CSQ_DATA                  0x07f4
+#define RADEON_CP_CSQ_APER_PRIMARY          0x1000
+#define RADEON_CP_CSQ_APER_INDIRECT         0x1300
+
+#define RADEON_CP_RB_WPTR_DELAY             0x0718
+#       define RADEON_PRE_WRITE_TIMER_SHIFT    0
+#       define RADEON_PRE_WRITE_LIMIT_SHIFT    23
+#define RADEON_CP_CSQ_MODE		0x0744
+#	define RADEON_INDIRECT2_START_SHIFT	0
+#	define RADEON_INDIRECT2_START_MASK	(0x7f << 0)
+#	define RADEON_INDIRECT1_START_SHIFT	8
+#	define RADEON_INDIRECT1_START_MASK	(0x7f << 8)
+
+#define RADEON_AIC_CNTL                     0x01d0
+#       define RADEON_PCIGART_TRANSLATE_EN     (1 << 0)
+#       define RADEON_DIS_OUT_OF_PCI_GART_ACCESS     (1 << 1)
+#define RADEON_AIC_LO_ADDR                  0x01dc
+#define RADEON_AIC_PT_BASE		0x01d8
+#define RADEON_AIC_HI_ADDR		0x01e0
+
+
+
+				/* Constants */
+/* #define RADEON_LAST_FRAME_REG               RADEON_GUI_SCRATCH_REG0 */
+/* efine RADEON_LAST_CLEAR_REG               RADEON_GUI_SCRATCH_REG2 */
+
+
+
+				/* CP packet types */
+#define RADEON_CP_PACKET0                           0x00000000
+#define RADEON_CP_PACKET1                           0x40000000
+#define RADEON_CP_PACKET2                           0x80000000
+#define RADEON_CP_PACKET3                           0xC0000000
+#       define RADEON_CP_PACKET_MASK                0xC0000000
+#       define RADEON_CP_PACKET_COUNT_MASK          0x3fff0000
+#       define RADEON_CP_PACKET_MAX_DWORDS          (1 << 12)
+#       define RADEON_CP_PACKET0_REG_MASK           0x000007ff
+#       define R300_CP_PACKET0_REG_MASK             0x00001fff
+#       define RADEON_CP_PACKET1_REG0_MASK          0x000007ff
+#       define RADEON_CP_PACKET1_REG1_MASK          0x003ff800
+
+#define RADEON_CP_PACKET0_ONE_REG_WR                0x00008000
+
+#define RADEON_CP_PACKET3_NOP                       0xC0001000
+#define RADEON_CP_PACKET3_NEXT_CHAR                 0xC0001900
+#define RADEON_CP_PACKET3_PLY_NEXTSCAN              0xC0001D00
+#define RADEON_CP_PACKET3_SET_SCISSORS              0xC0001E00
+#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM     0xC0002300
+#define RADEON_CP_PACKET3_LOAD_MICROCODE            0xC0002400
+#define RADEON_CP_PACKET3_WAIT_FOR_IDLE             0xC0002600
+#define RADEON_CP_PACKET3_3D_DRAW_VBUF              0xC0002800
+#define RADEON_CP_PACKET3_3D_DRAW_IMMD              0xC0002900
+#define RADEON_CP_PACKET3_3D_DRAW_INDX              0xC0002A00
+#define RADEON_CP_PACKET3_LOAD_PALETTE              0xC0002C00
+#define R200_CP_PACKET3_3D_DRAW_IMMD_2              0xc0003500
+#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR            0xC0002F00
+#define RADEON_CP_PACKET3_CNTL_PAINT                0xC0009100
+#define RADEON_CP_PACKET3_CNTL_BITBLT               0xC0009200
+#define RADEON_CP_PACKET3_CNTL_SMALLTEXT            0xC0009300
+#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT         0xC0009400
+#define RADEON_CP_PACKET3_CNTL_POLYLINE             0xC0009500
+#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES        0xC0009800
+#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI          0xC0009A00
+#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI         0xC0009B00
+#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT         0xC0009C00
+
+
+#define RADEON_CP_VC_FRMT_XY                        0x00000000
+#define RADEON_CP_VC_FRMT_W0                        0x00000001
+#define RADEON_CP_VC_FRMT_FPCOLOR                   0x00000002
+#define RADEON_CP_VC_FRMT_FPALPHA                   0x00000004
+#define RADEON_CP_VC_FRMT_PKCOLOR                   0x00000008
+#define RADEON_CP_VC_FRMT_FPSPEC                    0x00000010
+#define RADEON_CP_VC_FRMT_FPFOG                     0x00000020
+#define RADEON_CP_VC_FRMT_PKSPEC                    0x00000040
+#define RADEON_CP_VC_FRMT_ST0                       0x00000080
+#define RADEON_CP_VC_FRMT_ST1                       0x00000100
+#define RADEON_CP_VC_FRMT_Q1                        0x00000200
+#define RADEON_CP_VC_FRMT_ST2                       0x00000400
+#define RADEON_CP_VC_FRMT_Q2                        0x00000800
+#define RADEON_CP_VC_FRMT_ST3                       0x00001000
+#define RADEON_CP_VC_FRMT_Q3                        0x00002000
+#define RADEON_CP_VC_FRMT_Q0                        0x00004000
+#define RADEON_CP_VC_FRMT_BLND_WEIGHT_CNT_MASK      0x00038000
+#define RADEON_CP_VC_FRMT_N0                        0x00040000
+#define RADEON_CP_VC_FRMT_XY1                       0x08000000
+#define RADEON_CP_VC_FRMT_Z1                        0x10000000
+#define RADEON_CP_VC_FRMT_W1                        0x20000000
+#define RADEON_CP_VC_FRMT_N1                        0x40000000
+#define RADEON_CP_VC_FRMT_Z                         0x80000000
+
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_NONE            0x00000000
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_POINT           0x00000001
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE            0x00000002
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP      0x00000003
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST        0x00000004
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN         0x00000005
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP       0x00000006
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2      0x00000007
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST       0x00000008
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST  0x0000000a
+#define RADEON_CP_VC_CNTL_PRIM_WALK_IND             0x00000010
+#define RADEON_CP_VC_CNTL_PRIM_WALK_LIST            0x00000020
+#define RADEON_CP_VC_CNTL_PRIM_WALK_RING            0x00000030
+#define RADEON_CP_VC_CNTL_COLOR_ORDER_BGRA          0x00000000
+#define RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA          0x00000040
+#define RADEON_CP_VC_CNTL_MAOS_ENABLE               0x00000080
+#define RADEON_CP_VC_CNTL_VTX_FMT_NON_RADEON_MODE   0x00000000
+#define RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE       0x00000100
+#define RADEON_CP_VC_CNTL_TCL_DISABLE               0x00000000
+#define RADEON_CP_VC_CNTL_TCL_ENABLE                0x00000200
+#define RADEON_CP_VC_CNTL_NUM_SHIFT                 16
+
+#define RADEON_VS_MATRIX_0_ADDR                   0
+#define RADEON_VS_MATRIX_1_ADDR                   4
+#define RADEON_VS_MATRIX_2_ADDR                   8
+#define RADEON_VS_MATRIX_3_ADDR                  12
+#define RADEON_VS_MATRIX_4_ADDR                  16
+#define RADEON_VS_MATRIX_5_ADDR                  20
+#define RADEON_VS_MATRIX_6_ADDR                  24
+#define RADEON_VS_MATRIX_7_ADDR                  28
+#define RADEON_VS_MATRIX_8_ADDR                  32
+#define RADEON_VS_MATRIX_9_ADDR                  36
+#define RADEON_VS_MATRIX_10_ADDR                 40
+#define RADEON_VS_MATRIX_11_ADDR                 44
+#define RADEON_VS_MATRIX_12_ADDR                 48
+#define RADEON_VS_MATRIX_13_ADDR                 52
+#define RADEON_VS_MATRIX_14_ADDR                 56
+#define RADEON_VS_MATRIX_15_ADDR                 60
+#define RADEON_VS_LIGHT_AMBIENT_ADDR             64
+#define RADEON_VS_LIGHT_DIFFUSE_ADDR             72
+#define RADEON_VS_LIGHT_SPECULAR_ADDR            80
+#define RADEON_VS_LIGHT_DIRPOS_ADDR              88
+#define RADEON_VS_LIGHT_HWVSPOT_ADDR             96
+#define RADEON_VS_LIGHT_ATTENUATION_ADDR        104
+#define RADEON_VS_MATRIX_EYE2CLIP_ADDR          112
+#define RADEON_VS_UCP_ADDR                      116
+#define RADEON_VS_GLOBAL_AMBIENT_ADDR           122
+#define RADEON_VS_FOG_PARAM_ADDR                123
+#define RADEON_VS_EYE_VECTOR_ADDR               124
+
+#define RADEON_SS_LIGHT_DCD_ADDR                  0
+#define RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR        8
+#define RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR         16
+#define RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR     24
+#define RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR        32
+#define RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR       48
+#define RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR    49
+#define RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR       50
+#define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR    51
+#define RADEON_SS_SHININESS                      60
+
+#define RADEON_TV_MASTER_CNTL                    0x0800
+#       define RADEON_TV_ASYNC_RST               (1 <<  0)
+#       define RADEON_CRT_ASYNC_RST              (1 <<  1)
+#       define RADEON_RESTART_PHASE_FIX          (1 <<  3)
+#	define RADEON_TV_FIFO_ASYNC_RST		 (1 <<  4)
+#	define RADEON_VIN_ASYNC_RST		 (1 <<  5)
+#	define RADEON_AUD_ASYNC_RST		 (1 <<  6)
+#	define RADEON_DVS_ASYNC_RST		 (1 <<  7)
+#       define RADEON_CRT_FIFO_CE_EN             (1 <<  9)
+#       define RADEON_TV_FIFO_CE_EN              (1 << 10)
+#       define RADEON_RE_SYNC_NOW_SEL_MASK       (3 << 14)
+#       define RADEON_TVCLK_ALWAYS_ONb           (1 << 30)
+#	define RADEON_TV_ON			 (1 << 31)
+#define RADEON_TV_PRE_DAC_MUX_CNTL               0x0888
+#       define RADEON_Y_RED_EN                   (1 << 0)
+#       define RADEON_C_GRN_EN                   (1 << 1)
+#       define RADEON_CMP_BLU_EN                 (1 << 2)
+#       define RADEON_DAC_DITHER_EN              (1 << 3)
+#       define RADEON_RED_MX_FORCE_DAC_DATA      (6 << 4)
+#       define RADEON_GRN_MX_FORCE_DAC_DATA      (6 << 8)
+#       define RADEON_BLU_MX_FORCE_DAC_DATA      (6 << 12)
+#       define RADEON_TV_FORCE_DAC_DATA_SHIFT    16
+#define RADEON_TV_RGB_CNTL                           0x0804
+#       define RADEON_SWITCH_TO_BLUE		  (1 <<  4)
+#       define RADEON_RGB_DITHER_EN		  (1 <<  5)
+#       define RADEON_RGB_SRC_SEL_MASK		  (3 <<  8)
+#       define RADEON_RGB_SRC_SEL_CRTC1		  (0 <<  8)
+#       define RADEON_RGB_SRC_SEL_RMX		  (1 <<  8)
+#       define RADEON_RGB_SRC_SEL_CRTC2		  (2 <<  8)
+#       define RADEON_RGB_CONVERT_BY_PASS	  (1 << 10)
+#       define RADEON_UVRAM_READ_MARGIN_SHIFT	  16
+#       define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT	  20
+#	define RADEON_TVOUT_SCALE_EN		  (1 << 26)
+#define RADEON_TV_SYNC_CNTL                          0x0808
+#       define RADEON_SYNC_OE                     (1 <<  0)
+#       define RADEON_SYNC_OUT                    (1 <<  1)
+#       define RADEON_SYNC_IN                     (1 <<  2)
+#       define RADEON_SYNC_PUB                    (1 <<  3)
+#       define RADEON_SYNC_PD                     (1 <<  4)
+#       define RADEON_TV_SYNC_IO_DRIVE            (1 <<  5)
+#define RADEON_TV_HTOTAL                             0x080c
+#define RADEON_TV_HDISP                              0x0810
+#define RADEON_TV_HSTART                             0x0818
+#define RADEON_TV_HCOUNT                             0x081C
+#define RADEON_TV_VTOTAL                             0x0820
+#define RADEON_TV_VDISP                              0x0824
+#define RADEON_TV_VCOUNT                             0x0828
+#define RADEON_TV_FTOTAL                             0x082c
+#define RADEON_TV_FCOUNT                             0x0830
+#define RADEON_TV_FRESTART                           0x0834
+#define RADEON_TV_HRESTART                           0x0838
+#define RADEON_TV_VRESTART                           0x083c
+#define RADEON_TV_HOST_READ_DATA                     0x0840
+#define RADEON_TV_HOST_WRITE_DATA                    0x0844
+#define RADEON_TV_HOST_RD_WT_CNTL                    0x0848
+#	define RADEON_HOST_FIFO_RD		 (1 << 12)
+#	define RADEON_HOST_FIFO_RD_ACK		 (1 << 13)
+#	define RADEON_HOST_FIFO_WT		 (1 << 14)
+#	define RADEON_HOST_FIFO_WT_ACK		 (1 << 15)
+#define RADEON_TV_VSCALER_CNTL1                      0x084c
+#       define RADEON_UV_INC_MASK                0xffff
+#       define RADEON_UV_INC_SHIFT               0
+#       define RADEON_Y_W_EN			 (1 << 24)
+#       define RADEON_RESTART_FIELD              (1 << 29) /* restart on field 0 */
+#       define RADEON_Y_DEL_W_SIG_SHIFT          26
+#define RADEON_TV_TIMING_CNTL                        0x0850
+#       define RADEON_H_INC_MASK                 0xfff
+#       define RADEON_H_INC_SHIFT                0
+#       define RADEON_REQ_Y_FIRST                (1 << 19)
+#       define RADEON_FORCE_BURST_ALWAYS         (1 << 21)
+#       define RADEON_UV_POST_SCALE_BYPASS       (1 << 23)
+#       define RADEON_UV_OUTPUT_POST_SCALE_SHIFT 24
+#define RADEON_TV_VSCALER_CNTL2                      0x0854
+#       define RADEON_DITHER_MODE                (1 <<  0)
+#       define RADEON_Y_OUTPUT_DITHER_EN         (1 <<  1)
+#       define RADEON_UV_OUTPUT_DITHER_EN        (1 <<  2)
+#       define RADEON_UV_TO_BUF_DITHER_EN        (1 <<  3)
+#define RADEON_TV_Y_FALL_CNTL                        0x0858
+#       define RADEON_Y_FALL_PING_PONG           (1 << 16)
+#       define RADEON_Y_COEF_EN                  (1 << 17)
+#define RADEON_TV_Y_RISE_CNTL                        0x085c
+#       define RADEON_Y_RISE_PING_PONG           (1 << 16)
+#define RADEON_TV_Y_SAW_TOOTH_CNTL                   0x0860
+#define RADEON_TV_UPSAMP_AND_GAIN_CNTL               0x0864
+#	define RADEON_YUPSAMP_EN		 (1 <<  0)
+#	define RADEON_UVUPSAMP_EN		 (1 <<  2)
+#define RADEON_TV_GAIN_LIMIT_SETTINGS                0x0868
+#       define RADEON_Y_GAIN_LIMIT_SHIFT         0
+#       define RADEON_UV_GAIN_LIMIT_SHIFT        16
+#define RADEON_TV_LINEAR_GAIN_SETTINGS               0x086c
+#       define RADEON_Y_GAIN_SHIFT               0
+#       define RADEON_UV_GAIN_SHIFT              16
+#define RADEON_TV_MODULATOR_CNTL1                    0x0870
+#	define RADEON_YFLT_EN			 (1 <<  2)
+#	define RADEON_UVFLT_EN			 (1 <<  3)
+#       define RADEON_ALT_PHASE_EN               (1 <<  6)
+#       define RADEON_SYNC_TIP_LEVEL             (1 <<  7)
+#       define RADEON_BLANK_LEVEL_SHIFT          8
+#       define RADEON_SET_UP_LEVEL_SHIFT         16
+#	define RADEON_SLEW_RATE_LIMIT		 (1 << 23)
+#       define RADEON_CY_FILT_BLEND_SHIFT        28
+#define RADEON_TV_MODULATOR_CNTL2                    0x0874
+#       define RADEON_TV_U_BURST_LEVEL_MASK     0x1ff
+#       define RADEON_TV_V_BURST_LEVEL_MASK     0x1ff
+#       define RADEON_TV_V_BURST_LEVEL_SHIFT    16
+#define RADEON_TV_CRC_CNTL                           0x0890
+#define RADEON_TV_UV_ADR                             0x08ac
+#	define RADEON_MAX_UV_ADR_MASK		 0x000000ff
+#	define RADEON_MAX_UV_ADR_SHIFT		 0
+#	define RADEON_TABLE1_BOT_ADR_MASK	 0x0000ff00
+#	define RADEON_TABLE1_BOT_ADR_SHIFT	 8
+#	define RADEON_TABLE3_TOP_ADR_MASK	 0x00ff0000
+#	define RADEON_TABLE3_TOP_ADR_SHIFT	 16
+#	define RADEON_HCODE_TABLE_SEL_MASK	 0x06000000
+#	define RADEON_HCODE_TABLE_SEL_SHIFT	 25
+#	define RADEON_VCODE_TABLE_SEL_MASK	 0x18000000
+#	define RADEON_VCODE_TABLE_SEL_SHIFT	 27
+#	define RADEON_TV_MAX_FIFO_ADDR		 0x1a7
+#	define RADEON_TV_MAX_FIFO_ADDR_INTERNAL	 0x1ff
+#define RADEON_TV_PLL_FINE_CNTL			     0x0020	/* PLL */
+#define RADEON_TV_PLL_CNTL                           0x0021	/* PLL */
+#       define RADEON_TV_M0LO_MASK               0xff
+#       define RADEON_TV_M0HI_MASK               0x7
+#       define RADEON_TV_M0HI_SHIFT              18
+#       define RADEON_TV_N0LO_MASK               0x1ff
+#       define RADEON_TV_N0LO_SHIFT              8
+#       define RADEON_TV_N0HI_MASK               0x3
+#       define RADEON_TV_N0HI_SHIFT              21
+#       define RADEON_TV_P_MASK                  0xf
+#       define RADEON_TV_P_SHIFT                 24
+#       define RADEON_TV_SLIP_EN                 (1 << 23)
+#       define RADEON_TV_DTO_EN                  (1 << 28)
+#define RADEON_TV_PLL_CNTL1                          0x0022	/* PLL */
+#       define RADEON_TVPLL_RESET                (1 <<  1)
+#       define RADEON_TVPLL_SLEEP                (1 <<  3)
+#       define RADEON_TVPLL_REFCLK_SEL           (1 <<  4)
+#       define RADEON_TVPCP_SHIFT                8
+#       define RADEON_TVPCP_MASK                 (7 << 8)
+#       define RADEON_TVPVG_SHIFT                11
+#       define RADEON_TVPVG_MASK                 (7 << 11)
+#       define RADEON_TVPDC_SHIFT                14
+#       define RADEON_TVPDC_MASK                 (3 << 14)
+#       define RADEON_TVPLL_TEST_DIS             (1 << 31)
+#       define RADEON_TVCLK_SRC_SEL_TVPLL        (1 << 30)
+
+#define RS400_DISP2_REQ_CNTL1			0xe30
+#       define RS400_DISP2_START_REQ_LEVEL_SHIFT   0
+#       define RS400_DISP2_START_REQ_LEVEL_MASK    0x3ff
+#       define RS400_DISP2_STOP_REQ_LEVEL_SHIFT    12
+#       define RS400_DISP2_STOP_REQ_LEVEL_MASK     0x3ff
+#       define RS400_DISP2_ALLOW_FID_LEVEL_SHIFT   22
+#       define RS400_DISP2_ALLOW_FID_LEVEL_MASK    0x3ff
+#define RS400_DISP2_REQ_CNTL2			0xe34
+#       define RS400_DISP2_CRITICAL_POINT_START_SHIFT    12
+#       define RS400_DISP2_CRITICAL_POINT_START_MASK     0x3ff
+#       define RS400_DISP2_CRITICAL_POINT_STOP_SHIFT     22
+#       define RS400_DISP2_CRITICAL_POINT_STOP_MASK      0x3ff
+#define RS400_DMIF_MEM_CNTL1			0xe38
+#       define RS400_DISP2_START_ADR_SHIFT      0
+#       define RS400_DISP2_START_ADR_MASK       0x3ff
+#       define RS400_DISP1_CRITICAL_POINT_START_SHIFT    12
+#       define RS400_DISP1_CRITICAL_POINT_START_MASK     0x3ff
+#       define RS400_DISP1_CRITICAL_POINT_STOP_SHIFT     22
+#       define RS400_DISP1_CRITICAL_POINT_STOP_MASK      0x3ff
+#define RS400_DISP1_REQ_CNTL1			0xe3c
+#       define RS400_DISP1_START_REQ_LEVEL_SHIFT   0
+#       define RS400_DISP1_START_REQ_LEVEL_MASK    0x3ff
+#       define RS400_DISP1_STOP_REQ_LEVEL_SHIFT    12
+#       define RS400_DISP1_STOP_REQ_LEVEL_MASK     0x3ff
+#       define RS400_DISP1_ALLOW_FID_LEVEL_SHIFT   22
+#       define RS400_DISP1_ALLOW_FID_LEVEL_MASK    0x3ff
+
+#define RADEON_PCIE_INDEX               0x0030
+#define RADEON_PCIE_DATA                0x0034
+#define RADEON_PCIE_TX_GART_CNTL	0x10
+#	define RADEON_PCIE_TX_GART_EN		(1 << 0)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO  (1 << 1)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD   (3 << 1)
+#	define RADEON_PCIE_TX_GART_MODE_32_128_CACHE	(0 << 3)
+#	define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE	(1 << 3)
+#	define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN      (1 << 5)
+#	define RADEON_PCIE_TX_GART_INVALIDATE_TLB	(1 << 8)
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
+#define RADEON_PCIE_TX_GART_BASE	0x13
+#define RADEON_PCIE_TX_GART_START_LO	0x14
+#define RADEON_PCIE_TX_GART_START_HI	0x15
+#define RADEON_PCIE_TX_GART_END_LO	0x16
+#define RADEON_PCIE_TX_GART_END_HI	0x17
+#define RADEON_PCIE_TX_GART_ERROR	0x18
+
+#define RADEON_SCRATCH_REG0		0x15e0
+#define RADEON_SCRATCH_REG1		0x15e4
+#define RADEON_SCRATCH_REG2		0x15e8
+#define RADEON_SCRATCH_REG3		0x15ec
+#define RADEON_SCRATCH_REG4		0x15f0
+#define RADEON_SCRATCH_REG5		0x15f4
+
+#define RV530_GB_PIPE_SELECT2           0x4124
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_ring.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_ring.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_ring.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,472 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include <linux/seq_file.h>
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "atom.h"
+
+int radeon_debugfs_ib_init(struct radeon_device *rdev);
+
+/*
+ * IB.
+ */
+int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
+{
+	struct radeon_fence *fence;
+	struct radeon_ib *nib;
+	unsigned long i;
+	int r = 0;
+
+	*ib = NULL;
+	r = radeon_fence_create(rdev, &fence);
+	if (r) {
+		DRM_ERROR("failed to create fence for new IB\n");
+		return r;
+	}
+	mutex_lock(&rdev->ib_pool.mutex);
+	i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
+	if (i < RADEON_IB_POOL_SIZE) {
+		set_bit(i, rdev->ib_pool.alloc_bm);
+		rdev->ib_pool.ibs[i].length_dw = 0;
+		*ib = &rdev->ib_pool.ibs[i];
+		goto out;
+	}
+	if (list_empty(&rdev->ib_pool.scheduled_ibs)) {
+		/* we go do nothings here */
+		DRM_ERROR("all IB allocated none scheduled.\n");
+		r = -EINVAL;
+		goto out;
+	}
+	/* get the first ib on the scheduled list */
+	nib = list_entry(rdev->ib_pool.scheduled_ibs.next,
+			 struct radeon_ib, list);
+	if (nib->fence == NULL) {
+		/* we go do nothings here */
+		DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx);
+		r = -EINVAL;
+		goto out;
+	}
+	r = radeon_fence_wait(nib->fence, false);
+	if (r) {
+		DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx,
+			  (unsigned long)nib->gpu_addr, nib->length_dw);
+		DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n");
+		goto out;
+	}
+	radeon_fence_unref(&nib->fence);
+	nib->length_dw = 0;
+	list_del(&nib->list);
+	INIT_LIST_HEAD(&nib->list);
+	*ib = nib;
+out:
+	mutex_unlock(&rdev->ib_pool.mutex);
+	if (r) {
+		radeon_fence_unref(&fence);
+	} else {
+		(*ib)->fence = fence;
+	}
+	return r;
+}
+
+void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
+{
+	struct radeon_ib *tmp = *ib;
+
+	*ib = NULL;
+	if (tmp == NULL) {
+		return;
+	}
+	mutex_lock(&rdev->ib_pool.mutex);
+	if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) {
+		/* IB is scheduled & not signaled don't do anythings */
+		mutex_unlock(&rdev->ib_pool.mutex);
+		return;
+	}
+	list_del(&tmp->list);
+	INIT_LIST_HEAD(&tmp->list);
+	if (tmp->fence) {
+		radeon_fence_unref(&tmp->fence);
+	}
+	tmp->length_dw = 0;
+	clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
+	mutex_unlock(&rdev->ib_pool.mutex);
+}
+
+static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+	while ((ib->length_dw & rdev->cp.align_mask)) {
+		ib->ptr[ib->length_dw++] = PACKET2(0);
+	}
+}
+
+int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+	int r = 0;
+
+	mutex_lock(&rdev->ib_pool.mutex);
+	radeon_ib_align(rdev, ib);
+	if (!ib->length_dw || !rdev->cp.ready) {
+		/* TODO: Nothings in the ib we should report. */
+		mutex_unlock(&rdev->ib_pool.mutex);
+		DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
+		return -EINVAL;
+	}
+	/* 64 dwords should be enough for fence too */
+	r = radeon_ring_lock(rdev, 64);
+	if (r) {
+		DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
+		mutex_unlock(&rdev->ib_pool.mutex);
+		return r;
+	}
+	radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1));
+	radeon_ring_write(rdev, ib->gpu_addr);
+	radeon_ring_write(rdev, ib->length_dw);
+	radeon_fence_emit(rdev, ib->fence);
+	radeon_ring_unlock_commit(rdev);
+	list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs);
+	mutex_unlock(&rdev->ib_pool.mutex);
+	return 0;
+}
+
+int radeon_ib_pool_init(struct radeon_device *rdev)
+{
+	void *ptr;
+	uint64_t gpu_addr;
+	int i;
+	int r = 0;
+
+	/* Allocate 1M object buffer */
+	INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
+	r = radeon_object_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
+				 true, RADEON_GEM_DOMAIN_GTT,
+				 false, &rdev->ib_pool.robj);
+	if (r) {
+		DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
+		return r;
+	}
+	r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
+	if (r) {
+		DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r);
+		return r;
+	}
+	r = radeon_object_kmap(rdev->ib_pool.robj, &ptr);
+	if (r) {
+		DRM_ERROR("radeon: failed to map ib poll (%d).\n", r);
+		return r;
+	}
+	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
+		unsigned offset;
+
+		offset = i * 64 * 1024;
+		rdev->ib_pool.ibs[i].gpu_addr = gpu_addr + offset;
+		rdev->ib_pool.ibs[i].ptr = ptr + offset;
+		rdev->ib_pool.ibs[i].idx = i;
+		rdev->ib_pool.ibs[i].length_dw = 0;
+		INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list);
+	}
+	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
+	rdev->ib_pool.ready = true;
+	DRM_INFO("radeon: ib pool ready.\n");
+	if (radeon_debugfs_ib_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for IB !\n");
+	}
+	return r;
+}
+
+void radeon_ib_pool_fini(struct radeon_device *rdev)
+{
+	if (!rdev->ib_pool.ready) {
+		return;
+	}
+	mutex_lock(&rdev->ib_pool.mutex);
+	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
+	if (rdev->ib_pool.robj) {
+		radeon_object_kunmap(rdev->ib_pool.robj);
+		radeon_object_unref(&rdev->ib_pool.robj);
+		rdev->ib_pool.robj = NULL;
+	}
+	mutex_unlock(&rdev->ib_pool.mutex);
+}
+
+int radeon_ib_test(struct radeon_device *rdev)
+{
+	struct radeon_ib *ib;
+	uint32_t scratch;
+	uint32_t tmp = 0;
+	unsigned i;
+	int r;
+
+	r = radeon_scratch_get(rdev, &scratch);
+	if (r) {
+		DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r);
+		return r;
+	}
+	WREG32(scratch, 0xCAFEDEAD);
+	r = radeon_ib_get(rdev, &ib);
+	if (r) {
+		return r;
+	}
+	ib->ptr[0] = PACKET0(scratch, 0);
+	ib->ptr[1] = 0xDEADBEEF;
+	ib->ptr[2] = PACKET2(0);
+	ib->ptr[3] = PACKET2(0);
+	ib->ptr[4] = PACKET2(0);
+	ib->ptr[5] = PACKET2(0);
+	ib->ptr[6] = PACKET2(0);
+	ib->ptr[7] = PACKET2(0);
+	ib->length_dw = 8;
+	r = radeon_ib_schedule(rdev, ib);
+	if (r) {
+		radeon_scratch_free(rdev, scratch);
+		radeon_ib_free(rdev, &ib);
+		return r;
+	}
+	r = radeon_fence_wait(ib->fence, false);
+	if (r) {
+		return r;
+	}
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(scratch);
+		if (tmp == 0xDEADBEEF) {
+			break;
+		}
+		DRM_UDELAY(1);
+	}
+	if (i < rdev->usec_timeout) {
+		DRM_INFO("ib test succeeded in %u usecs\n", i);
+	} else {
+		DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n",
+			  scratch, tmp);
+		r = -EINVAL;
+	}
+	radeon_scratch_free(rdev, scratch);
+	radeon_ib_free(rdev, &ib);
+	return r;
+}
+
+
+/*
+ * Ring.
+ */
+void radeon_ring_free_size(struct radeon_device *rdev)
+{
+	rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
+	/* This works because ring_size is a power of 2 */
+	rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4));
+	rdev->cp.ring_free_dw -= rdev->cp.wptr;
+	rdev->cp.ring_free_dw &= rdev->cp.ptr_mask;
+	if (!rdev->cp.ring_free_dw) {
+		rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
+	}
+}
+
+int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw)
+{
+	int r;
+
+	/* Align requested size with padding so unlock_commit can
+	 * pad safely */
+	ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask;
+	mutex_lock(&rdev->cp.mutex);
+	while (ndw > (rdev->cp.ring_free_dw - 1)) {
+		radeon_ring_free_size(rdev);
+		if (ndw < rdev->cp.ring_free_dw) {
+			break;
+		}
+		r = radeon_fence_wait_next(rdev);
+		if (r) {
+			mutex_unlock(&rdev->cp.mutex);
+			return r;
+		}
+	}
+	rdev->cp.count_dw = ndw;
+	rdev->cp.wptr_old = rdev->cp.wptr;
+	return 0;
+}
+
+void radeon_ring_unlock_commit(struct radeon_device *rdev)
+{
+	unsigned count_dw_pad;
+	unsigned i;
+
+	/* We pad to match fetch size */
+	count_dw_pad = (rdev->cp.align_mask + 1) -
+		       (rdev->cp.wptr & rdev->cp.align_mask);
+	for (i = 0; i < count_dw_pad; i++) {
+		radeon_ring_write(rdev, PACKET2(0));
+	}
+	DRM_MEMORYBARRIER();
+	WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
+	(void)RREG32(RADEON_CP_RB_WPTR);
+	mutex_unlock(&rdev->cp.mutex);
+}
+
+void radeon_ring_unlock_undo(struct radeon_device *rdev)
+{
+	rdev->cp.wptr = rdev->cp.wptr_old;
+	mutex_unlock(&rdev->cp.mutex);
+}
+
+int radeon_ring_test(struct radeon_device *rdev)
+{
+	uint32_t scratch;
+	uint32_t tmp = 0;
+	unsigned i;
+	int r;
+
+	r = radeon_scratch_get(rdev, &scratch);
+	if (r) {
+		DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r);
+		return r;
+	}
+	WREG32(scratch, 0xCAFEDEAD);
+	r = radeon_ring_lock(rdev, 2);
+	if (r) {
+		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+		radeon_scratch_free(rdev, scratch);
+		return r;
+	}
+	radeon_ring_write(rdev, PACKET0(scratch, 0));
+	radeon_ring_write(rdev, 0xDEADBEEF);
+	radeon_ring_unlock_commit(rdev);
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(scratch);
+		if (tmp == 0xDEADBEEF) {
+			break;
+		}
+		DRM_UDELAY(1);
+	}
+	if (i < rdev->usec_timeout) {
+		DRM_INFO("ring test succeeded in %d usecs\n", i);
+	} else {
+		DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n",
+			  scratch, tmp);
+		r = -EINVAL;
+	}
+	radeon_scratch_free(rdev, scratch);
+	return r;
+}
+
+int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
+{
+	int r;
+
+	rdev->cp.ring_size = ring_size;
+	/* Allocate ring buffer */
+	if (rdev->cp.ring_obj == NULL) {
+		r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
+					 true,
+					 RADEON_GEM_DOMAIN_GTT,
+					 false,
+					 &rdev->cp.ring_obj);
+		if (r) {
+			DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r);
+			mutex_unlock(&rdev->cp.mutex);
+			return r;
+		}
+		r = radeon_object_pin(rdev->cp.ring_obj,
+				      RADEON_GEM_DOMAIN_GTT,
+				      &rdev->cp.gpu_addr);
+		if (r) {
+			DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r);
+			mutex_unlock(&rdev->cp.mutex);
+			return r;
+		}
+		r = radeon_object_kmap(rdev->cp.ring_obj,
+				       (void **)&rdev->cp.ring);
+		if (r) {
+			DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r);
+			mutex_unlock(&rdev->cp.mutex);
+			return r;
+		}
+	}
+	rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1;
+	rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
+	return 0;
+}
+
+void radeon_ring_fini(struct radeon_device *rdev)
+{
+	mutex_lock(&rdev->cp.mutex);
+	if (rdev->cp.ring_obj) {
+		radeon_object_kunmap(rdev->cp.ring_obj);
+		radeon_object_unpin(rdev->cp.ring_obj);
+		radeon_object_unref(&rdev->cp.ring_obj);
+		rdev->cp.ring = NULL;
+		rdev->cp.ring_obj = NULL;
+	}
+	mutex_unlock(&rdev->cp.mutex);
+}
+
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct radeon_ib *ib = node->info_ent->data;
+	unsigned i;
+
+	if (ib == NULL) {
+		return 0;
+	}
+	seq_printf(m, "IB %04lu\n", ib->idx);
+	seq_printf(m, "IB fence %p\n", ib->fence);
+	seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
+	for (i = 0; i < ib->length_dw; i++) {
+		seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]);
+	}
+	return 0;
+}
+
+static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
+static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
+#endif
+
+int radeon_debugfs_ib_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	unsigned i;
+
+	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
+		sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
+		radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
+		radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info;
+		radeon_debugfs_ib_list[i].driver_features = 0;
+		radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i];
+	}
+	return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list,
+					RADEON_IB_POOL_SIZE);
+#else
+	return 0;
+#endif
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_share.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_share.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_share.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_share.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RADEON_SHARE_H__
+#define __RADEON_SHARE_H__
+
+void r100_vram_init_sizes(struct radeon_device *rdev);
+
+void rs690_line_buffer_adjust(struct radeon_device *rdev,
+			      struct drm_display_mode *mode1,
+			      struct drm_display_mode *mode2);
+
+void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_state.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_state.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_state.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_state.c	2009-09-09 18:13:59.000000000 -0400
@@ -2866,12 +2866,12 @@
 	 */
 	orig_bufsz = cmdbuf->bufsz;
 	if (orig_bufsz != 0) {
-		kbuf = drm_alloc(cmdbuf->bufsz, DRM_MEM_DRIVER);
+		kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL);
 		if (kbuf == NULL)
 			return -ENOMEM;
 		if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
 				       cmdbuf->bufsz)) {
-			drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+			kfree(kbuf);
 			return -EFAULT;
 		}
 		cmdbuf->buf = kbuf;
@@ -2884,7 +2884,7 @@
 		temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
 
 		if (orig_bufsz != 0)
-			drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+			kfree(kbuf);
 
 		return temp;
 	}
@@ -2991,7 +2991,7 @@
 	}
 
 	if (orig_bufsz != 0)
-		drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+		kfree(kbuf);
 
 	DRM_DEBUG("DONE\n");
 	COMMIT_RING();
@@ -2999,7 +2999,7 @@
 
       err:
 	if (orig_bufsz != 0)
-		drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+		kfree(kbuf);
 	return -EINVAL;
 }
 
@@ -3081,6 +3081,9 @@
 	case RADEON_PARAM_NUM_GB_PIPES:
 		value = dev_priv->num_gb_pipes;
 		break;
+	case RADEON_PARAM_NUM_Z_PIPES:
+		value = dev_priv->num_z_pipes;
+		break;
 	default:
 		DRM_DEBUG("Invalid parameter %d\n", param->param);
 		return -EINVAL;
@@ -3175,9 +3178,7 @@
 	struct drm_radeon_driver_file_fields *radeon_priv;
 
 	DRM_DEBUG("\n");
-	radeon_priv =
-	    (struct drm_radeon_driver_file_fields *)
-	    drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
+	radeon_priv = kmalloc(sizeof(*radeon_priv), GFP_KERNEL);
 
 	if (!radeon_priv)
 		return -ENOMEM;
@@ -3196,7 +3197,7 @@
 	struct drm_radeon_driver_file_fields *radeon_priv =
 	    file_priv->driver_priv;
 
-	drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+	kfree(radeon_priv);
 }
 
 struct drm_ioctl_desc radeon_ioctls[] = {
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_test.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_test.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_test.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_test.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Michel Dänzer
+ */
+#include <drm/drmP.h>
+#include <drm/radeon_drm.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+
+
+/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
+void radeon_test_moves(struct radeon_device *rdev)
+{
+	struct radeon_object *vram_obj = NULL;
+	struct radeon_object **gtt_obj = NULL;
+	struct radeon_fence *fence = NULL;
+	uint64_t gtt_addr, vram_addr;
+	unsigned i, n, size;
+	int r;
+
+	size = 1024 * 1024;
+
+	/* Number of tests =
+	 * (Total GTT - IB pool - writeback page - ring buffer) / test size
+	 */
+	n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - 4096 -
+	     rdev->cp.ring_size) / size;
+
+	gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
+	if (!gtt_obj) {
+		DRM_ERROR("Failed to allocate %d pointers\n", n);
+		r = 1;
+		goto out_cleanup;
+	}
+
+	r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
+				 false, &vram_obj);
+	if (r) {
+		DRM_ERROR("Failed to create VRAM object\n");
+		goto out_cleanup;
+	}
+
+	r = radeon_object_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
+	if (r) {
+		DRM_ERROR("Failed to pin VRAM object\n");
+		goto out_cleanup;
+	}
+
+	for (i = 0; i < n; i++) {
+		void *gtt_map, *vram_map;
+		void **gtt_start, **gtt_end;
+		void **vram_start, **vram_end;
+
+		r = radeon_object_create(rdev, NULL, size, true,
+					 RADEON_GEM_DOMAIN_GTT, false, gtt_obj + i);
+		if (r) {
+			DRM_ERROR("Failed to create GTT object %d\n", i);
+			goto out_cleanup;
+		}
+
+		r = radeon_object_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
+		if (r) {
+			DRM_ERROR("Failed to pin GTT object %d\n", i);
+			goto out_cleanup;
+		}
+
+		r = radeon_object_kmap(gtt_obj[i], &gtt_map);
+		if (r) {
+			DRM_ERROR("Failed to map GTT object %d\n", i);
+			goto out_cleanup;
+		}
+
+		for (gtt_start = gtt_map, gtt_end = gtt_map + size;
+		     gtt_start < gtt_end;
+		     gtt_start++)
+			*gtt_start = gtt_start;
+
+		radeon_object_kunmap(gtt_obj[i]);
+
+		r = radeon_fence_create(rdev, &fence);
+		if (r) {
+			DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i);
+			goto out_cleanup;
+		}
+
+		r = radeon_copy(rdev, gtt_addr, vram_addr, size / 4096, fence);
+		if (r) {
+			DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
+			goto out_cleanup;
+		}
+
+		r = radeon_fence_wait(fence, false);
+		if (r) {
+			DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
+			goto out_cleanup;
+		}
+
+		radeon_fence_unref(&fence);
+
+		r = radeon_object_kmap(vram_obj, &vram_map);
+		if (r) {
+			DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
+			goto out_cleanup;
+		}
+
+		for (gtt_start = gtt_map, gtt_end = gtt_map + size,
+		     vram_start = vram_map, vram_end = vram_map + size;
+		     vram_start < vram_end;
+		     gtt_start++, vram_start++) {
+			if (*vram_start != gtt_start) {
+				DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
+					  "expected 0x%p (GTT map 0x%p-0x%p)\n",
+					  i, *vram_start, gtt_start, gtt_map,
+					  gtt_end);
+				radeon_object_kunmap(vram_obj);
+				goto out_cleanup;
+			}
+			*vram_start = vram_start;
+		}
+
+		radeon_object_kunmap(vram_obj);
+
+		r = radeon_fence_create(rdev, &fence);
+		if (r) {
+			DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i);
+			goto out_cleanup;
+		}
+
+		r = radeon_copy(rdev, vram_addr, gtt_addr, size / 4096, fence);
+		if (r) {
+			DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
+			goto out_cleanup;
+		}
+
+		r = radeon_fence_wait(fence, false);
+		if (r) {
+			DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
+			goto out_cleanup;
+		}
+
+		radeon_fence_unref(&fence);
+
+		r = radeon_object_kmap(gtt_obj[i], &gtt_map);
+		if (r) {
+			DRM_ERROR("Failed to map GTT object after copy %d\n", i);
+			goto out_cleanup;
+		}
+
+		for (gtt_start = gtt_map, gtt_end = gtt_map + size,
+		     vram_start = vram_map, vram_end = vram_map + size;
+		     gtt_start < gtt_end;
+		     gtt_start++, vram_start++) {
+			if (*gtt_start != vram_start) {
+				DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
+					  "expected 0x%p (VRAM map 0x%p-0x%p)\n",
+					  i, *gtt_start, vram_start, vram_map,
+					  vram_end);
+				radeon_object_kunmap(gtt_obj[i]);
+				goto out_cleanup;
+			}
+		}
+
+		radeon_object_kunmap(gtt_obj[i]);
+
+		DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
+			 gtt_addr - rdev->mc.gtt_location);
+	}
+
+out_cleanup:
+	if (vram_obj) {
+		radeon_object_unpin(vram_obj);
+		radeon_object_unref(&vram_obj);
+	}
+	if (gtt_obj) {
+		for (i = 0; i < n; i++) {
+			if (gtt_obj[i]) {
+				radeon_object_unpin(gtt_obj[i]);
+				radeon_object_unref(&gtt_obj[i]);
+			}
+		}
+		kfree(gtt_obj);
+	}
+	if (fence) {
+		radeon_fence_unref(&fence);
+	}
+	if (r) {
+		printk(KERN_WARNING "Error while testing BO move.\n");
+	}
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_ttm.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_ttm.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,659 @@
+/*
+ * Copyright 2009 Jerome Glisse.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors:
+ *    Jerome Glisse <glisse@freedesktop.org>
+ *    Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ *    Dave Airlie
+ */
+#include <ttm/ttm_bo_api.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <ttm/ttm_module.h>
+#include <drm/drmP.h>
+#include <drm/radeon_drm.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev)
+{
+	struct radeon_mman *mman;
+	struct radeon_device *rdev;
+
+	mman = container_of(bdev, struct radeon_mman, bdev);
+	rdev = container_of(mman, struct radeon_device, mman);
+	return rdev;
+}
+
+
+/*
+ * Global memory.
+ */
+static int radeon_ttm_mem_global_init(struct ttm_global_reference *ref)
+{
+	return ttm_mem_global_init(ref->object);
+}
+
+static void radeon_ttm_mem_global_release(struct ttm_global_reference *ref)
+{
+	ttm_mem_global_release(ref->object);
+}
+
+static int radeon_ttm_global_init(struct radeon_device *rdev)
+{
+	struct ttm_global_reference *global_ref;
+	int r;
+
+	rdev->mman.mem_global_referenced = false;
+	global_ref = &rdev->mman.mem_global_ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_MEM;
+	global_ref->size = sizeof(struct ttm_mem_global);
+	global_ref->init = &radeon_ttm_mem_global_init;
+	global_ref->release = &radeon_ttm_mem_global_release;
+	r = ttm_global_item_ref(global_ref);
+	if (r != 0) {
+		DRM_ERROR("Failed referencing a global TTM memory object.\n");
+		return r;
+	}
+	rdev->mman.mem_global_referenced = true;
+	return 0;
+}
+
+static void radeon_ttm_global_fini(struct radeon_device *rdev)
+{
+	if (rdev->mman.mem_global_referenced) {
+		ttm_global_item_unref(&rdev->mman.mem_global_ref);
+		rdev->mman.mem_global_referenced = false;
+	}
+}
+
+struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev);
+
+static struct ttm_backend*
+radeon_create_ttm_backend_entry(struct ttm_bo_device *bdev)
+{
+	struct radeon_device *rdev;
+
+	rdev = radeon_get_rdev(bdev);
+#if __OS_HAS_AGP
+	if (rdev->flags & RADEON_IS_AGP) {
+		return ttm_agp_backend_init(bdev, rdev->ddev->agp->bridge);
+	} else
+#endif
+	{
+		return radeon_ttm_backend_create(rdev);
+	}
+}
+
+static int radeon_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
+{
+	return 0;
+}
+
+static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+				struct ttm_mem_type_manager *man)
+{
+	struct radeon_device *rdev;
+
+	rdev = radeon_get_rdev(bdev);
+
+	switch (type) {
+	case TTM_PL_SYSTEM:
+		/* System memory */
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		break;
+	case TTM_PL_TT:
+		man->gpu_offset = 0;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
+#if __OS_HAS_AGP
+		if (rdev->flags & RADEON_IS_AGP) {
+			if (!(drm_core_has_AGP(rdev->ddev) && rdev->ddev->agp)) {
+				DRM_ERROR("AGP is not enabled for memory type %u\n",
+					  (unsigned)type);
+				return -EINVAL;
+			}
+			man->io_offset = rdev->mc.agp_base;
+			man->io_size = rdev->mc.gtt_size;
+			man->io_addr = NULL;
+			if (!rdev->ddev->agp->cant_use_aperture)
+				man->flags = TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
+					     TTM_MEMTYPE_FLAG_MAPPABLE;
+			man->available_caching = TTM_PL_FLAG_UNCACHED |
+						 TTM_PL_FLAG_WC;
+			man->default_caching = TTM_PL_FLAG_WC;
+		} else
+#endif
+		{
+			man->io_offset = 0;
+			man->io_size = 0;
+			man->io_addr = NULL;
+		}
+		break;
+	case TTM_PL_VRAM:
+		/* "On-card" video ram */
+		man->gpu_offset = 0;
+		man->flags = TTM_MEMTYPE_FLAG_FIXED |
+			     TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
+			     TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+		man->default_caching = TTM_PL_FLAG_WC;
+		man->io_addr = NULL;
+		man->io_offset = rdev->mc.aper_base;
+		man->io_size = rdev->mc.aper_size;
+		break;
+	default:
+		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static uint32_t radeon_evict_flags(struct ttm_buffer_object *bo)
+{
+	uint32_t cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEMTYPE;
+
+	switch (bo->mem.mem_type) {
+	default:
+		return (cur_placement & ~TTM_PL_MASK_CACHING) |
+			TTM_PL_FLAG_SYSTEM |
+			TTM_PL_FLAG_CACHED;
+	}
+}
+
+static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp)
+{
+	return 0;
+}
+
+static void radeon_move_null(struct ttm_buffer_object *bo,
+			     struct ttm_mem_reg *new_mem)
+{
+	struct ttm_mem_reg *old_mem = &bo->mem;
+
+	BUG_ON(old_mem->mm_node != NULL);
+	*old_mem = *new_mem;
+	new_mem->mm_node = NULL;
+}
+
+static int radeon_move_blit(struct ttm_buffer_object *bo,
+			    bool evict, int no_wait,
+			    struct ttm_mem_reg *new_mem,
+			    struct ttm_mem_reg *old_mem)
+{
+	struct radeon_device *rdev;
+	uint64_t old_start, new_start;
+	struct radeon_fence *fence;
+	int r;
+
+	rdev = radeon_get_rdev(bo->bdev);
+	r = radeon_fence_create(rdev, &fence);
+	if (unlikely(r)) {
+		return r;
+	}
+	old_start = old_mem->mm_node->start << PAGE_SHIFT;
+	new_start = new_mem->mm_node->start << PAGE_SHIFT;
+
+	switch (old_mem->mem_type) {
+	case TTM_PL_VRAM:
+		old_start += rdev->mc.vram_location;
+		break;
+	case TTM_PL_TT:
+		old_start += rdev->mc.gtt_location;
+		break;
+	default:
+		DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
+		return -EINVAL;
+	}
+	switch (new_mem->mem_type) {
+	case TTM_PL_VRAM:
+		new_start += rdev->mc.vram_location;
+		break;
+	case TTM_PL_TT:
+		new_start += rdev->mc.gtt_location;
+		break;
+	default:
+		DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
+		return -EINVAL;
+	}
+	if (!rdev->cp.ready) {
+		DRM_ERROR("Trying to move memory with CP turned off.\n");
+		return -EINVAL;
+	}
+	r = radeon_copy(rdev, old_start, new_start, new_mem->num_pages, fence);
+	/* FIXME: handle copy error */
+	r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL,
+				      evict, no_wait, new_mem);
+	radeon_fence_unref(&fence);
+	return r;
+}
+
+static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
+				bool evict, bool interruptible, bool no_wait,
+				struct ttm_mem_reg *new_mem)
+{
+	struct radeon_device *rdev;
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	struct ttm_mem_reg tmp_mem;
+	uint32_t proposed_placement;
+	int r;
+
+	rdev = radeon_get_rdev(bo->bdev);
+	tmp_mem = *new_mem;
+	tmp_mem.mm_node = NULL;
+	proposed_placement = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
+	r = ttm_bo_mem_space(bo, proposed_placement, &tmp_mem,
+			     interruptible, no_wait);
+	if (unlikely(r)) {
+		return r;
+	}
+	r = ttm_tt_bind(bo->ttm, &tmp_mem);
+	if (unlikely(r)) {
+		goto out_cleanup;
+	}
+	r = radeon_move_blit(bo, true, no_wait, &tmp_mem, old_mem);
+	if (unlikely(r)) {
+		goto out_cleanup;
+	}
+	r = ttm_bo_move_ttm(bo, true, no_wait, new_mem);
+out_cleanup:
+	if (tmp_mem.mm_node) {
+		spin_lock(&rdev->mman.bdev.lru_lock);
+		drm_mm_put_block(tmp_mem.mm_node);
+		spin_unlock(&rdev->mman.bdev.lru_lock);
+		return r;
+	}
+	return r;
+}
+
+static int radeon_move_ram_vram(struct ttm_buffer_object *bo,
+				bool evict, bool interruptible, bool no_wait,
+				struct ttm_mem_reg *new_mem)
+{
+	struct radeon_device *rdev;
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	struct ttm_mem_reg tmp_mem;
+	uint32_t proposed_flags;
+	int r;
+
+	rdev = radeon_get_rdev(bo->bdev);
+	tmp_mem = *new_mem;
+	tmp_mem.mm_node = NULL;
+	proposed_flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
+	r = ttm_bo_mem_space(bo, proposed_flags, &tmp_mem,
+			     interruptible, no_wait);
+	if (unlikely(r)) {
+		return r;
+	}
+	r = ttm_bo_move_ttm(bo, true, no_wait, &tmp_mem);
+	if (unlikely(r)) {
+		goto out_cleanup;
+	}
+	r = radeon_move_blit(bo, true, no_wait, new_mem, old_mem);
+	if (unlikely(r)) {
+		goto out_cleanup;
+	}
+out_cleanup:
+	if (tmp_mem.mm_node) {
+		spin_lock(&rdev->mman.bdev.lru_lock);
+		drm_mm_put_block(tmp_mem.mm_node);
+		spin_unlock(&rdev->mman.bdev.lru_lock);
+		return r;
+	}
+	return r;
+}
+
+static int radeon_bo_move(struct ttm_buffer_object *bo,
+			  bool evict, bool interruptible, bool no_wait,
+			  struct ttm_mem_reg *new_mem)
+{
+	struct radeon_device *rdev;
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	int r;
+
+	rdev = radeon_get_rdev(bo->bdev);
+	if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
+		radeon_move_null(bo, new_mem);
+		return 0;
+	}
+	if ((old_mem->mem_type == TTM_PL_TT &&
+	     new_mem->mem_type == TTM_PL_SYSTEM) ||
+	    (old_mem->mem_type == TTM_PL_SYSTEM &&
+	     new_mem->mem_type == TTM_PL_TT)) {
+		/* bind is enought */
+		radeon_move_null(bo, new_mem);
+		return 0;
+	}
+	if (!rdev->cp.ready) {
+		/* use memcpy */
+		DRM_ERROR("CP is not ready use memcpy.\n");
+		goto memcpy;
+	}
+
+	if (old_mem->mem_type == TTM_PL_VRAM &&
+	    new_mem->mem_type == TTM_PL_SYSTEM) {
+		r = radeon_move_vram_ram(bo, evict, interruptible,
+					    no_wait, new_mem);
+	} else if (old_mem->mem_type == TTM_PL_SYSTEM &&
+		   new_mem->mem_type == TTM_PL_VRAM) {
+		r = radeon_move_ram_vram(bo, evict, interruptible,
+					    no_wait, new_mem);
+	} else {
+		r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem);
+	}
+
+	if (r) {
+memcpy:
+		r = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+	}
+
+	return r;
+}
+
+const uint32_t radeon_mem_prios[] = {
+	TTM_PL_VRAM,
+	TTM_PL_TT,
+	TTM_PL_SYSTEM,
+};
+
+const uint32_t radeon_busy_prios[] = {
+	TTM_PL_TT,
+	TTM_PL_VRAM,
+	TTM_PL_SYSTEM,
+};
+
+static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg,
+				bool lazy, bool interruptible)
+{
+	return radeon_fence_wait((struct radeon_fence *)sync_obj, interruptible);
+}
+
+static int radeon_sync_obj_flush(void *sync_obj, void *sync_arg)
+{
+	return 0;
+}
+
+static void radeon_sync_obj_unref(void **sync_obj)
+{
+	radeon_fence_unref((struct radeon_fence **)sync_obj);
+}
+
+static void *radeon_sync_obj_ref(void *sync_obj)
+{
+	return radeon_fence_ref((struct radeon_fence *)sync_obj);
+}
+
+static bool radeon_sync_obj_signaled(void *sync_obj, void *sync_arg)
+{
+	return radeon_fence_signaled((struct radeon_fence *)sync_obj);
+}
+
+static struct ttm_bo_driver radeon_bo_driver = {
+	.mem_type_prio = radeon_mem_prios,
+	.mem_busy_prio = radeon_busy_prios,
+	.num_mem_type_prio = ARRAY_SIZE(radeon_mem_prios),
+	.num_mem_busy_prio = ARRAY_SIZE(radeon_busy_prios),
+	.create_ttm_backend_entry = &radeon_create_ttm_backend_entry,
+	.invalidate_caches = &radeon_invalidate_caches,
+	.init_mem_type = &radeon_init_mem_type,
+	.evict_flags = &radeon_evict_flags,
+	.move = &radeon_bo_move,
+	.verify_access = &radeon_verify_access,
+	.sync_obj_signaled = &radeon_sync_obj_signaled,
+	.sync_obj_wait = &radeon_sync_obj_wait,
+	.sync_obj_flush = &radeon_sync_obj_flush,
+	.sync_obj_unref = &radeon_sync_obj_unref,
+	.sync_obj_ref = &radeon_sync_obj_ref,
+	.move_notify = &radeon_bo_move_notify,
+	.fault_reserve_notify = &radeon_bo_fault_reserve_notify,
+};
+
+int radeon_ttm_init(struct radeon_device *rdev)
+{
+	int r;
+
+	r = radeon_ttm_global_init(rdev);
+	if (r) {
+		return r;
+	}
+	/* No others user of address space so set it to 0 */
+	r = ttm_bo_device_init(&rdev->mman.bdev,
+			       rdev->mman.mem_global_ref.object,
+			       &radeon_bo_driver, DRM_FILE_PAGE_OFFSET,
+			       rdev->need_dma32);
+	if (r) {
+		DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
+		return r;
+	}
+	r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0,
+			   ((rdev->mc.real_vram_size) >> PAGE_SHIFT));
+	if (r) {
+		DRM_ERROR("Failed initializing VRAM heap.\n");
+		return r;
+	}
+	r = radeon_object_create(rdev, NULL, 256 * 1024, true,
+				 RADEON_GEM_DOMAIN_VRAM, false,
+				 &rdev->stollen_vga_memory);
+	if (r) {
+		return r;
+	}
+	r = radeon_object_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL);
+	if (r) {
+		radeon_object_unref(&rdev->stollen_vga_memory);
+		return r;
+	}
+	DRM_INFO("radeon: %uM of VRAM memory ready\n",
+		 rdev->mc.real_vram_size / (1024 * 1024));
+	r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0,
+			   ((rdev->mc.gtt_size) >> PAGE_SHIFT));
+	if (r) {
+		DRM_ERROR("Failed initializing GTT heap.\n");
+		return r;
+	}
+	DRM_INFO("radeon: %uM of GTT memory ready.\n",
+		 rdev->mc.gtt_size / (1024 * 1024));
+	if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
+		rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping;
+	}
+	return 0;
+}
+
+void radeon_ttm_fini(struct radeon_device *rdev)
+{
+	if (rdev->stollen_vga_memory) {
+		radeon_object_unpin(rdev->stollen_vga_memory);
+		radeon_object_unref(&rdev->stollen_vga_memory);
+	}
+	ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM);
+	ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT);
+	ttm_bo_device_release(&rdev->mman.bdev);
+	radeon_gart_fini(rdev);
+	radeon_ttm_global_fini(rdev);
+	DRM_INFO("radeon: ttm finalized\n");
+}
+
+static struct vm_operations_struct radeon_ttm_vm_ops;
+static struct vm_operations_struct *ttm_vm_ops = NULL;
+
+static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct ttm_buffer_object *bo;
+	int r;
+
+	bo = (struct ttm_buffer_object *)vma->vm_private_data;
+	if (bo == NULL) {
+		return VM_FAULT_NOPAGE;
+	}
+	r = ttm_vm_ops->fault(vma, vmf);
+	return r;
+}
+
+int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	struct radeon_device *rdev;
+	int r;
+
+	if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) {
+		return drm_mmap(filp, vma);
+	}
+
+	file_priv = (struct drm_file *)filp->private_data;
+	rdev = file_priv->minor->dev->dev_private;
+	if (rdev == NULL) {
+		return -EINVAL;
+	}
+	r = ttm_bo_mmap(filp, vma, &rdev->mman.bdev);
+	if (unlikely(r != 0)) {
+		return r;
+	}
+	if (unlikely(ttm_vm_ops == NULL)) {
+		ttm_vm_ops = vma->vm_ops;
+		radeon_ttm_vm_ops = *ttm_vm_ops;
+		radeon_ttm_vm_ops.fault = &radeon_ttm_fault;
+	}
+	vma->vm_ops = &radeon_ttm_vm_ops;
+	return 0;
+}
+
+
+/*
+ * TTM backend functions.
+ */
+struct radeon_ttm_backend {
+	struct ttm_backend		backend;
+	struct radeon_device		*rdev;
+	unsigned long			num_pages;
+	struct page			**pages;
+	struct page			*dummy_read_page;
+	bool				populated;
+	bool				bound;
+	unsigned			offset;
+};
+
+static int radeon_ttm_backend_populate(struct ttm_backend *backend,
+				       unsigned long num_pages,
+				       struct page **pages,
+				       struct page *dummy_read_page)
+{
+	struct radeon_ttm_backend *gtt;
+
+	gtt = container_of(backend, struct radeon_ttm_backend, backend);
+	gtt->pages = pages;
+	gtt->num_pages = num_pages;
+	gtt->dummy_read_page = dummy_read_page;
+	gtt->populated = true;
+	return 0;
+}
+
+static void radeon_ttm_backend_clear(struct ttm_backend *backend)
+{
+	struct radeon_ttm_backend *gtt;
+
+	gtt = container_of(backend, struct radeon_ttm_backend, backend);
+	gtt->pages = NULL;
+	gtt->num_pages = 0;
+	gtt->dummy_read_page = NULL;
+	gtt->populated = false;
+	gtt->bound = false;
+}
+
+
+static int radeon_ttm_backend_bind(struct ttm_backend *backend,
+				   struct ttm_mem_reg *bo_mem)
+{
+	struct radeon_ttm_backend *gtt;
+	int r;
+
+	gtt = container_of(backend, struct radeon_ttm_backend, backend);
+	gtt->offset = bo_mem->mm_node->start << PAGE_SHIFT;
+	if (!gtt->num_pages) {
+		WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", gtt->num_pages, bo_mem, backend);
+	}
+	r = radeon_gart_bind(gtt->rdev, gtt->offset,
+			     gtt->num_pages, gtt->pages);
+	if (r) {
+		DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
+			  gtt->num_pages, gtt->offset);
+		return r;
+	}
+	gtt->bound = true;
+	return 0;
+}
+
+static int radeon_ttm_backend_unbind(struct ttm_backend *backend)
+{
+	struct radeon_ttm_backend *gtt;
+
+	gtt = container_of(backend, struct radeon_ttm_backend, backend);
+	radeon_gart_unbind(gtt->rdev, gtt->offset, gtt->num_pages);
+	gtt->bound = false;
+	return 0;
+}
+
+static void radeon_ttm_backend_destroy(struct ttm_backend *backend)
+{
+	struct radeon_ttm_backend *gtt;
+
+	gtt = container_of(backend, struct radeon_ttm_backend, backend);
+	if (gtt->bound) {
+		radeon_ttm_backend_unbind(backend);
+	}
+	kfree(gtt);
+}
+
+static struct ttm_backend_func radeon_backend_func = {
+	.populate = &radeon_ttm_backend_populate,
+	.clear = &radeon_ttm_backend_clear,
+	.bind = &radeon_ttm_backend_bind,
+	.unbind = &radeon_ttm_backend_unbind,
+	.destroy = &radeon_ttm_backend_destroy,
+};
+
+struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev)
+{
+	struct radeon_ttm_backend *gtt;
+
+	gtt = kzalloc(sizeof(struct radeon_ttm_backend), GFP_KERNEL);
+	if (gtt == NULL) {
+		return NULL;
+	}
+	gtt->backend.bdev = &rdev->mman.bdev;
+	gtt->backend.flags = 0;
+	gtt->backend.func = &radeon_backend_func;
+	gtt->rdev = rdev;
+	gtt->pages = NULL;
+	gtt->num_pages = 0;
+	gtt->dummy_read_page = NULL;
+	gtt->populated = false;
+	gtt->bound = false;
+	return &gtt->backend;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs400.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs400.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs400.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs400.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include <linux/seq_file.h>
+#include <drm/drmP.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "radeon_share.h"
+
+/* rs400,rs480 depends on : */
+void r100_hdp_reset(struct radeon_device *rdev);
+void r100_mc_disable_clients(struct radeon_device *rdev);
+int r300_mc_wait_for_idle(struct radeon_device *rdev);
+void r420_pipes_init(struct radeon_device *rdev);
+
+/* This files gather functions specifics to :
+ * rs400,rs480
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+void rs400_gpu_init(struct radeon_device *rdev);
+int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev);
+
+
+/*
+ * GART functions.
+ */
+void rs400_gart_adjust_size(struct radeon_device *rdev)
+{
+	/* Check gart size */
+	switch (rdev->mc.gtt_size/(1024*1024)) {
+	case 32:
+	case 64:
+	case 128:
+	case 256:
+	case 512:
+	case 1024:
+	case 2048:
+		break;
+	default:
+		DRM_ERROR("Unable to use IGP GART size %uM\n",
+			  rdev->mc.gtt_size >> 20);
+		DRM_ERROR("Valid GART size for IGP are 32M,64M,128M,256M,512M,1G,2G\n");
+		DRM_ERROR("Forcing to 32M GART size\n");
+		rdev->mc.gtt_size = 32 * 1024 * 1024;
+		return;
+	}
+	if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) {
+		/* FIXME: RS400 & RS480 seems to have issue with GART size
+		 * if 4G of system memory (needs more testing) */
+		rdev->mc.gtt_size = 32 * 1024 * 1024;
+		DRM_ERROR("Forcing to 32M GART size (because of ASIC bug ?)\n");
+	}
+}
+
+void rs400_gart_tlb_flush(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	unsigned int timeout = rdev->usec_timeout;
+
+	WREG32_MC(RS480_GART_CACHE_CNTRL, RS480_GART_CACHE_INVALIDATE);
+	do {
+		tmp = RREG32_MC(RS480_GART_CACHE_CNTRL);
+		if ((tmp & RS480_GART_CACHE_INVALIDATE) == 0)
+			break;
+		DRM_UDELAY(1);
+		timeout--;
+	} while (timeout > 0);
+	WREG32_MC(RS480_GART_CACHE_CNTRL, 0);
+}
+
+int rs400_gart_enable(struct radeon_device *rdev)
+{
+	uint32_t size_reg;
+	uint32_t tmp;
+	int r;
+
+	/* Initialize common gart structure */
+	r = radeon_gart_init(rdev);
+	if (r) {
+		return r;
+	}
+	if (rs400_debugfs_pcie_gart_info_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RS400 GART !\n");
+	}
+
+	tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
+	tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS;
+	WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp);
+	/* Check gart size */
+	switch(rdev->mc.gtt_size / (1024 * 1024)) {
+	case 32:
+		size_reg = RS480_VA_SIZE_32MB;
+		break;
+	case 64:
+		size_reg = RS480_VA_SIZE_64MB;
+		break;
+	case 128:
+		size_reg = RS480_VA_SIZE_128MB;
+		break;
+	case 256:
+		size_reg = RS480_VA_SIZE_256MB;
+		break;
+	case 512:
+		size_reg = RS480_VA_SIZE_512MB;
+		break;
+	case 1024:
+		size_reg = RS480_VA_SIZE_1GB;
+		break;
+	case 2048:
+		size_reg = RS480_VA_SIZE_2GB;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (rdev->gart.table.ram.ptr == NULL) {
+		rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
+		r = radeon_gart_table_ram_alloc(rdev);
+		if (r) {
+			return r;
+		}
+	}
+	/* It should be fine to program it to max value */
+	if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) {
+		WREG32_MC(RS690_MCCFG_AGP_BASE, 0xFFFFFFFF);
+		WREG32_MC(RS690_MCCFG_AGP_BASE_2, 0);
+	} else {
+		WREG32(RADEON_AGP_BASE, 0xFFFFFFFF);
+		WREG32(RS480_AGP_BASE_2, 0);
+	}
+	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	tmp = REG_SET(RS690_MC_AGP_TOP, tmp >> 16);
+	tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_location >> 16);
+	if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) {
+		WREG32_MC(RS690_MCCFG_AGP_LOCATION, tmp);
+		tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
+		WREG32(RADEON_BUS_CNTL, tmp);
+	} else {
+		WREG32(RADEON_MC_AGP_LOCATION, tmp);
+		tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+		WREG32(RADEON_BUS_CNTL, tmp);
+	}
+	/* Table should be in 32bits address space so ignore bits above. */
+	tmp = (u32)rdev->gart.table_addr & 0xfffff000;
+	tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4;
+
+	WREG32_MC(RS480_GART_BASE, tmp);
+	/* TODO: more tweaking here */
+	WREG32_MC(RS480_GART_FEATURE_ID,
+		  (RS480_TLB_ENABLE |
+		   RS480_GTW_LAC_EN | RS480_1LEVEL_GART));
+	/* Disable snooping */
+	WREG32_MC(RS480_AGP_MODE_CNTL,
+		  (1 << RS480_REQ_TYPE_SNOOP_SHIFT) | RS480_REQ_TYPE_SNOOP_DIS);
+	/* Disable AGP mode */
+	/* FIXME: according to doc we should set HIDE_MMCFG_BAR=0,
+	 * AGPMODE30=0 & AGP30ENHANCED=0 in NB_CNTL */
+	if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) {
+		WREG32_MC(RS480_MC_MISC_CNTL,
+			  (RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN));
+	} else {
+		WREG32_MC(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN);
+	}
+	/* Enable gart */
+	WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg));
+	rs400_gart_tlb_flush(rdev);
+	rdev->gart.ready = true;
+	return 0;
+}
+
+void rs400_gart_disable(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
+	tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS;
+	WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp);
+	WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
+}
+
+int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
+{
+	uint32_t entry;
+
+	if (i < 0 || i > rdev->gart.num_gpu_pages) {
+		return -EINVAL;
+	}
+
+	entry = (lower_32_bits(addr) & PAGE_MASK) |
+		((upper_32_bits(addr) & 0xff) << 4) |
+		0xc;
+	entry = cpu_to_le32(entry);
+	rdev->gart.table.ram.ptr[i] = entry;
+	return 0;
+}
+
+
+/*
+ * MC functions.
+ */
+int rs400_mc_init(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+
+	rs400_gpu_init(rdev);
+	rs400_gart_disable(rdev);
+	rdev->mc.gtt_location = rdev->mc.mc_vram_size;
+	rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
+	rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	r100_mc_disable_clients(rdev);
+	if (r300_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
+	tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
+	WREG32(RADEON_MC_FB_LOCATION, tmp);
+	tmp = RREG32(RADEON_HOST_PATH_CNTL) | RADEON_HP_LIN_RD_CACHE_DIS;
+	WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE);
+	(void)RREG32(RADEON_HOST_PATH_CNTL);
+	WREG32(RADEON_HOST_PATH_CNTL, tmp);
+	(void)RREG32(RADEON_HOST_PATH_CNTL);
+	return 0;
+}
+
+void rs400_mc_fini(struct radeon_device *rdev)
+{
+	rs400_gart_disable(rdev);
+	radeon_gart_table_ram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Global GPU functions
+ */
+void rs400_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+void rs400_gpu_init(struct radeon_device *rdev)
+{
+	/* FIXME: HDP same place on rs400 ? */
+	r100_hdp_reset(rdev);
+	/* FIXME: is this correct ? */
+	r420_pipes_init(rdev);
+	if (r300_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+}
+
+
+/*
+ * VRAM info.
+ */
+void rs400_vram_info(struct radeon_device *rdev)
+{
+	rs400_gart_adjust_size(rdev);
+	/* DDR for all card after R300 & IGP */
+	rdev->mc.vram_is_ddr = true;
+	rdev->mc.vram_width = 128;
+
+	r100_vram_init_sizes(rdev);
+}
+
+
+/*
+ * Indirect registers accessor
+ */
+uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t r;
+
+	WREG32(RS480_NB_MC_INDEX, reg & 0xff);
+	r = RREG32(RS480_NB_MC_DATA);
+	WREG32(RS480_NB_MC_INDEX, 0xff);
+	return r;
+}
+
+void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN);
+	WREG32(RS480_NB_MC_DATA, (v));
+	WREG32(RS480_NB_MC_INDEX, 0xff);
+}
+
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int rs400_debugfs_gart_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = RREG32(RADEON_HOST_PATH_CNTL);
+	seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp);
+	tmp = RREG32(RADEON_BUS_CNTL);
+	seq_printf(m, "BUS_CNTL 0x%08x\n", tmp);
+	tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
+	seq_printf(m, "AIC_CTRL_SCRATCH 0x%08x\n", tmp);
+	if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) {
+		tmp = RREG32_MC(RS690_MCCFG_AGP_BASE);
+		seq_printf(m, "MCCFG_AGP_BASE 0x%08x\n", tmp);
+		tmp = RREG32_MC(RS690_MCCFG_AGP_BASE_2);
+		seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp);
+		tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION);
+		seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp);
+		tmp = RREG32_MC(0x100);
+		seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp);
+		tmp = RREG32(0x134);
+		seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp);
+	} else {
+		tmp = RREG32(RADEON_AGP_BASE);
+		seq_printf(m, "AGP_BASE 0x%08x\n", tmp);
+		tmp = RREG32(RS480_AGP_BASE_2);
+		seq_printf(m, "AGP_BASE_2 0x%08x\n", tmp);
+		tmp = RREG32(RADEON_MC_AGP_LOCATION);
+		seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp);
+	}
+	tmp = RREG32_MC(RS480_GART_BASE);
+	seq_printf(m, "GART_BASE 0x%08x\n", tmp);
+	tmp = RREG32_MC(RS480_GART_FEATURE_ID);
+	seq_printf(m, "GART_FEATURE_ID 0x%08x\n", tmp);
+	tmp = RREG32_MC(RS480_AGP_MODE_CNTL);
+	seq_printf(m, "AGP_MODE_CONTROL 0x%08x\n", tmp);
+	tmp = RREG32_MC(RS480_MC_MISC_CNTL);
+	seq_printf(m, "MC_MISC_CNTL 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x5F);
+	seq_printf(m, "MC_MISC_UMA_CNTL 0x%08x\n", tmp);
+	tmp = RREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE);
+	seq_printf(m, "AGP_ADDRESS_SPACE_SIZE 0x%08x\n", tmp);
+	tmp = RREG32_MC(RS480_GART_CACHE_CNTRL);
+	seq_printf(m, "GART_CACHE_CNTRL 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x3B);
+	seq_printf(m, "MC_GART_ERROR_ADDRESS 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x3C);
+	seq_printf(m, "MC_GART_ERROR_ADDRESS_HI 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x30);
+	seq_printf(m, "GART_ERROR_0 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x31);
+	seq_printf(m, "GART_ERROR_1 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x32);
+	seq_printf(m, "GART_ERROR_2 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x33);
+	seq_printf(m, "GART_ERROR_3 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x34);
+	seq_printf(m, "GART_ERROR_4 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x35);
+	seq_printf(m, "GART_ERROR_5 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x36);
+	seq_printf(m, "GART_ERROR_6 0x%08x\n", tmp);
+	tmp = RREG32_MC(0x37);
+	seq_printf(m, "GART_ERROR_7 0x%08x\n", tmp);
+	return 0;
+}
+
+static struct drm_info_list rs400_gart_info_list[] = {
+	{"rs400_gart_info", rs400_debugfs_gart_info, 0, NULL},
+};
+#endif
+
+int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1);
+#else
+	return 0;
+#endif
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs600.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs600.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs600.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+/* rs600 depends on : */
+void r100_hdp_reset(struct radeon_device *rdev);
+int r100_gui_wait_for_idle(struct radeon_device *rdev);
+int r300_mc_wait_for_idle(struct radeon_device *rdev);
+void r420_pipes_init(struct radeon_device *rdev);
+
+/* This files gather functions specifics to :
+ * rs600
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+void rs600_gpu_init(struct radeon_device *rdev);
+int rs600_mc_wait_for_idle(struct radeon_device *rdev);
+void rs600_disable_vga(struct radeon_device *rdev);
+
+
+/*
+ * GART.
+ */
+void rs600_gart_tlb_flush(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	tmp = RREG32_MC(RS600_MC_PT0_CNTL);
+	tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
+	WREG32_MC(RS600_MC_PT0_CNTL, tmp);
+
+	tmp = RREG32_MC(RS600_MC_PT0_CNTL);
+	tmp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE;
+	WREG32_MC(RS600_MC_PT0_CNTL, tmp);
+
+	tmp = RREG32_MC(RS600_MC_PT0_CNTL);
+	tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
+	WREG32_MC(RS600_MC_PT0_CNTL, tmp);
+	tmp = RREG32_MC(RS600_MC_PT0_CNTL);
+}
+
+int rs600_gart_enable(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int i;
+	int r;
+
+	/* Initialize common gart structure */
+	r = radeon_gart_init(rdev);
+	if (r) {
+		return r;
+	}
+	rdev->gart.table_size = rdev->gart.num_gpu_pages * 8;
+	r = radeon_gart_table_vram_alloc(rdev);
+	if (r) {
+		return r;
+	}
+	/* FIXME: setup default page */
+	WREG32_MC(RS600_MC_PT0_CNTL,
+		 (RS600_EFFECTIVE_L2_CACHE_SIZE(6) |
+		  RS600_EFFECTIVE_L2_QUEUE_SIZE(6)));
+	for (i = 0; i < 19; i++) {
+		WREG32_MC(RS600_MC_PT0_CLIENT0_CNTL + i,
+			 (RS600_ENABLE_TRANSLATION_MODE_OVERRIDE |
+			  RS600_SYSTEM_ACCESS_MODE_IN_SYS |
+			  RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE |
+			  RS600_EFFECTIVE_L1_CACHE_SIZE(3) |
+			  RS600_ENABLE_FRAGMENT_PROCESSING |
+			  RS600_EFFECTIVE_L1_QUEUE_SIZE(3)));
+	}
+
+	/* System context map to GART space */
+	WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_location);
+	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, tmp);
+
+	/* enable first context */
+	WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_location);
+	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR, tmp);
+	WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL,
+		 (RS600_ENABLE_PAGE_TABLE | RS600_PAGE_TABLE_TYPE_FLAT));
+	/* disable all other contexts */
+	for (i = 1; i < 8; i++) {
+		WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL + i, 0);
+	}
+
+	/* setup the page table */
+	WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
+		 rdev->gart.table_addr);
+	WREG32_MC(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
+
+	/* enable page tables */
+	tmp = RREG32_MC(RS600_MC_PT0_CNTL);
+	WREG32_MC(RS600_MC_PT0_CNTL, (tmp | RS600_ENABLE_PT));
+	tmp = RREG32_MC(RS600_MC_CNTL1);
+	WREG32_MC(RS600_MC_CNTL1, (tmp | RS600_ENABLE_PAGE_TABLES));
+	rs600_gart_tlb_flush(rdev);
+	rdev->gart.ready = true;
+	return 0;
+}
+
+void rs600_gart_disable(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	/* FIXME: disable out of gart access */
+	WREG32_MC(RS600_MC_PT0_CNTL, 0);
+	tmp = RREG32_MC(RS600_MC_CNTL1);
+	tmp &= ~RS600_ENABLE_PAGE_TABLES;
+	WREG32_MC(RS600_MC_CNTL1, tmp);
+	radeon_object_kunmap(rdev->gart.table.vram.robj);
+	radeon_object_unpin(rdev->gart.table.vram.robj);
+}
+
+#define R600_PTE_VALID     (1 << 0)
+#define R600_PTE_SYSTEM    (1 << 1)
+#define R600_PTE_SNOOPED   (1 << 2)
+#define R600_PTE_READABLE  (1 << 5)
+#define R600_PTE_WRITEABLE (1 << 6)
+
+int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
+{
+	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+
+	if (i < 0 || i > rdev->gart.num_gpu_pages) {
+		return -EINVAL;
+	}
+	addr = addr & 0xFFFFFFFFFFFFF000ULL;
+	addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED;
+	addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
+	writeq(addr, ((void __iomem *)ptr) + (i * 8));
+	return 0;
+}
+
+
+/*
+ * MC.
+ */
+void rs600_mc_disable_clients(struct radeon_device *rdev)
+{
+	unsigned tmp;
+
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	tmp = RREG32(AVIVO_D1VGA_CONTROL);
+	WREG32(AVIVO_D1VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
+	tmp = RREG32(AVIVO_D2VGA_CONTROL);
+	WREG32(AVIVO_D2VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
+
+	tmp = RREG32(AVIVO_D1CRTC_CONTROL);
+	WREG32(AVIVO_D1CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN);
+	tmp = RREG32(AVIVO_D2CRTC_CONTROL);
+	WREG32(AVIVO_D2CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN);
+
+	/* make sure all previous write got through */
+	tmp = RREG32(AVIVO_D2CRTC_CONTROL);
+
+	mdelay(1);
+}
+
+int rs600_mc_init(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+
+	rs600_gpu_init(rdev);
+	rs600_gart_disable(rdev);
+
+	/* Setup GPU memory space */
+	rdev->mc.vram_location = 0xFFFFFFFFUL;
+	rdev->mc.gtt_location = 0xFFFFFFFFUL;
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	/* Program GPU memory space */
+	/* Enable bus master */
+	tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
+	WREG32(RADEON_BUS_CNTL, tmp);
+	/* FIXME: What does AGP means for such chipset ? */
+	WREG32_MC(RS600_MC_AGP_LOCATION, 0x0FFFFFFF);
+	/* FIXME: are this AGP reg in indirect MC range ? */
+	WREG32_MC(RS600_MC_AGP_BASE, 0);
+	WREG32_MC(RS600_MC_AGP_BASE_2, 0);
+	rs600_mc_disable_clients(rdev);
+	if (rs600_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16);
+	tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16);
+	WREG32_MC(RS600_MC_FB_LOCATION, tmp);
+	WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
+	return 0;
+}
+
+void rs600_mc_fini(struct radeon_device *rdev)
+{
+	rs600_gart_disable(rdev);
+	radeon_gart_table_vram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Interrupts
+ */
+int rs600_irq_set(struct radeon_device *rdev)
+{
+	uint32_t tmp = 0;
+	uint32_t mode_int = 0;
+
+	if (rdev->irq.sw_int) {
+		tmp |= RADEON_SW_INT_ENABLE;
+	}
+	if (rdev->irq.crtc_vblank_int[0]) {
+		tmp |= AVIVO_DISPLAY_INT_STATUS;
+		mode_int |= AVIVO_D1MODE_INT_MASK;
+	}
+	if (rdev->irq.crtc_vblank_int[1]) {
+		tmp |= AVIVO_DISPLAY_INT_STATUS;
+		mode_int |= AVIVO_D2MODE_INT_MASK;
+	}
+	WREG32(RADEON_GEN_INT_CNTL, tmp);
+	WREG32(AVIVO_DxMODE_INT_MASK, mode_int);
+	return 0;
+}
+
+static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int)
+{
+	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
+	uint32_t irq_mask = RADEON_SW_INT_TEST;
+
+	if (irqs & AVIVO_DISPLAY_INT_STATUS) {
+		*r500_disp_int = RREG32(AVIVO_DISP_INTERRUPT_STATUS);
+		if (*r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) {
+			WREG32(AVIVO_D1MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK);
+		}
+		if (*r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) {
+			WREG32(AVIVO_D2MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK);
+		}
+	} else {
+		*r500_disp_int = 0;
+	}
+
+	if (irqs) {
+		WREG32(RADEON_GEN_INT_STATUS, irqs);
+	}
+	return irqs & irq_mask;
+}
+
+int rs600_irq_process(struct radeon_device *rdev)
+{
+	uint32_t status;
+	uint32_t r500_disp_int;
+
+	status = rs600_irq_ack(rdev, &r500_disp_int);
+	if (!status && !r500_disp_int) {
+		return IRQ_NONE;
+	}
+	while (status || r500_disp_int) {
+		/* SW interrupt */
+		if (status & RADEON_SW_INT_TEST) {
+			radeon_fence_process(rdev);
+		}
+		/* Vertical blank interrupts */
+		if (r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) {
+			drm_handle_vblank(rdev->ddev, 0);
+		}
+		if (r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) {
+			drm_handle_vblank(rdev->ddev, 1);
+		}
+		status = rs600_irq_ack(rdev, &r500_disp_int);
+	}
+	return IRQ_HANDLED;
+}
+
+u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc)
+{
+	if (crtc == 0)
+		return RREG32(AVIVO_D1CRTC_FRAME_COUNT);
+	else
+		return RREG32(AVIVO_D2CRTC_FRAME_COUNT);
+}
+
+
+/*
+ * Global GPU functions
+ */
+void rs600_disable_vga(struct radeon_device *rdev)
+{
+	unsigned tmp;
+
+	WREG32(0x330, 0);
+	WREG32(0x338, 0);
+	tmp = RREG32(0x300);
+	tmp &= ~(3 << 16);
+	WREG32(0x300, tmp);
+	WREG32(0x308, (1 << 8));
+	WREG32(0x310, rdev->mc.vram_location);
+	WREG32(0x594, 0);
+}
+
+int rs600_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32_MC(RS600_MC_STATUS);
+		if (tmp & RS600_MC_STATUS_IDLE) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+void rs600_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+void rs600_gpu_init(struct radeon_device *rdev)
+{
+	/* FIXME: HDP same place on rs600 ? */
+	r100_hdp_reset(rdev);
+	rs600_disable_vga(rdev);
+	/* FIXME: is this correct ? */
+	r420_pipes_init(rdev);
+	if (rs600_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+}
+
+
+/*
+ * VRAM info.
+ */
+void rs600_vram_info(struct radeon_device *rdev)
+{
+	/* FIXME: to do or is these values sane ? */
+	rdev->mc.vram_is_ddr = true;
+	rdev->mc.vram_width = 128;
+}
+
+void rs600_bandwidth_update(struct radeon_device *rdev)
+{
+	/* FIXME: implement, should this be like rs690 ? */
+}
+
+
+/*
+ * Indirect registers accessor
+ */
+uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t r;
+
+	WREG32(RS600_MC_INDEX,
+	       ((reg & RS600_MC_ADDR_MASK) | RS600_MC_IND_CITF_ARB0));
+	r = RREG32(RS600_MC_DATA);
+	return r;
+}
+
+void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG32(RS600_MC_INDEX,
+		RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 |
+		((reg) & RS600_MC_ADDR_MASK));
+	WREG32(RS600_MC_DATA, v);
+}
+
+static const unsigned rs600_reg_safe_bm[219] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
+	0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
+	0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
+	0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
+	0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+	0x00000000, 0x0000C100, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x0003FC01, 0xFFFFFCF8, 0xFF800B19, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+};
+
+int rs600_init(struct radeon_device *rdev)
+{
+	rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm;
+	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs600_reg_safe_bm);
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs690.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs690.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs690.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs690.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,655 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "rs690r.h"
+#include "atom.h"
+#include "atom-bits.h"
+
+/* rs690,rs740 depends on : */
+void r100_hdp_reset(struct radeon_device *rdev);
+int r300_mc_wait_for_idle(struct radeon_device *rdev);
+void r420_pipes_init(struct radeon_device *rdev);
+void rs400_gart_disable(struct radeon_device *rdev);
+int rs400_gart_enable(struct radeon_device *rdev);
+void rs400_gart_adjust_size(struct radeon_device *rdev);
+void rs600_mc_disable_clients(struct radeon_device *rdev);
+void rs600_disable_vga(struct radeon_device *rdev);
+
+/* This files gather functions specifics to :
+ * rs690,rs740
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+void rs690_gpu_init(struct radeon_device *rdev);
+int rs690_mc_wait_for_idle(struct radeon_device *rdev);
+
+
+/*
+ * MC functions.
+ */
+int rs690_mc_init(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+
+	rs690_gpu_init(rdev);
+	rs400_gart_disable(rdev);
+
+	/* Setup GPU memory space */
+	rdev->mc.gtt_location = rdev->mc.mc_vram_size;
+	rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
+	rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
+	rdev->mc.vram_location = 0xFFFFFFFFUL;
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	/* Program GPU memory space */
+	rs600_mc_disable_clients(rdev);
+	if (rs690_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16);
+	tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16);
+	WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp);
+	/* FIXME: Does this reg exist on RS480,RS740 ? */
+	WREG32(0x310, rdev->mc.vram_location);
+	WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
+	return 0;
+}
+
+void rs690_mc_fini(struct radeon_device *rdev)
+{
+	rs400_gart_disable(rdev);
+	radeon_gart_table_ram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Global GPU functions
+ */
+int rs690_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32_MC(RS690_MC_STATUS);
+		if (tmp & RS690_MC_STATUS_IDLE) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+void rs690_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+void rs690_gpu_init(struct radeon_device *rdev)
+{
+	/* FIXME: HDP same place on rs690 ? */
+	r100_hdp_reset(rdev);
+	rs600_disable_vga(rdev);
+	/* FIXME: is this correct ? */
+	r420_pipes_init(rdev);
+	if (rs690_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+}
+
+
+/*
+ * VRAM info.
+ */
+void rs690_pm_info(struct radeon_device *rdev)
+{
+	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
+	struct _ATOM_INTEGRATED_SYSTEM_INFO *info;
+	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
+	void *ptr;
+	uint16_t data_offset;
+	uint8_t frev, crev;
+	fixed20_12 tmp;
+
+	atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
+			       &frev, &crev, &data_offset);
+	ptr = rdev->mode_info.atom_context->bios + data_offset;
+	info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
+	info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr;
+	/* Get various system informations from bios */
+	switch (crev) {
+	case 1:
+		tmp.full = rfixed_const(100);
+		rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock);
+		rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
+		rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock));
+		rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock));
+		rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth);
+		break;
+	case 2:
+		tmp.full = rfixed_const(100);
+		rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock);
+		rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
+		rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock);
+		rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
+		rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq);
+		rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
+		rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth));
+		break;
+	default:
+		tmp.full = rfixed_const(100);
+		/* We assume the slower possible clock ie worst case */
+		/* DDR 333Mhz */
+		rdev->pm.igp_sideport_mclk.full = rfixed_const(333);
+		/* FIXME: system clock ? */
+		rdev->pm.igp_system_mclk.full = rfixed_const(100);
+		rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
+		rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
+		rdev->pm.igp_ht_link_width.full = rfixed_const(8);
+		DRM_ERROR("No integrated system info for your GPU, using safe default\n");
+		break;
+	}
+	/* Compute various bandwidth */
+	/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4  */
+	tmp.full = rfixed_const(4);
+	rdev->pm.k8_bandwidth.full = rfixed_mul(rdev->pm.igp_system_mclk, tmp);
+	/* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8
+	 *              = ht_clk * ht_width / 5
+	 */
+	tmp.full = rfixed_const(5);
+	rdev->pm.ht_bandwidth.full = rfixed_mul(rdev->pm.igp_ht_link_clk,
+						rdev->pm.igp_ht_link_width);
+	rdev->pm.ht_bandwidth.full = rfixed_div(rdev->pm.ht_bandwidth, tmp);
+	if (tmp.full < rdev->pm.max_bandwidth.full) {
+		/* HT link is a limiting factor */
+		rdev->pm.max_bandwidth.full = tmp.full;
+	}
+	/* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7
+	 *                    = (sideport_clk * 14) / 10
+	 */
+	tmp.full = rfixed_const(14);
+	rdev->pm.sideport_bandwidth.full = rfixed_mul(rdev->pm.igp_sideport_mclk, tmp);
+	tmp.full = rfixed_const(10);
+	rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp);
+}
+
+void rs690_vram_info(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	fixed20_12 a;
+
+	rs400_gart_adjust_size(rdev);
+	/* DDR for all card after R300 & IGP */
+	rdev->mc.vram_is_ddr = true;
+	/* FIXME: is this correct for RS690/RS740 ? */
+	tmp = RREG32(RADEON_MEM_CNTL);
+	if (tmp & R300_MEM_NUM_CHANNELS_MASK) {
+		rdev->mc.vram_width = 128;
+	} else {
+		rdev->mc.vram_width = 64;
+	}
+	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
+	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+	rs690_pm_info(rdev);
+	/* FIXME: we should enforce default clock in case GPU is not in
+	 * default setup
+	 */
+	a.full = rfixed_const(100);
+	rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
+	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+	a.full = rfixed_const(16);
+	/* core_bandwidth = sclk(Mhz) * 16 */
+	rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
+}
+
+void rs690_line_buffer_adjust(struct radeon_device *rdev,
+			      struct drm_display_mode *mode1,
+			      struct drm_display_mode *mode2)
+{
+	u32 tmp;
+
+	/*
+	 * Line Buffer Setup
+	 * There is a single line buffer shared by both display controllers.
+	 * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
+	 * the display controllers.  The paritioning can either be done
+	 * manually or via one of four preset allocations specified in bits 1:0:
+	 *  0 - line buffer is divided in half and shared between crtc
+	 *  1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
+	 *  2 - D1 gets the whole buffer
+	 *  3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
+	 * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual
+	 * allocation mode. In manual allocation mode, D1 always starts at 0,
+	 * D1 end/2 is specified in bits 14:4; D2 allocation follows D1.
+	 */
+	tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK;
+	tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE;
+	/* auto */
+	if (mode1 && mode2) {
+		if (mode1->hdisplay > mode2->hdisplay) {
+			if (mode1->hdisplay > 2560)
+				tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
+			else
+				tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+		} else if (mode2->hdisplay > mode1->hdisplay) {
+			if (mode2->hdisplay > 2560)
+				tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+			else
+				tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+		} else
+			tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+	} else if (mode1) {
+		tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY;
+	} else if (mode2) {
+		tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+	}
+	WREG32(DC_LB_MEMORY_SPLIT, tmp);
+}
+
+struct rs690_watermark {
+	u32        lb_request_fifo_depth;
+	fixed20_12 num_line_pair;
+	fixed20_12 estimated_width;
+	fixed20_12 worst_case_latency;
+	fixed20_12 consumption_rate;
+	fixed20_12 active_time;
+	fixed20_12 dbpp;
+	fixed20_12 priority_mark_max;
+	fixed20_12 priority_mark;
+	fixed20_12 sclk;
+};
+
+void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
+				  struct radeon_crtc *crtc,
+				  struct rs690_watermark *wm)
+{
+	struct drm_display_mode *mode = &crtc->base.mode;
+	fixed20_12 a, b, c;
+	fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
+	fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
+	/* FIXME: detect IGP with sideport memory, i don't think there is any
+	 * such product available
+	 */
+	bool sideport = false;
+
+	if (!crtc->base.enabled) {
+		/* FIXME: wouldn't it better to set priority mark to maximum */
+		wm->lb_request_fifo_depth = 4;
+		return;
+	}
+
+	if (crtc->vsc.full > rfixed_const(2))
+		wm->num_line_pair.full = rfixed_const(2);
+	else
+		wm->num_line_pair.full = rfixed_const(1);
+
+	b.full = rfixed_const(mode->crtc_hdisplay);
+	c.full = rfixed_const(256);
+	a.full = rfixed_mul(wm->num_line_pair, b);
+	request_fifo_depth.full = rfixed_div(a, c);
+	if (a.full < rfixed_const(4)) {
+		wm->lb_request_fifo_depth = 4;
+	} else {
+		wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
+	}
+
+	/* Determine consumption rate
+	 *  pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)
+	 *  vtaps = number of vertical taps,
+	 *  vsc = vertical scaling ratio, defined as source/destination
+	 *  hsc = horizontal scaling ration, defined as source/destination
+	 */
+	a.full = rfixed_const(mode->clock);
+	b.full = rfixed_const(1000);
+	a.full = rfixed_div(a, b);
+	pclk.full = rfixed_div(b, a);
+	if (crtc->rmx_type != RMX_OFF) {
+		b.full = rfixed_const(2);
+		if (crtc->vsc.full > b.full)
+			b.full = crtc->vsc.full;
+		b.full = rfixed_mul(b, crtc->hsc);
+		c.full = rfixed_const(2);
+		b.full = rfixed_div(b, c);
+		consumption_time.full = rfixed_div(pclk, b);
+	} else {
+		consumption_time.full = pclk.full;
+	}
+	a.full = rfixed_const(1);
+	wm->consumption_rate.full = rfixed_div(a, consumption_time);
+
+
+	/* Determine line time
+	 *  LineTime = total time for one line of displayhtotal
+	 *  LineTime = total number of horizontal pixels
+	 *  pclk = pixel clock period(ns)
+	 */
+	a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+	line_time.full = rfixed_mul(a, pclk);
+
+	/* Determine active time
+	 *  ActiveTime = time of active region of display within one line,
+	 *  hactive = total number of horizontal active pixels
+	 *  htotal = total number of horizontal pixels
+	 */
+	a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+	b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+	wm->active_time.full = rfixed_mul(line_time, b);
+	wm->active_time.full = rfixed_div(wm->active_time, a);
+
+	/* Maximun bandwidth is the minimun bandwidth of all component */
+	rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
+	if (sideport) {
+		if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
+			rdev->pm.sideport_bandwidth.full)
+			rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
+		read_delay_latency.full = rfixed_const(370 * 800 * 1000);
+		read_delay_latency.full = rfixed_div(read_delay_latency,
+			rdev->pm.igp_sideport_mclk);
+	} else {
+		if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full &&
+			rdev->pm.k8_bandwidth.full)
+			rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth;
+		if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full &&
+			rdev->pm.ht_bandwidth.full)
+			rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth;
+		read_delay_latency.full = rfixed_const(5000);
+	}
+
+	/* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */
+	a.full = rfixed_const(16);
+	rdev->pm.sclk.full = rfixed_mul(rdev->pm.max_bandwidth, a);
+	a.full = rfixed_const(1000);
+	rdev->pm.sclk.full = rfixed_div(a, rdev->pm.sclk);
+	/* Determine chunk time
+	 * ChunkTime = the time it takes the DCP to send one chunk of data
+	 * to the LB which consists of pipeline delay and inter chunk gap
+	 * sclk = system clock(ns)
+	 */
+	a.full = rfixed_const(256 * 13);
+	chunk_time.full = rfixed_mul(rdev->pm.sclk, a);
+	a.full = rfixed_const(10);
+	chunk_time.full = rfixed_div(chunk_time, a);
+
+	/* Determine the worst case latency
+	 * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
+	 * WorstCaseLatency = worst case time from urgent to when the MC starts
+	 *                    to return data
+	 * READ_DELAY_IDLE_MAX = constant of 1us
+	 * ChunkTime = time it takes the DCP to send one chunk of data to the LB
+	 *             which consists of pipeline delay and inter chunk gap
+	 */
+	if (rfixed_trunc(wm->num_line_pair) > 1) {
+		a.full = rfixed_const(3);
+		wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
+		wm->worst_case_latency.full += read_delay_latency.full;
+	} else {
+		a.full = rfixed_const(2);
+		wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
+		wm->worst_case_latency.full += read_delay_latency.full;
+	}
+
+	/* Determine the tolerable latency
+	 * TolerableLatency = Any given request has only 1 line time
+	 *                    for the data to be returned
+	 * LBRequestFifoDepth = Number of chunk requests the LB can
+	 *                      put into the request FIFO for a display
+	 *  LineTime = total time for one line of display
+	 *  ChunkTime = the time it takes the DCP to send one chunk
+	 *              of data to the LB which consists of
+	 *  pipeline delay and inter chunk gap
+	 */
+	if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
+		tolerable_latency.full = line_time.full;
+	} else {
+		tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
+		tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
+		tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
+		tolerable_latency.full = line_time.full - tolerable_latency.full;
+	}
+	/* We assume worst case 32bits (4 bytes) */
+	wm->dbpp.full = rfixed_const(4 * 8);
+
+	/* Determine the maximum priority mark
+	 *  width = viewport width in pixels
+	 */
+	a.full = rfixed_const(16);
+	wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+	wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
+
+	/* Determine estimated width */
+	estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
+	estimated_width.full = rfixed_div(estimated_width, consumption_time);
+	if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
+		wm->priority_mark.full = rfixed_const(10);
+	} else {
+		a.full = rfixed_const(16);
+		wm->priority_mark.full = rfixed_div(estimated_width, a);
+		wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
+	}
+}
+
+void rs690_bandwidth_update(struct radeon_device *rdev)
+{
+	struct drm_display_mode *mode0 = NULL;
+	struct drm_display_mode *mode1 = NULL;
+	struct rs690_watermark wm0;
+	struct rs690_watermark wm1;
+	u32 tmp;
+	fixed20_12 priority_mark02, priority_mark12, fill_rate;
+	fixed20_12 a, b;
+
+	if (rdev->mode_info.crtcs[0]->base.enabled)
+		mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+	if (rdev->mode_info.crtcs[1]->base.enabled)
+		mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+	/*
+	 * Set display0/1 priority up in the memory controller for
+	 * modes if the user specifies HIGH for displaypriority
+	 * option.
+	 */
+	if (rdev->disp_priority == 2) {
+		tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER);
+		tmp &= ~MC_DISP1R_INIT_LAT_MASK;
+		tmp &= ~MC_DISP0R_INIT_LAT_MASK;
+		if (mode1)
+			tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
+		if (mode0)
+			tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
+		WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp);
+	}
+	rs690_line_buffer_adjust(rdev, mode0, mode1);
+
+	if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))
+		WREG32(DCP_CONTROL, 0);
+	if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+		WREG32(DCP_CONTROL, 2);
+
+	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
+	rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
+
+	tmp = (wm0.lb_request_fifo_depth - 1);
+	tmp |= (wm1.lb_request_fifo_depth - 1) << 16;
+	WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
+
+	if (mode0 && mode1) {
+		if (rfixed_trunc(wm0.dbpp) > 64)
+			a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
+		else
+			a.full = wm0.num_line_pair.full;
+		if (rfixed_trunc(wm1.dbpp) > 64)
+			b.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
+		else
+			b.full = wm1.num_line_pair.full;
+		a.full += b.full;
+		fill_rate.full = rfixed_div(wm0.sclk, a);
+		if (wm0.consumption_rate.full > fill_rate.full) {
+			b.full = wm0.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm0.active_time);
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			a.full = a.full + b.full;
+			b.full = rfixed_const(16 * 1000);
+			priority_mark02.full = rfixed_div(a, b);
+		} else {
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			b.full = rfixed_const(16 * 1000);
+			priority_mark02.full = rfixed_div(a, b);
+		}
+		if (wm1.consumption_rate.full > fill_rate.full) {
+			b.full = wm1.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm1.active_time);
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			a.full = a.full + b.full;
+			b.full = rfixed_const(16 * 1000);
+			priority_mark12.full = rfixed_div(a, b);
+		} else {
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			b.full = rfixed_const(16 * 1000);
+			priority_mark12.full = rfixed_div(a, b);
+		}
+		if (wm0.priority_mark.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark.full;
+		if (rfixed_trunc(priority_mark02) < 0)
+			priority_mark02.full = 0;
+		if (wm0.priority_mark_max.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark_max.full;
+		if (wm1.priority_mark.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark.full;
+		if (rfixed_trunc(priority_mark12) < 0)
+			priority_mark12.full = 0;
+		if (wm1.priority_mark_max.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark_max.full;
+		WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+		WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+	} else if (mode0) {
+		if (rfixed_trunc(wm0.dbpp) > 64)
+			a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
+		else
+			a.full = wm0.num_line_pair.full;
+		fill_rate.full = rfixed_div(wm0.sclk, a);
+		if (wm0.consumption_rate.full > fill_rate.full) {
+			b.full = wm0.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm0.active_time);
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			a.full = a.full + b.full;
+			b.full = rfixed_const(16 * 1000);
+			priority_mark02.full = rfixed_div(a, b);
+		} else {
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			b.full = rfixed_const(16 * 1000);
+			priority_mark02.full = rfixed_div(a, b);
+		}
+		if (wm0.priority_mark.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark.full;
+		if (rfixed_trunc(priority_mark02) < 0)
+			priority_mark02.full = 0;
+		if (wm0.priority_mark_max.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark_max.full;
+		WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+		WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+	} else {
+		if (rfixed_trunc(wm1.dbpp) > 64)
+			a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
+		else
+			a.full = wm1.num_line_pair.full;
+		fill_rate.full = rfixed_div(wm1.sclk, a);
+		if (wm1.consumption_rate.full > fill_rate.full) {
+			b.full = wm1.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm1.active_time);
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			a.full = a.full + b.full;
+			b.full = rfixed_const(16 * 1000);
+			priority_mark12.full = rfixed_div(a, b);
+		} else {
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			b.full = rfixed_const(16 * 1000);
+			priority_mark12.full = rfixed_div(a, b);
+		}
+		if (wm1.priority_mark.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark.full;
+		if (rfixed_trunc(priority_mark12) < 0)
+			priority_mark12.full = 0;
+		if (wm1.priority_mark_max.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark_max.full;
+		WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+		WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+		WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+		WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+	}
+}
+
+/*
+ * Indirect registers accessor
+ */
+uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t r;
+
+	WREG32(RS690_MC_INDEX, (reg & RS690_MC_INDEX_MASK));
+	r = RREG32(RS690_MC_DATA);
+	WREG32(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
+	return r;
+}
+
+void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG32(RS690_MC_INDEX,
+	       RS690_MC_INDEX_WR_EN | ((reg) & RS690_MC_INDEX_MASK));
+	WREG32(RS690_MC_DATA, v);
+	WREG32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs690r.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs690r.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs690r.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs690r.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef RS690R_H
+#define RS690R_H
+
+/* RS690/RS740 registers */
+#define MC_INDEX			0x0078
+#	define MC_INDEX_MASK			0x1FF
+#	define MC_INDEX_WR_EN			(1 << 9)
+#	define MC_INDEX_WR_ACK			0x7F
+#define MC_DATA				0x007C
+#define HDP_FB_LOCATION			0x0134
+#define DC_LB_MEMORY_SPLIT		0x6520
+#define		DC_LB_MEMORY_SPLIT_MASK			0x00000003
+#define		DC_LB_MEMORY_SPLIT_SHIFT		0
+#define		DC_LB_MEMORY_SPLIT_D1HALF_D2HALF	0
+#define		DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q		1
+#define		DC_LB_MEMORY_SPLIT_D1_ONLY		2
+#define		DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q		3
+#define		DC_LB_MEMORY_SPLIT_SHIFT_MODE		(1 << 2)
+#define		DC_LB_DISP1_END_ADR_SHIFT		4
+#define		DC_LB_DISP1_END_ADR_MASK		0x00007FF0
+#define D1MODE_PRIORITY_A_CNT		0x6548
+#define		MODE_PRIORITY_MARK_MASK			0x00007FFF
+#define		MODE_PRIORITY_OFF			(1 << 16)
+#define		MODE_PRIORITY_ALWAYS_ON			(1 << 20)
+#define		MODE_PRIORITY_FORCE_MASK		(1 << 24)
+#define D1MODE_PRIORITY_B_CNT		0x654C
+#define LB_MAX_REQ_OUTSTANDING		0x6D58
+#define		LB_D1_MAX_REQ_OUTSTANDING_MASK		0x0000000F
+#define		LB_D1_MAX_REQ_OUTSTANDING_SHIFT		0
+#define		LB_D2_MAX_REQ_OUTSTANDING_MASK		0x000F0000
+#define		LB_D2_MAX_REQ_OUTSTANDING_SHIFT		16
+#define DCP_CONTROL			0x6C9C
+#define D2MODE_PRIORITY_A_CNT		0x6D48
+#define D2MODE_PRIORITY_B_CNT		0x6D4C
+
+/* MC indirect registers */
+#define MC_STATUS_IDLE				(1 << 0)
+#define MC_MISC_CNTL			0x18
+#define		DISABLE_GTW			(1 << 1)
+#define		GART_INDEX_REG_EN		(1 << 12)
+#define		BLOCK_GFX_D3_EN			(1 << 14)
+#define GART_FEATURE_ID			0x2B
+#define		HANG_EN				(1 << 11)
+#define		TLB_ENABLE			(1 << 18)
+#define		P2P_ENABLE			(1 << 19)
+#define		GTW_LAC_EN			(1 << 25)
+#define		LEVEL2_GART			(0 << 30)
+#define		LEVEL1_GART			(1 << 30)
+#define		PDC_EN				(1 << 31)
+#define GART_BASE			0x2C
+#define GART_CACHE_CNTRL		0x2E
+#	define GART_CACHE_INVALIDATE		(1 << 0)
+#define MC_STATUS			0x90
+#define MCCFG_FB_LOCATION		0x100
+#define		MC_FB_START_MASK		0x0000FFFF
+#define		MC_FB_START_SHIFT		0
+#define		MC_FB_TOP_MASK			0xFFFF0000
+#define		MC_FB_TOP_SHIFT			16
+#define MCCFG_AGP_LOCATION		0x101
+#define		MC_AGP_START_MASK		0x0000FFFF
+#define		MC_AGP_START_SHIFT		0
+#define		MC_AGP_TOP_MASK			0xFFFF0000
+#define		MC_AGP_TOP_SHIFT		16
+#define MCCFG_AGP_BASE			0x102
+#define MCCFG_AGP_BASE_2		0x103
+#define MC_INIT_MISC_LAT_TIMER		0x104
+#define		MC_DISP0R_INIT_LAT_SHIFT	8
+#define		MC_DISP0R_INIT_LAT_MASK		0x00000F00
+#define		MC_DISP1R_INIT_LAT_SHIFT	12
+#define		MC_DISP1R_INIT_LAT_MASK		0x0000F000
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs780.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs780.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rs780.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rs780.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+/* rs780  depends on : */
+void rs600_mc_disable_clients(struct radeon_device *rdev);
+
+/* This files gather functions specifics to:
+ * rs780
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+int rs780_mc_wait_for_idle(struct radeon_device *rdev);
+void rs780_gpu_init(struct radeon_device *rdev);
+
+
+/*
+ * MC
+ */
+int rs780_mc_init(struct radeon_device *rdev)
+{
+	rs780_gpu_init(rdev);
+	/* FIXME: implement */
+
+	rs600_mc_disable_clients(rdev);
+	if (rs780_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	return 0;
+}
+
+void rs780_mc_fini(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+
+/*
+ * Global GPU functions
+ */
+void rs780_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+int rs780_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+	return 0;
+}
+
+void rs780_gpu_init(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+
+/*
+ * VRAM info
+ */
+void rs780_vram_get_type(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+void rs780_vram_info(struct radeon_device *rdev)
+{
+	rs780_vram_get_type(rdev);
+
+	/* FIXME: implement */
+	/* Could aper size report 0 ? */
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rv515.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rv515.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rv515.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rv515.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1082 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include <linux/seq_file.h>
+#include "drmP.h"
+#include "rv515r.h"
+#include "radeon.h"
+#include "radeon_share.h"
+
+/* rv515 depends on : */
+void r100_hdp_reset(struct radeon_device *rdev);
+int r100_cp_reset(struct radeon_device *rdev);
+int r100_rb2d_reset(struct radeon_device *rdev);
+int r100_gui_wait_for_idle(struct radeon_device *rdev);
+int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
+int rv370_pcie_gart_enable(struct radeon_device *rdev);
+void rv370_pcie_gart_disable(struct radeon_device *rdev);
+void r420_pipes_init(struct radeon_device *rdev);
+void rs600_mc_disable_clients(struct radeon_device *rdev);
+void rs600_disable_vga(struct radeon_device *rdev);
+
+/* This files gather functions specifics to:
+ * rv515
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
+int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
+void rv515_gpu_init(struct radeon_device *rdev);
+int rv515_mc_wait_for_idle(struct radeon_device *rdev);
+
+
+/*
+ * MC
+ */
+int rv515_mc_init(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	int r;
+
+	if (r100_debugfs_rbbm_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for RBBM !\n");
+	}
+	if (rv515_debugfs_pipes_info_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for pipes !\n");
+	}
+	if (rv515_debugfs_ga_info_init(rdev)) {
+		DRM_ERROR("Failed to register debugfs file for pipes !\n");
+	}
+
+	rv515_gpu_init(rdev);
+	rv370_pcie_gart_disable(rdev);
+
+	/* Setup GPU memory space */
+	rdev->mc.vram_location = 0xFFFFFFFFUL;
+	rdev->mc.gtt_location = 0xFFFFFFFFUL;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			printk(KERN_WARNING "[drm] Disabling AGP\n");
+			rdev->flags &= ~RADEON_IS_AGP;
+			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+		} else {
+			rdev->mc.gtt_location = rdev->mc.agp_base;
+		}
+	}
+	r = radeon_mc_setup(rdev);
+	if (r) {
+		return r;
+	}
+
+	/* Program GPU memory space */
+	rs600_mc_disable_clients(rdev);
+	if (rv515_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+	/* Write VRAM size in case we are limiting it */
+	WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+	tmp = REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
+	WREG32(0x134, tmp);
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(MC_FB_TOP, tmp >> 16);
+	tmp |= REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
+	WREG32_MC(MC_FB_LOCATION, tmp);
+	WREG32(HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
+	WREG32(0x310, rdev->mc.vram_location);
+	if (rdev->flags & RADEON_IS_AGP) {
+		tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+		tmp = REG_SET(MC_AGP_TOP, tmp >> 16);
+		tmp |= REG_SET(MC_AGP_START, rdev->mc.gtt_location >> 16);
+		WREG32_MC(MC_AGP_LOCATION, tmp);
+		WREG32_MC(MC_AGP_BASE, rdev->mc.agp_base);
+		WREG32_MC(MC_AGP_BASE_2, 0);
+	} else {
+		WREG32_MC(MC_AGP_LOCATION, 0x0FFFFFFF);
+		WREG32_MC(MC_AGP_BASE, 0);
+		WREG32_MC(MC_AGP_BASE_2, 0);
+	}
+	return 0;
+}
+
+void rv515_mc_fini(struct radeon_device *rdev)
+{
+	rv370_pcie_gart_disable(rdev);
+	radeon_gart_table_vram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+/*
+ * Global GPU functions
+ */
+void rv515_ring_start(struct radeon_device *rdev)
+{
+	int r;
+
+	r = radeon_ring_lock(rdev, 64);
+	if (r) {
+		return;
+	}
+	radeon_ring_write(rdev, PACKET0(ISYNC_CNTL, 0));
+	radeon_ring_write(rdev,
+			  ISYNC_ANY2D_IDLE3D |
+			  ISYNC_ANY3D_IDLE2D |
+			  ISYNC_WAIT_IDLEGUI |
+			  ISYNC_CPSCRATCH_IDLEGUI);
+	radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
+	radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
+	radeon_ring_write(rdev, PACKET0(0x170C, 0));
+	radeon_ring_write(rdev, 1 << 31);
+	radeon_ring_write(rdev, PACKET0(GB_SELECT, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(0x42C8, 0));
+	radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1);
+	radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
+	radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
+	radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
+	radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
+	radeon_ring_write(rdev, PACKET0(GB_AA_CONFIG, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
+	radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
+	radeon_ring_write(rdev, PACKET0(GB_MSPOS0, 0));
+	radeon_ring_write(rdev,
+			  ((6 << MS_X0_SHIFT) |
+			   (6 << MS_Y0_SHIFT) |
+			   (6 << MS_X1_SHIFT) |
+			   (6 << MS_Y1_SHIFT) |
+			   (6 << MS_X2_SHIFT) |
+			   (6 << MS_Y2_SHIFT) |
+			   (6 << MSBD0_Y_SHIFT) |
+			   (6 << MSBD0_X_SHIFT)));
+	radeon_ring_write(rdev, PACKET0(GB_MSPOS1, 0));
+	radeon_ring_write(rdev,
+			  ((6 << MS_X3_SHIFT) |
+			   (6 << MS_Y3_SHIFT) |
+			   (6 << MS_X4_SHIFT) |
+			   (6 << MS_Y4_SHIFT) |
+			   (6 << MS_X5_SHIFT) |
+			   (6 << MS_Y5_SHIFT) |
+			   (6 << MSBD1_SHIFT)));
+	radeon_ring_write(rdev, PACKET0(GA_ENHANCE, 0));
+	radeon_ring_write(rdev, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL);
+	radeon_ring_write(rdev, PACKET0(GA_POLY_MODE, 0));
+	radeon_ring_write(rdev, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE);
+	radeon_ring_write(rdev, PACKET0(GA_ROUND_MODE, 0));
+	radeon_ring_write(rdev, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST);
+	radeon_ring_write(rdev, PACKET0(0x20C8, 0));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_unlock_commit(rdev);
+}
+
+void rv515_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+int rv515_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32_MC(MC_STATUS);
+		if (tmp & MC_STATUS_IDLE) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
+void rv515_gpu_init(struct radeon_device *rdev)
+{
+	unsigned pipe_select_current, gb_pipe_select, tmp;
+
+	r100_hdp_reset(rdev);
+	r100_rb2d_reset(rdev);
+
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "reseting GPU. Bad things might happen.\n");
+	}
+
+	rs600_disable_vga(rdev);
+
+	r420_pipes_init(rdev);
+	gb_pipe_select = RREG32(0x402C);
+	tmp = RREG32(0x170C);
+	pipe_select_current = (tmp >> 2) & 3;
+	tmp = (1 << pipe_select_current) |
+	      (((gb_pipe_select >> 8) & 0xF) << 4);
+	WREG32_PLL(0x000D, tmp);
+	if (r100_gui_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait GUI idle while "
+		       "reseting GPU. Bad things might happen.\n");
+	}
+	if (rv515_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+}
+
+int rv515_ga_reset(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	bool reinit_cp;
+	int i;
+
+	reinit_cp = rdev->cp.ready;
+	rdev->cp.ready = false;
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		WREG32(CP_CSQ_MODE, 0);
+		WREG32(CP_CSQ_CNTL, 0);
+		WREG32(RBBM_SOFT_RESET, 0x32005);
+		(void)RREG32(RBBM_SOFT_RESET);
+		udelay(200);
+		WREG32(RBBM_SOFT_RESET, 0);
+		/* Wait to prevent race in RBBM_STATUS */
+		mdelay(1);
+		tmp = RREG32(RBBM_STATUS);
+		if (tmp & ((1 << 20) | (1 << 26))) {
+			DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)\n", tmp);
+			/* GA still busy soft reset it */
+			WREG32(0x429C, 0x200);
+			WREG32(VAP_PVS_STATE_FLUSH_REG, 0);
+			WREG32(0x43E0, 0);
+			WREG32(0x43E4, 0);
+			WREG32(0x24AC, 0);
+		}
+		/* Wait to prevent race in RBBM_STATUS */
+		mdelay(1);
+		tmp = RREG32(RBBM_STATUS);
+		if (!(tmp & ((1 << 20) | (1 << 26)))) {
+			break;
+		}
+	}
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		tmp = RREG32(RBBM_STATUS);
+		if (!(tmp & ((1 << 20) | (1 << 26)))) {
+			DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n",
+				 tmp);
+			DRM_INFO("GA_IDLE=0x%08X\n", RREG32(0x425C));
+			DRM_INFO("RB3D_RESET_STATUS=0x%08X\n", RREG32(0x46f0));
+			DRM_INFO("ISYNC_CNTL=0x%08X\n", RREG32(0x1724));
+			if (reinit_cp) {
+				return r100_cp_init(rdev, rdev->cp.ring_size);
+			}
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	tmp = RREG32(RBBM_STATUS);
+	DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp);
+	return -1;
+}
+
+int rv515_gpu_reset(struct radeon_device *rdev)
+{
+	uint32_t status;
+
+	/* reset order likely matter */
+	status = RREG32(RBBM_STATUS);
+	/* reset HDP */
+	r100_hdp_reset(rdev);
+	/* reset rb2d */
+	if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
+		r100_rb2d_reset(rdev);
+	}
+	/* reset GA */
+	if (status & ((1 << 20) | (1 << 26))) {
+		rv515_ga_reset(rdev);
+	}
+	/* reset CP */
+	status = RREG32(RBBM_STATUS);
+	if (status & (1 << 16)) {
+		r100_cp_reset(rdev);
+	}
+	/* Check if GPU is idle */
+	status = RREG32(RBBM_STATUS);
+	if (status & (1 << 31)) {
+		DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
+		return -1;
+	}
+	DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status);
+	return 0;
+}
+
+
+/*
+ * VRAM info
+ */
+static void rv515_vram_get_type(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	rdev->mc.vram_width = 128;
+	rdev->mc.vram_is_ddr = true;
+	tmp = RREG32_MC(RV515_MC_CNTL) & MEM_NUM_CHANNELS_MASK;
+	switch (tmp) {
+	case 0:
+		rdev->mc.vram_width = 64;
+		break;
+	case 1:
+		rdev->mc.vram_width = 128;
+		break;
+	default:
+		rdev->mc.vram_width = 128;
+		break;
+	}
+}
+
+void rv515_vram_info(struct radeon_device *rdev)
+{
+	fixed20_12 a;
+
+	rv515_vram_get_type(rdev);
+
+	r100_vram_init_sizes(rdev);
+	/* FIXME: we should enforce default clock in case GPU is not in
+	 * default setup
+	 */
+	a.full = rfixed_const(100);
+	rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
+	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+}
+
+
+/*
+ * Indirect registers accessor
+ */
+uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+	uint32_t r;
+
+	WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff));
+	r = RREG32(MC_IND_DATA);
+	WREG32(MC_IND_INDEX, 0);
+	return r;
+}
+
+void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+	WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff));
+	WREG32(MC_IND_DATA, (v));
+	WREG32(MC_IND_INDEX, 0);
+}
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+static int rv515_debugfs_pipes_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = RREG32(GB_PIPE_SELECT);
+	seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp);
+	tmp = RREG32(SU_REG_DEST);
+	seq_printf(m, "SU_REG_DEST 0x%08x\n", tmp);
+	tmp = RREG32(GB_TILE_CONFIG);
+	seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp);
+	tmp = RREG32(DST_PIPE_CONFIG);
+	seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp);
+	return 0;
+}
+
+static int rv515_debugfs_ga_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t tmp;
+
+	tmp = RREG32(0x2140);
+	seq_printf(m, "VAP_CNTL_STATUS 0x%08x\n", tmp);
+	radeon_gpu_reset(rdev);
+	tmp = RREG32(0x425C);
+	seq_printf(m, "GA_IDLE 0x%08x\n", tmp);
+	return 0;
+}
+
+static struct drm_info_list rv515_pipes_info_list[] = {
+	{"rv515_pipes_info", rv515_debugfs_pipes_info, 0, NULL},
+};
+
+static struct drm_info_list rv515_ga_info_list[] = {
+	{"rv515_ga_info", rv515_debugfs_ga_info, 0, NULL},
+};
+#endif
+
+int rv515_debugfs_pipes_info_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, rv515_pipes_info_list, 1);
+#else
+	return 0;
+#endif
+}
+
+int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, rv515_ga_info_list, 1);
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Asic initialization
+ */
+static const unsigned r500_reg_safe_bm[219] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
+	0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
+	0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0x1FFFFC78, 0xFFFFE000, 0xFFFFFFFE, 0xFFFFFFFF,
+	0x38CF8F50, 0xFFF88082, 0xFF0000FC, 0xFAE009FF,
+	0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+	0xFFFF8CFC, 0xFFFFC1FF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x0003FC01, 0x3FFFFCF8, 0xFF800B19, 0xFFDFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+};
+
+int rv515_init(struct radeon_device *rdev)
+{
+	rdev->config.r300.reg_safe_bm = r500_reg_safe_bm;
+	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm);
+	return 0;
+}
+
+void atom_rv515_force_tv_scaler(struct radeon_device *rdev)
+{
+
+	WREG32(0x659C, 0x0);
+	WREG32(0x6594, 0x705);
+	WREG32(0x65A4, 0x10001);
+	WREG32(0x65D8, 0x0);
+	WREG32(0x65B0, 0x0);
+	WREG32(0x65C0, 0x0);
+	WREG32(0x65D4, 0x0);
+	WREG32(0x6578, 0x0);
+	WREG32(0x657C, 0x841880A8);
+	WREG32(0x6578, 0x1);
+	WREG32(0x657C, 0x84208680);
+	WREG32(0x6578, 0x2);
+	WREG32(0x657C, 0xBFF880B0);
+	WREG32(0x6578, 0x100);
+	WREG32(0x657C, 0x83D88088);
+	WREG32(0x6578, 0x101);
+	WREG32(0x657C, 0x84608680);
+	WREG32(0x6578, 0x102);
+	WREG32(0x657C, 0xBFF080D0);
+	WREG32(0x6578, 0x200);
+	WREG32(0x657C, 0x83988068);
+	WREG32(0x6578, 0x201);
+	WREG32(0x657C, 0x84A08680);
+	WREG32(0x6578, 0x202);
+	WREG32(0x657C, 0xBFF080F8);
+	WREG32(0x6578, 0x300);
+	WREG32(0x657C, 0x83588058);
+	WREG32(0x6578, 0x301);
+	WREG32(0x657C, 0x84E08660);
+	WREG32(0x6578, 0x302);
+	WREG32(0x657C, 0xBFF88120);
+	WREG32(0x6578, 0x400);
+	WREG32(0x657C, 0x83188040);
+	WREG32(0x6578, 0x401);
+	WREG32(0x657C, 0x85008660);
+	WREG32(0x6578, 0x402);
+	WREG32(0x657C, 0xBFF88150);
+	WREG32(0x6578, 0x500);
+	WREG32(0x657C, 0x82D88030);
+	WREG32(0x6578, 0x501);
+	WREG32(0x657C, 0x85408640);
+	WREG32(0x6578, 0x502);
+	WREG32(0x657C, 0xBFF88180);
+	WREG32(0x6578, 0x600);
+	WREG32(0x657C, 0x82A08018);
+	WREG32(0x6578, 0x601);
+	WREG32(0x657C, 0x85808620);
+	WREG32(0x6578, 0x602);
+	WREG32(0x657C, 0xBFF081B8);
+	WREG32(0x6578, 0x700);
+	WREG32(0x657C, 0x82608010);
+	WREG32(0x6578, 0x701);
+	WREG32(0x657C, 0x85A08600);
+	WREG32(0x6578, 0x702);
+	WREG32(0x657C, 0x800081F0);
+	WREG32(0x6578, 0x800);
+	WREG32(0x657C, 0x8228BFF8);
+	WREG32(0x6578, 0x801);
+	WREG32(0x657C, 0x85E085E0);
+	WREG32(0x6578, 0x802);
+	WREG32(0x657C, 0xBFF88228);
+	WREG32(0x6578, 0x10000);
+	WREG32(0x657C, 0x82A8BF00);
+	WREG32(0x6578, 0x10001);
+	WREG32(0x657C, 0x82A08CC0);
+	WREG32(0x6578, 0x10002);
+	WREG32(0x657C, 0x8008BEF8);
+	WREG32(0x6578, 0x10100);
+	WREG32(0x657C, 0x81F0BF28);
+	WREG32(0x6578, 0x10101);
+	WREG32(0x657C, 0x83608CA0);
+	WREG32(0x6578, 0x10102);
+	WREG32(0x657C, 0x8018BED0);
+	WREG32(0x6578, 0x10200);
+	WREG32(0x657C, 0x8148BF38);
+	WREG32(0x6578, 0x10201);
+	WREG32(0x657C, 0x84408C80);
+	WREG32(0x6578, 0x10202);
+	WREG32(0x657C, 0x8008BEB8);
+	WREG32(0x6578, 0x10300);
+	WREG32(0x657C, 0x80B0BF78);
+	WREG32(0x6578, 0x10301);
+	WREG32(0x657C, 0x85008C20);
+	WREG32(0x6578, 0x10302);
+	WREG32(0x657C, 0x8020BEA0);
+	WREG32(0x6578, 0x10400);
+	WREG32(0x657C, 0x8028BF90);
+	WREG32(0x6578, 0x10401);
+	WREG32(0x657C, 0x85E08BC0);
+	WREG32(0x6578, 0x10402);
+	WREG32(0x657C, 0x8018BE90);
+	WREG32(0x6578, 0x10500);
+	WREG32(0x657C, 0xBFB8BFB0);
+	WREG32(0x6578, 0x10501);
+	WREG32(0x657C, 0x86C08B40);
+	WREG32(0x6578, 0x10502);
+	WREG32(0x657C, 0x8010BE90);
+	WREG32(0x6578, 0x10600);
+	WREG32(0x657C, 0xBF58BFC8);
+	WREG32(0x6578, 0x10601);
+	WREG32(0x657C, 0x87A08AA0);
+	WREG32(0x6578, 0x10602);
+	WREG32(0x657C, 0x8010BE98);
+	WREG32(0x6578, 0x10700);
+	WREG32(0x657C, 0xBF10BFF0);
+	WREG32(0x6578, 0x10701);
+	WREG32(0x657C, 0x886089E0);
+	WREG32(0x6578, 0x10702);
+	WREG32(0x657C, 0x8018BEB0);
+	WREG32(0x6578, 0x10800);
+	WREG32(0x657C, 0xBED8BFE8);
+	WREG32(0x6578, 0x10801);
+	WREG32(0x657C, 0x89408940);
+	WREG32(0x6578, 0x10802);
+	WREG32(0x657C, 0xBFE8BED8);
+	WREG32(0x6578, 0x20000);
+	WREG32(0x657C, 0x80008000);
+	WREG32(0x6578, 0x20001);
+	WREG32(0x657C, 0x90008000);
+	WREG32(0x6578, 0x20002);
+	WREG32(0x657C, 0x80008000);
+	WREG32(0x6578, 0x20003);
+	WREG32(0x657C, 0x80008000);
+	WREG32(0x6578, 0x20100);
+	WREG32(0x657C, 0x80108000);
+	WREG32(0x6578, 0x20101);
+	WREG32(0x657C, 0x8FE0BF70);
+	WREG32(0x6578, 0x20102);
+	WREG32(0x657C, 0xBFE880C0);
+	WREG32(0x6578, 0x20103);
+	WREG32(0x657C, 0x80008000);
+	WREG32(0x6578, 0x20200);
+	WREG32(0x657C, 0x8018BFF8);
+	WREG32(0x6578, 0x20201);
+	WREG32(0x657C, 0x8F80BF08);
+	WREG32(0x6578, 0x20202);
+	WREG32(0x657C, 0xBFD081A0);
+	WREG32(0x6578, 0x20203);
+	WREG32(0x657C, 0xBFF88000);
+	WREG32(0x6578, 0x20300);
+	WREG32(0x657C, 0x80188000);
+	WREG32(0x6578, 0x20301);
+	WREG32(0x657C, 0x8EE0BEC0);
+	WREG32(0x6578, 0x20302);
+	WREG32(0x657C, 0xBFB082A0);
+	WREG32(0x6578, 0x20303);
+	WREG32(0x657C, 0x80008000);
+	WREG32(0x6578, 0x20400);
+	WREG32(0x657C, 0x80188000);
+	WREG32(0x6578, 0x20401);
+	WREG32(0x657C, 0x8E00BEA0);
+	WREG32(0x6578, 0x20402);
+	WREG32(0x657C, 0xBF8883C0);
+	WREG32(0x6578, 0x20403);
+	WREG32(0x657C, 0x80008000);
+	WREG32(0x6578, 0x20500);
+	WREG32(0x657C, 0x80188000);
+	WREG32(0x6578, 0x20501);
+	WREG32(0x657C, 0x8D00BE90);
+	WREG32(0x6578, 0x20502);
+	WREG32(0x657C, 0xBF588500);
+	WREG32(0x6578, 0x20503);
+	WREG32(0x657C, 0x80008008);
+	WREG32(0x6578, 0x20600);
+	WREG32(0x657C, 0x80188000);
+	WREG32(0x6578, 0x20601);
+	WREG32(0x657C, 0x8BC0BE98);
+	WREG32(0x6578, 0x20602);
+	WREG32(0x657C, 0xBF308660);
+	WREG32(0x6578, 0x20603);
+	WREG32(0x657C, 0x80008008);
+	WREG32(0x6578, 0x20700);
+	WREG32(0x657C, 0x80108000);
+	WREG32(0x6578, 0x20701);
+	WREG32(0x657C, 0x8A80BEB0);
+	WREG32(0x6578, 0x20702);
+	WREG32(0x657C, 0xBF0087C0);
+	WREG32(0x6578, 0x20703);
+	WREG32(0x657C, 0x80008008);
+	WREG32(0x6578, 0x20800);
+	WREG32(0x657C, 0x80108000);
+	WREG32(0x6578, 0x20801);
+	WREG32(0x657C, 0x8920BED0);
+	WREG32(0x6578, 0x20802);
+	WREG32(0x657C, 0xBED08920);
+	WREG32(0x6578, 0x20803);
+	WREG32(0x657C, 0x80008010);
+	WREG32(0x6578, 0x30000);
+	WREG32(0x657C, 0x90008000);
+	WREG32(0x6578, 0x30001);
+	WREG32(0x657C, 0x80008000);
+	WREG32(0x6578, 0x30100);
+	WREG32(0x657C, 0x8FE0BF90);
+	WREG32(0x6578, 0x30101);
+	WREG32(0x657C, 0xBFF880A0);
+	WREG32(0x6578, 0x30200);
+	WREG32(0x657C, 0x8F60BF40);
+	WREG32(0x6578, 0x30201);
+	WREG32(0x657C, 0xBFE88180);
+	WREG32(0x6578, 0x30300);
+	WREG32(0x657C, 0x8EC0BF00);
+	WREG32(0x6578, 0x30301);
+	WREG32(0x657C, 0xBFC88280);
+	WREG32(0x6578, 0x30400);
+	WREG32(0x657C, 0x8DE0BEE0);
+	WREG32(0x6578, 0x30401);
+	WREG32(0x657C, 0xBFA083A0);
+	WREG32(0x6578, 0x30500);
+	WREG32(0x657C, 0x8CE0BED0);
+	WREG32(0x6578, 0x30501);
+	WREG32(0x657C, 0xBF7884E0);
+	WREG32(0x6578, 0x30600);
+	WREG32(0x657C, 0x8BA0BED8);
+	WREG32(0x6578, 0x30601);
+	WREG32(0x657C, 0xBF508640);
+	WREG32(0x6578, 0x30700);
+	WREG32(0x657C, 0x8A60BEE8);
+	WREG32(0x6578, 0x30701);
+	WREG32(0x657C, 0xBF2087A0);
+	WREG32(0x6578, 0x30800);
+	WREG32(0x657C, 0x8900BF00);
+	WREG32(0x6578, 0x30801);
+	WREG32(0x657C, 0xBF008900);
+}
+
+struct rv515_watermark {
+	u32        lb_request_fifo_depth;
+	fixed20_12 num_line_pair;
+	fixed20_12 estimated_width;
+	fixed20_12 worst_case_latency;
+	fixed20_12 consumption_rate;
+	fixed20_12 active_time;
+	fixed20_12 dbpp;
+	fixed20_12 priority_mark_max;
+	fixed20_12 priority_mark;
+	fixed20_12 sclk;
+};
+
+void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
+				  struct radeon_crtc *crtc,
+				  struct rv515_watermark *wm)
+{
+	struct drm_display_mode *mode = &crtc->base.mode;
+	fixed20_12 a, b, c;
+	fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
+	fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
+
+	if (!crtc->base.enabled) {
+		/* FIXME: wouldn't it better to set priority mark to maximum */
+		wm->lb_request_fifo_depth = 4;
+		return;
+	}
+
+	if (crtc->vsc.full > rfixed_const(2))
+		wm->num_line_pair.full = rfixed_const(2);
+	else
+		wm->num_line_pair.full = rfixed_const(1);
+
+	b.full = rfixed_const(mode->crtc_hdisplay);
+	c.full = rfixed_const(256);
+	a.full = rfixed_mul(wm->num_line_pair, b);
+	request_fifo_depth.full = rfixed_div(a, c);
+	if (a.full < rfixed_const(4)) {
+		wm->lb_request_fifo_depth = 4;
+	} else {
+		wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
+	}
+
+	/* Determine consumption rate
+	 *  pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)
+	 *  vtaps = number of vertical taps,
+	 *  vsc = vertical scaling ratio, defined as source/destination
+	 *  hsc = horizontal scaling ration, defined as source/destination
+	 */
+	a.full = rfixed_const(mode->clock);
+	b.full = rfixed_const(1000);
+	a.full = rfixed_div(a, b);
+	pclk.full = rfixed_div(b, a);
+	if (crtc->rmx_type != RMX_OFF) {
+		b.full = rfixed_const(2);
+		if (crtc->vsc.full > b.full)
+			b.full = crtc->vsc.full;
+		b.full = rfixed_mul(b, crtc->hsc);
+		c.full = rfixed_const(2);
+		b.full = rfixed_div(b, c);
+		consumption_time.full = rfixed_div(pclk, b);
+	} else {
+		consumption_time.full = pclk.full;
+	}
+	a.full = rfixed_const(1);
+	wm->consumption_rate.full = rfixed_div(a, consumption_time);
+
+
+	/* Determine line time
+	 *  LineTime = total time for one line of displayhtotal
+	 *  LineTime = total number of horizontal pixels
+	 *  pclk = pixel clock period(ns)
+	 */
+	a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+	line_time.full = rfixed_mul(a, pclk);
+
+	/* Determine active time
+	 *  ActiveTime = time of active region of display within one line,
+	 *  hactive = total number of horizontal active pixels
+	 *  htotal = total number of horizontal pixels
+	 */
+	a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+	b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+	wm->active_time.full = rfixed_mul(line_time, b);
+	wm->active_time.full = rfixed_div(wm->active_time, a);
+
+	/* Determine chunk time
+	 * ChunkTime = the time it takes the DCP to send one chunk of data
+	 * to the LB which consists of pipeline delay and inter chunk gap
+	 * sclk = system clock(Mhz)
+	 */
+	a.full = rfixed_const(600 * 1000);
+	chunk_time.full = rfixed_div(a, rdev->pm.sclk);
+	read_delay_latency.full = rfixed_const(1000);
+
+	/* Determine the worst case latency
+	 * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
+	 * WorstCaseLatency = worst case time from urgent to when the MC starts
+	 *                    to return data
+	 * READ_DELAY_IDLE_MAX = constant of 1us
+	 * ChunkTime = time it takes the DCP to send one chunk of data to the LB
+	 *             which consists of pipeline delay and inter chunk gap
+	 */
+	if (rfixed_trunc(wm->num_line_pair) > 1) {
+		a.full = rfixed_const(3);
+		wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
+		wm->worst_case_latency.full += read_delay_latency.full;
+	} else {
+		wm->worst_case_latency.full = chunk_time.full + read_delay_latency.full;
+	}
+
+	/* Determine the tolerable latency
+	 * TolerableLatency = Any given request has only 1 line time
+	 *                    for the data to be returned
+	 * LBRequestFifoDepth = Number of chunk requests the LB can
+	 *                      put into the request FIFO for a display
+	 *  LineTime = total time for one line of display
+	 *  ChunkTime = the time it takes the DCP to send one chunk
+	 *              of data to the LB which consists of
+	 *  pipeline delay and inter chunk gap
+	 */
+	if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
+		tolerable_latency.full = line_time.full;
+	} else {
+		tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
+		tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
+		tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
+		tolerable_latency.full = line_time.full - tolerable_latency.full;
+	}
+	/* We assume worst case 32bits (4 bytes) */
+	wm->dbpp.full = rfixed_const(2 * 16);
+
+	/* Determine the maximum priority mark
+	 *  width = viewport width in pixels
+	 */
+	a.full = rfixed_const(16);
+	wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+	wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
+
+	/* Determine estimated width */
+	estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
+	estimated_width.full = rfixed_div(estimated_width, consumption_time);
+	if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
+		wm->priority_mark.full = rfixed_const(10);
+	} else {
+		a.full = rfixed_const(16);
+		wm->priority_mark.full = rfixed_div(estimated_width, a);
+		wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
+	}
+}
+
+void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
+{
+	struct drm_display_mode *mode0 = NULL;
+	struct drm_display_mode *mode1 = NULL;
+	struct rv515_watermark wm0;
+	struct rv515_watermark wm1;
+	u32 tmp;
+	fixed20_12 priority_mark02, priority_mark12, fill_rate;
+	fixed20_12 a, b;
+
+	if (rdev->mode_info.crtcs[0]->base.enabled)
+		mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+	if (rdev->mode_info.crtcs[1]->base.enabled)
+		mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+	rs690_line_buffer_adjust(rdev, mode0, mode1);
+
+	rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
+	rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
+
+	tmp = wm0.lb_request_fifo_depth;
+	tmp |= wm1.lb_request_fifo_depth << 16;
+	WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
+
+	if (mode0 && mode1) {
+		if (rfixed_trunc(wm0.dbpp) > 64)
+			a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
+		else
+			a.full = wm0.num_line_pair.full;
+		if (rfixed_trunc(wm1.dbpp) > 64)
+			b.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
+		else
+			b.full = wm1.num_line_pair.full;
+		a.full += b.full;
+		fill_rate.full = rfixed_div(wm0.sclk, a);
+		if (wm0.consumption_rate.full > fill_rate.full) {
+			b.full = wm0.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm0.active_time);
+			a.full = rfixed_const(16);
+			b.full = rfixed_div(b, a);
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			priority_mark02.full = a.full + b.full;
+		} else {
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			b.full = rfixed_const(16 * 1000);
+			priority_mark02.full = rfixed_div(a, b);
+		}
+		if (wm1.consumption_rate.full > fill_rate.full) {
+			b.full = wm1.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm1.active_time);
+			a.full = rfixed_const(16);
+			b.full = rfixed_div(b, a);
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			priority_mark12.full = a.full + b.full;
+		} else {
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			b.full = rfixed_const(16 * 1000);
+			priority_mark12.full = rfixed_div(a, b);
+		}
+		if (wm0.priority_mark.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark.full;
+		if (rfixed_trunc(priority_mark02) < 0)
+			priority_mark02.full = 0;
+		if (wm0.priority_mark_max.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark_max.full;
+		if (wm1.priority_mark.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark.full;
+		if (rfixed_trunc(priority_mark12) < 0)
+			priority_mark12.full = 0;
+		if (wm1.priority_mark_max.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark_max.full;
+		WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+		WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+	} else if (mode0) {
+		if (rfixed_trunc(wm0.dbpp) > 64)
+			a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
+		else
+			a.full = wm0.num_line_pair.full;
+		fill_rate.full = rfixed_div(wm0.sclk, a);
+		if (wm0.consumption_rate.full > fill_rate.full) {
+			b.full = wm0.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm0.active_time);
+			a.full = rfixed_const(16);
+			b.full = rfixed_div(b, a);
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			priority_mark02.full = a.full + b.full;
+		} else {
+			a.full = rfixed_mul(wm0.worst_case_latency,
+						wm0.consumption_rate);
+			b.full = rfixed_const(16);
+			priority_mark02.full = rfixed_div(a, b);
+		}
+		if (wm0.priority_mark.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark.full;
+		if (rfixed_trunc(priority_mark02) < 0)
+			priority_mark02.full = 0;
+		if (wm0.priority_mark_max.full > priority_mark02.full)
+			priority_mark02.full = wm0.priority_mark_max.full;
+		WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+		WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+		WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+	} else {
+		if (rfixed_trunc(wm1.dbpp) > 64)
+			a.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
+		else
+			a.full = wm1.num_line_pair.full;
+		fill_rate.full = rfixed_div(wm1.sclk, a);
+		if (wm1.consumption_rate.full > fill_rate.full) {
+			b.full = wm1.consumption_rate.full - fill_rate.full;
+			b.full = rfixed_mul(b, wm1.active_time);
+			a.full = rfixed_const(16);
+			b.full = rfixed_div(b, a);
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			priority_mark12.full = a.full + b.full;
+		} else {
+			a.full = rfixed_mul(wm1.worst_case_latency,
+						wm1.consumption_rate);
+			b.full = rfixed_const(16 * 1000);
+			priority_mark12.full = rfixed_div(a, b);
+		}
+		if (wm1.priority_mark.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark.full;
+		if (rfixed_trunc(priority_mark12) < 0)
+			priority_mark12.full = 0;
+		if (wm1.priority_mark_max.full > priority_mark12.full)
+			priority_mark12.full = wm1.priority_mark_max.full;
+		WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+		WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+		WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+		WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+	}
+}
+
+void rv515_bandwidth_update(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	struct drm_display_mode *mode0 = NULL;
+	struct drm_display_mode *mode1 = NULL;
+
+	if (rdev->mode_info.crtcs[0]->base.enabled)
+		mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+	if (rdev->mode_info.crtcs[1]->base.enabled)
+		mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+	/*
+	 * Set display0/1 priority up in the memory controller for
+	 * modes if the user specifies HIGH for displaypriority
+	 * option.
+	 */
+	if (rdev->disp_priority == 2) {
+		tmp = RREG32_MC(MC_MISC_LAT_TIMER);
+		tmp &= ~MC_DISP1R_INIT_LAT_MASK;
+		tmp &= ~MC_DISP0R_INIT_LAT_MASK;
+		if (mode1)
+			tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
+		if (mode0)
+			tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
+		WREG32_MC(MC_MISC_LAT_TIMER, tmp);
+	}
+	rv515_bandwidth_avivo_update(rdev);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rv515r.h linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rv515r.h
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rv515r.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rv515r.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef RV515R_H
+#define RV515R_H
+
+/* RV515 registers */
+#define PCIE_INDEX			0x0030
+#define PCIE_DATA			0x0034
+#define	MC_IND_INDEX			0x0070
+#define		MC_IND_WR_EN				(1 << 24)
+#define	MC_IND_DATA			0x0074
+#define	RBBM_SOFT_RESET			0x00F0
+#define	CONFIG_MEMSIZE			0x00F8
+#define HDP_FB_LOCATION			0x0134
+#define	CP_CSQ_CNTL			0x0740
+#define	CP_CSQ_MODE			0x0744
+#define	CP_CSQ_ADDR			0x07F0
+#define	CP_CSQ_DATA			0x07F4
+#define	CP_CSQ_STAT			0x07F8
+#define	CP_CSQ2_STAT			0x07FC
+#define	RBBM_STATUS			0x0E40
+#define	DST_PIPE_CONFIG			0x170C
+#define	WAIT_UNTIL			0x1720
+#define		WAIT_2D_IDLE				(1 << 14)
+#define		WAIT_3D_IDLE				(1 << 15)
+#define		WAIT_2D_IDLECLEAN			(1 << 16)
+#define		WAIT_3D_IDLECLEAN			(1 << 17)
+#define	ISYNC_CNTL			0x1724
+#define		ISYNC_ANY2D_IDLE3D			(1 << 0)
+#define		ISYNC_ANY3D_IDLE2D			(1 << 1)
+#define		ISYNC_TRIG2D_IDLE3D			(1 << 2)
+#define		ISYNC_TRIG3D_IDLE2D			(1 << 3)
+#define		ISYNC_WAIT_IDLEGUI			(1 << 4)
+#define		ISYNC_CPSCRATCH_IDLEGUI			(1 << 5)
+#define	VAP_INDEX_OFFSET		0x208C
+#define	VAP_PVS_STATE_FLUSH_REG		0x2284
+#define	GB_ENABLE			0x4008
+#define	GB_MSPOS0			0x4010
+#define		MS_X0_SHIFT				0
+#define		MS_Y0_SHIFT				4
+#define		MS_X1_SHIFT				8
+#define		MS_Y1_SHIFT				12
+#define		MS_X2_SHIFT				16
+#define		MS_Y2_SHIFT				20
+#define		MSBD0_Y_SHIFT				24
+#define		MSBD0_X_SHIFT				28
+#define	GB_MSPOS1			0x4014
+#define		MS_X3_SHIFT				0
+#define		MS_Y3_SHIFT				4
+#define		MS_X4_SHIFT				8
+#define		MS_Y4_SHIFT				12
+#define		MS_X5_SHIFT				16
+#define		MS_Y5_SHIFT				20
+#define		MSBD1_SHIFT				24
+#define GB_TILE_CONFIG			0x4018
+#define		ENABLE_TILING				(1 << 0)
+#define		PIPE_COUNT_MASK				0x0000000E
+#define		PIPE_COUNT_SHIFT			1
+#define		TILE_SIZE_8				(0 << 4)
+#define		TILE_SIZE_16				(1 << 4)
+#define		TILE_SIZE_32				(2 << 4)
+#define		SUBPIXEL_1_12				(0 << 16)
+#define		SUBPIXEL_1_16				(1 << 16)
+#define	GB_SELECT			0x401C
+#define	GB_AA_CONFIG			0x4020
+#define	GB_PIPE_SELECT			0x402C
+#define	GA_ENHANCE			0x4274
+#define		GA_DEADLOCK_CNTL			(1 << 0)
+#define		GA_FASTSYNC_CNTL			(1 << 1)
+#define	GA_POLY_MODE			0x4288
+#define		FRONT_PTYPE_POINT			(0 << 4)
+#define		FRONT_PTYPE_LINE			(1 << 4)
+#define		FRONT_PTYPE_TRIANGE			(2 << 4)
+#define		BACK_PTYPE_POINT			(0 << 7)
+#define		BACK_PTYPE_LINE				(1 << 7)
+#define		BACK_PTYPE_TRIANGE			(2 << 7)
+#define	GA_ROUND_MODE			0x428C
+#define		GEOMETRY_ROUND_TRUNC			(0 << 0)
+#define		GEOMETRY_ROUND_NEAREST			(1 << 0)
+#define		COLOR_ROUND_TRUNC			(0 << 2)
+#define		COLOR_ROUND_NEAREST			(1 << 2)
+#define	SU_REG_DEST			0x42C8
+#define	RB3D_DSTCACHE_CTLSTAT		0x4E4C
+#define		RB3D_DC_FLUSH				(2 << 0)
+#define		RB3D_DC_FREE				(2 << 2)
+#define		RB3D_DC_FINISH				(1 << 4)
+#define ZB_ZCACHE_CTLSTAT		0x4F18
+#define		ZC_FLUSH				(1 << 0)
+#define		ZC_FREE					(1 << 1)
+#define DC_LB_MEMORY_SPLIT		0x6520
+#define		DC_LB_MEMORY_SPLIT_MASK			0x00000003
+#define		DC_LB_MEMORY_SPLIT_SHIFT		0
+#define		DC_LB_MEMORY_SPLIT_D1HALF_D2HALF	0
+#define		DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q		1
+#define		DC_LB_MEMORY_SPLIT_D1_ONLY		2
+#define		DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q		3
+#define		DC_LB_MEMORY_SPLIT_SHIFT_MODE		(1 << 2)
+#define		DC_LB_DISP1_END_ADR_SHIFT		4
+#define		DC_LB_DISP1_END_ADR_MASK		0x00007FF0
+#define D1MODE_PRIORITY_A_CNT		0x6548
+#define		MODE_PRIORITY_MARK_MASK			0x00007FFF
+#define		MODE_PRIORITY_OFF			(1 << 16)
+#define		MODE_PRIORITY_ALWAYS_ON			(1 << 20)
+#define		MODE_PRIORITY_FORCE_MASK		(1 << 24)
+#define D1MODE_PRIORITY_B_CNT		0x654C
+#define LB_MAX_REQ_OUTSTANDING		0x6D58
+#define		LB_D1_MAX_REQ_OUTSTANDING_MASK		0x0000000F
+#define		LB_D1_MAX_REQ_OUTSTANDING_SHIFT		0
+#define		LB_D2_MAX_REQ_OUTSTANDING_MASK		0x000F0000
+#define		LB_D2_MAX_REQ_OUTSTANDING_SHIFT		16
+#define D2MODE_PRIORITY_A_CNT		0x6D48
+#define D2MODE_PRIORITY_B_CNT		0x6D4C
+
+/* ix[MC] registers */
+#define MC_FB_LOCATION			0x01
+#define		MC_FB_START_MASK			0x0000FFFF
+#define		MC_FB_START_SHIFT			0
+#define		MC_FB_TOP_MASK				0xFFFF0000
+#define		MC_FB_TOP_SHIFT				16
+#define MC_AGP_LOCATION			0x02
+#define		MC_AGP_START_MASK			0x0000FFFF
+#define		MC_AGP_START_SHIFT			0
+#define		MC_AGP_TOP_MASK				0xFFFF0000
+#define		MC_AGP_TOP_SHIFT			16
+#define MC_AGP_BASE			0x03
+#define MC_AGP_BASE_2			0x04
+#define	MC_CNTL				0x5
+#define		MEM_NUM_CHANNELS_MASK			0x00000003
+#define	MC_STATUS			0x08
+#define		MC_STATUS_IDLE				(1 << 4)
+#define	MC_MISC_LAT_TIMER		0x09
+#define		MC_CPR_INIT_LAT_MASK			0x0000000F
+#define		MC_VF_INIT_LAT_MASK			0x000000F0
+#define		MC_DISP0R_INIT_LAT_MASK			0x00000F00
+#define		MC_DISP0R_INIT_LAT_SHIFT		8
+#define		MC_DISP1R_INIT_LAT_MASK			0x0000F000
+#define		MC_DISP1R_INIT_LAT_SHIFT		12
+#define		MC_FIXED_INIT_LAT_MASK			0x000F0000
+#define		MC_E2R_INIT_LAT_MASK			0x00F00000
+#define		SAME_PAGE_PRIO_MASK			0x0F000000
+#define		MC_GLOBW_INIT_LAT_MASK			0xF0000000
+
+
+#endif
+
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rv770.c linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rv770.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/radeon/rv770.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/radeon/rv770.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#include "drmP.h"
+#include "radeon_reg.h"
+#include "radeon.h"
+
+/* rv770,rv730,rv710  depends on : */
+void rs600_mc_disable_clients(struct radeon_device *rdev);
+
+/* This files gather functions specifics to:
+ * rv770,rv730,rv710
+ *
+ * Some of these functions might be used by newer ASICs.
+ */
+int rv770_mc_wait_for_idle(struct radeon_device *rdev);
+void rv770_gpu_init(struct radeon_device *rdev);
+
+
+/*
+ * MC
+ */
+int rv770_mc_init(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+
+	rv770_gpu_init(rdev);
+
+	/* setup the gart before changing location so we can ask to
+	 * discard unmapped mc request
+	 */
+	/* FIXME: disable out of gart access */
+	tmp = rdev->mc.gtt_location / 4096;
+	tmp = REG_SET(R700_LOGICAL_PAGE_NUMBER, tmp);
+	WREG32(R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, tmp);
+	tmp = (rdev->mc.gtt_location + rdev->mc.gtt_size) / 4096;
+	tmp = REG_SET(R700_LOGICAL_PAGE_NUMBER, tmp);
+	WREG32(R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, tmp);
+
+	rs600_mc_disable_clients(rdev);
+	if (rv770_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen.\n");
+	}
+
+	tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+	tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24);
+	tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24);
+	WREG32(R700_MC_VM_FB_LOCATION, tmp);
+	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	tmp = REG_SET(R700_MC_AGP_TOP, tmp >> 22);
+	WREG32(R700_MC_VM_AGP_TOP, tmp);
+	tmp = REG_SET(R700_MC_AGP_BOT, rdev->mc.gtt_location >> 22);
+	WREG32(R700_MC_VM_AGP_BOT, tmp);
+	return 0;
+}
+
+void rv770_mc_fini(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+
+/*
+ * Global GPU functions
+ */
+void rv770_errata(struct radeon_device *rdev)
+{
+	rdev->pll_errata = 0;
+}
+
+int rv770_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+	return 0;
+}
+
+void rv770_gpu_init(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+
+/*
+ * VRAM info
+ */
+void rv770_vram_get_type(struct radeon_device *rdev)
+{
+	/* FIXME: implement */
+}
+
+void rv770_vram_info(struct radeon_device *rdev)
+{
+	rv770_vram_get_type(rdev);
+
+	/* FIXME: implement */
+	/* Could aper size report 0 ? */
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/savage/savage_bci.c linux-libre-2.6.31-gnu/drivers/gpu/drm/savage/savage_bci.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/savage/savage_bci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/savage/savage_bci.c	2009-09-09 18:13:59.000000000 -0400
@@ -298,8 +298,8 @@
 
 	dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
 	    (SAVAGE_DMA_PAGE_SIZE * 4);
-	dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
-					dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
+	dev_priv->dma_pages = kmalloc(sizeof(drm_savage_dma_page_t) *
+				      dev_priv->nr_dma_pages, GFP_KERNEL);
 	if (dev_priv->dma_pages == NULL)
 		return -ENOMEM;
 
@@ -539,7 +539,7 @@
 {
 	drm_savage_private_t *dev_priv;
 
-	dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+	dev_priv = kmalloc(sizeof(drm_savage_private_t), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
@@ -671,7 +671,7 @@
 {
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
-	drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+	kfree(dev_priv);
 
 	return 0;
 }
@@ -804,8 +804,8 @@
 		dev_priv->fake_dma.offset = 0;
 		dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE;
 		dev_priv->fake_dma.type = _DRM_SHM;
-		dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE,
-						      DRM_MEM_DRIVER);
+		dev_priv->fake_dma.handle = kmalloc(SAVAGE_FAKE_DMA_SIZE,
+						    GFP_KERNEL);
 		if (!dev_priv->fake_dma.handle) {
 			DRM_ERROR("could not allocate faked DMA buffer!\n");
 			savage_do_cleanup_bci(dev);
@@ -903,9 +903,7 @@
 	drm_savage_private_t *dev_priv = dev->dev_private;
 
 	if (dev_priv->cmd_dma == &dev_priv->fake_dma) {
-		if (dev_priv->fake_dma.handle)
-			drm_free(dev_priv->fake_dma.handle,
-				 SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER);
+		kfree(dev_priv->fake_dma.handle);
 	} else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle &&
 		   dev_priv->cmd_dma->type == _DRM_AGP &&
 		   dev_priv->dma_type == SAVAGE_DMA_AGP)
@@ -920,10 +918,7 @@
 		dev->agp_buffer_map = NULL;
 	}
 
-	if (dev_priv->dma_pages)
-		drm_free(dev_priv->dma_pages,
-			 sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages,
-			 DRM_MEM_DRIVER);
+	kfree(dev_priv->dma_pages);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/savage/savage_state.c linux-libre-2.6.31-gnu/drivers/gpu/drm/savage/savage_state.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/savage/savage_state.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/savage/savage_state.c	2009-09-09 18:13:59.000000000 -0400
@@ -988,20 +988,20 @@
 	 * for locking on FreeBSD.
 	 */
 	if (cmdbuf->size) {
-		kcmd_addr = drm_alloc(cmdbuf->size * 8, DRM_MEM_DRIVER);
+		kcmd_addr = kmalloc(cmdbuf->size * 8, GFP_KERNEL);
 		if (kcmd_addr == NULL)
 			return -ENOMEM;
 
 		if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr,
 				       cmdbuf->size * 8))
 		{
-			drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
+			kfree(kcmd_addr);
 			return -EFAULT;
 		}
 		cmdbuf->cmd_addr = kcmd_addr;
 	}
 	if (cmdbuf->vb_size) {
-		kvb_addr = drm_alloc(cmdbuf->vb_size, DRM_MEM_DRIVER);
+		kvb_addr = kmalloc(cmdbuf->vb_size, GFP_KERNEL);
 		if (kvb_addr == NULL) {
 			ret = -ENOMEM;
 			goto done;
@@ -1015,8 +1015,8 @@
 		cmdbuf->vb_addr = kvb_addr;
 	}
 	if (cmdbuf->nbox) {
-		kbox_addr = drm_alloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
-				       DRM_MEM_DRIVER);
+		kbox_addr = kmalloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
+				    GFP_KERNEL);
 		if (kbox_addr == NULL) {
 			ret = -ENOMEM;
 			goto done;
@@ -1154,10 +1154,9 @@
 
 done:
 	/* If we didn't need to allocate them, these'll be NULL */
-	drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
-	drm_free(kvb_addr, cmdbuf->vb_size, DRM_MEM_DRIVER);
-	drm_free(kbox_addr, cmdbuf->nbox * sizeof(struct drm_clip_rect),
-		 DRM_MEM_DRIVER);
+	kfree(kcmd_addr);
+	kfree(kvb_addr);
+	kfree(kbox_addr);
 
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/sis/sis_drv.c linux-libre-2.6.31-gnu/drivers/gpu/drm/sis/sis_drv.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/sis/sis_drv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/sis/sis_drv.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 	drm_sis_private_t *dev_priv;
 	int ret;
 
-	dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER);
+	dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
@@ -48,7 +48,7 @@
 	dev_priv->chipset = chipset;
 	ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
 	if (ret) {
-		drm_free(dev_priv, sizeof(dev_priv), DRM_MEM_DRIVER);
+		kfree(dev_priv);
 	}
 
 	return ret;
@@ -59,7 +59,7 @@
 	drm_sis_private_t *dev_priv = dev->dev_private;
 
 	drm_sman_takedown(&dev_priv->sman);
-	drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+	kfree(dev_priv);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/Makefile linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/Makefile
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,8 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+
+ccflags-y := -Iinclude/drm
+ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \
+	ttm_bo_util.o ttm_bo_vm.o ttm_module.o ttm_global.o
+
+obj-$(CONFIG_DRM_TTM) += ttm.o
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,149 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ *          Keith Packard.
+ */
+
+#include "ttm/ttm_module.h"
+#include "ttm/ttm_bo_driver.h"
+#ifdef TTM_HAS_AGP
+#include "ttm/ttm_placement.h"
+#include <linux/agp_backend.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <asm/agp.h>
+
+struct ttm_agp_backend {
+	struct ttm_backend backend;
+	struct agp_memory *mem;
+	struct agp_bridge_data *bridge;
+};
+
+static int ttm_agp_populate(struct ttm_backend *backend,
+			    unsigned long num_pages, struct page **pages,
+			    struct page *dummy_read_page)
+{
+	struct ttm_agp_backend *agp_be =
+	    container_of(backend, struct ttm_agp_backend, backend);
+	struct page **cur_page, **last_page = pages + num_pages;
+	struct agp_memory *mem;
+
+	mem = agp_allocate_memory(agp_be->bridge, num_pages, AGP_USER_MEMORY);
+	if (unlikely(mem == NULL))
+		return -ENOMEM;
+
+	mem->page_count = 0;
+	for (cur_page = pages; cur_page < last_page; ++cur_page) {
+		struct page *page = *cur_page;
+		if (!page)
+			page = dummy_read_page;
+
+		mem->pages[mem->page_count++] = page;
+	}
+	agp_be->mem = mem;
+	return 0;
+}
+
+static int ttm_agp_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem)
+{
+	struct ttm_agp_backend *agp_be =
+	    container_of(backend, struct ttm_agp_backend, backend);
+	struct agp_memory *mem = agp_be->mem;
+	int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED);
+	int ret;
+
+	mem->is_flushed = 1;
+	mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY;
+
+	ret = agp_bind_memory(mem, bo_mem->mm_node->start);
+	if (ret)
+		printk(KERN_ERR TTM_PFX "AGP Bind memory failed.\n");
+
+	return ret;
+}
+
+static int ttm_agp_unbind(struct ttm_backend *backend)
+{
+	struct ttm_agp_backend *agp_be =
+	    container_of(backend, struct ttm_agp_backend, backend);
+
+	if (agp_be->mem->is_bound)
+		return agp_unbind_memory(agp_be->mem);
+	else
+		return 0;
+}
+
+static void ttm_agp_clear(struct ttm_backend *backend)
+{
+	struct ttm_agp_backend *agp_be =
+	    container_of(backend, struct ttm_agp_backend, backend);
+	struct agp_memory *mem = agp_be->mem;
+
+	if (mem) {
+		ttm_agp_unbind(backend);
+		agp_free_memory(mem);
+	}
+	agp_be->mem = NULL;
+}
+
+static void ttm_agp_destroy(struct ttm_backend *backend)
+{
+	struct ttm_agp_backend *agp_be =
+	    container_of(backend, struct ttm_agp_backend, backend);
+
+	if (agp_be->mem)
+		ttm_agp_clear(backend);
+	kfree(agp_be);
+}
+
+static struct ttm_backend_func ttm_agp_func = {
+	.populate = ttm_agp_populate,
+	.clear = ttm_agp_clear,
+	.bind = ttm_agp_bind,
+	.unbind = ttm_agp_unbind,
+	.destroy = ttm_agp_destroy,
+};
+
+struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev,
+					 struct agp_bridge_data *bridge)
+{
+	struct ttm_agp_backend *agp_be;
+
+	agp_be = kmalloc(sizeof(*agp_be), GFP_KERNEL);
+	if (!agp_be)
+		return NULL;
+
+	agp_be->mem = NULL;
+	agp_be->bridge = bridge;
+	agp_be->backend.func = &ttm_agp_func;
+	agp_be->backend.bdev = bdev;
+	return &agp_be->backend;
+}
+EXPORT_SYMBOL(ttm_agp_backend_init);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_bo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1741 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include "ttm/ttm_module.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/file.h>
+#include <linux/module.h>
+
+#define TTM_ASSERT_LOCKED(param)
+#define TTM_DEBUG(fmt, arg...)
+#define TTM_BO_HASH_ORDER 13
+
+static int ttm_bo_setup_vm(struct ttm_buffer_object *bo);
+static int ttm_bo_swapout(struct ttm_mem_shrink *shrink);
+
+static inline uint32_t ttm_bo_type_flags(unsigned type)
+{
+	return 1 << (type);
+}
+
+static void ttm_bo_release_list(struct kref *list_kref)
+{
+	struct ttm_buffer_object *bo =
+	    container_of(list_kref, struct ttm_buffer_object, list_kref);
+	struct ttm_bo_device *bdev = bo->bdev;
+
+	BUG_ON(atomic_read(&bo->list_kref.refcount));
+	BUG_ON(atomic_read(&bo->kref.refcount));
+	BUG_ON(atomic_read(&bo->cpu_writers));
+	BUG_ON(bo->sync_obj != NULL);
+	BUG_ON(bo->mem.mm_node != NULL);
+	BUG_ON(!list_empty(&bo->lru));
+	BUG_ON(!list_empty(&bo->ddestroy));
+
+	if (bo->ttm)
+		ttm_tt_destroy(bo->ttm);
+	if (bo->destroy)
+		bo->destroy(bo);
+	else {
+		ttm_mem_global_free(bdev->mem_glob, bo->acc_size, false);
+		kfree(bo);
+	}
+}
+
+int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, bool interruptible)
+{
+
+	if (interruptible) {
+		int ret = 0;
+
+		ret = wait_event_interruptible(bo->event_queue,
+					       atomic_read(&bo->reserved) == 0);
+		if (unlikely(ret != 0))
+			return -ERESTART;
+	} else {
+		wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0);
+	}
+	return 0;
+}
+
+static void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_type_manager *man;
+
+	BUG_ON(!atomic_read(&bo->reserved));
+
+	if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
+
+		BUG_ON(!list_empty(&bo->lru));
+
+		man = &bdev->man[bo->mem.mem_type];
+		list_add_tail(&bo->lru, &man->lru);
+		kref_get(&bo->list_kref);
+
+		if (bo->ttm != NULL) {
+			list_add_tail(&bo->swap, &bdev->swap_lru);
+			kref_get(&bo->list_kref);
+		}
+	}
+}
+
+/**
+ * Call with the lru_lock held.
+ */
+
+static int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
+{
+	int put_count = 0;
+
+	if (!list_empty(&bo->swap)) {
+		list_del_init(&bo->swap);
+		++put_count;
+	}
+	if (!list_empty(&bo->lru)) {
+		list_del_init(&bo->lru);
+		++put_count;
+	}
+
+	/*
+	 * TODO: Add a driver hook to delete from
+	 * driver-specific LRU's here.
+	 */
+
+	return put_count;
+}
+
+int ttm_bo_reserve_locked(struct ttm_buffer_object *bo,
+			  bool interruptible,
+			  bool no_wait, bool use_sequence, uint32_t sequence)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	int ret;
+
+	while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
+		if (use_sequence && bo->seq_valid &&
+			(sequence - bo->val_seq < (1 << 31))) {
+			return -EAGAIN;
+		}
+
+		if (no_wait)
+			return -EBUSY;
+
+		spin_unlock(&bdev->lru_lock);
+		ret = ttm_bo_wait_unreserved(bo, interruptible);
+		spin_lock(&bdev->lru_lock);
+
+		if (unlikely(ret))
+			return ret;
+	}
+
+	if (use_sequence) {
+		bo->val_seq = sequence;
+		bo->seq_valid = true;
+	} else {
+		bo->seq_valid = false;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ttm_bo_reserve);
+
+static void ttm_bo_ref_bug(struct kref *list_kref)
+{
+	BUG();
+}
+
+int ttm_bo_reserve(struct ttm_buffer_object *bo,
+		   bool interruptible,
+		   bool no_wait, bool use_sequence, uint32_t sequence)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	int put_count = 0;
+	int ret;
+
+	spin_lock(&bdev->lru_lock);
+	ret = ttm_bo_reserve_locked(bo, interruptible, no_wait, use_sequence,
+				    sequence);
+	if (likely(ret == 0))
+		put_count = ttm_bo_del_from_lru(bo);
+	spin_unlock(&bdev->lru_lock);
+
+	while (put_count--)
+		kref_put(&bo->list_kref, ttm_bo_ref_bug);
+
+	return ret;
+}
+
+void ttm_bo_unreserve(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+
+	spin_lock(&bdev->lru_lock);
+	ttm_bo_add_to_lru(bo);
+	atomic_set(&bo->reserved, 0);
+	wake_up_all(&bo->event_queue);
+	spin_unlock(&bdev->lru_lock);
+}
+EXPORT_SYMBOL(ttm_bo_unreserve);
+
+/*
+ * Call bo->mutex locked.
+ */
+
+static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	int ret = 0;
+	uint32_t page_flags = 0;
+
+	TTM_ASSERT_LOCKED(&bo->mutex);
+	bo->ttm = NULL;
+
+	if (bdev->need_dma32)
+		page_flags |= TTM_PAGE_FLAG_DMA32;
+
+	switch (bo->type) {
+	case ttm_bo_type_device:
+		if (zero_alloc)
+			page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC;
+	case ttm_bo_type_kernel:
+		bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
+					page_flags, bdev->dummy_read_page);
+		if (unlikely(bo->ttm == NULL))
+			ret = -ENOMEM;
+		break;
+	case ttm_bo_type_user:
+		bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
+					page_flags | TTM_PAGE_FLAG_USER,
+					bdev->dummy_read_page);
+		if (unlikely(bo->ttm == NULL))
+			ret = -ENOMEM;
+		break;
+
+		ret = ttm_tt_set_user(bo->ttm, current,
+				      bo->buffer_start, bo->num_pages);
+		if (unlikely(ret != 0))
+			ttm_tt_destroy(bo->ttm);
+		break;
+	default:
+		printk(KERN_ERR TTM_PFX "Illegal buffer object type\n");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
+				  struct ttm_mem_reg *mem,
+				  bool evict, bool interruptible, bool no_wait)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	bool old_is_pci = ttm_mem_reg_is_pci(bdev, &bo->mem);
+	bool new_is_pci = ttm_mem_reg_is_pci(bdev, mem);
+	struct ttm_mem_type_manager *old_man = &bdev->man[bo->mem.mem_type];
+	struct ttm_mem_type_manager *new_man = &bdev->man[mem->mem_type];
+	int ret = 0;
+
+	if (old_is_pci || new_is_pci ||
+	    ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0))
+		ttm_bo_unmap_virtual(bo);
+
+	/*
+	 * Create and bind a ttm if required.
+	 */
+
+	if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm == NULL)) {
+		ret = ttm_bo_add_ttm(bo, false);
+		if (ret)
+			goto out_err;
+
+		ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement);
+		if (ret)
+			goto out_err;
+
+		if (mem->mem_type != TTM_PL_SYSTEM) {
+			ret = ttm_tt_bind(bo->ttm, mem);
+			if (ret)
+				goto out_err;
+		}
+
+		if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+
+			struct ttm_mem_reg *old_mem = &bo->mem;
+			uint32_t save_flags = old_mem->placement;
+
+			*old_mem = *mem;
+			mem->mm_node = NULL;
+			ttm_flag_masked(&save_flags, mem->placement,
+					TTM_PL_MASK_MEMTYPE);
+			goto moved;
+		}
+
+	}
+
+	if (bdev->driver->move_notify)
+		bdev->driver->move_notify(bo, mem);
+
+	if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
+	    !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
+		ret = ttm_bo_move_ttm(bo, evict, no_wait, mem);
+	else if (bdev->driver->move)
+		ret = bdev->driver->move(bo, evict, interruptible,
+					 no_wait, mem);
+	else
+		ret = ttm_bo_move_memcpy(bo, evict, no_wait, mem);
+
+	if (ret)
+		goto out_err;
+
+moved:
+	if (bo->evicted) {
+		ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
+		if (ret)
+			printk(KERN_ERR TTM_PFX "Can not flush read caches\n");
+		bo->evicted = false;
+	}
+
+	if (bo->mem.mm_node) {
+		spin_lock(&bo->lock);
+		bo->offset = (bo->mem.mm_node->start << PAGE_SHIFT) +
+		    bdev->man[bo->mem.mem_type].gpu_offset;
+		bo->cur_placement = bo->mem.placement;
+		spin_unlock(&bo->lock);
+	}
+
+	return 0;
+
+out_err:
+	new_man = &bdev->man[bo->mem.mem_type];
+	if ((new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm) {
+		ttm_tt_unbind(bo->ttm);
+		ttm_tt_destroy(bo->ttm);
+		bo->ttm = NULL;
+	}
+
+	return ret;
+}
+
+/**
+ * If bo idle, remove from delayed- and lru lists, and unref.
+ * If not idle, and already on delayed list, do nothing.
+ * If not idle, and not on delayed list, put on delayed list,
+ *   up the list_kref and schedule a delayed list check.
+ */
+
+static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_bo_driver *driver = bdev->driver;
+	int ret;
+
+	spin_lock(&bo->lock);
+	(void) ttm_bo_wait(bo, false, false, !remove_all);
+
+	if (!bo->sync_obj) {
+		int put_count;
+
+		spin_unlock(&bo->lock);
+
+		spin_lock(&bdev->lru_lock);
+		ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
+		BUG_ON(ret);
+		if (bo->ttm)
+			ttm_tt_unbind(bo->ttm);
+
+		if (!list_empty(&bo->ddestroy)) {
+			list_del_init(&bo->ddestroy);
+			kref_put(&bo->list_kref, ttm_bo_ref_bug);
+		}
+		if (bo->mem.mm_node) {
+			drm_mm_put_block(bo->mem.mm_node);
+			bo->mem.mm_node = NULL;
+		}
+		put_count = ttm_bo_del_from_lru(bo);
+		spin_unlock(&bdev->lru_lock);
+
+		atomic_set(&bo->reserved, 0);
+
+		while (put_count--)
+			kref_put(&bo->list_kref, ttm_bo_release_list);
+
+		return 0;
+	}
+
+	spin_lock(&bdev->lru_lock);
+	if (list_empty(&bo->ddestroy)) {
+		void *sync_obj = bo->sync_obj;
+		void *sync_obj_arg = bo->sync_obj_arg;
+
+		kref_get(&bo->list_kref);
+		list_add_tail(&bo->ddestroy, &bdev->ddestroy);
+		spin_unlock(&bdev->lru_lock);
+		spin_unlock(&bo->lock);
+
+		if (sync_obj)
+			driver->sync_obj_flush(sync_obj, sync_obj_arg);
+		schedule_delayed_work(&bdev->wq,
+				      ((HZ / 100) < 1) ? 1 : HZ / 100);
+		ret = 0;
+
+	} else {
+		spin_unlock(&bdev->lru_lock);
+		spin_unlock(&bo->lock);
+		ret = -EBUSY;
+	}
+
+	return ret;
+}
+
+/**
+ * Traverse the delayed list, and call ttm_bo_cleanup_refs on all
+ * encountered buffers.
+ */
+
+static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
+{
+	struct ttm_buffer_object *entry, *nentry;
+	struct list_head *list, *next;
+	int ret;
+
+	spin_lock(&bdev->lru_lock);
+	list_for_each_safe(list, next, &bdev->ddestroy) {
+		entry = list_entry(list, struct ttm_buffer_object, ddestroy);
+		nentry = NULL;
+
+		/*
+		 * Protect the next list entry from destruction while we
+		 * unlock the lru_lock.
+		 */
+
+		if (next != &bdev->ddestroy) {
+			nentry = list_entry(next, struct ttm_buffer_object,
+					    ddestroy);
+			kref_get(&nentry->list_kref);
+		}
+		kref_get(&entry->list_kref);
+
+		spin_unlock(&bdev->lru_lock);
+		ret = ttm_bo_cleanup_refs(entry, remove_all);
+		kref_put(&entry->list_kref, ttm_bo_release_list);
+
+		spin_lock(&bdev->lru_lock);
+		if (nentry) {
+			bool next_onlist = !list_empty(next);
+			spin_unlock(&bdev->lru_lock);
+			kref_put(&nentry->list_kref, ttm_bo_release_list);
+			spin_lock(&bdev->lru_lock);
+			/*
+			 * Someone might have raced us and removed the
+			 * next entry from the list. We don't bother restarting
+			 * list traversal.
+			 */
+
+			if (!next_onlist)
+				break;
+		}
+		if (ret)
+			break;
+	}
+	ret = !list_empty(&bdev->ddestroy);
+	spin_unlock(&bdev->lru_lock);
+
+	return ret;
+}
+
+static void ttm_bo_delayed_workqueue(struct work_struct *work)
+{
+	struct ttm_bo_device *bdev =
+	    container_of(work, struct ttm_bo_device, wq.work);
+
+	if (ttm_bo_delayed_delete(bdev, false)) {
+		schedule_delayed_work(&bdev->wq,
+				      ((HZ / 100) < 1) ? 1 : HZ / 100);
+	}
+}
+
+static void ttm_bo_release(struct kref *kref)
+{
+	struct ttm_buffer_object *bo =
+	    container_of(kref, struct ttm_buffer_object, kref);
+	struct ttm_bo_device *bdev = bo->bdev;
+
+	if (likely(bo->vm_node != NULL)) {
+		rb_erase(&bo->vm_rb, &bdev->addr_space_rb);
+		drm_mm_put_block(bo->vm_node);
+		bo->vm_node = NULL;
+	}
+	write_unlock(&bdev->vm_lock);
+	ttm_bo_cleanup_refs(bo, false);
+	kref_put(&bo->list_kref, ttm_bo_release_list);
+	write_lock(&bdev->vm_lock);
+}
+
+void ttm_bo_unref(struct ttm_buffer_object **p_bo)
+{
+	struct ttm_buffer_object *bo = *p_bo;
+	struct ttm_bo_device *bdev = bo->bdev;
+
+	*p_bo = NULL;
+	write_lock(&bdev->vm_lock);
+	kref_put(&bo->kref, ttm_bo_release);
+	write_unlock(&bdev->vm_lock);
+}
+EXPORT_SYMBOL(ttm_bo_unref);
+
+static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type,
+			bool interruptible, bool no_wait)
+{
+	int ret = 0;
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_reg evict_mem;
+	uint32_t proposed_placement;
+
+	if (bo->mem.mem_type != mem_type)
+		goto out;
+
+	spin_lock(&bo->lock);
+	ret = ttm_bo_wait(bo, false, interruptible, no_wait);
+	spin_unlock(&bo->lock);
+
+	if (unlikely(ret != 0)) {
+		if (ret != -ERESTART) {
+			printk(KERN_ERR TTM_PFX
+			       "Failed to expire sync object before "
+			       "buffer eviction.\n");
+		}
+		goto out;
+	}
+
+	BUG_ON(!atomic_read(&bo->reserved));
+
+	evict_mem = bo->mem;
+	evict_mem.mm_node = NULL;
+
+	proposed_placement = bdev->driver->evict_flags(bo);
+
+	ret = ttm_bo_mem_space(bo, proposed_placement,
+			       &evict_mem, interruptible, no_wait);
+	if (unlikely(ret != 0 && ret != -ERESTART))
+		ret = ttm_bo_mem_space(bo, TTM_PL_FLAG_SYSTEM,
+				       &evict_mem, interruptible, no_wait);
+
+	if (ret) {
+		if (ret != -ERESTART)
+			printk(KERN_ERR TTM_PFX
+			       "Failed to find memory space for "
+			       "buffer 0x%p eviction.\n", bo);
+		goto out;
+	}
+
+	ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible,
+				     no_wait);
+	if (ret) {
+		if (ret != -ERESTART)
+			printk(KERN_ERR TTM_PFX "Buffer eviction failed\n");
+		goto out;
+	}
+
+	spin_lock(&bdev->lru_lock);
+	if (evict_mem.mm_node) {
+		drm_mm_put_block(evict_mem.mm_node);
+		evict_mem.mm_node = NULL;
+	}
+	spin_unlock(&bdev->lru_lock);
+	bo->evicted = true;
+out:
+	return ret;
+}
+
+/**
+ * Repeatedly evict memory from the LRU for @mem_type until we create enough
+ * space, or we've evicted everything and there isn't enough space.
+ */
+static int ttm_bo_mem_force_space(struct ttm_bo_device *bdev,
+				  struct ttm_mem_reg *mem,
+				  uint32_t mem_type,
+				  bool interruptible, bool no_wait)
+{
+	struct drm_mm_node *node;
+	struct ttm_buffer_object *entry;
+	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
+	struct list_head *lru;
+	unsigned long num_pages = mem->num_pages;
+	int put_count = 0;
+	int ret;
+
+retry_pre_get:
+	ret = drm_mm_pre_get(&man->manager);
+	if (unlikely(ret != 0))
+		return ret;
+
+	spin_lock(&bdev->lru_lock);
+	do {
+		node = drm_mm_search_free(&man->manager, num_pages,
+					  mem->page_alignment, 1);
+		if (node)
+			break;
+
+		lru = &man->lru;
+		if (list_empty(lru))
+			break;
+
+		entry = list_first_entry(lru, struct ttm_buffer_object, lru);
+		kref_get(&entry->list_kref);
+
+		ret =
+		    ttm_bo_reserve_locked(entry, interruptible, no_wait,
+					  false, 0);
+
+		if (likely(ret == 0))
+			put_count = ttm_bo_del_from_lru(entry);
+
+		spin_unlock(&bdev->lru_lock);
+
+		if (unlikely(ret != 0))
+			return ret;
+
+		while (put_count--)
+			kref_put(&entry->list_kref, ttm_bo_ref_bug);
+
+		ret = ttm_bo_evict(entry, mem_type, interruptible, no_wait);
+
+		ttm_bo_unreserve(entry);
+
+		kref_put(&entry->list_kref, ttm_bo_release_list);
+		if (ret)
+			return ret;
+
+		spin_lock(&bdev->lru_lock);
+	} while (1);
+
+	if (!node) {
+		spin_unlock(&bdev->lru_lock);
+		return -ENOMEM;
+	}
+
+	node = drm_mm_get_block_atomic(node, num_pages, mem->page_alignment);
+	if (unlikely(!node)) {
+		spin_unlock(&bdev->lru_lock);
+		goto retry_pre_get;
+	}
+
+	spin_unlock(&bdev->lru_lock);
+	mem->mm_node = node;
+	mem->mem_type = mem_type;
+	return 0;
+}
+
+static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man,
+				      uint32_t cur_placement,
+				      uint32_t proposed_placement)
+{
+	uint32_t caching = proposed_placement & TTM_PL_MASK_CACHING;
+	uint32_t result = proposed_placement & ~TTM_PL_MASK_CACHING;
+
+	/**
+	 * Keep current caching if possible.
+	 */
+
+	if ((cur_placement & caching) != 0)
+		result |= (cur_placement & caching);
+	else if ((man->default_caching & caching) != 0)
+		result |= man->default_caching;
+	else if ((TTM_PL_FLAG_CACHED & caching) != 0)
+		result |= TTM_PL_FLAG_CACHED;
+	else if ((TTM_PL_FLAG_WC & caching) != 0)
+		result |= TTM_PL_FLAG_WC;
+	else if ((TTM_PL_FLAG_UNCACHED & caching) != 0)
+		result |= TTM_PL_FLAG_UNCACHED;
+
+	return result;
+}
+
+
+static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man,
+				 bool disallow_fixed,
+				 uint32_t mem_type,
+				 uint32_t proposed_placement,
+				 uint32_t *masked_placement)
+{
+	uint32_t cur_flags = ttm_bo_type_flags(mem_type);
+
+	if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed)
+		return false;
+
+	if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0)
+		return false;
+
+	if ((proposed_placement & man->available_caching) == 0)
+		return false;
+
+	cur_flags |= (proposed_placement & man->available_caching);
+
+	*masked_placement = cur_flags;
+	return true;
+}
+
+/**
+ * Creates space for memory region @mem according to its type.
+ *
+ * This function first searches for free space in compatible memory types in
+ * the priority order defined by the driver.  If free space isn't found, then
+ * ttm_bo_mem_force_space is attempted in priority order to evict and find
+ * space.
+ */
+int ttm_bo_mem_space(struct ttm_buffer_object *bo,
+		     uint32_t proposed_placement,
+		     struct ttm_mem_reg *mem,
+		     bool interruptible, bool no_wait)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_type_manager *man;
+
+	uint32_t num_prios = bdev->driver->num_mem_type_prio;
+	const uint32_t *prios = bdev->driver->mem_type_prio;
+	uint32_t i;
+	uint32_t mem_type = TTM_PL_SYSTEM;
+	uint32_t cur_flags = 0;
+	bool type_found = false;
+	bool type_ok = false;
+	bool has_eagain = false;
+	struct drm_mm_node *node = NULL;
+	int ret;
+
+	mem->mm_node = NULL;
+	for (i = 0; i < num_prios; ++i) {
+		mem_type = prios[i];
+		man = &bdev->man[mem_type];
+
+		type_ok = ttm_bo_mt_compatible(man,
+					       bo->type == ttm_bo_type_user,
+					       mem_type, proposed_placement,
+					       &cur_flags);
+
+		if (!type_ok)
+			continue;
+
+		cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
+						  cur_flags);
+
+		if (mem_type == TTM_PL_SYSTEM)
+			break;
+
+		if (man->has_type && man->use_type) {
+			type_found = true;
+			do {
+				ret = drm_mm_pre_get(&man->manager);
+				if (unlikely(ret))
+					return ret;
+
+				spin_lock(&bdev->lru_lock);
+				node = drm_mm_search_free(&man->manager,
+							  mem->num_pages,
+							  mem->page_alignment,
+							  1);
+				if (unlikely(!node)) {
+					spin_unlock(&bdev->lru_lock);
+					break;
+				}
+				node = drm_mm_get_block_atomic(node,
+							       mem->num_pages,
+							       mem->
+							       page_alignment);
+				spin_unlock(&bdev->lru_lock);
+			} while (!node);
+		}
+		if (node)
+			break;
+	}
+
+	if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || node) {
+		mem->mm_node = node;
+		mem->mem_type = mem_type;
+		mem->placement = cur_flags;
+		return 0;
+	}
+
+	if (!type_found)
+		return -EINVAL;
+
+	num_prios = bdev->driver->num_mem_busy_prio;
+	prios = bdev->driver->mem_busy_prio;
+
+	for (i = 0; i < num_prios; ++i) {
+		mem_type = prios[i];
+		man = &bdev->man[mem_type];
+
+		if (!man->has_type)
+			continue;
+
+		if (!ttm_bo_mt_compatible(man,
+					  bo->type == ttm_bo_type_user,
+					  mem_type,
+					  proposed_placement, &cur_flags))
+			continue;
+
+		cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
+						  cur_flags);
+
+		ret = ttm_bo_mem_force_space(bdev, mem, mem_type,
+					     interruptible, no_wait);
+
+		if (ret == 0 && mem->mm_node) {
+			mem->placement = cur_flags;
+			return 0;
+		}
+
+		if (ret == -ERESTART)
+			has_eagain = true;
+	}
+
+	ret = (has_eagain) ? -ERESTART : -ENOMEM;
+	return ret;
+}
+EXPORT_SYMBOL(ttm_bo_mem_space);
+
+int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait)
+{
+	int ret = 0;
+
+	if ((atomic_read(&bo->cpu_writers) > 0) && no_wait)
+		return -EBUSY;
+
+	ret = wait_event_interruptible(bo->event_queue,
+				       atomic_read(&bo->cpu_writers) == 0);
+
+	if (ret == -ERESTARTSYS)
+		ret = -ERESTART;
+
+	return ret;
+}
+
+int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
+		       uint32_t proposed_placement,
+		       bool interruptible, bool no_wait)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	int ret = 0;
+	struct ttm_mem_reg mem;
+
+	BUG_ON(!atomic_read(&bo->reserved));
+
+	/*
+	 * FIXME: It's possible to pipeline buffer moves.
+	 * Have the driver move function wait for idle when necessary,
+	 * instead of doing it here.
+	 */
+
+	spin_lock(&bo->lock);
+	ret = ttm_bo_wait(bo, false, interruptible, no_wait);
+	spin_unlock(&bo->lock);
+
+	if (ret)
+		return ret;
+
+	mem.num_pages = bo->num_pages;
+	mem.size = mem.num_pages << PAGE_SHIFT;
+	mem.page_alignment = bo->mem.page_alignment;
+
+	/*
+	 * Determine where to move the buffer.
+	 */
+
+	ret = ttm_bo_mem_space(bo, proposed_placement, &mem,
+			       interruptible, no_wait);
+	if (ret)
+		goto out_unlock;
+
+	ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait);
+
+out_unlock:
+	if (ret && mem.mm_node) {
+		spin_lock(&bdev->lru_lock);
+		drm_mm_put_block(mem.mm_node);
+		spin_unlock(&bdev->lru_lock);
+	}
+	return ret;
+}
+
+static int ttm_bo_mem_compat(uint32_t proposed_placement,
+			     struct ttm_mem_reg *mem)
+{
+	if ((proposed_placement & mem->placement & TTM_PL_MASK_MEM) == 0)
+		return 0;
+	if ((proposed_placement & mem->placement & TTM_PL_MASK_CACHING) == 0)
+		return 0;
+
+	return 1;
+}
+
+int ttm_buffer_object_validate(struct ttm_buffer_object *bo,
+			       uint32_t proposed_placement,
+			       bool interruptible, bool no_wait)
+{
+	int ret;
+
+	BUG_ON(!atomic_read(&bo->reserved));
+	bo->proposed_placement = proposed_placement;
+
+	TTM_DEBUG("Proposed placement 0x%08lx, Old flags 0x%08lx\n",
+		  (unsigned long)proposed_placement,
+		  (unsigned long)bo->mem.placement);
+
+	/*
+	 * Check whether we need to move buffer.
+	 */
+
+	if (!ttm_bo_mem_compat(bo->proposed_placement, &bo->mem)) {
+		ret = ttm_bo_move_buffer(bo, bo->proposed_placement,
+					 interruptible, no_wait);
+		if (ret) {
+			if (ret != -ERESTART)
+				printk(KERN_ERR TTM_PFX
+				       "Failed moving buffer. "
+				       "Proposed placement 0x%08x\n",
+				       bo->proposed_placement);
+			if (ret == -ENOMEM)
+				printk(KERN_ERR TTM_PFX
+				       "Out of aperture space or "
+				       "DRM memory quota.\n");
+			return ret;
+		}
+	}
+
+	/*
+	 * We might need to add a TTM.
+	 */
+
+	if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
+		ret = ttm_bo_add_ttm(bo, true);
+		if (ret)
+			return ret;
+	}
+	/*
+	 * Validation has succeeded, move the access and other
+	 * non-mapping-related flag bits from the proposed flags to
+	 * the active flags
+	 */
+
+	ttm_flag_masked(&bo->mem.placement, bo->proposed_placement,
+			~TTM_PL_MASK_MEMTYPE);
+
+	return 0;
+}
+EXPORT_SYMBOL(ttm_buffer_object_validate);
+
+int
+ttm_bo_check_placement(struct ttm_buffer_object *bo,
+		       uint32_t set_flags, uint32_t clr_flags)
+{
+	uint32_t new_mask = set_flags | clr_flags;
+
+	if ((bo->type == ttm_bo_type_user) &&
+	    (clr_flags & TTM_PL_FLAG_CACHED)) {
+		printk(KERN_ERR TTM_PFX
+		       "User buffers require cache-coherent memory.\n");
+		return -EINVAL;
+	}
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (new_mask & TTM_PL_FLAG_NO_EVICT) {
+			printk(KERN_ERR TTM_PFX "Need to be root to modify"
+			       " NO_EVICT status.\n");
+			return -EINVAL;
+		}
+
+		if ((clr_flags & bo->mem.placement & TTM_PL_MASK_MEMTYPE) &&
+		    (bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
+			printk(KERN_ERR TTM_PFX
+			       "Incompatible memory specification"
+			       " for NO_EVICT buffer.\n");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+int ttm_buffer_object_init(struct ttm_bo_device *bdev,
+			   struct ttm_buffer_object *bo,
+			   unsigned long size,
+			   enum ttm_bo_type type,
+			   uint32_t flags,
+			   uint32_t page_alignment,
+			   unsigned long buffer_start,
+			   bool interruptible,
+			   struct file *persistant_swap_storage,
+			   size_t acc_size,
+			   void (*destroy) (struct ttm_buffer_object *))
+{
+	int ret = 0;
+	unsigned long num_pages;
+
+	size += buffer_start & ~PAGE_MASK;
+	num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	if (num_pages == 0) {
+		printk(KERN_ERR TTM_PFX "Illegal buffer object size.\n");
+		return -EINVAL;
+	}
+	bo->destroy = destroy;
+
+	spin_lock_init(&bo->lock);
+	kref_init(&bo->kref);
+	kref_init(&bo->list_kref);
+	atomic_set(&bo->cpu_writers, 0);
+	atomic_set(&bo->reserved, 1);
+	init_waitqueue_head(&bo->event_queue);
+	INIT_LIST_HEAD(&bo->lru);
+	INIT_LIST_HEAD(&bo->ddestroy);
+	INIT_LIST_HEAD(&bo->swap);
+	bo->bdev = bdev;
+	bo->type = type;
+	bo->num_pages = num_pages;
+	bo->mem.mem_type = TTM_PL_SYSTEM;
+	bo->mem.num_pages = bo->num_pages;
+	bo->mem.mm_node = NULL;
+	bo->mem.page_alignment = page_alignment;
+	bo->buffer_start = buffer_start & PAGE_MASK;
+	bo->priv_flags = 0;
+	bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED);
+	bo->seq_valid = false;
+	bo->persistant_swap_storage = persistant_swap_storage;
+	bo->acc_size = acc_size;
+
+	ret = ttm_bo_check_placement(bo, flags, 0ULL);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	/*
+	 * If no caching attributes are set, accept any form of caching.
+	 */
+
+	if ((flags & TTM_PL_MASK_CACHING) == 0)
+		flags |= TTM_PL_MASK_CACHING;
+
+	/*
+	 * For ttm_bo_type_device buffers, allocate
+	 * address space from the device.
+	 */
+
+	if (bo->type == ttm_bo_type_device) {
+		ret = ttm_bo_setup_vm(bo);
+		if (ret)
+			goto out_err;
+	}
+
+	ret = ttm_buffer_object_validate(bo, flags, interruptible, false);
+	if (ret)
+		goto out_err;
+
+	ttm_bo_unreserve(bo);
+	return 0;
+
+out_err:
+	ttm_bo_unreserve(bo);
+	ttm_bo_unref(&bo);
+
+	return ret;
+}
+EXPORT_SYMBOL(ttm_buffer_object_init);
+
+static inline size_t ttm_bo_size(struct ttm_bo_device *bdev,
+				 unsigned long num_pages)
+{
+	size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) &
+	    PAGE_MASK;
+
+	return bdev->ttm_bo_size + 2 * page_array_size;
+}
+
+int ttm_buffer_object_create(struct ttm_bo_device *bdev,
+			     unsigned long size,
+			     enum ttm_bo_type type,
+			     uint32_t flags,
+			     uint32_t page_alignment,
+			     unsigned long buffer_start,
+			     bool interruptible,
+			     struct file *persistant_swap_storage,
+			     struct ttm_buffer_object **p_bo)
+{
+	struct ttm_buffer_object *bo;
+	int ret;
+	struct ttm_mem_global *mem_glob = bdev->mem_glob;
+
+	size_t acc_size =
+	    ttm_bo_size(bdev, (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+	ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+
+	if (unlikely(bo == NULL)) {
+		ttm_mem_global_free(mem_glob, acc_size, false);
+		return -ENOMEM;
+	}
+
+	ret = ttm_buffer_object_init(bdev, bo, size, type, flags,
+				     page_alignment, buffer_start,
+				     interruptible,
+				     persistant_swap_storage, acc_size, NULL);
+	if (likely(ret == 0))
+		*p_bo = bo;
+
+	return ret;
+}
+
+static int ttm_bo_leave_list(struct ttm_buffer_object *bo,
+			     uint32_t mem_type, bool allow_errors)
+{
+	int ret;
+
+	spin_lock(&bo->lock);
+	ret = ttm_bo_wait(bo, false, false, false);
+	spin_unlock(&bo->lock);
+
+	if (ret && allow_errors)
+		goto out;
+
+	if (bo->mem.mem_type == mem_type)
+		ret = ttm_bo_evict(bo, mem_type, false, false);
+
+	if (ret) {
+		if (allow_errors) {
+			goto out;
+		} else {
+			ret = 0;
+			printk(KERN_ERR TTM_PFX "Cleanup eviction failed\n");
+		}
+	}
+
+out:
+	return ret;
+}
+
+static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
+				   struct list_head *head,
+				   unsigned mem_type, bool allow_errors)
+{
+	struct ttm_buffer_object *entry;
+	int ret;
+	int put_count;
+
+	/*
+	 * Can't use standard list traversal since we're unlocking.
+	 */
+
+	spin_lock(&bdev->lru_lock);
+
+	while (!list_empty(head)) {
+		entry = list_first_entry(head, struct ttm_buffer_object, lru);
+		kref_get(&entry->list_kref);
+		ret = ttm_bo_reserve_locked(entry, false, false, false, 0);
+		put_count = ttm_bo_del_from_lru(entry);
+		spin_unlock(&bdev->lru_lock);
+		while (put_count--)
+			kref_put(&entry->list_kref, ttm_bo_ref_bug);
+		BUG_ON(ret);
+		ret = ttm_bo_leave_list(entry, mem_type, allow_errors);
+		ttm_bo_unreserve(entry);
+		kref_put(&entry->list_kref, ttm_bo_release_list);
+		spin_lock(&bdev->lru_lock);
+	}
+
+	spin_unlock(&bdev->lru_lock);
+
+	return 0;
+}
+
+int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type)
+{
+	struct ttm_mem_type_manager *man;
+	int ret = -EINVAL;
+
+	if (mem_type >= TTM_NUM_MEM_TYPES) {
+		printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", mem_type);
+		return ret;
+	}
+	man = &bdev->man[mem_type];
+
+	if (!man->has_type) {
+		printk(KERN_ERR TTM_PFX "Trying to take down uninitialized "
+		       "memory manager type %u\n", mem_type);
+		return ret;
+	}
+
+	man->use_type = false;
+	man->has_type = false;
+
+	ret = 0;
+	if (mem_type > 0) {
+		ttm_bo_force_list_clean(bdev, &man->lru, mem_type, false);
+
+		spin_lock(&bdev->lru_lock);
+		if (drm_mm_clean(&man->manager))
+			drm_mm_takedown(&man->manager);
+		else
+			ret = -EBUSY;
+
+		spin_unlock(&bdev->lru_lock);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(ttm_bo_clean_mm);
+
+int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
+
+	if (mem_type == 0 || mem_type >= TTM_NUM_MEM_TYPES) {
+		printk(KERN_ERR TTM_PFX
+		       "Illegal memory manager memory type %u.\n",
+		       mem_type);
+		return -EINVAL;
+	}
+
+	if (!man->has_type) {
+		printk(KERN_ERR TTM_PFX
+		       "Memory type %u has not been initialized.\n",
+		       mem_type);
+		return 0;
+	}
+
+	return ttm_bo_force_list_clean(bdev, &man->lru, mem_type, true);
+}
+EXPORT_SYMBOL(ttm_bo_evict_mm);
+
+int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,
+		   unsigned long p_offset, unsigned long p_size)
+{
+	int ret = -EINVAL;
+	struct ttm_mem_type_manager *man;
+
+	if (type >= TTM_NUM_MEM_TYPES) {
+		printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", type);
+		return ret;
+	}
+
+	man = &bdev->man[type];
+	if (man->has_type) {
+		printk(KERN_ERR TTM_PFX
+		       "Memory manager already initialized for type %d\n",
+		       type);
+		return ret;
+	}
+
+	ret = bdev->driver->init_mem_type(bdev, type, man);
+	if (ret)
+		return ret;
+
+	ret = 0;
+	if (type != TTM_PL_SYSTEM) {
+		if (!p_size) {
+			printk(KERN_ERR TTM_PFX
+			       "Zero size memory manager type %d\n",
+			       type);
+			return ret;
+		}
+		ret = drm_mm_init(&man->manager, p_offset, p_size);
+		if (ret)
+			return ret;
+	}
+	man->has_type = true;
+	man->use_type = true;
+	man->size = p_size;
+
+	INIT_LIST_HEAD(&man->lru);
+
+	return 0;
+}
+EXPORT_SYMBOL(ttm_bo_init_mm);
+
+int ttm_bo_device_release(struct ttm_bo_device *bdev)
+{
+	int ret = 0;
+	unsigned i = TTM_NUM_MEM_TYPES;
+	struct ttm_mem_type_manager *man;
+
+	while (i--) {
+		man = &bdev->man[i];
+		if (man->has_type) {
+			man->use_type = false;
+			if ((i != TTM_PL_SYSTEM) && ttm_bo_clean_mm(bdev, i)) {
+				ret = -EBUSY;
+				printk(KERN_ERR TTM_PFX
+				       "DRM memory manager type %d "
+				       "is not clean.\n", i);
+			}
+			man->has_type = false;
+		}
+	}
+
+	if (!cancel_delayed_work(&bdev->wq))
+		flush_scheduled_work();
+
+	while (ttm_bo_delayed_delete(bdev, true))
+		;
+
+	spin_lock(&bdev->lru_lock);
+	if (list_empty(&bdev->ddestroy))
+		TTM_DEBUG("Delayed destroy list was clean\n");
+
+	if (list_empty(&bdev->man[0].lru))
+		TTM_DEBUG("Swap list was clean\n");
+	spin_unlock(&bdev->lru_lock);
+
+	ttm_mem_unregister_shrink(bdev->mem_glob, &bdev->shrink);
+	BUG_ON(!drm_mm_clean(&bdev->addr_space_mm));
+	write_lock(&bdev->vm_lock);
+	drm_mm_takedown(&bdev->addr_space_mm);
+	write_unlock(&bdev->vm_lock);
+
+	__free_page(bdev->dummy_read_page);
+	return ret;
+}
+EXPORT_SYMBOL(ttm_bo_device_release);
+
+/*
+ * This function is intended to be called on drm driver load.
+ * If you decide to call it from firstopen, you must protect the call
+ * from a potentially racing ttm_bo_driver_finish in lastclose.
+ * (This may happen on X server restart).
+ */
+
+int ttm_bo_device_init(struct ttm_bo_device *bdev,
+		       struct ttm_mem_global *mem_glob,
+		       struct ttm_bo_driver *driver, uint64_t file_page_offset,
+		       bool need_dma32)
+{
+	int ret = -EINVAL;
+
+	bdev->dummy_read_page = NULL;
+	rwlock_init(&bdev->vm_lock);
+	spin_lock_init(&bdev->lru_lock);
+
+	bdev->driver = driver;
+	bdev->mem_glob = mem_glob;
+
+	memset(bdev->man, 0, sizeof(bdev->man));
+
+	bdev->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32);
+	if (unlikely(bdev->dummy_read_page == NULL)) {
+		ret = -ENOMEM;
+		goto out_err0;
+	}
+
+	/*
+	 * Initialize the system memory buffer type.
+	 * Other types need to be driver / IOCTL initialized.
+	 */
+	ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0, 0);
+	if (unlikely(ret != 0))
+		goto out_err1;
+
+	bdev->addr_space_rb = RB_ROOT;
+	ret = drm_mm_init(&bdev->addr_space_mm, file_page_offset, 0x10000000);
+	if (unlikely(ret != 0))
+		goto out_err2;
+
+	INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue);
+	bdev->nice_mode = true;
+	INIT_LIST_HEAD(&bdev->ddestroy);
+	INIT_LIST_HEAD(&bdev->swap_lru);
+	bdev->dev_mapping = NULL;
+	bdev->need_dma32 = need_dma32;
+	ttm_mem_init_shrink(&bdev->shrink, ttm_bo_swapout);
+	ret = ttm_mem_register_shrink(mem_glob, &bdev->shrink);
+	if (unlikely(ret != 0)) {
+		printk(KERN_ERR TTM_PFX
+		       "Could not register buffer object swapout.\n");
+		goto out_err2;
+	}
+
+	bdev->ttm_bo_extra_size =
+		ttm_round_pot(sizeof(struct ttm_tt)) +
+		ttm_round_pot(sizeof(struct ttm_backend));
+
+	bdev->ttm_bo_size = bdev->ttm_bo_extra_size +
+		ttm_round_pot(sizeof(struct ttm_buffer_object));
+
+	return 0;
+out_err2:
+	ttm_bo_clean_mm(bdev, 0);
+out_err1:
+	__free_page(bdev->dummy_read_page);
+out_err0:
+	return ret;
+}
+EXPORT_SYMBOL(ttm_bo_device_init);
+
+/*
+ * buffer object vm functions.
+ */
+
+bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+
+	if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
+		if (mem->mem_type == TTM_PL_SYSTEM)
+			return false;
+
+		if (man->flags & TTM_MEMTYPE_FLAG_CMA)
+			return false;
+
+		if (mem->placement & TTM_PL_FLAG_CACHED)
+			return false;
+	}
+	return true;
+}
+
+int ttm_bo_pci_offset(struct ttm_bo_device *bdev,
+		      struct ttm_mem_reg *mem,
+		      unsigned long *bus_base,
+		      unsigned long *bus_offset, unsigned long *bus_size)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+
+	*bus_size = 0;
+	if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+		return -EINVAL;
+
+	if (ttm_mem_reg_is_pci(bdev, mem)) {
+		*bus_offset = mem->mm_node->start << PAGE_SHIFT;
+		*bus_size = mem->num_pages << PAGE_SHIFT;
+		*bus_base = man->io_offset;
+	}
+
+	return 0;
+}
+
+void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	loff_t offset = (loff_t) bo->addr_space_offset;
+	loff_t holelen = ((loff_t) bo->mem.num_pages) << PAGE_SHIFT;
+
+	if (!bdev->dev_mapping)
+		return;
+
+	unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1);
+}
+EXPORT_SYMBOL(ttm_bo_unmap_virtual);
+
+static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct rb_node **cur = &bdev->addr_space_rb.rb_node;
+	struct rb_node *parent = NULL;
+	struct ttm_buffer_object *cur_bo;
+	unsigned long offset = bo->vm_node->start;
+	unsigned long cur_offset;
+
+	while (*cur) {
+		parent = *cur;
+		cur_bo = rb_entry(parent, struct ttm_buffer_object, vm_rb);
+		cur_offset = cur_bo->vm_node->start;
+		if (offset < cur_offset)
+			cur = &parent->rb_left;
+		else if (offset > cur_offset)
+			cur = &parent->rb_right;
+		else
+			BUG();
+	}
+
+	rb_link_node(&bo->vm_rb, parent, cur);
+	rb_insert_color(&bo->vm_rb, &bdev->addr_space_rb);
+}
+
+/**
+ * ttm_bo_setup_vm:
+ *
+ * @bo: the buffer to allocate address space for
+ *
+ * Allocate address space in the drm device so that applications
+ * can mmap the buffer and access the contents. This only
+ * applies to ttm_bo_type_device objects as others are not
+ * placed in the drm device address space.
+ */
+
+static int ttm_bo_setup_vm(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	int ret;
+
+retry_pre_get:
+	ret = drm_mm_pre_get(&bdev->addr_space_mm);
+	if (unlikely(ret != 0))
+		return ret;
+
+	write_lock(&bdev->vm_lock);
+	bo->vm_node = drm_mm_search_free(&bdev->addr_space_mm,
+					 bo->mem.num_pages, 0, 0);
+
+	if (unlikely(bo->vm_node == NULL)) {
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	bo->vm_node = drm_mm_get_block_atomic(bo->vm_node,
+					      bo->mem.num_pages, 0);
+
+	if (unlikely(bo->vm_node == NULL)) {
+		write_unlock(&bdev->vm_lock);
+		goto retry_pre_get;
+	}
+
+	ttm_bo_vm_insert_rb(bo);
+	write_unlock(&bdev->vm_lock);
+	bo->addr_space_offset = ((uint64_t) bo->vm_node->start) << PAGE_SHIFT;
+
+	return 0;
+out_unlock:
+	write_unlock(&bdev->vm_lock);
+	return ret;
+}
+
+int ttm_bo_wait(struct ttm_buffer_object *bo,
+		bool lazy, bool interruptible, bool no_wait)
+{
+	struct ttm_bo_driver *driver = bo->bdev->driver;
+	void *sync_obj;
+	void *sync_obj_arg;
+	int ret = 0;
+
+	if (likely(bo->sync_obj == NULL))
+		return 0;
+
+	while (bo->sync_obj) {
+
+		if (driver->sync_obj_signaled(bo->sync_obj, bo->sync_obj_arg)) {
+			void *tmp_obj = bo->sync_obj;
+			bo->sync_obj = NULL;
+			clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
+			spin_unlock(&bo->lock);
+			driver->sync_obj_unref(&tmp_obj);
+			spin_lock(&bo->lock);
+			continue;
+		}
+
+		if (no_wait)
+			return -EBUSY;
+
+		sync_obj = driver->sync_obj_ref(bo->sync_obj);
+		sync_obj_arg = bo->sync_obj_arg;
+		spin_unlock(&bo->lock);
+		ret = driver->sync_obj_wait(sync_obj, sync_obj_arg,
+					    lazy, interruptible);
+		if (unlikely(ret != 0)) {
+			driver->sync_obj_unref(&sync_obj);
+			spin_lock(&bo->lock);
+			return ret;
+		}
+		spin_lock(&bo->lock);
+		if (likely(bo->sync_obj == sync_obj &&
+			   bo->sync_obj_arg == sync_obj_arg)) {
+			void *tmp_obj = bo->sync_obj;
+			bo->sync_obj = NULL;
+			clear_bit(TTM_BO_PRIV_FLAG_MOVING,
+				  &bo->priv_flags);
+			spin_unlock(&bo->lock);
+			driver->sync_obj_unref(&sync_obj);
+			driver->sync_obj_unref(&tmp_obj);
+			spin_lock(&bo->lock);
+		} else {
+			spin_unlock(&bo->lock);
+			driver->sync_obj_unref(&sync_obj);
+			spin_lock(&bo->lock);
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ttm_bo_wait);
+
+void ttm_bo_unblock_reservation(struct ttm_buffer_object *bo)
+{
+	atomic_set(&bo->reserved, 0);
+	wake_up_all(&bo->event_queue);
+}
+
+int ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible,
+			     bool no_wait)
+{
+	int ret;
+
+	while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
+		if (no_wait)
+			return -EBUSY;
+		else if (interruptible) {
+			ret = wait_event_interruptible
+			    (bo->event_queue, atomic_read(&bo->reserved) == 0);
+			if (unlikely(ret != 0))
+				return -ERESTART;
+		} else {
+			wait_event(bo->event_queue,
+				   atomic_read(&bo->reserved) == 0);
+		}
+	}
+	return 0;
+}
+
+int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait)
+{
+	int ret = 0;
+
+	/*
+	 * Using ttm_bo_reserve instead of ttm_bo_block_reservation
+	 * makes sure the lru lists are updated.
+	 */
+
+	ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
+	if (unlikely(ret != 0))
+		return ret;
+	spin_lock(&bo->lock);
+	ret = ttm_bo_wait(bo, false, true, no_wait);
+	spin_unlock(&bo->lock);
+	if (likely(ret == 0))
+		atomic_inc(&bo->cpu_writers);
+	ttm_bo_unreserve(bo);
+	return ret;
+}
+
+void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo)
+{
+	if (atomic_dec_and_test(&bo->cpu_writers))
+		wake_up_all(&bo->event_queue);
+}
+
+/**
+ * A buffer object shrink method that tries to swap out the first
+ * buffer object on the bo_global::swap_lru list.
+ */
+
+static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
+{
+	struct ttm_bo_device *bdev =
+	    container_of(shrink, struct ttm_bo_device, shrink);
+	struct ttm_buffer_object *bo;
+	int ret = -EBUSY;
+	int put_count;
+	uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM);
+
+	spin_lock(&bdev->lru_lock);
+	while (ret == -EBUSY) {
+		if (unlikely(list_empty(&bdev->swap_lru))) {
+			spin_unlock(&bdev->lru_lock);
+			return -EBUSY;
+		}
+
+		bo = list_first_entry(&bdev->swap_lru,
+				      struct ttm_buffer_object, swap);
+		kref_get(&bo->list_kref);
+
+		/**
+		 * Reserve buffer. Since we unlock while sleeping, we need
+		 * to re-check that nobody removed us from the swap-list while
+		 * we slept.
+		 */
+
+		ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
+		if (unlikely(ret == -EBUSY)) {
+			spin_unlock(&bdev->lru_lock);
+			ttm_bo_wait_unreserved(bo, false);
+			kref_put(&bo->list_kref, ttm_bo_release_list);
+			spin_lock(&bdev->lru_lock);
+		}
+	}
+
+	BUG_ON(ret != 0);
+	put_count = ttm_bo_del_from_lru(bo);
+	spin_unlock(&bdev->lru_lock);
+
+	while (put_count--)
+		kref_put(&bo->list_kref, ttm_bo_ref_bug);
+
+	/**
+	 * Wait for GPU, then move to system cached.
+	 */
+
+	spin_lock(&bo->lock);
+	ret = ttm_bo_wait(bo, false, false, false);
+	spin_unlock(&bo->lock);
+
+	if (unlikely(ret != 0))
+		goto out;
+
+	if ((bo->mem.placement & swap_placement) != swap_placement) {
+		struct ttm_mem_reg evict_mem;
+
+		evict_mem = bo->mem;
+		evict_mem.mm_node = NULL;
+		evict_mem.placement = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED;
+		evict_mem.mem_type = TTM_PL_SYSTEM;
+
+		ret = ttm_bo_handle_move_mem(bo, &evict_mem, true,
+					     false, false);
+		if (unlikely(ret != 0))
+			goto out;
+	}
+
+	ttm_bo_unmap_virtual(bo);
+
+	/**
+	 * Swap out. Buffer will be swapped in again as soon as
+	 * anyone tries to access a ttm page.
+	 */
+
+	ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage);
+out:
+
+	/**
+	 *
+	 * Unreserve without putting on LRU to avoid swapping out an
+	 * already swapped buffer.
+	 */
+
+	atomic_set(&bo->reserved, 0);
+	wake_up_all(&bo->event_queue);
+	kref_put(&bo->list_kref, ttm_bo_release_list);
+	return ret;
+}
+
+void ttm_bo_swapout_all(struct ttm_bo_device *bdev)
+{
+	while (ttm_bo_swapout(&bdev->shrink) == 0)
+		;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,603 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+#include <linux/io.h>
+#include <linux/highmem.h>
+#include <linux/wait.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+
+void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
+{
+	struct ttm_mem_reg *old_mem = &bo->mem;
+
+	if (old_mem->mm_node) {
+		spin_lock(&bo->bdev->lru_lock);
+		drm_mm_put_block(old_mem->mm_node);
+		spin_unlock(&bo->bdev->lru_lock);
+	}
+	old_mem->mm_node = NULL;
+}
+
+int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
+		    bool evict, bool no_wait, struct ttm_mem_reg *new_mem)
+{
+	struct ttm_tt *ttm = bo->ttm;
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	uint32_t save_flags = old_mem->placement;
+	int ret;
+
+	if (old_mem->mem_type != TTM_PL_SYSTEM) {
+		ttm_tt_unbind(ttm);
+		ttm_bo_free_old_node(bo);
+		ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM,
+				TTM_PL_MASK_MEM);
+		old_mem->mem_type = TTM_PL_SYSTEM;
+		save_flags = old_mem->placement;
+	}
+
+	ret = ttm_tt_set_placement_caching(ttm, new_mem->placement);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (new_mem->mem_type != TTM_PL_SYSTEM) {
+		ret = ttm_tt_bind(ttm, new_mem);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	*old_mem = *new_mem;
+	new_mem->mm_node = NULL;
+	ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
+	return 0;
+}
+EXPORT_SYMBOL(ttm_bo_move_ttm);
+
+int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
+			void **virtual)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+	unsigned long bus_offset;
+	unsigned long bus_size;
+	unsigned long bus_base;
+	int ret;
+	void *addr;
+
+	*virtual = NULL;
+	ret = ttm_bo_pci_offset(bdev, mem, &bus_base, &bus_offset, &bus_size);
+	if (ret || bus_size == 0)
+		return ret;
+
+	if (!(man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP))
+		addr = (void *)(((u8 *) man->io_addr) + bus_offset);
+	else {
+		if (mem->placement & TTM_PL_FLAG_WC)
+			addr = ioremap_wc(bus_base + bus_offset, bus_size);
+		else
+			addr = ioremap_nocache(bus_base + bus_offset, bus_size);
+		if (!addr)
+			return -ENOMEM;
+	}
+	*virtual = addr;
+	return 0;
+}
+
+void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
+			 void *virtual)
+{
+	struct ttm_mem_type_manager *man;
+
+	man = &bdev->man[mem->mem_type];
+
+	if (virtual && (man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP))
+		iounmap(virtual);
+}
+
+static int ttm_copy_io_page(void *dst, void *src, unsigned long page)
+{
+	uint32_t *dstP =
+	    (uint32_t *) ((unsigned long)dst + (page << PAGE_SHIFT));
+	uint32_t *srcP =
+	    (uint32_t *) ((unsigned long)src + (page << PAGE_SHIFT));
+
+	int i;
+	for (i = 0; i < PAGE_SIZE / sizeof(uint32_t); ++i)
+		iowrite32(ioread32(srcP++), dstP++);
+	return 0;
+}
+
+static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
+				unsigned long page,
+				pgprot_t prot)
+{
+	struct page *d = ttm_tt_get_page(ttm, page);
+	void *dst;
+
+	if (!d)
+		return -ENOMEM;
+
+	src = (void *)((unsigned long)src + (page << PAGE_SHIFT));
+
+#ifdef CONFIG_X86
+	dst = kmap_atomic_prot(d, KM_USER0, prot);
+#else
+	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+		dst = vmap(&d, 1, 0, prot);
+	else
+		dst = kmap(d);
+#endif
+	if (!dst)
+		return -ENOMEM;
+
+	memcpy_fromio(dst, src, PAGE_SIZE);
+
+#ifdef CONFIG_X86
+	kunmap_atomic(dst, KM_USER0);
+#else
+	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+		vunmap(dst);
+	else
+		kunmap(d);
+#endif
+
+	return 0;
+}
+
+static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
+				unsigned long page,
+				pgprot_t prot)
+{
+	struct page *s = ttm_tt_get_page(ttm, page);
+	void *src;
+
+	if (!s)
+		return -ENOMEM;
+
+	dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
+#ifdef CONFIG_X86
+	src = kmap_atomic_prot(s, KM_USER0, prot);
+#else
+	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+		src = vmap(&s, 1, 0, prot);
+	else
+		src = kmap(s);
+#endif
+	if (!src)
+		return -ENOMEM;
+
+	memcpy_toio(dst, src, PAGE_SIZE);
+
+#ifdef CONFIG_X86
+	kunmap_atomic(src, KM_USER0);
+#else
+	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+		vunmap(src);
+	else
+		kunmap(s);
+#endif
+
+	return 0;
+}
+
+int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
+		       bool evict, bool no_wait, struct ttm_mem_reg *new_mem)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
+	struct ttm_tt *ttm = bo->ttm;
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	struct ttm_mem_reg old_copy = *old_mem;
+	void *old_iomap;
+	void *new_iomap;
+	int ret;
+	uint32_t save_flags = old_mem->placement;
+	unsigned long i;
+	unsigned long page;
+	unsigned long add = 0;
+	int dir;
+
+	ret = ttm_mem_reg_ioremap(bdev, old_mem, &old_iomap);
+	if (ret)
+		return ret;
+	ret = ttm_mem_reg_ioremap(bdev, new_mem, &new_iomap);
+	if (ret)
+		goto out;
+
+	if (old_iomap == NULL && new_iomap == NULL)
+		goto out2;
+	if (old_iomap == NULL && ttm == NULL)
+		goto out2;
+
+	add = 0;
+	dir = 1;
+
+	if ((old_mem->mem_type == new_mem->mem_type) &&
+	    (new_mem->mm_node->start <
+	     old_mem->mm_node->start + old_mem->mm_node->size)) {
+		dir = -1;
+		add = new_mem->num_pages - 1;
+	}
+
+	for (i = 0; i < new_mem->num_pages; ++i) {
+		page = i * dir + add;
+		if (old_iomap == NULL) {
+			pgprot_t prot = ttm_io_prot(old_mem->placement,
+						    PAGE_KERNEL);
+			ret = ttm_copy_ttm_io_page(ttm, new_iomap, page,
+						   prot);
+		} else if (new_iomap == NULL) {
+			pgprot_t prot = ttm_io_prot(new_mem->placement,
+						    PAGE_KERNEL);
+			ret = ttm_copy_io_ttm_page(ttm, old_iomap, page,
+						   prot);
+		} else
+			ret = ttm_copy_io_page(new_iomap, old_iomap, page);
+		if (ret)
+			goto out1;
+	}
+	mb();
+out2:
+	ttm_bo_free_old_node(bo);
+
+	*old_mem = *new_mem;
+	new_mem->mm_node = NULL;
+	ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
+
+	if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && (ttm != NULL)) {
+		ttm_tt_unbind(ttm);
+		ttm_tt_destroy(ttm);
+		bo->ttm = NULL;
+	}
+
+out1:
+	ttm_mem_reg_iounmap(bdev, new_mem, new_iomap);
+out:
+	ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap);
+	return ret;
+}
+EXPORT_SYMBOL(ttm_bo_move_memcpy);
+
+static void ttm_transfered_destroy(struct ttm_buffer_object *bo)
+{
+	kfree(bo);
+}
+
+/**
+ * ttm_buffer_object_transfer
+ *
+ * @bo: A pointer to a struct ttm_buffer_object.
+ * @new_obj: A pointer to a pointer to a newly created ttm_buffer_object,
+ * holding the data of @bo with the old placement.
+ *
+ * This is a utility function that may be called after an accelerated move
+ * has been scheduled. A new buffer object is created as a placeholder for
+ * the old data while it's being copied. When that buffer object is idle,
+ * it can be destroyed, releasing the space of the old placement.
+ * Returns:
+ * !0: Failure.
+ */
+
+static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
+				      struct ttm_buffer_object **new_obj)
+{
+	struct ttm_buffer_object *fbo;
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_bo_driver *driver = bdev->driver;
+
+	fbo = kzalloc(sizeof(*fbo), GFP_KERNEL);
+	if (!fbo)
+		return -ENOMEM;
+
+	*fbo = *bo;
+
+	/**
+	 * Fix up members that we shouldn't copy directly:
+	 * TODO: Explicit member copy would probably be better here.
+	 */
+
+	spin_lock_init(&fbo->lock);
+	init_waitqueue_head(&fbo->event_queue);
+	INIT_LIST_HEAD(&fbo->ddestroy);
+	INIT_LIST_HEAD(&fbo->lru);
+	INIT_LIST_HEAD(&fbo->swap);
+	fbo->vm_node = NULL;
+
+	fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
+	if (fbo->mem.mm_node)
+		fbo->mem.mm_node->private = (void *)fbo;
+	kref_init(&fbo->list_kref);
+	kref_init(&fbo->kref);
+	fbo->destroy = &ttm_transfered_destroy;
+
+	*new_obj = fbo;
+	return 0;
+}
+
+pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp)
+{
+#if defined(__i386__) || defined(__x86_64__)
+	if (caching_flags & TTM_PL_FLAG_WC)
+		tmp = pgprot_writecombine(tmp);
+	else if (boot_cpu_data.x86 > 3)
+		tmp = pgprot_noncached(tmp);
+
+#elif defined(__powerpc__)
+	if (!(caching_flags & TTM_PL_FLAG_CACHED)) {
+		pgprot_val(tmp) |= _PAGE_NO_CACHE;
+		if (caching_flags & TTM_PL_FLAG_UNCACHED)
+			pgprot_val(tmp) |= _PAGE_GUARDED;
+	}
+#endif
+#if defined(__ia64__)
+	if (caching_flags & TTM_PL_FLAG_WC)
+		tmp = pgprot_writecombine(tmp);
+	else
+		tmp = pgprot_noncached(tmp);
+#endif
+#if defined(__sparc__)
+	if (!(caching_flags & TTM_PL_FLAG_CACHED))
+		tmp = pgprot_noncached(tmp);
+#endif
+	return tmp;
+}
+
+static int ttm_bo_ioremap(struct ttm_buffer_object *bo,
+			  unsigned long bus_base,
+			  unsigned long bus_offset,
+			  unsigned long bus_size,
+			  struct ttm_bo_kmap_obj *map)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_reg *mem = &bo->mem;
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+
+	if (!(man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP)) {
+		map->bo_kmap_type = ttm_bo_map_premapped;
+		map->virtual = (void *)(((u8 *) man->io_addr) + bus_offset);
+	} else {
+		map->bo_kmap_type = ttm_bo_map_iomap;
+		if (mem->placement & TTM_PL_FLAG_WC)
+			map->virtual = ioremap_wc(bus_base + bus_offset,
+						  bus_size);
+		else
+			map->virtual = ioremap_nocache(bus_base + bus_offset,
+						       bus_size);
+	}
+	return (!map->virtual) ? -ENOMEM : 0;
+}
+
+static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
+			   unsigned long start_page,
+			   unsigned long num_pages,
+			   struct ttm_bo_kmap_obj *map)
+{
+	struct ttm_mem_reg *mem = &bo->mem; pgprot_t prot;
+	struct ttm_tt *ttm = bo->ttm;
+	struct page *d;
+	int i;
+
+	BUG_ON(!ttm);
+	if (num_pages == 1 && (mem->placement & TTM_PL_FLAG_CACHED)) {
+		/*
+		 * We're mapping a single page, and the desired
+		 * page protection is consistent with the bo.
+		 */
+
+		map->bo_kmap_type = ttm_bo_map_kmap;
+		map->page = ttm_tt_get_page(ttm, start_page);
+		map->virtual = kmap(map->page);
+	} else {
+	    /*
+	     * Populate the part we're mapping;
+	     */
+		for (i = start_page; i < start_page + num_pages; ++i) {
+			d = ttm_tt_get_page(ttm, i);
+			if (!d)
+				return -ENOMEM;
+		}
+
+		/*
+		 * We need to use vmap to get the desired page protection
+		 * or to make the buffer object look contigous.
+		 */
+		prot = (mem->placement & TTM_PL_FLAG_CACHED) ?
+			PAGE_KERNEL :
+			ttm_io_prot(mem->placement, PAGE_KERNEL);
+		map->bo_kmap_type = ttm_bo_map_vmap;
+		map->virtual = vmap(ttm->pages + start_page, num_pages,
+				    0, prot);
+	}
+	return (!map->virtual) ? -ENOMEM : 0;
+}
+
+int ttm_bo_kmap(struct ttm_buffer_object *bo,
+		unsigned long start_page, unsigned long num_pages,
+		struct ttm_bo_kmap_obj *map)
+{
+	int ret;
+	unsigned long bus_base;
+	unsigned long bus_offset;
+	unsigned long bus_size;
+
+	BUG_ON(!list_empty(&bo->swap));
+	map->virtual = NULL;
+	if (num_pages > bo->num_pages)
+		return -EINVAL;
+	if (start_page > bo->num_pages)
+		return -EINVAL;
+#if 0
+	if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC))
+		return -EPERM;
+#endif
+	ret = ttm_bo_pci_offset(bo->bdev, &bo->mem, &bus_base,
+				&bus_offset, &bus_size);
+	if (ret)
+		return ret;
+	if (bus_size == 0) {
+		return ttm_bo_kmap_ttm(bo, start_page, num_pages, map);
+	} else {
+		bus_offset += start_page << PAGE_SHIFT;
+		bus_size = num_pages << PAGE_SHIFT;
+		return ttm_bo_ioremap(bo, bus_base, bus_offset, bus_size, map);
+	}
+}
+EXPORT_SYMBOL(ttm_bo_kmap);
+
+void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map)
+{
+	if (!map->virtual)
+		return;
+	switch (map->bo_kmap_type) {
+	case ttm_bo_map_iomap:
+		iounmap(map->virtual);
+		break;
+	case ttm_bo_map_vmap:
+		vunmap(map->virtual);
+		break;
+	case ttm_bo_map_kmap:
+		kunmap(map->page);
+		break;
+	case ttm_bo_map_premapped:
+		break;
+	default:
+		BUG();
+	}
+	map->virtual = NULL;
+	map->page = NULL;
+}
+EXPORT_SYMBOL(ttm_bo_kunmap);
+
+int ttm_bo_pfn_prot(struct ttm_buffer_object *bo,
+		    unsigned long dst_offset,
+		    unsigned long *pfn, pgprot_t *prot)
+{
+	struct ttm_mem_reg *mem = &bo->mem;
+	struct ttm_bo_device *bdev = bo->bdev;
+	unsigned long bus_offset;
+	unsigned long bus_size;
+	unsigned long bus_base;
+	int ret;
+	ret = ttm_bo_pci_offset(bdev, mem, &bus_base, &bus_offset,
+			&bus_size);
+	if (ret)
+		return -EINVAL;
+	if (bus_size != 0)
+		*pfn = (bus_base + bus_offset + dst_offset) >> PAGE_SHIFT;
+	else
+		if (!bo->ttm)
+			return -EINVAL;
+		else
+			*pfn = page_to_pfn(ttm_tt_get_page(bo->ttm,
+							   dst_offset >>
+							   PAGE_SHIFT));
+	*prot = (mem->placement & TTM_PL_FLAG_CACHED) ?
+		PAGE_KERNEL : ttm_io_prot(mem->placement, PAGE_KERNEL);
+
+	return 0;
+}
+
+int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
+			      void *sync_obj,
+			      void *sync_obj_arg,
+			      bool evict, bool no_wait,
+			      struct ttm_mem_reg *new_mem)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_bo_driver *driver = bdev->driver;
+	struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	int ret;
+	uint32_t save_flags = old_mem->placement;
+	struct ttm_buffer_object *ghost_obj;
+	void *tmp_obj = NULL;
+
+	spin_lock(&bo->lock);
+	if (bo->sync_obj) {
+		tmp_obj = bo->sync_obj;
+		bo->sync_obj = NULL;
+	}
+	bo->sync_obj = driver->sync_obj_ref(sync_obj);
+	bo->sync_obj_arg = sync_obj_arg;
+	if (evict) {
+		ret = ttm_bo_wait(bo, false, false, false);
+		spin_unlock(&bo->lock);
+		if (tmp_obj)
+			driver->sync_obj_unref(&tmp_obj);
+		if (ret)
+			return ret;
+
+		ttm_bo_free_old_node(bo);
+		if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
+		    (bo->ttm != NULL)) {
+			ttm_tt_unbind(bo->ttm);
+			ttm_tt_destroy(bo->ttm);
+			bo->ttm = NULL;
+		}
+	} else {
+		/**
+		 * This should help pipeline ordinary buffer moves.
+		 *
+		 * Hang old buffer memory on a new buffer object,
+		 * and leave it to be released when the GPU
+		 * operation has completed.
+		 */
+
+		set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
+		spin_unlock(&bo->lock);
+		if (tmp_obj)
+			driver->sync_obj_unref(&tmp_obj);
+
+		ret = ttm_buffer_object_transfer(bo, &ghost_obj);
+		if (ret)
+			return ret;
+
+		/**
+		 * If we're not moving to fixed memory, the TTM object
+		 * needs to stay alive. Otherwhise hang it on the ghost
+		 * bo to be unbound and destroyed.
+		 */
+
+		if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED))
+			ghost_obj->ttm = NULL;
+		else
+			bo->ttm = NULL;
+
+		ttm_bo_unreserve(ghost_obj);
+		ttm_bo_unref(&ghost_obj);
+	}
+
+	*old_mem = *new_mem;
+	new_mem->mm_node = NULL;
+	ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
+	return 0;
+}
+EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,456 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include <ttm/ttm_module.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+#define TTM_BO_VM_NUM_PREFAULT 16
+
+static struct ttm_buffer_object *ttm_bo_vm_lookup_rb(struct ttm_bo_device *bdev,
+						     unsigned long page_start,
+						     unsigned long num_pages)
+{
+	struct rb_node *cur = bdev->addr_space_rb.rb_node;
+	unsigned long cur_offset;
+	struct ttm_buffer_object *bo;
+	struct ttm_buffer_object *best_bo = NULL;
+
+	while (likely(cur != NULL)) {
+		bo = rb_entry(cur, struct ttm_buffer_object, vm_rb);
+		cur_offset = bo->vm_node->start;
+		if (page_start >= cur_offset) {
+			cur = cur->rb_right;
+			best_bo = bo;
+			if (page_start == cur_offset)
+				break;
+		} else
+			cur = cur->rb_left;
+	}
+
+	if (unlikely(best_bo == NULL))
+		return NULL;
+
+	if (unlikely((best_bo->vm_node->start + best_bo->num_pages) <
+		     (page_start + num_pages)))
+		return NULL;
+
+	return best_bo;
+}
+
+static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
+	    vma->vm_private_data;
+	struct ttm_bo_device *bdev = bo->bdev;
+	unsigned long bus_base;
+	unsigned long bus_offset;
+	unsigned long bus_size;
+	unsigned long page_offset;
+	unsigned long page_last;
+	unsigned long pfn;
+	struct ttm_tt *ttm = NULL;
+	struct page *page;
+	int ret;
+	int i;
+	bool is_iomem;
+	unsigned long address = (unsigned long)vmf->virtual_address;
+	int retval = VM_FAULT_NOPAGE;
+
+	/*
+	 * Work around locking order reversal in fault / nopfn
+	 * between mmap_sem and bo_reserve: Perform a trylock operation
+	 * for reserve, and if it fails, retry the fault after scheduling.
+	 */
+
+	ret = ttm_bo_reserve(bo, true, true, false, 0);
+	if (unlikely(ret != 0)) {
+		if (ret == -EBUSY)
+			set_need_resched();
+		return VM_FAULT_NOPAGE;
+	}
+
+	if (bdev->driver->fault_reserve_notify)
+		bdev->driver->fault_reserve_notify(bo);
+
+	/*
+	 * Wait for buffer data in transit, due to a pipelined
+	 * move.
+	 */
+
+	spin_lock(&bo->lock);
+	if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) {
+		ret = ttm_bo_wait(bo, false, true, false);
+		spin_unlock(&bo->lock);
+		if (unlikely(ret != 0)) {
+			retval = (ret != -ERESTART) ?
+			    VM_FAULT_SIGBUS : VM_FAULT_NOPAGE;
+			goto out_unlock;
+		}
+	} else
+		spin_unlock(&bo->lock);
+
+
+	ret = ttm_bo_pci_offset(bdev, &bo->mem, &bus_base, &bus_offset,
+				&bus_size);
+	if (unlikely(ret != 0)) {
+		retval = VM_FAULT_SIGBUS;
+		goto out_unlock;
+	}
+
+	is_iomem = (bus_size != 0);
+
+	page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
+	    bo->vm_node->start - vma->vm_pgoff;
+	page_last = ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) +
+	    bo->vm_node->start - vma->vm_pgoff;
+
+	if (unlikely(page_offset >= bo->num_pages)) {
+		retval = VM_FAULT_SIGBUS;
+		goto out_unlock;
+	}
+
+	/*
+	 * Strictly, we're not allowed to modify vma->vm_page_prot here,
+	 * since the mmap_sem is only held in read mode. However, we
+	 * modify only the caching bits of vma->vm_page_prot and
+	 * consider those bits protected by
+	 * the bo->mutex, as we should be the only writers.
+	 * There shouldn't really be any readers of these bits except
+	 * within vm_insert_mixed()? fork?
+	 *
+	 * TODO: Add a list of vmas to the bo, and change the
+	 * vma->vm_page_prot when the object changes caching policy, with
+	 * the correct locks held.
+	 */
+
+	if (is_iomem) {
+		vma->vm_page_prot = ttm_io_prot(bo->mem.placement,
+						vma->vm_page_prot);
+	} else {
+		ttm = bo->ttm;
+		vma->vm_page_prot = (bo->mem.placement & TTM_PL_FLAG_CACHED) ?
+		    vm_get_page_prot(vma->vm_flags) :
+		    ttm_io_prot(bo->mem.placement, vma->vm_page_prot);
+	}
+
+	/*
+	 * Speculatively prefault a number of pages. Only error on
+	 * first page.
+	 */
+
+	for (i = 0; i < TTM_BO_VM_NUM_PREFAULT; ++i) {
+
+		if (is_iomem)
+			pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) +
+			    page_offset;
+		else {
+			page = ttm_tt_get_page(ttm, page_offset);
+			if (unlikely(!page && i == 0)) {
+				retval = VM_FAULT_OOM;
+				goto out_unlock;
+			} else if (unlikely(!page)) {
+				break;
+			}
+			pfn = page_to_pfn(page);
+		}
+
+		ret = vm_insert_mixed(vma, address, pfn);
+		/*
+		 * Somebody beat us to this PTE or prefaulting to
+		 * an already populated PTE, or prefaulting error.
+		 */
+
+		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
+			break;
+		else if (unlikely(ret != 0)) {
+			retval =
+			    (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+			goto out_unlock;
+
+		}
+
+		address += PAGE_SIZE;
+		if (unlikely(++page_offset >= page_last))
+			break;
+	}
+
+out_unlock:
+	ttm_bo_unreserve(bo);
+	return retval;
+}
+
+static void ttm_bo_vm_open(struct vm_area_struct *vma)
+{
+	struct ttm_buffer_object *bo =
+	    (struct ttm_buffer_object *)vma->vm_private_data;
+
+	(void)ttm_bo_reference(bo);
+}
+
+static void ttm_bo_vm_close(struct vm_area_struct *vma)
+{
+	struct ttm_buffer_object *bo =
+	    (struct ttm_buffer_object *)vma->vm_private_data;
+
+	ttm_bo_unref(&bo);
+	vma->vm_private_data = NULL;
+}
+
+static struct vm_operations_struct ttm_bo_vm_ops = {
+	.fault = ttm_bo_vm_fault,
+	.open = ttm_bo_vm_open,
+	.close = ttm_bo_vm_close
+};
+
+int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
+		struct ttm_bo_device *bdev)
+{
+	struct ttm_bo_driver *driver;
+	struct ttm_buffer_object *bo;
+	int ret;
+
+	read_lock(&bdev->vm_lock);
+	bo = ttm_bo_vm_lookup_rb(bdev, vma->vm_pgoff,
+				 (vma->vm_end - vma->vm_start) >> PAGE_SHIFT);
+	if (likely(bo != NULL))
+		ttm_bo_reference(bo);
+	read_unlock(&bdev->vm_lock);
+
+	if (unlikely(bo == NULL)) {
+		printk(KERN_ERR TTM_PFX
+		       "Could not find buffer object to map.\n");
+		return -EINVAL;
+	}
+
+	driver = bo->bdev->driver;
+	if (unlikely(!driver->verify_access)) {
+		ret = -EPERM;
+		goto out_unref;
+	}
+	ret = driver->verify_access(bo, filp);
+	if (unlikely(ret != 0))
+		goto out_unref;
+
+	vma->vm_ops = &ttm_bo_vm_ops;
+
+	/*
+	 * Note: We're transferring the bo reference to
+	 * vma->vm_private_data here.
+	 */
+
+	vma->vm_private_data = bo;
+	vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+	return 0;
+out_unref:
+	ttm_bo_unref(&bo);
+	return ret;
+}
+EXPORT_SYMBOL(ttm_bo_mmap);
+
+int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo)
+{
+	if (vma->vm_pgoff != 0)
+		return -EACCES;
+
+	vma->vm_ops = &ttm_bo_vm_ops;
+	vma->vm_private_data = ttm_bo_reference(bo);
+	vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+	return 0;
+}
+EXPORT_SYMBOL(ttm_fbdev_mmap);
+
+
+ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
+		  const char __user *wbuf, char __user *rbuf, size_t count,
+		  loff_t *f_pos, bool write)
+{
+	struct ttm_buffer_object *bo;
+	struct ttm_bo_driver *driver;
+	struct ttm_bo_kmap_obj map;
+	unsigned long dev_offset = (*f_pos >> PAGE_SHIFT);
+	unsigned long kmap_offset;
+	unsigned long kmap_end;
+	unsigned long kmap_num;
+	size_t io_size;
+	unsigned int page_offset;
+	char *virtual;
+	int ret;
+	bool no_wait = false;
+	bool dummy;
+
+	read_lock(&bdev->vm_lock);
+	bo = ttm_bo_vm_lookup_rb(bdev, dev_offset, 1);
+	if (likely(bo != NULL))
+		ttm_bo_reference(bo);
+	read_unlock(&bdev->vm_lock);
+
+	if (unlikely(bo == NULL))
+		return -EFAULT;
+
+	driver = bo->bdev->driver;
+	if (unlikely(driver->verify_access)) {
+		ret = -EPERM;
+		goto out_unref;
+	}
+
+	ret = driver->verify_access(bo, filp);
+	if (unlikely(ret != 0))
+		goto out_unref;
+
+	kmap_offset = dev_offset - bo->vm_node->start;
+	if (unlikely(kmap_offset >= bo->num_pages)) {
+		ret = -EFBIG;
+		goto out_unref;
+	}
+
+	page_offset = *f_pos & ~PAGE_MASK;
+	io_size = bo->num_pages - kmap_offset;
+	io_size = (io_size << PAGE_SHIFT) - page_offset;
+	if (count < io_size)
+		io_size = count;
+
+	kmap_end = (*f_pos + count - 1) >> PAGE_SHIFT;
+	kmap_num = kmap_end - kmap_offset + 1;
+
+	ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
+
+	switch (ret) {
+	case 0:
+		break;
+	case -ERESTART:
+		ret = -EINTR;
+		goto out_unref;
+	case -EBUSY:
+		ret = -EAGAIN;
+		goto out_unref;
+	default:
+		goto out_unref;
+	}
+
+	ret = ttm_bo_kmap(bo, kmap_offset, kmap_num, &map);
+	if (unlikely(ret != 0)) {
+		ttm_bo_unreserve(bo);
+		goto out_unref;
+	}
+
+	virtual = ttm_kmap_obj_virtual(&map, &dummy);
+	virtual += page_offset;
+
+	if (write)
+		ret = copy_from_user(virtual, wbuf, io_size);
+	else
+		ret = copy_to_user(rbuf, virtual, io_size);
+
+	ttm_bo_kunmap(&map);
+	ttm_bo_unreserve(bo);
+	ttm_bo_unref(&bo);
+
+	if (unlikely(ret != 0))
+		return -EFBIG;
+
+	*f_pos += io_size;
+
+	return io_size;
+out_unref:
+	ttm_bo_unref(&bo);
+	return ret;
+}
+
+ssize_t ttm_bo_fbdev_io(struct ttm_buffer_object *bo, const char __user *wbuf,
+			char __user *rbuf, size_t count, loff_t *f_pos,
+			bool write)
+{
+	struct ttm_bo_kmap_obj map;
+	unsigned long kmap_offset;
+	unsigned long kmap_end;
+	unsigned long kmap_num;
+	size_t io_size;
+	unsigned int page_offset;
+	char *virtual;
+	int ret;
+	bool no_wait = false;
+	bool dummy;
+
+	kmap_offset = (*f_pos >> PAGE_SHIFT);
+	if (unlikely(kmap_offset >= bo->num_pages))
+		return -EFBIG;
+
+	page_offset = *f_pos & ~PAGE_MASK;
+	io_size = bo->num_pages - kmap_offset;
+	io_size = (io_size << PAGE_SHIFT) - page_offset;
+	if (count < io_size)
+		io_size = count;
+
+	kmap_end = (*f_pos + count - 1) >> PAGE_SHIFT;
+	kmap_num = kmap_end - kmap_offset + 1;
+
+	ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
+
+	switch (ret) {
+	case 0:
+		break;
+	case -ERESTART:
+		return -EINTR;
+	case -EBUSY:
+		return -EAGAIN;
+	default:
+		return ret;
+	}
+
+	ret = ttm_bo_kmap(bo, kmap_offset, kmap_num, &map);
+	if (unlikely(ret != 0)) {
+		ttm_bo_unreserve(bo);
+		return ret;
+	}
+
+	virtual = ttm_kmap_obj_virtual(&map, &dummy);
+	virtual += page_offset;
+
+	if (write)
+		ret = copy_from_user(virtual, wbuf, io_size);
+	else
+		ret = copy_to_user(rbuf, virtual, io_size);
+
+	ttm_bo_kunmap(&map);
+	ttm_bo_unreserve(bo);
+	ttm_bo_unref(&bo);
+
+	if (unlikely(ret != 0))
+		return ret;
+
+	*f_pos += io_size;
+
+	return io_size;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_global.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_global.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_global.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_global.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,114 @@
+/**************************************************************************
+ *
+ * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include "ttm/ttm_module.h"
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+struct ttm_global_item {
+	struct mutex mutex;
+	void *object;
+	int refcount;
+};
+
+static struct ttm_global_item glob[TTM_GLOBAL_NUM];
+
+void ttm_global_init(void)
+{
+	int i;
+
+	for (i = 0; i < TTM_GLOBAL_NUM; ++i) {
+		struct ttm_global_item *item = &glob[i];
+		mutex_init(&item->mutex);
+		item->object = NULL;
+		item->refcount = 0;
+	}
+}
+
+void ttm_global_release(void)
+{
+	int i;
+	for (i = 0; i < TTM_GLOBAL_NUM; ++i) {
+		struct ttm_global_item *item = &glob[i];
+		BUG_ON(item->object != NULL);
+		BUG_ON(item->refcount != 0);
+	}
+}
+
+int ttm_global_item_ref(struct ttm_global_reference *ref)
+{
+	int ret;
+	struct ttm_global_item *item = &glob[ref->global_type];
+	void *object;
+
+	mutex_lock(&item->mutex);
+	if (item->refcount == 0) {
+		item->object = kmalloc(ref->size, GFP_KERNEL);
+		if (unlikely(item->object == NULL)) {
+			ret = -ENOMEM;
+			goto out_err;
+		}
+
+		ref->object = item->object;
+		ret = ref->init(ref);
+		if (unlikely(ret != 0))
+			goto out_err;
+
+		++item->refcount;
+	}
+	ref->object = item->object;
+	object = item->object;
+	mutex_unlock(&item->mutex);
+	return 0;
+out_err:
+	kfree(item->object);
+	mutex_unlock(&item->mutex);
+	item->object = NULL;
+	return ret;
+}
+EXPORT_SYMBOL(ttm_global_item_ref);
+
+void ttm_global_item_unref(struct ttm_global_reference *ref)
+{
+	struct ttm_global_item *item = &glob[ref->global_type];
+
+	mutex_lock(&item->mutex);
+	BUG_ON(item->refcount == 0);
+	BUG_ON(ref->object != item->object);
+	if (--item->refcount == 0) {
+		ref->release(ref);
+		kfree(item->object);
+		item->object = NULL;
+	}
+	mutex_unlock(&item->mutex);
+}
+EXPORT_SYMBOL(ttm_global_item_unref);
+
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_memory.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_memory.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_memory.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_memory.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,234 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "ttm/ttm_memory.h"
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+
+#define TTM_PFX "[TTM] "
+#define TTM_MEMORY_ALLOC_RETRIES 4
+
+/**
+ * At this point we only support a single shrink callback.
+ * Extend this if needed, perhaps using a linked list of callbacks.
+ * Note that this function is reentrant:
+ * many threads may try to swap out at any given time.
+ */
+
+static void ttm_shrink(struct ttm_mem_global *glob, bool from_workqueue,
+		       uint64_t extra)
+{
+	int ret;
+	struct ttm_mem_shrink *shrink;
+	uint64_t target;
+	uint64_t total_target;
+
+	spin_lock(&glob->lock);
+	if (glob->shrink == NULL)
+		goto out;
+
+	if (from_workqueue) {
+		target = glob->swap_limit;
+		total_target = glob->total_memory_swap_limit;
+	} else if (capable(CAP_SYS_ADMIN)) {
+		total_target = glob->emer_total_memory;
+		target = glob->emer_memory;
+	} else {
+		total_target = glob->max_total_memory;
+		target = glob->max_memory;
+	}
+
+	total_target = (extra >= total_target) ? 0 : total_target - extra;
+	target = (extra >= target) ? 0 : target - extra;
+
+	while (glob->used_memory > target ||
+	       glob->used_total_memory > total_target) {
+		shrink = glob->shrink;
+		spin_unlock(&glob->lock);
+		ret = shrink->do_shrink(shrink);
+		spin_lock(&glob->lock);
+		if (unlikely(ret != 0))
+			goto out;
+	}
+out:
+	spin_unlock(&glob->lock);
+}
+
+static void ttm_shrink_work(struct work_struct *work)
+{
+	struct ttm_mem_global *glob =
+	    container_of(work, struct ttm_mem_global, work);
+
+	ttm_shrink(glob, true, 0ULL);
+}
+
+int ttm_mem_global_init(struct ttm_mem_global *glob)
+{
+	struct sysinfo si;
+	uint64_t mem;
+
+	spin_lock_init(&glob->lock);
+	glob->swap_queue = create_singlethread_workqueue("ttm_swap");
+	INIT_WORK(&glob->work, ttm_shrink_work);
+	init_waitqueue_head(&glob->queue);
+
+	si_meminfo(&si);
+
+	mem = si.totalram - si.totalhigh;
+	mem *= si.mem_unit;
+
+	glob->max_memory = mem >> 1;
+	glob->emer_memory = (mem >> 1) + (mem >> 2);
+	glob->swap_limit = glob->max_memory - (mem >> 3);
+	glob->used_memory = 0;
+	glob->used_total_memory = 0;
+	glob->shrink = NULL;
+
+	mem = si.totalram;
+	mem *= si.mem_unit;
+
+	glob->max_total_memory = mem >> 1;
+	glob->emer_total_memory = (mem >> 1) + (mem >> 2);
+
+	glob->total_memory_swap_limit = glob->max_total_memory - (mem >> 3);
+
+	printk(KERN_INFO TTM_PFX "TTM available graphics memory: %llu MiB\n",
+	       glob->max_total_memory >> 20);
+	printk(KERN_INFO TTM_PFX "TTM available object memory: %llu MiB\n",
+	       glob->max_memory >> 20);
+
+	return 0;
+}
+EXPORT_SYMBOL(ttm_mem_global_init);
+
+void ttm_mem_global_release(struct ttm_mem_global *glob)
+{
+	printk(KERN_INFO TTM_PFX "Used total memory is %llu bytes.\n",
+	       (unsigned long long)glob->used_total_memory);
+	flush_workqueue(glob->swap_queue);
+	destroy_workqueue(glob->swap_queue);
+	glob->swap_queue = NULL;
+}
+EXPORT_SYMBOL(ttm_mem_global_release);
+
+static inline void ttm_check_swapping(struct ttm_mem_global *glob)
+{
+	bool needs_swapping;
+
+	spin_lock(&glob->lock);
+	needs_swapping = (glob->used_memory > glob->swap_limit ||
+			  glob->used_total_memory >
+			  glob->total_memory_swap_limit);
+	spin_unlock(&glob->lock);
+
+	if (unlikely(needs_swapping))
+		(void)queue_work(glob->swap_queue, &glob->work);
+
+}
+
+void ttm_mem_global_free(struct ttm_mem_global *glob,
+			 uint64_t amount, bool himem)
+{
+	spin_lock(&glob->lock);
+	glob->used_total_memory -= amount;
+	if (!himem)
+		glob->used_memory -= amount;
+	wake_up_all(&glob->queue);
+	spin_unlock(&glob->lock);
+}
+
+static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
+				  uint64_t amount, bool himem, bool reserve)
+{
+	uint64_t limit;
+	uint64_t lomem_limit;
+	int ret = -ENOMEM;
+
+	spin_lock(&glob->lock);
+
+	if (capable(CAP_SYS_ADMIN)) {
+		limit = glob->emer_total_memory;
+		lomem_limit = glob->emer_memory;
+	} else {
+		limit = glob->max_total_memory;
+		lomem_limit = glob->max_memory;
+	}
+
+	if (unlikely(glob->used_total_memory + amount > limit))
+		goto out_unlock;
+	if (unlikely(!himem && glob->used_memory + amount > lomem_limit))
+		goto out_unlock;
+
+	if (reserve) {
+		glob->used_total_memory += amount;
+		if (!himem)
+			glob->used_memory += amount;
+	}
+	ret = 0;
+out_unlock:
+	spin_unlock(&glob->lock);
+	ttm_check_swapping(glob);
+
+	return ret;
+}
+
+int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory,
+			 bool no_wait, bool interruptible, bool himem)
+{
+	int count = TTM_MEMORY_ALLOC_RETRIES;
+
+	while (unlikely(ttm_mem_global_reserve(glob, memory, himem, true)
+			!= 0)) {
+		if (no_wait)
+			return -ENOMEM;
+		if (unlikely(count-- == 0))
+			return -ENOMEM;
+		ttm_shrink(glob, false, memory + (memory >> 2) + 16);
+	}
+
+	return 0;
+}
+
+size_t ttm_round_pot(size_t size)
+{
+	if ((size & (size - 1)) == 0)
+		return size;
+	else if (size > PAGE_SIZE)
+		return PAGE_ALIGN(size);
+	else {
+		size_t tmp_size = 4;
+
+		while (tmp_size < size)
+			tmp_size <<= 1;
+
+		return tmp_size;
+	}
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_module.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_module.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_module.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_module.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ * 	    Jerome Glisse
+ */
+#include <linux/module.h>
+#include <ttm/ttm_module.h>
+
+static int __init ttm_init(void)
+{
+	ttm_global_init();
+	return 0;
+}
+
+static void __exit ttm_exit(void)
+{
+	ttm_global_release();
+}
+
+module_init(ttm_init);
+module_exit(ttm_exit);
+
+MODULE_AUTHOR("Thomas Hellstrom, Jerome Glisse");
+MODULE_DESCRIPTION("TTM memory manager subsystem (for DRM device)");
+MODULE_LICENSE("GPL and additional rights");
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_tt.c linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_tt.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/ttm/ttm_tt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/ttm/ttm_tt.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,656 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/file.h>
+#include <linux/swap.h>
+#include "ttm/ttm_module.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+
+static int ttm_tt_swapin(struct ttm_tt *ttm);
+
+#if defined(CONFIG_X86)
+static void ttm_tt_clflush_page(struct page *page)
+{
+	uint8_t *page_virtual;
+	unsigned int i;
+
+	if (unlikely(page == NULL))
+		return;
+
+	page_virtual = kmap_atomic(page, KM_USER0);
+
+	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+		clflush(page_virtual + i);
+
+	kunmap_atomic(page_virtual, KM_USER0);
+}
+
+static void ttm_tt_cache_flush_clflush(struct page *pages[],
+				       unsigned long num_pages)
+{
+	unsigned long i;
+
+	mb();
+	for (i = 0; i < num_pages; ++i)
+		ttm_tt_clflush_page(*pages++);
+	mb();
+}
+#elif !defined(__powerpc__)
+static void ttm_tt_ipi_handler(void *null)
+{
+	;
+}
+#endif
+
+void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages)
+{
+
+#if defined(CONFIG_X86)
+	if (cpu_has_clflush) {
+		ttm_tt_cache_flush_clflush(pages, num_pages);
+		return;
+	}
+#elif defined(__powerpc__)
+	unsigned long i;
+
+	for (i = 0; i < num_pages; ++i) {
+		struct page *page = pages[i];
+		void *page_virtual;
+
+		if (unlikely(page == NULL))
+			continue;
+
+		page_virtual = kmap_atomic(page, KM_USER0);
+		flush_dcache_range((unsigned long) page_virtual,
+				   (unsigned long) page_virtual + PAGE_SIZE);
+		kunmap_atomic(page_virtual, KM_USER0);
+	}
+#else
+	if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0)
+		printk(KERN_ERR TTM_PFX
+		       "Timed out waiting for drm cache flush.\n");
+#endif
+}
+
+/**
+ * Allocates storage for pointers to the pages that back the ttm.
+ *
+ * Uses kmalloc if possible. Otherwise falls back to vmalloc.
+ */
+static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
+{
+	unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
+	ttm->pages = NULL;
+
+	if (size <= PAGE_SIZE)
+		ttm->pages = kzalloc(size, GFP_KERNEL);
+
+	if (!ttm->pages) {
+		ttm->pages = vmalloc_user(size);
+		if (ttm->pages)
+			ttm->page_flags |= TTM_PAGE_FLAG_VMALLOC;
+	}
+}
+
+static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
+{
+	if (ttm->page_flags & TTM_PAGE_FLAG_VMALLOC) {
+		vfree(ttm->pages);
+		ttm->page_flags &= ~TTM_PAGE_FLAG_VMALLOC;
+	} else {
+		kfree(ttm->pages);
+	}
+	ttm->pages = NULL;
+}
+
+static struct page *ttm_tt_alloc_page(unsigned page_flags)
+{
+	gfp_t gfp_flags = GFP_USER;
+
+	if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC)
+		gfp_flags |= __GFP_ZERO;
+
+	if (page_flags & TTM_PAGE_FLAG_DMA32)
+		gfp_flags |= __GFP_DMA32;
+	else
+		gfp_flags |= __GFP_HIGHMEM;
+
+	return alloc_page(gfp_flags);
+}
+
+static void ttm_tt_free_user_pages(struct ttm_tt *ttm)
+{
+	int write;
+	int dirty;
+	struct page *page;
+	int i;
+	struct ttm_backend *be = ttm->be;
+
+	BUG_ON(!(ttm->page_flags & TTM_PAGE_FLAG_USER));
+	write = ((ttm->page_flags & TTM_PAGE_FLAG_WRITE) != 0);
+	dirty = ((ttm->page_flags & TTM_PAGE_FLAG_USER_DIRTY) != 0);
+
+	if (be)
+		be->func->clear(be);
+
+	for (i = 0; i < ttm->num_pages; ++i) {
+		page = ttm->pages[i];
+		if (page == NULL)
+			continue;
+
+		if (page == ttm->dummy_read_page) {
+			BUG_ON(write);
+			continue;
+		}
+
+		if (write && dirty && !PageReserved(page))
+			set_page_dirty_lock(page);
+
+		ttm->pages[i] = NULL;
+		ttm_mem_global_free(ttm->bdev->mem_glob, PAGE_SIZE, false);
+		put_page(page);
+	}
+	ttm->state = tt_unpopulated;
+	ttm->first_himem_page = ttm->num_pages;
+	ttm->last_lomem_page = -1;
+}
+
+static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index)
+{
+	struct page *p;
+	struct ttm_bo_device *bdev = ttm->bdev;
+	struct ttm_mem_global *mem_glob = bdev->mem_glob;
+	int ret;
+
+	while (NULL == (p = ttm->pages[index])) {
+		p = ttm_tt_alloc_page(ttm->page_flags);
+
+		if (!p)
+			return NULL;
+
+		if (PageHighMem(p)) {
+			ret =
+			    ttm_mem_global_alloc(mem_glob, PAGE_SIZE,
+						 false, false, true);
+			if (unlikely(ret != 0))
+				goto out_err;
+			ttm->pages[--ttm->first_himem_page] = p;
+		} else {
+			ret =
+			    ttm_mem_global_alloc(mem_glob, PAGE_SIZE,
+						 false, false, false);
+			if (unlikely(ret != 0))
+				goto out_err;
+			ttm->pages[++ttm->last_lomem_page] = p;
+		}
+	}
+	return p;
+out_err:
+	put_page(p);
+	return NULL;
+}
+
+struct page *ttm_tt_get_page(struct ttm_tt *ttm, int index)
+{
+	int ret;
+
+	if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) {
+		ret = ttm_tt_swapin(ttm);
+		if (unlikely(ret != 0))
+			return NULL;
+	}
+	return __ttm_tt_get_page(ttm, index);
+}
+
+int ttm_tt_populate(struct ttm_tt *ttm)
+{
+	struct page *page;
+	unsigned long i;
+	struct ttm_backend *be;
+	int ret;
+
+	if (ttm->state != tt_unpopulated)
+		return 0;
+
+	if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) {
+		ret = ttm_tt_swapin(ttm);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	be = ttm->be;
+
+	for (i = 0; i < ttm->num_pages; ++i) {
+		page = __ttm_tt_get_page(ttm, i);
+		if (!page)
+			return -ENOMEM;
+	}
+
+	be->func->populate(be, ttm->num_pages, ttm->pages,
+			   ttm->dummy_read_page);
+	ttm->state = tt_unbound;
+	return 0;
+}
+
+#ifdef CONFIG_X86
+static inline int ttm_tt_set_page_caching(struct page *p,
+					  enum ttm_caching_state c_state)
+{
+	if (PageHighMem(p))
+		return 0;
+
+	switch (c_state) {
+	case tt_cached:
+		return set_pages_wb(p, 1);
+	case tt_wc:
+	    return set_memory_wc((unsigned long) page_address(p), 1);
+	default:
+		return set_pages_uc(p, 1);
+	}
+}
+#else /* CONFIG_X86 */
+static inline int ttm_tt_set_page_caching(struct page *p,
+					  enum ttm_caching_state c_state)
+{
+	return 0;
+}
+#endif /* CONFIG_X86 */
+
+/*
+ * Change caching policy for the linear kernel map
+ * for range of pages in a ttm.
+ */
+
+static int ttm_tt_set_caching(struct ttm_tt *ttm,
+			      enum ttm_caching_state c_state)
+{
+	int i, j;
+	struct page *cur_page;
+	int ret;
+
+	if (ttm->caching_state == c_state)
+		return 0;
+
+	if (c_state != tt_cached) {
+		ret = ttm_tt_populate(ttm);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	if (ttm->caching_state == tt_cached)
+		ttm_tt_cache_flush(ttm->pages, ttm->num_pages);
+
+	for (i = 0; i < ttm->num_pages; ++i) {
+		cur_page = ttm->pages[i];
+		if (likely(cur_page != NULL)) {
+			ret = ttm_tt_set_page_caching(cur_page, c_state);
+			if (unlikely(ret != 0))
+				goto out_err;
+		}
+	}
+
+	ttm->caching_state = c_state;
+
+	return 0;
+
+out_err:
+	for (j = 0; j < i; ++j) {
+		cur_page = ttm->pages[j];
+		if (likely(cur_page != NULL)) {
+			(void)ttm_tt_set_page_caching(cur_page,
+						      ttm->caching_state);
+		}
+	}
+
+	return ret;
+}
+
+int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement)
+{
+	enum ttm_caching_state state;
+
+	if (placement & TTM_PL_FLAG_WC)
+		state = tt_wc;
+	else if (placement & TTM_PL_FLAG_UNCACHED)
+		state = tt_uncached;
+	else
+		state = tt_cached;
+
+	return ttm_tt_set_caching(ttm, state);
+}
+
+static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm)
+{
+	int i;
+	struct page *cur_page;
+	struct ttm_backend *be = ttm->be;
+
+	if (be)
+		be->func->clear(be);
+	(void)ttm_tt_set_caching(ttm, tt_cached);
+	for (i = 0; i < ttm->num_pages; ++i) {
+		cur_page = ttm->pages[i];
+		ttm->pages[i] = NULL;
+		if (cur_page) {
+			if (page_count(cur_page) != 1)
+				printk(KERN_ERR TTM_PFX
+				       "Erroneous page count. "
+				       "Leaking pages.\n");
+			ttm_mem_global_free(ttm->bdev->mem_glob, PAGE_SIZE,
+					    PageHighMem(cur_page));
+			__free_page(cur_page);
+		}
+	}
+	ttm->state = tt_unpopulated;
+	ttm->first_himem_page = ttm->num_pages;
+	ttm->last_lomem_page = -1;
+}
+
+void ttm_tt_destroy(struct ttm_tt *ttm)
+{
+	struct ttm_backend *be;
+
+	if (unlikely(ttm == NULL))
+		return;
+
+	be = ttm->be;
+	if (likely(be != NULL)) {
+		be->func->destroy(be);
+		ttm->be = NULL;
+	}
+
+	if (likely(ttm->pages != NULL)) {
+		if (ttm->page_flags & TTM_PAGE_FLAG_USER)
+			ttm_tt_free_user_pages(ttm);
+		else
+			ttm_tt_free_alloced_pages(ttm);
+
+		ttm_tt_free_page_directory(ttm);
+	}
+
+	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP) &&
+	    ttm->swap_storage)
+		fput(ttm->swap_storage);
+
+	kfree(ttm);
+}
+
+int ttm_tt_set_user(struct ttm_tt *ttm,
+		    struct task_struct *tsk,
+		    unsigned long start, unsigned long num_pages)
+{
+	struct mm_struct *mm = tsk->mm;
+	int ret;
+	int write = (ttm->page_flags & TTM_PAGE_FLAG_WRITE) != 0;
+	struct ttm_mem_global *mem_glob = ttm->bdev->mem_glob;
+
+	BUG_ON(num_pages != ttm->num_pages);
+	BUG_ON((ttm->page_flags & TTM_PAGE_FLAG_USER) == 0);
+
+	/**
+	 * Account user pages as lowmem pages for now.
+	 */
+
+	ret = ttm_mem_global_alloc(mem_glob, num_pages * PAGE_SIZE,
+				   false, false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	down_read(&mm->mmap_sem);
+	ret = get_user_pages(tsk, mm, start, num_pages,
+			     write, 0, ttm->pages, NULL);
+	up_read(&mm->mmap_sem);
+
+	if (ret != num_pages && write) {
+		ttm_tt_free_user_pages(ttm);
+		ttm_mem_global_free(mem_glob, num_pages * PAGE_SIZE, false);
+		return -ENOMEM;
+	}
+
+	ttm->tsk = tsk;
+	ttm->start = start;
+	ttm->state = tt_unbound;
+
+	return 0;
+}
+
+struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
+			     uint32_t page_flags, struct page *dummy_read_page)
+{
+	struct ttm_bo_driver *bo_driver = bdev->driver;
+	struct ttm_tt *ttm;
+
+	if (!bo_driver)
+		return NULL;
+
+	ttm = kzalloc(sizeof(*ttm), GFP_KERNEL);
+	if (!ttm)
+		return NULL;
+
+	ttm->bdev = bdev;
+
+	ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	ttm->first_himem_page = ttm->num_pages;
+	ttm->last_lomem_page = -1;
+	ttm->caching_state = tt_cached;
+	ttm->page_flags = page_flags;
+
+	ttm->dummy_read_page = dummy_read_page;
+
+	ttm_tt_alloc_page_directory(ttm);
+	if (!ttm->pages) {
+		ttm_tt_destroy(ttm);
+		printk(KERN_ERR TTM_PFX "Failed allocating page table\n");
+		return NULL;
+	}
+	ttm->be = bo_driver->create_ttm_backend_entry(bdev);
+	if (!ttm->be) {
+		ttm_tt_destroy(ttm);
+		printk(KERN_ERR TTM_PFX "Failed creating ttm backend entry\n");
+		return NULL;
+	}
+	ttm->state = tt_unpopulated;
+	return ttm;
+}
+
+void ttm_tt_unbind(struct ttm_tt *ttm)
+{
+	int ret;
+	struct ttm_backend *be = ttm->be;
+
+	if (ttm->state == tt_bound) {
+		ret = be->func->unbind(be);
+		BUG_ON(ret);
+		ttm->state = tt_unbound;
+	}
+}
+
+int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
+{
+	int ret = 0;
+	struct ttm_backend *be;
+
+	if (!ttm)
+		return -EINVAL;
+
+	if (ttm->state == tt_bound)
+		return 0;
+
+	be = ttm->be;
+
+	ret = ttm_tt_populate(ttm);
+	if (ret)
+		return ret;
+
+	ret = be->func->bind(be, bo_mem);
+	if (ret) {
+		printk(KERN_ERR TTM_PFX "Couldn't bind backend.\n");
+		return ret;
+	}
+
+	ttm->state = tt_bound;
+
+	if (ttm->page_flags & TTM_PAGE_FLAG_USER)
+		ttm->page_flags |= TTM_PAGE_FLAG_USER_DIRTY;
+	return 0;
+}
+EXPORT_SYMBOL(ttm_tt_bind);
+
+static int ttm_tt_swapin(struct ttm_tt *ttm)
+{
+	struct address_space *swap_space;
+	struct file *swap_storage;
+	struct page *from_page;
+	struct page *to_page;
+	void *from_virtual;
+	void *to_virtual;
+	int i;
+	int ret;
+
+	if (ttm->page_flags & TTM_PAGE_FLAG_USER) {
+		ret = ttm_tt_set_user(ttm, ttm->tsk, ttm->start,
+				      ttm->num_pages);
+		if (unlikely(ret != 0))
+			return ret;
+
+		ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED;
+		return 0;
+	}
+
+	swap_storage = ttm->swap_storage;
+	BUG_ON(swap_storage == NULL);
+
+	swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;
+
+	for (i = 0; i < ttm->num_pages; ++i) {
+		from_page = read_mapping_page(swap_space, i, NULL);
+		if (IS_ERR(from_page))
+			goto out_err;
+		to_page = __ttm_tt_get_page(ttm, i);
+		if (unlikely(to_page == NULL))
+			goto out_err;
+
+		preempt_disable();
+		from_virtual = kmap_atomic(from_page, KM_USER0);
+		to_virtual = kmap_atomic(to_page, KM_USER1);
+		memcpy(to_virtual, from_virtual, PAGE_SIZE);
+		kunmap_atomic(to_virtual, KM_USER1);
+		kunmap_atomic(from_virtual, KM_USER0);
+		preempt_enable();
+		page_cache_release(from_page);
+	}
+
+	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP))
+		fput(swap_storage);
+	ttm->swap_storage = NULL;
+	ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED;
+
+	return 0;
+out_err:
+	ttm_tt_free_alloced_pages(ttm);
+	return -ENOMEM;
+}
+
+int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage)
+{
+	struct address_space *swap_space;
+	struct file *swap_storage;
+	struct page *from_page;
+	struct page *to_page;
+	void *from_virtual;
+	void *to_virtual;
+	int i;
+
+	BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated);
+	BUG_ON(ttm->caching_state != tt_cached);
+
+	/*
+	 * For user buffers, just unpin the pages, as there should be
+	 * vma references.
+	 */
+
+	if (ttm->page_flags & TTM_PAGE_FLAG_USER) {
+		ttm_tt_free_user_pages(ttm);
+		ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
+		ttm->swap_storage = NULL;
+		return 0;
+	}
+
+	if (!persistant_swap_storage) {
+		swap_storage = shmem_file_setup("ttm swap",
+						ttm->num_pages << PAGE_SHIFT,
+						0);
+		if (unlikely(IS_ERR(swap_storage))) {
+			printk(KERN_ERR "Failed allocating swap storage.\n");
+			return -ENOMEM;
+		}
+	} else
+		swap_storage = persistant_swap_storage;
+
+	swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;
+
+	for (i = 0; i < ttm->num_pages; ++i) {
+		from_page = ttm->pages[i];
+		if (unlikely(from_page == NULL))
+			continue;
+		to_page = read_mapping_page(swap_space, i, NULL);
+		if (unlikely(to_page == NULL))
+			goto out_err;
+
+		preempt_disable();
+		from_virtual = kmap_atomic(from_page, KM_USER0);
+		to_virtual = kmap_atomic(to_page, KM_USER1);
+		memcpy(to_virtual, from_virtual, PAGE_SIZE);
+		kunmap_atomic(to_virtual, KM_USER1);
+		kunmap_atomic(from_virtual, KM_USER0);
+		preempt_enable();
+		set_page_dirty(to_page);
+		mark_page_accessed(to_page);
+		page_cache_release(to_page);
+	}
+
+	ttm_tt_free_alloced_pages(ttm);
+	ttm->swap_storage = swap_storage;
+	ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
+	if (persistant_swap_storage)
+		ttm->page_flags |= TTM_PAGE_FLAG_PERSISTANT_SWAP;
+
+	return 0;
+out_err:
+	if (!persistant_swap_storage)
+		fput(swap_storage);
+
+	return -ENOMEM;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/via/via_dmablit.c linux-libre-2.6.31-gnu/drivers/gpu/drm/via/via_dmablit.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/via/via_dmablit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/via/via_dmablit.c	2009-09-09 18:13:59.000000000 -0400
@@ -195,10 +195,8 @@
 	default:
 		vsg->state = dr_via_sg_init;
 	}
-	if (vsg->bounce_buffer) {
-		vfree(vsg->bounce_buffer);
-		vsg->bounce_buffer = NULL;
-	}
+	vfree(vsg->bounce_buffer);
+	vsg->bounce_buffer = NULL;
 	vsg->free_on_sequence = 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/via/via_irq.c linux-libre-2.6.31-gnu/drivers/gpu/drm/via/via_irq.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/via/via_irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/via/via_irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -183,7 +183,7 @@
 	}
 
 	status = VIA_READ(VIA_REG_INTERRUPT);
-	VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
+	VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
 
 	VIA_WRITE8(0x83d4, 0x11);
 	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
@@ -194,6 +194,10 @@
 void via_disable_vblank(struct drm_device *dev, int crtc)
 {
 	drm_via_private_t *dev_priv = dev->dev_private;
+	u32 status;
+
+	status = VIA_READ(VIA_REG_INTERRUPT);
+	VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
 
 	VIA_WRITE8(0x83d4, 0x11);
 	VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
diff -druN linux-libre-2.6.30-gnu/drivers/gpu/drm/via/via_map.c linux-libre-2.6.31-gnu/drivers/gpu/drm/via/via_map.c
--- linux-libre-2.6.30-gnu/drivers/gpu/drm/via/via_map.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/gpu/drm/via/via_map.c	2009-09-09 18:13:59.000000000 -0400
@@ -96,7 +96,7 @@
 	drm_via_private_t *dev_priv;
 	int ret = 0;
 
-	dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+	dev_priv = kzalloc(sizeof(drm_via_private_t), GFP_KERNEL);
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
@@ -106,14 +106,14 @@
 
 	ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
 	if (ret) {
-		drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+		kfree(dev_priv);
 		return ret;
 	}
 
 	ret = drm_vblank_init(dev, 1);
 	if (ret) {
 		drm_sman_takedown(&dev_priv->sman);
-		drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+		kfree(dev_priv);
 		return ret;
 	}
 
@@ -126,7 +126,7 @@
 
 	drm_sman_takedown(&dev_priv->sman);
 
-	drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+	kfree(dev_priv);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-apple.c linux-libre-2.6.31-gnu/drivers/hid/hid-apple.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-apple.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-apple.c	2009-09-09 18:13:59.000000000 -0400
@@ -436,10 +436,6 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 
-	/* Apple wireless Mighty Mouse */
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c),
-		.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
-
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, apple_devices);
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-core.c linux-libre-2.6.31-gnu/drivers/hid/hid-core.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -1075,14 +1075,16 @@
  */
 int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
 {
-	struct hid_report_enum *report_enum = hid->report_enum + type;
-	struct hid_driver *hdrv = hid->driver;
+	struct hid_report_enum *report_enum;
+	struct hid_driver *hdrv;
 	struct hid_report *report;
 	unsigned int i;
 	int ret;
 
 	if (!hid || !hid->driver)
 		return -ENODEV;
+	report_enum = hid->report_enum + type;
+	hdrv = hid->driver;
 
 	if (!size) {
 		dbg_hid("empty report\n");
@@ -1312,6 +1314,8 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
 
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-debug.c linux-libre-2.6.31-gnu/drivers/hid/hid-debug.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-debug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -137,6 +137,14 @@
     {0, 0x44, "BarrelSwitch"},
     {0, 0x45, "Eraser"},
     {0, 0x46, "TabletPick"},
+    {0, 0x47, "Confidence"},
+    {0, 0x48, "Width"},
+    {0, 0x49, "Height"},
+    {0, 0x51, "ContactID"},
+    {0, 0x52, "InputMode"},
+    {0, 0x53, "DeviceIndex"},
+    {0, 0x54, "ContactCount"},
+    {0, 0x55, "ContactMaximumNumber"},
   { 15, 0, "PhysicalInterfaceDevice" },
     {0, 0x00, "Undefined"},
     {0, 0x01, "Physical_Interface_Device"},
@@ -514,9 +522,11 @@
 	[EV_FF_STATUS] = "ForceFeedbackStatus",
 };
 
-static const char *syncs[2] = {
+static const char *syncs[3] = {
 	[SYN_REPORT] = "Report",		[SYN_CONFIG] = "Config",
+	[SYN_MT_REPORT] = "MT Report",
 };
+
 static const char *keys[KEY_MAX + 1] = {
 	[KEY_RESERVED] = "Reserved",		[KEY_ESC] = "Esc",
 	[KEY_1] = "1",				[KEY_2] = "2",
@@ -734,8 +744,17 @@
 	[ABS_HAT2Y] = "Hat2Y",		[ABS_HAT3X] = "Hat3X",
 	[ABS_HAT3Y] = "Hat 3Y",		[ABS_PRESSURE] = "Pressure",
 	[ABS_DISTANCE] = "Distance",	[ABS_TILT_X] = "XTilt",
-	[ABS_TILT_Y] = "YTilt",		[ABS_TOOL_WIDTH] = "Tool Width",
+	[ABS_TILT_Y] = "YTilt",		[ABS_TOOL_WIDTH] = "ToolWidth",
 	[ABS_VOLUME] = "Volume",	[ABS_MISC] = "Misc",
+	[ABS_MT_TOUCH_MAJOR] = "MTMajor",
+	[ABS_MT_TOUCH_MINOR] = "MTMinor",
+	[ABS_MT_WIDTH_MAJOR] = "MTMajorW",
+	[ABS_MT_WIDTH_MINOR] = "MTMinorW",
+	[ABS_MT_ORIENTATION] = "MTOrientation",
+	[ABS_MT_POSITION_X] = "MTPositionX",
+	[ABS_MT_POSITION_Y] = "MTPositionY",
+	[ABS_MT_TOOL_TYPE] = "MTToolType",
+	[ABS_MT_BLOB_ID] = "MTBlobID",
 };
 
 static const char *misc[MSC_MAX + 1] = {
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-drff.c linux-libre-2.6.31-gnu/drivers/hid/hid-drff.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-drff.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-drff.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,6 +32,8 @@
 #include <linux/hid.h>
 
 #include "hid-ids.h"
+
+#ifdef CONFIG_DRAGONRISE_FF
 #include "usbhid/usbhid.h"
 
 struct drff_device {
@@ -135,6 +137,12 @@
 
 	return 0;
 }
+#else
+static inline int drff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
 
 static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-gaff.c linux-libre-2.6.31-gnu/drivers/hid/hid-gaff.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-gaff.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-gaff.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,8 @@
 #include <linux/usb.h>
 #include <linux/hid.h>
 #include "hid-ids.h"
+
+#ifdef CONFIG_GREENASIA_FF
 #include "usbhid/usbhid.h"
 
 struct gaff_device {
@@ -130,6 +132,12 @@
 
 	return 0;
 }
+#else
+static inline int gaff_init(struct hid_device *hdev)
+{
+	return 0;
+}
+#endif
 
 static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-ids.h linux-libre-2.6.31-gnu/drivers/hid/hid-ids.h
--- linux-libre-2.6.30-gnu/drivers/hid/hid-ids.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-ids.h	2009-09-09 18:13:59.000000000 -0400
@@ -414,8 +414,10 @@
 #define USB_DEVICE_ID_VERNIER_LCSPEC	0x0006
 
 #define USB_VENDOR_ID_WACOM		0x056a
+#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH	0x81
 
 #define USB_VENDOR_ID_WISEGROUP		0x0925
+#define USB_DEVICE_ID_SMARTJOY_PLUS	0x0005
 #define USB_DEVICE_ID_1_PHIDGETSERVO_20	0x8101
 #define USB_DEVICE_ID_4_PHIDGETSERVO_20	0x8104
 #define USB_DEVICE_ID_8_8_4_IF_KIT	0x8201
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-lgff.c linux-libre-2.6.31-gnu/drivers/hid/hid-lgff.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-lgff.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-lgff.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,12 @@
 	-1
 };
 
+static const signed short ff_joystick_ac[] = {
+	FF_CONSTANT,
+	FF_AUTOCENTER,
+	-1
+};
+
 static const signed short ff_wheel[] = {
 	FF_CONSTANT,
 	FF_AUTOCENTER,
@@ -60,8 +66,8 @@
 	{ 0x046d, 0xc211, ff_rumble },
 	{ 0x046d, 0xc219, ff_rumble },
 	{ 0x046d, 0xc283, ff_joystick },
-	{ 0x046d, 0xc286, ff_joystick },
-	{ 0x046d, 0xc294, ff_joystick },
+	{ 0x046d, 0xc286, ff_joystick_ac },
+	{ 0x046d, 0xc294, ff_wheel },
 	{ 0x046d, 0xc295, ff_joystick },
 	{ 0x046d, 0xca03, ff_wheel },
 };
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-ntrig.c linux-libre-2.6.31-gnu/drivers/hid/hid-ntrig.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-ntrig.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-ntrig.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,13 +1,8 @@
 /*
- *  HID driver for some ntrig "special" devices
+ *  HID driver for N-Trig touchscreens
  *
- *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
- *  Copyright (c) 2008 Jiri Slaby
  *  Copyright (c) 2008 Rafi Rubin
+ *  Copyright (c) 2009 Stephane Chatty
  *
  */
 
@@ -29,15 +24,79 @@
 #define nt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
 					EV_KEY, (c))
 
+struct ntrig_data {
+	__s32 x, y, id, w, h;
+	char reading_a_point, found_contact_id;
+};
+
+/*
+ * this driver is aimed at two firmware versions in circulation:
+ *  - dual pen/finger single touch
+ *  - finger multitouch, pen not working
+ */
+
 static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
-			(usage->hid & 0xff) == 0x47) {
-		nt_map_key_clear(BTN_TOOL_DOUBLETAP);
-		return 1;
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			input_set_abs_params(hi->input, ABS_X,
+					field->logical_minimum,
+					field->logical_maximum, 0, 0);
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			input_set_abs_params(hi->input, ABS_Y,
+					field->logical_minimum,
+					field->logical_maximum, 0, 0);
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		/* we do not want to map these for now */
+		case HID_DG_INVERT: /* value is always 0 */
+		case HID_DG_ERASER: /* value is always 0 */
+		case HID_DG_CONTACTID: /* value is useless */
+		case HID_DG_BARRELSWITCH:  /* doubtful */
+		case HID_DG_INPUTMODE:
+		case HID_DG_DEVICEINDEX:
+		case HID_DG_CONTACTCOUNT:
+		case HID_DG_CONTACTMAX:
+			return -1;
+
+		/* original mapping by Rafi Rubin */
+		case HID_DG_CONFIDENCE:
+			nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+			return 1;
+
+		/* width/height mapped on TouchMajor/TouchMinor/Orientation */
+		case HID_DG_WIDTH:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MAJOR);
+			return 1;
+		case HID_DG_HEIGHT:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MINOR);
+			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
+					0, 1, 0, 0);
+			return 1;
+		}
+		return 0;
+
+	case 0xff000000:
+		/* we do not want to map these: no input-oriented meaning */
+		return -1;
 	}
+
 	return 0;
 }
 
@@ -51,6 +110,138 @@
 
 	return 0;
 }
+
+/*
+ * this function is called upon all reports
+ * so that we can filter contact point information,
+ * decide whether we are in multi or single touch mode
+ * and call input_mt_sync after each point if necessary
+ */
+static int ntrig_event (struct hid_device *hid, struct hid_field *field,
+		                        struct hid_usage *usage, __s32 value)
+{
+	struct input_dev *input = field->hidinput->input;
+	struct ntrig_data *nd = hid_get_drvdata(hid);
+
+        if (hid->claimed & HID_CLAIMED_INPUT) {
+		switch (usage->hid) {
+		case HID_GD_X:
+			nd->x = value;
+			nd->reading_a_point = 1;
+			break;
+		case HID_GD_Y:
+			nd->y = value;
+			break;
+		case HID_DG_CONTACTID:
+			nd->id = value;
+			/* we receive this only when in multitouch mode */
+			nd->found_contact_id = 1;
+			break;
+		case HID_DG_WIDTH:
+			nd->w = value;
+			break;
+		case HID_DG_HEIGHT:
+			nd->h = value;
+			/*
+			 * when in single touch mode, this is the last
+			 * report received in a finger event. We want
+			 * to emit a normal (X, Y) position
+			 */
+			if (! nd->found_contact_id) {
+				input_event(input, EV_ABS, ABS_X, nd->x);
+				input_event(input, EV_ABS, ABS_Y, nd->y);
+			}
+			break;
+		case HID_DG_TIPPRESSURE:
+			/*
+			 * when in single touch mode, this is the last
+			 * report received in a pen event. We want
+			 * to emit a normal (X, Y) position
+			 */
+			if (! nd->found_contact_id) {
+				input_event(input, EV_ABS, ABS_X, nd->x);
+				input_event(input, EV_ABS, ABS_Y, nd->y);
+				input_event(input, EV_ABS, ABS_PRESSURE, value);
+			}
+			break;
+		case 0xff000002:
+			/*
+			 * we receive this when the device is in multitouch
+			 * mode. The first of the three values tagged with
+			 * this usage tells if the contact point is real
+			 * or a placeholder
+			 */
+			if (!nd->reading_a_point || value != 1)
+				break;
+			/* emit a normal (X, Y) for the first point only */
+			if (nd->id == 0) {
+				input_event(input, EV_ABS, ABS_X, nd->x);
+				input_event(input, EV_ABS, ABS_Y, nd->y);
+			}
+			input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
+			input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
+			if (nd->w > nd->h) {
+				input_event(input, EV_ABS,
+						ABS_MT_ORIENTATION, 1);
+				input_event(input, EV_ABS,
+						ABS_MT_TOUCH_MAJOR, nd->w);
+				input_event(input, EV_ABS,
+						ABS_MT_TOUCH_MINOR, nd->h);
+			} else {
+				input_event(input, EV_ABS,
+						ABS_MT_ORIENTATION, 0);
+				input_event(input, EV_ABS,
+						ABS_MT_TOUCH_MAJOR, nd->h);
+				input_event(input, EV_ABS,
+						ABS_MT_TOUCH_MINOR, nd->w);
+			}
+			input_mt_sync(field->hidinput->input);
+			nd->reading_a_point = 0;
+			nd->found_contact_id = 0;
+			break;
+
+		default:
+			/* fallback to the generic hidinput handling */
+			return 0;
+		}
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+        if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+                hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct ntrig_data *nd;
+
+	nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
+	if (!nd) {
+		dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
+		return -ENOMEM;
+	}
+	nd->reading_a_point = 0;
+	nd->found_contact_id = 0;
+	hid_set_drvdata(hdev, nd);
+
+	ret = hid_parse(hdev);
+	if (!ret)
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+	if (ret)
+		kfree (nd);
+	return ret;
+}
+
+static void ntrig_remove(struct hid_device *hdev)
+{
+	hid_hw_stop(hdev);
+	kfree(hid_get_drvdata(hdev));
+}
+
 static const struct hid_device_id ntrig_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
 		.driver_data = NTRIG_DUPLICATE_USAGES },
@@ -58,11 +249,20 @@
 };
 MODULE_DEVICE_TABLE(hid, ntrig_devices);
 
+static const struct hid_usage_id ntrig_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
 static struct hid_driver ntrig_driver = {
 	.name = "ntrig",
 	.id_table = ntrig_devices,
+	.probe = ntrig_probe,
+	.remove = ntrig_remove,
 	.input_mapping = ntrig_input_mapping,
 	.input_mapped = ntrig_input_mapped,
+	.usage_table = ntrig_grabbed_usages,
+	.event = ntrig_event,
 };
 
 static int ntrig_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hidraw.c linux-libre-2.6.31-gnu/drivers/hid/hidraw.c
--- linux-libre-2.6.30-gnu/drivers/hid/hidraw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hidraw.c	2009-09-09 18:13:59.000000000 -0400
@@ -349,10 +349,7 @@
 	int minor, result;
 	struct hidraw *dev;
 
-	/* TODO currently we accept any HID device. This should later
-	 * probably be fixed to accept only those devices which provide
-	 * non-input applications
-	 */
+	/* we accept any HID device, no matter the applications */
 
 	dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
 	if (!dev)
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-sjoy.c linux-libre-2.6.31-gnu/drivers/hid/hid-sjoy.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-sjoy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-sjoy.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,180 @@
+/*
+ *  Force feedback support for SmartJoy PLUS PS2->USB adapter
+ *
+ *  Copyright (c) 2009 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ *  Based of hid-pl.c and hid-gaff.c
+ *   Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com>
+ *   Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
+ */
+
+/*
+ * 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
+ */
+
+/* #define DEBUG */
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include "hid-ids.h"
+
+#ifdef CONFIG_SMARTJOYPLUS_FF
+#include "usbhid/usbhid.h"
+
+struct sjoyff_device {
+	struct hid_report *report;
+};
+
+static int hid_sjoyff_play(struct input_dev *dev, void *data,
+			 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct sjoyff_device *sjoyff = data;
+	u32 left, right;
+
+	left = effect->u.rumble.strong_magnitude;
+	right = effect->u.rumble.weak_magnitude;
+	dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right);
+
+	left = left * 0xff / 0xffff;
+	right = (right != 0); /* on/off only */
+
+	sjoyff->report->field[0]->value[1] = right;
+	sjoyff->report->field[0]->value[2] = left;
+	dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
+	usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+
+	return 0;
+}
+
+static int sjoyff_init(struct hid_device *hid)
+{
+	struct sjoyff_device *sjoyff;
+	struct hid_report *report;
+	struct hid_input *hidinput = list_entry(hid->inputs.next,
+						struct hid_input, list);
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct list_head *report_ptr = report_list;
+	struct input_dev *dev;
+	int error;
+
+	if (list_empty(report_list)) {
+		dev_err(&hid->dev, "no output reports found\n");
+		return -ENODEV;
+	}
+
+	report_ptr = report_ptr->next;
+
+	if (report_ptr == report_list) {
+		dev_err(&hid->dev, "required output report is "
+				"missing\n");
+		return -ENODEV;
+	}
+
+	report = list_entry(report_ptr, struct hid_report, list);
+	if (report->maxfield < 1) {
+		dev_err(&hid->dev, "no fields in the report\n");
+		return -ENODEV;
+	}
+
+	if (report->field[0]->report_count < 3) {
+		dev_err(&hid->dev, "not enough values in the field\n");
+		return -ENODEV;
+	}
+
+	sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
+	if (!sjoyff)
+		return -ENOMEM;
+
+	dev = hidinput->input;
+
+	set_bit(FF_RUMBLE, dev->ffbit);
+
+	error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
+	if (error) {
+		kfree(sjoyff);
+		return error;
+	}
+
+	sjoyff->report = report;
+	sjoyff->report->field[0]->value[0] = 0x01;
+	sjoyff->report->field[0]->value[1] = 0x00;
+	sjoyff->report->field[0]->value[2] = 0x00;
+	usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+
+	dev_info(&hid->dev,
+		"Force feedback for SmartJoy PLUS PS2/USB adapter\n");
+
+	return 0;
+}
+#else
+static inline int sjoyff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
+
+static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		dev_err(&hdev->dev, "parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		dev_err(&hdev->dev, "hw start failed\n");
+		goto err;
+	}
+
+	sjoyff_init(hdev);
+
+	return 0;
+err:
+	return ret;
+}
+
+static const struct hid_device_id sjoy_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, sjoy_devices);
+
+static struct hid_driver sjoy_driver = {
+	.name = "smartjoyplus",
+	.id_table = sjoy_devices,
+	.probe = sjoy_probe,
+};
+
+static int sjoy_init(void)
+{
+	return hid_register_driver(&sjoy_driver);
+}
+
+static void sjoy_exit(void)
+{
+	hid_unregister_driver(&sjoy_driver);
+}
+
+module_init(sjoy_init);
+module_exit(sjoy_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jussi Kivilinna");
+
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-tmff.c linux-libre-2.6.31-gnu/drivers/hid/hid-tmff.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-tmff.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-tmff.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,11 +33,6 @@
 
 #include "hid-ids.h"
 
-#include "usbhid/usbhid.h"
-
-/* Usages for thrustmaster devices I know about */
-#define THRUSTMASTER_USAGE_FF	(HID_UP_GENDESK | 0xbb)
-
 static const signed short ff_rumble[] = {
 	FF_RUMBLE,
 	-1
@@ -48,6 +43,12 @@
 	-1
 };
 
+#ifdef CONFIG_THRUSTMASTER_FF
+#include "usbhid/usbhid.h"
+
+/* Usages for thrustmaster devices I know about */
+#define THRUSTMASTER_USAGE_FF	(HID_UP_GENDESK | 0xbb)
+
 struct tmff_device {
 	struct hid_report *report;
 	struct hid_field *ff_field;
@@ -209,6 +210,12 @@
 	kfree(tmff);
 	return error;
 }
+#else
+static inline int tmff_init(struct hid_device *hid, const signed short *ff_bits)
+{
+	return 0;
+}
+#endif
 
 static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-wacom.c linux-libre-2.6.31-gnu/drivers/hid/hid-wacom.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-wacom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-wacom.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,259 @@
+/*
+ *  Bluetooth Wacom Tablet support
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
+ *  Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
+ *  Copyright (c) 2009 Bastien Nocera <hadess@hadess.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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+struct wacom_data {
+	__u16 tool;
+	unsigned char butstate;
+};
+
+static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size)
+{
+	struct wacom_data *wdata = hid_get_drvdata(hdev);
+	struct hid_input *hidinput;
+	struct input_dev *input;
+	unsigned char *data = (unsigned char *) raw_data;
+	int tool, x, y, rw;
+
+	if (!(hdev->claimed & HID_CLAIMED_INPUT))
+		return 0;
+
+	tool = 0;
+	hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
+	input = hidinput->input;
+
+	/* Check if this is a tablet report */
+	if (data[0] != 0x03)
+		return 0;
+
+	/* Get X & Y positions */
+	x = le16_to_cpu(*(__le16 *) &data[2]);
+	y = le16_to_cpu(*(__le16 *) &data[4]);
+
+	/* Get current tool identifier */
+	if (data[1] & 0x90) { /* If pen is in the in/active area */
+		switch ((data[1] >> 5) & 3) {
+		case 0:	/* Pen */
+			tool = BTN_TOOL_PEN;
+			break;
+
+		case 1: /* Rubber */
+			tool = BTN_TOOL_RUBBER;
+			break;
+
+		case 2: /* Mouse with wheel */
+		case 3: /* Mouse without wheel */
+			tool = BTN_TOOL_MOUSE;
+			break;
+		}
+
+		/* Reset tool if out of active tablet area */
+		if (!(data[1] & 0x10))
+			tool = 0;
+	}
+
+	/* If tool changed, notify input subsystem */
+	if (wdata->tool != tool) {
+		if (wdata->tool) {
+			/* Completely reset old tool state */
+			if (wdata->tool == BTN_TOOL_MOUSE) {
+				input_report_key(input, BTN_LEFT, 0);
+				input_report_key(input, BTN_RIGHT, 0);
+				input_report_key(input, BTN_MIDDLE, 0);
+				input_report_abs(input, ABS_DISTANCE,
+						input->absmax[ABS_DISTANCE]);
+			} else {
+				input_report_key(input, BTN_TOUCH, 0);
+				input_report_key(input, BTN_STYLUS, 0);
+				input_report_key(input, BTN_STYLUS2, 0);
+				input_report_abs(input, ABS_PRESSURE, 0);
+			}
+			input_report_key(input, wdata->tool, 0);
+			input_sync(input);
+		}
+		wdata->tool = tool;
+		if (tool)
+			input_report_key(input, tool, 1);
+	}
+
+	if (tool) {
+		input_report_abs(input, ABS_X, x);
+		input_report_abs(input, ABS_Y, y);
+
+		switch ((data[1] >> 5) & 3) {
+		case 2: /* Mouse with wheel */
+			input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
+			rw = (data[6] & 0x01) ? -1 :
+				(data[6] & 0x02) ? 1 : 0;
+			input_report_rel(input, REL_WHEEL, rw);
+			/* fall through */
+
+		case 3: /* Mouse without wheel */
+			input_report_key(input, BTN_LEFT, data[1] & 0x01);
+			input_report_key(input, BTN_RIGHT, data[1] & 0x02);
+			/* Compute distance between mouse and tablet */
+			rw = 44 - (data[6] >> 2);
+			if (rw < 0)
+				rw = 0;
+			else if (rw > 31)
+				rw = 31;
+			input_report_abs(input, ABS_DISTANCE, rw);
+			break;
+
+		default:
+			input_report_abs(input, ABS_PRESSURE,
+					data[6] | (((__u16) (data[1] & 0x08)) << 5));
+			input_report_key(input, BTN_TOUCH, data[1] & 0x01);
+			input_report_key(input, BTN_STYLUS, data[1] & 0x02);
+			input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
+			break;
+		}
+
+		input_sync(input);
+	}
+
+	/* Report the state of the two buttons at the top of the tablet
+	 * as two extra fingerpad keys (buttons 4 & 5). */
+	rw = data[7] & 0x03;
+	if (rw != wdata->butstate) {
+		wdata->butstate = rw;
+		input_report_key(input, BTN_0, rw & 0x02);
+		input_report_key(input, BTN_1, rw & 0x01);
+		input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+		input_sync(input);
+	}
+
+	return 1;
+}
+
+static int wacom_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	struct hid_input *hidinput;
+	struct input_dev *input;
+	struct wacom_data *wdata;
+	int ret;
+
+	wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
+	if (wdata == NULL) {
+		dev_err(&hdev->dev, "can't alloc wacom descriptor\n");
+		return -ENOMEM;
+	}
+
+	hid_set_drvdata(hdev, wdata);
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		dev_err(&hdev->dev, "parse failed\n");
+		goto err_free;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		dev_err(&hdev->dev, "hw start failed\n");
+		goto err_free;
+	}
+
+	hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
+	input = hidinput->input;
+
+	/* Basics */
+	input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
+	input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) |
+		BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
+	input->relbit[0] |= BIT(REL_WHEEL);
+	set_bit(BTN_TOOL_PEN, input->keybit);
+	set_bit(BTN_TOUCH, input->keybit);
+	set_bit(BTN_STYLUS, input->keybit);
+	set_bit(BTN_STYLUS2, input->keybit);
+	set_bit(BTN_LEFT, input->keybit);
+	set_bit(BTN_RIGHT, input->keybit);
+	set_bit(BTN_MIDDLE, input->keybit);
+
+	/* Pad */
+	input->evbit[0] |= BIT(EV_MSC);
+	input->mscbit[0] |= BIT(MSC_SERIAL);
+
+	/* Distance, rubber and mouse */
+	input->absbit[0] |= BIT(ABS_DISTANCE);
+	set_bit(BTN_TOOL_RUBBER, input->keybit);
+	set_bit(BTN_TOOL_MOUSE, input->keybit);
+
+	input->absmax[ABS_PRESSURE] = 511;
+	input->absmax[ABS_DISTANCE] = 32;
+
+	input->absmax[ABS_X] = 16704;
+	input->absmax[ABS_Y] = 12064;
+	input->absfuzz[ABS_X] = 4;
+	input->absfuzz[ABS_Y] = 4;
+
+	return 0;
+err_free:
+	kfree(wdata);
+	return ret;
+}
+
+static void wacom_remove(struct hid_device *hdev)
+{
+	hid_hw_stop(hdev);
+	kfree(hid_get_drvdata(hdev));
+}
+
+static const struct hid_device_id wacom_devices[] = {
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
+
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, wacom_devices);
+
+static struct hid_driver wacom_driver = {
+	.name = "wacom",
+	.id_table = wacom_devices,
+	.probe = wacom_probe,
+	.remove = wacom_remove,
+	.raw_event = wacom_raw_event,
+};
+
+static int wacom_init(void)
+{
+	int ret;
+
+	ret = hid_register_driver(&wacom_driver);
+	if (ret)
+		printk(KERN_ERR "can't register wacom driver\n");
+	printk(KERN_ERR "wacom driver registered\n");
+	return ret;
+}
+
+static void wacom_exit(void)
+{
+	hid_unregister_driver(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
+MODULE_LICENSE("GPL");
+
diff -druN linux-libre-2.6.30-gnu/drivers/hid/hid-zpff.c linux-libre-2.6.31-gnu/drivers/hid/hid-zpff.c
--- linux-libre-2.6.30-gnu/drivers/hid/hid-zpff.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/hid-zpff.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 
 #include "hid-ids.h"
 
+#ifdef CONFIG_ZEROPLUS_FF
 #include "usbhid/usbhid.h"
 
 struct zpff_device {
@@ -108,6 +109,12 @@
 
 	return 0;
 }
+#else
+static inline int zpff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
 
 static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/hid/Kconfig linux-libre-2.6.31-gnu/drivers/hid/Kconfig
--- linux-libre-2.6.30-gnu/drivers/hid/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -116,9 +116,16 @@
 	---help---
 	Support for cypress mouse and barcode readers.
 
-config DRAGONRISE_FF
-	tristate "DragonRise Inc. force feedback support"
+config HID_DRAGONRISE
+	tristate "DragonRise Inc. support" if EMBEDDED
 	depends on USB_HID
+	default !EMBEDDED
+	---help---
+	Say Y here if you have DragonRise Inc.game controllers.
+
+config DRAGONRISE_FF
+	bool "DragonRise Inc. force feedback support"
+	depends on HID_DRAGONRISE
 	select INPUT_FF_MEMLESS
 	---help---
 	Say Y here if you want to enable force feedback support for DragonRise Inc.
@@ -160,7 +167,7 @@
 	Support for Logitech devices that are not fully compliant with HID standard.
 
 config LOGITECH_FF
-	bool "Logitech force feedback"
+	bool "Logitech force feedback support"
 	depends on HID_LOGITECH
 	select INPUT_FF_MEMLESS
 	help
@@ -176,7 +183,7 @@
 	  force feedback.
 
 config LOGIRUMBLEPAD2_FF
-	bool "Logitech Rumblepad 2 force feedback"
+	bool "Logitech Rumblepad 2 force feedback support"
 	depends on HID_LOGITECH
 	select INPUT_FF_MEMLESS
 	help
@@ -211,11 +218,19 @@
 	---help---
 	Support for PantherLord/GreenAsia based device support.
 
+config HID_PANTHERLORD
+	tristate "Pantherlord support" if EMBEDDED
+	depends on USB_HID
+	default !EMBEDDED
+	---help---
+	  Say Y here if you have a PantherLord/GreenAsia based game controller
+	  or adapter.
+
 config PANTHERLORD_FF
 	bool "Pantherlord force feedback support"
 	depends on HID_PANTHERLORD
 	select INPUT_FF_MEMLESS
-	help
+	---help---
 	  Say Y here if you have a PantherLord/GreenAsia based game controller
 	  or adapter and want to enable force feedback support for it.
 
@@ -247,15 +262,38 @@
 	---help---
 	Support for Sunplus wireless desktop.
 
-config GREENASIA_FF
-	tristate "GreenAsia (Product ID 0x12) force feedback support"
+config HID_GREENASIA
+	tristate "GreenAsia (Product ID 0x12) support" if EMBEDDED
 	depends on USB_HID
+	default !EMBEDDED
+	---help---
+	  Say Y here if you have a GreenAsia (Product ID 0x12) based game
+	  controller or adapter.
+
+config GREENASIA_FF
+	bool "GreenAsia (Product ID 0x12) force feedback support"
+	depends on HID_GREENASIA
 	select INPUT_FF_MEMLESS
 	---help---
 	Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
 	(like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
 	and want to enable force feedback support for it.
 
+config HID_SMARTJOYPLUS
+	tristate "SmartJoy PLUS PS2/USB adapter support" if EMBEDDED
+	depends on USB_HID
+	default !EMBEDDED
+	---help---
+	Support for SmartJoy PLUS PS2/USB adapter.
+
+config SMARTJOYPLUS_FF
+	bool "SmartJoy PLUS PS2/USB adapter force feedback support"
+	depends on HID_SMARTJOYPLUS
+	select INPUT_FF_MEMLESS
+	---help---
+	Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to
+	enable force feedback support for it.
+
 config HID_TOPSEED
 	tristate "TopSeed Cyberlink remote control support" if EMBEDDED
 	depends on USB_HID
@@ -263,21 +301,45 @@
 	---help---
 	Say Y if you have a TopSeed Cyberlink remote control.
 
-config THRUSTMASTER_FF
-	tristate "ThrustMaster devices support"
+config HID_THRUSTMASTER
+	tristate "ThrustMaster devices support" if EMBEDDED
 	depends on USB_HID
+	default !EMBEDDED
+	---help---
+	  Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
+	  a THRUSTMASTER Ferrari GT Rumble Wheel.
+
+config THRUSTMASTER_FF
+	bool "ThrustMaster devices force feedback support"
+	depends on HID_THRUSTMASTER
 	select INPUT_FF_MEMLESS
-	help
+	---help---
 	  Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
-	  a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
+	  a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel and
+	  want to enable force feedback support for it.
 
-config ZEROPLUS_FF
-	tristate "Zeroplus based game controller support"
+config HID_WACOM
+	tristate "Wacom Bluetooth devices support" if EMBEDDED
+	depends on BT_HIDP
+	default !EMBEDDED
+	---help---
+	Support for Wacom Graphire Bluetooth tablet.
+
+config HID_ZEROPLUS
+	tristate "Zeroplus based game controller support" if EMBEDDED
 	depends on USB_HID
-	select INPUT_FF_MEMLESS
-	help
+	default !EMBEDDED
+	---help---
 	  Say Y here if you have a Zeroplus based game controller.
 
+config ZEROPLUS_FF
+	bool "Zeroplus based game controller force feedback support"
+	depends on HID_ZEROPLUS
+	select INPUT_FF_MEMLESS
+	---help---
+	  Say Y here if you have a Zeroplus based game controller and want
+	  to have force feedback support for it.
+
 endmenu
 
 endif # HID_SUPPORT
diff -druN linux-libre-2.6.30-gnu/drivers/hid/Makefile linux-libre-2.6.31-gnu/drivers/hid/Makefile
--- linux-libre-2.6.30-gnu/drivers/hid/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,7 @@
 obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
-obj-$(CONFIG_DRAGONRISE_FF)	+= hid-drff.o
+obj-$(CONFIG_HID_DRAGONRISE)	+= hid-drff.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_KENSINGTON)	+= hid-kensington.o
@@ -34,12 +34,14 @@
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
+obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
 obj-$(CONFIG_HID_SUNPLUS)	+= hid-sunplus.o
-obj-$(CONFIG_GREENASIA_FF)	+= hid-gaff.o
-obj-$(CONFIG_THRUSTMASTER_FF)	+= hid-tmff.o
+obj-$(CONFIG_HID_GREENASIA)	+= hid-gaff.o
+obj-$(CONFIG_HID_THRUSTMASTER)	+= hid-tmff.o
 obj-$(CONFIG_HID_TOPSEED)	+= hid-topseed.o
-obj-$(CONFIG_ZEROPLUS_FF)	+= hid-zpff.o
+obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
+obj-$(CONFIG_HID_WACOM)		+= hid-wacom.o
 
 obj-$(CONFIG_USB_HID)		+= usbhid/
 obj-$(CONFIG_USB_MOUSE)		+= usbhid/
diff -druN linux-libre-2.6.30-gnu/drivers/hid/usbhid/hid-core.c linux-libre-2.6.31-gnu/drivers/hid/usbhid/hid-core.c
--- linux-libre-2.6.30-gnu/drivers/hid/usbhid/hid-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/usbhid/hid-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,7 +22,6 @@
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
@@ -1234,12 +1233,11 @@
 	struct hid_device *hid = usb_get_intfdata(intf);
 	struct usbhid_device *usbhid = hid->driver_data;
 	int status;
- 
+
 	spin_lock_irq(&usbhid->lock);
 	clear_bit(HID_RESET_PENDING, &usbhid->iofl);
 	spin_unlock_irq(&usbhid->lock);
 	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
-	/* FIXME: Any more reinitialization needed? */
 	status = hid_start_in(hid);
 	if (status < 0)
 		hid_io_error(hid);
@@ -1251,14 +1249,14 @@
 int usbhid_get_power(struct hid_device *hid)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
- 
+
 	return usb_autopm_get_interface(usbhid->intf);
 }
 
 void usbhid_put_power(struct hid_device *hid)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
- 
+
 	usb_autopm_put_interface(usbhid->intf);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/hid/usbhid/hiddev.c linux-libre-2.6.31-gnu/drivers/hid/usbhid/hiddev.c
--- linux-libre-2.6.30-gnu/drivers/hid/usbhid/hiddev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hid/usbhid/hiddev.c	2009-09-09 18:13:59.000000000 -0400
@@ -527,8 +527,10 @@
 			goto goodreturn;
 
 		case HIDIOCGCOLLECTIONINDEX:
+			i = field->usage[uref->usage_index].collection_index;
+			unlock_kernel();
 			kfree(uref_multi);
-			return field->usage[uref->usage_index].collection_index;
+			return i;
 		case HIDIOCGUSAGES:
 			for (i = 0; i < uref_multi->num_values; i++)
 				uref_multi->values[i] =
@@ -850,8 +852,14 @@
 #endif
 };
 
+static char *hiddev_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev));
+}
+
 static struct usb_class_driver hiddev_class = {
 	.name =		"hiddev%d",
+	.nodename =	hiddev_nodename,
 	.fops =		&hiddev_fops,
 	.minor_base =	HIDDEV_MINOR_BASE,
 };
@@ -955,7 +963,6 @@
 	return -ENODEV;
 }
 
-
 static /* const */ struct usb_driver hiddev_driver = {
 	.name =		"hiddev",
 	.probe =	hiddev_usbd_probe,
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/abituguru3.c linux-libre-2.6.31-gnu/drivers/hwmon/abituguru3.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/abituguru3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/abituguru3.c	2009-09-09 18:13:59.000000000 -0400
@@ -357,7 +357,7 @@
 		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0014, NULL /* Abit AB9 Pro, need DMI string */, {
+	{ 0x0014, "AB9", /* + AB9 Pro */ {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -455,7 +455,7 @@
 		{ "AUX3 FAN",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x0018, NULL /* Unknown, need DMI string */, {
+	{ 0x0018, "AB9 QuadGT", {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -564,7 +564,7 @@
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
-	{ 0x001C, NULL /* Unknown, need DMI string */, {
+	{ 0x001C, "IX38 QuadGT", {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/asus_atk0110.c linux-libre-2.6.31-gnu/drivers/hwmon/asus_atk0110.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/asus_atk0110.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/asus_atk0110.c	2009-09-09 18:13:59.000000000 -0400
@@ -593,7 +593,11 @@
 	sensor->data = data;
 	sensor->id = flags->integer.value;
 	sensor->limit1 = limit1->integer.value;
-	sensor->limit2 = limit2->integer.value;
+	if (data->old_interface)
+		sensor->limit2 = limit2->integer.value;
+	else
+		/* The upper limit is expressed as delta from lower limit */
+		sensor->limit2 = sensor->limit1 + limit2->integer.value;
 
 	snprintf(sensor->input_attr_name, ATTR_NAME_SIZE,
 			"%s%d_input", base_name, start + *num);
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/f71882fg.c linux-libre-2.6.31-gnu/drivers/hwmon/f71882fg.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/f71882fg.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/f71882fg.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 /***************************************************************************
  *   Copyright (C) 2006 by Hans Edgington <hans@edgington.nl>              *
- *   Copyright (C) 2007,2008 by Hans de Goede <hdegoede@redhat.com>        *
+ *   Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com>           *
  *                                                                         *
  *   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  *
@@ -32,6 +32,7 @@
 
 #define DRVNAME "f71882fg"
 
+#define SIO_F71858FG_LD_HWM	0x02	/* Hardware monitor logical device */
 #define SIO_F71882FG_LD_HWM	0x04	/* Hardware monitor logical device */
 #define SIO_UNLOCK_KEY		0x87	/* Key to enable Super-I/O */
 #define SIO_LOCK_KEY		0xAA	/* Key to diasble Super-I/O */
@@ -44,6 +45,7 @@
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
 
 #define SIO_FINTEK_ID		0x1934	/* Manufacturers ID */
+#define SIO_F71858_ID		0x0507  /* Chipset ID */
 #define SIO_F71862_ID		0x0601	/* Chipset ID */
 #define SIO_F71882_ID		0x0541	/* Chipset ID */
 #define SIO_F8000_ID		0x0581	/* Chipset ID */
@@ -70,6 +72,7 @@
 #define F71882FG_REG_TEMP_HIGH(nr)	(0x81 + 2 * (nr))
 #define F71882FG_REG_TEMP_STATUS	0x62
 #define F71882FG_REG_TEMP_BEEP		0x63
+#define F71882FG_REG_TEMP_CONFIG	0x69
 #define F71882FG_REG_TEMP_HYST(nr)	(0x6C + (nr))
 #define F71882FG_REG_TEMP_TYPE		0x6B
 #define F71882FG_REG_TEMP_DIODE_OPEN	0x6F
@@ -92,9 +95,10 @@
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-enum chips { f71862fg, f71882fg, f8000 };
+enum chips { f71858fg, f71862fg, f71882fg, f8000 };
 
 static const char *f71882fg_names[] = {
+	"f71858fg",
 	"f71862fg",
 	"f71882fg",
 	"f8000",
@@ -119,6 +123,7 @@
 	struct device *hwmon_dev;
 
 	struct mutex update_lock;
+	int temp_start;			/* temp numbering start (0 or 1) */
 	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 	unsigned long last_limits;	/* In jiffies */
@@ -136,7 +141,7 @@
 	/* Note: all models have only 3 temperature channels, but on some
 	   they are addressed as 0-2 and on others as 1-3, so for coding
 	   convenience we reserve space for 4 channels */
-	u8	temp[4];
+	u16	temp[4];
 	u8	temp_ovt[4];
 	u8	temp_high[4];
 	u8	temp_hyst[2]; /* 2 hysts stored per reg */
@@ -144,6 +149,7 @@
 	u8	temp_status;
 	u8	temp_beep;
 	u8	temp_diode_open;
+	u8	temp_config;
 	u8	pwm[4];
 	u8	pwm_enable;
 	u8	pwm_auto_point_hyst[2];
@@ -247,11 +253,55 @@
 		.name	= DRVNAME,
 	},
 	.probe		= f71882fg_probe,
-	.remove		= __devexit_p(f71882fg_remove),
+	.remove		= f71882fg_remove,
 };
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
+/* Temp and in attr for the f71858fg */
+static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = {
+	SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
+	SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
+	SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
+	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
+	SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
+		store_temp_max, 0, 0),
+	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+		store_temp_max_hyst, 0, 0),
+	SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),
+	SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+		store_temp_crit, 0, 0),
+	SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
+		0, 0),
+	SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
+	SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
+	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
+	SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
+		store_temp_max, 0, 1),
+	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+		store_temp_max_hyst, 0, 1),
+	SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
+	SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+		store_temp_crit, 0, 1),
+	SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
+		0, 1),
+	SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
+	SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
+	SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
+	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
+	SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
+		store_temp_max, 0, 2),
+	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+		store_temp_max_hyst, 0, 2),
+	SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
+	SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+		store_temp_crit, 0, 2),
+	SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
+		0, 2),
+	SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
+	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
+};
+
 /* Temp and in attr common to both the f71862fg and f71882fg */
 static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = {
 	SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
@@ -344,6 +394,7 @@
 	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 0),
 	SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
+	SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
 	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
 	SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 1),
@@ -351,12 +402,14 @@
 		store_temp_max, 0, 1),
 	SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
 	SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
+	SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
 	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
 	SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 2),
 	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 2),
 	SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
+	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
 };
 
 /* Fan / PWM attr common to all models */
@@ -395,6 +448,9 @@
 		      show_pwm_auto_point_channel,
 		      store_pwm_auto_point_channel, 0, 1),
 
+	SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
+	SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+		      store_pwm_enable, 0, 2),
 	SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
 		      show_pwm_interpolate, store_pwm_interpolate, 0, 2),
 	SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
@@ -450,9 +506,6 @@
 	SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
 
-	SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
-	SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
-		      store_pwm_enable, 0, 2),
 	SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
 		      1, 2),
@@ -473,22 +526,8 @@
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
 };
 
-/* Fan / PWM attr for the f71882fg */
-static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
-	SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-		store_fan_beep, 0, 0),
-	SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-		store_fan_beep, 0, 1),
-	SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-		store_fan_beep, 0, 2),
-	SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
-	SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
-		      show_fan_full_speed,
-		      store_fan_full_speed, 0, 3),
-	SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-		store_fan_beep, 0, 3),
-	SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
-
+/* Fan / PWM attr common to both the f71882fg and f71858fg */
+static struct sensor_device_attribute_2 f71882fg_f71858fg_fan_attr[] = {
 	SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
 		      0, 0),
@@ -565,9 +604,6 @@
 	SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
 
-	SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
-	SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
-		      store_pwm_enable, 0, 2),
 	SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
 		      0, 2),
@@ -605,6 +641,24 @@
 		      show_pwm_auto_point_temp_hyst, NULL, 2, 2),
 	SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
+};
+
+/* Fan / PWM attr found on the f71882fg but not on the f71858fg */
+static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
+	SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+		store_fan_beep, 0, 0),
+	SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+		store_fan_beep, 0, 1),
+	SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+		store_fan_beep, 0, 2),
+
+	SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
+	SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
+		      show_fan_full_speed,
+		      store_fan_full_speed, 0, 3),
+	SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+		store_fan_beep, 0, 3),
+	SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
 
 	SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
 	SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
@@ -659,8 +713,6 @@
 static struct sensor_device_attribute_2 f8000_fan_attr[] = {
 	SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
 
-	SENSOR_ATTR_2(pwm3, S_IRUGO, show_pwm, NULL, 0, 2),
-
 	SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
 		      0, 2),
@@ -857,13 +909,20 @@
 	outb(val & 255, data->addr + DATA_REG_OFFSET);
 }
 
+static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
+{
+	if (data->type == f71858fg)
+		return f71882fg_read16(data, F71882FG_REG_TEMP(nr));
+	else
+		return f71882fg_read8(data, F71882FG_REG_TEMP(nr));
+}
+
 static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 {
 	struct f71882fg_data *data = dev_get_drvdata(dev);
 	int nr, reg = 0, reg2;
 	int nr_fans = (data->type == f71882fg) ? 4 : 3;
-	int nr_ins = (data->type == f8000) ? 3 : 9;
-	int temp_start = (data->type == f8000) ? 0 : 1;
+	int nr_ins = (data->type == f71858fg || data->type == f8000) ? 3 : 9;
 
 	mutex_lock(&data->update_lock);
 
@@ -878,7 +937,7 @@
 		}
 
 		/* Get High & boundary temps*/
-		for (nr = temp_start; nr < 3 + temp_start; nr++) {
+		for (nr = data->temp_start; nr < 3 + data->temp_start; nr++) {
 			data->temp_ovt[nr] = f71882fg_read8(data,
 						F71882FG_REG_TEMP_OVT(nr));
 			data->temp_high[nr] = f71882fg_read8(data,
@@ -886,14 +945,17 @@
 		}
 
 		if (data->type != f8000) {
-			data->fan_beep = f71882fg_read8(data,
-						F71882FG_REG_FAN_BEEP);
-			data->temp_beep = f71882fg_read8(data,
-						F71882FG_REG_TEMP_BEEP);
 			data->temp_hyst[0] = f71882fg_read8(data,
 						F71882FG_REG_TEMP_HYST(0));
 			data->temp_hyst[1] = f71882fg_read8(data,
 						F71882FG_REG_TEMP_HYST(1));
+		}
+
+		if (data->type == f71862fg || data->type == f71882fg) {
+			data->fan_beep = f71882fg_read8(data,
+						F71882FG_REG_FAN_BEEP);
+			data->temp_beep = f71882fg_read8(data,
+						F71882FG_REG_TEMP_BEEP);
 			/* Have to hardcode type, because temp1 is special */
 			reg  = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
 			data->temp_type[2] = (reg & 0x04) ? 2 : 4;
@@ -904,10 +966,10 @@
 			data->temp_type[1] = 6 /* PECI */;
 		else if ((reg2 & 0x03) == 0x02)
 			data->temp_type[1] = 5 /* AMDSI */;
-		else if (data->type != f8000)
+		else if (data->type == f71862fg || data->type == f71882fg)
 			data->temp_type[1] = (reg & 0x02) ? 2 : 4;
 		else
-			data->temp_type[1] = 2; /* F8000 only supports BJT */
+			data->temp_type[1] = 2; /* Only supports BJT */
 
 		data->pwm_enable = f71882fg_read8(data,
 						  F71882FG_REG_PWM_ENABLE);
@@ -963,9 +1025,8 @@
 						F71882FG_REG_TEMP_STATUS);
 		data->temp_diode_open = f71882fg_read8(data,
 						F71882FG_REG_TEMP_DIODE_OPEN);
-		for (nr = temp_start; nr < 3 + temp_start; nr++)
-			data->temp[nr] = f71882fg_read8(data,
-						F71882FG_REG_TEMP(nr));
+		for (nr = data->temp_start; nr < 3 + data->temp_start; nr++)
+			data->temp[nr] = f71882fg_read_temp(data, nr);
 
 		data->fan_status = f71882fg_read8(data,
 						F71882FG_REG_FAN_STATUS);
@@ -1168,8 +1229,24 @@
 {
 	struct f71882fg_data *data = f71882fg_update_device(dev);
 	int nr = to_sensor_dev_attr_2(devattr)->index;
+	int sign, temp;
 
-	return sprintf(buf, "%d\n", data->temp[nr] * 1000);
+	if (data->type == f71858fg) {
+		/* TEMP_TABLE_SEL 1 or 3 ? */
+		if (data->temp_config & 1) {
+			sign = data->temp[nr] & 0x0001;
+			temp = (data->temp[nr] >> 5) & 0x7ff;
+		} else {
+			sign = data->temp[nr] & 0x8000;
+			temp = (data->temp[nr] >> 5) & 0x3ff;
+		}
+		temp *= 125;
+		if (sign)
+			temp -= 128000;
+	} else
+		temp = data->temp[nr] * 1000;
+
+	return sprintf(buf, "%d\n", temp);
 }
 
 static ssize_t show_temp_max(struct device *dev, struct device_attribute
@@ -1440,6 +1517,10 @@
 	int nr = to_sensor_dev_attr_2(devattr)->index;
 	long val = simple_strtol(buf, NULL, 10);
 
+	/* Special case for F8000 pwm channel 3 which only does auto mode */
+	if (data->type == f8000 && nr == 2 && val != 2)
+		return -EINVAL;
+
 	mutex_lock(&data->update_lock);
 	data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
 	/* Special case for F8000 auto PWM mode / Thermostat mode */
@@ -1458,6 +1539,12 @@
 	} else {
 		switch (val) {
 		case 1:
+			/* The f71858fg does not support manual RPM mode */
+			if (data->type == f71858fg &&
+			    ((data->pwm_enable >> (2 * nr)) & 1)) {
+				count = -EINVAL;
+				goto leave;
+			}
 			data->pwm_enable |= 2 << (2 * nr);
 			break;		/* Manual */
 		case 2:
@@ -1616,9 +1703,9 @@
 	int result;
 	struct f71882fg_data *data = f71882fg_update_device(dev);
 	int nr = to_sensor_dev_attr_2(devattr)->index;
-	int temp_start = (data->type == f8000) ? 0 : 1;
 
-	result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - temp_start);
+	result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) -
+		       data->temp_start);
 
 	return sprintf(buf, "%d\n", result);
 }
@@ -1629,7 +1716,6 @@
 {
 	struct f71882fg_data *data = dev_get_drvdata(dev);
 	int nr = to_sensor_dev_attr_2(devattr)->index;
-	int temp_start = (data->type == f8000) ? 0 : 1;
 	long val = simple_strtol(buf, NULL, 10);
 
 	switch (val) {
@@ -1645,7 +1731,7 @@
 	default:
 		return -EINVAL;
 	}
-	val += temp_start;
+	val += data->temp_start;
 	mutex_lock(&data->update_lock);
 	data->pwm_auto_point_mapping[nr] =
 		f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
@@ -1721,6 +1807,8 @@
 
 	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
 	data->type = sio_data->type;
+	data->temp_start =
+	    (data->type == f71858fg || data->type == f8000) ? 0 : 1;
 	mutex_init(&data->update_lock);
 	platform_set_drvdata(pdev, data);
 
@@ -1736,19 +1824,6 @@
 		goto exit_free;
 	}
 
-	data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
-	/* If it is a 71862 and the fan / pwm part is enabled sanity check
-	   the pwm settings */
-	if (data->type == f71862fg && (start_reg & 0x02)) {
-		if ((data->pwm_enable & 0x15) != 0x15) {
-			dev_err(&pdev->dev,
-				"Invalid (reserved) pwm settings: 0x%02x\n",
-				(unsigned int)data->pwm_enable);
-			err = -ENODEV;
-			goto exit_free;
-		}
-	}
-
 	/* Register sysfs interface files */
 	err = device_create_file(&pdev->dev, &dev_attr_name);
 	if (err)
@@ -1756,6 +1831,20 @@
 
 	if (start_reg & 0x01) {
 		switch (data->type) {
+		case f71858fg:
+			data->temp_config =
+				f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG);
+			if (data->temp_config & 0x10)
+				/* The f71858fg temperature alarms behave as
+				   the f8000 alarms in this mode */
+				err = f71882fg_create_sysfs_files(pdev,
+					f8000_in_temp_attr,
+					ARRAY_SIZE(f8000_in_temp_attr));
+			else
+				err = f71882fg_create_sysfs_files(pdev,
+					f71858fg_in_temp_attr,
+					ARRAY_SIZE(f71858fg_in_temp_attr));
+			break;
 		case f71882fg:
 			err = f71882fg_create_sysfs_files(pdev,
 					f71882fg_in_temp_attr,
@@ -1779,6 +1868,35 @@
 	}
 
 	if (start_reg & 0x02) {
+		data->pwm_enable =
+			f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
+
+		/* Sanity check the pwm settings */
+		switch (data->type) {
+		case f71858fg:
+			err = 0;
+			for (i = 0; i < nr_fans; i++)
+				if (((data->pwm_enable >> (i * 2)) & 3) == 3)
+					err = 1;
+			break;
+		case f71862fg:
+			err = (data->pwm_enable & 0x15) != 0x15;
+			break;
+		case f71882fg:
+			err = 0;
+			break;
+		case f8000:
+			err = data->pwm_enable & 0x20;
+			break;
+		}
+		if (err) {
+			dev_err(&pdev->dev,
+				"Invalid (reserved) pwm settings: 0x%02x\n",
+				(unsigned int)data->pwm_enable);
+			err = -ENODEV;
+			goto exit_unregister_sysfs;
+		}
+
 		err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr,
 					ARRAY_SIZE(fxxxx_fan_attr));
 		if (err)
@@ -1794,6 +1912,13 @@
 			err = f71882fg_create_sysfs_files(pdev,
 					f71882fg_fan_attr,
 					ARRAY_SIZE(f71882fg_fan_attr));
+			if (err)
+				goto exit_unregister_sysfs;
+			/* fall through! */
+		case f71858fg:
+			err = f71882fg_create_sysfs_files(pdev,
+					f71882fg_f71858fg_fan_attr,
+					ARRAY_SIZE(f71882fg_f71858fg_fan_attr));
 			break;
 		case f8000:
 			err = f71882fg_create_sysfs_files(pdev,
@@ -1878,6 +2003,9 @@
 
 	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
 	switch (devid) {
+	case SIO_F71858_ID:
+		sio_data->type = f71858fg;
+		break;
 	case SIO_F71862_ID:
 		sio_data->type = f71862fg;
 		break;
@@ -1892,7 +2020,11 @@
 		goto exit;
 	}
 
-	superio_select(sioaddr, SIO_F71882FG_LD_HWM);
+	if (sio_data->type == f71858fg)
+		superio_select(sioaddr, SIO_F71858FG_LD_HWM);
+	else
+		superio_select(sioaddr, SIO_F71882FG_LD_HWM);
+
 	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
 		printk(KERN_WARNING DRVNAME ": Device not activated\n");
 		goto exit;
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/hp_accel.c linux-libre-2.6.31-gnu/drivers/hwmon/hp_accel.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/hp_accel.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/hp_accel.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,9 +27,6 @@
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/kthread.h>
-#include <linux/semaphore.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
@@ -161,6 +158,7 @@
 static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
 static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
 static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
+static struct axis_conversion lis3lv02d_axis_xy_swap = {2, 1, 3};
 static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
 static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
 static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
@@ -194,13 +192,16 @@
 	AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
 	AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
 	AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
+	AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
 	AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
 	AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
 	AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
 	AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
 	AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
 	AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
-	AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
+	AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
+	AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
+	AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
 	/* Intel-based HP Pavilion dv5 */
 	AXIS_DMI_MATCH2("HPDV5_I",
 			PRODUCT_NAME, "HP Pavilion dv5",
@@ -216,7 +217,6 @@
 	{ NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
- * HP Compaq 8710x Notebook PC / Mobile Workstation
  * "NC2400" "HP Compaq nc2400"
  * "NX74x0" "HP Compaq nx74"
  * "NX6325" "HP Compaq nx6325"
@@ -324,7 +324,7 @@
 	flush_work(&hpled_led.work);
 	led_classdev_unregister(&hpled_led.led_classdev);
 
-	return lis3lv02d_remove_fs();
+	return lis3lv02d_remove_fs(&lis3_dev);
 }
 
 
@@ -338,13 +338,7 @@
 
 static int lis3lv02d_resume(struct acpi_device *device)
 {
-	/* put back the device in the right state (ACPI might turn it on) */
-	mutex_lock(&lis3_dev.lock);
-	if (lis3_dev.usage > 0)
-		lis3lv02d_poweron(&lis3_dev);
-	else
-		lis3lv02d_poweroff(&lis3_dev);
-	mutex_unlock(&lis3_dev.lock);
+	lis3lv02d_poweron(&lis3_dev);
 	return 0;
 }
 #else
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/hwmon.c linux-libre-2.6.31-gnu/drivers/hwmon/hwmon.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/hwmon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/hwmon.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/hwmon.h>
 #include <linux/gfp.h>
 #include <linux/spinlock.h>
+#include <linux/pci.h>
 
 #define HWMON_ID_PREFIX "hwmon"
 #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
@@ -86,8 +87,36 @@
 			"hwmon_device_unregister() failed: bad class ID!\n");
 }
 
+static void __init hwmon_pci_quirks(void)
+{
+#if defined CONFIG_X86 && defined CONFIG_PCI
+	struct pci_dev *sb;
+	u16 base;
+	u8 enable;
+
+	/* Open access to 0x295-0x296 on MSI MS-7031 */
+	sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL);
+	if (sb &&
+	    (sb->subsystem_vendor == 0x1462 &&	/* MSI */
+	     sb->subsystem_device == 0x0031)) {	/* MS-7031 */
+
+		pci_read_config_byte(sb, 0x48, &enable);
+		pci_read_config_word(sb, 0x64, &base);
+
+		if (base == 0 && !(enable & BIT(2))) {
+			dev_info(&sb->dev,
+				 "Opening wide generic port at 0x295\n");
+			pci_write_config_word(sb, 0x64, 0x295);
+			pci_write_config_byte(sb, 0x48, enable | BIT(2));
+		}
+	}
+#endif
+}
+
 static int __init hwmon_init(void)
 {
+	hwmon_pci_quirks();
+
 	hwmon_class = class_create(THIS_MODULE, "hwmon");
 	if (IS_ERR(hwmon_class)) {
 		printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/ibmaem.c linux-libre-2.6.31-gnu/drivers/hwmon/ibmaem.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/ibmaem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/ibmaem.c	2009-09-09 18:13:59.000000000 -0400
@@ -1127,3 +1127,4 @@
 MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*");
 MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*");
 MODULE_ALIAS("dmi:bvnIBM:*:pnIBM3850M2/x3950M2-*");
+MODULE_ALIAS("dmi:bvnIBM:*:pnIBMBladeHC10-*");
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/Kconfig linux-libre-2.6.31-gnu/drivers/hwmon/Kconfig
--- linux-libre-2.6.30-gnu/drivers/hwmon/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -306,11 +306,11 @@
 	  will be called f71805f.
 
 config SENSORS_F71882FG
-	tristate "Fintek F71862FG, F71882FG and F8000"
+	tristate "Fintek F71858FG, F71862FG, F71882FG and F8000"
 	depends on EXPERIMENTAL
 	help
 	  If you say yes here you get support for hardware monitoring
-	  features of the Fintek F71882FG/F71883FG, F71862FG/71863FG
+	  features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG
 	  and F8000 Super-I/O chips.
 
 	  This driver can also be built as a module.  If so, the module
@@ -418,7 +418,7 @@
 	  power sensors and capping hardware in various IBM System X
 	  servers that support Active Energy Manager.  This includes
 	  the x3350, x3550, x3650, x3655, x3755, x3850 M2, x3950 M2,
-	  and certain HS2x/LS2x/QS2x blades.
+	  and certain HC10/HS2x/LS2x/QS2x blades.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called ibmaem.
@@ -787,6 +787,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called thmc50.
 
+config SENSORS_TMP401
+	tristate "Texas Instruments TMP401 and compatibles"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for Texas Instruments TMP401 and
+	  TMP411 temperature sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tmp401.
+
 config SENSORS_VIA686A
 	tristate "VIA686A"
 	depends on PCI
@@ -940,6 +950,7 @@
 config SENSORS_LIS3LV02D
 	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
 	depends on ACPI && INPUT
+	select INPUT_POLLDEV
 	select NEW_LEDS
 	select LEDS_CLASS
 	default n
@@ -967,6 +978,7 @@
 config SENSORS_LIS3_SPI
 	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
 	depends on !ACPI && SPI_MASTER && INPUT
+	select INPUT_POLLDEV
 	default n
 	help
 	  This driver provides support for the LIS3LV02Dx accelerometer connected
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/lis3lv02d.c linux-libre-2.6.31-gnu/drivers/hwmon/lis3lv02d.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/lis3lv02d.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/lis3lv02d.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,9 +27,7 @@
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/kthread.h>
-#include <linux/semaphore.h>
+#include <linux/input-polldev.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
@@ -105,56 +103,39 @@
 {
 	int position[3];
 
-	position[0] = lis3_dev.read_data(lis3, OUTX);
-	position[1] = lis3_dev.read_data(lis3, OUTY);
-	position[2] = lis3_dev.read_data(lis3, OUTZ);
+	position[0] = lis3->read_data(lis3, OUTX);
+	position[1] = lis3->read_data(lis3, OUTY);
+	position[2] = lis3->read_data(lis3, OUTZ);
 
-	*x = lis3lv02d_get_axis(lis3_dev.ac.x, position);
-	*y = lis3lv02d_get_axis(lis3_dev.ac.y, position);
-	*z = lis3lv02d_get_axis(lis3_dev.ac.z, position);
+	*x = lis3lv02d_get_axis(lis3->ac.x, position);
+	*y = lis3lv02d_get_axis(lis3->ac.y, position);
+	*z = lis3lv02d_get_axis(lis3->ac.z, position);
 }
 
 void lis3lv02d_poweroff(struct lis3lv02d *lis3)
 {
-	lis3_dev.is_on = 0;
+	/* disable X,Y,Z axis and power down */
+	lis3->write(lis3, CTRL_REG1, 0x00);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
 
 void lis3lv02d_poweron(struct lis3lv02d *lis3)
 {
-	lis3_dev.is_on = 1;
-	lis3_dev.init(lis3);
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
+	u8 reg;
 
-/*
- * To be called before starting to use the device. It makes sure that the
- * device will always be on until a call to lis3lv02d_decrease_use(). Not to be
- * used from interrupt context.
- */
-static void lis3lv02d_increase_use(struct lis3lv02d *dev)
-{
-	mutex_lock(&dev->lock);
-	dev->usage++;
-	if (dev->usage == 1) {
-		if (!dev->is_on)
-			lis3lv02d_poweron(dev);
-	}
-	mutex_unlock(&dev->lock);
-}
+	lis3->init(lis3);
 
-/*
- * To be called whenever a usage of the device is stopped.
- * It will make sure to turn off the device when there is not usage.
- */
-static void lis3lv02d_decrease_use(struct lis3lv02d *dev)
-{
-	mutex_lock(&dev->lock);
-	dev->usage--;
-	if (dev->usage == 0)
-		lis3lv02d_poweroff(dev);
-	mutex_unlock(&dev->lock);
+	/*
+	 * Common configuration
+	 * BDU: LSB and MSB values are not updated until both have been read.
+	 *      So the value read will always be correct.
+	 */
+	lis3->read(lis3, CTRL_REG2, &reg);
+	reg |= CTRL2_BDU;
+	lis3->write(lis3, CTRL_REG2, reg);
 }
+EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
+
 
 static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
 {
@@ -198,15 +179,12 @@
 		printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq);
 		return -EBUSY;
 	}
-	lis3lv02d_increase_use(&lis3_dev);
-	printk("lis3: registered interrupt %d\n", lis3_dev.irq);
 	return 0;
 }
 
 static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
 {
 	fasync_helper(-1, file, 0, &lis3_dev.async_queue);
-	lis3lv02d_decrease_use(&lis3_dev);
 	free_irq(lis3_dev.irq, &lis3_dev);
 	clear_bit(0, &lis3_dev.misc_opened); /* release the device */
 	return 0;
@@ -290,46 +268,16 @@
 	.fops    = &lis3lv02d_misc_fops,
 };
 
-/**
- * lis3lv02d_joystick_kthread - Kthread polling function
- * @data: unused - here to conform to threadfn prototype
- */
-static int lis3lv02d_joystick_kthread(void *data)
+static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
 {
 	int x, y, z;
 
-	while (!kthread_should_stop()) {
-		lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-		input_report_abs(lis3_dev.idev, ABS_X, x - lis3_dev.xcalib);
-		input_report_abs(lis3_dev.idev, ABS_Y, y - lis3_dev.ycalib);
-		input_report_abs(lis3_dev.idev, ABS_Z, z - lis3_dev.zcalib);
-
-		input_sync(lis3_dev.idev);
-
-		try_to_freeze();
-		msleep_interruptible(MDPS_POLL_INTERVAL);
-	}
-
-	return 0;
-}
-
-static int lis3lv02d_joystick_open(struct input_dev *input)
-{
-	lis3lv02d_increase_use(&lis3_dev);
-	lis3_dev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d");
-	if (IS_ERR(lis3_dev.kthread)) {
-		lis3lv02d_decrease_use(&lis3_dev);
-		return PTR_ERR(lis3_dev.kthread);
-	}
-
-	return 0;
+	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+	input_report_abs(pidev->input, ABS_X, x - lis3_dev.xcalib);
+	input_report_abs(pidev->input, ABS_Y, y - lis3_dev.ycalib);
+	input_report_abs(pidev->input, ABS_Z, z - lis3_dev.zcalib);
 }
 
-static void lis3lv02d_joystick_close(struct input_dev *input)
-{
-	kthread_stop(lis3_dev.kthread);
-	lis3lv02d_decrease_use(&lis3_dev);
-}
 
 static inline void lis3lv02d_calibrate_joystick(void)
 {
@@ -339,33 +287,36 @@
 
 int lis3lv02d_joystick_enable(void)
 {
+	struct input_dev *input_dev;
 	int err;
 
 	if (lis3_dev.idev)
 		return -EINVAL;
 
-	lis3_dev.idev = input_allocate_device();
+	lis3_dev.idev = input_allocate_polled_device();
 	if (!lis3_dev.idev)
 		return -ENOMEM;
 
+	lis3_dev.idev->poll = lis3lv02d_joystick_poll;
+	lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
+	input_dev = lis3_dev.idev->input;
+
 	lis3lv02d_calibrate_joystick();
 
-	lis3_dev.idev->name       = "ST LIS3LV02DL Accelerometer";
-	lis3_dev.idev->phys       = DRIVER_NAME "/input0";
-	lis3_dev.idev->id.bustype = BUS_HOST;
-	lis3_dev.idev->id.vendor  = 0;
-	lis3_dev.idev->dev.parent = &lis3_dev.pdev->dev;
-	lis3_dev.idev->open       = lis3lv02d_joystick_open;
-	lis3_dev.idev->close      = lis3lv02d_joystick_close;
+	input_dev->name       = "ST LIS3LV02DL Accelerometer";
+	input_dev->phys       = DRIVER_NAME "/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor  = 0;
+	input_dev->dev.parent = &lis3_dev.pdev->dev;
 
-	set_bit(EV_ABS, lis3_dev.idev->evbit);
-	input_set_abs_params(lis3_dev.idev, ABS_X, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
-	input_set_abs_params(lis3_dev.idev, ABS_Y, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
-	input_set_abs_params(lis3_dev.idev, ABS_Z, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
+	set_bit(EV_ABS, input_dev->evbit);
+	input_set_abs_params(input_dev, ABS_X, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
+	input_set_abs_params(input_dev, ABS_Y, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
+	input_set_abs_params(input_dev, ABS_Z, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3);
 
-	err = input_register_device(lis3_dev.idev);
+	err = input_register_polled_device(lis3_dev.idev);
 	if (err) {
-		input_free_device(lis3_dev.idev);
+		input_free_polled_device(lis3_dev.idev);
 		lis3_dev.idev = NULL;
 	}
 
@@ -378,8 +329,9 @@
 	if (!lis3_dev.idev)
 		return;
 
-	misc_deregister(&lis3lv02d_misc_device);
-	input_unregister_device(lis3_dev.idev);
+	if (lis3_dev.irq)
+		misc_deregister(&lis3lv02d_misc_device);
+	input_unregister_polled_device(lis3_dev.idev);
 	lis3_dev.idev = NULL;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
@@ -390,9 +342,7 @@
 {
 	int x, y, z;
 
-	lis3lv02d_increase_use(&lis3_dev);
 	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-	lis3lv02d_decrease_use(&lis3_dev);
 	return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
 }
 
@@ -406,9 +356,7 @@
 				struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	lis3lv02d_increase_use(&lis3_dev);
 	lis3lv02d_calibrate_joystick();
-	lis3lv02d_decrease_use(&lis3_dev);
 	return count;
 }
 
@@ -420,9 +368,7 @@
 	u8 ctrl;
 	int val;
 
-	lis3lv02d_increase_use(&lis3_dev);
 	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-	lis3lv02d_decrease_use(&lis3_dev);
 	val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4;
 	return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]);
 }
@@ -446,17 +392,17 @@
 
 static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
 {
-	lis3_dev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
-	if (IS_ERR(lis3_dev.pdev))
-		return PTR_ERR(lis3_dev.pdev);
+	lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+	if (IS_ERR(lis3->pdev))
+		return PTR_ERR(lis3->pdev);
 
-	return sysfs_create_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group);
+	return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
 }
 
-int lis3lv02d_remove_fs(void)
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
 {
-	sysfs_remove_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group);
-	platform_device_unregister(lis3_dev.pdev);
+	sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
+	platform_device_unregister(lis3->pdev);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
@@ -482,18 +428,35 @@
 		break;
 	default:
 		printk(KERN_ERR DRIVER_NAME
-			": unknown sensor type 0x%X\n", lis3_dev.whoami);
+			": unknown sensor type 0x%X\n", dev->whoami);
 		return -EINVAL;
 	}
 
-	mutex_init(&dev->lock);
 	lis3lv02d_add_fs(dev);
-	lis3lv02d_increase_use(dev);
+	lis3lv02d_poweron(dev);
 
 	if (lis3lv02d_joystick_enable())
 		printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
 
-	printk("lis3_init_device: irq %d\n", dev->irq);
+	/* passing in platform specific data is purely optional and only
+	 * used by the SPI transport layer at the moment */
+	if (dev->pdata) {
+		struct lis3lv02d_platform_data *p = dev->pdata;
+
+		if (p->click_flags && (dev->whoami == LIS_SINGLE_ID)) {
+			dev->write(dev, CLICK_CFG, p->click_flags);
+			dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
+			dev->write(dev, CLICK_LATENCY, p->click_latency);
+			dev->write(dev, CLICK_WINDOW, p->click_window);
+			dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
+			dev->write(dev, CLICK_THSY_X,
+					(p->click_thresh_x & 0xf) |
+					(p->click_thresh_y << 4));
+		}
+
+		if (p->irq_cfg)
+			dev->write(dev, CTRL_REG3, p->irq_cfg);
+	}
 
 	/* bail if we did not get an IRQ from the bus layer */
 	if (!dev->irq) {
@@ -502,11 +465,9 @@
 		goto out;
 	}
 
-	printk("lis3: registering device\n");
 	if (misc_register(&lis3lv02d_misc_device))
 		printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
 out:
-	lis3lv02d_decrease_use(dev);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/lis3lv02d.h linux-libre-2.6.31-gnu/drivers/hwmon/lis3lv02d.h
--- linux-libre-2.6.30-gnu/drivers/hwmon/lis3lv02d.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/lis3lv02d.h	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,8 @@
  *  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/platform_device.h>
+#include <linux/input-polldev.h>
 
 /*
  * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
@@ -27,12 +29,14 @@
  * They can also be connected via I²C.
  */
 
+#include <linux/lis3lv02d.h>
+
 /* 2-byte registers */
 #define LIS_DOUBLE_ID	0x3A /* LIS3LV02D[LQ] */
 /* 1-byte registers */
 #define LIS_SINGLE_ID	0x3B /* LIS[32]02DL and others */
 
-enum lis3lv02d_reg {
+enum lis3_reg {
 	WHO_AM_I	= 0x0F,
 	OFFSET_X	= 0x16,
 	OFFSET_Y	= 0x17,
@@ -60,6 +64,19 @@
 	FF_WU_THS_L	= 0x34,
 	FF_WU_THS_H	= 0x35,
 	FF_WU_DURATION	= 0x36,
+};
+
+enum lis302d_reg {
+	CLICK_CFG	= 0x38,
+	CLICK_SRC	= 0x39,
+	CLICK_THSY_X	= 0x3B,
+	CLICK_THSZ	= 0x3C,
+	CLICK_TIMELIMIT	= 0x3D,
+	CLICK_LATENCY	= 0x3E,
+	CLICK_WINDOW	= 0x3F,
+};
+
+enum lis3lv02d_reg {
 	DD_CFG		= 0x38,
 	DD_SRC		= 0x39,
 	DD_ACK		= 0x3A,
@@ -169,22 +186,20 @@
 	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
 	int			mdps_max_val;
 
-	struct input_dev	*idev;     /* input device */
-	struct task_struct	*kthread;  /* kthread for input */
-	struct mutex            lock;
+	struct input_polled_dev	*idev;     /* input device */
 	struct platform_device	*pdev;     /* platform device */
 	atomic_t		count;     /* interrupt count after last read */
 	int			xcalib;    /* calibrated null value for x */
 	int			ycalib;    /* calibrated null value for y */
 	int			zcalib;    /* calibrated null value for z */
-	unsigned char		is_on;     /* whether the device is on or off */
-	unsigned char		usage;     /* usage counter */
 	struct axis_conversion	ac;        /* hw -> logical axis */
 
 	u32			irq;       /* IRQ number */
 	struct fasync_struct	*async_queue; /* queue for the misc device */
 	wait_queue_head_t	misc_wait; /* Wait queue for the misc device */
 	unsigned long		misc_opened; /* bit0: whether the device is open */
+
+	struct lis3lv02d_platform_data *pdata;	/* for passing board config */
 };
 
 int lis3lv02d_init_device(struct lis3lv02d *lis3);
@@ -192,6 +207,6 @@
 void lis3lv02d_joystick_disable(void);
 void lis3lv02d_poweroff(struct lis3lv02d *lis3);
 void lis3lv02d_poweron(struct lis3lv02d *lis3);
-int lis3lv02d_remove_fs(void);
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
 
 extern struct lis3lv02d lis3_dev;
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/lis3lv02d_spi.c linux-libre-2.6.31-gnu/drivers/hwmon/lis3lv02d_spi.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/lis3lv02d_spi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/lis3lv02d_spi.c	2009-09-09 18:13:59.000000000 -0400
@@ -72,6 +72,7 @@
 	lis3_dev.write = lis3_spi_write;
 	lis3_dev.irq = spi->irq;
 	lis3_dev.ac = lis3lv02d_axis_normal;
+	lis3_dev.pdata = spi->dev.platform_data;
 	spi_set_drvdata(spi, &lis3_dev);
 
 	ret = lis3lv02d_init_device(&lis3_dev);
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/Makefile linux-libre-2.6.31-gnu/drivers/hwmon/Makefile
--- linux-libre-2.6.30-gnu/drivers/hwmon/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -82,6 +82,7 @@
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
+obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/max6650.c linux-libre-2.6.31-gnu/drivers/hwmon/max6650.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/max6650.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/max6650.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,7 +12,7 @@
  * also work with the MAX6651. It does not distinguish max6650 and max6651
  * chips.
  *
- * Tha datasheet was last seen at:
+ * The datasheet was last seen at:
  *
  *        http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
  *
@@ -98,6 +98,16 @@
 #define MAX6650_CFG_MODE_OPEN_LOOP	0x30
 #define MAX6650_COUNT_MASK		0x03
 
+/*
+ * Alarm status register bits
+ */
+
+#define MAX6650_ALRM_MAX	0x01
+#define MAX6650_ALRM_MIN	0x02
+#define MAX6650_ALRM_TACH	0x04
+#define MAX6650_ALRM_GPIO1	0x08
+#define MAX6650_ALRM_GPIO2	0x10
+
 /* Minimum and maximum values of the FAN-RPM */
 #define FAN_RPM_MIN 240
 #define FAN_RPM_MAX 30000
@@ -151,6 +161,7 @@
 	u8 tach[4];
 	u8 count;
 	u8 dac;
+	u8 alarm;
 };
 
 static ssize_t get_fan(struct device *dev, struct device_attribute *devattr,
@@ -407,6 +418,7 @@
 		data->count = 3;
 		break;
 	default:
+		mutex_unlock(&data->update_lock);
 		dev_err(&client->dev,
 			"illegal value for fan divider (%d)\n", div);
 		return -EINVAL;
@@ -418,6 +430,33 @@
 	return count;
 }
 
+/*
+ * Get alarm stati:
+ * Possible values:
+ * 0 = no alarm
+ * 1 = alarm
+ */
+
+static ssize_t get_alarm(struct device *dev, struct device_attribute *devattr,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct max6650_data *data = max6650_update_device(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	int alarm = 0;
+
+	if (data->alarm & attr->index) {
+		mutex_lock(&data->update_lock);
+		alarm = 1;
+		data->alarm &= ~attr->index;
+		data->alarm |= i2c_smbus_read_byte_data(client,
+							MAX6650_REG_ALARM);
+		mutex_unlock(&data->update_lock);
+	}
+
+	return sprintf(buf, "%d\n", alarm);
+}
+
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1);
 static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2);
@@ -426,7 +465,41 @@
 static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div);
 static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable);
 static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm);
+static SENSOR_DEVICE_ATTR(fan1_max_alarm, S_IRUGO, get_alarm, NULL,
+			  MAX6650_ALRM_MAX);
+static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, get_alarm, NULL,
+			  MAX6650_ALRM_MIN);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_alarm, NULL,
+			  MAX6650_ALRM_TACH);
+static SENSOR_DEVICE_ATTR(gpio1_alarm, S_IRUGO, get_alarm, NULL,
+			  MAX6650_ALRM_GPIO1);
+static SENSOR_DEVICE_ATTR(gpio2_alarm, S_IRUGO, get_alarm, NULL,
+			  MAX6650_ALRM_GPIO2);
+
+static mode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a,
+				    int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 alarm_en = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN);
+	struct device_attribute *devattr;
 
+	/*
+	 * Hide the alarms that have not been enabled by the firmware
+	 */
+
+	devattr = container_of(a, struct device_attribute, attr);
+	if (devattr == &sensor_dev_attr_fan1_max_alarm.dev_attr
+	 || devattr == &sensor_dev_attr_fan1_min_alarm.dev_attr
+	 || devattr == &sensor_dev_attr_fan1_fault.dev_attr
+	 || devattr == &sensor_dev_attr_gpio1_alarm.dev_attr
+	 || devattr == &sensor_dev_attr_gpio2_alarm.dev_attr) {
+		if (!(alarm_en & to_sensor_dev_attr(devattr)->index))
+			return 0;
+	}
+
+	return a->mode;
+}
 
 static struct attribute *max6650_attrs[] = {
 	&sensor_dev_attr_fan1_input.dev_attr.attr,
@@ -437,11 +510,17 @@
 	&dev_attr_fan1_div.attr,
 	&dev_attr_pwm1_enable.attr,
 	&dev_attr_pwm1.attr,
+	&sensor_dev_attr_fan1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_fault.dev_attr.attr,
+	&sensor_dev_attr_gpio1_alarm.dev_attr.attr,
+	&sensor_dev_attr_gpio2_alarm.dev_attr.attr,
 	NULL
 };
 
 static struct attribute_group max6650_attr_grp = {
 	.attrs = max6650_attrs,
+	.is_visible = max6650_attrs_visible,
 };
 
 /*
@@ -659,6 +738,12 @@
 							MAX6650_REG_COUNT);
 		data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC);
 
+		/* Alarms are cleared on read in case the condition that
+		 * caused the alarm is removed. Keep the value latched here
+		 * for providing the register through different alarm files. */
+		data->alarm |= i2c_smbus_read_byte_data(client,
+							MAX6650_REG_ALARM);
+
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/sht15.c linux-libre-2.6.31-gnu/drivers/hwmon/sht15.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/sht15.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/sht15.c	2009-09-09 18:13:59.000000000 -0400
@@ -257,7 +257,7 @@
 				 (data->flag == SHT15_READING_NOTHING),
 				 msecs_to_jiffies(timeout_msecs));
 	if (ret == 0) {/* timeout occurred */
-		disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));;
+		disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
 		sht15_connection_reset(data);
 		return -ETIME;
 	}
@@ -627,35 +627,35 @@
 			.owner = THIS_MODULE,
 		},
 		.probe = sht15_probe,
-		.remove = sht15_remove,
+		.remove = __devexit_p(sht15_remove),
 	}, {
 		.driver = {
 			.name = "sht11",
 			.owner = THIS_MODULE,
 		},
 		.probe = sht15_probe,
-		.remove = sht15_remove,
+		.remove = __devexit_p(sht15_remove),
 	}, {
 		.driver = {
 			.name = "sht15",
 			.owner = THIS_MODULE,
 		},
 		.probe = sht15_probe,
-		.remove = sht15_remove,
+		.remove = __devexit_p(sht15_remove),
 	}, {
 		.driver = {
 			.name = "sht71",
 			.owner = THIS_MODULE,
 		},
 		.probe = sht15_probe,
-		.remove = sht15_remove,
+		.remove = __devexit_p(sht15_remove),
 	}, {
 		.driver = {
 			.name = "sht75",
 			.owner = THIS_MODULE,
 		},
 		.probe = sht15_probe,
-		.remove = sht15_remove,
+		.remove = __devexit_p(sht15_remove),
 	},
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/smsc47m1.c linux-libre-2.6.31-gnu/drivers/hwmon/smsc47m1.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/smsc47m1.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/smsc47m1.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,6 +86,7 @@
 #define SUPERIO_REG_ACT		0x30
 #define SUPERIO_REG_BASE	0x60
 #define SUPERIO_REG_DEVID	0x20
+#define SUPERIO_REG_DEVREV	0x21
 
 /* Logical device registers */
 
@@ -429,6 +430,9 @@
 	 * The LPC47M292 (device id 0x6B) is somewhat compatible, but it
 	 * supports a 3rd fan, and the pin configuration registers are
 	 * unfortunately different.
+	 * The LPC47M233 has the same device id (0x6B) but is not compatible.
+	 * We check the high bit of the device revision register to
+	 * differentiate them.
 	 */
 	switch (val) {
 	case 0x51:
@@ -448,6 +452,13 @@
 		sio_data->type = smsc47m1;
 		break;
 	case 0x6B:
+		if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) {
+			pr_debug(DRVNAME ": "
+				 "Found SMSC LPC47M233, unsupported\n");
+			superio_exit();
+			return -ENODEV;
+		}
+
 		pr_info(DRVNAME ": Found SMSC LPC47M292\n");
 		sio_data->type = smsc47m2;
 		break;
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/tmp401.c linux-libre-2.6.31-gnu/drivers/hwmon/tmp401.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/tmp401.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/hwmon/tmp401.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,690 @@
+/* tmp401.c
+ *
+ * Copyright (C) 2007,2008 Hans de Goede <hdegoede@redhat.com>
+ * Preliminary tmp411 support by:
+ * Gabriel Konat, Sander Leget, Wouter Willems
+ * Copyright (C) 2009 Andre Prendel <andre.prendel@gmx.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.
+ *
+ * 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.
+ */
+
+/*
+ * Driver for the Texas Instruments TMP401 SMBUS temperature sensor IC.
+ *
+ * Note this IC is in some aspect similar to the LM90, but it has quite a
+ * few differences too, for example the local temp has a higher resolution
+ * and thus has 16 bits registers for its value and limit instead of 8 bits.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_2(tmp401, tmp411);
+
+/*
+ * The TMP401 registers, note some registers have different addresses for
+ * reading and writing
+ */
+#define TMP401_STATUS				0x02
+#define TMP401_CONFIG_READ			0x03
+#define TMP401_CONFIG_WRITE			0x09
+#define TMP401_CONVERSION_RATE_READ		0x04
+#define TMP401_CONVERSION_RATE_WRITE		0x0A
+#define TMP401_TEMP_CRIT_HYST			0x21
+#define TMP401_CONSECUTIVE_ALERT		0x22
+#define TMP401_MANUFACTURER_ID_REG		0xFE
+#define TMP401_DEVICE_ID_REG			0xFF
+#define TMP411_N_FACTOR_REG			0x18
+
+static const u8 TMP401_TEMP_MSB[2]			= { 0x00, 0x01 };
+static const u8 TMP401_TEMP_LSB[2]			= { 0x15, 0x10 };
+static const u8 TMP401_TEMP_LOW_LIMIT_MSB_READ[2]	= { 0x06, 0x08 };
+static const u8 TMP401_TEMP_LOW_LIMIT_MSB_WRITE[2]	= { 0x0C, 0x0E };
+static const u8 TMP401_TEMP_LOW_LIMIT_LSB[2]		= { 0x17, 0x14 };
+static const u8 TMP401_TEMP_HIGH_LIMIT_MSB_READ[2]	= { 0x05, 0x07 };
+static const u8 TMP401_TEMP_HIGH_LIMIT_MSB_WRITE[2]	= { 0x0B, 0x0D };
+static const u8 TMP401_TEMP_HIGH_LIMIT_LSB[2]		= { 0x16, 0x13 };
+/* These are called the THERM limit / hysteresis / mask in the datasheet */
+static const u8 TMP401_TEMP_CRIT_LIMIT[2]		= { 0x20, 0x19 };
+
+static const u8 TMP411_TEMP_LOWEST_MSB[2]		= { 0x30, 0x34 };
+static const u8 TMP411_TEMP_LOWEST_LSB[2]		= { 0x31, 0x35 };
+static const u8 TMP411_TEMP_HIGHEST_MSB[2]		= { 0x32, 0x36 };
+static const u8 TMP411_TEMP_HIGHEST_LSB[2]		= { 0x33, 0x37 };
+
+/* Flags */
+#define TMP401_CONFIG_RANGE		0x04
+#define TMP401_CONFIG_SHUTDOWN		0x40
+#define TMP401_STATUS_LOCAL_CRIT		0x01
+#define TMP401_STATUS_REMOTE_CRIT		0x02
+#define TMP401_STATUS_REMOTE_OPEN		0x04
+#define TMP401_STATUS_REMOTE_LOW		0x08
+#define TMP401_STATUS_REMOTE_HIGH		0x10
+#define TMP401_STATUS_LOCAL_LOW		0x20
+#define TMP401_STATUS_LOCAL_HIGH		0x40
+
+/* Manufacturer / Device ID's */
+#define TMP401_MANUFACTURER_ID			0x55
+#define TMP401_DEVICE_ID			0x11
+#define TMP411_DEVICE_ID			0x12
+
+/*
+ * Functions declarations
+ */
+
+static int tmp401_probe(struct i2c_client *client,
+			const struct i2c_device_id *id);
+static int tmp401_detect(struct i2c_client *client, int kind,
+			 struct i2c_board_info *info);
+static int tmp401_remove(struct i2c_client *client);
+static struct tmp401_data *tmp401_update_device(struct device *dev);
+
+/*
+ * Driver data (common to all clients)
+ */
+
+static const struct i2c_device_id tmp401_id[] = {
+	{ "tmp401", tmp401 },
+	{ "tmp411", tmp411 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tmp401_id);
+
+static struct i2c_driver tmp401_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "tmp401",
+	},
+	.probe		= tmp401_probe,
+	.remove		= tmp401_remove,
+	.id_table	= tmp401_id,
+	.detect		= tmp401_detect,
+	.address_data	= &addr_data,
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+
+struct tmp401_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	char valid; /* zero until following fields are valid */
+	unsigned long last_updated; /* in jiffies */
+	int kind;
+
+	/* register values */
+	u8 status;
+	u8 config;
+	u16 temp[2];
+	u16 temp_low[2];
+	u16 temp_high[2];
+	u8 temp_crit[2];
+	u8 temp_crit_hyst;
+	u16 temp_lowest[2];
+	u16 temp_highest[2];
+};
+
+/*
+ * Sysfs attr show / store functions
+ */
+
+static int tmp401_register_to_temp(u16 reg, u8 config)
+{
+	int temp = reg;
+
+	if (config & TMP401_CONFIG_RANGE)
+		temp -= 64 * 256;
+
+	return (temp * 625 + 80) / 160;
+}
+
+static u16 tmp401_temp_to_register(long temp, u8 config)
+{
+	if (config & TMP401_CONFIG_RANGE) {
+		temp = SENSORS_LIMIT(temp, -64000, 191000);
+		temp += 64000;
+	} else
+		temp = SENSORS_LIMIT(temp, 0, 127000);
+
+	return (temp * 160 + 312) / 625;
+}
+
+static int tmp401_crit_register_to_temp(u8 reg, u8 config)
+{
+	int temp = reg;
+
+	if (config & TMP401_CONFIG_RANGE)
+		temp -= 64;
+
+	return temp * 1000;
+}
+
+static u8 tmp401_crit_temp_to_register(long temp, u8 config)
+{
+	if (config & TMP401_CONFIG_RANGE) {
+		temp = SENSORS_LIMIT(temp, -64000, 191000);
+		temp += 64000;
+	} else
+		temp = SENSORS_LIMIT(temp, 0, 127000);
+
+	return (temp + 500) / 1000;
+}
+
+static ssize_t show_temp_value(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		tmp401_register_to_temp(data->temp[index], data->config));
+}
+
+static ssize_t show_temp_min(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		tmp401_register_to_temp(data->temp_low[index], data->config));
+}
+
+static ssize_t show_temp_max(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		tmp401_register_to_temp(data->temp_high[index], data->config));
+}
+
+static ssize_t show_temp_crit(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+			tmp401_crit_register_to_temp(data->temp_crit[index],
+							data->config));
+}
+
+static ssize_t show_temp_crit_hyst(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int temp, index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	mutex_lock(&data->update_lock);
+	temp = tmp401_crit_register_to_temp(data->temp_crit[index],
+						data->config);
+	temp -= data->temp_crit_hyst * 1000;
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t show_temp_lowest(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		tmp401_register_to_temp(data->temp_lowest[index],
+					data->config));
+}
+
+static ssize_t show_temp_highest(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	return sprintf(buf, "%d\n",
+		tmp401_register_to_temp(data->temp_highest[index],
+					data->config));
+}
+
+static ssize_t show_status(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int mask = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+
+	if (data->status & mask)
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static ssize_t store_temp_min(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+	long val;
+	u16 reg;
+
+	if (strict_strtol(buf, 10, &val))
+		return -EINVAL;
+
+	reg = tmp401_temp_to_register(val, data->config);
+
+	mutex_lock(&data->update_lock);
+
+	i2c_smbus_write_byte_data(to_i2c_client(dev),
+		TMP401_TEMP_LOW_LIMIT_MSB_WRITE[index], reg >> 8);
+	i2c_smbus_write_byte_data(to_i2c_client(dev),
+		TMP401_TEMP_LOW_LIMIT_LSB[index], reg & 0xFF);
+
+	data->temp_low[index] = reg;
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t store_temp_max(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+	long val;
+	u16 reg;
+
+	if (strict_strtol(buf, 10, &val))
+		return -EINVAL;
+
+	reg = tmp401_temp_to_register(val, data->config);
+
+	mutex_lock(&data->update_lock);
+
+	i2c_smbus_write_byte_data(to_i2c_client(dev),
+		TMP401_TEMP_HIGH_LIMIT_MSB_WRITE[index], reg >> 8);
+	i2c_smbus_write_byte_data(to_i2c_client(dev),
+		TMP401_TEMP_HIGH_LIMIT_LSB[index], reg & 0xFF);
+
+	data->temp_high[index] = reg;
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t store_temp_crit(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+	long val;
+	u8 reg;
+
+	if (strict_strtol(buf, 10, &val))
+		return -EINVAL;
+
+	reg = tmp401_crit_temp_to_register(val, data->config);
+
+	mutex_lock(&data->update_lock);
+
+	i2c_smbus_write_byte_data(to_i2c_client(dev),
+		TMP401_TEMP_CRIT_LIMIT[index], reg);
+
+	data->temp_crit[index] = reg;
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	int temp, index = to_sensor_dev_attr(devattr)->index;
+	struct tmp401_data *data = tmp401_update_device(dev);
+	long val;
+	u8 reg;
+
+	if (strict_strtol(buf, 10, &val))
+		return -EINVAL;
+
+	if (data->config & TMP401_CONFIG_RANGE)
+		val = SENSORS_LIMIT(val, -64000, 191000);
+	else
+		val = SENSORS_LIMIT(val, 0, 127000);
+
+	mutex_lock(&data->update_lock);
+	temp = tmp401_crit_register_to_temp(data->temp_crit[index],
+						data->config);
+	val = SENSORS_LIMIT(val, temp - 255000, temp);
+	reg = ((temp - val) + 500) / 1000;
+
+	i2c_smbus_write_byte_data(to_i2c_client(dev),
+		TMP401_TEMP_CRIT_HYST, reg);
+
+	data->temp_crit_hyst = reg;
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/*
+ * Resets the historical measurements of minimum and maximum temperatures.
+ * This is done by writing any value to any of the minimum/maximum registers
+ * (0x30-0x37).
+ */
+static ssize_t reset_temp_history(struct device *dev,
+	struct device_attribute	*devattr, const char *buf, size_t count)
+{
+	long val;
+
+	if (strict_strtol(buf, 10, &val))
+		return -EINVAL;
+
+	if (val != 1) {
+		dev_err(dev, "temp_reset_history value %ld not"
+			" supported. Use 1 to reset the history!\n", val);
+		return -EINVAL;
+	}
+	i2c_smbus_write_byte_data(to_i2c_client(dev),
+		TMP411_TEMP_LOWEST_MSB[0], val);
+
+	return count;
+}
+
+static struct sensor_device_attribute tmp401_attr[] = {
+	SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0),
+	SENSOR_ATTR(temp1_min, 0644, show_temp_min, store_temp_min, 0),
+	SENSOR_ATTR(temp1_max, 0644, show_temp_max, store_temp_max, 0),
+	SENSOR_ATTR(temp1_crit, 0644, show_temp_crit, store_temp_crit, 0),
+	SENSOR_ATTR(temp1_crit_hyst, 0644, show_temp_crit_hyst,
+		    store_temp_crit_hyst, 0),
+	SENSOR_ATTR(temp1_min_alarm, 0444, show_status, NULL,
+		    TMP401_STATUS_LOCAL_LOW),
+	SENSOR_ATTR(temp1_max_alarm, 0444, show_status, NULL,
+		    TMP401_STATUS_LOCAL_HIGH),
+	SENSOR_ATTR(temp1_crit_alarm, 0444, show_status, NULL,
+		    TMP401_STATUS_LOCAL_CRIT),
+	SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1),
+	SENSOR_ATTR(temp2_min, 0644, show_temp_min, store_temp_min, 1),
+	SENSOR_ATTR(temp2_max, 0644, show_temp_max, store_temp_max, 1),
+	SENSOR_ATTR(temp2_crit, 0644, show_temp_crit, store_temp_crit, 1),
+	SENSOR_ATTR(temp2_crit_hyst, 0444, show_temp_crit_hyst, NULL, 1),
+	SENSOR_ATTR(temp2_fault, 0444, show_status, NULL,
+		    TMP401_STATUS_REMOTE_OPEN),
+	SENSOR_ATTR(temp2_min_alarm, 0444, show_status, NULL,
+		    TMP401_STATUS_REMOTE_LOW),
+	SENSOR_ATTR(temp2_max_alarm, 0444, show_status, NULL,
+		    TMP401_STATUS_REMOTE_HIGH),
+	SENSOR_ATTR(temp2_crit_alarm, 0444, show_status, NULL,
+		    TMP401_STATUS_REMOTE_CRIT),
+};
+
+/*
+ * Additional features of the TMP411 chip.
+ * The TMP411 stores the minimum and maximum
+ * temperature measured since power-on, chip-reset, or
+ * minimum and maximum register reset for both the local
+ * and remote channels.
+ */
+static struct sensor_device_attribute tmp411_attr[] = {
+	SENSOR_ATTR(temp1_highest, 0444, show_temp_highest, NULL, 0),
+	SENSOR_ATTR(temp1_lowest, 0444, show_temp_lowest, NULL, 0),
+	SENSOR_ATTR(temp2_highest, 0444, show_temp_highest, NULL, 1),
+	SENSOR_ATTR(temp2_lowest, 0444, show_temp_lowest, NULL, 1),
+	SENSOR_ATTR(temp_reset_history, 0200, NULL, reset_temp_history, 0),
+};
+
+/*
+ * Begin non sysfs callback code (aka Real code)
+ */
+
+static void tmp401_init_client(struct i2c_client *client)
+{
+	int config, config_orig;
+
+	/* Set the conversion rate to 2 Hz */
+	i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
+
+	/* Start conversions (disable shutdown if necessary) */
+	config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ);
+	if (config < 0) {
+		dev_warn(&client->dev, "Initialization failed!\n");
+		return;
+	}
+
+	config_orig = config;
+	config &= ~TMP401_CONFIG_SHUTDOWN;
+
+	if (config != config_orig)
+		i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config);
+}
+
+static int tmp401_detect(struct i2c_client *client, int kind,
+			 struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	/* Detect and identify the chip */
+	if (kind <= 0) {
+		u8 reg;
+
+		reg = i2c_smbus_read_byte_data(client,
+					       TMP401_MANUFACTURER_ID_REG);
+		if (reg != TMP401_MANUFACTURER_ID)
+			return -ENODEV;
+
+		reg = i2c_smbus_read_byte_data(client, TMP401_DEVICE_ID_REG);
+
+		switch (reg) {
+		case TMP401_DEVICE_ID:
+			kind = tmp401;
+			break;
+		case TMP411_DEVICE_ID:
+			kind = tmp411;
+			break;
+		default:
+			return -ENODEV;
+		}
+
+		reg = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ);
+		if (reg & 0x1b)
+			return -ENODEV;
+
+		reg = i2c_smbus_read_byte_data(client,
+					       TMP401_CONVERSION_RATE_READ);
+		/* Datasheet says: 0x1-0x6 */
+		if (reg > 15)
+			return -ENODEV;
+	}
+	strlcpy(info->type, tmp401_id[kind - 1].name, I2C_NAME_SIZE);
+
+	return 0;
+}
+
+static int tmp401_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int i, err = 0;
+	struct tmp401_data *data;
+	const char *names[] = { "TMP401", "TMP411" };
+
+	data = kzalloc(sizeof(struct tmp401_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+	data->kind = id->driver_data;
+
+	/* Initialize the TMP401 chip */
+	tmp401_init_client(client);
+
+	/* Register sysfs hooks */
+	for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++) {
+		err = device_create_file(&client->dev,
+					 &tmp401_attr[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	/* Register aditional tmp411 sysfs hooks */
+	if (data->kind == tmp411) {
+		for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) {
+			err = device_create_file(&client->dev,
+						 &tmp411_attr[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		goto exit_remove;
+	}
+
+	dev_info(&client->dev, "Detected TI %s chip\n",
+		 names[data->kind - 1]);
+
+	return 0;
+
+exit_remove:
+	tmp401_remove(client); /* will also free data for us */
+	return err;
+}
+
+static int tmp401_remove(struct i2c_client *client)
+{
+	struct tmp401_data *data = i2c_get_clientdata(client);
+	int i;
+
+	if (data->hwmon_dev)
+		hwmon_device_unregister(data->hwmon_dev);
+
+	for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++)
+		device_remove_file(&client->dev, &tmp401_attr[i].dev_attr);
+
+	if (data->kind == tmp411) {
+		for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++)
+			device_remove_file(&client->dev,
+					   &tmp411_attr[i].dev_attr);
+	}
+
+	kfree(data);
+	return 0;
+}
+
+static struct tmp401_data *tmp401_update_device_reg16(
+	struct i2c_client *client, struct tmp401_data *data)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		/*
+		 * High byte must be read first immediately followed
+		 * by the low byte
+		 */
+		data->temp[i] = i2c_smbus_read_byte_data(client,
+			TMP401_TEMP_MSB[i]) << 8;
+		data->temp[i] |= i2c_smbus_read_byte_data(client,
+			TMP401_TEMP_LSB[i]);
+		data->temp_low[i] = i2c_smbus_read_byte_data(client,
+			TMP401_TEMP_LOW_LIMIT_MSB_READ[i]) << 8;
+		data->temp_low[i] |= i2c_smbus_read_byte_data(client,
+			TMP401_TEMP_LOW_LIMIT_LSB[i]);
+		data->temp_high[i] = i2c_smbus_read_byte_data(client,
+			TMP401_TEMP_HIGH_LIMIT_MSB_READ[i]) << 8;
+		data->temp_high[i] |= i2c_smbus_read_byte_data(client,
+			TMP401_TEMP_HIGH_LIMIT_LSB[i]);
+		data->temp_crit[i] = i2c_smbus_read_byte_data(client,
+			TMP401_TEMP_CRIT_LIMIT[i]);
+
+		if (data->kind == tmp411) {
+			data->temp_lowest[i] = i2c_smbus_read_byte_data(client,
+				TMP411_TEMP_LOWEST_MSB[i]) << 8;
+			data->temp_lowest[i] |= i2c_smbus_read_byte_data(
+				client, TMP411_TEMP_LOWEST_LSB[i]);
+
+			data->temp_highest[i] = i2c_smbus_read_byte_data(
+				client, TMP411_TEMP_HIGHEST_MSB[i]) << 8;
+			data->temp_highest[i] |= i2c_smbus_read_byte_data(
+				client, TMP411_TEMP_HIGHEST_LSB[i]);
+		}
+	}
+	return data;
+}
+
+static struct tmp401_data *tmp401_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tmp401_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		data->status = i2c_smbus_read_byte_data(client, TMP401_STATUS);
+		data->config = i2c_smbus_read_byte_data(client,
+						TMP401_CONFIG_READ);
+		tmp401_update_device_reg16(client, data);
+
+		data->temp_crit_hyst = i2c_smbus_read_byte_data(client,
+						TMP401_TEMP_CRIT_HYST);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+static int __init tmp401_init(void)
+{
+	return i2c_add_driver(&tmp401_driver);
+}
+
+static void __exit tmp401_exit(void)
+{
+	i2c_del_driver(&tmp401_driver);
+}
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Texas Instruments TMP401 temperature sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(tmp401_init);
+module_exit(tmp401_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/hwmon/w83627ehf.c linux-libre-2.6.31-gnu/drivers/hwmon/w83627ehf.c
--- linux-libre-2.6.30-gnu/drivers/hwmon/w83627ehf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/hwmon/w83627ehf.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,7 @@
     w83627ehf   10      5       4       3      0x8850 0x88    0x5ca3
                                                0x8860 0xa1
     w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
+    w83627dhg-p  9      5       4       3      0xb070 0xc1    0x5ca3
     w83667hg     9      5       3       3      0xa510 0xc1    0x5ca3
 */
 
@@ -53,12 +54,13 @@
 #include <asm/io.h>
 #include "lm75.h"
 
-enum kinds { w83627ehf, w83627dhg, w83667hg };
+enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg };
 
 /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
 static const char * w83627ehf_device_names[] = {
 	"w83627ehf",
 	"w83627dhg",
+	"w83627dhg",
 	"w83667hg",
 };
 
@@ -86,6 +88,7 @@
 #define SIO_W83627EHF_ID	0x8850
 #define SIO_W83627EHG_ID	0x8860
 #define SIO_W83627DHG_ID	0xa020
+#define SIO_W83627DHG_P_ID	0xb070
 #define SIO_W83667HG_ID 	0xa510
 #define SIO_ID_MASK		0xFFF0
 
@@ -1517,6 +1520,7 @@
 	static const char __initdata sio_name_W83627EHF[] = "W83627EHF";
 	static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
 	static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
+	static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
 	static const char __initdata sio_name_W83667HG[] = "W83667HG";
 
 	u16 val;
@@ -1542,6 +1546,10 @@
 		sio_data->kind = w83627dhg;
 		sio_name = sio_name_W83627DHG;
 		break;
+	case SIO_W83627DHG_P_ID:
+		sio_data->kind = w83627dhg_p;
+		sio_name = sio_name_W83627DHG_P;
+		break;
 	case SIO_W83667HG_ID:
 		sio_data->kind = w83667hg;
 		sio_name = sio_name_W83667HG;
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-at91.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-at91.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-at91.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-at91.c	2009-09-09 18:13:59.000000000 -0400
@@ -200,10 +200,10 @@
 	if (!res)
 		return -ENXIO;
 
-	if (!request_mem_region(res->start, res->end - res->start + 1, "at91_i2c"))
+	if (!request_mem_region(res->start, resource_size(res), "at91_i2c"))
 		return -EBUSY;
 
-	twi_base = ioremap(res->start, res->end - res->start + 1);
+	twi_base = ioremap(res->start, resource_size(res));
 	if (!twi_base) {
 		rc = -ENOMEM;
 		goto fail0;
@@ -252,7 +252,7 @@
 fail1:
 	iounmap(twi_base);
 fail0:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 	return rc;
 }
@@ -268,7 +268,7 @@
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	iounmap(twi_base);
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 	clk_disable(twi_clk);		/* disable peripheral clock */
 	clk_put(twi_clk);
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-au1550.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-au1550.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-au1550.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-au1550.c	2009-09-09 18:13:59.000000000 -0400
@@ -389,7 +389,7 @@
 		goto out;
 	}
 
-	priv->ioarea = request_mem_region(r->start, r->end - r->start + 1,
+	priv->ioarea = request_mem_region(r->start, resource_size(r),
 					  pdev->name);
 	if (!priv->ioarea) {
 		ret = -EBUSY;
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-bfin-twi.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-bfin-twi.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-bfin-twi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-bfin-twi.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
@@ -104,9 +105,14 @@
 			write_MASTER_CTL(iface,
 				read_MASTER_CTL(iface) | STOP);
 		else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
-				iface->cur_msg+1 < iface->msg_num)
-			write_MASTER_CTL(iface,
-				read_MASTER_CTL(iface) | RSTART);
+		         iface->cur_msg + 1 < iface->msg_num) {
+			if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
+				write_MASTER_CTL(iface,
+					read_MASTER_CTL(iface) | RSTART | MDIR);
+			else
+				write_MASTER_CTL(iface,
+					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
+		}
 		SSYNC();
 		/* Clear status */
 		write_INT_STAT(iface, XMTSERV);
@@ -134,9 +140,13 @@
 				read_MASTER_CTL(iface) | STOP);
 			SSYNC();
 		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
-				iface->cur_msg+1 < iface->msg_num) {
-			write_MASTER_CTL(iface,
-				read_MASTER_CTL(iface) | RSTART);
+		           iface->cur_msg + 1 < iface->msg_num) {
+			if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
+				write_MASTER_CTL(iface,
+					read_MASTER_CTL(iface) | RSTART | MDIR);
+			else
+				write_MASTER_CTL(iface,
+					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
 			SSYNC();
 		}
 		/* Clear interrupt source */
@@ -196,8 +206,6 @@
 			/* remove restart bit and enable master receive */
 			write_MASTER_CTL(iface,
 				read_MASTER_CTL(iface) & ~RSTART);
-			write_MASTER_CTL(iface,
-				read_MASTER_CTL(iface) | MEN | MDIR);
 			SSYNC();
 		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
 				iface->cur_msg+1 < iface->msg_num) {
@@ -222,18 +230,19 @@
 			}
 
 			if (iface->pmsg[iface->cur_msg].len <= 255)
-				write_MASTER_CTL(iface,
-				iface->pmsg[iface->cur_msg].len << 6);
+					write_MASTER_CTL(iface,
+					(read_MASTER_CTL(iface) &
+					(~(0xff << 6))) |
+				(iface->pmsg[iface->cur_msg].len << 6));
 			else {
-				write_MASTER_CTL(iface, 0xff << 6);
+				write_MASTER_CTL(iface,
+					(read_MASTER_CTL(iface) |
+					(0xff << 6)));
 				iface->manual_stop = 1;
 			}
 			/* remove restart bit and enable master receive */
 			write_MASTER_CTL(iface,
 				read_MASTER_CTL(iface) & ~RSTART);
-			write_MASTER_CTL(iface, read_MASTER_CTL(iface) |
-				MEN | ((iface->read_write == I2C_SMBUS_READ) ?
-				MDIR : 0));
 			SSYNC();
 		} else {
 			iface->result = 1;
@@ -441,6 +450,16 @@
 		}
 		iface->transPtr = data->block;
 		break;
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+		if (read_write == I2C_SMBUS_READ) {
+			iface->readNum = data->block[0];
+			iface->cur_mode = TWI_I2C_MODE_COMBINED;
+		} else {
+			iface->writeNum = data->block[0];
+			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+		}
+		iface->transPtr = (u8 *)&data->block[1];
+		break;
 	default:
 		return -1;
 	}
@@ -564,7 +583,7 @@
 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
 	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
-	       I2C_FUNC_I2C;
+	       I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK;
 }
 
 static struct i2c_algorithm bfin_twi_algorithm = {
@@ -614,6 +633,7 @@
 	struct i2c_adapter *p_adap;
 	struct resource *res;
 	int rc;
+	unsigned int clkhilow;
 
 	iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
 	if (!iface) {
@@ -632,7 +652,7 @@
 		goto out_error_get_res;
 	}
 
-	iface->regs_base = ioremap(res->start, res->end - res->start + 1);
+	iface->regs_base = ioremap(res->start, resource_size(res));
 	if (iface->regs_base == NULL) {
 		dev_err(&pdev->dev, "Cannot map IO\n");
 		rc = -ENXIO;
@@ -675,10 +695,14 @@
 	/* Set TWI internal clock as 10MHz */
 	write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
 
+	/*
+	 * We will not end up with a CLKDIV=0 because no one will specify
+	 * 20kHz SCL or less in Kconfig now. (5 * 1024 / 20 = 0x100)
+	 */
+	clkhilow = 5 * 1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ;
+
 	/* Set Twi interface clock as specified */
-	write_CLKDIV(iface, ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
-			<< 8) | ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
-			& 0xFF));
+	write_CLKDIV(iface, (clkhilow << 8) | clkhilow);
 
 	/* Enable TWI */
 	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-cpm.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-cpm.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-cpm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-cpm.c	2009-09-09 18:13:59.000000000 -0400
@@ -140,7 +140,7 @@
 
 	dev_dbg(&adap->dev, "Interrupt: %x\n", i);
 
-	wake_up_interruptible(&cpm->i2c_wait);
+	wake_up(&cpm->i2c_wait);
 
 	return i ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -364,12 +364,12 @@
 		dev_dbg(&adap->dev, "test ready.\n");
 		pmsg = &msgs[tptr];
 		if (pmsg->flags & I2C_M_RD)
-			ret = wait_event_interruptible_timeout(cpm->i2c_wait,
+			ret = wait_event_timeout(cpm->i2c_wait,
 				(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) ||
 				!(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY),
 				1 * HZ);
 		else
-			ret = wait_event_interruptible_timeout(cpm->i2c_wait,
+			ret = wait_event_timeout(cpm->i2c_wait,
 				!(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY),
 				1 * HZ);
 		if (ret == 0) {
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-davinci.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-davinci.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-davinci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-davinci.c	2009-09-09 18:13:59.000000000 -0400
@@ -187,6 +187,11 @@
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
 
+	/* Respond at reserved "SMBus Host" slave address" (and zero);
+	 * we seem to have no option to not respond...
+	 */
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08);
+
 	dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
 	dev_dbg(dev->dev, "PSC  = %d\n",
 		davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
@@ -387,7 +392,7 @@
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
 
 	if (!dev->terminate)
-		dev_err(dev->dev, "TDR IRQ while no data to send\n");
+		dev_dbg(dev->dev, "TDR IRQ while no data to send\n");
 }
 
 /*
@@ -473,9 +478,14 @@
 			break;
 
 		case DAVINCI_I2C_IVR_AAS:
-			dev_warn(dev->dev, "Address as slave interrupt\n");
-		}/* switch */
-	}/* while */
+			dev_dbg(dev->dev, "Address as slave interrupt\n");
+			break;
+
+		default:
+			dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat);
+			break;
+		}
+	}
 
 	return count ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -505,7 +515,7 @@
 		return -ENODEV;
 	}
 
-	ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+	ioarea = request_mem_region(mem->start, resource_size(mem),
 				    pdev->name);
 	if (!ioarea) {
 		dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -523,7 +533,7 @@
 	dev->irq = irq->start;
 	platform_set_drvdata(pdev, dev);
 
-	dev->clk = clk_get(&pdev->dev, "I2CCLK");
+	dev->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk)) {
 		r = -ENODEV;
 		goto err_free_mem;
@@ -568,7 +578,7 @@
 	put_device(&pdev->dev);
 	kfree(dev);
 err_release_region:
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 
 	return r;
 }
@@ -591,7 +601,7 @@
 	kfree(dev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-designware.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-designware.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-designware.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-designware.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,624 @@
+/*
+ * Synopsys Designware I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+/*
+ * Registers offset
+ */
+#define DW_IC_CON		0x0
+#define DW_IC_TAR		0x4
+#define DW_IC_DATA_CMD		0x10
+#define DW_IC_SS_SCL_HCNT	0x14
+#define DW_IC_SS_SCL_LCNT	0x18
+#define DW_IC_FS_SCL_HCNT	0x1c
+#define DW_IC_FS_SCL_LCNT	0x20
+#define DW_IC_INTR_STAT		0x2c
+#define DW_IC_INTR_MASK		0x30
+#define DW_IC_CLR_INTR		0x40
+#define DW_IC_ENABLE		0x6c
+#define DW_IC_STATUS		0x70
+#define DW_IC_TXFLR		0x74
+#define DW_IC_RXFLR		0x78
+#define DW_IC_COMP_PARAM_1	0xf4
+#define DW_IC_TX_ABRT_SOURCE	0x80
+
+#define DW_IC_CON_MASTER		0x1
+#define DW_IC_CON_SPEED_STD		0x2
+#define DW_IC_CON_SPEED_FAST		0x4
+#define DW_IC_CON_10BITADDR_MASTER	0x10
+#define DW_IC_CON_RESTART_EN		0x20
+#define DW_IC_CON_SLAVE_DISABLE		0x40
+
+#define DW_IC_INTR_TX_EMPTY	0x10
+#define DW_IC_INTR_TX_ABRT	0x40
+#define DW_IC_INTR_STOP_DET	0x200
+
+#define DW_IC_STATUS_ACTIVITY	0x1
+
+#define DW_IC_ERR_TX_ABRT	0x1
+
+/*
+ * status codes
+ */
+#define STATUS_IDLE			0x0
+#define STATUS_WRITE_IN_PROGRESS	0x1
+#define STATUS_READ_IN_PROGRESS		0x2
+
+#define TIMEOUT			20 /* ms */
+
+/*
+ * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
+ *
+ * only expected abort codes are listed here
+ * refer to the datasheet for the full list
+ */
+#define ABRT_7B_ADDR_NOACK	0
+#define ABRT_10ADDR1_NOACK	1
+#define ABRT_10ADDR2_NOACK	2
+#define ABRT_TXDATA_NOACK	3
+#define ABRT_GCALL_NOACK	4
+#define ABRT_GCALL_READ		5
+#define ABRT_SBYTE_ACKDET	7
+#define ABRT_SBYTE_NORSTRT	9
+#define ABRT_10B_RD_NORSTRT	10
+#define ARB_MASTER_DIS		11
+#define ARB_LOST		12
+
+static char *abort_sources[] = {
+	[ABRT_7B_ADDR_NOACK]	=
+		"slave address not acknowledged (7bit mode)",
+	[ABRT_10ADDR1_NOACK]	=
+		"first address byte not acknowledged (10bit mode)",
+	[ABRT_10ADDR2_NOACK]	=
+		"second address byte not acknowledged (10bit mode)",
+	[ABRT_TXDATA_NOACK]		=
+		"data not acknowledged",
+	[ABRT_GCALL_NOACK]		=
+		"no acknowledgement for a general call",
+	[ABRT_GCALL_READ]		=
+		"read after general call",
+	[ABRT_SBYTE_ACKDET]		=
+		"start byte acknowledged",
+	[ABRT_SBYTE_NORSTRT]	=
+		"trying to send start byte when restart is disabled",
+	[ABRT_10B_RD_NORSTRT]	=
+		"trying to read when restart is disabled (10bit mode)",
+	[ARB_MASTER_DIS]		=
+		"trying to use disabled adapter",
+	[ARB_LOST]			=
+		"lost arbitration",
+};
+
+/**
+ * struct dw_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @pump_msg: continue in progress transfers
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transfered
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ *	array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ *	array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct dw_i2c_dev {
+	struct device		*dev;
+	void __iomem		*base;
+	struct completion	cmd_complete;
+	struct tasklet_struct	pump_msg;
+	struct mutex		lock;
+	struct clk		*clk;
+	int			cmd_err;
+	struct i2c_msg		*msgs;
+	int			msgs_num;
+	int			msg_write_idx;
+	u16			tx_buf_len;
+	u8			*tx_buf;
+	int			msg_read_idx;
+	u16			rx_buf_len;
+	u8			*rx_buf;
+	int			msg_err;
+	unsigned int		status;
+	u16			abort_source;
+	int			irq;
+	struct i2c_adapter	adapter;
+	unsigned int		tx_fifo_depth;
+	unsigned int		rx_fifo_depth;
+};
+
+/**
+ * i2c_dw_init() - initialize the designware i2c master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+static void i2c_dw_init(struct dw_i2c_dev *dev)
+{
+	u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
+	u16 ic_con;
+
+	/* Disable the adapter */
+	writeb(0, dev->base + DW_IC_ENABLE);
+
+	/* set standard and fast speed deviders for high/low periods */
+	writew((input_clock_khz * 40 / 10000)+1, /* std speed high, 4us */
+			dev->base + DW_IC_SS_SCL_HCNT);
+	writew((input_clock_khz * 47 / 10000)+1, /* std speed low, 4.7us */
+			dev->base + DW_IC_SS_SCL_LCNT);
+	writew((input_clock_khz *  6 / 10000)+1, /* fast speed high, 0.6us */
+			dev->base + DW_IC_FS_SCL_HCNT);
+	writew((input_clock_khz * 13 / 10000)+1, /* fast speed low, 1.3us */
+			dev->base + DW_IC_FS_SCL_LCNT);
+
+	/* configure the i2c master */
+	ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+	writew(ic_con, dev->base + DW_IC_CON);
+}
+
+/*
+ * Waiting for bus not busy
+ */
+static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
+{
+	int timeout = TIMEOUT;
+
+	while (readb(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+		if (timeout <= 0) {
+			dev_warn(dev->dev, "timeout waiting for bus ready\n");
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+/*
+ * Initiate low level master read/write transaction.
+ * This function is called from i2c_dw_xfer when starting a transfer.
+ * This function is also called from dw_i2c_pump_msg to continue a transfer
+ * that is longer than the size of the TX FIFO.
+ */
+static void
+i2c_dw_xfer_msg(struct i2c_adapter *adap)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	struct i2c_msg *msgs = dev->msgs;
+	int num = dev->msgs_num;
+	u16 ic_con, intr_mask;
+	int tx_limit = dev->tx_fifo_depth - readb(dev->base + DW_IC_TXFLR);
+	int rx_limit = dev->rx_fifo_depth - readb(dev->base + DW_IC_RXFLR);
+	u16 addr = msgs[dev->msg_write_idx].addr;
+	u16 buf_len = dev->tx_buf_len;
+
+	if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
+		/* Disable the adapter */
+		writeb(0, dev->base + DW_IC_ENABLE);
+
+		/* set the slave (target) address */
+		writew(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
+
+		/* if the slave address is ten bit address, enable 10BITADDR */
+		ic_con = readw(dev->base + DW_IC_CON);
+		if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+			ic_con |= DW_IC_CON_10BITADDR_MASTER;
+		else
+			ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+		writew(ic_con, dev->base + DW_IC_CON);
+
+		/* Enable the adapter */
+		writeb(1, dev->base + DW_IC_ENABLE);
+	}
+
+	for (; dev->msg_write_idx < num; dev->msg_write_idx++) {
+		/* if target address has changed, we need to
+		 * reprogram the target address in the i2c
+		 * adapter when we are done with this transfer
+		 */
+		if (msgs[dev->msg_write_idx].addr != addr)
+			return;
+
+		if (msgs[dev->msg_write_idx].len == 0) {
+			dev_err(dev->dev,
+				"%s: invalid message length\n", __func__);
+			dev->msg_err = -EINVAL;
+			return;
+		}
+
+		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
+			/* new i2c_msg */
+			dev->tx_buf = msgs[dev->msg_write_idx].buf;
+			buf_len = msgs[dev->msg_write_idx].len;
+		}
+
+		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+				writew(0x100, dev->base + DW_IC_DATA_CMD);
+				rx_limit--;
+			} else
+				writew(*(dev->tx_buf++),
+						dev->base + DW_IC_DATA_CMD);
+			tx_limit--; buf_len--;
+		}
+	}
+
+	intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT;
+	if (buf_len > 0) { /* more bytes to be written */
+		intr_mask |= DW_IC_INTR_TX_EMPTY;
+		dev->status |= STATUS_WRITE_IN_PROGRESS;
+	} else
+		dev->status &= ~STATUS_WRITE_IN_PROGRESS;
+	writew(intr_mask, dev->base + DW_IC_INTR_MASK);
+
+	dev->tx_buf_len = buf_len;
+}
+
+static void
+i2c_dw_read(struct i2c_adapter *adap)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	struct i2c_msg *msgs = dev->msgs;
+	int num = dev->msgs_num;
+	u16 addr = msgs[dev->msg_read_idx].addr;
+	int rx_valid = readw(dev->base + DW_IC_RXFLR);
+
+	for (; dev->msg_read_idx < num; dev->msg_read_idx++) {
+		u16 len;
+		u8 *buf;
+
+		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
+			continue;
+
+		/* different i2c client, reprogram the i2c adapter */
+		if (msgs[dev->msg_read_idx].addr != addr)
+			return;
+
+		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
+			len = msgs[dev->msg_read_idx].len;
+			buf = msgs[dev->msg_read_idx].buf;
+		} else {
+			len = dev->rx_buf_len;
+			buf = dev->rx_buf;
+		}
+
+		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+			*buf++ = readb(dev->base + DW_IC_DATA_CMD);
+
+		if (len > 0) {
+			dev->status |= STATUS_READ_IN_PROGRESS;
+			dev->rx_buf_len = len;
+			dev->rx_buf = buf;
+			return;
+		} else
+			dev->status &= ~STATUS_READ_IN_PROGRESS;
+	}
+}
+
+/*
+ * Prepare controller for a transaction and call i2c_dw_xfer_msg
+ */
+static int
+i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	int ret;
+
+	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
+
+	mutex_lock(&dev->lock);
+
+	INIT_COMPLETION(dev->cmd_complete);
+	dev->msgs = msgs;
+	dev->msgs_num = num;
+	dev->cmd_err = 0;
+	dev->msg_write_idx = 0;
+	dev->msg_read_idx = 0;
+	dev->msg_err = 0;
+	dev->status = STATUS_IDLE;
+
+	ret = i2c_dw_wait_bus_not_busy(dev);
+	if (ret < 0)
+		goto done;
+
+	/* start the transfers */
+	i2c_dw_xfer_msg(adap);
+
+	/* wait for tx to complete */
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
+	if (ret == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+		i2c_dw_init(dev);
+		ret = -ETIMEDOUT;
+		goto done;
+	} else if (ret < 0)
+		goto done;
+
+	if (dev->msg_err) {
+		ret = dev->msg_err;
+		goto done;
+	}
+
+	/* no error */
+	if (likely(!dev->cmd_err)) {
+		/* read rx fifo, and disable the adapter */
+		do {
+			i2c_dw_read(adap);
+		} while (dev->status & STATUS_READ_IN_PROGRESS);
+		writeb(0, dev->base + DW_IC_ENABLE);
+		ret = num;
+		goto done;
+	}
+
+	/* We have an error */
+	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
+		unsigned long abort_source = dev->abort_source;
+		int i;
+
+		for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) {
+		    dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
+		}
+	}
+	ret = -EIO;
+
+done:
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+static u32 i2c_dw_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
+}
+
+static void dw_i2c_pump_msg(unsigned long data)
+{
+	struct dw_i2c_dev *dev = (struct dw_i2c_dev *) data;
+	u16 intr_mask;
+
+	i2c_dw_read(&dev->adapter);
+	i2c_dw_xfer_msg(&dev->adapter);
+
+	intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT;
+	if (dev->status & STATUS_WRITE_IN_PROGRESS)
+		intr_mask |= DW_IC_INTR_TX_EMPTY;
+	writew(intr_mask, dev->base + DW_IC_INTR_MASK);
+}
+
+/*
+ * Interrupt service routine. This gets called whenever an I2C interrupt
+ * occurs.
+ */
+static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+{
+	struct dw_i2c_dev *dev = dev_id;
+	u16 stat;
+
+	stat = readw(dev->base + DW_IC_INTR_STAT);
+	dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		dev->abort_source = readw(dev->base + DW_IC_TX_ABRT_SOURCE);
+		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
+		dev->status = STATUS_IDLE;
+	} else if (stat & DW_IC_INTR_TX_EMPTY)
+		tasklet_schedule(&dev->pump_msg);
+
+	readb(dev->base + DW_IC_CLR_INTR);	/* clear interrupts */
+	writew(0, dev->base + DW_IC_INTR_MASK);	/* disable interrupts */
+	if (stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET))
+		complete(&dev->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	struct resource *mem, *irq, *ioarea;
+	int r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return -EINVAL;
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	tasklet_init(&dev->pump_msg, dw_i2c_pump_msg, (unsigned long) dev);
+	mutex_init(&dev->lock);
+	dev->dev = get_device(&pdev->dev);
+	dev->irq = irq->start;
+	platform_set_drvdata(pdev, dev);
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
+		r = -ENODEV;
+		goto err_free_mem;
+	}
+	clk_enable(dev->clk);
+
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (dev->base == NULL) {
+		dev_err(&pdev->dev, "failure mapping io resources\n");
+		r = -EBUSY;
+		goto err_unuse_clocks;
+	}
+	{
+		u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
+
+		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+	}
+	i2c_dw_init(dev);
+
+	writew(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
+	r = request_irq(dev->irq, i2c_dw_isr, 0, pdev->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+			sizeof(adap->name));
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+
+	adap->nr = pdev->id;
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+err_unuse_clocks:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+err_free_mem:
+	platform_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	platform_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+
+	writeb(0, dev->base + DW_IC_ENABLE);
+	free_irq(dev->irq, dev);
+	kfree(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+	.remove		= __devexit_p(dw_i2c_remove),
+	.driver		= {
+		.name	= "i2c_designware",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-highlander.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-highlander.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-highlander.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-highlander.c	2009-09-09 18:13:59.000000000 -0400
@@ -373,7 +373,7 @@
 	if (unlikely(!dev))
 		return -ENOMEM;
 
-	dev->base = ioremap_nocache(res->start, res->end - res->start + 1);
+	dev->base = ioremap_nocache(res->start, resource_size(res));
 	if (unlikely(!dev->base)) {
 		ret = -ENXIO;
 		goto err;
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-ibm_iic.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-ibm_iic.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-ibm_iic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-ibm_iic.c	2009-09-09 18:13:59.000000000 -0400
@@ -85,10 +85,11 @@
 {
 	volatile struct iic_regs __iomem *iic = dev->vaddr;
 	printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header);
-	printk(KERN_DEBUG "  cntl     = 0x%02x, mdcntl = 0x%02x\n"
-	       KERN_DEBUG "  sts      = 0x%02x, extsts = 0x%02x\n"
-	       KERN_DEBUG "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
-	       KERN_DEBUG "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",
+	printk(KERN_DEBUG
+	       "  cntl     = 0x%02x, mdcntl = 0x%02x\n"
+	       "  sts      = 0x%02x, extsts = 0x%02x\n"
+	       "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
+	       "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",
 		in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
 		in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
 		in_8(&iic->xtcntlss), in_8(&iic->directcntl));
@@ -756,12 +757,12 @@
 		goto error_cleanup;
 	}
 
-	/* Now register all the child nodes */
-	of_register_i2c_devices(adap, np);
-
 	dev_info(&ofdev->dev, "using %s mode\n",
 		 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
 
+	/* Now register all the child nodes */
+	of_register_i2c_devices(adap, np);
+
 	return 0;
 
 error_cleanup:
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-mpc.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-mpc.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-mpc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-mpc.c	2009-09-09 18:13:59.000000000 -0400
@@ -197,7 +197,7 @@
 		return -EINVAL;
 
 	/* Determine divider value */
-	divider = mpc52xx_find_ipb_freq(node) / clock;
+	divider = mpc5xxx_get_bus_frequency(node) / clock;
 
 	/*
 	 * We want to choose an FDR/DFSR that generates an I2C bus speed that
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-mv64xxx.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-mv64xxx.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-mv64xxx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-mv64xxx.c	2009-09-09 18:13:59.000000000 -0400
@@ -469,7 +469,7 @@
 	if (!r)
 		return -ENODEV;
 
-	size = r->end - r->start + 1;
+	size = resource_size(r);
 
 	if (!request_mem_region(r->start, size, drv_data->adapter.name))
 		return -EBUSY;
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-ocores.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-ocores.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-ocores.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-ocores.c	2009-09-09 18:13:59.000000000 -0400
@@ -216,6 +216,7 @@
 	struct ocores_i2c_platform_data *pdata;
 	struct resource *res, *res2;
 	int ret;
+	int i;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -233,14 +234,14 @@
 	if (!i2c)
 		return -ENOMEM;
 
-	if (!request_mem_region(res->start, res->end - res->start + 1,
+	if (!request_mem_region(res->start, resource_size(res),
 				pdev->name)) {
 		dev_err(&pdev->dev, "Memory region busy\n");
 		ret = -EBUSY;
 		goto request_mem_failed;
 	}
 
-	i2c->base = ioremap(res->start, res->end - res->start + 1);
+	i2c->base = ioremap(res->start, resource_size(res));
 	if (!i2c->base) {
 		dev_err(&pdev->dev, "Unable to map registers\n");
 		ret = -EIO;
@@ -271,6 +272,10 @@
 		goto add_adapter_failed;
 	}
 
+	/* add in known devices to the bus */
+	for (i = 0; i < pdata->num_devices; i++)
+		i2c_new_device(&i2c->adap, pdata->devices + i);
+
 	return 0;
 
 add_adapter_failed:
@@ -278,7 +283,7 @@
 request_irq_failed:
 	iounmap(i2c->base);
 map_failed:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 request_mem_failed:
 	kfree(i2c);
 
@@ -306,7 +311,7 @@
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res)
-		release_mem_region(res->start, res->end - res->start + 1);
+		release_mem_region(res->start, resource_size(res));
 
 	kfree(i2c);
 
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-omap.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-omap.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-omap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-omap.c	2009-09-09 18:13:59.000000000 -0400
@@ -333,8 +333,18 @@
 
 	if (cpu_is_omap2430() || cpu_is_omap34xx()) {
 
-		/* HSI2C controller internal clk rate should be 19.2 Mhz */
-		internal_clk = 19200;
+		/*
+		 * HSI2C controller internal clk rate should be 19.2 Mhz for
+		 * HS and for all modes on 2430. On 34xx we can use lower rate
+		 * to get longer filter period for better noise suppression.
+		 * The filter is iclk (fclk for HS) period.
+		 */
+		if (dev->speed > 400 || cpu_is_omap2430())
+			internal_clk = 19200;
+		else if (dev->speed > 100)
+			internal_clk = 9600;
+		else
+			internal_clk = 4000;
 		fclk_rate = clk_get_rate(dev->fclk) / 1000;
 
 		/* Compute prescaler divisor */
@@ -343,17 +353,28 @@
 
 		/* If configured for High Speed */
 		if (dev->speed > 400) {
+			unsigned long scl;
+
 			/* For first phase of HS mode */
-			fsscll = internal_clk / (400 * 2) - 6;
-			fssclh = internal_clk / (400 * 2) - 6;
+			scl = internal_clk / 400;
+			fsscll = scl - (scl / 3) - 7;
+			fssclh = (scl / 3) - 5;
 
 			/* For second phase of HS mode */
-			hsscll = fclk_rate / (dev->speed * 2) - 6;
-			hssclh = fclk_rate / (dev->speed * 2) - 6;
+			scl = fclk_rate / dev->speed;
+			hsscll = scl - (scl / 3) - 7;
+			hssclh = (scl / 3) - 5;
+		} else if (dev->speed > 100) {
+			unsigned long scl;
+
+			/* Fast mode */
+			scl = internal_clk / dev->speed;
+			fsscll = scl - (scl / 3) - 7;
+			fssclh = (scl / 3) - 5;
 		} else {
-			/* To handle F/S modes */
-			fsscll = internal_clk / (dev->speed * 2) - 6;
-			fssclh = internal_clk / (dev->speed * 2) - 6;
+			/* Standard mode */
+			fsscll = internal_clk / (dev->speed * 2) - 7;
+			fssclh = internal_clk / (dev->speed * 2) - 5;
 		}
 		scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
 		sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
@@ -651,9 +672,17 @@
 			break;
 		}
 
-		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
-
 		err = 0;
+complete:
+		/*
+		 * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be
+		 * acked after the data operation is complete.
+		 * Ref: TRM SWPU114Q Figure 18-31
+		 */
+		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+				~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+				OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+
 		if (stat & OMAP_I2C_STAT_NACK) {
 			err |= OMAP_I2C_STAT_NACK;
 			omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
@@ -664,16 +693,22 @@
 			err |= OMAP_I2C_STAT_AL;
 		}
 		if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
-					OMAP_I2C_STAT_AL))
+					OMAP_I2C_STAT_AL)) {
+			omap_i2c_ack_stat(dev, stat &
+				(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+				OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
 			omap_i2c_complete_cmd(dev, err);
+			return IRQ_HANDLED;
+		}
 		if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
 			u8 num_bytes = 1;
 			if (dev->fifo_size) {
 				if (stat & OMAP_I2C_STAT_RRDY)
 					num_bytes = dev->fifo_size;
-				else
-					num_bytes = omap_i2c_read_reg(dev,
-							OMAP_I2C_BUFSTAT_REG);
+				else    /* read RXSTAT on RDR interrupt */
+					num_bytes = (omap_i2c_read_reg(dev,
+							OMAP_I2C_BUFSTAT_REG)
+							>> 8) & 0x3F;
 			}
 			while (num_bytes) {
 				num_bytes--;
@@ -710,9 +745,10 @@
 			if (dev->fifo_size) {
 				if (stat & OMAP_I2C_STAT_XRDY)
 					num_bytes = dev->fifo_size;
-				else
+				else    /* read TXSTAT on XDR interrupt */
 					num_bytes = omap_i2c_read_reg(dev,
-							OMAP_I2C_BUFSTAT_REG);
+							OMAP_I2C_BUFSTAT_REG)
+							& 0x3F;
 			}
 			while (num_bytes) {
 				num_bytes--;
@@ -739,6 +775,27 @@
 							"data to send\n");
 					break;
 				}
+
+				/*
+				 * OMAP3430 Errata 1.153: When an XRDY/XDR
+				 * is hit, wait for XUDF before writing data
+				 * to DATA_REG. Otherwise some data bytes can
+				 * be lost while transferring them from the
+				 * memory to the I2C interface.
+				 */
+
+				if (dev->rev <= OMAP_I2C_REV_ON_3430) {
+						while (!(stat & OMAP_I2C_STAT_XUDF)) {
+							if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
+								omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+								err |= OMAP_I2C_STAT_XUDF;
+								goto complete;
+							}
+							cpu_relax();
+							stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+						}
+				}
+
 				omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
 			}
 			omap_i2c_ack_stat(dev,
@@ -785,7 +842,7 @@
 		return -ENODEV;
 	}
 
-	ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+	ioarea = request_mem_region(mem->start, resource_size(mem),
 			pdev->name);
 	if (!ioarea) {
 		dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -807,7 +864,7 @@
 	dev->idle = 1;
 	dev->dev = &pdev->dev;
 	dev->irq = irq->start;
-	dev->base = ioremap(mem->start, mem->end - mem->start + 1);
+	dev->base = ioremap(mem->start, resource_size(mem));
 	if (!dev->base) {
 		r = -ENOMEM;
 		goto err_free_mem;
@@ -858,7 +915,7 @@
 	i2c_set_adapdata(adap, dev);
 	adap->owner = THIS_MODULE;
 	adap->class = I2C_CLASS_HWMON;
-	strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+	strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
 	adap->algo = &omap_i2c_algo;
 	adap->dev.parent = &pdev->dev;
 
@@ -884,7 +941,7 @@
 	platform_set_drvdata(pdev, NULL);
 	kfree(dev);
 err_release_region:
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 
 	return r;
 }
@@ -904,7 +961,7 @@
 	iounmap(dev->base);
 	kfree(dev);
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-pca-platform.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-pca-platform.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-pca-platform.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-pca-platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,8 +27,6 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 
-#define res_len(r)		((r)->end - (r)->start + 1)
-
 struct i2c_pca_pf_data {
 	void __iomem			*reg_base;
 	int				irq;	/* if 0, use polling */
@@ -148,7 +146,7 @@
 		goto e_print;
 	}
 
-	if (!request_mem_region(res->start, res_len(res), res->name)) {
+	if (!request_mem_region(res->start, resource_size(res), res->name)) {
 		ret = -ENOMEM;
 		goto e_print;
 	}
@@ -161,13 +159,13 @@
 
 	init_waitqueue_head(&i2c->wait);
 
-	i2c->reg_base = ioremap(res->start, res_len(res));
+	i2c->reg_base = ioremap(res->start, resource_size(res));
 	if (!i2c->reg_base) {
 		ret = -ENOMEM;
 		goto e_remap;
 	}
 	i2c->io_base = res->start;
-	i2c->io_size = res_len(res);
+	i2c->io_size = resource_size(res);
 	i2c->irq = irq;
 
 	i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
@@ -250,7 +248,7 @@
 e_remap:
 	kfree(i2c);
 e_alloc:
-	release_mem_region(res->start, res_len(res));
+	release_mem_region(res->start, resource_size(res));
 e_print:
 	printk(KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n", ret);
 	return ret;
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-pmcmsp.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-pmcmsp.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-pmcmsp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-pmcmsp.c	2009-09-09 18:13:59.000000000 -0400
@@ -283,7 +283,7 @@
 	}
 
 	/* reserve the memory region */
-	if (!request_mem_region(res->start, res->end - res->start + 1,
+	if (!request_mem_region(res->start, resource_size(res),
 				pldev->name)) {
 		dev_err(&pldev->dev,
 			"Unable to get memory/io address region 0x%08x\n",
@@ -294,7 +294,7 @@
 
 	/* remap the memory */
 	pmcmsptwi_data.iobase = ioremap_nocache(res->start,
-						res->end - res->start + 1);
+						resource_size(res));
 	if (!pmcmsptwi_data.iobase) {
 		dev_err(&pldev->dev,
 			"Unable to ioremap address 0x%08x\n", res->start);
@@ -360,7 +360,7 @@
 	iounmap(pmcmsptwi_data.iobase);
 
 ret_unreserve:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 ret_err:
 	return rc;
@@ -385,7 +385,7 @@
 	iounmap(pmcmsptwi_data.iobase);
 
 	res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-pxa.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-pxa.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-pxa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-pxa.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,10 +34,24 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 
-#include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
+
+/*
+ * I2C register offsets will be shifted 0 or 1 bit left, depending on
+ * different SoCs
+ */
+#define REG_SHIFT_0	(0 << 0)
+#define REG_SHIFT_1	(1 << 0)
+#define REG_SHIFT(d)	((d) & 0x1)
+
+static const struct platform_device_id i2c_pxa_id_table[] = {
+	{ "pxa2xx-i2c",		REG_SHIFT_1 },
+	{ "pxa3xx-pwri2c",	REG_SHIFT_0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
 
 /*
  * I2C registers and bit definitions
@@ -979,12 +993,12 @@
 	.functionality	= i2c_pxa_functionality,
 };
 
-#define res_len(r)		((r)->end - (r)->start + 1)
 static int i2c_pxa_probe(struct platform_device *dev)
 {
 	struct pxa_i2c *i2c;
 	struct resource *res;
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
+	struct platform_device_id *id = platform_get_device_id(dev);
 	int ret;
 	int irq;
 
@@ -993,7 +1007,7 @@
 	if (res == NULL || irq < 0)
 		return -ENODEV;
 
-	if (!request_mem_region(res->start, res_len(res), res->name))
+	if (!request_mem_region(res->start, resource_size(res), res->name))
 		return -ENOMEM;
 
 	i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
@@ -1023,15 +1037,15 @@
 		goto eclk;
 	}
 
-	i2c->reg_base = ioremap(res->start, res_len(res));
+	i2c->reg_base = ioremap(res->start, resource_size(res));
 	if (!i2c->reg_base) {
 		ret = -EIO;
 		goto eremap;
 	}
-	i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1;
+	i2c->reg_shift = REG_SHIFT(id->driver_data);
 
 	i2c->iobase = res->start;
-	i2c->iosize = res_len(res);
+	i2c->iosize = resource_size(res);
 
 	i2c->irq = irq;
 
@@ -1095,7 +1109,7 @@
 eclk:
 	kfree(i2c);
 emalloc:
-	release_mem_region(res->start, res_len(res));
+	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
@@ -1150,6 +1164,7 @@
 		.name	= "pxa2xx-i2c",
 		.owner	= THIS_MODULE,
 	},
+	.id_table	= i2c_pxa_id_table,
 };
 
 static int __init i2c_adap_pxa_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-s3c2410.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-s3c2410.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-s3c2410.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-s3c2410.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,6 +51,11 @@
 	STATE_STOP
 };
 
+enum s3c24xx_i2c_type {
+	TYPE_S3C2410,
+	TYPE_S3C2440,
+};
+
 struct s3c24xx_i2c {
 	spinlock_t		lock;
 	wait_queue_head_t	wait;
@@ -88,8 +93,10 @@
 static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
 {
 	struct platform_device *pdev = to_platform_device(i2c->dev);
+	enum s3c24xx_i2c_type type;
 
-	return !strcmp(pdev->name, "s3c2440-i2c");
+	type = platform_get_device_id(pdev)->driver_data;
+	return type == TYPE_S3C2440;
 }
 
 /* s3c24xx_i2c_master_complete
@@ -756,11 +763,6 @@
 	dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
 	dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
 
-	/* check for s3c2440 i2c controller  */
-
-	if (s3c24xx_i2c_is2440(i2c))
-		writel(0x0, i2c->regs + S3C2440_IICLC);
-
 	return 0;
 }
 
@@ -821,7 +823,7 @@
 		goto err_clk;
 	}
 
-	i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
+	i2c->ioarea = request_mem_region(res->start, resource_size(res),
 					 pdev->name);
 
 	if (i2c->ioarea == NULL) {
@@ -830,7 +832,7 @@
 		goto err_clk;
 	}
 
-	i2c->regs = ioremap(res->start, (res->end-res->start)+1);
+	i2c->regs = ioremap(res->start, resource_size(res));
 
 	if (i2c->regs == NULL) {
 		dev_err(&pdev->dev, "cannot map IO\n");
@@ -969,52 +971,41 @@
 
 /* device driver for platform bus bits */
 
-static struct platform_driver s3c2410_i2c_driver = {
-	.probe		= s3c24xx_i2c_probe,
-	.remove		= s3c24xx_i2c_remove,
-	.suspend_late	= s3c24xx_i2c_suspend_late,
-	.resume		= s3c24xx_i2c_resume,
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "s3c2410-i2c",
-	},
+static struct platform_device_id s3c24xx_driver_ids[] = {
+	{
+		.name		= "s3c2410-i2c",
+		.driver_data	= TYPE_S3C2410,
+	}, {
+		.name		= "s3c2440-i2c",
+		.driver_data	= TYPE_S3C2440,
+	}, { },
 };
+MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
 
-static struct platform_driver s3c2440_i2c_driver = {
+static struct platform_driver s3c24xx_i2c_driver = {
 	.probe		= s3c24xx_i2c_probe,
 	.remove		= s3c24xx_i2c_remove,
 	.suspend_late	= s3c24xx_i2c_suspend_late,
 	.resume		= s3c24xx_i2c_resume,
+	.id_table	= s3c24xx_driver_ids,
 	.driver		= {
 		.owner	= THIS_MODULE,
-		.name	= "s3c2440-i2c",
+		.name	= "s3c-i2c",
 	},
 };
 
 static int __init i2c_adap_s3c_init(void)
 {
-	int ret;
-
-	ret = platform_driver_register(&s3c2410_i2c_driver);
-	if (ret == 0) {
-		ret = platform_driver_register(&s3c2440_i2c_driver);
-		if (ret)
-			platform_driver_unregister(&s3c2410_i2c_driver);
-	}
-
-	return ret;
+	return platform_driver_register(&s3c24xx_i2c_driver);
 }
 subsys_initcall(i2c_adap_s3c_init);
 
 static void __exit i2c_adap_s3c_exit(void)
 {
-	platform_driver_unregister(&s3c2410_i2c_driver);
-	platform_driver_unregister(&s3c2440_i2c_driver);
+	platform_driver_unregister(&s3c24xx_i2c_driver);
 }
 module_exit(i2c_adap_s3c_exit);
 
 MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s3c2410-i2c");
-MODULE_ALIAS("platform:s3c2440-i2c");
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-sh7760.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-sh7760.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-sh7760.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-sh7760.c	2009-09-09 18:13:59.000000000 -0400
@@ -396,7 +396,7 @@
 	signed char cdf, cdfm;
 	int scgd, scgdm, scgds;
 
-	mclk = clk_get(NULL, "module_clk");
+	mclk = clk_get(NULL, "peripheral_clk");
 	if (IS_ERR(mclk)) {
 		return PTR_ERR(mclk);
 	} else {
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-sh_mobile.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-sh_mobile.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2009-09-09 18:13:59.000000000 -0400
@@ -563,7 +563,7 @@
 		goto err_irq;
 	}
 
-	size = (res->end - res->start) + 1;
+	size = resource_size(res);
 
 	pd->reg = ioremap(res->start, size);
 	if (pd->reg == NULL) {
@@ -637,7 +637,7 @@
 	platform_driver_unregister(&sh_mobile_i2c_driver);
 }
 
-module_init(sh_mobile_i2c_adap_init);
+subsys_initcall(sh_mobile_i2c_adap_init);
 module_exit(sh_mobile_i2c_adap_exit);
 
 MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-simtec.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-simtec.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-simtec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-simtec.c	2009-09-09 18:13:59.000000000 -0400
@@ -92,7 +92,7 @@
 		goto err;
 	}
 
-	size = (res->end-res->start)+1;
+	size = resource_size(res);
 
 	pd->ioarea = request_mem_region(res->start, size, dev->name);
 	if (pd->ioarea == NULL) {
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-stu300.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-stu300.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-stu300.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-stu300.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1056 @@
+/*
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * ST DDC I2C master mode driver, used in e.g. U300 series platforms.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+/* the name of this kernel module */
+#define NAME "stu300"
+
+/* CR (Control Register) 8bit (R/W) */
+#define I2C_CR					(0x00000000)
+#define I2C_CR_RESET_VALUE			(0x00)
+#define I2C_CR_RESET_UMASK			(0x00)
+#define I2C_CR_DDC1_ENABLE			(0x80)
+#define I2C_CR_TRANS_ENABLE			(0x40)
+#define I2C_CR_PERIPHERAL_ENABLE		(0x20)
+#define I2C_CR_DDC2B_ENABLE			(0x10)
+#define I2C_CR_START_ENABLE			(0x08)
+#define I2C_CR_ACK_ENABLE			(0x04)
+#define I2C_CR_STOP_ENABLE			(0x02)
+#define I2C_CR_INTERRUPT_ENABLE			(0x01)
+/* SR1 (Status Register 1) 8bit (R/-) */
+#define I2C_SR1					(0x00000004)
+#define I2C_SR1_RESET_VALUE			(0x00)
+#define I2C_SR1_RESET_UMASK			(0x00)
+#define I2C_SR1_EVF_IND				(0x80)
+#define I2C_SR1_ADD10_IND			(0x40)
+#define I2C_SR1_TRA_IND				(0x20)
+#define I2C_SR1_BUSY_IND			(0x10)
+#define I2C_SR1_BTF_IND				(0x08)
+#define I2C_SR1_ADSL_IND			(0x04)
+#define I2C_SR1_MSL_IND				(0x02)
+#define I2C_SR1_SB_IND				(0x01)
+/* SR2 (Status Register 2) 8bit (R/-) */
+#define I2C_SR2					(0x00000008)
+#define I2C_SR2_RESET_VALUE			(0x00)
+#define I2C_SR2_RESET_UMASK			(0x40)
+#define I2C_SR2_MASK				(0xBF)
+#define I2C_SR2_SCLFAL_IND			(0x80)
+#define I2C_SR2_ENDAD_IND			(0x20)
+#define I2C_SR2_AF_IND				(0x10)
+#define I2C_SR2_STOPF_IND			(0x08)
+#define I2C_SR2_ARLO_IND			(0x04)
+#define I2C_SR2_BERR_IND			(0x02)
+#define I2C_SR2_DDC2BF_IND			(0x01)
+/* CCR (Clock Control Register) 8bit (R/W) */
+#define I2C_CCR					(0x0000000C)
+#define I2C_CCR_RESET_VALUE			(0x00)
+#define I2C_CCR_RESET_UMASK			(0x00)
+#define I2C_CCR_MASK				(0xFF)
+#define I2C_CCR_FMSM				(0x80)
+#define I2C_CCR_CC_MASK				(0x7F)
+/* OAR1 (Own Address Register 1) 8bit (R/W) */
+#define I2C_OAR1				(0x00000010)
+#define I2C_OAR1_RESET_VALUE			(0x00)
+#define I2C_OAR1_RESET_UMASK			(0x00)
+#define I2C_OAR1_ADD_MASK			(0xFF)
+/* OAR2 (Own Address Register 2) 8bit (R/W) */
+#define I2C_OAR2				(0x00000014)
+#define I2C_OAR2_RESET_VALUE			(0x40)
+#define I2C_OAR2_RESET_UMASK			(0x19)
+#define I2C_OAR2_MASK				(0xE6)
+#define I2C_OAR2_FR_25_10MHZ			(0x00)
+#define I2C_OAR2_FR_10_1667MHZ			(0x20)
+#define I2C_OAR2_FR_1667_2667MHZ		(0x40)
+#define I2C_OAR2_FR_2667_40MHZ			(0x60)
+#define I2C_OAR2_FR_40_5333MHZ			(0x80)
+#define I2C_OAR2_FR_5333_66MHZ			(0xA0)
+#define I2C_OAR2_FR_66_80MHZ			(0xC0)
+#define I2C_OAR2_FR_80_100MHZ			(0xE0)
+#define I2C_OAR2_FR_MASK			(0xE0)
+#define I2C_OAR2_ADD_MASK			(0x06)
+/* DR (Data Register) 8bit (R/W) */
+#define I2C_DR					(0x00000018)
+#define I2C_DR_RESET_VALUE			(0x00)
+#define I2C_DR_RESET_UMASK			(0xFF)
+#define I2C_DR_D_MASK				(0xFF)
+/* ECCR (Extended Clock Control Register) 8bit (R/W) */
+#define I2C_ECCR				(0x0000001C)
+#define I2C_ECCR_RESET_VALUE			(0x00)
+#define I2C_ECCR_RESET_UMASK			(0xE0)
+#define I2C_ECCR_MASK				(0x1F)
+#define I2C_ECCR_CC_MASK			(0x1F)
+
+/*
+ * These events are more or less responses to commands
+ * sent into the hardware, presumably reflecting the state
+ * of an internal state machine.
+ */
+enum stu300_event {
+	STU300_EVENT_NONE = 0,
+	STU300_EVENT_1,
+	STU300_EVENT_2,
+	STU300_EVENT_3,
+	STU300_EVENT_4,
+	STU300_EVENT_5,
+	STU300_EVENT_6,
+	STU300_EVENT_7,
+	STU300_EVENT_8,
+	STU300_EVENT_9
+};
+
+enum stu300_error {
+	STU300_ERROR_NONE = 0,
+	STU300_ERROR_ACKNOWLEDGE_FAILURE,
+	STU300_ERROR_BUS_ERROR,
+	STU300_ERROR_ARBITRATION_LOST,
+	STU300_ERROR_UNKNOWN
+};
+
+/* timeout waiting for the controller to respond */
+#define STU300_TIMEOUT (msecs_to_jiffies(1000))
+
+/*
+ * The number of address send athemps tried before giving up.
+ * If the first one failes it seems like 5 to 8 attempts are required.
+ */
+#define NUM_ADDR_RESEND_ATTEMPTS 12
+
+/* I2C clock speed, in Hz 0-400kHz*/
+static unsigned int scl_frequency = 100000;
+module_param(scl_frequency, uint,  0644);
+
+/**
+ * struct stu300_dev - the stu300 driver state holder
+ * @pdev: parent platform device
+ * @adapter: corresponding I2C adapter
+ * @phybase: location of I/O area in memory
+ * @physize: size of I/O area in memory
+ * @clk: hardware block clock
+ * @irq: assigned interrupt line
+ * @cmd_issue_lock: this locks the following cmd_ variables
+ * @cmd_complete: acknowledge completion for an I2C command
+ * @cmd_event: expected event coming in as a response to a command
+ * @cmd_err: error code as response to a command
+ * @speed: current bus speed in Hz
+ * @msg_index: index of current message
+ * @msg_len: length of current message
+ */
+
+struct stu300_dev {
+	struct platform_device	*pdev;
+	struct i2c_adapter	adapter;
+	resource_size_t		phybase;
+	resource_size_t		physize;
+	void __iomem		*virtbase;
+	struct clk		*clk;
+	int			irq;
+	spinlock_t		cmd_issue_lock;
+	struct completion	cmd_complete;
+	enum stu300_event	cmd_event;
+	enum stu300_error	cmd_err;
+	unsigned int		speed;
+	int			msg_index;
+	int			msg_len;
+};
+
+/* Local forward function declarations */
+static int stu300_init_hw(struct stu300_dev *dev);
+
+/*
+ * The block needs writes in both MSW and LSW in order
+ * for all data lines to reach their destination.
+ */
+static inline void stu300_wr8(u32 value, void __iomem *address)
+{
+	writel((value << 16) | value, address);
+}
+
+/*
+ * This merely masks off the duplicates which appear
+ * in bytes 1-3. You _MUST_ use 32-bit bus access on this
+ * device, else it will not work.
+ */
+static inline u32 stu300_r8(void __iomem *address)
+{
+	return readl(address) & 0x000000FFU;
+}
+
+static void stu300_irq_enable(struct stu300_dev *dev)
+{
+	u32 val;
+	val = stu300_r8(dev->virtbase + I2C_CR);
+	val |= I2C_CR_INTERRUPT_ENABLE;
+	/* Twice paranoia (possible HW glitch) */
+	stu300_wr8(val, dev->virtbase + I2C_CR);
+	stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+static void stu300_irq_disable(struct stu300_dev *dev)
+{
+	u32 val;
+	val = stu300_r8(dev->virtbase + I2C_CR);
+	val &= ~I2C_CR_INTERRUPT_ENABLE;
+	/* Twice paranoia (possible HW glitch) */
+	stu300_wr8(val, dev->virtbase + I2C_CR);
+	stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+
+/*
+ * Tells whether a certain event or events occurred in
+ * response to a command. The events represent states in
+ * the internal state machine of the hardware. The events
+ * are not very well described in the hardware
+ * documentation and can only be treated as abstract state
+ * machine states.
+ *
+ * @ret 0 = event has not occurred or unknown error, any
+ * other value means the correct event occurred or an error.
+ */
+
+static int stu300_event_occurred(struct stu300_dev *dev,
+				   enum stu300_event mr_event) {
+	u32 status1;
+	u32 status2;
+
+	/* What event happened? */
+	status1 = stu300_r8(dev->virtbase + I2C_SR1);
+
+	if (!(status1 & I2C_SR1_EVF_IND))
+		/* No event at all */
+		return 0;
+
+	status2 = stu300_r8(dev->virtbase + I2C_SR2);
+
+	/* Block any multiple interrupts */
+	stu300_irq_disable(dev);
+
+	/* Check for errors first */
+	if (status2 & I2C_SR2_AF_IND) {
+		dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
+		return 1;
+	} else if (status2 & I2C_SR2_BERR_IND) {
+		dev->cmd_err = STU300_ERROR_BUS_ERROR;
+		return 1;
+	} else if (status2 & I2C_SR2_ARLO_IND) {
+		dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
+		return 1;
+	}
+
+	switch (mr_event) {
+	case STU300_EVENT_1:
+		if (status1 & I2C_SR1_ADSL_IND)
+			return 1;
+		break;
+	case STU300_EVENT_2:
+	case STU300_EVENT_3:
+	case STU300_EVENT_7:
+	case STU300_EVENT_8:
+		if (status1 & I2C_SR1_BTF_IND) {
+			return 1;
+		}
+		break;
+	case STU300_EVENT_4:
+		if (status2 & I2C_SR2_STOPF_IND)
+			return 1;
+		break;
+	case STU300_EVENT_5:
+		if (status1 & I2C_SR1_SB_IND)
+			/* Clear start bit */
+			return 1;
+		break;
+	case STU300_EVENT_6:
+		if (status2 & I2C_SR2_ENDAD_IND) {
+			/* First check for any errors */
+			return 1;
+		}
+		break;
+	case STU300_EVENT_9:
+		if (status1 & I2C_SR1_ADD10_IND)
+			return 1;
+		break;
+	default:
+		break;
+	}
+	/* If we get here, we're on thin ice.
+	 * Here we are in a status where we have
+	 * gotten a response that does not match
+	 * what we requested.
+	 */
+	dev->cmd_err = STU300_ERROR_UNKNOWN;
+	dev_err(&dev->pdev->dev,
+		"Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n",
+		mr_event, status1, status2);
+	return 0;
+}
+
+static irqreturn_t stu300_irh(int irq, void *data)
+{
+	struct stu300_dev *dev = data;
+	int res;
+
+	/* Just make sure that the block is clocked */
+	clk_enable(dev->clk);
+
+	/* See if this was what we were waiting for */
+	spin_lock(&dev->cmd_issue_lock);
+
+	res = stu300_event_occurred(dev, dev->cmd_event);
+	if (res || dev->cmd_err != STU300_ERROR_NONE)
+		complete(&dev->cmd_complete);
+
+	spin_unlock(&dev->cmd_issue_lock);
+
+	clk_disable(dev->clk);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Sends a command and then waits for the bits masked by *flagmask*
+ * to go high or low by IRQ awaiting.
+ */
+static int stu300_start_and_await_event(struct stu300_dev *dev,
+					  u8 cr_value,
+					  enum stu300_event mr_event)
+{
+	int ret;
+
+	if (unlikely(irqs_disabled())) {
+		/* TODO: implement polling for this case if need be. */
+		WARN(1, "irqs are disabled, cannot poll for event\n");
+		return -EIO;
+	}
+
+	/* Lock command issue, fill in an event we wait for */
+	spin_lock_irq(&dev->cmd_issue_lock);
+	init_completion(&dev->cmd_complete);
+	dev->cmd_err = STU300_ERROR_NONE;
+	dev->cmd_event = mr_event;
+	spin_unlock_irq(&dev->cmd_issue_lock);
+
+	/* Turn on interrupt, send command and wait. */
+	cr_value |= I2C_CR_INTERRUPT_ENABLE;
+	stu300_wr8(cr_value, dev->virtbase + I2C_CR);
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+							STU300_TIMEOUT);
+	if (ret < 0) {
+		dev_err(&dev->pdev->dev,
+		       "wait_for_completion_interruptible_timeout() "
+		       "returned %d waiting for event %04x\n", ret, mr_event);
+		return ret;
+	}
+
+	if (ret == 0) {
+		dev_err(&dev->pdev->dev, "controller timed out "
+		       "waiting for event %d, reinit hardware\n", mr_event);
+		(void) stu300_init_hw(dev);
+		return -ETIMEDOUT;
+	}
+
+	if (dev->cmd_err != STU300_ERROR_NONE) {
+		dev_err(&dev->pdev->dev, "controller (start) "
+		       "error %d waiting for event %d, reinit hardware\n",
+		       dev->cmd_err, mr_event);
+		(void) stu300_init_hw(dev);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * This waits for a flag to be set, if it is not set on entry, an interrupt is
+ * configured to wait for the flag using a completion.
+ */
+static int stu300_await_event(struct stu300_dev *dev,
+				enum stu300_event mr_event)
+{
+	int ret;
+
+	if (unlikely(irqs_disabled())) {
+		/* TODO: implement polling for this case if need be. */
+		dev_err(&dev->pdev->dev, "irqs are disabled on this "
+			"system!\n");
+		return -EIO;
+	}
+
+	/* Is it already here? */
+	spin_lock_irq(&dev->cmd_issue_lock);
+	dev->cmd_err = STU300_ERROR_NONE;
+	dev->cmd_event = mr_event;
+
+	init_completion(&dev->cmd_complete);
+
+	/* Turn on the I2C interrupt for current operation */
+	stu300_irq_enable(dev);
+
+	/* Unlock the command block and wait for the event to occur */
+	spin_unlock_irq(&dev->cmd_issue_lock);
+
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+							STU300_TIMEOUT);
+	if (ret < 0) {
+		dev_err(&dev->pdev->dev,
+		       "wait_for_completion_interruptible_timeout()"
+		       "returned %d waiting for event %04x\n", ret, mr_event);
+		return ret;
+	}
+
+	if (ret == 0) {
+		if (mr_event != STU300_EVENT_6) {
+			dev_err(&dev->pdev->dev, "controller "
+				"timed out waiting for event %d, reinit "
+				"hardware\n", mr_event);
+			(void) stu300_init_hw(dev);
+		}
+		return -ETIMEDOUT;
+	}
+
+	if (dev->cmd_err != STU300_ERROR_NONE) {
+		if (mr_event != STU300_EVENT_6) {
+			dev_err(&dev->pdev->dev, "controller "
+				"error (await_event) %d waiting for event %d, "
+			       "reinit hardware\n", dev->cmd_err, mr_event);
+			(void) stu300_init_hw(dev);
+		}
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * Waits for the busy bit to go low by repeated polling.
+ */
+#define BUSY_RELEASE_ATTEMPTS 10
+static int stu300_wait_while_busy(struct stu300_dev *dev)
+{
+	unsigned long timeout;
+	int i;
+
+	for (i = 0; i < BUSY_RELEASE_ATTEMPTS; i++) {
+		timeout = jiffies + STU300_TIMEOUT;
+
+		while (!time_after(jiffies, timeout)) {
+			/* Is not busy? */
+			if ((stu300_r8(dev->virtbase + I2C_SR1) &
+			     I2C_SR1_BUSY_IND) == 0)
+				return 0;
+			msleep(1);
+		}
+
+		dev_err(&dev->pdev->dev, "transaction timed out "
+			"waiting for device to be free (not busy). "
+		       "Attempt: %d\n", i+1);
+
+		dev_err(&dev->pdev->dev, "base address = "
+			"0x%08x, reinit hardware\n", (u32) dev->virtbase);
+
+		(void) stu300_init_hw(dev);
+	}
+
+	dev_err(&dev->pdev->dev, "giving up after %d attempts "
+		"to reset the bus.\n",  BUSY_RELEASE_ATTEMPTS);
+
+	return -ETIMEDOUT;
+}
+
+struct stu300_clkset {
+	unsigned long rate;
+	u32 setting;
+};
+
+static const struct stu300_clkset stu300_clktable[] = {
+	{ 0,         0xFFU },
+	{ 2500000,   I2C_OAR2_FR_25_10MHZ },
+	{ 10000000,  I2C_OAR2_FR_10_1667MHZ },
+	{ 16670000,  I2C_OAR2_FR_1667_2667MHZ },
+	{ 26670000,  I2C_OAR2_FR_2667_40MHZ },
+	{ 40000000,  I2C_OAR2_FR_40_5333MHZ },
+	{ 53330000,  I2C_OAR2_FR_5333_66MHZ },
+	{ 66000000,  I2C_OAR2_FR_66_80MHZ },
+	{ 80000000,  I2C_OAR2_FR_80_100MHZ },
+	{ 100000000, 0xFFU },
+};
+
+
+static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
+{
+
+	u32 val;
+	int i = 0;
+
+	/* Locate the apropriate clock setting */
+	while (i < ARRAY_SIZE(stu300_clktable) &&
+	       stu300_clktable[i].rate < clkrate)
+		i++;
+
+	if (stu300_clktable[i].setting == 0xFFU) {
+		dev_err(&dev->pdev->dev, "too %s clock rate requested "
+			"(%lu Hz).\n", i ? "high" : "low", clkrate);
+		return -EINVAL;
+	}
+
+	stu300_wr8(stu300_clktable[i].setting,
+		   dev->virtbase + I2C_OAR2);
+
+	dev_dbg(&dev->pdev->dev, "Clock rate %lu Hz, I2C bus speed %d Hz "
+		"virtbase %p\n", clkrate, dev->speed, dev->virtbase);
+
+	if (dev->speed > 100000)
+		/* Fast Mode I2C */
+		val = ((clkrate/dev->speed) - 9)/3 + 1;
+	else
+		/* Standard Mode I2C */
+		val = ((clkrate/dev->speed) - 7)/2 + 1;
+
+	/* According to spec the divider must be > 2 */
+	if (val < 0x002) {
+		dev_err(&dev->pdev->dev, "too low clock rate (%lu Hz).\n",
+			clkrate);
+		return -EINVAL;
+	}
+
+	/* We have 12 bits clock divider only! */
+	if (val & 0xFFFFF000U) {
+		dev_err(&dev->pdev->dev, "too high clock rate (%lu Hz).\n",
+			clkrate);
+		return -EINVAL;
+	}
+
+	if (dev->speed > 100000) {
+		/* CC6..CC0 */
+		stu300_wr8((val & I2C_CCR_CC_MASK) | I2C_CCR_FMSM,
+			   dev->virtbase + I2C_CCR);
+		dev_dbg(&dev->pdev->dev, "set clock divider to 0x%08x, "
+			"Fast Mode I2C\n", val);
+	} else {
+		/* CC6..CC0 */
+		stu300_wr8((val & I2C_CCR_CC_MASK),
+			   dev->virtbase + I2C_CCR);
+		dev_dbg(&dev->pdev->dev, "set clock divider to "
+			"0x%08x, Standard Mode I2C\n", val);
+	}
+
+	/* CC11..CC7 */
+	stu300_wr8(((val >> 7) & 0x1F),
+		   dev->virtbase + I2C_ECCR);
+
+	return 0;
+}
+
+
+static int stu300_init_hw(struct stu300_dev *dev)
+{
+	u32 dummy;
+	unsigned long clkrate;
+	int ret;
+
+	/* Disable controller */
+	stu300_wr8(0x00, dev->virtbase + I2C_CR);
+	/*
+	 * Set own address to some default value (0x00).
+	 * We do not support slave mode anyway.
+	 */
+	stu300_wr8(0x00, dev->virtbase + I2C_OAR1);
+	/*
+	 * The I2C controller only operates properly in 26 MHz but we
+	 * program this driver as if we didn't know. This will also set the two
+	 * high bits of the own address to zero as well.
+	 * There is no known hardware issue with running in 13 MHz
+	 * However, speeds over 200 kHz are not used.
+	 */
+	clkrate = clk_get_rate(dev->clk);
+	ret = stu300_set_clk(dev, clkrate);
+
+	if (ret)
+		return ret;
+	/*
+	 * Enable block, do it TWICE (hardware glitch)
+	 * Setting bit 7 can enable DDC mode. (Not used currently.)
+	 */
+	stu300_wr8(I2C_CR_PERIPHERAL_ENABLE,
+				  dev->virtbase + I2C_CR);
+	stu300_wr8(I2C_CR_PERIPHERAL_ENABLE,
+				  dev->virtbase + I2C_CR);
+	/* Make a dummy read of the status register SR1 & SR2 */
+	dummy = stu300_r8(dev->virtbase + I2C_SR2);
+	dummy = stu300_r8(dev->virtbase + I2C_SR1);
+
+	return 0;
+}
+
+
+
+/* Send slave address. */
+static int stu300_send_address(struct stu300_dev *dev,
+				 struct i2c_msg *msg, int resend)
+{
+	u32 val;
+	int ret;
+
+	if (msg->flags & I2C_M_TEN)
+		/* This is probably how 10 bit addresses look */
+		val = (0xf0 | (((u32) msg->addr & 0x300) >> 7)) &
+			I2C_DR_D_MASK;
+	else
+		val = ((msg->addr << 1) & I2C_DR_D_MASK);
+
+	if (msg->flags & I2C_M_RD) {
+		/* This is the direction bit */
+		val |= 0x01;
+		if (resend)
+			dev_dbg(&dev->pdev->dev, "read resend\n");
+	} else if (resend)
+		dev_dbg(&dev->pdev->dev, "write resend\n");
+	stu300_wr8(val, dev->virtbase + I2C_DR);
+
+	/* For 10bit addressing, await 10bit request (EVENT 9) */
+	if (msg->flags & I2C_M_TEN) {
+		ret = stu300_await_event(dev, STU300_EVENT_9);
+		/*
+		 * The slave device wants a 10bit address, send the rest
+		 * of the bits (the LSBits)
+		 */
+		val = msg->addr & I2C_DR_D_MASK;
+		/* This clears "event 9" */
+		stu300_wr8(val, dev->virtbase + I2C_DR);
+		if (ret != 0)
+			return ret;
+	}
+	/* FIXME: Why no else here? two events for 10bit?
+	 * Await event 6 (normal) or event 9 (10bit)
+	 */
+
+	if (resend)
+		dev_dbg(&dev->pdev->dev, "await event 6\n");
+	ret = stu300_await_event(dev, STU300_EVENT_6);
+
+	/*
+	 * Clear any pending EVENT 6 no matter what happend during
+	 * await_event.
+	 */
+	val = stu300_r8(dev->virtbase + I2C_CR);
+	val |= I2C_CR_PERIPHERAL_ENABLE;
+	stu300_wr8(val, dev->virtbase + I2C_CR);
+
+	return ret;
+}
+
+static int stu300_xfer_msg(struct i2c_adapter *adap,
+			     struct i2c_msg *msg, int stop)
+{
+	u32 cr;
+	u32 val;
+	u32 i;
+	int ret;
+	int attempts = 0;
+	struct stu300_dev *dev = i2c_get_adapdata(adap);
+
+	clk_enable(dev->clk);
+
+	/* Remove this if (0) to trace each and every message. */
+	if (0) {
+		dev_dbg(&dev->pdev->dev, "I2C message to: 0x%04x, len: %d, "
+			"flags: 0x%04x, stop: %d\n",
+			msg->addr, msg->len, msg->flags, stop);
+	}
+
+	/* Zero-length messages are not supported by this hardware */
+	if (msg->len == 0) {
+		ret = -EINVAL;
+		goto exit_disable;
+	}
+
+	/*
+	 * For some reason, sending the address sometimes fails when running
+	 * on  the 13 MHz clock. No interrupt arrives. This is a work around,
+	 * which tries to restart and send the address up to 10 times before
+	 * really giving up. Usually 5 to 8 attempts are enough.
+	 */
+	do {
+		if (attempts)
+			dev_dbg(&dev->pdev->dev, "wait while busy\n");
+		/* Check that the bus is free, or wait until some timeout */
+		ret = stu300_wait_while_busy(dev);
+		if (ret != 0)
+			goto exit_disable;
+
+		if (attempts)
+			dev_dbg(&dev->pdev->dev, "re-int hw\n");
+		/*
+		 * According to ST, there is no problem if the clock is
+		 * changed between 13 and 26 MHz during a transfer.
+		 */
+		ret = stu300_init_hw(dev);
+		if (ret)
+			goto exit_disable;
+
+		/* Send a start condition */
+		cr = I2C_CR_PERIPHERAL_ENABLE;
+		/* Setting the START bit puts the block in master mode */
+		if (!(msg->flags & I2C_M_NOSTART))
+			cr |= I2C_CR_START_ENABLE;
+		if ((msg->flags & I2C_M_RD) && (msg->len > 1))
+			/* On read more than 1 byte, we need ack. */
+			cr |= I2C_CR_ACK_ENABLE;
+		/* Check that it gets through */
+		if (!(msg->flags & I2C_M_NOSTART)) {
+			if (attempts)
+				dev_dbg(&dev->pdev->dev, "send start event\n");
+			ret = stu300_start_and_await_event(dev, cr,
+							     STU300_EVENT_5);
+		}
+
+		if (attempts)
+			dev_dbg(&dev->pdev->dev, "send address\n");
+
+		if (ret == 0)
+			/* Send address */
+			ret = stu300_send_address(dev, msg, attempts != 0);
+
+		if (ret != 0) {
+			attempts++;
+			dev_dbg(&dev->pdev->dev, "failed sending address, "
+				"retrying. Attempt: %d msg_index: %d/%d\n",
+			       attempts, dev->msg_index, dev->msg_len);
+		}
+
+	} while (ret != 0 && attempts < NUM_ADDR_RESEND_ATTEMPTS);
+
+	if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) {
+		dev_dbg(&dev->pdev->dev, "managed to get address "
+			"through after %d attempts\n", attempts);
+	} else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) {
+		dev_dbg(&dev->pdev->dev, "I give up, tried %d times "
+			"to resend address.\n",
+			NUM_ADDR_RESEND_ATTEMPTS);
+		goto exit_disable;
+	}
+
+
+	if (msg->flags & I2C_M_RD) {
+		/* READ: we read the actual bytes one at a time */
+		for (i = 0; i < msg->len; i++) {
+			if (i == msg->len-1) {
+				/*
+				 * Disable ACK and set STOP condition before
+				 * reading last byte
+				 */
+				val = I2C_CR_PERIPHERAL_ENABLE;
+
+				if (stop)
+					val |= I2C_CR_STOP_ENABLE;
+
+				stu300_wr8(val,
+					   dev->virtbase + I2C_CR);
+			}
+			/* Wait for this byte... */
+			ret = stu300_await_event(dev, STU300_EVENT_7);
+			if (ret != 0)
+				goto exit_disable;
+			/* This clears event 7 */
+			msg->buf[i] = (u8) stu300_r8(dev->virtbase + I2C_DR);
+		}
+	} else {
+		/* WRITE: we send the actual bytes one at a time */
+		for (i = 0; i < msg->len; i++) {
+			/* Write the byte */
+			stu300_wr8(msg->buf[i],
+				   dev->virtbase + I2C_DR);
+			/* Check status */
+			ret = stu300_await_event(dev, STU300_EVENT_8);
+			/* Next write to DR will clear event 8 */
+			if (ret != 0) {
+				dev_err(&dev->pdev->dev, "error awaiting "
+				       "event 8 (%d)\n", ret);
+				goto exit_disable;
+			}
+		}
+		/* Check NAK */
+		if (!(msg->flags & I2C_M_IGNORE_NAK)) {
+			if (stu300_r8(dev->virtbase + I2C_SR2) &
+			    I2C_SR2_AF_IND) {
+				dev_err(&dev->pdev->dev, "I2C payload "
+				       "send returned NAK!\n");
+				ret = -EIO;
+				goto exit_disable;
+			}
+		}
+		if (stop) {
+			/* Send stop condition */
+			val = I2C_CR_PERIPHERAL_ENABLE;
+			val |= I2C_CR_STOP_ENABLE;
+			stu300_wr8(val, dev->virtbase + I2C_CR);
+		}
+	}
+
+	/* Check that the bus is free, or wait until some timeout occurs */
+	ret = stu300_wait_while_busy(dev);
+	if (ret != 0) {
+		dev_err(&dev->pdev->dev, "timout waiting for transfer "
+		       "to commence.\n");
+		goto exit_disable;
+	}
+
+	/* Dummy read status registers */
+	val = stu300_r8(dev->virtbase + I2C_SR2);
+	val = stu300_r8(dev->virtbase + I2C_SR1);
+	ret = 0;
+
+ exit_disable:
+	/* Disable controller */
+	stu300_wr8(0x00, dev->virtbase + I2C_CR);
+	clk_disable(dev->clk);
+	return ret;
+}
+
+static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			 int num)
+{
+	int ret = -1;
+	int i;
+
+	struct stu300_dev *dev = i2c_get_adapdata(adap);
+	dev->msg_len = num;
+
+	for (i = 0; i < num; i++) {
+		/*
+		 * Another driver appears to send stop for each message,
+		 * here we only do that for the last message. Possibly some
+		 * peripherals require this behaviour, then their drivers
+		 * have to send single messages in order to get "stop" for
+		 * each message.
+		 */
+		dev->msg_index = i;
+
+		ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+
+		if (ret != 0) {
+			num = ret;
+			break;
+		}
+	}
+
+	return num;
+}
+
+static u32 stu300_func(struct i2c_adapter *adap)
+{
+	/* This is the simplest thing you can think of... */
+	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm stu300_algo = {
+	.master_xfer	= stu300_xfer,
+	.functionality	= stu300_func,
+};
+
+static int __init
+stu300_probe(struct platform_device *pdev)
+{
+	struct stu300_dev *dev;
+	struct i2c_adapter *adap;
+	struct resource *res;
+	int bus_nr;
+	int ret = 0;
+	char clk_name[] = "I2C0";
+
+	dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL);
+	if (!dev) {
+		dev_err(&pdev->dev, "could not allocate device struct\n");
+		ret = -ENOMEM;
+		goto err_no_devmem;
+	}
+
+	bus_nr = pdev->id;
+	clk_name[3] += (char)bus_nr;
+	dev->clk = clk_get(&pdev->dev, clk_name);
+	if (IS_ERR(dev->clk)) {
+		ret = PTR_ERR(dev->clk);
+		dev_err(&pdev->dev, "could not retrieve i2c bus clock\n");
+		goto err_no_clk;
+	}
+
+	dev->pdev = pdev;
+	platform_set_drvdata(pdev, dev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENOENT;
+		goto err_no_resource;
+	}
+
+	dev->phybase = res->start;
+	dev->physize = resource_size(res);
+
+	if (request_mem_region(dev->phybase, dev->physize,
+			       NAME " I/O Area") == NULL) {
+		ret = -EBUSY;
+		goto err_no_ioregion;
+	}
+
+	dev->virtbase = ioremap(dev->phybase, dev->physize);
+	dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual "
+		"base %p\n", bus_nr, dev->virtbase);
+	if (!dev->virtbase) {
+		ret = -ENOMEM;
+		goto err_no_ioremap;
+	}
+
+	dev->irq = platform_get_irq(pdev, 0);
+	if (request_irq(dev->irq, stu300_irh, IRQF_DISABLED,
+			NAME, dev)) {
+		ret = -EIO;
+		goto err_no_irq;
+	}
+
+	dev->speed = scl_frequency;
+
+	clk_enable(dev->clk);
+	ret = stu300_init_hw(dev);
+	clk_disable(dev->clk);
+
+	if (ret != 0) {
+		dev_err(&dev->pdev->dev, "error initializing hardware.\n");
+		goto err_init_hw;
+	}
+
+	/* IRQ event handling initialization */
+	spin_lock_init(&dev->cmd_issue_lock);
+	dev->cmd_event = STU300_EVENT_NONE;
+	dev->cmd_err = STU300_ERROR_NONE;
+
+	adap = &dev->adapter;
+	adap->owner = THIS_MODULE;
+	/* DDC class but actually often used for more generic I2C */
+	adap->class = I2C_CLASS_DDC;
+	strncpy(adap->name, "ST Microelectronics DDC I2C adapter",
+		sizeof(adap->name));
+	adap->nr = bus_nr;
+	adap->algo = &stu300_algo;
+	adap->dev.parent = &pdev->dev;
+	i2c_set_adapdata(adap, dev);
+
+	/* i2c device drivers may be active on return from add_adapter() */
+	ret = i2c_add_numbered_adapter(adap);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "failure adding ST Micro DDC "
+		       "I2C adapter\n");
+		goto err_add_adapter;
+	}
+	return 0;
+
+ err_add_adapter:
+ err_init_hw:
+	free_irq(dev->irq, dev);
+ err_no_irq:
+	iounmap(dev->virtbase);
+ err_no_ioremap:
+	release_mem_region(dev->phybase, dev->physize);
+ err_no_ioregion:
+	platform_set_drvdata(pdev, NULL);
+ err_no_resource:
+	clk_put(dev->clk);
+ err_no_clk:
+	kfree(dev);
+ err_no_devmem:
+	dev_err(&pdev->dev, "failed to add " NAME " adapter: %d\n",
+		pdev->id);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int stu300_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct stu300_dev *dev = platform_get_drvdata(pdev);
+
+	/* Turn off everything */
+	stu300_wr8(0x00, dev->virtbase + I2C_CR);
+	return 0;
+}
+
+static int stu300_resume(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct stu300_dev *dev = platform_get_drvdata(pdev);
+
+	clk_enable(dev->clk);
+	ret = stu300_init_hw(dev);
+	clk_disable(dev->clk);
+
+	if (ret != 0)
+		dev_err(&pdev->dev, "error re-initializing hardware.\n");
+	return ret;
+}
+#else
+#define stu300_suspend NULL
+#define stu300_resume NULL
+#endif
+
+static int __exit
+stu300_remove(struct platform_device *pdev)
+{
+	struct stu300_dev *dev = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&dev->adapter);
+	/* Turn off everything */
+	stu300_wr8(0x00, dev->virtbase + I2C_CR);
+	free_irq(dev->irq, dev);
+	iounmap(dev->virtbase);
+	release_mem_region(dev->phybase, dev->physize);
+	clk_put(dev->clk);
+	platform_set_drvdata(pdev, NULL);
+	kfree(dev);
+	return 0;
+}
+
+static struct platform_driver stu300_i2c_driver = {
+	.driver = {
+		.name	= NAME,
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(stu300_remove),
+	.suspend        = stu300_suspend,
+	.resume         = stu300_resume,
+
+};
+
+static int __init stu300_init(void)
+{
+	return platform_driver_probe(&stu300_i2c_driver, stu300_probe);
+}
+
+static void __exit stu300_exit(void)
+{
+	platform_driver_unregister(&stu300_i2c_driver);
+}
+
+/*
+ * The systems using this bus often have very basic devices such
+ * as regulators on the I2C bus, so this needs to be loaded early.
+ * Therefore it is registered in the subsys_initcall().
+ */
+subsys_initcall(stu300_init);
+module_exit(stu300_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
+MODULE_DESCRIPTION("ST Micro DDC I2C adapter (" NAME ")");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" NAME);
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-versatile.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-versatile.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-versatile.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-versatile.c	2009-09-09 18:13:59.000000000 -0400
@@ -76,7 +76,7 @@
 		goto err_out;
 	}
 
-	if (!request_mem_region(r->start, r->end - r->start + 1, "versatile-i2c")) {
+	if (!request_mem_region(r->start, resource_size(r), "versatile-i2c")) {
 		ret = -EBUSY;
 		goto err_out;
 	}
@@ -87,7 +87,7 @@
 		goto err_release;
 	}
 
-	i2c->base = ioremap(r->start, r->end - r->start + 1);
+	i2c->base = ioremap(r->start, resource_size(r));
 	if (!i2c->base) {
 		ret = -ENOMEM;
 		goto err_free;
@@ -118,7 +118,7 @@
  err_free:
 	kfree(i2c);
  err_release:
-	release_mem_region(r->start, r->end - r->start + 1);
+	release_mem_region(r->start, resource_size(r));
  err_out:
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-viapro.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-viapro.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-viapro.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-viapro.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,7 @@
    VT8251             0x3287             yes
    CX700              0x8324             yes
    VX800/VX820        0x8353             yes
+   VX855/VX875        0x8409             yes
 
    Note: we assume there can only be one device, with one SMBus interface.
 */
@@ -404,6 +405,7 @@
 	switch (pdev->device) {
 	case PCI_DEVICE_ID_VIA_CX700:
 	case PCI_DEVICE_ID_VIA_VX800:
+	case PCI_DEVICE_ID_VIA_VX855:
 	case PCI_DEVICE_ID_VIA_8251:
 	case PCI_DEVICE_ID_VIA_8237:
 	case PCI_DEVICE_ID_VIA_8237A:
@@ -469,6 +471,8 @@
 	  .driver_data = SMBBA3 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800),
 	  .driver_data = SMBBA3 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855),
+	  .driver_data = SMBBA3 },
 	{ 0, }
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-voodoo3.c linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-voodoo3.c
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/i2c-voodoo3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/i2c-voodoo3.c	2009-09-09 18:13:59.000000000 -0400
@@ -163,7 +163,6 @@
 
 static struct i2c_adapter voodoo3_i2c_adapter = {
 	.owner		= THIS_MODULE,
-	.class		= I2C_CLASS_TV_ANALOG, 
 	.name		= "I2C Voodoo3/Banshee adapter",
 	.algo_data	= &voo_i2c_bit_data,
 };
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/Kconfig linux-libre-2.6.31-gnu/drivers/i2c/busses/Kconfig
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -211,7 +211,7 @@
 	  will be called i2c-via.
 
 config I2C_VIAPRO
-	tristate "VIA VT82C596/82C686/82xx and CX700/VX800/VX820"
+	tristate "VIA VT82C596/82C686/82xx and CX700/VX8xx"
 	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the VIA
@@ -225,8 +225,8 @@
 	    VT8237R/A/S
 	    VT8251
 	    CX700
-	    VX800
-	    VX820
+	    VX800/VX820
+	    VX855/VX875
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-viapro.
@@ -298,7 +298,7 @@
 config I2C_BLACKFIN_TWI_CLK_KHZ
 	int "Blackfin TWI I2C clock (kHz)"
 	depends on I2C_BLACKFIN_TWI
-	range 10 400
+	range 21 400
 	default 50
 	help
 	  The unit of the TWI clock is kHz.
@@ -326,6 +326,16 @@
 	  devices such as DaVinci NIC.
 	  For details please see http://www.ti.com/davinci
 
+config I2C_DESIGNWARE
+	tristate "Synopsys DesignWare"
+	depends on HAVE_CLK
+	help
+	  If you say yes to this option, support will be included for the
+	  Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-designware.
+
 config I2C_GPIO
 	tristate "GPIO-based bitbanging I2C"
 	depends on GENERIC_GPIO
@@ -513,6 +523,19 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called i2c-simtec.
 
+config I2C_STU300
+	tristate "ST Microelectronics DDC I2C interface"
+	depends on MACH_U300
+	default y if MACH_U300
+	help
+	  If you say yes to this option, support will be included for the
+	  I2C interface from ST Microelectronics simply called "DDC I2C"
+	  supporting both I2C and DDC, used in e.g. the U300 series
+	  mobile platforms.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called i2c-stu300.
+
 config I2C_VERSATILE
 	tristate "ARM Versatile/Realview I2C bus support"
 	depends on ARCH_VERSATILE || ARCH_REALVIEW
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/busses/Makefile linux-libre-2.6.31-gnu/drivers/i2c/busses/Makefile
--- linux-libre-2.6.30-gnu/drivers/i2c/busses/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/busses/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
+obj-$(CONFIG_I2C_DESIGNWARE)	+= i2c-designware.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
@@ -48,6 +49,7 @@
 obj-$(CONFIG_I2C_SH7760)	+= i2c-sh7760.o
 obj-$(CONFIG_I2C_SH_MOBILE)	+= i2c-sh_mobile.o
 obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
+obj-$(CONFIG_I2C_STU300)	+= i2c-stu300.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 
 # External I2C/SMBus adapter drivers
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/chips/Kconfig linux-libre-2.6.31-gnu/drivers/i2c/chips/Kconfig
--- linux-libre-2.6.30-gnu/drivers/i2c/chips/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/chips/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -64,21 +64,6 @@
 	  This driver is deprecated and will be dropped soon. Use
 	  drivers/gpio/pca953x.c instead.
 
-config SENSORS_MAX6875
-	tristate "Maxim MAX6875 Power supply supervisor"
-	depends on EXPERIMENTAL
-	help
-	  If you say yes here you get support for the Maxim MAX6875
-	  EEPROM-programmable, quad power-supply sequencer/supervisor.
-
-	  This provides an interface to program the EEPROM and reset the chip.
-
-	  This driver also supports the Maxim MAX6874 hex power-supply
-	  sequencer/supervisor if found at a compatible address.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called max6875.
-
 config SENSORS_TSL2550
 	tristate "Taos TSL2550 ambient light sensor"
 	depends on EXPERIMENTAL
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/chips/Makefile linux-libre-2.6.31-gnu/drivers/i2c/chips/Makefile
--- linux-libre-2.6.30-gnu/drivers/i2c/chips/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/chips/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -11,7 +11,6 @@
 #
 
 obj-$(CONFIG_DS1682)		+= ds1682.o
-obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
 obj-$(CONFIG_SENSORS_PCA9539)	+= pca9539.o
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_PCF8575)		+= pcf8575.o
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/chips/max6875.c linux-libre-2.6.31-gnu/drivers/i2c/chips/max6875.c
--- linux-libre-2.6.30-gnu/drivers/i2c/chips/max6875.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/chips/max6875.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-/*
-    max6875.c - driver for MAX6874/MAX6875
-
-    Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
-
-    Based on i2c/chips/eeprom.c
-
-    The MAX6875 has a bank of registers and two banks of EEPROM.
-    Address ranges are defined as follows:
-     * 0x0000 - 0x0046 = configuration registers
-     * 0x8000 - 0x8046 = configuration EEPROM
-     * 0x8100 - 0x82FF = user EEPROM
-
-    This driver makes the user EEPROM available for read.
-
-    The registers & config EEPROM should be accessed via i2c-dev.
-
-    The MAX6875 ignores the lowest address bit, so each chip responds to
-    two addresses - 0x50/0x51 and 0x52/0x53.
-
-    Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
-    address, so this driver is destructive if loaded for the wrong EEPROM chip.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; version 2 of the License.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD_1(max6875);
-
-/* The MAX6875 can only read/write 16 bytes at a time */
-#define SLICE_SIZE			16
-#define SLICE_BITS			4
-
-/* USER EEPROM is at addresses 0x8100 - 0x82FF */
-#define USER_EEPROM_BASE		0x8100
-#define USER_EEPROM_SIZE		0x0200
-#define USER_EEPROM_SLICES		32
-
-/* MAX6875 commands */
-#define MAX6875_CMD_BLK_READ		0x84
-
-/* Each client has this additional data */
-struct max6875_data {
-	struct i2c_client	*fake_client;
-	struct mutex		update_lock;
-
-	u32			valid;
-	u8			data[USER_EEPROM_SIZE];
-	unsigned long		last_updated[USER_EEPROM_SLICES];
-};
-
-static void max6875_update_slice(struct i2c_client *client, int slice)
-{
-	struct max6875_data *data = i2c_get_clientdata(client);
-	int i, j, addr;
-	u8 *buf;
-
-	if (slice >= USER_EEPROM_SLICES)
-		return;
-
-	mutex_lock(&data->update_lock);
-
-	buf = &data->data[slice << SLICE_BITS];
-
-	if (!(data->valid & (1 << slice)) ||
-	    time_after(jiffies, data->last_updated[slice])) {
-
-		dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
-
-		data->valid &= ~(1 << slice);
-
-		addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
-
-		/* select the eeprom address */
-		if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
-			dev_err(&client->dev, "address set failed\n");
-			goto exit_up;
-		}
-
-		if (i2c_check_functionality(client->adapter,
-					    I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
-			if (i2c_smbus_read_i2c_block_data(client,
-							  MAX6875_CMD_BLK_READ,
-							  SLICE_SIZE,
-							  buf) != SLICE_SIZE) {
-				goto exit_up;
-			}
-		} else {
-			for (i = 0; i < SLICE_SIZE; i++) {
-				j = i2c_smbus_read_byte(client);
-				if (j < 0) {
-					goto exit_up;
-				}
-				buf[i] = j;
-			}
-		}
-		data->last_updated[slice] = jiffies;
-		data->valid |= (1 << slice);
-	}
-exit_up:
-	mutex_unlock(&data->update_lock);
-}
-
-static ssize_t max6875_read(struct kobject *kobj,
-			    struct bin_attribute *bin_attr,
-			    char *buf, loff_t off, size_t count)
-{
-	struct i2c_client *client = kobj_to_i2c_client(kobj);
-	struct max6875_data *data = i2c_get_clientdata(client);
-	int slice, max_slice;
-
-	if (off > USER_EEPROM_SIZE)
-		return 0;
-
-	if (off + count > USER_EEPROM_SIZE)
-		count = USER_EEPROM_SIZE - off;
-
-	/* refresh slices which contain requested bytes */
-	max_slice = (off + count - 1) >> SLICE_BITS;
-	for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
-		max6875_update_slice(client, slice);
-
-	memcpy(buf, &data->data[off], count);
-
-	return count;
-}
-
-static struct bin_attribute user_eeprom_attr = {
-	.attr = {
-		.name = "eeprom",
-		.mode = S_IRUGO,
-	},
-	.size = USER_EEPROM_SIZE,
-	.read = max6875_read,
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int max6875_detect(struct i2c_client *client, int kind,
-			  struct i2c_board_info *info)
-{
-	struct i2c_adapter *adapter = client->adapter;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
-				     | I2C_FUNC_SMBUS_READ_BYTE))
-		return -ENODEV;
-
-	/* Only check even addresses */
-	if (client->addr & 1)
-		return -ENODEV;
-
-	strlcpy(info->type, "max6875", I2C_NAME_SIZE);
-
-	return 0;
-}
-
-static int max6875_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct max6875_data *data;
-	int err;
-
-	if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
-		return -ENOMEM;
-
-	/* A fake client is created on the odd address */
-	data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1);
-	if (!data->fake_client) {
-		err = -ENOMEM;
-		goto exit_kfree;
-	}
-
-	/* Init real i2c_client */
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->update_lock);
-
-	err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr);
-	if (err)
-		goto exit_remove_fake;
-
-	return 0;
-
-exit_remove_fake:
-	i2c_unregister_device(data->fake_client);
-exit_kfree:
-	kfree(data);
-	return err;
-}
-
-static int max6875_remove(struct i2c_client *client)
-{
-	struct max6875_data *data = i2c_get_clientdata(client);
-
-	i2c_unregister_device(data->fake_client);
-
-	sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
-	kfree(data);
-
-	return 0;
-}
-
-static const struct i2c_device_id max6875_id[] = {
-	{ "max6875", 0 },
-	{ }
-};
-
-static struct i2c_driver max6875_driver = {
-	.driver = {
-		.name	= "max6875",
-	},
-	.probe		= max6875_probe,
-	.remove		= max6875_remove,
-	.id_table	= max6875_id,
-
-	.detect		= max6875_detect,
-	.address_data	= &addr_data,
-};
-
-static int __init max6875_init(void)
-{
-	return i2c_add_driver(&max6875_driver);
-}
-
-static void __exit max6875_exit(void)
-{
-	i2c_del_driver(&max6875_driver);
-}
-
-
-MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
-MODULE_DESCRIPTION("MAX6875 driver");
-MODULE_LICENSE("GPL");
-
-module_init(max6875_init);
-module_exit(max6875_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/chips/tsl2550.c linux-libre-2.6.31-gnu/drivers/i2c/chips/tsl2550.c
--- linux-libre-2.6.30-gnu/drivers/i2c/chips/tsl2550.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/chips/tsl2550.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,7 @@
 #include <linux/delay.h>
 
 #define TSL2550_DRV_NAME	"tsl2550"
-#define DRIVER_VERSION		"1.1.1"
+#define DRIVER_VERSION		"1.1.2"
 
 /*
  * Defines
@@ -189,13 +189,16 @@
 	u8 r = 128;
 
 	/* Avoid division by 0 and count 1 cannot be greater than count 0 */
-	if (c0 && (c1 <= c0))
-		r = c1 * 128 / c0;
-	else
-		return -1;
+	if (c1 <= c0)
+		if (c0) {
+			r = c1 * 128 / c0;
 
-	/* Calculate LUX */
-	lux = ((c0 - c1) * ratio_lut[r]) / 256;
+			/* Calculate LUX */
+			lux = ((c0 - c1) * ratio_lut[r]) / 256;
+		} else
+			lux = 0;
+	else
+		return -EAGAIN;
 
 	/* LUX range check */
 	return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/i2c-boardinfo.c linux-libre-2.6.31-gnu/drivers/i2c/i2c-boardinfo.c
--- linux-libre-2.6.30-gnu/drivers/i2c/i2c-boardinfo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/i2c-boardinfo.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 
 #include <linux/kernel.h>
 #include <linux/i2c.h>
+#include <linux/rwsem.h>
 
 #include "i2c-core.h"
 
@@ -25,7 +26,7 @@
 /* These symbols are exported ONLY FOR the i2c core.
  * No other users will be supported.
  */
-DEFINE_MUTEX(__i2c_board_lock);
+DECLARE_RWSEM(__i2c_board_lock);
 EXPORT_SYMBOL_GPL(__i2c_board_lock);
 
 LIST_HEAD(__i2c_board_list);
@@ -63,7 +64,7 @@
 {
 	int status;
 
-	mutex_lock(&__i2c_board_lock);
+	down_write(&__i2c_board_lock);
 
 	/* dynamic bus numbers will be assigned after the last static one */
 	if (busnum >= __i2c_first_dynamic_bus_num)
@@ -84,7 +85,7 @@
 		list_add_tail(&devinfo->list, &__i2c_board_list);
 	}
 
-	mutex_unlock(&__i2c_board_lock);
+	up_write(&__i2c_board_lock);
 
 	return status;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/i2c-core.c linux-libre-2.6.31-gnu/drivers/i2c/i2c-core.c
--- linux-libre-2.6.30-gnu/drivers/i2c/i2c-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/i2c-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,21 +29,24 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/idr.h>
-#include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
 #include <linux/hardirq.h>
 #include <linux/irqflags.h>
+#include <linux/rwsem.h>
 #include <asm/uaccess.h>
 
 #include "i2c-core.h"
 
 
+/* core_lock protects i2c_adapter_idr, userspace_devices, and guarantees
+   that device detection, deletion of detected devices, and attach_adapter
+   and detach_adapter calls are serialized */
 static DEFINE_MUTEX(core_lock);
 static DEFINE_IDR(i2c_adapter_idr);
+static LIST_HEAD(userspace_devices);
 
-#define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect)
-
+static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
 static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
 
 /* ------------------------------------------------------------------------- */
@@ -64,12 +67,6 @@
 	struct i2c_client	*client = to_i2c_client(dev);
 	struct i2c_driver	*driver = to_i2c_driver(drv);
 
-	/* make legacy i2c drivers bypass driver model probing entirely;
-	 * such drivers scan each i2c adapter/bus themselves.
-	 */
-	if (!is_newstyle_driver(driver))
-		return 0;
-
 	/* match on an id table if there is one */
 	if (driver->id_table)
 		return i2c_match_id(driver->id_table, client) != NULL;
@@ -84,10 +81,6 @@
 {
 	struct i2c_client	*client = to_i2c_client(dev);
 
-	/* by definition, legacy drivers can't hotplug */
-	if (dev->driver)
-		return 0;
-
 	if (add_uevent_var(env, "MODALIAS=%s%s",
 			   I2C_MODULE_PREFIX, client->name))
 		return -ENOMEM;
@@ -176,12 +169,6 @@
 	return driver->resume(to_i2c_client(dev));
 }
 
-static void i2c_client_release(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	complete(&client->released);
-}
-
 static void i2c_client_dev_release(struct device *dev)
 {
 	kfree(to_i2c_client(dev));
@@ -241,15 +228,17 @@
 
 
 /**
- * i2c_new_device - instantiate an i2c device for use with a new style driver
+ * i2c_new_device - instantiate an i2c device
  * @adap: the adapter managing the device
  * @info: describes one I2C device; bus_num is ignored
  * Context: can sleep
  *
- * Create a device to work with a new style i2c driver, where binding is
- * handled through driver model probe()/remove() methods.  This call is not
- * appropriate for use by mainboad initialization logic, which usually runs
- * during an arch_initcall() long before any i2c_adapter could exist.
+ * Create an i2c device. Binding is handled through driver model
+ * probe()/remove() methods.  A driver may be bound to this device when we
+ * return from this function, or any later moment (e.g. maybe hotplugging will
+ * load the driver module).  This call is not appropriate for use by mainboard
+ * initialization logic, which usually runs during an arch_initcall() long
+ * before any i2c_adapter could exist.
  *
  * This returns the new i2c client, which may be saved for later use with
  * i2c_unregister_device(); or NULL to indicate an error.
@@ -277,17 +266,31 @@
 
 	strlcpy(client->name, info->type, sizeof(client->name));
 
-	/* a new style driver may be bound to this device when we
-	 * return from this function, or any later moment (e.g. maybe
-	 * hotplugging will load the driver module).  and the device
-	 * refcount model is the standard driver model one.
-	 */
-	status = i2c_attach_client(client);
-	if (status < 0) {
-		kfree(client);
-		client = NULL;
-	}
+	/* Check for address business */
+	status = i2c_check_addr(adap, client->addr);
+	if (status)
+		goto out_err;
+
+	client->dev.parent = &client->adapter->dev;
+	client->dev.bus = &i2c_bus_type;
+	client->dev.release = i2c_client_dev_release;
+
+	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
+		     client->addr);
+	status = device_register(&client->dev);
+	if (status)
+		goto out_err;
+
+	dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
+		client->name, dev_name(&client->dev));
+
 	return client;
+
+out_err:
+	dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
+		"(%d)\n", client->name, client->addr, status);
+	kfree(client);
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(i2c_new_device);
 
@@ -299,28 +302,6 @@
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
-	struct i2c_adapter	*adapter = client->adapter;
-	struct i2c_driver	*driver = client->driver;
-
-	if (driver && !is_newstyle_driver(driver)) {
-		dev_err(&client->dev, "can't unregister devices "
-			"with legacy drivers\n");
-		WARN_ON(1);
-		return;
-	}
-
-	if (adapter->client_unregister) {
-		if (adapter->client_unregister(client)) {
-			dev_warn(&client->dev,
-				 "client_unregister [%s] failed\n",
-				 client->name);
-		}
-	}
-
-	mutex_lock(&adapter->clist_lock);
-	list_del(&client->list);
-	mutex_unlock(&adapter->clist_lock);
-
 	device_unregister(&client->dev);
 }
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
@@ -394,8 +375,128 @@
 	return sprintf(buf, "%s\n", adap->name);
 }
 
+/*
+ * Let users instantiate I2C devices through sysfs. This can be used when
+ * platform initialization code doesn't contain the proper data for
+ * whatever reason. Also useful for drivers that do device detection and
+ * detection fails, either because the device uses an unexpected address,
+ * or this is a compatible device with different ID register values.
+ *
+ * Parameter checking may look overzealous, but we really don't want
+ * the user to provide incorrect parameters.
+ */
+static ssize_t
+i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct i2c_adapter *adap = to_i2c_adapter(dev);
+	struct i2c_board_info info;
+	struct i2c_client *client;
+	char *blank, end;
+	int res;
+
+	dev_warn(dev, "The new_device interface is still experimental "
+		 "and may change in a near future\n");
+	memset(&info, 0, sizeof(struct i2c_board_info));
+
+	blank = strchr(buf, ' ');
+	if (!blank) {
+		dev_err(dev, "%s: Missing parameters\n", "new_device");
+		return -EINVAL;
+	}
+	if (blank - buf > I2C_NAME_SIZE - 1) {
+		dev_err(dev, "%s: Invalid device name\n", "new_device");
+		return -EINVAL;
+	}
+	memcpy(info.type, buf, blank - buf);
+
+	/* Parse remaining parameters, reject extra parameters */
+	res = sscanf(++blank, "%hi%c", &info.addr, &end);
+	if (res < 1) {
+		dev_err(dev, "%s: Can't parse I2C address\n", "new_device");
+		return -EINVAL;
+	}
+	if (res > 1  && end != '\n') {
+		dev_err(dev, "%s: Extra parameters\n", "new_device");
+		return -EINVAL;
+	}
+
+	if (info.addr < 0x03 || info.addr > 0x77) {
+		dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device",
+			info.addr);
+		return -EINVAL;
+	}
+
+	client = i2c_new_device(adap, &info);
+	if (!client)
+		return -EEXIST;
+
+	/* Keep track of the added device */
+	mutex_lock(&core_lock);
+	list_add_tail(&client->detected, &userspace_devices);
+	mutex_unlock(&core_lock);
+	dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",
+		 info.type, info.addr);
+
+	return count;
+}
+
+/*
+ * And of course let the users delete the devices they instantiated, if
+ * they got it wrong. This interface can only be used to delete devices
+ * instantiated by i2c_sysfs_new_device above. This guarantees that we
+ * don't delete devices to which some kernel code still has references.
+ *
+ * Parameter checking may look overzealous, but we really don't want
+ * the user to delete the wrong device.
+ */
+static ssize_t
+i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_adapter *adap = to_i2c_adapter(dev);
+	struct i2c_client *client, *next;
+	unsigned short addr;
+	char end;
+	int res;
+
+	/* Parse parameters, reject extra parameters */
+	res = sscanf(buf, "%hi%c", &addr, &end);
+	if (res < 1) {
+		dev_err(dev, "%s: Can't parse I2C address\n", "delete_device");
+		return -EINVAL;
+	}
+	if (res > 1  && end != '\n') {
+		dev_err(dev, "%s: Extra parameters\n", "delete_device");
+		return -EINVAL;
+	}
+
+	/* Make sure the device was added through sysfs */
+	res = -ENOENT;
+	mutex_lock(&core_lock);
+	list_for_each_entry_safe(client, next, &userspace_devices, detected) {
+		if (client->addr == addr && client->adapter == adap) {
+			dev_info(dev, "%s: Deleting device %s at 0x%02hx\n",
+				 "delete_device", client->name, client->addr);
+
+			list_del(&client->detected);
+			i2c_unregister_device(client);
+			res = count;
+			break;
+		}
+	}
+	mutex_unlock(&core_lock);
+
+	if (res < 0)
+		dev_err(dev, "%s: Can't find device in list\n",
+			"delete_device");
+	return res;
+}
+
 static struct device_attribute i2c_adapter_attrs[] = {
 	__ATTR(name, S_IRUGO, show_adapter_name, NULL),
+	__ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device),
+	__ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device),
 	{ },
 };
 
@@ -409,7 +510,7 @@
 {
 	struct i2c_devinfo	*devinfo;
 
-	mutex_lock(&__i2c_board_lock);
+	down_read(&__i2c_board_lock);
 	list_for_each_entry(devinfo, &__i2c_board_list, list) {
 		if (devinfo->busnum == adapter->nr
 				&& !i2c_new_device(adapter,
@@ -418,7 +519,7 @@
 				"Can't create device at 0x%02x\n",
 				devinfo->board_info.addr);
 	}
-	mutex_unlock(&__i2c_board_lock);
+	up_read(&__i2c_board_lock);
 }
 
 static int i2c_do_add_adapter(struct device_driver *d, void *data)
@@ -442,24 +543,12 @@
 	int res = 0, dummy;
 
 	/* Can't register until after driver model init */
-	if (unlikely(WARN_ON(!i2c_bus_type.p)))
-		return -EAGAIN;
+	if (unlikely(WARN_ON(!i2c_bus_type.p))) {
+		res = -EAGAIN;
+		goto out_list;
+	}
 
 	mutex_init(&adap->bus_lock);
-	mutex_init(&adap->clist_lock);
-	INIT_LIST_HEAD(&adap->clients);
-
-	mutex_lock(&core_lock);
-
-	/* Add the adapter to the driver core.
-	 * If the parent pointer is not set up,
-	 * we add this adapter to the host bus.
-	 */
-	if (adap->dev.parent == NULL) {
-		adap->dev.parent = &platform_bus;
-		pr_debug("I2C adapter driver [%s] forgot to specify "
-			 "physical device\n", adap->name);
-	}
 
 	/* Set default timeout to 1 second if not already set */
 	if (adap->timeout == 0)
@@ -474,21 +563,23 @@
 
 	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
-	/* create pre-declared device nodes for new-style drivers */
+	/* create pre-declared device nodes */
 	if (adap->nr < __i2c_first_dynamic_bus_num)
 		i2c_scan_static_board_info(adap);
 
 	/* Notify drivers */
+	mutex_lock(&core_lock);
 	dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
 				 i2c_do_add_adapter);
-
-out_unlock:
 	mutex_unlock(&core_lock);
-	return res;
+
+	return 0;
 
 out_list:
+	mutex_lock(&core_lock);
 	idr_remove(&i2c_adapter_idr, adap->nr);
-	goto out_unlock;
+	mutex_unlock(&core_lock);
+	return res;
 }
 
 /**
@@ -607,6 +698,14 @@
 	return res;
 }
 
+static int __unregister_client(struct device *dev, void *dummy)
+{
+	struct i2c_client *client = i2c_verify_client(dev);
+	if (client)
+		i2c_unregister_device(client);
+	return 0;
+}
+
 /**
  * i2c_del_adapter - unregister I2C adapter
  * @adap: the adapter being unregistered
@@ -617,46 +716,30 @@
  */
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
-	struct i2c_client *client, *_n;
 	int res = 0;
-
-	mutex_lock(&core_lock);
+	struct i2c_adapter *found;
 
 	/* First make sure that this adapter was ever added */
-	if (idr_find(&i2c_adapter_idr, adap->nr) != adap) {
+	mutex_lock(&core_lock);
+	found = idr_find(&i2c_adapter_idr, adap->nr);
+	mutex_unlock(&core_lock);
+	if (found != adap) {
 		pr_debug("i2c-core: attempting to delete unregistered "
 			 "adapter [%s]\n", adap->name);
-		res = -EINVAL;
-		goto out_unlock;
+		return -EINVAL;
 	}
 
 	/* Tell drivers about this removal */
+	mutex_lock(&core_lock);
 	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
 			       i2c_do_del_adapter);
+	mutex_unlock(&core_lock);
 	if (res)
-		goto out_unlock;
-
-	/* detach any active clients. This must be done first, because
-	 * it can fail; in which case we give up. */
-	list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) {
-		struct i2c_driver	*driver;
-
-		driver = client->driver;
-
-		/* new style, follow standard driver model */
-		if (!driver || is_newstyle_driver(driver)) {
-			i2c_unregister_device(client);
-			continue;
-		}
+		return res;
 
-		/* legacy drivers create and remove clients themselves */
-		if ((res = driver->detach_client(client))) {
-			dev_err(&adap->dev, "detach_client failed for client "
-				"[%s] at address 0x%02x\n", client->name,
-				client->addr);
-			goto out_unlock;
-		}
-	}
+	/* Detach any active clients. This can't fail, thus we do not
+	   checking the returned value. */
+	res = device_for_each_child(&adap->dev, NULL, __unregister_client);
 
 	/* clean up the sysfs representation */
 	init_completion(&adap->dev_released);
@@ -666,7 +749,9 @@
 	wait_for_completion(&adap->dev_released);
 
 	/* free bus id */
+	mutex_lock(&core_lock);
 	idr_remove(&i2c_adapter_idr, adap->nr);
+	mutex_unlock(&core_lock);
 
 	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
 
@@ -674,9 +759,7 @@
 	   added again */
 	memset(&adap->dev, 0, sizeof(adap->dev));
 
- out_unlock:
-	mutex_unlock(&core_lock);
-	return res;
+	return 0;
 }
 EXPORT_SYMBOL(i2c_del_adapter);
 
@@ -699,11 +782,7 @@
 
 /*
  * An i2c_driver is used with one or more i2c_client (device) nodes to access
- * i2c slave chips, on a bus instance associated with some i2c_adapter.  There
- * are two models for binding the driver to its device:  "new style" drivers
- * follow the standard Linux driver model and just respond to probe() calls
- * issued if the driver core sees they match(); "legacy" drivers create device
- * nodes themselves.
+ * i2c slave chips, on a bus instance associated with some i2c_adapter.
  */
 
 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
@@ -714,37 +793,26 @@
 	if (unlikely(WARN_ON(!i2c_bus_type.p)))
 		return -EAGAIN;
 
-	/* new style driver methods can't mix with legacy ones */
-	if (is_newstyle_driver(driver)) {
-		if (driver->detach_adapter || driver->detach_client) {
-			printk(KERN_WARNING
-					"i2c-core: driver [%s] is confused\n",
-					driver->driver.name);
-			return -EINVAL;
-		}
-	}
-
 	/* add the driver to the list of i2c drivers in the driver core */
 	driver->driver.owner = owner;
 	driver->driver.bus = &i2c_bus_type;
 
-	/* for new style drivers, when registration returns the driver core
+	/* When registration returns, the driver core
 	 * will have called probe() for all matching-but-unbound devices.
 	 */
 	res = driver_register(&driver->driver);
 	if (res)
 		return res;
 
-	mutex_lock(&core_lock);
-
 	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
 	INIT_LIST_HEAD(&driver->clients);
 	/* Walk the adapters that are already present */
+	mutex_lock(&core_lock);
 	class_for_each_device(&i2c_adapter_class, NULL, driver,
 			      __attach_adapter);
-
 	mutex_unlock(&core_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(i2c_register_driver);
@@ -764,32 +832,11 @@
 		i2c_unregister_device(client);
 	}
 
-	if (is_newstyle_driver(driver))
-		return 0;
-
-	/* Have a look at each adapter, if clients of this driver are still
-	 * attached. If so, detach them to be able to kill the driver
-	 * afterwards.
-	 */
 	if (driver->detach_adapter) {
 		if (driver->detach_adapter(adapter))
 			dev_err(&adapter->dev,
 				"detach_adapter failed for driver [%s]\n",
 				driver->driver.name);
-	} else {
-		struct i2c_client *client, *_n;
-
-		list_for_each_entry_safe(client, _n, &adapter->clients, list) {
-			if (client->driver != driver)
-				continue;
-			dev_dbg(&adapter->dev,
-				"detaching client [%s] at 0x%02x\n",
-				client->name, client->addr);
-			if (driver->detach_client(client))
-				dev_err(&adapter->dev, "detach_client "
-					"failed for client [%s] at 0x%02x\n",
-					client->name, client->addr);
-		}
 	}
 
 	return 0;
@@ -803,14 +850,12 @@
 void i2c_del_driver(struct i2c_driver *driver)
 {
 	mutex_lock(&core_lock);
-
 	class_for_each_device(&i2c_adapter_class, NULL, driver,
 			      __detach_adapter);
+	mutex_unlock(&core_lock);
 
 	driver_unregister(&driver->driver);
 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
-
-	mutex_unlock(&core_lock);
 }
 EXPORT_SYMBOL(i2c_del_driver);
 
@@ -831,86 +876,6 @@
 	return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
 }
 
-int i2c_attach_client(struct i2c_client *client)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	int res;
-
-	/* Check for address business */
-	res = i2c_check_addr(adapter, client->addr);
-	if (res)
-		return res;
-
-	client->dev.parent = &client->adapter->dev;
-	client->dev.bus = &i2c_bus_type;
-
-	if (client->driver)
-		client->dev.driver = &client->driver->driver;
-
-	if (client->driver && !is_newstyle_driver(client->driver)) {
-		client->dev.release = i2c_client_release;
-		dev_set_uevent_suppress(&client->dev, 1);
-	} else
-		client->dev.release = i2c_client_dev_release;
-
-	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adapter),
-		     client->addr);
-	res = device_register(&client->dev);
-	if (res)
-		goto out_err;
-
-	mutex_lock(&adapter->clist_lock);
-	list_add_tail(&client->list, &adapter->clients);
-	mutex_unlock(&adapter->clist_lock);
-
-	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
-		client->name, dev_name(&client->dev));
-
-	if (adapter->client_register)  {
-		if (adapter->client_register(client)) {
-			dev_dbg(&adapter->dev, "client_register "
-				"failed for client [%s] at 0x%02x\n",
-				client->name, client->addr);
-		}
-	}
-
-	return 0;
-
-out_err:
-	dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
-		"(%d)\n", client->name, client->addr, res);
-	return res;
-}
-EXPORT_SYMBOL(i2c_attach_client);
-
-int i2c_detach_client(struct i2c_client *client)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	int res = 0;
-
-	if (adapter->client_unregister)  {
-		res = adapter->client_unregister(client);
-		if (res) {
-			dev_err(&client->dev,
-				"client_unregister [%s] failed, "
-				"client not detached\n", client->name);
-			goto out;
-		}
-	}
-
-	mutex_lock(&adapter->clist_lock);
-	list_del(&client->list);
-	mutex_unlock(&adapter->clist_lock);
-
-	init_completion(&client->released);
-	device_unregister(&client->dev);
-	wait_for_completion(&client->released);
-
- out:
-	return res;
-}
-EXPORT_SYMBOL(i2c_detach_client);
-
 /**
  * i2c_use_client - increments the reference count of the i2c client structure
  * @client: the client being referenced
@@ -1022,7 +987,8 @@
  */
 int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
-	int ret;
+	unsigned long orig_jiffies;
+	int ret, try;
 
 	/* REVISIT the fault reporting model here is weak:
 	 *
@@ -1060,7 +1026,15 @@
 			mutex_lock_nested(&adap->bus_lock, adap->level);
 		}
 
-		ret = adap->algo->master_xfer(adap,msgs,num);
+		/* Retry automatically on arbitration loss */
+		orig_jiffies = jiffies;
+		for (ret = 0, try = 0; try <= adap->retries; try++) {
+			ret = adap->algo->master_xfer(adap, msgs, num);
+			if (ret != -EAGAIN)
+				break;
+			if (time_after(jiffies, orig_jiffies + adap->timeout))
+				break;
+		}
 		mutex_unlock(&adap->bus_lock);
 
 		return ret;
@@ -1131,144 +1105,7 @@
  * Will not work for 10-bit addresses!
  * ----------------------------------------------------
  */
-static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
-			     int (*found_proc) (struct i2c_adapter *, int, int))
-{
-	int err;
-
-	/* Make sure the address is valid */
-	if (addr < 0x03 || addr > 0x77) {
-		dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
-			 addr);
-		return -EINVAL;
-	}
-
-	/* Skip if already in use */
-	if (i2c_check_addr(adapter, addr))
-		return 0;
-
-	/* Make sure there is something at this address, unless forced */
-	if (kind < 0) {
-		if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
-				   I2C_SMBUS_QUICK, NULL) < 0)
-			return 0;
-
-		/* prevent 24RF08 corruption */
-		if ((addr & ~0x0f) == 0x50)
-			i2c_smbus_xfer(adapter, addr, 0, 0, 0,
-				       I2C_SMBUS_QUICK, NULL);
-	}
-
-	/* Finally call the custom detection function */
-	err = found_proc(adapter, addr, kind);
-	/* -ENODEV can be returned if there is a chip at the given address
-	   but it isn't supported by this chip driver. We catch it here as
-	   this isn't an error. */
-	if (err == -ENODEV)
-		err = 0;
-
-	if (err)
-		dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n",
-			 addr, err);
-	return err;
-}
-
-int i2c_probe(struct i2c_adapter *adapter,
-	      const struct i2c_client_address_data *address_data,
-	      int (*found_proc) (struct i2c_adapter *, int, int))
-{
-	int i, err;
-	int adap_id = i2c_adapter_id(adapter);
-
-	/* Force entries are done first, and are not affected by ignore
-	   entries */
-	if (address_data->forces) {
-		const unsigned short * const *forces = address_data->forces;
-		int kind;
-
-		for (kind = 0; forces[kind]; kind++) {
-			for (i = 0; forces[kind][i] != I2C_CLIENT_END;
-			     i += 2) {
-				if (forces[kind][i] == adap_id
-				 || forces[kind][i] == ANY_I2C_BUS) {
-					dev_dbg(&adapter->dev, "found force "
-						"parameter for adapter %d, "
-						"addr 0x%02x, kind %d\n",
-						adap_id, forces[kind][i + 1],
-						kind);
-					err = i2c_probe_address(adapter,
-						forces[kind][i + 1],
-						kind, found_proc);
-					if (err)
-						return err;
-				}
-			}
-		}
-	}
-
-	/* Stop here if we can't use SMBUS_QUICK */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
-		if (address_data->probe[0] == I2C_CLIENT_END
-		 && address_data->normal_i2c[0] == I2C_CLIENT_END)
-			return 0;
-
-		dev_dbg(&adapter->dev, "SMBus Quick command not supported, "
-			"can't probe for chips\n");
-		return -EOPNOTSUPP;
-	}
-
-	/* Probe entries are done second, and are not affected by ignore
-	   entries either */
-	for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
-		if (address_data->probe[i] == adap_id
-		 || address_data->probe[i] == ANY_I2C_BUS) {
-			dev_dbg(&adapter->dev, "found probe parameter for "
-				"adapter %d, addr 0x%02x\n", adap_id,
-				address_data->probe[i + 1]);
-			err = i2c_probe_address(adapter,
-						address_data->probe[i + 1],
-						-1, found_proc);
-			if (err)
-				return err;
-		}
-	}
-
-	/* Normal entries are done last, unless shadowed by an ignore entry */
-	for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
-		int j, ignore;
 
-		ignore = 0;
-		for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
-		     j += 2) {
-			if ((address_data->ignore[j] == adap_id ||
-			     address_data->ignore[j] == ANY_I2C_BUS)
-			 && address_data->ignore[j + 1]
-			    == address_data->normal_i2c[i]) {
-				dev_dbg(&adapter->dev, "found ignore "
-					"parameter for adapter %d, "
-					"addr 0x%02x\n", adap_id,
-					address_data->ignore[j + 1]);
-				ignore = 1;
-				break;
-			}
-		}
-		if (ignore)
-			continue;
-
-		dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
-			"addr 0x%02x\n", adap_id,
-			address_data->normal_i2c[i]);
-		err = i2c_probe_address(adapter, address_data->normal_i2c[i],
-					-1, found_proc);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(i2c_probe);
-
-/* Separate detection function for new-style drivers */
 static int i2c_detect_address(struct i2c_client *temp_client, int kind,
 			      struct i2c_driver *driver)
 {
@@ -1509,7 +1346,7 @@
 	struct i2c_adapter *adapter;
 
 	mutex_lock(&core_lock);
-	adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
+	adapter = idr_find(&i2c_adapter_idr, id);
 	if (adapter && !try_module_get(adapter->owner))
 		adapter = NULL;
 
@@ -1995,14 +1832,27 @@
 		   char read_write, u8 command, int protocol,
 		   union i2c_smbus_data *data)
 {
+	unsigned long orig_jiffies;
+	int try;
 	s32 res;
 
 	flags &= I2C_M_TEN | I2C_CLIENT_PEC;
 
 	if (adapter->algo->smbus_xfer) {
 		mutex_lock(&adapter->bus_lock);
-		res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
-						command, protocol, data);
+
+		/* Retry automatically on arbitration loss */
+		orig_jiffies = jiffies;
+		for (res = 0, try = 0; try <= adapter->retries; try++) {
+			res = adapter->algo->smbus_xfer(adapter, addr, flags,
+							read_write, command,
+							protocol, data);
+			if (res != -EAGAIN)
+				break;
+			if (time_after(jiffies,
+				       orig_jiffies + adapter->timeout))
+				break;
+		}
 		mutex_unlock(&adapter->bus_lock);
 	} else
 		res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
diff -druN linux-libre-2.6.30-gnu/drivers/i2c/i2c-core.h linux-libre-2.6.31-gnu/drivers/i2c/i2c-core.h
--- linux-libre-2.6.30-gnu/drivers/i2c/i2c-core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/i2c/i2c-core.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/rwsem.h>
+
 struct i2c_devinfo {
 	struct list_head	list;
 	int			busnum;
@@ -25,7 +27,7 @@
 /* board_lock protects board_list and first_dynamic_bus_num.
  * only i2c core components are allowed to use these symbols.
  */
-extern struct mutex	__i2c_board_lock;
+extern struct rw_semaphore	__i2c_board_lock;
 extern struct list_head	__i2c_board_list;
 extern int		__i2c_first_dynamic_bus_num;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/alim15x3.c linux-libre-2.6.31-gnu/drivers/ide/alim15x3.c
--- linux-libre-2.6.30-gnu/drivers/ide/alim15x3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/alim15x3.c	2009-09-09 18:13:59.000000000 -0400
@@ -402,27 +402,23 @@
 	return cbl;
 }
 
-#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
+#ifndef CONFIG_SPARC64
 /**
  *	init_hwif_ali15x3	-	Initialize the ALI IDE x86 stuff
  *	@hwif: interface to configure
  *
  *	Obtain the IRQ tables for an ALi based IDE solution on the PC
  *	class platforms. This part of the code isn't applicable to the
- *	Sparc and PowerPC systems.
+ *	Sparc systems.
  */
 
 static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 ideic, inmir;
 	s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
 				      1, 11, 0, 12, 0, 14, 0, 15 };
 	int irq = -1;
 
-	if (dev->device == PCI_DEVICE_ID_AL_M5229)
-		hwif->irq = hwif->channel ? 15 : 14;
-
 	if (isa_dev) {
 		/*
 		 * read IDE interface control
@@ -455,7 +451,7 @@
 }
 #else
 #define init_hwif_ali15x3 NULL
-#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
+#endif /* CONFIG_SPARC64 */
 
 /**
  *	init_dma_ali15x3	-	set up DMA on ALi15x3
diff -druN linux-libre-2.6.30-gnu/drivers/ide/at91_ide.c linux-libre-2.6.31-gnu/drivers/ide/at91_ide.c
--- linux-libre-2.6.30-gnu/drivers/ide/at91_ide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/at91_ide.c	2009-09-09 18:13:59.000000000 -0400
@@ -185,8 +185,7 @@
 	timing = ide_timing_find_mode(XFER_PIO_0 + pio);
 	BUG_ON(!timing);
 
-	if ((pio > 2 || ata_id_has_iordy(drive->id)) &&
-	    !(ata_id_is_cfa(drive->id) && pio > 4))
+	if (ide_pio_need_iordy(drive, pio))
 		use_iordy = 1;
 
 	apply_timings(chipselect, pio, timing, use_iordy);
@@ -216,6 +215,7 @@
 	.host_flags 	= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE |
 			  IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS,
 	.pio_mask 	= ATA_PIO6,
+	.chipset	= ide_generic,
 };
 
 /*
@@ -246,8 +246,7 @@
 static int __init at91_ide_probe(struct platform_device *pdev)
 {
 	int ret;
-	hw_regs_t hw;
-	hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	struct ide_host *host;
 	struct resource *res;
 	unsigned long tf_base = 0, ctl_base = 0;
@@ -304,10 +303,9 @@
 		ide_std_init_ports(&hw, tf_base, ctl_base + 6);
 
 	hw.irq = board->irq_pin;
-	hw.chipset = ide_generic;
 	hw.dev = &pdev->dev;
 
-	host = ide_host_alloc(&at91_ide_port_info, hws);
+	host = ide_host_alloc(&at91_ide_port_info, hws, 1);
 	if (!host) {
 		perr("failed to allocate ide host\n");
 		return -ENOMEM;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/au1xxx-ide.c linux-libre-2.6.31-gnu/drivers/ide/au1xxx-ide.c
--- linux-libre-2.6.30-gnu/drivers/ide/au1xxx-ide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/au1xxx-ide.c	2009-09-09 18:13:59.000000000 -0400
@@ -449,7 +449,7 @@
 }
 #endif
 
-static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
+static void auide_setup_ports(struct ide_hw *hw, _auide_hwif *ahwif)
 {
 	int i;
 	unsigned long *ata_regs = hw->io_ports_array;
@@ -499,6 +499,7 @@
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	.mwdma_mask		= ATA_MWDMA2,
 #endif
+	.chipset		= ide_au1xxx,
 };
 
 static int au_ide_probe(struct platform_device *dev)
@@ -507,7 +508,7 @@
 	struct resource *res;
 	struct ide_host *host;
 	int ret = 0;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 
 #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
 	char *mode = "MWDMA2";
@@ -548,9 +549,8 @@
 	auide_setup_ports(&hw, ahwif);
 	hw.irq = ahwif->irq;
 	hw.dev = &dev->dev;
-	hw.chipset = ide_au1xxx;
 
-	ret = ide_host_add(&au1xxx_port_info, hws, &host);
+	ret = ide_host_add(&au1xxx_port_info, hws, 1, &host);
 	if (ret)
 		goto out;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/buddha.c linux-libre-2.6.31-gnu/drivers/ide/buddha.c
--- linux-libre-2.6.30-gnu/drivers/ide/buddha.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/buddha.c	2009-09-09 18:13:59.000000000 -0400
@@ -99,7 +99,7 @@
      *  Check and acknowledge the interrupt status
      */
 
-static int buddha_ack_intr(ide_hwif_t *hwif)
+static int buddha_test_irq(ide_hwif_t *hwif)
 {
     unsigned char ch;
 
@@ -109,21 +109,16 @@
     return 1;
 }
 
-static int xsurf_ack_intr(ide_hwif_t *hwif)
+static void xsurf_clear_irq(ide_drive_t *drive)
 {
-    unsigned char ch;
-
-    ch = z_readb(hwif->io_ports.irq_addr);
-    /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */
-    z_writeb(0, hwif->io_ports.irq_addr);
-    if (!(ch & 0x80))
-	    return 0;
-    return 1;
+    /*
+     * X-Surf needs 0 written to IRQ register to ensure ISA bit A11 stays at 0
+     */
+    z_writeb(0, drive->hwif->io_ports.irq_addr);
 }
 
-static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
-				      unsigned long ctl, unsigned long irq_port,
-				      ide_ack_intr_t *ack_intr)
+static void __init buddha_setup_ports(struct ide_hw *hw, unsigned long base,
+				      unsigned long ctl, unsigned long irq_port)
 {
 	int i;
 
@@ -138,14 +133,22 @@
 	hw->io_ports.irq_addr = irq_port;
 
 	hw->irq = IRQ_AMIGA_PORTS;
-	hw->ack_intr = ack_intr;
-
-	hw->chipset = ide_generic;
 }
 
+static const struct ide_port_ops buddha_port_ops = {
+	.test_irq		= buddha_test_irq,
+};
+
+static const struct ide_port_ops xsurf_port_ops = {
+	.clear_irq		= xsurf_clear_irq,
+	.test_irq		= buddha_test_irq,
+};
+
 static const struct ide_port_info buddha_port_info = {
+	.port_ops		= &buddha_port_ops,
 	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
 	.irq_flags		= IRQF_SHARED,
+	.chipset		= ide_generic,
 };
 
     /*
@@ -161,7 +164,8 @@
 
 	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
 		unsigned long board;
-		hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
+		struct ide_hw hw[MAX_NUM_HWIFS], *hws[MAX_NUM_HWIFS];
+		struct ide_port_info d = buddha_port_info;
 
 		if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
 			buddha_num_hwifs = BUDDHA_NUM_HWIFS;
@@ -172,6 +176,7 @@
 		} else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) {
 			buddha_num_hwifs = XSURF_NUM_HWIFS;
 			type=BOARD_XSURF;
+			d.port_ops = &xsurf_port_ops;
 		} else 
 			continue;
 		
@@ -204,28 +209,24 @@
 
 		for (i = 0; i < buddha_num_hwifs; i++) {
 			unsigned long base, ctl, irq_port;
-			ide_ack_intr_t *ack_intr;
 
 			if (type != BOARD_XSURF) {
 				base = buddha_board + buddha_bases[i];
 				ctl = base + BUDDHA_CONTROL;
 				irq_port = buddha_board + buddha_irqports[i];
-				ack_intr = buddha_ack_intr;
 			} else {
 				base = buddha_board + xsurf_bases[i];
 				/* X-Surf has no CS1* (Control/AltStat) */
 				ctl = 0;
 				irq_port = buddha_board + xsurf_irqports[i];
-				ack_intr = xsurf_ack_intr;
 			}
 
-			buddha_setup_ports(&hw[i], base, ctl, irq_port,
-					   ack_intr);
+			buddha_setup_ports(&hw[i], base, ctl, irq_port);
 
 			hws[i] = &hw[i];
 		}
 
-		ide_host_add(&buddha_port_info, hws, NULL);
+		ide_host_add(&d, hws, i, NULL);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/cmd640.c linux-libre-2.6.31-gnu/drivers/ide/cmd640.c
--- linux-libre-2.6.30-gnu/drivers/ide/cmd640.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/cmd640.c	2009-09-09 18:13:59.000000000 -0400
@@ -153,6 +153,7 @@
 #define ARTTIM23	0x57
 #define   ARTTIM23_DIS_RA2	0x04
 #define   ARTTIM23_DIS_RA3	0x08
+#define   ARTTIM23_IDE23INTR	0x10
 #define DRWTIM23	0x58
 #define BRST		0x59
 
@@ -629,12 +630,24 @@
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 }
 
+static int cmd640_test_irq(ide_hwif_t *hwif)
+{
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
+	u8  irq_stat, irq_mask	= hwif->channel ? ARTTIM23_IDE23INTR :
+						  CFR_IDE01INTR;
+
+	pci_read_config_byte(dev, irq_reg, &irq_stat);
+
+	return (irq_stat & irq_mask) ? 1 : 0;
+}
 
 static const struct ide_port_ops cmd640_port_ops = {
 	.init_dev		= cmd640_init_dev,
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 	.set_pio_mode		= cmd640_set_pio_mode,
 #endif
+	.test_irq		= cmd640_test_irq,
 };
 
 static int pci_conf1(void)
@@ -708,7 +721,7 @@
 	int second_port_cmd640 = 0, rc;
 	const char *bus_type, *port2;
 	u8 b, cfr;
-	hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
+	struct ide_hw hw[2], *hws[2];
 
 	if (cmd640_vlb && probe_for_cmd640_vlb()) {
 		bus_type = "VLB";
@@ -762,11 +775,9 @@
 
 	ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
 	hw[0].irq = 14;
-	hw[0].chipset = ide_cmd640;
 
 	ide_std_init_ports(&hw[1], 0x170, 0x376);
 	hw[1].irq = 15;
-	hw[1].chipset = ide_cmd640;
 
 	printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
 			 "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
@@ -824,7 +835,8 @@
 	cmd640_dump_regs();
 #endif
 
-	return ide_host_add(&cmd640_port_info, hws, NULL);
+	return ide_host_add(&cmd640_port_info, hws, second_port_cmd640 ? 2 : 1,
+			    NULL);
 }
 
 module_param_named(probe_vlb, cmd640_vlb, bool, 0);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/cmd64x.c linux-libre-2.6.31-gnu/drivers/ide/cmd64x.c
--- linux-libre-2.6.30-gnu/drivers/ide/cmd64x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/cmd64x.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
  * Copyright (C) 1998		David S. Miller (davem@redhat.com)
  *
  * Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2007		MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007,2009	MontaVista Software, Inc. <source@mvista.com>
  */
 
 #include <linux/module.h>
@@ -118,8 +118,9 @@
 	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	struct ide_timing *t	= ide_timing_find_mode(XFER_PIO_0 + pio);
+	unsigned long setup_count;
 	unsigned int cycle_time;
-	u8 setup_count, arttim = 0;
+	u8 arttim = 0;
 
 	static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
 	static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
@@ -140,10 +141,11 @@
 	if (hwif->channel) {
 		ide_drive_t *pair = ide_get_pair_dev(drive);
 
-		drive->drive_data = setup_count;
+		ide_set_drivedata(drive, (void *)setup_count);
 
 		if (pair)
-			setup_count = max_t(u8, setup_count, pair->drive_data);
+			setup_count = max_t(u8, setup_count,
+					(unsigned long)ide_get_drivedata(pair));
 	}
 
 	if (setup_count > 5)		/* shouldn't actually happen... */
@@ -226,11 +228,11 @@
 		(void) pci_write_config_byte(dev, pciU, regU);
 }
 
-static int cmd648_dma_end(ide_drive_t *drive)
+static void cmd648_clear_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= drive->hwif;
-	unsigned long base	= hwif->dma_base - (hwif->channel * 8);
-	int err			= ide_dma_end(drive);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	unsigned long base	= pci_resource_start(dev, 4);
 	u8  irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
 						  MRDMODE_INTR_CH0;
 	u8  mrdmode		= inb(base + 1);
@@ -238,11 +240,9 @@
 	/* clear the interrupt bit */
 	outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
 	     base + 1);
-
-	return err;
 }
 
-static int cmd64x_dma_end(ide_drive_t *drive)
+static void cmd64x_clear_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
@@ -250,62 +250,40 @@
 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
 						  CFR_INTR_CH0;
 	u8  irq_stat		= 0;
-	int err			= ide_dma_end(drive);
 
 	(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
 	/* clear the interrupt bit */
 	(void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
-
-	return err;
 }
 
-static int cmd648_dma_test_irq(ide_drive_t *drive)
+static int cmd648_test_irq(ide_hwif_t *hwif)
 {
-	ide_hwif_t *hwif	= drive->hwif;
-	unsigned long base	= hwif->dma_base - (hwif->channel * 8);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	unsigned long base	= pci_resource_start(dev, 4);
 	u8 irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
 						  MRDMODE_INTR_CH0;
-	u8 dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
 	u8 mrdmode		= inb(base + 1);
 
-#ifdef DEBUG
-	printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
-	       drive->name, dma_stat, mrdmode, irq_mask);
-#endif
-	if (!(mrdmode & irq_mask))
-		return 0;
-
-	/* return 1 if INTR asserted */
-	if (dma_stat & 4)
-		return 1;
+	pr_debug("%s: mrdmode: 0x%02x irq_mask: 0x%02x\n",
+		 hwif->name, mrdmode, irq_mask);
 
-	return 0;
+	return (mrdmode & irq_mask) ? 1 : 0;
 }
 
-static int cmd64x_dma_test_irq(ide_drive_t *drive)
+static int cmd64x_test_irq(ide_hwif_t *hwif)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
 						  CFR_INTR_CH0;
-	u8  dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
 	u8  irq_stat		= 0;
 
 	(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
 
-#ifdef DEBUG
-	printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
-	       drive->name, dma_stat, irq_stat, irq_mask);
-#endif
-	if (!(irq_stat & irq_mask))
-		return 0;
-
-	/* return 1 if INTR asserted */
-	if (dma_stat & 4)
-		return 1;
+	pr_debug("%s: irq_stat: 0x%02x irq_mask: 0x%02x\n",
+		 hwif->name, irq_stat, irq_mask);
 
-	return 0;
+	return (irq_stat & irq_mask) ? 1 : 0;
 }
 
 /*
@@ -370,18 +348,17 @@
 static const struct ide_port_ops cmd64x_port_ops = {
 	.set_pio_mode		= cmd64x_set_pio_mode,
 	.set_dma_mode		= cmd64x_set_dma_mode,
+	.clear_irq		= cmd64x_clear_irq,
+	.test_irq		= cmd64x_test_irq,
 	.cable_detect		= cmd64x_cable_detect,
 };
 
-static const struct ide_dma_ops cmd64x_dma_ops = {
-	.dma_host_set		= ide_dma_host_set,
-	.dma_setup		= ide_dma_setup,
-	.dma_start		= ide_dma_start,
-	.dma_end		= cmd64x_dma_end,
-	.dma_test_irq		= cmd64x_dma_test_irq,
-	.dma_lost_irq		= ide_dma_lost_irq,
-	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
-	.dma_sff_read_status	= ide_dma_sff_read_status,
+static const struct ide_port_ops cmd648_port_ops = {
+	.set_pio_mode		= cmd64x_set_pio_mode,
+	.set_dma_mode		= cmd64x_set_dma_mode,
+	.clear_irq		= cmd648_clear_irq,
+	.test_irq		= cmd648_test_irq,
+	.cable_detect		= cmd64x_cable_detect,
 };
 
 static const struct ide_dma_ops cmd646_rev1_dma_ops = {
@@ -395,24 +372,12 @@
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
-static const struct ide_dma_ops cmd648_dma_ops = {
-	.dma_host_set		= ide_dma_host_set,
-	.dma_setup		= ide_dma_setup,
-	.dma_start		= ide_dma_start,
-	.dma_end		= cmd648_dma_end,
-	.dma_test_irq		= cmd648_dma_test_irq,
-	.dma_lost_irq		= ide_dma_lost_irq,
-	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
-	.dma_sff_read_status	= ide_dma_sff_read_status,
-};
-
 static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
 	{	/* 0: CMD643 */
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_cmd64x,
 		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
 		.port_ops	= &cmd64x_port_ops,
-		.dma_ops	= &cmd64x_dma_ops,
 		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
 				  IDE_HFLAG_ABUSE_PREFETCH,
 		.pio_mask	= ATA_PIO5,
@@ -423,10 +388,8 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_cmd64x,
 		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-		.port_ops	= &cmd64x_port_ops,
-		.dma_ops	= &cmd648_dma_ops,
-		.host_flags	= IDE_HFLAG_SERIALIZE |
-				  IDE_HFLAG_ABUSE_PREFETCH,
+		.port_ops	= &cmd648_port_ops,
+		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH,
 		.pio_mask	= ATA_PIO5,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA2,
@@ -435,8 +398,7 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_cmd64x,
 		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-		.port_ops	= &cmd64x_port_ops,
-		.dma_ops	= &cmd648_dma_ops,
+		.port_ops	= &cmd648_port_ops,
 		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH,
 		.pio_mask	= ATA_PIO5,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -446,8 +408,7 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_cmd64x,
 		.enablebits	= {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-		.port_ops	= &cmd64x_port_ops,
-		.dma_ops	= &cmd648_dma_ops,
+		.port_ops	= &cmd648_port_ops,
 		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH,
 		.pio_mask	= ATA_PIO5,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -484,10 +445,9 @@
 			 */
 			if (dev->revision < 3) {
 				d.enablebits[0].reg = 0;
+				d.port_ops = &cmd64x_port_ops;
 				if (dev->revision == 1)
 					d.dma_ops = &cmd646_rev1_dma_ops;
-				else
-					d.dma_ops = &cmd64x_dma_ops;
 			}
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/ide/cs5520.c linux-libre-2.6.31-gnu/drivers/ide/cs5520.c
--- linux-libre-2.6.30-gnu/drivers/ide/cs5520.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/cs5520.c	2009-09-09 18:13:59.000000000 -0400
@@ -110,7 +110,7 @@
 static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	const struct ide_port_info *d = &cyrix_chipset;
-	hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
+	struct ide_hw hw[2], *hws[] = { NULL, NULL };
 
 	ide_setup_pci_noise(dev, d);
 
@@ -135,8 +135,9 @@
 
 	ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
 	hw[0].irq = 14;
+	hw[1].irq = 15;
 
-	return ide_host_add(d, hws, NULL);
+	return ide_host_add(d, hws, 2, NULL);
 }
 
 static const struct pci_device_id cs5520_pci_tbl[] = {
diff -druN linux-libre-2.6.30-gnu/drivers/ide/cs5536.c linux-libre-2.6.31-gnu/drivers/ide/cs5536.c
--- linux-libre-2.6.30-gnu/drivers/ide/cs5536.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/cs5536.c	2009-09-09 18:13:59.000000000 -0400
@@ -146,14 +146,16 @@
 	struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
 	ide_drive_t *pair = ide_get_pair_dev(drive);
 	int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
+	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
 	u32 cast;
 	u8 cmd_pio = pio;
 
 	if (pair)
 		cmd_pio = min(pio, ide_get_best_pio_mode(pair, 255, 4));
 
-	drive->drive_data &= (IDE_DRV_MASK << 8);
-	drive->drive_data |= drv_timings[pio];
+	timings &= (IDE_DRV_MASK << 8);
+	timings |= drv_timings[pio];
+	ide_set_drivedata(drive, (void *)timings);
 
 	cs5536_program_dtc(drive, drv_timings[pio]);
 
@@ -186,6 +188,7 @@
 
 	struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
 	int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
+	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
 	u32 etc;
 
 	cs5536_read(pdev, ETC, &etc);
@@ -195,8 +198,9 @@
 		etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
 	} else { /* MWDMA */
 		etc &= ~(IDE_ETC_UDMA_MASK << dshift);
-		drive->drive_data &= IDE_DRV_MASK;
-		drive->drive_data |= mwdma_timings[mode - XFER_MW_DMA_0] << 8;
+		timings &= IDE_DRV_MASK;
+		timings |= mwdma_timings[mode - XFER_MW_DMA_0] << 8;
+		ide_set_drivedata(drive, (void *)timings);
 	}
 
 	cs5536_write(pdev, ETC, etc);
@@ -204,9 +208,11 @@
 
 static void cs5536_dma_start(ide_drive_t *drive)
 {
+	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
+
 	if (drive->current_speed < XFER_UDMA_0 &&
-	    (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK))
-		cs5536_program_dtc(drive, drive->drive_data >> 8);
+	    (timings >> 8) != (timings & IDE_DRV_MASK))
+		cs5536_program_dtc(drive, timings >> 8);
 
 	ide_dma_start(drive);
 }
@@ -214,10 +220,11 @@
 static int cs5536_dma_end(ide_drive_t *drive)
 {
 	int ret = ide_dma_end(drive);
+	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
 
 	if (drive->current_speed < XFER_UDMA_0 &&
-	    (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK))
-		cs5536_program_dtc(drive, drive->drive_data & IDE_DRV_MASK);
+	    (timings >> 8) != (timings & IDE_DRV_MASK))
+		cs5536_program_dtc(drive, timings & IDE_DRV_MASK);
 
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/ide/delkin_cb.c linux-libre-2.6.31-gnu/drivers/ide/delkin_cb.c
--- linux-libre-2.6.30-gnu/drivers/ide/delkin_cb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/delkin_cb.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,6 +68,7 @@
 				  IDE_HFLAG_NO_DMA,
 	.irq_flags		= IRQF_SHARED,
 	.init_chipset		= delkin_cb_init_chipset,
+	.chipset		= ide_pci,
 };
 
 static int __devinit
@@ -76,7 +77,7 @@
 	struct ide_host *host;
 	unsigned long base;
 	int rc;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 
 	rc = pci_enable_device(dev);
 	if (rc) {
@@ -97,9 +98,8 @@
 	ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
 	hw.irq = dev->irq;
 	hw.dev = &dev->dev;
-	hw.chipset = ide_pci;		/* this enables IRQ sharing */
 
-	rc = ide_host_add(&delkin_cb_port_info, hws, &host);
+	rc = ide_host_add(&delkin_cb_port_info, hws, 1, &host);
 	if (rc)
 		goto out_disable;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/falconide.c linux-libre-2.6.31-gnu/drivers/ide/falconide.c
--- linux-libre-2.6.30-gnu/drivers/ide/falconide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/falconide.c	2009-09-09 18:13:59.000000000 -0400
@@ -111,9 +111,10 @@
 	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE |
 				  IDE_HFLAG_NO_DMA,
 	.irq_flags		= IRQF_SHARED,
+	.chipset		= ide_generic,
 };
 
-static void __init falconide_setup_ports(hw_regs_t *hw)
+static void __init falconide_setup_ports(struct ide_hw *hw)
 {
 	int i;
 
@@ -127,9 +128,6 @@
 	hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL;
 
 	hw->irq = IRQ_MFP_IDE;
-	hw->ack_intr = NULL;
-
-	hw->chipset = ide_generic;
 }
 
     /*
@@ -139,7 +137,7 @@
 static int __init falconide_init(void)
 {
 	struct ide_host *host;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	int rc;
 
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
@@ -154,7 +152,7 @@
 
 	falconide_setup_ports(&hw);
 
-	host = ide_host_alloc(&falconide_port_info, hws);
+	host = ide_host_alloc(&falconide_port_info, hws, 1);
 	if (host == NULL) {
 		rc = -ENOMEM;
 		goto err;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/gayle.c linux-libre-2.6.31-gnu/drivers/ide/gayle.c
--- linux-libre-2.6.30-gnu/drivers/ide/gayle.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/gayle.c	2009-09-09 18:13:59.000000000 -0400
@@ -66,7 +66,7 @@
      *  Check and acknowledge the interrupt status
      */
 
-static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+static int gayle_test_irq(ide_hwif_t *hwif)
 {
     unsigned char ch;
 
@@ -76,21 +76,16 @@
     return 1;
 }
 
-static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+static void gayle_a1200_clear_irq(ide_drive_t *drive)
 {
-    unsigned char ch;
+    ide_hwif_t *hwif = drive->hwif;
 
-    ch = z_readb(hwif->io_ports.irq_addr);
-    if (!(ch & GAYLE_IRQ_IDE))
-	return 0;
     (void)z_readb(hwif->io_ports.status_addr);
     z_writeb(0x7c, hwif->io_ports.irq_addr);
-    return 1;
 }
 
-static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
-				     unsigned long ctl, unsigned long irq_port,
-				     ide_ack_intr_t *ack_intr)
+static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base,
+				     unsigned long ctl, unsigned long irq_port)
 {
 	int i;
 
@@ -105,15 +100,22 @@
 	hw->io_ports.irq_addr = irq_port;
 
 	hw->irq = IRQ_AMIGA_PORTS;
-	hw->ack_intr = ack_intr;
-
-	hw->chipset = ide_generic;
 }
 
+static const struct ide_port_ops gayle_a4000_port_ops = {
+	.test_irq		= gayle_test_irq,
+};
+
+static const struct ide_port_ops gayle_a1200_port_ops = {
+	.clear_irq		= gayle_a1200_clear_irq,
+	.test_irq		= gayle_test_irq,
+};
+
 static const struct ide_port_info gayle_port_info = {
 	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE |
 				  IDE_HFLAG_NO_DMA,
 	.irq_flags		= IRQF_SHARED,
+	.chipset		= ide_generic,
 };
 
     /*
@@ -124,9 +126,9 @@
 {
     unsigned long phys_base, res_start, res_n;
     unsigned long base, ctrlport, irqport;
-    ide_ack_intr_t *ack_intr;
     int a4000, i, rc;
-    hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
+    struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS];
+    struct ide_port_info d = gayle_port_info;
 
     if (!MACH_IS_AMIGA)
 	return -ENODEV;
@@ -149,11 +151,11 @@
 	if (a4000) {
 	    phys_base = GAYLE_BASE_4000;
 	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
-	    ack_intr = gayle_ack_intr_a4000;
+	    d.port_ops = &gayle_a4000_port_ops;
 	} else {
 	    phys_base = GAYLE_BASE_1200;
 	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
-	    ack_intr = gayle_ack_intr_a1200;
+	    d.port_ops = &gayle_a1200_port_ops;
 	}
 
 	res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
@@ -166,12 +168,12 @@
 	base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
 	ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
 
-	gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
+	gayle_setup_ports(&hw[i], base, ctrlport, irqport);
 
 	hws[i] = &hw[i];
     }
 
-    rc = ide_host_add(&gayle_port_info, hws, NULL);
+    rc = ide_host_add(&d, hws, i, NULL);
     if (rc)
 	release_mem_region(res_start, res_n);
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/hpt366.c linux-libre-2.6.31-gnu/drivers/ide/hpt366.c
--- linux-libre-2.6.30-gnu/drivers/ide/hpt366.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/hpt366.c	2009-09-09 18:13:59.000000000 -0400
@@ -138,14 +138,6 @@
 #undef	HPT_RESET_STATE_ENGINE
 #undef	HPT_DELAY_INTERRUPT
 
-static const char *quirk_drives[] = {
-	"QUANTUM FIREBALLlct08 08",
-	"QUANTUM FIREBALLP KA6.4",
-	"QUANTUM FIREBALLP LM20.4",
-	"QUANTUM FIREBALLP LM20.5",
-	NULL
-};
-
 static const char *bad_ata100_5[] = {
 	"IBM-DTLA-307075",
 	"IBM-DTLA-307060",
@@ -729,27 +721,13 @@
 	hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
 }
 
-static void hpt3xx_quirkproc(ide_drive_t *drive)
-{
-	char *m			= (char *)&drive->id[ATA_ID_PROD];
-	const  char **list	= quirk_drives;
-
-	while (*list)
-		if (strstr(m, *list++)) {
-			drive->quirk_list = 1;
-			return;
-		}
-
-	drive->quirk_list = 0;
-}
-
 static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
 {
 	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
 	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
 
-	if (drive->quirk_list == 0)
+	if ((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0)
 		return;
 
 	if (info->chip_type >= HPT370) {
@@ -1404,7 +1382,6 @@
 static const struct ide_port_ops hpt3xx_port_ops = {
 	.set_pio_mode		= hpt3xx_set_pio_mode,
 	.set_dma_mode		= hpt3xx_set_mode,
-	.quirkproc		= hpt3xx_quirkproc,
 	.maskproc		= hpt3xx_maskproc,
 	.mdma_filter		= hpt3xx_mdma_filter,
 	.udma_filter		= hpt3xx_udma_filter,
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ht6560b.c linux-libre-2.6.31-gnu/drivers/ide/ht6560b.c
--- linux-libre-2.6.30-gnu/drivers/ide/ht6560b.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ht6560b.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,7 +44,12 @@
  *    bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time	      (?)
  */
 #define HT_CONFIG_PORT	  0x3e6
-#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8)
+
+static inline u8 HT_CONFIG(ide_drive_t *drive)
+{
+	return ((unsigned long)ide_get_drivedata(drive) & 0xff00) >> 8;
+}
+
 /*
  * FIFO + PREFETCH (both a/b-model)
  */
@@ -90,7 +95,11 @@
  * Active Time for each drive. Smaller value gives higher speed.
  * In case of failures you should probably fall back to a higher value.
  */
-#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff)
+static inline u8 HT_TIMING(ide_drive_t *drive)
+{
+	return (unsigned long)ide_get_drivedata(drive) & 0x00ff;
+}
+
 #define HT_TIMING_DEFAULT 0xff
 
 /*
@@ -242,23 +251,27 @@
  */
 static void ht_set_prefetch(ide_drive_t *drive, u8 state)
 {
-	unsigned long flags;
+	unsigned long flags, config;
 	int t = HT_PREFETCH_MODE << 8;
 
 	spin_lock_irqsave(&ht6560b_lock, flags);
 
+	config = (unsigned long)ide_get_drivedata(drive);
+
 	/*
 	 *  Prefetch mode and unmask irq seems to conflict
 	 */
 	if (state) {
-		drive->drive_data |= t;   /* enable prefetch mode */
+		config |= t;   /* enable prefetch mode */
 		drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
 		drive->dev_flags &= ~IDE_DFLAG_UNMASK;
 	} else {
-		drive->drive_data &= ~t;  /* disable prefetch mode */
+		config &= ~t;  /* disable prefetch mode */
 		drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
 	}
 
+	ide_set_drivedata(drive, (void *)config);
+
 	spin_unlock_irqrestore(&ht6560b_lock, flags);
 
 #ifdef DEBUG
@@ -268,7 +281,7 @@
 
 static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	unsigned long flags;
+	unsigned long flags, config;
 	u8 timing;
 	
 	switch (pio) {
@@ -281,8 +294,10 @@
 	timing = ht_pio2timings(drive, pio);
 
 	spin_lock_irqsave(&ht6560b_lock, flags);
-	drive->drive_data &= 0xff00;
-	drive->drive_data |= timing;
+	config = (unsigned long)ide_get_drivedata(drive);
+	config &= 0xff00;
+	config |= timing;
+	ide_set_drivedata(drive, (void *)config);
 	spin_unlock_irqrestore(&ht6560b_lock, flags);
 
 #ifdef DEBUG
@@ -299,7 +314,7 @@
 	if (hwif->channel)
 		t |= (HT_SECONDARY_IF << 8);
 
-	drive->drive_data = t;
+	ide_set_drivedata(drive, (void *)t);
 }
 
 static int probe_ht6560b;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/icside.c linux-libre-2.6.31-gnu/drivers/ide/icside.c
--- linux-libre-2.6.30-gnu/drivers/ide/icside.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/icside.c	2009-09-09 18:13:59.000000000 -0400
@@ -65,8 +65,6 @@
 };
 
 struct icside_state {
-	unsigned int channel;
-	unsigned int enabled;
 	void __iomem *irq_port;
 	void __iomem *ioc_base;
 	unsigned int sel;
@@ -116,18 +114,11 @@
 	struct icside_state *state = ec->irq_data;
 	void __iomem *base = state->irq_port;
 
-	state->enabled = 1;
+	writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
+	readb(base + ICS_ARCIN_V6_INTROFFSET_2);
 
-	switch (state->channel) {
-	case 0:
-		writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
-		readb(base + ICS_ARCIN_V6_INTROFFSET_2);
-		break;
-	case 1:
-		writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
-		readb(base + ICS_ARCIN_V6_INTROFFSET_1);
-		break;
-	}
+	writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
+	readb(base + ICS_ARCIN_V6_INTROFFSET_1);
 }
 
 /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
@@ -137,8 +128,6 @@
 {
 	struct icside_state *state = ec->irq_data;
 
-	state->enabled = 0;
-
 	readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
 	readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
 }
@@ -160,44 +149,6 @@
 	.irqpending	= icside_irqpending_arcin_v6,
 };
 
-/*
- * Handle routing of interrupts.  This is called before
- * we write the command to the drive.
- */
-static void icside_maskproc(ide_drive_t *drive, int mask)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct expansion_card *ec = ECARD_DEV(hwif->dev);
-	struct icside_state *state = ecard_get_drvdata(ec);
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	state->channel = hwif->channel;
-
-	if (state->enabled && !mask) {
-		switch (hwif->channel) {
-		case 0:
-			writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-			readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-			break;
-		case 1:
-			writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-			readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-			break;
-		}
-	} else {
-		readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-		readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-	}
-
-	local_irq_restore(flags);
-}
-
-static const struct ide_port_ops icside_v6_no_dma_port_ops = {
-	.maskproc		= icside_maskproc,
-};
-
 #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
 /*
  * SG-DMA support.
@@ -236,7 +187,8 @@
  */
 static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
 {
-	int cycle_time, use_dma_info = 0;
+	unsigned long cycle_time;
+	int use_dma_info = 0;
 
 	switch (xfer_mode) {
 	case XFER_MW_DMA_2:
@@ -267,15 +219,15 @@
 	if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
 		cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
 
-	drive->drive_data = cycle_time;
+	ide_set_drivedata(drive, (void *)cycle_time);
 
 	printk("%s: %s selected (peak %dMB/s)\n", drive->name,
-		ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
+		ide_xfer_verbose(xfer_mode),
+		2000 / (unsigned long)ide_get_drivedata(drive));
 }
 
 static const struct ide_port_ops icside_v6_port_ops = {
 	.set_dma_mode		= icside_set_dma_mode,
-	.maskproc		= icside_maskproc,
 };
 
 static void icside_dma_host_set(ide_drive_t *drive, int on)
@@ -320,11 +272,6 @@
 	BUG_ON(dma_channel_active(ec->dma));
 
 	/*
-	 * Ensure that we have the right interrupt routed.
-	 */
-	icside_maskproc(drive, 0);
-
-	/*
 	 * Route the DMA signals to the correct interface.
 	 */
 	writeb(state->sel | hwif->channel, state->ioc_base);
@@ -332,7 +279,7 @@
 	/*
 	 * Select the correct timing for this drive.
 	 */
-	set_dma_speed(ec->dma, drive->drive_data);
+	set_dma_speed(ec->dma, (unsigned long)ide_get_drivedata(drive));
 
 	/*
 	 * Tell the DMA engine about the SG table and
@@ -381,7 +328,7 @@
 	return -EOPNOTSUPP;
 }
 
-static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
+static void icside_setup_ports(struct ide_hw *hw, void __iomem *base,
 			       struct cardinfo *info, struct expansion_card *ec)
 {
 	unsigned long port = (unsigned long)base + info->dataoffset;
@@ -398,11 +345,11 @@
 
 	hw->irq = ec->irq;
 	hw->dev = &ec->dev;
-	hw->chipset = ide_acorn;
 }
 
 static const struct ide_port_info icside_v5_port_info = {
 	.host_flags		= IDE_HFLAG_NO_DMA,
+	.chipset		= ide_acorn,
 };
 
 static int __devinit
@@ -410,7 +357,7 @@
 {
 	void __iomem *base;
 	struct ide_host *host;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	int ret;
 
 	base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
@@ -431,7 +378,7 @@
 
 	icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
 
-	host = ide_host_alloc(&icside_v5_port_info, hws);
+	host = ide_host_alloc(&icside_v5_port_info, hws, 1);
 	if (host == NULL)
 		return -ENODEV;
 
@@ -452,11 +399,11 @@
 
 static const struct ide_port_info icside_v6_port_info __initdata = {
 	.init_dma		= icside_dma_off_init,
-	.port_ops		= &icside_v6_no_dma_port_ops,
 	.dma_ops		= &icside_v6_dma_ops,
 	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
 	.mwdma_mask		= ATA_MWDMA2,
 	.swdma_mask		= ATA_SWDMA2,
+	.chipset		= ide_acorn,
 };
 
 static int __devinit
@@ -466,7 +413,7 @@
 	struct ide_host *host;
 	unsigned int sel = 0;
 	int ret;
-	hw_regs_t hw[2], *hws[] = { &hw[0], &hw[1], NULL, NULL };
+	struct ide_hw hw[2], *hws[] = { &hw[0], &hw[1] };
 	struct ide_port_info d = icside_v6_port_info;
 
 	ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
@@ -506,7 +453,7 @@
 	icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
 	icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
 
-	host = ide_host_alloc(&d, hws);
+	host = ide_host_alloc(&d, hws, 2);
 	if (host == NULL)
 		return -ENODEV;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-4drives.c linux-libre-2.6.31-gnu/drivers/ide/ide-4drives.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-4drives.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-4drives.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,12 +25,13 @@
 	.port_ops		= &ide_4drives_port_ops,
 	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA |
 				  IDE_HFLAG_4DRIVES,
+	.chipset		= ide_4drives,
 };
 
 static int __init ide_4drives_init(void)
 {
 	unsigned long base = 0x1f0, ctl = 0x3f6;
-	hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw, &hw };
 
 	if (probe_4drives == 0)
 		return -ENODEV;
@@ -52,9 +53,8 @@
 
 	ide_std_init_ports(&hw, base, ctl);
 	hw.irq = 14;
-	hw.chipset = ide_4drives;
 
-	return ide_host_add(&ide_4drives_port_info, hws, NULL);
+	return ide_host_add(&ide_4drives_port_info, hws, 2, NULL);
 }
 
 module_init(ide_4drives_init);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-acpi.c linux-libre-2.6.31-gnu/drivers/ide/ide-acpi.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-acpi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-acpi.c	2009-09-09 18:13:59.000000000 -0400
@@ -92,6 +92,11 @@
 	return 0;
 }
 
+bool ide_port_acpi(ide_hwif_t *hwif)
+{
+	return ide_noacpi == 0 && hwif->acpidata;
+}
+
 /**
  * ide_get_dev_handle - finds acpi_handle and PCI device.function
  * @dev: device to locate
@@ -352,9 +357,6 @@
 	unsigned long	gtf_address;
 	unsigned long	obj_loc;
 
-	if (ide_noacpi)
-		return 0;
-
 	DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn);
 
 	ret = do_drive_get_GTF(drive, &gtf_length, &gtf_address, &obj_loc);
@@ -389,16 +391,6 @@
 	struct acpi_buffer	output;
 	union acpi_object 	*out_obj;
 
-	if (ide_noacpi)
-		return;
-
-	DEBPRINT("ENTER:\n");
-
-	if (!hwif->acpidata) {
-		DEBPRINT("no ACPI data for %s\n", hwif->name);
-		return;
-	}
-
 	/* Setting up output buffer for _GTM */
 	output.length = ACPI_ALLOCATE_BUFFER;
 	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
@@ -479,16 +471,6 @@
 	struct ide_acpi_drive_link	*master = &hwif->acpidata->master;
 	struct ide_acpi_drive_link	*slave = &hwif->acpidata->slave;
 
-	if (ide_noacpi)
-		return;
-
-	DEBPRINT("ENTER:\n");
-
-	if (!hwif->acpidata) {
-		DEBPRINT("no ACPI data for %s\n", hwif->name);
-		return;
-	}
-
 	/* Give the GTM buffer + drive Identify data to the channel via the
 	 * _STM method: */
 	/* setup input parameters buffer for _STM */
@@ -527,16 +509,11 @@
 	ide_drive_t *drive;
 	int i;
 
-	if (ide_noacpi || ide_noacpi_psx)
+	if (ide_noacpi_psx)
 		return;
 
 	DEBPRINT("ENTER:\n");
 
-	if (!hwif->acpidata) {
-		DEBPRINT("no ACPI data for %s\n", hwif->name);
-		return;
-	}
-
 	/* channel first and then drives for power on and verse versa for power off */
 	if (on)
 		acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
@@ -616,7 +593,7 @@
 				 drive->name, err);
 	}
 
-	if (!ide_acpionboot) {
+	if (ide_noacpi || ide_acpionboot == 0) {
 		DEBPRINT("ACPI methods disabled on boot\n");
 		return;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-atapi.c linux-libre-2.6.31-gnu/drivers/ide/ide-atapi.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-atapi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-atapi.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,9 @@
 
 #include <scsi/scsi.h>
 
+#define DRV_NAME "ide-atapi"
+#define PFX DRV_NAME ": "
+
 #ifdef DEBUG
 #define debug_log(fmt, args...) \
 	printk(KERN_INFO "ide: " fmt, ## args)
@@ -74,64 +77,36 @@
 void ide_init_pc(struct ide_atapi_pc *pc)
 {
 	memset(pc, 0, sizeof(*pc));
-	pc->buf = pc->pc_buf;
-	pc->buf_size = IDE_PC_BUFFER_SIZE;
 }
 EXPORT_SYMBOL_GPL(ide_init_pc);
 
 /*
- * Generate a new packet command request in front of the request queue, before
- * the current request, so that it will be processed immediately, on the next
- * pass through the driver.
- */
-static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
-			      struct ide_atapi_pc *pc, struct request *rq)
-{
-	blk_rq_init(NULL, rq);
-	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->cmd_flags |= REQ_PREEMPT;
-	rq->buffer = (char *)pc;
-	rq->rq_disk = disk;
-
-	if (pc->req_xfer) {
-		rq->data = pc->buf;
-		rq->data_len = pc->req_xfer;
-	}
-
-	memcpy(rq->cmd, pc->c, 12);
-	if (drive->media == ide_tape)
-		rq->cmd[13] = REQ_IDETAPE_PC1;
-
-	drive->hwif->rq = NULL;
-
-	elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
-/*
  * Add a special packet command request to the tail of the request queue,
  * and wait for it to be serviced.
  */
 int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
-		      struct ide_atapi_pc *pc)
+		      struct ide_atapi_pc *pc, void *buf, unsigned int bufflen)
 {
 	struct request *rq;
 	int error;
 
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->buffer = (char *)pc;
+	rq->special = (char *)pc;
 
-	if (pc->req_xfer) {
-		rq->data = pc->buf;
-		rq->data_len = pc->req_xfer;
+	if (buf && bufflen) {
+		error = blk_rq_map_kern(drive->queue, rq, buf, bufflen,
+					GFP_NOIO);
+		if (error)
+			goto put_req;
 	}
 
 	memcpy(rq->cmd, pc->c, 12);
 	if (drive->media == ide_tape)
 		rq->cmd[13] = REQ_IDETAPE_PC1;
 	error = blk_execute_rq(drive->queue, disk, rq, 0);
+put_req:
 	blk_put_request(rq);
-
 	return error;
 }
 EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
@@ -143,7 +118,7 @@
 	ide_init_pc(&pc);
 	pc.c[0] = TEST_UNIT_READY;
 
-	return ide_queue_pc_tail(drive, disk, &pc);
+	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
 }
 EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
 
@@ -158,7 +133,7 @@
 	if (drive->media == ide_tape)
 		pc.flags |= PC_FLAG_WAIT_FOR_DSC;
 
-	return ide_queue_pc_tail(drive, disk, &pc);
+	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
 }
 EXPORT_SYMBOL_GPL(ide_do_start_stop);
 
@@ -173,7 +148,7 @@
 	pc.c[0] = ALLOW_MEDIUM_REMOVAL;
 	pc.c[4] = on;
 
-	return ide_queue_pc_tail(drive, disk, &pc);
+	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
 }
 EXPORT_SYMBOL_GPL(ide_set_media_lock);
 
@@ -191,20 +166,109 @@
 }
 EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
 
+void ide_prep_sense(ide_drive_t *drive, struct request *rq)
+{
+	struct request_sense *sense = &drive->sense_data;
+	struct request *sense_rq = &drive->sense_rq;
+	unsigned int cmd_len, sense_len;
+	int err;
+
+	switch (drive->media) {
+	case ide_floppy:
+		cmd_len = 255;
+		sense_len = 18;
+		break;
+	case ide_tape:
+		cmd_len = 20;
+		sense_len = 20;
+		break;
+	default:
+		cmd_len = 18;
+		sense_len = 18;
+	}
+
+	BUG_ON(sense_len > sizeof(*sense));
+
+	if (blk_sense_request(rq) || drive->sense_rq_armed)
+		return;
+
+	memset(sense, 0, sizeof(*sense));
+
+	blk_rq_init(rq->q, sense_rq);
+
+	err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
+			      GFP_NOIO);
+	if (unlikely(err)) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING PFX "%s: failed to map sense "
+					    "buffer\n", drive->name);
+		return;
+	}
+
+	sense_rq->rq_disk = rq->rq_disk;
+	sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
+	sense_rq->cmd[4] = cmd_len;
+	sense_rq->cmd_type = REQ_TYPE_SENSE;
+	sense_rq->cmd_flags |= REQ_PREEMPT;
+
+	if (drive->media == ide_tape)
+		sense_rq->cmd[13] = REQ_IDETAPE_PC1;
+
+	drive->sense_rq_armed = true;
+}
+EXPORT_SYMBOL_GPL(ide_prep_sense);
+
+int ide_queue_sense_rq(ide_drive_t *drive, void *special)
+{
+	/* deferred failure from ide_prep_sense() */
+	if (!drive->sense_rq_armed) {
+		printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
+		       drive->name);
+		return -ENOMEM;
+	}
+
+	drive->sense_rq.special = special;
+	drive->sense_rq_armed = false;
+
+	drive->hwif->rq = NULL;
+
+	elv_add_request(drive->queue, &drive->sense_rq,
+			ELEVATOR_INSERT_FRONT, 0);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
+
 /*
  * Called when an error was detected during the last packet command.
- * We queue a request sense packet command in the head of the request list.
+ * We queue a request sense packet command at the head of the request
+ * queue.
  */
-void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
+void ide_retry_pc(ide_drive_t *drive)
 {
-	struct request *rq = &drive->request_sense_rq;
+	struct request *failed_rq = drive->hwif->rq;
+	struct request *sense_rq = &drive->sense_rq;
 	struct ide_atapi_pc *pc = &drive->request_sense_pc;
 
 	(void)ide_read_error(drive);
-	ide_create_request_sense_cmd(drive, pc);
+
+	/* init pc from sense_rq */
+	ide_init_pc(pc);
+	memcpy(pc->c, sense_rq->cmd, 12);
+
 	if (drive->media == ide_tape)
-		set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
-	ide_queue_pc_head(drive, disk, pc, rq);
+		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
+
+	/*
+	 * Push back the failed request and put request sense on top
+	 * of it.  The failed command will be retried after sense data
+	 * is acquired.
+	 */
+	blk_requeue_request(failed_rq->q, failed_rq);
+	drive->hwif->rq = NULL;
+	if (ide_queue_sense_rq(drive, pc)) {
+		blk_start_request(failed_rq);
+		ide_complete_rq(drive, -EIO, blk_rq_bytes(failed_rq));
+	}
 }
 EXPORT_SYMBOL_GPL(ide_retry_pc);
 
@@ -231,7 +295,7 @@
 		break;
 	default:
 		if (!(rq->cmd_flags & REQ_QUIET))
-			printk(KERN_INFO "cmd 0x%x timed out\n",
+			printk(KERN_INFO PFX "cmd 0x%x timed out\n",
 					 rq->cmd[0]);
 		wait = 0;
 		break;
@@ -246,7 +310,7 @@
 		return 32768;
 	else if (blk_sense_request(rq) || blk_pc_request(rq) ||
 			 rq->cmd_type == REQ_TYPE_ATA_PC)
-		return rq->data_len;
+		return blk_rq_bytes(rq);
 	else
 		return 0;
 }
@@ -265,6 +329,55 @@
 EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
 
 /*
+ * Check the contents of the interrupt reason register and attempt to recover if
+ * there are problems.
+ *
+ * Returns:
+ * - 0 if everything's ok
+ * - 1 if the request has to be terminated.
+ */
+int ide_check_ireason(ide_drive_t *drive, struct request *rq, int len,
+		      int ireason, int rw)
+{
+	ide_hwif_t *hwif = drive->hwif;
+
+	debug_log("ireason: 0x%x, rw: 0x%x\n", ireason, rw);
+
+	if (ireason == (!rw << 1))
+		return 0;
+	else if (ireason == (rw << 1)) {
+		printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
+				drive->name, __func__);
+
+		if (dev_is_idecd(drive))
+			ide_pad_transfer(drive, rw, len);
+	} else if (!rw && ireason == ATAPI_COD) {
+		if (dev_is_idecd(drive)) {
+			/*
+			 * Some drives (ASUS) seem to tell us that status info
+			 * is available.  Just get it and ignore.
+			 */
+			(void)hwif->tp_ops->read_status(hwif);
+			return 0;
+		}
+	} else {
+		if (ireason & ATAPI_COD)
+			printk(KERN_ERR PFX "%s: CoD != 0 in %s\n", drive->name,
+					__func__);
+
+		/* drive wants a command packet, or invalid ireason... */
+		printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
+				drive->name, __func__, ireason);
+	}
+
+	if (dev_is_idecd(drive) && rq->cmd_type == REQ_TYPE_ATA_PC)
+		rq->cmd_flags |= REQ_FAILED;
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(ide_check_ireason);
+
+/*
  * This is the usual interrupt handler which will be called during a packet
  * command.  We will transfer some of the data (as requested by the drive)
  * and will re-point interrupt handler to us.
@@ -276,7 +389,6 @@
 	struct ide_cmd *cmd = &hwif->cmd;
 	struct request *rq = hwif->rq;
 	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
-	xfer_func_t *xferfunc;
 	unsigned int timeout, done;
 	u16 bcount;
 	u8 stat, ireason, dsc = 0;
@@ -299,25 +411,21 @@
 
 		if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) {
 			if (drive->media == ide_floppy)
-				printk(KERN_ERR "%s: DMA %s error\n",
+				printk(KERN_ERR PFX "%s: DMA %s error\n",
 					drive->name, rq_data_dir(pc->rq)
 						     ? "write" : "read");
 			pc->flags |= PC_FLAG_DMA_ERROR;
-		} else {
-			pc->xferred = pc->req_xfer;
-			if (drive->pc_update_buffers)
-				drive->pc_update_buffers(drive, pc);
-		}
+		} else
+			rq->resid_len = 0;
 		debug_log("%s: DMA finished\n", drive->name);
 	}
 
 	/* No more interrupts */
 	if ((stat & ATA_DRQ) == 0) {
 		int uptodate, error;
-		unsigned int done;
 
 		debug_log("Packet command completed, %d bytes transferred\n",
-			  pc->xferred);
+			  blk_rq_bytes(rq));
 
 		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
 
@@ -335,15 +443,15 @@
 				pc->rq->errors++;
 
 			if (rq->cmd[0] == REQUEST_SENSE) {
-				printk(KERN_ERR "%s: I/O error in request sense"
-						" command\n", drive->name);
+				printk(KERN_ERR PFX "%s: I/O error in request "
+						"sense command\n", drive->name);
 				return ide_do_reset(drive);
 			}
 
 			debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
 
 			/* Retry operation */
-			ide_retry_pc(drive, rq->rq_disk);
+			ide_retry_pc(drive);
 
 			/* queued, but not started */
 			return ide_stopped;
@@ -353,6 +461,12 @@
 		if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
 			dsc = 1;
 
+		/*
+		 * ->pc_callback() might change rq->data_len for
+		 * residual count, cache total length.
+		 */
+		done = blk_rq_bytes(rq);
+
 		/* Command finished - Call the callback function */
 		uptodate = drive->pc_callback(drive, dsc);
 
@@ -361,7 +475,6 @@
 
 		if (blk_special_request(rq)) {
 			rq->errors = 0;
-			done = blk_rq_bytes(rq);
 			error = 0;
 		} else {
 
@@ -370,22 +483,17 @@
 					rq->errors = -EIO;
 			}
 
-			if (drive->media == ide_tape)
-				done = ide_rq_bytes(rq); /* FIXME */
-			else
-				done = blk_rq_bytes(rq);
-
 			error = uptodate ? 0 : -EIO;
 		}
 
-		ide_complete_rq(drive, error, done);
+		ide_complete_rq(drive, error, blk_rq_bytes(rq));
 		return ide_stopped;
 	}
 
 	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
 		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
-		printk(KERN_ERR "%s: The device wants to issue more interrupts "
-				"in DMA mode\n", drive->name);
+		printk(KERN_ERR PFX "%s: The device wants to issue more "
+				"interrupts in DMA mode\n", drive->name);
 		ide_dma_off(drive);
 		return ide_do_reset(drive);
 	}
@@ -393,43 +501,22 @@
 	/* Get the number of bytes to transfer on this interrupt. */
 	ide_read_bcount_and_ireason(drive, &bcount, &ireason);
 
-	if (ireason & ATAPI_COD) {
-		printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
-		return ide_do_reset(drive);
-	}
-
-	if (((ireason & ATAPI_IO) == ATAPI_IO) == write) {
-		/* Hopefully, we will never get here */
-		printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
-				"to %s!\n", drive->name,
-				(ireason & ATAPI_IO) ? "Write" : "Read",
-				(ireason & ATAPI_IO) ? "Read" : "Write");
+	if (ide_check_ireason(drive, rq, bcount, ireason, write))
 		return ide_do_reset(drive);
-	}
 
-	xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
-
-	if (drive->media == ide_floppy && pc->buf == NULL) {
-		done = min_t(unsigned int, bcount, cmd->nleft);
-		ide_pio_bytes(drive, cmd, write, done);
-	} else if (drive->media == ide_tape && pc->bh) {
-		done = drive->pc_io_buffers(drive, pc, bcount, write);
-	} else {
-		done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
-		xferfunc(drive, NULL, pc->cur_pos, done);
-	}
+	done = min_t(unsigned int, bcount, cmd->nleft);
+	ide_pio_bytes(drive, cmd, write, done);
 
-	/* Update the current position */
-	pc->xferred += done;
-	pc->cur_pos += done;
+	/* Update transferred byte count */
+	rq->resid_len -= done;
 
 	bcount -= done;
 
 	if (bcount)
 		ide_pad_transfer(drive, write, bcount);
 
-	debug_log("[cmd %x] transferred %d bytes, padded %d bytes\n",
-		  rq->cmd[0], done, bcount);
+	debug_log("[cmd %x] transferred %d bytes, padded %d bytes, resid: %u\n",
+		  rq->cmd[0], done, bcount, rq->resid_len);
 
 	/* And set the interrupt handler again */
 	ide_set_handler(drive, ide_pc_intr, timeout);
@@ -463,13 +550,13 @@
 
 	while (retries-- && ((ireason & ATAPI_COD) == 0 ||
 		(ireason & ATAPI_IO))) {
-		printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
+		printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing "
 				"a packet command, retrying\n", drive->name);
 		udelay(100);
 		ireason = ide_read_ireason(drive);
 		if (retries == 0) {
-			printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
-					"a packet command, ignoring\n",
+			printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing"
+					" a packet command, ignoring\n",
 					drive->name);
 			ireason |= ATAPI_COD;
 			ireason &= ~ATAPI_IO;
@@ -500,7 +587,7 @@
 	u8 ireason;
 
 	if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
-		printk(KERN_ERR "%s: Strange, packet command initiated yet "
+		printk(KERN_ERR PFX "%s: Strange, packet command initiated yet "
 				"DRQ isn't asserted\n", drive->name);
 		return startstop;
 	}
@@ -525,7 +612,7 @@
 
 		/*
 		 * If necessary schedule the packet transfer to occur 'timeout'
-		 * miliseconds later in ide_delayed_transfer_pc() after the
+		 * milliseconds later in ide_delayed_transfer_pc() after the
 		 * device says it's ready for a packet.
 		 */
 		if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
@@ -542,8 +629,8 @@
 			ireason = ide_wait_ireason(drive, ireason);
 
 		if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
-			printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
-					"a packet command\n", drive->name);
+			printk(KERN_ERR PFX "%s: (IO,CoD) != (0,1) while "
+				"issuing a packet command\n", drive->name);
 
 			return ide_do_reset(drive);
 		}
@@ -581,7 +668,7 @@
 	ide_hwif_t *hwif = drive->hwif;
 	ide_expiry_t *expiry = NULL;
 	struct request *rq = hwif->rq;
-	unsigned int timeout;
+	unsigned int timeout, bytes;
 	u16 bcount;
 	u8 valid_tf;
 	u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT);
@@ -597,14 +684,14 @@
 	} else {
 		pc = drive->pc;
 
-		/* We haven't transferred any data yet */
-		pc->xferred = 0;
-		pc->cur_pos = pc->buf;
-
 		valid_tf = IDE_VALID_DEVICE;
-		bcount = ((drive->media == ide_tape) ?
-				pc->req_xfer :
-				min(pc->req_xfer, 63 * 1024));
+		bytes = blk_rq_bytes(rq);
+		bcount = ((drive->media == ide_tape) ? bytes
+						     : min_t(unsigned int,
+							     bytes, 63 * 1024));
+
+		/* We haven't transferred any data yet */
+		rq->resid_len = bcount;
 
 		if (pc->flags & PC_FLAG_DMA_ERROR) {
 			pc->flags &= ~PC_FLAG_DMA_ERROR;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide.c linux-libre-2.6.31-gnu/drivers/ide/ide.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide.c	2009-09-09 18:13:59.000000000 -0400
@@ -211,6 +211,11 @@
 module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0);
 MODULE_PARM_DESC(noflush, "disable flush requests for a device");
 
+static unsigned int ide_nohpa;
+
+module_param_call(nohpa, ide_set_dev_param_mask, NULL, &ide_nohpa, 0);
+MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device");
+
 static unsigned int ide_noprobe;
 
 module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0);
@@ -281,6 +286,11 @@
 				 drive->name);
 		drive->dev_flags |= IDE_DFLAG_NOFLUSH;
 	}
+	if (ide_nohpa & (1 << i)) {
+		printk(KERN_INFO "ide: disabling Host Protected Area for %s\n",
+				 drive->name);
+		drive->dev_flags |= IDE_DFLAG_NOHPA;
+	}
 	if (ide_noprobe & (1 << i)) {
 		printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
 		drive->dev_flags |= IDE_DFLAG_NOPROBE;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-cd.c linux-libre-2.6.31-gnu/drivers/ide/ide-cd.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-cd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-cd.c	2009-09-09 18:13:59.000000000 -0400
@@ -92,16 +92,16 @@
 	drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
 }
 
-static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
-			   struct request_sense *sense)
+static int cdrom_log_sense(ide_drive_t *drive, struct request *rq)
 {
+	struct request_sense *sense = &drive->sense_data;
 	int log = 0;
 
-	ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
-
 	if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
 		return 0;
 
+	ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
+
 	switch (sense->sense_key) {
 	case NO_SENSE:
 	case RECOVERED_ERROR:
@@ -140,12 +140,12 @@
 }
 
 static void cdrom_analyze_sense_data(ide_drive_t *drive,
-			      struct request *failed_command,
-			      struct request_sense *sense)
+				     struct request *failed_command)
 {
+	struct request_sense *sense = &drive->sense_data;
+	struct cdrom_info *info = drive->driver_data;
 	unsigned long sector;
 	unsigned long bio_sectors;
-	struct cdrom_info *info = drive->driver_data;
 
 	ide_debug_log(IDE_DBG_SENSE, "error_code: 0x%x, sense_key: 0x%x",
 				     sense->error_code, sense->sense_key);
@@ -154,7 +154,7 @@
 		ide_debug_log(IDE_DBG_SENSE, "failed cmd: 0x%x",
 					     failed_command->cmd[0]);
 
-	if (!cdrom_log_sense(drive, failed_command, sense))
+	if (!cdrom_log_sense(drive, failed_command))
 		return;
 
 	/*
@@ -182,7 +182,7 @@
 				 (sense->information[2] <<  8) |
 				 (sense->information[3]);
 
-			if (drive->queue->hardsect_size == 2048)
+			if (queue_logical_block_size(drive->queue) == 2048)
 				/* device sector size is 2K */
 				sector <<= 2;
 
@@ -206,63 +206,33 @@
 	ide_cd_log_error(drive->name, failed_command, sense);
 }
 
-static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
-				      struct request *failed_command)
-{
-	struct cdrom_info *info		= drive->driver_data;
-	struct request *rq		= &drive->request_sense_rq;
-
-	ide_debug_log(IDE_DBG_SENSE, "enter");
-
-	if (sense == NULL)
-		sense = &info->sense_data;
-
-	/* stuff the sense request in front of our current request */
-	blk_rq_init(NULL, rq);
-	rq->cmd_type = REQ_TYPE_ATA_PC;
-	rq->rq_disk = info->disk;
-
-	rq->data = sense;
-	rq->cmd[0] = GPCMD_REQUEST_SENSE;
-	rq->cmd[4] = 18;
-	rq->data_len = 18;
-
-	rq->cmd_type = REQ_TYPE_SENSE;
-	rq->cmd_flags |= REQ_PREEMPT;
-
-	/* NOTE! Save the failed command in "rq->buffer" */
-	rq->buffer = (void *) failed_command;
-
-	if (failed_command)
-		ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x",
-					     failed_command->cmd[0]);
-
-	drive->hwif->rq = NULL;
-
-	elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
 static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
 {
 	/*
-	 * For REQ_TYPE_SENSE, "rq->buffer" points to the original
-	 * failed request
+	 * For REQ_TYPE_SENSE, "rq->special" points to the original
+	 * failed request.  Also, the sense data should be read
+	 * directly from rq which might be different from the original
+	 * sense buffer if it got copied during mapping.
 	 */
-	struct request *failed = (struct request *)rq->buffer;
-	struct cdrom_info *info = drive->driver_data;
-	void *sense = &info->sense_data;
+	struct request *failed = (struct request *)rq->special;
+	void *sense = bio_data(rq->bio);
 
 	if (failed) {
 		if (failed->sense) {
-			sense = failed->sense;
+			/*
+			 * Sense is always read into drive->sense_data.
+			 * Copy back if the failed request has its
+			 * sense pointer set.
+			 */
+			memcpy(failed->sense, sense, 18);
 			failed->sense_len = rq->sense_len;
 		}
-		cdrom_analyze_sense_data(drive, failed, sense);
+		cdrom_analyze_sense_data(drive, failed);
 
 		if (ide_end_rq(drive, failed, -EIO, blk_rq_bytes(failed)))
 			BUG();
 	} else
-		cdrom_analyze_sense_data(drive, NULL, sense);
+		cdrom_analyze_sense_data(drive, NULL);
 }
 
 
@@ -428,70 +398,17 @@
 
 	/* if we got a CHECK_CONDITION status, queue a request sense command */
 	if (stat & ATA_ERR)
-		cdrom_queue_request_sense(drive, NULL, NULL);
+		return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
 	return 1;
 
 end_request:
 	if (stat & ATA_ERR) {
-		struct request_queue *q = drive->queue;
-		unsigned long flags;
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blkdev_dequeue_request(rq);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-
 		hwif->rq = NULL;
-
-		cdrom_queue_request_sense(drive, rq->sense, rq);
-		return 1;
+		return ide_queue_sense_rq(drive, rq) ? 2 : 1;
 	} else
 		return 2;
 }
 
-/*
- * Check the contents of the interrupt reason register from the cdrom
- * and attempt to recover if there are problems.  Returns  0 if everything's
- * ok; nonzero if the request has been terminated.
- */
-static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
-				int len, int ireason, int rw)
-{
-	ide_hwif_t *hwif = drive->hwif;
-
-	ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw);
-
-	/*
-	 * ireason == 0: the drive wants to receive data from us
-	 * ireason == 2: the drive is expecting to transfer data to us
-	 */
-	if (ireason == (!rw << 1))
-		return 0;
-	else if (ireason == (rw << 1)) {
-
-		/* whoops... */
-		printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
-				drive->name, __func__);
-
-		ide_pad_transfer(drive, rw, len);
-	} else  if (rw == 0 && ireason == 1) {
-		/*
-		 * Some drives (ASUS) seem to tell us that status info is
-		 * available.  Just get it and ignore.
-		 */
-		(void)hwif->tp_ops->read_status(hwif);
-		return 0;
-	} else {
-		/* drive wants a command packet, or invalid ireason... */
-		printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
-				drive->name, __func__, ireason);
-	}
-
-	if (rq->cmd_type == REQ_TYPE_ATA_PC)
-		rq->cmd_flags |= REQ_FAILED;
-
-	return -1;
-}
-
 static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	struct request *rq = cmd->rq;
@@ -503,14 +420,8 @@
 	 * and some drives don't send them.  Sigh.
 	 */
 	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
-	    cmd->nleft > 0 && cmd->nleft <= 5) {
-		unsigned int ofs = cmd->nbytes - cmd->nleft;
-
-		while (cmd->nleft > 0) {
-			*((u8 *)rq->data + ofs++) = 0;
-			cmd->nleft--;
-		}
-	}
+	    cmd->nleft > 0 && cmd->nleft <= 5)
+		cmd->nleft = 0;
 }
 
 int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
@@ -543,14 +454,18 @@
 		rq->cmd_flags |= cmd_flags;
 		rq->timeout = timeout;
 		if (buffer) {
-			rq->data = buffer;
-			rq->data_len = *bufflen;
+			error = blk_rq_map_kern(drive->queue, rq, buffer,
+						*bufflen, GFP_NOIO);
+			if (error) {
+				blk_put_request(rq);
+				return error;
+			}
 		}
 
 		error = blk_execute_rq(drive->queue, info->disk, rq, 0);
 
 		if (buffer)
-			*bufflen = rq->data_len;
+			*bufflen = rq->resid_len;
 
 		flags = rq->cmd_flags;
 		blk_put_request(rq);
@@ -608,7 +523,7 @@
 	struct request *rq = hwif->rq;
 	ide_expiry_t *expiry = NULL;
 	int dma_error = 0, dma, thislen, uptodate = 0;
-	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0, nsectors;
+	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0;
 	int sense = blk_sense_request(rq);
 	unsigned int timeout;
 	u16 len;
@@ -677,16 +592,25 @@
 			}
 		} else if (!blk_pc_request(rq)) {
 			ide_cd_request_sense_fixup(drive, cmd);
-			/* complain if we still have data left to transfer */
+
 			uptodate = cmd->nleft ? 0 : 1;
-			if (uptodate == 0)
+
+			/*
+			 * suck out the remaining bytes from the drive in an
+			 * attempt to complete the data xfer. (see BZ#13399)
+			 */
+			if (!(stat & ATA_ERR) && !uptodate && thislen) {
+				ide_pio_bytes(drive, cmd, write, thislen);
+				uptodate = cmd->nleft ? 0 : 1;
+			}
+
+			if (!uptodate)
 				rq->cmd_flags |= REQ_FAILED;
 		}
 		goto out_end;
 	}
 
-	/* check which way to transfer data */
-	rc = ide_cd_check_ireason(drive, rq, len, ireason, write);
+	rc = ide_check_ireason(drive, rq, len, ireason, write);
 	if (rc)
 		goto out_end;
 
@@ -738,13 +662,8 @@
 
 out_end:
 	if (blk_pc_request(rq) && rc == 0) {
-		unsigned int dlen = rq->data_len;
-
-		rq->data_len = 0;
-
-		if (blk_end_request(rq, 0, dlen))
-			BUG();
-
+		rq->resid_len = 0;
+		blk_end_request_all(rq, 0);
 		hwif->rq = NULL;
 	} else {
 		if (sense && uptodate)
@@ -758,25 +677,17 @@
 				rq->errors = -EIO;
 		}
 
-		if (uptodate == 0)
+		if (uptodate == 0 && rq->bio)
 			ide_cd_error_cmd(drive, cmd);
 
 		/* make sure it's fully ended */
-		if (blk_pc_request(rq))
-			nsectors = (rq->data_len + 511) >> 9;
-		else
-			nsectors = rq->hard_nr_sectors;
-
-		if (nsectors == 0)
-			nsectors = 1;
-
 		if (blk_fs_request(rq) == 0) {
-			rq->data_len -= (cmd->nbytes - cmd->nleft);
+			rq->resid_len -= cmd->nbytes - cmd->nleft;
 			if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE))
-				rq->data_len += cmd->last_xfer_len;
+				rq->resid_len += cmd->last_xfer_len;
 		}
 
-		ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9);
+		ide_complete_rq(drive, uptodate ? 0 : -EIO, blk_rq_bytes(rq));
 
 		if (sense && rc == 2)
 			ide_error(drive, "request sense failure", stat);
@@ -790,7 +701,7 @@
 	struct request_queue *q = drive->queue;
 	int write = rq_data_dir(rq) == WRITE;
 	unsigned short sectors_per_frame =
-		queue_hardsect_size(q) >> SECTOR_BITS;
+		queue_logical_block_size(q) >> SECTOR_BITS;
 
 	ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, "
 				  "secs_per_frame: %u",
@@ -809,8 +720,8 @@
 	}
 
 	/* fs requests *must* be hardware frame aligned */
-	if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
-	    (rq->sector & (sectors_per_frame - 1)))
+	if ((blk_rq_sectors(rq) & (sectors_per_frame - 1)) ||
+	    (blk_rq_pos(rq) & (sectors_per_frame - 1)))
 		return ide_stopped;
 
 	/* use DMA, if possible */
@@ -838,15 +749,10 @@
 	drive->dma = 0;
 
 	/* sg request */
-	if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
+	if (rq->bio) {
 		struct request_queue *q = drive->queue;
+		char *buf = bio_data(rq->bio);
 		unsigned int alignment;
-		char *buf;
-
-		if (rq->bio)
-			buf = bio_data(rq->bio);
-		else
-			buf = rq->data;
 
 		drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
@@ -858,7 +764,7 @@
 		 */
 		alignment = queue_dma_alignment(q) | q->dma_pad_mask;
 		if ((unsigned long)buf & alignment
-		    || rq->data_len & q->dma_pad_mask
+		    || blk_rq_bytes(rq) & q->dma_pad_mask
 		    || object_is_on_stack(buf))
 			drive->dma = 0;
 	}
@@ -889,12 +795,11 @@
 		/* right now this can only be a reset... */
 		uptodate = 1;
 		goto out_end;
-	} else {
-		blk_dump_rq_flags(rq, DRV_NAME " bad flags");
-		if (rq->errors == 0)
-			rq->errors = -EIO;
-		goto out_end;
-	}
+	} else
+		BUG();
+
+	/* prepare sense request for this command */
+	ide_prep_sense(drive, rq);
 
 	memset(&cmd, 0, sizeof(cmd));
 
@@ -903,15 +808,14 @@
 
 	cmd.rq = rq;
 
-	if (blk_fs_request(rq) || rq->data_len) {
-		ide_init_sg_cmd(&cmd, blk_fs_request(rq) ? (rq->nr_sectors << 9)
-							 : rq->data_len);
+	if (blk_fs_request(rq) || blk_rq_bytes(rq)) {
+		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
 		ide_map_sg(drive, &cmd);
 	}
 
 	return ide_issue_pc(drive, &cmd);
 out_end:
-	nsectors = rq->hard_nr_sectors;
+	nsectors = blk_rq_sectors(rq);
 
 	if (nsectors == 0)
 		nsectors = 1;
@@ -982,9 +886,12 @@
 		return stat;
 
 	/*
-	 * Sanity check the given block size
+	 * Sanity check the given block size, in so far as making
+	 * sure the sectors_per_frame we give to the caller won't
+	 * end up being bogus.
 	 */
 	blocklen = be32_to_cpu(capbuf.blocklen);
+	blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS;
 	switch (blocklen) {
 	case 512:
 	case 1024:
@@ -992,10 +899,9 @@
 	case 4096:
 		break;
 	default:
-		printk(KERN_ERR PFX "%s: weird block size %u\n",
+		printk_once(KERN_ERR PFX "%s: weird block size %u; "
+				"setting default block size to 2048\n",
 				drive->name, blocklen);
-		printk(KERN_ERR PFX "%s: default to 2kb block size\n",
-				drive->name);
 		blocklen = 2048;
 		break;
 	}
@@ -1077,8 +983,8 @@
 	/* save a private copy of the TOC capacity for error handling */
 	drive->probed_capacity = toc->capacity * sectors_per_frame;
 
-	blk_queue_hardsect_size(drive->queue,
-				sectors_per_frame << SECTOR_BITS);
+	blk_queue_logical_block_size(drive->queue,
+				     sectors_per_frame << SECTOR_BITS);
 
 	/* first read just the header, so we know how long the TOC is */
 	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
@@ -1394,9 +1300,9 @@
 /* standard prep_rq_fn that builds 10 byte cmds */
 static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
 {
-	int hard_sect = queue_hardsect_size(q);
-	long block = (long)rq->hard_sector / (hard_sect >> 9);
-	unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
+	int hard_sect = queue_logical_block_size(q);
+	long block = (long)blk_rq_pos(rq) / (hard_sect >> 9);
+	unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9);
 
 	memset(rq->cmd, 0, BLK_MAX_CDB);
 
@@ -1599,7 +1505,7 @@
 
 	nslots = ide_cdrom_probe_capabilities(drive);
 
-	blk_queue_hardsect_size(q, CD_FRAMESIZE);
+	blk_queue_logical_block_size(q, CD_FRAMESIZE);
 
 	if (ide_cdrom_register(drive, nslots)) {
 		printk(KERN_ERR PFX "%s: %s failed to register device with the"
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-cd.h linux-libre-2.6.31-gnu/drivers/ide/ide-cd.h
--- linux-libre-2.6.30-gnu/drivers/ide/ide-cd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-cd.h	2009-09-09 18:13:59.000000000 -0400
@@ -87,10 +87,6 @@
 
 	struct atapi_toc *toc;
 
-	/* The result of the last successful request sense command
-	   on this device. */
-	struct request_sense sense_data;
-
 	u8 max_speed;		/* Max speed of the drive. */
 	u8 current_speed;	/* Current speed of the drive. */
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-cs.c linux-libre-2.6.31-gnu/drivers/ide/ide-cs.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -155,6 +155,7 @@
 	.port_ops		= &idecs_port_ops,
 	.host_flags		= IDE_HFLAG_NO_DMA,
 	.irq_flags		= IRQF_SHARED,
+	.chipset		= ide_pci,
 };
 
 static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
@@ -163,7 +164,7 @@
     struct ide_host *host;
     ide_hwif_t *hwif;
     int i, rc;
-    hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+    struct ide_hw hw, *hws[] = { &hw };
 
     if (!request_region(io, 8, DRV_NAME)) {
 	printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -181,10 +182,9 @@
     memset(&hw, 0, sizeof(hw));
     ide_std_init_ports(&hw, io, ctl);
     hw.irq = irq;
-    hw.chipset = ide_pci;
     hw.dev = &handle->dev;
 
-    rc = ide_host_add(&idecs_port_info, hws, &host);
+    rc = ide_host_add(&idecs_port_info, hws, 1, &host);
     if (rc)
 	goto out_release;
 
@@ -408,6 +408,7 @@
 	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
 	PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
 	PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
+	PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
 	PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
 	PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
 	PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-devsets.c linux-libre-2.6.31-gnu/drivers/ide/ide-devsets.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-devsets.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-devsets.c	2009-09-09 18:13:59.000000000 -0400
@@ -183,6 +183,6 @@
 	err = setfunc(drive, *(int *)&rq->cmd[1]);
 	if (err)
 		rq->errors = err;
-	ide_complete_rq(drive, err, ide_rq_bytes(rq));
+	ide_complete_rq(drive, err, blk_rq_bytes(rq));
 	return ide_stopped;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-disk.c linux-libre-2.6.31-gnu/drivers/ide/ide-disk.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-disk.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-disk.c	2009-09-09 18:13:59.000000000 -0400
@@ -82,7 +82,7 @@
 					sector_t block)
 {
 	ide_hwif_t *hwif	= drive->hwif;
-	u16 nsectors		= (u16)rq->nr_sectors;
+	u16 nsectors		= (u16)blk_rq_sectors(rq);
 	u8 lba48		= !!(drive->dev_flags & IDE_DFLAG_LBA48);
 	u8 dma			= !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 	struct ide_cmd		cmd;
@@ -90,7 +90,7 @@
 	ide_startstop_t		rc;
 
 	if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
-		if (block + rq->nr_sectors > 1ULL << 28)
+		if (block + blk_rq_sectors(rq) > 1ULL << 28)
 			dma = 0;
 		else
 			lba48 = 0;
@@ -184,20 +184,13 @@
 	ide_hwif_t *hwif = drive->hwif;
 
 	BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
-
-	if (!blk_fs_request(rq)) {
-		blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
-		if (rq->errors == 0)
-			rq->errors = -EIO;
-		ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
-		return ide_stopped;
-	}
+	BUG_ON(!blk_fs_request(rq));
 
 	ledtrig_ide_activity();
 
-	pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
+	pr_debug("%s: %sing: block=%llu, sectors=%u, buffer=0x%08lx\n",
 		 drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
-		 (unsigned long long)block, rq->nr_sectors,
+		 (unsigned long long)block, blk_rq_sectors(rq),
 		 (unsigned long)rq->buffer);
 
 	if (hwif->rw_disk)
@@ -302,14 +295,12 @@
 	{ NULL,		NULL }
 };
 
-static void idedisk_check_hpa(ide_drive_t *drive)
+static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48)
 {
-	unsigned long long capacity, set_max;
-	int lba48 = ata_id_lba48_enabled(drive->id);
+	u64 capacity, set_max;
 
 	capacity = drive->capacity64;
-
-	set_max = idedisk_read_native_max_address(drive, lba48);
+	set_max  = idedisk_read_native_max_address(drive, lba48);
 
 	if (ide_in_drive_list(drive->id, hpa_list)) {
 		/*
@@ -320,9 +311,31 @@
 			set_max--;
 	}
 
+	return set_max;
+}
+
+static u64 ide_disk_hpa_set_capacity(ide_drive_t *drive, u64 set_max, int lba48)
+{
+	set_max = idedisk_set_max_address(drive, set_max, lba48);
+	if (set_max)
+		drive->capacity64 = set_max;
+
+	return set_max;
+}
+
+static void idedisk_check_hpa(ide_drive_t *drive)
+{
+	u64 capacity, set_max;
+	int lba48 = ata_id_lba48_enabled(drive->id);
+
+	capacity = drive->capacity64;
+	set_max  = ide_disk_hpa_get_native_capacity(drive, lba48);
+
 	if (set_max <= capacity)
 		return;
 
+	drive->probed_capacity = set_max;
+
 	printk(KERN_INFO "%s: Host Protected Area detected.\n"
 			 "\tcurrent capacity is %llu sectors (%llu MB)\n"
 			 "\tnative  capacity is %llu sectors (%llu MB)\n",
@@ -330,13 +343,13 @@
 			 capacity, sectors_to_MB(capacity),
 			 set_max, sectors_to_MB(set_max));
 
-	set_max = idedisk_set_max_address(drive, set_max, lba48);
+	if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0)
+		return;
 
-	if (set_max) {
-		drive->capacity64 = set_max;
+	set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48);
+	if (set_max)
 		printk(KERN_INFO "%s: Host Protected Area disabled.\n",
 				 drive->name);
-	}
 }
 
 static int ide_disk_get_capacity(ide_drive_t *drive)
@@ -358,6 +371,8 @@
 		drive->capacity64 = drive->cyl * drive->head * drive->sect;
 	}
 
+	drive->probed_capacity = drive->capacity64;
+
 	if (lba) {
 		drive->dev_flags |= IDE_DFLAG_LBA;
 
@@ -376,7 +391,7 @@
 		       "%llu sectors (%llu MB)\n",
 		       drive->name, (unsigned long long)drive->capacity64,
 		       sectors_to_MB(drive->capacity64));
-		drive->capacity64 = 1ULL << 28;
+		drive->probed_capacity = drive->capacity64 = 1ULL << 28;
 	}
 
 	if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
@@ -392,6 +407,34 @@
 	return 0;
 }
 
+static u64 ide_disk_set_capacity(ide_drive_t *drive, u64 capacity)
+{
+	u64 set = min(capacity, drive->probed_capacity);
+	u16 *id = drive->id;
+	int lba48 = ata_id_lba48_enabled(id);
+
+	if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 ||
+	    ata_id_hpa_enabled(id) == 0)
+		goto out;
+
+	/*
+	 * according to the spec the SET MAX ADDRESS command shall be
+	 * immediately preceded by a READ NATIVE MAX ADDRESS command
+	 */
+	capacity = ide_disk_hpa_get_native_capacity(drive, lba48);
+	if (capacity == 0)
+		goto out;
+
+	set = ide_disk_hpa_set_capacity(drive, set, lba48);
+	if (set) {
+		/* needed for ->resume to disable HPA */
+		drive->dev_flags |= IDE_DFLAG_NOHPA;
+		return set;
+	}
+out:
+	return drive->capacity64;
+}
+
 static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
 {
 	ide_drive_t *drive = q->queuedata;
@@ -411,8 +454,8 @@
 	cmd->protocol = ATA_PROT_NODATA;
 
 	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
-	rq->cmd_flags |= REQ_SOFTBARRIER;
 	rq->special = cmd;
+	cmd->rq = rq;
 }
 
 ide_devset_get(multcount, mult_count);
@@ -429,14 +472,14 @@
 	if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
 		return -EINVAL;
 
-	if (drive->special.b.set_multmode)
+	if (drive->special_flags & IDE_SFLAG_SET_MULTMODE)
 		return -EBUSY;
 
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
 
 	drive->mult_req = arg;
-	drive->special.b.set_multmode = 1;
+	drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
 	error = blk_execute_rq(drive->queue, NULL, rq, 0);
 	blk_put_request(rq);
 
@@ -640,7 +683,7 @@
 	}
 
 	printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
-		q->max_sectors / 2);
+	       queue_max_sectors(q) / 2);
 
 	if (ata_id_is_ssd(id))
 		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
@@ -741,6 +784,7 @@
 
 const struct ide_disk_ops ide_ata_disk_ops = {
 	.check		= ide_disk_check,
+	.set_capacity	= ide_disk_set_capacity,
 	.get_capacity	= ide_disk_get_capacity,
 	.setup		= ide_disk_setup,
 	.flush		= ide_disk_flush,
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-dma.c linux-libre-2.6.31-gnu/drivers/ide/ide-dma.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -103,7 +103,7 @@
 				ide_finish_cmd(drive, cmd, stat);
 			else
 				ide_complete_rq(drive, 0,
-						cmd->rq->nr_sectors << 9);
+						blk_rq_sectors(cmd->rq) << 9);
 			return ide_stopped;
 		}
 		printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n",
@@ -347,7 +347,6 @@
 
 	return mode;
 }
-EXPORT_SYMBOL_GPL(ide_find_dma_mode);
 
 static int ide_tune_dma(ide_drive_t *drive)
 {
@@ -362,9 +361,6 @@
 	if (__ide_dma_bad_drive(drive))
 		return 0;
 
-	if (ide_id_dma_bug(drive))
-		return 0;
-
 	if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
 		return config_drive_for_dma(drive);
 
@@ -395,24 +391,6 @@
 	return -1;
 }
 
-int ide_id_dma_bug(ide_drive_t *drive)
-{
-	u16 *id = drive->id;
-
-	if (id[ATA_ID_FIELD_VALID] & 4) {
-		if ((id[ATA_ID_UDMA_MODES] >> 8) &&
-		    (id[ATA_ID_MWDMA_MODES] >> 8))
-			goto err_out;
-	} else if ((id[ATA_ID_MWDMA_MODES] >> 8) &&
-		   (id[ATA_ID_SWDMA_MODES] >> 8))
-		goto err_out;
-
-	return 0;
-err_out:
-	printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
-	return 1;
-}
-
 int ide_set_dma(ide_drive_t *drive)
 {
 	int rc;
@@ -510,23 +488,11 @@
 	/*
 	 * un-busy drive etc and make sure request is sane
 	 */
-
 	rq = hwif->rq;
-	if (!rq)
-		goto out;
-
-	hwif->rq = NULL;
-
-	rq->errors = 0;
-
-	if (!rq->bio)
-		goto out;
-
-	rq->sector = rq->bio->bi_sector;
-	rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
-	rq->hard_cur_sectors = rq->current_nr_sectors;
-	rq->buffer = bio_data(rq->bio);
-out:
+	if (rq) {
+		hwif->rq = NULL;
+		rq->errors = 0;
+	}
 	return ret;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-eh.c linux-libre-2.6.31-gnu/drivers/ide/ide-eh.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-eh.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-eh.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,7 +52,7 @@
 	}
 
 	if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
-		drive->special.b.recalibrate = 1;
+		drive->special_flags |= IDE_SFLAG_RECALIBRATE;
 
 	++rq->errors;
 
@@ -149,7 +149,7 @@
 	if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) {
 		if (err <= 0 && rq->errors == 0)
 			rq->errors = -EIO;
-		ide_complete_rq(drive, err ? err : 0, ide_rq_bytes(rq));
+		ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq));
 	}
 }
 
@@ -268,9 +268,8 @@
 {
 	int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
 
-	drive->special.all = 0;
-	drive->special.b.set_geometry = legacy;
-	drive->special.b.recalibrate  = legacy;
+	drive->special_flags =
+		legacy ? (IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE) : 0;
 
 	drive->mult_count = 0;
 	drive->dev_flags &= ~IDE_DFLAG_PARKED;
@@ -280,7 +279,7 @@
 		drive->mult_req = 0;
 
 	if (drive->mult_req != drive->mult_count)
-		drive->special.b.set_multmode = 1;
+		drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
 }
 
 static void pre_reset(ide_drive_t *drive)
@@ -408,8 +407,9 @@
 	/* more than enough time */
 	udelay(10);
 	/* clear SRST, leave nIEN (unless device is on the quirk list) */
-	tp_ops->write_devctl(hwif, (drive->quirk_list == 2 ? 0 : ATA_NIEN) |
-			     ATA_DEVCTL_OBS);
+	tp_ops->write_devctl(hwif,
+		((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) ? 0 : ATA_NIEN) |
+		 ATA_DEVCTL_OBS);
 	/* more than enough time */
 	udelay(10);
 	hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-floppy.c linux-libre-2.6.31-gnu/drivers/ide/ide-floppy.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-floppy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-floppy.c	2009-09-09 18:13:59.000000000 -0400
@@ -77,7 +77,8 @@
 	    (rq && blk_pc_request(rq)))
 		uptodate = 1; /* FIXME */
 	else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
-		u8 *buf = pc->buf;
+
+		u8 *buf = bio_data(rq->bio);
 
 		if (!pc->error) {
 			floppy->sense_key = buf[2] & 0x0F;
@@ -134,13 +135,17 @@
 	drive->pc = pc;
 
 	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
+		unsigned int done = blk_rq_bytes(drive->hwif->rq);
+
 		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
 			ide_floppy_report_error(floppy, pc);
+
 		/* Giving up */
 		pc->error = IDE_DRV_ERROR_GENERAL;
 
 		drive->failed_pc = NULL;
 		drive->pc_callback(drive, 0);
+		ide_complete_rq(drive, -EIO, done);
 		return ide_stopped;
 	}
 
@@ -190,7 +195,7 @@
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
 	int block = sector / floppy->bs_factor;
-	int blocks = rq->nr_sectors / floppy->bs_factor;
+	int blocks = blk_rq_sectors(rq) / floppy->bs_factor;
 	int cmd = rq_data_dir(rq);
 
 	ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks);
@@ -205,8 +210,7 @@
 	pc->rq = rq;
 	if (rq->cmd_flags & REQ_RW)
 		pc->flags |= PC_FLAG_WRITING;
-	pc->buf = NULL;
-	pc->req_xfer = pc->buf_size = blocks * floppy->block_size;
+
 	pc->flags |= PC_FLAG_DMA_OK;
 }
 
@@ -216,16 +220,11 @@
 	ide_init_pc(pc);
 	memcpy(pc->c, rq->cmd, sizeof(pc->c));
 	pc->rq = rq;
-	if (rq->data_len && rq_data_dir(rq) == WRITE)
-		pc->flags |= PC_FLAG_WRITING;
-	pc->buf = rq->data;
-	if (rq->bio)
+	if (blk_rq_bytes(rq)) {
 		pc->flags |= PC_FLAG_DMA_OK;
-	/*
-	 * possibly problematic, doesn't look like ide-floppy correctly
-	 * handled scattered requests if dma fails...
-	 */
-	pc->req_xfer = pc->buf_size = rq->data_len;
+		if (rq_data_dir(rq) == WRITE)
+			pc->flags |= PC_FLAG_WRITING;
+	}
 }
 
 static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
@@ -257,23 +256,23 @@
 			goto out_end;
 	}
 	if (blk_fs_request(rq)) {
-		if (((long)rq->sector % floppy->bs_factor) ||
-		    (rq->nr_sectors % floppy->bs_factor)) {
+		if (((long)blk_rq_pos(rq) % floppy->bs_factor) ||
+		    (blk_rq_sectors(rq) % floppy->bs_factor)) {
 			printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
 				drive->name);
 			goto out_end;
 		}
 		pc = &floppy->queued_pc;
 		idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
-	} else if (blk_special_request(rq)) {
-		pc = (struct ide_atapi_pc *) rq->buffer;
+	} else if (blk_special_request(rq) || blk_sense_request(rq)) {
+		pc = (struct ide_atapi_pc *)rq->special;
 	} else if (blk_pc_request(rq)) {
 		pc = &floppy->queued_pc;
 		idefloppy_blockpc_cmd(floppy, pc, rq);
-	} else {
-		blk_dump_rq_flags(rq, PFX "unsupported command in queue");
-		goto out_end;
-	}
+	} else
+		BUG();
+
+	ide_prep_sense(drive, rq);
 
 	memset(&cmd, 0, sizeof(cmd));
 
@@ -282,8 +281,8 @@
 
 	cmd.rq = rq;
 
-	if (blk_fs_request(rq) || pc->req_xfer) {
-		ide_init_sg_cmd(&cmd, pc->req_xfer);
+	if (blk_fs_request(rq) || blk_rq_bytes(rq)) {
+		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
 		ide_map_sg(drive, &cmd);
 	}
 
@@ -294,7 +293,7 @@
 	drive->failed_pc = NULL;
 	if (blk_fs_request(rq) == 0 && rq->errors == 0)
 		rq->errors = -EIO;
-	ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
+	ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
 	return ide_stopped;
 }
 
@@ -307,33 +306,33 @@
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
 	struct gendisk *disk = floppy->disk;
-	u8 *page;
+	u8 *page, buf[40];
 	int capacity, lba_capacity;
 	u16 transfer_rate, sector_size, cyls, rpm;
 	u8 heads, sectors;
 
 	ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
 
-	if (ide_queue_pc_tail(drive, disk, pc)) {
+	if (ide_queue_pc_tail(drive, disk, pc, buf, pc->req_xfer)) {
 		printk(KERN_ERR PFX "Can't get flexible disk page params\n");
 		return 1;
 	}
 
-	if (pc->buf[3] & 0x80)
+	if (buf[3] & 0x80)
 		drive->dev_flags |= IDE_DFLAG_WP;
 	else
 		drive->dev_flags &= ~IDE_DFLAG_WP;
 
 	set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP));
 
-	page = &pc->buf[8];
+	page = &buf[8];
 
-	transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]);
-	sector_size   = be16_to_cpup((__be16 *)&pc->buf[8 + 6]);
-	cyls          = be16_to_cpup((__be16 *)&pc->buf[8 + 8]);
-	rpm           = be16_to_cpup((__be16 *)&pc->buf[8 + 28]);
-	heads         = pc->buf[8 + 4];
-	sectors       = pc->buf[8 + 5];
+	transfer_rate = be16_to_cpup((__be16 *)&buf[8 + 2]);
+	sector_size   = be16_to_cpup((__be16 *)&buf[8 + 6]);
+	cyls          = be16_to_cpup((__be16 *)&buf[8 + 8]);
+	rpm           = be16_to_cpup((__be16 *)&buf[8 + 28]);
+	heads         = buf[8 + 4];
+	sectors       = buf[8 + 5];
 
 	capacity = cyls * heads * sectors * sector_size;
 
@@ -383,22 +382,19 @@
 	drive->capacity64 = 0;
 
 	ide_floppy_create_read_capacity_cmd(&pc);
-	pc.buf = &pc_buf[0];
-	pc.buf_size = sizeof(pc_buf);
-
-	if (ide_queue_pc_tail(drive, disk, &pc)) {
+	if (ide_queue_pc_tail(drive, disk, &pc, pc_buf, pc.req_xfer)) {
 		printk(KERN_ERR PFX "Can't get floppy parameters\n");
 		return 1;
 	}
-	header_len = pc.buf[3];
-	cap_desc = &pc.buf[4];
+	header_len = pc_buf[3];
+	cap_desc = &pc_buf[4];
 	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
 
 	for (i = 0; i < desc_cnt; i++) {
 		unsigned int desc_start = 4 + i*8;
 
-		blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
-		length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
+		blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]);
+		length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]);
 
 		ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
 					     "%d sector size",
@@ -411,7 +407,7 @@
 		 * the code below is valid only for the 1st descriptor, ie i=0
 		 */
 
-		switch (pc.buf[desc_start + 4] & 0x03) {
+		switch (pc_buf[desc_start + 4] & 0x03) {
 		/* Clik! drive returns this instead of CAPACITY_CURRENT */
 		case CAPACITY_UNFORMATTED:
 			if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
@@ -460,7 +456,7 @@
 			break;
 		}
 		ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d",
-					     pc.buf[desc_start + 4] & 0x03);
+					     pc_buf[desc_start + 4] & 0x03);
 	}
 
 	/* Clik! disk does not support get_flexible_disk_page */
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-floppy_ioctl.c linux-libre-2.6.31-gnu/drivers/ide/ide-floppy_ioctl.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-floppy_ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-floppy_ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,15 +47,13 @@
 		return -EINVAL;
 
 	ide_floppy_create_read_capacity_cmd(pc);
-	pc->buf = &pc_buf[0];
-	pc->buf_size = sizeof(pc_buf);
 
-	if (ide_queue_pc_tail(drive, floppy->disk, pc)) {
+	if (ide_queue_pc_tail(drive, floppy->disk, pc, pc_buf, pc->req_xfer)) {
 		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
 		return -EIO;
 	}
 
-	header_len = pc->buf[3];
+	header_len = pc_buf[3];
 	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
 
 	u_index = 0;
@@ -72,8 +70,8 @@
 		if (u_index >= u_array_size)
 			break;	/* User-supplied buffer too small */
 
-		blocks = be32_to_cpup((__be32 *)&pc->buf[desc_start]);
-		length = be16_to_cpup((__be16 *)&pc->buf[desc_start + 6]);
+		blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]);
+		length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]);
 
 		if (put_user(blocks, argp))
 			return -EFAULT;
@@ -94,40 +92,42 @@
 	return 0;
 }
 
-static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
-		int l, int flags)
+static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc,
+					      u8 *buf, int b, int l,
+					      int flags)
 {
 	ide_init_pc(pc);
 	pc->c[0] = GPCMD_FORMAT_UNIT;
 	pc->c[1] = 0x17;
 
-	memset(pc->buf, 0, 12);
-	pc->buf[1] = 0xA2;
+	memset(buf, 0, 12);
+	buf[1] = 0xA2;
 	/* Default format list header, u8 1: FOV/DCRT/IMM bits set */
 
 	if (flags & 1)				/* Verify bit on... */
-		pc->buf[1] ^= 0x20;		/* ... turn off DCRT bit */
-	pc->buf[3] = 8;
+		buf[1] ^= 0x20;			/* ... turn off DCRT bit */
+	buf[3] = 8;
 
-	put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
-	put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
-	pc->buf_size = 12;
+	put_unaligned(cpu_to_be32(b), (unsigned int *)(&buf[4]));
+	put_unaligned(cpu_to_be32(l), (unsigned int *)(&buf[8]));
+	pc->req_xfer = 12;
 	pc->flags |= PC_FLAG_WRITING;
 }
 
 static int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc)
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
+	u8 buf[20];
 
 	drive->atapi_flags &= ~IDE_AFLAG_SRFP;
 
 	ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE);
 	pc->flags |= PC_FLAG_SUPPRESS_ERROR;
 
-	if (ide_queue_pc_tail(drive, floppy->disk, pc))
+	if (ide_queue_pc_tail(drive, floppy->disk, pc, buf, pc->req_xfer))
 		return 1;
 
-	if (pc->buf[8 + 2] & 0x40)
+	if (buf[8 + 2] & 0x40)
 		drive->atapi_flags |= IDE_AFLAG_SRFP;
 
 	return 0;
@@ -137,6 +137,7 @@
 				  int __user *arg)
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
+	u8 buf[12];
 	int blocks, length, flags, err = 0;
 
 	if (floppy->openers > 1) {
@@ -170,9 +171,9 @@
 	}
 
 	ide_floppy_get_sfrp_bit(drive, pc);
-	ide_floppy_create_format_unit_cmd(pc, blocks, length, flags);
+	ide_floppy_create_format_unit_cmd(pc, buf, blocks, length, flags);
 
-	if (ide_queue_pc_tail(drive, floppy->disk, pc))
+	if (ide_queue_pc_tail(drive, floppy->disk, pc, buf, pc->req_xfer))
 		err = -EIO;
 
 out:
@@ -196,11 +197,13 @@
 					  int __user *arg)
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
+	u8 sense_buf[18];
 	int progress_indication = 0x10000;
 
 	if (drive->atapi_flags & IDE_AFLAG_SRFP) {
 		ide_create_request_sense_cmd(drive, pc);
-		if (ide_queue_pc_tail(drive, floppy->disk, pc))
+		if (ide_queue_pc_tail(drive, floppy->disk, pc, sense_buf,
+				      pc->req_xfer))
 			return -EIO;
 
 		if (floppy->sense_key == 2 &&
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-gd.c linux-libre-2.6.31-gnu/drivers/ide/ide-gd.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-gd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-gd.c	2009-09-09 18:13:59.000000000 -0400
@@ -287,6 +287,19 @@
 	return ret;
 }
 
+static unsigned long long ide_gd_set_capacity(struct gendisk *disk,
+					      unsigned long long capacity)
+{
+	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
+	ide_drive_t *drive = idkp->drive;
+	const struct ide_disk_ops *disk_ops = drive->disk_ops;
+
+	if (disk_ops->set_capacity)
+		return disk_ops->set_capacity(drive, capacity);
+
+	return drive->capacity64;
+}
+
 static int ide_gd_revalidate_disk(struct gendisk *disk)
 {
 	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
@@ -315,6 +328,7 @@
 	.locked_ioctl		= ide_gd_ioctl,
 	.getgeo			= ide_gd_getgeo,
 	.media_changed		= ide_gd_media_changed,
+	.set_capacity		= ide_gd_set_capacity,
 	.revalidate_disk	= ide_gd_revalidate_disk
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-generic.c linux-libre-2.6.31-gnu/drivers/ide/ide-generic.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,7 @@
 
 static const struct ide_port_info ide_generic_port_info = {
 	.host_flags		= IDE_HFLAG_NO_DMA,
+	.chipset		= ide_generic,
 };
 
 #ifdef CONFIG_ARM
@@ -85,7 +86,7 @@
 
 static int __init ide_generic_init(void)
 {
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	unsigned long io_addr;
 	int i, rc = 0, primary = 0, secondary = 0;
 
@@ -132,9 +133,7 @@
 #else
 			hw.irq = legacy_irqs[i];
 #endif
-			hw.chipset = ide_generic;
-
-			rc = ide_host_add(&ide_generic_port_info, hws, NULL);
+			rc = ide_host_add(&ide_generic_port_info, hws, 1, NULL);
 			if (rc) {
 				release_region(io_addr + 0x206, 1);
 				release_region(io_addr, 8);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-h8300.c linux-libre-2.6.31-gnu/drivers/ide/ide-h8300.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-h8300.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-h8300.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,26 +64,26 @@
 
 #define H8300_IDE_GAP (2)
 
-static inline void hw_setup(hw_regs_t *hw)
+static inline void hw_setup(struct ide_hw *hw)
 {
 	int i;
 
-	memset(hw, 0, sizeof(hw_regs_t));
+	memset(hw, 0, sizeof(*hw));
 	for (i = 0; i <= 7; i++)
 		hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
 	hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
 	hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
-	hw->chipset = ide_generic;
 }
 
 static const struct ide_port_info h8300_port_info = {
 	.tp_ops			= &h8300_tp_ops,
 	.host_flags		= IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
+	.chipset		= ide_generic,
 };
 
 static int __init h8300_ide_init(void)
 {
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 
 	printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
 
@@ -96,7 +96,7 @@
 
 	hw_setup(&hw);
 
-	return ide_host_add(&h8300_port_info, hws, NULL);
+	return ide_host_add(&h8300_port_info, hws, 1, NULL);
 
 out_busy:
 	printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-io.c linux-libre-2.6.31-gnu/drivers/ide/ide-io.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-io.c	2009-09-09 18:13:59.000000000 -0400
@@ -112,16 +112,6 @@
 	}
 }
 
-/* obsolete, blk_rq_bytes() should be used instead */
-unsigned int ide_rq_bytes(struct request *rq)
-{
-	if (blk_pc_request(rq))
-		return rq->data_len;
-	else
-		return rq->hard_cur_sectors << 9;
-}
-EXPORT_SYMBOL_GPL(ide_rq_bytes);
-
 int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
 {
 	ide_hwif_t *hwif = drive->hwif;
@@ -133,7 +123,7 @@
 	 * and complete the whole request right now
 	 */
 	if (blk_noretry_request(rq) && error <= 0)
-		nr_bytes = rq->hard_nr_sectors << 9;
+		nr_bytes = blk_rq_sectors(rq) << 9;
 
 	rc = ide_end_rq(drive, rq, error, nr_bytes);
 	if (rc == 0)
@@ -152,14 +142,14 @@
 
 	if ((media == ide_floppy || media == ide_tape) && drv_req) {
 		rq->errors = 0;
-		ide_complete_rq(drive, 0, blk_rq_bytes(rq));
 	} else {
 		if (media == ide_tape)
 			rq->errors = IDE_DRV_ERROR_GENERAL;
 		else if (blk_fs_request(rq) == 0 && rq->errors == 0)
 			rq->errors = -EIO;
-		ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
 	}
+
+	ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
 }
 
 static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
@@ -184,29 +174,42 @@
 	tf->command = ATA_CMD_SET_MULTI;
 }
 
-static ide_startstop_t ide_disk_special(ide_drive_t *drive)
+/**
+ *	do_special		-	issue some special commands
+ *	@drive: drive the command is for
+ *
+ *	do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS,
+ *	ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive.
+ */
+
+static ide_startstop_t do_special(ide_drive_t *drive)
 {
-	special_t *s = &drive->special;
 	struct ide_cmd cmd;
 
+#ifdef DEBUG
+	printk(KERN_DEBUG "%s: %s: 0x%02x\n", drive->name, __func__,
+		drive->special_flags);
+#endif
+	if (drive->media != ide_disk) {
+		drive->special_flags = 0;
+		drive->mult_req = 0;
+		return ide_stopped;
+	}
+
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.protocol = ATA_PROT_NODATA;
 
-	if (s->b.set_geometry) {
-		s->b.set_geometry = 0;
+	if (drive->special_flags & IDE_SFLAG_SET_GEOMETRY) {
+		drive->special_flags &= ~IDE_SFLAG_SET_GEOMETRY;
 		ide_tf_set_specify_cmd(drive, &cmd.tf);
-	} else if (s->b.recalibrate) {
-		s->b.recalibrate = 0;
+	} else if (drive->special_flags & IDE_SFLAG_RECALIBRATE) {
+		drive->special_flags &= ~IDE_SFLAG_RECALIBRATE;
 		ide_tf_set_restore_cmd(drive, &cmd.tf);
-	} else if (s->b.set_multmode) {
-		s->b.set_multmode = 0;
+	} else if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) {
+		drive->special_flags &= ~IDE_SFLAG_SET_MULTMODE;
 		ide_tf_set_setmult_cmd(drive, &cmd.tf);
-	} else if (s->all) {
-		int special = s->all;
-		s->all = 0;
-		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
-		return ide_stopped;
-	}
+	} else
+		BUG();
 
 	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
 	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
@@ -217,45 +220,13 @@
 	return ide_started;
 }
 
-/**
- *	do_special		-	issue some special commands
- *	@drive: drive the command is for
- *
- *	do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS,
- *	ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive.
- *
- *	It used to do much more, but has been scaled back.
- */
-
-static ide_startstop_t do_special (ide_drive_t *drive)
-{
-	special_t *s = &drive->special;
-
-#ifdef DEBUG
-	printk("%s: do_special: 0x%02x\n", drive->name, s->all);
-#endif
-	if (drive->media == ide_disk)
-		return ide_disk_special(drive);
-
-	s->all = 0;
-	drive->mult_req = 0;
-	return ide_stopped;
-}
-
 void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct scatterlist *sg = hwif->sg_table;
 	struct request *rq = cmd->rq;
 
-	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-		sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
-		cmd->sg_nents = 1;
-	} else if (!rq->bio) {
-		sg_init_one(sg, rq->data, rq->data_len);
-		cmd->sg_nents = 1;
-	} else
-		cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
+	cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
 }
 EXPORT_SYMBOL_GPL(ide_map_sg);
 
@@ -286,7 +257,7 @@
 
 	if (cmd) {
 		if (cmd->protocol == ATA_PROT_PIO) {
-			ide_init_sg_cmd(cmd, rq->nr_sectors << 9);
+			ide_init_sg_cmd(cmd, blk_rq_sectors(rq) << 9);
 			ide_map_sg(drive, cmd);
 		}
 
@@ -358,7 +329,8 @@
 		printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
 		return startstop;
 	}
-	if (!drive->special.all) {
+
+	if (drive->special_flags == 0) {
 		struct ide_driver *drv;
 
 		/*
@@ -371,7 +343,7 @@
 		if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
 			return execute_drive_cmd(drive, rq);
 		else if (blk_pm_request(rq)) {
-			struct request_pm_state *pm = rq->data;
+			struct request_pm_state *pm = rq->special;
 #ifdef DEBUG_PM
 			printk("%s: start_power_step(step: %d)\n",
 				drive->name, pm->pm_step);
@@ -394,7 +366,7 @@
 
 		drv = *(struct ide_driver **)rq->rq_disk->private_data;
 
-		return drv->do_request(drive, rq, rq->sector);
+		return drv->do_request(drive, rq, blk_rq_pos(rq));
 	}
 	return do_special(drive);
 kill_rq:
@@ -484,6 +456,9 @@
 
 	spin_unlock_irq(q->queue_lock);
 
+	/* HLD do_request() callback might sleep, make sure it's okay */
+	might_sleep();
+
 	if (ide_lock_host(host, hwif))
 		goto plug_device_2;
 
@@ -491,10 +466,10 @@
 
 	if (!ide_lock_port(hwif)) {
 		ide_hwif_t *prev_port;
+
+		WARN_ON_ONCE(hwif->rq);
 repeat:
 		prev_port = hwif->host->cur_port;
-		hwif->rq = NULL;
-
 		if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
 		    time_after(drive->sleep, jiffies)) {
 			ide_unlock_port(hwif);
@@ -503,11 +478,15 @@
 
 		if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) &&
 		    hwif != prev_port) {
+			ide_drive_t *cur_dev =
+				prev_port ? prev_port->cur_dev : NULL;
+
 			/*
 			 * set nIEN for previous port, drives in the
-			 * quirk_list may not like intr setups/cleanups
+			 * quirk list may not like intr setups/cleanups
 			 */
-			if (prev_port && prev_port->cur_dev->quirk_list == 0)
+			if (cur_dev &&
+			    (cur_dev->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0)
 				prev_port->tp_ops->write_devctl(prev_port,
 								ATA_NIEN |
 								ATA_DEVCTL_OBS);
@@ -523,7 +502,9 @@
 		 * we know that the queue isn't empty, but this can happen
 		 * if the q->prep_rq_fn() decides to kill a request
 		 */
-		rq = elv_next_request(drive->queue);
+		if (!rq)
+			rq = blk_fetch_request(drive->queue);
+
 		spin_unlock_irq(q->queue_lock);
 		spin_lock_irq(&hwif->lock);
 
@@ -535,7 +516,7 @@
 		/*
 		 * Sanity: don't accept a request that isn't a PM request
 		 * if we are currently power managed. This is very important as
-		 * blk_stop_queue() doesn't prevent the elv_next_request()
+		 * blk_stop_queue() doesn't prevent the blk_fetch_request()
 		 * above to return us whatever is in the queue. Since we call
 		 * ide_do_request() ourselves, we end up taking requests while
 		 * the queue is blocked...
@@ -559,8 +540,11 @@
 		startstop = start_request(drive, rq);
 		spin_lock_irq(&hwif->lock);
 
-		if (startstop == ide_stopped)
+		if (startstop == ide_stopped) {
+			rq = hwif->rq;
+			hwif->rq = NULL;
 			goto repeat;
+		}
 	} else
 		goto plug_device;
 out:
@@ -576,18 +560,24 @@
 plug_device_2:
 	spin_lock_irq(q->queue_lock);
 
+	if (rq)
+		blk_requeue_request(q, rq);
 	if (!elv_queue_empty(q))
 		blk_plug_device(q);
 }
 
-static void ide_plug_device(ide_drive_t *drive)
+static void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
 {
 	struct request_queue *q = drive->queue;
 	unsigned long flags;
 
 	spin_lock_irqsave(q->queue_lock, flags);
+
+	if (rq)
+		blk_requeue_request(q, rq);
 	if (!elv_queue_empty(q))
 		blk_plug_device(q);
+
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -636,6 +626,7 @@
 	unsigned long	flags;
 	int		wait = -1;
 	int		plug_device = 0;
+	struct request	*uninitialized_var(rq_in_flight);
 
 	spin_lock_irqsave(&hwif->lock, flags);
 
@@ -682,8 +673,9 @@
 		} else if (drive_is_ready(drive)) {
 			if (drive->waiting_for_dma)
 				hwif->dma_ops->dma_lost_irq(drive);
-			if (hwif->ack_intr)
-				hwif->ack_intr(hwif);
+			if (hwif->port_ops && hwif->port_ops->clear_irq)
+				hwif->port_ops->clear_irq(drive);
+
 			printk(KERN_WARNING "%s: lost interrupt\n",
 				drive->name);
 			startstop = handler(drive);
@@ -697,6 +689,8 @@
 		spin_lock_irq(&hwif->lock);
 		enable_irq(hwif->irq);
 		if (startstop == ide_stopped && hwif->polling == 0) {
+			rq_in_flight = hwif->rq;
+			hwif->rq = NULL;
 			ide_unlock_port(hwif);
 			plug_device = 1;
 		}
@@ -705,7 +699,7 @@
 
 	if (plug_device) {
 		ide_unlock_host(hwif->host);
-		ide_plug_device(drive);
+		ide_requeue_and_plug(drive, rq_in_flight);
 	}
 }
 
@@ -791,6 +785,7 @@
 	ide_startstop_t startstop;
 	irqreturn_t irq_ret = IRQ_NONE;
 	int plug_device = 0;
+	struct request *uninitialized_var(rq_in_flight);
 
 	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
 		if (hwif != host->cur_port)
@@ -799,7 +794,8 @@
 
 	spin_lock_irqsave(&hwif->lock, flags);
 
-	if (hwif->ack_intr && hwif->ack_intr(hwif) == 0)
+	if (hwif->port_ops && hwif->port_ops->test_irq &&
+	    hwif->port_ops->test_irq(hwif) == 0)
 		goto out;
 
 	handler = hwif->handler;
@@ -870,6 +866,8 @@
 	 */
 	if (startstop == ide_stopped && hwif->polling == 0) {
 		BUG_ON(hwif->handler);
+		rq_in_flight = hwif->rq;
+		hwif->rq = NULL;
 		ide_unlock_port(hwif);
 		plug_device = 1;
 	}
@@ -879,7 +877,7 @@
 out_early:
 	if (plug_device) {
 		ide_unlock_host(hwif->host);
-		ide_plug_device(drive);
+		ide_requeue_and_plug(drive, rq_in_flight);
 	}
 
 	return irq_ret;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-ioctls.c linux-libre-2.6.31-gnu/drivers/ide/ide-ioctls.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-ioctls.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-ioctls.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,7 +64,8 @@
 		goto out;
 	}
 
-	id = kmalloc(size, GFP_KERNEL);
+	/* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */
+	id = kmalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
 	if (id == NULL) {
 		rc = -ENOMEM;
 		goto out;
@@ -118,7 +119,6 @@
 	u8 args[4], xfer_rate = 0;
 	struct ide_cmd cmd;
 	struct ide_taskfile *tf = &cmd.tf;
-	u16 *id = drive->id;
 
 	if (NULL == (void *) arg) {
 		struct request *rq;
@@ -161,14 +161,10 @@
 
 	if (tf->command == ATA_CMD_SET_FEATURES &&
 	    tf->feature == SETFEATURES_XFER &&
-	    tf->nsect >= XFER_SW_DMA_0 &&
-	    (id[ATA_ID_UDMA_MODES] ||
-	     id[ATA_ID_MWDMA_MODES] ||
-	     id[ATA_ID_SWDMA_MODES])) {
-		xfer_rate = args[1];
-		if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
-			printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
-					    "be set\n", drive->name);
+	    tf->nsect >= XFER_SW_DMA_0) {
+		xfer_rate = ide_find_dma_mode(drive, XFER_UDMA_6);
+		if (xfer_rate != tf->nsect) {
+			err = -EINVAL;
 			goto abort;
 		}
 	}
@@ -231,7 +227,6 @@
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->cmd_len = 1;
 	rq->cmd[0] = REQ_DRIVE_RESET;
-	rq->cmd_flags |= REQ_SOFTBARRIER;
 	if (blk_execute_rq(drive->queue, NULL, rq, 1))
 		ret = rq->errors;
 	blk_put_request(rq);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-iops.c linux-libre-2.6.31-gnu/drivers/ide/ide-iops.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-iops.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-iops.c	2009-09-09 18:13:59.000000000 -0400
@@ -210,6 +210,7 @@
  */
 static const struct drive_list_entry ivb_list[] = {
 	{ "QUANTUM FIREBALLlct10 05"	, "A03.0900"	},
+	{ "QUANTUM FIREBALLlct20 30"	, "APL.0900"	},
 	{ "TSSTcorp CDDVDW SH-S202J"	, "SB00"	},
 	{ "TSSTcorp CDDVDW SH-S202J"	, "SB01"	},
 	{ "TSSTcorp CDDVDW SH-S202N"	, "SB00"	},
@@ -282,6 +283,29 @@
 	return 0;
 }
 
+static const char *nien_quirk_list[] = {
+	"QUANTUM FIREBALLlct08 08",
+	"QUANTUM FIREBALLP KA6.4",
+	"QUANTUM FIREBALLP KA9.1",
+	"QUANTUM FIREBALLP KX13.6",
+	"QUANTUM FIREBALLP KX20.5",
+	"QUANTUM FIREBALLP KX27.3",
+	"QUANTUM FIREBALLP LM20.4",
+	"QUANTUM FIREBALLP LM20.5",
+	NULL
+};
+
+void ide_check_nien_quirk_list(ide_drive_t *drive)
+{
+	const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
+
+	for (list = nien_quirk_list; *list != NULL; list++)
+		if (strstr(m, *list) != NULL) {
+			drive->dev_flags |= IDE_DFLAG_NIEN_QUIRK;
+			return;
+		}
+}
+
 int ide_driveid_update(ide_drive_t *drive)
 {
 	u16 *id;
@@ -306,12 +330,8 @@
 
 	kfree(id);
 
-	if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive))
-		ide_dma_off(drive);
-
 	return 1;
 out_err:
-	SELECT_MASK(drive, 0);
 	if (rc == 2)
 		printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__);
 	kfree(id);
@@ -365,7 +385,7 @@
 
 	tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
 
-	if (drive->quirk_list == 2)
+	if (drive->dev_flags & IDE_DFLAG_NIEN_QUIRK)
 		tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
 
 	error = __ide_wait_stat(drive, drive->ready_stat,
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-legacy.c linux-libre-2.6.31-gnu/drivers/ide/ide-legacy.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-legacy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-legacy.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 
-static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
+static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw,
 				u8 port_no, const struct ide_port_info *d,
 				unsigned long config)
 {
@@ -33,7 +33,6 @@
 
 	ide_std_init_ports(hw, base, ctl);
 	hw->irq = irq;
-	hw->chipset = d->chipset;
 	hw->config = config;
 
 	hws[port_no] = hw;
@@ -41,7 +40,7 @@
 
 int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
 {
-	hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
+	struct ide_hw hw[2], *hws[] = { NULL, NULL };
 
 	memset(&hw, 0, sizeof(hw));
 
@@ -53,6 +52,6 @@
 	    (d->host_flags & IDE_HFLAG_SINGLE))
 		return -ENOENT;
 
-	return ide_host_add(d, hws, NULL);
+	return ide_host_add(d, hws, 2, NULL);
 }
 EXPORT_SYMBOL_GPL(ide_legacy_device_add);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-lib.c linux-libre-2.6.31-gnu/drivers/ide/ide-lib.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-lib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-lib.c	2009-09-09 18:13:59.000000000 -0400
@@ -96,7 +96,7 @@
 
 		if (rq)
 			printk(KERN_CONT ", sector=%llu",
-			       (unsigned long long)rq->sector);
+			       (unsigned long long)blk_rq_pos(rq));
 	}
 	printk(KERN_CONT "\n");
 }
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-park.c linux-libre-2.6.31-gnu/drivers/ide/ide-park.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-park.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-park.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,11 +24,8 @@
 			start_queue = 1;
 		spin_unlock_irq(&hwif->lock);
 
-		if (start_queue) {
-			spin_lock_irq(q->queue_lock);
-			blk_start_queueing(q);
-			spin_unlock_irq(q->queue_lock);
-		}
+		if (start_queue)
+			blk_run_queue(q);
 		return;
 	}
 	spin_unlock_irq(&hwif->lock);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide_platform.c linux-libre-2.6.31-gnu/drivers/ide/ide_platform.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide_platform.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide_platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,7 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
+static void __devinit plat_ide_setup_ports(struct ide_hw *hw,
 					   void __iomem *base,
 					   void __iomem *ctrl,
 					   struct pata_platform_info *pdata,
@@ -40,12 +40,11 @@
 	hw->io_ports.ctl_addr = (unsigned long)ctrl;
 
 	hw->irq = irq;
-
-	hw->chipset = ide_generic;
 }
 
 static const struct ide_port_info platform_ide_port_info = {
 	.host_flags		= IDE_HFLAG_NO_DMA,
+	.chipset		= ide_generic,
 };
 
 static int __devinit plat_ide_probe(struct platform_device *pdev)
@@ -55,7 +54,7 @@
 	struct pata_platform_info *pdata;
 	struct ide_host *host;
 	int ret = 0, mmio = 0;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	struct ide_port_info d = platform_ide_port_info;
 
 	pdata = pdev->dev.platform_data;
@@ -99,7 +98,7 @@
 	if (mmio)
 		d.host_flags |= IDE_HFLAG_MMIO;
 
-	ret = ide_host_add(&d, hws, &host);
+	ret = ide_host_add(&d, hws, 1, &host);
 	if (ret)
 		goto out;
 
@@ -113,7 +112,7 @@
 
 static int __devexit plat_ide_remove(struct platform_device *pdev)
 {
-	struct ide_host *host = pdev->dev.driver_data;
+	struct ide_host *host = dev_get_drvdata(&pdev->dev);
 
 	ide_host_remove(host);
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-pm.c linux-libre-2.6.31-gnu/drivers/ide/ide-pm.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-pm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-pm.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,23 +3,23 @@
 
 int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 {
-	ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
+	ide_drive_t *drive = dev_get_drvdata(dev);
+	ide_drive_t *pair = ide_get_pair_dev(drive);
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq;
 	struct request_pm_state rqpm;
-	struct ide_cmd cmd;
 	int ret;
 
-	/* call ACPI _GTM only once */
-	if ((drive->dn & 1) == 0 || pair == NULL)
-		ide_acpi_get_timing(hwif);
+	if (ide_port_acpi(hwif)) {
+		/* call ACPI _GTM only once */
+		if ((drive->dn & 1) == 0 || pair == NULL)
+			ide_acpi_get_timing(hwif);
+	}
 
 	memset(&rqpm, 0, sizeof(rqpm));
-	memset(&cmd, 0, sizeof(cmd));
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_PM_SUSPEND;
-	rq->special = &cmd;
-	rq->data = &rqpm;
+	rq->special = &rqpm;
 	rqpm.pm_step = IDE_PM_START_SUSPEND;
 	if (mesg.event == PM_EVENT_PRETHAW)
 		mesg.event = PM_EVENT_FREEZE;
@@ -28,37 +28,39 @@
 	ret = blk_execute_rq(drive->queue, NULL, rq, 0);
 	blk_put_request(rq);
 
-	/* call ACPI _PS3 only after both devices are suspended */
-	if (ret == 0 && ((drive->dn & 1) || pair == NULL))
-		ide_acpi_set_state(hwif, 0);
+	if (ret == 0 && ide_port_acpi(hwif)) {
+		/* call ACPI _PS3 only after both devices are suspended */
+		if ((drive->dn & 1) || pair == NULL)
+			ide_acpi_set_state(hwif, 0);
+	}
 
 	return ret;
 }
 
 int generic_ide_resume(struct device *dev)
 {
-	ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
+	ide_drive_t *drive = dev_get_drvdata(dev);
+	ide_drive_t *pair = ide_get_pair_dev(drive);
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq;
 	struct request_pm_state rqpm;
-	struct ide_cmd cmd;
 	int err;
 
-	/* call ACPI _PS0 / _STM only once */
-	if ((drive->dn & 1) == 0 || pair == NULL) {
-		ide_acpi_set_state(hwif, 1);
-		ide_acpi_push_timing(hwif);
-	}
+	if (ide_port_acpi(hwif)) {
+		/* call ACPI _PS0 / _STM only once */
+		if ((drive->dn & 1) == 0 || pair == NULL) {
+			ide_acpi_set_state(hwif, 1);
+			ide_acpi_push_timing(hwif);
+		}
 
-	ide_acpi_exec_tfs(drive);
+		ide_acpi_exec_tfs(drive);
+	}
 
 	memset(&rqpm, 0, sizeof(rqpm));
-	memset(&cmd, 0, sizeof(cmd));
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_PM_RESUME;
 	rq->cmd_flags |= REQ_PREEMPT;
-	rq->special = &cmd;
-	rq->data = &rqpm;
+	rq->special = &rqpm;
 	rqpm.pm_step = IDE_PM_START_RESUME;
 	rqpm.pm_state = PM_EVENT_ON;
 
@@ -77,7 +79,7 @@
 
 void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
 {
-	struct request_pm_state *pm = rq->data;
+	struct request_pm_state *pm = rq->special;
 
 #ifdef DEBUG_PM
 	printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
@@ -107,10 +109,8 @@
 
 ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
 {
-	struct request_pm_state *pm = rq->data;
-	struct ide_cmd *cmd = rq->special;
-
-	memset(cmd, 0, sizeof(*cmd));
+	struct request_pm_state *pm = rq->special;
+	struct ide_cmd cmd = { };
 
 	switch (pm->pm_step) {
 	case IDE_PM_FLUSH_CACHE:	/* Suspend step 1 (flush cache) */
@@ -123,12 +123,12 @@
 			return ide_stopped;
 		}
 		if (ata_id_flush_ext_enabled(drive->id))
-			cmd->tf.command = ATA_CMD_FLUSH_EXT;
+			cmd.tf.command = ATA_CMD_FLUSH_EXT;
 		else
-			cmd->tf.command = ATA_CMD_FLUSH;
+			cmd.tf.command = ATA_CMD_FLUSH;
 		goto out_do_tf;
 	case IDE_PM_STANDBY:		/* Suspend step 2 (standby) */
-		cmd->tf.command = ATA_CMD_STANDBYNOW1;
+		cmd.tf.command = ATA_CMD_STANDBYNOW1;
 		goto out_do_tf;
 	case IDE_PM_RESTORE_PIO:	/* Resume step 1 (restore PIO) */
 		ide_set_max_pio(drive);
@@ -141,7 +141,7 @@
 			ide_complete_power_step(drive, rq);
 		return ide_stopped;
 	case IDE_PM_IDLE:		/* Resume step 2 (idle) */
-		cmd->tf.command = ATA_CMD_IDLEIMMEDIATE;
+		cmd.tf.command = ATA_CMD_IDLEIMMEDIATE;
 		goto out_do_tf;
 	case IDE_PM_RESTORE_DMA:	/* Resume step 3 (restore DMA) */
 		/*
@@ -163,11 +163,11 @@
 	return ide_stopped;
 
 out_do_tf:
-	cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
-	cmd->valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
-	cmd->protocol = ATA_PROT_NODATA;
+	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
+	cmd.protocol = ATA_PROT_NODATA;
 
-	return do_rw_taskfile(drive, cmd);
+	return do_rw_taskfile(drive, &cmd);
 }
 
 /**
@@ -181,7 +181,7 @@
 void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
 {
 	struct request_queue *q = drive->queue;
-	struct request_pm_state *pm = rq->data;
+	struct request_pm_state *pm = rq->special;
 	unsigned long flags;
 
 	ide_complete_power_step(drive, rq);
@@ -207,7 +207,7 @@
 
 void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
 {
-	struct request_pm_state *pm = rq->data;
+	struct request_pm_state *pm = rq->special;
 
 	if (blk_pm_suspend_request(rq) &&
 	    pm->pm_step == IDE_PM_START_SUSPEND)
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-pnp.c linux-libre-2.6.31-gnu/drivers/ide/ide-pnp.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-pnp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-pnp.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,7 @@
 
 static const struct ide_port_info ide_pnp_port_info = {
 	.host_flags		= IDE_HFLAG_NO_DMA,
+	.chipset		= ide_generic,
 };
 
 static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
@@ -36,7 +37,7 @@
 	struct ide_host *host;
 	unsigned long base, ctl;
 	int rc;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 
 	printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n");
 
@@ -62,9 +63,8 @@
 	memset(&hw, 0, sizeof(hw));
 	ide_std_init_ports(&hw, base, ctl);
 	hw.irq = pnp_irq(dev, 0);
-	hw.chipset = ide_generic;
 
-	rc = ide_host_add(&ide_pnp_port_info, hws, &host);
+	rc = ide_host_add(&ide_pnp_port_info, hws, 1, &host);
 	if (rc)
 		goto out;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-probe.c linux-libre-2.6.31-gnu/drivers/ide/ide-probe.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-probe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-probe.c	2009-09-09 18:13:59.000000000 -0400
@@ -97,7 +97,7 @@
 		drive->mult_req = id[ATA_ID_MULTSECT] & 0xff;
 
 		if (drive->mult_req)
-			drive->special.b.set_multmode = 1;
+			drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
 	}
 }
 
@@ -465,23 +465,8 @@
 	int rc;
 	u8 cmd;
 
-	/*
-	 *	In order to keep things simple we have an id
-	 *	block for all drives at all times. If the device
-	 *	is pre ATA or refuses ATA/ATAPI identify we
-	 *	will add faked data to this.
-	 *
-	 *	Also note that 0 everywhere means "can't do X"
-	 */
- 
 	drive->dev_flags &= ~IDE_DFLAG_ID_READ;
 
-	drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
-	if (drive->id == NULL) {
-		printk(KERN_ERR "ide: out of memory for id data.\n");
-		return 0;
-	}
-
 	m = (char *)&drive->id[ATA_ID_PROD];
 	strcpy(m, "UNKNOWN");
 
@@ -497,7 +482,7 @@
 		}
 
 		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-			goto out_free;
+			return 0;
 
 		/* identification failed? */
 		if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -521,7 +506,7 @@
 	}
 
 	if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-		goto out_free;
+		return 0;
 
 	/* The drive wasn't being helpful. Add generic info only */
 	if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -535,9 +520,6 @@
 	}
 
 	return 1;
-out_free:
-	kfree(drive->id);
-	return 0;
 }
 
 static void hwif_release_dev(struct device *dev)
@@ -553,7 +535,7 @@
 
 	/* register with global device tree */
 	dev_set_name(&hwif->gendev, hwif->name);
-	hwif->gendev.driver_data = hwif;
+	dev_set_drvdata(&hwif->gendev, hwif);
 	if (hwif->gendev.parent == NULL)
 		hwif->gendev.parent = hwif->dev;
 	hwif->gendev.release = hwif_release_dev;
@@ -702,8 +684,14 @@
 	if (irqd)
 		disable_irq(hwif->irq);
 
-	if (ide_port_wait_ready(hwif) == -EBUSY)
-		printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
+	rc = ide_port_wait_ready(hwif);
+	if (rc == -ENODEV) {
+		printk(KERN_INFO "%s: no devices on the port\n", hwif->name);
+		goto out;
+	} else if (rc == -EBUSY)
+		printk(KERN_ERR "%s: not ready before the probe\n", hwif->name);
+	else
+		rc = -ENODEV;
 
 	/*
 	 * Second drive should only exist if first drive was found,
@@ -714,7 +702,7 @@
 		if (drive->dev_flags & IDE_DFLAG_PRESENT)
 			rc = 0;
 	}
-
+out:
 	/*
 	 * Use cached IRQ number. It might be (and is...) changed by probe
 	 * code above
@@ -732,6 +720,8 @@
 	int i;
 
 	ide_port_for_each_present_dev(i, drive, hwif) {
+		ide_check_nien_quirk_list(drive);
+
 		if (port_ops && port_ops->quirkproc)
 			port_ops->quirkproc(drive);
 	}
@@ -817,8 +807,6 @@
 		if (ide_init_queue(drive)) {
 			printk(KERN_ERR "ide: failed to init %s\n",
 					drive->name);
-			kfree(drive->id);
-			drive->id = NULL;
 			drive->dev_flags &= ~IDE_DFLAG_PRESENT;
 			continue;
 		}
@@ -830,6 +818,24 @@
 	return j;
 }
 
+static void ide_host_enable_irqs(struct ide_host *host)
+{
+	ide_hwif_t *hwif;
+	int i;
+
+	ide_host_for_each_port(i, hwif, host) {
+		if (hwif == NULL)
+			continue;
+
+		/* clear any pending IRQs */
+		hwif->tp_ops->read_status(hwif);
+
+		/* unmask IRQs */
+		if (hwif->io_ports.ctl_addr)
+			hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
+	}
+}
+
 /*
  * This routine sets up the IRQ for an IDE interface.
  */
@@ -843,9 +849,6 @@
 	if (irq_handler == NULL)
 		irq_handler = ide_intr;
 
-	if (io_ports->ctl_addr)
-		hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
-
 	if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
 		goto out_up;
 
@@ -947,9 +950,6 @@
 	blk_cleanup_queue(drive->queue);
 	drive->queue = NULL;
 
-	kfree(drive->id);
-	drive->id = NULL;
-
 	drive->dev_flags &= ~IDE_DFLAG_PRESENT;
 
 	complete(&drive->gendev_rel_comp);
@@ -1002,9 +1002,9 @@
 		int ret;
 
 		dev_set_name(dev, "%u.%u", hwif->index, i);
+		dev_set_drvdata(dev, drive);
 		dev->parent = &hwif->gendev;
 		dev->bus = &ide_bus_type;
-		dev->driver_data = drive;
 		dev->release = drive_release_dev;
 
 		ret = device_register(dev);
@@ -1035,6 +1035,15 @@
 		if (port_ops && port_ops->init_dev)
 			port_ops->init_dev(drive);
 	}
+
+	ide_port_for_each_dev(i, drive, hwif) {
+		/*
+		 * default to PIO Mode 0 before we figure out
+		 * the most suited mode for the attached device
+		 */
+		if (port_ops && port_ops->set_pio_mode)
+			port_ops->set_pio_mode(drive, 0);
+	}
 }
 
 static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
@@ -1042,8 +1051,7 @@
 {
 	hwif->channel = port;
 
-	if (d->chipset)
-		hwif->chipset = d->chipset;
+	hwif->chipset = d->chipset ? d->chipset : ide_pci;
 
 	if (d->init_iops)
 		d->init_iops(hwif);
@@ -1124,16 +1132,19 @@
 
 	ide_port_for_each_dev(i, drive, hwif) {
 		u8 j = (hwif->index * MAX_DRIVES) + i;
+		u16 *saved_id = drive->id;
 
 		memset(drive, 0, sizeof(*drive));
+		memset(saved_id, 0, SECTOR_SIZE);
+		drive->id = saved_id;
 
 		drive->media			= ide_disk;
 		drive->select			= (i << 4) | ATA_DEVICE_OBS;
 		drive->hwif			= hwif;
 		drive->ready_stat		= ATA_DRDY;
 		drive->bad_wstat		= BAD_W_STAT;
-		drive->special.b.recalibrate	= 1;
-		drive->special.b.set_geometry	= 1;
+		drive->special_flags		= IDE_SFLAG_RECALIBRATE |
+						  IDE_SFLAG_SET_GEOMETRY;
 		drive->name[0]			= 'h';
 		drive->name[1]			= 'd';
 		drive->name[2]			= 'a' + j;
@@ -1168,14 +1179,12 @@
 	ide_port_init_devices_data(hwif);
 }
 
-static void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
+static void ide_init_port_hw(ide_hwif_t *hwif, struct ide_hw *hw)
 {
 	memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
 	hwif->irq = hw->irq;
-	hwif->chipset = hw->chipset;
 	hwif->dev = hw->dev;
 	hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
-	hwif->ack_intr = hw->ack_intr;
 	hwif->config_data = hw->config;
 }
 
@@ -1233,8 +1242,10 @@
 	ide_drive_t *drive;
 	int i;
 
-	ide_port_for_each_dev(i, drive, hwif)
+	ide_port_for_each_dev(i, drive, hwif) {
+		kfree(drive->id);
 		kfree(drive);
+	}
 }
 
 static int ide_port_alloc_devices(ide_hwif_t *hwif, int node)
@@ -1248,6 +1259,18 @@
 		if (drive == NULL)
 			goto out_nomem;
 
+		/*
+		 * In order to keep things simple we have an id
+		 * block for all drives at all times. If the device
+		 * is pre ATA or refuses ATA/ATAPI identify we
+		 * will add faked data to this.
+		 *
+		 * Also note that 0 everywhere means "can't do X"
+		 */
+		drive->id = kzalloc_node(SECTOR_SIZE, GFP_KERNEL, node);
+		if (drive->id == NULL)
+			goto out_nomem;
+
 		hwif->devices[i] = drive;
 	}
 	return 0;
@@ -1257,7 +1280,8 @@
 	return -ENOMEM;
 }
 
-struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
+struct ide_host *ide_host_alloc(const struct ide_port_info *d,
+				struct ide_hw **hws, unsigned int n_ports)
 {
 	struct ide_host *host;
 	struct device *dev = hws[0] ? hws[0]->dev : NULL;
@@ -1268,7 +1292,7 @@
 	if (host == NULL)
 		return NULL;
 
-	for (i = 0; i < MAX_HOST_PORTS; i++) {
+	for (i = 0; i < n_ports; i++) {
 		ide_hwif_t *hwif;
 		int idx;
 
@@ -1288,6 +1312,7 @@
 		if (idx < 0) {
 			printk(KERN_ERR "%s: no free slot for interface\n",
 					d ? d->name : "ide");
+			ide_port_free_devices(hwif);
 			kfree(hwif);
 			continue;
 		}
@@ -1344,7 +1369,7 @@
 }
 
 int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
-		      hw_regs_t **hws)
+		      struct ide_hw **hws)
 {
 	ide_hwif_t *hwif, *mate = NULL;
 	int i, j = 0;
@@ -1367,6 +1392,9 @@
 
 		ide_init_port(hwif, i & 1, d);
 		ide_port_cable_detect(hwif);
+
+		hwif->port_flags |= IDE_PFLAG_PROBING;
+
 		ide_port_init_devices(hwif);
 	}
 
@@ -1377,6 +1405,8 @@
 		if (ide_probe_port(hwif) == 0)
 			hwif->present = 1;
 
+		hwif->port_flags &= ~IDE_PFLAG_PROBING;
+
 		if ((hwif->host_flags & IDE_HFLAG_4DRIVES) == 0 ||
 		    hwif->mate == NULL || hwif->mate->present == 0) {
 			if (ide_register_port(hwif)) {
@@ -1389,6 +1419,8 @@
 			ide_port_tune_devices(hwif);
 	}
 
+	ide_host_enable_irqs(host);
+
 	ide_host_for_each_port(i, hwif, host) {
 		if (hwif == NULL)
 			continue;
@@ -1438,13 +1470,13 @@
 }
 EXPORT_SYMBOL_GPL(ide_host_register);
 
-int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
-		 struct ide_host **hostp)
+int ide_host_add(const struct ide_port_info *d, struct ide_hw **hws,
+		 unsigned int n_ports, struct ide_host **hostp)
 {
 	struct ide_host *host;
 	int rc;
 
-	host = ide_host_alloc(d, hws);
+	host = ide_host_alloc(d, hws, n_ports);
 	if (host == NULL)
 		return -ENOMEM;
 
@@ -1558,11 +1590,20 @@
 
 void ide_port_scan(ide_hwif_t *hwif)
 {
+	int rc;
+
 	ide_port_apply_params(hwif);
 	ide_port_cable_detect(hwif);
+
+	hwif->port_flags |= IDE_PFLAG_PROBING;
+
 	ide_port_init_devices(hwif);
 
-	if (ide_probe_port(hwif) < 0)
+	rc = ide_probe_port(hwif);
+
+	hwif->port_flags &= ~IDE_PFLAG_PROBING;
+
+	if (rc < 0)
 		return;
 
 	hwif->present = 1;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-tape.c linux-libre-2.6.31-gnu/drivers/ide/ide-tape.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-tape.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-tape.c	2009-09-09 18:13:59.000000000 -0400
@@ -131,13 +131,6 @@
 	IDETAPE_DIR_WRITE = (1 << 2),
 };
 
-struct idetape_bh {
-	u32 b_size;
-	atomic_t b_count;
-	struct idetape_bh *b_reqnext;
-	char *b_data;
-};
-
 /* Tape door status */
 #define DOOR_UNLOCKED			0
 #define DOOR_LOCKED			1
@@ -219,18 +212,12 @@
 
 	/* Data buffer size chosen based on the tape's recommendation */
 	int buffer_size;
-	/* merge buffer */
-	struct idetape_bh *merge_bh;
-	/* size of the merge buffer */
-	int merge_bh_size;
-	/* pointer to current buffer head within the merge buffer */
-	struct idetape_bh *bh;
-	char *b_data;
-	int b_count;
-
-	int pages_per_buffer;
-	/* Wasted space in each stage */
-	int excess_bh_size;
+	/* Staging buffer of buffer_size bytes */
+	void *buf;
+	/* The read/write cursor */
+	void *cur;
+	/* The number of valid bytes in buf */
+	size_t valid;
 
 	/* Measures average tape speed */
 	unsigned long avg_time;
@@ -253,18 +240,27 @@
 
 static void ide_tape_release(struct device *);
 
-static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
+static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
+
+static struct ide_tape_obj *ide_tape_get(struct gendisk *disk, bool cdev,
+					 unsigned int i)
 {
 	struct ide_tape_obj *tape = NULL;
 
 	mutex_lock(&idetape_ref_mutex);
-	tape = ide_drv_g(disk, ide_tape_obj);
+
+	if (cdev)
+		tape = idetape_devs[i];
+	else
+		tape = ide_drv_g(disk, ide_tape_obj);
+
 	if (tape) {
 		if (ide_device_get(tape->drive))
 			tape = NULL;
 		else
 			get_device(&tape->dev);
 	}
+
 	mutex_unlock(&idetape_ref_mutex);
 	return tape;
 }
@@ -280,109 +276,15 @@
 }
 
 /*
- * The variables below are used for the character device interface. Additional
- * state variables are defined in our ide_drive_t structure.
- */
-static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
-
-static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
-{
-	struct ide_tape_obj *tape = NULL;
-
-	mutex_lock(&idetape_ref_mutex);
-	tape = idetape_devs[i];
-	if (tape)
-		get_device(&tape->dev);
-	mutex_unlock(&idetape_ref_mutex);
-	return tape;
-}
-
-static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
-				  unsigned int bcount)
-{
-	struct idetape_bh *bh = pc->bh;
-	int count;
-
-	while (bcount) {
-		if (bh == NULL)
-			break;
-		count = min(
-			(unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
-			bcount);
-		drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
-					atomic_read(&bh->b_count), count);
-		bcount -= count;
-		atomic_add(count, &bh->b_count);
-		if (atomic_read(&bh->b_count) == bh->b_size) {
-			bh = bh->b_reqnext;
-			if (bh)
-				atomic_set(&bh->b_count, 0);
-		}
-	}
-
-	pc->bh = bh;
-
-	return bcount;
-}
-
-static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
-				   unsigned int bcount)
-{
-	struct idetape_bh *bh = pc->bh;
-	int count;
-
-	while (bcount) {
-		if (bh == NULL)
-			break;
-		count = min((unsigned int)pc->b_count, (unsigned int)bcount);
-		drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
-		bcount -= count;
-		pc->b_data += count;
-		pc->b_count -= count;
-		if (!pc->b_count) {
-			bh = bh->b_reqnext;
-			pc->bh = bh;
-			if (bh) {
-				pc->b_data = bh->b_data;
-				pc->b_count = atomic_read(&bh->b_count);
-			}
-		}
-	}
-
-	return bcount;
-}
-
-static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
-	struct idetape_bh *bh = pc->bh;
-	int count;
-	unsigned int bcount = pc->xferred;
-
-	if (pc->flags & PC_FLAG_WRITING)
-		return;
-	while (bcount) {
-		if (bh == NULL) {
-			printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
-					__func__);
-			return;
-		}
-		count = min((unsigned int)bh->b_size, (unsigned int)bcount);
-		atomic_set(&bh->b_count, count);
-		if (atomic_read(&bh->b_count) == bh->b_size)
-			bh = bh->b_reqnext;
-		bcount -= count;
-	}
-	pc->bh = bh;
-}
-
-/*
  * called on each failed packet command retry to analyze the request sense. We
  * currently do not utilize this information.
  */
-static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+static void idetape_analyze_error(ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc *pc = drive->failed_pc;
+	struct request *rq = drive->hwif->rq;
+	u8 *sense = bio_data(rq->bio);
 
 	tape->sense_key = sense[2] & 0xF;
 	tape->asc       = sense[12];
@@ -391,13 +293,9 @@
 	debug_log(DBG_ERR, "pc = %x, sense key = %x, asc = %x, ascq = %x\n",
 		 pc->c[0], tape->sense_key, tape->asc, tape->ascq);
 
-	/* Correct pc->xferred by asking the tape.	 */
-	if (pc->flags & PC_FLAG_DMA_ERROR) {
-		pc->xferred = pc->req_xfer -
-			tape->blk_size *
-			get_unaligned_be32(&sense[3]);
-		idetape_update_buffers(drive, pc);
-	}
+	/* correct remaining bytes to transfer */
+	if (pc->flags & PC_FLAG_DMA_ERROR)
+		rq->resid_len = tape->blk_size * get_unaligned_be32(&sense[3]);
 
 	/*
 	 * If error was the result of a zero-length read or write command,
@@ -431,34 +329,11 @@
 			pc->flags |= PC_FLAG_ABORT;
 		}
 		if (!(pc->flags & PC_FLAG_ABORT) &&
-		    pc->xferred)
+		    (blk_rq_bytes(rq) - rq->resid_len))
 			pc->retries = IDETAPE_MAX_PC_RETRIES + 1;
 	}
 }
 
-/* Free data buffers completely. */
-static void ide_tape_kfree_buffer(idetape_tape_t *tape)
-{
-	struct idetape_bh *prev_bh, *bh = tape->merge_bh;
-
-	while (bh) {
-		u32 size = bh->b_size;
-
-		while (size) {
-			unsigned int order = fls(size >> PAGE_SHIFT)-1;
-
-			if (bh->b_data)
-				free_pages((unsigned long)bh->b_data, order);
-
-			size &= (order-1);
-			bh->b_data += (1 << order) * PAGE_SIZE;
-		}
-		prev_bh = bh;
-		bh = bh->b_reqnext;
-		kfree(prev_bh);
-	}
-}
-
 static void ide_tape_handle_dsc(ide_drive_t *);
 
 static int ide_tape_callback(ide_drive_t *drive, int dsc)
@@ -479,12 +354,13 @@
 
 	if (pc->c[0] == REQUEST_SENSE) {
 		if (uptodate)
-			idetape_analyze_error(drive, pc->buf);
+			idetape_analyze_error(drive);
 		else
 			printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
 					"itself - Aborting request!\n");
 	} else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
-		int blocks = pc->xferred / tape->blk_size;
+		unsigned int blocks =
+			(blk_rq_bytes(rq) - rq->resid_len) / tape->blk_size;
 
 		tape->avg_size += blocks * tape->blk_size;
 
@@ -496,36 +372,12 @@
 		}
 
 		tape->first_frame += blocks;
-		rq->current_nr_sectors -= blocks;
 
 		if (pc->error) {
 			uptodate = 0;
 			err = pc->error;
 		}
-	} else if (pc->c[0] == READ_POSITION && uptodate) {
-		u8 *readpos = pc->buf;
-
-		debug_log(DBG_SENSE, "BOP - %s\n",
-				(readpos[0] & 0x80) ? "Yes" : "No");
-		debug_log(DBG_SENSE, "EOP - %s\n",
-				(readpos[0] & 0x40) ? "Yes" : "No");
-
-		if (readpos[0] & 0x4) {
-			printk(KERN_INFO "ide-tape: Block location is unknown"
-					 "to the tape\n");
-			clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
-			uptodate = 0;
-			err = IDE_DRV_ERROR_GENERAL;
-		} else {
-			debug_log(DBG_SENSE, "Block Location - %u\n",
-					be32_to_cpup((__be32 *)&readpos[4]));
-
-			tape->partition = readpos[1];
-			tape->first_frame = be32_to_cpup((__be32 *)&readpos[4]);
-			set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
-		}
 	}
-
 	rq->errors = err;
 
 	return uptodate;
@@ -558,19 +410,6 @@
 	idetape_postpone_request(drive);
 }
 
-static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
-				unsigned int bcount, int write)
-{
-	unsigned int bleft;
-
-	if (write)
-		bleft = idetape_output_buffers(drive, pc, bcount);
-	else
-		bleft = idetape_input_buffers(drive, pc, bcount);
-
-	return bcount - bleft;
-}
-
 /*
  * Packet Command Interface
  *
@@ -613,6 +452,7 @@
 					 struct ide_atapi_pc *pc)
 {
 	idetape_tape_t *tape = drive->driver_data;
+	struct request *rq = drive->hwif->rq;
 
 	if (drive->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
 		drive->failed_pc = pc;
@@ -622,6 +462,7 @@
 
 	if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
 		(pc->flags & PC_FLAG_ABORT)) {
+
 		/*
 		 * We will "abort" retrying a packet command in case legitimate
 		 * error code was received (crossing a filemark, or end of the
@@ -641,8 +482,10 @@
 			/* Giving up */
 			pc->error = IDE_DRV_ERROR_GENERAL;
 		}
+
 		drive->failed_pc = NULL;
 		drive->pc_callback(drive, 0);
+		ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
 		return ide_stopped;
 	}
 	debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
@@ -695,7 +538,7 @@
 				printk(KERN_ERR "ide-tape: %s: I/O error, ",
 						tape->name);
 			/* Retry operation */
-			ide_retry_pc(drive, tape->disk);
+			ide_retry_pc(drive);
 			return ide_stopped;
 		}
 		pc->error = 0;
@@ -711,27 +554,20 @@
 				   struct ide_atapi_pc *pc, struct request *rq,
 				   u8 opcode)
 {
-	struct idetape_bh *bh = (struct idetape_bh *)rq->special;
-	unsigned int length = rq->current_nr_sectors;
+	unsigned int length = blk_rq_sectors(rq) / (tape->blk_size >> 9);
 
 	ide_init_pc(pc);
 	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
 	pc->c[1] = 1;
-	pc->bh = bh;
-	pc->buf = NULL;
-	pc->buf_size = length * tape->blk_size;
-	pc->req_xfer = pc->buf_size;
-	if (pc->req_xfer == tape->buffer_size)
+
+	if (blk_rq_bytes(rq) == tape->buffer_size)
 		pc->flags |= PC_FLAG_DMA_OK;
 
-	if (opcode == READ_6) {
+	if (opcode == READ_6)
 		pc->c[0] = READ_6;
-		atomic_set(&bh->b_count, 0);
-	} else if (opcode == WRITE_6) {
+	else if (opcode == WRITE_6) {
 		pc->c[0] = WRITE_6;
 		pc->flags |= PC_FLAG_WRITING;
-		pc->b_data = bh->b_data;
-		pc->b_count = atomic_read(&bh->b_count);
 	}
 
 	memcpy(rq->cmd, pc->c, 12);
@@ -747,20 +583,10 @@
 	struct ide_cmd cmd;
 	u8 stat;
 
-	debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu,"
-			" current_nr_sectors: %u\n",
-			(unsigned long long)rq->sector, rq->nr_sectors,
-			rq->current_nr_sectors);
+	debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %u\n"
+		  (unsigned long long)blk_rq_pos(rq), blk_rq_sectors(rq));
 
-	if (!blk_special_request(rq)) {
-		/* We do not support buffer cache originated requests. */
-		printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
-			"request queue (%d)\n", drive->name, rq->cmd_type);
-		if (blk_fs_request(rq) == 0 && rq->errors == 0)
-			rq->errors = -EIO;
-		ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
-		return ide_stopped;
-	}
+	BUG_ON(!(blk_special_request(rq) || blk_sense_request(rq)));
 
 	/* Retry a failed packet command */
 	if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
@@ -788,15 +614,15 @@
 
 	if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
 	    (rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
-		set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
+		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
 
 	if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
-		set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
+		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
 		drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
 	}
 
-	if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
-	    (stat & ATA_DSC) == 0) {
+	if (!(drive->atapi_flags & IDE_AFLAG_IGNORE_DSC) &&
+	    !(stat & ATA_DSC)) {
 		if (postponed_rq == NULL) {
 			tape->dsc_polling_start = jiffies;
 			tape->dsc_poll_freq = tape->best_dsc_rw_freq;
@@ -816,7 +642,9 @@
 			tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW;
 		idetape_postpone_request(drive);
 		return ide_stopped;
-	}
+	} else
+		drive->atapi_flags &= ~IDE_AFLAG_IGNORE_DSC;
+
 	if (rq->cmd[13] & REQ_IDETAPE_READ) {
 		pc = &tape->queued_pc;
 		ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
@@ -828,7 +656,7 @@
 		goto out;
 	}
 	if (rq->cmd[13] & REQ_IDETAPE_PC1) {
-		pc = (struct ide_atapi_pc *) rq->buffer;
+		pc = (struct ide_atapi_pc *)rq->special;
 		rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
 		rq->cmd[13] |= REQ_IDETAPE_PC2;
 		goto out;
@@ -840,6 +668,9 @@
 	BUG();
 
 out:
+	/* prepare sense request for this command */
+	ide_prep_sense(drive, rq);
+
 	memset(&cmd, 0, sizeof(cmd));
 
 	if (rq_data_dir(rq))
@@ -847,167 +678,10 @@
 
 	cmd.rq = rq;
 
-	return ide_tape_issue_pc(drive, &cmd, pc);
-}
-
-/*
- * The function below uses __get_free_pages to allocate a data buffer of size
- * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
- * much as possible.
- *
- * It returns a pointer to the newly allocated buffer, or NULL in case of
- * failure.
- */
-static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape,
-						  int full, int clear)
-{
-	struct idetape_bh *prev_bh, *bh, *merge_bh;
-	int pages = tape->pages_per_buffer;
-	unsigned int order, b_allocd;
-	char *b_data = NULL;
-
-	merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
-	bh = merge_bh;
-	if (bh == NULL)
-		goto abort;
-
-	order = fls(pages) - 1;
-	bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order);
-	if (!bh->b_data)
-		goto abort;
-	b_allocd = (1 << order) * PAGE_SIZE;
-	pages &= (order-1);
-
-	if (clear)
-		memset(bh->b_data, 0, b_allocd);
-	bh->b_reqnext = NULL;
-	bh->b_size = b_allocd;
-	atomic_set(&bh->b_count, full ? bh->b_size : 0);
-
-	while (pages) {
-		order = fls(pages) - 1;
-		b_data = (char *) __get_free_pages(GFP_KERNEL, order);
-		if (!b_data)
-			goto abort;
-		b_allocd = (1 << order) * PAGE_SIZE;
-
-		if (clear)
-			memset(b_data, 0, b_allocd);
-
-		/* newly allocated page frames below buffer header or ...*/
-		if (bh->b_data == b_data + b_allocd) {
-			bh->b_size += b_allocd;
-			bh->b_data -= b_allocd;
-			if (full)
-				atomic_add(b_allocd, &bh->b_count);
-			continue;
-		}
-		/* they are above the header */
-		if (b_data == bh->b_data + bh->b_size) {
-			bh->b_size += b_allocd;
-			if (full)
-				atomic_add(b_allocd, &bh->b_count);
-			continue;
-		}
-		prev_bh = bh;
-		bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
-		if (!bh) {
-			free_pages((unsigned long) b_data, order);
-			goto abort;
-		}
-		bh->b_reqnext = NULL;
-		bh->b_data = b_data;
-		bh->b_size = b_allocd;
-		atomic_set(&bh->b_count, full ? bh->b_size : 0);
-		prev_bh->b_reqnext = bh;
-
-		pages &= (order-1);
-	}
-
-	bh->b_size -= tape->excess_bh_size;
-	if (full)
-		atomic_sub(tape->excess_bh_size, &bh->b_count);
-	return merge_bh;
-abort:
-	ide_tape_kfree_buffer(tape);
-	return NULL;
-}
-
-static int idetape_copy_stage_from_user(idetape_tape_t *tape,
-					const char __user *buf, int n)
-{
-	struct idetape_bh *bh = tape->bh;
-	int count;
-	int ret = 0;
-
-	while (n) {
-		if (bh == NULL) {
-			printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
-					__func__);
-			return 1;
-		}
-		count = min((unsigned int)
-				(bh->b_size - atomic_read(&bh->b_count)),
-				(unsigned int)n);
-		if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf,
-				count))
-			ret = 1;
-		n -= count;
-		atomic_add(count, &bh->b_count);
-		buf += count;
-		if (atomic_read(&bh->b_count) == bh->b_size) {
-			bh = bh->b_reqnext;
-			if (bh)
-				atomic_set(&bh->b_count, 0);
-		}
-	}
-	tape->bh = bh;
-	return ret;
-}
-
-static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
-				      int n)
-{
-	struct idetape_bh *bh = tape->bh;
-	int count;
-	int ret = 0;
-
-	while (n) {
-		if (bh == NULL) {
-			printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
-					__func__);
-			return 1;
-		}
-		count = min(tape->b_count, n);
-		if  (copy_to_user(buf, tape->b_data, count))
-			ret = 1;
-		n -= count;
-		tape->b_data += count;
-		tape->b_count -= count;
-		buf += count;
-		if (!tape->b_count) {
-			bh = bh->b_reqnext;
-			tape->bh = bh;
-			if (bh) {
-				tape->b_data = bh->b_data;
-				tape->b_count = atomic_read(&bh->b_count);
-			}
-		}
-	}
-	return ret;
-}
-
-static void idetape_init_merge_buffer(idetape_tape_t *tape)
-{
-	struct idetape_bh *bh = tape->merge_bh;
-	tape->bh = tape->merge_bh;
+	ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
+	ide_map_sg(drive, &cmd);
 
-	if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
-		atomic_set(&bh->b_count, 0);
-	else {
-		tape->b_data = bh->b_data;
-		tape->b_count = atomic_read(&bh->b_count);
-	}
+	return ide_tape_issue_pc(drive, &cmd, pc);
 }
 
 /*
@@ -1030,7 +704,7 @@
 	int load_attempted = 0;
 
 	/* Wait for the tape to become ready */
-	set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
+	set_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), &drive->atapi_flags);
 	timeout += jiffies;
 	while (time_before(jiffies, timeout)) {
 		if (ide_do_test_unit_ready(drive, disk) == 0)
@@ -1058,33 +732,53 @@
 	int rc;
 
 	idetape_create_write_filemark_cmd(drive, &pc, 0);
-	rc = ide_queue_pc_tail(drive, tape->disk, &pc);
+	rc = ide_queue_pc_tail(drive, tape->disk, &pc, NULL, 0);
 	if (rc)
 		return rc;
 	idetape_wait_ready(drive, 60 * 5 * HZ);
 	return 0;
 }
 
-static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc)
-{
-	ide_init_pc(pc);
-	pc->c[0] = READ_POSITION;
-	pc->req_xfer = 20;
-}
-
-static int idetape_read_position(ide_drive_t *drive)
+static int ide_tape_read_position(ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc pc;
-	int position;
+	u8 buf[20];
 
 	debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
-	idetape_create_read_position_cmd(&pc);
-	if (ide_queue_pc_tail(drive, tape->disk, &pc))
+	/* prep cmd */
+	ide_init_pc(&pc);
+	pc.c[0] = READ_POSITION;
+	pc.req_xfer = 20;
+
+	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer))
 		return -1;
-	position = tape->first_frame;
-	return position;
+
+	if (!pc.error) {
+		debug_log(DBG_SENSE, "BOP - %s\n",
+				(buf[0] & 0x80) ? "Yes" : "No");
+		debug_log(DBG_SENSE, "EOP - %s\n",
+				(buf[0] & 0x40) ? "Yes" : "No");
+
+		if (buf[0] & 0x4) {
+			printk(KERN_INFO "ide-tape: Block location is unknown"
+					 "to the tape\n");
+			clear_bit(ilog2(IDE_AFLAG_ADDRESS_VALID),
+				  &drive->atapi_flags);
+			return -1;
+		} else {
+			debug_log(DBG_SENSE, "Block Location - %u\n",
+					be32_to_cpup((__be32 *)&buf[4]));
+
+			tape->partition = buf[1];
+			tape->first_frame = be32_to_cpup((__be32 *)&buf[4]);
+			set_bit(ilog2(IDE_AFLAG_ADDRESS_VALID),
+				&drive->atapi_flags);
+		}
+	}
+
+	return tape->first_frame;
 }
 
 static void idetape_create_locate_cmd(ide_drive_t *drive,
@@ -1106,11 +800,11 @@
 	if (tape->chrdev_dir != IDETAPE_DIR_READ)
 		return;
 
-	clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags);
-	tape->merge_bh_size = 0;
-	if (tape->merge_bh != NULL) {
-		ide_tape_kfree_buffer(tape);
-		tape->merge_bh = NULL;
+	clear_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags);
+	tape->valid = 0;
+	if (tape->buf != NULL) {
+		kfree(tape->buf);
+		tape->buf = NULL;
 	}
 
 	tape->chrdev_dir = IDETAPE_DIR_NONE;
@@ -1127,19 +821,21 @@
 {
 	idetape_tape_t *tape = drive->driver_data;
 	struct gendisk *disk = tape->disk;
-	int retval;
+	int ret;
 	struct ide_atapi_pc pc;
 
 	if (tape->chrdev_dir == IDETAPE_DIR_READ)
 		__ide_tape_discard_merge_buffer(drive);
 	idetape_wait_ready(drive, 60 * 5 * HZ);
 	idetape_create_locate_cmd(drive, &pc, block, partition, skip);
-	retval = ide_queue_pc_tail(drive, disk, &pc);
-	if (retval)
-		return (retval);
+	ret = ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
+	if (ret)
+		return ret;
 
-	idetape_create_read_position_cmd(&pc);
-	return ide_queue_pc_tail(drive, disk, &pc);
+	ret = ide_tape_read_position(drive);
+	if (ret < 0)
+		return ret;
+	return 0;
 }
 
 static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
@@ -1150,7 +846,7 @@
 
 	__ide_tape_discard_merge_buffer(drive);
 	if (restore_position) {
-		position = idetape_read_position(drive);
+		position = ide_tape_read_position(drive);
 		seek = position > 0 ? position : 0;
 		if (idetape_position_tape(drive, seek, 0, 0)) {
 			printk(KERN_INFO "ide-tape: %s: position_tape failed in"
@@ -1164,36 +860,44 @@
  * Generate a read/write request for the block device interface and wait for it
  * to be serviced.
  */
-static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
-				 struct idetape_bh *bh)
+static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	struct request *rq;
-	int ret, errors;
+	int ret;
 
 	debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
+	BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE);
+	BUG_ON(size < 0 || size % tape->blk_size);
 
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->cmd[13] = cmd;
 	rq->rq_disk = tape->disk;
-	rq->special = (void *)bh;
-	rq->sector = tape->first_frame;
-	rq->nr_sectors = blocks;
-	rq->current_nr_sectors = blocks;
-	blk_execute_rq(drive->queue, tape->disk, rq, 0);
+	rq->__sector = tape->first_frame;
 
-	errors = rq->errors;
-	ret = tape->blk_size * (blocks - rq->current_nr_sectors);
-	blk_put_request(rq);
+	if (size) {
+		ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size,
+				      __GFP_WAIT);
+		if (ret)
+			goto out_put;
+	}
 
-	if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
-		return 0;
+	blk_execute_rq(drive->queue, tape->disk, rq, 0);
 
-	if (tape->merge_bh)
-		idetape_init_merge_buffer(tape);
-	if (errors == IDE_DRV_ERROR_GENERAL)
-		return -EIO;
+	/* calculate the number of transferred bytes and update buffer state */
+	size -= rq->resid_len;
+	tape->cur = tape->buf;
+	if (cmd == REQ_IDETAPE_READ)
+		tape->valid = size;
+	else
+		tape->valid = 0;
+
+	ret = size;
+	if (rq->errors == IDE_DRV_ERROR_GENERAL)
+		ret = -EIO;
+out_put:
+	blk_put_request(rq);
 	return ret;
 }
 
@@ -1230,153 +934,87 @@
 	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
 }
 
-/* Queue up a character device originated write request. */
-static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
-{
-	idetape_tape_t *tape = drive->driver_data;
-
-	debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
-
-	return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
-				     blocks, tape->merge_bh);
-}
-
 static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
-	int blocks, min;
-	struct idetape_bh *bh;
 
 	if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
 		printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
 				" but we are not writing.\n");
 		return;
 	}
-	if (tape->merge_bh_size > tape->buffer_size) {
-		printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
-		tape->merge_bh_size = tape->buffer_size;
-	}
-	if (tape->merge_bh_size) {
-		blocks = tape->merge_bh_size / tape->blk_size;
-		if (tape->merge_bh_size % tape->blk_size) {
-			unsigned int i;
+	if (tape->buf) {
+		size_t aligned = roundup(tape->valid, tape->blk_size);
 
-			blocks++;
-			i = tape->blk_size - tape->merge_bh_size %
-				tape->blk_size;
-			bh = tape->bh->b_reqnext;
-			while (bh) {
-				atomic_set(&bh->b_count, 0);
-				bh = bh->b_reqnext;
-			}
-			bh = tape->bh;
-			while (i) {
-				if (bh == NULL) {
-					printk(KERN_INFO "ide-tape: bug,"
-							 " bh NULL\n");
-					break;
-				}
-				min = min(i, (unsigned int)(bh->b_size -
-						atomic_read(&bh->b_count)));
-				memset(bh->b_data + atomic_read(&bh->b_count),
-						0, min);
-				atomic_add(min, &bh->b_count);
-				i -= min;
-				bh = bh->b_reqnext;
-			}
-		}
-		(void) idetape_add_chrdev_write_request(drive, blocks);
-		tape->merge_bh_size = 0;
-	}
-	if (tape->merge_bh != NULL) {
-		ide_tape_kfree_buffer(tape);
-		tape->merge_bh = NULL;
+		memset(tape->cur, 0, aligned - tape->valid);
+		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned);
+		kfree(tape->buf);
+		tape->buf = NULL;
 	}
 	tape->chrdev_dir = IDETAPE_DIR_NONE;
 }
 
-static int idetape_init_read(ide_drive_t *drive)
+static int idetape_init_rw(ide_drive_t *drive, int dir)
 {
 	idetape_tape_t *tape = drive->driver_data;
-	int bytes_read;
+	int rc;
 
-	/* Initialize read operation */
-	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
-		if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
-			ide_tape_flush_merge_buffer(drive);
-			idetape_flush_tape_buffers(drive);
-		}
-		if (tape->merge_bh || tape->merge_bh_size) {
-			printk(KERN_ERR "ide-tape: merge_bh_size should be"
-					 " 0 now\n");
-			tape->merge_bh_size = 0;
-		}
-		tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
-		if (!tape->merge_bh)
-			return -ENOMEM;
-		tape->chrdev_dir = IDETAPE_DIR_READ;
+	BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE);
 
-		/*
-		 * Issue a read 0 command to ensure that DSC handshake is
-		 * switched from completion mode to buffer available mode.
-		 * No point in issuing this if DSC overlap isn't supported, some
-		 * drives (Seagate STT3401A) will return an error.
-		 */
-		if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
-			bytes_read = idetape_queue_rw_tail(drive,
-							REQ_IDETAPE_READ, 0,
-							tape->merge_bh);
-			if (bytes_read < 0) {
-				ide_tape_kfree_buffer(tape);
-				tape->merge_bh = NULL;
-				tape->chrdev_dir = IDETAPE_DIR_NONE;
-				return bytes_read;
-			}
-		}
-	}
+	if (tape->chrdev_dir == dir)
+		return 0;
 
-	return 0;
-}
+	if (tape->chrdev_dir == IDETAPE_DIR_READ)
+		ide_tape_discard_merge_buffer(drive, 1);
+	else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+		ide_tape_flush_merge_buffer(drive);
+		idetape_flush_tape_buffers(drive);
+	}
 
-/* called from idetape_chrdev_read() to service a chrdev read request. */
-static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
-{
-	idetape_tape_t *tape = drive->driver_data;
+	if (tape->buf || tape->valid) {
+		printk(KERN_ERR "ide-tape: valid should be 0 now\n");
+		tape->valid = 0;
+	}
 
-	debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
+	tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
+	if (!tape->buf)
+		return -ENOMEM;
+	tape->chrdev_dir = dir;
+	tape->cur = tape->buf;
 
-	/* If we are at a filemark, return a read length of 0 */
-	if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
-		return 0;
+	/*
+	 * Issue a 0 rw command to ensure that DSC handshake is
+	 * switched from completion mode to buffer available mode.  No
+	 * point in issuing this if DSC overlap isn't supported, some
+	 * drives (Seagate STT3401A) will return an error.
+	 */
+	if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
+		int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ
+						  : REQ_IDETAPE_WRITE;
 
-	idetape_init_read(drive);
+		rc = idetape_queue_rw_tail(drive, cmd, 0);
+		if (rc < 0) {
+			kfree(tape->buf);
+			tape->buf = NULL;
+			tape->chrdev_dir = IDETAPE_DIR_NONE;
+			return rc;
+		}
+	}
 
-	return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
-				     tape->merge_bh);
+	return 0;
 }
 
 static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
 {
 	idetape_tape_t *tape = drive->driver_data;
-	struct idetape_bh *bh;
-	int blocks;
+
+	memset(tape->buf, 0, tape->buffer_size);
 
 	while (bcount) {
-		unsigned int count;
+		unsigned int count = min(tape->buffer_size, bcount);
 
-		bh = tape->merge_bh;
-		count = min(tape->buffer_size, bcount);
+		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, count);
 		bcount -= count;
-		blocks = count / tape->blk_size;
-		while (count) {
-			atomic_set(&bh->b_count,
-				   min(count, (unsigned int)bh->b_size));
-			memset(bh->b_data, 0, atomic_read(&bh->b_count));
-			count -= atomic_read(&bh->b_count);
-			bh = bh->b_reqnext;
-		}
-		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
-				      tape->merge_bh);
 	}
 }
 
@@ -1388,20 +1026,19 @@
 {
 	struct ide_tape_obj *tape = drive->driver_data;
 	struct gendisk *disk = tape->disk;
-	int retval;
 	struct ide_atapi_pc pc;
+	int ret;
 
 	debug_log(DBG_SENSE, "Enter %s\n", __func__);
 
 	idetape_create_rewind_cmd(drive, &pc);
-	retval = ide_queue_pc_tail(drive, disk, &pc);
-	if (retval)
-		return retval;
+	ret = ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
+	if (ret)
+		return ret;
 
-	idetape_create_read_position_cmd(&pc);
-	retval = ide_queue_pc_tail(drive, disk, &pc);
-	if (retval)
-		return retval;
+	ret = ide_tape_read_position(drive);
+	if (ret < 0)
+		return ret;
 	return 0;
 }
 
@@ -1427,6 +1064,7 @@
 		tape->best_dsc_rw_freq = config.dsc_rw_frequency;
 		break;
 	case 0x0350:
+		memset(&config, 0, sizeof(config));
 		config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
 		config.nr_stages = 1;
 		if (copy_to_user(argp, &config, sizeof(config)))
@@ -1456,8 +1094,9 @@
 	}
 
 	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
-		tape->merge_bh_size = 0;
-		if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
+		tape->valid = 0;
+		if (test_and_clear_bit(ilog2(IDE_AFLAG_FILEMARK),
+				       &drive->atapi_flags))
 			++count;
 		ide_tape_discard_merge_buffer(drive, 0);
 	}
@@ -1467,7 +1106,7 @@
 	case MTBSF:
 		idetape_create_space_cmd(&pc, mt_count - count,
 					 IDETAPE_SPACE_OVER_FILEMARK);
-		return ide_queue_pc_tail(drive, disk, &pc);
+		return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
 	case MTFSFM:
 	case MTBSFM:
 		if (!sprev)
@@ -1505,61 +1144,56 @@
 {
 	struct ide_tape_obj *tape = file->private_data;
 	ide_drive_t *drive = tape->drive;
-	ssize_t bytes_read, temp, actually_read = 0, rc;
+	size_t done = 0;
 	ssize_t ret = 0;
-	u16 ctl = *(u16 *)&tape->caps[12];
+	int rc;
 
 	debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
 
 	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
-		if (test_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags))
+		if (test_bit(ilog2(IDE_AFLAG_DETECT_BS), &drive->atapi_flags))
 			if (count > tape->blk_size &&
 			    (count % tape->blk_size) == 0)
 				tape->user_bs_factor = count / tape->blk_size;
 	}
-	rc = idetape_init_read(drive);
+
+	rc = idetape_init_rw(drive, IDETAPE_DIR_READ);
 	if (rc < 0)
 		return rc;
-	if (count == 0)
-		return (0);
-	if (tape->merge_bh_size) {
-		actually_read = min((unsigned int)(tape->merge_bh_size),
-				    (unsigned int)count);
-		if (idetape_copy_stage_to_user(tape, buf, actually_read))
-			ret = -EFAULT;
-		buf += actually_read;
-		tape->merge_bh_size -= actually_read;
-		count -= actually_read;
-	}
-	while (count >= tape->buffer_size) {
-		bytes_read = idetape_add_chrdev_read_request(drive, ctl);
-		if (bytes_read <= 0)
-			goto finish;
-		if (idetape_copy_stage_to_user(tape, buf, bytes_read))
-			ret = -EFAULT;
-		buf += bytes_read;
-		count -= bytes_read;
-		actually_read += bytes_read;
-	}
-	if (count) {
-		bytes_read = idetape_add_chrdev_read_request(drive, ctl);
-		if (bytes_read <= 0)
-			goto finish;
-		temp = min((unsigned long)count, (unsigned long)bytes_read);
-		if (idetape_copy_stage_to_user(tape, buf, temp))
+
+	while (done < count) {
+		size_t todo;
+
+		/* refill if staging buffer is empty */
+		if (!tape->valid) {
+			/* If we are at a filemark, nothing more to read */
+			if (test_bit(ilog2(IDE_AFLAG_FILEMARK),
+				     &drive->atapi_flags))
+				break;
+			/* read */
+			if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ,
+						  tape->buffer_size) <= 0)
+				break;
+		}
+
+		/* copy out */
+		todo = min_t(size_t, count - done, tape->valid);
+		if (copy_to_user(buf + done, tape->cur, todo))
 			ret = -EFAULT;
-		actually_read += temp;
-		tape->merge_bh_size = bytes_read-temp;
+
+		tape->cur += todo;
+		tape->valid -= todo;
+		done += todo;
 	}
-finish:
-	if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
+
+	if (!done && test_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags)) {
 		debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
 
 		idetape_space_over_filemarks(drive, MTFSF, 1);
 		return 0;
 	}
 
-	return ret ? ret : actually_read;
+	return ret ? ret : done;
 }
 
 static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
@@ -1567,9 +1201,9 @@
 {
 	struct ide_tape_obj *tape = file->private_data;
 	ide_drive_t *drive = tape->drive;
-	ssize_t actually_written = 0;
+	size_t done = 0;
 	ssize_t ret = 0;
-	u16 ctl = *(u16 *)&tape->caps[12];
+	int rc;
 
 	/* The drive is write protected. */
 	if (tape->write_prot)
@@ -1578,80 +1212,31 @@
 	debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
 
 	/* Initialize write operation */
-	if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
-		if (tape->chrdev_dir == IDETAPE_DIR_READ)
-			ide_tape_discard_merge_buffer(drive, 1);
-		if (tape->merge_bh || tape->merge_bh_size) {
-			printk(KERN_ERR "ide-tape: merge_bh_size "
-				"should be 0 now\n");
-			tape->merge_bh_size = 0;
-		}
-		tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
-		if (!tape->merge_bh)
-			return -ENOMEM;
-		tape->chrdev_dir = IDETAPE_DIR_WRITE;
-		idetape_init_merge_buffer(tape);
+	rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE);
+	if (rc < 0)
+		return rc;
 
-		/*
-		 * Issue a write 0 command to ensure that DSC handshake is
-		 * switched from completion mode to buffer available mode. No
-		 * point in issuing this if DSC overlap isn't supported, some
-		 * drives (Seagate STT3401A) will return an error.
-		 */
-		if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
-			ssize_t retval = idetape_queue_rw_tail(drive,
-							REQ_IDETAPE_WRITE, 0,
-							tape->merge_bh);
-			if (retval < 0) {
-				ide_tape_kfree_buffer(tape);
-				tape->merge_bh = NULL;
-				tape->chrdev_dir = IDETAPE_DIR_NONE;
-				return retval;
-			}
-		}
-	}
-	if (count == 0)
-		return (0);
-	if (tape->merge_bh_size) {
-		if (tape->merge_bh_size >= tape->buffer_size) {
-			printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
-			tape->merge_bh_size = 0;
-		}
-		actually_written = min((unsigned int)
-				(tape->buffer_size - tape->merge_bh_size),
-				(unsigned int)count);
-		if (idetape_copy_stage_from_user(tape, buf, actually_written))
-				ret = -EFAULT;
-		buf += actually_written;
-		tape->merge_bh_size += actually_written;
-		count -= actually_written;
+	while (done < count) {
+		size_t todo;
 
-		if (tape->merge_bh_size == tape->buffer_size) {
-			ssize_t retval;
-			tape->merge_bh_size = 0;
-			retval = idetape_add_chrdev_write_request(drive, ctl);
-			if (retval <= 0)
-				return (retval);
-		}
-	}
-	while (count >= tape->buffer_size) {
-		ssize_t retval;
-		if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size))
-			ret = -EFAULT;
-		buf += tape->buffer_size;
-		count -= tape->buffer_size;
-		retval = idetape_add_chrdev_write_request(drive, ctl);
-		actually_written += tape->buffer_size;
-		if (retval <= 0)
-			return (retval);
-	}
-	if (count) {
-		actually_written += count;
-		if (idetape_copy_stage_from_user(tape, buf, count))
+		/* flush if staging buffer is full */
+		if (tape->valid == tape->buffer_size &&
+		    idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
+					  tape->buffer_size) <= 0)
+			return rc;
+
+		/* copy in */
+		todo = min_t(size_t, count - done,
+			     tape->buffer_size - tape->valid);
+		if (copy_from_user(tape->cur, buf + done, todo))
 			ret = -EFAULT;
-		tape->merge_bh_size += count;
+
+		tape->cur += todo;
+		tape->valid += todo;
+		done += todo;
 	}
-	return ret ? ret : actually_written;
+
+	return ret ? ret : done;
 }
 
 static int idetape_write_filemark(ide_drive_t *drive)
@@ -1661,7 +1246,7 @@
 
 	/* Write a filemark */
 	idetape_create_write_filemark_cmd(drive, &pc, 1);
-	if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
+	if (ide_queue_pc_tail(drive, tape->disk, &pc, NULL, 0)) {
 		printk(KERN_ERR "ide-tape: Couldn't write a filemark\n");
 		return -EIO;
 	}
@@ -1735,7 +1320,8 @@
 		ide_tape_discard_merge_buffer(drive, 0);
 		retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK);
 		if (!retval)
-			clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
+			clear_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT),
+				  &drive->atapi_flags);
 		return retval;
 	case MTNOP:
 		ide_tape_discard_merge_buffer(drive, 0);
@@ -1746,20 +1332,22 @@
 			IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
 	case MTEOM:
 		idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
-		return ide_queue_pc_tail(drive, disk, &pc);
+		return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
 	case MTERASE:
 		(void)idetape_rewind_tape(drive);
 		idetape_create_erase_cmd(&pc);
-		return ide_queue_pc_tail(drive, disk, &pc);
+		return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
 	case MTSETBLK:
 		if (mt_count) {
 			if (mt_count < tape->blk_size ||
 			    mt_count % tape->blk_size)
 				return -EIO;
 			tape->user_bs_factor = mt_count / tape->blk_size;
-			clear_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
+			clear_bit(ilog2(IDE_AFLAG_DETECT_BS),
+				  &drive->atapi_flags);
 		} else
-			set_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
+			set_bit(ilog2(IDE_AFLAG_DETECT_BS),
+				&drive->atapi_flags);
 		return 0;
 	case MTSEEK:
 		ide_tape_discard_merge_buffer(drive, 0);
@@ -1812,9 +1400,9 @@
 		idetape_flush_tape_buffers(drive);
 	}
 	if (cmd == MTIOCGET || cmd == MTIOCPOS) {
-		block_offset = tape->merge_bh_size /
+		block_offset = tape->valid /
 			(tape->blk_size * tape->user_bs_factor);
-		position = idetape_read_position(drive);
+		position = ide_tape_read_position(drive);
 		if (position < 0)
 			return -EIO;
 	}
@@ -1857,9 +1445,10 @@
 {
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc pc;
+	u8 buf[12];
 
 	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
-	if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
+	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer)) {
 		printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
 		if (tape->blk_size == 0) {
 			printk(KERN_WARNING "ide-tape: Cannot deal with zero "
@@ -1868,10 +1457,10 @@
 		}
 		return;
 	}
-	tape->blk_size = (pc.buf[4 + 5] << 16) +
-				(pc.buf[4 + 6] << 8)  +
-				 pc.buf[4 + 7];
-	tape->drv_write_prot = (pc.buf[2] & 0x80) >> 7;
+	tape->blk_size = (buf[4 + 5] << 16) +
+				(buf[4 + 6] << 8)  +
+				 buf[4 + 7];
+	tape->drv_write_prot = (buf[2] & 0x80) >> 7;
 }
 
 static int idetape_chrdev_open(struct inode *inode, struct file *filp)
@@ -1885,7 +1474,7 @@
 		return -ENXIO;
 
 	lock_kernel();
-	tape = ide_tape_chrdev_get(i);
+	tape = ide_tape_get(NULL, true, i);
 	if (!tape) {
 		unlock_kernel();
 		return -ENXIO;
@@ -1904,20 +1493,20 @@
 
 	filp->private_data = tape;
 
-	if (test_and_set_bit(IDE_AFLAG_BUSY, &drive->atapi_flags)) {
+	if (test_and_set_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags)) {
 		retval = -EBUSY;
 		goto out_put_tape;
 	}
 
 	retval = idetape_wait_ready(drive, 60 * HZ);
 	if (retval) {
-		clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
+		clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags);
 		printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
 		goto out_put_tape;
 	}
 
-	idetape_read_position(drive);
-	if (!test_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags))
+	ide_tape_read_position(drive);
+	if (!test_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), &drive->atapi_flags))
 		(void)idetape_rewind_tape(drive);
 
 	/* Read block size and write protect status from drive. */
@@ -1933,7 +1522,7 @@
 	if (tape->write_prot) {
 		if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
 		    (filp->f_flags & O_ACCMODE) == O_RDWR) {
-			clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
+			clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags);
 			retval = -EROFS;
 			goto out_put_tape;
 		}
@@ -1960,12 +1549,12 @@
 	idetape_tape_t *tape = drive->driver_data;
 
 	ide_tape_flush_merge_buffer(drive);
-	tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0);
-	if (tape->merge_bh != NULL) {
+	tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
+	if (tape->buf != NULL) {
 		idetape_pad_zeros(drive, tape->blk_size *
 				(tape->user_bs_factor - 1));
-		ide_tape_kfree_buffer(tape);
-		tape->merge_bh = NULL;
+		kfree(tape->buf);
+		tape->buf = NULL;
 	}
 	idetape_write_filemark(drive);
 	idetape_flush_tape_buffers(drive);
@@ -1990,15 +1579,17 @@
 			ide_tape_discard_merge_buffer(drive, 1);
 	}
 
-	if (minor < 128 && test_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags))
+	if (minor < 128 && test_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT),
+				    &drive->atapi_flags))
 		(void) idetape_rewind_tape(drive);
+
 	if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
 		if (tape->door_locked == DOOR_LOCKED) {
 			if (!ide_set_media_lock(drive, tape->disk, 0))
 				tape->door_locked = DOOR_UNLOCKED;
 		}
 	}
-	clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
+	clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags);
 	ide_tape_put(tape);
 	unlock_kernel();
 	return 0;
@@ -2012,17 +1603,14 @@
 	char fw_rev[4], vendor_id[8], product_id[16];
 
 	idetape_create_inquiry_cmd(&pc);
-	pc.buf = &pc_buf[0];
-	pc.buf_size = sizeof(pc_buf);
-
-	if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
+	if (ide_queue_pc_tail(drive, tape->disk, &pc, pc_buf, pc.req_xfer)) {
 		printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
 				tape->name);
 		return;
 	}
-	memcpy(vendor_id, &pc.buf[8], 8);
-	memcpy(product_id, &pc.buf[16], 16);
-	memcpy(fw_rev, &pc.buf[32], 4);
+	memcpy(vendor_id, &pc_buf[8], 8);
+	memcpy(product_id, &pc_buf[16], 16);
+	memcpy(fw_rev, &pc_buf[32], 4);
 
 	ide_fixstring(vendor_id, 8, 0);
 	ide_fixstring(product_id, 16, 0);
@@ -2040,11 +1628,11 @@
 {
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc pc;
-	u8 *caps;
+	u8 buf[24], *caps;
 	u8 speed, max_speed;
 
 	idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
-	if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
+	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer)) {
 		printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
 				" some default values\n");
 		tape->blk_size = 512;
@@ -2053,7 +1641,7 @@
 		put_unaligned(6*52, (u16 *)&tape->caps[16]);
 		return;
 	}
-	caps = pc.buf + 4 + pc.buf[3];
+	caps = buf + 4 + buf[3];
 
 	/* convert to host order and save for later use */
 	speed = be16_to_cpup((__be16 *)&caps[14]);
@@ -2159,8 +1747,6 @@
 	u16 *ctl = (u16 *)&tape->caps[12];
 
 	drive->pc_callback	 = ide_tape_callback;
-	drive->pc_update_buffers = idetape_update_buffers;
-	drive->pc_io_buffers	 = ide_tape_io_buffers;
 
 	drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
 
@@ -2191,11 +1777,6 @@
 		tape->buffer_size = *ctl * tape->blk_size;
 	}
 	buffer_size = tape->buffer_size;
-	tape->pages_per_buffer = buffer_size / PAGE_SIZE;
-	if (buffer_size % PAGE_SIZE) {
-		tape->pages_per_buffer++;
-		tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
-	}
 
 	/* select the "best" DSC read/write polling freq */
 	speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
@@ -2238,7 +1819,7 @@
 	ide_drive_t *drive = tape->drive;
 	struct gendisk *g = tape->disk;
 
-	BUG_ON(tape->merge_bh_size);
+	BUG_ON(tape->valid);
 
 	drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
 	drive->driver_data = NULL;
@@ -2311,7 +1892,7 @@
 
 static int idetape_open(struct block_device *bdev, fmode_t mode)
 {
-	struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk);
+	struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk, false, 0);
 
 	if (!tape)
 		return -ENXIO;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-taskfile.c linux-libre-2.6.31-gnu/drivers/ide/ide-taskfile.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-taskfile.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-taskfile.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,7 +98,6 @@
 	if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
 		ide_tf_dump(drive->name, cmd);
 		tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
-		SELECT_MASK(drive, 0);
 
 		if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
 			u8 data[2] = { cmd->tf.data, cmd->hob.data };
@@ -166,7 +165,7 @@
 	if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
 		if (custom && tf->command == ATA_CMD_SET_MULTI) {
 			drive->mult_req = drive->mult_count = 0;
-			drive->special.b.recalibrate = 1;
+			drive->special_flags |= IDE_SFLAG_RECALIBRATE;
 			(void)ide_dump_status(drive, __func__, stat);
 			return ide_stopped;
 		} else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
@@ -385,7 +384,7 @@
 	if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
 		ide_finish_cmd(drive, cmd, stat);
 	else
-		ide_complete_rq(drive, 0, cmd->rq->nr_sectors << 9);
+		ide_complete_rq(drive, 0, blk_rq_sectors(cmd->rq) << 9);
 	return ide_stopped;
 out_err:
 	ide_error_cmd(drive, cmd);
@@ -424,7 +423,9 @@
 
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
-	rq->buffer = buf;
+
+	if (cmd->tf_flags & IDE_TFLAG_WRITE)
+		rq->cmd_flags |= REQ_RW;
 
 	/*
 	 * (ks) We transfer currently only whole sectors.
@@ -432,18 +433,20 @@
 	 * if we would find a solution to transfer any size.
 	 * To support special commands like READ LONG.
 	 */
-	rq->hard_nr_sectors = rq->nr_sectors = nsect;
-	rq->hard_cur_sectors = rq->current_nr_sectors = nsect;
-
-	if (cmd->tf_flags & IDE_TFLAG_WRITE)
-		rq->cmd_flags |= REQ_RW;
+	if (nsect) {
+		error = blk_rq_map_kern(drive->queue, rq, buf,
+					nsect * SECTOR_SIZE, __GFP_WAIT);
+		if (error)
+			goto put_req;
+	}
 
 	rq->special = cmd;
 	cmd->rq = rq;
 
 	error = blk_execute_rq(drive->queue, NULL, rq, 0);
-	blk_put_request(rq);
 
+put_req:
+	blk_put_request(rq);
 	return error;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/ide-xfer-mode.c linux-libre-2.6.31-gnu/drivers/ide/ide-xfer-mode.c
--- linux-libre-2.6.30-gnu/drivers/ide/ide-xfer-mode.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/ide-xfer-mode.c	2009-09-09 18:13:59.000000000 -0400
@@ -107,6 +107,18 @@
 }
 EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
 
+int ide_pio_need_iordy(ide_drive_t *drive, const u8 pio)
+{
+	/*
+	 * IORDY may lead to controller lock up on certain controllers
+	 * if the port is not occupied.
+	 */
+	if (pio == 0 && (drive->hwif->port_flags & IDE_PFLAG_PROBING))
+		return 0;
+	return ata_id_pio_need_iordy(drive->id, pio);
+}
+EXPORT_SYMBOL_GPL(ide_pio_need_iordy);
+
 int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
 {
 	ide_hwif_t *hwif = drive->hwif;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/it8172.c linux-libre-2.6.31-gnu/drivers/ide/it8172.c
--- linux-libre-2.6.30-gnu/drivers/ide/it8172.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/it8172.c	2009-09-09 18:13:59.000000000 -0400
@@ -66,7 +66,7 @@
 	if (drive->media == ide_disk)
 		/* enable prefetch */
 		drive_enables |= 0x0004 << (drive->dn * 4);
-	if (ata_id_has_iordy(drive->id))
+	if (ide_pio_need_iordy(drive, pio))
 		/* enable IORDY sample-point */
 		drive_enables |= 0x0002 << (drive->dn * 4);
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/it8213.c linux-libre-2.6.31-gnu/drivers/ide/it8213.c
--- linux-libre-2.6.30-gnu/drivers/ide/it8213.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/it8213.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,7 @@
 		control |= 1;	/* Programmable timing on */
 	if (drive->media != ide_disk)
 		control |= 4;	/* ATAPI */
-	if (pio > 2)
+	if (ide_pio_need_iordy(drive, pio))
 		control |= 2;	/* IORDY */
 	if (is_slave) {
 		master_data |=  0x4000;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/Kconfig linux-libre-2.6.31-gnu/drivers/ide/Kconfig
--- linux-libre-2.6.30-gnu/drivers/ide/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 	  SMART parameters from disk drives.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ide-core.ko.
+	  module will be called ide-core.
 
 	  For further information, please read <file:Documentation/ide/ide.txt>.
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/macide.c linux-libre-2.6.31-gnu/drivers/ide/macide.c
--- linux-libre-2.6.30-gnu/drivers/ide/macide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/macide.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,17 +53,20 @@
 
 volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR);
 
-int macide_ack_intr(ide_hwif_t* hwif)
+int macide_test_irq(ide_hwif_t *hwif)
 {
-	if (*ide_ifr & 0x20) {
-		*ide_ifr &= ~0x20;
+	if (*ide_ifr & 0x20)
 		return 1;
-	}
 	return 0;
 }
 
-static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base,
-				      int irq, ide_ack_intr_t *ack_intr)
+static void macide_clear_irq(ide_drive_t *drive)
+{
+	*ide_ifr &= ~0x20;
+}
+
+static void __init macide_setup_ports(struct ide_hw *hw, unsigned long base,
+				      int irq)
 {
 	int i;
 
@@ -75,14 +78,18 @@
 	hw->io_ports.ctl_addr = base + IDE_CONTROL;
 
 	hw->irq = irq;
-	hw->ack_intr = ack_intr;
-
-	hw->chipset = ide_generic;
 }
 
+static const struct ide_port_ops macide_port_ops = {
+	.clear_irq		= macide_clear_irq,
+	.test_irq		= macide_test_irq,
+};
+
 static const struct ide_port_info macide_port_info = {
+	.port_ops		= &macide_port_ops,
 	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
 	.irq_flags		= IRQF_SHARED,
+	.chipset		= ide_generic,
 };
 
 static const char *mac_ide_name[] =
@@ -94,10 +101,10 @@
 
 static int __init macide_init(void)
 {
-	ide_ack_intr_t *ack_intr;
 	unsigned long base;
 	int irq;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
+	struct ide_port_info d = macide_port_info;
 
 	if (!MACH_IS_MAC)
 		return -ENODEV;
@@ -105,17 +112,15 @@
 	switch (macintosh_config->ide_type) {
 	case MAC_IDE_QUADRA:
 		base = IDE_BASE;
-		ack_intr = macide_ack_intr;
 		irq = IRQ_NUBUS_F;
 		break;
 	case MAC_IDE_PB:
 		base = IDE_BASE;
-		ack_intr = macide_ack_intr;
 		irq = IRQ_NUBUS_C;
 		break;
 	case MAC_IDE_BABOON:
 		base = BABOON_BASE;
-		ack_intr = NULL;
+		d.port_ops = NULL;
 		irq = IRQ_BABOON_1;
 		break;
 	default:
@@ -125,9 +130,9 @@
 	printk(KERN_INFO "ide: Macintosh %s IDE controller\n",
 			 mac_ide_name[macintosh_config->ide_type - 1]);
 
-	macide_setup_ports(&hw, base, irq, ack_intr);
+	macide_setup_ports(&hw, base, irq);
 
-	return ide_host_add(&macide_port_info, hws, NULL);
+	return ide_host_add(&d, hws, 1, NULL);
 }
 
 module_init(macide_init);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/opti621.c linux-libre-2.6.31-gnu/drivers/ide/opti621.c
--- linux-libre-2.6.30-gnu/drivers/ide/opti621.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/opti621.c	2009-09-09 18:13:59.000000000 -0400
@@ -138,6 +138,7 @@
 	ide_hwif_t *hwif = drive->hwif;
 	ide_drive_t *pair = ide_get_pair_dev(drive);
 	unsigned long flags;
+	unsigned long mode = XFER_PIO_0 + pio, pair_mode;
 	u8 tim, misc, addr_pio = pio, clk;
 
 	/* DRDY is default 2 (by OPTi Databook) */
@@ -150,11 +151,12 @@
 		{ 0x48, 0x34, 0x21, 0x10, 0x10 }	/* 25 MHz */
 	};
 
-	drive->drive_data = XFER_PIO_0 + pio;
+	ide_set_drivedata(drive, (void *)mode);
 
 	if (pair) {
-		if (pair->drive_data && pair->drive_data < drive->drive_data)
-			addr_pio = pair->drive_data - XFER_PIO_0;
+		pair_mode = (unsigned long)ide_get_drivedata(pair);
+		if (pair_mode && pair_mode < mode)
+			addr_pio = pair_mode - XFER_PIO_0;
 	}
 
 	spin_lock_irqsave(&opti621_lock, flags);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/palm_bk3710.c linux-libre-2.6.31-gnu/drivers/ide/palm_bk3710.c
--- linux-libre-2.6.30-gnu/drivers/ide/palm_bk3710.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/palm_bk3710.c	2009-09-09 18:13:59.000000000 -0400
@@ -306,6 +306,7 @@
 	.host_flags		= IDE_HFLAG_MMIO,
 	.pio_mask		= ATA_PIO4,
 	.mwdma_mask		= ATA_MWDMA2,
+	.chipset		= ide_palm3710,
 };
 
 static int __init palm_bk3710_probe(struct platform_device *pdev)
@@ -315,7 +316,7 @@
 	void __iomem *base;
 	unsigned long rate, mem_size;
 	int i, rc;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 
 	clk = clk_get(&pdev->dev, "IDECLK");
 	if (IS_ERR(clk))
@@ -363,13 +364,12 @@
 			(base + IDE_PALM_ATA_PRI_CTL_OFFSET);
 	hw.irq = irq->start;
 	hw.dev = &pdev->dev;
-	hw.chipset = ide_palm3710;
 
 	palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
 							     ATA_UDMA5;
 
 	/* Register the IDE interface with Linux */
-	rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
+	rc = ide_host_add(&palm_bk3710_port_info, hws, 1, NULL);
 	if (rc)
 		goto out;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/pdc202xx_new.c linux-libre-2.6.31-gnu/drivers/ide/pdc202xx_new.c
--- linux-libre-2.6.30-gnu/drivers/ide/pdc202xx_new.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/pdc202xx_new.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,18 +40,6 @@
 #define DBG(fmt, args...)
 #endif
 
-static const char *pdc_quirk_drives[] = {
-	"QUANTUM FIREBALLlct08 08",
-	"QUANTUM FIREBALLP KA6.4",
-	"QUANTUM FIREBALLP KA9.1",
-	"QUANTUM FIREBALLP LM20.4",
-	"QUANTUM FIREBALLP KX13.6",
-	"QUANTUM FIREBALLP KX20.5",
-	"QUANTUM FIREBALLP KX27.3",
-	"QUANTUM FIREBALLP LM20.5",
-	NULL
-};
-
 static u8 max_dma_rate(struct pci_dev *pdev)
 {
 	u8 mode;
@@ -200,19 +188,6 @@
 		return ATA_CBL_PATA80;
 }
 
-static void pdcnew_quirkproc(ide_drive_t *drive)
-{
-	const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
-
-	for (list = pdc_quirk_drives; *list != NULL; list++)
-		if (strstr(m, *list) != NULL) {
-			drive->quirk_list = 2;
-			return;
-		}
-
-	drive->quirk_list = 0;
-}
-
 static void pdcnew_reset(ide_drive_t *drive)
 {
 	/*
@@ -473,7 +448,6 @@
 static const struct ide_port_ops pdcnew_port_ops = {
 	.set_pio_mode		= pdcnew_set_pio_mode,
 	.set_dma_mode		= pdcnew_set_dma_mode,
-	.quirkproc		= pdcnew_quirkproc,
 	.resetproc		= pdcnew_reset,
 	.cable_detect		= pdcnew_cable_detect,
 };
diff -druN linux-libre-2.6.30-gnu/drivers/ide/pdc202xx_old.c linux-libre-2.6.31-gnu/drivers/ide/pdc202xx_old.c
--- linux-libre-2.6.30-gnu/drivers/ide/pdc202xx_old.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/pdc202xx_old.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,18 +23,6 @@
 
 #define PDC202XX_DEBUG_DRIVE_INFO	0
 
-static const char *pdc_quirk_drives[] = {
-	"QUANTUM FIREBALLlct08 08",
-	"QUANTUM FIREBALLP KA6.4",
-	"QUANTUM FIREBALLP KA9.1",
-	"QUANTUM FIREBALLP LM20.4",
-	"QUANTUM FIREBALLP KX13.6",
-	"QUANTUM FIREBALLP KX20.5",
-	"QUANTUM FIREBALLP KX27.3",
-	"QUANTUM FIREBALLP LM20.5",
-	NULL
-};
-
 static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
 
 static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
@@ -85,7 +73,7 @@
 		 * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
 		 */
 		AP &= ~0x3f;
-		if (ata_id_iordy_disable(drive->id))
+		if (ide_pio_need_iordy(drive, speed - XFER_PIO_0))
 			AP |= 0x20;	/* set IORDY_EN bit */
 		if (drive->media == ide_disk)
 			AP |= 0x10;	/* set Prefetch_EN bit */
@@ -116,6 +104,27 @@
 	pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
 }
 
+static int pdc202xx_test_irq(ide_hwif_t *hwif)
+{
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	unsigned long high_16	= pci_resource_start(dev, 4);
+	u8 sc1d			= inb(high_16 + 0x1d);
+
+	if (hwif->channel) {
+		/*
+		 * bit 7: error, bit 6: interrupting,
+		 * bit 5: FIFO full, bit 4: FIFO empty
+		 */
+		return ((sc1d & 0x50) == 0x40) ? 1 : 0;
+	} else	{
+		/*
+		 * bit 3: error, bit 2: interrupting,
+		 * bit 1: FIFO full, bit 0: FIFO empty
+		 */
+		return ((sc1d & 0x05) == 0x04) ? 1 : 0;
+	}
+}
+
 static u8 pdc2026x_cable_detect(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -151,19 +160,6 @@
 	outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
 }
 
-static void pdc202xx_quirkproc(ide_drive_t *drive)
-{
-	const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
-
-	for (list = pdc_quirk_drives; *list != NULL; list++)
-		if (strstr(m, *list) != NULL) {
-			drive->quirk_list = 2;
-			return;
-		}
-
-	drive->quirk_list = 0;
-}
-
 static void pdc202xx_dma_start(ide_drive_t *drive)
 {
 	if (drive->current_speed > XFER_UDMA_2)
@@ -177,7 +173,7 @@
 		u8 clock = inb(high_16 + 0x11);
 
 		outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
-		word_count = (rq->nr_sectors << 8);
+		word_count = (blk_rq_sectors(rq) << 8);
 		word_count = (rq_data_dir(rq) == READ) ?
 					word_count | 0x05000000 :
 					word_count | 0x06000000;
@@ -203,52 +199,6 @@
 	return ide_dma_end(drive);
 }
 
-static int pdc202xx_dma_test_irq(ide_drive_t *drive)
-{
-	ide_hwif_t *hwif	= drive->hwif;
-	unsigned long high_16	= hwif->extra_base - 16;
-	u8 dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
-	u8 sc1d			= inb(high_16 + 0x001d);
-
-	if (hwif->channel) {
-		/* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */
-		if ((sc1d & 0x50) == 0x50)
-			goto somebody_else;
-		else if ((sc1d & 0x40) == 0x40)
-			return (dma_stat & 4) == 4;
-	} else {
-		/* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */
-		if ((sc1d & 0x05) == 0x05)
-			goto somebody_else;
-		else if ((sc1d & 0x04) == 0x04)
-			return (dma_stat & 4) == 4;
-	}
-somebody_else:
-	return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
-}
-
-static void pdc202xx_reset(ide_drive_t *drive)
-{
-	ide_hwif_t *hwif	= drive->hwif;
-	unsigned long high_16	= hwif->extra_base - 16;
-	u8 udma_speed_flag	= inb(high_16 | 0x001f);
-
-	printk(KERN_WARNING "PDC202xx: software reset...\n");
-
-	outb(udma_speed_flag | 0x10, high_16 | 0x001f);
-	mdelay(100);
-	outb(udma_speed_flag & ~0x10, high_16 | 0x001f);
-	mdelay(2000);	/* 2 seconds ?! */
-
-	ide_set_max_pio(drive);
-}
-
-static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
-{
-	pdc202xx_reset(drive);
-	ide_dma_lost_irq(drive);
-}
-
 static int init_chipset_pdc202xx(struct pci_dev *dev)
 {
 	unsigned long dmabase = pci_resource_start(dev, 4);
@@ -302,37 +252,23 @@
 static const struct ide_port_ops pdc20246_port_ops = {
 	.set_pio_mode		= pdc202xx_set_pio_mode,
 	.set_dma_mode		= pdc202xx_set_mode,
-	.quirkproc		= pdc202xx_quirkproc,
+	.test_irq		= pdc202xx_test_irq,
 };
 
 static const struct ide_port_ops pdc2026x_port_ops = {
 	.set_pio_mode		= pdc202xx_set_pio_mode,
 	.set_dma_mode		= pdc202xx_set_mode,
-	.quirkproc		= pdc202xx_quirkproc,
-	.resetproc		= pdc202xx_reset,
 	.cable_detect		= pdc2026x_cable_detect,
 };
 
-static const struct ide_dma_ops pdc20246_dma_ops = {
-	.dma_host_set		= ide_dma_host_set,
-	.dma_setup		= ide_dma_setup,
-	.dma_start		= ide_dma_start,
-	.dma_end		= ide_dma_end,
-	.dma_test_irq		= pdc202xx_dma_test_irq,
-	.dma_lost_irq		= ide_dma_lost_irq,
-	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
-	.dma_sff_read_status	= ide_dma_sff_read_status,
-};
-
 static const struct ide_dma_ops pdc2026x_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
 	.dma_start		= pdc202xx_dma_start,
 	.dma_end		= pdc202xx_dma_end,
-	.dma_test_irq		= pdc202xx_dma_test_irq,
-	.dma_lost_irq		= pdc202xx_dma_lost_irq,
+	.dma_test_irq		= ide_dma_test_irq,
+	.dma_lost_irq		= ide_dma_lost_irq,
 	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
-	.dma_clear		= pdc202xx_reset,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
@@ -354,7 +290,7 @@
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_pdc202xx,
 		.port_ops	= &pdc20246_port_ops,
-		.dma_ops	= &pdc20246_dma_ops,
+		.dma_ops	= &sff_dma_ops,
 		.host_flags	= IDE_HFLAGS_PDC202XX,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
diff -druN linux-libre-2.6.30-gnu/drivers/ide/piix.c linux-libre-2.6.31-gnu/drivers/ide/piix.c
--- linux-libre-2.6.30-gnu/drivers/ide/piix.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/piix.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,7 +98,7 @@
 		control |= 1;	/* Programmable timing on */
 	if (drive->media == ide_disk)
 		control |= 4;	/* Prefetch, post write */
-	if (pio > 2)
+	if (ide_pio_need_iordy(drive, pio))
 		control |= 2;	/* IORDY */
 	if (is_slave) {
 		master_data |=  0x4000;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/pmac.c linux-libre-2.6.31-gnu/drivers/ide/pmac.c
--- linux-libre-2.6.30-gnu/drivers/ide/pmac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/pmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -1023,13 +1023,14 @@
  * Setup, register & probe an IDE channel driven by this driver, this is
  * called by one of the 2 probe functions (macio or PCI).
  */
-static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
+static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
+					   struct ide_hw *hw)
 {
 	struct device_node *np = pmif->node;
 	const int *bidp;
 	struct ide_host *host;
 	ide_hwif_t *hwif;
-	hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
+	struct ide_hw *hws[] = { hw };
 	struct ide_port_info d = pmac_port_info;
 	int rc;
 
@@ -1077,7 +1078,7 @@
 	/* Make sure we have sane timings */
 	sanitize_timings(pmif);
 
-	host = ide_host_alloc(&d, hws);
+	host = ide_host_alloc(&d, hws, 1);
 	if (host == NULL)
 		return -ENOMEM;
 	hwif = host->ports[0];
@@ -1124,7 +1125,7 @@
 	return 0;
 }
 
-static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base)
+static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base)
 {
 	int i;
 
@@ -1144,7 +1145,7 @@
 	unsigned long regbase;
 	pmac_ide_hwif_t *pmif;
 	int irq, rc;
-	hw_regs_t hw;
+	struct ide_hw hw;
 
 	pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
 	if (pmif == NULL)
@@ -1268,7 +1269,7 @@
 	void __iomem *base;
 	unsigned long rbase, rlen;
 	int rc;
-	hw_regs_t hw;
+	struct ide_hw hw;
 
 	np = pci_device_to_OF_node(pdev);
 	if (np == NULL) {
diff -druN linux-libre-2.6.30-gnu/drivers/ide/q40ide.c linux-libre-2.6.31-gnu/drivers/ide/q40ide.c
--- linux-libre-2.6.30-gnu/drivers/ide/q40ide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/q40ide.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,11 +51,9 @@
 /*
  * Addresses are pretranslated for Q40 ISA access.
  */
-static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base,
-			ide_ack_intr_t *ack_intr,
-			int irq)
+static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, int irq)
 {
-	memset(hw, 0, sizeof(hw_regs_t));
+	memset(hw, 0, sizeof(*hw));
 	/* BIG FAT WARNING: 
 	   assumption: only DATA port is ever used in 16 bit mode */
 	hw->io_ports.data_addr = Q40_ISA_IO_W(base);
@@ -69,9 +67,6 @@
 	hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206);
 
 	hw->irq = irq;
-	hw->ack_intr = ack_intr;
-
-	hw->chipset = ide_generic;
 }
 
 static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
@@ -119,6 +114,7 @@
 	.tp_ops			= &q40ide_tp_ops,
 	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
 	.irq_flags		= IRQF_SHARED,
+	.chipset		= ide_generic,
 };
 
 /* 
@@ -136,7 +132,7 @@
 static int __init q40ide_init(void)
 {
     int i;
-    hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
+    struct ide_hw hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL };
 
     if (!MACH_IS_Q40)
       return -ENODEV;
@@ -157,13 +153,13 @@
 		release_region(pcide_bases[i], 8);
 		continue;
 	}
-	q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL,
+	q40_ide_setup_ports(&hw[i], pcide_bases[i],
 			q40ide_default_irq(pcide_bases[i]));
 
 	hws[i] = &hw[i];
     }
 
-    return ide_host_add(&q40ide_port_info, hws, NULL);
+    return ide_host_add(&q40ide_port_info, hws, Q40IDE_NUM_HWIFS, NULL);
 }
 
 module_init(q40ide_init);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/qd65xx.c linux-libre-2.6.31-gnu/drivers/ide/qd65xx.c
--- linux-libre-2.6.30-gnu/drivers/ide/qd65xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/qd65xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -180,8 +180,11 @@
 
 static void qd_set_timing (ide_drive_t *drive, u8 timing)
 {
-	drive->drive_data &= 0xff00;
-	drive->drive_data |= timing;
+	unsigned long data = (unsigned long)ide_get_drivedata(drive);
+
+	data &= 0xff00;
+	data |= timing;
+	ide_set_drivedata(drive, (void *)data);
 
 	printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
 }
@@ -292,7 +295,7 @@
 	u8 base = (hwif->config_data & 0xff00) >> 8;
 	u8 config = QD_CONFIG(hwif);
 
-	drive->drive_data = QD6500_DEF_DATA;
+	ide_set_drivedata(drive, (void *)QD6500_DEF_DATA);
 }
 
 static void __init qd6580_init_dev(ide_drive_t *drive)
@@ -308,7 +311,7 @@
 	} else
 		t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
 
-	drive->drive_data = (drive->dn & 1) ? t2 : t1;
+	ide_set_drivedata(drive, (void *)((drive->dn & 1) ? t2 : t1));
 }
 
 static const struct ide_tp_ops qd65xx_tp_ops = {
diff -druN linux-libre-2.6.30-gnu/drivers/ide/qd65xx.h linux-libre-2.6.31-gnu/drivers/ide/qd65xx.h
--- linux-libre-2.6.30-gnu/drivers/ide/qd65xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/qd65xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -31,8 +31,15 @@
 
 #define QD_CONFIG(hwif)		((hwif)->config_data & 0x00ff)
 
-#define QD_TIMING(drive)	(u8)(((drive)->drive_data) & 0x00ff)
-#define QD_TIMREG(drive)	(u8)((((drive)->drive_data) & 0xff00) >> 8)
+static inline u8 QD_TIMING(ide_drive_t *drive)
+{
+	return (unsigned long)ide_get_drivedata(drive) & 0x00ff;
+}
+
+static inline u8 QD_TIMREG(ide_drive_t *drive)
+{
+	return ((unsigned long)ide_get_drivedata(drive) & 0xff00) >> 8;
+}
 
 #define QD6500_DEF_DATA		((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08))
 #define QD6580_DEF_DATA		((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
diff -druN linux-libre-2.6.30-gnu/drivers/ide/rapide.c linux-libre-2.6.31-gnu/drivers/ide/rapide.c
--- linux-libre-2.6.30-gnu/drivers/ide/rapide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/rapide.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,9 +13,10 @@
 
 static const struct ide_port_info rapide_port_info = {
 	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+	.chipset		= ide_generic,
 };
 
-static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
+static void rapide_setup_ports(struct ide_hw *hw, void __iomem *base,
 			       void __iomem *ctrl, unsigned int sz, int irq)
 {
 	unsigned long port = (unsigned long)base;
@@ -35,7 +36,7 @@
 	void __iomem *base;
 	struct ide_host *host;
 	int ret;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 
 	ret = ecard_request_resources(ec);
 	if (ret)
@@ -49,10 +50,9 @@
 
 	memset(&hw, 0, sizeof(hw));
 	rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
-	hw.chipset = ide_generic;
 	hw.dev = &ec->dev;
 
-	ret = ide_host_add(&rapide_port_info, hws, &host);
+	ret = ide_host_add(&rapide_port_info, hws, 1, &host);
 	if (ret)
 		goto release;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ide/scc_pata.c linux-libre-2.6.31-gnu/drivers/ide/scc_pata.c
--- linux-libre-2.6.30-gnu/drivers/ide/scc_pata.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/scc_pata.c	2009-09-09 18:13:59.000000000 -0400
@@ -559,7 +559,7 @@
 {
 	struct scc_ports *ports = pci_get_drvdata(dev);
 	struct ide_host *host;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	int i, rc;
 
 	memset(&hw, 0, sizeof(hw));
@@ -567,9 +567,8 @@
 		hw.io_ports_array[i] = ports->dma + 0x20 + i * 4;
 	hw.irq = dev->irq;
 	hw.dev = &dev->dev;
-	hw.chipset = ide_pci;
 
-	rc = ide_host_add(d, hws, &host);
+	rc = ide_host_add(d, hws, 1, &host);
 	if (rc)
 		return rc;
 
@@ -823,6 +822,7 @@
 	.host_flags	= IDE_HFLAG_SINGLE,
 	.irq_flags	= IRQF_SHARED,
 	.pio_mask	= ATA_PIO4,
+	.chipset	= ide_pci,
 };
 
 /**
diff -druN linux-libre-2.6.30-gnu/drivers/ide/setup-pci.c linux-libre-2.6.31-gnu/drivers/ide/setup-pci.c
--- linux-libre-2.6.30-gnu/drivers/ide/setup-pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/setup-pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1998-2000  Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 1995-1998  Mark Lord
- *  Copyright (C)      2007  Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2007-2009  Bartlomiej Zolnierkiewicz
  *
  *  May be copied or modified under the terms of the GNU General Public License
  */
@@ -301,11 +301,11 @@
 }
 
 /**
- *	ide_hw_configure	-	configure a hw_regs_t instance
+ *	ide_hw_configure	-	configure a struct ide_hw instance
  *	@dev: PCI device holding interface
  *	@d: IDE port info
  *	@port: port number
- *	@hw: hw_regs_t instance corresponding to this port
+ *	@hw: struct ide_hw instance corresponding to this port
  *
  *	Perform the initial set up for the hardware interface structure. This
  *	is done per interface port rather than per PCI device. There may be
@@ -315,7 +315,7 @@
  */
 
 static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
-			    unsigned int port, hw_regs_t *hw)
+			    unsigned int port, struct ide_hw *hw)
 {
 	unsigned long ctl = 0, base = 0;
 
@@ -344,7 +344,6 @@
 
 	memset(hw, 0, sizeof(*hw));
 	hw->dev = &dev->dev;
-	hw->chipset = d->chipset ? d->chipset : ide_pci;
 	ide_std_init_ports(hw, base, ctl | 2);
 
 	return 0;
@@ -446,8 +445,8 @@
  *	ide_pci_setup_ports	-	configure ports/devices on PCI IDE
  *	@dev: PCI device
  *	@d: IDE port info
- *	@hw: hw_regs_t instances corresponding to this PCI IDE device
- *	@hws: hw_regs_t pointers table to update
+ *	@hw: struct ide_hw instances corresponding to this PCI IDE device
+ *	@hws: struct ide_hw pointers table to update
  *
  *	Scan the interfaces attached to this device and do any
  *	necessary per port setup. Attach the devices and ask the
@@ -459,7 +458,7 @@
  */
 
 void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
-			 hw_regs_t *hw, hw_regs_t **hws)
+			 struct ide_hw *hw, struct ide_hw **hws)
 {
 	int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
 	u8 tmp;
@@ -535,61 +534,15 @@
 	return ret;
 }
 
-int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
-		     void *priv)
-{
-	struct ide_host *host;
-	hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
-	int ret;
-
-	ret = ide_setup_pci_controller(dev, d, 1);
-	if (ret < 0)
-		goto out;
-
-	ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
-
-	host = ide_host_alloc(d, hws);
-	if (host == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	host->dev[0] = &dev->dev;
-
-	host->host_priv = priv;
-
-	host->irq_flags = IRQF_SHARED;
-
-	pci_set_drvdata(dev, host);
-
-	ret = do_ide_setup_pci_device(dev, d, 1);
-	if (ret < 0)
-		goto out;
-
-	/* fixup IRQ */
-	if (ide_pci_is_in_compatibility_mode(dev)) {
-		hw[0].irq = pci_get_legacy_ide_irq(dev, 0);
-		hw[1].irq = pci_get_legacy_ide_irq(dev, 1);
-	} else
-		hw[1].irq = hw[0].irq = ret;
-
-	ret = ide_host_register(host, d, hws);
-	if (ret)
-		ide_host_free(host);
-out:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(ide_pci_init_one);
-
 int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
 		     const struct ide_port_info *d, void *priv)
 {
 	struct pci_dev *pdev[] = { dev1, dev2 };
 	struct ide_host *host;
-	int ret, i;
-	hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
+	int ret, i, n_ports = dev2 ? 4 : 2;
+	struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL };
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < n_ports / 2; i++) {
 		ret = ide_setup_pci_controller(pdev[i], d, !i);
 		if (ret < 0)
 			goto out;
@@ -597,23 +550,24 @@
 		ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]);
 	}
 
-	host = ide_host_alloc(d, hws);
+	host = ide_host_alloc(d, hws, n_ports);
 	if (host == NULL) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	host->dev[0] = &dev1->dev;
-	host->dev[1] = &dev2->dev;
+	if (dev2)
+		host->dev[1] = &dev2->dev;
 
 	host->host_priv = priv;
-
 	host->irq_flags = IRQF_SHARED;
 
 	pci_set_drvdata(pdev[0], host);
-	pci_set_drvdata(pdev[1], host);
+	if (dev2)
+		pci_set_drvdata(pdev[1], host);
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < n_ports / 2; i++) {
 		ret = do_ide_setup_pci_device(pdev[i], d, !i);
 
 		/*
@@ -639,6 +593,13 @@
 }
 EXPORT_SYMBOL_GPL(ide_pci_init_two);
 
+int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
+		     void *priv)
+{
+	return ide_pci_init_two(dev, NULL, d, priv);
+}
+EXPORT_SYMBOL_GPL(ide_pci_init_one);
+
 void ide_pci_remove(struct pci_dev *dev)
 {
 	struct ide_host *host = pci_get_drvdata(dev);
diff -druN linux-libre-2.6.30-gnu/drivers/ide/sgiioc4.c linux-libre-2.6.31-gnu/drivers/ide/sgiioc4.c
--- linux-libre-2.6.30-gnu/drivers/ide/sgiioc4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/sgiioc4.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved.
- * Copyright (C) 2008 MontaVista Software, Inc.
+ * Copyright (C) 2008-2009 MontaVista Software, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -29,8 +29,7 @@
 #include <linux/blkdev.h>
 #include <linux/scatterlist.h>
 #include <linux/ioc4.h>
-#include <asm/io.h>
-
+#include <linux/io.h>
 #include <linux/ide.h>
 
 #define DRV_NAME "SGIIOC4"
@@ -72,7 +71,7 @@
 #define IOC4_CMD_CTL_BLK_SIZE	0x20
 #define IOC4_SUPPORTED_FIRMWARE_REV 46
 
-typedef struct {
+struct ioc4_dma_regs {
 	u32 timing_reg0;
 	u32 timing_reg1;
 	u32 low_mem_ptr;
@@ -82,17 +81,18 @@
 	u32 dev_byte_count;
 	u32 mem_byte_count;
 	u32 status;
-} ioc4_dma_regs_t;
+};
 
 /* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */
 /* IOC4 has only 1 IDE channel */
-#define IOC4_PRD_BYTES       16
-#define IOC4_PRD_ENTRIES     (PAGE_SIZE /(4*IOC4_PRD_BYTES))
+#define IOC4_PRD_BYTES		16
+#define IOC4_PRD_ENTRIES	(PAGE_SIZE / (4 * IOC4_PRD_BYTES))
 
 
-static void
-sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
-			unsigned long ctrl_port, unsigned long irq_port)
+static void sgiioc4_init_hwif_ports(struct ide_hw *hw,
+				    unsigned long data_port,
+				    unsigned long ctrl_port,
+				    unsigned long irq_port)
 {
 	unsigned long reg = data_port;
 	int i;
@@ -105,13 +105,11 @@
 	hw->io_ports.irq_addr = irq_port;
 }
 
-static int
-sgiioc4_checkirq(ide_hwif_t * hwif)
+static int sgiioc4_checkirq(ide_hwif_t *hwif)
 {
-	unsigned long intr_addr =
-		hwif->io_ports.irq_addr + IOC4_INTR_REG * 4;
+	unsigned long intr_addr = hwif->io_ports.irq_addr + IOC4_INTR_REG * 4;
 
-	if ((u8)readl((void __iomem *)intr_addr) & 0x03)
+	if (readl((void __iomem *)intr_addr) & 0x03)
 		return 1;
 
 	return 0;
@@ -119,8 +117,7 @@
 
 static u8 sgiioc4_read_status(ide_hwif_t *);
 
-static int
-sgiioc4_clearirq(ide_drive_t * drive)
+static int sgiioc4_clearirq(ide_drive_t *drive)
 {
 	u32 intr_reg;
 	ide_hwif_t *hwif = drive->hwif;
@@ -158,12 +155,10 @@
 				readl((void __iomem *)(io_ports->irq_addr + 4));
 			pci_read_config_dword(dev, PCI_COMMAND,
 					      &pci_stat_cmd_reg);
-			printk(KERN_ERR
-			       "%s(%s) : PCI Bus Error when doing DMA:"
-				   " status-cmd reg is 0x%x\n",
+			printk(KERN_ERR "%s(%s): PCI Bus Error when doing DMA: "
+			       "status-cmd reg is 0x%x\n",
 			       __func__, drive->name, pci_stat_cmd_reg);
-			printk(KERN_ERR
-			       "%s(%s) : PCI Error Address is 0x%x%x\n",
+			printk(KERN_ERR "%s(%s): PCI Error Address is 0x%x%x\n",
 			       __func__, drive->name,
 			       pci_err_addr_high, pci_err_addr_low);
 			/* Clear the PCI Error indicator */
@@ -189,8 +184,7 @@
 	writel(temp_reg, (void __iomem *)ioc4_dma_addr);
 }
 
-static u32
-sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
+static u32 sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
 {
 	unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
 	u32	ioc4_dma;
@@ -227,7 +221,7 @@
 	}
 
 	/*
-	 * The IOC4 will DMA 1's to the ending dma area to indicate that
+	 * The IOC4 will DMA 1's to the ending DMA area to indicate that
 	 * previous data DMA is complete.  This is necessary because of relaxed
 	 * ordering between register reads and DMA writes on the Altix.
 	 */
@@ -265,7 +259,7 @@
 {
 }
 
-/* returns 1 if dma irq issued, 0 otherwise */
+/* Returns 1 if DMA IRQ issued, 0 otherwise */
 static int sgiioc4_dma_test_irq(ide_drive_t *drive)
 {
 	return sgiioc4_checkirq(drive->hwif);
@@ -286,8 +280,7 @@
 	sgiioc4_clearirq(drive);
 }
 
-static void
-sgiioc4_dma_lost_irq(ide_drive_t * drive)
+static void sgiioc4_dma_lost_irq(ide_drive_t *drive)
 {
 	sgiioc4_resetproc(drive);
 
@@ -313,13 +306,13 @@
 	return reg;
 }
 
-/* Creates a dma map for the scatter-gather list entries */
-static int __devinit
-ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
+/* Creates a DMA map for the scatter-gather list entries */
+static int __devinit ide_dma_sgiioc4(ide_hwif_t *hwif,
+				     const struct ide_port_info *d)
 {
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
-	int num_ports = sizeof (ioc4_dma_regs_t);
+	int num_ports = sizeof(struct ioc4_dma_regs);
 	void *pad;
 
 	printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
@@ -362,8 +355,7 @@
 }
 
 /* Initializes the IOC4 DMA Engine */
-static void
-sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
+static void sgiioc4_configure_for_dma(int dma_direction, ide_drive_t *drive)
 {
 	u32 ioc4_dma;
 	ide_hwif_t *hwif = drive->hwif;
@@ -374,31 +366,27 @@
 	ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
 
 	if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
-		printk(KERN_WARNING
-			"%s(%s):Warning!! DMA from previous transfer was still active\n",
-		       __func__, drive->name);
+		printk(KERN_WARNING "%s(%s): Warning!! DMA from previous "
+		       "transfer was still active\n", __func__, drive->name);
 		writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
 		ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
 		if (ioc4_dma & IOC4_S_DMA_STOP)
-			printk(KERN_ERR
-			       "%s(%s) : IOC4 Dma STOP bit is still 1\n",
-			       __func__, drive->name);
+			printk(KERN_ERR "%s(%s): IOC4 DMA STOP bit is "
+			       "still 1\n", __func__, drive->name);
 	}
 
 	ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
 	if (ioc4_dma & IOC4_S_DMA_ERROR) {
-		printk(KERN_WARNING
-		       "%s(%s) : Warning!! - DMA Error during Previous"
-		       " transfer | status 0x%x\n",
+		printk(KERN_WARNING "%s(%s): Warning!! DMA Error during "
+		       "previous transfer, status 0x%x\n",
 		       __func__, drive->name, ioc4_dma);
 		writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
 		ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
 
 		if (ioc4_dma & IOC4_S_DMA_STOP)
-			printk(KERN_ERR
-			       "%s(%s) : IOC4 DMA STOP bit is still 1\n",
-			       __func__, drive->name);
+			printk(KERN_ERR "%s(%s): IOC4 DMA STOP bit is "
+			       "still 1\n", __func__, drive->name);
 	}
 
 	/* Address of the Scatter Gather List */
@@ -408,20 +396,22 @@
 	/* Address of the Ending DMA */
 	memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
 	ending_dma_addr = cpu_to_le32(hwif->extra_base);
-	writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4));
+	writel(ending_dma_addr, (void __iomem *)(dma_base +
+						 IOC4_DMA_END_ADDR * 4));
 
 	writel(dma_direction, (void __iomem *)ioc4_dma_addr);
 }
 
-/* IOC4 Scatter Gather list Format 					 */
+/* IOC4 Scatter Gather list Format					 */
 /* 128 Bit entries to support 64 bit addresses in the future		 */
 /* The Scatter Gather list Entry should be in the BIG-ENDIAN Format	 */
 /* --------------------------------------------------------------------- */
-/* | Upper 32 bits - Zero           |	 	Lower 32 bits- address | */
+/* | Upper 32 bits - Zero	    |		Lower 32 bits- address | */
 /* --------------------------------------------------------------------- */
 /* | Upper 32 bits - Zero	    |EOL| 15 unused     | 16 Bit Length| */
 /* --------------------------------------------------------------------- */
-/* Creates the scatter gather list, DMA Table */
+/* Creates the scatter gather list, DMA Table				 */
+
 static int sgiioc4_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
@@ -448,8 +438,10 @@
 				if (bcount > cur_len)
 					bcount = cur_len;
 
-				/* put the addr, length in
-				 * the IOC4 dma-table format */
+				/*
+				 * Put the address, length in
+				 * the IOC4 dma-table format
+				 */
 				*table = 0x0;
 				table++;
 				*table = cpu_to_be32(cur_addr);
@@ -540,16 +532,15 @@
 	.mwdma_mask		= ATA_MWDMA2_ONLY,
 };
 
-static int __devinit
-sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
 {
 	unsigned long cmd_base, irqport;
 	unsigned long bar0, cmd_phys_base, ctl;
 	void __iomem *virt_base;
-	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	int rc;
 
-	/*  Get the CmdBlk and CtrlBlk Base Registers */
+	/* Get the CmdBlk and CtrlBlk base registers */
 	bar0 = pci_resource_start(dev, 0);
 	virt_base = pci_ioremap_bar(dev, 0);
 	if (virt_base == NULL) {
@@ -557,9 +548,9 @@
 				DRV_NAME, bar0);
 		return -ENOMEM;
 	}
-	cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
-	ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
-	irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
+	cmd_base = (unsigned long)virt_base + IOC4_CMD_OFFSET;
+	ctl = (unsigned long)virt_base + IOC4_CTRL_OFFSET;
+	irqport = (unsigned long)virt_base + IOC4_INTR_OFFSET;
 
 	cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
 	if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
@@ -575,13 +566,12 @@
 	memset(&hw, 0, sizeof(hw));
 	sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
 	hw.irq = dev->irq;
-	hw.chipset = ide_pci;
 	hw.dev = &dev->dev;
 
-	/* Initializing chipset IRQ Registers */
+	/* Initialize chipset IRQ registers */
 	writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
 
-	rc = ide_host_add(&sgiioc4_port_info, hws, NULL);
+	rc = ide_host_add(&sgiioc4_port_info, hws, 1, NULL);
 	if (!rc)
 		return 0;
 
@@ -591,8 +581,7 @@
 	return rc;
 }
 
-static unsigned int __devinit
-pci_init_sgiioc4(struct pci_dev *dev)
+static unsigned int __devinit pci_init_sgiioc4(struct pci_dev *dev)
 {
 	int ret;
 
@@ -612,10 +601,10 @@
 	return ret;
 }
 
-int __devinit
-ioc4_ide_attach_one(struct ioc4_driver_data *idd)
+int __devinit ioc4_ide_attach_one(struct ioc4_driver_data *idd)
 {
-	/* PCI-RT does not bring out IDE connection.
+	/*
+	 * PCI-RT does not bring out IDE connection.
 	 * Do not attach to this particular IOC4.
 	 */
 	if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
@@ -628,7 +617,6 @@
 	.is_name = "IOC4_ide",
 	.is_owner = THIS_MODULE,
 	.is_probe = ioc4_ide_attach_one,
-/*	.is_remove = ioc4_ide_remove_one,	*/
 };
 
 static int __init ioc4_ide_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/ide/siimage.c linux-libre-2.6.31-gnu/drivers/ide/siimage.c
--- linux-libre-2.6.30-gnu/drivers/ide/siimage.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/siimage.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,6 @@
  *  smarter code in libata.
  *
  * TODO:
- * - IORDY fixes
  * - VDMA support
  */
 
@@ -234,8 +233,7 @@
  *	@pio: PIO mode number
  *
  *	Load the timing settings for this device mode into the
- *	controller. If we are in PIO mode 3 or 4 turn on IORDY
- *	monitoring (bit 9). The TF timing is bits 31:16
+ *	controller.
  */
 
 static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
@@ -276,13 +274,16 @@
 	/* now set up IORDY */
 	speedp = sil_ioread16(dev, tfaddr - 2);
 	speedp &= ~0x200;
-	if (pio > 2)
-		speedp |= 0x200;
-	sil_iowrite16(dev, speedp, tfaddr - 2);
 
 	mode = sil_ioread8(dev, base + addr_mask);
 	mode &= ~(unit ? 0x30 : 0x03);
-	mode |= unit ? 0x10 : 0x01;
+
+	if (ide_pio_need_iordy(drive, pio)) {
+		speedp |= 0x200;
+		mode |= unit ? 0x10 : 0x01;
+	}
+
+	sil_iowrite16(dev, speedp, tfaddr - 2);
 	sil_iowrite8(dev, mode, base + addr_mask);
 }
 
@@ -337,24 +338,14 @@
 	sil_iowrite16(dev, ultra, ua);
 }
 
-/* returns 1 if dma irq issued, 0 otherwise */
-static int siimage_io_dma_test_irq(ide_drive_t *drive)
+static int sil_test_irq(ide_hwif_t *hwif)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-	u8 dma_altstat		= 0;
 	unsigned long addr	= siimage_selreg(hwif, 1);
+	u8 val			= sil_ioread8(dev, addr);
 
-	/* return 1 if INTR asserted */
-	if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
-		return 1;
-
-	/* return 1 if Device INTR asserted */
-	pci_read_config_byte(dev, addr, &dma_altstat);
-	if (dma_altstat & 8)
-		return 0;	/* return 1; */
-
-	return 0;
+	/* Return 1 if INTRQ asserted */
+	return (val & 8) ? 1 : 0;
 }
 
 /**
@@ -368,7 +359,6 @@
 static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= drive->hwif;
-	unsigned long addr	= siimage_selreg(hwif, 0x1);
 	void __iomem *sata_error_addr
 		= (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
 
@@ -397,10 +387,6 @@
 	if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
 		return 1;
 
-	/* return 1 if Device INTR asserted */
-	if (readb((void __iomem *)addr) & 8)
-		return 0;	/* return 1; */
-
 	return 0;
 }
 
@@ -409,7 +395,7 @@
 	if (drive->hwif->host_flags & IDE_HFLAG_MMIO)
 		return siimage_mmio_dma_test_irq(drive);
 	else
-		return siimage_io_dma_test_irq(drive);
+		return ide_dma_test_irq(drive);
 }
 
 /**
@@ -451,8 +437,8 @@
 static void sil_sata_pre_reset(ide_drive_t *drive)
 {
 	if (drive->media == ide_disk) {
-		drive->special.b.set_geometry = 0;
-		drive->special.b.recalibrate = 0;
+		drive->special_flags &=
+			~(IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE);
 	}
 }
 
@@ -694,6 +680,7 @@
 	.set_pio_mode		= sil_set_pio_mode,
 	.set_dma_mode		= sil_set_dma_mode,
 	.quirkproc		= sil_quirkproc,
+	.test_irq		= sil_test_irq,
 	.udma_filter		= sil_pata_udma_filter,
 	.cable_detect		= sil_cable_detect,
 };
@@ -704,6 +691,7 @@
 	.reset_poll		= sil_sata_reset_poll,
 	.pre_reset		= sil_sata_pre_reset,
 	.quirkproc		= sil_quirkproc,
+	.test_irq		= sil_test_irq,
 	.udma_filter		= sil_sata_udma_filter,
 	.cable_detect		= sil_cable_detect,
 };
diff -druN linux-libre-2.6.30-gnu/drivers/ide/sl82c105.c linux-libre-2.6.31-gnu/drivers/ide/sl82c105.c
--- linux-libre-2.6.30-gnu/drivers/ide/sl82c105.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/sl82c105.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,7 @@
  * with the timing registers setup.
  *  -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org
  *
- * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2006-2007,2009 MontaVista Software, Inc. <source@mvista.com>
  * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
  */
 
@@ -61,8 +61,7 @@
 	if (cmd_off == 0)
 		cmd_off = 1;
 
-	if ((pio > 2 || ata_id_has_iordy(drive->id)) &&
-	    !(pio > 4 && ata_id_is_cfa(drive->id)))
+	if (ide_pio_need_iordy(drive, pio))
 		iordy = 0x40;
 
 	return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy;
@@ -74,6 +73,7 @@
 static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
+	unsigned long timings	= (unsigned long)ide_get_drivedata(drive);
 	int reg			= 0x44 + drive->dn * 4;
 	u16 drv_ctrl;
 
@@ -83,8 +83,9 @@
 	 * Store the PIO timings so that we can restore them
 	 * in case DMA will be turned off...
 	 */
-	drive->drive_data &= 0xffff0000;
-	drive->drive_data |= drv_ctrl;
+	timings &= 0xffff0000;
+	timings |= drv_ctrl;
+	ide_set_drivedata(drive, (void *)timings);
 
 	pci_write_config_word(dev, reg,  drv_ctrl);
 	pci_read_config_word (dev, reg, &drv_ctrl);
@@ -100,6 +101,7 @@
 static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200};
+	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
 	u16 drv_ctrl;
 
  	DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
@@ -111,8 +113,19 @@
 	 * Store the DMA timings so that we can actually program
 	 * them when DMA will be turned on...
 	 */
-	drive->drive_data &= 0x0000ffff;
-	drive->drive_data |= (unsigned long)drv_ctrl << 16;
+	timings &= 0x0000ffff;
+	timings |= (unsigned long)drv_ctrl << 16;
+	ide_set_drivedata(drive, (void *)timings);
+}
+
+static int sl82c105_test_irq(ide_hwif_t *hwif)
+{
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	u32 val, mask		= hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+
+	pci_read_config_dword(dev, 0x40, &val);
+
+	return (val & mask) ? 1 : 0;
 }
 
 /*
@@ -146,14 +159,15 @@
 	u32 val, mask		= hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
 	u8 dma_cmd;
 
-	printk("sl82c105: lost IRQ, resetting host\n");
+	printk(KERN_WARNING "sl82c105: lost IRQ, resetting host\n");
 
 	/*
 	 * Check the raw interrupt from the drive.
 	 */
 	pci_read_config_dword(dev, 0x40, &val);
 	if (val & mask)
-		printk("sl82c105: drive was requesting IRQ, but host lost it\n");
+		printk(KERN_INFO "sl82c105: drive was requesting IRQ, "
+		       "but host lost it\n");
 
 	/*
 	 * Was DMA enabled?  If so, disable it - we're resetting the
@@ -162,7 +176,7 @@
 	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
 	if (dma_cmd & 1) {
 		outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
-		printk("sl82c105: DMA was enabled\n");
+		printk(KERN_INFO "sl82c105: DMA was enabled\n");
 	}
 
 	sl82c105_reset_host(dev);
@@ -184,7 +198,8 @@
 
 	DBG(("%s(drive:%s)\n", __func__, drive->name));
 
-	pci_write_config_word(dev, reg, drive->drive_data >> 16);
+	pci_write_config_word(dev, reg,
+			      (unsigned long)ide_get_drivedata(drive) >> 16);
 
 	sl82c105_reset_host(dev);
 	ide_dma_start(drive);
@@ -209,7 +224,8 @@
 
 	ret = ide_dma_end(drive);
 
-	pci_write_config_word(dev, reg, drive->drive_data);
+	pci_write_config_word(dev, reg,
+			      (unsigned long)ide_get_drivedata(drive));
 
 	return ret;
 }
@@ -288,6 +304,7 @@
 	.set_pio_mode		= sl82c105_set_pio_mode,
 	.set_dma_mode		= sl82c105_set_dma_mode,
 	.resetproc		= sl82c105_resetproc,
+	.test_irq		= sl82c105_test_irq,
 };
 
 static const struct ide_dma_ops sl82c105_dma_ops = {
diff -druN linux-libre-2.6.30-gnu/drivers/ide/slc90e66.c linux-libre-2.6.31-gnu/drivers/ide/slc90e66.c
--- linux-libre-2.6.30-gnu/drivers/ide/slc90e66.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/slc90e66.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,7 +44,7 @@
 		control |= 1;	/* Programmable timing on */
 	if (drive->media == ide_disk)
 		control |= 4;	/* Prefetch, post write */
-	if (pio > 2)
+	if (ide_pio_need_iordy(drive, pio))
 		control |= 2;	/* IORDY */
 	if (is_slave) {
 		master_data |=  0x4000;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/tc86c001.c linux-libre-2.6.31-gnu/drivers/ide/tc86c001.c
--- linux-libre-2.6.30-gnu/drivers/ide/tc86c001.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/tc86c001.c	2009-09-09 18:13:59.000000000 -0400
@@ -112,7 +112,7 @@
 	ide_hwif_t *hwif	= drive->hwif;
 	unsigned long sc_base	= hwif->config_data;
 	unsigned long twcr_port	= sc_base + (drive->dn ? 0x06 : 0x04);
-	unsigned long nsectors	= hwif->rq->nr_sectors;
+	unsigned long nsectors	= blk_rq_sectors(hwif->rq);
 
 	/*
 	 * We have to manually load the sector count and size into
diff -druN linux-libre-2.6.30-gnu/drivers/ide/tx4938ide.c linux-libre-2.6.31-gnu/drivers/ide/tx4938ide.c
--- linux-libre-2.6.30-gnu/drivers/ide/tx4938ide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/tx4938ide.c	2009-09-09 18:13:59.000000000 -0400
@@ -130,8 +130,7 @@
 
 static int __init tx4938ide_probe(struct platform_device *pdev)
 {
-	hw_regs_t hw;
-	hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	struct ide_host *host;
 	struct resource *res;
 	struct tx4938ide_platform_info *pdata = pdev->dev.platform_data;
@@ -183,7 +182,7 @@
 		tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0);
 	else
 		d.port_ops = NULL;
-	ret = ide_host_add(&d, hws, &host);
+	ret = ide_host_add(&d, hws, 1, &host);
 	if (!ret)
 		platform_set_drvdata(pdev, host);
 	return ret;
diff -druN linux-libre-2.6.30-gnu/drivers/ide/tx4939ide.c linux-libre-2.6.31-gnu/drivers/ide/tx4939ide.c
--- linux-libre-2.6.30-gnu/drivers/ide/tx4939ide.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ide/tx4939ide.c	2009-09-09 18:13:59.000000000 -0400
@@ -307,7 +307,7 @@
 	tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ?
 			 TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1);
 
-	tx4939ide_writew(cmd->rq->nr_sectors, base, TX4939IDE_Sec_Cnt);
+	tx4939ide_writew(blk_rq_sectors(cmd->rq), base, TX4939IDE_Sec_Cnt);
 
 	return 0;
 }
@@ -537,8 +537,7 @@
 
 static int __init tx4939ide_probe(struct platform_device *pdev)
 {
-	hw_regs_t hw;
-	hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
+	struct ide_hw hw, *hws[] = { &hw };
 	struct ide_host *host;
 	struct resource *res;
 	int irq, ret;
@@ -581,7 +580,7 @@
 	hw.dev = &pdev->dev;
 
 	pr_info("TX4939 IDE interface (base %#lx, irq %d)\n", mapbase, irq);
-	host = ide_host_alloc(&tx4939ide_port_info, hws);
+	host = ide_host_alloc(&tx4939ide_port_info, hws, 1);
 	if (!host)
 		return -ENOMEM;
 	/* use extra_base for base address of the all registers */
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/csr1212.c linux-libre-2.6.31-gnu/drivers/ieee1394/csr1212.c
--- linux-libre-2.6.30-gnu/drivers/ieee1394/csr1212.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/csr1212.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,6 +35,7 @@
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/kmemcheck.h>
 #include <linux/string.h>
 #include <asm/bug.h>
 #include <asm/byteorder.h>
@@ -387,6 +388,7 @@
 	if (!kv)
 		return NULL;
 
+	kmemcheck_annotate_variable(kv->value.leaf.data[0]);
 	CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
 	CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
 
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/dv1394.c linux-libre-2.6.31-gnu/drivers/ieee1394/dv1394.c
--- linux-libre-2.6.30-gnu/drivers/ieee1394/dv1394.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/dv1394.c	2009-09-09 18:13:59.000000000 -0400
@@ -1789,12 +1789,13 @@
 	} else {
 		/* look up the card by ID */
 		unsigned long flags;
+		int idx = ieee1394_file_to_instance(file);
 
 		spin_lock_irqsave(&dv1394_cards_lock, flags);
 		if (!list_empty(&dv1394_cards)) {
 			struct video_card *p;
 			list_for_each_entry(p, &dv1394_cards, list) {
-				if ((p->id) == ieee1394_file_to_instance(file)) {
+				if ((p->id) == idx) {
 					video = p;
 					break;
 				}
@@ -1803,7 +1804,7 @@
 		spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 
 		if (!video) {
-			debug_printk("dv1394: OHCI card %d not found", ieee1394_file_to_instance(file));
+			debug_printk("dv1394: OHCI card %d not found", idx);
 			return -ENODEV;
 		}
 
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/eth1394.c linux-libre-2.6.31-gnu/drivers/ieee1394/eth1394.c
--- linux-libre-2.6.30-gnu/drivers/ieee1394/eth1394.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/eth1394.c	2009-09-09 18:13:59.000000000 -0400
@@ -361,7 +361,7 @@
 	node_info->pdg.sz = 0;
 	node_info->fifo = CSR1212_INVALID_ADDR_SPACE;
 
-	ud->device.driver_data = node_info;
+	dev_set_drvdata(&ud->device, node_info);
 	new_node->ud = ud;
 
 	priv = netdev_priv(hi->dev);
@@ -406,7 +406,7 @@
 	list_del(&old_node->list);
 	kfree(old_node);
 
-	node_info = (struct eth1394_node_info*)ud->device.driver_data;
+	node_info = dev_get_drvdata(&ud->device);
 
 	spin_lock_irqsave(&node_info->pdg.lock, flags);
 	/* The partial datagram list should be empty, but we'll just
@@ -416,7 +416,7 @@
 	spin_unlock_irqrestore(&node_info->pdg.lock, flags);
 
 	kfree(node_info);
-	ud->device.driver_data = NULL;
+	dev_set_drvdata(&ud->device, NULL);
 	return 0;
 }
 
@@ -688,7 +688,7 @@
 	ether1394_reset_priv(dev, 0);
 
 	list_for_each_entry(node, &priv->ip_node_list, list) {
-		node_info = node->ud->device.driver_data;
+		node_info = dev_get_drvdata(&node->ud->device);
 
 		spin_lock_irqsave(&node_info->pdg.lock, flags);
 
@@ -872,8 +872,7 @@
 		if (!node)
 			return cpu_to_be16(0);
 
-		node_info =
-		    (struct eth1394_node_info *)node->ud->device.driver_data;
+		node_info = dev_get_drvdata(&node->ud->device);
 
 		/* Update our speed/payload/fifo_offset table */
 		node_info->maxpayload =	maxpayload;
@@ -1080,7 +1079,7 @@
 		priv->ud_list[NODEID_TO_NODE(srcid)] = ud;
 	}
 
-	node_info = (struct eth1394_node_info *)ud->device.driver_data;
+	node_info = dev_get_drvdata(&ud->device);
 
 	/* First, did we receive a fragmented or unfragmented datagram? */
 	hdr->words.word1 = ntohs(hdr->words.word1);
@@ -1617,8 +1616,7 @@
 		if (!node)
 			goto fail;
 
-		node_info =
-		    (struct eth1394_node_info *)node->ud->device.driver_data;
+		node_info = dev_get_drvdata(&node->ud->device);
 		if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE)
 			goto fail;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/ieee1394_core.h linux-libre-2.6.31-gnu/drivers/ieee1394/ieee1394_core.h
--- linux-libre-2.6.30-gnu/drivers/ieee1394/ieee1394_core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/ieee1394_core.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,6 +5,7 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/types.h>
+#include <linux/cdev.h>
 #include <asm/atomic.h>
 
 #include "hosts.h"
@@ -155,7 +156,10 @@
  */
 static inline unsigned char ieee1394_file_to_instance(struct file *file)
 {
-	return file->f_path.dentry->d_inode->i_cindex;
+	int idx = cdev_index(file->f_path.dentry->d_inode);
+	if (idx < 0)
+		idx = 0;
+	return idx;
 }
 
 extern int hpsb_disable_irm;
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/Kconfig linux-libre-2.6.31-gnu/drivers/ieee1394/Kconfig
--- linux-libre-2.6.30-gnu/drivers/ieee1394/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -4,7 +4,7 @@
 source "drivers/firewire/Kconfig"
 
 config IEEE1394
-	tristate "Stable FireWire stack"
+	tristate "Legacy alternative FireWire driver stack"
 	depends on PCI || BROKEN
 	help
 	  IEEE 1394 describes a high performance serial bus, which is also
@@ -33,11 +33,9 @@
 	  module will be called ohci1394.
 
 	  NOTE:
-
-	  You should only build either ohci1394 or the new firewire-ohci driver,
-	  but not both.  If you nevertheless want to install both, you should
-	  configure them only as modules and blacklist the driver(s) which you
-	  don't want to have auto-loaded.  Add either
+	  If you want to install firewire-ohci and ohci1394 together, you
+	  should configure them only as modules and blacklist the driver(s)
+	  which you don't want to have auto-loaded.  Add either
 
 	      blacklist firewire-ohci
 	  or
@@ -46,12 +44,7 @@
 	      blacklist dv1394
 
 	  to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf
-	  depending on your distribution.  The latter two modules should be
-	  blacklisted together with ohci1394 because they depend on ohci1394.
-
-	  If you have an old modprobe which doesn't implement the blacklist
-	  directive, use "install modulename /bin/true" for the modules to be
-	  blacklisted.
+	  depending on your distribution.
 
 comment "PCILynx controller requires I2C"
 	depends on IEEE1394 && I2C=n
@@ -105,7 +98,7 @@
 	default n
 
 config IEEE1394_ETH1394
-	tristate "IP over 1394"
+	tristate "IP networking over 1394 (experimental)"
 	depends on IEEE1394 && EXPERIMENTAL && INET
 	select IEEE1394_ETH1394_ROM_ENTRY
 	help
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/nodemgr.c linux-libre-2.6.31-gnu/drivers/ieee1394/nodemgr.c
--- linux-libre-2.6.30-gnu/drivers/ieee1394/nodemgr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/nodemgr.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/kernel.h>
+#include <linux/kmemcheck.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -39,7 +40,10 @@
 	struct hpsb_host *host;
 	nodeid_t nodeid;
 	unsigned int generation;
+
+	kmemcheck_bitfield_begin(flags);
 	unsigned int speed_unverified:1;
+	kmemcheck_bitfield_end(flags);
 };
 
 
@@ -1293,6 +1297,7 @@
 	u8 *speed;
 
 	ci = kmalloc(sizeof(*ci), GFP_KERNEL);
+	kmemcheck_annotate_bitfield(ci, flags);
 	if (!ci)
 		return;
 
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/sbp2.c linux-libre-2.6.31-gnu/drivers/ieee1394/sbp2.c
--- linux-libre-2.6.30-gnu/drivers/ieee1394/sbp2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/sbp2.c	2009-09-09 18:13:59.000000000 -0400
@@ -718,7 +718,7 @@
 	struct scsi_device *sdev;
 
 	ud = container_of(dev, struct unit_directory, device);
-	lu = ud->device.driver_data;
+	lu = dev_get_drvdata(&ud->device);
 	if (!lu)
 		return 0;
 
@@ -746,7 +746,7 @@
 
 static int sbp2_update(struct unit_directory *ud)
 {
-	struct sbp2_lu *lu = ud->device.driver_data;
+	struct sbp2_lu *lu = dev_get_drvdata(&ud->device);
 
 	if (sbp2_reconnect_device(lu) != 0) {
 		/*
@@ -815,7 +815,7 @@
 	atomic_set(&lu->state, SBP2LU_STATE_RUNNING);
 	INIT_WORK(&lu->protocol_work, NULL);
 
-	ud->device.driver_data = lu;
+	dev_set_drvdata(&ud->device, lu);
 
 	hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
 	if (!hi) {
@@ -880,6 +880,7 @@
 	}
 
 	shost->hostdata[0] = (unsigned long)lu;
+	shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
 
 	if (!scsi_add_host(shost, &ud->device)) {
 		lu->shost = shost;
@@ -1051,7 +1052,7 @@
 		hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
 					  lu->status_fifo_addr);
 
-	lu->ud->device.driver_data = NULL;
+	dev_set_drvdata(&lu->ud->device, NULL);
 
 	module_put(hi->host->driver->owner);
 no_hi:
diff -druN linux-libre-2.6.30-gnu/drivers/ieee1394/sbp2.h linux-libre-2.6.31-gnu/drivers/ieee1394/sbp2.h
--- linux-libre-2.6.30-gnu/drivers/ieee1394/sbp2.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/ieee1394/sbp2.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,12 @@
 #define SBP2_DEVICE_NAME		"sbp2"
 
 /*
+ * There is no transport protocol limit to the CDB length,  but we implement
+ * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
+ */
+#define SBP2_MAX_CDB_SIZE		16
+
+/*
  * SBP-2 specific definitions
  */
 
@@ -51,7 +57,7 @@
 	u32 data_descriptor_hi;
 	u32 data_descriptor_lo;
 	u32 misc;
-	u8 cdb[12];
+	u8 cdb[SBP2_MAX_CDB_SIZE];
 } __attribute__((packed));
 
 #define SBP2_LOGIN_REQUEST		0x0
diff -druN linux-libre-2.6.30-gnu/drivers/ieee802154/fakehard.c linux-libre-2.6.31-gnu/drivers/ieee802154/fakehard.c
--- linux-libre-2.6.30-gnu/drivers/ieee802154/fakehard.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/ieee802154/fakehard.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,270 @@
+/*
+ * Sample driver for HardMAC IEEE 802.15.4 devices
+ *
+ * Copyright (C) 2009 Siemens AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+
+#include <net/ieee802154/af_ieee802154.h>
+#include <net/ieee802154/netdevice.h>
+#include <net/ieee802154/mac_def.h>
+#include <net/ieee802154/nl802154.h>
+
+static u16 fake_get_pan_id(struct net_device *dev)
+{
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return 0xeba1;
+}
+
+static u16 fake_get_short_addr(struct net_device *dev)
+{
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return 0x1;
+}
+
+static u8 fake_get_dsn(struct net_device *dev)
+{
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return 0x00; /* DSN are implemented in HW, so return just 0 */
+}
+
+static u8 fake_get_bsn(struct net_device *dev)
+{
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return 0x00; /* BSN are implemented in HW, so return just 0 */
+}
+
+static int fake_assoc_req(struct net_device *dev,
+		struct ieee802154_addr *addr, u8 channel, u8 cap)
+{
+	/* We simply emulate it here */
+	return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev),
+			IEEE802154_SUCCESS);
+}
+
+static int fake_assoc_resp(struct net_device *dev,
+		struct ieee802154_addr *addr, u16 short_addr, u8 status)
+{
+	return 0;
+}
+
+static int fake_disassoc_req(struct net_device *dev,
+		struct ieee802154_addr *addr, u8 reason)
+{
+	return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS);
+}
+
+static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr,
+				u8 channel,
+				u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
+				u8 coord_realign)
+{
+	return 0;
+}
+
+static int fake_scan_req(struct net_device *dev, u8 type, u32 channels,
+		u8 duration)
+{
+	u8 edl[27] = {};
+	return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type,
+			channels,
+			type == IEEE802154_MAC_SCAN_ED ? edl : NULL);
+}
+
+static struct ieee802154_mlme_ops fake_mlme = {
+	.assoc_req = fake_assoc_req,
+	.assoc_resp = fake_assoc_resp,
+	.disassoc_req = fake_disassoc_req,
+	.start_req = fake_start_req,
+	.scan_req = fake_scan_req,
+
+	.get_pan_id = fake_get_pan_id,
+	.get_short_addr = fake_get_short_addr,
+	.get_dsn = fake_get_dsn,
+	.get_bsn = fake_get_bsn,
+};
+
+static int ieee802154_fake_open(struct net_device *dev)
+{
+	netif_start_queue(dev);
+	return 0;
+}
+
+static int ieee802154_fake_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static int ieee802154_fake_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	skb->iif = dev->ifindex;
+	skb->dev = dev;
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	dev->trans_start = jiffies;
+
+	/* FIXME: do hardware work here ... */
+
+	return 0;
+}
+
+
+static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr,
+		int cmd)
+{
+	struct sockaddr_ieee802154 *sa =
+		(struct sockaddr_ieee802154 *)&ifr->ifr_addr;
+	u16 pan_id, short_addr;
+
+	switch (cmd) {
+	case SIOCGIFADDR:
+		/* FIXME: fixed here, get from device IRL */
+		pan_id = fake_get_pan_id(dev);
+		short_addr = fake_get_short_addr(dev);
+		if (pan_id == IEEE802154_PANID_BROADCAST ||
+		    short_addr == IEEE802154_ADDR_BROADCAST)
+			return -EADDRNOTAVAIL;
+
+		sa->family = AF_IEEE802154;
+		sa->addr.addr_type = IEEE802154_ADDR_SHORT;
+		sa->addr.pan_id = pan_id;
+		sa->addr.short_addr = short_addr;
+		return 0;
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int ieee802154_fake_mac_addr(struct net_device *dev, void *p)
+{
+	return -EBUSY; /* HW address is built into the device */
+}
+
+static const struct net_device_ops fake_ops = {
+	.ndo_open		= ieee802154_fake_open,
+	.ndo_stop		= ieee802154_fake_close,
+	.ndo_start_xmit		= ieee802154_fake_xmit,
+	.ndo_do_ioctl		= ieee802154_fake_ioctl,
+	.ndo_set_mac_address	= ieee802154_fake_mac_addr,
+};
+
+
+static void ieee802154_fake_setup(struct net_device *dev)
+{
+	dev->addr_len		= IEEE802154_ADDR_LEN;
+	memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
+	dev->features		= NETIF_F_NO_CSUM;
+	dev->needed_tailroom	= 2; /* FCS */
+	dev->mtu		= 127;
+	dev->tx_queue_len	= 10;
+	dev->type		= ARPHRD_IEEE802154;
+	dev->flags		= IFF_NOARP | IFF_BROADCAST;
+	dev->watchdog_timeo	= 0;
+}
+
+
+static int __devinit ieee802154fake_probe(struct platform_device *pdev)
+{
+	struct net_device *dev =
+		alloc_netdev(0, "hardwpan%d", ieee802154_fake_setup);
+	int err;
+
+	if (!dev)
+		return -ENOMEM;
+
+	memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
+			dev->addr_len);
+	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+	dev->netdev_ops = &fake_ops;
+	dev->ml_priv = &fake_mlme;
+
+	/*
+	 * If the name is a format string the caller wants us to do a
+	 * name allocation.
+	 */
+	if (strchr(dev->name, '%')) {
+		err = dev_alloc_name(dev, dev->name);
+		if (err < 0)
+			goto out;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	platform_set_drvdata(pdev, dev);
+
+	err = register_netdev(dev);
+	if (err < 0)
+		goto out;
+
+
+	dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n");
+	return 0;
+
+out:
+	unregister_netdev(dev);
+	return err;
+}
+
+static int __devexit ieee802154fake_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	unregister_netdev(dev);
+	free_netdev(dev);
+	return 0;
+}
+
+static struct platform_device *ieee802154fake_dev;
+
+static struct platform_driver ieee802154fake_driver = {
+	.probe = ieee802154fake_probe,
+	.remove = __devexit_p(ieee802154fake_remove),
+	.driver = {
+			.name = "ieee802154hardmac",
+			.owner = THIS_MODULE,
+	},
+};
+
+static __init int fake_init(void)
+{
+	ieee802154fake_dev = platform_device_register_simple(
+			"ieee802154hardmac", -1, NULL, 0);
+	return platform_driver_register(&ieee802154fake_driver);
+}
+
+static __exit void fake_exit(void)
+{
+	platform_driver_unregister(&ieee802154fake_driver);
+	platform_device_unregister(ieee802154fake_dev);
+}
+
+module_init(fake_init);
+module_exit(fake_exit);
+MODULE_LICENSE("GPL");
+
diff -druN linux-libre-2.6.30-gnu/drivers/ieee802154/Kconfig linux-libre-2.6.31-gnu/drivers/ieee802154/Kconfig
--- linux-libre-2.6.30-gnu/drivers/ieee802154/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/ieee802154/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+menuconfig IEEE802154_DRIVERS
+	tristate "IEEE 802.15.4 drivers"
+	depends on NETDEVICES && IEEE802154
+	default y
+	---help---
+	  Say Y here to get to see options for IEEE 802.15.4 Low-Rate
+	  Wireless Personal Area Network device drivers. This option alone
+	  does not add any kernel code.
+
+	  If you say N, all options in this submenu will be skipped and
+	  disabled.
+
+config IEEE802154_FAKEHARD
+	tristate "Fake LR-WPAN driver with several interconnected devices"
+	depends on  IEEE802154_DRIVERS
+	---help---
+	  Say Y here to enable the fake driver that serves as an example
+          of HardMAC device driver.
+
+          This driver can also be built as a module. To do so say M here.
+	  The module will be called 'fakehard'.
+
diff -druN linux-libre-2.6.30-gnu/drivers/ieee802154/Makefile linux-libre-2.6.31-gnu/drivers/ieee802154/Makefile
--- linux-libre-2.6.30-gnu/drivers/ieee802154/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/ieee802154/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3 @@
+obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
+
+EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/core/addr.c linux-libre-2.6.31-gnu/drivers/infiniband/core/addr.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/core/addr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/core/addr.c	2009-09-09 18:13:59.000000000 -0400
@@ -514,7 +514,7 @@
 	.notifier_call = netevent_callback
 };
 
-static int addr_init(void)
+static int __init addr_init(void)
 {
 	addr_wq = create_singlethread_workqueue("ib_addr");
 	if (!addr_wq)
@@ -524,7 +524,7 @@
 	return 0;
 }
 
-static void addr_cleanup(void)
+static void __exit addr_cleanup(void)
 {
 	unregister_netevent_notifier(&nb);
 	destroy_workqueue(addr_wq);
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/core/cma.c linux-libre-2.6.31-gnu/drivers/infiniband/core/cma.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/core/cma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/core/cma.c	2009-09-09 18:13:59.000000000 -0400
@@ -2960,7 +2960,7 @@
 	kfree(cma_dev);
 }
 
-static int cma_init(void)
+static int __init cma_init(void)
 {
 	int ret, low, high, remaining;
 
@@ -2990,7 +2990,7 @@
 	return ret;
 }
 
-static void cma_cleanup(void)
+static void __exit cma_cleanup(void)
 {
 	ib_unregister_client(&cma_client);
 	unregister_netdevice_notifier(&cma_nb);
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/core/sysfs.c linux-libre-2.6.31-gnu/drivers/infiniband/core/sysfs.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/core/sysfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/core/sysfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -760,9 +760,9 @@
 	int i;
 
 	class_dev->class      = &ib_class;
-	class_dev->driver_data = device;
 	class_dev->parent     = device->dma_device;
 	dev_set_name(class_dev, device->name);
+	dev_set_drvdata(class_dev, device);
 
 	INIT_LIST_HEAD(&device->port_list);
 
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/amso1100/c2_cq.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/amso1100/c2_cq.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/amso1100/c2_cq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/amso1100/c2_cq.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,7 +133,7 @@
 	struct c2_qp *qp;
 	int is_recv = 0;
 
-	ce = (struct c2wr_ce *) c2_mq_consume(&cq->mq);
+	ce = c2_mq_consume(&cq->mq);
 	if (!ce) {
 		return -EAGAIN;
 	}
@@ -146,7 +146,7 @@
 	while ((qp =
 		(struct c2_qp *) (unsigned long) ce->qp_user_context) == NULL) {
 		c2_mq_free(&cq->mq);
-		ce = (struct c2wr_ce *) c2_mq_consume(&cq->mq);
+		ce = c2_mq_consume(&cq->mq);
 		if (!ce)
 			return -EAGAIN;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/cxgb3/cxio_wr.h linux-libre-2.6.31-gnu/drivers/infiniband/hw/cxgb3/cxio_wr.h
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/cxgb3/cxio_wr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/cxgb3/cxio_wr.h	2009-09-09 18:13:59.000000000 -0400
@@ -176,7 +176,7 @@
 	struct t3_sge sgl[T3_MAX_SGE];	/* 4+ */
 };
 
-#define T3_MAX_FASTREG_DEPTH 24
+#define T3_MAX_FASTREG_DEPTH 10
 #define T3_MAX_FASTREG_FRAG 10
 
 struct t3_fastreg_wr {
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,6 +40,7 @@
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
+#include <linux/inetdevice.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -1152,12 +1153,39 @@
 static int iwch_query_port(struct ib_device *ibdev,
 			   u8 port, struct ib_port_attr *props)
 {
+	struct iwch_dev *dev;
+	struct net_device *netdev;
+	struct in_device *inetdev;
+
 	PDBG("%s ibdev %p\n", __func__, ibdev);
 
+	dev = to_iwch_dev(ibdev);
+	netdev = dev->rdev.port_info.lldevs[port-1];
+
 	memset(props, 0, sizeof(struct ib_port_attr));
 	props->max_mtu = IB_MTU_4096;
-	props->active_mtu = IB_MTU_2048;
-	props->state = IB_PORT_ACTIVE;
+	if (netdev->mtu >= 4096)
+		props->active_mtu = IB_MTU_4096;
+	else if (netdev->mtu >= 2048)
+		props->active_mtu = IB_MTU_2048;
+	else if (netdev->mtu >= 1024)
+		props->active_mtu = IB_MTU_1024;
+	else if (netdev->mtu >= 512)
+		props->active_mtu = IB_MTU_512;
+	else
+		props->active_mtu = IB_MTU_256;
+
+	if (!netif_carrier_ok(netdev))
+		props->state = IB_PORT_DOWN;
+	else {
+		inetdev = in_dev_get(netdev);
+		if (inetdev->ifa_list)
+			props->state = IB_PORT_ACTIVE;
+		else
+			props->state = IB_PORT_INIT;
+		in_dev_put(inetdev);
+	}
+
 	props->port_cap_flags =
 	    IB_PORT_CM_SUP |
 	    IB_PORT_SNMP_TUNNEL_SUP |
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h	2009-09-09 18:13:59.000000000 -0400
@@ -165,7 +165,6 @@
 #define MQPCB_MASK_ALT_P_KEY_IDX                EHCA_BMASK_IBM( 7,  7)
 #define MQPCB_MASK_RDMA_ATOMIC_CTRL             EHCA_BMASK_IBM( 8,  8)
 #define MQPCB_MASK_QP_STATE                     EHCA_BMASK_IBM( 9,  9)
-#define MQPCB_QP_STATE                          EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES      EHCA_BMASK_IBM(11, 11)
 #define MQPCB_MASK_PATH_MIGRATION_STATE         EHCA_BMASK_IBM(12, 12)
 #define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP    EHCA_BMASK_IBM(13, 13)
@@ -176,60 +175,33 @@
 #define MQPCB_MASK_RETRY_COUNT                  EHCA_BMASK_IBM(18, 18)
 #define MQPCB_MASK_TIMEOUT                      EHCA_BMASK_IBM(19, 19)
 #define MQPCB_MASK_PATH_MTU                     EHCA_BMASK_IBM(20, 20)
-#define MQPCB_PATH_MTU                          EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_MAX_STATIC_RATE              EHCA_BMASK_IBM(21, 21)
-#define MQPCB_MAX_STATIC_RATE                   EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_DLID                         EHCA_BMASK_IBM(22, 22)
-#define MQPCB_DLID                              EHCA_BMASK_IBM(16, 31)
 #define MQPCB_MASK_RNR_RETRY_COUNT              EHCA_BMASK_IBM(23, 23)
-#define MQPCB_RNR_RETRY_COUNT                   EHCA_BMASK_IBM(29, 31)
 #define MQPCB_MASK_SOURCE_PATH_BITS             EHCA_BMASK_IBM(24, 24)
-#define MQPCB_SOURCE_PATH_BITS                  EHCA_BMASK_IBM(25, 31)
 #define MQPCB_MASK_TRAFFIC_CLASS                EHCA_BMASK_IBM(25, 25)
-#define MQPCB_TRAFFIC_CLASS                     EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_HOP_LIMIT                    EHCA_BMASK_IBM(26, 26)
-#define MQPCB_HOP_LIMIT                         EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_SOURCE_GID_IDX               EHCA_BMASK_IBM(27, 27)
-#define MQPCB_SOURCE_GID_IDX                    EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_FLOW_LABEL                   EHCA_BMASK_IBM(28, 28)
-#define MQPCB_FLOW_LABEL                        EHCA_BMASK_IBM(12, 31)
 #define MQPCB_MASK_DEST_GID                     EHCA_BMASK_IBM(30, 30)
 #define MQPCB_MASK_SERVICE_LEVEL_AL             EHCA_BMASK_IBM(31, 31)
-#define MQPCB_SERVICE_LEVEL_AL                  EHCA_BMASK_IBM(28, 31)
 #define MQPCB_MASK_SEND_GRH_FLAG_AL             EHCA_BMASK_IBM(32, 32)
-#define MQPCB_SEND_GRH_FLAG_AL                  EHCA_BMASK_IBM(31, 31)
 #define MQPCB_MASK_RETRY_COUNT_AL               EHCA_BMASK_IBM(33, 33)
-#define MQPCB_RETRY_COUNT_AL                    EHCA_BMASK_IBM(29, 31)
 #define MQPCB_MASK_TIMEOUT_AL                   EHCA_BMASK_IBM(34, 34)
-#define MQPCB_TIMEOUT_AL                        EHCA_BMASK_IBM(27, 31)
 #define MQPCB_MASK_MAX_STATIC_RATE_AL           EHCA_BMASK_IBM(35, 35)
-#define MQPCB_MAX_STATIC_RATE_AL                EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_DLID_AL                      EHCA_BMASK_IBM(36, 36)
-#define MQPCB_DLID_AL                           EHCA_BMASK_IBM(16, 31)
 #define MQPCB_MASK_RNR_RETRY_COUNT_AL           EHCA_BMASK_IBM(37, 37)
-#define MQPCB_RNR_RETRY_COUNT_AL                EHCA_BMASK_IBM(29, 31)
 #define MQPCB_MASK_SOURCE_PATH_BITS_AL          EHCA_BMASK_IBM(38, 38)
-#define MQPCB_SOURCE_PATH_BITS_AL               EHCA_BMASK_IBM(25, 31)
 #define MQPCB_MASK_TRAFFIC_CLASS_AL             EHCA_BMASK_IBM(39, 39)
-#define MQPCB_TRAFFIC_CLASS_AL                  EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_HOP_LIMIT_AL                 EHCA_BMASK_IBM(40, 40)
-#define MQPCB_HOP_LIMIT_AL                      EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_SOURCE_GID_IDX_AL            EHCA_BMASK_IBM(41, 41)
-#define MQPCB_SOURCE_GID_IDX_AL                 EHCA_BMASK_IBM(24, 31)
 #define MQPCB_MASK_FLOW_LABEL_AL                EHCA_BMASK_IBM(42, 42)
-#define MQPCB_FLOW_LABEL_AL                     EHCA_BMASK_IBM(12, 31)
 #define MQPCB_MASK_DEST_GID_AL                  EHCA_BMASK_IBM(44, 44)
 #define MQPCB_MASK_MAX_NR_OUTST_SEND_WR         EHCA_BMASK_IBM(45, 45)
-#define MQPCB_MAX_NR_OUTST_SEND_WR              EHCA_BMASK_IBM(16, 31)
 #define MQPCB_MASK_MAX_NR_OUTST_RECV_WR         EHCA_BMASK_IBM(46, 46)
-#define MQPCB_MAX_NR_OUTST_RECV_WR              EHCA_BMASK_IBM(16, 31)
 #define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK     EHCA_BMASK_IBM(47, 47)
-#define MQPCB_DISABLE_ETE_CREDIT_CHECK          EHCA_BMASK_IBM(31, 31)
-#define MQPCB_QP_NUMBER                         EHCA_BMASK_IBM( 8, 31)
 #define MQPCB_MASK_QP_ENABLE                    EHCA_BMASK_IBM(48, 48)
-#define MQPCB_QP_ENABLE                         EHCA_BMASK_IBM(31, 31)
 #define MQPCB_MASK_CURR_SRQ_LIMIT               EHCA_BMASK_IBM(49, 49)
-#define MQPCB_CURR_SRQ_LIMIT                    EHCA_BMASK_IBM(16, 31)
 #define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG       EHCA_BMASK_IBM(50, 50)
 #define MQPCB_MASK_SHARED_RQ_HNDL               EHCA_BMASK_IBM(51, 51)
 
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_hca.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_hca.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_hca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_hca.c	2009-09-09 18:13:59.000000000 -0400
@@ -319,7 +319,7 @@
 					      ib_device);
 	struct hipz_query_port *rblock;
 
-	if (index > 255) {
+	if (index < 0 || index > 255) {
 		ehca_err(&shca->ib_device, "Invalid index: %x.", index);
 		return -EINVAL;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_irq.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_irq.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -479,13 +479,13 @@
 	struct ehca_eqe *eqe;
 	u64 ret;
 
-	eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq);
+	eqe = ehca_poll_eq(shca, &shca->neq);
 
 	while (eqe) {
 		if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry))
 			parse_ec(shca, eqe->entry);
 
-		eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq);
+		eqe = ehca_poll_eq(shca, &shca->neq);
 	}
 
 	ret = hipz_h_reset_event(shca->ipz_hca_handle,
@@ -572,8 +572,7 @@
 	eqe_cnt = 0;
 	do {
 		u32 token;
-		eqe_cache[eqe_cnt].eqe =
-			(struct ehca_eqe *)ehca_poll_eq(shca, eq);
+		eqe_cache[eqe_cnt].eqe = ehca_poll_eq(shca, eq);
 		if (!eqe_cache[eqe_cnt].eqe)
 			break;
 		eqe_value = eqe_cache[eqe_cnt].eqe->entry;
@@ -637,7 +636,7 @@
 		goto unlock_irq_spinlock;
 	do {
 		struct ehca_eqe *eqe;
-		eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+		eqe = ehca_poll_eq(shca, &shca->eq);
 		if (!eqe)
 			break;
 		process_eqe(shca, eqe);
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_main.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_main.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,7 +52,7 @@
 #include "ehca_tools.h"
 #include "hcp_if.h"
 
-#define HCAD_VERSION "0026"
+#define HCAD_VERSION "0028"
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
@@ -506,6 +506,7 @@
 	shca->ib_device.detach_mcast	    = ehca_detach_mcast;
 	shca->ib_device.process_mad	    = ehca_process_mad;
 	shca->ib_device.mmap		    = ehca_mmap;
+	shca->ib_device.dma_ops		    = &ehca_dma_mapping_ops;
 
 	if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
 		shca->ib_device.uverbs_cmd_mask |=
@@ -636,7 +637,7 @@
 	struct hipz_query_hca *rblock;				           \
 	int data;                                                          \
 									   \
-	shca = dev->driver_data;					   \
+	shca = dev_get_drvdata(dev);					   \
 									   \
 	rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);			   \
 	if (!rblock) {						           \
@@ -680,7 +681,7 @@
 					struct device_attribute *attr,
 					char *buf)
 {
-	struct ehca_shca *shca = dev->driver_data;
+	struct ehca_shca *shca = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%llx\n", shca->ipz_hca_handle.handle);
 
@@ -749,7 +750,7 @@
 
 	shca->ofdev = dev;
 	shca->ipz_hca_handle.handle = *handle;
-	dev->dev.driver_data = shca;
+	dev_set_drvdata(&dev->dev, shca);
 
 	ret = ehca_sense_attributes(shca);
 	if (ret < 0) {
@@ -878,7 +879,7 @@
 
 static int __devexit ehca_remove(struct of_device *dev)
 {
-	struct ehca_shca *shca = dev->dev.driver_data;
+	struct ehca_shca *shca = dev_get_drvdata(&dev->dev);
 	unsigned long flags;
 	int ret;
 
@@ -1028,17 +1029,23 @@
 		goto module_init1;
 	}
 
+	ret = ehca_create_busmap();
+	if (ret) {
+		ehca_gen_err("Cannot create busmap.");
+		goto module_init2;
+	}
+
 	ret = ibmebus_register_driver(&ehca_driver);
 	if (ret) {
 		ehca_gen_err("Cannot register eHCA device driver");
 		ret = -EINVAL;
-		goto module_init2;
+		goto module_init3;
 	}
 
 	ret = register_memory_notifier(&ehca_mem_nb);
 	if (ret) {
 		ehca_gen_err("Failed registering memory add/remove notifier");
-		goto module_init3;
+		goto module_init4;
 	}
 
 	if (ehca_poll_all_eqs != 1) {
@@ -1053,9 +1060,12 @@
 
 	return 0;
 
-module_init3:
+module_init4:
 	ibmebus_unregister_driver(&ehca_driver);
 
+module_init3:
+	ehca_destroy_busmap();
+
 module_init2:
 	ehca_destroy_slab_caches();
 
@@ -1073,6 +1083,8 @@
 
 	unregister_memory_notifier(&ehca_mem_nb);
 
+	ehca_destroy_busmap();
+
 	ehca_destroy_slab_caches();
 
 	ehca_destroy_comp_pool();
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,38 @@
 /* max number of rpages (per hcall register_rpages) */
 #define MAX_RPAGES 512
 
+/* DMEM toleration management */
+#define EHCA_SECTSHIFT        SECTION_SIZE_BITS
+#define EHCA_SECTSIZE          (1UL << EHCA_SECTSHIFT)
+#define EHCA_HUGEPAGESHIFT     34
+#define EHCA_HUGEPAGE_SIZE     (1UL << EHCA_HUGEPAGESHIFT)
+#define EHCA_HUGEPAGE_PFN_MASK ((EHCA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT)
+#define EHCA_INVAL_ADDR        0xFFFFFFFFFFFFFFFFULL
+#define EHCA_DIR_INDEX_SHIFT 13                   /* 8k Entries in 64k block */
+#define EHCA_TOP_INDEX_SHIFT (EHCA_DIR_INDEX_SHIFT * 2)
+#define EHCA_MAP_ENTRIES (1 << EHCA_DIR_INDEX_SHIFT)
+#define EHCA_TOP_MAP_SIZE (0x10000)               /* currently fixed map size */
+#define EHCA_DIR_MAP_SIZE (0x10000)
+#define EHCA_ENT_MAP_SIZE (0x10000)
+#define EHCA_INDEX_MASK (EHCA_MAP_ENTRIES - 1)
+
+static unsigned long ehca_mr_len;
+
+/*
+ * Memory map data structures
+ */
+struct ehca_dir_bmap {
+	u64 ent[EHCA_MAP_ENTRIES];
+};
+struct ehca_top_bmap {
+	struct ehca_dir_bmap *dir[EHCA_MAP_ENTRIES];
+};
+struct ehca_bmap {
+	struct ehca_top_bmap *top[EHCA_MAP_ENTRIES];
+};
+
+static struct ehca_bmap *ehca_bmap;
+
 static struct kmem_cache *mr_cache;
 static struct kmem_cache *mw_cache;
 
@@ -68,6 +100,8 @@
 #define EHCA_MR_PGSHIFT1M  20
 #define EHCA_MR_PGSHIFT16M 24
 
+static u64 ehca_map_vaddr(void *caddr);
+
 static u32 ehca_encode_hwpage_size(u32 pgsize)
 {
 	int log = ilog2(pgsize);
@@ -135,7 +169,8 @@
 			goto get_dma_mr_exit0;
 		}
 
-		ret = ehca_reg_maxmr(shca, e_maxmr, (u64 *)KERNELBASE,
+		ret = ehca_reg_maxmr(shca, e_maxmr,
+				     (void *)ehca_map_vaddr((void *)KERNELBASE),
 				     mr_access_flags, e_pd,
 				     &e_maxmr->ib.ib_mr.lkey,
 				     &e_maxmr->ib.ib_mr.rkey);
@@ -251,7 +286,7 @@
 
 		ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
 				  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
-				  &e_mr->ib.ib_mr.rkey);
+				  &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
 		if (ret) {
 			ib_mr = ERR_PTR(ret);
 			goto reg_phys_mr_exit1;
@@ -370,7 +405,7 @@
 
 	ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
 			  e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
-			  &e_mr->ib.ib_mr.rkey);
+			  &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
 	if (ret == -EINVAL && pginfo.hwpage_size > PAGE_SIZE) {
 		ehca_warn(pd->device, "failed to register mr "
 			  "with hwpage_size=%llx", hwpage_size);
@@ -794,7 +829,7 @@
 	ret = ehca_reg_mr(shca, e_fmr, NULL,
 			  fmr_attr->max_pages * (1 << fmr_attr->page_shift),
 			  mr_access_flags, e_pd, &pginfo,
-			  &tmp_lkey, &tmp_rkey);
+			  &tmp_lkey, &tmp_rkey, EHCA_REG_MR);
 	if (ret) {
 		ib_fmr = ERR_PTR(ret);
 		goto alloc_fmr_exit1;
@@ -983,6 +1018,10 @@
 
 /*----------------------------------------------------------------------*/
 
+static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
+				   struct ehca_mr *e_mr,
+				   struct ehca_mr_pginfo *pginfo);
+
 int ehca_reg_mr(struct ehca_shca *shca,
 		struct ehca_mr *e_mr,
 		u64 *iova_start,
@@ -991,7 +1030,8 @@
 		struct ehca_pd *e_pd,
 		struct ehca_mr_pginfo *pginfo,
 		u32 *lkey, /*OUT*/
-		u32 *rkey) /*OUT*/
+		u32 *rkey, /*OUT*/
+		enum ehca_reg_type reg_type)
 {
 	int ret;
 	u64 h_ret;
@@ -1015,7 +1055,13 @@
 
 	e_mr->ipz_mr_handle = hipzout.handle;
 
-	ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
+	if (reg_type == EHCA_REG_BUSMAP_MR)
+		ret = ehca_reg_bmap_mr_rpages(shca, e_mr, pginfo);
+	else if (reg_type == EHCA_REG_MR)
+		ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
+	else
+		ret = -EINVAL;
+
 	if (ret)
 		goto ehca_reg_mr_exit1;
 
@@ -1316,7 +1362,7 @@
 		e_mr->fmr_map_cnt = save_mr.fmr_map_cnt;
 
 		ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl,
-				  e_pd, pginfo, lkey, rkey);
+				  e_pd, pginfo, lkey, rkey, EHCA_REG_MR);
 		if (ret) {
 			u32 offset = (u64)(&e_mr->flags) - (u64)e_mr;
 			memcpy(&e_mr->flags, &(save_mr.flags),
@@ -1409,7 +1455,7 @@
 	ret = ehca_reg_mr(shca, e_fmr, NULL,
 			  (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
 			  e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
-			  &tmp_rkey);
+			  &tmp_rkey, EHCA_REG_MR);
 	if (ret) {
 		u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr;
 		memcpy(&e_fmr->flags, &(save_mr.flags),
@@ -1478,6 +1524,90 @@
 } /* end ehca_reg_smr() */
 
 /*----------------------------------------------------------------------*/
+static inline void *ehca_calc_sectbase(int top, int dir, int idx)
+{
+	unsigned long ret = idx;
+	ret |= dir << EHCA_DIR_INDEX_SHIFT;
+	ret |= top << EHCA_TOP_INDEX_SHIFT;
+	return abs_to_virt(ret << SECTION_SIZE_BITS);
+}
+
+#define ehca_bmap_valid(entry) \
+	((u64)entry != (u64)EHCA_INVAL_ADDR)
+
+static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
+			       struct ehca_shca *shca, struct ehca_mr *mr,
+			       struct ehca_mr_pginfo *pginfo)
+{
+	u64 h_ret = 0;
+	unsigned long page = 0;
+	u64 rpage = virt_to_abs(kpage);
+	int page_count;
+
+	void *sectbase = ehca_calc_sectbase(top, dir, idx);
+	if ((unsigned long)sectbase & (pginfo->hwpage_size - 1)) {
+		ehca_err(&shca->ib_device, "reg_mr_section will probably fail:"
+					   "hwpage_size does not fit to "
+					   "section start address");
+	}
+	page_count = EHCA_SECTSIZE / pginfo->hwpage_size;
+
+	while (page < page_count) {
+		u64 rnum;
+		for (rnum = 0; (rnum < MAX_RPAGES) && (page < page_count);
+		     rnum++) {
+			void *pg = sectbase + ((page++) * pginfo->hwpage_size);
+			kpage[rnum] = virt_to_abs(pg);
+		}
+
+		h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, mr,
+			ehca_encode_hwpage_size(pginfo->hwpage_size),
+			0, rpage, rnum);
+
+		if ((h_ret != H_SUCCESS) && (h_ret != H_PAGE_REGISTERED)) {
+			ehca_err(&shca->ib_device, "register_rpage_mr failed");
+			return h_ret;
+		}
+	}
+	return h_ret;
+}
+
+static u64 ehca_reg_mr_sections(int top, int dir, u64 *kpage,
+				struct ehca_shca *shca, struct ehca_mr *mr,
+				struct ehca_mr_pginfo *pginfo)
+{
+	u64 hret = H_SUCCESS;
+	int idx;
+
+	for (idx = 0; idx < EHCA_MAP_ENTRIES; idx++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]->ent[idx]))
+			continue;
+
+		hret = ehca_reg_mr_section(top, dir, idx, kpage, shca, mr,
+					   pginfo);
+		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
+				return hret;
+	}
+	return hret;
+}
+
+static u64 ehca_reg_mr_dir_sections(int top, u64 *kpage, struct ehca_shca *shca,
+				    struct ehca_mr *mr,
+				    struct ehca_mr_pginfo *pginfo)
+{
+	u64 hret = H_SUCCESS;
+	int dir;
+
+	for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+			continue;
+
+		hret = ehca_reg_mr_sections(top, dir, kpage, shca, mr, pginfo);
+		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
+				return hret;
+	}
+	return hret;
+}
 
 /* register internal max-MR to internal SHCA */
 int ehca_reg_internal_maxmr(
@@ -1495,6 +1625,11 @@
 	u32 num_hwpages;
 	u64 hw_pgsize;
 
+	if (!ehca_bmap) {
+		ret = -EFAULT;
+		goto ehca_reg_internal_maxmr_exit0;
+	}
+
 	e_mr = ehca_mr_new();
 	if (!e_mr) {
 		ehca_err(&shca->ib_device, "out of memory");
@@ -1504,8 +1639,8 @@
 	e_mr->flags |= EHCA_MR_FLAG_MAXMR;
 
 	/* register internal max-MR on HCA */
-	size_maxmr = (u64)high_memory - PAGE_OFFSET;
-	iova_start = (u64 *)KERNELBASE;
+	size_maxmr = ehca_mr_len;
+	iova_start = (u64 *)ehca_map_vaddr((void *)KERNELBASE);
 	ib_pbuf.addr = 0;
 	ib_pbuf.size = size_maxmr;
 	num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
@@ -1524,7 +1659,7 @@
 
 	ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd,
 			  &pginfo, &e_mr->ib.ib_mr.lkey,
-			  &e_mr->ib.ib_mr.rkey);
+			  &e_mr->ib.ib_mr.rkey, EHCA_REG_BUSMAP_MR);
 	if (ret) {
 		ehca_err(&shca->ib_device, "reg of internal max MR failed, "
 			 "e_mr=%p iova_start=%p size_maxmr=%llx num_kpages=%x "
@@ -2077,8 +2212,8 @@
 		     u64 *iova_start)
 {
 	/* a MR is treated as max-MR only if it fits following: */
-	if ((size == ((u64)high_memory - PAGE_OFFSET)) &&
-	    (iova_start == (void *)KERNELBASE)) {
+	if ((size == ehca_mr_len) &&
+	    (iova_start == (void *)ehca_map_vaddr((void *)KERNELBASE))) {
 		ehca_gen_dbg("this is a max-MR");
 		return 1;
 	} else
@@ -2184,3 +2319,350 @@
 	if (mw_cache)
 		kmem_cache_destroy(mw_cache);
 }
+
+static inline int ehca_init_top_bmap(struct ehca_top_bmap *ehca_top_bmap,
+				     int dir)
+{
+	if (!ehca_bmap_valid(ehca_top_bmap->dir[dir])) {
+		ehca_top_bmap->dir[dir] =
+			kmalloc(sizeof(struct ehca_dir_bmap), GFP_KERNEL);
+		if (!ehca_top_bmap->dir[dir])
+			return -ENOMEM;
+		/* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+		memset(ehca_top_bmap->dir[dir], 0xFF, EHCA_ENT_MAP_SIZE);
+	}
+	return 0;
+}
+
+static inline int ehca_init_bmap(struct ehca_bmap *ehca_bmap, int top, int dir)
+{
+	if (!ehca_bmap_valid(ehca_bmap->top[top])) {
+		ehca_bmap->top[top] =
+			kmalloc(sizeof(struct ehca_top_bmap), GFP_KERNEL);
+		if (!ehca_bmap->top[top])
+			return -ENOMEM;
+		/* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+		memset(ehca_bmap->top[top], 0xFF, EHCA_DIR_MAP_SIZE);
+	}
+	return ehca_init_top_bmap(ehca_bmap->top[top], dir);
+}
+
+static inline int ehca_calc_index(unsigned long i, unsigned long s)
+{
+	return (i >> s) & EHCA_INDEX_MASK;
+}
+
+void ehca_destroy_busmap(void)
+{
+	int top, dir;
+
+	if (!ehca_bmap)
+		return;
+
+	for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]))
+			continue;
+		for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
+			if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+				continue;
+
+			kfree(ehca_bmap->top[top]->dir[dir]);
+		}
+
+		kfree(ehca_bmap->top[top]);
+	}
+
+	kfree(ehca_bmap);
+	ehca_bmap = NULL;
+}
+
+static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages)
+{
+	unsigned long i, start_section, end_section;
+	int top, dir, idx;
+
+	if (!nr_pages)
+		return 0;
+
+	if (!ehca_bmap) {
+		ehca_bmap = kmalloc(sizeof(struct ehca_bmap), GFP_KERNEL);
+		if (!ehca_bmap)
+			return -ENOMEM;
+		/* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+		memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE);
+	}
+
+	start_section = phys_to_abs(pfn * PAGE_SIZE) / EHCA_SECTSIZE;
+	end_section = phys_to_abs((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
+	for (i = start_section; i < end_section; i++) {
+		int ret;
+		top = ehca_calc_index(i, EHCA_TOP_INDEX_SHIFT);
+		dir = ehca_calc_index(i, EHCA_DIR_INDEX_SHIFT);
+		idx = i & EHCA_INDEX_MASK;
+
+		ret = ehca_init_bmap(ehca_bmap, top, dir);
+		if (ret) {
+			ehca_destroy_busmap();
+			return ret;
+		}
+		ehca_bmap->top[top]->dir[dir]->ent[idx] = ehca_mr_len;
+		ehca_mr_len += EHCA_SECTSIZE;
+	}
+	return 0;
+}
+
+static int ehca_is_hugepage(unsigned long pfn)
+{
+	int page_order;
+
+	if (pfn & EHCA_HUGEPAGE_PFN_MASK)
+		return 0;
+
+	page_order = compound_order(pfn_to_page(pfn));
+	if (page_order + PAGE_SHIFT != EHCA_HUGEPAGESHIFT)
+		return 0;
+
+	return 1;
+}
+
+static int ehca_create_busmap_callback(unsigned long initial_pfn,
+				       unsigned long total_nr_pages, void *arg)
+{
+	int ret;
+	unsigned long pfn, start_pfn, end_pfn, nr_pages;
+
+	if ((total_nr_pages * PAGE_SIZE) < EHCA_HUGEPAGE_SIZE)
+		return ehca_update_busmap(initial_pfn, total_nr_pages);
+
+	/* Given chunk is >= 16GB -> check for hugepages */
+	start_pfn = initial_pfn;
+	end_pfn = initial_pfn + total_nr_pages;
+	pfn = start_pfn;
+
+	while (pfn < end_pfn) {
+		if (ehca_is_hugepage(pfn)) {
+			/* Add mem found in front of the hugepage */
+			nr_pages = pfn - start_pfn;
+			ret = ehca_update_busmap(start_pfn, nr_pages);
+			if (ret)
+				return ret;
+			/* Skip the hugepage */
+			pfn += (EHCA_HUGEPAGE_SIZE / PAGE_SIZE);
+			start_pfn = pfn;
+		} else
+			pfn += (EHCA_SECTSIZE / PAGE_SIZE);
+	}
+
+	/* Add mem found behind the hugepage(s)  */
+	nr_pages = pfn - start_pfn;
+	return ehca_update_busmap(start_pfn, nr_pages);
+}
+
+int ehca_create_busmap(void)
+{
+	int ret;
+
+	ehca_mr_len = 0;
+	ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
+				   ehca_create_busmap_callback);
+	return ret;
+}
+
+static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
+				   struct ehca_mr *e_mr,
+				   struct ehca_mr_pginfo *pginfo)
+{
+	int top;
+	u64 hret, *kpage;
+
+	kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+	if (!kpage) {
+		ehca_err(&shca->ib_device, "kpage alloc failed");
+		return -ENOMEM;
+	}
+	for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
+		if (!ehca_bmap_valid(ehca_bmap->top[top]))
+			continue;
+		hret = ehca_reg_mr_dir_sections(top, kpage, shca, e_mr, pginfo);
+		if ((hret != H_PAGE_REGISTERED) && (hret != H_SUCCESS))
+			break;
+	}
+
+	ehca_free_fw_ctrlblock(kpage);
+
+	if (hret == H_SUCCESS)
+		return 0; /* Everything is fine */
+	else {
+		ehca_err(&shca->ib_device, "ehca_reg_bmap_mr_rpages failed, "
+				 "h_ret=%lli e_mr=%p top=%x lkey=%x "
+				 "hca_hndl=%llx mr_hndl=%llx", hret, e_mr, top,
+				 e_mr->ib.ib_mr.lkey,
+				 shca->ipz_hca_handle.handle,
+				 e_mr->ipz_mr_handle.handle);
+		return ehca2ib_return_code(hret);
+	}
+}
+
+static u64 ehca_map_vaddr(void *caddr)
+{
+	int top, dir, idx;
+	unsigned long abs_addr, offset;
+	u64 entry;
+
+	if (!ehca_bmap)
+		return EHCA_INVAL_ADDR;
+
+	abs_addr = virt_to_abs(caddr);
+	top = ehca_calc_index(abs_addr, EHCA_TOP_INDEX_SHIFT + EHCA_SECTSHIFT);
+	if (!ehca_bmap_valid(ehca_bmap->top[top]))
+		return EHCA_INVAL_ADDR;
+
+	dir = ehca_calc_index(abs_addr, EHCA_DIR_INDEX_SHIFT + EHCA_SECTSHIFT);
+	if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+		return EHCA_INVAL_ADDR;
+
+	idx = ehca_calc_index(abs_addr, EHCA_SECTSHIFT);
+
+	entry = ehca_bmap->top[top]->dir[dir]->ent[idx];
+	if (ehca_bmap_valid(entry)) {
+		offset = (unsigned long)caddr & (EHCA_SECTSIZE - 1);
+		return entry | offset;
+	} else
+		return EHCA_INVAL_ADDR;
+}
+
+static int ehca_dma_mapping_error(struct ib_device *dev, u64 dma_addr)
+{
+	return dma_addr == EHCA_INVAL_ADDR;
+}
+
+static u64 ehca_dma_map_single(struct ib_device *dev, void *cpu_addr,
+			       size_t size, enum dma_data_direction direction)
+{
+	if (cpu_addr)
+		return ehca_map_vaddr(cpu_addr);
+	else
+		return EHCA_INVAL_ADDR;
+}
+
+static void ehca_dma_unmap_single(struct ib_device *dev, u64 addr, size_t size,
+				  enum dma_data_direction direction)
+{
+	/* This is only a stub; nothing to be done here */
+}
+
+static u64 ehca_dma_map_page(struct ib_device *dev, struct page *page,
+			     unsigned long offset, size_t size,
+			     enum dma_data_direction direction)
+{
+	u64 addr;
+
+	if (offset + size > PAGE_SIZE)
+		return EHCA_INVAL_ADDR;
+
+	addr = ehca_map_vaddr(page_address(page));
+	if (!ehca_dma_mapping_error(dev, addr))
+		addr += offset;
+
+	return addr;
+}
+
+static void ehca_dma_unmap_page(struct ib_device *dev, u64 addr, size_t size,
+				enum dma_data_direction direction)
+{
+	/* This is only a stub; nothing to be done here */
+}
+
+static int ehca_dma_map_sg(struct ib_device *dev, struct scatterlist *sgl,
+			   int nents, enum dma_data_direction direction)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i) {
+		u64 addr;
+		addr = ehca_map_vaddr(sg_virt(sg));
+		if (ehca_dma_mapping_error(dev, addr))
+			return 0;
+
+		sg->dma_address = addr;
+		sg->dma_length = sg->length;
+	}
+	return nents;
+}
+
+static void ehca_dma_unmap_sg(struct ib_device *dev, struct scatterlist *sg,
+			      int nents, enum dma_data_direction direction)
+{
+	/* This is only a stub; nothing to be done here */
+}
+
+static u64 ehca_dma_address(struct ib_device *dev, struct scatterlist *sg)
+{
+	return sg->dma_address;
+}
+
+static unsigned int ehca_dma_len(struct ib_device *dev, struct scatterlist *sg)
+{
+	return sg->length;
+}
+
+static void ehca_dma_sync_single_for_cpu(struct ib_device *dev, u64 addr,
+					 size_t size,
+					 enum dma_data_direction dir)
+{
+	dma_sync_single_for_cpu(dev->dma_device, addr, size, dir);
+}
+
+static void ehca_dma_sync_single_for_device(struct ib_device *dev, u64 addr,
+					    size_t size,
+					    enum dma_data_direction dir)
+{
+	dma_sync_single_for_device(dev->dma_device, addr, size, dir);
+}
+
+static void *ehca_dma_alloc_coherent(struct ib_device *dev, size_t size,
+				     u64 *dma_handle, gfp_t flag)
+{
+	struct page *p;
+	void *addr = NULL;
+	u64 dma_addr;
+
+	p = alloc_pages(flag, get_order(size));
+	if (p) {
+		addr = page_address(p);
+		dma_addr = ehca_map_vaddr(addr);
+		if (ehca_dma_mapping_error(dev, dma_addr)) {
+			free_pages((unsigned long)addr,	get_order(size));
+			return NULL;
+		}
+		if (dma_handle)
+			*dma_handle = dma_addr;
+		return addr;
+	}
+	return NULL;
+}
+
+static void ehca_dma_free_coherent(struct ib_device *dev, size_t size,
+				   void *cpu_addr, u64 dma_handle)
+{
+	if (cpu_addr && size)
+		free_pages((unsigned long)cpu_addr, get_order(size));
+}
+
+
+struct ib_dma_mapping_ops ehca_dma_mapping_ops = {
+	.mapping_error          = ehca_dma_mapping_error,
+	.map_single             = ehca_dma_map_single,
+	.unmap_single           = ehca_dma_unmap_single,
+	.map_page               = ehca_dma_map_page,
+	.unmap_page             = ehca_dma_unmap_page,
+	.map_sg                 = ehca_dma_map_sg,
+	.unmap_sg               = ehca_dma_unmap_sg,
+	.dma_address            = ehca_dma_address,
+	.dma_len                = ehca_dma_len,
+	.sync_single_for_cpu    = ehca_dma_sync_single_for_cpu,
+	.sync_single_for_device = ehca_dma_sync_single_for_device,
+	.alloc_coherent         = ehca_dma_alloc_coherent,
+	.free_coherent          = ehca_dma_free_coherent,
+};
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.h linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.h
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_mrmw.h	2009-09-09 18:13:59.000000000 -0400
@@ -42,6 +42,11 @@
 #ifndef _EHCA_MRMW_H_
 #define _EHCA_MRMW_H_
 
+enum ehca_reg_type {
+	EHCA_REG_MR,
+	EHCA_REG_BUSMAP_MR
+};
+
 int ehca_reg_mr(struct ehca_shca *shca,
 		struct ehca_mr *e_mr,
 		u64 *iova_start,
@@ -50,7 +55,8 @@
 		struct ehca_pd *e_pd,
 		struct ehca_mr_pginfo *pginfo,
 		u32 *lkey,
-		u32 *rkey);
+		u32 *rkey,
+		enum ehca_reg_type reg_type);
 
 int ehca_reg_mr_rpages(struct ehca_shca *shca,
 		       struct ehca_mr *e_mr,
@@ -118,4 +124,9 @@
 
 void ehca_mr_deletenew(struct ehca_mr *mr);
 
+int ehca_create_busmap(void);
+
+void ehca_destroy_busmap(void);
+
+extern struct ib_dma_mapping_ops ehca_dma_mapping_ops;
 #endif  /*_EHCA_MRMW_H_*/
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_qp.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_qp.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ehca_qp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ehca_qp.c	2009-09-09 18:13:59.000000000 -0400
@@ -461,7 +461,7 @@
 					      ib_device);
 	struct ib_ucontext *context = NULL;
 	u64 h_ret;
-	int is_llqp = 0, has_srq = 0;
+	int is_llqp = 0, has_srq = 0, is_user = 0;
 	int qp_type, max_send_sge, max_recv_sge, ret;
 
 	/* h_call's out parameters */
@@ -609,9 +609,6 @@
 		}
 	}
 
-	if (pd->uobject && udata)
-		context = pd->uobject->context;
-
 	my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
 	if (!my_qp) {
 		ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
@@ -619,6 +616,11 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
+	if (pd->uobject && udata) {
+		is_user = 1;
+		context = pd->uobject->context;
+	}
+
 	atomic_set(&my_qp->nr_events, 0);
 	init_waitqueue_head(&my_qp->wait_completion);
 	spin_lock_init(&my_qp->spinlock_s);
@@ -707,7 +709,7 @@
 			(parms.squeue.is_small || parms.rqueue.is_small);
 	}
 
-	h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);
+	h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms, is_user);
 	if (h_ret != H_SUCCESS) {
 		ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli",
 			 h_ret);
@@ -769,18 +771,20 @@
 			goto create_qp_exit2;
 		}
 
-		my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
-			 my_qp->ipz_squeue.qe_size;
-		my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
-					sizeof(struct ehca_qmap_entry));
-		if (!my_qp->sq_map.map) {
-			ehca_err(pd->device, "Couldn't allocate squeue "
-				 "map ret=%i", ret);
-			goto create_qp_exit3;
+		if (!is_user) {
+			my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
+				my_qp->ipz_squeue.qe_size;
+			my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
+						    sizeof(struct ehca_qmap_entry));
+			if (!my_qp->sq_map.map) {
+				ehca_err(pd->device, "Couldn't allocate squeue "
+					 "map ret=%i", ret);
+				goto create_qp_exit3;
+			}
+			INIT_LIST_HEAD(&my_qp->sq_err_node);
+			/* to avoid the generation of bogus flush CQEs */
+			reset_queue_map(&my_qp->sq_map);
 		}
-		INIT_LIST_HEAD(&my_qp->sq_err_node);
-		/* to avoid the generation of bogus flush CQEs */
-		reset_queue_map(&my_qp->sq_map);
 	}
 
 	if (HAS_RQ(my_qp)) {
@@ -792,20 +796,21 @@
 				 "and pages ret=%i", ret);
 			goto create_qp_exit4;
 		}
-
-		my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
-			my_qp->ipz_rqueue.qe_size;
-		my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
-				sizeof(struct ehca_qmap_entry));
-		if (!my_qp->rq_map.map) {
-			ehca_err(pd->device, "Couldn't allocate squeue "
-					"map ret=%i", ret);
-			goto create_qp_exit5;
+		if (!is_user) {
+			my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
+				my_qp->ipz_rqueue.qe_size;
+			my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
+						    sizeof(struct ehca_qmap_entry));
+			if (!my_qp->rq_map.map) {
+				ehca_err(pd->device, "Couldn't allocate squeue "
+					 "map ret=%i", ret);
+				goto create_qp_exit5;
+			}
+			INIT_LIST_HEAD(&my_qp->rq_err_node);
+			/* to avoid the generation of bogus flush CQEs */
+			reset_queue_map(&my_qp->rq_map);
 		}
-		INIT_LIST_HEAD(&my_qp->rq_err_node);
-		/* to avoid the generation of bogus flush CQEs */
-		reset_queue_map(&my_qp->rq_map);
-	} else if (init_attr->srq) {
+	} else if (init_attr->srq && !is_user) {
 		/* this is a base QP, use the queue map of the SRQ */
 		my_qp->rq_map = my_srq->rq_map;
 		INIT_LIST_HEAD(&my_qp->rq_err_node);
@@ -918,7 +923,7 @@
 	kfree(my_qp->mod_qp_parm);
 
 create_qp_exit6:
-	if (HAS_RQ(my_qp))
+	if (HAS_RQ(my_qp) && !is_user)
 		vfree(my_qp->rq_map.map);
 
 create_qp_exit5:
@@ -926,7 +931,7 @@
 		ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
 
 create_qp_exit4:
-	if (HAS_SQ(my_qp))
+	if (HAS_SQ(my_qp) && !is_user)
 		vfree(my_qp->sq_map.map);
 
 create_qp_exit3:
@@ -1244,6 +1249,7 @@
 	u64 update_mask;
 	u64 h_ret;
 	int bad_wqe_cnt = 0;
+	int is_user = 0;
 	int squeue_locked = 0;
 	unsigned long flags = 0;
 
@@ -1266,6 +1272,8 @@
 		ret = ehca2ib_return_code(h_ret);
 		goto modify_qp_exit1;
 	}
+	if (ibqp->uobject)
+		is_user = 1;
 
 	qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state);
 
@@ -1728,7 +1736,8 @@
 			goto modify_qp_exit2;
 		}
 	}
-	if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)) {
+	if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)
+	    && !is_user) {
 		ret = check_for_left_cqes(my_qp, shca);
 		if (ret)
 			goto modify_qp_exit2;
@@ -1738,16 +1747,17 @@
 		ipz_qeit_reset(&my_qp->ipz_rqueue);
 		ipz_qeit_reset(&my_qp->ipz_squeue);
 
-		if (qp_cur_state == IB_QPS_ERR) {
+		if (qp_cur_state == IB_QPS_ERR && !is_user) {
 			del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
 
 			if (HAS_RQ(my_qp))
 				del_from_err_list(my_qp->recv_cq,
 						  &my_qp->rq_err_node);
 		}
-		reset_queue_map(&my_qp->sq_map);
+		if (!is_user)
+			reset_queue_map(&my_qp->sq_map);
 
-		if (HAS_RQ(my_qp))
+		if (HAS_RQ(my_qp) && !is_user)
 			reset_queue_map(&my_qp->rq_map);
 	}
 
@@ -1952,19 +1962,13 @@
 	qp_attr->cap.max_inline_data = my_qp->sq_max_inline_data_size;
 	qp_attr->dest_qp_num = qpcb->dest_qp_nr;
 
-	qp_attr->pkey_index =
-		EHCA_BMASK_GET(MQPCB_PRIM_P_KEY_IDX, qpcb->prim_p_key_idx);
-
-	qp_attr->port_num =
-		EHCA_BMASK_GET(MQPCB_PRIM_PHYS_PORT, qpcb->prim_phys_port);
-
+	qp_attr->pkey_index = qpcb->prim_p_key_idx;
+	qp_attr->port_num = qpcb->prim_phys_port;
 	qp_attr->timeout = qpcb->timeout;
 	qp_attr->retry_cnt = qpcb->retry_count;
 	qp_attr->rnr_retry = qpcb->rnr_retry_count;
 
-	qp_attr->alt_pkey_index =
-		EHCA_BMASK_GET(MQPCB_PRIM_P_KEY_IDX, qpcb->alt_p_key_idx);
-
+	qp_attr->alt_pkey_index = qpcb->alt_p_key_idx;
 	qp_attr->alt_port_num = qpcb->alt_phys_port;
 	qp_attr->alt_timeout = qpcb->timeout_al;
 
@@ -2051,8 +2055,7 @@
 		update_mask |=
 			EHCA_BMASK_SET(MQPCB_MASK_CURR_SRQ_LIMIT, 1)
 			| EHCA_BMASK_SET(MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG, 1);
-		mqpcb->curr_srq_limit =
-			EHCA_BMASK_SET(MQPCB_CURR_SRQ_LIMIT, attr->srq_limit);
+		mqpcb->curr_srq_limit = attr->srq_limit;
 		mqpcb->qp_aff_asyn_ev_log_reg =
 			EHCA_BMASK_SET(QPX_AAELOG_RESET_SRQ_LIMIT, 1);
 	}
@@ -2115,8 +2118,7 @@
 
 	srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
 	srq_attr->max_sge = 3;
-	srq_attr->srq_limit = EHCA_BMASK_GET(
-		MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
+	srq_attr->srq_limit = qpcb->curr_srq_limit;
 
 	if (ehca_debug_level >= 2)
 		ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
@@ -2138,10 +2140,12 @@
 	int ret;
 	u64 h_ret;
 	u8 port_num;
+	int is_user = 0;
 	enum ib_qp_type	qp_type;
 	unsigned long flags;
 
 	if (uobject) {
+		is_user = 1;
 		if (my_qp->mm_count_galpa ||
 		    my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
 			ehca_err(dev, "Resources still referenced in "
@@ -2168,10 +2172,10 @@
 	 * SRQs will never get into an error list and do not have a recv_cq,
 	 * so we need to skip them here.
 	 */
-	if (HAS_RQ(my_qp) && !IS_SRQ(my_qp))
+	if (HAS_RQ(my_qp) && !IS_SRQ(my_qp) && !is_user)
 		del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node);
 
-	if (HAS_SQ(my_qp))
+	if (HAS_SQ(my_qp) && !is_user)
 		del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
 
 	/* now wait until all pending events have completed */
@@ -2209,13 +2213,13 @@
 
 	if (HAS_RQ(my_qp)) {
 		ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
-
-		vfree(my_qp->rq_map.map);
+		if (!is_user)
+			vfree(my_qp->rq_map.map);
 	}
 	if (HAS_SQ(my_qp)) {
 		ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
-
-		vfree(my_qp->sq_map.map);
+		if (!is_user)
+			vfree(my_qp->sq_map.map);
 	}
 	kmem_cache_free(qp_cache, my_qp);
 	atomic_dec(&shca->num_qps);
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_if.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_if.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_if.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_if.c	2009-09-09 18:13:59.000000000 -0400
@@ -284,7 +284,7 @@
 	param->act_pages = (u32)outs[4];
 
 	if (ret == H_SUCCESS)
-		hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
+		hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);
 
 	if (ret == H_NOT_ENOUGH_RESOURCES)
 		ehca_gen_err("Not enough resources. ret=%lli", ret);
@@ -293,7 +293,7 @@
 }
 
 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-			     struct ehca_alloc_qp_parms *parms)
+			     struct ehca_alloc_qp_parms *parms, int is_user)
 {
 	u64 ret;
 	u64 allocate_controls, max_r10_reg, r11, r12;
@@ -359,7 +359,7 @@
 		(u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
 
 	if (ret == H_SUCCESS)
-		hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
+		hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);
 
 	if (ret == H_NOT_ENOUGH_RESOURCES)
 		ehca_gen_err("Not enough resources. ret=%lli", ret);
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_if.h linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_if.h
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_if.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_if.h	2009-09-09 18:13:59.000000000 -0400
@@ -78,7 +78,7 @@
  * initialize resources, create empty QPPTs (2 rings).
  */
 u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-			     struct ehca_alloc_qp_parms *parms);
+			     struct ehca_alloc_qp_parms *parms, int is_user);
 
 u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
 		      const u8 port_id,
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_phyp.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_phyp.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_phyp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_phyp.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,12 +54,15 @@
 	return 0;
 }
 
-int hcp_galpas_ctor(struct h_galpas *galpas,
+int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
 		    u64 paddr_kernel, u64 paddr_user)
 {
-	int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle);
-	if (ret)
-		return ret;
+	if (!is_user) {
+		int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle);
+		if (ret)
+			return ret;
+	} else
+		galpas->kernel.fw_handle = 0;
 
 	galpas->user.fw_handle = paddr_user;
 
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_phyp.h linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_phyp.h
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/hcp_phyp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/hcp_phyp.h	2009-09-09 18:13:59.000000000 -0400
@@ -78,7 +78,7 @@
 	*(volatile u64 __force *)addr = value;
 }
 
-int hcp_galpas_ctor(struct h_galpas *galpas,
+int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
 		    u64 paddr_kernel, u64 paddr_user);
 
 int hcp_galpas_dtor(struct h_galpas *galpas);
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ipz_pt_fn.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ipz_pt_fn.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/ehca/ipz_pt_fn.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/ehca/ipz_pt_fn.c	2009-09-09 18:13:59.000000000 -0400
@@ -220,10 +220,13 @@
 	queue->small_page = NULL;
 
 	/* allocate queue page pointers */
-	queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *));
+	queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
 	if (!queue->queue_pages) {
-		ehca_gen_err("Couldn't allocate queue page list");
-		return 0;
+		queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *));
+		if (!queue->queue_pages) {
+			ehca_gen_err("Couldn't allocate queue page list");
+			return 0;
+		}
 	}
 	memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *));
 
@@ -240,7 +243,10 @@
 ipz_queue_ctor_exit0:
 	ehca_gen_err("Couldn't alloc pages queue=%p "
 		 "nr_of_pages=%x",  queue, nr_of_pages);
-	vfree(queue->queue_pages);
+	if (is_vmalloc_addr(queue->queue_pages))
+		vfree(queue->queue_pages);
+	else
+		kfree(queue->queue_pages);
 
 	return 0;
 }
@@ -262,7 +268,10 @@
 			free_page((unsigned long)queue->queue_pages[i]);
 	}
 
-	vfree(queue->queue_pages);
+	if (is_vmalloc_addr(queue->queue_pages))
+		vfree(queue->queue_pages);
+	else
+		kfree(queue->queue_pages);
 
 	return 1;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/mlx4/qp.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/mlx4/qp.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/mlx4/qp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/mlx4/qp.c	2009-09-09 18:13:59.000000000 -0400
@@ -1585,12 +1585,16 @@
 				break;
 
 			case IB_WR_LOCAL_INV:
+				ctrl->srcrb_flags |=
+					cpu_to_be32(MLX4_WQE_CTRL_STRONG_ORDER);
 				set_local_inv_seg(wqe, wr->ex.invalidate_rkey);
 				wqe  += sizeof (struct mlx4_wqe_local_inval_seg);
 				size += sizeof (struct mlx4_wqe_local_inval_seg) / 16;
 				break;
 
 			case IB_WR_FAST_REG_MR:
+				ctrl->srcrb_flags |=
+					cpu_to_be32(MLX4_WQE_CTRL_STRONG_ORDER);
 				set_fmr_seg(wqe, wr);
 				wqe  += sizeof (struct mlx4_wqe_fmr_seg);
 				size += sizeof (struct mlx4_wqe_fmr_seg) / 16;
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_cmd.c	2009-09-09 18:13:59.000000000 -0400
@@ -1059,7 +1059,7 @@
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_MTT_OFFSET);
 	if (mthca_is_memfree(dev))
 		dev_lim->reserved_mtts = ALIGN((1 << (field >> 4)) * sizeof(u64),
-					       MTHCA_MTT_SEG_SIZE) / MTHCA_MTT_SEG_SIZE;
+					       dev->limits.mtt_seg_size) / dev->limits.mtt_seg_size;
 	else
 		dev_lim->reserved_mtts = 1 << (field >> 4);
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_MRW_SZ_OFFSET);
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_dev.h linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_dev.h
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_dev.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_dev.h	2009-09-09 18:13:59.000000000 -0400
@@ -159,6 +159,7 @@
 	int      reserved_eqs;
 	int      num_mpts;
 	int      num_mtt_segs;
+	int	 mtt_seg_size;
 	int      fmr_reserved_mtts;
 	int      reserved_mtts;
 	int      reserved_mrws;
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_eq.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_eq.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_eq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_eq.c	2009-09-09 18:13:59.000000000 -0400
@@ -641,9 +641,11 @@
 	if (dev->eq_table.have_irq)
 		free_irq(dev->pdev->irq, dev);
 	for (i = 0; i < MTHCA_NUM_EQ; ++i)
-		if (dev->eq_table.eq[i].have_irq)
+		if (dev->eq_table.eq[i].have_irq) {
 			free_irq(dev->eq_table.eq[i].msi_x_vector,
 				 dev->eq_table.eq + i);
+			dev->eq_table.eq[i].have_irq = 0;
+		}
 }
 
 static int mthca_map_reg(struct mthca_dev *dev,
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_main.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_main.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -125,6 +125,10 @@
 MODULE_PARM_DESC(fmr_reserved_mtts,
 		 "number of memory translation table segments reserved for FMR");
 
+static int log_mtts_per_seg = ilog2(MTHCA_MTT_SEG_SIZE / 8);
+module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
+MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-5)");
+
 static char mthca_version[] __devinitdata =
 	DRV_NAME ": Mellanox InfiniBand HCA driver v"
 	DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -162,6 +166,7 @@
 	int err;
 	u8 status;
 
+	mdev->limits.mtt_seg_size = (1 << log_mtts_per_seg) * 8;
 	err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status);
 	if (err) {
 		mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
@@ -460,11 +465,11 @@
 	}
 
 	/* CPU writes to non-reserved MTTs, while HCA might DMA to reserved mtts */
-	mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * MTHCA_MTT_SEG_SIZE,
-					   dma_get_cache_alignment()) / MTHCA_MTT_SEG_SIZE;
+	mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * mdev->limits.mtt_seg_size,
+					   dma_get_cache_alignment()) / mdev->limits.mtt_seg_size;
 
 	mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,
-							 MTHCA_MTT_SEG_SIZE,
+							 mdev->limits.mtt_seg_size,
 							 mdev->limits.num_mtt_segs,
 							 mdev->limits.reserved_mtts,
 							 1, 0);
@@ -1315,6 +1320,12 @@
 		printk(KERN_WARNING PFX "Corrected fmr_reserved_mtts to %d.\n",
 		       hca_profile.fmr_reserved_mtts);
 	}
+
+	if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 5)) {
+		printk(KERN_WARNING PFX "bad log_mtts_per_seg (%d). Using default - %d\n",
+		       log_mtts_per_seg, ilog2(MTHCA_MTT_SEG_SIZE / 8));
+		log_mtts_per_seg = ilog2(MTHCA_MTT_SEG_SIZE / 8);
+	}
 }
 
 static int __init mthca_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_mr.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_mr.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_mr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_mr.c	2009-09-09 18:13:59.000000000 -0400
@@ -220,7 +220,7 @@
 
 	mtt->buddy = buddy;
 	mtt->order = 0;
-	for (i = MTHCA_MTT_SEG_SIZE / 8; i < size; i <<= 1)
+	for (i = dev->limits.mtt_seg_size / 8; i < size; i <<= 1)
 		++mtt->order;
 
 	mtt->first_seg = mthca_alloc_mtt_range(dev, mtt->order, buddy);
@@ -267,7 +267,7 @@
 
 	while (list_len > 0) {
 		mtt_entry[0] = cpu_to_be64(dev->mr_table.mtt_base +
-					   mtt->first_seg * MTHCA_MTT_SEG_SIZE +
+					   mtt->first_seg * dev->limits.mtt_seg_size +
 					   start_index * 8);
 		mtt_entry[1] = 0;
 		for (i = 0; i < list_len && i < MTHCA_MAILBOX_SIZE / 8 - 2; ++i)
@@ -326,7 +326,7 @@
 	u64 __iomem *mtts;
 	int i;
 
-	mtts = dev->mr_table.tavor_fmr.mtt_base + mtt->first_seg * MTHCA_MTT_SEG_SIZE +
+	mtts = dev->mr_table.tavor_fmr.mtt_base + mtt->first_seg * dev->limits.mtt_seg_size +
 		start_index * sizeof (u64);
 	for (i = 0; i < list_len; ++i)
 		mthca_write64_raw(cpu_to_be64(buffer_list[i] | MTHCA_MTT_FLAG_PRESENT),
@@ -345,17 +345,21 @@
 	/* For Arbel, all MTTs must fit in the same page. */
 	BUG_ON(s / PAGE_SIZE != (s + list_len * sizeof(u64) - 1) / PAGE_SIZE);
 	/* Require full segments */
-	BUG_ON(s % MTHCA_MTT_SEG_SIZE);
+	BUG_ON(s % dev->limits.mtt_seg_size);
 
 	mtts = mthca_table_find(dev->mr_table.mtt_table, mtt->first_seg +
-				s / MTHCA_MTT_SEG_SIZE, &dma_handle);
+				s / dev->limits.mtt_seg_size, &dma_handle);
 
 	BUG_ON(!mtts);
 
+	dma_sync_single_for_cpu(&dev->pdev->dev, dma_handle,
+				list_len * sizeof (u64), DMA_TO_DEVICE);
+
 	for (i = 0; i < list_len; ++i)
 		mtts[i] = cpu_to_be64(buffer_list[i] | MTHCA_MTT_FLAG_PRESENT);
 
-	dma_sync_single(&dev->pdev->dev, dma_handle, list_len * sizeof (u64), DMA_TO_DEVICE);
+	dma_sync_single_for_device(&dev->pdev->dev, dma_handle,
+				   list_len * sizeof (u64), DMA_TO_DEVICE);
 }
 
 int mthca_write_mtt(struct mthca_dev *dev, struct mthca_mtt *mtt,
@@ -479,7 +483,7 @@
 	if (mr->mtt)
 		mpt_entry->mtt_seg =
 			cpu_to_be64(dev->mr_table.mtt_base +
-				    mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE);
+				    mr->mtt->first_seg * dev->limits.mtt_seg_size);
 
 	if (0) {
 		mthca_dbg(dev, "Dumping MPT entry %08x:\n", mr->ibmr.lkey);
@@ -626,7 +630,7 @@
 		goto err_out_table;
 	}
 
-	mtt_seg = mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE;
+	mtt_seg = mr->mtt->first_seg * dev->limits.mtt_seg_size;
 
 	if (mthca_is_memfree(dev)) {
 		mr->mem.arbel.mtts = mthca_table_find(dev->mr_table.mtt_table,
@@ -803,12 +807,15 @@
 
 	wmb();
 
+	dma_sync_single_for_cpu(&dev->pdev->dev, fmr->mem.arbel.dma_handle,
+				list_len * sizeof(u64), DMA_TO_DEVICE);
+
 	for (i = 0; i < list_len; ++i)
 		fmr->mem.arbel.mtts[i] = cpu_to_be64(page_list[i] |
 						     MTHCA_MTT_FLAG_PRESENT);
 
-	dma_sync_single(&dev->pdev->dev, fmr->mem.arbel.dma_handle,
-			list_len * sizeof(u64), DMA_TO_DEVICE);
+	dma_sync_single_for_device(&dev->pdev->dev, fmr->mem.arbel.dma_handle,
+				   list_len * sizeof(u64), DMA_TO_DEVICE);
 
 	fmr->mem.arbel.mpt->key    = cpu_to_be32(key);
 	fmr->mem.arbel.mpt->lkey   = cpu_to_be32(key);
@@ -908,7 +915,7 @@
 			 dev->mr_table.mtt_base);
 
 		dev->mr_table.tavor_fmr.mtt_base =
-			ioremap(addr, mtts * MTHCA_MTT_SEG_SIZE);
+			ioremap(addr, mtts * dev->limits.mtt_seg_size);
 		if (!dev->mr_table.tavor_fmr.mtt_base) {
 			mthca_warn(dev, "MTT ioremap for FMR failed.\n");
 			err = -ENOMEM;
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_profile.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_profile.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/mthca/mthca_profile.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/mthca/mthca_profile.c	2009-09-09 18:13:59.000000000 -0400
@@ -94,7 +94,7 @@
 	profile[MTHCA_RES_RDB].size  = MTHCA_RDB_ENTRY_SIZE;
 	profile[MTHCA_RES_MCG].size  = MTHCA_MGM_ENTRY_SIZE;
 	profile[MTHCA_RES_MPT].size  = dev_lim->mpt_entry_sz;
-	profile[MTHCA_RES_MTT].size  = MTHCA_MTT_SEG_SIZE;
+	profile[MTHCA_RES_MTT].size  = dev->limits.mtt_seg_size;
 	profile[MTHCA_RES_UAR].size  = dev_lim->uar_scratch_entry_sz;
 	profile[MTHCA_RES_UDAV].size = MTHCA_AV_SIZE;
 	profile[MTHCA_RES_UARC].size = request->uarc_size;
@@ -232,7 +232,7 @@
 			dev->limits.num_mtt_segs = profile[i].num;
 			dev->mr_table.mtt_base   = profile[i].start;
 			init_hca->mtt_base       = profile[i].start;
-			init_hca->mtt_seg_sz     = ffs(MTHCA_MTT_SEG_SIZE) - 7;
+			init_hca->mtt_seg_sz     = ffs(dev->limits.mtt_seg_size) - 7;
 			break;
 		case MTHCA_RES_UAR:
 			dev->limits.num_uars       = profile[i].num;
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/nes/nes_cm.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/nes/nes_cm.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/nes/nes_cm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/nes/nes_cm.c	2009-09-09 18:13:59.000000000 -0400
@@ -472,6 +472,7 @@
 
 static void nes_retrans_expired(struct nes_cm_node *cm_node)
 {
+	struct iw_cm_id *cm_id = cm_node->cm_id;
 	switch (cm_node->state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_CLOSING:
@@ -479,7 +480,9 @@
 		break;
 	case NES_CM_STATE_LAST_ACK:
 	case NES_CM_STATE_FIN_WAIT1:
-	case NES_CM_STATE_MPAREJ_RCVD:
+		if (cm_node->cm_id)
+			cm_id->rem_ref(cm_id);
+		cm_node->state = NES_CM_STATE_CLOSED;
 		send_reset(cm_node, NULL);
 		break;
 	default:
@@ -1406,6 +1409,7 @@
 	case NES_CM_STATE_CLOSED:
 		drop_packet(skb);
 		break;
+	case NES_CM_STATE_FIN_WAIT1:
 	case NES_CM_STATE_LAST_ACK:
 		cm_node->cm_id->rem_ref(cm_node->cm_id);
 	case NES_CM_STATE_TIME_WAIT:
@@ -1413,8 +1417,6 @@
 		rem_ref_cm_node(cm_node->cm_core, cm_node);
 		drop_packet(skb);
 		break;
-	case NES_CM_STATE_FIN_WAIT1:
-		nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__);
 	default:
 		drop_packet(skb);
 		break;
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/nes/nes_hw.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/nes/nes_hw.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/nes/nes_hw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/nes/nes_hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -667,7 +667,7 @@
 		i = 0;
 		while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
 			mdelay(1);
-		if (i >= 10000) {
+		if (i > 10000) {
 			nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n");
 			return 0;
 		}
@@ -675,7 +675,7 @@
 		i = 0;
 		while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
 			mdelay(1);
-		if (i >= 10000) {
+		if (i > 10000) {
 			printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
 			       nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
 			return 0;
@@ -701,7 +701,7 @@
 	i = 0;
 	while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
 		mdelay(1);
-	if (i >= 10000) {
+	if (i > 10000) {
 		nes_debug(NES_DBG_INIT, "Did not see port soft reset done.\n");
 		return 0;
 	}
@@ -711,7 +711,7 @@
 	while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
 			& 0x0000000f)) != 0x0000000f) && i++ < 5000)
 		mdelay(1);
-	if (i >= 5000) {
+	if (i > 5000) {
 		nes_debug(NES_DBG_INIT, "Serdes 0 not ready, status=%x\n", u32temp);
 		return 0;
 	}
@@ -722,7 +722,7 @@
 		while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
 				& 0x0000000f)) != 0x0000000f) && i++ < 5000)
 			mdelay(1);
-		if (i >= 5000) {
+		if (i > 5000) {
 			nes_debug(NES_DBG_INIT, "Serdes 1 not ready, status=%x\n", u32temp);
 			return 0;
 		}
@@ -792,7 +792,7 @@
 		while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
 				& 0x0000000f)) != 0x0000000f) && i++ < 5000)
 			mdelay(1);
-		if (i >= 5000) {
+		if (i > 5000) {
 			nes_debug(NES_DBG_PHY, "Init: serdes 0 not ready, status=%x\n", u32temp);
 			return 1;
 		}
@@ -815,7 +815,7 @@
 			while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
 				& 0x0000000f)) != 0x0000000f) && (i++ < 5000))
 				mdelay(1);
-			if (i >= 5000) {
+			if (i > 5000) {
 				printk("%s: Init: serdes 1 not ready, status=%x\n", __func__, u32temp);
 				/* return 1; */
 			}
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/hw/nes/nes_verbs.c linux-libre-2.6.31-gnu/drivers/infiniband/hw/nes/nes_verbs.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2009-09-09 18:13:59.000000000 -0400
@@ -654,7 +654,7 @@
 		default:
 			props->max_qp_rd_atom = 0;
 	}
-	props->max_qp_init_rd_atom = props->max_qp_wr;
+	props->max_qp_init_rd_atom = props->max_qp_rd_atom;
 	props->atomic_cap = IB_ATOMIC_NONE;
 	props->max_map_per_fmr = 1;
 
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2009-09-09 18:13:59.000000000 -0400
@@ -1394,8 +1394,8 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int e = skb_queue_empty(&priv->cm.skb_queue);
 
-	if (skb->dst)
-		skb->dst->ops->update_pmtu(skb->dst, mtu);
+	if (skb_dst(skb))
+		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
 
 	skb_queue_tail(&priv->cm.skb_queue, skb);
 	if (e)
@@ -1455,13 +1455,15 @@
 	struct net_device *dev = to_net_dev(d);
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
+	if (!rtnl_trylock())
+		return restart_syscall();
+
 	/* flush paths if we switch modes so that connections are restarted */
 	if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) {
 		set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
 		ipoib_warn(priv, "enabling connected mode "
 			   "will cause multicast packet drops\n");
 
-		rtnl_lock();
 		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
 		rtnl_unlock();
 		priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
@@ -1473,7 +1475,6 @@
 	if (!strcmp(buf, "datagram\n")) {
 		clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
 
-		rtnl_lock();
 		if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) {
 			dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 			if (priv->hca_caps & IB_DEVICE_UD_TSO)
@@ -1485,6 +1486,7 @@
 
 		return count;
 	}
+	rtnl_unlock();
 
 	return -EINVAL;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -561,7 +561,7 @@
 	struct ipoib_neigh *neigh;
 	unsigned long flags;
 
-	neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
+	neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
 	if (!neigh) {
 		++dev->stats.tx_dropped;
 		dev_kfree_skb_any(skb);
@@ -570,9 +570,9 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	path = __path_find(dev, skb->dst->neighbour->ha + 4);
+	path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
 	if (!path) {
-		path = path_rec_create(dev, skb->dst->neighbour->ha + 4);
+		path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
 		if (!path)
 			goto err_path;
 
@@ -605,7 +605,7 @@
 				goto err_drop;
 			}
 		} else
-			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
+			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
 	} else {
 		neigh->ah  = NULL;
 
@@ -635,15 +635,15 @@
 	struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
 
 	/* Look up path record for unicasts */
-	if (skb->dst->neighbour->ha[4] != 0xff) {
+	if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
 		neigh_add_path(skb, dev);
 		return;
 	}
 
 	/* Add in the P_Key for multicasts */
-	skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
-	skb->dst->neighbour->ha[9] = priv->pkey & 0xff;
-	ipoib_mcast_send(dev, skb->dst->neighbour->ha + 4, skb);
+	skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
+	skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
+	ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -708,16 +708,16 @@
 	struct ipoib_neigh *neigh;
 	unsigned long flags;
 
-	if (likely(skb->dst && skb->dst->neighbour)) {
-		if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) {
+	if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
+		if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
 			ipoib_path_lookup(skb, dev);
 			return NETDEV_TX_OK;
 		}
 
-		neigh = *to_ipoib_neigh(skb->dst->neighbour);
+		neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
 
 		if (unlikely((memcmp(&neigh->dgid.raw,
-				     skb->dst->neighbour->ha + 4,
+				     skb_dst(skb)->neighbour->ha + 4,
 				     sizeof(union ib_gid))) ||
 			     (neigh->dev != dev))) {
 			spin_lock_irqsave(&priv->lock, flags);
@@ -743,7 +743,7 @@
 				return NETDEV_TX_OK;
 			}
 		} else if (neigh->ah) {
-			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha));
+			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
 			return NETDEV_TX_OK;
 		}
 
@@ -772,7 +772,7 @@
 			if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) &&
 			    (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) {
 				ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
-					   skb->dst ? "neigh" : "dst",
+					   skb_dst(skb) ? "neigh" : "dst",
 					   be16_to_cpup((__be16 *) skb->data),
 					   IPOIB_QPN(phdr->hwaddr),
 					   phdr->hwaddr + 4);
@@ -817,7 +817,7 @@
 	 * destination address onto the front of the skb so we can
 	 * figure out where to send the packet later.
 	 */
-	if ((!skb->dst || !skb->dst->neighbour) && daddr) {
+	if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
 		struct ipoib_pseudoheader *phdr =
 			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
 		memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
@@ -1053,6 +1053,7 @@
 	dev->tx_queue_len	 = ipoib_sendq_size * 2;
 	dev->features		 = (NETIF_F_VLAN_CHALLENGED	|
 				    NETIF_F_HIGHDMA);
+	dev->priv_flags		&= ~IFF_XMIT_DST_RELEASE;
 
 	memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN);
 
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2009-09-09 18:13:59.000000000 -0400
@@ -261,7 +261,7 @@
 
 		skb->dev = dev;
 
-		if (!skb->dst || !skb->dst->neighbour) {
+		if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
 			/* put pseudoheader back on for next time */
 			skb_push(skb, sizeof (struct ipoib_pseudoheader));
 		}
@@ -707,10 +707,10 @@
 
 out:
 	if (mcast && mcast->ah) {
-		if (skb->dst		&&
-		    skb->dst->neighbour &&
-		    !*to_ipoib_neigh(skb->dst->neighbour)) {
-			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour,
+		if (skb_dst(skb)		&&
+		    skb_dst(skb)->neighbour &&
+		    !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
+			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
 									skb->dev);
 
 			if (neigh) {
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,7 +61,8 @@
 
 	ppriv = netdev_priv(pdev);
 
-	rtnl_lock();
+	if (!rtnl_trylock())
+		return restart_syscall();
 	mutex_lock(&ppriv->vlan_mutex);
 
 	/*
@@ -167,7 +168,8 @@
 
 	ppriv = netdev_priv(pdev);
 
-	rtnl_lock();
+	if (!rtnl_trylock())
+		return restart_syscall();
 	mutex_lock(&ppriv->vlan_mutex);
 	list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
 		if (priv->pkey == pkey) {
diff -druN linux-libre-2.6.30-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c linux-libre-2.6.31-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c
--- linux-libre-2.6.30-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2009-09-09 18:13:59.000000000 -0400
@@ -257,11 +257,8 @@
 {
 	struct iscsi_iser_task *iser_task = task->dd_data;
 
-	/*
-	 * mgmt tasks do not need special cleanup and we do not
-	 * allocate anything in the init task callout
-	 */
-	if (!task->sc || task->state == ISCSI_TASK_PENDING)
+	/* mgmt tasks do not need special cleanup */
+	if (!task->sc)
 		return;
 
 	if (iser_task->status == ISER_TASK_STATUS_STARTED) {
@@ -517,7 +514,8 @@
 }
 
 static struct iscsi_endpoint *
-iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking)
+iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
+		      int non_blocking)
 {
 	int err;
 	struct iser_conn *ib_conn;
diff -druN linux-libre-2.6.30-gnu/drivers/input/evdev.c linux-libre-2.6.31-gnu/drivers/input/evdev.c
--- linux-libre-2.6.30-gnu/drivers/input/evdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/evdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,6 @@
 	int exist;
 	int open;
 	int minor;
-	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct evdev_client *grab;
@@ -626,8 +625,11 @@
 				abs.maximum = dev->absmax[t];
 				abs.fuzz = dev->absfuzz[t];
 				abs.flat = dev->absflat[t];
+				abs.resolution = dev->absres[t];
 
-				if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
+				if (copy_to_user(p, &abs, min_t(size_t,
+								_IOC_SIZE(cmd),
+								sizeof(struct input_absinfo))))
 					return -EFAULT;
 
 				return 0;
@@ -654,8 +656,9 @@
 
 				t = _IOC_NR(cmd) & ABS_MAX;
 
-				if (copy_from_user(&abs, p,
-						sizeof(struct input_absinfo)))
+				if (copy_from_user(&abs, p, min_t(size_t,
+								  _IOC_SIZE(cmd),
+								  sizeof(struct input_absinfo))))
 					return -EFAULT;
 
 				/*
@@ -670,6 +673,8 @@
 				dev->absmax[t] = abs.maximum;
 				dev->absfuzz[t] = abs.fuzz;
 				dev->absflat[t] = abs.flat;
+				dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
+							0 : abs.resolution;
 
 				spin_unlock_irq(&dev->event_lock);
 
@@ -807,16 +812,15 @@
 	mutex_init(&evdev->mutex);
 	init_waitqueue_head(&evdev->wait);
 
-	snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
+	dev_set_name(&evdev->dev, "event%d", minor);
 	evdev->exist = 1;
 	evdev->minor = minor;
 
 	evdev->handle.dev = input_get_device(dev);
-	evdev->handle.name = evdev->name;
+	evdev->handle.name = dev_name(&evdev->dev);
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
 
-	dev_set_name(&evdev->dev, evdev->name);
 	evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
 	evdev->dev.class = &input_class;
 	evdev->dev.parent = &dev->dev;
diff -druN linux-libre-2.6.30-gnu/drivers/input/gameport/fm801-gp.c linux-libre-2.6.31-gnu/drivers/input/gameport/fm801-gp.c
--- linux-libre-2.6.30-gnu/drivers/input/gameport/fm801-gp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/gameport/fm801-gp.c	2009-09-09 18:13:59.000000000 -0400
@@ -167,5 +167,6 @@
 
 MODULE_DEVICE_TABLE(pci, fm801_gp_id_table);
 
+MODULE_DESCRIPTION("FM801 gameport driver");
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/input/gameport/gameport.c linux-libre-2.6.31-gnu/drivers/input/gameport/gameport.c
--- linux-libre-2.6.30-gnu/drivers/input/gameport/gameport.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/gameport/gameport.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,16 +30,6 @@
 MODULE_DESCRIPTION("Generic gameport layer");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(__gameport_register_port);
-EXPORT_SYMBOL(gameport_unregister_port);
-EXPORT_SYMBOL(__gameport_register_driver);
-EXPORT_SYMBOL(gameport_unregister_driver);
-EXPORT_SYMBOL(gameport_open);
-EXPORT_SYMBOL(gameport_close);
-EXPORT_SYMBOL(gameport_set_phys);
-EXPORT_SYMBOL(gameport_start_polling);
-EXPORT_SYMBOL(gameport_stop_polling);
-
 /*
  * gameport_mutex protects entire gameport subsystem and is taken
  * every time gameport port or driver registrered or unregistered.
@@ -162,6 +152,7 @@
 
 	spin_unlock(&gameport->timer_lock);
 }
+EXPORT_SYMBOL(gameport_start_polling);
 
 void gameport_stop_polling(struct gameport *gameport)
 {
@@ -172,6 +163,7 @@
 
 	spin_unlock(&gameport->timer_lock);
 }
+EXPORT_SYMBOL(gameport_stop_polling);
 
 static void gameport_run_poll_handler(unsigned long d)
 {
@@ -516,6 +508,7 @@
 	vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
 	va_end(args);
 }
+EXPORT_SYMBOL(gameport_set_phys);
 
 /*
  * Prepare gameport port for registration.
@@ -658,6 +651,7 @@
 	gameport_init_port(gameport);
 	gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
 }
+EXPORT_SYMBOL(__gameport_register_port);
 
 /*
  * Synchronously unregisters gameport port.
@@ -669,6 +663,7 @@
 	gameport_destroy_port(gameport);
 	mutex_unlock(&gameport_mutex);
 }
+EXPORT_SYMBOL(gameport_unregister_port);
 
 
 /*
@@ -728,7 +723,7 @@
 	 * Temporarily disable automatic binding because probing
 	 * takes long time and we are better off doing it in kgameportd
 	 */
-	drv->ignore = 1;
+	drv->ignore = true;
 
 	error = driver_register(&drv->driver);
 	if (error) {
@@ -741,7 +736,7 @@
 	/*
 	 * Reset ignore flag and let kgameportd bind the driver to free ports
 	 */
-	drv->ignore = 0;
+	drv->ignore = false;
 	error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);
 	if (error) {
 		driver_unregister(&drv->driver);
@@ -750,6 +745,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(__gameport_register_driver);
 
 void gameport_unregister_driver(struct gameport_driver *drv)
 {
@@ -757,7 +753,7 @@
 
 	mutex_lock(&gameport_mutex);
 
-	drv->ignore = 1;	/* so gameport_find_driver ignores it */
+	drv->ignore = true;	/* so gameport_find_driver ignores it */
 	gameport_remove_pending_events(drv);
 
 start_over:
@@ -774,6 +770,7 @@
 
 	mutex_unlock(&gameport_mutex);
 }
+EXPORT_SYMBOL(gameport_unregister_driver);
 
 static int gameport_bus_match(struct device *dev, struct device_driver *drv)
 {
@@ -812,6 +809,7 @@
 	gameport_set_drv(gameport, drv);
 	return 0;
 }
+EXPORT_SYMBOL(gameport_open);
 
 void gameport_close(struct gameport *gameport)
 {
@@ -822,6 +820,7 @@
 	if (gameport->close)
 		gameport->close(gameport);
 }
+EXPORT_SYMBOL(gameport_close);
 
 static int __init gameport_init(void)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/input/input.c linux-libre-2.6.31-gnu/drivers/input/input.c
--- linux-libre-2.6.30-gnu/drivers/input/input.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/input.c	2009-09-09 18:13:59.000000000 -0400
@@ -1265,8 +1265,14 @@
 	.uevent		= input_dev_uevent,
 };
 
+static char *input_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev));
+}
+
 struct class input_class = {
 	.name		= "input",
+	.nodename	= input_nodename,
 };
 EXPORT_SYMBOL_GPL(input_class);
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/joydev.c linux-libre-2.6.31-gnu/drivers/input/joydev.c
--- linux-libre-2.6.30-gnu/drivers/input/joydev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/joydev.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,7 +39,6 @@
 	int exist;
 	int open;
 	int minor;
-	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
@@ -457,8 +456,11 @@
 				unsigned int cmd, void __user *argp)
 {
 	struct input_dev *dev = joydev->handle.dev;
+	size_t len;
 	int i, j;
+	const char *name;
 
+	/* Process fixed-sized commands. */
 	switch (cmd) {
 
 	case JS_SET_CAL:
@@ -500,9 +502,22 @@
 		return copy_to_user(argp, joydev->corr,
 			sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
 
-	case JSIOCSAXMAP:
-		if (copy_from_user(joydev->abspam, argp,
-				   sizeof(__u8) * (ABS_MAX + 1)))
+	}
+
+	/*
+	 * Process variable-sized commands (the axis and button map commands
+	 * are considered variable-sized to decouple them from the values of
+	 * ABS_MAX and KEY_MAX).
+	 */
+	switch (cmd & ~IOCSIZE_MASK) {
+
+	case (JSIOCSAXMAP & ~IOCSIZE_MASK):
+		len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
+		/*
+		 * FIXME: we should not copy into our axis map before
+		 * validating the data.
+		 */
+		if (copy_from_user(joydev->abspam, argp, len))
 			return -EFAULT;
 
 		for (i = 0; i < joydev->nabs; i++) {
@@ -512,13 +527,17 @@
 		}
 		return 0;
 
-	case JSIOCGAXMAP:
-		return copy_to_user(argp, joydev->abspam,
-			sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
+	case (JSIOCGAXMAP & ~IOCSIZE_MASK):
+		len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
+		return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0;
 
-	case JSIOCSBTNMAP:
-		if (copy_from_user(joydev->keypam, argp,
-				   sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
+	case (JSIOCSBTNMAP & ~IOCSIZE_MASK):
+		len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
+		/*
+		 * FIXME: we should not copy into our keymap before
+		 * validating the data.
+		 */
+		if (copy_from_user(joydev->keypam, argp, len))
 			return -EFAULT;
 
 		for (i = 0; i < joydev->nkey; i++) {
@@ -530,23 +549,19 @@
 
 		return 0;
 
-	case JSIOCGBTNMAP:
-		return copy_to_user(argp, joydev->keypam,
-			sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
+	case (JSIOCGBTNMAP & ~IOCSIZE_MASK):
+		len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
+		return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0;
 
-	default:
-		if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
-			int len;
-			if (!dev->name)
-				return 0;
-			len = strlen(dev->name) + 1;
-			if (len > _IOC_SIZE(cmd))
-				len = _IOC_SIZE(cmd);
-			if (copy_to_user(argp, dev->name, len))
-				return -EFAULT;
-			return len;
-		}
+	case JSIOCGNAME(0):
+		name = dev->name;
+		if (!name)
+			return 0;
+
+		len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1);
+		return copy_to_user(argp, name, len) ? -EFAULT : len;
 	}
+
 	return -EINVAL;
 }
 
@@ -742,13 +757,13 @@
 	mutex_init(&joydev->mutex);
 	init_waitqueue_head(&joydev->wait);
 
-	snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
+	dev_set_name(&joydev->dev, "js%d", minor);
 	joydev->exist = 1;
 	joydev->minor = minor;
 
 	joydev->exist = 1;
 	joydev->handle.dev = input_get_device(dev);
-	joydev->handle.name = joydev->name;
+	joydev->handle.name = dev_name(&joydev->dev);
 	joydev->handle.handler = handler;
 	joydev->handle.private = joydev;
 
@@ -797,7 +812,6 @@
 		}
 	}
 
-	dev_set_name(&joydev->dev, joydev->name);
 	joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
 	joydev->dev.class = &input_class;
 	joydev->dev.parent = &dev->dev;
diff -druN linux-libre-2.6.30-gnu/drivers/input/joystick/analog.c linux-libre-2.6.31-gnu/drivers/input/joystick/analog.c
--- linux-libre-2.6.30-gnu/drivers/input/joystick/analog.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/joystick/analog.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,7 @@
 #include <linux/input.h>
 #include <linux/gameport.h>
 #include <linux/jiffies.h>
-#include <asm/timex.h>
+#include <linux/timex.h>
 
 #define DRIVER_DESC	"Analog joystick and gamepad driver"
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/joystick/iforce/iforce-main.c linux-libre-2.6.31-gnu/drivers/input/joystick/iforce/iforce-main.c
--- linux-libre-2.6.30-gnu/drivers/input/joystick/iforce/iforce-main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/joystick/iforce/iforce-main.c	2009-09-09 18:13:59.000000000 -0400
@@ -74,6 +74,7 @@
 	{ 0x05ef, 0x8884, "AVB Mag Turbo Force",			btn_avb_wheel, abs_wheel, ff_iforce },
 	{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel",	btn_avb_tw, abs_wheel, ff_iforce }, //?
 	{ 0x061c, 0xc0a4, "ACT LABS Force RS",                          btn_wheel, abs_wheel, ff_iforce }, //?
+	{ 0x061c, 0xc084, "ACT LABS Force RS",				btn_wheel, abs_wheel, ff_iforce },
 	{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback",	btn_wheel, abs_wheel, ff_iforce }, //?
 	{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel",	btn_wheel, abs_wheel, ff_iforce }, //?
 	{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D",			btn_joystick, abs_joystick, ff_iforce }, //?
diff -druN linux-libre-2.6.30-gnu/drivers/input/joystick/iforce/iforce-usb.c linux-libre-2.6.31-gnu/drivers/input/joystick/iforce/iforce-usb.c
--- linux-libre-2.6.30-gnu/drivers/input/joystick/iforce/iforce-usb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/joystick/iforce/iforce-usb.c	2009-09-09 18:13:59.000000000 -0400
@@ -223,6 +223,7 @@
 	{ USB_DEVICE(0x05ef, 0x8884) },		/* AVB Mag Turbo Force */
 	{ USB_DEVICE(0x05ef, 0x8888) },		/* AVB Top Shot FFB Racing Wheel */
 	{ USB_DEVICE(0x061c, 0xc0a4) },         /* ACT LABS Force RS */
+	{ USB_DEVICE(0x061c, 0xc084) },         /* ACT LABS Force RS */
 	{ USB_DEVICE(0x06f8, 0x0001) },		/* Guillemot Race Leader Force Feedback */
 	{ USB_DEVICE(0x06f8, 0x0004) },		/* Guillemot Force Feedback Racing Wheel */
 	{ USB_DEVICE(0x06f8, 0xa302) },		/* Guillemot Jet Leader 3D */
diff -druN linux-libre-2.6.30-gnu/drivers/input/joystick/xpad.c linux-libre-2.6.31-gnu/drivers/input/joystick/xpad.c
--- linux-libre-2.6.30-gnu/drivers/input/joystick/xpad.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/joystick/xpad.c	2009-09-09 18:13:59.000000000 -0400
@@ -470,20 +470,20 @@
 	status = urb->status;
 
 	switch (status) {
-		case 0:
+	case 0:
 		/* success */
-		break;
-		case -ECONNRESET:
-		case -ENOENT:
-		case -ESHUTDOWN:
-			/* this urb is terminated, clean up */
-			dbg("%s - urb shutting down with status: %d",
-				__func__, status);
-			return;
-		default:
-			dbg("%s - nonzero urb status received: %d",
-				__func__, status);
-			goto exit;
+		return;
+
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __func__, status);
+		return;
+
+	default:
+		dbg("%s - nonzero urb status received: %d", __func__, status);
+		goto exit;
 	}
 
 exit:
diff -druN linux-libre-2.6.30-gnu/drivers/input/keyboard/atkbd.c linux-libre-2.6.31-gnu/drivers/input/keyboard/atkbd.c
--- linux-libre-2.6.30-gnu/drivers/input/keyboard/atkbd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/keyboard/atkbd.c	2009-09-09 18:13:59.000000000 -0400
@@ -880,6 +880,14 @@
 };
 
 /*
+ * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate
+ * release for their volume buttons
+ */
+static unsigned int atkbd_hp_r4000_forced_release_keys[] = {
+	0xae, 0xb0, -1U
+};
+
+/*
  * Samsung NC10,NC20 with Fn+F? key release not working
  */
 static unsigned int atkbd_samsung_forced_release_keys[] = {
@@ -895,6 +903,13 @@
 };
 
 /*
+ * Amilo Pi 3525 key release for Fn+Volume keys not working
+ */
+static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = {
+	0x20, 0xa0, 0x2e, 0xae, 0x30, 0xb0, -1U
+};
+
+/*
  * Amilo Xi 3650 key release for light touch bar not working
  */
 static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = {
@@ -902,6 +917,13 @@
 };
 
 /*
+ * Soltech TA12 system with broken key release on volume keys and mute key
+ */
+static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
+	0xa0, 0xae, 0xb0, -1U
+};
+
+/*
  * atkbd_set_keycode_table() initializes keyboard's keycode table
  * according to the selected scancode set
  */
@@ -1523,6 +1545,33 @@
 		.driver_data = atkbd_hp_zv6100_forced_release_keys,
 	},
 	{
+		.ident = "HP Presario R4000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkbd_hp_r4000_forced_release_keys,
+	},
+	{
+		.ident = "HP Presario R4100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkbd_hp_r4000_forced_release_keys,
+	},
+	{
+		.ident = "HP Presario R4200",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkbd_hp_r4000_forced_release_keys,
+	},
+	{
 		.ident = "Inventec Symphony",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"),
@@ -1568,6 +1617,15 @@
 		.driver_data = atkbd_amilo_pa1510_forced_release_keys,
 	},
 	{
+		.ident = "Fujitsu Amilo Pi 3525",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkbd_amilo_pi3525_forced_release_keys,
+	},
+	{
 		.ident = "Fujitsu Amilo Xi 3650",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -1576,6 +1634,15 @@
 		.callback = atkbd_setup_forced_release,
 		.driver_data = atkbd_amilo_xi3650_forced_release_keys,
 	},
+	{
+		.ident = "Soltech Corporation TA12",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TA12"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkdb_soltech_ta12_forced_release_keys,
+	},
 	{ }
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/keyboard/ep93xx_keypad.c linux-libre-2.6.31-gnu/drivers/input/keyboard/ep93xx_keypad.c
--- linux-libre-2.6.30-gnu/drivers/input/keyboard/ep93xx_keypad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/keyboard/ep93xx_keypad.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,470 @@
+/*
+ * Driver for the Cirrus EP93xx matrix keypad controller.
+ *
+ * Copyright (c) 2008 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on the pxa27x matrix keypad controller by Rodolfo Giometti.
+ *
+ * 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.
+ *
+ * NOTE:
+ *
+ * The 3-key reset is triggered by pressing the 3 keys in
+ * Row 0, Columns 2, 4, and 7 at the same time.  This action can
+ * be disabled by setting the EP93XX_KEYPAD_DISABLE_3_KEY flag.
+ *
+ * Normal operation for the matrix does not autorepeat the key press.
+ * This action can be enabled by setting the EP93XX_KEYPAD_AUTOREPEAT
+ * flag.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/ep93xx_keypad.h>
+
+/*
+ * Keypad Interface Register offsets
+ */
+#define KEY_INIT		0x00	/* Key Scan Initialization register */
+#define KEY_DIAG		0x04	/* Key Scan Diagnostic register */
+#define KEY_REG			0x08	/* Key Value Capture register */
+
+/* Key Scan Initialization Register bit defines */
+#define KEY_INIT_DBNC_MASK	(0x00ff0000)
+#define KEY_INIT_DBNC_SHIFT	(16)
+#define KEY_INIT_DIS3KY		(1<<15)
+#define KEY_INIT_DIAG		(1<<14)
+#define KEY_INIT_BACK		(1<<13)
+#define KEY_INIT_T2		(1<<12)
+#define KEY_INIT_PRSCL_MASK	(0x000003ff)
+#define KEY_INIT_PRSCL_SHIFT	(0)
+
+/* Key Scan Diagnostic Register bit defines */
+#define KEY_DIAG_MASK		(0x0000003f)
+#define KEY_DIAG_SHIFT		(0)
+
+/* Key Value Capture Register bit defines */
+#define KEY_REG_K		(1<<15)
+#define KEY_REG_INT		(1<<14)
+#define KEY_REG_2KEYS		(1<<13)
+#define KEY_REG_1KEY		(1<<12)
+#define KEY_REG_KEY2_MASK	(0x00000fc0)
+#define KEY_REG_KEY2_SHIFT	(6)
+#define KEY_REG_KEY1_MASK	(0x0000003f)
+#define KEY_REG_KEY1_SHIFT	(0)
+
+#define keypad_readl(off)	__raw_readl(keypad->mmio_base + (off))
+#define keypad_writel(v, off)	__raw_writel((v), keypad->mmio_base + (off))
+
+#define MAX_MATRIX_KEY_NUM	(MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
+
+struct ep93xx_keypad {
+	struct ep93xx_keypad_platform_data *pdata;
+
+	struct clk *clk;
+	struct input_dev *input_dev;
+	void __iomem *mmio_base;
+
+	int irq;
+	int enabled;
+
+	int key1;
+	int key2;
+
+	unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
+};
+
+static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad)
+{
+	struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
+	struct input_dev *input_dev = keypad->input_dev;
+	int i;
+
+	for (i = 0; i < pdata->matrix_key_map_size; i++) {
+		unsigned int key = pdata->matrix_key_map[i];
+		int row = (key >> 28) & 0xf;
+		int col = (key >> 24) & 0xf;
+		int code = key & 0xffffff;
+
+		keypad->matrix_keycodes[(row << 3) + col] = code;
+		__set_bit(code, input_dev->keybit);
+	}
+}
+
+static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
+{
+	struct ep93xx_keypad *keypad = dev_id;
+	struct input_dev *input_dev = keypad->input_dev;
+	unsigned int status = keypad_readl(KEY_REG);
+	int keycode, key1, key2;
+
+	keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
+	key1 = keypad->matrix_keycodes[keycode];
+
+	keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT;
+	key2 = keypad->matrix_keycodes[keycode];
+
+	if (status & KEY_REG_2KEYS) {
+		if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1)
+			input_report_key(input_dev, keypad->key1, 0);
+
+		if (keypad->key2 && key1 != keypad->key2 && key2 != keypad->key2)
+			input_report_key(input_dev, keypad->key2, 0);
+
+		input_report_key(input_dev, key1, 1);
+		input_report_key(input_dev, key2, 1);
+
+		keypad->key1 = key1;
+		keypad->key2 = key2;
+
+	} else if (status & KEY_REG_1KEY) {
+		if (keypad->key1 && key1 != keypad->key1)
+			input_report_key(input_dev, keypad->key1, 0);
+
+		if (keypad->key2 && key1 != keypad->key2)
+			input_report_key(input_dev, keypad->key2, 0);
+
+		input_report_key(input_dev, key1, 1);
+
+		keypad->key1 = key1;
+		keypad->key2 = 0;
+
+	} else {
+		input_report_key(input_dev, keypad->key1, 0);
+		input_report_key(input_dev, keypad->key2, 0);
+
+		keypad->key1 = keypad->key2 = 0;
+	}
+	input_sync(input_dev);
+
+	return IRQ_HANDLED;
+}
+
+static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
+{
+	struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
+	unsigned int val = 0;
+
+	clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV);
+
+	if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
+		val |= KEY_INIT_DIS3KY;
+	if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE)
+		val |= KEY_INIT_DIAG;
+	if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE)
+		val |= KEY_INIT_BACK;
+	if (pdata->flags & EP93XX_KEYPAD_TEST_MODE)
+		val |= KEY_INIT_T2;
+
+	val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK);
+
+	val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
+
+	keypad_writel(val, KEY_INIT);
+}
+
+static int ep93xx_keypad_open(struct input_dev *pdev)
+{
+	struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
+
+	if (!keypad->enabled) {
+		ep93xx_keypad_config(keypad);
+		clk_enable(keypad->clk);
+		keypad->enabled = 1;
+	}
+
+	return 0;
+}
+
+static void ep93xx_keypad_close(struct input_dev *pdev)
+{
+	struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
+
+	if (keypad->enabled) {
+		clk_disable(keypad->clk);
+		keypad->enabled = 0;
+	}
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * NOTE: I don't know if this is correct, or will work on the ep93xx.
+ *
+ * None of the existing ep93xx drivers have power management support.
+ * But, this is basically what the pxa27x_keypad driver does.
+ */
+static int ep93xx_keypad_suspend(struct platform_device *pdev,
+				 pm_message_t state)
+{
+	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = keypad->input_dev;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (keypad->enabled) {
+		clk_disable(keypad->clk);
+		keypad->enabled = 0;
+	}
+
+	mutex_unlock(&input_dev->mutex);
+
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(keypad->irq);
+
+	return 0;
+}
+
+static int ep93xx_keypad_resume(struct platform_device *pdev)
+{
+	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+	struct input_dev *input_dev = keypad->input_dev;
+
+	if (device_may_wakeup(&pdev->dev))
+		disable_irq_wake(keypad->irq);
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users) {
+		if (!keypad->enabled) {
+			ep93xx_keypad_config(keypad);
+			clk_enable(keypad->clk);
+			keypad->enabled = 1;
+		}
+	}
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+#else	/* !CONFIG_PM */
+#define ep93xx_keypad_suspend	NULL
+#define ep93xx_keypad_resume	NULL
+#endif	/* !CONFIG_PM */
+
+static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
+{
+	struct ep93xx_keypad *keypad;
+	struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data;
+	struct input_dev *input_dev;
+	struct resource *res;
+	int irq, err, i, gpio;
+
+	if (!pdata ||
+	    !pdata->matrix_key_rows ||
+	    pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS ||
+	    !pdata->matrix_key_cols ||
+	    pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) {
+		dev_err(&pdev->dev, "invalid or missing platform data\n");
+		return -EINVAL;
+	}
+
+	keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL);
+	if (!keypad) {
+		dev_err(&pdev->dev, "failed to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	keypad->pdata = pdata;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get keypad irq\n");
+		err = -ENXIO;
+		goto failed_free;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		err = -ENXIO;
+		goto failed_free;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		err = -EBUSY;
+		goto failed_free;
+	}
+
+	keypad->mmio_base = ioremap(res->start, resource_size(res));
+	if (keypad->mmio_base == NULL) {
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
+		err = -ENXIO;
+		goto failed_free_mem;
+	}
+
+	/* Request the needed GPIO's */
+	gpio = EP93XX_GPIO_LINE_ROW0;
+	for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) {
+		err = gpio_request(gpio, pdev->name);
+		if (err) {
+			dev_err(&pdev->dev, "failed to request gpio-%d\n",
+				gpio);
+			goto failed_free_rows;
+		}
+	}
+
+	gpio = EP93XX_GPIO_LINE_COL0;
+	for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) {
+		err = gpio_request(gpio, pdev->name);
+		if (err) {
+			dev_err(&pdev->dev, "failed to request gpio-%d\n",
+				gpio);
+			goto failed_free_cols;
+		}
+	}
+
+	keypad->clk = clk_get(&pdev->dev, "key_clk");
+	if (IS_ERR(keypad->clk)) {
+		dev_err(&pdev->dev, "failed to get keypad clock\n");
+		err = PTR_ERR(keypad->clk);
+		goto failed_free_io;
+	}
+
+	/* Create and register the input driver */
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		dev_err(&pdev->dev, "failed to allocate input device\n");
+		err = -ENOMEM;
+		goto failed_put_clk;
+	}
+
+	keypad->input_dev = input_dev;
+
+	input_dev->name = pdev->name;
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->open = ep93xx_keypad_open;
+	input_dev->close = ep93xx_keypad_close;
+	input_dev->dev.parent = &pdev->dev;
+	input_dev->keycode = keypad->matrix_keycodes;
+	input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]);
+	input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes);
+
+	input_set_drvdata(input_dev, keypad);
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY);
+	if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
+		input_dev->evbit[0] |= BIT_MASK(EV_REP);
+
+	ep93xx_keypad_build_keycode(keypad);
+	platform_set_drvdata(pdev, keypad);
+
+	err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED,
+				pdev->name, keypad);
+	if (err) {
+		dev_err(&pdev->dev, "failed to request IRQ\n");
+		goto failed_free_dev;
+	}
+
+	keypad->irq = irq;
+
+	/* Register the input device */
+	err = input_register_device(input_dev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register input device\n");
+		goto failed_free_irq;
+	}
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	return 0;
+
+failed_free_irq:
+	free_irq(irq, pdev);
+	platform_set_drvdata(pdev, NULL);
+failed_free_dev:
+	input_free_device(input_dev);
+failed_put_clk:
+	clk_put(keypad->clk);
+failed_free_io:
+	i = keypad->pdata->matrix_key_cols - 1;
+	gpio = EP93XX_GPIO_LINE_COL0 + i;
+failed_free_cols:
+	for ( ; i >= 0; i--, gpio--)
+		gpio_free(gpio);
+	i = keypad->pdata->matrix_key_rows - 1;
+	gpio = EP93XX_GPIO_LINE_ROW0 + i;
+failed_free_rows:
+	for ( ; i >= 0; i--, gpio--)
+		gpio_free(gpio);
+	iounmap(keypad->mmio_base);
+failed_free_mem:
+	release_mem_region(res->start, resource_size(res));
+failed_free:
+	kfree(keypad);
+	return err;
+}
+
+static int __devexit ep93xx_keypad_remove(struct platform_device *pdev)
+{
+	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
+	struct resource *res;
+	int i, gpio;
+
+	free_irq(keypad->irq, pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (keypad->enabled)
+		clk_disable(keypad->clk);
+	clk_put(keypad->clk);
+
+	input_unregister_device(keypad->input_dev);
+
+	i = keypad->pdata->matrix_key_cols - 1;
+	gpio = EP93XX_GPIO_LINE_COL0 + i;
+	for ( ; i >= 0; i--, gpio--)
+		gpio_free(gpio);
+
+	i = keypad->pdata->matrix_key_rows - 1;
+	gpio = EP93XX_GPIO_LINE_ROW0 + i;
+	for ( ; i >= 0; i--, gpio--)
+		gpio_free(gpio);
+
+	iounmap(keypad->mmio_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(keypad);
+
+	return 0;
+}
+
+static struct platform_driver ep93xx_keypad_driver = {
+	.driver		= {
+		.name	= "ep93xx-keypad",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ep93xx_keypad_probe,
+	.remove		= __devexit_p(ep93xx_keypad_remove),
+	.suspend	= ep93xx_keypad_suspend,
+	.resume		= ep93xx_keypad_resume,
+};
+
+static int __init ep93xx_keypad_init(void)
+{
+	return platform_driver_register(&ep93xx_keypad_driver);
+}
+
+static void __exit ep93xx_keypad_exit(void)
+{
+	platform_driver_unregister(&ep93xx_keypad_driver);
+}
+
+module_init(ep93xx_keypad_init);
+module_exit(ep93xx_keypad_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller");
+MODULE_ALIAS("platform:ep93xx-keypad");
diff -druN linux-libre-2.6.30-gnu/drivers/input/keyboard/gpio_keys.c linux-libre-2.6.31-gnu/drivers/input/keyboard/gpio_keys.c
--- linux-libre-2.6.30-gnu/drivers/input/keyboard/gpio_keys.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/keyboard/gpio_keys.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
+#include <linux/workqueue.h>
 
 #include <asm/gpio.h>
 
@@ -29,6 +30,7 @@
 	struct gpio_keys_button *button;
 	struct input_dev *input;
 	struct timer_list timer;
+	struct work_struct work;
 };
 
 struct gpio_keys_drvdata {
@@ -36,8 +38,10 @@
 	struct gpio_button_data data[0];
 };
 
-static void gpio_keys_report_event(struct gpio_button_data *bdata)
+static void gpio_keys_report_event(struct work_struct *work)
 {
+	struct gpio_button_data *bdata =
+		container_of(work, struct gpio_button_data, work);
 	struct gpio_keys_button *button = bdata->button;
 	struct input_dev *input = bdata->input;
 	unsigned int type = button->type ?: EV_KEY;
@@ -47,11 +51,11 @@
 	input_sync(input);
 }
 
-static void gpio_check_button(unsigned long _data)
+static void gpio_keys_timer(unsigned long _data)
 {
 	struct gpio_button_data *data = (struct gpio_button_data *)_data;
 
-	gpio_keys_report_event(data);
+	schedule_work(&data->work);
 }
 
 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
@@ -65,7 +69,7 @@
 		mod_timer(&bdata->timer,
 			jiffies + msecs_to_jiffies(button->debounce_interval));
 	else
-		gpio_keys_report_event(bdata);
+		schedule_work(&bdata->work);
 
 	return IRQ_HANDLED;
 }
@@ -113,7 +117,8 @@
 		bdata->input = input;
 		bdata->button = button;
 		setup_timer(&bdata->timer,
-			    gpio_check_button, (unsigned long)bdata);
+			    gpio_keys_timer, (unsigned long)bdata);
+		INIT_WORK(&bdata->work, gpio_keys_report_event);
 
 		error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
 		if (error < 0) {
@@ -142,8 +147,7 @@
 		}
 
 		error = request_irq(irq, gpio_keys_isr,
-				    IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
-					IRQF_TRIGGER_FALLING,
+				    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				    button->desc ? button->desc : "gpio_keys",
 				    bdata);
 		if (error) {
@@ -175,6 +179,7 @@
 		free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
 		if (pdata->buttons[i].debounce_interval)
 			del_timer_sync(&ddata->data[i].timer);
+		cancel_work_sync(&ddata->data[i].work);
 		gpio_free(pdata->buttons[i].gpio);
 	}
 
@@ -200,6 +205,7 @@
 		free_irq(irq, &ddata->data[i]);
 		if (pdata->buttons[i].debounce_interval)
 			del_timer_sync(&ddata->data[i].timer);
+		cancel_work_sync(&ddata->data[i].work);
 		gpio_free(pdata->buttons[i].gpio);
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/keyboard/Kconfig linux-libre-2.6.31-gnu/drivers/input/keyboard/Kconfig
--- linux-libre-2.6.30-gnu/drivers/input/keyboard/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/keyboard/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,42 @@
 
 if INPUT_KEYBOARD
 
+config KEYBOARD_AAED2000
+	tristate "AAED-2000 keyboard"
+	depends on MACH_AAED2000
+	select INPUT_POLLDEV
+	default y
+	help
+	  Say Y here to enable the keyboard on the Agilent AAED-2000
+	  development board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called aaed2000_kbd.
+
+config KEYBOARD_AMIGA
+	tristate "Amiga keyboard"
+	depends on AMIGA
+	help
+	  Say Y here if you are running Linux on any AMIGA and have a keyboard
+	  attached.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called amikbd.
+
+config ATARI_KBD_CORE
+	bool
+
+config KEYBOARD_ATARI
+	tristate "Atari keyboard"
+	depends on ATARI
+	select ATARI_KBD_CORE
+	help
+	  Say Y here if you are running Linux on any Atari and have a keyboard
+	  attached.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atakbd.
+
 config KEYBOARD_ATKBD
 	tristate "AT keyboard" if EMBEDDED || !X86
 	default y
@@ -68,69 +104,14 @@
 	  right-hand column will be interpreted as the key shown in the
 	  left-hand column.
 
-config KEYBOARD_SUNKBD
-	tristate "Sun Type 4 and Type 5 keyboard"
-	select SERIO
-	help
-	  Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
-	  connected either to the Sun keyboard connector or to an serial
-	  (RS-232) port via a simple adapter.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sunkbd.
-
-config KEYBOARD_LKKBD
-	tristate "DECstation/VAXstation LK201/LK401 keyboard"
-	select SERIO
-	help
-	  Say Y here if you want to use a LK201 or LK401 style serial
-	  keyboard. This keyboard is also useable on PCs if you attach
-	  it with the inputattach program. The connector pinout is
-	  described within lkkbd.c.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called lkkbd.
-
-config KEYBOARD_LOCOMO
-	tristate "LoCoMo Keyboard Support"
-	depends on SHARP_LOCOMO && INPUT_KEYBOARD
-	help
-	  Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called locomokbd.
-
-config KEYBOARD_XTKBD
-	tristate "XT keyboard"
-	select SERIO
-	help
-	  Say Y here if you want to use the old IBM PC/XT keyboard (or
-	  compatible) on your system. This is only possible with a
-	  parallel port keyboard adapter, you cannot connect it to the
-	  keyboard port on a PC that runs Linux.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called xtkbd.
-
-config KEYBOARD_NEWTON
-	tristate "Newton keyboard"
-	select SERIO
-	help
-	  Say Y here if you have a Newton keyboard on a serial port.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called newtonkbd.
-
-config KEYBOARD_STOWAWAY
-	tristate "Stowaway keyboard"
-	select SERIO
+config KEYBOARD_BFIN
+	tristate "Blackfin BF54x keypad support"
+	depends on (BF54x && !BF544)
 	help
-	  Say Y here if you have a Stowaway keyboard on a serial port.
-	  Stowaway compatible keyboards like Dicota Input-PDA keyboard
-	  are also supported by this driver.
+	  Say Y here if you want to use the BF54x keypad.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called stowaway.
+	  module will be called bf54x-keys.
 
 config KEYBOARD_CORGI
 	tristate "Corgi keyboard"
@@ -143,61 +124,50 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called corgikbd.
 
-config KEYBOARD_SPITZ
-	tristate "Spitz keyboard"
-	depends on PXA_SHARPSL
-	default y
+config KEYBOARD_LKKBD
+	tristate "DECstation/VAXstation LK201/LK401 keyboard"
+	select SERIO
 	help
-	  Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
-	  SL-C3000 and Sl-C3100 series of PDAs.
+	  Say Y here if you want to use a LK201 or LK401 style serial
+	  keyboard. This keyboard is also useable on PCs if you attach
+	  it with the inputattach program. The connector pinout is
+	  described within lkkbd.c.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called spitzkbd.
+	  module will be called lkkbd.
 
-config KEYBOARD_TOSA
-	tristate "Tosa keyboard"
-	depends on MACH_TOSA
-	default y
+config KEYBOARD_EP93XX
+	tristate "EP93xx Matrix Keypad support"
+	depends on ARCH_EP93XX
 	help
-	  Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
+	  Say Y here to enable the matrix keypad on the Cirrus EP93XX.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called tosakbd.
+	  module will be called ep93xx_keypad.
 
-config KEYBOARD_TOSA_USE_EXT_KEYCODES
-	bool "Tosa keyboard: use extended keycodes"
-	depends on KEYBOARD_TOSA
-	default n
+config KEYBOARD_GPIO
+	tristate "GPIO Buttons"
+	depends on GENERIC_GPIO
 	help
-	  Say Y here to enable the tosa keyboard driver to generate extended
-	  (>= 127) keycodes. Be aware, that they can't be correctly interpreted
-	  by either console keyboard driver or by Kdrive keybd driver.
-
-	  Say Y only if you know, what you are doing!
+	  This driver implements support for buttons connected
+	  to GPIO pins of various CPUs (and some other chips).
 
-config KEYBOARD_AMIGA
-	tristate "Amiga keyboard"
-	depends on AMIGA
-	help
-	  Say Y here if you are running Linux on any AMIGA and have a keyboard
-	  attached.
+	  Say Y here if your device has buttons connected
+	  directly to such GPIO pins.  Your board-specific
+	  setup logic must also provide a platform device,
+	  with configuration data saying which GPIOs are used.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called amikbd.
-
-config ATARI_KBD_CORE
-	bool
+	  module will be called gpio_keys.
 
-config KEYBOARD_ATARI
-	tristate "Atari keyboard"
-	depends on ATARI
-	select ATARI_KBD_CORE
+config KEYBOARD_MATRIX
+	tristate "GPIO driven matrix keypad support"
+	depends on GENERIC_GPIO
 	help
-	  Say Y here if you are running Linux on any Atari and have a keyboard
-	  attached.
+	  Enable support for GPIO driven matrix keypad.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called atakbd.
+	  module will be called matrix_keypad.
 
 config KEYBOARD_HIL_OLD
 	tristate "HP HIL keyboard support (simple driver)"
@@ -250,20 +220,50 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called jornada720_kbd.
 
-config KEYBOARD_OMAP
-	tristate "TI OMAP keypad support"
-	depends on (ARCH_OMAP1 || ARCH_OMAP2)
+config KEYBOARD_LM8323
+	tristate "LM8323 keypad chip"
+	depends on I2C
+	depends on LEDS_CLASS
 	help
-	  Say Y here if you want to use the OMAP keypad.
+	  If you say yes here you get support for the National Semiconductor
+	  LM8323 keypad controller.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called omap-keypad.
+	  module will be called lm8323.
+
+config KEYBOARD_LOCOMO
+	tristate "LoCoMo Keyboard Support"
+	depends on SHARP_LOCOMO
+	help
+	  Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called locomokbd.
+
+config KEYBOARD_MAPLE
+	tristate "Maple bus keyboard"
+	depends on SH_DREAMCAST && MAPLE
+	help
+	  Say Y here if you have a Dreamcast console running Linux and have
+	  a keyboard attached to its Maple bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called maple_keyb.
+
+config KEYBOARD_NEWTON
+	tristate "Newton keyboard"
+	select SERIO
+	help
+	  Say Y here if you have a Newton keyboard on a serial port.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called newtonkbd.
 
 config KEYBOARD_PXA27x
 	tristate "PXA27x/PXA3xx keypad support"
 	depends on PXA27x || PXA3xx
 	help
-	  Enable support for PXA27x/PXA3xx keypad controller
+	  Enable support for PXA27x/PXA3xx keypad controller.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called pxa27x_keypad.
@@ -277,51 +277,38 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called pxa930_rotary.
 
-config KEYBOARD_AAED2000
-	tristate "AAED-2000 keyboard"
-	depends on MACH_AAED2000
-	select INPUT_POLLDEV
+config KEYBOARD_SPITZ
+	tristate "Spitz keyboard"
+	depends on PXA_SHARPSL
 	default y
 	help
-	  Say Y here to enable the keyboard on the Agilent AAED-2000
-	  development board.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aaed2000_kbd.
-
-config KEYBOARD_GPIO
-	tristate "GPIO Buttons"
-	depends on GENERIC_GPIO
-	help
-	  This driver implements support for buttons connected
-	  to GPIO pins of various CPUs (and some other chips).
-
-	  Say Y here if your device has buttons connected
-	  directly to such GPIO pins.  Your board-specific
-	  setup logic must also provide a platform device,
-	  with configuration data saying which GPIOs are used.
+	  Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+	  SL-C3000 and Sl-C3100 series of PDAs.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called gpio-keys.
+	  module will be called spitzkbd.
 
-config KEYBOARD_MAPLE
-	tristate "Maple bus keyboard"
-	depends on SH_DREAMCAST && MAPLE
+config KEYBOARD_STOWAWAY
+	tristate "Stowaway keyboard"
+	select SERIO
 	help
-	  Say Y here if you have a Dreamcast console running Linux and have
-	  a keyboard attached to its Maple bus.
+	  Say Y here if you have a Stowaway keyboard on a serial port.
+	  Stowaway compatible keyboards like Dicota Input-PDA keyboard
+	  are also supported by this driver.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called maple_keyb.
+	  module will be called stowaway.
 
-config KEYBOARD_BFIN
-	tristate "Blackfin BF54x keypad support"
-	depends on (BF54x && !BF544)
+config KEYBOARD_SUNKBD
+	tristate "Sun Type 4 and Type 5 keyboard"
+	select SERIO
 	help
-	  Say Y here if you want to use the BF54x keypad.
+	  Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
+	  connected either to the Sun keyboard connector or to an serial
+	  (RS-232) port via a simple adapter.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called bf54x-keys.
+	  module will be called sunkbd.
 
 config KEYBOARD_SH_KEYSC
 	tristate "SuperH KEYSC keypad support"
@@ -332,4 +319,46 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called sh_keysc.
+
+config KEYBOARD_OMAP
+	tristate "TI OMAP keypad support"
+	depends on (ARCH_OMAP1 || ARCH_OMAP2)
+	help
+	  Say Y here if you want to use the OMAP keypad.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called omap-keypad.
+
+config KEYBOARD_TOSA
+	tristate "Tosa keyboard"
+	depends on MACH_TOSA
+	default y
+	help
+	  Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tosakbd.
+
+config KEYBOARD_TOSA_USE_EXT_KEYCODES
+	bool "Tosa keyboard: use extended keycodes"
+	depends on KEYBOARD_TOSA
+	help
+	  Say Y here to enable the tosa keyboard driver to generate extended
+	  (>= 127) keycodes. Be aware, that they can't be correctly interpreted
+	  by either console keyboard driver or by Kdrive keybd driver.
+
+	  Say Y only if you know, what you are doing!
+
+config KEYBOARD_XTKBD
+	tristate "XT keyboard"
+	select SERIO
+	help
+	  Say Y here if you want to use the old IBM PC/XT keyboard (or
+	  compatible) on your system. This is only possible with a
+	  parallel port keyboard adapter, you cannot connect it to the
+	  keyboard port on a PC that runs Linux.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called xtkbd.
+
 endif
diff -druN linux-libre-2.6.30-gnu/drivers/input/keyboard/lm8323.c linux-libre-2.6.31-gnu/drivers/input/keyboard/lm8323.c
--- linux-libre-2.6.30-gnu/drivers/input/keyboard/lm8323.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/keyboard/lm8323.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,878 @@
+/*
+ * drivers/i2c/chips/lm8323.c
+ *
+ * Copyright (C) 2007-2009 Nokia Corporation
+ *
+ * Written by Daniel Stone <daniel.stone@nokia.com>
+ *            Timo O. Karjalainen <timo.o.karjalainen@nokia.com>
+ *
+ * Updated by Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License only).
+ *
+ * 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/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <linux/i2c/lm8323.h>
+
+/* Commands to send to the chip. */
+#define LM8323_CMD_READ_ID		0x80 /* Read chip ID. */
+#define LM8323_CMD_WRITE_CFG		0x81 /* Set configuration item. */
+#define LM8323_CMD_READ_INT		0x82 /* Get interrupt status. */
+#define LM8323_CMD_RESET		0x83 /* Reset, same as external one */
+#define LM8323_CMD_WRITE_PORT_SEL	0x85 /* Set GPIO in/out. */
+#define LM8323_CMD_WRITE_PORT_STATE	0x86 /* Set GPIO pullup. */
+#define LM8323_CMD_READ_PORT_SEL	0x87 /* Get GPIO in/out. */
+#define LM8323_CMD_READ_PORT_STATE	0x88 /* Get GPIO pullup. */
+#define LM8323_CMD_READ_FIFO		0x89 /* Read byte from FIFO. */
+#define LM8323_CMD_RPT_READ_FIFO	0x8a /* Read FIFO (no increment). */
+#define LM8323_CMD_SET_ACTIVE		0x8b /* Set active time. */
+#define LM8323_CMD_READ_ERR		0x8c /* Get error status. */
+#define LM8323_CMD_READ_ROTATOR		0x8e /* Read rotator status. */
+#define LM8323_CMD_SET_DEBOUNCE		0x8f /* Set debouncing time. */
+#define LM8323_CMD_SET_KEY_SIZE		0x90 /* Set keypad size. */
+#define LM8323_CMD_READ_KEY_SIZE	0x91 /* Get keypad size. */
+#define LM8323_CMD_READ_CFG		0x92 /* Get configuration item. */
+#define LM8323_CMD_WRITE_CLOCK		0x93 /* Set clock config. */
+#define LM8323_CMD_READ_CLOCK		0x94 /* Get clock config. */
+#define LM8323_CMD_PWM_WRITE		0x95 /* Write PWM script. */
+#define LM8323_CMD_START_PWM		0x96 /* Start PWM engine. */
+#define LM8323_CMD_STOP_PWM		0x97 /* Stop PWM engine. */
+
+/* Interrupt status. */
+#define INT_KEYPAD			0x01 /* Key event. */
+#define INT_ROTATOR			0x02 /* Rotator event. */
+#define INT_ERROR			0x08 /* Error: use CMD_READ_ERR. */
+#define INT_NOINIT			0x10 /* Lost configuration. */
+#define INT_PWM1			0x20 /* PWM1 stopped. */
+#define INT_PWM2			0x40 /* PWM2 stopped. */
+#define INT_PWM3			0x80 /* PWM3 stopped. */
+
+/* Errors (signalled by INT_ERROR, read with CMD_READ_ERR). */
+#define ERR_BADPAR			0x01 /* Bad parameter. */
+#define ERR_CMDUNK			0x02 /* Unknown command. */
+#define ERR_KEYOVR			0x04 /* Too many keys pressed. */
+#define ERR_FIFOOVER			0x40 /* FIFO overflow. */
+
+/* Configuration keys (CMD_{WRITE,READ}_CFG). */
+#define CFG_MUX1SEL			0x01 /* Select MUX1_OUT input. */
+#define CFG_MUX1EN			0x02 /* Enable MUX1_OUT. */
+#define CFG_MUX2SEL			0x04 /* Select MUX2_OUT input. */
+#define CFG_MUX2EN			0x08 /* Enable MUX2_OUT. */
+#define CFG_PSIZE			0x20 /* Package size (must be 0). */
+#define CFG_ROTEN			0x40 /* Enable rotator. */
+
+/* Clock settings (CMD_{WRITE,READ}_CLOCK). */
+#define CLK_RCPWM_INTERNAL		0x00
+#define CLK_RCPWM_EXTERNAL		0x03
+#define CLK_SLOWCLKEN			0x08 /* Enable 32.768kHz clock. */
+#define CLK_SLOWCLKOUT			0x40 /* Enable slow pulse output. */
+
+/* The possible addresses corresponding to CONFIG1 and CONFIG2 pin wirings. */
+#define LM8323_I2C_ADDR00		(0x84 >> 1)	/* 1000 010x */
+#define LM8323_I2C_ADDR01		(0x86 >> 1)	/* 1000 011x */
+#define LM8323_I2C_ADDR10		(0x88 >> 1)	/* 1000 100x */
+#define LM8323_I2C_ADDR11		(0x8A >> 1)	/* 1000 101x */
+
+/* Key event fifo length */
+#define LM8323_FIFO_LEN			15
+
+/* Commands for PWM engine; feed in with PWM_WRITE. */
+/* Load ramp counter from duty cycle field (range 0 - 0xff). */
+#define PWM_SET(v)			(0x4000 | ((v) & 0xff))
+/* Go to start of script. */
+#define PWM_GOTOSTART			0x0000
+/*
+ * Stop engine (generates interrupt).  If reset is 1, clear the program
+ * counter, else leave it.
+ */
+#define PWM_END(reset)			(0xc000 | (!!(reset) << 11))
+/*
+ * Ramp.  If s is 1, divide clock by 512, else divide clock by 16.
+ * Take t clock scales (up to 63) per step, for n steps (up to 126).
+ * If u is set, ramp up, else ramp down.
+ */
+#define PWM_RAMP(s, t, n, u)		((!!(s) << 14) | ((t) & 0x3f) << 8 | \
+					 ((n) & 0x7f) | ((u) ? 0 : 0x80))
+/*
+ * Loop (i.e. jump back to pos) for a given number of iterations (up to 63).
+ * If cnt is zero, execute until PWM_END is encountered.
+ */
+#define PWM_LOOP(cnt, pos)		(0xa000 | (((cnt) & 0x3f) << 7) | \
+					 ((pos) & 0x3f))
+/*
+ * Wait for trigger.  Argument is a mask of channels, shifted by the channel
+ * number, e.g. 0xa for channels 3 and 1.  Note that channels are numbered
+ * from 1, not 0.
+ */
+#define PWM_WAIT_TRIG(chans)		(0xe000 | (((chans) & 0x7) << 6))
+/* Send trigger.  Argument is same as PWM_WAIT_TRIG. */
+#define PWM_SEND_TRIG(chans)		(0xe000 | ((chans) & 0x7))
+
+struct lm8323_pwm {
+	int			id;
+	int			fade_time;
+	int			brightness;
+	int			desired_brightness;
+	bool			enabled;
+	bool			running;
+	/* pwm lock */
+	struct mutex		lock;
+	struct work_struct	work;
+	struct led_classdev	cdev;
+	struct lm8323_chip	*chip;
+};
+
+struct lm8323_chip {
+	/* device lock */
+	struct mutex		lock;
+	struct i2c_client	*client;
+	struct work_struct	work;
+	struct input_dev	*idev;
+	bool			kp_enabled;
+	bool			pm_suspend;
+	unsigned		keys_down;
+	char			phys[32];
+	unsigned short		keymap[LM8323_KEYMAP_SIZE];
+	int			size_x;
+	int			size_y;
+	int			debounce_time;
+	int			active_time;
+	struct lm8323_pwm	pwm[LM8323_NUM_PWMS];
+};
+
+#define client_to_lm8323(c)	container_of(c, struct lm8323_chip, client)
+#define dev_to_lm8323(d)	container_of(d, struct lm8323_chip, client->dev)
+#define work_to_lm8323(w)	container_of(w, struct lm8323_chip, work)
+#define cdev_to_pwm(c)		container_of(c, struct lm8323_pwm, cdev)
+#define work_to_pwm(w)		container_of(w, struct lm8323_pwm, work)
+
+#define LM8323_MAX_DATA 8
+
+/*
+ * To write, we just access the chip's address in write mode, and dump the
+ * command and data out on the bus.  The command byte and data are taken as
+ * sequential u8s out of varargs, to a maximum of LM8323_MAX_DATA.
+ */
+static int lm8323_write(struct lm8323_chip *lm, int len, ...)
+{
+	int ret, i;
+	va_list ap;
+	u8 data[LM8323_MAX_DATA];
+
+	va_start(ap, len);
+
+	if (unlikely(len > LM8323_MAX_DATA)) {
+		dev_err(&lm->client->dev, "tried to send %d bytes\n", len);
+		va_end(ap);
+		return 0;
+	}
+
+	for (i = 0; i < len; i++)
+		data[i] = va_arg(ap, int);
+
+	va_end(ap);
+
+	/*
+	 * If the host is asleep while we send the data, we can get a NACK
+	 * back while it wakes up, so try again, once.
+	 */
+	ret = i2c_master_send(lm->client, data, len);
+	if (unlikely(ret == -EREMOTEIO))
+		ret = i2c_master_send(lm->client, data, len);
+	if (unlikely(ret != len))
+		dev_err(&lm->client->dev, "sent %d bytes of %d total\n",
+			len, ret);
+
+	return ret;
+}
+
+/*
+ * To read, we first send the command byte to the chip and end the transaction,
+ * then access the chip in read mode, at which point it will send the data.
+ */
+static int lm8323_read(struct lm8323_chip *lm, u8 cmd, u8 *buf, int len)
+{
+	int ret;
+
+	/*
+	 * If the host is asleep while we send the byte, we can get a NACK
+	 * back while it wakes up, so try again, once.
+	 */
+	ret = i2c_master_send(lm->client, &cmd, 1);
+	if (unlikely(ret == -EREMOTEIO))
+		ret = i2c_master_send(lm->client, &cmd, 1);
+	if (unlikely(ret != 1)) {
+		dev_err(&lm->client->dev, "sending read cmd 0x%02x failed\n",
+			cmd);
+		return 0;
+	}
+
+	ret = i2c_master_recv(lm->client, buf, len);
+	if (unlikely(ret != len))
+		dev_err(&lm->client->dev, "wanted %d bytes, got %d\n",
+			len, ret);
+
+	return ret;
+}
+
+/*
+ * Set the chip active time (idle time before it enters halt).
+ */
+static void lm8323_set_active_time(struct lm8323_chip *lm, int time)
+{
+	lm8323_write(lm, 2, LM8323_CMD_SET_ACTIVE, time >> 2);
+}
+
+/*
+ * The signals are AT-style: the low 7 bits are the keycode, and the top
+ * bit indicates the state (1 for down, 0 for up).
+ */
+static inline u8 lm8323_whichkey(u8 event)
+{
+	return event & 0x7f;
+}
+
+static inline int lm8323_ispress(u8 event)
+{
+	return (event & 0x80) ? 1 : 0;
+}
+
+static void process_keys(struct lm8323_chip *lm)
+{
+	u8 event;
+	u8 key_fifo[LM8323_FIFO_LEN + 1];
+	int old_keys_down = lm->keys_down;
+	int ret;
+	int i = 0;
+
+	/*
+	 * Read all key events from the FIFO at once. Next READ_FIFO clears the
+	 * FIFO even if we didn't read all events previously.
+	 */
+	ret = lm8323_read(lm, LM8323_CMD_READ_FIFO, key_fifo, LM8323_FIFO_LEN);
+
+	if (ret < 0) {
+		dev_err(&lm->client->dev, "Failed reading fifo \n");
+		return;
+	}
+	key_fifo[ret] = 0;
+
+	while ((event = key_fifo[i++])) {
+		u8 key = lm8323_whichkey(event);
+		int isdown = lm8323_ispress(event);
+		unsigned short keycode = lm->keymap[key];
+
+		dev_vdbg(&lm->client->dev, "key 0x%02x %s\n",
+			 key, isdown ? "down" : "up");
+
+		if (lm->kp_enabled) {
+			input_event(lm->idev, EV_MSC, MSC_SCAN, key);
+			input_report_key(lm->idev, keycode, isdown);
+			input_sync(lm->idev);
+		}
+
+		if (isdown)
+			lm->keys_down++;
+		else
+			lm->keys_down--;
+	}
+
+	/*
+	 * Errata: We need to ensure that the chip never enters halt mode
+	 * during a keypress, so set active time to 0.  When it's released,
+	 * we can enter halt again, so set the active time back to normal.
+	 */
+	if (!old_keys_down && lm->keys_down)
+		lm8323_set_active_time(lm, 0);
+	if (old_keys_down && !lm->keys_down)
+		lm8323_set_active_time(lm, lm->active_time);
+}
+
+static void lm8323_process_error(struct lm8323_chip *lm)
+{
+	u8 error;
+
+	if (lm8323_read(lm, LM8323_CMD_READ_ERR, &error, 1) == 1) {
+		if (error & ERR_FIFOOVER)
+			dev_vdbg(&lm->client->dev, "fifo overflow!\n");
+		if (error & ERR_KEYOVR)
+			dev_vdbg(&lm->client->dev,
+					"more than two keys pressed\n");
+		if (error & ERR_CMDUNK)
+			dev_vdbg(&lm->client->dev,
+					"unknown command submitted\n");
+		if (error & ERR_BADPAR)
+			dev_vdbg(&lm->client->dev, "bad command parameter\n");
+	}
+}
+
+static void lm8323_reset(struct lm8323_chip *lm)
+{
+	/* The docs say we must pass 0xAA as the data byte. */
+	lm8323_write(lm, 2, LM8323_CMD_RESET, 0xAA);
+}
+
+static int lm8323_configure(struct lm8323_chip *lm)
+{
+	int keysize = (lm->size_x << 4) | lm->size_y;
+	int clock = (CLK_SLOWCLKEN | CLK_RCPWM_EXTERNAL);
+	int debounce = lm->debounce_time >> 2;
+	int active = lm->active_time >> 2;
+
+	/*
+	 * Active time must be greater than the debounce time: if it's
+	 * a close-run thing, give ourselves a 12ms buffer.
+	 */
+	if (debounce >= active)
+		active = debounce + 3;
+
+	lm8323_write(lm, 2, LM8323_CMD_WRITE_CFG, 0);
+	lm8323_write(lm, 2, LM8323_CMD_WRITE_CLOCK, clock);
+	lm8323_write(lm, 2, LM8323_CMD_SET_KEY_SIZE, keysize);
+	lm8323_set_active_time(lm, lm->active_time);
+	lm8323_write(lm, 2, LM8323_CMD_SET_DEBOUNCE, debounce);
+	lm8323_write(lm, 3, LM8323_CMD_WRITE_PORT_STATE, 0xff, 0xff);
+	lm8323_write(lm, 3, LM8323_CMD_WRITE_PORT_SEL, 0, 0);
+
+	/*
+	 * Not much we can do about errors at this point, so just hope
+	 * for the best.
+	 */
+
+	return 0;
+}
+
+static void pwm_done(struct lm8323_pwm *pwm)
+{
+	mutex_lock(&pwm->lock);
+	pwm->running = false;
+	if (pwm->desired_brightness != pwm->brightness)
+		schedule_work(&pwm->work);
+	mutex_unlock(&pwm->lock);
+}
+
+/*
+ * Bottom half: handle the interrupt by posting key events, or dealing with
+ * errors appropriately.
+ */
+static void lm8323_work(struct work_struct *work)
+{
+	struct lm8323_chip *lm = work_to_lm8323(work);
+	u8 ints;
+	int i;
+
+	mutex_lock(&lm->lock);
+
+	while ((lm8323_read(lm, LM8323_CMD_READ_INT, &ints, 1) == 1) && ints) {
+		if (likely(ints & INT_KEYPAD))
+			process_keys(lm);
+		if (ints & INT_ROTATOR) {
+			/* We don't currently support the rotator. */
+			dev_vdbg(&lm->client->dev, "rotator fired\n");
+		}
+		if (ints & INT_ERROR) {
+			dev_vdbg(&lm->client->dev, "error!\n");
+			lm8323_process_error(lm);
+		}
+		if (ints & INT_NOINIT) {
+			dev_err(&lm->client->dev, "chip lost config; "
+						  "reinitialising\n");
+			lm8323_configure(lm);
+		}
+		for (i = 0; i < LM8323_NUM_PWMS; i++) {
+			if (ints & (1 << (INT_PWM1 + i))) {
+				dev_vdbg(&lm->client->dev,
+					 "pwm%d engine completed\n", i);
+				pwm_done(&lm->pwm[i]);
+			}
+		}
+	}
+
+	mutex_unlock(&lm->lock);
+}
+
+/*
+ * We cannot use I2C in interrupt context, so we just schedule work.
+ */
+static irqreturn_t lm8323_irq(int irq, void *data)
+{
+	struct lm8323_chip *lm = data;
+
+	schedule_work(&lm->work);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Read the chip ID.
+ */
+static int lm8323_read_id(struct lm8323_chip *lm, u8 *buf)
+{
+	int bytes;
+
+	bytes = lm8323_read(lm, LM8323_CMD_READ_ID, buf, 2);
+	if (unlikely(bytes != 2))
+		return -EIO;
+
+	return 0;
+}
+
+static void lm8323_write_pwm_one(struct lm8323_pwm *pwm, int pos, u16 cmd)
+{
+	lm8323_write(pwm->chip, 4, LM8323_CMD_PWM_WRITE, (pos << 2) | pwm->id,
+		     (cmd & 0xff00) >> 8, cmd & 0x00ff);
+}
+
+/*
+ * Write a script into a given PWM engine, concluding with PWM_END.
+ * If 'kill' is nonzero, the engine will be shut down at the end
+ * of the script, producing a zero output. Otherwise the engine
+ * will be kept running at the final PWM level indefinitely.
+ */
+static void lm8323_write_pwm(struct lm8323_pwm *pwm, int kill,
+			     int len, const u16 *cmds)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		lm8323_write_pwm_one(pwm, i, cmds[i]);
+
+	lm8323_write_pwm_one(pwm, i++, PWM_END(kill));
+	lm8323_write(pwm->chip, 2, LM8323_CMD_START_PWM, pwm->id);
+	pwm->running = true;
+}
+
+static void lm8323_pwm_work(struct work_struct *work)
+{
+	struct lm8323_pwm *pwm = work_to_pwm(work);
+	int div512, perstep, steps, hz, up, kill;
+	u16 pwm_cmds[3];
+	int num_cmds = 0;
+
+	mutex_lock(&pwm->lock);
+
+	/*
+	 * Do nothing if we're already at the requested level,
+	 * or previous setting is not yet complete. In the latter
+	 * case we will be called again when the previous PWM script
+	 * finishes.
+	 */
+	if (pwm->running || pwm->desired_brightness == pwm->brightness)
+		goto out;
+
+	kill = (pwm->desired_brightness == 0);
+	up = (pwm->desired_brightness > pwm->brightness);
+	steps = abs(pwm->desired_brightness - pwm->brightness);
+
+	/*
+	 * Convert time (in ms) into a divisor (512 or 16 on a refclk of
+	 * 32768Hz), and number of ticks per step.
+	 */
+	if ((pwm->fade_time / steps) > (32768 / 512)) {
+		div512 = 1;
+		hz = 32768 / 512;
+	} else {
+		div512 = 0;
+		hz = 32768 / 16;
+	}
+
+	perstep = (hz * pwm->fade_time) / (steps * 1000);
+
+	if (perstep == 0)
+		perstep = 1;
+	else if (perstep > 63)
+		perstep = 63;
+
+	while (steps) {
+		int s;
+
+		s = min(126, steps);
+		pwm_cmds[num_cmds++] = PWM_RAMP(div512, perstep, s, up);
+		steps -= s;
+	}
+
+	lm8323_write_pwm(pwm, kill, num_cmds, pwm_cmds);
+	pwm->brightness = pwm->desired_brightness;
+
+ out:
+	mutex_unlock(&pwm->lock);
+}
+
+static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev,
+				      enum led_brightness brightness)
+{
+	struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev);
+	struct lm8323_chip *lm = pwm->chip;
+
+	mutex_lock(&pwm->lock);
+	pwm->desired_brightness = brightness;
+	mutex_unlock(&pwm->lock);
+
+	if (in_interrupt()) {
+		schedule_work(&pwm->work);
+	} else {
+		/*
+		 * Schedule PWM work as usual unless we are going into suspend
+		 */
+		mutex_lock(&lm->lock);
+		if (likely(!lm->pm_suspend))
+			schedule_work(&pwm->work);
+		else
+			lm8323_pwm_work(&pwm->work);
+		mutex_unlock(&lm->lock);
+	}
+}
+
+static ssize_t lm8323_pwm_show_time(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev);
+
+	return sprintf(buf, "%d\n", pwm->fade_time);
+}
+
+static ssize_t lm8323_pwm_store_time(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t len)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev);
+	int ret;
+	unsigned long time;
+
+	ret = strict_strtoul(buf, 10, &time);
+	/* Numbers only, please. */
+	if (ret)
+		return -EINVAL;
+
+	pwm->fade_time = time;
+
+	return strlen(buf);
+}
+static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time);
+
+static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev,
+		    const char *name)
+{
+	struct lm8323_pwm *pwm;
+
+	BUG_ON(id > 3);
+
+	pwm = &lm->pwm[id - 1];
+
+	pwm->id = id;
+	pwm->fade_time = 0;
+	pwm->brightness = 0;
+	pwm->desired_brightness = 0;
+	pwm->running = false;
+	pwm->enabled = false;
+	INIT_WORK(&pwm->work, lm8323_pwm_work);
+	mutex_init(&pwm->lock);
+	pwm->chip = lm;
+
+	if (name) {
+		pwm->cdev.name = name;
+		pwm->cdev.brightness_set = lm8323_pwm_set_brightness;
+		if (led_classdev_register(dev, &pwm->cdev) < 0) {
+			dev_err(dev, "couldn't register PWM %d\n", id);
+			return -1;
+		}
+		if (device_create_file(pwm->cdev.dev,
+					&dev_attr_time) < 0) {
+			dev_err(dev, "couldn't register time attribute\n");
+			led_classdev_unregister(&pwm->cdev);
+			return -1;
+		}
+		pwm->enabled = true;
+	}
+
+	return 0;
+}
+
+static struct i2c_driver lm8323_i2c_driver;
+
+static ssize_t lm8323_show_disable(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct lm8323_chip *lm = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", !lm->kp_enabled);
+}
+
+static ssize_t lm8323_set_disable(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct lm8323_chip *lm = dev_get_drvdata(dev);
+	int ret;
+	unsigned long i;
+
+	ret = strict_strtoul(buf, 10, &i);
+
+	mutex_lock(&lm->lock);
+	lm->kp_enabled = !i;
+	mutex_unlock(&lm->lock);
+
+	return count;
+}
+static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable);
+
+static int __devinit lm8323_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct lm8323_platform_data *pdata = client->dev.platform_data;
+	struct input_dev *idev;
+	struct lm8323_chip *lm;
+	int i, err;
+	unsigned long tmo;
+	u8 data[2];
+
+	if (!pdata || !pdata->size_x || !pdata->size_y) {
+		dev_err(&client->dev, "missing platform_data\n");
+		return -EINVAL;
+	}
+
+	if (pdata->size_x > 8) {
+		dev_err(&client->dev, "invalid x size %d specified\n",
+			pdata->size_x);
+		return -EINVAL;
+	}
+
+	if (pdata->size_y > 12) {
+		dev_err(&client->dev, "invalid y size %d specified\n",
+			pdata->size_y);
+		return -EINVAL;
+	}
+
+	lm = kzalloc(sizeof *lm, GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!lm || !idev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
+
+	i2c_set_clientdata(client, lm);
+
+	lm->client = client;
+	lm->idev = idev;
+	mutex_init(&lm->lock);
+	INIT_WORK(&lm->work, lm8323_work);
+
+	lm->size_x = pdata->size_x;
+	lm->size_y = pdata->size_y;
+	dev_vdbg(&client->dev, "Keypad size: %d x %d\n",
+		 lm->size_x, lm->size_y);
+
+	lm->debounce_time = pdata->debounce_time;
+	lm->active_time = pdata->active_time;
+
+	lm8323_reset(lm);
+
+	/* Nothing's set up to service the IRQ yet, so just spin for max.
+	 * 100ms until we can configure. */
+	tmo = jiffies + msecs_to_jiffies(100);
+	while (lm8323_read(lm, LM8323_CMD_READ_INT, data, 1) == 1) {
+		if (data[0] & INT_NOINIT)
+			break;
+
+		if (time_after(jiffies, tmo)) {
+			dev_err(&client->dev,
+				"timeout waiting for initialisation\n");
+			break;
+		}
+
+		msleep(1);
+	}
+
+	lm8323_configure(lm);
+
+	/* If a true probe check the device */
+	if (lm8323_read_id(lm, data) != 0) {
+		dev_err(&client->dev, "device not found\n");
+		err = -ENODEV;
+		goto fail1;
+	}
+
+	for (i = 0; i < LM8323_NUM_PWMS; i++) {
+		err = init_pwm(lm, i + 1, &client->dev, pdata->pwm_names[i]);
+		if (err < 0)
+			goto fail2;
+	}
+
+	lm->kp_enabled = true;
+	err = device_create_file(&client->dev, &dev_attr_disable_kp);
+	if (err < 0)
+		goto fail2;
+
+	idev->name = pdata->name ? : "LM8323 keypad";
+	snprintf(lm->phys, sizeof(lm->phys),
+		 "%s/input-kp", dev_name(&client->dev));
+	idev->phys = lm->phys;
+
+	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_MSC);
+	__set_bit(MSC_SCAN, idev->mscbit);
+	for (i = 0; i < LM8323_KEYMAP_SIZE; i++) {
+		__set_bit(pdata->keymap[i], idev->keybit);
+		lm->keymap[i] = pdata->keymap[i];
+	}
+	__clear_bit(KEY_RESERVED, idev->keybit);
+
+	if (pdata->repeat)
+		__set_bit(EV_REP, idev->evbit);
+
+	err = input_register_device(idev);
+	if (err) {
+		dev_dbg(&client->dev, "error registering input device\n");
+		goto fail3;
+	}
+
+	err = request_irq(client->irq, lm8323_irq,
+			  IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+			  "lm8323", lm);
+	if (err) {
+		dev_err(&client->dev, "could not get IRQ %d\n", client->irq);
+		goto fail4;
+	}
+
+	device_init_wakeup(&client->dev, 1);
+	enable_irq_wake(client->irq);
+
+	return 0;
+
+fail4:
+	input_unregister_device(idev);
+	idev = NULL;
+fail3:
+	device_remove_file(&client->dev, &dev_attr_disable_kp);
+fail2:
+	while (--i >= 0)
+		if (lm->pwm[i].enabled)
+			led_classdev_unregister(&lm->pwm[i].cdev);
+fail1:
+	input_free_device(idev);
+	kfree(lm);
+	return err;
+}
+
+static int __devexit lm8323_remove(struct i2c_client *client)
+{
+	struct lm8323_chip *lm = i2c_get_clientdata(client);
+	int i;
+
+	disable_irq_wake(client->irq);
+	free_irq(client->irq, lm);
+	cancel_work_sync(&lm->work);
+
+	input_unregister_device(lm->idev);
+
+	device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
+
+	for (i = 0; i < 3; i++)
+		if (lm->pwm[i].enabled)
+			led_classdev_unregister(&lm->pwm[i].cdev);
+
+	kfree(lm);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * We don't need to explicitly suspend the chip, as it already switches off
+ * when there's no activity.
+ */
+static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct lm8323_chip *lm = i2c_get_clientdata(client);
+	int i;
+
+	set_irq_wake(client->irq, 0);
+	disable_irq(client->irq);
+
+	mutex_lock(&lm->lock);
+	lm->pm_suspend = true;
+	mutex_unlock(&lm->lock);
+
+	for (i = 0; i < 3; i++)
+		if (lm->pwm[i].enabled)
+			led_classdev_suspend(&lm->pwm[i].cdev);
+
+	return 0;
+}
+
+static int lm8323_resume(struct i2c_client *client)
+{
+	struct lm8323_chip *lm = i2c_get_clientdata(client);
+	int i;
+
+	mutex_lock(&lm->lock);
+	lm->pm_suspend = false;
+	mutex_unlock(&lm->lock);
+
+	for (i = 0; i < 3; i++)
+		if (lm->pwm[i].enabled)
+			led_classdev_resume(&lm->pwm[i].cdev);
+
+	enable_irq(client->irq);
+	set_irq_wake(client->irq, 1);
+
+	return 0;
+}
+#else
+#define lm8323_suspend	NULL
+#define lm8323_resume	NULL
+#endif
+
+static const struct i2c_device_id lm8323_id[] = {
+	{ "lm8323", 0 },
+	{ }
+};
+
+static struct i2c_driver lm8323_i2c_driver = {
+	.driver = {
+		.name	= "lm8323",
+	},
+	.probe		= lm8323_probe,
+	.remove		= __devexit_p(lm8323_remove),
+	.suspend	= lm8323_suspend,
+	.resume		= lm8323_resume,
+	.id_table	= lm8323_id,
+};
+MODULE_DEVICE_TABLE(i2c, lm8323_id);
+
+static int __init lm8323_init(void)
+{
+	return i2c_add_driver(&lm8323_i2c_driver);
+}
+module_init(lm8323_init);
+
+static void __exit lm8323_exit(void)
+{
+	i2c_del_driver(&lm8323_i2c_driver);
+}
+module_exit(lm8323_exit);
+
+MODULE_AUTHOR("Timo O. Karjalainen <timo.o.karjalainen@nokia.com>");
+MODULE_AUTHOR("Daniel Stone");
+MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
+MODULE_DESCRIPTION("LM8323 keypad driver");
+MODULE_LICENSE("GPL");
+
diff -druN linux-libre-2.6.30-gnu/drivers/input/keyboard/Makefile linux-libre-2.6.31-gnu/drivers/input/keyboard/Makefile
--- linux-libre-2.6.30-gnu/drivers/input/keyboard/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/keyboard/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,27 +4,30 @@
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_KEYBOARD_ATKBD)		+= atkbd.o
-obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
-obj-$(CONFIG_KEYBOARD_LKKBD)		+= lkkbd.o
-obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
+obj-$(CONFIG_KEYBOARD_AAED2000)		+= aaed2000_kbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
 obj-$(CONFIG_KEYBOARD_ATARI)		+= atakbd.o
-obj-$(CONFIG_KEYBOARD_LOCOMO)		+= locomokbd.o
-obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
-obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
+obj-$(CONFIG_KEYBOARD_ATKBD)		+= atkbd.o
+obj-$(CONFIG_KEYBOARD_BFIN)		+= bf54x-keys.o
 obj-$(CONFIG_KEYBOARD_CORGI)		+= corgikbd.o
-obj-$(CONFIG_KEYBOARD_SPITZ)		+= spitzkbd.o
-obj-$(CONFIG_KEYBOARD_TOSA)		+= tosakbd.o
+obj-$(CONFIG_KEYBOARD_EP93XX)		+= ep93xx_keypad.o
+obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
-obj-$(CONFIG_KEYBOARD_OMAP)		+= omap-keypad.o
-obj-$(CONFIG_KEYBOARD_PXA27x)		+= pxa27x_keypad.o
-obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)	+= pxa930_rotary.o
-obj-$(CONFIG_KEYBOARD_AAED2000)		+= aaed2000_kbd.o
-obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
 obj-$(CONFIG_KEYBOARD_HP6XX)		+= jornada680_kbd.o
 obj-$(CONFIG_KEYBOARD_HP7XX)		+= jornada720_kbd.o
+obj-$(CONFIG_KEYBOARD_LKKBD)		+= lkkbd.o
+obj-$(CONFIG_KEYBOARD_LM8323)		+= lm8323.o
+obj-$(CONFIG_KEYBOARD_LOCOMO)		+= locomokbd.o
 obj-$(CONFIG_KEYBOARD_MAPLE)		+= maple_keyb.o
-obj-$(CONFIG_KEYBOARD_BFIN)		+= bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_MATRIX)		+= matrix_keypad.o
+obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
+obj-$(CONFIG_KEYBOARD_OMAP)		+= omap-keypad.o
+obj-$(CONFIG_KEYBOARD_PXA27x)		+= pxa27x_keypad.o
+obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)	+= pxa930_rotary.o
 obj-$(CONFIG_KEYBOARD_SH_KEYSC)		+= sh_keysc.o
+obj-$(CONFIG_KEYBOARD_SPITZ)		+= spitzkbd.o
+obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
+obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
+obj-$(CONFIG_KEYBOARD_TOSA)		+= tosakbd.o
+obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
diff -druN linux-libre-2.6.30-gnu/drivers/input/keyboard/matrix_keypad.c linux-libre-2.6.31-gnu/drivers/input/keyboard/matrix_keypad.c
--- linux-libre-2.6.30-gnu/drivers/input/keyboard/matrix_keypad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/keyboard/matrix_keypad.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,453 @@
+/*
+ *  GPIO driven matrix keyboard driver
+ *
+ *  Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ *  Based on corgikbd.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.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/input/matrix_keypad.h>
+
+struct matrix_keypad {
+	const struct matrix_keypad_platform_data *pdata;
+	struct input_dev *input_dev;
+	unsigned short *keycodes;
+	unsigned int row_shift;
+
+	uint32_t last_key_state[MATRIX_MAX_COLS];
+	struct delayed_work work;
+	bool scan_pending;
+	bool stopped;
+	spinlock_t lock;
+};
+
+/*
+ * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
+ * minmal side effect when scanning other columns, here it is configured to
+ * be input, and it should work on most platforms.
+ */
+static void __activate_col(const struct matrix_keypad_platform_data *pdata,
+			   int col, bool on)
+{
+	bool level_on = !pdata->active_low;
+
+	if (on) {
+		gpio_direction_output(pdata->col_gpios[col], level_on);
+	} else {
+		gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
+		gpio_direction_input(pdata->col_gpios[col]);
+	}
+}
+
+static void activate_col(const struct matrix_keypad_platform_data *pdata,
+			 int col, bool on)
+{
+	__activate_col(pdata, col, on);
+
+	if (on && pdata->col_scan_delay_us)
+		udelay(pdata->col_scan_delay_us);
+}
+
+static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
+			      bool on)
+{
+	int col;
+
+	for (col = 0; col < pdata->num_col_gpios; col++)
+		__activate_col(pdata, col, on);
+}
+
+static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
+			 int row)
+{
+	return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
+			!pdata->active_low : pdata->active_low;
+}
+
+static void enable_row_irqs(struct matrix_keypad *keypad)
+{
+	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+	int i;
+
+	for (i = 0; i < pdata->num_row_gpios; i++)
+		enable_irq(gpio_to_irq(pdata->row_gpios[i]));
+}
+
+static void disable_row_irqs(struct matrix_keypad *keypad)
+{
+	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+	int i;
+
+	for (i = 0; i < pdata->num_row_gpios; i++)
+		disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
+}
+
+/*
+ * This gets the keys from keyboard and reports it to input subsystem
+ */
+static void matrix_keypad_scan(struct work_struct *work)
+{
+	struct matrix_keypad *keypad =
+		container_of(work, struct matrix_keypad, work.work);
+	struct input_dev *input_dev = keypad->input_dev;
+	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+	uint32_t new_state[MATRIX_MAX_COLS];
+	int row, col, code;
+
+	/* de-activate all columns for scanning */
+	activate_all_cols(pdata, false);
+
+	memset(new_state, 0, sizeof(new_state));
+
+	/* assert each column and read the row status out */
+	for (col = 0; col < pdata->num_col_gpios; col++) {
+
+		activate_col(pdata, col, true);
+
+		for (row = 0; row < pdata->num_row_gpios; row++)
+			new_state[col] |=
+				row_asserted(pdata, row) ? (1 << row) : 0;
+
+		activate_col(pdata, col, false);
+	}
+
+	for (col = 0; col < pdata->num_col_gpios; col++) {
+		uint32_t bits_changed;
+
+		bits_changed = keypad->last_key_state[col] ^ new_state[col];
+		if (bits_changed == 0)
+			continue;
+
+		for (row = 0; row < pdata->num_row_gpios; row++) {
+			if ((bits_changed & (1 << row)) == 0)
+				continue;
+
+			code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+			input_event(input_dev, EV_MSC, MSC_SCAN, code);
+			input_report_key(input_dev,
+					 keypad->keycodes[code],
+					 new_state[col] & (1 << row));
+		}
+	}
+	input_sync(input_dev);
+
+	memcpy(keypad->last_key_state, new_state, sizeof(new_state));
+
+	activate_all_cols(pdata, true);
+
+	/* Enable IRQs again */
+	spin_lock_irq(&keypad->lock);
+	keypad->scan_pending = false;
+	enable_row_irqs(keypad);
+	spin_unlock_irq(&keypad->lock);
+}
+
+static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
+{
+	struct matrix_keypad *keypad = id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&keypad->lock, flags);
+
+	/*
+	 * See if another IRQ beaten us to it and scheduled the
+	 * scan already. In that case we should not try to
+	 * disable IRQs again.
+	 */
+	if (unlikely(keypad->scan_pending || keypad->stopped))
+		goto out;
+
+	disable_row_irqs(keypad);
+	keypad->scan_pending = true;
+	schedule_delayed_work(&keypad->work,
+		msecs_to_jiffies(keypad->pdata->debounce_ms));
+
+out:
+	spin_unlock_irqrestore(&keypad->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static int matrix_keypad_start(struct input_dev *dev)
+{
+	struct matrix_keypad *keypad = input_get_drvdata(dev);
+
+	keypad->stopped = false;
+	mb();
+
+	/*
+	 * Schedule an immediate key scan to capture current key state;
+	 * columns will be activated and IRQs be enabled after the scan.
+	 */
+	schedule_delayed_work(&keypad->work, 0);
+
+	return 0;
+}
+
+static void matrix_keypad_stop(struct input_dev *dev)
+{
+	struct matrix_keypad *keypad = input_get_drvdata(dev);
+
+	keypad->stopped = true;
+	mb();
+	flush_work(&keypad->work.work);
+	/*
+	 * matrix_keypad_scan() will leave IRQs enabled;
+	 * we should disable them now.
+	 */
+	disable_row_irqs(keypad);
+}
+
+#ifdef CONFIG_PM
+static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct matrix_keypad *keypad = platform_get_drvdata(pdev);
+	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+	int i;
+
+	matrix_keypad_stop(keypad->input_dev);
+
+	if (device_may_wakeup(&pdev->dev))
+		for (i = 0; i < pdata->num_row_gpios; i++)
+			enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+
+	return 0;
+}
+
+static int matrix_keypad_resume(struct platform_device *pdev)
+{
+	struct matrix_keypad *keypad = platform_get_drvdata(pdev);
+	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+	int i;
+
+	if (device_may_wakeup(&pdev->dev))
+		for (i = 0; i < pdata->num_row_gpios; i++)
+			disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+
+	matrix_keypad_start(keypad->input_dev);
+
+	return 0;
+}
+#else
+#define matrix_keypad_suspend	NULL
+#define matrix_keypad_resume	NULL
+#endif
+
+static int __devinit init_matrix_gpio(struct platform_device *pdev,
+					struct matrix_keypad *keypad)
+{
+	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+	int i, err = -EINVAL;
+
+	/* initialized strobe lines as outputs, activated */
+	for (i = 0; i < pdata->num_col_gpios; i++) {
+		err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
+		if (err) {
+			dev_err(&pdev->dev,
+				"failed to request GPIO%d for COL%d\n",
+				pdata->col_gpios[i], i);
+			goto err_free_cols;
+		}
+
+		gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
+	}
+
+	for (i = 0; i < pdata->num_row_gpios; i++) {
+		err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
+		if (err) {
+			dev_err(&pdev->dev,
+				"failed to request GPIO%d for ROW%d\n",
+				pdata->row_gpios[i], i);
+			goto err_free_rows;
+		}
+
+		gpio_direction_input(pdata->row_gpios[i]);
+	}
+
+	for (i = 0; i < pdata->num_row_gpios; i++) {
+		err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
+				matrix_keypad_interrupt,
+				IRQF_DISABLED |
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"matrix-keypad", keypad);
+		if (err) {
+			dev_err(&pdev->dev,
+				"Unable to acquire interrupt for GPIO line %i\n",
+				pdata->row_gpios[i]);
+			goto err_free_irqs;
+		}
+	}
+
+	/* initialized as disabled - enabled by input->open */
+	disable_row_irqs(keypad);
+	return 0;
+
+err_free_irqs:
+	while (--i >= 0)
+		free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
+	i = pdata->num_row_gpios;
+err_free_rows:
+	while (--i >= 0)
+		gpio_free(pdata->row_gpios[i]);
+	i = pdata->num_col_gpios;
+err_free_cols:
+	while (--i >= 0)
+		gpio_free(pdata->col_gpios[i]);
+
+	return err;
+}
+
+static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+{
+	const struct matrix_keypad_platform_data *pdata;
+	const struct matrix_keymap_data *keymap_data;
+	struct matrix_keypad *keypad;
+	struct input_dev *input_dev;
+	unsigned short *keycodes;
+	unsigned int row_shift;
+	int i;
+	int err;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
+
+	keymap_data = pdata->keymap_data;
+	if (!keymap_data) {
+		dev_err(&pdev->dev, "no keymap data defined\n");
+		return -EINVAL;
+	}
+
+	row_shift = get_count_order(pdata->num_col_gpios);
+
+	keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
+	keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
+				sizeof(*keycodes),
+			   GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!keypad || !keycodes || !input_dev) {
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	keypad->input_dev = input_dev;
+	keypad->pdata = pdata;
+	keypad->keycodes = keycodes;
+	keypad->row_shift = row_shift;
+	keypad->stopped = true;
+	INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
+	spin_lock_init(&keypad->lock);
+
+	input_dev->name		= pdev->name;
+	input_dev->id.bustype	= BUS_HOST;
+	input_dev->dev.parent	= &pdev->dev;
+	input_dev->evbit[0]	= BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+	input_dev->open		= matrix_keypad_start;
+	input_dev->close	= matrix_keypad_stop;
+
+	input_dev->keycode	= keycodes;
+	input_dev->keycodesize	= sizeof(*keycodes);
+	input_dev->keycodemax	= pdata->num_row_gpios << keypad->row_shift;
+
+	for (i = 0; i < keymap_data->keymap_size; i++) {
+		unsigned int key = keymap_data->keymap[i];
+		unsigned int row = KEY_ROW(key);
+		unsigned int col = KEY_COL(key);
+		unsigned short code = KEY_VAL(key);
+
+		keycodes[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
+		__set_bit(code, input_dev->keybit);
+	}
+	__clear_bit(KEY_RESERVED, input_dev->keybit);
+
+	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+	input_set_drvdata(input_dev, keypad);
+
+	err = init_matrix_gpio(pdev, keypad);
+	if (err)
+		goto err_free_mem;
+
+	err = input_register_device(keypad->input_dev);
+	if (err)
+		goto err_free_mem;
+
+	device_init_wakeup(&pdev->dev, pdata->wakeup);
+	platform_set_drvdata(pdev, keypad);
+
+	return 0;
+
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(keycodes);
+	kfree(keypad);
+	return err;
+}
+
+static int __devexit matrix_keypad_remove(struct platform_device *pdev)
+{
+	struct matrix_keypad *keypad = platform_get_drvdata(pdev);
+	const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+	int i;
+
+	device_init_wakeup(&pdev->dev, 0);
+
+	for (i = 0; i < pdata->num_row_gpios; i++) {
+		free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
+		gpio_free(pdata->row_gpios[i]);
+	}
+
+	for (i = 0; i < pdata->num_col_gpios; i++)
+		gpio_free(pdata->col_gpios[i]);
+
+	input_unregister_device(keypad->input_dev);
+	platform_set_drvdata(pdev, NULL);
+	kfree(keypad->keycodes);
+	kfree(keypad);
+
+	return 0;
+}
+
+static struct platform_driver matrix_keypad_driver = {
+	.probe		= matrix_keypad_probe,
+	.remove		= __devexit_p(matrix_keypad_remove),
+	.suspend	= matrix_keypad_suspend,
+	.resume		= matrix_keypad_resume,
+	.driver		= {
+		.name	= "matrix-keypad",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init matrix_keypad_init(void)
+{
+	return platform_driver_register(&matrix_keypad_driver);
+}
+
+static void __exit matrix_keypad_exit(void)
+{
+	platform_driver_unregister(&matrix_keypad_driver);
+}
+
+module_init(matrix_keypad_init);
+module_exit(matrix_keypad_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:matrix-keypad");
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/ati_remote2.c linux-libre-2.6.31-gnu/drivers/input/misc/ati_remote2.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/ati_remote2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/ati_remote2.c	2009-09-09 18:13:59.000000000 -0400
@@ -509,7 +509,7 @@
 
 	old_keycode = ar2->keycode[mode][index];
 	ar2->keycode[mode][index] = keycode;
-	set_bit(keycode, idev->keybit);
+	__set_bit(keycode, idev->keybit);
 
 	for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
 		for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
@@ -518,7 +518,7 @@
 		}
 	}
 
-	clear_bit(old_keycode, idev->keybit);
+	__clear_bit(old_keycode, idev->keybit);
 
 	return 0;
 }
@@ -543,7 +543,7 @@
 	for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
 		for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
 			ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode;
-			set_bit(ar2->keycode[mode][index], idev->keybit);
+			__set_bit(ar2->keycode[mode][index], idev->keybit);
 		}
 	}
 
@@ -554,11 +554,11 @@
 	ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3;
 	ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4;
 	ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC;
-	set_bit(KEY_PROG1, idev->keybit);
-	set_bit(KEY_PROG2, idev->keybit);
-	set_bit(KEY_PROG3, idev->keybit);
-	set_bit(KEY_PROG4, idev->keybit);
-	set_bit(KEY_PC, idev->keybit);
+	__set_bit(KEY_PROG1, idev->keybit);
+	__set_bit(KEY_PROG2, idev->keybit);
+	__set_bit(KEY_PROG3, idev->keybit);
+	__set_bit(KEY_PROG4, idev->keybit);
+	__set_bit(KEY_PC, idev->keybit);
 
 	idev->rep[REP_DELAY]  = 250;
 	idev->rep[REP_PERIOD] = 33;
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/cobalt_btns.c linux-libre-2.6.31-gnu/drivers/input/misc/cobalt_btns.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/cobalt_btns.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/cobalt_btns.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Cobalt button interface driver.
  *
- *  Copyright (C) 2007-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@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
@@ -148,7 +148,7 @@
 	return 0;
 }
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("Cobalt button interface driver");
 MODULE_LICENSE("GPL");
 /* work with hotplug and coldplug */
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/dm355evm_keys.c linux-libre-2.6.31-gnu/drivers/input/misc/dm355evm_keys.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/dm355evm_keys.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/misc/dm355evm_keys.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,329 @@
+/*
+ * dm355evm_keys.c - support buttons and IR remote on DM355 EVM board
+ *
+ * Copyright (c) 2008 by David Brownell
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+#include <linux/i2c/dm355evm_msp.h>
+
+
+/*
+ * The MSP430 firmware on the DM355 EVM monitors on-board pushbuttons
+ * and an IR receptor used for the remote control.  When any key is
+ * pressed, or its autorepeat kicks in, an event is sent.  This driver
+ * read those events from the small (32 event) queue and reports them.
+ *
+ * Because we communicate with the MSP430 using I2C, and all I2C calls
+ * in Linux sleep, we need to cons up a kind of threaded IRQ handler
+ * using a work_struct.  The IRQ is active low, but we use it through
+ * the GPIO controller so we can trigger on falling edges.
+ *
+ * Note that physically there can only be one of these devices.
+ *
+ * This driver was tested with firmware revision A4.
+ */
+struct dm355evm_keys {
+	struct work_struct	work;
+	struct input_dev	*input;
+	struct device		*dev;
+	int			irq;
+};
+
+static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
+{
+	struct dm355evm_keys	*keys = _keys;
+
+	schedule_work(&keys->work);
+	return IRQ_HANDLED;
+}
+
+/* These initial keycodes can be remapped by dm355evm_setkeycode(). */
+static struct {
+	u16	event;
+	u16	keycode;
+} dm355evm_keys[] = {
+
+	/*
+	 * Pushbuttons on the EVM board ... note that the labels for these
+	 * are SW10/SW11/etc on the PC board.  The left/right orientation
+	 * comes only from the firmware's documentation, and presumes the
+	 * power connector is immediately in front of you and the IR sensor
+	 * is to the right.  (That is, rotate the board counter-clockwise
+	 * by 90 degrees from the SW10/etc and "DM355 EVM" labels.)
+	 */
+	{ 0x00d8, KEY_OK, },		/* SW12 */
+	{ 0x00b8, KEY_UP, },		/* SW13 */
+	{ 0x00e8, KEY_DOWN, },		/* SW11 */
+	{ 0x0078, KEY_LEFT, },		/* SW14 */
+	{ 0x00f0, KEY_RIGHT, },		/* SW10 */
+
+	/*
+	 * IR buttons ... codes assigned to match the universal remote
+	 * provided with the EVM (Philips PM4S) using DVD code 0020.
+	 *
+	 * These event codes match firmware documentation, but other
+	 * remote controls could easily send more RC5-encoded events.
+	 * The PM4S manual was used in several cases to help select
+	 * a keycode reflecting the intended usage.
+	 *
+	 * RC5 codes are 14 bits, with two start bits (0x3 prefix)
+	 * and a toggle bit (masked out below).
+	 */
+	{ 0x300c, KEY_POWER, },		/* NOTE: docs omit this */
+	{ 0x3000, KEY_NUMERIC_0, },
+	{ 0x3001, KEY_NUMERIC_1, },
+	{ 0x3002, KEY_NUMERIC_2, },
+	{ 0x3003, KEY_NUMERIC_3, },
+	{ 0x3004, KEY_NUMERIC_4, },
+	{ 0x3005, KEY_NUMERIC_5, },
+	{ 0x3006, KEY_NUMERIC_6, },
+	{ 0x3007, KEY_NUMERIC_7, },
+	{ 0x3008, KEY_NUMERIC_8, },
+	{ 0x3009, KEY_NUMERIC_9, },
+	{ 0x3022, KEY_ENTER, },
+	{ 0x30ec, KEY_MODE, },		/* "tv/vcr/..." */
+	{ 0x300f, KEY_SELECT, },	/* "info" */
+	{ 0x3020, KEY_CHANNELUP, },	/* "up" */
+	{ 0x302e, KEY_MENU, },		/* "in/out" */
+	{ 0x3011, KEY_VOLUMEDOWN, },	/* "left" */
+	{ 0x300d, KEY_MUTE, },		/* "ok" */
+	{ 0x3010, KEY_VOLUMEUP, },	/* "right" */
+	{ 0x301e, KEY_SUBTITLE, },	/* "cc" */
+	{ 0x3021, KEY_CHANNELDOWN, },	/* "down" */
+	{ 0x3022, KEY_PREVIOUS, },
+	{ 0x3026, KEY_SLEEP, },
+	{ 0x3172, KEY_REWIND, },	/* NOTE: docs wrongly say 0x30ca */
+	{ 0x3175, KEY_PLAY, },
+	{ 0x3174, KEY_FASTFORWARD, },
+	{ 0x3177, KEY_RECORD, },
+	{ 0x3176, KEY_STOP, },
+	{ 0x3169, KEY_PAUSE, },
+};
+
+static void dm355evm_keys_work(struct work_struct *work)
+{
+	struct dm355evm_keys	*keys;
+	int			status;
+
+	keys = container_of(work, struct dm355evm_keys, work);
+
+	/* For simplicity we ignore INPUT_COUNT and just read
+	 * events until we get the "queue empty" indicator.
+	 * Reading INPUT_LOW decrements the count.
+	 */
+	for (;;) {
+		static u16	last_event;
+		u16		event;
+		int		keycode;
+		int		i;
+
+		status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH);
+		if (status < 0) {
+			dev_dbg(keys->dev, "input high err %d\n",
+					status);
+			break;
+		}
+		event = status << 8;
+
+		status = dm355evm_msp_read(DM355EVM_MSP_INPUT_LOW);
+		if (status < 0) {
+			dev_dbg(keys->dev, "input low err %d\n",
+					status);
+			break;
+		}
+		event |= status;
+		if (event == 0xdead)
+			break;
+
+		/* Press and release a button:  two events, same code.
+		 * Press and hold (autorepeat), then release: N events
+		 * (N > 2), same code.  For RC5 buttons the toggle bits
+		 * distinguish (for example) "1-autorepeat" from "1 1";
+		 * but PCB buttons don't support that bit.
+		 *
+		 * So we must synthesize release events.  We do that by
+		 * mapping events to a press/release event pair; then
+		 * to avoid adding extra events, skip the second event
+		 * of each pair.
+		 */
+		if (event == last_event) {
+			last_event = 0;
+			continue;
+		}
+		last_event = event;
+
+		/* ignore the RC5 toggle bit */
+		event &= ~0x0800;
+
+		/* find the key, or leave it as unknown */
+		keycode = KEY_UNKNOWN;
+		for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
+			if (dm355evm_keys[i].event != event)
+				continue;
+			keycode = dm355evm_keys[i].keycode;
+			break;
+		}
+		dev_dbg(keys->dev,
+			"input event 0x%04x--> keycode %d\n",
+			event, keycode);
+
+		/* report press + release */
+		input_report_key(keys->input, keycode, 1);
+		input_sync(keys->input);
+		input_report_key(keys->input, keycode, 0);
+		input_sync(keys->input);
+	}
+}
+
+static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode)
+{
+	u16		old_keycode;
+	unsigned	i;
+
+	if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
+		return -EINVAL;
+
+	old_keycode = dm355evm_keys[index].keycode;
+	dm355evm_keys[index].keycode = keycode;
+	set_bit(keycode, dev->keybit);
+
+	for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
+		if (dm355evm_keys[index].keycode == old_keycode)
+			goto done;
+	}
+	clear_bit(old_keycode, dev->keybit);
+done:
+	return 0;
+}
+
+static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode)
+{
+	if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
+		return -EINVAL;
+
+	return dm355evm_keys[index].keycode;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
+{
+	struct dm355evm_keys	*keys;
+	struct input_dev	*input;
+	int			status;
+	int			i;
+
+	/* allocate instance struct and input dev */
+	keys = kzalloc(sizeof *keys, GFP_KERNEL);
+	input = input_allocate_device();
+	if (!keys || !input) {
+		status = -ENOMEM;
+		goto fail1;
+	}
+
+	keys->dev = &pdev->dev;
+	keys->input = input;
+	INIT_WORK(&keys->work, dm355evm_keys_work);
+
+	/* set up "threaded IRQ handler" */
+	status = platform_get_irq(pdev, 0);
+	if (status < 0)
+		goto fail1;
+	keys->irq = status;
+
+	input_set_drvdata(input, keys);
+
+	input->name = "DM355 EVM Controls";
+	input->phys = "dm355evm/input0";
+	input->dev.parent = &pdev->dev;
+
+	input->id.bustype = BUS_I2C;
+	input->id.product = 0x0355;
+	input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
+
+	input->evbit[0] = BIT(EV_KEY);
+	for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++)
+		__set_bit(dm355evm_keys[i].keycode, input->keybit);
+
+	input->setkeycode = dm355evm_setkeycode;
+	input->getkeycode = dm355evm_getkeycode;
+
+	/* REVISIT:  flush the event queue? */
+
+	status = request_irq(keys->irq, dm355evm_keys_irq,
+			     IRQF_TRIGGER_FALLING,
+			     dev_name(&pdev->dev), keys);
+	if (status < 0)
+		goto fail1;
+
+	/* register */
+	status = input_register_device(input);
+	if (status < 0)
+		goto fail2;
+
+	platform_set_drvdata(pdev, keys);
+
+	return 0;
+
+fail2:
+	free_irq(keys->irq, keys);
+fail1:
+	input_free_device(input);
+	kfree(keys);
+	dev_err(&pdev->dev, "can't register, err %d\n", status);
+
+	return status;
+}
+
+static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
+{
+	struct dm355evm_keys	*keys = platform_get_drvdata(pdev);
+
+	free_irq(keys->irq, keys);
+	input_unregister_device(keys->input);
+	kfree(keys);
+
+	return 0;
+}
+
+/* REVISIT:  add suspend/resume when DaVinci supports it.  The IRQ should
+ * be able to wake up the system.  When device_may_wakeup(&pdev->dev), call
+ * enable_irq_wake() on suspend, and disable_irq_wake() on resume.
+ */
+
+/*
+ * I2C is used to talk to the MSP430, but this platform device is
+ * exposed by an MFD driver that manages I2C communications.
+ */
+static struct platform_driver dm355evm_keys_driver = {
+	.probe		= dm355evm_keys_probe,
+	.remove		= __devexit_p(dm355evm_keys_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "dm355evm_keys",
+	},
+};
+
+static int __init dm355evm_keys_init(void)
+{
+	return platform_driver_register(&dm355evm_keys_driver);
+}
+module_init(dm355evm_keys_init);
+
+static void __exit dm355evm_keys_exit(void)
+{
+	platform_driver_unregister(&dm355evm_keys_driver);
+}
+module_exit(dm355evm_keys_exit);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/Kconfig linux-libre-2.6.31-gnu/drivers/input/misc/Kconfig
--- linux-libre-2.6.30-gnu/drivers/input/misc/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -193,6 +193,16 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called cm109.
 
+config INPUT_TWL4030_PWRBUTTON
+	tristate "TWL4030 Power button Driver"
+	depends on TWL4030_CORE
+	help
+	  Say Y here if you want to enable power key reporting via the
+	  TWL4030 family of chips.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called twl4030_pwrbutton.
+
 config INPUT_UINPUT
 	tristate "User level driver support"
 	help
@@ -232,7 +242,7 @@
 	depends on GPIOLIB && GENERIC_GPIO
 	help
 	  Say Y here to add support for rotary encoders connected to GPIO lines.
-	  Check file:Documentation/incput/rotary_encoder.txt for more
+	  Check file:Documentation/input/rotary-encoder.txt for more
 	  information.
 
 	  To compile this driver as a module, choose M here: the
@@ -250,4 +260,13 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rb532_button.
 
+config INPUT_DM355EVM
+	tristate "TI DaVinci DM355 EVM Keypad and IR Remote"
+	depends on MFD_DM355EVM_MSP
+	help
+	  Supports the pushbuttons and IR remote used with
+	  the DM355 EVM board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called dm355evm_keys.
 endif
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/Makefile linux-libre-2.6.31-gnu/drivers/input/misc/Makefile
--- linux-libre-2.6.30-gnu/drivers/input/misc/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_INPUT_CM109)		+= cm109.o
 obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
+obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
@@ -21,6 +22,7 @@
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)	+= rotary_encoder.o
 obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
+obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)	+= twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/pcspkr.c linux-libre-2.6.31-gnu/drivers/input/misc/pcspkr.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/pcspkr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/pcspkr.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/platform_device.h>
+#include <linux/timex.h>
 #include <asm/io.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
@@ -113,7 +114,7 @@
 	return 0;
 }
 
-static int pcspkr_suspend(struct platform_device *dev, pm_message_t state)
+static int pcspkr_suspend(struct device *dev)
 {
 	pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 
@@ -126,14 +127,18 @@
 	pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 }
 
+static struct dev_pm_ops pcspkr_pm_ops = {
+	.suspend = pcspkr_suspend,
+};
+
 static struct platform_driver pcspkr_platform_driver = {
 	.driver		= {
 		.name	= "pcspkr",
 		.owner	= THIS_MODULE,
+		.pm	= &pcspkr_pm_ops,
 	},
 	.probe		= pcspkr_probe,
 	.remove		= __devexit_p(pcspkr_remove),
-	.suspend	= pcspkr_suspend,
 	.shutdown	= pcspkr_shutdown,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/rotary_encoder.c linux-libre-2.6.31-gnu/drivers/input/misc/rotary_encoder.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/rotary_encoder.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/rotary_encoder.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,13 +26,17 @@
 #define DRV_NAME "rotary-encoder"
 
 struct rotary_encoder {
-	unsigned int irq_a;
-	unsigned int irq_b;
-	unsigned int pos;
-	unsigned int armed;
-	unsigned int dir;
 	struct input_dev *input;
 	struct rotary_encoder_platform_data *pdata;
+
+	unsigned int axis;
+	unsigned int pos;
+
+	unsigned int irq_a;
+	unsigned int irq_b;
+
+	bool armed;
+	unsigned char dir;	/* 0 - clockwise, 1 - CCW */
 };
 
 static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
@@ -53,21 +57,32 @@
 		if (!encoder->armed)
 			break;
 
-		if (encoder->dir) {
-			/* turning counter-clockwise */
-			encoder->pos += pdata->steps;
-			encoder->pos--;
-			encoder->pos %= pdata->steps;
+		if (pdata->relative_axis) {
+			input_report_rel(encoder->input, pdata->axis,
+					 encoder->dir ? -1 : 1);
 		} else {
-			/* turning clockwise */
-			encoder->pos++;
-			encoder->pos %= pdata->steps;
-		}
+			unsigned int pos = encoder->pos;
 
-		input_report_abs(encoder->input, pdata->axis, encoder->pos);
+			if (encoder->dir) {
+				/* turning counter-clockwise */
+				if (pdata->rollover)
+					pos += pdata->steps;
+				if (pos)
+					pos--;
+			} else {
+				/* turning clockwise */
+				if (pdata->rollover || pos < pdata->steps)
+					pos++;
+			}
+			if (pdata->rollover)
+				pos %= pdata->steps;
+			encoder->pos = pos;
+			input_report_abs(encoder->input, pdata->axis,
+					 encoder->pos);
+		}
 		input_sync(encoder->input);
 
-		encoder->armed = 0;
+		encoder->armed = false;
 		break;
 
 	case 0x1:
@@ -77,7 +92,7 @@
 		break;
 
 	case 0x3:
-		encoder->armed = 1;
+		encoder->armed = true;
 		break;
 	}
 
@@ -113,9 +128,15 @@
 	input->name = pdev->name;
 	input->id.bustype = BUS_HOST;
 	input->dev.parent = &pdev->dev;
-	input->evbit[0] = BIT_MASK(EV_ABS);
-	input_set_abs_params(encoder->input,
-			     pdata->axis, 0, pdata->steps, 0, 1);
+
+	if (pdata->relative_axis) {
+		input->evbit[0] = BIT_MASK(EV_REL);
+		input->relbit[0] = BIT_MASK(pdata->axis);
+	} else {
+		input->evbit[0] = BIT_MASK(EV_ABS);
+		input_set_abs_params(encoder->input,
+				     pdata->axis, 0, pdata->steps, 0, 1);
+	}
 
 	err = input_register_device(input);
 	if (err) {
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/twl4030-pwrbutton.c linux-libre-2.6.31-gnu/drivers/input/misc/twl4030-pwrbutton.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/twl4030-pwrbutton.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/misc/twl4030-pwrbutton.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,145 @@
+/**
+ * twl4030-pwrbutton.c - TWL4030 Power Button Input Driver
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Peter De Schrijver <peter.de-schrijver@nokia.com>
+ * Several fixes by Felipe Balbi <felipe.balbi@nokia.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.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl4030.h>
+
+#define PWR_PWRON_IRQ (1 << 0)
+
+#define STS_HW_CONDITIONS 0xf
+
+static irqreturn_t powerbutton_irq(int irq, void *_pwr)
+{
+	struct input_dev *pwr = _pwr;
+	int err;
+	u8 value;
+
+#ifdef CONFIG_LOCKDEP
+	/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+	 * we don't want and can't tolerate since this is a threaded
+	 * IRQ and can sleep due to the i2c reads it has to issue.
+	 * Although it might be friendlier not to borrow this thread
+	 * context...
+	 */
+	local_irq_enable();
+#endif
+
+	err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value,
+				  STS_HW_CONDITIONS);
+	if (!err)  {
+		input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
+		input_sync(pwr);
+	} else {
+		dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading"
+			" TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev)
+{
+	struct input_dev *pwr;
+	int irq = platform_get_irq(pdev, 0);
+	int err;
+
+	pwr = input_allocate_device();
+	if (!pwr) {
+		dev_dbg(&pdev->dev, "Can't allocate power button\n");
+		return -ENOMEM;
+	}
+
+	pwr->evbit[0] = BIT_MASK(EV_KEY);
+	pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
+	pwr->name = "twl4030_pwrbutton";
+	pwr->phys = "twl4030_pwrbutton/input0";
+	pwr->dev.parent = &pdev->dev;
+
+	err = request_irq(irq, powerbutton_irq,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"twl4030_pwrbutton", pwr);
+	if (err < 0) {
+		dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
+		goto free_input_dev;
+	}
+
+	err = input_register_device(pwr);
+	if (err) {
+		dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
+		goto free_irq;
+	}
+
+	platform_set_drvdata(pdev, pwr);
+
+	return 0;
+
+free_irq:
+	free_irq(irq, NULL);
+free_input_dev:
+	input_free_device(pwr);
+	return err;
+}
+
+static int __devexit twl4030_pwrbutton_remove(struct platform_device *pdev)
+{
+	struct input_dev *pwr = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	free_irq(irq, pwr);
+	input_unregister_device(pwr);
+
+	return 0;
+}
+
+struct platform_driver twl4030_pwrbutton_driver = {
+	.probe		= twl4030_pwrbutton_probe,
+	.remove		= __devexit_p(twl4030_pwrbutton_remove),
+	.driver		= {
+		.name	= "twl4030_pwrbutton",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init twl4030_pwrbutton_init(void)
+{
+	return platform_driver_register(&twl4030_pwrbutton_driver);
+}
+module_init(twl4030_pwrbutton_init);
+
+static void __exit twl4030_pwrbutton_exit(void)
+{
+	platform_driver_unregister(&twl4030_pwrbutton_driver);
+}
+module_exit(twl4030_pwrbutton_exit);
+
+MODULE_ALIAS("platform:twl4030_pwrbutton");
+MODULE_DESCRIPTION("Triton2 Power Button");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Peter De Schrijver <peter.de-schrijver@nokia.com>");
+MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
+
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/uinput.c linux-libre-2.6.31-gnu/drivers/input/misc/uinput.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/uinput.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/uinput.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,27 +54,28 @@
 	return 0;
 }
 
+/* Atomically allocate an ID for the given request. Returns 0 on success. */
 static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request)
 {
-	/* Atomically allocate an ID for the given request. Returns 0 on success. */
 	int id;
 	int err = -1;
 
 	spin_lock(&udev->requests_lock);
 
-	for (id = 0; id < UINPUT_NUM_REQUESTS; id++)
+	for (id = 0; id < UINPUT_NUM_REQUESTS; id++) {
 		if (!udev->requests[id]) {
 			request->id = id;
 			udev->requests[id] = request;
 			err = 0;
 			break;
 		}
+	}
 
 	spin_unlock(&udev->requests_lock);
 	return err;
 }
 
-static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id)
+static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id)
 {
 	/* Find an input request, by ID. Returns NULL if the ID isn't valid. */
 	if (id >= UINPUT_NUM_REQUESTS || id < 0)
@@ -99,14 +100,51 @@
 	complete(&request->done);
 }
 
-static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request)
+static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request)
 {
+	int retval;
+
+	retval = uinput_request_reserve_slot(udev, request);
+	if (retval)
+		return retval;
+
+	retval = mutex_lock_interruptible(&udev->mutex);
+	if (retval)
+		return retval;
+
+	if (udev->state != UIST_CREATED) {
+		retval = -ENODEV;
+		goto out;
+	}
+
 	/* Tell our userspace app about this new request by queueing an input event */
-	uinput_dev_event(dev, EV_UINPUT, request->code, request->id);
+	uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id);
 
-	/* Wait for the request to complete */
-	wait_for_completion(&request->done);
-	return request->retval;
+ out:
+	mutex_unlock(&udev->mutex);
+	return retval;
+}
+
+/*
+ * Fail all ouitstanding requests so handlers don't wait for the userspace
+ * to finish processing them.
+ */
+static void uinput_flush_requests(struct uinput_device *udev)
+{
+	struct uinput_request *request;
+	int i;
+
+	spin_lock(&udev->requests_lock);
+
+	for (i = 0; i < UINPUT_NUM_REQUESTS; i++) {
+		request = udev->requests[i];
+		if (request) {
+			request->retval = -ENODEV;
+			uinput_request_done(udev, request);
+		}
+	}
+
+	spin_unlock(&udev->requests_lock);
 }
 
 static void uinput_dev_set_gain(struct input_dev *dev, u16 gain)
@@ -126,6 +164,7 @@
 
 static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
 {
+	struct uinput_device *udev = input_get_drvdata(dev);
 	struct uinput_request request;
 	int retval;
 
@@ -146,15 +185,18 @@
 	request.u.upload.effect = effect;
 	request.u.upload.old = old;
 
-	retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
-	if (!retval)
-		retval = uinput_request_submit(dev, &request);
+	retval = uinput_request_submit(udev, &request);
+	if (!retval) {
+		wait_for_completion(&request.done);
+		retval = request.retval;
+	}
 
 	return retval;
 }
 
 static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
 {
+	struct uinput_device *udev = input_get_drvdata(dev);
 	struct uinput_request request;
 	int retval;
 
@@ -166,9 +208,11 @@
 	request.code = UI_FF_ERASE;
 	request.u.effect_id = effect_id;
 
-	retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
-	if (!retval)
-		retval = uinput_request_submit(dev, &request);
+	retval = uinput_request_submit(udev, &request);
+	if (!retval) {
+		wait_for_completion(&request.done);
+		retval = request.retval;
+	}
 
 	return retval;
 }
@@ -176,20 +220,24 @@
 static void uinput_destroy_device(struct uinput_device *udev)
 {
 	const char *name, *phys;
+	struct input_dev *dev = udev->dev;
+	enum uinput_state old_state = udev->state;
 
-	if (udev->dev) {
-		name = udev->dev->name;
-		phys = udev->dev->phys;
-		if (udev->state == UIST_CREATED)
-			input_unregister_device(udev->dev);
-		else
-			input_free_device(udev->dev);
+	udev->state = UIST_NEW_DEVICE;
+
+	if (dev) {
+		name = dev->name;
+		phys = dev->phys;
+		if (old_state == UIST_CREATED) {
+			uinput_flush_requests(udev);
+			input_unregister_device(dev);
+		} else {
+			input_free_device(dev);
+		}
 		kfree(name);
 		kfree(phys);
 		udev->dev = NULL;
 	}
-
-	udev->state = UIST_NEW_DEVICE;
 }
 
 static int uinput_create_device(struct uinput_device *udev)
diff -druN linux-libre-2.6.30-gnu/drivers/input/misc/wistron_btns.c linux-libre-2.6.31-gnu/drivers/input/misc/wistron_btns.c
--- linux-libre-2.6.30-gnu/drivers/input/misc/wistron_btns.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/misc/wistron_btns.c	2009-09-09 18:13:59.000000000 -0400
@@ -611,6 +611,20 @@
 	{ KE_END, 0 }
 };
 
+static struct key_entry keymap_prestigio[] __initdata = {
+	{ KE_KEY,  0x11, {KEY_PROG1} },
+	{ KE_KEY,  0x12, {KEY_PROG2} },
+	{ KE_WIFI,  0x30 },
+	{ KE_KEY,  0x22, {KEY_REWIND} },
+	{ KE_KEY,  0x23, {KEY_FORWARD} },
+	{ KE_KEY,  0x24, {KEY_PLAYPAUSE} },
+	{ KE_KEY,  0x25, {KEY_STOPCD} },
+	{ KE_KEY,  0x31, {KEY_MAIL} },
+	{ KE_KEY,  0x36, {KEY_WWW} },
+	{ KE_END,  0 }
+};
+
+
 /*
  * If your machine is not here (which is currently rather likely), please send
  * a list of buttons and their key codes (reported when loading this module
@@ -646,6 +660,15 @@
 	},
 	{
 		.callback = dmi_matched,
+		.ident = "Maxdata Pro 7000 DX",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
+		},
+		.driver_data = keymap_fs_amilo_pro_v2000
+	},
+	{
+		.callback = dmi_matched,
 		.ident = "Fujitsu N3510",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@ -962,6 +985,8 @@
 	if (keymap_name != NULL) {
 		if (strcmp (keymap_name, "1557/MS2141") == 0)
 			keymap = keymap_wistron_ms2141;
+		else if (strcmp (keymap_name, "prestigio") == 0)
+			keymap = keymap_prestigio;
 		else if (strcmp (keymap_name, "generic") == 0)
 			keymap = keymap_wistron_generic;
 		else {
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/alps.c linux-libre-2.6.31-gnu/drivers/input/mouse/alps.c
--- linux-libre-2.6.30-gnu/drivers/input/mouse/alps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/alps.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,25 +38,25 @@
 
 static const struct alps_model_info alps_model_data[] = {
 	{ { 0x32, 0x02, 0x14 },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
-	{ { 0x33, 0x02, 0x0a },	0x88, 0xf8, ALPS_OLDPROTO },		/* UMAX-530T */
+	{ { 0x33, 0x02, 0x0a },	0x88, 0xf8, ALPS_OLDPROTO },		  /* UMAX-530T */
 	{ { 0x53, 0x02, 0x0a },	0xf8, 0xf8, 0 },
 	{ { 0x53, 0x02, 0x14 },	0xf8, 0xf8, 0 },
-	{ { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 },			/* HP ze1115 */
+	{ { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 },			  /* HP ze1115 */
 	{ { 0x63, 0x02, 0x0a },	0xf8, 0xf8, 0 },
 	{ { 0x63, 0x02, 0x14 },	0xf8, 0xf8, 0 },
-	{ { 0x63, 0x02, 0x28 },	0xf8, 0xf8, ALPS_FW_BK_2 },		/* Fujitsu Siemens S6010 */
-	{ { 0x63, 0x02, 0x3c },	0x8f, 0x8f, ALPS_WHEEL },		/* Toshiba Satellite S2400-103 */
-	{ { 0x63, 0x02, 0x50 },	0xef, 0xef, ALPS_FW_BK_1 },		/* NEC Versa L320 */
+	{ { 0x63, 0x02, 0x28 },	0xf8, 0xf8, ALPS_FW_BK_2 },		  /* Fujitsu Siemens S6010 */
+	{ { 0x63, 0x02, 0x3c },	0x8f, 0x8f, ALPS_WHEEL },		  /* Toshiba Satellite S2400-103 */
+	{ { 0x63, 0x02, 0x50 },	0xef, 0xef, ALPS_FW_BK_1 },		  /* NEC Versa L320 */
 	{ { 0x63, 0x02, 0x64 },	0xf8, 0xf8, 0 },
-	{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS },		/* Dell Latitude D800 */
-	{ { 0x73, 0x00, 0x0a },	0xf8, 0xf8, ALPS_DUALPOINT },		/* ThinkPad R61 8918-5QG */
+	{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */
+	{ { 0x73, 0x00, 0x0a },	0xf8, 0xf8, ALPS_DUALPOINT },		  /* ThinkPad R61 8918-5QG */
 	{ { 0x73, 0x02, 0x0a },	0xf8, 0xf8, 0 },
-	{ { 0x73, 0x02, 0x14 },	0xf8, 0xf8, ALPS_FW_BK_2 },		/* Ahtec Laptop */
+	{ { 0x73, 0x02, 0x14 },	0xf8, 0xf8, ALPS_FW_BK_2 },		  /* Ahtec Laptop */
 	{ { 0x20, 0x02, 0x0e },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
 	{ { 0x22, 0x02, 0x0a },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
 	{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
 	{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
-	{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */
+	{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 },		  /* Dell Vostro 1400 */
 };
 
 /*
@@ -132,18 +132,23 @@
 	ges = packet[2] & 1;
 	fin = packet[2] & 2;
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
-	input_report_key(dev, BTN_MIDDLE, middle);
-
 	if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) {
 		input_report_rel(dev2, REL_X,  (x > 383 ? (x - 768) : x));
 		input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
+
+		input_report_key(dev2, BTN_LEFT, left);
+		input_report_key(dev2, BTN_RIGHT, right);
+		input_report_key(dev2, BTN_MIDDLE, middle);
+
 		input_sync(dev);
 		input_sync(dev2);
 		return;
 	}
 
+	input_report_key(dev, BTN_LEFT, left);
+	input_report_key(dev, BTN_RIGHT, right);
+	input_report_key(dev, BTN_MIDDLE, middle);
+
 	/* Convert hardware tap to a reasonable Z value */
 	if (ges && !fin) z = 40;
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/appletouch.c linux-libre-2.6.31-gnu/drivers/input/mouse/appletouch.c
--- linux-libre-2.6.30-gnu/drivers/input/mouse/appletouch.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/appletouch.c	2009-09-09 18:13:59.000000000 -0400
@@ -361,7 +361,7 @@
 		    (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
 			(*fingers)++;
 			is_increasing = 1;
-		} else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
+		} else if (i > 0 && (xy_sensors[i - 1] - xy_sensors[i] > threshold)) {
 			is_increasing = 0;
 		}
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/gpio_mouse.c linux-libre-2.6.31-gnu/drivers/input/mouse/gpio_mouse.c
--- linux-libre-2.6.30-gnu/drivers/input/mouse/gpio_mouse.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/gpio_mouse.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 	input_sync(input);
 }
 
-static int __init gpio_mouse_probe(struct platform_device *pdev)
+static int __devinit gpio_mouse_probe(struct platform_device *pdev)
 {
 	struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
 	struct input_polled_dev *input_poll;
@@ -170,10 +170,8 @@
 	return 0;
 }
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:gpio_mouse");
-
 static struct platform_driver gpio_mouse_device_driver = {
+	.probe		= gpio_mouse_probe,
 	.remove		= __devexit_p(gpio_mouse_remove),
 	.driver		= {
 		.name	= "gpio_mouse",
@@ -183,8 +181,7 @@
 
 static int __init gpio_mouse_init(void)
 {
-	return platform_driver_probe(&gpio_mouse_device_driver,
-			gpio_mouse_probe);
+	return platform_driver_register(&gpio_mouse_device_driver);
 }
 module_init(gpio_mouse_init);
 
@@ -197,3 +194,5 @@
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("GPIO mouse driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
+
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/Kconfig linux-libre-2.6.31-gnu/drivers/input/mouse/Kconfig
--- linux-libre-2.6.30-gnu/drivers/input/mouse/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -303,4 +303,22 @@
 	  To compile this driver as a module choose M here: the module will be
 	  called maplemouse.
 
+config MOUSE_SYNAPTICS_I2C
+	tristate "Synaptics I2C Touchpad support"
+	depends on I2C
+	help
+	  This driver supports Synaptics I2C touchpad controller on eXeda
+	  mobile device.
+	  The device will not work the synaptics X11 driver because
+	  (i) it  reports only relative coordinates and has no capabilities
+	  to report absolute coordinates
+	  (ii) the eXeda device itself uses Xfbdev as X Server and it does
+	  not allow using xf86-input-* drivers.
+
+	  Say y here if you have eXeda device and want to use a Synaptics
+	  I2C Touchpad.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called synaptics_i2c.
+
 endif
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/lifebook.c linux-libre-2.6.31-gnu/drivers/input/mouse/lifebook.c
--- linux-libre-2.6.30-gnu/drivers/input/mouse/lifebook.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/lifebook.c	2009-09-09 18:13:59.000000000 -0400
@@ -159,21 +159,22 @@
 		if (!dev2)
 			printk(KERN_WARNING "lifebook.c: got relative packet "
 				"but no relative device set up\n");
-	} else if (lifebook_use_6byte_proto) {
-		input_report_abs(dev1, ABS_X,
-				 ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
-		input_report_abs(dev1, ABS_Y,
-				 4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
 	} else {
-		input_report_abs(dev1, ABS_X,
-				 (packet[1] | ((packet[0] & 0x30) << 4)));
-		input_report_abs(dev1, ABS_Y,
-				 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+		if (lifebook_use_6byte_proto) {
+			input_report_abs(dev1, ABS_X,
+				((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
+			input_report_abs(dev1, ABS_Y,
+				4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
+		} else {
+			input_report_abs(dev1, ABS_X,
+				(packet[1] | ((packet[0] & 0x30) << 4)));
+			input_report_abs(dev1, ABS_Y,
+				1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
+		}
+		input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
+		input_sync(dev1);
 	}
 
-	input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
-	input_sync(dev1);
-
 	if (dev2) {
 		if (relative_packet) {
 			input_report_rel(dev2, REL_X,
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/Makefile linux-libre-2.6.31-gnu/drivers/input/mouse/Makefile
--- linux-libre-2.6.30-gnu/drivers/input/mouse/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,7 @@
 obj-$(CONFIG_MOUSE_PXA930_TRKBALL)	+= pxa930_trkball.o
 obj-$(CONFIG_MOUSE_RISCPC)		+= rpcmouse.o
 obj-$(CONFIG_MOUSE_SERIAL)		+= sermouse.o
+obj-$(CONFIG_MOUSE_SYNAPTICS_I2C)	+= synaptics_i2c.o
 obj-$(CONFIG_MOUSE_VSXXXAA)		+= vsxxxaa.o
 
 psmouse-objs := psmouse-base.o synaptics.o
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/psmouse-base.c linux-libre-2.6.31-gnu/drivers/input/mouse/psmouse-base.c
--- linux-libre-2.6.30-gnu/drivers/input/mouse/psmouse-base.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/psmouse-base.c	2009-09-09 18:13:59.000000000 -0400
@@ -327,7 +327,9 @@
 			goto out;
 		}
 
-		if (psmouse->packet[1] == PSMOUSE_RET_ID) {
+		if (psmouse->packet[1] == PSMOUSE_RET_ID ||
+		    (psmouse->type == PSMOUSE_HGPK &&
+		     psmouse->packet[1] == PSMOUSE_RET_BAT)) {
 			__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 			serio_reconnect(serio);
 			goto out;
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/synaptics.c linux-libre-2.6.31-gnu/drivers/input/mouse/synaptics.c
--- linux-libre-2.6.30-gnu/drivers/input/mouse/synaptics.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/synaptics.c	2009-09-09 18:13:59.000000000 -0400
@@ -180,6 +180,29 @@
 	return -1;
 }
 
+/*
+ * Read touchpad resolution
+ * Resolution is left zero if touchpad does not support the query
+ */
+static int synaptics_resolution(struct psmouse *psmouse)
+{
+	struct synaptics_data *priv = psmouse->private;
+	unsigned char res[3];
+
+	if (SYN_ID_MAJOR(priv->identity) < 4)
+		return 0;
+
+	if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res))
+		return 0;
+
+	if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) {
+		priv->x_res = res[0]; /* x resolution in units/mm */
+		priv->y_res = res[2]; /* y resolution in units/mm */
+	}
+
+	return 0;
+}
+
 static int synaptics_query_hardware(struct psmouse *psmouse)
 {
 	if (synaptics_identify(psmouse))
@@ -188,6 +211,8 @@
 		return -1;
 	if (synaptics_capability(psmouse))
 		return -1;
+	if (synaptics_resolution(psmouse))
+		return -1;
 
 	return 0;
 }
@@ -563,6 +588,9 @@
 	clear_bit(EV_REL, dev->evbit);
 	clear_bit(REL_X, dev->relbit);
 	clear_bit(REL_Y, dev->relbit);
+
+	dev->absres[ABS_X] = priv->x_res;
+	dev->absres[ABS_Y] = priv->y_res;
 }
 
 static void synaptics_disconnect(struct psmouse *psmouse)
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/synaptics.h linux-libre-2.6.31-gnu/drivers/input/mouse/synaptics.h
--- linux-libre-2.6.30-gnu/drivers/input/mouse/synaptics.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/synaptics.h	2009-09-09 18:13:59.000000000 -0400
@@ -97,6 +97,8 @@
 	unsigned long int capabilities;		/* Capabilities */
 	unsigned long int ext_cap;		/* Extended Capabilities */
 	unsigned long int identity;		/* Identification */
+	int x_res;				/* X resolution in units/mm */
+	int y_res;				/* Y resolution in units/mm */
 
 	unsigned char pkt_type;			/* packet type - old, new, etc */
 	unsigned char mode;			/* current mode byte */
diff -druN linux-libre-2.6.30-gnu/drivers/input/mouse/synaptics_i2c.c linux-libre-2.6.31-gnu/drivers/input/mouse/synaptics_i2c.c
--- linux-libre-2.6.30-gnu/drivers/input/mouse/synaptics_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/mouse/synaptics_i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,676 @@
+/*
+ * Synaptics touchpad with I2C interface
+ *
+ * Copyright (C) 2009 Compulab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ * Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * 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/module.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+
+#define DRIVER_NAME		"synaptics_i2c"
+/* maximum product id is 15 characters */
+#define PRODUCT_ID_LENGTH	15
+#define REGISTER_LENGTH		8
+
+/*
+ * after soft reset, we should wait for 1 ms
+ * before the device becomes operational
+ */
+#define SOFT_RESET_DELAY_MS	3
+/* and after hard reset, we should wait for max 500ms */
+#define HARD_RESET_DELAY_MS	500
+
+/* Registers by SMBus address */
+#define PAGE_SEL_REG		0xff
+#define DEVICE_STATUS_REG	0x09
+
+/* Registers by RMI address */
+#define DEV_CONTROL_REG		0x0000
+#define INTERRUPT_EN_REG	0x0001
+#define ERR_STAT_REG		0x0002
+#define INT_REQ_STAT_REG	0x0003
+#define DEV_COMMAND_REG		0x0004
+
+#define RMI_PROT_VER_REG	0x0200
+#define MANUFACT_ID_REG		0x0201
+#define PHYS_INT_VER_REG	0x0202
+#define PROD_PROPERTY_REG	0x0203
+#define INFO_QUERY_REG0		0x0204
+#define INFO_QUERY_REG1		(INFO_QUERY_REG0 + 1)
+#define INFO_QUERY_REG2		(INFO_QUERY_REG0 + 2)
+#define INFO_QUERY_REG3		(INFO_QUERY_REG0 + 3)
+
+#define PRODUCT_ID_REG0		0x0210
+#define PRODUCT_ID_REG1		(PRODUCT_ID_REG0 + 1)
+#define PRODUCT_ID_REG2		(PRODUCT_ID_REG0 + 2)
+#define PRODUCT_ID_REG3		(PRODUCT_ID_REG0 + 3)
+#define PRODUCT_ID_REG4		(PRODUCT_ID_REG0 + 4)
+#define PRODUCT_ID_REG5		(PRODUCT_ID_REG0 + 5)
+#define PRODUCT_ID_REG6		(PRODUCT_ID_REG0 + 6)
+#define PRODUCT_ID_REG7		(PRODUCT_ID_REG0 + 7)
+#define PRODUCT_ID_REG8		(PRODUCT_ID_REG0 + 8)
+#define PRODUCT_ID_REG9		(PRODUCT_ID_REG0 + 9)
+#define PRODUCT_ID_REG10	(PRODUCT_ID_REG0 + 10)
+#define PRODUCT_ID_REG11	(PRODUCT_ID_REG0 + 11)
+#define PRODUCT_ID_REG12	(PRODUCT_ID_REG0 + 12)
+#define PRODUCT_ID_REG13	(PRODUCT_ID_REG0 + 13)
+#define PRODUCT_ID_REG14	(PRODUCT_ID_REG0 + 14)
+#define PRODUCT_ID_REG15	(PRODUCT_ID_REG0 + 15)
+
+#define DATA_REG0		0x0400
+#define ABS_PRESSURE_REG	0x0401
+#define ABS_MSB_X_REG		0x0402
+#define ABS_LSB_X_REG		(ABS_MSB_X_REG + 1)
+#define ABS_MSB_Y_REG		0x0404
+#define ABS_LSB_Y_REG		(ABS_MSB_Y_REG + 1)
+#define REL_X_REG		0x0406
+#define REL_Y_REG		0x0407
+
+#define DEV_QUERY_REG0		0x1000
+#define DEV_QUERY_REG1		(DEV_QUERY_REG0 + 1)
+#define DEV_QUERY_REG2		(DEV_QUERY_REG0 + 2)
+#define DEV_QUERY_REG3		(DEV_QUERY_REG0 + 3)
+#define DEV_QUERY_REG4		(DEV_QUERY_REG0 + 4)
+#define DEV_QUERY_REG5		(DEV_QUERY_REG0 + 5)
+#define DEV_QUERY_REG6		(DEV_QUERY_REG0 + 6)
+#define DEV_QUERY_REG7		(DEV_QUERY_REG0 + 7)
+#define DEV_QUERY_REG8		(DEV_QUERY_REG0 + 8)
+
+#define GENERAL_2D_CONTROL_REG	0x1041
+#define SENSOR_SENSITIVITY_REG	0x1044
+#define SENS_MAX_POS_MSB_REG	0x1046
+#define SENS_MAX_POS_LSB_REG	(SENS_MAX_POS_UPPER_REG + 1)
+
+/* Register bits */
+/* Device Control Register Bits */
+#define REPORT_RATE_1ST_BIT	6
+
+/* Interrupt Enable Register Bits (INTERRUPT_EN_REG) */
+#define F10_ABS_INT_ENA		0
+#define F10_REL_INT_ENA		1
+#define F20_INT_ENA		2
+
+/* Interrupt Request Register Bits (INT_REQ_STAT_REG | DEVICE_STATUS_REG) */
+#define F10_ABS_INT_REQ		0
+#define F10_REL_INT_REQ		1
+#define F20_INT_REQ		2
+/* Device Status Register Bits (DEVICE_STATUS_REG) */
+#define STAT_CONFIGURED		6
+#define STAT_ERROR		7
+
+/* Device Command Register Bits (DEV_COMMAND_REG) */
+#define RESET_COMMAND		0x01
+#define REZERO_COMMAND		0x02
+
+/* Data Register 0 Bits (DATA_REG0) */
+#define GESTURE			3
+
+/* Device Query Registers Bits */
+/* DEV_QUERY_REG3 */
+#define HAS_PALM_DETECT		1
+#define HAS_MULTI_FING		2
+#define HAS_SCROLLER		4
+#define HAS_2D_SCROLL		5
+
+/* General 2D Control Register Bits (GENERAL_2D_CONTROL_REG) */
+#define NO_DECELERATION		1
+#define REDUCE_REPORTING	3
+#define NO_FILTER		5
+
+/* Function Masks */
+/* Device Control Register Masks (DEV_CONTROL_REG) */
+#define REPORT_RATE_MSK		0xc0
+#define SLEEP_MODE_MSK		0x07
+
+/* Device Sleep Modes */
+#define FULL_AWAKE		0x0
+#define NORMAL_OP		0x1
+#define LOW_PWR_OP		0x2
+#define VERY_LOW_PWR_OP		0x3
+#define SENS_SLEEP		0x4
+#define SLEEP_MOD		0x5
+#define DEEP_SLEEP		0x6
+#define HIBERNATE		0x7
+
+/* Interrupt Register Mask */
+/* (INT_REQ_STAT_REG | DEVICE_STATUS_REG | INTERRUPT_EN_REG) */
+#define INT_ENA_REQ_MSK		0x07
+#define INT_ENA_ABS_MSK		0x01
+#define INT_ENA_REL_MSK		0x02
+#define INT_ENA_F20_MSK		0x04
+
+/* Device Status Register Masks (DEVICE_STATUS_REG) */
+#define CONFIGURED_MSK		0x40
+#define ERROR_MSK		0x80
+
+/* Data Register 0 Masks */
+#define FINGER_WIDTH_MSK	0xf0
+#define GESTURE_MSK		0x08
+#define SENSOR_STATUS_MSK	0x07
+
+/*
+ * MSB Position Register Masks
+ * ABS_MSB_X_REG | ABS_MSB_Y_REG | SENS_MAX_POS_MSB_REG |
+ * DEV_QUERY_REG3 | DEV_QUERY_REG5
+ */
+#define MSB_POSITION_MSK	0x1f
+
+/* Device Query Registers Masks */
+
+/* DEV_QUERY_REG2 */
+#define NUM_EXTRA_POS_MSK	0x07
+
+/* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */
+#define THREAD_IRQ_SLEEP_SECS	2
+#define THREAD_IRQ_SLEEP_MSECS	(THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC)
+
+/*
+ * When in Polling mode and no data received for NO_DATA_THRES msecs
+ * reduce the polling rate to NO_DATA_SLEEP_MSECS
+ */
+#define NO_DATA_THRES		(MSEC_PER_SEC)
+#define NO_DATA_SLEEP_MSECS	(MSEC_PER_SEC / 4)
+
+/* Control touchpad's No Deceleration option */
+static int no_decel = 1;
+module_param(no_decel, bool, 0644);
+MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)");
+
+/* Control touchpad's Reduced Reporting option */
+static int reduce_report;
+module_param(reduce_report, bool, 0644);
+MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)");
+
+/* Control touchpad's No Filter option */
+static int no_filter;
+module_param(no_filter, bool, 0644);
+MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)");
+
+/*
+ * touchpad Attention line is Active Low and Open Drain,
+ * therefore should be connected to pulled up line
+ * and the irq configuration should be set to Falling Edge Trigger
+ */
+/* Control IRQ / Polling option */
+static int polling_req;
+module_param(polling_req, bool, 0444);
+MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
+
+/* Control Polling Rate */
+static int scan_rate = 80;
+module_param(scan_rate, int, 0644);
+MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 80");
+
+/* The main device structure */
+struct synaptics_i2c {
+	struct i2c_client	*client;
+	struct input_dev	*input;
+	struct delayed_work	dwork;
+	int			no_data_count;
+	int			no_decel_param;
+	int			reduce_report_param;
+	int			no_filter_param;
+	int			scan_rate_param;
+	int			scan_ms;
+};
+
+static inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rate)
+{
+	touch->scan_ms = MSEC_PER_SEC / scan_rate;
+	touch->scan_rate_param = scan_rate;
+}
+
+/*
+ * Driver's initial design makes no race condition possible on i2c bus,
+ * so there is no need in any locking.
+ * Keep it in mind, while playing with the code.
+ */
+static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
+	if (ret == 0)
+		ret = i2c_smbus_read_byte_data(client, reg & 0xff);
+
+	return ret;
+}
+
+static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
+	if (ret == 0)
+		ret = i2c_smbus_write_byte_data(client, reg & 0xff, val);
+
+	return ret;
+}
+
+static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
+	if (ret == 0)
+		ret = i2c_smbus_read_word_data(client, reg & 0xff);
+
+	return ret;
+}
+
+static int synaptics_i2c_config(struct i2c_client *client)
+{
+	int ret, control;
+	u8 int_en;
+
+	/* set Report Rate to Device Highest (>=80) and Sleep to normal */
+	ret = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1);
+	if (ret)
+		return ret;
+
+	/* set Interrupt Disable to Func20 / Enable to Func10) */
+	int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK;
+	ret = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en);
+	if (ret)
+		return ret;
+
+	control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG);
+	/* No Deceleration */
+	control |= no_decel ? 1 << NO_DECELERATION : 0;
+	/* Reduced Reporting */
+	control |= reduce_report ? 1 << REDUCE_REPORTING : 0;
+	/* No Filter */
+	control |= no_filter ? 1 << NO_FILTER : 0;
+	ret = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int synaptics_i2c_reset_config(struct i2c_client *client)
+{
+	int ret;
+
+	/* Reset the Touchpad */
+	ret = synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND);
+	if (ret) {
+		dev_err(&client->dev, "Unable to reset device\n");
+	} else {
+		msleep(SOFT_RESET_DELAY_MS);
+		ret = synaptics_i2c_config(client);
+		if (ret)
+			dev_err(&client->dev, "Unable to config device\n");
+	}
+
+	return ret;
+}
+
+static int synaptics_i2c_check_error(struct i2c_client *client)
+{
+	int status, ret = 0;
+
+	status = i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) &
+		(CONFIGURED_MSK | ERROR_MSK);
+
+	if (status != CONFIGURED_MSK)
+		ret = synaptics_i2c_reset_config(client);
+
+	return ret;
+}
+
+static bool synaptics_i2c_get_input(struct synaptics_i2c *touch)
+{
+	struct input_dev *input = touch->input;
+	int xy_delta, gesture;
+	s32 data;
+	s8 x_delta, y_delta;
+
+	/* Deal with spontanious resets and errors */
+	if (synaptics_i2c_check_error(touch->client))
+		return 0;
+
+	/* Get Gesture Bit */
+	data = synaptics_i2c_reg_get(touch->client, DATA_REG0);
+	gesture = (data >> GESTURE) & 0x1;
+
+	/*
+	 * Get Relative axes. we have to get them in one shot,
+	 * so we get 2 bytes starting from REL_X_REG.
+	 */
+	xy_delta = synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff;
+
+	/* Separate X from Y */
+	x_delta = xy_delta & 0xff;
+	y_delta = (xy_delta >> REGISTER_LENGTH) & 0xff;
+
+	/* Report the button event */
+	input_report_key(input, BTN_LEFT, gesture);
+
+	/* Report the deltas */
+	input_report_rel(input, REL_X, x_delta);
+	input_report_rel(input, REL_Y, -y_delta);
+	input_sync(input);
+
+	return xy_delta || gesture;
+}
+
+static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id)
+{
+	struct synaptics_i2c *touch = dev_id;
+
+	/*
+	 * We want to have the work run immediately but it might have
+	 * already been scheduled with a delay, that's why we have to
+	 * cancel it first.
+	 */
+	cancel_delayed_work(&touch->dwork);
+	schedule_delayed_work(&touch->dwork, 0);
+
+	return IRQ_HANDLED;
+}
+
+static void synaptics_i2c_check_params(struct synaptics_i2c *touch)
+{
+	bool reset = false;
+
+	if (scan_rate != touch->scan_rate_param)
+		set_scan_rate(touch, scan_rate);
+
+	if (no_decel != touch->no_decel_param) {
+		touch->no_decel_param = no_decel;
+		reset = true;
+	}
+
+	if (no_filter != touch->no_filter_param) {
+		touch->no_filter_param = no_filter;
+		reset = true;
+	}
+
+	if (reduce_report != touch->reduce_report_param) {
+		touch->reduce_report_param = reduce_report;
+		reset = true;
+	}
+
+	if (reset)
+		synaptics_i2c_reset_config(touch->client);
+}
+
+/* Control the Device polling rate / Work Handler sleep time */
+unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch,
+					 bool have_data)
+{
+	unsigned long delay, nodata_count_thres;
+
+	if (polling_req) {
+		delay = touch->scan_ms;
+		if (have_data) {
+			touch->no_data_count = 0;
+		} else {
+			nodata_count_thres = NO_DATA_THRES / touch->scan_ms;
+			if (touch->no_data_count < nodata_count_thres)
+				touch->no_data_count++;
+			else
+				delay = NO_DATA_SLEEP_MSECS;
+		}
+		return msecs_to_jiffies(delay);
+	} else {
+		delay = msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS);
+		return round_jiffies_relative(delay);
+	}
+}
+
+/* Work Handler */
+static void synaptics_i2c_work_handler(struct work_struct *work)
+{
+	bool have_data;
+	struct synaptics_i2c *touch =
+			container_of(work, struct synaptics_i2c, dwork.work);
+	unsigned long delay;
+
+	synaptics_i2c_check_params(touch);
+
+	have_data = synaptics_i2c_get_input(touch);
+	delay = synaptics_i2c_adjust_delay(touch, have_data);
+
+	/*
+	 * While interrupt driven, there is no real need to poll the device.
+	 * But touchpads are very sensitive, so there could be errors
+	 * related to physical environment and the attention line isn't
+	 * neccesarily asserted. In such case we can lose the touchpad.
+	 * We poll the device once in THREAD_IRQ_SLEEP_SECS and
+	 * if error is detected, we try to reset and reconfigure the touchpad.
+	 */
+	schedule_delayed_work(&touch->dwork, delay);
+}
+
+static int synaptics_i2c_open(struct input_dev *input)
+{
+	struct synaptics_i2c *touch = input_get_drvdata(input);
+	int ret;
+
+	ret = synaptics_i2c_reset_config(touch->client);
+	if (ret)
+		return ret;
+
+	if (polling_req)
+		schedule_delayed_work(&touch->dwork,
+				       msecs_to_jiffies(NO_DATA_SLEEP_MSECS));
+
+	return 0;
+}
+
+static void synaptics_i2c_close(struct input_dev *input)
+{
+	struct synaptics_i2c *touch = input_get_drvdata(input);
+
+	if (!polling_req)
+		synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0);
+
+	cancel_delayed_work_sync(&touch->dwork);
+
+	/* Save some power */
+	synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP);
+}
+
+static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch)
+{
+	struct input_dev *input = touch->input;
+
+	input->name = touch->client->name;
+	input->phys = touch->client->adapter->name;
+	input->id.bustype = BUS_I2C;
+	input->id.version = synaptics_i2c_word_get(touch->client,
+						   INFO_QUERY_REG0);
+	input->dev.parent = &touch->client->dev;
+	input->open = synaptics_i2c_open;
+	input->close = synaptics_i2c_close;
+	input_set_drvdata(input, touch);
+
+	/* Register the device as mouse */
+	__set_bit(EV_REL, input->evbit);
+	__set_bit(REL_X, input->relbit);
+	__set_bit(REL_Y, input->relbit);
+
+	/* Register device's buttons and keys */
+	__set_bit(EV_KEY, input->evbit);
+	__set_bit(BTN_LEFT, input->keybit);
+}
+
+struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client)
+{
+	struct synaptics_i2c *touch;
+
+	touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL);
+	if (!touch)
+		return NULL;
+
+	touch->client = client;
+	touch->no_decel_param = no_decel;
+	touch->scan_rate_param = scan_rate;
+	set_scan_rate(touch, scan_rate);
+	INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler);
+
+	return touch;
+}
+
+static int __devinit synaptics_i2c_probe(struct i2c_client *client,
+			       const struct i2c_device_id *dev_id)
+{
+	int ret;
+	struct synaptics_i2c *touch;
+
+	touch = synaptics_i2c_touch_create(client);
+	if (!touch)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, touch);
+
+	ret = synaptics_i2c_reset_config(client);
+	if (ret)
+		goto err_mem_free;
+
+	if (client->irq < 1)
+		polling_req = 1;
+
+	touch->input = input_allocate_device();
+	if (!touch->input) {
+		ret = -ENOMEM;
+		goto err_mem_free;
+	}
+
+	synaptics_i2c_set_input_params(touch);
+
+	if (!polling_req) {
+		dev_dbg(&touch->client->dev,
+			 "Requesting IRQ: %d\n", touch->client->irq);
+
+		ret = request_irq(touch->client->irq, synaptics_i2c_irq,
+				  IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING,
+				  DRIVER_NAME, touch);
+		if (ret) {
+			dev_warn(&touch->client->dev,
+				  "IRQ request failed: %d, "
+				  "falling back to polling\n", ret);
+			polling_req = 1;
+			synaptics_i2c_reg_set(touch->client,
+					      INTERRUPT_EN_REG, 0);
+		}
+	}
+
+	if (polling_req)
+		dev_dbg(&touch->client->dev,
+			 "Using polling at rate: %d times/sec\n", scan_rate);
+
+	/* Register the device in input subsystem */
+	ret = input_register_device(touch->input);
+	if (ret) {
+		dev_err(&client->dev,
+			 "Input device register failed: %d\n", ret);
+		goto err_input_free;
+	}
+	return 0;
+
+err_input_free:
+	input_free_device(touch->input);
+err_mem_free:
+	i2c_set_clientdata(client, NULL);
+	kfree(touch);
+
+	return ret;
+}
+
+static int __devexit synaptics_i2c_remove(struct i2c_client *client)
+{
+	struct synaptics_i2c *touch = i2c_get_clientdata(client);
+
+	if (!polling_req)
+		free_irq(touch->client->irq, touch);
+
+	input_unregister_device(touch->input);
+	i2c_set_clientdata(client, NULL);
+	kfree(touch);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct synaptics_i2c *touch = i2c_get_clientdata(client);
+
+	cancel_delayed_work_sync(&touch->dwork);
+
+	/* Save some power */
+	synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP);
+
+	return 0;
+}
+
+static int synaptics_i2c_resume(struct i2c_client *client)
+{
+	int ret;
+	struct synaptics_i2c *touch = i2c_get_clientdata(client);
+
+	ret = synaptics_i2c_reset_config(client);
+	if (ret)
+		return ret;
+
+	schedule_delayed_work(&touch->dwork,
+			       msecs_to_jiffies(NO_DATA_SLEEP_MSECS));
+
+	return 0;
+}
+#else
+#define synaptics_i2c_suspend	NULL
+#define synaptics_i2c_resume	NULL
+#endif
+
+static const struct i2c_device_id synaptics_i2c_id_table[] = {
+	{ "synaptics_i2c", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table);
+
+static struct i2c_driver synaptics_i2c_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+
+	.probe		= synaptics_i2c_probe,
+	.remove		= __devexit_p(synaptics_i2c_remove),
+
+	.suspend	= synaptics_i2c_suspend,
+	.resume		= synaptics_i2c_resume,
+	.id_table	= synaptics_i2c_id_table,
+};
+
+static int __init synaptics_i2c_init(void)
+{
+	return i2c_add_driver(&synaptics_i2c_driver);
+}
+
+static void __exit synaptics_i2c_exit(void)
+{
+	i2c_del_driver(&synaptics_i2c_driver);
+}
+
+module_init(synaptics_i2c_init);
+module_exit(synaptics_i2c_exit);
+
+MODULE_DESCRIPTION("Synaptics I2C touchpad driver");
+MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab");
+MODULE_LICENSE("GPL");
+
diff -druN linux-libre-2.6.30-gnu/drivers/input/mousedev.c linux-libre-2.6.31-gnu/drivers/input/mousedev.c
--- linux-libre-2.6.30-gnu/drivers/input/mousedev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/mousedev.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,7 +60,6 @@
 	int exist;
 	int open;
 	int minor;
-	char name[16];
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
@@ -863,19 +862,17 @@
 	init_waitqueue_head(&mousedev->wait);
 
 	if (minor == MOUSEDEV_MIX)
-		strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+		dev_set_name(&mousedev->dev, "mice");
 	else
-		snprintf(mousedev->name, sizeof(mousedev->name),
-			 "mouse%d", minor);
+		dev_set_name(&mousedev->dev, "mouse%d", minor);
 
 	mousedev->minor = minor;
 	mousedev->exist = 1;
 	mousedev->handle.dev = input_get_device(dev);
-	mousedev->handle.name = mousedev->name;
+	mousedev->handle.name = dev_name(&mousedev->dev);
 	mousedev->handle.handler = handler;
 	mousedev->handle.private = mousedev;
 
-	dev_set_name(&mousedev->dev, mousedev->name);
 	mousedev->dev.class = &input_class;
 	if (dev)
 		mousedev->dev.parent = &dev->dev;
diff -druN linux-libre-2.6.30-gnu/drivers/input/serio/ambakmi.c linux-libre-2.6.31-gnu/drivers/input/serio/ambakmi.c
--- linux-libre-2.6.30-gnu/drivers/input/serio/ambakmi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/serio/ambakmi.c	2009-09-09 18:13:59.000000000 -0400
@@ -135,7 +135,7 @@
 	io->dev.parent	= &dev->dev;
 
 	kmi->io 	= io;
-	kmi->base	= ioremap(dev->res.start, KMI_SIZE);
+	kmi->base	= ioremap(dev->res.start, resource_size(&dev->res));
 	if (!kmi->base) {
 		ret = -ENOMEM;
 		goto out;
diff -druN linux-libre-2.6.30-gnu/drivers/input/serio/hp_sdc_mlc.c linux-libre-2.6.31-gnu/drivers/input/serio/hp_sdc_mlc.c
--- linux-libre-2.6.30-gnu/drivers/input/serio/hp_sdc_mlc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/serio/hp_sdc_mlc.c	2009-09-09 18:13:59.000000000 -0400
@@ -296,7 +296,7 @@
 	priv->tseq[3] = 0;
 	if (mlc->opacket & HIL_CTRL_APE) {
 		priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
-		down_trylock(&mlc->csem);
+		BUG_ON(down_trylock(&mlc->csem));
 	}
  enqueue:
 	hp_sdc_enqueue_transaction(&priv->trans);
diff -druN linux-libre-2.6.30-gnu/drivers/input/serio/i8042.c linux-libre-2.6.31-gnu/drivers/input/serio/i8042.c
--- linux-libre-2.6.30-gnu/drivers/input/serio/i8042.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/serio/i8042.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -921,6 +922,9 @@
 #endif
 
 #ifdef CONFIG_PM
+
+static bool i8042_suspended;
+
 /*
  * Here we try to restore the original BIOS settings. We only want to
  * do that once, when we really suspend, not when we taking memory
@@ -930,12 +934,11 @@
 
 static int i8042_suspend(struct platform_device *dev, pm_message_t state)
 {
-	if (dev->dev.power.power_state.event != state.event) {
-		if (state.event == PM_EVENT_SUSPEND)
-			i8042_controller_reset();
+	if (!i8042_suspended && state.event == PM_EVENT_SUSPEND)
+		i8042_controller_reset();
 
-		dev->dev.power.power_state = state;
-	}
+	i8042_suspended = state.event == PM_EVENT_SUSPEND ||
+			  state.event == PM_EVENT_FREEZE;
 
 	return 0;
 }
@@ -952,7 +955,7 @@
 /*
  * Do not bother with restoring state if we haven't suspened yet
  */
-	if (dev->dev.power.power_state.event == PM_EVENT_ON)
+	if (!i8042_suspended)
 		return 0;
 
 	error = i8042_controller_check();
@@ -998,10 +1001,9 @@
 	if (i8042_ports[I8042_KBD_PORT_NO].serio)
 		i8042_enable_kbd_port();
 
+	i8042_suspended = false;
 	i8042_interrupt(0, NULL);
 
-	dev->dev.power.power_state = PMSG_ON;
-
 	return 0;
 }
 #endif /* CONFIG_PM */
diff -druN linux-libre-2.6.30-gnu/drivers/input/serio/i8042-x86ia64io.h linux-libre-2.6.31-gnu/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-2.6.30-gnu/drivers/input/serio/i8042-x86ia64io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/serio/i8042-x86ia64io.h	2009-09-09 18:13:59.000000000 -0400
@@ -78,6 +78,14 @@
 		},
 	},
 	{
+		.ident = "ASUS G1S",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "G1S"),
+			DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+		},
+	},
+	{
 		/* AUX LOOP command does not raise AUX IRQ */
 		.ident = "ASUS P65UP5",
 		.matches = {
@@ -374,6 +382,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
 		},
 	},
+	{
+		.ident = "Acer Aspire 5536",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+		},
+	},
 	{ }
 };
 
@@ -392,6 +408,34 @@
 			DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
 		},
 	},
+	{
+		.ident = "Acer Aspire One 150",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
+		},
+	},
+	{
+		.ident = "Advent 4211",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
+		},
+	},
+	{
+		.ident = "Medion Akoya Mini E1210",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),
+		},
+	},
+	{
+		.ident = "Mivvy M310",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
+		},
+	},
 	{ }
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/input/serio/Kconfig linux-libre-2.6.31-gnu/drivers/input/serio/Kconfig
--- linux-libre-2.6.30-gnu/drivers/input/serio/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/serio/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -192,7 +192,7 @@
 
 config SERIO_XILINX_XPS_PS2
 	tristate "Xilinx XPS PS/2 Controller Support"
-	depends on PPC
+	depends on PPC || MICROBLAZE
 	help
 	  This driver supports XPS PS/2 IP from the Xilinx EDK on
 	  PowerPC platform.
diff -druN linux-libre-2.6.30-gnu/drivers/input/serio/serio.c linux-libre-2.6.31-gnu/drivers/input/serio/serio.c
--- linux-libre-2.6.30-gnu/drivers/input/serio/serio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/serio/serio.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,17 +41,6 @@
 MODULE_DESCRIPTION("Serio abstraction core");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(serio_interrupt);
-EXPORT_SYMBOL(__serio_register_port);
-EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_unregister_child_port);
-EXPORT_SYMBOL(__serio_register_driver);
-EXPORT_SYMBOL(serio_unregister_driver);
-EXPORT_SYMBOL(serio_open);
-EXPORT_SYMBOL(serio_close);
-EXPORT_SYMBOL(serio_rescan);
-EXPORT_SYMBOL(serio_reconnect);
-
 /*
  * serio_mutex protects entire serio subsystem and is taken every time
  * serio port or driver registrered or unregistered.
@@ -506,9 +495,9 @@
 
 	retval = count;
 	if (!strncmp(buf, "manual", count)) {
-		serio->manual_bind = 1;
+		serio->manual_bind = true;
 	} else if (!strncmp(buf, "auto", count)) {
-		serio->manual_bind = 0;
+		serio->manual_bind = false;
 	} else {
 		retval = -EINVAL;
 	}
@@ -581,7 +570,7 @@
 			"serio: device_add() failed for %s (%s), error: %d\n",
 			serio->phys, serio->name, error);
 	else {
-		serio->registered = 1;
+		serio->registered = true;
 		error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
 		if (error)
 			printk(KERN_ERR
@@ -617,7 +606,7 @@
 	if (serio->registered) {
 		sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
 		device_del(&serio->dev);
-		serio->registered = 0;
+		serio->registered = false;
 	}
 
 	list_del_init(&serio->node);
@@ -692,11 +681,13 @@
 {
 	serio_queue_event(serio, NULL, SERIO_RESCAN_PORT);
 }
+EXPORT_SYMBOL(serio_rescan);
 
 void serio_reconnect(struct serio *serio)
 {
 	serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN);
 }
+EXPORT_SYMBOL(serio_reconnect);
 
 /*
  * Submits register request to kseriod for subsequent execution.
@@ -707,6 +698,7 @@
 	serio_init_port(serio);
 	serio_queue_event(serio, owner, SERIO_REGISTER_PORT);
 }
+EXPORT_SYMBOL(__serio_register_port);
 
 /*
  * Synchronously unregisters serio port.
@@ -718,6 +710,7 @@
 	serio_destroy_port(serio);
 	mutex_unlock(&serio_mutex);
 }
+EXPORT_SYMBOL(serio_unregister_port);
 
 /*
  * Safely unregisters child port if one is present.
@@ -731,6 +724,7 @@
 	}
 	mutex_unlock(&serio_mutex);
 }
+EXPORT_SYMBOL(serio_unregister_child_port);
 
 
 /*
@@ -756,9 +750,9 @@
 
 	retval = count;
 	if (!strncmp(buf, "manual", count)) {
-		serio_drv->manual_bind = 1;
+		serio_drv->manual_bind = true;
 	} else if (!strncmp(buf, "auto", count)) {
-		serio_drv->manual_bind = 0;
+		serio_drv->manual_bind = false;
 	} else {
 		retval = -EINVAL;
 	}
@@ -818,7 +812,7 @@
 
 int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name)
 {
-	int manual_bind = drv->manual_bind;
+	bool manual_bind = drv->manual_bind;
 	int error;
 
 	drv->driver.bus = &serio_bus;
@@ -829,7 +823,7 @@
 	 * Temporarily disable automatic binding because probing
 	 * takes long time and we are better off doing it in kseriod
 	 */
-	drv->manual_bind = 1;
+	drv->manual_bind = true;
 
 	error = driver_register(&drv->driver);
 	if (error) {
@@ -844,7 +838,7 @@
 	 * driver to free ports
 	 */
 	if (!manual_bind) {
-		drv->manual_bind = 0;
+		drv->manual_bind = false;
 		error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER);
 		if (error) {
 			driver_unregister(&drv->driver);
@@ -854,6 +848,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(__serio_register_driver);
 
 void serio_unregister_driver(struct serio_driver *drv)
 {
@@ -861,7 +856,7 @@
 
 	mutex_lock(&serio_mutex);
 
-	drv->manual_bind = 1;	/* so serio_find_driver ignores it */
+	drv->manual_bind = true;	/* so serio_find_driver ignores it */
 	serio_remove_pending_events(drv);
 
 start_over:
@@ -877,6 +872,7 @@
 	driver_unregister(&drv->driver);
 	mutex_unlock(&serio_mutex);
 }
+EXPORT_SYMBOL(serio_unregister_driver);
 
 static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
 {
@@ -937,26 +933,28 @@
 #ifdef CONFIG_PM
 static int serio_suspend(struct device *dev, pm_message_t state)
 {
-	if (dev->power.power_state.event != state.event) {
-		if (state.event == PM_EVENT_SUSPEND)
-			serio_cleanup(to_serio_port(dev));
+	struct serio *serio = to_serio_port(dev);
 
-		dev->power.power_state = state;
-	}
+	if (!serio->suspended && state.event == PM_EVENT_SUSPEND)
+		serio_cleanup(serio);
+
+	serio->suspended = state.event == PM_EVENT_SUSPEND ||
+			   state.event == PM_EVENT_FREEZE;
 
 	return 0;
 }
 
 static int serio_resume(struct device *dev)
 {
+	struct serio *serio = to_serio_port(dev);
+
 	/*
 	 * Driver reconnect can take a while, so better let kseriod
 	 * deal with it.
 	 */
-	if (dev->power.power_state.event != PM_EVENT_ON) {
-		dev->power.power_state = PMSG_ON;
-		serio_queue_event(to_serio_port(dev), NULL,
-				  SERIO_RECONNECT_PORT);
+	if (serio->suspended) {
+		serio->suspended = false;
+		serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT);
 	}
 
 	return 0;
@@ -974,6 +972,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(serio_open);
 
 /* called from serio_driver->connect/disconnect methods under serio_mutex */
 void serio_close(struct serio *serio)
@@ -983,6 +982,7 @@
 
 	serio_set_drv(serio, NULL);
 }
+EXPORT_SYMBOL(serio_close);
 
 irqreturn_t serio_interrupt(struct serio *serio,
 		unsigned char data, unsigned int dfl)
@@ -1003,6 +1003,7 @@
 
 	return ret;
 }
+EXPORT_SYMBOL(serio_interrupt);
 
 static struct bus_type serio_bus = {
 	.name		= "serio",
diff -druN linux-libre-2.6.30-gnu/drivers/input/tablet/gtco.c linux-libre-2.6.31-gnu/drivers/input/tablet/gtco.c
--- linux-libre-2.6.30-gnu/drivers/input/tablet/gtco.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/tablet/gtco.c	2009-09-09 18:13:59.000000000 -0400
@@ -1050,4 +1050,5 @@
 module_init(gtco_init);
 module_exit(gtco_exit);
 
+MODULE_DESCRIPTION("GTCO digitizer USB driver");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/input/tablet/wacom.h linux-libre-2.6.31-gnu/drivers/input/tablet/wacom.h
--- linux-libre-2.6.30-gnu/drivers/input/tablet/wacom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/tablet/wacom.h	2009-09-09 18:13:59.000000000 -0400
@@ -68,6 +68,7 @@
  *      v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
  *      v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
  *      v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
+ *      v1.51 (pc) - Added support for Intuos4
  */
 
 /*
@@ -88,7 +89,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.50"
+#define DRIVER_VERSION "v1.51"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
 #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
 #define DRIVER_LICENSE "GPL"
@@ -128,6 +129,8 @@
 extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
diff -druN linux-libre-2.6.30-gnu/drivers/input/tablet/wacom_sys.c linux-libre-2.6.31-gnu/drivers/input/tablet/wacom_sys.c
--- linux-libre-2.6.30-gnu/drivers/input/tablet/wacom_sys.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/tablet/wacom_sys.c	2009-09-09 18:13:59.000000000 -0400
@@ -229,6 +229,19 @@
 	input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
 }
 
+void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER);
+	input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3);
+	input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6);
+	input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+}
+
+void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_7) | BIT_MASK(BTN_8);
+}
+
 void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
 	input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9);
@@ -375,6 +388,32 @@
 	return result;
 }
 
+static int wacom_query_tablet_data(struct usb_interface *intf)
+{
+	unsigned char *rep_data;
+	int limit = 0;
+	int error;
+
+	rep_data = kmalloc(2, GFP_KERNEL);
+	if (!rep_data)
+		return -ENOMEM;
+
+	do {
+		rep_data[0] = 2;
+		rep_data[1] = 2;
+		error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+					2, rep_data, 2);
+		if (error >= 0)
+			error = usb_get_report(intf,
+						WAC_HID_FEATURE_REPORT, 2,
+						rep_data, 2);
+	} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+
+	kfree(rep_data);
+
+	return error < 0 ? error : 0;
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -385,7 +424,6 @@
 	struct wacom_features *features;
 	struct input_dev *input_dev;
 	int error = -ENOMEM;
-	char rep_data[2], limit = 0;
 	struct hid_descriptor *hid_desc;
 
 	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
@@ -476,20 +514,10 @@
 
 	/*
 	 * Ask the tablet to report tablet data if it is not a Tablet PC.
-	 * Repeat until it succeeds
+	 * Note that if query fails it is not a hard failure.
 	 */
-	if (wacom_wac->features->type != TABLETPC) {
-		do {
-			rep_data[0] = 2;
-			rep_data[1] = 2;
-			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-						2, rep_data, 2);
-			if (error >= 0)
-				error = usb_get_report(intf,
-						WAC_HID_FEATURE_REPORT, 2,
-						rep_data, 2);
-		} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
-	}
+	if (wacom_wac->features->type != TABLETPC)
+		wacom_query_tablet_data(intf);
 
 	usb_set_intfdata(intf, wacom);
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/input/tablet/wacom_wac.c linux-libre-2.6.31-gnu/drivers/input/tablet/wacom_wac.c
--- linux-libre-2.6.30-gnu/drivers/input/tablet/wacom_wac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/tablet/wacom_wac.c	2009-09-09 18:13:59.000000000 -0400
@@ -283,10 +283,11 @@
 static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
 {
 	unsigned char *data = wacom->data;
-	int idx;
+	int idx = 0;
 
 	/* tool number */
-	idx = data[1] & 0x01;
+	if (wacom->features->type == INTUOS)
+		idx = data[1] & 0x01;
 
 	/* Enter report */
 	if ((data[1] & 0xfc) == 0xc0) {
@@ -299,6 +300,7 @@
 		switch (wacom->id[idx]) {
 			case 0x812: /* Inking pen */
 			case 0x801: /* Intuos3 Inking pen */
+			case 0x20802: /* Intuos4 Classic Pen */
 			case 0x012:
 				wacom->tool[idx] = BTN_TOOL_PENCIL;
 				break;
@@ -308,6 +310,9 @@
 			case 0x823: /* Intuos3 Grip Pen */
 			case 0x813: /* Intuos3 Classic Pen */
 			case 0x885: /* Intuos3 Marker Pen */
+			case 0x802: /* Intuos4 Grip Pen Eraser */
+			case 0x804: /* Intuos4 Marker Pen */
+			case 0x40802: /* Intuos4 Classic Pen */
 			case 0x022:
 				wacom->tool[idx] = BTN_TOOL_PEN;
 				break;
@@ -319,10 +324,12 @@
 		        case 0x09c:
 			case 0x094:
 			case 0x017: /* Intuos3 2D Mouse */
+			case 0x806: /* Intuos4 Mouse */
 				wacom->tool[idx] = BTN_TOOL_MOUSE;
 				break;
 			case 0x096: /* Lens cursor */
 			case 0x097: /* Intuos3 Lens cursor */
+			case 0x006: /* Intuos4 Lens cursor */
 				wacom->tool[idx] = BTN_TOOL_LENS;
 				break;
 			case 0x82a: /* Eraser */
@@ -333,12 +340,17 @@
 			case 0x82b: /* Intuos3 Grip Pen Eraser */
 			case 0x81b: /* Intuos3 Classic Pen Eraser */
 			case 0x91b: /* Intuos3 Airbrush Eraser */
+			case 0x80c: /* Intuos4 Marker Pen Eraser */
+			case 0x80a: /* Intuos4 Grip Pen Eraser */
+			case 0x4080a: /* Intuos4 Classic Pen Eraser */
+			case 0x90a: /* Intuos4 Airbrush Eraser */
 				wacom->tool[idx] = BTN_TOOL_RUBBER;
 				break;
 			case 0xd12:
 			case 0x912:
 			case 0x112:
 			case 0x913: /* Intuos3 Airbrush */
+			case 0x902: /* Intuos4 Airbrush */
 				wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
 				break;
 			default: /* Unknown tool */
@@ -349,9 +361,15 @@
 
 	/* Exit report */
 	if ((data[1] & 0xfe) == 0x80) {
+		/*
+		 * Reset all states otherwise we lose the initial states
+		 * when in-prox next time
+		 */
 		wacom_report_abs(wcombo, ABS_X, 0);
 		wacom_report_abs(wcombo, ABS_Y, 0);
 		wacom_report_abs(wcombo, ABS_DISTANCE, 0);
+		wacom_report_abs(wcombo, ABS_TILT_X, 0);
+		wacom_report_abs(wcombo, ABS_TILT_Y, 0);
 		if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
 			wacom_report_key(wcombo, BTN_LEFT, 0);
 			wacom_report_key(wcombo, BTN_MIDDLE, 0);
@@ -362,16 +380,17 @@
 			wacom_report_abs(wcombo, ABS_RZ, 0);
 		} else {
 			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
-			wacom_report_abs(wcombo, ABS_TILT_X, 0);
-			wacom_report_abs(wcombo, ABS_TILT_Y, 0);
 			wacom_report_key(wcombo, BTN_STYLUS, 0);
 			wacom_report_key(wcombo, BTN_STYLUS2, 0);
 			wacom_report_key(wcombo, BTN_TOUCH, 0);
 			wacom_report_abs(wcombo, ABS_WHEEL, 0);
+			if (wacom->features->type >= INTUOS3S)
+				wacom_report_abs(wcombo, ABS_Z, 0);
 		}
 		wacom_report_key(wcombo, wacom->tool[idx], 0);
 		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
 		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+		wacom->id[idx] = 0;
 		return 2;
 	}
 	return 0;
@@ -385,6 +404,8 @@
 	/* general pen packet */
 	if ((data[1] & 0xb8) == 0xa0) {
 		t = (data[6] << 2) | ((data[7] >> 6) & 3);
+		if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L)
+			t = (t << 1) | (data[1] & 1);
 		wacom_report_abs(wcombo, ABS_PRESSURE, t);
 		wacom_report_abs(wcombo, ABS_TILT_X,
 				((data[7] << 1) & 0x7e) | (data[8] >> 7));
@@ -409,7 +430,7 @@
 {
 	unsigned char *data = wacom->data;
 	unsigned int t;
-	int idx, result;
+	int idx = 0, result;
 
 	if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
 		dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
@@ -417,7 +438,8 @@
 	}
 
 	/* tool number */
-	idx = data[1] & 0x01;
+	if (wacom->features->type == INTUOS)
+		idx = data[1] & 0x01;
 
 	/* pad packets. Works as a second tool and is always in prox */
 	if (data[0] == 12) {
@@ -425,25 +447,54 @@
 		if (wacom->tool[1] != BTN_TOOL_FINGER)
 			wacom->tool[1] = BTN_TOOL_FINGER;
 
-		wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
-		wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
-		wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
-		wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
-		wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
-		wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
-		wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
-		wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
-		wacom_report_key(wcombo, BTN_8, (data[5] & 0x10));
-		wacom_report_key(wcombo, BTN_9, (data[6] & 0x10));
-		wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
-		wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+		if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
+			wacom_report_key(wcombo, BTN_0, (data[2] & 0x01));
+			wacom_report_key(wcombo, BTN_1, (data[3] & 0x01));
+			wacom_report_key(wcombo, BTN_2, (data[3] & 0x02));
+			wacom_report_key(wcombo, BTN_3, (data[3] & 0x04));
+			wacom_report_key(wcombo, BTN_4, (data[3] & 0x08));
+			wacom_report_key(wcombo, BTN_5, (data[3] & 0x10));
+			wacom_report_key(wcombo, BTN_6, (data[3] & 0x20));
+			if (data[1] & 0x80) {
+				wacom_report_abs(wcombo, ABS_WHEEL, (data[1] & 0x7f));
+			} else {
+				/* Out of proximity, clear wheel value. */
+				wacom_report_abs(wcombo, ABS_WHEEL, 0);
+			}
+			if (wacom->features->type != INTUOS4S) {
+				wacom_report_key(wcombo, BTN_7, (data[3] & 0x40));
+				wacom_report_key(wcombo, BTN_8, (data[3] & 0x80));
+			}
+			if (data[1] | (data[2] & 0x01) | data[3]) {
+				wacom_report_key(wcombo, wacom->tool[1], 1);
+				wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				wacom_report_key(wcombo, wacom->tool[1], 0);
+				wacom_report_abs(wcombo, ABS_MISC, 0);
+			}
+		} else {
+			wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
+			wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
+			wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
+			wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
+			wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
+			wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
+			wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
+			wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
+			wacom_report_key(wcombo, BTN_8, (data[5] & 0x10));
+			wacom_report_key(wcombo, BTN_9, (data[6] & 0x10));
+			wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+			wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
 
-		if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
-			data[2] | (data[3] & 0x1f) | data[4])
-			wacom_report_key(wcombo, wacom->tool[1], 1);
-		else
-			wacom_report_key(wcombo, wacom->tool[1], 0);
-		wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+			if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
+				data[2] | (data[3] & 0x1f) | data[4]) {
+				wacom_report_key(wcombo, wacom->tool[1], 1);
+				wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				wacom_report_key(wcombo, wacom->tool[1], 0);
+				wacom_report_abs(wcombo, ABS_MISC, 0);
+			}
+		}
 		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
                 return 1;
 	}
@@ -453,10 +504,16 @@
 	if (result)
                 return result-1;
 
-	/* Only large I3 and I1 & I2 support Lense Cursor */
+	/* don't proceed if we don't know the ID */
+	if (!wacom->id[idx])
+		return 0;
+
+	/* Only large Intuos support Lense Cursor */
 	if ((wacom->tool[idx] == BTN_TOOL_LENS)
 			&& ((wacom->features->type == INTUOS3)
-			|| (wacom->features->type == INTUOS3S)))
+			|| (wacom->features->type == INTUOS3S)
+			|| (wacom->features->type == INTUOS4)
+			|| (wacom->features->type == INTUOS4S)))
 		return 0;
 
 	/* Cintiq doesn't send data when RDY bit isn't set */
@@ -476,8 +533,8 @@
 	/* process general packets */
 	wacom_intuos_general(wacom, wcombo);
 
-	/* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
-	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
+	/* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
+	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
 
 		if (data[1] & 0x02) {
 			/* Rotation packet */
@@ -506,20 +563,36 @@
 			wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
 
 		} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
-			/* 2D mouse packet */
-			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04);
-			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
-			wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10);
-			wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
+			/* I4 mouse */
+			if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
+				wacom_report_key(wcombo, BTN_LEFT,   data[6] & 0x01);
+				wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02);
+				wacom_report_key(wcombo, BTN_RIGHT,  data[6] & 0x04);
+				wacom_report_rel(wcombo, REL_WHEEL, ((data[7] & 0x80) >> 7)
+						 - ((data[7] & 0x40) >> 6));
+				wacom_report_key(wcombo, BTN_SIDE,   data[6] & 0x08);
+				wacom_report_key(wcombo, BTN_EXTRA,  data[6] & 0x10);
+
+				wacom_report_abs(wcombo, ABS_TILT_X,
+					((data[7] << 1) & 0x7e) | (data[8] >> 7));
+				wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+			} else {
+				/* 2D mouse packet */
+				wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04);
+				wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
+				wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10);
+				wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
 						 - ((data[8] & 0x02) >> 1));
 
-			/* I3 2D mouse side buttons */
-			if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
-				wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
-				wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
+				/* I3 2D mouse side buttons */
+				if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
+					wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
+					wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
+				}
 			}
-
-		} else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) {
+		} else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L ||
+				wacom->features->type == INTUOS4L) &&
+			   wacom->tool[idx] == BTN_TOOL_LENS) {
 			/* Lens cursor packets */
 			wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
 			wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
@@ -581,6 +654,7 @@
 			}
 		} else if (touchOut || !prox) { /* force touch out-prox */
 			wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
+			wacom_report_key(wcombo, wacom->tool[1], 0);
 			wacom_report_key(wcombo, BTN_TOUCH, 0);
 			touchOut = 0;
 			touchInProx = 1;
@@ -669,6 +743,9 @@
 		case INTUOS3S:
 		case INTUOS3:
 		case INTUOS3L:
+		case INTUOS4S:
+		case INTUOS4:
+		case INTUOS4L:
 		case CINTIQ:
 		case WACOM_BEE:
 			return wacom_intuos_irq(wacom_wac, wcombo);
@@ -706,6 +783,14 @@
 		case INTUOS:
 			input_dev_i(input_dev, wacom_wac);
 			break;
+		case INTUOS4:
+		case INTUOS4L:
+			input_dev_i4(input_dev, wacom_wac);
+			/* fall through */
+		case INTUOS4S:
+			input_dev_i4s(input_dev, wacom_wac);
+			input_dev_i(input_dev, wacom_wac);
+			break;
 		case PL:
 		case PTU:
 		case TABLETPC:
@@ -753,6 +838,7 @@
 	{ "Wacom DTU710",        8,  34080, 27660,  511,  0, PL },
 	{ "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
 	{ "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
+	{ "Wacom DTF720a",       8,   6858,  5506,  511,  0, PL },
 	{ "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
 	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
 	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
@@ -766,6 +852,10 @@
 	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
 	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
 	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
+	{ "Wacom Intuos4 4x6",   10, 31496, 19685, 2047, 63, INTUOS4S },
+	{ "Wacom Intuos4 6x9",   10, 44704, 27940, 2047, 63, INTUOS4 },
+	{ "Wacom Intuos4 8x13",  10, 65024, 40640, 2047, 63, INTUOS4L },
+	{ "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L },
 	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
 	{ "Wacom Cintiq 20WSX",  10, 86680, 54180, 1023, 63, WACOM_BEE },
 	{ "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE },
@@ -810,8 +900,9 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
@@ -825,6 +916,10 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
diff -druN linux-libre-2.6.30-gnu/drivers/input/tablet/wacom_wac.h linux-libre-2.6.31-gnu/drivers/input/tablet/wacom_wac.h
--- linux-libre-2.6.30-gnu/drivers/input/tablet/wacom_wac.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/tablet/wacom_wac.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,9 @@
 	INTUOS3S,
 	INTUOS3,
 	INTUOS3L,
+	INTUOS4S,
+	INTUOS4,
+	INTUOS4L,
 	CINTIQ,
 	WACOM_BEE,
 	WACOM_MO,
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/ads7846.c linux-libre-2.6.31-gnu/drivers/input/touchscreen/ads7846.c
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/ads7846.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/ads7846.c	2009-09-09 18:13:59.000000000 -0400
@@ -83,6 +83,7 @@
 struct ads7846 {
 	struct input_dev	*input;
 	char			phys[32];
+	char			name[32];
 
 	struct spi_device	*spi;
 
@@ -97,6 +98,8 @@
 	u16			x_plate_ohms;
 	u16			pressure_max;
 
+	bool			swap_xy;
+
 	struct ads7846_packet	*packet;
 
 	struct spi_transfer	xfer[18];
@@ -599,6 +602,10 @@
 			dev_dbg(&ts->spi->dev, "DOWN\n");
 #endif
 		}
+
+		if (ts->swap_xy)
+			swap(x, y);
+
 		input_report_abs(input, ABS_X, x);
 		input_report_abs(input, ABS_Y, y);
 		input_report_abs(input, ABS_PRESSURE, Rt);
@@ -917,6 +924,7 @@
 	ts->spi = spi;
 	ts->input = input_dev;
 	ts->vref_mv = pdata->vref_mv;
+	ts->swap_xy = pdata->swap_xy;
 
 	hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	ts->timer.function = ads7846_timer;
@@ -958,8 +966,9 @@
 	ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
 
 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
+	snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
 
-	input_dev->name = "ADS784x Touchscreen";
+	input_dev->name = ts->name;
 	input_dev->phys = ts->phys;
 	input_dev->dev.parent = &spi->dev;
 
@@ -1141,9 +1150,15 @@
 
 	if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING,
 			spi->dev.driver->name, ts)) {
-		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
-		err = -EBUSY;
-		goto err_free_gpio;
+		dev_info(&spi->dev,
+			"trying pin change workaround on irq %d\n", spi->irq);
+		err = request_irq(spi->irq, ads7846_irq,
+				  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+				  spi->dev.driver->name, ts);
+		if (err) {
+			dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
+			goto err_free_gpio;
+		}
 	}
 
 	err = ads784x_hwmon_register(spi, ts);
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/atmel-wm97xx.c linux-libre-2.6.31-gnu/drivers/input/touchscreen/atmel-wm97xx.c
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/atmel-wm97xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/atmel-wm97xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,446 @@
+/*
+ * Atmel AT91 and AVR32 continuous touch screen driver for Wolfson WM97xx AC97
+ * codecs.
+ *
+ * Copyright (C) 2008 - 2009 Atmel Corporation
+ *
+ * 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.
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/wm97xx.h>
+#include <linux/timer.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#define AC97C_ICA		0x10
+#define AC97C_CBRHR		0x30
+#define AC97C_CBSR		0x38
+#define AC97C_CBMR		0x3c
+#define AC97C_IER		0x54
+#define AC97C_IDR		0x58
+
+#define AC97C_RXRDY		(1 << 4)
+#define AC97C_OVRUN		(1 << 5)
+
+#define AC97C_CMR_SIZE_20	(0 << 16)
+#define AC97C_CMR_SIZE_18	(1 << 16)
+#define AC97C_CMR_SIZE_16	(2 << 16)
+#define AC97C_CMR_SIZE_10	(3 << 16)
+#define AC97C_CMR_CEM_LITTLE	(1 << 18)
+#define AC97C_CMR_CEM_BIG	(0 << 18)
+#define AC97C_CMR_CENA		(1 << 21)
+
+#define AC97C_INT_CBEVT		(1 << 4)
+
+#define AC97C_SR_CAEVT		(1 << 3)
+
+#define AC97C_CH_MASK(slot)						\
+	(0x7 << (3 * (slot - 3)))
+#define AC97C_CH_ASSIGN(slot, channel)					\
+	(AC97C_CHANNEL_##channel << (3 * (slot - 3)))
+#define AC97C_CHANNEL_NONE	0x0
+#define AC97C_CHANNEL_B		0x2
+
+#define ac97c_writel(chip, reg, val)			\
+	__raw_writel((val), (chip)->regs + AC97C_##reg)
+#define ac97c_readl(chip, reg)				\
+	__raw_readl((chip)->regs + AC97C_##reg)
+
+#ifdef CONFIG_CPU_AT32AP700X
+#define ATMEL_WM97XX_AC97C_IOMEM	(0xfff02800)
+#define ATMEL_WM97XX_AC97C_IRQ		(29)
+#define ATMEL_WM97XX_GPIO_DEFAULT	(32+16) /* Pin 16 on port B. */
+#else
+#error Unkown CPU, this driver only supports AT32AP700X CPUs.
+#endif
+
+struct continuous {
+	u16 id;    /* codec id */
+	u8 code;   /* continuous code */
+	u8 reads;  /* number of coord reads per read cycle */
+	u32 speed; /* number of coords per second */
+};
+
+#define WM_READS(sp) ((sp / HZ) + 1)
+
+static const struct continuous cinfo[] = {
+	{WM9705_ID2, 0, WM_READS(94), 94},
+	{WM9705_ID2, 1, WM_READS(188), 188},
+	{WM9705_ID2, 2, WM_READS(375), 375},
+	{WM9705_ID2, 3, WM_READS(750), 750},
+	{WM9712_ID2, 0, WM_READS(94), 94},
+	{WM9712_ID2, 1, WM_READS(188), 188},
+	{WM9712_ID2, 2, WM_READS(375), 375},
+	{WM9712_ID2, 3, WM_READS(750), 750},
+	{WM9713_ID2, 0, WM_READS(94), 94},
+	{WM9713_ID2, 1, WM_READS(120), 120},
+	{WM9713_ID2, 2, WM_READS(154), 154},
+	{WM9713_ID2, 3, WM_READS(188), 188},
+};
+
+/* Continuous speed index. */
+static int sp_idx;
+
+/*
+ * Pen sampling frequency (Hz) in continuous mode.
+ */
+static int cont_rate = 188;
+module_param(cont_rate, int, 0);
+MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
+
+/*
+ * Pen down detection.
+ *
+ * This driver can either poll or use an interrupt to indicate a pen down
+ * event. If the irq request fails then it will fall back to polling mode.
+ */
+static int pen_int = 1;
+module_param(pen_int, int, 0);
+MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
+
+/*
+ * Pressure readback.
+ *
+ * Set to 1 to read back pen down pressure.
+ */
+static int pressure;
+module_param(pressure, int, 0);
+MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
+
+/*
+ * AC97 touch data slot.
+ *
+ * Touch screen readback data ac97 slot.
+ */
+static int ac97_touch_slot = 5;
+module_param(ac97_touch_slot, int, 0);
+MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
+
+/*
+ * GPIO line number.
+ *
+ * Set to GPIO number where the signal from the WM97xx device is hooked up.
+ */
+static int atmel_gpio_line = ATMEL_WM97XX_GPIO_DEFAULT;
+module_param(atmel_gpio_line, int, 0);
+MODULE_PARM_DESC(atmel_gpio_line, "GPIO line number connected to WM97xx");
+
+struct atmel_wm97xx {
+	struct wm97xx		*wm;
+	struct timer_list	pen_timer;
+	void __iomem		*regs;
+	unsigned long		ac97c_irq;
+	unsigned long		gpio_pen;
+	unsigned long		gpio_irq;
+	unsigned short		x;
+	unsigned short		y;
+};
+
+static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
+{
+	struct atmel_wm97xx *atmel_wm97xx = dev_id;
+	struct wm97xx *wm = atmel_wm97xx->wm;
+	int status = ac97c_readl(atmel_wm97xx, CBSR);
+	irqreturn_t retval = IRQ_NONE;
+
+	if (status & AC97C_OVRUN) {
+		dev_dbg(&wm->touch_dev->dev, "AC97C overrun\n");
+		ac97c_readl(atmel_wm97xx, CBRHR);
+		retval = IRQ_HANDLED;
+	} else if (status & AC97C_RXRDY) {
+		u16 data;
+		u16 value;
+		u16 source;
+		u16 pen_down;
+
+		data = ac97c_readl(atmel_wm97xx, CBRHR);
+		value = data & 0x0fff;
+		source = data & WM97XX_ADCSRC_MASK;
+		pen_down = (data & WM97XX_PEN_DOWN) >> 8;
+
+		if (source == WM97XX_ADCSEL_X)
+			atmel_wm97xx->x = value;
+		if (source == WM97XX_ADCSEL_Y)
+			atmel_wm97xx->y = value;
+
+		if (!pressure && source == WM97XX_ADCSEL_Y) {
+			input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
+			input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
+			input_report_key(wm->input_dev, BTN_TOUCH, pen_down);
+			input_sync(wm->input_dev);
+		} else if (pressure && source == WM97XX_ADCSEL_PRES) {
+			input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
+			input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
+			input_report_abs(wm->input_dev, ABS_PRESSURE, value);
+			input_report_key(wm->input_dev, BTN_TOUCH, value);
+			input_sync(wm->input_dev);
+		}
+
+		retval = IRQ_HANDLED;
+	}
+
+	return retval;
+}
+
+static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm)
+{
+	struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
+	struct input_dev *input_dev = wm->input_dev;
+	int pen_down = gpio_get_value(atmel_wm97xx->gpio_pen);
+
+	if (pen_down != 0) {
+		mod_timer(&atmel_wm97xx->pen_timer,
+			  jiffies + msecs_to_jiffies(1));
+	} else {
+		if (pressure)
+			input_report_abs(input_dev, ABS_PRESSURE, 0);
+		input_report_key(input_dev, BTN_TOUCH, 0);
+		input_sync(input_dev);
+	}
+}
+
+static void atmel_wm97xx_pen_timer(unsigned long data)
+{
+	atmel_wm97xx_acc_pen_up((struct wm97xx *)data);
+}
+
+static int atmel_wm97xx_acc_startup(struct wm97xx *wm)
+{
+	struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
+	int idx = 0;
+
+	if (wm->ac97 == NULL)
+		return -ENODEV;
+
+	for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
+		if (wm->id != cinfo[idx].id)
+			continue;
+
+		sp_idx = idx;
+
+		if (cont_rate <= cinfo[idx].speed)
+			break;
+	}
+
+	wm->acc_rate = cinfo[sp_idx].code;
+	wm->acc_slot = ac97_touch_slot;
+	dev_info(&wm->touch_dev->dev, "atmel accelerated touchscreen driver, "
+			"%d samples/sec\n", cinfo[sp_idx].speed);
+
+	if (pen_int) {
+		unsigned long reg;
+
+		wm->pen_irq = atmel_wm97xx->gpio_irq;
+
+		switch (wm->id) {
+		case WM9712_ID2: /* Fall through. */
+		case WM9713_ID2:
+			/*
+			 * Use GPIO 13 (PEN_DOWN) to assert GPIO line 3
+			 * (PENDOWN).
+			 */
+			wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
+					WM97XX_GPIO_POL_HIGH,
+					WM97XX_GPIO_STICKY,
+					WM97XX_GPIO_WAKE);
+			wm97xx_config_gpio(wm, WM97XX_GPIO_3, WM97XX_GPIO_OUT,
+					WM97XX_GPIO_POL_HIGH,
+					WM97XX_GPIO_NOTSTICKY,
+					WM97XX_GPIO_NOWAKE);
+		case WM9705_ID2: /* Fall through. */
+			/*
+			 * Enable touch data slot in AC97 controller channel B.
+			 */
+			reg = ac97c_readl(atmel_wm97xx, ICA);
+			reg &= ~AC97C_CH_MASK(wm->acc_slot);
+			reg |= AC97C_CH_ASSIGN(wm->acc_slot, B);
+			ac97c_writel(atmel_wm97xx, ICA, reg);
+
+			/*
+			 * Enable channel and interrupt for RXRDY and OVERRUN.
+			 */
+			ac97c_writel(atmel_wm97xx, CBMR, AC97C_CMR_CENA
+					| AC97C_CMR_CEM_BIG
+					| AC97C_CMR_SIZE_16
+					| AC97C_OVRUN
+					| AC97C_RXRDY);
+			/* Dummy read to empty RXRHR. */
+			ac97c_readl(atmel_wm97xx, CBRHR);
+			/*
+			 * Enable interrupt for channel B in the AC97
+			 * controller.
+			 */
+			ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
+			break;
+		default:
+			dev_err(&wm->touch_dev->dev, "pen down irq not "
+					"supported on this device\n");
+			pen_int = 0;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void atmel_wm97xx_acc_shutdown(struct wm97xx *wm)
+{
+	if (pen_int) {
+		struct atmel_wm97xx *atmel_wm97xx =
+			platform_get_drvdata(wm->touch_dev);
+		unsigned long ica;
+
+		switch (wm->id & 0xffff) {
+		case WM9705_ID2: /* Fall through. */
+		case WM9712_ID2: /* Fall through. */
+		case WM9713_ID2:
+			/* Disable slot and turn off channel B interrupts. */
+			ica = ac97c_readl(atmel_wm97xx, ICA);
+			ica &= ~AC97C_CH_MASK(wm->acc_slot);
+			ac97c_writel(atmel_wm97xx, ICA, ica);
+			ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
+			ac97c_writel(atmel_wm97xx, CBMR, 0);
+			wm->pen_irq = 0;
+			break;
+		default:
+			dev_err(&wm->touch_dev->dev, "unknown codec\n");
+			break;
+		}
+	}
+}
+
+static void atmel_wm97xx_irq_enable(struct wm97xx *wm, int enable)
+{
+	/* Intentionally left empty. */
+}
+
+static struct wm97xx_mach_ops atmel_mach_ops = {
+	.acc_enabled	= 1,
+	.acc_pen_up	= atmel_wm97xx_acc_pen_up,
+	.acc_startup	= atmel_wm97xx_acc_startup,
+	.acc_shutdown	= atmel_wm97xx_acc_shutdown,
+	.irq_enable	= atmel_wm97xx_irq_enable,
+	.irq_gpio	= WM97XX_GPIO_3,
+};
+
+static int __init atmel_wm97xx_probe(struct platform_device *pdev)
+{
+	struct wm97xx *wm = platform_get_drvdata(pdev);
+	struct atmel_wm97xx *atmel_wm97xx;
+	int ret;
+
+	atmel_wm97xx = kzalloc(sizeof(struct atmel_wm97xx), GFP_KERNEL);
+	if (!atmel_wm97xx) {
+		dev_dbg(&pdev->dev, "out of memory\n");
+		return -ENOMEM;
+	}
+
+	atmel_wm97xx->wm	= wm;
+	atmel_wm97xx->regs	= (void *)ATMEL_WM97XX_AC97C_IOMEM;
+	atmel_wm97xx->ac97c_irq	= ATMEL_WM97XX_AC97C_IRQ;
+	atmel_wm97xx->gpio_pen	= atmel_gpio_line;
+	atmel_wm97xx->gpio_irq	= gpio_to_irq(atmel_wm97xx->gpio_pen);
+
+	setup_timer(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer,
+			(unsigned long)wm);
+
+	ret = request_irq(atmel_wm97xx->ac97c_irq,
+			  atmel_wm97xx_channel_b_interrupt,
+			  IRQF_SHARED, "atmel-wm97xx-ch-b", atmel_wm97xx);
+	if (ret) {
+		dev_dbg(&pdev->dev, "could not request ac97c irq\n");
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, atmel_wm97xx);
+
+	ret = wm97xx_register_mach_ops(wm, &atmel_mach_ops);
+	if (ret)
+		goto err_irq;
+
+	return ret;
+
+err_irq:
+	free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
+err:
+	platform_set_drvdata(pdev, NULL);
+	kfree(atmel_wm97xx);
+	return ret;
+}
+
+static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
+{
+	struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
+	struct wm97xx *wm = atmel_wm97xx->wm;
+
+	ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
+	free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
+	del_timer_sync(&atmel_wm97xx->pen_timer);
+	wm97xx_unregister_mach_ops(wm);
+	platform_set_drvdata(pdev, NULL);
+	kfree(atmel_wm97xx);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
+
+	ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
+	disable_irq(atmel_wm97xx->gpio_irq);
+	del_timer_sync(&atmel_wm97xx->pen_timer);
+
+	return 0;
+}
+
+static int atmel_wm97xx_resume(struct platform_device *pdev)
+{
+	struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
+	struct wm97xx *wm = atmel_wm97xx->wm;
+
+	if (wm->input_dev->users) {
+		enable_irq(atmel_wm97xx->gpio_irq);
+		ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
+	}
+
+	return 0;
+}
+#else
+#define atmel_wm97xx_suspend	NULL
+#define atmel_wm97xx_resume	NULL
+#endif
+
+static struct platform_driver atmel_wm97xx_driver = {
+	.remove		= __exit_p(atmel_wm97xx_remove),
+	.driver		= {
+		.name = "wm97xx-touch",
+	},
+	.suspend	= atmel_wm97xx_suspend,
+	.resume		= atmel_wm97xx_resume,
+};
+
+static int __init atmel_wm97xx_init(void)
+{
+	return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe);
+}
+module_init(atmel_wm97xx_init);
+
+static void __exit atmel_wm97xx_exit(void)
+{
+	platform_driver_unregister(&atmel_wm97xx_driver);
+}
+module_exit(atmel_wm97xx_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/eeti_ts.c linux-libre-2.6.31-gnu/drivers/input/touchscreen/eeti_ts.c
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/eeti_ts.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/eeti_ts.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,286 @@
+/*
+ * Touch Screen driver for EETI's I2C connected touch screen panels
+ *   Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * See EETI's software guide for the protocol specification:
+ *   http://home.eeti.com.tw/web20/eg/guide.htm
+ *
+ * Based on migor_ts.c
+ *   Copyright (c) 2008 Magnus Damm
+ *   Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>
+ *
+ * This file 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 file 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 library; 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/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/timer.h>
+#include <linux/gpio.h>
+
+static int flip_x;
+module_param(flip_x, bool, 0644);
+MODULE_PARM_DESC(flip_x, "flip x coordinate");
+
+static int flip_y;
+module_param(flip_y, bool, 0644);
+MODULE_PARM_DESC(flip_y, "flip y coordinate");
+
+struct eeti_ts_priv {
+	struct i2c_client *client;
+	struct input_dev *input;
+	struct work_struct work;
+	struct mutex mutex;
+	int irq;
+};
+
+#define EETI_TS_BITDEPTH	(11)
+#define EETI_MAXVAL		((1 << (EETI_TS_BITDEPTH + 1)) - 1)
+
+#define REPORT_BIT_PRESSED	(1 << 0)
+#define REPORT_BIT_AD0		(1 << 1)
+#define REPORT_BIT_AD1		(1 << 2)
+#define REPORT_BIT_HAS_PRESSURE	(1 << 6)
+#define REPORT_RES_BITS(v)	(((v) >> 1) + EETI_TS_BITDEPTH)
+
+static void eeti_ts_read(struct work_struct *work)
+{
+	char buf[6];
+	unsigned int x, y, res, pressed, to = 100;
+	struct eeti_ts_priv *priv =
+		container_of(work, struct eeti_ts_priv, work);
+
+	mutex_lock(&priv->mutex);
+
+	while (!gpio_get_value(irq_to_gpio(priv->irq)) && --to)
+		i2c_master_recv(priv->client, buf, sizeof(buf));
+
+	if (!to) {
+		dev_err(&priv->client->dev,
+			"unable to clear IRQ - line stuck?\n");
+		goto out;
+	}
+
+	/* drop non-report packets */
+	if (!(buf[0] & 0x80))
+		goto out;
+
+	pressed = buf[0] & REPORT_BIT_PRESSED;
+	res = REPORT_RES_BITS(buf[0] & (REPORT_BIT_AD0 | REPORT_BIT_AD1));
+	x = buf[2] | (buf[1] << 8);
+	y = buf[4] | (buf[3] << 8);
+
+	/* fix the range to 11 bits */
+	x >>= res - EETI_TS_BITDEPTH;
+	y >>= res - EETI_TS_BITDEPTH;
+
+	if (flip_x)
+		x = EETI_MAXVAL - x;
+
+	if (flip_y)
+		y = EETI_MAXVAL - y;
+
+	if (buf[0] & REPORT_BIT_HAS_PRESSURE)
+		input_report_abs(priv->input, ABS_PRESSURE, buf[5]);
+
+	input_report_abs(priv->input, ABS_X, x);
+	input_report_abs(priv->input, ABS_Y, y);
+	input_report_key(priv->input, BTN_TOUCH, !!pressed);
+	input_sync(priv->input);
+
+out:
+	mutex_unlock(&priv->mutex);
+}
+
+static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
+{
+	struct eeti_ts_priv *priv = dev_id;
+
+	 /* postpone I2C transactions as we are atomic */
+	schedule_work(&priv->work);
+
+	return IRQ_HANDLED;
+}
+
+static int eeti_ts_open(struct input_dev *dev)
+{
+	struct eeti_ts_priv *priv = input_get_drvdata(dev);
+
+	enable_irq(priv->irq);
+
+	/* Read the events once to arm the IRQ */
+	eeti_ts_read(&priv->work);
+
+	return 0;
+}
+
+static void eeti_ts_close(struct input_dev *dev)
+{
+	struct eeti_ts_priv *priv = input_get_drvdata(dev);
+
+	disable_irq(priv->irq);
+	cancel_work_sync(&priv->work);
+}
+
+static int __devinit eeti_ts_probe(struct i2c_client *client,
+				   const struct i2c_device_id *idp)
+{
+	struct eeti_ts_priv *priv;
+	struct input_dev *input;
+	int err = -ENOMEM;
+
+	/* In contrast to what's described in the datasheet, there seems
+	 * to be no way of probing the presence of that device using I2C
+	 * commands. So we need to blindly believe it is there, and wait
+	 * for interrupts to occur. */
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&client->dev, "failed to allocate driver data\n");
+		goto err0;
+	}
+
+	mutex_init(&priv->mutex);
+	input = input_allocate_device();
+
+	if (!input) {
+		dev_err(&client->dev, "Failed to allocate input device.\n");
+		goto err1;
+	}
+
+	input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(input, ABS_X, 0, EETI_MAXVAL, 0, 0);
+	input_set_abs_params(input, ABS_Y, 0, EETI_MAXVAL, 0, 0);
+	input_set_abs_params(input, ABS_PRESSURE, 0, 0xff, 0, 0);
+
+	input->name = client->name;
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = &client->dev;
+	input->open = eeti_ts_open;
+	input->close = eeti_ts_close;
+
+	priv->client = client;
+	priv->input = input;
+	priv->irq = client->irq;
+
+	INIT_WORK(&priv->work, eeti_ts_read);
+	i2c_set_clientdata(client, priv);
+	input_set_drvdata(input, priv);
+
+	err = input_register_device(input);
+	if (err)
+		goto err1;
+
+	err = request_irq(priv->irq, eeti_ts_isr, IRQF_TRIGGER_FALLING,
+			  client->name, priv);
+	if (err) {
+		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+		goto err2;
+	}
+
+	/* Disable the irq for now. It will be enabled once the input device
+	 * is opened. */
+	disable_irq(priv->irq);
+
+	device_init_wakeup(&client->dev, 0);
+	return 0;
+
+err2:
+	input_unregister_device(input);
+	input = NULL; /* so we dont try to free it below */
+err1:
+	input_free_device(input);
+	i2c_set_clientdata(client, NULL);
+	kfree(priv);
+err0:
+	return err;
+}
+
+static int __devexit eeti_ts_remove(struct i2c_client *client)
+{
+	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
+
+	free_irq(priv->irq, priv);
+	input_unregister_device(priv->input);
+	i2c_set_clientdata(client, NULL);
+	kfree(priv);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(priv->irq);
+
+	return 0;
+}
+
+static int eeti_ts_resume(struct i2c_client *client)
+{
+	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(&client->dev))
+		disable_irq_wake(priv->irq);
+
+	return 0;
+}
+#else
+#define eeti_ts_suspend NULL
+#define eeti_ts_resume NULL
+#endif
+
+static const struct i2c_device_id eeti_ts_id[] = {
+	{ "eeti_ts", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, eeti_ts_id);
+
+static struct i2c_driver eeti_ts_driver = {
+	.driver = {
+		.name = "eeti_ts",
+	},
+	.probe = eeti_ts_probe,
+	.remove = __devexit_p(eeti_ts_remove),
+	.suspend = eeti_ts_suspend,
+	.resume = eeti_ts_resume,
+	.id_table = eeti_ts_id,
+};
+
+static int __init eeti_ts_init(void)
+{
+	return i2c_add_driver(&eeti_ts_driver);
+}
+
+static void __exit eeti_ts_exit(void)
+{
+	i2c_del_driver(&eeti_ts_driver);
+}
+
+MODULE_DESCRIPTION("EETI Touchscreen driver");
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_LICENSE("GPL");
+
+module_init(eeti_ts_init);
+module_exit(eeti_ts_exit);
+
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/Kconfig linux-libre-2.6.31-gnu/drivers/input/touchscreen/Kconfig
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -111,6 +111,15 @@
 	  Say Y here to enable the support for the touchscreen found
 	  on Dialog Semiconductor DA9034 PMIC.
 
+config TOUCHSCREEN_EETI
+	tristate "EETI touchscreen panel support"
+	depends on I2C
+	help
+	  Say Y here to enable support for I2C connected EETI touch panels.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called eeti_ts.
+
 config TOUCHSCREEN_FUJITSU
 	tristate "Fujitsu serial touchscreen"
 	select SERIO
@@ -341,6 +350,21 @@
 	  Say Y here to enable support for the Wolfson Microelectronics
 	  WM9713 touchscreen controller.
 
+config TOUCHSCREEN_WM97XX_ATMEL
+	tristate "WM97xx Atmel accelerated touch"
+	depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91)
+	help
+	  Say Y here for support for streaming mode with WM97xx touchscreens
+	  on Atmel AT91 or AVR32 systems with an AC97C module.
+
+	  Be aware that this will use channel B in the controller for
+	  streaming data, this must not conflict with other AC97C drivers.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called atmel-wm97xx.
+
 config TOUCHSCREEN_WM97XX_MAINSTONE
 	tristate "WM97xx Mainstone accelerated touch"
 	depends on TOUCHSCREEN_WM97XX && ARCH_PXA
@@ -466,4 +490,12 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called tsc2007.
 
+config TOUCHSCREEN_W90X900
+	tristate "W90P910 touchscreen driver"
+	help
+	  Say Y here if you have a W90P910 based touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called w90p910_ts.
+
 endif
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/Makefile linux-libre-2.6.31-gnu/drivers/input/touchscreen/Makefile
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_CORGI)		+= corgi_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
+obj-$(CONFIG_TOUCHSCREEN_EETI)		+= eeti_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
@@ -35,5 +36,7 @@
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+= wm9705.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+= wm9712.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)	+= wm9713.o
+obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL)	+= atmel-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)	+= mainstone-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)	+= zylonite-wm97xx.o
+obj-$(CONFIG_TOUCHSCREEN_W90X900)	+= w90p910_ts.o
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/tsc2007.c linux-libre-2.6.31-gnu/drivers/input/touchscreen/tsc2007.c
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/tsc2007.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/tsc2007.c	2009-09-09 18:13:59.000000000 -0400
@@ -257,7 +257,7 @@
 	struct input_dev *input_dev;
 	int err;
 
-	if (!pdata) {
+	if (!pdata || !pdata->get_pendown_state) {
 		dev_err(&client->dev, "platform data is required!\n");
 		return -EINVAL;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/ucb1400_ts.c linux-libre-2.6.31-gnu/drivers/input/touchscreen/ucb1400_ts.c
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/ucb1400_ts.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/ucb1400_ts.c	2009-09-09 18:13:59.000000000 -0400
@@ -170,11 +170,11 @@
 	ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr);
 	ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);
 
-	if (isr & UCB_IE_TSPX) {
+	if (isr & UCB_IE_TSPX)
 		ucb1400_ts_irq_disable(ucb->ac97);
-		enable_irq(ucb->irq);
-	} else
-		printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+	else
+		dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+	enable_irq(ucb->irq);
 }
 
 static int ucb1400_ts_thread(void *_ucb)
@@ -345,6 +345,7 @@
 static int ucb1400_ts_probe(struct platform_device *dev)
 {
 	int error, x_res, y_res;
+	u16 fcsr;
 	struct ucb1400_ts *ucb = dev->dev.platform_data;
 
 	ucb->ts_idev = input_allocate_device();
@@ -382,6 +383,14 @@
 	ucb->ts_idev->evbit[0]		= BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
 	ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
+	/*
+	 * Enable ADC filter to prevent horrible jitter on Colibri.
+	 * This also further reduces jitter on boards where ADCSYNC
+	 * pin is connected.
+	 */
+	fcsr = ucb1400_reg_read(ucb->ac97, UCB_FCSR);
+	ucb1400_reg_write(ucb->ac97, UCB_FCSR, fcsr | UCB_FCSR_AVE);
+
 	ucb1400_adc_enable(ucb->ac97);
 	x_res = ucb1400_ts_read_xres(ucb);
 	y_res = ucb1400_ts_read_yres(ucb);
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/w90p910_ts.c linux-libre-2.6.31-gnu/drivers/input/touchscreen/w90p910_ts.c
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/w90p910_ts.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/w90p910_ts.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+
+/* ADC controller bit defines */
+#define ADC_DELAY	0xf00
+#define ADC_DOWN	0x01
+#define ADC_TSC_Y	(0x01 << 8)
+#define ADC_TSC_X	(0x00 << 8)
+#define TSC_FOURWIRE	(~(0x03 << 1))
+#define ADC_CLK_EN	(0x01 << 28)	/* ADC clock enable */
+#define ADC_READ_CON	(0x01 << 12)
+#define ADC_CONV	(0x01 << 13)
+#define ADC_SEMIAUTO	(0x01 << 14)
+#define ADC_WAITTRIG	(0x03 << 14)
+#define ADC_RST1	(0x01 << 16)
+#define ADC_RST0	(0x00 << 16)
+#define ADC_EN		(0x01 << 17)
+#define ADC_INT		(0x01 << 18)
+#define WT_INT		(0x01 << 20)
+#define ADC_INT_EN	(0x01 << 21)
+#define LVD_INT_EN	(0x01 << 22)
+#define WT_INT_EN	(0x01 << 23)
+#define ADC_DIV		(0x04 << 1)	/* div = 6 */
+
+enum ts_state {
+	TS_WAIT_NEW_PACKET,	/* We are waiting next touch report */
+	TS_WAIT_X_COORD,	/* We are waiting for ADC to report X coord */
+	TS_WAIT_Y_COORD,	/* We are waiting for ADC to report Y coord */
+	TS_IDLE,		/* Input device is closed, don't do anything */
+};
+
+struct w90p910_ts {
+	struct input_dev *input;
+	struct timer_list timer;
+	int irq_num;
+	void __iomem *clocken;
+	void __iomem *ts_reg;
+	spinlock_t lock;
+	enum ts_state state;
+};
+
+static void w90p910_report_event(struct w90p910_ts *w90p910_ts, bool down)
+{
+	struct input_dev *dev = w90p910_ts->input;
+
+	if (down) {
+		input_report_abs(dev, ABS_X,
+				 __raw_readl(w90p910_ts->ts_reg + 0x0c));
+		input_report_abs(dev, ABS_Y,
+				 __raw_readl(w90p910_ts->ts_reg + 0x10));
+	}
+
+	input_report_key(dev, BTN_TOUCH, down);
+	input_sync(dev);
+}
+
+static void w90p910_prepare_x_reading(struct w90p910_ts *w90p910_ts)
+{
+	unsigned long ctlreg;
+
+	__raw_writel(ADC_TSC_X, w90p910_ts->ts_reg + 0x04);
+	ctlreg = __raw_readl(w90p910_ts->ts_reg);
+	ctlreg &= ~(ADC_WAITTRIG | WT_INT | WT_INT_EN);
+	ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV;
+	__raw_writel(ctlreg, w90p910_ts->ts_reg);
+
+	w90p910_ts->state = TS_WAIT_X_COORD;
+}
+
+static void w90p910_prepare_y_reading(struct w90p910_ts *w90p910_ts)
+{
+	unsigned long ctlreg;
+
+	__raw_writel(ADC_TSC_Y, w90p910_ts->ts_reg + 0x04);
+	ctlreg = __raw_readl(w90p910_ts->ts_reg);
+	ctlreg &= ~(ADC_WAITTRIG | ADC_INT | WT_INT_EN);
+	ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV;
+	__raw_writel(ctlreg, w90p910_ts->ts_reg);
+
+	w90p910_ts->state = TS_WAIT_Y_COORD;
+}
+
+static void w90p910_prepare_next_packet(struct w90p910_ts *w90p910_ts)
+{
+	unsigned long ctlreg;
+
+	ctlreg = __raw_readl(w90p910_ts->ts_reg);
+	ctlreg &= ~(ADC_INT | ADC_INT_EN | ADC_SEMIAUTO | ADC_CONV);
+	ctlreg |= ADC_WAITTRIG | WT_INT_EN;
+	__raw_writel(ctlreg, w90p910_ts->ts_reg);
+
+	w90p910_ts->state = TS_WAIT_NEW_PACKET;
+}
+
+static irqreturn_t w90p910_ts_interrupt(int irq, void *dev_id)
+{
+	struct w90p910_ts *w90p910_ts = dev_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&w90p910_ts->lock, flags);
+
+	switch (w90p910_ts->state) {
+	case TS_WAIT_NEW_PACKET:
+		/*
+		 * The controller only generates interrupts when pen
+		 * is down.
+		 */
+		del_timer(&w90p910_ts->timer);
+		w90p910_prepare_x_reading(w90p910_ts);
+		break;
+
+
+	case TS_WAIT_X_COORD:
+		w90p910_prepare_y_reading(w90p910_ts);
+		break;
+
+	case TS_WAIT_Y_COORD:
+		w90p910_report_event(w90p910_ts, true);
+		w90p910_prepare_next_packet(w90p910_ts);
+		mod_timer(&w90p910_ts->timer, jiffies + msecs_to_jiffies(100));
+		break;
+
+	case TS_IDLE:
+		break;
+	}
+
+	spin_unlock_irqrestore(&w90p910_ts->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static void w90p910_check_pen_up(unsigned long data)
+{
+	struct w90p910_ts *w90p910_ts = (struct w90p910_ts *) data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&w90p910_ts->lock, flags);
+
+	if (w90p910_ts->state == TS_WAIT_NEW_PACKET &&
+	    !(__raw_readl(w90p910_ts->ts_reg + 0x04) & ADC_DOWN)) {
+
+		w90p910_report_event(w90p910_ts, false);
+	}
+
+	spin_unlock_irqrestore(&w90p910_ts->lock, flags);
+}
+
+static int w90p910_open(struct input_dev *dev)
+{
+	struct w90p910_ts *w90p910_ts = input_get_drvdata(dev);
+	unsigned long val;
+
+	/* enable the ADC clock */
+	val = __raw_readl(w90p910_ts->clocken);
+	__raw_writel(val | ADC_CLK_EN, w90p910_ts->clocken);
+
+	__raw_writel(ADC_RST1, w90p910_ts->ts_reg);
+	msleep(1);
+	__raw_writel(ADC_RST0, w90p910_ts->ts_reg);
+	msleep(1);
+
+	/* set delay and screen type */
+	val = __raw_readl(w90p910_ts->ts_reg + 0x04);
+	__raw_writel(val & TSC_FOURWIRE, w90p910_ts->ts_reg + 0x04);
+	__raw_writel(ADC_DELAY, w90p910_ts->ts_reg + 0x08);
+
+	w90p910_ts->state = TS_WAIT_NEW_PACKET;
+	wmb();
+
+	/* set trigger mode */
+	val = __raw_readl(w90p910_ts->ts_reg);
+	val |= ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN;
+	__raw_writel(val, w90p910_ts->ts_reg);
+
+	return 0;
+}
+
+static void w90p910_close(struct input_dev *dev)
+{
+	struct w90p910_ts *w90p910_ts = input_get_drvdata(dev);
+	unsigned long val;
+
+	/* disable trigger mode */
+
+	spin_lock_irq(&w90p910_ts->lock);
+
+	w90p910_ts->state = TS_IDLE;
+
+	val = __raw_readl(w90p910_ts->ts_reg);
+	val &= ~(ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN | ADC_INT_EN);
+	__raw_writel(val, w90p910_ts->ts_reg);
+
+	spin_unlock_irq(&w90p910_ts->lock);
+
+	/* Now that interrupts are shut off we can safely delete timer */
+	del_timer_sync(&w90p910_ts->timer);
+
+	/* stop the ADC clock */
+	val = __raw_readl(w90p910_ts->clocken);
+	__raw_writel(val & ~ADC_CLK_EN, w90p910_ts->clocken);
+}
+
+static int __devinit w90x900ts_probe(struct platform_device *pdev)
+{
+	struct w90p910_ts *w90p910_ts;
+	struct input_dev *input_dev;
+	struct resource *res;
+	int err;
+
+	w90p910_ts = kzalloc(sizeof(struct w90p910_ts), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!w90p910_ts || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
+
+	w90p910_ts->input = input_dev;
+	w90p910_ts->state = TS_IDLE;
+	spin_lock_init(&w90p910_ts->lock);
+	setup_timer(&w90p910_ts->timer, w90p910_check_pen_up,
+		    (unsigned long)&w90p910_ts);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENXIO;
+		goto fail1;
+	}
+
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				pdev->name)) {
+		err = -EBUSY;
+		goto fail1;
+	}
+
+	w90p910_ts->ts_reg = ioremap(res->start, res->end - res->start + 1);
+	if (!w90p910_ts->ts_reg) {
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		err = -ENXIO;
+		goto fail3;
+	}
+
+	w90p910_ts->clocken = (void __iomem *)res->start;
+
+	input_dev->name = "W90P910 TouchScreen";
+	input_dev->phys = "w90p910ts/event0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor  = 0x0005;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &pdev->dev;
+	input_dev->open = w90p910_open;
+	input_dev->close = w90p910_close;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(input_dev, ABS_X, 0, 0x400, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 0x400, 0, 0);
+
+	input_set_drvdata(input_dev, w90p910_ts);
+
+	w90p910_ts->irq_num = platform_get_irq(pdev, 0);
+	if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt,
+			IRQF_DISABLED, "w90p910ts", w90p910_ts)) {
+		err = -EBUSY;
+		goto fail3;
+	}
+
+	err = input_register_device(w90p910_ts->input);
+	if (err)
+		goto fail4;
+
+	platform_set_drvdata(pdev, w90p910_ts);
+
+	return 0;
+
+fail4:	free_irq(w90p910_ts->irq_num, w90p910_ts);
+fail3:	iounmap(w90p910_ts->ts_reg);
+fail2:	release_mem_region(res->start, res->end - res->start + 1);
+fail1:	input_free_device(input_dev);
+	kfree(w90p910_ts);
+	return err;
+}
+
+static int __devexit w90x900ts_remove(struct platform_device *pdev)
+{
+	struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	free_irq(w90p910_ts->irq_num, w90p910_ts);
+	del_timer_sync(&w90p910_ts->timer);
+	iounmap(w90p910_ts->ts_reg);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	input_unregister_device(w90p910_ts->input);
+	kfree(w90p910_ts);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver w90x900ts_driver = {
+	.probe		= w90x900ts_probe,
+	.remove		= __devexit_p(w90x900ts_remove),
+	.driver		= {
+		.name	= "w90x900-ts",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init w90x900ts_init(void)
+{
+	return platform_driver_register(&w90x900ts_driver);
+}
+
+static void __exit w90x900ts_exit(void)
+{
+	platform_driver_unregister(&w90x900ts_driver);
+}
+
+module_init(w90x900ts_init);
+module_exit(w90x900ts_exit);
+
+MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
+MODULE_DESCRIPTION("w90p910 touch screen driver!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:w90p910-ts");
diff -druN linux-libre-2.6.30-gnu/drivers/input/touchscreen/wm97xx-core.c linux-libre-2.6.31-gnu/drivers/input/touchscreen/wm97xx-core.c
--- linux-libre-2.6.30-gnu/drivers/input/touchscreen/wm97xx-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/touchscreen/wm97xx-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -569,7 +569,7 @@
 	mutex_init(&wm->codec_mutex);
 
 	wm->dev = dev;
-	dev->driver_data = wm;
+	dev_set_drvdata(dev, wm);
 	wm->ac97 = to_ac97_t(dev);
 
 	/* check that we have a supported codec */
diff -druN linux-libre-2.6.30-gnu/drivers/input/xen-kbdfront.c linux-libre-2.6.31-gnu/drivers/input/xen-kbdfront.c
--- linux-libre-2.6.30-gnu/drivers/input/xen-kbdfront.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/input/xen-kbdfront.c	2009-09-09 18:13:59.000000000 -0400
@@ -114,7 +114,7 @@
 		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
 		return -ENOMEM;
 	}
-	dev->dev.driver_data = info;
+	dev_set_drvdata(&dev->dev, info);
 	info->xbdev = dev;
 	info->irq = -1;
 	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
@@ -186,7 +186,7 @@
 
 static int xenkbd_resume(struct xenbus_device *dev)
 {
-	struct xenkbd_info *info = dev->dev.driver_data;
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
 
 	xenkbd_disconnect_backend(info);
 	memset(info->page, 0, PAGE_SIZE);
@@ -195,7 +195,7 @@
 
 static int xenkbd_remove(struct xenbus_device *dev)
 {
-	struct xenkbd_info *info = dev->dev.driver_data;
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
 
 	xenkbd_disconnect_backend(info);
 	if (info->kbd)
@@ -266,7 +266,7 @@
 static void xenkbd_backend_changed(struct xenbus_device *dev,
 				   enum xenbus_state backend_state)
 {
-	struct xenkbd_info *info = dev->dev.driver_data;
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
 	int ret, val;
 
 	switch (backend_state) {
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/capi/capiutil.c linux-libre-2.6.31-gnu/drivers/isdn/capi/capiutil.c
--- linux-libre-2.6.30-gnu/drivers/isdn/capi/capiutil.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/capi/capiutil.c	2009-09-09 18:13:59.000000000 -0400
@@ -490,7 +490,14 @@
 	}
 }
 
-/*-------------------------------------------------------*/
+/**
+ * capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure
+ * @cmsg:	_cmsg structure
+ * @msg:	buffer for assembled message
+ *
+ * Return value: 0 for success
+ */
+
 unsigned capi_cmsg2message(_cmsg * cmsg, u8 * msg)
 {
 	cmsg->m = msg;
@@ -553,7 +560,14 @@
 	}
 }
 
-/*-------------------------------------------------------*/
+/**
+ * capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure
+ * @cmsg:	_cmsg structure
+ * @msg:	buffer for assembled message
+ *
+ * Return value: 0 for success
+ */
+
 unsigned capi_message2cmsg(_cmsg * cmsg, u8 * msg)
 {
 	memset(cmsg, 0, sizeof(_cmsg));
@@ -573,7 +587,18 @@
 	return 0;
 }
 
-/*-------------------------------------------------------*/
+/**
+ * capi_cmsg_header() - initialize header part of _cmsg structure
+ * @cmsg:	_cmsg structure
+ * @_ApplId:	ApplID field value
+ * @_Command:	Command field value
+ * @_Subcommand:	Subcommand field value
+ * @_Messagenumber:	Message Number field value
+ * @_Controller:	Controller/PLCI/NCCI field value
+ *
+ * Return value: 0 for success
+ */
+
 unsigned capi_cmsg_header(_cmsg * cmsg, u16 _ApplId,
 			  u8 _Command, u8 _Subcommand,
 			  u16 _Messagenumber, u32 _Controller)
@@ -641,6 +666,14 @@
 	[0x4e] = "MANUFACTURER_RESP"
 };
 
+/**
+ * capi_cmd2str() - convert CAPI 2.0 command/subcommand number to name
+ * @cmd:	command number
+ * @subcmd:	subcommand number
+ *
+ * Return value: static string, NULL if command/subcommand unknown
+ */
+
 char *capi_cmd2str(u8 cmd, u8 subcmd)
 {
 	return mnames[command_2_index(cmd, subcmd)];
@@ -879,6 +912,11 @@
 	return cdb;
 }
 
+/**
+ * cdebbuf_free() - free CAPI debug buffer
+ * @cdb:	buffer to free
+ */
+
 void cdebbuf_free(_cdebbuf *cdb)
 {
 	if (likely(cdb == g_debbuf)) {
@@ -891,6 +929,16 @@
 }
 
 
+/**
+ * capi_message2str() - format CAPI 2.0 message for printing
+ * @msg:	CAPI 2.0 message
+ *
+ * Allocates a CAPI debug buffer and fills it with a printable representation
+ * of the CAPI 2.0 message in @msg.
+ * Return value: allocated debug buffer, NULL on error
+ * The returned buffer should be freed by a call to cdebbuf_free() after use.
+ */
+
 _cdebbuf *capi_message2str(u8 * msg)
 {
 	_cdebbuf *cdb;
@@ -926,10 +974,23 @@
 	return cdb;
 }
 
+/**
+ * capi_cmsg2str() - format _cmsg structure for printing
+ * @cmsg:	_cmsg structure
+ *
+ * Allocates a CAPI debug buffer and fills it with a printable representation
+ * of the CAPI 2.0 message stored in @cmsg by a previous call to
+ * capi_cmsg2message() or capi_message2cmsg().
+ * Return value: allocated debug buffer, NULL on error
+ * The returned buffer should be freed by a call to cdebbuf_free() after use.
+ */
+
 _cdebbuf *capi_cmsg2str(_cmsg * cmsg)
 {
 	_cdebbuf *cdb;
 
+	if (!cmsg->m)
+		return NULL;	/* no message */
 	cdb = cdebbuf_alloc();
 	if (!cdb)
 		return NULL;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/capi/kcapi.c linux-libre-2.6.31-gnu/drivers/isdn/capi/kcapi.c
--- linux-libre-2.6.30-gnu/drivers/isdn/capi/kcapi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/capi/kcapi.c	2009-09-09 18:13:59.000000000 -0400
@@ -377,14 +377,14 @@
 EXPORT_SYMBOL(capi_ctr_ready);
 
 /**
- * capi_ctr_reseted() - signal CAPI controller reset
+ * capi_ctr_down() - signal CAPI controller not ready
  * @card:	controller descriptor structure.
  *
  * Called by hardware driver to signal that the controller is down and
  * unavailable for use.
  */
 
-void capi_ctr_reseted(struct capi_ctr * card)
+void capi_ctr_down(struct capi_ctr * card)
 {
 	u16 appl;
 
@@ -413,7 +413,7 @@
 	notify_push(KCI_CONTRDOWN, card->cnr, 0, 0);
 }
 
-EXPORT_SYMBOL(capi_ctr_reseted);
+EXPORT_SYMBOL(capi_ctr_down);
 
 /**
  * capi_ctr_suspend_output() - suspend controller
@@ -517,7 +517,7 @@
 int detach_capi_ctr(struct capi_ctr *card)
 {
         if (card->cardstate != CARD_DETECTED)
-		capi_ctr_reseted(card);
+		capi_ctr_down(card);
 
 	ncards--;
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/divert/isdn_divert.c linux-libre-2.6.31-gnu/drivers/isdn/divert/isdn_divert.c
--- linux-libre-2.6.30-gnu/drivers/isdn/divert/isdn_divert.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/divert/isdn_divert.c	2009-09-09 18:13:59.000000000 -0400
@@ -183,7 +183,7 @@
           (mode != 1) ? "" : " 0 ",
           (mode != 1) ? "" : fwd_nr);
  
-  retval = divert_if.ll_cmd(&cs->ics); /* excute command */
+  retval = divert_if.ll_cmd(&cs->ics); /* execute command */
 
   if (!retval)
    { cs->prev = NULL;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/asyncdata.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/asyncdata.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/asyncdata.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/asyncdata.c	2009-09-09 18:13:59.000000000 -0400
@@ -174,9 +174,8 @@
 
 				if (unlikely(fcs != PPP_GOODFCS)) {
 					dev_err(cs->dev,
-					    "Packet checksum at %lu failed, "
-					    "packet is corrupted (%u bytes)!\n",
-					    bcs->rcvbytes, skb->len);
+				"Checksum failed, %u bytes corrupted!\n",
+						skb->len);
 					compskb = NULL;
 					gigaset_rcv_error(compskb, cs, bcs);
 					error = 1;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/common.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/common.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/common.c	2009-09-09 18:13:59.000000000 -0400
@@ -565,8 +565,6 @@
 	gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
 	gigaset_at_init(&bcs->at_state, bcs, cs, -1);
 
-	bcs->rcvbytes = 0;
-
 #ifdef CONFIG_GIGASET_DEBUG
 	bcs->emptycount = 0;
 #endif
@@ -672,14 +670,8 @@
 	cs->tty = NULL;
 	cs->tty_dev = NULL;
 	cs->cidmode = cidmode != 0;
-
-	//if(onechannel) { //FIXME
-		cs->tabnocid = gigaset_tab_nocid_m10x;
-		cs->tabcid = gigaset_tab_cid_m10x;
-	//} else {
-	//	cs->tabnocid = gigaset_tab_nocid;
-	//	cs->tabcid = gigaset_tab_cid;
-	//}
+	cs->tabnocid = gigaset_tab_nocid;
+	cs->tabcid = gigaset_tab_cid;
 
 	init_waitqueue_head(&cs->waitqueue);
 	cs->waiting = 0;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/ev-layer.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/ev-layer.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/ev-layer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/ev-layer.c	2009-09-09 18:13:59.000000000 -0400
@@ -160,7 +160,7 @@
 
 
 // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring
-struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */
+struct reply_t gigaset_tab_nocid[] =
 {
 	/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
 
@@ -280,7 +280,7 @@
 };
 
 // 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall
-struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */
+struct reply_t gigaset_tab_cid[] =
 {
 	/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
 
@@ -294,32 +294,33 @@
 	{RSP_OK,      604,604, -1,                605, 5, {ACT_CMD+AT_MSN}},
 	{RSP_OK,      605,605, -1,                606, 5, {ACT_CMD+AT_ISO}},
 	{RSP_NULL,    605,605, -1,                606, 5, {ACT_CMD+AT_ISO}},
-	{RSP_OK,      606,606, -1,                607, 5, {0},             "+VLS=17\r"}, /* set "Endgeraetemodus" */
+	{RSP_OK,      606,606, -1,                607, 5, {0}, "+VLS=17\r"},
 	{RSP_OK,      607,607, -1,                608,-1},
-	//{RSP_ZSAU,    608,608,ZSAU_PROCEEDING,    608, 0, {ACT_ERROR}},//DELETE
 	{RSP_ZSAU,    608,608,ZSAU_PROCEEDING,    609, 5, {ACT_CMD+AT_DIAL}},
 	{RSP_OK,      609,609, -1,                650, 0, {ACT_DIALING}},
 
-	{RSP_ZVLS,    608,608, 17,                 -1,-1, {ACT_DEBUG}},
-	{RSP_ZCTP,    609,609, -1,                 -1,-1, {ACT_DEBUG}},
-	{RSP_ZCPN,    609,609, -1,                 -1,-1, {ACT_DEBUG}},
 	{RSP_ERROR,   601,609, -1,                  0, 0, {ACT_ABORTDIAL}},
 	{EV_TIMEOUT,  601,609, -1,                  0, 0, {ACT_ABORTDIAL}},
 
-	/* dialing */
-	{RSP_ZCTP,    650,650, -1,                 -1,-1, {ACT_DEBUG}},
-	{RSP_ZCPN,    650,650, -1,                 -1,-1, {ACT_DEBUG}},
-	{RSP_ZSAU,    650,650,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* some devices don't send this */
-
-	/* connection established  */
-	{RSP_ZSAU,    650,650,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}}, //FIXME -> DLE1
-	{RSP_ZSAU,    750,750,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}}, //FIXME -> DLE1
+	/* optional dialing responses */
+	{EV_BC_OPEN,  650,650, -1,                651,-1},
+	{RSP_ZVLS,    608,651, 17,                 -1,-1, {ACT_DEBUG}},
+	{RSP_ZCTP,    609,651, -1,                 -1,-1, {ACT_DEBUG}},
+	{RSP_ZCPN,    609,651, -1,                 -1,-1, {ACT_DEBUG}},
+	{RSP_ZSAU,    650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}},
 
-	{EV_BC_OPEN,  800,800, -1,                800,-1, {ACT_NOTIFY_BC_UP}}, //FIXME new constate + timeout
+	/* connect */
+	{RSP_ZSAU,    650,650,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}},
+	{RSP_ZSAU,    651,651,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT,
+							   ACT_NOTIFY_BC_UP}},
+	{RSP_ZSAU,    750,750,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}},
+	{RSP_ZSAU,    751,751,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT,
+							   ACT_NOTIFY_BC_UP}},
+	{EV_BC_OPEN,  800,800, -1,                800,-1, {ACT_NOTIFY_BC_UP}},
 
 	/* remote hangup */
-	{RSP_ZSAU,    650,650,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEREJECT}},
-	{RSP_ZSAU,    750,750,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEHUP}},
+	{RSP_ZSAU,    650,651,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEREJECT}},
+	{RSP_ZSAU,    750,751,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEHUP}},
 	{RSP_ZSAU,    800,800,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEHUP}},
 
 	/* hangup */
@@ -358,7 +359,8 @@
 	{RSP_ZSAU,    700,729,ZSAU_ACTIVE,          0, 0, {ACT_ABORTACCEPT}},
 	{RSP_ZSAU,    700,729,ZSAU_DISCONNECT_IND,  0, 0, {ACT_ABORTACCEPT}},
 
-	{EV_TIMEOUT,  750,750, -1,                  0, 0, {ACT_CONNTIMEOUT}},
+	{EV_BC_OPEN,  750,750, -1,                751,-1},
+	{EV_TIMEOUT,  750,751, -1,                  0, 0, {ACT_CONNTIMEOUT}},
 
 	/* B channel closed (general case) */
 	{EV_BC_CLOSED, -1, -1, -1,                 -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
@@ -876,12 +878,6 @@
 
 static void bchannel_up(struct bc_state *bcs)
 {
-	if (!(bcs->chstate & CHS_D_UP)) {
-		dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__);
-		bcs->chstate |= CHS_D_UP;
-		gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
-	}
-
 	if (bcs->chstate & CHS_B_UP) {
 		dev_notice(bcs->cs->dev, "%s: B channel already up\n",
 			   __func__);
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/gigaset.h linux-libre-2.6.31-gnu/drivers/isdn/gigaset/gigaset.h
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/gigaset.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/gigaset.h	2009-09-09 18:13:59.000000000 -0400
@@ -282,8 +282,8 @@
 	char	*command;	/* NULL==none */
 };
 
-extern struct reply_t gigaset_tab_cid_m10x[];
-extern struct reply_t gigaset_tab_nocid_m10x[];
+extern struct reply_t gigaset_tab_cid[];
+extern struct reply_t gigaset_tab_nocid[];
 
 struct inbuf_t {
 	unsigned char		*rcvbuf;	/* usb-gigaset receive buffer */
@@ -384,7 +384,6 @@
 	int trans_up;			/* Counter of packages (upstream) */
 
 	struct at_state_t at_state;
-	unsigned long rcvbytes;
 
 	__u16 fcs;
 	struct sk_buff *skb;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/i4l.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/i4l.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/i4l.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/i4l.c	2009-09-09 18:13:59.000000000 -0400
@@ -544,11 +544,11 @@
 
 	gig_dbg(DEBUG_ANY, "Register driver capabilities to LL");
 
-	//iif->id[sizeof(iif->id) - 1]=0;
-	//strncpy(iif->id, isdnid, sizeof(iif->id) - 1);
 	if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
-	    >= sizeof iif->id)
-		return -ENOMEM; //FIXME EINVAL/...??
+	    >= sizeof iif->id) {
+		pr_err("ID too long: %s\n", isdnid);
+		return 0;
+	}
 
 	iif->owner = THIS_MODULE;
 	iif->channels = cs->channels;
@@ -568,8 +568,10 @@
 	iif->rcvcallb_skb = NULL;		/* Will be set by LL */
 	iif->statcallb = NULL;			/* Will be set by LL */
 
-	if (!register_isdn(iif))
+	if (!register_isdn(iif)) {
+		pr_err("register_isdn failed\n");
 		return 0;
+	}
 
 	cs->myid = iif->channels;		/* Set my device id */
 	return 1;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/interface.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/interface.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/interface.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/interface.c	2009-09-09 18:13:59.000000000 -0400
@@ -408,6 +408,8 @@
 	return retval;
 }
 
+/* FIXME: This function does not have error returns */
+
 static int if_chars_in_buffer(struct tty_struct *tty)
 {
 	struct cardstate *cs;
@@ -599,8 +601,7 @@
 	if (!IS_ERR(cs->tty_dev))
 		dev_set_drvdata(cs->tty_dev, cs);
 	else {
-		dev_warn(cs->dev,
-			 "could not register device to the tty subsystem\n");
+		pr_warning("could not register device to the tty subsystem\n");
 		cs->tty_dev = NULL;
 	}
 	mutex_unlock(&cs->mutex);
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/isocdata.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/isocdata.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/isocdata.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/isocdata.c	2009-09-09 18:13:59.000000000 -0400
@@ -174,12 +174,6 @@
 		pr_err("invalid size %d\n", size);
 		return -EINVAL;
 	}
-	src = iwb->read;
-	if (unlikely(limit >= BAS_OUTBUFSIZE + BAS_OUTBUFPAD ||
-		     (read < src && limit >= src))) {
-		pr_err("isoc write buffer frame reservation violated\n");
-		return -EFAULT;
-	}
 #endif
 
 	if (read < write) {
@@ -246,6 +240,10 @@
 	unsigned char c;
 	static char dbgline[3 * 32 + 1];
 	int i = 0;
+
+	if (!(gigaset_debuglevel & level))
+		return;
+
 	while (count-- > 0) {
 		if (i > sizeof(dbgline) - 4) {
 			dbgline[i] = '\0';
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/Kconfig linux-libre-2.6.31-gnu/drivers/isdn/gigaset/Kconfig
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,6 @@
 menuconfig ISDN_DRV_GIGASET
 	tristate "Siemens Gigaset support"
+	depends on ISDN_I4L
 	select CRC_CCITT
 	select BITREVERSE
 	help
@@ -42,11 +43,4 @@
 	  This enables debugging code in the Gigaset drivers.
 	  If in doubt, say yes.
 
-config GIGASET_UNDOCREQ
-	bool "Support for undocumented USB requests"
-	help
-	  This enables support for USB requests we only know from
-	  reverse engineering (currently M105 only). If you need
-	  features like configuration mode of M105, say yes.
-
 endif # ISDN_DRV_GIGASET
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/proc.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/proc.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/proc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/proc.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,5 +79,5 @@
 
 	gig_dbg(DEBUG_INIT, "setting up sysfs");
 	if (device_create_file(cs->tty_dev, &dev_attr_cidmode))
-		dev_err(cs->dev, "could not create sysfs attribute\n");
+		pr_err("could not create sysfs attribute\n");
 }
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/gigaset/usb-gigaset.c linux-libre-2.6.31-gnu/drivers/isdn/gigaset/usb-gigaset.c
--- linux-libre-2.6.30-gnu/drivers/isdn/gigaset/usb-gigaset.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/gigaset/usb-gigaset.c	2009-09-09 18:13:59.000000000 -0400
@@ -153,8 +153,6 @@
 	return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0);
 }
 
-#ifdef CONFIG_GIGASET_UNDOCREQ
-/* WARNING: EXPERIMENTAL! */
 static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
 				  unsigned new_state)
 {
@@ -176,6 +174,11 @@
 	return 0;
 }
 
+/*
+ * Set M105 configuration value
+ * using undocumented device commands reverse engineered from USB traces
+ * of the Siemens Windows driver
+ */
 static int set_value(struct cardstate *cs, u8 req, u16 val)
 {
 	struct usb_device *udev = cs->hw.usb->udev;
@@ -205,8 +208,10 @@
 	return r < 0 ? r : (r2 < 0 ? r2 : 0);
 }
 
-/* WARNING: HIGHLY EXPERIMENTAL! */
-// don't use this in an interrupt/BH
+/*
+ * set the baud rate on the internal serial adapter
+ * using the undocumented parameter setting command
+ */
 static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
 {
 	u16 val;
@@ -237,8 +242,10 @@
 	return set_value(cs, 1, val);
 }
 
-/* WARNING: HIGHLY EXPERIMENTAL! */
-// don't use this in an interrupt/BH
+/*
+ * set the line format on the internal serial adapter
+ * using the undocumented parameter setting command
+ */
 static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
 {
 	u16 val = 0;
@@ -274,24 +281,6 @@
 	return set_value(cs, 3, val);
 }
 
-#else
-static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
-				  unsigned new_state)
-{
-	return -ENOTTY;
-}
-
-static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
-{
-	return -ENOTTY;
-}
-
-static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
-{
-	return -ENOTTY;
-}
-#endif
-
 
  /*================================================================================================================*/
 static int gigaset_init_bchannel(struct bc_state *bcs)
@@ -362,10 +351,8 @@
 	} while (again);
 }
 
-/**
- *	gigaset_read_int_callback
- *
- *	It is called if the data was received from the device.
+/*
+ * Interrupt Input URB completion routine
  */
 static void gigaset_read_int_callback(struct urb *urb)
 {
@@ -567,18 +554,19 @@
 	return cs->cmdbytes;
 }
 
+/*
+ * set the break characters on the internal serial adapter
+ * using undocumented device commands reverse engineered from USB traces
+ * of the Siemens Windows driver
+ */
 static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
 {
-#ifdef CONFIG_GIGASET_UNDOCREQ
 	struct usb_device *udev = cs->hw.usb->udev;
 
 	gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf);
 	memcpy(cs->hw.usb->bchars, buf, 6);
 	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
 			       0, 0, &buf, 6, 2000);
-#else
-	return -ENOTTY;
-#endif
 }
 
 static int gigaset_freebcshw(struct bc_state *bcs)
@@ -625,7 +613,6 @@
 	ucs->bchars[5] = 0x13;
 	ucs->bulk_out_buffer = NULL;
 	ucs->bulk_out_urb = NULL;
-	//ucs->urb_cmd_out = NULL;
 	ucs->read_urb = NULL;
 	tasklet_init(&cs->write_tasklet,
 		     &gigaset_modem_fill, (unsigned long) cs);
@@ -742,7 +729,7 @@
 	cs->dev = &interface->dev;
 
 	/* save address of controller structure */
-	usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs);
+	usb_set_intfdata(interface, cs);
 
 	endpoint = &hostif->endpoint[0].desc;
 
@@ -921,8 +908,7 @@
 	gigaset_m10x_input,
 };
 
-/**
- *	usb_gigaset_init
+/*
  * This function is called while kernel-module is loaded
  */
 static int __init usb_gigaset_init(void)
@@ -952,9 +938,7 @@
 	return -1;
 }
 
-
-/**
- *	usb_gigaset_exit
+/*
  * This function is called while unloading the kernel-module
  */
 static void __exit usb_gigaset_exit(void)
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/b1.c linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/b1.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/b1.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/b1.c	2009-09-09 18:13:59.000000000 -0400
@@ -330,7 +330,7 @@
 	spin_lock_irqsave(&card->lock, flags);
 	capilib_release(&cinfo->ncci_head);
 	spin_unlock_irqrestore(&card->lock, flags);
-	capi_ctr_reseted(ctrl);
+	capi_ctr_down(ctrl);
 }
 
 void b1_register_appl(struct capi_ctr *ctrl,
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/b1dma.c linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/b1dma.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/b1dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/b1dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -759,7 +759,7 @@
 	memset(cinfo->version, 0, sizeof(cinfo->version));
 	capilib_release(&cinfo->ncci_head);
 	spin_unlock_irqrestore(&card->lock, flags);
-	capi_ctr_reseted(ctrl);
+	capi_ctr_down(ctrl);
 }
 
 /* ------------------------------------------------------------- */
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/c4.c linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/c4.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/c4.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/c4.c	2009-09-09 18:13:59.000000000 -0400
@@ -681,7 +681,7 @@
 			spin_lock_irqsave(&card->lock, flags);
 			capilib_release(&cinfo->ncci_head);
 			spin_unlock_irqrestore(&card->lock, flags);
-			capi_ctr_reseted(&cinfo->capi_ctrl);
+			capi_ctr_down(&cinfo->capi_ctrl);
 		}
 		card->nlogcontr = 0;
 		return IRQ_HANDLED;
@@ -909,7 +909,7 @@
         for (i=0; i < card->nr_controllers; i++) {
 		cinfo = &card->ctrlinfo[i];
 		memset(cinfo->version, 0, sizeof(cinfo->version));
-		capi_ctr_reseted(&cinfo->capi_ctrl);
+		capi_ctr_down(&cinfo->capi_ctrl);
 	}
 	card->nlogcontr = 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/t1isa.c linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/t1isa.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/avm/t1isa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/avm/t1isa.c	2009-09-09 18:13:59.000000000 -0400
@@ -339,7 +339,7 @@
 	spin_lock_irqsave(&card->lock, flags);
 	capilib_release(&cinfo->ncci_head);
 	spin_unlock_irqrestore(&card->lock, flags);
-	capi_ctr_reseted(ctrl);
+	capi_ctr_down(ctrl);
 }
 
 static void t1isa_remove(struct pci_dev *pdev)
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,167 @@
+/*
+ * For License see notice in hfc_multi.c
+ *
+ * special IO and init functions for the embedded XHFC board
+ * from Speech Design
+ *
+ */
+
+#include <asm/8xx_immap.h>
+
+/* Change this to the value used by your board */
+#ifndef IMAP_ADDR
+#define IMAP_ADDR	0xFFF00000
+#endif
+
+static void
+#ifdef HFC_REGISTER_DEBUG
+HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val,
+		const char *function, int line)
+#else
+HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val)
+#endif
+{
+	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
+	writeb(reg, hc->xhfc_memaddr);
+	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
+	writeb(val, hc->xhfc_memdata);
+}
+static u_char
+#ifdef HFC_REGISTER_DEBUG
+HFC_inb_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line)
+#else
+HFC_inb_embsd(struct hfc_multi *hc, u_char reg)
+#endif
+{
+	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
+	writeb(reg, hc->xhfc_memaddr);
+	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
+	return readb(hc->xhfc_memdata);
+}
+static u_short
+#ifdef HFC_REGISTER_DEBUG
+HFC_inw_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line)
+#else
+HFC_inw_embsd(struct hfc_multi *hc, u_char reg)
+#endif
+{
+	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
+	writeb(reg, hc->xhfc_memaddr);
+	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
+	return readb(hc->xhfc_memdata);
+}
+static void
+#ifdef HFC_REGISTER_DEBUG
+HFC_wait_embsd(struct hfc_multi *hc, const char *function, int line)
+#else
+HFC_wait_embsd(struct hfc_multi *hc)
+#endif
+{
+	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
+	writeb(R_STATUS, hc->xhfc_memaddr);
+	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
+	while (readb(hc->xhfc_memdata) & V_BUSY)
+		cpu_relax();
+}
+
+/* write fifo data (EMBSD) */
+void
+write_fifo_embsd(struct hfc_multi *hc, u_char *data, int len)
+{
+	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
+	*hc->xhfc_memaddr = A_FIFO_DATA0;
+	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
+	while (len) {
+		*hc->xhfc_memdata = *data;
+		data++;
+		len--;
+	}
+}
+
+/* read fifo data (EMBSD) */
+void
+read_fifo_embsd(struct hfc_multi *hc, u_char *data, int len)
+{
+	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
+	*hc->xhfc_memaddr = A_FIFO_DATA0;
+	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
+	while (len) {
+		*data = (u_char)(*hc->xhfc_memdata);
+		data++;
+		len--;
+	}
+}
+
+static int
+setup_embedded(struct hfc_multi *hc, struct hm_map *m)
+{
+	printk(KERN_INFO
+	    "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n",
+	    m->vendor_name, m->card_name, m->clock2 ? "double" : "normal");
+
+	hc->pci_dev = NULL;
+	if (m->clock2)
+		test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip);
+
+	hc->leds = m->leds;
+	hc->ledstate = 0xAFFEAFFE;
+	hc->opticalsupport = m->opticalsupport;
+
+	hc->pci_iobase = 0;
+	hc->pci_membase = 0;
+	hc->xhfc_membase = NULL;
+	hc->xhfc_memaddr = NULL;
+	hc->xhfc_memdata = NULL;
+
+	/* set memory access methods */
+	if (m->io_mode) /* use mode from card config */
+		hc->io_mode = m->io_mode;
+	switch (hc->io_mode) {
+	case HFC_IO_MODE_EMBSD:
+		test_and_set_bit(HFC_CHIP_EMBSD, &hc->chip);
+		hc->slots = 128; /* required */
+		/* fall through */
+		hc->HFC_outb = HFC_outb_embsd;
+		hc->HFC_inb = HFC_inb_embsd;
+		hc->HFC_inw = HFC_inw_embsd;
+		hc->HFC_wait = HFC_wait_embsd;
+		hc->read_fifo = read_fifo_embsd;
+		hc->write_fifo = write_fifo_embsd;
+		hc->xhfc_origmembase = XHFC_MEMBASE + XHFC_OFFSET * hc->id;
+		hc->xhfc_membase = (u_char *)ioremap(hc->xhfc_origmembase,
+				XHFC_MEMSIZE);
+		if (!hc->xhfc_membase) {
+			printk(KERN_WARNING
+			    "HFC-multi: failed to remap xhfc address space. "
+			    "(internal error)\n");
+			return -EIO;
+		}
+		hc->xhfc_memaddr = (u_long *)(hc->xhfc_membase + 4);
+		hc->xhfc_memdata = (u_long *)(hc->xhfc_membase);
+		printk(KERN_INFO
+		    "HFC-multi: xhfc_membase:%#lx xhfc_origmembase:%#lx "
+		    "xhfc_memaddr:%#lx xhfc_memdata:%#lx\n",
+		    (u_long)hc->xhfc_membase, hc->xhfc_origmembase,
+		    (u_long)hc->xhfc_memaddr, (u_long)hc->xhfc_memdata);
+		break;
+	default:
+		printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n");
+		return -EIO;
+	}
+
+	/* Prepare the MPC8XX PortA 10 as output (address/data selector) */
+	hc->immap = (struct immap *)(IMAP_ADDR);
+	hc->immap->im_ioport.iop_papar &= ~(PA_XHFC_A0);
+	hc->immap->im_ioport.iop_paodr &= ~(PA_XHFC_A0);
+	hc->immap->im_ioport.iop_padir |=   PA_XHFC_A0;
+
+	/* Prepare the MPC8xx PortB __X__ as input (ISDN__X__IRQ) */
+	hc->pb_irqmsk = (PB_XHFC_IRQ1 << hc->id);
+	hc->immap->im_cpm.cp_pbpar &= ~(hc->pb_irqmsk);
+	hc->immap->im_cpm.cp_pbodr &= ~(hc->pb_irqmsk);
+	hc->immap->im_cpm.cp_pbdir &= ~(hc->pb_irqmsk);
+
+	/* At this point the needed config is done */
+	/* fifos are still not enabled */
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c	2009-09-09 18:13:59.000000000 -0400
@@ -104,7 +104,7 @@
  *	If unsure, don't give this parameter.
  *
  * dslot:
- *	NOTE: only one poll value must be given for every card.
+ *	NOTE: only one dslot value must be given for every card.
  *	Also this value must be given for non-E1 cards. If omitted, the E1
  *	card has D-channel on time slot 16, which is default.
  *	If 1..15 or 17..31, an alternate time slot is used for D-channel.
@@ -139,6 +139,10 @@
  *	Selects interface with clock source for mISDN and applications.
  *	Set to card number starting with 1. Set to -1 to disable.
  *	By default, the first card is used as clock source.
+ *
+ * hwid:
+ *	NOTE: only one hwid value must be given once
+ * 	Enable special embedded devices with XHFC controllers.
  */
 
 /*
@@ -206,6 +210,11 @@
 static uint	timer;
 static uint	clockdelay_te = CLKDEL_TE;
 static uint	clockdelay_nt = CLKDEL_NT;
+#define HWID_NONE	0
+#define HWID_MINIP4	1
+#define HWID_MINIP8	2
+#define HWID_MINIP16	3
+static uint	hwid = HWID_NONE;
 
 static int	HFC_cnt, Port_cnt, PCM_cnt = 99;
 
@@ -223,6 +232,7 @@
 module_param_array(dslot, int, NULL, S_IRUGO | S_IWUSR);
 module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR);
 module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR);
+module_param(hwid, uint, S_IRUGO | S_IWUSR); /* The hardware ID */
 
 #ifdef HFC_REGISTER_DEBUG
 #define HFC_outb(hc, reg, val) \
@@ -252,6 +262,10 @@
 #define HFC_wait_nodebug(hc)		(hc->HFC_wait_nodebug(hc))
 #endif
 
+#ifdef CONFIG_MISDN_HFCMULTI_8xx
+#include "hfc_multi_8xx.h"
+#endif
+
 /* HFC_IO_MODE_PCIMEM */
 static void
 #ifdef HFC_REGISTER_DEBUG
@@ -261,7 +275,7 @@
 HFC_outb_pcimem(struct hfc_multi *hc, u_char reg, u_char val)
 #endif
 {
-	writeb(val, (hc->pci_membase)+reg);
+	writeb(val, hc->pci_membase + reg);
 }
 static u_char
 #ifdef HFC_REGISTER_DEBUG
@@ -270,7 +284,7 @@
 HFC_inb_pcimem(struct hfc_multi *hc, u_char reg)
 #endif
 {
-	return readb((hc->pci_membase)+reg);
+	return readb(hc->pci_membase + reg);
 }
 static u_short
 #ifdef HFC_REGISTER_DEBUG
@@ -279,7 +293,7 @@
 HFC_inw_pcimem(struct hfc_multi *hc, u_char reg)
 #endif
 {
-	return readw((hc->pci_membase)+reg);
+	return readw(hc->pci_membase + reg);
 }
 static void
 #ifdef HFC_REGISTER_DEBUG
@@ -288,7 +302,8 @@
 HFC_wait_pcimem(struct hfc_multi *hc)
 #endif
 {
-	while (readb((hc->pci_membase)+R_STATUS) & V_BUSY);
+	while (readb(hc->pci_membase + R_STATUS) & V_BUSY)
+		cpu_relax();
 }
 
 /* HFC_IO_MODE_REGIO */
@@ -300,7 +315,7 @@
 HFC_outb_regio(struct hfc_multi *hc, u_char reg, u_char val)
 #endif
 {
-	outb(reg, (hc->pci_iobase)+4);
+	outb(reg, hc->pci_iobase + 4);
 	outb(val, hc->pci_iobase);
 }
 static u_char
@@ -310,7 +325,7 @@
 HFC_inb_regio(struct hfc_multi *hc, u_char reg)
 #endif
 {
-	outb(reg, (hc->pci_iobase)+4);
+	outb(reg, hc->pci_iobase + 4);
 	return inb(hc->pci_iobase);
 }
 static u_short
@@ -320,7 +335,7 @@
 HFC_inw_regio(struct hfc_multi *hc, u_char reg)
 #endif
 {
-	outb(reg, (hc->pci_iobase)+4);
+	outb(reg, hc->pci_iobase + 4);
 	return inw(hc->pci_iobase);
 }
 static void
@@ -330,8 +345,9 @@
 HFC_wait_regio(struct hfc_multi *hc)
 #endif
 {
-	outb(R_STATUS, (hc->pci_iobase)+4);
-	while (inb(hc->pci_iobase) & V_BUSY);
+	outb(R_STATUS, hc->pci_iobase + 4);
+	while (inb(hc->pci_iobase) & V_BUSY)
+		cpu_relax();
 }
 
 #ifdef HFC_REGISTER_DEBUG
@@ -350,14 +366,14 @@
 	if (regname[0] == '\0')
 		strcpy(regname, "register");
 
-	bits[7] = '0'+(!!(val&1));
-	bits[6] = '0'+(!!(val&2));
-	bits[5] = '0'+(!!(val&4));
-	bits[4] = '0'+(!!(val&8));
-	bits[3] = '0'+(!!(val&16));
-	bits[2] = '0'+(!!(val&32));
-	bits[1] = '0'+(!!(val&64));
-	bits[0] = '0'+(!!(val&128));
+	bits[7] = '0' + (!!(val & 1));
+	bits[6] = '0' + (!!(val & 2));
+	bits[5] = '0' + (!!(val & 4));
+	bits[4] = '0' + (!!(val & 8));
+	bits[3] = '0' + (!!(val & 16));
+	bits[2] = '0' + (!!(val & 32));
+	bits[1] = '0' + (!!(val & 64));
+	bits[0] = '0' + (!!(val & 128));
 	printk(KERN_DEBUG
 	    "HFC_outb(chip %d, %02x=%s, 0x%02x=%s); in %s() line %d\n",
 	    hc->id, reg, regname, val, bits, function, line);
@@ -380,14 +396,14 @@
 	if (regname[0] == '\0')
 		strcpy(regname, "register");
 
-	bits[7] = '0'+(!!(val&1));
-	bits[6] = '0'+(!!(val&2));
-	bits[5] = '0'+(!!(val&4));
-	bits[4] = '0'+(!!(val&8));
-	bits[3] = '0'+(!!(val&16));
-	bits[2] = '0'+(!!(val&32));
-	bits[1] = '0'+(!!(val&64));
-	bits[0] = '0'+(!!(val&128));
+	bits[7] = '0' + (!!(val & 1));
+	bits[6] = '0' + (!!(val & 2));
+	bits[5] = '0' + (!!(val & 4));
+	bits[4] = '0' + (!!(val & 8));
+	bits[3] = '0' + (!!(val & 16));
+	bits[2] = '0' + (!!(val & 32));
+	bits[1] = '0' + (!!(val & 64));
+	bits[0] = '0' + (!!(val & 128));
 	printk(KERN_DEBUG
 	    "HFC_inb(chip %d, %02x=%s) = 0x%02x=%s; in %s() line %d\n",
 	    hc->id, reg, regname, val, bits, function, line);
@@ -467,6 +483,7 @@
 		len--;
 	}
 }
+
 /* read fifo data (REGIO) */
 static void
 read_fifo_regio(struct hfc_multi *hc, u_char *data, int len)
@@ -512,7 +529,6 @@
 	}
 }
 
-
 static void
 enable_hwirq(struct hfc_multi *hc)
 {
@@ -928,7 +944,7 @@
 			writel(pv, plx_acc_32);
 			if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) {
 				pcmmaster = hc;
-				if (hc->type == 1) {
+				if (hc->ctype == HFC_TYPE_E1) {
 					if (debug & DEBUG_HFCMULTI_PLXSD)
 						printk(KERN_DEBUG
 							"Schedule SYNC_I\n");
@@ -949,7 +965,8 @@
 		pv |= PLX_SYNC_O_EN;
 		writel(pv, plx_acc_32);
 		/* switch to jatt PLL, if not disabled by RX_SYNC */
-		if (hc->type == 1 && !test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) {
+		if (hc->ctype == HFC_TYPE_E1
+				&& !test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) {
 			if (debug & DEBUG_HFCMULTI_PLXSD)
 				printk(KERN_DEBUG "Schedule jatt PLL\n");
 			hc->e1_resync |= 2; /* switch to jatt */
@@ -961,7 +978,7 @@
 				printk(KERN_DEBUG
 					"id=%d (0x%p) = PCM master syncronized "
 					"with QUARTZ\n", hc->id, hc);
-			if (hc->type == 1) {
+			if (hc->ctype == HFC_TYPE_E1) {
 				/* Use the crystal clock for the PCM
 				   master card */
 				if (debug & DEBUG_HFCMULTI_PLXSD)
@@ -972,7 +989,7 @@
 				if (debug & DEBUG_HFCMULTI_PLXSD)
 					printk(KERN_DEBUG
 					    "QUARTZ is automatically "
-					    "enabled by HFC-%dS\n", hc->type);
+					    "enabled by HFC-%dS\n", hc->ctype);
 			}
 			plx_acc_32 = hc->plx_membase + PLX_GPIOC;
 			pv = readl(plx_acc_32);
@@ -996,7 +1013,7 @@
 	if (hc->syncronized) {
 		if (syncmaster == NULL) {
 			if (debug & DEBUG_HFCMULTI_PLXSD)
-				printk(KERN_WARNING "%s: GOT sync on card %d"
+				printk(KERN_DEBUG "%s: GOT sync on card %d"
 					" (id=%d)\n", __func__, hc->id + 1,
 					hc->id);
 			hfcmulti_resync(hc, hc, rm);
@@ -1004,7 +1021,7 @@
 	} else {
 		if (syncmaster == hc) {
 			if (debug & DEBUG_HFCMULTI_PLXSD)
-				printk(KERN_WARNING "%s: LOST sync on card %d"
+				printk(KERN_DEBUG "%s: LOST sync on card %d"
 					" (id=%d)\n", __func__, hc->id + 1,
 					hc->id);
 			hfcmulti_resync(hc, NULL, rm);
@@ -1053,20 +1070,23 @@
 		pv &= ~PLX_DSP_RES_N;
 		writel(pv, plx_acc_32);
 		if (debug & DEBUG_HFCMULTI_INIT)
-			printk(KERN_WARNING "%s: PCM off: PLX_GPIO=%x\n",
+			printk(KERN_DEBUG "%s: PCM off: PLX_GPIO=%x\n",
 				__func__, pv);
 		spin_unlock_irqrestore(&plx_lock, plx_flags);
 	}
 
 	/* disable memory mapped ports / io ports */
 	test_and_clear_bit(HFC_CHIP_PLXSD, &hc->chip); /* prevent resync */
-	pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0);
+	if (hc->pci_dev)
+		pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0);
 	if (hc->pci_membase)
 		iounmap(hc->pci_membase);
 	if (hc->plx_membase)
 		iounmap(hc->plx_membase);
 	if (hc->pci_iobase)
 		release_region(hc->pci_iobase, 8);
+	if (hc->xhfc_membase)
+		iounmap((void *)hc->xhfc_membase);
 
 	if (hc->pci_dev) {
 		pci_disable_device(hc->pci_dev);
@@ -1100,8 +1120,9 @@
 	/* revision check */
 	if (debug & DEBUG_HFCMULTI_INIT)
 		printk(KERN_DEBUG "%s: entered\n", __func__);
-	val = HFC_inb(hc, R_CHIP_ID)>>4;
-	if (val != 0x8 && val != 0xc && val != 0xe) {
+	val = HFC_inb(hc, R_CHIP_ID);
+	if ((val >> 4) != 0x8 && (val >> 4) != 0xc && (val >> 4) != 0xe &&
+	    (val >> 1) != 0x31) {
 		printk(KERN_INFO "HFC_multi: unknown CHIP_ID:%x\n", (u_int)val);
 		err = -EIO;
 		goto out;
@@ -1109,8 +1130,9 @@
 	rev = HFC_inb(hc, R_CHIP_RV);
 	printk(KERN_INFO
 	    "HFC_multi: detected HFC with chip ID=0x%lx revision=%ld%s\n",
-	    val, rev, (rev == 0) ? " (old FIFO handling)" : "");
-	if (rev == 0) {
+	    val, rev, (rev == 0 && (hc->ctype != HFC_TYPE_XHFC)) ?
+		" (old FIFO handling)" : "");
+	if (hc->ctype != HFC_TYPE_XHFC && rev == 0) {
 		test_and_set_bit(HFC_CHIP_REVISION0, &hc->chip);
 		printk(KERN_WARNING
 		    "HFC_multi: NOTE: Your chip is revision 0, "
@@ -1152,6 +1174,12 @@
 		hc->Zlen = 8000;
 		hc->DTMFbase = 0x2000;
 	}
+	if (hc->ctype == HFC_TYPE_XHFC) {
+		hc->Flen = 0x8;
+		hc->Zmin = 0x0;
+		hc->Zlen = 64;
+		hc->DTMFbase = 0x0;
+	}
 	hc->max_trans = poll << 1;
 	if (hc->max_trans > hc->Zlen)
 		hc->max_trans = hc->Zlen;
@@ -1176,7 +1204,7 @@
 		writel(pv, plx_acc_32);
 		spin_unlock_irqrestore(&plx_lock, plx_flags);
 		if (debug & DEBUG_HFCMULTI_INIT)
-			printk(KERN_WARNING "%s: slave/term: PLX_GPIO=%x\n",
+			printk(KERN_DEBUG "%s: slave/term: PLX_GPIO=%x\n",
 				__func__, pv);
 		/*
 		 * If we are the 3rd PLXSD card or higher, we must turn
@@ -1204,13 +1232,17 @@
 			writel(pv, plx_acc_32);
 			spin_unlock_irqrestore(&plx_lock, plx_flags);
 			if (debug & DEBUG_HFCMULTI_INIT)
-			    printk(KERN_WARNING "%s: term off: PLX_GPIO=%x\n",
-					__func__, pv);
+				printk(KERN_DEBUG
+				    "%s: term off: PLX_GPIO=%x\n",
+				    __func__, pv);
 		}
 		spin_unlock_irqrestore(&HFClock, hfc_flags);
 		hc->hw.r_pcm_md0 = V_F0_LEN; /* shift clock for DSP */
 	}
 
+	if (test_bit(HFC_CHIP_EMBSD, &hc->chip))
+		hc->hw.r_pcm_md0 = V_F0_LEN; /* shift clock for DSP */
+
 	/* we only want the real Z2 read-pointer for revision > 0 */
 	if (!test_bit(HFC_CHIP_REVISION0, &hc->chip))
 		hc->hw.r_ram_sz |= V_FZ_MD;
@@ -1234,15 +1266,24 @@
 
 	/* soft reset */
 	HFC_outb(hc, R_CTRL, hc->hw.r_ctrl);
-	HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
+	if (hc->ctype == HFC_TYPE_XHFC)
+		HFC_outb(hc, 0x0C /* R_FIFO_THRES */,
+				0x11 /* 16 Bytes TX/RX */);
+	else
+		HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
 	HFC_outb(hc, R_FIFO_MD, 0);
-	hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES | V_RLD_EPR;
+	if (hc->ctype == HFC_TYPE_XHFC)
+		hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES;
+	else
+		hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES
+			| V_RLD_EPR;
 	HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
 	udelay(100);
 	hc->hw.r_cirm = 0;
 	HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
 	udelay(100);
-	HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
+	if (hc->ctype != HFC_TYPE_XHFC)
+		HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
 
 	/* Speech Design PLX bridge pcm and sync mode */
 	if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
@@ -1254,13 +1295,13 @@
 			pv |= PLX_MASTER_EN | PLX_SLAVE_EN_N;
 			pv |= PLX_SYNC_O_EN;
 			if (debug & DEBUG_HFCMULTI_INIT)
-				printk(KERN_WARNING "%s: master: PLX_GPIO=%x\n",
+				printk(KERN_DEBUG "%s: master: PLX_GPIO=%x\n",
 					__func__, pv);
 		} else {
 			pv &= ~(PLX_MASTER_EN | PLX_SLAVE_EN_N);
 			pv &= ~PLX_SYNC_O_EN;
 			if (debug & DEBUG_HFCMULTI_INIT)
-				printk(KERN_WARNING "%s: slave: PLX_GPIO=%x\n",
+				printk(KERN_DEBUG "%s: slave: PLX_GPIO=%x\n",
 					__func__, pv);
 		}
 		writel(pv, plx_acc_32);
@@ -1278,13 +1319,16 @@
 	HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0);
 	if (test_bit(HFC_CHIP_PLXSD, &hc->chip))
 		HFC_outb(hc, R_PCM_MD2, V_SYNC_SRC); /* sync via SYNC_I / O */
+	else if (test_bit(HFC_CHIP_EMBSD, &hc->chip))
+		HFC_outb(hc, R_PCM_MD2, 0x10); /* V_C2O_EN */
 	else
 		HFC_outb(hc, R_PCM_MD2, 0x00); /* sync from interface */
 	HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00);
 	for (i = 0; i < 256; i++) {
 		HFC_outb_nodebug(hc, R_SLOT, i);
 		HFC_outb_nodebug(hc, A_SL_CFG, 0);
-		HFC_outb_nodebug(hc, A_CONF, 0);
+		if (hc->ctype != HFC_TYPE_XHFC)
+			HFC_outb_nodebug(hc, A_CONF, 0);
 		hc->slot_owner[i] = -1;
 	}
 
@@ -1296,6 +1340,9 @@
 		HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
 	}
 
+	if (test_bit(HFC_CHIP_EMBSD, &hc->chip))
+		HFC_outb(hc, 0x02 /* R_CLK_CFG */, 0x40 /* V_CLKO_OFF */);
+
 	/* B410P GPIO */
 	if (test_bit(HFC_CHIP_B410P, &hc->chip)) {
 		printk(KERN_NOTICE "Setting GPIOs\n");
@@ -1366,8 +1413,8 @@
 				writel(pv, plx_acc_32);
 				spin_unlock_irqrestore(&plx_lock, plx_flags);
 				if (debug & DEBUG_HFCMULTI_INIT)
-				    printk(KERN_WARNING "%s: master: PLX_GPIO"
-					"=%x\n", __func__, pv);
+					printk(KERN_DEBUG "%s: master: "
+					    "PLX_GPIO=%x\n", __func__, pv);
 			}
 			hc->hw.r_pcm_md0 |= V_PCM_MD;
 			HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00);
@@ -1401,7 +1448,7 @@
 		writel(pv, plx_acc_32);
 		spin_unlock_irqrestore(&plx_lock, plx_flags);
 		if (debug & DEBUG_HFCMULTI_INIT)
-			printk(KERN_WARNING "%s: reset off: PLX_GPIO=%x\n",
+			printk(KERN_DEBUG "%s: reset off: PLX_GPIO=%x\n",
 				__func__, pv);
 	}
 
@@ -1424,7 +1471,7 @@
 	hc->hw.r_irqmsk_misc |= V_TI_IRQMSK;
 
 	/* set E1 state machine IRQ */
-	if (hc->type == 1)
+	if (hc->ctype == HFC_TYPE_E1)
 		hc->hw.r_irqmsk_misc |= V_STA_IRQMSK;
 
 	/* set DTMF detection */
@@ -1444,7 +1491,8 @@
 		r_conf_en = V_CONF_EN | V_ULAW;
 	else
 		r_conf_en = V_CONF_EN;
-	HFC_outb(hc, R_CONF_EN, r_conf_en);
+	if (hc->ctype != HFC_TYPE_XHFC)
+		HFC_outb(hc, R_CONF_EN, r_conf_en);
 
 	/* setting leds */
 	switch (hc->leds) {
@@ -1468,16 +1516,23 @@
 		break;
 	}
 
+	if (test_bit(HFC_CHIP_EMBSD, &hc->chip)) {
+		hc->hw.r_st_sync = 0x10; /* V_AUTO_SYNCI */
+		HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync);
+	}
+
 	/* set master clock */
 	if (hc->masterclk >= 0) {
 		if (debug & DEBUG_HFCMULTI_INIT)
 			printk(KERN_DEBUG "%s: setting ST master clock "
 			    "to port %d (0..%d)\n",
 			    __func__, hc->masterclk, hc->ports-1);
-		hc->hw.r_st_sync = hc->masterclk | V_AUTO_SYNC;
+		hc->hw.r_st_sync |= (hc->masterclk | V_AUTO_SYNC);
 		HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync);
 	}
 
+
+
 	/* setting misc irq */
 	HFC_outb(hc, R_IRQMSK_MISC, hc->hw.r_irqmsk_misc);
 	if (debug & DEBUG_HFCMULTI_INIT)
@@ -1817,8 +1872,8 @@
 			coeff[(co<<1)|1] = mantissa;
 		}
 		if (debug & DEBUG_HFCMULTI_DTMF)
-			printk("%s: DTMF ready %08x %08x %08x %08x "
-			    "%08x %08x %08x %08x\n", __func__,
+			printk(" DTMF ready %08x %08x %08x %08x "
+			    "%08x %08x %08x %08x\n",
 			    coeff[0], coeff[1], coeff[2], coeff[3],
 			    coeff[4], coeff[5], coeff[6], coeff[7]);
 		hc->chan[ch].coeff_count++;
@@ -1826,7 +1881,7 @@
 			hc->chan[ch].coeff_count = 0;
 			skb = mI_alloc_skb(512, GFP_ATOMIC);
 			if (!skb) {
-				printk(KERN_WARNING "%s: No memory for skb\n",
+				printk(KERN_DEBUG "%s: No memory for skb\n",
 				    __func__);
 				continue;
 			}
@@ -1929,7 +1984,7 @@
 				Fspace = 1;
 		}
 		/* one frame only for ST D-channels, to allow resending */
-		if (hc->type != 1 && dch) {
+		if (hc->ctype != HFC_TYPE_E1 && dch) {
 			if (f1 != f2)
 				Fspace = 0;
 		}
@@ -1945,6 +2000,9 @@
 				"%d!=%d\n", __func__, hc->id + 1, temp, z2);
 		z2 = temp; /* repeat unti Z2 is equal */
 	}
+	hc->chan[ch].Zfill = z1 - z2;
+	if (hc->chan[ch].Zfill < 0)
+		hc->chan[ch].Zfill += hc->Zlen;
 	Zspace = z2 - z1;
 	if (Zspace <= 0)
 		Zspace += hc->Zlen;
@@ -1968,12 +2026,22 @@
 					    "slot_tx %d\n",
 					    __func__, ch, slot_tx);
 				/* connect slot */
-				HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 |
-				    V_HDLC_TRP | V_IFF);
+				if (hc->ctype == HFC_TYPE_XHFC)
+					HFC_outb(hc, A_CON_HDLC, 0xc0
+					    | 0x07 << 2 | V_HDLC_TRP | V_IFF);
+						/* Enable FIFO, no interrupt */
+				else
+					HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 |
+					    V_HDLC_TRP | V_IFF);
 				HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1);
 				HFC_wait_nodebug(hc);
-				HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 |
-				    V_HDLC_TRP | V_IFF);
+				if (hc->ctype == HFC_TYPE_XHFC)
+					HFC_outb(hc, A_CON_HDLC, 0xc0
+					    | 0x07 << 2 | V_HDLC_TRP | V_IFF);
+						/* Enable FIFO, no interrupt */
+				else
+					HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 |
+					    V_HDLC_TRP | V_IFF);
 				HFC_outb_nodebug(hc, R_FIFO, ch<<1);
 				HFC_wait_nodebug(hc);
 			}
@@ -2001,10 +2069,22 @@
 			    "FIFO data: channel %d slot_tx %d\n",
 			    __func__, ch, slot_tx);
 		/* disconnect slot */
-		HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
+		if (hc->ctype == HFC_TYPE_XHFC)
+			HFC_outb(hc, A_CON_HDLC, 0x80
+			    | 0x07 << 2 | V_HDLC_TRP | V_IFF);
+				/* Enable FIFO, no interrupt */
+		else
+			HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 |
+			    V_HDLC_TRP | V_IFF);
 		HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1);
 		HFC_wait_nodebug(hc);
-		HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
+		if (hc->ctype == HFC_TYPE_XHFC)
+			HFC_outb(hc, A_CON_HDLC, 0x80
+			    | 0x07 << 2 | V_HDLC_TRP | V_IFF);
+				/* Enable FIFO, no interrupt */
+		else
+			HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 |
+			    V_HDLC_TRP | V_IFF);
 		HFC_outb_nodebug(hc, R_FIFO, ch<<1);
 		HFC_wait_nodebug(hc);
 	}
@@ -2027,10 +2107,11 @@
 		printk(KERN_DEBUG "%s(card %d): fifo(%d) has %d bytes space "
 		    "left (z1=%04x, z2=%04x) sending %d of %d bytes %s\n",
 			__func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i,
-			temp ? "HDLC":"TRANS");
+			temp ? "HDLC" : "TRANS");
 
 	/* Have to prep the audio data */
 	hc->write_fifo(hc, d, ii - i);
+	hc->chan[ch].Zfill += ii - i;
 	*idxp = ii;
 
 	/* if not all data has been written */
@@ -2226,7 +2307,7 @@
 			if (dch)
 				recv_Dchannel(dch);
 			else
-				recv_Bchannel(bch);
+				recv_Bchannel(bch, MISDN_ID_ANY);
 			*sp = skb;
 			again++;
 			goto next_frame;
@@ -2258,7 +2339,7 @@
 			    "(z1=%04x, z2=%04x) TRANS\n",
 				__func__, hc->id + 1, ch, Zsize, z1, z2);
 		/* only bch is transparent */
-		recv_Bchannel(bch);
+		recv_Bchannel(bch, hc->chan[ch].Zfill);
 		*sp = skb;
 	}
 }
@@ -2323,7 +2404,7 @@
 		spin_unlock_irqrestore(&HFClock, flags);
 	}
 
-	if (hc->type != 1 || hc->e1_state == 1)
+	if (hc->ctype != HFC_TYPE_E1 || hc->e1_state == 1)
 		for (ch = 0; ch <= 31; ch++) {
 			if (hc->created[hc->chan[ch].port]) {
 				hfcmulti_tx(hc, ch);
@@ -2346,7 +2427,7 @@
 				}
 			}
 		}
-	if (hc->type == 1 && hc->created[0]) {
+	if (hc->ctype == HFC_TYPE_E1 && hc->created[0]) {
 		dch = hc->chan[hc->dslot].dch;
 		if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) {
 			/* LOS */
@@ -2606,7 +2687,10 @@
 		"card %d, this is no bug.\n", hc->id + 1, irqsem);
 	irqsem = hc->id + 1;
 #endif
-
+#ifdef CONFIG_MISDN_HFCMULTI_8xx
+	if (hc->immap->im_cpm.cp_pbdat & hc->pb_irqmsk)
+		goto irq_notforus;
+#endif
 	if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
 		spin_lock_irqsave(&plx_lock, flags);
 		plx_acc = hc->plx_membase + PLX_INTCSR;
@@ -2646,7 +2730,7 @@
 	}
 	hc->irqcnt++;
 	if (r_irq_statech) {
-		if (hc->type != 1)
+		if (hc->ctype != HFC_TYPE_E1)
 			ph_state_irq(hc, r_irq_statech);
 	}
 	if (status & V_EXT_IRQSTA)
@@ -2660,7 +2744,7 @@
 		r_irq_misc = HFC_inb_nodebug(hc, R_IRQ_MISC);
 		r_irq_misc &= hc->hw.r_irqmsk_misc; /* ignore disabled irqs */
 		if (r_irq_misc & V_STA_IRQ) {
-			if (hc->type == 1) {
+			if (hc->ctype == HFC_TYPE_E1) {
 				/* state machine */
 				dch = hc->chan[hc->dslot].dch;
 				e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA);
@@ -2699,13 +2783,13 @@
 			handle_timer_irq(hc);
 		}
 
-		if (r_irq_misc & V_DTMF_IRQ) {
+		if (r_irq_misc & V_DTMF_IRQ)
 			hfcmulti_dtmf(hc);
-		}
+
 		if (r_irq_misc & V_IRQ_PROC) {
 			static int irq_proc_cnt;
 			if (!irq_proc_cnt++)
-				printk(KERN_WARNING "%s: got V_IRQ_PROC -"
+				printk(KERN_DEBUG "%s: got V_IRQ_PROC -"
 				    " this should not happen\n", __func__);
 		}
 
@@ -2782,7 +2866,8 @@
 		if (hc->slot_owner[oslot_tx<<1] == ch) {
 			HFC_outb(hc, R_SLOT, oslot_tx << 1);
 			HFC_outb(hc, A_SL_CFG, 0);
-			HFC_outb(hc, A_CONF, 0);
+			if (hc->ctype != HFC_TYPE_XHFC)
+				HFC_outb(hc, A_CONF, 0);
 			hc->slot_owner[oslot_tx<<1] = -1;
 		} else {
 			if (debug & DEBUG_HFCMULTI_MODE)
@@ -2835,7 +2920,9 @@
 			    flow_tx, routing, conf);
 		HFC_outb(hc, R_SLOT, slot_tx << 1);
 		HFC_outb(hc, A_SL_CFG, (ch<<1) | routing);
-		HFC_outb(hc, A_CONF, (conf < 0) ? 0 : (conf | V_CONF_SL));
+		if (hc->ctype != HFC_TYPE_XHFC)
+			HFC_outb(hc, A_CONF,
+				(conf < 0) ? 0 : (conf | V_CONF_SL));
 		hc->slot_owner[slot_tx << 1] = ch;
 		hc->chan[ch].slot_tx = slot_tx;
 		hc->chan[ch].bank_tx = bank_tx;
@@ -2852,7 +2939,7 @@
 		else
 			flow_rx = 0xc0; /* ST->(FIFO,PCM) */
 		/* put on slot */
-		routing = bank_rx?0x80:0xc0; /* reversed */
+		routing = bank_rx ? 0x80 : 0xc0; /* reversed */
 		if (conf >= 0 || bank_rx > 1)
 			routing = 0x40; /* loop */
 		if (debug & DEBUG_HFCMULTI_MODE)
@@ -2885,9 +2972,9 @@
 		HFC_outb(hc, A_IRQ_MSK, 0);
 		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
 		HFC_wait(hc);
-		if (hc->chan[ch].bch && hc->type != 1) {
+		if (hc->chan[ch].bch && hc->ctype != HFC_TYPE_E1) {
 			hc->hw.a_st_ctrl0[hc->chan[ch].port] &=
-			    ((ch & 0x3) == 0)? ~V_B1_EN: ~V_B2_EN;
+			    ((ch & 0x3) == 0) ? ~V_B1_EN : ~V_B2_EN;
 			HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
 			/* undocumented: delay after R_ST_SEL */
 			udelay(1);
@@ -2961,8 +3048,13 @@
 			/* enable TX fifo */
 			HFC_outb(hc, R_FIFO, ch << 1);
 			HFC_wait(hc);
-			HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 |
-			    V_HDLC_TRP | V_IFF);
+			if (hc->ctype == HFC_TYPE_XHFC)
+				HFC_outb(hc, A_CON_HDLC, flow_tx | 0x07 << 2 |
+					V_HDLC_TRP | V_IFF);
+					/* Enable FIFO, no interrupt */
+			else
+				HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 |
+					V_HDLC_TRP | V_IFF);
 			HFC_outb(hc, A_SUBCH_CFG, 0);
 			HFC_outb(hc, A_IRQ_MSK, 0);
 			HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
@@ -2972,13 +3064,19 @@
 			/* enable RX fifo */
 			HFC_outb(hc, R_FIFO, (ch<<1)|1);
 			HFC_wait(hc);
-			HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP);
+			if (hc->ctype == HFC_TYPE_XHFC)
+				HFC_outb(hc, A_CON_HDLC, flow_rx | 0x07 << 2 |
+					V_HDLC_TRP);
+					/* Enable FIFO, no interrupt*/
+			else
+				HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 |
+						V_HDLC_TRP);
 			HFC_outb(hc, A_SUBCH_CFG, 0);
 			HFC_outb(hc, A_IRQ_MSK, 0);
 			HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
 			HFC_wait(hc);
 		}
-		if (hc->type != 1) {
+		if (hc->ctype != HFC_TYPE_E1) {
 			hc->hw.a_st_ctrl0[hc->chan[ch].port] |=
 			    ((ch & 0x3) == 0) ? V_B1_EN : V_B2_EN;
 			HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
@@ -2999,7 +3097,7 @@
 		/* enable TX fifo */
 		HFC_outb(hc, R_FIFO, ch<<1);
 		HFC_wait(hc);
-		if (hc->type == 1 || hc->chan[ch].bch) {
+		if (hc->ctype == HFC_TYPE_E1 || hc->chan[ch].bch) {
 			/* E1 or B-channel */
 			HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04);
 			HFC_outb(hc, A_SUBCH_CFG, 0);
@@ -3015,7 +3113,7 @@
 		HFC_outb(hc, R_FIFO, (ch<<1)|1);
 		HFC_wait(hc);
 		HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04);
-		if (hc->type == 1 || hc->chan[ch].bch)
+		if (hc->ctype == HFC_TYPE_E1 || hc->chan[ch].bch)
 			HFC_outb(hc, A_SUBCH_CFG, 0); /* full 8 bits */
 		else
 			HFC_outb(hc, A_SUBCH_CFG, 2); /* 2 bits dchannel */
@@ -3024,7 +3122,7 @@
 		HFC_wait(hc);
 		if (hc->chan[ch].bch) {
 			test_and_set_bit(FLG_HDLC, &hc->chan[ch].bch->Flags);
-			if (hc->type != 1) {
+			if (hc->ctype != HFC_TYPE_E1) {
 				hc->hw.a_st_ctrl0[hc->chan[ch].port] |=
 				  ((ch&0x3) == 0) ? V_B1_EN : V_B2_EN;
 				HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
@@ -3104,7 +3202,7 @@
 	case HW_RESET_REQ:
 		/* start activation */
 		spin_lock_irqsave(&hc->lock, flags);
-		if (hc->type == 1) {
+		if (hc->ctype == HFC_TYPE_E1) {
 			if (debug & DEBUG_HFCMULTI_MSG)
 				printk(KERN_DEBUG
 				    "%s: HW_RESET_REQ no BRI\n",
@@ -3125,7 +3223,7 @@
 	case HW_DEACT_REQ:
 		/* start deactivation */
 		spin_lock_irqsave(&hc->lock, flags);
-		if (hc->type == 1) {
+		if (hc->ctype == HFC_TYPE_E1) {
 			if (debug & DEBUG_HFCMULTI_MSG)
 				printk(KERN_DEBUG
 				    "%s: HW_DEACT_REQ no BRI\n",
@@ -3159,7 +3257,7 @@
 		break;
 	case HW_POWERUP_REQ:
 		spin_lock_irqsave(&hc->lock, flags);
-		if (hc->type == 1) {
+		if (hc->ctype == HFC_TYPE_E1) {
 			if (debug & DEBUG_HFCMULTI_MSG)
 				printk(KERN_DEBUG
 				    "%s: HW_POWERUP_REQ no BRI\n",
@@ -3236,7 +3334,7 @@
 				    __func__, hc->chan[dch->slot].port,
 				    hc->ports-1);
 			/* start activation */
-			if (hc->type == 1) {
+			if (hc->ctype == HFC_TYPE_E1) {
 				ph_state_change(dch);
 				if (debug & DEBUG_HFCMULTI_STATE)
 					printk(KERN_DEBUG
@@ -3269,7 +3367,7 @@
 				    __func__, hc->chan[dch->slot].port,
 				    hc->ports-1);
 			/* start deactivation */
-			if (hc->type == 1) {
+			if (hc->ctype == HFC_TYPE_E1) {
 				if (debug & DEBUG_HFCMULTI_MSG)
 					printk(KERN_DEBUG
 					    "%s: PH_DEACTIVATE no BRI\n",
@@ -3410,9 +3508,9 @@
 		switch (hh->id) {
 		case HFC_SPL_LOOP_ON: /* set sample loop */
 			if (debug & DEBUG_HFCMULTI_MSG)
-			printk(KERN_DEBUG
-			    "%s: HFC_SPL_LOOP_ON (len = %d)\n",
-			    __func__, skb->len);
+				printk(KERN_DEBUG
+				    "%s: HFC_SPL_LOOP_ON (len = %d)\n",
+				    __func__, skb->len);
 			ret = 0;
 			break;
 		case HFC_SPL_LOOP_OFF: /* set silence */
@@ -3489,6 +3587,8 @@
 		features->hfc_id = hc->id;
 		if (test_bit(HFC_CHIP_DTMF, &hc->chip))
 			features->hfc_dtmf = 1;
+		if (test_bit(HFC_CHIP_CONF, &hc->chip))
+			features->hfc_conf = 1;
 		features->hfc_loops = 0;
 		if (test_bit(HFC_CHIP_B410P, &hc->chip)) {
 			features->hfc_echocanhw = 1;
@@ -3619,14 +3719,13 @@
 	int ch, i;
 
 	if (!dch) {
-		printk(KERN_WARNING "%s: ERROR given dch is NULL\n",
-		    __func__);
+		printk(KERN_WARNING "%s: ERROR given dch is NULL\n", __func__);
 		return;
 	}
 	hc = dch->hw;
 	ch = dch->slot;
 
-	if (hc->type == 1) {
+	if (hc->ctype == HFC_TYPE_E1) {
 		if (dch->dev.D.protocol == ISDN_P_TE_E1) {
 			if (debug & DEBUG_HFCMULTI_STATE)
 				printk(KERN_DEBUG
@@ -3641,14 +3740,15 @@
 		switch (dch->state) {
 		case (1):
 			if (hc->e1_state != 1) {
-			    for (i = 1; i <= 31; i++) {
-				/* reset fifos on e1 activation */
-				HFC_outb_nodebug(hc, R_FIFO, (i << 1) | 1);
-				HFC_wait_nodebug(hc);
-				HFC_outb_nodebug(hc,
-					R_INC_RES_FIFO, V_RES_F);
-				HFC_wait_nodebug(hc);
-			    }
+				for (i = 1; i <= 31; i++) {
+					/* reset fifos on e1 activation */
+					HFC_outb_nodebug(hc, R_FIFO,
+						(i << 1) | 1);
+					HFC_wait_nodebug(hc);
+					HFC_outb_nodebug(hc, R_INC_RES_FIFO,
+						V_RES_F);
+					HFC_wait_nodebug(hc);
+				}
 			}
 			test_and_set_bit(FLG_ACTIVE, &dch->Flags);
 			_queue_data(&dch->dev.D, PH_ACTIVATE_IND,
@@ -3751,7 +3851,7 @@
 	if (debug & DEBUG_HFCMULTI_INIT)
 		printk(KERN_DEBUG "%s: entered\n", __func__);
 
-	if (hc->type == 1) {
+	if (hc->ctype == HFC_TYPE_E1) {
 		hc->chan[hc->dslot].slot_tx = -1;
 		hc->chan[hc->dslot].slot_rx = -1;
 		hc->chan[hc->dslot].conf = -1;
@@ -3900,6 +4000,11 @@
 		}
 		if (!test_bit(HFC_CFG_NONCAP_TX, &hc->chan[i].cfg))
 			hc->hw.a_st_ctrl0[pt] |= V_TX_LI;
+		if (hc->ctype == HFC_TYPE_XHFC) {
+			hc->hw.a_st_ctrl0[pt] |= 0x40 /* V_ST_PU_CTRL */;
+			HFC_outb(hc, 0x35 /* A_ST_CTRL3 */,
+				0x7c << 1 /* V_ST_PULSE */);
+		}
 		/* line setup */
 		HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[pt]);
 		/* disable E-channel */
@@ -3943,12 +4048,12 @@
 		return -EINVAL;
 	if ((dch->dev.D.protocol != ISDN_P_NONE) &&
 	    (dch->dev.D.protocol != rq->protocol)) {
-	    if (debug & DEBUG_HFCMULTI_MODE)
-		printk(KERN_WARNING "%s: change protocol %x to %x\n",
-		    __func__, dch->dev.D.protocol, rq->protocol);
+		if (debug & DEBUG_HFCMULTI_MODE)
+			printk(KERN_DEBUG "%s: change protocol %x to %x\n",
+			    __func__, dch->dev.D.protocol, rq->protocol);
 	}
-	if ((dch->dev.D.protocol == ISDN_P_TE_S0)
-	 && (rq->protocol != ISDN_P_TE_S0))
+	if ((dch->dev.D.protocol == ISDN_P_TE_S0) &&
+	    (rq->protocol != ISDN_P_TE_S0))
 		l1_event(dch->l1, CLOSE_CHANNEL);
 	if (dch->dev.D.protocol != rq->protocol) {
 		if (rq->protocol == ISDN_P_TE_S0) {
@@ -3986,7 +4091,7 @@
 		return -EINVAL;
 	if (rq->protocol == ISDN_P_NONE)
 		return -EINVAL;
-	if (hc->type == 1)
+	if (hc->ctype == HFC_TYPE_E1)
 		ch = rq->adr.channel;
 	else
 		ch = (rq->adr.channel - 1) + (dch->slot - 2);
@@ -4013,11 +4118,41 @@
 static int
 channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
 {
+	struct hfc_multi	*hc = dch->hw;
 	int	ret = 0;
+	int	wd_mode, wd_cnt;
 
 	switch (cq->op) {
 	case MISDN_CTRL_GETOP:
-		cq->op = 0;
+		cq->op = MISDN_CTRL_HFC_OP;
+		break;
+	case MISDN_CTRL_HFC_WD_INIT: /* init the watchdog */
+		wd_cnt = cq->p1 & 0xf;
+		wd_mode = !!(cq->p1 >> 4);
+		if (debug & DEBUG_HFCMULTI_MSG)
+			printk(KERN_DEBUG "%s: MISDN_CTRL_HFC_WD_INIT mode %s"
+			    ", counter 0x%x\n", __func__,
+			    wd_mode ? "AUTO" : "MANUAL", wd_cnt);
+		/* set the watchdog timer */
+		HFC_outb(hc, R_TI_WD, poll_timer | (wd_cnt << 4));
+		hc->hw.r_bert_wd_md = (wd_mode ? V_AUTO_WD_RES : 0);
+		if (hc->ctype == HFC_TYPE_XHFC)
+			hc->hw.r_bert_wd_md |= 0x40 /* V_WD_EN */;
+		/* init the watchdog register and reset the counter */
+		HFC_outb(hc, R_BERT_WD_MD, hc->hw.r_bert_wd_md | V_WD_RES);
+		if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+			/* enable the watchdog output for Speech-Design */
+			HFC_outb(hc, R_GPIO_SEL,  V_GPIO_SEL7);
+			HFC_outb(hc, R_GPIO_EN1,  V_GPIO_EN15);
+			HFC_outb(hc, R_GPIO_OUT1, 0);
+			HFC_outb(hc, R_GPIO_OUT1, V_GPIO_OUT15);
+		}
+		break;
+	case MISDN_CTRL_HFC_WD_RESET: /* reset the watchdog counter */
+		if (debug & DEBUG_HFCMULTI_MSG)
+			printk(KERN_DEBUG "%s: MISDN_CTRL_HFC_WD_RESET\n",
+			    __func__);
+		HFC_outb(hc, R_BERT_WD_MD, hc->hw.r_bert_wd_md | V_WD_RES);
 		break;
 	default:
 		printk(KERN_WARNING "%s: unknown Op %x\n",
@@ -4047,7 +4182,7 @@
 		switch (rq->protocol) {
 		case ISDN_P_TE_S0:
 		case ISDN_P_NT_S0:
-			if (hc->type == 1) {
+			if (hc->ctype == HFC_TYPE_E1) {
 				err = -EINVAL;
 				break;
 			}
@@ -4055,7 +4190,7 @@
 			break;
 		case ISDN_P_TE_E1:
 		case ISDN_P_NT_E1:
-			if (hc->type != 1) {
+			if (hc->ctype != HFC_TYPE_E1) {
 				err = -EINVAL;
 				break;
 			}
@@ -4122,13 +4257,13 @@
 	disable_hwirq(hc);
 	spin_unlock_irqrestore(&hc->lock, flags);
 
-	if (request_irq(hc->pci_dev->irq, hfcmulti_interrupt, IRQF_SHARED,
+	if (request_irq(hc->irq, hfcmulti_interrupt, IRQF_SHARED,
 	    "HFC-multi", hc)) {
 		printk(KERN_WARNING "mISDN: Could not get interrupt %d.\n",
-		    hc->pci_dev->irq);
+		    hc->irq);
+		hc->irq = 0;
 		return -EIO;
 	}
-	hc->irq = hc->pci_dev->irq;
 
 	if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
 		spin_lock_irqsave(&plx_lock, plx_flags);
@@ -4187,7 +4322,7 @@
 	}
 
 	if (debug & DEBUG_HFCMULTI_INIT)
-		printk(KERN_WARNING "%s: free irq %d\n", __func__, hc->irq);
+		printk(KERN_DEBUG "%s: free irq %d\n", __func__, hc->irq);
 	if (hc->irq) {
 		free_irq(hc->irq, hc);
 		hc->irq = 0;
@@ -4235,6 +4370,10 @@
 	hc->ledstate = 0xAFFEAFFE;
 	hc->opticalsupport = m->opticalsupport;
 
+	hc->pci_iobase = 0;
+	hc->pci_membase = NULL;
+	hc->plx_membase = NULL;
+
 	/* set memory access methods */
 	if (m->io_mode) /* use mode from card config */
 		hc->io_mode = m->io_mode;
@@ -4242,44 +4381,12 @@
 	case HFC_IO_MODE_PLXSD:
 		test_and_set_bit(HFC_CHIP_PLXSD, &hc->chip);
 		hc->slots = 128; /* required */
-		/* fall through */
-	case HFC_IO_MODE_PCIMEM:
 		hc->HFC_outb = HFC_outb_pcimem;
 		hc->HFC_inb = HFC_inb_pcimem;
 		hc->HFC_inw = HFC_inw_pcimem;
 		hc->HFC_wait = HFC_wait_pcimem;
 		hc->read_fifo = read_fifo_pcimem;
 		hc->write_fifo = write_fifo_pcimem;
-		break;
-	case HFC_IO_MODE_REGIO:
-		hc->HFC_outb = HFC_outb_regio;
-		hc->HFC_inb = HFC_inb_regio;
-		hc->HFC_inw = HFC_inw_regio;
-		hc->HFC_wait = HFC_wait_regio;
-		hc->read_fifo = read_fifo_regio;
-		hc->write_fifo = write_fifo_regio;
-		break;
-	default:
-		printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n");
-		pci_disable_device(hc->pci_dev);
-		return -EIO;
-	}
-	hc->HFC_outb_nodebug = hc->HFC_outb;
-	hc->HFC_inb_nodebug = hc->HFC_inb;
-	hc->HFC_inw_nodebug = hc->HFC_inw;
-	hc->HFC_wait_nodebug = hc->HFC_wait;
-#ifdef HFC_REGISTER_DEBUG
-	hc->HFC_outb = HFC_outb_debug;
-	hc->HFC_inb = HFC_inb_debug;
-	hc->HFC_inw = HFC_inw_debug;
-	hc->HFC_wait = HFC_wait_debug;
-#endif
-	hc->pci_iobase = 0;
-	hc->pci_membase = NULL;
-	hc->plx_membase = NULL;
-
-	switch (hc->io_mode) {
-	case HFC_IO_MODE_PLXSD:
 		hc->plx_origmembase =  hc->pci_dev->resource[0].start;
 		/* MEMBASE 1 is PLX PCI Bridge */
 
@@ -4327,6 +4434,12 @@
 		pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO);
 		break;
 	case HFC_IO_MODE_PCIMEM:
+		hc->HFC_outb = HFC_outb_pcimem;
+		hc->HFC_inb = HFC_inb_pcimem;
+		hc->HFC_inw = HFC_inw_pcimem;
+		hc->HFC_wait = HFC_wait_pcimem;
+		hc->read_fifo = read_fifo_pcimem;
+		hc->write_fifo = write_fifo_pcimem;
 		hc->pci_origmembase = hc->pci_dev->resource[1].start;
 		if (!hc->pci_origmembase) {
 			printk(KERN_WARNING
@@ -4343,12 +4456,18 @@
 			pci_disable_device(hc->pci_dev);
 			return -EIO;
 		}
-		printk(KERN_INFO "card %d: defined at MEMBASE %#lx (%#lx) IRQ %d "
-		    "HZ %d leds-type %d\n", hc->id, (u_long)hc->pci_membase,
+		printk(KERN_INFO "card %d: defined at MEMBASE %#lx (%#lx) IRQ "
+		    "%d HZ %d leds-type %d\n", hc->id, (u_long)hc->pci_membase,
 		    hc->pci_origmembase, hc->pci_dev->irq, HZ, hc->leds);
 		pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO);
 		break;
 	case HFC_IO_MODE_REGIO:
+		hc->HFC_outb = HFC_outb_regio;
+		hc->HFC_inb = HFC_inb_regio;
+		hc->HFC_inw = HFC_inw_regio;
+		hc->HFC_wait = HFC_wait_regio;
+		hc->read_fifo = read_fifo_regio;
+		hc->write_fifo = write_fifo_regio;
 		hc->pci_iobase = (u_int) hc->pci_dev->resource[0].start;
 		if (!hc->pci_iobase) {
 			printk(KERN_WARNING
@@ -4430,7 +4549,7 @@
 		dch->timer.function = NULL;
 	}
 
-	if (hc->type == 1) { /* E1 */
+	if (hc->ctype == HFC_TYPE_E1) { /* E1 */
 		/* remove sync */
 		if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
 			hc->syncronized = 0;
@@ -4508,7 +4627,7 @@
 	int	ch;
 
 	if (debug & DEBUG_HFCMULTI_INIT)
-		printk(KERN_WARNING "%s: release card (%d) entered\n",
+		printk(KERN_DEBUG "%s: release card (%d) entered\n",
 		    __func__, hc->id);
 
 	/* unregister clock source */
@@ -4537,7 +4656,7 @@
 	/* release hardware & irq */
 	if (hc->irq) {
 		if (debug & DEBUG_HFCMULTI_INIT)
-			printk(KERN_WARNING "%s: free irq %d\n",
+			printk(KERN_DEBUG "%s: free irq %d\n",
 			    __func__, hc->irq);
 		free_irq(hc->irq, hc);
 		hc->irq = 0;
@@ -4546,17 +4665,17 @@
 	release_io_hfcmulti(hc);
 
 	if (debug & DEBUG_HFCMULTI_INIT)
-		printk(KERN_WARNING "%s: remove instance from list\n",
+		printk(KERN_DEBUG "%s: remove instance from list\n",
 		     __func__);
 	list_del(&hc->list);
 
 	if (debug & DEBUG_HFCMULTI_INIT)
-		printk(KERN_WARNING "%s: delete instance\n", __func__);
+		printk(KERN_DEBUG "%s: delete instance\n", __func__);
 	if (hc == syncmaster)
 		syncmaster = NULL;
 	kfree(hc);
 	if (debug & DEBUG_HFCMULTI_INIT)
-		printk(KERN_WARNING "%s: card successfully removed\n",
+		printk(KERN_DEBUG "%s: card successfully removed\n",
 		    __func__);
 }
 
@@ -4579,7 +4698,7 @@
 	    (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
 	dch->dev.D.send = handle_dmsg;
 	dch->dev.D.ctrl = hfcm_dctrl;
-	dch->dev.nrbchan = (hc->dslot)?30:31;
+	dch->dev.nrbchan = (hc->dslot) ? 30 : 31;
 	dch->slot = hc->dslot;
 	hc->chan[hc->dslot].dch = dch;
 	hc->chan[hc->dslot].port = 0;
@@ -4821,7 +4940,7 @@
 	}
 	/* disable E-channel */
 	if (port[Port_cnt] & 0x004) {
-	if (debug & DEBUG_HFCMULTI_INIT)
+		if (debug & DEBUG_HFCMULTI_INIT)
 			printk(KERN_DEBUG
 			    "%s: PROTOCOL disable E-channel: "
 			    "card(%d) port(%d)\n",
@@ -4829,9 +4948,15 @@
 		test_and_set_bit(HFC_CFG_DIS_ECHANNEL,
 		    &hc->chan[i + 2].cfg);
 	}
-	snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d",
-		hc->type, HFC_cnt + 1, pt + 1);
-	ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
+	if (hc->ctype == HFC_TYPE_XHFC) {
+		snprintf(name, MISDN_MAX_IDLEN - 1, "xhfc.%d-%d",
+			HFC_cnt + 1, pt + 1);
+		ret = mISDN_register_device(&dch->dev, NULL, name);
+	} else {
+		snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d",
+			hc->ctype, HFC_cnt + 1, pt + 1);
+		ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
+	}
 	if (ret)
 		goto free_chan;
 	hc->created[pt] = 1;
@@ -4842,9 +4967,9 @@
 }
 
 static int
-hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
+hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
+    const struct pci_device_id *ent)
 {
-	struct hm_map	*m = (struct hm_map *)ent->driver_data;
 	int		ret_err = 0;
 	int		pt;
 	struct hfc_multi	*hc;
@@ -4879,16 +5004,18 @@
 	}
 	spin_lock_init(&hc->lock);
 	hc->mtyp = m;
-	hc->type =  m->type;
+	hc->ctype =  m->type;
 	hc->ports = m->ports;
 	hc->id = HFC_cnt;
 	hc->pcm = pcm[HFC_cnt];
 	hc->io_mode = iomode[HFC_cnt];
-	if (dslot[HFC_cnt] < 0 && hc->type == 1) {
+	if (dslot[HFC_cnt] < 0 && hc->ctype == HFC_TYPE_E1) {
 		hc->dslot = 0;
 		printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
 			"31 B-channels\n");
-	} if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 && hc->type == 1) {
+	}
+	if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32
+	    && hc->ctype == HFC_TYPE_E1) {
 		hc->dslot = dslot[HFC_cnt];
 		printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
 			"time slot %d\n", dslot[HFC_cnt]);
@@ -4910,8 +5037,11 @@
 	for (i = 0; i < (poll >> 1); i++)
 		hc->silence_data[i] = hc->silence;
 
-	if (!(type[HFC_cnt] & 0x200))
-		test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
+	if (hc->ctype != HFC_TYPE_XHFC) {
+		if (!(type[HFC_cnt] & 0x200))
+			test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
+		test_and_set_bit(HFC_CHIP_CONF, &hc->chip);
+	}
 
 	if (type[HFC_cnt] & 0x800)
 		test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip);
@@ -4935,8 +5065,18 @@
 		printk(KERN_NOTICE "Watchdog enabled\n");
 	}
 
-	/* setup pci, hc->slots may change due to PLXSD */
-	ret_err = setup_pci(hc, pdev, ent);
+	if (pdev && ent)
+		/* setup pci, hc->slots may change due to PLXSD */
+		ret_err = setup_pci(hc, pdev, ent);
+	else
+#ifdef CONFIG_MISDN_HFCMULTI_8xx
+		ret_err = setup_embedded(hc, m);
+#else
+	{
+		printk(KERN_WARNING "Embedded IO Mode not selected\n");
+		ret_err = -EIO;
+	}
+#endif
 	if (ret_err) {
 		if (hc == syncmaster)
 			syncmaster = NULL;
@@ -4944,7 +5084,17 @@
 		return ret_err;
 	}
 
-	/* crate channels */
+	hc->HFC_outb_nodebug = hc->HFC_outb;
+	hc->HFC_inb_nodebug = hc->HFC_inb;
+	hc->HFC_inw_nodebug = hc->HFC_inw;
+	hc->HFC_wait_nodebug = hc->HFC_wait;
+#ifdef HFC_REGISTER_DEBUG
+	hc->HFC_outb = HFC_outb_debug;
+	hc->HFC_inb = HFC_inb_debug;
+	hc->HFC_inw = HFC_inw_debug;
+	hc->HFC_wait = HFC_wait_debug;
+#endif
+	/* create channels */
 	for (pt = 0; pt < hc->ports; pt++) {
 		if (Port_cnt >= MAX_PORTS) {
 			printk(KERN_ERR "too many ports (max=%d).\n",
@@ -4952,7 +5102,7 @@
 			ret_err = -EINVAL;
 			goto free_card;
 		}
-		if (hc->type == 1)
+		if (hc->ctype == HFC_TYPE_E1)
 			ret_err = init_e1_port(hc, m);
 		else
 			ret_err = init_multi_port(hc, pt);
@@ -5036,6 +5186,7 @@
 		hc->iclock = mISDN_register_clock("HFCMulti", 0, clockctl, hc);
 
 	/* initialize hardware */
+	hc->irq = (m->irq) ? : hc->pci_dev->irq;
 	ret_err = init_card(hc);
 	if (ret_err) {
 		printk(KERN_ERR "init card returns %d\n", ret_err);
@@ -5074,7 +5225,7 @@
 		spin_unlock_irqrestore(&HFClock, flags);
 	}  else {
 		if (debug)
-			printk(KERN_WARNING "%s: drvdata allready removed\n",
+			printk(KERN_DEBUG "%s: drvdata allready removed\n",
 			    __func__);
 	}
 }
@@ -5086,45 +5237,48 @@
 #define VENDOR_PRIM	"PrimuX"
 
 static const struct hm_map hfcm_map[] = {
-/*0*/	{VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0},
-/*1*/	{VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S, 0},
-/*2*/	{VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0},
-/*3*/	{VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0},
-/*4*/	{VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0},
-/*5*/	{VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0},
-/*6*/	{VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, DIP_4S, 0},
-/*7*/	{VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0},
-/*8*/	{VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO},
-/*9*/	{VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0},
-/*10*/	{VENDOR_JH, "HFC-4S (junghanns 2.0)", 4, 4, 1, 2, 0, 0, 0},
-/*11*/	{VENDOR_PRIM, "HFC-2S Primux Card", 4, 2, 0, 0, 0, 0, 0},
+/*0*/	{VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0, 0},
+/*1*/	{VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S, 0, 0},
+/*2*/	{VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0, 0},
+/*3*/	{VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0, 0},
+/*4*/	{VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0, 0},
+/*5*/	{VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0, 0},
+/*6*/	{VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, DIP_4S, 0, 0},
+/*7*/	{VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0, 0},
+/*8*/	{VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO, 0},
+/*9*/	{VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0, 0},
+/*10*/	{VENDOR_JH, "HFC-4S (junghanns 2.0)", 4, 4, 1, 2, 0, 0, 0, 0},
+/*11*/	{VENDOR_PRIM, "HFC-2S Primux Card", 4, 2, 0, 0, 0, 0, 0, 0},
 
-/*12*/	{VENDOR_BN, "HFC-8S Card", 8, 8, 1, 0, 0, 0, 0},
+/*12*/	{VENDOR_BN, "HFC-8S Card", 8, 8, 1, 0, 0, 0, 0, 0},
 /*13*/	{VENDOR_BN, "HFC-8S Card (+)", 8, 8, 1, 8, 0, DIP_8S,
-		HFC_IO_MODE_REGIO},
-/*14*/	{VENDOR_CCD, "HFC-8S Eval (old)", 8, 8, 0, 0, 0, 0, 0},
-/*15*/	{VENDOR_CCD, "HFC-8S IOB4ST Recording", 8, 8, 1, 0, 0, 0, 0},
+		HFC_IO_MODE_REGIO, 0},
+/*14*/	{VENDOR_CCD, "HFC-8S Eval (old)", 8, 8, 0, 0, 0, 0, 0, 0},
+/*15*/	{VENDOR_CCD, "HFC-8S IOB4ST Recording", 8, 8, 1, 0, 0, 0, 0, 0},
 
-/*16*/	{VENDOR_CCD, "HFC-8S IOB8ST", 8, 8, 1, 0, 0, 0, 0},
-/*17*/	{VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0},
-/*18*/	{VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0},
+/*16*/	{VENDOR_CCD, "HFC-8S IOB8ST", 8, 8, 1, 0, 0, 0, 0, 0},
+/*17*/	{VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0, 0},
+/*18*/	{VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0, 0},
 
-/*19*/	{VENDOR_BN, "HFC-E1 Card", 1, 1, 0, 1, 0, DIP_E1, 0},
-/*20*/	{VENDOR_BN, "HFC-E1 Card (mini PCI)", 1, 1, 0, 1, 0, 0, 0},
-/*21*/	{VENDOR_BN, "HFC-E1+ Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0},
-/*22*/	{VENDOR_BN, "HFC-E1 Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0},
+/*19*/	{VENDOR_BN, "HFC-E1 Card", 1, 1, 0, 1, 0, DIP_E1, 0, 0},
+/*20*/	{VENDOR_BN, "HFC-E1 Card (mini PCI)", 1, 1, 0, 1, 0, 0, 0, 0},
+/*21*/	{VENDOR_BN, "HFC-E1+ Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0, 0},
+/*22*/	{VENDOR_BN, "HFC-E1 Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0, 0},
 
-/*23*/	{VENDOR_CCD, "HFC-E1 Eval (old)", 1, 1, 0, 0, 0, 0, 0},
-/*24*/	{VENDOR_CCD, "HFC-E1 IOB1E1", 1, 1, 0, 1, 0, 0, 0},
-/*25*/	{VENDOR_CCD, "HFC-E1", 1, 1, 0, 1, 0, 0, 0},
+/*23*/	{VENDOR_CCD, "HFC-E1 Eval (old)", 1, 1, 0, 0, 0, 0, 0, 0},
+/*24*/	{VENDOR_CCD, "HFC-E1 IOB1E1", 1, 1, 0, 1, 0, 0, 0, 0},
+/*25*/	{VENDOR_CCD, "HFC-E1", 1, 1, 0, 1, 0, 0, 0, 0},
 
 /*26*/	{VENDOR_CCD, "HFC-4S Speech Design", 4, 4, 0, 0, 0, 0,
-		HFC_IO_MODE_PLXSD},
+		HFC_IO_MODE_PLXSD, 0},
 /*27*/	{VENDOR_CCD, "HFC-E1 Speech Design", 1, 1, 0, 0, 0, 0,
-		HFC_IO_MODE_PLXSD},
-/*28*/	{VENDOR_CCD, "HFC-4S OpenVox", 4, 4, 1, 0, 0, 0, 0},
-/*29*/	{VENDOR_CCD, "HFC-2S OpenVox", 4, 2, 1, 0, 0, 0, 0},
-/*30*/	{VENDOR_CCD, "HFC-8S OpenVox", 8, 8, 1, 0, 0, 0, 0},
+		HFC_IO_MODE_PLXSD, 0},
+/*28*/	{VENDOR_CCD, "HFC-4S OpenVox", 4, 4, 1, 0, 0, 0, 0, 0},
+/*29*/	{VENDOR_CCD, "HFC-2S OpenVox", 4, 2, 1, 0, 0, 0, 0, 0},
+/*30*/	{VENDOR_CCD, "HFC-8S OpenVox", 8, 8, 1, 0, 0, 0, 0, 0},
+/*31*/	{VENDOR_CCD, "XHFC-4S Speech Design", 5, 4, 0, 0, 0, 0,
+		HFC_IO_MODE_EMBSD, XHFC_IRQ},
+/*32*/	{VENDOR_JH, "HFC-8S (junghanns)", 8, 8, 1, 0, 0, 0, 0, 0},
 };
 
 #undef H
@@ -5178,6 +5332,8 @@
 		PCI_SUBDEVICE_ID_CCD_HFC8S, 0, 0, H(18)}, /* 8S */
 	{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
 		PCI_SUBDEVICE_ID_CCD_OV8S, 0, 0, H(30)}, /* OpenVox 8 */
+	{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
+		PCI_SUBDEVICE_ID_CCD_JH8S, 0, 0, H(32)}, /* Junganns 8S  */
 
 
 	/* Cards with HFC-E1 Chip */
@@ -5201,6 +5357,10 @@
 		PCI_SUBDEVICE_ID_CCD_SPD4S, 0, 0, H(26)}, /* PLX PCI Bridge */
 	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_CCD,
 		PCI_SUBDEVICE_ID_CCD_SPDE1, 0, 0, H(27)}, /* PLX PCI Bridge */
+
+	{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
+		PCI_SUBDEVICE_ID_CCD_JHSE1, 0, 0, H(25)}, /* Junghanns E1 */
+
 	{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_ANY_ID, PCI_ANY_ID,
 		0, 0, 0},
 	{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_ANY_ID, PCI_ANY_ID,
@@ -5231,7 +5391,7 @@
 		    "Please contact the driver maintainer for support.\n");
 		return -ENODEV;
 	}
-	ret = hfcmulti_init(pdev, ent);
+	ret = hfcmulti_init(m, pdev, ent);
 	if (ret)
 		return ret;
 	HFC_cnt++;
@@ -5261,6 +5421,8 @@
 HFCmulti_init(void)
 {
 	int err;
+	int i, xhfc = 0;
+	struct hm_map m;
 
 	printk(KERN_INFO "mISDN: HFC-multi driver %s\n", HFC_MULTI_VERSION);
 
@@ -5308,11 +5470,43 @@
 	if (!clock)
 		clock = 1;
 
+	/* Register the embedded devices.
+	 * This should be done before the PCI cards registration */
+	switch (hwid) {
+	case HWID_MINIP4:
+		xhfc = 1;
+		m = hfcm_map[31];
+		break;
+	case HWID_MINIP8:
+		xhfc = 2;
+		m = hfcm_map[31];
+		break;
+	case HWID_MINIP16:
+		xhfc = 4;
+		m = hfcm_map[31];
+		break;
+	default:
+		xhfc = 0;
+	}
+
+	for (i = 0; i < xhfc; ++i) {
+		err = hfcmulti_init(&m, NULL, NULL);
+		if (err) {
+			printk(KERN_ERR "error registering embedded driver: "
+				"%x\n", err);
+			return -err;
+		}
+		HFC_cnt++;
+		printk(KERN_INFO "%d devices registered\n", HFC_cnt);
+	}
+
+	/* Register the PCI cards */
 	err = pci_register_driver(&hfcmultipci_driver);
 	if (err < 0) {
 		printk(KERN_ERR "error registering pci driver: %x\n", err);
 		return err;
 	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfc_multi.h linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfc_multi.h
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfc_multi.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfc_multi.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,16 @@
 #define	PCI_ENA_REGIO	0x01
 #define	PCI_ENA_MEMIO	0x02
 
+#define XHFC_IRQ	4		/* SIU_IRQ2 */
+#define XHFC_MEMBASE	0xFE000000
+#define XHFC_MEMSIZE    0x00001000
+#define XHFC_OFFSET	0x00001000
+#define PA_XHFC_A0	0x0020		/* PA10 */
+#define PB_XHFC_IRQ1	0x00000100	/* PB23 */
+#define PB_XHFC_IRQ2	0x00000200	/* PB22 */
+#define PB_XHFC_IRQ3	0x00000400	/* PB21 */
+#define PB_XHFC_IRQ4	0x00000800	/* PB20 */
+
 /*
  * NOTE: some registers are assigned multiple times due to different modes
  *       also registers are assigned differen for HFC-4s/8s and HFC-E1
@@ -44,6 +54,7 @@
 	int		conf;	/* conference setting of TX slot */
 	int		txpending;	/* if there is currently data in */
 					/* the FIFO 0=no, 1=yes, 2=splloop */
+	int		Zfill;	/* rx-fifo level on last hfcmulti_tx */
 	int		rx_off; /* set to turn fifo receive off */
 	int		coeff_count; /* curren coeff block */
 	s32		*coeff; /* memory pointer to 8 coeff blocks */
@@ -62,6 +73,7 @@
 	u_char	r_sci_msk;
 	u_char	r_tx0, r_tx1;
 	u_char	a_st_ctrl0[8];
+	u_char	r_bert_wd_md;
 	timer_t	timer;
 };
 
@@ -79,6 +91,11 @@
 #define	HFC_CFG_CRC4		10 /* disable CRC-4 Multiframe mode, */
 					/* use double frame instead. */
 
+#define HFC_TYPE_E1		1 /* controller is HFC-E1 */
+#define HFC_TYPE_4S		4 /* controller is HFC-4S */
+#define HFC_TYPE_8S		8 /* controller is HFC-8S */
+#define HFC_TYPE_XHFC		5 /* controller is XHFC */
+
 #define	HFC_CHIP_EXRAM_128	0 /* external ram 128k */
 #define	HFC_CHIP_EXRAM_512	1 /* external ram 256k */
 #define	HFC_CHIP_REVISION0	2 /* old fifo handling */
@@ -86,19 +103,22 @@
 #define	HFC_CHIP_PCM_MASTER	4 /* PCM is master */
 #define	HFC_CHIP_RX_SYNC	5 /* disable pll sync for pcm */
 #define	HFC_CHIP_DTMF		6 /* DTMF decoding is enabled */
-#define	HFC_CHIP_ULAW		7 /* ULAW mode */
-#define	HFC_CHIP_CLOCK2		8 /* double clock mode */
-#define	HFC_CHIP_E1CLOCK_GET	9 /* always get clock from E1 interface */
-#define	HFC_CHIP_E1CLOCK_PUT	10 /* always put clock from E1 interface */
-#define	HFC_CHIP_WATCHDOG	11 /* whether we should send signals */
+#define	HFC_CHIP_CONF		7 /* conference handling is enabled */
+#define	HFC_CHIP_ULAW		8 /* ULAW mode */
+#define	HFC_CHIP_CLOCK2		9 /* double clock mode */
+#define	HFC_CHIP_E1CLOCK_GET	10 /* always get clock from E1 interface */
+#define	HFC_CHIP_E1CLOCK_PUT	11 /* always put clock from E1 interface */
+#define	HFC_CHIP_WATCHDOG	12 /* whether we should send signals */
 					/* to the watchdog */
-#define	HFC_CHIP_B410P		12 /* whether we have a b410p with echocan in */
+#define	HFC_CHIP_B410P		13 /* whether we have a b410p with echocan in */
 					/* hw */
-#define	HFC_CHIP_PLXSD		13 /* whether we have a Speech-Design PLX */
+#define	HFC_CHIP_PLXSD		14 /* whether we have a Speech-Design PLX */
+#define	HFC_CHIP_EMBSD          15 /* whether we have a SD Embedded board */
 
 #define HFC_IO_MODE_PCIMEM	0x00 /* normal memory mapped IO */
 #define HFC_IO_MODE_REGIO	0x01 /* PCI io access */
 #define HFC_IO_MODE_PLXSD	0x02 /* access HFC via PLX9030 */
+#define HFC_IO_MODE_EMBSD	0x03 /* direct access */
 
 /* table entry in the PCI devices list */
 struct hm_map {
@@ -111,6 +131,7 @@
 	int opticalsupport;
 	int dip_type;
 	int io_mode;
+	int irq;
 };
 
 struct hfc_multi {
@@ -118,7 +139,7 @@
 	struct hm_map	*mtyp;
 	int		id;
 	int		pcm;	/* id of pcm bus */
-	int		type;
+	int		ctype;	/* controller type */
 	int		ports;
 
 	u_int		irq;	/* irq used by card */
@@ -158,10 +179,16 @@
 				int len);
 	void		(*write_fifo)(struct hfc_multi *hc, u_char *data,
 				int len);
-	u_long		pci_origmembase, plx_origmembase, dsp_origmembase;
+	u_long		pci_origmembase, plx_origmembase;
 	void __iomem	*pci_membase; /* PCI memory */
 	void __iomem	*plx_membase; /* PLX memory */
-	u_char		*dsp_membase; /* DSP on PLX */
+	u_long		xhfc_origmembase;
+	u_char		*xhfc_membase;
+	u_long		*xhfc_memaddr, *xhfc_memdata;
+#ifdef CONFIG_MISDN_HFCMULTI_8xx
+	struct immap	*immap;
+#endif
+	u_long		pb_irqmsk;	/* Portbit mask to check the IRQ line */
 	u_long		pci_iobase; /* PCI IO */
 	struct hfcm_hw	hw;	/* remember data of write-only-registers */
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfcpci.c linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfcpci.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfcpci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfcpci.c	2009-09-09 18:13:59.000000000 -0400
@@ -257,7 +257,7 @@
 	Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
 
 	/* Clear already pending ints */
-	if (Read_hfc(hc, HFCPCI_INT_S1));
+	val = Read_hfc(hc, HFCPCI_INT_S1);
 
 	/* set NT/TE mode */
 	hfcpci_setmode(hc);
@@ -452,7 +452,7 @@
 		}
 		bz->za[new_f2].z2 = cpu_to_le16(new_z2);
 		bz->f2 = new_f2;	/* next buffer */
-		recv_Bchannel(bch);
+		recv_Bchannel(bch, MISDN_ID_ANY);
 	}
 }
 
@@ -499,7 +499,8 @@
 			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) |
 			    (MAX_D_FRAMES + 1);	/* next buffer */
 			df->za[df->f2 & D_FREG_MASK].z2 =
-			    cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & (D_FIFO_SIZE - 1));
+			    cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) &
+			    (D_FIFO_SIZE - 1));
 		} else {
 			dch->rx_skb = mI_alloc_skb(rcnt - 3, GFP_ATOMIC);
 			if (!dch->rx_skb) {
@@ -541,35 +542,45 @@
  * check for transparent receive data and read max one 'poll' size if avail
  */
 static void
-hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
+hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
+	struct bzfifo *txbz, u_char *bdata)
 {
-	 __le16 *z1r, *z2r;
-	int		new_z2, fcnt, maxlen;
-	u_char		*ptr, *ptr1;
+	 __le16	*z1r, *z2r, *z1t, *z2t;
+	int	new_z2, fcnt_rx, fcnt_tx, maxlen;
+	u_char	*ptr, *ptr1;
 
-	z1r = &bz->za[MAX_B_FRAMES].z1;		/* pointer to z reg */
+	z1r = &rxbz->za[MAX_B_FRAMES].z1;	/* pointer to z reg */
 	z2r = z1r + 1;
+	z1t = &txbz->za[MAX_B_FRAMES].z1;
+	z2t = z1t + 1;
 
-	fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
-	if (!fcnt)
+	fcnt_rx = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
+	if (!fcnt_rx)
 		return;	/* no data avail */
 
-	if (fcnt <= 0)
-		fcnt += B_FIFO_SIZE;	/* bytes actually buffered */
-	new_z2 = le16_to_cpu(*z2r) + fcnt;	/* new position in fifo */
+	if (fcnt_rx <= 0)
+		fcnt_rx += B_FIFO_SIZE;	/* bytes actually buffered */
+	new_z2 = le16_to_cpu(*z2r) + fcnt_rx;	/* new position in fifo */
 	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
 		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
 
-	if (fcnt > MAX_DATA_SIZE) {	/* flush, if oversized */
+	if (fcnt_rx > MAX_DATA_SIZE) {	/* flush, if oversized */
 		*z2r = cpu_to_le16(new_z2);		/* new position */
 		return;
 	}
 
-	bch->rx_skb = mI_alloc_skb(fcnt, GFP_ATOMIC);
+	fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
+	if (fcnt_tx <= 0)
+		fcnt_tx += B_FIFO_SIZE;
+		    /* fcnt_tx contains available bytes in tx-fifo */
+	fcnt_tx = B_FIFO_SIZE - fcnt_tx;
+		    /* remaining bytes to send (bytes in tx-fifo) */
+
+	bch->rx_skb = mI_alloc_skb(fcnt_rx, GFP_ATOMIC);
 	if (bch->rx_skb) {
-		ptr = skb_put(bch->rx_skb, fcnt);
-		if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
-			maxlen = fcnt;	/* complete transfer */
+		ptr = skb_put(bch->rx_skb, fcnt_rx);
+		if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL)
+			maxlen = fcnt_rx;	/* complete transfer */
 		else
 			maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r);
 			    /* maximum */
@@ -577,14 +588,14 @@
 		ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL);
 		    /* start of data */
 		memcpy(ptr, ptr1, maxlen);	/* copy data */
-		fcnt -= maxlen;
+		fcnt_rx -= maxlen;
 
-		if (fcnt) {	/* rest remaining */
+		if (fcnt_rx) {	/* rest remaining */
 			ptr += maxlen;
 			ptr1 = bdata;	/* start of buffer */
-			memcpy(ptr, ptr1, fcnt);	/* rest */
+			memcpy(ptr, ptr1, fcnt_rx);	/* rest */
 		}
-		recv_Bchannel(bch);
+		recv_Bchannel(bch, fcnt_tx); /* bch, id */
 	} else
 		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
 
@@ -600,26 +611,28 @@
 	struct hfc_pci	*hc = bch->hw;
 	int		rcnt, real_fifo;
 	int		receive = 0, count = 5;
-	struct bzfifo	*bz;
+	struct bzfifo	*txbz, *rxbz;
 	u_char		*bdata;
 	struct zt	*zp;
 
 	if ((bch->nr & 2) && (!hc->hw.bswapped)) {
-		bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
+		rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
+		txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2;
 		bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2;
 		real_fifo = 1;
 	} else {
-		bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1;
+		rxbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b1;
+		txbz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b1;
 		bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b1;
 		real_fifo = 0;
 	}
 Begin:
 	count--;
-	if (bz->f1 != bz->f2) {
+	if (rxbz->f1 != rxbz->f2) {
 		if (bch->debug & DEBUG_HW_BCHANNEL)
 			printk(KERN_DEBUG "hfcpci rec ch(%x) f1(%d) f2(%d)\n",
-			    bch->nr, bz->f1, bz->f2);
-		zp = &bz->za[bz->f2];
+			    bch->nr, rxbz->f1, rxbz->f2);
+		zp = &rxbz->za[rxbz->f2];
 
 		rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
 		if (rcnt < 0)
@@ -630,8 +643,8 @@
 			    "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)\n",
 			    bch->nr, le16_to_cpu(zp->z1),
 			    le16_to_cpu(zp->z2), rcnt);
-		hfcpci_empty_bfifo(bch, bz, bdata, rcnt);
-		rcnt = bz->f1 - bz->f2;
+		hfcpci_empty_bfifo(bch, rxbz, bdata, rcnt);
+		rcnt = rxbz->f1 - rxbz->f2;
 		if (rcnt < 0)
 			rcnt += MAX_B_FRAMES + 1;
 		if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) {
@@ -644,7 +657,7 @@
 		else
 			receive = 0;
 	} else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
-		hfcpci_empty_fifo_trans(bch, bz, bdata);
+		hfcpci_empty_fifo_trans(bch, rxbz, txbz, bdata);
 		return;
 	} else
 		receive = 0;
@@ -954,6 +967,7 @@
 ph_state_nt(struct dchannel *dch)
 {
 	struct hfc_pci	*hc = dch->hw;
+	u_char	val;
 
 	if (dch->debug)
 		printk(KERN_DEBUG "%s: NT newstate %x\n",
@@ -967,7 +981,7 @@
 			hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
 			Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
 			/* Clear already pending ints */
-			if (Read_hfc(hc, HFCPCI_INT_S1));
+			val = Read_hfc(hc, HFCPCI_INT_S1);
 			Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
 			udelay(10);
 			Write_hfc(hc, HFCPCI_STATES, 4);
@@ -1256,8 +1270,7 @@
 		rx_slot = (bc>>8) & 0xff;
 		tx_slot = (bc>>16) & 0xff;
 		bc = bc & 0xff;
-	} else if (test_bit(HFC_CFG_PCM, &hc->cfg) &&
-	    (protocol > ISDN_P_NONE))
+	} else if (test_bit(HFC_CFG_PCM, &hc->cfg) && (protocol > ISDN_P_NONE))
 		printk(KERN_WARNING "%s: no pcm channel id but HFC_CFG_PCM\n",
 		    __func__);
 	if (hc->chanlimit > 1) {
@@ -1315,8 +1328,8 @@
 	case (ISDN_P_B_RAW):
 		bch->state = protocol;
 		bch->nr = bc;
-		hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0);
-		hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0);
+		hfcpci_clear_fifo_rx(hc, (fifo2 & 2) ? 1 : 0);
+		hfcpci_clear_fifo_tx(hc, (fifo2 & 2) ? 1 : 0);
 		if (bc & 2) {
 			hc->hw.sctrl |= SCTRL_B2_ENA;
 			hc->hw.sctrl_r |= SCTRL_B2_ENA;
@@ -1350,8 +1363,8 @@
 	case (ISDN_P_B_HDLC):
 		bch->state = protocol;
 		bch->nr = bc;
-		hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0);
-		hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0);
+		hfcpci_clear_fifo_rx(hc, (fifo2 & 2) ? 1 : 0);
+		hfcpci_clear_fifo_tx(hc, (fifo2 & 2) ? 1 : 0);
 		if (bc & 2) {
 			hc->hw.sctrl |= SCTRL_B2_ENA;
 			hc->hw.sctrl_r |= SCTRL_B2_ENA;
@@ -1445,7 +1458,7 @@
 	switch (protocol) {
 	case (ISDN_P_B_RAW):
 		bch->state = protocol;
-		hfcpci_clear_fifo_rx(hc, (chan & 2)?1:0);
+		hfcpci_clear_fifo_rx(hc, (chan & 2) ? 1 : 0);
 		if (chan & 2) {
 			hc->hw.sctrl_r |= SCTRL_B2_ENA;
 			hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
@@ -1470,7 +1483,7 @@
 		break;
 	case (ISDN_P_B_HDLC):
 		bch->state = protocol;
-		hfcpci_clear_fifo_rx(hc, (chan & 2)?1:0);
+		hfcpci_clear_fifo_rx(hc, (chan & 2) ? 1 : 0);
 		if (chan & 2) {
 			hc->hw.sctrl_r |= SCTRL_B2_ENA;
 			hc->hw.last_bfifo_cnt[1] = 0;
@@ -1793,10 +1806,9 @@
 			printk(KERN_WARNING
 			    "HFC PCI: IRQ(%d) getting no interrupts "
 			    "during init %d\n", hc->irq, 4 - cnt);
-			if (cnt == 1) {
-				spin_unlock_irqrestore(&hc->lock, flags);
-				return -EIO;
-			} else {
+			if (cnt == 1)
+				break;
+			else {
 				reset_hfcpci(hc);
 				cnt--;
 			}
@@ -2035,7 +2047,8 @@
 		printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
 		return 1;
 	}
-	hc->hw.pci_io = (char __iomem *)(unsigned long)hc->pdev->resource[1].start;
+	hc->hw.pci_io =
+		(char __iomem *)(unsigned long)hc->pdev->resource[1].start;
 
 	if (!hc->hw.pci_io) {
 		printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
@@ -2277,7 +2290,7 @@
 		release_card(card);
 	else
 		if (debug)
-			printk(KERN_WARNING "%s: drvdata already removed\n",
+			printk(KERN_DEBUG "%s: drvdata already removed\n",
 			    __func__);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfcsusb.c linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfcsusb.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/hfcsusb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/hfcsusb.c	2009-09-09 18:13:59.000000000 -0400
@@ -947,7 +947,7 @@
 				if (fifo->dch)
 					recv_Dchannel(fifo->dch);
 				if (fifo->bch)
-					recv_Bchannel(fifo->bch);
+					recv_Bchannel(fifo->bch, MISDN_ID_ANY);
 				if (fifo->ech)
 					recv_Echannel(fifo->ech,
 						     &hw->dch);
@@ -969,7 +969,7 @@
 	} else {
 		/* deliver transparent data to layer2 */
 		if (rx_skb->len >= poll)
-			recv_Bchannel(fifo->bch);
+			recv_Bchannel(fifo->bch, MISDN_ID_ANY);
 	}
 	spin_unlock(&hw->lock);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/Kconfig linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/Kconfig
--- linux-libre-2.6.30-gnu/drivers/isdn/hardware/mISDN/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hardware/mISDN/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,7 @@
 
 config MISDN_HFCMULTI
 	tristate "Support for HFC multiport cards (HFC-4S/8S/E1)"
-	depends on PCI
+	depends on PCI || 8xx
 	depends on MISDN
 	help
 	  Enable support for cards with Cologne Chip AG's HFC multiport
@@ -23,6 +23,15 @@
 	   * HFC-8S (8 S/T interfaces on one chip)
 	   * HFC-E1 (E1 interface for 2Mbit ISDN)
 
+config MISDN_HFCMULTI_8xx
+	boolean "Support for XHFC embedded board in HFC multiport driver"
+	depends on MISDN
+	depends on MISDN_HFCMULTI
+	depends on 8xx
+	default 8xx
+	help
+	  Enable support for the XHFC embedded solution from Speech Design.
+
 config MISDN_HFCUSB
 	tristate "Support for HFC-S USB based TAs"
 	depends on USB
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hisax/hfc_pci.c linux-libre-2.6.31-gnu/drivers/isdn/hisax/hfc_pci.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hisax/hfc_pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hisax/hfc_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -82,8 +82,9 @@
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
 	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0);	/* disable memory mapped ports + busmaster */
 	del_timer(&cs->hw.hfcpci.timer);
-	kfree(cs->hw.hfcpci.share_start);
-	cs->hw.hfcpci.share_start = NULL;
+	pci_free_consistent(cs->hw.hfcpci.dev, 0x8000,
+		cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma);
+	cs->hw.hfcpci.fifos = NULL;
 	iounmap((void *)cs->hw.hfcpci.pci_io);
 }
 
@@ -1663,8 +1664,19 @@
 					     dev_hfcpci);
 		i++;
 		if (tmp_hfcpci) {
+			dma_addr_t	dma_mask = DMA_BIT_MASK(32) & ~0x7fffUL;
 			if (pci_enable_device(tmp_hfcpci))
 				continue;
+			if (pci_set_dma_mask(tmp_hfcpci, dma_mask)) {
+				printk(KERN_WARNING
+					"HiSax hfc_pci: No suitable DMA available.\n");
+				continue;
+			}
+			if (pci_set_consistent_dma_mask(tmp_hfcpci, dma_mask)) {
+				printk(KERN_WARNING
+					"HiSax hfc_pci: No suitable consistent DMA available.\n");
+				continue;
+			}
 			pci_set_master(tmp_hfcpci);
 			if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
 				continue;
@@ -1693,22 +1705,29 @@
 		printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
 		return (0);
 	}
+
 	/* Allocate memory for FIFOS */
-	/* Because the HFC-PCI needs a 32K physical alignment, we */
-	/* need to allocate the double mem and align the address */
-	if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
-		printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+	cs->hw.hfcpci.fifos = pci_alloc_consistent(cs->hw.hfcpci.dev,
+					0x8000, &cs->hw.hfcpci.dma);
+	if (!cs->hw.hfcpci.fifos) {
+		printk(KERN_WARNING "HFC-PCI: Error allocating FIFO memory!\n");
 		return 0;
 	}
-	cs->hw.hfcpci.fifos = (void *)
-	    (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
-	pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+	if (cs->hw.hfcpci.dma & 0x7fff) {
+		printk(KERN_WARNING
+		    "HFC-PCI: Error DMA memory not on 32K boundary (%lx)\n",
+		    (u_long)cs->hw.hfcpci.dma);
+		pci_free_consistent(cs->hw.hfcpci.dev, 0x8000,
+			cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma);
+		return 0;
+	}
+	pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u32)cs->hw.hfcpci.dma);
 	cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
 	printk(KERN_INFO
-	       "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n",
+	       "HFC-PCI: defined at mem %p fifo %p(%lx) IRQ %d HZ %d\n",
 	       cs->hw.hfcpci.pci_io,
 	       cs->hw.hfcpci.fifos,
-	       (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
+	       (u_long)cs->hw.hfcpci.dma,
 	       cs->irq, HZ);
 
 	spin_lock_irqsave(&cs->lock, flags);
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hisax/hfc_usb.c linux-libre-2.6.31-gnu/drivers/isdn/hisax/hfc_usb.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hisax/hfc_usb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hisax/hfc_usb.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,7 +37,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/usb.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/moduleparam.h>
 #include "hisax.h"
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hisax/hisax.h linux-libre-2.6.31-gnu/drivers/isdn/hisax/hisax.h
--- linux-libre-2.6.30-gnu/drivers/isdn/hisax/hisax.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hisax/hisax.h	2009-09-09 18:13:59.000000000 -0400
@@ -703,7 +703,7 @@
         int nt_timer;
         struct pci_dev *dev;
         unsigned char *pci_io; /* start of PCI IO memory */
-        void *share_start; /* shared memory for Fifos start */
+	dma_addr_t dma; /* dma handle for Fifos */
         void *fifos; /* FIFO memory */ 
         int last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */
 	struct timer_list timer;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/hysdn/hycapi.c linux-libre-2.6.31-gnu/drivers/isdn/hysdn/hycapi.c
--- linux-libre-2.6.30-gnu/drivers/isdn/hysdn/hycapi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/hysdn/hycapi.c	2009-09-09 18:13:59.000000000 -0400
@@ -67,7 +67,7 @@
 	printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n");
 #endif
 	capilib_release(&cinfo->ncci_head);
-	capi_ctr_reseted(ctrl);
+	capi_ctr_down(ctrl);
 }
 
 /******************************
@@ -347,7 +347,7 @@
 	if(cinfo) {
 		ctrl = &cinfo->capi_ctrl;
 /*		ctrl->suspend_output(ctrl); */
-		capi_ctr_reseted(ctrl);
+		capi_ctr_down(ctrl);
 	}
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/i4l/isdn_net.c linux-libre-2.6.31-gnu/drivers/isdn/i4l/isdn_net.c
--- linux-libre-2.6.30-gnu/drivers/isdn/i4l/isdn_net.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/i4l/isdn_net.c	2009-09-09 18:13:59.000000000 -0400
@@ -1069,7 +1069,7 @@
 	lp = isdn_net_get_locked_lp(nd);
 	if (!lp) {
 		printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	/* we have our lp locked from now on */
 
@@ -1273,14 +1273,14 @@
 					spin_unlock_irqrestore(&dev->lock, flags);
 					isdn_net_dial();	/* Initiate dialing */
 					netif_stop_queue(ndev);
-					return 1;	/* let upper layer requeue skb packet */
+					return NETDEV_TX_BUSY;	/* let upper layer requeue skb packet */
 				}
 #endif
 				/* Initiate dialing */
 				spin_unlock_irqrestore(&dev->lock, flags);
 				isdn_net_dial();
 				isdn_net_device_stop_queue(lp);
-				return 1;
+				return NETDEV_TX_BUSY;
 			} else {
 				isdn_net_unreachable(ndev, skb,
 						     "No phone number");
@@ -1300,7 +1300,7 @@
 				netif_stop_queue(ndev);
 		}
 	}
-	return 1;
+	return NETDEV_TX_BUSY;
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/i4l/isdn_tty.c linux-libre-2.6.31-gnu/drivers/isdn/i4l/isdn_tty.c
--- linux-libre-2.6.30-gnu/drivers/isdn/i4l/isdn_tty.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/i4l/isdn_tty.c	2009-09-09 18:13:59.000000000 -0400
@@ -13,6 +13,7 @@
 
 #include <linux/isdn.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include "isdn_common.h"
 #include "isdn_tty.h"
 #ifdef CONFIG_ISDN_AUDIO
@@ -1592,7 +1593,7 @@
 	int retval, line;
 
 	line = tty->index;
-	if (line < 0 || line > ISDN_MAX_CHANNELS)
+	if (line < 0 || line >= ISDN_MAX_CHANNELS)
 		return -ENODEV;
 	info = &dev->mdm.info[line];
 	if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/i4l/Kconfig linux-libre-2.6.31-gnu/drivers/isdn/i4l/Kconfig
--- linux-libre-2.6.30-gnu/drivers/isdn/i4l/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/i4l/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -135,5 +135,3 @@
 source "drivers/isdn/hysdn/Kconfig"
 
 endmenu
-
-source "drivers/isdn/gigaset/Kconfig"
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/Kconfig linux-libre-2.6.31-gnu/drivers/isdn/Kconfig
--- linux-libre-2.6.30-gnu/drivers/isdn/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -61,4 +61,6 @@
 
 endif # ISDN_CAPI
 
+source "drivers/isdn/gigaset/Kconfig"
+
 endif # ISDN
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/core.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/core.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -214,7 +214,7 @@
 		if (!test_and_set_bit(i, (u_long *)&device_ids))
 			break;
 	if (i > MAX_DEVICE_ID)
-		return -1;
+		return -EBUSY;
 	return i;
 }
 
@@ -224,10 +224,10 @@
 {
 	int	err;
 
-	dev->id = get_free_devid();
-	err = -EBUSY;
-	if (dev->id < 0)
+	err = get_free_devid();
+	if (err < 0)
 		goto error1;
+	dev->id = err;
 
 	device_initialize(&dev->dev);
 	if (name && name[0])
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_audio.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_audio.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_audio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_audio.c	2009-09-09 18:13:59.000000000 -0400
@@ -210,9 +210,8 @@
 		j = 0;
 		for (k = 0; k < 256; k++) {
 			if (dsp_audio_alaw_to_s32[k]
-				< dsp_audio_alaw_to_s32[i]) {
-			j++;
-			}
+			    < dsp_audio_alaw_to_s32[i])
+				j++;
 		}
 		sorted_alaw[j] = i;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_cmx.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_cmx.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_cmx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_cmx.c	2009-09-09 18:13:59.000000000 -0400
@@ -163,8 +163,9 @@
 
 	printk(KERN_DEBUG "-----Current DSP\n");
 	list_for_each_entry(odsp, &dsp_ilist, list) {
-		printk(KERN_DEBUG "* %s echo=%d txmix=%d",
-		    odsp->name, odsp->echo, odsp->tx_mix);
+		printk(KERN_DEBUG "* %s hardecho=%d softecho=%d txmix=%d",
+		    odsp->name, odsp->echo.hardware, odsp->echo.software,
+		    odsp->tx_mix);
 		if (odsp->conf)
 			printk(" (Conf %d)", odsp->conf->id);
 		if (dsp == odsp)
@@ -177,10 +178,12 @@
 		list_for_each_entry(member, &conf->mlist, list) {
 			printk(KERN_DEBUG
 			    "  - member = %s (slot_tx %d, bank_tx %d, "
-			    "slot_rx %d, bank_rx %d hfc_conf %d)%s\n",
+			    "slot_rx %d, bank_rx %d hfc_conf %d "
+			    "tx_data %d rx_is_off %d)%s\n",
 			    member->dsp->name, member->dsp->pcm_slot_tx,
 			    member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
 			    member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
+			    member->dsp->tx_data, member->dsp->rx_is_off,
 			    (member->dsp == dsp) ? " *this*" : "");
 		}
 	}
@@ -235,7 +238,7 @@
 
 	member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC);
 	if (!member) {
-		printk(KERN_ERR "kmalloc struct dsp_conf_member failed\n");
+		printk(KERN_ERR "kzalloc struct dsp_conf_member failed\n");
 		return -ENOMEM;
 	}
 	member->dsp = dsp;
@@ -314,7 +317,7 @@
 
 	conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC);
 	if (!conf) {
-		printk(KERN_ERR "kmalloc struct dsp_conf failed\n");
+		printk(KERN_ERR "kzalloc struct dsp_conf failed\n");
 		return NULL;
 	}
 	INIT_LIST_HEAD(&conf->mlist);
@@ -385,7 +388,7 @@
 	int		freeunits[8];
 	u_char		freeslots[256];
 	int		same_hfc = -1, same_pcm = -1, current_conf = -1,
-	    all_conf = 1;
+	    all_conf = 1, tx_data = 0;
 
 	/* dsp gets updated (no conf) */
 	if (!conf) {
@@ -409,7 +412,7 @@
 		/* process hw echo */
 		if (dsp->features.pcm_banks < 1)
 			return;
-		if (!dsp->echo) {
+		if (!dsp->echo.software && !dsp->echo.hardware) {
 			/* NO ECHO: remove PCM slot if assigned */
 			if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
 				if (dsp_debug & DEBUG_DSP_CMX)
@@ -427,10 +430,15 @@
 			}
 			return;
 		}
+		/* echo is enabled, find out if we use soft or hardware */
+		dsp->echo.software = dsp->tx_data;
+		dsp->echo.hardware = 0;
 		/* ECHO: already echo */
 		if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
-		    dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2)
+		    dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) {
+			dsp->echo.hardware = 1;
 			return;
+		}
 		/* ECHO: if slot already assigned */
 		if (dsp->pcm_slot_tx >= 0) {
 			dsp->pcm_slot_rx = dsp->pcm_slot_tx;
@@ -443,6 +451,7 @@
 				    dsp->pcm_slot_tx);
 			dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
 			    dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
+			dsp->echo.hardware = 1;
 			return;
 		}
 		/* ECHO: find slot */
@@ -472,6 +481,7 @@
 				    "%s no slot available for echo\n",
 				    __func__);
 			/* no more slots available */
+			dsp->echo.software = 1;
 			return;
 		}
 		/* assign free slot */
@@ -485,6 +495,7 @@
 			    __func__, dsp->name, dsp->pcm_slot_tx);
 		dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
 		    dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
+		dsp->echo.hardware = 1;
 		return;
 	}
 
@@ -554,7 +565,7 @@
 			return;
 		}
 		/* check if member has echo turned on */
-		if (member->dsp->echo) {
+		if (member->dsp->echo.hardware || member->dsp->echo.software) {
 			if (dsp_debug & DEBUG_DSP_CMX)
 				printk(KERN_DEBUG
 				    "%s dsp %s cannot form a conf, because "
@@ -592,10 +603,9 @@
 		if (member->dsp->tx_data) {
 			if (dsp_debug & DEBUG_DSP_CMX)
 				printk(KERN_DEBUG
-				    "%s dsp %s cannot form a conf, because "
-				    "tx_data is turned on\n",
+				    "%s dsp %s tx_data is turned on\n",
 				    __func__, member->dsp->name);
-			goto conf_software;
+			tx_data = 1;
 		}
 		/* check if pipeline exists */
 		if (member->dsp->pipeline.inuse) {
@@ -794,7 +804,7 @@
 			    nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
 			    nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
 			conf->hardware = 1;
-			conf->software = 0;
+			conf->software = tx_data;
 			return;
 		/* if members have one bank (or on the same chip) */
 		} else {
@@ -904,7 +914,7 @@
 			    nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
 			    nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
 			conf->hardware = 1;
-			conf->software = 0;
+			conf->software = tx_data;
 			return;
 		}
 	}
@@ -937,6 +947,10 @@
 	if (current_conf >= 0) {
 join_members:
 		list_for_each_entry(member, &conf->mlist, list) {
+			/* if no conference engine on our chip, change to
+			 * software */
+			if (!member->dsp->features.hfc_conf)
+				goto conf_software;
 			/* in case of hdlc, change to software */
 			if (member->dsp->hdlc)
 				goto conf_software;
@@ -1295,17 +1309,25 @@
 	int r, rr, t, tt, o_r, o_rr;
 	int preload = 0;
 	struct mISDNhead *hh, *thh;
+	int tx_data_only = 0;
 
 	/* don't process if: */
 	if (!dsp->b_active) { /* if not active */
 		dsp->last_tx = 0;
 		return;
 	}
-	if (dsp->pcm_slot_tx >= 0 && /* connected to pcm slot */
+	if (((dsp->conf && dsp->conf->hardware) || /* hardware conf */
+	    dsp->echo.hardware) && /* OR hardware echo */
 	    dsp->tx_R == dsp->tx_W && /* AND no tx-data */
 	    !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
-		dsp->last_tx = 0;
-		return;
+		if (!dsp->tx_data) { /* no tx_data for user space required */
+			dsp->last_tx = 0;
+			return;
+		}
+		if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
+			tx_data_only = 1;
+		if (dsp->conf->software && dsp->echo.hardware)
+			tx_data_only = 1;
 	}
 
 #ifdef CMX_DEBUG
@@ -1367,7 +1389,8 @@
 		while (r != rr && t != tt) {
 #ifdef CMX_TX_DEBUG
 			if (strlen(debugbuf) < 48)
-			    sprintf(debugbuf+strlen(debugbuf), " %02x", p[t]);
+				sprintf(debugbuf+strlen(debugbuf), " %02x",
+				    p[t]);
 #endif
 			*d++ = p[t]; /* write tx_buff */
 			t = (t+1) & CMX_BUFF_MASK;
@@ -1388,7 +1411,7 @@
 	/* PROCESS DATA (one member / no conf) */
 	if (!conf || members <= 1) {
 		/* -> if echo is NOT enabled */
-		if (!dsp->echo) {
+		if (!dsp->echo.software) {
 			/* -> send tx-data if available or use 0-volume */
 			while (r != rr && t != tt) {
 				*d++ = p[t]; /* write tx_buff */
@@ -1438,7 +1461,7 @@
 		o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
 			/* start rx-pointer at current read position*/
 		/* -> if echo is NOT enabled */
-		if (!dsp->echo) {
+		if (!dsp->echo.software) {
 			/*
 			 * -> copy other member's rx-data,
 			 * if tx-data is available, mix
@@ -1486,7 +1509,7 @@
 #endif
 	/* PROCESS DATA (three or more members) */
 	/* -> if echo is NOT enabled */
-	if (!dsp->echo) {
+	if (!dsp->echo.software) {
 		/*
 		 * -> substract rx-data from conf-data,
 		 * if tx-data is available, mix
@@ -1550,27 +1573,40 @@
 	 * becuase we want what we send, not what we filtered
 	 */
 	if (dsp->tx_data) {
-		/* PREPARE RESULT */
-		txskb = mI_alloc_skb(len, GFP_ATOMIC);
-		if (!txskb) {
-			printk(KERN_ERR
-			    "FATAL ERROR in mISDN_dsp.o: "
-			    "cannot alloc %d bytes\n", len);
+		if (tx_data_only) {
+			hh->prim = DL_DATA_REQ;
+			hh->id = 0;
+			/* queue and trigger */
+			skb_queue_tail(&dsp->sendq, nskb);
+			schedule_work(&dsp->workq);
+			/* exit because only tx_data is used */
+			return;
 		} else {
-			thh = mISDN_HEAD_P(txskb);
-			thh->prim = DL_DATA_REQ;
-			thh->id = 0;
-			memcpy(skb_put(txskb, len), nskb->data+preload, len);
-			/* queue (trigger later) */
-			skb_queue_tail(&dsp->sendq, txskb);
+			txskb = mI_alloc_skb(len, GFP_ATOMIC);
+			if (!txskb) {
+				printk(KERN_ERR
+				    "FATAL ERROR in mISDN_dsp.o: "
+				    "cannot alloc %d bytes\n", len);
+			} else {
+				thh = mISDN_HEAD_P(txskb);
+				thh->prim = DL_DATA_REQ;
+				thh->id = 0;
+				memcpy(skb_put(txskb, len), nskb->data+preload,
+					len);
+				/* queue (trigger later) */
+				skb_queue_tail(&dsp->sendq, txskb);
+			}
 		}
 	}
+
+	/* send data only to card, if we don't just calculated tx_data */
 	/* adjust volume */
 	if (dsp->tx_volume)
 		dsp_change_volume(nskb, dsp->tx_volume);
 	/* pipeline */
 	if (dsp->pipeline.inuse)
-		dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, nskb->len);
+		dsp_pipeline_process_tx(&dsp->pipeline, nskb->data,
+			nskb->len);
 	/* crypt */
 	if (dsp->bf_enable)
 		dsp_bf_encrypt(dsp, nskb->data, nskb->len);
@@ -1592,7 +1628,8 @@
 	struct dsp_conf_member *member;
 	struct dsp *dsp;
 	int mustmix, members;
-	s32 mixbuffer[MAX_POLL+100], *c;
+	static s32 mixbuffer[MAX_POLL+100];
+	s32 *c;
 	u8 *p, *q;
 	int r, rr;
 	int jittercheck = 0, delay, i;
@@ -1890,10 +1927,8 @@
 
 	/* no conf */
 	if (!dsp->conf) {
-		/* in case of hardware (echo) */
-		if (dsp->pcm_slot_tx >= 0)
-			return;
-		if (dsp->echo) {
+		/* in case of software echo */
+		if (dsp->echo.software) {
 			nskb = skb_clone(skb, GFP_ATOMIC);
 			if (nskb) {
 				hh = mISDN_HEAD_P(nskb);
@@ -1909,7 +1944,7 @@
 	if (dsp->conf->hardware)
 		return;
 	list_for_each_entry(member, &dsp->conf->mlist, list) {
-		if (dsp->echo || member->dsp != dsp) {
+		if (dsp->echo.software || member->dsp != dsp) {
 			nskb = skb_clone(skb, GFP_ATOMIC);
 			if (nskb) {
 				hh = mISDN_HEAD_P(nskb);
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_core.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_core.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -203,13 +203,13 @@
 	else if (dsp->dtmf.software)
 		rx_off = 0;
 	/* echo in software */
-	else if (dsp->echo && dsp->pcm_slot_tx < 0)
+	else if (dsp->echo.software)
 		rx_off = 0;
 	/* bridge in software */
-	else if (dsp->conf) {
-		if (dsp->conf->software)
-			rx_off = 0;
-	}
+	else if (dsp->conf && dsp->conf->software)
+		rx_off = 0;
+	/* data is not required by user space and not required
+	 * for echo dtmf detection, soft-echo, soft-bridging */
 
 	if (rx_off == dsp->rx_is_off)
 		return;
@@ -280,7 +280,7 @@
 static int
 dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
 {
-	struct		sk_buff *nskb;
+	struct sk_buff	*nskb;
 	int ret = 0;
 	int cont;
 	u8 *data;
@@ -306,15 +306,18 @@
 					"to %d\n", *((int *)data));
 			dsp->dtmf.treshold = (*(int *)data) * 10000;
 		}
+		dsp->dtmf.enable = 1;
 		/* init goertzel */
 		dsp_dtmf_goertzel_init(dsp);
 
 		/* check dtmf hardware */
 		dsp_dtmf_hardware(dsp);
+		dsp_rx_off(dsp);
 		break;
 	case DTMF_TONE_STOP: /* turn off DTMF */
 		if (dsp_debug & DEBUG_DSP_CORE)
 			printk(KERN_DEBUG "%s: stop dtmf\n", __func__);
+		dsp->dtmf.enable = 0;
 		dsp->dtmf.hardware = 0;
 		dsp->dtmf.software = 0;
 		break;
@@ -414,7 +417,7 @@
 		dsp_rx_off(dsp);
 		break;
 	case DSP_ECHO_ON: /* enable echo */
-		dsp->echo = 1; /* soft echo */
+		dsp->echo.software = 1; /* soft echo */
 		if (dsp_debug & DEBUG_DSP_CORE)
 			printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__);
 		dsp_cmx_hardware(dsp->conf, dsp);
@@ -423,7 +426,8 @@
 			dsp_cmx_debug(dsp);
 		break;
 	case DSP_ECHO_OFF: /* disable echo */
-		dsp->echo = 0;
+		dsp->echo.software = 0;
+		dsp->echo.hardware = 0;
 		if (dsp_debug & DEBUG_DSP_CORE)
 			printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__);
 		dsp_cmx_hardware(dsp->conf, dsp);
@@ -502,7 +506,7 @@
 			break;
 		}
 		dsp->cmx_delay = (*((int *)data)) << 3;
-			/* miliseconds to samples */
+			/* milliseconds to samples */
 		if (dsp->cmx_delay >= (CMX_BUFF_HALF>>1))
 			/* clip to half of maximum usable buffer
 			(half of half buffer) */
@@ -556,7 +560,7 @@
 			dsp->pipeline.inuse = 1;
 			dsp_cmx_hardware(dsp->conf, dsp);
 			ret = dsp_pipeline_build(&dsp->pipeline,
-				len > 0 ? (char *)data : NULL);
+				len > 0 ? data : NULL);
 			dsp_cmx_hardware(dsp->conf, dsp);
 			dsp_rx_off(dsp);
 		}
@@ -657,11 +661,10 @@
 static int
 dsp_function(struct mISDNchannel *ch,  struct sk_buff *skb)
 {
-	struct dsp			*dsp = container_of(ch, struct dsp, ch);
+	struct dsp		*dsp = container_of(ch, struct dsp, ch);
 	struct mISDNhead	*hh;
 	int			ret = 0;
-	u8			*digits;
-	int			cont;
+	u8			*digits = NULL;
 	u_long			flags;
 
 	hh = mISDN_HEAD_P(skb);
@@ -704,50 +707,55 @@
 			break;
 		}
 
+		spin_lock_irqsave(&dsp_lock, flags);
+
 		/* decrypt if enabled */
 		if (dsp->bf_enable)
 			dsp_bf_decrypt(dsp, skb->data, skb->len);
 		/* pipeline */
 		if (dsp->pipeline.inuse)
 			dsp_pipeline_process_rx(&dsp->pipeline, skb->data,
-				skb->len);
+				skb->len, hh->id);
 		/* change volume if requested */
 		if (dsp->rx_volume)
 			dsp_change_volume(skb, dsp->rx_volume);
-
 		/* check if dtmf soft decoding is turned on */
 		if (dsp->dtmf.software) {
 			digits = dsp_dtmf_goertzel_decode(dsp, skb->data,
-				skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
+				skb->len, (dsp_options&DSP_OPT_ULAW) ? 1 : 0);
+		}
+		/* we need to process receive data if software */
+		if (dsp->conf && dsp->conf->software) {
+			/* process data from card at cmx */
+			dsp_cmx_receive(dsp, skb);
+		}
+
+		spin_unlock_irqrestore(&dsp_lock, flags);
+
+		/* send dtmf result, if any */
+		if (digits) {
 			while (*digits) {
+				int k;
 				struct sk_buff *nskb;
 				if (dsp_debug & DEBUG_DSP_DTMF)
 					printk(KERN_DEBUG "%s: digit"
 					    "(%c) to layer %s\n",
 					    __func__, *digits, dsp->name);
-				cont = DTMF_TONE_VAL | *digits;
+				k = *digits | DTMF_TONE_VAL;
 				nskb = _alloc_mISDN_skb(PH_CONTROL_IND,
-				    MISDN_ID_ANY, sizeof(int), &cont,
-				    GFP_ATOMIC);
+					MISDN_ID_ANY, sizeof(int), &k,
+					GFP_ATOMIC);
 				if (nskb) {
 					if (dsp->up) {
 						if (dsp->up->send(
 						    dsp->up, nskb))
-						dev_kfree_skb(nskb);
+							dev_kfree_skb(nskb);
 					} else
 						dev_kfree_skb(nskb);
 				}
 				digits++;
 			}
 		}
-		/* we need to process receive data if software */
-		spin_lock_irqsave(&dsp_lock, flags);
-		if (dsp->pcm_slot_tx < 0 && dsp->pcm_slot_rx < 0) {
-			/* process data from card at cmx */
-			dsp_cmx_receive(dsp, skb);
-		}
-		spin_unlock_irqrestore(&dsp_lock, flags);
-
 		if (dsp->rx_disabled) {
 			/* if receive is not allowed */
 			break;
@@ -787,7 +795,7 @@
 					if (dsp->up) {
 						if (dsp->up->send(
 						    dsp->up, nskb))
-						dev_kfree_skb(nskb);
+							dev_kfree_skb(nskb);
 					} else
 						dev_kfree_skb(nskb);
 				}
@@ -946,7 +954,7 @@
 	int		err = 0;
 
 	if (debug & DEBUG_DSP_CTRL)
-	printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);
+		printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);
 
 	switch (cmd) {
 	case OPEN_CHANNEL:
@@ -1169,9 +1177,9 @@
 
 	/* init conversion tables */
 	dsp_audio_generate_law_tables();
-	dsp_silence = (dsp_options&DSP_OPT_ULAW)?0xff:0x2a;
-	dsp_audio_law_to_s32 = (dsp_options&DSP_OPT_ULAW)?dsp_audio_ulaw_to_s32:
-		dsp_audio_alaw_to_s32;
+	dsp_silence = (dsp_options&DSP_OPT_ULAW) ? 0xff : 0x2a;
+	dsp_audio_law_to_s32 = (dsp_options&DSP_OPT_ULAW) ?
+		dsp_audio_ulaw_to_s32 : dsp_audio_alaw_to_s32;
 	dsp_audio_generate_s2law_table();
 	dsp_audio_generate_seven();
 	dsp_audio_generate_mix_table();
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_dtmf.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_dtmf.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_dtmf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_dtmf.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,6 +51,9 @@
 {
 	int hardware = 1;
 
+	if (!dsp->dtmf.enable)
+		return;
+
 	if (!dsp->features.hfc_dtmf)
 		hardware = 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_ecdis.h linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_ecdis.h
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_ecdis.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_ecdis.h	2009-09-09 18:13:59.000000000 -0400
@@ -91,7 +91,7 @@
 					&& det->tone_cycle_duration <= 475*8) {
 					det->good_cycles++;
 					if (det->good_cycles > 2)
-					det->hit = TRUE;
+						det->hit = TRUE;
 				}
 				det->tone_cycle_duration = 0;
 			}
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp.h linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp.h
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp.h	2009-09-09 18:13:59.000000000 -0400
@@ -112,9 +112,11 @@
 
 #define DSP_DTMF_NPOINTS 102
 
-#define ECHOCAN_BUFLEN (4*128)
+#define ECHOCAN_BUFF_SIZE 0x400 /* must be 2**n */
+#define ECHOCAN_BUFF_MASK 0x3ff /* -1 */
 
 struct dsp_dtmf {
+	int		enable; /* dtmf is enabled */
 	int		treshold; /* above this is dtmf (square of) */
 	int		software; /* dtmf uses software decoding */
 	int		hardware; /* dtmf uses hardware decoding */
@@ -123,7 +125,7 @@
 		/* buffers one full dtmf frame */
 	u8		lastwhat, lastdigit;
 	int		count;
-	u8		digits[16]; /* just the dtmf result */
+	u8		digits[16]; /* dtmf result */
 };
 
 
@@ -150,6 +152,15 @@
 	struct timer_list tl;
 };
 
+/***************
+ * echo stuff *
+ ***************/
+
+struct dsp_echo {
+	int		software; /* echo is generated by software */
+	int		hardware; /* echo is generated by hardware */
+};
+
 /*****************
  * general stuff *
  *****************/
@@ -160,7 +171,7 @@
 	struct mISDNchannel	*up;
 	unsigned char	name[64];
 	int		b_active;
-	int		echo; /* echo is enabled */
+	struct dsp_echo	echo;
 	int		rx_disabled; /* what the user wants */
 	int		rx_is_off; /* what the card is */
 	int		tx_mix;
@@ -261,5 +272,5 @@
 extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data,
 		int len);
 extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data,
-		int len);
+		int len, unsigned int txlen);
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_pipeline.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_pipeline.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_pipeline.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_pipeline.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,20 +55,19 @@
 attr_show_args(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct mISDN_dsp_element *elem = dev_get_drvdata(dev);
-	ssize_t len = 0;
-	int i = 0;
+	int i;
+	char *p = buf;
 
 	*buf = 0;
-	for (; i < elem->num_args; ++i)
-		len = sprintf(buf, "%sName:        %s\n%s%s%sDescription: %s\n"
-			"\n", buf,
+	for (i = 0; i < elem->num_args; i++)
+		p += sprintf(p, "Name:        %s\n%s%s%sDescription: %s\n\n",
 			  elem->args[i].name,
 			  elem->args[i].def ? "Default:     " : "",
 			  elem->args[i].def ? elem->args[i].def : "",
 			  elem->args[i].def ? "\n" : "",
 			  elem->args[i].desc);
 
-	return len;
+	return p - buf;
 }
 
 static struct device_attribute element_attributes[] = {
@@ -347,7 +346,8 @@
 			entry->elem->process_tx(entry->p, data, len);
 }
 
-void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len)
+void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len,
+	unsigned int txlen)
 {
 	struct dsp_pipeline_entry *entry;
 
@@ -356,7 +356,7 @@
 
 	list_for_each_entry_reverse(entry, &pipeline->list, list)
 		if (entry->elem->process_rx)
-			entry->elem->process_rx(entry->p, data, len);
+			entry->elem->process_rx(entry->p, data, len, txlen);
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_tones.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_tones.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/dsp_tones.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/dsp_tones.c	2009-09-09 18:13:59.000000000 -0400
@@ -253,18 +253,24 @@
 	{8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
 
 	{TONE_GERMAN_DIALPBX,
-	{DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, NULL},
-	{SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL},
+	{DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL,
+		NULL},
+	{SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL,
+		NULL},
 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
 
 	{TONE_GERMAN_OLDDIALPBX,
-	{DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL},
-	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL},
+	{DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL,
+		NULL},
+	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL,
+		NULL},
 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
 
 	{TONE_AMERICAN_DIALPBX,
-	{DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, NULL, NULL, NULL, NULL},
-	{SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, NULL, NULL, NULL, NULL},
+	{DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, NULL, NULL, NULL,
+		NULL},
+	{SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, NULL, NULL, NULL,
+		NULL},
 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
 
 	{TONE_GERMAN_RINGING,
@@ -434,7 +440,7 @@
 
 	/* unlocking is not required, because we don't expect a response */
 	nskb = _alloc_mISDN_skb(PH_CONTROL_REQ,
-		(len)?HFC_SPL_LOOP_ON:HFC_SPL_LOOP_OFF, len, sample,
+		(len) ? HFC_SPL_LOOP_ON : HFC_SPL_LOOP_OFF, len, sample,
 		GFP_ATOMIC);
 	if (nskb) {
 		if (dsp->ch.peer) {
@@ -498,8 +504,7 @@
 
 	/* we turn off the tone */
 	if (!tone) {
-		if (dsp->features.hfc_loops)
-		if (timer_pending(&tonet->tl))
+		if (dsp->features.hfc_loops && timer_pending(&tonet->tl))
 			del_timer(&tonet->tl);
 		if (dsp->features.hfc_loops)
 			dsp_tone_hw_message(dsp, NULL, 0);
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/hwchannel.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/hwchannel.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/hwchannel.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/hwchannel.c	2009-09-09 18:13:59.000000000 -0400
@@ -185,13 +185,13 @@
 EXPORT_SYMBOL(recv_Echannel);
 
 void
-recv_Bchannel(struct bchannel *bch)
+recv_Bchannel(struct bchannel *bch, unsigned int id)
 {
 	struct mISDNhead *hh;
 
 	hh = mISDN_HEAD_P(bch->rx_skb);
 	hh->prim = PH_DATA_IND;
-	hh->id = MISDN_ID_ANY;
+	hh->id = id;
 	if (bch->rcount >= 64) {
 		printk(KERN_WARNING "B-channel %p receive queue overflow, "
 			"fushing!\n", bch);
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/l1oip_codec.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/l1oip_codec.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/l1oip_codec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/l1oip_codec.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,7 @@
 
 #include <linux/vmalloc.h>
 #include <linux/mISDNif.h>
+#include <linux/in.h>
 #include "core.h"
 #include "l1oip.h"
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/l1oip_core.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/l1oip_core.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/l1oip_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/l1oip_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -279,7 +279,6 @@
 	int multi = 0;
 	u8 frame[len+32];
 	struct socket *socket = NULL;
-	mm_segment_t oldfs;
 
 	if (debug & DEBUG_L1OIP_MSG)
 		printk(KERN_DEBUG "%s: sending data to socket (len = %d)\n",
@@ -308,8 +307,8 @@
 
 	/* assemble frame */
 	*p++ = (L1OIP_VERSION<<6) /* version and coding */
-	     | (hc->pri?0x20:0x00) /* type */
-	     | (hc->id?0x10:0x00) /* id */
+	     | (hc->pri ? 0x20 : 0x00) /* type */
+	     | (hc->id ? 0x10 : 0x00) /* id */
 	     | localcodec;
 	if (hc->id) {
 		*p++ = hc->id>>24; /* id */
@@ -317,7 +316,7 @@
 		*p++ = hc->id>>8;
 		*p++ = hc->id;
 	}
-	*p++ = (multi == 1)?0x80:0x00 + channel; /* m-flag, channel */
+	*p++ = (multi == 1) ? 0x80 : 0x00 + channel; /* m-flag, channel */
 	if (multi == 1)
 		*p++ = len; /* length */
 	*p++ = timebase>>8; /* time base */
@@ -352,10 +351,7 @@
 			"= %d)\n", __func__, len);
 	hc->sendiov.iov_base = frame;
 	hc->sendiov.iov_len  = len;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	len = sock_sendmsg(socket, &hc->sendmsg, len);
-	set_fs(oldfs);
+	len = kernel_sendmsg(socket, &hc->sendmsg, &hc->sendiov, 1, len);
 	/* give socket back */
 	hc->socket = socket; /* no locking required */
 
@@ -401,12 +397,12 @@
 	}
 
 	/* prepare message */
-	nskb = mI_alloc_skb((remotecodec == 3)?(len<<1):len, GFP_ATOMIC);
+	nskb = mI_alloc_skb((remotecodec == 3) ? (len<<1) : len, GFP_ATOMIC);
 	if (!nskb) {
 		printk(KERN_ERR "%s: No mem for skb.\n", __func__);
 		return;
 	}
-	p = skb_put(nskb, (remotecodec == 3)?(len<<1):len);
+	p = skb_put(nskb, (remotecodec == 3) ? (len<<1) : len);
 
 	if (remotecodec == 1 && ulaw)
 		l1oip_alaw_to_ulaw(buf, len, p);
@@ -458,7 +454,7 @@
 		hc->chan[channel].disorder_flag ^= 1;
 		if (nskb)
 #endif
-		queue_ch_frame(&bch->ch, PH_DATA_IND, rx_counter, nskb);
+			queue_ch_frame(&bch->ch, PH_DATA_IND, rx_counter, nskb);
 	}
 }
 
@@ -660,21 +656,29 @@
 	struct l1oip *hc = (struct l1oip *)data;
 	int ret = 0;
 	struct msghdr msg;
-	struct iovec iov;
-	mm_segment_t oldfs;
 	struct sockaddr_in sin_rx;
-	unsigned char recvbuf[1500];
+	unsigned char *recvbuf;
+	size_t recvbuf_size = 1500;
 	int recvlen;
 	struct socket *socket = NULL;
 	DECLARE_COMPLETION(wait);
 
+	/* allocate buffer memory */
+	recvbuf = kmalloc(recvbuf_size, GFP_KERNEL);
+	if (!recvbuf) {
+		printk(KERN_ERR "%s: Failed to alloc recvbuf.\n", __func__);
+		ret = -ENOMEM;
+		goto fail;
+	}
+
 	/* make daemon */
 	allow_signal(SIGTERM);
 
 	/* create socket */
 	if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &socket)) {
 		printk(KERN_ERR "%s: Failed to create socket.\n", __func__);
-		return -EIO;
+		ret = -EIO;
+		goto fail;
 	}
 
 	/* set incoming address */
@@ -708,16 +712,12 @@
 	msg.msg_namelen = sizeof(sin_rx);
 	msg.msg_control = NULL;
 	msg.msg_controllen = 0;
-	msg.msg_iov = &iov;
-	msg.msg_iovlen = 1;
 
 	/* build send message */
 	hc->sendmsg.msg_name = &hc->sin_remote;
 	hc->sendmsg.msg_namelen = sizeof(hc->sin_remote);
 	hc->sendmsg.msg_control = NULL;
 	hc->sendmsg.msg_controllen = 0;
-	hc->sendmsg.msg_iov    = &hc->sendiov;
-	hc->sendmsg.msg_iovlen = 1;
 
 	/* give away socket */
 	spin_lock(&hc->socket_lock);
@@ -729,18 +729,18 @@
 		printk(KERN_DEBUG "%s: socket created and open\n",
 			__func__);
 	while (!signal_pending(current)) {
-		iov.iov_base = recvbuf;
-		iov.iov_len = sizeof(recvbuf);
-		oldfs = get_fs();
-		set_fs(KERNEL_DS);
-		recvlen = sock_recvmsg(socket, &msg, sizeof(recvbuf), 0);
-		set_fs(oldfs);
+		struct kvec iov = {
+			.iov_base = recvbuf,
+			.iov_len = recvbuf_size,
+		};
+		recvlen = kernel_recvmsg(socket, &msg, &iov, 1,
+					 recvbuf_size, 0);
 		if (recvlen > 0) {
 			l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen);
 		} else {
 			if (debug & DEBUG_L1OIP_SOCKET)
-			    printk(KERN_WARNING "%s: broken pipe on socket\n",
-				__func__);
+				printk(KERN_WARNING
+				    "%s: broken pipe on socket\n", __func__);
 		}
 	}
 
@@ -760,6 +760,9 @@
 			__func__);
 
 fail:
+	/* free recvbuf */
+	kfree(recvbuf);
+
 	/* close socket */
 	if (socket)
 		sock_release(socket);
@@ -912,7 +915,7 @@
 		p = skb->data;
 		l = skb->len;
 		while (l) {
-			ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME;
+			ll = (l < L1OIP_MAX_PERFRAME) ? l : L1OIP_MAX_PERFRAME;
 			l1oip_socket_send(hc, 0, dch->slot, 0,
 				hc->chan[dch->slot].tx_counter++, p, ll);
 			p += ll;
@@ -1160,7 +1163,7 @@
 		p = skb->data;
 		l = skb->len;
 		while (l) {
-			ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME;
+			ll = (l < L1OIP_MAX_PERFRAME) ? l : L1OIP_MAX_PERFRAME;
 			l1oip_socket_send(hc, hc->codec, bch->slot, 0,
 				hc->chan[bch->slot].tx_counter, p, ll);
 			hc->chan[bch->slot].tx_counter += ll;
@@ -1318,8 +1321,8 @@
 	spin_lock_init(&hc->socket_lock);
 	hc->idx = l1oip_cnt;
 	hc->pri = pri;
-	hc->d_idx = pri?16:3;
-	hc->b_num = pri?30:2;
+	hc->d_idx = pri ? 16 : 3;
+	hc->b_num = pri ? 30 : 2;
 	hc->bundle = bundle;
 	if (hc->pri)
 		sprintf(hc->name, "l1oip-e1.%d", l1oip_cnt + 1);
@@ -1477,7 +1480,7 @@
 		return -ENOMEM;
 
 	l1oip_cnt = 0;
-	while (type[l1oip_cnt] && l1oip_cnt < MAX_CARDS) {
+	while (l1oip_cnt < MAX_CARDS && type[l1oip_cnt]) {
 		switch (type[l1oip_cnt] & 0xff) {
 		case 1:
 			pri = 0;
@@ -1504,9 +1507,9 @@
 
 		if (debug & DEBUG_L1OIP_INIT)
 			printk(KERN_DEBUG "%s: interface %d is %s with %s.\n",
-				__func__, l1oip_cnt, pri?"PRI":"BRI",
-				bundle?"bundled IP packet for all B-channels"
-				 :"seperate IP packets for every B-channel");
+			    __func__, l1oip_cnt, pri ? "PRI" : "BRI",
+			    bundle ? "bundled IP packet for all B-channels" :
+			    "seperate IP packets for every B-channel");
 
 		hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC);
 		if (!hc) {
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/l1oip.h linux-libre-2.6.31-gnu/drivers/isdn/mISDN/l1oip.h
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/l1oip.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/l1oip.h	2009-09-09 18:13:59.000000000 -0400
@@ -76,7 +76,7 @@
 	struct sockaddr_in	sin_local;	/* local socket name */
 	struct sockaddr_in	sin_remote;	/* remote socket name */
 	struct msghdr		sendmsg;	/* ip message to send */
-	struct iovec		sendiov;	/* iov for message */
+	struct kvec		sendiov;	/* iov for message */
 
 	/* frame */
 	struct l1oip_chan	chan[128];	/* channel instances */
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/layer2.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/layer2.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/layer2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/layer2.c	2009-09-09 18:13:59.000000000 -0400
@@ -99,7 +99,7 @@
 	if (!(*debug & DEBUG_L2_FSM))
 		return;
 	va_start(va, fmt);
-	printk(KERN_DEBUG "l2 (tei %d): ", l2->tei);
+	printk(KERN_DEBUG "l2 (sapi %d tei %d): ", l2->sapi, l2->tei);
 	vprintk(fmt, va);
 	printk("\n");
 	va_end(va);
@@ -1859,20 +1859,18 @@
 		psapi >>= 2;
 		ptei >>= 1;
 		if (psapi != l2->sapi) {
-			/* not our bussiness
-			 * printk(KERN_DEBUG "%s: sapi %d/%d sapi mismatch\n",
-			 *  __func__,
-			 *	psapi, l2->sapi);
-			 */
+			/* not our bussiness */
+			if (*debug & DEBUG_L2)
+				printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n",
+					__func__, psapi, l2->sapi);
 			dev_kfree_skb(skb);
 			return 0;
 		}
 		if ((ptei != l2->tei) && (ptei != GROUP_TEI)) {
-			/* not our bussiness
-			 * printk(KERN_DEBUG "%s: tei %d/%d sapi %d mismatch\n",
-			 *  __func__,
-			 *	ptei, l2->tei, psapi);
-			 */
+			/* not our bussiness */
+			if (*debug & DEBUG_L2)
+				printk(KERN_DEBUG "%s: tei %d/%d mismatch\n",
+					__func__, ptei, l2->tei);
 			dev_kfree_skb(skb);
 			return 0;
 		}
@@ -1927,8 +1925,8 @@
 	int 			ret = -EINVAL;
 
 	if (*debug & DEBUG_L2_RECV)
-		printk(KERN_DEBUG "%s: prim(%x) id(%x) tei(%d)\n",
-		    __func__, hh->prim, hh->id, l2->tei);
+		printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n",
+		    __func__, hh->prim, hh->id, l2->sapi, l2->tei);
 	switch (hh->prim) {
 	case PH_DATA_IND:
 		ret = ph_data_indication(l2, hh, skb);
@@ -2068,7 +2066,8 @@
 }
 
 struct layer2 *
-create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, u_long arg)
+create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei,
+		int sapi)
 {
 	struct layer2		*l2;
 	struct channel_req	rq;
@@ -2089,7 +2088,7 @@
 		test_and_set_bit(FLG_LAPD, &l2->flag);
 		test_and_set_bit(FLG_LAPD_NET, &l2->flag);
 		test_and_set_bit(FLG_MOD128, &l2->flag);
-		l2->sapi = 0;
+		l2->sapi = sapi;
 		l2->maxlen = MAX_DFRAME_LEN;
 		if (test_bit(OPTION_L2_PMX, &options))
 			l2->window = 7;
@@ -2099,7 +2098,7 @@
 			test_and_set_bit(FLG_PTP, &l2->flag);
 		if (test_bit(OPTION_L2_FIXEDTEI, &options))
 			test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
-		l2->tei = (u_int)arg;
+		l2->tei = tei;
 		l2->T200 = 1000;
 		l2->N200 = 3;
 		l2->T203 = 10000;
@@ -2114,7 +2113,7 @@
 		test_and_set_bit(FLG_LAPD, &l2->flag);
 		test_and_set_bit(FLG_MOD128, &l2->flag);
 		test_and_set_bit(FLG_ORIG, &l2->flag);
-		l2->sapi = 0;
+		l2->sapi = sapi;
 		l2->maxlen = MAX_DFRAME_LEN;
 		if (test_bit(OPTION_L2_PMX, &options))
 			l2->window = 7;
@@ -2124,7 +2123,7 @@
 			test_and_set_bit(FLG_PTP, &l2->flag);
 		if (test_bit(OPTION_L2_FIXEDTEI, &options))
 			test_and_set_bit(FLG_FIXED_TEI, &l2->flag);
-		l2->tei = (u_int)arg;
+		l2->tei = tei;
 		l2->T200 = 1000;
 		l2->N200 = 3;
 		l2->T203 = 10000;
@@ -2180,7 +2179,7 @@
 
 	if (crq->protocol != ISDN_P_B_X75SLP)
 		return -EPROTONOSUPPORT;
-	l2 = create_l2(crq->ch, crq->protocol, 0, 0);
+	l2 = create_l2(crq->ch, crq->protocol, 0, 0, 0);
 	if (!l2)
 		return -ENOMEM;
 	crq->ch = &l2->ch;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/layer2.h linux-libre-2.6.31-gnu/drivers/isdn/mISDN/layer2.h
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/layer2.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/layer2.h	2009-09-09 18:13:59.000000000 -0400
@@ -90,7 +90,7 @@
 #define L2_STATE_COUNT (ST_L2_8+1)
 
 extern struct layer2	*create_l2(struct mISDNchannel *, u_int,
-				u_long, u_long);
+				u_long, int, int);
 extern int		tei_l2(struct layer2 *, u_int, u_long arg);
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/socket.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/socket.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/socket.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/socket.c	2009-09-09 18:13:59.000000000 -0400
@@ -209,7 +209,7 @@
 
 	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
 		err = -EFAULT;
-		goto drop;
+		goto done;
 	}
 
 	memcpy(mISDN_HEAD_P(skb), skb->data, MISDN_HEADER_LEN);
@@ -222,7 +222,7 @@
 	} else { /* use default for L2 messages */
 		if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
 		    (sk->sk_protocol == ISDN_P_LAPD_NT))
-		    mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr;
+			mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr;
 	}
 
 	if (*debug & DEBUG_SOCKET)
@@ -230,19 +230,21 @@
 		     __func__, mISDN_HEAD_ID(skb));
 
 	err = -ENODEV;
-	if (!_pms(sk)->ch.peer ||
-	    (err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb)))
-		goto drop;
-
-	err = len;
+	if (!_pms(sk)->ch.peer)
+		goto done;
+	err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb);
+	if (err)
+		goto done;
+	else {
+		skb = NULL;
+		err = len;
+	}
 
 done:
+	if (skb)
+		kfree_skb(skb);
 	release_sock(sk);
 	return err;
-
-drop:
-	kfree_skb(skb);
-	goto done;
 }
 
 static int
@@ -292,7 +294,7 @@
 data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p)
 {
 	struct mISDN_ctrl_req	cq;
-	int			err = -EINVAL, val;
+	int			err = -EINVAL, val[2];
 	struct mISDNchannel	*bchan, *next;
 
 	lock_sock(sk);
@@ -328,12 +330,27 @@
 			err = -EINVAL;
 			break;
 		}
-		if (get_user(val, (int __user *)p)) {
+		val[0] = cmd;
+		if (get_user(val[1], (int __user *)p)) {
 			err = -EFAULT;
 			break;
 		}
 		err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr,
-		    CONTROL_CHANNEL, &val);
+		    CONTROL_CHANNEL, val);
+		break;
+	case IMHOLD_L1:
+		if (sk->sk_protocol != ISDN_P_LAPD_NT
+		 && sk->sk_protocol != ISDN_P_LAPD_TE) {
+			err = -EINVAL;
+			break;
+		}
+		val[0] = cmd;
+		if (get_user(val[1], (int __user *)p)) {
+			err = -EFAULT;
+			break;
+		}
+		err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr,
+		    CONTROL_CHANNEL, val);
 		break;
 	default:
 		err = -EINVAL;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/stack.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/stack.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/stack.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/stack.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 
 #include <linux/mISDNif.h>
 #include <linux/kthread.h>
+#include <linux/smp_lock.h>
 #include "core.h"
 
 static u_int	*debug;
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/tei.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/tei.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/tei.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/tei.c	2009-09-09 18:13:59.000000000 -0400
@@ -122,8 +122,11 @@
 	}
 	read_unlock_irqrestore(&mgr->lock, flags);
 	/* All TEI are inactiv */
-	mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 1);
-	mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
+	if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
+		mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
+			NULL, 1);
+		mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
+	}
 }
 
 static void
@@ -132,9 +135,11 @@
 	struct manager	*mgr = fi->userdata;
 
 	/* restart da timer */
-	mISDN_FsmDelTimer(&mgr->datimer, 2);
-	mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 2);
-
+	if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
+		mISDN_FsmDelTimer(&mgr->datimer, 2);
+		mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
+			NULL, 2);
+	}
 }
 
 static void
@@ -222,7 +227,7 @@
 	if (!(*debug & DEBUG_L2_TEIFSM))
 		return;
 	va_start(va, fmt);
-	printk(KERN_DEBUG "tei(%d): ", tm->l2->tei);
+	printk(KERN_DEBUG "sapi(%d) tei(%d): ", tm->l2->sapi, tm->l2->tei);
 	vprintk(fmt, va);
 	printk("\n");
 	va_end(va);
@@ -421,7 +426,7 @@
 }
 
 static void
-put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, u_char tei)
+put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, int tei)
 {
 	struct sk_buff *skb;
 	u_char bp[8];
@@ -435,9 +440,8 @@
 	bp[4] = ri >> 8;
 	bp[5] = ri & 0xff;
 	bp[6] = m_id;
-	bp[7] = (tei << 1) | 1;
-	skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr),
-	    8, bp, GFP_ATOMIC);
+	bp[7] = ((tei << 1) & 0xff) | 1;
+	skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr), 8, bp, GFP_ATOMIC);
 	if (!skb) {
 		printk(KERN_WARNING "%s: no skb for tei msg\n", __func__);
 		return;
@@ -772,7 +776,7 @@
 }
 
 static struct layer2 *
-create_new_tei(struct manager *mgr, int tei)
+create_new_tei(struct manager *mgr, int tei, int sapi)
 {
 	u_long		opt = 0;
 	u_long		flags;
@@ -781,12 +785,12 @@
 
 	if (!mgr->up)
 		return NULL;
-	if (tei < 64)
+	if ((tei >= 0) && (tei < 64))
 		test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
 	if (mgr->ch.st->dev->Dprotocols
 	  & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
 		test_and_set_bit(OPTION_L2_PMX, &opt);
-	l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, (u_int)opt, (u_long)tei);
+	l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi);
 	if (!l2) {
 		printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
 		return NULL;
@@ -834,12 +838,17 @@
 	ri += dp[1];
 	if (!mgr->up)
 		goto denied;
-	tei = get_free_tei(mgr);
+	if (!(dp[3] & 1)) /* Extension bit != 1 */
+		goto denied;
+	if (dp[3] != 0xff)
+		tei = dp[3] >> 1; /* 3GPP TS 08.56 6.1.11.2 */
+	else
+		tei = get_free_tei(mgr);
 	if (tei < 0) {
 		printk(KERN_WARNING "%s:No free tei\n", __func__);
 		goto denied;
 	}
-	l2 = create_new_tei(mgr, tei);
+	l2 = create_new_tei(mgr, tei, CTRL_SAPI);
 	if (!l2)
 		goto denied;
 	else
@@ -853,8 +862,7 @@
 ph_data_ind(struct manager *mgr, struct sk_buff *skb)
 {
 	int		ret = -EINVAL;
-	struct layer2	*l2;
-	u_long		flags;
+	struct layer2	*l2, *nl2;
 	u_char		mt;
 
 	if (skb->len < 8) {
@@ -863,7 +871,6 @@
 			    __func__, skb->len);
 		goto done;
 	}
-	if (*debug  & DEBUG_L2_TEI)
 
 	if ((skb->data[0] >> 2) != TEI_SAPI) /* not for us */
 		goto done;
@@ -900,11 +907,9 @@
 		new_tei_req(mgr, &skb->data[4]);
 		goto done;
 	}
-	read_lock_irqsave(&mgr->lock, flags);
-	list_for_each_entry(l2, &mgr->layer2, list) {
+	list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
 		tei_ph_data_ind(l2->tm, mt, &skb->data[4], skb->len - 4);
 	}
-	read_unlock_irqrestore(&mgr->lock, flags);
 done:
 	return ret;
 }
@@ -971,8 +976,6 @@
 			__func__, dev_name(&mgr->ch.st->dev->dev),
 			crq->protocol, crq->adr.dev, crq->adr.channel,
 			crq->adr.sapi, crq->adr.tei);
-	if (crq->adr.sapi != 0) /* not supported yet */
-		return -EINVAL;
 	if (crq->adr.tei > GROUP_TEI)
 		return -EINVAL;
 	if (crq->adr.tei < 64)
@@ -1019,8 +1022,8 @@
 		}
 		return 0;
 	}
-	l2 = create_l2(crq->ch, crq->protocol, (u_int)opt,
-		(u_long)crq->adr.tei);
+	l2 = create_l2(crq->ch, crq->protocol, opt,
+		crq->adr.tei, crq->adr.sapi);
 	if (!l2)
 		return -ENOMEM;
 	l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
@@ -1103,6 +1106,7 @@
 {
 	struct layer2	*l2, *nl2;
 
+	test_and_clear_bit(OPTION_L1_HOLD, &mgr->options);
 	if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
 		/* not locked lock is taken in release tei */
 		mgr->up = NULL;
@@ -1133,13 +1137,26 @@
 ctrl_teimanager(struct manager *mgr, void *arg)
 {
 	/* currently we only have one option */
-	int	clean = *((int *)arg);
+	int	*val = (int *)arg;
+	int	ret = 0;
 
-	if (clean)
-		test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
-	else
-		test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options);
-	return 0;
+	switch (val[0]) {
+	case IMCLEAR_L2:
+		if (val[1])
+			test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
+		else
+			test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options);
+		break;
+	case IMHOLD_L1:
+		if (val[1])
+			test_and_set_bit(OPTION_L1_HOLD, &mgr->options);
+		else
+			test_and_clear_bit(OPTION_L1_HOLD, &mgr->options);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
 }
 
 /* This function does create a L2 for fixed TEI in NT Mode */
@@ -1147,7 +1164,7 @@
 check_data(struct manager *mgr, struct sk_buff *skb)
 {
 	struct mISDNhead	*hh =  mISDN_HEAD_P(skb);
-	int			ret, tei;
+	int			ret, tei, sapi;
 	struct layer2		*l2;
 
 	if (*debug & DEBUG_L2_CTRL)
@@ -1159,20 +1176,27 @@
 		return -ENOTCONN;
 	if (skb->len != 3)
 		return -ENOTCONN;
-	if (skb->data[0] != 0)
-		/* only SAPI 0 command */
-		return -ENOTCONN;
+	if (skb->data[0] & 3) /* EA0 and CR must be  0 */
+		return -EINVAL;
+	sapi = skb->data[0] >> 2;
 	if (!(skb->data[1] & 1)) /* invalid EA1 */
 		return -EINVAL;
-	tei = skb->data[1] >> 0;
+	tei = skb->data[1] >> 1;
 	if (tei > 63) /* not a fixed tei */
 		return -ENOTCONN;
 	if ((skb->data[2] & ~0x10) != SABME)
 		return -ENOTCONN;
 	/* We got a SABME for a fixed TEI */
-	l2 = create_new_tei(mgr, tei);
-	if (!l2)
+	if (*debug & DEBUG_L2_CTRL)
+		printk(KERN_DEBUG "%s: SABME sapi(%d) tei(%d)\n",
+		    __func__, sapi, tei);
+	l2 = create_new_tei(mgr, tei, sapi);
+	if (!l2) {
+		if (*debug & DEBUG_L2_CTRL)
+			printk(KERN_DEBUG "%s: failed to create new tei\n",
+			    __func__);
 		return -ENOMEM;
+	}
 	ret = l2->ch.send(&l2->ch, skb);
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/isdn/mISDN/timerdev.c linux-libre-2.6.31-gnu/drivers/isdn/mISDN/timerdev.c
--- linux-libre-2.6.30-gnu/drivers/isdn/mISDN/timerdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/isdn/mISDN/timerdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -259,7 +259,7 @@
 	return ret;
 }
 
-static struct file_operations mISDN_fops = {
+static const struct file_operations mISDN_fops = {
 	.read		= mISDN_read,
 	.poll		= mISDN_poll,
 	.ioctl		= mISDN_ioctl,
diff -druN linux-libre-2.6.30-gnu/drivers/Kconfig linux-libre-2.6.31-gnu/drivers/Kconfig
--- linux-libre-2.6.30-gnu/drivers/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -52,6 +52,8 @@
 
 source "drivers/spi/Kconfig"
 
+source "drivers/pps/Kconfig"
+
 source "drivers/gpio/Kconfig"
 
 source "drivers/w1/Kconfig"
@@ -104,6 +106,8 @@
 
 source "drivers/uio/Kconfig"
 
+source "drivers/vlynq/Kconfig"
+
 source "drivers/xen/Kconfig"
 
 source "drivers/staging/Kconfig"
diff -druN linux-libre-2.6.30-gnu/drivers/leds/Kconfig linux-libre-2.6.31-gnu/drivers/leds/Kconfig
--- linux-libre-2.6.30-gnu/drivers/leds/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -75,6 +75,7 @@
 	depends on LEDS_CLASS && X86 && EXPERIMENTAL
 	help
 	  This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
+	  You have to set leds-alix2.force=1 for boards with Award BIOS.
 
 config LEDS_H1940
 	tristate "LED Support for iPAQ H1940 device"
@@ -145,15 +146,16 @@
 	  of_platform devices.  For instance, LEDs which are listed in a "dts"
 	  file.
 
-config LEDS_LP5521
-	tristate "LED Support for the LP5521 LEDs"
+config LEDS_LP3944
+	tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
 	depends on LEDS_CLASS && I2C
 	help
-	  If you say 'Y' here you get support for the National Semiconductor
-	  LP5521 LED driver used in n8x0 boards.
+    This option enables support for LEDs connected to the National
+    Semiconductor LP3944 Lighting Management Unit (LMU) also known as
+    Fun Light Chip.
 
-	  This driver can be built as a module by choosing 'M'. The module
-	  will be called leds-lp5521.
+	  To compile this driver as a module, choose M here: the
+	  module will be called leds-lp3944.
 
 config LEDS_CLEVO_MAIL
 	tristate "Mail LED on Clevo notebook"
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-alix2.c linux-libre-2.6.31-gnu/drivers/leds/leds-alix2.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-alix2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-alix2.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,7 +14,7 @@
 
 static int force = 0;
 module_param(force, bool, 0444);
-MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs");
+MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
 
 struct alix_led {
 	struct led_classdev cdev;
@@ -155,6 +155,11 @@
 		goto out;
 	}
 
+	/* enable output on GPIO for LED 1,2,3 */
+	outl(1 << 6, 0x6104);
+	outl(1 << 9, 0x6184);
+	outl(1 << 11, 0x6184);
+
 	pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
 	if (!IS_ERR(pdev)) {
 		ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-bd2802.c linux-libre-2.6.31-gnu/drivers/leds/leds-bd2802.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-bd2802.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-bd2802.c	2009-09-09 18:13:59.000000000 -0400
@@ -97,6 +97,10 @@
 	enum led_ids			led_id;
 	enum led_colors			color;
 	enum led_bits			state;
+
+	/* General attributes of RGB LEDs */
+	int				wave_pattern;
+	int				rgb_current;
 };
 
 
@@ -254,7 +258,7 @@
 		bd2802_reset_cancel(led);
 
 	reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP);
-	bd2802_write_byte(led->client, reg, BD2802_CURRENT_032);
+	bd2802_write_byte(led->client, reg, led->rgb_current);
 	reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP);
 	bd2802_write_byte(led->client, reg, BD2802_CURRENT_000);
 	reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN);
@@ -275,9 +279,9 @@
 	reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP);
 	bd2802_write_byte(led->client, reg, BD2802_CURRENT_000);
 	reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP);
-	bd2802_write_byte(led->client, reg, BD2802_CURRENT_032);
+	bd2802_write_byte(led->client, reg, led->rgb_current);
 	reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN);
-	bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF);
+	bd2802_write_byte(led->client, reg, led->wave_pattern);
 
 	bd2802_enable(led, id);
 	bd2802_update_state(led, id, color, BD2802_BLINK);
@@ -406,7 +410,7 @@
 		ret = device_create_file(&led->client->dev,
 						bd2802_addr_attributes[i]);
 		if (ret) {
-			dev_err(&led->client->dev, "failed to sysfs file %s\n",
+			dev_err(&led->client->dev, "failed: sysfs file %s\n",
 					bd2802_addr_attributes[i]->attr.name);
 			goto failed_remove_files;
 		}
@@ -483,6 +487,52 @@
 	.store = bd2802_store_adv_conf,
 };
 
+#define BD2802_CONTROL_ATTR(attr_name, name_str)			\
+static ssize_t bd2802_show_##attr_name(struct device *dev,		\
+	struct device_attribute *attr, char *buf)			\
+{									\
+	struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
+	ssize_t ret;							\
+	down_read(&led->rwsem);						\
+	ret = sprintf(buf, "0x%02x\n", led->attr_name);			\
+	up_read(&led->rwsem);						\
+	return ret;							\
+}									\
+static ssize_t bd2802_store_##attr_name(struct device *dev,		\
+	struct device_attribute *attr, const char *buf, size_t count)	\
+{									\
+	struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
+	unsigned long val;						\
+	int ret;							\
+	if (!count)							\
+		return -EINVAL;						\
+	ret = strict_strtoul(buf, 16, &val);				\
+	if (ret)							\
+		return ret;						\
+	down_write(&led->rwsem);					\
+	led->attr_name = val;						\
+	up_write(&led->rwsem);						\
+	return count;							\
+}									\
+static struct device_attribute bd2802_##attr_name##_attr = {		\
+	.attr = {							\
+		.name = name_str,					\
+		.mode = 0644,						\
+		.owner = THIS_MODULE					\
+	},								\
+	.show = bd2802_show_##attr_name,				\
+	.store = bd2802_store_##attr_name,				\
+};
+
+BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern");
+BD2802_CONTROL_ATTR(rgb_current, "rgb_current");
+
+static struct device_attribute *bd2802_attributes[] = {
+	&bd2802_adv_conf_attr,
+	&bd2802_wave_pattern_attr,
+	&bd2802_rgb_current_attr,
+};
+
 static void bd2802_led_work(struct work_struct *work)
 {
 	struct bd2802_led *led = container_of(work, struct bd2802_led, work);
@@ -538,7 +588,6 @@
 	led->cdev_led1r.brightness = LED_OFF;
 	led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness;
 	led->cdev_led1r.blink_set = bd2802_set_led1r_blink;
-	led->cdev_led1r.flags |= LED_CORE_SUSPENDRESUME;
 
 	ret = led_classdev_register(&led->client->dev, &led->cdev_led1r);
 	if (ret < 0) {
@@ -551,7 +600,6 @@
 	led->cdev_led1g.brightness = LED_OFF;
 	led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness;
 	led->cdev_led1g.blink_set = bd2802_set_led1g_blink;
-	led->cdev_led1g.flags |= LED_CORE_SUSPENDRESUME;
 
 	ret = led_classdev_register(&led->client->dev, &led->cdev_led1g);
 	if (ret < 0) {
@@ -564,7 +612,6 @@
 	led->cdev_led1b.brightness = LED_OFF;
 	led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness;
 	led->cdev_led1b.blink_set = bd2802_set_led1b_blink;
-	led->cdev_led1b.flags |= LED_CORE_SUSPENDRESUME;
 
 	ret = led_classdev_register(&led->client->dev, &led->cdev_led1b);
 	if (ret < 0) {
@@ -577,7 +624,6 @@
 	led->cdev_led2r.brightness = LED_OFF;
 	led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness;
 	led->cdev_led2r.blink_set = bd2802_set_led2r_blink;
-	led->cdev_led2r.flags |= LED_CORE_SUSPENDRESUME;
 
 	ret = led_classdev_register(&led->client->dev, &led->cdev_led2r);
 	if (ret < 0) {
@@ -590,7 +636,6 @@
 	led->cdev_led2g.brightness = LED_OFF;
 	led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness;
 	led->cdev_led2g.blink_set = bd2802_set_led2g_blink;
-	led->cdev_led2g.flags |= LED_CORE_SUSPENDRESUME;
 
 	ret = led_classdev_register(&led->client->dev, &led->cdev_led2g);
 	if (ret < 0) {
@@ -640,7 +685,7 @@
 {
 	struct bd2802_led *led;
 	struct bd2802_led_platform_data *pdata;
-	int ret;
+	int ret, i;
 
 	led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL);
 	if (!led) {
@@ -670,13 +715,20 @@
 	/* To save the power, reset BD2802 after detecting */
 	gpio_set_value(led->pdata->reset_gpio, 0);
 
+	/* Default attributes */
+	led->wave_pattern = BD2802_PATTERN_HALF;
+	led->rgb_current = BD2802_CURRENT_032;
+
 	init_rwsem(&led->rwsem);
 
-	ret = device_create_file(&client->dev, &bd2802_adv_conf_attr);
-	if (ret) {
-		dev_err(&client->dev, "failed to create sysfs file %s\n",
-					bd2802_adv_conf_attr.attr.name);
-		goto failed_free;
+	for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) {
+		ret = device_create_file(&led->client->dev,
+						bd2802_attributes[i]);
+		if (ret) {
+			dev_err(&led->client->dev, "failed: sysfs file %s\n",
+					bd2802_attributes[i]->attr.name);
+			goto failed_unregister_dev_file;
+		}
 	}
 
 	ret = bd2802_register_led_classdev(led);
@@ -686,7 +738,8 @@
 	return 0;
 
 failed_unregister_dev_file:
-	device_remove_file(&client->dev, &bd2802_adv_conf_attr);
+	for (i--; i >= 0; i--)
+		device_remove_file(&led->client->dev, bd2802_attributes[i]);
 failed_free:
 	i2c_set_clientdata(client, NULL);
 	kfree(led);
@@ -697,12 +750,14 @@
 static int __exit bd2802_remove(struct i2c_client *client)
 {
 	struct bd2802_led *led = i2c_get_clientdata(client);
+	int i;
 
-	bd2802_unregister_led_classdev(led);
 	gpio_set_value(led->pdata->reset_gpio, 0);
+	bd2802_unregister_led_classdev(led);
 	if (led->adf_on)
 		bd2802_disable_adv_conf(led);
-	device_remove_file(&client->dev, &bd2802_adv_conf_attr);
+	for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++)
+		device_remove_file(&led->client->dev, bd2802_attributes[i]);
 	i2c_set_clientdata(client, NULL);
 	kfree(led);
 
@@ -723,8 +778,7 @@
 	struct bd2802_led *led = i2c_get_clientdata(client);
 
 	if (!bd2802_is_all_off(led) || led->adf_on) {
-		gpio_set_value(led->pdata->reset_gpio, 1);
-		udelay(100);
+		bd2802_reset_cancel(led);
 		bd2802_restore_state(led);
 	}
 
@@ -762,4 +816,4 @@
 
 MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
 MODULE_DESCRIPTION("BD2802 LED driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-cobalt-raq.c linux-libre-2.6.31-gnu/drivers/leds/leds-cobalt-raq.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-cobalt-raq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-cobalt-raq.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  LEDs driver for the Cobalt Raq series.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@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
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-gpio.c linux-libre-2.6.31-gnu/drivers/leds/leds-gpio.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -76,7 +76,7 @@
 	struct gpio_led_data *led_dat, struct device *parent,
 	int (*blink_set)(unsigned, unsigned long *, unsigned long *))
 {
-	int ret;
+	int ret, state;
 
 	/* skip leds that aren't available */
 	if (!gpio_is_valid(template->gpio)) {
@@ -99,11 +99,15 @@
 		led_dat->cdev.blink_set = gpio_blink_set;
 	}
 	led_dat->cdev.brightness_set = gpio_led_set;
-	led_dat->cdev.brightness = LED_OFF;
+	if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
+		state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low;
+	else
+		state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
+	led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
 	if (!template->retain_state_suspended)
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-	ret = gpio_direction_output(led_dat->gpio, led_dat->active_low);
+	ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
 	if (ret < 0)
 		goto err;
 
@@ -129,7 +133,7 @@
 }
 
 #ifdef CONFIG_LEDS_GPIO_PLATFORM
-static int gpio_led_probe(struct platform_device *pdev)
+static int __devinit gpio_led_probe(struct platform_device *pdev)
 {
 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 	struct gpio_led_data *leds_data;
@@ -223,12 +227,22 @@
 	memset(&led, 0, sizeof(led));
 	for_each_child_of_node(np, child) {
 		enum of_gpio_flags flags;
+		const char *state;
 
 		led.gpio = of_get_gpio_flags(child, 0, &flags);
 		led.active_low = flags & OF_GPIO_ACTIVE_LOW;
 		led.name = of_get_property(child, "label", NULL) ? : child->name;
 		led.default_trigger =
 			of_get_property(child, "linux,default-trigger", NULL);
+		state = of_get_property(child, "default-state", NULL);
+		if (state) {
+			if (!strcmp(state, "keep"))
+				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
+			else if(!strcmp(state, "on"))
+				led.default_state = LEDS_GPIO_DEFSTATE_ON;
+			else
+				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
+		}
 
 		ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++],
 				      &ofdev->dev, NULL);
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-h1940.c linux-libre-2.6.31-gnu/drivers/leds/leds-h1940.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-h1940.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-h1940.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,8 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/leds.h>
+#include <linux/gpio.h>
+
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
 #include <mach/h1940-latch.h>
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-lp3944.c linux-libre-2.6.31-gnu/drivers/leds/leds-lp3944.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-lp3944.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-lp3944.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,466 @@
+/*
+ * leds-lp3944.c - driver for National Semiconductor LP3944 Funlight Chip
+ *
+ * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * 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.
+ *
+ */
+
+/*
+ * I2C driver for National Semiconductor LP3944 Funlight Chip
+ * http://www.national.com/pf/LP/LP3944.html
+ *
+ * This helper chip can drive up to 8 leds, with two programmable DIM modes;
+ * it could even be used as a gpio expander but this driver assumes it is used
+ * as a led controller.
+ *
+ * The DIM modes are used to set _blink_ patterns for leds, the pattern is
+ * specified supplying two parameters:
+ *   - period: from 0s to 1.6s
+ *   - duty cycle: percentage of the period the led is on, from 0 to 100
+ *
+ * LP3944 can be found on Motorola A910 smartphone, where it drives the rgb
+ * leds, the camera flash light and the displays backlights.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/leds-lp3944.h>
+
+/* Read Only Registers */
+#define LP3944_REG_INPUT1     0x00 /* LEDs 0-7 InputRegister (Read Only) */
+#define LP3944_REG_REGISTER1  0x01 /* None (Read Only) */
+
+#define LP3944_REG_PSC0       0x02 /* Frequency Prescaler 0 (R/W) */
+#define LP3944_REG_PWM0       0x03 /* PWM Register 0 (R/W) */
+#define LP3944_REG_PSC1       0x04 /* Frequency Prescaler 1 (R/W) */
+#define LP3944_REG_PWM1       0x05 /* PWM Register 1 (R/W) */
+#define LP3944_REG_LS0        0x06 /* LEDs 0-3 Selector (R/W) */
+#define LP3944_REG_LS1        0x07 /* LEDs 4-7 Selector (R/W) */
+
+/* These registers are not used to control leds in LP3944, they can store
+ * arbitrary values which the chip will ignore.
+ */
+#define LP3944_REG_REGISTER8  0x08
+#define LP3944_REG_REGISTER9  0x09
+
+#define LP3944_DIM0 0
+#define LP3944_DIM1 1
+
+/* period in ms */
+#define LP3944_PERIOD_MIN 0
+#define LP3944_PERIOD_MAX 1600
+
+/* duty cycle is a percentage */
+#define LP3944_DUTY_CYCLE_MIN 0
+#define LP3944_DUTY_CYCLE_MAX 100
+
+#define ldev_to_led(c)       container_of(c, struct lp3944_led_data, ldev)
+
+/* Saved data */
+struct lp3944_led_data {
+	u8 id;
+	enum lp3944_type type;
+	enum lp3944_status status;
+	struct led_classdev ldev;
+	struct i2c_client *client;
+	struct work_struct work;
+};
+
+struct lp3944_data {
+	struct mutex lock;
+	struct i2c_client *client;
+	struct lp3944_led_data leds[LP3944_LEDS_MAX];
+};
+
+static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value)
+{
+	int tmp;
+
+	tmp = i2c_smbus_read_byte_data(client, reg);
+	if (tmp < 0)
+		return -EINVAL;
+
+	*value = tmp;
+
+	return 0;
+}
+
+static int lp3944_reg_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/**
+ * Set the period for DIM status
+ *
+ * @client: the i2c client
+ * @dim: either LP3944_DIM0 or LP3944_DIM1
+ * @period: period of a blink, that is a on/off cycle, expressed in ms.
+ */
+static int lp3944_dim_set_period(struct i2c_client *client, u8 dim, u16 period)
+{
+	u8 psc_reg;
+	u8 psc_value;
+	int err;
+
+	if (dim == LP3944_DIM0)
+		psc_reg = LP3944_REG_PSC0;
+	else if (dim == LP3944_DIM1)
+		psc_reg = LP3944_REG_PSC1;
+	else
+		return -EINVAL;
+
+	/* Convert period to Prescaler value */
+	if (period > LP3944_PERIOD_MAX)
+		return -EINVAL;
+
+	psc_value = (period * 255) / LP3944_PERIOD_MAX;
+
+	err = lp3944_reg_write(client, psc_reg, psc_value);
+
+	return err;
+}
+
+/**
+ * Set the duty cycle for DIM status
+ *
+ * @client: the i2c client
+ * @dim: either LP3944_DIM0 or LP3944_DIM1
+ * @duty_cycle: percentage of a period during which a led is ON
+ */
+static int lp3944_dim_set_dutycycle(struct i2c_client *client, u8 dim,
+				    u8 duty_cycle)
+{
+	u8 pwm_reg;
+	u8 pwm_value;
+	int err;
+
+	if (dim == LP3944_DIM0)
+		pwm_reg = LP3944_REG_PWM0;
+	else if (dim == LP3944_DIM1)
+		pwm_reg = LP3944_REG_PWM1;
+	else
+		return -EINVAL;
+
+	/* Convert duty cycle to PWM value */
+	if (duty_cycle > LP3944_DUTY_CYCLE_MAX)
+		return -EINVAL;
+
+	pwm_value = (duty_cycle * 255) / LP3944_DUTY_CYCLE_MAX;
+
+	err = lp3944_reg_write(client, pwm_reg, pwm_value);
+
+	return err;
+}
+
+/**
+ * Set the led status
+ *
+ * @led: a lp3944_led_data structure
+ * @status: one of LP3944_LED_STATUS_OFF
+ *                 LP3944_LED_STATUS_ON
+ *                 LP3944_LED_STATUS_DIM0
+ *                 LP3944_LED_STATUS_DIM1
+ */
+static int lp3944_led_set(struct lp3944_led_data *led, u8 status)
+{
+	struct lp3944_data *data = i2c_get_clientdata(led->client);
+	u8 id = led->id;
+	u8 reg;
+	u8 val = 0;
+	int err;
+
+	dev_dbg(&led->client->dev, "%s: %s, status before normalization:%d\n",
+		__func__, led->ldev.name, status);
+
+	switch (id) {
+	case LP3944_LED0:
+	case LP3944_LED1:
+	case LP3944_LED2:
+	case LP3944_LED3:
+		reg = LP3944_REG_LS0;
+		break;
+	case LP3944_LED4:
+	case LP3944_LED5:
+	case LP3944_LED6:
+	case LP3944_LED7:
+		id -= LP3944_LED4;
+		reg = LP3944_REG_LS1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (status > LP3944_LED_STATUS_DIM1)
+		return -EINVAL;
+
+	/* invert only 0 and 1, leave unchanged the other values,
+	 * remember we are abusing status to set blink patterns
+	 */
+	if (led->type == LP3944_LED_TYPE_LED_INVERTED && status < 2)
+		status = 1 - status;
+
+	mutex_lock(&data->lock);
+	lp3944_reg_read(led->client, reg, &val);
+
+	val &= ~(LP3944_LED_STATUS_MASK << (id << 1));
+	val |= (status << (id << 1));
+
+	dev_dbg(&led->client->dev, "%s: %s, reg:%d id:%d status:%d val:%#x\n",
+		__func__, led->ldev.name, reg, id, status, val);
+
+	/* set led status */
+	err = lp3944_reg_write(led->client, reg, val);
+	mutex_unlock(&data->lock);
+
+	return err;
+}
+
+static int lp3944_led_set_blink(struct led_classdev *led_cdev,
+				unsigned long *delay_on,
+				unsigned long *delay_off)
+{
+	struct lp3944_led_data *led = ldev_to_led(led_cdev);
+	u16 period;
+	u8 duty_cycle;
+	int err;
+
+	/* units are in ms */
+	if (*delay_on + *delay_off > LP3944_PERIOD_MAX)
+		return -EINVAL;
+
+	if (*delay_on == 0 && *delay_off == 0) {
+		/* Special case: the leds subsystem requires a default user
+		 * friendly blink pattern for the LED.  Let's blink the led
+		 * slowly (1Hz).
+		 */
+		*delay_on = 500;
+		*delay_off = 500;
+	}
+
+	period = (*delay_on) + (*delay_off);
+
+	/* duty_cycle is the percentage of period during which the led is ON */
+	duty_cycle = 100 * (*delay_on) / period;
+
+	/* invert duty cycle for inverted leds, this has the same effect of
+	 * swapping delay_on and delay_off
+	 */
+	if (led->type == LP3944_LED_TYPE_LED_INVERTED)
+		duty_cycle = 100 - duty_cycle;
+
+	/* NOTE: using always the first DIM mode, this means that all leds
+	 * will have the same blinking pattern.
+	 *
+	 * We could find a way later to have two leds blinking in hardware
+	 * with different patterns at the same time, falling back to software
+	 * control for the other ones.
+	 */
+	err = lp3944_dim_set_period(led->client, LP3944_DIM0, period);
+	if (err)
+		return err;
+
+	err = lp3944_dim_set_dutycycle(led->client, LP3944_DIM0, duty_cycle);
+	if (err)
+		return err;
+
+	dev_dbg(&led->client->dev, "%s: OK hardware accelerated blink!\n",
+		__func__);
+
+	led->status = LP3944_LED_STATUS_DIM0;
+	schedule_work(&led->work);
+
+	return 0;
+}
+
+static void lp3944_led_set_brightness(struct led_classdev *led_cdev,
+				      enum led_brightness brightness)
+{
+	struct lp3944_led_data *led = ldev_to_led(led_cdev);
+
+	dev_dbg(&led->client->dev, "%s: %s, %d\n",
+		__func__, led_cdev->name, brightness);
+
+	led->status = brightness;
+	schedule_work(&led->work);
+}
+
+static void lp3944_led_work(struct work_struct *work)
+{
+	struct lp3944_led_data *led;
+
+	led = container_of(work, struct lp3944_led_data, work);
+	lp3944_led_set(led, led->status);
+}
+
+static int lp3944_configure(struct i2c_client *client,
+			    struct lp3944_data *data,
+			    struct lp3944_platform_data *pdata)
+{
+	int i, err = 0;
+
+	for (i = 0; i < pdata->leds_size; i++) {
+		struct lp3944_led *pled = &pdata->leds[i];
+		struct lp3944_led_data *led = &data->leds[i];
+		led->client = client;
+		led->id = i;
+
+		switch (pled->type) {
+
+		case LP3944_LED_TYPE_LED:
+		case LP3944_LED_TYPE_LED_INVERTED:
+			led->type = pled->type;
+			led->status = pled->status;
+			led->ldev.name = pled->name;
+			led->ldev.max_brightness = 1;
+			led->ldev.brightness_set = lp3944_led_set_brightness;
+			led->ldev.blink_set = lp3944_led_set_blink;
+			led->ldev.flags = LED_CORE_SUSPENDRESUME;
+
+			INIT_WORK(&led->work, lp3944_led_work);
+			err = led_classdev_register(&client->dev, &led->ldev);
+			if (err < 0) {
+				dev_err(&client->dev,
+					"couldn't register LED %s\n",
+					led->ldev.name);
+				goto exit;
+			}
+
+			/* to expose the default value to userspace */
+			led->ldev.brightness = led->status;
+
+			/* Set the default led status */
+			err = lp3944_led_set(led, led->status);
+			if (err < 0) {
+				dev_err(&client->dev,
+					"%s couldn't set STATUS %d\n",
+					led->ldev.name, led->status);
+				goto exit;
+			}
+			break;
+
+		case LP3944_LED_TYPE_NONE:
+		default:
+			break;
+
+		}
+	}
+	return 0;
+
+exit:
+	if (i > 0)
+		for (i = i - 1; i >= 0; i--)
+			switch (pdata->leds[i].type) {
+
+			case LP3944_LED_TYPE_LED:
+			case LP3944_LED_TYPE_LED_INVERTED:
+				led_classdev_unregister(&data->leds[i].ldev);
+				cancel_work_sync(&data->leds[i].work);
+				break;
+
+			case LP3944_LED_TYPE_NONE:
+			default:
+				break;
+			}
+
+	return err;
+}
+
+static int __devinit lp3944_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
+	struct lp3944_data *data;
+
+	if (lp3944_pdata == NULL) {
+		dev_err(&client->dev, "no platform data\n");
+		return -EINVAL;
+	}
+
+	/* Let's see whether this adapter can support what we need. */
+	if (!i2c_check_functionality(client->adapter,
+				I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev, "insufficient functionality!\n");
+		return -ENODEV;
+	}
+
+	data = kzalloc(sizeof(struct lp3944_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->client = client;
+	i2c_set_clientdata(client, data);
+
+	mutex_init(&data->lock);
+
+	dev_info(&client->dev, "lp3944 enabled\n");
+
+	lp3944_configure(client, data, lp3944_pdata);
+	return 0;
+}
+
+static int __devexit lp3944_remove(struct i2c_client *client)
+{
+	struct lp3944_platform_data *pdata = client->dev.platform_data;
+	struct lp3944_data *data = i2c_get_clientdata(client);
+	int i;
+
+	for (i = 0; i < pdata->leds_size; i++)
+		switch (data->leds[i].type) {
+		case LP3944_LED_TYPE_LED:
+		case LP3944_LED_TYPE_LED_INVERTED:
+			led_classdev_unregister(&data->leds[i].ldev);
+			cancel_work_sync(&data->leds[i].work);
+			break;
+
+		case LP3944_LED_TYPE_NONE:
+		default:
+			break;
+		}
+
+	kfree(data);
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+/* lp3944 i2c driver struct */
+static const struct i2c_device_id lp3944_id[] = {
+	{"lp3944", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, lp3944_id);
+
+static struct i2c_driver lp3944_driver = {
+	.driver   = {
+		   .name = "lp3944",
+	},
+	.probe    = lp3944_probe,
+	.remove   = __devexit_p(lp3944_remove),
+	.id_table = lp3944_id,
+};
+
+static int __init lp3944_module_init(void)
+{
+	return i2c_add_driver(&lp3944_driver);
+}
+
+static void __exit lp3944_module_exit(void)
+{
+	i2c_del_driver(&lp3944_driver);
+}
+
+module_init(lp3944_module_init);
+module_exit(lp3944_module_exit);
+
+MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
+MODULE_DESCRIPTION("LP3944 Fun Light Chip");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-pca9532.c linux-libre-2.6.31-gnu/drivers/leds/leds-pca9532.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-pca9532.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-pca9532.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,7 @@
 	struct pca9532_led leds[16];
 	struct mutex update_lock;
 	struct input_dev    *idev;
-       struct work_struct work;
+	struct work_struct work;
 	u8 pwm[2];
 	u8 psc[2];
 };
@@ -87,14 +87,14 @@
 	if (b > 0xFF)
 		return -EINVAL;
 	data->pwm[pwm] = b;
-       data->psc[pwm] = blink;
-       return 0;
+	data->psc[pwm] = blink;
+	return 0;
 }
 
 static int pca9532_setpwm(struct i2c_client *client, int pwm)
 {
-       struct pca9532_data *data = i2c_get_clientdata(client);
-       mutex_lock(&data->update_lock);
+	struct pca9532_data *data = i2c_get_clientdata(client);
+	mutex_lock(&data->update_lock);
 	i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm),
 		data->pwm[pwm]);
 	i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm),
@@ -132,11 +132,11 @@
 		led->state = PCA9532_ON;
 	else {
 		led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
-               err = pca9532_calcpwm(led->client, 0, 0, value);
+		err = pca9532_calcpwm(led->client, 0, 0, value);
 		if (err)
 			return; /* XXX: led api doesn't allow error code? */
 	}
-       schedule_work(&led->work);
+	schedule_work(&led->work);
 }
 
 static int pca9532_set_blink(struct led_classdev *led_cdev,
@@ -145,7 +145,7 @@
 	struct pca9532_led *led = ldev_to_led(led_cdev);
 	struct i2c_client *client = led->client;
 	int psc;
-       int err = 0;
+	int err = 0;
 
 	if (*delay_on == 0 && *delay_off == 0) {
 	/* led subsystem ask us for a blink rate */
@@ -157,11 +157,11 @@
 
 	/* Thecus specific: only use PSC/PWM 0 */
 	psc = (*delay_on * 152-1)/1000;
-       err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness);
-       if (err)
-               return err;
-       schedule_work(&led->work);
-       return 0;
+	err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness);
+	if (err)
+		return err;
+	schedule_work(&led->work);
+	return 0;
 }
 
 static int pca9532_event(struct input_dev *dev, unsigned int type,
@@ -178,15 +178,15 @@
 	else
 		data->pwm[1] = 0;
 
-       schedule_work(&data->work);
+	schedule_work(&data->work);
 
-       return 0;
+	return 0;
 }
 
 static void pca9532_input_work(struct work_struct *work)
 {
-       struct pca9532_data *data;
-       data = container_of(work, struct pca9532_data, work);
+	struct pca9532_data *data;
+	data = container_of(work, struct pca9532_data, work);
 	mutex_lock(&data->update_lock);
 	i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1),
 		data->pwm[1]);
@@ -195,11 +195,11 @@
 
 static void pca9532_led_work(struct work_struct *work)
 {
-       struct pca9532_led *led;
-       led = container_of(work, struct pca9532_led, work);
-       if (led->state == PCA9532_PWM0)
-               pca9532_setpwm(led->client, 0);
-       pca9532_setled(led);
+	struct pca9532_led *led;
+	led = container_of(work, struct pca9532_led, work);
+	if (led->state == PCA9532_PWM0)
+		pca9532_setpwm(led->client, 0);
+	pca9532_setled(led);
 }
 
 static int pca9532_configure(struct i2c_client *client,
@@ -232,7 +232,7 @@
 			led->ldev.brightness = LED_OFF;
 			led->ldev.brightness_set = pca9532_set_brightness;
 			led->ldev.blink_set = pca9532_set_blink;
-                       INIT_WORK(&led->work, pca9532_led_work);
+			INIT_WORK(&led->work, pca9532_led_work);
 			err = led_classdev_register(&client->dev, &led->ldev);
 			if (err < 0) {
 				dev_err(&client->dev,
@@ -262,11 +262,11 @@
 						BIT_MASK(SND_TONE);
 			data->idev->event = pca9532_event;
 			input_set_drvdata(data->idev, data);
-                       INIT_WORK(&data->work, pca9532_input_work);
+			INIT_WORK(&data->work, pca9532_input_work);
 			err = input_register_device(data->idev);
 			if (err) {
 				input_free_device(data->idev);
-                               cancel_work_sync(&data->work);
+				cancel_work_sync(&data->work);
 				data->idev = NULL;
 				goto exit;
 			}
@@ -283,13 +283,13 @@
 				break;
 			case PCA9532_TYPE_LED:
 				led_classdev_unregister(&data->leds[i].ldev);
-                               cancel_work_sync(&data->leds[i].work);
+				cancel_work_sync(&data->leds[i].work);
 				break;
 			case PCA9532_TYPE_N2100_BEEP:
 				if (data->idev != NULL) {
 					input_unregister_device(data->idev);
 					input_free_device(data->idev);
-                                       cancel_work_sync(&data->work);
+					cancel_work_sync(&data->work);
 					data->idev = NULL;
 				}
 				break;
@@ -340,13 +340,13 @@
 			break;
 		case PCA9532_TYPE_LED:
 			led_classdev_unregister(&data->leds[i].ldev);
-                       cancel_work_sync(&data->leds[i].work);
+			cancel_work_sync(&data->leds[i].work);
 			break;
 		case PCA9532_TYPE_N2100_BEEP:
 			if (data->idev != NULL) {
 				input_unregister_device(data->idev);
 				input_free_device(data->idev);
-                               cancel_work_sync(&data->work);
+				cancel_work_sync(&data->work);
 				data->idev = NULL;
 			}
 			break;
diff -druN linux-libre-2.6.30-gnu/drivers/leds/leds-s3c24xx.c linux-libre-2.6.31-gnu/drivers/leds/leds-s3c24xx.c
--- linux-libre-2.6.30-gnu/drivers/leds/leds-s3c24xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/leds-s3c24xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
diff -druN linux-libre-2.6.30-gnu/drivers/leds/ledtrig-gpio.c linux-libre-2.6.31-gnu/drivers/leds/ledtrig-gpio.c
--- linux-libre-2.6.30-gnu/drivers/leds/ledtrig-gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/ledtrig-gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -117,6 +117,9 @@
 
 	gpio_data->inverted = !!inverted;
 
+	/* After inverting, we need to update the LED. */
+	schedule_work(&gpio_data->work);
+
 	return n;
 }
 static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show,
@@ -146,20 +149,26 @@
 		return -EINVAL;
 	}
 
+	if (gpio_data->gpio == gpio)
+		return n;
+
 	if (!gpio) {
-		free_irq(gpio_to_irq(gpio_data->gpio), led);
+		if (gpio_data->gpio != 0)
+			free_irq(gpio_to_irq(gpio_data->gpio), led);
+		gpio_data->gpio = 0;
 		return n;
 	}
 
-	if (gpio_data->gpio > 0 && gpio_data->gpio != gpio)
-		free_irq(gpio_to_irq(gpio_data->gpio), led);
-
-	gpio_data->gpio = gpio;
 	ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq,
 			IRQF_SHARED | IRQF_TRIGGER_RISING
 			| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
-	if (ret)
+	if (ret) {
 		dev_err(dev, "request_irq failed with error %d\n", ret);
+	} else {
+		if (gpio_data->gpio != 0)
+			free_irq(gpio_to_irq(gpio_data->gpio), led);
+		gpio_data->gpio = gpio;
+	}
 
 	return ret ? ret : n;
 }
@@ -211,7 +220,8 @@
 		device_remove_file(led->dev, &dev_attr_inverted);
 		device_remove_file(led->dev, &dev_attr_desired_brightness);
 		flush_work(&gpio_data->work);
-		free_irq(gpio_to_irq(gpio_data->gpio),led);
+		if (gpio_data->gpio != 0)
+			free_irq(gpio_to_irq(gpio_data->gpio), led);
 		kfree(gpio_data);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/leds/Makefile linux-libre-2.6.31-gnu/drivers/leds/Makefile
--- linux-libre-2.6.30-gnu/drivers/leds/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/leds/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
 obj-$(CONFIG_LEDS_SUNFIRE)		+= leds-sunfire.o
 obj-$(CONFIG_LEDS_PCA9532)		+= leds-pca9532.o
 obj-$(CONFIG_LEDS_GPIO)			+= leds-gpio.o
+obj-$(CONFIG_LEDS_LP3944)		+= leds-lp3944.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)		+= leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)		+= leds-hp6xx.o
 obj-$(CONFIG_LEDS_FSG)			+= leds-fsg.o
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/core.c linux-libre-2.6.31-gnu/drivers/lguest/core.c
--- linux-libre-2.6.30-gnu/drivers/lguest/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,8 @@
-/*P:400 This contains run_guest() which actually calls into the Host<->Guest
+/*P:400
+ * This contains run_guest() which actually calls into the Host<->Guest
  * Switcher and analyzes the return, such as determining if the Guest wants the
- * Host to do something.  This file also contains useful helper routines. :*/
+ * Host to do something.  This file also contains useful helper routines.
+:*/
 #include <linux/module.h>
 #include <linux/stringify.h>
 #include <linux/stddef.h>
@@ -24,7 +26,8 @@
 /* This One Big lock protects all inter-guest data structures. */
 DEFINE_MUTEX(lguest_lock);
 
-/*H:010 We need to set up the Switcher at a high virtual address.  Remember the
+/*H:010
+ * We need to set up the Switcher at a high virtual address.  Remember the
  * Switcher is a few hundred bytes of assembler code which actually changes the
  * CPU to run the Guest, and then changes back to the Host when a trap or
  * interrupt happens.
@@ -33,7 +36,8 @@
  * Host since it will be running as the switchover occurs.
  *
  * Trying to map memory at a particular address is an unusual thing to do, so
- * it's not a simple one-liner. */
+ * it's not a simple one-liner.
+ */
 static __init int map_switcher(void)
 {
 	int i, err;
@@ -47,8 +51,10 @@
 	 * easy.
 	 */
 
-	/* We allocate an array of struct page pointers.  map_vm_area() wants
-	 * this, rather than just an array of pages. */
+	/*
+	 * We allocate an array of struct page pointers.  map_vm_area() wants
+	 * this, rather than just an array of pages.
+	 */
 	switcher_page = kmalloc(sizeof(switcher_page[0])*TOTAL_SWITCHER_PAGES,
 				GFP_KERNEL);
 	if (!switcher_page) {
@@ -56,8 +62,10 @@
 		goto out;
 	}
 
-	/* Now we actually allocate the pages.  The Guest will see these pages,
-	 * so we make sure they're zeroed. */
+	/*
+	 * Now we actually allocate the pages.  The Guest will see these pages,
+	 * so we make sure they're zeroed.
+	 */
 	for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) {
 		unsigned long addr = get_zeroed_page(GFP_KERNEL);
 		if (!addr) {
@@ -67,19 +75,23 @@
 		switcher_page[i] = virt_to_page(addr);
 	}
 
-	/* First we check that the Switcher won't overlap the fixmap area at
+	/*
+	 * First we check that the Switcher won't overlap the fixmap area at
 	 * the top of memory.  It's currently nowhere near, but it could have
-	 * very strange effects if it ever happened. */
+	 * very strange effects if it ever happened.
+	 */
 	if (SWITCHER_ADDR + (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE > FIXADDR_START){
 		err = -ENOMEM;
 		printk("lguest: mapping switcher would thwack fixmap\n");
 		goto free_pages;
 	}
 
-	/* Now we reserve the "virtual memory area" we want: 0xFFC00000
+	/*
+	 * Now we reserve the "virtual memory area" we want: 0xFFC00000
 	 * (SWITCHER_ADDR).  We might not get it in theory, but in practice
 	 * it's worked so far.  The end address needs +1 because __get_vm_area
-	 * allocates an extra guard page, so we need space for that. */
+	 * allocates an extra guard page, so we need space for that.
+	 */
 	switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
 				     VM_ALLOC, SWITCHER_ADDR, SWITCHER_ADDR
 				     + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
@@ -89,20 +101,24 @@
 		goto free_pages;
 	}
 
-	/* This code actually sets up the pages we've allocated to appear at
+	/*
+	 * This code actually sets up the pages we've allocated to appear at
 	 * SWITCHER_ADDR.  map_vm_area() takes the vma we allocated above, the
 	 * kind of pages we're mapping (kernel pages), and a pointer to our
 	 * array of struct pages.  It increments that pointer, but we don't
-	 * care. */
+	 * care.
+	 */
 	pagep = switcher_page;
-	err = map_vm_area(switcher_vma, PAGE_KERNEL, &pagep);
+	err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, &pagep);
 	if (err) {
 		printk("lguest: map_vm_area failed: %i\n", err);
 		goto free_vma;
 	}
 
-	/* Now the Switcher is mapped at the right address, we can't fail!
-	 * Copy in the compiled-in Switcher code (from <arch>_switcher.S). */
+	/*
+	 * Now the Switcher is mapped at the right address, we can't fail!
+	 * Copy in the compiled-in Switcher code (from <arch>_switcher.S).
+	 */
 	memcpy(switcher_vma->addr, start_switcher_text,
 	       end_switcher_text - start_switcher_text);
 
@@ -124,8 +140,7 @@
 }
 /*:*/
 
-/* Cleaning up the mapping when the module is unloaded is almost...
- * too easy. */
+/* Cleaning up the mapping when the module is unloaded is almost... too easy. */
 static void unmap_switcher(void)
 {
 	unsigned int i;
@@ -151,16 +166,19 @@
  * But we can't trust the Guest: it might be trying to access the Launcher
  * code.  We have to check that the range is below the pfn_limit the Launcher
  * gave us.  We have to make sure that addr + len doesn't give us a false
- * positive by overflowing, too. */
+ * positive by overflowing, too.
+ */
 bool lguest_address_ok(const struct lguest *lg,
 		       unsigned long addr, unsigned long len)
 {
 	return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
 }
 
-/* This routine copies memory from the Guest.  Here we can see how useful the
+/*
+ * This routine copies memory from the Guest.  Here we can see how useful the
  * kill_lguest() routine we met in the Launcher can be: we return a random
- * value (all zeroes) instead of needing to return an error. */
+ * value (all zeroes) instead of needing to return an error.
+ */
 void __lgread(struct lg_cpu *cpu, void *b, unsigned long addr, unsigned bytes)
 {
 	if (!lguest_address_ok(cpu->lg, addr, bytes)
@@ -181,58 +199,87 @@
 }
 /*:*/
 
-/*H:030 Let's jump straight to the the main loop which runs the Guest.
+/*H:030
+ * Let's jump straight to the the main loop which runs the Guest.
  * Remember, this is called by the Launcher reading /dev/lguest, and we keep
- * going around and around until something interesting happens. */
+ * going around and around until something interesting happens.
+ */
 int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
 {
 	/* We stop running once the Guest is dead. */
 	while (!cpu->lg->dead) {
+		unsigned int irq;
+		bool more;
+
 		/* First we run any hypercalls the Guest wants done. */
 		if (cpu->hcall)
 			do_hypercalls(cpu);
 
-		/* It's possible the Guest did a NOTIFY hypercall to the
-		 * Launcher, in which case we return from the read() now. */
+		/*
+		 * It's possible the Guest did a NOTIFY hypercall to the
+		 * Launcher.
+		 */
 		if (cpu->pending_notify) {
-			if (put_user(cpu->pending_notify, user))
-				return -EFAULT;
-			return sizeof(cpu->pending_notify);
+			/*
+			 * Does it just needs to write to a registered
+			 * eventfd (ie. the appropriate virtqueue thread)?
+			 */
+			if (!send_notify_to_eventfd(cpu)) {
+				/* OK, we tell the main Laucher. */
+				if (put_user(cpu->pending_notify, user))
+					return -EFAULT;
+				return sizeof(cpu->pending_notify);
+			}
 		}
 
 		/* Check for signals */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
-		/* If Waker set break_out, return to Launcher. */
-		if (cpu->break_out)
-			return -EAGAIN;
-
-		/* Check if there are any interrupts which can be delivered now:
+		/*
+		 * Check if there are any interrupts which can be delivered now:
 		 * if so, this sets up the hander to be executed when we next
-		 * run the Guest. */
-		maybe_do_interrupt(cpu);
+		 * run the Guest.
+		 */
+		irq = interrupt_pending(cpu, &more);
+		if (irq < LGUEST_IRQS)
+			try_deliver_interrupt(cpu, irq, more);
 
-		/* All long-lived kernel loops need to check with this horrible
+		/*
+		 * All long-lived kernel loops need to check with this horrible
 		 * thing called the freezer.  If the Host is trying to suspend,
-		 * it stops us. */
+		 * it stops us.
+		 */
 		try_to_freeze();
 
-		/* Just make absolutely sure the Guest is still alive.  One of
-		 * those hypercalls could have been fatal, for example. */
+		/*
+		 * Just make absolutely sure the Guest is still alive.  One of
+		 * those hypercalls could have been fatal, for example.
+		 */
 		if (cpu->lg->dead)
 			break;
 
-		/* If the Guest asked to be stopped, we sleep.  The Guest's
-		 * clock timer or LHREQ_BREAK from the Waker will wake us. */
+		/*
+		 * If the Guest asked to be stopped, we sleep.  The Guest's
+		 * clock timer will wake us.
+		 */
 		if (cpu->halted) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule();
+			/*
+			 * Just before we sleep, make sure no interrupt snuck in
+			 * which we should be doing.
+			 */
+			if (interrupt_pending(cpu, &more) < LGUEST_IRQS)
+				set_current_state(TASK_RUNNING);
+			else
+				schedule();
 			continue;
 		}
 
-		/* OK, now we're ready to jump into the Guest.  First we put up
-		 * the "Do Not Disturb" sign: */
+		/*
+		 * OK, now we're ready to jump into the Guest.  First we put up
+		 * the "Do Not Disturb" sign:
+		 */
 		local_irq_disable();
 
 		/* Actually run the Guest until something happens. */
@@ -319,8 +366,10 @@
 }
 /*:*/
 
-/* The Host side of lguest can be a module.  This is a nice way for people to
- * play with it.  */
+/*
+ * The Host side of lguest can be a module.  This is a nice way for people to
+ * play with it.
+ */
 module_init(init);
 module_exit(fini);
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/hypercalls.c linux-libre-2.6.31-gnu/drivers/lguest/hypercalls.c
--- linux-libre-2.6.30-gnu/drivers/lguest/hypercalls.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/hypercalls.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,10 @@
-/*P:500 Just as userspace programs request kernel operations through a system
+/*P:500
+ * Just as userspace programs request kernel operations through a system
  * call, the Guest requests Host operations through a "hypercall".  You might
  * notice this nomenclature doesn't really follow any logic, but the name has
  * been around for long enough that we're stuck with it.  As you'd expect, this
- * code is basically a one big switch statement. :*/
+ * code is basically a one big switch statement.
+:*/
 
 /*  Copyright (C) 2006 Rusty Russell IBM Corporation
 
@@ -28,26 +30,41 @@
 #include <asm/pgtable.h>
 #include "lg.h"
 
-/*H:120 This is the core hypercall routine: where the Guest gets what it wants.
- * Or gets killed.  Or, in the case of LHCALL_SHUTDOWN, both. */
+/*H:120
+ * This is the core hypercall routine: where the Guest gets what it wants.
+ * Or gets killed.  Or, in the case of LHCALL_SHUTDOWN, both.
+ */
 static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
 {
 	switch (args->arg0) {
 	case LHCALL_FLUSH_ASYNC:
-		/* This call does nothing, except by breaking out of the Guest
-		 * it makes us process all the asynchronous hypercalls. */
+		/*
+		 * This call does nothing, except by breaking out of the Guest
+		 * it makes us process all the asynchronous hypercalls.
+		 */
+		break;
+	case LHCALL_SEND_INTERRUPTS:
+		/*
+		 * This call does nothing too, but by breaking out of the Guest
+		 * it makes us process any pending interrupts.
+		 */
 		break;
 	case LHCALL_LGUEST_INIT:
-		/* You can't get here unless you're already initialized.  Don't
-		 * do that. */
+		/*
+		 * You can't get here unless you're already initialized.  Don't
+		 * do that.
+		 */
 		kill_guest(cpu, "already have lguest_data");
 		break;
 	case LHCALL_SHUTDOWN: {
-		/* Shutdown is such a trivial hypercall that we do it in four
-		 * lines right here. */
 		char msg[128];
-		/* If the lgread fails, it will call kill_guest() itself; the
-		 * kill_guest() with the message will be ignored. */
+		/*
+		 * Shutdown is such a trivial hypercall that we do it in five
+		 * lines right here.
+		 *
+		 * If the lgread fails, it will call kill_guest() itself; the
+		 * kill_guest() with the message will be ignored.
+		 */
 		__lgread(cpu, msg, args->arg1, sizeof(msg));
 		msg[sizeof(msg)-1] = '\0';
 		kill_guest(cpu, "CRASH: %s", msg);
@@ -56,16 +73,17 @@
 		break;
 	}
 	case LHCALL_FLUSH_TLB:
-		/* FLUSH_TLB comes in two flavors, depending on the
-		 * argument: */
+		/* FLUSH_TLB comes in two flavors, depending on the argument: */
 		if (args->arg1)
 			guest_pagetable_clear_all(cpu);
 		else
 			guest_pagetable_flush_user(cpu);
 		break;
 
-	/* All these calls simply pass the arguments through to the right
-	 * routines. */
+	/*
+	 * All these calls simply pass the arguments through to the right
+	 * routines.
+	 */
 	case LHCALL_NEW_PGTABLE:
 		guest_new_pagetable(cpu, args->arg1);
 		break;
@@ -73,11 +91,21 @@
 		guest_set_stack(cpu, args->arg1, args->arg2, args->arg3);
 		break;
 	case LHCALL_SET_PTE:
+#ifdef CONFIG_X86_PAE
+		guest_set_pte(cpu, args->arg1, args->arg2,
+				__pte(args->arg3 | (u64)args->arg4 << 32));
+#else
 		guest_set_pte(cpu, args->arg1, args->arg2, __pte(args->arg3));
+#endif
 		break;
+	case LHCALL_SET_PGD:
+		guest_set_pgd(cpu->lg, args->arg1, args->arg2);
+		break;
+#ifdef CONFIG_X86_PAE
 	case LHCALL_SET_PMD:
 		guest_set_pmd(cpu->lg, args->arg1, args->arg2);
 		break;
+#endif
 	case LHCALL_SET_CLOCKEVENT:
 		guest_set_clockevent(cpu, args->arg1);
 		break;
@@ -98,15 +126,16 @@
 			kill_guest(cpu, "Bad hypercall %li\n", args->arg0);
 	}
 }
-/*:*/
 
-/*H:124 Asynchronous hypercalls are easy: we just look in the array in the
+/*H:124
+ * Asynchronous hypercalls are easy: we just look in the array in the
  * Guest's "struct lguest_data" to see if any new ones are marked "ready".
  *
  * We are careful to do these in order: obviously we respect the order the
  * Guest put them in the ring, but we also promise the Guest that they will
  * happen before any normal hypercall (which is why we check this before
- * checking for a normal hcall). */
+ * checking for a normal hcall).
+ */
 static void do_async_hcalls(struct lg_cpu *cpu)
 {
 	unsigned int i;
@@ -119,22 +148,28 @@
 	/* We process "struct lguest_data"s hcalls[] ring once. */
 	for (i = 0; i < ARRAY_SIZE(st); i++) {
 		struct hcall_args args;
-		/* We remember where we were up to from last time.  This makes
+		/*
+		 * We remember where we were up to from last time.  This makes
 		 * sure that the hypercalls are done in the order the Guest
-		 * places them in the ring. */
+		 * places them in the ring.
+		 */
 		unsigned int n = cpu->next_hcall;
 
 		/* 0xFF means there's no call here (yet). */
 		if (st[n] == 0xFF)
 			break;
 
-		/* OK, we have hypercall.  Increment the "next_hcall" cursor,
-		 * and wrap back to 0 if we reach the end. */
+		/*
+		 * OK, we have hypercall.  Increment the "next_hcall" cursor,
+		 * and wrap back to 0 if we reach the end.
+		 */
 		if (++cpu->next_hcall == LHCALL_RING_SIZE)
 			cpu->next_hcall = 0;
 
-		/* Copy the hypercall arguments into a local copy of
-		 * the hcall_args struct. */
+		/*
+		 * Copy the hypercall arguments into a local copy of the
+		 * hcall_args struct.
+		 */
 		if (copy_from_user(&args, &cpu->lg->lguest_data->hcalls[n],
 				   sizeof(struct hcall_args))) {
 			kill_guest(cpu, "Fetching async hypercalls");
@@ -150,19 +185,25 @@
 			break;
 		}
 
-		/* Stop doing hypercalls if they want to notify the Launcher:
-		 * it needs to service this first. */
+		/*
+		 * Stop doing hypercalls if they want to notify the Launcher:
+		 * it needs to service this first.
+		 */
 		if (cpu->pending_notify)
 			break;
 	}
 }
 
-/* Last of all, we look at what happens first of all.  The very first time the
- * Guest makes a hypercall, we end up here to set things up: */
+/*
+ * Last of all, we look at what happens first of all.  The very first time the
+ * Guest makes a hypercall, we end up here to set things up:
+ */
 static void initialize(struct lg_cpu *cpu)
 {
-	/* You can't do anything until you're initialized.  The Guest knows the
-	 * rules, so we're unforgiving here. */
+	/*
+	 * You can't do anything until you're initialized.  The Guest knows the
+	 * rules, so we're unforgiving here.
+	 */
 	if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) {
 		kill_guest(cpu, "hypercall %li before INIT", cpu->hcall->arg0);
 		return;
@@ -171,32 +212,44 @@
 	if (lguest_arch_init_hypercalls(cpu))
 		kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
 
-	/* The Guest tells us where we're not to deliver interrupts by putting
-	 * the range of addresses into "struct lguest_data". */
+	/*
+	 * The Guest tells us where we're not to deliver interrupts by putting
+	 * the range of addresses into "struct lguest_data".
+	 */
 	if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start)
 	    || get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end))
 		kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
 
-	/* We write the current time into the Guest's data page once so it can
-	 * set its clock. */
+	/*
+	 * We write the current time into the Guest's data page once so it can
+	 * set its clock.
+	 */
 	write_timestamp(cpu);
 
 	/* page_tables.c will also do some setup. */
 	page_table_guest_data_init(cpu);
 
-	/* This is the one case where the above accesses might have been the
+	/*
+	 * This is the one case where the above accesses might have been the
 	 * first write to a Guest page.  This may have caused a copy-on-write
 	 * fault, but the old page might be (read-only) in the Guest
-	 * pagetable. */
+	 * pagetable.
+	 */
 	guest_pagetable_clear_all(cpu);
 }
 /*:*/
 
-/*M:013 If a Guest reads from a page (so creates a mapping) that it has never
+/*M:013
+ * If a Guest reads from a page (so creates a mapping) that it has never
  * written to, and then the Launcher writes to it (ie. the output of a virtual
  * device), the Guest will still see the old page.  In practice, this never
  * happens: why would the Guest read a page which it has never written to?  But
- * a similar scenario might one day bite us, so it's worth mentioning. :*/
+ * a similar scenario might one day bite us, so it's worth mentioning.
+ *
+ * Note that if we used a shared anonymous mapping in the Launcher instead of
+ * mapping /dev/zero private, we wouldn't worry about cop-on-write.  And we
+ * need that to switch the Launcher to processes (away from threads) anyway.
+:*/
 
 /*H:100
  * Hypercalls
@@ -215,17 +268,22 @@
 		return;
 	}
 
-	/* The Guest has initialized.
+	/*
+	 * The Guest has initialized.
 	 *
-	 * Look in the hypercall ring for the async hypercalls: */
+	 * Look in the hypercall ring for the async hypercalls:
+	 */
 	do_async_hcalls(cpu);
 
-	/* If we stopped reading the hypercall ring because the Guest did a
+	/*
+	 * If we stopped reading the hypercall ring because the Guest did a
 	 * NOTIFY to the Launcher, we want to return now.  Otherwise we do
-	 * the hypercall. */
+	 * the hypercall.
+	 */
 	if (!cpu->pending_notify) {
 		do_hcall(cpu, cpu->hcall);
-		/* Tricky point: we reset the hcall pointer to mark the
+		/*
+		 * Tricky point: we reset the hcall pointer to mark the
 		 * hypercall as "done".  We use the hcall pointer rather than
 		 * the trap number to indicate a hypercall is pending.
 		 * Normally it doesn't matter: the Guest will run again and
@@ -234,13 +292,16 @@
 		 * However, if we are signalled or the Guest sends I/O to the
 		 * Launcher, the run_guest() loop will exit without running the
 		 * Guest.  When it comes back it would try to re-run the
-		 * hypercall.  Finding that bug sucked. */
+		 * hypercall.  Finding that bug sucked.
+		 */
 		cpu->hcall = NULL;
 	}
 }
 
-/* This routine supplies the Guest with time: it's used for wallclock time at
- * initial boot and as a rough time source if the TSC isn't available. */
+/*
+ * This routine supplies the Guest with time: it's used for wallclock time at
+ * initial boot and as a rough time source if the TSC isn't available.
+ */
 void write_timestamp(struct lg_cpu *cpu)
 {
 	struct timespec now;
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/interrupts_and_traps.c linux-libre-2.6.31-gnu/drivers/lguest/interrupts_and_traps.c
--- linux-libre-2.6.30-gnu/drivers/lguest/interrupts_and_traps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/interrupts_and_traps.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,5 @@
-/*P:800 Interrupts (traps) are complicated enough to earn their own file.
+/*P:800
+ * Interrupts (traps) are complicated enough to earn their own file.
  * There are three classes of interrupts:
  *
  * 1) Real hardware interrupts which occur while we're running the Guest,
@@ -10,7 +11,8 @@
  * just like real hardware would deliver them.  Traps from the Guest can be set
  * up to go directly back into the Guest, but sometimes the Host wants to see
  * them first, so we also have a way of "reflecting" them into the Guest as if
- * they had been delivered to it directly. :*/
+ * they had been delivered to it directly.
+:*/
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -26,8 +28,10 @@
 	return (lo & 0x0000FFFF) | (hi & 0xFFFF0000);
 }
 
-/* The "type" of the interrupt handler is a 4 bit field: we only support a
- * couple of types. */
+/*
+ * The "type" of the interrupt handler is a 4 bit field: we only support a
+ * couple of types.
+ */
 static int idt_type(u32 lo, u32 hi)
 {
 	return (hi >> 8) & 0xF;
@@ -39,8 +43,10 @@
 	return (hi & 0x8000);
 }
 
-/* We need a helper to "push" a value onto the Guest's stack, since that's a
- * big part of what delivering an interrupt does. */
+/*
+ * We need a helper to "push" a value onto the Guest's stack, since that's a
+ * big part of what delivering an interrupt does.
+ */
 static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
 {
 	/* Stack grows upwards: move stack then write value. */
@@ -48,7 +54,8 @@
 	lgwrite(cpu, *gstack, u32, val);
 }
 
-/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or
+/*H:210
+ * The set_guest_interrupt() routine actually delivers the interrupt or
  * trap.  The mechanics of delivering traps and interrupts to the Guest are the
  * same, except some traps have an "error code" which gets pushed onto the
  * stack as well: the caller tells us if this is one.
@@ -59,7 +66,8 @@
  *
  * We set up the stack just like the CPU does for a real interrupt, so it's
  * identical for the Guest (and the standard "iret" instruction will undo
- * it). */
+ * it).
+ */
 static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
 				bool has_err)
 {
@@ -67,20 +75,26 @@
 	u32 eflags, ss, irq_enable;
 	unsigned long virtstack;
 
-	/* There are two cases for interrupts: one where the Guest is already
+	/*
+	 * There are two cases for interrupts: one where the Guest is already
 	 * in the kernel, and a more complex one where the Guest is in
-	 * userspace.  We check the privilege level to find out. */
+	 * userspace.  We check the privilege level to find out.
+	 */
 	if ((cpu->regs->ss&0x3) != GUEST_PL) {
-		/* The Guest told us their kernel stack with the SET_STACK
-		 * hypercall: both the virtual address and the segment */
+		/*
+		 * The Guest told us their kernel stack with the SET_STACK
+		 * hypercall: both the virtual address and the segment.
+		 */
 		virtstack = cpu->esp1;
 		ss = cpu->ss1;
 
 		origstack = gstack = guest_pa(cpu, virtstack);
-		/* We push the old stack segment and pointer onto the new
+		/*
+		 * We push the old stack segment and pointer onto the new
 		 * stack: when the Guest does an "iret" back from the interrupt
 		 * handler the CPU will notice they're dropping privilege
-		 * levels and expect these here. */
+		 * levels and expect these here.
+		 */
 		push_guest_stack(cpu, &gstack, cpu->regs->ss);
 		push_guest_stack(cpu, &gstack, cpu->regs->esp);
 	} else {
@@ -91,18 +105,22 @@
 		origstack = gstack = guest_pa(cpu, virtstack);
 	}
 
-	/* Remember that we never let the Guest actually disable interrupts, so
+	/*
+	 * Remember that we never let the Guest actually disable interrupts, so
 	 * the "Interrupt Flag" bit is always set.  We copy that bit from the
 	 * Guest's "irq_enabled" field into the eflags word: we saw the Guest
-	 * copy it back in "lguest_iret". */
+	 * copy it back in "lguest_iret".
+	 */
 	eflags = cpu->regs->eflags;
 	if (get_user(irq_enable, &cpu->lg->lguest_data->irq_enabled) == 0
 	    && !(irq_enable & X86_EFLAGS_IF))
 		eflags &= ~X86_EFLAGS_IF;
 
-	/* An interrupt is expected to push three things on the stack: the old
+	/*
+	 * An interrupt is expected to push three things on the stack: the old
 	 * "eflags" word, the old code segment, and the old instruction
-	 * pointer. */
+	 * pointer.
+	 */
 	push_guest_stack(cpu, &gstack, eflags);
 	push_guest_stack(cpu, &gstack, cpu->regs->cs);
 	push_guest_stack(cpu, &gstack, cpu->regs->eip);
@@ -111,15 +129,19 @@
 	if (has_err)
 		push_guest_stack(cpu, &gstack, cpu->regs->errcode);
 
-	/* Now we've pushed all the old state, we change the stack, the code
-	 * segment and the address to execute. */
+	/*
+	 * Now we've pushed all the old state, we change the stack, the code
+	 * segment and the address to execute.
+	 */
 	cpu->regs->ss = ss;
 	cpu->regs->esp = virtstack + (gstack - origstack);
 	cpu->regs->cs = (__KERNEL_CS|GUEST_PL);
 	cpu->regs->eip = idt_address(lo, hi);
 
-	/* There are two kinds of interrupt handlers: 0xE is an "interrupt
-	 * gate" which expects interrupts to be disabled on entry. */
+	/*
+	 * There are two kinds of interrupt handlers: 0xE is an "interrupt
+	 * gate" which expects interrupts to be disabled on entry.
+	 */
 	if (idt_type(lo, hi) == 0xE)
 		if (put_user(0, &cpu->lg->lguest_data->irq_enabled))
 			kill_guest(cpu, "Disabling interrupts");
@@ -128,33 +150,49 @@
 /*H:205
  * Virtual Interrupts.
  *
- * maybe_do_interrupt() gets called before every entry to the Guest, to see if
- * we should divert the Guest to running an interrupt handler. */
-void maybe_do_interrupt(struct lg_cpu *cpu)
+ * interrupt_pending() returns the first pending interrupt which isn't blocked
+ * by the Guest.  It is called before every entry to the Guest, and just before
+ * we go to sleep when the Guest has halted itself.
+ */
+unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more)
 {
 	unsigned int irq;
 	DECLARE_BITMAP(blk, LGUEST_IRQS);
-	struct desc_struct *idt;
 
 	/* If the Guest hasn't even initialized yet, we can do nothing. */
 	if (!cpu->lg->lguest_data)
-		return;
+		return LGUEST_IRQS;
 
-	/* Take our "irqs_pending" array and remove any interrupts the Guest
-	 * wants blocked: the result ends up in "blk". */
+	/*
+	 * Take our "irqs_pending" array and remove any interrupts the Guest
+	 * wants blocked: the result ends up in "blk".
+	 */
 	if (copy_from_user(&blk, cpu->lg->lguest_data->blocked_interrupts,
 			   sizeof(blk)))
-		return;
+		return LGUEST_IRQS;
 	bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS);
 
 	/* Find the first interrupt. */
 	irq = find_first_bit(blk, LGUEST_IRQS);
-	/* None?  Nothing to do */
-	if (irq >= LGUEST_IRQS)
-		return;
+	*more = find_next_bit(blk, LGUEST_IRQS, irq+1);
 
-	/* They may be in the middle of an iret, where they asked us never to
-	 * deliver interrupts. */
+	return irq;
+}
+
+/*
+ * This actually diverts the Guest to running an interrupt handler, once an
+ * interrupt has been identified by interrupt_pending().
+ */
+void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
+{
+	struct desc_struct *idt;
+
+	BUG_ON(irq >= LGUEST_IRQS);
+
+	/*
+	 * They may be in the middle of an iret, where they asked us never to
+	 * deliver interrupts.
+	 */
 	if (cpu->regs->eip >= cpu->lg->noirq_start &&
 	   (cpu->regs->eip < cpu->lg->noirq_end))
 		return;
@@ -170,39 +208,75 @@
 		u32 irq_enabled;
 		if (get_user(irq_enabled, &cpu->lg->lguest_data->irq_enabled))
 			irq_enabled = 0;
-		if (!irq_enabled)
+		if (!irq_enabled) {
+			/* Make sure they know an IRQ is pending. */
+			put_user(X86_EFLAGS_IF,
+				 &cpu->lg->lguest_data->irq_pending);
 			return;
+		}
 	}
 
-	/* Look at the IDT entry the Guest gave us for this interrupt.  The
+	/*
+	 * Look at the IDT entry the Guest gave us for this interrupt.  The
 	 * first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip
-	 * over them. */
+	 * over them.
+	 */
 	idt = &cpu->arch.idt[FIRST_EXTERNAL_VECTOR+irq];
 	/* If they don't have a handler (yet?), we just ignore it */
 	if (idt_present(idt->a, idt->b)) {
 		/* OK, mark it no longer pending and deliver it. */
 		clear_bit(irq, cpu->irqs_pending);
-		/* set_guest_interrupt() takes the interrupt descriptor and a
+		/*
+		 * set_guest_interrupt() takes the interrupt descriptor and a
 		 * flag to say whether this interrupt pushes an error code onto
-		 * the stack as well: virtual interrupts never do. */
+		 * the stack as well: virtual interrupts never do.
+		 */
 		set_guest_interrupt(cpu, idt->a, idt->b, false);
 	}
 
-	/* Every time we deliver an interrupt, we update the timestamp in the
+	/*
+	 * Every time we deliver an interrupt, we update the timestamp in the
 	 * Guest's lguest_data struct.  It would be better for the Guest if we
 	 * did this more often, but it can actually be quite slow: doing it
 	 * here is a compromise which means at least it gets updated every
-	 * timer interrupt. */
+	 * timer interrupt.
+	 */
 	write_timestamp(cpu);
+
+	/*
+	 * If there are no other interrupts we want to deliver, clear
+	 * the pending flag.
+	 */
+	if (!more)
+		put_user(0, &cpu->lg->lguest_data->irq_pending);
+}
+
+/* And this is the routine when we want to set an interrupt for the Guest. */
+void set_interrupt(struct lg_cpu *cpu, unsigned int irq)
+{
+	/*
+	 * Next time the Guest runs, the core code will see if it can deliver
+	 * this interrupt.
+	 */
+	set_bit(irq, cpu->irqs_pending);
+
+	/*
+	 * Make sure it sees it; it might be asleep (eg. halted), or running
+	 * the Guest right now, in which case kick_process() will knock it out.
+	 */
+	if (!wake_up_process(cpu->tsk))
+		kick_process(cpu->tsk);
 }
 /*:*/
 
-/* Linux uses trap 128 for system calls.  Plan9 uses 64, and Ron Minnich sent
+/*
+ * Linux uses trap 128 for system calls.  Plan9 uses 64, and Ron Minnich sent
  * me a patch, so we support that too.  It'd be a big step for lguest if half
  * the Plan 9 user base were to start using it.
  *
  * Actually now I think of it, it's possible that Ron *is* half the Plan 9
- * userbase.  Oh well. */
+ * userbase.  Oh well.
+ */
 static bool could_be_syscall(unsigned int num)
 {
 	/* Normal Linux SYSCALL_VECTOR or reserved vector? */
@@ -242,9 +316,11 @@
 		clear_bit(syscall_vector, used_vectors);
 }
 
-/*H:220 Now we've got the routines to deliver interrupts, delivering traps like
+/*H:220
+ * Now we've got the routines to deliver interrupts, delivering traps like
  * page fault is easy.  The only trick is that Intel decided that some traps
- * should have error codes: */
+ * should have error codes:
+ */
 static bool has_err(unsigned int trap)
 {
 	return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17);
@@ -253,13 +329,17 @@
 /* deliver_trap() returns true if it could deliver the trap. */
 bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
 {
-	/* Trap numbers are always 8 bit, but we set an impossible trap number
-	 * for traps inside the Switcher, so check that here. */
+	/*
+	 * Trap numbers are always 8 bit, but we set an impossible trap number
+	 * for traps inside the Switcher, so check that here.
+	 */
 	if (num >= ARRAY_SIZE(cpu->arch.idt))
 		return false;
 
-	/* Early on the Guest hasn't set the IDT entries (or maybe it put a
-	 * bogus one in): if we fail here, the Guest will be killed. */
+	/*
+	 * Early on the Guest hasn't set the IDT entries (or maybe it put a
+	 * bogus one in): if we fail here, the Guest will be killed.
+	 */
 	if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b))
 		return false;
 	set_guest_interrupt(cpu, cpu->arch.idt[num].a,
@@ -267,7 +347,8 @@
 	return true;
 }
 
-/*H:250 Here's the hard part: returning to the Host every time a trap happens
+/*H:250
+ * Here's the hard part: returning to the Host every time a trap happens
  * and then calling deliver_trap() and re-entering the Guest is slow.
  * Particularly because Guest userspace system calls are traps (usually trap
  * 128).
@@ -279,69 +360,87 @@
  * the other hypervisors would beat it up at lunchtime.
  *
  * This routine indicates if a particular trap number could be delivered
- * directly. */
+ * directly.
+ */
 static bool direct_trap(unsigned int num)
 {
-	/* Hardware interrupts don't go to the Guest at all (except system
-	 * call). */
+	/*
+	 * Hardware interrupts don't go to the Guest at all (except system
+	 * call).
+	 */
 	if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num))
 		return false;
 
-	/* The Host needs to see page faults (for shadow paging and to save the
+	/*
+	 * The Host needs to see page faults (for shadow paging and to save the
 	 * fault address), general protection faults (in/out emulation) and
 	 * device not available (TS handling), invalid opcode fault (kvm hcall),
-	 * and of course, the hypercall trap. */
+	 * and of course, the hypercall trap.
+	 */
 	return num != 14 && num != 13 && num != 7 &&
 			num != 6 && num != LGUEST_TRAP_ENTRY;
 }
 /*:*/
 
-/*M:005 The Guest has the ability to turn its interrupt gates into trap gates,
+/*M:005
+ * The Guest has the ability to turn its interrupt gates into trap gates,
  * if it is careful.  The Host will let trap gates can go directly to the
  * Guest, but the Guest needs the interrupts atomically disabled for an
  * interrupt gate.  It can do this by pointing the trap gate at instructions
- * within noirq_start and noirq_end, where it can safely disable interrupts. */
+ * within noirq_start and noirq_end, where it can safely disable interrupts.
+ */
 
-/*M:006 The Guests do not use the sysenter (fast system call) instruction,
+/*M:006
+ * The Guests do not use the sysenter (fast system call) instruction,
  * because it's hardcoded to enter privilege level 0 and so can't go direct.
  * It's about twice as fast as the older "int 0x80" system call, so it might
  * still be worthwhile to handle it in the Switcher and lcall down to the
  * Guest.  The sysenter semantics are hairy tho: search for that keyword in
- * entry.S :*/
+ * entry.S
+:*/
 
-/*H:260 When we make traps go directly into the Guest, we need to make sure
+/*H:260
+ * When we make traps go directly into the Guest, we need to make sure
  * the kernel stack is valid (ie. mapped in the page tables).  Otherwise, the
  * CPU trying to deliver the trap will fault while trying to push the interrupt
  * words on the stack: this is called a double fault, and it forces us to kill
  * the Guest.
  *
- * Which is deeply unfair, because (literally!) it wasn't the Guests' fault. */
+ * Which is deeply unfair, because (literally!) it wasn't the Guests' fault.
+ */
 void pin_stack_pages(struct lg_cpu *cpu)
 {
 	unsigned int i;
 
-	/* Depending on the CONFIG_4KSTACKS option, the Guest can have one or
-	 * two pages of stack space. */
+	/*
+	 * Depending on the CONFIG_4KSTACKS option, the Guest can have one or
+	 * two pages of stack space.
+	 */
 	for (i = 0; i < cpu->lg->stack_pages; i++)
-		/* The stack grows *upwards*, so the address we're given is the
+		/*
+		 * The stack grows *upwards*, so the address we're given is the
 		 * start of the page after the kernel stack.  Subtract one to
 		 * get back onto the first stack page, and keep subtracting to
-		 * get to the rest of the stack pages. */
+		 * get to the rest of the stack pages.
+		 */
 		pin_page(cpu, cpu->esp1 - 1 - i * PAGE_SIZE);
 }
 
-/* Direct traps also mean that we need to know whenever the Guest wants to use
+/*
+ * Direct traps also mean that we need to know whenever the Guest wants to use
  * a different kernel stack, so we can change the IDT entries to use that
  * stack.  The IDT entries expect a virtual address, so unlike most addresses
  * the Guest gives us, the "esp" (stack pointer) value here is virtual, not
  * physical.
  *
  * In Linux each process has its own kernel stack, so this happens a lot: we
- * change stacks on each context switch. */
+ * change stacks on each context switch.
+ */
 void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages)
 {
-	/* You are not allowed have a stack segment with privilege level 0: bad
-	 * Guest! */
+	/*
+	 * You're not allowed a stack segment with privilege level 0: bad Guest!
+	 */
 	if ((seg & 0x3) != GUEST_PL)
 		kill_guest(cpu, "bad stack segment %i", seg);
 	/* We only expect one or two stack pages. */
@@ -355,11 +454,15 @@
 	pin_stack_pages(cpu);
 }
 
-/* All this reference to mapping stacks leads us neatly into the other complex
- * part of the Host: page table handling. */
+/*
+ * All this reference to mapping stacks leads us neatly into the other complex
+ * part of the Host: page table handling.
+ */
 
-/*H:235 This is the routine which actually checks the Guest's IDT entry and
- * transfers it into the entry in "struct lguest": */
+/*H:235
+ * This is the routine which actually checks the Guest's IDT entry and
+ * transfers it into the entry in "struct lguest":
+ */
 static void set_trap(struct lg_cpu *cpu, struct desc_struct *trap,
 		     unsigned int num, u32 lo, u32 hi)
 {
@@ -375,30 +478,38 @@
 	if (type != 0xE && type != 0xF)
 		kill_guest(cpu, "bad IDT type %i", type);
 
-	/* We only copy the handler address, present bit, privilege level and
+	/*
+	 * We only copy the handler address, present bit, privilege level and
 	 * type.  The privilege level controls where the trap can be triggered
 	 * manually with an "int" instruction.  This is usually GUEST_PL,
-	 * except for system calls which userspace can use. */
+	 * except for system calls which userspace can use.
+	 */
 	trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF);
 	trap->b = (hi&0xFFFFEF00);
 }
 
-/*H:230 While we're here, dealing with delivering traps and interrupts to the
+/*H:230
+ * While we're here, dealing with delivering traps and interrupts to the
  * Guest, we might as well complete the picture: how the Guest tells us where
  * it wants them to go.  This would be simple, except making traps fast
  * requires some tricks.
  *
  * We saw the Guest setting Interrupt Descriptor Table (IDT) entries with the
- * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here. */
+ * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here.
+ */
 void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
 {
-	/* Guest never handles: NMI, doublefault, spurious interrupt or
-	 * hypercall.  We ignore when it tries to set them. */
+	/*
+	 * Guest never handles: NMI, doublefault, spurious interrupt or
+	 * hypercall.  We ignore when it tries to set them.
+	 */
 	if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY)
 		return;
 
-	/* Mark the IDT as changed: next time the Guest runs we'll know we have
-	 * to copy this again. */
+	/*
+	 * Mark the IDT as changed: next time the Guest runs we'll know we have
+	 * to copy this again.
+	 */
 	cpu->changed |= CHANGED_IDT;
 
 	/* Check that the Guest doesn't try to step outside the bounds. */
@@ -408,9 +519,11 @@
 		set_trap(cpu, &cpu->arch.idt[num], num, lo, hi);
 }
 
-/* The default entry for each interrupt points into the Switcher routines which
+/*
+ * The default entry for each interrupt points into the Switcher routines which
  * simply return to the Host.  The run_guest() loop will then call
- * deliver_trap() to bounce it back into the Guest. */
+ * deliver_trap() to bounce it back into the Guest.
+ */
 static void default_idt_entry(struct desc_struct *idt,
 			      int trap,
 			      const unsigned long handler,
@@ -419,13 +532,17 @@
 	/* A present interrupt gate. */
 	u32 flags = 0x8e00;
 
-	/* Set the privilege level on the entry for the hypercall: this allows
-	 * the Guest to use the "int" instruction to trigger it. */
+	/*
+	 * Set the privilege level on the entry for the hypercall: this allows
+	 * the Guest to use the "int" instruction to trigger it.
+	 */
 	if (trap == LGUEST_TRAP_ENTRY)
 		flags |= (GUEST_PL << 13);
 	else if (base)
-		/* Copy priv. level from what Guest asked for.  This allows
-		 * debug (int 3) traps from Guest userspace, for example. */
+		/*
+		 * Copy privilege level from what Guest asked for.  This allows
+		 * debug (int 3) traps from Guest userspace, for example.
+		 */
 		flags |= (base->b & 0x6000);
 
 	/* Now pack it into the IDT entry in its weird format. */
@@ -443,16 +560,20 @@
 		default_idt_entry(&state->guest_idt[i], i, def[i], NULL);
 }
 
-/*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
+/*H:240
+ * We don't use the IDT entries in the "struct lguest" directly, instead
  * we copy them into the IDT which we've set up for Guests on this CPU, just
- * before we run the Guest.  This routine does that copy. */
+ * before we run the Guest.  This routine does that copy.
+ */
 void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
 		const unsigned long *def)
 {
 	unsigned int i;
 
-	/* We can simply copy the direct traps, otherwise we use the default
-	 * ones in the Switcher: they will return to the Host. */
+	/*
+	 * We can simply copy the direct traps, otherwise we use the default
+	 * ones in the Switcher: they will return to the Host.
+	 */
 	for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) {
 		const struct desc_struct *gidt = &cpu->arch.idt[i];
 
@@ -460,14 +581,16 @@
 		if (!direct_trap(i))
 			continue;
 
-		/* Only trap gates (type 15) can go direct to the Guest.
+		/*
+		 * Only trap gates (type 15) can go direct to the Guest.
 		 * Interrupt gates (type 14) disable interrupts as they are
 		 * entered, which we never let the Guest do.  Not present
 		 * entries (type 0x0) also can't go direct, of course.
 		 *
 		 * If it can't go direct, we still need to copy the priv. level:
 		 * they might want to give userspace access to a software
-		 * interrupt. */
+		 * interrupt.
+		 */
 		if (idt_type(gidt->a, gidt->b) == 0xF)
 			idt[i] = *gidt;
 		else
@@ -486,7 +609,8 @@
  * the next timer interrupt (in nanoseconds).  We use the high-resolution timer
  * infrastructure to set a callback at that time.
  *
- * 0 means "turn off the clock". */
+ * 0 means "turn off the clock".
+ */
 void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
 {
 	ktime_t expires;
@@ -497,9 +621,11 @@
 		return;
 	}
 
-	/* We use wallclock time here, so the Guest might not be running for
+	/*
+	 * We use wallclock time here, so the Guest might not be running for
 	 * all the time between now and the timer interrupt it asked for.  This
-	 * is almost always the right thing to do. */
+	 * is almost always the right thing to do.
+	 */
 	expires = ktime_add_ns(ktime_get_real(), delta);
 	hrtimer_start(&cpu->hrt, expires, HRTIMER_MODE_ABS);
 }
@@ -510,10 +636,7 @@
 	struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
 
 	/* Remember the first interrupt is the timer interrupt. */
-	set_bit(0, cpu->irqs_pending);
-	/* If the Guest is actually stopped, we need to wake it up. */
-	if (cpu->halted)
-		wake_up_process(cpu->tsk);
+	set_interrupt(cpu, 0);
 	return HRTIMER_NORESTART;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/Kconfig linux-libre-2.6.31-gnu/drivers/lguest/Kconfig
--- linux-libre-2.6.30-gnu/drivers/lguest/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,6 +1,6 @@
 config LGUEST
 	tristate "Linux hypervisor example code"
-	depends on X86_32 && EXPERIMENTAL && !X86_PAE && FUTEX
+	depends on X86_32 && EXPERIMENTAL && EVENTFD
 	select HVC_DRIVER
 	---help---
 	  This is a very simple module which allows you to run
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/lg.h linux-libre-2.6.31-gnu/drivers/lguest/lg.h
--- linux-libre-2.6.30-gnu/drivers/lguest/lg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/lg.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,15 +16,13 @@
 void free_pagetables(void);
 int init_pagetables(struct page **switcher_page, unsigned int pages);
 
-struct pgdir
-{
+struct pgdir {
 	unsigned long gpgdir;
 	pgd_t *pgdir;
 };
 
 /* We have two pages shared with guests, per cpu.  */
-struct lguest_pages
-{
+struct lguest_pages {
 	/* This is the stack page mapped rw in guest */
 	char spare[PAGE_SIZE - sizeof(struct lguest_regs)];
 	struct lguest_regs regs;
@@ -38,8 +36,6 @@
 #define CHANGED_GDT_TLS		4 /* Actually a subset of CHANGED_GDT */
 #define CHANGED_ALL	        3
 
-struct lguest;
-
 struct lg_cpu {
 	unsigned int id;
 	struct lguest *lg;
@@ -49,20 +45,20 @@
 	u32 cr2;
 	int ts;
 	u32 esp1;
-	u8 ss1;
+	u16 ss1;
 
 	/* Bitmap of what has changed: see CHANGED_* above. */
 	int changed;
 
 	unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */
 
-	/* At end of a page shared mapped over lguest_pages in guest.  */
+	/* At end of a page shared mapped over lguest_pages in guest. */
 	unsigned long regs_page;
 	struct lguest_regs *regs;
 
 	struct lguest_pages *last_pages;
 
-	int cpu_pgd; /* which pgd this cpu is currently using */
+	int cpu_pgd; /* Which pgd this cpu is currently using */
 
 	/* If a hypercall was asked for, this points to the arguments. */
 	struct hcall_args *hcall;
@@ -71,9 +67,7 @@
 	/* Virtual clock device */
 	struct hrtimer hrt;
 
-	/* Do we need to stop what we're doing and return to userspace? */
-	int break_out;
-	wait_queue_head_t break_wq;
+	/* Did the Guest tell us to halt? */
 	int halted;
 
 	/* Pending virtual interrupts */
@@ -82,16 +76,28 @@
 	struct lg_cpu_arch arch;
 };
 
+struct lg_eventfd {
+	unsigned long addr;
+	struct eventfd_ctx *event;
+};
+
+struct lg_eventfd_map {
+	unsigned int num;
+	struct lg_eventfd map[];
+};
+
 /* The private info the thread maintains about the guest. */
-struct lguest
-{
+struct lguest {
 	struct lguest_data __user *lguest_data;
 	struct lg_cpu cpus[NR_CPUS];
 	unsigned int nr_cpus;
 
 	u32 pfn_limit;
-	/* This provides the offset to the base of guest-physical
-	 * memory in the Launcher. */
+
+	/*
+	 * This provides the offset to the base of guest-physical memory in the
+	 * Launcher.
+	 */
 	void __user *mem_base;
 	unsigned long kernel_address;
 
@@ -102,6 +108,8 @@
 	unsigned int stack_pages;
 	u32 tsc_khz;
 
+	struct lg_eventfd_map *eventfds;
+
 	/* Dead? */
 	const char *dead;
 };
@@ -114,11 +122,13 @@
 void __lgread(struct lg_cpu *, void *, unsigned long, unsigned);
 void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned);
 
-/*H:035 Using memory-copy operations like that is usually inconvient, so we
+/*H:035
+ * Using memory-copy operations like that is usually inconvient, so we
  * have the following helper macros which read and write a specific type (often
  * an unsigned long).
  *
- * This reads into a variable of the given type then returns that. */
+ * This reads into a variable of the given type then returns that.
+ */
 #define lgread(cpu, addr, type)						\
 	({ type _v; __lgread((cpu), &_v, (addr), sizeof(_v)); _v; })
 
@@ -132,14 +142,20 @@
 
 int run_guest(struct lg_cpu *cpu, unsigned long __user *user);
 
-/* Helper macros to obtain the first 12 or the last 20 bits, this is only the
+/*
+ * Helper macros to obtain the first 12 or the last 20 bits, this is only the
  * first step in the migration to the kernel types.  pte_pfn is already defined
- * in the kernel. */
+ * in the kernel.
+ */
 #define pgd_flags(x)	(pgd_val(x) & ~PAGE_MASK)
 #define pgd_pfn(x)	(pgd_val(x) >> PAGE_SHIFT)
+#define pmd_flags(x)    (pmd_val(x) & ~PAGE_MASK)
+#define pmd_pfn(x)	(pmd_val(x) >> PAGE_SHIFT)
 
 /* interrupts_and_traps.c: */
-void maybe_do_interrupt(struct lg_cpu *cpu);
+unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more);
+void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more);
+void set_interrupt(struct lg_cpu *cpu, unsigned int irq);
 bool deliver_trap(struct lg_cpu *cpu, unsigned int num);
 void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i,
 			  u32 low, u32 hi);
@@ -150,6 +166,7 @@
 void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
 		const unsigned long *def);
 void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta);
+bool send_notify_to_eventfd(struct lg_cpu *cpu);
 void init_clockdev(struct lg_cpu *cpu);
 bool check_syscall_vector(struct lguest *lg);
 int init_interrupts(void);
@@ -168,7 +185,10 @@
 int init_guest_pagetable(struct lguest *lg);
 void free_guest_pagetable(struct lguest *lg);
 void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable);
+void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 i);
+#ifdef CONFIG_X86_PAE
 void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i);
+#endif
 void guest_pagetable_clear_all(struct lg_cpu *cpu);
 void guest_pagetable_flush_user(struct lg_cpu *cpu);
 void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir,
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/lguest_device.c linux-libre-2.6.31-gnu/drivers/lguest/lguest_device.c
--- linux-libre-2.6.30-gnu/drivers/lguest/lguest_device.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/lguest_device.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,10 +1,12 @@
-/*P:050 Lguest guests use a very simple method to describe devices.  It's a
+/*P:050
+ * Lguest guests use a very simple method to describe devices.  It's a
  * series of device descriptors contained just above the top of normal Guest
  * memory.
  *
  * We use the standard "virtio" device infrastructure, which provides us with a
  * console, a network and a block driver.  Each one expects some configuration
- * information and a "virtqueue" or two to send and receive data. :*/
+ * information and a "virtqueue" or two to send and receive data.
+:*/
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/lguest_launcher.h>
@@ -20,8 +22,10 @@
 /* The pointer to our (page) of device descriptions. */
 static void *lguest_devices;
 
-/* For Guests, device memory can be used as normal memory, so we cast away the
- * __iomem to quieten sparse. */
+/*
+ * For Guests, device memory can be used as normal memory, so we cast away the
+ * __iomem to quieten sparse.
+ */
 static inline void *lguest_map(unsigned long phys_addr, unsigned long pages)
 {
 	return (__force void *)ioremap_cache(phys_addr, PAGE_SIZE*pages);
@@ -32,8 +36,10 @@
 	iounmap((__force void __iomem *)addr);
 }
 
-/*D:100 Each lguest device is just a virtio device plus a pointer to its entry
- * in the lguest_devices page. */
+/*D:100
+ * Each lguest device is just a virtio device plus a pointer to its entry
+ * in the lguest_devices page.
+ */
 struct lguest_device {
 	struct virtio_device vdev;
 
@@ -41,9 +47,11 @@
 	struct lguest_device_desc *desc;
 };
 
-/* Since the virtio infrastructure hands us a pointer to the virtio_device all
+/*
+ * Since the virtio infrastructure hands us a pointer to the virtio_device all
  * the time, it helps to have a curt macro to get a pointer to the struct
- * lguest_device it's enclosed in.  */
+ * lguest_device it's enclosed in.
+ */
 #define to_lgdev(vd) container_of(vd, struct lguest_device, vdev)
 
 /*D:130
@@ -55,7 +63,8 @@
  * the driver will look at them during setup.
  *
  * A convenient routine to return the device's virtqueue config array:
- * immediately after the descriptor. */
+ * immediately after the descriptor.
+ */
 static struct lguest_vqconfig *lg_vq(const struct lguest_device_desc *desc)
 {
 	return (void *)(desc + 1);
@@ -98,10 +107,12 @@
 	return features;
 }
 
-/* The virtio core takes the features the Host offers, and copies the
- * ones supported by the driver into the vdev->features array.  Once
- * that's all sorted out, this routine is called so we can tell the
- * Host which features we understand and accept. */
+/*
+ * The virtio core takes the features the Host offers, and copies the ones
+ * supported by the driver into the vdev->features array.  Once that's all
+ * sorted out, this routine is called so we can tell the Host which features we
+ * understand and accept.
+ */
 static void lg_finalize_features(struct virtio_device *vdev)
 {
 	unsigned int i, bits;
@@ -112,10 +123,11 @@
 	/* Give virtio_ring a chance to accept features. */
 	vring_transport_features(vdev);
 
-	/* The vdev->feature array is a Linux bitmask: this isn't the
-	 * same as a the simple array of bits used by lguest devices
-	 * for features.  So we do this slow, manual conversion which is
-	 * completely general. */
+	/*
+	 * The vdev->feature array is a Linux bitmask: this isn't the same as a
+	 * the simple array of bits used by lguest devices for features.  So we
+	 * do this slow, manual conversion which is completely general.
+	 */
 	memset(out_features, 0, desc->feature_len);
 	bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8;
 	for (i = 0; i < bits; i++) {
@@ -146,15 +158,19 @@
 	memcpy(lg_config(desc) + offset, buf, len);
 }
 
-/* The operations to get and set the status word just access the status field
- * of the device descriptor. */
+/*
+ * The operations to get and set the status word just access the status field
+ * of the device descriptor.
+ */
 static u8 lg_get_status(struct virtio_device *vdev)
 {
 	return to_lgdev(vdev)->desc->status;
 }
 
-/* To notify on status updates, we (ab)use the NOTIFY hypercall, with the
- * descriptor address of the device.  A zero status means "reset". */
+/*
+ * To notify on status updates, we (ab)use the NOTIFY hypercall, with the
+ * descriptor address of the device.  A zero status means "reset".
+ */
 static void set_status(struct virtio_device *vdev, u8 status)
 {
 	unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
@@ -191,8 +207,7 @@
  */
 
 /*D:140 This is the information we remember about each virtqueue. */
-struct lguest_vq_info
-{
+struct lguest_vq_info {
 	/* A copy of the information contained in the device config. */
 	struct lguest_vqconfig config;
 
@@ -200,13 +215,17 @@
 	void *pages;
 };
 
-/* When the virtio_ring code wants to prod the Host, it calls us here and we
+/*
+ * When the virtio_ring code wants to prod the Host, it calls us here and we
  * make a hypercall.  We hand the physical address of the virtqueue so the Host
- * knows which virtqueue we're talking about. */
+ * knows which virtqueue we're talking about.
+ */
 static void lg_notify(struct virtqueue *vq)
 {
-	/* We store our virtqueue information in the "priv" pointer of the
-	 * virtqueue structure. */
+	/*
+	 * We store our virtqueue information in the "priv" pointer of the
+	 * virtqueue structure.
+	 */
 	struct lguest_vq_info *lvq = vq->priv;
 
 	kvm_hypercall1(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT);
@@ -215,7 +234,8 @@
 /* An extern declaration inside a C file is bad form.  Don't do it. */
 extern void lguest_setup_irq(unsigned int irq);
 
-/* This routine finds the first virtqueue described in the configuration of
+/*
+ * This routine finds the Nth virtqueue described in the configuration of
  * this device and sets it up.
  *
  * This is kind of an ugly duckling.  It'd be nicer to have a standard
@@ -223,12 +243,11 @@
  * everyone wants to do it differently.  The KVM coders want the Guest to
  * allocate its own pages and tell the Host where they are, but for lguest it's
  * simpler for the Host to simply tell us where the pages are.
- *
- * So we provide drivers with a "find the Nth virtqueue and set it up"
- * function. */
+ */
 static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
 				    unsigned index,
-				    void (*callback)(struct virtqueue *vq))
+				    void (*callback)(struct virtqueue *vq),
+				    const char *name)
 {
 	struct lguest_device *ldev = to_lgdev(vdev);
 	struct lguest_vq_info *lvq;
@@ -243,9 +262,11 @@
 	if (!lvq)
 		return ERR_PTR(-ENOMEM);
 
-	/* Make a copy of the "struct lguest_vqconfig" entry, which sits after
+	/*
+	 * Make a copy of the "struct lguest_vqconfig" entry, which sits after
 	 * the descriptor.  We need a copy because the config space might not
-	 * be aligned correctly. */
+	 * be aligned correctly.
+	 */
 	memcpy(&lvq->config, lg_vq(ldev->desc)+index, sizeof(lvq->config));
 
 	printk("Mapping virtqueue %i addr %lx\n", index,
@@ -260,10 +281,12 @@
 		goto free_lvq;
 	}
 
-	/* OK, tell virtio_ring.c to set up a virtqueue now we know its size
-	 * and we've got a pointer to its pages. */
+	/*
+	 * OK, tell virtio_ring.c to set up a virtqueue now we know its size
+	 * and we've got a pointer to its pages.
+	 */
 	vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN,
-				 vdev, lvq->pages, lg_notify, callback);
+				 vdev, lvq->pages, lg_notify, callback, name);
 	if (!vq) {
 		err = -ENOMEM;
 		goto unmap;
@@ -272,18 +295,23 @@
 	/* Make sure the interrupt is allocated. */
 	lguest_setup_irq(lvq->config.irq);
 
-	/* Tell the interrupt for this virtqueue to go to the virtio_ring
-	 * interrupt handler. */
-	/* FIXME: We used to have a flag for the Host to tell us we could use
+	/*
+	 * Tell the interrupt for this virtqueue to go to the virtio_ring
+	 * interrupt handler.
+	 *
+	 * FIXME: We used to have a flag for the Host to tell us we could use
 	 * the interrupt as a source of randomness: it'd be nice to have that
-	 * back.. */
+	 * back.
+	 */
 	err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
 			  dev_name(&vdev->dev), vq);
 	if (err)
 		goto destroy_vring;
 
-	/* Last of all we hook up our 'struct lguest_vq_info" to the
-	 * virtqueue's priv pointer. */
+	/*
+	 * Last of all we hook up our 'struct lguest_vq_info" to the
+	 * virtqueue's priv pointer.
+	 */
 	vq->priv = lvq;
 	return vq;
 
@@ -312,6 +340,38 @@
 	kfree(lvq);
 }
 
+static void lg_del_vqs(struct virtio_device *vdev)
+{
+	struct virtqueue *vq, *n;
+
+	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+		lg_del_vq(vq);
+}
+
+static int lg_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+		       struct virtqueue *vqs[],
+		       vq_callback_t *callbacks[],
+		       const char *names[])
+{
+	struct lguest_device *ldev = to_lgdev(vdev);
+	int i;
+
+	/* We must have this many virtqueues. */
+	if (nvqs > ldev->desc->num_vq)
+		return -ENOENT;
+
+	for (i = 0; i < nvqs; ++i) {
+		vqs[i] = lg_find_vq(vdev, i, callbacks[i], names[i]);
+		if (IS_ERR(vqs[i]))
+			goto error;
+	}
+	return 0;
+
+error:
+	lg_del_vqs(vdev);
+	return PTR_ERR(vqs[i]);
+}
+
 /* The ops structure which hooks everything together. */
 static struct virtio_config_ops lguest_config_ops = {
 	.get_features = lg_get_features,
@@ -321,15 +381,18 @@
 	.get_status = lg_get_status,
 	.set_status = lg_set_status,
 	.reset = lg_reset,
-	.find_vq = lg_find_vq,
-	.del_vq = lg_del_vq,
+	.find_vqs = lg_find_vqs,
+	.del_vqs = lg_del_vqs,
 };
 
-/* The root device for the lguest virtio devices.  This makes them appear as
- * /sys/devices/lguest/0,1,2 not /sys/devices/0,1,2. */
+/*
+ * The root device for the lguest virtio devices.  This makes them appear as
+ * /sys/devices/lguest/0,1,2 not /sys/devices/0,1,2.
+ */
 static struct device *lguest_root;
 
-/*D:120 This is the core of the lguest bus: actually adding a new device.
+/*D:120
+ * This is the core of the lguest bus: actually adding a new device.
  * It's a separate function because it's neater that way, and because an
  * earlier version of the code supported hotplug and unplug.  They were removed
  * early on because they were never used.
@@ -338,14 +401,14 @@
  *
  * It's worth reading this carefully: we start with a pointer to the new device
  * descriptor in the "lguest_devices" page, and the offset into the device
- * descriptor page so we can uniquely identify it if things go badly wrong. */
+ * descriptor page so we can uniquely identify it if things go badly wrong.
+ */
 static void add_lguest_device(struct lguest_device_desc *d,
 			      unsigned int offset)
 {
 	struct lguest_device *ldev;
 
-	/* Start with zeroed memory; Linux's device layer seems to count on
-	 * it. */
+	/* Start with zeroed memory; Linux's device layer counts on it. */
 	ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
 	if (!ldev) {
 		printk(KERN_EMERG "Cannot allocate lguest dev %u type %u\n",
@@ -355,17 +418,25 @@
 
 	/* This devices' parent is the lguest/ dir. */
 	ldev->vdev.dev.parent = lguest_root;
-	/* We have a unique device index thanks to the dev_index counter. */
+	/*
+	 * The device type comes straight from the descriptor.  There's also a
+	 * device vendor field in the virtio_device struct, which we leave as
+	 * 0.
+	 */
 	ldev->vdev.id.device = d->type;
-	/* We have a simple set of routines for querying the device's
-	 * configuration information and setting its status. */
+	/*
+	 * We have a simple set of routines for querying the device's
+	 * configuration information and setting its status.
+	 */
 	ldev->vdev.config = &lguest_config_ops;
 	/* And we remember the device's descriptor for lguest_config_ops. */
 	ldev->desc = d;
 
-	/* register_virtio_device() sets up the generic fields for the struct
+	/*
+	 * register_virtio_device() sets up the generic fields for the struct
 	 * virtio_device and calls device_register().  This makes the bus
-	 * infrastructure look for a matching driver. */
+	 * infrastructure look for a matching driver.
+	 */
 	if (register_virtio_device(&ldev->vdev) != 0) {
 		printk(KERN_ERR "Failed to register lguest dev %u type %u\n",
 		       offset, d->type);
@@ -373,8 +444,10 @@
 	}
 }
 
-/*D:110 scan_devices() simply iterates through the device page.  The type 0 is
- * reserved to mean "end of devices". */
+/*D:110
+ * scan_devices() simply iterates through the device page.  The type 0 is
+ * reserved to mean "end of devices".
+ */
 static void scan_devices(void)
 {
 	unsigned int i;
@@ -393,7 +466,8 @@
 	}
 }
 
-/*D:105 Fairly early in boot, lguest_devices_init() is called to set up the
+/*D:105
+ * Fairly early in boot, lguest_devices_init() is called to set up the
  * lguest device infrastructure.  We check that we are a Guest by checking
  * pv_info.name: there are other ways of checking, but this seems most
  * obvious to me.
@@ -404,7 +478,8 @@
  * correct sysfs incantation).
  *
  * Finally we call scan_devices() which adds all the devices found in the
- * lguest_devices page. */
+ * lguest_devices page.
+ */
 static int __init lguest_devices_init(void)
 {
 	if (strcmp(pv_info.name, "lguest") != 0)
@@ -423,11 +498,13 @@
 /* We do this after core stuff, but before the drivers. */
 postcore_initcall(lguest_devices_init);
 
-/*D:150 At this point in the journey we used to now wade through the lguest
+/*D:150
+ * At this point in the journey we used to now wade through the lguest
  * devices themselves: net, block and console.  Since they're all now virtio
  * devices rather than lguest-specific, I've decided to ignore them.  Mostly,
  * they're kind of boring.  But this does mean you'll never experience the
  * thrill of reading the forbidden love scene buried deep in the block driver.
  *
  * "make Launcher" beckons, where we answer questions like "Where do Guests
- * come from?", and "What do you do when someone asks for optimization?". */
+ * come from?", and "What do you do when someone asks for optimization?".
+ */
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/lguest_user.c linux-libre-2.6.31-gnu/drivers/lguest/lguest_user.c
--- linux-libre-2.6.30-gnu/drivers/lguest/lguest_user.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/lguest_user.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,42 +1,178 @@
 /*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
  * controls and communicates with the Guest.  For example, the first write will
- * tell us the Guest's memory layout, pagetable, entry point and kernel address
- * offset.  A read will run the Guest until something happens, such as a signal
- * or the Guest doing a NOTIFY out to the Launcher. :*/
+ * tell us the Guest's memory layout and entry point.  A read will run the
+ * Guest until something happens, such as a signal or the Guest doing a NOTIFY
+ * out to the Launcher.
+:*/
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
+#include <linux/eventfd.h>
+#include <linux/file.h>
 #include "lg.h"
 
-/*L:055 When something happens, the Waker process needs a way to stop the
- * kernel running the Guest and return to the Launcher.  So the Waker writes
- * LHREQ_BREAK and the value "1" to /dev/lguest to do this.  Once the Launcher
- * has done whatever needs attention, it writes LHREQ_BREAK and "0" to release
- * the Waker. */
-static int break_guest_out(struct lg_cpu *cpu, const unsigned long __user*input)
+/*L:056
+ * Before we move on, let's jump ahead and look at what the kernel does when
+ * it needs to look up the eventfds.  That will complete our picture of how we
+ * use RCU.
+ *
+ * The notification value is in cpu->pending_notify: we return true if it went
+ * to an eventfd.
+ */
+bool send_notify_to_eventfd(struct lg_cpu *cpu)
 {
-	unsigned long on;
+	unsigned int i;
+	struct lg_eventfd_map *map;
 
-	/* Fetch whether they're turning break on or off. */
-	if (get_user(on, input) != 0)
-		return -EFAULT;
+	/*
+	 * This "rcu_read_lock()" helps track when someone is still looking at
+	 * the (RCU-using) eventfds array.  It's not actually a lock at all;
+	 * indeed it's a noop in many configurations.  (You didn't expect me to
+	 * explain all the RCU secrets here, did you?)
+	 */
+	rcu_read_lock();
+	/*
+	 * rcu_dereference is the counter-side of rcu_assign_pointer(); it
+	 * makes sure we don't access the memory pointed to by
+	 * cpu->lg->eventfds before cpu->lg->eventfds is set.  Sounds crazy,
+	 * but Alpha allows this!  Paul McKenney points out that a really
+	 * aggressive compiler could have the same effect:
+	 *   http://lists.ozlabs.org/pipermail/lguest/2009-July/001560.html
+	 *
+	 * So play safe, use rcu_dereference to get the rcu-protected pointer:
+	 */
+	map = rcu_dereference(cpu->lg->eventfds);
+	/*
+	 * Simple array search: even if they add an eventfd while we do this,
+	 * we'll continue to use the old array and just won't see the new one.
+	 */
+	for (i = 0; i < map->num; i++) {
+		if (map->map[i].addr == cpu->pending_notify) {
+			eventfd_signal(map->map[i].event, 1);
+			cpu->pending_notify = 0;
+			break;
+		}
+	}
+	/* We're done with the rcu-protected variable cpu->lg->eventfds. */
+	rcu_read_unlock();
 
-	if (on) {
-		cpu->break_out = 1;
-		/* Pop it out of the Guest (may be running on different CPU) */
-		wake_up_process(cpu->tsk);
-		/* Wait for them to reset it */
-		return wait_event_interruptible(cpu->break_wq, !cpu->break_out);
-	} else {
-		cpu->break_out = 0;
-		wake_up(&cpu->break_wq);
-		return 0;
+	/* If we cleared the notification, it's because we found a match. */
+	return cpu->pending_notify == 0;
+}
+
+/*L:055
+ * One of the more tricksy tricks in the Linux Kernel is a technique called
+ * Read Copy Update.  Since one point of lguest is to teach lguest journeyers
+ * about kernel coding, I use it here.  (In case you're curious, other purposes
+ * include learning about virtualization and instilling a deep appreciation for
+ * simplicity and puppies).
+ *
+ * We keep a simple array which maps LHCALL_NOTIFY values to eventfds, but we
+ * add new eventfds without ever blocking readers from accessing the array.
+ * The current Launcher only does this during boot, so that never happens.  But
+ * Read Copy Update is cool, and adding a lock risks damaging even more puppies
+ * than this code does.
+ *
+ * We allocate a brand new one-larger array, copy the old one and add our new
+ * element.  Then we make the lg eventfd pointer point to the new array.
+ * That's the easy part: now we need to free the old one, but we need to make
+ * sure no slow CPU somewhere is still looking at it.  That's what
+ * synchronize_rcu does for us: waits until every CPU has indicated that it has
+ * moved on to know it's no longer using the old one.
+ *
+ * If that's unclear, see http://en.wikipedia.org/wiki/Read-copy-update.
+ */
+static int add_eventfd(struct lguest *lg, unsigned long addr, int fd)
+{
+	struct lg_eventfd_map *new, *old = lg->eventfds;
+
+	/*
+	 * We don't allow notifications on value 0 anyway (pending_notify of
+	 * 0 means "nothing pending").
+	 */
+	if (!addr)
+		return -EINVAL;
+
+	/*
+	 * Replace the old array with the new one, carefully: others can
+	 * be accessing it at the same time.
+	 */
+	new = kmalloc(sizeof(*new) + sizeof(new->map[0]) * (old->num + 1),
+		      GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+
+	/* First make identical copy. */
+	memcpy(new->map, old->map, sizeof(old->map[0]) * old->num);
+	new->num = old->num;
+
+	/* Now append new entry. */
+	new->map[new->num].addr = addr;
+	new->map[new->num].event = eventfd_ctx_fdget(fd);
+	if (IS_ERR(new->map[new->num].event)) {
+		int err =  PTR_ERR(new->map[new->num].event);
+		kfree(new);
+		return err;
 	}
+	new->num++;
+
+	/*
+	 * Now put new one in place: rcu_assign_pointer() is a fancy way of
+	 * doing "lg->eventfds = new", but it uses memory barriers to make
+	 * absolutely sure that the contents of "new" written above is nailed
+	 * down before we actually do the assignment.
+	 *
+	 * We have to think about these kinds of things when we're operating on
+	 * live data without locks.
+	 */
+	rcu_assign_pointer(lg->eventfds, new);
+
+	/*
+	 * We're not in a big hurry.  Wait until noone's looking at old
+	 * version, then free it.
+	 */
+	synchronize_rcu();
+	kfree(old);
+
+	return 0;
 }
 
-/*L:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
- * number to /dev/lguest. */
+/*L:052
+ * Receiving notifications from the Guest is usually done by attaching a
+ * particular LHCALL_NOTIFY value to an event filedescriptor.  The eventfd will
+ * become readable when the Guest does an LHCALL_NOTIFY with that value.
+ *
+ * This is really convenient for processing each virtqueue in a separate
+ * thread.
+ */
+static int attach_eventfd(struct lguest *lg, const unsigned long __user *input)
+{
+	unsigned long addr, fd;
+	int err;
+
+	if (get_user(addr, input) != 0)
+		return -EFAULT;
+	input++;
+	if (get_user(fd, input) != 0)
+		return -EFAULT;
+
+	/*
+	 * Just make sure two callers don't add eventfds at once.  We really
+	 * only need to lock against callers adding to the same Guest, so using
+	 * the Big Lguest Lock is overkill.  But this is setup, not a fast path.
+	 */
+	mutex_lock(&lguest_lock);
+	err = add_eventfd(lg, addr, fd);
+	mutex_unlock(&lguest_lock);
+
+	return err;
+}
+
+/*L:050
+ * Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
+ * number to /dev/lguest.
+ */
 static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
 {
 	unsigned long irq;
@@ -45,14 +181,19 @@
 		return -EFAULT;
 	if (irq >= LGUEST_IRQS)
 		return -EINVAL;
-	/* Next time the Guest runs, the core code will see if it can deliver
-	 * this interrupt. */
-	set_bit(irq, cpu->irqs_pending);
+
+	/*
+	 * Next time the Guest runs, the core code will see if it can deliver
+	 * this interrupt.
+	 */
+	set_interrupt(cpu, irq);
 	return 0;
 }
 
-/*L:040 Once our Guest is initialized, the Launcher makes it run by reading
- * from /dev/lguest. */
+/*L:040
+ * Once our Guest is initialized, the Launcher makes it run by reading
+ * from /dev/lguest.
+ */
 static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
 {
 	struct lguest *lg = file->private_data;
@@ -88,8 +229,10 @@
 		return len;
 	}
 
-	/* If we returned from read() last time because the Guest sent I/O,
-	 * clear the flag. */
+	/*
+	 * If we returned from read() last time because the Guest sent I/O,
+	 * clear the flag.
+	 */
 	if (cpu->pending_notify)
 		cpu->pending_notify = 0;
 
@@ -97,8 +240,10 @@
 	return run_guest(cpu, (unsigned long __user *)user);
 }
 
-/*L:025 This actually initializes a CPU.  For the moment, a Guest is only
- * uniprocessor, so "id" is always 0. */
+/*L:025
+ * This actually initializes a CPU.  For the moment, a Guest is only
+ * uniprocessor, so "id" is always 0.
+ */
 static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
 {
 	/* We have a limited number the number of CPUs in the lguest struct. */
@@ -113,8 +258,10 @@
 	/* Each CPU has a timer it can set. */
 	init_clockdev(cpu);
 
-	/* We need a complete page for the Guest registers: they are accessible
-	 * to the Guest and we can only grant it access to whole pages. */
+	/*
+	 * We need a complete page for the Guest registers: they are accessible
+	 * to the Guest and we can only grant it access to whole pages.
+	 */
 	cpu->regs_page = get_zeroed_page(GFP_KERNEL);
 	if (!cpu->regs_page)
 		return -ENOMEM;
@@ -122,32 +269,38 @@
 	/* We actually put the registers at the bottom of the page. */
 	cpu->regs = (void *)cpu->regs_page + PAGE_SIZE - sizeof(*cpu->regs);
 
-	/* Now we initialize the Guest's registers, handing it the start
-	 * address. */
+	/*
+	 * Now we initialize the Guest's registers, handing it the start
+	 * address.
+	 */
 	lguest_arch_setup_regs(cpu, start_ip);
 
-	/* Initialize the queue for the Waker to wait on */
-	init_waitqueue_head(&cpu->break_wq);
-
-	/* We keep a pointer to the Launcher task (ie. current task) for when
-	 * other Guests want to wake this one (eg. console input). */
+	/*
+	 * We keep a pointer to the Launcher task (ie. current task) for when
+	 * other Guests want to wake this one (eg. console input).
+	 */
 	cpu->tsk = current;
 
-	/* We need to keep a pointer to the Launcher's memory map, because if
+	/*
+	 * We need to keep a pointer to the Launcher's memory map, because if
 	 * the Launcher dies we need to clean it up.  If we don't keep a
-	 * reference, it is destroyed before close() is called. */
+	 * reference, it is destroyed before close() is called.
+	 */
 	cpu->mm = get_task_mm(cpu->tsk);
 
-	/* We remember which CPU's pages this Guest used last, for optimization
-	 * when the same Guest runs on the same CPU twice. */
+	/*
+	 * We remember which CPU's pages this Guest used last, for optimization
+	 * when the same Guest runs on the same CPU twice.
+	 */
 	cpu->last_pages = NULL;
 
 	/* No error == success. */
 	return 0;
 }
 
-/*L:020 The initialization write supplies 3 pointer sized (32 or 64 bit)
- * values (in addition to the LHREQ_INITIALIZE value).  These are:
+/*L:020
+ * The initialization write supplies 3 pointer sized (32 or 64 bit) values (in
+ * addition to the LHREQ_INITIALIZE value).  These are:
  *
  * base: The start of the Guest-physical memory inside the Launcher memory.
  *
@@ -159,14 +312,15 @@
  */
 static int initialize(struct file *file, const unsigned long __user *input)
 {
-	/* "struct lguest" contains everything we (the Host) know about a
-	 * Guest. */
+	/* "struct lguest" contains all we (the Host) know about a Guest. */
 	struct lguest *lg;
 	int err;
 	unsigned long args[3];
 
-	/* We grab the Big Lguest lock, which protects against multiple
-	 * simultaneous initializations. */
+	/*
+	 * We grab the Big Lguest lock, which protects against multiple
+	 * simultaneous initializations.
+	 */
 	mutex_lock(&lguest_lock);
 	/* You can't initialize twice!  Close the device and start again... */
 	if (file->private_data) {
@@ -185,6 +339,13 @@
 		goto unlock;
 	}
 
+	lg->eventfds = kmalloc(sizeof(*lg->eventfds), GFP_KERNEL);
+	if (!lg->eventfds) {
+		err = -ENOMEM;
+		goto free_lg;
+	}
+	lg->eventfds->num = 0;
+
 	/* Populate the easy fields of our "struct lguest" */
 	lg->mem_base = (void __user *)args[0];
 	lg->pfn_limit = args[1];
@@ -192,10 +353,12 @@
 	/* This is the first cpu (cpu 0) and it will start booting at args[2] */
 	err = lg_cpu_start(&lg->cpus[0], 0, args[2]);
 	if (err)
-		goto release_guest;
+		goto free_eventfds;
 
-	/* Initialize the Guest's shadow page tables, using the toplevel
-	 * address the Launcher gave us.  This allocates memory, so can fail. */
+	/*
+	 * Initialize the Guest's shadow page tables, using the toplevel
+	 * address the Launcher gave us.  This allocates memory, so can fail.
+	 */
 	err = init_guest_pagetable(lg);
 	if (err)
 		goto free_regs;
@@ -211,27 +374,33 @@
 free_regs:
 	/* FIXME: This should be in free_vcpu */
 	free_page(lg->cpus[0].regs_page);
-release_guest:
+free_eventfds:
+	kfree(lg->eventfds);
+free_lg:
 	kfree(lg);
 unlock:
 	mutex_unlock(&lguest_lock);
 	return err;
 }
 
-/*L:010 The first operation the Launcher does must be a write.  All writes
+/*L:010
+ * The first operation the Launcher does must be a write.  All writes
  * start with an unsigned long number: for the first write this must be
  * LHREQ_INITIALIZE to set up the Guest.  After that the Launcher can use
- * writes of other values to send interrupts.
+ * writes of other values to send interrupts or set up receipt of notifications.
  *
  * Note that we overload the "offset" in the /dev/lguest file to indicate what
- * CPU number we're dealing with.  Currently this is always 0, since we only
+ * CPU number we're dealing with.  Currently this is always 0 since we only
  * support uniprocessor Guests, but you can see the beginnings of SMP support
- * here. */
+ * here.
+ */
 static ssize_t write(struct file *file, const char __user *in,
 		     size_t size, loff_t *off)
 {
-	/* Once the Guest is initialized, we hold the "struct lguest" in the
-	 * file private data. */
+	/*
+	 * Once the Guest is initialized, we hold the "struct lguest" in the
+	 * file private data.
+	 */
 	struct lguest *lg = file->private_data;
 	const unsigned long __user *input = (const unsigned long __user *)in;
 	unsigned long req;
@@ -252,11 +421,6 @@
 		/* Once the Guest is dead, you can only read() why it died. */
 		if (lg->dead)
 			return -ENOENT;
-
-		/* If you're not the task which owns the Guest, all you can do
-		 * is break the Launcher out of running the Guest. */
-		if (current != cpu->tsk && req != LHREQ_BREAK)
-			return -EPERM;
 	}
 
 	switch (req) {
@@ -264,20 +428,22 @@
 		return initialize(file, input);
 	case LHREQ_IRQ:
 		return user_send_irq(cpu, input);
-	case LHREQ_BREAK:
-		return break_guest_out(cpu, input);
+	case LHREQ_EVENTFD:
+		return attach_eventfd(lg, input);
 	default:
 		return -EINVAL;
 	}
 }
 
-/*L:060 The final piece of interface code is the close() routine.  It reverses
+/*L:060
+ * The final piece of interface code is the close() routine.  It reverses
  * everything done in initialize().  This is usually called because the
  * Launcher exited.
  *
  * Note that the close routine returns 0 or a negative error number: it can't
  * really fail, but it can whine.  I blame Sun for this wart, and K&R C for
- * letting them do it. :*/
+ * letting them do it.
+:*/
 static int close(struct inode *inode, struct file *file)
 {
 	struct lguest *lg = file->private_data;
@@ -287,8 +453,10 @@
 	if (!lg)
 		return 0;
 
-	/* We need the big lock, to protect from inter-guest I/O and other
-	 * Launchers initializing guests. */
+	/*
+	 * We need the big lock, to protect from inter-guest I/O and other
+	 * Launchers initializing guests.
+	 */
 	mutex_lock(&lguest_lock);
 
 	/* Free up the shadow page tables for the Guest. */
@@ -299,12 +467,22 @@
 		hrtimer_cancel(&lg->cpus[i].hrt);
 		/* We can free up the register page we allocated. */
 		free_page(lg->cpus[i].regs_page);
-		/* Now all the memory cleanups are done, it's safe to release
-		 * the Launcher's memory management structure. */
+		/*
+		 * Now all the memory cleanups are done, it's safe to release
+		 * the Launcher's memory management structure.
+		 */
 		mmput(lg->cpus[i].mm);
 	}
-	/* If lg->dead doesn't contain an error code it will be NULL or a
-	 * kmalloc()ed string, either of which is ok to hand to kfree(). */
+
+	/* Release any eventfds they registered. */
+	for (i = 0; i < lg->eventfds->num; i++)
+		eventfd_ctx_put(lg->eventfds->map[i].event);
+	kfree(lg->eventfds);
+
+	/*
+	 * If lg->dead doesn't contain an error code it will be NULL or a
+	 * kmalloc()ed string, either of which is ok to hand to kfree().
+	 */
 	if (!IS_ERR(lg->dead))
 		kfree(lg->dead);
 	/* Free the memory allocated to the lguest_struct */
@@ -328,7 +506,8 @@
  *
  * We begin our understanding with the Host kernel interface which the Launcher
  * uses: reading and writing a character device called /dev/lguest.  All the
- * work happens in the read(), write() and close() routines: */
+ * work happens in the read(), write() and close() routines:
+ */
 static struct file_operations lguest_fops = {
 	.owner	 = THIS_MODULE,
 	.release = close,
@@ -336,8 +515,10 @@
 	.read	 = read,
 };
 
-/* This is a textbook example of a "misc" character device.  Populate a "struct
- * miscdevice" and register it with misc_register(). */
+/*
+ * This is a textbook example of a "misc" character device.  Populate a "struct
+ * miscdevice" and register it with misc_register().
+ */
 static struct miscdevice lguest_dev = {
 	.minor	= MISC_DYNAMIC_MINOR,
 	.name	= "lguest",
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/page_tables.c linux-libre-2.6.31-gnu/drivers/lguest/page_tables.c
--- linux-libre-2.6.30-gnu/drivers/lguest/page_tables.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/page_tables.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,9 +1,11 @@
-/*P:700 The pagetable code, on the other hand, still shows the scars of
+/*P:700
+ * The pagetable code, on the other hand, still shows the scars of
  * previous encounters.  It's functional, and as neat as it can be in the
  * circumstances, but be wary, for these things are subtle and break easily.
  * The Guest provides a virtual to physical mapping, but we can neither trust
  * it nor use it: we verify and convert it here then point the CPU to the
- * converted Guest pages when running the Guest. :*/
+ * converted Guest pages when running the Guest.
+:*/
 
 /* Copyright (C) Rusty Russell IBM Corporation 2006.
  * GPL v2 and any later version */
@@ -17,18 +19,20 @@
 #include <asm/bootparam.h>
 #include "lg.h"
 
-/*M:008 We hold reference to pages, which prevents them from being swapped.
+/*M:008
+ * We hold reference to pages, which prevents them from being swapped.
  * It'd be nice to have a callback in the "struct mm_struct" when Linux wants
  * to swap out.  If we had this, and a shrinker callback to trim PTE pages, we
- * could probably consider launching Guests as non-root. :*/
+ * could probably consider launching Guests as non-root.
+:*/
 
 /*H:300
  * The Page Table Code
  *
- * We use two-level page tables for the Guest.  If you're not entirely
- * comfortable with virtual addresses, physical addresses and page tables then
- * I recommend you review arch/x86/lguest/boot.c's "Page Table Handling" (with
- * diagrams!).
+ * We use two-level page tables for the Guest, or three-level with PAE.  If
+ * you're not entirely comfortable with virtual addresses, physical addresses
+ * and page tables then I recommend you review arch/x86/lguest/boot.c's "Page
+ * Table Handling" (with diagrams!).
  *
  * The Guest keeps page tables, but we maintain the actual ones here: these are
  * called "shadow" page tables.  Which is a very Guest-centric name: these are
@@ -45,22 +49,39 @@
  *  (v) Flushing (throwing away) page tables,
  *  (vi) Mapping the Switcher when the Guest is about to run,
  *  (vii) Setting up the page tables initially.
- :*/
-
+:*/
 
-/* 1024 entries in a page table page maps 1024 pages: 4MB.  The Switcher is
- * conveniently placed at the top 4MB, so it uses a separate, complete PTE
- * page.  */
+/*
+ * The Switcher uses the complete top PTE page.  That's 1024 PTE entries (4MB)
+ * or 512 PTE entries with PAE (2MB).
+ */
 #define SWITCHER_PGD_INDEX (PTRS_PER_PGD - 1)
 
-/* We actually need a separate PTE page for each CPU.  Remember that after the
+/*
+ * For PAE we need the PMD index as well. We use the last 2MB, so we
+ * will need the last pmd entry of the last pmd page.
+ */
+#ifdef CONFIG_X86_PAE
+#define SWITCHER_PMD_INDEX 	(PTRS_PER_PMD - 1)
+#define RESERVE_MEM 		2U
+#define CHECK_GPGD_MASK		_PAGE_PRESENT
+#else
+#define RESERVE_MEM 		4U
+#define CHECK_GPGD_MASK		_PAGE_TABLE
+#endif
+
+/*
+ * We actually need a separate PTE page for each CPU.  Remember that after the
  * Switcher code itself comes two pages for each CPU, and we don't want this
- * CPU's guest to see the pages of any other CPU. */
+ * CPU's guest to see the pages of any other CPU.
+ */
 static DEFINE_PER_CPU(pte_t *, switcher_pte_pages);
 #define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu)
 
-/*H:320 The page table code is curly enough to need helper functions to keep it
- * clear and clean.
+/*H:320
+ * The page table code is curly enough to need helper functions to keep it
+ * clear and clean.  The kernel itself provides many of them; one advantage
+ * of insisting that the Guest and Host use the same CONFIG_PAE setting.
  *
  * There are two functions which return pointers to the shadow (aka "real")
  * page tables.
@@ -68,58 +89,127 @@
  * spgd_addr() takes the virtual address and returns a pointer to the top-level
  * page directory entry (PGD) for that address.  Since we keep track of several
  * page tables, the "i" argument tells us which one we're interested in (it's
- * usually the current one). */
+ * usually the current one).
+ */
 static pgd_t *spgd_addr(struct lg_cpu *cpu, u32 i, unsigned long vaddr)
 {
 	unsigned int index = pgd_index(vaddr);
 
+#ifndef CONFIG_X86_PAE
 	/* We kill any Guest trying to touch the Switcher addresses. */
 	if (index >= SWITCHER_PGD_INDEX) {
 		kill_guest(cpu, "attempt to access switcher pages");
 		index = 0;
 	}
+#endif
 	/* Return a pointer index'th pgd entry for the i'th page table. */
 	return &cpu->lg->pgdirs[i].pgdir[index];
 }
 
-/* This routine then takes the page directory entry returned above, which
+#ifdef CONFIG_X86_PAE
+/*
+ * This routine then takes the PGD entry given above, which contains the
+ * address of the PMD page.  It then returns a pointer to the PMD entry for the
+ * given address.
+ */
+static pmd_t *spmd_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
+{
+	unsigned int index = pmd_index(vaddr);
+	pmd_t *page;
+
+	/* We kill any Guest trying to touch the Switcher addresses. */
+	if (pgd_index(vaddr) == SWITCHER_PGD_INDEX &&
+					index >= SWITCHER_PMD_INDEX) {
+		kill_guest(cpu, "attempt to access switcher pages");
+		index = 0;
+	}
+
+	/* You should never call this if the PGD entry wasn't valid */
+	BUG_ON(!(pgd_flags(spgd) & _PAGE_PRESENT));
+	page = __va(pgd_pfn(spgd) << PAGE_SHIFT);
+
+	return &page[index];
+}
+#endif
+
+/*
+ * This routine then takes the page directory entry returned above, which
  * contains the address of the page table entry (PTE) page.  It then returns a
- * pointer to the PTE entry for the given address. */
-static pte_t *spte_addr(pgd_t spgd, unsigned long vaddr)
+ * pointer to the PTE entry for the given address.
+ */
+static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
 {
+#ifdef CONFIG_X86_PAE
+	pmd_t *pmd = spmd_addr(cpu, spgd, vaddr);
+	pte_t *page = __va(pmd_pfn(*pmd) << PAGE_SHIFT);
+
+	/* You should never call this if the PMD entry wasn't valid */
+	BUG_ON(!(pmd_flags(*pmd) & _PAGE_PRESENT));
+#else
 	pte_t *page = __va(pgd_pfn(spgd) << PAGE_SHIFT);
 	/* You should never call this if the PGD entry wasn't valid */
 	BUG_ON(!(pgd_flags(spgd) & _PAGE_PRESENT));
-	return &page[(vaddr >> PAGE_SHIFT) % PTRS_PER_PTE];
+#endif
+
+	return &page[pte_index(vaddr)];
 }
 
-/* These two functions just like the above two, except they access the Guest
- * page tables.  Hence they return a Guest address. */
+/*
+ * These functions are just like the above two, except they access the Guest
+ * page tables.  Hence they return a Guest address.
+ */
 static unsigned long gpgd_addr(struct lg_cpu *cpu, unsigned long vaddr)
 {
 	unsigned int index = vaddr >> (PGDIR_SHIFT);
 	return cpu->lg->pgdirs[cpu->cpu_pgd].gpgdir + index * sizeof(pgd_t);
 }
 
-static unsigned long gpte_addr(pgd_t gpgd, unsigned long vaddr)
+#ifdef CONFIG_X86_PAE
+/* Follow the PGD to the PMD. */
+static unsigned long gpmd_addr(pgd_t gpgd, unsigned long vaddr)
 {
 	unsigned long gpage = pgd_pfn(gpgd) << PAGE_SHIFT;
 	BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT));
-	return gpage + ((vaddr>>PAGE_SHIFT) % PTRS_PER_PTE) * sizeof(pte_t);
+	return gpage + pmd_index(vaddr) * sizeof(pmd_t);
+}
+
+/* Follow the PMD to the PTE. */
+static unsigned long gpte_addr(struct lg_cpu *cpu,
+			       pmd_t gpmd, unsigned long vaddr)
+{
+	unsigned long gpage = pmd_pfn(gpmd) << PAGE_SHIFT;
+
+	BUG_ON(!(pmd_flags(gpmd) & _PAGE_PRESENT));
+	return gpage + pte_index(vaddr) * sizeof(pte_t);
+}
+#else
+/* Follow the PGD to the PTE (no mid-level for !PAE). */
+static unsigned long gpte_addr(struct lg_cpu *cpu,
+				pgd_t gpgd, unsigned long vaddr)
+{
+	unsigned long gpage = pgd_pfn(gpgd) << PAGE_SHIFT;
+
+	BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT));
+	return gpage + pte_index(vaddr) * sizeof(pte_t);
 }
+#endif
 /*:*/
 
-/*M:014 get_pfn is slow: we could probably try to grab batches of pages here as
- * an optimization (ie. pre-faulting). :*/
+/*M:014
+ * get_pfn is slow: we could probably try to grab batches of pages here as
+ * an optimization (ie. pre-faulting).
+:*/
 
-/*H:350 This routine takes a page number given by the Guest and converts it to
+/*H:350
+ * This routine takes a page number given by the Guest and converts it to
  * an actual, physical page number.  It can fail for several reasons: the
  * virtual address might not be mapped by the Launcher, the write flag is set
  * and the page is read-only, or the write flag was set and the page was
  * shared so had to be copied, but we ran out of memory.
  *
  * This holds a reference to the page, so release_pte() is careful to put that
- * back. */
+ * back.
+ */
 static unsigned long get_pfn(unsigned long virtpfn, int write)
 {
 	struct page *page;
@@ -132,33 +222,41 @@
 	return -1UL;
 }
 
-/*H:340 Converting a Guest page table entry to a shadow (ie. real) page table
+/*H:340
+ * Converting a Guest page table entry to a shadow (ie. real) page table
  * entry can be a little tricky.  The flags are (almost) the same, but the
  * Guest PTE contains a virtual page number: the CPU needs the real page
- * number. */
+ * number.
+ */
 static pte_t gpte_to_spte(struct lg_cpu *cpu, pte_t gpte, int write)
 {
 	unsigned long pfn, base, flags;
 
-	/* The Guest sets the global flag, because it thinks that it is using
+	/*
+	 * The Guest sets the global flag, because it thinks that it is using
 	 * PGE.  We only told it to use PGE so it would tell us whether it was
 	 * flushing a kernel mapping or a userspace mapping.  We don't actually
-	 * use the global bit, so throw it away. */
+	 * use the global bit, so throw it away.
+	 */
 	flags = (pte_flags(gpte) & ~_PAGE_GLOBAL);
 
 	/* The Guest's pages are offset inside the Launcher. */
 	base = (unsigned long)cpu->lg->mem_base / PAGE_SIZE;
 
-	/* We need a temporary "unsigned long" variable to hold the answer from
+	/*
+	 * We need a temporary "unsigned long" variable to hold the answer from
 	 * get_pfn(), because it returns 0xFFFFFFFF on failure, which wouldn't
 	 * fit in spte.pfn.  get_pfn() finds the real physical number of the
-	 * page, given the virtual number. */
+	 * page, given the virtual number.
+	 */
 	pfn = get_pfn(base + pte_pfn(gpte), write);
 	if (pfn == -1UL) {
 		kill_guest(cpu, "failed to get page %lu", pte_pfn(gpte));
-		/* When we destroy the Guest, we'll go through the shadow page
+		/*
+		 * When we destroy the Guest, we'll go through the shadow page
 		 * tables and release_pte() them.  Make sure we don't think
-		 * this one is valid! */
+		 * this one is valid!
+		 */
 		flags = 0;
 	}
 	/* Now we assemble our shadow PTE from the page number and flags. */
@@ -168,10 +266,12 @@
 /*H:460 And to complete the chain, release_pte() looks like this: */
 static void release_pte(pte_t pte)
 {
-	/* Remember that get_user_pages_fast() took a reference to the page, in
-	 * get_pfn()?  We have to put it back now. */
+	/*
+	 * Remember that get_user_pages_fast() took a reference to the page, in
+	 * get_pfn()?  We have to put it back now.
+	 */
 	if (pte_flags(pte) & _PAGE_PRESENT)
-		put_page(pfn_to_page(pte_pfn(pte)));
+		put_page(pte_page(pte));
 }
 /*:*/
 
@@ -184,11 +284,20 @@
 
 static void check_gpgd(struct lg_cpu *cpu, pgd_t gpgd)
 {
-	if ((pgd_flags(gpgd) & ~_PAGE_TABLE) ||
+	if ((pgd_flags(gpgd) & ~CHECK_GPGD_MASK) ||
 	   (pgd_pfn(gpgd) >= cpu->lg->pfn_limit))
 		kill_guest(cpu, "bad page directory entry");
 }
 
+#ifdef CONFIG_X86_PAE
+static void check_gpmd(struct lg_cpu *cpu, pmd_t gpmd)
+{
+	if ((pmd_flags(gpmd) & ~_PAGE_TABLE) ||
+	   (pmd_pfn(gpmd) >= cpu->lg->pfn_limit))
+		kill_guest(cpu, "bad page middle directory entry");
+}
+#endif
+
 /*H:330
  * (i) Looking up a page table entry when the Guest faults.
  *
@@ -198,7 +307,8 @@
  * and return to the Guest without it knowing.
  *
  * If we fixed up the fault (ie. we mapped the address), this routine returns
- * true.  Otherwise, it was a real fault and we need to tell the Guest. */
+ * true.  Otherwise, it was a real fault and we need to tell the Guest.
+ */
 bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
 {
 	pgd_t gpgd;
@@ -207,6 +317,12 @@
 	pte_t gpte;
 	pte_t *spte;
 
+	/* Mid level for PAE. */
+#ifdef CONFIG_X86_PAE
+	pmd_t *spmd;
+	pmd_t gpmd;
+#endif
+
 	/* First step: get the top-level Guest page table entry. */
 	gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
 	/* Toplevel not present?  We can't map it in. */
@@ -218,30 +334,79 @@
 	if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) {
 		/* No shadow entry: allocate a new shadow PTE page. */
 		unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
-		/* This is not really the Guest's fault, but killing it is
-		 * simple for this corner case. */
+		/*
+		 * This is not really the Guest's fault, but killing it is
+		 * simple for this corner case.
+		 */
 		if (!ptepage) {
 			kill_guest(cpu, "out of memory allocating pte page");
 			return false;
 		}
 		/* We check that the Guest pgd is OK. */
 		check_gpgd(cpu, gpgd);
-		/* And we copy the flags to the shadow PGD entry.  The page
-		 * number in the shadow PGD is the page we just allocated. */
-		*spgd = __pgd(__pa(ptepage) | pgd_flags(gpgd));
+		/*
+		 * And we copy the flags to the shadow PGD entry.  The page
+		 * number in the shadow PGD is the page we just allocated.
+		 */
+		set_pgd(spgd, __pgd(__pa(ptepage) | pgd_flags(gpgd)));
 	}
 
-	/* OK, now we look at the lower level in the Guest page table: keep its
-	 * address, because we might update it later. */
-	gpte_ptr = gpte_addr(gpgd, vaddr);
+#ifdef CONFIG_X86_PAE
+	gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
+	/* Middle level not present?  We can't map it in. */
+	if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
+		return false;
+
+	/* Now look at the matching shadow entry. */
+	spmd = spmd_addr(cpu, *spgd, vaddr);
+
+	if (!(pmd_flags(*spmd) & _PAGE_PRESENT)) {
+		/* No shadow entry: allocate a new shadow PTE page. */
+		unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
+
+		/*
+		 * This is not really the Guest's fault, but killing it is
+		 * simple for this corner case.
+		 */
+		if (!ptepage) {
+			kill_guest(cpu, "out of memory allocating pte page");
+			return false;
+		}
+
+		/* We check that the Guest pmd is OK. */
+		check_gpmd(cpu, gpmd);
+
+		/*
+		 * And we copy the flags to the shadow PMD entry.  The page
+		 * number in the shadow PMD is the page we just allocated.
+		 */
+		native_set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd)));
+	}
+
+	/*
+	 * OK, now we look at the lower level in the Guest page table: keep its
+	 * address, because we might update it later.
+	 */
+	gpte_ptr = gpte_addr(cpu, gpmd, vaddr);
+#else
+	/*
+	 * OK, now we look at the lower level in the Guest page table: keep its
+	 * address, because we might update it later.
+	 */
+	gpte_ptr = gpte_addr(cpu, gpgd, vaddr);
+#endif
+
+	/* Read the actual PTE value. */
 	gpte = lgread(cpu, gpte_ptr, pte_t);
 
 	/* If this page isn't in the Guest page tables, we can't page it in. */
 	if (!(pte_flags(gpte) & _PAGE_PRESENT))
 		return false;
 
-	/* Check they're not trying to write to a page the Guest wants
-	 * read-only (bit 2 of errcode == write). */
+	/*
+	 * Check they're not trying to write to a page the Guest wants
+	 * read-only (bit 2 of errcode == write).
+	 */
 	if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW))
 		return false;
 
@@ -249,8 +414,10 @@
 	if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER))
 		return false;
 
-	/* Check that the Guest PTE flags are OK, and the page number is below
-	 * the pfn_limit (ie. not mapping the Launcher binary). */
+	/*
+	 * Check that the Guest PTE flags are OK, and the page number is below
+	 * the pfn_limit (ie. not mapping the Launcher binary).
+	 */
 	check_gpte(cpu, gpte);
 
 	/* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */
@@ -259,30 +426,41 @@
 		gpte = pte_mkdirty(gpte);
 
 	/* Get the pointer to the shadow PTE entry we're going to set. */
-	spte = spte_addr(*spgd, vaddr);
-	/* If there was a valid shadow PTE entry here before, we release it.
-	 * This can happen with a write to a previously read-only entry. */
+	spte = spte_addr(cpu, *spgd, vaddr);
+
+	/*
+	 * If there was a valid shadow PTE entry here before, we release it.
+	 * This can happen with a write to a previously read-only entry.
+	 */
 	release_pte(*spte);
 
-	/* If this is a write, we insist that the Guest page is writable (the
-	 * final arg to gpte_to_spte()). */
+	/*
+	 * If this is a write, we insist that the Guest page is writable (the
+	 * final arg to gpte_to_spte()).
+	 */
 	if (pte_dirty(gpte))
 		*spte = gpte_to_spte(cpu, gpte, 1);
 	else
-		/* If this is a read, don't set the "writable" bit in the page
+		/*
+		 * If this is a read, don't set the "writable" bit in the page
 		 * table entry, even if the Guest says it's writable.  That way
 		 * we will come back here when a write does actually occur, so
-		 * we can update the Guest's _PAGE_DIRTY flag. */
-		*spte = gpte_to_spte(cpu, pte_wrprotect(gpte), 0);
+		 * we can update the Guest's _PAGE_DIRTY flag.
+		 */
+		native_set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0));
 
-	/* Finally, we write the Guest PTE entry back: we've set the
-	 * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */
+	/*
+	 * Finally, we write the Guest PTE entry back: we've set the
+	 * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags.
+	 */
 	lgwrite(cpu, gpte_ptr, pte_t, gpte);
 
-	/* The fault is fixed, the page table is populated, the mapping
+	/*
+	 * The fault is fixed, the page table is populated, the mapping
 	 * manipulated, the result returned and the code complete.  A small
 	 * delay and a trace of alliteration are the only indications the Guest
-	 * has that a page fault occurred at all. */
+	 * has that a page fault occurred at all.
+	 */
 	return true;
 }
 
@@ -295,42 +473,98 @@
  * mapped, so it's overkill.
  *
  * This is a quick version which answers the question: is this virtual address
- * mapped by the shadow page tables, and is it writable? */
+ * mapped by the shadow page tables, and is it writable?
+ */
 static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr)
 {
 	pgd_t *spgd;
 	unsigned long flags;
 
+#ifdef CONFIG_X86_PAE
+	pmd_t *spmd;
+#endif
 	/* Look at the current top level entry: is it present? */
 	spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
 	if (!(pgd_flags(*spgd) & _PAGE_PRESENT))
 		return false;
 
-	/* Check the flags on the pte entry itself: it must be present and
-	 * writable. */
-	flags = pte_flags(*(spte_addr(*spgd, vaddr)));
+#ifdef CONFIG_X86_PAE
+	spmd = spmd_addr(cpu, *spgd, vaddr);
+	if (!(pmd_flags(*spmd) & _PAGE_PRESENT))
+		return false;
+#endif
+
+	/*
+	 * Check the flags on the pte entry itself: it must be present and
+	 * writable.
+	 */
+	flags = pte_flags(*(spte_addr(cpu, *spgd, vaddr)));
 
 	return (flags & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW);
 }
 
-/* So, when pin_stack_pages() asks us to pin a page, we check if it's already
+/*
+ * So, when pin_stack_pages() asks us to pin a page, we check if it's already
  * in the page tables, and if not, we call demand_page() with error code 2
- * (meaning "write"). */
+ * (meaning "write").
+ */
 void pin_page(struct lg_cpu *cpu, unsigned long vaddr)
 {
 	if (!page_writable(cpu, vaddr) && !demand_page(cpu, vaddr, 2))
 		kill_guest(cpu, "bad stack page %#lx", vaddr);
 }
+/*:*/
 
-/*H:450 If we chase down the release_pgd() code, it looks like this: */
-static void release_pgd(struct lguest *lg, pgd_t *spgd)
+#ifdef CONFIG_X86_PAE
+static void release_pmd(pmd_t *spmd)
+{
+	/* If the entry's not present, there's nothing to release. */
+	if (pmd_flags(*spmd) & _PAGE_PRESENT) {
+		unsigned int i;
+		pte_t *ptepage = __va(pmd_pfn(*spmd) << PAGE_SHIFT);
+		/* For each entry in the page, we might need to release it. */
+		for (i = 0; i < PTRS_PER_PTE; i++)
+			release_pte(ptepage[i]);
+		/* Now we can free the page of PTEs */
+		free_page((long)ptepage);
+		/* And zero out the PMD entry so we never release it twice. */
+		native_set_pmd(spmd, __pmd(0));
+	}
+}
+
+static void release_pgd(pgd_t *spgd)
 {
 	/* If the entry's not present, there's nothing to release. */
 	if (pgd_flags(*spgd) & _PAGE_PRESENT) {
 		unsigned int i;
-		/* Converting the pfn to find the actual PTE page is easy: turn
+		pmd_t *pmdpage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
+
+		for (i = 0; i < PTRS_PER_PMD; i++)
+			release_pmd(&pmdpage[i]);
+
+		/* Now we can free the page of PMDs */
+		free_page((long)pmdpage);
+		/* And zero out the PGD entry so we never release it twice. */
+		set_pgd(spgd, __pgd(0));
+	}
+}
+
+#else /* !CONFIG_X86_PAE */
+/*H:450
+ * If we chase down the release_pgd() code, the non-PAE version looks like
+ * this.  The PAE version is almost identical, but instead of calling
+ * release_pte it calls release_pmd(), which looks much like this.
+ */
+static void release_pgd(pgd_t *spgd)
+{
+	/* If the entry's not present, there's nothing to release. */
+	if (pgd_flags(*spgd) & _PAGE_PRESENT) {
+		unsigned int i;
+		/*
+		 * Converting the pfn to find the actual PTE page is easy: turn
 		 * the page number into a physical address, then convert to a
-		 * virtual address (easy for kernel pages like this one). */
+		 * virtual address (easy for kernel pages like this one).
+		 */
 		pte_t *ptepage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
 		/* For each entry in the page, we might need to release it. */
 		for (i = 0; i < PTRS_PER_PTE; i++)
@@ -341,22 +575,27 @@
 		*spgd = __pgd(0);
 	}
 }
+#endif
 
-/*H:445 We saw flush_user_mappings() twice: once from the flush_user_mappings()
+/*H:445
+ * We saw flush_user_mappings() twice: once from the flush_user_mappings()
  * hypercall and once in new_pgdir() when we re-used a top-level pgdir page.
- * It simply releases every PTE page from 0 up to the Guest's kernel address. */
+ * It simply releases every PTE page from 0 up to the Guest's kernel address.
+ */
 static void flush_user_mappings(struct lguest *lg, int idx)
 {
 	unsigned int i;
 	/* Release every pgd entry up to the kernel's address. */
 	for (i = 0; i < pgd_index(lg->kernel_address); i++)
-		release_pgd(lg, lg->pgdirs[idx].pgdir + i);
+		release_pgd(lg->pgdirs[idx].pgdir + i);
 }
 
-/*H:440 (v) Flushing (throwing away) page tables,
+/*H:440
+ * (v) Flushing (throwing away) page tables,
  *
  * The Guest has a hypercall to throw away the page tables: it's used when a
- * large number of mappings have been changed. */
+ * large number of mappings have been changed.
+ */
 void guest_pagetable_flush_user(struct lg_cpu *cpu)
 {
 	/* Drop the userspace part of the current page table. */
@@ -369,7 +608,9 @@
 {
 	pgd_t gpgd;
 	pte_t gpte;
-
+#ifdef CONFIG_X86_PAE
+	pmd_t gpmd;
+#endif
 	/* First step: get the top-level Guest page table entry. */
 	gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
 	/* Toplevel not present?  We can't map it in. */
@@ -378,16 +619,25 @@
 		return -1UL;
 	}
 
-	gpte = lgread(cpu, gpte_addr(gpgd, vaddr), pte_t);
+#ifdef CONFIG_X86_PAE
+	gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
+	if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
+		kill_guest(cpu, "Bad address %#lx", vaddr);
+	gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t);
+#else
+	gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t);
+#endif
 	if (!(pte_flags(gpte) & _PAGE_PRESENT))
 		kill_guest(cpu, "Bad address %#lx", vaddr);
 
 	return pte_pfn(gpte) * PAGE_SIZE | (vaddr & ~PAGE_MASK);
 }
 
-/* We keep several page tables.  This is a simple routine to find the page
+/*
+ * We keep several page tables.  This is a simple routine to find the page
  * table (if any) corresponding to this top-level address the Guest has given
- * us. */
+ * us.
+ */
 static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
 {
 	unsigned int i;
@@ -397,17 +647,24 @@
 	return i;
 }
 
-/*H:435 And this is us, creating the new page directory.  If we really do
+/*H:435
+ * And this is us, creating the new page directory.  If we really do
  * allocate a new one (and so the kernel parts are not there), we set
- * blank_pgdir. */
+ * blank_pgdir.
+ */
 static unsigned int new_pgdir(struct lg_cpu *cpu,
 			      unsigned long gpgdir,
 			      int *blank_pgdir)
 {
 	unsigned int next;
+#ifdef CONFIG_X86_PAE
+	pmd_t *pmd_table;
+#endif
 
-	/* We pick one entry at random to throw out.  Choosing the Least
-	 * Recently Used might be better, but this is easy. */
+	/*
+	 * We pick one entry at random to throw out.  Choosing the Least
+	 * Recently Used might be better, but this is easy.
+	 */
 	next = random32() % ARRAY_SIZE(cpu->lg->pgdirs);
 	/* If it's never been allocated at all before, try now. */
 	if (!cpu->lg->pgdirs[next].pgdir) {
@@ -416,10 +673,31 @@
 		/* If the allocation fails, just keep using the one we have */
 		if (!cpu->lg->pgdirs[next].pgdir)
 			next = cpu->cpu_pgd;
-		else
-			/* This is a blank page, so there are no kernel
-			 * mappings: caller must map the stack! */
+		else {
+#ifdef CONFIG_X86_PAE
+			/*
+			 * In PAE mode, allocate a pmd page and populate the
+			 * last pgd entry.
+			 */
+			pmd_table = (pmd_t *)get_zeroed_page(GFP_KERNEL);
+			if (!pmd_table) {
+				free_page((long)cpu->lg->pgdirs[next].pgdir);
+				set_pgd(cpu->lg->pgdirs[next].pgdir, __pgd(0));
+				next = cpu->cpu_pgd;
+			} else {
+				set_pgd(cpu->lg->pgdirs[next].pgdir +
+					SWITCHER_PGD_INDEX,
+					__pgd(__pa(pmd_table) | _PAGE_PRESENT));
+				/*
+				 * This is a blank page, so there are no kernel
+				 * mappings: caller must map the stack!
+				 */
+				*blank_pgdir = 1;
+			}
+#else
 			*blank_pgdir = 1;
+#endif
+		}
 	}
 	/* Record which Guest toplevel this shadows. */
 	cpu->lg->pgdirs[next].gpgdir = gpgdir;
@@ -429,19 +707,23 @@
 	return next;
 }
 
-/*H:430 (iv) Switching page tables
+/*H:430
+ * (iv) Switching page tables
  *
- * Now we've seen all the page table setting and manipulation, let's see what
+ * Now we've seen all the page table setting and manipulation, let's see
  * what happens when the Guest changes page tables (ie. changes the top-level
- * pgdir).  This occurs on almost every context switch. */
+ * pgdir).  This occurs on almost every context switch.
+ */
 void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
 {
 	int newpgdir, repin = 0;
 
 	/* Look to see if we have this one already. */
 	newpgdir = find_pgdir(cpu->lg, pgtable);
-	/* If not, we allocate or mug an existing one: if it's a fresh one,
-	 * repin gets set to 1. */
+	/*
+	 * If not, we allocate or mug an existing one: if it's a fresh one,
+	 * repin gets set to 1.
+	 */
 	if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
 		newpgdir = new_pgdir(cpu, pgtable, &repin);
 	/* Change the current pgd index to the new one. */
@@ -451,25 +733,46 @@
 		pin_stack_pages(cpu);
 }
 
-/*H:470 Finally, a routine which throws away everything: all PGD entries in all
+/*H:470
+ * Finally, a routine which throws away everything: all PGD entries in all
  * the shadow page tables, including the Guest's kernel mappings.  This is used
- * when we destroy the Guest. */
+ * when we destroy the Guest.
+ */
 static void release_all_pagetables(struct lguest *lg)
 {
 	unsigned int i, j;
 
 	/* Every shadow pagetable this Guest has */
 	for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
-		if (lg->pgdirs[i].pgdir)
+		if (lg->pgdirs[i].pgdir) {
+#ifdef CONFIG_X86_PAE
+			pgd_t *spgd;
+			pmd_t *pmdpage;
+			unsigned int k;
+
+			/* Get the last pmd page. */
+			spgd = lg->pgdirs[i].pgdir + SWITCHER_PGD_INDEX;
+			pmdpage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
+
+			/*
+			 * And release the pmd entries of that pmd page,
+			 * except for the switcher pmd.
+			 */
+			for (k = 0; k < SWITCHER_PMD_INDEX; k++)
+				release_pmd(&pmdpage[k]);
+#endif
 			/* Every PGD entry except the Switcher at the top */
 			for (j = 0; j < SWITCHER_PGD_INDEX; j++)
-				release_pgd(lg, lg->pgdirs[i].pgdir + j);
+				release_pgd(lg->pgdirs[i].pgdir + j);
+		}
 }
 
-/* We also throw away everything when a Guest tells us it's changed a kernel
+/*
+ * We also throw away everything when a Guest tells us it's changed a kernel
  * mapping.  Since kernel mappings are in every page table, it's easiest to
  * throw them all away.  This traps the Guest in amber for a while as
- * everything faults back in, but it's rare. */
+ * everything faults back in, but it's rare.
+ */
 void guest_pagetable_clear_all(struct lg_cpu *cpu)
 {
 	release_all_pagetables(cpu->lg);
@@ -477,15 +780,19 @@
 	pin_stack_pages(cpu);
 }
 /*:*/
-/*M:009 Since we throw away all mappings when a kernel mapping changes, our
+
+/*M:009
+ * Since we throw away all mappings when a kernel mapping changes, our
  * performance sucks for guests using highmem.  In fact, a guest with
  * PAGE_OFFSET 0xc0000000 (the default) and more than about 700MB of RAM is
  * usually slower than a Guest with less memory.
  *
  * This, of course, cannot be fixed.  It would take some kind of... well, I
- * don't know, but the term "puissant code-fu" comes to mind. :*/
+ * don't know, but the term "puissant code-fu" comes to mind.
+:*/
 
-/*H:420 This is the routine which actually sets the page table entry for then
+/*H:420
+ * This is the routine which actually sets the page table entry for then
  * "idx"'th shadow page table.
  *
  * Normally, we can just throw out the old entry and replace it with 0: if they
@@ -504,28 +811,46 @@
 {
 	/* Look up the matching shadow page directory entry. */
 	pgd_t *spgd = spgd_addr(cpu, idx, vaddr);
+#ifdef CONFIG_X86_PAE
+	pmd_t *spmd;
+#endif
 
 	/* If the top level isn't present, there's no entry to update. */
 	if (pgd_flags(*spgd) & _PAGE_PRESENT) {
-		/* Otherwise, we start by releasing the existing entry. */
-		pte_t *spte = spte_addr(*spgd, vaddr);
-		release_pte(*spte);
+#ifdef CONFIG_X86_PAE
+		spmd = spmd_addr(cpu, *spgd, vaddr);
+		if (pmd_flags(*spmd) & _PAGE_PRESENT) {
+#endif
+			/* Otherwise, start by releasing the existing entry. */
+			pte_t *spte = spte_addr(cpu, *spgd, vaddr);
+			release_pte(*spte);
 
-		/* If they're setting this entry as dirty or accessed, we might
-		 * as well put that entry they've given us in now.  This shaves
-		 * 10% off a copy-on-write micro-benchmark. */
-		if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) {
-			check_gpte(cpu, gpte);
-			*spte = gpte_to_spte(cpu, gpte,
-					     pte_flags(gpte) & _PAGE_DIRTY);
-		} else
-			/* Otherwise kill it and we can demand_page() it in
-			 * later. */
-			*spte = __pte(0);
+			/*
+			 * If they're setting this entry as dirty or accessed,
+			 * we might as well put that entry they've given us in
+			 * now.  This shaves 10% off a copy-on-write
+			 * micro-benchmark.
+			 */
+			if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) {
+				check_gpte(cpu, gpte);
+				native_set_pte(spte,
+						gpte_to_spte(cpu, gpte,
+						pte_flags(gpte) & _PAGE_DIRTY));
+			} else {
+				/*
+				 * Otherwise kill it and we can demand_page()
+				 * it in later.
+				 */
+				native_set_pte(spte, __pte(0));
+			}
+#ifdef CONFIG_X86_PAE
+		}
+#endif
 	}
 }
 
-/*H:410 Updating a PTE entry is a little trickier.
+/*H:410
+ * Updating a PTE entry is a little trickier.
  *
  * We keep track of several different page tables (the Guest uses one for each
  * process, so it makes sense to cache at least a few).  Each of these have
@@ -534,12 +859,15 @@
  * all the page tables, not just the current one.  This is rare.
  *
  * The benefit is that when we have to track a new page table, we can keep all
- * the kernel mappings.  This speeds up context switch immensely. */
+ * the kernel mappings.  This speeds up context switch immensely.
+ */
 void guest_set_pte(struct lg_cpu *cpu,
 		   unsigned long gpgdir, unsigned long vaddr, pte_t gpte)
 {
-	/* Kernel mappings must be changed on all top levels.  Slow, but doesn't
-	 * happen often. */
+	/*
+	 * Kernel mappings must be changed on all top levels.  Slow, but doesn't
+	 * happen often.
+	 */
 	if (vaddr >= cpu->lg->kernel_address) {
 		unsigned int i;
 		for (i = 0; i < ARRAY_SIZE(cpu->lg->pgdirs); i++)
@@ -568,12 +896,10 @@
  *
  * So with that in mind here's our code to to update a (top-level) PGD entry:
  */
-void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 idx)
+void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 idx)
 {
 	int pgdir;
 
-	/* The kernel seems to try to initialize this early on: we ignore its
-	 * attempts to map over the Switcher. */
 	if (idx >= SWITCHER_PGD_INDEX)
 		return;
 
@@ -581,26 +907,48 @@
 	pgdir = find_pgdir(lg, gpgdir);
 	if (pgdir < ARRAY_SIZE(lg->pgdirs))
 		/* ... throw it away. */
-		release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx);
+		release_pgd(lg->pgdirs[pgdir].pgdir + idx);
 }
 
-/* Once we know how much memory we have we can construct simple identity
- * (which set virtual == physical) and linear mappings
- * which will get the Guest far enough into the boot to create its own.
+#ifdef CONFIG_X86_PAE
+/* For setting a mid-level, we just throw everything away.  It's easy. */
+void guest_set_pmd(struct lguest *lg, unsigned long pmdp, u32 idx)
+{
+	guest_pagetable_clear_all(&lg->cpus[0]);
+}
+#endif
+
+/*H:505
+ * To get through boot, we construct simple identity page mappings (which
+ * set virtual == physical) and linear mappings which will get the Guest far
+ * enough into the boot to create its own.  The linear mapping means we
+ * simplify the Guest boot, but it makes assumptions about their PAGE_OFFSET,
+ * as you'll see.
  *
  * We lay them out of the way, just below the initrd (which is why we need to
- * know its size here). */
+ * know its size here).
+ */
 static unsigned long setup_pagetables(struct lguest *lg,
 				      unsigned long mem,
 				      unsigned long initrd_size)
 {
 	pgd_t __user *pgdir;
 	pte_t __user *linear;
-	unsigned int mapped_pages, i, linear_pages, phys_linear;
 	unsigned long mem_base = (unsigned long)lg->mem_base;
+	unsigned int mapped_pages, i, linear_pages;
+#ifdef CONFIG_X86_PAE
+	pmd_t __user *pmds;
+	unsigned int j;
+	pgd_t pgd;
+	pmd_t pmd;
+#else
+	unsigned int phys_linear;
+#endif
 
-	/* We have mapped_pages frames to map, so we need
-	 * linear_pages page tables to map them. */
+	/*
+	 * We have mapped_pages frames to map, so we need linear_pages page
+	 * tables to map them.
+	 */
 	mapped_pages = mem / PAGE_SIZE;
 	linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE;
 
@@ -610,8 +958,17 @@
 	/* Now we use the next linear_pages pages as pte pages */
 	linear = (void *)pgdir - linear_pages * PAGE_SIZE;
 
-	/* Linear mapping is easy: put every page's address into the
-	 * mapping in order. */
+#ifdef CONFIG_X86_PAE
+	/*
+	 * And the single mid page goes below that.  We only use one, but
+	 * that's enough to map 1G, which definitely gets us through boot.
+	 */
+	pmds = (void *)linear - PAGE_SIZE;
+#endif
+	/*
+	 * Linear mapping is easy: put every page's address into the
+	 * mapping in order.
+	 */
 	for (i = 0; i < mapped_pages; i++) {
 		pte_t pte;
 		pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER));
@@ -619,70 +976,143 @@
 			return -EFAULT;
 	}
 
-	/* The top level points to the linear page table pages above.
-	 * We setup the identity and linear mappings here. */
+#ifdef CONFIG_X86_PAE
+	/*
+	 * Make the Guest PMD entries point to the corresponding place in the
+	 * linear mapping (up to one page worth of PMD).
+	 */
+	for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD;
+	     i += PTRS_PER_PTE, j++) {
+		/* FIXME: native_set_pmd is overkill here. */
+		native_set_pmd(&pmd, __pmd(((unsigned long)(linear + i)
+		- mem_base) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
+
+		if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0)
+			return -EFAULT;
+	}
+
+	/* One PGD entry, pointing to that PMD page. */
+	set_pgd(&pgd, __pgd(((u32)pmds - mem_base) | _PAGE_PRESENT));
+	/* Copy it in as the first PGD entry (ie. addresses 0-1G). */
+	if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0)
+		return -EFAULT;
+	/*
+	 * And the third PGD entry (ie. addresses 3G-4G).
+	 *
+	 * FIXME: This assumes that PAGE_OFFSET for the Guest is 0xC0000000.
+	 */
+	if (copy_to_user(&pgdir[3], &pgd, sizeof(pgd)) != 0)
+		return -EFAULT;
+#else
+	/*
+	 * The top level points to the linear page table pages above.
+	 * We setup the identity and linear mappings here.
+	 */
 	phys_linear = (unsigned long)linear - mem_base;
 	for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) {
 		pgd_t pgd;
+		/*
+		 * Create a PGD entry which points to the right part of the
+		 * linear PTE pages.
+		 */
 		pgd = __pgd((phys_linear + i * sizeof(pte_t)) |
 			    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
 
+		/*
+		 * Copy it into the PGD page at 0 and PAGE_OFFSET.
+		 */
 		if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd))
 		    || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET)
 					   + i / PTRS_PER_PTE],
 				    &pgd, sizeof(pgd)))
 			return -EFAULT;
 	}
+#endif
 
-	/* We return the top level (guest-physical) address: remember where
-	 * this is. */
+	/*
+	 * We return the top level (guest-physical) address: we remember where
+	 * this is to write it into lguest_data when the Guest initializes.
+	 */
 	return (unsigned long)pgdir - mem_base;
 }
 
-/*H:500 (vii) Setting up the page tables initially.
+/*H:500
+ * (vii) Setting up the page tables initially.
  *
  * When a Guest is first created, the Launcher tells us where the toplevel of
- * its first page table is.  We set some things up here: */
+ * its first page table is.  We set some things up here:
+ */
 int init_guest_pagetable(struct lguest *lg)
 {
 	u64 mem;
 	u32 initrd_size;
 	struct boot_params __user *boot = (struct boot_params *)lg->mem_base;
-
-	/* Get the Guest memory size and the ramdisk size from the boot header
-	 * located at lg->mem_base (Guest address 0). */
+#ifdef CONFIG_X86_PAE
+	pgd_t *pgd;
+	pmd_t *pmd_table;
+#endif
+	/*
+	 * Get the Guest memory size and the ramdisk size from the boot header
+	 * located at lg->mem_base (Guest address 0).
+	 */
 	if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem))
 	    || get_user(initrd_size, &boot->hdr.ramdisk_size))
 		return -EFAULT;
 
-	/* We start on the first shadow page table, and give it a blank PGD
-	 * page. */
+	/*
+	 * We start on the first shadow page table, and give it a blank PGD
+	 * page.
+	 */
 	lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size);
 	if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir))
 		return lg->pgdirs[0].gpgdir;
 	lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
 	if (!lg->pgdirs[0].pgdir)
 		return -ENOMEM;
+
+#ifdef CONFIG_X86_PAE
+	/* For PAE, we also create the initial mid-level. */
+	pgd = lg->pgdirs[0].pgdir;
+	pmd_table = (pmd_t *) get_zeroed_page(GFP_KERNEL);
+	if (!pmd_table)
+		return -ENOMEM;
+
+	set_pgd(pgd + SWITCHER_PGD_INDEX,
+		__pgd(__pa(pmd_table) | _PAGE_PRESENT));
+#endif
+
+	/* This is the current page table. */
 	lg->cpus[0].cpu_pgd = 0;
 	return 0;
 }
 
-/* When the Guest calls LHCALL_LGUEST_INIT we do more setup. */
+/*H:508 When the Guest calls LHCALL_LGUEST_INIT we do more setup. */
 void page_table_guest_data_init(struct lg_cpu *cpu)
 {
 	/* We get the kernel address: above this is all kernel memory. */
 	if (get_user(cpu->lg->kernel_address,
-		     &cpu->lg->lguest_data->kernel_address)
-	    /* We tell the Guest that it can't use the top 4MB of virtual
-	     * addresses used by the Switcher. */
-	    || put_user(4U*1024*1024, &cpu->lg->lguest_data->reserve_mem)
-	    || put_user(cpu->lg->pgdirs[0].gpgdir, &cpu->lg->lguest_data->pgdir))
+		&cpu->lg->lguest_data->kernel_address)
+		/*
+		 * We tell the Guest that it can't use the top 2 or 4 MB
+		 * of virtual addresses used by the Switcher.
+		 */
+		|| put_user(RESERVE_MEM * 1024 * 1024,
+			&cpu->lg->lguest_data->reserve_mem)
+		|| put_user(cpu->lg->pgdirs[0].gpgdir,
+			&cpu->lg->lguest_data->pgdir))
 		kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
 
-	/* In flush_user_mappings() we loop from 0 to
+	/*
+	 * In flush_user_mappings() we loop from 0 to
 	 * "pgd_index(lg->kernel_address)".  This assumes it won't hit the
-	 * Switcher mappings, so check that now. */
+	 * Switcher mappings, so check that now.
+	 */
+#ifdef CONFIG_X86_PAE
+	if (pgd_index(cpu->lg->kernel_address) == SWITCHER_PGD_INDEX &&
+		pmd_index(cpu->lg->kernel_address) == SWITCHER_PMD_INDEX)
+#else
 	if (pgd_index(cpu->lg->kernel_address) >= SWITCHER_PGD_INDEX)
+#endif
 		kill_guest(cpu, "bad kernel address %#lx",
 				 cpu->lg->kernel_address);
 }
@@ -699,35 +1129,60 @@
 		free_page((long)lg->pgdirs[i].pgdir);
 }
 
-/*H:480 (vi) Mapping the Switcher when the Guest is about to run.
+/*H:480
+ * (vi) Mapping the Switcher when the Guest is about to run.
  *
  * The Switcher and the two pages for this CPU need to be visible in the
  * Guest (and not the pages for other CPUs).  We have the appropriate PTE pages
  * for each CPU already set up, we just need to hook them in now we know which
- * Guest is about to run on this CPU. */
+ * Guest is about to run on this CPU.
+ */
 void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
 {
 	pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
-	pgd_t switcher_pgd;
 	pte_t regs_pte;
 	unsigned long pfn;
 
-	/* Make the last PGD entry for this Guest point to the Switcher's PTE
-	 * page for this CPU (with appropriate flags). */
-	switcher_pgd = __pgd(__pa(switcher_pte_page) | __PAGE_KERNEL);
+#ifdef CONFIG_X86_PAE
+	pmd_t switcher_pmd;
+	pmd_t *pmd_table;
+
+	/* FIXME: native_set_pmd is overkill here. */
+	native_set_pmd(&switcher_pmd, pfn_pmd(__pa(switcher_pte_page) >>
+		       PAGE_SHIFT, PAGE_KERNEL_EXEC));
+
+	/* Figure out where the pmd page is, by reading the PGD, and converting
+	 * it to a virtual address. */
+	pmd_table = __va(pgd_pfn(cpu->lg->
+			pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX])
+								<< PAGE_SHIFT);
+	/* Now write it into the shadow page table. */
+	native_set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd);
+#else
+	pgd_t switcher_pgd;
+
+	/*
+	 * Make the last PGD entry for this Guest point to the Switcher's PTE
+	 * page for this CPU (with appropriate flags).
+	 */
+	switcher_pgd = __pgd(__pa(switcher_pte_page) | __PAGE_KERNEL_EXEC);
 
 	cpu->lg->pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX] = switcher_pgd;
 
-	/* We also change the Switcher PTE page.  When we're running the Guest,
+#endif
+	/*
+	 * We also change the Switcher PTE page.  When we're running the Guest,
 	 * we want the Guest's "regs" page to appear where the first Switcher
 	 * page for this CPU is.  This is an optimization: when the Switcher
 	 * saves the Guest registers, it saves them into the first page of this
 	 * CPU's "struct lguest_pages": if we make sure the Guest's register
 	 * page is already mapped there, we don't have to copy them out
-	 * again. */
+	 * again.
+	 */
 	pfn = __pa(cpu->regs_page) >> PAGE_SHIFT;
-	regs_pte = pfn_pte(pfn, __pgprot(__PAGE_KERNEL));
-	switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTRS_PER_PTE] = regs_pte;
+	native_set_pte(&regs_pte, pfn_pte(pfn, PAGE_KERNEL));
+	native_set_pte(&switcher_pte_page[pte_index((unsigned long)pages)],
+			regs_pte);
 }
 /*:*/
 
@@ -739,10 +1194,12 @@
 		free_page((long)switcher_pte_page(i));
 }
 
-/*H:520 Setting up the Switcher PTE page for given CPU is fairly easy, given
+/*H:520
+ * Setting up the Switcher PTE page for given CPU is fairly easy, given
  * the CPU number and the "struct page"s for the Switcher code itself.
  *
- * Currently the Switcher is less than a page long, so "pages" is always 1. */
+ * Currently the Switcher is less than a page long, so "pages" is always 1.
+ */
 static __init void populate_switcher_pte_page(unsigned int cpu,
 					      struct page *switcher_page[],
 					      unsigned int pages)
@@ -752,24 +1209,27 @@
 
 	/* The first entries are easy: they map the Switcher code. */
 	for (i = 0; i < pages; i++) {
-		pte[i] = mk_pte(switcher_page[i],
-				__pgprot(_PAGE_PRESENT|_PAGE_ACCESSED));
+		native_set_pte(&pte[i], mk_pte(switcher_page[i],
+				__pgprot(_PAGE_PRESENT|_PAGE_ACCESSED)));
 	}
 
 	/* The only other thing we map is this CPU's pair of pages. */
 	i = pages + cpu*2;
 
 	/* First page (Guest registers) is writable from the Guest */
-	pte[i] = pfn_pte(page_to_pfn(switcher_page[i]),
-			 __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW));
+	native_set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]),
+			 __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW)));
 
-	/* The second page contains the "struct lguest_ro_state", and is
-	 * read-only. */
-	pte[i+1] = pfn_pte(page_to_pfn(switcher_page[i+1]),
-			   __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED));
+	/*
+	 * The second page contains the "struct lguest_ro_state", and is
+	 * read-only.
+	 */
+	native_set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]),
+			   __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED)));
 }
 
-/* We've made it through the page table code.  Perhaps our tired brains are
+/*
+ * We've made it through the page table code.  Perhaps our tired brains are
  * still processing the details, or perhaps we're simply glad it's over.
  *
  * If nothing else, note that all this complexity in juggling shadow page tables
@@ -778,10 +1238,13 @@
  * uses exotic direct Guest pagetable manipulation, and why both Intel and AMD
  * have implemented shadow page table support directly into hardware.
  *
- * There is just one file remaining in the Host. */
+ * There is just one file remaining in the Host.
+ */
 
-/*H:510 At boot or module load time, init_pagetables() allocates and populates
- * the Switcher PTE page for each CPU. */
+/*H:510
+ * At boot or module load time, init_pagetables() allocates and populates
+ * the Switcher PTE page for each CPU.
+ */
 __init int init_pagetables(struct page **switcher_page, unsigned int pages)
 {
 	unsigned int i;
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/segments.c linux-libre-2.6.31-gnu/drivers/lguest/segments.c
--- linux-libre-2.6.30-gnu/drivers/lguest/segments.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/segments.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,5 @@
-/*P:600 The x86 architecture has segments, which involve a table of descriptors
+/*P:600
+ * The x86 architecture has segments, which involve a table of descriptors
  * which can be used to do funky things with virtual address interpretation.
  * We originally used to use segments so the Guest couldn't alter the
  * Guest<->Host Switcher, and then we had to trim Guest segments, and restore
@@ -8,7 +9,8 @@
  *
  * In these modern times, the segment handling code consists of simple sanity
  * checks, and the worst you'll experience reading this code is butterfly-rash
- * from frolicking through its parklike serenity. :*/
+ * from frolicking through its parklike serenity.
+:*/
 #include "lg.h"
 
 /*H:600
@@ -41,10 +43,12 @@
  * begin.
  */
 
-/* There are several entries we don't let the Guest set.  The TSS entry is the
+/*
+ * There are several entries we don't let the Guest set.  The TSS entry is the
  * "Task State Segment" which controls all kinds of delicate things.  The
  * LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the
- * the Guest can't be trusted to deal with double faults. */
+ * the Guest can't be trusted to deal with double faults.
+ */
 static bool ignored_gdt(unsigned int num)
 {
 	return (num == GDT_ENTRY_TSS
@@ -53,42 +57,52 @@
 		|| num == GDT_ENTRY_DOUBLEFAULT_TSS);
 }
 
-/*H:630 Once the Guest gave us new GDT entries, we fix them up a little.  We
+/*H:630
+ * Once the Guest gave us new GDT entries, we fix them up a little.  We
  * don't care if they're invalid: the worst that can happen is a General
  * Protection Fault in the Switcher when it restores a Guest segment register
  * which tries to use that entry.  Then we kill the Guest for causing such a
- * mess: the message will be "unhandled trap 256". */
+ * mess: the message will be "unhandled trap 256".
+ */
 static void fixup_gdt_table(struct lg_cpu *cpu, unsigned start, unsigned end)
 {
 	unsigned int i;
 
 	for (i = start; i < end; i++) {
-		/* We never copy these ones to real GDT, so we don't care what
-		 * they say */
+		/*
+		 * We never copy these ones to real GDT, so we don't care what
+		 * they say
+		 */
 		if (ignored_gdt(i))
 			continue;
 
-		/* Segment descriptors contain a privilege level: the Guest is
+		/*
+		 * Segment descriptors contain a privilege level: the Guest is
 		 * sometimes careless and leaves this as 0, even though it's
-		 * running at privilege level 1.  If so, we fix it here. */
+		 * running at privilege level 1.  If so, we fix it here.
+		 */
 		if ((cpu->arch.gdt[i].b & 0x00006000) == 0)
 			cpu->arch.gdt[i].b |= (GUEST_PL << 13);
 
-		/* Each descriptor has an "accessed" bit.  If we don't set it
+		/*
+		 * Each descriptor has an "accessed" bit.  If we don't set it
 		 * now, the CPU will try to set it when the Guest first loads
 		 * that entry into a segment register.  But the GDT isn't
-		 * writable by the Guest, so bad things can happen. */
+		 * writable by the Guest, so bad things can happen.
+		 */
 		cpu->arch.gdt[i].b |= 0x00000100;
 	}
 }
 
-/*H:610 Like the IDT, we never simply use the GDT the Guest gives us.  We keep
+/*H:610
+ * Like the IDT, we never simply use the GDT the Guest gives us.  We keep
  * a GDT for each CPU, and copy across the Guest's entries each time we want to
  * run the Guest on that CPU.
  *
  * This routine is called at boot or modprobe time for each CPU to set up the
  * constant GDT entries: the ones which are the same no matter what Guest we're
- * running. */
+ * running.
+ */
 void setup_default_gdt_entries(struct lguest_ro_state *state)
 {
 	struct desc_struct *gdt = state->guest_gdt;
@@ -98,30 +112,37 @@
 	gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
 	gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
 
-	/* The TSS segment refers to the TSS entry for this particular CPU.
+	/*
+	 * The TSS segment refers to the TSS entry for this particular CPU.
 	 * Forgive the magic flags: the 0x8900 means the entry is Present, it's
 	 * privilege level 0 Available 386 TSS system segment, and the 0x67
-	 * means Saturn is eclipsed by Mercury in the twelfth house. */
+	 * means Saturn is eclipsed by Mercury in the twelfth house.
+	 */
 	gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16);
 	gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000)
 		| ((tss >> 16) & 0x000000FF);
 }
 
-/* This routine sets up the initial Guest GDT for booting.  All entries start
- * as 0 (unusable). */
+/*
+ * This routine sets up the initial Guest GDT for booting.  All entries start
+ * as 0 (unusable).
+ */
 void setup_guest_gdt(struct lg_cpu *cpu)
 {
-	/* Start with full 0-4G segments... */
+	/*
+	 * Start with full 0-4G segments...except the Guest is allowed to use
+	 * them, so set the privilege level appropriately in the flags.
+	 */
 	cpu->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
 	cpu->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
-	/* ...except the Guest is allowed to use them, so set the privilege
-	 * level appropriately in the flags. */
 	cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
 	cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
 }
 
-/*H:650 An optimization of copy_gdt(), for just the three "thead-local storage"
- * entries. */
+/*H:650
+ * An optimization of copy_gdt(), for just the three "thead-local storage"
+ * entries.
+ */
 void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt)
 {
 	unsigned int i;
@@ -130,42 +151,54 @@
 		gdt[i] = cpu->arch.gdt[i];
 }
 
-/*H:640 When the Guest is run on a different CPU, or the GDT entries have
- * changed, copy_gdt() is called to copy the Guest's GDT entries across to this
- * CPU's GDT. */
+/*H:640
+ * When the Guest is run on a different CPU, or the GDT entries have changed,
+ * copy_gdt() is called to copy the Guest's GDT entries across to this CPU's
+ * GDT.
+ */
 void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt)
 {
 	unsigned int i;
 
-	/* The default entries from setup_default_gdt_entries() are not
-	 * replaced.  See ignored_gdt() above. */
+	/*
+	 * The default entries from setup_default_gdt_entries() are not
+	 * replaced.  See ignored_gdt() above.
+	 */
 	for (i = 0; i < GDT_ENTRIES; i++)
 		if (!ignored_gdt(i))
 			gdt[i] = cpu->arch.gdt[i];
 }
 
-/*H:620 This is where the Guest asks us to load a new GDT entry
- * (LHCALL_LOAD_GDT_ENTRY).  We tweak the entry and copy it in. */
+/*H:620
+ * This is where the Guest asks us to load a new GDT entry
+ * (LHCALL_LOAD_GDT_ENTRY).  We tweak the entry and copy it in.
+ */
 void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi)
 {
-	/* We assume the Guest has the same number of GDT entries as the
-	 * Host, otherwise we'd have to dynamically allocate the Guest GDT. */
-	if (num > ARRAY_SIZE(cpu->arch.gdt))
+	/*
+	 * We assume the Guest has the same number of GDT entries as the
+	 * Host, otherwise we'd have to dynamically allocate the Guest GDT.
+	 */
+	if (num >= ARRAY_SIZE(cpu->arch.gdt))
 		kill_guest(cpu, "too many gdt entries %i", num);
 
 	/* Set it up, then fix it. */
 	cpu->arch.gdt[num].a = lo;
 	cpu->arch.gdt[num].b = hi;
 	fixup_gdt_table(cpu, num, num+1);
-	/* Mark that the GDT changed so the core knows it has to copy it again,
-	 * even if the Guest is run on the same CPU. */
+	/*
+	 * Mark that the GDT changed so the core knows it has to copy it again,
+	 * even if the Guest is run on the same CPU.
+	 */
 	cpu->changed |= CHANGED_GDT;
 }
 
-/* This is the fast-track version for just changing the three TLS entries.
+/*
+ * This is the fast-track version for just changing the three TLS entries.
  * Remember that this happens on every context switch, so it's worth
  * optimizing.  But wouldn't it be neater to have a single hypercall to cover
- * both cases? */
+ * both cases?
+ */
 void guest_load_tls(struct lg_cpu *cpu, unsigned long gtls)
 {
 	struct desc_struct *tls = &cpu->arch.gdt[GDT_ENTRY_TLS_MIN];
@@ -175,7 +208,6 @@
 	/* Note that just the TLS entries have changed. */
 	cpu->changed |= CHANGED_GDT_TLS;
 }
-/*:*/
 
 /*H:660
  * With this, we have finished the Host.
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/x86/core.c linux-libre-2.6.31-gnu/drivers/lguest/x86/core.c
--- linux-libre-2.6.30-gnu/drivers/lguest/x86/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/x86/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,13 +17,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/*P:450 This file contains the x86-specific lguest code.  It used to be all
+/*P:450
+ * This file contains the x86-specific lguest code.  It used to be all
  * mixed in with drivers/lguest/core.c but several foolhardy code slashers
  * wrestled most of the dependencies out to here in preparation for porting
  * lguest to other architectures (see what I mean by foolhardy?).
  *
  * This also contains a couple of non-obvious setup and teardown pieces which
- * were implemented after days of debugging pain. :*/
+ * were implemented after days of debugging pain.
+:*/
 #include <linux/kernel.h>
 #include <linux/start_kernel.h>
 #include <linux/string.h>
@@ -82,25 +84,33 @@
  */
 static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages)
 {
-	/* Copying all this data can be quite expensive.  We usually run the
+	/*
+	 * Copying all this data can be quite expensive.  We usually run the
 	 * same Guest we ran last time (and that Guest hasn't run anywhere else
 	 * meanwhile).  If that's not the case, we pretend everything in the
-	 * Guest has changed. */
+	 * Guest has changed.
+	 */
 	if (__get_cpu_var(last_cpu) != cpu || cpu->last_pages != pages) {
 		__get_cpu_var(last_cpu) = cpu;
 		cpu->last_pages = pages;
 		cpu->changed = CHANGED_ALL;
 	}
 
-	/* These copies are pretty cheap, so we do them unconditionally: */
-	/* Save the current Host top-level page directory. */
+	/*
+	 * These copies are pretty cheap, so we do them unconditionally: */
+	/* Save the current Host top-level page directory.
+	 */
 	pages->state.host_cr3 = __pa(current->mm->pgd);
-	/* Set up the Guest's page tables to see this CPU's pages (and no
-	 * other CPU's pages). */
+	/*
+	 * Set up the Guest's page tables to see this CPU's pages (and no
+	 * other CPU's pages).
+	 */
 	map_switcher_in_guest(cpu, pages);
-	/* Set up the two "TSS" members which tell the CPU what stack to use
+	/*
+	 * Set up the two "TSS" members which tell the CPU what stack to use
 	 * for traps which do directly into the Guest (ie. traps at privilege
-	 * level 1). */
+	 * level 1).
+	 */
 	pages->state.guest_tss.sp1 = cpu->esp1;
 	pages->state.guest_tss.ss1 = cpu->ss1;
 
@@ -125,97 +135,126 @@
 	/* This is a dummy value we need for GCC's sake. */
 	unsigned int clobber;
 
-	/* Copy the guest-specific information into this CPU's "struct
-	 * lguest_pages". */
+	/*
+	 * Copy the guest-specific information into this CPU's "struct
+	 * lguest_pages".
+	 */
 	copy_in_guest_info(cpu, pages);
 
-	/* Set the trap number to 256 (impossible value).  If we fault while
+	/*
+	 * Set the trap number to 256 (impossible value).  If we fault while
 	 * switching to the Guest (bad segment registers or bug), this will
-	 * cause us to abort the Guest. */
+	 * cause us to abort the Guest.
+	 */
 	cpu->regs->trapnum = 256;
 
-	/* Now: we push the "eflags" register on the stack, then do an "lcall".
+	/*
+	 * Now: we push the "eflags" register on the stack, then do an "lcall".
 	 * This is how we change from using the kernel code segment to using
 	 * the dedicated lguest code segment, as well as jumping into the
 	 * Switcher.
 	 *
 	 * The lcall also pushes the old code segment (KERNEL_CS) onto the
 	 * stack, then the address of this call.  This stack layout happens to
-	 * exactly match the stack layout created by an interrupt... */
+	 * exactly match the stack layout created by an interrupt...
+	 */
 	asm volatile("pushf; lcall *lguest_entry"
-		     /* This is how we tell GCC that %eax ("a") and %ebx ("b")
-		      * are changed by this routine.  The "=" means output. */
+		     /*
+		      * This is how we tell GCC that %eax ("a") and %ebx ("b")
+		      * are changed by this routine.  The "=" means output.
+		      */
 		     : "=a"(clobber), "=b"(clobber)
-		     /* %eax contains the pages pointer.  ("0" refers to the
+		     /*
+		      * %eax contains the pages pointer.  ("0" refers to the
 		      * 0-th argument above, ie "a").  %ebx contains the
 		      * physical address of the Guest's top-level page
-		      * directory. */
+		      * directory.
+		      */
 		     : "0"(pages), "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir))
-		     /* We tell gcc that all these registers could change,
+		     /*
+		      * We tell gcc that all these registers could change,
 		      * which means we don't have to save and restore them in
-		      * the Switcher. */
+		      * the Switcher.
+		      */
 		     : "memory", "%edx", "%ecx", "%edi", "%esi");
 }
 /*:*/
 
-/*M:002 There are hooks in the scheduler which we can register to tell when we
+/*M:002
+ * There are hooks in the scheduler which we can register to tell when we
  * get kicked off the CPU (preempt_notifier_register()).  This would allow us
  * to lazily disable SYSENTER which would regain some performance, and should
  * also simplify copy_in_guest_info().  Note that we'd still need to restore
  * things when we exit to Launcher userspace, but that's fairly easy.
  *
- * We could also try using this hooks for PGE, but that might be too expensive.
+ * We could also try using these hooks for PGE, but that might be too expensive.
  *
- * The hooks were designed for KVM, but we can also put them to good use. :*/
+ * The hooks were designed for KVM, but we can also put them to good use.
+:*/
 
-/*H:040 This is the i386-specific code to setup and run the Guest.  Interrupts
- * are disabled: we own the CPU. */
+/*H:040
+ * This is the i386-specific code to setup and run the Guest.  Interrupts
+ * are disabled: we own the CPU.
+ */
 void lguest_arch_run_guest(struct lg_cpu *cpu)
 {
-	/* Remember the awfully-named TS bit?  If the Guest has asked to set it
+	/*
+	 * Remember the awfully-named TS bit?  If the Guest has asked to set it
 	 * we set it now, so we can trap and pass that trap to the Guest if it
-	 * uses the FPU. */
+	 * uses the FPU.
+	 */
 	if (cpu->ts)
 		unlazy_fpu(current);
 
-	/* SYSENTER is an optimized way of doing system calls.  We can't allow
+	/*
+	 * SYSENTER is an optimized way of doing system calls.  We can't allow
 	 * it because it always jumps to privilege level 0.  A normal Guest
 	 * won't try it because we don't advertise it in CPUID, but a malicious
 	 * Guest (or malicious Guest userspace program) could, so we tell the
-	 * CPU to disable it before running the Guest. */
+	 * CPU to disable it before running the Guest.
+	 */
 	if (boot_cpu_has(X86_FEATURE_SEP))
 		wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
 
-	/* Now we actually run the Guest.  It will return when something
+	/*
+	 * Now we actually run the Guest.  It will return when something
 	 * interesting happens, and we can examine its registers to see what it
-	 * was doing. */
+	 * was doing.
+	 */
 	run_guest_once(cpu, lguest_pages(raw_smp_processor_id()));
 
-	/* Note that the "regs" structure contains two extra entries which are
+	/*
+	 * Note that the "regs" structure contains two extra entries which are
 	 * not really registers: a trap number which says what interrupt or
 	 * trap made the switcher code come back, and an error code which some
-	 * traps set.  */
+	 * traps set.
+	 */
 
 	 /* Restore SYSENTER if it's supposed to be on. */
 	 if (boot_cpu_has(X86_FEATURE_SEP))
 		wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
 
-	/* If the Guest page faulted, then the cr2 register will tell us the
+	/*
+	 * If the Guest page faulted, then the cr2 register will tell us the
 	 * bad virtual address.  We have to grab this now, because once we
 	 * re-enable interrupts an interrupt could fault and thus overwrite
-	 * cr2, or we could even move off to a different CPU. */
+	 * cr2, or we could even move off to a different CPU.
+	 */
 	if (cpu->regs->trapnum == 14)
 		cpu->arch.last_pagefault = read_cr2();
-	/* Similarly, if we took a trap because the Guest used the FPU,
+	/*
+	 * Similarly, if we took a trap because the Guest used the FPU,
 	 * we have to restore the FPU it expects to see.
 	 * math_state_restore() may sleep and we may even move off to
 	 * a different CPU. So all the critical stuff should be done
-	 * before this.  */
+	 * before this.
+	 */
 	else if (cpu->regs->trapnum == 7)
 		math_state_restore();
 }
 
-/*H:130 Now we've examined the hypercall code; our Guest can make requests.
+/*H:130
+ * Now we've examined the hypercall code; our Guest can make requests.
  * Our Guest is usually so well behaved; it never tries to do things it isn't
  * allowed to, and uses hypercalls instead.  Unfortunately, Linux's paravirtual
  * infrastructure isn't quite complete, because it doesn't contain replacements
@@ -225,26 +264,33 @@
  *
  * When the Guest uses one of these instructions, we get a trap (General
  * Protection Fault) and come here.  We see if it's one of those troublesome
- * instructions and skip over it.  We return true if we did. */
+ * instructions and skip over it.  We return true if we did.
+ */
 static int emulate_insn(struct lg_cpu *cpu)
 {
 	u8 insn;
 	unsigned int insnlen = 0, in = 0, shift = 0;
-	/* The eip contains the *virtual* address of the Guest's instruction:
-	 * guest_pa just subtracts the Guest's page_offset. */
+	/*
+	 * The eip contains the *virtual* address of the Guest's instruction:
+	 * guest_pa just subtracts the Guest's page_offset.
+	 */
 	unsigned long physaddr = guest_pa(cpu, cpu->regs->eip);
 
-	/* This must be the Guest kernel trying to do something, not userspace!
+	/*
+	 * This must be the Guest kernel trying to do something, not userspace!
 	 * The bottom two bits of the CS segment register are the privilege
-	 * level. */
+	 * level.
+	 */
 	if ((cpu->regs->cs & 3) != GUEST_PL)
 		return 0;
 
 	/* Decoding x86 instructions is icky. */
 	insn = lgread(cpu, physaddr, u8);
 
-	/* 0x66 is an "operand prefix".  It means it's using the upper 16 bits
-	   of the eax register. */
+	/*
+	 * 0x66 is an "operand prefix".  It means it's using the upper 16 bits
+	 * of the eax register.
+	 */
 	if (insn == 0x66) {
 		shift = 16;
 		/* The instruction is 1 byte so far, read the next byte. */
@@ -252,8 +298,10 @@
 		insn = lgread(cpu, physaddr + insnlen, u8);
 	}
 
-	/* We can ignore the lower bit for the moment and decode the 4 opcodes
-	 * we need to emulate. */
+	/*
+	 * We can ignore the lower bit for the moment and decode the 4 opcodes
+	 * we need to emulate.
+	 */
 	switch (insn & 0xFE) {
 	case 0xE4: /* in     <next byte>,%al */
 		insnlen += 2;
@@ -274,9 +322,11 @@
 		return 0;
 	}
 
-	/* If it was an "IN" instruction, they expect the result to be read
+	/*
+	 * If it was an "IN" instruction, they expect the result to be read
 	 * into %eax, so we change %eax.  We always return all-ones, which
-	 * traditionally means "there's nothing there". */
+	 * traditionally means "there's nothing there".
+	 */
 	if (in) {
 		/* Lower bit tells is whether it's a 16 or 32 bit access */
 		if (insn & 0x1)
@@ -290,7 +340,8 @@
 	return 1;
 }
 
-/* Our hypercalls mechanism used to be based on direct software interrupts.
+/*
+ * Our hypercalls mechanism used to be based on direct software interrupts.
  * After Anthony's "Refactor hypercall infrastructure" kvm patch, we decided to
  * change over to using kvm hypercalls.
  *
@@ -318,16 +369,20 @@
  */
 static void rewrite_hypercall(struct lg_cpu *cpu)
 {
-	/* This are the opcodes we use to patch the Guest.  The opcode for "int
+	/*
+	 * This are the opcodes we use to patch the Guest.  The opcode for "int
 	 * $0x1f" is "0xcd 0x1f" but vmcall instruction is 3 bytes long, so we
-	 * complete the sequence with a NOP (0x90). */
+	 * complete the sequence with a NOP (0x90).
+	 */
 	u8 insn[3] = {0xcd, 0x1f, 0x90};
 
 	__lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
-	/* The above write might have caused a copy of that page to be made
+	/*
+	 * The above write might have caused a copy of that page to be made
 	 * (if it was read-only).  We need to make sure the Guest has
 	 * up-to-date pagetables.  As this doesn't happen often, we can just
-	 * drop them all. */
+	 * drop them all.
+	 */
 	guest_pagetable_clear_all(cpu);
 }
 
@@ -335,9 +390,11 @@
 {
 	u8 insn[3];
 
-	/* This must be the Guest kernel trying to do something.
+	/*
+	 * This must be the Guest kernel trying to do something.
 	 * The bottom two bits of the CS segment register are the privilege
-	 * level. */
+	 * level.
+	 */
 	if ((cpu->regs->cs & 3) != GUEST_PL)
 		return false;
 
@@ -351,86 +408,105 @@
 {
 	switch (cpu->regs->trapnum) {
 	case 13: /* We've intercepted a General Protection Fault. */
-		/* Check if this was one of those annoying IN or OUT
+		/*
+		 * Check if this was one of those annoying IN or OUT
 		 * instructions which we need to emulate.  If so, we just go
-		 * back into the Guest after we've done it. */
+		 * back into the Guest after we've done it.
+		 */
 		if (cpu->regs->errcode == 0) {
 			if (emulate_insn(cpu))
 				return;
 		}
-		/* If KVM is active, the vmcall instruction triggers a
-		 * General Protection Fault.  Normally it triggers an
-		 * invalid opcode fault (6): */
+		/*
+		 * If KVM is active, the vmcall instruction triggers a General
+		 * Protection Fault.  Normally it triggers an invalid opcode
+		 * fault (6):
+		 */
 	case 6:
-		/* We need to check if ring == GUEST_PL and
-		 * faulting instruction == vmcall. */
+		/*
+		 * We need to check if ring == GUEST_PL and faulting
+		 * instruction == vmcall.
+		 */
 		if (is_hypercall(cpu)) {
 			rewrite_hypercall(cpu);
 			return;
 		}
 		break;
 	case 14: /* We've intercepted a Page Fault. */
-		/* The Guest accessed a virtual address that wasn't mapped.
+		/*
+		 * The Guest accessed a virtual address that wasn't mapped.
 		 * This happens a lot: we don't actually set up most of the page
 		 * tables for the Guest at all when we start: as it runs it asks
 		 * for more and more, and we set them up as required. In this
 		 * case, we don't even tell the Guest that the fault happened.
 		 *
 		 * The errcode tells whether this was a read or a write, and
-		 * whether kernel or userspace code. */
+		 * whether kernel or userspace code.
+		 */
 		if (demand_page(cpu, cpu->arch.last_pagefault,
 				cpu->regs->errcode))
 			return;
 
-		/* OK, it's really not there (or not OK): the Guest needs to
+		/*
+		 * OK, it's really not there (or not OK): the Guest needs to
 		 * know.  We write out the cr2 value so it knows where the
 		 * fault occurred.
 		 *
 		 * Note that if the Guest were really messed up, this could
 		 * happen before it's done the LHCALL_LGUEST_INIT hypercall, so
-		 * lg->lguest_data could be NULL */
+		 * lg->lguest_data could be NULL
+		 */
 		if (cpu->lg->lguest_data &&
 		    put_user(cpu->arch.last_pagefault,
 			     &cpu->lg->lguest_data->cr2))
 			kill_guest(cpu, "Writing cr2");
 		break;
 	case 7: /* We've intercepted a Device Not Available fault. */
-		/* If the Guest doesn't want to know, we already restored the
-		 * Floating Point Unit, so we just continue without telling
-		 * it. */
+		/*
+		 * If the Guest doesn't want to know, we already restored the
+		 * Floating Point Unit, so we just continue without telling it.
+		 */
 		if (!cpu->ts)
 			return;
 		break;
 	case 32 ... 255:
-		/* These values mean a real interrupt occurred, in which case
+		/*
+		 * These values mean a real interrupt occurred, in which case
 		 * the Host handler has already been run. We just do a
 		 * friendly check if another process should now be run, then
-		 * return to run the Guest again */
+		 * return to run the Guest again
+		 */
 		cond_resched();
 		return;
 	case LGUEST_TRAP_ENTRY:
-		/* Our 'struct hcall_args' maps directly over our regs: we set
-		 * up the pointer now to indicate a hypercall is pending. */
+		/*
+		 * Our 'struct hcall_args' maps directly over our regs: we set
+		 * up the pointer now to indicate a hypercall is pending.
+		 */
 		cpu->hcall = (struct hcall_args *)cpu->regs;
 		return;
 	}
 
 	/* We didn't handle the trap, so it needs to go to the Guest. */
 	if (!deliver_trap(cpu, cpu->regs->trapnum))
-		/* If the Guest doesn't have a handler (either it hasn't
+		/*
+		 * If the Guest doesn't have a handler (either it hasn't
 		 * registered any yet, or it's one of the faults we don't let
-		 * it handle), it dies with this cryptic error message. */
+		 * it handle), it dies with this cryptic error message.
+		 */
 		kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)",
 			   cpu->regs->trapnum, cpu->regs->eip,
 			   cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault
 			   : cpu->regs->errcode);
 }
 
-/* Now we can look at each of the routines this calls, in increasing order of
+/*
+ * Now we can look at each of the routines this calls, in increasing order of
  * complexity: do_hypercalls(), emulate_insn(), maybe_do_interrupt(),
  * deliver_trap() and demand_page().  After all those, we'll be ready to
  * examine the Switcher, and our philosophical understanding of the Host/Guest
- * duality will be complete. :*/
+ * duality will be complete.
+:*/
 static void adjust_pge(void *on)
 {
 	if (on)
@@ -439,13 +515,16 @@
 		write_cr4(read_cr4() & ~X86_CR4_PGE);
 }
 
-/*H:020 Now the Switcher is mapped and every thing else is ready, we need to do
- * some more i386-specific initialization. */
+/*H:020
+ * Now the Switcher is mapped and every thing else is ready, we need to do
+ * some more i386-specific initialization.
+ */
 void __init lguest_arch_host_init(void)
 {
 	int i;
 
-	/* Most of the i386/switcher.S doesn't care that it's been moved; on
+	/*
+	 * Most of the i386/switcher.S doesn't care that it's been moved; on
 	 * Intel, jumps are relative, and it doesn't access any references to
 	 * external code or data.
 	 *
@@ -453,7 +532,8 @@
 	 * addresses are placed in a table (default_idt_entries), so we need to
 	 * update the table with the new addresses.  switcher_offset() is a
 	 * convenience function which returns the distance between the
-	 * compiled-in switcher code and the high-mapped copy we just made. */
+	 * compiled-in switcher code and the high-mapped copy we just made.
+	 */
 	for (i = 0; i < IDT_ENTRIES; i++)
 		default_idt_entries[i] += switcher_offset();
 
@@ -468,63 +548,81 @@
 	for_each_possible_cpu(i) {
 		/* lguest_pages() returns this CPU's two pages. */
 		struct lguest_pages *pages = lguest_pages(i);
-		/* This is a convenience pointer to make the code fit one
-		 * statement to a line. */
+		/* This is a convenience pointer to make the code neater. */
 		struct lguest_ro_state *state = &pages->state;
 
-		/* The Global Descriptor Table: the Host has a different one
+		/*
+		 * The Global Descriptor Table: the Host has a different one
 		 * for each CPU.  We keep a descriptor for the GDT which says
 		 * where it is and how big it is (the size is actually the last
-		 * byte, not the size, hence the "-1"). */
+		 * byte, not the size, hence the "-1").
+		 */
 		state->host_gdt_desc.size = GDT_SIZE-1;
 		state->host_gdt_desc.address = (long)get_cpu_gdt_table(i);
 
-		/* All CPUs on the Host use the same Interrupt Descriptor
+		/*
+		 * All CPUs on the Host use the same Interrupt Descriptor
 		 * Table, so we just use store_idt(), which gets this CPU's IDT
-		 * descriptor. */
+		 * descriptor.
+		 */
 		store_idt(&state->host_idt_desc);
 
-		/* The descriptors for the Guest's GDT and IDT can be filled
+		/*
+		 * The descriptors for the Guest's GDT and IDT can be filled
 		 * out now, too.  We copy the GDT & IDT into ->guest_gdt and
-		 * ->guest_idt before actually running the Guest. */
+		 * ->guest_idt before actually running the Guest.
+		 */
 		state->guest_idt_desc.size = sizeof(state->guest_idt)-1;
 		state->guest_idt_desc.address = (long)&state->guest_idt;
 		state->guest_gdt_desc.size = sizeof(state->guest_gdt)-1;
 		state->guest_gdt_desc.address = (long)&state->guest_gdt;
 
-		/* We know where we want the stack to be when the Guest enters
+		/*
+		 * We know where we want the stack to be when the Guest enters
 		 * the Switcher: in pages->regs.  The stack grows upwards, so
-		 * we start it at the end of that structure. */
+		 * we start it at the end of that structure.
+		 */
 		state->guest_tss.sp0 = (long)(&pages->regs + 1);
-		/* And this is the GDT entry to use for the stack: we keep a
-		 * couple of special LGUEST entries. */
+		/*
+		 * And this is the GDT entry to use for the stack: we keep a
+		 * couple of special LGUEST entries.
+		 */
 		state->guest_tss.ss0 = LGUEST_DS;
 
-		/* x86 can have a finegrained bitmap which indicates what I/O
+		/*
+		 * x86 can have a finegrained bitmap which indicates what I/O
 		 * ports the process can use.  We set it to the end of our
-		 * structure, meaning "none". */
+		 * structure, meaning "none".
+		 */
 		state->guest_tss.io_bitmap_base = sizeof(state->guest_tss);
 
-		/* Some GDT entries are the same across all Guests, so we can
-		 * set them up now. */
+		/*
+		 * Some GDT entries are the same across all Guests, so we can
+		 * set them up now.
+		 */
 		setup_default_gdt_entries(state);
 		/* Most IDT entries are the same for all Guests, too.*/
 		setup_default_idt_entries(state, default_idt_entries);
 
-		/* The Host needs to be able to use the LGUEST segments on this
-		 * CPU, too, so put them in the Host GDT. */
+		/*
+		 * The Host needs to be able to use the LGUEST segments on this
+		 * CPU, too, so put them in the Host GDT.
+		 */
 		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
 		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
 	}
 
-	/* In the Switcher, we want the %cs segment register to use the
+	/*
+	 * In the Switcher, we want the %cs segment register to use the
 	 * LGUEST_CS GDT entry: we've put that in the Host and Guest GDTs, so
 	 * it will be undisturbed when we switch.  To change %cs and jump we
-	 * need this structure to feed to Intel's "lcall" instruction. */
+	 * need this structure to feed to Intel's "lcall" instruction.
+	 */
 	lguest_entry.offset = (long)switch_to_guest + switcher_offset();
 	lguest_entry.segment = LGUEST_CS;
 
-	/* Finally, we need to turn off "Page Global Enable".  PGE is an
+	/*
+	 * Finally, we need to turn off "Page Global Enable".  PGE is an
 	 * optimization where page table entries are specially marked to show
 	 * they never change.  The Host kernel marks all the kernel pages this
 	 * way because it's always present, even when userspace is running.
@@ -534,16 +632,21 @@
 	 * you'll get really weird bugs that you'll chase for two days.
 	 *
 	 * I used to turn PGE off every time we switched to the Guest and back
-	 * on when we return, but that slowed the Switcher down noticibly. */
+	 * on when we return, but that slowed the Switcher down noticibly.
+	 */
 
-	/* We don't need the complexity of CPUs coming and going while we're
-	 * doing this. */
+	/*
+	 * We don't need the complexity of CPUs coming and going while we're
+	 * doing this.
+	 */
 	get_online_cpus();
 	if (cpu_has_pge) { /* We have a broader idea of "global". */
 		/* Remember that this was originally set (for cleanup). */
 		cpu_had_pge = 1;
-		/* adjust_pge is a helper function which sets or unsets the PGE
-		 * bit on its CPU, depending on the argument (0 == unset). */
+		/*
+		 * adjust_pge is a helper function which sets or unsets the PGE
+		 * bit on its CPU, depending on the argument (0 == unset).
+		 */
 		on_each_cpu(adjust_pge, (void *)0, 1);
 		/* Turn off the feature in the global feature set. */
 		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
@@ -590,26 +693,32 @@
 {
 	u32 tsc_speed;
 
-	/* The pointer to the Guest's "struct lguest_data" is the only argument.
-	 * We check that address now. */
+	/*
+	 * The pointer to the Guest's "struct lguest_data" is the only argument.
+	 * We check that address now.
+	 */
 	if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1,
 			       sizeof(*cpu->lg->lguest_data)))
 		return -EFAULT;
 
-	/* Having checked it, we simply set lg->lguest_data to point straight
+	/*
+	 * Having checked it, we simply set lg->lguest_data to point straight
 	 * into the Launcher's memory at the right place and then use
 	 * copy_to_user/from_user from now on, instead of lgread/write.  I put
 	 * this in to show that I'm not immune to writing stupid
-	 * optimizations. */
+	 * optimizations.
+	 */
 	cpu->lg->lguest_data = cpu->lg->mem_base + cpu->hcall->arg1;
 
-	/* We insist that the Time Stamp Counter exist and doesn't change with
+	/*
+	 * We insist that the Time Stamp Counter exist and doesn't change with
 	 * cpu frequency.  Some devious chip manufacturers decided that TSC
 	 * changes could be handled in software.  I decided that time going
 	 * backwards might be good for benchmarks, but it's bad for users.
 	 *
 	 * We also insist that the TSC be stable: the kernel detects unreliable
-	 * TSCs for its own purposes, and we use that here. */
+	 * TSCs for its own purposes, and we use that here.
+	 */
 	if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
 		tsc_speed = tsc_khz;
 	else
@@ -625,38 +734,47 @@
 }
 /*:*/
 
-/*L:030 lguest_arch_setup_regs()
+/*L:030
+ * lguest_arch_setup_regs()
  *
  * Most of the Guest's registers are left alone: we used get_zeroed_page() to
- * allocate the structure, so they will be 0. */
+ * allocate the structure, so they will be 0.
+ */
 void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start)
 {
 	struct lguest_regs *regs = cpu->regs;
 
-	/* There are four "segment" registers which the Guest needs to boot:
+	/*
+	 * There are four "segment" registers which the Guest needs to boot:
 	 * The "code segment" register (cs) refers to the kernel code segment
 	 * __KERNEL_CS, and the "data", "extra" and "stack" segment registers
 	 * refer to the kernel data segment __KERNEL_DS.
 	 *
 	 * The privilege level is packed into the lower bits.  The Guest runs
-	 * at privilege level 1 (GUEST_PL).*/
+	 * at privilege level 1 (GUEST_PL).
+	 */
 	regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
 	regs->cs = __KERNEL_CS|GUEST_PL;
 
-	/* The "eflags" register contains miscellaneous flags.  Bit 1 (0x002)
+	/*
+	 * The "eflags" register contains miscellaneous flags.  Bit 1 (0x002)
 	 * is supposed to always be "1".  Bit 9 (0x200) controls whether
 	 * interrupts are enabled.  We always leave interrupts enabled while
-	 * running the Guest. */
+	 * running the Guest.
+	 */
 	regs->eflags = X86_EFLAGS_IF | 0x2;
 
-	/* The "Extended Instruction Pointer" register says where the Guest is
-	 * running. */
+	/*
+	 * The "Extended Instruction Pointer" register says where the Guest is
+	 * running.
+	 */
 	regs->eip = start;
 
-	/* %esi points to our boot information, at physical address 0, so don't
-	 * touch it. */
+	/*
+	 * %esi points to our boot information, at physical address 0, so don't
+	 * touch it.
+	 */
 
-	/* There are a couple of GDT entries the Guest expects when first
-	 * booting. */
+	/* There are a couple of GDT entries the Guest expects at boot. */
 	setup_guest_gdt(cpu);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/lguest/x86/switcher_32.S linux-libre-2.6.31-gnu/drivers/lguest/x86/switcher_32.S
--- linux-libre-2.6.30-gnu/drivers/lguest/x86/switcher_32.S	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/lguest/x86/switcher_32.S	2009-09-09 18:13:59.000000000 -0400
@@ -1,12 +1,15 @@
-/*P:900 This is the Switcher: code which sits at 0xFFC00000 astride both the
- * Host and Guest to do the low-level Guest<->Host switch.  It is as simple as
- * it can be made, but it's naturally very specific to x86.
+/*P:900
+ * This is the Switcher: code which sits at 0xFFC00000 (or 0xFFE00000) astride
+ * both the Host and Guest to do the low-level Guest<->Host switch.  It is as
+ * simple as it can be made, but it's naturally very specific to x86.
  *
  * You have now completed Preparation.  If this has whet your appetite; if you
  * are feeling invigorated and refreshed then the next, more challenging stage
- * can be found in "make Guest". :*/
+ * can be found in "make Guest".
+ :*/
 
-/*M:012 Lguest is meant to be simple: my rule of thumb is that 1% more LOC must
+/*M:012
+ * Lguest is meant to be simple: my rule of thumb is that 1% more LOC must
  * gain at least 1% more performance.  Since neither LOC nor performance can be
  * measured beforehand, it generally means implementing a feature then deciding
  * if it's worth it.  And once it's implemented, who can say no?
@@ -31,11 +34,14 @@
  * Host (which is actually really easy).
  *
  * Two questions remain.  Would the performance gain outweigh the complexity?
- * And who would write the verse documenting it? :*/
+ * And who would write the verse documenting it?
+:*/
 
-/*M:011 Lguest64 handles NMI.  This gave me NMI envy (until I looked at their
+/*M:011
+ * Lguest64 handles NMI.  This gave me NMI envy (until I looked at their
  * code).  It's worth doing though, since it would let us use oprofile in the
- * Host when a Guest is running. :*/
+ * Host when a Guest is running.
+:*/
 
 /*S:100
  * Welcome to the Switcher itself!
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/macio_asic.c linux-libre-2.6.31-gnu/drivers/macintosh/macio_asic.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/macio_asic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/macio_asic.c	2009-09-09 18:13:59.000000000 -0400
@@ -378,6 +378,17 @@
 	dev->ofdev.dev.bus = &macio_bus_type;
 	dev->ofdev.dev.release = macio_release_dev;
 
+#ifdef CONFIG_PCI
+	/* Set the DMA ops to the ones from the PCI device, this could be
+	 * fishy if we didn't know that on PowerMac it's always direct ops
+	 * or iommu ops that will work fine
+	 */
+	dev->ofdev.dev.archdata.dma_ops =
+		chip->lbus.pdev->dev.archdata.dma_ops;
+	dev->ofdev.dev.archdata.dma_data =
+		chip->lbus.pdev->dev.archdata.dma_data;
+#endif /* CONFIG_PCI */
+
 #ifdef DEBUG
 	printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n",
 	       dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj);
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/therm_adt746x.c linux-libre-2.6.31-gnu/drivers/macintosh/therm_adt746x.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/therm_adt746x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/therm_adt746x.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,7 @@
 #define CONFIG_REG   0x40
 #define MANUAL_MASK  0xe0
 #define AUTO_MASK    0x20
+#define INVERT_MASK  0x10
 
 static u8 TEMP_REG[3]    = {0x26, 0x25, 0x27}; /* local, sensor1, sensor2 */
 static u8 LIMIT_REG[3]   = {0x6b, 0x6a, 0x6c}; /* local, sensor1, sensor2 */
@@ -71,7 +72,7 @@
 		 "(default 0)");
 
 struct thermostat {
-	struct i2c_client	clt;
+	struct i2c_client	*clt;
 	u8			temps[3];
 	u8			cached_temp[3];
 	u8			initial_limits[3];
@@ -86,9 +87,6 @@
 static struct thermostat* thermostat;
 static struct task_struct *thread_therm = NULL;
 
-static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
-				 int busno);
-
 static void write_both_fan_speed(struct thermostat *th, int speed);
 static void write_fan_speed(struct thermostat *th, int speed, int fan);
 
@@ -100,7 +98,7 @@
 	
 	tmp[0] = reg;
 	tmp[1] = data;
-	rc = i2c_master_send(&th->clt, (const char *)tmp, 2);
+	rc = i2c_master_send(th->clt, (const char *)tmp, 2);
 	if (rc < 0)
 		return rc;
 	if (rc != 2)
@@ -115,12 +113,12 @@
 	int rc;
 
 	reg_addr = (u8)reg;
-	rc = i2c_master_send(&th->clt, &reg_addr, 1);
+	rc = i2c_master_send(th->clt, &reg_addr, 1);
 	if (rc < 0)
 		return rc;
 	if (rc != 1)
 		return -ENODEV;
-	rc = i2c_master_recv(&th->clt, (char *)&data, 1);
+	rc = i2c_master_recv(th->clt, (char *)&data, 1);
 	if (rc < 0)
 		return rc;
 	return data;
@@ -130,26 +128,36 @@
 attach_thermostat(struct i2c_adapter *adapter)
 {
 	unsigned long bus_no;
+	struct i2c_board_info info;
+	struct i2c_client *client;
 
 	if (strncmp(adapter->name, "uni-n", 5))
 		return -ENODEV;
 	bus_no = simple_strtoul(adapter->name + 6, NULL, 10);
 	if (bus_no != therm_bus)
 		return -ENODEV;
-	return attach_one_thermostat(adapter, therm_address, bus_no);
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, "therm_adt746x", I2C_NAME_SIZE);
+	info.addr = therm_address;
+	client = i2c_new_device(adapter, &info);
+	if (!client)
+		return -ENODEV;
+
+	/*
+	 * Let i2c-core delete that device on driver removal.
+	 * This is safe because i2c-core holds the core_lock mutex for us.
+	 */
+	list_add_tail(&client->detected, &client->driver->clients);
+	return 0;
 }
 
 static int
-detach_thermostat(struct i2c_adapter *adapter)
+remove_thermostat(struct i2c_client *client)
 {
-	struct thermostat* th;
+	struct thermostat *th = i2c_get_clientdata(client);
 	int i;
 	
-	if (thermostat == NULL)
-		return 0;
-
-	th = thermostat;
-
 	if (thread_therm != NULL) {
 		kthread_stop(thread_therm);
 	}
@@ -165,8 +173,6 @@
 
 	write_both_fan_speed(th, -1);
 
-	i2c_detach_client(&th->clt);
-
 	thermostat = NULL;
 
 	kfree(th);
@@ -174,14 +180,6 @@
 	return 0;
 }
 
-static struct i2c_driver thermostat_driver = {  
-	.driver = {
-		.name	= "therm_adt746x",
-	},
-	.attach_adapter	= attach_thermostat,
-	.detach_adapter	= detach_thermostat,
-};
-
 static int read_fan_speed(struct thermostat *th, u8 addr)
 {
 	u8 tmp[2];
@@ -229,7 +227,8 @@
 	
 	if (speed >= 0) {
 		manual = read_reg(th, MANUAL_MODE[fan]);
-		write_reg(th, MANUAL_MODE[fan], manual|MANUAL_MASK);
+		write_reg(th, MANUAL_MODE[fan],
+			(manual|MANUAL_MASK) & (~INVERT_MASK));
 		write_reg(th, FAN_SPD_SET[fan], speed);
 	} else {
 		/* back to automatic */
@@ -369,8 +368,8 @@
 		th->limits[i] = default_limits_local[i] + limit_adjust;
 }
 
-static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
-				 int busno)
+static int probe_thermostat(struct i2c_client *client,
+			    const struct i2c_device_id *id)
 {
 	struct thermostat* th;
 	int rc;
@@ -383,16 +382,12 @@
 	if (!th)
 		return -ENOMEM;
 
-	th->clt.addr = addr;
-	th->clt.adapter = adapter;
-	th->clt.driver = &thermostat_driver;
-	strcpy(th->clt.name, "thermostat");
+	i2c_set_clientdata(client, th);
+	th->clt = client;
 
 	rc = read_reg(th, 0);
 	if (rc < 0) {
-		printk(KERN_ERR "adt746x: Thermostat failed to read config "
-				"from bus %d !\n",
-				busno);
+		dev_err(&client->dev, "Thermostat failed to read config!\n");
 		kfree(th);
 		return -ENODEV;
 	}
@@ -421,14 +416,6 @@
 
 	thermostat = th;
 
-	if (i2c_attach_client(&th->clt)) {
-		printk(KERN_INFO "adt746x: Thermostat failed to attach "
-				 "client !\n");
-		thermostat = NULL;
-		kfree(th);
-		return -ENODEV;
-	}
-
 	/* be sure to really write fan speed the first time */
 	th->last_speed[0] = -2;
 	th->last_speed[1] = -2;
@@ -454,6 +441,21 @@
 	return 0;
 }
 
+static const struct i2c_device_id therm_adt746x_id[] = {
+	{ "therm_adt746x", 0 },
+	{ }
+};
+
+static struct i2c_driver thermostat_driver = {
+	.driver = {
+		.name	= "therm_adt746x",
+	},
+	.attach_adapter	= attach_thermostat,
+	.probe = probe_thermostat,
+	.remove = remove_thermostat,
+	.id_table = therm_adt746x_id,
+};
+
 /* 
  * Now, unfortunately, sysfs doesn't give us a nice void * we could
  * pass around to the attribute functions, so we don't really have
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/therm_pm72.c linux-libre-2.6.31-gnu/drivers/macintosh/therm_pm72.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/therm_pm72.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/therm_pm72.c	2009-09-09 18:13:59.000000000 -0400
@@ -287,22 +287,6 @@
 };
 
 /*
- * i2c_driver structure to attach to the host i2c controller
- */
-
-static int therm_pm72_attach(struct i2c_adapter *adapter);
-static int therm_pm72_detach(struct i2c_adapter *adapter);
-
-static struct i2c_driver therm_pm72_driver =
-{
-	.driver = {
-		.name	= "therm_pm72",
-	},
-	.attach_adapter	= therm_pm72_attach,
-	.detach_adapter	= therm_pm72_detach,
-};
-
-/*
  * Utility function to create an i2c_client structure and
  * attach it to one of u3 adapters
  */
@@ -310,6 +294,7 @@
 {
 	struct i2c_client *clt;
 	struct i2c_adapter *adap;
+	struct i2c_board_info info;
 
 	if (id & 0x200)
 		adap = k2;
@@ -320,31 +305,21 @@
 	if (adap == NULL)
 		return NULL;
 
-	clt = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (clt == NULL)
-		return NULL;
-
-	clt->addr = (id >> 1) & 0x7f;
-	clt->adapter = adap;
-	clt->driver = &therm_pm72_driver;
-	strncpy(clt->name, name, I2C_NAME_SIZE-1);
-
-	if (i2c_attach_client(clt)) {
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = (id >> 1) & 0x7f;
+	strlcpy(info.type, "therm_pm72", I2C_NAME_SIZE);
+	clt = i2c_new_device(adap, &info);
+	if (!clt) {
 		printk(KERN_ERR "therm_pm72: Failed to attach to i2c ID 0x%x\n", id);
-		kfree(clt);
 		return NULL;
 	}
-	return clt;
-}
 
-/*
- * Utility function to get rid of the i2c_client structure
- * (will also detach from the adapter hopepfully)
- */
-static void detach_i2c_chip(struct i2c_client *clt)
-{
-	i2c_detach_client(clt);
-	kfree(clt);
+	/*
+	 * Let i2c-core delete that device on driver removal.
+	 * This is safe because i2c-core holds the core_lock mutex for us.
+	 */
+	list_add_tail(&clt->detected, &clt->driver->clients);
+	return clt;
 }
 
 /*
@@ -1203,8 +1178,6 @@
 
 	return 0;
  fail:
-	if (state->monitor)
-		detach_i2c_chip(state->monitor);
 	state->monitor = NULL;
 	
 	return -ENODEV;
@@ -1232,7 +1205,6 @@
 		device_remove_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm);
 	}
 
-	detach_i2c_chip(state->monitor);
 	state->monitor = NULL;
 }
 
@@ -1407,7 +1379,6 @@
 	device_remove_file(&of_dev->dev, &dev_attr_backside_temperature);
 	device_remove_file(&of_dev->dev, &dev_attr_backside_fan_pwm);
 
-	detach_i2c_chip(state->monitor);
 	state->monitor = NULL;
 }
  
@@ -1532,7 +1503,6 @@
 	device_remove_file(&of_dev->dev, &dev_attr_drives_temperature);
 	device_remove_file(&of_dev->dev, &dev_attr_drives_fan_rpm);
 
-	detach_i2c_chip(state->monitor);
 	state->monitor = NULL;
 }
 
@@ -1654,7 +1624,6 @@
 
 	device_remove_file(&of_dev->dev, &dev_attr_dimms_temperature);
 
-	detach_i2c_chip(state->monitor);
 	state->monitor = NULL;
 }
 
@@ -1779,7 +1748,6 @@
 	device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
 	device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
 
-	detach_i2c_chip(state->monitor);
 	state->monitor = NULL;
 }
 
@@ -2008,8 +1976,6 @@
  */
 static void detach_fcu(void)
 {
-	if (fcu)
-		detach_i2c_chip(fcu);
 	fcu = NULL;
 }
 
@@ -2060,12 +2026,21 @@
 	return 0;
 }
 
+static int therm_pm72_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	/* Always succeed, the real work was done in therm_pm72_attach() */
+	return 0;
+}
+
 /*
- * Called on every adapter when the driver or the i2c controller
+ * Called when any of the devices which participates into thermal management
  * is going away.
  */
-static int therm_pm72_detach(struct i2c_adapter *adapter)
+static int therm_pm72_remove(struct i2c_client *client)
 {
+	struct i2c_adapter *adapter = client->adapter;
+
 	mutex_lock(&driver_lock);
 
 	if (state != state_detached)
@@ -2096,6 +2071,30 @@
 	return 0;
 }
 
+/*
+ * i2c_driver structure to attach to the host i2c controller
+ */
+
+static const struct i2c_device_id therm_pm72_id[] = {
+	/*
+	 * Fake device name, thermal management is done by several
+	 * chips but we don't need to differentiate between them at
+	 * this point.
+	 */
+	{ "therm_pm72", 0 },
+	{ }
+};
+
+static struct i2c_driver therm_pm72_driver = {
+	.driver = {
+		.name	= "therm_pm72",
+	},
+	.attach_adapter	= therm_pm72_attach,
+	.probe		= therm_pm72_probe,
+	.remove		= therm_pm72_remove,
+	.id_table	= therm_pm72_id,
+};
+
 static int fan_check_loc_match(const char *loc, int fan)
 {
 	char	tmp[64];
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/therm_windtunnel.c linux-libre-2.6.31-gnu/drivers/macintosh/therm_windtunnel.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/therm_windtunnel.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/therm_windtunnel.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,16 +48,6 @@
 
 #define LOG_TEMP		0			/* continously log temperature */
 
-static int 			do_probe( struct i2c_adapter *adapter, int addr, int kind);
-
-/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
-static const unsigned short	normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
-						 0x4c, 0x4d, 0x4e, 0x4f,
-						 0x2c, 0x2d, 0x2e, 0x2f,
-						 I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
 static struct {
 	volatile int		running;
 	struct task_struct	*poll_task;
@@ -315,53 +305,54 @@
 static int
 do_attach( struct i2c_adapter *adapter )
 {
-	int ret = 0;
+	/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
+	static const unsigned short scan_ds1775[] = {
+		0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+		I2C_CLIENT_END
+	};
+	static const unsigned short scan_adm1030[] = {
+		0x2c, 0x2d, 0x2e, 0x2f,
+		I2C_CLIENT_END
+	};
 
 	if( strncmp(adapter->name, "uni-n", 5) )
 		return 0;
 
 	if( !x.running ) {
-		ret = i2c_probe( adapter, &addr_data, &do_probe );
+		struct i2c_board_info info;
+
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
+		i2c_new_probed_device(adapter, &info, scan_ds1775);
+
+		strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
+		i2c_new_probed_device(adapter, &info, scan_adm1030);
+
 		if( x.thermostat && x.fan ) {
 			x.running = 1;
 			x.poll_task = kthread_run(control_loop, NULL, "g4fand");
 		}
 	}
-	return ret;
+	return 0;
 }
 
 static int
-do_detach( struct i2c_client *client )
+do_remove(struct i2c_client *client)
 {
-	int err;
-
-	if( (err=i2c_detach_client(client)) )
-		printk(KERN_ERR "failed to detach thermostat client\n");
-	else {
-		if( x.running ) {
-			x.running = 0;
-			kthread_stop(x.poll_task);
-			x.poll_task = NULL;
-		}
-		if( client == x.thermostat )
-			x.thermostat = NULL;
-		else if( client == x.fan )
-			x.fan = NULL;
-		else {
-			printk(KERN_ERR "g4fan: bad client\n");
-		}
-		kfree( client );
+	if (x.running) {
+		x.running = 0;
+		kthread_stop(x.poll_task);
+		x.poll_task = NULL;
 	}
-	return err;
-}
+	if (client == x.thermostat)
+		x.thermostat = NULL;
+	else if (client == x.fan)
+		x.fan = NULL;
+	else
+		printk(KERN_ERR "g4fan: bad client\n");
 
-static struct i2c_driver g4fan_driver = {  
-	.driver = {
-		.name	= "therm_windtunnel",
-	},
-	.attach_adapter = do_attach,
-	.detach_client	= do_detach,
-};
+	return 0;
+}
 
 static int
 attach_fan( struct i2c_client *cl )
@@ -374,13 +365,8 @@
 		goto out;
 	printk("ADM1030 fan controller [@%02x]\n", cl->addr );
 
-	strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) );
-
-	if( !i2c_attach_client(cl) )
-		x.fan = cl;
+	x.fan = cl;
  out:
-	if( cl != x.fan )
-		kfree( cl );
 	return 0;
 }
 
@@ -412,39 +398,47 @@
 	x.temp = temp;
 	x.overheat_temp = os_temp;
 	x.overheat_hyst = hyst_temp;
-	
-	strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
-
-	if( !i2c_attach_client(cl) )
-		x.thermostat = cl;
+	x.thermostat = cl;
 out:
-	if( cl != x.thermostat )
-		kfree( cl );
 	return 0;
 }
 
+enum chip { ds1775, adm1030 };
+
+static const struct i2c_device_id therm_windtunnel_id[] = {
+	{ "therm_ds1775", ds1775 },
+	{ "therm_adm1030", adm1030 },
+	{ }
+};
+
 static int
-do_probe( struct i2c_adapter *adapter, int addr, int kind )
+do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
-	struct i2c_client *cl;
+	struct i2c_adapter *adapter = cl->adapter;
 
 	if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
 				     | I2C_FUNC_SMBUS_WRITE_BYTE) )
 		return 0;
 
-	if( !(cl=kzalloc(sizeof(*cl), GFP_KERNEL)) )
-		return -ENOMEM;
-
-	cl->addr = addr;
-	cl->adapter = adapter;
-	cl->driver = &g4fan_driver;
-	cl->flags = 0;
-
-	if( addr < 0x48 )
+	switch (id->driver_data) {
+	case adm1030:
 		return attach_fan( cl );
-	return attach_thermostat( cl );
+	case ds1775:
+		return attach_thermostat(cl);
+	}
+	return 0;
 }
 
+static struct i2c_driver g4fan_driver = {
+	.driver = {
+		.name	= "therm_windtunnel",
+	},
+	.attach_adapter = do_attach,
+	.probe		= do_probe,
+	.remove		= do_remove,
+	.id_table	= therm_windtunnel_id,
+};
+
 
 /************************************************************************/
 /*	initialization / cleanup					*/
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/via-maciisi.c linux-libre-2.6.31-gnu/drivers/macintosh/via-maciisi.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/via-maciisi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/via-maciisi.c	2009-09-09 18:13:59.000000000 -0400
@@ -288,7 +288,7 @@
 	}
 	/* This could be BAD... when the ADB controller doesn't respond
 	 * for this long, it's probably not coming back :-( */
-	if(count >= 50) /* Hopefully shouldn't happen */
+	if (count > 50) /* Hopefully shouldn't happen */
 		printk(KERN_ERR "maciisi_send_request: poll timed out!\n");
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/windfarm_lm75_sensor.c linux-libre-2.6.31-gnu/drivers/macintosh/windfarm_lm75_sensor.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/windfarm_lm75_sensor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/windfarm_lm75_sensor.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,34 +37,22 @@
 struct wf_lm75_sensor {
 	int			ds1775 : 1;
 	int			inited : 1;
-	struct 	i2c_client	i2c;
+	struct 	i2c_client	*i2c;
 	struct 	wf_sensor	sens;
 };
 #define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens)
-#define i2c_to_lm75(c) container_of(c, struct wf_lm75_sensor, i2c)
-
-static int wf_lm75_attach(struct i2c_adapter *adapter);
-static int wf_lm75_detach(struct i2c_client *client);
-
-static struct i2c_driver wf_lm75_driver = {
-	.driver = {
-		.name	= "wf_lm75",
-	},
-	.attach_adapter	= wf_lm75_attach,
-	.detach_client	= wf_lm75_detach,
-};
 
 static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
 {
 	struct wf_lm75_sensor *lm = wf_to_lm75(sr);
 	s32 data;
 
-	if (lm->i2c.adapter == NULL)
+	if (lm->i2c == NULL)
 		return -ENODEV;
 
 	/* Init chip if necessary */
 	if (!lm->inited) {
-		u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(&lm->i2c, 1);
+		u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(lm->i2c, 1);
 
 		DBG("wf_lm75: Initializing %s, cfg was: %02x\n",
 		    sr->name, cfg);
@@ -73,7 +61,7 @@
 		 * the firmware for now
 		 */
 		cfg_new = cfg & ~0x01;
-		i2c_smbus_write_byte_data(&lm->i2c, 1, cfg_new);
+		i2c_smbus_write_byte_data(lm->i2c, 1, cfg_new);
 		lm->inited = 1;
 
 		/* If we just powered it up, let's wait 200 ms */
@@ -81,7 +69,7 @@
 	}
 
 	/* Read temperature register */
-	data = (s32)le16_to_cpu(i2c_smbus_read_word_data(&lm->i2c, 0));
+	data = (s32)le16_to_cpu(i2c_smbus_read_word_data(lm->i2c, 0));
 	data <<= 8;
 	*value = data;
 
@@ -92,12 +80,6 @@
 {
 	struct wf_lm75_sensor *lm = wf_to_lm75(sr);
 
-	/* check if client is registered and detach from i2c */
-	if (lm->i2c.adapter) {
-		i2c_detach_client(&lm->i2c);
-		lm->i2c.adapter = NULL;
-	}
-
 	kfree(lm);
 }
 
@@ -107,59 +89,77 @@
 	.owner		= THIS_MODULE,
 };
 
-static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
-					     u8 addr, int ds1775,
-					     const char *loc)
+static int wf_lm75_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
 {
 	struct wf_lm75_sensor *lm;
 	int rc;
 
-	DBG("wf_lm75: creating  %s device at address 0x%02x\n",
-	    ds1775 ? "ds1775" : "lm75", addr);
-
 	lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
 	if (lm == NULL)
-		return NULL;
+		return -ENODEV;
+
+	lm->inited = 0;
+	lm->ds1775 = id->driver_data;
+	lm->i2c = client;
+	lm->sens.name = client->dev.platform_data;
+	lm->sens.ops = &wf_lm75_ops;
+	i2c_set_clientdata(client, lm);
+
+	rc = wf_register_sensor(&lm->sens);
+	if (rc) {
+		i2c_set_clientdata(client, NULL);
+		kfree(lm);
+	}
+
+	return rc;
+}
+
+static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
+					     u8 addr, int ds1775,
+					     const char *loc)
+{
+	struct i2c_board_info info;
+	struct i2c_client *client;
+	char *name;
+
+	DBG("wf_lm75: creating  %s device at address 0x%02x\n",
+	    ds1775 ? "ds1775" : "lm75", addr);
 
 	/* Usual rant about sensor names not beeing very consistent in
 	 * the device-tree, oh well ...
 	 * Add more entries below as you deal with more setups
 	 */
 	if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
-		lm->sens.name = "hd-temp";
+		name = "hd-temp";
 	else if (!strcmp(loc, "Incoming Air Temp"))
-		lm->sens.name = "incoming-air-temp";
+		name = "incoming-air-temp";
 	else if (!strcmp(loc, "ODD Temp"))
-		lm->sens.name = "optical-drive-temp";
+		name = "optical-drive-temp";
 	else if (!strcmp(loc, "HD Temp"))
-		lm->sens.name = "hard-drive-temp";
+		name = "hard-drive-temp";
 	else
 		goto fail;
 
-	lm->inited = 0;
-	lm->sens.ops = &wf_lm75_ops;
-	lm->ds1775 = ds1775;
-	lm->i2c.addr = (addr >> 1) & 0x7f;
-	lm->i2c.adapter = adapter;
-	lm->i2c.driver = &wf_lm75_driver;
-	strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1);
-
-	rc = i2c_attach_client(&lm->i2c);
-	if (rc) {
-		printk(KERN_ERR "windfarm: failed to attach %s %s to i2c,"
-		       " err %d\n", ds1775 ? "ds1775" : "lm75",
-		       lm->i2c.name, rc);
-		goto fail;
-	}
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = (addr >> 1) & 0x7f;
+	info.platform_data = name;
+	strlcpy(info.type, ds1775 ? "wf_ds1775" : "wf_lm75", I2C_NAME_SIZE);
 
-	if (wf_register_sensor(&lm->sens)) {
-		i2c_detach_client(&lm->i2c);
+	client = i2c_new_device(adapter, &info);
+	if (client == NULL) {
+		printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n",
+		       ds1775 ? "ds1775" : "lm75", name);
 		goto fail;
 	}
 
-	return lm;
+	/*
+	 * Let i2c-core delete that device on driver removal.
+	 * This is safe because i2c-core holds the core_lock mutex for us.
+	 */
+	list_add_tail(&client->detected, &client->driver->clients);
+	return client;
  fail:
-	kfree(lm);
 	return NULL;
 }
 
@@ -202,21 +202,38 @@
 	return 0;
 }
 
-static int wf_lm75_detach(struct i2c_client *client)
+static int wf_lm75_remove(struct i2c_client *client)
 {
-	struct wf_lm75_sensor *lm = i2c_to_lm75(client);
+	struct wf_lm75_sensor *lm = i2c_get_clientdata(client);
 
 	DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name);
 
 	/* Mark client detached */
-	lm->i2c.adapter = NULL;
+	lm->i2c = NULL;
 
 	/* release sensor */
 	wf_unregister_sensor(&lm->sens);
 
+	i2c_set_clientdata(client, NULL);
 	return 0;
 }
 
+static const struct i2c_device_id wf_lm75_id[] = {
+	{ "wf_lm75", 0 },
+	{ "wf_ds1775", 1 },
+	{ }
+};
+
+static struct i2c_driver wf_lm75_driver = {
+	.driver = {
+		.name	= "wf_lm75",
+	},
+	.attach_adapter	= wf_lm75_attach,
+	.probe		= wf_lm75_probe,
+	.remove		= wf_lm75_remove,
+	.id_table	= wf_lm75_id,
+};
+
 static int __init wf_lm75_sensor_init(void)
 {
 	/* Don't register on old machines that use therm_pm72 for now */
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/windfarm_max6690_sensor.c linux-libre-2.6.31-gnu/drivers/macintosh/windfarm_max6690_sensor.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/windfarm_max6690_sensor.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/windfarm_max6690_sensor.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,34 +26,22 @@
 #define MAX6690_EXTERNAL_TEMP	1
 
 struct wf_6690_sensor {
-	struct i2c_client	i2c;
+	struct i2c_client	*i2c;
 	struct wf_sensor	sens;
 };
 
 #define wf_to_6690(x)	container_of((x), struct wf_6690_sensor, sens)
-#define i2c_to_6690(x)	container_of((x), struct wf_6690_sensor, i2c)
-
-static int wf_max6690_attach(struct i2c_adapter *adapter);
-static int wf_max6690_detach(struct i2c_client *client);
-
-static struct i2c_driver wf_max6690_driver = {
-	.driver = {
-		.name		= "wf_max6690",
-	},
-	.attach_adapter	= wf_max6690_attach,
-	.detach_client	= wf_max6690_detach,
-};
 
 static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
 {
 	struct wf_6690_sensor *max = wf_to_6690(sr);
 	s32 data;
 
-	if (max->i2c.adapter == NULL)
+	if (max->i2c == NULL)
 		return -ENODEV;
 
 	/* chip gets initialized by firmware */
-	data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP);
+	data = i2c_smbus_read_byte_data(max->i2c, MAX6690_EXTERNAL_TEMP);
 	if (data < 0)
 		return data;
 	*value = data << 16;
@@ -64,10 +52,6 @@
 {
 	struct wf_6690_sensor *max = wf_to_6690(sr);
 
-	if (max->i2c.adapter) {
-		i2c_detach_client(&max->i2c);
-		max->i2c.adapter = NULL;
-	}
 	kfree(max);
 }
 
@@ -77,19 +61,40 @@
 	.owner		= THIS_MODULE,
 };
 
-static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
-			      const char *loc)
+static int wf_max6690_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
 {
 	struct wf_6690_sensor *max;
-	char *name;
+	int rc;
 
 	max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
 	if (max == NULL) {
-		printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: "
-		       "no memory\n", loc);
-		return;
+		printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: "
+		       "no memory\n");
+		return -ENOMEM;
+	}
+
+	max->i2c = client;
+	max->sens.name = client->dev.platform_data;
+	max->sens.ops = &wf_max6690_ops;
+	i2c_set_clientdata(client, max);
+
+	rc = wf_register_sensor(&max->sens);
+	if (rc) {
+		i2c_set_clientdata(client, NULL);
+		kfree(max);
 	}
 
+	return rc;
+}
+
+static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
+					    u8 addr, const char *loc)
+{
+	struct i2c_board_info info;
+	struct i2c_client *client;
+	char *name;
+
 	if (!strcmp(loc, "BACKSIDE"))
 		name = "backside-temp";
 	else if (!strcmp(loc, "NB Ambient"))
@@ -99,27 +104,26 @@
 	else
 		goto fail;
 
-	max->sens.ops = &wf_max6690_ops;
-	max->sens.name = name;
-	max->i2c.addr = addr >> 1;
-	max->i2c.adapter = adapter;
-	max->i2c.driver = &wf_max6690_driver;
-	strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = addr >> 1;
+	info.platform_data = name;
+	strlcpy(info.type, "wf_max6690", I2C_NAME_SIZE);
 
-	if (i2c_attach_client(&max->i2c)) {
+	client = i2c_new_device(adapter, &info);
+	if (client == NULL) {
 		printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
 		goto fail;
 	}
 
-	if (wf_register_sensor(&max->sens)) {
-		i2c_detach_client(&max->i2c);
-		goto fail;
-	}
-
-	return;
+	/*
+	 * Let i2c-core delete that device on driver removal.
+	 * This is safe because i2c-core holds the core_lock mutex for us.
+	 */
+	list_add_tail(&client->detected, &client->driver->clients);
+	return client;
 
  fail:
-	kfree(max);
+	return NULL;
 }
 
 static int wf_max6690_attach(struct i2c_adapter *adapter)
@@ -154,16 +158,31 @@
 	return 0;
 }
 
-static int wf_max6690_detach(struct i2c_client *client)
+static int wf_max6690_remove(struct i2c_client *client)
 {
-	struct wf_6690_sensor *max = i2c_to_6690(client);
+	struct wf_6690_sensor *max = i2c_get_clientdata(client);
 
-	max->i2c.adapter = NULL;
+	max->i2c = NULL;
 	wf_unregister_sensor(&max->sens);
 
 	return 0;
 }
 
+static const struct i2c_device_id wf_max6690_id[] = {
+	{ "wf_max6690", 0 },
+	{ }
+};
+
+static struct i2c_driver wf_max6690_driver = {
+	.driver = {
+		.name		= "wf_max6690",
+	},
+	.attach_adapter	= wf_max6690_attach,
+	.probe		= wf_max6690_probe,
+	.remove		= wf_max6690_remove,
+	.id_table	= wf_max6690_id,
+};
+
 static int __init wf_max6690_sensor_init(void)
 {
 	/* Don't register on old machines that use therm_pm72 for now */
diff -druN linux-libre-2.6.30-gnu/drivers/macintosh/windfarm_smu_sat.c linux-libre-2.6.31-gnu/drivers/macintosh/windfarm_smu_sat.c
--- linux-libre-2.6.30-gnu/drivers/macintosh/windfarm_smu_sat.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/macintosh/windfarm_smu_sat.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,7 +39,7 @@
 	struct mutex		mutex;
 	unsigned long		last_read; /* jiffies when cache last updated */
 	u8			cache[16];
-	struct i2c_client	i2c;
+	struct i2c_client	*i2c;
 	struct device_node	*node;
 };
 
@@ -54,18 +54,6 @@
 };
 
 #define wf_to_sat(c)	container_of(c, struct wf_sat_sensor, sens)
-#define i2c_to_sat(c)	container_of(c, struct wf_sat, i2c)
-
-static int wf_sat_attach(struct i2c_adapter *adapter);
-static int wf_sat_detach(struct i2c_client *client);
-
-static struct i2c_driver wf_sat_driver = {
-	.driver = {
-		.name		= "wf_smu_sat",
-	},
-	.attach_adapter	= wf_sat_attach,
-	.detach_client	= wf_sat_detach,
-};
 
 struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
 						  unsigned int *size)
@@ -81,13 +69,13 @@
 	if (sat_id > 1 || (sat = sats[sat_id]) == NULL)
 		return NULL;
 
-	err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8);
+	err = i2c_smbus_write_word_data(sat->i2c, 8, id << 8);
 	if (err) {
 		printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err);
 		return NULL;
 	}
 
-	err = i2c_smbus_read_word_data(&sat->i2c, 9);
+	err = i2c_smbus_read_word_data(sat->i2c, 9);
 	if (err < 0) {
 		printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n");
 		return NULL;
@@ -105,7 +93,7 @@
 		return NULL;
 
 	for (i = 0; i < len; i += 4) {
-		err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data);
+		err = i2c_smbus_read_i2c_block_data(sat->i2c, 0xa, 4, data);
 		if (err < 0) {
 			printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
 			       err);
@@ -138,7 +126,7 @@
 {
 	int err;
 
-	err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache);
+	err = i2c_smbus_read_i2c_block_data(sat->i2c, 0x3f, 16, sat->cache);
 	if (err < 0)
 		return err;
 	sat->last_read = jiffies;
@@ -161,7 +149,7 @@
 	int i, err;
 	s32 val;
 
-	if (sat->i2c.adapter == NULL)
+	if (sat->i2c == NULL)
 		return -ENODEV;
 
 	mutex_lock(&sat->mutex);
@@ -193,10 +181,6 @@
 	struct wf_sat *sat = sens->sat;
 
 	if (atomic_dec_and_test(&sat->refcnt)) {
-		if (sat->i2c.adapter) {
-			i2c_detach_client(&sat->i2c);
-			sat->i2c.adapter = NULL;
-		}
 		if (sat->nr >= 0)
 			sats[sat->nr] = NULL;
 		kfree(sat);
@@ -212,38 +196,58 @@
 
 static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
 {
+	struct i2c_board_info info;
+	struct i2c_client *client;
+	const u32 *reg;
+	u8 addr;
+
+	reg = of_get_property(dev, "reg", NULL);
+	if (reg == NULL)
+		return;
+	addr = *reg;
+	DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = (addr >> 1) & 0x7f;
+	info.platform_data = dev;
+	strlcpy(info.type, "wf_sat", I2C_NAME_SIZE);
+
+	client = i2c_new_device(adapter, &info);
+	if (client == NULL) {
+		printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
+		return;
+	}
+
+	/*
+	 * Let i2c-core delete that device on driver removal.
+	 * This is safe because i2c-core holds the core_lock mutex for us.
+	 */
+	list_add_tail(&client->detected, &client->driver->clients);
+}
+
+static int wf_sat_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct device_node *dev = client->dev.platform_data;
 	struct wf_sat *sat;
 	struct wf_sat_sensor *sens;
 	const u32 *reg;
 	const char *loc, *type;
-	u8 addr, chip, core;
+	u8 chip, core;
 	struct device_node *child;
 	int shift, cpu, index;
 	char *name;
 	int vsens[2], isens[2];
 
-	reg = of_get_property(dev, "reg", NULL);
-	if (reg == NULL)
-		return;
-	addr = *reg;
-	DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
-
 	sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL);
 	if (sat == NULL)
-		return;
+		return -ENOMEM;
 	sat->nr = -1;
 	sat->node = of_node_get(dev);
 	atomic_set(&sat->refcnt, 0);
 	mutex_init(&sat->mutex);
-	sat->i2c.addr = (addr >> 1) & 0x7f;
-	sat->i2c.adapter = adapter;
-	sat->i2c.driver = &wf_sat_driver;
-	strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1);
-
-	if (i2c_attach_client(&sat->i2c)) {
-		printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
-		goto fail;
-	}
+	sat->i2c = client;
+	i2c_set_clientdata(client, sat);
 
 	vsens[0] = vsens[1] = -1;
 	isens[0] = isens[1] = -1;
@@ -344,10 +348,7 @@
 	if (sat->nr >= 0)
 		sats[sat->nr] = sat;
 
-	return;
-
- fail:
-	kfree(sat);
+	return 0;
 }
 
 static int wf_sat_attach(struct i2c_adapter *adapter)
@@ -366,16 +367,32 @@
 	return 0;
 }
 
-static int wf_sat_detach(struct i2c_client *client)
+static int wf_sat_remove(struct i2c_client *client)
 {
-	struct wf_sat *sat = i2c_to_sat(client);
+	struct wf_sat *sat = i2c_get_clientdata(client);
 
 	/* XXX TODO */
 
-	sat->i2c.adapter = NULL;
+	sat->i2c = NULL;
+	i2c_set_clientdata(client, NULL);
 	return 0;
 }
 
+static const struct i2c_device_id wf_sat_id[] = {
+	{ "wf_sat", 0 },
+	{ }
+};
+
+static struct i2c_driver wf_sat_driver = {
+	.driver = {
+		.name		= "wf_smu_sat",
+	},
+	.attach_adapter	= wf_sat_attach,
+	.probe		= wf_sat_probe,
+	.remove		= wf_sat_remove,
+	.id_table	= wf_sat_id,
+};
+
 static int __init sat_sensors_init(void)
 {
 	return i2c_add_driver(&wf_sat_driver);
diff -druN linux-libre-2.6.30-gnu/drivers/Makefile linux-libre-2.6.31-gnu/drivers/Makefile
--- linux-libre-2.6.30-gnu/drivers/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -72,6 +72,7 @@
 obj-$(CONFIG_I2O)		+= message/
 obj-$(CONFIG_RTC_LIB)		+= rtc/
 obj-y				+= i2c/ media/
+obj-$(CONFIG_PPS)		+= pps/
 obj-$(CONFIG_W1)		+= w1/
 obj-$(CONFIG_POWER_SUPPLY)	+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
@@ -105,5 +106,7 @@
 obj-$(CONFIG_OF)		+= of/
 obj-$(CONFIG_SSB)		+= ssb/
 obj-$(CONFIG_VIRTIO)		+= virtio/
+obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
+obj-y				+= ieee802154/
diff -druN linux-libre-2.6.30-gnu/drivers/md/bitmap.c linux-libre-2.6.31-gnu/drivers/md/bitmap.c
--- linux-libre-2.6.30-gnu/drivers/md/bitmap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/bitmap.c	2009-09-09 18:13:59.000000000 -0400
@@ -232,7 +232,7 @@
 		target = rdev->sb_start + offset + index * (PAGE_SIZE/512);
 
 		if (sync_page_io(rdev->bdev, target,
-				 roundup(size, bdev_hardsect_size(rdev->bdev)),
+				 roundup(size, bdev_logical_block_size(rdev->bdev)),
 				 page, READ)) {
 			page->index = index;
 			attach_page_buffers(page, NULL); /* so that free_buffer will
@@ -287,7 +287,7 @@
 			int size = PAGE_SIZE;
 			if (page->index == bitmap->file_pages-1)
 				size = roundup(bitmap->last_page_size,
-					       bdev_hardsect_size(rdev->bdev));
+					       bdev_logical_block_size(rdev->bdev));
 			/* Just make sure we aren't corrupting data or
 			 * metadata
 			 */
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm.c linux-libre-2.6.31-gnu/drivers/md/dm.c
--- linux-libre-2.6.30-gnu/drivers/md/dm.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,11 +19,18 @@
 #include <linux/slab.h>
 #include <linux/idr.h>
 #include <linux/hdreg.h>
-#include <linux/blktrace_api.h>
-#include <trace/block.h>
+
+#include <trace/events/block.h>
 
 #define DM_MSG_PREFIX "core"
 
+/*
+ * Cookies are numeric values sent with CHANGE and REMOVE
+ * uevents while resuming, removing or renaming the device.
+ */
+#define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
+#define DM_COOKIE_LENGTH 24
+
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
@@ -53,8 +60,6 @@
 	union map_info info;
 };
 
-DEFINE_TRACE(block_bio_complete);
-
 /*
  * For request-based dm.
  * One of these is allocated per request.
@@ -73,7 +78,7 @@
  */
 struct dm_rq_clone_bio_info {
 	struct bio *orig;
-	struct request *rq;
+	struct dm_rq_target_io *tio;
 };
 
 union map_info *dm_get_mapinfo(struct bio *bio)
@@ -83,6 +88,14 @@
 	return NULL;
 }
 
+union map_info *dm_get_rq_mapinfo(struct request *rq)
+{
+	if (rq && rq->end_io_data)
+		return &((struct dm_rq_target_io *)rq->end_io_data)->info;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
+
 #define MINOR_ALLOCED ((void *)-1)
 
 /*
@@ -159,13 +172,31 @@
 	 * freeze/thaw support require holding onto a super block
 	 */
 	struct super_block *frozen_sb;
-	struct block_device *suspended_bdev;
+	struct block_device *bdev;
 
 	/* forced geometry settings */
 	struct hd_geometry geometry;
 
+	/* marker of flush suspend for request-based dm */
+	struct request suspend_rq;
+
+	/* For saving the address of __make_request for request based dm */
+	make_request_fn *saved_make_request_fn;
+
 	/* sysfs handle */
 	struct kobject kobj;
+
+	/* zero-length barrier that will be cloned and submitted to targets */
+	struct bio barrier_bio;
+};
+
+/*
+ * For mempools pre-allocation at the table loading time.
+ */
+struct dm_md_mempools {
+	mempool_t *io_pool;
+	mempool_t *tio_pool;
+	struct bio_set *bs;
 };
 
 #define MIN_IOS 256
@@ -393,14 +424,29 @@
 	mempool_free(io, md->io_pool);
 }
 
-static struct dm_target_io *alloc_tio(struct mapped_device *md)
+static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
 {
-	return mempool_alloc(md->tio_pool, GFP_NOIO);
+	mempool_free(tio, md->tio_pool);
 }
 
-static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
+static struct dm_rq_target_io *alloc_rq_tio(struct mapped_device *md)
 {
-	mempool_free(tio, md->tio_pool);
+	return mempool_alloc(md->tio_pool, GFP_ATOMIC);
+}
+
+static void free_rq_tio(struct dm_rq_target_io *tio)
+{
+	mempool_free(tio, tio->md->tio_pool);
+}
+
+static struct dm_rq_clone_bio_info *alloc_bio_info(struct mapped_device *md)
+{
+	return mempool_alloc(md->io_pool, GFP_ATOMIC);
+}
+
+static void free_bio_info(struct dm_rq_clone_bio_info *info)
+{
+	mempool_free(info, info->tio->md->io_pool);
 }
 
 static void start_io_acct(struct dm_io *io)
@@ -466,12 +512,13 @@
 struct dm_table *dm_get_table(struct mapped_device *md)
 {
 	struct dm_table *t;
+	unsigned long flags;
 
-	read_lock(&md->map_lock);
+	read_lock_irqsave(&md->map_lock, flags);
 	t = md->map;
 	if (t)
 		dm_table_get(t);
-	read_unlock(&md->map_lock);
+	read_unlock_irqrestore(&md->map_lock, flags);
 
 	return t;
 }
@@ -538,9 +585,11 @@
 			 * Target requested pushing back the I/O.
 			 */
 			spin_lock_irqsave(&md->deferred_lock, flags);
-			if (__noflush_suspending(md))
-				bio_list_add_head(&md->deferred, io->bio);
-			else
+			if (__noflush_suspending(md)) {
+				if (!bio_barrier(io->bio))
+					bio_list_add_head(&md->deferred,
+							  io->bio);
+			} else
 				/* noflush suspend was interrupted. */
 				io->error = -EIO;
 			spin_unlock_irqrestore(&md->deferred_lock, flags);
@@ -555,7 +604,8 @@
 			 * a per-device variable for error reporting.
 			 * Note that you can't touch the bio after end_io_acct
 			 */
-			md->barrier_error = io_error;
+			if (!md->barrier_error && io_error != -EOPNOTSUPP)
+				md->barrier_error = io_error;
 			end_io_acct(io);
 		} else {
 			end_io_acct(io);
@@ -609,6 +659,267 @@
 	dec_pending(io, error);
 }
 
+/*
+ * Partial completion handling for request-based dm
+ */
+static void end_clone_bio(struct bio *clone, int error)
+{
+	struct dm_rq_clone_bio_info *info = clone->bi_private;
+	struct dm_rq_target_io *tio = info->tio;
+	struct bio *bio = info->orig;
+	unsigned int nr_bytes = info->orig->bi_size;
+
+	bio_put(clone);
+
+	if (tio->error)
+		/*
+		 * An error has already been detected on the request.
+		 * Once error occurred, just let clone->end_io() handle
+		 * the remainder.
+		 */
+		return;
+	else if (error) {
+		/*
+		 * Don't notice the error to the upper layer yet.
+		 * The error handling decision is made by the target driver,
+		 * when the request is completed.
+		 */
+		tio->error = error;
+		return;
+	}
+
+	/*
+	 * I/O for the bio successfully completed.
+	 * Notice the data completion to the upper layer.
+	 */
+
+	/*
+	 * bios are processed from the head of the list.
+	 * So the completing bio should always be rq->bio.
+	 * If it's not, something wrong is happening.
+	 */
+	if (tio->orig->bio != bio)
+		DMERR("bio completion is going in the middle of the request");
+
+	/*
+	 * Update the original request.
+	 * Do not use blk_end_request() here, because it may complete
+	 * the original request before the clone, and break the ordering.
+	 */
+	blk_update_request(tio->orig, 0, nr_bytes);
+}
+
+/*
+ * Don't touch any member of the md after calling this function because
+ * the md may be freed in dm_put() at the end of this function.
+ * Or do dm_get() before calling this function and dm_put() later.
+ */
+static void rq_completed(struct mapped_device *md, int run_queue)
+{
+	int wakeup_waiters = 0;
+	struct request_queue *q = md->queue;
+	unsigned long flags;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	if (!queue_in_flight(q))
+		wakeup_waiters = 1;
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	/* nudge anyone waiting on suspend queue */
+	if (wakeup_waiters)
+		wake_up(&md->wait);
+
+	if (run_queue)
+		blk_run_queue(q);
+
+	/*
+	 * dm_put() must be at the end of this function. See the comment above
+	 */
+	dm_put(md);
+}
+
+static void free_rq_clone(struct request *clone)
+{
+	struct dm_rq_target_io *tio = clone->end_io_data;
+
+	blk_rq_unprep_clone(clone);
+	free_rq_tio(tio);
+}
+
+static void dm_unprep_request(struct request *rq)
+{
+	struct request *clone = rq->special;
+
+	rq->special = NULL;
+	rq->cmd_flags &= ~REQ_DONTPREP;
+
+	free_rq_clone(clone);
+}
+
+/*
+ * Requeue the original request of a clone.
+ */
+void dm_requeue_unmapped_request(struct request *clone)
+{
+	struct dm_rq_target_io *tio = clone->end_io_data;
+	struct mapped_device *md = tio->md;
+	struct request *rq = tio->orig;
+	struct request_queue *q = rq->q;
+	unsigned long flags;
+
+	dm_unprep_request(rq);
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	if (elv_queue_empty(q))
+		blk_plug_device(q);
+	blk_requeue_request(q, rq);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	rq_completed(md, 0);
+}
+EXPORT_SYMBOL_GPL(dm_requeue_unmapped_request);
+
+static void __stop_queue(struct request_queue *q)
+{
+	blk_stop_queue(q);
+}
+
+static void stop_queue(struct request_queue *q)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	__stop_queue(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+static void __start_queue(struct request_queue *q)
+{
+	if (blk_queue_stopped(q))
+		blk_start_queue(q);
+}
+
+static void start_queue(struct request_queue *q)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	__start_queue(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+/*
+ * Complete the clone and the original request.
+ * Must be called without queue lock.
+ */
+static void dm_end_request(struct request *clone, int error)
+{
+	struct dm_rq_target_io *tio = clone->end_io_data;
+	struct mapped_device *md = tio->md;
+	struct request *rq = tio->orig;
+
+	if (blk_pc_request(rq)) {
+		rq->errors = clone->errors;
+		rq->resid_len = clone->resid_len;
+
+		if (rq->sense)
+			/*
+			 * We are using the sense buffer of the original
+			 * request.
+			 * So setting the length of the sense data is enough.
+			 */
+			rq->sense_len = clone->sense_len;
+	}
+
+	free_rq_clone(clone);
+
+	blk_end_request_all(rq, error);
+
+	rq_completed(md, 1);
+}
+
+/*
+ * Request completion handler for request-based dm
+ */
+static void dm_softirq_done(struct request *rq)
+{
+	struct request *clone = rq->completion_data;
+	struct dm_rq_target_io *tio = clone->end_io_data;
+	dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io;
+	int error = tio->error;
+
+	if (!(rq->cmd_flags & REQ_FAILED) && rq_end_io)
+		error = rq_end_io(tio->ti, clone, error, &tio->info);
+
+	if (error <= 0)
+		/* The target wants to complete the I/O */
+		dm_end_request(clone, error);
+	else if (error == DM_ENDIO_INCOMPLETE)
+		/* The target will handle the I/O */
+		return;
+	else if (error == DM_ENDIO_REQUEUE)
+		/* The target wants to requeue the I/O */
+		dm_requeue_unmapped_request(clone);
+	else {
+		DMWARN("unimplemented target endio return value: %d", error);
+		BUG();
+	}
+}
+
+/*
+ * Complete the clone and the original request with the error status
+ * through softirq context.
+ */
+static void dm_complete_request(struct request *clone, int error)
+{
+	struct dm_rq_target_io *tio = clone->end_io_data;
+	struct request *rq = tio->orig;
+
+	tio->error = error;
+	rq->completion_data = clone;
+	blk_complete_request(rq);
+}
+
+/*
+ * Complete the not-mapped clone and the original request with the error status
+ * through softirq context.
+ * Target's rq_end_io() function isn't called.
+ * This may be used when the target's map_rq() function fails.
+ */
+void dm_kill_unmapped_request(struct request *clone, int error)
+{
+	struct dm_rq_target_io *tio = clone->end_io_data;
+	struct request *rq = tio->orig;
+
+	rq->cmd_flags |= REQ_FAILED;
+	dm_complete_request(clone, error);
+}
+EXPORT_SYMBOL_GPL(dm_kill_unmapped_request);
+
+/*
+ * Called with the queue lock held
+ */
+static void end_clone_request(struct request *clone, int error)
+{
+	/*
+	 * For just cleaning up the information of the queue in which
+	 * the clone was dispatched.
+	 * The clone is *NOT* freed actually here because it is alloced from
+	 * dm own mempool and REQ_ALLOCED isn't set in clone->cmd_flags.
+	 */
+	__blk_put_request(clone->q, clone);
+
+	/*
+	 * Actual request completion is done in a softirq context which doesn't
+	 * hold the queue lock.  Otherwise, deadlock could occur because:
+	 *     - another request may be submitted by the upper level driver
+	 *       of the stacking during the completion
+	 *     - the submission which requires queue lock may be done
+	 *       against this queue
+	 */
+	dm_complete_request(clone, error);
+}
+
 static sector_t max_io_len(struct mapped_device *md,
 			   sector_t sector, struct dm_target *ti)
 {
@@ -636,11 +947,6 @@
 	sector_t sector;
 	struct mapped_device *md;
 
-	/*
-	 * Sanity checks.
-	 */
-	BUG_ON(!clone->bi_size);
-
 	clone->bi_end_io = clone_endio;
 	clone->bi_private = tio;
 
@@ -656,8 +962,7 @@
 		/* the bio has been remapped so dispatch it */
 
 		trace_block_remap(bdev_get_queue(clone->bi_bdev), clone,
-				    tio->io->bio->bi_bdev->bd_dev,
-				    clone->bi_sector, sector);
+				    tio->io->bio->bi_bdev->bd_dev, sector);
 
 		generic_make_request(clone);
 	} else if (r < 0 || r == DM_MAPIO_REQUEUE) {
@@ -717,7 +1022,7 @@
 	clone->bi_flags |= 1 << BIO_CLONED;
 
 	if (bio_integrity(bio)) {
-		bio_integrity_clone(clone, bio, GFP_NOIO);
+		bio_integrity_clone(clone, bio, GFP_NOIO, bs);
 		bio_integrity_trim(clone,
 				   bio_sector_offset(bio, idx, offset), len);
 	}
@@ -745,7 +1050,7 @@
 	clone->bi_flags &= ~(1 << BIO_SEG_VALID);
 
 	if (bio_integrity(bio)) {
-		bio_integrity_clone(clone, bio, GFP_NOIO);
+		bio_integrity_clone(clone, bio, GFP_NOIO, bs);
 
 		if (idx != bio->bi_idx || clone->bi_size < bio->bi_size)
 			bio_integrity_trim(clone,
@@ -755,6 +1060,48 @@
 	return clone;
 }
 
+static struct dm_target_io *alloc_tio(struct clone_info *ci,
+				      struct dm_target *ti)
+{
+	struct dm_target_io *tio = mempool_alloc(ci->md->tio_pool, GFP_NOIO);
+
+	tio->io = ci->io;
+	tio->ti = ti;
+	memset(&tio->info, 0, sizeof(tio->info));
+
+	return tio;
+}
+
+static void __flush_target(struct clone_info *ci, struct dm_target *ti,
+			  unsigned flush_nr)
+{
+	struct dm_target_io *tio = alloc_tio(ci, ti);
+	struct bio *clone;
+
+	tio->info.flush_request = flush_nr;
+
+	clone = bio_alloc_bioset(GFP_NOIO, 0, ci->md->bs);
+	__bio_clone(clone, ci->bio);
+	clone->bi_destructor = dm_bio_destructor;
+
+	__map_bio(ti, clone, tio);
+}
+
+static int __clone_and_map_empty_barrier(struct clone_info *ci)
+{
+	unsigned target_nr = 0, flush_nr;
+	struct dm_target *ti;
+
+	while ((ti = dm_table_get_target(ci->map, target_nr++)))
+		for (flush_nr = 0; flush_nr < ti->num_flush_requests;
+		     flush_nr++)
+			__flush_target(ci, ti, flush_nr);
+
+	ci->sector_count = 0;
+
+	return 0;
+}
+
 static int __clone_and_map(struct clone_info *ci)
 {
 	struct bio *clone, *bio = ci->bio;
@@ -762,6 +1109,9 @@
 	sector_t len = 0, max;
 	struct dm_target_io *tio;
 
+	if (unlikely(bio_empty_barrier(bio)))
+		return __clone_and_map_empty_barrier(ci);
+
 	ti = dm_table_find_target(ci->map, ci->sector);
 	if (!dm_target_is_valid(ti))
 		return -EIO;
@@ -771,10 +1121,7 @@
 	/*
 	 * Allocate a target io object.
 	 */
-	tio = alloc_tio(ci->md);
-	tio->io = ci->io;
-	tio->ti = ti;
-	memset(&tio->info, 0, sizeof(tio->info));
+	tio = alloc_tio(ci, ti);
 
 	if (ci->sector_count <= max) {
 		/*
@@ -830,10 +1177,7 @@
 
 				max = max_io_len(ci->md, ci->sector, ti);
 
-				tio = alloc_tio(ci->md);
-				tio->io = ci->io;
-				tio->ti = ti;
-				memset(&tio->info, 0, sizeof(tio->info));
+				tio = alloc_tio(ci, ti);
 			}
 
 			len = min(remaining, max);
@@ -868,7 +1212,8 @@
 		if (!bio_barrier(bio))
 			bio_io_error(bio);
 		else
-			md->barrier_error = -EIO;
+			if (!md->barrier_error)
+				md->barrier_error = -EIO;
 		return;
 	}
 
@@ -881,6 +1226,8 @@
 	ci.io->md = md;
 	ci.sector = bio->bi_sector;
 	ci.sector_count = bio_sectors(bio);
+	if (unlikely(bio_empty_barrier(bio)))
+		ci.sector_count = 1;
 	ci.idx = bio->bi_idx;
 
 	start_io_acct(ci.io);
@@ -928,6 +1275,16 @@
 	 */
 	if (max_size && ti->type->merge)
 		max_size = ti->type->merge(ti, bvm, biovec, max_size);
+	/*
+	 * If the target doesn't support merge method and some of the devices
+	 * provided their merge_bvec method (we know this by looking at
+	 * queue_max_hw_sectors), then we can't allow bios with multiple vector
+	 * entries.  So always set max_size to 0, and the code below allows
+	 * just one page.
+	 */
+	else if (queue_max_hw_sectors(q) <= PAGE_SIZE >> 9)
+
+		max_size = 0;
 
 out_table:
 	dm_table_put(map);
@@ -946,7 +1303,7 @@
  * The request function that just remaps the bio built up by
  * dm_merge_bvec.
  */
-static int dm_request(struct request_queue *q, struct bio *bio)
+static int _dm_request(struct request_queue *q, struct bio *bio)
 {
 	int rw = bio_data_dir(bio);
 	struct mapped_device *md = q->queuedata;
@@ -983,12 +1340,274 @@
 	return 0;
 }
 
+static int dm_make_request(struct request_queue *q, struct bio *bio)
+{
+	struct mapped_device *md = q->queuedata;
+
+	if (unlikely(bio_barrier(bio))) {
+		bio_endio(bio, -EOPNOTSUPP);
+		return 0;
+	}
+
+	return md->saved_make_request_fn(q, bio); /* call __make_request() */
+}
+
+static int dm_request_based(struct mapped_device *md)
+{
+	return blk_queue_stackable(md->queue);
+}
+
+static int dm_request(struct request_queue *q, struct bio *bio)
+{
+	struct mapped_device *md = q->queuedata;
+
+	if (dm_request_based(md))
+		return dm_make_request(q, bio);
+
+	return _dm_request(q, bio);
+}
+
+void dm_dispatch_request(struct request *rq)
+{
+	int r;
+
+	if (blk_queue_io_stat(rq->q))
+		rq->cmd_flags |= REQ_IO_STAT;
+
+	rq->start_time = jiffies;
+	r = blk_insert_cloned_request(rq->q, rq);
+	if (r)
+		dm_complete_request(rq, r);
+}
+EXPORT_SYMBOL_GPL(dm_dispatch_request);
+
+static void dm_rq_bio_destructor(struct bio *bio)
+{
+	struct dm_rq_clone_bio_info *info = bio->bi_private;
+	struct mapped_device *md = info->tio->md;
+
+	free_bio_info(info);
+	bio_free(bio, md->bs);
+}
+
+static int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig,
+				 void *data)
+{
+	struct dm_rq_target_io *tio = data;
+	struct mapped_device *md = tio->md;
+	struct dm_rq_clone_bio_info *info = alloc_bio_info(md);
+
+	if (!info)
+		return -ENOMEM;
+
+	info->orig = bio_orig;
+	info->tio = tio;
+	bio->bi_end_io = end_clone_bio;
+	bio->bi_private = info;
+	bio->bi_destructor = dm_rq_bio_destructor;
+
+	return 0;
+}
+
+static int setup_clone(struct request *clone, struct request *rq,
+		       struct dm_rq_target_io *tio)
+{
+	int r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC,
+				  dm_rq_bio_constructor, tio);
+
+	if (r)
+		return r;
+
+	clone->cmd = rq->cmd;
+	clone->cmd_len = rq->cmd_len;
+	clone->sense = rq->sense;
+	clone->buffer = rq->buffer;
+	clone->end_io = end_clone_request;
+	clone->end_io_data = tio;
+
+	return 0;
+}
+
+static int dm_rq_flush_suspending(struct mapped_device *md)
+{
+	return !md->suspend_rq.special;
+}
+
+/*
+ * Called with the queue lock held.
+ */
+static int dm_prep_fn(struct request_queue *q, struct request *rq)
+{
+	struct mapped_device *md = q->queuedata;
+	struct dm_rq_target_io *tio;
+	struct request *clone;
+
+	if (unlikely(rq == &md->suspend_rq)) {
+		if (dm_rq_flush_suspending(md))
+			return BLKPREP_OK;
+		else
+			/* The flush suspend was interrupted */
+			return BLKPREP_KILL;
+	}
+
+	if (unlikely(rq->special)) {
+		DMWARN("Already has something in rq->special.");
+		return BLKPREP_KILL;
+	}
+
+	tio = alloc_rq_tio(md); /* Only one for each original request */
+	if (!tio)
+		/* -ENOMEM */
+		return BLKPREP_DEFER;
+
+	tio->md = md;
+	tio->ti = NULL;
+	tio->orig = rq;
+	tio->error = 0;
+	memset(&tio->info, 0, sizeof(tio->info));
+
+	clone = &tio->clone;
+	if (setup_clone(clone, rq, tio)) {
+		/* -ENOMEM */
+		free_rq_tio(tio);
+		return BLKPREP_DEFER;
+	}
+
+	rq->special = clone;
+	rq->cmd_flags |= REQ_DONTPREP;
+
+	return BLKPREP_OK;
+}
+
+static void map_request(struct dm_target *ti, struct request *rq,
+			struct mapped_device *md)
+{
+	int r;
+	struct request *clone = rq->special;
+	struct dm_rq_target_io *tio = clone->end_io_data;
+
+	/*
+	 * Hold the md reference here for the in-flight I/O.
+	 * We can't rely on the reference count by device opener,
+	 * because the device may be closed during the request completion
+	 * when all bios are completed.
+	 * See the comment in rq_completed() too.
+	 */
+	dm_get(md);
+
+	tio->ti = ti;
+	r = ti->type->map_rq(ti, clone, &tio->info);
+	switch (r) {
+	case DM_MAPIO_SUBMITTED:
+		/* The target has taken the I/O to submit by itself later */
+		break;
+	case DM_MAPIO_REMAPPED:
+		/* The target has remapped the I/O so dispatch it */
+		dm_dispatch_request(clone);
+		break;
+	case DM_MAPIO_REQUEUE:
+		/* The target wants to requeue the I/O */
+		dm_requeue_unmapped_request(clone);
+		break;
+	default:
+		if (r > 0) {
+			DMWARN("unimplemented target map return value: %d", r);
+			BUG();
+		}
+
+		/* The target wants to complete the I/O */
+		dm_kill_unmapped_request(clone, r);
+		break;
+	}
+}
+
+/*
+ * q->request_fn for request-based dm.
+ * Called with the queue lock held.
+ */
+static void dm_request_fn(struct request_queue *q)
+{
+	struct mapped_device *md = q->queuedata;
+	struct dm_table *map = dm_get_table(md);
+	struct dm_target *ti;
+	struct request *rq;
+
+	/*
+	 * For noflush suspend, check blk_queue_stopped() to immediately
+	 * quit I/O dispatching.
+	 */
+	while (!blk_queue_plugged(q) && !blk_queue_stopped(q)) {
+		rq = blk_peek_request(q);
+		if (!rq)
+			goto plug_and_out;
+
+		if (unlikely(rq == &md->suspend_rq)) { /* Flush suspend maker */
+			if (queue_in_flight(q))
+				/* Not quiet yet.  Wait more */
+				goto plug_and_out;
+
+			/* This device should be quiet now */
+			__stop_queue(q);
+			blk_start_request(rq);
+			__blk_end_request_all(rq, 0);
+			wake_up(&md->wait);
+			goto out;
+		}
+
+		ti = dm_table_find_target(map, blk_rq_pos(rq));
+		if (ti->type->busy && ti->type->busy(ti))
+			goto plug_and_out;
+
+		blk_start_request(rq);
+		spin_unlock(q->queue_lock);
+		map_request(ti, rq, md);
+		spin_lock_irq(q->queue_lock);
+	}
+
+	goto out;
+
+plug_and_out:
+	if (!elv_queue_empty(q))
+		/* Some requests still remain, retry later */
+		blk_plug_device(q);
+
+out:
+	dm_table_put(map);
+
+	return;
+}
+
+int dm_underlying_device_busy(struct request_queue *q)
+{
+	return blk_lld_busy(q);
+}
+EXPORT_SYMBOL_GPL(dm_underlying_device_busy);
+
+static int dm_lld_busy(struct request_queue *q)
+{
+	int r;
+	struct mapped_device *md = q->queuedata;
+	struct dm_table *map = dm_get_table(md);
+
+	if (!map || test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))
+		r = 1;
+	else
+		r = dm_table_any_busy_target(map);
+
+	dm_table_put(map);
+
+	return r;
+}
+
 static void dm_unplug_all(struct request_queue *q)
 {
 	struct mapped_device *md = q->queuedata;
 	struct dm_table *map = dm_get_table(md);
 
 	if (map) {
+		if (dm_request_based(md))
+			generic_unplug_device(q);
+
 		dm_table_unplug_all(map);
 		dm_table_put(map);
 	}
@@ -1003,7 +1622,16 @@
 	if (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
 		map = dm_get_table(md);
 		if (map) {
-			r = dm_table_any_congested(map, bdi_bits);
+			/*
+			 * Request-based dm cares about only own queue for
+			 * the query about congestion status of request_queue
+			 */
+			if (dm_request_based(md))
+				r = md->queue->backing_dev_info.state &
+				    bdi_bits;
+			else
+				r = dm_table_any_congested(map, bdi_bits);
+
 			dm_table_put(map);
 		}
 	}
@@ -1126,30 +1754,32 @@
 	INIT_LIST_HEAD(&md->uevent_list);
 	spin_lock_init(&md->uevent_lock);
 
-	md->queue = blk_alloc_queue(GFP_KERNEL);
+	md->queue = blk_init_queue(dm_request_fn, NULL);
 	if (!md->queue)
 		goto bad_queue;
 
+	/*
+	 * Request-based dm devices cannot be stacked on top of bio-based dm
+	 * devices.  The type of this dm device has not been decided yet,
+	 * although we initialized the queue using blk_init_queue().
+	 * The type is decided at the first table loading time.
+	 * To prevent problematic device stacking, clear the queue flag
+	 * for request stacking support until then.
+	 *
+	 * This queue is new, so no concurrency on the queue_flags.
+	 */
+	queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue);
+	md->saved_make_request_fn = md->queue->make_request_fn;
 	md->queue->queuedata = md;
 	md->queue->backing_dev_info.congested_fn = dm_any_congested;
 	md->queue->backing_dev_info.congested_data = md;
 	blk_queue_make_request(md->queue, dm_request);
-	blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN, NULL);
 	blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
 	md->queue->unplug_fn = dm_unplug_all;
 	blk_queue_merge_bvec(md->queue, dm_merge_bvec);
-
-	md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
-	if (!md->io_pool)
-		goto bad_io_pool;
-
-	md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache);
-	if (!md->tio_pool)
-		goto bad_tio_pool;
-
-	md->bs = bioset_create(16, 0);
-	if (!md->bs)
-		goto bad_no_bioset;
+	blk_queue_softirq_done(md->queue, dm_softirq_done);
+	blk_queue_prep_rq(md->queue, dm_prep_fn);
+	blk_queue_lld_busy(md->queue, dm_lld_busy);
 
 	md->disk = alloc_disk(1);
 	if (!md->disk)
@@ -1173,6 +1803,10 @@
 	if (!md->wq)
 		goto bad_thread;
 
+	md->bdev = bdget_disk(md->disk, 0);
+	if (!md->bdev)
+		goto bad_bdev;
+
 	/* Populate the mapping, nobody knows we exist yet */
 	spin_lock(&_minor_lock);
 	old_md = idr_replace(&_minor_idr, md, minor);
@@ -1182,15 +1816,11 @@
 
 	return md;
 
+bad_bdev:
+	destroy_workqueue(md->wq);
 bad_thread:
 	put_disk(md->disk);
 bad_disk:
-	bioset_free(md->bs);
-bad_no_bioset:
-	mempool_destroy(md->tio_pool);
-bad_tio_pool:
-	mempool_destroy(md->io_pool);
-bad_io_pool:
 	blk_cleanup_queue(md->queue);
 bad_queue:
 	free_minor(minor);
@@ -1207,14 +1837,15 @@
 {
 	int minor = MINOR(disk_devt(md->disk));
 
-	if (md->suspended_bdev) {
-		unlock_fs(md);
-		bdput(md->suspended_bdev);
-	}
+	unlock_fs(md);
+	bdput(md->bdev);
 	destroy_workqueue(md->wq);
-	mempool_destroy(md->tio_pool);
-	mempool_destroy(md->io_pool);
-	bioset_free(md->bs);
+	if (md->tio_pool)
+		mempool_destroy(md->tio_pool);
+	if (md->io_pool)
+		mempool_destroy(md->io_pool);
+	if (md->bs)
+		bioset_free(md->bs);
 	blk_integrity_unregister(md->disk);
 	del_gendisk(md->disk);
 	free_minor(minor);
@@ -1229,6 +1860,29 @@
 	kfree(md);
 }
 
+static void __bind_mempools(struct mapped_device *md, struct dm_table *t)
+{
+	struct dm_md_mempools *p;
+
+	if (md->io_pool && md->tio_pool && md->bs)
+		/* the md already has necessary mempools */
+		goto out;
+
+	p = dm_table_get_md_mempools(t);
+	BUG_ON(!p || md->io_pool || md->tio_pool || md->bs);
+
+	md->io_pool = p->io_pool;
+	p->io_pool = NULL;
+	md->tio_pool = p->tio_pool;
+	p->tio_pool = NULL;
+	md->bs = p->bs;
+	p->bs = NULL;
+
+out:
+	/* mempool bind completed, now no need any mempools in the table */
+	dm_table_free_md_mempools(t);
+}
+
 /*
  * Bind a table to the device.
  */
@@ -1252,15 +1906,17 @@
 {
 	set_capacity(md->disk, size);
 
-	mutex_lock(&md->suspended_bdev->bd_inode->i_mutex);
-	i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
-	mutex_unlock(&md->suspended_bdev->bd_inode->i_mutex);
+	mutex_lock(&md->bdev->bd_inode->i_mutex);
+	i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
+	mutex_unlock(&md->bdev->bd_inode->i_mutex);
 }
 
-static int __bind(struct mapped_device *md, struct dm_table *t)
+static int __bind(struct mapped_device *md, struct dm_table *t,
+		  struct queue_limits *limits)
 {
 	struct request_queue *q = md->queue;
 	sector_t size;
+	unsigned long flags;
 
 	size = dm_table_get_size(t);
 
@@ -1270,8 +1926,7 @@
 	if (size != get_capacity(md->disk))
 		memset(&md->geometry, 0, sizeof(md->geometry));
 
-	if (md->suspended_bdev)
-		__set_size(md, size);
+	__set_size(md, size);
 
 	if (!size) {
 		dm_table_destroy(t);
@@ -1280,10 +1935,22 @@
 
 	dm_table_event_callback(t, event_callback, md);
 
-	write_lock(&md->map_lock);
+	/*
+	 * The queue hasn't been stopped yet, if the old table type wasn't
+	 * for request-based during suspension.  So stop it to prevent
+	 * I/O mapping before resume.
+	 * This must be done before setting the queue restrictions,
+	 * because request-based dm may be run just after the setting.
+	 */
+	if (dm_table_request_based(t) && !blk_queue_stopped(q))
+		stop_queue(q);
+
+	__bind_mempools(md, t);
+
+	write_lock_irqsave(&md->map_lock, flags);
 	md->map = t;
-	dm_table_set_restrictions(t, q);
-	write_unlock(&md->map_lock);
+	dm_table_set_restrictions(t, q, limits);
+	write_unlock_irqrestore(&md->map_lock, flags);
 
 	return 0;
 }
@@ -1291,14 +1958,15 @@
 static void __unbind(struct mapped_device *md)
 {
 	struct dm_table *map = md->map;
+	unsigned long flags;
 
 	if (!map)
 		return;
 
 	dm_table_event_callback(map, NULL, NULL);
-	write_lock(&md->map_lock);
+	write_lock_irqsave(&md->map_lock, flags);
 	md->map = NULL;
-	write_unlock(&md->map_lock);
+	write_unlock_irqrestore(&md->map_lock, flags);
 	dm_table_destroy(map);
 }
 
@@ -1402,6 +2070,8 @@
 {
 	int r = 0;
 	DECLARE_WAITQUEUE(wait, current);
+	struct request_queue *q = md->queue;
+	unsigned long flags;
 
 	dm_unplug_all(md->queue);
 
@@ -1411,7 +2081,14 @@
 		set_current_state(interruptible);
 
 		smp_mb();
-		if (!atomic_read(&md->pending))
+		if (dm_request_based(md)) {
+			spin_lock_irqsave(q->queue_lock, flags);
+			if (!queue_in_flight(q) && blk_queue_stopped(q)) {
+				spin_unlock_irqrestore(q->queue_lock, flags);
+				break;
+			}
+			spin_unlock_irqrestore(q->queue_lock, flags);
+		} else if (!atomic_read(&md->pending))
 			break;
 
 		if (interruptible == TASK_INTERRUPTIBLE &&
@@ -1429,34 +2106,36 @@
 	return r;
 }
 
-static int dm_flush(struct mapped_device *md)
+static void dm_flush(struct mapped_device *md)
 {
 	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-	return 0;
+
+	bio_init(&md->barrier_bio);
+	md->barrier_bio.bi_bdev = md->bdev;
+	md->barrier_bio.bi_rw = WRITE_BARRIER;
+	__split_and_process_bio(md, &md->barrier_bio);
+
+	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
 }
 
 static void process_barrier(struct mapped_device *md, struct bio *bio)
 {
-	int error = dm_flush(md);
-
-	if (unlikely(error)) {
-		bio_endio(bio, error);
-		return;
-	}
-	if (bio_empty_barrier(bio)) {
-		bio_endio(bio, 0);
-		return;
-	}
-
-	__split_and_process_bio(md, bio);
+	md->barrier_error = 0;
 
-	error = dm_flush(md);
+	dm_flush(md);
 
-	if (!error && md->barrier_error)
-		error = md->barrier_error;
+	if (!bio_empty_barrier(bio)) {
+		__split_and_process_bio(md, bio);
+		dm_flush(md);
+	}
 
 	if (md->barrier_error != DM_ENDIO_REQUEUE)
-		bio_endio(bio, error);
+		bio_endio(bio, md->barrier_error);
+	else {
+		spin_lock_irq(&md->deferred_lock);
+		bio_list_add_head(&md->deferred, bio);
+		spin_unlock_irq(&md->deferred_lock);
+	}
 }
 
 /*
@@ -1482,10 +2161,14 @@
 
 		up_write(&md->io_lock);
 
-		if (bio_barrier(c))
-			process_barrier(md, c);
-		else
-			__split_and_process_bio(md, c);
+		if (dm_request_based(md))
+			generic_make_request(c);
+		else {
+			if (bio_barrier(c))
+				process_barrier(md, c);
+			else
+				__split_and_process_bio(md, c);
+		}
 
 		down_write(&md->io_lock);
 	}
@@ -1505,6 +2188,7 @@
  */
 int dm_swap_table(struct mapped_device *md, struct dm_table *table)
 {
+	struct queue_limits limits;
 	int r = -EINVAL;
 
 	mutex_lock(&md->suspend_lock);
@@ -1513,19 +2197,86 @@
 	if (!dm_suspended(md))
 		goto out;
 
-	/* without bdev, the device size cannot be changed */
-	if (!md->suspended_bdev)
-		if (get_capacity(md->disk) != dm_table_get_size(table))
-			goto out;
+	r = dm_calculate_queue_limits(table, &limits);
+	if (r)
+		goto out;
+
+	/* cannot change the device type, once a table is bound */
+	if (md->map &&
+	    (dm_table_get_type(md->map) != dm_table_get_type(table))) {
+		DMWARN("can't change the device type after a table is bound");
+		goto out;
+	}
 
 	__unbind(md);
-	r = __bind(md, table);
+	r = __bind(md, table, &limits);
 
 out:
 	mutex_unlock(&md->suspend_lock);
 	return r;
 }
 
+static void dm_rq_invalidate_suspend_marker(struct mapped_device *md)
+{
+	md->suspend_rq.special = (void *)0x1;
+}
+
+static void dm_rq_abort_suspend(struct mapped_device *md, int noflush)
+{
+	struct request_queue *q = md->queue;
+	unsigned long flags;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	if (!noflush)
+		dm_rq_invalidate_suspend_marker(md);
+	__start_queue(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+static void dm_rq_start_suspend(struct mapped_device *md, int noflush)
+{
+	struct request *rq = &md->suspend_rq;
+	struct request_queue *q = md->queue;
+
+	if (noflush)
+		stop_queue(q);
+	else {
+		blk_rq_init(q, rq);
+		blk_insert_request(q, rq, 0, NULL);
+	}
+}
+
+static int dm_rq_suspend_available(struct mapped_device *md, int noflush)
+{
+	int r = 1;
+	struct request *rq = &md->suspend_rq;
+	struct request_queue *q = md->queue;
+	unsigned long flags;
+
+	if (noflush)
+		return r;
+
+	/* The marker must be protected by queue lock if it is in use */
+	spin_lock_irqsave(q->queue_lock, flags);
+	if (unlikely(rq->ref_count)) {
+		/*
+		 * This can happen, when the previous flush suspend was
+		 * interrupted, the marker is still in the queue and
+		 * this flush suspend has been invoked, because we don't
+		 * remove the marker at the time of suspend interruption.
+		 * We have only one marker per mapped_device, so we can't
+		 * start another flush suspend while it is in use.
+		 */
+		BUG_ON(!rq->special); /* The marker should be invalidated */
+		DMWARN("Invalidating the previous flush suspend is still in"
+		       " progress.  Please retry later.");
+		r = 0;
+	}
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	return r;
+}
+
 /*
  * Functions to lock and unlock any filesystem running on the
  * device.
@@ -1536,7 +2287,7 @@
 
 	WARN_ON(md->frozen_sb);
 
-	md->frozen_sb = freeze_bdev(md->suspended_bdev);
+	md->frozen_sb = freeze_bdev(md->bdev);
 	if (IS_ERR(md->frozen_sb)) {
 		r = PTR_ERR(md->frozen_sb);
 		md->frozen_sb = NULL;
@@ -1545,9 +2296,6 @@
 
 	set_bit(DMF_FROZEN, &md->flags);
 
-	/* don't bdput right now, we don't want the bdev
-	 * to go away while it is locked.
-	 */
 	return 0;
 }
 
@@ -1556,7 +2304,7 @@
 	if (!test_bit(DMF_FROZEN, &md->flags))
 		return;
 
-	thaw_bdev(md->suspended_bdev, md->frozen_sb);
+	thaw_bdev(md->bdev, md->frozen_sb);
 	md->frozen_sb = NULL;
 	clear_bit(DMF_FROZEN, &md->flags);
 }
@@ -1568,6 +2316,53 @@
  * dm_bind_table, dm_suspend must be called to flush any in
  * flight bios and ensure that any further io gets deferred.
  */
+/*
+ * Suspend mechanism in request-based dm.
+ *
+ * After the suspend starts, further incoming requests are kept in
+ * the request_queue and deferred.
+ * Remaining requests in the request_queue at the start of suspend are flushed
+ * if it is flush suspend.
+ * The suspend completes when the following conditions have been satisfied,
+ * so wait for it:
+ *    1. q->in_flight is 0 (which means no in_flight request)
+ *    2. queue has been stopped (which means no request dispatching)
+ *
+ *
+ * Noflush suspend
+ * ---------------
+ * Noflush suspend doesn't need to dispatch remaining requests.
+ * So stop the queue immediately.  Then, wait for all in_flight requests
+ * to be completed or requeued.
+ *
+ * To abort noflush suspend, start the queue.
+ *
+ *
+ * Flush suspend
+ * -------------
+ * Flush suspend needs to dispatch remaining requests.  So stop the queue
+ * after the remaining requests are completed. (Requeued request must be also
+ * re-dispatched and completed.  Until then, we can't stop the queue.)
+ *
+ * During flushing the remaining requests, further incoming requests are also
+ * inserted to the same queue.  To distinguish which requests are to be
+ * flushed, we insert a marker request to the queue at the time of starting
+ * flush suspend, like a barrier.
+ * The dispatching is blocked when the marker is found on the top of the queue.
+ * And the queue is stopped when all in_flight requests are completed, since
+ * that means the remaining requests are completely flushed.
+ * Then, the marker is removed from the queue.
+ *
+ * To abort flush suspend, we also need to take care of the marker, not only
+ * starting the queue.
+ * We don't remove the marker forcibly from the queue since it's against
+ * the block-layer manner.  Instead, we put a invalidated mark on the marker.
+ * When the invalidated marker is found on the top of the queue, it is
+ * immediately removed from the queue, so it doesn't block dispatching.
+ * Because we have only one marker per mapped_device, we can't start another
+ * flush suspend until the invalidated marker is removed from the queue.
+ * So fail and return with -EBUSY in such a case.
+ */
 int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
 {
 	struct dm_table *map = NULL;
@@ -1582,6 +2377,11 @@
 		goto out_unlock;
 	}
 
+	if (dm_request_based(md) && !dm_rq_suspend_available(md, noflush)) {
+		r = -EBUSY;
+		goto out_unlock;
+	}
+
 	map = dm_get_table(md);
 
 	/*
@@ -1594,24 +2394,14 @@
 	/* This does not get reverted if there's an error later. */
 	dm_table_presuspend_targets(map);
 
-	/* bdget() can stall if the pending I/Os are not flushed */
-	if (!noflush) {
-		md->suspended_bdev = bdget_disk(md->disk, 0);
-		if (!md->suspended_bdev) {
-			DMWARN("bdget failed in dm_suspend");
-			r = -ENOMEM;
+	/*
+	 * Flush I/O to the device. noflush supersedes do_lockfs,
+	 * because lock_fs() needs to flush I/Os.
+	 */
+	if (!noflush && do_lockfs) {
+		r = lock_fs(md);
+		if (r)
 			goto out;
-		}
-
-		/*
-		 * Flush I/O to the device. noflush supersedes do_lockfs,
-		 * because lock_fs() needs to flush I/Os.
-		 */
-		if (do_lockfs) {
-			r = lock_fs(md);
-			if (r)
-				goto out;
-		}
 	}
 
 	/*
@@ -1637,6 +2427,9 @@
 
 	flush_workqueue(md->wq);
 
+	if (dm_request_based(md))
+		dm_rq_start_suspend(md, noflush);
+
 	/*
 	 * At this point no more requests are entering target request routines.
 	 * We call dm_wait_for_completion to wait for all existing requests
@@ -1653,6 +2446,9 @@
 	if (r < 0) {
 		dm_queue_flush(md);
 
+		if (dm_request_based(md))
+			dm_rq_abort_suspend(md, noflush);
+
 		unlock_fs(md);
 		goto out; /* pushback list is already flushed, so skip flush */
 	}
@@ -1668,11 +2464,6 @@
 	set_bit(DMF_SUSPENDED, &md->flags);
 
 out:
-	if (r && md->suspended_bdev) {
-		bdput(md->suspended_bdev);
-		md->suspended_bdev = NULL;
-	}
-
 	dm_table_put(map);
 
 out_unlock:
@@ -1699,21 +2490,20 @@
 
 	dm_queue_flush(md);
 
-	unlock_fs(md);
+	/*
+	 * Flushing deferred I/Os must be done after targets are resumed
+	 * so that mapping of targets can work correctly.
+	 * Request-based dm is queueing the deferred I/Os in its request_queue.
+	 */
+	if (dm_request_based(md))
+		start_queue(md->queue);
 
-	if (md->suspended_bdev) {
-		bdput(md->suspended_bdev);
-		md->suspended_bdev = NULL;
-	}
+	unlock_fs(md);
 
 	clear_bit(DMF_SUSPENDED, &md->flags);
 
 	dm_table_unplug_all(map);
-
-	dm_kobject_uevent(md);
-
 	r = 0;
-
 out:
 	dm_table_put(map);
 	mutex_unlock(&md->suspend_lock);
@@ -1724,9 +2514,19 @@
 /*-----------------------------------------------------------------
  * Event notification.
  *---------------------------------------------------------------*/
-void dm_kobject_uevent(struct mapped_device *md)
+void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
+		       unsigned cookie)
 {
-	kobject_uevent(&disk_to_dev(md->disk)->kobj, KOBJ_CHANGE);
+	char udev_cookie[DM_COOKIE_LENGTH];
+	char *envp[] = { udev_cookie, NULL };
+
+	if (!cookie)
+		kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
+	else {
+		snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
+			 DM_COOKIE_ENV_VAR_NAME, cookie);
+		kobject_uevent_env(&disk_to_dev(md->disk)->kobj, action, envp);
+	}
 }
 
 uint32_t dm_next_uevent_seq(struct mapped_device *md)
@@ -1780,6 +2580,10 @@
 	if (&md->kobj != kobj)
 		return NULL;
 
+	if (test_bit(DMF_FREEING, &md->flags) ||
+	    test_bit(DMF_DELETING, &md->flags))
+		return NULL;
+
 	dm_get(md);
 	return md;
 }
@@ -1800,6 +2604,61 @@
 }
 EXPORT_SYMBOL_GPL(dm_noflush_suspending);
 
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type)
+{
+	struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL);
+
+	if (!pools)
+		return NULL;
+
+	pools->io_pool = (type == DM_TYPE_BIO_BASED) ?
+			 mempool_create_slab_pool(MIN_IOS, _io_cache) :
+			 mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache);
+	if (!pools->io_pool)
+		goto free_pools_and_out;
+
+	pools->tio_pool = (type == DM_TYPE_BIO_BASED) ?
+			  mempool_create_slab_pool(MIN_IOS, _tio_cache) :
+			  mempool_create_slab_pool(MIN_IOS, _rq_tio_cache);
+	if (!pools->tio_pool)
+		goto free_io_pool_and_out;
+
+	pools->bs = (type == DM_TYPE_BIO_BASED) ?
+		    bioset_create(16, 0) : bioset_create(MIN_IOS, 0);
+	if (!pools->bs)
+		goto free_tio_pool_and_out;
+
+	return pools;
+
+free_tio_pool_and_out:
+	mempool_destroy(pools->tio_pool);
+
+free_io_pool_and_out:
+	mempool_destroy(pools->io_pool);
+
+free_pools_and_out:
+	kfree(pools);
+
+	return NULL;
+}
+
+void dm_free_md_mempools(struct dm_md_mempools *pools)
+{
+	if (!pools)
+		return;
+
+	if (pools->io_pool)
+		mempool_destroy(pools->io_pool);
+
+	if (pools->tio_pool)
+		mempool_destroy(pools->tio_pool);
+
+	if (pools->bs)
+		bioset_free(pools->bs);
+
+	kfree(pools);
+}
+
 static struct block_device_operations dm_blk_dops = {
 	.open = dm_blk_open,
 	.release = dm_blk_close,
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-crypt.c linux-libre-2.6.31-gnu/drivers/md/dm-crypt.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-crypt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-crypt.c	2009-09-09 18:13:59.000000000 -0400
@@ -776,7 +776,7 @@
 		 * But don't wait if split was due to the io size restriction
 		 */
 		if (unlikely(out_of_pages))
-			congestion_wait(WRITE, HZ/100);
+			congestion_wait(BLK_RW_ASYNC, HZ/100);
 
 		/*
 		 * With async crypto it is unsafe to share the crypto context
@@ -1132,6 +1132,7 @@
 		goto bad_crypt_queue;
 	}
 
+	ti->num_flush_requests = 1;
 	ti->private = cc;
 	return 0;
 
@@ -1189,6 +1190,13 @@
 		     union map_info *map_context)
 {
 	struct dm_crypt_io *io;
+	struct crypt_config *cc;
+
+	if (unlikely(bio_empty_barrier(bio))) {
+		cc = ti->private;
+		bio->bi_bdev = cc->dev->bdev;
+		return DM_MAPIO_REMAPPED;
+	}
 
 	io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin);
 
@@ -1305,9 +1313,17 @@
 	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
 }
 
+static int crypt_iterate_devices(struct dm_target *ti,
+				 iterate_devices_callout_fn fn, void *data)
+{
+	struct crypt_config *cc = ti->private;
+
+	return fn(ti, cc->dev, cc->start, ti->len, data);
+}
+
 static struct target_type crypt_target = {
 	.name   = "crypt",
-	.version= {1, 6, 0},
+	.version = {1, 7, 0},
 	.module = THIS_MODULE,
 	.ctr    = crypt_ctr,
 	.dtr    = crypt_dtr,
@@ -1318,6 +1334,7 @@
 	.resume = crypt_resume,
 	.message = crypt_message,
 	.merge  = crypt_merge,
+	.iterate_devices = crypt_iterate_devices,
 };
 
 static int __init dm_crypt_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-delay.c linux-libre-2.6.31-gnu/drivers/md/dm-delay.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-delay.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-delay.c	2009-09-09 18:13:59.000000000 -0400
@@ -197,6 +197,7 @@
 	mutex_init(&dc->timer_lock);
 	atomic_set(&dc->may_delay, 1);
 
+	ti->num_flush_requests = 1;
 	ti->private = dc;
 	return 0;
 
@@ -278,8 +279,9 @@
 
 	if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) {
 		bio->bi_bdev = dc->dev_write->bdev;
-		bio->bi_sector = dc->start_write +
-				 (bio->bi_sector - ti->begin);
+		if (bio_sectors(bio))
+			bio->bi_sector = dc->start_write +
+					 (bio->bi_sector - ti->begin);
 
 		return delay_bio(dc, dc->write_delay, bio);
 	}
@@ -316,9 +318,26 @@
 	return 0;
 }
 
+static int delay_iterate_devices(struct dm_target *ti,
+				 iterate_devices_callout_fn fn, void *data)
+{
+	struct delay_c *dc = ti->private;
+	int ret = 0;
+
+	ret = fn(ti, dc->dev_read, dc->start_read, ti->len, data);
+	if (ret)
+		goto out;
+
+	if (dc->dev_write)
+		ret = fn(ti, dc->dev_write, dc->start_write, ti->len, data);
+
+out:
+	return ret;
+}
+
 static struct target_type delay_target = {
 	.name	     = "delay",
-	.version     = {1, 0, 2},
+	.version     = {1, 1, 0},
 	.module      = THIS_MODULE,
 	.ctr	     = delay_ctr,
 	.dtr	     = delay_dtr,
@@ -326,6 +345,7 @@
 	.presuspend  = delay_presuspend,
 	.resume	     = delay_resume,
 	.status	     = delay_status,
+	.iterate_devices = delay_iterate_devices,
 };
 
 static int __init dm_delay_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-exception-store.c linux-libre-2.6.31-gnu/drivers/md/dm-exception-store.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-exception-store.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-exception-store.c	2009-09-09 18:13:59.000000000 -0400
@@ -171,6 +171,14 @@
 	 */
 	chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9);
 
+	return dm_exception_store_set_chunk_size(store, chunk_size_ulong,
+						 error);
+}
+
+int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
+				      unsigned long chunk_size_ulong,
+				      char **error)
+{
 	/* Check chunk_size is a power of 2 */
 	if (!is_power_of_2(chunk_size_ulong)) {
 		*error = "Chunk size is not a power of 2";
@@ -178,11 +186,16 @@
 	}
 
 	/* Validate the chunk size against the device block size */
-	if (chunk_size_ulong % (bdev_hardsect_size(store->cow->bdev) >> 9)) {
+	if (chunk_size_ulong % (bdev_logical_block_size(store->cow->bdev) >> 9)) {
 		*error = "Chunk size is not a multiple of device blocksize";
 		return -EINVAL;
 	}
 
+	if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) {
+		*error = "Chunk size is too high";
+		return -EINVAL;
+	}
+
 	store->chunk_size = chunk_size_ulong;
 	store->chunk_mask = chunk_size_ulong - 1;
 	store->chunk_shift = ffs(chunk_size_ulong) - 1;
@@ -195,7 +208,7 @@
 			      struct dm_exception_store **store)
 {
 	int r = 0;
-	struct dm_exception_store_type *type;
+	struct dm_exception_store_type *type = NULL;
 	struct dm_exception_store *tmp_store;
 	char persistent;
 
@@ -211,12 +224,15 @@
 	}
 
 	persistent = toupper(*argv[1]);
-	if (persistent != 'P' && persistent != 'N') {
+	if (persistent == 'P')
+		type = get_type("P");
+	else if (persistent == 'N')
+		type = get_type("N");
+	else {
 		ti->error = "Persistent flag is not P or N";
 		return -EINVAL;
 	}
 
-	type = get_type(argv[1]);
 	if (!type) {
 		ti->error = "Exception store type not recognised";
 		r = -EINVAL;
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-exception-store.h linux-libre-2.6.31-gnu/drivers/md/dm-exception-store.h
--- linux-libre-2.6.30-gnu/drivers/md/dm-exception-store.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-exception-store.h	2009-09-09 18:13:59.000000000 -0400
@@ -111,7 +111,7 @@
 /*
  * Funtions to manipulate consecutive chunks
  */
-#  if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
+#  if defined(CONFIG_LBDAF) || (BITS_PER_LONG == 64)
 #    define DM_CHUNK_CONSECUTIVE_BITS 8
 #    define DM_CHUNK_NUMBER_BITS 56
 
@@ -156,7 +156,7 @@
  */
 static inline sector_t get_dev_size(struct block_device *bdev)
 {
-	return bdev->bd_inode->i_size >> SECTOR_SHIFT;
+	return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
 }
 
 static inline chunk_t sector_to_chunk(struct dm_exception_store *store,
@@ -168,6 +168,10 @@
 int dm_exception_store_type_register(struct dm_exception_store_type *type);
 int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
 
+int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
+				      unsigned long chunk_size_ulong,
+				      char **error);
+
 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
 			      unsigned *args_used,
 			      struct dm_exception_store **store);
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm.h linux-libre-2.6.31-gnu/drivers/md/dm.h
--- linux-libre-2.6.30-gnu/drivers/md/dm.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm.h	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,13 @@
 #define DM_SUSPEND_NOFLUSH_FLAG		(1 << 1)
 
 /*
+ * Type of table and mapped_device's mempool
+ */
+#define DM_TYPE_NONE		0
+#define DM_TYPE_BIO_BASED	1
+#define DM_TYPE_REQUEST_BASED	2
+
+/*
  * List of devices that a metadevice uses and should open/close.
  */
 struct dm_dev_internal {
@@ -32,6 +39,7 @@
 };
 
 struct dm_table;
+struct dm_md_mempools;
 
 /*-----------------------------------------------------------------
  * Internal table functions.
@@ -41,18 +49,33 @@
 			     void (*fn)(void *), void *context);
 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
 struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector);
-void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
+int dm_calculate_queue_limits(struct dm_table *table,
+			      struct queue_limits *limits);
+void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
+			       struct queue_limits *limits);
 struct list_head *dm_table_get_devices(struct dm_table *t);
 void dm_table_presuspend_targets(struct dm_table *t);
 void dm_table_postsuspend_targets(struct dm_table *t);
 int dm_table_resume_targets(struct dm_table *t);
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
+int dm_table_any_busy_target(struct dm_table *t);
+int dm_table_set_type(struct dm_table *t);
+unsigned dm_table_get_type(struct dm_table *t);
+bool dm_table_request_based(struct dm_table *t);
+int dm_table_alloc_md_mempools(struct dm_table *t);
+void dm_table_free_md_mempools(struct dm_table *t);
+struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
 
 /*
  * To check the return value from dm_table_find_target().
  */
 #define dm_target_is_valid(t) ((t)->table)
 
+/*
+ * To check whether the target type is request-based or not (bio-based).
+ */
+#define dm_target_request_based(t) ((t)->type->map_rq != NULL)
+
 /*-----------------------------------------------------------------
  * A registry of target types.
  *---------------------------------------------------------------*/
@@ -92,9 +115,16 @@
 int dm_open_count(struct mapped_device *md);
 int dm_lock_for_deletion(struct mapped_device *md);
 
-void dm_kobject_uevent(struct mapped_device *md);
+void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
+		       unsigned cookie);
 
 int dm_kcopyd_init(void);
 void dm_kcopyd_exit(void);
 
+/*
+ * Mempool operations
+ */
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type);
+void dm_free_md_mempools(struct dm_md_mempools *pools);
+
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-io.c linux-libre-2.6.31-gnu/drivers/md/dm-io.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-io.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 /* FIXME: can we shrink this ? */
 struct io {
 	unsigned long error_bits;
+	unsigned long eopnotsupp_bits;
 	atomic_t count;
 	struct task_struct *sleeper;
 	struct dm_io_client *client;
@@ -107,8 +108,11 @@
  *---------------------------------------------------------------*/
 static void dec_count(struct io *io, unsigned int region, int error)
 {
-	if (error)
+	if (error) {
 		set_bit(region, &io->error_bits);
+		if (error == -EOPNOTSUPP)
+			set_bit(region, &io->eopnotsupp_bits);
+	}
 
 	if (atomic_dec_and_test(&io->count)) {
 		if (io->sleeper)
@@ -360,7 +364,9 @@
 		return -EIO;
 	}
 
+retry:
 	io.error_bits = 0;
+	io.eopnotsupp_bits = 0;
 	atomic_set(&io.count, 1); /* see dispatch_io() */
 	io.sleeper = current;
 	io.client = client;
@@ -377,6 +383,11 @@
 	}
 	set_current_state(TASK_RUNNING);
 
+	if (io.eopnotsupp_bits && (rw & (1 << BIO_RW_BARRIER))) {
+		rw &= ~(1 << BIO_RW_BARRIER);
+		goto retry;
+	}
+
 	if (error_bits)
 		*error_bits = io.error_bits;
 
@@ -397,6 +408,7 @@
 
 	io = mempool_alloc(client->pool, GFP_NOIO);
 	io->error_bits = 0;
+	io->eopnotsupp_bits = 0;
 	atomic_set(&io->count, 1); /* see dispatch_io() */
 	io->sleeper = NULL;
 	io->client = client;
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-ioctl.c linux-libre-2.6.31-gnu/drivers/md/dm-ioctl.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -276,7 +276,7 @@
 	up_write(&_hash_lock);
 }
 
-static int dm_hash_rename(const char *old, const char *new)
+static int dm_hash_rename(uint32_t cookie, const char *old, const char *new)
 {
 	char *new_name, *old_name;
 	struct hash_cell *hc;
@@ -333,7 +333,7 @@
 		dm_table_put(table);
 	}
 
-	dm_kobject_uevent(hc->md);
+	dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie);
 
 	dm_put(hc->md);
 	up_write(&_hash_lock);
@@ -680,6 +680,9 @@
 
 	__hash_remove(hc);
 	up_write(&_hash_lock);
+
+	dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr);
+
 	dm_put(md);
 	param->data_size = 0;
 	return 0;
@@ -715,7 +718,7 @@
 		return r;
 
 	param->data_size = 0;
-	return dm_hash_rename(param->name, new_name);
+	return dm_hash_rename(param->event_nr, param->name, new_name);
 }
 
 static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
@@ -842,8 +845,11 @@
 	if (dm_suspended(md))
 		r = dm_resume(md);
 
-	if (!r)
+
+	if (!r) {
+		dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr);
 		r = __dev_status(md, param);
+	}
 
 	dm_put(md);
 	return r;
@@ -1044,6 +1050,12 @@
 		next = spec->next;
 	}
 
+	r = dm_table_set_type(table);
+	if (r) {
+		DMWARN("unable to set table type");
+		return r;
+	}
+
 	return dm_table_complete(table);
 }
 
@@ -1089,6 +1101,13 @@
 		goto out;
 	}
 
+	r = dm_table_alloc_md_mempools(t);
+	if (r) {
+		DMWARN("unable to allocate mempools for this table");
+		dm_table_destroy(t);
+		goto out;
+	}
+
 	down_write(&_hash_lock);
 	hc = dm_get_mdptr(md);
 	if (!hc || hc->md != md) {
@@ -1513,6 +1532,7 @@
 static struct miscdevice _dm_misc = {
 	.minor 		= MISC_DYNAMIC_MINOR,
 	.name  		= DM_NAME,
+	.devnode	= "mapper/control",
 	.fops  		= &_ctl_fops
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-linear.c linux-libre-2.6.31-gnu/drivers/md/dm-linear.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-linear.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-linear.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,7 @@
 		goto bad;
 	}
 
+	ti->num_flush_requests = 1;
 	ti->private = lc;
 	return 0;
 
@@ -81,7 +82,8 @@
 	struct linear_c *lc = ti->private;
 
 	bio->bi_bdev = lc->dev->bdev;
-	bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
+	if (bio_sectors(bio))
+		bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
 }
 
 static int linear_map(struct dm_target *ti, struct bio *bio,
@@ -132,9 +134,17 @@
 	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
 }
 
+static int linear_iterate_devices(struct dm_target *ti,
+				  iterate_devices_callout_fn fn, void *data)
+{
+	struct linear_c *lc = ti->private;
+
+	return fn(ti, lc->dev, lc->start, ti->len, data);
+}
+
 static struct target_type linear_target = {
 	.name   = "linear",
-	.version= {1, 0, 3},
+	.version = {1, 1, 0},
 	.module = THIS_MODULE,
 	.ctr    = linear_ctr,
 	.dtr    = linear_dtr,
@@ -142,6 +152,7 @@
 	.status = linear_status,
 	.ioctl  = linear_ioctl,
 	.merge  = linear_merge,
+	.iterate_devices = linear_iterate_devices,
 };
 
 int __init dm_linear_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-log.c linux-libre-2.6.31-gnu/drivers/md/dm-log.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-log.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-log.c	2009-09-09 18:13:59.000000000 -0400
@@ -412,10 +412,12 @@
 		/*
 		 * Buffer holds both header and bitset.
 		 */
-		buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) +
-				       bitset_size, ti->limits.hardsect_size);
+		buf_size =
+		    dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size,
+				bdev_logical_block_size(lc->header_location.
+							    bdev));
 
-		if (buf_size > dev->bdev->bd_inode->i_size) {
+		if (buf_size > i_size_read(dev->bdev->bd_inode)) {
 			DMWARN("log device %s too small: need %llu bytes",
 				dev->name, (unsigned long long)buf_size);
 			kfree(lc);
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-log-userspace-base.c linux-libre-2.6.31-gnu/drivers/md/dm-log-userspace-base.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-log-userspace-base.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/md/dm-log-userspace-base.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This file is released under the LGPL.
+ */
+
+#include <linux/bio.h>
+#include <linux/dm-dirty-log.h>
+#include <linux/device-mapper.h>
+#include <linux/dm-log-userspace.h>
+
+#include "dm-log-userspace-transfer.h"
+
+struct flush_entry {
+	int type;
+	region_t region;
+	struct list_head list;
+};
+
+struct log_c {
+	struct dm_target *ti;
+	uint32_t region_size;
+	region_t region_count;
+	uint64_t luid;
+	char uuid[DM_UUID_LEN];
+
+	char *usr_argv_str;
+	uint32_t usr_argc;
+
+	/*
+	 * in_sync_hint gets set when doing is_remote_recovering.  It
+	 * represents the first region that needs recovery.  IOW, the
+	 * first zero bit of sync_bits.  This can be useful for to limit
+	 * traffic for calls like is_remote_recovering and get_resync_work,
+	 * but be take care in its use for anything else.
+	 */
+	uint64_t in_sync_hint;
+
+	spinlock_t flush_lock;
+	struct list_head flush_list;  /* only for clear and mark requests */
+};
+
+static mempool_t *flush_entry_pool;
+
+static void *flush_entry_alloc(gfp_t gfp_mask, void *pool_data)
+{
+	return kmalloc(sizeof(struct flush_entry), gfp_mask);
+}
+
+static void flush_entry_free(void *element, void *pool_data)
+{
+	kfree(element);
+}
+
+static int userspace_do_request(struct log_c *lc, const char *uuid,
+				int request_type, char *data, size_t data_size,
+				char *rdata, size_t *rdata_size)
+{
+	int r;
+
+	/*
+	 * If the server isn't there, -ESRCH is returned,
+	 * and we must keep trying until the server is
+	 * restored.
+	 */
+retry:
+	r = dm_consult_userspace(uuid, lc->luid, request_type, data,
+				 data_size, rdata, rdata_size);
+
+	if (r != -ESRCH)
+		return r;
+
+	DMERR(" Userspace log server not found.");
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(2*HZ);
+		DMWARN("Attempting to contact userspace log server...");
+		r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_CTR,
+					 lc->usr_argv_str,
+					 strlen(lc->usr_argv_str) + 1,
+					 NULL, NULL);
+		if (!r)
+			break;
+	}
+	DMINFO("Reconnected to userspace log server... DM_ULOG_CTR complete");
+	r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_RESUME, NULL,
+				 0, NULL, NULL);
+	if (!r)
+		goto retry;
+
+	DMERR("Error trying to resume userspace log: %d", r);
+
+	return -ESRCH;
+}
+
+static int build_constructor_string(struct dm_target *ti,
+				    unsigned argc, char **argv,
+				    char **ctr_str)
+{
+	int i, str_size;
+	char *str = NULL;
+
+	*ctr_str = NULL;
+
+	for (i = 0, str_size = 0; i < argc; i++)
+		str_size += strlen(argv[i]) + 1; /* +1 for space between args */
+
+	str_size += 20; /* Max number of chars in a printed u64 number */
+
+	str = kzalloc(str_size, GFP_KERNEL);
+	if (!str) {
+		DMWARN("Unable to allocate memory for constructor string");
+		return -ENOMEM;
+	}
+
+	str_size = sprintf(str, "%llu", (unsigned long long)ti->len);
+	for (i = 0; i < argc; i++)
+		str_size += sprintf(str + str_size, " %s", argv[i]);
+
+	*ctr_str = str;
+	return str_size;
+}
+
+/*
+ * userspace_ctr
+ *
+ * argv contains:
+ *	<UUID> <other args>
+ * Where 'other args' is the userspace implementation specific log
+ * arguments.  An example might be:
+ *	<UUID> clustered_disk <arg count> <log dev> <region_size> [[no]sync]
+ *
+ * So, this module will strip off the <UUID> for identification purposes
+ * when communicating with userspace about a log; but will pass on everything
+ * else.
+ */
+static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+			 unsigned argc, char **argv)
+{
+	int r = 0;
+	int str_size;
+	char *ctr_str = NULL;
+	struct log_c *lc = NULL;
+	uint64_t rdata;
+	size_t rdata_size = sizeof(rdata);
+
+	if (argc < 3) {
+		DMWARN("Too few arguments to userspace dirty log");
+		return -EINVAL;
+	}
+
+	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
+	if (!lc) {
+		DMWARN("Unable to allocate userspace log context.");
+		return -ENOMEM;
+	}
+
+	/* The ptr value is sufficient for local unique id */
+	lc->luid = (uint64_t)lc;
+
+	lc->ti = ti;
+
+	if (strlen(argv[0]) > (DM_UUID_LEN - 1)) {
+		DMWARN("UUID argument too long.");
+		kfree(lc);
+		return -EINVAL;
+	}
+
+	strncpy(lc->uuid, argv[0], DM_UUID_LEN);
+	spin_lock_init(&lc->flush_lock);
+	INIT_LIST_HEAD(&lc->flush_list);
+
+	str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str);
+	if (str_size < 0) {
+		kfree(lc);
+		return str_size;
+	}
+
+	/* Send table string */
+	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
+				 ctr_str, str_size, NULL, NULL);
+
+	if (r == -ESRCH) {
+		DMERR("Userspace log server not found");
+		goto out;
+	}
+
+	/* Since the region size does not change, get it now */
+	rdata_size = sizeof(rdata);
+	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_GET_REGION_SIZE,
+				 NULL, 0, (char *)&rdata, &rdata_size);
+
+	if (r) {
+		DMERR("Failed to get region size of dirty log");
+		goto out;
+	}
+
+	lc->region_size = (uint32_t)rdata;
+	lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
+
+out:
+	if (r) {
+		kfree(lc);
+		kfree(ctr_str);
+	} else {
+		lc->usr_argv_str = ctr_str;
+		lc->usr_argc = argc;
+		log->context = lc;
+	}
+
+	return r;
+}
+
+static void userspace_dtr(struct dm_dirty_log *log)
+{
+	int r;
+	struct log_c *lc = log->context;
+
+	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_DTR,
+				 NULL, 0,
+				 NULL, NULL);
+
+	kfree(lc->usr_argv_str);
+	kfree(lc);
+
+	return;
+}
+
+static int userspace_presuspend(struct dm_dirty_log *log)
+{
+	int r;
+	struct log_c *lc = log->context;
+
+	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_PRESUSPEND,
+				 NULL, 0,
+				 NULL, NULL);
+
+	return r;
+}
+
+static int userspace_postsuspend(struct dm_dirty_log *log)
+{
+	int r;
+	struct log_c *lc = log->context;
+
+	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_POSTSUSPEND,
+				 NULL, 0,
+				 NULL, NULL);
+
+	return r;
+}
+
+static int userspace_resume(struct dm_dirty_log *log)
+{
+	int r;
+	struct log_c *lc = log->context;
+
+	lc->in_sync_hint = 0;
+	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_RESUME,
+				 NULL, 0,
+				 NULL, NULL);
+
+	return r;
+}
+
+static uint32_t userspace_get_region_size(struct dm_dirty_log *log)
+{
+	struct log_c *lc = log->context;
+
+	return lc->region_size;
+}
+
+/*
+ * userspace_is_clean
+ *
+ * Check whether a region is clean.  If there is any sort of
+ * failure when consulting the server, we return not clean.
+ *
+ * Returns: 1 if clean, 0 otherwise
+ */
+static int userspace_is_clean(struct dm_dirty_log *log, region_t region)
+{
+	int r;
+	uint64_t region64 = (uint64_t)region;
+	int64_t is_clean;
+	size_t rdata_size;
+	struct log_c *lc = log->context;
+
+	rdata_size = sizeof(is_clean);
+	r = userspace_do_request(lc, lc->uuid, DM_ULOG_IS_CLEAN,
+				 (char *)&region64, sizeof(region64),
+				 (char *)&is_clean, &rdata_size);
+
+	return (r) ? 0 : (int)is_clean;
+}
+
+/*
+ * userspace_in_sync
+ *
+ * Check if the region is in-sync.  If there is any sort
+ * of failure when consulting the server, we assume that
+ * the region is not in sync.
+ *
+ * If 'can_block' is set, return immediately
+ *
+ * Returns: 1 if in-sync, 0 if not-in-sync, -EWOULDBLOCK
+ */
+static int userspace_in_sync(struct dm_dirty_log *log, region_t region,
+			     int can_block)
+{
+	int r;
+	uint64_t region64 = region;
+	int64_t in_sync;
+	size_t rdata_size;
+	struct log_c *lc = log->context;
+
+	/*
+	 * We can never respond directly - even if in_sync_hint is
+	 * set.  This is because another machine could see a device
+	 * failure and mark the region out-of-sync.  If we don't go
+	 * to userspace to ask, we might think the region is in-sync
+	 * and allow a read to pick up data that is stale.  (This is
+	 * very unlikely if a device actually fails; but it is very
+	 * likely if a connection to one device from one machine fails.)
+	 *
+	 * There still might be a problem if the mirror caches the region
+	 * state as in-sync... but then this call would not be made.  So,
+	 * that is a mirror problem.
+	 */
+	if (!can_block)
+		return -EWOULDBLOCK;
+
+	rdata_size = sizeof(in_sync);
+	r = userspace_do_request(lc, lc->uuid, DM_ULOG_IN_SYNC,
+				 (char *)&region64, sizeof(region64),
+				 (char *)&in_sync, &rdata_size);
+	return (r) ? 0 : (int)in_sync;
+}
+
+/*
+ * userspace_flush
+ *
+ * This function is ok to block.
+ * The flush happens in two stages.  First, it sends all
+ * clear/mark requests that are on the list.  Then it
+ * tells the server to commit them.  This gives the
+ * server a chance to optimise the commit, instead of
+ * doing it for every request.
+ *
+ * Additionally, we could implement another thread that
+ * sends the requests up to the server - reducing the
+ * load on flush.  Then the flush would have less in
+ * the list and be responsible for the finishing commit.
+ *
+ * Returns: 0 on success, < 0 on failure
+ */
+static int userspace_flush(struct dm_dirty_log *log)
+{
+	int r = 0;
+	unsigned long flags;
+	struct log_c *lc = log->context;
+	LIST_HEAD(flush_list);
+	struct flush_entry *fe, *tmp_fe;
+
+	spin_lock_irqsave(&lc->flush_lock, flags);
+	list_splice_init(&lc->flush_list, &flush_list);
+	spin_unlock_irqrestore(&lc->flush_lock, flags);
+
+	if (list_empty(&flush_list))
+		return 0;
+
+	/*
+	 * FIXME: Count up requests, group request types,
+	 * allocate memory to stick all requests in and
+	 * send to server in one go.  Failing the allocation,
+	 * do it one by one.
+	 */
+
+	list_for_each_entry(fe, &flush_list, list) {
+		r = userspace_do_request(lc, lc->uuid, fe->type,
+					 (char *)&fe->region,
+					 sizeof(fe->region),
+					 NULL, NULL);
+		if (r)
+			goto fail;
+	}
+
+	r = userspace_do_request(lc, lc->uuid, DM_ULOG_FLUSH,
+				 NULL, 0, NULL, NULL);
+
+fail:
+	/*
+	 * We can safely remove these entries, even if failure.
+	 * Calling code will receive an error and will know that
+	 * the log facility has failed.
+	 */
+	list_for_each_entry_safe(fe, tmp_fe, &flush_list, list) {
+		list_del(&fe->list);
+		mempool_free(fe, flush_entry_pool);
+	}
+
+	if (r)
+		dm_table_event(lc->ti->table);
+
+	return r;
+}
+
+/*
+ * userspace_mark_region
+ *
+ * This function should avoid blocking unless absolutely required.
+ * (Memory allocation is valid for blocking.)
+ */
+static void userspace_mark_region(struct dm_dirty_log *log, region_t region)
+{
+	unsigned long flags;
+	struct log_c *lc = log->context;
+	struct flush_entry *fe;
+
+	/* Wait for an allocation, but _never_ fail */
+	fe = mempool_alloc(flush_entry_pool, GFP_NOIO);
+	BUG_ON(!fe);
+
+	spin_lock_irqsave(&lc->flush_lock, flags);
+	fe->type = DM_ULOG_MARK_REGION;
+	fe->region = region;
+	list_add(&fe->list, &lc->flush_list);
+	spin_unlock_irqrestore(&lc->flush_lock, flags);
+
+	return;
+}
+
+/*
+ * userspace_clear_region
+ *
+ * This function must not block.
+ * So, the alloc can't block.  In the worst case, it is ok to
+ * fail.  It would simply mean we can't clear the region.
+ * Does nothing to current sync context, but does mean
+ * the region will be re-sync'ed on a reload of the mirror
+ * even though it is in-sync.
+ */
+static void userspace_clear_region(struct dm_dirty_log *log, region_t region)
+{
+	unsigned long flags;
+	struct log_c *lc = log->context;
+	struct flush_entry *fe;
+
+	/*
+	 * If we fail to allocate, we skip the clearing of
+	 * the region.  This doesn't hurt us in any way, except
+	 * to cause the region to be resync'ed when the
+	 * device is activated next time.
+	 */
+	fe = mempool_alloc(flush_entry_pool, GFP_ATOMIC);
+	if (!fe) {
+		DMERR("Failed to allocate memory to clear region.");
+		return;
+	}
+
+	spin_lock_irqsave(&lc->flush_lock, flags);
+	fe->type = DM_ULOG_CLEAR_REGION;
+	fe->region = region;
+	list_add(&fe->list, &lc->flush_list);
+	spin_unlock_irqrestore(&lc->flush_lock, flags);
+
+	return;
+}
+
+/*
+ * userspace_get_resync_work
+ *
+ * Get a region that needs recovery.  It is valid to return
+ * an error for this function.
+ *
+ * Returns: 1 if region filled, 0 if no work, <0 on error
+ */
+static int userspace_get_resync_work(struct dm_dirty_log *log, region_t *region)
+{
+	int r;
+	size_t rdata_size;
+	struct log_c *lc = log->context;
+	struct {
+		int64_t i; /* 64-bit for mix arch compatibility */
+		region_t r;
+	} pkg;
+
+	if (lc->in_sync_hint >= lc->region_count)
+		return 0;
+
+	rdata_size = sizeof(pkg);
+	r = userspace_do_request(lc, lc->uuid, DM_ULOG_GET_RESYNC_WORK,
+				 NULL, 0,
+				 (char *)&pkg, &rdata_size);
+
+	*region = pkg.r;
+	return (r) ? r : (int)pkg.i;
+}
+
+/*
+ * userspace_set_region_sync
+ *
+ * Set the sync status of a given region.  This function
+ * must not fail.
+ */
+static void userspace_set_region_sync(struct dm_dirty_log *log,
+				      region_t region, int in_sync)
+{
+	int r;
+	struct log_c *lc = log->context;
+	struct {
+		region_t r;
+		int64_t i;
+	} pkg;
+
+	pkg.r = region;
+	pkg.i = (int64_t)in_sync;
+
+	r = userspace_do_request(lc, lc->uuid, DM_ULOG_SET_REGION_SYNC,
+				 (char *)&pkg, sizeof(pkg),
+				 NULL, NULL);
+
+	/*
+	 * It would be nice to be able to report failures.
+	 * However, it is easy emough to detect and resolve.
+	 */
+	return;
+}
+
+/*
+ * userspace_get_sync_count
+ *
+ * If there is any sort of failure when consulting the server,
+ * we assume that the sync count is zero.
+ *
+ * Returns: sync count on success, 0 on failure
+ */
+static region_t userspace_get_sync_count(struct dm_dirty_log *log)
+{
+	int r;
+	size_t rdata_size;
+	uint64_t sync_count;
+	struct log_c *lc = log->context;
+
+	rdata_size = sizeof(sync_count);
+	r = userspace_do_request(lc, lc->uuid, DM_ULOG_GET_SYNC_COUNT,
+				 NULL, 0,
+				 (char *)&sync_count, &rdata_size);
+
+	if (r)
+		return 0;
+
+	if (sync_count >= lc->region_count)
+		lc->in_sync_hint = lc->region_count;
+
+	return (region_t)sync_count;
+}
+
+/*
+ * userspace_status
+ *
+ * Returns: amount of space consumed
+ */
+static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
+			    char *result, unsigned maxlen)
+{
+	int r = 0;
+	char *table_args;
+	size_t sz = (size_t)maxlen;
+	struct log_c *lc = log->context;
+
+	switch (status_type) {
+	case STATUSTYPE_INFO:
+		r = userspace_do_request(lc, lc->uuid, DM_ULOG_STATUS_INFO,
+					 NULL, 0,
+					 result, &sz);
+
+		if (r) {
+			sz = 0;
+			DMEMIT("%s 1 COM_FAILURE", log->type->name);
+		}
+		break;
+	case STATUSTYPE_TABLE:
+		sz = 0;
+		table_args = strstr(lc->usr_argv_str, " ");
+		BUG_ON(!table_args); /* There will always be a ' ' */
+		table_args++;
+
+		DMEMIT("%s %u %s %s ", log->type->name, lc->usr_argc,
+		       lc->uuid, table_args);
+		break;
+	}
+	return (r) ? 0 : (int)sz;
+}
+
+/*
+ * userspace_is_remote_recovering
+ *
+ * Returns: 1 if region recovering, 0 otherwise
+ */
+static int userspace_is_remote_recovering(struct dm_dirty_log *log,
+					  region_t region)
+{
+	int r;
+	uint64_t region64 = region;
+	struct log_c *lc = log->context;
+	static unsigned long long limit;
+	struct {
+		int64_t is_recovering;
+		uint64_t in_sync_hint;
+	} pkg;
+	size_t rdata_size = sizeof(pkg);
+
+	/*
+	 * Once the mirror has been reported to be in-sync,
+	 * it will never again ask for recovery work.  So,
+	 * we can safely say there is not a remote machine
+	 * recovering if the device is in-sync.  (in_sync_hint
+	 * must be reset at resume time.)
+	 */
+	if (region < lc->in_sync_hint)
+		return 0;
+	else if (jiffies < limit)
+		return 1;
+
+	limit = jiffies + (HZ / 4);
+	r = userspace_do_request(lc, lc->uuid, DM_ULOG_IS_REMOTE_RECOVERING,
+				 (char *)&region64, sizeof(region64),
+				 (char *)&pkg, &rdata_size);
+	if (r)
+		return 1;
+
+	lc->in_sync_hint = pkg.in_sync_hint;
+
+	return (int)pkg.is_recovering;
+}
+
+static struct dm_dirty_log_type _userspace_type = {
+	.name = "userspace",
+	.module = THIS_MODULE,
+	.ctr = userspace_ctr,
+	.dtr = userspace_dtr,
+	.presuspend = userspace_presuspend,
+	.postsuspend = userspace_postsuspend,
+	.resume = userspace_resume,
+	.get_region_size = userspace_get_region_size,
+	.is_clean = userspace_is_clean,
+	.in_sync = userspace_in_sync,
+	.flush = userspace_flush,
+	.mark_region = userspace_mark_region,
+	.clear_region = userspace_clear_region,
+	.get_resync_work = userspace_get_resync_work,
+	.set_region_sync = userspace_set_region_sync,
+	.get_sync_count = userspace_get_sync_count,
+	.status = userspace_status,
+	.is_remote_recovering = userspace_is_remote_recovering,
+};
+
+static int __init userspace_dirty_log_init(void)
+{
+	int r = 0;
+
+	flush_entry_pool = mempool_create(100, flush_entry_alloc,
+					  flush_entry_free, NULL);
+
+	if (!flush_entry_pool) {
+		DMWARN("Unable to create flush_entry_pool:  No memory.");
+		return -ENOMEM;
+	}
+
+	r = dm_ulog_tfr_init();
+	if (r) {
+		DMWARN("Unable to initialize userspace log communications");
+		mempool_destroy(flush_entry_pool);
+		return r;
+	}
+
+	r = dm_dirty_log_type_register(&_userspace_type);
+	if (r) {
+		DMWARN("Couldn't register userspace dirty log type");
+		dm_ulog_tfr_exit();
+		mempool_destroy(flush_entry_pool);
+		return r;
+	}
+
+	DMINFO("version 1.0.0 loaded");
+	return 0;
+}
+
+static void __exit userspace_dirty_log_exit(void)
+{
+	dm_dirty_log_type_unregister(&_userspace_type);
+	dm_ulog_tfr_exit();
+	mempool_destroy(flush_entry_pool);
+
+	DMINFO("version 1.0.0 unloaded");
+	return;
+}
+
+module_init(userspace_dirty_log_init);
+module_exit(userspace_dirty_log_exit);
+
+MODULE_DESCRIPTION(DM_NAME " userspace dirty log link");
+MODULE_AUTHOR("Jonathan Brassow <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-log-userspace-transfer.c linux-libre-2.6.31-gnu/drivers/md/dm-log-userspace-transfer.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-log-userspace-transfer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/md/dm-log-userspace-transfer.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This file is released under the LGPL.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <net/sock.h>
+#include <linux/workqueue.h>
+#include <linux/connector.h>
+#include <linux/device-mapper.h>
+#include <linux/dm-log-userspace.h>
+
+#include "dm-log-userspace-transfer.h"
+
+static uint32_t dm_ulog_seq;
+
+/*
+ * Netlink/Connector is an unreliable protocol.  How long should
+ * we wait for a response before assuming it was lost and retrying?
+ * (If we do receive a response after this time, it will be discarded
+ * and the response to the resent request will be waited for.
+ */
+#define DM_ULOG_RETRY_TIMEOUT (15 * HZ)
+
+/*
+ * Pre-allocated space for speed
+ */
+#define DM_ULOG_PREALLOCED_SIZE 512
+static struct cn_msg *prealloced_cn_msg;
+static struct dm_ulog_request *prealloced_ulog_tfr;
+
+static struct cb_id ulog_cn_id = {
+	.idx = CN_IDX_DM,
+	.val = CN_VAL_DM_USERSPACE_LOG
+};
+
+static DEFINE_MUTEX(dm_ulog_lock);
+
+struct receiving_pkg {
+	struct list_head list;
+	struct completion complete;
+
+	uint32_t seq;
+
+	int error;
+	size_t *data_size;
+	char *data;
+};
+
+static DEFINE_SPINLOCK(receiving_list_lock);
+static struct list_head receiving_list;
+
+static int dm_ulog_sendto_server(struct dm_ulog_request *tfr)
+{
+	int r;
+	struct cn_msg *msg = prealloced_cn_msg;
+
+	memset(msg, 0, sizeof(struct cn_msg));
+
+	msg->id.idx = ulog_cn_id.idx;
+	msg->id.val = ulog_cn_id.val;
+	msg->ack = 0;
+	msg->seq = tfr->seq;
+	msg->len = sizeof(struct dm_ulog_request) + tfr->data_size;
+
+	r = cn_netlink_send(msg, 0, gfp_any());
+
+	return r;
+}
+
+/*
+ * Parameters for this function can be either msg or tfr, but not
+ * both.  This function fills in the reply for a waiting request.
+ * If just msg is given, then the reply is simply an ACK from userspace
+ * that the request was received.
+ *
+ * Returns: 0 on success, -ENOENT on failure
+ */
+static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
+{
+	uint32_t rtn_seq = (msg) ? msg->seq : (tfr) ? tfr->seq : 0;
+	struct receiving_pkg *pkg;
+
+	/*
+	 * The 'receiving_pkg' entries in this list are statically
+	 * allocated on the stack in 'dm_consult_userspace'.
+	 * Each process that is waiting for a reply from the user
+	 * space server will have an entry in this list.
+	 *
+	 * We are safe to do it this way because the stack space
+	 * is unique to each process, but still addressable by
+	 * other processes.
+	 */
+	list_for_each_entry(pkg, &receiving_list, list) {
+		if (rtn_seq != pkg->seq)
+			continue;
+
+		if (msg) {
+			pkg->error = -msg->ack;
+			/*
+			 * If we are trying again, we will need to know our
+			 * storage capacity.  Otherwise, along with the
+			 * error code, we make explicit that we have no data.
+			 */
+			if (pkg->error != -EAGAIN)
+				*(pkg->data_size) = 0;
+		} else if (tfr->data_size > *(pkg->data_size)) {
+			DMERR("Insufficient space to receive package [%u] "
+			      "(%u vs %zu)", tfr->request_type,
+			      tfr->data_size, *(pkg->data_size));
+
+			*(pkg->data_size) = 0;
+			pkg->error = -ENOSPC;
+		} else {
+			pkg->error = tfr->error;
+			memcpy(pkg->data, tfr->data, tfr->data_size);
+			*(pkg->data_size) = tfr->data_size;
+		}
+		complete(&pkg->complete);
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+/*
+ * This is the connector callback that delivers data
+ * that was sent from userspace.
+ */
+static void cn_ulog_callback(void *data)
+{
+	struct cn_msg *msg = (struct cn_msg *)data;
+	struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
+
+	spin_lock(&receiving_list_lock);
+	if (msg->len == 0)
+		fill_pkg(msg, NULL);
+	else if (msg->len < sizeof(*tfr))
+		DMERR("Incomplete message received (expected %u, got %u): [%u]",
+		      (unsigned)sizeof(*tfr), msg->len, msg->seq);
+	else
+		fill_pkg(NULL, tfr);
+	spin_unlock(&receiving_list_lock);
+}
+
+/**
+ * dm_consult_userspace
+ * @uuid: log's universal unique identifier (must be DM_UUID_LEN in size)
+ * @luid: log's local unique identifier
+ * @request_type:  found in include/linux/dm-log-userspace.h
+ * @data: data to tx to the server
+ * @data_size: size of data in bytes
+ * @rdata: place to put return data from server
+ * @rdata_size: value-result (amount of space given/amount of space used)
+ *
+ * rdata_size is undefined on failure.
+ *
+ * Memory used to communicate with userspace is zero'ed
+ * before populating to ensure that no unwanted bits leak
+ * from kernel space to user-space.  All userspace log communications
+ * between kernel and user space go through this function.
+ *
+ * Returns: 0 on success, -EXXX on failure
+ **/
+int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type,
+			 char *data, size_t data_size,
+			 char *rdata, size_t *rdata_size)
+{
+	int r = 0;
+	size_t dummy = 0;
+	int overhead_size =
+		sizeof(struct dm_ulog_request *) + sizeof(struct cn_msg);
+	struct dm_ulog_request *tfr = prealloced_ulog_tfr;
+	struct receiving_pkg pkg;
+
+	if (data_size > (DM_ULOG_PREALLOCED_SIZE - overhead_size)) {
+		DMINFO("Size of tfr exceeds preallocated size");
+		return -EINVAL;
+	}
+
+	if (!rdata_size)
+		rdata_size = &dummy;
+resend:
+	/*
+	 * We serialize the sending of requests so we can
+	 * use the preallocated space.
+	 */
+	mutex_lock(&dm_ulog_lock);
+
+	memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size);
+	memcpy(tfr->uuid, uuid, DM_UUID_LEN);
+	tfr->luid = luid;
+	tfr->seq = dm_ulog_seq++;
+
+	/*
+	 * Must be valid request type (all other bits set to
+	 * zero).  This reserves other bits for possible future
+	 * use.
+	 */
+	tfr->request_type = request_type & DM_ULOG_REQUEST_MASK;
+
+	tfr->data_size = data_size;
+	if (data && data_size)
+		memcpy(tfr->data, data, data_size);
+
+	memset(&pkg, 0, sizeof(pkg));
+	init_completion(&pkg.complete);
+	pkg.seq = tfr->seq;
+	pkg.data_size = rdata_size;
+	pkg.data = rdata;
+	spin_lock(&receiving_list_lock);
+	list_add(&(pkg.list), &receiving_list);
+	spin_unlock(&receiving_list_lock);
+
+	r = dm_ulog_sendto_server(tfr);
+
+	mutex_unlock(&dm_ulog_lock);
+
+	if (r) {
+		DMERR("Unable to send log request [%u] to userspace: %d",
+		      request_type, r);
+		spin_lock(&receiving_list_lock);
+		list_del_init(&(pkg.list));
+		spin_unlock(&receiving_list_lock);
+
+		goto out;
+	}
+
+	r = wait_for_completion_timeout(&(pkg.complete), DM_ULOG_RETRY_TIMEOUT);
+	spin_lock(&receiving_list_lock);
+	list_del_init(&(pkg.list));
+	spin_unlock(&receiving_list_lock);
+	if (!r) {
+		DMWARN("[%s] Request timed out: [%u/%u] - retrying",
+		       (strlen(uuid) > 8) ?
+		       (uuid + (strlen(uuid) - 8)) : (uuid),
+		       request_type, pkg.seq);
+		goto resend;
+	}
+
+	r = pkg.error;
+	if (r == -EAGAIN)
+		goto resend;
+
+out:
+	return r;
+}
+
+int dm_ulog_tfr_init(void)
+{
+	int r;
+	void *prealloced;
+
+	INIT_LIST_HEAD(&receiving_list);
+
+	prealloced = kmalloc(DM_ULOG_PREALLOCED_SIZE, GFP_KERNEL);
+	if (!prealloced)
+		return -ENOMEM;
+
+	prealloced_cn_msg = prealloced;
+	prealloced_ulog_tfr = prealloced + sizeof(struct cn_msg);
+
+	r = cn_add_callback(&ulog_cn_id, "dmlogusr", cn_ulog_callback);
+	if (r) {
+		cn_del_callback(&ulog_cn_id);
+		return r;
+	}
+
+	return 0;
+}
+
+void dm_ulog_tfr_exit(void)
+{
+	cn_del_callback(&ulog_cn_id);
+	kfree(prealloced_cn_msg);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-log-userspace-transfer.h linux-libre-2.6.31-gnu/drivers/md/dm-log-userspace-transfer.h
--- linux-libre-2.6.30-gnu/drivers/md/dm-log-userspace-transfer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/md/dm-log-userspace-transfer.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * This file is released under the LGPL.
+ */
+
+#ifndef __DM_LOG_USERSPACE_TRANSFER_H__
+#define __DM_LOG_USERSPACE_TRANSFER_H__
+
+#define DM_MSG_PREFIX "dm-log-userspace"
+
+int dm_ulog_tfr_init(void);
+void dm_ulog_tfr_exit(void);
+int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type,
+			 char *data, size_t data_size,
+			 char *rdata, size_t *rdata_size);
+
+#endif /* __DM_LOG_USERSPACE_TRANSFER_H__ */
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-mpath.c linux-libre-2.6.31-gnu/drivers/md/dm-mpath.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-mpath.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-mpath.c	2009-09-09 18:13:59.000000000 -0400
@@ -8,7 +8,6 @@
 #include <linux/device-mapper.h>
 
 #include "dm-path-selector.h"
-#include "dm-bio-record.h"
 #include "dm-uevent.h"
 
 #include <linux/ctype.h>
@@ -35,6 +34,7 @@
 
 	struct dm_path path;
 	struct work_struct deactivate_path;
+	struct work_struct activate_path;
 };
 
 #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
@@ -64,8 +64,6 @@
 	spinlock_t lock;
 
 	const char *hw_handler_name;
-	struct work_struct activate_path;
-	struct pgpath *pgpath_to_activate;
 	unsigned nr_priority_groups;
 	struct list_head priority_groups;
 	unsigned pg_init_required;	/* pg_init needs calling? */
@@ -84,7 +82,7 @@
 	unsigned pg_init_count;		/* Number of times pg_init called */
 
 	struct work_struct process_queued_ios;
-	struct bio_list queued_ios;
+	struct list_head queued_ios;
 	unsigned queue_size;
 
 	struct work_struct trigger_event;
@@ -101,7 +99,7 @@
  */
 struct dm_mpath_io {
 	struct pgpath *pgpath;
-	struct dm_bio_details details;
+	size_t nr_bytes;
 };
 
 typedef int (*action_fn) (struct pgpath *pgpath);
@@ -128,6 +126,7 @@
 	if (pgpath) {
 		pgpath->is_active = 1;
 		INIT_WORK(&pgpath->deactivate_path, deactivate_path);
+		INIT_WORK(&pgpath->activate_path, activate_path);
 	}
 
 	return pgpath;
@@ -160,7 +159,6 @@
 
 static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
 {
-	unsigned long flags;
 	struct pgpath *pgpath, *tmp;
 	struct multipath *m = ti->private;
 
@@ -169,10 +167,6 @@
 		if (m->hw_handler_name)
 			scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
 		dm_put_device(ti, pgpath->path.dev);
-		spin_lock_irqsave(&m->lock, flags);
-		if (m->pgpath_to_activate == pgpath)
-			m->pgpath_to_activate = NULL;
-		spin_unlock_irqrestore(&m->lock, flags);
 		free_pgpath(pgpath);
 	}
 }
@@ -198,11 +192,11 @@
 	m = kzalloc(sizeof(*m), GFP_KERNEL);
 	if (m) {
 		INIT_LIST_HEAD(&m->priority_groups);
+		INIT_LIST_HEAD(&m->queued_ios);
 		spin_lock_init(&m->lock);
 		m->queue_io = 1;
 		INIT_WORK(&m->process_queued_ios, process_queued_ios);
 		INIT_WORK(&m->trigger_event, trigger_event);
-		INIT_WORK(&m->activate_path, activate_path);
 		m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
 		if (!m->mpio_pool) {
 			kfree(m);
@@ -250,11 +244,12 @@
 	m->pg_init_count = 0;
 }
 
-static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
+static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg,
+			       size_t nr_bytes)
 {
 	struct dm_path *path;
 
-	path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
+	path = pg->ps.type->select_path(&pg->ps, &m->repeat_count, nr_bytes);
 	if (!path)
 		return -ENXIO;
 
@@ -266,7 +261,7 @@
 	return 0;
 }
 
-static void __choose_pgpath(struct multipath *m)
+static void __choose_pgpath(struct multipath *m, size_t nr_bytes)
 {
 	struct priority_group *pg;
 	unsigned bypassed = 1;
@@ -278,12 +273,12 @@
 	if (m->next_pg) {
 		pg = m->next_pg;
 		m->next_pg = NULL;
-		if (!__choose_path_in_pg(m, pg))
+		if (!__choose_path_in_pg(m, pg, nr_bytes))
 			return;
 	}
 
 	/* Don't change PG until it has no remaining paths */
-	if (m->current_pg && !__choose_path_in_pg(m, m->current_pg))
+	if (m->current_pg && !__choose_path_in_pg(m, m->current_pg, nr_bytes))
 		return;
 
 	/*
@@ -295,7 +290,7 @@
 		list_for_each_entry(pg, &m->priority_groups, list) {
 			if (pg->bypassed == bypassed)
 				continue;
-			if (!__choose_path_in_pg(m, pg))
+			if (!__choose_path_in_pg(m, pg, nr_bytes))
 				return;
 		}
 	} while (bypassed--);
@@ -322,19 +317,21 @@
 		dm_noflush_suspending(m->ti));
 }
 
-static int map_io(struct multipath *m, struct bio *bio,
+static int map_io(struct multipath *m, struct request *clone,
 		  struct dm_mpath_io *mpio, unsigned was_queued)
 {
 	int r = DM_MAPIO_REMAPPED;
+	size_t nr_bytes = blk_rq_bytes(clone);
 	unsigned long flags;
 	struct pgpath *pgpath;
+	struct block_device *bdev;
 
 	spin_lock_irqsave(&m->lock, flags);
 
 	/* Do we need to select a new pgpath? */
 	if (!m->current_pgpath ||
 	    (!m->queue_io && (m->repeat_count && --m->repeat_count == 0)))
-		__choose_pgpath(m);
+		__choose_pgpath(m, nr_bytes);
 
 	pgpath = m->current_pgpath;
 
@@ -344,21 +341,28 @@
 	if ((pgpath && m->queue_io) ||
 	    (!pgpath && m->queue_if_no_path)) {
 		/* Queue for the daemon to resubmit */
-		bio_list_add(&m->queued_ios, bio);
+		list_add_tail(&clone->queuelist, &m->queued_ios);
 		m->queue_size++;
 		if ((m->pg_init_required && !m->pg_init_in_progress) ||
 		    !m->queue_io)
 			queue_work(kmultipathd, &m->process_queued_ios);
 		pgpath = NULL;
 		r = DM_MAPIO_SUBMITTED;
-	} else if (pgpath)
-		bio->bi_bdev = pgpath->path.dev->bdev;
-	else if (__must_push_back(m))
+	} else if (pgpath) {
+		bdev = pgpath->path.dev->bdev;
+		clone->q = bdev_get_queue(bdev);
+		clone->rq_disk = bdev->bd_disk;
+	} else if (__must_push_back(m))
 		r = DM_MAPIO_REQUEUE;
 	else
 		r = -EIO;	/* Failed */
 
 	mpio->pgpath = pgpath;
+	mpio->nr_bytes = nr_bytes;
+
+	if (r == DM_MAPIO_REMAPPED && pgpath->pg->ps.type->start_io)
+		pgpath->pg->ps.type->start_io(&pgpath->pg->ps, &pgpath->path,
+					      nr_bytes);
 
 	spin_unlock_irqrestore(&m->lock, flags);
 
@@ -396,30 +400,31 @@
 {
 	int r;
 	unsigned long flags;
-	struct bio *bio = NULL, *next;
 	struct dm_mpath_io *mpio;
 	union map_info *info;
+	struct request *clone, *n;
+	LIST_HEAD(cl);
 
 	spin_lock_irqsave(&m->lock, flags);
-	bio = bio_list_get(&m->queued_ios);
+	list_splice_init(&m->queued_ios, &cl);
 	spin_unlock_irqrestore(&m->lock, flags);
 
-	while (bio) {
-		next = bio->bi_next;
-		bio->bi_next = NULL;
+	list_for_each_entry_safe(clone, n, &cl, queuelist) {
+		list_del_init(&clone->queuelist);
 
-		info = dm_get_mapinfo(bio);
+		info = dm_get_rq_mapinfo(clone);
 		mpio = info->ptr;
 
-		r = map_io(m, bio, mpio, 1);
-		if (r < 0)
-			bio_endio(bio, r);
-		else if (r == DM_MAPIO_REMAPPED)
-			generic_make_request(bio);
-		else if (r == DM_MAPIO_REQUEUE)
-			bio_endio(bio, -EIO);
-
-		bio = next;
+		r = map_io(m, clone, mpio, 1);
+		if (r < 0) {
+			mempool_free(mpio, m->mpio_pool);
+			dm_kill_unmapped_request(clone, r);
+		} else if (r == DM_MAPIO_REMAPPED)
+			dm_dispatch_request(clone);
+		else if (r == DM_MAPIO_REQUEUE) {
+			mempool_free(mpio, m->mpio_pool);
+			dm_requeue_unmapped_request(clone);
+		}
 	}
 }
 
@@ -427,8 +432,8 @@
 {
 	struct multipath *m =
 		container_of(work, struct multipath, process_queued_ios);
-	struct pgpath *pgpath = NULL;
-	unsigned init_required = 0, must_queue = 1;
+	struct pgpath *pgpath = NULL, *tmp;
+	unsigned must_queue = 1;
 	unsigned long flags;
 
 	spin_lock_irqsave(&m->lock, flags);
@@ -437,7 +442,7 @@
 		goto out;
 
 	if (!m->current_pgpath)
-		__choose_pgpath(m);
+		__choose_pgpath(m, 0);
 
 	pgpath = m->current_pgpath;
 
@@ -446,19 +451,15 @@
 		must_queue = 0;
 
 	if (m->pg_init_required && !m->pg_init_in_progress && pgpath) {
-		m->pgpath_to_activate = pgpath;
 		m->pg_init_count++;
 		m->pg_init_required = 0;
-		m->pg_init_in_progress = 1;
-		init_required = 1;
+		list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) {
+			if (queue_work(kmpath_handlerd, &tmp->activate_path))
+				m->pg_init_in_progress++;
+		}
 	}
-
 out:
 	spin_unlock_irqrestore(&m->lock, flags);
-
-	if (init_required)
-		queue_work(kmpath_handlerd, &m->activate_path);
-
 	if (!must_queue)
 		dispatch_queued_ios(m);
 }
@@ -553,6 +554,12 @@
 		return -EINVAL;
 	}
 
+	if (ps_argc > as->argc) {
+		dm_put_path_selector(pst);
+		ti->error = "not enough arguments for path selector";
+		return -EINVAL;
+	}
+
 	r = pst->create(&pg->ps, ps_argc, as->argv);
 	if (r) {
 		dm_put_path_selector(pst);
@@ -591,9 +598,20 @@
 	}
 
 	if (m->hw_handler_name) {
-		r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev),
-				   m->hw_handler_name);
+		struct request_queue *q = bdev_get_queue(p->path.dev->bdev);
+
+		r = scsi_dh_attach(q, m->hw_handler_name);
+		if (r == -EBUSY) {
+			/*
+			 * Already attached to different hw_handler,
+			 * try to reattach with correct one.
+			 */
+			scsi_dh_detach(q);
+			r = scsi_dh_attach(q, m->hw_handler_name);
+		}
+
 		if (r < 0) {
+			ti->error = "error attaching hardware handler";
 			dm_put_device(ti, p->path.dev);
 			goto bad;
 		}
@@ -699,6 +717,11 @@
 	if (!hw_argc)
 		return 0;
 
+	if (hw_argc > as->argc) {
+		ti->error = "not enough arguments for hardware handler";
+		return -EINVAL;
+	}
+
 	m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL);
 	request_module("scsi_dh_%s", m->hw_handler_name);
 	if (scsi_dh_handler_exist(m->hw_handler_name) == 0) {
@@ -823,6 +846,8 @@
 		goto bad;
 	}
 
+	ti->num_flush_requests = 1;
+
 	return 0;
 
  bad:
@@ -836,25 +861,29 @@
 
 	flush_workqueue(kmpath_handlerd);
 	flush_workqueue(kmultipathd);
+	flush_scheduled_work();
 	free_multipath(m);
 }
 
 /*
- * Map bios, recording original fields for later in case we have to resubmit
+ * Map cloned requests
  */
-static int multipath_map(struct dm_target *ti, struct bio *bio,
+static int multipath_map(struct dm_target *ti, struct request *clone,
 			 union map_info *map_context)
 {
 	int r;
 	struct dm_mpath_io *mpio;
 	struct multipath *m = (struct multipath *) ti->private;
 
-	mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
-	dm_bio_record(&mpio->details, bio);
+	mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC);
+	if (!mpio)
+		/* ENOMEM, requeue */
+		return DM_MAPIO_REQUEUE;
+	memset(mpio, 0, sizeof(*mpio));
 
 	map_context->ptr = mpio;
-	bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT);
-	r = map_io(m, bio, mpio, 0);
+	clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
+	r = map_io(m, clone, mpio, 0);
 	if (r < 0 || r == DM_MAPIO_REQUEUE)
 		mempool_free(mpio, m->mpio_pool);
 
@@ -924,9 +953,13 @@
 
 	pgpath->is_active = 1;
 
-	m->current_pgpath = NULL;
-	if (!m->nr_valid_paths++ && m->queue_size)
+	if (!m->nr_valid_paths++ && m->queue_size) {
+		m->current_pgpath = NULL;
 		queue_work(kmultipathd, &m->process_queued_ios);
+	} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
+		if (queue_work(kmpath_handlerd, &pgpath->activate_path))
+			m->pg_init_in_progress++;
+	}
 
 	dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
 		      pgpath->path.dev->name, m->nr_valid_paths);
@@ -1102,87 +1135,70 @@
 
 	spin_lock_irqsave(&m->lock, flags);
 	if (errors) {
-		DMERR("Could not failover device. Error %d.", errors);
-		m->current_pgpath = NULL;
-		m->current_pg = NULL;
+		if (pgpath == m->current_pgpath) {
+			DMERR("Could not failover device. Error %d.", errors);
+			m->current_pgpath = NULL;
+			m->current_pg = NULL;
+		}
 	} else if (!m->pg_init_required) {
 		m->queue_io = 0;
 		pg->bypassed = 0;
 	}
 
-	m->pg_init_in_progress = 0;
-	queue_work(kmultipathd, &m->process_queued_ios);
+	m->pg_init_in_progress--;
+	if (!m->pg_init_in_progress)
+		queue_work(kmultipathd, &m->process_queued_ios);
 	spin_unlock_irqrestore(&m->lock, flags);
 }
 
 static void activate_path(struct work_struct *work)
 {
 	int ret;
-	struct multipath *m =
-		container_of(work, struct multipath, activate_path);
-	struct dm_path *path;
-	unsigned long flags;
+	struct pgpath *pgpath =
+		container_of(work, struct pgpath, activate_path);
 
-	spin_lock_irqsave(&m->lock, flags);
-	path = &m->pgpath_to_activate->path;
-	m->pgpath_to_activate = NULL;
-	spin_unlock_irqrestore(&m->lock, flags);
-	if (!path)
-		return;
-	ret = scsi_dh_activate(bdev_get_queue(path->dev->bdev));
-	pg_init_done(path, ret);
+	ret = scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev));
+	pg_init_done(&pgpath->path, ret);
 }
 
 /*
  * end_io handling
  */
-static int do_end_io(struct multipath *m, struct bio *bio,
+static int do_end_io(struct multipath *m, struct request *clone,
 		     int error, struct dm_mpath_io *mpio)
 {
+	/*
+	 * We don't queue any clone request inside the multipath target
+	 * during end I/O handling, since those clone requests don't have
+	 * bio clones.  If we queue them inside the multipath target,
+	 * we need to make bio clones, that requires memory allocation.
+	 * (See drivers/md/dm.c:end_clone_bio() about why the clone requests
+	 *  don't have bio clones.)
+	 * Instead of queueing the clone request here, we queue the original
+	 * request into dm core, which will remake a clone request and
+	 * clone bios for it and resubmit it later.
+	 */
+	int r = DM_ENDIO_REQUEUE;
 	unsigned long flags;
 
-	if (!error)
+	if (!error && !clone->errors)
 		return 0;	/* I/O complete */
 
-	if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
-		return error;
-
 	if (error == -EOPNOTSUPP)
 		return error;
 
-	spin_lock_irqsave(&m->lock, flags);
-	if (!m->nr_valid_paths) {
-		if (__must_push_back(m)) {
-			spin_unlock_irqrestore(&m->lock, flags);
-			return DM_ENDIO_REQUEUE;
-		} else if (!m->queue_if_no_path) {
-			spin_unlock_irqrestore(&m->lock, flags);
-			return -EIO;
-		} else {
-			spin_unlock_irqrestore(&m->lock, flags);
-			goto requeue;
-		}
-	}
-	spin_unlock_irqrestore(&m->lock, flags);
-
 	if (mpio->pgpath)
 		fail_path(mpio->pgpath);
 
-      requeue:
-	dm_bio_restore(&mpio->details, bio);
-
-	/* queue for the daemon to resubmit or fail */
 	spin_lock_irqsave(&m->lock, flags);
-	bio_list_add(&m->queued_ios, bio);
-	m->queue_size++;
-	if (!m->queue_io)
-		queue_work(kmultipathd, &m->process_queued_ios);
+	if (!m->nr_valid_paths && !m->queue_if_no_path && !__must_push_back(m))
+		r = -EIO;
 	spin_unlock_irqrestore(&m->lock, flags);
 
-	return DM_ENDIO_INCOMPLETE;	/* io not complete */
+	return r;
 }
 
-static int multipath_end_io(struct dm_target *ti, struct bio *bio,
+static int multipath_end_io(struct dm_target *ti, struct request *clone,
 			    int error, union map_info *map_context)
 {
 	struct multipath *m = ti->private;
@@ -1191,14 +1207,13 @@
 	struct path_selector *ps;
 	int r;
 
-	r  = do_end_io(m, bio, error, mpio);
+	r  = do_end_io(m, clone, error, mpio);
 	if (pgpath) {
 		ps = &pgpath->pg->ps;
 		if (ps->type->end_io)
-			ps->type->end_io(ps, &pgpath->path);
+			ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
 	}
-	if (r != DM_ENDIO_INCOMPLETE)
-		mempool_free(mpio, m->mpio_pool);
+	mempool_free(mpio, m->mpio_pool);
 
 	return r;
 }
@@ -1411,7 +1426,7 @@
 	spin_lock_irqsave(&m->lock, flags);
 
 	if (!m->current_pgpath)
-		__choose_pgpath(m);
+		__choose_pgpath(m, 0);
 
 	if (m->current_pgpath) {
 		bdev = m->current_pgpath->path.dev->bdev;
@@ -1428,22 +1443,113 @@
 	return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
 }
 
+static int multipath_iterate_devices(struct dm_target *ti,
+				     iterate_devices_callout_fn fn, void *data)
+{
+	struct multipath *m = ti->private;
+	struct priority_group *pg;
+	struct pgpath *p;
+	int ret = 0;
+
+	list_for_each_entry(pg, &m->priority_groups, list) {
+		list_for_each_entry(p, &pg->pgpaths, list) {
+			ret = fn(ti, p->path.dev, ti->begin, ti->len, data);
+			if (ret)
+				goto out;
+		}
+	}
+
+out:
+	return ret;
+}
+
+static int __pgpath_busy(struct pgpath *pgpath)
+{
+	struct request_queue *q = bdev_get_queue(pgpath->path.dev->bdev);
+
+	return dm_underlying_device_busy(q);
+}
+
+/*
+ * We return "busy", only when we can map I/Os but underlying devices
+ * are busy (so even if we map I/Os now, the I/Os will wait on
+ * the underlying queue).
+ * In other words, if we want to kill I/Os or queue them inside us
+ * due to map unavailability, we don't return "busy".  Otherwise,
+ * dm core won't give us the I/Os and we can't do what we want.
+ */
+static int multipath_busy(struct dm_target *ti)
+{
+	int busy = 0, has_active = 0;
+	struct multipath *m = ti->private;
+	struct priority_group *pg;
+	struct pgpath *pgpath;
+	unsigned long flags;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	/* Guess which priority_group will be used at next mapping time */
+	if (unlikely(!m->current_pgpath && m->next_pg))
+		pg = m->next_pg;
+	else if (likely(m->current_pg))
+		pg = m->current_pg;
+	else
+		/*
+		 * We don't know which pg will be used at next mapping time.
+		 * We don't call __choose_pgpath() here to avoid to trigger
+		 * pg_init just by busy checking.
+		 * So we don't know whether underlying devices we will be using
+		 * at next mapping time are busy or not. Just try mapping.
+		 */
+		goto out;
+
+	/*
+	 * If there is one non-busy active path at least, the path selector
+	 * will be able to select it. So we consider such a pg as not busy.
+	 */
+	busy = 1;
+	list_for_each_entry(pgpath, &pg->pgpaths, list)
+		if (pgpath->is_active) {
+			has_active = 1;
+
+			if (!__pgpath_busy(pgpath)) {
+				busy = 0;
+				break;
+			}
+		}
+
+	if (!has_active)
+		/*
+		 * No active path in this pg, so this pg won't be used and
+		 * the current_pg will be changed at next mapping time.
+		 * We need to try mapping to determine it.
+		 */
+		busy = 0;
+
+out:
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	return busy;
+}
+
 /*-----------------------------------------------------------------
  * Module setup
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
 	.name = "multipath",
-	.version = {1, 0, 5},
+	.version = {1, 1, 0},
 	.module = THIS_MODULE,
 	.ctr = multipath_ctr,
 	.dtr = multipath_dtr,
-	.map = multipath_map,
-	.end_io = multipath_end_io,
+	.map_rq = multipath_map,
+	.rq_end_io = multipath_end_io,
 	.presuspend = multipath_presuspend,
 	.resume = multipath_resume,
 	.status = multipath_status,
 	.message = multipath_message,
 	.ioctl  = multipath_ioctl,
+	.iterate_devices = multipath_iterate_devices,
+	.busy = multipath_busy,
 };
 
 static int __init dm_multipath_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-path-selector.h linux-libre-2.6.31-gnu/drivers/md/dm-path-selector.h
--- linux-libre-2.6.30-gnu/drivers/md/dm-path-selector.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-path-selector.h	2009-09-09 18:13:59.000000000 -0400
@@ -56,7 +56,8 @@
 	 * the path fails.
 	 */
 	struct dm_path *(*select_path) (struct path_selector *ps,
-				     unsigned *repeat_count);
+					unsigned *repeat_count,
+					size_t nr_bytes);
 
 	/*
 	 * Notify the selector that a path has failed.
@@ -75,7 +76,10 @@
 	int (*status) (struct path_selector *ps, struct dm_path *path,
 		       status_type_t type, char *result, unsigned int maxlen);
 
-	int (*end_io) (struct path_selector *ps, struct dm_path *path);
+	int (*start_io) (struct path_selector *ps, struct dm_path *path,
+			 size_t nr_bytes);
+	int (*end_io) (struct path_selector *ps, struct dm_path *path,
+		       size_t nr_bytes);
 };
 
 /* Register a path selector */
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-queue-length.c linux-libre-2.6.31-gnu/drivers/md/dm-queue-length.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-queue-length.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/md/dm-queue-length.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2004-2005 IBM Corp.  All Rights Reserved.
+ * Copyright (C) 2006-2009 NEC Corporation.
+ *
+ * dm-queue-length.c
+ *
+ * Module Author: Stefan Bader, IBM
+ * Modified by: Kiyoshi Ueda, NEC
+ *
+ * This file is released under the GPL.
+ *
+ * queue-length path selector - choose a path with the least number of
+ * in-flight I/Os.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <asm/atomic.h>
+
+#define DM_MSG_PREFIX	"multipath queue-length"
+#define QL_MIN_IO	128
+#define QL_VERSION	"0.1.0"
+
+struct selector {
+	struct list_head	valid_paths;
+	struct list_head	failed_paths;
+};
+
+struct path_info {
+	struct list_head	list;
+	struct dm_path		*path;
+	unsigned		repeat_count;
+	atomic_t		qlen;	/* the number of in-flight I/Os */
+};
+
+static struct selector *alloc_selector(void)
+{
+	struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (s) {
+		INIT_LIST_HEAD(&s->valid_paths);
+		INIT_LIST_HEAD(&s->failed_paths);
+	}
+
+	return s;
+}
+
+static int ql_create(struct path_selector *ps, unsigned argc, char **argv)
+{
+	struct selector *s = alloc_selector();
+
+	if (!s)
+		return -ENOMEM;
+
+	ps->context = s;
+	return 0;
+}
+
+static void ql_free_paths(struct list_head *paths)
+{
+	struct path_info *pi, *next;
+
+	list_for_each_entry_safe(pi, next, paths, list) {
+		list_del(&pi->list);
+		kfree(pi);
+	}
+}
+
+static void ql_destroy(struct path_selector *ps)
+{
+	struct selector *s = ps->context;
+
+	ql_free_paths(&s->valid_paths);
+	ql_free_paths(&s->failed_paths);
+	kfree(s);
+	ps->context = NULL;
+}
+
+static int ql_status(struct path_selector *ps, struct dm_path *path,
+		     status_type_t type, char *result, unsigned maxlen)
+{
+	unsigned sz = 0;
+	struct path_info *pi;
+
+	/* When called with NULL path, return selector status/args. */
+	if (!path)
+		DMEMIT("0 ");
+	else {
+		pi = path->pscontext;
+
+		switch (type) {
+		case STATUSTYPE_INFO:
+			DMEMIT("%d ", atomic_read(&pi->qlen));
+			break;
+		case STATUSTYPE_TABLE:
+			DMEMIT("%u ", pi->repeat_count);
+			break;
+		}
+	}
+
+	return sz;
+}
+
+static int ql_add_path(struct path_selector *ps, struct dm_path *path,
+		       int argc, char **argv, char **error)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi;
+	unsigned repeat_count = QL_MIN_IO;
+
+	/*
+	 * Arguments: [<repeat_count>]
+	 * 	<repeat_count>: The number of I/Os before switching path.
+	 * 			If not given, default (QL_MIN_IO) is used.
+	 */
+	if (argc > 1) {
+		*error = "queue-length ps: incorrect number of arguments";
+		return -EINVAL;
+	}
+
+	if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+		*error = "queue-length ps: invalid repeat count";
+		return -EINVAL;
+	}
+
+	/* Allocate the path information structure */
+	pi = kmalloc(sizeof(*pi), GFP_KERNEL);
+	if (!pi) {
+		*error = "queue-length ps: Error allocating path information";
+		return -ENOMEM;
+	}
+
+	pi->path = path;
+	pi->repeat_count = repeat_count;
+	atomic_set(&pi->qlen, 0);
+
+	path->pscontext = pi;
+
+	list_add_tail(&pi->list, &s->valid_paths);
+
+	return 0;
+}
+
+static void ql_fail_path(struct path_selector *ps, struct dm_path *path)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi = path->pscontext;
+
+	list_move(&pi->list, &s->failed_paths);
+}
+
+static int ql_reinstate_path(struct path_selector *ps, struct dm_path *path)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi = path->pscontext;
+
+	list_move_tail(&pi->list, &s->valid_paths);
+
+	return 0;
+}
+
+/*
+ * Select a path having the minimum number of in-flight I/Os
+ */
+static struct dm_path *ql_select_path(struct path_selector *ps,
+				      unsigned *repeat_count, size_t nr_bytes)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi = NULL, *best = NULL;
+
+	if (list_empty(&s->valid_paths))
+		return NULL;
+
+	/* Change preferred (first in list) path to evenly balance. */
+	list_move_tail(s->valid_paths.next, &s->valid_paths);
+
+	list_for_each_entry(pi, &s->valid_paths, list) {
+		if (!best ||
+		    (atomic_read(&pi->qlen) < atomic_read(&best->qlen)))
+			best = pi;
+
+		if (!atomic_read(&best->qlen))
+			break;
+	}
+
+	if (!best)
+		return NULL;
+
+	*repeat_count = best->repeat_count;
+
+	return best->path;
+}
+
+static int ql_start_io(struct path_selector *ps, struct dm_path *path,
+		       size_t nr_bytes)
+{
+	struct path_info *pi = path->pscontext;
+
+	atomic_inc(&pi->qlen);
+
+	return 0;
+}
+
+static int ql_end_io(struct path_selector *ps, struct dm_path *path,
+		     size_t nr_bytes)
+{
+	struct path_info *pi = path->pscontext;
+
+	atomic_dec(&pi->qlen);
+
+	return 0;
+}
+
+static struct path_selector_type ql_ps = {
+	.name		= "queue-length",
+	.module		= THIS_MODULE,
+	.table_args	= 1,
+	.info_args	= 1,
+	.create		= ql_create,
+	.destroy	= ql_destroy,
+	.status		= ql_status,
+	.add_path	= ql_add_path,
+	.fail_path	= ql_fail_path,
+	.reinstate_path	= ql_reinstate_path,
+	.select_path	= ql_select_path,
+	.start_io	= ql_start_io,
+	.end_io		= ql_end_io,
+};
+
+static int __init dm_ql_init(void)
+{
+	int r = dm_register_path_selector(&ql_ps);
+
+	if (r < 0)
+		DMERR("register failed %d", r);
+
+	DMINFO("version " QL_VERSION " loaded");
+
+	return r;
+}
+
+static void __exit dm_ql_exit(void)
+{
+	int r = dm_unregister_path_selector(&ql_ps);
+
+	if (r < 0)
+		DMERR("unregister failed %d", r);
+}
+
+module_init(dm_ql_init);
+module_exit(dm_ql_exit);
+
+MODULE_AUTHOR("Stefan Bader <Stefan.Bader at de.ibm.com>");
+MODULE_DESCRIPTION(
+	"(C) Copyright IBM Corp. 2004,2005   All Rights Reserved.\n"
+	DM_NAME " path selector to balance the number of in-flight I/Os"
+);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-raid1.c linux-libre-2.6.31-gnu/drivers/md/dm-raid1.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-raid1.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-raid1.c	2009-09-09 18:13:59.000000000 -0400
@@ -638,6 +638,7 @@
 		spin_lock_irq(&ms->lock);
 		bio_list_merge(&ms->writes, &requeue);
 		spin_unlock_irq(&ms->lock);
+		delayed_wake(ms);
 	}
 
 	/*
@@ -647,7 +648,13 @@
 	 */
 	dm_rh_inc_pending(ms->rh, &sync);
 	dm_rh_inc_pending(ms->rh, &nosync);
-	ms->log_failure = dm_rh_flush(ms->rh) ? 1 : 0;
+
+	/*
+	 * If the flush fails on a previous call and succeeds here,
+	 * we must not reset the log_failure variable.  We need
+	 * userspace interaction to do that.
+	 */
+	ms->log_failure = dm_rh_flush(ms->rh) ? 1 : ms->log_failure;
 
 	/*
 	 * Dispatch io.
@@ -1283,9 +1290,23 @@
 	return 0;
 }
 
+static int mirror_iterate_devices(struct dm_target *ti,
+				  iterate_devices_callout_fn fn, void *data)
+{
+	struct mirror_set *ms = ti->private;
+	int ret = 0;
+	unsigned i;
+
+	for (i = 0; !ret && i < ms->nr_mirrors; i++)
+		ret = fn(ti, ms->mirror[i].dev,
+			 ms->mirror[i].offset, ti->len, data);
+
+	return ret;
+}
+
 static struct target_type mirror_target = {
 	.name	 = "mirror",
-	.version = {1, 0, 20},
+	.version = {1, 12, 0},
 	.module	 = THIS_MODULE,
 	.ctr	 = mirror_ctr,
 	.dtr	 = mirror_dtr,
@@ -1295,6 +1316,7 @@
 	.postsuspend = mirror_postsuspend,
 	.resume	 = mirror_resume,
 	.status	 = mirror_status,
+	.iterate_devices = mirror_iterate_devices,
 };
 
 static int __init dm_mirror_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-region-hash.c linux-libre-2.6.31-gnu/drivers/md/dm-region-hash.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-region-hash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-region-hash.c	2009-09-09 18:13:59.000000000 -0400
@@ -283,7 +283,7 @@
 
 	nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
 	if (unlikely(!nreg))
-		nreg = kmalloc(sizeof(*nreg), GFP_NOIO);
+		nreg = kmalloc(sizeof(*nreg), GFP_NOIO | __GFP_NOFAIL);
 
 	nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
 		      DM_RH_CLEAN : DM_RH_NOSYNC;
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-round-robin.c linux-libre-2.6.31-gnu/drivers/md/dm-round-robin.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-round-robin.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-round-robin.c	2009-09-09 18:13:59.000000000 -0400
@@ -161,7 +161,7 @@
 }
 
 static struct dm_path *rr_select_path(struct path_selector *ps,
-				   unsigned *repeat_count)
+				      unsigned *repeat_count, size_t nr_bytes)
 {
 	struct selector *s = (struct selector *) ps->context;
 	struct path_info *pi = NULL;
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-service-time.c linux-libre-2.6.31-gnu/drivers/md/dm-service-time.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-service-time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/md/dm-service-time.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2007-2009 NEC Corporation.  All Rights Reserved.
+ *
+ * Module Author: Kiyoshi Ueda
+ *
+ * This file is released under the GPL.
+ *
+ * Throughput oriented path selector.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+
+#define DM_MSG_PREFIX	"multipath service-time"
+#define ST_MIN_IO	1
+#define ST_MAX_RELATIVE_THROUGHPUT	100
+#define ST_MAX_RELATIVE_THROUGHPUT_SHIFT	7
+#define ST_MAX_INFLIGHT_SIZE	((size_t)-1 >> ST_MAX_RELATIVE_THROUGHPUT_SHIFT)
+#define ST_VERSION	"0.2.0"
+
+struct selector {
+	struct list_head valid_paths;
+	struct list_head failed_paths;
+};
+
+struct path_info {
+	struct list_head list;
+	struct dm_path *path;
+	unsigned repeat_count;
+	unsigned relative_throughput;
+	atomic_t in_flight_size;	/* Total size of in-flight I/Os */
+};
+
+static struct selector *alloc_selector(void)
+{
+	struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (s) {
+		INIT_LIST_HEAD(&s->valid_paths);
+		INIT_LIST_HEAD(&s->failed_paths);
+	}
+
+	return s;
+}
+
+static int st_create(struct path_selector *ps, unsigned argc, char **argv)
+{
+	struct selector *s = alloc_selector();
+
+	if (!s)
+		return -ENOMEM;
+
+	ps->context = s;
+	return 0;
+}
+
+static void free_paths(struct list_head *paths)
+{
+	struct path_info *pi, *next;
+
+	list_for_each_entry_safe(pi, next, paths, list) {
+		list_del(&pi->list);
+		kfree(pi);
+	}
+}
+
+static void st_destroy(struct path_selector *ps)
+{
+	struct selector *s = ps->context;
+
+	free_paths(&s->valid_paths);
+	free_paths(&s->failed_paths);
+	kfree(s);
+	ps->context = NULL;
+}
+
+static int st_status(struct path_selector *ps, struct dm_path *path,
+		     status_type_t type, char *result, unsigned maxlen)
+{
+	unsigned sz = 0;
+	struct path_info *pi;
+
+	if (!path)
+		DMEMIT("0 ");
+	else {
+		pi = path->pscontext;
+
+		switch (type) {
+		case STATUSTYPE_INFO:
+			DMEMIT("%d %u ", atomic_read(&pi->in_flight_size),
+			       pi->relative_throughput);
+			break;
+		case STATUSTYPE_TABLE:
+			DMEMIT("%u %u ", pi->repeat_count,
+			       pi->relative_throughput);
+			break;
+		}
+	}
+
+	return sz;
+}
+
+static int st_add_path(struct path_selector *ps, struct dm_path *path,
+		       int argc, char **argv, char **error)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi;
+	unsigned repeat_count = ST_MIN_IO;
+	unsigned relative_throughput = 1;
+
+	/*
+	 * Arguments: [<repeat_count> [<relative_throughput>]]
+	 * 	<repeat_count>: The number of I/Os before switching path.
+	 * 			If not given, default (ST_MIN_IO) is used.
+	 * 	<relative_throughput>: The relative throughput value of
+	 *			the path among all paths in the path-group.
+	 * 			The valid range: 0-<ST_MAX_RELATIVE_THROUGHPUT>
+	 *			If not given, minimum value '1' is used.
+	 *			If '0' is given, the path isn't selected while
+	 * 			other paths having a positive value are
+	 * 			available.
+	 */
+	if (argc > 2) {
+		*error = "service-time ps: incorrect number of arguments";
+		return -EINVAL;
+	}
+
+	if (argc && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+		*error = "service-time ps: invalid repeat count";
+		return -EINVAL;
+	}
+
+	if ((argc == 2) &&
+	    (sscanf(argv[1], "%u", &relative_throughput) != 1 ||
+	     relative_throughput > ST_MAX_RELATIVE_THROUGHPUT)) {
+		*error = "service-time ps: invalid relative_throughput value";
+		return -EINVAL;
+	}
+
+	/* allocate the path */
+	pi = kmalloc(sizeof(*pi), GFP_KERNEL);
+	if (!pi) {
+		*error = "service-time ps: Error allocating path context";
+		return -ENOMEM;
+	}
+
+	pi->path = path;
+	pi->repeat_count = repeat_count;
+	pi->relative_throughput = relative_throughput;
+	atomic_set(&pi->in_flight_size, 0);
+
+	path->pscontext = pi;
+
+	list_add_tail(&pi->list, &s->valid_paths);
+
+	return 0;
+}
+
+static void st_fail_path(struct path_selector *ps, struct dm_path *path)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi = path->pscontext;
+
+	list_move(&pi->list, &s->failed_paths);
+}
+
+static int st_reinstate_path(struct path_selector *ps, struct dm_path *path)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi = path->pscontext;
+
+	list_move_tail(&pi->list, &s->valid_paths);
+
+	return 0;
+}
+
+/*
+ * Compare the estimated service time of 2 paths, pi1 and pi2,
+ * for the incoming I/O.
+ *
+ * Returns:
+ * < 0 : pi1 is better
+ * 0   : no difference between pi1 and pi2
+ * > 0 : pi2 is better
+ *
+ * Description:
+ * Basically, the service time is estimated by:
+ *     ('pi->in-flight-size' + 'incoming') / 'pi->relative_throughput'
+ * To reduce the calculation, some optimizations are made.
+ * (See comments inline)
+ */
+static int st_compare_load(struct path_info *pi1, struct path_info *pi2,
+			   size_t incoming)
+{
+	size_t sz1, sz2, st1, st2;
+
+	sz1 = atomic_read(&pi1->in_flight_size);
+	sz2 = atomic_read(&pi2->in_flight_size);
+
+	/*
+	 * Case 1: Both have same throughput value. Choose less loaded path.
+	 */
+	if (pi1->relative_throughput == pi2->relative_throughput)
+		return sz1 - sz2;
+
+	/*
+	 * Case 2a: Both have same load. Choose higher throughput path.
+	 * Case 2b: One path has no throughput value. Choose the other one.
+	 */
+	if (sz1 == sz2 ||
+	    !pi1->relative_throughput || !pi2->relative_throughput)
+		return pi2->relative_throughput - pi1->relative_throughput;
+
+	/*
+	 * Case 3: Calculate service time. Choose faster path.
+	 *         Service time using pi1:
+	 *             st1 = (sz1 + incoming) / pi1->relative_throughput
+	 *         Service time using pi2:
+	 *             st2 = (sz2 + incoming) / pi2->relative_throughput
+	 *
+	 *         To avoid the division, transform the expression to use
+	 *         multiplication.
+	 *         Because ->relative_throughput > 0 here, if st1 < st2,
+	 *         the expressions below are the same meaning:
+	 *             (sz1 + incoming) / pi1->relative_throughput <
+	 *                 (sz2 + incoming) / pi2->relative_throughput
+	 *             (sz1 + incoming) * pi2->relative_throughput <
+	 *                 (sz2 + incoming) * pi1->relative_throughput
+	 *         So use the later one.
+	 */
+	sz1 += incoming;
+	sz2 += incoming;
+	if (unlikely(sz1 >= ST_MAX_INFLIGHT_SIZE ||
+		     sz2 >= ST_MAX_INFLIGHT_SIZE)) {
+		/*
+		 * Size may be too big for multiplying pi->relative_throughput
+		 * and overflow.
+		 * To avoid the overflow and mis-selection, shift down both.
+		 */
+		sz1 >>= ST_MAX_RELATIVE_THROUGHPUT_SHIFT;
+		sz2 >>= ST_MAX_RELATIVE_THROUGHPUT_SHIFT;
+	}
+	st1 = sz1 * pi2->relative_throughput;
+	st2 = sz2 * pi1->relative_throughput;
+	if (st1 != st2)
+		return st1 - st2;
+
+	/*
+	 * Case 4: Service time is equal. Choose higher throughput path.
+	 */
+	return pi2->relative_throughput - pi1->relative_throughput;
+}
+
+static struct dm_path *st_select_path(struct path_selector *ps,
+				      unsigned *repeat_count, size_t nr_bytes)
+{
+	struct selector *s = ps->context;
+	struct path_info *pi = NULL, *best = NULL;
+
+	if (list_empty(&s->valid_paths))
+		return NULL;
+
+	/* Change preferred (first in list) path to evenly balance. */
+	list_move_tail(s->valid_paths.next, &s->valid_paths);
+
+	list_for_each_entry(pi, &s->valid_paths, list)
+		if (!best || (st_compare_load(pi, best, nr_bytes) < 0))
+			best = pi;
+
+	if (!best)
+		return NULL;
+
+	*repeat_count = best->repeat_count;
+
+	return best->path;
+}
+
+static int st_start_io(struct path_selector *ps, struct dm_path *path,
+		       size_t nr_bytes)
+{
+	struct path_info *pi = path->pscontext;
+
+	atomic_add(nr_bytes, &pi->in_flight_size);
+
+	return 0;
+}
+
+static int st_end_io(struct path_selector *ps, struct dm_path *path,
+		     size_t nr_bytes)
+{
+	struct path_info *pi = path->pscontext;
+
+	atomic_sub(nr_bytes, &pi->in_flight_size);
+
+	return 0;
+}
+
+static struct path_selector_type st_ps = {
+	.name		= "service-time",
+	.module		= THIS_MODULE,
+	.table_args	= 2,
+	.info_args	= 2,
+	.create		= st_create,
+	.destroy	= st_destroy,
+	.status		= st_status,
+	.add_path	= st_add_path,
+	.fail_path	= st_fail_path,
+	.reinstate_path	= st_reinstate_path,
+	.select_path	= st_select_path,
+	.start_io	= st_start_io,
+	.end_io		= st_end_io,
+};
+
+static int __init dm_st_init(void)
+{
+	int r = dm_register_path_selector(&st_ps);
+
+	if (r < 0)
+		DMERR("register failed %d", r);
+
+	DMINFO("version " ST_VERSION " loaded");
+
+	return r;
+}
+
+static void __exit dm_st_exit(void)
+{
+	int r = dm_unregister_path_selector(&st_ps);
+
+	if (r < 0)
+		DMERR("unregister failed %d", r);
+}
+
+module_init(dm_st_init);
+module_exit(dm_st_exit);
+
+MODULE_DESCRIPTION(DM_NAME " throughput oriented path selector");
+MODULE_AUTHOR("Kiyoshi Ueda <k-ueda@ct.jp.nec.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-snap.c linux-libre-2.6.31-gnu/drivers/md/dm-snap.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-snap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-snap.c	2009-09-09 18:13:59.000000000 -0400
@@ -678,6 +678,7 @@
 
 	ti->private = s;
 	ti->split_io = s->store->chunk_size;
+	ti->num_flush_requests = 1;
 
 	return 0;
 
@@ -1030,6 +1031,11 @@
 	chunk_t chunk;
 	struct dm_snap_pending_exception *pe = NULL;
 
+	if (unlikely(bio_empty_barrier(bio))) {
+		bio->bi_bdev = s->store->cow->bdev;
+		return DM_MAPIO_REMAPPED;
+	}
+
 	chunk = sector_to_chunk(s->store, bio->bi_sector);
 
 	/* Full snapshots are not usable */
@@ -1170,6 +1176,15 @@
 	return 0;
 }
 
+static int snapshot_iterate_devices(struct dm_target *ti,
+				    iterate_devices_callout_fn fn, void *data)
+{
+	struct dm_snapshot *snap = ti->private;
+
+	return fn(ti, snap->origin, 0, ti->len, data);
+}
+
+
 /*-----------------------------------------------------------------
  * Origin methods
  *---------------------------------------------------------------*/
@@ -1338,6 +1353,8 @@
 	}
 
 	ti->private = dev;
+	ti->num_flush_requests = 1;
+
 	return 0;
 }
 
@@ -1353,6 +1370,9 @@
 	struct dm_dev *dev = ti->private;
 	bio->bi_bdev = dev->bdev;
 
+	if (unlikely(bio_empty_barrier(bio)))
+		return DM_MAPIO_REMAPPED;
+
 	/* Only tell snapshots if this is a write */
 	return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
 }
@@ -1399,20 +1419,29 @@
 	return 0;
 }
 
+static int origin_iterate_devices(struct dm_target *ti,
+				  iterate_devices_callout_fn fn, void *data)
+{
+	struct dm_dev *dev = ti->private;
+
+	return fn(ti, dev, 0, ti->len, data);
+}
+
 static struct target_type origin_target = {
 	.name    = "snapshot-origin",
-	.version = {1, 6, 0},
+	.version = {1, 7, 0},
 	.module  = THIS_MODULE,
 	.ctr     = origin_ctr,
 	.dtr     = origin_dtr,
 	.map     = origin_map,
 	.resume  = origin_resume,
 	.status  = origin_status,
+	.iterate_devices = origin_iterate_devices,
 };
 
 static struct target_type snapshot_target = {
 	.name    = "snapshot",
-	.version = {1, 6, 0},
+	.version = {1, 7, 0},
 	.module  = THIS_MODULE,
 	.ctr     = snapshot_ctr,
 	.dtr     = snapshot_dtr,
@@ -1420,6 +1449,7 @@
 	.end_io  = snapshot_end_io,
 	.resume  = snapshot_resume,
 	.status  = snapshot_status,
+	.iterate_devices = snapshot_iterate_devices,
 };
 
 static int __init dm_snapshot_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-snap-persistent.c linux-libre-2.6.31-gnu/drivers/md/dm-snap-persistent.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-snap-persistent.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-snap-persistent.c	2009-09-09 18:13:59.000000000 -0400
@@ -106,6 +106,13 @@
 	void *zero_area;
 
 	/*
+	 * An area used for header. The header can be written
+	 * concurrently with metadata (when invalidating the snapshot),
+	 * so it needs a separate buffer.
+	 */
+	void *header_area;
+
+	/*
 	 * Used to keep track of which metadata area the data in
 	 * 'chunk' refers to.
 	 */
@@ -148,16 +155,27 @@
 	 */
 	ps->area = vmalloc(len);
 	if (!ps->area)
-		return r;
+		goto err_area;
 
 	ps->zero_area = vmalloc(len);
-	if (!ps->zero_area) {
-		vfree(ps->area);
-		return r;
-	}
+	if (!ps->zero_area)
+		goto err_zero_area;
 	memset(ps->zero_area, 0, len);
 
+	ps->header_area = vmalloc(len);
+	if (!ps->header_area)
+		goto err_header_area;
+
 	return 0;
+
+err_header_area:
+	vfree(ps->zero_area);
+
+err_zero_area:
+	vfree(ps->area);
+
+err_area:
+	return r;
 }
 
 static void free_area(struct pstore *ps)
@@ -169,6 +187,10 @@
 	if (ps->zero_area)
 		vfree(ps->zero_area);
 	ps->zero_area = NULL;
+
+	if (ps->header_area)
+		vfree(ps->header_area);
+	ps->header_area = NULL;
 }
 
 struct mdata_req {
@@ -188,7 +210,8 @@
 /*
  * Read or write a chunk aligned and sized block of data from a device.
  */
-static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
+static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw,
+		    int metadata)
 {
 	struct dm_io_region where = {
 		.bdev = ps->store->cow->bdev,
@@ -198,7 +221,7 @@
 	struct dm_io_request io_req = {
 		.bi_rw = rw,
 		.mem.type = DM_IO_VMA,
-		.mem.ptr.vma = ps->area,
+		.mem.ptr.vma = area,
 		.client = ps->io_client,
 		.notify.fn = NULL,
 	};
@@ -240,7 +263,7 @@
 
 	chunk = area_location(ps, ps->current_area);
 
-	r = chunk_io(ps, chunk, rw, 0);
+	r = chunk_io(ps, ps->area, chunk, rw, 0);
 	if (r)
 		return r;
 
@@ -254,20 +277,7 @@
 
 static int zero_disk_area(struct pstore *ps, chunk_t area)
 {
-	struct dm_io_region where = {
-		.bdev = ps->store->cow->bdev,
-		.sector = ps->store->chunk_size * area_location(ps, area),
-		.count = ps->store->chunk_size,
-	};
-	struct dm_io_request io_req = {
-		.bi_rw = WRITE,
-		.mem.type = DM_IO_VMA,
-		.mem.ptr.vma = ps->zero_area,
-		.client = ps->io_client,
-		.notify.fn = NULL,
-	};
-
-	return dm_io(&io_req, 1, &where, NULL);
+	return chunk_io(ps, ps->zero_area, area_location(ps, area), WRITE, 0);
 }
 
 static int read_header(struct pstore *ps, int *new_snapshot)
@@ -276,13 +286,14 @@
 	struct disk_header *dh;
 	chunk_t chunk_size;
 	int chunk_size_supplied = 1;
+	char *chunk_err;
 
 	/*
 	 * Use default chunk size (or hardsect_size, if larger) if none supplied
 	 */
 	if (!ps->store->chunk_size) {
 		ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
-		    bdev_hardsect_size(ps->store->cow->bdev) >> 9);
+		    bdev_logical_block_size(ps->store->cow->bdev) >> 9);
 		ps->store->chunk_mask = ps->store->chunk_size - 1;
 		ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1;
 		chunk_size_supplied = 0;
@@ -297,11 +308,11 @@
 	if (r)
 		return r;
 
-	r = chunk_io(ps, 0, READ, 1);
+	r = chunk_io(ps, ps->header_area, 0, READ, 1);
 	if (r)
 		goto bad;
 
-	dh = (struct disk_header *) ps->area;
+	dh = ps->header_area;
 
 	if (le32_to_cpu(dh->magic) == 0) {
 		*new_snapshot = 1;
@@ -319,20 +330,25 @@
 	ps->version = le32_to_cpu(dh->version);
 	chunk_size = le32_to_cpu(dh->chunk_size);
 
-	if (!chunk_size_supplied || ps->store->chunk_size == chunk_size)
+	if (ps->store->chunk_size == chunk_size)
 		return 0;
 
-	DMWARN("chunk size %llu in device metadata overrides "
-	       "table chunk size of %llu.",
-	       (unsigned long long)chunk_size,
-	       (unsigned long long)ps->store->chunk_size);
+	if (chunk_size_supplied)
+		DMWARN("chunk size %llu in device metadata overrides "
+		       "table chunk size of %llu.",
+		       (unsigned long long)chunk_size,
+		       (unsigned long long)ps->store->chunk_size);
 
 	/* We had a bogus chunk_size. Fix stuff up. */
 	free_area(ps);
 
-	ps->store->chunk_size = chunk_size;
-	ps->store->chunk_mask = chunk_size - 1;
-	ps->store->chunk_shift = ffs(chunk_size) - 1;
+	r = dm_exception_store_set_chunk_size(ps->store, chunk_size,
+					      &chunk_err);
+	if (r) {
+		DMERR("invalid on-disk chunk size %llu: %s.",
+		      (unsigned long long)chunk_size, chunk_err);
+		return r;
+	}
 
 	r = dm_io_client_resize(sectors_to_pages(ps->store->chunk_size),
 				ps->io_client);
@@ -351,15 +367,15 @@
 {
 	struct disk_header *dh;
 
-	memset(ps->area, 0, ps->store->chunk_size << SECTOR_SHIFT);
+	memset(ps->header_area, 0, ps->store->chunk_size << SECTOR_SHIFT);
 
-	dh = (struct disk_header *) ps->area;
+	dh = ps->header_area;
 	dh->magic = cpu_to_le32(SNAP_MAGIC);
 	dh->valid = cpu_to_le32(ps->valid);
 	dh->version = cpu_to_le32(ps->version);
 	dh->chunk_size = cpu_to_le32(ps->store->chunk_size);
 
-	return chunk_io(ps, 0, WRITE, 1);
+	return chunk_io(ps, ps->header_area, 0, WRITE, 1);
 }
 
 /*
@@ -636,7 +652,7 @@
 	/*
 	 * Commit exceptions to disk.
 	 */
-	if (ps->valid && area_io(ps, WRITE))
+	if (ps->valid && area_io(ps, WRITE_BARRIER))
 		ps->valid = 0;
 
 	/*
@@ -679,6 +695,8 @@
 	ps->valid = 1;
 	ps->version = SNAPSHOT_DISK_VERSION;
 	ps->area = NULL;
+	ps->zero_area = NULL;
+	ps->header_area = NULL;
 	ps->next_free = 2;	/* skipping the header and first area */
 	ps->current_committed = 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-stripe.c linux-libre-2.6.31-gnu/drivers/md/dm-stripe.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-stripe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-stripe.c	2009-09-09 18:13:59.000000000 -0400
@@ -167,6 +167,7 @@
 	sc->stripes = stripes;
 	sc->stripe_width = width;
 	ti->split_io = chunk_size;
+	ti->num_flush_requests = stripes;
 
 	sc->chunk_mask = ((sector_t) chunk_size) - 1;
 	for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++)
@@ -211,10 +212,18 @@
 		      union map_info *map_context)
 {
 	struct stripe_c *sc = (struct stripe_c *) ti->private;
+	sector_t offset, chunk;
+	uint32_t stripe;
 
-	sector_t offset = bio->bi_sector - ti->begin;
-	sector_t chunk = offset >> sc->chunk_shift;
-	uint32_t stripe = sector_div(chunk, sc->stripes);
+	if (unlikely(bio_empty_barrier(bio))) {
+		BUG_ON(map_context->flush_request >= sc->stripes);
+		bio->bi_bdev = sc->stripe[map_context->flush_request].dev->bdev;
+		return DM_MAPIO_REMAPPED;
+	}
+
+	offset = bio->bi_sector - ti->begin;
+	chunk = offset >> sc->chunk_shift;
+	stripe = sector_div(chunk, sc->stripes);
 
 	bio->bi_bdev = sc->stripe[stripe].dev->bdev;
 	bio->bi_sector = sc->stripe[stripe].physical_start +
@@ -304,15 +313,43 @@
 	return error;
 }
 
+static int stripe_iterate_devices(struct dm_target *ti,
+				  iterate_devices_callout_fn fn, void *data)
+{
+	struct stripe_c *sc = ti->private;
+	int ret = 0;
+	unsigned i = 0;
+
+	do {
+		ret = fn(ti, sc->stripe[i].dev,
+			 sc->stripe[i].physical_start,
+			 sc->stripe_width, data);
+	} while (!ret && ++i < sc->stripes);
+
+	return ret;
+}
+
+static void stripe_io_hints(struct dm_target *ti,
+			    struct queue_limits *limits)
+{
+	struct stripe_c *sc = ti->private;
+	unsigned chunk_size = (sc->chunk_mask + 1) << 9;
+
+	blk_limits_io_min(limits, chunk_size);
+	limits->io_opt = chunk_size * sc->stripes;
+}
+
 static struct target_type stripe_target = {
 	.name   = "striped",
-	.version = {1, 1, 0},
+	.version = {1, 3, 0},
 	.module = THIS_MODULE,
 	.ctr    = stripe_ctr,
 	.dtr    = stripe_dtr,
 	.map    = stripe_map,
 	.end_io = stripe_end_io,
 	.status = stripe_status,
+	.iterate_devices = stripe_iterate_devices,
+	.io_hints = stripe_io_hints,
 };
 
 int __init dm_stripe_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-sysfs.c linux-libre-2.6.31-gnu/drivers/md/dm-sysfs.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-sysfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-sysfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -57,12 +57,21 @@
 	return strlen(buf);
 }
 
+static ssize_t dm_attr_suspended_show(struct mapped_device *md, char *buf)
+{
+	sprintf(buf, "%d\n", dm_suspended(md));
+
+	return strlen(buf);
+}
+
 static DM_ATTR_RO(name);
 static DM_ATTR_RO(uuid);
+static DM_ATTR_RO(suspended);
 
 static struct attribute *dm_attrs[] = {
 	&dm_attr_name.attr,
 	&dm_attr_uuid.attr,
+	&dm_attr_suspended.attr,
 	NULL,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/md/dm-table.c linux-libre-2.6.31-gnu/drivers/md/dm-table.c
--- linux-libre-2.6.30-gnu/drivers/md/dm-table.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/dm-table.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,7 @@
 struct dm_table {
 	struct mapped_device *md;
 	atomic_t holders;
+	unsigned type;
 
 	/* btree table */
 	unsigned int depth;
@@ -62,15 +63,11 @@
 	/* a list of devices used by this table */
 	struct list_head devices;
 
-	/*
-	 * These are optimistic limits taken from all the
-	 * targets, some targets will need smaller limits.
-	 */
-	struct io_restrictions limits;
-
 	/* events get handed up using this callback */
 	void (*event_fn)(void *);
 	void *event_context;
+
+	struct dm_md_mempools *mempools;
 };
 
 /*
@@ -89,42 +86,6 @@
 }
 
 /*
- * Returns the minimum that is _not_ zero, unless both are zero.
- */
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
-
-/*
- * Combine two io_restrictions, always taking the lower value.
- */
-static void combine_restrictions_low(struct io_restrictions *lhs,
-				     struct io_restrictions *rhs)
-{
-	lhs->max_sectors =
-		min_not_zero(lhs->max_sectors, rhs->max_sectors);
-
-	lhs->max_phys_segments =
-		min_not_zero(lhs->max_phys_segments, rhs->max_phys_segments);
-
-	lhs->max_hw_segments =
-		min_not_zero(lhs->max_hw_segments, rhs->max_hw_segments);
-
-	lhs->hardsect_size = max(lhs->hardsect_size, rhs->hardsect_size);
-
-	lhs->max_segment_size =
-		min_not_zero(lhs->max_segment_size, rhs->max_segment_size);
-
-	lhs->max_hw_sectors =
-		min_not_zero(lhs->max_hw_sectors, rhs->max_hw_sectors);
-
-	lhs->seg_boundary_mask =
-		min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask);
-
-	lhs->bounce_pfn = min_not_zero(lhs->bounce_pfn, rhs->bounce_pfn);
-
-	lhs->no_cluster |= rhs->no_cluster;
-}
-
-/*
  * Calculate the index of the child node of the n'th node k'th key.
  */
 static inline unsigned int get_child(unsigned int n, unsigned int k)
@@ -266,6 +227,8 @@
 	list_for_each_safe(tmp, next, devices) {
 		struct dm_dev_internal *dd =
 		    list_entry(tmp, struct dm_dev_internal, list);
+		DMWARN("dm_table_destroy: dm_put_device call missing for %s",
+		       dd->dm_dev.name);
 		kfree(dd);
 	}
 }
@@ -295,12 +258,10 @@
 	vfree(t->highs);
 
 	/* free the device list */
-	if (t->devices.next != &t->devices) {
-		DMWARN("devices still present during destroy: "
-		       "dm_table_remove_device calls missing");
-
+	if (t->devices.next != &t->devices)
 		free_devices(&t->devices);
-	}
+
+	dm_free_md_mempools(t->mempools);
 
 	kfree(t);
 }
@@ -382,17 +343,54 @@
 }
 
 /*
- * If possible, this checks an area of a destination device is valid.
+ * If possible, this checks an area of a destination device is invalid.
  */
-static int check_device_area(struct dm_dev_internal *dd, sector_t start,
-			     sector_t len)
+static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
+				  sector_t start, sector_t len, void *data)
 {
-	sector_t dev_size = dd->dm_dev.bdev->bd_inode->i_size >> SECTOR_SHIFT;
+	struct queue_limits *limits = data;
+	struct block_device *bdev = dev->bdev;
+	sector_t dev_size =
+		i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	unsigned short logical_block_size_sectors =
+		limits->logical_block_size >> SECTOR_SHIFT;
+	char b[BDEVNAME_SIZE];
 
 	if (!dev_size)
+		return 0;
+
+	if ((start >= dev_size) || (start + len > dev_size)) {
+		DMWARN("%s: %s too small for target: "
+		       "start=%llu, len=%llu, dev_size=%llu",
+		       dm_device_name(ti->table->md), bdevname(bdev, b),
+		       (unsigned long long)start,
+		       (unsigned long long)len,
+		       (unsigned long long)dev_size);
 		return 1;
+	}
 
-	return ((start < dev_size) && (len <= (dev_size - start)));
+	if (logical_block_size_sectors <= 1)
+		return 0;
+
+	if (start & (logical_block_size_sectors - 1)) {
+		DMWARN("%s: start=%llu not aligned to h/w "
+		       "logical block size %u of %s",
+		       dm_device_name(ti->table->md),
+		       (unsigned long long)start,
+		       limits->logical_block_size, bdevname(bdev, b));
+		return 1;
+	}
+
+	if (len & (logical_block_size_sectors - 1)) {
+		DMWARN("%s: len=%llu not aligned to h/w "
+		       "logical block size %u of %s",
+		       dm_device_name(ti->table->md),
+		       (unsigned long long)len,
+		       limits->logical_block_size, bdevname(bdev, b));
+		return 1;
+	}
+
+	return 0;
 }
 
 /*
@@ -478,38 +476,39 @@
 	}
 	atomic_inc(&dd->count);
 
-	if (!check_device_area(dd, start, len)) {
-		DMWARN("device %s too small for target", path);
-		dm_put_device(ti, &dd->dm_dev);
-		return -EINVAL;
-	}
-
 	*result = &dd->dm_dev;
-
 	return 0;
 }
 
-void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev)
+/*
+ * Returns the minimum that is _not_ zero, unless both are zero.
+ */
+#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
+
+int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
+			 sector_t start, sector_t len, void *data)
 {
+	struct queue_limits *limits = data;
+	struct block_device *bdev = dev->bdev;
 	struct request_queue *q = bdev_get_queue(bdev);
-	struct io_restrictions *rs = &ti->limits;
 	char b[BDEVNAME_SIZE];
 
 	if (unlikely(!q)) {
 		DMWARN("%s: Cannot set limits for nonexistent device %s",
 		       dm_device_name(ti->table->md), bdevname(bdev, b));
-		return;
+		return 0;
 	}
 
-	/*
-	 * Combine the device limits low.
-	 *
-	 * FIXME: if we move an io_restriction struct
-	 *        into q this would just be a call to
-	 *        combine_restrictions_low()
-	 */
-	rs->max_sectors =
-		min_not_zero(rs->max_sectors, q->max_sectors);
+	if (blk_stack_limits(limits, &q->limits, start << 9) < 0)
+		DMWARN("%s: target device %s is misaligned: "
+		       "physical_block_size=%u, logical_block_size=%u, "
+		       "alignment_offset=%u, start=%llu",
+		       dm_device_name(ti->table->md), bdevname(bdev, b),
+		       q->limits.physical_block_size,
+		       q->limits.logical_block_size,
+		       q->limits.alignment_offset,
+		       (unsigned long long) start << 9);
+
 
 	/*
 	 * Check if merge fn is supported.
@@ -518,47 +517,21 @@
 	 */
 
 	if (q->merge_bvec_fn && !ti->type->merge)
-		rs->max_sectors =
-			min_not_zero(rs->max_sectors,
+		limits->max_sectors =
+			min_not_zero(limits->max_sectors,
 				     (unsigned int) (PAGE_SIZE >> 9));
-
-	rs->max_phys_segments =
-		min_not_zero(rs->max_phys_segments,
-			     q->max_phys_segments);
-
-	rs->max_hw_segments =
-		min_not_zero(rs->max_hw_segments, q->max_hw_segments);
-
-	rs->hardsect_size = max(rs->hardsect_size, q->hardsect_size);
-
-	rs->max_segment_size =
-		min_not_zero(rs->max_segment_size, q->max_segment_size);
-
-	rs->max_hw_sectors =
-		min_not_zero(rs->max_hw_sectors, q->max_hw_sectors);
-
-	rs->seg_boundary_mask =
-		min_not_zero(rs->seg_boundary_mask,
-			     q->seg_boundary_mask);
-
-	rs->bounce_pfn = min_not_zero(rs->bounce_pfn, q->bounce_pfn);
-
-	rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
 
 int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
 		  sector_t len, fmode_t mode, struct dm_dev **result)
 {
-	int r = __table_get_device(ti->table, ti, path,
-				   start, len, mode, result);
-
-	if (!r)
-		dm_set_device_limits(ti, (*result)->bdev);
-
-	return r;
+	return __table_get_device(ti->table, ti, path,
+				  start, len, mode, result);
 }
 
+
 /*
  * Decrement a devices use count and remove it if necessary.
  */
@@ -673,24 +646,78 @@
 	return 0;
 }
 
-static void check_for_valid_limits(struct io_restrictions *rs)
+/*
+ * Impose necessary and sufficient conditions on a devices's table such
+ * that any incoming bio which respects its logical_block_size can be
+ * processed successfully.  If it falls across the boundary between
+ * two or more targets, the size of each piece it gets split into must
+ * be compatible with the logical_block_size of the target processing it.
+ */
+static int validate_hardware_logical_block_alignment(struct dm_table *table,
+						 struct queue_limits *limits)
 {
-	if (!rs->max_sectors)
-		rs->max_sectors = SAFE_MAX_SECTORS;
-	if (!rs->max_hw_sectors)
-		rs->max_hw_sectors = SAFE_MAX_SECTORS;
-	if (!rs->max_phys_segments)
-		rs->max_phys_segments = MAX_PHYS_SEGMENTS;
-	if (!rs->max_hw_segments)
-		rs->max_hw_segments = MAX_HW_SEGMENTS;
-	if (!rs->hardsect_size)
-		rs->hardsect_size = 1 << SECTOR_SHIFT;
-	if (!rs->max_segment_size)
-		rs->max_segment_size = MAX_SEGMENT_SIZE;
-	if (!rs->seg_boundary_mask)
-		rs->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
-	if (!rs->bounce_pfn)
-		rs->bounce_pfn = -1;
+	/*
+	 * This function uses arithmetic modulo the logical_block_size
+	 * (in units of 512-byte sectors).
+	 */
+	unsigned short device_logical_block_size_sects =
+		limits->logical_block_size >> SECTOR_SHIFT;
+
+	/*
+	 * Offset of the start of the next table entry, mod logical_block_size.
+	 */
+	unsigned short next_target_start = 0;
+
+	/*
+	 * Given an aligned bio that extends beyond the end of a
+	 * target, how many sectors must the next target handle?
+	 */
+	unsigned short remaining = 0;
+
+	struct dm_target *uninitialized_var(ti);
+	struct queue_limits ti_limits;
+	unsigned i = 0;
+
+	/*
+	 * Check each entry in the table in turn.
+	 */
+	while (i < dm_table_get_num_targets(table)) {
+		ti = dm_table_get_target(table, i++);
+
+		blk_set_default_limits(&ti_limits);
+
+		/* combine all target devices' limits */
+		if (ti->type->iterate_devices)
+			ti->type->iterate_devices(ti, dm_set_device_limits,
+						  &ti_limits);
+
+		/*
+		 * If the remaining sectors fall entirely within this
+		 * table entry are they compatible with its logical_block_size?
+		 */
+		if (remaining < ti->len &&
+		    remaining & ((ti_limits.logical_block_size >>
+				  SECTOR_SHIFT) - 1))
+			break;	/* Error */
+
+		next_target_start =
+		    (unsigned short) ((next_target_start + ti->len) &
+				      (device_logical_block_size_sects - 1));
+		remaining = next_target_start ?
+		    device_logical_block_size_sects - next_target_start : 0;
+	}
+
+	if (remaining) {
+		DMWARN("%s: table line %u (start sect %llu len %llu) "
+		       "not aligned to h/w logical block size %u",
+		       dm_device_name(table->md), i,
+		       (unsigned long long) ti->begin,
+		       (unsigned long long) ti->len,
+		       limits->logical_block_size);
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 int dm_table_add_target(struct dm_table *t, const char *type,
@@ -745,9 +772,6 @@
 
 	t->highs[t->num_targets++] = tgt->begin + tgt->len - 1;
 
-	/* FIXME: the plan is to combine high here and then have
-	 * the merge fn apply the target level restrictions. */
-	combine_restrictions_low(&t->limits, &tgt->limits);
 	return 0;
 
  bad:
@@ -756,6 +780,99 @@
 	return r;
 }
 
+int dm_table_set_type(struct dm_table *t)
+{
+	unsigned i;
+	unsigned bio_based = 0, request_based = 0;
+	struct dm_target *tgt;
+	struct dm_dev_internal *dd;
+	struct list_head *devices;
+
+	for (i = 0; i < t->num_targets; i++) {
+		tgt = t->targets + i;
+		if (dm_target_request_based(tgt))
+			request_based = 1;
+		else
+			bio_based = 1;
+
+		if (bio_based && request_based) {
+			DMWARN("Inconsistent table: different target types"
+			       " can't be mixed up");
+			return -EINVAL;
+		}
+	}
+
+	if (bio_based) {
+		/* We must use this table as bio-based */
+		t->type = DM_TYPE_BIO_BASED;
+		return 0;
+	}
+
+	BUG_ON(!request_based); /* No targets in this table */
+
+	/* Non-request-stackable devices can't be used for request-based dm */
+	devices = dm_table_get_devices(t);
+	list_for_each_entry(dd, devices, list) {
+		if (!blk_queue_stackable(bdev_get_queue(dd->dm_dev.bdev))) {
+			DMWARN("table load rejected: including"
+			       " non-request-stackable devices");
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Request-based dm supports only tables that have a single target now.
+	 * To support multiple targets, request splitting support is needed,
+	 * and that needs lots of changes in the block-layer.
+	 * (e.g. request completion process for partial completion.)
+	 */
+	if (t->num_targets > 1) {
+		DMWARN("Request-based dm doesn't support multiple targets yet");
+		return -EINVAL;
+	}
+
+	t->type = DM_TYPE_REQUEST_BASED;
+
+	return 0;
+}
+
+unsigned dm_table_get_type(struct dm_table *t)
+{
+	return t->type;
+}
+
+bool dm_table_request_based(struct dm_table *t)
+{
+	return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
+}
+
+int dm_table_alloc_md_mempools(struct dm_table *t)
+{
+	unsigned type = dm_table_get_type(t);
+
+	if (unlikely(type == DM_TYPE_NONE)) {
+		DMWARN("no table type is set, can't allocate mempools");
+		return -EINVAL;
+	}
+
+	t->mempools = dm_alloc_md_mempools(type);
+	if (!t->mempools)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void dm_table_free_md_mempools(struct dm_table *t)
+{
+	dm_free_md_mempools(t->mempools);
+	t->mempools = NULL;
+}
+
+struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t)
+{
+	return t->mempools;
+}
+
 static int setup_indexes(struct dm_table *t)
 {
 	int i;
@@ -790,8 +907,6 @@
 	int r = 0;
 	unsigned int leaf_nodes;
 
-	check_for_valid_limits(&t->limits);
-
 	/* how many indexes will the btree have ? */
 	leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
 	t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
@@ -867,6 +982,61 @@
 }
 
 /*
+ * Establish the new table's queue_limits and validate them.
+ */
+int dm_calculate_queue_limits(struct dm_table *table,
+			      struct queue_limits *limits)
+{
+	struct dm_target *uninitialized_var(ti);
+	struct queue_limits ti_limits;
+	unsigned i = 0;
+
+	blk_set_default_limits(limits);
+
+	while (i < dm_table_get_num_targets(table)) {
+		blk_set_default_limits(&ti_limits);
+
+		ti = dm_table_get_target(table, i++);
+
+		if (!ti->type->iterate_devices)
+			goto combine_limits;
+
+		/*
+		 * Combine queue limits of all the devices this target uses.
+		 */
+		ti->type->iterate_devices(ti, dm_set_device_limits,
+					  &ti_limits);
+
+		/* Set I/O hints portion of queue limits */
+		if (ti->type->io_hints)
+			ti->type->io_hints(ti, &ti_limits);
+
+		/*
+		 * Check each device area is consistent with the target's
+		 * overall queue limits.
+		 */
+		if (ti->type->iterate_devices(ti, device_area_is_invalid,
+					      &ti_limits))
+			return -EINVAL;
+
+combine_limits:
+		/*
+		 * Merge this target's queue limits into the overall limits
+		 * for the table.
+		 */
+		if (blk_stack_limits(limits, &ti_limits, 0) < 0)
+			DMWARN("%s: target device "
+			       "(start sect %llu len %llu) "
+			       "is misaligned",
+			       dm_device_name(table->md),
+			       (unsigned long long) ti->begin,
+			       (unsigned long long) ti->len);
+	}
+
+	return validate_hardware_logical_block_alignment(table, limits);
+}
+
+/*
  * Set the integrity profile for this device if all devices used have
  * matching profiles.
  */
@@ -905,27 +1075,42 @@
 	return;
 }
 
-void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
+void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
+			       struct queue_limits *limits)
 {
 	/*
-	 * Make sure we obey the optimistic sub devices
-	 * restrictions.
+	 * Each target device in the table has a data area that should normally
+	 * be aligned such that the DM device's alignment_offset is 0.
+	 * FIXME: Propagate alignment_offsets up the stack and warn of
+	 *	  sub-optimal or inconsistent settings.
 	 */
-	blk_queue_max_sectors(q, t->limits.max_sectors);
-	q->max_phys_segments = t->limits.max_phys_segments;
-	q->max_hw_segments = t->limits.max_hw_segments;
-	q->hardsect_size = t->limits.hardsect_size;
-	q->max_segment_size = t->limits.max_segment_size;
-	q->max_hw_sectors = t->limits.max_hw_sectors;
-	q->seg_boundary_mask = t->limits.seg_boundary_mask;
-	q->bounce_pfn = t->limits.bounce_pfn;
+	limits->alignment_offset = 0;
+	limits->misaligned = 0;
 
-	if (t->limits.no_cluster)
+	/*
+	 * Copy table's limits to the DM device's request_queue
+	 */
+	q->limits = *limits;
+
+	if (limits->no_cluster)
 		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
 	else
 		queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
 
 	dm_table_set_integrity(t);
+
+	/*
+	 * QUEUE_FLAG_STACKABLE must be set after all queue settings are
+	 * visible to other CPUs because, once the flag is set, incoming bios
+	 * are processed by request-based dm, which refers to the queue
+	 * settings.
+	 * Until the flag set, bios are passed to bio-based dm and queued to
+	 * md->deferred where queue settings are not needed yet.
+	 * Those bios are passed to request-based dm at the resume time.
+	 */
+	smp_mb();
+	if (dm_table_request_based(t))
+		queue_flag_set_unlocked(QUEUE_FLAG_STACKABLE, q);
 }
 
 unsigned int dm_table_get_num_targets(struct dm_table *t)
@@ -1021,6 +1206,20 @@
 	return r;
 }
 
+int dm_table_any_busy_target(struct dm_table *t)
+{
+	unsigned i;
+	struct dm_target *ti;
+
+	for (i = 0; i < t->num_targets; i++) {
+		ti = t->targets + i;
+		if (ti->type->busy && ti->type->busy(ti))
+			return 1;
+	}
+
+	return 0;
+}
+
 void dm_table_unplug_all(struct dm_table *t)
 {
 	struct dm_dev_internal *dd;
diff -druN linux-libre-2.6.30-gnu/drivers/md/faulty.c linux-libre-2.6.31-gnu/drivers/md/faulty.c
--- linux-libre-2.6.30-gnu/drivers/md/faulty.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/faulty.c	2009-09-09 18:13:59.000000000 -0400
@@ -255,14 +255,14 @@
 }
 
 
-static int reconfig(mddev_t *mddev, int layout, int chunk_size)
+static int reshape(mddev_t *mddev)
 {
-	int mode = layout & ModeMask;
-	int count = layout >> ModeShift;
+	int mode = mddev->new_layout & ModeMask;
+	int count = mddev->new_layout >> ModeShift;
 	conf_t *conf = mddev->private;
 
-	if (chunk_size != -1)
-		return -EINVAL;
+	if (mddev->new_layout < 0)
+		return 0;
 
 	/* new layout */
 	if (mode == ClearFaults)
@@ -279,6 +279,7 @@
 		atomic_set(&conf->counters[mode], count);
 	} else
 		return -EINVAL;
+	mddev->new_layout = -1;
 	mddev->layout = -1; /* makes sure further changes come through */
 	return 0;
 }
@@ -298,8 +299,12 @@
 {
 	mdk_rdev_t *rdev;
 	int i;
+	conf_t *conf;
 
-	conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL);
+	if (md_check_no_bitmap(mddev))
+		return -EINVAL;
+
+	conf = kmalloc(sizeof(*conf), GFP_KERNEL);
 	if (!conf)
 		return -ENOMEM;
 
@@ -315,7 +320,7 @@
 	md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
 	mddev->private = conf;
 
-	reconfig(mddev, mddev->layout, -1);
+	reshape(mddev);
 
 	return 0;
 }
@@ -338,7 +343,7 @@
 	.run		= run,
 	.stop		= stop,
 	.status		= status,
-	.reconfig	= reconfig,
+	.check_reshape	= reshape,
 	.size		= faulty_size,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/md/Kconfig linux-libre-2.6.31-gnu/drivers/md/Kconfig
--- linux-libre-2.6.30-gnu/drivers/md/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -231,6 +231,17 @@
          Allow volume managers to mirror logical volumes, also
          needed for live data migration tools such as 'pvmove'.
 
+config DM_LOG_USERSPACE
+	tristate "Mirror userspace logging (EXPERIMENTAL)"
+	depends on DM_MIRROR && EXPERIMENTAL && NET
+	select CONNECTOR
+	---help---
+	  The userspace logging module provides a mechanism for
+	  relaying the dm-dirty-log API to userspace.  Log designs
+	  which are more suited to userspace implementation (e.g.
+	  shared storage logs) or experimental logs can be implemented
+	  by leveraging this framework.
+
 config DM_ZERO
 	tristate "Zero target"
 	depends on BLK_DEV_DM
@@ -249,6 +260,25 @@
 	---help---
 	  Allow volume managers to support multipath hardware.
 
+config DM_MULTIPATH_QL
+	tristate "I/O Path Selector based on the number of in-flight I/Os"
+	depends on DM_MULTIPATH
+	---help---
+	  This path selector is a dynamic load balancer which selects
+	  the path with the least number of in-flight I/Os.
+
+	  If unsure, say N.
+
+config DM_MULTIPATH_ST
+	tristate "I/O Path Selector based on the service time"
+	depends on DM_MULTIPATH
+	---help---
+	  This path selector is a dynamic load balancer which selects
+	  the path expected to complete the incoming I/O in the shortest
+	  time.
+
+	  If unsure, say N.
+
 config DM_DELAY
 	tristate "I/O delaying target (EXPERIMENTAL)"
 	depends on BLK_DEV_DM && EXPERIMENTAL
diff -druN linux-libre-2.6.30-gnu/drivers/md/linear.c linux-libre-2.6.31-gnu/drivers/md/linear.c
--- linux-libre-2.6.30-gnu/drivers/md/linear.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/linear.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,19 +27,27 @@
  */
 static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
 {
-	dev_info_t *hash;
-	linear_conf_t *conf = mddev_to_conf(mddev);
-	sector_t idx = sector >> conf->sector_shift;
+	int lo, mid, hi;
+	linear_conf_t *conf;
+
+	lo = 0;
+	hi = mddev->raid_disks - 1;
+	conf = rcu_dereference(mddev->private);
 
 	/*
-	 * sector_div(a,b) returns the remainer and sets a to a/b
+	 * Binary Search
 	 */
-	(void)sector_div(idx, conf->spacing);
-	hash = conf->hash_table[idx];
 
-	while (sector >= hash->num_sectors + hash->start_sector)
-		hash++;
-	return hash;
+	while (hi > lo) {
+
+		mid = (hi + lo) / 2;
+		if (sector < conf->disks[mid].end_sector)
+			hi = mid;
+		else
+			lo = mid + 1;
+	}
+
+	return conf->disks + lo;
 }
 
 /**
@@ -59,8 +67,10 @@
 	unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 
+	rcu_read_lock();
 	dev0 = which_dev(mddev, sector);
-	maxsectors = dev0->num_sectors - (sector - dev0->start_sector);
+	maxsectors = dev0->end_sector - sector;
+	rcu_read_unlock();
 
 	if (maxsectors < bio_sectors)
 		maxsectors = 0;
@@ -79,46 +89,57 @@
 static void linear_unplug(struct request_queue *q)
 {
 	mddev_t *mddev = q->queuedata;
-	linear_conf_t *conf = mddev_to_conf(mddev);
+	linear_conf_t *conf;
 	int i;
 
+	rcu_read_lock();
+	conf = rcu_dereference(mddev->private);
+
 	for (i=0; i < mddev->raid_disks; i++) {
 		struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev);
 		blk_unplug(r_queue);
 	}
+	rcu_read_unlock();
 }
 
 static int linear_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
-	linear_conf_t *conf = mddev_to_conf(mddev);
+	linear_conf_t *conf;
 	int i, ret = 0;
 
+	rcu_read_lock();
+	conf = rcu_dereference(mddev->private);
+
 	for (i = 0; i < mddev->raid_disks && !ret ; i++) {
 		struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
 		ret |= bdi_congested(&q->backing_dev_info, bits);
 	}
+
+	rcu_read_unlock();
 	return ret;
 }
 
 static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 {
-	linear_conf_t *conf = mddev_to_conf(mddev);
+	linear_conf_t *conf;
+	sector_t array_sectors;
 
+	rcu_read_lock();
+	conf = rcu_dereference(mddev->private);
 	WARN_ONCE(sectors || raid_disks,
 		  "%s does not support generic reshape\n", __func__);
+	array_sectors = conf->array_sectors;
+	rcu_read_unlock();
 
-	return conf->array_sectors;
+	return array_sectors;
 }
 
 static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
 {
 	linear_conf_t *conf;
-	dev_info_t **table;
 	mdk_rdev_t *rdev;
-	int i, nb_zone, cnt;
-	sector_t min_sectors;
-	sector_t curr_sector;
+	int i, cnt;
 
 	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
 			GFP_KERNEL);
@@ -131,6 +152,7 @@
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		int j = rdev->raid_disk;
 		dev_info_t *disk = conf->disks + j;
+		sector_t sectors;
 
 		if (j < 0 || j >= raid_disks || disk->rdev) {
 			printk("linear: disk numbering problem. Aborting!\n");
@@ -138,113 +160,40 @@
 		}
 
 		disk->rdev = rdev;
+		if (mddev->chunk_sectors) {
+			sectors = rdev->sectors;
+			sector_div(sectors, mddev->chunk_sectors);
+			rdev->sectors = sectors * mddev->chunk_sectors;
+		}
 
-		blk_queue_stack_limits(mddev->queue,
-				       rdev->bdev->bd_disk->queue);
+		disk_stack_limits(mddev->gendisk, rdev->bdev,
+				  rdev->data_offset << 9);
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, so limit ->max_sector to one PAGE, as
 		 * a one page request is never in violation.
 		 */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
 			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
-		disk->num_sectors = rdev->sectors;
 		conf->array_sectors += rdev->sectors;
-
 		cnt++;
+
 	}
 	if (cnt != raid_disks) {
 		printk("linear: not enough drives present. Aborting!\n");
 		goto out;
 	}
 
-	min_sectors = conf->array_sectors;
-	sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
-	if (min_sectors == 0)
-		min_sectors = 1;
-
-	/* min_sectors is the minimum spacing that will fit the hash
-	 * table in one PAGE.  This may be much smaller than needed.
-	 * We find the smallest non-terminal set of consecutive devices
-	 * that is larger than min_sectors and use the size of that as
-	 * the actual spacing
-	 */
-	conf->spacing = conf->array_sectors;
-	for (i=0; i < cnt-1 ; i++) {
-		sector_t tmp = 0;
-		int j;
-		for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
-			tmp += conf->disks[j].num_sectors;
-		if (tmp >= min_sectors && tmp < conf->spacing)
-			conf->spacing = tmp;
-	}
-
-	/* spacing may be too large for sector_div to work with,
-	 * so we might need to pre-shift
-	 */
-	conf->sector_shift = 0;
-	if (sizeof(sector_t) > sizeof(u32)) {
-		sector_t space = conf->spacing;
-		while (space > (sector_t)(~(u32)0)) {
-			space >>= 1;
-			conf->sector_shift++;
-		}
-	}
 	/*
-	 * This code was restructured to work around a gcc-2.95.3 internal
-	 * compiler error.  Alter it with care.
+	 * Here we calculate the device offsets.
 	 */
-	{
-		sector_t sz;
-		unsigned round;
-		unsigned long base;
-
-		sz = conf->array_sectors >> conf->sector_shift;
-		sz += 1; /* force round-up */
-		base = conf->spacing >> conf->sector_shift;
-		round = sector_div(sz, base);
-		nb_zone = sz + (round ? 1 : 0);
-	}
-	BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *));
-
-	conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone,
-					GFP_KERNEL);
-	if (!conf->hash_table)
-		goto out;
+	conf->disks[0].end_sector = conf->disks[0].rdev->sectors;
 
-	/*
-	 * Here we generate the linear hash table
-	 * First calculate the device offsets.
-	 */
-	conf->disks[0].start_sector = 0;
 	for (i = 1; i < raid_disks; i++)
-		conf->disks[i].start_sector =
-			conf->disks[i-1].start_sector +
-			conf->disks[i-1].num_sectors;
-
-	table = conf->hash_table;
-	i = 0;
-	for (curr_sector = 0;
-	     curr_sector < conf->array_sectors;
-	     curr_sector += conf->spacing) {
-
-		while (i < raid_disks-1 &&
-		       curr_sector >= conf->disks[i+1].start_sector)
-			i++;
-
-		*table ++ = conf->disks + i;
-	}
-
-	if (conf->sector_shift) {
-		conf->spacing >>= conf->sector_shift;
-		/* round spacing up so that when we divide by it,
-		 * we err on the side of "too-low", which is safest.
-		 */
-		conf->spacing++;
-	}
-
-	BUG_ON(table - conf->hash_table > nb_zone);
+		conf->disks[i].end_sector =
+			conf->disks[i-1].end_sector +
+			conf->disks[i].rdev->sectors;
 
 	return conf;
 
@@ -257,6 +206,8 @@
 {
 	linear_conf_t *conf;
 
+	if (md_check_no_bitmap(mddev))
+		return -EINVAL;
 	mddev->queue->queue_lock = &mddev->queue->__queue_lock;
 	conf = linear_conf(mddev, mddev->raid_disks);
 
@@ -269,9 +220,16 @@
 	mddev->queue->unplug_fn = linear_unplug;
 	mddev->queue->backing_dev_info.congested_fn = linear_congested;
 	mddev->queue->backing_dev_info.congested_data = mddev;
+	md_integrity_register(mddev);
 	return 0;
 }
 
+static void free_conf(struct rcu_head *head)
+{
+	linear_conf_t *conf = container_of(head, linear_conf_t, rcu);
+	kfree(conf);
+}
+
 static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	/* Adding a drive to a linear array allows the array to grow.
@@ -282,7 +240,7 @@
 	 * The current one is never freed until the array is stopped.
 	 * This avoids races.
 	 */
-	linear_conf_t *newconf;
+	linear_conf_t *newconf, *oldconf;
 
 	if (rdev->saved_raid_disk != mddev->raid_disks)
 		return -EINVAL;
@@ -294,25 +252,30 @@
 	if (!newconf)
 		return -ENOMEM;
 
-	newconf->prev = mddev_to_conf(mddev);
-	mddev->private = newconf;
+	oldconf = rcu_dereference(mddev->private);
 	mddev->raid_disks++;
+	rcu_assign_pointer(mddev->private, newconf);
 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
 	set_capacity(mddev->gendisk, mddev->array_sectors);
+	revalidate_disk(mddev->gendisk);
+	call_rcu(&oldconf->rcu, free_conf);
 	return 0;
 }
 
 static int linear_stop (mddev_t *mddev)
 {
-	linear_conf_t *conf = mddev_to_conf(mddev);
-  
+	linear_conf_t *conf = mddev->private;
+
+	/*
+	 * We do not require rcu protection here since
+	 * we hold reconfig_mutex for both linear_add and
+	 * linear_stop, so they cannot race.
+	 * We should make sure any old 'conf's are properly
+	 * freed though.
+	 */
+	rcu_barrier();
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
-	do {
-		linear_conf_t *t = conf->prev;
-		kfree(conf->hash_table);
-		kfree(conf);
-		conf = t;
-	} while (conf);
+	kfree(conf);
 
 	return 0;
 }
@@ -322,6 +285,7 @@
 	const int rw = bio_data_dir(bio);
 	mddev_t *mddev = q->queuedata;
 	dev_info_t *tmp_dev;
+	sector_t start_sector;
 	int cpu;
 
 	if (unlikely(bio_barrier(bio))) {
@@ -335,33 +299,36 @@
 		      bio_sectors(bio));
 	part_stat_unlock();
 
+	rcu_read_lock();
 	tmp_dev = which_dev(mddev, bio->bi_sector);
-    
-	if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors +
-					tmp_dev->start_sector)
-		     || (bio->bi_sector <
-			 tmp_dev->start_sector))) {
+	start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
+
+
+	if (unlikely(bio->bi_sector >= (tmp_dev->end_sector)
+		     || (bio->bi_sector < start_sector))) {
 		char b[BDEVNAME_SIZE];
 
 		printk("linear_make_request: Sector %llu out of bounds on "
 			"dev %s: %llu sectors, offset %llu\n",
 			(unsigned long long)bio->bi_sector,
 			bdevname(tmp_dev->rdev->bdev, b),
-			(unsigned long long)tmp_dev->num_sectors,
-			(unsigned long long)tmp_dev->start_sector);
+			(unsigned long long)tmp_dev->rdev->sectors,
+			(unsigned long long)start_sector);
+		rcu_read_unlock();
 		bio_io_error(bio);
 		return 0;
 	}
 	if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
-		     tmp_dev->start_sector + tmp_dev->num_sectors)) {
+		     tmp_dev->end_sector)) {
 		/* This bio crosses a device boundary, so we have to
 		 * split it.
 		 */
 		struct bio_pair *bp;
+		sector_t end_sector = tmp_dev->end_sector;
 
-		bp = bio_split(bio,
-			       tmp_dev->start_sector + tmp_dev->num_sectors
-			       - bio->bi_sector);
+		rcu_read_unlock();
+
+		bp = bio_split(bio, end_sector - bio->bi_sector);
 
 		if (linear_make_request(q, &bp->bio1))
 			generic_make_request(&bp->bio1);
@@ -372,8 +339,9 @@
 	}
 		    
 	bio->bi_bdev = tmp_dev->rdev->bdev;
-	bio->bi_sector = bio->bi_sector - tmp_dev->start_sector
+	bio->bi_sector = bio->bi_sector - start_sector
 		+ tmp_dev->rdev->data_offset;
+	rcu_read_unlock();
 
 	return 1;
 }
@@ -381,7 +349,7 @@
 static void linear_status (struct seq_file *seq, mddev_t *mddev)
 {
 
-	seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
+	seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/md/linear.h linux-libre-2.6.31-gnu/drivers/md/linear.h
--- linux-libre-2.6.30-gnu/drivers/md/linear.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/linear.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,27 +3,19 @@
 
 struct dev_info {
 	mdk_rdev_t	*rdev;
-	sector_t	num_sectors;
-	sector_t	start_sector;
+	sector_t	end_sector;
 };
 
 typedef struct dev_info dev_info_t;
 
 struct linear_private_data
 {
-	struct linear_private_data *prev;	/* earlier version */
-	dev_info_t		**hash_table;
-	sector_t		spacing;
 	sector_t		array_sectors;
-	int			sector_shift;	/* shift before dividing
-						 * by spacing
-						 */
 	dev_info_t		disks[0];
+	struct rcu_head		rcu;
 };
 
 
 typedef struct linear_private_data linear_conf_t;
 
-#define mddev_to_conf(mddev) ((linear_conf_t *) mddev->private)
-
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/md/Makefile linux-libre-2.6.31-gnu/drivers/md/Makefile
--- linux-libre-2.6.30-gnu/drivers/md/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,8 @@
 dm-snapshot-y	+= dm-snap.o dm-exception-store.o dm-snap-transient.o \
 		    dm-snap-persistent.o
 dm-mirror-y	+= dm-raid1.o
+dm-log-userspace-y \
+		+= dm-log-userspace-base.o dm-log-userspace-transfer.o
 md-mod-y	+= md.o bitmap.o
 raid456-y	+= raid5.o
 raid6_pq-y	+= raid6algos.o raid6recov.o raid6tables.o \
@@ -36,8 +38,11 @@
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
+obj-$(CONFIG_DM_MULTIPATH_QL)	+= dm-queue-length.o
+obj-$(CONFIG_DM_MULTIPATH_ST)	+= dm-service-time.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o dm-log.o dm-region-hash.o
+obj-$(CONFIG_DM_LOG_USERSPACE)	+= dm-log-userspace.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
 
 quiet_cmd_unroll = UNROLL  $@
diff -druN linux-libre-2.6.30-gnu/drivers/md/md.c linux-libre-2.6.31-gnu/drivers/md/md.c
--- linux-libre-2.6.30-gnu/drivers/md/md.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/md.c	2009-09-09 18:13:59.000000000 -0400
@@ -359,6 +359,7 @@
 	else
 		new->md_minor = MINOR(unit) >> MdpMinorShift;
 
+	mutex_init(&new->open_mutex);
 	mutex_init(&new->reconfig_mutex);
 	INIT_LIST_HEAD(&new->disks);
 	INIT_LIST_HEAD(&new->all_mddevs);
@@ -440,15 +441,6 @@
 	return MD_NEW_SIZE_SECTORS(num_sectors);
 }
 
-static sector_t calc_num_sectors(mdk_rdev_t *rdev, unsigned chunk_size)
-{
-	sector_t num_sectors = rdev->sb_start;
-
-	if (chunk_size)
-		num_sectors &= ~((sector_t)chunk_size/512 - 1);
-	return num_sectors;
-}
-
 static int alloc_disk_sb(mdk_rdev_t * rdev)
 {
 	if (rdev->sb_page)
@@ -745,6 +737,24 @@
 };
 
 /*
+ * Check that the given mddev has no bitmap.
+ *
+ * This function is called from the run method of all personalities that do not
+ * support bitmaps. It prints an error message and returns non-zero if mddev
+ * has a bitmap. Otherwise, it returns 0.
+ *
+ */
+int md_check_no_bitmap(mddev_t *mddev)
+{
+	if (!mddev->bitmap_file && !mddev->bitmap_offset)
+		return 0;
+	printk(KERN_ERR "%s: bitmaps are not supported for %s\n",
+		mdname(mddev), mddev->pers->name);
+	return 1;
+}
+EXPORT_SYMBOL(md_check_no_bitmap);
+
+/*
  * load_super for 0.90.0 
  */
 static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
@@ -797,17 +807,6 @@
 	rdev->data_offset = 0;
 	rdev->sb_size = MD_SB_BYTES;
 
-	if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
-		if (sb->level != 1 && sb->level != 4
-		    && sb->level != 5 && sb->level != 6
-		    && sb->level != 10) {
-			/* FIXME use a better test */
-			printk(KERN_WARNING
-			       "md: bitmaps not supported for this level.\n");
-			goto abort;
-		}
-	}
-
 	if (sb->level == LEVEL_MULTIPATH)
 		rdev->desc_nr = -1;
 	else
@@ -836,7 +835,7 @@
 		else 
 			ret = 0;
 	}
-	rdev->sectors = calc_num_sectors(rdev, sb->chunk_size);
+	rdev->sectors = rdev->sb_start;
 
 	if (rdev->sectors < sb->size * 2 && sb->level > 1)
 		/* "this cannot possibly happen" ... */
@@ -866,7 +865,7 @@
 		mddev->minor_version = sb->minor_version;
 		mddev->patch_version = sb->patch_version;
 		mddev->external = 0;
-		mddev->chunk_size = sb->chunk_size;
+		mddev->chunk_sectors = sb->chunk_size >> 9;
 		mddev->ctime = sb->ctime;
 		mddev->utime = sb->utime;
 		mddev->level = sb->level;
@@ -883,13 +882,13 @@
 			mddev->delta_disks = sb->delta_disks;
 			mddev->new_level = sb->new_level;
 			mddev->new_layout = sb->new_layout;
-			mddev->new_chunk = sb->new_chunk;
+			mddev->new_chunk_sectors = sb->new_chunk >> 9;
 		} else {
 			mddev->reshape_position = MaxSector;
 			mddev->delta_disks = 0;
 			mddev->new_level = mddev->level;
 			mddev->new_layout = mddev->layout;
-			mddev->new_chunk = mddev->chunk_size;
+			mddev->new_chunk_sectors = mddev->chunk_sectors;
 		}
 
 		if (sb->state & (1<<MD_SB_CLEAN))
@@ -1004,7 +1003,7 @@
 		sb->new_level = mddev->new_level;
 		sb->delta_disks = mddev->delta_disks;
 		sb->new_layout = mddev->new_layout;
-		sb->new_chunk = mddev->new_chunk;
+		sb->new_chunk = mddev->new_chunk_sectors << 9;
 	}
 	mddev->minor_version = sb->minor_version;
 	if (mddev->in_sync)
@@ -1018,7 +1017,7 @@
 		sb->recovery_cp = 0;
 
 	sb->layout = mddev->layout;
-	sb->chunk_size = mddev->chunk_size;
+	sb->chunk_size = mddev->chunk_sectors << 9;
 
 	if (mddev->bitmap && mddev->bitmap_file == NULL)
 		sb->state |= (1<<MD_SB_BITMAP_PRESENT);
@@ -1185,24 +1184,13 @@
 		       bdevname(rdev->bdev,b));
 		return -EINVAL;
 	}
-	if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) {
-		if (sb->level != cpu_to_le32(1) &&
-		    sb->level != cpu_to_le32(4) &&
-		    sb->level != cpu_to_le32(5) &&
-		    sb->level != cpu_to_le32(6) &&
-		    sb->level != cpu_to_le32(10)) {
-			printk(KERN_WARNING
-			       "md: bitmaps not supported for this level.\n");
-			return -EINVAL;
-		}
-	}
 
 	rdev->preferred_minor = 0xffff;
 	rdev->data_offset = le64_to_cpu(sb->data_offset);
 	atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
 
 	rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
-	bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
+	bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1;
 	if (rdev->sb_size & bmask)
 		rdev->sb_size = (rdev->sb_size | bmask) + 1;
 
@@ -1248,9 +1236,6 @@
 	if (rdev->sectors < le64_to_cpu(sb->data_size))
 		return -EINVAL;
 	rdev->sectors = le64_to_cpu(sb->data_size);
-	if (le32_to_cpu(sb->chunksize))
-		rdev->sectors &= ~((sector_t)le32_to_cpu(sb->chunksize) - 1);
-
 	if (le64_to_cpu(sb->size) > rdev->sectors)
 		return -EINVAL;
 	return ret;
@@ -1271,7 +1256,7 @@
 		mddev->major_version = 1;
 		mddev->patch_version = 0;
 		mddev->external = 0;
-		mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
+		mddev->chunk_sectors = le32_to_cpu(sb->chunksize);
 		mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
 		mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
 		mddev->level = le32_to_cpu(sb->level);
@@ -1297,13 +1282,13 @@
 			mddev->delta_disks = le32_to_cpu(sb->delta_disks);
 			mddev->new_level = le32_to_cpu(sb->new_level);
 			mddev->new_layout = le32_to_cpu(sb->new_layout);
-			mddev->new_chunk = le32_to_cpu(sb->new_chunk)<<9;
+			mddev->new_chunk_sectors = le32_to_cpu(sb->new_chunk);
 		} else {
 			mddev->reshape_position = MaxSector;
 			mddev->delta_disks = 0;
 			mddev->new_level = mddev->level;
 			mddev->new_layout = mddev->layout;
-			mddev->new_chunk = mddev->chunk_size;
+			mddev->new_chunk_sectors = mddev->chunk_sectors;
 		}
 
 	} else if (mddev->pers == NULL) {
@@ -1324,7 +1309,12 @@
 	}
 	if (mddev->level != LEVEL_MULTIPATH) {
 		int role;
-		role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
+		if (rdev->desc_nr < 0 ||
+		    rdev->desc_nr >= le32_to_cpu(sb->max_dev)) {
+			role = 0xffff;
+			rdev->desc_nr = -1;
+		} else
+			role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
 		switch(role) {
 		case 0xffff: /* spare */
 			break;
@@ -1375,7 +1365,7 @@
 
 	sb->raid_disks = cpu_to_le32(mddev->raid_disks);
 	sb->size = cpu_to_le64(mddev->dev_sectors);
-	sb->chunksize = cpu_to_le32(mddev->chunk_size >> 9);
+	sb->chunksize = cpu_to_le32(mddev->chunk_sectors);
 	sb->level = cpu_to_le32(mddev->level);
 	sb->layout = cpu_to_le32(mddev->layout);
 
@@ -1402,7 +1392,7 @@
 		sb->new_layout = cpu_to_le32(mddev->new_layout);
 		sb->delta_disks = cpu_to_le32(mddev->delta_disks);
 		sb->new_level = cpu_to_le32(mddev->new_level);
-		sb->new_chunk = cpu_to_le32(mddev->new_chunk>>9);
+		sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors);
 	}
 
 	max_dev = 0;
@@ -1410,8 +1400,14 @@
 		if (rdev2->desc_nr+1 > max_dev)
 			max_dev = rdev2->desc_nr+1;
 
-	if (max_dev > le32_to_cpu(sb->max_dev))
+	if (max_dev > le32_to_cpu(sb->max_dev)) {
+		int bmask;
 		sb->max_dev = cpu_to_le32(max_dev);
+		rdev->sb_size = max_dev * 2 + 256;
+		bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1;
+		if (rdev->sb_size & bmask)
+			rdev->sb_size = (rdev->sb_size | bmask) + 1;
+	}
 	for (i=0; i<max_dev;i++)
 		sb->dev_roles[i] = cpu_to_le16(0xfffe);
 	
@@ -1503,37 +1499,76 @@
 
 static LIST_HEAD(pending_raid_disks);
 
-static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev)
+/*
+ * Try to register data integrity profile for an mddev
+ *
+ * This is called when an array is started and after a disk has been kicked
+ * from the array. It only succeeds if all working and active component devices
+ * are integrity capable with matching profiles.
+ */
+int md_integrity_register(mddev_t *mddev)
+{
+	mdk_rdev_t *rdev, *reference = NULL;
+
+	if (list_empty(&mddev->disks))
+		return 0; /* nothing to do */
+	if (blk_get_integrity(mddev->gendisk))
+		return 0; /* already registered */
+	list_for_each_entry(rdev, &mddev->disks, same_set) {
+		/* skip spares and non-functional disks */
+		if (test_bit(Faulty, &rdev->flags))
+			continue;
+		if (rdev->raid_disk < 0)
+			continue;
+		/*
+		 * If at least one rdev is not integrity capable, we can not
+		 * enable data integrity for the md device.
+		 */
+		if (!bdev_get_integrity(rdev->bdev))
+			return -EINVAL;
+		if (!reference) {
+			/* Use the first rdev as the reference */
+			reference = rdev;
+			continue;
+		}
+		/* does this rdev's profile match the reference profile? */
+		if (blk_integrity_compare(reference->bdev->bd_disk,
+				rdev->bdev->bd_disk) < 0)
+			return -EINVAL;
+	}
+	/*
+	 * All component devices are integrity capable and have matching
+	 * profiles, register the common profile for the md device.
+	 */
+	if (blk_integrity_register(mddev->gendisk,
+			bdev_get_integrity(reference->bdev)) != 0) {
+		printk(KERN_ERR "md: failed to register integrity for %s\n",
+			mdname(mddev));
+		return -EINVAL;
+	}
+	printk(KERN_NOTICE "md: data integrity on %s enabled\n",
+		mdname(mddev));
+	return 0;
+}
+EXPORT_SYMBOL(md_integrity_register);
+
+/* Disable data integrity if non-capable/non-matching disk is being added */
+void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
 {
-	struct mdk_personality *pers = mddev->pers;
-	struct gendisk *disk = mddev->gendisk;
 	struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
-	struct blk_integrity *bi_mddev = blk_get_integrity(disk);
+	struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
 
-	/* Data integrity passthrough not supported on RAID 4, 5 and 6 */
-	if (pers && pers->level >= 4 && pers->level <= 6)
+	if (!bi_mddev) /* nothing to do */
 		return;
-
-	/* If rdev is integrity capable, register profile for mddev */
-	if (!bi_mddev && bi_rdev) {
-		if (blk_integrity_register(disk, bi_rdev))
-			printk(KERN_ERR "%s: %s Could not register integrity!\n",
-			       __func__, disk->disk_name);
-		else
-			printk(KERN_NOTICE "Enabling data integrity on %s\n",
-			       disk->disk_name);
+	if (rdev->raid_disk < 0) /* skip spares */
 		return;
-	}
-
-	/* Check that mddev and rdev have matching profiles */
-	if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) {
-		printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__,
-		       disk->disk_name, rdev->bdev->bd_disk->disk_name);
-		printk(KERN_NOTICE "Disabling data integrity on %s\n",
-		       disk->disk_name);
-		blk_integrity_unregister(disk);
-	}
+	if (bi_rdev && blk_integrity_compare(mddev->gendisk,
+					     rdev->bdev->bd_disk) >= 0)
+		return;
+	printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
+	blk_integrity_unregister(mddev->gendisk);
 }
+EXPORT_SYMBOL(md_integrity_add_rdev);
 
 static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 {
@@ -1607,7 +1642,6 @@
 	/* May as well allow recovery to be retried once */
 	mddev->recovery_disabled = 0;
 
-	md_integrity_check(rdev, mddev);
 	return 0;
 
  fail:
@@ -1772,9 +1806,10 @@
 	__u8 *uuid;
 
 	uuid = sb->set_uuid;
-	printk(KERN_INFO "md:  SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x"
-			":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n"
-	       KERN_INFO "md:    Name: \"%s\" CT:%llu\n",
+	printk(KERN_INFO
+	       "md:  SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x"
+	       ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n"
+	       "md:    Name: \"%s\" CT:%llu\n",
 		le32_to_cpu(sb->major_version),
 		le32_to_cpu(sb->feature_map),
 		uuid[0], uuid[1], uuid[2], uuid[3],
@@ -1786,12 +1821,13 @@
 		       & MD_SUPERBLOCK_1_TIME_SEC_MASK);
 
 	uuid = sb->device_uuid;
-	printk(KERN_INFO "md:       L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu"
+	printk(KERN_INFO
+	       "md:       L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu"
 			" RO:%llu\n"
-	       KERN_INFO "md:     Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x"
-			":%02x%02x%02x%02x%02x%02x\n"
-	       KERN_INFO "md:       (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n"
-	       KERN_INFO "md:         (MaxDev:%u) \n",
+	       "md:     Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+	                ":%02x%02x%02x%02x%02x%02x\n"
+	       "md:       (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n"
+	       "md:         (MaxDev:%u) \n",
 		le32_to_cpu(sb->level),
 		(unsigned long long)le64_to_cpu(sb->size),
 		le32_to_cpu(sb->raid_disks),
@@ -1897,6 +1933,7 @@
 	int sync_req;
 	int nospares = 0;
 
+	mddev->utime = get_seconds();
 	if (mddev->external)
 		return;
 repeat:
@@ -1926,7 +1963,6 @@
 		nospares = 0;
 
 	sync_req = mddev->in_sync;
-	mddev->utime = get_seconds();
 
 	/* If this is just a dirty<->clean transition, and the array is clean
 	 * and 'events' is odd, we can roll back to the previous clean state */
@@ -1939,17 +1975,14 @@
 		/* otherwise we have to go forward and ... */
 		mddev->events ++;
 		if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
-			/* .. if the array isn't clean, insist on an odd 'events' */
-			if ((mddev->events&1)==0) {
-				mddev->events++;
+			/* .. if the array isn't clean, an 'even' event must also go
+			 * to spares. */
+			if ((mddev->events&1)==0)
 				nospares = 0;
-			}
 		} else {
-			/* otherwise insist on an even 'events' (for clean states) */
-			if ((mddev->events&1)) {
-				mddev->events++;
+			/* otherwise an 'odd' event must go to spares */
+			if ((mddev->events&1))
 				nospares = 0;
-			}
 		}
 	}
 
@@ -2597,15 +2630,6 @@
 			clear_bit(In_sync, &rdev->flags);
 		}
 	}
-
-
-
-	if (mddev->recovery_cp != MaxSector &&
-	    mddev->level >= 1)
-		printk(KERN_ERR "md: %s: raid array is not clean"
-		       " -- starting background reconstruction\n",
-		       mdname(mddev));
-
 }
 
 static void md_safemode_timeout(unsigned long data);
@@ -2680,6 +2704,7 @@
 	ssize_t rv = len;
 	struct mdk_personality *pers;
 	void *priv;
+	mdk_rdev_t *rdev;
 
 	if (mddev->pers == NULL) {
 		if (len == 0)
@@ -2746,7 +2771,7 @@
 	if (IS_ERR(priv)) {
 		mddev->new_level = mddev->level;
 		mddev->new_layout = mddev->layout;
-		mddev->new_chunk = mddev->chunk_size;
+		mddev->new_chunk_sectors = mddev->chunk_sectors;
 		mddev->raid_disks -= mddev->delta_disks;
 		mddev->delta_disks = 0;
 		module_put(pers->owner);
@@ -2759,12 +2784,18 @@
 	mddev_suspend(mddev);
 	mddev->pers->stop(mddev);
 	module_put(mddev->pers->owner);
+	/* Invalidate devices that are now superfluous */
+	list_for_each_entry(rdev, &mddev->disks, same_set)
+		if (rdev->raid_disk >= mddev->raid_disks) {
+			rdev->raid_disk = -1;
+			clear_bit(In_sync, &rdev->flags);
+		}
 	mddev->pers = pers;
 	mddev->private = priv;
 	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
 	mddev->level = mddev->new_level;
 	mddev->layout = mddev->new_layout;
-	mddev->chunk_size = mddev->new_chunk;
+	mddev->chunk_sectors = mddev->new_chunk_sectors;
 	mddev->delta_disks = 0;
 	pers->run(mddev);
 	mddev_resume(mddev);
@@ -2800,11 +2831,14 @@
 
 	if (mddev->pers) {
 		int err;
-		if (mddev->pers->reconfig == NULL)
+		if (mddev->pers->check_reshape == NULL)
 			return -EBUSY;
-		err = mddev->pers->reconfig(mddev, n, -1);
-		if (err)
+		mddev->new_layout = n;
+		err = mddev->pers->check_reshape(mddev);
+		if (err) {
+			mddev->new_layout = mddev->layout;
 			return err;
+		}
 	} else {
 		mddev->new_layout = n;
 		if (mddev->reshape_position == MaxSector)
@@ -2857,10 +2891,11 @@
 chunk_size_show(mddev_t *mddev, char *page)
 {
 	if (mddev->reshape_position != MaxSector &&
-	    mddev->chunk_size != mddev->new_chunk)
-		return sprintf(page, "%d (%d)\n", mddev->new_chunk,
-			       mddev->chunk_size);
-	return sprintf(page, "%d\n", mddev->chunk_size);
+	    mddev->chunk_sectors != mddev->new_chunk_sectors)
+		return sprintf(page, "%d (%d)\n",
+			       mddev->new_chunk_sectors << 9,
+			       mddev->chunk_sectors << 9);
+	return sprintf(page, "%d\n", mddev->chunk_sectors << 9);
 }
 
 static ssize_t
@@ -2874,15 +2909,18 @@
 
 	if (mddev->pers) {
 		int err;
-		if (mddev->pers->reconfig == NULL)
+		if (mddev->pers->check_reshape == NULL)
 			return -EBUSY;
-		err = mddev->pers->reconfig(mddev, -1, n);
-		if (err)
+		mddev->new_chunk_sectors = n >> 9;
+		err = mddev->pers->check_reshape(mddev);
+		if (err) {
+			mddev->new_chunk_sectors = mddev->chunk_sectors;
 			return err;
+		}
 	} else {
-		mddev->new_chunk = n;
+		mddev->new_chunk_sectors = n >> 9;
 		if (mddev->reshape_position == MaxSector)
-			mddev->chunk_size = n;
+			mddev->chunk_sectors = n >> 9;
 	}
 	return len;
 }
@@ -3527,8 +3565,9 @@
 		return -EBUSY;
 
 	/* Must be a multiple of chunk_size */
-	if (mddev->chunk_size) {
-		if (min & (sector_t)((mddev->chunk_size>>9)-1))
+	if (mddev->chunk_sectors) {
+		sector_t temp = min;
+		if (sector_div(temp, mddev->chunk_sectors))
 			return -EINVAL;
 	}
 	mddev->resync_min = min;
@@ -3560,12 +3599,14 @@
 		if (max < mddev->resync_min)
 			return -EINVAL;
 		if (max < mddev->resync_max &&
+		    mddev->ro == 0 &&
 		    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
 			return -EBUSY;
 
 		/* Must be a multiple of chunk_size */
-		if (mddev->chunk_size) {
-			if (max & (sector_t)((mddev->chunk_size>>9)-1))
+		if (mddev->chunk_sectors) {
+			sector_t temp = max;
+			if (sector_div(temp, mddev->chunk_sectors))
 				return -EINVAL;
 		}
 		mddev->resync_max = max;
@@ -3589,7 +3630,8 @@
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
 
-	if (mddev->pers->quiesce == NULL)
+	if (mddev->pers == NULL || 
+	    mddev->pers->quiesce == NULL)
 		return -EINVAL;
 	if (buf == e || (*e && *e != '\n'))
 		return -EINVAL;
@@ -3617,7 +3659,8 @@
 	char *e;
 	unsigned long long new = simple_strtoull(buf, &e, 10);
 
-	if (mddev->pers->quiesce == NULL)
+	if (mddev->pers == NULL ||
+	    mddev->pers->quiesce == NULL)
 		return -EINVAL;
 	if (buf == e || (*e && *e != '\n'))
 		return -EINVAL;
@@ -3656,7 +3699,7 @@
 	mddev->delta_disks = 0;
 	mddev->new_level = mddev->level;
 	mddev->new_layout = mddev->layout;
-	mddev->new_chunk = mddev->chunk_size;
+	mddev->new_chunk_sectors = mddev->chunk_sectors;
 	return len;
 }
 
@@ -3697,17 +3740,8 @@
 
 	mddev->array_sectors = sectors;
 	set_capacity(mddev->gendisk, mddev->array_sectors);
-	if (mddev->pers) {
-		struct block_device *bdev = bdget_disk(mddev->gendisk, 0);
-
-		if (bdev) {
-			mutex_lock(&bdev->bd_inode->i_mutex);
-			i_size_write(bdev->bd_inode,
-				     (loff_t)mddev->array_sectors << 9);
-			mutex_unlock(&bdev->bd_inode->i_mutex);
-			bdput(bdev);
-		}
-	}
+	if (mddev->pers)
+		revalidate_disk(mddev->gendisk);
 
 	return len;
 }
@@ -3860,11 +3894,9 @@
 	flush_scheduled_work();
 
 	mutex_lock(&disks_mutex);
-	if (mddev->gendisk) {
-		mutex_unlock(&disks_mutex);
-		mddev_put(mddev);
-		return -EEXIST;
-	}
+	error = -EEXIST;
+	if (mddev->gendisk)
+		goto abort;
 
 	if (name) {
 		/* Need to ensure that 'name' is not a duplicate.
@@ -3876,17 +3908,15 @@
 			if (mddev2->gendisk &&
 			    strcmp(mddev2->gendisk->disk_name, name) == 0) {
 				spin_unlock(&all_mddevs_lock);
-				return -EEXIST;
+				goto abort;
 			}
 		spin_unlock(&all_mddevs_lock);
 	}
 
+	error = -ENOMEM;
 	mddev->queue = blk_alloc_queue(GFP_KERNEL);
-	if (!mddev->queue) {
-		mutex_unlock(&disks_mutex);
-		mddev_put(mddev);
-		return -ENOMEM;
-	}
+	if (!mddev->queue)
+		goto abort;
 	mddev->queue->queuedata = mddev;
 
 	/* Can be unlocked because the queue is new: no concurrency */
@@ -3896,11 +3926,9 @@
 
 	disk = alloc_disk(1 << shift);
 	if (!disk) {
-		mutex_unlock(&disks_mutex);
 		blk_cleanup_queue(mddev->queue);
 		mddev->queue = NULL;
-		mddev_put(mddev);
-		return -ENOMEM;
+		goto abort;
 	}
 	disk->major = MAJOR(mddev->unit);
 	disk->first_minor = unit << shift;
@@ -3922,16 +3950,22 @@
 	mddev->gendisk = disk;
 	error = kobject_init_and_add(&mddev->kobj, &md_ktype,
 				     &disk_to_dev(disk)->kobj, "%s", "md");
-	mutex_unlock(&disks_mutex);
-	if (error)
+	if (error) {
+		/* This isn't possible, but as kobject_init_and_add is marked
+		 * __must_check, we must do something with the result
+		 */
 		printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
 		       disk->disk_name);
-	else {
+		error = 0;
+	}
+ abort:
+	mutex_unlock(&disks_mutex);
+	if (!error) {
 		kobject_uevent(&mddev->kobj, KOBJ_ADD);
 		mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state");
 	}
 	mddev_put(mddev);
-	return 0;
+	return error;
 }
 
 static struct kobject *md_probe(dev_t dev, int *part, void *data)
@@ -3976,11 +4010,9 @@
 static int do_md_run(mddev_t * mddev)
 {
 	int err;
-	int chunk_size;
 	mdk_rdev_t *rdev;
 	struct gendisk *disk;
 	struct mdk_personality *pers;
-	char b[BDEVNAME_SIZE];
 
 	if (list_empty(&mddev->disks))
 		/* cannot run an array with no devices.. */
@@ -3998,38 +4030,6 @@
 		analyze_sbs(mddev);
 	}
 
-	chunk_size = mddev->chunk_size;
-
-	if (chunk_size) {
-		if (chunk_size > MAX_CHUNK_SIZE) {
-			printk(KERN_ERR "too big chunk_size: %d > %d\n",
-				chunk_size, MAX_CHUNK_SIZE);
-			return -EINVAL;
-		}
-		/*
-		 * chunk-size has to be a power of 2
-		 */
-		if ( (1 << ffz(~chunk_size)) != chunk_size) {
-			printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size);
-			return -EINVAL;
-		}
-
-		/* devices must have minimum size of one chunk */
-		list_for_each_entry(rdev, &mddev->disks, same_set) {
-			if (test_bit(Faulty, &rdev->flags))
-				continue;
-			if (rdev->sectors < chunk_size / 512) {
-				printk(KERN_WARNING
-					"md: Dev %s smaller than chunk_size:"
-					" %llu < %d\n",
-					bdevname(rdev->bdev,b),
-					(unsigned long long)rdev->sectors,
-					chunk_size / 512);
-				return -EINVAL;
-			}
-		}
-	}
-
 	if (mddev->level != LEVEL_NONE)
 		request_module("md-level-%d", mddev->level);
 	else if (mddev->clevel[0])
@@ -4094,10 +4094,6 @@
 	}
 	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
 
-	if (pers->level >= 4 && pers->level <= 6)
-		/* Cannot support integrity (yet) */
-		blk_integrity_unregister(mddev->gendisk);
-
 	if (mddev->reshape_position != MaxSector &&
 	    pers->start_reshape == NULL) {
 		/* This personality cannot handle reshaping... */
@@ -4235,6 +4231,7 @@
 	md_wakeup_thread(mddev->thread);
 	md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 
+	revalidate_disk(mddev->gendisk);
 	mddev->changed = 1;
 	md_new_event(mddev);
 	sysfs_notify_dirent(mddev->sysfs_state);
@@ -4306,12 +4303,11 @@
 	struct gendisk *disk = mddev->gendisk;
 	mdk_rdev_t *rdev;
 
+	mutex_lock(&mddev->open_mutex);
 	if (atomic_read(&mddev->openers) > is_open) {
 		printk("md: %s still in use.\n",mdname(mddev));
-		return -EBUSY;
-	}
-
-	if (mddev->pers) {
+		err = -EBUSY;
+	} else if (mddev->pers) {
 
 		if (mddev->sync_thread) {
 			set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -4368,8 +4364,12 @@
 		if (mode == 1)
 			set_disk_ro(disk, 1);
 		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+		err = 0;
 	}
-
+out:
+	mutex_unlock(&mddev->open_mutex);
+	if (err)
+		return err;
 	/*
 	 * Free resources if final stop
 	 */
@@ -4405,7 +4405,7 @@
 		mddev->flags = 0;
 		mddev->ro = 0;
 		mddev->metadata_type[0] = 0;
-		mddev->chunk_size = 0;
+		mddev->chunk_sectors = 0;
 		mddev->ctime = mddev->utime = 0;
 		mddev->layout = 0;
 		mddev->max_disks = 0;
@@ -4413,7 +4413,7 @@
 		mddev->delta_disks = 0;
 		mddev->new_level = LEVEL_NONE;
 		mddev->new_layout = 0;
-		mddev->new_chunk = 0;
+		mddev->new_chunk_sectors = 0;
 		mddev->curr_resync = 0;
 		mddev->resync_mismatches = 0;
 		mddev->suspend_lo = mddev->suspend_hi = 0;
@@ -4435,7 +4435,6 @@
 	blk_integrity_unregister(disk);
 	md_new_event(mddev);
 	sysfs_notify_dirent(mddev->sysfs_state);
-out:
 	return err;
 }
 
@@ -4618,7 +4617,7 @@
 	info.spare_disks   = spare;
 
 	info.layout        = mddev->layout;
-	info.chunk_size    = mddev->chunk_size;
+	info.chunk_size    = mddev->chunk_sectors << 9;
 
 	if (copy_to_user(arg, &info, sizeof(info)))
 		return -EFAULT;
@@ -4843,7 +4842,7 @@
 			rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
 		} else 
 			rdev->sb_start = calc_dev_sboffset(rdev->bdev);
-		rdev->sectors = calc_num_sectors(rdev, mddev->chunk_size);
+		rdev->sectors = rdev->sb_start;
 
 		err = bind_rdev_to_array(rdev, mddev);
 		if (err) {
@@ -4913,7 +4912,7 @@
 	else
 		rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
 
-	rdev->sectors = calc_num_sectors(rdev, mddev->chunk_size);
+	rdev->sectors = rdev->sb_start;
 
 	if (test_bit(Faulty, &rdev->flags)) {
 		printk(KERN_WARNING 
@@ -5062,7 +5061,7 @@
 	mddev->external	     = 0;
 
 	mddev->layout        = info->layout;
-	mddev->chunk_size    = info->chunk_size;
+	mddev->chunk_sectors = info->chunk_size >> 9;
 
 	mddev->max_disks     = MD_SB_DISKS;
 
@@ -5081,7 +5080,7 @@
 	get_random_bytes(mddev->uuid, 16);
 
 	mddev->new_level = mddev->level;
-	mddev->new_chunk = mddev->chunk_size;
+	mddev->new_chunk_sectors = mddev->chunk_sectors;
 	mddev->new_layout = mddev->layout;
 	mddev->delta_disks = 0;
 
@@ -5133,18 +5132,8 @@
 			return -ENOSPC;
 	}
 	rv = mddev->pers->resize(mddev, num_sectors);
-	if (!rv) {
-		struct block_device *bdev;
-
-		bdev = bdget_disk(mddev->gendisk, 0);
-		if (bdev) {
-			mutex_lock(&bdev->bd_inode->i_mutex);
-			i_size_write(bdev->bd_inode,
-				     (loff_t)mddev->array_sectors << 9);
-			mutex_unlock(&bdev->bd_inode->i_mutex);
-			bdput(bdev);
-		}
-	}
+	if (!rv)
+		revalidate_disk(mddev->gendisk);
 	return rv;
 }
 
@@ -5191,7 +5180,7 @@
 	    mddev->level         != info->level         ||
 /*	    mddev->layout        != info->layout        || */
 	    !mddev->persistent	 != info->not_persistent||
-	    mddev->chunk_size    != info->chunk_size    ||
+	    mddev->chunk_sectors != info->chunk_size >> 9 ||
 	    /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
 	    ((state^info->state) & 0xfffffe00)
 		)
@@ -5215,10 +5204,15 @@
 		 * we don't need to do anything at the md level, the
 		 * personality will take care of it all.
 		 */
-		if (mddev->pers->reconfig == NULL)
+		if (mddev->pers->check_reshape == NULL)
 			return -EINVAL;
-		else
-			return mddev->pers->reconfig(mddev, info->layout, -1);
+		else {
+			mddev->new_layout = info->layout;
+			rv = mddev->pers->check_reshape(mddev);
+			if (rv)
+				mddev->new_layout = mddev->layout;
+			return rv;
+		}
 	}
 	if (info->size >= 0 && mddev->dev_sectors / 2 != info->size)
 		rv = update_size(mddev, (sector_t)info->size * 2);
@@ -5525,12 +5519,12 @@
 	}
 	BUG_ON(mddev != bdev->bd_disk->private_data);
 
-	if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
+	if ((err = mutex_lock_interruptible(&mddev->open_mutex)))
 		goto out;
 
 	err = 0;
 	atomic_inc(&mddev->openers);
-	mddev_unlock(mddev);
+	mutex_unlock(&mddev->open_mutex);
 
 	check_disk_change(bdev);
  out:
@@ -6379,10 +6373,16 @@
 			sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 		}
 
-		if (j >= mddev->resync_max)
-			wait_event(mddev->recovery_wait,
-				   mddev->resync_max > j
-				   || kthread_should_stop());
+		while (j >= mddev->resync_max && !kthread_should_stop()) {
+			/* As this condition is controlled by user-space,
+			 * we can block indefinitely, so use '_interruptible'
+			 * to avoid triggering warnings.
+			 */
+			flush_signals(current); /* just in case */
+			wait_event_interruptible(mddev->recovery_wait,
+						 mddev->resync_max > j
+						 || kthread_should_stop());
+		}
 
 		if (kthread_should_stop())
 			goto interrupted;
@@ -6717,7 +6717,8 @@
 		 */
 
 		if (mddev->reshape_position != MaxSector) {
-			if (mddev->pers->check_reshape(mddev) != 0)
+			if (mddev->pers->check_reshape == NULL ||
+			    mddev->pers->check_reshape(mddev) != 0)
 				/* Cannot proceed */
 				goto unlock;
 			set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
diff -druN linux-libre-2.6.30-gnu/drivers/md/md.h linux-libre-2.6.31-gnu/drivers/md/md.h
--- linux-libre-2.6.30-gnu/drivers/md/md.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/md.h	2009-09-09 18:13:59.000000000 -0400
@@ -30,13 +30,6 @@
 typedef struct mdk_rdev_s mdk_rdev_t;
 
 /*
- * options passed in raidrun:
- */
-
-/* Currently this must fit in an 'int' */
-#define MAX_CHUNK_SIZE (1<<30)
-
-/*
  * MD's 'extended' device
  */
 struct mdk_rdev_s
@@ -145,7 +138,7 @@
 	int 				external;	/* metadata is
 							 * managed externally */
 	char				metadata_type[17]; /* externally set*/
-	int				chunk_size;
+	int				chunk_sectors;
 	time_t				ctime, utime;
 	int				level, layout;
 	char				clevel[16];
@@ -166,7 +159,8 @@
 	 * If reshape_position is MaxSector, then no reshape is happening (yet).
 	 */
 	sector_t			reshape_position;
-	int				delta_disks, new_level, new_layout, new_chunk;
+	int				delta_disks, new_level, new_layout;
+	int				new_chunk_sectors;
 
 	struct mdk_thread_s		*thread;	/* management thread */
 	struct mdk_thread_s		*sync_thread;	/* doing resync or reconstruct */
@@ -229,6 +223,16 @@
 							    * so we don't loop trying */
 
 	int				in_sync;	/* know to not need resync */
+	/* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so
+	 * that we are never stopping an array while it is open.
+	 * 'reconfig_mutex' protects all other reconfiguration.
+	 * These locks are separate due to conflicting interactions
+	 * with bdev->bd_mutex.
+	 * Lock ordering is:
+	 *  reconfig_mutex -> bd_mutex : e.g. do_md_run -> revalidate_disk
+	 *  bd_mutex -> open_mutex:  e.g. __blkdev_get -> md_open
+	 */
+	struct mutex			open_mutex;
 	struct mutex			reconfig_mutex;
 	atomic_t			active;		/* general refcount */
 	atomic_t			openers;	/* number of active opens */
@@ -325,7 +329,6 @@
 	int (*check_reshape) (mddev_t *mddev);
 	int (*start_reshape) (mddev_t *mddev);
 	void (*finish_reshape) (mddev_t *mddev);
-	int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
 	/* quiesce moves between quiescence states
 	 * 0 - fully active
 	 * 1 - no new requests allowed
@@ -437,5 +440,8 @@
 extern int md_allow_write(mddev_t *mddev);
 extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
+extern int md_check_no_bitmap(mddev_t *mddev);
+extern int md_integrity_register(mddev_t *mddev);
+void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 
 #endif /* _MD_MD_H */
diff -druN linux-libre-2.6.30-gnu/drivers/md/multipath.c linux-libre-2.6.31-gnu/drivers/md/multipath.c
--- linux-libre-2.6.30-gnu/drivers/md/multipath.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/multipath.c	2009-09-09 18:13:59.000000000 -0400
@@ -58,7 +58,7 @@
 {
 	unsigned long flags;
 	mddev_t *mddev = mp_bh->mddev;
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&mp_bh->retry_list, &conf->retry_list);
@@ -75,7 +75,7 @@
 static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
 {
 	struct bio *bio = mp_bh->master_bio;
-	multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev);
+	multipath_conf_t *conf = mp_bh->mddev->private;
 
 	bio_endio(bio, err);
 	mempool_free(mp_bh, conf->pool);
@@ -85,7 +85,7 @@
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private);
-	multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev);
+	multipath_conf_t *conf = mp_bh->mddev->private;
 	mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev;
 
 	if (uptodate)
@@ -107,7 +107,7 @@
 
 static void unplug_slaves(mddev_t *mddev)
 {
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 	int i;
 
 	rcu_read_lock();
@@ -138,7 +138,7 @@
 static int multipath_make_request (struct request_queue *q, struct bio * bio)
 {
 	mddev_t *mddev = q->queuedata;
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
 	const int rw = bio_data_dir(bio);
@@ -180,7 +180,7 @@
 
 static void multipath_status (struct seq_file *seq, mddev_t *mddev)
 {
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 	int i;
 	
 	seq_printf (seq, " [%d/%d] [", conf->raid_disks,
@@ -195,7 +195,7 @@
 static int multipath_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 	int i, ret = 0;
 
 	rcu_read_lock();
@@ -220,7 +220,7 @@
  */
 static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
 {
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 
 	if (conf->working_disks <= 1) {
 		/*
@@ -294,7 +294,8 @@
 	for (path = first; path <= last; path++)
 		if ((p=conf->multipaths+path)->rdev == NULL) {
 			q = rdev->bdev->bd_disk->queue;
-			blk_queue_stack_limits(mddev->queue, q);
+			disk_stack_limits(mddev->gendisk, rdev->bdev,
+					  rdev->data_offset << 9);
 
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, so limit ->max_sector to one PAGE, as
@@ -303,7 +304,7 @@
 		 * merge_bvec_fn will be involved in multipath.)
 		 */
 			if (q->merge_bvec_fn &&
-			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+			    queue_max_sectors(q) > (PAGE_SIZE>>9))
 				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 			conf->working_disks++;
@@ -312,6 +313,7 @@
 			set_bit(In_sync, &rdev->flags);
 			rcu_assign_pointer(p->rdev, rdev);
 			err = 0;
+			md_integrity_add_rdev(rdev, mddev);
 			break;
 		}
 
@@ -344,7 +346,9 @@
 			/* lost the race, try later */
 			err = -EBUSY;
 			p->rdev = rdev;
+			goto abort;
 		}
+		md_integrity_register(mddev);
 	}
 abort:
 
@@ -367,7 +371,7 @@
 	struct multipath_bh *mp_bh;
 	struct bio *bio;
 	unsigned long flags;
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 
 	md_check_recovery(mddev);
@@ -421,6 +425,9 @@
 	struct multipath_info *disk;
 	mdk_rdev_t *rdev;
 
+	if (md_check_no_bitmap(mddev))
+		return -EINVAL;
+
 	if (mddev->level != LEVEL_MULTIPATH) {
 		printk("multipath: %s: raid level not set to multipath IO (%d)\n",
 		       mdname(mddev), mddev->level);
@@ -460,14 +467,14 @@
 
 		disk = conf->multipaths + disk_idx;
 		disk->rdev = rdev;
+		disk_stack_limits(mddev->gendisk, rdev->bdev,
+				  rdev->data_offset << 9);
 
-		blk_queue_stack_limits(mddev->queue,
-				       rdev->bdev->bd_disk->queue);
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, not that we ever expect a device with
 		 * a merge_bvec_fn to be involved in multipath */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
 			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		if (!test_bit(Faulty, &rdev->flags))
@@ -515,7 +522,7 @@
 	mddev->queue->unplug_fn = multipath_unplug;
 	mddev->queue->backing_dev_info.congested_fn = multipath_congested;
 	mddev->queue->backing_dev_info.congested_data = mddev;
-
+	md_integrity_register(mddev);
 	return 0;
 
 out_free_conf:
@@ -531,7 +538,7 @@
 
 static int multipath_stop (mddev_t *mddev)
 {
-	multipath_conf_t *conf = mddev_to_conf(mddev);
+	multipath_conf_t *conf = mddev->private;
 
 	md_unregister_thread(mddev->thread);
 	mddev->thread = NULL;
diff -druN linux-libre-2.6.30-gnu/drivers/md/multipath.h linux-libre-2.6.31-gnu/drivers/md/multipath.h
--- linux-libre-2.6.30-gnu/drivers/md/multipath.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/multipath.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,12 +19,6 @@
 typedef struct multipath_private_data multipath_conf_t;
 
 /*
- * this is the only point in the RAID code where we violate
- * C type safety. mddev->private is an 'opaque' pointer.
- */
-#define mddev_to_conf(mddev) ((multipath_conf_t *) mddev->private)
-
-/*
  * this is our 'private' 'collective' MULTIPATH buffer head.
  * it contains information about what kind of IO operations were started
  * for this MULTIPATH operation, and about their status:
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid0.c linux-libre-2.6.31-gnu/drivers/md/raid0.c
--- linux-libre-2.6.30-gnu/drivers/md/raid0.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid0.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,8 +26,8 @@
 static void raid0_unplug(struct request_queue *q)
 {
 	mddev_t *mddev = q->queuedata;
-	raid0_conf_t *conf = mddev_to_conf(mddev);
-	mdk_rdev_t **devlist = conf->strip_zone[0].dev;
+	raid0_conf_t *conf = mddev->private;
+	mdk_rdev_t **devlist = conf->devlist;
 	int i;
 
 	for (i=0; i<mddev->raid_disks; i++) {
@@ -40,8 +40,8 @@
 static int raid0_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
-	raid0_conf_t *conf = mddev_to_conf(mddev);
-	mdk_rdev_t **devlist = conf->strip_zone[0].dev;
+	raid0_conf_t *conf = mddev->private;
+	mdk_rdev_t **devlist = conf->devlist;
 	int i, ret = 0;
 
 	for (i = 0; i < mddev->raid_disks && !ret ; i++) {
@@ -52,27 +52,60 @@
 	return ret;
 }
 
+/*
+ * inform the user of the raid configuration
+*/
+static void dump_zones(mddev_t *mddev)
+{
+	int j, k, h;
+	sector_t zone_size = 0;
+	sector_t zone_start = 0;
+	char b[BDEVNAME_SIZE];
+	raid0_conf_t *conf = mddev->private;
+	printk(KERN_INFO "******* %s configuration *********\n",
+		mdname(mddev));
+	h = 0;
+	for (j = 0; j < conf->nr_strip_zones; j++) {
+		printk(KERN_INFO "zone%d=[", j);
+		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
+			printk("%s/",
+			bdevname(conf->devlist[j*mddev->raid_disks
+						+ k]->bdev, b));
+		printk("]\n");
+
+		zone_size  = conf->strip_zone[j].zone_end - zone_start;
+		printk(KERN_INFO "        zone offset=%llukb "
+				"device offset=%llukb size=%llukb\n",
+			(unsigned long long)zone_start>>1,
+			(unsigned long long)conf->strip_zone[j].dev_start>>1,
+			(unsigned long long)zone_size>>1);
+		zone_start = conf->strip_zone[j].zone_end;
+	}
+	printk(KERN_INFO "**********************************\n\n");
+}
 
-static int create_strip_zones (mddev_t *mddev)
+static int create_strip_zones(mddev_t *mddev)
 {
-	int i, c, j;
-	sector_t current_start, curr_zone_start;
-	sector_t min_spacing;
-	raid0_conf_t *conf = mddev_to_conf(mddev);
-	mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev;
+	int i, c, j, err;
+	sector_t curr_zone_end, sectors;
+	mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev, **dev;
 	struct strip_zone *zone;
 	int cnt;
 	char b[BDEVNAME_SIZE];
- 
-	/*
-	 * The number of 'same size groups'
-	 */
-	conf->nr_strip_zones = 0;
- 
+	raid0_conf_t *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+
+	if (!conf)
+		return -ENOMEM;
 	list_for_each_entry(rdev1, &mddev->disks, same_set) {
 		printk(KERN_INFO "raid0: looking at %s\n",
 			bdevname(rdev1->bdev,b));
 		c = 0;
+
+		/* round size to chunk_size */
+		sectors = rdev1->sectors;
+		sector_div(sectors, mddev->chunk_sectors);
+		rdev1->sectors = sectors * mddev->chunk_sectors;
+
 		list_for_each_entry(rdev2, &mddev->disks, same_set) {
 			printk(KERN_INFO "raid0:   comparing %s(%llu)",
 			       bdevname(rdev1->bdev,b),
@@ -103,16 +136,16 @@
 		}
 	}
 	printk(KERN_INFO "raid0: FINAL %d zones\n", conf->nr_strip_zones);
-
+	err = -ENOMEM;
 	conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
 				conf->nr_strip_zones, GFP_KERNEL);
 	if (!conf->strip_zone)
-		return 1;
+		goto abort;
 	conf->devlist = kzalloc(sizeof(mdk_rdev_t*)*
 				conf->nr_strip_zones*mddev->raid_disks,
 				GFP_KERNEL);
 	if (!conf->devlist)
-		return 1;
+		goto abort;
 
 	/* The first zone must contain all devices, so here we check that
 	 * there is a proper alignment of slots to devices and find them all
@@ -120,7 +153,8 @@
 	zone = &conf->strip_zone[0];
 	cnt = 0;
 	smallest = NULL;
-	zone->dev = conf->devlist;
+	dev = conf->devlist;
+	err = -EINVAL;
 	list_for_each_entry(rdev1, &mddev->disks, same_set) {
 		int j = rdev1->raid_disk;
 
@@ -129,22 +163,22 @@
 				"aborting!\n", j);
 			goto abort;
 		}
-		if (zone->dev[j]) {
+		if (dev[j]) {
 			printk(KERN_ERR "raid0: multiple devices for %d - "
 				"aborting!\n", j);
 			goto abort;
 		}
-		zone->dev[j] = rdev1;
+		dev[j] = rdev1;
 
-		blk_queue_stack_limits(mddev->queue,
-				       rdev1->bdev->bd_disk->queue);
+		disk_stack_limits(mddev->gendisk, rdev1->bdev,
+				  rdev1->data_offset << 9);
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, so limit ->max_sector to one PAGE, as
 		 * a one page request is never in violation.
 		 */
 
 		if (rdev1->bdev->bd_disk->queue->merge_bvec_fn &&
-		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
 			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		if (!smallest || (rdev1->sectors < smallest->sectors))
@@ -157,34 +191,32 @@
 		goto abort;
 	}
 	zone->nb_dev = cnt;
-	zone->sectors = smallest->sectors * cnt;
-	zone->zone_start = 0;
+	zone->zone_end = smallest->sectors * cnt;
 
-	current_start = smallest->sectors;
-	curr_zone_start = zone->sectors;
+	curr_zone_end = zone->zone_end;
 
 	/* now do the other zones */
 	for (i = 1; i < conf->nr_strip_zones; i++)
 	{
 		zone = conf->strip_zone + i;
-		zone->dev = conf->strip_zone[i-1].dev + mddev->raid_disks;
+		dev = conf->devlist + i * mddev->raid_disks;
 
 		printk(KERN_INFO "raid0: zone %d\n", i);
-		zone->dev_start = current_start;
+		zone->dev_start = smallest->sectors;
 		smallest = NULL;
 		c = 0;
 
 		for (j=0; j<cnt; j++) {
 			char b[BDEVNAME_SIZE];
-			rdev = conf->strip_zone[0].dev[j];
+			rdev = conf->devlist[j];
 			printk(KERN_INFO "raid0: checking %s ...",
 				bdevname(rdev->bdev, b));
-			if (rdev->sectors <= current_start) {
+			if (rdev->sectors <= zone->dev_start) {
 				printk(KERN_INFO " nope.\n");
 				continue;
 			}
 			printk(KERN_INFO " contained as device %d\n", c);
-			zone->dev[c] = rdev;
+			dev[c] = rdev;
 			c++;
 			if (!smallest || rdev->sectors < smallest->sectors) {
 				smallest = rdev;
@@ -194,47 +226,44 @@
 		}
 
 		zone->nb_dev = c;
-		zone->sectors = (smallest->sectors - current_start) * c;
+		sectors = (smallest->sectors - zone->dev_start) * c;
 		printk(KERN_INFO "raid0: zone->nb_dev: %d, sectors: %llu\n",
-			zone->nb_dev, (unsigned long long)zone->sectors);
+			zone->nb_dev, (unsigned long long)sectors);
 
-		zone->zone_start = curr_zone_start;
-		curr_zone_start += zone->sectors;
+		curr_zone_end += sectors;
+		zone->zone_end = curr_zone_end;
 
-		current_start = smallest->sectors;
 		printk(KERN_INFO "raid0: current zone start: %llu\n",
-			(unsigned long long)current_start);
+			(unsigned long long)smallest->sectors);
 	}
+	mddev->queue->unplug_fn = raid0_unplug;
+	mddev->queue->backing_dev_info.congested_fn = raid0_congested;
+	mddev->queue->backing_dev_info.congested_data = mddev;
 
-	/* Now find appropriate hash spacing.
-	 * We want a number which causes most hash entries to cover
-	 * at most two strips, but the hash table must be at most
-	 * 1 PAGE.  We choose the smallest strip, or contiguous collection
-	 * of strips, that has big enough size.  We never consider the last
-	 * strip though as it's size has no bearing on the efficacy of the hash
-	 * table.
+	/*
+	 * now since we have the hard sector sizes, we can make sure
+	 * chunk size is a multiple of that sector size
 	 */
-	conf->spacing = curr_zone_start;
-	min_spacing = curr_zone_start;
-	sector_div(min_spacing, PAGE_SIZE/sizeof(struct strip_zone*));
-	for (i=0; i < conf->nr_strip_zones-1; i++) {
-		sector_t s = 0;
-		for (j = i; j < conf->nr_strip_zones - 1 &&
-				s < min_spacing; j++)
-			s += conf->strip_zone[j].sectors;
-		if (s >= min_spacing && s < conf->spacing)
-			conf->spacing = s;
+	if ((mddev->chunk_sectors << 9) % queue_logical_block_size(mddev->queue)) {
+		printk(KERN_ERR "%s chunk_size of %d not valid\n",
+		       mdname(mddev),
+		       mddev->chunk_sectors << 9);
+		goto abort;
 	}
 
-	mddev->queue->unplug_fn = raid0_unplug;
-
-	mddev->queue->backing_dev_info.congested_fn = raid0_congested;
-	mddev->queue->backing_dev_info.congested_data = mddev;
+	blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
+	blk_queue_io_opt(mddev->queue,
+			 (mddev->chunk_sectors << 9) * mddev->raid_disks);
 
 	printk(KERN_INFO "raid0: done.\n");
+	mddev->private = conf;
 	return 0;
- abort:
-	return 1;
+abort:
+	kfree(conf->strip_zone);
+	kfree(conf->devlist);
+	kfree(conf);
+	mddev->private = NULL;
+	return err;
 }
 
 /**
@@ -252,10 +281,15 @@
 	mddev_t *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
-	unsigned int chunk_sectors = mddev->chunk_size >> 9;
+	unsigned int chunk_sectors = mddev->chunk_sectors;
 	unsigned int bio_sectors = bvm->bi_size >> 9;
 
-	max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
+	if (is_power_of_2(chunk_sectors))
+		max =  (chunk_sectors - ((sector & (chunk_sectors-1))
+						+ bio_sectors)) << 9;
+	else
+		max =  (chunk_sectors - (sector_div(sector, chunk_sectors)
+						+ bio_sectors)) << 9;
 	if (max < 0) max = 0; /* bio_add cannot handle a negative return */
 	if (max <= biovec->bv_len && bio_sectors == 0)
 		return biovec->bv_len;
@@ -277,84 +311,28 @@
 	return array_sectors;
 }
 
-static int raid0_run (mddev_t *mddev)
+static int raid0_run(mddev_t *mddev)
 {
-	unsigned  cur=0, i=0, nb_zone;
-	s64 sectors;
-	raid0_conf_t *conf;
+	int ret;
 
-	if (mddev->chunk_size == 0) {
-		printk(KERN_ERR "md/raid0: non-zero chunk size required.\n");
+	if (mddev->chunk_sectors == 0) {
+		printk(KERN_ERR "md/raid0: chunk size must be set.\n");
 		return -EINVAL;
 	}
-	printk(KERN_INFO "%s: setting max_sectors to %d, segment boundary to %d\n",
-	       mdname(mddev),
-	       mddev->chunk_size >> 9,
-	       (mddev->chunk_size>>1)-1);
-	blk_queue_max_sectors(mddev->queue, mddev->chunk_size >> 9);
-	blk_queue_segment_boundary(mddev->queue, (mddev->chunk_size>>1) - 1);
+	if (md_check_no_bitmap(mddev))
+		return -EINVAL;
+	blk_queue_max_sectors(mddev->queue, mddev->chunk_sectors);
 	mddev->queue->queue_lock = &mddev->queue->__queue_lock;
 
-	conf = kmalloc(sizeof (raid0_conf_t), GFP_KERNEL);
-	if (!conf)
-		goto out;
-	mddev->private = (void *)conf;
- 
-	conf->strip_zone = NULL;
-	conf->devlist = NULL;
-	if (create_strip_zones (mddev)) 
-		goto out_free_conf;
+	ret = create_strip_zones(mddev);
+	if (ret < 0)
+		return ret;
 
 	/* calculate array device size */
 	md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
 
 	printk(KERN_INFO "raid0 : md_size is %llu sectors.\n",
 		(unsigned long long)mddev->array_sectors);
-	printk(KERN_INFO "raid0 : conf->spacing is %llu sectors.\n",
-		(unsigned long long)conf->spacing);
-	{
-		sector_t s = raid0_size(mddev, 0, 0);
-		sector_t space = conf->spacing;
-		int round;
-		conf->sector_shift = 0;
-		if (sizeof(sector_t) > sizeof(u32)) {
-			/*shift down space and s so that sector_div will work */
-			while (space > (sector_t) (~(u32)0)) {
-				s >>= 1;
-				space >>= 1;
-				s += 1; /* force round-up */
-				conf->sector_shift++;
-			}
-		}
-		round = sector_div(s, (u32)space) ? 1 : 0;
-		nb_zone = s + round;
-	}
-	printk(KERN_INFO "raid0 : nb_zone is %d.\n", nb_zone);
-
-	printk(KERN_INFO "raid0 : Allocating %zu bytes for hash.\n",
-				nb_zone*sizeof(struct strip_zone*));
-	conf->hash_table = kmalloc (sizeof (struct strip_zone *)*nb_zone, GFP_KERNEL);
-	if (!conf->hash_table)
-		goto out_free_conf;
-	sectors = conf->strip_zone[cur].sectors;
-
-	conf->hash_table[0] = conf->strip_zone + cur;
-	for (i=1; i< nb_zone; i++) {
-		while (sectors <= conf->spacing) {
-			cur++;
-			sectors += conf->strip_zone[cur].sectors;
-		}
-		sectors -= conf->spacing;
-		conf->hash_table[i] = conf->strip_zone + cur;
-	}
-	if (conf->sector_shift) {
-		conf->spacing >>= conf->sector_shift;
-		/* round spacing up so when we divide by it, we
-		 * err on the side of too-low, which is safest
-		 */
-		conf->spacing++;
-	}
-
 	/* calculate the max read-ahead size.
 	 * For read-ahead of large files to be effective, we need to
 	 * readahead at least twice a whole stripe. i.e. number of devices
@@ -365,48 +343,108 @@
 	 * chunksize should be used in that case.
 	 */
 	{
-		int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_SIZE;
+		int stripe = mddev->raid_disks *
+			(mddev->chunk_sectors << 9) / PAGE_SIZE;
 		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
 	}
 
-
 	blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
+	dump_zones(mddev);
+	md_integrity_register(mddev);
 	return 0;
+}
 
-out_free_conf:
+static int raid0_stop(mddev_t *mddev)
+{
+	raid0_conf_t *conf = mddev->private;
+
+	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	kfree(conf->strip_zone);
 	kfree(conf->devlist);
 	kfree(conf);
 	mddev->private = NULL;
-out:
-	return -ENOMEM;
+	return 0;
 }
 
-static int raid0_stop (mddev_t *mddev)
+/* Find the zone which holds a particular offset
+ * Update *sectorp to be an offset in that zone
+ */
+static struct strip_zone *find_zone(struct raid0_private_data *conf,
+				    sector_t *sectorp)
 {
-	raid0_conf_t *conf = mddev_to_conf(mddev);
+	int i;
+	struct strip_zone *z = conf->strip_zone;
+	sector_t sector = *sectorp;
 
-	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
-	kfree(conf->hash_table);
-	conf->hash_table = NULL;
-	kfree(conf->strip_zone);
-	conf->strip_zone = NULL;
-	kfree(conf);
-	mddev->private = NULL;
+	for (i = 0; i < conf->nr_strip_zones; i++)
+		if (sector < z[i].zone_end) {
+			if (i)
+				*sectorp = sector - z[i-1].zone_end;
+			return z + i;
+		}
+	BUG();
+}
 
-	return 0;
+/*
+ * remaps the bio to the target device. we separate two flows.
+ * power 2 flow and a general flow for the sake of perfromance
+*/
+static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
+				sector_t sector, sector_t *sector_offset)
+{
+	unsigned int sect_in_chunk;
+	sector_t chunk;
+	raid0_conf_t *conf = mddev->private;
+	unsigned int chunk_sects = mddev->chunk_sectors;
+
+	if (is_power_of_2(chunk_sects)) {
+		int chunksect_bits = ffz(~chunk_sects);
+		/* find the sector offset inside the chunk */
+		sect_in_chunk  = sector & (chunk_sects - 1);
+		sector >>= chunksect_bits;
+		/* chunk in zone */
+		chunk = *sector_offset;
+		/* quotient is the chunk in real device*/
+		sector_div(chunk, zone->nb_dev << chunksect_bits);
+	} else{
+		sect_in_chunk = sector_div(sector, chunk_sects);
+		chunk = *sector_offset;
+		sector_div(chunk, chunk_sects * zone->nb_dev);
+	}
+	/*
+	*  position the bio over the real device
+	*  real sector = chunk in device + starting of zone
+	*	+ the position in the chunk
+	*/
+	*sector_offset = (chunk * chunk_sects) + sect_in_chunk;
+	return conf->devlist[(zone - conf->strip_zone)*mddev->raid_disks
+			     + sector_div(sector, zone->nb_dev)];
 }
 
-static int raid0_make_request (struct request_queue *q, struct bio *bio)
+/*
+ * Is io distribute over 1 or more chunks ?
+*/
+static inline int is_io_in_chunk_boundary(mddev_t *mddev,
+			unsigned int chunk_sects, struct bio *bio)
+{
+	if (likely(is_power_of_2(chunk_sects))) {
+		return chunk_sects >= ((bio->bi_sector & (chunk_sects-1))
+					+ (bio->bi_size >> 9));
+	} else{
+		sector_t sector = bio->bi_sector;
+		return chunk_sects >= (sector_div(sector, chunk_sects)
+						+ (bio->bi_size >> 9));
+	}
+}
+
+static int raid0_make_request(struct request_queue *q, struct bio *bio)
 {
 	mddev_t *mddev = q->queuedata;
-	unsigned int sect_in_chunk, chunksect_bits, chunk_sects;
-	raid0_conf_t *conf = mddev_to_conf(mddev);
+	unsigned int chunk_sects;
+	sector_t sector_offset;
 	struct strip_zone *zone;
 	mdk_rdev_t *tmp_dev;
-	sector_t chunk;
-	sector_t sector, rsect;
 	const int rw = bio_data_dir(bio);
 	int cpu;
 
@@ -421,11 +459,9 @@
 		      bio_sectors(bio));
 	part_stat_unlock();
 
-	chunk_sects = mddev->chunk_size >> 9;
-	chunksect_bits = ffz(~chunk_sects);
-	sector = bio->bi_sector;
-
-	if (unlikely(chunk_sects < (bio->bi_sector & (chunk_sects - 1)) + (bio->bi_size >> 9))) {
+	chunk_sects = mddev->chunk_sectors;
+	if (unlikely(!is_io_in_chunk_boundary(mddev, chunk_sects, bio))) {
+		sector_t sector = bio->bi_sector;
 		struct bio_pair *bp;
 		/* Sanity check -- queue functions should prevent this happening */
 		if (bio->bi_vcnt != 1 ||
@@ -434,7 +470,12 @@
 		/* This is a one page bio that upper layers
 		 * refuse to split for us, so we need to split it.
 		 */
-		bp = bio_split(bio, chunk_sects - (bio->bi_sector & (chunk_sects - 1)));
+		if (likely(is_power_of_2(chunk_sects)))
+			bp = bio_split(bio, chunk_sects - (sector &
+							   (chunk_sects-1)));
+		else
+			bp = bio_split(bio, chunk_sects -
+				       sector_div(sector, chunk_sects));
 		if (raid0_make_request(q, &bp->bio1))
 			generic_make_request(&bp->bio1);
 		if (raid0_make_request(q, &bp->bio2))
@@ -443,34 +484,14 @@
 		bio_pair_release(bp);
 		return 0;
 	}
- 
-
-	{
-		sector_t x = sector >> conf->sector_shift;
-		sector_div(x, (u32)conf->spacing);
-		zone = conf->hash_table[x];
-	}
-
-	while (sector >= zone->zone_start + zone->sectors)
-		zone++;
-
-	sect_in_chunk = bio->bi_sector & (chunk_sects - 1);
-
-
-	{
-		sector_t x = (sector - zone->zone_start) >> chunksect_bits;
-
-		sector_div(x, zone->nb_dev);
-		chunk = x;
 
-		x = sector >> chunksect_bits;
-		tmp_dev = zone->dev[sector_div(x, zone->nb_dev)];
-	}
-	rsect = (chunk << chunksect_bits) + zone->dev_start + sect_in_chunk;
- 
+	sector_offset = bio->bi_sector;
+	zone =  find_zone(mddev->private, &sector_offset);
+	tmp_dev = map_sector(mddev, zone, bio->bi_sector,
+			     &sector_offset);
 	bio->bi_bdev = tmp_dev->bdev;
-	bio->bi_sector = rsect + tmp_dev->data_offset;
-
+	bio->bi_sector = sector_offset + zone->dev_start +
+		tmp_dev->data_offset;
 	/*
 	 * Let the main block layer submit the IO and resolve recursion:
 	 */
@@ -485,31 +506,35 @@
 	return 0;
 }
 
-static void raid0_status (struct seq_file *seq, mddev_t *mddev)
+static void raid0_status(struct seq_file *seq, mddev_t *mddev)
 {
 #undef MD_DEBUG
 #ifdef MD_DEBUG
 	int j, k, h;
 	char b[BDEVNAME_SIZE];
-	raid0_conf_t *conf = mddev_to_conf(mddev);
+	raid0_conf_t *conf = mddev->private;
 
+	sector_t zone_size;
+	sector_t zone_start = 0;
 	h = 0;
+
 	for (j = 0; j < conf->nr_strip_zones; j++) {
 		seq_printf(seq, "      z%d", j);
-		if (conf->hash_table[h] == conf->strip_zone+j)
-			seq_printf(seq, "(h%d)", h++);
 		seq_printf(seq, "=[");
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
 			seq_printf(seq, "%s/", bdevname(
-				conf->strip_zone[j].dev[k]->bdev,b));
+				conf->devlist[j*mddev->raid_disks + k]
+						->bdev, b));
 
-		seq_printf(seq, "] zs=%d ds=%d s=%d\n",
-				conf->strip_zone[j].zone_start,
-				conf->strip_zone[j].dev_start,
-				conf->strip_zone[j].sectors);
+		zone_size  = conf->strip_zone[j].zone_end - zone_start;
+		seq_printf(seq, "] ze=%lld ds=%lld s=%lld\n",
+			(unsigned long long)zone_start>>1,
+			(unsigned long long)conf->strip_zone[j].dev_start>>1,
+			(unsigned long long)zone_size>>1);
+		zone_start = conf->strip_zone[j].zone_end;
 	}
 #endif
-	seq_printf(seq, " %dk chunks", mddev->chunk_size/1024);
+	seq_printf(seq, " %dk chunks", mddev->chunk_sectors / 2);
 	return;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid0.h linux-libre-2.6.31-gnu/drivers/md/raid0.h
--- linux-libre-2.6.30-gnu/drivers/md/raid0.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid0.h	2009-09-09 18:13:59.000000000 -0400
@@ -3,26 +3,18 @@
 
 struct strip_zone
 {
-	sector_t zone_start;	/* Zone offset in md_dev (in sectors) */
+	sector_t zone_end;	/* Start of the next zone (in sectors) */
 	sector_t dev_start;	/* Zone offset in real dev (in sectors) */
-	sector_t sectors;	/* Zone size in sectors */
 	int nb_dev;		/* # of devices attached to the zone */
-	mdk_rdev_t **dev;	/* Devices attached to the zone */
 };
 
 struct raid0_private_data
 {
-	struct strip_zone **hash_table; /* Table of indexes into strip_zone */
 	struct strip_zone *strip_zone;
 	mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
 	int nr_strip_zones;
-
-	sector_t spacing;
-	int sector_shift; /* shift this before divide by spacing */
 };
 
 typedef struct raid0_private_data raid0_conf_t;
 
-#define mddev_to_conf(mddev) ((raid0_conf_t *) mddev->private)
-
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid10.c linux-libre-2.6.31-gnu/drivers/md/raid10.c
--- linux-libre-2.6.30-gnu/drivers/md/raid10.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid10.c	2009-09-09 18:13:59.000000000 -0400
@@ -188,7 +188,7 @@
 
 static void free_r10bio(r10bio_t *r10_bio)
 {
-	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	conf_t *conf = r10_bio->mddev->private;
 
 	/*
 	 * Wake up any possible resync thread that waits for the device
@@ -202,7 +202,7 @@
 
 static void put_buf(r10bio_t *r10_bio)
 {
-	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	conf_t *conf = r10_bio->mddev->private;
 
 	mempool_free(r10_bio, conf->r10buf_pool);
 
@@ -213,7 +213,7 @@
 {
 	unsigned long flags;
 	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r10_bio->retry_list, &conf->retry_list);
@@ -245,7 +245,7 @@
  */
 static inline void update_head_pos(int slot, r10bio_t *r10_bio)
 {
-	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	conf_t *conf = r10_bio->mddev->private;
 
 	conf->mirrors[r10_bio->devs[slot].devnum].head_position =
 		r10_bio->devs[slot].addr + (r10_bio->sectors);
@@ -256,7 +256,7 @@
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
 	int slot, dev;
-	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	conf_t *conf = r10_bio->mddev->private;
 
 
 	slot = r10_bio->read_slot;
@@ -297,7 +297,7 @@
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
 	int slot, dev;
-	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	conf_t *conf = r10_bio->mddev->private;
 
 	for (slot = 0; slot < conf->copies; slot++)
 		if (r10_bio->devs[slot].bio == bio)
@@ -461,7 +461,7 @@
 	mddev_t *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
-	unsigned int chunk_sectors = mddev->chunk_size >> 9;
+	unsigned int chunk_sectors = mddev->chunk_sectors;
 	unsigned int bio_sectors = bvm->bi_size >> 9;
 
 	max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
@@ -596,7 +596,7 @@
 
 static void unplug_slaves(mddev_t *mddev)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i;
 
 	rcu_read_lock();
@@ -628,7 +628,7 @@
 static int raid10_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i, ret = 0;
 
 	rcu_read_lock();
@@ -788,7 +788,7 @@
 static int make_request(struct request_queue *q, struct bio * bio)
 {
 	mddev_t *mddev = q->queuedata;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	mirror_info_t *mirror;
 	r10bio_t *r10_bio;
 	struct bio *read_bio;
@@ -981,11 +981,11 @@
 
 static void status(struct seq_file *seq, mddev_t *mddev)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i;
 
 	if (conf->near_copies < conf->raid_disks)
-		seq_printf(seq, " %dK chunks", mddev->chunk_size/1024);
+		seq_printf(seq, " %dK chunks", mddev->chunk_sectors / 2);
 	if (conf->near_copies > 1)
 		seq_printf(seq, " %d near-copies", conf->near_copies);
 	if (conf->far_copies > 1) {
@@ -1006,7 +1006,7 @@
 static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	/*
 	 * If it is not operational, then we have already marked it as dead
@@ -1151,15 +1151,15 @@
 	for ( ; mirror <= last ; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
 
-			blk_queue_stack_limits(mddev->queue,
-					       rdev->bdev->bd_disk->queue);
+			disk_stack_limits(mddev->gendisk, rdev->bdev,
+					  rdev->data_offset << 9);
 			/* as we don't honour merge_bvec_fn, we must never risk
 			 * violating it, so limit ->max_sector to one PAGE, as
 			 * a one page request is never in violation.
 			 */
 			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
+				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
@@ -1170,6 +1170,7 @@
 			break;
 		}
 
+	md_integrity_add_rdev(rdev, mddev);
 	print_conf(conf);
 	return err;
 }
@@ -1203,7 +1204,9 @@
 			/* lost the race, try later */
 			err = -EBUSY;
 			p->rdev = rdev;
+			goto abort;
 		}
+		md_integrity_register(mddev);
 	}
 abort:
 
@@ -1215,7 +1218,7 @@
 static void end_sync_read(struct bio *bio, int error)
 {
 	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
-	conf_t *conf = mddev_to_conf(r10_bio->mddev);
+	conf_t *conf = r10_bio->mddev->private;
 	int i,d;
 
 	for (i=0; i<conf->copies; i++)
@@ -1253,7 +1256,7 @@
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
 	mddev_t *mddev = r10_bio->mddev;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i,d;
 
 	for (i = 0; i < conf->copies; i++)
@@ -1300,7 +1303,7 @@
  */
 static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i, first;
 	struct bio *tbio, *fbio;
 
@@ -1400,7 +1403,7 @@
 
 static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i, d;
 	struct bio *bio, *wbio;
 
@@ -1549,7 +1552,7 @@
 	r10bio_t *r10_bio;
 	struct bio *bio;
 	unsigned long flags;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 	int unplug=0;
 	mdk_rdev_t *rdev;
@@ -1572,7 +1575,7 @@
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 
 		mddev = r10_bio->mddev;
-		conf = mddev_to_conf(mddev);
+		conf = mddev->private;
 		if (test_bit(R10BIO_IsSync, &r10_bio->state)) {
 			sync_request_write(mddev, r10_bio);
 			unplug = 1;
@@ -1680,7 +1683,7 @@
 
 static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	r10bio_t *r10_bio;
 	struct bio *biolist = NULL, *bio;
 	sector_t max_sector, nr_sectors;
@@ -2026,7 +2029,7 @@
 raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 {
 	sector_t size;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	if (!raid_disks)
 		raid_disks = mddev->raid_disks;
@@ -2044,15 +2047,16 @@
 static int run(mddev_t *mddev)
 {
 	conf_t *conf;
-	int i, disk_idx;
+	int i, disk_idx, chunk_size;
 	mirror_info_t *disk;
 	mdk_rdev_t *rdev;
 	int nc, fc, fo;
 	sector_t stride, size;
 
-	if (mddev->chunk_size < PAGE_SIZE) {
+	if (mddev->chunk_sectors < (PAGE_SIZE >> 9) ||
+	    !is_power_of_2(mddev->chunk_sectors)) {
 		printk(KERN_ERR "md/raid10: chunk size must be "
-		       "at least PAGE_SIZE(%ld).\n", PAGE_SIZE);
+		       "at least PAGE_SIZE(%ld) and be a power of 2.\n", PAGE_SIZE);
 		return -EINVAL;
 	}
 
@@ -2095,8 +2099,8 @@
 	conf->far_copies = fc;
 	conf->copies = nc*fc;
 	conf->far_offset = fo;
-	conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1;
-	conf->chunk_shift = ffz(~mddev->chunk_size) - 9;
+	conf->chunk_mask = mddev->chunk_sectors - 1;
+	conf->chunk_shift = ffz(~mddev->chunk_sectors);
 	size = mddev->dev_sectors >> conf->chunk_shift;
 	sector_div(size, fc);
 	size = size * conf->raid_disks;
@@ -2129,6 +2133,14 @@
 	spin_lock_init(&conf->device_lock);
 	mddev->queue->queue_lock = &conf->device_lock;
 
+	chunk_size = mddev->chunk_sectors << 9;
+	blk_queue_io_min(mddev->queue, chunk_size);
+	if (conf->raid_disks % conf->near_copies)
+		blk_queue_io_opt(mddev->queue, chunk_size * conf->raid_disks);
+	else
+		blk_queue_io_opt(mddev->queue, chunk_size *
+				 (conf->raid_disks / conf->near_copies));
+
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		disk_idx = rdev->raid_disk;
 		if (disk_idx >= mddev->raid_disks
@@ -2137,16 +2149,15 @@
 		disk = conf->mirrors + disk_idx;
 
 		disk->rdev = rdev;
-
-		blk_queue_stack_limits(mddev->queue,
-				       rdev->bdev->bd_disk->queue);
+		disk_stack_limits(mddev->gendisk, rdev->bdev,
+				  rdev->data_offset << 9);
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, so limit ->max_sector to one PAGE, as
 		 * a one page request is never in violation.
 		 */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->head_position = 0;
 	}
@@ -2185,6 +2196,10 @@
 		goto out_free_conf;
 	}
 
+	if (mddev->recovery_cp != MaxSector)
+		printk(KERN_NOTICE "raid10: %s is not clean"
+		       " -- starting background reconstruction\n",
+		       mdname(mddev));
 	printk(KERN_INFO
 		"raid10: raid set %s active with %d out of %d devices\n",
 		mdname(mddev), mddev->raid_disks - mddev->degraded,
@@ -2204,7 +2219,8 @@
 	 * maybe...
 	 */
 	{
-		int stripe = conf->raid_disks * (mddev->chunk_size / PAGE_SIZE);
+		int stripe = conf->raid_disks *
+			((mddev->chunk_sectors << 9) / PAGE_SIZE);
 		stripe /= conf->near_copies;
 		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
@@ -2212,6 +2228,7 @@
 
 	if (conf->near_copies < mddev->raid_disks)
 		blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
+	md_integrity_register(mddev);
 	return 0;
 
 out_free_conf:
@@ -2227,7 +2244,7 @@
 
 static int stop(mddev_t *mddev)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	raise_barrier(conf, 0);
 	lower_barrier(conf);
@@ -2245,7 +2262,7 @@
 
 static void raid10_quiesce(mddev_t *mddev, int state)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	switch(state) {
 	case 1:
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid10.h linux-libre-2.6.31-gnu/drivers/md/raid10.h
--- linux-libre-2.6.30-gnu/drivers/md/raid10.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid10.h	2009-09-09 18:13:59.000000000 -0400
@@ -62,12 +62,6 @@
 typedef struct r10_private_data_s conf_t;
 
 /*
- * this is the only point in the RAID code where we violate
- * C type safety. mddev->private is an 'opaque' pointer.
- */
-#define mddev_to_conf(mddev) ((conf_t *) mddev->private)
-
-/*
  * this is our 'private' RAID10 bio.
  *
  * it contains information about what kind of IO operations were started
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid1.c linux-libre-2.6.31-gnu/drivers/md/raid1.c
--- linux-libre-2.6.30-gnu/drivers/md/raid1.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid1.c	2009-09-09 18:13:59.000000000 -0400
@@ -182,7 +182,7 @@
 
 static void free_r1bio(r1bio_t *r1_bio)
 {
-	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+	conf_t *conf = r1_bio->mddev->private;
 
 	/*
 	 * Wake up any possible resync thread that waits for the device
@@ -196,7 +196,7 @@
 
 static void put_buf(r1bio_t *r1_bio)
 {
-	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+	conf_t *conf = r1_bio->mddev->private;
 	int i;
 
 	for (i=0; i<conf->raid_disks; i++) {
@@ -214,7 +214,7 @@
 {
 	unsigned long flags;
 	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	list_add(&r1_bio->retry_list, &conf->retry_list);
@@ -253,7 +253,7 @@
  */
 static inline void update_head_pos(int disk, r1bio_t *r1_bio)
 {
-	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+	conf_t *conf = r1_bio->mddev->private;
 
 	conf->mirrors[disk].head_position =
 		r1_bio->sector + (r1_bio->sectors);
@@ -264,7 +264,7 @@
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
 	int mirror;
-	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+	conf_t *conf = r1_bio->mddev->private;
 
 	mirror = r1_bio->read_disk;
 	/*
@@ -309,7 +309,7 @@
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
 	int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
-	conf_t *conf = mddev_to_conf(r1_bio->mddev);
+	conf_t *conf = r1_bio->mddev->private;
 	struct bio *to_put = NULL;
 
 
@@ -541,7 +541,7 @@
 
 static void unplug_slaves(mddev_t *mddev)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i;
 
 	rcu_read_lock();
@@ -573,7 +573,7 @@
 static int raid1_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i, ret = 0;
 
 	rcu_read_lock();
@@ -772,7 +772,7 @@
 static int make_request(struct request_queue *q, struct bio * bio)
 {
 	mddev_t *mddev = q->queuedata;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	mirror_info_t *mirror;
 	r1bio_t *r1_bio;
 	struct bio *read_bio;
@@ -991,7 +991,7 @@
 
 static void status(struct seq_file *seq, mddev_t *mddev)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i;
 
 	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
@@ -1010,7 +1010,7 @@
 static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	/*
 	 * If it is not operational, then we have already marked it as dead
@@ -1123,14 +1123,14 @@
 	for (mirror = first; mirror <= last; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
 
-			blk_queue_stack_limits(mddev->queue,
-					       rdev->bdev->bd_disk->queue);
+			disk_stack_limits(mddev->gendisk, rdev->bdev,
+					  rdev->data_offset << 9);
 			/* as we don't honour merge_bvec_fn, we must never risk
 			 * violating it, so limit ->max_sector to one PAGE, as
 			 * a one page request is never in violation.
 			 */
 			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+			    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
 				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 			p->head_position = 0;
@@ -1144,7 +1144,7 @@
 			rcu_assign_pointer(p->rdev, rdev);
 			break;
 		}
-
+	md_integrity_add_rdev(rdev, mddev);
 	print_conf(conf);
 	return err;
 }
@@ -1178,7 +1178,9 @@
 			/* lost the race, try later */
 			err = -EBUSY;
 			p->rdev = rdev;
+			goto abort;
 		}
+		md_integrity_register(mddev);
 	}
 abort:
 
@@ -1214,7 +1216,7 @@
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
 	mddev_t *mddev = r1_bio->mddev;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i;
 	int mirror=0;
 
@@ -1248,7 +1250,7 @@
 
 static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int i;
 	int disks = conf->raid_disks;
 	struct bio *bio, *wbio;
@@ -1562,7 +1564,7 @@
 	r1bio_t *r1_bio;
 	struct bio *bio;
 	unsigned long flags;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
 	int unplug=0;
 	mdk_rdev_t *rdev;
@@ -1585,7 +1587,7 @@
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 
 		mddev = r1_bio->mddev;
-		conf = mddev_to_conf(mddev);
+		conf = mddev->private;
 		if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
 			sync_request_write(mddev, r1_bio);
 			unplug = 1;
@@ -1706,7 +1708,7 @@
 
 static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	r1bio_t *r1_bio;
 	struct bio *bio;
 	sector_t max_sector, nr_sectors;
@@ -1988,15 +1990,14 @@
 		disk = conf->mirrors + disk_idx;
 
 		disk->rdev = rdev;
-
-		blk_queue_stack_limits(mddev->queue,
-				       rdev->bdev->bd_disk->queue);
+		disk_stack_limits(mddev->gendisk, rdev->bdev,
+				  rdev->data_offset << 9);
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, so limit ->max_sector to one PAGE, as
 		 * a one page request is never in violation.
 		 */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
+		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
 			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->head_position = 0;
@@ -2052,6 +2053,10 @@
 		goto out_free_conf;
 	}
 
+	if (mddev->recovery_cp != MaxSector)
+		printk(KERN_NOTICE "raid1: %s is not clean"
+		       " -- starting background reconstruction\n",
+		       mdname(mddev));
 	printk(KERN_INFO 
 		"raid1: raid set %s active with %d out of %d mirrors\n",
 		mdname(mddev), mddev->raid_disks - mddev->degraded, 
@@ -2064,7 +2069,7 @@
 	mddev->queue->unplug_fn = raid1_unplug;
 	mddev->queue->backing_dev_info.congested_fn = raid1_congested;
 	mddev->queue->backing_dev_info.congested_data = mddev;
-
+	md_integrity_register(mddev);
 	return 0;
 
 out_no_mem:
@@ -2087,7 +2092,7 @@
 
 static int stop(mddev_t *mddev)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	struct bitmap *bitmap = mddev->bitmap;
 	int behind_wait = 0;
 
@@ -2129,6 +2134,7 @@
 		return -EINVAL;
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	mddev->changed = 1;
+	revalidate_disk(mddev->gendisk);
 	if (sectors > mddev->dev_sectors &&
 	    mddev->recovery_cp == MaxSector) {
 		mddev->recovery_cp = mddev->dev_sectors;
@@ -2155,16 +2161,16 @@
 	mempool_t *newpool, *oldpool;
 	struct pool_info *newpoolinfo;
 	mirror_info_t *newmirrors;
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 	int cnt, raid_disks;
 	unsigned long flags;
 	int d, d2, err;
 
 	/* Cannot change chunk_size, layout, or level */
-	if (mddev->chunk_size != mddev->new_chunk ||
+	if (mddev->chunk_sectors != mddev->new_chunk_sectors ||
 	    mddev->layout != mddev->new_layout ||
 	    mddev->level != mddev->new_level) {
-		mddev->new_chunk = mddev->chunk_size;
+		mddev->new_chunk_sectors = mddev->chunk_sectors;
 		mddev->new_layout = mddev->layout;
 		mddev->new_level = mddev->level;
 		return -EINVAL;
@@ -2252,7 +2258,7 @@
 
 static void raid1_quiesce(mddev_t *mddev, int state)
 {
-	conf_t *conf = mddev_to_conf(mddev);
+	conf_t *conf = mddev->private;
 
 	switch(state) {
 	case 1:
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid1.h linux-libre-2.6.31-gnu/drivers/md/raid1.h
--- linux-libre-2.6.30-gnu/drivers/md/raid1.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid1.h	2009-09-09 18:13:59.000000000 -0400
@@ -64,12 +64,6 @@
 typedef struct r1_private_data_s conf_t;
 
 /*
- * this is the only point in the RAID code where we violate
- * C type safety. mddev->private is an 'opaque' pointer.
- */
-#define mddev_to_conf(mddev) ((conf_t *) mddev->private)
-
-/*
  * this is our 'private' RAID1 bio.
  *
  * it contains information about what kind of IO operations were started
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid5.c linux-libre-2.6.31-gnu/drivers/md/raid5.c
--- linux-libre-2.6.30-gnu/drivers/md/raid5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid5.c	2009-09-09 18:13:59.000000000 -0400
@@ -1274,8 +1274,8 @@
 	sector_t new_sector;
 	int algorithm = previous ? conf->prev_algo
 				 : conf->algorithm;
-	int sectors_per_chunk = previous ? (conf->prev_chunk >> 9)
-					 : (conf->chunk_size >> 9);
+	int sectors_per_chunk = previous ? conf->prev_chunk_sectors
+					 : conf->chunk_sectors;
 	int raid_disks = previous ? conf->previous_raid_disks
 				  : conf->raid_disks;
 	int data_disks = raid_disks - conf->max_degraded;
@@ -1480,8 +1480,8 @@
 	int raid_disks = sh->disks;
 	int data_disks = raid_disks - conf->max_degraded;
 	sector_t new_sector = sh->sector, check;
-	int sectors_per_chunk = previous ? (conf->prev_chunk >> 9)
-					 : (conf->chunk_size >> 9);
+	int sectors_per_chunk = previous ? conf->prev_chunk_sectors
+					 : conf->chunk_sectors;
 	int algorithm = previous ? conf->prev_algo
 				 : conf->algorithm;
 	sector_t stripe;
@@ -1997,8 +1997,7 @@
 			    struct stripe_head *sh)
 {
 	int sectors_per_chunk =
-		previous ? (conf->prev_chunk >> 9)
-			 : (conf->chunk_size >> 9);
+		previous ? conf->prev_chunk_sectors : conf->chunk_sectors;
 	int dd_idx;
 	int chunk_offset = sector_div(stripe, sectors_per_chunk);
 	int disks = previous ? conf->previous_raid_disks : conf->raid_disks;
@@ -3284,7 +3283,7 @@
 
 static void unplug_slaves(mddev_t *mddev)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	int i;
 
 	rcu_read_lock();
@@ -3308,7 +3307,7 @@
 static void raid5_unplug_device(struct request_queue *q)
 {
 	mddev_t *mddev = q->queuedata;
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&conf->device_lock, flags);
@@ -3327,7 +3326,7 @@
 static int raid5_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 
 	/* No difference between reads and writes.  Just check
 	 * how busy the stripe_cache is
@@ -3352,14 +3351,14 @@
 	mddev_t *mddev = q->queuedata;
 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 	int max;
-	unsigned int chunk_sectors = mddev->chunk_size >> 9;
+	unsigned int chunk_sectors = mddev->chunk_sectors;
 	unsigned int bio_sectors = bvm->bi_size >> 9;
 
 	if ((bvm->bi_rw & 1) == WRITE)
 		return biovec->bv_len; /* always allow writes to be mergeable */
 
-	if (mddev->new_chunk < mddev->chunk_size)
-		chunk_sectors = mddev->new_chunk >> 9;
+	if (mddev->new_chunk_sectors < mddev->chunk_sectors)
+		chunk_sectors = mddev->new_chunk_sectors;
 	max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
 	if (max < 0) max = 0;
 	if (max <= biovec->bv_len && bio_sectors == 0)
@@ -3372,11 +3371,11 @@
 static int in_chunk_boundary(mddev_t *mddev, struct bio *bio)
 {
 	sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
-	unsigned int chunk_sectors = mddev->chunk_size >> 9;
+	unsigned int chunk_sectors = mddev->chunk_sectors;
 	unsigned int bio_sectors = bio->bi_size >> 9;
 
-	if (mddev->new_chunk < mddev->chunk_size)
-		chunk_sectors = mddev->new_chunk >> 9;
+	if (mddev->new_chunk_sectors < mddev->chunk_sectors)
+		chunk_sectors = mddev->new_chunk_sectors;
 	return  chunk_sectors >=
 		((sector & (chunk_sectors - 1)) + bio_sectors);
 }
@@ -3440,7 +3439,7 @@
 	bio_put(bi);
 
 	mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata;
-	conf = mddev_to_conf(mddev);
+	conf = mddev->private;
 	rdev = (void*)raid_bi->bi_next;
 	raid_bi->bi_next = NULL;
 
@@ -3463,10 +3462,10 @@
 {
 	struct request_queue *q = bdev_get_queue(bi->bi_bdev);
 
-	if ((bi->bi_size>>9) > q->max_sectors)
+	if ((bi->bi_size>>9) > queue_max_sectors(q))
 		return 0;
 	blk_recount_segments(q, bi);
-	if (bi->bi_phys_segments > q->max_phys_segments)
+	if (bi->bi_phys_segments > queue_max_phys_segments(q))
 		return 0;
 
 	if (q->merge_bvec_fn)
@@ -3482,7 +3481,7 @@
 static int chunk_aligned_read(struct request_queue *q, struct bio * raid_bio)
 {
 	mddev_t *mddev = q->queuedata;
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	unsigned int dd_idx;
 	struct bio* align_bi;
 	mdk_rdev_t *rdev;
@@ -3599,7 +3598,7 @@
 static int make_request(struct request_queue *q, struct bio * bi)
 {
 	mddev_t *mddev = q->queuedata;
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	int dd_idx;
 	sector_t new_sector;
 	sector_t logical_sector, last_sector;
@@ -3696,16 +3695,25 @@
 				spin_unlock_irq(&conf->device_lock);
 				if (must_retry) {
 					release_stripe(sh);
+					schedule();
 					goto retry;
 				}
 			}
-			/* FIXME what if we get a false positive because these
-			 * are being updated.
-			 */
-			if (logical_sector >= mddev->suspend_lo &&
+
+			if (bio_data_dir(bi) == WRITE &&
+			    logical_sector >= mddev->suspend_lo &&
 			    logical_sector < mddev->suspend_hi) {
 				release_stripe(sh);
-				schedule();
+				/* As the suspend_* range is controlled by
+				 * userspace, we want an interruptible
+				 * wait.
+				 */
+				flush_signals(current);
+				prepare_to_wait(&conf->wait_for_overlap,
+						&w, TASK_INTERRUPTIBLE);
+				if (logical_sector >= mddev->suspend_lo &&
+				    logical_sector < mddev->suspend_hi)
+					schedule();
 				goto retry;
 			}
 
@@ -3777,7 +3785,7 @@
 		    conf->reshape_progress < raid5_size(mddev, 0, 0)) {
 			sector_nr = raid5_size(mddev, 0, 0)
 				- conf->reshape_progress;
-		} else if (mddev->delta_disks > 0 &&
+		} else if (mddev->delta_disks >= 0 &&
 			   conf->reshape_progress > 0)
 			sector_nr = conf->reshape_progress;
 		sector_div(sector_nr, new_data_disks);
@@ -3791,10 +3799,10 @@
 	 * If old and new chunk sizes differ, we need to process the
 	 * largest of these
 	 */
-	if (mddev->new_chunk > mddev->chunk_size)
-		reshape_sectors = mddev->new_chunk / 512;
+	if (mddev->new_chunk_sectors > mddev->chunk_sectors)
+		reshape_sectors = mddev->new_chunk_sectors;
 	else
-		reshape_sectors = mddev->chunk_size / 512;
+		reshape_sectors = mddev->chunk_sectors;
 
 	/* we update the metadata when there is more than 3Meg
 	 * in the block range (that is rather arbitrary, should
@@ -3917,7 +3925,7 @@
 				     1, &dd_idx, NULL);
 	last_sector =
 		raid5_compute_sector(conf, ((stripe_addr+reshape_sectors)
-					    *(new_data_disks) - 1),
+					    * new_data_disks - 1),
 				     1, &dd_idx, NULL);
 	if (last_sector >= mddev->dev_sectors)
 		last_sector = mddev->dev_sectors - 1;
@@ -3946,7 +3954,7 @@
 		wait_event(conf->wait_for_overlap,
 			   atomic_read(&conf->reshape_stripes) == 0);
 		mddev->reshape_position = conf->reshape_progress;
-		mddev->curr_resync_completed = mddev->curr_resync;
+		mddev->curr_resync_completed = mddev->curr_resync + reshape_sectors;
 		conf->reshape_checkpoint = jiffies;
 		set_bit(MD_CHANGE_DEVS, &mddev->flags);
 		md_wakeup_thread(mddev->thread);
@@ -3991,6 +3999,9 @@
 		return 0;
 	}
 
+	/* Allow raid5_quiesce to complete */
+	wait_event(conf->wait_for_overlap, conf->quiesce != 2);
+
 	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
 		return reshape_request(mddev, sector_nr, skipped);
 
@@ -4129,7 +4140,7 @@
 static void raid5d(mddev_t *mddev)
 {
 	struct stripe_head *sh;
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	int handled;
 
 	pr_debug("+++ raid5d active\n");
@@ -4185,7 +4196,7 @@
 static ssize_t
 raid5_show_stripe_cache_size(mddev_t *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", conf->max_nr_stripes);
 	else
@@ -4195,7 +4206,7 @@
 static ssize_t
 raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	unsigned long new;
 	int err;
 
@@ -4233,7 +4244,7 @@
 static ssize_t
 raid5_show_preread_threshold(mddev_t *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", conf->bypass_threshold);
 	else
@@ -4243,7 +4254,7 @@
 static ssize_t
 raid5_store_preread_threshold(mddev_t *mddev, const char *page, size_t len)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	unsigned long new;
 	if (len >= PAGE_SIZE)
 		return -EINVAL;
@@ -4267,7 +4278,7 @@
 static ssize_t
 stripe_cache_active_show(mddev_t *mddev, char *page)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	if (conf)
 		return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
 	else
@@ -4291,7 +4302,7 @@
 static sector_t
 raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 
 	if (!sectors)
 		sectors = mddev->dev_sectors;
@@ -4303,11 +4314,20 @@
 			raid_disks = conf->previous_raid_disks;
 	}
 
-	sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
-	sectors &= ~((sector_t)mddev->new_chunk/512 - 1);
+	sectors &= ~((sector_t)mddev->chunk_sectors - 1);
+	sectors &= ~((sector_t)mddev->new_chunk_sectors - 1);
 	return sectors * (raid_disks - conf->max_degraded);
 }
 
+static void free_conf(raid5_conf_t *conf)
+{
+	shrink_stripes(conf);
+	safe_put_page(conf->spare_page);
+	kfree(conf->disks);
+	kfree(conf->stripe_hashtbl);
+	kfree(conf);
+}
+
 static raid5_conf_t *setup_conf(mddev_t *mddev)
 {
 	raid5_conf_t *conf;
@@ -4336,9 +4356,11 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (!mddev->new_chunk || mddev->new_chunk % PAGE_SIZE) {
+	if (!mddev->new_chunk_sectors ||
+	    (mddev->new_chunk_sectors << 9) % PAGE_SIZE ||
+	    !is_power_of_2(mddev->new_chunk_sectors)) {
 		printk(KERN_ERR "raid5: invalid chunk size %d for %s\n",
-			mddev->new_chunk, mdname(mddev));
+		       mddev->new_chunk_sectors << 9, mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -4401,7 +4423,7 @@
 			conf->fullsync = 1;
 	}
 
-	conf->chunk_size = mddev->new_chunk;
+	conf->chunk_sectors = mddev->new_chunk_sectors;
 	conf->level = mddev->new_level;
 	if (conf->level == 6)
 		conf->max_degraded = 2;
@@ -4411,7 +4433,7 @@
 	conf->max_nr_stripes = NR_STRIPES;
 	conf->reshape_progress = mddev->reshape_position;
 	if (conf->reshape_progress != MaxSector) {
-		conf->prev_chunk = mddev->chunk_size;
+		conf->prev_chunk_sectors = mddev->chunk_sectors;
 		conf->prev_algo = mddev->layout;
 	}
 
@@ -4437,11 +4459,7 @@
 
  abort:
 	if (conf) {
-		shrink_stripes(conf);
-		safe_put_page(conf->spare_page);
-		kfree(conf->disks);
-		kfree(conf->stripe_hashtbl);
-		kfree(conf);
+		free_conf(conf);
 		return ERR_PTR(-EIO);
 	} else
 		return ERR_PTR(-ENOMEM);
@@ -4450,9 +4468,13 @@
 static int run(mddev_t *mddev)
 {
 	raid5_conf_t *conf;
-	int working_disks = 0;
+	int working_disks = 0, chunk_size;
 	mdk_rdev_t *rdev;
 
+	if (mddev->recovery_cp != MaxSector)
+		printk(KERN_NOTICE "raid5: %s is not clean"
+		       " -- starting background reconstruction\n",
+		       mdname(mddev));
 	if (mddev->reshape_position != MaxSector) {
 		/* Check that we can continue the reshape.
 		 * Currently only disks can change, it must
@@ -4475,7 +4497,7 @@
 		 * geometry.
 		 */
 		here_new = mddev->reshape_position;
-		if (sector_div(here_new, (mddev->new_chunk>>9)*
+		if (sector_div(here_new, mddev->new_chunk_sectors *
 			       (mddev->raid_disks - max_degraded))) {
 			printk(KERN_ERR "raid5: reshape_position not "
 			       "on a stripe boundary\n");
@@ -4483,11 +4505,30 @@
 		}
 		/* here_new is the stripe we will write to */
 		here_old = mddev->reshape_position;
-		sector_div(here_old, (mddev->chunk_size>>9)*
+		sector_div(here_old, mddev->chunk_sectors *
 			   (old_disks-max_degraded));
 		/* here_old is the first stripe that we might need to read
 		 * from */
-		if (here_new >= here_old) {
+		if (mddev->delta_disks == 0) {
+			/* We cannot be sure it is safe to start an in-place
+			 * reshape.  It is only safe if user-space if monitoring
+			 * and taking constant backups.
+			 * mdadm always starts a situation like this in
+			 * readonly mode so it can take control before
+			 * allowing any writes.  So just check for that.
+			 */
+			if ((here_new * mddev->new_chunk_sectors != 
+			     here_old * mddev->chunk_sectors) ||
+			    mddev->ro == 0) {
+				printk(KERN_ERR "raid5: in-place reshape must be started"
+				       " in read-only mode - aborting\n");
+				return -EINVAL;
+			}
+		} else if (mddev->delta_disks < 0
+		    ? (here_new * mddev->new_chunk_sectors <=
+		       here_old * mddev->chunk_sectors)
+		    : (here_new * mddev->new_chunk_sectors >=
+		       here_old * mddev->chunk_sectors)) {
 			/* Reading from the same stripe as writing to - bad */
 			printk(KERN_ERR "raid5: reshape_position too early for "
 			       "auto-recovery - aborting.\n");
@@ -4498,7 +4539,7 @@
 	} else {
 		BUG_ON(mddev->level != mddev->new_level);
 		BUG_ON(mddev->layout != mddev->new_layout);
-		BUG_ON(mddev->chunk_size != mddev->new_chunk);
+		BUG_ON(mddev->chunk_sectors != mddev->new_chunk_sectors);
 		BUG_ON(mddev->delta_disks != 0);
 	}
 
@@ -4532,7 +4573,7 @@
 	}
 
 	/* device size must be a multiple of chunk size */
-	mddev->dev_sectors &= ~(mddev->chunk_size / 512 - 1);
+	mddev->dev_sectors &= ~(mddev->chunk_sectors - 1);
 	mddev->resync_max_sectors = mddev->dev_sectors;
 
 	if (mddev->degraded > 0 &&
@@ -4581,7 +4622,7 @@
 	{
 		int data_disks = conf->previous_raid_disks - conf->max_degraded;
 		int stripe = data_disks *
-			(mddev->chunk_size / PAGE_SIZE);
+			((mddev->chunk_sectors << 9) / PAGE_SIZE);
 		if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
 	}
@@ -4601,18 +4642,22 @@
 	md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
 
 	blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
+	chunk_size = mddev->chunk_sectors << 9;
+	blk_queue_io_min(mddev->queue, chunk_size);
+	blk_queue_io_opt(mddev->queue, chunk_size *
+			 (conf->raid_disks - conf->max_degraded));
+
+	list_for_each_entry(rdev, &mddev->disks, same_set)
+		disk_stack_limits(mddev->gendisk, rdev->bdev,
+				  rdev->data_offset << 9);
 
 	return 0;
 abort:
 	md_unregister_thread(mddev->thread);
 	mddev->thread = NULL;
 	if (conf) {
-		shrink_stripes(conf);
 		print_raid5_conf(conf);
-		safe_put_page(conf->spare_page);
-		kfree(conf->disks);
-		kfree(conf->stripe_hashtbl);
-		kfree(conf);
+		free_conf(conf);
 	}
 	mddev->private = NULL;
 	printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev));
@@ -4627,13 +4672,10 @@
 
 	md_unregister_thread(mddev->thread);
 	mddev->thread = NULL;
-	shrink_stripes(conf);
-	kfree(conf->stripe_hashtbl);
 	mddev->queue->backing_dev_info.congested_fn = NULL;
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
-	kfree(conf->disks);
-	kfree(conf);
+	free_conf(conf);
 	mddev->private = NULL;
 	return 0;
 }
@@ -4678,7 +4720,8 @@
 	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
 	int i;
 
-	seq_printf (seq, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout);
+	seq_printf(seq, " level %d, %dk chunk, algorithm %d", mddev->level,
+		mddev->chunk_sectors / 2, mddev->layout);
 	seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->raid_disks - mddev->degraded);
 	for (i = 0; i < conf->raid_disks; i++)
 		seq_printf (seq, "%s",
@@ -4826,7 +4869,7 @@
 	 * any io in the removed space completes, but it hardly seems
 	 * worth it.
 	 */
-	sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
+	sectors &= ~((sector_t)mddev->chunk_sectors - 1);
 	md_set_array_sectors(mddev, raid5_size(mddev, sectors,
 					       mddev->raid_disks));
 	if (mddev->array_sectors >
@@ -4834,6 +4877,7 @@
 		return -EINVAL;
 	set_capacity(mddev->gendisk, mddev->array_sectors);
 	mddev->changed = 1;
+	revalidate_disk(mddev->gendisk);
 	if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) {
 		mddev->recovery_cp = mddev->dev_sectors;
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -4843,14 +4887,37 @@
 	return 0;
 }
 
-static int raid5_check_reshape(mddev_t *mddev)
+static int check_stripe_cache(mddev_t *mddev)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	/* Can only proceed if there are plenty of stripe_heads.
+	 * We need a minimum of one full stripe,, and for sensible progress
+	 * it is best to have about 4 times that.
+	 * If we require 4 times, then the default 256 4K stripe_heads will
+	 * allow for chunk sizes up to 256K, which is probably OK.
+	 * If the chunk size is greater, user-space should request more
+	 * stripe_heads first.
+	 */
+	raid5_conf_t *conf = mddev->private;
+	if (((mddev->chunk_sectors << 9) / STRIPE_SIZE) * 4
+	    > conf->max_nr_stripes ||
+	    ((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
+	    > conf->max_nr_stripes) {
+		printk(KERN_WARNING "raid5: reshape: not enough stripes.  Needed %lu\n",
+		       ((max(mddev->chunk_sectors, mddev->new_chunk_sectors) << 9)
+			/ STRIPE_SIZE)*4);
+		return 0;
+	}
+	return 1;
+}
+
+static int check_reshape(mddev_t *mddev)
+{
+	raid5_conf_t *conf = mddev->private;
 
 	if (mddev->delta_disks == 0 &&
 	    mddev->new_layout == mddev->layout &&
-	    mddev->new_chunk == mddev->chunk_size)
-		return -EINVAL; /* nothing to do */
+	    mddev->new_chunk_sectors == mddev->chunk_sectors)
+		return 0; /* nothing to do */
 	if (mddev->bitmap)
 		/* Cannot grow a bitmap yet */
 		return -EBUSY;
@@ -4869,28 +4936,15 @@
 			return -EINVAL;
 	}
 
-	/* Can only proceed if there are plenty of stripe_heads.
-	 * We need a minimum of one full stripe,, and for sensible progress
-	 * it is best to have about 4 times that.
-	 * If we require 4 times, then the default 256 4K stripe_heads will
-	 * allow for chunk sizes up to 256K, which is probably OK.
-	 * If the chunk size is greater, user-space should request more
-	 * stripe_heads first.
-	 */
-	if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes ||
-	    (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) {
-		printk(KERN_WARNING "raid5: reshape: not enough stripes.  Needed %lu\n",
-		       (max(mddev->chunk_size, mddev->new_chunk)
-			/ STRIPE_SIZE)*4);
+	if (!check_stripe_cache(mddev))
 		return -ENOSPC;
-	}
 
 	return resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
 }
 
 static int raid5_start_reshape(mddev_t *mddev)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 	mdk_rdev_t *rdev;
 	int spares = 0;
 	int added_devices = 0;
@@ -4899,6 +4953,9 @@
 	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
 		return -EBUSY;
 
+	if (!check_stripe_cache(mddev))
+		return -ENOSPC;
+
 	list_for_each_entry(rdev, &mddev->disks, same_set)
 		if (rdev->raid_disk < 0 &&
 		    !test_bit(Faulty, &rdev->flags))
@@ -4925,8 +4982,8 @@
 	spin_lock_irq(&conf->device_lock);
 	conf->previous_raid_disks = conf->raid_disks;
 	conf->raid_disks += mddev->delta_disks;
-	conf->prev_chunk = conf->chunk_size;
-	conf->chunk_size = mddev->new_chunk;
+	conf->prev_chunk_sectors = conf->chunk_sectors;
+	conf->chunk_sectors = mddev->new_chunk_sectors;
 	conf->prev_algo = conf->algorithm;
 	conf->algorithm = mddev->new_layout;
 	if (mddev->delta_disks < 0)
@@ -4966,7 +5023,7 @@
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 	mddev->raid_disks = conf->raid_disks;
-	mddev->reshape_position = 0;
+	mddev->reshape_position = conf->reshape_progress;
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
 	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
@@ -5008,7 +5065,7 @@
 		 */
 		{
 			int data_disks = conf->raid_disks - conf->max_degraded;
-			int stripe = data_disks * (conf->chunk_size
+			int stripe = data_disks * ((conf->chunk_sectors << 9)
 						   / PAGE_SIZE);
 			if (conf->mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
 				conf->mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
@@ -5021,8 +5078,7 @@
  */
 static void raid5_finish_reshape(mddev_t *mddev)
 {
-	struct block_device *bdev;
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 
 	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
 
@@ -5030,15 +5086,7 @@
 			md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
 			set_capacity(mddev->gendisk, mddev->array_sectors);
 			mddev->changed = 1;
-
-			bdev = bdget_disk(mddev->gendisk, 0);
-			if (bdev) {
-				mutex_lock(&bdev->bd_inode->i_mutex);
-				i_size_write(bdev->bd_inode,
-					     (loff_t)mddev->array_sectors << 9);
-				mutex_unlock(&bdev->bd_inode->i_mutex);
-				bdput(bdev);
-			}
+			revalidate_disk(mddev->gendisk);
 		} else {
 			int d;
 			mddev->degraded = conf->raid_disks;
@@ -5049,11 +5097,18 @@
 					mddev->degraded--;
 			for (d = conf->raid_disks ;
 			     d < conf->raid_disks - mddev->delta_disks;
-			     d++)
-				raid5_remove_disk(mddev, d);
+			     d++) {
+				mdk_rdev_t *rdev = conf->disks[d].rdev;
+				if (rdev && raid5_remove_disk(mddev, d) == 0) {
+					char nm[20];
+					sprintf(nm, "rd%d", rdev->raid_disk);
+					sysfs_remove_link(&mddev->kobj, nm);
+					rdev->raid_disk = -1;
+				}
+			}
 		}
 		mddev->layout = conf->algorithm;
-		mddev->chunk_size = conf->chunk_size;
+		mddev->chunk_sectors = conf->chunk_sectors;
 		mddev->reshape_position = MaxSector;
 		mddev->delta_disks = 0;
 	}
@@ -5061,7 +5116,7 @@
 
 static void raid5_quiesce(mddev_t *mddev, int state)
 {
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
 
 	switch(state) {
 	case 2: /* resume for a suspend */
@@ -5070,12 +5125,18 @@
 
 	case 1: /* stop all writes */
 		spin_lock_irq(&conf->device_lock);
-		conf->quiesce = 1;
+		/* '2' tells resync/reshape to pause so that all
+		 * active stripes can drain
+		 */
+		conf->quiesce = 2;
 		wait_event_lock_irq(conf->wait_for_stripe,
 				    atomic_read(&conf->active_stripes) == 0 &&
 				    atomic_read(&conf->active_aligned_reads) == 0,
 				    conf->device_lock, /* nothing */);
+		conf->quiesce = 1;
 		spin_unlock_irq(&conf->device_lock);
+		/* allow reshape to continue */
+		wake_up(&conf->wait_for_overlap);
 		break;
 
 	case 0: /* re-enable writes */
@@ -5111,7 +5172,7 @@
 
 	mddev->new_level = 5;
 	mddev->new_layout = ALGORITHM_LEFT_SYMMETRIC;
-	mddev->new_chunk = chunksect << 9;
+	mddev->new_chunk_sectors = chunksect;
 
 	return setup_conf(mddev);
 }
@@ -5150,24 +5211,24 @@
 }
 
 
-static int raid5_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
+static int raid5_check_reshape(mddev_t *mddev)
 {
 	/* For a 2-drive array, the layout and chunk size can be changed
 	 * immediately as not restriping is needed.
 	 * For larger arrays we record the new value - after validation
 	 * to be used by a reshape pass.
 	 */
-	raid5_conf_t *conf = mddev_to_conf(mddev);
+	raid5_conf_t *conf = mddev->private;
+	int new_chunk = mddev->new_chunk_sectors;
 
-	if (new_layout >= 0 && !algorithm_valid_raid5(new_layout))
+	if (mddev->new_layout >= 0 && !algorithm_valid_raid5(mddev->new_layout))
 		return -EINVAL;
 	if (new_chunk > 0) {
-		if (new_chunk & (new_chunk-1))
-			/* not a power of 2 */
+		if (!is_power_of_2(new_chunk))
 			return -EINVAL;
-		if (new_chunk < PAGE_SIZE)
+		if (new_chunk < (PAGE_SIZE>>9))
 			return -EINVAL;
-		if (mddev->array_sectors & ((new_chunk>>9)-1))
+		if (mddev->array_sectors & (new_chunk-1))
 			/* not factor of array size */
 			return -EINVAL;
 	}
@@ -5175,49 +5236,39 @@
 	/* They look valid */
 
 	if (mddev->raid_disks == 2) {
-
-		if (new_layout >= 0) {
-			conf->algorithm = new_layout;
-			mddev->layout = mddev->new_layout = new_layout;
+		/* can make the change immediately */
+		if (mddev->new_layout >= 0) {
+			conf->algorithm = mddev->new_layout;
+			mddev->layout = mddev->new_layout;
 		}
 		if (new_chunk > 0) {
-			conf->chunk_size = new_chunk;
-			mddev->chunk_size = mddev->new_chunk = new_chunk;
+			conf->chunk_sectors = new_chunk ;
+			mddev->chunk_sectors = new_chunk;
 		}
 		set_bit(MD_CHANGE_DEVS, &mddev->flags);
 		md_wakeup_thread(mddev->thread);
-	} else {
-		if (new_layout >= 0)
-			mddev->new_layout = new_layout;
-		if (new_chunk > 0)
-			mddev->new_chunk = new_chunk;
 	}
-	return 0;
+	return check_reshape(mddev);
 }
 
-static int raid6_reconfig(mddev_t *mddev, int new_layout, int new_chunk)
+static int raid6_check_reshape(mddev_t *mddev)
 {
-	if (new_layout >= 0 && !algorithm_valid_raid6(new_layout))
+	int new_chunk = mddev->new_chunk_sectors;
+
+	if (mddev->new_layout >= 0 && !algorithm_valid_raid6(mddev->new_layout))
 		return -EINVAL;
 	if (new_chunk > 0) {
-		if (new_chunk & (new_chunk-1))
-			/* not a power of 2 */
+		if (!is_power_of_2(new_chunk))
 			return -EINVAL;
-		if (new_chunk < PAGE_SIZE)
+		if (new_chunk < (PAGE_SIZE >> 9))
 			return -EINVAL;
-		if (mddev->array_sectors & ((new_chunk>>9)-1))
+		if (mddev->array_sectors & (new_chunk-1))
 			/* not factor of array size */
 			return -EINVAL;
 	}
 
 	/* They look valid */
-
-	if (new_layout >= 0)
-		mddev->new_layout = new_layout;
-	if (new_chunk > 0)
-		mddev->new_chunk = new_chunk;
-
-	return 0;
+	return check_reshape(mddev);
 }
 
 static void *raid5_takeover(mddev_t *mddev)
@@ -5227,8 +5278,6 @@
 	 *  raid1 - if there are two drives.  We need to know the chunk size
 	 *  raid4 - trivial - just use a raid4 layout.
 	 *  raid6 - Providing it is a *_6 layout
-	 *
-	 * For now, just do raid1
 	 */
 
 	if (mddev->level == 1)
@@ -5310,12 +5359,11 @@
 	.sync_request	= sync_request,
 	.resize		= raid5_resize,
 	.size		= raid5_size,
-	.check_reshape	= raid5_check_reshape,
+	.check_reshape	= raid6_check_reshape,
 	.start_reshape  = raid5_start_reshape,
 	.finish_reshape = raid5_finish_reshape,
 	.quiesce	= raid5_quiesce,
 	.takeover	= raid6_takeover,
-	.reconfig	= raid6_reconfig,
 };
 static struct mdk_personality raid5_personality =
 {
@@ -5338,7 +5386,6 @@
 	.finish_reshape = raid5_finish_reshape,
 	.quiesce	= raid5_quiesce,
 	.takeover	= raid5_takeover,
-	.reconfig	= raid5_reconfig,
 };
 
 static struct mdk_personality raid4_personality =
diff -druN linux-libre-2.6.30-gnu/drivers/md/raid5.h linux-libre-2.6.31-gnu/drivers/md/raid5.h
--- linux-libre-2.6.30-gnu/drivers/md/raid5.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/md/raid5.h	2009-09-09 18:13:59.000000000 -0400
@@ -334,7 +334,8 @@
 	struct hlist_head	*stripe_hashtbl;
 	mddev_t			*mddev;
 	struct disk_info	*spare;
-	int			chunk_size, level, algorithm;
+	int			chunk_sectors;
+	int			level, algorithm;
 	int			max_degraded;
 	int			raid_disks;
 	int			max_nr_stripes;
@@ -350,7 +351,8 @@
 	 */
 	sector_t		reshape_safe;
 	int			previous_raid_disks;
-	int			prev_chunk, prev_algo;
+	int			prev_chunk_sectors;
+	int			prev_algo;
 	short			generation; /* increments with every reshape */
 	unsigned long		reshape_checkpoint; /* Time we last updated
 						     * metadata */
@@ -408,8 +410,6 @@
 
 typedef struct raid5_private_data raid5_conf_t;
 
-#define mddev_to_conf(mddev) ((raid5_conf_t *) mddev->private)
-
 /*
  * Our supported algorithms
  */
diff -druN linux-libre-2.6.30-gnu/drivers/media/common/ir-keymaps.c linux-libre-2.6.31-gnu/drivers/media/common/ir-keymaps.c
--- linux-libre-2.6.30-gnu/drivers/media/common/ir-keymaps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/common/ir-keymaps.c	2009-09-09 18:13:59.000000000 -0400
@@ -2750,3 +2750,26 @@
 	[0x1b] = KEY_B,		/*recall*/
 };
 EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec);
+
+/* EVGA inDtube
+   Devin Heitmueller <devin.heitmueller@gmail.com>
+ */
+IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE] = {
+	[0x12] = KEY_POWER,
+	[0x02] = KEY_MODE,	/* TV */
+	[0x14] = KEY_MUTE,
+	[0x1a] = KEY_CHANNELUP,
+	[0x16] = KEY_TV2,	/* PIP */
+	[0x1d] = KEY_VOLUMEUP,
+	[0x05] = KEY_CHANNELDOWN,
+	[0x0f] = KEY_PLAYPAUSE,
+	[0x19] = KEY_VOLUMEDOWN,
+	[0x1c] = KEY_REWIND,
+	[0x0d] = KEY_RECORD,
+	[0x18] = KEY_FORWARD,
+	[0x1e] = KEY_PREVIOUS,
+	[0x1b] = KEY_STOP,
+	[0x1f] = KEY_NEXT,
+	[0x13] = KEY_CAMERA,
+};
+EXPORT_SYMBOL_GPL(ir_codes_evga_indtube);
diff -druN linux-libre-2.6.30-gnu/drivers/media/common/tuners/qt1010.c linux-libre-2.6.31-gnu/drivers/media/common/tuners/qt1010.c
--- linux-libre-2.6.30-gnu/drivers/media/common/tuners/qt1010.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/common/tuners/qt1010.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,24 +64,22 @@
 /* dump all registers */
 static void qt1010_dump_regs(struct qt1010_priv *priv)
 {
-	char buf[52], buf2[4];
 	u8 reg, val;
 
 	for (reg = 0; ; reg++) {
 		if (reg % 16 == 0) {
 			if (reg)
-				printk("%s\n", buf);
-			sprintf(buf, "%02x: ", reg);
+				printk(KERN_CONT "\n");
+			printk(KERN_DEBUG "%02x:", reg);
 		}
 		if (qt1010_readreg(priv, reg, &val) == 0)
-			sprintf(buf2, "%02x ", val);
+			printk(KERN_CONT " %02x", val);
 		else
-			strcpy(buf2, "-- ");
-		strcat(buf, buf2);
+			printk(KERN_CONT " --");
 		if (reg == 0x2f)
 			break;
 	}
-	printk("%s\n", buf);
+	printk(KERN_CONT "\n");
 }
 
 static int qt1010_set_params(struct dvb_frontend *fe,
diff -druN linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-simple.c linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-simple.c
--- linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-simple.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-simple.c	2009-09-09 18:13:59.000000000 -0400
@@ -416,6 +416,24 @@
 	return 0;
 }
 
+static int simple_set_aux_byte(struct dvb_frontend *fe, u8 config, u8 aux)
+{
+	struct tuner_simple_priv *priv = fe->tuner_priv;
+	int rc;
+	u8 buffer[2];
+
+	buffer[0] = (config & ~0x38) | 0x18;
+	buffer[1] = aux;
+
+	tuner_dbg("setting aux byte: 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+
+	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
+	if (2 != rc)
+		tuner_warn("i2c i/o error: rc == %d (should be 2)\n", rc);
+
+	return rc == 2 ? 0 : rc;
+}
+
 static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
 			    u16 div, u8 config, u8 cb)
 {
@@ -424,17 +442,10 @@
 
 	switch (priv->type) {
 	case TUNER_LG_TDVS_H06XF:
-		/* Set the Auxiliary Byte. */
-		buffer[0] = buffer[2];
-		buffer[0] &= ~0x20;
-		buffer[0] |= 0x18;
-		buffer[1] = 0x20;
-		tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
-
-		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
-		if (2 != rc)
-			tuner_warn("i2c i/o error: rc == %d "
-				   "(should be 2)\n", rc);
+		simple_set_aux_byte(fe, config, 0x20);
+		break;
+	case TUNER_PHILIPS_FQ1216LME_MK3:
+		simple_set_aux_byte(fe, config, 0x60); /* External AGC */
 		break;
 	case TUNER_MICROTUNE_4042FI5:
 	{
@@ -506,6 +517,11 @@
 	case TUNER_THOMSON_DTT761X:
 		buffer[3] = 0x39;
 		break;
+	case TUNER_PHILIPS_FQ1216LME_MK3:
+		tuner_err("This tuner doesn't have FM\n");
+		/* Set the low band for sanity, since it covers 88-108 MHz */
+		buffer[3] = 0x01;
+		break;
 	case TUNER_MICROTUNE_4049FM5:
 	default:
 		buffer[3] = 0xa4;
@@ -678,12 +694,12 @@
 		return 0;
 	}
 
-	/* Bandswitch byte */
-	simple_radio_bandswitch(fe, &buffer[0]);
-
 	buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
 		    TUNER_RATIO_SELECT_50; /* 50 kHz step */
 
+	/* Bandswitch byte */
+	simple_radio_bandswitch(fe, &buffer[0]);
+
 	/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
 	   freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
 	   freq * (1/800) */
diff -druN linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-types.c linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-types.c
--- linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-types.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-types.c	2009-09-09 18:13:59.000000000 -0400
@@ -578,6 +578,31 @@
 	},
 };
 
+/* ------------ TUNER_PHILIPS_FM1216MK5 - Philips PAL ------------ */
+
+static struct tuner_range tuner_fm1216mk5_pal_ranges[] = {
+	{ 16 * 158.00 /*MHz*/, 0xce, 0x01, },
+	{ 16 * 441.00 /*MHz*/, 0xce, 0x02, },
+	{ 16 * 864.00        , 0xce, 0x04, },
+};
+
+static struct tuner_params tuner_fm1216mk5_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_PAL,
+		.ranges = tuner_fm1216mk5_pal_ranges,
+		.count  = ARRAY_SIZE(tuner_fm1216mk5_pal_ranges),
+		.cb_first_if_lower_freq = 1,
+		.has_tda9887 = 1,
+		.port1_active = 1,
+		.port2_active = 1,
+		.port2_invert_for_secam_lc = 1,
+		.port1_fm_high_sensitivity = 1,
+		.default_top_mid = -2,
+		.default_top_secam_mid = -2,
+		.default_top_secam_high = -2,
+	},
+};
+
 /* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
 
 static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
@@ -1254,6 +1279,28 @@
 	},
 };
 
+/* 80-89 */
+/* --------- TUNER_PHILIPS_FQ1216LME_MK3 -- active loopthrough, no FM ------- */
+
+static struct tuner_params tuner_fq1216lme_mk3_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_PAL,
+		.ranges = tuner_fm1216me_mk3_pal_ranges,
+		.count  = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
+		.cb_first_if_lower_freq = 1, /* not specified, but safe to do */
+		.has_tda9887 = 1, /* TDA9886 */
+		.port1_active = 1,
+		.port2_active = 1,
+		.port2_invert_for_secam_lc = 1,
+		.default_top_low = 4,
+		.default_top_mid = 4,
+		.default_top_high = 4,
+		.default_top_secam_low = 4,
+		.default_top_secam_mid = 4,
+		.default_top_secam_high = 4,
+	},
+};
+
 /* --------------------------------------------------------------------- */
 
 struct tunertype tuners[] = {
@@ -1694,6 +1741,18 @@
 		.initdata = tua603x_agc112,
 		.sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
 	},
+		[TUNER_PHILIPS_FM1216MK5] = { /* Philips PAL */
+		.name   = "Philips PAL/SECAM multi (FM1216 MK5)",
+		.params = tuner_fm1216mk5_params,
+		.count  = ARRAY_SIZE(tuner_fm1216mk5_params),
+	},
+
+	/* 80-89 */
+	[TUNER_PHILIPS_FQ1216LME_MK3] = { /* PAL/SECAM, Loop-thru, no FM */
+		.name = "Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough",
+		.params = tuner_fq1216lme_mk3_params,
+		.count  = ARRAY_SIZE(tuner_fq1216lme_mk3_params),
+	},
 };
 EXPORT_SYMBOL(tuners);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-xc2028.c linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-xc2028.c
--- linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-xc2028.c	2012-03-22 19:11:44.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-xc2028.c	2012-03-22 20:08:07.000000000 -0400
@@ -30,7 +30,7 @@
 
 static int no_poweroff;
 module_param(no_poweroff, int, 0644);
-MODULE_PARM_DESC(debug, "0 (default) powers device off when not used.\n"
+MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
 	"1 keep device energized and with tuner ready all the times.\n"
 	"  Faster, but consumes more power and keeps the device hotter\n");
 
@@ -48,7 +48,7 @@
 	"NICAM/A\n"
 	"NICAM/B\n");
 
-static char firmware_name[FIRMWARE_NAME_MAX];
+static char firmware_name[30];
 module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
 MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
 				"default firmware name\n");
@@ -272,7 +272,7 @@
 		fname = firmware_name;
 
 	tuner_dbg("Reading firmware %s\n", fname);
-	rc = reject_firmware(&fw, fname, &priv->i2c_props.adap->dev);
+	rc = reject_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
 	if (rc < 0) {
 		if (rc == -ENOENT)
 			tuner_err("Error: firmware %s not found.\n",
@@ -917,22 +917,29 @@
 	 * that xc2028 will be in a safe state.
 	 * Maybe this might also be needed for DTV.
 	 */
-	if (new_mode == T_ANALOG_TV) {
+	if (new_mode == T_ANALOG_TV)
 		rc = send_seq(priv, {0x00, 0x00});
-	} else if (priv->cur_fw.type & ATSC) {
-		offset = 1750000;
-	} else {
-		offset = 2750000;
+
+	/*
+	 * Digital modes require an offset to adjust to the
+	 * proper frequency.
+	 * Analog modes require offset = 0
+	 */
+	if (new_mode == T_DIGITAL_TV) {
+		/* Sets the offset according with firmware */
+		if (priv->cur_fw.type & DTV6)
+			offset = 1750000;
+		else if (priv->cur_fw.type & DTV7)
+			offset = 2250000;
+		else	/* DTV8 or DTV78 */
+			offset = 2750000;
+
 		/*
-		 * We must adjust the offset by 500kHz in two cases in order
-		 * to correctly center the IF output:
-		 * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly
-		 *    selected and a 7MHz channel is tuned;
-		 * 2) When tuning a VHF channel with DTV78 firmware.
+		 * We must adjust the offset by 500kHz  when
+		 * tuning a 7MHz VHF channel with DTV78 firmware
+		 * (used in Australia, Italy and Germany)
 		 */
-		if (((priv->cur_fw.type & DTV7) &&
-		     (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) ||
-		    ((priv->cur_fw.type & DTV78) && freq < 470000000))
+		if ((priv->cur_fw.type & DTV78) && freq < 470000000)
 			offset -= 500000;
 	}
 
@@ -991,7 +998,7 @@
 		if (priv->ctrl.input1)
 			type |= INPUT1;
 		return generic_set_freq(fe, (625l * p->frequency) / 10,
-				T_ANALOG_TV, type, 0, 0);
+				T_RADIO, type, 0, 0);
 	}
 
 	/* if std is not defined, choose one */
@@ -1022,21 +1029,20 @@
 	switch(fe->ops.info.type) {
 	case FE_OFDM:
 		bw = p->u.ofdm.bandwidth;
-		break;
-	case FE_QAM:
-		tuner_info("WARN: There are some reports that "
-			   "QAM 6 MHz doesn't work.\n"
-			   "If this works for you, please report by "
-			   "e-mail to: v4l-dvb-maintainer@linuxtv.org\n");
-		bw = BANDWIDTH_6_MHZ;
-		type |= QAM;
+		/*
+		 * The only countries with 6MHz seem to be Taiwan/Uruguay.
+		 * Both seem to require QAM firmware for OFDM decoding
+		 * Tested in Taiwan by Terry Wu <terrywu2009@gmail.com>
+		 */
+		if (bw == BANDWIDTH_6_MHZ)
+			type |= QAM;
 		break;
 	case FE_ATSC:
 		bw = BANDWIDTH_6_MHZ;
 		/* The only ATSC firmware (at least on v2.7) is D2633 */
 		type |= ATSC | D2633;
 		break;
-	/* DVB-S is not supported */
+	/* DVB-S and pure QAM (FE_QAM) are not supported */
 	default:
 		return -EINVAL;
 	}
@@ -1090,8 +1096,19 @@
 	}
 
 	/* All S-code tables need a 200kHz shift */
-	if (priv->ctrl.demod)
+	if (priv->ctrl.demod) {
 		demod = priv->ctrl.demod + 200;
+		/*
+		 * The DTV7 S-code table needs a 700 kHz shift.
+		 * Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this
+		 *
+		 * DTV7 is only used in Australia.  Germany or Italy may also
+		 * use this firmware after initialization, but a tune to a UHF
+		 * channel should then cause DTV78 to be used.
+		 */
+		if (type & DTV7)
+			demod += 500;
+	}
 
 	return generic_set_freq(fe, p->frequency,
 				T_DIGITAL_TV, type, 0, demod);
@@ -1102,8 +1119,8 @@
 	struct xc2028_data *priv = fe->tuner_priv;
 	int rc = 0;
 
-	/* Avoid firmware reload on slow devices */
-	if (no_poweroff)
+	/* Avoid firmware reload on slow devices or if PM disabled */
+	if (no_poweroff || priv->ctrl.disable_power_mgmt)
 		return 0;
 
 	tuner_dbg("Putting xc2028/3028 into poweroff mode.\n");
diff -druN linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-xc2028.h linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-xc2028.h
--- linux-libre-2.6.30-gnu/drivers/media/common/tuners/tuner-xc2028.h	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/common/tuners/tuner-xc2028.h	2012-03-22 20:08:07.000000000 -0400
@@ -38,6 +38,7 @@
 	unsigned int		input1:1;
 	unsigned int		vhfbw7:1;
 	unsigned int		uhfbw8:1;
+	unsigned int		disable_power_mgmt:1;
 	unsigned int		demod;
 	enum firmware_type	type:2;
 };
diff -druN linux-libre-2.6.30-gnu/drivers/media/common/tuners/xc5000.c linux-libre-2.6.31-gnu/drivers/media/common/tuners/xc5000.c
--- linux-libre-2.6.30-gnu/drivers/media/common/tuners/xc5000.c	2012-03-22 19:11:44.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/common/tuners/xc5000.c	2012-03-22 20:08:07.000000000 -0400
@@ -3,6 +3,7 @@
  *
  *  Copyright (c) 2007 Xceive Corporation
  *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
+ *  Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
  *
  *  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
@@ -36,6 +37,12 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+static int no_poweroff;
+module_param(no_poweroff, int, 0644);
+MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
+	"\t\t1 keep device energized and with tuner ready all the times.\n"
+	"\t\tFaster, but consumes more power and keeps the device hotter");
+
 static DEFINE_MUTEX(xc5000_list_mutex);
 static LIST_HEAD(hybrid_tuner_instance_list);
 
@@ -83,11 +90,11 @@
 #define XREG_D_CODE       0x04
 #define XREG_IF_OUT       0x05
 #define XREG_SEEK_MODE    0x07
-#define XREG_POWER_DOWN   0x0A
+#define XREG_POWER_DOWN   0x0A /* Obsolete */
 #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
 #define XREG_SMOOTHEDCVBS 0x0E
 #define XREG_XTALFREQ     0x0F
-#define XREG_FINERFFREQ   0x10
+#define XREG_FINERFREQ    0x10
 #define XREG_DDIMODE      0x11
 
 #define XREG_ADC_ENV      0x00
@@ -100,6 +107,7 @@
 #define XREG_VERSION      0x07
 #define XREG_PRODUCT_ID   0x08
 #define XREG_BUSY         0x09
+#define XREG_BUILD        0x0D
 
 /*
    Basic firmware description. This will remain with
@@ -191,27 +199,36 @@
 	{"FM Radio-INPUT1",   0x0208, 0x9002}
 };
 
-static int  xc5000_is_firmware_loaded(struct dvb_frontend *fe);
-static int  xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
-static int  xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
-static void xc5000_TunerReset(struct dvb_frontend *fe);
+static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
+static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
+static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
+static int xc5000_TunerReset(struct dvb_frontend *fe);
 
 static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
 {
-	return xc5000_writeregs(priv, buf, len)
-		? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS;
+	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
+			       .flags = 0, .buf = buf, .len = len };
+
+	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
+		printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len);
+		return XC_RESULT_I2C_WRITE_FAILURE;
+	}
+	return XC_RESULT_SUCCESS;
 }
 
+/* This routine is never used because the only time we read data from the
+   i2c bus is when we read registers, and we want that to be an atomic i2c
+   transaction in case we are on a multi-master bus */
 static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
 {
-	return xc5000_readregs(priv, buf, len)
-		? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS;
-}
+	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
+		.flags = I2C_M_RD, .buf = buf, .len = len };
 
-static int xc_reset(struct dvb_frontend *fe)
-{
-	xc5000_TunerReset(fe);
-	return XC_RESULT_SUCCESS;
+	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
+		printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len);
+		return -EREMOTEIO;
+	}
+	return 0;
 }
 
 static void xc_wait(int wait_ms)
@@ -219,7 +236,7 @@
 	msleep(wait_ms);
 }
 
-static void xc5000_TunerReset(struct dvb_frontend *fe)
+static int xc5000_TunerReset(struct dvb_frontend *fe)
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret;
@@ -232,16 +249,21 @@
 					   priv->i2c_props.adap->algo_data,
 					   DVB_FRONTEND_COMPONENT_TUNER,
 					   XC5000_TUNER_RESET, 0);
-		if (ret)
+		if (ret) {
 			printk(KERN_ERR "xc5000: reset failed\n");
-	} else
+			return XC_RESULT_RESET_FAILURE;
+		}
+	} else {
 		printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
+		return XC_RESULT_RESET_FAILURE;
+	}
+	return XC_RESULT_SUCCESS;
 }
 
 static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
 {
 	u8 buf[4];
-	int WatchDogTimer = 5;
+	int WatchDogTimer = 100;
 	int result;
 
 	buf[0] = (regAddr >> 8) & 0xFF;
@@ -263,7 +285,7 @@
 						/* busy flag cleared */
 					break;
 					} else {
-						xc_wait(100); /* wait 5 ms */
+						xc_wait(5); /* wait 5 ms */
 						WatchDogTimer--;
 					}
 				}
@@ -276,25 +298,6 @@
 	return result;
 }
 
-static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
-{
-	u8 buf[2];
-	int result;
-
-	buf[0] = (regAddr >> 8) & 0xFF;
-	buf[1] = regAddr & 0xFF;
-	result = xc_send_i2c_data(priv, buf, 2);
-	if (result != XC_RESULT_SUCCESS)
-		return result;
-
-	result = xc_read_i2c_data(priv, buf, 2);
-	if (result != XC_RESULT_SUCCESS)
-		return result;
-
-	*i2cData = buf[0] * 256 + buf[1];
-	return result;
-}
-
 static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
@@ -309,7 +312,7 @@
 		len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
 		if (len == 0x0000) {
 			/* RESET command */
-			result = xc_reset(fe);
+			result = xc5000_TunerReset(fe);
 			index += 2;
 			if (result != XC_RESULT_SUCCESS)
 				return result;
@@ -371,15 +374,6 @@
 	return ret;
 }
 
-static int xc_shutdown(struct xc5000_priv *priv)
-{
-	return XC_RESULT_SUCCESS;
-	/* Fixme: cannot bring tuner back alive once shutdown
-	 *        without reloading the driver modules.
-	 *    return xc_write_reg(priv, XREG_POWER_DOWN, 0);
-	 */
-}
-
 static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
 {
 	dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
@@ -408,7 +402,10 @@
 
 	freq_code = (u16)(freq_hz / 15625);
 
-	return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
+	/* Starting in firmware version 1.1.44, Xceive recommends using the
+	   FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
+	   only be used for fast scanning for channel lock) */
+	return xc_write_reg(priv, XREG_FINERFREQ, freq_code);
 }
 
 
@@ -424,7 +421,7 @@
 
 static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
 {
-	return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope);
+	return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope);
 }
 
 static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
@@ -433,8 +430,8 @@
 	u16 regData;
 	u32 tmp;
 
-	result = xc_read_reg(priv, XREG_FREQ_ERROR, &regData);
-	if (result)
+	result = xc5000_readreg(priv, XREG_FREQ_ERROR, &regData);
+	if (result != XC_RESULT_SUCCESS)
 		return result;
 
 	tmp = (u32)regData;
@@ -444,7 +441,7 @@
 
 static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
 {
-	return xc_read_reg(priv, XREG_LOCK, lock_status);
+	return xc5000_readreg(priv, XREG_LOCK, lock_status);
 }
 
 static int xc_get_version(struct xc5000_priv *priv,
@@ -454,8 +451,8 @@
 	u16 data;
 	int result;
 
-	result = xc_read_reg(priv, XREG_VERSION, &data);
-	if (result)
+	result = xc5000_readreg(priv, XREG_VERSION, &data);
+	if (result != XC_RESULT_SUCCESS)
 		return result;
 
 	(*hw_majorversion) = (data >> 12) & 0x0F;
@@ -466,13 +463,18 @@
 	return 0;
 }
 
+static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev)
+{
+	return xc5000_readreg(priv, XREG_BUILD, buildrev);
+}
+
 static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
 {
 	u16 regData;
 	int result;
 
-	result = xc_read_reg(priv, XREG_HSYNC_FREQ, &regData);
-	if (result)
+	result = xc5000_readreg(priv, XREG_HSYNC_FREQ, &regData);
+	if (result != XC_RESULT_SUCCESS)
 		return result;
 
 	(*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
@@ -481,12 +483,12 @@
 
 static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
 {
-	return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines);
+	return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines);
 }
 
 static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
 {
-	return xc_read_reg(priv, XREG_QUALITY, quality);
+	return xc5000_readreg(priv, XREG_QUALITY, quality);
 }
 
 static u16 WaitForLock(struct xc5000_priv *priv)
@@ -504,7 +506,9 @@
 	return lockState;
 }
 
-static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
+#define XC_TUNE_ANALOG  0
+#define XC_TUNE_DIGITAL 1
+static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
 {
 	int found = 0;
 
@@ -513,8 +517,10 @@
 	if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
 		return 0;
 
-	if (WaitForLock(priv) == 1)
-		found = 1;
+	if (mode == XC_TUNE_ANALOG) {
+		if (WaitForLock(priv) == 1)
+			found = 1;
+	}
 
 	return found;
 }
@@ -536,32 +542,7 @@
 	}
 
 	*val = (bval[0] << 8) | bval[1];
-	return 0;
-}
-
-static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
-{
-	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
-		.flags = 0, .buf = buf, .len = len };
-
-	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
-		printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
-			(int)len);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
-{
-	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
-		.flags = I2C_M_RD, .buf = buf, .len = len };
-
-	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
-		printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", (int)len);
-		return -EREMOTEIO;
-	}
-	return 0;
+	return XC_RESULT_SUCCESS;
 }
 
 static int xc5000_fwupload(struct dvb_frontend *fe)
@@ -575,13 +556,13 @@
 		"/*(DEBLOBBED)*/");
 
 	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
-		&priv->i2c_props.adap->dev);
+		priv->i2c_props.adap->dev.parent);
 	if (ret) {
 		printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
 		ret = XC_RESULT_RESET_FAILURE;
 		goto out;
 	} else {
-		printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n",
+		printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
 		       fw->size);
 		ret = XC_RESULT_SUCCESS;
 	}
@@ -590,8 +571,9 @@
 		printk(KERN_ERR "xc5000: firmware incorrect size\n");
 		ret = XC_RESULT_RESET_FAILURE;
 	} else {
-		printk(KERN_INFO "xc5000: firmware upload\n");
+		printk(KERN_INFO "xc5000: firmware uploading...\n");
 		ret = xc_load_i2c_sequence(fe,  fw->data);
+		printk(KERN_INFO "xc5000: firmware upload complete...\n");
 	}
 
 out:
@@ -609,6 +591,7 @@
 	u16 quality;
 	u8 hw_majorversion = 0, hw_minorversion = 0;
 	u8 fw_majorversion = 0, fw_minorversion = 0;
+	u16 fw_buildversion = 0;
 
 	/* Wait for stats to stabilize.
 	 * Frame Lines needs two frame times after initial lock
@@ -628,9 +611,10 @@
 
 	xc_get_version(priv,  &hw_majorversion, &hw_minorversion,
 		&fw_majorversion, &fw_minorversion);
-	dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
+	xc_get_buildversion(priv,  &fw_buildversion);
+	dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n",
 		hw_majorversion, hw_minorversion,
-		fw_majorversion, fw_minorversion);
+		fw_majorversion, fw_minorversion, fw_buildversion);
 
 	xc_get_hsync_freq(priv,  &hsync_freq_hz);
 	dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
@@ -648,27 +632,57 @@
 	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret;
 
+	if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
+		xc_load_fw_and_init_tuner(fe);
+
 	dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
 
-	switch (params->u.vsb.modulation) {
-	case VSB_8:
-	case VSB_16:
-		dprintk(1, "%s() VSB modulation\n", __func__);
+	if (fe->ops.info.type == FE_ATSC) {
+		dprintk(1, "%s() ATSC\n", __func__);
+		switch (params->u.vsb.modulation) {
+		case VSB_8:
+		case VSB_16:
+			dprintk(1, "%s() VSB modulation\n", __func__);
+			priv->rf_mode = XC_RF_MODE_AIR;
+			priv->freq_hz = params->frequency - 1750000;
+			priv->bandwidth = BANDWIDTH_6_MHZ;
+			priv->video_standard = DTV6;
+			break;
+		case QAM_64:
+		case QAM_256:
+		case QAM_AUTO:
+			dprintk(1, "%s() QAM modulation\n", __func__);
+			priv->rf_mode = XC_RF_MODE_CABLE;
+			priv->freq_hz = params->frequency - 1750000;
+			priv->bandwidth = BANDWIDTH_6_MHZ;
+			priv->video_standard = DTV6;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else if (fe->ops.info.type == FE_OFDM) {
+		dprintk(1, "%s() OFDM\n", __func__);
+		switch (params->u.ofdm.bandwidth) {
+		case BANDWIDTH_6_MHZ:
+			priv->bandwidth = BANDWIDTH_6_MHZ;
+			priv->video_standard = DTV6;
+			priv->freq_hz = params->frequency - 1750000;
+			break;
+		case BANDWIDTH_7_MHZ:
+			printk(KERN_ERR "xc5000 bandwidth 7MHz not supported\n");
+			return -EINVAL;
+		case BANDWIDTH_8_MHZ:
+			priv->bandwidth = BANDWIDTH_8_MHZ;
+			priv->video_standard = DTV8;
+			priv->freq_hz = params->frequency - 2750000;
+			break;
+		default:
+			printk(KERN_ERR "xc5000 bandwidth not set!\n");
+			return -EINVAL;
+		}
 		priv->rf_mode = XC_RF_MODE_AIR;
-		priv->freq_hz = params->frequency - 1750000;
-		priv->bandwidth = BANDWIDTH_6_MHZ;
-		priv->video_standard = DTV6;
-		break;
-	case QAM_64:
-	case QAM_256:
-	case QAM_AUTO:
-		dprintk(1, "%s() QAM modulation\n", __func__);
-		priv->rf_mode = XC_RF_MODE_CABLE;
-		priv->freq_hz = params->frequency - 1750000;
-		priv->bandwidth = BANDWIDTH_6_MHZ;
-		priv->video_standard = DTV6;
-		break;
-	default:
+	} else {
+		printk(KERN_ERR "xc5000 modulation type not supported!\n");
 		return -EINVAL;
 	}
 
@@ -698,7 +712,7 @@
 		return -EIO;
 	}
 
-	xc_tune_channel(priv, priv->freq_hz);
+	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
 
 	if (debug)
 		xc_debug_dump(priv);
@@ -725,8 +739,6 @@
 	return ret;
 }
 
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
-
 static int xc5000_set_analog_params(struct dvb_frontend *fe,
 	struct analog_parameters *params)
 {
@@ -807,7 +819,7 @@
 		return -EREMOTEIO;
 	}
 
-	xc_tune_channel(priv, priv->freq_hz);
+	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
 
 	if (debug)
 		xc_debug_dump(priv);
@@ -875,18 +887,18 @@
 
 static int xc5000_sleep(struct dvb_frontend *fe)
 {
-	struct xc5000_priv *priv = fe->tuner_priv;
 	int ret;
 
 	dprintk(1, "%s()\n", __func__);
 
-	/* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
-	 * once shutdown without reloading the driver. Maybe I am not
-	 * doing something right.
-	 *
-	 */
+	/* Avoid firmware reload on slow devices */
+	if (no_poweroff)
+		return 0;
 
-	ret = xc_shutdown(priv);
+	/* According to Xceive technical support, the "powerdown" register
+	   was removed in newer versions of the firmware.  The "supported"
+	   way to sleep the tuner is to pull the reset pin low for 10ms */
+	ret = xc5000_TunerReset(fe);
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR
 			"xc5000: %s() unable to shutdown tuner\n",
@@ -991,7 +1003,7 @@
 	/* Check if firmware has been loaded. It is possible that another
 	   instance of the driver has loaded the firmware.
 	 */
-	if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
+	if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
 		goto fail;
 
 	switch (id) {
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-common.h linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-common.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-common.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,9 +1,7 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-common.h - common header file for device-specific source files also.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-common.h - common header file for device-specific source files
+ * see flexcop.c for copyright information
  */
 #ifndef __FLEXCOP_COMMON_H__
 #define __FLEXCOP_COMMON_H__
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-fe-tuner.c linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-fe-tuner.c	2012-03-22 19:11:47.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-fe-tuner.c	2012-03-22 20:08:10.000000000 -0400
@@ -1,34 +1,33 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling
+ * see flexcop.c for copyright information
  */
 #include <media/tuner.h>
-
 #include "flexcop.h"
-
+#include "mt312.h"
 #include "stv0299.h"
+#include "s5h1420.h"
+#include "itd1000.h"
+#include "cx24113.h"
+#include "cx24123.h"
+#include "isl6421.h"
 #include "mt352.h"
-#include "nxt200x.h"
 #include "bcm3510.h"
-#include "stv0297.h"
-#include "mt312.h"
-#include "lgdt330x.h"
+#include "nxt200x.h"
 #include "dvb-pll.h"
+#include "lgdt330x.h"
 #include "tuner-simple.h"
+#include "stv0297.h"
 
-#include "s5h1420.h"
-#include "itd1000.h"
-
-#include "cx24123.h"
-#include "cx24113.h"
 
-#include "isl6421.h"
+/* Can we use the specified front-end?  Remember that if we are compiled
+ * into the kernel we can't call code that's in modules.  */
+#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
+	(defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
 
 /* lnb control */
-
+#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
 static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
 	struct flexcop_device *fc = fe->dvb->priv;
@@ -37,65 +36,61 @@
 
 	v = fc->read_ibi_reg(fc, misc_204);
 	switch (voltage) {
-		case SEC_VOLTAGE_OFF:
-			v.misc_204.ACPI1_sig = 1;
-			break;
-		case SEC_VOLTAGE_13:
-			v.misc_204.ACPI1_sig = 0;
-			v.misc_204.LNB_L_H_sig = 0;
-			break;
-		case SEC_VOLTAGE_18:
-			v.misc_204.ACPI1_sig = 0;
-			v.misc_204.LNB_L_H_sig = 1;
-			break;
-		default:
-			err("unknown SEC_VOLTAGE value");
-			return -EINVAL;
+	case SEC_VOLTAGE_OFF:
+		v.misc_204.ACPI1_sig = 1;
+		break;
+	case SEC_VOLTAGE_13:
+		v.misc_204.ACPI1_sig = 0;
+		v.misc_204.LNB_L_H_sig = 0;
+		break;
+	case SEC_VOLTAGE_18:
+		v.misc_204.ACPI1_sig = 0;
+		v.misc_204.LNB_L_H_sig = 1;
+		break;
+	default:
+		err("unknown SEC_VOLTAGE value");
+		return -EINVAL;
 	}
 	return fc->write_ibi_reg(fc, misc_204, v);
 }
+#endif
 
+#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
 static int flexcop_sleep(struct dvb_frontend* fe)
 {
 	struct flexcop_device *fc = fe->dvb->priv;
-/*	flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */
-
 	if (fc->fe_sleep)
 		return fc->fe_sleep(fe);
-
-/*	v.misc_204.ACPI3_sig = 1;
-	fc->write_ibi_reg(fc,misc_204,v);*/
-
 	return 0;
 }
+#endif
 
+/* SkyStar2 DVB-S rev 2.3 */
+#if FE_SUPPORTED(MT312)
 static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 {
-	/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
+/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
 	struct flexcop_device *fc = fe->dvb->priv;
 	flexcop_ibi_value v;
 	u16 ax;
 	v.raw = 0;
-
 	deb_tuner("tone = %u\n",tone);
 
 	switch (tone) {
-		case SEC_TONE_ON:
-			ax = 0x01ff;
-			break;
-		case SEC_TONE_OFF:
-			ax = 0;
-			break;
-		default:
-			err("unknown SEC_TONE value");
-			return -EINVAL;
+	case SEC_TONE_ON:
+		ax = 0x01ff;
+		break;
+	case SEC_TONE_OFF:
+		ax = 0;
+		break;
+	default:
+		err("unknown SEC_TONE value");
+		return -EINVAL;
 	}
 
 	v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
-
 	v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
 	v.lnb_switch_freq_200.LNB_CTLLowCount_sig  = ax == 0 ? 0x1ff : ax;
-
 	return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
 }
 
@@ -110,17 +105,16 @@
 static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
 {
 	int i, par = 1, d;
-
 	for (i = 7; i >= 0; i--) {
 		d = (data >> i) & 1;
 		par ^= d;
 		flexcop_diseqc_send_bit(fe, d);
 	}
-
 	flexcop_diseqc_send_bit(fe, par);
 }
 
-static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst)
+static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
+	int len, u8 *msg, unsigned long burst)
 {
 	int i;
 
@@ -129,7 +123,6 @@
 
 	for (i = 0; i < len; i++)
 		flexcop_diseqc_send_byte(fe,msg[i]);
-
 	mdelay(16);
 
 	if (burst != -1) {
@@ -146,50 +139,112 @@
 	return 0;
 }
 
-static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *cmd)
 {
 	return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
 }
 
-static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+static int flexcop_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t minicmd)
 {
 	return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
 }
 
-/* dvb-s stv0299 */
-static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
+static struct mt312_config skystar23_samsung_tbdu18132_config = {
+	.demod_address = 0x0e,
+};
+
+static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
+{
+	u8 buf[4];
+	u32 div;
+	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf,
+	.len = sizeof(buf) };
+	struct flexcop_device *fc = fe->dvb->priv;
+	div = (params->frequency + (125/2)) / 125;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = (div >> 0) & 0xff;
+	buf[2] = 0x84 | ((div >> 10) & 0x60);
+	buf[3] = 0x80;
+
+	if (params->frequency < 1550000)
+		buf[3] |= 0x02;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
+		return -EIO;
+	return 0;
+}
+
+static int skystar2_rev23_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
+	if (fc->fe != NULL) {
+		struct dvb_frontend_ops *ops = &fc->fe->ops;
+		ops->tuner_ops.set_params   =
+			skystar23_samsung_tbdu18132_tuner_set_params;
+		ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
+		ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
+		ops->set_tone               = flexcop_set_tone;
+		ops->set_voltage            = flexcop_set_voltage;
+		fc->fe_sleep                = ops->sleep;
+		ops->sleep                  = flexcop_sleep;
+		return 1;
+	}
+	return 0;
+}
+#else
+#define skystar2_rev23_attach NULL
+#endif
+
+/* SkyStar2 DVB-S rev 2.6 */
+#if FE_SUPPORTED(STV0299)
+static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
+	u32 srate, u32 ratio)
 {
 	u8 aclk = 0;
 	u8 bclk = 0;
 
-	if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
-	else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
-	else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
-	else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
-	else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
-	else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
-
-	stv0299_writereg (fe, 0x13, aclk);
-	stv0299_writereg (fe, 0x14, bclk);
-	stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg (fe, 0x20, (ratio >>  8) & 0xff);
-	stv0299_writereg (fe, 0x21, (ratio      ) & 0xf0);
+	if (srate < 1500000) {
+		aclk = 0xb7; bclk = 0x47;
+	} else if (srate < 3000000) {
+		aclk = 0xb7; bclk = 0x4b;
+	} else if (srate < 7000000) {
+		aclk = 0xb7; bclk = 0x4f;
+	} else if (srate < 14000000) {
+		aclk = 0xb7; bclk = 0x53;
+	} else if (srate < 30000000) {
+		aclk = 0xb6; bclk = 0x53;
+	} else if (srate < 45000000) {
+		aclk = 0xb4; bclk = 0x51;
+	}
 
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
+	stv0299_writereg(fe, 0x21,  ratio        & 0xf0);
 	return 0;
 }
 
-static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
 {
 	u8 buf[4];
 	u32 div;
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	struct i2c_msg msg = {
+	.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
 	struct flexcop_device *fc = fe->dvb->priv;
-
 	div = params->frequency / 125;
 
 	buf[0] = (div >> 8) & 0x7f;
 	buf[1] = div & 0xff;
-	buf[2] = 0x84;  /* 0xC4 */
+	buf[2] = 0x84; /* 0xC4 */
 	buf[3] = 0x08;
 
 	if (params->frequency < 1500000)
@@ -203,48 +258,48 @@
 }
 
 static u8 samsung_tbmu24112_inittab[] = {
-	     0x01, 0x15,
-	     0x02, 0x30,
-	     0x03, 0x00,
-	     0x04, 0x7D,
-	     0x05, 0x35,
-	     0x06, 0x02,
-	     0x07, 0x00,
-	     0x08, 0xC3,
-	     0x0C, 0x00,
-	     0x0D, 0x81,
-	     0x0E, 0x23,
-	     0x0F, 0x12,
-	     0x10, 0x7E,
-	     0x11, 0x84,
-	     0x12, 0xB9,
-	     0x13, 0x88,
-	     0x14, 0x89,
-	     0x15, 0xC9,
-	     0x16, 0x00,
-	     0x17, 0x5C,
-	     0x18, 0x00,
-	     0x19, 0x00,
-	     0x1A, 0x00,
-	     0x1C, 0x00,
-	     0x1D, 0x00,
-	     0x1E, 0x00,
-	     0x1F, 0x3A,
-	     0x20, 0x2E,
-	     0x21, 0x80,
-	     0x22, 0xFF,
-	     0x23, 0xC1,
-	     0x28, 0x00,
-	     0x29, 0x1E,
-	     0x2A, 0x14,
-	     0x2B, 0x0F,
-	     0x2C, 0x09,
-	     0x2D, 0x05,
-	     0x31, 0x1F,
-	     0x32, 0x19,
-	     0x33, 0xFE,
-	     0x34, 0x93,
-	     0xff, 0xff,
+	0x01, 0x15,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x7D,
+	0x05, 0x35,
+	0x06, 0x02,
+	0x07, 0x00,
+	0x08, 0xC3,
+	0x0C, 0x00,
+	0x0D, 0x81,
+	0x0E, 0x23,
+	0x0F, 0x12,
+	0x10, 0x7E,
+	0x11, 0x84,
+	0x12, 0xB9,
+	0x13, 0x88,
+	0x14, 0x89,
+	0x15, 0xC9,
+	0x16, 0x00,
+	0x17, 0x5C,
+	0x18, 0x00,
+	0x19, 0x00,
+	0x1A, 0x00,
+	0x1C, 0x00,
+	0x1D, 0x00,
+	0x1E, 0x00,
+	0x1F, 0x3A,
+	0x20, 0x2E,
+	0x21, 0x80,
+	0x22, 0xFF,
+	0x23, 0xC1,
+	0x28, 0x00,
+	0x29, 0x1E,
+	0x2A, 0x14,
+	0x2B, 0x0F,
+	0x2C, 0x09,
+	0x2D, 0x05,
+	0x31, 0x1F,
+	0x32, 0x19,
+	0x33, 0xFE,
+	0x34, 0x93,
+	0xff, 0xff,
 };
 
 static struct stv0299_config samsung_tbmu24112_config = {
@@ -259,27 +314,161 @@
 	.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
 };
 
-/* dvb-t mt352 */
-static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
+static int skystar2_rev26_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
 {
-	static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d };
-	static u8 mt352_reset [] = { 0x50, 0x80 };
-	static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-	static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 };
+	fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
+	if (fc->fe != NULL) {
+		struct dvb_frontend_ops *ops  = &fc->fe->ops;
+		ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
+		ops->set_voltage = flexcop_set_voltage;
+		fc->fe_sleep = ops->sleep;
+		ops->sleep = flexcop_sleep;
+		return 1;
+	}
+	return 0;
+}
+#else
+#define skystar2_rev26_attach NULL
+#endif
+
+/* SkyStar2 DVB-S rev 2.7 */
+#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
+static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
+	.demod_address = 0x53,
+	.invert = 1,
+	.repeated_start_workaround = 1,
+	.serial_mpeg = 1,
+};
+
+static struct itd1000_config skystar2_rev2_7_itd1000_config = {
+	.i2c_address = 0x61,
+};
+
+static int skystar2_rev27_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	flexcop_ibi_value r108;
+	struct i2c_adapter *i2c_tuner;
+
+	/* enable no_base_addr - no repeated start when reading */
+	fc->fc_i2c_adap[0].no_base_addr = 1;
+	fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
+			    i2c);
+	if (!fc->fe)
+		goto fail;
+
+	i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+	if (!i2c_tuner)
+		goto fail;
+
+	fc->fe_sleep = fc->fe->ops.sleep;
+	fc->fe->ops.sleep = flexcop_sleep;
+
+	/* enable no_base_addr - no repeated start when reading */
+	fc->fc_i2c_adap[2].no_base_addr = 1;
+	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+			0x08, 1, 1)) {
+		err("ISL6421 could NOT be attached");
+		goto fail_isl;
+	}
+	info("ISL6421 successfully attached");
+
+	/* the ITD1000 requires a lower i2c clock - is it a problem ? */
+	r108.raw = 0x00000506;
+	fc->write_ibi_reg(fc, tw_sm_c_108, r108);
+	if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
+			&skystar2_rev2_7_itd1000_config)) {
+		err("ITD1000 could NOT be attached");
+		/* Should i2c clock be restored? */
+		goto fail_isl;
+	}
+	info("ITD1000 successfully attached");
+
+	return 1;
+
+fail_isl:
+	fc->fc_i2c_adap[2].no_base_addr = 0;
+fail:
+	/* for the next devices we need it again */
+	fc->fc_i2c_adap[0].no_base_addr = 0;
+	return 0;
+}
+#else
+#define skystar2_rev27_attach NULL
+#endif
+
+/* SkyStar2 rev 2.8 */
+#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
+static struct cx24123_config skystar2_rev2_8_cx24123_config = {
+	.demod_address = 0x55,
+	.dont_use_pll = 1,
+	.agc_callback = cx24113_agc_callback,
+};
+
+static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
+	.i2c_addr = 0x54,
+	.xtal_khz = 10111,
+};
+
+static int skystar2_rev28_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	struct i2c_adapter *i2c_tuner;
+
+	fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
+			    i2c);
+	if (!fc->fe)
+		return 0;
+
+	i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);;
+	if (!i2c_tuner)
+		return 0;
+
+	if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
+			i2c_tuner)) {
+		err("CX24113 could NOT be attached");
+		return 0;
+	}
+	info("CX24113 successfully attached");
+
+	fc->fc_i2c_adap[2].no_base_addr = 1;
+	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+			0x08, 0, 0)) {
+		err("ISL6421 could NOT be attached");
+		fc->fc_i2c_adap[2].no_base_addr = 0;
+		return 0;
+	}
+	info("ISL6421 successfully attached");
+	/* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
+	 * IR-receiver (PIC16F818) - but the card has no input for that ??? */
+	return 1;
+}
+#else
+#define skystar2_rev28_attach NULL
+#endif
+
+/* AirStar DVB-T */
+#if FE_SUPPORTED(MT352)
+static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
+{
+	static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
+	static u8 mt352_reset[] = { 0x50, 0x80 };
+	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
+	static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
 	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
 
 	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
 	udelay(2000);
 	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
 	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-
 	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
 	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
-
 	return 0;
 }
 
-static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
+static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
 {
 	u32 div;
 	unsigned char bs = 0;
@@ -287,19 +476,20 @@
 	if (buf_len < 5)
 		return -EINVAL;
 
-	#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
+#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
-	if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09;
-	if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
-	if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
+	if (params->frequency >= 48000000 && params->frequency <= 154000000) \
+		bs = 0x09;
+	if (params->frequency >= 161000000 && params->frequency <= 439000000) \
+		bs = 0x0a;
+	if (params->frequency >= 447000000 && params->frequency <= 863000000) \
+		bs = 0x08;
 
 	pllbuf[0] = 0x61;
 	pllbuf[1] = div >> 8;
 	pllbuf[2] = div & 0xff;
 	pllbuf[3] = 0xcc;
 	pllbuf[4] = bs;
-
 	return 5;
 }
 
@@ -308,70 +498,103 @@
 	.demod_init    = samsung_tdtc9251dh0_demod_init,
 };
 
-static int flexcop_fe_reject_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
+static int airstar_dvbt_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
+	if (fc->fe != NULL) {
+		fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
+		return 1;
+	}
+	return 0;
+}
+#else
+#define airstar_dvbt_attach NULL
+#endif
+
+/* AirStar ATSC 1st generation */
+#if FE_SUPPORTED(BCM3510)
+static int flexcop_fe_reject_firmware(struct dvb_frontend *fe,
+	const struct firmware **fw, char* name)
 {
 	struct flexcop_device *fc = fe->dvb->priv;
 	return reject_firmware(fw, name, fc->dev);
 }
 
-static struct lgdt330x_config air2pc_atsc_hd5000_config = {
-	.demod_address       = 0x59,
-	.demod_chip          = LGDT3303,
-	.serial_mpeg         = 0x04,
-	.clock_polarity_flip = 1,
-};
-
-static struct nxt200x_config samsung_tbmv_config = {
-	.demod_address    = 0x0a,
-};
-
 static struct bcm3510_config air2pc_atsc_first_gen_config = {
 	.demod_address    = 0x0f,
 	.reject_firmware = flexcop_fe_reject_firmware,
 };
 
-static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int airstar_atsc1_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
 {
-	u8 buf[4];
-	u32 div;
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-	struct flexcop_device *fc = fe->dvb->priv;
-
-	div = (params->frequency + (125/2)) / 125;
+	fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
+	return fc->fe != NULL;
+}
+#else
+#define airstar_atsc1_attach NULL
+#endif
 
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = (div >> 0) & 0xff;
-	buf[2] = 0x84 | ((div >> 10) & 0x60);
-	buf[3] = 0x80;
+/* AirStar ATSC 2nd generation */
+#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
+static struct nxt200x_config samsung_tbmv_config = {
+	.demod_address = 0x0a,
+};
 
-	if (params->frequency < 1550000)
-		buf[3] |= 0x02;
+static int airstar_atsc2_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
+	if (!fc->fe)
+		return 0;
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
+	return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
+			    DVB_PLL_SAMSUNG_TBMV);
 }
+#else
+#define airstar_atsc2_attach NULL
+#endif
 
-static struct mt312_config skystar23_samsung_tbdu18132_config = {
-
-	.demod_address = 0x0e,
+/* AirStar ATSC 3rd generation */
+#if FE_SUPPORTED(LGDT330X)
+static struct lgdt330x_config air2pc_atsc_hd5000_config = {
+	.demod_address       = 0x59,
+	.demod_chip          = LGDT3303,
+	.serial_mpeg         = 0x04,
+	.clock_polarity_flip = 1,
 };
 
+static int airstar_atsc3_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
+	if (!fc->fe)
+		return 0;
+
+	return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
+			    TUNER_LG_TDVS_H06XF);
+}
+#else
+#define airstar_atsc3_attach NULL
+#endif
+
+/* CableStar2 DVB-C */
+#if FE_SUPPORTED(STV0297)
 static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
-					       struct dvb_frontend_parameters *fep)
+		struct dvb_frontend_parameters *fep)
 {
 	struct flexcop_device *fc = fe->dvb->priv;
 	u8 buf[4];
 	u16 div;
 	int ret;
 
-/*  62.5 kHz * 10 */
+/* 62.5 kHz * 10 */
 #define REF_FREQ    625
 #define FREQ_OFFSET 36125
 
-	div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10)  / REF_FREQ; // 4 MHz = 4000 KHz
+	div = ((fep->frequency/1000 + FREQ_OFFSET) * 10) / REF_FREQ;
+/* 4 MHz = 4000 KHz */
 
 	buf[0] = (u8)( div >> 8) & 0x7f;
 	buf[1] = (u8)        div & 0xff;
@@ -384,11 +607,11 @@
  * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
 	buf[2] = 0x95;
 
-// Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
-//  47 - 153   0  *  0   0   0   0   0   1   0x01
-// 153 - 430   0  *  0   0   0   0   1   0   0x02
-// 430 - 822   0  *  0   0   1   0   0   0   0x08
-// 822 - 862   1  *  0   0   1   0   0   0   0x88
+/* Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
+ *  47 - 153   0  *  0   0   0   0   0   1   0x01
+ * 153 - 430   0  *  0   0   0   0   1   0   0x02
+ * 430 - 822   0  *  0   0   1   0   0   0   0x08
+ * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
 
 	     if (fep->frequency <= 153000000) buf[3] = 0x01;
 	else if (fep->frequency <= 430000000) buf[3] = 0x02;
@@ -397,11 +620,11 @@
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
-	deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
+	deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n", fep->frequency,
+	buf[0], buf[1], buf[2], buf[3]);
 	ret = fc->i2c_request(&fc->fc_i2c_adap[2],
-		FC_WRITE, 0x61, buf[0], &buf[1], 3);
+			FC_WRITE, 0x61, buf[0], &buf[1], 3);
 	deb_tuner("tuner write returned: %d\n",ret);
-
 	return ret;
 }
 
@@ -481,182 +704,59 @@
 static struct stv0297_config alps_tdee4_stv0297_config = {
 	.demod_address = 0x1c,
 	.inittab = alps_tdee4_stv0297_inittab,
-//	.invert = 1,
-//	.pll_set = alps_tdee4_stv0297_pll_set,
-};
-
-
-/* SkyStar2 rev2.7 (a/u) */
-static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
-	.demod_address = 0x53,
-	.invert = 1,
-	.repeated_start_workaround = 1,
-	.serial_mpeg = 1,
-};
-
-static struct itd1000_config skystar2_rev2_7_itd1000_config = {
-	.i2c_address = 0x61,
 };
 
-/* SkyStar2 rev2.8 */
-static struct cx24123_config skystar2_rev2_8_cx24123_config = {
-	.demod_address = 0x55,
-	.dont_use_pll = 1,
-	.agc_callback = cx24113_agc_callback,
-};
-
-static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
-	.i2c_addr = 0x54,
-	.xtal_khz = 10111,
-};
-
-/* try to figure out the frontend, each card/box can have on of the following list */
-int flexcop_frontend_init(struct flexcop_device *fc)
+static int cablestar2_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
 {
-	struct dvb_frontend_ops *ops;
-	struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
-	struct i2c_adapter *i2c_tuner;
-
-	/* enable no_base_addr - no repeated start when reading */
-	fc->fc_i2c_adap[0].no_base_addr = 1;
-	fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
-	if (fc->fe != NULL) {
-		flexcop_ibi_value r108;
-		i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
-		ops = &fc->fe->ops;
-
-		fc->fe_sleep = ops->sleep;
-		ops->sleep   = flexcop_sleep;
-
-		fc->dev_type = FC_SKY_REV27;
-
-		/* enable no_base_addr - no repeated start when reading */
-		fc->fc_i2c_adap[2].no_base_addr = 1;
-		if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
-			err("ISL6421 could NOT be attached");
-		else
-			info("ISL6421 successfully attached");
-
-		/* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
-		r108.raw = 0x00000506;
-		fc->write_ibi_reg(fc, tw_sm_c_108, r108);
-		if (i2c_tuner) {
-			if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
-				err("ITD1000 could NOT be attached");
-			else
-				info("ITD1000 successfully attached");
-		}
-		goto fe_found;
-	}
-	fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
-
-	/* try the sky v2.8 (cx24123, isl6421) */
-	fc->fe = dvb_attach(cx24123_attach,
-		&skystar2_rev2_8_cx24123_config, i2c);
-	if (fc->fe != NULL) {
-		i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
-		if (i2c_tuner != NULL) {
-			if (dvb_attach(cx24113_attach, fc->fe,
-					&skystar2_rev2_8_cx24113_config,
-					i2c_tuner) == NULL)
-				err("CX24113 could NOT be attached");
-			else
-				info("CX24113 successfully attached");
-		}
-
-		fc->dev_type = FC_SKY_REV28;
-
-		fc->fc_i2c_adap[2].no_base_addr = 1;
-		if (dvb_attach(isl6421_attach, fc->fe,
-		       &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
-			err("ISL6421 could NOT be attached");
-		else
-			info("ISL6421 successfully attached");
-
-		/* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
-		 * IR-receiver (PIC16F818) - but the card has no input for
-		 * that ??? */
-
-		goto fe_found;
-    }
-
-	/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
-	fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
-	if (fc->fe != NULL) {
-		ops = &fc->fe->ops;
-
-		ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
-
-		ops->set_voltage = flexcop_set_voltage;
-
-		fc->fe_sleep = ops->sleep;
-		ops->sleep = flexcop_sleep;
-
-		fc->dev_type = FC_SKY_REV26;
-		goto fe_found;
-	}
-
-	/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
-	fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
-	if (fc->fe != NULL) {
-		fc->dev_type = FC_AIR_DVBT;
-		fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
-		goto fe_found;
-	}
-
-	/* try the air atsc 2nd generation (nxt2002) */
-	fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
-	if (fc->fe != NULL) {
-		fc->dev_type = FC_AIR_ATSC2;
-		dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
-		goto fe_found;
-	}
-
-	fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
-	if (fc->fe != NULL) {
-		fc->dev_type = FC_AIR_ATSC3;
-		dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
-				TUNER_LG_TDVS_H06XF);
-		goto fe_found;
-	}
-
-	/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
-	fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
-	if (fc->fe != NULL) {
-		fc->dev_type = FC_AIR_ATSC1;
-		goto fe_found;
-	}
-
-	/* try the cable dvb (stv0297) */
 	fc->fc_i2c_adap[0].no_base_addr = 1;
 	fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
-	if (fc->fe != NULL) {
-		fc->dev_type = FC_CABLE;
-		fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
-		goto fe_found;
+	if (!fc->fe) {
+		/* Reset for next frontend to try */
+		fc->fc_i2c_adap[0].no_base_addr = 0;
+		return 0;
 	}
-	fc->fc_i2c_adap[0].no_base_addr = 0;
-
-	/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
-	fc->fe = dvb_attach(mt312_attach,
-		&skystar23_samsung_tbdu18132_config, i2c);
-	if (fc->fe != NULL) {
-		ops = &fc->fe->ops;
-
-		ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
-
-		ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
-		ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
-		ops->set_tone               = flexcop_set_tone;
-		ops->set_voltage            = flexcop_set_voltage;
+	fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
+	return 1;
+}
+#else
+#define cablestar2_attach NULL
+#endif
 
-		fc->fe_sleep                = ops->sleep;
-		ops->sleep                  = flexcop_sleep;
+static struct {
+	flexcop_device_type_t type;
+	int (*attach)(struct flexcop_device *, struct i2c_adapter *);
+} flexcop_frontends[] = {
+	{ FC_SKY_REV27, skystar2_rev27_attach },
+	{ FC_SKY_REV28, skystar2_rev28_attach },
+	{ FC_SKY_REV26, skystar2_rev26_attach },
+	{ FC_AIR_DVBT, airstar_dvbt_attach },
+	{ FC_AIR_ATSC2, airstar_atsc2_attach },
+	{ FC_AIR_ATSC3, airstar_atsc3_attach },
+	{ FC_AIR_ATSC1, airstar_atsc1_attach },
+	{ FC_CABLE, cablestar2_attach },
+	{ FC_SKY_REV23, skystar2_rev23_attach },
+};
 
-		fc->dev_type                = FC_SKY_REV23;
-		goto fe_found;
+/* try to figure out the frontend */
+int flexcop_frontend_init(struct flexcop_device *fc)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
+		if (!flexcop_frontends[i].attach)
+			continue;
+		/* type needs to be set before, because of some workarounds
+		 * done based on the probed card type */
+		fc->dev_type = flexcop_frontends[i].type;
+		if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
+			goto fe_found;
+		/* Clean up partially attached frontend */
+		if (fc->fe) {
+			dvb_frontend_detach(fc->fe);
+			fc->fe = NULL;
+		}
 	}
-
+	fc->dev_type = FC_UNK;
 	err("no frontend driver found for this B2C2/FlexCop adapter");
 	return -ENODEV;
 
@@ -664,9 +764,7 @@
 	info("found '%s' .", fc->fe->ops.info.name);
 	if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
 		err("frontend registration failed!");
-		ops = &fc->fe->ops;
-		if (ops->release != NULL)
-			ops->release(fc->fe);
+		dvb_frontend_detach(fc->fe);
 		fc->fe = NULL;
 		return -EINVAL;
 	}
@@ -680,6 +778,5 @@
 		dvb_unregister_frontend(fc->fe);
 		dvb_frontend_detach(fc->fe);
 	}
-
 	fc->init_state &= ~FC_STATE_FE_INIT;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-i2c.c linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -200,7 +200,7 @@
 					msgs[i].buf[0], &msgs[i].buf[1],
 					msgs[i].len - 1);
 		if (ret < 0) {
-			err("i2c master_xfer failed");
+			deb_i2c("i2c master_xfer failed");
 			break;
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-misc.c linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-misc.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/b2c2/flexcop-misc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/b2c2/flexcop-misc.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,16 +46,16 @@
 };
 
 static const char *flexcop_device_names[] = {
-	"Unknown device",
-	"Air2PC/AirStar 2 DVB-T",
-	"Air2PC/AirStar 2 ATSC 1st generation",
-	"Air2PC/AirStar 2 ATSC 2nd generation",
-	"Sky2PC/SkyStar 2 DVB-S",
-	"Sky2PC/SkyStar 2 DVB-S (old version)",
-	"Cable2PC/CableStar 2 DVB-C",
-	"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
-	"Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
-	"Sky2PC/SkyStar 2 DVB-S rev 2.8",
+	[FC_UNK]	= "Unknown device",
+	[FC_CABLE]	= "Cable2PC/CableStar 2 DVB-C",
+	[FC_AIR_DVBT]	= "Air2PC/AirStar 2 DVB-T",
+	[FC_AIR_ATSC1]	= "Air2PC/AirStar 2 ATSC 1st generation",
+	[FC_AIR_ATSC2]	= "Air2PC/AirStar 2 ATSC 2nd generation",
+	[FC_AIR_ATSC3]	= "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
+	[FC_SKY_REV23]	= "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)",
+	[FC_SKY_REV26]	= "Sky2PC/SkyStar 2 DVB-S rev 2.6",
+	[FC_SKY_REV27]	= "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
+	[FC_SKY_REV28]	= "Sky2PC/SkyStar 2 DVB-S rev 2.8",
 };
 
 static const char *flexcop_bus_names[] = {
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/bt8xx/bt878.c linux-libre-2.6.31-gnu/drivers/media/dvb/bt8xx/bt878.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/bt8xx/bt878.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/bt8xx/bt878.c	2009-09-09 18:13:59.000000000 -0400
@@ -508,12 +508,6 @@
 	pci_set_master(dev);
 	pci_set_drvdata(dev, bt);
 
-/*        if(init_bt878(btv) < 0) {
-		bt878_remove(dev);
-		return -EIO;
-	}
-*/
-
 	if ((result = bt878_mem_alloc(bt))) {
 		printk(KERN_ERR "bt878: failed to allocate memory!\n");
 		goto fail2;
@@ -579,7 +573,7 @@
       .name	= "bt878",
       .id_table = bt878_pci_tbl,
       .probe	= bt878_probe,
-      .remove	= bt878_remove,
+      .remove	= __devexit_p(bt878_remove),
 };
 
 static int bt878_pci_driver_registered;
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/bt8xx/dst_ca.c linux-libre-2.6.31-gnu/drivers/media/dvb/bt8xx/dst_ca.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/bt8xx/dst_ca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/bt8xx/dst_ca.c	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/dvb/ca.h>
 #include "dvbdev.h"
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dm1105/dm1105.c linux-libre-2.6.31-gnu/drivers/media/dvb/dm1105/dm1105.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dm1105/dm1105.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dm1105/dm1105.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,6 +51,9 @@
 #ifndef PCI_VENDOR_ID_TRIGEM
 #define PCI_VENDOR_ID_TRIGEM	0x109f
 #endif
+#ifndef PCI_VENDOR_ID_AXESS
+#define PCI_VENDOR_ID_AXESS	0x195d
+#endif
 #ifndef PCI_DEVICE_ID_DM1105
 #define PCI_DEVICE_ID_DM1105	0x036f
 #endif
@@ -60,6 +63,9 @@
 #ifndef PCI_DEVICE_ID_DW2004
 #define PCI_DEVICE_ID_DW2004	0x2004
 #endif
+#ifndef PCI_DEVICE_ID_DM05
+#define PCI_DEVICE_ID_DM05	0x1105
+#endif
 /* ----------------------------------------------- */
 /* sdmc dm1105 registers */
 
@@ -150,6 +156,11 @@
 #define DM1105_LNB_13V				0x00010100
 #define DM1105_LNB_18V				0x00000100
 
+/* GPIO's for LNB power control for Axess DM05 */
+#define DM05_LNB_MASK				0x00000000
+#define DM05_LNB_13V				0x00020000
+#define DM05_LNB_18V				0x00030000
+
 static int ir_debug;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
@@ -188,6 +199,8 @@
 
 	/* irq */
 	struct work_struct work;
+	struct workqueue_struct *wq;
+	char wqn[16];
 
 	/* dma */
 	dma_addr_t dma_addr;
@@ -313,15 +326,25 @@
 static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
 	struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
+	u32 lnb_mask, lnb_13v, lnb_18v;
 
-		if (voltage == SEC_VOLTAGE_18) {
-			outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
-			outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL));
-		} else	{
-		/*LNB ON-13V by default!*/
-			outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
-			outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL));
-		}
+	switch (dm1105dvb->pdev->subsystem_device) {
+	case PCI_DEVICE_ID_DM05:
+		lnb_mask = DM05_LNB_MASK;
+		lnb_13v = DM05_LNB_13V;
+		lnb_18v = DM05_LNB_18V;
+		break;
+	default:
+		lnb_mask = DM1105_LNB_MASK;
+		lnb_13v = DM1105_LNB_13V;
+		lnb_18v = DM1105_LNB_18V;
+	}
+
+	outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR));
+	if (voltage == SEC_VOLTAGE_18)
+		outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL));
+	else
+		outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL));
 
 	return 0;
 }
@@ -440,7 +463,7 @@
 	case (INTSTS_TSIRQ | INTSTS_IR):
 		dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
 					inl(dm_io_mem(DM1105_STADR));
-		schedule_work(&dm1105dvb->work);
+		queue_work(dm1105dvb->wq, &dm1105dvb->work);
 		break;
 	case INTSTS_IR:
 		dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
@@ -567,46 +590,44 @@
 	int ret;
 
 	switch (dm1105dvb->pdev->subsystem_device) {
-	case PCI_DEVICE_ID_DW2002:
+	case PCI_DEVICE_ID_DW2004:
 		dm1105dvb->fe = dvb_attach(
-			stv0299_attach, &sharp_z0194a_config,
+			cx24116_attach, &serit_sp2633_config,
 			&dm1105dvb->i2c_adap);
+		if (dm1105dvb->fe)
+			dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
 
+		break;
+	default:
+		dm1105dvb->fe = dvb_attach(
+			stv0299_attach, &sharp_z0194a_config,
+			&dm1105dvb->i2c_adap);
 		if (dm1105dvb->fe) {
 			dm1105dvb->fe->ops.set_voltage =
 							dm1105dvb_set_voltage;
 			dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
 					&dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
+			break;
 		}
 
-		if (!dm1105dvb->fe) {
-			dm1105dvb->fe = dvb_attach(
-				stv0288_attach, &earda_config,
-				&dm1105dvb->i2c_adap);
-			if (dm1105dvb->fe) {
-				dm1105dvb->fe->ops.set_voltage =
-							dm1105dvb_set_voltage;
-				dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
-						&dm1105dvb->i2c_adap);
-			}
+		dm1105dvb->fe = dvb_attach(
+			stv0288_attach, &earda_config,
+			&dm1105dvb->i2c_adap);
+		if (dm1105dvb->fe) {
+			dm1105dvb->fe->ops.set_voltage =
+						dm1105dvb_set_voltage;
+			dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
+					&dm1105dvb->i2c_adap);
+			break;
 		}
 
-		if (!dm1105dvb->fe) {
-			dm1105dvb->fe = dvb_attach(
-				si21xx_attach, &serit_config,
-				&dm1105dvb->i2c_adap);
-			if (dm1105dvb->fe)
-				dm1105dvb->fe->ops.set_voltage =
-							dm1105dvb_set_voltage;
-		}
-		break;
-	case PCI_DEVICE_ID_DW2004:
 		dm1105dvb->fe = dvb_attach(
-			cx24116_attach, &serit_sp2633_config,
+			si21xx_attach, &serit_config,
 			&dm1105dvb->i2c_adap);
 		if (dm1105dvb->fe)
-			dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
-		break;
+			dm1105dvb->fe->ops.set_voltage =
+						dm1105dvb_set_voltage;
+
 	}
 
 	if (!dm1105dvb->fe) {
@@ -630,10 +651,17 @@
 	static u8 command[1] = { 0x28 };
 
 	struct i2c_msg msg[] = {
-		{ .addr = IIC_24C01_addr >> 1, .flags = 0,
-				.buf = command, .len = 1 },
-		{ .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD,
-				.buf = mac, .len = 6 },
+		{
+			.addr = IIC_24C01_addr >> 1,
+			.flags = 0,
+			.buf = command,
+			.len = 1
+		}, {
+			.addr = IIC_24C01_addr >> 1,
+			.flags = I2C_M_RD,
+			.buf = mac,
+			.len = 6
+		},
 	};
 
 	dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
@@ -752,14 +780,22 @@
 	dm1105_ir_init(dm1105dvb);
 
 	INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
+	sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
+	dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn);
+	if (!dm1105dvb->wq)
+		goto err_dvb_net;
 
 	ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
 						DRIVER_NAME, dm1105dvb);
 	if (ret < 0)
-		goto err_free_irq;
+		goto err_workqueue;
 
 	return 0;
 
+err_workqueue:
+	destroy_workqueue(dm1105dvb->wq);
+err_dvb_net:
+	dvb_net_release(&dm1105dvb->dvbnet);
 err_disconnect_frontend:
 	dmx->disconnect_frontend(dmx);
 err_remove_mem_frontend:
@@ -776,8 +812,6 @@
 	i2c_del_adapter(&dm1105dvb->i2c_adap);
 err_dm1105dvb_hw_exit:
 	dm1105dvb_hw_exit(dm1105dvb);
-err_free_irq:
-	free_irq(pdev->irq, dm1105dvb);
 err_pci_iounmap:
 	pci_iounmap(pdev, dm1105dvb->io_mem);
 err_pci_release_regions:
@@ -834,6 +868,11 @@
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_DEVICE_ID_DW2004,
 	}, {
+		.vendor = PCI_VENDOR_ID_AXESS,
+		.device = PCI_DEVICE_ID_DM05,
+		.subvendor = PCI_VENDOR_ID_AXESS,
+		.subdevice = PCI_DEVICE_ID_DM05,
+	}, {
 		/* empty */
 	},
 };
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dmxdev.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dmxdev.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dmxdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dmxdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -244,19 +244,13 @@
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dmxdev *dmxdev = dvbdev->priv;
-	int ret;
 
-	if (dmxdev->exit) {
-		mutex_unlock(&dmxdev->mutex);
+	if (dmxdev->exit)
 		return -ENODEV;
-	}
 
-	//mutex_lock(&dmxdev->mutex);
-	ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
-				     file->f_flags & O_NONBLOCK,
-				     buf, count, ppos);
-	//mutex_unlock(&dmxdev->mutex);
-	return ret;
+	return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
+				      file->f_flags & O_NONBLOCK,
+				      buf, count, ppos);
 }
 
 static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvb_demux.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvb_demux.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvb_demux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvb_demux.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,16 @@
 */
 // #define DVB_DEMUX_SECTION_LOSS_LOG
 
+static int dvb_demux_tscheck;
+module_param(dvb_demux_tscheck, int, 0644);
+MODULE_PARM_DESC(dvb_demux_tscheck,
+		"enable transport stream continuity and TEI check");
+
+#define dprintk_tscheck(x...) do {                              \
+		if (dvb_demux_tscheck && printk_ratelimit())    \
+			printk(x);                              \
+	} while (0)
+
 /******************************************************************************
  * static inlined helper functions
  ******************************************************************************/
@@ -376,6 +386,36 @@
 	u16 pid = ts_pid(buf);
 	int dvr_done = 0;
 
+	if (dvb_demux_tscheck) {
+		if (!demux->cnt_storage)
+			demux->cnt_storage = vmalloc(MAX_PID + 1);
+
+		if (!demux->cnt_storage) {
+			printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
+			dvb_demux_tscheck = 0;
+			goto no_dvb_demux_tscheck;
+		}
+
+		/* check pkt counter */
+		if (pid < MAX_PID) {
+			if (buf[1] & 0x80)
+				dprintk_tscheck("TEI detected. "
+						"PID=0x%x data1=0x%x\n",
+						pid, buf[1]);
+
+			if ((buf[3] & 0xf) != demux->cnt_storage[pid])
+				dprintk_tscheck("TS packet counter mismatch. "
+						"PID=0x%x expected 0x%x "
+						"got 0x%x\n",
+						pid, demux->cnt_storage[pid],
+						buf[3] & 0xf);
+
+			demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
+		};
+		/* end check */
+	};
+no_dvb_demux_tscheck:
+
 	list_for_each_entry(feed, &demux->feed_list, list_head) {
 		if ((feed->pid != pid) && (feed->pid != 0x2000))
 			continue;
@@ -1160,6 +1200,7 @@
 	int i;
 	struct dmx_demux *dmx = &dvbdemux->dmx;
 
+	dvbdemux->cnt_storage = NULL;
 	dvbdemux->users = 0;
 	dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
 
@@ -1226,6 +1267,7 @@
 
 void dvb_dmx_release(struct dvb_demux *dvbdemux)
 {
+	vfree(dvbdemux->cnt_storage);
 	vfree(dvbdemux->filter);
 	vfree(dvbdemux->feed);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvb_demux.h linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvb_demux.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvb_demux.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvb_demux.h	2009-09-09 18:13:59.000000000 -0400
@@ -42,6 +42,8 @@
 
 #define DVB_DEMUX_MASK_MAX 18
 
+#define MAX_PID 0x1fff
+
 struct dvb_demux_filter {
 	struct dmx_section_filter filter;
 	u8 maskandmode[DMX_MAX_FILTER_SIZE];
@@ -127,6 +129,8 @@
 
 	struct mutex mutex;
 	spinlock_t lock;
+
+	uint8_t *cnt_storage; /* for TS continuity check */
 };
 
 int dvb_dmx_init(struct dvb_demux *dvbdemux);
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvbdev.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvbdev.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvbdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvbdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -447,6 +447,15 @@
 	return 0;
 }
 
+static char *dvb_nodename(struct device *dev)
+{
+	struct dvb_device *dvbdev = dev_get_drvdata(dev);
+
+	return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
+		dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
+}
+
+
 static int __init init_dvbdev(void)
 {
 	int retval;
@@ -469,6 +478,7 @@
 		goto error;
 	}
 	dvb_class->dev_uevent = dvb_uevent;
+	dvb_class->nodename = dvb_nodename;
 	return 0;
 
 error:
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvbdev.h linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvbdev.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvbdev.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvbdev.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,7 +27,6 @@
 #include <linux/poll.h>
 #include <linux/fs.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 
 #define DVB_MAJOR 212
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2009-09-09 18:13:59.000000000 -0400
@@ -543,6 +543,7 @@
 
 		if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
 			/* got signal or quitting */
+			fepriv->exit = 1;
 			break;
 		}
 
@@ -656,6 +657,7 @@
 	}
 
 	fepriv->thread = NULL;
+	fepriv->exit = 0;
 	mb();
 
 	dvb_frontend_wakeup(fe);
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/af9015.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/af9015.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/af9015.c	2012-03-22 19:11:55.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/af9015.c	2012-03-22 20:08:17.000000000 -0400
@@ -40,7 +40,7 @@
 static DEFINE_MUTEX(af9015_usb_mutex);
 
 static struct af9015_config af9015_config;
-static struct dvb_usb_device_properties af9015_properties[2];
+static struct dvb_usb_device_properties af9015_properties[3];
 static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
 
 static struct af9013_config af9015_af9013_config[] = {
@@ -81,7 +81,6 @@
 
 	switch (req->cmd) {
 	case GET_CONFIG:
-	case BOOT:
 	case READ_MEMORY:
 	case RECONNECT_USB:
 	case GET_IR_CODE:
@@ -100,6 +99,7 @@
 	case WRITE_VIRTUAL_MEMORY:
 	case COPY_FIRMWARE:
 	case DOWNLOAD_FIRMWARE:
+	case BOOT:
 		break;
 	default:
 		err("unknown command:%d", req->cmd);
@@ -538,7 +538,7 @@
 /* dump eeprom */
 static int af9015_eeprom_dump(struct dvb_usb_device *d)
 {
-	char buf[52], buf2[4];
+	char buf[4+3*16+1], buf2[4];
 	u8 reg, val;
 
 	for (reg = 0; ; reg++) {
@@ -1261,7 +1261,11 @@
 	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U_2)},
 	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U_3)},
 	{USB_DEVICE(USB_VID_AFATECH,   USB_PID_TREKSTOR_DVBT)},
-	{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
+/* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
+	{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
+	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_CONCEPTRONIC_CTVDIGRCU)},
+	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_MC810)},
+	{USB_DEVICE(USB_VID_KYE,       USB_PID_GENIUS_TVGO_DVB_T03)},
 	{0},
 };
 MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1321,7 +1325,7 @@
 
 		.i2c_algo = &af9015_i2c_algo,
 
-		.num_device_descs = 9,
+		.num_device_descs = 9, /* max 9 */
 		.devices = {
 			{
 				.name = "Afatech AF9015 DVB-T USB2.0 stick",
@@ -1426,7 +1430,7 @@
 
 		.i2c_algo = &af9015_i2c_algo,
 
-		.num_device_descs = 9,
+		.num_device_descs = 9, /* max 9 */
 		.devices = {
 			{
 				.name = "Xtensions XD-380",
@@ -1478,7 +1482,85 @@
 				.warm_ids = {NULL},
 			},
 		}
-	}
+	}, {
+		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+		.usb_ctrl = DEVICE_SPECIFIC,
+		.download_firmware = af9015_download_firmware,
+		.firmware = "/*(DEBLOBBED)*/",
+		.no_reconnect = 1,
+
+		.size_of_priv = sizeof(struct af9015_state), \
+
+		.num_adapters = 2,
+		.adapter = {
+			{
+				.caps = DVB_USB_ADAP_HAS_PID_FILTER |
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+				.pid_filter_count = 32,
+				.pid_filter       = af9015_pid_filter,
+				.pid_filter_ctrl  = af9015_pid_filter_ctrl,
+
+				.frontend_attach =
+					af9015_af9013_frontend_attach,
+				.tuner_attach    = af9015_tuner_attach,
+				.stream = {
+					.type = USB_BULK,
+					.count = 6,
+					.endpoint = 0x84,
+				},
+			},
+			{
+				.frontend_attach =
+					af9015_af9013_frontend_attach,
+				.tuner_attach    = af9015_tuner_attach,
+				.stream = {
+					.type = USB_BULK,
+					.count = 6,
+					.endpoint = 0x85,
+					.u = {
+						.bulk = {
+							.buffersize =
+						TS_USB20_MAX_PACKET_SIZE,
+						}
+					}
+				},
+			}
+		},
+
+		.identify_state = af9015_identify_state,
+
+		.rc_query         = af9015_rc_query,
+		.rc_interval      = 150,
+
+		.i2c_algo = &af9015_i2c_algo,
+
+		.num_device_descs = 4, /* max 9 */
+		.devices = {
+			{
+				.name = "AverMedia AVerTV Volar GPS 805 (A805)",
+				.cold_ids = {&af9015_usb_table[21], NULL},
+				.warm_ids = {NULL},
+			},
+			{
+				.name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
+					"V3.0",
+				.cold_ids = {&af9015_usb_table[22], NULL},
+				.warm_ids = {NULL},
+			},
+			{
+				.name = "KWorld Digial MC-810",
+				.cold_ids = {&af9015_usb_table[23], NULL},
+				.warm_ids = {NULL},
+			},
+			{
+				.name = "Genius TVGo DVB-T03",
+				.cold_ids = {&af9015_usb_table[24], NULL},
+				.warm_ids = {NULL},
+			},
+		}
+	},
 };
 
 static int af9015_usb_probe(struct usb_interface *intf,
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c	2012-03-22 19:12:02.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c	2012-03-22 20:08:23.000000000 -0400
@@ -1346,9 +1346,9 @@
 	if (command == XC5000_TUNER_RESET) {
 		/* Reset the tuner */
 		dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0);
-		msleep(330); /* from Windows USB trace */
+		msleep(10);
 		dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1);
-		msleep(330); /* from Windows USB trace */
+		msleep(10);
 	} else {
 		err("xc5000: unknown tuner callback command: %d\n", command);
 		return -EINVAL;
@@ -1493,6 +1493,10 @@
 	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) },
 	{ USB_DEVICE(USB_VID_YUAN,	USB_PID_YUAN_MC770) },
 	{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT) },
+/* 50 */{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT_Dlx) },
+	{ USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_H) },
+	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_T3) },
+	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_T5) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1692,7 +1696,7 @@
 			},
 		},
 
-		.num_device_descs = 11,
+		.num_device_descs = 12,
 		.devices = {
 			{   "DiBcom STK7070P reference design",
 				{ &dib0700_usb_id_table[15], NULL },
@@ -1726,8 +1730,9 @@
 				{ &dib0700_usb_id_table[30], NULL },
 				{ NULL },
 			},
-			{   "Terratec Cinergy T USB XXS",
-				{ &dib0700_usb_id_table[33], NULL },
+			{   "Terratec Cinergy T USB XXS/ T3",
+				{ &dib0700_usb_id_table[33],
+					&dib0700_usb_id_table[52], NULL },
 				{ NULL },
 			},
 			{   "Elgato EyeTV DTT",
@@ -1738,6 +1743,10 @@
 				{ &dib0700_usb_id_table[45], NULL },
 				{ NULL },
 			},
+			{   "Elgato EyeTV Dtt Dlx PD378S",
+				{ &dib0700_usb_id_table[50], NULL },
+				{ NULL },
+			},
 		},
 
 		.rc_interval      = DEFAULT_RC_INTERVAL,
@@ -1784,8 +1793,9 @@
 				{ &dib0700_usb_id_table[36], NULL },
 				{ NULL },
 			},
-			{  "Terratec Cinergy DT USB XS Diversity",
-				{ &dib0700_usb_id_table[43], NULL },
+			{  "Terratec Cinergy DT USB XS Diversity/ T5",
+				{ &dib0700_usb_id_table[43],
+					&dib0700_usb_id_table[53], NULL},
 				{ NULL },
 			},
 			{  "Sony PlayTV",
@@ -1812,7 +1822,7 @@
 			},
 		},
 
-		.num_device_descs = 7,
+		.num_device_descs = 8,
 		.devices = {
 			{   "Terratec Cinergy HT USB XE",
 				{ &dib0700_usb_id_table[27], NULL },
@@ -1842,6 +1852,11 @@
 				{ &dib0700_usb_id_table[48], NULL },
 				{ NULL },
 			},
+			{   "Leadtek WinFast DTV Dongle H",
+				{ &dib0700_usb_id_table[51], NULL },
+				{ NULL },
+			},
+
 		},
 		.rc_interval      = DEFAULT_RC_INTERVAL,
 		.rc_key_map       = dib0700_rc_keys,
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dibusb-common.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,14 +133,17 @@
 
 	for (i = 0; i < num; i++) {
 		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+		if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0
+					  && (msg[i+1].flags & I2C_M_RD)) {
 			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
 						msg[i+1].buf,msg[i+1].len) < 0)
 				break;
 			i++;
-		} else
+		} else if ((msg[i].flags & I2C_M_RD) == 0) {
 			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
 				break;
+		} else
+			break;
 	}
 
 	mutex_unlock(&d->i2c_mutex);
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h	2009-09-09 18:13:59.000000000 -0400
@@ -196,7 +196,7 @@
 #define CYPRESS_FX2     3
 	int        usb_ctrl;
 	int        (*download_firmware) (struct usb_device *, const struct firmware *);
-	const char firmware[FIRMWARE_NAME_MAX];
+	const char *firmware;
 	int        no_reconnect;
 
 	int size_of_priv;
@@ -223,7 +223,7 @@
 	int generic_bulk_ctrl_endpoint;
 
 	int num_device_descs;
-	struct dvb_usb_device_description devices[11];
+	struct dvb_usb_device_description devices[12];
 };
 
 /**
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2009-09-09 18:13:59.000000000 -0400
@@ -80,6 +80,7 @@
 #define USB_PID_COMPRO_DVBU2000_UNK_WARM		0x010d
 #define USB_PID_COMPRO_VIDEOMATE_U500			0x1e78
 #define USB_PID_COMPRO_VIDEOMATE_U500_PC		0x1e80
+#define USB_PID_CONCEPTRONIC_CTVDIGRCU			0xe397
 #define USB_PID_CONEXANT_D680_DMB			0x86d6
 #define USB_PID_DIBCOM_HOOK_DEFAULT			0x0064
 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM		0x0065
@@ -97,6 +98,7 @@
 #define USB_PID_DPOSH_M9206_COLD			0x9206
 #define USB_PID_DPOSH_M9206_WARM			0xa090
 #define USB_PID_UNIWILL_STK7700P			0x6003
+#define USB_PID_GENIUS_TVGO_DVB_T03			0x4012
 #define USB_PID_GRANDTEC_DVBT_USB_COLD			0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM			0x0fa1
 #define USB_PID_INTEL_CE9500				0x9500
@@ -104,6 +106,7 @@
 #define USB_PID_KWORLD_395U				0xe396
 #define USB_PID_KWORLD_395U_2				0xe39b
 #define USB_PID_KWORLD_395U_3				0xe395
+#define USB_PID_KWORLD_MC810				0xc810
 #define USB_PID_KWORLD_PC160_2T				0xc160
 #define USB_PID_KWORLD_VSTREAM_COLD			0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM			0x17df
@@ -171,6 +174,7 @@
 #define USB_PID_AVERMEDIA_A309				0xa309
 #define USB_PID_AVERMEDIA_A310				0xa310
 #define USB_PID_AVERMEDIA_A850				0x850a
+#define USB_PID_AVERMEDIA_A805				0xa805
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2	0x0081
@@ -178,6 +182,8 @@
 #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS		0x0060
 #define USB_PID_TERRATEC_CINERGY_T_EXPRESS		0x0062
 #define USB_PID_TERRATEC_CINERGY_T_XXS			0x0078
+#define USB_PID_TERRATEC_T3				0x10a0
+#define USB_PID_TERRATEC_T5				0x10a1
 #define USB_PID_PINNACLE_EXPRESSCARD_320CX		0x022e
 #define USB_PID_PINNACLE_PCTV2000E			0x022c
 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH		0x0228
@@ -222,6 +228,7 @@
 #define USB_PID_WINFAST_DTV_DONGLE_COLD			0x6025
 #define USB_PID_WINFAST_DTV_DONGLE_WARM			0x6026
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P		0x6f00
+#define USB_PID_WINFAST_DTV_DONGLE_H			0x60f6
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2		0x6f01
 #define USB_PID_WINFAST_DTV_DONGLE_GOLD			0x6029
 #define USB_PID_GENPIX_8PSK_REV_1_COLD			0x0200
@@ -251,5 +258,6 @@
 #define USB_PID_MSI_DIGI_VOX_MINI_III                   0x8807
 #define USB_PID_SONY_PLAYTV				0x0003
 #define USB_PID_ELGATO_EYETV_DTT			0x0021
+#define USB_PID_ELGATO_EYETV_DTT_Dlx			0x0020
 
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dw2102.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dw2102.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dw2102.c	2012-03-22 19:12:14.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dw2102.c	2012-03-22 20:08:33.000000000 -0400
@@ -1,7 +1,7 @@
 /* DVB USB framework compliant Linux driver for the
-*	DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card
-*
-* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*	DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
+*	TeVii S600, S650 Cards
+* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
 *
 *	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
@@ -17,6 +17,7 @@
 #include "stb6000.h"
 #include "eds1547.h"
 #include "cx24116.h"
+#include "tda1002x.h"
 
 #ifndef USB_PID_DW2102
 #define USB_PID_DW2102 0x2102
@@ -26,10 +27,18 @@
 #define USB_PID_DW2104 0x2104
 #endif
 
+#ifndef USB_PID_DW3101
+#define USB_PID_DW3101 0x3101
+#endif
+
 #ifndef USB_PID_CINERGY_S
 #define USB_PID_CINERGY_S 0x0064
 #endif
 
+#ifndef USB_PID_TEVII_S650
+#define USB_PID_TEVII_S650 0xd650
+#endif
+
 #define DW210X_READ_MSG 0
 #define DW210X_WRITE_MSG 1
 
@@ -40,18 +49,21 @@
 #define DW2102_VOLTAGE_CTRL (0x1800)
 #define DW2102_RC_QUERY (0x1a00)
 
-struct dw210x_state {
-	u32 last_key_pressed;
-};
-struct dw210x_rc_keys {
-	u32 keycode;
-	u32 event;
+struct dvb_usb_rc_keys_table {
+	struct dvb_usb_rc_key *rc_keys;
+	int rc_keys_size;
 };
 
 /* debug */
 static int dvb_usb_dw2102_debug;
 module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS);
+MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
+						DVB_USB_DEBUG_STATUS);
+
+/* keymaps */
+static int ir_keymap;
+module_param_named(keymap, ir_keymap, int, 0644);
+MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs  ...");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -79,7 +91,7 @@
 static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 		int num)
 {
-struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	int i = 0, ret = 0;
 	u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
 	u16 value;
@@ -205,6 +217,7 @@
 	mutex_unlock(&d->i2c_mutex);
 	return num;
 }
+
 static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -219,7 +232,7 @@
 	case 2: {
 		/* read */
 		/* first write first register number */
-		u8 ibuf [msg[1].len + 2], obuf[3];
+		u8 ibuf[msg[1].len + 2], obuf[3];
 		obuf[0] = 0xd0;
 		obuf[1] = msg[0].len;
 		obuf[2] = msg[0].buf[0];
@@ -293,7 +306,7 @@
 	case 2: {
 		/* read */
 		/* first write first register number */
-		u8 ibuf [msg[1].len + 2], obuf[3];
+		u8 ibuf[msg[1].len + 2], obuf[3];
 		obuf[0] = 0xaa;
 		obuf[1] = msg[0].len;
 		obuf[2] = msg[0].buf[0];
@@ -360,6 +373,69 @@
 	return num;
 }
 
+static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+								int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int ret = 0, i;
+
+	if (!d)
+		return -ENODEV;
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	switch (num) {
+	case 2: {
+		/* read */
+		/* first write first register number */
+		u8 ibuf[msg[1].len + 2], obuf[3];
+		obuf[0] = msg[0].addr << 1;
+		obuf[1] = msg[0].len;
+		obuf[2] = msg[0].buf[0];
+		ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+				obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+		/* second read registers */
+		ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
+				ibuf, msg[1].len + 2, DW210X_READ_MSG);
+		memcpy(msg[1].buf, ibuf + 2, msg[1].len);
+
+		break;
+	}
+	case 1:
+		switch (msg[0].addr) {
+		case 0x60:
+		case 0x0c: {
+			/* write to register */
+			u8 obuf[msg[0].len + 2];
+			obuf[0] = msg[0].addr << 1;
+			obuf[1] = msg[0].len;
+			memcpy(obuf + 2, msg[0].buf, msg[0].len);
+			ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+			break;
+		}
+		case(DW2102_RC_QUERY): {
+			u8 ibuf[2];
+			ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+					ibuf, 2, DW210X_READ_MSG);
+			memcpy(msg[0].buf, ibuf , 2);
+			break;
+		}
+		}
+
+		break;
+	}
+
+	for (i = 0; i < num; i++) {
+		deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
+				msg[i].flags == 0 ? ">>>" : "<<<");
+		debug_dump(msg[i].buf, msg[i].len, deb_xfer);
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return num;
+}
+
 static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
 {
 	return I2C_FUNC_I2C;
@@ -385,6 +461,11 @@
 	.functionality = dw210x_i2c_func,
 };
 
+static struct i2c_algorithm dw3101_i2c_algo = {
+	.master_xfer = dw3101_i2c_transfer,
+	.functionality = dw210x_i2c_func,
+};
+
 static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
 {
 	int i;
@@ -404,6 +485,7 @@
 			debug_dump(eepromline, 16, deb_xfer);
 		}
 	}
+
 	memcpy(mac, eeprom + 8, 6);
 	return 0;
 };
@@ -448,6 +530,11 @@
 
 };
 
+static struct tda10023_config dw3101_tda10023_config = {
+	.demod_address = 0x0c,
+	.invert = 1,
+};
+
 static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
 {
 	if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
@@ -460,6 +547,7 @@
 }
 
 static struct dvb_usb_device_properties dw2102_properties;
+static struct dvb_usb_device_properties dw2104_properties;
 
 static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
 {
@@ -497,6 +585,17 @@
 	return -EIO;
 }
 
+static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
+{
+	d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
+				&d->dev->i2c_adap, 0x48);
+	if (d->fe != NULL) {
+		info("Attached tda10023!\n");
+		return 0;
+	}
+	return -EIO;
+}
+
 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -512,6 +611,14 @@
 	return 0;
 }
 
+static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+		&adap->dev->i2c_adap, DVB_PLL_TUA6034);
+
+	return 0;
+}
+
 static struct dvb_usb_rc_key dw210x_rc_keys[] = {
 	{ 0xf8,	0x0a, KEY_Q },		/*power*/
 	{ 0xf8,	0x0c, KEY_M },		/*mute*/
@@ -544,44 +651,147 @@
 	{ 0xf8, 0x40, KEY_F },		/*full*/
 	{ 0xf8, 0x1e, KEY_W },		/*tvmode*/
 	{ 0xf8, 0x1b, KEY_B },		/*recall*/
+};
 
+static struct dvb_usb_rc_key tevii_rc_keys[] = {
+	{ 0xf8, 0x0a, KEY_POWER },
+	{ 0xf8, 0x0c, KEY_MUTE },
+	{ 0xf8, 0x11, KEY_1 },
+	{ 0xf8, 0x12, KEY_2 },
+	{ 0xf8, 0x13, KEY_3 },
+	{ 0xf8, 0x14, KEY_4 },
+	{ 0xf8, 0x15, KEY_5 },
+	{ 0xf8, 0x16, KEY_6 },
+	{ 0xf8, 0x17, KEY_7 },
+	{ 0xf8, 0x18, KEY_8 },
+	{ 0xf8, 0x19, KEY_9 },
+	{ 0xf8, 0x10, KEY_0 },
+	{ 0xf8, 0x1c, KEY_MENU },
+	{ 0xf8, 0x0f, KEY_VOLUMEDOWN },
+	{ 0xf8, 0x1a, KEY_LAST },
+	{ 0xf8, 0x0e, KEY_OPEN },
+	{ 0xf8, 0x04, KEY_RECORD },
+	{ 0xf8, 0x09, KEY_VOLUMEUP },
+	{ 0xf8, 0x08, KEY_CHANNELUP },
+	{ 0xf8, 0x07, KEY_PVR },
+	{ 0xf8, 0x0b, KEY_TIME },
+	{ 0xf8, 0x02, KEY_RIGHT },
+	{ 0xf8, 0x03, KEY_LEFT },
+	{ 0xf8, 0x00, KEY_UP },
+	{ 0xf8, 0x1f, KEY_OK },
+	{ 0xf8, 0x01, KEY_DOWN },
+	{ 0xf8, 0x05, KEY_TUNER },
+	{ 0xf8, 0x06, KEY_CHANNELDOWN },
+	{ 0xf8, 0x40, KEY_PLAYPAUSE },
+	{ 0xf8, 0x1e, KEY_REWIND },
+	{ 0xf8, 0x1b, KEY_FAVORITES },
+	{ 0xf8, 0x1d, KEY_BACK },
+	{ 0xf8, 0x4d, KEY_FASTFORWARD },
+	{ 0xf8, 0x44, KEY_EPG },
+	{ 0xf8, 0x4c, KEY_INFO },
+	{ 0xf8, 0x41, KEY_AB },
+	{ 0xf8, 0x43, KEY_AUDIO },
+	{ 0xf8, 0x45, KEY_SUBTITLE },
+	{ 0xf8, 0x4a, KEY_LIST },
+	{ 0xf8, 0x46, KEY_F1 },
+	{ 0xf8, 0x47, KEY_F2 },
+	{ 0xf8, 0x5e, KEY_F3 },
+	{ 0xf8, 0x5c, KEY_F4 },
+	{ 0xf8, 0x52, KEY_F5 },
+	{ 0xf8, 0x5a, KEY_F6 },
+	{ 0xf8, 0x56, KEY_MODE },
+	{ 0xf8, 0x58, KEY_SWITCHVIDEOMODE },
 };
 
+static struct dvb_usb_rc_key tbs_rc_keys[] = {
+	{ 0xf8,	0x84, KEY_POWER },
+	{ 0xf8,	0x94, KEY_MUTE },
+	{ 0xf8,	0x87, KEY_1 },
+	{ 0xf8,	0x86, KEY_2 },
+	{ 0xf8,	0x85, KEY_3 },
+	{ 0xf8,	0x8b, KEY_4 },
+	{ 0xf8,	0x8a, KEY_5 },
+	{ 0xf8,	0x89, KEY_6 },
+	{ 0xf8,	0x8f, KEY_7 },
+	{ 0xf8,	0x8e, KEY_8 },
+	{ 0xf8,	0x8d, KEY_9 },
+	{ 0xf8, 0x92, KEY_0 },
+	{ 0xf8, 0x96, KEY_CHANNELUP },
+	{ 0xf8, 0x91, KEY_CHANNELDOWN },
+	{ 0xf8, 0x93, KEY_VOLUMEUP },
+	{ 0xf8, 0x8c, KEY_VOLUMEDOWN },
+	{ 0xf8, 0x83, KEY_RECORD },
+	{ 0xf8, 0x98, KEY_PAUSE  },
+	{ 0xf8, 0x99, KEY_OK },
+	{ 0xf8, 0x9a, KEY_SHUFFLE },
+	{ 0xf8, 0x81, KEY_UP },
+	{ 0xf8, 0x90, KEY_LEFT },
+	{ 0xf8, 0x82, KEY_RIGHT },
+	{ 0xf8, 0x88, KEY_DOWN },
+	{ 0xf8, 0x95, KEY_FAVORITES },
+	{ 0xf8, 0x97, KEY_SUBTITLE },
+	{ 0xf8, 0x9d, KEY_ZOOM },
+	{ 0xf8, 0x9f, KEY_EXIT },
+	{ 0xf8, 0x9e, KEY_MENU },
+	{ 0xf8, 0x9c, KEY_EPG },
+	{ 0xf8, 0x80, KEY_PREVIOUS },
+	{ 0xf8, 0x9b, KEY_MODE }
+};
 
+static struct dvb_usb_rc_keys_table keys_tables[] = {
+	{ dw210x_rc_keys, ARRAY_SIZE(dw210x_rc_keys) },
+	{ tevii_rc_keys, ARRAY_SIZE(tevii_rc_keys) },
+	{ tbs_rc_keys, ARRAY_SIZE(tbs_rc_keys) },
+};
 
 static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	struct dw210x_state *st = d->priv;
+	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	int keymap_size = d->props.rc_key_map_size;
 	u8 key[2];
-	struct i2c_msg msg[] = {
-		{.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
-		.len = 2},
+	struct i2c_msg msg = {
+		.addr = DW2102_RC_QUERY,
+		.flags = I2C_M_RD,
+		.buf = key,
+		.len = 2
 	};
 	int i;
+	/* override keymap */
+	if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
+		keymap = keys_tables[ir_keymap - 1].rc_keys ;
+		keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
+	}
 
 	*state = REMOTE_NO_KEY_PRESSED;
-	if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
-		for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) {
-			if (dw210x_rc_keys[i].data == msg[0].buf[0]) {
+	if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) {
+		for (i = 0; i < keymap_size ; i++) {
+			if (keymap[i].data == msg.buf[0]) {
 				*state = REMOTE_KEY_PRESSED;
-				*event = dw210x_rc_keys[i].event;
-				st->last_key_pressed =
-					dw210x_rc_keys[i].event;
+				*event = keymap[i].event;
 				break;
 			}
-		st->last_key_pressed = 0;
+
 		}
+
+		if ((*state) == REMOTE_KEY_PRESSED)
+			deb_rc("%s: found rc key: %x, %x, event: %x\n",
+					__func__, key[0], key[1], (*event));
+		else if (key[0] != 0xff)
+			deb_rc("%s: unknown rc key: %x, %x\n",
+					__func__, key[0], key[1]);
+
 	}
-	/* info("key: %x %x\n",key[0],key[1]); */
+
 	return 0;
 }
 
 static struct usb_device_id dw2102_table[] = {
 	{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
 	{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
-	{USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
-	{USB_DEVICE(0x9022, 0xd650)},
+	{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
+	{USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
 	{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
+	{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
 	{ }
 };
 
@@ -642,11 +852,16 @@
 		}
 		/* init registers */
 		switch (dev->descriptor.idProduct) {
+		case USB_PID_TEVII_S650:
+			dw2104_properties.rc_key_map = tevii_rc_keys;
+			dw2104_properties.rc_key_map_size =
+					ARRAY_SIZE(tevii_rc_keys);
 		case USB_PID_DW2104:
-		case 0xd650:
 			reset = 1;
 			dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
 					DW210X_WRITE_MSG);
+			/* break omitted intentionally */
+		case USB_PID_DW3101:
 			reset = 0;
 			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
 					DW210X_WRITE_MSG);
@@ -690,6 +905,7 @@
 					DW210X_READ_MSG);
 			break;
 		}
+
 		msleep(100);
 		kfree(p);
 	}
@@ -700,7 +916,6 @@
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 	.usb_ctrl = DEVICE_SPECIFIC,
 	.firmware = "/*(DEBLOBBED)*/",
-	.size_of_priv = sizeof(struct dw210x_state),
 	.no_reconnect = 1,
 
 	.i2c_algo = &dw2102_serit_i2c_algo,
@@ -714,7 +929,7 @@
 	.num_adapters = 1,
 	.download_firmware = dw2102_load_firmware,
 	.read_mac_address = dw210x_read_mac_address,
-		.adapter = {
+	.adapter = {
 		{
 			.frontend_attach = dw2102_frontend_attach,
 			.streaming_ctrl = NULL,
@@ -752,7 +967,6 @@
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 	.usb_ctrl = DEVICE_SPECIFIC,
 	.firmware = "/*(DEBLOBBED)*/",
-	.size_of_priv = sizeof(struct dw210x_state),
 	.no_reconnect = 1,
 
 	.i2c_algo = &dw2104_i2c_algo,
@@ -796,12 +1010,57 @@
 	}
 };
 
+static struct dvb_usb_device_properties dw3101_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.firmware = "/*(DEBLOBBED)*/",
+	.no_reconnect = 1,
+
+	.i2c_algo = &dw3101_i2c_algo,
+	.rc_key_map = dw210x_rc_keys,
+	.rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
+	.rc_interval = 150,
+	.rc_query = dw2102_rc_query,
+
+	.generic_bulk_ctrl_endpoint = 0x81,
+	/* parameter for the MPEG2-data transfer */
+	.num_adapters = 1,
+	.download_firmware = dw2102_load_firmware,
+	.read_mac_address = dw210x_read_mac_address,
+	.adapter = {
+		{
+			.frontend_attach = dw3101_frontend_attach,
+			.streaming_ctrl = NULL,
+			.tuner_attach = dw3101_tuner_attach,
+			.stream = {
+				.type = USB_BULK,
+				.count = 8,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = 4096,
+					}
+				}
+			},
+		}
+	},
+	.num_device_descs = 1,
+	.devices = {
+		{ "DVBWorld DVB-C 3101 USB2.0",
+			{&dw2102_table[5], NULL},
+			{NULL},
+		},
+	}
+};
+
 static int dw2102_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
 	if (0 == dvb_usb_device_init(intf, &dw2102_properties,
 			THIS_MODULE, NULL, adapter_nr) ||
 	    0 == dvb_usb_device_init(intf, &dw2104_properties,
+			THIS_MODULE, NULL, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf, &dw3101_properties,
 			THIS_MODULE, NULL, adapter_nr)) {
 		return 0;
 	}
@@ -833,6 +1092,8 @@
 module_exit(dw2102_module_exit);
 
 MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
-MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
+				" DVB-C 3101 USB2.0,"
+				" TeVii S600, S650 USB2.0 devices");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dw2102.h linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dw2102.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/dw2102.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/dw2102.h	2009-09-09 18:13:59.000000000 -0400
@@ -5,4 +5,5 @@
 #include "dvb-usb.h"
 
 #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
+#define deb_rc(args...)   dprintk(dvb_usb_dw2102_debug, 0x04, args)
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/gp8psk.c linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/gp8psk.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/gp8psk.c	2012-03-22 19:12:16.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/gp8psk.c	2012-03-22 20:08:35.000000000 -0400
@@ -223,7 +223,7 @@
 	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
 	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
 	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
-	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) },
+/*	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */
 	    { 0 },
 };
 MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
@@ -254,7 +254,7 @@
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	.num_device_descs = 4,
+	.num_device_descs = 3,
 	.devices = {
 		{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
 		  .cold_ids = { &gp8psk_usb_table[0], NULL },
@@ -268,10 +268,6 @@
 		  .cold_ids = { NULL },
 		  .warm_ids = { &gp8psk_usb_table[3], NULL },
 		},
-		{ .name = "Genpix SkyWalker-CW3K DVB-S receiver",
-		  .cold_ids = { NULL },
-		  .warm_ids = { &gp8psk_usb_table[4], NULL },
-		},
 		{ NULL },
 	}
 };
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/Kconfig linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/dvb/dvb-usb/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/dvb-usb/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -216,7 +216,7 @@
 	help
 	  Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
 	  firmware protocol used by this module is similar to the one used by the
-	  old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko.
+	  old ttusb-driver - that's why the module is called dvb-usb-ttusb2.
 
 config DVB_USB_DTT200U
 	tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
@@ -261,6 +261,7 @@
 	select DVB_STB6000 if !DVB_FE_CUSTOMISE
 	select DVB_CX24116 if !DVB_FE_CUSTOMISE
 	select DVB_SI21XX if !DVB_FE_CUSTOMISE
+	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
 	help
 	  Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
 	  and the TeVii S650.
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/firewire/firedtv-1394.c linux-libre-2.6.31-gnu/drivers/media/dvb/firewire/firedtv-1394.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/firewire/firedtv-1394.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/firewire/firedtv-1394.c	2009-09-09 18:13:59.000000000 -0400
@@ -225,7 +225,7 @@
 
 static int node_remove(struct device *dev)
 {
-	struct firedtv *fdtv = dev->driver_data;
+	struct firedtv *fdtv = dev_get_drvdata(dev);
 
 	fdtv_dvb_unregister(fdtv);
 
@@ -242,7 +242,7 @@
 
 static int node_update(struct unit_directory *ud)
 {
-	struct firedtv *fdtv = ud->device.driver_data;
+	struct firedtv *fdtv = dev_get_drvdata(&ud->device);
 
 	if (fdtv->isochannel >= 0)
 		cmp_establish_pp_connection(fdtv, fdtv->subunit,
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/firewire/firedtv-dvb.c linux-libre-2.6.31-gnu/drivers/media/dvb/firewire/firedtv-dvb.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/firewire/firedtv-dvb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/firewire/firedtv-dvb.c	2009-09-09 18:13:59.000000000 -0400
@@ -268,7 +268,7 @@
 	if (!fdtv)
 		return NULL;
 
-	dev->driver_data	= fdtv;
+	dev_set_drvdata(dev, fdtv);
 	fdtv->device		= dev;
 	fdtv->isochannel	= -1;
 	fdtv->voltage		= 0xff;
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/firewire/firedtv-rc.c linux-libre-2.6.31-gnu/drivers/media/dvb/firewire/firedtv-rc.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/firewire/firedtv-rc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/firewire/firedtv-rc.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,7 +18,7 @@
 #include "firedtv.h"
 
 /* fixed table with older keycodes, geared towards MythTV */
-const static u16 oldtable[] = {
+static const u16 oldtable[] = {
 
 	/* code from device: 0x4501...0x451f */
 
@@ -62,7 +62,7 @@
 };
 
 /* user-modifiable table for a remote as sold in 2008 */
-const static u16 keytable[] = {
+static const u16 keytable[] = {
 
 	/* code from device: 0x0300...0x031f */
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/af9013.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/af9013.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/af9013.c	2012-03-22 19:12:33.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/af9013.c	2012-03-22 20:08:50.000000000 -0400
@@ -527,6 +527,10 @@
 	u8 i, buf[3] = {0, 0, 0};
 	*auto_mode = 0; /* set if parameters are requested to auto set */
 
+	/* Try auto-detect transmission parameters in case of AUTO requested or
+	   garbage parameters given by application for compatibility.
+	   MPlayer seems to provide garbage parameters currently. */
+
 	switch (params->transmission_mode) {
 	case TRANSMISSION_MODE_AUTO:
 		*auto_mode = 1;
@@ -536,7 +540,8 @@
 		buf[0] |= (1 << 0);
 		break;
 	default:
-		return -EINVAL;
+		deb_info("%s: invalid transmission_mode\n", __func__);
+		*auto_mode = 1;
 	}
 
 	switch (params->guard_interval) {
@@ -554,7 +559,8 @@
 		buf[0] |= (3 << 2);
 		break;
 	default:
-		return -EINVAL;
+		deb_info("%s: invalid guard_interval\n", __func__);
+		*auto_mode = 1;
 	}
 
 	switch (params->hierarchy_information) {
@@ -572,7 +578,8 @@
 		buf[0] |= (3 << 4);
 		break;
 	default:
-		return -EINVAL;
+		deb_info("%s: invalid hierarchy_information\n", __func__);
+		*auto_mode = 1;
 	};
 
 	switch (params->constellation) {
@@ -587,7 +594,8 @@
 		buf[1] |= (2 << 6);
 		break;
 	default:
-		return -EINVAL;
+		deb_info("%s: invalid constellation\n", __func__);
+		*auto_mode = 1;
 	}
 
 	/* Use HP. How and which case we can switch to LP? */
@@ -611,7 +619,8 @@
 		buf[2] |= (4 << 0);
 		break;
 	default:
-		return -EINVAL;
+		deb_info("%s: invalid code_rate_HP\n", __func__);
+		*auto_mode = 1;
 	}
 
 	switch (params->code_rate_LP) {
@@ -638,7 +647,8 @@
 		if (params->hierarchy_information == HIERARCHY_AUTO)
 			break;
 	default:
-		return -EINVAL;
+		deb_info("%s: invalid code_rate_LP\n", __func__);
+		*auto_mode = 1;
 	}
 
 	switch (params->bandwidth) {
@@ -651,7 +661,8 @@
 		buf[1] |= (2 << 2);
 		break;
 	default:
-		return -EINVAL;
+		deb_info("%s: invalid bandwidth\n", __func__);
+		buf[1] |= (2 << 2); /* cannot auto-detect BW, try 8 MHz */
 	}
 
 	/* program */
@@ -1455,7 +1466,7 @@
 		af9013_ops.info.name);
 
 	/* request the firmware, this will block and timeout */
-	ret = reject_firmware(&fw, fw_file,  &state->i2c->dev);
+	ret = reject_firmware(&fw, fw_file, state->i2c->dev.parent);
 	if (ret) {
 		err("did not find the firmware file. (%s) "
 			"Please see linux/Documentation/dvb/ for more details" \
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/au8522_dig.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/au8522_dig.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/au8522_dig.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/au8522_dig.c	2009-09-09 18:13:59.000000000 -0400
@@ -367,11 +367,90 @@
 	{ 0x8231, 0x13 },
 };
 
-/* QAM Modulation table */
+/* QAM64 Modulation table */
 static struct {
 	u16 reg;
 	u16 data;
-} QAM_mod_tab[] = {
+} QAM64_mod_tab[] = {
+	{ 0x00a3, 0x09 },
+	{ 0x00a4, 0x00 },
+	{ 0x0081, 0xc4 },
+	{ 0x00a5, 0x40 },
+	{ 0x00aa, 0x77 },
+	{ 0x00ad, 0x77 },
+	{ 0x00a6, 0x67 },
+	{ 0x0262, 0x20 },
+	{ 0x021c, 0x30 },
+	{ 0x00b8, 0x3e },
+	{ 0x00b9, 0xf0 },
+	{ 0x00ba, 0x01 },
+	{ 0x00bb, 0x18 },
+	{ 0x00bc, 0x50 },
+	{ 0x00bd, 0x00 },
+	{ 0x00be, 0xea },
+	{ 0x00bf, 0xef },
+	{ 0x00c0, 0xfc },
+	{ 0x00c1, 0xbd },
+	{ 0x00c2, 0x1f },
+	{ 0x00c3, 0xfc },
+	{ 0x00c4, 0xdd },
+	{ 0x00c5, 0xaf },
+	{ 0x00c6, 0x00 },
+	{ 0x00c7, 0x38 },
+	{ 0x00c8, 0x30 },
+	{ 0x00c9, 0x05 },
+	{ 0x00ca, 0x4a },
+	{ 0x00cb, 0xd0 },
+	{ 0x00cc, 0x01 },
+	{ 0x00cd, 0xd9 },
+	{ 0x00ce, 0x6f },
+	{ 0x00cf, 0xf9 },
+	{ 0x00d0, 0x70 },
+	{ 0x00d1, 0xdf },
+	{ 0x00d2, 0xf7 },
+	{ 0x00d3, 0xc2 },
+	{ 0x00d4, 0xdf },
+	{ 0x00d5, 0x02 },
+	{ 0x00d6, 0x9a },
+	{ 0x00d7, 0xd0 },
+	{ 0x0250, 0x0d },
+	{ 0x0251, 0xcd },
+	{ 0x0252, 0xe0 },
+	{ 0x0253, 0x05 },
+	{ 0x0254, 0xa7 },
+	{ 0x0255, 0xff },
+	{ 0x0256, 0xed },
+	{ 0x0257, 0x5b },
+	{ 0x0258, 0xae },
+	{ 0x0259, 0xe6 },
+	{ 0x025a, 0x3d },
+	{ 0x025b, 0x0f },
+	{ 0x025c, 0x0d },
+	{ 0x025d, 0xea },
+	{ 0x025e, 0xf2 },
+	{ 0x025f, 0x51 },
+	{ 0x0260, 0xf5 },
+	{ 0x0261, 0x06 },
+	{ 0x021a, 0x00 },
+	{ 0x0546, 0x40 },
+	{ 0x0210, 0xc7 },
+	{ 0x0211, 0xaa },
+	{ 0x0212, 0xab },
+	{ 0x0213, 0x02 },
+	{ 0x0502, 0x00 },
+	{ 0x0121, 0x04 },
+	{ 0x0122, 0x04 },
+	{ 0x052e, 0x10 },
+	{ 0x00a4, 0xca },
+	{ 0x00a7, 0x40 },
+	{ 0x0526, 0x01 },
+};
+
+/* QAM256 Modulation table */
+static struct {
+	u16 reg;
+	u16 data;
+} QAM256_mod_tab[] = {
 	{ 0x80a3, 0x09 },
 	{ 0x80a4, 0x00 },
 	{ 0x8081, 0xc4 },
@@ -464,12 +543,19 @@
 		au8522_set_if(fe, state->config->vsb_if);
 		break;
 	case QAM_64:
+		dprintk("%s() QAM 64\n", __func__);
+		for (i = 0; i < ARRAY_SIZE(QAM64_mod_tab); i++)
+			au8522_writereg(state,
+				QAM64_mod_tab[i].reg,
+				QAM64_mod_tab[i].data);
+		au8522_set_if(fe, state->config->qam_if);
+		break;
 	case QAM_256:
-		dprintk("%s() QAM 64/256\n", __func__);
-		for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
+		dprintk("%s() QAM 256\n", __func__);
+		for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
 			au8522_writereg(state,
-				QAM_mod_tab[i].reg,
-				QAM_mod_tab[i].data);
+				QAM256_mod_tab[i].reg,
+				QAM256_mod_tab[i].data);
 		au8522_set_if(fe, state->config->qam_if);
 		break;
 	default:
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx22700.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx22700.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx22700.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx22700.c	2009-09-09 18:13:59.000000000 -0400
@@ -380,7 +380,7 @@
 	struct cx22700_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct cx22700_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct cx22700_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx22702.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx22702.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx22702.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx22702.c	2009-09-09 18:13:59.000000000 -0400
@@ -580,7 +580,7 @@
 	struct cx22702_state *state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct cx22702_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx24110.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx24110.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx24110.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx24110.c	2009-09-09 18:13:59.000000000 -0400
@@ -598,7 +598,7 @@
 	int ret;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct cx24110_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx24116.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx24116.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/cx24116.c	2012-03-22 19:12:44.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/cx24116.c	2012-03-22 20:09:00.000000000 -0400
@@ -492,7 +492,7 @@
 		printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
 			__func__, "/*(DEBLOBBED)*/");
 		ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
-			&state->i2c->dev);
+			state->i2c->dev.parent);
 		printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
 			__func__);
 		if (ret) {
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/drx397xD.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/drx397xD.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/drx397xD.c	2012-03-22 19:12:53.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/drx397xD.c	2012-03-22 20:09:12.000000000 -0400
@@ -123,10 +123,10 @@
 	}
 	memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
 
-	if (reject_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) {
+	rc = reject_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent);
+	if (rc != 0) {
 		printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
 		       mod_name, fw[ix].name);
-		rc = -ENOENT;
 		goto exit_err;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/dvb_dummy_fe.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/dvb_dummy_fe.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/dvb_dummy_fe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/dvb_dummy_fe.c	2009-09-09 18:13:59.000000000 -0400
@@ -117,7 +117,7 @@
 	struct dvb_dummy_fe_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* create dvb_frontend */
@@ -137,7 +137,7 @@
 	struct dvb_dummy_fe_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* create dvb_frontend */
@@ -157,7 +157,7 @@
 	struct dvb_dummy_fe_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* create dvb_frontend */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/isl6423.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/isl6423.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/isl6423.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/isl6423.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,308 @@
+/*
+	Intersil ISL6423 SEC and LNB Power supply controller
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6423.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(__y, __z, format, arg...) do {						\
+	if (__z) {									\
+		if	((verbose > FE_ERROR) && (verbose > __y))			\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((verbose > FE_INFO) && (verbose > __y))			\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (verbose > __y)							\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+struct isl6423_dev {
+	const struct isl6423_config	*config;
+	struct i2c_adapter		*i2c;
+
+	u8 reg_3;
+	u8 reg_4;
+
+	unsigned int verbose;
+};
+
+static int isl6423_write(struct isl6423_dev *isl6423, u8 reg)
+{
+	struct i2c_adapter *i2c = isl6423->i2c;
+	u8 addr			= isl6423->config->addr;
+	int err = 0;
+
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = &reg, .len = 1 };
+
+	dprintk(FE_DEBUG, 1, "write reg %02X", reg);
+	err = i2c_transfer(i2c, &msg, 1);
+	if (err < 0)
+		goto exit;
+	return 0;
+
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static int isl6423_set_modulation(struct dvb_frontend *fe)
+{
+	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
+	const struct isl6423_config *config	= isl6423->config;
+	int err = 0;
+	u8 reg_2 = 0;
+
+	reg_2 = 0x01 << 5;
+
+	if (config->mod_extern)
+		reg_2 |= (1 << 3);
+	else
+		reg_2 |= (1 << 4);
+
+	err = isl6423_write(isl6423, reg_2);
+	if (err < 0)
+		goto exit;
+	return 0;
+
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg)
+{
+	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+	u8 reg_3 = isl6423->reg_3;
+	u8 reg_4 = isl6423->reg_4;
+	int err = 0;
+
+	if (arg) {
+		/* EN = 1, VSPEN = 1, VBOT = 1 */
+		reg_4 |= (1 << 4);
+		reg_4 |= 0x1;
+		reg_3 |= (1 << 3);
+	} else {
+		/* EN = 1, VSPEN = 1, VBOT = 0 */
+		reg_4 |= (1 << 4);
+		reg_4 &= ~0x1;
+		reg_3 |= (1 << 3);
+	}
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	err = isl6423_write(isl6423, reg_4);
+	if (err < 0)
+		goto exit;
+
+	isl6423->reg_3 = reg_3;
+	isl6423->reg_4 = reg_4;
+
+	return 0;
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+
+static int isl6423_set_voltage(struct dvb_frontend *fe,
+			       enum fe_sec_voltage voltage)
+{
+	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+	u8 reg_3 = isl6423->reg_3;
+	u8 reg_4 = isl6423->reg_4;
+	int err = 0;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		/* EN = 0 */
+		reg_4 &= ~(1 << 4);
+		break;
+
+	case SEC_VOLTAGE_13:
+		/* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */
+		reg_4 |= (1 << 4);
+		reg_4 &= ~0x3;
+		reg_3 |= (1 << 3);
+		break;
+
+	case SEC_VOLTAGE_18:
+		/* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */
+		reg_4 |= (1 << 4);
+		reg_4 |=  0x2;
+		reg_4 &= ~0x1;
+		reg_3 |= (1 << 3);
+		break;
+
+	default:
+		break;
+	}
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	err = isl6423_write(isl6423, reg_4);
+	if (err < 0)
+		goto exit;
+
+	isl6423->reg_3 = reg_3;
+	isl6423->reg_4 = reg_4;
+
+	return 0;
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static int isl6423_set_current(struct dvb_frontend *fe)
+{
+	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
+	u8 reg_3 = isl6423->reg_3;
+	const struct isl6423_config *config	= isl6423->config;
+	int err = 0;
+
+	switch (config->current_max) {
+	case SEC_CURRENT_275m:
+		/* 275mA */
+		/* ISELH = 0, ISELL = 0 */
+		reg_3 &= ~0x3;
+		break;
+
+	case SEC_CURRENT_515m:
+		/* 515mA */
+		/* ISELH = 0, ISELL = 1 */
+		reg_3 &= ~0x2;
+		reg_3 |=  0x1;
+		break;
+
+	case SEC_CURRENT_635m:
+		/* 635mA */
+		/* ISELH = 1, ISELL = 0 */
+		reg_3 &= ~0x1;
+		reg_3 |=  0x2;
+		break;
+
+	case SEC_CURRENT_800m:
+		/* 800mA */
+		/* ISELH = 1, ISELL = 1 */
+		reg_3 |= 0x3;
+		break;
+	}
+
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	switch (config->curlim) {
+	case SEC_CURRENT_LIM_ON:
+		/* DCL = 0 */
+		reg_3 &= ~0x10;
+		break;
+
+	case SEC_CURRENT_LIM_OFF:
+		/* DCL = 1 */
+		reg_3 |= 0x10;
+		break;
+	}
+
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	isl6423->reg_3 = reg_3;
+
+	return 0;
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static void isl6423_release(struct dvb_frontend *fe)
+{
+	isl6423_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+				    struct i2c_adapter *i2c,
+				    const struct isl6423_config *config)
+{
+	struct isl6423_dev *isl6423;
+
+	isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL);
+	if (!isl6423)
+		return NULL;
+
+	isl6423->config	= config;
+	isl6423->i2c	= i2c;
+	fe->sec_priv	= isl6423;
+
+	/* SR3H = 0, SR3M = 1, SR3L = 0 */
+	isl6423->reg_3 = 0x02 << 5;
+	/* SR4H = 0, SR4M = 1, SR4L = 1 */
+	isl6423->reg_4 = 0x03 << 5;
+
+	if (isl6423_set_current(fe))
+		goto exit;
+
+	if (isl6423_set_modulation(fe))
+		goto exit;
+
+	fe->ops.release_sec		= isl6423_release;
+	fe->ops.set_voltage		= isl6423_set_voltage;
+	fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost;
+	isl6423->verbose		= verbose;
+
+	return fe;
+
+exit:
+	kfree(isl6423);
+	fe->sec_priv = NULL;
+	return NULL;
+}
+EXPORT_SYMBOL(isl6423_attach);
+
+MODULE_DESCRIPTION("ISL6423 SEC");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/isl6423.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/isl6423.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/isl6423.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/isl6423.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+	Intersil ISL6423 SEC and LNB Power supply controller
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __ISL_6423_H
+#define __ISL_6423_H
+
+#include <linux/dvb/frontend.h>
+
+enum isl6423_current {
+	SEC_CURRENT_275m = 0,
+	SEC_CURRENT_515m,
+	SEC_CURRENT_635m,
+	SEC_CURRENT_800m,
+};
+
+enum isl6423_curlim {
+	SEC_CURRENT_LIM_ON = 1,
+	SEC_CURRENT_LIM_OFF
+};
+
+struct isl6423_config {
+	enum isl6423_current current_max;
+	enum isl6423_curlim curlim;
+	u8 addr;
+	u8 mod_extern;
+};
+
+#if defined(CONFIG_DVB_ISL6423) || (defined(CONFIG_DVB_ISL6423_MODULE) && defined(MODULE))
+
+
+extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+					   struct i2c_adapter *i2c,
+					   const struct isl6423_config *config);
+
+#else
+static inline struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+						  struct i2c_adapter *i2c,
+						  const struct isl6423_config *config)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_ISL6423 */
+
+#endif /* __ISL_6423_H */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/Kconfig linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -35,6 +35,21 @@
 	  A Silicon tuner from ST used in conjunction with the STB0899
 	  demodulator. Say Y when you want to support this tuner.
 
+config DVB_STV090x
+	tristate "STV0900/STV0903(A/B) based"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
+	  Say Y when you want to support these frontends.
+
+config DVB_STV6110x
+	tristate "STV6110/(A) based tuners"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A Silicon tuner that supports DVB-S and DVB-S2 modes
+
 comment "DVB-S (satellite) frontends"
 	depends on DVB_CORE
 
@@ -506,6 +521,13 @@
 	help
 	  An SEC control chip.
 
+config DVB_ISL6423
+	tristate "ISL6423 SEC controller"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A SEC controller chip from Intersil
+
 config DVB_LGS8GL5
 	tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
 	depends on DVB_CORE && I2C
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/l64781.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/l64781.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/l64781.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/l64781.c	2009-09-09 18:13:59.000000000 -0400
@@ -501,7 +501,7 @@
 			   { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct l64781_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lgdt3305.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lgdt3305.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lgdt3305.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lgdt3305.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,6 +19,7 @@
  *
  */
 
+#include <asm/div64.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_math.h"
 #include "lgdt3305.h"
@@ -496,27 +497,15 @@
 
 	nco = if_freq_khz / 10;
 
-#define LGDT3305_64BIT_DIVISION_ENABLED 0
-	/* FIXME: 64bit division disabled to avoid linking error:
-	 * WARNING: "__udivdi3" [lgdt3305.ko] undefined!
-	 */
 	switch (param->u.vsb.modulation) {
 	case VSB_8:
-#if LGDT3305_64BIT_DIVISION_ENABLED
 		nco <<= 24;
-		nco /= 625;
-#else
-		nco *= ((1 << 24) / 625);
-#endif
+		do_div(nco, 625);
 		break;
 	case QAM_64:
 	case QAM_256:
-#if LGDT3305_64BIT_DIVISION_ENABLED
 		nco <<= 28;
-		nco /= 625;
-#else
-		nco *= ((1 << 28) / 625);
-#endif
+		do_div(nco, 625);
 		break;
 	default:
 		return -EINVAL;
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lgs8gl5.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lgs8gl5.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lgs8gl5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lgs8gl5.c	2009-09-09 18:13:59.000000000 -0400
@@ -387,7 +387,7 @@
 	dprintk("%s\n", __func__);
 
 	/* Allocate memory for the internal state */
-	state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lgs8gxx.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lgs8gxx.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lgs8gxx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lgs8gxx.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,14 +37,14 @@
 	} while (0)
 
 static int debug;
-static int fake_signal_str;
+static int fake_signal_str = 1;
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
 module_param(fake_signal_str, int, 0644);
 MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
-"Signal strength calculation is slow.(default:off).");
+"Signal strength calculation is slow.(default:on).");
 
 /* LGS8GXX internal helper functions */
 
@@ -610,7 +610,7 @@
 	else
 		cat = 0;
 
-	*signal = cat;
+	*signal = cat * 65535 / 5;
 
 	return 0;
 }
@@ -630,8 +630,8 @@
 
 	if (fake_signal_str) {
 		if ((t & 0xC0) == 0xC0) {
-			dprintk("Fake signal strength as 50\n");
-			*signal = 0x32;
+			dprintk("Fake signal strength\n");
+			*signal = 0x7FFF;
 		} else
 			*signal = 0;
 		return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lnbp21.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lnbp21.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/lnbp21.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/lnbp21.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,7 +133,7 @@
 	/* override frontend ops */
 	fe->ops.set_voltage = lnbp21_set_voltage;
 	fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
-	printk(KERN_INFO "LNBx2x attached on addr=%x", lnbp21->i2c_addr);
+	printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
 
 	return fe;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/Makefile linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -71,4 +71,6 @@
 obj-$(CONFIG_DVB_S921) += s921.o
 obj-$(CONFIG_DVB_STV6110) += stv6110.o
 obj-$(CONFIG_DVB_STV0900) += stv0900.o
-
+obj-$(CONFIG_DVB_STV090x) += stv090x.o
+obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
+obj-$(CONFIG_DVB_ISL6423) += isl6423.o
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/mt312.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/mt312.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/mt312.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/mt312.c	2009-09-09 18:13:59.000000000 -0400
@@ -77,7 +77,7 @@
 	ret = i2c_transfer(state->i2c, msg, 2);
 
 	if (ret != 2) {
-		printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
+		printk(KERN_DEBUG "%s: ret == %d\n", __func__, ret);
 		return -EREMOTEIO;
 	}
 
@@ -782,7 +782,7 @@
 	struct mt312_state *state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct mt312_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/nxt200x.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/nxt200x.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/nxt200x.c	2012-03-22 19:12:36.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/nxt200x.c	2012-03-22 20:08:53.000000000 -0400
@@ -863,7 +863,8 @@
 
 	/* request the firmware, this will block until someone uploads it */
 	printk("nxt2002: Waiting for firmware upload (%s)...\n", "/*(DEBLOBBED)*/");
-	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/", &state->i2c->dev);
+	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
+			       state->i2c->dev.parent);
 	printk("nxt2002: Waiting for firmware upload(2)...\n");
 	if (ret) {
 		printk("nxt2002: No firmware uploaded (timeout or file not found?)\n");
@@ -927,7 +928,8 @@
 
 	/* request the firmware, this will block until someone uploads it */
 	printk("nxt2004: Waiting for firmware upload (%s)...\n", "/*(DEBLOBBED)*/");
-	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/", &state->i2c->dev);
+	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
+			       state->i2c->dev.parent);
 	printk("nxt2004: Waiting for firmware upload(2)...\n");
 	if (ret) {
 		printk("nxt2004: No firmware uploaded (timeout or file not found?)\n");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/nxt6000.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/nxt6000.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/nxt6000.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/nxt6000.c	2009-09-09 18:13:59.000000000 -0400
@@ -545,7 +545,7 @@
 	struct nxt6000_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/or51132.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/or51132.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/or51132.c	2012-03-22 19:12:39.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/or51132.c	2012-03-22 20:08:55.000000000 -0400
@@ -335,7 +335,7 @@
 		}
 		printk("or51132: Waiting for firmware upload(%s)...\n",
 		       fwname);
-		ret = reject_firmware(&fw, fwname, &state->i2c->dev);
+		ret = reject_firmware(&fw, fwname, state->i2c->dev.parent);
 		if (ret) {
 			printk(KERN_WARNING "or51132: No firmware up"
 			       "loaded(timeout or file not found?)\n");
@@ -557,7 +557,7 @@
 	struct or51132_state* state = NULL;
 
 	/* Allocate memory for the internal state */
-	state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct or51132_state), GFP_KERNEL);
 	if (state == NULL)
 		return NULL;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/or51211.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/or51211.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/or51211.c	2012-03-22 19:12:41.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/or51211.c	2012-03-22 20:08:58.000000000 -0400
@@ -521,7 +521,7 @@
 	struct or51211_state* state = NULL;
 
 	/* Allocate memory for the internal state */
-	state = kmalloc(sizeof(struct or51211_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct or51211_state), GFP_KERNEL);
 	if (state == NULL)
 		return NULL;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/s5h1409.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/s5h1409.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/s5h1409.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/s5h1409.c	2009-09-09 18:13:59.000000000 -0400
@@ -796,7 +796,7 @@
 	u16 reg;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/s5h1411.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/s5h1411.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/s5h1411.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/s5h1411.c	2009-09-09 18:13:59.000000000 -0400
@@ -844,7 +844,7 @@
 	u16 reg;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/si21xx.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/si21xx.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/si21xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/si21xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -928,7 +928,7 @@
 	dprintk("%s\n", __func__);
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/sp8870.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/sp8870.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/sp8870.c	2012-03-22 19:12:44.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/sp8870.c	2012-03-22 20:09:00.000000000 -0400
@@ -551,7 +551,7 @@
 	struct sp8870_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct sp8870_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/sp887x.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/sp887x.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/sp887x.c	2012-03-22 19:12:46.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/sp887x.c	2012-03-22 20:09:02.000000000 -0400
@@ -551,7 +551,7 @@
 	struct sp887x_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct sp887x_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct sp887x_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0288.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0288.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0288.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0288.c	2009-09-09 18:13:59.000000000 -0400
@@ -570,7 +570,7 @@
 	int id;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct stv0288_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0297.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0297.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0297.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0297.c	2009-09-09 18:13:59.000000000 -0400
@@ -663,7 +663,7 @@
 	struct stv0297_state *state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct stv0297_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0299.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0299.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0299.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0299.c	2009-09-09 18:13:59.000000000 -0400
@@ -667,7 +667,7 @@
 	int id;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct stv0299_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0900_core.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0900_core.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0900_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0900_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -149,31 +149,31 @@
 		dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
 }
 
-u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg_addr)
+u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg)
 {
-	u8 data[2];
 	int ret;
-	struct i2c_msg i2cmsg = {
-		.addr  = i_params->i2c_addr,
-		.flags = 0,
-		.len   = 2,
-		.buf   = data,
+	u8 b0[] = { MSB(reg), LSB(reg) };
+	u8 buf = 0;
+	struct i2c_msg msg[] = {
+		{
+			.addr	= i_params->i2c_addr,
+			.flags	= 0,
+			.buf = b0,
+			.len = 2,
+		}, {
+			.addr	= i_params->i2c_addr,
+			.flags	= I2C_M_RD,
+			.buf = &buf,
+			.len = 1,
+		},
 	};
 
-	data[0] = MSB(reg_addr);
-	data[1] = LSB(reg_addr);
-
-	ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
-	if (ret != 1)
-		dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
-
-	i2cmsg.flags = I2C_M_RD;
-	i2cmsg.len = 1;
-	ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
-	if (ret != 1)
-		dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
+	ret = i2c_transfer(i_params->i2c_adap, msg, 2);
+	if (ret != 2)
+		dprintk(KERN_ERR "%s: i2c error %d, reg[0x%02x]\n",
+				__func__, ret, reg);
 
-	return data[0];
+	return buf;
 }
 
 void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
@@ -712,6 +712,44 @@
 	return c_n;
 }
 
+static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	u8 err_val1, err_val0;
+	s32 err_field1, err_field0;
+	u32 header_err_val = 0;
+
+	*ucblocks = 0x0;
+	if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
+		/* DVB-S2 delineator errors count */
+
+		/* retreiving number for errnous headers */
+		dmd_reg(err_field0, R0900_P1_BBFCRCKO0,
+					R0900_P2_BBFCRCKO0);
+		dmd_reg(err_field1, R0900_P1_BBFCRCKO1,
+					R0900_P2_BBFCRCKO1);
+
+		err_val1 = stv0900_read_reg(i_params, err_field1);
+		err_val0 = stv0900_read_reg(i_params, err_field0);
+		header_err_val = (err_val1<<8) | err_val0;
+
+		/* retreiving number for errnous packets */
+		dmd_reg(err_field0, R0900_P1_UPCRCKO0,
+					R0900_P2_UPCRCKO0);
+		dmd_reg(err_field1, R0900_P1_UPCRCKO1,
+					R0900_P2_UPCRCKO1);
+
+		err_val1 = stv0900_read_reg(i_params, err_field1);
+		err_val0 = stv0900_read_reg(i_params, err_field0);
+		*ucblocks = (err_val1<<8) | err_val0;
+		*ucblocks += header_err_val;
+	}
+
+	return 0;
+}
+
 static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
 	*snr = stv0900_carr_get_quality(fe,
@@ -1355,7 +1393,7 @@
 	struct stv0900_state *state = fe->demodulator_priv;
 	enum fe_stv0900_error error = STV0900_NO_ERROR;
 	enum fe_stv0900_error demodError = STV0900_NO_ERROR;
-	int selosci;
+	int selosci, i;
 
 	struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
 						state->config->demod_address);
@@ -1402,7 +1440,23 @@
 				stv0900_write_bits(state->internal, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff);
 				stv0900_write_bits(state->internal, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff);
 
-				stv0900_set_ts_parallel_serial(state->internal, p_init->path1_ts_clock, p_init->path2_ts_clock);
+				state->internal->ts_config = p_init->ts_config;
+				if (state->internal->ts_config == NULL)
+					stv0900_set_ts_parallel_serial(state->internal,
+							p_init->path1_ts_clock,
+							p_init->path2_ts_clock);
+				else {
+					for (i = 0; state->internal->ts_config[i].addr != 0xffff; i++)
+						stv0900_write_reg(state->internal,
+								state->internal->ts_config[i].addr,
+								state->internal->ts_config[i].val);
+
+					stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 1);
+					stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 0);
+					stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 1);
+					stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 0);
+				}
+
 				stv0900_write_bits(state->internal, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
 				switch (p_init->tuner1_adc) {
 				case 1:
@@ -1882,6 +1936,7 @@
 	.read_ber			= stv0900_read_ber,
 	.read_signal_strength		= stv0900_read_signal_strength,
 	.read_snr			= stv0900_read_snr,
+	.read_ucblocks                  = stv0900_read_ucblocks,
 };
 
 struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
@@ -1915,6 +1970,7 @@
 		init_params.tun1_iq_inversion	= STV0900_IQ_NORMAL;
 		init_params.tuner1_adc		= config->tun1_adc;
 		init_params.path2_ts_clock	= config->path2_mode;
+		init_params.ts_config		= config->ts_config_regs;
 		init_params.tun2_maddress	= config->tun2_maddress;
 		init_params.tuner2_adc		= config->tun2_adc;
 		init_params.tun2_iq_inversion	= STV0900_IQ_SWAPPED;
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0900.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0900.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0900.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0900.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,11 @@
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
+struct stv0900_reg {
+	u16 addr;
+	u8  val;
+};
+
 struct stv0900_config {
 	u8 demod_address;
 	u32 xtal;
@@ -38,7 +43,7 @@
 
 	u8 path1_mode;
 	u8 path2_mode;
-
+	struct stv0900_reg *ts_config_regs;
 	u8 tun1_maddress;/* 0, 1, 2, 3 for 0xc0, 0xc2, 0xc4, 0xc6 */
 	u8 tun2_maddress;
 	u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0900_priv.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0900_priv.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv0900_priv.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv0900_priv.h	2009-09-09 18:13:59.000000000 -0400
@@ -60,8 +60,6 @@
 		} \
 	} while (0)
 
-#define dmd_choose(a, b)	(demod = STV0900_DEMOD_2 ? b : a))
-
 static int stvdebug;
 
 #define dprintk(args...) \
@@ -273,6 +271,7 @@
 
 	/* IQ from the tuner2 to the demod */
 	enum stv0900_iq_inversion	tun2_iq_inversion;
+	struct stv0900_reg		*ts_config;
 };
 
 struct stv0900_search_params {
@@ -365,6 +364,7 @@
 	u8			i2c_addr;
 	u8			clkmode;/* 0 for CLKI, 2 for XTALI */
 	u8			chip_id;
+	struct stv0900_reg	*ts_config;
 	enum fe_stv0900_error	errs;
 	int dmds_used;
 };
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,4302 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#include "stv6110x.h" /* for demodulator internal modes */
+
+#include "stv090x_reg.h"
+#include "stv090x.h"
+#include "stv090x_priv.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+
+struct mutex demod_lock;
+
+/* DVBS1 and DSS C/N Lookup table */
+static const struct stv090x_tab stv090x_s1cn_tab[] = {
+	{   0, 8917 }, /*  0.0dB */
+	{   5, 8801 }, /*  0.5dB */
+	{  10, 8667 }, /*  1.0dB */
+	{  15, 8522 }, /*  1.5dB */
+	{  20, 8355 }, /*  2.0dB */
+	{  25, 8175 }, /*  2.5dB */
+	{  30, 7979 }, /*  3.0dB */
+	{  35, 7763 }, /*  3.5dB */
+	{  40, 7530 }, /*  4.0dB */
+	{  45, 7282 }, /*  4.5dB */
+	{  50, 7026 }, /*  5.0dB */
+	{  55, 6781 }, /*  5.5dB */
+	{  60, 6514 }, /*  6.0dB */
+	{  65, 6241 }, /*  6.5dB */
+	{  70, 5965 }, /*  7.0dB */
+	{  75, 5690 }, /*  7.5dB */
+	{  80, 5424 }, /*  8.0dB */
+	{  85, 5161 }, /*  8.5dB */
+	{  90, 4902 }, /*  9.0dB */
+	{  95, 4654 }, /*  9.5dB */
+	{ 100, 4417 }, /* 10.0dB */
+	{ 105, 4186 }, /* 10.5dB */
+	{ 110, 3968 }, /* 11.0dB */
+	{ 115, 3757 }, /* 11.5dB */
+	{ 120, 3558 }, /* 12.0dB */
+	{ 125, 3366 }, /* 12.5dB */
+	{ 130, 3185 }, /* 13.0dB */
+	{ 135, 3012 }, /* 13.5dB */
+	{ 140, 2850 }, /* 14.0dB */
+	{ 145, 2698 }, /* 14.5dB */
+	{ 150, 2550 }, /* 15.0dB */
+	{ 160, 2283 }, /* 16.0dB */
+	{ 170, 2042 }, /* 17.0dB */
+	{ 180, 1827 }, /* 18.0dB */
+	{ 190, 1636 }, /* 19.0dB */
+	{ 200, 1466 }, /* 20.0dB */
+	{ 210, 1315 }, /* 21.0dB */
+	{ 220, 1181 }, /* 22.0dB */
+	{ 230, 1064 }, /* 23.0dB */
+	{ 240,	960 }, /* 24.0dB */
+	{ 250,	869 }, /* 25.0dB */
+	{ 260,	792 }, /* 26.0dB */
+	{ 270,	724 }, /* 27.0dB */
+	{ 280,	665 }, /* 28.0dB */
+	{ 290,	616 }, /* 29.0dB */
+	{ 300,	573 }, /* 30.0dB */
+	{ 310,	537 }, /* 31.0dB */
+	{ 320,	507 }, /* 32.0dB */
+	{ 330,	483 }, /* 33.0dB */
+	{ 400,	398 }, /* 40.0dB */
+	{ 450,	381 }, /* 45.0dB */
+	{ 500,	377 }  /* 50.0dB */
+};
+
+/* DVBS2 C/N Lookup table */
+static const struct stv090x_tab stv090x_s2cn_tab[] = {
+	{ -30, 13348 }, /* -3.0dB */
+	{ -20, 12640 }, /* -2d.0B */
+	{ -10, 11883 }, /* -1.0dB */
+	{   0, 11101 }, /* -0.0dB */
+	{   5, 10718 }, /*  0.5dB */
+	{  10, 10339 }, /*  1.0dB */
+	{  15,  9947 }, /*  1.5dB */
+	{  20,  9552 }, /*  2.0dB */
+	{  25,  9183 }, /*  2.5dB */
+	{  30,  8799 }, /*  3.0dB */
+	{  35,  8422 }, /*  3.5dB */
+	{  40,  8062 }, /*  4.0dB */
+	{  45,  7707 }, /*  4.5dB */
+	{  50,  7353 }, /*  5.0dB */
+	{  55,  7025 }, /*  5.5dB */
+	{  60,  6684 }, /*  6.0dB */
+	{  65,  6331 }, /*  6.5dB */
+	{  70,  6036 }, /*  7.0dB */
+	{  75,  5727 }, /*  7.5dB */
+	{  80,  5437 }, /*  8.0dB */
+	{  85,  5164 }, /*  8.5dB */
+	{  90,  4902 }, /*  9.0dB */
+	{  95,  4653 }, /*  9.5dB */
+	{ 100,  4408 }, /* 10.0dB */
+	{ 105,  4187 }, /* 10.5dB */
+	{ 110,  3961 }, /* 11.0dB */
+	{ 115,  3751 }, /* 11.5dB */
+	{ 120,  3558 }, /* 12.0dB */
+	{ 125,  3368 }, /* 12.5dB */
+	{ 130,  3191 }, /* 13.0dB */
+	{ 135,  3017 }, /* 13.5dB */
+	{ 140,  2862 }, /* 14.0dB */
+	{ 145,  2710 }, /* 14.5dB */
+	{ 150,  2565 }, /* 15.0dB */
+	{ 160,  2300 }, /* 16.0dB */
+	{ 170,  2058 }, /* 17.0dB */
+	{ 180,  1849 }, /* 18.0dB */
+	{ 190,  1663 }, /* 19.0dB */
+	{ 200,  1495 }, /* 20.0dB */
+	{ 210,  1349 }, /* 21.0dB */
+	{ 220,  1222 }, /* 22.0dB */
+	{ 230,  1110 }, /* 23.0dB */
+	{ 240,  1011 }, /* 24.0dB */
+	{ 250,   925 }, /* 25.0dB */
+	{ 260,   853 }, /* 26.0dB */
+	{ 270,   789 }, /* 27.0dB */
+	{ 280,   734 }, /* 28.0dB */
+	{ 290,   690 }, /* 29.0dB */
+	{ 300,   650 }, /* 30.0dB */
+	{ 310,   619 }, /* 31.0dB */
+	{ 320,   593 }, /* 32.0dB */
+	{ 330,   571 }, /* 33.0dB */
+	{ 400,   498 }, /* 40.0dB */
+	{ 450,	 484 }, /* 45.0dB */
+	{ 500,	 481 }	/* 50.0dB */
+};
+
+/* RF level C/N lookup table */
+static const struct stv090x_tab stv090x_rf_tab[] = {
+	{  -5, 0xcaa1 }, /*  -5dBm */
+	{ -10, 0xc229 }, /* -10dBm */
+	{ -15, 0xbb08 }, /* -15dBm */
+	{ -20, 0xb4bc }, /* -20dBm */
+	{ -25, 0xad5a }, /* -25dBm */
+	{ -30, 0xa298 }, /* -30dBm */
+	{ -35, 0x98a8 }, /* -35dBm */
+	{ -40, 0x8389 }, /* -40dBm */
+	{ -45, 0x59be }, /* -45dBm */
+	{ -50, 0x3a14 }, /* -50dBm */
+	{ -55, 0x2d11 }, /* -55dBm */
+	{ -60, 0x210d }, /* -60dBm */
+	{ -65, 0xa14f }, /* -65dBm */
+	{ -70, 0x07aa }	 /* -70dBm */
+};
+
+
+static struct stv090x_reg stv0900_initval[] = {
+
+	{ STV090x_OUTCFG,		0x00 },
+	{ STV090x_MODECFG,		0xff },
+	{ STV090x_AGCRF1CFG,		0x11 },
+	{ STV090x_AGCRF2CFG,		0x13 },
+	{ STV090x_TSGENERAL1X,		0x14 },
+	{ STV090x_TSTTNR2,		0x21 },
+	{ STV090x_TSTTNR4,		0x21 },
+	{ STV090x_P2_DISTXCTL,		0x22 },
+	{ STV090x_P2_F22TX,		0xc0 },
+	{ STV090x_P2_F22RX,		0xc0 },
+	{ STV090x_P2_DISRXCTL,		0x00 },
+	{ STV090x_P2_DMDCFGMD,		0xF9 },
+	{ STV090x_P2_DEMOD,		0x08 },
+	{ STV090x_P2_DMDCFG3,		0xc4 },
+	{ STV090x_P2_CARFREQ,		0xed },
+	{ STV090x_P2_LDT,		0xd0 },
+	{ STV090x_P2_LDT2,		0xb8 },
+	{ STV090x_P2_TMGCFG,		0xd2 },
+	{ STV090x_P2_TMGTHRISE,		0x20 },
+	{ STV090x_P1_TMGCFG,		0xd2 },
+
+	{ STV090x_P2_TMGTHFALL,		0x00 },
+	{ STV090x_P2_FECSPY,		0x88 },
+	{ STV090x_P2_FSPYDATA,		0x3a },
+	{ STV090x_P2_FBERCPT4,		0x00 },
+	{ STV090x_P2_FSPYBER,		0x10 },
+	{ STV090x_P2_ERRCTRL1,		0x35 },
+	{ STV090x_P2_ERRCTRL2,		0xc1 },
+	{ STV090x_P2_CFRICFG,		0xf8 },
+	{ STV090x_P2_NOSCFG,		0x1c },
+	{ STV090x_P2_DMDTOM,		0x20 },
+	{ STV090x_P2_CORRELMANT,	0x70 },
+	{ STV090x_P2_CORRELABS,		0x88 },
+	{ STV090x_P2_AGC2O,		0x5b },
+	{ STV090x_P2_AGC2REF,		0x38 },
+	{ STV090x_P2_CARCFG,		0xe4 },
+	{ STV090x_P2_ACLC,		0x1A },
+	{ STV090x_P2_BCLC,		0x09 },
+	{ STV090x_P2_CARHDR,		0x08 },
+	{ STV090x_P2_KREFTMG,		0xc1 },
+	{ STV090x_P2_SFRUPRATIO,	0xf0 },
+	{ STV090x_P2_SFRLOWRATIO,	0x70 },
+	{ STV090x_P2_SFRSTEP,		0x58 },
+	{ STV090x_P2_TMGCFG2,		0x01 },
+	{ STV090x_P2_CAR2CFG,		0x26 },
+	{ STV090x_P2_BCLC2S2Q,		0x86 },
+	{ STV090x_P2_BCLC2S28,		0x86 },
+	{ STV090x_P2_SMAPCOEF7,		0x77 },
+	{ STV090x_P2_SMAPCOEF6,		0x85 },
+	{ STV090x_P2_SMAPCOEF5,		0x77 },
+	{ STV090x_P2_TSCFGL,		0x20 },
+	{ STV090x_P2_DMDCFG2,		0x3b },
+	{ STV090x_P2_MODCODLST0,	0xff },
+	{ STV090x_P2_MODCODLST1,	0xff },
+	{ STV090x_P2_MODCODLST2,	0xff },
+	{ STV090x_P2_MODCODLST3,	0xff },
+	{ STV090x_P2_MODCODLST4,	0xff },
+	{ STV090x_P2_MODCODLST5,	0xff },
+	{ STV090x_P2_MODCODLST6,	0xff },
+	{ STV090x_P2_MODCODLST7,	0xcc },
+	{ STV090x_P2_MODCODLST8,	0xcc },
+	{ STV090x_P2_MODCODLST9,	0xcc },
+	{ STV090x_P2_MODCODLSTA,	0xcc },
+	{ STV090x_P2_MODCODLSTB,	0xcc },
+	{ STV090x_P2_MODCODLSTC,	0xcc },
+	{ STV090x_P2_MODCODLSTD,	0xcc },
+	{ STV090x_P2_MODCODLSTE,	0xcc },
+	{ STV090x_P2_MODCODLSTF,	0xcf },
+	{ STV090x_P1_DISTXCTL,		0x22 },
+	{ STV090x_P1_F22TX,		0xc0 },
+	{ STV090x_P1_F22RX,		0xc0 },
+	{ STV090x_P1_DISRXCTL,		0x00 },
+	{ STV090x_P1_DMDCFGMD,		0xf9 },
+	{ STV090x_P1_DEMOD,		0x08 },
+	{ STV090x_P1_DMDCFG3,		0xc4 },
+	{ STV090x_P1_DMDTOM,		0x20 },
+	{ STV090x_P1_CARFREQ,		0xed },
+	{ STV090x_P1_LDT,		0xd0 },
+	{ STV090x_P1_LDT2,		0xb8 },
+	{ STV090x_P1_TMGCFG,		0xd2 },
+	{ STV090x_P1_TMGTHRISE,		0x20 },
+	{ STV090x_P1_TMGTHFALL,		0x00 },
+	{ STV090x_P1_SFRUPRATIO,	0xf0 },
+	{ STV090x_P1_SFRLOWRATIO,	0x70 },
+	{ STV090x_P1_TSCFGL,		0x20 },
+	{ STV090x_P1_FECSPY,		0x88 },
+	{ STV090x_P1_FSPYDATA,		0x3a },
+	{ STV090x_P1_FBERCPT4,		0x00 },
+	{ STV090x_P1_FSPYBER,		0x10 },
+	{ STV090x_P1_ERRCTRL1,		0x35 },
+	{ STV090x_P1_ERRCTRL2,		0xc1 },
+	{ STV090x_P1_CFRICFG,		0xf8 },
+	{ STV090x_P1_NOSCFG,		0x1c },
+	{ STV090x_P1_CORRELMANT,	0x70 },
+	{ STV090x_P1_CORRELABS,		0x88 },
+	{ STV090x_P1_AGC2O,		0x5b },
+	{ STV090x_P1_AGC2REF,		0x38 },
+	{ STV090x_P1_CARCFG,		0xe4 },
+	{ STV090x_P1_ACLC,		0x1A },
+	{ STV090x_P1_BCLC,		0x09 },
+	{ STV090x_P1_CARHDR,		0x08 },
+	{ STV090x_P1_KREFTMG,		0xc1 },
+	{ STV090x_P1_SFRSTEP,		0x58 },
+	{ STV090x_P1_TMGCFG2,		0x01 },
+	{ STV090x_P1_CAR2CFG,		0x26 },
+	{ STV090x_P1_BCLC2S2Q,		0x86 },
+	{ STV090x_P1_BCLC2S28,		0x86 },
+	{ STV090x_P1_SMAPCOEF7,		0x77 },
+	{ STV090x_P1_SMAPCOEF6,		0x85 },
+	{ STV090x_P1_SMAPCOEF5,		0x77 },
+	{ STV090x_P1_DMDCFG2,		0x3b },
+	{ STV090x_P1_MODCODLST0,	0xff },
+	{ STV090x_P1_MODCODLST1,	0xff },
+	{ STV090x_P1_MODCODLST2,	0xff },
+	{ STV090x_P1_MODCODLST3,	0xff },
+	{ STV090x_P1_MODCODLST4,	0xff },
+	{ STV090x_P1_MODCODLST5,	0xff },
+	{ STV090x_P1_MODCODLST6,	0xff },
+	{ STV090x_P1_MODCODLST7,	0xcc },
+	{ STV090x_P1_MODCODLST8,	0xcc },
+	{ STV090x_P1_MODCODLST9,	0xcc },
+	{ STV090x_P1_MODCODLSTA,	0xcc },
+	{ STV090x_P1_MODCODLSTB,	0xcc },
+	{ STV090x_P1_MODCODLSTC,	0xcc },
+	{ STV090x_P1_MODCODLSTD,	0xcc },
+	{ STV090x_P1_MODCODLSTE,	0xcc },
+	{ STV090x_P1_MODCODLSTF,	0xcf },
+	{ STV090x_GENCFG,		0x1d },
+	{ STV090x_NBITER_NF4,		0x37 },
+	{ STV090x_NBITER_NF5,		0x29 },
+	{ STV090x_NBITER_NF6,		0x37 },
+	{ STV090x_NBITER_NF7,		0x33 },
+	{ STV090x_NBITER_NF8,		0x31 },
+	{ STV090x_NBITER_NF9,		0x2f },
+	{ STV090x_NBITER_NF10,		0x39 },
+	{ STV090x_NBITER_NF11,		0x3a },
+	{ STV090x_NBITER_NF12,		0x29 },
+	{ STV090x_NBITER_NF13,		0x37 },
+	{ STV090x_NBITER_NF14,		0x33 },
+	{ STV090x_NBITER_NF15,		0x2f },
+	{ STV090x_NBITER_NF16,		0x39 },
+	{ STV090x_NBITER_NF17,		0x3a },
+	{ STV090x_NBITERNOERR,		0x04 },
+	{ STV090x_GAINLLR_NF4,		0x0C },
+	{ STV090x_GAINLLR_NF5,		0x0F },
+	{ STV090x_GAINLLR_NF6,		0x11 },
+	{ STV090x_GAINLLR_NF7,		0x14 },
+	{ STV090x_GAINLLR_NF8,		0x17 },
+	{ STV090x_GAINLLR_NF9,		0x19 },
+	{ STV090x_GAINLLR_NF10,		0x20 },
+	{ STV090x_GAINLLR_NF11,		0x21 },
+	{ STV090x_GAINLLR_NF12,		0x0D },
+	{ STV090x_GAINLLR_NF13,		0x0F },
+	{ STV090x_GAINLLR_NF14,		0x13 },
+	{ STV090x_GAINLLR_NF15,		0x1A },
+	{ STV090x_GAINLLR_NF16,		0x1F },
+	{ STV090x_GAINLLR_NF17,		0x21 },
+	{ STV090x_RCCFGH,		0x20 },
+	{ STV090x_P1_FECM,		0x01 }, /* disable DSS modes */
+	{ STV090x_P2_FECM,		0x01 }, /* disable DSS modes */
+	{ STV090x_P1_PRVIT,		0x2F }, /* disable PR 6/7 */
+	{ STV090x_P2_PRVIT,		0x2F }, /* disable PR 6/7 */
+};
+
+static struct stv090x_reg stv0903_initval[] = {
+	{ STV090x_OUTCFG,		0x00 },
+	{ STV090x_AGCRF1CFG,		0x11 },
+	{ STV090x_STOPCLK1,		0x48 },
+	{ STV090x_STOPCLK2,		0x14 },
+	{ STV090x_TSTTNR1,		0x27 },
+	{ STV090x_TSTTNR2,		0x21 },
+	{ STV090x_P1_DISTXCTL,		0x22 },
+	{ STV090x_P1_F22TX,		0xc0 },
+	{ STV090x_P1_F22RX,		0xc0 },
+	{ STV090x_P1_DISRXCTL,		0x00 },
+	{ STV090x_P1_DMDCFGMD,		0xF9 },
+	{ STV090x_P1_DEMOD,		0x08 },
+	{ STV090x_P1_DMDCFG3,		0xc4 },
+	{ STV090x_P1_CARFREQ,		0xed },
+	{ STV090x_P1_TNRCFG2,		0x82 },
+	{ STV090x_P1_LDT,		0xd0 },
+	{ STV090x_P1_LDT2,		0xb8 },
+	{ STV090x_P1_TMGCFG,		0xd2 },
+	{ STV090x_P1_TMGTHRISE,		0x20 },
+	{ STV090x_P1_TMGTHFALL,		0x00 },
+	{ STV090x_P1_SFRUPRATIO,	0xf0 },
+	{ STV090x_P1_SFRLOWRATIO,	0x70 },
+	{ STV090x_P1_TSCFGL,		0x20 },
+	{ STV090x_P1_FECSPY,		0x88 },
+	{ STV090x_P1_FSPYDATA,		0x3a },
+	{ STV090x_P1_FBERCPT4,		0x00 },
+	{ STV090x_P1_FSPYBER,		0x10 },
+	{ STV090x_P1_ERRCTRL1,		0x35 },
+	{ STV090x_P1_ERRCTRL2,		0xc1 },
+	{ STV090x_P1_CFRICFG,		0xf8 },
+	{ STV090x_P1_NOSCFG,		0x1c },
+	{ STV090x_P1_DMDTOM,		0x20 },
+	{ STV090x_P1_CORRELMANT,	0x70 },
+	{ STV090x_P1_CORRELABS,		0x88 },
+	{ STV090x_P1_AGC2O,		0x5b },
+	{ STV090x_P1_AGC2REF,		0x38 },
+	{ STV090x_P1_CARCFG,		0xe4 },
+	{ STV090x_P1_ACLC,		0x1A },
+	{ STV090x_P1_BCLC,		0x09 },
+	{ STV090x_P1_CARHDR,		0x08 },
+	{ STV090x_P1_KREFTMG,		0xc1 },
+	{ STV090x_P1_SFRSTEP,		0x58 },
+	{ STV090x_P1_TMGCFG2,		0x01 },
+	{ STV090x_P1_CAR2CFG,		0x26 },
+	{ STV090x_P1_BCLC2S2Q,		0x86 },
+	{ STV090x_P1_BCLC2S28,		0x86 },
+	{ STV090x_P1_SMAPCOEF7,		0x77 },
+	{ STV090x_P1_SMAPCOEF6,		0x85 },
+	{ STV090x_P1_SMAPCOEF5,		0x77 },
+	{ STV090x_P1_DMDCFG2,		0x3b },
+	{ STV090x_P1_MODCODLST0,	0xff },
+	{ STV090x_P1_MODCODLST1,	0xff },
+	{ STV090x_P1_MODCODLST2,	0xff },
+	{ STV090x_P1_MODCODLST3,	0xff },
+	{ STV090x_P1_MODCODLST4,	0xff },
+	{ STV090x_P1_MODCODLST5,	0xff },
+	{ STV090x_P1_MODCODLST6,	0xff },
+	{ STV090x_P1_MODCODLST7,	0xcc },
+	{ STV090x_P1_MODCODLST8,	0xcc },
+	{ STV090x_P1_MODCODLST9,	0xcc },
+	{ STV090x_P1_MODCODLSTA,	0xcc },
+	{ STV090x_P1_MODCODLSTB,	0xcc },
+	{ STV090x_P1_MODCODLSTC,	0xcc },
+	{ STV090x_P1_MODCODLSTD,	0xcc },
+	{ STV090x_P1_MODCODLSTE,	0xcc },
+	{ STV090x_P1_MODCODLSTF,	0xcf },
+	{ STV090x_GENCFG,		0x1c },
+	{ STV090x_NBITER_NF4,		0x37 },
+	{ STV090x_NBITER_NF5,		0x29 },
+	{ STV090x_NBITER_NF6,		0x37 },
+	{ STV090x_NBITER_NF7,		0x33 },
+	{ STV090x_NBITER_NF8,		0x31 },
+	{ STV090x_NBITER_NF9,		0x2f },
+	{ STV090x_NBITER_NF10,		0x39 },
+	{ STV090x_NBITER_NF11,		0x3a },
+	{ STV090x_NBITER_NF12,		0x29 },
+	{ STV090x_NBITER_NF13,		0x37 },
+	{ STV090x_NBITER_NF14,		0x33 },
+	{ STV090x_NBITER_NF15,		0x2f },
+	{ STV090x_NBITER_NF16,		0x39 },
+	{ STV090x_NBITER_NF17,		0x3a },
+	{ STV090x_NBITERNOERR,		0x04 },
+	{ STV090x_GAINLLR_NF4,		0x0C },
+	{ STV090x_GAINLLR_NF5,		0x0F },
+	{ STV090x_GAINLLR_NF6,		0x11 },
+	{ STV090x_GAINLLR_NF7,		0x14 },
+	{ STV090x_GAINLLR_NF8,		0x17 },
+	{ STV090x_GAINLLR_NF9,		0x19 },
+	{ STV090x_GAINLLR_NF10,		0x20 },
+	{ STV090x_GAINLLR_NF11,		0x21 },
+	{ STV090x_GAINLLR_NF12,		0x0D },
+	{ STV090x_GAINLLR_NF13,		0x0F },
+	{ STV090x_GAINLLR_NF14,		0x13 },
+	{ STV090x_GAINLLR_NF15,		0x1A },
+	{ STV090x_GAINLLR_NF16,		0x1F },
+	{ STV090x_GAINLLR_NF17,		0x21 },
+	{ STV090x_RCCFGH,		0x20 },
+	{ STV090x_P1_FECM,		0x01 }, /*disable the DSS mode */
+	{ STV090x_P1_PRVIT,		0x2f }  /*disable puncture rate 6/7*/
+};
+
+static struct stv090x_reg stv0900_cut20_val[] = {
+
+	{ STV090x_P2_DMDCFG3,		0xe8 },
+	{ STV090x_P2_DMDCFG4,		0x10 },
+	{ STV090x_P2_CARFREQ,		0x38 },
+	{ STV090x_P2_CARHDR,		0x20 },
+	{ STV090x_P2_KREFTMG,		0x5a },
+	{ STV090x_P2_SMAPCOEF7,		0x06 },
+	{ STV090x_P2_SMAPCOEF6,		0x00 },
+	{ STV090x_P2_SMAPCOEF5,		0x04 },
+	{ STV090x_P2_NOSCFG,		0x0c },
+	{ STV090x_P1_DMDCFG3,		0xe8 },
+	{ STV090x_P1_DMDCFG4,		0x10 },
+	{ STV090x_P1_CARFREQ,		0x38 },
+	{ STV090x_P1_CARHDR,		0x20 },
+	{ STV090x_P1_KREFTMG,		0x5a },
+	{ STV090x_P1_SMAPCOEF7,		0x06 },
+	{ STV090x_P1_SMAPCOEF6,		0x00 },
+	{ STV090x_P1_SMAPCOEF5,		0x04 },
+	{ STV090x_P1_NOSCFG,		0x0c },
+	{ STV090x_GAINLLR_NF4,		0x21 },
+	{ STV090x_GAINLLR_NF5,		0x21 },
+	{ STV090x_GAINLLR_NF6,		0x20 },
+	{ STV090x_GAINLLR_NF7,		0x1F },
+	{ STV090x_GAINLLR_NF8,		0x1E },
+	{ STV090x_GAINLLR_NF9,		0x1E },
+	{ STV090x_GAINLLR_NF10,		0x1D },
+	{ STV090x_GAINLLR_NF11,		0x1B },
+	{ STV090x_GAINLLR_NF12,		0x20 },
+	{ STV090x_GAINLLR_NF13,		0x20 },
+	{ STV090x_GAINLLR_NF14,		0x20 },
+	{ STV090x_GAINLLR_NF15,		0x20 },
+	{ STV090x_GAINLLR_NF16,		0x20 },
+	{ STV090x_GAINLLR_NF17,		0x21 },
+};
+
+static struct stv090x_reg stv0903_cut20_val[] = {
+	{ STV090x_P1_DMDCFG3,		0xe8 },
+	{ STV090x_P1_DMDCFG4,		0x10 },
+	{ STV090x_P1_CARFREQ,		0x38 },
+	{ STV090x_P1_CARHDR,		0x20 },
+	{ STV090x_P1_KREFTMG,		0x5a },
+	{ STV090x_P1_SMAPCOEF7,		0x06 },
+	{ STV090x_P1_SMAPCOEF6,		0x00 },
+	{ STV090x_P1_SMAPCOEF5,		0x04 },
+	{ STV090x_P1_NOSCFG,		0x0c },
+	{ STV090x_GAINLLR_NF4,		0x21 },
+	{ STV090x_GAINLLR_NF5,		0x21 },
+	{ STV090x_GAINLLR_NF6,		0x20 },
+	{ STV090x_GAINLLR_NF7,		0x1F },
+	{ STV090x_GAINLLR_NF8,		0x1E },
+	{ STV090x_GAINLLR_NF9,		0x1E },
+	{ STV090x_GAINLLR_NF10,		0x1D },
+	{ STV090x_GAINLLR_NF11,		0x1B },
+	{ STV090x_GAINLLR_NF12,		0x20 },
+	{ STV090x_GAINLLR_NF13,		0x20 },
+	{ STV090x_GAINLLR_NF14,		0x20 },
+	{ STV090x_GAINLLR_NF15,		0x20 },
+	{ STV090x_GAINLLR_NF16,		0x20 },
+	{ STV090x_GAINLLR_NF17,		0x21 }
+};
+
+/* Cut 2.0 Long Frame Tracking CR loop */
+static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_12,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e },
+	{ STV090x_QPSK_35,  0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e },
+	{ STV090x_QPSK_23,  0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_34,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_45,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_56,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_89,  0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_8PSK_35,  0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d },
+	{ STV090x_8PSK_23,  0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d },
+	{ STV090x_8PSK_34,  0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d },
+	{ STV090x_8PSK_56,  0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d },
+	{ STV090x_8PSK_89,  0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d },
+	{ STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d }
+};
+
+/* Cut 3.0 Long Frame Tracking CR loop */
+static	struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_12,  0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_35,  0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_23,  0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_34,  0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_45,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_QPSK_56,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_QPSK_89,  0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_8PSK_35,  0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 },
+	{ STV090x_8PSK_23,  0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a },
+	{ STV090x_8PSK_34,  0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a },
+	{ STV090x_8PSK_56,  0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b },
+	{ STV090x_8PSK_89,  0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b },
+	{ STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b }
+};
+
+/* Cut 2.0 Long Frame Tracking CR Loop */
+static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_16APSK_23,  0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c },
+	{ STV090x_16APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c },
+	{ STV090x_16APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
+	{ STV090x_16APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
+	{ STV090x_16APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
+	{ STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
+	{ STV090x_32APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }
+};
+
+/* Cut 3.0 Long Frame Tracking CR Loop */
+static struct stv090x_long_frame_crloop	stv090x_s2_apsk_crl_cut30[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_16APSK_23,  0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a },
+	{ STV090x_16APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a },
+	{ STV090x_16APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
+	{ STV090x_16APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
+	{ STV090x_16APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
+	{ STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
+	{ STV090x_32APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }
+};
+
+static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_14,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e },
+	{ STV090x_QPSK_13,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e },
+	{ STV090x_QPSK_25,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e }
+};
+
+static struct stv090x_long_frame_crloop	stv090x_s2_lowqpsk_crl_cut30[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_14,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b },
+	{ STV090x_QPSK_13,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b },
+	{ STV090x_QPSK_25,  0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b }
+};
+
+/* Cut 2.0 Short Frame Tracking CR Loop */
+static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = {
+	/* MODCOD	  2M    5M    10M   20M   30M */
+	{ STV090x_QPSK,   0x2f, 0x2e, 0x0e, 0x0e, 0x3d },
+	{ STV090x_8PSK,   0x3e, 0x0e, 0x2d, 0x0d, 0x3c },
+	{ STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d },
+	{ STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }
+};
+
+/* Cut 3.0 Short Frame Tracking CR Loop */
+static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = {
+	/* MODCOD  	  2M	5M    10M   20M	  30M */
+	{ STV090x_QPSK,   0x2C, 0x2B, 0x0B, 0x0B, 0x3A },
+	{ STV090x_8PSK,   0x3B, 0x0B, 0x2A, 0x0A, 0x39 },
+	{ STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A },
+	{ STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }
+};
+
+static inline s32 comp2(s32 __x, s32 __width)
+{
+	if (__width == 32)
+		return __x;
+	else
+		return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x;
+}
+
+static int stv090x_read_reg(struct stv090x_state *state, unsigned int reg)
+{
+	const struct stv090x_config *config = state->config;
+	int ret;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+	u8 buf;
+
+	struct i2c_msg msg[] = {
+		{ .addr	= config->address, .flags	= 0, 		.buf = b0,   .len = 2 },
+		{ .addr	= config->address, .flags	= I2C_M_RD,	.buf = &buf, .len = 1 }
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2) {
+		if (ret != -ERESTARTSYS)
+			dprintk(FE_ERROR, 1,
+				"Read error, Reg=[0x%02x], Status=%d",
+				reg, ret);
+
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
+			reg, buf);
+
+	return (unsigned int) buf;
+}
+
+static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count)
+{
+	const struct stv090x_config *config = state->config;
+	int ret;
+	u8 buf[2 + count];
+	struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count };
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	memcpy(&buf[2], data, count);
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++)
+			printk(" %02x", data[i]);
+		printk("\n");
+	}
+
+	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
+	if (ret != 1) {
+		if (ret != -ERESTARTSYS)
+			dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
+				reg, data[0], count, ret);
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
+{
+	return stv090x_write_regs(state, reg, &data, 1);
+}
+
+static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+
+	reg = STV090x_READ_DEMOD(state, I2CRPT);
+	if (enable) {
+		dprintk(FE_DEBUG, 1, "Enable Gate");
+		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0)
+			goto err;
+
+	} else {
+		dprintk(FE_DEBUG, 1, "Disable Gate");
+		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0);
+		if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static void stv090x_get_lock_tmg(struct stv090x_state *state)
+{
+	switch (state->algo) {
+	case STV090x_BLIND_SEARCH:
+		dprintk(FE_DEBUG, 1, "Blind Search");
+		if (state->srate <= 1500000) {  /*10Msps< SR <=15Msps*/
+			state->DemodTimeout = 1500;
+			state->FecTimeout = 400;
+		} else if (state->srate <= 5000000) {  /*10Msps< SR <=15Msps*/
+			state->DemodTimeout = 1000;
+			state->FecTimeout = 300;
+		} else {  /*SR >20Msps*/
+			state->DemodTimeout = 700;
+			state->FecTimeout = 100;
+		}
+		break;
+
+	case STV090x_COLD_SEARCH:
+	case STV090x_WARM_SEARCH:
+	default:
+		dprintk(FE_DEBUG, 1, "Normal Search");
+		if (state->srate <= 1000000) {  /*SR <=1Msps*/
+			state->DemodTimeout = 4500;
+			state->FecTimeout = 1700;
+		} else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */
+			state->DemodTimeout = 2500;
+			state->FecTimeout = 1100;
+		} else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */
+			state->DemodTimeout = 1000;
+			state->FecTimeout = 550;
+		} else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */
+			state->DemodTimeout = 700;
+			state->FecTimeout = 250;
+		} else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */
+			state->DemodTimeout = 400;
+			state->FecTimeout = 130;
+		} else {   /*SR >20Msps*/
+			state->DemodTimeout = 300;
+			state->FecTimeout = 100;
+		}
+		break;
+	}
+
+	if (state->algo == STV090x_WARM_SEARCH)
+		state->DemodTimeout /= 2;
+}
+
+static int stv090x_set_srate(struct stv090x_state *state, u32 srate)
+{
+	u32 sym;
+
+	if (srate > 60000000) {
+		sym  = (srate << 4); /* SR * 2^16 / master_clk */
+		sym /= (state->mclk >> 12);
+	} else if (srate > 6000000) {
+		sym  = (srate << 6);
+		sym /= (state->mclk >> 10);
+	} else {
+		sym  = (srate << 9);
+		sym /= (state->mclk >> 7);
+	}
+
+	if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate)
+{
+	u32 sym;
+
+	srate = 105 * (srate / 100);
+	if (srate > 60000000) {
+		sym  = (srate << 4); /* SR * 2^16 / master_clk */
+		sym /= (state->mclk >> 12);
+	} else if (srate > 6000000) {
+		sym  = (srate << 6);
+		sym /= (state->mclk >> 10);
+	} else {
+		sym  = (srate << 9);
+		sym /= (state->mclk >> 7);
+	}
+
+	if (sym < 0x7fff) {
+		if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */
+			goto err;
+	} else {
+		if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */
+			goto err;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate)
+{
+	u32 sym;
+
+	srate = 95 * (srate / 100);
+	if (srate > 60000000) {
+		sym  = (srate << 4); /* SR * 2^16 / master_clk */
+		sym /= (state->mclk >> 12);
+	} else if (srate > 6000000) {
+		sym  = (srate << 6);
+		sym /= (state->mclk >> 10);
+	} else {
+		sym  = (srate << 9);
+		sym /= (state->mclk >> 7);
+	}
+
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0xff)) < 0) /* MSB */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff)
+{
+	u32 ro;
+
+	switch (rolloff) {
+	case STV090x_RO_20:
+		ro = 20;
+		break;
+	case STV090x_RO_25:
+		ro = 25;
+		break;
+	case STV090x_RO_35:
+	default:
+		ro = 35;
+		break;
+	}
+
+	return srate + (srate * ro) / 100;
+}
+
+static int stv090x_set_vit_thacq(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0)
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_vit_thtracq(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0)
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_viterbi(struct stv090x_state *state)
+{
+	switch (state->search_mode) {
+	case STV090x_SEARCH_AUTO:
+		if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */
+			goto err;
+		break;
+	case STV090x_SEARCH_DVBS1:
+		if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */
+			goto err;
+		switch (state->fec) {
+		case STV090x_PR12:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR23:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR34:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR56:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR78:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0)
+				goto err;
+			break;
+
+		default:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */
+				goto err;
+			break;
+		}
+		break;
+	case STV090x_SEARCH_DSS:
+		if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0)
+			goto err;
+		switch (state->fec) {
+		case STV090x_PR12:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR23:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR67:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0)
+				goto err;
+			break;
+
+		default:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */
+				goto err;
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_stop_modcod(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0)
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_activate_modcod(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_activate_modcod_single(struct stv090x_state *state)
+{
+
+	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable)
+{
+	u32 reg;
+
+	switch (state->demod) {
+	case STV090x_DEMODULATOR_0:
+		mutex_lock(&demod_lock);
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		mutex_unlock(&demod_lock);
+		break;
+
+	case STV090x_DEMODULATOR_1:
+		mutex_lock(&demod_lock);
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		mutex_unlock(&demod_lock);
+		break;
+
+	default:
+		dprintk(FE_ERROR, 1, "Wrong demodulator!");
+		break;
+	}
+	return 0;
+err:
+	mutex_unlock(&demod_lock);
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_dvbs_track_crl(struct stv090x_state *state)
+{
+	if (state->dev_ver >= 0x30) {
+		/* Set ACLC BCLC optimised value vs SR */
+		if (state->srate >= 15000000) {
+			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0)
+				goto err;
+		} else if ((state->srate >= 7000000) && (15000000 > state->srate)) {
+			if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0)
+				goto err;
+		} else if (state->srate < 7000000) {
+			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0)
+				goto err;
+		}
+
+	} else {
+		/* Cut 2.0 */
+		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_delivery_search(struct stv090x_state *state)
+{
+	u32 reg;
+
+	switch (state->search_mode) {
+	case STV090x_SEARCH_DVBS1:
+	case STV090x_SEARCH_DSS:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		/* Activate Viterbi decoder in legacy search,
+		 * do not use FRESVIT1, might impact VITERBI2
+		 */
+		if (stv090x_vitclk_ctl(state, 0) < 0)
+			goto err;
+
+		if (stv090x_dvbs_track_crl(state) < 0)
+			goto err;
+
+		if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */
+			goto err;
+
+		if (stv090x_set_vit_thacq(state) < 0)
+			goto err;
+		if (stv090x_set_viterbi(state) < 0)
+			goto err;
+		break;
+
+	case STV090x_SEARCH_DVBS2:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		if (stv090x_vitclk_ctl(state, 1) < 0)
+			goto err;
+
+		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
+			goto err;
+
+		if (state->dev_ver <= 0x20) {
+			/* enable S2 carrier loop */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
+				goto err;
+		} else {
+			/* > Cut 3: Stop carrier 3 */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
+				goto err;
+		}
+
+		if (state->demod_mode != STV090x_SINGLE) {
+			/* Cut 2: enable link during search */
+			if (stv090x_activate_modcod(state) < 0)
+				goto err;
+		} else {
+			/* Single demodulator
+			 * Authorize SHORT and LONG frames,
+			 * QPSK, 8PSK, 16APSK and 32APSK
+			 */
+			if (stv090x_activate_modcod_single(state) < 0)
+				goto err;
+		}
+
+		break;
+
+	case STV090x_SEARCH_AUTO:
+	default:
+		/* enable DVB-S2 and DVB-S2 in Auto MODE */
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		if (stv090x_vitclk_ctl(state, 0) < 0)
+			goto err;
+
+		if (stv090x_dvbs_track_crl(state) < 0)
+			goto err;
+
+		if (state->dev_ver <= 0x20) {
+			/* enable S2 carrier loop */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
+				goto err;
+		} else {
+			/* > Cut 3: Stop carrier 3 */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
+				goto err;
+		}
+
+		if (state->demod_mode != STV090x_SINGLE) {
+			/* Cut 2: enable link during search */
+			if (stv090x_activate_modcod(state) < 0)
+				goto err;
+		} else {
+			/* Single demodulator
+			 * Authorize SHORT and LONG frames,
+			 * QPSK, 8PSK, 16APSK and 32APSK
+			 */
+			if (stv090x_activate_modcod_single(state) < 0)
+				goto err;
+		}
+
+		if (state->srate >= 2000000) {
+			/* Srate >= 2MSPS, Viterbi threshold to acquire */
+			if (stv090x_set_vit_thacq(state) < 0)
+				goto err;
+		} else {
+			/* Srate < 2MSPS, Reset Viterbi thresholdto track
+			 * and then re-acquire
+			 */
+			if (stv090x_set_vit_thtracq(state) < 0)
+				goto err;
+		}
+
+		if (stv090x_set_viterbi(state) < 0)
+			goto err;
+		break;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_start_search(struct stv090x_state *state)
+{
+	u32 reg, freq_abs;
+	s16 freq;
+
+	/* Reset demodulator */
+	reg = STV090x_READ_DEMOD(state, DMDISTATE);
+	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f);
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+		goto err;
+
+	if (state->dev_ver <= 0x20) {
+		if (state->srate <= 5000000) {
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRUP1, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0)
+				goto err;
+
+			/*enlarge the timing bandwith for Low SR*/
+			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0)
+				goto err;
+		} else {
+			/* If the symbol rate is >5 Msps
+			Set The carrier search up and low to auto mode */
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
+				goto err;
+			/*reduce the timing bandwith for high SR*/
+			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
+				goto err;
+		}
+	} else {
+		/* >= Cut 3 */
+		if (state->srate <= 5000000) {
+			/* enlarge the timing bandwith for Low SR */
+			STV090x_WRITE_DEMOD(state, RTCS2, 0x68);
+		} else {
+			/* reduce timing bandwith for high SR */
+			STV090x_WRITE_DEMOD(state, RTCS2, 0x44);
+		}
+
+		/* Set CFR min and max to manual mode */
+		STV090x_WRITE_DEMOD(state, CARCFG, 0x46);
+
+		if (state->algo == STV090x_WARM_SEARCH) {
+			/* WARM Start
+			 * CFR min = -1MHz,
+			 * CFR max = +1MHz
+			 */
+			freq_abs  = 1000 << 16;
+			freq_abs /= (state->mclk / 1000);
+			freq      = (s16) freq_abs;
+		} else {
+			/* COLD Start
+			 * CFR min =- (SearchRange / 2 + 600KHz)
+			 * CFR max = +(SearchRange / 2 + 600KHz)
+			 * (600KHz for the tuner step size)
+			 */
+			freq_abs  = (state->search_range / 2000) + 600;
+			freq_abs  = freq_abs << 16;
+			freq_abs /= (state->mclk / 1000);
+			freq      = (s16) freq_abs;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRUP1, LSB(freq)) < 0)
+			goto err;
+
+		freq *= -1;
+
+		if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0)
+			goto err;
+
+	}
+
+	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0)
+		goto err;
+
+	if (state->dev_ver >= 0x20) {
+		if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
+			goto err;
+
+		if ((state->search_mode == STV090x_DVBS1)	||
+			(state->search_mode == STV090x_DSS)	||
+			(state->search_mode == STV090x_SEARCH_AUTO)) {
+
+			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0)
+				goto err;
+		}
+	}
+
+	if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DMDCFG2);
+	STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0);
+	if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0)
+		goto err;
+
+	if (state->dev_ver >= 0x20) {
+		/*Frequency offset detector setting*/
+		if (state->srate < 2000000) {
+			if (state->dev_ver <= 0x20) {
+				/* Cut 2 */
+				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0)
+					goto err;
+			} else {
+				/* Cut 2 */
+				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0)
+					goto err;
+			}
+			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0)
+				goto err;
+		}
+
+		if (state->srate < 10000000) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0)
+				goto err;
+		} else {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0)
+				goto err;
+		}
+	} else {
+		if (state->srate < 10000000) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0)
+				goto err;
+		} else {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0)
+				goto err;
+		}
+	}
+
+	switch (state->algo) {
+	case STV090x_WARM_SEARCH:
+		/* The symbol rate and the exact
+		 * carrier Frequency are known
+		 */
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+			goto err;
+		break;
+
+	case STV090x_COLD_SEARCH:
+		/* The symbol rate is known */
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+			goto err;
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_agc2_min_level(struct stv090x_state *state)
+{
+	u32 agc2_min = 0, agc2 = 0, freq_init, freq_step, reg;
+	s32 i, j, steps, dir;
+
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */
+		goto err;
+	if (stv090x_set_srate(state, 1000000) < 0)
+		goto err;
+
+	steps  = -1 + state->search_range / 1000000;
+	steps /= 2;
+	steps  = (2 * steps) + 1;
+	if (steps < 0)
+		steps = 1;
+
+	dir = 1;
+	freq_step = (1000000 * 256) / (state->mclk / 256);
+	freq_init = 0;
+
+	for (i = 0; i < steps; i++) {
+		if (dir > 0)
+			freq_init = freq_init + (freq_step * i);
+		else
+			freq_init = freq_init - (freq_step * i);
+
+		dir = -1;
+
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */
+			goto err;
+		msleep(10);
+		for (j = 0; j < 10; j++) {
+			agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8;
+			agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+		}
+		agc2 /= 10;
+		agc2_min = 0xffff;
+		if (agc2 < 0xffff)
+			agc2_min = agc2;
+	}
+
+	return agc2_min;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk)
+{
+	u8 r3, r2, r1, r0;
+	s32 srate, int_1, int_2, tmp_1, tmp_2;
+
+	r3 = STV090x_READ_DEMOD(state, SFR3);
+	r2 = STV090x_READ_DEMOD(state, SFR2);
+	r1 = STV090x_READ_DEMOD(state, SFR1);
+	r0 = STV090x_READ_DEMOD(state, SFR0);
+
+	srate = ((r3 << 24) | (r2 << 16) | (r1 <<  8) | r0);
+
+	int_1 = clk >> 16;
+	int_2 = srate >> 16;
+
+	tmp_1 = clk % 0x10000;
+	tmp_2 = srate % 0x10000;
+
+	srate = (int_1 * int_2) +
+		((int_1 * tmp_2) >> 16) +
+		((int_2 * tmp_1) >> 16);
+
+	return srate;
+}
+
+static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	int tmg_lock = 0, i;
+	s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq;
+	u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg;
+
+	reg = STV090x_READ_DEMOD(state, DMDISTATE);
+	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0)
+		goto err;
+
+	if (state->dev_ver >= 0x30) {
+		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
+			goto err;
+
+	} else if (state->dev_ver >= 0x20) {
+		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
+			goto err;
+	}
+
+	if (state->srate <= 2000000)
+		car_step = 1000;
+	else if (state->srate <= 5000000)
+		car_step = 2000;
+	else if (state->srate <= 12000000)
+		car_step = 3000;
+	else
+		car_step = 5000;
+
+	steps  = -1 + ((state->search_range / 1000) / car_step);
+	steps /= 2;
+	steps  = (2 * steps) + 1;
+	if (steps < 0)
+		steps = 1;
+	else if (steps > 10) {
+		steps = 11;
+		car_step = (state->search_range / 1000) / 10;
+	}
+	cur_step = 0;
+	dir = 1;
+	freq = state->frequency;
+
+	while ((!tmg_lock) && (cur_step < steps)) {
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */
+			goto err;
+		reg = STV090x_READ_DEMOD(state, DMDISTATE);
+		STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x00); /* trigger acquisition */
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+			goto err;
+		msleep(50);
+		for (i = 0; i < 10; i++) {
+			reg = STV090x_READ_DEMOD(state, DSTATUS);
+			if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
+				tmg_cpt++;
+			agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8;
+			agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+		}
+		agc2 /= 10;
+		srate_coarse = stv090x_get_srate(state, state->mclk);
+		cur_step++;
+		dir *= -1;
+		if ((tmg_cpt >= 5) && (agc2 < 0x1f00) && (srate_coarse < 55000000) && (srate_coarse > 850000))
+			tmg_lock = 1;
+		else if (cur_step < steps) {
+			if (dir > 0)
+				freq += cur_step * car_step;
+			else
+				freq -= cur_step * car_step;
+
+			/* Setup tuner */
+			if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+				goto err;
+
+			if (state->config->tuner_set_frequency) {
+				if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
+					goto err;
+			}
+
+			if (state->config->tuner_set_bandwidth) {
+				if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+					goto err;
+			}
+
+			if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+				goto err;
+
+			msleep(50);
+
+			if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+				goto err;
+
+			if (state->config->tuner_get_status) {
+				if (state->config->tuner_get_status(fe, &reg) < 0)
+					goto err;
+			}
+
+			if (reg)
+				dprintk(FE_DEBUG, 1, "Tuner phase locked");
+			else
+				dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+			if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+				goto err;
+
+		}
+	}
+	if (!tmg_lock)
+		srate_coarse = 0;
+	else
+		srate_coarse = stv090x_get_srate(state, state->mclk);
+
+	return srate_coarse;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
+{
+	u32 srate_coarse, freq_coarse, sym, reg;
+
+	srate_coarse = stv090x_get_srate(state, state->mclk);
+	freq_coarse  = STV090x_READ_DEMOD(state, CFR2) << 8;
+	freq_coarse |= STV090x_READ_DEMOD(state, CFR1);
+	sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+
+	if (sym < state->srate)
+		srate_coarse = 0;
+	else {
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
+			goto err;
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		if (state->dev_ver >= 0x30) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0)
+				goto err;
+		} else if (state->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+				goto err;
+		}
+
+		if (srate_coarse > 3000000) {
+			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+			sym  = (sym / 1000) * 65536;
+			sym /= (state->mclk / 1000);
+			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
+				goto err;
+			sym  = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */
+			sym  = (sym / 1000) * 65536;
+			sym /= (state->mclk / 1000);
+			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
+				goto err;
+			sym  = (srate_coarse / 1000) * 65536;
+			sym /= (state->mclk / 1000);
+			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
+				goto err;
+		} else {
+			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+			sym  = (sym / 100) * 65536;
+			sym /= (state->mclk / 100);
+			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
+				goto err;
+			sym  = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */
+			sym  = (sym / 100) * 65536;
+			sym /= (state->mclk / 100);
+			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
+				goto err;
+			sym  = (srate_coarse / 100) * 65536;
+			sym /= (state->mclk / 100);
+			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
+				goto err;
+		}
+		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */
+			goto err;
+	}
+
+	return srate_coarse;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout)
+{
+	s32 timer = 0, lock = 0;
+	u32 reg;
+	u8 stat;
+
+	while ((timer < timeout) && (!lock)) {
+		reg = STV090x_READ_DEMOD(state, DMDSTATE);
+		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+		switch (stat) {
+		case 0: /* searching */
+		case 1: /* first PLH detected */
+		default:
+			dprintk(FE_DEBUG, 1, "Demodulator searching ..");
+			lock = 0;
+			break;
+		case 2: /* DVB-S2 mode */
+		case 3: /* DVB-S1/legacy mode */
+			reg = STV090x_READ_DEMOD(state, DSTATUS);
+			lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+			break;
+		}
+
+		if (!lock)
+			msleep(10);
+		else
+			dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK");
+
+		timer += 10;
+	}
+	return lock;
+}
+
+static int stv090x_blind_search(struct stv090x_state *state)
+{
+	u32 agc2, reg, srate_coarse;
+	s32 timeout_dmd = 500, cpt_fail, agc2_ovflw, i;
+	u8 k_ref, k_max, k_min;
+	int coarse_fail, lock;
+
+	k_max = 120;
+	k_min = 30;
+
+	agc2 = stv090x_get_agc2_min_level(state);
+
+	if (agc2 > STV090x_SEARCH_AGC2_TH(state->dev_ver)) {
+		lock = 0;
+	} else {
+
+		if (state->dev_ver <= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
+				goto err;
+		} else {
+			/* > Cut 3 */
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
+			goto err;
+
+		if (state->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */
+				goto err;
+		}
+
+		k_ref = k_max;
+		do {
+			if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0)
+				goto err;
+			if (stv090x_srate_srch_coarse(state) != 0) {
+				srate_coarse = stv090x_srate_srch_fine(state);
+				if (srate_coarse != 0) {
+					stv090x_get_lock_tmg(state);
+					lock = stv090x_get_dmdlock(state, timeout_dmd);
+				} else {
+					lock = 0;
+				}
+			} else {
+				cpt_fail = 0;
+				agc2_ovflw = 0;
+				for (i = 0; i < 10; i++) {
+					agc2  = STV090x_READ_DEMOD(state, AGC2I1) << 8;
+					agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+					if (agc2 >= 0xff00)
+						agc2_ovflw++;
+					reg = STV090x_READ_DEMOD(state, DSTATUS2);
+					if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) &&
+					    (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01))
+
+						cpt_fail++;
+				}
+				if ((cpt_fail > 7) || (agc2_ovflw > 7))
+					coarse_fail = 1;
+
+				lock = 0;
+			}
+			k_ref -= 30;
+		} while ((k_ref >= k_min) && (!lock) && (!coarse_fail));
+	}
+
+	return lock;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_chk_tmg(struct stv090x_state *state)
+{
+	u32 reg;
+	s32 tmg_cpt = 0, i;
+	u8 freq, tmg_thh, tmg_thl;
+	int tmg_lock;
+
+	freq = STV090x_READ_DEMOD(state, CARFREQ);
+	tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE);
+	tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL);
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */
+		goto err;
+	msleep(10);
+
+	for (i = 0; i < 10; i++) {
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
+			tmg_cpt++;
+		msleep(1);
+	}
+	if (tmg_cpt >= 3)
+		tmg_lock = 1;
+
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0)
+		goto err;
+
+	return	tmg_lock;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	u32 reg;
+	s32 car_step, steps, cur_step, dir, freq, timeout_lock;
+	int lock = 0;
+
+	if (state->srate >= 10000000)
+		timeout_lock = timeout_dmd / 3;
+	else
+		timeout_lock = timeout_dmd / 2;
+
+	lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
+	if (!lock) {
+		if (state->srate >= 10000000) {
+			if (stv090x_chk_tmg(state)) {
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+					goto err;
+				lock = stv090x_get_dmdlock(state, timeout_dmd);
+			} else {
+				lock = 0;
+			}
+		} else {
+			if (state->srate <= 4000000)
+				car_step = 1000;
+			else if (state->srate <= 7000000)
+				car_step = 2000;
+			else if (state->srate <= 10000000)
+				car_step = 3000;
+			else
+				car_step = 5000;
+
+			steps  = (state->search_range / 1000) / car_step;
+			steps /= 2;
+			steps  = 2 * (steps + 1);
+			if (steps < 0)
+				steps = 2;
+			else if (steps > 12)
+				steps = 12;
+
+			cur_step = 1;
+			dir = 1;
+
+			if (!lock) {
+				freq = state->frequency;
+				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
+				while ((cur_step <= steps) && (!lock)) {
+					if (dir > 0)
+						freq += cur_step * car_step;
+					else
+						freq -= cur_step * car_step;
+
+					/* Setup tuner */
+					if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+						goto err;
+
+					if (state->config->tuner_set_frequency) {
+						if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
+							goto err;
+					}
+
+					if (state->config->tuner_set_bandwidth) {
+						if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+							goto err;
+					}
+
+					if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+						goto err;
+
+					msleep(50);
+
+					if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+						goto err;
+
+					if (state->config->tuner_get_status) {
+						if (state->config->tuner_get_status(fe, &reg) < 0)
+							goto err;
+					}
+
+					if (reg)
+						dprintk(FE_DEBUG, 1, "Tuner phase locked");
+					else
+						dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+					if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+						goto err;
+
+					STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
+					if (state->delsys == STV090x_DVBS2) {
+						reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+						STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+						STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+						if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+							goto err;
+						STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+						STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+						if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+							goto err;
+					}
+					if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+						goto err;
+					lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
+
+					dir *= -1;
+					cur_step++;
+				}
+			}
+		}
+	}
+
+	return lock;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps)
+{
+	s32 timeout, inc, steps_max, srate, car_max;
+
+	srate = state->srate;
+	car_max = state->search_range / 1000;
+	car_max += car_max / 10;
+	car_max  = 65536 * (car_max / 2);
+	car_max /= (state->mclk / 1000);
+
+	if (car_max > 0x4000)
+		car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */
+
+	inc  = srate;
+	inc /= state->mclk / 1000;
+	inc *= 256;
+	inc *= 256;
+	inc /= 1000;
+
+	switch (state->search_mode) {
+	case STV090x_SEARCH_DVBS1:
+	case STV090x_SEARCH_DSS:
+		inc *= 3; /* freq step = 3% of srate */
+		timeout = 20;
+		break;
+
+	case STV090x_SEARCH_DVBS2:
+		inc *= 4;
+		timeout = 25;
+		break;
+
+	case STV090x_SEARCH_AUTO:
+	default:
+		inc *= 3;
+		timeout = 25;
+		break;
+	}
+	inc /= 100;
+	if ((inc > car_max) || (inc < 0))
+		inc = car_max / 2; /* increment <= 1/8 Mclk */
+
+	timeout *= 27500; /* 27.5 Msps reference */
+	if (srate > 0)
+		timeout /= (srate / 1000);
+
+	if ((timeout > 100) || (timeout < 0))
+		timeout = 100;
+
+	steps_max = (car_max / inc) + 1; /* min steps = 3 */
+	if ((steps_max > 100) || (steps_max < 0)) {
+		steps_max = 100; /* max steps <= 100 */
+		inc = car_max / steps_max;
+	}
+	*freq_inc = inc;
+	*timeout_sw = timeout;
+	*steps = steps_max;
+
+	return 0;
+}
+
+static int stv090x_chk_signal(struct stv090x_state *state)
+{
+	s32 offst_car, agc2, car_max;
+	int no_signal;
+
+	offst_car  = STV090x_READ_DEMOD(state, CFR2) << 8;
+	offst_car |= STV090x_READ_DEMOD(state, CFR1);
+	offst_car = comp2(offst_car, 16);
+
+	agc2  = STV090x_READ_DEMOD(state, AGC2I1) << 8;
+	agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+	car_max = state->search_range / 1000;
+
+	car_max += (car_max / 10); /* 10% margin */
+	car_max  = (65536 * car_max / 2);
+	car_max /= state->mclk / 1000;
+
+	if (car_max > 0x4000)
+		car_max = 0x4000;
+
+	if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) {
+		no_signal = 1;
+		dprintk(FE_DEBUG, 1, "No Signal");
+	} else {
+		no_signal = 0;
+		dprintk(FE_DEBUG, 1, "Found Signal");
+	}
+
+	return no_signal;
+}
+
+static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max)
+{
+	int no_signal, lock = 0;
+	s32 cpt_step = 0, offst_freq, car_max;
+	u32 reg;
+
+	car_max  = state->search_range / 1000;
+	car_max += (car_max / 10);
+	car_max  = (65536 * car_max / 2);
+	car_max /= (state->mclk / 1000);
+	if (car_max > 0x4000)
+		car_max = 0x4000;
+
+	if (zigzag)
+		offst_freq = 0;
+	else
+		offst_freq = -car_max + inc;
+
+	do {
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+			goto err;
+
+		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+
+		if (zigzag) {
+			if (offst_freq >= 0)
+				offst_freq = -offst_freq - 2 * inc;
+			else
+				offst_freq = -offst_freq;
+		} else {
+			offst_freq += 2 * inc;
+		}
+
+		cpt_step++;
+
+		lock = stv090x_get_dmdlock(state, timeout);
+		no_signal = stv090x_chk_signal(state);
+
+	} while ((!lock) &&
+		 (!no_signal) &&
+		  ((offst_freq - inc) < car_max) &&
+		  ((offst_freq + inc) > -car_max) &&
+		  (cpt_step < steps_max));
+
+	reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+	STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+
+	return lock;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_sw_algo(struct stv090x_state *state)
+{
+	int no_signal, zigzag, lock = 0;
+	u32 reg;
+
+	s32 dvbs2_fly_wheel;
+	s32 inc, timeout_step, trials, steps_max;
+
+	/* get params */
+	stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max);
+
+	switch (state->search_mode) {
+	case STV090x_SEARCH_DVBS1:
+	case STV090x_SEARCH_DSS:
+		/* accelerate the frequency detector */
+		if (state->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0)
+			goto err;
+		zigzag = 0;
+		break;
+
+	case STV090x_SEARCH_DVBS2:
+		if (state->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
+			goto err;
+		zigzag = 1;
+		break;
+
+	case STV090x_SEARCH_AUTO:
+	default:
+		/* accelerate the frequency detector */
+		if (state->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0)
+			goto err;
+		zigzag = 0;
+		break;
+	}
+
+	trials = 0;
+	do {
+		lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max);
+		no_signal = stv090x_chk_signal(state);
+		trials++;
+
+		/*run the SW search 2 times maximum*/
+		if (lock || no_signal || (trials == 2)) {
+			/*Check if the demod is not losing lock in DVBS2*/
+			if (state->dev_ver >= 0x20) {
+				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
+					goto err;
+			}
+
+			reg = STV090x_READ_DEMOD(state, DMDSTATE);
+			if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) {
+				/*Check if the demod is not losing lock in DVBS2*/
+				msleep(timeout_step);
+				reg = STV090x_READ_DEMOD(state, DMDFLYW);
+				dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
+				if (dvbs2_fly_wheel < 0xd) {	 /*if correct frames is decrementing */
+					msleep(timeout_step);
+					reg = STV090x_READ_DEMOD(state, DMDFLYW);
+					dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
+				}
+				if (dvbs2_fly_wheel < 0xd) {
+					/*FALSE lock, The demod is loosing lock */
+					lock = 0;
+					if (trials < 2) {
+						if (state->dev_ver >= 0x20) {
+							if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+								goto err;
+						}
+
+						if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
+							goto err;
+					}
+				}
+			}
+		}
+	} while ((!lock) && (trials < 2) && (!no_signal));
+
+	return lock;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state)
+{
+	u32 reg;
+	enum stv090x_delsys delsys;
+
+	reg = STV090x_READ_DEMOD(state, DMDSTATE);
+	if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2)
+		delsys = STV090x_DVBS2;
+	else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) {
+		reg = STV090x_READ_DEMOD(state, FECM);
+		if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1)
+			delsys = STV090x_DSS;
+		else
+			delsys = STV090x_DVBS1;
+	} else {
+		delsys = STV090x_ERROR;
+	}
+
+	return delsys;
+}
+
+/* in Hz */
+static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk)
+{
+	s32 derot, int_1, int_2, tmp_1, tmp_2;
+
+	derot  = STV090x_READ_DEMOD(state, CFR2) << 16;
+	derot |= STV090x_READ_DEMOD(state, CFR1) <<  8;
+	derot |= STV090x_READ_DEMOD(state, CFR0);
+
+	derot = comp2(derot, 24);
+	int_1 = state->mclk >> 12;
+	int_2 = derot >> 12;
+
+	/* carrier_frequency = MasterClock * Reg / 2^24 */
+	tmp_1 = state->mclk % 0x1000;
+	tmp_2 = derot % 0x1000;
+
+	derot = (int_1 * int_2) +
+		((int_1 * tmp_2) >> 12) +
+		((int_1 * tmp_1) >> 12);
+
+	return derot;
+}
+
+static int stv090x_get_viterbi(struct stv090x_state *state)
+{
+	u32 reg, rate;
+
+	reg = STV090x_READ_DEMOD(state, VITCURPUN);
+	rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD);
+
+	switch (rate) {
+	case 13:
+		state->fec = STV090x_PR12;
+		break;
+
+	case 18:
+		state->fec = STV090x_PR23;
+		break;
+
+	case 21:
+		state->fec = STV090x_PR34;
+		break;
+
+	case 24:
+		state->fec = STV090x_PR56;
+		break;
+
+	case 25:
+		state->fec = STV090x_PR67;
+		break;
+
+	case 26:
+		state->fec = STV090x_PR78;
+		break;
+
+	default:
+		state->fec = STV090x_PRERR;
+		break;
+	}
+
+	return 0;
+}
+
+static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	u8 tmg;
+	u32 reg;
+	s32 i = 0, offst_freq;
+
+	msleep(5);
+
+	if (state->algo == STV090x_BLIND_SEARCH) {
+		tmg = STV090x_READ_DEMOD(state, TMGREG2);
+		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c);
+		while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) {
+			tmg = STV090x_READ_DEMOD(state, TMGREG2);
+			msleep(5);
+			i += 5;
+		}
+	}
+	state->delsys = stv090x_get_std(state);
+
+	if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+		goto err;
+
+	if (state->config->tuner_get_frequency) {
+		if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
+			goto err;
+	}
+
+	if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+		goto err;
+
+	offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000;
+	state->frequency += offst_freq;
+
+	if (stv090x_get_viterbi(state) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DMDMODCOD);
+	state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
+	state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
+	state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1;
+	reg = STV090x_READ_DEMOD(state, TMGOBS);
+	state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
+	reg = STV090x_READ_DEMOD(state, FECM);
+	state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD);
+
+	if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) {
+
+		if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+			goto err;
+
+		if (state->config->tuner_get_frequency) {
+			if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
+				goto err;
+		}
+
+		if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+			goto err;
+
+		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
+			return STV090x_RANGEOK;
+		else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
+			return STV090x_RANGEOK;
+		else
+			return STV090x_OUTOFRANGE; /* Out of Range */
+	} else {
+		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
+			return STV090x_RANGEOK;
+		else
+			return STV090x_OUTOFRANGE;
+	}
+
+	return STV090x_OUTOFRANGE;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate)
+{
+	s32 offst_tmg;
+
+	offst_tmg  = STV090x_READ_DEMOD(state, TMGREG2) << 16;
+	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) <<  8;
+	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0);
+
+	offst_tmg = comp2(offst_tmg, 24); /* 2's complement */
+	if (!offst_tmg)
+		offst_tmg = 1;
+
+	offst_tmg  = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg);
+	offst_tmg /= 320;
+
+	return offst_tmg;
+}
+
+static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots)
+{
+	u8 aclc = 0x29;
+	s32 i;
+	struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low;
+
+	if (state->dev_ver == 0x20) {
+		car_loop		= stv090x_s2_crl_cut20;
+		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut20;
+		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut20;
+	} else {
+		/* >= Cut 3 */
+		car_loop		= stv090x_s2_crl_cut30;
+		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut30;
+		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut30;
+	}
+
+	if (modcod < STV090x_QPSK_12) {
+		i = 0;
+		while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod))
+			i++;
+
+		if (i >= 3)
+			i = 2;
+
+	} else {
+		i = 0;
+		while ((i < 14) && (modcod != car_loop[i].modcod))
+			i++;
+
+		if (i >= 14) {
+			i = 0;
+			while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod))
+				i++;
+
+			if (i >= 11)
+				i = 10;
+		}
+	}
+
+	if (modcod <= STV090x_QPSK_25) {
+		if (pilots) {
+			if (state->srate <= 3000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_20;
+			else
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_30;
+		} else {
+			if (state->srate <= 3000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_20;
+			else
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_30;
+		}
+
+	} else if (modcod <= STV090x_8PSK_910) {
+		if (pilots) {
+			if (state->srate <= 3000000)
+				aclc = car_loop[i].crl_pilots_on_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop[i].crl_pilots_on_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop[i].crl_pilots_on_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop[i].crl_pilots_on_20;
+			else
+				aclc = car_loop[i].crl_pilots_on_30;
+		} else {
+			if (state->srate <= 3000000)
+				aclc = car_loop[i].crl_pilots_off_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop[i].crl_pilots_off_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop[i].crl_pilots_off_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop[i].crl_pilots_off_20;
+			else
+				aclc = car_loop[i].crl_pilots_off_30;
+		}
+	} else { /* 16APSK and 32APSK */
+		if (state->srate <= 3000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_2;
+		else if (state->srate <= 7000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_5;
+		else if (state->srate <= 15000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_10;
+		else if (state->srate <= 25000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_20;
+		else
+			aclc = car_loop_apsk_low[i].crl_pilots_on_30;
+	}
+
+	return aclc;
+}
+
+static u8 stv090x_optimize_carloop_short(struct stv090x_state *state)
+{
+	struct stv090x_short_frame_crloop *short_crl = NULL;
+	s32 index = 0;
+	u8 aclc = 0x0b;
+
+	switch (state->modulation) {
+	case STV090x_QPSK:
+	default:
+		index = 0;
+		break;
+	case STV090x_8PSK:
+		index = 1;
+		break;
+	case STV090x_16APSK:
+		index = 2;
+		break;
+	case STV090x_32APSK:
+		index = 3;
+		break;
+	}
+
+	if (state->dev_ver >= 0x30) {
+		/* Cut 3.0 and up */
+		short_crl = stv090x_s2_short_crl_cut30;
+	} else {
+		/* Cut 2.0 and up: we don't support cuts older than 2.0 */
+		short_crl = stv090x_s2_short_crl_cut20;
+	}
+
+	if (state->srate <= 3000000)
+		aclc = short_crl[index].crl_2;
+	else if (state->srate <= 7000000)
+		aclc = short_crl[index].crl_5;
+	else if (state->srate <= 15000000)
+		aclc = short_crl[index].crl_10;
+	else if (state->srate <= 25000000)
+		aclc = short_crl[index].crl_20;
+	else
+		aclc = short_crl[index].crl_30;
+
+	return aclc;
+}
+
+static int stv090x_optimize_track(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	enum stv090x_rolloff rolloff;
+	enum stv090x_modcod modcod;
+
+	s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0;
+	u32 reg;
+
+	srate  = stv090x_get_srate(state, state->mclk);
+	srate += stv090x_get_tmgoffst(state, srate);
+
+	switch (state->delsys) {
+	case STV090x_DVBS1:
+	case STV090x_DSS:
+		if (state->algo == STV090x_SEARCH_AUTO) {
+			reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+			STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+			STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+			if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+				goto err;
+		}
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
+		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01);
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+
+		if (state->dev_ver >= 0x30) {
+			if (stv090x_get_viterbi(state) < 0)
+				goto err;
+
+			if (state->fec == STV090x_PR12) {
+				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
+					goto err;
+			} else {
+				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
+					goto err;
+			}
+		}
+
+		if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
+			goto err;
+		break;
+
+	case STV090x_DVBS2:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0)
+			goto err;
+		if (state->frame_len == STV090x_LONG_FRAME) {
+			reg = STV090x_READ_DEMOD(state, DMDMODCOD);
+			modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
+			pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
+			aclc = stv090x_optimize_carloop(state, modcod, pilots);
+			if (modcod <= STV090x_QPSK_910) {
+				STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc);
+			} else if (modcod <= STV090x_8PSK_910) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
+					goto err;
+			}
+			if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) {
+				if (modcod <= STV090x_16APSK_910) {
+					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
+						goto err;
+				} else {
+					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
+						goto err;
+				}
+			}
+		} else {
+			/*Carrier loop setting for short frame*/
+			aclc = stv090x_optimize_carloop_short(state);
+			if (state->modulation == STV090x_QPSK) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0)
+					goto err;
+			} else if (state->modulation == STV090x_8PSK) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
+					goto err;
+			} else if (state->modulation == STV090x_16APSK) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
+					goto err;
+			} else if (state->modulation == STV090x_32APSK)  {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
+					goto err;
+			}
+		}
+
+		STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */
+		break;
+
+	case STV090x_UNKNOWN:
+	default:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		break;
+	}
+
+	f_1 = STV090x_READ_DEMOD(state, CFR2);
+	f_0 = STV090x_READ_DEMOD(state, CFR1);
+	reg = STV090x_READ_DEMOD(state, TMGOBS);
+	rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
+
+	if (state->algo == STV090x_BLIND_SEARCH) {
+		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00);
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
+			goto err;
+
+		if (stv090x_set_srate(state, srate) < 0)
+			goto err;
+		blind_tune = 1;
+	}
+
+	if (state->dev_ver >= 0x20) {
+		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
+		    (state->search_mode == STV090x_SEARCH_DSS)		||
+		    (state->search_mode == STV090x_SEARCH_AUTO)) {
+
+			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0)
+				goto err;
+		}
+	}
+
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+		goto err;
+
+	/* AUTO tracking MODE */
+	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0)
+		goto err;
+	/* AUTO tracking MODE */
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0)
+		goto err;
+
+	if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) {
+		/* update initial carrier freq with the found freq offset */
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+			goto err;
+		state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000;
+
+		if ((state->dev_ver >= 0x20) || (blind_tune == 1)) {
+
+			if (state->algo != STV090x_WARM_SEARCH) {
+
+				if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+					goto err;
+
+				if (state->config->tuner_set_bandwidth) {
+					if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+						goto err;
+				}
+
+				if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+					goto err;
+
+			}
+		}
+		if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000))
+			msleep(50); /* blind search: wait 50ms for SR stabilization */
+		else
+			msleep(5);
+
+		stv090x_get_lock_tmg(state);
+
+		if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) {
+			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+				goto err;
+
+			i = 0;
+
+			while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) {
+
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+					goto err;
+				i++;
+			}
+		}
+
+	}
+
+	if (state->dev_ver >= 0x20) {
+		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+			goto err;
+	}
+
+	if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS))
+		stv090x_set_vit_thtracq(state);
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_feclock(struct stv090x_state *state, s32 timeout)
+{
+	s32 timer = 0, lock = 0, stat;
+	u32 reg;
+
+	while ((timer < timeout) && (!lock)) {
+		reg = STV090x_READ_DEMOD(state, DMDSTATE);
+		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+		switch (stat) {
+		case 0: /* searching */
+		case 1: /* first PLH detected */
+		default:
+			lock = 0;
+			break;
+
+		case 2: /* DVB-S2 mode */
+			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
+			lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD);
+			break;
+
+		case 3: /* DVB-S1/legacy mode */
+			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
+			lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD);
+			break;
+		}
+		if (!lock) {
+			msleep(10);
+			timer += 10;
+		}
+	}
+	return lock;
+}
+
+static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec)
+{
+	u32 reg;
+	s32 timer = 0;
+	int lock;
+
+	lock = stv090x_get_dmdlock(state, timeout_dmd);
+	if (lock)
+		lock = stv090x_get_feclock(state, timeout_fec);
+
+	if (lock) {
+		lock = 0;
+
+		while ((timer < timeout_fec) && (!lock)) {
+			reg = STV090x_READ_DEMOD(state, TSSTATUS);
+			lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD);
+			msleep(1);
+			timer++;
+		}
+	}
+
+	return lock;
+}
+
+static int stv090x_set_s2rolloff(struct stv090x_state *state)
+{
+	u32 reg;
+
+	if (state->dev_ver <= 0x20) {
+		/* rolloff to auto mode if DVBS2 */
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+	} else {
+		/* DVB-S2 rolloff to auto mode if DVBS2 */
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+
+static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+	enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
+	u32 reg;
+	s32 timeout_dmd = 500, timeout_fec = 50, agc1_power, power_iq = 0, i;
+	int lock = 0, low_sr = 0, no_signal = 0;
+
+	reg = STV090x_READ_DEMOD(state, TSCFGH);
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
+	if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */
+		goto err;
+
+	if (state->dev_ver >= 0x20) {
+		if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) /* cut 2.0 */
+			goto err;
+	}
+
+	stv090x_get_lock_tmg(state);
+
+	if (state->algo == STV090x_BLIND_SEARCH) {
+		state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
+			goto err;
+		if (stv090x_set_srate(state, 1000000) < 0) /* inital srate = 1Msps */
+			goto err;
+	} else {
+		/* known srate */
+		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
+			goto err;
+
+		if (state->srate < 2000000) {
+			/* SR < 2MSPS */
+			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0)
+				goto err;
+		} else {
+			/* SR >= 2Msps */
+			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+			goto err;
+
+		if (state->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0)
+				goto err;
+			if (state->algo == STV090x_COLD_SEARCH)
+				state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10;
+			else if (state->algo == STV090x_WARM_SEARCH)
+				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000;
+		}
+
+		/* if cold start or warm  (Symbolrate is known)
+		 * use a Narrow symbol rate scan range
+		 */
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */
+			goto err;
+
+		if (stv090x_set_srate(state, state->srate) < 0)
+			goto err;
+
+		if (stv090x_set_max_srate(state, state->mclk, state->srate) < 0)
+			goto err;
+		if (stv090x_set_min_srate(state, state->mclk, state->srate) < 0)
+			goto err;
+
+		if (state->srate >= 10000000)
+			low_sr = 0;
+		else
+			low_sr = 1;
+	}
+
+	/* Setup tuner */
+	if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+		goto err;
+
+	if (state->config->tuner_set_bbgain) {
+		if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */
+			goto err;
+	}
+
+	if (state->config->tuner_set_frequency) {
+		if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
+			goto err;
+	}
+
+	if (state->config->tuner_set_bandwidth) {
+		if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+			goto err;
+	}
+
+	if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+		goto err;
+
+	msleep(50);
+
+	if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+		goto err;
+
+	if (state->config->tuner_get_status) {
+		if (state->config->tuner_get_status(fe, &reg) < 0)
+			goto err;
+	}
+
+	if (reg)
+		dprintk(FE_DEBUG, 1, "Tuner phase locked");
+	else
+		dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+	if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+		goto err;
+
+	msleep(10);
+	agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1),
+				STV090x_READ_DEMOD(state, AGCIQIN0));
+
+	if (agc1_power == 0) {
+		/* If AGC1 integrator value is 0
+		 * then read POWERI, POWERQ
+		 */
+		for (i = 0; i < 5; i++) {
+			power_iq += (STV090x_READ_DEMOD(state, POWERI) +
+				     STV090x_READ_DEMOD(state, POWERQ)) >> 1;
+		}
+		power_iq /= 5;
+	}
+
+	if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) {
+		dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq);
+		lock = 0;
+
+	} else {
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion);
+
+		if (state->dev_ver <= 0x20) {
+			/* rolloff to auto mode if DVBS2 */
+			STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1);
+		} else {
+			/* DVB-S2 rolloff to auto mode if DVBS2 */
+			STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1);
+		}
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+
+		if (stv090x_delivery_search(state) < 0)
+			goto err;
+
+		if (state->algo != STV090x_BLIND_SEARCH) {
+			if (stv090x_start_search(state) < 0)
+				goto err;
+		}
+	}
+
+	/* need to check for AGC1 state */
+
+
+
+	if (state->algo == STV090x_BLIND_SEARCH)
+		lock = stv090x_blind_search(state);
+
+	else if (state->algo == STV090x_COLD_SEARCH)
+		lock = stv090x_get_coldlock(state, timeout_dmd);
+
+	else if (state->algo == STV090x_WARM_SEARCH)
+		lock = stv090x_get_dmdlock(state, timeout_dmd);
+
+	if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) {
+		if (!low_sr) {
+			if (stv090x_chk_tmg(state))
+				lock = stv090x_sw_algo(state);
+		}
+	}
+
+	if (lock)
+		signal_state = stv090x_get_sig_params(state);
+
+	if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */
+		stv090x_optimize_track(state);
+
+		if (state->dev_ver >= 0x20) {
+			/* >= Cut 2.0 :release TS reset after
+			 * demod lock and optimized Tracking
+			 */
+			reg = STV090x_READ_DEMOD(state, TSCFGH);
+			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
+			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+				goto err;
+
+			msleep(3);
+
+			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */
+			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+				goto err;
+
+			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
+			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+				goto err;
+		}
+
+		if (stv090x_get_lock(state, timeout_fec, timeout_fec)) {
+			lock = 1;
+			if (state->delsys == STV090x_DVBS2) {
+				stv090x_set_s2rolloff(state);
+
+				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
+				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1);
+				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
+					goto err;
+				/* Reset DVBS2 packet delinator error counter */
+				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
+				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0);
+				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
+					goto err;
+
+				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */
+					goto err;
+			} else {
+				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
+					goto err;
+			}
+			/* Reset the Total packet counter */
+			if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0)
+				goto err;
+			/* Reset the packet Error counter2 */
+			if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
+				goto err;
+		} else {
+			lock = 0;
+			signal_state = STV090x_NODATA;
+			no_signal = stv090x_chk_signal(state);
+		}
+	}
+	return signal_state;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *props = &fe->dtv_property_cache;
+
+	state->delsys = props->delivery_system;
+	state->frequency = p->frequency;
+	state->srate = p->u.qpsk.symbol_rate;
+	state->search_mode = STV090x_SEARCH_AUTO;
+	state->algo = STV090x_COLD_SEARCH;
+	state->fec = STV090x_PRERR;
+	state->search_range = 2000000;
+
+	if (stv090x_algo(state) == STV090x_RANGEOK) {
+		dprintk(FE_DEBUG, 1, "Search success!");
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	} else {
+		dprintk(FE_DEBUG, 1, "Search failed!");
+		return DVBFE_ALGO_SEARCH_FAILED;
+	}
+
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+/* FIXME! */
+static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+	u8 search_state;
+
+	reg = STV090x_READ_DEMOD(state, DMDSTATE);
+	search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+	switch (search_state) {
+	case 0: /* searching */
+	case 1: /* first PLH detected */
+	default:
+		dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
+		*status = 0;
+		break;
+
+	case 2: /* DVB-S2 mode */
+		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+			reg = STV090x_READ_DEMOD(state, TSSTATUS);
+			if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
+				*status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+			}
+		}
+		break;
+
+	case 3: /* DVB-S1/legacy mode */
+		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) {
+			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
+			if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
+				reg = STV090x_READ_DEMOD(state, TSSTATUS);
+				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
+					*status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+				}
+			}
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static int stv090x_read_per(struct dvb_frontend *fe, u32 *per)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+
+	s32 count_4, count_3, count_2, count_1, count_0, count;
+	u32 reg, h, m, l;
+	enum fe_status status;
+
+	stv090x_read_status(fe, &status);
+	if (!(status & FE_HAS_LOCK)) {
+		*per = 1 << 23; /* Max PER */
+	} else {
+		/* Counter 2 */
+		reg = STV090x_READ_DEMOD(state, ERRCNT22);
+		h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD);
+
+		reg = STV090x_READ_DEMOD(state, ERRCNT21);
+		m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD);
+
+		reg = STV090x_READ_DEMOD(state, ERRCNT20);
+		l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD);
+
+		*per = ((h << 16) | (m << 8) | l);
+
+		count_4 = STV090x_READ_DEMOD(state, FBERCPT4);
+		count_3 = STV090x_READ_DEMOD(state, FBERCPT3);
+		count_2 = STV090x_READ_DEMOD(state, FBERCPT2);
+		count_1 = STV090x_READ_DEMOD(state, FBERCPT1);
+		count_0 = STV090x_READ_DEMOD(state, FBERCPT0);
+
+		if ((!count_4) && (!count_3)) {
+			count  = (count_2 & 0xff) << 16;
+			count |= (count_1 & 0xff) <<  8;
+			count |=  count_0 & 0xff;
+		} else {
+			count = 1 << 24;
+		}
+		if (count == 0)
+			*per = 1;
+	}
+	if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val)
+{
+	int res = 0;
+	int min = 0, med;
+
+	if (val < tab[min].read)
+		res = tab[min].real;
+	else if (val >= tab[max].read)
+		res = tab[max].real;
+	else {
+		while ((max - min) > 1) {
+			med = (max + min) / 2;
+			if (val >= tab[min].read && val < tab[med].read)
+				max = med;
+			else
+				min = med;
+		}
+		res = ((val - tab[min].read) *
+		       (tab[max].real - tab[min].real) /
+		       (tab[max].read - tab[min].read)) +
+			tab[min].real;
+	}
+
+	return res;
+}
+
+static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+	s32 agc;
+
+	reg = STV090x_READ_DEMOD(state, AGCIQIN1);
+	agc = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
+
+	*strength = stv090x_table_lookup(stv090x_rf_tab, ARRAY_SIZE(stv090x_rf_tab) - 1, agc);
+	if (agc > stv090x_rf_tab[0].read)
+		*strength = 5;
+	else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read)
+		*strength = -100;
+
+	return 0;
+}
+
+static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg_0, reg_1, reg, i;
+	s32 val_0, val_1, val = 0;
+	u8 lock_f;
+
+	switch (state->delsys) {
+	case STV090x_DVBS2:
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+		if (lock_f) {
+			msleep(5);
+			for (i = 0; i < 16; i++) {
+				reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1);
+				val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD);
+				reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0);
+				val_0 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD);
+				val  += MAKEWORD16(val_1, val_0);
+				msleep(1);
+			}
+			val /= 16;
+			*cnr = stv090x_table_lookup(stv090x_s2cn_tab, ARRAY_SIZE(stv090x_s2cn_tab) - 1, val);
+			if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s2cn_tab) - 1].read)
+				*cnr = 1000;
+		}
+		break;
+
+	case STV090x_DVBS1:
+	case STV090x_DSS:
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+		if (lock_f) {
+			msleep(5);
+			for (i = 0; i < 16; i++) {
+				reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1);
+				val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD);
+				reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0);
+				val_0 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD);
+				val  += MAKEWORD16(val_1, val_0);
+				msleep(1);
+			}
+			val /= 16;
+			*cnr = stv090x_table_lookup(stv090x_s1cn_tab, ARRAY_SIZE(stv090x_s1cn_tab) - 1, val);
+			if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s1cn_tab) - 1].read)
+				*cnr = 1000;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+	switch (tone) {
+	case SEC_TONE_ON:
+		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+			goto err;
+		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+			goto err;
+		break;
+
+	case SEC_TONE_OFF:
+		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+			goto err;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+
+static enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg, idle = 0, fifo_full = 1;
+	int i;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2);
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	for (i = 0; i < cmd->msg_len; i++) {
+
+		while (fifo_full) {
+			reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+			fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0)
+			goto err;
+	}
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	i = 0;
+
+	while ((!idle) && (i < 10)) {
+		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
+		msleep(10);
+		i++;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg, idle = 0, fifo_full = 1;
+	u8 mode, value;
+	int i;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+	if (burst == SEC_MINI_A) {
+		mode = 3;
+		value = 0x00;
+	} else {
+		mode = 2;
+		value = 0xFF;
+	}
+
+	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode);
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	while (fifo_full) {
+		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+		fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
+	}
+
+	if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	i = 0;
+
+	while ((!idle) && (i < 10)) {
+		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
+		msleep(10);
+		i++;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg = 0, i = 0, rx_end = 0;
+
+	while ((rx_end != 1) && (i < 10)) {
+		msleep(10);
+		i++;
+		reg = STV090x_READ_DEMOD(state, DISRX_ST0);
+		rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD);
+	}
+
+	if (rx_end) {
+		reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD);
+		for (i = 0; i < reply->msg_len; i++)
+			reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA);
+	}
+
+	return 0;
+}
+
+static int stv090x_sleep(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+
+	dprintk(FE_DEBUG, 1, "Set %s to sleep",
+		state->device == STV0900 ? "STV0900" : "STV0903");
+
+	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+	STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
+	if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
+		goto err;
+
+	reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+	STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
+	if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_wakeup(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+
+	dprintk(FE_DEBUG, 1, "Wake %s from standby",
+		state->device == STV0900 ? "STV0900" : "STV0903");
+
+	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+	STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00);
+	if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
+		goto err;
+
+	reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+	STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1);
+	if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static void stv090x_release(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+
+	kfree(state);
+}
+
+static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode)
+{
+	u32 reg = 0;
+
+	switch (ldpc_mode) {
+	case STV090x_DUAL:
+	default:
+		if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) {
+			/* set LDPC to dual mode */
+			if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0)
+				goto err;
+
+			state->demod_mode = STV090x_DUAL;
+
+			reg = stv090x_read_reg(state, STV090x_TSTRES0);
+			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
+			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+				goto err;
+			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
+			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+				goto err;
+
+			if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
+				goto err;
+
+			if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
+				goto err;
+
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
+				goto err;
+		}
+		break;
+
+	case STV090x_SINGLE:
+		if (stv090x_stop_modcod(state) < 0)
+			goto err;
+		if (stv090x_activate_modcod_single(state) < 0)
+			goto err;
+
+		if (state->demod == STV090x_DEMODULATOR_1) {
+			if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */
+				goto err;
+		} else {
+			if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */
+				goto err;
+		}
+
+		reg = stv090x_read_reg(state, STV090x_TSTRES0);
+		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
+		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+			goto err;
+		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
+		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+			goto err;
+
+		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01);
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+		break;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+/* return (Hz), clk in Hz*/
+static u32 stv090x_get_mclk(struct stv090x_state *state)
+{
+	const struct stv090x_config *config = state->config;
+	u32 div, reg;
+	u8 ratio;
+
+	div = stv090x_read_reg(state, STV090x_NCOARSE);
+	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+	ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6;
+
+	return (div + 1) * config->xtal / ratio; /* kHz */
+}
+
+static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk)
+{
+	const struct stv090x_config *config = state->config;
+	u32 reg, div, clk_sel;
+
+	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+	clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6);
+
+	div = ((clk_sel * mclk) / config->xtal) - 1;
+
+	reg = stv090x_read_reg(state, STV090x_NCOARSE);
+	STV090x_SETFIELD(reg, M_DIV_FIELD, div);
+	if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0)
+		goto err;
+
+	state->mclk = stv090x_get_mclk(state);
+
+	/*Set the DiseqC frequency to 22KHz */
+	div = state->mclk / 704000;
+	if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_tspath(struct stv090x_state *state)
+{
+	u32 reg;
+
+	if (state->dev_ver >= 0x20) {
+		switch (state->config->ts1_mode) {
+		case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		case STV090x_TSMODE_DVBCI:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				stv090x_write_reg(state, STV090x_TSGENERAL, 0x00);
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */
+					goto err;
+				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+					goto err;
+				reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+				if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
+					goto err;
+				break;
+			}
+			break;
+
+		case STV090x_TSMODE_SERIAL_PUNCTURED:
+		case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		default:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
+					goto err;
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0)
+					goto err;
+				break;
+			}
+			break;
+		}
+	} else {
+		switch (state->config->ts1_mode) {
+		case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		case STV090x_TSMODE_DVBCI:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16);
+				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+					goto err;
+				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0);
+				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
+					goto err;
+				break;
+			}
+			break;
+
+		case STV090x_TSMODE_SERIAL_PUNCTURED:
+		case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		default:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12);
+				break;
+			}
+			break;
+		}
+	}
+
+	switch (state->config->ts1_mode) {
+	case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_DVBCI:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		break;
+	}
+
+	switch (state->config->ts2_mode) {
+	case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_DVBCI:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		break;
+	}
+	reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
+	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
+	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+		goto err;
+
+	reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
+	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
+	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_init(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	const struct stv090x_config *config = state->config;
+	u32 reg;
+
+	if (stv090x_wakeup(fe) < 0) {
+		dprintk(FE_ERROR, 1, "Error waking device");
+		goto err;
+	}
+
+	if (stv090x_ldpc_mode(state, state->demod_mode) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, TNRCFG2);
+	STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion);
+	if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DEMOD);
+	STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
+	if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+		goto err;
+
+	if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+		goto err;
+
+	if (config->tuner_set_mode) {
+		if (config->tuner_set_mode(fe, TUNER_WAKE) < 0)
+			goto err;
+	}
+
+	if (config->tuner_init) {
+		if (config->tuner_init(fe) < 0)
+			goto err;
+	}
+
+	if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
+		goto err;
+
+	if (stv090x_set_tspath(state) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_setup(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	const struct stv090x_config *config = state->config;
+	const struct stv090x_reg *stv090x_initval = NULL;
+	const struct stv090x_reg *stv090x_cut20_val = NULL;
+	unsigned long t1_size = 0, t2_size = 0;
+	u32 reg = 0;
+
+	int i;
+
+	if (state->device == STV0900) {
+		dprintk(FE_DEBUG, 1, "Initializing STV0900");
+		stv090x_initval = stv0900_initval;
+		t1_size = ARRAY_SIZE(stv0900_initval);
+		stv090x_cut20_val = stv0900_cut20_val;
+		t2_size = ARRAY_SIZE(stv0900_cut20_val);
+	} else if (state->device == STV0903) {
+		dprintk(FE_DEBUG, 1, "Initializing STV0903");
+		stv090x_initval = stv0903_initval;
+		t1_size = ARRAY_SIZE(stv0903_initval);
+		stv090x_cut20_val = stv0903_cut20_val;
+		t2_size = ARRAY_SIZE(stv0903_cut20_val);
+	}
+
+	/* STV090x init */
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Stop Demod */
+		goto err;
+
+	msleep(5);
+
+	if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */
+		goto err;
+
+	STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
+	if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */
+		goto err;
+
+	if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */
+		goto err;
+	msleep(5);
+	if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */
+		goto err;
+	if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */
+		goto err;
+	msleep(5);
+
+	/* write initval */
+	dprintk(FE_DEBUG, 1, "Setting up initial values");
+	for (i = 0; i < t1_size; i++) {
+		if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0)
+			goto err;
+	}
+
+	state->dev_ver = stv090x_read_reg(state, STV090x_MID);
+	if (state->dev_ver >= 0x20) {
+		if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
+			goto err;
+
+		/* write cut20_val*/
+		dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values");
+		for (i = 0; i < t2_size; i++) {
+			if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0)
+				goto err;
+		}
+
+	} else if (state->dev_ver < 0x20) {
+		dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!",
+			state->dev_ver);
+
+		goto err;
+	} else if (state->dev_ver > 0x30) {
+		/* we shouldn't bail out from here */
+		dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!",
+			state->dev_ver);
+	}
+
+	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0)
+		goto err;
+	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
+		goto err;
+
+	stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
+	msleep(5);
+	if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0)
+		goto err;
+	stv090x_get_mclk(state);
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static struct dvb_frontend_ops stv090x_ops = {
+
+	.info = {
+		.name			= "STV090x Multistandard",
+		.type			= FE_QPSK,
+		.frequency_min		= 950000,
+		.frequency_max 		= 2150000,
+		.frequency_stepsize	= 0,
+		.frequency_tolerance	= 0,
+		.symbol_rate_min 	= 1000000,
+		.symbol_rate_max 	= 45000000,
+		.caps			= FE_CAN_INVERSION_AUTO |
+					  FE_CAN_FEC_AUTO       |
+					  FE_CAN_QPSK           |
+					  FE_CAN_2G_MODULATION
+	},
+
+	.release			= stv090x_release,
+	.init				= stv090x_init,
+
+	.sleep				= stv090x_sleep,
+	.get_frontend_algo		= stv090x_frontend_algo,
+
+	.i2c_gate_ctrl			= stv090x_i2c_gate_ctrl,
+
+	.diseqc_send_master_cmd		= stv090x_send_diseqc_msg,
+	.diseqc_send_burst		= stv090x_send_diseqc_burst,
+	.diseqc_recv_slave_reply	= stv090x_recv_slave_reply,
+	.set_tone			= stv090x_set_tone,
+
+	.search				= stv090x_search,
+	.read_status			= stv090x_read_status,
+	.read_ber			= stv090x_read_per,
+	.read_signal_strength		= stv090x_read_signal_strength,
+	.read_snr			= stv090x_read_cnr
+};
+
+
+struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+				    struct i2c_adapter *i2c,
+				    enum stv090x_demodulator demod)
+{
+	struct stv090x_state *state = NULL;
+
+	state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->verbose				= &verbose;
+	state->config				= config;
+	state->i2c				= i2c;
+	state->frontend.ops			= stv090x_ops;
+	state->frontend.demodulator_priv	= state;
+	state->demod				= demod;
+	state->demod_mode 			= config->demod_mode; /* Single or Dual mode */
+	state->device				= config->device;
+	state->rolloff				= STV090x_RO_35; /* default */
+
+	if (state->demod == STV090x_DEMODULATOR_0)
+		mutex_init(&demod_lock);
+
+	if (stv090x_sleep(&state->frontend) < 0) {
+		dprintk(FE_ERROR, 1, "Error putting device to sleep");
+		goto error;
+	}
+
+	if (stv090x_setup(&state->frontend) < 0) {
+		dprintk(FE_ERROR, 1, "Error setting up device");
+		goto error;
+	}
+	if (stv090x_wakeup(&state->frontend) < 0) {
+		dprintk(FE_ERROR, 1, "Error waking device");
+		goto error;
+	}
+
+	dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n",
+	       state->device == STV0900 ? "STV0900" : "STV0903",
+	       demod,
+	       state->dev_ver);
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stv090x_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,106 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __STV090x_H
+#define __STV090x_H
+
+enum stv090x_demodulator {
+	STV090x_DEMODULATOR_0 = 1,
+	STV090x_DEMODULATOR_1
+};
+
+enum stv090x_device {
+	STV0903	=  0,
+	STV0900,
+};
+
+enum stv090x_mode {
+	STV090x_DUAL = 0,
+	STV090x_SINGLE
+};
+
+enum stv090x_tsmode {
+	STV090x_TSMODE_SERIAL_PUNCTURED	= 1,
+	STV090x_TSMODE_SERIAL_CONTINUOUS,
+	STV090x_TSMODE_PARALLEL_PUNCTURED,
+	STV090x_TSMODE_DVBCI
+};
+
+enum stv090x_clkmode {
+	STV090x_CLK_INT = 0, /* Clk i/p = CLKI */
+	STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */
+};
+
+enum stv090x_i2crpt {
+	STV090x_RPTLEVEL_256	= 0,
+	STV090x_RPTLEVEL_128	= 1,
+	STV090x_RPTLEVEL_64	= 2,
+	STV090x_RPTLEVEL_32	= 3,
+	STV090x_RPTLEVEL_16	= 4,
+	STV090x_RPTLEVEL_8	= 5,
+	STV090x_RPTLEVEL_4	= 6,
+	STV090x_RPTLEVEL_2	= 7,
+};
+
+struct stv090x_config {
+	enum stv090x_device	device;
+	enum stv090x_mode	demod_mode;
+	enum stv090x_clkmode	clk_mode;
+
+	u32 xtal; /* default: 8000000 */
+	u8 address; /* default: 0x68 */
+
+	u32 ref_clk; /* default: 16000000 FIXME to tuner config */
+
+	u8 ts1_mode;
+	u8 ts2_mode;
+
+	enum stv090x_i2crpt	repeater_level;
+
+	int (*tuner_init) (struct dvb_frontend *fe);
+	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+	int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+	int (*tuner_set_refclk)  (struct dvb_frontend *fe, u32 refclk);
+	int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+};
+
+#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+					   struct i2c_adapter *i2c,
+					   enum stv090x_demodulator demod);
+#else
+
+static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+						  struct i2c_adapter *i2c,
+						  enum stv090x_demodulator demod)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_STV090x */
+
+#endif /* __STV090x_H */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x_priv.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x_priv.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x_priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x_priv.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,269 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __STV090x_PRIV_H
+#define __STV090x_PRIV_H
+
+#include "dvb_frontend.h"
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(__y, __z, format, arg...) do {						\
+	if (__z) {									\
+		if	((verbose > FE_ERROR) && (verbose > __y))			\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((verbose > FE_INFO) && (verbose > __y))			\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (verbose > __y)							\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+#define STV090x_READ_DEMOD(__state, __reg) ((			\
+	(__state)->demod == STV090x_DEMODULATOR_1)	?	\
+	stv090x_read_reg(__state, STV090x_P2_##__reg) :		\
+	stv090x_read_reg(__state, STV090x_P1_##__reg))
+
+#define STV090x_WRITE_DEMOD(__state, __reg, __data) ((		\
+	(__state)->demod == STV090x_DEMODULATOR_1)	?	\
+	stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\
+	stv090x_write_reg(__state, STV090x_P1_##__reg, __data))
+
+#define STV090x_ADDR_OFFST(__state, __x) ((			\
+	(__state->demod) == STV090x_DEMODULATOR_1)	?	\
+		STV090x_P1_##__x :				\
+		STV090x_P2_##__x)
+
+
+#define STV090x_SETFIELD(mask, bitf, val)	(mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\
+							 STV090x_OFFST_##bitf))) | \
+							 (val << STV090x_OFFST_##bitf))
+
+#define STV090x_GETFIELD(val, bitf)		((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1))
+
+
+#define STV090x_SETFIELD_Px(mask, bitf, val)	(mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\
+							 STV090x_OFFST_Px_##bitf))) | \
+							 (val << STV090x_OFFST_Px_##bitf))
+
+#define STV090x_GETFIELD_Px(val, bitf)		((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1))
+
+#define MAKEWORD16(__a, __b)			(((__a) << 8) | (__b))
+
+#define MSB(__x)				((__x >> 8) & 0xff)
+#define LSB(__x)				(__x & 0xff)
+
+
+#define STV090x_IQPOWER_THRESHOLD	  30
+#define STV090x_SEARCH_AGC2_TH_CUT20	 700
+#define STV090x_SEARCH_AGC2_TH_CUT30	1200
+
+#define STV090x_SEARCH_AGC2_TH(__ver)	\
+	((__ver <= 0x20) ?		\
+	STV090x_SEARCH_AGC2_TH_CUT20 :	\
+	STV090x_SEARCH_AGC2_TH_CUT30)
+
+enum stv090x_signal_state {
+	STV090x_NOCARRIER,
+	STV090x_NODATA,
+	STV090x_DATAOK,
+	STV090x_RANGEOK,
+	STV090x_OUTOFRANGE
+};
+
+enum stv090x_fec {
+	STV090x_PR12 = 0,
+	STV090x_PR23,
+	STV090x_PR34,
+	STV090x_PR45,
+	STV090x_PR56,
+	STV090x_PR67,
+	STV090x_PR78,
+	STV090x_PR89,
+	STV090x_PR910,
+	STV090x_PRERR
+};
+
+enum stv090x_modulation {
+	STV090x_QPSK,
+	STV090x_8PSK,
+	STV090x_16APSK,
+	STV090x_32APSK,
+	STV090x_UNKNOWN
+};
+
+enum stv090x_frame {
+	STV090x_LONG_FRAME,
+	STV090x_SHORT_FRAME
+};
+
+enum stv090x_pilot {
+	STV090x_PILOTS_OFF,
+	STV090x_PILOTS_ON
+};
+
+enum stv090x_rolloff {
+	STV090x_RO_35,
+	STV090x_RO_25,
+	STV090x_RO_20
+};
+
+enum stv090x_inversion {
+	STV090x_IQ_AUTO,
+	STV090x_IQ_NORMAL,
+	STV090x_IQ_SWAP
+};
+
+enum stv090x_modcod {
+	STV090x_DUMMY_PLF = 0,
+	STV090x_QPSK_14,
+	STV090x_QPSK_13,
+	STV090x_QPSK_25,
+	STV090x_QPSK_12,
+	STV090x_QPSK_35,
+	STV090x_QPSK_23,
+	STV090x_QPSK_34,
+	STV090x_QPSK_45,
+	STV090x_QPSK_56,
+	STV090x_QPSK_89,
+	STV090x_QPSK_910,
+	STV090x_8PSK_35,
+	STV090x_8PSK_23,
+	STV090x_8PSK_34,
+	STV090x_8PSK_56,
+	STV090x_8PSK_89,
+	STV090x_8PSK_910,
+	STV090x_16APSK_23,
+	STV090x_16APSK_34,
+	STV090x_16APSK_45,
+	STV090x_16APSK_56,
+	STV090x_16APSK_89,
+	STV090x_16APSK_910,
+	STV090x_32APSK_34,
+	STV090x_32APSK_45,
+	STV090x_32APSK_56,
+	STV090x_32APSK_89,
+	STV090x_32APSK_910,
+	STV090x_MODCODE_UNKNOWN
+};
+
+enum stv090x_search {
+	STV090x_SEARCH_DSS = 0,
+	STV090x_SEARCH_DVBS1,
+	STV090x_SEARCH_DVBS2,
+	STV090x_SEARCH_AUTO
+};
+
+enum stv090x_algo {
+	STV090x_BLIND_SEARCH,
+	STV090x_COLD_SEARCH,
+	STV090x_WARM_SEARCH
+};
+
+enum stv090x_delsys {
+	STV090x_ERROR = 0,
+	STV090x_DVBS1 = 1,
+	STV090x_DVBS2,
+	STV090x_DSS
+};
+
+struct stv090x_long_frame_crloop {
+	enum stv090x_modcod	modcod;
+
+	u8 crl_pilots_on_2;
+	u8 crl_pilots_off_2;
+	u8 crl_pilots_on_5;
+	u8 crl_pilots_off_5;
+	u8 crl_pilots_on_10;
+	u8 crl_pilots_off_10;
+	u8 crl_pilots_on_20;
+	u8 crl_pilots_off_20;
+	u8 crl_pilots_on_30;
+	u8 crl_pilots_off_30;
+};
+
+struct stv090x_short_frame_crloop {
+	enum stv090x_modulation	modulation;
+
+	u8 crl_2;  /*      SR <   3M */
+	u8 crl_5;  /*  3 < SR <=  7M */
+	u8 crl_10; /*  7 < SR <= 15M */
+	u8 crl_20; /* 10 < SR <= 25M */
+	u8 crl_30; /* 10 < SR <= 45M */
+};
+
+struct stv090x_reg {
+	u16 addr;
+	u8  data;
+};
+
+struct stv090x_tab {
+	s32 real;
+	s32 read;
+};
+
+struct stv090x_state {
+	enum stv090x_device		device;
+	enum stv090x_demodulator	demod;
+	enum stv090x_mode		demod_mode;
+	u32				dev_ver;
+
+	struct i2c_adapter		*i2c;
+	const struct stv090x_config	*config;
+	struct dvb_frontend		frontend;
+
+	u32				*verbose; /* Cached module verbosity */
+
+	enum stv090x_delsys		delsys;
+	enum stv090x_fec		fec;
+	enum stv090x_modulation		modulation;
+	enum stv090x_modcod		modcod;
+	enum stv090x_search		search_mode;
+	enum stv090x_frame		frame_len;
+	enum stv090x_pilot		pilots;
+	enum stv090x_rolloff		rolloff;
+	enum stv090x_inversion		inversion;
+	enum stv090x_algo		algo;
+
+	u32				frequency;
+	u32				srate;
+
+	s32				mclk; /* Masterclock Divider factor */
+	s32				tuner_bw;
+
+	u32				tuner_refclk;
+
+	s32				search_range;
+
+	s32				DemodTimeout;
+	s32				FecTimeout;
+};
+
+#endif /* __STV090x_PRIV_H */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x_reg.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x_reg.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv090x_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv090x_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2373 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __STV090x_REG_H
+#define __STV090x_REG_H
+
+#define STV090x_MID				0xf100
+#define STV090x_OFFST_MCHIP_IDENT_FIELD		4
+#define STV090x_WIDTH_MCHIP_IDENT_FIELD		4
+#define STV090x_OFFST_MRELEASE_FIELD		0
+#define STV090x_WIDTH_MRELEASE_FIELD		4
+
+#define STV090x_DACR1				0xf113
+#define STV090x_OFFST_DACR1_MODE_FIELD		5
+#define STV090x_WIDTH_DACR1_MODE_FIELD		3
+#define STV090x_OFFST_DACR1_VALUE_FIELD		0
+#define STV090x_WIDTH_DACR1_VALUE_FIELD		4
+
+#define STV090x_DACR2				0xf114
+#define STV090x_OFFST_DACR2_VALUE_FIELD		0
+#define STV090x_WIDTH_DACR2_VALUE_FIELD		8
+
+#define STV090x_OUTCFG				0xf11c
+#define STV090x_OFFST_OUTSERRS1_HZ_FIELD	6
+#define STV090x_WIDTH_OUTSERRS1_HZ_FIELD	1
+#define STV090x_OFFST_OUTSERRS2_HZ_FIELD	5
+#define STV090x_WIDTH_OUTSERRS2_HZ_FIELD	1
+#define STV090x_OFFST_OUTSERRS3_HZ_FIELD	4
+#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD	1
+#define STV090x_OFFST_OUTPARRS3_HZ_FIELD	3
+#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD	1
+
+#define STV090x_MODECFG				0xf11d
+
+#define STV090x_IRQSTATUS3			0xf120
+#define STV090x_OFFST_SPLL_LOCK_FIELD		5
+#define STV090x_WIDTH_SPLL_LOCK_FIELD		1
+#define STV090x_OFFST_SSTREAM_LCK_3_FIELD	4
+#define STV090x_WIDTH_SSTREAM_LCK_3_FIELD	1
+#define STV090x_OFFST_SSTREAM_LCK_2_FIELD	3
+#define STV090x_WIDTH_SSTREAM_LCK_2_FIELD	1
+#define STV090x_OFFST_SSTREAM_LCK_1_FIELD	2
+#define STV090x_WIDTH_SSTREAM_LCK_1_FIELD	1
+#define STV090x_OFFST_SDVBS1_PRF_2_FIELD	1
+#define STV090x_WIDTH_SDVBS1_PRF_2_FIELD	1
+#define STV090x_OFFST_SDVBS1_PRF_1_FIELD	0
+#define STV090x_WIDTH_SDVBS1_PRF_1_FIELD	1
+
+#define STV090x_IRQSTATUS2			0xf121
+#define STV090x_OFFST_SSPY_ENDSIM_3_FIELD	7
+#define STV090x_WIDTH_SSPY_ENDSIM_3_FIELD	1
+#define STV090x_OFFST_SSPY_ENDSIM_2_FIELD	6
+#define STV090x_WIDTH_SSPY_ENDSIM_2_FIELD	1
+#define STV090x_OFFST_SSPY_ENDSIM_1_FIELD	5
+#define STV090x_WIDTH_SSPY_ENDSIM_1_FIELD	1
+#define STV090x_OFFST_SPKTDEL_ERROR_2_FIELD	4
+#define STV090x_WIDTH_SPKTDEL_ERROR_2_FIELD	1
+#define STV090x_OFFST_SPKTDEL_LOCKB_2_FIELD	3
+#define STV090x_WIDTH_SPKTDEL_LOCKB_2_FIELD	1
+#define STV090x_OFFST_SPKTDEL_LOCK_2_FIELD	2
+#define STV090x_WIDTH_SPKTDEL_LOCK_2_FIELD	1
+#define STV090x_OFFST_SPKTDEL_ERROR_1_FIELD	1
+#define STV090x_WIDTH_SPKTDEL_ERROR_1_FIELD	1
+#define STV090x_OFFST_SPKTDEL_LOCKB_1_FIELD	0
+#define STV090x_WIDTH_SPKTDEL_LOCKB_1_FIELD	1
+
+#define STV090x_IRQSTATUS1			0xf122
+#define STV090x_OFFST_SPKTDEL_LOCK_1_FIELD	7
+#define STV090x_WIDTH_SPKTDEL_LOCK_1_FIELD	1
+#define STV090x_OFFST_SDEMOD_LOCKB_2_FIELD	2
+#define STV090x_WIDTH_SDEMOD_LOCKB_2_FIELD	1
+#define STV090x_OFFST_SDEMOD_LOCK_2_FIELD	1
+#define STV090x_WIDTH_SDEMOD_LOCK_2_FIELD	1
+#define STV090x_OFFST_SDEMOD_IRQ_2_FIELD	0
+#define STV090x_WIDTH_SDEMOD_IRQ_2_FIELD	1
+
+#define STV090x_IRQSTATUS0			0xf123
+#define STV090x_OFFST_SDEMOD_LOCKB_1_FIELD	7
+#define STV090x_WIDTH_SDEMOD_LOCKB_1_FIELD	1
+#define STV090x_OFFST_SDEMOD_LOCK_1_FIELD	6
+#define STV090x_WIDTH_SDEMOD_LOCK_1_FIELD	1
+#define STV090x_OFFST_SDEMOD_IRQ_1_FIELD	5
+#define STV090x_WIDTH_SDEMOD_IRQ_1_FIELD	1
+#define STV090x_OFFST_SBCH_ERRFLAG_FIELD	4
+#define STV090x_WIDTH_SBCH_ERRFLAG_FIELD	1
+#define STV090x_OFFST_SDISEQC2RX_IRQ_FIELD	3
+#define STV090x_WIDTH_SDISEQC2RX_IRQ_FIELD	1
+#define STV090x_OFFST_SDISEQC2TX_IRQ_FIELD	2
+#define STV090x_WIDTH_SDISEQC2TX_IRQ_FIELD	1
+#define STV090x_OFFST_SDISEQC1RX_IRQ_FIELD	1
+#define STV090x_WIDTH_SDISEQC1RX_IRQ_FIELD	1
+#define STV090x_OFFST_SDISEQC1TX_IRQ_FIELD	0
+#define STV090x_WIDTH_SDISEQC1TX_IRQ_FIELD	1
+
+#define STV090x_IRQMASK3			0xf124
+#define STV090x_OFFST_MPLL_LOCK_FIELD		5
+#define STV090x_WIDTH_MPLL_LOCK_FIELD		1
+#define STV090x_OFFST_MSTREAM_LCK_3_FIELD	2
+#define STV090x_WIDTH_MSTREAM_LCK_3_FIELD	3
+#define STV090x_OFFST_MSTREAM_LCK_2_FIELD	2
+#define STV090x_WIDTH_MSTREAM_LCK_2_FIELD	3
+#define STV090x_OFFST_MSTREAM_LCK_1_FIELD	2
+#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD	3
+#define STV090x_OFFST_MDVBS1_PRF_2_FIELD	1
+#define STV090x_WIDTH_MDVBS1_PRF_2_FIELD	1
+#define STV090x_OFFST_MDVBS1_PRF_1_FIELD	0
+#define STV090x_WIDTH_MDVBS1_PRF_1_FIELD	1
+
+#define STV090x_IRQMASK2			0xf125
+#define STV090x_OFFST_MSPY_ENDSIM_3_FIELD	5
+#define STV090x_WIDTH_MSPY_ENDSIM_3_FIELD	3
+#define STV090x_OFFST_MSPY_ENDSIM_2_FIELD	5
+#define STV090x_WIDTH_MSPY_ENDSIM_2_FIELD	3
+#define STV090x_OFFST_MSPY_ENDSIM_1_FIELD	5
+#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD	3
+#define STV090x_OFFST_MPKTDEL_ERROR_2_FIELD	4
+#define STV090x_WIDTH_MPKTDEL_ERROR_2_FIELD	1
+#define STV090x_OFFST_MPKTDEL_LOCKB_2_FIELD	3
+#define STV090x_WIDTH_MPKTDEL_LOCKB_2_FIELD	1
+#define STV090x_OFFST_MPKTDEL_LOCK_2_FIELD	2
+#define STV090x_WIDTH_MPKTDEL_LOCK_2_FIELD	1
+#define STV090x_OFFST_MPKTDEL_ERROR_1_FIELD	1
+#define STV090x_WIDTH_MPKTDEL_ERROR_1_FIELD	1
+#define STV090x_OFFST_MPKTDEL_LOCKB_1_FIELD	0
+#define STV090x_WIDTH_MPKTDEL_LOCKB_1_FIELD	1
+
+#define STV090x_IRQMASK1			0xf126
+#define STV090x_OFFST_MPKTDEL_LOCK_1_FIELD	7
+#define STV090x_WIDTH_MPKTDEL_LOCK_1_FIELD	1
+#define STV090x_OFFST_MEXTPINB2_FIELD		6
+#define STV090x_WIDTH_MEXTPINB2_FIELD		1
+#define STV090x_OFFST_MEXTPIN2_FIELD		5
+#define STV090x_WIDTH_MEXTPIN2_FIELD		1
+#define STV090x_OFFST_MEXTPINB1_FIELD		4
+#define STV090x_WIDTH_MEXTPINB1_FIELD		1
+#define STV090x_OFFST_MEXTPIN1_FIELD		3
+#define STV090x_WIDTH_MEXTPIN1_FIELD		1
+#define STV090x_OFFST_MDEMOD_LOCKB_2_FIELD	2
+#define STV090x_WIDTH_MDEMOD_LOCKB_2_FIELD	1
+#define STV090x_OFFST_MDEMOD_LOCK_2_FIELD	1
+#define STV090x_WIDTH_MDEMOD_LOCK_2_FIELD	1
+#define STV090x_OFFST_MDEMOD_IRQ_2_FIELD	0
+#define STV090x_WIDTH_MDEMOD_IRQ_2_FIELD	1
+
+#define STV090x_IRQMASK0			0xf127
+#define STV090x_OFFST_MDEMOD_LOCKB_1_FIELD	7
+#define STV090x_WIDTH_MDEMOD_LOCKB_1_FIELD	1
+#define STV090x_OFFST_MDEMOD_LOCK_1_FIELD	6
+#define STV090x_WIDTH_MDEMOD_LOCK_1_FIELD	1
+#define STV090x_OFFST_MDEMOD_IRQ_1_FIELD	5
+#define STV090x_WIDTH_MDEMOD_IRQ_1_FIELD	1
+#define STV090x_OFFST_MBCH_ERRFLAG_FIELD	4
+#define STV090x_WIDTH_MBCH_ERRFLAG_FIELD	1
+#define STV090x_OFFST_MDISEQC2RX_IRQ_FIELD	3
+#define STV090x_WIDTH_MDISEQC2RX_IRQ_FIELD	1
+#define STV090x_OFFST_MDISEQC2TX_IRQ_FIELD	2
+#define STV090x_WIDTH_MDISEQC2TX_IRQ_FIELD	1
+#define STV090x_OFFST_MDISEQC1RX_IRQ_FIELD	1
+#define STV090x_WIDTH_MDISEQC1RX_IRQ_FIELD	1
+#define STV090x_OFFST_MDISEQC1TX_IRQ_FIELD	0
+#define STV090x_WIDTH_MDISEQC1TX_IRQ_FIELD	1
+
+#define STV090x_I2CCFG				0xf129
+#define STV090x_OFFST_12C_FASTMODE_FIELD	3
+#define STV090x_WIDTH_12C_FASTMODE_FIELD	1
+#define STV090x_OFFST_12CADDR_INC_FIELD		0
+#define STV090x_WIDTH_12CADDR_INC_FIELD		2
+
+#define STV090x_Px_I2CRPT(__x)			(0xf12a + (__x - 1) * 0x1)
+#define STV090x_P1_I2CRPT			STV090x_Px_I2CRPT(1)
+#define STV090x_P2_I2CRPT			STV090x_Px_I2CRPT(2)
+#define STV090x_OFFST_Px_I2CT_ON_FIELD		7
+#define STV090x_WIDTH_Px_I2CT_ON_FIELD		1
+#define STV090x_OFFST_Px_ENARPT_LEVEL_FIELD	4
+#define STV090x_WIDTH_Px_ENARPT_LEVEL_FIELD	3
+#define STV090x_OFFST_Px_SCLT_DELAY_FIELD	3
+#define STV090x_WIDTH_Px_SCLT_DELAY_FIELD	1
+#define STV090x_OFFST_Px_STOP_ENABLE_FIELD	2
+#define STV090x_WIDTH_Px_STOP_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_STOP_SDAT2SDA_FIELD	1
+#define STV090x_WIDTH_Px_STOP_SDAT2SDA_FIELD	1
+
+#define STV090x_CLKI2CFG			0xf140
+#define STV090x_OFFST_CLKI2_OPD_FIELD		7
+#define STV090x_WIDTH_CLKI2_OPD_FIELD		1
+#define STV090x_OFFST_CLKI2_CONFIG_FIELD	1
+#define STV090x_WIDTH_CLKI2_CONFIG_FIELD	6
+#define STV090x_OFFST_CLKI2_XOR_FIELD		0
+#define STV090x_WIDTH_CLKI2_XOR_FIELD		1
+
+#define STV090x_GPIOxCFG(__x)			(0xf141 + (__x - 1))
+#define STV090x_GPIO1CFG			STV090x_GPIOxCFG(1)
+#define STV090x_GPIO2CFG			STV090x_GPIOxCFG(2)
+#define STV090x_GPIO3CFG			STV090x_GPIOxCFG(3)
+#define STV090x_GPIO4CFG			STV090x_GPIOxCFG(4)
+#define STV090x_GPIO5CFG			STV090x_GPIOxCFG(5)
+#define STV090x_GPIO6CFG			STV090x_GPIOxCFG(6)
+#define STV090x_GPIO7CFG			STV090x_GPIOxCFG(7)
+#define STV090x_GPIO8CFG			STV090x_GPIOxCFG(8)
+#define STV090x_GPIO9CFG			STV090x_GPIOxCFG(9)
+#define STV090x_GPIO10CFG			STV090x_GPIOxCFG(10)
+#define STV090x_GPIO11CFG			STV090x_GPIOxCFG(11)
+#define STV090x_GPIO12CFG			STV090x_GPIOxCFG(12)
+#define STV090x_GPIO13CFG			STV090x_GPIOxCFG(13)
+#define STV090x_OFFST_GPIOx_OPD_FIELD		7
+#define STV090x_WIDTH_GPIOx_OPD_FIELD		1
+#define STV090x_OFFST_GPIOx_CONFIG_FIELD	1
+#define STV090x_WIDTH_GPIOx_CONFIG_FIELD	6
+#define STV090x_OFFST_GPIOx_XOR_FIELD		0
+#define STV090x_WIDTH_GPIOx_XOR_FIELD		1
+
+#define STV090x_CSxCFG(__x)			(0xf14e + __x * 0x1)
+#define STV090x_CS0CFG				STV090x_CSxCFG(0)
+#define STV090x_CS1CFG				STV090x_CSxCFG(1)
+#define STV090x_OFFST_CSX_OPD_FIELD		7
+#define STV090x_WIDTH_CSX_OPD_FIELD		1
+#define STV090x_OFFST_CSX_CONFIG_FIELD		1
+#define STV090x_WIDTH_CSX_CONFIG_FIELD		6
+#define STV090x_OFFST_CSX_XOR_FIELD		0
+#define STV090x_WIDTH_CSX_XOR_FIELD		1
+
+
+#define STV090x_STDBYCFG			0xf150
+#define STV090x_OFFST_STDBY_OPD_FIELD		7
+#define STV090x_WIDTH_STDBY_OPD_FIELD		1
+#define STV090x_OFFST_STDBY_CONFIG_FIELD	1
+#define STV090x_WIDTH_STDBY_CONFIG_FIELD	6
+#define STV090x_OFFST_STDBY_XOR_FIELD		0
+#define STV090x_WIDTH_STDBY_XOR_FIELD		1
+
+#define STV090x_DIRCLKCFG			0xf151
+#define STV090x_OFFST_DIRCLK_OPD_FIELD		7
+#define STV090x_WIDTH_DIRCLK_OPD_FIELD		1
+#define STV090x_OFFST_DIRCLK_CONFIG_FIELD	1
+#define STV090x_WIDTH_DIRCLK_CONFIG_FIELD	6
+#define STV090x_OFFST_DIRCLK_XOR_FIELD		0
+#define STV090x_WIDTH_DIRCLK_XOR_FIELD		1
+
+
+#define STV090x_AGCRFxCFG(__x)			(0xf152 + (__x - 1) * 0x4)
+#define STV090x_AGCRF1CFG			STV090x_AGCRFxCFG(1)
+#define STV090x_AGCRF2CFG			STV090x_AGCRFxCFG(2)
+#define STV090x_OFFST_AGCRFx_OPD_FIELD		7
+#define STV090x_WIDTH_AGCRFx_OPD_FIELD		1
+#define STV090x_OFFST_AGCRFx_CONFIG_FIELD	1
+#define STV090x_WIDTH_AGCRFx_CONFIG_FIELD	6
+#define STV090x_OFFST_AGCRFx_XOR_FIELD		0
+#define STV090x_WIDTH_AGCRFx_XOR_FIELD		1
+
+#define STV090x_SDATxCFG(__x)			(0xf153 + (__x - 1) * 0x4)
+#define STV090x_SDAT1CFG			STV090x_SDATxCFG(1)
+#define STV090x_SDAT2CFG			STV090x_SDATxCFG(2)
+#define STV090x_OFFST_SDATx_OPD_FIELD		7
+#define STV090x_WIDTH_SDATx_OPD_FIELD		1
+#define STV090x_OFFST_SDATx_CONFIG_FIELD	1
+#define STV090x_WIDTH_SDATx_CONFIG_FIELD	6
+#define STV090x_OFFST_SDATx_XOR_FIELD		0
+#define STV090x_WIDTH_SDATx_XOR_FIELD		1
+
+#define STV090x_SCLTxCFG(__x)			(0xf154 + (__x - 1) * 0x4)
+#define STV090x_SCLT1CFG			STV090x_SCLTxCFG(1)
+#define STV090x_SCLT2CFG			STV090x_SCLTxCFG(2)
+#define STV090x_OFFST_SCLTx_OPD_FIELD		7
+#define STV090x_WIDTH_SCLTx_OPD_FIELD		1
+#define STV090x_OFFST_SCLTx_CONFIG_FIELD	1
+#define STV090x_WIDTH_SCLTx_CONFIG_FIELD	6
+#define STV090x_OFFST_SCLTx_XOR_FIELD		0
+#define STV090x_WIDTH_SCLTx_XOR_FIELD		1
+
+#define STV090x_DISEQCOxCFG(__x)		(0xf155 + (__x - 1) * 0x4)
+#define STV090x_DISEQCO1CFG			STV090x_DISEQCOxCFG(1)
+#define STV090x_DISEQCO2CFG			STV090x_DISEQCOxCFG(2)
+#define STV090x_OFFST_DISEQCOx_OPD_FIELD	7
+#define STV090x_WIDTH_DISEQCOx_OPD_FIELD	1
+#define STV090x_OFFST_DISEQCOx_CONFIG_FIELD	1
+#define STV090x_WIDTH_DISEQCOx_CONFIG_FIELD	6
+#define STV090x_OFFST_DISEQCOx_XOR_FIELD	0
+#define STV090x_WIDTH_DISEQCOx_XOR_FIELD	1
+
+#define STV090x_CLKOUT27CFG			0xf15a
+#define STV090x_OFFST_CLKOUT27_OPD_FIELD	7
+#define STV090x_WIDTH_CLKOUT27_OPD_FIELD	1
+#define STV090x_OFFST_CLKOUT27_CONFIG_FIELD	1
+#define STV090x_WIDTH_CLKOUT27_CONFIG_FIELD	6
+#define STV090x_OFFST_CLKOUT27_XOR_FIELD	0
+#define STV090x_WIDTH_CLKOUT27_XOR_FIELD	1
+
+#define STV090x_ERRORxCFG(__x)			(0xf15b + (__x - 1) * 0x5)
+#define STV090x_ERROR1CFG			STV090x_ERRORxCFG(1)
+#define STV090x_ERROR2CFG			STV090x_ERRORxCFG(2)
+#define STV090x_ERROR3CFG			STV090x_ERRORxCFG(3)
+#define STV090x_OFFST_ERRORx_OPD_FIELD		7
+#define STV090x_WIDTH_ERRORx_OPD_FIELD		1
+#define STV090x_OFFST_ERRORx_CONFIG_FIELD	1
+#define STV090x_WIDTH_ERRORx_CONFIG_FIELD	6
+#define STV090x_OFFST_ERRORx_XOR_FIELD		0
+#define STV090x_WIDTH_ERRORx_XOR_FIELD		1
+
+#define STV090x_DPNxCFG(__x)			(0xf15c + (__x - 1) * 0x5)
+#define STV090x_DPN1CFG				STV090x_DPNxCFG(1)
+#define STV090x_DPN2CFG				STV090x_DPNxCFG(2)
+#define STV090x_DPN3CFG				STV090x_DPNxCFG(3)
+#define STV090x_OFFST_DPNx_OPD_FIELD		7
+#define STV090x_WIDTH_DPNx_OPD_FIELD		1
+#define STV090x_OFFST_DPNx_CONFIG_FIELD		1
+#define STV090x_WIDTH_DPNx_CONFIG_FIELD		6
+#define STV090x_OFFST_DPNx_XOR_FIELD		0
+#define STV090x_WIDTH_DPNx_XOR_FIELD		1
+
+#define STV090x_STROUTxCFG(__x)			(0xf15d + (__x - 1) * 0x5)
+#define STV090x_STROUT1CFG			STV090x_STROUTxCFG(1)
+#define STV090x_STROUT2CFG			STV090x_STROUTxCFG(2)
+#define STV090x_STROUT3CFG			STV090x_STROUTxCFG(3)
+#define STV090x_OFFST_STROUTx_OPD_FIELD		7
+#define STV090x_WIDTH_STROUTx_OPD_FIELD		1
+#define STV090x_OFFST_STROUTx_CONFIG_FIELD	1
+#define STV090x_WIDTH_STROUTx_CONFIG_FIELD	6
+#define STV090x_OFFST_STROUTx_XOR_FIELD		0
+#define STV090x_WIDTH_STROUTx_XOR_FIELD		1
+
+#define STV090x_CLKOUTxCFG(__x)			(0xf15e + (__x - 1) * 0x5)
+#define STV090x_CLKOUT1CFG			STV090x_CLKOUTxCFG(1)
+#define STV090x_CLKOUT2CFG			STV090x_CLKOUTxCFG(2)
+#define STV090x_CLKOUT3CFG			STV090x_CLKOUTxCFG(3)
+#define STV090x_OFFST_CLKOUTx_OPD_FIELD		7
+#define STV090x_WIDTH_CLKOUTx_OPD_FIELD		1
+#define STV090x_OFFST_CLKOUTx_CONFIG_FIELD	1
+#define STV090x_WIDTH_CLKOUTx_CONFIG_FIELD	6
+#define STV090x_OFFST_CLKOUTx_XOR_FIELD		0
+#define STV090x_WIDTH_CLKOUTx_XOR_FIELD		1
+
+#define STV090x_DATAxCFG(__x)			(0xf15f + (__x - 71) * 0x5)
+#define STV090x_DATA71CFG			STV090x_DATAxCFG(71)
+#define STV090x_DATA72CFG			STV090x_DATAxCFG(72)
+#define STV090x_DATA73CFG			STV090x_DATAxCFG(73)
+#define STV090x_OFFST_DATAx_OPD_FIELD		7
+#define STV090x_WIDTH_DATAx_OPD_FIELD		1
+#define STV090x_OFFST_DATAx_CONFIG_FIELD	1
+#define STV090x_WIDTH_DATAx_CONFIG_FIELD	6
+#define STV090x_OFFST_DATAx_XOR_FIELD		0
+#define STV090x_WIDTH_DATAx_XOR_FIELD		1
+
+#define STV090x_NCOARSE				0xf1b3
+#define STV090x_OFFST_M_DIV_FIELD		0
+#define STV090x_WIDTH_M_DIV_FIELD		8
+
+#define STV090x_SYNTCTRL			0xf1b6
+#define STV090x_OFFST_STANDBY_FIELD		7
+#define STV090x_WIDTH_STANDBY_FIELD		1
+#define STV090x_OFFST_BYPASSPLLCORE_FIELD	6
+#define STV090x_WIDTH_BYPASSPLLCORE_FIELD	1
+#define STV090x_OFFST_SELX1RATIO_FIELD		5
+#define STV090x_WIDTH_SELX1RATIO_FIELD		1
+#define STV090x_OFFST_STOP_PLL_FIELD		3
+#define STV090x_WIDTH_SELX1RATIO_FIELD		1
+#define STV090x_OFFST_BYPASSPLLFSK_FIELD	2
+#define STV090x_WIDTH_BYPASSPLLFSK_FIELD	1
+#define STV090x_OFFST_SELOSCI_FIELD		1
+#define STV090x_WIDTH_SELOSCI_FIELD		1
+#define STV090x_OFFST_BYPASSPLLADC_FIELD	0
+#define STV090x_WIDTH_BYPASSPLLADC_FIELD	1
+
+#define STV090x_FILTCTRL			0xf1b7
+#define STV090x_OFFST_INV_CLK135_FIELD		7
+#define STV090x_WIDTH_INV_CLK135_FIELD		1
+#define STV090x_OFFST_SEL_FSKCKDIV_FIELD	2
+#define STV090x_WIDTH_SEL_FSKCKDIV_FIELD	1
+#define STV090x_OFFST_INV_CLKFSK_FIELD		1
+#define STV090x_WIDTH_INV_CLKFSK_FIELD		1
+#define STV090x_OFFST_BYPASS_APPLI_FIELD	0
+#define STV090x_WIDTH_BYPASS_APPLI_FIELD	1
+
+#define STV090x_PLLSTAT				0xf1b8
+#define STV090x_OFFST_PLLLOCK_FIELD		0
+#define STV090x_WIDTH_PLLLOCK_FIELD		1
+
+#define STV090x_STOPCLK1			0xf1c2
+#define STV090x_OFFST_STOP_CLKPKDT2_FIELD	6
+#define STV090x_WIDTH_STOP_CLKPKDT2_FIELD	1
+#define STV090x_OFFST_STOP_CLKPKDT1_FIELD	5
+#define STV090x_WIDTH_STOP_CLKPKDT1_FIELD	1
+#define STV090x_OFFST_STOP_CLKFEC_FIELD		4
+#define STV090x_WIDTH_STOP_CLKFEC_FIELD		1
+#define STV090x_OFFST_STOP_CLKADCI2_FIELD	3
+#define STV090x_WIDTH_STOP_CLKADCI2_FIELD	1
+#define STV090x_OFFST_INV_CLKADCI2_FIELD	2
+#define STV090x_WIDTH_INV_CLKADCI2_FIELD	1
+#define STV090x_OFFST_STOP_CLKADCI1_FIELD	1
+#define STV090x_WIDTH_STOP_CLKADCI1_FIELD	1
+#define STV090x_OFFST_INV_CLKADCI1_FIELD	0
+#define STV090x_WIDTH_INV_CLKADCI1_FIELD	1
+
+#define STV090x_STOPCLK2			0xf1c3
+#define STV090x_OFFST_STOP_CLKSAMP2_FIELD	4
+#define STV090x_WIDTH_STOP_CLKSAMP2_FIELD	1
+#define STV090x_OFFST_STOP_CLKSAMP1_FIELD	3
+#define STV090x_WIDTH_STOP_CLKSAMP1_FIELD	1
+#define STV090x_OFFST_STOP_CLKVIT2_FIELD	2
+#define STV090x_WIDTH_STOP_CLKVIT2_FIELD	1
+#define STV090x_OFFST_STOP_CLKVIT1_FIELD	1
+#define STV090x_WIDTH_STOP_CLKVIT1_FIELD	1
+#define STV090x_OFFST_STOP_CLKTS_FIELD		0
+#define STV090x_WIDTH_STOP_CLKTS_FIELD		1
+
+#define STV090x_TSTTNR0				0xf1df
+#define STV090x_OFFST_SEL_FSK_FIELD		7
+#define STV090x_WIDTH_SEL_FSK_FIELD		1
+#define STV090x_OFFST_FSK_PON_FIELD		2
+#define STV090x_WIDTH_FSK_PON_FIELD		1
+
+#define STV090x_TSTTNR1				0xf1e0
+#define STV090x_OFFST_ADC1_PON_FIELD		1
+#define STV090x_WIDTH_ADC1_PON_FIELD		1
+#define STV090x_OFFST_ADC1_INMODE_FIELD		0
+#define STV090x_WIDTH_ADC1_INMODE_FIELD		1
+
+#define STV090x_TSTTNR2				0xf1e1
+#define STV090x_OFFST_DISEQC1_PON_FIELD		5
+#define STV090x_WIDTH_DISEQC1_PON_FIELD		1
+
+#define STV090x_TSTTNR3				0xf1e2
+#define STV090x_OFFST_ADC2_PON_FIELD		1
+#define STV090x_WIDTH_ADC2_PON_FIELD		1
+#define STV090x_OFFST_ADC2_INMODE_FIELD		0
+#define STV090x_WIDTH_ADC2_INMODE_FIELD		1
+
+#define STV090x_TSTTNR4				0xf1e3
+#define STV090x_OFFST_DISEQC2_PON_FIELD		5
+#define STV090x_WIDTH_DISEQC2_PON_FIELD		1
+
+#define STV090x_FSKTFC2				0xf170
+#define STV090x_OFFST_FSKT_KMOD_FIELD		2
+#define STV090x_WIDTH_FSKT_KMOD_FIELD		6
+#define STV090x_OFFST_FSKT_CAR_FIELD		0
+#define STV090x_WIDTH_FSKT_CAR_FIELD		2
+
+#define STV090x_FSKTFC1				0xf171
+#define STV090x_OFFST_FSKTC1_CAR_FIELD		0
+#define STV090x_WIDTH_FSKTC1_CAR_FIELD		8
+
+#define STV090x_FSKTFC0				0xf172
+#define STV090x_OFFST_FSKTC0_CAR_FIELD		0
+#define STV090x_WIDTH_FSKTC0_CAR_FIELD		8
+
+#define STV090x_FSKTDELTAF1			0xf173
+#define STV090x_OFFST_FSKTF1_DELTAF_FIELD	0
+#define STV090x_WIDTH_FSKTF1_DELTAF_FIELD	4
+
+#define STV090x_FSKTDELTAF0			0xf174
+#define STV090x_OFFST_FSKTF0_DELTAF_FIELD	0
+#define STV090x_WIDTH_FSKTF0_DELTAF_FIELD	8
+
+#define STV090x_FSKTCTRL			0xf175
+#define STV090x_OFFST_FSKT_EN_SGN_FIELD		6
+#define STV090x_WIDTH_FSKT_EN_SGN_FIELD		1
+#define STV090x_OFFST_FSKT_MOD_SGN_FIELD	5
+#define STV090x_WIDTH_FSKT_MOD_SGN_FIELD	1
+#define STV090x_OFFST_FSKT_MOD_EN_FIELD		2
+#define STV090x_WIDTH_FSKT_MOD_EN_FIELD		3
+#define STV090x_OFFST_FSKT_DACMODE_FIELD	0
+#define STV090x_WIDTH_FSKT_DACMODE_FIELD	2
+
+#define STV090x_FSKRFC2				0xf176
+#define STV090x_OFFST_FSKRC2_DETSGN_FIELD	6
+#define STV090x_WIDTH_FSKRC2_DETSGN_FIELD	1
+#define STV090x_OFFST_FSKRC2_OUTSGN_FIELD	5
+#define STV090x_WIDTH_FSKRC2_OUTSGN_FIELD	1
+#define STV090x_OFFST_FSKRC2_KAGC_FIELD		2
+#define STV090x_WIDTH_FSKRC2_KAGC_FIELD		3
+#define STV090x_OFFST_FSKRC2_CAR_FIELD		0
+#define STV090x_WIDTH_FSKRC2_CAR_FIELD		2
+
+#define STV090x_FSKRFC1				0xf177
+#define STV090x_OFFST_FSKRC1_CAR_FIELD		0
+#define STV090x_WIDTH_FSKRC1_CAR_FIELD		8
+
+#define STV090x_FSKRFC0				0xf178
+#define STV090x_OFFST_FSKRC0_CAR_FIELD		0
+#define STV090x_WIDTH_FSKRC0_CAR_FIELD		8
+
+#define STV090x_FSKRK1				0xf179
+#define STV090x_OFFST_FSKR_K1_EXP_FIELD		5
+#define STV090x_WIDTH_FSKR_K1_EXP_FIELD		3
+#define STV090x_OFFST_FSKR_K1_MANT_FIELD	0
+#define STV090x_WIDTH_FSKR_K1_MANT_FIELD	5
+
+#define STV090x_FSKRK2				0xf17a
+#define STV090x_OFFST_FSKR_K2_EXP_FIELD		5
+#define STV090x_WIDTH_FSKR_K2_EXP_FIELD		3
+#define STV090x_OFFST_FSKR_K2_MANT_FIELD	0
+#define STV090x_WIDTH_FSKR_K2_MANT_FIELD	5
+
+#define STV090x_FSKRAGCR			0xf17b
+#define STV090x_OFFST_FSKR_OUTCTL_FIELD		6
+#define STV090x_WIDTH_FSKR_OUTCTL_FIELD		2
+#define STV090x_OFFST_FSKR_AGC_REF_FIELD	0
+#define STV090x_WIDTH_FSKR_AGC_REF_FIELD	6
+
+#define STV090x_FSKRAGC				0xf17c
+#define STV090x_OFFST_FSKR_AGC_ACCU_FIELD	0
+#define STV090x_WIDTH_FSKR_AGC_ACCU_FIELD	8
+
+#define STV090x_FSKRALPHA			0xf17d
+#define STV090x_OFFST_FSKR_ALPHA_EXP_FIELD	2
+#define STV090x_WIDTH_FSKR_ALPHA_EXP_FIELD	3
+#define STV090x_OFFST_FSKR_ALPHA_M_FIELD	0
+#define STV090x_WIDTH_FSKR_ALPHA_M_FIELD	2
+
+#define STV090x_FSKRPLTH1			0xf17e
+#define STV090x_OFFST_FSKR_BETA_FIELD		4
+#define STV090x_WIDTH_FSKR_BETA_FIELD		4
+#define STV090x_OFFST_FSKR_PLL_TRESH1_FIELD	0
+#define STV090x_WIDTH_FSKR_PLL_TRESH1_FIELD	4
+
+#define STV090x_FSKRPLTH0			0xf17f
+#define STV090x_OFFST_FSKR_PLL_TRESH0_FIELD	0
+#define STV090x_WIDTH_FSKR_PLL_TRESH0_FIELD	8
+
+#define STV090x_FSKRDF1				0xf180
+#define STV090x_OFFST_FSKR_DELTAF1_FIELD	0
+#define STV090x_WIDTH_FSKR_DELTAF1_FIELD	5
+
+#define STV090x_FSKRDF0				0xf181
+#define STV090x_OFFST_FSKR_DELTAF0_FIELD	0
+#define STV090x_WIDTH_FSKR_DELTAF0_FIELD	8
+
+#define STV090x_FSKRSTEPP			0xf182
+#define STV090x_OFFST_FSKR_STEP_PLUS_FIELD	0
+#define STV090x_WIDTH_FSKR_STEP_PLUS_FIELD	8
+
+#define STV090x_FSKRSTEPM			0xf183
+#define STV090x_OFFST_FSKR_STEP_MINUS_FIELD	0
+#define STV090x_WIDTH_FSKR_STEP_MINUS_FIELD	8
+
+#define STV090x_FSKRDET1			0xf184
+#define STV090x_OFFST_FSKR_CARDET1_ACCU_FIELD	0
+#define STV090x_WIDTH_FSKR_CARDET1_ACCU_FIELD	4
+
+#define STV090x_FSKRDET0			0xf185
+#define STV090x_OFFST_FSKR_CARDET0_ACCU_FIELD	0
+#define STV090x_WIDTH_FSKR_CARDET0_ACCU_FIELD	8
+
+#define STV090x_FSKRDTH1				0xf186
+#define STV090x_OFFST_FSKR_CARLOSS_THRESH1_FIELD	4
+#define STV090x_WIDTH_FSKR_CARLOSS_THRESH1_FIELD	4
+#define STV090x_OFFST_FSKR_CARDET_THRESH1_FIELD		0
+#define STV090x_WIDTH_FSKR_CARDET_THRESH1_FIELD		4
+
+#define STV090x_FSKRDTH0			0xf187
+#define STV090x_OFFST_FSKR_CARDET_THRESH0_FIELD	0
+#define STV090x_WIDTH_FSKR_CARDET_THRESH0_FIELD	8
+
+#define STV090x_FSKRLOSS			0xf188
+#define STV090x_OFFST_FSKR_CARLOSS_THRESH_FIELD	0
+#define STV090x_WIDTH_FSKR_CARLOSS_THRESH_FIELD	8
+
+#define STV090x_Px_DISTXCTL(__x)		(0xF1A0 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXCTL			STV090x_Px_DISTXCTL(1)
+#define STV090x_P2_DISTXCTL			STV090x_Px_DISTXCTL(2)
+#define STV090x_OFFST_Px_TIM_OFF_FIELD		7
+#define STV090x_WIDTH_Px_TIM_OFF_FIELD		1
+#define STV090x_OFFST_Px_DISEQC_RESET_FIELD	6
+#define STV090x_WIDTH_Px_DISEQC_RESET_FIELD	1
+#define STV090x_OFFST_Px_TIM_CMD_FIELD		4
+#define STV090x_WIDTH_Px_TIM_CMD_FIELD		2
+#define STV090x_OFFST_Px_DIS_PRECHARGE_FIELD	3
+#define STV090x_WIDTH_Px_DIS_PRECHARGE_FIELD	1
+#define STV090x_OFFST_Px_DISTX_MODE_FIELD	0
+#define STV090x_WIDTH_Px_DISTX_MODE_FIELD	3
+
+#define STV090x_Px_DISRXCTL(__x)		(0xf1a1 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRXCTL			STV090x_Px_DISRXCTL(1)
+#define STV090x_P2_DISRXCTL			STV090x_Px_DISRXCTL(2)
+#define STV090x_OFFST_Px_RECEIVER_ON_FIELD	7
+#define STV090x_WIDTH_Px_RECEIVER_ON_FIELD	1
+#define STV090x_OFFST_Px_IGNO_SHORT22K_FIELD	6
+#define STV090x_WIDTH_Px_IGNO_SHORT22K_FIELD	1
+#define STV090x_OFFST_Px_ONECHIP_TRX_FIELD	5
+#define STV090x_WIDTH_Px_ONECHIP_TRX_FIELD	1
+#define STV090x_OFFST_Px_EXT_ENVELOP_FIELD	4
+#define STV090x_WIDTH_Px_EXT_ENVELOP_FIELD	1
+#define STV090x_OFFST_Px_PIN_SELECT_FIELD	2
+#define STV090x_WIDTH_Px_PIN_SELECT_FIELD	2
+#define STV090x_OFFST_Px_IRQ_RXEND_FIELD	1
+#define STV090x_WIDTH_Px_IRQ_RXEND_FIELD	1
+#define STV090x_OFFST_Px_IRQ_4NBYTES_FIELD	0
+#define STV090x_WIDTH_Px_IRQ_4NBYTES_FIELD	1
+
+#define STV090x_Px_DISRX_ST0(__x)		(0xf1a4 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRX_ST0			STV090x_Px_DISRX_ST0(1)
+#define STV090x_P2_DISRX_ST0			STV090x_Px_DISRX_ST0(2)
+#define STV090x_OFFST_Px_RX_END_FIELD		7
+#define STV090x_WIDTH_Px_RX_END_FIELD		1
+#define STV090x_OFFST_Px_RX_ACTIVE_FIELD	6
+#define STV090x_WIDTH_Px_RX_ACTIVE_FIELD	1
+#define STV090x_OFFST_Px_SHORT_22KHZ_FIELD	5
+#define STV090x_WIDTH_Px_SHORT_22KHZ_FIELD	1
+#define STV090x_OFFST_Px_CONT_TONE_FIELD	4
+#define STV090x_WIDTH_Px_CONT_TONE_FIELD	1
+#define STV090x_OFFST_Px_FIFO_4BREADY_FIELD	3
+#define STV090x_WIDTH_Px_FIFO_4BREADY_FIELD	2
+#define STV090x_OFFST_Px_FIFO_EMPTY_FIELD	2
+#define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD	1
+#define STV090x_OFFST_Px_ABORT_DISRX_FIELD	0
+#define STV090x_WIDTH_Px_ABORT_DISRX_FIELD	1
+
+#define STV090x_Px_DISRX_ST1(__x)		(0xf1a5 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRX_ST1			STV090x_Px_DISRX_ST1(1)
+#define STV090x_P2_DISRX_ST1			STV090x_Px_DISRX_ST1(2)
+#define STV090x_OFFST_Px_RX_FAIL_FIELD		7
+#define STV090x_WIDTH_Px_RX_FAIL_FIELD		1
+#define STV090x_OFFST_Px_FIFO_PARITYFAIL_FIELD	6
+#define STV090x_WIDTH_Px_FIFO_PARITYFAIL_FIELD	1
+#define STV090x_OFFST_Px_RX_NONBYTE_FIELD	5
+#define STV090x_WIDTH_Px_RX_NONBYTE_FIELD	1
+#define STV090x_OFFST_Px_FIFO_OVERFLOW_FIELD	4
+#define STV090x_WIDTH_Px_FIFO_OVERFLOW_FIELD	1
+#define STV090x_OFFST_Px_FIFO_BYTENBR_FIELD	0
+#define STV090x_WIDTH_Px_FIFO_BYTENBR_FIELD	4
+
+#define STV090x_Px_DISRXDATA(__x)		(0xf1a6 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRXDATA			STV090x_Px_DISRXDATA(1)
+#define STV090x_P2_DISRXDATA			STV090x_Px_DISRXDATA(2)
+#define STV090x_OFFST_Px_DISRX_DATA_FIELD	0
+#define STV090x_WIDTH_Px_DISRX_DATA_FIELD	8
+
+#define STV090x_Px_DISTXDATA(__x)		(0xf1a7 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXDATA			STV090x_Px_DISTXDATA(1)
+#define STV090x_P2_DISTXDATA			STV090x_Px_DISTXDATA(2)
+#define STV090x_OFFST_Px_DISEQC_FIFO_FIELD	0
+#define STV090x_WIDTH_Px_DISEQC_FIFO_FIELD	8
+
+#define STV090x_Px_DISTXSTATUS(__x)		(0xf1a8 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXSTATUS			STV090x_Px_DISTXSTATUS(1)
+#define STV090x_P2_DISTXSTATUS			STV090x_Px_DISTXSTATUS(2)
+#define STV090x_OFFST_Px_TX_FAIL_FIELD		7
+#define STV090x_WIDTH_Px_TX_FAIL_FIELD		1
+#define STV090x_OFFST_Px_FIFO_FULL_FIELD	6
+#define STV090x_WIDTH_Px_FIFO_FULL_FIELD	1
+#define STV090x_OFFST_Px_TX_IDLE_FIELD		5
+#define STV090x_WIDTH_Px_TX_IDLE_FIELD		1
+#define STV090x_OFFST_Px_GAP_BURST_FIELD	4
+#define STV090x_WIDTH_Px_GAP_BURST_FIELD	1
+#define STV090x_OFFST_Px_TXFIFO_BYTES_FIELD	0
+#define STV090x_WIDTH_Px_TXFIFO_BYTES_FIELD	4
+
+#define STV090x_Px_F22TX(__x)			(0xf1a9 - (__x - 1) * 0x10)
+#define STV090x_P1_F22TX			STV090x_Px_F22TX(1)
+#define STV090x_P2_F22TX			STV090x_Px_F22TX(2)
+#define STV090x_OFFST_Px_F22_REG_FIELD		0
+#define STV090x_WIDTH_Px_F22_REG_FIELD		8
+
+#define STV090x_Px_F22RX(__x)			(0xf1aa - (__x - 1) * 0x10)
+#define STV090x_P1_F22RX			STV090x_Px_F22RX(1)
+#define STV090x_P2_F22RX			STV090x_Px_F22RX(2)
+#define STV090x_OFFST_Px_F22RX_REG_FIELD	0
+#define STV090x_WIDTH_Px_F22RX_REG_FIELD	8
+
+#define STV090x_Px_ACRPRESC(__x)		(0xf1ac - (__x - 1) * 0x10)
+#define STV090x_P1_ACRPRESC			STV090x_Px_ACRPRESC(1)
+#define STV090x_P2_ACRPRESC			STV090x_Px_ACRPRESC(2)
+#define STV090x_OFFST_Px_ACR_PRESC_FIELD	0
+#define STV090x_WIDTH_Px_ACR_PRESC_FIELD	3
+
+#define STV090x_Px_ACRDIV(__x)			(0xf1ad - (__x - 1) * 0x10)
+#define STV090x_P1_ACRDIV			STV090x_Px_ACRDIV(1)
+#define STV090x_P2_ACRDIV			STV090x_Px_ACRDIV(2)
+#define STV090x_OFFST_Px_ACR_DIV_FIELD		0
+#define STV090x_WIDTH_Px_ACR_DIV_FIELD		8
+
+#define STV090x_Px_IQCONST(__x)			(0xF400 - (__x - 1) * 0x200)
+#define STV090x_P1_IQCONST			STV090x_Px_IQCONST(1)
+#define STV090x_P2_IQCONST			STV090x_Px_IQCONST(2)
+#define STV090x_OFFST_Px_CONSTEL_SELECT_FIELD	5
+#define STV090x_WIDTH_Px_CONSTEL_SELECT_FIELD	2
+
+#define STV090x_Px_NOSCFG(__x)			(0xF401 - (__x - 1) * 0x200)
+#define STV090x_P1_NOSCFG			STV090x_Px_NOSCFG(1)
+#define STV090x_P2_NOSCFG			STV090x_Px_NOSCFG(2)
+#define STV090x_OFFST_Px_NOSPLH_BETA_FIELD	3
+#define STV090x_WIDTH_Px_NOSPLH_BETA_FIELD	2
+#define STV090x_OFFST_Px_NOSDATA_BETA_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATA_BETA_FIELD	3
+
+#define STV090x_Px_ISYMB(__x)			(0xF402 - (__x - 1) * 0x200)
+#define STV090x_P1_ISYMB			STV090x_Px_ISYMB(1)
+#define STV090x_P2_ISYMB			STV090x_Px_ISYMB(2)
+#define STV090x_OFFST_Px_I_SYMBOL_FIELD		0
+#define STV090x_WIDTH_Px_I_SYMBOL_FIELD		8
+
+#define STV090x_Px_QSYMB(__x)			(0xF403 - (__x - 1) * 0x200)
+#define STV090x_P1_QSYMB			STV090x_Px_QSYMB(1)
+#define STV090x_P2_QSYMB			STV090x_Px_QSYMB(2)
+#define STV090x_OFFST_Px_Q_SYMBOL_FIELD		0
+#define STV090x_WIDTH_Px_Q_SYMBOL_FIELD		8
+
+#define STV090x_Px_AGC1CFG(__x)			(0xF404 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1CFG			STV090x_Px_AGC1CFG(1)
+#define STV090x_P2_AGC1CFG			STV090x_Px_AGC1CFG(2)
+#define STV090x_OFFST_Px_DC_FROZEN_FIELD	7
+#define STV090x_WIDTH_Px_DC_FROZEN_FIELD	1
+#define STV090x_OFFST_Px_DC_CORRECT_FIELD	6
+#define STV090x_WIDTH_Px_DC_CORRECT_FIELD	1
+#define STV090x_OFFST_Px_AMM_FROZEN_FIELD	5
+#define STV090x_WIDTH_Px_AMM_FROZEN_FIELD	1
+#define STV090x_OFFST_Px_AMM_CORRECT_FIELD	4
+#define STV090x_WIDTH_Px_AMM_CORRECT_FIELD	1
+#define STV090x_OFFST_Px_QUAD_FROZEN_FIELD	3
+#define STV090x_WIDTH_Px_QUAD_FROZEN_FIELD	1
+#define STV090x_OFFST_Px_QUAD_CORRECT_FIELD	2
+#define STV090x_WIDTH_Px_QUAD_CORRECT_FIELD	1
+
+#define STV090x_Px_AGC1CN(__x)			(0xF406 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1CN			STV090x_Px_AGC1CN(1)
+#define STV090x_P2_AGC1CN			STV090x_Px_AGC1CN(2)
+#define STV090x_WIDTH_Px_AGC1_LOCKED_FIELD	7
+#define STV090x_OFFST_Px_AGC1_LOCKED_FIELD	1
+#define STV090x_OFFST_Px_AGC1_MINPOWER_FIELD	4
+#define STV090x_WIDTH_Px_AGC1_MINPOWER_FIELD	1
+#define STV090x_OFFST_Px_AGCOUT_FAST_FIELD	3
+#define STV090x_WIDTH_Px_AGCOUT_FAST_FIELD	1
+#define STV090x_OFFST_Px_AGCIQ_BETA_FIELD	0
+#define STV090x_WIDTH_Px_AGCIQ_BETA_FIELD	3
+
+#define STV090x_Px_AGC1REF(__x)			(0xF407 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1REF			STV090x_Px_AGC1REF(1)
+#define STV090x_P2_AGC1REF			STV090x_Px_AGC1REF(2)
+#define STV090x_OFFST_Px_AGCIQ_REF_FIELD	0
+#define STV090x_WIDTH_Px_AGCIQ_REF_FIELD	8
+
+#define STV090x_Px_IDCCOMP(__x)			(0xF408 - (__x - 1) * 0x200)
+#define STV090x_P1_IDCCOMP			STV090x_Px_IDCCOMP(1)
+#define STV090x_P2_IDCCOMP			STV090x_Px_IDCCOMP(2)
+#define STV090x_OFFST_Px_IAVERAGE_ADJ_FIELD	0
+#define STV090x_WIDTH_Px_IAVERAGE_ADJ_FIELD	8
+
+#define STV090x_Px_QDCCOMP(__x)			(0xF409 - (__x - 1) * 0x200)
+#define STV090x_P1_QDCCOMP			STV090x_Px_QDCCOMP(1)
+#define STV090x_P2_QDCCOMP			STV090x_Px_QDCCOMP(2)
+#define STV090x_OFFST_Px_QAVERAGE_ADJ_FIELD	0
+#define STV090x_WIDTH_Px_QAVERAGE_ADJ_FIELD	8
+
+#define STV090x_Px_POWERI(__x)			(0xF40A - (__x - 1) * 0x200)
+#define STV090x_P1_POWERI			STV090x_Px_POWERI(1)
+#define STV090x_P2_POWERI			STV090x_Px_POWERI(2)
+#define STV090x_OFFST_Px_POWER_I_FIELD		0
+#define STV090x_WIDTH_Px_POWER_I_FIELD		8
+
+#define STV090x_Px_POWERQ(__x)			(0xF40B - (__x - 1) * 0x200)
+#define STV090x_P1_POWERQ			STV090x_Px_POWERQ(1)
+#define STV090x_P2_POWERQ			STV090x_Px_POWERQ(2)
+#define STV090x_OFFST_Px_POWER_Q_FIELD		0
+#define STV090x_WIDTH_Px_POWER_Q_FIELD		8
+
+#define STV090x_Px_AGC1AMM(__x)			(0xF40C - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1AMM			STV090x_Px_AGC1AMM(1)
+#define STV090x_P2_AGC1AMM			STV090x_Px_AGC1AMM(2)
+#define STV090x_OFFST_Px_AMM_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_AMM_VALUE_FIELD	8
+
+#define STV090x_Px_AGC1QUAD(__x)		(0xF40D - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1QUAD			STV090x_Px_AGC1QUAD(1)
+#define STV090x_P2_AGC1QUAD			STV090x_Px_AGC1QUAD(2)
+#define STV090x_OFFST_Px_QUAD_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_QUAD_VALUE_FIELD	8
+
+#define STV090x_Px_AGCIQINy(__x, __y)		(0xF40F - (__x-1) * 0x200 - __y * 0x1)
+#define STV090x_P1_AGCIQIN0			STV090x_Px_AGCIQINy(1, 0)
+#define STV090x_P1_AGCIQIN1			STV090x_Px_AGCIQINy(1, 1)
+#define STV090x_P2_AGCIQIN0			STV090x_Px_AGCIQINy(2, 0)
+#define STV090x_P2_AGCIQIN1			STV090x_Px_AGCIQINy(2, 1)
+#define STV090x_OFFST_Px_AGCIQ_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_AGCIQ_VALUE_FIELD	8
+
+#define STV090x_Px_DEMOD(__x)			(0xF410 - (__x - 1) * 0x200)
+#define STV090x_P1_DEMOD			STV090x_Px_DEMOD(1)
+#define STV090x_P2_DEMOD			STV090x_Px_DEMOD(2)
+#define STV090x_OFFST_Px_MANUAL_S2ROLLOFF_FIELD	7
+#define STV090x_WIDTH_Px_MANUAL_S2ROLLOFF_FIELD	1
+#define STV090x_OFFST_Px_DEMOD_STOP_FIELD	6
+#define STV090x_WIDTH_Px_DEMOD_STOP_FIELD	1
+#define STV090x_OFFST_Px_SPECINV_CONTROL_FIELD	4
+#define STV090x_WIDTH_Px_SPECINV_CONTROL_FIELD	2
+#define STV090x_OFFST_Px_FORCE_ENASAMP_FIELD	3
+#define STV090x_WIDTH_Px_FORCE_ENASAMP_FIELD	1
+#define STV090x_OFFST_Px_MANUAL_SXROLLOFF_FIELD	2
+#define STV090x_WIDTH_Px_MANUAL_SXROLLOFF_FIELD	1
+#define STV090x_OFFST_Px_ROLLOFF_CONTROL_FIELD	0
+#define STV090x_WIDTH_Px_ROLLOFF_CONTROL_FIELD	2
+
+#define STV090x_Px_DMDMODCOD(__x)		(0xF411 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDMODCOD			STV090x_Px_DMDMODCOD(1)
+#define STV090x_P2_DMDMODCOD			STV090x_Px_DMDMODCOD(2)
+#define STV090x_OFFST_Px_MANUAL_MODCOD_FIELD	7
+#define STV090x_WIDTH_Px_MANUAL_MODCOD_FIELD	1
+#define STV090x_OFFST_Px_DEMOD_MODCOD_FIELD	2
+#define STV090x_WIDTH_Px_DEMOD_MODCOD_FIELD	5
+#define STV090x_OFFST_Px_DEMOD_TYPE_FIELD	0
+#define STV090x_WIDTH_Px_DEMOD_TYPE_FIELD	2
+
+#define STV090x_Px_DSTATUS(__x)			(0xF412 - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS			STV090x_Px_DSTATUS(1)
+#define STV090x_P2_DSTATUS			STV090x_Px_DSTATUS(2)
+#define STV090x_OFFST_Px_CAR_LOCK_FIELD		7
+#define STV090x_WIDTH_Px_CAR_LOCK_FIELD		1
+#define STV090x_OFFST_Px_TMGLOCK_QUALITY_FIELD	5
+#define STV090x_WIDTH_Px_TMGLOCK_QUALITY_FIELD	2
+#define STV090x_OFFST_Px_LOCK_DEFINITIF_FIELD	3
+#define STV090x_WIDTH_Px_LOCK_DEFINITIF_FIELD	1
+
+#define STV090x_Px_DSTATUS2(__x)		(0xF413 - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS2			STV090x_Px_DSTATUS2(1)
+#define STV090x_P2_DSTATUS2			STV090x_Px_DSTATUS2(2)
+#define STV090x_OFFST_Px_DEMOD_DELOCK_FIELD	7
+#define STV090x_WIDTH_Px_DEMOD_DELOCK_FIELD	1
+#define STV090x_OFFST_Px_AGC1_NOSIGNALACK_FIELD	3
+#define STV090x_WIDTH_Px_AGC1_NOSIGNALACK_FIELD	1
+#define STV090x_OFFST_Px_AGC2_OVERFLOW_FIELD	2
+#define STV090x_WIDTH_Px_AGC2_OVERFLOW_FIELD	1
+#define STV090x_OFFST_Px_CFR_OVERFLOW_FIELD	1
+#define STV090x_WIDTH_Px_CFR_OVERFLOW_FIELD	1
+#define STV090x_OFFST_Px_GAMMA_OVERUNDER_FIELD	0
+#define STV090x_WIDTH_Px_GAMMA_OVERUNDER_FIELD	1
+
+#define STV090x_Px_DMDCFGMD(__x)		(0xF414 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFGMD			STV090x_Px_DMDCFGMD(1)
+#define STV090x_P2_DMDCFGMD			STV090x_Px_DMDCFGMD(2)
+#define STV090x_OFFST_Px_DVBS2_ENABLE_FIELD	7
+#define STV090x_WIDTH_Px_DVBS2_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_DVBS1_ENABLE_FIELD	6
+#define STV090x_WIDTH_Px_DVBS1_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_CFR_AUTOSCAN_FIELD	5 /* check */
+#define STV090x_WIDTH_Px_CFR_AUTOSCAN_FIELD	1
+#define STV090x_OFFST_Px_SCAN_ENABLE_FIELD	4 /* check */
+#define STV090x_WIDTH_Px_SCAN_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_TUN_AUTOSCAN_FIELD	3
+#define STV090x_WIDTH_Px_TUN_AUTOSCAN_FIELD	1
+#define STV090x_OFFST_Px_NOFORCE_RELOCK_FIELD	2
+#define STV090x_WIDTH_Px_NOFORCE_RELOCK_FIELD	1
+#define STV090x_OFFST_Px_TUN_RNG_FIELD		0
+#define STV090x_WIDTH_Px_TUN_RNG_FIELD		2
+
+#define STV090x_Px_DMDCFG2(__x)			(0xF415 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG2			STV090x_Px_DMDCFG2(1)
+#define STV090x_P2_DMDCFG2			STV090x_Px_DMDCFG2(2)
+#define STV090x_OFFST_Px_S1S2_SEQUENTIAL_FIELD	6
+#define STV090x_WIDTH_Px_S1S2_SEQUENTIAL_FIELD	1
+
+#define STV090x_Px_DMDISTATE(__x)		(0xF416 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDISTATE			STV090x_Px_DMDISTATE(1)
+#define STV090x_P2_DMDISTATE			STV090x_Px_DMDISTATE(2)
+#define STV090x_OFFST_Px_I2C_DEMOD_MODE_FIELD	0
+#define STV090x_WIDTH_Px_I2C_DEMOD_MODE_FIELD	5
+
+#define STV090x_Px_DMDTOM(__x)			(0xF417 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_DMDTOM			STV090x_Px_DMDTOM(1)
+#define STV090x_P2_DMDTOM			STV090x_Px_DMDTOM(2)
+
+#define STV090x_Px_DMDSTATE(__x)		(0xF41B - (__x - 1) * 0x200)
+#define STV090x_P1_DMDSTATE			STV090x_Px_DMDSTATE(1)
+#define STV090x_P2_DMDSTATE			STV090x_Px_DMDSTATE(2)
+#define STV090x_OFFST_Px_HEADER_MODE_FIELD	5
+#define STV090x_WIDTH_Px_HEADER_MODE_FIELD	2
+
+#define STV090x_Px_DMDFLYW(__x)			(0xF41C - (__x - 1) * 0x200)
+#define STV090x_P1_DMDFLYW			STV090x_Px_DMDFLYW(1)
+#define STV090x_P2_DMDFLYW			STV090x_Px_DMDFLYW(2)
+#define STV090x_OFFST_Px_I2C_IRQVAL_FIELD	4
+#define STV090x_WIDTH_Px_I2C_IRQVAL_FIELD	4
+#define STV090x_OFFST_Px_FLYWHEEL_CPT_FIELD	0 /* check */
+#define STV090x_WIDTH_Px_FLYWHEEL_CPT_FIELD	4
+
+#define STV090x_Px_DSTATUS3(__x)		(0xF41D - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS3			STV090x_Px_DSTATUS3(1)
+#define STV090x_P2_DSTATUS3			STV090x_Px_DSTATUS3(2)
+#define STV090x_OFFST_Px_DEMOD_CFGMODE_FIELD	5
+#define STV090x_WIDTH_Px_DEMOD_CFGMODE_FIELD	2
+
+#define STV090x_Px_DMDCFG3(__x)			(0xF41E - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG3			STV090x_Px_DMDCFG3(1)
+#define STV090x_P2_DMDCFG3			STV090x_Px_DMDCFG3(2)
+#define STV090x_OFFST_Px_NOSTOP_FIFOFULL_FIELD	3
+#define STV090x_WIDTH_Px_NOSTOP_FIFOFULL_FIELD	1
+
+#define STV090x_Px_DMDCFG4(__x)			(0xf41f - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG4			STV090x_Px_DMDCFG4(1)
+#define STV090x_P2_DMDCFG4			STV090x_Px_DMDCFG4(2)
+
+#define STV090x_Px_CORRELMANT(__x)		(0xF420 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELMANT			STV090x_Px_CORRELMANT(1)
+#define STV090x_P2_CORRELMANT			STV090x_Px_CORRELMANT(2)
+#define STV090x_OFFST_Px_CORREL_MANT_FIELD	0
+#define STV090x_WIDTH_Px_CORREL_MANT_FIELD	8
+
+#define STV090x_Px_CORRELABS(__x)		(0xF421 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELABS			STV090x_Px_CORRELABS(1)
+#define STV090x_P2_CORRELABS			STV090x_Px_CORRELABS(2)
+#define STV090x_OFFST_Px_CORREL_ABS_FIELD	0
+#define STV090x_WIDTH_Px_CORREL_ABS_FIELD	8
+
+#define STV090x_Px_CORRELEXP(__x)		(0xF422 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELEXP			STV090x_Px_CORRELEXP(1)
+#define STV090x_P2_CORRELEXP			STV090x_Px_CORRELEXP(2)
+#define STV090x_OFFST_Px_CORREL_ABSEXP_FIELD	4
+#define STV090x_WIDTH_Px_CORREL_ABSEXP_FIELD	4
+#define STV090x_OFFST_Px_CORREL_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CORREL_EXP_FIELD	4
+
+#define STV090x_Px_PLHMODCOD(__x)		(0xF424 - (__x - 1) * 0x200)
+#define STV090x_P1_PLHMODCOD			STV090x_Px_PLHMODCOD(1)
+#define STV090x_P2_PLHMODCOD			STV090x_Px_PLHMODCOD(2)
+#define STV090x_OFFST_Px_SPECINV_DEMOD_FIELD	7
+#define STV090x_WIDTH_Px_SPECINV_DEMOD_FIELD	1
+#define STV090x_OFFST_Px_PLH_MODCOD_FIELD	2
+#define STV090x_WIDTH_Px_PLH_MODCOD_FIELD	5
+#define STV090x_OFFST_Px_PLH_TYPE_FIELD		0
+#define STV090x_WIDTH_Px_PLH_TYPE_FIELD		2
+
+#define STV090x_Px_AGCK32(__x)			(0xf42b - (__x - 1) * 0x200)
+#define STV090x_P1_AGCK32			STV090x_Px_AGCK32(1)
+#define STV090x_P2_AGCK32			STV090x_Px_AGCK32(2)
+
+#define STV090x_Px_AGC2O(__x)			(0xF42C - (__x - 1) * 0x200)
+#define STV090x_P1_AGC2O			STV090x_Px_AGC2O(1)
+#define STV090x_P2_AGC2O			STV090x_Px_AGC2O(2)
+
+#define STV090x_Px_AGC2REF(__x)			(0xF42D - (__x - 1) * 0x200)
+#define STV090x_P1_AGC2REF			STV090x_Px_AGC2REF(1)
+#define STV090x_P2_AGC2REF			STV090x_Px_AGC2REF(2)
+#define STV090x_OFFST_Px_AGC2_REF_FIELD		0
+#define STV090x_WIDTH_Px_AGC2_REF_FIELD		8
+
+#define STV090x_Px_AGC1ADJ(__x)			(0xF42E - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1ADJ			STV090x_Px_AGC1ADJ(1)
+#define STV090x_P2_AGC1ADJ			STV090x_Px_AGC1ADJ(2)
+#define STV090x_OFFST_Px_AGC1_ADJUSTED_FIELD	0
+#define STV090x_WIDTH_Px_AGC1_ADJUSTED_FIELD	7
+
+#define STV090x_Px_AGC2Iy(__x, __y)		(0xF437 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_AGC2I0			STV090x_Px_AGC2Iy(1, 0)
+#define STV090x_P1_AGC2I1			STV090x_Px_AGC2Iy(1, 1)
+#define STV090x_P2_AGC2I0			STV090x_Px_AGC2Iy(2, 0)
+#define STV090x_P2_AGC2I1			STV090x_Px_AGC2Iy(2, 1)
+#define STV090x_OFFST_Px_AGC2_INTEGRATOR_FIELD	0
+#define STV090x_WIDTH_Px_AGC2_INTEGRATOR_FIELD	8
+
+#define STV090x_Px_CARCFG(__x)			(0xF438 - (__x - 1) * 0x200)
+#define STV090x_P1_CARCFG			STV090x_Px_CARCFG(1)
+#define STV090x_P2_CARCFG			STV090x_Px_CARCFG(2)
+#define STV090x_OFFST_Px_EN_CAR2CENTER_FIELD	5
+#define STV090x_WIDTH_Px_EN_CAR2CENTER_FIELD	1
+#define STV090x_OFFST_Px_ROTATON_FIELD		2
+#define STV090x_WIDTH_Px_ROTATON_FIELD		1
+#define STV090x_OFFST_Px_PH_DET_ALGO_FIELD	0
+#define STV090x_WIDTH_Px_PH_DET_ALGO_FIELD	2
+
+#define STV090x_Px_ACLC(__x)			(0xF439 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC				STV090x_Px_ACLC(1)
+#define STV090x_P2_ACLC				STV090x_Px_ACLC(2)
+#define STV090x_OFFST_Px_CAR_ALPHA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR_ALPHA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR_ALPHA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR_ALPHA_EXP_FIELD	4
+
+#define STV090x_Px_BCLC(__x)			(0xF43A - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC				STV090x_Px_BCLC(1)
+#define STV090x_P2_BCLC				STV090x_Px_BCLC(2)
+#define STV090x_OFFST_Px_CAR_BETA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR_BETA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR_BETA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR_BETA_EXP_FIELD	4
+
+#define STV090x_Px_CARFREQ(__x)			(0xF43D - (__x - 1) * 0x200)
+#define STV090x_P1_CARFREQ			STV090x_Px_CARFREQ(1)
+#define STV090x_P2_CARFREQ			STV090x_Px_CARFREQ(2)
+#define STV090x_OFFST_Px_KC_COARSE_EXP_FIELD	4
+#define STV090x_WIDTH_Px_KC_COARSE_EXP_FIELD	4
+#define STV090x_OFFST_Px_BETA_FREQ_FIELD	0
+#define STV090x_WIDTH_Px_BETA_FREQ_FIELD	4
+
+#define STV090x_Px_CARHDR(__x)			(0xF43E - (__x - 1) * 0x200)
+#define STV090x_P1_CARHDR			STV090x_Px_CARHDR(1)
+#define STV090x_P2_CARHDR			STV090x_Px_CARHDR(2)
+#define STV090x_OFFST_Px_FREQ_HDR_FIELD		0
+#define STV090x_WIDTH_Px_FREQ_HDR_FIELD		8
+
+#define STV090x_Px_LDT(__x)			(0xF43F - (__x - 1) * 0x200)
+#define STV090x_P1_LDT				STV090x_Px_LDT(1)
+#define STV090x_P2_LDT				STV090x_Px_LDT(2)
+#define STV090x_OFFST_Px_CARLOCK_THRES_FIELD	0
+#define STV090x_WIDTH_Px_CARLOCK_THRES_FIELD	8
+
+#define STV090x_Px_LDT2(__x)			(0xF440 - (__x - 1) * 0x200)
+#define STV090x_P1_LDT2				STV090x_Px_LDT2(1)
+#define STV090x_P2_LDT2				STV090x_Px_LDT2(2)
+#define STV090x_OFFST_Px_CARLOCK_THRES2_FIELD	0
+#define STV090x_WIDTH_Px_CARLOCK_THRES2_FIELD	8
+
+#define STV090x_Px_CFRICFG(__x)			(0xF441 - (__x - 1) * 0x200)
+#define STV090x_P1_CFRICFG			STV090x_Px_CFRICFG(1)
+#define STV090x_P2_CFRICFG			STV090x_Px_CFRICFG(2)
+#define STV090x_OFFST_Px_NEG_CFRSTEP_FIELD	0
+#define STV090x_WIDTH_Px_NEG_CFRSTEP_FIELD	1
+
+#define STV090x_Pn_CFRUPy(__x, __y)		(0xF443 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRUP0			STV090x_Pn_CFRUPy(1, 0)
+#define STV090x_P1_CFRUP1			STV090x_Pn_CFRUPy(1, 1)
+#define STV090x_P2_CFRUP0			STV090x_Pn_CFRUPy(2, 0)
+#define STV090x_P2_CFRUP1			STV090x_Pn_CFRUPy(2, 1)
+#define STV090x_OFFST_Px_CFR_UP_FIELD		0
+#define STV090x_WIDTH_Px_CFR_UP_FIELD		8
+
+#define STV090x_Pn_CFRLOWy(__x, __y)		(0xF447 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRLOW0			STV090x_Pn_CFRLOWy(1, 0)
+#define STV090x_P1_CFRLOW1			STV090x_Pn_CFRLOWy(1, 1)
+#define STV090x_P2_CFRLOW0			STV090x_Pn_CFRLOWy(2, 0)
+#define STV090x_P2_CFRLOW1			STV090x_Pn_CFRLOWy(2, 1)
+#define STV090x_OFFST_Px_CFR_LOW_FIELD		0
+#define STV090x_WIDTH_Px_CFR_LOW_FIELD		8
+
+#define STV090x_Pn_CFRINITy(__x, __y)		(0xF449 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRINIT0			STV090x_Pn_CFRINITy(1, 0)
+#define STV090x_P1_CFRINIT1			STV090x_Pn_CFRINITy(1, 1)
+#define STV090x_P2_CFRINIT0			STV090x_Pn_CFRINITy(2, 0)
+#define STV090x_P2_CFRINIT1			STV090x_Pn_CFRINITy(2, 1)
+#define STV090x_OFFST_Px_CFR_INIT_FIELD		0
+#define STV090x_WIDTH_Px_CFR_INIT_FIELD		8
+
+#define STV090x_Px_CFRINC1(__x)			(0xF44A - (__x - 1) * 0x200)
+#define STV090x_P1_CFRINC1			STV090x_Px_CFRINC1(1)
+#define STV090x_P2_CFRINC1			STV090x_Px_CFRINC1(2)
+#define STV090x_OFFST_Px_CFR_INC1_FIELD		0
+#define STV090x_WIDTH_Px_CFR_INC1_FIELD		7
+
+#define STV090x_Px_CFRINC0(__x)			(0xF44B - (__x - 1) * 0x200)
+#define STV090x_P1_CFRINC0			STV090x_Px_CFRINC0(1)
+#define STV090x_P2_CFRINC0			STV090x_Px_CFRINC0(2)
+#define STV090x_OFFST_Px_CFR_INC0_FIELD		4
+#define STV090x_WIDTH_Px_CFR_INC0_FIELD		4
+
+#define STV090x_Pn_CFRy(__x, __y)		(0xF44E - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFR0				STV090x_Pn_CFRy(1, 0)
+#define STV090x_P1_CFR1				STV090x_Pn_CFRy(1, 1)
+#define STV090x_P1_CFR2				STV090x_Pn_CFRy(1, 2)
+#define STV090x_P2_CFR0				STV090x_Pn_CFRy(2, 0)
+#define STV090x_P2_CFR1				STV090x_Pn_CFRy(2, 1)
+#define STV090x_P2_CFR2				STV090x_Pn_CFRy(2, 2)
+#define STV090x_OFFST_Px_CAR_FREQ_FIELD		0
+#define STV090x_WIDTH_Px_CAR_FREQ_FIELD		8
+
+#define STV090x_Px_LDI(__x)			(0xF44F - (__x - 1) * 0x200)
+#define STV090x_P1_LDI				STV090x_Px_LDI(1)
+#define STV090x_P2_LDI				STV090x_Px_LDI(2)
+#define STV090x_OFFST_Px_LOCK_DET_INTEGR_FIELD	0
+#define STV090x_WIDTH_Px_LOCK_DET_INTEGR_FIELD	8
+
+#define STV090x_Px_TMGCFG(__x)			(0xF450 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGCFG			STV090x_Px_TMGCFG(1)
+#define STV090x_P2_TMGCFG			STV090x_Px_TMGCFG(2)
+#define STV090x_OFFST_Px_TMGLOCK_BETA_FIELD	6
+#define STV090x_WIDTH_Px_TMGLOCK_BETA_FIELD	2
+#define STV090x_OFFST_Px_DO_TIMING_FIELD	4
+#define STV090x_WIDTH_Px_DO_TIMING_FIELD	1
+#define STV090x_OFFST_Px_TMG_MINFREQ_FIELD	0
+#define STV090x_WIDTH_Px_TMG_MINFREQ_FIELD	2
+
+#define STV090x_Px_RTC(__x)			(0xF451 - (__x - 1) * 0x200)
+#define STV090x_P1_RTC				STV090x_Px_RTC(1)
+#define STV090x_P2_RTC				STV090x_Px_RTC(2)
+#define STV090x_OFFST_Px_TMGALPHA_EXP_FIELD	4
+#define STV090x_WIDTH_Px_TMGALPHA_EXP_FIELD	4
+#define STV090x_OFFST_Px_TMGBETA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_TMGBETA_EXP_FIELD	4
+
+#define STV090x_Px_RTCS2(__x)			(0xF452 - (__x - 1) * 0x200)
+#define STV090x_P1_RTCS2			STV090x_Px_RTCS2(1)
+#define STV090x_P2_RTCS2			STV090x_Px_RTCS2(2)
+#define STV090x_OFFST_Px_TMGALPHAS2_EXP_FIELD	4
+#define STV090x_WIDTH_Px_TMGALPHAS2_EXP_FIELD	4
+#define STV090x_OFFST_Px_TMGBETAS2_EXP_FIELD	0
+#define STV090x_WIDTH_Px_TMGBETAS2_EXP_FIELD	4
+
+#define STV090x_Px_TMGTHRISE(__x)		(0xF453 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGTHRISE			STV090x_Px_TMGTHRISE(1)
+#define STV090x_P2_TMGTHRISE			STV090x_Px_TMGTHRISE(2)
+#define STV090x_OFFST_Px_TMGLOCK_THRISE_FIELD	0
+#define STV090x_WIDTH_Px_TMGLOCK_THRISE_FIELD	8
+
+#define STV090x_Px_TMGTHFALL(__x)		(0xF454 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGTHFALL			STV090x_Px_TMGTHFALL(1)
+#define STV090x_P2_TMGTHFALL			STV090x_Px_TMGTHFALL(2)
+#define STV090x_OFFST_Px_TMGLOCK_THFALL_FIELD	0
+#define STV090x_WIDTH_Px_TMGLOCK_THFALL_FIELD	8
+
+#define STV090x_Px_SFRUPRATIO(__x)		(0xF455 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUPRATIO			STV090x_Px_SFRUPRATIO(1)
+#define STV090x_P2_SFRUPRATIO			STV090x_Px_SFRUPRATIO(2)
+#define STV090x_OFFST_Px_SFR_UPRATIO_FIELD	0
+#define STV090x_WIDTH_Px_SFR_UPRATIO_FIELD	8
+
+#define STV090x_Px_SFRLOWRATIO(__x)		(0xF456 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOWRATIO			STV090x_Px_SFRLOWRATIO(1)
+#define STV090x_P2_SFRLOWRATIO			STV090x_Px_SFRLOWRATIO(2)
+#define STV090x_OFFST_Px_SFR_LOWRATIO_FIELD	0
+#define STV090x_WIDTH_Px_SFR_LOWRATIO_FIELD	8
+
+#define STV090x_Px_KREFTMG(__x)			(0xF458 - (__x - 1) * 0x200)
+#define STV090x_P1_KREFTMG			STV090x_Px_KREFTMG(1)
+#define STV090x_P2_KREFTMG			STV090x_Px_KREFTMG(2)
+#define STV090x_OFFST_Px_KREF_TMG_FIELD		0
+#define STV090x_WIDTH_Px_KREF_TMG_FIELD		8
+
+#define STV090x_Px_SFRSTEP(__x)			(0xF459 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRSTEP			STV090x_Px_SFRSTEP(1)
+#define STV090x_P2_SFRSTEP			STV090x_Px_SFRSTEP(2)
+#define STV090x_OFFST_Px_SFR_SCANSTEP_FIELD	4
+#define STV090x_WIDTH_Px_SFR_SCANSTEP_FIELD	4
+#define STV090x_OFFST_Px_SFR_CENTERSTEP_FIELD	0
+#define STV090x_WIDTH_Px_SFR_CENTERSTEP_FIELD	4
+
+#define STV090x_Px_TMGCFG2(__x)			(0xF45A - (__x - 1) * 0x200)
+#define STV090x_P1_TMGCFG2			STV090x_Px_TMGCFG2(1)
+#define STV090x_P2_TMGCFG2			STV090x_Px_TMGCFG2(2)
+#define STV090x_OFFST_Px_SFRRATIO_FINE_FIELD	0
+#define STV090x_WIDTH_Px_SFRRATIO_FINE_FIELD	1
+
+#define STV090x_Px_SFRINIT1(__x)		(0xF45E - (__x - 1) * 0x200)
+#define STV090x_P1_SFRINIT1			STV090x_Px_SFRINIT1(1)
+#define STV090x_P2_SFRINIT1			STV090x_Px_SFRINIT1(2)
+#define STV090x_OFFST_Px_SFR_INIT_FIELD		0
+#define STV090x_WIDTH_Px_SFR_INIT_FIELD		8
+
+#define STV090x_Px_SFRINIT0(__x)		(0xF45F - (__x - 1) * 0x200)
+#define STV090x_P1_SFRINIT0			STV090x_Px_SFRINIT0(1)
+#define STV090x_P2_SFRINIT0			STV090x_Px_SFRINIT0(2)
+#define STV090x_OFFST_Px_SFR_INIT_FIELD		0
+#define STV090x_WIDTH_Px_SFR_INIT_FIELD		8
+
+#define STV090x_Px_SFRUP1(__x)			(0xF460 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUP1			STV090x_Px_SFRUP1(1)
+#define STV090x_P2_SFRUP1			STV090x_Px_SFRUP1(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_UP1_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_UP1_FIELD	7
+
+#define STV090x_Px_SFRUP0(__x)			(0xF461 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUP0			STV090x_Px_SFRUP0(1)
+#define STV090x_P2_SFRUP0			STV090x_Px_SFRUP0(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_UP0_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_UP0_FIELD	8
+
+#define STV090x_Px_SFRLOW1(__x)			(0xF462 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOW1			STV090x_Px_SFRLOW1(1)
+#define STV090x_P2_SFRLOW1			STV090x_Px_SFRLOW1(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_LOW1_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_LOW1_FIELD	7
+
+#define STV090x_Px_SFRLOW0(__x)			(0xF463 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOW0			STV090x_Px_SFRLOW0(1)
+#define STV090x_P2_SFRLOW0			STV090x_Px_SFRLOW0(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_LOW0_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_LOW0_FIELD	8
+
+#define STV090x_Px_SFRy(__x, __y)		(0xF464 - (__x-1) * 0x200 + (3 - __y))
+#define STV090x_P1_SFR0				STV090x_Px_SFRy(1, 0)
+#define STV090x_P1_SFR1				STV090x_Px_SFRy(1, 1)
+#define STV090x_P1_SFR2				STV090x_Px_SFRy(1, 2)
+#define STV090x_P1_SFR3				STV090x_Px_SFRy(1, 3)
+#define STV090x_P2_SFR0				STV090x_Px_SFRy(2, 0)
+#define STV090x_P2_SFR1				STV090x_Px_SFRy(2, 1)
+#define STV090x_P2_SFR2				STV090x_Px_SFRy(2, 2)
+#define STV090x_P2_SFR3				STV090x_Px_SFRy(2, 3)
+#define STV090x_OFFST_Px_SYMB_FREQ_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_FIELD	32
+
+#define STV090x_Px_TMGREG2(__x)			(0xF468 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG2			STV090x_Px_TMGREG2(1)
+#define STV090x_P2_TMGREG2			STV090x_Px_TMGREG2(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD		0
+#define STV090x_WIDTH_Px_TMGREG_FIELD		8
+
+#define STV090x_Px_TMGREG1(__x)			(0xF469 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG1			STV090x_Px_TMGREG1(1)
+#define STV090x_P2_TMGREG1				STV090x_Px_TMGREG1(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD		0
+#define STV090x_WIDTH_Px_TMGREG_FIELD		8
+
+#define STV090x_Px_TMGREG0(__x)			(0xF46A - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG0			STV090x_Px_TMGREG0(1)
+#define STV090x_P2_TMGREG0			STV090x_Px_TMGREG0(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD		0
+#define STV090x_WIDTH_Px_TMGREG_FIELD		8
+
+#define STV090x_Px_TMGLOCKy(__x, __y)		(0xF46C - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_TMGLOCK0			STV090x_Px_TMGLOCKy(1, 0)
+#define STV090x_P1_TMGLOCK1			STV090x_Px_TMGLOCKy(1, 1)
+#define STV090x_P2_TMGLOCK0			STV090x_Px_TMGLOCKy(2, 0)
+#define STV090x_P2_TMGLOCK1			STV090x_Px_TMGLOCKy(2, 1)
+#define STV090x_OFFST_Px_TMGLOCK_LEVEL_FIELD	0
+#define STV090x_WIDTH_Px_TMGLOCK_LEVEL_FIELD	8
+
+#define STV090x_Px_TMGOBS(__x)			(0xF46D - (__x - 1) * 0x200)
+#define STV090x_P1_TMGOBS			STV090x_Px_TMGOBS(1)
+#define STV090x_P2_TMGOBS			STV090x_Px_TMGOBS(2)
+#define STV090x_OFFST_Px_ROLLOFF_STATUS_FIELD	6
+#define STV090x_WIDTH_Px_ROLLOFF_STATUS_FIELD	2
+
+#define STV090x_Px_EQUALCFG(__x)		(0xF46F - (__x - 1) * 0x200)
+#define STV090x_P1_EQUALCFG			STV090x_Px_EQUALCFG(1)
+#define STV090x_P2_EQUALCFG			STV090x_Px_EQUALCFG(2)
+#define STV090x_OFFST_Px_EQUAL_ON_FIELD		6
+#define STV090x_WIDTH_Px_EQUAL_ON_FIELD		1
+#define STV090x_OFFST_Px_MU_EQUALDFE_FIELD	0
+#define STV090x_WIDTH_Px_MU_EQUALDFE_FIELD	3
+
+#define STV090x_Px_EQUAIy(__x, __y)		(0xf470 - (__x - 1) * 0x200 + (__y - 1))
+#define STV090x_P1_EQUAI1			STV090x_Px_EQUAIy(1, 1)
+#define STV090x_P1_EQUAI2			STV090x_Px_EQUAIy(1, 2)
+#define STV090x_P1_EQUAI3			STV090x_Px_EQUAIy(1, 3)
+#define STV090x_P1_EQUAI4			STV090x_Px_EQUAIy(1, 4)
+#define STV090x_P1_EQUAI5			STV090x_Px_EQUAIy(1, 5)
+#define STV090x_P1_EQUAI6			STV090x_Px_EQUAIy(1, 6)
+#define STV090x_P1_EQUAI7			STV090x_Px_EQUAIy(1, 7)
+#define STV090x_P1_EQUAI8			STV090x_Px_EQUAIy(1, 8)
+
+#define STV090x_P2_EQUAI1			STV090x_Px_EQUAIy(2, 1)
+#define STV090x_P2_EQUAI2			STV090x_Px_EQUAIy(2, 2)
+#define STV090x_P2_EQUAI3			STV090x_Px_EQUAIy(2, 3)
+#define STV090x_P2_EQUAI4			STV090x_Px_EQUAIy(2, 4)
+#define STV090x_P2_EQUAI5			STV090x_Px_EQUAIy(2, 5)
+#define STV090x_P2_EQUAI6			STV090x_Px_EQUAIy(2, 6)
+#define STV090x_P2_EQUAI7			STV090x_Px_EQUAIy(2, 7)
+#define STV090x_P2_EQUAI8			STV090x_Px_EQUAIy(2, 8)
+#define STV090x_OFFST_Px_EQUA_ACCIy_FIELD	0
+#define STV090x_WIDTH_Px_EQUA_ACCIy_FIELD	8
+
+#define STV090x_Px_EQUAQy(__x, __y)		(0xf471 - (__x - 1) * 0x200 + (__y - 1))
+#define STV090x_P1_EQUAQ1			STV090x_Px_EQUAQy(1, 1)
+#define STV090x_P1_EQUAQ2			STV090x_Px_EQUAQy(1, 2)
+#define STV090x_P1_EQUAQ3			STV090x_Px_EQUAQy(1, 3)
+#define STV090x_P1_EQUAQ4			STV090x_Px_EQUAQy(1, 4)
+#define STV090x_P1_EQUAQ5			STV090x_Px_EQUAQy(1, 5)
+#define STV090x_P1_EQUAQ6			STV090x_Px_EQUAQy(1, 6)
+#define STV090x_P1_EQUAQ7			STV090x_Px_EQUAQy(1, 7)
+#define STV090x_P1_EQUAQ8			STV090x_Px_EQUAQy(1, 8)
+
+#define STV090x_P2_EQUAQ1			STV090x_Px_EQUAQy(2, 1)
+#define STV090x_P2_EQUAQ2			STV090x_Px_EQUAQy(2, 2)
+#define STV090x_P2_EQUAQ3			STV090x_Px_EQUAQy(2, 3)
+#define STV090x_P2_EQUAQ4			STV090x_Px_EQUAQy(2, 4)
+#define STV090x_P2_EQUAQ5			STV090x_Px_EQUAQy(2, 5)
+#define STV090x_P2_EQUAQ6			STV090x_Px_EQUAQy(2, 6)
+#define STV090x_P2_EQUAQ7			STV090x_Px_EQUAQy(2, 7)
+#define STV090x_P2_EQUAQ8			STV090x_Px_EQUAQy(2, 8)
+#define STV090x_OFFST_Px_EQUA_ACCQy_FIELD	0
+#define STV090x_WIDTH_Px_EQUA_ACCQy_FIELD	8
+
+#define STV090x_Px_NNOSDATATy(__x, __y)		(0xf481 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSDATAT0			STV090x_Px_NNOSDATATy(1, 0)
+#define STV090x_P1_NNOSDATAT1			STV090x_Px_NNOSDATATy(1, 1)
+#define STV090x_P2_NNOSDATAT0			STV090x_Px_NNOSDATATy(2, 0)
+#define STV090x_P2_NNOSDATAT1			STV090x_Px_NNOSDATATy(2, 1)
+#define STV090x_OFFST_Px_NOSDATAT_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATAT_NORMED_FIELD	8
+
+#define STV090x_Px_NNOSDATAy(__x, __y)		(0xf483 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSDATA0			STV090x_Px_NNOSDATAy(1, 0)
+#define STV090x_P1_NNOSDATA1			STV090x_Px_NNOSDATAy(1, 1)
+#define STV090x_P2_NNOSDATA0			STV090x_Px_NNOSDATAy(2, 0)
+#define STV090x_P2_NNOSDATA1			STV090x_Px_NNOSDATAy(2, 1)
+#define STV090x_OFFST_Px_NOSDATA_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATA_NORMED_FIELD	8
+
+#define STV090x_Px_NNOSPLHTy(__x, __y)		(0xf485 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSPLHT0			STV090x_Px_NNOSPLHTy(1, 0)
+#define STV090x_P1_NNOSPLHT1			STV090x_Px_NNOSPLHTy(1, 1)
+#define STV090x_P2_NNOSPLHT0			STV090x_Px_NNOSPLHTy(2, 0)
+#define STV090x_P2_NNOSPLHT1			STV090x_Px_NNOSPLHTy(2, 1)
+#define STV090x_OFFST_Px_NOSPLHT_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLHT_NORMED_FIELD	8
+
+#define STV090x_Px_NNOSPLHy(__x, __y)		(0xf487 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSPLH0			STV090x_Px_NNOSPLHy(1, 0)
+#define STV090x_P1_NNOSPLH1			STV090x_Px_NNOSPLHy(1, 1)
+#define STV090x_P2_NNOSPLH0			STV090x_Px_NNOSPLHy(2, 0)
+#define STV090x_P2_NNOSPLH1			STV090x_Px_NNOSPLHy(2, 1)
+#define STV090x_OFFST_Px_NOSPLH_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLH_NORMED_FIELD	8
+
+#define STV090x_Px_NOSDATATy(__x, __y)			(0xf489 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSDATAT0				STV090x_Px_NOSDATATy(1, 0)
+#define STV090x_P1_NOSDATAT1				STV090x_Px_NOSDATATy(1, 1)
+#define STV090x_P2_NOSDATAT0				STV090x_Px_NOSDATATy(2, 0)
+#define STV090x_P2_NOSDATAT1				STV090x_Px_NOSDATATy(2, 1)
+#define STV090x_OFFST_Px_NOSDATAT_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATAT_UNNORMED_FIELD	8
+
+#define STV090x_Px_NOSDATAy(__x, __y)		(0xf48b - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSDATA0			STV090x_Px_NOSDATAy(1, 0)
+#define STV090x_P1_NOSDATA1			STV090x_Px_NOSDATAy(1, 1)
+#define STV090x_P2_NOSDATA0			STV090x_Px_NOSDATAy(2, 0)
+#define STV090x_P2_NOSDATA1			STV090x_Px_NOSDATAy(2, 1)
+#define STV090x_OFFST_Px_NOSDATA_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATA_UNNORMED_FIELD	8
+
+#define STV090x_Px_NOSPLHTy(__x, __y)		(0xf48d - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSPLHT0			STV090x_Px_NOSPLHTy(1, 0)
+#define STV090x_P1_NOSPLHT1			STV090x_Px_NOSPLHTy(1, 1)
+#define STV090x_P2_NOSPLHT0			STV090x_Px_NOSPLHTy(2, 0)
+#define STV090x_P2_NOSPLHT1			STV090x_Px_NOSPLHTy(2, 1)
+#define STV090x_OFFST_Px_NOSPLHT_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLHT_UNNORMED_FIELD	8
+
+#define STV090x_Px_NOSPLHy(__x, __y)		(0xf48f - (__x - 1) * 0x200 - __y * 0x1)
+#define STv090x_P1_NOSPLH0			STV090x_Px_NOSPLHy(1, 0)
+#define STv090x_P1_NOSPLH1			STV090x_Px_NOSPLHy(1, 1)
+#define STv090x_P2_NOSPLH0			STV090x_Px_NOSPLHy(2, 0)
+#define STv090x_P2_NOSPLH1			STV090x_Px_NOSPLHy(2, 1)
+#define STV090x_OFFST_Px_NOSPLH_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLH_UNNORMED_FIELD	8
+
+#define STV090x_Px_CAR2CFG(__x)			(0xf490 - (__x - 1) * 0x200)
+#define STV090x_P1_CAR2CFG			STV090x_Px_CAR2CFG(1)
+#define STV090x_P2_CAR2CFG			STV090x_Px_CAR2CFG(2)
+#define STV090x_OFFST_Px_PN4_SELECT_FIELD	6
+#define STV090x_WIDTH_Px_PN4_SELECT_FIELD	1
+#define STV090x_OFFST_Px_CFR2_STOPDVBS1_FIELD	5
+#define STV090x_WIDTH_Px_CFR2_STOPDVBS1_FIELD	1
+#define STV090x_OFFST_Px_ROTA2ON_FIELD		2
+#define STV090x_WIDTH_Px_ROTA2ON_FIELD		1
+#define STV090x_OFFST_Px_PH_DET_ALGO2_FIELD	0
+#define STV090x_WIDTH_Px_PH_DET_ALGO2_FIELD	2
+
+#define STV090x_Px_ACLC2(__x)			(0xf491 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2			STV090x_Px_ACLC2(1)
+#define STV090x_P2_ACLC2			STV090x_Px_ACLC2(2)
+#define STV090x_OFFST_Px_CAR2_ALPHA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR2_ALPHA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR2_ALPHA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR2_ALPHA_EXP_FIELD	4
+
+#define STV090x_Px_BCLC2(__x)			(0xf492 - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2			STV090x_Px_BCLC2(1)
+#define STV090x_P2_BCLC2			STV090x_Px_BCLC2(2)
+#define STV090x_OFFST_Px_CAR2_BETA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR2_BETA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR2_BETA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR2_BETA_EXP_FIELD	4
+
+#define STV090x_Px_ACLC2S2Q(__x)		(0xf497 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S2Q			STV090x_Px_ACLC2S2Q(1)
+#define STV090x_P2_ACLC2S2Q			STV090x_Px_ACLC2S2Q(2)
+#define STV090x_OFFST_Px_ENAB_SPSKSYMB_FIELD	7
+#define STV090x_WIDTH_Px_ENAB_SPSKSYMB_FIELD	1
+#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_E_FIELD	4
+
+#define STV090x_Px_ACLC2S28(__x)		(0xf498 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S28			STV090x_Px_ACLC2S28(1)
+#define STV090x_P2_ACLC2S28			STV090x_Px_ACLC2S28(2)
+#define STV090x_OFFST_Px_CAR2S2_8_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_8_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_E_FIELD	4
+
+#define STV090x_Px_ACLC2S216A(__x)		(0xf499 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S216A			STV090x_Px_ACLC2S216A(1)
+#define STV090x_P2_ACLC2S216A			STV090x_Px_ACLC2S216A(2)
+#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_E_FIELD	4
+
+#define STV090x_Px_ACLC2S232A(__x)		(0xf499 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S232A			STV090x_Px_ACLC2S232A(1)
+#define STV090x_P2_ACLC2S232A			STV090x_Px_ACLC2S232A(2)
+#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_E_FIELD	4
+
+#define STV090x_Px_BCLC2S2Q(__x)		(0xf49c - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S2Q			STV090x_Px_BCLC2S2Q(1)
+#define STV090x_P2_BCLC2S2Q			STV090x_Px_BCLC2S2Q(2)
+#define STV090x_OFFST_Px_CAR2S2_Q_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_Q_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_E_FIELD	4
+
+#define STV090x_Px_BCLC2S28(__x)		(0xf49d - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S28			STV090x_Px_BCLC2S28(1)
+#define STV090x_P2_BCLC2S28			STV090x_Px_BCLC2S28(1)
+#define STV090x_OFFST_Px_CAR2S2_8_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_8_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_8_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_8_BETA_E_FIELD	4
+
+#define STV090x_Px_BCLC2S216A(__x)		(0xf49d - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S216A			STV090x_Px_BCLC2S216A(1)
+#define STV090x_P2_BCLC2S216A			STV090x_Px_BCLC2S216A(1)
+#define STV090x_OFFST_Px_CAR2S2_16A_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_16A_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_E_FIELD	4
+
+#define STV090x_Px_BCLC2S232A(__x)		(0xf49d - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S232A			STV090x_Px_BCLC2S232A(1)
+#define STV090x_P2_BCLC2S232A			STV090x_Px_BCLC2S232A(1)
+#define STV090x_OFFST_Px_CAR2S2_32A_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_32A_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_E_FIELD	4
+
+#define STV090x_Px_PLROOT2(__x)			(0xf4ac - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT2			STV090x_Px_PLROOT2(1)
+#define STV090x_P2_PLROOT2			STV090x_Px_PLROOT2(2)
+#define STV090x_OFFST_Px_PLSCRAMB_MODE_FIELD	2
+#define STV090x_WIDTH_Px_PLSCRAMB_MODE_FIELD	2
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT_FIELD	0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT_FIELD	2
+
+#define STV090x_Px_PLROOT1(__x)			(0xf4ad - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT1			STV090x_Px_PLROOT1(1)
+#define STV090x_P2_PLROOT1			STV090x_Px_PLROOT1(2)
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT1_FIELD	0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT1_FIELD	8
+
+#define STV090x_Px_PLROOT0(__x)			(0xf4ae - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT0			STV090x_Px_PLROOT0(1)
+#define STV090x_P2_PLROOT0			STV090x_Px_PLROOT0(2)
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT0_FIELD	0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT0_FIELD	8
+
+#define STV090x_Px_MODCODLST0(__x)		(0xf4b0 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_MODCODLST0			STV090x_Px_MODCODLST0(1)
+#define STV090x_P2_MODCODLST0			STV090x_Px_MODCODLST0(2)
+
+#define STV090x_Px_MODCODLST1(__x)		(0xf4b1 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST1			STV090x_Px_MODCODLST1(1)
+#define STV090x_P2_MODCODLST1			STV090x_Px_MODCODLST1(2)
+#define STV090x_OFFST_Px_DIS_MODCOD29_FIELD	4
+#define STV090x_WIDTH_Px_DIS_MODCOD29T_FIELD	4
+#define STV090x_OFFST_Px_DIS_32PSK_9_10_FIELD	0
+#define STV090x_WIDTH_Px_DIS_32PSK_9_10_FIELD	4
+
+#define STV090x_Px_MODCODLST2(__x)		(0xf4b2 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST2			STV090x_Px_MODCODLST2(1)
+#define STV090x_P2_MODCODLST2			STV090x_Px_MODCODLST2(2)
+#define STV090x_OFFST_Px_DIS_32PSK_8_9_FIELD	4
+#define STV090x_WIDTH_Px_DIS_32PSK_8_9_FIELD	4
+#define STV090x_OFFST_Px_DIS_32PSK_5_6_FIELD	0
+#define STV090x_WIDTH_Px_DIS_32PSK_5_6_FIELD	4
+
+#define STV090x_Px_MODCODLST3(__x)		(0xf4b3 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST3			STV090x_Px_MODCODLST3(1)
+#define STV090x_P2_MODCODLST3			STV090x_Px_MODCODLST3(2)
+#define STV090x_OFFST_Px_DIS_32PSK_4_5_FIELD	4
+#define STV090x_WIDTH_Px_DIS_32PSK_4_5_FIELD	4
+#define STV090x_OFFST_Px_DIS_32PSK_3_4_FIELD	0
+#define STV090x_WIDTH_Px_DIS_32PSK_3_4_FIELD	4
+
+#define STV090x_Px_MODCODLST4(__x)		(0xf4b4 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST4			STV090x_Px_MODCODLST4(1)
+#define STV090x_P2_MODCODLST4			STV090x_Px_MODCODLST4(2)
+#define STV090x_OFFST_Px_DIS_16PSK_9_10_FIELD	4
+#define STV090x_WIDTH_Px_DIS_16PSK_9_10_FIELD	4
+#define STV090x_OFFST_Px_DIS_16PSK_8_9_FIELD	0
+#define STV090x_WIDTH_Px_DIS_16PSK_8_9_FIELD	4
+
+#define STV090x_Px_MODCODLST5(__x)		(0xf4b5 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST5			STV090x_Px_MODCODLST5(1)
+#define STV090x_P2_MODCODLST5			STV090x_Px_MODCODLST5(2)
+#define STV090x_OFFST_Px_DIS_16PSK_5_6_FIELD	4
+#define STV090x_WIDTH_Px_DIS_16PSK_5_6_FIELD	4
+#define STV090x_OFFST_Px_DIS_16PSK_4_5_FIELD	0
+#define STV090x_WIDTH_Px_DIS_16PSK_4_5_FIELD	4
+
+#define STV090x_Px_MODCODLST6(__x)		(0xf4b6 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST6			STV090x_Px_MODCODLST6(1)
+#define STV090x_P2_MODCODLST6			STV090x_Px_MODCODLST6(2)
+#define STV090x_OFFST_Px_DIS_16PSK_3_4_FIELD	4
+#define STV090x_WIDTH_Px_DIS_16PSK_3_4_FIELD	4
+#define STV090x_OFFST_Px_DIS_16PSK_2_3_FIELD	0
+#define STV090x_WIDTH_Px_DIS_16PSK_2_3_FIELD	4
+
+#define STV090x_Px_MODCODLST7(__x)		(0xf4b7 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST7			STV090x_Px_MODCODLST7(1)
+#define STV090x_P2_MODCODLST7			STV090x_Px_MODCODLST7(2)
+#define STV090x_OFFST_Px_DIS_8P_9_10_FIELD	4
+#define STV090x_WIDTH_Px_DIS_8P_9_10_FIELD	4
+#define STV090x_OFFST_Px_DIS_8P_8_9_FIELD	0
+#define STV090x_WIDTH_Px_DIS_8P_8_9_FIELD	4
+
+#define STV090x_Px_MODCODLST8(__x)		(0xf4b8 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST8			STV090x_Px_MODCODLST8(1)
+#define STV090x_P2_MODCODLST8			STV090x_Px_MODCODLST8(2)
+#define STV090x_OFFST_Px_DIS_8P_5_6_FIELD	4
+#define STV090x_WIDTH_Px_DIS_8P_5_6_FIELD	4
+#define STV090x_OFFST_Px_DIS_8P_3_4_FIELD	0
+#define STV090x_WIDTH_Px_DIS_8P_3_4_FIELD	4
+
+#define STV090x_Px_MODCODLST9(__x)		(0xf4b9 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST9			STV090x_Px_MODCODLST9(1)
+#define STV090x_P2_MODCODLST9			STV090x_Px_MODCODLST9(2)
+#define STV090x_OFFST_Px_DIS_8P_2_3_FIELD	4
+#define STV090x_WIDTH_Px_DIS_8P_2_3_FIELD	4
+#define STV090x_OFFST_Px_DIS_8P_3_5_FIELD	0
+#define STV090x_WIDTH_Px_DIS_8P_3_5_FIELD	4
+
+#define STV090x_Px_MODCODLSTA(__x)		(0xf4ba - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTA			STV090x_Px_MODCODLSTA(1)
+#define STV090x_P2_MODCODLSTA			STV090x_Px_MODCODLSTA(2)
+#define STV090x_OFFST_Px_DIS_QP_9_10_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_9_10_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_8_9_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_8_9_FIELD	4
+
+#define STV090x_Px_MODCODLSTB(__x)		(0xf4bb - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTB			STV090x_Px_MODCODLSTB(1)
+#define STV090x_P2_MODCODLSTB			STV090x_Px_MODCODLSTB(2)
+#define STV090x_OFFST_Px_DIS_QP_5_6_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_5_6_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_4_5_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_4_5_FIELD	4
+
+#define STV090x_Px_MODCODLSTC(__x)		(0xf4bc - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTC			STV090x_Px_MODCODLSTC(1)
+#define STV090x_P2_MODCODLSTC			STV090x_Px_MODCODLSTC(2)
+#define STV090x_OFFST_Px_DIS_QP_3_4_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_3_4_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_2_3_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_2_3_FIELD	4
+
+#define STV090x_Px_MODCODLSTD(__x)		(0xf4bd - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTD			STV090x_Px_MODCODLSTD(1)
+#define STV090x_P2_MODCODLSTD			STV090x_Px_MODCODLSTD(2)
+#define STV090x_OFFST_Px_DIS_QP_3_5_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_3_5_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_1_2_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_1_2_FIELD	4
+
+#define STV090x_Px_MODCODLSTE(__x)		(0xf4be - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTE			STV090x_Px_MODCODLSTE(1)
+#define STV090x_P2_MODCODLSTE			STV090x_Px_MODCODLSTE(2)
+#define STV090x_OFFST_Px_DIS_QP_2_5_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_2_5_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_1_3_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_1_3_FIELD	4
+
+#define STV090x_Px_MODCODLSTF(__x)		(0xf4bf - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTF			STV090x_Px_MODCODLSTF(1)
+#define STV090x_P2_MODCODLSTF			STV090x_Px_MODCODLSTF(2)
+#define STV090x_OFFST_Px_DIS_QP_1_4_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_1_4_FIELD	4
+
+#define STV090x_Px_GAUSSR0(__x)			(0xf4c0 - (__x - 1) * 0x200)
+#define STV090x_P1_GAUSSR0			STV090x_Px_GAUSSR0(1)
+#define STV090x_P2_GAUSSR0			STV090x_Px_GAUSSR0(2)
+#define STV090x_OFFST_Px_EN_CCIMODE_FIELD	7
+#define STV090x_WIDTH_Px_EN_CCIMODE_FIELD	1
+#define STV090x_OFFST_Px_R0_GAUSSIEN_FIELD	0
+#define STV090x_WIDTH_Px_R0_GAUSSIEN_FIELD	7
+
+#define STV090x_Px_CCIR0(__x)			(0xf4c1 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIR0			STV090x_Px_CCIR0(1)
+#define STV090x_P2_CCIR0			STV090x_Px_CCIR0(2)
+#define STV090x_OFFST_Px_CCIDETECT_PLH_FIELD	7
+#define STV090x_WIDTH_Px_CCIDETECT_PLH_FIELD	1
+#define STV090x_OFFST_Px_R0_CCI_FIELD		0
+#define STV090x_WIDTH_Px_R0_CCI_FIELD		7
+
+#define STV090x_Px_CCIQUANT(__x)		(0xf4c2 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIQUANT			STV090x_Px_CCIQUANT(1)
+#define STV090x_P2_CCIQUANT			STV090x_Px_CCIQUANT(2)
+#define STV090x_OFFST_Px_CCI_BETA_FIELD		5
+#define STV090x_WIDTH_Px_CCI_BETA_FIELD		3
+#define STV090x_OFFST_Px_CCI_QUANT_FIELD	0
+#define STV090x_WIDTH_Px_CCI_QUANT_FIELD	5
+
+#define STV090x_Px_CCITHRESH(__x)		(0xf4c3 - (__x - 1) * 0x200)
+#define STV090x_P1_CCITHRESH			STV090x_Px_CCITHRESH(1)
+#define STV090x_P2_CCITHRESH			STV090x_Px_CCITHRESH(2)
+#define STV090x_OFFST_Px_CCI_THRESHOLD_FIELD	0
+#define STV090x_WIDTH_Px_CCI_THRESHOLD_FIELD	8
+
+#define STV090x_Px_CCIACC(__x)			(0xf4c4 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIACC			STV090x_Px_CCIACC(1)
+#define STV090x_P2_CCIACC			STV090x_Px_CCIACC(1)
+#define STV090x_OFFST_Px_CCI_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_CCI_VALUE_FIELD	8
+
+#define STV090x_Px_DMDRESCFG(__x)		(0xF4C6 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDRESCFG			STV090x_Px_DMDRESCFG(1)
+#define STV090x_P2_DMDRESCFG			STV090x_Px_DMDRESCFG(2)
+#define STV090x_OFFST_Px_DMDRES_RESET_FIELD	7
+#define STV090x_WIDTH_Px_DMDRES_RESET_FIELD	1
+
+#define STV090x_Px_DMDRESADR(__x)		(0xF4C7 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDRESADR			STV090x_Px_DMDRESADR(1)
+#define STV090x_P2_DMDRESADR			STV090x_Px_DMDRESADR(2)
+#define STV090x_OFFST_Px_DMDRES_RESNBR_FIELD	0
+#define STV090x_WIDTH_Px_DMDRES_RESNBR_FIELD	4
+
+#define STV090x_Px_DMDRESDATAy(__x, __y)	(0xF4C8 - (__x - 1) * 0x200 + (7 - __y))
+#define STV090x_P1_DMDRESDATA0			STV090x_Px_DMDRESDATAy(1, 0)
+#define STV090x_P1_DMDRESDATA1			STV090x_Px_DMDRESDATAy(1, 1)
+#define STV090x_P1_DMDRESDATA2			STV090x_Px_DMDRESDATAy(1, 2)
+#define STV090x_P1_DMDRESDATA3			STV090x_Px_DMDRESDATAy(1, 3)
+#define STV090x_P1_DMDRESDATA4			STV090x_Px_DMDRESDATAy(1, 4)
+#define STV090x_P1_DMDRESDATA5			STV090x_Px_DMDRESDATAy(1, 5)
+#define STV090x_P1_DMDRESDATA6			STV090x_Px_DMDRESDATAy(1, 6)
+#define STV090x_P1_DMDRESDATA7			STV090x_Px_DMDRESDATAy(1, 7)
+#define STV090x_P2_DMDRESDATA0			STV090x_Px_DMDRESDATAy(2, 0)
+#define STV090x_P2_DMDRESDATA1			STV090x_Px_DMDRESDATAy(2, 1)
+#define STV090x_P2_DMDRESDATA2			STV090x_Px_DMDRESDATAy(2, 2)
+#define STV090x_P2_DMDRESDATA3			STV090x_Px_DMDRESDATAy(2, 3)
+#define STV090x_P2_DMDRESDATA4			STV090x_Px_DMDRESDATAy(2, 4)
+#define STV090x_P2_DMDRESDATA5			STV090x_Px_DMDRESDATAy(2, 5)
+#define STV090x_P2_DMDRESDATA6			STV090x_Px_DMDRESDATAy(2, 6)
+#define STV090x_P2_DMDRESDATA7			STV090x_Px_DMDRESDATAy(2, 7)
+#define STV090x_OFFST_Px_DMDRES_DATA_FIELD	0
+#define STV090x_WIDTH_Px_DMDRES_DATA_FIELD	8
+
+#define STV090x_Px_FFEIy(__x, __y)		(0xf4d0 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
+#define STV090x_P1_FFEI1			STV090x_Px_FFEIy(1, 1)
+#define STV090x_P1_FFEI2			STV090x_Px_FFEIy(1, 2)
+#define STV090x_P1_FFEI3			STV090x_Px_FFEIy(1, 3)
+#define STV090x_P1_FFEI4			STV090x_Px_FFEIy(1, 4)
+#define STV090x_P2_FFEI1			STV090x_Px_FFEIy(2, 1)
+#define STV090x_P2_FFEI2			STV090x_Px_FFEIy(2, 2)
+#define STV090x_P2_FFEI3			STV090x_Px_FFEIy(2, 3)
+#define STV090x_P2_FFEI4			STV090x_Px_FFEIy(2, 4)
+#define STV090x_OFFST_Px_FFE_ACCIy_FIELD	0
+#define STV090x_WIDTH_Px_FFE_ACCIy_FIELD	8
+
+#define STV090x_Px_FFEQy(__x, __y)		(0xf4d1 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
+#define STV090x_P1_FFEQ1			STV090x_Px_FFEQy(1, 1)
+#define STV090x_P1_FFEQ2			STV090x_Px_FFEQy(1, 2)
+#define STV090x_P1_FFEQ3			STV090x_Px_FFEQy(1, 3)
+#define STV090x_P1_FFEQ4			STV090x_Px_FFEQy(1, 4)
+#define STV090x_P2_FFEQ1			STV090x_Px_FFEQy(2, 1)
+#define STV090x_P2_FFEQ2			STV090x_Px_FFEQy(2, 2)
+#define STV090x_P2_FFEQ3			STV090x_Px_FFEQy(2, 3)
+#define STV090x_P2_FFEQ4			STV090x_Px_FFEQy(2, 4)
+#define STV090x_OFFST_Px_FFE_ACCQy_FIELD	0
+#define STV090x_WIDTH_Px_FFE_ACCQy_FIELD	8
+
+#define STV090x_Px_FFECFG(__x)			(0xf4d8 - (__x - 1) * 0x200)
+#define STV090x_P1_FFECFG			STV090x_Px_FFECFG(1)
+#define STV090x_P2_FFECFG			STV090x_Px_FFECFG(2)
+#define STV090x_OFFST_Px_EQUALFFE_ON_FIELD	6
+#define STV090x_WIDTH_Px_EQUALFFE_ON_FIELD	1
+
+#define STV090x_Px_SMAPCOEF7(__x)		(0xf500 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF7			STV090x_Px_SMAPCOEF7(1)
+#define STV090x_P2_SMAPCOEF7			STV090x_Px_SMAPCOEF7(2)
+#define STV090x_OFFST_Px_DIS_QSCALE_FIELD	7
+#define STV090x_WIDTH_Px_DIS_QSCALE_FIELD	1
+#define STV090x_OFFST_Px_SMAPCOEF_Q_LLR12_FIELD	0
+#define STV090x_WIDTH_Px_SMAPCOEF_Q_LLR12_FIELD	7
+
+#define STV090x_Px_SMAPCOEF6(__x)		(0xf501 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF6			STV090x_Px_SMAPCOEF6(1)
+#define STV090x_P2_SMAPCOEF6			STV090x_Px_SMAPCOEF6(2)
+#define STV090x_OFFST_Px_ADJ_8PSKLLR1_FIELD	2
+#define STV090x_WIDTH_Px_ADJ_8PSKLLR1_FIELD	1
+#define STV090x_OFFST_Px_OLD_8PSKLLR1_FIELD	1
+#define STV090x_WIDTH_Px_OLD_8PSKLLR1_FIELD	1
+#define STV090x_OFFST_Px_DIS_AB8PSK_FIELD	0
+#define STV090x_WIDTH_Px_DIS_AB8PSK_FIELD	1
+
+#define STV090x_Px_SMAPCOEF5(__x)			(0xf502 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF5				STV090x_Px_SMAPCOEF5(1)
+#define STV090x_P2_SMAPCOEF5				STV090x_Px_SMAPCOEF5(2)
+#define STV090x_OFFST_Px_DIS_8SCALE_FIELD		7
+#define STV090x_WIDTH_Px_DIS_8SCALE_FIELD		1
+#define STV090x_OFFST_Px_SMAPCOEF_8P_LLR23_FIELD	0
+#define STV090x_WIDTH_Px_SMAPCOEF_8P_LLR23_FIELD	7
+
+#define STV090x_Px_DMDPLHSTAT(__x)		(0xF520 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDPLHSTAT			STV090x_Px_DMDPLHSTAT(1)
+#define STV090x_P2_DMDPLHSTAT			STV090x_Px_DMDPLHSTAT(2)
+#define STV090x_OFFST_Px_PLH_STATISTIC_FIELD	0
+#define STV090x_WIDTH_Px_PLH_STATISTIC_FIELD	8
+
+#define STV090x_Px_LOCKTIMEy(__x, __y)		(0xF525 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_LOCKTIME0			STV090x_Px_LOCKTIMEy(1, 0)
+#define STV090x_P1_LOCKTIME1			STV090x_Px_LOCKTIMEy(1, 1)
+#define STV090x_P1_LOCKTIME2			STV090x_Px_LOCKTIMEy(1, 2)
+#define STV090x_P1_LOCKTIME3			STV090x_Px_LOCKTIMEy(1, 3)
+#define STV090x_P2_LOCKTIME0			STV090x_Px_LOCKTIMEy(2, 0)
+#define STV090x_P2_LOCKTIME1			STV090x_Px_LOCKTIMEy(2, 1)
+#define STV090x_P2_LOCKTIME2			STV090x_Px_LOCKTIMEy(2, 2)
+#define STV090x_P2_LOCKTIME3			STV090x_Px_LOCKTIMEy(2, 3)
+#define STV090x_OFFST_Px_DEMOD_LOCKTIME_FIELD	0
+#define STV090x_WIDTH_Px_DEMOD_LOCKTIME_FIELD	8
+
+#define STV090x_Px_TNRCFG(__x)			(0xf4e0 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_TNRCFG			STV090x_Px_TNRCFG(1)
+#define STV090x_P2_TNRCFG			STV090x_Px_TNRCFG(2)
+
+#define STV090x_Px_TNRCFG2(__x)			(0xf4e1 - (__x - 1) * 0x200)
+#define STV090x_P1_TNRCFG2			STV090x_Px_TNRCFG2(1)
+#define STV090x_P2_TNRCFG2			STV090x_Px_TNRCFG2(2)
+#define STV090x_OFFST_Px_TUN_IQSWAP_FIELD	7
+#define STV090x_WIDTH_Px_TUN_IQSWAP_FIELD	1
+
+#define STV090x_Px_VITSCALE(__x)		(0xf532 - (__x - 1) * 0x200)
+#define STV090x_P1_VITSCALE			STV090x_Px_VITSCALE(1)
+#define STV090x_P2_VITSCALE			STV090x_Px_VITSCALE(2)
+#define STV090x_OFFST_Px_NVTH_NOSRANGE_FIELD	7
+#define STV090x_WIDTH_Px_NVTH_NOSRANGE_FIELD	1
+#define STV090x_OFFST_Px_VERROR_MAXMODE_FIELD	6
+#define STV090x_WIDTH_Px_VERROR_MAXMODE_FIELD	1
+#define STV090x_OFFST_Px_NSLOWSN_LOCKED_FIELD	3
+#define STV090x_WIDTH_Px_NSLOWSN_LOCKED_FIELD	1
+#define STV090x_OFFST_Px_DIS_RSFLOCK_FIELD	1
+#define STV090x_WIDTH_Px_DIS_RSFLOCK_FIELD	1
+
+#define STV090x_Px_FECM(__x)			(0xf533 - (__x - 1) * 0x200)
+#define STV090x_P1_FECM				STV090x_Px_FECM(1)
+#define STV090x_P2_FECM				STV090x_Px_FECM(2)
+#define STV090x_OFFST_Px_DSS_DVB_FIELD		7
+#define STV090x_WIDTH_Px_DSS_DVB_FIELD		1
+#define STV090x_OFFST_Px_DSS_SRCH_FIELD		4
+#define STV090x_WIDTH_Px_DSS_SRCH_FIELD		1
+#define STV090x_OFFST_Px_SYNCVIT_FIELD		1
+#define STV090x_WIDTH_Px_SYNCVIT_FIELD		1
+#define STV090x_OFFST_Px_IQINV_FIELD		0
+#define STV090x_WIDTH_Px_IQINV_FIELD		1
+
+#define STV090x_Px_VTH12(__x)			(0xf534 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH12			STV090x_Px_VTH12(1)
+#define STV090x_P2_VTH12			STV090x_Px_VTH12(2)
+#define STV090x_OFFST_Px_VTH12_FIELD		0
+#define STV090x_WIDTH_Px_VTH12_FIELD		8
+
+#define STV090x_Px_VTH23(__x)			(0xf535 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH23			STV090x_Px_VTH23(1)
+#define STV090x_P2_VTH23			STV090x_Px_VTH23(2)
+#define STV090x_OFFST_Px_VTH23_FIELD		0
+#define STV090x_WIDTH_Px_VTH23_FIELD		8
+
+#define STV090x_Px_VTH34(__x)			(0xf536 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH34			STV090x_Px_VTH34(1)
+#define STV090x_P2_VTH34			STV090x_Px_VTH34(2)
+#define STV090x_OFFST_Px_VTH34_FIELD		0
+#define STV090x_WIDTH_Px_VTH34_FIELD		8
+
+#define STV090x_Px_VTH56(__x)			(0xf537 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH56			STV090x_Px_VTH56(1)
+#define STV090x_P2_VTH56			STV090x_Px_VTH56(2)
+#define STV090x_OFFST_Px_VTH56_FIELD		0
+#define STV090x_WIDTH_Px_VTH56_FIELD		8
+
+#define STV090x_Px_VTH67(__x)			(0xf538 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH67			STV090x_Px_VTH67(1)
+#define STV090x_P2_VTH67			STV090x_Px_VTH67(2)
+#define STV090x_OFFST_Px_VTH67_FIELD		0
+#define STV090x_WIDTH_Px_VTH67_FIELD		8
+
+#define STV090x_Px_VTH78(__x)			(0xf539 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH78			STV090x_Px_VTH78(1)
+#define STV090x_P2_VTH78			STV090x_Px_VTH78(2)
+#define STV090x_OFFST_Px_VTH78_FIELD		0
+#define STV090x_WIDTH_Px_VTH78_FIELD		8
+
+#define STV090x_Px_VITCURPUN(__x)		(0xf53a - (__x - 1) * 0x200)
+#define STV090x_P1_VITCURPUN			STV090x_Px_VITCURPUN(1)
+#define STV090x_P2_VITCURPUN			STV090x_Px_VITCURPUN(2)
+#define STV090x_OFFST_Px_VIT_CURPUN_FIELD	0
+#define STV090x_WIDTH_Px_VIT_CURPUN_FIELD	5
+
+#define STV090x_Px_VERROR(__x)			(0xf53b - (__x - 1) * 0x200)
+#define STV090x_P1_VERROR			STV090x_Px_VERROR(1)
+#define STV090x_P2_VERROR			STV090x_Px_VERROR(2)
+#define STV090x_OFFST_Px_REGERR_VIT_FIELD	0
+#define STV090x_WIDTH_Px_REGERR_VIT_FIELD	8
+
+#define STV090x_Px_PRVIT(__x)			(0xf53c - (__x - 1) * 0x200)
+#define STV090x_P1_PRVIT			STV090x_Px_PRVIT(1)
+#define STV090x_P2_PRVIT			STV090x_Px_PRVIT(2)
+#define STV090x_OFFST_Px_DIS_VTHLOCK_FIELD	6
+#define STV090x_WIDTH_Px_DIS_VTHLOCK_FIELD	1
+#define STV090x_OFFST_Px_E7_8VIT_FIELD		5
+#define STV090x_WIDTH_Px_E7_8VIT_FIELD		1
+#define STV090x_OFFST_Px_E6_7VIT_FIELD		4
+#define STV090x_WIDTH_Px_E6_7VIT_FIELD		1
+#define STV090x_OFFST_Px_E5_6VIT_FIELD		3
+#define STV090x_WIDTH_Px_E5_6VIT_FIELD		1
+#define STV090x_OFFST_Px_E3_4VIT_FIELD		2
+#define STV090x_WIDTH_Px_E3_4VIT_FIELD		1
+#define STV090x_OFFST_Px_E2_3VIT_FIELD		1
+#define STV090x_WIDTH_Px_E2_3VIT_FIELD		1
+#define STV090x_OFFST_Px_E1_2VIT_FIELD		0
+#define STV090x_WIDTH_Px_E1_2VIT_FIELD		1
+
+#define STV090x_Px_VAVSRVIT(__x)		(0xf53d - (__x - 1) * 0x200)
+#define STV090x_P1_VAVSRVIT			STV090x_Px_VAVSRVIT(1)
+#define STV090x_P2_VAVSRVIT			STV090x_Px_VAVSRVIT(2)
+#define STV090x_OFFST_Px_SNVIT_FIELD		4
+#define STV090x_WIDTH_Px_SNVIT_FIELD		2
+#define STV090x_OFFST_Px_TOVVIT_FIELD		2
+#define STV090x_WIDTH_Px_TOVVIT_FIELD		2
+#define STV090x_OFFST_Px_HYPVIT_FIELD		0
+#define STV090x_WIDTH_Px_HYPVIT_FIELD		2
+
+#define STV090x_Px_VSTATUSVIT(__x)		(0xf53e - (__x - 1) * 0x200)
+#define STV090x_P1_VSTATUSVIT			STV090x_Px_VSTATUSVIT(1)
+#define STV090x_P2_VSTATUSVIT			STV090x_Px_VSTATUSVIT(2)
+#define STV090x_OFFST_Px_PRFVIT_FIELD		4
+#define STV090x_WIDTH_Px_PRFVIT_FIELD		1
+#define STV090x_OFFST_Px_LOCKEDVIT_FIELD	3
+#define STV090x_WIDTH_Px_LOCKEDVIT_FIELD	1
+
+#define STV090x_Px_VTHINUSE(__x)		(0xf53f - (__x - 1) * 0x200)
+#define STV090x_P1_VTHINUSE			STV090x_Px_VTHINUSE(1)
+#define STV090x_P2_VTHINUSE			STV090x_Px_VTHINUSE(2)
+#define STV090x_OFFST_Px_VIT_INUSE_FIELD	0
+#define STV090x_WIDTH_Px_VIT_INUSE_FIELD	8
+
+#define STV090x_Px_KDIV12(__x)			(0xf540 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV12			STV090x_Px_KDIV12(1)
+#define STV090x_P2_KDIV12			STV090x_Px_KDIV12(2)
+#define STV090x_OFFST_Px_K_DIVIDER_12_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_12_FIELD	7
+
+#define STV090x_Px_KDIV23(__x)			(0xf541 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV23			STV090x_Px_KDIV23(1)
+#define STV090x_P2_KDIV23			STV090x_Px_KDIV23(2)
+#define STV090x_OFFST_Px_K_DIVIDER_23_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_23_FIELD	7
+
+#define STV090x_Px_KDIV34(__x)			(0xf542 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV34			STV090x_Px_KDIV34(1)
+#define STV090x_P2_KDIV34			STV090x_Px_KDIV34(2)
+#define STV090x_OFFST_Px_K_DIVIDER_34_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_34_FIELD	7
+
+#define STV090x_Px_KDIV56(__x)			(0xf543 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV56			STV090x_Px_KDIV56(1)
+#define STV090x_P2_KDIV56			STV090x_Px_KDIV56(2)
+#define STV090x_OFFST_Px_K_DIVIDER_56_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_56_FIELD	7
+
+#define STV090x_Px_KDIV67(__x)			(0xf544 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV67			STV090x_Px_KDIV67(1)
+#define STV090x_P2_KDIV67			STV090x_Px_KDIV67(2)
+#define STV090x_OFFST_Px_K_DIVIDER_67_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_67_FIELD	7
+
+#define STV090x_Px_KDIV78(__x)			(0xf545 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV78			STV090x_Px_KDIV78(1)
+#define STV090x_P2_KDIV78			STV090x_Px_KDIV78(2)
+#define STV090x_OFFST_Px_K_DIVIDER_78_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_78_FIELD	7
+
+#define STV090x_Px_PDELCTRL1(__x)		(0xf550 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELCTRL1			STV090x_Px_PDELCTRL1(1)
+#define STV090x_P2_PDELCTRL1			STV090x_Px_PDELCTRL1(2)
+#define STV090x_OFFST_Px_INV_MISMASK_FIELD	7
+#define STV090x_WIDTH_Px_INV_MISMASK_FIELD	1
+#define STV090x_OFFST_Px_FILTER_EN_FIELD	5
+#define STV090x_WIDTH_Px_FILTER_EN_FIELD	1
+#define STV090x_OFFST_Px_EN_MIS00_FIELD		1
+#define STV090x_WIDTH_Px_EN_MIS00_FIELD		1
+#define STV090x_OFFST_Px_ALGOSWRST_FIELD	0
+#define STV090x_WIDTH_Px_ALGOSWRST_FIELD	1
+
+#define STV090x_Px_PDELCTRL2(__x)		(0xf551 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELCTRL2			STV090x_Px_PDELCTRL2(1)
+#define STV090x_P2_PDELCTRL2			STV090x_Px_PDELCTRL2(2)
+#define STV090x_OFFST_Px_FORCE_CONTINUOUS	7
+#define STV090x_WIDTH_Px_FORCE_CONTINUOUS	1
+#define STV090x_OFFST_Px_RESET_UPKO_COUNT	6
+#define STV090x_WIDTH_Px_RESET_UPKO_COUNT	1
+#define STV090x_OFFST_Px_USER_PKTDELIN_NB	5
+#define STV090x_WIDTH_Px_USER_PKTDELIN_NB	1
+#define STV090x_OFFST_Px_FORCE_LOCKED		4
+#define STV090x_WIDTH_Px_FORCE_LOCKED		1
+#define STV090x_OFFST_Px_DATA_UNBBSCRAM		3
+#define STV090x_WIDTH_Px_DATA_UNBBSCRAM		1
+#define STV090x_OFFST_Px_FORCE_LONGPACKET	2
+#define STV090x_WIDTH_Px_FORCE_LONGPACKET	1
+#define STV090x_OFFST_Px_FRAME_MODE_FIELD	1
+#define STV090x_WIDTH_Px_FRAME_MODE_FIELD	1
+
+#define STV090x_Px_HYSTTHRESH(__x)		(0xf554 - (__x - 1) * 0x200)
+#define STV090x_P1_HYSTTHRESH			STV090x_Px_HYSTTHRESH(1)
+#define STV090x_P2_HYSTTHRESH			STV090x_Px_HYSTTHRESH(2)
+#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD	4
+#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD	4
+#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD	0
+#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD	4
+
+#define STV090x_Px_ISIENTRY(__x)		(0xf55e - (__x - 1) * 0x200)
+#define STV090x_P1_ISIENTRY			STV090x_Px_ISIENTRY(1)
+#define STV090x_P2_ISIENTRY			STV090x_Px_ISIENTRY(2)
+#define STV090x_OFFST_Px_ISI_ENTRY_FIELD	0
+#define STV090x_WIDTH_Px_ISI_ENTRY_FIELD	8
+
+#define STV090x_Px_ISIBITENA(__x)		(0xf55f - (__x - 1) * 0x200)
+#define STV090x_P1_ISIBITENA			STV090x_Px_ISIBITENA(1)
+#define STV090x_P2_ISIBITENA			STV090x_Px_ISIBITENA(2)
+#define STV090x_OFFST_Px_ISI_BIT_EN_FIELD	0
+#define STV090x_WIDTH_Px_ISI_BIT_EN_FIELD	8
+
+#define STV090x_Px_MATSTRy(__x, __y)		(0xf561 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_MATSTR0			STV090x_Px_MATSTRy(1, 0)
+#define STV090x_P1_MATSTR1			STV090x_Px_MATSTRy(1, 1)
+#define STV090x_P2_MATSTR0			STV090x_Px_MATSTRy(2, 0)
+#define STV090x_P2_MATSTR1			STV090x_Px_MATSTRy(2, 1)
+#define STV090x_OFFST_Px_MATYPE_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_MATYPE_CURRENT_FIELD	8
+
+#define STV090x_Px_UPLSTRy(__x, __y)		(0xf563 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_UPLSTR0			STV090x_Px_UPLSTRy(1, 0)
+#define STV090x_P1_UPLSTR1			STV090x_Px_UPLSTRy(1, 1)
+#define STV090x_P2_UPLSTR0			STV090x_Px_UPLSTRy(2, 0)
+#define STV090x_P2_UPLSTR1			STV090x_Px_UPLSTRy(2, 1)
+#define STV090x_OFFST_Px_UPL_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_UPL_CURRENT_FIELD	8
+
+#define STV090x_Px_DFLSTRy(__x, __y)		(0xf565 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_DFLSTR0			STV090x_Px_DFLSTRy(1, 0)
+#define STV090x_P1_DFLSTR1			STV090x_Px_DFLSTRy(1, 1)
+#define STV090x_P2_DFLSTR0			STV090x_Px_DFLSTRy(2, 0)
+#define STV090x_P2_DFLSTR1			STV090x_Px_DFLSTRy(2, 1)
+#define STV090x_OFFST_Px_DFL_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_DFL_CURRENT_FIELD	8
+
+#define STV090x_Px_SYNCSTR(__x)			(0xf566 - (__x - 1) * 0x200)
+#define STV090x_P1_SYNCSTR			STV090x_Px_SYNCSTR(1)
+#define STV090x_P2_SYNCSTR			STV090x_Px_SYNCSTR(2)
+#define STV090x_OFFST_Px_SYNC_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_SYNC_CURRENT_FIELD	8
+
+#define STV090x_Px_SYNCDSTRy(__x, __y)		(0xf568 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_SYNCDSTR0			STV090x_Px_SYNCDSTRy(1, 0)
+#define STV090x_P1_SYNCDSTR1			STV090x_Px_SYNCDSTRy(1, 1)
+#define STV090x_P2_SYNCDSTR0			STV090x_Px_SYNCDSTRy(2, 0)
+#define STV090x_P2_SYNCDSTR1			STV090x_Px_SYNCDSTRy(2, 1)
+#define STV090x_OFFST_Px_SYNCD_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_SYNCD_CURRENT_FIELD	8
+
+#define STV090x_Px_PDELSTATUS1(__x)		(0xf569 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELSTATUS1			STV090x_Px_PDELSTATUS1(1)
+#define STV090x_P2_PDELSTATUS1			STV090x_Px_PDELSTATUS1(2)
+#define STV090x_OFFST_Px_PKTDELIN_LOCK_FIELD	1
+#define STV090x_WIDTH_Px_PKTDELIN_LOCK_FIELD	1
+#define STV090x_OFFST_Px_FIRST_LOCK_FIELD	0
+#define STV090x_WIDTH_Px_FIRST_LOCK_FIELD	1
+
+#define STV090x_Px_PDELSTATUS2(__x)		(0xf56a - (__x - 1) * 0x200)
+#define STV090x_P1_PDELSTATUS2			STV090x_Px_PDELSTATUS2(1)
+#define STV090x_P2_PDELSTATUS2			STV090x_Px_PDELSTATUS2(2)
+#define STV090x_OFFST_Px_FRAME_MODCOD_FIELD	2
+#define STV090x_WIDTH_Px_FRAME_MODCOD_FIELD	5
+#define STV090x_OFFST_Px_FRAME_TYPE_FIELD	0
+#define STV090x_WIDTH_Px_FRAME_TYPE_FIELD	2
+
+#define STV090x_Px_BBFCRCKO1(__x)		(0xf56b - (__x - 1) * 0x200)
+#define STV090x_P1_BBFCRCKO1			STV090x_Px_BBFCRCKO1(1)
+#define STV090x_P2_BBFCRCKO1			STV090x_Px_BBFCRCKO1(2)
+#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD	8
+
+#define STV090x_Px_BBFCRCKO0(__x)		(0xf56c - (__x - 1) * 0x200)
+#define STV090x_P1_BBFCRCKO0			STV090x_Px_BBFCRCKO0(1)
+#define STV090x_P2_BBFCRCKO0			STV090x_Px_BBFCRCKO0(2)
+#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD	8
+
+#define STV090x_Px_UPCRCKO1(__x)		(0xf56d - (__x - 1) * 0x200)
+#define STV090x_P1_UPCRCKO1			STV090x_Px_UPCRCKO1(1)
+#define STV090x_P2_UPCRCKO1			STV090x_Px_UPCRCKO1(2)
+#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD	8
+
+#define STV090x_Px_UPCRCKO0(__x)		(0xf56e - (__x - 1) * 0x200)
+#define STV090x_P1_UPCRCKO0			STV090x_Px_UPCRCKO0(1)
+#define STV090x_P2_UPCRCKO0			STV090x_Px_UPCRCKO0(2)
+#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD	8
+
+#define STV090x_NBITER_NFx(__x)				(0xFA03 + (__x - 4) * 0x1)
+#define STV090x_NBITER_NF4				STV090x_NBITER_NFx(4)
+#define STV090x_NBITER_NF5				STV090x_NBITER_NFx(5)
+#define STV090x_NBITER_NF6				STV090x_NBITER_NFx(6)
+#define STV090x_NBITER_NF7				STV090x_NBITER_NFx(7)
+#define STV090x_NBITER_NF8				STV090x_NBITER_NFx(8)
+#define STV090x_NBITER_NF9				STV090x_NBITER_NFx(9)
+#define STV090x_NBITER_NF10				STV090x_NBITER_NFx(10)
+#define STV090x_NBITER_NF11				STV090x_NBITER_NFx(11)
+#define STV090x_NBITER_NF12				STV090x_NBITER_NFx(12)
+#define STV090x_NBITER_NF13				STV090x_NBITER_NFx(13)
+#define STV090x_NBITER_NF14				STV090x_NBITER_NFx(14)
+#define STV090x_NBITER_NF15				STV090x_NBITER_NFx(15)
+#define STV090x_NBITER_NF16				STV090x_NBITER_NFx(16)
+#define STV090x_NBITER_NF17				STV090x_NBITER_NFx(17)
+
+#define STV090x_NBITERNOERR				0xFA3F
+#define STV090x_OFFST_NBITER_STOP_CRIT_FIELD		0
+#define STV090x_WIDTH_NBITER_STOP_CRIT_FIELD		4
+
+#define STV090x_GAINLLR_NFx(__x)			(0xFA43 + (__x - 4) * 0x1)
+#define STV090x_GAINLLR_NF4				STV090x_GAINLLR_NFx(4)
+#define STV090x_OFFST_GAINLLR_NF_QP_1_2_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_1_2_FIELD		7
+
+#define STV090x_GAINLLR_NF5				STV090x_GAINLLR_NFx(5)
+#define STV090x_OFFST_GAINLLR_NF_QP_3_5_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_3_5_FIELD		7
+
+#define STV090x_GAINLLR_NF6				STV090x_GAINLLR_NFx(6)
+#define STV090x_OFFST_GAINLLR_NF_QP_2_3_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_2_3_FIELD		7
+
+#define STV090x_GAINLLR_NF7				STV090x_GAINLLR_NFx(7)
+#define STV090x_OFFST_GAINLLR_NF_QP_3_4_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_3_4_FIELD		7
+
+#define STV090x_GAINLLR_NF8				STV090x_GAINLLR_NFx(8)
+#define STV090x_OFFST_GAINLLR_NF_QP_4_5_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_4_5_FIELD		7
+
+#define STV090x_GAINLLR_NF9				STV090x_GAINLLR_NFx(9)
+#define STV090x_OFFST_GAINLLR_NF_QP_5_6_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_5_6_FIELD		7
+
+#define STV090x_GAINLLR_NF10				STV090x_GAINLLR_NFx(10)
+#define STV090x_OFFST_GAINLLR_NF_QP_8_9_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_8_9_FIELD		7
+
+#define STV090x_GAINLLR_NF11				STV090x_GAINLLR_NFx(11)
+#define STV090x_OFFST_GAINLLR_NF_QP_9_10_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_9_10_FIELD		7
+
+#define STV090x_GAINLLR_NF12				STV090x_GAINLLR_NFx(12)
+#define STV090x_OFFST_GAINLLR_NF_8P_3_5_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_3_5_FIELD		7
+
+#define STV090x_GAINLLR_NF13				STV090x_GAINLLR_NFx(13)
+#define STV090x_OFFST_GAINLLR_NF_8P_2_3_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_2_3_FIELD		7
+
+#define STV090x_GAINLLR_NF14				STV090x_GAINLLR_NFx(14)
+#define STV090x_OFFST_GAINLLR_NF_8P_3_4_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_3_4_FIELD		7
+
+#define STV090x_GAINLLR_NF15				STV090x_GAINLLR_NFx(15)
+#define STV090x_OFFST_GAINLLR_NF_8P_5_6_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_5_6_FIELD		7
+
+#define STV090x_GAINLLR_NF16				STV090x_GAINLLR_NFx(16)
+#define STV090x_OFFST_GAINLLR_NF_8P_8_9_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_8_9_FIELD		7
+
+#define STV090x_GAINLLR_NF17				STV090x_GAINLLR_NFx(17)
+#define STV090x_OFFST_GAINLLR_NF_8P_9_10_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_9_10_FIELD		7
+
+#define STV090x_GENCFG					0xFA86
+#define STV090x_OFFST_BROADCAST_FIELD			4
+#define STV090x_WIDTH_BROADCAST_FIELD			1
+#define STV090x_OFFST_PRIORITY_FIELD			1
+#define STV090x_WIDTH_PRIORITY_FIELD			1
+#define STV090x_OFFST_DDEMOD_FIELD			0
+#define STV090x_WIDTH_DDEMOD_FIELD			1
+
+#define STV090x_LDPCERRx(__x)				(0xFA97 - (__x  * 0x1))
+#define STV090x_LDPCERR0				STV090x_LDPCERRx(0)
+#define STV090x_LDPCERR1				STV090x_LDPCERRx(1)
+#define STV090x_OFFST_Px_LDPC_ERRORS_COUNTER_FIELD	0
+#define STV090x_WIDTH_Px_LDPC_ERRORS_COUNTER_FIELD	8
+
+#define STV090x_BCHERR					0xFA98
+#define STV090x_OFFST_Px_ERRORFLAG_FIELD		4
+#define STV090x_WIDTH_Px_ERRORFLAG_FIELD		1
+#define STV090x_OFFST_Px_BCH_ERRORS_COUNTER_FIELD	0
+#define STV090x_WIDTH_Px_BCH_ERRORS_COUNTER_FIELD	4
+
+#define STV090x_Px_TSSTATEM(__x)			(0xF570 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATEM				STV090x_Px_TSSTATEM(1)
+#define STV090x_P2_TSSTATEM				STV090x_Px_TSSTATEM(2)
+#define STV090x_OFFST_Px_TSDIL_ON_FIELD			7
+#define STV090x_WIDTH_Px_TSDIL_ON_FIELD			1
+#define STV090x_OFFST_Px_TSRS_ON_FIELD			5
+#define STV090x_WIDTH_Px_TSRS_ON_FIELD			1
+
+#define STV090x_Px_TSCFGH(__x)				(0xF572 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGH				STV090x_Px_TSCFGH(1)
+#define STV090x_P2_TSCFGH				STV090x_Px_TSCFGH(2)
+#define STV090x_OFFST_Px_TSFIFO_DVBCI_FIELD		7
+#define STV090x_WIDTH_Px_TSFIFO_DVBCI_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_SERIAL_FIELD		6
+#define STV090x_WIDTH_Px_TSFIFO_SERIAL_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_TEIUPDATE_FIELD		5
+#define STV090x_WIDTH_Px_TSFIFO_TEIUPDATE_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_DUTY50_FIELD		4
+#define STV090x_WIDTH_Px_TSFIFO_DUTY50_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_HSGNLOUT_FIELD		3
+#define STV090x_WIDTH_Px_TSFIFO_HSGNLOUT_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_ERRORMODE_FIELD		1
+#define STV090x_WIDTH_Px_TSFIFO_ERRORMODE_FIELD		2
+#define STV090x_OFFST_Px_RST_HWARE_FIELD		0
+#define STV090x_WIDTH_Px_RST_HWARE_FIELD		1
+
+#define STV090x_Px_TSCFGM(__x)				(0xF573 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGM				STV090x_Px_TSCFGM(1)
+#define STV090x_P2_TSCFGM				STV090x_Px_TSCFGM(2)
+#define STV090x_OFFST_Px_TSFIFO_MANSPEED_FIELD		6
+#define STV090x_WIDTH_Px_TSFIFO_MANSPEED_FIELD		2
+#define STV090x_OFFST_Px_TSFIFO_PERMDATA_FIELD		5
+#define STV090x_WIDTH_Px_TSFIFO_PERMDATA_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_INVDATA_FIELD		0
+#define STV090x_WIDTH_Px_TSFIFO_INVDATA_FIELD		1
+
+#define STV090x_Px_TSCFGL(__x)				(0xF574 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGL				STV090x_Px_TSCFGL(1)
+#define STV090x_P2_TSCFGL				STV090x_Px_TSCFGL(2)
+#define STV090x_OFFST_Px_TSFIFO_BCLKDEL1CK_FIELD	6
+#define STV090x_WIDTH_Px_TSFIFO_BCLKDEL1CK_FIELD	2
+#define STV090x_OFFST_Px_BCHERROR_MODE_FIELD		4
+#define STV090x_WIDTH_Px_BCHERROR_MODE_FIELD		2
+#define STV090x_OFFST_Px_TSFIFO_NSGNL2DATA_FIELD	3
+#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA_FIELD	1
+#define STV090x_OFFST_Px_TSFIFO_EMBINDVB_FIELD		2
+#define STV090x_WIDTH_Px_TSFIFO_EMBINDVB_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD		1
+#define STV090x_WIDTH_Px_TSFIFO_DPUNACT_FIELD		1
+
+#define STV090x_Px_TSINSDELH(__x)			(0xF576 - (__x - 1) * 0x200)
+#define STV090x_P1_TSINSDELH				STV090x_Px_TSINSDELH(1)
+#define STV090x_P2_TSINSDELH				STV090x_Px_TSINSDELH(2)
+#define STV090x_OFFST_Px_TSDEL_SYNCBYTE_FIELD		7
+#define STV090x_WIDTH_Px_TSDEL_SYNCBYTE_FIELD		1
+#define STV090x_OFFST_Px_TSDEL_XXHEADER_FIELD		6
+#define STV090x_WIDTH_Px_TSDEL_XXHEADER_FIELD		1
+
+#define STV090x_Px_TSSPEED(__x)				(0xF580 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSPEED				STV090x_Px_TSSPEED(1)
+#define STV090x_P2_TSSPEED				STV090x_Px_TSSPEED(2)
+#define STV090x_OFFST_Px_TSFIFO_OUTSPEED_FIELD		0
+#define STV090x_WIDTH_Px_TSFIFO_OUTSPEED_FIELD		8
+
+#define STV090x_Px_TSSTATUS(__x)			(0xF581 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATUS				STV090x_Px_TSSTATUS(1)
+#define STV090x_P2_TSSTATUS				STV090x_Px_TSSTATUS(2)
+#define STV090x_OFFST_Px_TSFIFO_LINEOK_FIELD		7
+#define STV090x_WIDTH_Px_TSFIFO_LINEOK_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_ERROR_FIELD		6
+#define STV090x_WIDTH_Px_TSFIFO_ERROR_FIELD		1
+
+#define STV090x_Px_TSSTATUS2(__x)			(0xF582 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATUS2				STV090x_Px_TSSTATUS2(1)
+#define STV090x_P2_TSSTATUS2				STV090x_Px_TSSTATUS2(2)
+#define STV090x_OFFST_Px_TSFIFO_DEMODSEL_FIELD		7
+#define STV090x_WIDTH_Px_TSFIFO_DEMODSEL_FIELD		1
+#define STV090x_OFFST_Px_TSFIFOSPEED_STORE_FIELD	6
+#define STV090x_WIDTH_Px_TSFIFOSPEED_STORE_FIELD	1
+#define STV090x_OFFST_Px_DILXX_RESET_FIELD		5
+#define STV090x_WIDTH_Px_DILXX_RESET_FIELD		1
+#define STV090x_OFFST_Px_TSSERIAL_IMPOS_FIELD		5
+#define STV090x_WIDTH_Px_TSSERIAL_IMPOS_FIELD		1
+#define STV090x_OFFST_Px_SCRAMBDETECT_FIELD		1
+#define STV090x_WIDTH_Px_SCRAMBDETECT_FIELD		1
+
+#define STV090x_Px_TSBITRATEy(__x, __y)			(0xF584 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_TSBITRATE0				STV090x_Px_TSBITRATEy(1, 0)
+#define STV090x_P1_TSBITRATE1				STV090x_Px_TSBITRATEy(1, 1)
+#define STV090x_P2_TSBITRATE0				STV090x_Px_TSBITRATEy(2, 0)
+#define STV090x_P2_TSBITRATE1				STV090x_Px_TSBITRATEy(2, 1)
+#define STV090x_OFFST_Px_TSFIFO_BITRATE_FIELD		7
+#define STV090x_WIDTH_Px_TSFIFO_BITRATE_FIELD		8
+
+#define STV090x_Px_ERRCTRL1(__x)			(0xF598 - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCTRL1				STV090x_Px_ERRCTRL1(1)
+#define STV090x_P2_ERRCTRL1				STV090x_Px_ERRCTRL1(2)
+#define STV090x_OFFST_Px_ERR_SOURCE_FIELD		4
+#define STV090x_WIDTH_Px_ERR_SOURCE_FIELD		4
+#define STV090x_OFFST_Px_NUM_EVENT_FIELD		0
+#define STV090x_WIDTH_Px_NUM_EVENT_FIELD		3
+
+#define STV090x_Px_ERRCNT12(__x)			(0xF599 - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT12				STV090x_Px_ERRCNT12(1)
+#define STV090x_P2_ERRCNT12				STV090x_Px_ERRCNT12(2)
+#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE_FIELD		7
+#define STV090x_WIDTH_Px_ERRCNT1_OLDVALUE_FIELD		1
+#define STV090x_OFFST_Px_ERR_CNT12_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT12_FIELD		7
+
+#define STV090x_Px_ERRCNT11(__x)			(0xF59A - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT11				STV090x_Px_ERRCNT11(1)
+#define STV090x_P2_ERRCNT11				STV090x_Px_ERRCNT11(2)
+#define STV090x_OFFST_Px_ERR_CNT11_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT11_FIELD		8
+
+#define STV090x_Px_ERRCNT10(__x)			(0xF59B - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT10				STV090x_Px_ERRCNT10(1)
+#define STV090x_P2_ERRCNT10				STV090x_Px_ERRCNT10(2)
+#define STV090x_OFFST_Px_ERR_CNT10_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT10_FIELD		8
+
+#define STV090x_Px_ERRCTRL2(__x)			(0xF59C - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCTRL2				STV090x_Px_ERRCTRL2(1)
+#define STV090x_P2_ERRCTRL2				STV090x_Px_ERRCTRL2(2)
+#define STV090x_OFFST_Px_ERR_SOURCE2_FIELD		4
+#define STV090x_WIDTH_Px_ERR_SOURCE2_FIELD		4
+#define STV090x_OFFST_Px_NUM_EVENT2_FIELD		0
+#define STV090x_WIDTH_Px_NUM_EVENT2_FIELD		3
+
+#define STV090x_Px_ERRCNT22(__x)			(0xF59D - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT22				STV090x_Px_ERRCNT22(1)
+#define STV090x_P2_ERRCNT22				STV090x_Px_ERRCNT22(2)
+#define STV090x_OFFST_Px_ERRCNT2_OLDVALUE_FIELD		7
+#define STV090x_WIDTH_Px_ERRCNT2_OLDVALUE_FIELD		1
+#define STV090x_OFFST_Px_ERR_CNT2_FIELD			0
+#define STV090x_WIDTH_Px_ERR_CNT2_FIELD			7
+
+#define STV090x_Px_ERRCNT21(__x)			(0xF59E - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT21				STV090x_Px_ERRCNT21(1)
+#define STV090x_P2_ERRCNT21				STV090x_Px_ERRCNT21(2)
+#define STV090x_OFFST_Px_ERR_CNT21_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT21_FIELD		8
+
+#define STV090x_Px_ERRCNT20(__x)			(0xF59F - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT20				STV090x_Px_ERRCNT20(1)
+#define STV090x_P2_ERRCNT20				STV090x_Px_ERRCNT20(2)
+#define STV090x_OFFST_Px_ERR_CNT20_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT20_FIELD		8
+
+#define STV090x_Px_FECSPY(__x)				(0xF5A0 - (__x - 1) * 0x200)
+#define STV090x_P1_FECSPY				STV090x_Px_FECSPY(1)
+#define STV090x_P2_FECSPY				STV090x_Px_FECSPY(2)
+#define STV090x_OFFST_Px_SPY_ENABLE_FIELD		7
+#define STV090x_WIDTH_Px_SPY_ENABLE_FIELD		1
+#define STV090x_OFFST_Px_BERMETER_DATAMAODE_FIELD	2
+#define STV090x_WIDTH_Px_BERMETER_DATAMAODE_FIELD	2
+
+#define STV090x_Px_FSPYCFG(__x)				(0xF5A1 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYCFG				STV090x_Px_FSPYCFG(1)
+#define STV090x_P2_FSPYCFG				STV090x_Px_FSPYCFG(2)
+#define STV090x_OFFST_Px_RST_ON_ERROR_FIELD		5
+#define STV090x_WIDTH_Px_RST_ON_ERROR_FIELD		1
+#define STV090x_OFFST_Px_ONE_SHOT_FIELD			4
+#define STV090x_WIDTH_Px_ONE_SHOT_FIELD			1
+#define STV090x_OFFST_Px_I2C_MODE_FIELD			2
+#define STV090x_WIDTH_Px_I2C_MODE_FIELD			2
+
+#define STV090x_Px_FSPYDATA(__x)			(0xF5A2 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYDATA				STV090x_Px_FSPYDATA(1)
+#define STV090x_P2_FSPYDATA				STV090x_Px_FSPYDATA(2)
+#define STV090x_OFFST_Px_SPY_STUFFING_FIELD		7
+#define STV090x_WIDTH_Px_SPY_STUFFING_FIELD		1
+#define STV090x_OFFST_Px_SPY_CNULLPKT_FIELD		5
+#define STV090x_WIDTH_Px_SPY_CNULLPKT_FIELD		1
+#define STV090x_OFFST_Px_SPY_OUTDATA_MODE_FIELD		0
+#define STV090x_WIDTH_Px_SPY_OUTDATA_MODE_FIELD		5
+
+#define STV090x_Px_FSPYOUT(__x)				(0xF5A3 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYOUT				STV090x_Px_FSPYOUT(1)
+#define STV090x_P2_FSPYOUT				STV090x_Px_FSPYOUT(2)
+#define STV090x_OFFST_Px_FSPY_DIRECT_FIELD		7
+#define STV090x_WIDTH_Px_FSPY_DIRECT_FIELD		1
+#define STV090x_OFFST_Px_STUFF_MODE_FIELD		0
+#define STV090x_WIDTH_Px_STUFF_MODE_FIELD		3
+
+#define STV090x_Px_FSTATUS(__x)				(0xF5A4 - (__x - 1) * 0x200)
+#define STV090x_P1_FSTATUS				STV090x_Px_FSTATUS(1)
+#define STV090x_P2_FSTATUS				STV090x_Px_FSTATUS(2)
+#define STV090x_OFFST_Px_SPY_ENDSIM_FIELD		7
+#define STV090x_WIDTH_Px_SPY_ENDSIM_FIELD		1
+#define STV090x_OFFST_Px_VALID_SIM_FIELD		6
+#define STV090x_WIDTH_Px_VALID_SIM_FIELD		1
+#define STV090x_OFFST_Px_FOUND_SIGNAL_FIELD		5
+#define STV090x_WIDTH_Px_FOUND_SIGNAL_FIELD		1
+#define STV090x_OFFST_Px_DSS_SYNCBYTE_FIELD		4
+#define STV090x_WIDTH_Px_DSS_SYNCBYTE_FIELD		1
+#define STV090x_OFFST_Px_RESULT_STATE_FIELD		0
+#define STV090x_WIDTH_Px_RESULT_STATE_FIELD		4
+
+#define STV090x_Px_FBERCPT4(__x)			(0xF5A8 - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT4				STV090x_Px_FBERCPT4(1)
+#define STV090x_P2_FBERCPT4				STV090x_Px_FBERCPT4(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT3(__x)			(0xF5A9 - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT3				STV090x_Px_FBERCPT3(1)
+#define STV090x_P2_FBERCPT3				STV090x_Px_FBERCPT3(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT2(__x)			(0xF5AA - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT2				STV090x_Px_FBERCPT2(1)
+#define STV090x_P2_FBERCPT2				STV090x_Px_FBERCPT2(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT1(__x)			(0xF5AB - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT1				STV090x_Px_FBERCPT1(1)
+#define STV090x_P2_FBERCPT1				STV090x_Px_FBERCPT1(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT0(__x)			(0xF5AC - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT0				STV090x_Px_FBERCPT0(1)
+#define STV090x_P2_FBERCPT0				STV090x_Px_FBERCPT0(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERERRy(__x, __y)			(0xF5AF - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_FBERERR0				STV090x_Px_FBERERRy(1, 0)
+#define STV090x_P1_FBERERR1				STV090x_Px_FBERERRy(1, 1)
+#define STV090x_P1_FBERERR2				STV090x_Px_FBERERRy(1, 2)
+#define STV090x_P2_FBERERR0				STV090x_Px_FBERERRy(2, 0)
+#define STV090x_P2_FBERERR1				STV090x_Px_FBERERRy(2, 1)
+#define STV090x_P2_FBERERR2				STV090x_Px_FBERERRy(2, 2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_ERR_FIELD	0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_ERR_FIELD	8
+
+#define STV090x_Px_FSPYBER(__x)				(0xF5B2 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYBER				STV090x_Px_FSPYBER(1)
+#define STV090x_P2_FSPYBER				STV090x_Px_FSPYBER(2)
+#define STV090x_OFFST_Px_FSPYBER_SYNCBYTE_FIELD		4
+#define STV090x_WIDTH_Px_FSPYBER_SYNCBYTE_FIELD		1
+#define STV090x_OFFST_Px_FSPYBER_UNSYNC_FIELD		3
+#define STV090x_WIDTH_Px_FSPYBER_UNSYNC_FIELD		1
+#define STV090x_OFFST_Px_FSPYBER_CTIME_FIELD		0
+#define STV090x_WIDTH_Px_FSPYBER_CTIME_FIELD		3
+
+#define STV090x_RCCFGH					0xf600
+
+#define STV090x_TSGENERAL				0xF630
+#define STV090x_OFFST_Px_MUXSTREAM_OUT_FIELD		3
+#define STV090x_WIDTH_Px_MUXSTREAM_OUT_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_PERMPARAL_FIELD		1
+#define STV090x_WIDTH_Px_TSFIFO_PERMPARAL_FIELD		2
+
+#define STV090x_TSGENERAL1X				0xf670
+#define STV090x_CFGEXT					0xfa80
+
+#define STV090x_TSTRES0					0xFF11
+#define STV090x_OFFST_FRESFEC_FIELD			7
+#define STV090x_WIDTH_FRESFEC_FIELD			1
+
+#define STV090x_Px_TSTDISRX(__x)			(0xFF67 - (__x - 1) * 0x2)
+#define STV090x_P1_TSTDISRX				STV090x_Px_TSTDISRX(1)
+#define STV090x_P2_TSTDISRX				STV090x_Px_TSTDISRX(2)
+#define STV090x_OFFST_Px_TSTDISRX_SELECT_FIELD		3
+#define STV090x_WIDTH_Px_TSTDISRX_SELECT_FIELD		1
+
+#endif /* __STV090x_REG_H */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,373 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "dvb_frontend.h"
+
+#include "stv6110x_reg.h"
+#include "stv6110x.h"
+#include "stv6110x_priv.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
+
+static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
+{
+	int ret;
+	const struct stv6110x_config *config = stv6110x->config;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{ .addr = config->addr, .flags = 0, 	   .buf = b0, .len = 1 },
+		{ .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+	};
+
+	ret = i2c_transfer(stv6110x->i2c, msg, 2);
+	if (ret != 2) {
+		dprintk(FE_ERROR, 1, "I/O Error");
+		return -EREMOTEIO;
+	}
+	*data = b1[0];
+
+	return 0;
+}
+
+static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
+{
+	int ret;
+	const struct stv6110x_config *config = stv6110x->config;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 };
+
+	ret = i2c_transfer(stv6110x->i2c, &msg, 1);
+	if (ret != 1) {
+		dprintk(FE_ERROR, 1, "I/O Error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int stv6110x_init(struct dvb_frontend *fe)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	int ret;
+	u8 i;
+
+	for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) {
+		ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]);
+		if (ret < 0) {
+			dprintk(FE_ERROR, 1, "Initialization failed");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	u32 rDiv, divider;
+	s32 pVal, pCalc, rDivOpt = 0;
+	u8 i;
+
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
+
+	if (frequency <= 1023000) {
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+		pVal = 40;
+	} else if (frequency <= 1300000) {
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+		pVal = 40;
+	} else if (frequency <= 2046000) {
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+		pVal = 20;
+	} else {
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+		pVal = 20;
+	}
+
+	for (rDiv = 0; rDiv <= 3; rDiv++) {
+		pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
+
+		if ((abs((s32)(pCalc - pVal))) < (abs((s32)(1000 - pVal))))
+			rDivOpt = rDiv;
+	}
+
+	divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
+	divider = (divider + 5) / 10;
+
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
+
+	/* VCO Auto calibration */
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
+
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
+	stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]);
+	stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]);
+	stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
+
+	for (i = 0; i < TRIALS; i++) {
+		stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
+		if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1]))
+				break;
+		msleep(1);
+	}
+
+	return 0;
+}
+
+static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]);
+	stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]);
+
+	*frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]),
+				 STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
+
+	*frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) +
+			     STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1])));
+
+	*frequency >>= 2;
+
+	return 0;
+}
+
+static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	u32 halfbw;
+	u8 i;
+
+	halfbw = bandwidth >> 1;
+
+	if (halfbw > 36000000)
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
+	else if (halfbw < 5000000)
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
+	else
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
+
+
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
+
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
+	stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
+
+	for (i = 0; i < TRIALS; i++) {
+		stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
+		if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1]))
+			break;
+		msleep(1);
+	}
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
+
+	return 0;
+}
+
+static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]);
+	*bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000;
+
+	return 0;
+}
+
+static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	/* setup divider */
+	switch (refclock) {
+	default:
+	case 1:
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
+		break;
+	case 2:
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
+		break;
+	case 4:
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
+		break;
+	case 8:
+	case 0:
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
+		break;
+	}
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
+
+	return 0;
+}
+
+static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]);
+	*gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]);
+
+	return 0;
+}
+
+static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
+
+	return 0;
+}
+
+static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	int ret;
+
+	switch (mode) {
+	case TUNER_SLEEP:
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0);
+		break;
+
+	case TUNER_WAKE:
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1);
+		STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1);
+		break;
+	}
+
+	ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
+	if (ret < 0) {
+		dprintk(FE_ERROR, 1, "I/O Error");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int stv6110x_sleep(struct dvb_frontend *fe)
+{
+	return stv6110x_set_mode(fe, TUNER_SLEEP);
+}
+
+static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
+
+	if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1]))
+		*status = TUNER_PHASELOCKED;
+	else
+		*status = 0;
+
+	return 0;
+}
+
+
+static int stv6110x_release(struct dvb_frontend *fe)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(stv6110x);
+
+	return 0;
+}
+
+static struct dvb_tuner_ops stv6110x_ops = {
+	.info = {
+		.name		= "STV6110(A) Silicon Tuner",
+		.frequency_min	=  950000,
+		.frequency_max	= 2150000,
+		.frequency_step	= 0,
+	},
+
+	.init			= stv6110x_init,
+	.sleep          	= stv6110x_sleep,
+	.release		= stv6110x_release
+};
+
+static struct stv6110x_devctl stv6110x_ctl = {
+	.tuner_init		= stv6110x_init,
+	.tuner_set_mode		= stv6110x_set_mode,
+	.tuner_set_frequency	= stv6110x_set_frequency,
+	.tuner_get_frequency	= stv6110x_get_frequency,
+	.tuner_set_bandwidth	= stv6110x_set_bandwidth,
+	.tuner_get_bandwidth	= stv6110x_get_bandwidth,
+	.tuner_set_bbgain	= stv6110x_set_bbgain,
+	.tuner_get_bbgain	= stv6110x_get_bbgain,
+	.tuner_set_refclk	= stv6110x_set_refclock,
+	.tuner_get_status	= stv6110x_get_status,
+};
+
+struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+					const struct stv6110x_config *config,
+					struct i2c_adapter *i2c)
+{
+	struct stv6110x_state *stv6110x;
+
+	stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
+	if (stv6110x == NULL)
+		goto error;
+
+	stv6110x->i2c		= i2c;
+	stv6110x->config	= config;
+	stv6110x->devctl	= &stv6110x_ctl;
+
+	fe->tuner_priv		= stv6110x;
+	fe->ops.tuner_ops	= stv6110x_ops;
+
+	printk("%s: Attaching STV6110x \n", __func__);
+	return stv6110x->devctl;
+
+error:
+	kfree(stv6110x);
+	return NULL;
+}
+EXPORT_SYMBOL(stv6110x_attach);
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STV6110x Silicon tuner");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,71 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __STV6110x_H
+#define __STV6110x_H
+
+struct stv6110x_config {
+	u8	addr;
+	u32	refclk;
+};
+
+enum tuner_mode {
+	TUNER_SLEEP = 1,
+	TUNER_WAKE,
+};
+
+enum tuner_status {
+	TUNER_PHASELOCKED = 1,
+};
+
+struct stv6110x_devctl {
+	int (*tuner_init) (struct dvb_frontend *fe);
+	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+	int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+	int (*tuner_set_refclk)  (struct dvb_frontend *fe, u32 refclk);
+	int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+};
+
+
+#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE))
+
+extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+					       const struct stv6110x_config *config,
+					       struct i2c_adapter *i2c);
+
+#else
+static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+						      const struct stv6110x_config *config,
+						      struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_STV6110x */
+
+#endif /* __STV6110x_H */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x_priv.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x_priv.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x_priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x_priv.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,75 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __STV6110x_PRIV_H
+#define __STV6110x_PRIV_H
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(__y, __z, format, arg...) do {						\
+	if (__z) {									\
+		if	((verbose > FE_ERROR) && (verbose > __y))			\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((verbose > FE_INFO) && (verbose > __y))			\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (verbose > __y)							\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+
+#define STV6110x_SETFIELD(mask, bitf, val)				\
+	(mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) <<	\
+				  STV6110x_OFFST_##bitf))) | 		\
+			  (val << STV6110x_OFFST_##bitf))
+
+#define STV6110x_GETFIELD(bitf, val)					\
+	((val >> STV6110x_OFFST_##bitf) & 				\
+	((1 << STV6110x_WIDTH_##bitf) - 1))
+
+#define MAKEWORD16(a, b)			(((a) << 8) | (b))
+
+#define LSB(x)					((x & 0xff))
+#define MSB(y)					((y >> 8) & 0xff)
+
+#define TRIALS					10
+#define R_DIV(__div)				(1 << (__div + 1))
+#define REFCLOCK_kHz				(stv6110x->config->refclk /    1000)
+#define REFCLOCK_MHz				(stv6110x->config->refclk / 1000000)
+
+struct stv6110x_state {
+	struct i2c_adapter		*i2c;
+	const struct stv6110x_config	*config;
+
+	struct stv6110x_devctl		*devctl;
+};
+
+#endif /* __STV6110x_PRIV_H */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x_reg.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x_reg.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/stv6110x_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/stv6110x_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __STV6110x_REG_H
+#define __STV6110x_REG_H
+
+#define STV6110x_CTRL1				0x00
+#define STV6110x_OFFST_CTRL1_K			3
+#define STV6110x_WIDTH_CTRL1_K			5
+#define STV6110x_OFFST_CTRL1_LPT		2
+#define STV6110x_WIDTH_CTRL1_LPT		1
+#define STV6110x_OFFST_CTRL1_RX			1
+#define STV6110x_WIDTH_CTRL1_RX			1
+#define STV6110x_OFFST_CTRL1_SYN		0
+#define STV6110x_WIDTH_CTRL1_SYN		1
+
+#define STV6110x_CTRL2				0x01
+#define STV6110x_OFFST_CTRL2_CO_DIV		6
+#define STV6110x_WIDTH_CTRL2_CO_DIV		2
+#define STV6110x_OFFST_CTRL2_RSVD		5
+#define STV6110x_WIDTH_CTRL2_RSVD		1
+#define STV6110x_OFFST_CTRL2_REFOUT_SEL		4
+#define STV6110x_WIDTH_CTRL2_REFOUT_SEL		1
+#define STV6110x_OFFST_CTRL2_BBGAIN		0
+#define STV6110x_WIDTH_CTRL2_BBGAIN		4
+
+#define STV6110x_TNG0				0x02
+#define STV6110x_OFFST_TNG0_N_DIV_7_0		0
+#define STV6110x_WIDTH_TNG0_N_DIV_7_0		8
+
+#define STV6110x_TNG1				0x03
+#define STV6110x_OFFST_TNG1_R_DIV		6
+#define STV6110x_WIDTH_TNG1_R_DIV		2
+#define STV6110x_OFFST_TNG1_PRESC32_ON		5
+#define STV6110x_WIDTH_TNG1_PRESC32_ON		1
+#define STV6110x_OFFST_TNG1_DIV4SEL		4
+#define STV6110x_WIDTH_TNG1_DIV4SEL		1
+#define STV6110x_OFFST_TNG1_N_DIV_11_8		0
+#define STV6110x_WIDTH_TNG1_N_DIV_11_8		4
+
+
+#define STV6110x_CTRL3				0x04
+#define STV6110x_OFFST_CTRL3_DCLOOP_OFF		7
+#define STV6110x_WIDTH_CTRL3_DCLOOP_OFF		1
+#define STV6110x_OFFST_CTRL3_RCCLK_OFF		6
+#define STV6110x_WIDTH_CTRL3_RCCLK_OFF		1
+#define STV6110x_OFFST_CTRL3_ICP		5
+#define STV6110x_WIDTH_CTRL3_ICP		1
+#define STV6110x_OFFST_CTRL3_CF			0
+#define STV6110x_WIDTH_CTRL3_CF			5
+
+#define STV6110x_STAT1				0x05
+#define STV6110x_OFFST_STAT1_CALVCO_STRT	2
+#define STV6110x_WIDTH_STAT1_CALVCO_STRT	1
+#define STV6110x_OFFST_STAT1_CALRC_STRT		1
+#define STV6110x_WIDTH_STAT1_CALRC_STRT		1
+#define STV6110x_OFFST_STAT1_LOCK		0
+#define STV6110x_WIDTH_STAT1_LOCK		1
+
+#define STV6110x_STAT2				0x06
+#define STV6110x_STAT3				0x07
+
+#endif /* __STV6110x_REG_H */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10021.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10021.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10021.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10021.c	2009-09-09 18:13:59.000000000 -0400
@@ -413,7 +413,7 @@
 	u8 id;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tda10021_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10048.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10048.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10048.c	2012-03-22 19:12:46.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10048.c	2012-03-22 20:09:03.000000000 -0400
@@ -1,7 +1,7 @@
 /*
     NXP TDA10048HN DVB OFDM demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
+    Copyright (C) 2009 Steven Toth <stoth@kernellabs.com>
 
     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
@@ -25,6 +25,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <asm/div64.h>
 #include "dvb_frontend.h"
 #include "dvb_math.h"
 #include "tda10048.h"
@@ -138,11 +139,20 @@
 
 	struct i2c_adapter *i2c;
 
-	/* configuration settings */
-	const struct tda10048_config *config;
+	/* We'll cache and update the attach config settings */
+	struct tda10048_config config;
 	struct dvb_frontend frontend;
 
 	int fwloaded;
+
+	u32 freq_if_hz;
+	u32 xtal_hz;
+	u32 pll_mfactor;
+	u32 pll_nfactor;
+	u32 pll_pfactor;
+	u32 sample_freq;
+
+	enum fe_bandwidth bandwidth;
 };
 
 static struct init_tab {
@@ -192,12 +202,27 @@
 	{ TDA10048_CONF_C4_2, 0x04 },
 };
 
+static struct pll_tab {
+	u32	clk_freq_khz;
+	u32	if_freq_khz;
+	u8	m, n, p;
+} pll_tab[] = {
+	{ TDA10048_CLK_4000,  TDA10048_IF_36130, 10, 0, 0 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3300,  10, 3, 0 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3500,  10, 3, 0 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3800,  10, 3, 0 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4000,  10, 3, 0 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4300,  10, 3, 0 },
+	{ TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
+};
+
 static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
 {
+	struct tda10048_config *config = &state->config;
 	int ret;
 	u8 buf[] = { reg, data };
 	struct i2c_msg msg = {
-		.addr = state->config->demod_address,
+		.addr = config->demod_address,
 		.flags = 0, .buf = buf, .len = 2 };
 
 	dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
@@ -212,13 +237,14 @@
 
 static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
 {
+	struct tda10048_config *config = &state->config;
 	int ret;
 	u8 b0[] = { reg };
 	u8 b1[] = { 0 };
 	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address,
+		{ .addr = config->demod_address,
 			.flags = 0, .buf = b0, .len = 1 },
-		{ .addr = state->config->demod_address,
+		{ .addr = config->demod_address,
 			.flags = I2C_M_RD, .buf = b1, .len = 1 } };
 
 	dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
@@ -235,6 +261,7 @@
 static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
 				 const u8 *data, u16 len)
 {
+	struct tda10048_config *config = &state->config;
 	int ret = -EREMOTEIO;
 	struct i2c_msg msg;
 	u8 *buf;
@@ -250,7 +277,7 @@
 	*buf = reg;
 	memcpy(buf + 1, data, len);
 
-	msg.addr = state->config->demod_address;
+	msg.addr = config->demod_address;
 	msg.flags = 0;
 	msg.buf = buf;
 	msg.len = len + 1;
@@ -271,14 +298,206 @@
 	return ret;
 }
 
+static int tda10048_set_phy2(struct dvb_frontend *fe, u32 sample_freq_hz,
+			     u32 if_hz)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u64 t;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (sample_freq_hz == 0)
+		return -EINVAL;
+
+	if (if_hz < (sample_freq_hz / 2)) {
+		/* PHY2 = (if2/fs) * 2^15 */
+		t = if_hz;
+		t *= 10;
+		t *= 32768;
+		do_div(t, sample_freq_hz);
+		t += 5;
+		do_div(t, 10);
+	} else {
+		/* PHY2 = ((IF1-fs)/fs) * 2^15 */
+		t = sample_freq_hz - if_hz;
+		t *= 10;
+		t *= 32768;
+		do_div(t, sample_freq_hz);
+		t += 5;
+		do_div(t, 10);
+		t = ~t + 1;
+	}
+
+	tda10048_writereg(state, TDA10048_FREQ_PHY2_LSB, (u8)t);
+	tda10048_writereg(state, TDA10048_FREQ_PHY2_MSB, (u8)(t >> 8));
+
+	return 0;
+}
+
+static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz,
+			     u32 bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u64 t, z;
+	u32 b = 8000000;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (sample_freq_hz == 0)
+		return -EINVAL;
+
+	if (bw == BANDWIDTH_6_MHZ)
+		b = 6000000;
+	else
+	if (bw == BANDWIDTH_7_MHZ)
+		b = 7000000;
+
+	/* WREF = (B / (7 * fs)) * 2^31 */
+	t = b * 10;
+	/* avoid warning: this decimal constant is unsigned only in ISO C90 */
+	/* t *= 2147483648 on 32bit platforms */
+	t *= (2048 * 1024);
+	t *= 1024;
+	z = 7 * sample_freq_hz;
+	do_div(t, z);
+	t += 5;
+	do_div(t, 10);
+
+	tda10048_writereg(state, TDA10048_TIME_WREF_LSB, (u8)t);
+	tda10048_writereg(state, TDA10048_TIME_WREF_MID1, (u8)(t >> 8));
+	tda10048_writereg(state, TDA10048_TIME_WREF_MID2, (u8)(t >> 16));
+	tda10048_writereg(state, TDA10048_TIME_WREF_MSB, (u8)(t >> 24));
+
+	return 0;
+}
+
+static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
+				u32 bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u64 t;
+	u32 b = 8000000;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (sample_freq_hz == 0)
+		return -EINVAL;
+
+	if (bw == BANDWIDTH_6_MHZ)
+		b = 6000000;
+	else
+	if (bw == BANDWIDTH_7_MHZ)
+		b = 7000000;
+
+	/* INVWREF = ((7 * fs) / B) * 2^5 */
+	t = sample_freq_hz;
+	t *= 7;
+	t *= 32;
+	t *= 10;
+	do_div(t, b);
+	t += 5;
+	do_div(t, 10);
+
+	tda10048_writereg(state, TDA10048_TIME_INVWREF_LSB, (u8)t);
+	tda10048_writereg(state, TDA10048_TIME_INVWREF_MSB, (u8)(t >> 8));
+
+	return 0;
+}
+
+static int tda10048_set_bandwidth(struct dvb_frontend *fe,
+	enum fe_bandwidth bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	dprintk(1, "%s(bw=%d)\n", __func__, bw);
+
+	/* Bandwidth setting may need to be adjusted */
+	switch (bw) {
+	case BANDWIDTH_6_MHZ:
+	case BANDWIDTH_7_MHZ:
+	case BANDWIDTH_8_MHZ:
+		tda10048_set_wref(fe, state->sample_freq, bw);
+		tda10048_set_invwref(fe, state->sample_freq, bw);
+		break;
+	default:
+		printk(KERN_ERR "%s() invalid bandwidth\n", __func__);
+		return -EINVAL;
+	}
+
+	state->bandwidth = bw;
+
+	return 0;
+}
+
+static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
+	int i;
+	u32 if_freq_khz;
+
+	dprintk(1, "%s(bw = %d)\n", __func__, bw);
+
+	/* based on target bandwidth and clk we calculate pll factors */
+	switch (bw) {
+	case BANDWIDTH_6_MHZ:
+		if_freq_khz = config->dtv6_if_freq_khz;
+		break;
+	case BANDWIDTH_7_MHZ:
+		if_freq_khz = config->dtv7_if_freq_khz;
+		break;
+	case BANDWIDTH_8_MHZ:
+		if_freq_khz = config->dtv8_if_freq_khz;
+		break;
+	default:
+		printk(KERN_ERR "%s() no default\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pll_tab); i++) {
+		if ((pll_tab[i].clk_freq_khz == config->clk_freq_khz) &&
+			(pll_tab[i].if_freq_khz == if_freq_khz)) {
+
+			state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
+			state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
+			state->pll_mfactor = pll_tab[i].m;
+			state->pll_nfactor = pll_tab[i].n;
+			state->pll_pfactor = pll_tab[i].p;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(pll_tab)) {
+		printk(KERN_ERR "%s() Incorrect attach settings\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz);
+	dprintk(1, "- xtal_hz = %d\n", state->xtal_hz);
+	dprintk(1, "- pll_mfactor = %d\n", state->pll_mfactor);
+	dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor);
+	dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor);
+
+	/* Calculate the sample frequency */
+	state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45);
+	state->sample_freq /= (state->pll_nfactor + 1);
+	state->sample_freq /= (state->pll_pfactor + 4);
+	dprintk(1, "- sample_freq = %d\n", state->sample_freq);
+
+	/* Update the I/F */
+	tda10048_set_phy2(fe, state->sample_freq, state->freq_if_hz);
+
+	return 0;
+}
+
 static int tda10048_firmware_upload(struct dvb_frontend *fe)
 {
 	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
 	const struct firmware *fw;
 	int ret;
 	int pos = 0;
 	int cnt;
-	u8 wlen = state->config->fwbulkwritelen;
+	u8 wlen = config->fwbulkwritelen;
 
 	if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
 		wlen = TDA10048_BULKWRITE_200;
@@ -289,7 +508,7 @@
 		"/*(DEBLOBBED)*/");
 
 	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
-		&state->i2c->dev);
+		state->i2c->dev.parent);
 	if (ret) {
 		printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
 			__func__);
@@ -484,8 +703,12 @@
 static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
 	dprintk(1, "%s(%d)\n", __func__, enable);
 
+	if (config->disable_gate_access)
+		return 0;
+
 	if (enable)
 		return tda10048_writereg(state, TDA10048_CONF_C4_1,
 			tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
@@ -523,6 +746,12 @@
 
 	dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
 
+	/* Update the I/F pll's if the bandwidth changes */
+	if (p->u.ofdm.bandwidth != state->bandwidth) {
+		tda10048_set_if(fe, p->u.ofdm.bandwidth);
+		tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth);
+	}
+
 	if (fe->ops.tuner_ops.set_params) {
 
 		if (fe->ops.i2c_gate_ctrl)
@@ -544,6 +773,7 @@
 static int tda10048_init(struct dvb_frontend *fe)
 {
 	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
 	int ret = 0, i;
 
 	dprintk(1, "%s()\n", __func__);
@@ -556,10 +786,14 @@
 		ret = tda10048_firmware_upload(fe);
 
 	/* Set either serial or parallel */
-	tda10048_output_mode(fe, state->config->output_mode);
+	tda10048_output_mode(fe, config->output_mode);
 
-	/* set inversion */
-	tda10048_set_inversion(fe, state->config->inversion);
+	/* Set inversion */
+	tda10048_set_inversion(fe, config->inversion);
+
+	/* Establish default RF values */
+	tda10048_set_if(fe, BANDWIDTH_8_MHZ);
+	tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ);
 
 	/* Ensure we leave the gate closed */
 	tda10048_i2c_gate_ctrl(fe, 0);
@@ -812,6 +1046,45 @@
 	kfree(state);
 }
 
+static void tda10048_establish_defaults(struct dvb_frontend *fe)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
+
+	/* Validate/default the config */
+	if (config->dtv6_if_freq_khz == 0) {
+		config->dtv6_if_freq_khz = TDA10048_IF_4300;
+		printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->dtv6_if_freq_khz);
+	}
+
+	if (config->dtv7_if_freq_khz == 0) {
+		config->dtv7_if_freq_khz = TDA10048_IF_4300;
+		printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->dtv7_if_freq_khz);
+	}
+
+	if (config->dtv8_if_freq_khz == 0) {
+		config->dtv8_if_freq_khz = TDA10048_IF_4300;
+		printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->dtv8_if_freq_khz);
+	}
+
+	if (config->clk_freq_khz == 0) {
+		config->clk_freq_khz = TDA10048_CLK_16000;
+		printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->clk_freq_khz);
+	}
+}
+
 static struct dvb_frontend_ops tda10048_ops;
 
 struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
@@ -822,14 +1095,15 @@
 	dprintk(1, "%s()\n", __func__);
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tda10048_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
-	/* setup the state */
-	state->config = config;
+	/* setup the state and clone the config */
+	memcpy(&state->config, config, sizeof(*config));
 	state->i2c = i2c;
 	state->fwloaded = 0;
+	state->bandwidth = BANDWIDTH_8_MHZ;
 
 	/* check if the demod is present */
 	if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
@@ -840,6 +1114,17 @@
 		sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
+	/* Establish any defaults the the user didn't pass */
+	tda10048_establish_defaults(&state->frontend);
+
+	/* Set the xtal and freq defaults */
+	if (tda10048_set_if(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+		goto error;
+
+	/* Default bandwidth */
+	if (tda10048_set_bandwidth(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+		goto error;
+
 	/* Leave the gate closed */
 	tda10048_i2c_gate_ctrl(&state->frontend, 0);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10048.h linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10048.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10048.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10048.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
     NXP TDA10048HN DVB OFDM demodulator driver
 
-    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
+    Copyright (C) 2009 Steven Toth <stoth@kernellabs.com>
 
     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
@@ -43,6 +43,25 @@
 #define TDA10048_INVERSION_OFF 0
 #define TDA10048_INVERSION_ON  1
 	u8 inversion;
+
+#define TDA10048_IF_3300  3300
+#define TDA10048_IF_3500  3500
+#define TDA10048_IF_3800  3800
+#define TDA10048_IF_4000  4000
+#define TDA10048_IF_4300  4300
+#define TDA10048_IF_4500  4500
+#define TDA10048_IF_4750  4750
+#define TDA10048_IF_36130 36130
+	u16 dtv6_if_freq_khz;
+	u16 dtv7_if_freq_khz;
+	u16 dtv8_if_freq_khz;
+
+#define TDA10048_CLK_4000  4000
+#define TDA10048_CLK_16000 16000
+	u16 clk_freq_khz;
+
+	/* Disable I2C gate access */
+	u8 disable_gate_access;
 };
 
 #if defined(CONFIG_DVB_TDA10048) || \
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda1004x.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda1004x.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda1004x.c	2012-03-22 19:12:49.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda1004x.c	2012-03-22 20:09:05.000000000 -0400
@@ -1261,7 +1261,7 @@
 	int id;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
 	if (!state) {
 		printk(KERN_ERR "Can't alocate memory for tda10045 state\n");
 		return NULL;
@@ -1331,7 +1331,7 @@
 	int id;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
 	if (!state) {
 		printk(KERN_ERR "Can't alocate memory for tda10046 state\n");
 		return NULL;
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10086.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10086.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda10086.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda10086.c	2009-09-09 18:13:59.000000000 -0400
@@ -745,7 +745,7 @@
 	dprintk ("%s\n", __func__);
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tda10086_state), GFP_KERNEL);
 	if (!state)
 		return NULL;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda8083.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda8083.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/tda8083.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/tda8083.c	2009-09-09 18:13:59.000000000 -0400
@@ -417,7 +417,7 @@
 	struct tda8083_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct tda8083_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/ves1820.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/ves1820.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/ves1820.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/ves1820.c	2009-09-09 18:13:59.000000000 -0400
@@ -374,7 +374,7 @@
 	struct ves1820_state* state = NULL;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct ves1820_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/ves1x93.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/ves1x93.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/ves1x93.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/ves1x93.c	2009-09-09 18:13:59.000000000 -0400
@@ -456,7 +456,7 @@
 	u8 identity;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
 	/* setup the state */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/zl10353.c linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/zl10353.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/frontends/zl10353.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/frontends/zl10353.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,7 +98,6 @@
 static void zl10353_dump_regs(struct dvb_frontend *fe)
 {
 	struct zl10353_state *state = fe->demodulator_priv;
-	char buf[52], buf2[4];
 	int ret;
 	u8 reg;
 
@@ -106,19 +105,18 @@
 	for (reg = 0; ; reg++) {
 		if (reg % 16 == 0) {
 			if (reg)
-				printk(KERN_DEBUG "%s\n", buf);
-			sprintf(buf, "%02x: ", reg);
+				printk(KERN_CONT "\n");
+			printk(KERN_DEBUG "%02x:", reg);
 		}
 		ret = zl10353_read_register(state, reg);
 		if (ret >= 0)
-			sprintf(buf2, "%02x ", (u8)ret);
+			printk(KERN_CONT " %02x", (u8)ret);
 		else
-			strcpy(buf2, "-- ");
-		strcat(buf, buf2);
+			printk(KERN_CONT " --");
 		if (reg == 0xff)
 			break;
 	}
-	printk(KERN_DEBUG "%s\n", buf);
+	printk(KERN_CONT "\n");
 }
 
 static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/Kconfig linux-libre-2.6.31-gnu/drivers/media/dvb/siano/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -2,25 +2,33 @@
 # Siano Mobile Silicon Digital TV device configuration
 #
 
-config DVB_SIANO_SMS1XXX
-	tristate "Siano SMS1XXX USB dongle support"
-	depends on DVB_CORE && USB
+config SMS_SIANO_MDTV
+	tristate "Siano SMS1xxx based MDTV receiver"
+	depends on DVB_CORE && INPUT
 	---help---
-	  Choose Y here if you have a USB dongle with a SMS1XXX chipset.
+	  Choose Y or M here if you have MDTV receiver with a Siano chipset.
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called sms1xxx.
+	  To compile this driver as a module, choose M here
+	  (The module will be called smsmdtv).
 
-config DVB_SIANO_SMS1XXX_SMS_IDS
-	bool "Enable support for Siano Mobile Silicon default USB IDs"
-	depends on DVB_SIANO_SMS1XXX
-	default y
-	---help---
-	  Choose Y here if you have a USB dongle with a SMS1XXX chipset
-	  that uses Siano Mobile Silicon's default usb vid:pid.
+	  Further documentation on this driver can be found on the WWW
+	  at http://www.siano-ms.com/
 
-	  Choose N here if you would prefer to use Siano's external driver.
+if SMS_SIANO_MDTV
+menu "Siano module components"
 
-	  Further documentation on this driver can be found on the WWW at
-	  <http://www.siano-ms.com/>.
+# Hardware interfaces support
+
+config SMS_USB_DRV
+	tristate "USB interface support"
+	depends on DVB_CORE && USB
+	---help---
+	  Choose if you would like to have Siano's support for USB interface
 
+config SMS_SDIO_DRV
+	tristate "SDIO interface support"
+	depends on DVB_CORE && MMC
+	---help---
+	  Choose if you would like to have Siano's support for SDIO interface
+endmenu
+endif # SMS_SIANO_MDTV
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/Makefile linux-libre-2.6.31-gnu/drivers/media/dvb/siano/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,8 +1,9 @@
-sms1xxx-objs := smscoreapi.o sms-cards.o
 
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o
+smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
+
+obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
+obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
+obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/sms-cards.c linux-libre-2.6.31-gnu/drivers/media/dvb/siano/sms-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/sms-cards.c	2012-03-22 19:13:04.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/sms-cards.c	2012-03-22 20:09:19.000000000 -0400
@@ -18,6 +18,7 @@
  */
 
 #include "sms-cards.h"
+#include "smsir.h"
 
 static int sms_dbg;
 module_param_named(cards_dbg, sms_dbg, int, 0644);
@@ -30,17 +31,14 @@
 	[SMS1XXX_BOARD_SIANO_STELLAR] = {
 		.name	= "Siano Stellar Digital Receiver",
 		.type	= SMS_STELLAR,
-		.fw[DEVICE_MODE_DVBT_BDA] = "/*(DEBLOBBED)*/",
 	},
 	[SMS1XXX_BOARD_SIANO_NOVA_A] = {
 		.name	= "Siano Nova A Digital Receiver",
 		.type	= SMS_NOVA_A0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "/*(DEBLOBBED)*/",
 	},
 	[SMS1XXX_BOARD_SIANO_NOVA_B] = {
 		.name	= "Siano Nova B Digital Receiver",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "/*(DEBLOBBED)*/",
 	},
 	[SMS1XXX_BOARD_SIANO_VEGA] = {
 		.name	= "Siano Vega Digital Receiver",
@@ -65,6 +63,9 @@
 		.name	= "Hauppauge WinTV MiniStick",
 		.type	= SMS_NOVA_B0,
 		.fw[DEVICE_MODE_DVBT_BDA] = "/*(DEBLOBBED)*/",
+		.board_cfg.leds_power = 26,
+		.board_cfg.led0 = 27,
+		.board_cfg.led1 = 28,
 		.led_power = 26,
 		.led_lo    = 27,
 		.led_hi    = 28,
@@ -74,7 +75,9 @@
 		.type	= SMS_NOVA_B0,
 		.fw[DEVICE_MODE_DVBT_BDA] = "/*(DEBLOBBED)*/",
 		.lna_ctrl  = 29,
+		.board_cfg.foreign_lna0_ctrl = 29,
 		.rf_switch = 17,
+		.board_cfg.rf_switch_uhf = 17,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
 		.name	= "Hauppauge WinTV MiniCard",
@@ -82,6 +85,16 @@
 		.fw[DEVICE_MODE_DVBT_BDA] = "/*(DEBLOBBED)*/",
 		.lna_ctrl  = -1,
 	},
+	[SMS1XXX_BOARD_SIANO_NICE] = {
+	/* 11 */
+		.name = "Siano Nice Digital Receiver",
+		.type = SMS_NOVA_B0,
+	},
+	[SMS1XXX_BOARD_SIANO_VENICE] = {
+	/* 12 */
+		.name = "Siano Venice Digital Receiver",
+		.type = SMS_VEGA,
+	},
 };
 
 struct sms_board *sms_get_board(int id)
@@ -91,12 +104,77 @@
 	return &sms_boards[id];
 }
 EXPORT_SYMBOL_GPL(sms_get_board);
+static inline void sms_gpio_assign_11xx_default_led_config(
+		struct smscore_gpio_config *pGpioConfig) {
+	pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
+	pGpioConfig->InputCharacteristics =
+		SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
+	pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
+	pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
+	pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
+}
+
+int sms_board_event(struct smscore_device_t *coredev,
+		enum SMS_BOARD_EVENTS gevent) {
+	struct smscore_gpio_config MyGpioConfig;
+
+	sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
+
+	switch (gevent) {
+	case BOARD_EVENT_POWER_INIT: /* including hotplug */
+		break; /* BOARD_EVENT_BIND */
+
+	case BOARD_EVENT_POWER_SUSPEND:
+		break; /* BOARD_EVENT_POWER_SUSPEND */
+
+	case BOARD_EVENT_POWER_RESUME:
+		break; /* BOARD_EVENT_POWER_RESUME */
+
+	case BOARD_EVENT_BIND:
+		break; /* BOARD_EVENT_BIND */
+
+	case BOARD_EVENT_SCAN_PROG:
+		break; /* BOARD_EVENT_SCAN_PROG */
+	case BOARD_EVENT_SCAN_COMP:
+		break; /* BOARD_EVENT_SCAN_COMP */
+	case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL:
+		break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */
+	case BOARD_EVENT_FE_LOCK:
+		break; /* BOARD_EVENT_FE_LOCK */
+	case BOARD_EVENT_FE_UNLOCK:
+		break; /* BOARD_EVENT_FE_UNLOCK */
+	case BOARD_EVENT_DEMOD_LOCK:
+		break; /* BOARD_EVENT_DEMOD_LOCK */
+	case BOARD_EVENT_DEMOD_UNLOCK:
+		break; /* BOARD_EVENT_DEMOD_UNLOCK */
+	case BOARD_EVENT_RECEPTION_MAX_4:
+		break; /* BOARD_EVENT_RECEPTION_MAX_4 */
+	case BOARD_EVENT_RECEPTION_3:
+		break; /* BOARD_EVENT_RECEPTION_3 */
+	case BOARD_EVENT_RECEPTION_2:
+		break; /* BOARD_EVENT_RECEPTION_2 */
+	case BOARD_EVENT_RECEPTION_1:
+		break; /* BOARD_EVENT_RECEPTION_1 */
+	case BOARD_EVENT_RECEPTION_LOST_0:
+		break; /* BOARD_EVENT_RECEPTION_LOST_0 */
+	case BOARD_EVENT_MULTIPLEX_OK:
+		break; /* BOARD_EVENT_MULTIPLEX_OK */
+	case BOARD_EVENT_MULTIPLEX_ERRORS:
+		break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
+
+	default:
+		sms_err("Unknown SMS board event");
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sms_board_event);
 
 static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
 {
 	int lvl, ret;
 	u32 gpio;
-	struct smscore_gpio_config gpioconfig = {
+	struct smscore_config_gpio gpioconfig = {
 		.direction            = SMS_GPIO_DIRECTION_OUTPUT,
 		.pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
 		.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/sms-cards.h linux-libre-2.6.31-gnu/drivers/media/dvb/siano/sms-cards.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/sms-cards.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/sms-cards.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 
 #include <linux/usb.h>
 #include "smscoreapi.h"
+#include "smsir.h"
 
 #define SMS_BOARD_UNKNOWN 0
 #define SMS1XXX_BOARD_SIANO_STELLAR 1
@@ -34,10 +35,47 @@
 #define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9
 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
+#define SMS1XXX_BOARD_SIANO_NICE	11
+#define SMS1XXX_BOARD_SIANO_VENICE	12
+
+struct sms_board_gpio_cfg {
+	int lna_vhf_exist;
+	int lna_vhf_ctrl;
+	int lna_uhf_exist;
+	int lna_uhf_ctrl;
+	int lna_uhf_d_ctrl;
+	int lna_sband_exist;
+	int lna_sband_ctrl;
+	int lna_sband_d_ctrl;
+	int foreign_lna0_ctrl;
+	int foreign_lna1_ctrl;
+	int foreign_lna2_ctrl;
+	int rf_switch_vhf;
+	int rf_switch_uhf;
+	int rf_switch_sband;
+	int leds_power;
+	int led0;
+	int led1;
+	int led2;
+	int led3;
+	int led4;
+	int ir;
+	int eeprom_wp;
+	int mrc_sense;
+	int mrc_pdn_resetn;
+	int mrc_gp0; /* mrcs spi int */
+	int mrc_gp1;
+	int mrc_gp2;
+	int mrc_gp3;
+	int mrc_gp4;
+	int host_spi_gsp_ts_int;
+};
 
 struct sms_board {
 	enum sms_device_type_st type;
 	char *name, *fw[DEVICE_MODE_MAX];
+	struct sms_board_gpio_cfg board_cfg;
+	enum ir_kb_type ir_kb_type;
 
 	/* gpios */
 	int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
@@ -45,6 +83,32 @@
 
 struct sms_board *sms_get_board(int id);
 
+extern struct smscore_device_t *coredev;
+
+enum SMS_BOARD_EVENTS {
+	BOARD_EVENT_POWER_INIT,
+	BOARD_EVENT_POWER_SUSPEND,
+	BOARD_EVENT_POWER_RESUME,
+	BOARD_EVENT_BIND,
+	BOARD_EVENT_SCAN_PROG,
+	BOARD_EVENT_SCAN_COMP,
+	BOARD_EVENT_EMERGENCY_WARNING_SIGNAL,
+	BOARD_EVENT_FE_LOCK,
+	BOARD_EVENT_FE_UNLOCK,
+	BOARD_EVENT_DEMOD_LOCK,
+	BOARD_EVENT_DEMOD_UNLOCK,
+	BOARD_EVENT_RECEPTION_MAX_4,
+	BOARD_EVENT_RECEPTION_3,
+	BOARD_EVENT_RECEPTION_2,
+	BOARD_EVENT_RECEPTION_1,
+	BOARD_EVENT_RECEPTION_LOST_0,
+	BOARD_EVENT_MULTIPLEX_OK,
+	BOARD_EVENT_MULTIPLEX_ERRORS
+};
+
+int sms_board_event(struct smscore_device_t *coredev,
+		enum SMS_BOARD_EVENTS gevent);
+
 int sms_board_setup(struct smscore_device_t *coredev);
 
 #define SMS_LED_OFF 0
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smscoreapi.c linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smscoreapi.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smscoreapi.c	2012-03-22 19:12:59.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smscoreapi.c	2012-03-22 20:09:17.000000000 -0400
@@ -30,9 +30,13 @@
 #include <linux/io.h>
 
 #include <linux/firmware.h>
+#include <linux/wait.h>
+#include <asm/byteorder.h>
 
 #include "smscoreapi.h"
 #include "sms-cards.h"
+#include "smsir.h"
+#include "smsendian.h"
 
 static int sms_dbg;
 module_param_named(debug, sms_dbg, int, 0644);
@@ -58,42 +62,6 @@
 	onremove_t		onremove_handler;
 };
 
-struct smscore_device_t {
-	struct list_head entry;
-
-	struct list_head clients;
-	struct list_head subclients;
-	spinlock_t		clientslock;
-
-	struct list_head buffers;
-	spinlock_t		bufferslock;
-	int				num_buffers;
-
-	void			*common_buffer;
-	int				common_buffer_size;
-	dma_addr_t		common_buffer_phys;
-
-	void			*context;
-	struct device	*device;
-
-	char			devpath[32];
-	unsigned long	device_flags;
-
-	setmode_t		setmode_handler;
-	detectmode_t	detectmode_handler;
-	sendrequest_t	sendrequest_handler;
-	preload_t		preload_handler;
-	postload_t		postload_handler;
-
-	int				mode, modes_supported;
-
-	struct completion version_ex_done, data_download_done, trigger_done;
-	struct completion init_device_done, reload_start_done, resume_done;
-
-	int board_id;
-	int led_state;
-};
-
 void smscore_set_board_id(struct smscore_device_t *core, int id)
 {
 	core->board_id = id;
@@ -384,6 +352,13 @@
 	init_completion(&dev->init_device_done);
 	init_completion(&dev->reload_start_done);
 	init_completion(&dev->resume_done);
+	init_completion(&dev->gpio_configuration_done);
+	init_completion(&dev->gpio_set_level_done);
+	init_completion(&dev->gpio_get_level_done);
+	init_completion(&dev->ir_init_done);
+
+	/* Buffer management */
+	init_waitqueue_head(&dev->buffer_mng_waitq);
 
 	/* alloc common buffer */
 	dev->common_buffer_size = params->buffer_size * params->num_buffers;
@@ -439,6 +414,71 @@
 }
 EXPORT_SYMBOL_GPL(smscore_register_device);
 
+
+static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
+		void *buffer, size_t size, struct completion *completion) {
+	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+	if (rc < 0) {
+		sms_info("sendrequest returned error %d", rc);
+		return rc;
+	}
+
+	return wait_for_completion_timeout(completion,
+			msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ?
+			0 : -ETIME;
+}
+
+/**
+ * Starts & enables IR operations
+ *
+ * @return 0 on success, < 0 on error.
+ */
+static int smscore_init_ir(struct smscore_device_t *coredev)
+{
+	int ir_io;
+	int rc;
+	void *buffer;
+
+	coredev->ir.input_dev = NULL;
+	ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
+	if (ir_io) {/* only if IR port exist we use IR sub-module */
+		sms_info("IR loading");
+		rc = sms_ir_init(coredev);
+
+		if	(rc != 0)
+			sms_err("Error initialization DTV IR sub-module");
+		else {
+			buffer = kmalloc(sizeof(struct SmsMsgData_ST2) +
+						SMS_DMA_ALIGNMENT,
+						GFP_KERNEL | GFP_DMA);
+			if (buffer) {
+				struct SmsMsgData_ST2 *msg =
+				(struct SmsMsgData_ST2 *)
+				SMS_ALIGN_ADDRESS(buffer);
+
+				SMS_INIT_MSG(&msg->xMsgHeader,
+						MSG_SMS_START_IR_REQ,
+						sizeof(struct SmsMsgData_ST2));
+				msg->msgData[0] = coredev->ir.controller;
+				msg->msgData[1] = coredev->ir.timeout;
+
+				smsendian_handle_tx_message(
+					(struct SmsMsgHdr_ST2 *)msg);
+				rc = smscore_sendrequest_and_wait(coredev, msg,
+						msg->xMsgHeader. msgLength,
+						&coredev->ir_init_done);
+
+				kfree(buffer);
+			} else
+				sms_err
+				("Sending IR initialization message failed");
+		}
+	} else
+		sms_info("IR port has not been detected");
+
+	return 0;
+}
+
 /**
  * sets initial device mode and notifies client hotplugs that device is ready
  *
@@ -459,6 +499,7 @@
 	kmutex_lock(&g_smscore_deviceslock);
 
 	rc = smscore_notify_callbacks(coredev, coredev->device, 1);
+	smscore_init_ir(coredev);
 
 	sms_info("device %p started, rc %d", coredev, rc);
 
@@ -468,29 +509,19 @@
 }
 EXPORT_SYMBOL_GPL(smscore_start_device);
 
-static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
-					void *buffer, size_t size,
-					struct completion *completion)
-{
-	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
-	if (rc < 0) {
-		sms_info("sendrequest returned error %d", rc);
-		return rc;
-	}
-
-	return wait_for_completion_timeout(completion,
-					   msecs_to_jiffies(10000)) ?
-						0 : -ETIME;
-}
 
 static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 					 void *buffer, size_t size)
 {
 	struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
 	struct SmsMsgHdr_ST *msg;
-	u32 mem_address = firmware->StartAddress;
+	u32 mem_address;
 	u8 *payload = firmware->Payload;
 	int rc = 0;
+	firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
+	firmware->Length = le32_to_cpu(firmware->Length);
+
+	mem_address = firmware->StartAddress;
 
 	sms_info("loading FW to addr 0x%x size %d",
 		 mem_address, firmware->Length);
@@ -657,6 +688,9 @@
 
 	kmutex_lock(&g_smscore_deviceslock);
 
+	/* Release input device (IR) resources */
+	sms_ir_exit(coredev);
+
 	smscore_notify_clients(coredev);
 	smscore_notify_callbacks(coredev, NULL, 0);
 
@@ -664,7 +698,9 @@
 	 * onresponse must no longer be called */
 
 	while (1) {
-		while ((cb = smscore_getbuffer(coredev))) {
+		while (!list_empty(&coredev->buffers)) {
+			cb = (struct smscore_buffer_t *) coredev->buffers.next;
+			list_del(&cb->entry);
 			kfree(cb);
 			num_buffers++;
 		}
@@ -685,8 +721,10 @@
 
 	if (coredev->common_buffer)
 		dma_free_coherent(NULL, coredev->common_buffer_size,
-				  coredev->common_buffer,
-				  coredev->common_buffer_phys);
+			coredev->common_buffer, coredev->common_buffer_phys);
+
+	if (coredev->fw_buf != NULL)
+		kfree(coredev->fw_buf);
 
 	list_del(&coredev->entry);
 	kfree(coredev);
@@ -778,7 +816,7 @@
 
 	sms_debug("set device mode to %d", mode);
 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
+		if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
 			sms_err("invalid mode specified %d", mode);
 			return -EINVAL;
 		}
@@ -870,7 +908,7 @@
 		coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
 	}
 
-	if (rc != 0)
+	if (rc < 0)
 		sms_err("return error code %d.", rc);
 	return rc;
 }
@@ -940,14 +978,11 @@
  *
  */
 void smscore_onresponse(struct smscore_device_t *coredev,
-			struct smscore_buffer_t *cb)
-{
-	struct SmsMsgHdr_ST *phdr =
-		(struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);
-	struct smscore_client_t *client =
-		smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+		struct smscore_buffer_t *cb) {
+	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
+			+ cb->offset);
+	struct smscore_client_t *client;
 	int rc = -EBUSY;
-
 	static unsigned long last_sample_time; /* = 0; */
 	static int data_total; /* = 0; */
 	unsigned long time_now = jiffies_to_msecs(jiffies);
@@ -965,6 +1000,16 @@
 	}
 
 	data_total += cb->size;
+	/* Do we need to re-route? */
+	if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) ||
+			(phdr->msgType == MSG_SMS_TRANSMISSION_IND)) {
+		if (coredev->mode == DEVICE_MODE_DVBT_BDA)
+			phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID;
+	}
+
+
+	client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+
 	/* If no client registered for type & id,
 	 * check for control client where type is not registered */
 	if (client)
@@ -1009,6 +1054,35 @@
 		case MSG_SMS_SLEEP_RESUME_COMP_IND:
 			complete(&coredev->resume_done);
 			break;
+		case MSG_SMS_GPIO_CONFIG_EX_RES:
+			sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
+			complete(&coredev->gpio_configuration_done);
+			break;
+		case MSG_SMS_GPIO_SET_LEVEL_RES:
+			sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
+			complete(&coredev->gpio_set_level_done);
+			break;
+		case MSG_SMS_GPIO_GET_LEVEL_RES:
+		{
+			u32 *msgdata = (u32 *) phdr;
+			coredev->gpio_get_res = msgdata[1];
+			sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
+					coredev->gpio_get_res);
+			complete(&coredev->gpio_get_level_done);
+			break;
+		}
+		case MSG_SMS_START_IR_RES:
+			complete(&coredev->ir_init_done);
+			break;
+		case MSG_SMS_IR_SAMPLES_IND:
+			sms_ir_event(coredev,
+				(const char *)
+				((char *)phdr
+				+ sizeof(struct SmsMsgHdr_ST)),
+				(int)phdr->msgLength
+				- sizeof(struct SmsMsgHdr_ST));
+			break;
+
 		default:
 			break;
 		}
@@ -1030,12 +1104,24 @@
 	struct smscore_buffer_t *cb = NULL;
 	unsigned long flags;
 
+	DEFINE_WAIT(wait);
+
 	spin_lock_irqsave(&coredev->bufferslock, flags);
 
-	if (!list_empty(&coredev->buffers)) {
-		cb = (struct smscore_buffer_t *) coredev->buffers.next;
-		list_del(&cb->entry);
-	}
+	/* This function must return a valid buffer, since the buffer list is
+	 * finite, we check that there is an available buffer, if not, we wait
+	 * until such buffer become available.
+	 */
+
+	prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE);
+
+	if (list_empty(&coredev->buffers))
+		schedule();
+
+	finish_wait(&coredev->buffer_mng_waitq, &wait);
+
+	cb = (struct smscore_buffer_t *) coredev->buffers.next;
+	list_del(&cb->entry);
 
 	spin_unlock_irqrestore(&coredev->bufferslock, flags);
 
@@ -1052,8 +1138,8 @@
  *
  */
 void smscore_putbuffer(struct smscore_device_t *coredev,
-		       struct smscore_buffer_t *cb)
-{
+		struct smscore_buffer_t *cb) {
+	wake_up_interruptible(&coredev->buffer_mng_waitq);
 	list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
 }
 EXPORT_SYMBOL_GPL(smscore_putbuffer);
@@ -1210,8 +1296,9 @@
 EXPORT_SYMBOL_GPL(smsclient_sendrequest);
 
 
+/* old GPIO managments implementation */
 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-			   struct smscore_gpio_config *pinconfig)
+			   struct smscore_config_gpio *pinconfig)
 {
 	struct {
 		struct SmsMsgHdr_ST hdr;
@@ -1280,35 +1367,254 @@
 					    &msg, sizeof(msg));
 }
 
-static int __init smscore_module_init(void)
-{
-	int rc = 0;
+/* new GPIO managment implementation */
+static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
+		u32 *pGroupNum, u32 *pGroupCfg) {
 
-	INIT_LIST_HEAD(&g_smscore_notifyees);
-	INIT_LIST_HEAD(&g_smscore_devices);
-	kmutex_init(&g_smscore_deviceslock);
+	*pGroupCfg = 1;
 
-	INIT_LIST_HEAD(&g_smscore_registry);
-	kmutex_init(&g_smscore_registrylock);
+	if (PinNum >= 0 && PinNum <= 1)	{
+		*pTranslatedPinNum = 0;
+		*pGroupNum = 9;
+		*pGroupCfg = 2;
+	} else if (PinNum >= 2 && PinNum <= 6) {
+		*pTranslatedPinNum = 2;
+		*pGroupNum = 0;
+		*pGroupCfg = 2;
+	} else if (PinNum >= 7 && PinNum <= 11) {
+		*pTranslatedPinNum = 7;
+		*pGroupNum = 1;
+	} else if (PinNum >= 12 && PinNum <= 15) {
+		*pTranslatedPinNum = 12;
+		*pGroupNum = 2;
+		*pGroupCfg = 3;
+	} else if (PinNum == 16) {
+		*pTranslatedPinNum = 16;
+		*pGroupNum = 23;
+	} else if (PinNum >= 17 && PinNum <= 24) {
+		*pTranslatedPinNum = 17;
+		*pGroupNum = 3;
+	} else if (PinNum == 25) {
+		*pTranslatedPinNum = 25;
+		*pGroupNum = 6;
+	} else if (PinNum >= 26 && PinNum <= 28) {
+		*pTranslatedPinNum = 26;
+		*pGroupNum = 4;
+	} else if (PinNum == 29) {
+		*pTranslatedPinNum = 29;
+		*pGroupNum = 5;
+		*pGroupCfg = 2;
+	} else if (PinNum == 30) {
+		*pTranslatedPinNum = 30;
+		*pGroupNum = 8;
+	} else if (PinNum == 31) {
+		*pTranslatedPinNum = 31;
+		*pGroupNum = 17;
+	} else
+		return -1;
+
+	*pGroupCfg <<= 24;
+
+	return 0;
+}
+
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+		struct smscore_gpio_config *pGpioConfig) {
+
+	u32 totalLen;
+	u32 TranslatedPinNum = 0;
+	u32 GroupNum = 0;
+	u32 ElectricChar;
+	u32 groupCfg;
+	void *buffer;
+	int rc;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[6];
+	} *pMsg;
+
+
+	if (PinNum > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	if (pGpioConfig == NULL)
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+
+	if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
+		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
+		if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
+				&groupCfg) != 0)
+			return -EINVAL;
+
+		pMsg->msgData[1] = TranslatedPinNum;
+		pMsg->msgData[2] = GroupNum;
+		ElectricChar = (pGpioConfig->PullUpDown)
+				| (pGpioConfig->InputCharacteristics << 2)
+				| (pGpioConfig->OutputSlewRate << 3)
+				| (pGpioConfig->OutputDriving << 4);
+		pMsg->msgData[3] = ElectricChar;
+		pMsg->msgData[4] = pGpioConfig->Direction;
+		pMsg->msgData[5] = groupCfg;
+	} else {
+		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		pMsg->msgData[1] = pGpioConfig->PullUpDown;
+		pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
+		pMsg->msgData[3] = pGpioConfig->OutputDriving;
+		pMsg->msgData[4] = pGpioConfig->Direction;
+		pMsg->msgData[5] = 0;
+	}
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_configuration_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_configure timeout");
+		else
+			sms_err("smscore_gpio_configure error");
+	}
+	kfree(buffer);
+
+	return rc;
+}
+
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 NewLevel) {
+
+	u32 totalLen;
+	int rc;
+	void *buffer;
 
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[3]; /* keep it 3 ! */
+	} *pMsg;
 
+	if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) ||
+			(PinNum > MAX_GPIO_PIN_NUMBER))
+		return -EINVAL;
 
+	totalLen = sizeof(struct SmsMsgHdr_ST) +
+			(3 * sizeof(u32)); /* keep it 3 ! */
 
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
 
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+	pMsg->msgData[1] = NewLevel;
+
+	/* Send message to SMS */
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_set_level_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_set_level timeout");
+		else
+			sms_err("smscore_gpio_set_level error");
+	}
+	kfree(buffer);
 
 	return rc;
-	sms_debug("rc %d", rc);
+}
+
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 *level) {
+
+	u32 totalLen;
+	int rc;
+	void *buffer;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[2];
+	} *pMsg;
+
+
+	if (PinNum > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+	pMsg->msgData[1] = 0;
+
+	/* Send message to SMS */
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_get_level_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_get_level timeout");
+		else
+			sms_err("smscore_gpio_get_level error");
+	}
+	kfree(buffer);
+
+	/* Its a race between other gpio_get_level() and the copy of the single
+	 * global 'coredev->gpio_get_res' to  the function's variable 'level'
+	 */
+	*level = coredev->gpio_get_res;
 
 	return rc;
 }
 
-static void __exit smscore_module_exit(void)
+static int __init smscore_module_init(void)
 {
+	int rc = 0;
 
+	INIT_LIST_HEAD(&g_smscore_notifyees);
+	INIT_LIST_HEAD(&g_smscore_devices);
+	kmutex_init(&g_smscore_deviceslock);
 
+	INIT_LIST_HEAD(&g_smscore_registry);
+	kmutex_init(&g_smscore_registrylock);
 
+	return rc;
+}
 
-
+static void __exit smscore_module_exit(void)
+{
 	kmutex_lock(&g_smscore_deviceslock);
 	while (!list_empty(&g_smscore_notifyees)) {
 		struct smscore_device_notifyee_t *notifyee =
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smscoreapi.h linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smscoreapi.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smscoreapi.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smscoreapi.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,26 +1,26 @@
-/*
- *  Driver for the Siano SMS1xxx USB dongle
- *
- *  author: Anatoly Greenblat
- *
- *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation;
- *
- *  Software distributed under the License is distributed on an "AS IS"
- *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- *
- *  See the 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.
- */
+/****************************************************************
 
-#ifndef __smscoreapi_h__
-#define __smscoreapi_h__
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat
+
+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, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_CORE_API_H__
+#define __SMS_CORE_API_H__
 
 #include <linux/version.h>
 #include <linux/device.h>
@@ -28,14 +28,13 @@
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 #include <linux/types.h>
-#include <asm/page.h>
 #include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
 
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
+#include <asm/page.h>
 
+#include "smsir.h"
 
 #define kmutex_init(_p_) mutex_init(_p_)
 #define kmutex_lock(_p_) mutex_lock(_p_)
@@ -46,13 +45,14 @@
 #define min(a, b) (((a) < (b)) ? (a) : (b))
 #endif
 
-#define SMS_ALLOC_ALIGNMENT					128
-#define SMS_DMA_ALIGNMENT					16
+#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS			(10000)
+#define SMS_ALLOC_ALIGNMENT				128
+#define SMS_DMA_ALIGNMENT				16
 #define SMS_ALIGN_ADDRESS(addr) \
 	((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
 
-#define SMS_DEVICE_FAMILY2					1
-#define SMS_ROM_NO_RESPONSE					2
+#define SMS_DEVICE_FAMILY2				1
+#define SMS_ROM_NO_RESPONSE				2
 #define SMS_DEVICE_NOT_READY				0x8000000
 
 enum sms_device_type_st {
@@ -83,13 +83,13 @@
 struct smscore_buffer_t {
 	/* public members, once passed to clients can be changed freely */
 	struct list_head entry;
-	int				size;
-	int				offset;
+	int size;
+	int offset;
 
 	/* private members, read-only for clients */
-	void			*p;
-	dma_addr_t		phys;
-	unsigned long	offset_in_common;
+	void *p;
+	dma_addr_t phys;
+	unsigned long offset_in_common;
 };
 
 struct smsdevice_params_t {
@@ -116,10 +116,63 @@
 	int				data_type;
 	onresponse_t	onresponse_handler;
 	onremove_t		onremove_handler;
-
 	void			*context;
 };
 
+struct smscore_device_t {
+	struct list_head entry;
+
+	struct list_head clients;
+	struct list_head subclients;
+	spinlock_t clientslock;
+
+	struct list_head buffers;
+	spinlock_t bufferslock;
+	int num_buffers;
+
+	void *common_buffer;
+	int common_buffer_size;
+	dma_addr_t common_buffer_phys;
+
+	void *context;
+	struct device *device;
+
+	char devpath[32];
+	unsigned long device_flags;
+
+	setmode_t setmode_handler;
+	detectmode_t detectmode_handler;
+	sendrequest_t sendrequest_handler;
+	preload_t preload_handler;
+	postload_t postload_handler;
+
+	int mode, modes_supported;
+
+	/* host <--> device messages */
+	struct completion version_ex_done, data_download_done, trigger_done;
+	struct completion init_device_done, reload_start_done, resume_done;
+	struct completion gpio_configuration_done, gpio_set_level_done;
+	struct completion gpio_get_level_done, ir_init_done;
+
+	/* Buffer management */
+	wait_queue_head_t buffer_mng_waitq;
+
+	/* GPIO */
+	int gpio_get_res;
+
+	/* Target hardware board */
+	int board_id;
+
+	/* Firmware */
+	u8 *fw_buf;
+	u32 fw_buf_size;
+
+	/* Infrared (IR) */
+	struct ir_t ir;
+
+	int led_state;
+};
+
 /* GPIO definitions for antenna frequency domain control (SMS8021) */
 #define SMS_ANTENNA_GPIO_0					1
 #define SMS_ANTENNA_GPIO_1					0
@@ -154,18 +207,15 @@
 #define MSG_SMS_INIT_DEVICE_RES				579
 #define MSG_SMS_ADD_PID_FILTER_REQ			601
 #define MSG_SMS_ADD_PID_FILTER_RES			602
-#define MSG_SMS_REMOVE_PID_FILTER_REQ		603
-#define MSG_SMS_REMOVE_PID_FILTER_RES		604
-#define MSG_SMS_DAB_CHANNEL					607
-#define MSG_SMS_GET_PID_FILTER_LIST_REQ		608
-#define MSG_SMS_GET_PID_FILTER_LIST_RES		609
-#define MSG_SMS_GET_STATISTICS_REQ			615
-#define MSG_SMS_GET_STATISTICS_RES			616
-#define MSG_SMS_SET_ANTENNA_CONFIG_REQ		651
-#define MSG_SMS_SET_ANTENNA_CONFIG_RES		652
-#define MSG_SMS_GET_STATISTICS_EX_REQ		653
-#define MSG_SMS_GET_STATISTICS_EX_RES		654
-#define MSG_SMS_SLEEP_RESUME_COMP_IND		655
+#define MSG_SMS_REMOVE_PID_FILTER_REQ			603
+#define MSG_SMS_REMOVE_PID_FILTER_RES			604
+#define MSG_SMS_DAB_CHANNEL				607
+#define MSG_SMS_GET_PID_FILTER_LIST_REQ			608
+#define MSG_SMS_GET_PID_FILTER_LIST_RES			609
+#define MSG_SMS_HO_PER_SLICES_IND			630
+#define MSG_SMS_SET_ANTENNA_CONFIG_REQ			651
+#define MSG_SMS_SET_ANTENNA_CONFIG_RES			652
+#define MSG_SMS_SLEEP_RESUME_COMP_IND			655
 #define MSG_SMS_DATA_DOWNLOAD_REQ			660
 #define MSG_SMS_DATA_DOWNLOAD_RES			661
 #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ		664
@@ -190,14 +240,31 @@
 #define MSG_SMS_GPIO_CONFIG_EX_RES			713
 #define MSG_SMS_ISDBT_TUNE_REQ				776
 #define MSG_SMS_ISDBT_TUNE_RES				777
+#define MSG_SMS_TRANSMISSION_IND			782
+#define MSG_SMS_START_IR_REQ				800
+#define MSG_SMS_START_IR_RES				801
+#define MSG_SMS_IR_SAMPLES_IND				802
+#define MSG_SMS_SIGNAL_DETECTED_IND			827
+#define MSG_SMS_NO_SIGNAL_IND				828
 
 #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
 	(ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
 	(ptr)->msgLength = len; (ptr)->msgFlags = 0; \
 } while (0)
+
 #define SMS_INIT_MSG(ptr, type, len) \
 	SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
 
+enum SMS_DVB3_EVENTS {
+	DVB3_EVENT_INIT = 0,
+	DVB3_EVENT_SLEEP,
+	DVB3_EVENT_HOTPLUG,
+	DVB3_EVENT_FE_LOCK,
+	DVB3_EVENT_FE_UNLOCK,
+	DVB3_EVENT_UNC_OK,
+	DVB3_EVENT_UNC_ERR
+};
+
 enum SMS_DEVICE_MODE {
 	DEVICE_MODE_NONE = -1,
 	DEVICE_MODE_DVBT = 0,
@@ -221,8 +288,13 @@
 };
 
 struct SmsMsgData_ST {
-	struct SmsMsgHdr_ST	xMsgHeader;
-	u32			msgData[1];
+	struct SmsMsgHdr_ST xMsgHeader;
+	u32 msgData[1];
+};
+
+struct SmsMsgData_ST2 {
+	struct SmsMsgHdr_ST xMsgHeader;
+	u32 msgData[2];
 };
 
 struct SmsDataDownload_ST {
@@ -238,11 +310,12 @@
 	u8		Step; /* 0 - Step A */
 	u8		MetalFix; /* 0 - Metal 0 */
 
-	u8		FirmwareId; /* 0xFF � ROM, otherwise the
-				     * value indicated by
-				     * SMSHOSTLIB_DEVICE_MODES_E */
-	u8		SupportedProtocols; /* Bitwise OR combination of
+	/* FirmwareId 0xFF if ROM, otherwise the
+	 * value indicated by SMSHOSTLIB_DEVICE_MODES_E */
+	u8 FirmwareId;
+	/* SupportedProtocols Bitwise OR combination of
 					     * supported protocols */
+	u8 SupportedProtocols;
 
 	u8		VersionMajor;
 	u8		VersionMinor;
@@ -264,86 +337,219 @@
 	u8			Payload[1];
 };
 
-struct SMSHOSTLIB_STATISTICS_ST {
-	u32 Reserved; /* Reserved */
+/* Statistics information returned as response for
+ * SmsHostApiGetStatistics_Req */
+struct SMSHOSTLIB_STATISTICS_S {
+	u32 Reserved;		/* Reserved */
 
 	/* Common parameters */
-	u32 IsRfLocked; /* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
+	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
+	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
 
 	/* Reception quality */
-	s32  SNR; /* dB */
-	u32 BER; /* Post Viterbi BER [1E-5] */
-	u32 FIB_CRC;	/* CRC errors percentage, valid only for DAB */
-	u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A,
-		     * valid only for DVB-T/H */
-	u32 MFER; /* DVB-H frame error rate in percentage,
-		   * 0xFFFFFFFF indicate N/A, valid only for DVB-H */
-	s32  RSSI; /* dBm */
-	s32  InBandPwr; /* In band power in dBM */
-	s32  CarrierOffset; /* Carrier Offset in bin/1024 */
+	s32 SNR;		/* dB */
+	u32 BER;		/* Post Viterbi BER [1E-5] */
+	u32 FIB_CRC;		/* CRC errors percentage, valid only for DAB */
+	u32 TS_PER;		/* Transport stream PER,
+	0xFFFFFFFF indicate N/A, valid only for DVB-T/H */
+	u32 MFER;		/* DVB-H frame error rate in percentage,
+	0xFFFFFFFF indicate N/A, valid only for DVB-H */
+	s32 RSSI;		/* dBm */
+	s32 InBandPwr;		/* In band power in dBM */
+	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
 
-	/* Transmission parameters, valid only for DVB-T/H */
-	u32 Frequency; /* Frequency in Hz */
-	u32 Bandwidth; /* Bandwidth in MHz */
-	u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4,
-			       * for DVB-T/H FFT mode carriers in Kilos */
-	u32 ModemState; /* from SMS_DvbModemState_ET */
-	u32 GuardInterval; /* Guard Interval, 1 divided by value */
-	u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */
-	u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */
-	u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */
-	u32 Constellation; /* Constellation from SMS_Constellation_ET */
+	/* Transmission parameters */
+	u32 Frequency;		/* Frequency in Hz */
+	u32 Bandwidth;		/* Bandwidth in MHz, valid only for DVB-T/H */
+	u32 TransmissionMode;	/* Transmission Mode, for DAB modes 1-4,
+	for DVB-T/H FFT mode carriers in Kilos */
+	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET,
+	valid only for DVB-T/H */
+	u32 GuardInterval;	/* Guard Interval from
+	SMSHOSTLIB_GUARD_INTERVALS_ET, 	valid only for DVB-T/H */
+	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+	valid only for DVB-T/H */
+	u32 LPCodeRate;		/* Low Priority Code Rate from
+	SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */
+	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET,
+	valid only for DVB-T/H */
+	u32 Constellation;	/* Constellation from
+	SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */
 
 	/* Burst parameters, valid only for DVB-H */
-	u32 BurstSize; /* Current burst size in bytes */
-	u32 BurstDuration; /* Current burst duration in mSec */
-	u32 BurstCycleTime; /* Current burst cycle time in mSec */
-	u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec,
-				       * as calculated by demodulator */
-	u32 NumOfRows; /* Number of rows in MPE table */
-	u32 NumOfPaddCols; /* Number of padding columns in MPE table */
-	u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */
-	/* Burst parameters */
-	u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
-	u32 TotalTSPackets; /* Total number of transport-stream packets */
-	u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include
-				* errors after MPE RS decoding */
-	u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors
-				  * after MPE RS decoding */
-	u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected
-				    * by MPE RS decoding */
-
+	u32 BurstSize;		/* Current burst size in bytes,
+	valid only for DVB-H */
+	u32 BurstDuration;	/* Current burst duration in mSec,
+	valid only for DVB-H */
+	u32 BurstCycleTime;	/* Current burst cycle time in mSec,
+	valid only for DVB-H */
+	u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec,
+	as calculated by demodulator, valid only for DVB-H */
+	u32 NumOfRows;		/* Number of rows in MPE table,
+	valid only for DVB-H */
+	u32 NumOfPaddCols;	/* Number of padding columns in MPE table,
+	valid only for DVB-H */
+	u32 NumOfPunctCols;	/* Number of puncturing columns in MPE table,
+	valid only for DVB-H */
+	u32 ErrorTSPackets;	/* Number of erroneous
+	transport-stream packets */
+	u32 TotalTSPackets;	/* Total number of transport-stream packets */
+	u32 NumOfValidMpeTlbs;	/* Number of MPE tables which do not include
+	errors after MPE RS decoding */
+	u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors
+	after MPE RS decoding */
+	u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were
+	corrected by MPE RS decoding */
 	/* Common params */
-	u32 BERErrorCount; /* Number of errornous SYNC bits. */
-	u32 BERBitCount; /* Total number of SYNC bits. */
+	u32 BERErrorCount;	/* Number of errornous SYNC bits. */
+	u32 BERBitCount;	/* Total number of SYNC bits. */
 
 	/* Interface information */
-	u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+	u32 SmsToHostTxErrors;	/* Total number of transmission errors. */
 
 	/* DAB/T-DMB */
-	u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
+	u32 PreBER; 		/* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
 
 	/* DVB-H TPS parameters */
-	u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero;
-		     * if set to 0xFFFFFFFF cell_id not yet recovered */
+	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	 if set to 0xFFFFFFFF cell_id not yet recovered */
+	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	Time Slicing indicator, bit 0 - MPE-FEC indicator */
+	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	Time Slicing indicator, bit 0 - MPE-FEC indicator */
 
+	u32 NumMPEReceived;	/* DVB-H, Num MPE section received */
+
+	u32 ReservedFields[10];	/* Reserved */
 };
 
-struct SmsMsgStatisticsInfo_ST {
-	u32 RequestResult;
+struct PID_STATISTICS_DATA_S {
+	struct PID_BURST_S {
+		u32 size;
+		u32 padding_cols;
+		u32 punct_cols;
+		u32 duration;
+		u32 cycle;
+		u32 calc_cycle;
+	} burst;
 
-	struct SMSHOSTLIB_STATISTICS_ST Stat;
+	u32 tot_tbl_cnt;
+	u32 invalid_tbl_cnt;
+	u32 tot_cor_tbl;
+};
 
-	/* Split the calc of the SNR in DAB */
-	u32 Signal; /* dB */
-	u32 Noise; /* dB */
+struct PID_DATA_S {
+	u32 pid;
+	u32 num_rows;
+	struct PID_STATISTICS_DATA_S pid_statistics;
+};
+
+#define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1)
+#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth)
+#define CORRECT_STAT_TRANSMISSON_MODE(_stat) \
+	if (_stat.TransmissionMode == 0) \
+		_stat.TransmissionMode = 2; \
+	else if (_stat.TransmissionMode == 1) \
+		_stat.TransmissionMode = 8; \
+		else \
+			_stat.TransmissionMode = 4;
+
+struct TRANSMISSION_STATISTICS_S {
+	u32 Frequency;		/* Frequency in Hz */
+	u32 Bandwidth;		/* Bandwidth in MHz */
+	u32 TransmissionMode;	/* FFT mode carriers in Kilos */
+	u32 GuardInterval;	/* Guard Interval from
+	SMSHOSTLIB_GUARD_INTERVALS_ET */
+	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
+	u32 LPCodeRate;		/* Low Priority Code Rate from
+	SMSHOSTLIB_CODE_RATE_ET */
+	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */
+	u32 Constellation;	/* Constellation from
+	SMSHOSTLIB_CONSTELLATION_ET */
 
+	/* DVB-H TPS parameters */
+	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	 if set to 0xFFFFFFFF cell_id not yet recovered */
+	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
+	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
+	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
 };
 
+struct RECEPTION_STATISTICS_S {
+	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
+	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
+	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
 
-struct smscore_gpio_config {
+	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+	s32 SNR;		/* dB */
+	u32 BER;		/* Post Viterbi BER [1E-5] */
+	u32 BERErrorCount;	/* Number of erronous SYNC bits. */
+	u32 BERBitCount;	/* Total number of SYNC bits. */
+	u32 TS_PER;		/* Transport stream PER,
+	0xFFFFFFFF indicate N/A */
+	u32 MFER;		/* DVB-H frame error rate in percentage,
+	0xFFFFFFFF indicate N/A, valid only for DVB-H */
+	s32 RSSI;		/* dBm */
+	s32 InBandPwr;		/* In band power in dBM */
+	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
+	u32 ErrorTSPackets;	/* Number of erroneous
+	transport-stream packets */
+	u32 TotalTSPackets;	/* Total number of transport-stream packets */
+
+	s32 MRC_SNR;		/* dB */
+	s32 MRC_RSSI;		/* dBm */
+	s32 MRC_InBandPwr;	/* In band power in dBM */
+};
+
+
+/* Statistics information returned as response for
+ * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
+struct SMSHOSTLIB_STATISTICS_DVB_S {
+	/* Reception */
+	struct RECEPTION_STATISTICS_S ReceptionData;
+
+	/* Transmission parameters */
+	struct TRANSMISSION_STATISTICS_S TransmissionData;
+
+	/* Burst parameters, valid only for DVB-H */
+#define	SRVM_MAX_PID_FILTERS 8
+	struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS];
+};
+
+struct SRVM_SIGNAL_STATUS_S {
+	u32 result;
+	u32 snr;
+	u32 tsPackets;
+	u32 etsPackets;
+	u32 constellation;
+	u32 hpCode;
+	u32 tpsSrvIndLP;
+	u32 tpsSrvIndHP;
+	u32 cellId;
+	u32 reason;
+
+	s32 inBandPower;
+	u32 requestId;
+};
+
+struct SMSHOSTLIB_I2C_REQ_ST {
+	u32	DeviceAddress; /* I2c device address */
+	u32	WriteCount; /* number of bytes to write */
+	u32	ReadCount; /* number of bytes to read */
+	u8	Data[1];
+};
+
+struct SMSHOSTLIB_I2C_RES_ST {
+	u32	Status; /* non-zero value in case of failure */
+	u32	ReadCount; /* number of bytes read */
+	u8	Data[1];
+};
+
+
+struct smscore_config_gpio {
 #define SMS_GPIO_DIRECTION_INPUT  0
 #define SMS_GPIO_DIRECTION_OUTPUT 1
 	u8 direction;
@@ -369,6 +575,47 @@
 	u8 outputdriving;
 };
 
+struct smscore_gpio_config {
+#define SMS_GPIO_DIRECTION_INPUT  0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+	u8 Direction;
+
+#define SMS_GPIO_PULL_UP_DOWN_NONE     0
+#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1
+#define SMS_GPIO_PULL_UP_DOWN_PULLUP   2
+#define SMS_GPIO_PULL_UP_DOWN_KEEPER   3
+	u8 PullUpDown;
+
+#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
+#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
+	u8 InputCharacteristics;
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW		1 /* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST		0 /* 10xx */
+
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3 /* 11xx */
+	u8 OutputSlewRate;
+
+#define SMS_GPIO_OUTPUT_DRIVING_S_4mA		0 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_8mA		1 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_12mA		2 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_16mA		3 /* 10xx */
+
+#define SMS_GPIO_OUTPUT_DRIVING_1_5mA		0 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_2_8mA		1 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_4mA		2 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_7mA		3 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_10mA		4 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_11mA		5 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_14mA		6 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_16mA		7 /* 11xx */
+	u8 OutputDriving;
+};
+
 extern void smscore_registry_setmode(char *devpath, int mode);
 extern int smscore_registry_getmode(char *devpath);
 
@@ -410,10 +657,19 @@
 extern void smscore_putbuffer(struct smscore_device_t *coredev,
 			      struct smscore_buffer_t *cb);
 
+/* old GPIO managment */
 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-			   struct smscore_gpio_config *pinconfig);
+			   struct smscore_config_gpio *pinconfig);
 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
 
+/* new GPIO managment */
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+		struct smscore_gpio_config *pGpioConfig);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 NewLevel);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 *level);
+
 void smscore_set_board_id(struct smscore_device_t *core, int id);
 int smscore_get_board_id(struct smscore_device_t *core);
 
@@ -442,4 +698,4 @@
 	dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
 
 
-#endif /* __smscoreapi_h__ */
+#endif /* __SMS_CORE_API_H__ */
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsdvb.c linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsdvb.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsdvb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsdvb.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,28 +1,34 @@
-/*
- *  Driver for the Siano SMS1xxx USB dongle
- *
- *  Author: Uri Shkolni
- *
- *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation;
- *
- *  Software distributed under the License is distributed on an "AS IS"
- *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- *
- *  See the 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.
- */
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2008, Uri Shkolnik
+
+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, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
 
 #include <linux/module.h>
 #include <linux/init.h>
 
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
 #include "smscoreapi.h"
+#include "smsendian.h"
 #include "sms-cards.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -39,12 +45,15 @@
 	struct dvb_frontend     frontend;
 
 	fe_status_t             fe_status;
-	int                     fe_ber, fe_snr, fe_unc, fe_signal_strength;
 
-	struct completion       tune_done, stat_done;
+	struct completion       tune_done;
 
 	/* todo: save freq/band instead whole struct */
 	struct dvb_frontend_parameters fe_params;
+
+	struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
+	int event_fe_state;
+	int event_unc_state;
 };
 
 static struct list_head g_smsdvb_clients;
@@ -54,11 +63,69 @@
 module_param_named(debug, sms_dbg, int, 0644);
 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
 
+/* Events that may come from DVB v3 adapter */
+static void sms_board_dvb3_event(struct smsdvb_client_t *client,
+		enum SMS_DVB3_EVENTS event) {
+
+	struct smscore_device_t *coredev = client->coredev;
+	switch (event) {
+	case DVB3_EVENT_INIT:
+		sms_debug("DVB3_EVENT_INIT");
+		sms_board_event(coredev, BOARD_EVENT_BIND);
+		break;
+	case DVB3_EVENT_SLEEP:
+		sms_debug("DVB3_EVENT_SLEEP");
+		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
+		break;
+	case DVB3_EVENT_HOTPLUG:
+		sms_debug("DVB3_EVENT_HOTPLUG");
+		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
+		break;
+	case DVB3_EVENT_FE_LOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_LOCK;
+			sms_debug("DVB3_EVENT_FE_LOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
+		}
+		break;
+	case DVB3_EVENT_FE_UNLOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
+			sms_debug("DVB3_EVENT_FE_UNLOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
+		}
+		break;
+	case DVB3_EVENT_UNC_OK:
+		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
+			client->event_unc_state = DVB3_EVENT_UNC_OK;
+			sms_debug("DVB3_EVENT_UNC_OK");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
+		}
+		break;
+	case DVB3_EVENT_UNC_ERR:
+		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
+			client->event_unc_state = DVB3_EVENT_UNC_ERR;
+			sms_debug("DVB3_EVENT_UNC_ERR");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
+		}
+		break;
+
+	default:
+		sms_err("Unknown dvb3 api event");
+		break;
+	}
+}
+
 static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 {
 	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
-	struct SmsMsgHdr_ST *phdr =
-		(struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset);
+	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
+			+ cb->offset);
+	u32 *pMsgData = (u32 *) phdr + 1;
+	/*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
+	bool is_status_update = false;
+
+	smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
 
 	switch (phdr->msgType) {
 	case MSG_SMS_DVBT_BDA_DATA:
@@ -70,43 +137,110 @@
 		complete(&client->tune_done);
 		break;
 
-	case MSG_SMS_GET_STATISTICS_RES:
-	{
-		struct SmsMsgStatisticsInfo_ST *p =
-			(struct SmsMsgStatisticsInfo_ST *)(phdr + 1);
+	case MSG_SMS_SIGNAL_DETECTED_IND:
+		sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
+		client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
+		is_status_update = true;
+		break;
 
-		if (p->Stat.IsDemodLocked) {
-			client->fe_status = FE_HAS_SIGNAL |
-					    FE_HAS_CARRIER |
-					    FE_HAS_VITERBI |
-					    FE_HAS_SYNC |
-					    FE_HAS_LOCK;
+	case MSG_SMS_NO_SIGNAL_IND:
+		sms_info("MSG_SMS_NO_SIGNAL_IND");
+		client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
+		is_status_update = true;
+		break;
 
-			client->fe_snr = p->Stat.SNR;
-			client->fe_ber = p->Stat.BER;
-			client->fe_unc = p->Stat.BERErrorCount;
+	case MSG_SMS_TRANSMISSION_IND: {
+		sms_info("MSG_SMS_TRANSMISSION_IND");
 
-			if (p->Stat.InBandPwr < -95)
-				client->fe_signal_strength = 0;
-			else if (p->Stat.InBandPwr > -29)
-				client->fe_signal_strength = 100;
-			else
-				client->fe_signal_strength =
-					(p->Stat.InBandPwr + 95) * 3 / 2;
+		pMsgData++;
+		memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
+				sizeof(struct TRANSMISSION_STATISTICS_S));
+
+		/* Mo need to correct guard interval
+		 * (as opposed to old statistics message).
+		 */
+		CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
+		CORRECT_STAT_TRANSMISSON_MODE(
+				client->sms_stat_dvb.TransmissionData);
+		is_status_update = true;
+		break;
+	}
+	case MSG_SMS_HO_PER_SLICES_IND: {
+		struct RECEPTION_STATISTICS_S *pReceptionData =
+				&client->sms_stat_dvb.ReceptionData;
+		struct SRVM_SIGNAL_STATUS_S SignalStatusData;
+
+		/*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/
+		pMsgData++;
+		SignalStatusData.result = pMsgData[0];
+		SignalStatusData.snr = pMsgData[1];
+		SignalStatusData.inBandPower = (s32) pMsgData[2];
+		SignalStatusData.tsPackets = pMsgData[3];
+		SignalStatusData.etsPackets = pMsgData[4];
+		SignalStatusData.constellation = pMsgData[5];
+		SignalStatusData.hpCode = pMsgData[6];
+		SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
+		SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
+		SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
+		SignalStatusData.reason = pMsgData[10];
+		SignalStatusData.requestId = pMsgData[11];
+		pReceptionData->IsRfLocked = pMsgData[16];
+		pReceptionData->IsDemodLocked = pMsgData[17];
+		pReceptionData->ModemState = pMsgData[12];
+		pReceptionData->SNR = pMsgData[1];
+		pReceptionData->BER = pMsgData[13];
+		pReceptionData->RSSI = pMsgData[14];
+		CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
+
+		pReceptionData->InBandPwr = (s32) pMsgData[2];
+		pReceptionData->CarrierOffset = (s32) pMsgData[15];
+		pReceptionData->TotalTSPackets = pMsgData[3];
+		pReceptionData->ErrorTSPackets = pMsgData[4];
+
+		/* TS PER */
+		if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
+				> 0) {
+			pReceptionData->TS_PER = (SignalStatusData.etsPackets
+					* 100) / (SignalStatusData.tsPackets
+					+ SignalStatusData.etsPackets);
 		} else {
-			client->fe_status = 0;
-			client->fe_snr =
-			client->fe_ber =
-			client->fe_unc =
-			client->fe_signal_strength = 0;
+			pReceptionData->TS_PER = 0;
 		}
 
-		complete(&client->stat_done);
-		break;
-	} }
+		pReceptionData->BERBitCount = pMsgData[18];
+		pReceptionData->BERErrorCount = pMsgData[19];
+
+		pReceptionData->MRC_SNR = pMsgData[20];
+		pReceptionData->MRC_InBandPwr = pMsgData[21];
+		pReceptionData->MRC_RSSI = pMsgData[22];
 
+		is_status_update = true;
+		break;
+	}
+	}
 	smscore_putbuffer(client->coredev, cb);
 
+	if (is_status_update) {
+		if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
+			client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
+				| FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
+			if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
+					== 0)
+				sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
+			else
+				sms_board_dvb3_event(client,
+						DVB3_EVENT_UNC_ERR);
+
+		} else {
+			/*client->fe_status =
+				(phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ?
+				0 : FE_HAS_SIGNAL;*/
+			client->fe_status = 0;
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
+		}
+	}
+
 	return 0;
 }
 
@@ -149,6 +283,7 @@
 	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
 	PidMsg.msgData[0] = feed->pid;
 
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
 	return smsclient_sendrequest(client->smsclient,
 				     &PidMsg, sizeof(PidMsg));
 }
@@ -169,6 +304,7 @@
 	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
 	PidMsg.msgData[0] = feed->pid;
 
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
 	return smsclient_sendrequest(client->smsclient,
 				     &PidMsg, sizeof(PidMsg));
 }
@@ -177,7 +313,10 @@
 					void *buffer, size_t size,
 					struct completion *completion)
 {
-	int rc = smsclient_sendrequest(client->smsclient, buffer, size);
+	int rc;
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
+	rc = smsclient_sendrequest(client->smsclient, buffer, size);
 	if (rc < 0)
 		return rc;
 
@@ -186,83 +325,81 @@
 						0 : -ETIME;
 }
 
-static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+static inline int led_feedback(struct smsdvb_client_t *client)
 {
-	struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
-			     DVBT_BDA_CONTROL_MSG_ID,
-			     HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 };
-	int ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					      &client->stat_done);
-	if (ret < 0)
-		return ret;
-
 	if (client->fe_status & FE_HAS_LOCK)
-		sms_board_led_feedback(client->coredev,
-				       (client->fe_unc == 0) ?
-				       SMS_LED_HI : SMS_LED_LO);
+		return sms_board_led_feedback(client->coredev,
+			(client->sms_stat_dvb.ReceptionData.BER
+			== 0) ? SMS_LED_HI : SMS_LED_LO);
 	else
-		sms_board_led_feedback(client->coredev, SMS_LED_OFF);
-	return ret;
+		return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
 }
 
 static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
 {
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	int rc = smsdvb_send_statistics_request(client);
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
 
-	if (!rc)
-		*stat = client->fe_status;
+	*stat = client->fe_status;
 
-	return rc;
+	led_feedback(client);
+
+	return 0;
 }
 
 static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	int rc = smsdvb_send_statistics_request(client);
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
 
-	if (!rc)
-		*ber = client->fe_ber;
+	*ber = client->sms_stat_dvb.ReceptionData.BER;
 
-	return rc;
+	led_feedback(client);
+
+	return 0;
 }
 
 static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	int rc = smsdvb_send_statistics_request(client);
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
 
-	if (!rc)
-		*strength = client->fe_signal_strength;
+	if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
+		*strength = 0;
+		else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
+			*strength = 100;
+		else
+			*strength =
+				(client->sms_stat_dvb.ReceptionData.InBandPwr
+				+ 95) * 3 / 2;
 
-	return rc;
+	led_feedback(client);
+
+	return 0;
 }
 
 static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	int rc = smsdvb_send_statistics_request(client);
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
 
-	if (!rc)
-		*snr = client->fe_snr;
+	*snr = client->sms_stat_dvb.ReceptionData.SNR;
 
-	return rc;
+	led_feedback(client);
+
+	return 0;
 }
 
 static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	int rc = smsdvb_send_statistics_request(client);
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
 
-	if (!rc)
-		*ucblocks = client->fe_unc;
+	*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
 
-	return rc;
+	led_feedback(client);
+
+	return 0;
 }
 
 static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
@@ -286,12 +423,17 @@
 		struct SmsMsgHdr_ST	Msg;
 		u32		Data[3];
 	} Msg;
+
 	int ret;
 
-	Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
-	Msg.Msg.msgDstId  = HIF_TASK;
-	Msg.Msg.msgFlags  = 0;
-	Msg.Msg.msgType   = MSG_SMS_RF_TUNE_REQ;
+	client->fe_status = FE_HAS_SIGNAL;
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+
+	Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	Msg.Msg.msgDstId = HIF_TASK;
+	Msg.Msg.msgFlags = 0;
+	Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
 	Msg.Msg.msgLength = sizeof(Msg);
 	Msg.Data[0] = fep->frequency;
 	Msg.Data[2] = 12000000;
@@ -306,7 +448,6 @@
 	case BANDWIDTH_AUTO: return -EOPNOTSUPP;
 	default: return -EINVAL;
 	}
-
 	/* Disable LNA, if any. An error is returned if no LNA is present */
 	ret = sms_board_lna_control(client->coredev, 0);
 	if (ret == 0) {
@@ -351,6 +492,7 @@
 
 	sms_board_power(client->coredev, 1);
 
+	sms_board_dvb3_event(client, DVB3_EVENT_INIT);
 	return 0;
 }
 
@@ -362,6 +504,8 @@
 	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
 	sms_board_power(client->coredev, 0);
 
+	sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
+
 	return 0;
 }
 
@@ -485,7 +629,6 @@
 	client->coredev = coredev;
 
 	init_completion(&client->tune_done);
-	init_completion(&client->stat_done);
 
 	kmutex_lock(&g_smsdvb_clientslock);
 
@@ -493,8 +636,11 @@
 
 	kmutex_unlock(&g_smsdvb_clientslock);
 
-	sms_info("success");
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
 
+	sms_info("success");
 	sms_board_setup(coredev);
 
 	return 0;
@@ -547,5 +693,5 @@
 module_exit(smsdvb_module_exit);
 
 MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
-MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)");
+MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsendian.c linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsendian.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsendian.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsendian.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,102 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, Uri Shkolnik
+
+ 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, see <http://www.gnu.org/licenses/>.
+
+ ****************************************************************/
+
+#include <asm/byteorder.h>
+
+#include "smsendian.h"
+#include "smscoreapi.h"
+
+void smsendian_handle_tx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	int i;
+	int msgWords;
+
+	switch (msg->xMsgHeader.msgType) {
+	case MSG_SMS_DATA_DOWNLOAD_REQ:
+	{
+		msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
+		break;
+	}
+
+	default:
+		msgWords = (msg->xMsgHeader.msgLength -
+				sizeof(struct SmsMsgHdr_ST))/4;
+
+		for (i = 0; i < msgWords; i++)
+			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+		break;
+	}
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
+
+void smsendian_handle_rx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	int i;
+	int msgWords;
+
+	switch (msg->xMsgHeader.msgType) {
+	case MSG_SMS_GET_VERSION_EX_RES:
+	{
+		struct SmsVersionRes_ST *ver =
+			(struct SmsVersionRes_ST *) msg;
+		ver->ChipModel = le16_to_cpu(ver->ChipModel);
+		break;
+	}
+
+	case MSG_SMS_DVBT_BDA_DATA:
+	case MSG_SMS_DAB_CHANNEL:
+	case MSG_SMS_DATA_MSG:
+	{
+		break;
+	}
+
+	default:
+	{
+		msgWords = (msg->xMsgHeader.msgLength -
+				sizeof(struct SmsMsgHdr_ST))/4;
+
+		for (i = 0; i < msgWords; i++)
+			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+		break;
+	}
+	}
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
+
+void smsendian_handle_message_header(void *msg)
+{
+#ifdef __BIG_ENDIAN
+	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
+
+	phdr->msgType = le16_to_cpu(phdr->msgType);
+	phdr->msgLength = le16_to_cpu(phdr->msgLength);
+	phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_message_header);
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsendian.h linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsendian.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsendian.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsendian.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,32 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, Uri Shkolnik
+
+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, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_ENDIAN_H__
+#define __SMS_ENDIAN_H__
+
+#include <asm/byteorder.h>
+
+extern void smsendian_handle_tx_message(void *buffer);
+extern void smsendian_handle_rx_message(void *buffer);
+extern void smsendian_handle_message_header(void *msg);
+
+#endif /* __SMS_ENDIAN_H__ */
+
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsir.c linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsir.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsir.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,301 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, Uri Shkolnik
+
+ 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, see <http://www.gnu.org/licenses/>.
+
+ ****************************************************************/
+
+
+#include <linux/types.h>
+#include <linux/input.h>
+
+#include "smscoreapi.h"
+#include "smsir.h"
+#include "sms-cards.h"
+
+/* In order to add new IR remote control -
+ * 1) Add it to the <enum ir_kb_type> @ smsir,h,
+ * 2) Add its map to keyboard_layout_maps below
+ * 3) Set your board (sms-cards sub-module) to use it
+ */
+
+static struct keyboard_layout_map_t keyboard_layout_maps[] = {
+		[SMS_IR_KB_DEFAULT_TV] = {
+			.ir_protocol = IR_RC5,
+			.rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
+			.keyboard_layout_map = {
+					KEY_0, KEY_1, KEY_2,
+					KEY_3, KEY_4, KEY_5,
+					KEY_6, KEY_7, KEY_8,
+					KEY_9, 0, 0, KEY_POWER,
+					KEY_MUTE, 0, 0,
+					KEY_VOLUMEUP, KEY_VOLUMEDOWN,
+					KEY_BRIGHTNESSUP,
+					KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
+					KEY_CHANNELDOWN,
+					0, 0, 0, 0, 0, 0, 0, 0,
+					0, 0, 0, 0, 0, 0, 0, 0,
+					0, 0, 0, 0, 0, 0, 0, 0,
+					0, 0, 0, 0, 0, 0, 0, 0,
+					0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+			}
+		},
+		[SMS_IR_KB_HCW_SILVER] = {
+			.ir_protocol = IR_RC5,
+			.rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
+			.keyboard_layout_map = {
+					KEY_0, KEY_1, KEY_2,
+					KEY_3, KEY_4, KEY_5,
+					KEY_6, KEY_7, KEY_8,
+					KEY_9, KEY_TEXT, KEY_RED,
+					KEY_RADIO, KEY_MENU,
+					KEY_SUBTITLE,
+					KEY_MUTE, KEY_VOLUMEUP,
+					KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
+					KEY_UP, KEY_DOWN, KEY_LEFT,
+					KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
+					KEY_MHP, KEY_EPG, KEY_TV,
+					0, KEY_NEXTSONG, KEY_EXIT,
+					KEY_CHANNELUP, 	KEY_CHANNELDOWN,
+					KEY_CHANNEL, 0,
+					KEY_PREVIOUSSONG, KEY_ENTER,
+					KEY_SLEEP, 0, 0, KEY_BLUE,
+					0, 0, 0, 0, KEY_GREEN, 0,
+					KEY_PAUSE, 0, KEY_REWIND,
+					0, KEY_FASTFORWARD, KEY_PLAY,
+					KEY_STOP, KEY_RECORD,
+					KEY_YELLOW, 0, 0, KEY_SELECT,
+					KEY_ZOOM, KEY_POWER, 0, 0
+			}
+		},
+		{ } /* Terminating entry */
+};
+
+u32 ir_pos;
+u32	ir_word;
+u32 ir_toggle;
+
+#define RC5_PUSH_BIT(dst, bit, pos)	\
+	{ dst <<= 1; dst |= bit; pos++; }
+
+
+static void sms_ir_rc5_event(struct smscore_device_t *coredev,
+				u32 toggle, u32 addr, u32 cmd)
+{
+	bool toggle_changed;
+	u16 keycode;
+
+	sms_log("IR RC5 word: address %d, command %d, toggle %d",
+				addr, cmd, toggle);
+
+	toggle_changed = ir_toggle != toggle;
+	/* keep toggle */
+	ir_toggle = toggle;
+
+	if (addr !=
+		keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
+		return; /* Check for valid address */
+
+	keycode =
+		keyboard_layout_maps
+		[coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
+
+	if (!toggle_changed &&
+			(keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
+		return; /* accept only repeated volume, reject other keys */
+
+	sms_log("kernel input keycode (from ir) %d", keycode);
+	input_report_key(coredev->ir.input_dev, keycode, 1);
+	input_sync(coredev->ir.input_dev);
+
+}
+
+/* decode raw bit pattern to RC5 code */
+/* taken from ir-functions.c */
+static u32 ir_rc5_decode(unsigned int code)
+{
+/*	unsigned int org_code = code;*/
+	unsigned int pair;
+	unsigned int rc5 = 0;
+	int i;
+
+	for (i = 0; i < 14; ++i) {
+		pair = code & 0x3;
+		code >>= 2;
+
+		rc5 <<= 1;
+		switch (pair) {
+		case 0:
+		case 2:
+			break;
+		case 1:
+			rc5 |= 1;
+			break;
+		case 3:
+/*	dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
+			sms_log("bad code");
+			return 0;
+		}
+	}
+/*
+	dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
+		toggle=%x, address=%x, "
+		"instr=%x\n", rc5, org_code, RC5_START(rc5),
+		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+*/
+	return rc5;
+}
+
+static void sms_rc5_parse_word(struct smscore_device_t *coredev)
+{
+	#define RC5_START(x)    (((x)>>12)&3)
+	#define RC5_TOGGLE(x)   (((x)>>11)&1)
+	#define RC5_ADDR(x)     (((x)>>6)&0x1F)
+	#define RC5_INSTR(x)    ((x)&0x3F)
+
+	int i, j;
+	u32 rc5_word = 0;
+
+	/* Reverse the IR word direction */
+	for (i = 0 ; i < 28 ; i++)
+		RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
+
+	rc5_word = ir_rc5_decode(rc5_word);
+	/* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
+
+	sms_ir_rc5_event(coredev,
+				RC5_TOGGLE(rc5_word),
+				RC5_ADDR(rc5_word),
+				RC5_INSTR(rc5_word));
+}
+
+
+static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
+		s32 ir_sample)
+{
+	#define RC5_TIME_GRANULARITY	200
+	#define RC5_DEF_BIT_TIME		889
+	#define RC5_MAX_SAME_BIT_CONT	4
+	#define RC5_WORD_LEN			27 /* 28 bit */
+
+	u32 i, j;
+	s32 delta_time;
+	u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
+	u32 level = (ir_sample < 0) ? 0 : 1;
+
+	for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) {
+		delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY;
+		if (delta_time < 0)
+			continue; /* not so many consecutive bits */
+		if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
+			/* timeout */
+			if (ir_pos == (RC5_WORD_LEN-1))
+				/* complete last bit */
+				RC5_PUSH_BIT(ir_word, level, ir_pos)
+
+			if (ir_pos == RC5_WORD_LEN)
+				sms_rc5_parse_word(coredev);
+			else if (ir_pos) /* timeout within a word */
+				sms_log("IR error parsing a word");
+
+			ir_pos = 0;
+			ir_word = 0;
+			/* sms_log("timeout %d", time); */
+			break;
+		}
+		/* The time is within the range of this number of bits */
+		for (j = 0 ; j < i ; j++)
+			RC5_PUSH_BIT(ir_word, level, ir_pos)
+
+		break;
+	}
+}
+
+void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
+{
+	#define IR_DATA_RECEIVE_MAX_LEN	520 /* 128*4 + 4 + 4 */
+	u32 i;
+	enum ir_protocol ir_protocol =
+			keyboard_layout_maps[coredev->ir.ir_kb_type]
+					     .ir_protocol;
+	s32 *samples;
+	int count = len>>2;
+
+	samples = (s32 *)buf;
+/*	sms_log("IR buffer received, length = %d", count);*/
+
+	for (i = 0; i < count; i++)
+		if (ir_protocol == IR_RC5)
+			sms_rc5_accumulate_bits(coredev, samples[i]);
+	/*  IR_RCMM not implemented */
+}
+
+int sms_ir_init(struct smscore_device_t *coredev)
+{
+	struct input_dev *input_dev;
+
+	sms_log("Allocating input device");
+	input_dev = input_allocate_device();
+	if (!input_dev)	{
+		sms_err("Not enough memory");
+		return -ENOMEM;
+	}
+
+	coredev->ir.input_dev = input_dev;
+	coredev->ir.ir_kb_type =
+		sms_get_board(smscore_get_board_id(coredev))->ir_kb_type;
+	coredev->ir.keyboard_layout_map =
+		keyboard_layout_maps[coredev->ir.ir_kb_type].
+				keyboard_layout_map;
+	sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type);
+
+	coredev->ir.controller = 0;	/* Todo: vega/nova SPI number */
+	coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
+	sms_log("IR port %d, timeout %d ms",
+			coredev->ir.controller, coredev->ir.timeout);
+
+	snprintf(coredev->ir.name,
+				IR_DEV_NAME_MAX_LEN,
+				"SMS IR w/kbd type %d",
+				coredev->ir.ir_kb_type);
+	input_dev->name = coredev->ir.name;
+	input_dev->phys = coredev->ir.name;
+	input_dev->dev.parent = coredev->device;
+
+	/* Key press events only */
+	input_dev->evbit[0] = BIT_MASK(EV_KEY);
+	input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+
+	sms_log("Input device (IR) %s is set for key events", input_dev->name);
+
+	if (input_register_device(input_dev)) {
+		sms_err("Failed to register device");
+		input_free_device(input_dev);
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+void sms_ir_exit(struct smscore_device_t *coredev)
+{
+	if (coredev->ir.input_dev)
+		input_unregister_device(coredev->ir.input_dev);
+
+	sms_log("");
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsir.h linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsir.h
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsir.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsir.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,93 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, Uri Shkolnik
+
+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, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_IR_H__
+#define __SMS_IR_H__
+
+#include <linux/input.h>
+
+#define IR_DEV_NAME_MAX_LEN		23 /* "SMS IR kbd type nn\0" */
+#define IR_KEYBOARD_LAYOUT_SIZE	64
+#define IR_DEFAULT_TIMEOUT		100
+
+enum ir_kb_type {
+	SMS_IR_KB_DEFAULT_TV,
+	SMS_IR_KB_HCW_SILVER
+};
+
+enum rc5_keyboard_address {
+	KEYBOARD_ADDRESS_TV1 = 0,
+	KEYBOARD_ADDRESS_TV2 = 1,
+	KEYBOARD_ADDRESS_TELETEXT = 2,
+	KEYBOARD_ADDRESS_VIDEO = 3,
+	KEYBOARD_ADDRESS_LV1 = 4,
+	KEYBOARD_ADDRESS_VCR1 = 5,
+	KEYBOARD_ADDRESS_VCR2 = 6,
+	KEYBOARD_ADDRESS_EXPERIMENTAL = 7,
+	KEYBOARD_ADDRESS_SAT1 = 8,
+	KEYBOARD_ADDRESS_CAMERA = 9,
+	KEYBOARD_ADDRESS_SAT2 = 10,
+	KEYBOARD_ADDRESS_CDV = 12,
+	KEYBOARD_ADDRESS_CAMCORDER = 13,
+	KEYBOARD_ADDRESS_PRE_AMP = 16,
+	KEYBOARD_ADDRESS_TUNER = 17,
+	KEYBOARD_ADDRESS_RECORDER1 = 18,
+	KEYBOARD_ADDRESS_PRE_AMP1 = 19,
+	KEYBOARD_ADDRESS_CD_PLAYER = 20,
+	KEYBOARD_ADDRESS_PHONO = 21,
+	KEYBOARD_ADDRESS_SATA = 22,
+	KEYBOARD_ADDRESS_RECORDER2 = 23,
+	KEYBOARD_ADDRESS_CDR = 26,
+	KEYBOARD_ADDRESS_LIGHTING = 29,
+	KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */
+	KEYBOARD_ADDRESS_PHONE = 31,
+	KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF
+};
+
+enum ir_protocol {
+	IR_RC5,
+	IR_RCMM
+};
+
+struct keyboard_layout_map_t {
+	enum ir_protocol ir_protocol;
+	enum rc5_keyboard_address rc5_kbd_address;
+	u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE];
+};
+
+struct smscore_device_t;
+
+struct ir_t {
+	struct input_dev *input_dev;
+	enum ir_kb_type ir_kb_type;
+	char name[IR_DEV_NAME_MAX_LEN+1];
+	u16 *keyboard_layout_map;
+	u32 timeout;
+	u32 controller;
+};
+
+int sms_ir_init(struct smscore_device_t *coredev);
+void sms_ir_exit(struct smscore_device_t *coredev);
+void sms_ir_event(struct smscore_device_t *coredev,
+			const char *buf, int len);
+
+#endif /* __SMS_IR_H__ */
+
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smssdio.c linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smssdio.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smssdio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smssdio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,363 @@
+/*
+ *  smssdio.c - Siano 1xxx SDIO interface driver
+ *
+ *  Copyright 2008 Pierre Ossman
+ *
+ * Based on code by Siano Mobile Silicon, Inc.,
+ * Copyright (C) 2006-2008, Uri Shkolnik
+ *
+ * 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 hardware is a bit odd in that all transfers should be done
+ * to/from the SMSSDIO_DATA register, yet the "increase address" bit
+ * always needs to be set.
+ *
+ * Also, buffers from the card are always aligned to 128 byte
+ * boundaries.
+ */
+
+/*
+ * General cleanup notes:
+ *
+ * - only typedefs should be name *_t
+ *
+ * - use ERR_PTR and friends for smscore_register_device()
+ *
+ * - smscore_getbuffer should zero fields
+ *
+ * Fix stop command
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+/* Registers */
+
+#define SMSSDIO_DATA		0x00
+#define SMSSDIO_INT		0x04
+#define SMSSDIO_BLOCK_SIZE	128
+
+static const struct sdio_device_id smssdio_ids[] = {
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
+	 .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
+	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+	{ /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, smssdio_ids);
+
+struct smssdio_device {
+	struct sdio_func *func;
+
+	struct smscore_device_t *coredev;
+
+	struct smscore_buffer_t *split_cb;
+};
+
+/*******************************************************************/
+/* Siano core callbacks                                            */
+/*******************************************************************/
+
+static int smssdio_sendrequest(void *context, void *buffer, size_t size)
+{
+	int ret;
+	struct smssdio_device *smsdev;
+
+	smsdev = context;
+
+	sdio_claim_host(smsdev->func);
+
+	while (size >= smsdev->func->cur_blksize) {
+		ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+					buffer, smsdev->func->cur_blksize);
+		if (ret)
+			goto out;
+
+		buffer += smsdev->func->cur_blksize;
+		size -= smsdev->func->cur_blksize;
+	}
+
+	if (size) {
+		ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+					buffer, size);
+	}
+
+out:
+	sdio_release_host(smsdev->func);
+
+	return ret;
+}
+
+/*******************************************************************/
+/* SDIO callbacks                                                  */
+/*******************************************************************/
+
+static void smssdio_interrupt(struct sdio_func *func)
+{
+	int ret, isr;
+
+	struct smssdio_device *smsdev;
+	struct smscore_buffer_t *cb;
+	struct SmsMsgHdr_ST *hdr;
+	size_t size;
+
+	smsdev = sdio_get_drvdata(func);
+
+	/*
+	 * The interrupt register has no defined meaning. It is just
+	 * a way of turning of the level triggered interrupt.
+	 */
+	isr = sdio_readb(func, SMSSDIO_INT, &ret);
+	if (ret) {
+		sms_err("Unable to read interrupt register!\n");
+		return;
+	}
+
+	if (smsdev->split_cb == NULL) {
+		cb = smscore_getbuffer(smsdev->coredev);
+		if (!cb) {
+			sms_err("Unable to allocate data buffer!\n");
+			return;
+		}
+
+		ret = sdio_memcpy_fromio(smsdev->func,
+					 cb->p,
+					 SMSSDIO_DATA,
+					 SMSSDIO_BLOCK_SIZE);
+		if (ret) {
+			sms_err("Error %d reading initial block!\n", ret);
+			return;
+		}
+
+		hdr = cb->p;
+
+		if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
+			smsdev->split_cb = cb;
+			return;
+		}
+
+		if (hdr->msgLength > smsdev->func->cur_blksize)
+			size = hdr->msgLength - smsdev->func->cur_blksize;
+		else
+			size = 0;
+	} else {
+		cb = smsdev->split_cb;
+		hdr = cb->p;
+
+		size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
+
+		smsdev->split_cb = NULL;
+	}
+
+	if (size) {
+		void *buffer;
+
+		buffer = cb->p + (hdr->msgLength - size);
+		size = ALIGN(size, SMSSDIO_BLOCK_SIZE);
+
+		BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE);
+
+		/*
+		 * First attempt to transfer all of it in one go...
+		 */
+		ret = sdio_memcpy_fromio(smsdev->func,
+					 buffer,
+					 SMSSDIO_DATA,
+					 size);
+		if (ret && ret != -EINVAL) {
+			smscore_putbuffer(smsdev->coredev, cb);
+			sms_err("Error %d reading data from card!\n", ret);
+			return;
+		}
+
+		/*
+		 * ..then fall back to one block at a time if that is
+		 * not possible...
+		 *
+		 * (we have to do this manually because of the
+		 * problem with the "increase address" bit)
+		 */
+		if (ret == -EINVAL) {
+			while (size) {
+				ret = sdio_memcpy_fromio(smsdev->func,
+						  buffer, SMSSDIO_DATA,
+						  smsdev->func->cur_blksize);
+				if (ret) {
+					smscore_putbuffer(smsdev->coredev, cb);
+					sms_err("Error %d reading "
+						"data from card!\n", ret);
+					return;
+				}
+
+				buffer += smsdev->func->cur_blksize;
+				if (size > smsdev->func->cur_blksize)
+					size -= smsdev->func->cur_blksize;
+				else
+					size = 0;
+			}
+		}
+	}
+
+	cb->size = hdr->msgLength;
+	cb->offset = 0;
+
+	smscore_onresponse(smsdev->coredev, cb);
+}
+
+static int smssdio_probe(struct sdio_func *func,
+			 const struct sdio_device_id *id)
+{
+	int ret;
+
+	int board_id;
+	struct smssdio_device *smsdev;
+	struct smsdevice_params_t params;
+
+	board_id = id->driver_data;
+
+	smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
+	if (!smsdev)
+		return -ENOMEM;
+
+	smsdev->func = func;
+
+	memset(&params, 0, sizeof(struct smsdevice_params_t));
+
+	params.device = &func->dev;
+	params.buffer_size = 0x5000;	/* ?? */
+	params.num_buffers = 22;	/* ?? */
+	params.context = smsdev;
+
+	snprintf(params.devpath, sizeof(params.devpath),
+		 "sdio\\%s", sdio_func_id(func));
+
+	params.sendrequest_handler = smssdio_sendrequest;
+
+	params.device_type = sms_get_board(board_id)->type;
+
+	if (params.device_type != SMS_STELLAR)
+		params.flags |= SMS_DEVICE_FAMILY2;
+	else {
+		/*
+		 * FIXME: Stellar needs special handling...
+		 */
+		ret = -ENODEV;
+		goto free;
+	}
+
+	ret = smscore_register_device(&params, &smsdev->coredev);
+	if (ret < 0)
+		goto free;
+
+	smscore_set_board_id(smsdev->coredev, board_id);
+
+	sdio_claim_host(func);
+
+	ret = sdio_enable_func(func);
+	if (ret)
+		goto release;
+
+	ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE);
+	if (ret)
+		goto disable;
+
+	ret = sdio_claim_irq(func, smssdio_interrupt);
+	if (ret)
+		goto disable;
+
+	sdio_set_drvdata(func, smsdev);
+
+	sdio_release_host(func);
+
+	ret = smscore_start_device(smsdev->coredev);
+	if (ret < 0)
+		goto reclaim;
+
+	return 0;
+
+reclaim:
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+disable:
+	sdio_disable_func(func);
+release:
+	sdio_release_host(func);
+	smscore_unregister_device(smsdev->coredev);
+free:
+	kfree(smsdev);
+
+	return ret;
+}
+
+static void smssdio_remove(struct sdio_func *func)
+{
+	struct smssdio_device *smsdev;
+
+	smsdev = sdio_get_drvdata(func);
+
+	/* FIXME: racy! */
+	if (smsdev->split_cb)
+		smscore_putbuffer(smsdev->coredev, smsdev->split_cb);
+
+	smscore_unregister_device(smsdev->coredev);
+
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+
+	kfree(smsdev);
+}
+
+static struct sdio_driver smssdio_driver = {
+	.name = "smssdio",
+	.id_table = smssdio_ids,
+	.probe = smssdio_probe,
+	.remove = smssdio_remove,
+};
+
+/*******************************************************************/
+/* Module functions                                                */
+/*******************************************************************/
+
+int smssdio_module_init(void)
+{
+	int ret = 0;
+
+	printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n");
+	printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n");
+
+	ret = sdio_register_driver(&smssdio_driver);
+
+	return ret;
+}
+
+void smssdio_module_exit(void)
+{
+	sdio_unregister_driver(&smssdio_driver);
+}
+
+module_init(smssdio_module_init);
+module_exit(smssdio_module_exit);
+
+MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
+MODULE_AUTHOR("Pierre Ossman");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsusb.c linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsusb.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/siano/smsusb.c	2012-03-22 19:13:01.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/siano/smsusb.c	2012-03-22 20:09:21.000000000 -0400
@@ -1,23 +1,23 @@
-/*
- *  Driver for the Siano SMS1xxx USB dongle
- *
- *  author: Anatoly Greenblat
- *
- *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation;
- *
- *  Software distributed under the License is distributed on an "AS IS"
- *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- *
- *  See the 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.
- */
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat
+
+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, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
 
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -26,6 +26,7 @@
 
 #include "smscoreapi.h"
 #include "sms-cards.h"
+#include "smsendian.h"
 
 static int sms_dbg;
 module_param_named(debug, sms_dbg, int, 0644);
@@ -64,15 +65,16 @@
 	struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
 	struct smsusb_device_t *dev = surb->dev;
 
-	if (urb->status < 0) {
-		sms_err("error, urb status %d, %d bytes",
+	if (urb->status == -ESHUTDOWN) {
+		sms_err("error, urb status %d (-ESHUTDOWN), %d bytes",
 			urb->status, urb->actual_length);
 		return;
 	}
 
-	if (urb->actual_length > 0) {
-		struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p;
+	if ((urb->actual_length > 0) && (urb->status == 0)) {
+		struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p;
 
+		smsendian_handle_message_header(phdr);
 		if (urb->actual_length >= phdr->msgLength) {
 			surb->cb->size = phdr->msgLength;
 
@@ -109,7 +111,10 @@
 				"msglen %d actual %d",
 				phdr->msgLength, urb->actual_length);
 		}
-	}
+	} else
+		sms_err("error, urb status %d, %d bytes",
+			urb->status, urb->actual_length);
+
 
 exit_and_resubmit:
 	smsusb_submit_urb(dev, surb);
@@ -176,6 +181,7 @@
 	struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
 	int dummy;
 
+	smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer);
 	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
 			    buffer, size, &dummy, 1000);
 }
@@ -333,8 +339,8 @@
 	case SMS_VEGA:
 		dev->buffer_size = USB2_BUFFER_SIZE;
 		dev->response_alignment =
-			dev->udev->ep_in[1]->desc.wMaxPacketSize -
-			sizeof(struct SmsMsgHdr_ST);
+		    le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
+		    sizeof(struct SmsMsgHdr_ST);
 
 		params.flags |= SMS_DEVICE_FAMILY2;
 		break;
@@ -479,7 +485,6 @@
 }
 
 struct usb_device_id smsusb_id_table[] = {
-#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
 	{ USB_DEVICE(0x187f, 0x0010),
 		.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
 	{ USB_DEVICE(0x187f, 0x0100),
@@ -490,7 +495,6 @@
 		.driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
 	{ USB_DEVICE(0x187f, 0x0300),
 		.driver_info = SMS1XXX_BOARD_SIANO_VEGA },
-#endif
 	{ USB_DEVICE(0x2040, 0x1700),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
 	{ USB_DEVICE(0x2040, 0x1800),
@@ -521,8 +525,13 @@
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0x5590),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ }		/* Terminating entry */
-};
+	{ USB_DEVICE(0x187f, 0x0202),
+		.driver_info = SMS1XXX_BOARD_SIANO_NICE },
+	{ USB_DEVICE(0x187f, 0x0301),
+		.driver_info = SMS1XXX_BOARD_SIANO_VENICE },
+	{ } /* Terminating entry */
+	};
+
 MODULE_DEVICE_TABLE(usb, smsusb_id_table);
 
 static struct usb_driver smsusb_driver = {
@@ -548,14 +557,14 @@
 
 void smsusb_module_exit(void)
 {
-	sms_debug("");
 	/* Regular USB Cleanup */
 	usb_deregister(&smsusb_driver);
+	sms_info("end");
 }
 
 module_init(smsusb_module_init);
 module_exit(smsusb_module_exit);
 
-MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
+MODULE_DESCRIPTION("Driver for the Siano SMS1xxx USB dongle");
 MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110_av.c linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110_av.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110_av.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110_av.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,6 +89,7 @@
 
 static void p_to_t(u8 const *buf, long int length, u16 pid,
 		   u8 *counter, struct dvb_demux_feed *feed);
+static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len);
 
 
 int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
@@ -192,8 +193,6 @@
 		ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
 		break;
 	}
-	if (!ret)
-		ret = av7110->playing;
 	return ret;
 }
 
@@ -437,6 +436,45 @@
 	aux_ring_buffer_write(&av7110->aout, buf, count);
 }
 
+
+#define FREE_COND_TS (dvb_ringbuffer_free(rb) >= 4096)
+
+static ssize_t ts_play(struct av7110 *av7110, const char __user *buf,
+		       unsigned long count, int nonblock, int type)
+{
+	struct dvb_ringbuffer *rb;
+	u8 *kb;
+	unsigned long todo = count;
+
+	dprintk(2, "%s: type %d cnt %lu\n", __func__, type, count);
+
+	rb = (type) ? &av7110->avout : &av7110->aout;
+	kb = av7110->kbuf[type];
+
+	if (!kb)
+		return -ENOBUFS;
+
+	if (nonblock && !FREE_COND_TS)
+		return -EWOULDBLOCK;
+
+	while (todo >= TS_SIZE) {
+		if (!FREE_COND_TS) {
+			if (nonblock)
+				return count - todo;
+			if (wait_event_interruptible(rb->queue, FREE_COND_TS))
+				return count - todo;
+		}
+		if (copy_from_user(kb, buf, TS_SIZE))
+			return -EFAULT;
+		write_ts_to_decoder(av7110, type, kb, TS_SIZE);
+		todo -= TS_SIZE;
+		buf += TS_SIZE;
+	}
+
+	return count - todo;
+}
+
+
 #define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \
 		   dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
 
@@ -780,11 +818,37 @@
 }
 
 
+static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len)
+{
+	struct ipack *ipack = &av7110->ipack[type];
+
+	if (buf[1] & TRANS_ERROR) {
+		av7110_ipack_reset(ipack);
+		return -1;
+	}
+
+	if (!(buf[3] & PAYLOAD))
+		return -1;
+
+	if (buf[1] & PAY_START)
+		av7110_ipack_flush(ipack);
+
+	if (buf[3] & ADAPT_FIELD) {
+		len -= buf[4] + 1;
+		buf += buf[4] + 1;
+		if (!len)
+			return 0;
+	}
+
+	av7110_ipack_instant_repack(buf + 4, len - 4, ipack);
+	return 0;
+}
+
+
 int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len)
 {
 	struct dvb_demux *demux = feed->demux;
 	struct av7110 *av7110 = (struct av7110 *) demux->priv;
-	struct ipack *ipack = &av7110->ipack[feed->pes_type];
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
@@ -804,20 +868,7 @@
 		return -1;
 	}
 
-	if (!(buf[3] & 0x10)) /* no payload? */
-		return -1;
-	if (buf[1] & 0x40)
-		av7110_ipack_flush(ipack);
-
-	if (buf[3] & 0x20) {  /* adaptation field? */
-		len -= buf[4] + 1;
-		buf += buf[4] + 1;
-		if (!len)
-			return 0;
-	}
-
-	av7110_ipack_instant_repack(buf + 4, len - 4, &av7110->ipack[feed->pes_type]);
-	return 0;
+	return write_ts_to_decoder(av7110, feed->pes_type, buf, len);
 }
 
 
@@ -916,6 +967,7 @@
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct av7110 *av7110 = dvbdev->priv;
+	unsigned char c;
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
@@ -925,7 +977,12 @@
 	if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY)
 		return -EPERM;
 
-	return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
+	if (get_user(c, buf))
+		return -EFAULT;
+	if (c == 0x47 && count % TS_SIZE == 0)
+		return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
+	else
+		return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
 }
 
 static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
@@ -952,6 +1009,7 @@
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct av7110 *av7110 = dvbdev->priv;
+	unsigned char c;
 
 	dprintk(2, "av7110:%p, \n", av7110);
 
@@ -959,7 +1017,13 @@
 		printk(KERN_ERR "not audio source memory\n");
 		return -EPERM;
 	}
-	return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
+
+	if (get_user(c, buf))
+		return -EFAULT;
+	if (c == 0x47 && count % TS_SIZE == 0)
+		return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
+	else
+		return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
 }
 
 static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
@@ -1062,7 +1126,6 @@
 			if (ret)
 				break;
 		}
-
 		if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) {
 			if (av7110->playing == RP_AV) {
 				ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
@@ -1122,20 +1185,16 @@
 	case VIDEO_SET_DISPLAY_FORMAT:
 	{
 		video_displayformat_t format = (video_displayformat_t) arg;
-
 		switch (format) {
 		case VIDEO_PAN_SCAN:
 			av7110->display_panscan = VID_PAN_SCAN_PREF;
 			break;
-
 		case VIDEO_LETTER_BOX:
 			av7110->display_panscan = VID_VC_AND_PS_PREF;
 			break;
-
 		case VIDEO_CENTER_CUT_OUT:
 			av7110->display_panscan = VID_CENTRE_CUT_PREF;
 			break;
-
 		default:
 			ret = -EINVAL;
 		}
@@ -1183,7 +1242,8 @@
 
 	case VIDEO_SLOWMOTION:
 		if (av7110->playing&RP_VIDEO) {
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
+			if (av7110->trickmode != TRICK_SLOW)
+				ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
 			if (!ret)
 				ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
 		} else {
@@ -1207,7 +1267,6 @@
 	case VIDEO_CLEAR_BUFFER:
 		dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
 		av7110_ipack_reset(&av7110->ipack[1]);
-
 		if (av7110->playing == RP_AV) {
 			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
 					    __Play, 2, AV_PES, 0);
@@ -1228,13 +1287,13 @@
 		break;
 
 	case VIDEO_SET_STREAMTYPE:
-
 		break;
 
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
 	}
+
 	return ret;
 }
 
@@ -1309,7 +1368,6 @@
 
 	case AUDIO_CHANNEL_SELECT:
 		av7110->audiostate.channel_select = (audio_channel_select_t) arg;
-
 		switch(av7110->audiostate.channel_select) {
 		case AUDIO_STEREO:
 			ret = audcom(av7110, AUDIO_CMD_STEREO);
@@ -1320,7 +1378,6 @@
 					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220);
 			}
 			break;
-
 		case AUDIO_MONO_LEFT:
 			ret = audcom(av7110, AUDIO_CMD_MONO_L);
 			if (!ret) {
@@ -1330,7 +1387,6 @@
 					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200);
 			}
 			break;
-
 		case AUDIO_MONO_RIGHT:
 			ret = audcom(av7110, AUDIO_CMD_MONO_R);
 			if (!ret) {
@@ -1340,7 +1396,6 @@
 					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210);
 			}
 			break;
-
 		default:
 			ret = -EINVAL;
 			break;
@@ -1366,21 +1421,24 @@
 			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
 					    __Play, 2, AV_PES, 0);
 		break;
-	case AUDIO_SET_ID:
 
+	case AUDIO_SET_ID:
 		break;
+
 	case AUDIO_SET_MIXER:
 	{
 		struct audio_mixer *amix = (struct audio_mixer *)parg;
-
 		ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
 		break;
 	}
+
 	case AUDIO_SET_STREAMTYPE:
 		break;
+
 	default:
 		ret = -ENOIOCTLCMD;
 	}
+
 	return ret;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110.c linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110.c	2012-03-22 19:12:53.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110.c	2012-03-22 20:09:12.000000000 -0400
@@ -36,7 +36,6 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110_hw.c linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110_hw.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110_hw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110_hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -1089,7 +1089,7 @@
 		else {
 			int i, len = dc->x0-dc->color+1;
 			u8 __user *colors = (u8 __user *)dc->data;
-			u8 r, g, b, blend;
+			u8 r, g = 0, b = 0, blend = 0;
 			ret = 0;
 			for (i = 0; i<len; i++) {
 				if (get_user(r, colors + i * 4) ||
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110_v4l.c linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110_v4l.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/av7110_v4l.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/av7110_v4l.c	2009-09-09 18:13:59.000000000 -0400
@@ -458,7 +458,7 @@
 	dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
 
 	if (av7110->analog_tuner_flags) {
-		if (i->index < 0 || i->index >= 4)
+		if (i->index >= 4)
 			return -EINVAL;
 	} else {
 		if (i->index != 0)
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/budget-av.c linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/budget-av.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/budget-av.c	2012-03-22 19:12:53.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/budget-av.c	2012-03-22 20:09:12.000000000 -0400
@@ -1413,7 +1413,7 @@
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
 	dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
-	if (i->index < 0 || i->index >= KNC1_INPUTS)
+	if (i->index >= KNC1_INPUTS)
 		return -EINVAL;
 	memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/budget.c linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/budget.c
--- linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/budget.c	2012-03-22 19:12:53.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/budget.c	2012-03-22 20:09:12.000000000 -0400
@@ -47,6 +47,9 @@
 #include "bsru6.h"
 #include "bsbe1.h"
 #include "tdhd1.h"
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "isl6423.h"
 
 static int diseqc_method;
 module_param(diseqc_method, int, 0444);
@@ -425,6 +428,44 @@
 	return pwm;
 }
 
+static struct stv090x_config tt1600_stv090x_config = {
+	.device			= STV0903,
+	.demod_mode		= STV090x_SINGLE,
+	.clk_mode		= STV090x_CLK_EXT,
+
+	.xtal			= 27000000,
+	.address		= 0x68,
+	.ref_clk		= 27000000,
+
+	.ts1_mode		= STV090x_TSMODE_DVBCI,
+	.ts2_mode		= STV090x_TSMODE_SERIAL_CONTINUOUS,
+
+	.repeater_level		= STV090x_RPTLEVEL_16,
+
+	.tuner_init		= NULL,
+	.tuner_set_mode		= NULL,
+	.tuner_set_frequency	= NULL,
+	.tuner_get_frequency	= NULL,
+	.tuner_set_bandwidth	= NULL,
+	.tuner_get_bandwidth	= NULL,
+	.tuner_set_bbgain	= NULL,
+	.tuner_get_bbgain	= NULL,
+	.tuner_set_refclk	= NULL,
+	.tuner_get_status	= NULL,
+};
+
+static struct stv6110x_config tt1600_stv6110x_config = {
+	.addr			= 0x60,
+	.refclk			= 27000000,
+};
+
+static struct isl6423_config tt1600_isl6423_config = {
+	.current_max		= SEC_CURRENT_515m,
+	.curlim			= SEC_CURRENT_LIM_ON,
+	.mod_extern		= 1,
+	.addr			= 0x08,
+};
+
 static void frontend_init(struct budget *budget)
 {
 	(void)alps_bsbe1_config; /* avoid warning */
@@ -566,6 +607,48 @@
 			}
 			break;
 		}
+
+	case 0x101c: { /* TT S2-1600 */
+			struct stv6110x_devctl *ctl;
+			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
+			msleep(50);
+			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
+			msleep(250);
+
+			budget->dvb_frontend = dvb_attach(stv090x_attach,
+							  &tt1600_stv090x_config,
+							  &budget->i2c_adap,
+							  STV090x_DEMODULATOR_0);
+
+			if (budget->dvb_frontend) {
+
+				ctl = dvb_attach(stv6110x_attach,
+						 budget->dvb_frontend,
+						 &tt1600_stv6110x_config,
+						 &budget->i2c_adap);
+
+				tt1600_stv090x_config.tuner_init	  = ctl->tuner_init;
+				tt1600_stv090x_config.tuner_set_mode	  = ctl->tuner_set_mode;
+				tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
+				tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
+				tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+				tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+				tt1600_stv090x_config.tuner_set_bbgain	  = ctl->tuner_set_bbgain;
+				tt1600_stv090x_config.tuner_get_bbgain	  = ctl->tuner_get_bbgain;
+				tt1600_stv090x_config.tuner_set_refclk	  = ctl->tuner_set_refclk;
+				tt1600_stv090x_config.tuner_get_status	  = ctl->tuner_get_status;
+
+				dvb_attach(isl6423_attach,
+					budget->dvb_frontend,
+					&budget->i2c_adap,
+					&tt1600_isl6423_config);
+
+			} else {
+				dvb_frontend_detach(budget->dvb_frontend);
+				budget->dvb_frontend = NULL;
+			}
+		}
+		break;
 	}
 
 	if (budget->dvb_frontend == NULL) {
@@ -641,6 +724,7 @@
 MAKE_BUDGET_INFO(ttbt,	"TT-Budget/WinTV-NOVA-T  PCI",	BUDGET_TT);
 MAKE_BUDGET_INFO(satel,	"SATELCO Multimedia PCI",	BUDGET_TT_HW_DISEQC);
 MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsact,	 "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
@@ -653,6 +737,7 @@
 	MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
 	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1016),
 	MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
+	MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c),
 	MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
 	MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
 	MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
diff -druN linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/Kconfig linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/dvb/ttpci/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/dvb/ttpci/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,6 @@
 config TTPCI_EEPROM
 	tristate
+	depends on I2C
 	default n
 
 config DVB_AV7110
diff -druN linux-libre-2.6.30-gnu/drivers/media/Kconfig linux-libre-2.6.31-gnu/drivers/media/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -2,8 +2,14 @@
 # Multimedia device configuration
 #
 
-menu "Multimedia devices"
+menuconfig MEDIA_SUPPORT
+	tristate "Multimedia support"
 	depends on HAS_IOMEM
+	help
+	  If you want to use Video for Linux, DVB for Linux, or DAB adapters,
+	  enable this option and other options below.
+
+if MEDIA_SUPPORT
 
 comment "Multimedia core support"
 
@@ -136,4 +142,4 @@
 	  module will be called dabusb.
 endif # DAB
 
-endmenu
+endif # MEDIA_SUPPORT
diff -druN linux-libre-2.6.30-gnu/drivers/media/radio/dsbr100.c linux-libre-2.6.31-gnu/drivers/media/radio/dsbr100.c
--- linux-libre-2.6.30-gnu/drivers/media/radio/dsbr100.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/radio/dsbr100.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,6 +33,10 @@
 
  History:
 
+ Version 0.46:
+	Removed usb_dsbr100_open/close calls and radio->users counter. Also,
+	radio->muted changed to radio->status and suspend/resume calls updated.
+
  Version 0.45:
 	Converted to v4l2_device.
 
@@ -100,8 +104,8 @@
  */
 #include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
 
-#define DRIVER_VERSION "v0.45"
-#define RADIO_VERSION KERNEL_VERSION(0, 4, 5)
+#define DRIVER_VERSION "v0.46"
+#define RADIO_VERSION KERNEL_VERSION(0, 4, 6)
 
 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
@@ -121,13 +125,15 @@
 #define FREQ_MAX 108.0
 #define FREQ_MUL 16000
 
+/* defines for radio->status */
+#define STARTED	0
+#define STOPPED	1
+
 #define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev)
 
 static int usb_dsbr100_probe(struct usb_interface *intf,
 			     const struct usb_device_id *id);
 static void usb_dsbr100_disconnect(struct usb_interface *intf);
-static int usb_dsbr100_open(struct file *file);
-static int usb_dsbr100_close(struct file *file);
 static int usb_dsbr100_suspend(struct usb_interface *intf,
 						pm_message_t message);
 static int usb_dsbr100_resume(struct usb_interface *intf);
@@ -145,9 +151,8 @@
 	struct mutex lock;	/* buffer locking */
 	int curfreq;
 	int stereo;
-	int users;
 	int removed;
-	int muted;
+	int status;
 };
 
 static struct usb_device_id usb_dsbr100_device_table [] = {
@@ -201,7 +206,7 @@
 		goto usb_control_msg_failed;
 	}
 
-	radio->muted = 0;
+	radio->status = STARTED;
 	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
 
@@ -244,7 +249,7 @@
 		goto usb_control_msg_failed;
 	}
 
-	radio->muted = 1;
+	radio->status = STOPPED;
 	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
 
@@ -258,12 +263,12 @@
 }
 
 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
-static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
+static int dsbr100_setfreq(struct dsbr100_device *radio)
 {
 	int retval;
 	int request;
+	int freq = (radio->curfreq / 16 * 80) / 1000 + 856;
 
-	freq = (freq / 16 * 80) / 1000 + 856;
 	mutex_lock(&radio->lock);
 
 	retval = usb_control_msg(radio->usbdev,
@@ -431,7 +436,7 @@
 	radio->curfreq = f->frequency;
 	mutex_unlock(&radio->lock);
 
-	retval = dsbr100_setfreq(radio, radio->curfreq);
+	retval = dsbr100_setfreq(radio);
 	if (retval < 0)
 		dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
 	return 0;
@@ -473,7 +478,7 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = radio->muted;
+		ctrl->value = radio->status;
 		return 0;
 	}
 	return -EINVAL;
@@ -543,65 +548,27 @@
 	return 0;
 }
 
-static int usb_dsbr100_open(struct file *file)
-{
-	struct dsbr100_device *radio = video_drvdata(file);
-	int retval;
-
-	lock_kernel();
-	radio->users = 1;
-	radio->muted = 1;
-
-	retval = dsbr100_start(radio);
-	if (retval < 0) {
-		dev_warn(&radio->usbdev->dev,
-			 "Radio did not start up properly\n");
-		radio->users = 0;
-		unlock_kernel();
-		return -EIO;
-	}
-
-	retval = dsbr100_setfreq(radio, radio->curfreq);
-	if (retval < 0)
-		dev_warn(&radio->usbdev->dev,
-			"set frequency failed\n");
-
-	unlock_kernel();
-	return 0;
-}
-
-static int usb_dsbr100_close(struct file *file)
-{
-	struct dsbr100_device *radio = video_drvdata(file);
-	int retval;
-
-	if (!radio)
-		return -ENODEV;
-
-	mutex_lock(&radio->lock);
-	radio->users = 0;
-	mutex_unlock(&radio->lock);
-
-	if (!radio->removed) {
-		retval = dsbr100_stop(radio);
-		if (retval < 0) {
-			dev_warn(&radio->usbdev->dev,
-				"dsbr100_stop failed\n");
-		}
-
-	}
-	return 0;
-}
-
 /* Suspend device - stop device. */
 static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct dsbr100_device *radio = usb_get_intfdata(intf);
 	int retval;
 
-	retval = dsbr100_stop(radio);
-	if (retval < 0)
-		dev_warn(&intf->dev, "dsbr100_stop failed\n");
+	if (radio->status == STARTED) {
+		retval = dsbr100_stop(radio);
+		if (retval < 0)
+			dev_warn(&intf->dev, "dsbr100_stop failed\n");
+
+		/* After dsbr100_stop() status set to STOPPED.
+		 * If we want driver to start radio on resume
+		 * we set status equal to STARTED.
+		 * On resume we will check status and run radio if needed.
+		 */
+
+		mutex_lock(&radio->lock);
+		radio->status = STARTED;
+		mutex_unlock(&radio->lock);
+	}
 
 	dev_info(&intf->dev, "going into suspend..\n");
 
@@ -614,9 +581,11 @@
 	struct dsbr100_device *radio = usb_get_intfdata(intf);
 	int retval;
 
-	retval = dsbr100_start(radio);
-	if (retval < 0)
-		dev_warn(&intf->dev, "dsbr100_start failed\n");
+	if (radio->status == STARTED) {
+		retval = dsbr100_start(radio);
+		if (retval < 0)
+			dev_warn(&intf->dev, "dsbr100_start failed\n");
+	}
 
 	dev_info(&intf->dev, "coming out of suspend..\n");
 
@@ -636,8 +605,6 @@
 /* File system interface */
 static const struct v4l2_file_operations usb_dsbr100_fops = {
 	.owner		= THIS_MODULE,
-	.open		= usb_dsbr100_open,
-	.release	= usb_dsbr100_close,
 	.ioctl		= video_ioctl2,
 };
 
@@ -695,9 +662,9 @@
 	mutex_init(&radio->lock);
 
 	radio->removed = 0;
-	radio->users = 0;
 	radio->usbdev = interface_to_usbdev(intf);
 	radio->curfreq = FREQ_MIN * FREQ_MUL;
+	radio->status = STOPPED;
 
 	video_set_drvdata(&radio->videodev, radio);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/radio/radio-mr800.c linux-libre-2.6.31-gnu/drivers/media/radio/radio-mr800.c
--- linux-libre-2.6.30-gnu/drivers/media/radio/radio-mr800.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/radio/radio-mr800.c	2009-09-09 18:13:59.000000000 -0400
@@ -58,12 +58,14 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <linux/usb.h>
 #include <linux/version.h>	/* for KERNEL_VERSION MACRO */
+#include <linux/mutex.h>
 
 /* driver and module definitions */
 #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
diff -druN linux-libre-2.6.30-gnu/drivers/media/radio/radio-sf16fmi.c linux-libre-2.6.31-gnu/drivers/media/radio/radio-sf16fmi.c
--- linux-libre-2.6.30-gnu/drivers/media/radio/radio-sf16fmi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/radio/radio-sf16fmi.c	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,6 @@
 	int io;
 	int curvol; /* 1 or 0 */
 	unsigned long curfreq; /* freq in kHz */
-	__u32 flags;
 	struct mutex lock;
 };
 
@@ -57,7 +56,7 @@
 static struct pnp_dev *dev;
 
 /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
-/* It is only useful to give freq in intervall of 800 (=0.05Mhz),
+/* It is only useful to give freq in interval of 800 (=0.05Mhz),
  * other bits will be truncated, e.g 92.7400016 -> 92.7, but
  * 92.7400017 -> 92.75
  */
@@ -142,7 +141,6 @@
 static int vidioc_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	int mult;
 	struct fmi *fmi = video_drvdata(file);
 
 	if (v->index > 0)
@@ -150,11 +148,10 @@
 
 	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-	mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
-	v->rangelow = RSF16_MINFREQ / mult;
-	v->rangehigh = RSF16_MAXFREQ / mult;
+	v->rangelow = RSF16_MINFREQ;
+	v->rangehigh = RSF16_MAXFREQ;
 	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-	v->capability = fmi->flags & V4L2_TUNER_CAP_LOW;
+	v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
 	v->audmode = V4L2_TUNER_MODE_STEREO;
 	v->signal = fmi_getsigstr(fmi);
 	return 0;
@@ -171,8 +168,6 @@
 {
 	struct fmi *fmi = video_drvdata(file);
 
-	if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
-		f->frequency *= 1000;
 	if (f->frequency < RSF16_MINFREQ ||
 			f->frequency > RSF16_MAXFREQ)
 		return -EINVAL;
@@ -189,8 +184,6 @@
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = fmi->curfreq;
-	if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
-		f->frequency /= 1000;
 	return 0;
 }
 
@@ -347,7 +340,6 @@
 		return res;
 	}
 
-	fmi->flags = V4L2_TUNER_CAP_LOW;
 	strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
 	fmi->vdev.v4l2_dev = v4l2_dev;
 	fmi->vdev.fops = &fmi_fops;
diff -druN linux-libre-2.6.30-gnu/drivers/media/radio/radio-sf16fmr2.c linux-libre-2.6.31-gnu/drivers/media/radio/radio-sf16fmr2.c
--- linux-libre-2.6.30-gnu/drivers/media/radio/radio-sf16fmr2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/radio/radio-sf16fmr2.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,13 +61,12 @@
 	int stereo; /* card is producing stereo audio */
 	unsigned long curfreq; /* freq in kHz */
 	int card_type;
-	u32 flags;
 };
 
 static struct fmr2 fmr2_card;
 
 /* hw precision is 12.5 kHz
- * It is only useful to give freq in intervall of 200 (=0.0125Mhz),
+ * It is only useful to give freq in interval of 200 (=0.0125Mhz),
  * other bits will be truncated
  */
 #define RSF16_ENCODE(x)	((x) / 200 + 856)
@@ -221,7 +220,6 @@
 static int vidioc_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	int mult;
 	struct fmr2 *fmr2 = video_drvdata(file);
 
 	if (v->index > 0)
@@ -230,13 +228,12 @@
 	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
 
-	mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
-	v->rangelow = RSF16_MINFREQ / mult;
-	v->rangehigh = RSF16_MAXFREQ / mult;
-	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-	v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW;
-	v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO:
-				V4L2_TUNER_MODE_MONO;
+	v->rangelow = RSF16_MINFREQ;
+	v->rangehigh = RSF16_MAXFREQ;
+	v->rxsubchans = fmr2->stereo ? V4L2_TUNER_SUB_STEREO :
+					V4L2_TUNER_SUB_MONO;
+	v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
+	v->audmode = V4L2_TUNER_MODE_STEREO;
 	mutex_lock(&fmr2->lock);
 	v->signal = fmr2_getsigstr(fmr2);
 	mutex_unlock(&fmr2->lock);
@@ -254,8 +251,6 @@
 {
 	struct fmr2 *fmr2 = video_drvdata(file);
 
-	if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
-		f->frequency *= 1000;
 	if (f->frequency < RSF16_MINFREQ ||
 			f->frequency > RSF16_MAXFREQ)
 		return -EINVAL;
@@ -279,8 +274,6 @@
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = fmr2->curfreq;
-	if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
-		f->frequency /= 1000;
 	return 0;
 }
 
@@ -406,7 +399,6 @@
 	strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name));
 	fmr2->io = io;
 	fmr2->stereo = 1;
-	fmr2->flags = V4L2_TUNER_CAP_LOW;
 	mutex_init(&fmr2->lock);
 
 	if (!request_region(fmr2->io, 2, "sf16fmr2")) {
diff -druN linux-libre-2.6.30-gnu/drivers/media/radio/radio-si470x.c linux-libre-2.6.31-gnu/drivers/media/radio/radio-si470x.c
--- linux-libre-2.6.30-gnu/drivers/media/radio/radio-si470x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/radio/radio-si470x.c	2009-09-09 18:13:59.000000000 -0400
@@ -127,6 +127,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
@@ -1200,7 +1201,7 @@
 			video_unregister_device(radio->videodev);
 			kfree(radio->buffer);
 			kfree(radio);
-			goto done;
+			goto unlock;
 		}
 
 		/* stop rds reception */
@@ -1213,10 +1214,8 @@
 		retval = si470x_stop(radio);
 		usb_autopm_put_interface(radio->intf);
 	}
-
 unlock:
 	mutex_unlock(&radio->disconnect_lock);
-
 done:
 	return retval;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/radio/radio-tea5764.c linux-libre-2.6.31-gnu/drivers/media/radio/radio-tea5764.c
--- linux-libre-2.6.30-gnu/drivers/media/radio/radio-tea5764.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/radio/radio-tea5764.c	2009-09-09 18:13:59.000000000 -0400
@@ -322,7 +322,9 @@
 	v->rangehigh  = FREQ_MAX * FREQ_MUL;
 	v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
 	if (r->tunchk & TEA5764_TUNCHK_STEREO)
-			v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+		v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+	else
+		v->rxsubchans = V4L2_TUNER_SUB_MONO;
 	v->audmode = tea5764_get_audout_mode(radio);
 	v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
 	v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/adv7343.c linux-libre-2.6.31-gnu/drivers/media/video/adv7343.c
--- linux-libre-2.6.30-gnu/drivers/media/video/adv7343.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/adv7343.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,534 @@
+/*
+ * adv7343 - ADV7343 Video Encoder Driver
+ *
+ * The encoder hardware does not support SECAM.
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/videodev2.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+
+#include <media/adv7343.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+#include "adv7343_regs.h"
+
+MODULE_DESCRIPTION("ADV7343 video encoder driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+struct adv7343_state {
+	struct v4l2_subdev sd;
+	u8 reg00;
+	u8 reg01;
+	u8 reg02;
+	u8 reg35;
+	u8 reg80;
+	u8 reg82;
+	int bright;
+	int hue;
+	int gain;
+	u32 output;
+	v4l2_std_id std;
+};
+
+static inline struct adv7343_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7343_state, sd);
+}
+
+static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static const u8 adv7343_init_reg_val[] = {
+	ADV7343_SOFT_RESET, ADV7343_SOFT_RESET_DEFAULT,
+	ADV7343_POWER_MODE_REG, ADV7343_POWER_MODE_REG_DEFAULT,
+
+	ADV7343_HD_MODE_REG1, ADV7343_HD_MODE_REG1_DEFAULT,
+	ADV7343_HD_MODE_REG2, ADV7343_HD_MODE_REG2_DEFAULT,
+	ADV7343_HD_MODE_REG3, ADV7343_HD_MODE_REG3_DEFAULT,
+	ADV7343_HD_MODE_REG4, ADV7343_HD_MODE_REG4_DEFAULT,
+	ADV7343_HD_MODE_REG5, ADV7343_HD_MODE_REG5_DEFAULT,
+	ADV7343_HD_MODE_REG6, ADV7343_HD_MODE_REG6_DEFAULT,
+	ADV7343_HD_MODE_REG7, ADV7343_HD_MODE_REG7_DEFAULT,
+
+	ADV7343_SD_MODE_REG1, ADV7343_SD_MODE_REG1_DEFAULT,
+	ADV7343_SD_MODE_REG2, ADV7343_SD_MODE_REG2_DEFAULT,
+	ADV7343_SD_MODE_REG3, ADV7343_SD_MODE_REG3_DEFAULT,
+	ADV7343_SD_MODE_REG4, ADV7343_SD_MODE_REG4_DEFAULT,
+	ADV7343_SD_MODE_REG5, ADV7343_SD_MODE_REG5_DEFAULT,
+	ADV7343_SD_MODE_REG6, ADV7343_SD_MODE_REG6_DEFAULT,
+	ADV7343_SD_MODE_REG7, ADV7343_SD_MODE_REG7_DEFAULT,
+	ADV7343_SD_MODE_REG8, ADV7343_SD_MODE_REG8_DEFAULT,
+
+	ADV7343_SD_HUE_REG, ADV7343_SD_HUE_REG_DEFAULT,
+	ADV7343_SD_CGMS_WSS0, ADV7343_SD_CGMS_WSS0_DEFAULT,
+	ADV7343_SD_BRIGHTNESS_WSS, ADV7343_SD_BRIGHTNESS_WSS_DEFAULT,
+};
+
+/*
+ * 			    2^32
+ * FSC(reg) =  FSC (HZ) * --------
+ *			  27000000
+ */
+static const struct adv7343_std_info stdinfo[] = {
+	{
+		/* FSC(Hz) = 3,579,545.45 Hz */
+		SD_STD_NTSC, 569408542, V4L2_STD_NTSC,
+	}, {
+		/* FSC(Hz) = 3,575,611.00 Hz */
+		SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M,
+	}, {
+		/* FSC(Hz) = 3,582,056.00 */
+		SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60,
+	},
+};
+
+static int adv7343_setstd(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7343_state *state = to_state(sd);
+	struct adv7343_std_info *std_info;
+	int output_idx, num_std;
+	char *fsc_ptr;
+	u8 reg, val;
+	int err = 0;
+	int i = 0;
+
+	output_idx = state->output;
+
+	std_info = (struct adv7343_std_info *)stdinfo;
+	num_std = ARRAY_SIZE(stdinfo);
+
+	for (i = 0; i < num_std; i++) {
+		if (std_info[i].stdid & std)
+			break;
+	}
+
+	if (i == num_std) {
+		v4l2_dbg(1, debug, sd,
+				"Invalid std or std is not supported: %llx\n",
+						(unsigned long long)std);
+		return -EINVAL;
+	}
+
+	/* Set the standard */
+	val = state->reg80 & (~(SD_STD_MASK));
+	val |= std_info[i].standard_val3;
+	err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg80 = val;
+
+	/* Configure the input mode register */
+	val = state->reg01 & (~((u8) INPUT_MODE_MASK));
+	val |= SD_INPUT_MODE;
+	err = adv7343_write(sd, ADV7343_MODE_SELECT_REG, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg01 = val;
+
+	/* Program the sub carrier frequency registers */
+	fsc_ptr = (unsigned char *)&std_info[i].fsc_val;
+	reg = ADV7343_FSC_REG0;
+	for (i = 0; i < 4; i++, reg++, fsc_ptr++) {
+		err = adv7343_write(sd, reg, *fsc_ptr);
+		if (err < 0)
+			goto setstd_exit;
+	}
+
+	val = state->reg80;
+
+	/* Filter settings */
+	if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443))
+		val &= 0x03;
+	else if (std & ~V4L2_STD_SECAM)
+		val |= 0x04;
+
+	err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg80 = val;
+
+setstd_exit:
+	if (err != 0)
+		v4l2_err(sd, "Error setting std, write failed\n");
+
+	return err;
+}
+
+static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
+{
+	struct adv7343_state *state = to_state(sd);
+	unsigned char val;
+	int err = 0;
+
+	if (output_type > ADV7343_SVIDEO_ID) {
+		v4l2_dbg(1, debug, sd,
+			"Invalid output type or output type not supported:%d\n",
+								output_type);
+		return -EINVAL;
+	}
+
+	/* Enable Appropriate DAC */
+	val = state->reg00 & 0x03;
+
+	if (output_type == ADV7343_COMPOSITE_ID)
+		val |= ADV7343_COMPOSITE_POWER_VALUE;
+	else if (output_type == ADV7343_COMPONENT_ID)
+		val |= ADV7343_COMPONENT_POWER_VALUE;
+	else
+		val |= ADV7343_SVIDEO_POWER_VALUE;
+
+	err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg00 = val;
+
+	/* Enable YUV output */
+	val = state->reg02 | YUV_OUTPUT_SELECT;
+	err = adv7343_write(sd, ADV7343_MODE_REG0, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg02 = val;
+
+	/* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */
+	val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI);
+	err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg82 = val;
+
+	/* configure ED/HD Color DAC Swap and ED/HD RGB Input Enable bit to
+	 * zero */
+	val = state->reg35 & (HD_RGB_INPUT_DI & HD_DAC_SWAP_DI);
+	err = adv7343_write(sd, ADV7343_HD_MODE_REG6, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg35 = val;
+
+setoutput_exit:
+	if (err != 0)
+		v4l2_err(sd, "Error setting output, write failed\n");
+
+	return err;
+}
+
+static int adv7343_log_status(struct v4l2_subdev *sd)
+{
+	struct adv7343_state *state = to_state(sd);
+
+	v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std);
+	v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" :
+			((state->output == 1) ? "Component" : "S-Video"));
+	return 0;
+}
+
+static int adv7343_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, ADV7343_BRIGHTNESS_MIN,
+						ADV7343_BRIGHTNESS_MAX, 1,
+						ADV7343_BRIGHTNESS_DEF);
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill(qc, ADV7343_HUE_MIN,
+						ADV7343_HUE_MAX, 1 ,
+						ADV7343_HUE_DEF);
+	case V4L2_CID_GAIN:
+		return v4l2_ctrl_query_fill(qc, ADV7343_GAIN_MIN,
+						ADV7343_GAIN_MAX, 1,
+						ADV7343_GAIN_DEF);
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int adv7343_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct adv7343_state *state = to_state(sd);
+	int err = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		if (ctrl->value < ADV7343_BRIGHTNESS_MIN ||
+					ctrl->value > ADV7343_BRIGHTNESS_MAX) {
+			v4l2_dbg(1, debug, sd,
+					"invalid brightness settings %d\n",
+								ctrl->value);
+			return -ERANGE;
+		}
+
+		state->bright = ctrl->value;
+		err = adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS,
+					state->bright);
+		break;
+
+	case V4L2_CID_HUE:
+		if (ctrl->value < ADV7343_HUE_MIN ||
+					ctrl->value > ADV7343_HUE_MAX) {
+			v4l2_dbg(1, debug, sd, "invalid hue settings %d\n",
+								ctrl->value);
+			return -ERANGE;
+		}
+
+		state->hue = ctrl->value;
+		err = adv7343_write(sd, ADV7343_SD_HUE_REG, state->hue);
+		break;
+
+	case V4L2_CID_GAIN:
+		if (ctrl->value < ADV7343_GAIN_MIN ||
+					ctrl->value > ADV7343_GAIN_MAX) {
+			v4l2_dbg(1, debug, sd, "invalid gain settings %d\n",
+								ctrl->value);
+			return -ERANGE;
+		}
+
+		if ((ctrl->value > POSITIVE_GAIN_MAX) &&
+			(ctrl->value < NEGATIVE_GAIN_MIN)) {
+			v4l2_dbg(1, debug, sd,
+				"gain settings not within the specified range\n");
+			return -ERANGE;
+		}
+
+		state->gain = ctrl->value;
+		err = adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, state->gain);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (err < 0)
+		v4l2_err(sd, "Failed to set the encoder controls\n");
+
+	return err;
+}
+
+static int adv7343_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct adv7343_state *state = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctrl->value = state->bright;
+		break;
+
+	case V4L2_CID_HUE:
+		ctrl->value = state->hue;
+		break;
+
+	case V4L2_CID_GAIN:
+		ctrl->value = state->gain;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int adv7343_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0);
+}
+
+static const struct v4l2_subdev_core_ops adv7343_core_ops = {
+	.log_status	= adv7343_log_status,
+	.g_chip_ident	= adv7343_g_chip_ident,
+	.g_ctrl		= adv7343_g_ctrl,
+	.s_ctrl		= adv7343_s_ctrl,
+	.queryctrl	= adv7343_queryctrl,
+};
+
+static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7343_state *state = to_state(sd);
+	int err = 0;
+
+	if (state->std == std)
+		return 0;
+
+	err = adv7343_setstd(sd, std);
+	if (!err)
+		state->std = std;
+
+	return err;
+}
+
+static int adv7343_s_routing(struct v4l2_subdev *sd,
+		u32 input, u32 output, u32 config)
+{
+	struct adv7343_state *state = to_state(sd);
+	int err = 0;
+
+	if (state->output == output)
+		return 0;
+
+	err = adv7343_setoutput(sd, output);
+	if (!err)
+		state->output = output;
+
+	return err;
+}
+
+static const struct v4l2_subdev_video_ops adv7343_video_ops = {
+	.s_std_output	= adv7343_s_std_output,
+	.s_routing	= adv7343_s_routing,
+};
+
+static const struct v4l2_subdev_ops adv7343_ops = {
+	.core	= &adv7343_core_ops,
+	.video	= &adv7343_video_ops,
+};
+
+static int adv7343_initialize(struct v4l2_subdev *sd)
+{
+	struct adv7343_state *state = to_state(sd);
+	int err = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(adv7343_init_reg_val); i += 2) {
+
+		err = adv7343_write(sd, adv7343_init_reg_val[i],
+					adv7343_init_reg_val[i+1]);
+		if (err) {
+			v4l2_err(sd, "Error initializing\n");
+			return err;
+		}
+	}
+
+	/* Configure for default video standard */
+	err = adv7343_setoutput(sd, state->output);
+	if (err < 0) {
+		v4l2_err(sd, "Error setting output during init\n");
+		return -EINVAL;
+	}
+
+	err = adv7343_setstd(sd, state->std);
+	if (err < 0) {
+		v4l2_err(sd, "Error setting std during init\n");
+		return -EINVAL;
+	}
+
+	return err;
+}
+
+static int adv7343_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct adv7343_state *state;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct adv7343_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+
+	state->reg00	= 0x80;
+	state->reg01	= 0x00;
+	state->reg02	= 0x20;
+	state->reg35	= 0x00;
+	state->reg80	= ADV7343_SD_MODE_REG1_DEFAULT;
+	state->reg82	= ADV7343_SD_MODE_REG2_DEFAULT;
+
+	state->output = ADV7343_COMPOSITE_ID;
+	state->std = V4L2_STD_NTSC;
+
+	v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops);
+	return adv7343_initialize(&state->sd);
+}
+
+static int adv7343_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+
+	return 0;
+}
+
+static const struct i2c_device_id adv7343_id[] = {
+	{"adv7343", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, adv7343_id);
+
+static struct i2c_driver adv7343_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "adv7343",
+	},
+	.probe		= adv7343_probe,
+	.remove		= adv7343_remove,
+	.id_table	= adv7343_id,
+};
+
+static __init int init_adv7343(void)
+{
+	return i2c_add_driver(&adv7343_driver);
+}
+
+static __exit void exit_adv7343(void)
+{
+	i2c_del_driver(&adv7343_driver);
+}
+
+module_init(init_adv7343);
+module_exit(exit_adv7343);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/adv7343_regs.h linux-libre-2.6.31-gnu/drivers/media/video/adv7343_regs.h
--- linux-libre-2.6.30-gnu/drivers/media/video/adv7343_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/adv7343_regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,185 @@
+/*
+ * ADV7343 encoder related structure and register definitions
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef ADV7343_REG_H
+#define ADV7343_REGS_H
+
+struct adv7343_std_info {
+	u32 standard_val3;
+	u32 fsc_val;
+	v4l2_std_id stdid;
+};
+
+/* Register offset macros */
+#define ADV7343_POWER_MODE_REG		(0x00)
+#define ADV7343_MODE_SELECT_REG		(0x01)
+#define ADV7343_MODE_REG0		(0x02)
+
+#define ADV7343_DAC2_OUTPUT_LEVEL	(0x0b)
+
+#define ADV7343_SOFT_RESET		(0x17)
+
+#define ADV7343_HD_MODE_REG1		(0x30)
+#define ADV7343_HD_MODE_REG2		(0x31)
+#define ADV7343_HD_MODE_REG3		(0x32)
+#define ADV7343_HD_MODE_REG4		(0x33)
+#define ADV7343_HD_MODE_REG5		(0x34)
+#define ADV7343_HD_MODE_REG6		(0x35)
+
+#define ADV7343_HD_MODE_REG7		(0x39)
+
+#define ADV7343_SD_MODE_REG1		(0x80)
+#define ADV7343_SD_MODE_REG2		(0x82)
+#define ADV7343_SD_MODE_REG3		(0x83)
+#define ADV7343_SD_MODE_REG4		(0x84)
+#define ADV7343_SD_MODE_REG5		(0x86)
+#define ADV7343_SD_MODE_REG6		(0x87)
+#define ADV7343_SD_MODE_REG7		(0x88)
+#define ADV7343_SD_MODE_REG8		(0x89)
+
+#define ADV7343_FSC_REG0		(0x8C)
+#define ADV7343_FSC_REG1		(0x8D)
+#define ADV7343_FSC_REG2		(0x8E)
+#define ADV7343_FSC_REG3		(0x8F)
+
+#define ADV7343_SD_CGMS_WSS0		(0x99)
+
+#define ADV7343_SD_HUE_REG		(0xA0)
+#define ADV7343_SD_BRIGHTNESS_WSS	(0xA1)
+
+/* Default values for the registers */
+#define ADV7343_POWER_MODE_REG_DEFAULT		(0x10)
+#define ADV7343_HD_MODE_REG1_DEFAULT		(0x3C)	/* Changed Default
+							   720p EAVSAV code*/
+#define ADV7343_HD_MODE_REG2_DEFAULT		(0x01)	/* Changed Pixel data
+							   valid */
+#define ADV7343_HD_MODE_REG3_DEFAULT		(0x00)	/* Color delay 0 clks */
+#define ADV7343_HD_MODE_REG4_DEFAULT		(0xE8)	/* Changed */
+#define ADV7343_HD_MODE_REG5_DEFAULT		(0x08)
+#define ADV7343_HD_MODE_REG6_DEFAULT		(0x00)
+#define ADV7343_HD_MODE_REG7_DEFAULT		(0x00)
+#define ADV7343_SD_MODE_REG8_DEFAULT		(0x00)
+#define ADV7343_SOFT_RESET_DEFAULT		(0x02)
+#define ADV7343_COMPOSITE_POWER_VALUE		(0x80)
+#define ADV7343_COMPONENT_POWER_VALUE		(0x1C)
+#define ADV7343_SVIDEO_POWER_VALUE		(0x60)
+#define ADV7343_SD_HUE_REG_DEFAULT		(127)
+#define ADV7343_SD_BRIGHTNESS_WSS_DEFAULT	(0x03)
+
+#define ADV7343_SD_CGMS_WSS0_DEFAULT		(0x10)
+
+#define ADV7343_SD_MODE_REG1_DEFAULT		(0x00)
+#define ADV7343_SD_MODE_REG2_DEFAULT		(0xC9)
+#define ADV7343_SD_MODE_REG3_DEFAULT		(0x10)
+#define ADV7343_SD_MODE_REG4_DEFAULT		(0x01)
+#define ADV7343_SD_MODE_REG5_DEFAULT		(0x02)
+#define ADV7343_SD_MODE_REG6_DEFAULT		(0x0C)
+#define ADV7343_SD_MODE_REG7_DEFAULT		(0x04)
+#define ADV7343_SD_MODE_REG8_DEFAULT		(0x00)
+
+/* Bit masks for Mode Select Register */
+#define INPUT_MODE_MASK			(0x70)
+#define SD_INPUT_MODE			(0x00)
+#define HD_720P_INPUT_MODE		(0x10)
+#define HD_1080I_INPUT_MODE		(0x10)
+
+/* Bit masks for Mode Register 0 */
+#define TEST_PATTERN_BLACK_BAR_EN	(0x04)
+#define YUV_OUTPUT_SELECT		(0x20)
+#define RGB_OUTPUT_SELECT		(0xDF)
+
+/* Bit masks for DAC output levels */
+#define DAC_OUTPUT_LEVEL_MASK		(0xFF)
+#define POSITIVE_GAIN_MAX		(0x40)
+#define POSITIVE_GAIN_MIN		(0x00)
+#define NEGATIVE_GAIN_MAX		(0xFF)
+#define NEGATIVE_GAIN_MIN		(0xC0)
+
+/* Bit masks for soft reset register */
+#define SOFT_RESET			(0x02)
+
+/* Bit masks for HD Mode Register 1 */
+#define OUTPUT_STD_MASK		(0x03)
+#define OUTPUT_STD_SHIFT	(0)
+#define OUTPUT_STD_EIA0_2	(0x00)
+#define OUTPUT_STD_EIA0_1	(0x01)
+#define OUTPUT_STD_FULL		(0x02)
+#define EMBEDDED_SYNC		(0x04)
+#define EXTERNAL_SYNC		(0xFB)
+#define STD_MODE_SHIFT		(3)
+#define STD_MODE_MASK		(0x1F)
+#define STD_MODE_720P		(0x05)
+#define STD_MODE_720P_25	(0x08)
+#define STD_MODE_720P_30	(0x07)
+#define STD_MODE_720P_50	(0x06)
+#define STD_MODE_1080I		(0x0D)
+#define STD_MODE_1080I_25fps	(0x0E)
+#define STD_MODE_1080P_24	(0x12)
+#define STD_MODE_1080P_25	(0x10)
+#define STD_MODE_1080P_30	(0x0F)
+#define STD_MODE_525P		(0x00)
+#define STD_MODE_625P		(0x03)
+
+/* Bit masks for SD Mode Register 1 */
+#define SD_STD_MASK		(0x03)
+#define SD_STD_NTSC		(0x00)
+#define SD_STD_PAL_BDGHI	(0x01)
+#define SD_STD_PAL_M		(0x02)
+#define SD_STD_PAL_N		(0x03)
+#define SD_LUMA_FLTR_MASK	(0x7)
+#define SD_LUMA_FLTR_SHIFT	(0x2)
+#define SD_CHROMA_FLTR_MASK	(0x7)
+#define SD_CHROMA_FLTR_SHIFT	(0x5)
+
+/* Bit masks for SD Mode Register 2 */
+#define SD_PBPR_SSAF_EN		(0x01)
+#define SD_PBPR_SSAF_DI		(0xFE)
+#define SD_DAC_1_DI		(0xFD)
+#define SD_DAC_2_DI		(0xFB)
+#define SD_PEDESTAL_EN		(0x08)
+#define SD_PEDESTAL_DI		(0xF7)
+#define SD_SQUARE_PIXEL_EN	(0x10)
+#define SD_SQUARE_PIXEL_DI	(0xEF)
+#define SD_PIXEL_DATA_VALID	(0x40)
+#define SD_ACTIVE_EDGE_EN	(0x80)
+#define SD_ACTIVE_EDGE_DI	(0x7F)
+
+/* Bit masks for HD Mode Register 6 */
+#define HD_RGB_INPUT_EN		(0x02)
+#define HD_RGB_INPUT_DI		(0xFD)
+#define HD_PBPR_SYNC_EN		(0x04)
+#define HD_PBPR_SYNC_DI		(0xFB)
+#define HD_DAC_SWAP_EN		(0x08)
+#define HD_DAC_SWAP_DI		(0xF7)
+#define HD_GAMMA_CURVE_A	(0xEF)
+#define HD_GAMMA_CURVE_B	(0x10)
+#define HD_GAMMA_EN		(0x20)
+#define HD_GAMMA_DI		(0xDF)
+#define HD_ADPT_FLTR_MODEB	(0x40)
+#define HD_ADPT_FLTR_MODEA	(0xBF)
+#define HD_ADPT_FLTR_EN		(0x80)
+#define HD_ADPT_FLTR_DI		(0x7F)
+
+#define ADV7343_BRIGHTNESS_MAX	(127)
+#define ADV7343_BRIGHTNESS_MIN	(0)
+#define ADV7343_BRIGHTNESS_DEF	(3)
+#define ADV7343_HUE_MAX		(255)
+#define ADV7343_HUE_MIN		(0)
+#define ADV7343_HUE_DEF		(127)
+#define ADV7343_GAIN_MAX	(255)
+#define ADV7343_GAIN_MIN	(0)
+#define ADV7343_GAIN_DEF	(0)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/au0828/au0828-cards.c linux-libre-2.6.31-gnu/drivers/media/video/au0828/au0828-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/au0828/au0828-cards.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/au0828/au0828-cards.c	2009-09-09 18:13:59.000000000 -0400
@@ -136,9 +136,9 @@
 			/* Tuner Reset Command from xc5000 */
 			/* Drive the tuner into reset and out */
 			au0828_clear(dev, REG_001, 2);
-			mdelay(200);
+			mdelay(10);
 			au0828_set(dev, REG_001, 2);
-			mdelay(50);
+			mdelay(10);
 			return 0;
 		} else {
 			printk(KERN_ERR
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/au0828/au0828-core.c linux-libre-2.6.31-gnu/drivers/media/video/au0828/au0828-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/au0828/au0828-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/au0828/au0828-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,11 @@
 module_param_named(debug, au0828_debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable debug messages");
 
+static unsigned int disable_usb_speed_check;
+module_param(disable_usb_speed_check, int, 0444);
+MODULE_PARM_DESC(disable_usb_speed_check,
+		 "override min bandwidth requirement of 480M bps");
+
 #define _AU0828_BULKPIPE 0x03
 #define _BULKPIPESIZE 0xffff
 
@@ -181,6 +186,18 @@
 		le16_to_cpu(usbdev->descriptor.idProduct),
 		ifnum);
 
+	/*
+	 * Make sure we have 480 Mbps of bandwidth, otherwise things like
+	 * video stream wouldn't likely work, since 12 Mbps is generally
+	 * not enough even for most Digital TV streams.
+	 */
+	if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
+		printk(KERN_ERR "au0828: Device initialization failed.\n");
+		printk(KERN_ERR "au0828: Device must be connected to a "
+		       "high-speed USB 2.0 port.\n");
+		return -ENODEV;
+	}
+
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
 		printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/au0828/au0828-video.c linux-libre-2.6.31-gnu/drivers/media/video/au0828/au0828-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/au0828/au0828-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/au0828/au0828-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -829,6 +829,9 @@
 
 		au0828_uninit_isoc(dev);
 
+		/* Save some power by putting tuner to sleep */
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby);
+
 		/* When close the device, set the usb intf0 into alt0 to free
 		   USB bandwidth */
 		ret = usb_set_interface(dev->usbdev, 0, 0);
@@ -910,11 +913,6 @@
 
 	rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
 
-	dprintk(2, "vma start=0x%08lx, size=%ld, ret=%d\n",
-		(unsigned long)vma->vm_start,
-		(unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
-		rc);
-
 	return rc;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv-cards.c linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv-cards.c	2012-03-22 19:13:19.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv-cards.c	2012-03-22 20:09:32.000000000 -0400
@@ -3324,8 +3324,6 @@
 /* initialization part two -- after registering i2c bus */
 void __devinit bttv_init_card2(struct bttv *btv)
 {
-	int addr=ADDR_UNSET;
-
 	btv->tuner_type = UNSET;
 
 	if (BTTV_BOARD_UNKNOWN == btv->c.type) {
@@ -3470,9 +3468,6 @@
 	btv->pll.pll_current = -1;
 
 	/* tuner configuration (from card list / autodetect / insmod option) */
-	if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
-		addr = bttv_tvcards[btv->c.type].tuner_addr;
-
 	if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
 		if (UNSET == btv->tuner_type)
 			btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
@@ -3496,40 +3491,6 @@
 	if (UNSET == btv->tuner_type)
 		btv->tuner_type = TUNER_ABSENT;
 
-	if (btv->tuner_type != TUNER_ABSENT) {
-		struct tuner_setup tun_setup;
-
-		/* Load tuner module before issuing tuner config call! */
-		if (bttv_tvcards[btv->c.type].has_radio)
-			v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
-				&btv->c.i2c_adap, "tuner", "tuner",
-				v4l2_i2c_tuner_addrs(ADDRS_RADIO));
-		v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
-				&btv->c.i2c_adap, "tuner", "tuner",
-				v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
-		v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
-				&btv->c.i2c_adap, "tuner", "tuner",
-				v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
-
-		tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
-		tun_setup.type = btv->tuner_type;
-		tun_setup.addr = addr;
-
-		if (bttv_tvcards[btv->c.type].has_radio)
-			tun_setup.mode_mask |= T_RADIO;
-
-		bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
-	}
-
-	if (btv->tda9887_conf) {
-		struct v4l2_priv_tun_config tda9887_cfg;
-
-		tda9887_cfg.tuner = TUNER_TDA9887;
-		tda9887_cfg.priv = &btv->tda9887_conf;
-
-		bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
-	}
-
 	btv->dig = bttv_tvcards[btv->c.type].has_dig_in ?
 		   bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET;
 	btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ?
@@ -3540,15 +3501,15 @@
 		btv->has_remote = remote[btv->c.nr];
 
 	if (bttv_tvcards[btv->c.type].has_radio)
-		btv->has_radio=1;
+		btv->has_radio = 1;
 	if (bttv_tvcards[btv->c.type].has_remote)
-		btv->has_remote=1;
+		btv->has_remote = 1;
 	if (!bttv_tvcards[btv->c.type].no_gpioirq)
-		btv->gpioirq=1;
+		btv->gpioirq = 1;
 	if (bttv_tvcards[btv->c.type].volume_gpio)
-		btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio;
+		btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio;
 	if (bttv_tvcards[btv->c.type].audio_mode_gpio)
-		btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio;
+		btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio;
 
 	if (btv->tuner_type == TUNER_ABSENT)
 		return;  /* no tuner or related drivers to load */
@@ -3666,6 +3627,49 @@
 }
 
 
+/* initialize the tuner */
+void __devinit bttv_init_tuner(struct bttv *btv)
+{
+	int addr = ADDR_UNSET;
+
+	if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
+		addr = bttv_tvcards[btv->c.type].tuner_addr;
+
+	if (btv->tuner_type != TUNER_ABSENT) {
+		struct tuner_setup tun_setup;
+
+		/* Load tuner module before issuing tuner config call! */
+		if (bttv_tvcards[btv->c.type].has_radio)
+			v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tuner", "tuner",
+				v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+		v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tuner", "tuner",
+				v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tuner", "tuner",
+				v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
+
+		tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
+		tun_setup.type = btv->tuner_type;
+		tun_setup.addr = addr;
+
+		if (bttv_tvcards[btv->c.type].has_radio)
+			tun_setup.mode_mask |= T_RADIO;
+
+		bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
+	}
+
+	if (btv->tda9887_conf) {
+		struct v4l2_priv_tun_config tda9887_cfg;
+
+		tda9887_cfg.tuner = TUNER_TDA9887;
+		tda9887_cfg.priv = &btv->tda9887_conf;
+
+		bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
+	}
+}
+
 /* ----------------------------------------------------------------------- */
 
 static void modtec_eeprom(struct bttv *btv)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv-driver.c linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv-driver.c
--- linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv-driver.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv-driver.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
 #include "bttvp.h"
@@ -3152,6 +3153,7 @@
 	struct bttv_fh *fh = file->private_data;
 	struct bttv_buffer *buf;
 	enum v4l2_field field;
+	unsigned int rc = POLLERR;
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
 		if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
@@ -3160,9 +3162,10 @@
 	}
 
 	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
+		mutex_lock(&fh->cap.vb_lock);
 		/* streaming capture */
 		if (list_empty(&fh->cap.stream))
-			return POLLERR;
+			goto err;
 		buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
 	} else {
 		/* read() capture */
@@ -3191,11 +3194,12 @@
 	poll_wait(file, &buf->vb.done, wait);
 	if (buf->vb.state == VIDEOBUF_DONE ||
 	    buf->vb.state == VIDEOBUF_ERROR)
-		return POLLIN|POLLRDNORM;
-	return 0;
+		rc =  POLLIN|POLLRDNORM;
+	else
+		rc = 0;
 err:
 	mutex_unlock(&fh->cap.vb_lock);
-	return POLLERR;
+	return rc;
 }
 
 static int bttv_open(struct file *file)
@@ -4166,7 +4170,6 @@
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor   = -1;
 	vfd->v4l2_dev = &btv->c.v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug   = bttv_debug;
@@ -4416,6 +4419,7 @@
 
 	/* some card-specific stuff (needs working i2c) */
 	bttv_init_card2(btv);
+	bttv_init_tuner(btv);
 	init_irqreg(btv);
 
 	/* register video4linux + input */
@@ -4629,7 +4633,7 @@
 #endif
 	if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
 		gbuffers = 2;
-	if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF)
+	if (gbufsize > BTTV_MAX_FBUF)
 		gbufsize = BTTV_MAX_FBUF;
 	gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
 	if (bttv_verbose)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv.h linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv.h
--- linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv.h	2009-09-09 18:13:59.000000000 -0400
@@ -283,6 +283,7 @@
 extern void bttv_idcard(struct bttv *btv);
 extern void bttv_init_card1(struct bttv *btv);
 extern void bttv_init_card2(struct bttv *btv);
+extern void bttv_init_tuner(struct bttv *btv);
 
 /* card-specific funtions */
 extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/bt8xx/bttv-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/bt8xx/bttv-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -389,6 +389,27 @@
 	}
 	if (0 == btv->i2c_rc && i2c_scan)
 		do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
+
+	/* Instantiate the IR receiver device, if present */
+	if (0 == btv->i2c_rc) {
+		struct i2c_board_info info;
+		/* The external IR receiver is at i2c address 0x34 (0x35 for
+		   reads).  Future Hauppauge cards will have an internal
+		   receiver at 0x30 (0x31 for reads).  In theory, both can be
+		   fitted, and Hauppauge suggest an external overrides an
+		   internal.
+
+		   That's why we probe 0x1a (~0x34) first. CB
+		*/
+		const unsigned short addr_list[] = {
+			0x1a, 0x18, 0x4b, 0x64, 0x30,
+			I2C_CLIENT_END
+		};
+
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+		i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list);
+	}
 	return btv->i2c_rc;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/bw-qcam.c linux-libre-2.6.31-gnu/drivers/media/video/bw-qcam.c
--- linux-libre-2.6.30-gnu/drivers/media/video/bw-qcam.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/bw-qcam.c	2009-09-09 18:13:59.000000000 -0400
@@ -992,7 +992,7 @@
 
 	if (parport[0] && strncmp(parport[0], "auto", 4) != 0) {
 		/* user gave parport parameters */
-		for(n=0; parport[n] && n<MAX_CAMS; n++){
+		for (n = 0; n < MAX_CAMS && parport[n]; n++) {
 			char *ep;
 			unsigned long r;
 			r = simple_strtoul(parport[n], &ep, 0);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cpia2/cpia2_v4l.c linux-libre-2.6.31-gnu/drivers/media/video/cpia2/cpia2_v4l.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cpia2/cpia2_v4l.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cpia2/cpia2_v4l.c	2009-09-09 18:13:59.000000000 -0400
@@ -1064,7 +1064,7 @@
 
 	switch(m->id) {
 	case CPIA2_CID_FLICKER_MODE:
-		if(m->index < 0 || m->index >= NUM_FLICKER_CONTROLS)
+		if (m->index >= NUM_FLICKER_CONTROLS)
 			return -EINVAL;
 
 		strcpy(m->name, flicker_controls[m->index].name);
@@ -1082,14 +1082,14 @@
 					maximum = i;
 			}
 		}
-		if(m->index < 0 || m->index > maximum)
+		if (m->index > maximum)
 			return -EINVAL;
 
 		strcpy(m->name, framerate_controls[m->index].name);
 		break;
 	    }
 	case CPIA2_CID_LIGHTS:
-		if(m->index < 0 || m->index >= NUM_LIGHTS_CONTROLS)
+		if (m->index >= NUM_LIGHTS_CONTROLS)
 			return -EINVAL;
 
 		strcpy(m->name, lights_controls[m->index].name);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-audio.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-audio.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-audio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-audio.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,14 +26,18 @@
 #include "cx18-cards.h"
 #include "cx18-audio.h"
 
-#define CX18_AUDIO_ENABLE 0xc72014
+#define CX18_AUDIO_ENABLE    0xc72014
+#define CX18_AI1_MUX_MASK    0x30
+#define CX18_AI1_MUX_I2S1    0x00
+#define CX18_AI1_MUX_I2S2    0x10
+#define CX18_AI1_MUX_843_I2S 0x20
 
 /* Selects the audio input and output according to the current
    settings. */
 int cx18_audio_set_io(struct cx18 *cx)
 {
 	const struct cx18_card_audio_input *in;
-	u32 val;
+	u32 u, v;
 	int err;
 
 	/* Determine which input to use */
@@ -52,9 +56,37 @@
 		return err;
 
 	/* FIXME - this internal mux should be abstracted to a subdev */
-	val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30;
-	val |= (in->audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
-					(in->audio_input << 4);
-	cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30);
+	u = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+	v = u & ~CX18_AI1_MUX_MASK;
+	switch (in->audio_input) {
+	case CX18_AV_AUDIO_SERIAL1:
+		v |= CX18_AI1_MUX_I2S1;
+		break;
+	case CX18_AV_AUDIO_SERIAL2:
+		v |= CX18_AI1_MUX_I2S2;
+		break;
+	default:
+		v |= CX18_AI1_MUX_843_I2S;
+		break;
+	}
+	if (v == u) {
+		/* force a toggle of some AI1 MUX control bits */
+		u &= ~CX18_AI1_MUX_MASK;
+		switch (in->audio_input) {
+		case CX18_AV_AUDIO_SERIAL1:
+			u |= CX18_AI1_MUX_843_I2S;
+			break;
+		case CX18_AV_AUDIO_SERIAL2:
+			u |= CX18_AI1_MUX_843_I2S;
+			break;
+		default:
+			u |= CX18_AI1_MUX_I2S1;
+			break;
+		}
+		cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE,
+				      u, CX18_AI1_MUX_MASK);
+	}
+	cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+			      v, CX18_AI1_MUX_MASK);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-av-core.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-av-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-av-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-av-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -99,9 +99,39 @@
 			     or_value);
 }
 
-static void cx18_av_initialize(struct cx18 *cx)
+static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
 {
-	struct cx18_av_state *state = &cx->av_state;
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	/*
+	 * The crystal freq used in calculations in this driver will be
+	 * 28.636360 MHz.
+	 * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
+	 */
+
+	/*
+	 * VDCLK  Integer = 0x0f, Post Divider = 0x04
+	 * AIMCLK Integer = 0x0e, Post Divider = 0x16
+	 */
+	cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
+
+	/* VDCLK Fraction = 0x2be2fe */
+	/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
+	cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
+
+	/* AIMCLK Fraction = 0x05227ad */
+	/* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
+	cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
+
+	/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
+	cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
+	return 0;
+}
+
+static void cx18_av_initialize(struct v4l2_subdev *sd)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
 	u32 v;
 
 	cx18_av_loadfw(cx);
@@ -150,6 +180,26 @@
 	cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
 	cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
 
+	/*
+	 * Disable Video Auto-config of the Analog Front End and Video PLL.
+	 *
+	 * Since we only use BT.656 pixel mode, which works for both 525 and 625
+	 * line systems, it's just easier for us to set registers
+	 * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL),
+	 * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC)
+	 * ourselves, than to run around cleaning up after the auto-config.
+	 *
+	 * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit
+	 * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL
+	 * autoconfig either.)
+	 *
+	 * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3.
+	 */
+	cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
+
+	/* Setup the Video and and Aux/Audio PLLs */
+	cx18_av_init(sd, 0);
+
 	/* set video to auto-detect */
 	/* Clear bits 11-12 to enable slow locking mode.  Set autodetect mode */
 	/* set the comb notch = 1 */
@@ -176,12 +226,23 @@
 	/* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
 	/* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
 
-	v = cx18_av_read4(cx, CXADEC_AFE_CTRL);
-	v &= 0xFFFBFFFF;            /* turn OFF bit 18 for droop_comp_ch1 */
-	v &= 0xFFFF7FFF;            /* turn OFF bit 9 for clamp_sel_ch1 */
-	v &= 0xFFFFFFFE;            /* turn OFF bit 0 for 12db_ch1 */
-	/* v |= 0x00000001;*/            /* turn ON bit 0 for 12db_ch1 */
-	cx18_av_write4(cx, CXADEC_AFE_CTRL, v);
+	/*
+	 * Analog Front End (AFE)
+	 * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2
+	 *  bypass_ch[1-3]     use filter
+	 *  droop_comp_ch[1-3] disable
+	 *  clamp_en_ch[1-3]   disable
+	 *  aud_in_sel         ADC2
+	 *  luma_in_sel        ADC1
+	 *  chroma_in_sel      ADC2
+	 *  clamp_sel_ch[2-3]  midcode
+	 *  clamp_sel_ch1      video decoder
+	 *  vga_sel_ch3        audio decoder
+	 *  vga_sel_ch[1-2]    video decoder
+	 *  half_bw_ch[1-3]    disable
+	 *  +12db_ch[1-3]      disable
+	 */
+	cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00);
 
 /* 	if(dwEnable && dw3DCombAvailable) { */
 /*      	CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
@@ -195,50 +256,18 @@
 
 static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
 {
-	struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-	cx18_av_initialize(cx);
-	return 0;
-}
-
-static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
-{
-	struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-	/*
-	 * The crystal freq used in calculations in this driver will be
-	 * 28.636360 MHz.
-	 * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
-	 */
-
-	/*
-	 * VDCLK  Integer = 0x0f, Post Divider = 0x04
-	 * AIMCLK Integer = 0x0e, Post Divider = 0x16
-	 */
-	cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
-
-	/* VDCLK Fraction = 0x2be2fe */
-	/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
-	cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
-
-	/* AIMCLK Fraction = 0x05227ad */
-	/* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
-	cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
-
-	/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
-	cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
+	cx18_av_initialize(sd);
 	return 0;
 }
 
 static int cx18_av_load_fw(struct v4l2_subdev *sd)
 {
 	struct cx18_av_state *state = to_cx18_av_state(sd);
-	struct cx18 *cx = v4l2_get_subdevdata(sd);
 
 	if (!state->is_initialized) {
 		/* initialize on first use */
 		state->is_initialized = 1;
-		cx18_av_initialize(cx);
+		cx18_av_initialize(sd);
 	}
 	return 0;
 }
@@ -248,8 +277,15 @@
 	struct cx18_av_state *state = &cx->av_state;
 	struct v4l2_subdev *sd = &state->sd;
 	v4l2_std_id std = state->std;
+
+	/*
+	 * Video ADC crystal clock to pixel clock SRC decimation ratio
+	 * 28.636360 MHz/13.5 Mpps * 256 = 0x21f.07b
+	 */
+	const int src_decimation = 0x21f;
+
 	int hblank, hactive, burst, vblank, vactive, sc;
-	int vblank656, src_decimation;
+	int vblank656;
 	int luma_lpf, uv_lpf, comb;
 	u32 pll_int, pll_frac, pll_post;
 
@@ -259,40 +295,96 @@
 	else
 		cx18_av_write(cx, 0x49f, 0x14);
 
+	/*
+	 * Note: At the end of a field, there are 3 sets of half line duration
+	 * (double horizontal rate) pulses:
+	 *
+	 * 5 (625) or 6 (525) half-lines to blank for the vertical retrace
+	 * 5 (625) or 6 (525) vertical sync pulses of half line duration
+	 * 5 (625) or 6 (525) half-lines of equalization pulses
+	 */
 	if (std & V4L2_STD_625_50) {
-		/* FIXME - revisit these for Sliced VBI */
+		/*
+		 * The following relationships of half line counts should hold:
+		 * 625 = vblank656 + vactive
+		 * 10 = vblank656 - vblank = vsync pulses + equalization pulses
+		 *
+		 * vblank656: half lines after line 625/mid-313 of blanked video
+		 * vblank:    half lines, after line 5/317, of blanked video
+		 * vactive:   half lines of active video +
+		 * 		5 half lines after the end of active video
+		 *
+		 * As far as I can tell:
+		 * vblank656 starts counting from the falling edge of the first
+		 * 	vsync pulse (start of line 1 or mid-313)
+		 * vblank starts counting from the after the 5 vsync pulses and
+		 * 	5 or 4 equalization pulses (start of line 6 or 318)
+		 *
+		 * For 625 line systems the driver will extract VBI information
+		 * from lines 6-23 and lines 318-335 (but the slicer can only
+		 * handle 17 lines, not the 18 in the vblank region).
+		 * In addition, we need vblank656 and vblank to be one whole
+		 * line longer, to cover line 24 and 336, so the SAV/EAV RP
+		 * codes get generated such that the encoder can actually
+		 * extract line 23 & 335 (WSS).  We'll lose 1 line in each field
+		 * at the top of the screen.
+		 *
+		 * It appears the 5 half lines that happen after active
+		 * video must be included in vactive (579 instead of 574),
+		 * otherwise the colors get badly displayed in various regions
+		 * of the screen.  I guess the chroma comb filter gets confused
+		 * without them (at least when a PVR-350 is the PAL source).
+		 */
+		vblank656 = 48; /* lines  1 -  24  &  313 - 336 */
+		vblank = 38;    /* lines  6 -  24  &  318 - 336 */
+		vactive = 579;  /* lines 24 - 313  &  337 - 626 */
+
+		/*
+		 * For a 13.5 Mpps clock and 15,625 Hz line rate, a line is
+		 * is 864 pixels = 720 active + 144 blanking.  ITU-R BT.601
+		 * specifies 12 luma clock periods or ~ 0.9 * 13.5 Mpps after
+		 * the end of active video to start a horizontal line, so that
+		 * leaves 132 pixels of hblank to ignore.
+		 */
 		hblank = 132;
 		hactive = 720;
-		burst = 93;
-		vblank = 36;
-		vactive = 580;
-		vblank656 = 40;
-		src_decimation = 0x21f;
 
+		/*
+		 * Burst gate delay (for 625 line systems)
+		 * Hsync leading edge to color burst rise = 5.6 us
+		 * Color burst width = 2.25 us
+		 * Gate width = 4 pixel clocks
+		 * (5.6 us + 2.25/2 us) * 13.5 Mpps + 4/2 clocks = 92.79 clocks
+		 */
+		burst = 93;
 		luma_lpf = 2;
 		if (std & V4L2_STD_PAL) {
 			uv_lpf = 1;
 			comb = 0x20;
-			sc = 688739;
+			/* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
+			sc = 688700;
 		} else if (std == V4L2_STD_PAL_Nc) {
 			uv_lpf = 1;
 			comb = 0x20;
-			sc = 556453;
+			/* sc = 3582056.25 * src_decimation/28636360 * 2^13 */
+			sc = 556422;
 		} else { /* SECAM */
 			uv_lpf = 0;
 			comb = 0;
-			sc = 672351;
+			/* (fr + fb)/2 = (4406260 + 4250000)/2 = 4328130 */
+			/* sc = 4328130 * src_decimation/28636360 * 2^13 */
+			sc = 672314;
 		}
 	} else {
 		/*
 		 * The following relationships of half line counts should hold:
-		 * 525 = vsync + vactive + vblank656
-		 * 12 = vblank656 - vblank
+		 * 525 = prevsync + vblank656 + vactive
+		 * 12 = vblank656 - vblank = vsync pulses + equalization pulses
 		 *
-		 * vsync:     always 6 half-lines of vsync pulses
-		 * vactive:   half lines of active video
+		 * prevsync:  6 half-lines before the vsync pulses
 		 * vblank656: half lines, after line 3/mid-266, of blanked video
 		 * vblank:    half lines, after line 9/272, of blanked video
+		 * vactive:   half lines of active video
 		 *
 		 * As far as I can tell:
 		 * vblank656 starts counting from the falling edge of the first
@@ -319,20 +411,30 @@
 		luma_lpf = 1;
 		uv_lpf = 1;
 
-		src_decimation = 0x21f;
+		/*
+		 * Burst gate delay (for 525 line systems)
+		 * Hsync leading edge to color burst rise = 5.3 us
+		 * Color burst width = 2.5 us
+		 * Gate width = 4 pixel clocks
+		 * (5.3 us + 2.5/2 us) * 13.5 Mpps + 4/2 clocks = 90.425 clocks
+		 */
 		if (std == V4L2_STD_PAL_60) {
-			burst = 0x5b;
+			burst = 90;
 			luma_lpf = 2;
 			comb = 0x20;
-			sc = 688739;
+			/* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
+			sc = 688700;
 		} else if (std == V4L2_STD_PAL_M) {
-			burst = 0x61;
+			/* The 97 needs to be verified against PAL-M timings */
+			burst = 97;
 			comb = 0x20;
-			sc = 555452;
+			/* sc = 3575611.49 * src_decimation/28636360 * 2^13 */
+			sc = 555421;
 		} else {
-			burst = 0x5b;
+			burst = 90;
 			comb = 0x66;
-			sc = 556063;
+			/* sc = 3579545.45.. * src_decimation/28636360 * 2^13 */
+			sc = 556032;
 		}
 	}
 
@@ -344,23 +446,26 @@
 			    pll_int, pll_frac, pll_post);
 
 	if (pll_post) {
-		int fin, fsc, pll;
+		int fsc, pll;
+		u64 tmp;
 
 		pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
 		pll /= pll_post;
-		CX18_DEBUG_INFO_DEV(sd, "PLL = %d.%06d MHz\n",
+		CX18_DEBUG_INFO_DEV(sd, "Video PLL = %d.%06d MHz\n",
 				    pll / 1000000, pll % 1000000);
-		CX18_DEBUG_INFO_DEV(sd, "PLL/8 = %d.%06d MHz\n",
+		CX18_DEBUG_INFO_DEV(sd, "Pixel rate = %d.%06d Mpixel/sec\n",
 				    pll / 8000000, (pll / 8) % 1000000);
 
-		fin = ((u64)src_decimation * pll) >> 12;
-		CX18_DEBUG_INFO_DEV(sd, "ADC Sampling freq = %d.%06d MHz\n",
-				    fin / 1000000, fin % 1000000);
+		CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio "
+				    "= %d.%03d\n", src_decimation / 256,
+				    ((src_decimation % 256) * 1000) / 256);
 
-		fsc = (((u64)sc) * pll) >> 24L;
+		tmp = 28636360 * (u64) sc;
+		do_div(tmp, src_decimation);
+		fsc = tmp >> 13;
 		CX18_DEBUG_INFO_DEV(sd,
-				    "Chroma sub-carrier freq = %d.%06d MHz\n",
-				    fsc / 1000000, fsc % 1000000);
+				    "Chroma sub-carrier initial freq = %d.%06d "
+				    "MHz\n", fsc / 1000000, fsc % 1000000);
 
 		CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, "
 				    "vactive %i, vblank656 %i, src_dec %i, "
@@ -470,16 +575,23 @@
 {
 	struct cx18_av_state *state = &cx->av_state;
 	struct v4l2_subdev *sd = &state->sd;
-	u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
-			   vid_input <= CX18_AV_COMPOSITE8);
-	u8 reg;
-	u8 v;
+
+	enum analog_signal_type {
+		NONE, CVBS, Y, C, SIF, Pb, Pr
+	} ch[3] = {NONE, NONE, NONE};
+
+	u8 afe_mux_cfg;
+	u8 adc2_cfg;
+	u32 afe_cfg;
+	int i;
 
 	CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
 			    vid_input, aud_input);
 
-	if (is_composite) {
-		reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+	if (vid_input >= CX18_AV_COMPOSITE1 &&
+	    vid_input <= CX18_AV_COMPOSITE8) {
+		afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+		ch[0] = CVBS;
 	} else {
 		int luma = vid_input & 0xf0;
 		int chroma = vid_input & 0xf00;
@@ -493,26 +605,45 @@
 				     vid_input);
 			return -EINVAL;
 		}
-		reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+		afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+		ch[0] = Y;
 		if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
-			reg &= 0x3f;
-			reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+			afe_mux_cfg &= 0x3f;
+			afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+			ch[2] = C;
 		} else {
-			reg &= 0xcf;
-			reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+			afe_mux_cfg &= 0xcf;
+			afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+			ch[1] = C;
 		}
 	}
+	/* TODO: LeadTek WinFast DVR3100 H & WinFast PVR2100 can do Y/Pb/Pr */
 
 	switch (aud_input) {
 	case CX18_AV_AUDIO_SERIAL1:
 	case CX18_AV_AUDIO_SERIAL2:
 		/* do nothing, use serial audio input */
 		break;
-	case CX18_AV_AUDIO4: reg &= ~0x30; break;
-	case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
-	case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
-	case CX18_AV_AUDIO7: reg &= ~0xc0; break;
-	case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
+	case CX18_AV_AUDIO4:
+		afe_mux_cfg &= ~0x30;
+		ch[1] = SIF;
+		break;
+	case CX18_AV_AUDIO5:
+		afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10;
+		ch[1] = SIF;
+		break;
+	case CX18_AV_AUDIO6:
+		afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20;
+		ch[1] = SIF;
+		break;
+	case CX18_AV_AUDIO7:
+		afe_mux_cfg &= ~0xc0;
+		ch[2] = SIF;
+		break;
+	case CX18_AV_AUDIO8:
+		afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40;
+		ch[2] = SIF;
+		break;
 
 	default:
 		CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
@@ -520,24 +651,65 @@
 		return -EINVAL;
 	}
 
-	cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7);
+	/* Set up analog front end multiplexers */
+	cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7);
 	/* Set INPUT_MODE to Composite (0) or S-Video (1) */
-	cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
+	cx18_av_and_or(cx, 0x401, ~0x6, ch[0] == CVBS ? 0 : 0x02);
 
 	/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
-	v = cx18_av_read(cx, 0x102);
-	if (reg & 0x80)
-		v &= ~0x2;
+	adc2_cfg = cx18_av_read(cx, 0x102);
+	if (ch[2] == NONE)
+		adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */
 	else
-		v |= 0x2;
+		adc2_cfg |= 0x2;  /* Signal on CH3, set ADC2 to CH3 for input */
+
 	/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
-	if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
-		v |= 0x4;
+	if (ch[1] != NONE && ch[2] != NONE)
+		adc2_cfg |= 0x4; /* Set dual mode */
 	else
-		v &= ~0x4;
-	cx18_av_write_expect(cx, 0x102, v, v, 0x17);
+		adc2_cfg &= ~0x4; /* Clear dual mode */
+	cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17);
 
-	/*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/
+	/* Configure the analog front end */
+	afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL);
+	afe_cfg &= 0xff000000;
+	afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */
+	if (ch[1] != NONE && ch[2] != NONE)
+		afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */
+
+	for (i = 0; i < 3; i++) {
+		switch (ch[i]) {
+		default:
+		case NONE:
+			/* CLAMP_SEL = Fixed to midcode clamp level */
+			afe_cfg |= (0x00000200 << i);
+			break;
+		case CVBS:
+		case Y:
+			if (i > 0)
+				afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */
+			break;
+		case C:
+		case Pb:
+		case Pr:
+			/* CLAMP_SEL = Fixed to midcode clamp level */
+			afe_cfg |= (0x00000200 << i);
+			if (i == 0 && ch[i] == C)
+				afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */
+			break;
+		case SIF:
+			/*
+			 * VGA_GAIN_SEL = Audio Decoder
+			 * CLAMP_SEL = Fixed to midcode clamp level
+			 */
+			afe_cfg |= (0x00000240 << i);
+			if (i == 0)
+				afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */
+			break;
+		}
+	}
+
+	cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg);
 
 	state->vid_input = vid_input;
 	state->aud_input = aud_input;
@@ -858,9 +1030,9 @@
 		 * cx18_av_std_setup(), above standard values:
 		 *
 		 * 480 + 1 for 60 Hz systems
-		 * 576 + 4 for 50 Hz systems
+		 * 576 + 3 for 50 Hz systems
 		 */
-		Vlines = pix->height + (is_50Hz ? 4 : 1);
+		Vlines = pix->height + (is_50Hz ? 3 : 1);
 
 		/*
 		 * Invalid height and width scaling requests are:
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-av-firmware.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-av-firmware.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-av-firmware.c	2012-03-22 19:13:30.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-av-firmware.c	2012-03-22 20:09:42.000000000 -0400
@@ -24,15 +24,63 @@
 #include "cx18-io.h"
 #include <linux/firmware.h>
 
-#define CX18_AUDIO_ENABLE 0xc72014
+#define CX18_AUDIO_ENABLE    0xc72014
+#define CX18_AI1_MUX_MASK    0x30
+#define CX18_AI1_MUX_I2S1    0x00
+#define CX18_AI1_MUX_I2S2    0x10
+#define CX18_AI1_MUX_843_I2S 0x20
+#define CX18_AI1_MUX_INVALID 0x30
+
 #define FWFILE "/*(DEBLOBBED)*/"
 
+static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw)
+{
+	struct v4l2_subdev *sd = &cx->av_state.sd;
+	int ret = 0;
+	const u8 *data;
+	u32 size;
+	int addr;
+	u32 expected, dl_control;
+
+	/* Ensure we put the 8051 in reset and enable firmware upload mode */
+	dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+	do {
+		dl_control &= 0x00ffffff;
+		dl_control |= 0x0f000000;
+		cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control);
+		dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+	} while ((dl_control & 0xff000000) != 0x0f000000);
+
+	/* Read and auto increment until at address 0x0000 */
+	while (dl_control & 0x3fff)
+		dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+
+	data = fw->data;
+	size = fw->size;
+	for (addr = 0; addr < size; addr++) {
+		dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
+		expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
+		if (expected != dl_control) {
+			CX18_ERR_DEV(sd, "verification of %s firmware load "
+				     "failed: expected %#010x got %#010x\n",
+				     FWFILE, expected, dl_control);
+			ret = -EIO;
+			break;
+		}
+		dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+	}
+	if (ret == 0)
+		CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n",
+			      FWFILE, size);
+	return ret;
+}
+
 int cx18_av_loadfw(struct cx18 *cx)
 {
 	struct v4l2_subdev *sd = &cx->av_state.sd;
 	const struct firmware *fw = NULL;
 	u32 size;
-	u32 v;
+	u32 u, v;
 	const u8 *ptr;
 	int i;
 	int retries1 = 0;
@@ -95,6 +143,12 @@
 	}
 
 	cx18_av_write4_expect(cx, CXADEC_DL_CTL,
+				0x03000000 | fw->size, 0x03000000, 0x13000000);
+
+	CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
+
+	if (cx18_av_verifyfw(cx, fw) == 0)
+		cx18_av_write4_expect(cx, CXADEC_DL_CTL,
 				0x13000000 | fw->size, 0x13000000, 0x13000000);
 
 	/* Output to the 416 */
@@ -135,6 +189,28 @@
 		cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE,
 				      0, 0x400);
 
+	/* Toggle the AI1 MUX */
+	v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+	u = v & CX18_AI1_MUX_MASK;
+	v &= ~CX18_AI1_MUX_MASK;
+	if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) {
+		/* Switch to I2S1 */
+		v |= CX18_AI1_MUX_I2S1;
+		cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+				      v, CX18_AI1_MUX_MASK);
+		/* Switch back to the A/V decoder core I2S output */
+		v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S;
+	} else {
+		/* Switch to the A/V decoder core I2S output */
+		v |= CX18_AI1_MUX_843_I2S;
+		cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+				      v, CX18_AI1_MUX_MASK);
+		/* Switch back to I2S1 or I2S2 */
+		v = (v & ~CX18_AI1_MUX_MASK) | u;
+	}
+	cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+			      v, CX18_AI1_MUX_MASK);
+
 	/* Enable WW auto audio standard detection */
 	v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
 	v |= 0xFF;   /* Auto by default */
@@ -143,7 +219,5 @@
 	cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
 
 	release_firmware(fw);
-
-	CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-av-vbi.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-av-vbi.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-av-vbi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-av-vbi.c	2009-09-09 18:13:59.000000000 -0400
@@ -255,8 +255,8 @@
 	}
 
 	cx18_av_write(cx, 0x43c, 0x16);
-	/* FIXME - should match vblank set in cx18_av_std_setup() */
-	cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26);
+	/* Should match vblank set in cx18_av_std_setup() */
+	cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-cards.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-cards.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-cards.c	2009-09-09 18:13:59.000000000 -0400
@@ -198,11 +198,14 @@
 
 static const struct cx18_card cx18_card_mpc718 = {
 	.type = CX18_CARD_YUAN_MPC718,
-	.name = "Yuan MPC718",
-	.comment = "Analog video capture works; some audio line in may not.\n",
+	.name = "Yuan MPC718 MiniPCI DVB-T/Analog",
+	.comment = "Experimenters needed for device to work well.\n"
+		  "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
 	.hw_audio_ctrl = CX18_HW_418_AV,
-	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
+	.hw_muxer = CX18_HW_GPIO_MUX,
+	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1,
@@ -211,27 +214,34 @@
 		{ CX18_CARD_INPUT_SVIDEO2,    2,
 				CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
 		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
-		{ CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 },
 	},
 	.audio_inputs = {
 		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 0 },
-		{ CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL1, 0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+		{ CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
 	},
-	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 },
 	.tuners = {
 		/* XC3028 tuner */
 		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
 	},
+	/* FIXME - the FM radio is just a guess and driver doesn't use SIF */
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
 	.ddr = {
-		/* Probably Samsung K4D263238G-VC33 memory */
-		.chip_config = 0x003,
-		.refresh = 0x30c,
-		.timing1 = 0x23230b73,
-		.timing2 = 0x08,
+		/* Hynix HY5DU283222B DDR RAM */
+		.chip_config = 0x303,
+		.refresh = 0x3bd,
+		.timing1 = 0x36320966,
+		.timing2 = 0x1f,
 		.tune_lane = 0,
 		.initial_emrs = 2,
 	},
+	.gpio_init.initial_value = 0x1,
+	.gpio_init.direction = 0x3,
+	/* FIXME - these GPIO's are just guesses */
+	.gpio_audio_input = { .mask   = 0x3,
+			      .tuner  = 0x1,
+			      .linein = 0x3,
+			      .radio  = 0x1 },
 	.xceive_pin = 0,
 	.pci_list = cx18_pci_mpc718,
 	.i2c = &cx18_i2c_std,
@@ -340,13 +350,12 @@
 
 static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
 	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, /* PVR2100   */
-	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */
 	{ 0, 0, 0 }
 };
 
 static const struct cx18_card cx18_card_leadtek_pvr2100 = {
 	.type = CX18_CARD_LEADTEK_PVR2100,
-	.name = "Leadtek WinFast PVR2100/DVR3100 H",
+	.name = "Leadtek WinFast PVR2100",
 	.comment = "Experimenters and photos needed for device to work well.\n"
 		  "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
@@ -365,15 +374,12 @@
 		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
 	},
 	.tuners = {
-		/* XC3028 tuner */
+		/* XC2028 tuner */
 		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
 	},
 	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
 	.ddr = {
-		/*
-		 * Pointer to proper DDR config values provided by
-		 * Terry Wu <terrywu at leadtek.com.tw>
-		 */
+		/* Pointer to proper DDR config values provided by Terry Wu */
 		.chip_config = 0x303,
 		.refresh = 0x3bb,
 		.timing1 = 0x24220e83,
@@ -392,6 +398,58 @@
 
 /* ------------------------------------------------------------------------- */
 
+/* Leadtek WinFast DVR3100 H */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_dvr3100h[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_dvr3100h = {
+	.type = CX18_CARD_LEADTEK_DVR3100H,
+	.name = "Leadtek WinFast DVR3100 H",
+	.comment = "Simultaneous DVB-T and Analog capture supported,\n"
+		  "\texcept when capturing Analog from the antenna input.\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_GPIO_MUX,
+	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
+		  CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1,
+			CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 	    0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+	},
+	.tuners = {
+		/* XC3028 tuner */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+	.ddr = {
+		/* Pointer to proper DDR config values provided by Terry Wu */
+		.chip_config = 0x303,
+		.refresh = 0x3bb,
+		.timing1 = 0x24220e83,
+		.timing2 = 0x1f,
+		.tune_lane = 0,
+		.initial_emrs = 0x2,
+	},
+	.gpio_init.initial_value = 0x6,
+	.gpio_init.direction = 0x7,
+	.gpio_audio_input = { .mask   = 0x7,
+			      .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
+	.xceive_pin = 1,
+	.pci_list = cx18_pci_leadtek_dvr3100h,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
 static const struct cx18_card *cx18_card_list[] = {
 	&cx18_card_hvr1600_esmt,
 	&cx18_card_hvr1600_samsung,
@@ -400,6 +458,7 @@
 	&cx18_card_cnxt_raptor_pal,
 	&cx18_card_toshiba_qosmio_dvbt,
 	&cx18_card_leadtek_pvr2100,
+	&cx18_card_leadtek_dvr3100h,
 };
 
 const struct cx18_card *cx18_get_card(u16 index)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-controls.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-controls.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-controls.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-controls.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,6 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  *  02111-1307  USA
  */
+#include <linux/kernel.h>
 
 #include "cx18-driver.h"
 #include "cx18-cards.h"
@@ -61,6 +62,8 @@
 
 	switch (qctrl->id) {
 	/* Standard V4L2 controls */
+	case V4L2_CID_USER_CLASS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
 	case V4L2_CID_BRIGHTNESS:
 	case V4L2_CID_HUE:
 	case V4L2_CID_SATURATION:
@@ -176,8 +179,10 @@
 		return -EBUSY;
 
 	if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV ||
-	    type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
-		/* We don't do VBI insertion aside from IVTV format in a PS */
+	    !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS ||
+	      type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD ||
+	      type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) {
+		/* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */
 		cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE;
 		CX18_DEBUG_INFO("disabled insertion of sliced VBI data into "
 				"the MPEG stream\n");
@@ -313,7 +318,7 @@
 		idx = p.audio_properties & 0x03;
 		/* The audio clock of the digitizer must match the codec sample
 		   rate otherwise you get some very strange effects. */
-		if (idx < sizeof(freqs))
+		if (idx < ARRAY_SIZE(freqs))
 			cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
 		return err;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-driver.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-driver.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-driver.c	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-driver.c	2012-03-22 20:08:07.000000000 -0400
@@ -30,6 +30,7 @@
 #include "cx18-irq.h"
 #include "cx18-gpio.h"
 #include "cx18-firmware.h"
+#include "cx18-queue.h"
 #include "cx18-streams.h"
 #include "cx18-av-core.h"
 #include "cx18-scb.h"
@@ -151,7 +152,8 @@
 		 "\t\t\t 4 = Yuan MPC718\n"
 		 "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
 		 "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
-		 "\t\t\t 7 = Leadtek WinFast PVR2100/DVR3100 H\n"
+		 "\t\t\t 7 = Leadtek WinFast PVR2100\n"
+		 "\t\t\t 8 = Leadtek WinFast DVR3100 H\n"
 		 "\t\t\t 0 = Autodetect (default)\n"
 		 "\t\t\t-1 = Ignore this card\n\t\t");
 MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
@@ -312,7 +314,7 @@
 	CX18_INFO("Autodetected %s\n", cx->card_name);
 
 	if (tv.tuner_type == TUNER_ABSENT)
-		CX18_ERR("tveeprom cannot autodetect tuner!");
+		CX18_ERR("tveeprom cannot autodetect tuner!\n");
 
 	if (cx->options.tuner == -1)
 		cx->options.tuner = tv.tuner_type;
@@ -546,6 +548,40 @@
 	cx->card_i2c = cx->card->i2c;
 }
 
+static int __devinit cx18_create_in_workq(struct cx18 *cx)
+{
+	snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
+		 cx->v4l2_dev.name);
+	cx->in_work_queue = create_singlethread_workqueue(cx->in_workq_name);
+	if (cx->in_work_queue == NULL) {
+		CX18_ERR("Unable to create incoming mailbox handler thread\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int __devinit cx18_create_out_workq(struct cx18 *cx)
+{
+	snprintf(cx->out_workq_name, sizeof(cx->out_workq_name), "%s-out",
+		 cx->v4l2_dev.name);
+	cx->out_work_queue = create_workqueue(cx->out_workq_name);
+	if (cx->out_work_queue == NULL) {
+		CX18_ERR("Unable to create outgoing mailbox handler threads\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
+		cx->in_work_order[i].cx = cx;
+		cx->in_work_order[i].str = cx->epu_debug_str;
+		INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler);
+	}
+}
+
 /* Precondition: the cx18 structure has been memset to 0. Only
    the dev and instance fields have been filled in.
    No assumptions on the card type may be made here (see cx18_init_struct2
@@ -553,7 +589,7 @@
  */
 static int __devinit cx18_init_struct1(struct cx18 *cx)
 {
-	int i;
+	int ret;
 
 	cx->base_addr = pci_resource_start(cx->pci_dev, 0);
 
@@ -562,18 +598,18 @@
 	mutex_init(&cx->epu2apu_mb_lock);
 	mutex_init(&cx->epu2cpu_mb_lock);
 
-	cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name);
-	if (cx->work_queue == NULL) {
-		CX18_ERR("Unable to create work hander thread\n");
-		return -ENOMEM;
-	}
+	ret = cx18_create_out_workq(cx);
+	if (ret)
+		return ret;
 
-	for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
-		cx->epu_work_order[i].cx = cx;
-		cx->epu_work_order[i].str = cx->epu_debug_str;
-		INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler);
+	ret = cx18_create_in_workq(cx);
+	if (ret) {
+		destroy_workqueue(cx->out_work_queue);
+		return ret;
 	}
 
+	cx18_init_in_work_orders(cx);
+
 	/* start counting open_id at 1 */
 	cx->open_id = 1;
 
@@ -759,17 +795,17 @@
 		retval = -ENODEV;
 		goto err;
 	}
-	if (cx18_init_struct1(cx)) {
-		retval = -ENOMEM;
+
+	retval = cx18_init_struct1(cx);
+	if (retval)
 		goto err;
-	}
 
 	CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
 
 	/* PCI Device Setup */
 	retval = cx18_setup_pci(cx, pci_dev, pci_id);
 	if (retval != 0)
-		goto free_workqueue;
+		goto free_workqueues;
 
 	/* map io memory */
 	CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
@@ -943,8 +979,9 @@
 	cx18_iounmap(cx);
 free_mem:
 	release_mem_region(cx->base_addr, CX18_MEM_SIZE);
-free_workqueue:
-	destroy_workqueue(cx->work_queue);
+free_workqueues:
+	destroy_workqueue(cx->in_work_queue);
+	destroy_workqueue(cx->out_work_queue);
 err:
 	if (retval == 0)
 		retval = -ENODEV;
@@ -1053,11 +1090,19 @@
 	return 0;
 }
 
-static void cx18_cancel_epu_work_orders(struct cx18 *cx)
+static void cx18_cancel_in_work_orders(struct cx18 *cx)
 {
 	int i;
-	for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++)
-		cancel_work_sync(&cx->epu_work_order[i].work);
+	for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++)
+		cancel_work_sync(&cx->in_work_order[i].work);
+}
+
+static void cx18_cancel_out_work_orders(struct cx18 *cx)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_STREAMS; i++)
+		if (&cx->streams[i].video_dev != NULL)
+			cancel_work_sync(&cx->streams[i].out_work_order);
 }
 
 static void cx18_remove(struct pci_dev *pci_dev)
@@ -1073,15 +1118,20 @@
 	if (atomic_read(&cx->tot_capturing) > 0)
 		cx18_stop_all_captures(cx);
 
-	/* Interrupts */
+	/* Stop interrupts that cause incoming work to be queued */
 	cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+
+	/* Incoming work can cause outgoing work, so clean up incoming first */
+	cx18_cancel_in_work_orders(cx);
+	cx18_cancel_out_work_orders(cx);
+
+	/* Stop ack interrupts that may have been needed for work to finish */
 	cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
 
 	cx18_halt_firmware(cx);
 
-	cx18_cancel_epu_work_orders(cx);
-
-	destroy_workqueue(cx->work_queue);
+	destroy_workqueue(cx->in_work_queue);
+	destroy_workqueue(cx->out_work_queue);
 
 	cx18_streams_cleanup(cx, 1);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-driver.h linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-driver.h
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-driver.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-driver.h	2009-09-09 18:13:59.000000000 -0400
@@ -80,8 +80,9 @@
 #define CX18_CARD_YUAN_MPC718 	      3	/* Yuan MPC718 */
 #define CX18_CARD_CNXT_RAPTOR_PAL     4	/* Conexant Raptor PAL */
 #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/
-#define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100/DVR3100 H */
-#define CX18_CARD_LAST 		      6
+#define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100 */
+#define CX18_CARD_LEADTEK_DVR3100H    7 /* Leadtek WinFast DVR3100 H */
+#define CX18_CARD_LAST 		      7
 
 #define CX18_ENC_STREAM_TYPE_MPG  0
 #define CX18_ENC_STREAM_TYPE_TS   1
@@ -254,6 +255,7 @@
 #define CX18_F_S_INTERNAL_USE	5	/* this stream is used internally (sliced VBI processing) */
 #define CX18_F_S_STREAMOFF	7	/* signal end of stream EOS */
 #define CX18_F_S_APPL_IO        8	/* this stream is used read/written by an application */
+#define CX18_F_S_STOPPING	9	/* telling the fw to stop capturing */
 
 /* per-cx18, i_flags */
 #define CX18_F_I_LOADED_FW		0 	/* Loaded firmware 1st time */
@@ -285,6 +287,7 @@
 	struct list_head list;
 	atomic_t buffers;
 	u32 bytesused;
+	spinlock_t lock;
 };
 
 struct cx18_dvb {
@@ -305,7 +308,7 @@
 
 
 #define CX18_MAX_MDL_ACKS 2
-#define CX18_MAX_EPU_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7)
+#define CX18_MAX_IN_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7)
 /* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */
 
 #define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1
@@ -313,7 +316,7 @@
 #define CX18_F_EWO_MB_STALE \
 	     (CX18_F_EWO_MB_STALE_UPON_RECEIPT | CX18_F_EWO_MB_STALE_WHILE_PROC)
 
-struct cx18_epu_work_order {
+struct cx18_in_work_order {
 	struct work_struct work;
 	atomic_t pending;
 	struct cx18 *cx;
@@ -337,7 +340,6 @@
 	unsigned mdl_offset;
 
 	u32 id;
-	struct mutex qlock; 	/* locks access to the queues */
 	unsigned long s_flags;	/* status flags, see above */
 	int dma;		/* can be PCI_DMA_TODEVICE,
 				   PCI_DMA_FROMDEVICE or
@@ -353,6 +355,8 @@
 	struct cx18_queue q_busy;	/* busy buffers - in use by firmware */
 	struct cx18_queue q_full;	/* full buffers - data for user apps */
 
+	struct work_struct out_work_order;
+
 	/* DVB / Digital Transport */
 	struct cx18_dvb dvb;
 };
@@ -568,10 +572,14 @@
 	u32 sw2_irq_mask;
 	u32 hw2_irq_mask;
 
-	struct workqueue_struct *work_queue;
-	struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS];
+	struct workqueue_struct *in_work_queue;
+	char in_workq_name[11]; /* "cx18-NN-in" */
+	struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS];
 	char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
 
+	struct workqueue_struct *out_work_queue;
+	char out_workq_name[12]; /* "cx18-NN-out" */
+
 	/* i2c */
 	struct i2c_adapter i2c_adap[2];
 	struct i2c_algo_bit_data i2c_algo[2];
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-dvb.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-dvb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-dvb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-dvb.c	2012-03-22 20:09:44.000000000 -0400
@@ -23,14 +23,29 @@
 #include "cx18-version.h"
 #include "cx18-dvb.h"
 #include "cx18-io.h"
+#include "cx18-queue.h"
 #include "cx18-streams.h"
 #include "cx18-cards.h"
+#include "cx18-gpio.h"
 #include "s5h1409.h"
 #include "mxl5005s.h"
+#include "zl10353.h"
+
+#include <linux/firmware.h>
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "tuner-xc2028.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
+#define CX18_CLOCK_ENABLE2		 0xc71024
+#define CX18_DMUX_CLK_MASK		 0x0080
+
+/*
+ * CX18_CARD_HVR_1600_ESMT
+ * CX18_CARD_HVR_1600_SAMSUNG
+ */
 
 static struct mxl5005s_config hauppauge_hvr1600_tuner = {
 	.i2c_address     = 0xC6 >> 1,
@@ -57,7 +72,133 @@
 	.inversion     = S5H1409_INVERSION_OFF,
 	.status_mode   = S5H1409_DEMODLOCKING,
 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
+};
+
+/*
+ * CX18_CARD_LEADTEK_DVR3100H
+ */
+/* Information/confirmation of proper config values provided by Terry Wu */
+static struct zl10353_config leadtek_dvr3100h_demod = {
+	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+	.parallel_ts           = 1,         /* Not a serial TS */
+	.no_tuner              = 1,         /* XC3028 is not behind the gate */
+	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
+/*
+ * CX18_CARD_YUAN_MPC718
+ */
+/*
+ * Due to
+ *
+ * 1. an absence of information on how to prgram the MT352
+ * 2. the Linux mt352 module pushing MT352 initialzation off onto us here
+ *
+ * We have to use an init sequence that *you* must extract from the Windows
+ * driver (yuanrap.sys) and which we load as a firmware.
+ *
+ * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual
+ * with chip programming details, then I can remove this annoyance.
+ */
+static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
+				   const struct firmware **fw)
+{
+	struct cx18 *cx = stream->cx;
+	const char *fn = "/*(DEBLOBBED)*/";
+	int ret;
+
+	ret = reject_firmware(fw, fn, &cx->pci_dev->dev);
+	if (ret)
+		CX18_ERR("Unable to open firmware file %s\n", fn);
+	else {
+		size_t sz = (*fw)->size;
+		if (sz < 2 || sz > 64 || (sz % 2) != 0) {
+			CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
+				 fn, (unsigned long) sz);
+			ret = -EILSEQ;
+			release_firmware(*fw);
+			*fw = NULL;
+		}
+	}
+
+	if (ret) {
+		CX18_ERR("The MPC718 board variant with the MT352 DVB-T"
+			  "demodualtor will not work without it\n");
+		CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware "
+			  "mpc718' if you need the firmware\n");
+	}
+	return ret;
+}
+
+static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
+{
+	struct cx18_dvb *dvb = container_of(fe->dvb,
+					    struct cx18_dvb, dvb_adapter);
+	struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb);
+	const struct firmware *fw = NULL;
+	int ret;
+	int i;
+	u8 buf[3];
+
+	ret = yuan_mpc718_mt352_reqfw(stream, &fw);
+	if (ret)
+		return ret;
+
+	/* Loop through all the register-value pairs in the firmware file */
+	for (i = 0; i < fw->size; i += 2) {
+		buf[0] = fw->data[i];
+		/* Intercept a few registers we want to set ourselves */
+		switch (buf[0]) {
+		case TRL_NOMINAL_RATE_0:
+			/* Set our custom OFDM bandwidth in the case below */
+			break;
+		case TRL_NOMINAL_RATE_1:
+			/* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
+			/* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
+			/* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
+			buf[1] = 0x72;
+			buf[2] = 0x49;
+			mt352_write(fe, buf, 3);
+			break;
+		case INPUT_FREQ_0:
+			/* Set our custom IF in the case below */
+			break;
+		case INPUT_FREQ_1:
+			/* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
+			buf[1] = 0x31;
+			buf[2] = 0xc0;
+			mt352_write(fe, buf, 3);
+			break;
+		default:
+			/* Pass through the register-value pair from the fw */
+			buf[1] = fw->data[i+1];
+			mt352_write(fe, buf, 2);
+			break;
+		}
+	}
+
+	buf[0] = (u8) TUNER_GO;
+	buf[1] = 0x01; /* Go */
+	mt352_write(fe, buf, 2);
+	release_firmware(fw);
+	return 0;
+}
+
+static struct mt352_config yuan_mpc718_mt352_demod = {
+	.demod_address = 0x1e >> 1,
+	.adc_clock     = 20480,     /* 20.480 MHz */
+	.if2           =  4560,     /*  4.560 MHz */
+	.no_tuner      = 1,         /* XC3028 is not behind the gate */
+	.demod_init    = yuan_mpc718_mt352_init,
+};
 
+static struct zl10353_config yuan_mpc718_zl10353_demod = {
+	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+	.parallel_ts           = 1,         /* Not a serial TS */
+	.no_tuner              = 1,         /* XC3028 is not behind the gate */
+	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
 };
 
 static int dvb_register(struct cx18_stream *stream);
@@ -98,6 +239,8 @@
 		cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
 		break;
 
+	case CX18_CARD_LEADTEK_DVR3100H:
+	case CX18_CARD_YUAN_MPC718:
 	default:
 		/* Assumption - Parallel transport - Signalling
 		 * undefined or default.
@@ -267,8 +410,7 @@
 }
 
 /* All the DVB attach calls go here, this function get's modified
- * for each new card. No other function in this file needs
- * to change.
+ * for each new card. cx18_dvb_start_feed() will also need changes.
  */
 static int dvb_register(struct cx18_stream *stream)
 {
@@ -289,6 +431,61 @@
 			ret = 0;
 		}
 		break;
+	case CX18_CARD_LEADTEK_DVR3100H:
+		dvb->fe = dvb_attach(zl10353_attach,
+				     &leadtek_dvr3100h_demod,
+				     &cx->i2c_adap[1]);
+		if (dvb->fe != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap = &cx->i2c_adap[1],
+				.i2c_addr = 0xc2 >> 1,
+				.ctrl = NULL,
+			};
+			static struct xc2028_ctrl ctrl = {
+				.fname   = "/*(DEBLOBBED)*/",
+				.max_len = 64,
+				.demod   = XC3028_FE_ZARLINK456,
+				.type    = XC2028_AUTO,
+			};
+
+			fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctrl);
+		}
+		break;
+	case CX18_CARD_YUAN_MPC718:
+		/*
+		 * TODO
+		 * Apparently, these cards also could instead have a
+		 * DiBcom demod supported by one of the db7000 drivers
+		 */
+		dvb->fe = dvb_attach(mt352_attach,
+				     &yuan_mpc718_mt352_demod,
+				     &cx->i2c_adap[1]);
+		if (dvb->fe == NULL)
+			dvb->fe = dvb_attach(zl10353_attach,
+					     &yuan_mpc718_zl10353_demod,
+					     &cx->i2c_adap[1]);
+		if (dvb->fe != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap = &cx->i2c_adap[1],
+				.i2c_addr = 0xc2 >> 1,
+				.ctrl = NULL,
+			};
+			static struct xc2028_ctrl ctrl = {
+				.fname   = "/*(DEBLOBBED)*/",
+				.max_len = 64,
+				.demod   = XC3028_FE_ZARLINK456,
+				.type    = XC2028_AUTO,
+			};
+
+			fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctrl);
+		}
+		break;
 	default:
 		/* No Digital Tv Support */
 		break;
@@ -299,6 +496,8 @@
 		return -1;
 	}
 
+	dvb->fe->callback = cx18_reset_tuner_gpio;
+
 	ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
 	if (ret < 0) {
 		if (dvb->fe->ops.release)
@@ -306,5 +505,16 @@
 		return ret;
 	}
 
+	/*
+	 * The firmware seems to enable the TS DMUX clock
+	 * under various circumstances.  However, since we know we
+	 * might use it, let's just turn it on ourselves here.
+	 */
+	cx18_write_reg_expect(cx,
+			      (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK,
+			      CX18_CLOCK_ENABLE2,
+			      CX18_DMUX_CLK_MASK,
+			      (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK);
+
 	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-fileops.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-fileops.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-fileops.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-fileops.c	2009-09-09 18:13:59.000000000 -0400
@@ -265,8 +265,13 @@
 		 * an MPEG-2 Program Pack start code, and provide only
 		 * up to that point to the user, so it's easy to insert VBI data
 		 * the next time around.
+		 *
+		 * This will not work for an MPEG-2 TS and has only been
+		 * verified by analysis to work for an MPEG-2 PS.  Helen Buus
+		 * pointed out this works for the CX23416 MPEG-2 DVD compatible
+		 * stream, and research indicates both the MPEG 2 SVCD and DVD
+		 * stream types use an MPEG-2 PS container.
 		 */
-		/* FIXME - This only works for an MPEG-2 PS, not a TS */
 		/*
 		 * An MPEG-2 Program Stream (PS) is a series of
 		 * MPEG-2 Program Packs terminated by an
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-mailbox.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-mailbox.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-mailbox.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-mailbox.c	2009-09-09 18:13:59.000000000 -0400
@@ -131,7 +131,7 @@
  * Functions that run in a work_queue work handling context
  */
 
-static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	u32 handle, mdl_ack_count, id;
 	struct cx18_mailbox *mb;
@@ -191,29 +191,30 @@
 		if (buf == NULL) {
 			CX18_WARN("Could not find buf %d for stream %s\n",
 				  id, s->name);
-			/* Put as many buffers as possible back into fw use */
-			cx18_stream_load_fw_queue(s);
 			continue;
 		}
 
-		if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
-			CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n",
-					  buf->bytesused);
-			dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
-					 buf->bytesused);
+		CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n",
+				  s->name, buf->bytesused);
+
+		if (s->type != CX18_ENC_STREAM_TYPE_TS)
+			cx18_enqueue(s, buf, &s->q_full);
+		else {
+			if (s->dvb.enabled)
+				dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
+						 buf->bytesused);
+			cx18_enqueue(s, buf, &s->q_free);
 		}
-		/* Put as many buffers as possible back into fw use */
-		cx18_stream_load_fw_queue(s);
-		/* Put back TS buffer, since it was removed from all queues */
-		if (s->type == CX18_ENC_STREAM_TYPE_TS)
-			cx18_stream_put_buf_fw(s, buf);
 	}
+	/* Put as many buffers as possible back into fw use */
+	cx18_stream_load_fw_queue(s);
+
 	wake_up(&cx->dma_waitq);
 	if (s->id != -1)
 		wake_up(&s->waitq);
 }
 
-static void epu_debug(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void epu_debug(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	char *p;
 	char *str = order->str;
@@ -224,7 +225,7 @@
 		CX18_INFO("FW version: %s\n", p - 1);
 }
 
-static void epu_cmd(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void epu_cmd(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	switch (order->rpu) {
 	case CPU:
@@ -253,18 +254,18 @@
 }
 
 static
-void free_epu_work_order(struct cx18 *cx, struct cx18_epu_work_order *order)
+void free_in_work_order(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	atomic_set(&order->pending, 0);
 }
 
-void cx18_epu_work_handler(struct work_struct *work)
+void cx18_in_work_handler(struct work_struct *work)
 {
-	struct cx18_epu_work_order *order =
-			container_of(work, struct cx18_epu_work_order, work);
+	struct cx18_in_work_order *order =
+			container_of(work, struct cx18_in_work_order, work);
 	struct cx18 *cx = order->cx;
 	epu_cmd(cx, order);
-	free_epu_work_order(cx, order);
+	free_in_work_order(cx, order);
 }
 
 
@@ -272,7 +273,7 @@
  * Functions that run in an interrupt handling context
  */
 
-static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+static void mb_ack_irq(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	struct cx18_mailbox __iomem *ack_mb;
 	u32 ack_irq, req;
@@ -308,7 +309,7 @@
 	return;
 }
 
-static int epu_dma_done_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+static int epu_dma_done_irq(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	u32 handle, mdl_ack_offset, mdl_ack_count;
 	struct cx18_mailbox *mb;
@@ -334,7 +335,7 @@
 }
 
 static
-int epu_debug_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+int epu_debug_irq(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	u32 str_offset;
 	char *str = order->str;
@@ -355,7 +356,7 @@
 }
 
 static inline
-int epu_cmd_irq(struct cx18 *cx, struct cx18_epu_work_order *order)
+int epu_cmd_irq(struct cx18 *cx, struct cx18_in_work_order *order)
 {
 	int ret = -1;
 
@@ -387,12 +388,12 @@
 }
 
 static inline
-struct cx18_epu_work_order *alloc_epu_work_order_irq(struct cx18 *cx)
+struct cx18_in_work_order *alloc_in_work_order_irq(struct cx18 *cx)
 {
 	int i;
-	struct cx18_epu_work_order *order = NULL;
+	struct cx18_in_work_order *order = NULL;
 
-	for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
+	for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
 		/*
 		 * We only need "pending" atomic to inspect its contents,
 		 * and need not do a check and set because:
@@ -401,8 +402,8 @@
 		 * 2. "pending" is only set here, and we're serialized because
 		 * we're called in an IRQ handler context.
 		 */
-		if (atomic_read(&cx->epu_work_order[i].pending) == 0) {
-			order = &cx->epu_work_order[i];
+		if (atomic_read(&cx->in_work_order[i].pending) == 0) {
+			order = &cx->in_work_order[i];
 			atomic_set(&order->pending, 1);
 			break;
 		}
@@ -414,7 +415,7 @@
 {
 	struct cx18_mailbox __iomem *mb;
 	struct cx18_mailbox *order_mb;
-	struct cx18_epu_work_order *order;
+	struct cx18_in_work_order *order;
 	int submit;
 
 	switch (rpu) {
@@ -428,7 +429,7 @@
 		return;
 	}
 
-	order = alloc_epu_work_order_irq(cx);
+	order = alloc_in_work_order_irq(cx);
 	if (order == NULL) {
 		CX18_WARN("Unable to find blank work order form to schedule "
 			  "incoming mailbox command processing\n");
@@ -461,7 +462,7 @@
 	 */
 	submit = epu_cmd_irq(cx, order);
 	if (submit > 0) {
-		queue_work(cx->work_queue, &order->work);
+		queue_work(cx->in_work_queue, &order->work);
 	}
 }
 
@@ -478,9 +479,10 @@
 	u32 __iomem *xpu_state;
 	wait_queue_head_t *waitq;
 	struct mutex *mb_lock;
-	long int timeout, ret;
+	unsigned long int t0, timeout, ret;
 	int i;
 	char argstr[MAX_MB_ARGUMENTS*11+1];
+	DEFINE_WAIT(w);
 
 	if (info == NULL) {
 		CX18_WARN("unknown cmd %x\n", cmd);
@@ -562,25 +564,49 @@
 
 	CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n",
 			  irq, info->name);
+
+	/* So we don't miss the wakeup, prepare to wait before notifying fw */
+	prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE);
 	cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
 
-	ret = wait_event_timeout(
-		       *waitq,
-		       cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request),
-		       timeout);
+	t0 = jiffies;
+	ack = cx18_readl(cx, &mb->ack);
+	if (ack != req) {
+		schedule_timeout(timeout);
+		ret = jiffies - t0;
+		ack = cx18_readl(cx, &mb->ack);
+	} else {
+		ret = jiffies - t0;
+	}
 
-	if (ret == 0) {
-		/* Timed out */
+	finish_wait(waitq, &w);
+
+	if (req != ack) {
 		mutex_unlock(mb_lock);
-		CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU "
-				"acknowledgement\n",
-				info->name, jiffies_to_msecs(timeout));
+		if (ret >= timeout) {
+			/* Timed out */
+			CX18_DEBUG_WARN("sending %s timed out waiting %d msecs "
+					"for RPU acknowledgement\n",
+					info->name, jiffies_to_msecs(ret));
+		} else {
+			CX18_DEBUG_WARN("woken up before mailbox ack was ready "
+					"after submitting %s to RPU.  only "
+					"waited %d msecs on req %u but awakened"
+					" with unmatched ack %u\n",
+					info->name,
+					jiffies_to_msecs(ret),
+					req, ack);
+		}
 		return -EINVAL;
 	}
 
-	if (ret != timeout)
+	if (ret >= timeout)
+		CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment "
+				"sending %s; timed out waiting %d msecs\n",
+				info->name, jiffies_to_msecs(ret));
+	else
 		CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
-				  jiffies_to_msecs(timeout-ret), info->name);
+				  jiffies_to_msecs(ret), info->name);
 
 	/* Collect data returned by the XPU */
 	for (i = 0; i < MAX_MB_ARGUMENTS; i++)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-mailbox.h linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-mailbox.h
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-mailbox.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-mailbox.h	2009-09-09 18:13:59.000000000 -0400
@@ -95,6 +95,6 @@
 
 void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu);
 
-void cx18_epu_work_handler(struct work_struct *work);
+void cx18_in_work_handler(struct work_struct *work);
 
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-queue.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-queue.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-queue.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-queue.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,8 @@
  */
 
 #include "cx18-driver.h"
-#include "cx18-streams.h"
 #include "cx18-queue.h"
+#include "cx18-streams.h"
 #include "cx18-scb.h"
 
 void cx18_buf_swap(struct cx18_buffer *buf)
@@ -53,13 +53,13 @@
 		buf->skipped = 0;
 	}
 
-	mutex_lock(&s->qlock);
-
 	/* q_busy is restricted to a max buffer count imposed by firmware */
 	if (q == &s->q_busy &&
 	    atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM)
 		q = &s->q_free;
 
+	spin_lock(&q->lock);
+
 	if (to_front)
 		list_add(&buf->list, &q->list); /* LIFO */
 	else
@@ -67,7 +67,7 @@
 	q->bytesused += buf->bytesused - buf->readpos;
 	atomic_inc(&q->buffers);
 
-	mutex_unlock(&s->qlock);
+	spin_unlock(&q->lock);
 	return q;
 }
 
@@ -75,7 +75,7 @@
 {
 	struct cx18_buffer *buf = NULL;
 
-	mutex_lock(&s->qlock);
+	spin_lock(&q->lock);
 	if (!list_empty(&q->list)) {
 		buf = list_first_entry(&q->list, struct cx18_buffer, list);
 		list_del_init(&buf->list);
@@ -83,7 +83,7 @@
 		buf->skipped = 0;
 		atomic_dec(&q->buffers);
 	}
-	mutex_unlock(&s->qlock);
+	spin_unlock(&q->lock);
 	return buf;
 }
 
@@ -94,9 +94,23 @@
 	struct cx18_buffer *buf;
 	struct cx18_buffer *tmp;
 	struct cx18_buffer *ret = NULL;
+	LIST_HEAD(sweep_up);
 
-	mutex_lock(&s->qlock);
+	/*
+	 * We don't have to acquire multiple q locks here, because we are
+	 * serialized by the single threaded work handler.
+	 * Buffers from the firmware will thus remain in order as
+	 * they are moved from q_busy to q_full or to the dvb ring buffer.
+	 */
+	spin_lock(&s->q_busy.lock);
 	list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) {
+		/*
+		 * We should find what the firmware told us is done,
+		 * right at the front of the queue.  If we don't, we likely have
+		 * missed a buffer done message from the firmware.
+		 * Once we skip a buffer repeatedly, relative to the size of
+		 * q_busy, we have high confidence we've missed it.
+		 */
 		if (buf->id != id) {
 			buf->skipped++;
 			if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) {
@@ -105,38 +119,41 @@
 					  "times - it must have dropped out of "
 					  "rotation\n", s->name, buf->id,
 					  buf->skipped);
-				/* move it to q_free */
-				list_move_tail(&buf->list, &s->q_free.list);
-				buf->bytesused = buf->readpos = buf->b_flags =
-					buf->skipped = 0;
+				/* Sweep it up to put it back into rotation */
+				list_move_tail(&buf->list, &sweep_up);
 				atomic_dec(&s->q_busy.buffers);
-				atomic_inc(&s->q_free.buffers);
 			}
 			continue;
 		}
-
-		buf->bytesused = bytesused;
-		/* Sync the buffer before we release the qlock */
-		cx18_buf_sync_for_cpu(s, buf);
-		if (s->type == CX18_ENC_STREAM_TYPE_TS) {
-			/*
-			 * TS doesn't use q_full.  As we pull the buffer off of
-			 * the queue here, the caller will have to put it back.
-			 */
-			list_del_init(&buf->list);
-		} else {
-			/* Move buffer from q_busy to q_full */
-			list_move_tail(&buf->list, &s->q_full.list);
-			set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
-			s->q_full.bytesused += buf->bytesused;
-			atomic_inc(&s->q_full.buffers);
-		}
+		/*
+		 * We pull the desired buffer off of the queue here.  Something
+		 * will have to put it back on a queue later.
+		 */
+		list_del_init(&buf->list);
 		atomic_dec(&s->q_busy.buffers);
-
 		ret = buf;
 		break;
 	}
-	mutex_unlock(&s->qlock);
+	spin_unlock(&s->q_busy.lock);
+
+	/*
+	 * We found the buffer for which we were looking.  Get it ready for
+	 * the caller to put on q_full or in the dvb ring buffer.
+	 */
+	if (ret != NULL) {
+		ret->bytesused = bytesused;
+		ret->skipped = 0;
+		/* readpos and b_flags were 0'ed when the buf went on q_busy */
+		cx18_buf_sync_for_cpu(s, ret);
+		if (s->type != CX18_ENC_STREAM_TYPE_TS)
+			set_bit(CX18_F_B_NEED_BUF_SWAP, &ret->b_flags);
+	}
+
+	/* Put any buffers the firmware is ignoring back into normal rotation */
+	list_for_each_entry_safe(buf, tmp, &sweep_up, list) {
+		list_del_init(&buf->list);
+		cx18_enqueue(s, buf, &s->q_free);
+	}
 	return ret;
 }
 
@@ -148,7 +165,7 @@
 	if (q == &s->q_free)
 		return;
 
-	mutex_lock(&s->qlock);
+	spin_lock(&q->lock);
 	while (!list_empty(&q->list)) {
 		buf = list_first_entry(&q->list, struct cx18_buffer, list);
 		list_move_tail(&buf->list, &s->q_free.list);
@@ -156,7 +173,7 @@
 		atomic_inc(&s->q_free.buffers);
 	}
 	cx18_queue_init(q);
-	mutex_unlock(&s->qlock);
+	spin_unlock(&q->lock);
 }
 
 void cx18_flush_queues(struct cx18_stream *s)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-streams.c linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-streams.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-streams.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-streams.c	2009-09-09 18:13:59.000000000 -0400
@@ -116,12 +116,16 @@
 	s->buffers = cx->stream_buffers[type];
 	s->buf_size = cx->stream_buf_size[type];
 
-	mutex_init(&s->qlock);
 	init_waitqueue_head(&s->waitq);
 	s->id = -1;
+	spin_lock_init(&s->q_free.lock);
 	cx18_queue_init(&s->q_free);
+	spin_lock_init(&s->q_busy.lock);
 	cx18_queue_init(&s->q_busy);
+	spin_lock_init(&s->q_full.lock);
 	cx18_queue_init(&s->q_full);
+
+	INIT_WORK(&s->out_work_order, cx18_out_work_handler);
 }
 
 static int cx18_prep_dev(struct cx18 *cx, int type)
@@ -367,9 +371,14 @@
 		 * Tell the encoder to capture 21-4+1=18 lines per field,
 		 * since we want lines 10 through 21.
 		 *
-		 * FIXME - revisit for 625/50 systems
+		 * For 625/50 systems, according to the VIP 2 & BT.656 std:
+		 * The EAV RP code's Field bit toggles on line 1, a few lines
+		 * after the Vertcal Blank bit has already toggled.
+		 * (We've actually set the digitizer so that the Field bit
+		 * toggles on line 2.) Tell the encoder to capture 23-2+1=22
+		 * lines per field, since we want lines 6 through 23.
 		 */
-		lines = cx->is_60hz ? (21 - 4 + 1) * 2 : 38;
+		lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 2 + 1) * 2;
 	}
 
 	data[0] = s->handle;
@@ -431,14 +440,16 @@
 	cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
 }
 
-struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
-					  struct cx18_buffer *buf)
+static
+struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s,
+					   struct cx18_buffer *buf)
 {
 	struct cx18 *cx = s->cx;
 	struct cx18_queue *q;
 
 	/* Don't give it to the firmware, if we're not running a capture */
 	if (s->handle == CX18_INVALID_TASK_HANDLE ||
+	    test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
 	    !test_bit(CX18_F_S_STREAMING, &s->s_flags))
 		return cx18_enqueue(s, buf, &s->q_free);
 
@@ -453,7 +464,8 @@
 	return q;
 }
 
-void cx18_stream_load_fw_queue(struct cx18_stream *s)
+static
+void _cx18_stream_load_fw_queue(struct cx18_stream *s)
 {
 	struct cx18_queue *q;
 	struct cx18_buffer *buf;
@@ -467,11 +479,19 @@
 		buf = cx18_dequeue(s, &s->q_free);
 		if (buf == NULL)
 			break;
-		q = cx18_stream_put_buf_fw(s, buf);
+		q = _cx18_stream_put_buf_fw(s, buf);
 	} while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM
 		 && q == &s->q_busy);
 }
 
+void cx18_out_work_handler(struct work_struct *work)
+{
+	struct cx18_stream *s =
+			 container_of(work, struct cx18_stream, out_work_order);
+
+	_cx18_stream_load_fw_queue(s);
+}
+
 int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
 {
 	u32 data[MAX_MB_ARGUMENTS];
@@ -600,19 +620,20 @@
 
 	/* Init all the cpu_mdls for this stream */
 	cx18_flush_queues(s);
-	mutex_lock(&s->qlock);
+	spin_lock(&s->q_free.lock);
 	list_for_each_entry(buf, &s->q_free.list, list) {
 		cx18_writel(cx, buf->dma_handle,
 					&cx->scb->cpu_mdl[buf->id].paddr);
 		cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
 	}
-	mutex_unlock(&s->qlock);
-	cx18_stream_load_fw_queue(s);
+	spin_unlock(&s->q_free.lock);
+	_cx18_stream_load_fw_queue(s);
 
 	/* begin_capture */
 	if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
 		CX18_DEBUG_WARN("Error starting capture!\n");
 		/* Ensure we're really not capturing before releasing MDLs */
+		set_bit(CX18_F_S_STOPPING, &s->s_flags);
 		if (s->type == CX18_ENC_STREAM_TYPE_MPG)
 			cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
 		else
@@ -622,6 +643,7 @@
 		cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
 		cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
 		s->handle = CX18_INVALID_TASK_HANDLE;
+		clear_bit(CX18_F_S_STOPPING, &s->s_flags);
 		if (atomic_read(&cx->tot_capturing) == 0) {
 			set_bit(CX18_F_I_EOS, &cx->i_flags);
 			cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
@@ -666,6 +688,7 @@
 	if (atomic_read(&cx->tot_capturing) == 0)
 		return 0;
 
+	set_bit(CX18_F_S_STOPPING, &s->s_flags);
 	if (s->type == CX18_ENC_STREAM_TYPE_MPG)
 		cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
 	else
@@ -689,6 +712,7 @@
 
 	cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
 	s->handle = CX18_INVALID_TASK_HANDLE;
+	clear_bit(CX18_F_S_STOPPING, &s->s_flags);
 
 	if (atomic_read(&cx->tot_capturing) > 0)
 		return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-streams.h linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-streams.h
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-streams.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-streams.h	2009-09-09 18:13:59.000000000 -0400
@@ -28,10 +28,24 @@
 int cx18_streams_register(struct cx18 *cx);
 void cx18_streams_cleanup(struct cx18 *cx, int unregister);
 
+/* Related to submission of buffers to firmware */
+static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
+{
+	struct cx18 *cx = s->cx;
+	queue_work(cx->out_work_queue, &s->out_work_order);
+}
+
+static inline void cx18_stream_put_buf_fw(struct cx18_stream *s,
+					  struct cx18_buffer *buf)
+{
+	/* Put buf on q_free; the out work handler will move buf(s) to q_busy */
+	cx18_enqueue(s, buf, &s->q_free);
+	cx18_stream_load_fw_queue(s);
+}
+
+void cx18_out_work_handler(struct work_struct *work);
+
 /* Capture related */
-void cx18_stream_load_fw_queue(struct cx18_stream *s);
-struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
-					  struct cx18_buffer *buf);
 int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
 int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-version.h linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-version.h
--- linux-libre-2.6.30-gnu/drivers/media/video/cx18/cx18-version.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx18/cx18-version.h	2009-09-09 18:13:59.000000000 -0400
@@ -24,7 +24,7 @@
 
 #define CX18_DRIVER_NAME "cx18"
 #define CX18_DRIVER_VERSION_MAJOR 1
-#define CX18_DRIVER_VERSION_MINOR 1
+#define CX18_DRIVER_VERSION_MINOR 2
 #define CX18_DRIVER_VERSION_PATCHLEVEL 0
 
 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,6 @@
 #include <linux/bitmap.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
 
@@ -1053,22 +1052,13 @@
 /* Set resolution of the video */
 int cx231xx_resolution_set(struct cx231xx *dev)
 {
-	int width, height;
-	u32 hscale, vscale;
-	int status = 0;
-
-	width = dev->width;
-	height = dev->height;
-
-	get_scale(dev, width, height, &hscale, &vscale);
-
 	/* set horzontal scale */
-	status = vid_blk_write_word(dev, HSCALE_CTRL, hscale);
+	int status = vid_blk_write_word(dev, HSCALE_CTRL, dev->hscale);
+	if (status)
+		return status;
 
 	/* set vertical scale */
-	status = vid_blk_write_word(dev, VSCALE_CTRL, vscale);
-
-	return status;
+	return vid_blk_write_word(dev, VSCALE_CTRL, dev->vscale);
 }
 
 /******************************************************************************
@@ -2056,7 +2046,7 @@
 
 int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
 {
-	int rc;
+	int rc = -1;
 	u32 ep_mask = -1;
 	struct pcb_config *pcb_config;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-cards.c linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-cards.c	2012-03-22 19:11:44.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-cards.c	2012-03-22 20:08:07.000000000 -0400
@@ -281,12 +281,12 @@
 }
 
 /* ----------------------------------------------------------------------- */
-void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir)
+void cx231xx_register_i2c_ir(struct cx231xx *dev)
 {
-	if (disable_ir) {
-		ir->get_key = NULL;
+	if (disable_ir)
 		return;
-	}
+
+	/* REVISIT: instantiate IR device */
 
 	/* detect & configure */
 	switch (dev->model) {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx.h linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx.h
--- linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -722,9 +722,6 @@
 int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input);
 int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev);
 int cx231xx_set_audio_input(struct cx231xx *dev, u8 input);
-void get_scale(struct cx231xx *dev,
-	       unsigned int width, unsigned int height,
-	       unsigned int *hscale, unsigned int *vscale);
 
 /* Provided by cx231xx-video.c */
 int cx231xx_register_extension(struct cx231xx_ops *dev);
@@ -738,7 +735,7 @@
 extern struct cx231xx_board cx231xx_boards[];
 extern struct usb_device_id cx231xx_id_table[];
 extern const unsigned int cx231xx_bcount;
-void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir);
+void cx231xx_register_i2c_ir(struct cx231xx *dev);
 int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
 
 /* Provided by cx231xx-input.c */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -424,34 +424,6 @@
 	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
 }
 
-/*
- * attach_inform()
- * gets called when a device attaches to the i2c bus
- * does some basic configuration
- */
-static int attach_inform(struct i2c_client *client)
-{
-	struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter);
-	struct cx231xx *dev = bus->dev;
-
-	switch (client->addr << 1) {
-	case 0x8e:
-		{
-			struct IR_i2c *ir = i2c_get_clientdata(client);
-			dprintk1(1, "attach_inform: IR detected (%s).\n",
-				 ir->phys);
-			cx231xx_set_ir(dev, ir);
-			break;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return 0;
-}
-
 static struct i2c_algorithm cx231xx_algo = {
 	.master_xfer = cx231xx_i2c_xfer,
 	.functionality = functionality,
@@ -462,7 +434,6 @@
 	.name = "cx231xx",
 	.id = I2C_HW_B_CX231XX,
 	.algo = &cx231xx_algo,
-	.client_register = attach_inform,
 };
 
 static struct i2c_client cx231xx_client_template = {
@@ -537,6 +508,9 @@
 	if (0 == bus->i2c_rc) {
 		if (i2c_scan)
 			cx231xx_do_i2c_scan(dev, &bus->i2c_client);
+
+		/* Instantiate the IR receiver device, if present */
+		cx231xx_register_i2c_ir(dev);
 	} else
 		cx231xx_warn("%s: i2c bus %d register FAILED\n",
 			     dev->name, bus->nr);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-input.c linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-input.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-input.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-input.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,7 +36,7 @@
 
 #define i2cdprintk(fmt, arg...) \
 	if (ir_debug) { \
-		printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+		printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
 	}
 
 #define dprintk(fmt, arg...) \
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,7 +26,6 @@
 #include <linux/bitmap.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-video.c linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx231xx/cx231xx-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx231xx/cx231xx-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -893,9 +893,9 @@
 	return 0;
 }
 
-void get_scale(struct cx231xx *dev,
-	       unsigned int width, unsigned int height,
-	       unsigned int *hscale, unsigned int *vscale)
+static void get_scale(struct cx231xx *dev,
+		      unsigned int width, unsigned int height,
+		      unsigned int *hscale, unsigned int *vscale)
 {
 	unsigned int maxw = norm_maxw(dev);
 	unsigned int maxh = norm_maxh(dev);
@@ -907,10 +907,6 @@
 	*vscale = (((unsigned long)maxh) << 12) / height - 4096L;
 	if (*vscale >= 0x4000)
 		*vscale = 0x3fff;
-
-	dev->hscale = *hscale;
-	dev->vscale = *vscale;
-
 }
 
 /* ------------------------------------------------------------------
@@ -955,8 +951,8 @@
 {
 	struct cx231xx_fh *fh = priv;
 	struct cx231xx *dev = fh->dev;
-	int width = f->fmt.pix.width;
-	int height = f->fmt.pix.height;
+	unsigned int width = f->fmt.pix.width;
+	unsigned int height = f->fmt.pix.height;
 	unsigned int maxw = norm_maxw(dev);
 	unsigned int maxh = norm_maxh(dev);
 	unsigned int hscale, vscale;
@@ -971,17 +967,7 @@
 
 	/* width must even because of the YUYV format
 	   height must be even because of interlacing */
-	height &= 0xfffe;
-	width &= 0xfffe;
-
-	if (unlikely(height < 32))
-		height = 32;
-	if (unlikely(height > maxh))
-		height = maxh;
-	if (unlikely(width < 48))
-		width = 48;
-	if (unlikely(width > maxw))
-		width = maxw;
+	v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
 
 	get_scale(dev, width, height, &hscale, &vscale);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx2341x.c linux-libre-2.6.31-gnu/drivers/media/video/cx2341x.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx2341x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx2341x.c	2009-09-09 18:13:59.000000000 -0400
@@ -500,6 +500,8 @@
 	int err;
 
 	switch (qctrl->id) {
+	case V4L2_CID_MPEG_CLASS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
 	case V4L2_CID_MPEG_STREAM_TYPE:
 		return v4l2_ctrl_query_fill(qctrl,
 				V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cimax2.c linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cimax2.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cimax2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cimax2.c	2009-09-09 18:13:59.000000000 -0400
@@ -312,7 +312,7 @@
 		"TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0],
 		buf[32]);
 
-	if (buf[0] && 1)
+	if (buf[0] & 1)
 		state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
 			DVB_CA_EN50221_POLL_CAM_READY;
 	else
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-417.c linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-417.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-417.c	2012-03-22 19:13:36.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-417.c	2012-03-22 20:09:49.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/smp_lock.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
@@ -57,7 +58,8 @@
 
 #define dprintk(level, fmt, arg...)\
 	do { if (v4l_debug >= level) \
-		printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
+		printk(KERN_DEBUG "%s: " fmt, \
+		(dev) ? dev->name : "cx23885[?]", ## arg); \
 	} while (0)
 
 static struct cx23885_tvnorm cx23885_tvnorms[] = {
@@ -1676,6 +1678,7 @@
 	.read	       = mpeg_read,
 	.poll          = mpeg_poll,
 	.mmap	       = mpeg_mmap,
+	.ioctl	       = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
@@ -1712,6 +1715,8 @@
 	.fops          = &mpeg_fops,
 	.ioctl_ops     = &mpeg_ioctl_ops,
 	.minor         = -1,
+	.tvnorms       = CX23885_NORMS,
+	.current_norm  = V4L2_STD_NTSC_M,
 };
 
 void cx23885_417_unregister(struct cx23885_dev *dev)
@@ -1742,7 +1747,6 @@
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor   = -1;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
 		type, cx23885_boards[tsport->dev->board].name);
 	vfd->parent  = &pci->dev;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-cards.c linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-cards.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-cards.c	2009-09-09 18:13:59.000000000 -0400
@@ -181,6 +181,26 @@
 		.portb		= CX23885_MPEG_DVB,
 		.portc		= CX23885_MPEG_DVB,
 	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1270] = {
+		.name		= "Hauppauge WinTV-HVR1270",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1275] = {
+		.name		= "Hauppauge WinTV-HVR1275",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1255] = {
+		.name		= "Hauppauge WinTV-HVR1255",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1210] = {
+		.name		= "Hauppauge WinTV-HVR1210",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_MYGICA_X8506] = {
+		.name		= "Mygica X8506 DMB-TH",
+		.portb		= CX23885_MPEG_DVB,
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -280,6 +300,30 @@
 		.subvendor = 0x1b55,
 		.subdevice = 0x2a2c,
 		.card      = CX23885_BOARD_NETUP_DUAL_DVBS2_CI,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2211,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1270,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2215,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2251,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2291,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2295,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+	}, {
+		.subvendor = 0x14f1,
+		.subdevice = 0x8651,
+		.card      = CX23885_BOARD_MYGICA_X8506,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -321,6 +365,42 @@
 
 	/* Make sure we support the board model */
 	switch (tv.model) {
+	case 22001:
+		/* WinTV-HVR1270 (PCIe, Retail, half height)
+		 * ATSC/QAM and basic analog, IR Blast */
+	case 22009:
+		/* WinTV-HVR1210 (PCIe, Retail, half height)
+		 * DVB-T and basic analog, IR Blast */
+	case 22011:
+		/* WinTV-HVR1270 (PCIe, Retail, half height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22019:
+		/* WinTV-HVR1210 (PCIe, Retail, half height)
+		 * DVB-T and basic analog, IR Recv */
+	case 22021:
+		/* WinTV-HVR1275 (PCIe, Retail, half height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22029:
+		/* WinTV-HVR1210 (PCIe, Retail, half height)
+		 * DVB-T and basic analog, IR Recv */
+	case 22101:
+		/* WinTV-HVR1270 (PCIe, Retail, full height)
+		 * ATSC/QAM and basic analog, IR Blast */
+	case 22109:
+		/* WinTV-HVR1210 (PCIe, Retail, full height)
+		 * DVB-T and basic analog, IR Blast */
+	case 22111:
+		/* WinTV-HVR1270 (PCIe, Retail, full height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22119:
+		/* WinTV-HVR1210 (PCIe, Retail, full height)
+		 * DVB-T and basic analog, IR Recv */
+	case 22121:
+		/* WinTV-HVR1275 (PCIe, Retail, full height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22129:
+		/* WinTV-HVR1210 (PCIe, Retail, full height)
+		 * DVB-T and basic analog, IR Recv */
 	case 71009:
 		/* WinTV-HVR1200 (PCIe, Retail, full height)
 		 * DVB-T and basic analog */
@@ -619,6 +699,30 @@
 		/* enable irq */
 		cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
 		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
+		/* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */
+		/* GPIO-6 I2C Gate which can isolate the demod from the bus */
+		/* GPIO-9 Demod reset */
+
+		/* Put the parts into reset and back */
+		cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1);
+		cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5);
+		cx23885_gpio_clear(dev, GPIO_9);
+		mdelay(20);
+		cx23885_gpio_set(dev, GPIO_9);
+		break;
+	case CX23885_BOARD_MYGICA_X8506:
+		/* GPIO-1 reset XC5000 */
+		/* GPIO-2 reset LGS8GL5 */
+		cx_set(GP0_IO, 0x00060000);
+		cx_clear(GP0_IO, 0x00000006);
+		mdelay(100);
+		cx_set(GP0_IO, 0x00060006);
+		mdelay(100);
+		break;
 	}
 }
 
@@ -631,6 +735,10 @@
 	case CX23885_BOARD_HAUPPAUGE_HVR1800:
 	case CX23885_BOARD_HAUPPAUGE_HVR1200:
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
 		/* FIXME: Implement me */
 		break;
 	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
@@ -666,6 +774,10 @@
 	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
 	case CX23885_BOARD_HAUPPAUGE_HVR1200:
 	case CX23885_BOARD_HAUPPAUGE_HVR1700:
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
 		if (dev->i2c_bus[0].i2c_rc == 0)
 			hauppauge_eeprom(dev, eeprom+0xc0);
 		break;
@@ -714,6 +826,11 @@
 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
 		break;
+	case CX23885_BOARD_MYGICA_X8506:
+		ts1->gen_ctrl_val  = 0x5; /* Parallel */
+		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -723,6 +840,10 @@
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
 	default:
 		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-core.c linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -1700,9 +1700,13 @@
 	}
 
 	if (cx23885_boards[dev->board].cimax > 0 &&
-		((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1)))
-		/* handled += cx23885_irq_gpio(dev, pci_status); */
-		handled += netup_ci_slot_status(dev, pci_status);
+		((pci_status & PCI_MSK_GPIO0) ||
+			(pci_status & PCI_MSK_GPIO1))) {
+
+		if (cx23885_boards[dev->board].cimax > 0)
+			handled += netup_ci_slot_status(dev, pci_status);
+
+	}
 
 	if (ts1_status) {
 		if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
@@ -1729,6 +1733,88 @@
 	return IRQ_RETVAL(handled);
 }
 
+static inline int encoder_on_portb(struct cx23885_dev *dev)
+{
+	return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
+}
+
+static inline int encoder_on_portc(struct cx23885_dev *dev)
+{
+	return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER;
+}
+
+/* Mask represents 32 different GPIOs, GPIO's are split into multiple
+ * registers depending on the board configuration (and whether the
+ * 417 encoder (wi it's own GPIO's) are present. Each GPIO bit will
+ * be pushed into the correct hardware register, regardless of the
+ * physical location. Certain registers are shared so we sanity check
+ * and report errors if we think we're tampering with a GPIo that might
+ * be assigned to the encoder (and used for the host bus).
+ *
+ * GPIO  2 thru  0 - On the cx23885 bridge
+ * GPIO 18 thru  3 - On the cx23417 host bus interface
+ * GPIO 23 thru 19 - On the cx25840 a/v core
+ */
+void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask)
+{
+	if (mask & 0x7)
+		cx_set(GP0_IO, mask & 0x7);
+
+	if (mask & 0x0007fff8) {
+		if (encoder_on_portb(dev) || encoder_on_portc(dev))
+			printk(KERN_ERR
+				"%s: Setting GPIO on encoder ports\n",
+				dev->name);
+		cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3);
+	}
+
+	/* TODO: 23-19 */
+	if (mask & 0x00f80000)
+		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+}
+
+void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
+{
+	if (mask & 0x00000007)
+		cx_clear(GP0_IO, mask & 0x7);
+
+	if (mask & 0x0007fff8) {
+		if (encoder_on_portb(dev) || encoder_on_portc(dev))
+			printk(KERN_ERR
+				"%s: Clearing GPIO moving on encoder ports\n",
+				dev->name);
+		cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3);
+	}
+
+	/* TODO: 23-19 */
+	if (mask & 0x00f80000)
+		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+}
+
+void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
+{
+	if ((mask & 0x00000007) && asoutput)
+		cx_set(GP0_IO, (mask & 0x7) << 16);
+	else if ((mask & 0x00000007) && !asoutput)
+		cx_clear(GP0_IO, (mask & 0x7) << 16);
+
+	if (mask & 0x0007fff8) {
+		if (encoder_on_portb(dev) || encoder_on_portc(dev))
+			printk(KERN_ERR
+				"%s: Enabling GPIO on encoder ports\n",
+				dev->name);
+	}
+
+	/* MC417_OEN is active low for output, write 1 for an input */
+	if ((mask & 0x0007fff8) && asoutput)
+		cx_clear(MC417_OEN, (mask & 0x7fff8) >> 3);
+
+	else if ((mask & 0x0007fff8) && !asoutput)
+		cx_set(MC417_OEN, (mask & 0x7fff8) >> 3);
+
+	/* TODO: 23-19 */
+}
+
 static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
 				     const struct pci_device_id *pci_id)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-dvb.c linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-dvb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-dvb.c	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-dvb.c	2012-03-22 20:08:07.000000000 -0400
@@ -45,12 +45,15 @@
 #include "dibx000_common.h"
 #include "zl10353.h"
 #include "stv0900.h"
+#include "stv0900_reg.h"
 #include "stv6110.h"
 #include "lnbh24.h"
 #include "cx24116.h"
 #include "cimax2.h"
+#include "lgs8gxx.h"
 #include "netup-eeprom.h"
 #include "netup-init.h"
+#include "lgdt3305.h"
 
 static unsigned int debug;
 
@@ -122,7 +125,22 @@
 	.demod_address    = 0x10 >> 1,
 	.output_mode      = TDA10048_SERIAL_OUTPUT,
 	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
-	.inversion        = TDA10048_INVERSION_ON
+	.inversion        = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_3300,
+	.dtv7_if_freq_khz = TDA10048_IF_3800,
+	.dtv8_if_freq_khz = TDA10048_IF_4300,
+	.clk_freq_khz     = TDA10048_CLK_16000,
+};
+
+static struct tda10048_config hauppauge_hvr1210_config = {
+	.demod_address    = 0x10 >> 1,
+	.output_mode      = TDA10048_SERIAL_OUTPUT,
+	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
+	.inversion        = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_3300,
+	.dtv7_if_freq_khz = TDA10048_IF_3500,
+	.dtv8_if_freq_khz = TDA10048_IF_4000,
+	.clk_freq_khz     = TDA10048_CLK_16000,
 };
 
 static struct s5h1409_config hauppauge_ezqam_config = {
@@ -194,6 +212,16 @@
 	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
 };
 
+static struct s5h1411_config hcw_s5h1411_config = {
+	.output_mode   = S5H1411_SERIAL_OUTPUT,
+	.gpio          = S5H1411_GPIO_OFF,
+	.vsb_if        = S5H1411_IF_44000,
+	.qam_if        = S5H1411_IF_4000,
+	.inversion     = S5H1411_INVERSION_ON,
+	.status_mode   = S5H1411_DEMODLOCKING,
+	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
 static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
 	.i2c_address      = 0x61,
 	.if_khz           = 5380,
@@ -215,15 +243,51 @@
 		      .if_lvl = 6, .rfagc_top = 0x37 },
 };
 
+static struct tda18271_std_map hauppauge_hvr1200_tda18271_std_map = {
+	.dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+		      .if_lvl = 1, .rfagc_top = 0x37, },
+	.dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+		      .if_lvl = 1, .rfagc_top = 0x37, },
+	.dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+		      .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
 static struct tda18271_config hauppauge_tda18271_config = {
 	.std_map = &hauppauge_tda18271_std_map,
 	.gate    = TDA18271_GATE_ANALOG,
 };
 
 static struct tda18271_config hauppauge_hvr1200_tuner_config = {
+	.std_map = &hauppauge_hvr1200_tda18271_std_map,
 	.gate    = TDA18271_GATE_ANALOG,
 };
 
+static struct tda18271_config hauppauge_hvr1210_tuner_config = {
+	.gate    = TDA18271_GATE_DIGITAL,
+};
+
+static struct tda18271_std_map hauppauge_hvr127x_std_map = {
+	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
+		      .if_lvl = 1, .rfagc_top = 0x58 },
+	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
+		      .if_lvl = 1, .rfagc_top = 0x58 },
+};
+
+static struct tda18271_config hauppauge_hvr127x_config = {
+	.std_map = &hauppauge_hvr127x_std_map,
+};
+
+static struct lgdt3305_config hauppauge_lgdt3305_config = {
+	.i2c_addr           = 0x0e,
+	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
+	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
+	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+	.deny_i2c_rptr      = 1,
+	.spectral_inversion = 1,
+	.qam_if_khz         = 4000,
+	.vsb_if_khz         = 3250,
+};
+
 static struct dibx000_agc_config xc3028_agc_config = {
 	BAND_VHF | BAND_UHF,	/* band_caps */
 
@@ -317,13 +381,25 @@
 	.disable_i2c_gate_ctrl = 1,
 };
 
+static struct stv0900_reg stv0900_ts_regs[] = {
+	{ R0900_TSGENERAL, 0x00 },
+	{ R0900_P1_TSSPEED, 0x40 },
+	{ R0900_P2_TSSPEED, 0x40 },
+	{ R0900_P1_TSCFGM, 0xc0 },
+	{ R0900_P2_TSCFGM, 0xc0 },
+	{ R0900_P1_TSCFGH, 0xe0 },
+	{ R0900_P2_TSCFGH, 0xe0 },
+	{ R0900_P1_TSCFGL, 0x20 },
+	{ R0900_P2_TSCFGL, 0x20 },
+	{ 0xffff, 0xff }, /* terminate */
+};
+
 static struct stv0900_config netup_stv0900_config = {
 	.demod_address = 0x68,
 	.xtal = 27000000,
 	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
 	.diseqc_mode = 2,/* 2/3 PWM */
-	.path1_mode = 2,/*Serial continues clock */
-	.path2_mode = 2,/*Serial continues clock */
+	.ts_config_regs = stv0900_ts_regs,
 	.tun1_maddress = 0,/* 0x60 */
 	.tun2_maddress = 3,/* 0x63 */
 	.tun1_adc = 1,/* 1 Vpp */
@@ -368,10 +444,53 @@
 	.demod_address = 0x05,
 };
 
+static struct lgs8gxx_config mygica_x8506_lgs8gl5_config = {
+	.prod = LGS8GXX_PROD_LGS8GL5,
+	.demod_address = 0x19,
+	.serial_ts = 0,
+	.ts_clk_pol = 1,
+	.ts_clk_gated = 1,
+	.if_clk_freq = 30400, /* 30.4 MHz */
+	.if_freq = 5380, /* 5.38 MHz */
+	.if_neg_center = 1,
+	.ext_adc = 0,
+	.adc_signed = 0,
+	.if_neg_edge = 0,
+};
+
+static struct xc5000_config mygica_x8506_xc5000_config = {
+	.i2c_address = 0x61,
+	.if_khz = 5380,
+};
+
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe,
+				    struct dvb_frontend_parameters *param)
+{
+	struct cx23885_tsport *port = fe->dvb->priv;
+	struct cx23885_dev *dev = port->dev;
+
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+		switch (param->u.vsb.modulation) {
+		case VSB_8:
+			cx23885_gpio_clear(dev, GPIO_5);
+			break;
+		case QAM_64:
+		case QAM_256:
+		default:
+			cx23885_gpio_set(dev, GPIO_5);
+			break;
+		}
+		break;
+	}
+	return (port->set_frontend_save) ?
+		port->set_frontend_save(fe, param) : -ENODEV;
+}
+
 static int dvb_register(struct cx23885_tsport *port)
 {
 	struct cx23885_dev *dev = port->dev;
-	struct cx23885_i2c *i2c_bus = NULL;
+	struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
 	struct videobuf_dvb_frontend *fe0;
 	int ret;
 
@@ -396,6 +515,35 @@
 				   &hauppauge_generic_tunerconfig, 0);
 		}
 		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
+					       &hauppauge_lgdt3305_config,
+					       &i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_bus[1].i2c_adap,
+				   &hauppauge_hvr127x_config);
+		}
+
+		/* FIXME: temporary hack */
+		/* define bridge override to set_frontend */
+		port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend;
+		fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend;
+
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+					       &hcw_s5h1411_config,
+					       &i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_bus[1].i2c_adap,
+				   &hauppauge_tda18271_config);
+		}
+		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1800:
 		i2c_bus = &dev->i2c_bus[0];
 		switch (alt_tuner) {
@@ -496,6 +644,17 @@
 				&hauppauge_hvr1200_tuner_config);
 		}
 		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(tda10048_attach,
+			&hauppauge_hvr1210_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[1].i2c_adap,
+				&hauppauge_hvr1210_tuner_config);
+		}
+		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
 		i2c_bus = &dev->i2c_bus[0];
 		fe0->dvb.frontend = dvb_attach(dib7000p_attach,
@@ -630,7 +789,8 @@
 					if (!dvb_attach(lnbh24_attach,
 							fe0->dvb.frontend,
 							&i2c_bus->i2c_adap,
-							LNBH24_PCL, 0, 0x09))
+							LNBH24_PCL,
+							LNBH24_TTX, 0x09))
 						printk(KERN_ERR
 							"No LNBH24 found!\n");
 
@@ -650,7 +810,8 @@
 					if (!dvb_attach(lnbh24_attach,
 							fe0->dvb.frontend,
 							&i2c_bus->i2c_adap,
-							LNBH24_PCL, 0, 0x0a))
+							LNBH24_PCL,
+							LNBH24_TTX, 0x0a))
 						printk(KERN_ERR
 							"No LNBH24 found!\n");
 
@@ -659,6 +820,19 @@
 			break;
 		}
 		break;
+	case CX23885_BOARD_MYGICA_X8506:
+		i2c_bus = &dev->i2c_bus[0];
+		i2c_bus2 = &dev->i2c_bus[1];
+		fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
+			&mygica_x8506_lgs8gl5_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(xc5000_attach,
+				fe0->dvb.frontend,
+				&i2c_bus2->i2c_adap,
+				&mygica_x8506_xc5000_config);
+		}
+		break;
 	default:
 		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
 			" isn't supported yet\n",
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885.h linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885.h
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885.h	2009-09-09 18:13:59.000000000 -0400
@@ -71,6 +71,22 @@
 #define CX23885_BOARD_TEVII_S470               15
 #define CX23885_BOARD_DVBWORLD_2005            16
 #define CX23885_BOARD_NETUP_DUAL_DVBS2_CI      17
+#define CX23885_BOARD_HAUPPAUGE_HVR1270        18
+#define CX23885_BOARD_HAUPPAUGE_HVR1275        19
+#define CX23885_BOARD_HAUPPAUGE_HVR1255        20
+#define CX23885_BOARD_HAUPPAUGE_HVR1210        21
+#define CX23885_BOARD_MYGICA_X8506             22
+
+#define GPIO_0 0x00000001
+#define GPIO_1 0x00000002
+#define GPIO_2 0x00000004
+#define GPIO_3 0x00000008
+#define GPIO_4 0x00000010
+#define GPIO_5 0x00000020
+#define GPIO_6 0x00000040
+#define GPIO_7 0x00000080
+#define GPIO_8 0x00000100
+#define GPIO_9 0x00000200
 
 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
 #define CX23885_NORMS (\
@@ -272,6 +288,10 @@
 	/* Allow a single tsport to have multiple frontends */
 	u32                        num_frontends;
 	void                       *port_priv;
+
+	/* FIXME: temporary hack */
+	int (*set_frontend_save) (struct dvb_frontend *,
+				  struct dvb_frontend_parameters *);
 };
 
 struct cx23885_dev {
@@ -422,6 +442,11 @@
 extern void cx23885_wakeup(struct cx23885_tsport *port,
 			   struct cx23885_dmaqueue *q, u32 count);
 
+extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
+	int asoutput);
+
 
 /* ----------------------------------------------------------- */
 /* cx23885-cards.c                                             */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -357,6 +357,18 @@
 		printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
 			dev->name, bus->nr);
 
+	/* Instantiate the IR receiver device, if present */
+	if (0 == bus->i2c_rc) {
+		struct i2c_board_info info;
+		const unsigned short addr_list[] = {
+			0x6b, I2C_CLIENT_END
+		};
+
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+		i2c_new_probed_device(&bus->i2c_adap, &info, addr_list);
+	}
+
 	return bus->i2c_rc;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-video.c linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx23885/cx23885-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx23885/cx23885-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/kmod.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
@@ -796,6 +797,7 @@
 {
 	struct cx23885_fh *fh = file->private_data;
 	struct cx23885_buffer *buf;
+	unsigned int rc = POLLERR;
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
 		if (!res_get(fh->dev, fh, RESOURCE_VBI))
@@ -803,23 +805,28 @@
 		return videobuf_poll_stream(file, &fh->vbiq, wait);
 	}
 
+	mutex_lock(&fh->vidq.vb_lock);
 	if (res_check(fh, RESOURCE_VIDEO)) {
 		/* streaming capture */
 		if (list_empty(&fh->vidq.stream))
-			return POLLERR;
+			goto done;
 		buf = list_entry(fh->vidq.stream.next,
 			struct cx23885_buffer, vb.stream);
 	} else {
 		/* read() capture */
 		buf = (struct cx23885_buffer *)fh->vidq.read_buf;
 		if (NULL == buf)
-			return POLLERR;
+			goto done;
 	}
 	poll_wait(file, &buf->vb.done, wait);
 	if (buf->vb.state == VIDEOBUF_DONE ||
 	    buf->vb.state == VIDEOBUF_ERROR)
-		return POLLIN|POLLRDNORM;
-	return 0;
+		rc =  POLLIN|POLLRDNORM;
+	else
+		rc = 0;
+done:
+	mutex_unlock(&fh->vidq.vb_lock);
+	return rc;
 }
 
 static int video_release(struct file *file)
@@ -957,15 +964,8 @@
 	}
 
 	f->fmt.pix.field = field;
-	if (f->fmt.pix.height < 32)
-		f->fmt.pix.height = 32;
-	if (f->fmt.pix.height > maxh)
-		f->fmt.pix.height = maxh;
-	if (f->fmt.pix.width < 48)
-		f->fmt.pix.width = 48;
-	if (f->fmt.pix.width > maxw)
-		f->fmt.pix.width = maxw;
-	f->fmt.pix.width &= ~0x03;
+	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+			      &f->fmt.pix.height, 32, maxh, 0, 0);
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-alsa.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-alsa.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-alsa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-alsa.c	2009-09-09 18:13:59.000000000 -0400
@@ -871,7 +871,7 @@
 	.name     = "cx88_audio",
 	.id_table = cx88_audio_pci_tbl,
 	.probe    = cx88_audio_initdev,
-	.remove   = cx88_audio_finidev,
+	.remove   = __devexit_p(cx88_audio_finidev),
 };
 
 /****************************************************************************
@@ -881,7 +881,7 @@
 /*
  * module init
  */
-static int cx88_audio_init(void)
+static int __init cx88_audio_init(void)
 {
 	printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n",
 	       (CX88_VERSION_CODE >> 16) & 0xff,
@@ -897,9 +897,8 @@
 /*
  * module remove
  */
-static void cx88_audio_fini(void)
+static void __exit cx88_audio_fini(void)
 {
-
 	pci_unregister_driver(&cx88_audio_pci_driver);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-blackbird.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-blackbird.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-blackbird.c	2012-03-22 19:13:38.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-blackbird.c	2012-03-22 20:09:51.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/smp_lock.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-cards.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-cards.c	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-cards.c	2012-03-22 20:08:07.000000000 -0400
@@ -1524,33 +1524,45 @@
 		},
 		.mpeg           = CX88_MPEG_DVB,
 	},
+	/* Terry Wu <terrywu2009@gmail.com> */
+	/* TV Audio :      set GPIO 2, 18, 19 value to 0, 1, 0 */
+	/* FM Audio :      set GPIO 2, 18, 19 value to 0, 0, 0 */
+	/* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */
+	/* Mute Audio :    set GPIO 2 value to 1               */
 	[CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
-		.name           = "Winfast TV2000 XP Global",
+		.name           = "Leadtek TV2000 XP Global",
 		.tuner_type     = TUNER_XC2028,
 		.tuner_addr     = 0x61,
+		.radio_type     = TUNER_XC2028,
+		.radio_addr     = 0x61,
 		.input          = { {
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
-			.gpio0  = 0x0400, /* pin 2:mute = 0 (off?) */
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
 			.gpio1  = 0x0000,
-			.gpio2  = 0x0800, /* pin 19:audio = 0 (tv) */
-
+			.gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
+			.gpio3  = 0x0000,
 		}, {
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
-			.gpio0  = 0x0400, /* probably?  or 0x0404 to turn mute on */
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
 			.gpio1  = 0x0000,
-			.gpio2  = 0x0808, /* pin 19:audio = 1 (line) */
-
+			.gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+			.gpio3  = 0x0000,
 		}, {
 			.type   = CX88_VMUX_SVIDEO,
 			.vmux   = 2,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+			.gpio3  = 0x0000,
 		} },
 		.radio = {
 			.type   = CX88_RADIO,
-			.gpio0  = 0x004ff,
-			.gpio1  = 0x010ff,
-			.gpio2  = 0x0ff,
+			.gpio0  = 0x0400,        /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
+			.gpio3  = 0x0000,
 		},
 	},
 	[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
@@ -1969,6 +1981,54 @@
 		},
 		.mpeg           = CX88_MPEG_DVB,
 	},
+	[CX88_BOARD_HAUPPAUGE_IRONLY] = {
+		.name           = "Hauppauge WinTV-IR Only",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+	},
+	[CX88_BOARD_WINFAST_DTV1800H] = {
+		.name           = "Leadtek WinFast DTV1800 Hybrid",
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.radio_addr     = 0x61,
+		/*
+		 * GPIO setting
+		 *
+		 *  2: mute (0=off,1=on)
+		 * 12: tuner reset pin
+		 * 13: audio source (0=tuner audio,1=line in)
+		 * 14: FM (0=on,1=off ???)
+		 */
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6040,       /* pin 13 = 0, pin 14 = 1 */
+			.gpio2  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+			.gpio2  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+			.gpio2  = 0x0000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6000,       /* pin 13 = 0, pin 14 = 0 */
+			.gpio2  = 0x0000,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
 };
 
 /* ------------------------------------------------------------------ */
@@ -2382,6 +2442,49 @@
 		.subvendor = 0x153b,
 		.subdevice = 0x1177,
 		.card      = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x9290,
+		.card      = CX88_BOARD_HAUPPAUGE_IRONLY,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6654,
+		.card      = CX88_BOARD_WINFAST_DTV1800H,
+	}, {
+		/* PVR2000 PAL Model [107d:6630] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6630,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 PAL Model [107d:6638] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6638,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 NTSC Model [107d:6631] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6631,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 NTSC Model [107d:6637] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6637,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 NTSC Model [107d:663d] */
+		.subvendor = 0x107d,
+		.subdevice = 0x663d,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* DV2000 NTSC Model [107d:6621] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6621,
+		.card      = CX88_BOARD_WINFAST_DV2000,
+	}, {
+		/* TV2000 XP Global [107d:6618]  */
+		.subvendor = 0x107d,
+		.subdevice = 0x6618,
+		.card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
 	},
 };
 
@@ -2390,12 +2493,6 @@
 
 static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
 {
-	/* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on
-	 * any others.
-	 *
-	 * Byte 0 is 1 on the NTSC board.
-	 */
-
 	if (eeprom_data[4] != 0x7d ||
 	    eeprom_data[5] != 0x10 ||
 	    eeprom_data[7] != 0x66) {
@@ -2403,8 +2500,19 @@
 		return;
 	}
 
-	core->board.tuner_type = (eeprom_data[6] == 0x13) ?
-		TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
+	/* Terry Wu <terrywu2009@gmail.com> */
+	switch (eeprom_data[6]) {
+	case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */
+	case 0x21: /* SSID 6621 for DV2000 NTSC Model */
+	case 0x31: /* SSID 6631 for PVR2000 NTSC Model */
+	case 0x37: /* SSID 6637 for PVR2000 NTSC Model */
+	case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */
+		core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3;
+		break;
+	default:
+		core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+		break;
+	}
 
 	info_printk(core, "Leadtek Winfast 2000XP Expert config: "
 		    "tuner=%d, eeprom[0]=0x%02x\n",
@@ -2448,6 +2556,7 @@
 	case 90500: /* Nova-T-PCI (oem) */
 	case 90501: /* Nova-T-PCI (oem/IR) */
 	case 92000: /* Nova-SE2 (OEM, No Video or IR) */
+	case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */
 	case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
 	case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
 	case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
@@ -2579,6 +2688,23 @@
 	return -EINVAL;
 }
 
+static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
+					     int command, int arg)
+{
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		/* GPIO 12 (xc3028 tuner reset) */
+		cx_set(MO_GP1_IO, 0x1010);
+		mdelay(50);
+		cx_clear(MO_GP1_IO, 0x10);
+		mdelay(50);
+		cx_set(MO_GP1_IO, 0x10);
+		mdelay(50);
+		return 0;
+	}
+	return -EINVAL;
+}
+
 /* ------------------------------------------------------------------- */
 /* some Divco specific stuff                                           */
 static int cx88_pv_8000gt_callback(struct cx88_core *core,
@@ -2639,7 +2765,6 @@
 {
 	/* Board-specific callbacks */
 	switch (core->boardnr) {
-	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
 	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
 	case CX88_BOARD_GENIATECH_X8000_MT:
 	case CX88_BOARD_KWORLD_ATSC_120:
@@ -2651,6 +2776,9 @@
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
 	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
 		return cx88_dvico_xc2028_callback(core, command, arg);
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+	case CX88_BOARD_WINFAST_DTV1800H:
+		return cx88_xc3028_winfast1800h_callback(core, command, arg);
 	}
 
 	switch (command) {
@@ -2690,10 +2818,22 @@
 	switch (core->boardnr) {
 	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
 		if (command == 0) { /* This is the reset command from xc5000 */
-			/* Reset XC5000 tuner via SYS_RSTO_pin */
-			cx_write(MO_SRST_IO, 0);
-			msleep(10);
-			cx_write(MO_SRST_IO, 1);
+
+			/* djh - According to the engineer at PCTV Systems,
+			   the xc5000 reset pin is supposed to be on GPIO12.
+			   However, despite three nights of effort, pulling
+			   that GPIO low didn't reset the xc5000.  While
+			   pulling MO_SRST_IO low does reset the xc5000, this
+			   also resets in the s5h1409 being reset as well.
+			   This causes tuning to always fail since the internal
+			   state of the s5h1409 does not match the driver's
+			   state.  Given that the only two conditions in which
+			   the driver performs a reset is during firmware load
+			   and powering down the chip, I am taking out the
+			   reset.  We know that the chip is being reset
+			   when the cx88 comes online, and not being able to
+			   do power management for this board is worse than
+			   not having any tuning at all. */
 			return 0;
 		} else {
 			err_printk(core, "xc5000: unknown tuner "
@@ -2825,6 +2965,17 @@
 		cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
 		udelay(1000);
 		break;
+
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+	case CX88_BOARD_WINFAST_DTV1800H:
+		/* GPIO 12 (xc3028 tuner reset) */
+		cx_set(MO_GP1_IO, 0x1010);
+		mdelay(50);
+		cx_clear(MO_GP1_IO, 0x10);
+		mdelay(50);
+		cx_set(MO_GP1_IO, 0x10);
+		mdelay(50);
+		break;
 	}
 }
 
@@ -2845,12 +2996,22 @@
 			core->i2c_algo.udelay = 16;
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+	case CX88_BOARD_WINFAST_DTV1800H:
 		ctl->demod = XC3028_FE_ZARLINK456;
 		break;
 	case CX88_BOARD_KWORLD_ATSC_120:
 	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
 		ctl->demod = XC3028_FE_OREN538;
 		break;
+	case CX88_BOARD_GENIATECH_X8000_MT:
+		/* FIXME: For this board, the xc3028 never recovers after being
+		   powered down (the reset GPIO probably is not set properly).
+		   We don't have access to the hardware so we cannot determine
+		   which GPIO is used for xc3028, so just disable power xc3028
+		   power management for now */
+		ctl->disable_power_mgmt = 1;
+		break;
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
 	case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
 	case CX88_BOARD_PROLINK_PV_8000GT:
 		/*
@@ -2894,6 +3055,8 @@
 		if (0 == core->i2c_rc)
 			gdi_eeprom(core, eeprom);
 		break;
+	case CX88_BOARD_LEADTEK_PVR2000:
+	case CX88_BOARD_WINFAST_DV2000:
 	case CX88_BOARD_WINFAST2000XP_EXPERT:
 		if (0 == core->i2c_rc)
 			leadtek_eeprom(core, eeprom);
@@ -2907,6 +3070,7 @@
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 	case CX88_BOARD_HAUPPAUGE_HVR4000:
 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+	case CX88_BOARD_HAUPPAUGE_IRONLY:
 		if (0 == core->i2c_rc)
 			hauppauge_eeprom(core, eeprom);
 		break;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-core.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -231,7 +231,7 @@
  * can use the whole SDRAM for the DMA fifos.  To simplify things, we
  * use a static memory layout.  That surely will waste memory in case
  * we don't use all DMA channels at the same time (which will be the
- * case most of the time).  But that still gives us enougth FIFO space
+ * case most of the time).  But that still gives us enough FIFO space
  * to be able to deal with insane long pci latencies ...
  *
  * FIFO space allocations:
@@ -241,6 +241,7 @@
  *    channel  24    (vbi)      -  4.0k
  *    channels 25+26 (audio)    -  4.0k
  *    channel  28    (mpeg)     -  4.0k
+ *    channel  27    (audio rds)-  3.0k
  *    TOTAL                     = 29.0k
  *
  * Every channel has 160 bytes control data (64 bytes instruction
@@ -337,6 +338,18 @@
 		.cnt1_reg   = MO_DMA28_CNT1,
 		.cnt2_reg   = MO_DMA28_CNT2,
 	},
+	[SRAM_CH27] = {
+		.name       = "audio rds",
+		.cmds_start = 0x1801C0,
+		.ctrl_start = 0x180860,
+		.cdt        = 0x180860 + 64,
+		.fifo_start = 0x187400,
+		.fifo_size  = 0x000C00,
+		.ptr1_reg   = MO_DMA27_PTR1,
+		.ptr2_reg   = MO_DMA27_PTR2,
+		.cnt1_reg   = MO_DMA27_CNT1,
+		.cnt2_reg   = MO_DMA27_CNT2,
+	},
 };
 
 int cx88_sram_channel_setup(struct cx88_core *core,
@@ -598,6 +611,7 @@
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
 
 	/* misc init ... */
 	cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable
@@ -796,6 +810,8 @@
 	/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
 	int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
 
+	int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
+
 	/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
 	if (cx_read(MO_AUD_DMACNTRL) & 0x10)
 		return 0;
@@ -803,12 +819,14 @@
 	/* setup fifo + format */
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
+				rds_bpl, 0);
 
 	cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
-	cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
+	cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
 
-	/* start dma */
-	cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
+	/* enable Up, Down and Audio RDS fifo */
+	cx_write(MO_AUD_DMACNTRL, 0x0007);
 
 	return 0;
 }
@@ -1010,7 +1028,6 @@
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor   = -1;
 	vfd->v4l2_dev = &core->v4l2_dev;
 	vfd->parent = &pci->dev;
 	vfd->release = video_device_release;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-dsp.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-dsp.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-dsp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-dsp.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,312 @@
+/*
+ *
+ *  Stereo and SAP detection for cx88
+ *
+ *  Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
+ *
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define INT_PI			((s32)(3.141592653589 * 32768.0))
+
+#define compat_remainder(a, b) \
+	 ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0)
+
+#define baseband_freq(carrier, srate, tone) ((s32)( \
+	 (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
+
+/* We calculate the baseband frequencies of the carrier and the pilot tones
+ * based on the the sampling rate of the audio rds fifo. */
+
+#define FREQ_A2_CARRIER         baseband_freq(54687.5, 2689.36, 0.0)
+#define FREQ_A2_DUAL            baseband_freq(54687.5, 2689.36, 274.1)
+#define FREQ_A2_STEREO          baseband_freq(54687.5, 2689.36, 117.5)
+
+/* The frequencies below are from the reference driver. They probably need
+ * further adjustments, because they are not tested at all. You may even need
+ * to play a bit with the registers of the chip to select the proper signal
+ * for the input of the audio rds fifo, and measure it's sampling rate to
+ * calculate the proper baseband frequencies... */
+
+#define FREQ_A2M_CARRIER	((s32)(2.114516 * 32768.0))
+#define FREQ_A2M_DUAL		((s32)(2.754916 * 32768.0))
+#define FREQ_A2M_STEREO		((s32)(2.462326 * 32768.0))
+
+#define FREQ_EIAJ_CARRIER	((s32)(1.963495 * 32768.0)) /* 5pi/8  */
+#define FREQ_EIAJ_DUAL		((s32)(2.562118 * 32768.0))
+#define FREQ_EIAJ_STEREO	((s32)(2.601053 * 32768.0))
+
+#define FREQ_BTSC_DUAL		((s32)(1.963495 * 32768.0)) /* 5pi/8  */
+#define FREQ_BTSC_DUAL_REF	((s32)(1.374446 * 32768.0)) /* 7pi/16 */
+
+#define FREQ_BTSC_SAP		((s32)(2.471532 * 32768.0))
+#define FREQ_BTSC_SAP_REF	((s32)(1.730072 * 32768.0))
+
+/* The spectrum of the signal should be empty between these frequencies. */
+#define FREQ_NOISE_START	((s32)(0.100000 * 32768.0))
+#define FREQ_NOISE_END		((s32)(1.200000 * 32768.0))
+
+static unsigned int dsp_debug;
+module_param(dsp_debug, int, 0644);
+MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages");
+
+#define dprintk(level, fmt, arg...)	if (dsp_debug >= level) \
+	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+static s32 int_cos(u32 x)
+{
+	u32 t2, t4, t6, t8;
+	s32 ret;
+	u16 period = x / INT_PI;
+	if (period % 2)
+		return -int_cos(x - INT_PI);
+	x = x % INT_PI;
+	if (x > INT_PI/2)
+		return -int_cos(INT_PI/2 - (x % (INT_PI/2)));
+	/* Now x is between 0 and INT_PI/2.
+	 * To calculate cos(x) we use it's Taylor polinom. */
+	t2 = x*x/32768/2;
+	t4 = t2*x/32768*x/32768/3/4;
+	t6 = t4*x/32768*x/32768/5/6;
+	t8 = t6*x/32768*x/32768/7/8;
+	ret = 32768-t2+t4-t6+t8;
+	return ret;
+}
+
+static u32 int_goertzel(s16 x[], u32 N, u32 freq)
+{
+	/* We use the Goertzel algorithm to determine the power of the
+	 * given frequency in the signal */
+	s32 s_prev = 0;
+	s32 s_prev2 = 0;
+	s32 coeff = 2*int_cos(freq);
+	u32 i;
+
+	u64 tmp;
+	u32 divisor;
+
+	for (i = 0; i < N; i++) {
+		s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2;
+		s_prev2 = s_prev;
+		s_prev = s;
+	}
+
+	tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev -
+		      (s64)coeff * s_prev2 * s_prev / 32768;
+
+	/* XXX: N must be low enough so that N*N fits in s32.
+	 * Else we need two divisions. */
+	divisor = N * N;
+	do_div(tmp, divisor);
+
+	return (u32) tmp;
+}
+
+static u32 freq_magnitude(s16 x[], u32 N, u32 freq)
+{
+	u32 sum = int_goertzel(x, N, freq);
+	return (u32)int_sqrt(sum);
+}
+
+static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end)
+{
+	int i;
+	u32 sum = 0;
+	u32 freq_step;
+	int samples = 5;
+
+	if (N > 192) {
+		/* The last 192 samples are enough for noise detection */
+		x += (N-192);
+		N = 192;
+	}
+
+	freq_step = (freq_end - freq_start) / (samples - 1);
+
+	for (i = 0; i < samples; i++) {
+		sum += int_goertzel(x, N, freq_start);
+		freq_start += freq_step;
+	}
+
+	return (u32)int_sqrt(sum / samples);
+}
+
+static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N)
+{
+	s32 carrier, stereo, dual, noise;
+	s32 carrier_freq, stereo_freq, dual_freq;
+	s32 ret;
+
+	switch (core->tvaudio) {
+	case WW_BG:
+	case WW_DK:
+		carrier_freq = FREQ_A2_CARRIER;
+		stereo_freq = FREQ_A2_STEREO;
+		dual_freq = FREQ_A2_DUAL;
+		break;
+	case WW_M:
+		carrier_freq = FREQ_A2M_CARRIER;
+		stereo_freq = FREQ_A2M_STEREO;
+		dual_freq = FREQ_A2M_DUAL;
+		break;
+	case WW_EIAJ:
+		carrier_freq = FREQ_EIAJ_CARRIER;
+		stereo_freq = FREQ_EIAJ_STEREO;
+		dual_freq = FREQ_EIAJ_DUAL;
+		break;
+	default:
+		printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
+		       core->name, core->tvaudio, __func__);
+		return UNSET;
+	}
+
+	carrier = freq_magnitude(x, N, carrier_freq);
+	stereo  = freq_magnitude(x, N, stereo_freq);
+	dual    = freq_magnitude(x, N, dual_freq);
+	noise   = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);
+
+	dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
+		   "noise=%d\n", carrier, stereo, dual, noise);
+
+	if (stereo > dual)
+		ret = V4L2_TUNER_SUB_STEREO;
+	else
+		ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+	if (core->tvaudio == WW_EIAJ) {
+		/* EIAJ checks may need adjustments */
+		if ((carrier > max(stereo, dual)*2) &&
+		    (carrier < max(stereo, dual)*6) &&
+		    (carrier > 20 && carrier < 200) &&
+		    (max(stereo, dual) > min(stereo, dual))) {
+			/* For EIAJ the carrier is always present,
+			   so we probably don't need noise detection */
+			return ret;
+		}
+	} else {
+		if ((carrier > max(stereo, dual)*2) &&
+		    (carrier < max(stereo, dual)*8) &&
+		    (carrier > 20 && carrier < 200) &&
+		    (noise < 10) &&
+		    (max(stereo, dual) > min(stereo, dual)*2)) {
+			return ret;
+		}
+	}
+	return V4L2_TUNER_SUB_MONO;
+}
+
+static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N)
+{
+	s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF);
+	s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP);
+	s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF);
+	s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL);
+	dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d"
+		   "\n", dual_ref, dual, sap_ref, sap);
+	/* FIXME: Currently not supported */
+	return UNSET;
+}
+
+static s16 *read_rds_samples(struct cx88_core *core, u32 *N)
+{
+	struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27];
+	s16 *samples;
+
+	unsigned int i;
+	unsigned int bpl = srch->fifo_size/AUD_RDS_LINES;
+	unsigned int spl = bpl/4;
+	unsigned int sample_count = spl*(AUD_RDS_LINES-1);
+
+	u32 current_address = cx_read(srch->ptr1_reg);
+	u32 offset = (current_address - srch->fifo_start + bpl);
+
+	dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), "
+		"sample_count=%d, aud_intstat=%08x\n", current_address,
+		current_address - srch->fifo_start, sample_count,
+		cx_read(MO_AUD_INTSTAT));
+
+	samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL);
+	if (!samples)
+		return NULL;
+
+	*N = sample_count;
+
+	for (i = 0; i < sample_count; i++)  {
+		offset = offset % (AUD_RDS_LINES*bpl);
+		samples[i] = cx_read(srch->fifo_start + offset);
+		offset += 4;
+	}
+
+	if (dsp_debug >= 2) {
+		dprintk(2, "RDS samples dump: ");
+		for (i = 0; i < sample_count; i++)
+			printk("%hd ", samples[i]);
+		printk(".\n");
+	}
+
+	return samples;
+}
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core)
+{
+	s16 *samples;
+	u32 N = 0;
+	s32 ret = UNSET;
+
+	/* If audio RDS fifo is disabled, we can't read the samples */
+	if (!(cx_read(MO_AUD_DMACNTRL) & 0x04))
+		return ret;
+	if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS))
+		return ret;
+
+	/* Wait at least 500 ms after an audio standard change */
+	if (time_before(jiffies, core->last_change + msecs_to_jiffies(500)))
+		return ret;
+
+	samples = read_rds_samples(core, &N);
+
+	if (!samples)
+		return ret;
+
+	switch (core->tvaudio) {
+	case WW_BG:
+	case WW_DK:
+		ret = detect_a2_a2m_eiaj(core, samples, N);
+		break;
+	case WW_BTSC:
+		ret = detect_btsc(core, samples, N);
+		break;
+	}
+
+	kfree(samples);
+
+	if (UNSET != ret)
+		dprintk(1, "stereo/sap detection result:%s%s%s\n",
+			   (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
+			   (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
+			   (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
+
+	return ret;
+}
+EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap);
+
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-dvb.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-dvb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-dvb.c	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-dvb.c	2012-03-22 20:08:07.000000000 -0400
@@ -501,6 +501,7 @@
 static struct zl10353_config cx88_geniatech_x8000_mt = {
        .demod_address = (0x1e >> 1),
        .no_tuner = 1,
+       .disable_i2c_gate_ctrl = 1,
 };
 
 static struct s5h1411_config dvico_fusionhdtv7_config = {
@@ -1014,6 +1015,7 @@
 		}
 		break;
 	 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+	case CX88_BOARD_WINFAST_DTV1800H:
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &cx88_pinnacle_hybrid_pctv,
 					       &core->i2c_adap);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88.h linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88.h
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88.h	2009-09-09 18:13:59.000000000 -0400
@@ -65,6 +65,8 @@
 #define VBI_LINE_COUNT              17
 #define VBI_LINE_LENGTH           2048
 
+#define AUD_RDS_LINES		     4
+
 /* need "shadow" registers for some write-only ones ... */
 #define SHADOW_AUD_VOL_CTL           1
 #define SHADOW_AUD_BAL_CTL           2
@@ -132,6 +134,7 @@
 #define SRAM_CH25 4   /* audio */
 #define SRAM_CH26 5
 #define SRAM_CH28 6   /* mpeg */
+#define SRAM_CH27 7   /* audio rds */
 /* more */
 
 struct sram_channel {
@@ -232,6 +235,8 @@
 #define CX88_BOARD_TBS_8910                77
 #define CX88_BOARD_PROF_6200               78
 #define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
+#define CX88_BOARD_HAUPPAUGE_IRONLY        80
+#define CX88_BOARD_WINFAST_DTV1800H        81
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
@@ -350,6 +355,7 @@
 	u32                        input;
 	u32                        astat;
 	u32			   use_nicam;
+	unsigned long		   last_change;
 
 	/* IR remote control state */
 	struct cx88_IR             *ir;
@@ -652,6 +658,7 @@
 #define WW_I2SPT	 8
 #define WW_FM		 9
 #define WW_I2SADC	 10
+#define WW_M		 11
 
 void cx88_set_tvaudio(struct cx88_core *core);
 void cx88_newstation(struct cx88_core *core);
@@ -665,6 +672,11 @@
 struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
 
 /* ----------------------------------------------------------- */
+/* cx88-dsp.c                                                  */
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
 /* cx88-input.c                                                */
 
 int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -180,6 +180,19 @@
 			do_i2c_scan(core->name,&core->i2c_client);
 	} else
 		printk("%s: i2c register FAILED\n", core->name);
+
+	/* Instantiate the IR receiver device, if present */
+	if (0 == core->i2c_rc) {
+		struct i2c_board_info info;
+		const unsigned short addr_list[] = {
+			0x18, 0x6b, 0x71,
+			I2C_CLIENT_END
+		};
+
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+		i2c_new_probed_device(&core->i2c_adap, &info, addr_list);
+	}
 	return core->i2c_rc;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-input.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-input.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-input.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-input.c	2009-09-09 18:13:59.000000000 -0400
@@ -91,6 +91,8 @@
 		gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
 		break;
 	case CX88_BOARD_WINFAST_DTV1000:
+	case CX88_BOARD_WINFAST_DTV1800H:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
 		gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
 		auxgpio = gpio;
 		break;
@@ -217,11 +219,13 @@
 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
 	case CX88_BOARD_PCHDTV_HD3000:
 	case CX88_BOARD_PCHDTV_HD5500:
+	case CX88_BOARD_HAUPPAUGE_IRONLY:
 		ir_codes = ir_codes_hauppauge_new;
 		ir_type = IR_TYPE_RC5;
 		ir->sampling = 1;
 		break;
 	case CX88_BOARD_WINFAST_DTV2000H:
+	case CX88_BOARD_WINFAST_DTV1800H:
 		ir_codes = ir_codes_winfast;
 		ir->gpio_addr = MO_GP0_IO;
 		ir->mask_keycode = 0x8f8;
@@ -230,6 +234,7 @@
 		break;
 	case CX88_BOARD_WINFAST2000XP_EXPERT:
 	case CX88_BOARD_WINFAST_DTV1000:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
 		ir_codes = ir_codes_winfast;
 		ir->gpio_addr = MO_GP0_IO;
 		ir->mask_keycode = 0x8f8;
@@ -459,6 +464,7 @@
 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
 	case CX88_BOARD_PCHDTV_HD3000:
 	case CX88_BOARD_PCHDTV_HD5500:
+	case CX88_BOARD_HAUPPAUGE_IRONLY:
 		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
 		ir_dprintk("biphase decoded: %x\n", ircode);
 		/*
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-mpeg.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-mpeg.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-mpeg.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-mpeg.c	2009-09-09 18:13:59.000000000 -0400
@@ -116,6 +116,10 @@
 			udelay(100);
 			break;
 		case CX88_BOARD_HAUPPAUGE_HVR1300:
+			/* Enable MPEG parallel IO and video signal pins */
+			cx_write(MO_PINMUX_IO, 0x88);
+			cx_write(TS_SOP_STAT, 0);
+			cx_write(TS_VALERR_CNTRL, 0);
 			break;
 		case CX88_BOARD_PINNACLE_PCTV_HD_800i:
 			/* Enable MPEG parallel IO and video signal pins */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-tvaudio.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-tvaudio.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-tvaudio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-tvaudio.c	2009-09-09 18:13:59.000000000 -0400
@@ -163,6 +163,8 @@
 	/* unmute */
 	volume = cx_sread(SHADOW_AUD_VOL_CTL);
 	cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
+
+	core->last_change = jiffies;
 }
 
 /* ----------------------------------------------------------- */
@@ -745,6 +747,7 @@
 		break;
 	case WW_BG:
 	case WW_DK:
+	case WW_M:
 	case WW_I:
 	case WW_L:
 		/* prepare all dsp registers */
@@ -756,6 +759,7 @@
 		if (0 == cx88_detect_nicam(core)) {
 			/* fall back to fm / am mono */
 			set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+			core->audiomode_current = V4L2_TUNER_MODE_MONO;
 			core->use_nicam = 0;
 		} else {
 			core->use_nicam = 1;
@@ -787,6 +791,7 @@
 void cx88_newstation(struct cx88_core *core)
 {
 	core->audiomode_manual = UNSET;
+	core->last_change = jiffies;
 }
 
 void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
@@ -805,12 +810,50 @@
 			aud_ctl_names[cx_read(AUD_CTL) & 63]);
 	core->astat = reg;
 
-/* TODO
-	Reading from AUD_STATUS is not enough
-	for auto-detecting sap/dual-fm/nicam.
-	Add some code here later.
-*/
+	t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
+	    V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+	t->rxsubchans = UNSET;
+	t->audmode = V4L2_TUNER_MODE_MONO;
 
+	switch (mode) {
+	case 0:
+		t->audmode = V4L2_TUNER_MODE_STEREO;
+		break;
+	case 1:
+		t->audmode = V4L2_TUNER_MODE_LANG2;
+		break;
+	case 2:
+		t->audmode = V4L2_TUNER_MODE_MONO;
+		break;
+	case 3:
+		t->audmode = V4L2_TUNER_MODE_SAP;
+		break;
+	}
+
+	switch (core->tvaudio) {
+	case WW_BTSC:
+	case WW_BG:
+	case WW_DK:
+	case WW_M:
+	case WW_EIAJ:
+		if (!core->use_nicam) {
+			t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
+			break;
+		}
+		break;
+	default:
+		/* nothing */
+		break;
+	}
+
+	/* If software stereo detection is not supported... */
+	if (UNSET == t->rxsubchans) {
+		t->rxsubchans = V4L2_TUNER_SUB_MONO;
+		/* If the hardware itself detected stereo, also return
+		   stereo as an available subchannel */
+		if (V4L2_TUNER_MODE_STEREO == t->audmode)
+			t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+	}
 	return;
 }
 
@@ -847,6 +890,7 @@
 		break;
 	case WW_BG:
 	case WW_DK:
+	case WW_M:
 	case WW_I:
 	case WW_L:
 		if (1 == core->use_nicam) {
@@ -872,20 +916,18 @@
 				set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
 			} else {
 				/* TODO: Add A2 autodection */
+				mask = 0x3f;
 				switch (mode) {
 				case V4L2_TUNER_MODE_MONO:
 				case V4L2_TUNER_MODE_LANG1:
-					set_audio_standard_A2(core,
-							      EN_A2_FORCE_MONO1);
+					ctl = EN_A2_FORCE_MONO1;
 					break;
 				case V4L2_TUNER_MODE_LANG2:
-					set_audio_standard_A2(core,
-							      EN_A2_FORCE_MONO2);
+					ctl = EN_A2_FORCE_MONO2;
 					break;
 				case V4L2_TUNER_MODE_STEREO:
 				case V4L2_TUNER_MODE_LANG1_LANG2:
-					set_audio_standard_A2(core,
-							      EN_A2_FORCE_STEREO);
+					ctl = EN_A2_FORCE_STEREO;
 					break;
 				}
 			}
@@ -932,24 +974,39 @@
 			break;
 		try_to_freeze();
 
-		/* just monitor the audio status for now ... */
-		memset(&t, 0, sizeof(t));
-		cx88_get_stereo(core, &t);
+		switch (core->tvaudio) {
+		case WW_BG:
+		case WW_DK:
+		case WW_M:
+		case WW_I:
+		case WW_L:
+			if (core->use_nicam)
+				goto hw_autodetect;
 
-		if (UNSET != core->audiomode_manual)
-			/* manually set, don't do anything. */
-			continue;
+			/* just monitor the audio status for now ... */
+			memset(&t, 0, sizeof(t));
+			cx88_get_stereo(core, &t);
 
-		/* monitor signal */
-		if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
-			mode = V4L2_TUNER_MODE_STEREO;
-		else
-			mode = V4L2_TUNER_MODE_MONO;
-		if (mode == core->audiomode_current)
-			continue;
+			if (UNSET != core->audiomode_manual)
+				/* manually set, don't do anything. */
+				continue;
 
-		/* automatically switch to best available mode */
-		cx88_set_stereo(core, mode, 0);
+			/* monitor signal and set stereo if available */
+			if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
+				mode = V4L2_TUNER_MODE_STEREO;
+			else
+				mode = V4L2_TUNER_MODE_MONO;
+			if (mode == core->audiomode_current)
+				continue;
+			/* automatically switch to best available mode */
+			cx88_set_stereo(core, mode, 0);
+			break;
+		default:
+hw_autodetect:
+			/* stereo autodetection is supported by hardware so
+			   we don't need to do it manually. Do nothing. */
+			break;
+		}
 	}
 
 	dprintk("cx88: tvaudio thread exiting\n");
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-video.c linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/cx88-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/cx88-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/kmod.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -869,6 +870,7 @@
 {
 	struct cx8800_fh *fh = file->private_data;
 	struct cx88_buffer *buf;
+	unsigned int rc = POLLERR;
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
 		if (!res_get(fh->dev,fh,RESOURCE_VBI))
@@ -876,22 +878,27 @@
 		return videobuf_poll_stream(file, &fh->vbiq, wait);
 	}
 
+	mutex_lock(&fh->vidq.vb_lock);
 	if (res_check(fh,RESOURCE_VIDEO)) {
 		/* streaming capture */
 		if (list_empty(&fh->vidq.stream))
-			return POLLERR;
+			goto done;
 		buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
 	} else {
 		/* read() capture */
 		buf = (struct cx88_buffer*)fh->vidq.read_buf;
 		if (NULL == buf)
-			return POLLERR;
+			goto done;
 	}
 	poll_wait(file, &buf->vb.done, wait);
 	if (buf->vb.state == VIDEOBUF_DONE ||
 	    buf->vb.state == VIDEOBUF_ERROR)
-		return POLLIN|POLLRDNORM;
-	return 0;
+		rc = POLLIN|POLLRDNORM;
+	else
+		rc = 0;
+done:
+	mutex_unlock(&fh->vidq.vb_lock);
+	return rc;
 }
 
 static int video_release(struct file *file)
@@ -926,8 +933,10 @@
 	file->private_data = NULL;
 	kfree(fh);
 
+	mutex_lock(&dev->core->lock);
 	if(atomic_dec_and_test(&dev->core->users))
 		call_all(dev->core, tuner, s_standby);
+	mutex_unlock(&dev->core->lock);
 
 	return 0;
 }
@@ -1103,15 +1112,8 @@
 	}
 
 	f->fmt.pix.field = field;
-	if (f->fmt.pix.height < 32)
-		f->fmt.pix.height = 32;
-	if (f->fmt.pix.height > maxh)
-		f->fmt.pix.height = maxh;
-	if (f->fmt.pix.width < 48)
-		f->fmt.pix.width = 48;
-	if (f->fmt.pix.width > maxw)
-		f->fmt.pix.width = maxw;
-	f->fmt.pix.width &= ~0x03;
+	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+			      &f->fmt.pix.height, 32, maxh, 0, 0);
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/cx88/Makefile linux-libre-2.6.31-gnu/drivers/media/video/cx88/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/video/cx88/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/cx88/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 cx88xx-objs	:= cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
-		   cx88-input.o
+		   cx88-dsp.o cx88-input.o
 cx8800-objs	:= cx88-video.o cx88-vbi.o
 cx8802-objs	:= cx88-mpeg.o
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/dabusb.c linux-libre-2.6.31-gnu/drivers/media/video/dabusb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/dabusb.c	2012-03-22 19:14:04.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/dabusb.c	2012-03-22 20:10:16.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/list.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
@@ -747,8 +748,14 @@
 	.release =	dabusb_release,
 };
 
+static char *dabusb_nodename(struct device *dev)
+{
+	return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev));
+}
+
 static struct usb_class_driver dabusb_class = {
 	.name =		"dabusb%d",
+	.nodename =	dabusb_nodename,
 	.fops =		&dabusb_fops,
 	.minor_base =	DABUSB_MINOR,
 };
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-audio.c linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-audio.c
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-audio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-audio.c	2009-09-09 18:13:59.000000000 -0400
@@ -339,6 +339,11 @@
 	mutex_lock(&dev->lock);
 	dev->adev.users--;
 	em28xx_audio_analog_set(dev);
+	if (substream->runtime->dma_area) {
+		dprintk("freeing\n");
+		vfree(substream->runtime->dma_area);
+		substream->runtime->dma_area = NULL;
+	}
 	mutex_unlock(&dev->lock);
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-cards.c linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-03-22 20:08:07.000000000 -0400
@@ -49,6 +49,11 @@
 module_param(disable_ir, int, 0444);
 MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
 
+static unsigned int disable_usb_speed_check;
+module_param(disable_usb_speed_check, int, 0444);
+MODULE_PARM_DESC(disable_usb_speed_check,
+		 "override min bandwidth requirement of 480M bps");
+
 static unsigned int card[]     = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
 module_param_array(card,  int, NULL, 0444);
 MODULE_PARM_DESC(card,     "card type");
@@ -104,6 +109,24 @@
 /* Board  - EM2870 Kworld 355u
    Analog - No input analog */
 
+/* Board - EM2882 Kworld 315U digital */
+static struct em28xx_reg_seq em2882_kworld_315u_digital[] = {
+	{EM28XX_R08_GPIO,	0xff,	0xff,		10},
+	{EM28XX_R08_GPIO,	0xfe,	0xff,		10},
+	{EM2880_R04_GPO,	0x04,	0xff,		10},
+	{EM2880_R04_GPO,	0x0c,	0xff,		10},
+	{EM28XX_R08_GPIO,	0x7e,	0xff,		10},
+	{  -1,			-1,	-1,		-1},
+};
+
+static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = {
+	{EM2880_R04_GPO,	0x08,	0xff,		10},
+	{EM2880_R04_GPO,	0x0c,	0xff,		10},
+	{EM2880_R04_GPO,	0x08,	0xff,		10},
+	{EM2880_R04_GPO,	0x0c,	0xff,		10},
+	{  -1,			-1,	-1,		-1},
+};
+
 static struct em28xx_reg_seq kworld_330u_analog[] = {
 	{EM28XX_R08_GPIO,	0x6d,	~EM_GPIO_4,	10},
 	{EM2880_R04_GPO,	0x00,	0xff,		10},
@@ -116,6 +139,38 @@
 	{ -1,			-1,	-1,		-1},
 };
 
+/* Evga inDtube
+   GPIO0 - Enable digital power (s5h1409) - low to enable
+   GPIO1 - Enable analog power (tvp5150/emp202) - low to enable
+   GPIO4 - xc3028 reset
+   GOP3  - s5h1409 reset
+ */
+static struct em28xx_reg_seq evga_indtube_analog[] = {
+	{EM28XX_R08_GPIO,	0x79,   0xff,		60},
+	{	-1,		-1,	-1,		-1},
+};
+
+static struct em28xx_reg_seq evga_indtube_digital[] = {
+	{EM28XX_R08_GPIO,	0x7a,	0xff,		 1},
+	{EM2880_R04_GPO,	0x04,	0xff,		10},
+	{EM2880_R04_GPO,	0x0c,	0xff,		 1},
+	{ -1,			-1,	-1,		-1},
+};
+
+/* Pinnacle Hybrid Pro eb1a:2881 */
+static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
+	{EM28XX_R08_GPIO,	0xfd,   ~EM_GPIO_4,	10},
+	{	-1,		-1,	-1,		-1},
+};
+
+static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
+	{EM28XX_R08_GPIO,	0x6e,	~EM_GPIO_4,	10},
+	{EM2880_R04_GPO,	0x04,	0xff,	       100},/* zl10353 reset */
+	{EM2880_R04_GPO,	0x0c,	0xff,		 1},
+	{	-1,		-1,	-1,		-1},
+};
+
+
 /* Callback for the most boards */
 static struct em28xx_reg_seq default_tuner_gpio[] = {
 	{EM28XX_R08_GPIO,	EM_GPIO_4,	EM_GPIO_4,	10},
@@ -140,18 +195,37 @@
 	{  -1,			-1,		-1,		-1},
 };
 
+/* Terratec AV350 */
+static struct em28xx_reg_seq terratec_av350_mute_gpio[] = {
+	{EM28XX_R08_GPIO,	0xff,	0x7f,		10},
+	{	-1,		-1,	-1,		-1},
+};
+
+static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
+	{EM28XX_R08_GPIO,	0xff,	0xff,		10},
+	{	-1,		-1,	-1,		-1},
+};
+
+static struct em28xx_reg_seq silvercrest_reg_seq[] = {
+	{EM28XX_R08_GPIO,	0xff,	0xff,		10},
+	{EM28XX_R08_GPIO,	0x01,	0xf7,		10},
+	{	-1,		-1,	-1,		-1},
+};
+
 /*
  *  Board definitions
  */
 struct em28xx_board em28xx_boards[] = {
 	[EM2750_BOARD_UNKNOWN] = {
-		.name          = "Unknown EM2750/EM2751 webcam grabber",
-		.xclk          = EM28XX_XCLK_FREQUENCY_48MHZ,
-		.tuner_type    = TUNER_ABSENT,	/* This is a webcam */
+		.name          = "EM2710/EM2750/EM2751 webcam grabber",
+		.xclk          = EM28XX_XCLK_FREQUENCY_20MHZ,
+		.tuner_type    = TUNER_ABSENT,
+		.is_webcam     = 1,
 		.input         = { {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = 0,
 			.amux     = EM28XX_AMUX_VIDEO,
+			.gpio     = silvercrest_reg_seq,
 		} },
 	},
 	[EM2800_BOARD_UNKNOWN] = {
@@ -173,13 +247,15 @@
 	[EM2820_BOARD_UNKNOWN] = {
 		.name          = "Unknown EM2750/28xx video grabber",
 		.tuner_type    = TUNER_ABSENT,
+		.is_webcam     = 1,	/* To enable sensor probe */
 	},
 	[EM2750_BOARD_DLCW_130] = {
 		/* Beijing Huaqi Information Digital Technology Co., Ltd */
 		.name          = "Huaqi DLCW-130",
 		.valid         = EM28XX_BOARD_NOT_VALIDATED,
 		.xclk          = EM28XX_XCLK_FREQUENCY_48MHZ,
-		.tuner_type    = TUNER_ABSENT,	/* This is a webcam */
+		.tuner_type    = TUNER_ABSENT,
+		.is_webcam     = 1,
 		.input         = { {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = 0,
@@ -380,11 +456,23 @@
 	[EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
 		.name         = "Videology 20K14XUSB USB2.0",
 		.valid        = EM28XX_BOARD_NOT_VALIDATED,
-		.tuner_type   = TUNER_ABSENT,	/* This is a webcam */
+		.tuner_type   = TUNER_ABSENT,
+		.is_webcam    = 1,
+		.input        = { {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = 0,
+			.amux     = EM28XX_AMUX_VIDEO,
+		} },
+	},
+	[EM2820_BOARD_SILVERCREST_WEBCAM] = {
+		.name         = "Silvercrest Webcam 1.3mpix",
+		.tuner_type   = TUNER_ABSENT,
+		.is_webcam    = 1,
 		.input        = { {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = 0,
 			.amux     = EM28XX_AMUX_VIDEO,
+			.gpio     = silvercrest_reg_seq,
 		} },
 	},
 	[EM2821_BOARD_SUPERCOMP_USB_2] = {
@@ -428,7 +516,8 @@
 		/* Beijing Huaqi Information Digital Technology Co., Ltd */
 		.name         = "NetGMBH Cam",
 		.valid        = EM28XX_BOARD_NOT_VALIDATED,
-		.tuner_type   = TUNER_ABSENT,	/* This is a webcam */
+		.tuner_type   = TUNER_ABSENT,
+		.is_webcam    = 1,
 		.input        = { {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = 0,
@@ -533,22 +622,27 @@
 	},
 	[EM2861_BOARD_PLEXTOR_PX_TV100U] = {
 		.name         = "Plextor ConvertX PX-TV100U",
-		.valid        = EM28XX_BOARD_NOT_VALIDATED,
 		.tuner_type   = TUNER_TNF_5335MF,
+		.xclk         = EM28XX_XCLK_I2S_MSB_TIMING |
+				EM28XX_XCLK_FREQUENCY_12MHZ,
 		.tda9887_conf = TDA9887_PRESENT,
 		.decoder      = EM28XX_TVP5150,
+		.has_msp34xx  = 1,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
 			.amux     = EM28XX_AMUX_LINE_IN,
+			.gpio     = pinnacle_hybrid_pro_analog,
 		}, {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = TVP5150_COMPOSITE1,
 			.amux     = EM28XX_AMUX_LINE_IN,
+			.gpio     = pinnacle_hybrid_pro_analog,
 		}, {
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = TVP5150_SVIDEO,
 			.amux     = EM28XX_AMUX_LINE_IN,
+			.gpio     = pinnacle_hybrid_pro_analog,
 		} },
 	},
 
@@ -775,7 +869,7 @@
 		.tuner_gpio     = default_tuner_gpio,
 		.decoder        = EM28XX_TVP5150,
 		.has_dvb        = 1,
-		.dvb_gpio       = default_analog,
+		.dvb_gpio       = default_digital,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
@@ -992,16 +1086,17 @@
 			.amux     = EM28XX_AMUX_LINE_IN,
 		} },
 	},
-	[EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = {
-		.name                = "PointNix Intra-Oral Camera",
+	[EM2860_BOARD_SAA711X_REFERENCE_DESIGN] = {
+		.name                = "EM2860/SAA711X Reference Design",
 		.has_snapshot_button = 1,
-		.tda9887_conf        = TDA9887_PRESENT,
 		.tuner_type          = TUNER_ABSENT,
 		.decoder             = EM28XX_SAA711X,
 		.input               = { {
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = SAA7115_SVIDEO3,
-			.amux     = EM28XX_AMUX_VIDEO,
+		}, {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = SAA7115_COMPOSITE0,
 		} },
 	},
 	[EM2880_BOARD_MSI_DIGIVOX_AD] = {
@@ -1095,6 +1190,63 @@
 			.gpio     = default_analog,
 		} },
 	},
+	[EM2882_BOARD_KWORLD_ATSC_315U] = {
+		.name		= "KWorld ATSC 315U HDTV TV Box",
+		.valid		= EM28XX_BOARD_NOT_VALIDATED,
+		.tuner_type	= TUNER_THOMSON_DTT761X,
+		.tuner_gpio	= em2882_kworld_315u_tuner_gpio,
+		.tda9887_conf	= TDA9887_PRESENT,
+		.decoder	= EM28XX_SAA711X,
+		.has_dvb	= 1,
+		.dvb_gpio	= em2882_kworld_315u_digital,
+		.xclk		= EM28XX_XCLK_FREQUENCY_12MHZ,
+		.i2c_speed	= EM28XX_I2C_CLK_WAIT_ENABLE,
+		/* Analog mode - still not ready */
+		/*.input        = { {
+			.type = EM28XX_VMUX_TELEVISION,
+			.vmux = SAA7115_COMPOSITE2,
+			.amux = EM28XX_AMUX_VIDEO,
+			.gpio = em2882_kworld_315u_analog,
+			.aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+		}, {
+			.type = EM28XX_VMUX_COMPOSITE1,
+			.vmux = SAA7115_COMPOSITE0,
+			.amux = EM28XX_AMUX_LINE_IN,
+			.gpio = em2882_kworld_315u_analog1,
+			.aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+		}, {
+			.type = EM28XX_VMUX_SVIDEO,
+			.vmux = SAA7115_SVIDEO3,
+			.amux = EM28XX_AMUX_LINE_IN,
+			.gpio = em2882_kworld_315u_analog1,
+			.aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+		} }, */
+	},
+	[EM2880_BOARD_EMPIRE_DUAL_TV] = {
+		.name = "Empire dual TV",
+		.tuner_type = TUNER_XC2028,
+		.tuner_gpio = default_tuner_gpio,
+		.has_dvb = 1,
+		.dvb_gpio = default_digital,
+		.mts_firmware = 1,
+		.decoder = EM28XX_TVP5150,
+		.input = { {
+			.type = EM28XX_VMUX_TELEVISION,
+			.vmux = TVP5150_COMPOSITE0,
+			.amux = EM28XX_AMUX_VIDEO,
+			.gpio = default_analog,
+		}, {
+			.type = EM28XX_VMUX_COMPOSITE1,
+			.vmux = TVP5150_COMPOSITE1,
+			.amux = EM28XX_AMUX_LINE_IN,
+			.gpio = default_analog,
+		}, {
+			.type = EM28XX_VMUX_SVIDEO,
+			.vmux = TVP5150_SVIDEO,
+			.amux = EM28XX_AMUX_LINE_IN,
+			.gpio = default_analog,
+		} },
+	},
 	[EM2881_BOARD_DNT_DA2_HYBRID] = {
 		.name         = "DNT DA2 Hybrid",
 		.valid        = EM28XX_BOARD_NOT_VALIDATED,
@@ -1120,25 +1272,26 @@
 	},
 	[EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
 		.name         = "Pinnacle Hybrid Pro",
-		.valid        = EM28XX_BOARD_NOT_VALIDATED,
 		.tuner_type   = TUNER_XC2028,
 		.tuner_gpio   = default_tuner_gpio,
 		.decoder      = EM28XX_TVP5150,
+		.has_dvb      = 1,
+		.dvb_gpio     = pinnacle_hybrid_pro_digital,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
 			.amux     = EM28XX_AMUX_VIDEO,
-			.gpio     = default_analog,
+			.gpio     = pinnacle_hybrid_pro_analog,
 		}, {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = TVP5150_COMPOSITE1,
 			.amux     = EM28XX_AMUX_LINE_IN,
-			.gpio     = default_analog,
+			.gpio     = pinnacle_hybrid_pro_analog,
 		}, {
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = TVP5150_SVIDEO,
 			.amux     = EM28XX_AMUX_LINE_IN,
-			.gpio     = default_analog,
+			.gpio     = pinnacle_hybrid_pro_analog,
 		} },
 	},
 	[EM2882_BOARD_PINNACLE_HYBRID_PRO] = {
@@ -1322,6 +1475,69 @@
 			.amux     = EM28XX_AMUX_VIDEO,
 		} },
 	},
+	[EM2860_BOARD_TERRATEC_GRABBY] = {
+		.name            = "Terratec Grabby",
+		.vchannels       = 2,
+		.tuner_type      = TUNER_ABSENT,
+		.decoder         = EM28XX_SAA711X,
+		.xclk            = EM28XX_XCLK_FREQUENCY_12MHZ,
+		.input           = { {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = SAA7115_COMPOSITE0,
+			.amux     = EM28XX_AMUX_VIDEO2,
+		}, {
+			.type     = EM28XX_VMUX_SVIDEO,
+			.vmux     = SAA7115_SVIDEO3,
+			.amux     = EM28XX_AMUX_VIDEO2,
+		} },
+	},
+	[EM2860_BOARD_TERRATEC_AV350] = {
+		.name            = "Terratec AV350",
+		.vchannels       = 2,
+		.tuner_type      = TUNER_ABSENT,
+		.decoder         = EM28XX_TVP5150,
+		.xclk            = EM28XX_XCLK_FREQUENCY_12MHZ,
+		.mute_gpio       = terratec_av350_mute_gpio,
+		.input           = { {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = TVP5150_COMPOSITE1,
+			.amux     = EM28XX_AUDIO_SRC_LINE,
+			.gpio     = terratec_av350_unmute_gpio,
+
+		}, {
+			.type     = EM28XX_VMUX_SVIDEO,
+			.vmux     = TVP5150_SVIDEO,
+			.amux     = EM28XX_AUDIO_SRC_LINE,
+			.gpio     = terratec_av350_unmute_gpio,
+		} },
+	},
+	[EM2882_BOARD_EVGA_INDTUBE] = {
+		.name         = "Evga inDtube",
+		.tuner_type   = TUNER_XC2028,
+		.tuner_gpio   = default_tuner_gpio,
+		.decoder      = EM28XX_TVP5150,
+		.xclk         = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
+		.mts_firmware = 1,
+		.has_dvb      = 1,
+		.dvb_gpio     = evga_indtube_digital,
+		.ir_codes     = ir_codes_evga_indtube,
+		.input        = { {
+			.type     = EM28XX_VMUX_TELEVISION,
+			.vmux     = TVP5150_COMPOSITE0,
+			.amux     = EM28XX_AMUX_VIDEO,
+			.gpio     = evga_indtube_analog,
+		}, {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = TVP5150_COMPOSITE1,
+			.amux     = EM28XX_AMUX_LINE_IN,
+			.gpio     = evga_indtube_analog,
+		}, {
+			.type     = EM28XX_VMUX_SVIDEO,
+			.vmux     = TVP5150_SVIDEO,
+			.amux     = EM28XX_AMUX_LINE_IN,
+			.gpio     = evga_indtube_analog,
+		} },
+	},
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
@@ -1333,6 +1549,8 @@
 			.driver_info = EM2750_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0x2800),
 			.driver_info = EM2800_BOARD_UNKNOWN },
+	{ USB_DEVICE(0xeb1a, 0x2710),
+			.driver_info = EM2820_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0x2820),
 			.driver_info = EM2820_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0x2821),
@@ -1355,6 +1573,8 @@
 			.driver_info = EM2880_BOARD_KWORLD_DVB_305U },
 	{ USB_DEVICE(0xeb1a, 0xe310),
 			.driver_info = EM2880_BOARD_MSI_DIGIVOX_AD },
+	{ USB_DEVICE(0xeb1a, 0xa313),
+		.driver_info = EM2882_BOARD_KWORLD_ATSC_315U },
 	{ USB_DEVICE(0xeb1a, 0xa316),
 			.driver_info = EM2883_BOARD_KWORLD_HYBRID_330U },
 	{ USB_DEVICE(0xeb1a, 0xe320),
@@ -1385,6 +1605,10 @@
 			.driver_info = EM2870_BOARD_TERRATEC_XS },
 	{ USB_DEVICE(0x0ccd, 0x0047),
 			.driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
+	{ USB_DEVICE(0x0ccd, 0x0084),
+			.driver_info = EM2860_BOARD_TERRATEC_AV350 },
+	{ USB_DEVICE(0x0ccd, 0x0096),
+			.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
 	{ USB_DEVICE(0x185b, 0x2870),
 			.driver_info = EM2870_BOARD_COMPRO_VIDEOMATE },
 	{ USB_DEVICE(0x185b, 0x2041),
@@ -1437,13 +1661,16 @@
 	{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
 	{0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF},
 	{0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
+	{0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
+	{0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
+	{0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
 };
 
 /* I2C devicelist hash table for devices with generic USB IDs */
 static struct em28xx_hash_table em28xx_i2c_hash[] = {
 	{0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
 	{0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
-	{0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
+	{0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT},
 	{0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
 };
 
@@ -1459,6 +1686,11 @@
 	I2C_CLIENT_END
 };
 
+static unsigned short mt9v011_addrs[] = {
+	0xba >> 1,
+	I2C_CLIENT_END
+};
+
 static unsigned short msp3400_addrs[] = {
 	0x80 >> 1,
 	0x88 >> 1,
@@ -1498,65 +1730,150 @@
 				       EM28XX_I2C_FREQ_100_KHZ;
 }
 
-/* Since em28xx_pre_card_setup() requires a proper dev->model,
- * this won't work for boards with generic PCI IDs
+
+/* FIXME: Should be replaced by a proper mt9m111 driver */
+static int em28xx_initialize_mt9m111(struct em28xx *dev)
+{
+	int i;
+	unsigned char regs[][3] = {
+		{ 0x0d, 0x00, 0x01, },  /* reset and use defaults */
+		{ 0x0d, 0x00, 0x00, },
+		{ 0x0a, 0x00, 0x21, },
+		{ 0x21, 0x04, 0x00, },  /* full readout speed, no row/col skipping */
+	};
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++)
+		i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
+
+	return 0;
+}
+
+
+/* FIXME: Should be replaced by a proper mt9m001 driver */
+static int em28xx_initialize_mt9m001(struct em28xx *dev)
+{
+	int i;
+	unsigned char regs[][3] = {
+		{ 0x0d, 0x00, 0x01, },
+		{ 0x0d, 0x00, 0x00, },
+		{ 0x04, 0x05, 0x00, },	/* hres = 1280 */
+		{ 0x03, 0x04, 0x00, },  /* vres = 1024 */
+		{ 0x20, 0x11, 0x00, },
+		{ 0x06, 0x00, 0x10, },
+		{ 0x2b, 0x00, 0x24, },
+		{ 0x2e, 0x00, 0x24, },
+		{ 0x35, 0x00, 0x24, },
+		{ 0x2d, 0x00, 0x20, },
+		{ 0x2c, 0x00, 0x20, },
+		{ 0x09, 0x0a, 0xd4, },
+		{ 0x35, 0x00, 0x57, },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++)
+		i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
+
+	return 0;
+}
+
+/* HINT method: webcam I2C chips
+ *
+ * This method works for webcams with Micron sensors
  */
-void em28xx_pre_card_setup(struct em28xx *dev)
+static int em28xx_hint_sensor(struct em28xx *dev)
 {
 	int rc;
+	char *sensor_name;
+	unsigned char cmd;
+	__be16 version_be;
+	u16 version;
 
-	em28xx_set_model(dev);
+	/* Micron sensor detection */
+	dev->i2c_client.addr = 0xba >> 1;
+	cmd = 0;
+	i2c_master_send(&dev->i2c_client, &cmd, 1);
+	rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2);
+	if (rc != 2)
+		return -EINVAL;
 
-	em28xx_info("Identified as %s (card=%d)\n",
-		    dev->board.name, dev->model);
+	version = be16_to_cpu(version_be);
+	switch (version) {
+	case 0x8232:		/* mt9v011 640x480 1.3 Mpix sensor */
+	case 0x8243:		/* mt9v011 rev B 640x480 1.3 Mpix sensor */
+		dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
+		em28xx_set_model(dev);
 
-	/* Set the default GPO/GPIO for legacy devices */
-	dev->reg_gpo_num = EM2880_R04_GPO;
-	dev->reg_gpio_num = EM28XX_R08_GPIO;
+		sensor_name = "mt9v011";
+		dev->em28xx_sensor = EM28XX_MT9V011;
+		dev->sensor_xres = 640;
+		dev->sensor_yres = 480;
+		/*
+		 * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
+		 * the Silvercrest cam I have here for testing - for higher
+		 * resolutions, a high clock cause horizontal artifacts, so we
+		 * need to use a lower xclk frequency.
+		 * Yet, it would be possible to adjust xclk depending on the
+		 * desired resolution, since this affects directly the
+		 * frame rate.
+		 */
+		dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
+		dev->sensor_xtal = 4300000;
 
-	dev->wait_after_write = 5;
+		/* probably means GRGB 16 bit bayer */
+		dev->vinmode = 0x0d;
+		dev->vinctl = 0x00;
 
-	/* Based on the Chip ID, set the device configuration */
-	rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
-	if (rc > 0) {
-		dev->chip_id = rc;
+		break;
 
-		switch (dev->chip_id) {
-		case CHIP_ID_EM2750:
-			em28xx_info("chip ID is em2750\n");
-			break;
-		case CHIP_ID_EM2820:
-			em28xx_info("chip ID is em2820\n");
-			break;
-		case CHIP_ID_EM2840:
-			em28xx_info("chip ID is em2840\n");
-			break;
-		case CHIP_ID_EM2860:
-			em28xx_info("chip ID is em2860\n");
-			break;
-		case CHIP_ID_EM2870:
-			em28xx_info("chip ID is em2870\n");
-			dev->wait_after_write = 0;
-			break;
-		case CHIP_ID_EM2874:
-			em28xx_info("chip ID is em2874\n");
-			dev->reg_gpio_num = EM2874_R80_GPIO;
-			dev->wait_after_write = 0;
-			break;
-		case CHIP_ID_EM2883:
-			em28xx_info("chip ID is em2882/em2883\n");
-			dev->wait_after_write = 0;
-			break;
-		default:
-			em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
-		}
+	case 0x143a:    /* MT9M111 as found in the ECS G200 */
+		dev->model = EM2750_BOARD_UNKNOWN;
+		em28xx_set_model(dev);
+
+		sensor_name = "mt9m111";
+		dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
+		dev->em28xx_sensor = EM28XX_MT9M111;
+		em28xx_initialize_mt9m111(dev);
+		dev->sensor_xres = 640;
+		dev->sensor_yres = 512;
+
+		dev->vinmode = 0x0a;
+		dev->vinctl = 0x00;
+
+		break;
+
+	case 0x8431:
+		dev->model = EM2750_BOARD_UNKNOWN;
+		em28xx_set_model(dev);
+
+		sensor_name = "mt9m001";
+		dev->em28xx_sensor = EM28XX_MT9M001;
+		em28xx_initialize_mt9m001(dev);
+		dev->sensor_xres = 1280;
+		dev->sensor_yres = 1024;
+
+		/* probably means BGGR 16 bit bayer */
+		dev->vinmode = 0x0c;
+		dev->vinctl = 0x00;
+
+		break;
+	default:
+		printk("Unknown Micron Sensor 0x%04x\n", version);
+		return -EINVAL;
 	}
 
-	/* Prepopulate cached GPO register content */
-	rc = em28xx_read_reg(dev, dev->reg_gpo_num);
-	if (rc >= 0)
-		dev->reg_gpo = rc;
+	/* Setup webcam defaults */
+	em28xx_pre_card_setup(dev);
+
+	em28xx_errdev("Sensor is %s, using model %s entry.\n",
+		      sensor_name, em28xx_boards[dev->model].name);
+
+	return 0;
+}
 
+/* Since em28xx_pre_card_setup() requires a proper dev->model,
+ * this won't work for boards with generic PCI IDs
+ */
+void em28xx_pre_card_setup(struct em28xx *dev)
+{
 	/* Set the initial XCLK and I2C clock values based on the board
 	   definition */
 	em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
@@ -1566,9 +1883,8 @@
 	/* request some modules */
 	switch (dev->model) {
 	case EM2861_BOARD_PLEXTOR_PX_TV100U:
-		/* FIXME guess */
-		/* Turn on analog audio output */
-		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+		/* Sets the msp34xx I2S speed */
+		dev->i2s_speed = 2048000;
 		break;
 	case EM2861_BOARD_KWORLD_PVRTV_300U:
 	case EM2880_BOARD_KWORLD_DVB_305U:
@@ -1619,6 +1935,17 @@
 		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
 		break;
 
+	case EM2882_BOARD_KWORLD_ATSC_315U:
+		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+		msleep(10);
+		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+		msleep(10);
+		em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
+		msleep(10);
+		em28xx_write_reg(dev, EM2880_R04_GPO, 0x08);
+		msleep(10);
+		break;
+
 	case EM2860_BOARD_KAIOMY_TVNPC_U2:
 		em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1);
 		em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
@@ -1664,10 +1991,12 @@
 	ctl->mts = em28xx_boards[dev->model].mts_firmware;
 
 	switch (dev->model) {
+	case EM2880_BOARD_EMPIRE_DUAL_TV:
 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
 		ctl->demod = XC3028_FE_ZARLINK456;
 		break;
 	case EM2880_BOARD_TERRATEC_HYBRID_XS:
+	case EM2881_BOARD_PINNACLE_HYBRID_PRO:
 		ctl->demod = XC3028_FE_ZARLINK456;
 		break;
 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
@@ -1688,6 +2017,10 @@
 		ctl->demod = XC3028_FE_CHINA;
 		ctl->fname = "/*(DEBLOBBED)*/";
 		break;
+	case EM2882_BOARD_EVGA_INDTUBE:
+		ctl->demod = XC3028_FE_CHINA;
+		ctl->fname = "/*(DEBLOBBED)*/";
+		break;
 	default:
 		ctl->demod = XC3028_FE_OREN538;
 	}
@@ -1835,12 +2168,20 @@
 }
 
 /* ----------------------------------------------------------------------- */
-void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
+void em28xx_register_i2c_ir(struct em28xx *dev)
 {
-	if (disable_ir) {
-		ir->get_key = NULL;
-		return ;
-	}
+	struct i2c_board_info info;
+	struct IR_i2c_init_data init_data;
+	const unsigned short addr_list[] = {
+		 0x30, 0x47, I2C_CLIENT_END
+	};
+
+	if (disable_ir)
+		return;
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
+	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
 
 	/* detect & configure */
 	switch (dev->model) {
@@ -1850,22 +2191,19 @@
 		break;
 	case (EM2800_BOARD_TERRATEC_CINERGY_200):
 	case (EM2820_BOARD_TERRATEC_CINERGY_250):
-		ir->ir_codes = ir_codes_em_terratec;
-		ir->get_key = em28xx_get_key_terratec;
-		snprintf(ir->c.name, sizeof(ir->c.name),
-			 "i2c IR (EM28XX Terratec)");
+		init_data.ir_codes = ir_codes_em_terratec;
+		init_data.get_key = em28xx_get_key_terratec;
+		init_data.name = "i2c IR (EM28XX Terratec)";
 		break;
 	case (EM2820_BOARD_PINNACLE_USB_2):
-		ir->ir_codes = ir_codes_pinnacle_grey;
-		ir->get_key = em28xx_get_key_pinnacle_usb_grey;
-		snprintf(ir->c.name, sizeof(ir->c.name),
-			 "i2c IR (EM28XX Pinnacle PCTV)");
+		init_data.ir_codes = ir_codes_pinnacle_grey;
+		init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
+		init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
 		break;
 	case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
-		ir->ir_codes = ir_codes_hauppauge_new;
-		ir->get_key = em28xx_get_key_em_haup;
-		snprintf(ir->c.name, sizeof(ir->c.name),
-			 "i2c IR (EM2840 Hauppauge)");
+		init_data.ir_codes = ir_codes_hauppauge_new;
+		init_data.get_key = em28xx_get_key_em_haup;
+		init_data.name = "i2c IR (EM2840 Hauppauge)";
 		break;
 	case (EM2820_BOARD_MSI_VOX_USB_2):
 		break;
@@ -1876,16 +2214,36 @@
 	case (EM2800_BOARD_GRABBEEX_USB2800):
 		break;
 	}
+
+	if (init_data.name)
+		info.platform_data = &init_data;
+	i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
 }
 
 void em28xx_card_setup(struct em28xx *dev)
 {
-	em28xx_set_model(dev);
+	/*
+	 * If the device can be a webcam, seek for a sensor.
+	 * If sensor is not found, then it isn't a webcam.
+	 */
+	if (dev->board.is_webcam) {
+		if (em28xx_hint_sensor(dev) < 0)
+			dev->board.is_webcam = 0;
+		else
+			dev->progressive = 1;
+	} else
+		em28xx_set_model(dev);
+
+	em28xx_info("Identified as %s (card=%d)\n",
+		    dev->board.name, dev->model);
 
 	dev->tuner_type = em28xx_boards[dev->model].tuner_type;
 	if (em28xx_boards[dev->model].tuner_addr)
 		dev->tuner_addr = em28xx_boards[dev->model].tuner_addr;
 
+	if (em28xx_boards[dev->model].tda9887_conf)
+		dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+
 	/* request some modules */
 	switch (dev->model) {
 	case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
@@ -1915,6 +2273,12 @@
 #endif
 		break;
 	}
+	case EM2882_BOARD_KWORLD_ATSC_315U:
+		em28xx_write_reg(dev, 0x0d, 0x42);
+		msleep(10);
+		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+		msleep(10);
+		break;
 	case EM2820_BOARD_KWORLD_PVRTV2800RF:
 		/* GPIO enables sound on KWORLD PVR TV 2800RF */
 		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9);
@@ -1937,6 +2301,13 @@
 	case EM2880_BOARD_MSI_DIGIVOX_AD:
 		if (!em28xx_hint_board(dev))
 			em28xx_set_model(dev);
+
+		/* In cases where we had to use a board hint, the call to
+		   em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
+		   so make the call now so the analog GPIOs are set properly
+		   before probing the i2c bus. */
+		em28xx_gpio_set(dev, dev->board.tuner_gpio);
+		em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
 		break;
 	}
 
@@ -1969,6 +2340,15 @@
 		v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 			"tvp5150", "tvp5150", tvp5150_addrs);
 
+	if (dev->em28xx_sensor == EM28XX_MT9V011) {
+		struct v4l2_subdev *sd;
+
+		sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev,
+			 &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs);
+		v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
+	}
+
+
 	if (dev->board.adecoder == EM28XX_TVAUDIO)
 		v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
 			"tvaudio", "tvaudio", dev->board.tvaudio_addr);
@@ -2002,7 +2382,9 @@
 	}
 
 	em28xx_tuner_setup(dev);
-	em28xx_ir_init(dev);
+
+	if(!disable_ir)
+		em28xx_ir_init(dev);
 }
 
 
@@ -2068,7 +2450,7 @@
 			   int minor)
 {
 	struct em28xx *dev = *devhandle;
-	int retval = -ENOMEM;
+	int retval;
 	int errCode;
 
 	dev->udev = udev;
@@ -2085,6 +2467,58 @@
 	dev->em28xx_read_reg_req = em28xx_read_reg_req;
 	dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
 
+	em28xx_set_model(dev);
+
+	/* Set the default GPO/GPIO for legacy devices */
+	dev->reg_gpo_num = EM2880_R04_GPO;
+	dev->reg_gpio_num = EM28XX_R08_GPIO;
+
+	dev->wait_after_write = 5;
+
+	/* Based on the Chip ID, set the device configuration */
+	retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
+	if (retval > 0) {
+		dev->chip_id = retval;
+
+		switch (dev->chip_id) {
+		case CHIP_ID_EM2710:
+			em28xx_info("chip ID is em2710\n");
+			break;
+		case CHIP_ID_EM2750:
+			em28xx_info("chip ID is em2750\n");
+			break;
+		case CHIP_ID_EM2820:
+			em28xx_info("chip ID is em2820 (or em2710)\n");
+			break;
+		case CHIP_ID_EM2840:
+			em28xx_info("chip ID is em2840\n");
+			break;
+		case CHIP_ID_EM2860:
+			em28xx_info("chip ID is em2860\n");
+			break;
+		case CHIP_ID_EM2870:
+			em28xx_info("chip ID is em2870\n");
+			dev->wait_after_write = 0;
+			break;
+		case CHIP_ID_EM2874:
+			em28xx_info("chip ID is em2874\n");
+			dev->reg_gpio_num = EM2874_R80_GPIO;
+			dev->wait_after_write = 0;
+			break;
+		case CHIP_ID_EM2883:
+			em28xx_info("chip ID is em2882/em2883\n");
+			dev->wait_after_write = 0;
+			break;
+		default:
+			em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
+		}
+	}
+
+	/* Prepopulate cached GPO register content */
+	retval = em28xx_read_reg(dev, dev->reg_gpo_num);
+	if (retval >= 0)
+		dev->reg_gpo = retval;
+
 	em28xx_pre_card_setup(dev);
 
 	if (!dev->board.is_em2800) {
@@ -2113,6 +2547,12 @@
 		return errCode;
 	}
 
+	/*
+	 * Default format, used for tvp5150 or saa711x output formats
+	 */
+	dev->vinmode = 0x10;
+	dev->vinctl  = 0x11;
+
 	/* Do board specific init and eeprom reading */
 	em28xx_card_setup(dev);
 
@@ -2279,6 +2719,20 @@
 		ifnum,
 		interface->altsetting->desc.bInterfaceNumber);
 
+	/*
+	 * Make sure we have 480 Mbps of bandwidth, otherwise things like
+	 * video stream wouldn't likely work, since 12 Mbps is generally
+	 * not enough even for most Digital TV streams.
+	 */
+	if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
+		printk(DRIVER_NAME ": Device initialization failed.\n");
+		printk(DRIVER_NAME ": Device must be connected to a high-speed"
+		       " USB 2.0 port.\n");
+		em28xx_devused &= ~(1<<nr);
+		retval = -ENODEV;
+		goto err;
+	}
+
 	if (nr >= EM28XX_MAXBOARDS) {
 		printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
 				EM28XX_MAXBOARDS);
@@ -2339,6 +2793,7 @@
 	retval = em28xx_init_dev(&dev, udev, interface, nr);
 	if (retval) {
 		em28xx_devused &= ~(1<<dev->devno);
+		mutex_unlock(&dev->lock);
 		kfree(dev);
 		goto err;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-core.c linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -500,18 +500,21 @@
 
 	/* See how this device is configured */
 	cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG);
-	if (cfg < 0)
+	em28xx_info("Config register raw data: 0x%02x\n", cfg);
+	if (cfg < 0) {
+		/* Register read error?  */
 		cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */
-	else
-		em28xx_info("Config register raw data: 0x%02x\n", cfg);
-
-	if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
-		    EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
+	} else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) {
+		/* The device doesn't have vendor audio at all */
+		dev->has_alsa_audio = 0;
+		dev->audio_mode.has_audio = 0;
+		return 0;
+	} else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+		   EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
 		em28xx_info("I2S Audio (3 sample rates)\n");
 		dev->audio_mode.i2s_3rates = 1;
-	}
-	if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
-		    EM28XX_CHIPCFG_I2S_5_SAMPRATES) {
+	} else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+		   EM28XX_CHIPCFG_I2S_5_SAMPRATES) {
 		em28xx_info("I2S Audio (5 sample rates)\n");
 		dev->audio_mode.i2s_5rates = 1;
 	}
@@ -629,6 +632,9 @@
 		return rc;
 	}
 
+	if (dev->board.is_webcam)
+		rc = em28xx_write_reg(dev, 0x13, 0x0c);
+
 	/* enable video capture */
 	rc = em28xx_write_reg(dev, 0x48, 0x00);
 
@@ -647,15 +653,15 @@
 	int ret;
 
 	ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
-				    dev->format->reg | 0x20, 0x3f);
+				dev->format->reg | 0x20, 0xff);
 	if (ret < 0)
-		return ret;
+			return ret;
 
-	ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
+	ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
 	if (ret < 0)
 		return ret;
 
-	return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11);
+	return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl);
 }
 
 static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
@@ -692,13 +698,16 @@
 {
 	u8 mode;
 	/* the em2800 scaler only supports scaling down to 50% */
-	if (dev->board.is_em2800)
+
+	if (dev->board.is_em2800) {
 		mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
-	else {
+	} else {
 		u8 buf[2];
+
 		buf[0] = h;
 		buf[1] = h >> 8;
 		em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
+
 		buf[0] = v;
 		buf[1] = v >> 8;
 		em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
@@ -714,11 +723,17 @@
 {
 	int width, height;
 	width = norm_maxw(dev);
-	height = norm_maxh(dev) >> 1;
+	height = norm_maxh(dev);
+
+	if (!dev->progressive)
+		height >>= norm_maxh(dev);
 
 	em28xx_set_outfmt(dev);
+
+
 	em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
 	em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
+
 	return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
 }
 
@@ -938,7 +953,7 @@
 	dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
 					      GFP_KERNEL);
 	if (!dev->isoc_ctl.transfer_buffer) {
-		em28xx_errdev("cannot allocate memory for usbtransfer\n");
+		em28xx_errdev("cannot allocate memory for usb transfer\n");
 		kfree(dev->isoc_ctl.urb);
 		return -ENOMEM;
 	}
@@ -1012,6 +1027,41 @@
 }
 EXPORT_SYMBOL_GPL(em28xx_init_isoc);
 
+/* Determine the packet size for the DVB stream for the given device
+   (underlying value programmed into the eeprom) */
+int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
+{
+	unsigned int chip_cfg2;
+	unsigned int packet_size = 564;
+
+	if (dev->chip_id == CHIP_ID_EM2874) {
+		/* FIXME - for now assume 564 like it was before, but the
+		   em2874 code should be added to return the proper value... */
+		packet_size = 564;
+	} else {
+		/* TS max packet size stored in bits 1-0 of R01 */
+		chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2);
+		switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) {
+		case EM28XX_CHIPCFG2_TS_PACKETSIZE_188:
+			packet_size = 188;
+			break;
+		case EM28XX_CHIPCFG2_TS_PACKETSIZE_376:
+			packet_size = 376;
+			break;
+		case EM28XX_CHIPCFG2_TS_PACKETSIZE_564:
+			packet_size = 564;
+			break;
+		case EM28XX_CHIPCFG2_TS_PACKETSIZE_752:
+			packet_size = 752;
+			break;
+		}
+	}
+
+	em28xx_coredbg("dvb max packet size=%d\n", packet_size);
+	return packet_size;
+}
+EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize);
+
 /*
  * em28xx_wake_i2c()
  * configure i2c attached devices
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-dvb.c linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-dvb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-dvb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-dvb.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,10 +25,14 @@
 #include "em28xx.h"
 #include <media/v4l2-common.h>
 #include <media/videobuf-vmalloc.h>
+#include <media/tuner.h>
+#include "tuner-simple.h"
 
 #include "lgdt330x.h"
 #include "zl10353.h"
 #include "s5h1409.h"
+#include "mt352.h"
+#include "mt352_priv.h" /* FIXME */
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -46,7 +50,6 @@
 } while (0)
 
 #define EM28XX_DVB_NUM_BUFS 5
-#define EM28XX_DVB_MAX_PACKETSIZE 564
 #define EM28XX_DVB_MAX_PACKETS 64
 
 struct em28xx_dvb {
@@ -142,14 +145,17 @@
 {
 	int rc;
 	struct em28xx *dev = dvb->adapter.priv;
+	int max_dvb_packet_size;
 
 	usb_set_interface(dev->udev, 0, 1);
 	rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
 	if (rc < 0)
 		return rc;
 
+	max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev);
+
 	return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
-				EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
+				EM28XX_DVB_NUM_BUFS, max_dvb_packet_size,
 				dvb_isoc_copy);
 }
 
@@ -239,6 +245,14 @@
 	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
 };
 
+static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
+	.demod_address = (0x1e >> 1),
+	.no_tuner = 1,
+	.disable_i2c_gate_ctrl = 1,
+	.parallel_ts = 1,
+	.if2 = 45600,
+};
+
 #ifdef EM28XX_DRX397XD_SUPPORT
 /* [TODO] djh - not sure yet what the device config needs to contain */
 static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
@@ -246,6 +260,41 @@
 };
 #endif
 
+static int mt352_terratec_xs_init(struct dvb_frontend *fe)
+{
+	/* Values extracted from a USB trace of the Terratec Windows driver */
+	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
+	static u8 reset[]          = { RESET,      0x80 };
+	static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
+	static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0xa0 };
+	static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
+	static u8 rs_err_cfg[]     = { RS_ERR_PER_1, 0x00, 0x4d };
+	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+	static u8 trl_nom_cfg[]    = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
+	static u8 tps_given_cfg[]  = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
+	static u8 tuner_go[]       = { TUNER_GO, 0x01};
+
+	mt352_write(fe, clock_config,   sizeof(clock_config));
+	udelay(200);
+	mt352_write(fe, reset,          sizeof(reset));
+	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+	mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
+	mt352_write(fe, rs_err_cfg,     sizeof(rs_err_cfg));
+	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+	mt352_write(fe, trl_nom_cfg,    sizeof(trl_nom_cfg));
+	mt352_write(fe, tps_given_cfg,  sizeof(tps_given_cfg));
+	mt352_write(fe, tuner_go,       sizeof(tuner_go));
+	return 0;
+}
+
+static struct mt352_config terratec_xs_mt352_cfg = {
+	.demod_address = (0x1e >> 1),
+	.no_tuner = 1,
+	.if2 = 45600,
+	.demod_init = mt352_terratec_xs_init,
+};
+
 /* ------------------------------------------------------------------ */
 
 static int attach_xc3028(u8 addr, struct em28xx *dev)
@@ -428,8 +477,6 @@
 			goto out_free;
 		}
 		break;
-	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-	case EM2880_BOARD_TERRATEC_HYBRID_XS:
 	case EM2880_BOARD_KWORLD_DVB_310U:
 		dvb->frontend = dvb_attach(zl10353_attach,
 					   &em28xx_zl10353_with_xc3028,
@@ -439,7 +486,36 @@
 			goto out_free;
 		}
 		break;
+	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+	case EM2880_BOARD_EMPIRE_DUAL_TV:
+		dvb->frontend = dvb_attach(zl10353_attach,
+					   &em28xx_zl10353_xc3028_no_i2c_gate,
+					   &dev->i2c_adap);
+		if (attach_xc3028(0x61, dev) < 0) {
+			result = -EINVAL;
+			goto out_free;
+		}
+		break;
+	case EM2880_BOARD_TERRATEC_HYBRID_XS:
+	case EM2881_BOARD_PINNACLE_HYBRID_PRO:
+		dvb->frontend = dvb_attach(zl10353_attach,
+					   &em28xx_zl10353_xc3028_no_i2c_gate,
+					   &dev->i2c_adap);
+		if (dvb->frontend == NULL) {
+			/* This board could have either a zl10353 or a mt352.
+			   If the chip id isn't for zl10353, try mt352 */
+			dvb->frontend = dvb_attach(mt352_attach,
+						   &terratec_xs_mt352_cfg,
+						   &dev->i2c_adap);
+		}
+
+		if (attach_xc3028(0x61, dev) < 0) {
+			result = -EINVAL;
+			goto out_free;
+		}
+		break;
 	case EM2883_BOARD_KWORLD_HYBRID_330U:
+	case EM2882_BOARD_EVGA_INDTUBE:
 		dvb->frontend = dvb_attach(s5h1409_attach,
 					   &em28xx_s5h1409_with_xc3028,
 					   &dev->i2c_adap);
@@ -448,6 +524,18 @@
 			goto out_free;
 		}
 		break;
+	case EM2882_BOARD_KWORLD_ATSC_315U:
+		dvb->frontend = dvb_attach(lgdt330x_attach,
+					   &em2880_lgdt3303_dev,
+					   &dev->i2c_adap);
+		if (dvb->frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, dvb->frontend,
+				&dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) {
+				result = -EINVAL;
+				goto out_free;
+			}
+		}
+		break;
 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
 #ifdef EM28XX_DRX397XD_SUPPORT
 		/* We don't have the config structure properly populated, so
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx.h linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx.h
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -58,7 +58,7 @@
 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950	16
 #define EM2880_BOARD_PINNACLE_PCTV_HD_PRO	17
 #define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2	18
-#define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA  19
+#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN	19
 #define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600   20
 #define EM2800_BOARD_GRABBEEX_USB2800           21
 #define EM2750_BOARD_UNKNOWN			  22
@@ -102,6 +102,12 @@
 #define EM2860_BOARD_KAIOMY_TVNPC_U2              63
 #define EM2860_BOARD_EASYCAP                      64
 #define EM2820_BOARD_IODATA_GVMVP_SZ		  65
+#define EM2880_BOARD_EMPIRE_DUAL_TV		  66
+#define EM2860_BOARD_TERRATEC_GRABBY		  67
+#define EM2860_BOARD_TERRATEC_AV350		  68
+#define EM2882_BOARD_KWORLD_ATSC_315U		  69
+#define EM2882_BOARD_EVGA_INDTUBE		  70
+#define EM2820_BOARD_SILVERCREST_WEBCAM           71
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -352,11 +358,18 @@
 #define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
 
 enum em28xx_decoder {
-	EM28XX_NODECODER,
+	EM28XX_NODECODER = 0,
 	EM28XX_TVP5150,
 	EM28XX_SAA711X,
 };
 
+enum em28xx_sensor {
+	EM28XX_NOSENSOR = 0,
+	EM28XX_MT9V011,
+	EM28XX_MT9M001,
+	EM28XX_MT9M111,
+};
+
 enum em28xx_adecoder {
 	EM28XX_NOADECODER = 0,
 	EM28XX_TVAUDIO,
@@ -383,6 +396,7 @@
 	unsigned int max_range_640_480:1;
 	unsigned int has_dvb:1;
 	unsigned int has_snapshot_button:1;
+	unsigned int is_webcam:1;
 	unsigned int valid:1;
 
 	unsigned char xclk, i2c_speed;
@@ -466,6 +480,17 @@
 	struct v4l2_device v4l2_dev;
 	struct em28xx_board board;
 
+	/* Webcam specific fields */
+	enum em28xx_sensor em28xx_sensor;
+	int sensor_xres, sensor_yres;
+	int sensor_xtal;
+
+	/* Allows progressive (e. g. non-interlaced) mode */
+	int progressive;
+
+	/* Vinmode/Vinctl used at the driver */
+	int vinmode, vinctl;
+
 	unsigned int stream_on:1;	/* Locks streams */
 	unsigned int has_audio_class:1;
 	unsigned int has_alsa_audio:1;
@@ -615,6 +640,7 @@
 		     int num_bufs, int max_pkt_size,
 		     int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
 void em28xx_uninit_isoc(struct em28xx *dev);
+int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
 int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
 int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 void em28xx_wake_i2c(struct em28xx *dev);
@@ -639,7 +665,7 @@
 extern struct em28xx_board em28xx_boards[];
 extern struct usb_device_id em28xx_id_table[];
 extern const unsigned int em28xx_bcount;
-void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
+void em28xx_register_i2c_ir(struct em28xx *dev);
 int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
 void em28xx_release_resources(struct em28xx *dev);
 
@@ -745,17 +771,23 @@
 /*FIXME: maxw should be dependent of alt mode */
 static inline unsigned int norm_maxw(struct em28xx *dev)
 {
+	if (dev->board.is_webcam)
+		return dev->sensor_xres;
+
 	if (dev->board.max_range_640_480)
 		return 640;
-	else
-		return 720;
+
+	return 720;
 }
 
 static inline unsigned int norm_maxh(struct em28xx *dev)
 {
+	if (dev->board.is_webcam)
+		return dev->sensor_yres;
+
 	if (dev->board.max_range_640_480)
 		return 480;
-	else
-		return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
+
+	return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
 }
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -451,27 +451,6 @@
 	return I2C_FUNC_SMBUS_EMUL;
 }
 
-/*
- * attach_inform()
- * gets called when a device attaches to the i2c bus
- * does some basic configuration
- */
-static int attach_inform(struct i2c_client *client)
-{
-	struct em28xx *dev = client->adapter->algo_data;
-	struct IR_i2c *ir = i2c_get_clientdata(client);
-
-	switch (client->addr << 1) {
-	case 0x60:
-	case 0x8e:
-		dprintk1(1, "attach_inform: IR detected (%s).\n", ir->phys);
-		em28xx_set_ir(dev, ir);
-		break;
-	}
-
-	return 0;
-}
-
 static struct i2c_algorithm em28xx_algo = {
 	.master_xfer   = em28xx_i2c_xfer,
 	.functionality = functionality,
@@ -482,7 +461,6 @@
 	.name = "em28xx",
 	.id = I2C_HW_B_EM28XX,
 	.algo = &em28xx_algo,
-	.client_register = attach_inform,
 };
 
 static struct i2c_client em28xx_client_template = {
@@ -505,7 +483,7 @@
 	[0xa0 >> 1] = "eeprom",
 	[0xb0 >> 1] = "tda9874",
 	[0xb8 >> 1] = "tvp5150a",
-	[0xba >> 1] = "tvp5150a",
+	[0xba >> 1] = "webcam sensor or tvp5150a",
 	[0xc0 >> 1] = "tuner (analog)",
 	[0xc2 >> 1] = "tuner (analog)",
 	[0xc4 >> 1] = "tuner (analog)",
@@ -575,6 +553,9 @@
 	if (i2c_scan)
 		em28xx_do_i2c_scan(dev);
 
+	/* Instantiate the IR receiver device, if present */
+	em28xx_register_i2c_ir(dev);
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-input.c linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-input.c
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-input.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-input.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 
 #define i2cdprintk(fmt, arg...) \
 	if (ir_debug) { \
-		printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+		printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
 	}
 
 #define dprintk(fmt, arg...) \
@@ -85,7 +85,7 @@
 	unsigned char b;
 
 	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
 		i2cdprintk("read error\n");
 		return -EIO;
 	}
@@ -114,7 +114,7 @@
 	unsigned char code;
 
 	/* poll IR chip */
-	if (2 != i2c_master_recv(&ir->c, buf, 2))
+	if (2 != i2c_master_recv(ir->c, buf, 2))
 		return -EIO;
 
 	/* Does eliminate repeated parity code */
@@ -147,7 +147,7 @@
 
 	/* poll IR chip */
 
-	if (3 != i2c_master_recv(&ir->c, buf, 3)) {
+	if (3 != i2c_master_recv(ir->c, buf, 3)) {
 		i2cdprintk("read error\n");
 		return -EIO;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-reg.h linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-reg.h
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,22 @@
 #define EM28XX_CHIPCFG_AC97			0x10
 #define EM28XX_CHIPCFG_AUDIOMASK		0x30
 
+#define EM28XX_R01_CHIPCFG2	0x01
+
+/* em28xx Chip Configuration 2 0x01 */
+#define EM28XX_CHIPCFG2_TS_PRESENT		0x10
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK	0x0c /* bits 3-2 */
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF	0x00
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF	0x04
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF	0x08
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF	0x0c
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK	0x03 /* bits 0-1 */
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188	0x00
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376	0x01
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564	0x02
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752	0x03
+
+
 	/* GPIO/GPO registers */
 #define EM2880_R04_GPO	0x04    /* em2880-em2883 only */
 #define EM28XX_R08_GPIO	0x08	/* em2820 or upper */
@@ -160,7 +176,8 @@
 
 /* FIXME: Need to be populated with the other chip ID's */
 enum em28xx_chip_id {
-	CHIP_ID_EM2820 = 18,	/* Also used by em2710 */
+	CHIP_ID_EM2710 = 17,
+	CHIP_ID_EM2820 = 18,	/* Also used by some em2710 */
 	CHIP_ID_EM2840 = 20,
 	CHIP_ID_EM2750 = 33,
 	CHIP_ID_EM2860 = 34,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-video.c linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/em28xx-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/em28xx-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -90,10 +90,35 @@
 /* supported video standards */
 static struct em28xx_fmt format[] = {
 	{
-		.name     = "16bpp YUY2, 4:2:2, packed",
+		.name     = "16 bpp YUY2, 4:2:2, packed",
 		.fourcc   = V4L2_PIX_FMT_YUYV,
 		.depth    = 16,
 		.reg	  = EM28XX_OUTFMT_YUV422_Y0UY1V,
+	}, {
+		.name     = "16 bpp RGB 565, LE",
+		.fourcc   = V4L2_PIX_FMT_RGB565,
+		.depth    = 16,
+		.reg      = EM28XX_OUTFMT_RGB_16_656,
+	}, {
+		.name     = "8 bpp Bayer BGBG..GRGR",
+		.fourcc   = V4L2_PIX_FMT_SBGGR8,
+		.depth    = 8,
+		.reg      = EM28XX_OUTFMT_RGB_8_BGBG,
+	}, {
+		.name     = "8 bpp Bayer GRGR..BGBG",
+		.fourcc   = V4L2_PIX_FMT_SGRBG8,
+		.depth    = 8,
+		.reg      = EM28XX_OUTFMT_RGB_8_GRGR,
+	}, {
+		.name     = "8 bpp Bayer GBGB..RGRG",
+		.fourcc   = V4L2_PIX_FMT_SGBRG8,
+		.depth    = 8,
+		.reg      = EM28XX_OUTFMT_RGB_8_GBGB,
+	}, {
+		.name     = "12 bpp YUV411",
+		.fourcc   = V4L2_PIX_FMT_YUV411P,
+		.depth    = 12,
+		.reg      = EM28XX_OUTFMT_YUV411,
 	},
 };
 
@@ -169,15 +194,24 @@
 	startread = p;
 	remain = len;
 
-	/* Interlaces frame */
-	if (buf->top_field)
+	if (dev->progressive)
 		fieldstart = outp;
-	else
-		fieldstart = outp + bytesperline;
+	else {
+		/* Interlaces two half frames */
+		if (buf->top_field)
+			fieldstart = outp;
+		else
+			fieldstart = outp + bytesperline;
+	}
 
 	linesdone = dma_q->pos / bytesperline;
 	currlinedone = dma_q->pos % bytesperline;
-	offset = linesdone * bytesperline * 2 + currlinedone;
+
+	if (dev->progressive)
+		offset = linesdone * bytesperline + currlinedone;
+	else
+		offset = linesdone * bytesperline * 2 + currlinedone;
+
 	startwrite = fieldstart + offset;
 	lencopy = bytesperline - currlinedone;
 	lencopy = lencopy > remain ? remain : lencopy;
@@ -351,7 +385,7 @@
 			em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
 				       len, (p[2] & 1) ? "odd" : "even");
 
-			if (!(p[2] & 1)) {
+			if (dev->progressive || !(p[2] & 1)) {
 				if (buf != NULL)
 					buffer_filled(dev, dma_q, buf);
 				get_next_buf(dma_q, &buf);
@@ -632,8 +666,8 @@
 			unsigned int width, unsigned int height,
 			unsigned int *hscale, unsigned int *vscale)
 {
-	unsigned int          maxw   = norm_maxw(dev);
-	unsigned int          maxh   = norm_maxh(dev);
+	unsigned int          maxw = norm_maxw(dev);
+	unsigned int          maxh = norm_maxh(dev);
 
 	*hscale = (((unsigned long)maxw) << 12) / width - 4096L;
 	if (*hscale >= 0x4000)
@@ -664,7 +698,10 @@
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
 	/* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
-	f->fmt.pix.field = dev->interlaced ?
+	if (dev->progressive)
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+	else
+		f->fmt.pix.field = dev->interlaced ?
 			   V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
 
 	mutex_unlock(&dev->lock);
@@ -687,8 +724,8 @@
 {
 	struct em28xx_fh      *fh    = priv;
 	struct em28xx         *dev   = fh->dev;
-	int                   width  = f->fmt.pix.width;
-	int                   height = f->fmt.pix.height;
+	unsigned int          width  = f->fmt.pix.width;
+	unsigned int          height = f->fmt.pix.height;
 	unsigned int          maxw   = norm_maxw(dev);
 	unsigned int          maxh   = norm_maxh(dev);
 	unsigned int          hscale, vscale;
@@ -701,34 +738,20 @@
 		return -EINVAL;
 	}
 
-	/* width must even because of the YUYV format
-	   height must be even because of interlacing */
-	height &= 0xfffe;
-	width  &= 0xfffe;
-
-	if (unlikely(height < 32))
-		height = 32;
-	if (unlikely(height > maxh))
-		height = maxh;
-	if (unlikely(width < 48))
-		width = 48;
-	if (unlikely(width > maxw))
-		width = maxw;
-
 	if (dev->board.is_em2800) {
 		/* the em2800 can only scale down to 50% */
-		if (height % (maxh / 2))
-			height = maxh;
-		if (width % (maxw / 2))
-			width = maxw;
-		/* according to empiatech support */
-		/* the MaxPacketSize is to small to support */
-		/* framesizes larger than 640x480 @ 30 fps */
-		/* or 640x576 @ 25 fps. As this would cut */
-		/* of a part of the image we prefer */
-		/* 360x576 or 360x480 for now */
+		height = height > (3 * maxh / 4) ? maxh : maxh / 2;
+		width = width > (3 * maxw / 4) ? maxw : maxw / 2;
+		/* According to empiatech support the MaxPacketSize is too small
+		 * to support framesizes larger than 640x480 @ 30 fps or 640x576
+		 * @ 25 fps.  As this would cut of a part of the image we prefer
+		 * 360x576 or 360x480 for now */
 		if (width == maxw && height == maxh)
 			width /= 2;
+	} else {
+		/* width must even because of the YUYV format
+		   height must be even because of interlacing */
+		v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
 	}
 
 	get_scale(dev, width, height, &hscale, &vscale);
@@ -742,7 +765,33 @@
 	f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
 	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	if (dev->progressive)
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+	else
+		f->fmt.pix.field = dev->interlaced ?
+			   V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
+
+	return 0;
+}
+
+static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
+				   unsigned width, unsigned height)
+{
+	struct em28xx_fmt     *fmt;
+
+	fmt = format_by_fourcc(fourcc);
+	if (!fmt)
+		return -EINVAL;
+
+	dev->format = fmt;
+	dev->width  = width;
+	dev->height = height;
+
+	/* set new image size */
+	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+	em28xx_set_alternate(dev);
+	em28xx_resolution_set(dev);
 
 	return 0;
 }
@@ -753,7 +802,6 @@
 	struct em28xx_fh      *fh  = priv;
 	struct em28xx         *dev = fh->dev;
 	int                   rc;
-	struct em28xx_fmt     *fmt;
 
 	rc = check_dev(dev);
 	if (rc < 0)
@@ -763,12 +811,6 @@
 
 	vidioc_try_fmt_vid_cap(file, priv, f);
 
-	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-	if (!fmt) {
-		rc = -EINVAL;
-		goto out;
-	}
-
 	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
 		em28xx_errdev("%s queue busy\n", __func__);
 		rc = -EBUSY;
@@ -781,16 +823,8 @@
 		goto out;
 	}
 
-	/* set new image size */
-	dev->width = f->fmt.pix.width;
-	dev->height = f->fmt.pix.height;
-	dev->format = fmt;
-	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
-
-	em28xx_set_alternate(dev);
-	em28xx_resolution_set(dev);
-
-	rc = 0;
+	rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
+				f->fmt.pix.width, f->fmt.pix.height);
 
 out:
 	mutex_unlock(&dev->lock);
@@ -828,6 +862,41 @@
 	return 0;
 }
 
+static int vidioc_g_parm(struct file *file, void *priv,
+			 struct v4l2_streamparm *p)
+{
+	struct em28xx_fh   *fh  = priv;
+	struct em28xx      *dev = fh->dev;
+	int rc = 0;
+
+	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (dev->board.is_webcam)
+		rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
+						video, g_parm, p);
+	else
+		v4l2_video_std_frame_period(dev->norm,
+						 &p->parm.capture.timeperframe);
+
+	return rc;
+}
+
+static int vidioc_s_parm(struct file *file, void *priv,
+			 struct v4l2_streamparm *p)
+{
+	struct em28xx_fh   *fh  = priv;
+	struct em28xx      *dev = fh->dev;
+
+	if (!dev->board.is_webcam)
+		return -EINVAL;
+
+	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
+}
+
 static const char *iname[] = {
 	[EM28XX_VMUX_COMPOSITE1] = "Composite1",
 	[EM28XX_VMUX_COMPOSITE2] = "Composite2",
@@ -1606,6 +1675,7 @@
 	struct em28xx *dev;
 	enum v4l2_buf_type fh_type;
 	struct em28xx_fh *fh;
+	enum v4l2_field field;
 
 	dev = em28xx_get_device(minor, &fh_type, &radio);
 
@@ -1630,11 +1700,6 @@
 	filp->private_data = fh;
 
 	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
-		dev->width = norm_maxw(dev);
-		dev->height = norm_maxh(dev);
-		dev->hscale = 0;
-		dev->vscale = 0;
-
 		em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
 		em28xx_set_alternate(dev);
 		em28xx_resolution_set(dev);
@@ -1652,8 +1717,13 @@
 
 	dev->users++;
 
+	if (dev->progressive)
+		field = V4L2_FIELD_NONE;
+	else
+		field = V4L2_FIELD_INTERLACED;
+
 	videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
-			NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
+			NULL, &dev->slock, fh->type, field,
 			sizeof(struct em28xx_buffer), fh);
 
 	mutex_unlock(&dev->lock);
@@ -1872,6 +1942,8 @@
 	.vidioc_qbuf                = vidioc_qbuf,
 	.vidioc_dqbuf               = vidioc_dqbuf,
 	.vidioc_s_std               = vidioc_s_std,
+	.vidioc_g_parm		    = vidioc_g_parm,
+	.vidioc_s_parm		    = vidioc_s_parm,
 	.vidioc_enum_input          = vidioc_enum_input,
 	.vidioc_g_input             = vidioc_g_input,
 	.vidioc_s_input             = vidioc_s_input,
@@ -1976,15 +2048,14 @@
 
 	/* set default norm */
 	dev->norm = em28xx_video_template.current_norm;
-	dev->width = norm_maxw(dev);
-	dev->height = norm_maxh(dev);
 	dev->interlaced = EM28XX_INTERLACED_DEFAULT;
-	dev->hscale = 0;
-	dev->vscale = 0;
 	dev->ctl_input = 0;
 
 	/* Analog specific initialization */
 	dev->format = &format[0];
+	em28xx_set_video_format(dev, format[0].fourcc,
+				norm_maxw(dev), norm_maxh(dev));
+
 	video_mux(dev, dev->ctl_input);
 
 	/* Audio defaults */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/em28xx/Kconfig linux-libre-2.6.31-gnu/drivers/media/video/em28xx/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/video/em28xx/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/em28xx/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,8 @@
 	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+	select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO
+
 	---help---
 	  This is a video4linux driver for Empia 28xx based TV cards.
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/conex.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/conex.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/conex.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/conex.c	2009-09-09 18:13:59.000000000 -0400
@@ -846,6 +846,8 @@
 
 	/* create the JPEG header */
 	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (!sd->jpeg_hdr)
+		return -ENOMEM;
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x22);		/* JPEG 411 */
 	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/finepix.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/finepix.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/finepix.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/finepix.c	2009-09-09 18:13:59.000000000 -0400
@@ -168,6 +168,7 @@
 
 	cam->cam_mode = fpix_mode;
 	cam->nmodes = 1;
+	cam->bulk = 1;
 	cam->bulk_size = FPIX_MAX_TRANSFER;
 
 	INIT_WORK(&dev->work_struct, dostream);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/gspca.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/gspca.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/gspca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/gspca.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Main USB camera driver
  *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr)
  *
  * 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
@@ -47,7 +47,7 @@
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 5, 0)
+#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 6, 0)
 
 #ifdef GSPCA_DEBUG
 int gspca_debug = D_ERR | D_PROBE;
@@ -441,7 +441,7 @@
  * look for an input transfer endpoint in an alternate setting
  */
 static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
-					  __u8 xfer)
+					  int xfer)
 {
 	struct usb_host_endpoint *ep;
 	int i, attr;
@@ -449,7 +449,8 @@
 	for (i = 0; i < alt->desc.bNumEndpoints; i++) {
 		ep = &alt->endpoint[i];
 		attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-		if (attr == xfer)
+		if (attr == xfer
+		    && ep->desc.wMaxPacketSize != 0)
 			return ep;
 	}
 	return NULL;
@@ -467,37 +468,28 @@
 {
 	struct usb_interface *intf;
 	struct usb_host_endpoint *ep;
-	int i, ret;
+	int xfer, i, ret;
 
 	intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
 	ep = NULL;
+	xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
+				   : USB_ENDPOINT_XFER_ISOC;
 	i = gspca_dev->alt;			/* previous alt setting */
-
-	/* try isoc */
 	while (--i >= 0) {
-		ep = alt_xfer(&intf->altsetting[i],
-				USB_ENDPOINT_XFER_ISOC);
+		ep = alt_xfer(&intf->altsetting[i], xfer);
 		if (ep)
 			break;
 	}
-
-	/* if no isoc, try bulk (alt 0 only) */
 	if (ep == NULL) {
-		ep = alt_xfer(&intf->altsetting[0],
-				USB_ENDPOINT_XFER_BULK);
-		if (ep == NULL) {
-			err("no transfer endpoint found");
-			return NULL;
-		}
-		i = 0;
-		gspca_dev->bulk = 1;
+		err("no transfer endpoint found");
+		return NULL;
 	}
 	PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
 			i, ep->desc.bEndpointAddress);
-	if (i > 0) {
+	if (gspca_dev->nbalt > 1) {
 		ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
 		if (ret < 0) {
-			err("set interface err %d", ret);
+			err("set alt %d err %d", i, ret);
 			return NULL;
 		}
 	}
@@ -517,13 +509,13 @@
 	/* calculate the packet size and the number of packets */
 	psize = le16_to_cpu(ep->desc.wMaxPacketSize);
 
-	if (!gspca_dev->bulk) {			/* isoc */
+	if (!gspca_dev->cam.bulk) {		/* isoc */
 
 		/* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
 		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-		npkt = ISO_MAX_SIZE / psize;
-		if (npkt > ISO_MAX_PKT)
-			npkt = ISO_MAX_PKT;
+		npkt = gspca_dev->cam.npkt;
+		if (npkt == 0)
+			npkt = 32;		/* default value */
 		bsize = psize * npkt;
 		PDEBUG(D_STREAM,
 			"isoc %d pkts size %d = bsize:%d",
@@ -617,7 +609,7 @@
 			goto out;
 
 		/* clear the bulk endpoint */
-		if (gspca_dev->bulk)
+		if (gspca_dev->cam.bulk)
 			usb_clear_halt(gspca_dev->dev,
 					gspca_dev->urb[0]->pipe);
 
@@ -630,7 +622,7 @@
 		gspca_dev->streaming = 1;
 
 		/* some bulk transfers are started by the subdriver */
-		if (gspca_dev->bulk && gspca_dev->cam.bulk_nurbs == 0)
+		if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0)
 			break;
 
 		/* submit the URBs */
@@ -661,6 +653,8 @@
 {
 	int ret;
 
+	if (gspca_dev->alt == 0)
+		return 0;
 	ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
 	if (ret < 0)
 		PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret);
@@ -733,6 +727,74 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *priv,
+			struct v4l2_dbg_register *reg)
+{
+	int ret;
+	struct gspca_dev *gspca_dev = priv;
+
+	if (!gspca_dev->sd_desc->get_chip_ident)
+		return -EINVAL;
+
+	if (!gspca_dev->sd_desc->get_register)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+		return -ERESTARTSYS;
+	if (gspca_dev->present)
+		ret = gspca_dev->sd_desc->get_register(gspca_dev, reg);
+	else
+		ret = -ENODEV;
+	mutex_unlock(&gspca_dev->usb_lock);
+
+	return ret;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+			struct v4l2_dbg_register *reg)
+{
+	int ret;
+	struct gspca_dev *gspca_dev = priv;
+
+	if (!gspca_dev->sd_desc->get_chip_ident)
+		return -EINVAL;
+
+	if (!gspca_dev->sd_desc->set_register)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+		return -ERESTARTSYS;
+	if (gspca_dev->present)
+		ret = gspca_dev->sd_desc->set_register(gspca_dev, reg);
+	else
+		ret = -ENODEV;
+	mutex_unlock(&gspca_dev->usb_lock);
+
+	return ret;
+}
+#endif
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	int ret;
+	struct gspca_dev *gspca_dev = priv;
+
+	if (!gspca_dev->sd_desc->get_chip_ident)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+		return -ERESTARTSYS;
+	if (gspca_dev->present)
+		ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
+	else
+		ret = -ENODEV;
+	mutex_unlock(&gspca_dev->usb_lock);
+
+	return ret;
+}
+
 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 				struct v4l2_fmtdesc *fmtdesc)
 {
@@ -869,6 +931,32 @@
 	return ret;
 }
 
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	struct gspca_dev *gspca_dev = priv;
+	int i;
+	__u32 index = 0;
+
+	for (i = 0; i < gspca_dev->cam.nmodes; i++) {
+		if (fsize->pixel_format !=
+				gspca_dev->cam.cam_mode[i].pixelformat)
+			continue;
+
+		if (fsize->index == index) {
+			fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+			fsize->discrete.width =
+				gspca_dev->cam.cam_mode[i].width;
+			fsize->discrete.height =
+				gspca_dev->cam.cam_mode[i].height;
+			return 0;
+		}
+		index++;
+	}
+
+	return -EINVAL;
+}
+
 static void gspca_release(struct video_device *vfd)
 {
 	struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev);
@@ -989,43 +1077,52 @@
 	return ret;
 }
 
+static const struct ctrl *get_ctrl(struct gspca_dev *gspca_dev,
+				   int id)
+{
+	const struct ctrl *ctrls;
+	int i;
+
+	for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
+	     i < gspca_dev->sd_desc->nctrls;
+	     i++, ctrls++) {
+		if (gspca_dev->ctrl_dis & (1 << i))
+			continue;
+		if (id == ctrls->qctrl.id)
+			return ctrls;
+	}
+	return NULL;
+}
+
 static int vidioc_queryctrl(struct file *file, void *priv,
 			   struct v4l2_queryctrl *q_ctrl)
 {
 	struct gspca_dev *gspca_dev = priv;
-	int i, ix;
+	const struct ctrl *ctrls;
+	int i;
 	u32 id;
 
-	ix = -1;
+	ctrls = NULL;
 	id = q_ctrl->id;
 	if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
 		id &= V4L2_CTRL_ID_MASK;
 		id++;
 		for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
-			if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
+			if (gspca_dev->ctrl_dis & (1 << i))
 				continue;
-			if (ix < 0) {
-				ix = i;
+			if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
 				continue;
-			}
-			if (gspca_dev->sd_desc->ctrls[i].qctrl.id
-				    > gspca_dev->sd_desc->ctrls[ix].qctrl.id)
+			if (ctrls && gspca_dev->sd_desc->ctrls[i].qctrl.id
+					    > ctrls->qctrl.id)
 				continue;
-			ix = i;
-		}
-	}
-	for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
-		if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
-			ix = i;
-			break;
+			ctrls = &gspca_dev->sd_desc->ctrls[i];
 		}
+	} else {
+		ctrls = get_ctrl(gspca_dev, id);
 	}
-	if (ix < 0)
+	if (ctrls == NULL)
 		return -EINVAL;
-	memcpy(q_ctrl, &gspca_dev->sd_desc->ctrls[ix].qctrl,
-		sizeof *q_ctrl);
-	if (gspca_dev->ctrl_dis & (1 << ix))
-		q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+	memcpy(q_ctrl, ctrls, sizeof *q_ctrl);
 	return 0;
 }
 
@@ -1034,56 +1131,45 @@
 {
 	struct gspca_dev *gspca_dev = priv;
 	const struct ctrl *ctrls;
-	int i, ret;
+	int ret;
 
-	for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
-	     i < gspca_dev->sd_desc->nctrls;
-	     i++, ctrls++) {
-		if (ctrl->id != ctrls->qctrl.id)
-			continue;
-		if (gspca_dev->ctrl_dis & (1 << i))
-			return -EINVAL;
-		if (ctrl->value < ctrls->qctrl.minimum
-		    || ctrl->value > ctrls->qctrl.maximum)
-			return -ERANGE;
-		PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
-		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
-			return -ERESTARTSYS;
-		if (gspca_dev->present)
-			ret = ctrls->set(gspca_dev, ctrl->value);
-		else
-			ret = -ENODEV;
-		mutex_unlock(&gspca_dev->usb_lock);
-		return ret;
-	}
-	return -EINVAL;
+	ctrls = get_ctrl(gspca_dev, ctrl->id);
+	if (ctrls == NULL)
+		return -EINVAL;
+
+	if (ctrl->value < ctrls->qctrl.minimum
+	    || ctrl->value > ctrls->qctrl.maximum)
+		return -ERANGE;
+	PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
+	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+		return -ERESTARTSYS;
+	if (gspca_dev->present)
+		ret = ctrls->set(gspca_dev, ctrl->value);
+	else
+		ret = -ENODEV;
+	mutex_unlock(&gspca_dev->usb_lock);
+	return ret;
 }
 
 static int vidioc_g_ctrl(struct file *file, void *priv,
 			 struct v4l2_control *ctrl)
 {
 	struct gspca_dev *gspca_dev = priv;
-
 	const struct ctrl *ctrls;
-	int i, ret;
+	int ret;
 
-	for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
-	     i < gspca_dev->sd_desc->nctrls;
-	     i++, ctrls++) {
-		if (ctrl->id != ctrls->qctrl.id)
-			continue;
-		if (gspca_dev->ctrl_dis & (1 << i))
-			return -EINVAL;
-		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
-			return -ERESTARTSYS;
-		if (gspca_dev->present)
-			ret = ctrls->get(gspca_dev, &ctrl->value);
-		else
-			ret = -ENODEV;
-		mutex_unlock(&gspca_dev->usb_lock);
-		return ret;
-	}
-	return -EINVAL;
+	ctrls = get_ctrl(gspca_dev, ctrl->id);
+	if (ctrls == NULL)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+		return -ERESTARTSYS;
+	if (gspca_dev->present)
+		ret = ctrls->get(gspca_dev, &ctrl->value);
+	else
+		ret = -ENODEV;
+	mutex_unlock(&gspca_dev->usb_lock);
+	return ret;
 }
 
 /*fixme: have an audio flag in gspca_dev?*/
@@ -1864,6 +1950,12 @@
 	.vidioc_g_parm		= vidioc_g_parm,
 	.vidioc_s_parm		= vidioc_s_parm,
 	.vidioc_s_std		= vidioc_s_std,
+	.vidioc_enum_framesizes = vidioc_enum_framesizes,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register	= vidioc_g_register,
+	.vidioc_s_register	= vidioc_s_register,
+#endif
+	.vidioc_g_chip_ident	= vidioc_g_chip_ident,
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 	.vidiocgmbuf          = vidiocgmbuf,
 #endif
@@ -1943,7 +2035,7 @@
 
 	/* init video stuff */
 	memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
-	gspca_dev->vdev.parent = &dev->dev;
+	gspca_dev->vdev.parent = &intf->dev;
 	gspca_dev->module = module;
 	gspca_dev->present = 1;
 	ret = video_register_device(&gspca_dev->vdev,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/gspca.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/gspca.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/gspca.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/gspca.h	2009-09-09 18:13:59.000000000 -0400
@@ -44,8 +44,6 @@
 #define GSPCA_MAX_FRAMES 16	/* maximum number of video frame buffers */
 /* image transfers */
 #define MAX_NURBS 4		/* max number of URBs */
-#define ISO_MAX_PKT 32		/* max number of packets in an ISOC transfer */
-#define ISO_MAX_SIZE 0x8000	/* max size of one URB buffer (32 Kb) */
 
 /* device information - set at probe time */
 struct cam {
@@ -56,6 +54,9 @@
 				 * - cannot be > MAX_NURBS
 				 * - when 0 and bulk_size != 0 means
 				 *   1 URB and submit done by subdriver */
+	u8 bulk;		/* image transfer by 0:isoc / 1:bulk */
+	u8 npkt;		/* number of packets in an ISOC message
+				 * 0 is the default value: 32 packets */
 	u32 input_flags;	/* value for ENUM_INPUT status flags */
 };
 
@@ -68,6 +69,10 @@
 typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
 typedef int (*cam_jpg_op) (struct gspca_dev *,
 				struct v4l2_jpegcompression *);
+typedef int (*cam_reg_op) (struct gspca_dev *,
+				struct v4l2_dbg_register *);
+typedef int (*cam_ident_op) (struct gspca_dev *,
+				struct v4l2_dbg_chip_ident *);
 typedef int (*cam_streamparm_op) (struct gspca_dev *,
 				  struct v4l2_streamparm *);
 typedef int (*cam_qmnu_op) (struct gspca_dev *,
@@ -104,6 +109,11 @@
 	cam_qmnu_op querymenu;
 	cam_streamparm_op get_streamparm;
 	cam_streamparm_op set_streamparm;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	cam_reg_op set_register;
+	cam_reg_op get_register;
+#endif
+	cam_ident_op get_chip_ident;
 };
 
 /* packet types when moving from iso buf to frame buf */
@@ -168,7 +178,6 @@
 	__u8 iface;			/* USB interface number */
 	__u8 alt;			/* USB alternate setting */
 	__u8 nbalt;			/* number of USB alternate settings */
-	u8 bulk;			/* image transfer by 0:isoc / 1:bulk */
 };
 
 int gspca_dev_probe(struct usb_interface *intf,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/Kconfig linux-libre-2.6.31-gnu/drivers/media/video/gspca/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -102,6 +102,22 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_pac7311.
 
+config USB_GSPCA_SN9C20X
+       tristate "SN9C20X USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+	 Say Y here if you want support for cameras based on the
+	 sn9c20x chips (SN9C201 and SN9C202).
+
+	 To compile this driver as a module, choose M here: the
+	 module will be called gspca_sn9c20x.
+
+config USB_GSPCA_SN9C20X_EVDEV
+       bool "Enable evdev support"
+	depends on USB_GSPCA_SN9C20X && INPUT
+       ---help---
+	 Say Y here in order to enable evdev support for sn9c20x webcam button.
+
 config USB_GSPCA_SONIXB
 	tristate "SONIX Bayer USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_bridge.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_bridge.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_bridge.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_bridge.h	2009-09-09 18:13:59.000000000 -0400
@@ -45,6 +45,15 @@
 #define M5602_XB_SEN_CLK_DIV		0x15
 #define M5602_XB_AUD_CLK_CTRL		0x16
 #define M5602_XB_AUD_CLK_DIV		0x17
+#define M5602_OB_AC_LINK_STATE		0x22
+#define M5602_OB_PCM_SLOT_INDEX		0x24
+#define M5602_OB_GPIO_SLOT_INDEX	0x25
+#define M5602_OB_ACRX_STATUS_ADDRESS_H	0x28
+#define M5602_OB_ACRX_STATUS_DATA_L	0x29
+#define M5602_OB_ACRX_STATUS_DATA_H	0x2a
+#define M5602_OB_ACTX_COMMAND_ADDRESS	0x31
+#define M5602_OB_ACRX_COMMAND_DATA_L	0x32
+#define M5602_OB_ACTX_COMMAND_DATA_H	0X33
 #define M5602_XB_DEVCTR1		0x41
 #define M5602_XB_EPSETR0		0x42
 #define M5602_XB_EPAFCTR		0x47
@@ -77,7 +86,18 @@
 #define M5602_XB_GPIO_EN_L		0x75
 #define M5602_XB_GPIO_DAT		0x76
 #define M5602_XB_GPIO_DIR		0x77
-#define M5602_XB_MISC_CTL		0x70
+#define M5602_XB_SEN_CLK_CONTROL	0x80
+#define M5602_XB_SEN_CLK_DIVISION	0x81
+#define M5602_XB_CPR_CLK_CONTROL	0x82
+#define M5602_XB_CPR_CLK_DIVISION	0x83
+#define M5602_XB_MCU_CLK_CONTROL	0x84
+#define M5602_XB_MCU_CLK_DIVISION	0x85
+#define M5602_XB_DCT_CLK_CONTROL	0x86
+#define M5602_XB_DCT_CLK_DIVISION	0x87
+#define M5602_XB_EC_CLK_CONTROL		0x88
+#define M5602_XB_EC_CLK_DIVISION	0x89
+#define M5602_XB_LBUF_CLK_CONTROL	0x8a
+#define M5602_XB_LBUF_CLK_DIVISION	0x8b
 
 #define I2C_BUSY 0x80
 
@@ -128,10 +148,10 @@
 };
 
 int m5602_read_bridge(
-	struct sd *sd, u8 address, u8 *i2c_data);
+	struct sd *sd, const u8 address, u8 *i2c_data);
 
 int m5602_write_bridge(
-	struct sd *sd, u8 address, u8 i2c_data);
+	struct sd *sd, const u8 address, const u8 i2c_data);
 
 int m5602_write_sensor(struct sd *sd, const u8 address,
 		       u8 *i2c_data, const u8 len);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_core.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
  */
 
 #include "m5602_ov9650.h"
+#include "m5602_ov7660.h"
 #include "m5602_mt9m111.h"
 #include "m5602_po1030.h"
 #include "m5602_s5k83a.h"
@@ -35,7 +36,7 @@
 MODULE_DEVICE_TABLE(usb, m5602_table);
 
 /* Reads a byte from the m5602 */
-int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
+int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
 {
 	int err;
 	struct usb_device *udev = sd->gspca_dev.dev;
@@ -56,7 +57,7 @@
 }
 
 /* Writes a byte to to the m5602 */
-int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
+int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
 {
 	int err;
 	struct usb_device *udev = sd->gspca_dev.dev;
@@ -80,6 +81,17 @@
 	return (err < 0) ? err : 0;
 }
 
+int m5602_wait_for_i2c(struct sd *sd)
+{
+	int err;
+	u8 data;
+
+	do {
+		err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data);
+	} while ((data & I2C_BUSY) && !err);
+	return err;
+}
+
 int m5602_read_sensor(struct sd *sd, const u8 address,
 		       u8 *i2c_data, const u8 len)
 {
@@ -88,9 +100,7 @@
 	if (!len || len > sd->sensor->i2c_regW)
 		return -EINVAL;
 
-	do {
-		err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
-	} while ((*i2c_data & I2C_BUSY) && !err);
+	err = m5602_wait_for_i2c(sd);
 	if (err < 0)
 		return err;
 
@@ -103,21 +113,25 @@
 	if (err < 0)
 		return err;
 
+	/* Sensors with registers that are of only
+	   one byte width are differently read */
+
+	/* FIXME: This works with the ov9650, but has issues with the po1030 */
 	if (sd->sensor->i2c_regW == 1) {
-		err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, len);
+		err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1);
 		if (err < 0)
 			return err;
 
 		err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
-		if (err < 0)
-			return err;
 	} else {
 		err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
-		if (err < 0)
-			return err;
 	}
 
 	for (i = 0; (i < len) && !err; i++) {
+		err = m5602_wait_for_i2c(sd);
+		if (err < 0)
+			return err;
+
 		err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
 
 		PDEBUG(D_CONF, "Reading sensor register "
@@ -206,6 +220,11 @@
 	if (!sd->sensor->probe(sd))
 		return 0;
 
+	/* Try the ov7660 */
+	sd->sensor = &ov7660;
+	if (!sd->sensor->probe(sd))
+		return 0;
+
 	/* Try the s5k83a */
 	sd->sensor = &s5k83a;
 	if (!sd->sensor->probe(sd))
@@ -409,8 +428,9 @@
 MODULE_LICENSE("GPL");
 module_param(force_sensor, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(force_sensor,
-		"force detection of sensor, "
-		"1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030");
+		"forces detection of a sensor, "
+		"1 = OV9650, 2 = S5K83A, 3 = S5K4AA, "
+		"4 = MT9M111, 5 = PO1030, 6 = OV7660");
 
 module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,23 @@
 
 #include "m5602_mt9m111.h"
 
+static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 val);
+static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
+					  __s32 *val);
+static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+
 static struct v4l2_pix_format mt9m111_modes[] = {
 	{
 		640,
@@ -32,6 +49,7 @@
 };
 
 const static struct ctrl mt9m111_ctrls[] = {
+#define VFLIP_IDX 0
 	{
 		{
 			.id		= V4L2_CID_VFLIP,
@@ -44,7 +62,9 @@
 		},
 		.set = mt9m111_set_vflip,
 		.get = mt9m111_get_vflip
-	}, {
+	},
+#define HFLIP_IDX 1
+	{
 		{
 			.id             = V4L2_CID_HFLIP,
 			.type           = V4L2_CTRL_TYPE_BOOLEAN,
@@ -56,7 +76,9 @@
 		},
 		.set = mt9m111_set_hflip,
 		.get = mt9m111_get_hflip
-	}, {
+	},
+#define GAIN_IDX 2
+	{
 		{
 			.id             = V4L2_CID_GAIN,
 			.type           = V4L2_CTRL_TYPE_INTEGER,
@@ -64,21 +86,80 @@
 			.minimum        = 0,
 			.maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
 			.step           = 1,
-			.default_value  = DEFAULT_GAIN,
+			.default_value  = MT9M111_DEFAULT_GAIN,
 			.flags          = V4L2_CTRL_FLAG_SLIDER
 		},
 		.set = mt9m111_set_gain,
 		.get = mt9m111_get_gain
-	}
+	},
+#define AUTO_WHITE_BALANCE_IDX 3
+	{
+		{
+			.id             = V4L2_CID_AUTO_WHITE_BALANCE,
+			.type           = V4L2_CTRL_TYPE_BOOLEAN,
+			.name           = "auto white balance",
+			.minimum        = 0,
+			.maximum        = 1,
+			.step           = 1,
+			.default_value  = 0,
+		},
+		.set = mt9m111_set_auto_white_balance,
+		.get = mt9m111_get_auto_white_balance
+	},
+#define GREEN_BALANCE_IDX 4
+	{
+		{
+			.id 		= M5602_V4L2_CID_GREEN_BALANCE,
+			.type 		= V4L2_CTRL_TYPE_INTEGER,
+			.name 		= "green balance",
+			.minimum 	= 0x00,
+			.maximum 	= 0x7ff,
+			.step 		= 0x1,
+			.default_value 	= MT9M111_GREEN_GAIN_DEFAULT,
+			.flags         	= V4L2_CTRL_FLAG_SLIDER
+		},
+		.set = mt9m111_set_green_balance,
+		.get = mt9m111_get_green_balance
+	},
+#define BLUE_BALANCE_IDX 5
+	{
+		{
+			.id 		= V4L2_CID_BLUE_BALANCE,
+			.type 		= V4L2_CTRL_TYPE_INTEGER,
+			.name 		= "blue balance",
+			.minimum 	= 0x00,
+			.maximum 	= 0x7ff,
+			.step 		= 0x1,
+			.default_value 	= MT9M111_BLUE_GAIN_DEFAULT,
+			.flags         	= V4L2_CTRL_FLAG_SLIDER
+		},
+		.set = mt9m111_set_blue_balance,
+		.get = mt9m111_get_blue_balance
+	},
+#define RED_BALANCE_IDX 5
+	{
+		{
+			.id 		= V4L2_CID_RED_BALANCE,
+			.type 		= V4L2_CTRL_TYPE_INTEGER,
+			.name 		= "red balance",
+			.minimum 	= 0x00,
+			.maximum 	= 0x7ff,
+			.step 		= 0x1,
+			.default_value 	= MT9M111_RED_GAIN_DEFAULT,
+			.flags         	= V4L2_CTRL_FLAG_SLIDER
+		},
+		.set = mt9m111_set_red_balance,
+		.get = mt9m111_get_red_balance
+	},
 };
 
-
 static void mt9m111_dump_registers(struct sd *sd);
 
 int mt9m111_probe(struct sd *sd)
 {
 	u8 data[2] = {0x00, 0x00};
 	int i;
+	s32 *sensor_settings;
 
 	if (force_sensor) {
 		if (force_sensor == MT9M111_SENSOR) {
@@ -117,16 +198,27 @@
 	return -ENODEV;
 
 sensor_found:
+	sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
+				  GFP_KERNEL);
+	if (!sensor_settings)
+		return -ENOMEM;
+
 	sd->gspca_dev.cam.cam_mode = mt9m111_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
 	sd->desc->ctrls = mt9m111_ctrls;
 	sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
+
+	for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
+		sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
+	sd->sensor_priv = sensor_settings;
+
 	return 0;
 }
 
 int mt9m111_init(struct sd *sd)
 {
 	int i, err = 0;
+	s32 *sensor_settings = sd->sensor_priv;
 
 	/* Init the sensor */
 	for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
@@ -147,36 +239,154 @@
 	if (dump_sensor)
 		mt9m111_dump_registers(sd);
 
-	return (err < 0) ? err : 0;
+	err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+	if (err < 0)
+		return err;
+
+	err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+	if (err < 0)
+		return err;
+
+	err = mt9m111_set_green_balance(&sd->gspca_dev,
+					 sensor_settings[GREEN_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = mt9m111_set_blue_balance(&sd->gspca_dev,
+					 sensor_settings[BLUE_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = mt9m111_set_red_balance(&sd->gspca_dev,
+					sensor_settings[RED_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
 }
 
-int mt9m111_power_down(struct sd *sd)
+int mt9m111_start(struct sd *sd)
 {
-	return 0;
+	int i, err = 0;
+	u8 data[2];
+	struct cam *cam = &sd->gspca_dev.cam;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
+	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+
+	for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
+		if (start_mt9m111[i][0] == BRIDGE) {
+			err = m5602_write_bridge(sd,
+				start_mt9m111[i][1],
+				start_mt9m111[i][2]);
+		} else {
+			data[0] = start_mt9m111[i][2];
+			data[1] = start_mt9m111[i][3];
+			err = m5602_write_sensor(sd,
+				start_mt9m111[i][1], data, 2);
+		}
+	}
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < 2 && !err; i++)
+		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < 2 && !err; i++)
+		err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+				 (width >> 8) & 0xff);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+	if (err < 0)
+		return err;
+
+	switch (width) {
+	case 640:
+		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+		data[0] = MT9M111_RMB_OVER_SIZED;
+		data[1] = MT9M111_RMB_ROW_SKIP_2X |
+			  MT9M111_RMB_COLUMN_SKIP_2X |
+			  (sensor_settings[VFLIP_IDX] << 0) |
+			  (sensor_settings[HFLIP_IDX] << 1);
+
+		err = m5602_write_sensor(sd,
+					 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+		break;
+
+	case 320:
+		PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
+		data[0] = MT9M111_RMB_OVER_SIZED;
+		data[1] = MT9M111_RMB_ROW_SKIP_4X |
+				MT9M111_RMB_COLUMN_SKIP_4X |
+				(sensor_settings[VFLIP_IDX] << 0) |
+				(sensor_settings[HFLIP_IDX] << 1);
+		err = m5602_write_sensor(sd,
+					 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+		break;
+	}
+	return err;
 }
 
-int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+void mt9m111_disconnect(struct sd *sd)
+{
+	sd->sensor = NULL;
+	kfree(sd->sensor_priv);
+}
+
+static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
-				  data, 2);
-	*val = data[0] & MT9M111_RMB_MIRROR_ROWS;
+	*val = sensor_settings[VFLIP_IDX];
 	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
-	return err;
+	return 0;
 }
 
-int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
 	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 
+	sensor_settings[VFLIP_IDX] = val;
+
+	/* The mt9m111 is flipped by default */
+	val = !val;
+
 	/* Set the correct page map */
 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
 	if (err < 0)
@@ -186,34 +396,37 @@
 	if (err < 0)
 		return err;
 
-	data[0] = (data[0] & 0xfe) | val;
+	data[1] = (data[1] & 0xfe) | val;
 	err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
 				   data, 2);
 	return err;
 }
 
-int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
-				  data, 2);
-	*val = data[0] & MT9M111_RMB_MIRROR_COLS;
+	*val = sensor_settings[HFLIP_IDX];
 	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 
-	return err;
+	return 0;
 }
 
-int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
 	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
 
+	sensor_settings[HFLIP_IDX] = val;
+
+	/* The mt9m111 is flipped by default */
+	val = !val;
+
 	/* Set the correct page map */
 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
 	if (err < 0)
@@ -223,36 +436,62 @@
 	if (err < 0)
 		return err;
 
-	data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
+	data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
 	err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
 					data, 2);
 	return err;
 }
 
-int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err, tmp;
-	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
-	tmp = ((data[1] << 8) | data[0]);
+	*val = sensor_settings[GAIN_IDX];
+	PDEBUG(D_V4L2, "Read gain %d", *val);
 
-	*val = ((tmp & (1 << 10)) * 2) |
-	      ((tmp & (1 <<  9)) * 2) |
-	      ((tmp & (1 <<  8)) * 2) |
-	       (tmp & 0x7f);
+	return 0;
+}
 
-	PDEBUG(D_V4L2, "Read gain %d", *val);
+static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
+					  __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+	int err;
+	u8 data[2];
 
+	err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
+	if (err < 0)
+		return err;
+
+	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
+	data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
+
+	err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
+
+	PDEBUG(D_V4L2, "Set auto white balance %d", val);
 	return err;
 }
 
-int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
+					  __s32 *val) {
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Read auto white balance %d", *val);
+	return 0;
+}
+
+static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err, tmp;
 	u8 data[2] = {0x00, 0x00};
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[GAIN_IDX] = val;
 
 	/* Set the correct page map */
 	err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
@@ -275,8 +514,8 @@
 	else
 		tmp = val;
 
-	data[1] = (tmp & 0xff00) >> 8;
-	data[0] = (tmp & 0xff);
+	data[1] = (tmp & 0xff);
+	data[0] = (tmp & 0xff00) >> 8;
 	PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
 	       data[1], data[0]);
 
@@ -286,6 +525,89 @@
 	return err;
 }
 
+static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+	int err;
+	u8 data[2];
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[GREEN_BALANCE_IDX] = val;
+	data[1] = (val & 0xff);
+	data[0] = (val & 0xff00) >> 8;
+
+	PDEBUG(D_V4L2, "Set green balance %d", val);
+	err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
+				 data, 2);
+	if (err < 0)
+		return err;
+
+	return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
+				  data, 2);
+}
+
+static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[GREEN_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Read green balance %d", *val);
+	return 0;
+}
+
+static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+	u8 data[2];
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[BLUE_BALANCE_IDX] = val;
+	data[1] = (val & 0xff);
+	data[0] = (val & 0xff00) >> 8;
+
+	PDEBUG(D_V4L2, "Set blue balance %d", val);
+
+	return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
+				  data, 2);
+}
+
+static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[BLUE_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Read blue balance %d", *val);
+	return 0;
+}
+
+static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+	u8 data[2];
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[RED_BALANCE_IDX] = val;
+	data[1] = (val & 0xff);
+	data[0] = (val & 0xff00) >> 8;
+
+	PDEBUG(D_V4L2, "Set red balance %d", val);
+
+	return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
+				  data, 2);
+}
+
+static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[RED_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Read red balance %d", *val);
+	return 0;
+}
+
 static void mt9m111_dump_registers(struct sd *sd)
 {
 	u8 address, value[2] = {0x00, 0x00};
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_mt9m111.h	2009-09-09 18:13:59.000000000 -0400
@@ -37,7 +37,6 @@
 #define MT9M111_SC_VBLANK_CONTEXT_A		0x08
 #define MT9M111_SC_SHUTTER_WIDTH		0x09
 #define MT9M111_SC_ROW_SPEED			0x0a
-
 #define MT9M111_SC_EXTRA_DELAY			0x0b
 #define MT9M111_SC_SHUTTER_DELAY		0x0c
 #define MT9M111_SC_RESET			0x0d
@@ -50,9 +49,6 @@
 #define MT9M111_SC_GREEN_2_GAIN			0x2e
 #define MT9M111_SC_GLOBAL_GAIN			0x2f
 
-#define MT9M111_RMB_MIRROR_ROWS			(1 << 0)
-#define MT9M111_RMB_MIRROR_COLS			(1 << 1)
-
 #define MT9M111_CONTEXT_CONTROL			0xc8
 #define MT9M111_PAGE_MAP			0xf0
 #define MT9M111_BYTEWISE_ADDRESS		0xf1
@@ -74,8 +70,37 @@
 #define MT9M111_COLORPIPE			0x01
 #define MT9M111_CAMERA_CONTROL			0x02
 
+#define MT9M111_RESET 				(1 << 0)
+#define MT9M111_RESTART				(1 << 1)
+#define MT9M111_ANALOG_STANDBY			(1 << 2)
+#define MT9M111_CHIP_ENABLE			(1 << 3)
+#define MT9M111_CHIP_DISABLE			(0 << 3)
+#define MT9M111_OUTPUT_DISABLE			(1 << 4)
+#define MT9M111_SHOW_BAD_FRAMES			(1 << 0)
+#define MT9M111_RESTART_BAD_FRAMES		(1 << 1)
+#define MT9M111_SYNCHRONIZE_CHANGES		(1 << 7)
+
+#define MT9M111_RMB_OVER_SIZED			(1 << 0)
+#define MT9M111_RMB_MIRROR_ROWS			(1 << 0)
+#define MT9M111_RMB_MIRROR_COLS			(1 << 1)
+#define MT9M111_RMB_ROW_SKIP_2X			(1 << 2)
+#define MT9M111_RMB_COLUMN_SKIP_2X		(1 << 3)
+#define MT9M111_RMB_ROW_SKIP_4X			(1 << 4)
+#define MT9M111_RMB_COLUMN_SKIP_4X		(1 << 5)
+
+#define MT9M111_COLOR_MATRIX_BYPASS		(1 << 4)
+#define MT9M111_SEL_CONTEXT_B			(1 << 3)
+
+#define MT9M111_TRISTATE_PIN_IN_STANDBY		(1 << 1)
+#define MT9M111_SOC_SOFT_STANDBY		(1 << 0)
+
+#define MT9M111_2D_DEFECT_CORRECTION_ENABLE	(1 << 0)
+
 #define INITIAL_MAX_GAIN			64
-#define DEFAULT_GAIN 				283
+#define MT9M111_DEFAULT_GAIN 			283
+#define MT9M111_GREEN_GAIN_DEFAULT		0x20
+#define MT9M111_BLUE_GAIN_DEFAULT		0x20
+#define MT9M111_RED_GAIN_DEFAULT		0x20
 
 /*****************************************************************************/
 
@@ -85,16 +110,10 @@
 
 int mt9m111_probe(struct sd *sd);
 int mt9m111_init(struct sd *sd);
-int mt9m111_power_down(struct sd *sd);
-
-int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+int mt9m111_start(struct sd *sd);
+void mt9m111_disconnect(struct sd *sd);
 
-const static struct m5602_sensor mt9m111 = {
+static const struct m5602_sensor mt9m111 = {
 	.name = "MT9M111",
 
 	.i2c_slave_id = 0xba,
@@ -102,7 +121,8 @@
 
 	.probe = mt9m111_probe,
 	.init = mt9m111_init,
-	.power_down = mt9m111_power_down
+	.disconnect = mt9m111_disconnect,
+	.start = mt9m111_start,
 };
 
 static const unsigned char preinit_mt9m111[][4] =
@@ -117,7 +137,14 @@
 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
 
 	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
+	{SENSOR, MT9M111_SC_RESET,
+		MT9M111_RESET |
+		MT9M111_RESTART |
+		MT9M111_ANALOG_STANDBY |
+		MT9M111_CHIP_DISABLE,
+		MT9M111_SHOW_BAD_FRAMES |
+		MT9M111_RESTART_BAD_FRAMES |
+		MT9M111_SYNCHRONIZE_CHANGES},
 
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
@@ -145,731 +172,42 @@
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
-	{SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
-	{SENSOR, MT9M111_SC_RESET, 0xff, 0xde},
-	{SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
-	{SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
-
-	{SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff},
 
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
 	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
-
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
-	{SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
-	{SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
-
-	{SENSOR, 0xcd, 0x00, 0x0e},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
-	{SENSOR, 0xd0, 0x00, 0x40},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
-	{SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-	{SENSOR, 0x33, 0x03, 0x49},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-
-	{SENSOR, 0x33, 0x03, 0x49},
-	{SENSOR, 0x34, 0xc0, 0x19},
-	{SENSOR, 0x3f, 0x20, 0x20},
-	{SENSOR, 0x40, 0x20, 0x20},
-	{SENSOR, 0x5a, 0xc0, 0x0a},
-	{SENSOR, 0x70, 0x7b, 0x0a},
-	{SENSOR, 0x71, 0xff, 0x00},
-	{SENSOR, 0x72, 0x19, 0x0e},
-	{SENSOR, 0x73, 0x18, 0x0f},
-	{SENSOR, 0x74, 0x57, 0x32},
-	{SENSOR, 0x75, 0x56, 0x34},
-	{SENSOR, 0x76, 0x73, 0x35},
-	{SENSOR, 0x77, 0x30, 0x12},
-	{SENSOR, 0x78, 0x79, 0x02},
-	{SENSOR, 0x79, 0x75, 0x06},
-	{SENSOR, 0x7a, 0x77, 0x0a},
-	{SENSOR, 0x7b, 0x78, 0x09},
-	{SENSOR, 0x7c, 0x7d, 0x06},
-	{SENSOR, 0x7d, 0x31, 0x10},
-	{SENSOR, 0x7e, 0x00, 0x7e},
-	{SENSOR, 0x80, 0x59, 0x04},
-	{SENSOR, 0x81, 0x59, 0x04},
-	{SENSOR, 0x82, 0x57, 0x0a},
-	{SENSOR, 0x83, 0x58, 0x0b},
-	{SENSOR, 0x84, 0x47, 0x0c},
-	{SENSOR, 0x85, 0x48, 0x0e},
-	{SENSOR, 0x86, 0x5b, 0x02},
-	{SENSOR, 0x87, 0x00, 0x5c},
-	{SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
-	{SENSOR, 0x60, 0x00, 0x80},
-	{SENSOR, 0x61, 0x00, 0x00},
-	{SENSOR, 0x62, 0x00, 0x00},
-	{SENSOR, 0x63, 0x00, 0x00},
-	{SENSOR, 0x64, 0x00, 0x00},
-
-	{SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
-	{SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
-	{SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
-	{SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
-	{SENSOR, 0x30, 0x04, 0x00},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
-	{SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
-	{SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
-
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
-	{SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
-	{SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
-	{SENSOR, 0xcd, 0x00, 0x0e},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
-	{SENSOR, 0xd0, 0x00, 0x40},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
-	{SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-	{SENSOR, 0x33, 0x03, 0x49},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-
-	{SENSOR, 0x33, 0x03, 0x49},
-	{SENSOR, 0x34, 0xc0, 0x19},
-	{SENSOR, 0x3f, 0x20, 0x20},
-	{SENSOR, 0x40, 0x20, 0x20},
-	{SENSOR, 0x5a, 0xc0, 0x0a},
-	{SENSOR, 0x70, 0x7b, 0x0a},
-	{SENSOR, 0x71, 0xff, 0x00},
-	{SENSOR, 0x72, 0x19, 0x0e},
-	{SENSOR, 0x73, 0x18, 0x0f},
-	{SENSOR, 0x74, 0x57, 0x32},
-	{SENSOR, 0x75, 0x56, 0x34},
-	{SENSOR, 0x76, 0x73, 0x35},
-	{SENSOR, 0x77, 0x30, 0x12},
-	{SENSOR, 0x78, 0x79, 0x02},
-	{SENSOR, 0x79, 0x75, 0x06},
-	{SENSOR, 0x7a, 0x77, 0x0a},
-	{SENSOR, 0x7b, 0x78, 0x09},
-	{SENSOR, 0x7c, 0x7d, 0x06},
-	{SENSOR, 0x7d, 0x31, 0x10},
-	{SENSOR, 0x7e, 0x00, 0x7e},
-	{SENSOR, 0x80, 0x59, 0x04},
-	{SENSOR, 0x81, 0x59, 0x04},
-	{SENSOR, 0x82, 0x57, 0x0a},
-	{SENSOR, 0x83, 0x58, 0x0b},
-	{SENSOR, 0x84, 0x47, 0x0c},
-	{SENSOR, 0x85, 0x48, 0x0e},
-	{SENSOR, 0x86, 0x5b, 0x02},
-	{SENSOR, 0x87, 0x00, 0x5c},
-	{SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
-	{SENSOR, 0x60, 0x00, 0x80},
-	{SENSOR, 0x61, 0x00, 0x00},
-	{SENSOR, 0x62, 0x00, 0x00},
-	{SENSOR, 0x63, 0x00, 0x00},
-	{SENSOR, 0x64, 0x00, 0x00},
-
-	{SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
-	{SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
-	{SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
-	{SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
-	{SENSOR, 0x30, 0x04, 0x00},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
-	{SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
-	{SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
 	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
 
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
 	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
 	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
 	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
 	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+	{SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00,
+			MT9M111_CP_OPERATING_MODE_CTL},
 	{SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00,
+				MT9M111_2D_DEFECT_CORRECTION_ENABLE},
+	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00,
+				MT9M111_2D_DEFECT_CORRECTION_ENABLE},
 	{SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
 	{SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
 	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
 	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
 	{SENSOR, 0xcd, 0x00, 0x0e},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
 	{SENSOR, 0xd0, 0x00, 0x40},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
-	{SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-	{SENSOR, 0x33, 0x03, 0x49},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
 
-	{SENSOR, 0x33, 0x03, 0x49},
-	{SENSOR, 0x34, 0xc0, 0x19},
-	{SENSOR, 0x3f, 0x20, 0x20},
-	{SENSOR, 0x40, 0x20, 0x20},
-	{SENSOR, 0x5a, 0xc0, 0x0a},
-	{SENSOR, 0x70, 0x7b, 0x0a},
-	{SENSOR, 0x71, 0xff, 0x00},
-	{SENSOR, 0x72, 0x19, 0x0e},
-	{SENSOR, 0x73, 0x18, 0x0f},
-	{SENSOR, 0x74, 0x57, 0x32},
-	{SENSOR, 0x75, 0x56, 0x34},
-	{SENSOR, 0x76, 0x73, 0x35},
-	{SENSOR, 0x77, 0x30, 0x12},
-	{SENSOR, 0x78, 0x79, 0x02},
-	{SENSOR, 0x79, 0x75, 0x06},
-	{SENSOR, 0x7a, 0x77, 0x0a},
-	{SENSOR, 0x7b, 0x78, 0x09},
-	{SENSOR, 0x7c, 0x7d, 0x06},
-	{SENSOR, 0x7d, 0x31, 0x10},
-	{SENSOR, 0x7e, 0x00, 0x7e},
-	{SENSOR, 0x80, 0x59, 0x04},
-	{SENSOR, 0x81, 0x59, 0x04},
-	{SENSOR, 0x82, 0x57, 0x0a},
-	{SENSOR, 0x83, 0x58, 0x0b},
-	{SENSOR, 0x84, 0x47, 0x0c},
-	{SENSOR, 0x85, 0x48, 0x0e},
-	{SENSOR, 0x86, 0x5b, 0x02},
-	{SENSOR, 0x87, 0x00, 0x5c},
-	{SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
-	{SENSOR, 0x60, 0x00, 0x80},
-	{SENSOR, 0x61, 0x00, 0x00},
-	{SENSOR, 0x62, 0x00, 0x00},
-	{SENSOR, 0x63, 0x00, 0x00},
-	{SENSOR, 0x64, 0x00, 0x00},
-
-	{SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
-	{SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
-	{SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
-	{SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
-	{SENSOR, 0x30, 0x04, 0x00},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
-	{SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
-	{SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
-	{SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, 0xcd, 0x00, 0x0e},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, 0xd0, 0x00, 0x40},
 	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
 	{SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
 	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, 0x33, 0x03, 0x49},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-
-	{SENSOR, 0x33, 0x03, 0x49},
-	{SENSOR, 0x34, 0xc0, 0x19},
-	{SENSOR, 0x3f, 0x20, 0x20},
-	{SENSOR, 0x40, 0x20, 0x20},
-	{SENSOR, 0x5a, 0xc0, 0x0a},
-	{SENSOR, 0x70, 0x7b, 0x0a},
-	{SENSOR, 0x71, 0xff, 0x00},
-	{SENSOR, 0x72, 0x19, 0x0e},
-	{SENSOR, 0x73, 0x18, 0x0f},
-	{SENSOR, 0x74, 0x57, 0x32},
-	{SENSOR, 0x75, 0x56, 0x34},
-	{SENSOR, 0x76, 0x73, 0x35},
-	{SENSOR, 0x77, 0x30, 0x12},
-	{SENSOR, 0x78, 0x79, 0x02},
-	{SENSOR, 0x79, 0x75, 0x06},
-	{SENSOR, 0x7a, 0x77, 0x0a},
-	{SENSOR, 0x7b, 0x78, 0x09},
-	{SENSOR, 0x7c, 0x7d, 0x06},
-	{SENSOR, 0x7d, 0x31, 0x10},
-	{SENSOR, 0x7e, 0x00, 0x7e},
-	{SENSOR, 0x80, 0x59, 0x04},
-	{SENSOR, 0x81, 0x59, 0x04},
-	{SENSOR, 0x82, 0x57, 0x0a},
-	{SENSOR, 0x83, 0x58, 0x0b},
-	{SENSOR, 0x84, 0x47, 0x0c},
-	{SENSOR, 0x85, 0x48, 0x0e},
-	{SENSOR, 0x86, 0x5b, 0x02},
-	{SENSOR, 0x87, 0x00, 0x5c},
-	{SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
-	{SENSOR, 0x60, 0x00, 0x80},
-	{SENSOR, 0x61, 0x00, 0x00},
-	{SENSOR, 0x62, 0x00, 0x00},
-	{SENSOR, 0x63, 0x00, 0x00},
-	{SENSOR, 0x64, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
-	{SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
-	{SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
-	{SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
-	{SENSOR, 0x30, 0x04, 0x00},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 
 	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
-	{SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
-
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
-	{SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
-	{SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
-	{SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
-	{SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, 0xcd, 0x00, 0x0e},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, 0xd0, 0x00, 0x40},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
-	{SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-	{SENSOR, 0x33, 0x03, 0x49},
-	{BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
-	{BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
-	{BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
-
 	{SENSOR, 0x33, 0x03, 0x49},
 	{SENSOR, 0x34, 0xc0, 0x19},
 	{SENSOR, 0x3f, 0x20, 0x20},
@@ -898,25 +236,29 @@
 	{SENSOR, 0x85, 0x48, 0x0e},
 	{SENSOR, 0x86, 0x5b, 0x02},
 	{SENSOR, 0x87, 0x00, 0x5c},
-	{SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+	{SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B},
 	{SENSOR, 0x60, 0x00, 0x80},
 	{SENSOR, 0x61, 0x00, 0x00},
 	{SENSOR, 0x62, 0x00, 0x00},
 	{SENSOR, 0x63, 0x00, 0x00},
 	{SENSOR, 0x64, 0x00, 0x00},
 
-	{SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
-	{SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
-	{SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
-	{SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
-	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
-	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
+	{SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */
+	{SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */
+	{SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */
+	{SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */
+	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */
+	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */
+	{SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */
+	{SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */
+	{SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */
 	{SENSOR, 0x30, 0x04, 0x00},
+	/* Set number of blank rows chosen to 400 */
+	{SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
+};
 
+static const unsigned char start_mt9m111[][4] =
+{
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
@@ -928,25 +270,6 @@
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, /* 639*/
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-	/* Set number of blank rows chosen to 400 */
-	{SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
-	/* Set the global gain to 283 (of 512) */
-	{SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63}
 };
 
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,227 @@
+/*
+ * Driver for the ov7660 sensor
+ *
+ * Copyright (C) 2009 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include "m5602_ov7660.h"
+
+static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+const static struct ctrl ov7660_ctrls[] = {
+#define GAIN_IDX 1
+	{
+		{
+			.id		= V4L2_CID_GAIN,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "gain",
+			.minimum	= 0x00,
+			.maximum	= 0xff,
+			.step		= 0x1,
+			.default_value	= OV7660_DEFAULT_GAIN,
+			.flags		= V4L2_CTRL_FLAG_SLIDER
+		},
+		.set = ov7660_set_gain,
+		.get = ov7660_get_gain
+	},
+};
+
+static struct v4l2_pix_format ov7660_modes[] = {
+	{
+		640,
+		480,
+		V4L2_PIX_FMT_SBGGR8,
+		V4L2_FIELD_NONE,
+		.sizeimage =
+			640 * 480,
+		.bytesperline = 640,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0
+	}
+};
+
+static void ov7660_dump_registers(struct sd *sd);
+
+int ov7660_probe(struct sd *sd)
+{
+	int err = 0, i;
+	u8 prod_id = 0, ver_id = 0;
+
+	s32 *sensor_settings;
+
+	if (force_sensor) {
+		if (force_sensor == OV7660_SENSOR) {
+			info("Forcing an %s sensor", ov7660.name);
+			goto sensor_found;
+		}
+		/* If we want to force another sensor,
+		don't try to probe this one */
+		return -ENODEV;
+	}
+
+	/* Do the preinit */
+	for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
+		u8 data[2];
+
+		if (preinit_ov7660[i][0] == BRIDGE) {
+			err = m5602_write_bridge(sd,
+				preinit_ov7660[i][1],
+				preinit_ov7660[i][2]);
+		} else {
+			data[0] = preinit_ov7660[i][2];
+			err = m5602_write_sensor(sd,
+				preinit_ov7660[i][1], data, 1);
+		}
+	}
+	if (err < 0)
+		return err;
+
+	if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
+		return -ENODEV;
+
+	if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
+		return -ENODEV;
+
+	info("Sensor reported 0x%x%x", prod_id, ver_id);
+
+	if ((prod_id == 0x76) && (ver_id == 0x60)) {
+		info("Detected a ov7660 sensor");
+		goto sensor_found;
+	}
+	return -ENODEV;
+
+sensor_found:
+	sensor_settings = kmalloc(
+		ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
+	if (!sensor_settings)
+		return -ENOMEM;
+
+	sd->gspca_dev.cam.cam_mode = ov7660_modes;
+	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
+	sd->desc->ctrls = ov7660_ctrls;
+	sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
+
+	for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
+		sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
+	sd->sensor_priv = sensor_settings;
+
+	return 0;
+}
+
+int ov7660_init(struct sd *sd)
+{
+	int i, err = 0;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	/* Init the sensor */
+	for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
+		u8 data[2];
+
+		if (init_ov7660[i][0] == BRIDGE) {
+			err = m5602_write_bridge(sd,
+				init_ov7660[i][1],
+				init_ov7660[i][2]);
+		} else {
+			data[0] = init_ov7660[i][2];
+			err = m5602_write_sensor(sd,
+					init_ov7660[i][1], data, 1);
+		}
+	}
+
+	if (dump_sensor)
+		ov7660_dump_registers(sd);
+
+	err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+	if (err < 0)
+		return err;
+
+	return err;
+}
+
+int ov7660_start(struct sd *sd)
+{
+	return 0;
+}
+
+int ov7660_stop(struct sd *sd)
+{
+	return 0;
+}
+
+void ov7660_disconnect(struct sd *sd)
+{
+	ov7660_stop(sd);
+
+	sd->sensor = NULL;
+	kfree(sd->sensor_priv);
+}
+
+static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[GAIN_IDX];
+	PDEBUG(D_V4L2, "Read gain %d", *val);
+	return 0;
+}
+
+static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	int err;
+	u8 i2c_data;
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	PDEBUG(D_V4L2, "Setting gain to %d", val);
+
+	sensor_settings[GAIN_IDX] = val;
+
+	err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
+	return err;
+}
+
+static void ov7660_dump_registers(struct sd *sd)
+{
+	int address;
+	info("Dumping the ov7660 register state");
+	for (address = 0; address < 0xa9; address++) {
+		u8 value;
+		m5602_read_sensor(sd, address, &value, 1);
+		info("register 0x%x contains 0x%x",
+		     address, value);
+	}
+
+	info("ov7660 register state dump complete");
+
+	info("Probing for which registers that are read/write");
+	for (address = 0; address < 0xff; address++) {
+		u8 old_value, ctrl_value;
+		u8 test_value[2] = {0xff, 0xff};
+
+		m5602_read_sensor(sd, address, &old_value, 1);
+		m5602_write_sensor(sd, address, test_value, 1);
+		m5602_read_sensor(sd, address, &ctrl_value, 1);
+
+		if (ctrl_value == test_value[0])
+			info("register 0x%x is writeable", address);
+		else
+			info("register 0x%x is read only", address);
+
+		/* Restore original value */
+		m5602_write_sensor(sd, address, &old_value, 1);
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov7660.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,279 @@
+/*
+ * Driver for the ov7660 sensor
+ *
+ * Copyright (C) 2009 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_OV7660_H_
+#define M5602_OV7660_H_
+
+#include "m5602_sensor.h"
+
+#define OV7660_GAIN		0x00
+#define OV7660_BLUE_GAIN	0x01
+#define OV7660_RED_GAIN		0x02
+#define OV7660_VREF		0x03
+#define OV7660_COM1		0x04
+#define OV7660_BAVE		0x05
+#define OV7660_GEAVE		0x06
+#define OV7660_AECHH		0x07
+#define OV7660_RAVE		0x08
+#define OV7660_COM2		0x09
+#define OV7660_PID		0x0a
+#define OV7660_VER		0x0b
+#define OV7660_COM3		0x0c
+#define OV7660_COM4		0x0d
+#define OV7660_COM5		0x0e
+#define OV7660_COM6		0x0f
+#define OV7660_AECH		0x10
+#define OV7660_CLKRC		0x11
+#define OV7660_COM7		0x12
+#define OV7660_COM8		0x13
+#define OV7660_COM9		0x14
+#define OV7660_COM10		0x15
+#define OV7660_RSVD16		0x16
+#define OV7660_HSTART		0x17
+#define OV7660_HSTOP		0x18
+#define OV7660_VSTART		0x19
+#define OV7660_VSTOP		0x1a
+#define OV7660_PSHFT		0x1b
+#define OV7660_MIDH		0x1c
+#define OV7660_MIDL		0x1d
+#define OV7660_MVFP		0x1e
+#define OV7660_LAEC		0x1f
+#define OV7660_BOS		0x20
+#define OV7660_GBOS		0x21
+#define OV7660_GROS		0x22
+#define OV7660_ROS		0x23
+#define OV7660_AEW		0x24
+#define OV7660_AEB		0x25
+#define OV7660_VPT		0x26
+#define OV7660_BBIAS		0x27
+#define OV7660_GbBIAS		0x28
+#define OV7660_RSVD29		0x29
+#define OV7660_RBIAS		0x2c
+#define OV7660_HREF		0x32
+#define OV7660_ADC		0x37
+#define OV7660_OFON 		0x39
+#define OV7660_TSLB 		0x3a
+#define OV7660_COM12 		0x3c
+#define OV7660_COM13 		0x3d
+#define OV7660_LCC1		0x62
+#define OV7660_LCC2		0x63
+#define OV7660_LCC3		0x64
+#define OV7660_LCC4		0x65
+#define OV7660_LCC5		0x66
+#define OV7660_HV 		0x69
+#define OV7660_RSVDA1 		0xa1
+
+#define OV7660_DEFAULT_GAIN		0x0e
+#define OV7660_DEFAULT_RED_GAIN	0x80
+#define OV7660_DEFAULT_BLUE_GAIN 	0x80
+#define OV7660_DEFAULT_SATURATION	0x00
+#define OV7660_DEFAULT_EXPOSURE	0x20
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+
+int ov7660_probe(struct sd *sd);
+int ov7660_init(struct sd *sd);
+int ov7660_start(struct sd *sd);
+int ov7660_stop(struct sd *sd);
+void ov7660_disconnect(struct sd *sd);
+
+const static struct m5602_sensor ov7660 = {
+	.name = "ov7660",
+	.i2c_slave_id = 0x42,
+	.i2c_regW = 1,
+	.probe = ov7660_probe,
+	.init = ov7660_init,
+	.start = ov7660_start,
+	.stop = ov7660_stop,
+	.disconnect = ov7660_disconnect,
+};
+
+static const unsigned char preinit_ov7660[][4] =
+{
+	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+	{SENSOR, OV7660_OFON, 0x0c},
+	{SENSOR, OV7660_COM2, 0x11},
+	{SENSOR, OV7660_COM7, 0x05},
+
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00}
+};
+
+static const unsigned char init_ov7660[][4] =
+{
+	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+	{SENSOR, OV7660_OFON, 0x0c},
+	{SENSOR, OV7660_COM2, 0x11},
+	{SENSOR, OV7660_COM7, 0x05},
+
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x02},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+	{SENSOR, OV7660_AECH, OV7660_DEFAULT_EXPOSURE},
+	{SENSOR, OV7660_COM1, 0x00},
+
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+
+	{SENSOR, OV7660_COM7, 0x80},
+	{SENSOR, OV7660_CLKRC, 0x80},
+	{SENSOR, OV7660_BLUE_GAIN, 0x80},
+	{SENSOR, OV7660_RED_GAIN, 0x80},
+	{SENSOR, OV7660_COM9, 0x4c},
+	{SENSOR, OV7660_OFON, 0x43},
+	{SENSOR, OV7660_COM12, 0x28},
+	{SENSOR, OV7660_COM8, 0x00},
+	{SENSOR, OV7660_COM10, 0x40},
+	{SENSOR, OV7660_HSTART, 0x0c},
+	{SENSOR, OV7660_HSTOP, 0x61},
+	{SENSOR, OV7660_HREF, 0xa4},
+	{SENSOR, OV7660_PSHFT, 0x0b},
+	{SENSOR, OV7660_VSTART, 0x01},
+	{SENSOR, OV7660_VSTOP, 0x7a},
+	{SENSOR, OV7660_VREF, 0x00},
+	{SENSOR, OV7660_COM7, 0x05},
+	{SENSOR, OV7660_COM6, 0x4b},
+	{SENSOR, OV7660_BBIAS, 0x98},
+	{SENSOR, OV7660_GbBIAS, 0x98},
+	{SENSOR, OV7660_RSVD29, 0x98},
+	{SENSOR, OV7660_RBIAS, 0x98},
+	{SENSOR, OV7660_COM1, 0x00},
+	{SENSOR, OV7660_AECH, 0x00},
+	{SENSOR, OV7660_AECHH, 0x00},
+	{SENSOR, OV7660_ADC, 0x04},
+	{SENSOR, OV7660_COM13, 0x00},
+	{SENSOR, OV7660_RSVDA1, 0x23},
+	{SENSOR, OV7660_TSLB, 0x0d},
+	{SENSOR, OV7660_HV, 0x80},
+	{SENSOR, OV7660_LCC1, 0x00},
+	{SENSOR, OV7660_LCC2, 0x00},
+	{SENSOR, OV7660_LCC3, 0x10},
+	{SENSOR, OV7660_LCC4, 0x40},
+	{SENSOR, OV7660_LCC5, 0x01},
+
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+	{BRIDGE, M5602_XB_SIG_INI, 0x01},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+	{BRIDGE, M5602_XB_SIG_INI, 0x00},
+	{BRIDGE, M5602_XB_SIG_INI, 0x02},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x27}, /* 39 */
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0xa7}, /* 679 */
+	{BRIDGE, M5602_XB_SIG_INI, 0x00},
+
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+	{SENSOR, OV7660_AECH, 0x20},
+	{SENSOR, OV7660_COM1, 0x00},
+	{SENSOR, OV7660_OFON, 0x0c},
+	{SENSOR, OV7660_COM2, 0x11},
+	{SENSOR, OV7660_COM7, 0x05},
+	{SENSOR, OV7660_BLUE_GAIN, 0x80},
+	{SENSOR, OV7660_RED_GAIN, 0x80},
+
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,44 +18,87 @@
 
 #include "m5602_ov9650.h"
 
+static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 *val);
+static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 val);
+static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
+
 /* Vertically and horizontally flips the image if matched, needed for machines
    where the sensor is mounted upside down */
 static
     const
 	struct dmi_system_id ov9650_flip_dmi_table[] = {
 	{
-		.ident = "ASUS A6VC",
+		.ident = "ASUS A6Ja",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
+			DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
 		}
 	},
 	{
-		.ident = "ASUS A6VM",
+		.ident = "ASUS A6JC",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
+			DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
 		}
 	},
 	{
-		.ident = "ASUS A6JC",
+		.ident = "ASUS A6K",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
+			DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
 		}
 	},
 	{
-		.ident = "ASUS A6Ja",
+		.ident = "ASUS A6Kt",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
+			DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
 		}
 	},
 	{
-		.ident = "ASUS A6Kt",
+		.ident = "ASUS A6VA",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
+			DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
+		}
+	},
+	{
+
+		.ident = "ASUS A6VC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
+		}
+	},
+	{
+		.ident = "ASUS A6VM",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
+		}
+	},
+	{
+		.ident = "ASUS A7V",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
 		}
 	},
 	{
@@ -68,7 +111,7 @@
 	{}
 };
 
-const static struct ctrl ov9650_ctrls[] = {
+static const struct ctrl ov9650_ctrls[] = {
 #define EXPOSURE_IDX 0
 	{
 		{
@@ -102,6 +145,7 @@
 #define RED_BALANCE_IDX 2
 	{
 		{
+			.id		= V4L2_CID_RED_BALANCE,
 			.type 		= V4L2_CTRL_TYPE_INTEGER,
 			.name 		= "red balance",
 			.minimum 	= 0x00,
@@ -116,6 +160,7 @@
 #define BLUE_BALANCE_IDX 3
 	{
 		{
+			.id		= V4L2_CID_BLUE_BALANCE,
 			.type 		= V4L2_CTRL_TYPE_INTEGER,
 			.name 		= "blue balance",
 			.minimum 	= 0x00,
@@ -182,7 +227,22 @@
 		},
 		.set = ov9650_set_auto_gain,
 		.get = ov9650_get_auto_gain
+	},
+#define AUTO_EXPOSURE_IDX 8
+	{
+		{
+			.id 		= V4L2_CID_EXPOSURE_AUTO,
+			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name 		= "auto exposure",
+			.minimum 	= 0,
+			.maximum 	= 1,
+			.step 		= 1,
+			.default_value 	= 1
+		},
+		.set = ov9650_set_auto_exposure,
+		.get = ov9650_get_auto_exposure
 	}
+
 };
 
 static struct v4l2_pix_format ov9650_modes[] = {
@@ -289,12 +349,6 @@
 	for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
 		sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
 	sd->sensor_priv = sensor_settings;
-
-	if (dmi_check_system(ov9650_flip_dmi_table) && !err) {
-		info("vflip quirk active");
-		sensor_settings[VFLIP_IDX] = 1;
-	}
-
 	return 0;
 }
 
@@ -316,7 +370,8 @@
 			err = m5602_write_bridge(sd, init_ov9650[i][1], data);
 	}
 
-	err = ov9650_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]);
+	err = ov9650_set_exposure(&sd->gspca_dev,
+				   sensor_settings[EXPOSURE_IDX]);
 	if (err < 0)
 		return err;
 
@@ -324,11 +379,13 @@
 	if (err < 0)
 		return err;
 
-	err = ov9650_set_red_balance(&sd->gspca_dev, sensor_settings[RED_BALANCE_IDX]);
+	err = ov9650_set_red_balance(&sd->gspca_dev,
+				      sensor_settings[RED_BALANCE_IDX]);
 	if (err < 0)
 		return err;
 
-	err = ov9650_set_blue_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]);
+	err = ov9650_set_blue_balance(&sd->gspca_dev,
+				       sensor_settings[BLUE_BALANCE_IDX]);
 	if (err < 0)
 		return err;
 
@@ -340,11 +397,18 @@
 	if (err < 0)
 		return err;
 
-	err = ov9650_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+	err = ov9650_set_auto_exposure(&sd->gspca_dev,
+				sensor_settings[AUTO_EXPOSURE_IDX]);
 	if (err < 0)
 		return err;
 
-	err = ov9650_set_auto_gain(&sd->gspca_dev, sensor_settings[AUTO_GAIN_CTRL_IDX]);
+	err = ov9650_set_auto_white_balance(&sd->gspca_dev,
+				sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = ov9650_set_auto_gain(&sd->gspca_dev,
+				sensor_settings[AUTO_GAIN_CTRL_IDX]);
 	return err;
 }
 
@@ -360,7 +424,10 @@
 	int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
 	int hor_offs = OV9650_LEFT_OFFSET;
 
-	if (sensor_settings[VFLIP_IDX])
+	if ((!dmi_check_system(ov9650_flip_dmi_table) &&
+		sensor_settings[VFLIP_IDX]) ||
+		(dmi_check_system(ov9650_flip_dmi_table) &&
+		!sensor_settings[VFLIP_IDX]))
 		ver_offs--;
 
 	if (width <= 320)
@@ -406,6 +473,14 @@
 	if (err < 0)
 		return err;
 
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
+	if (err < 0)
+		return err;
+
 	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
 				 (hor_offs >> 8) & 0xff);
 	if (err < 0)
@@ -425,6 +500,10 @@
 	if (err < 0)
 		return err;
 
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+	if (err < 0)
+		return err;
+
 	switch (width) {
 	case 640:
 		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
@@ -467,32 +546,15 @@
 	return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
 }
 
-int ov9650_power_down(struct sd *sd)
-{
-	int i, err = 0;
-	for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
-		u8 data = power_down_ov9650[i][2];
-		if (power_down_ov9650[i][0] == SENSOR)
-			err = m5602_write_sensor(sd,
-					    power_down_ov9650[i][1], &data, 1);
-		else
-			err = m5602_write_bridge(sd, power_down_ov9650[i][1],
-						 data);
-	}
-
-	return err;
-}
-
 void ov9650_disconnect(struct sd *sd)
 {
 	ov9650_stop(sd);
-	ov9650_power_down(sd);
 
 	sd->sensor = NULL;
 	kfree(sd->sensor_priv);
 }
 
-int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -502,7 +564,7 @@
 	return 0;
 }
 
-int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -532,7 +594,7 @@
 	return err;
 }
 
-int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -542,7 +604,7 @@
 	return 0;
 }
 
-int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
@@ -573,7 +635,7 @@
 	return err;
 }
 
-int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -583,7 +645,7 @@
 	return 0;
 }
 
-int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
@@ -599,7 +661,7 @@
 	return err;
 }
 
-int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -610,7 +672,7 @@
 	return 0;
 }
 
-int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
@@ -626,7 +688,7 @@
 	return err;
 }
 
-int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -636,7 +698,7 @@
 	return 0;
 }
 
-int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
@@ -646,13 +708,20 @@
 	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
 
 	sensor_settings[HFLIP_IDX] = val;
-	i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4);
+
+	if (!dmi_check_system(ov9650_flip_dmi_table))
+		i2c_data = ((val & 0x01) << 5) |
+				(sensor_settings[VFLIP_IDX] << 4);
+	else
+		i2c_data = ((val & 0x01) << 5) |
+				(!sensor_settings[VFLIP_IDX] << 4);
+
 	err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 
 	return err;
 }
 
-int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -663,7 +732,7 @@
 	return 0;
 }
 
-int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
@@ -673,6 +742,9 @@
 	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 	sensor_settings[VFLIP_IDX] = val;
 
+	if (dmi_check_system(ov9650_flip_dmi_table))
+		val = !val;
+
 	i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
 	err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
 	if (err < 0)
@@ -685,48 +757,38 @@
 	return err;
 }
 
-int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
 
-	*val = sensor_settings[GAIN_IDX];
-	PDEBUG(D_V4L2, "Read gain %d", *val);
-
+	*val = sensor_settings[AUTO_EXPOSURE_IDX];
+	PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
 	return 0;
 }
 
-int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
+				    __s32 val)
 {
 	int err;
 	u8 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
 
-	PDEBUG(D_V4L2, "Set gain to %d", val);
-
-	sensor_settings[GAIN_IDX] = val;
-
-	/* Read the OV9650_VREF register first to avoid
-		corrupting the VREF high and low bits */
-	err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
-	if (err < 0)
-		return err;
+	PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
 
-	/* Mask away all uninteresting bits */
-	i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
-	err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+	sensor_settings[AUTO_EXPOSURE_IDX] = val;
+	err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
-	/* The 8 LSBs */
-	i2c_data = val & 0xff;
-	err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+	i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
 
-	return err;
+	return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 }
 
-int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -735,7 +797,8 @@
 	return 0;
 }
 
-int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 val)
 {
 	int err;
 	u8 i2c_data;
@@ -755,7 +818,7 @@
 	return err;
 }
 
-int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	s32 *sensor_settings = sd->sensor_priv;
@@ -765,7 +828,7 @@
 	return 0;
 }
 
-int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 i2c_data;
@@ -780,9 +843,8 @@
 		return err;
 
 	i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
-	err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 
-	return err;
+	return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
 }
 
 static void ov9650_dump_registers(struct sd *sd)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_ov9650.h	2009-09-09 18:13:59.000000000 -0400
@@ -120,6 +120,10 @@
 #define OV9650_SOFT_SLEEP		(1 << 4)
 #define OV9650_OUTPUT_DRIVE_2X		(1 << 0)
 
+#define OV9650_DENOISE_ENABLE		(1 << 5)
+#define OV9650_WHITE_PIXEL_ENABLE	(1 << 1)
+#define OV9650_WHITE_PIXEL_OPTION	(1 << 0)
+
 #define OV9650_LEFT_OFFSET		0x62
 
 #define GAIN_DEFAULT			0x14
@@ -137,29 +141,9 @@
 int ov9650_init(struct sd *sd);
 int ov9650_start(struct sd *sd);
 int ov9650_stop(struct sd *sd);
-int ov9650_power_down(struct sd *sd);
 void ov9650_disconnect(struct sd *sd);
 
-int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val);
-int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
-
-const static struct m5602_sensor ov9650 = {
+static const struct m5602_sensor ov9650 = {
 	.name = "OV9650",
 	.i2c_slave_id = 0x60,
 	.i2c_regW = 1,
@@ -167,7 +151,6 @@
 	.init = ov9650_init,
 	.start = ov9650_start,
 	.stop = ov9650_stop,
-	.power_down = ov9650_power_down,
 	.disconnect = ov9650_disconnect,
 };
 
@@ -219,7 +202,7 @@
 	/* Reset chip */
 	{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
 	/* One extra reset is needed in order to make the sensor behave
-	   properly when resuming from ram */
+	   properly when resuming from ram, could be a timing issue */
 	{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
 
 	/* Enable double clock */
@@ -229,8 +212,7 @@
 
 	/* Set fast AGC/AEC algorithm with unlimited step size */
 	{SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
-			      OV9650_AEC_UNLIM_STEP_SIZE |
-			      OV9650_AWB_EN | OV9650_AGC_EN},
+			      OV9650_AEC_UNLIM_STEP_SIZE},
 
 	{SENSOR, OV9650_CHLF, 0x10},
 	{SENSOR, OV9650_ARBLM, 0xbf},
@@ -301,8 +283,11 @@
 	{SENSOR, OV9650_VREF, 0x10},
 	{SENSOR, OV9650_ADC, 0x04},
 	{SENSOR, OV9650_HV, 0x40},
+
 	/* Enable denoise, and white-pixel erase */
-	{SENSOR, OV9650_COM22, 0x23},
+	{SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
+		 OV9650_WHITE_PIXEL_ENABLE |
+		 OV9650_WHITE_PIXEL_OPTION},
 
 	/* Enable VARIOPIXEL */
 	{SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
@@ -312,26 +297,6 @@
 	{SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
 };
 
-static const unsigned char power_down_ov9650[][3] =
-{
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	{SENSOR, OV9650_COM7, 0x80},
-	{SENSOR, OV9650_OFON, 0xf4},
-	{SENSOR, OV9650_MVFP, 0x80},
-	{SENSOR, OV9650_DBLV, 0x3f},
-	{SENSOR, OV9650_RSVD36, 0x49},
-	{SENSOR, OV9650_COM7, 0x05},
-
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0x06},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-};
-
 static const unsigned char res_init_ov9650[][3] =
 {
 	{SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_po1030.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,29 @@
 
 #include "m5602_po1030.h"
 
+static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 val);
+static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 *val);
+static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
+					 __s32 val);
+static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
+					 __s32 *val);
+
 static struct v4l2_pix_format po1030_modes[] = {
 	{
 		640,
@@ -27,11 +50,12 @@
 		.sizeimage = 640 * 480,
 		.bytesperline = 640,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 0
+		.priv = 2
 	}
 };
 
-const static struct ctrl po1030_ctrls[] = {
+static const struct ctrl po1030_ctrls[] = {
+#define GAIN_IDX 0
 	{
 		{
 			.id 		= V4L2_CID_GAIN,
@@ -45,7 +69,9 @@
 		},
 		.set = po1030_set_gain,
 		.get = po1030_get_gain
-	}, {
+	},
+#define EXPOSURE_IDX 1
+	{
 		{
 			.id 		= V4L2_CID_EXPOSURE,
 			.type 		= V4L2_CTRL_TYPE_INTEGER,
@@ -58,7 +84,9 @@
 		},
 		.set = po1030_set_exposure,
 		.get = po1030_get_exposure
-	}, {
+	},
+#define RED_BALANCE_IDX 2
+	{
 		{
 			.id 		= V4L2_CID_RED_BALANCE,
 			.type 		= V4L2_CTRL_TYPE_INTEGER,
@@ -71,7 +99,9 @@
 		},
 		.set = po1030_set_red_balance,
 		.get = po1030_get_red_balance
-	}, {
+	},
+#define BLUE_BALANCE_IDX 3
+	{
 		{
 			.id 		= V4L2_CID_BLUE_BALANCE,
 			.type 		= V4L2_CTRL_TYPE_INTEGER,
@@ -84,7 +114,9 @@
 		},
 		.set = po1030_set_blue_balance,
 		.get = po1030_get_blue_balance
-	}, {
+	},
+#define HFLIP_IDX 4
+	{
 		{
 			.id 		= V4L2_CID_HFLIP,
 			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
@@ -96,7 +128,9 @@
 		},
 		.set = po1030_set_hflip,
 		.get = po1030_get_hflip
-	}, {
+	},
+#define VFLIP_IDX 5
+	{
 		{
 			.id 		= V4L2_CID_VFLIP,
 			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
@@ -108,14 +142,58 @@
 		},
 		.set = po1030_set_vflip,
 		.get = po1030_get_vflip
-	}
+	},
+#define AUTO_WHITE_BALANCE_IDX 6
+	{
+		{
+			.id 		= V4L2_CID_AUTO_WHITE_BALANCE,
+			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name 		= "auto white balance",
+			.minimum 	= 0,
+			.maximum 	= 1,
+			.step 		= 1,
+			.default_value 	= 0,
+		},
+		.set = po1030_set_auto_white_balance,
+		.get = po1030_get_auto_white_balance
+	},
+#define AUTO_EXPOSURE_IDX 7
+	{
+		{
+			.id 		= V4L2_CID_EXPOSURE_AUTO,
+			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name 		= "auto exposure",
+			.minimum 	= 0,
+			.maximum 	= 1,
+			.step 		= 1,
+			.default_value 	= 0,
+		},
+		.set = po1030_set_auto_exposure,
+		.get = po1030_get_auto_exposure
+	},
+#define GREEN_BALANCE_IDX 8
+	{
+		{
+			.id 		= M5602_V4L2_CID_GREEN_BALANCE,
+			.type 		= V4L2_CTRL_TYPE_INTEGER,
+			.name 		= "green balance",
+			.minimum 	= 0x00,
+			.maximum 	= 0xff,
+			.step 		= 0x1,
+			.default_value 	= PO1030_GREEN_GAIN_DEFAULT,
+			.flags         	= V4L2_CTRL_FLAG_SLIDER
+		},
+		.set = po1030_set_green_balance,
+		.get = po1030_get_green_balance
+	},
 };
 
 static void po1030_dump_registers(struct sd *sd);
 
 int po1030_probe(struct sd *sd)
 {
-	u8 prod_id = 0, ver_id = 0, i;
+	u8 dev_id_h = 0, i;
+	s32 *sensor_settings;
 
 	if (force_sensor) {
 		if (force_sensor == PO1030_SENSOR) {
@@ -139,28 +217,36 @@
 			m5602_write_bridge(sd, preinit_po1030[i][1], data);
 	}
 
-	if (m5602_read_sensor(sd, 0x3, &prod_id, 1))
-		return -ENODEV;
-
-	if (m5602_read_sensor(sd, 0x4, &ver_id, 1))
+	if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
 		return -ENODEV;
 
-	if ((prod_id == 0x02) && (ver_id == 0xef)) {
+	if (dev_id_h == 0x30) {
 		info("Detected a po1030 sensor");
 		goto sensor_found;
 	}
 	return -ENODEV;
 
 sensor_found:
+	sensor_settings = kmalloc(
+		ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
+	if (!sensor_settings)
+		return -ENOMEM;
+
 	sd->gspca_dev.cam.cam_mode = po1030_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
 	sd->desc->ctrls = po1030_ctrls;
 	sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
+
+	for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
+		sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
+	sd->sensor_priv = sensor_settings;
+
 	return 0;
 }
 
 int po1030_init(struct sd *sd)
 {
+	s32 *sensor_settings = sd->sensor_priv;
 	int i, err = 0;
 
 	/* Init the sensor */
@@ -185,47 +271,206 @@
 			return -EINVAL;
 		}
 	}
+	if (err < 0)
+		return err;
 
 	if (dump_sensor)
 		po1030_dump_registers(sd);
 
+	err = po1030_set_exposure(&sd->gspca_dev,
+				   sensor_settings[EXPOSURE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_red_balance(&sd->gspca_dev,
+				      sensor_settings[RED_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_blue_balance(&sd->gspca_dev,
+				      sensor_settings[BLUE_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_green_balance(&sd->gspca_dev,
+				       sensor_settings[GREEN_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_auto_white_balance(&sd->gspca_dev,
+				sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = po1030_set_auto_exposure(&sd->gspca_dev,
+				sensor_settings[AUTO_EXPOSURE_IDX]);
 	return err;
 }
 
-int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+int po1030_start(struct sd *sd)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
-	u8 i2c_data;
-	int err;
+	struct cam *cam = &sd->gspca_dev.cam;
+	int i, err = 0;
+	int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
+	int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+	int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+	u8 data;
 
-	err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H,
-				 &i2c_data, 1);
+	switch (width) {
+	case 320:
+		data = PO1030_SUBSAMPLING;
+		err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = ((width + 3) >> 8) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = (width + 3) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = ((height + 1) >> 8) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = (height + 1) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
+
+		height += 6;
+		width -= 1;
+		break;
+
+	case 640:
+		data = 0;
+		err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = ((width + 7) >> 8) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = (width + 7) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = ((height + 3) >> 8) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
+		if (err < 0)
+			return err;
+
+		data = (height + 3) & 0xff;
+		err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
+
+		height += 12;
+		width -= 2;
+		break;
+	}
+	err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
 	if (err < 0)
 		return err;
-	*val = (i2c_data << 8);
 
-	err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M,
-				 &i2c_data, 1);
-	*val |= i2c_data;
+	err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
+	if (err < 0)
+		return err;
 
-	PDEBUG(D_V4L2, "Exposure read as %d", *val);
+	err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
+				 ((ver_offs >> 8) & 0xff));
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < 2 && !err; i++)
+		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < 2 && !err; i++)
+		err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+
+	for (i = 0; i < 2 && !err; i++)
+		err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+
+	for (i = 0; i < 2 && !err; i++)
+		err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
+	if (err < 0)
+		return err;
 
+	err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
+	if (err < 0)
+		return err;
+
+	err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
 	return err;
 }
 
-int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[EXPOSURE_IDX];
+	PDEBUG(D_V4L2, "Exposure read as %d", *val);
+	return 0;
+}
+
+static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
+	sensor_settings[EXPOSURE_IDX] = val;
 	PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
 
 	i2c_data = ((val & 0xff00) >> 8);
 	PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
 	       i2c_data);
 
-	err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H,
+	err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
 				  &i2c_data, 1);
 	if (err < 0)
 		return err;
@@ -233,167 +478,256 @@
 	i2c_data = (val & 0xff);
 	PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
 	       i2c_data);
-	err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M,
+	err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
 				  &i2c_data, 1);
 
 	return err;
 }
 
-int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	u8 i2c_data;
-	int err;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
-				 &i2c_data, 1);
-	*val = i2c_data;
+	*val = sensor_settings[GAIN_IDX];
 	PDEBUG(D_V4L2, "Read global gain %d", *val);
-
-	return err;
+	return 0;
 }
 
-int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	err = m5602_read_sensor(sd, PO1030_REG_CONTROL2,
+	sensor_settings[GAIN_IDX] = val;
+
+	i2c_data = val & 0xff;
+	PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
+	err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
 				 &i2c_data, 1);
+	return err;
+}
 
-	*val = (i2c_data >> 7) & 0x01 ;
+static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
+	*val = sensor_settings[HFLIP_IDX];
 	PDEBUG(D_V4L2, "Read hflip %d", *val);
 
-	return err;
+	return 0;
 }
 
-int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
+	sensor_settings[HFLIP_IDX] = val;
+
 	PDEBUG(D_V4L2, "Set hflip %d", val);
-	err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
+	err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
 	i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
 
-	err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
+	err = m5602_write_sensor(sd, PO1030_CONTROL2,
 				 &i2c_data, 1);
 
 	return err;
 }
 
-int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	u8 i2c_data;
-	int err;
-
-	err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
-				 &i2c_data, 1);
-
-	*val = (i2c_data >> 6) & 0x01;
+	s32 *sensor_settings = sd->sensor_priv;
 
+	*val = sensor_settings[VFLIP_IDX];
 	PDEBUG(D_V4L2, "Read vflip %d", *val);
 
-	return err;
+	return 0;
 }
 
-int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
+	sensor_settings[VFLIP_IDX] = val;
+
 	PDEBUG(D_V4L2, "Set vflip %d", val);
-	err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
+	err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
 	if (err < 0)
 		return err;
 
 	i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
 
-	err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
+	err = m5602_write_sensor(sd, PO1030_CONTROL2,
 				 &i2c_data, 1);
 
 	return err;
 }
 
-int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[RED_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Read red gain %d", *val);
+	return 0;
+}
+
+static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
+	sensor_settings[RED_BALANCE_IDX] = val;
+
 	i2c_data = val & 0xff;
-	PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
-	err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN,
+	PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
+	err = m5602_write_sensor(sd, PO1030_RED_GAIN,
 				  &i2c_data, 1);
 	return err;
 }
 
-int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	u8 i2c_data;
-	int err;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, PO1030_REG_RED_GAIN,
-				 &i2c_data, 1);
-	*val = i2c_data;
-	PDEBUG(D_V4L2, "Read red gain %d", *val);
-	return err;
+	*val = sensor_settings[BLUE_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Read blue gain %d", *val);
+
+	return 0;
 }
 
-int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
+	sensor_settings[BLUE_BALANCE_IDX] = val;
+
 	i2c_data = val & 0xff;
-	PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
-	err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN,
+	PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
+	err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
 				  &i2c_data, 1);
+
 	return err;
 }
 
-int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[GREEN_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Read green gain %d", *val);
+
+	return 0;
+}
+
+static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
 
-	err = m5602_read_sensor(sd, PO1030_REG_BLUE_GAIN,
+	sensor_settings[GREEN_BALANCE_IDX] = val;
+	i2c_data = val & 0xff;
+	PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
+
+	err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
+			   &i2c_data, 1);
+	if (err < 0)
+		return err;
+
+	return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
 				 &i2c_data, 1);
-	*val = i2c_data;
-	PDEBUG(D_V4L2, "Read blue gain %d", *val);
+}
 
-	return err;
+static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+	PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
+
+	return 0;
 }
 
-int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
+					 __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 i2c_data;
 	int err;
-	i2c_data = val & 0xff;
-	PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
-	err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN,
-				  &i2c_data, 1);
 
+	sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
+
+	err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+	if (err < 0)
+		return err;
+
+	PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+	i2c_data = (i2c_data & 0xfe) | (val & 0x01);
+	err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
 	return err;
 }
 
-int po1030_power_down(struct sd *sd)
+static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
+				    __s32 *val)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[AUTO_EXPOSURE_IDX];
+	PDEBUG(D_V4L2, "Auto exposure is %d", *val);
 	return 0;
 }
 
+static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
+				    __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+	u8 i2c_data;
+	int err;
+
+	sensor_settings[AUTO_EXPOSURE_IDX] = val;
+	err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+	if (err < 0)
+		return err;
+
+	PDEBUG(D_V4L2, "Set auto exposure to %d", val);
+	i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
+	return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+}
+
+void po1030_disconnect(struct sd *sd)
+{
+	sd->sensor = NULL;
+	kfree(sd->sensor_priv);
+}
+
 static void po1030_dump_registers(struct sd *sd)
 {
 	int address;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_po1030.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_po1030.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_po1030.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_po1030.h	2009-09-09 18:13:59.000000000 -0400
@@ -25,98 +25,123 @@
 
 /*****************************************************************************/
 
-#define PO1030_REG_DEVID_H		0x00
-#define PO1030_REG_DEVID_L		0x01
-#define PO1030_REG_FRAMEWIDTH_H		0x04
-#define PO1030_REG_FRAMEWIDTH_L		0x05
-#define PO1030_REG_FRAMEHEIGHT_H	0x06
-#define PO1030_REG_FRAMEHEIGHT_L	0x07
-#define PO1030_REG_WINDOWX_H		0x08
-#define PO1030_REG_WINDOWX_L		0x09
-#define PO1030_REG_WINDOWY_H		0x0a
-#define PO1030_REG_WINDOWY_L		0x0b
-#define PO1030_REG_WINDOWWIDTH_H	0x0c
-#define PO1030_REG_WINDOWWIDTH_L	0x0d
-#define PO1030_REG_WINDOWHEIGHT_H	0x0e
-#define PO1030_REG_WINDOWHEIGHT_L	0x0f
+#define PO1030_DEVID_H		0x00
+#define PO1030_DEVID_L		0x01
+#define PO1030_FRAMEWIDTH_H	0x04
+#define PO1030_FRAMEWIDTH_L	0x05
+#define PO1030_FRAMEHEIGHT_H	0x06
+#define PO1030_FRAMEHEIGHT_L	0x07
+#define PO1030_WINDOWX_H	0x08
+#define PO1030_WINDOWX_L	0x09
+#define PO1030_WINDOWY_H	0x0a
+#define PO1030_WINDOWY_L	0x0b
+#define PO1030_WINDOWWIDTH_H	0x0c
+#define PO1030_WINDOWWIDTH_L	0x0d
+#define PO1030_WINDOWHEIGHT_H	0x0e
+#define PO1030_WINDOWHEIGHT_L	0x0f
 
-#define PO1030_REG_GLOBALIBIAS		0x12
-#define PO1030_REG_PIXELIBIAS		0x13
+#define PO1030_GLOBALIBIAS	0x12
+#define PO1030_PIXELIBIAS	0x13
 
-#define PO1030_REG_GLOBALGAIN		0x15
-#define PO1030_REG_RED_GAIN		0x16
-#define PO1030_REG_GREEN_1_GAIN		0x17
-#define PO1030_REG_BLUE_GAIN		0x18
-#define PO1030_REG_GREEN_2_GAIN		0x19
+#define PO1030_GLOBALGAIN	0x15
+#define PO1030_RED_GAIN		0x16
+#define PO1030_GREEN_1_GAIN	0x17
+#define PO1030_BLUE_GAIN	0x18
+#define PO1030_GREEN_2_GAIN	0x19
 
-#define PO1030_REG_INTEGLINES_H		0x1a
-#define PO1030_REG_INTEGLINES_M		0x1b
-#define PO1030_REG_INTEGLINES_L		0x1c
+#define PO1030_INTEGLINES_H	0x1a
+#define PO1030_INTEGLINES_M	0x1b
+#define PO1030_INTEGLINES_L	0x1c
 
-#define PO1030_REG_CONTROL1		0x1d
-#define PO1030_REG_CONTROL2		0x1e
-#define PO1030_REG_CONTROL3		0x1f
-#define PO1030_REG_CONTROL4		0x20
+#define PO1030_CONTROL1		0x1d
+#define PO1030_CONTROL2		0x1e
+#define PO1030_CONTROL3		0x1f
+#define PO1030_CONTROL4		0x20
 
-#define PO1030_REG_PERIOD50_H		0x23
-#define PO1030_REG_PERIOD50_L		0x24
-#define PO1030_REG_PERIOD60_H		0x25
-#define PO1030_REG_PERIOD60_L		0x26
-#define PO1030_REG_REGCLK167		0x27
-#define PO1030_REG_DELTA50		0x28
-#define PO1030_REG_DELTA60		0x29
+#define PO1030_PERIOD50_H	0x23
+#define PO1030_PERIOD50_L	0x24
+#define PO1030_PERIOD60_H	0x25
+#define PO1030_PERIOD60_L	0x26
+#define PO1030_REGCLK167	0x27
+#define PO1030_FLICKER_DELTA50	0x28
+#define PO1030_FLICKERDELTA60	0x29
 
-#define PO1030_REG_ADCOFFSET		0x2c
+#define PO1030_ADCOFFSET	0x2c
 
 /* Gamma Correction Coeffs */
-#define PO1030_REG_GC0			0x2d
-#define PO1030_REG_GC1			0x2e
-#define PO1030_REG_GC2			0x2f
-#define PO1030_REG_GC3			0x30
-#define PO1030_REG_GC4			0x31
-#define PO1030_REG_GC5			0x32
-#define PO1030_REG_GC6			0x33
-#define PO1030_REG_GC7			0x34
+#define PO1030_GC0		0x2d
+#define PO1030_GC1		0x2e
+#define PO1030_GC2		0x2f
+#define PO1030_GC3		0x30
+#define PO1030_GC4		0x31
+#define PO1030_GC5		0x32
+#define PO1030_GC6		0x33
+#define PO1030_GC7		0x34
 
 /* Color Transform Matrix */
-#define PO1030_REG_CT0			0x35
-#define PO1030_REG_CT1			0x36
-#define PO1030_REG_CT2			0x37
-#define PO1030_REG_CT3			0x38
-#define PO1030_REG_CT4			0x39
-#define PO1030_REG_CT5			0x3a
-#define PO1030_REG_CT6			0x3b
-#define PO1030_REG_CT7			0x3c
-#define PO1030_REG_CT8			0x3d
+#define PO1030_CT0		0x35
+#define PO1030_CT1		0x36
+#define PO1030_CT2		0x37
+#define PO1030_CT3		0x38
+#define PO1030_CT4		0x39
+#define PO1030_CT5		0x3a
+#define PO1030_CT6		0x3b
+#define PO1030_CT7		0x3c
+#define PO1030_CT8		0x3d
 
-#define PO1030_REG_AUTOCTRL1		0x3e
-#define PO1030_REG_AUTOCTRL2		0x3f
+#define PO1030_AUTOCTRL1	0x3e
+#define PO1030_AUTOCTRL2	0x3f
 
-#define PO1030_REG_YTARGET		0x40
-#define PO1030_REG_GLOBALGAINMIN	0x41
-#define PO1030_REG_GLOBALGAINMAX	0x42
+#define PO1030_YTARGET		0x40
+#define PO1030_GLOBALGAINMIN	0x41
+#define PO1030_GLOBALGAINMAX	0x42
+
+#define PO1030_AWB_RED_TUNING	0x47
+#define PO1030_AWB_BLUE_TUNING	0x48
 
 /* Output format control */
-#define PO1030_REG_OUTFORMCTRL1		0x5a
-#define PO1030_REG_OUTFORMCTRL2		0x5b
-#define PO1030_REG_OUTFORMCTRL3		0x5c
-#define PO1030_REG_OUTFORMCTRL4		0x5d
-#define PO1030_REG_OUTFORMCTRL5		0x5e
+#define PO1030_OUTFORMCTRL1	0x5a
+#define PO1030_OUTFORMCTRL2	0x5b
+#define PO1030_OUTFORMCTRL3	0x5c
+#define PO1030_OUTFORMCTRL4	0x5d
+#define PO1030_OUTFORMCTRL5	0x5e
 
-/* Imaging coefficients */
-#define PO1030_REG_YBRIGHT		0x73
-#define PO1030_REG_YCONTRAST		0x74
-#define PO1030_REG_YSATURATION		0x75
+#define PO1030_EDGE_ENH_OFF	0x5f
+#define PO1030_EGA		0x60
 
-#define PO1030_HFLIP			(1 << 7)
-#define PO1030_VFLIP			(1 << 6)
+#define PO1030_Cb_U_GAIN	0x63
+#define PO1030_Cr_V_GAIN	0x64
+
+#define PO1030_YCONTRAST	0x74
+#define PO1030_YSATURATION	0x75
+
+#define PO1030_HFLIP		(1 << 7)
+#define PO1030_VFLIP		(1 << 6)
+
+#define PO1030_HREF_ENABLE	(1 << 6)
+
+#define PO1030_RAW_RGB_BAYER	0x4
+
+#define PO1030_FRAME_EQUAL	(1 << 3)
+#define PO1030_AUTO_SUBSAMPLING (1 << 4)
+
+#define PO1030_WEIGHT_WIN_2X	(1 << 3)
+
+#define PO1030_SHUTTER_MODE	(1 << 6)
+#define PO1030_AUTO_SUBSAMPLING	(1 << 4)
+#define PO1030_FRAME_EQUAL	(1 << 3)
+
+#define PO1030_SENSOR_RESET	(1 << 5)
+
+#define PO1030_SUBSAMPLING	(1 << 6)
 
 /*****************************************************************************/
 
 #define PO1030_GLOBAL_GAIN_DEFAULT	0x12
 #define PO1030_EXPOSURE_DEFAULT		0x0085
-#define PO1030_BLUE_GAIN_DEFAULT 	0x40
-#define PO1030_RED_GAIN_DEFAULT 	0x40
+#define PO1030_BLUE_GAIN_DEFAULT 	0x36
+#define PO1030_RED_GAIN_DEFAULT 	0x36
+#define PO1030_GREEN_GAIN_DEFAULT 	0x40
 
 /*****************************************************************************/
 
@@ -126,20 +151,8 @@
 
 int po1030_probe(struct sd *sd);
 int po1030_init(struct sd *sd);
-int po1030_power_down(struct sd *sd);
-
-int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_start(struct sd *sd);
+void po1030_disconnect(struct sd *sd);
 
 static const struct m5602_sensor po1030 = {
 	.name = "PO1030",
@@ -149,7 +162,8 @@
 
 	.probe = po1030_probe,
 	.init = po1030_init,
-	.power_down = po1030_power_down,
+	.start = po1030_start,
+	.disconnect = po1030_disconnect,
 };
 
 static const unsigned char preinit_po1030[][3] =
@@ -159,248 +173,103 @@
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
 	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-
-	{SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
-
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
 	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00},
 
-	{SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+	{SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
 
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x00}
 };
 
-static const unsigned char init_po1030[][4] =
+static const unsigned char init_po1030[][3] =
 {
 	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
 	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
-	/*sequence 1*/
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
-
 	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
 	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-	/*end of sequence 1*/
 
-	/*sequence 2 (same as stop sequence)*/
-	{SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	/*end of sequence 2*/
-
-	/*sequence 5*/
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00},
-	/*end of sequence 5*/
-
-	/*sequence 2 stop */
-	{SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+	{SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
 
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x04},
 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	/*end of sequence 2 stop */
-
-/* ---------------------------------
- * end of init - begin of start
- * --------------------------------- */
-
-	/*sequence 3*/
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-	/*end of sequence 3*/
-	/*sequence 4*/
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
 
-	{SENSOR, PO1030_REG_AUTOCTRL2, 0x04},
+	{SENSOR, PO1030_AUTOCTRL2, 0x04},
+
+	{SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER},
+	{SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X},
+
+	{SENSOR, PO1030_CONTROL2, 0x03},
+	{SENSOR, 0x21, 0x90},
+	{SENSOR, PO1030_YTARGET, 0x60},
+	{SENSOR, 0x59, 0x13},
+	{SENSOR, PO1030_OUTFORMCTRL1, PO1030_HREF_ENABLE},
+	{SENSOR, PO1030_EDGE_ENH_OFF, 0x00},
+	{SENSOR, PO1030_EGA, 0x80},
+	{SENSOR, 0x78, 0x14},
+	{SENSOR, 0x6f, 0x01},
+	{SENSOR, PO1030_GLOBALGAINMAX, 0x14},
+	{SENSOR, PO1030_Cb_U_GAIN, 0x38},
+	{SENSOR, PO1030_Cr_V_GAIN, 0x38},
+	{SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE |
+				  PO1030_AUTO_SUBSAMPLING |
+				  PO1030_FRAME_EQUAL},
+	{SENSOR, PO1030_GC0, 0x10},
+	{SENSOR, PO1030_GC1, 0x20},
+	{SENSOR, PO1030_GC2, 0x40},
+	{SENSOR, PO1030_GC3, 0x60},
+	{SENSOR, PO1030_GC4, 0x80},
+	{SENSOR, PO1030_GC5, 0xa0},
+	{SENSOR, PO1030_GC6, 0xc0},
+	{SENSOR, PO1030_GC7, 0xff},
 
 	/* Set the width to 751 */
-	{SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
-	{SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef},
+	{SENSOR, PO1030_FRAMEWIDTH_H, 0x02},
+	{SENSOR, PO1030_FRAMEWIDTH_L, 0xef},
 
 	/* Set the height to 540 */
-	{SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02},
-	{SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c},
+	{SENSOR, PO1030_FRAMEHEIGHT_H, 0x02},
+	{SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c},
 
 	/* Set the x window to 1 */
-	{SENSOR, PO1030_REG_WINDOWX_H, 0x00},
-	{SENSOR, PO1030_REG_WINDOWX_L, 0x01},
+	{SENSOR, PO1030_WINDOWX_H, 0x00},
+	{SENSOR, PO1030_WINDOWX_L, 0x01},
 
 	/* Set the y window to 1 */
-	{SENSOR, PO1030_REG_WINDOWY_H, 0x00},
-	{SENSOR, PO1030_REG_WINDOWY_L, 0x01},
-
-	{SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02},
-	{SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87},
-	{SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01},
-	{SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3},
-
-	{SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
-	{SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
-	{SENSOR, PO1030_REG_AUTOCTRL1, 0x08},
-	{SENSOR, PO1030_REG_CONTROL2, 0x03},
-	{SENSOR, 0x21, 0x90},
-	{SENSOR, PO1030_REG_YTARGET, 0x60},
-	{SENSOR, 0x59, 0x13},
-	{SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40},
-	{SENSOR, 0x5f, 0x00},
-	{SENSOR, 0x60, 0x80},
-	{SENSOR, 0x78, 0x14},
-	{SENSOR, 0x6f, 0x01},
-	{SENSOR, PO1030_REG_CONTROL1, 0x18},
-	{SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14},
-	{SENSOR, 0x63, 0x38},
-	{SENSOR, 0x64, 0x38},
-	{SENSOR, PO1030_REG_CONTROL1, 0x58},
-	{SENSOR, PO1030_REG_RED_GAIN, 0x30},
-	{SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30},
-	{SENSOR, PO1030_REG_BLUE_GAIN, 0x30},
-	{SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30},
-	{SENSOR, PO1030_REG_GC0, 0x10},
-	{SENSOR, PO1030_REG_GC1, 0x20},
-	{SENSOR, PO1030_REG_GC2, 0x40},
-	{SENSOR, PO1030_REG_GC3, 0x60},
-	{SENSOR, PO1030_REG_GC4, 0x80},
-	{SENSOR, PO1030_REG_GC5, 0xa0},
-	{SENSOR, PO1030_REG_GC6, 0xc0},
-	{SENSOR, PO1030_REG_GC7, 0xff},
-	/*end of sequence 4*/
-	/*sequence 5*/
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x7e},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00},
-	/*end of sequence 5*/
-
-	/*sequence 6*/
-	/* Changing 40 in f0 the image becomes green in bayer mode and red in
-	 * rgb mode */
-	{SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT},
-	/* in changing 40 in f0 the image becomes green in bayer mode and red in
-	 * rgb mode */
-	{SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT},
+	{SENSOR, PO1030_WINDOWY_H, 0x00},
+	{SENSOR, PO1030_WINDOWY_L, 0x01},
 
 	/* with a very low lighted environment increase the exposure but
 	 * decrease the FPS (Frame Per Second) */
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
 
-	/* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in
-	 * low lighted environment (f0 is more than ff ?)*/
-	{SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2)
-		& 0xff)},
-
-	/* Controls middle exposure, use only in high lighted environment */
-	{SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff},
-
-	/* Controls clarity (not sure) */
-	{SENSOR, PO1030_REG_INTEGLINES_L, 0x00},
-	/* Controls gain (the image is more lighted) */
-	{SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT},
-
-	/* Sets the width */
-	{SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
-	{SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}
-	/*end of sequence 6*/
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
 };
 
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.c	2009-09-09 18:13:59.000000000 -0400
@@ -18,6 +18,19 @@
 
 #include "m5602_s5k4aa.h"
 
+static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+
 static
     const
 	struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
@@ -46,6 +59,18 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
 		}
+	}, {
+		.ident = "MSI L735",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
+		}
+	}, {
+		.ident = "Lenovo Y300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
+		}
 	},
 	{ }
 };
@@ -61,10 +86,22 @@
 		.bytesperline = 640,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 0
+	},
+	{
+		1280,
+		1024,
+		V4L2_PIX_FMT_SBGGR8,
+		V4L2_FIELD_NONE,
+		.sizeimage =
+			1280 * 1024,
+		.bytesperline = 1280,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0
 	}
 };
 
-const static struct ctrl s5k4aa_ctrls[] = {
+static const struct ctrl s5k4aa_ctrls[] = {
+#define VFLIP_IDX 0
 	{
 		{
 			.id 		= V4L2_CID_VFLIP,
@@ -77,8 +114,9 @@
 		},
 		.set = s5k4aa_set_vflip,
 		.get = s5k4aa_get_vflip
-
-	}, {
+	},
+#define HFLIP_IDX 1
+	{
 		{
 			.id 		= V4L2_CID_HFLIP,
 			.type 		= V4L2_CTRL_TYPE_BOOLEAN,
@@ -90,8 +128,9 @@
 		},
 		.set = s5k4aa_set_hflip,
 		.get = s5k4aa_get_hflip
-
-	}, {
+	},
+#define GAIN_IDX 2
+	{
 		{
 			.id		= V4L2_CID_GAIN,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -99,12 +138,14 @@
 			.minimum	= 0,
 			.maximum	= 127,
 			.step		= 1,
-			.default_value	= 0xa0,
+			.default_value	= S5K4AA_DEFAULT_GAIN,
 			.flags		= V4L2_CTRL_FLAG_SLIDER
 		},
 		.set = s5k4aa_set_gain,
 		.get = s5k4aa_get_gain
-	}, {
+	},
+#define EXPOSURE_IDX 3
+	{
 		{
 			.id		= V4L2_CID_EXPOSURE,
 			.type		= V4L2_CTRL_TYPE_INTEGER,
@@ -117,7 +158,36 @@
 		},
 		.set = s5k4aa_set_exposure,
 		.get = s5k4aa_get_exposure
-	}
+	},
+#define NOISE_SUPP_IDX 4
+	{
+		{
+			.id		= V4L2_CID_PRIVATE_BASE,
+			.type		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name		= "Noise suppression (smoothing)",
+			.minimum	= 0,
+			.maximum	= 1,
+			.step		= 1,
+			.default_value	= 1,
+		},
+			.set = s5k4aa_set_noise,
+			.get = s5k4aa_get_noise
+	},
+#define BRIGHTNESS_IDX 5
+	{
+		{
+			.id		= V4L2_CID_BRIGHTNESS,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Brightness",
+			.minimum	= 0,
+			.maximum	= 0x1f,
+			.step		= 1,
+			.default_value	= S5K4AA_DEFAULT_BRIGHTNESS,
+		},
+			.set = s5k4aa_set_brightness,
+			.get = s5k4aa_get_brightness
+	},
+
 };
 
 static void s5k4aa_dump_registers(struct sd *sd);
@@ -127,6 +197,7 @@
 	u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 	const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
 	int i, err = 0;
+	s32 *sensor_settings;
 
 	if (force_sensor) {
 		if (force_sensor == S5K4AA_SENSOR) {
@@ -185,10 +256,20 @@
 		info("Detected a s5k4aa sensor");
 
 sensor_found:
+	sensor_settings = kmalloc(
+		ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
+	if (!sensor_settings)
+		return -ENOMEM;
+
 	sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
 	sd->desc->ctrls = s5k4aa_ctrls;
 	sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
+
+	for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
+		sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
+	sd->sensor_priv = sensor_settings;
+
 	return 0;
 }
 
@@ -197,9 +278,45 @@
 	int i, err = 0;
 	u8 data[2];
 	struct cam *cam = &sd->gspca_dev.cam;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
+	case 1280:
+		PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
+
+		for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
+			switch (SXGA_s5k4aa[i][0]) {
+			case BRIDGE:
+				err = m5602_write_bridge(sd,
+						 SXGA_s5k4aa[i][1],
+						 SXGA_s5k4aa[i][2]);
+			break;
+
+			case SENSOR:
+				data[0] = SXGA_s5k4aa[i][2];
+				err = m5602_write_sensor(sd,
+						 SXGA_s5k4aa[i][1],
+						 data, 1);
+			break;
+
+			case SENSOR_LONG:
+				data[0] = SXGA_s5k4aa[i][2];
+				data[1] = SXGA_s5k4aa[i][3];
+				err = m5602_write_sensor(sd,
+						  SXGA_s5k4aa[i][1],
+						  data, 2);
+			break;
+
+			default:
+				err("Invalid stream command, exiting init");
+				return -EINVAL;
+			}
+		}
+		err = s5k4aa_set_noise(&sd->gspca_dev, 0);
+		if (err < 0)
+			return err;
+		break;
 
-	switch (cam->cam_mode[sd->gspca_dev.curr_mode].width)
-	{
 	case 640:
 		PDEBUG(D_V4L2, "Configuring camera for VGA mode");
 
@@ -231,8 +348,37 @@
 				return -EINVAL;
 			}
 		}
+		err = s5k4aa_set_noise(&sd->gspca_dev, 1);
+		if (err < 0)
+			return err;
+		break;
 	}
-	return err;
+	if (err < 0)
+		return err;
+
+	err = s5k4aa_set_exposure(&sd->gspca_dev,
+				   sensor_settings[EXPOSURE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+	if (err < 0)
+		return err;
+
+	err = s5k4aa_set_brightness(&sd->gspca_dev,
+				     sensor_settings[BRIGHTNESS_IDX]);
+	if (err < 0)
+		return err;
+
+	err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
+	if (err < 0)
+		return err;
+
+	err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+	if (err < 0)
+		return err;
+
+	return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
 }
 
 int s5k4aa_init(struct sd *sd)
@@ -270,62 +416,28 @@
 	if (dump_sensor)
 		s5k4aa_dump_registers(sd);
 
-	if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
-		u8 data = 0x02;
-		info("vertical flip quirk active");
-		m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-		m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-		data |= S5K4AA_RM_V_FLIP;
-		data &= ~S5K4AA_RM_H_FLIP;
-		m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-
-		/* Decrement COLSTART to preserve color order (BGGR) */
-		m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-		data--;
-		m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-
-		/* Increment ROWSTART to preserve color order (BGGR) */
-		m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-		data++;
-		m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-	}
-
-	return (err < 0) ? err : 0;
-}
-
-int s5k4aa_power_down(struct sd *sd)
-{
-	return 0;
+	return err;
 }
 
-int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	u8 data = S5K4AA_PAGE_MAP_2;
-	int err;
-
-	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-	if (err < 0)
-		return err;
-
-	err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
-	if (err < 0)
-		return err;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	*val = data << 8;
-	err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
-	*val |= data;
+	*val = sensor_settings[EXPOSURE_IDX];
 	PDEBUG(D_V4L2, "Read exposure %d", *val);
 
-	return err;
+	return 0;
 }
 
-int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
+	sensor_settings[EXPOSURE_IDX] = val;
 	PDEBUG(D_V4L2, "Set exposure to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
@@ -340,149 +452,186 @@
 	return err;
 }
 
-int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	u8 data = S5K4AA_PAGE_MAP_2;
-	int err;
-
-	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-	if (err < 0)
-		return err;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-	*val = (data & S5K4AA_RM_V_FLIP) >> 7;
+	*val = sensor_settings[VFLIP_IDX];
 	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
-	return err;
+	return 0;
 }
 
-int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
+	sensor_settings[VFLIP_IDX] = val;
+
 	PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
-	err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+
+	err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
 	if (err < 0)
 		return err;
-	data = ((data & ~S5K4AA_RM_V_FLIP)
-			| ((val & 0x01) << 7));
+
+	if (dmi_check_system(s5k4aa_vflip_dmi_table))
+		val = !val;
+
+	data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
 	err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
 	if (err < 0)
 		return err;
 
-	if (val) {
-		err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-		if (err < 0)
-			return err;
-
-		data++;
-		err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-	} else {
-		err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-		if (err < 0)
-			return err;
-
-		data--;
-		err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-	}
-
+	err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+	if (err < 0)
+		return err;
+	data = (data & 0xfe) | !val;
+	err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
 	return err;
 }
 
-int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	u8 data = S5K4AA_PAGE_MAP_2;
-	int err;
-
-	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-	if (err < 0)
-		return err;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-	*val = (data & S5K4AA_RM_H_FLIP) >> 6;
+	*val = sensor_settings[HFLIP_IDX];
 	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 
-	return err;
+	return 0;
 }
 
-int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	PDEBUG(D_V4L2, "Set horizontal flip to %d",
-	       val);
+	sensor_settings[HFLIP_IDX] = val;
+
+	PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
-	err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+
+	err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
 	if (err < 0)
 		return err;
 
+	if (dmi_check_system(s5k4aa_vflip_dmi_table))
+		val = !val;
+
 	data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
 	err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
 	if (err < 0)
 		return err;
 
-	if (val) {
-		err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-		if (err < 0)
-			return err;
-		data++;
-		err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-		if (err < 0)
-			return err;
-	} else {
-		err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-		if (err < 0)
-			return err;
-		data--;
-		err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-	}
-
+	err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+	if (err < 0)
+		return err;
+	data = (data & 0xfe) | !val;
+	err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
 	return err;
 }
 
-int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[GAIN_IDX];
+	PDEBUG(D_V4L2, "Read gain %d", *val);
+	return 0;
+}
+
+static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
+	sensor_settings[GAIN_IDX] = val;
+
+	PDEBUG(D_V4L2, "Set gain to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
 
-	err = m5602_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
-	*val = data;
-	PDEBUG(D_V4L2, "Read gain %d", *val);
+	data = val & 0xff;
+	err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
 
 	return err;
 }
 
-int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[BRIGHTNESS_IDX];
+	PDEBUG(D_V4L2, "Read brightness %d", *val);
+	return 0;
+}
+
+static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 	u8 data = S5K4AA_PAGE_MAP_2;
 	int err;
 
-	PDEBUG(D_V4L2, "Set gain to %d", val);
+	sensor_settings[BRIGHTNESS_IDX] = val;
+
+	PDEBUG(D_V4L2, "Set brightness to %d", val);
 	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
 	if (err < 0)
 		return err;
 
 	data = val & 0xff;
-	err = m5602_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+	return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
+}
 
-	return err;
+static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[NOISE_SUPP_IDX];
+	PDEBUG(D_V4L2, "Read noise %d", *val);
+	return 0;
+}
+
+static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+	u8 data = S5K4AA_PAGE_MAP_2;
+	int err;
+
+	sensor_settings[NOISE_SUPP_IDX] = val;
+
+	PDEBUG(D_V4L2, "Set noise to %d", val);
+	err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+	if (err < 0)
+		return err;
+
+	data = val & 0x01;
+	return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
+}
+
+void s5k4aa_disconnect(struct sd *sd)
+{
+	sd->sensor = NULL;
+	kfree(sd->sensor_priv);
 }
 
 static void s5k4aa_dump_registers(struct sd *sd)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k4aa.h	2009-09-09 18:13:59.000000000 -0400
@@ -47,8 +47,9 @@
 #define S5K4AA_H_BLANK_LO__		0x1e
 #define S5K4AA_EXPOSURE_HI		0x17
 #define S5K4AA_EXPOSURE_LO		0x18
-#define S5K4AA_GAIN_1			0x1f /* (digital?) gain : 5 bits */
-#define S5K4AA_GAIN_2			0x20 /* (analogue?) gain : 7 bits */
+#define S5K4AA_BRIGHTNESS		0x1f /* (digital?) gain : 5 bits */
+#define S5K4AA_GAIN			0x20 /* (analogue?) gain : 7 bits */
+#define S5K4AA_NOISE_SUPP		0x37
 
 #define S5K4AA_RM_ROW_SKIP_4X		0x08
 #define S5K4AA_RM_ROW_SKIP_2X		0x04
@@ -57,6 +58,9 @@
 #define S5K4AA_RM_H_FLIP		0x40
 #define S5K4AA_RM_V_FLIP		0x80
 
+#define S5K4AA_DEFAULT_GAIN		0x5f
+#define S5K4AA_DEFAULT_BRIGHTNESS	0x10
+
 /*****************************************************************************/
 
 /* Kernel module parameters */
@@ -66,25 +70,17 @@
 int s5k4aa_probe(struct sd *sd);
 int s5k4aa_init(struct sd *sd);
 int s5k4aa_start(struct sd *sd);
-int s5k4aa_power_down(struct sd *sd);
-
-int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+void s5k4aa_disconnect(struct sd *sd);
 
 static const struct m5602_sensor s5k4aa = {
 	.name = "S5K4AA",
+	.i2c_slave_id = 0x5a,
+	.i2c_regW = 2,
+
 	.probe = s5k4aa_probe,
 	.init = s5k4aa_init,
 	.start = s5k4aa_start,
-	.power_down = s5k4aa_power_down,
-	.i2c_slave_id = 0x5a,
-	.i2c_regW = 2,
+	.disconnect = s5k4aa_disconnect,
 };
 
 static const unsigned char preinit_s5k4aa[][4] =
@@ -179,30 +175,12 @@
 	{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
 	{SENSOR, 0x0c, 0x05, 0x00},
 	{SENSOR, 0x02, 0x0e, 0x00},
-	{SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00},
-	{SENSOR, S5K4AA_GAIN_2, 0x00, 0x00},
-	{SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00},
-	{SENSOR, 0x11, 0x00, 0x00},
-	{SENSOR, 0x12, 0x00, 0x00},
-	{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
 	{SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
 	{SENSOR, 0x37, 0x00, 0x00},
-	{SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
-	{SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
-	{SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
-	{SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00},
-	{SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
-	{SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00},
-	{SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
-	{SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00},
-	{SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
-	{SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00},
-	{SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00},
-	{SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00},
-	{SENSOR, 0x11, 0x04, 0x00},
-	{SENSOR, 0x12, 0xc3, 0x00},
-	{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+};
 
+static const unsigned char VGA_s5k4aa[][4] =
+{
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
@@ -238,7 +216,7 @@
 	{SENSOR, 0x37, 0x01, 0x00},
 	/* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
 	{SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
-	{SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+	{SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00},
 	{SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
 	{SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
 	/* window_height_hi, window_height_lo : 960 = 0x03c0 */
@@ -255,12 +233,9 @@
 	{SENSOR, 0x12, 0xc3, 0x00},
 	{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
 	{SENSOR, 0x02, 0x0e, 0x00},
-	{SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00},
-	{SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00},
-	{SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00}
 };
 
-static const unsigned char VGA_s5k4aa[][4] =
+static const unsigned char SXGA_s5k4aa[][4] =
 {
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
@@ -273,50 +248,42 @@
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	/* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
+	/* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	/* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
+	/* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */
+	{BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
 
 	{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
-	{SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
-		| S5K4AA_RM_COL_SKIP_2X, 0x00},
-	/* 0x37 : Fix image stability when light is too bright and improves
-	 * image quality in 640x480, but worsens it in 1280x1024 */
+	{SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00},
 	{SENSOR, 0x37, 0x01, 0x00},
-	/* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
 	{SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
-	{SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+	{SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00},
 	{SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
-	{SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
-	/* window_height_hi, window_height_lo : 960 = 0x03c0 */
-	{SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
-	{SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
-	/* window_width_hi, window_width_lo : 1280 = 0x0500 */
+	{SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00},
+	{SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00},
+	{SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00},
 	{SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
 	{SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
-	{SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
-	{SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
+	{SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00},
+	{SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00},
 	{SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
 	{SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
 	{SENSOR, 0x11, 0x04, 0x00},
 	{SENSOR, 0x12, 0xc3, 0x00},
 	{SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
 	{SENSOR, 0x02, 0x0e, 0x00},
-	{SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00},
-	{SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00},
-	{SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00}
 };
 
+
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,8 +16,20 @@
  *
  */
 
+#include <linux/kthread.h>
 #include "m5602_s5k83a.h"
 
+static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+
 static struct v4l2_pix_format s5k83a_modes[] = {
 	{
 		640,
@@ -32,68 +44,77 @@
 	}
 };
 
-const static struct ctrl s5k83a_ctrls[] = {
+static const struct ctrl s5k83a_ctrls[] = {
+#define GAIN_IDX 0
 	{
 		{
-			.id = V4L2_CID_BRIGHTNESS,
+			.id = V4L2_CID_GAIN,
 			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "brightness",
+			.name = "gain",
 			.minimum = 0x00,
 			.maximum = 0xff,
 			.step = 0x01,
-			.default_value = S5K83A_DEFAULT_BRIGHTNESS,
+			.default_value = S5K83A_DEFAULT_GAIN,
 			.flags = V4L2_CTRL_FLAG_SLIDER
 		},
-			.set = s5k83a_set_brightness,
-			.get = s5k83a_get_brightness
+			.set = s5k83a_set_gain,
+			.get = s5k83a_get_gain
 
-	}, {
+	},
+#define BRIGHTNESS_IDX 1
+	{
 		{
-			.id = V4L2_CID_WHITENESS,
+			.id = V4L2_CID_BRIGHTNESS,
 			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "whiteness",
+			.name = "brightness",
 			.minimum = 0x00,
 			.maximum = 0xff,
 			.step = 0x01,
-			.default_value = S5K83A_DEFAULT_WHITENESS,
+			.default_value = S5K83A_DEFAULT_BRIGHTNESS,
 			.flags = V4L2_CTRL_FLAG_SLIDER
 		},
-			.set = s5k83a_set_whiteness,
-			.get = s5k83a_get_whiteness,
-	}, {
+			.set = s5k83a_set_brightness,
+			.get = s5k83a_get_brightness,
+	},
+#define EXPOSURE_IDX 2
+	{
 		{
-			.id = V4L2_CID_GAIN,
+			.id = V4L2_CID_EXPOSURE,
 			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "gain",
+			.name = "exposure",
 			.minimum = 0x00,
-			.maximum = S5K83A_MAXIMUM_GAIN,
+			.maximum = S5K83A_MAXIMUM_EXPOSURE,
 			.step = 0x01,
-			.default_value = S5K83A_DEFAULT_GAIN,
+			.default_value = S5K83A_DEFAULT_EXPOSURE,
 			.flags = V4L2_CTRL_FLAG_SLIDER
 		},
-			.set = s5k83a_set_gain,
-			.get = s5k83a_get_gain
-	}, {
+			.set = s5k83a_set_exposure,
+			.get = s5k83a_get_exposure
+	},
+#define HFLIP_IDX 3
+	{
 		{
-			.id         = V4L2_CID_HFLIP,
-			.type       = V4L2_CTRL_TYPE_BOOLEAN,
-			.name       = "horizontal flip",
-			.minimum    = 0,
-			.maximum    = 1,
-			.step       = 1,
-			.default_value  = 0
+			.id = V4L2_CID_HFLIP,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "horizontal flip",
+			.minimum = 0,
+			.maximum = 1,
+			.step = 1,
+			.default_value = 0
 		},
 			.set = s5k83a_set_hflip,
 			.get = s5k83a_get_hflip
-	}, {
+	},
+#define VFLIP_IDX 4
+	{
 		{
-		 .id         = V4L2_CID_VFLIP,
-		.type       = V4L2_CTRL_TYPE_BOOLEAN,
-		.name       = "vertical flip",
-		.minimum    = 0,
-		.maximum    = 1,
-		.step       = 1,
-		.default_value  = 0
+			.id = V4L2_CID_VFLIP,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "vertical flip",
+			.minimum = 0,
+			.maximum = 1,
+			.step = 1,
+			.default_value = 0
 		},
 		.set = s5k83a_set_vflip,
 		.get = s5k83a_get_vflip
@@ -101,9 +122,14 @@
 };
 
 static void s5k83a_dump_registers(struct sd *sd);
+static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
+static int s5k83a_set_led_indication(struct sd *sd, u8 val);
+static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
+				__s32 vflip, __s32 hflip);
 
 int s5k83a_probe(struct sd *sd)
 {
+	struct s5k83a_priv *sens_priv;
 	u8 prod_id = 0, ver_id = 0;
 	int i, err = 0;
 
@@ -145,16 +171,36 @@
 		info("Detected a s5k83a sensor");
 
 sensor_found:
+	sens_priv = kmalloc(
+		sizeof(struct s5k83a_priv), GFP_KERNEL);
+	if (!sens_priv)
+		return -ENOMEM;
+
+	sens_priv->settings =
+	kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
+	if (!sens_priv->settings)
+		return -ENOMEM;
+
 	sd->gspca_dev.cam.cam_mode = s5k83a_modes;
 	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
 	sd->desc->ctrls = s5k83a_ctrls;
 	sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
+
+	/* null the pointer! thread is't running now */
+	sens_priv->rotation_thread = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
+		sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
+
+	sd->sensor_priv = sens_priv;
 	return 0;
 }
 
 int s5k83a_init(struct sd *sd)
 {
 	int i, err = 0;
+	s32 *sensor_settings =
+			((struct s5k83a_priv *) sd->sensor_priv)->settings;
 
 	for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
 		u8 data[2] = {0x00, 0x00};
@@ -187,87 +233,138 @@
 	if (dump_sensor)
 		s5k83a_dump_registers(sd);
 
-	return (err < 0) ? err : 0;
-}
+	err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+	if (err < 0)
+		return err;
 
-int s5k83a_start(struct sd *sd)
-{
-	return s5k83a_set_led_indication(sd, 1);
-}
+	err = s5k83a_set_brightness(&sd->gspca_dev,
+				     sensor_settings[BRIGHTNESS_IDX]);
+	if (err < 0)
+		return err;
 
-int s5k83a_stop(struct sd *sd)
-{
-	return s5k83a_set_led_indication(sd, 0);
+	err = s5k83a_set_exposure(&sd->gspca_dev,
+				   sensor_settings[EXPOSURE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+	if (err < 0)
+		return err;
+
+	err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+
+	return err;
 }
 
-int s5k83a_power_down(struct sd *sd)
+static int rotation_thread_function(void *data)
 {
+	struct sd *sd = (struct sd *) data;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
+	u8 reg, previous_rotation = 0;
+	__s32 vflip, hflip;
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (!schedule_timeout(100)) {
+		if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
+			break;
+
+		s5k83a_get_rotation(sd, &reg);
+		if (previous_rotation != reg) {
+			previous_rotation = reg;
+			info("Camera was flipped");
+
+			s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
+			s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+
+			if (reg) {
+				vflip = !vflip;
+				hflip = !hflip;
+			}
+			s5k83a_set_flip_real((struct gspca_dev *) sd,
+					      vflip, hflip);
+		}
+
+		mutex_unlock(&sd->gspca_dev.usb_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+	}
+
+	/* return to "front" flip */
+	if (previous_rotation) {
+		s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
+		s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+		s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
+	}
+
+	sens_priv->rotation_thread = NULL;
 	return 0;
 }
 
-static void s5k83a_dump_registers(struct sd *sd)
+int s5k83a_start(struct sd *sd)
 {
-	int address;
-	u8 page, old_page;
-	m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+	int i, err = 0;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	for (page = 0; page < 16; page++) {
-		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-		info("Dumping the s5k83a register state for page 0x%x", page);
-		for (address = 0; address <= 0xff; address++) {
-			u8 val = 0;
-			m5602_read_sensor(sd, address, &val, 1);
-			info("register 0x%x contains 0x%x",
-			     address, val);
-		}
+	/* Create another thread, polling the GPIO ports of the camera to check
+	   if it got rotated. This is how the windows driver does it so we have
+	   to assume that there is no better way of accomplishing this */
+	sens_priv->rotation_thread = kthread_create(rotation_thread_function,
+						    sd, "rotation thread");
+	wake_up_process(sens_priv->rotation_thread);
+
+	/* Preinit the sensor */
+	for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
+		u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
+		if (start_s5k83a[i][0] == SENSOR)
+			err = m5602_write_sensor(sd, start_s5k83a[i][1],
+				data, 2);
+		else
+			err = m5602_write_bridge(sd, start_s5k83a[i][1],
+				data[0]);
 	}
-	info("s5k83a register state dump complete");
+	if (err < 0)
+		return err;
 
-	for (page = 0; page < 16; page++) {
-		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-		info("Probing for which registers that are read/write "
-		      "for page 0x%x", page);
-		for (address = 0; address <= 0xff; address++) {
-			u8 old_val, ctrl_val, test_val = 0xff;
+	return s5k83a_set_led_indication(sd, 1);
+}
 
-			m5602_read_sensor(sd, address, &old_val, 1);
-			m5602_write_sensor(sd, address, &test_val, 1);
-			m5602_read_sensor(sd, address, &ctrl_val, 1);
+int s5k83a_stop(struct sd *sd)
+{
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-			if (ctrl_val == test_val)
-				info("register 0x%x is writeable", address);
-			else
-				info("register 0x%x is read only", address);
+	if (sens_priv->rotation_thread)
+		kthread_stop(sens_priv->rotation_thread);
 
-			/* Restore original val */
-			m5602_write_sensor(sd, address, &old_val, 1);
-		}
-	}
-	info("Read/write register probing complete");
-	m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+	return s5k83a_set_led_indication(sd, 0);
 }
 
-int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+void s5k83a_disconnect(struct sd *sd)
 {
-	int err;
-	u8 data[2];
-	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
-	if (err < 0)
-		return err;
+	s5k83a_stop(sd);
 
-	data[1] = data[1] << 1;
-	*val = data[1];
+	sd->sensor = NULL;
+	kfree(sens_priv->settings);
+	kfree(sens_priv);
+}
 
-	return err;
+static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+	*val = sens_priv->settings[GAIN_IDX];
+	return 0;
 }
 
-int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+	sens_priv->settings[GAIN_IDX] = val;
 
 	data[0] = 0x00;
 	data[1] = 0x20;
@@ -283,89 +380,69 @@
 
 	/* FIXME: This is not sane, we need to figure out the composition
 		  of these registers */
-	data[0] = val >> 3; /* brightness, high 5 bits */
-	data[1] = val >> 1; /* brightness, high 7 bits */
-	err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+	data[0] = val >> 3; /* gain, high 5 bits */
+	data[1] = val >> 1; /* gain, high 7 bits */
+	err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
 
 	return err;
 }
 
-int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u8 data;
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
-	if (err < 0)
-		return err;
-
-	*val = data;
-
-	return err;
+	*val = sens_priv->settings[BRIGHTNESS_IDX];
+	return 0;
 }
 
-int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 data[1];
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
+	sens_priv->settings[BRIGHTNESS_IDX] = val;
 	data[0] = val;
-	err = m5602_write_sensor(sd, S5K83A_WHITENESS, data, 1);
-
+	err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
 	return err;
 }
 
-int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	err = m5602_read_sensor(sd, S5K83A_GAIN, data, 2);
-	if (err < 0)
-		return err;
-
-	data[1] = data[1] & 0x3f;
-	if (data[1] > S5K83A_MAXIMUM_GAIN)
-		data[1] = S5K83A_MAXIMUM_GAIN;
-
-	*val = data[1];
-
-	return err;
+	*val = sens_priv->settings[EXPOSURE_IDX];
+	return 0;
 }
 
-int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	u8 data[2];
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
+	sens_priv->settings[EXPOSURE_IDX] = val;
 	data[0] = 0;
 	data[1] = val;
-	err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
+	err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
 	return err;
 }
 
-int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u8 data[1];
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	data[0] = 0x05;
-	err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
-	if (err < 0)
-		return err;
-
-	err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
-	*val = (data[0] | 0x40) ? 1 : 0;
-
-	return err;
+	*val = sens_priv->settings[VFLIP_IDX];
+	return 0;
 }
 
-int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
+				__s32 vflip, __s32 hflip)
 {
 	int err;
 	u8 data[1];
@@ -376,69 +453,83 @@
 	if (err < 0)
 		return err;
 
-	err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
-	if (err < 0)
-		return err;
+	/* six bit is vflip, seven is hflip */
+	data[0] = S5K83A_FLIP_MASK;
+	data[0] = (vflip) ? data[0] | 0x40 : data[0];
+	data[0] = (hflip) ? data[0] | 0x80 : data[0];
 
-	/* set or zero six bit, seven is hflip */
-	data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK
-			: (data[0] & 0x80) | S5K83A_FLIP_MASK;
 	err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
 	if (err < 0)
 		return err;
 
-	data[0] = (val) ? 0x0b : 0x0a;
+	data[0] = (vflip) ? 0x0b : 0x0a;
 	err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
+	if (err < 0)
+		return err;
 
+	data[0] = (hflip) ? 0x0a : 0x0b;
+	err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
 	return err;
 }
 
-int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
-	u8 data[1];
+	u8 reg;
+	__s32 hflip;
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	data[0] = 0x05;
-	err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+	sens_priv->settings[VFLIP_IDX] = val;
+
+	s5k83a_get_hflip(gspca_dev, &hflip);
+
+	err = s5k83a_get_rotation(sd, &reg);
 	if (err < 0)
 		return err;
+	if (reg) {
+		val = !val;
+		hflip = !hflip;
+	}
 
-	err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
-	*val = (data[0] | 0x80) ? 1 : 0;
-
+	err = s5k83a_set_flip_real(gspca_dev, val, hflip);
 	return err;
 }
 
-int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+	*val = sens_priv->settings[HFLIP_IDX];
+	return 0;
+}
+
+static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
-	u8 data[1];
+	u8 reg;
+	__s32 vflip;
 	struct sd *sd = (struct sd *) gspca_dev;
+	struct s5k83a_priv *sens_priv = sd->sensor_priv;
 
-	data[0] = 0x05;
-	err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
-	if (err < 0)
-		return err;
+	sens_priv->settings[HFLIP_IDX] = val;
 
-	err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
-	if (err < 0)
-		return err;
+	s5k83a_get_vflip(gspca_dev, &vflip);
 
-	/* set or zero seven bit, six is vflip */
-	data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK
-			: (data[0] & 0x40) | S5K83A_FLIP_MASK;
-	err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
+	err = s5k83a_get_rotation(sd, &reg);
 	if (err < 0)
 		return err;
+	if (reg) {
+		val = !val;
+		vflip = !vflip;
+	}
 
-	data[0] = (val) ? 0x0a : 0x0b;
-	err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
-
+	err = s5k83a_set_flip_real(gspca_dev, vflip, val);
 	return err;
 }
 
-int s5k83a_set_led_indication(struct sd *sd, u8 val)
+static int s5k83a_set_led_indication(struct sd *sd, u8 val)
 {
 	int err = 0;
 	u8 data[1];
@@ -454,5 +545,55 @@
 
 	err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
 
-	return (err < 0) ? err : 0;
+	return err;
+}
+
+/* Get camera rotation on Acer notebooks */
+static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
+{
+	int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
+	*reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
+	return err;
+}
+
+static void s5k83a_dump_registers(struct sd *sd)
+{
+	int address;
+	u8 page, old_page;
+	m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+
+	for (page = 0; page < 16; page++) {
+		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+		info("Dumping the s5k83a register state for page 0x%x", page);
+		for (address = 0; address <= 0xff; address++) {
+			u8 val = 0;
+			m5602_read_sensor(sd, address, &val, 1);
+			info("register 0x%x contains 0x%x",
+			     address, val);
+		}
+	}
+	info("s5k83a register state dump complete");
+
+	for (page = 0; page < 16; page++) {
+		m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+		info("Probing for which registers that are read/write "
+				"for page 0x%x", page);
+		for (address = 0; address <= 0xff; address++) {
+			u8 old_val, ctrl_val, test_val = 0xff;
+
+			m5602_read_sensor(sd, address, &old_val, 1);
+			m5602_write_sensor(sd, address, &test_val, 1);
+			m5602_read_sensor(sd, address, &ctrl_val, 1);
+
+			if (ctrl_val == test_val)
+				info("register 0x%x is writeable", address);
+			else
+				info("register 0x%x is read only", address);
+
+			/* Restore original val */
+			m5602_write_sensor(sd, address, &old_val, 1);
+		}
+	}
+	info("Read/write register probing complete");
+	m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_s5k83a.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,20 +21,21 @@
 
 #include "m5602_sensor.h"
 
-#define S5K83A_FLIP				0x01
-#define S5K83A_HFLIP_TUNE			0x03
-#define S5K83A_VFLIP_TUNE			0x05
-#define S5K83A_WHITENESS			0x0a
-#define S5K83A_GAIN				0x18
-#define S5K83A_BRIGHTNESS			0x1b
-#define S5K83A_PAGE_MAP				0xec
+#define S5K83A_FLIP			0x01
+#define S5K83A_HFLIP_TUNE		0x03
+#define S5K83A_VFLIP_TUNE		0x05
+#define S5K83A_BRIGHTNESS		0x0a
+#define S5K83A_EXPOSURE			0x18
+#define S5K83A_GAIN			0x1b
+#define S5K83A_PAGE_MAP			0xec
 
-#define S5K83A_DEFAULT_BRIGHTNESS		0x71
-#define S5K83A_DEFAULT_WHITENESS		0x7e
-#define S5K83A_DEFAULT_GAIN			0x00
-#define S5K83A_MAXIMUM_GAIN			0x3c
-#define S5K83A_FLIP_MASK			0x10
+#define S5K83A_DEFAULT_GAIN		0x71
+#define S5K83A_DEFAULT_BRIGHTNESS	0x7e
+#define S5K83A_DEFAULT_EXPOSURE		0x00
+#define S5K83A_MAXIMUM_EXPOSURE		0x3c
+#define S5K83A_FLIP_MASK		0x10
 #define S5K83A_GPIO_LED_MASK		0x10
+#define S5K83A_GPIO_ROTATION_MASK 	0x40
 
 /*****************************************************************************/
 
@@ -46,20 +47,7 @@
 int s5k83a_init(struct sd *sd);
 int s5k83a_start(struct sd *sd);
 int s5k83a_stop(struct sd *sd);
-int s5k83a_power_down(struct sd *sd);
-
-int s5k83a_set_led_indication(struct sd *sd, u8 val);
-
-int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+void s5k83a_disconnect(struct sd *sd);
 
 static const struct m5602_sensor s5k83a = {
 	.name = "S5K83A",
@@ -67,11 +55,18 @@
 	.init = s5k83a_init,
 	.start = s5k83a_start,
 	.stop = s5k83a_stop,
-	.power_down = s5k83a_power_down,
+	.disconnect = s5k83a_disconnect,
 	.i2c_slave_id = 0x5a,
 	.i2c_regW = 2,
 };
 
+struct s5k83a_priv {
+	/* We use another thread periodically
+	   probing the orientation of the camera */
+	struct task_struct *rotation_thread;
+	s32 *settings;
+};
+
 static const unsigned char preinit_s5k83a[][4] =
 {
 	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
@@ -108,8 +103,6 @@
 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
 	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
 	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-
-	{SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}
 };
 
 /* This could probably be considerably shortened.
@@ -117,86 +110,8 @@
 */
 static const unsigned char init_s5k83a[][4] =
 {
-	{SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
-	{SENSOR, 0xaf, 0x01, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, 0x7b, 0xff, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR, 0x01, 0x50, 0x00},
-	{SENSOR, 0x12, 0x20, 0x00},
-	{SENSOR, 0x17, 0x40, 0x00},
-	{SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
-	{SENSOR, 0x1c, 0x00, 0x00},
-	{SENSOR, 0x02, 0x70, 0x00},
-	{SENSOR, 0x03, 0x0b, 0x00},
-	{SENSOR, 0x04, 0xf0, 0x00},
-	{SENSOR, 0x05, 0x0b, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR, 0x06, 0x71, 0x00},
-	{SENSOR, 0x07, 0xe8, 0x00},
-	{SENSOR, 0x08, 0x02, 0x00},
-	{SENSOR, 0x09, 0x88, 0x00},
-	{SENSOR, 0x14, 0x00, 0x00},
-	{SENSOR, 0x15, 0x20, 0x00},
-	{SENSOR, 0x19, 0x00, 0x00},
-	{SENSOR, 0x1a, 0x98, 0x00},
-	{SENSOR, 0x0f, 0x02, 0x00},
-	{SENSOR, 0x10, 0xe5, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR_LONG, 0x14, 0x00, 0x20},
-	{SENSOR_LONG, 0x0d, 0x00, 0x7d},
-	{SENSOR_LONG, 0x1b, 0x0d, 0x05},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
-
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+	/* The following sequence is useless after a clean boot
+	   but is necessary after resume from suspend */
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
@@ -216,7 +131,7 @@
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
 	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
 	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
@@ -225,109 +140,34 @@
 
 	{SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
 	{SENSOR, 0xaf, 0x01, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	/* ff ( init value )is very dark) || 71 and f0 better */
+	{SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
 	{SENSOR, 0x7b, 0xff, 0x00},
 	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
 	{SENSOR, 0x01, 0x50, 0x00},
 	{SENSOR, 0x12, 0x20, 0x00},
 	{SENSOR, 0x17, 0x40, 0x00},
-	{SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
 	{SENSOR, 0x1c, 0x00, 0x00},
 	{SENSOR, 0x02, 0x70, 0x00},
-	/* some values like 0x10 give a blue-purple image */
 	{SENSOR, 0x03, 0x0b, 0x00},
 	{SENSOR, 0x04, 0xf0, 0x00},
 	{SENSOR, 0x05, 0x0b, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-	/* under 80 don't work, highter depend on value */
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
-
-	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
 	{SENSOR, 0x06, 0x71, 0x00},
-	{SENSOR, 0x07, 0xe8, 0x00},
+	{SENSOR, 0x07, 0xe8, 0x00}, /* 488 */
 	{SENSOR, 0x08, 0x02, 0x00},
-	{SENSOR, 0x09, 0x88, 0x00},
+	{SENSOR, 0x09, 0x88, 0x00}, /* 648 */
 	{SENSOR, 0x14, 0x00, 0x00},
-	{SENSOR, 0x15, 0x20, 0x00},
+	{SENSOR, 0x15, 0x20, 0x00}, /* 32 */
 	{SENSOR, 0x19, 0x00, 0x00},
-	{SENSOR, 0x1a, 0x98, 0x00},
+	{SENSOR, 0x1a, 0x98, 0x00}, /* 152 */
 	{SENSOR, 0x0f, 0x02, 0x00},
-	{SENSOR, 0x10, 0xe5, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR_LONG, 0x14, 0x00, 0x20},
-	{SENSOR_LONG, 0x0d, 0x00, 0x7d},
-	{SENSOR_LONG, 0x1b, 0x0d, 0x05},
-
-	/* The following sequence is useless after a clean boot
-	   but is necessary after resume from suspend */
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
-	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-
-	{SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
-	{SENSOR, 0xaf, 0x01, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
-	{SENSOR, 0x7b, 0xff, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR, 0x01, 0x50, 0x00},
-	{SENSOR, 0x12, 0x20, 0x00},
-	{SENSOR, 0x17, 0x40, 0x00},
-	{SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
-	{SENSOR, 0x1c, 0x00, 0x00},
-	{SENSOR, 0x02, 0x70, 0x00},
-	{SENSOR, 0x03, 0x0b, 0x00},
-	{SENSOR, 0x04, 0xf0, 0x00},
-	{SENSOR, 0x05, 0x0b, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+	{SENSOR, 0x10, 0xe5, 0x00}, /* 741 */
+	/* normal colors
+	(this is value after boot, but after tries can be different) */
+	{SENSOR, 0x00, 0x06, 0x00},
+};
 
+static const unsigned char start_s5k83a[][4] =
+{
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
 	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
@@ -340,7 +180,7 @@
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
@@ -348,50 +188,10 @@
 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
 	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-	{BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+	{BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */
 	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
 	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR, 0x06, 0x71, 0x00},
-	{SENSOR, 0x07, 0xe8, 0x00},
-	{SENSOR, 0x08, 0x02, 0x00},
-	{SENSOR, 0x09, 0x88, 0x00},
-	{SENSOR, 0x14, 0x00, 0x00},
-	{SENSOR, 0x15, 0x20, 0x00},
-	{SENSOR, 0x19, 0x00, 0x00},
-	{SENSOR, 0x1a, 0x98, 0x00},
-	{SENSOR, 0x0f, 0x02, 0x00},
-
-	{SENSOR, 0x10, 0xe5, 0x00},
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR_LONG, 0x14, 0x00, 0x20},
-	{SENSOR_LONG, 0x0d, 0x00, 0x7d},
-	{SENSOR_LONG, 0x1b, 0x0d, 0x05},
-
-	/* normal colors
-	   (this is value after boot, but after tries can be different) */
-	{SENSOR, 0x00, 0x06, 0x00},
-
-	/* set default brightness */
-	{SENSOR_LONG, 0x14, 0x00, 0x20},
-	{SENSOR_LONG, 0x0d, 0x01, 0x00},
-	{SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3,
-			    S5K83A_DEFAULT_BRIGHTNESS >> 1},
-
-	/* set default whiteness */
-	{SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00},
-
-	/* set default gain */
-	{SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN},
-
-	/* set default flip */
-	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-	{SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00},
-	{SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00},
-	{SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00}
-
 };
 
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_sensor.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_sensor.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/m5602_sensor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/m5602_sensor.h	2009-09-09 18:13:59.000000000 -0400
@@ -21,13 +21,17 @@
 
 #include "m5602_bridge.h"
 
+#define M5602_V4L2_CID_GREEN_BALANCE	(V4L2_CID_PRIVATE_BASE + 0)
+#define M5602_V4L2_CID_NOISE_SUPPRESION	(V4L2_CID_PRIVATE_BASE + 1)
+
 /* Enumerates all supported sensors */
 enum sensors {
 	OV9650_SENSOR	= 1,
 	S5K83A_SENSOR	= 2,
 	S5K4AA_SENSOR	= 3,
 	MT9M111_SENSOR	= 4,
-	PO1030_SENSOR	= 5
+	PO1030_SENSOR	= 5,
+	OV7660_SENSOR   = 6,
 };
 
 /* Enumerates all possible instruction types */
@@ -61,9 +65,6 @@
 
 	/* Executed when the device is disconnected */
 	void (*disconnect)(struct sd *sd);
-
-	/* Performs a power down sequence */
-	int (*power_down)(struct sd *sd);
 };
 
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/Makefile linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/m5602/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/m5602/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,9 +2,10 @@
 
 gspca_m5602-objs := m5602_core.o \
 		    m5602_ov9650.o \
+		    m5602_ov7660.o \
 		    m5602_mt9m111.o \
 		    m5602_po1030.o \
 		    m5602_s5k83a.o \
 		    m5602_s5k4aa.o
 
-EXTRA_CFLAGS += -Idrivers/media/video/gspca
\ No newline at end of file
+EXTRA_CFLAGS += -Idrivers/media/video/gspca
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/Makefile linux-libre-2.6.31-gnu/drivers/media/video/gspca/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,7 @@
 obj-$(CONFIG_USB_GSPCA_OV534)    += gspca_ov534.o
 obj-$(CONFIG_USB_GSPCA_PAC207)   += gspca_pac207.o
 obj-$(CONFIG_USB_GSPCA_PAC7311)  += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SN9C20X)  += gspca_sn9c20x.o
 obj-$(CONFIG_USB_GSPCA_SONIXB)   += gspca_sonixb.o
 obj-$(CONFIG_USB_GSPCA_SONIXJ)   += gspca_sonixj.o
 obj-$(CONFIG_USB_GSPCA_SPCA500)  += gspca_spca500.o
@@ -35,6 +36,7 @@
 gspca_ov534-objs    := ov534.o
 gspca_pac207-objs   := pac207.o
 gspca_pac7311-objs  := pac7311.o
+gspca_sn9c20x-objs  := sn9c20x.o
 gspca_sonixb-objs   := sonixb.o
 gspca_sonixj-objs   := sonixj.o
 gspca_spca500-objs  := spca500.o
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/mars.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/mars.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/mars.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/mars.c	2009-09-09 18:13:59.000000000 -0400
@@ -201,6 +201,8 @@
 
 	/* create the JPEG header */
 	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (!sd->jpeg_hdr)
+		return -ENOMEM;
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x21);		/* JPEG 422 */
 	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/mr97310a.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/mr97310a.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/mr97310a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/mr97310a.c	2009-09-09 18:13:59.000000000 -0400
@@ -321,6 +321,7 @@
 /* -- module initialisation -- */
 static const __devinitdata struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x08ca, 0x0111)},
+	{USB_DEVICE(0x093a, 0x010f)},
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -347,8 +348,11 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/ov519.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/ov519.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/ov519.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/ov519.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,19 @@
 struct sd {
 	struct gspca_dev gspca_dev;		/* !! must be the first item */
 
+	__u8 packet_nr;
+
+	char bridge;
+#define BRIDGE_OV511		0
+#define BRIDGE_OV511PLUS	1
+#define BRIDGE_OV518		2
+#define BRIDGE_OV518PLUS	3
+#define BRIDGE_OV519		4
+#define BRIDGE_MASK		7
+
+	char invert_led;
+#define BRIDGE_INVERT_LED	8
+
 	/* Determined by sensor type */
 	__u8 sif;
 
@@ -58,22 +71,25 @@
 	__u8 colors;
 	__u8 hflip;
 	__u8 vflip;
+	__u8 autobrightness;
+	__u8 freq;
 
 	__u8 stopped;		/* Streaming is temporarily paused */
 
-	__u8 frame_rate;	/* current Framerate (OV519 only) */
-	__u8 clockdiv;		/* clockdiv override for OV519 only */
+	__u8 frame_rate;	/* current Framerate */
+	__u8 clockdiv;		/* clockdiv override */
 
 	char sensor;		/* Type of image sensor chip (SEN_*) */
 #define SEN_UNKNOWN 0
 #define SEN_OV6620 1
 #define SEN_OV6630 2
-#define SEN_OV7610 3
-#define SEN_OV7620 4
-#define SEN_OV7640 5
-#define SEN_OV7670 6
-#define SEN_OV76BE 7
-#define SEN_OV8610 8
+#define SEN_OV66308AF 3
+#define SEN_OV7610 4
+#define SEN_OV7620 5
+#define SEN_OV7640 6
+#define SEN_OV7670 7
+#define SEN_OV76BE 8
+#define SEN_OV8610 9
 };
 
 /* V4L2 controls supported by the driver */
@@ -87,8 +103,17 @@
 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setcolors(struct gspca_dev *gspca_dev);
+static void setautobrightness(struct sd *sd);
+static void setfreq(struct sd *sd);
 
-static struct ctrl sd_ctrls[] = {
+static const struct ctrl sd_ctrls[] = {
 	{
 	    {
 		.id      = V4L2_CID_BRIGHTNESS,
@@ -131,7 +156,7 @@
 	    .set = sd_setcolors,
 	    .get = sd_getcolors,
 	},
-/* next controls work with ov7670 only */
+/* The flip controls work with ov7670 only */
 #define HFLIP_IDX 3
 	{
 	    {
@@ -162,9 +187,54 @@
 	    .set = sd_setvflip,
 	    .get = sd_getvflip,
 	},
+#define AUTOBRIGHT_IDX 5
+	{
+	    {
+		.id      = V4L2_CID_AUTOBRIGHTNESS,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Auto Brightness",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+#define AUTOBRIGHT_DEF 1
+		.default_value = AUTOBRIGHT_DEF,
+	    },
+	    .set = sd_setautobrightness,
+	    .get = sd_getautobrightness,
+	},
+#define FREQ_IDX 6
+	{
+	    {
+		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
+		.type    = V4L2_CTRL_TYPE_MENU,
+		.name    = "Light frequency filter",
+		.minimum = 0,
+		.maximum = 2,	/* 0: 0, 1: 50Hz, 2:60Hz */
+		.step    = 1,
+#define FREQ_DEF 0
+		.default_value = FREQ_DEF,
+	    },
+	    .set = sd_setfreq,
+	    .get = sd_getfreq,
+	},
+#define OV7670_FREQ_IDX 7
+	{
+	    {
+		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
+		.type    = V4L2_CTRL_TYPE_MENU,
+		.name    = "Light frequency filter",
+		.minimum = 0,
+		.maximum = 3,	/* 0: 0, 1: 50Hz, 2:60Hz 3: Auto Hz */
+		.step    = 1,
+#define OV7670_FREQ_DEF 3
+		.default_value = OV7670_FREQ_DEF,
+	    },
+	    .set = sd_setfreq,
+	    .get = sd_getfreq,
+	},
 };
 
-static const struct v4l2_pix_format vga_mode[] = {
+static const struct v4l2_pix_format ov519_vga_mode[] = {
 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 320 * 240 * 3 / 8 + 590,
@@ -176,12 +246,22 @@
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = 0},
 };
-static const struct v4l2_pix_format sif_mode[] = {
+static const struct v4l2_pix_format ov519_sif_mode[] = {
+	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 160 * 120 * 3 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 3},
 	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 176,
 		.sizeimage = 176 * 144 * 3 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = 1},
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 3 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 2},
 	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 352,
 		.sizeimage = 352 * 288 * 3 / 8 + 590,
@@ -189,6 +269,123 @@
 		.priv = 0},
 };
 
+/* Note some of the sizeimage values for the ov511 / ov518 may seem
+   larger then necessary, however they need to be this big as the ov511 /
+   ov518 always fills the entire isoc frame, using 0 padding bytes when
+   it doesn't have any data. So with low framerates the amount of data
+   transfered can become quite large (libv4l will remove all the 0 padding
+   in userspace). */
+static const struct v4l2_pix_format ov518_vga_mode[] = {
+	{320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 3,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 1},
+	{640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480 * 2,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 0},
+};
+static const struct v4l2_pix_format ov518_sif_mode[] = {
+	{160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 70000,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 3},
+	{176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+		.bytesperline = 176,
+		.sizeimage = 70000,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 1},
+	{320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 3,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 2},
+	{352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+		.bytesperline = 352,
+		.sizeimage = 352 * 288 * 3,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 0},
+};
+
+static const struct v4l2_pix_format ov511_vga_mode[] = {
+	{320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 3,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 1},
+	{640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480 * 2,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 0},
+};
+static const struct v4l2_pix_format ov511_sif_mode[] = {
+	{160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 70000,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 3},
+	{176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+		.bytesperline = 176,
+		.sizeimage = 70000,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 1},
+	{320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 3,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 2},
+	{352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+		.bytesperline = 352,
+		.sizeimage = 352 * 288 * 3,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 0},
+};
+
+/* Registers common to OV511 / OV518 */
+#define R51x_FIFO_PSIZE			0x30	/* 2 bytes wide w/ OV518(+) */
+#define R51x_SYS_RESET          	0x50
+	/* Reset type flags */
+	#define	OV511_RESET_OMNICE	0x08
+#define R51x_SYS_INIT         		0x53
+#define R51x_SYS_SNAP			0x52
+#define R51x_SYS_CUST_ID		0x5F
+#define R51x_COMP_LUT_BEGIN		0x80
+
+/* OV511 Camera interface register numbers */
+#define R511_CAM_DELAY			0x10
+#define R511_CAM_EDGE			0x11
+#define R511_CAM_PXCNT			0x12
+#define R511_CAM_LNCNT			0x13
+#define R511_CAM_PXDIV			0x14
+#define R511_CAM_LNDIV			0x15
+#define R511_CAM_UV_EN			0x16
+#define R511_CAM_LINE_MODE		0x17
+#define R511_CAM_OPTS			0x18
+
+#define R511_SNAP_FRAME			0x19
+#define R511_SNAP_PXCNT			0x1A
+#define R511_SNAP_LNCNT			0x1B
+#define R511_SNAP_PXDIV			0x1C
+#define R511_SNAP_LNDIV			0x1D
+#define R511_SNAP_UV_EN			0x1E
+#define R511_SNAP_UV_EN			0x1E
+#define R511_SNAP_OPTS			0x1F
+
+#define R511_DRAM_FLOW_CTL		0x20
+#define R511_FIFO_OPTS			0x31
+#define R511_I2C_CTL			0x40
+#define R511_SYS_LED_CTL		0x55	/* OV511+ only */
+#define R511_COMP_EN			0x78
+#define R511_COMP_LUT_EN		0x79
+
+/* OV518 Camera interface register numbers */
+#define R518_GPIO_OUT			0x56	/* OV518(+) only */
+#define R518_GPIO_CTL			0x57	/* OV518(+) only */
+
 /* OV519 Camera interface register numbers */
 #define OV519_R10_H_SIZE		0x10
 #define OV519_R11_V_SIZE		0x11
@@ -224,6 +421,8 @@
 
 /* OV7610 registers */
 #define OV7610_REG_GAIN		0x00	/* gain setting (5:0) */
+#define OV7610_REG_BLUE		0x01	/* blue channel balance */
+#define OV7610_REG_RED		0x02	/* red channel balance */
 #define OV7610_REG_SAT		0x03	/* saturation */
 #define OV8610_REG_HUE		0x04	/* 04 reserved */
 #define OV7610_REG_CNT		0x05	/* Y contrast */
@@ -330,7 +529,7 @@
 	{ 0x28, 0x05 },
 	{ 0x2a, 0x04 }, /* Disable framerate adjust */
 /*	{ 0x2b, 0xac },  * Framerate; Set 2a[7] first */
-	{ 0x2d, 0x99 },
+	{ 0x2d, 0x85 },
 	{ 0x33, 0xa0 }, /* Color Processing Parameter */
 	{ 0x34, 0xd2 }, /* Max A/D range */
 	{ 0x38, 0x8b },
@@ -363,7 +562,7 @@
 	{ 0x07, 0x2d }, /* Sharpness */
 	{ 0x0c, 0x20 },
 	{ 0x0d, 0x20 },
-	{ 0x0e, 0x20 },
+	{ 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
 	{ 0x0f, 0x05 },
 	{ 0x10, 0x9a },
 	{ 0x11, 0x00 }, /* Pixel clock = fastest */
@@ -505,7 +704,7 @@
 	{ 0x23, 0x00 },
 	{ 0x26, 0xa2 },
 	{ 0x27, 0xea },
-	{ 0x28, 0x20 },
+	{ 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */
 	{ 0x29, 0x00 },
 	{ 0x2a, 0x10 },
 	{ 0x2b, 0x00 },
@@ -846,11 +1045,12 @@
 static int reg_w(struct sd *sd, __u16 index, __u8 value)
 {
 	int ret;
+	int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1;
 
 	sd->gspca_dev.usb_buf[0] = value;
 	ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
-			1,			/* REQ_IO (ov518/519) */
+			req,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0, index,
 			sd->gspca_dev.usb_buf, 1, 500);
@@ -864,10 +1064,11 @@
 static int reg_r(struct sd *sd, __u16 index)
 {
 	int ret;
+	int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1;
 
 	ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
-			1,			/* REQ_IO */
+			req,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0, index, sd->gspca_dev.usb_buf, 1, 500);
 
@@ -924,11 +1125,148 @@
 }
 
 /*
+ * Writes multiple (n) byte value to a single register. Only valid with certain
+ * registers (0x30 and 0xc4 - 0xce).
+ */
+static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
+{
+	int ret;
+
+	*((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
+
+	ret = usb_control_msg(sd->gspca_dev.dev,
+			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
+			1 /* REG_IO */,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0, index,
+			sd->gspca_dev.usb_buf, n, 500);
+	if (ret < 0)
+		PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value);
+	return ret;
+}
+
+static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value)
+{
+	int rc, retries;
+
+	PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+
+	/* Three byte write cycle */
+	for (retries = 6; ; ) {
+		/* Select camera register */
+		rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
+		if (rc < 0)
+			return rc;
+
+		/* Write "value" to I2C data port of OV511 */
+		rc = reg_w(sd, R51x_I2C_DATA, value);
+		if (rc < 0)
+			return rc;
+
+		/* Initiate 3-byte write cycle */
+		rc = reg_w(sd, R511_I2C_CTL, 0x01);
+		if (rc < 0)
+			return rc;
+
+		do
+			rc = reg_r(sd, R511_I2C_CTL);
+		while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+		if (rc < 0)
+			return rc;
+
+		if ((rc & 2) == 0) /* Ack? */
+			break;
+		if (--retries < 0) {
+			PDEBUG(D_USBO, "i2c write retries exhausted");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int ov511_i2c_r(struct sd *sd, __u8 reg)
+{
+	int rc, value, retries;
+
+	/* Two byte write cycle */
+	for (retries = 6; ; ) {
+		/* Select camera register */
+		rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
+		if (rc < 0)
+			return rc;
+
+		/* Initiate 2-byte write cycle */
+		rc = reg_w(sd, R511_I2C_CTL, 0x03);
+		if (rc < 0)
+			return rc;
+
+		do
+			rc = reg_r(sd, R511_I2C_CTL);
+		while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+		if (rc < 0)
+			return rc;
+
+		if ((rc & 2) == 0) /* Ack? */
+			break;
+
+		/* I2C abort */
+		reg_w(sd, R511_I2C_CTL, 0x10);
+
+		if (--retries < 0) {
+			PDEBUG(D_USBI, "i2c write retries exhausted");
+			return -1;
+		}
+	}
+
+	/* Two byte read cycle */
+	for (retries = 6; ; ) {
+		/* Initiate 2-byte read cycle */
+		rc = reg_w(sd, R511_I2C_CTL, 0x05);
+		if (rc < 0)
+			return rc;
+
+		do
+			rc = reg_r(sd, R511_I2C_CTL);
+		while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+		if (rc < 0)
+			return rc;
+
+		if ((rc & 2) == 0) /* Ack? */
+			break;
+
+		/* I2C abort */
+		rc = reg_w(sd, R511_I2C_CTL, 0x10);
+		if (rc < 0)
+			return rc;
+
+		if (--retries < 0) {
+			PDEBUG(D_USBI, "i2c read retries exhausted");
+			return -1;
+		}
+	}
+
+	value = reg_r(sd, R51x_I2C_DATA);
+
+	PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+
+	/* This is needed to make i2c_w() work */
+	rc = reg_w(sd, R511_I2C_CTL, 0x05);
+	if (rc < 0)
+		return rc;
+
+	return value;
+}
+
+/*
  * The OV518 I2C I/O procedure is different, hence, this function.
  * This is normally only called from i2c_w(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
-static int i2c_w(struct sd *sd,
+static int ov518_i2c_w(struct sd *sd,
 		__u8 reg,
 		__u8 value)
 {
@@ -963,7 +1301,7 @@
  * This is normally only called from i2c_r(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
-static int i2c_r(struct sd *sd, __u8 reg)
+static int ov518_i2c_r(struct sd *sd, __u8 reg)
 {
 	int rc, value;
 
@@ -986,6 +1324,34 @@
 	return value;
 }
 
+static int i2c_w(struct sd *sd, __u8 reg, __u8 value)
+{
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		return ov511_i2c_w(sd, reg, value);
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+	case BRIDGE_OV519:
+		return ov518_i2c_w(sd, reg, value);
+	}
+	return -1; /* Should never happen */
+}
+
+static int i2c_r(struct sd *sd, __u8 reg)
+{
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		return ov511_i2c_r(sd, reg);
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+	case BRIDGE_OV519:
+		return ov518_i2c_r(sd, reg);
+	}
+	return -1; /* Should never happen */
+}
+
 /* Writes bits at positions specified by mask to an I2C reg. Bits that are in
  * the same position as 1's in "mask" are cleared and set to "value". Bits
  * that are in the same position as 0's in "mask" are preserved, regardless
@@ -1014,20 +1380,47 @@
 {
 	PDEBUG(D_STREAM, "stopping");
 	sd->stopped = 1;
-	return reg_w(sd, OV519_SYS_RESET1, 0x0f);
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		return reg_w(sd, R51x_SYS_RESET, 0x3d);
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
+	case BRIDGE_OV519:
+		return reg_w(sd, OV519_SYS_RESET1, 0x0f);
+	}
+
+	return 0;
 }
 
 /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
  * actually stopped (for performance). */
 static inline int ov51x_restart(struct sd *sd)
 {
+	int rc;
+
 	PDEBUG(D_STREAM, "restarting");
 	if (!sd->stopped)
 		return 0;
 	sd->stopped = 0;
 
 	/* Reinitialize the stream */
-	return reg_w(sd, OV519_SYS_RESET1, 0x00);
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		return reg_w(sd, R51x_SYS_RESET, 0x00);
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		rc = reg_w(sd, 0x2f, 0x80);
+		if (rc < 0)
+			return rc;
+		return reg_w(sd, R51x_SYS_RESET, 0x00);
+	case BRIDGE_OV519:
+		return reg_w(sd, OV519_SYS_RESET1, 0x00);
+	}
+
+	return 0;
 }
 
 /* This does an initial reset of an OmniVision sensor and ensures that I2C
@@ -1138,7 +1531,6 @@
 	}
 
 	/* Set sensor-specific vars */
-/*	sd->sif = 0;		already done */
 	return 0;
 }
 
@@ -1175,15 +1567,13 @@
 		}
 	} else if ((rc & 3) == 1) {
 		/* I don't know what's different about the 76BE yet. */
-		if (i2c_r(sd, 0x15) & 1)
+		if (i2c_r(sd, 0x15) & 1) {
 			PDEBUG(D_PROBE, "Sensor is an OV7620AE");
-		else
+			sd->sensor = SEN_OV7620;
+		} else {
 			PDEBUG(D_PROBE, "Sensor is an OV76BE");
-
-		/* OV511+ will return all zero isoc data unless we
-		 * configure the sensor as a 7620. Someone needs to
-		 * find the exact reg. setting that causes this. */
-		sd->sensor = SEN_OV76BE;
+			sd->sensor = SEN_OV76BE;
+		}
 	} else if ((rc & 3) == 0) {
 		/* try to read product id registers */
 		high = i2c_r(sd, 0x0a);
@@ -1229,7 +1619,6 @@
 	}
 
 	/* Set sensor-specific vars */
-/*	sd->sif = 0;		already done */
 	return 0;
 }
 
@@ -1258,13 +1647,14 @@
 		break;
 	case 0x01:
 		sd->sensor = SEN_OV6620;
+		PDEBUG(D_PROBE, "Sensor is an OV6620");
 		break;
 	case 0x02:
 		sd->sensor = SEN_OV6630;
 		PDEBUG(D_PROBE, "Sensor is an OV66308AE");
 		break;
 	case 0x03:
-		sd->sensor = SEN_OV6630;
+		sd->sensor = SEN_OV66308AF;
 		PDEBUG(D_PROBE, "Sensor is an OV66308AF");
 		break;
 	case 0x90:
@@ -1287,16 +1677,276 @@
 /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
 static void ov51x_led_control(struct sd *sd, int on)
 {
-	reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1);	/* 0 / 1 */
+	if (sd->invert_led)
+		on = !on;
+
+	switch (sd->bridge) {
+	/* OV511 has no LED control */
+	case BRIDGE_OV511PLUS:
+		reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0);
+		break;
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02);
+		break;
+	case BRIDGE_OV519:
+		reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1);	/* 0 / 1 */
+		break;
+	}
 }
 
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-			const struct usb_device_id *id)
+static int ov51x_upload_quan_tables(struct sd *sd)
+{
+	const unsigned char yQuanTable511[] = {
+		0, 1, 1, 2, 2, 3, 3, 4,
+		1, 1, 1, 2, 2, 3, 4, 4,
+		1, 1, 2, 2, 3, 4, 4, 4,
+		2, 2, 2, 3, 4, 4, 4, 4,
+		2, 2, 3, 4, 4, 5, 5, 5,
+		3, 3, 4, 4, 5, 5, 5, 5,
+		3, 4, 4, 4, 5, 5, 5, 5,
+		4, 4, 4, 4, 5, 5, 5, 5
+	};
+
+	const unsigned char uvQuanTable511[] = {
+		0, 2, 2, 3, 4, 4, 4, 4,
+		2, 2, 2, 4, 4, 4, 4, 4,
+		2, 2, 3, 4, 4, 4, 4, 4,
+		3, 4, 4, 4, 4, 4, 4, 4,
+		4, 4, 4, 4, 4, 4, 4, 4,
+		4, 4, 4, 4, 4, 4, 4, 4,
+		4, 4, 4, 4, 4, 4, 4, 4,
+		4, 4, 4, 4, 4, 4, 4, 4
+	};
+
+	/* OV518 quantization tables are 8x4 (instead of 8x8) */
+	const unsigned char yQuanTable518[] = {
+		5, 4, 5, 6, 6, 7, 7, 7,
+		5, 5, 5, 5, 6, 7, 7, 7,
+		6, 6, 6, 6, 7, 7, 7, 8,
+		7, 7, 6, 7, 7, 7, 8, 8
+	};
+
+	const unsigned char uvQuanTable518[] = {
+		6, 6, 6, 7, 7, 7, 7, 7,
+		6, 6, 6, 7, 7, 7, 7, 7,
+		6, 6, 6, 7, 7, 7, 7, 8,
+		7, 7, 7, 7, 7, 7, 8, 8
+	};
+
+	const unsigned char *pYTable, *pUVTable;
+	unsigned char val0, val1;
+	int i, size, rc, reg = R51x_COMP_LUT_BEGIN;
+
+	PDEBUG(D_PROBE, "Uploading quantization tables");
+
+	if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
+		pYTable = yQuanTable511;
+		pUVTable = uvQuanTable511;
+		size  = 32;
+	} else {
+		pYTable = yQuanTable518;
+		pUVTable = uvQuanTable518;
+		size  = 16;
+	}
+
+	for (i = 0; i < size; i++) {
+		val0 = *pYTable++;
+		val1 = *pYTable++;
+		val0 &= 0x0f;
+		val1 &= 0x0f;
+		val0 |= val1 << 4;
+		rc = reg_w(sd, reg, val0);
+		if (rc < 0)
+			return rc;
+
+		val0 = *pUVTable++;
+		val1 = *pUVTable++;
+		val0 &= 0x0f;
+		val1 &= 0x0f;
+		val0 |= val1 << 4;
+		rc = reg_w(sd, reg + size, val0);
+		if (rc < 0)
+			return rc;
+
+		reg++;
+	}
+
+	return 0;
+}
+
+/* This initializes the OV511/OV511+ and the sensor */
+static int ov511_configure(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct cam *cam;
+	int rc;
+
+	/* For 511 and 511+ */
+	const struct ov_regvals init_511[] = {
+		{ R51x_SYS_RESET,	0x7f },
+		{ R51x_SYS_INIT,	0x01 },
+		{ R51x_SYS_RESET,	0x7f },
+		{ R51x_SYS_INIT,	0x01 },
+		{ R51x_SYS_RESET,	0x3f },
+		{ R51x_SYS_INIT,	0x01 },
+		{ R51x_SYS_RESET,	0x3d },
+	};
+
+	const struct ov_regvals norm_511[] = {
+		{ R511_DRAM_FLOW_CTL, 	0x01 },
+		{ R51x_SYS_SNAP,	0x00 },
+		{ R51x_SYS_SNAP,	0x02 },
+		{ R51x_SYS_SNAP,	0x00 },
+		{ R511_FIFO_OPTS,	0x1f },
+		{ R511_COMP_EN,		0x00 },
+		{ R511_COMP_LUT_EN,	0x03 },
+	};
+
+	const struct ov_regvals norm_511_p[] = {
+		{ R511_DRAM_FLOW_CTL,	0xff },
+		{ R51x_SYS_SNAP,	0x00 },
+		{ R51x_SYS_SNAP,	0x02 },
+		{ R51x_SYS_SNAP,	0x00 },
+		{ R511_FIFO_OPTS,	0xff },
+		{ R511_COMP_EN,		0x00 },
+		{ R511_COMP_LUT_EN,	0x03 },
+	};
+
+	const struct ov_regvals compress_511[] = {
+		{ 0x70, 0x1f },
+		{ 0x71, 0x05 },
+		{ 0x72, 0x06 },
+		{ 0x73, 0x06 },
+		{ 0x74, 0x14 },
+		{ 0x75, 0x03 },
+		{ 0x76, 0x04 },
+		{ 0x77, 0x04 },
+	};
+
+	PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
+
+	rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511));
+	if (rc < 0)
+		return rc;
+
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+		rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
+		if (rc < 0)
+			return rc;
+		break;
+	case BRIDGE_OV511PLUS:
+		rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
+		if (rc < 0)
+			return rc;
+		break;
+	}
+
+	/* Init compression */
+	rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
+	if (rc < 0)
+		return rc;
+
+	rc = ov51x_upload_quan_tables(sd);
+	if (rc < 0) {
+		PDEBUG(D_ERR, "Error uploading quantization tables");
+		return rc;
+	}
+
+	return 0;
+}
+
+/* This initializes the OV518/OV518+ and the sensor */
+static int ov518_configure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int rc;
+
+	/* For 518 and 518+ */
+	const struct ov_regvals init_518[] = {
+		{ R51x_SYS_RESET,	0x40 },
+		{ R51x_SYS_INIT,	0xe1 },
+		{ R51x_SYS_RESET,	0x3e },
+		{ R51x_SYS_INIT,	0xe1 },
+		{ R51x_SYS_RESET,	0x00 },
+		{ R51x_SYS_INIT,	0xe1 },
+		{ 0x46,			0x00 },
+		{ 0x5d,			0x03 },
+	};
+
+	const struct ov_regvals norm_518[] = {
+		{ R51x_SYS_SNAP,	0x02 }, /* Reset */
+		{ R51x_SYS_SNAP,	0x01 }, /* Enable */
+		{ 0x31, 		0x0f },
+		{ 0x5d,			0x03 },
+		{ 0x24,			0x9f },
+		{ 0x25,			0x90 },
+		{ 0x20,			0x00 },
+		{ 0x51,			0x04 },
+		{ 0x71,			0x19 },
+		{ 0x2f,			0x80 },
+	};
+
+	const struct ov_regvals norm_518_p[] = {
+		{ R51x_SYS_SNAP,	0x02 }, /* Reset */
+		{ R51x_SYS_SNAP,	0x01 }, /* Enable */
+		{ 0x31, 		0x0f },
+		{ 0x5d,			0x03 },
+		{ 0x24,			0x9f },
+		{ 0x25,			0x90 },
+		{ 0x20,			0x60 },
+		{ 0x51,			0x02 },
+		{ 0x71,			0x19 },
+		{ 0x40,			0xff },
+		{ 0x41,			0x42 },
+		{ 0x46,			0x00 },
+		{ 0x33,			0x04 },
+		{ 0x21,			0x19 },
+		{ 0x3f,			0x10 },
+		{ 0x2f,			0x80 },
+	};
+
+	/* First 5 bits of custom ID reg are a revision ID on OV518 */
+	PDEBUG(D_PROBE, "Device revision %d",
+	       0x1F & reg_r(sd, R51x_SYS_CUST_ID));
+
+	rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518));
+	if (rc < 0)
+		return rc;
+
+	/* Set LED GPIO pin to output mode */
+	rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
+	if (rc < 0)
+		return rc;
+
+	switch (sd->bridge) {
+	case BRIDGE_OV518:
+		rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
+		if (rc < 0)
+			return rc;
+		break;
+	case BRIDGE_OV518PLUS:
+		rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
+		if (rc < 0)
+			return rc;
+		break;
+	}
+
+	rc = ov51x_upload_quan_tables(sd);
+	if (rc < 0) {
+		PDEBUG(D_ERR, "Error uploading quantization tables");
+		return rc;
+	}
 
+	rc = reg_w(sd, 0x2f, 0x80);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
+static int ov519_configure(struct sd *sd)
+{
 	static const struct ov_regvals init_519[] = {
 		{ 0x5a,  0x6d }, /* EnableSystem */
 		{ 0x53,  0x9b },
@@ -1313,8 +1963,37 @@
 		/* windows reads 0x55 at this point*/
 	};
 
-	if (write_regvals(sd, init_519, ARRAY_SIZE(init_519)))
+	return write_regvals(sd, init_519, ARRAY_SIZE(init_519));
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+			const struct usb_device_id *id)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct cam *cam;
+	int ret = 0;
+
+	sd->bridge = id->driver_info & BRIDGE_MASK;
+	sd->invert_led = id->driver_info & BRIDGE_INVERT_LED;
+
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		ret = ov511_configure(gspca_dev);
+		break;
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		ret = ov518_configure(gspca_dev);
+		break;
+	case BRIDGE_OV519:
+		ret = ov519_configure(sd);
+		break;
+	}
+
+	if (ret)
 		goto error;
+
 	ov51x_led_control(sd, 0);	/* turn LED off */
 
 	/* Test for 76xx */
@@ -1360,21 +2039,60 @@
 	}
 
 	cam = &gspca_dev->cam;
-	if (!sd->sif) {
-		cam->cam_mode = vga_mode;
-		cam->nmodes = ARRAY_SIZE(vga_mode);
-	} else {
-		cam->cam_mode = sif_mode;
-		cam->nmodes = ARRAY_SIZE(sif_mode);
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		if (!sd->sif) {
+			cam->cam_mode = ov511_vga_mode;
+			cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
+		} else {
+			cam->cam_mode = ov511_sif_mode;
+			cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
+		}
+		break;
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		if (!sd->sif) {
+			cam->cam_mode = ov518_vga_mode;
+			cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
+		} else {
+			cam->cam_mode = ov518_sif_mode;
+			cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
+		}
+		break;
+	case BRIDGE_OV519:
+		if (!sd->sif) {
+			cam->cam_mode = ov519_vga_mode;
+			cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
+		} else {
+			cam->cam_mode = ov519_sif_mode;
+			cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
+		}
+		break;
 	}
 	sd->brightness = BRIGHTNESS_DEF;
-	sd->contrast = CONTRAST_DEF;
+	if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF)
+		sd->contrast = 200; /* The default is too low for the ov6630 */
+	else
+		sd->contrast = CONTRAST_DEF;
 	sd->colors = COLOR_DEF;
 	sd->hflip = HFLIP_DEF;
 	sd->vflip = VFLIP_DEF;
-	if (sd->sensor != SEN_OV7670)
-		gspca_dev->ctrl_dis = (1 << HFLIP_IDX)
-					| (1 << VFLIP_IDX);
+	sd->autobrightness = AUTOBRIGHT_DEF;
+	if (sd->sensor == SEN_OV7670) {
+		sd->freq = OV7670_FREQ_DEF;
+		gspca_dev->ctrl_dis = 1 << FREQ_IDX;
+	} else {
+		sd->freq = FREQ_DEF;
+		gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) |
+				      (1 << OV7670_FREQ_IDX);
+	}
+	if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
+		gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
+	/* OV8610 Frequency filter control should work but needs testing */
+	if (sd->sensor == SEN_OV8610)
+		gspca_dev->ctrl_dis |= 1 << FREQ_IDX;
+
 	return 0;
 error:
 	PDEBUG(D_ERR, "OV519 Config failed");
@@ -1393,6 +2111,7 @@
 			return -EIO;
 		break;
 	case SEN_OV6630:
+	case SEN_OV66308AF:
 		if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
 			return -EIO;
 		break;
@@ -1401,6 +2120,8 @@
 /*	case SEN_OV76BE: */
 		if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
 			return -EIO;
+		if (i2c_w_mask(sd, 0x0e, 0x00, 0x40))
+			return -EIO;
 		break;
 	case SEN_OV7620:
 		if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
@@ -1422,6 +2143,248 @@
 	return 0;
 }
 
+/* Set up the OV511/OV511+ with the given image parameters.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int ov511_mode_init_regs(struct sd *sd)
+{
+	int hsegs, vsegs, packet_size, fps, needed;
+	int interlaced = 0;
+	struct usb_host_interface *alt;
+	struct usb_interface *intf;
+
+	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+	if (!alt) {
+		PDEBUG(D_ERR, "Couldn't get altsetting");
+		return -EIO;
+	}
+
+	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+	reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
+
+	reg_w(sd, R511_CAM_UV_EN, 0x01);
+	reg_w(sd, R511_SNAP_UV_EN, 0x01);
+	reg_w(sd, R511_SNAP_OPTS, 0x03);
+
+	/* Here I'm assuming that snapshot size == image size.
+	 * I hope that's always true. --claudio
+	 */
+	hsegs = (sd->gspca_dev.width >> 3) - 1;
+	vsegs = (sd->gspca_dev.height >> 3) - 1;
+
+	reg_w(sd, R511_CAM_PXCNT, hsegs);
+	reg_w(sd, R511_CAM_LNCNT, vsegs);
+	reg_w(sd, R511_CAM_PXDIV, 0x00);
+	reg_w(sd, R511_CAM_LNDIV, 0x00);
+
+	/* YUV420, low pass filter on */
+	reg_w(sd, R511_CAM_OPTS, 0x03);
+
+	/* Snapshot additions */
+	reg_w(sd, R511_SNAP_PXCNT, hsegs);
+	reg_w(sd, R511_SNAP_LNCNT, vsegs);
+	reg_w(sd, R511_SNAP_PXDIV, 0x00);
+	reg_w(sd, R511_SNAP_LNDIV, 0x00);
+
+	/******** Set the framerate ********/
+	if (frame_rate > 0)
+		sd->frame_rate = frame_rate;
+
+	switch (sd->sensor) {
+	case SEN_OV6620:
+		/* No framerate control, doesn't like higher rates yet */
+		sd->clockdiv = 3;
+		break;
+
+	/* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
+	   for more sensors we need to do this for them too */
+	case SEN_OV7620:
+	case SEN_OV7640:
+	case SEN_OV76BE:
+		if (sd->gspca_dev.width == 320)
+			interlaced = 1;
+		/* Fall through */
+	case SEN_OV6630:
+	case SEN_OV7610:
+	case SEN_OV7670:
+		switch (sd->frame_rate) {
+		case 30:
+		case 25:
+			/* Not enough bandwidth to do 640x480 @ 30 fps */
+			if (sd->gspca_dev.width != 640) {
+				sd->clockdiv = 0;
+				break;
+			}
+			/* Fall through for 640x480 case */
+		default:
+/*		case 20: */
+/*		case 15: */
+			sd->clockdiv = 1;
+			break;
+		case 10:
+			sd->clockdiv = 2;
+			break;
+		case 5:
+			sd->clockdiv = 5;
+			break;
+		}
+		if (interlaced) {
+			sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
+			/* Higher then 10 does not work */
+			if (sd->clockdiv > 10)
+				sd->clockdiv = 10;
+		}
+		break;
+
+	case SEN_OV8610:
+		/* No framerate control ?? */
+		sd->clockdiv = 0;
+		break;
+	}
+
+	/* Check if we have enough bandwidth to disable compression */
+	fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
+	needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
+	/* 1400 is a conservative estimate of the max nr of isoc packets/sec */
+	if (needed > 1400 * packet_size) {
+		/* Enable Y and UV quantization and compression */
+		reg_w(sd, R511_COMP_EN, 0x07);
+		reg_w(sd, R511_COMP_LUT_EN, 0x03);
+	} else {
+		reg_w(sd, R511_COMP_EN, 0x06);
+		reg_w(sd, R511_COMP_LUT_EN, 0x00);
+	}
+
+	reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
+	reg_w(sd, R51x_SYS_RESET, 0);
+
+	return 0;
+}
+
+/* Sets up the OV518/OV518+ with the given image parameters
+ *
+ * OV518 needs a completely different approach, until we can figure out what
+ * the individual registers do. Also, only 15 FPS is supported now.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int ov518_mode_init_regs(struct sd *sd)
+{
+	int hsegs, vsegs, packet_size;
+	struct usb_host_interface *alt;
+	struct usb_interface *intf;
+
+	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+	if (!alt) {
+		PDEBUG(D_ERR, "Couldn't get altsetting");
+		return -EIO;
+	}
+
+	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+	ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
+
+	/******** Set the mode ********/
+
+	reg_w(sd, 0x2b, 0);
+	reg_w(sd, 0x2c, 0);
+	reg_w(sd, 0x2d, 0);
+	reg_w(sd, 0x2e, 0);
+	reg_w(sd, 0x3b, 0);
+	reg_w(sd, 0x3c, 0);
+	reg_w(sd, 0x3d, 0);
+	reg_w(sd, 0x3e, 0);
+
+	if (sd->bridge == BRIDGE_OV518) {
+		/* Set 8-bit (YVYU) input format */
+		reg_w_mask(sd, 0x20, 0x08, 0x08);
+
+		/* Set 12-bit (4:2:0) output format */
+		reg_w_mask(sd, 0x28, 0x80, 0xf0);
+		reg_w_mask(sd, 0x38, 0x80, 0xf0);
+	} else {
+		reg_w(sd, 0x28, 0x80);
+		reg_w(sd, 0x38, 0x80);
+	}
+
+	hsegs = sd->gspca_dev.width / 16;
+	vsegs = sd->gspca_dev.height / 4;
+
+	reg_w(sd, 0x29, hsegs);
+	reg_w(sd, 0x2a, vsegs);
+
+	reg_w(sd, 0x39, hsegs);
+	reg_w(sd, 0x3a, vsegs);
+
+	/* Windows driver does this here; who knows why */
+	reg_w(sd, 0x2f, 0x80);
+
+	/******** Set the framerate  ********/
+	sd->clockdiv = 1;
+
+	/* Mode independent, but framerate dependent, regs */
+	/* 0x51: Clock divider; Only works on some cams which use 2 crystals */
+	reg_w(sd, 0x51, 0x04);
+	reg_w(sd, 0x22, 0x18);
+	reg_w(sd, 0x23, 0xff);
+
+	if (sd->bridge == BRIDGE_OV518PLUS) {
+		switch (sd->sensor) {
+		case SEN_OV7620:
+			if (sd->gspca_dev.width == 320) {
+				reg_w(sd, 0x20, 0x00);
+				reg_w(sd, 0x21, 0x19);
+			} else {
+				reg_w(sd, 0x20, 0x60);
+				reg_w(sd, 0x21, 0x1f);
+			}
+			break;
+		default:
+			reg_w(sd, 0x21, 0x19);
+		}
+	} else
+		reg_w(sd, 0x71, 0x17);	/* Compression-related? */
+
+	/* FIXME: Sensor-specific */
+	/* Bit 5 is what matters here. Of course, it is "reserved" */
+	i2c_w(sd, 0x54, 0x23);
+
+	reg_w(sd, 0x2f, 0x80);
+
+	if (sd->bridge == BRIDGE_OV518PLUS) {
+		reg_w(sd, 0x24, 0x94);
+		reg_w(sd, 0x25, 0x90);
+		ov518_reg_w32(sd, 0xc4,    400, 2);	/* 190h   */
+		ov518_reg_w32(sd, 0xc6,    540, 2);	/* 21ch   */
+		ov518_reg_w32(sd, 0xc7,    540, 2);	/* 21ch   */
+		ov518_reg_w32(sd, 0xc8,    108, 2);	/* 6ch    */
+		ov518_reg_w32(sd, 0xca, 131098, 3);	/* 2001ah */
+		ov518_reg_w32(sd, 0xcb,    532, 2);	/* 214h   */
+		ov518_reg_w32(sd, 0xcc,   2400, 2);	/* 960h   */
+		ov518_reg_w32(sd, 0xcd,     32, 2);	/* 20h    */
+		ov518_reg_w32(sd, 0xce,    608, 2);	/* 260h   */
+	} else {
+		reg_w(sd, 0x24, 0x9f);
+		reg_w(sd, 0x25, 0x90);
+		ov518_reg_w32(sd, 0xc4,    400, 2);	/* 190h   */
+		ov518_reg_w32(sd, 0xc6,    381, 2);	/* 17dh   */
+		ov518_reg_w32(sd, 0xc7,    381, 2);	/* 17dh   */
+		ov518_reg_w32(sd, 0xc8,    128, 2);	/* 80h    */
+		ov518_reg_w32(sd, 0xca, 183331, 3);	/* 2cc23h */
+		ov518_reg_w32(sd, 0xcb,    746, 2);	/* 2eah   */
+		ov518_reg_w32(sd, 0xcc,   1750, 2);	/* 6d6h   */
+		ov518_reg_w32(sd, 0xcd,     45, 2);	/* 2dh    */
+		ov518_reg_w32(sd, 0xce,    851, 2);	/* 353h   */
+	}
+
+	reg_w(sd, 0x2f, 0x80);
+
+	return 0;
+}
+
+
 /* Sets up the OV519 with the given image parameters
  *
  * OV519 needs a completely different approach, until we can figure out what
@@ -1492,7 +2455,11 @@
 
 	reg_w(sd, OV519_R10_H_SIZE,	sd->gspca_dev.width >> 4);
 	reg_w(sd, OV519_R11_V_SIZE,	sd->gspca_dev.height >> 3);
-	reg_w(sd, OV519_R12_X_OFFSETL,	0x00);
+	if (sd->sensor == SEN_OV7670 &&
+	    sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
+		reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
+	else
+		reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
 	reg_w(sd, OV519_R13_X_OFFSETH,	0x00);
 	reg_w(sd, OV519_R14_Y_OFFSETL,	0x00);
 	reg_w(sd, OV519_R15_Y_OFFSETH,	0x00);
@@ -1584,7 +2551,7 @@
 	int qvga;
 
 	gspca_dev = &sd->gspca_dev;
-	qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+	qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
 
 	/******** Mode (VGA/QVGA) and sensor specific regs ********/
 	switch (sd->sensor) {
@@ -1596,21 +2563,16 @@
 		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
 		break;
 	case SEN_OV7620:
-/*		i2c_w(sd, 0x2b, 0x00); */
+	case SEN_OV76BE:
 		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
 		i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
 		i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
 		i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
 		i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
-		i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
+		i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0);
 		i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
 		break;
-	case SEN_OV76BE:
-/*		i2c_w(sd, 0x2b, 0x00); */
-		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-		break;
 	case SEN_OV7640:
-/*		i2c_w(sd, 0x2b, 0x00); */
 		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
 		i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
 /*		i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */
@@ -1629,6 +2591,7 @@
 		break;
 	case SEN_OV6620:
 	case SEN_OV6630:
+	case SEN_OV66308AF:
 		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
 		break;
 	default:
@@ -1636,10 +2599,6 @@
 	}
 
 	/******** Palette-specific regs ********/
-	if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
-		/* not valid on the OV6620/OV7620/6630? */
-		i2c_w_mask(sd, 0x0e, 0x00, 0x40);
-	}
 
 	/* The OV518 needs special treatment. Although both the OV518
 	 * and the OV6630 support a 16-bit video bus, only the 8 bit Y
@@ -1649,25 +2608,12 @@
 
 	/* OV7640 is 8-bit only */
 
-	if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)
+	if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF &&
+					sd->sensor != SEN_OV7640)
 		i2c_w_mask(sd, 0x13, 0x00, 0x20);
 
 	/******** Clock programming ********/
-	/* The OV6620 needs special handling. This prevents the
-	 * severe banding that normally occurs */
-	if (sd->sensor == SEN_OV6620) {
-
-		/* Clock down */
-		i2c_w(sd, 0x2a, 0x04);
-		i2c_w(sd, 0x11, sd->clockdiv);
-		i2c_w(sd, 0x2a, 0x84);
-		/* This next setting is critical. It seems to improve
-		 * the gain or the contrast. The "reserved" bits seem
-		 * to have some effect in this case. */
-		i2c_w(sd, 0x2d, 0x85);
-	} else {
-		i2c_w(sd, 0x11, sd->clockdiv);
-	}
+	i2c_w(sd, 0x11, sd->clockdiv);
 
 	/******** Special Features ********/
 /* no evidence this is possible with OV7670, either */
@@ -1711,13 +2657,14 @@
 static int set_ov_sensor_window(struct sd *sd)
 {
 	struct gspca_dev *gspca_dev;
-	int qvga;
+	int qvga, crop;
 	int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
 	int ret, hstart, hstop, vstop, vstart;
 	__u8 v;
 
 	gspca_dev = &sd->gspca_dev;
-	qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+	qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
+	crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2;
 
 	/* The different sensor ICs handle setting up of window differently.
 	 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
@@ -1736,10 +2683,20 @@
 		break;
 	case SEN_OV6620:
 	case SEN_OV6630:
+	case SEN_OV66308AF:
 		hwsbase = 0x38;
 		hwebase = 0x3a;
 		vwsbase = 0x05;
 		vwebase = 0x06;
+		if (sd->sensor == SEN_OV66308AF && qvga)
+			/* HDG: this fixes U and V getting swapped */
+			hwsbase++;
+		if (crop) {
+			hwsbase += 8;
+			hwebase += 8;
+			vwsbase += 11;
+			vwebase += 11;
+		}
 		break;
 	case SEN_OV7620:
 		hwsbase = 0x2f;		/* From 7620.SET (spec is wrong) */
@@ -1763,6 +2720,7 @@
 	switch (sd->sensor) {
 	case SEN_OV6620:
 	case SEN_OV6630:
+	case SEN_OV66308AF:
 		if (qvga) {		/* QCIF */
 			hwscale = 0;
 			vwscale = 0;
@@ -1815,7 +2773,7 @@
 		if (qvga) {		/* QVGA from ov7670.c by
 					 * Jonathan Corbet */
 			hstart = 164;
-			hstop = 20;
+			hstop = 28;
 			vstart = 14;
 			vstop = 494;
 		} else {		/* VGA */
@@ -1841,7 +2799,6 @@
 		msleep(10);	/* need to sleep between read and write to
 				 * same reg! */
 		i2c_w(sd, OV7670_REG_VREF, v);
-		sethvflip(sd);
 	} else {
 		i2c_w(sd, 0x17, hwsbase);
 		i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale));
@@ -1855,15 +2812,35 @@
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int ret;
+	int ret = 0;
 
-	ret = ov519_mode_init_regs(sd);
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		ret = ov511_mode_init_regs(sd);
+		break;
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		ret = ov518_mode_init_regs(sd);
+		break;
+	case BRIDGE_OV519:
+		ret = ov519_mode_init_regs(sd);
+		break;
+	}
 	if (ret < 0)
 		goto out;
+
 	ret = set_ov_sensor_window(sd);
 	if (ret < 0)
 		goto out;
 
+	setcontrast(gspca_dev);
+	setbrightness(gspca_dev);
+	setcolors(gspca_dev);
+	sethvflip(sd);
+	setautobrightness(sd);
+	setfreq(sd);
+
 	ret = ov51x_restart(sd);
 	if (ret < 0)
 		goto out;
@@ -1882,7 +2859,95 @@
 	ov51x_led_control(sd, 0);
 }
 
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
+			struct gspca_frame *frame,	/* target */
+			__u8 *in,			/* isoc packet */
+			int len)			/* iso packet length */
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
+	 * byte non-zero. The EOF packet has image width/height in the
+	 * 10th and 11th bytes. The 9th byte is given as follows:
+	 *
+	 * bit 7: EOF
+	 *     6: compression enabled
+	 *     5: 422/420/400 modes
+	 *     4: 422/420/400 modes
+	 *     3: 1
+	 *     2: snapshot button on
+	 *     1: snapshot frame
+	 *     0: even/odd field
+	 */
+	if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
+	    (in[8] & 0x08)) {
+		if (in[8] & 0x80) {
+			/* Frame end */
+			if ((in[9] + 1) * 8 != gspca_dev->width ||
+			    (in[10] + 1) * 8 != gspca_dev->height) {
+				PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
+					" requested: %dx%d\n",
+					(in[9] + 1) * 8, (in[10] + 1) * 8,
+					gspca_dev->width, gspca_dev->height);
+				gspca_dev->last_packet_type = DISCARD_PACKET;
+				return;
+			}
+			/* Add 11 byte footer to frame, might be usefull */
+			gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11);
+			return;
+		} else {
+			/* Frame start */
+			gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0);
+			sd->packet_nr = 0;
+		}
+	}
+
+	/* Ignore the packet number */
+	len--;
+
+	/* intermediate packet */
+	gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len);
+}
+
+static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
+			struct gspca_frame *frame,	/* target */
+			__u8 *data,			/* isoc packet */
+			int len)			/* iso packet length */
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* A false positive here is likely, until OVT gives me
+	 * the definitive SOF/EOF format */
+	if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
+		gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0);
+		sd->packet_nr = 0;
+	}
+
+	if (gspca_dev->last_packet_type == DISCARD_PACKET)
+		return;
+
+	/* Does this device use packet numbers ? */
+	if (len & 7) {
+		len--;
+		if (sd->packet_nr == data[len])
+			sd->packet_nr++;
+		/* The last few packets of the frame (which are all 0's
+		   except that they may contain part of the footer), are
+		   numbered 0 */
+		else if (sd->packet_nr == 0 || data[len]) {
+			PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
+				(int)data[len], (int)sd->packet_nr);
+			gspca_dev->last_packet_type = DISCARD_PACKET;
+			return;
+		}
+	}
+
+	/* intermediate packet */
+	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+}
+
+static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
 			__u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
@@ -1926,6 +2991,28 @@
 			data, len);
 }
 
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			struct gspca_frame *frame,	/* target */
+			__u8 *data,			/* isoc packet */
+			int len)			/* iso packet length */
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	switch (sd->bridge) {
+	case BRIDGE_OV511:
+	case BRIDGE_OV511PLUS:
+		ov511_pkt_scan(gspca_dev, frame, data, len);
+		break;
+	case BRIDGE_OV518:
+	case BRIDGE_OV518PLUS:
+		ov518_pkt_scan(gspca_dev, frame, data, len);
+		break;
+	case BRIDGE_OV519:
+		ov519_pkt_scan(gspca_dev, frame, data, len);
+		break;
+	}
+}
+
 /* -- management routines -- */
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -1940,13 +3027,13 @@
 	case SEN_OV76BE:
 	case SEN_OV6620:
 	case SEN_OV6630:
+	case SEN_OV66308AF:
 	case SEN_OV7640:
 		i2c_w(sd, OV7610_REG_BRT, val);
 		break;
 	case SEN_OV7620:
 		/* 7620 doesn't like manual changes when in auto mode */
-/*fixme
- *		if (!sd->auto_brt) */
+		if (!sd->autobrightness)
 			i2c_w(sd, OV7610_REG_BRT, val);
 		break;
 	case SEN_OV7670:
@@ -1969,7 +3056,9 @@
 		i2c_w(sd, OV7610_REG_CNT, val);
 		break;
 	case SEN_OV6630:
+	case SEN_OV66308AF:
 		i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
+		break;
 	case SEN_OV8610: {
 		static const __u8 ctab[] = {
 			0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
@@ -2012,6 +3101,7 @@
 	case SEN_OV76BE:
 	case SEN_OV6620:
 	case SEN_OV6630:
+	case SEN_OV66308AF:
 		i2c_w(sd, OV7610_REG_SAT, val);
 		break;
 	case SEN_OV7620:
@@ -2032,6 +3122,72 @@
 	}
 }
 
+static void setautobrightness(struct sd *sd)
+{
+	if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
+		return;
+
+	i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10);
+}
+
+static void setfreq(struct sd *sd)
+{
+	if (sd->sensor == SEN_OV7670) {
+		switch (sd->freq) {
+		case 0: /* Banding filter disabled */
+			i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT);
+			break;
+		case 1: /* 50 hz */
+			i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+				   OV7670_COM8_BFILT);
+			i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18);
+			break;
+		case 2: /* 60 hz */
+			i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+				   OV7670_COM8_BFILT);
+			i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18);
+			break;
+		case 3: /* Auto hz */
+			i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+				   OV7670_COM8_BFILT);
+			i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO,
+				   0x18);
+			break;
+		}
+	} else {
+		switch (sd->freq) {
+		case 0: /* Banding filter disabled */
+			i2c_w_mask(sd, 0x2d, 0x00, 0x04);
+			i2c_w_mask(sd, 0x2a, 0x00, 0x80);
+			break;
+		case 1: /* 50 hz (filter on and framerate adj) */
+			i2c_w_mask(sd, 0x2d, 0x04, 0x04);
+			i2c_w_mask(sd, 0x2a, 0x80, 0x80);
+			/* 20 fps -> 16.667 fps */
+			if (sd->sensor == SEN_OV6620 ||
+			    sd->sensor == SEN_OV6630 ||
+			    sd->sensor == SEN_OV66308AF)
+				i2c_w(sd, 0x2b, 0x5e);
+			else
+				i2c_w(sd, 0x2b, 0xac);
+			break;
+		case 2: /* 60 hz (filter on, ...) */
+			i2c_w_mask(sd, 0x2d, 0x04, 0x04);
+			if (sd->sensor == SEN_OV6620 ||
+			    sd->sensor == SEN_OV6630 ||
+			    sd->sensor == SEN_OV66308AF) {
+				/* 20 fps -> 15 fps */
+				i2c_w_mask(sd, 0x2a, 0x80, 0x80);
+				i2c_w(sd, 0x2b, 0xa8);
+			} else {
+				/* no framerate adj. */
+				i2c_w_mask(sd, 0x2a, 0x00, 0x80);
+			}
+			break;
+		}
+	}
+}
+
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -2122,6 +3278,71 @@
 	return 0;
 }
 
+static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->autobrightness = val;
+	if (gspca_dev->streaming)
+		setautobrightness(sd);
+	return 0;
+}
+
+static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->autobrightness;
+	return 0;
+}
+
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->freq = val;
+	if (gspca_dev->streaming)
+		setfreq(sd);
+	return 0;
+}
+
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->freq;
+	return 0;
+}
+
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+			struct v4l2_querymenu *menu)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	switch (menu->id) {
+	case V4L2_CID_POWER_LINE_FREQUENCY:
+		switch (menu->index) {
+		case 0:		/* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
+			strcpy((char *) menu->name, "NoFliker");
+			return 0;
+		case 1:		/* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
+			strcpy((char *) menu->name, "50 Hz");
+			return 0;
+		case 2:		/* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
+			strcpy((char *) menu->name, "60 Hz");
+			return 0;
+		case 3:
+			if (sd->sensor != SEN_OV7670)
+				return -EINVAL;
+
+			strcpy((char *) menu->name, "Automatic");
+			return 0;
+		}
+		break;
+	}
+	return -EINVAL;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -2132,23 +3353,31 @@
 	.start = sd_start,
 	.stopN = sd_stopN,
 	.pkt_scan = sd_pkt_scan,
+	.querymenu = sd_querymenu,
 };
 
 /* -- module initialisation -- */
 static const __devinitdata struct usb_device_id device_table[] = {
-	{USB_DEVICE(0x041e, 0x4052)},
-	{USB_DEVICE(0x041e, 0x405f)},
-	{USB_DEVICE(0x041e, 0x4060)},
-	{USB_DEVICE(0x041e, 0x4061)},
-	{USB_DEVICE(0x041e, 0x4064)},
-	{USB_DEVICE(0x041e, 0x4068)},
-	{USB_DEVICE(0x045e, 0x028c)},
-	{USB_DEVICE(0x054c, 0x0154)},
-	{USB_DEVICE(0x054c, 0x0155)},
-	{USB_DEVICE(0x05a9, 0x0519)},
-	{USB_DEVICE(0x05a9, 0x0530)},
-	{USB_DEVICE(0x05a9, 0x4519)},
-	{USB_DEVICE(0x05a9, 0x8519)},
+	{USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x041e, 0x4064),
+	 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+	{USB_DEVICE(0x041e, 0x4068),
+	 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+	{USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
+	{USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
+	{USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
+	{USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
+	{USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
+	{USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
 	{}
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/ov534.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/ov534.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/ov534.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/ov534.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,10 +60,23 @@
 static struct ctrl sd_ctrls[] = {
 };
 
-static const struct v4l2_pix_format vga_mode[] = {
+static const struct v4l2_pix_format vga_yuyv_mode[] = {
 	{640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 	 .bytesperline = 640 * 2,
 	 .sizeimage = 640 * 480 * 2,
+	 .colorspace = V4L2_COLORSPACE_SRGB,
+	 .priv = 0},
+};
+
+static const struct v4l2_pix_format vga_jpeg_mode[] = {
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+	 .bytesperline = 320,
+	 .sizeimage = 320 * 240 * 3 / 8 + 590,
+	 .colorspace = V4L2_COLORSPACE_JPEG,
+	 .priv = 1},
+	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+	 .bytesperline = 640,
+	 .sizeimage = 640 * 480 * 3 / 8 + 590,
 	 .colorspace = V4L2_COLORSPACE_JPEG,
 	 .priv = 0},
 };
@@ -244,7 +257,7 @@
 };
 
 static const u8 sensor_init_ov965x[][2] = {
-	{0x12, 0x80},	/* com7 - reset */
+	{0x12, 0x80},	/* com7 - SSCB reset */
 	{0x00, 0x00},	/* gain */
 	{0x01, 0x80},	/* blue */
 	{0x02, 0x80},	/* red */
@@ -254,10 +267,10 @@
 	{0x0e, 0x61},	/* com5 */
 	{0x0f, 0x42},	/* com6 */
 	{0x11, 0x00},	/* clkrc */
-	{0x12, 0x02},	/* com7 */
+	{0x12, 0x02},	/* com7 - 15fps VGA YUYV */
 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
 	{0x14, 0x28},	/* com9 */
-	{0x16, 0x24},	/* rsvd16 */
+	{0x16, 0x24},	/* reg16 */
 	{0x17, 0x1d},	/* hstart*/
 	{0x18, 0xbd},	/* hstop */
 	{0x19, 0x01},	/* vstrt */
@@ -269,24 +282,24 @@
 	{0x27, 0x08},	/* bbias */
 	{0x28, 0x08},	/* gbbias */
 	{0x29, 0x15},	/* gr com */
-	{0x2a, 0x00},
-	{0x2b, 0x00},
+	{0x2a, 0x00},	/* exhch */
+	{0x2b, 0x00},	/* exhcl */
 	{0x2c, 0x08},	/* rbias */
 	{0x32, 0xff},	/* href */
 	{0x33, 0x00},	/* chlf */
-	{0x34, 0x3f},	/* arblm */
-	{0x35, 0x00},	/* rsvd35 */
-	{0x36, 0xf8},	/* rsvd36 */
-	{0x38, 0x72},	/* acom38 */
-	{0x39, 0x57},	/* ofon */
-	{0x3a, 0x80},	/* tslb */
-	{0x3b, 0xc4},
+	{0x34, 0x3f},	/* aref1 */
+	{0x35, 0x00},	/* aref2 */
+	{0x36, 0xf8},	/* aref3 */
+	{0x38, 0x72},	/* adc2 */
+	{0x39, 0x57},	/* aref4 */
+	{0x3a, 0x80},	/* tslb - yuyv */
+	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
 	{0x3d, 0x99},	/* com13 */
-	{0x3f, 0xc1},
+	{0x3f, 0xc1},	/* edge */
 	{0x40, 0xc0},	/* com15 */
 	{0x41, 0x40},	/* com16 */
-	{0x42, 0xc0},
-	{0x43, 0x0a},
+	{0x42, 0xc0},	/* com17 */
+	{0x43, 0x0a},	/* rsvd */
 	{0x44, 0xf0},
 	{0x45, 0x46},
 	{0x46, 0x62},
@@ -297,22 +310,22 @@
 	{0x4c, 0x7f},
 	{0x4d, 0x7f},
 	{0x4e, 0x7f},
-	{0x4f, 0x98},
+	{0x4f, 0x98},	/* matrix */
 	{0x50, 0x98},
 	{0x51, 0x00},
 	{0x52, 0x28},
 	{0x53, 0x70},
 	{0x54, 0x98},
-	{0x58, 0x1a},
-	{0x59, 0x85},
+	{0x58, 0x1a},	/* matrix coef sign */
+	{0x59, 0x85},	/* AWB control */
 	{0x5a, 0xa9},
 	{0x5b, 0x64},
 	{0x5c, 0x84},
 	{0x5d, 0x53},
 	{0x5e, 0x0e},
-	{0x5f, 0xf0},
-	{0x60, 0xf0},
-	{0x61, 0xf0},
+	{0x5f, 0xf0},	/* AWB blue limit */
+	{0x60, 0xf0},	/* AWB red limit */
+	{0x61, 0xf0},	/* AWB green limit */
 	{0x62, 0x00},	/* lcc1 */
 	{0x63, 0x00},	/* lcc2 */
 	{0x64, 0x02},	/* lcc3 */
@@ -324,15 +337,15 @@
 	{0x6d, 0x55},
 	{0x6e, 0x00},
 	{0x6f, 0x9d},
-	{0x70, 0x21},
+	{0x70, 0x21},	/* dnsth */
 	{0x71, 0x78},
-	{0x72, 0x00},
-	{0x73, 0x01},
-	{0x74, 0x3a},
-	{0x75, 0x35},
+	{0x72, 0x00},	/* poidx */
+	{0x73, 0x01},	/* pckdv */
+	{0x74, 0x3a},	/* xindx */
+	{0x75, 0x35},	/* yindx */
 	{0x76, 0x01},
 	{0x77, 0x02},
-	{0x7a, 0x12},
+	{0x7a, 0x12},	/* gamma curve */
 	{0x7b, 0x08},
 	{0x7c, 0x16},
 	{0x7d, 0x30},
@@ -349,33 +362,33 @@
 	{0x88, 0xe6},
 	{0x89, 0xf2},
 	{0x8a, 0x03},
-	{0x8c, 0x89},
+	{0x8c, 0x89},	/* com19 */
 	{0x14, 0x28},	/* com9 */
 	{0x90, 0x7d},
 	{0x91, 0x7b},
-	{0x9d, 0x03},
-	{0x9e, 0x04},
+	{0x9d, 0x03},	/* lcc6 */
+	{0x9e, 0x04},	/* lcc7 */
 	{0x9f, 0x7a},
 	{0xa0, 0x79},
 	{0xa1, 0x40},	/* aechm */
-	{0xa4, 0x50},
+	{0xa4, 0x50},	/* com21 */
 	{0xa5, 0x68},	/* com26 */
-	{0xa6, 0x4a},
-	{0xa8, 0xc1},	/* acoma8 */
-	{0xa9, 0xef},	/* acoma9 */
+	{0xa6, 0x4a},	/* AWB green */
+	{0xa8, 0xc1},	/* refa8 */
+	{0xa9, 0xef},	/* refa9 */
 	{0xaa, 0x92},
 	{0xab, 0x04},
-	{0xac, 0x80},
+	{0xac, 0x80},	/* black level control */
 	{0xad, 0x80},
 	{0xae, 0x80},
 	{0xaf, 0x80},
 	{0xb2, 0xf2},
 	{0xb3, 0x20},
-	{0xb4, 0x20},
+	{0xb4, 0x20},	/* ctrlb4 */
 	{0xb5, 0x00},
 	{0xb6, 0xaf},
 	{0xbb, 0xae},
-	{0xbc, 0x7f},
+	{0xbc, 0x7f},	/* ADC channel offsets */
 	{0xdb, 0x7f},
 	{0xbe, 0x7f},
 	{0xbf, 0x7f},
@@ -384,7 +397,7 @@
 	{0xc2, 0x01},
 	{0xc3, 0x4e},
 	{0xc6, 0x85},
-	{0xc7, 0x80},
+	{0xc7, 0x80},	/* com24 */
 	{0xc9, 0xe0},
 	{0xca, 0xe8},
 	{0xcb, 0xf0},
@@ -399,11 +412,11 @@
 	{0x58, 0x1a},
 	{0xff, 0x41},	/* read 41, write ff 00 */
 	{0x41, 0x40},	/* com16 */
-	{0xc5, 0x03},
-	{0x6a, 0x02},
+	{0xc5, 0x03},	/* 60 Hz banding filter */
+	{0x6a, 0x02},	/* 50 Hz banding filter */
 
-	{0x12, 0x62},	/* com7 - VGA + CIF */
-	{0x36, 0xfa},	/* rsvd36 */
+	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
+	{0x36, 0xfa},	/* aref3 */
 	{0x69, 0x0a},	/* hv */
 	{0x8c, 0x89},	/* com22 */
 	{0x14, 0x28},	/* com9 */
@@ -442,8 +455,8 @@
 	{0x52, 0x3c},
 	{0x53, 0x00},
 	{0x54, 0x00},
-	{0x55, 0x00},
-	{0x57, 0x00},
+	{0x55, 0x00},	/* brightness */
+	{0x57, 0x00},	/* contrast 2 */
 	{0x5c, 0x00},
 	{0x5a, 0xa0},
 	{0x5b, 0x78},
@@ -489,9 +502,66 @@
 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
 };
 
+static const u8 sensor_start_ov965x[][2] = {
+	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
+	{0x36, 0xfa},	/* aref3 */
+	{0x69, 0x0a},	/* hv */
+	{0x8c, 0x89},	/* com22 */
+	{0x14, 0x28},	/* com9 */
+	{0x3e, 0x0c},	/* com14 */
+	{0x41, 0x40},	/* com16 */
+	{0x72, 0x00},
+	{0x73, 0x00},
+	{0x74, 0x3a},
+	{0x75, 0x35},
+	{0x76, 0x01},
+	{0xc7, 0x80},	/* com24 */
+	{0x03, 0x12},	/* vref */
+	{0x17, 0x16},	/* hstart */
+	{0x18, 0x02},	/* hstop */
+	{0x19, 0x01},	/* vstrt */
+	{0x1a, 0x3d},	/* vstop */
+	{0x32, 0xff},	/* href */
+	{0xc0, 0xaa},
+	{}
+};
+
 static const u8 bridge_start_ov965x[][2] = {
+	{0x94, 0xaa},
+	{0xf1, 0x60},
+	{0xe5, 0x04},
+	{0xc0, 0x50},
+	{0xc1, 0x3c},
+	{0x8c, 0x00},
+	{0x8d, 0x1c},
+	{0x34, 0x05},
+	{}
+};
+
+static const u8 bridge_start_ov965x_vga[][2] = {
+	{0xc2, 0x0c},
+	{0xc3, 0xf9},
+	{0xda, 0x01},
+	{0x50, 0x00},
+	{0x51, 0xa0},
+	{0x52, 0x3c},
+	{0x53, 0x00},
+	{0x54, 0x00},
+	{0x55, 0x00},
+	{0x57, 0x00},
+	{0x5c, 0x00},
+	{0x5a, 0xa0},
+	{0x5b, 0x78},
+	{0x35, 0x02},
+	{0xd9, 0x10},
+	{0x94, 0x11},
+	{}
+};
+
+static const u8 bridge_start_ov965x_cif[][2] = {
 	{0xc2, 0x4c},
 	{0xc3, 0xf9},
+	{0xda, 0x00},
 	{0x50, 0x00},
 	{0x51, 0xa0},
 	{0x52, 0x78},
@@ -500,30 +570,54 @@
 	{0x55, 0x00},
 	{0x57, 0x00},
 	{0x5c, 0x00},
-	{0x5a, 0x28},
-	{0x5b, 0x1e},
-	{0x35, 0x00},
-	{0xd9, 0x21},
+	{0x5a, 0x50},
+	{0x5b, 0x3c},
+	{0x35, 0x02},
+	{0xd9, 0x10},
 	{0x94, 0x11},
+	{}
 };
 
-static const u8 sensor_start_ov965x[][2] = {
-	{0x3b, 0xe4},
+static const u8 sensor_start_ov965x_vga[][2] = {
+	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
+	{0x1e, 0x04},	/* mvfp */
+	{0x13, 0xe0},	/* com8 */
+	{0x00, 0x00},
+	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
+	{0x11, 0x03},	/* clkrc */
+	{0x6b, 0x5a},	/* dblv */
+	{0x6a, 0x05},	/* 50 Hz banding filter */
+	{0xc5, 0x07},	/* 60 Hz banding filter */
+	{0xa2, 0x4b},	/* bd50 */
+	{0xa3, 0x3e},	/* bd60 */
+
+	{0x2d, 0x00},	/* advfl */
+	{}
+};
+
+static const u8 sensor_start_ov965x_cif[][2] = {
+	{0x3b, 0xe4},	/* com11 - night mode 1/4 frame rate */
 	{0x1e, 0x04},	/* mvfp */
 	{0x13, 0xe0},	/* com8 */
 	{0x00, 0x00},
 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
 	{0x11, 0x01},	/* clkrc */
 	{0x6b, 0x5a},	/* dblv */
-	{0x6a, 0x02},
-	{0xc5, 0x03},
-	{0xa2, 0x96},
-	{0xa3, 0x7d},
+	{0x6a, 0x02},	/* 50 Hz banding filter */
+	{0xc5, 0x03},	/* 60 Hz banding filter */
+	{0xa2, 0x96},	/* bd50 */
+	{0xa3, 0x7d},	/* bd60 */
+
 	{0xff, 0x13},	/* read 13, write ff 00 */
 	{0x13, 0xe7},
-	{0x3a, 0x80},
+	{0x3a, 0x80},	/* tslb - yuyv */
+	{}
+};
+
+static const u8 sensor_start_ov965x_2[][2] = {
 	{0xff, 0x42},	/* read 42, write ff 00 */
-	{0x42, 0xc1},
+	{0x42, 0xc1},	/* com17 - 50 Hz filter */
+	{}
 };
 
 
@@ -705,11 +799,17 @@
 
 	cam = &gspca_dev->cam;
 
-	cam->cam_mode = vga_mode;
-	cam->nmodes = ARRAY_SIZE(vga_mode);
+	if (sd->sensor == SENSOR_OV772X) {
+		cam->cam_mode = vga_yuyv_mode;
+		cam->nmodes = ARRAY_SIZE(vga_yuyv_mode);
 
-	cam->bulk_size = 16384;
-	cam->bulk_nurbs = 2;
+		cam->bulk = 1;
+		cam->bulk_size = 16384;
+		cam->bulk_nurbs = 2;
+	} else {		/* ov965x */
+		cam->cam_mode = vga_jpeg_mode;
+		cam->nmodes = ARRAY_SIZE(vga_jpeg_mode);
+	}
 
 	return 0;
 }
@@ -778,6 +878,7 @@
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	int mode;
 
 	switch (sd->sensor) {
 	case SENSOR_OV772X:
@@ -786,13 +887,28 @@
 		break;
 	default:
 /*	case SENSOR_OV965X: */
-		reg_w_array(gspca_dev, bridge_start_ov965x,
-				ARRAY_SIZE(bridge_start_ov965x));
+
 		sccb_w_array(gspca_dev, sensor_start_ov965x,
 				ARRAY_SIZE(sensor_start_ov965x));
+		reg_w_array(gspca_dev, bridge_start_ov965x,
+				ARRAY_SIZE(bridge_start_ov965x));
+		mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+		if (mode != 0) {	/* 320x240 */
+			reg_w_array(gspca_dev, bridge_start_ov965x_cif,
+					ARRAY_SIZE(bridge_start_ov965x_cif));
+			sccb_w_array(gspca_dev, sensor_start_ov965x_cif,
+					ARRAY_SIZE(sensor_start_ov965x_cif));
+		} else {		/* 640x480 */
+			reg_w_array(gspca_dev, bridge_start_ov965x_vga,
+					ARRAY_SIZE(bridge_start_ov965x_vga));
+			sccb_w_array(gspca_dev, sensor_start_ov965x_vga,
+					ARRAY_SIZE(sensor_start_ov965x_vga));
+		}
+		sccb_w_array(gspca_dev, sensor_start_ov965x_2,
+				ARRAY_SIZE(sensor_start_ov965x_2));
+		ov534_reg_write(gspca_dev, 0xe0, 0x00);
 		ov534_reg_write(gspca_dev, 0xe0, 0x00);
 		ov534_set_led(gspca_dev, 1);
-/*fixme: other sensor start omitted*/
 	}
 	return 0;
 }
@@ -832,9 +948,11 @@
 	__u32 this_pts;
 	u16 this_fid;
 	int remaining_len = len;
+	int payload_len;
 
+	payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
 	do {
-		len = min(remaining_len, 2040);		/*fixme: was 2048*/
+		len = min(remaining_len, payload_len);
 
 		/* Payloads are prefixed with a UVC-style header.  We
 		   consider a frame to start when the FID toggles, or the PTS
@@ -864,30 +982,27 @@
 
 		/* If PTS or FID has changed, start a new frame. */
 		if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
-			gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
-					NULL, 0);
+			if (gspca_dev->last_packet_type == INTER_PACKET)
+				frame = gspca_frame_add(gspca_dev,
+							LAST_PACKET, frame,
+							NULL, 0);
 			sd->last_pts = this_pts;
 			sd->last_fid = this_fid;
-		}
-
-		/* Add the data from this payload */
-		gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+			gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
 					data + 12, len - 12);
-
 		/* If this packet is marked as EOF, end the frame */
-		if (data[1] & UVC_STREAM_EOF) {
+		} else if (data[1] & UVC_STREAM_EOF) {
 			sd->last_pts = 0;
-
-			if (frame->data_end - frame->data !=
-			    gspca_dev->width * gspca_dev->height * 2) {
-				PDEBUG(D_PACK, "short frame");
-				goto discard;
-			}
-
 			frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
-						NULL, 0);
+						data + 12, len - 12);
+		} else {
+
+			/* Add the data from this payload */
+			gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+						data + 12, len - 12);
 		}
 
+
 		/* Done this payload */
 		goto scan_next;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/sn9c20x.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/sn9c20x.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/sn9c20x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/sn9c20x.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2434 @@
+/*
+ *	Sonix sn9c201 sn9c202 library
+ *	Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
+ *	Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
+ *
+ * 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
+ * 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
+ */
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/usb/input.h>
+#include <linux/input.h>
+#endif
+
+#include "gspca.h"
+#include "jpeg.h"
+
+#include <media/v4l2-chip-ident.h>
+
+MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
+		"microdia project <microdia@googlegroups.com>");
+MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define MODULE_NAME "sn9c20x"
+
+#define MODE_RAW	0x10
+#define MODE_JPEG	0x20
+#define MODE_SXGA	0x80
+
+#define SENSOR_OV9650	0
+#define SENSOR_OV9655	1
+#define SENSOR_SOI968	2
+#define SENSOR_OV7660	3
+#define SENSOR_OV7670	4
+#define SENSOR_MT9V011	5
+#define SENSOR_MT9V111	6
+#define SENSOR_MT9V112	7
+#define SENSOR_MT9M001	8
+#define SENSOR_MT9M111	9
+#define SENSOR_HV7131R	10
+#define SENSOR_MT9VPRB	20
+
+/* specific webcam descriptor */
+struct sd {
+	struct gspca_dev gspca_dev;
+
+#define MIN_AVG_LUM 80
+#define MAX_AVG_LUM 130
+	atomic_t avg_lum;
+	u8 old_step;
+	u8 older_step;
+	u8 exposure_step;
+
+	u8 brightness;
+	u8 contrast;
+	u8 saturation;
+	s16 hue;
+	u8 gamma;
+	u8 red;
+	u8 blue;
+
+	u8 hflip;
+	u8 vflip;
+	u8 gain;
+	u16 exposure;
+	u8 auto_exposure;
+
+	u8 i2c_addr;
+	u8 sensor;
+	u8 hstart;
+	u8 vstart;
+
+	u8 *jpeg_hdr;
+	u8 quality;
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+	struct input_dev *input_dev;
+	u8 input_gpio;
+	struct task_struct *input_task;
+#endif
+};
+
+static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
+static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
+static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
+
+static struct ctrl sd_ctrls[] = {
+	{
+#define BRIGHTNESS_IDX 0
+	    {
+		.id      = V4L2_CID_BRIGHTNESS,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Brightness",
+		.minimum = 0,
+		.maximum = 0xff,
+		.step    = 1,
+#define BRIGHTNESS_DEFAULT 0x7f
+		.default_value = BRIGHTNESS_DEFAULT,
+	    },
+	    .set = sd_setbrightness,
+	    .get = sd_getbrightness,
+	},
+	{
+#define CONTRAST_IDX 1
+	    {
+		.id      = V4L2_CID_CONTRAST,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Contrast",
+		.minimum = 0,
+		.maximum = 0xff,
+		.step    = 1,
+#define CONTRAST_DEFAULT 0x7f
+		.default_value = CONTRAST_DEFAULT,
+	    },
+	    .set = sd_setcontrast,
+	    .get = sd_getcontrast,
+	},
+	{
+#define SATURATION_IDX 2
+	    {
+		.id      = V4L2_CID_SATURATION,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Saturation",
+		.minimum = 0,
+		.maximum = 0xff,
+		.step    = 1,
+#define SATURATION_DEFAULT 0x7f
+		.default_value = SATURATION_DEFAULT,
+	    },
+	    .set = sd_setsaturation,
+	    .get = sd_getsaturation,
+	},
+	{
+#define HUE_IDX 3
+	    {
+		.id      = V4L2_CID_HUE,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Hue",
+		.minimum = -180,
+		.maximum = 180,
+		.step    = 1,
+#define HUE_DEFAULT 0
+		.default_value = HUE_DEFAULT,
+	    },
+	    .set = sd_sethue,
+	    .get = sd_gethue,
+	},
+	{
+#define GAMMA_IDX 4
+	    {
+		.id      = V4L2_CID_GAMMA,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gamma",
+		.minimum = 0,
+		.maximum = 0xff,
+		.step    = 1,
+#define GAMMA_DEFAULT 0x10
+		.default_value = GAMMA_DEFAULT,
+	    },
+	    .set = sd_setgamma,
+	    .get = sd_getgamma,
+	},
+	{
+#define BLUE_IDX 5
+	    {
+		.id	 = V4L2_CID_BLUE_BALANCE,
+		.type	 = V4L2_CTRL_TYPE_INTEGER,
+		.name	 = "Blue Balance",
+		.minimum = 0,
+		.maximum = 0x7f,
+		.step	 = 1,
+#define BLUE_DEFAULT 0x28
+		.default_value = BLUE_DEFAULT,
+	    },
+	    .set = sd_setbluebalance,
+	    .get = sd_getbluebalance,
+	},
+	{
+#define RED_IDX 6
+	    {
+		.id	 = V4L2_CID_RED_BALANCE,
+		.type	 = V4L2_CTRL_TYPE_INTEGER,
+		.name	 = "Red Balance",
+		.minimum = 0,
+		.maximum = 0x7f,
+		.step	 = 1,
+#define RED_DEFAULT 0x28
+		.default_value = RED_DEFAULT,
+	    },
+	    .set = sd_setredbalance,
+	    .get = sd_getredbalance,
+	},
+	{
+#define HFLIP_IDX 7
+	    {
+		.id      = V4L2_CID_HFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Horizontal Flip",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+#define HFLIP_DEFAULT 0
+		.default_value = HFLIP_DEFAULT,
+	    },
+	    .set = sd_sethflip,
+	    .get = sd_gethflip,
+	},
+	{
+#define VFLIP_IDX 8
+	    {
+		.id      = V4L2_CID_VFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Vertical Flip",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+#define VFLIP_DEFAULT 0
+		.default_value = VFLIP_DEFAULT,
+	    },
+	    .set = sd_setvflip,
+	    .get = sd_getvflip,
+	},
+	{
+#define EXPOSURE_IDX 9
+	    {
+		.id      = V4L2_CID_EXPOSURE,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Exposure",
+		.minimum = 0,
+		.maximum = 0x1780,
+		.step    = 1,
+#define EXPOSURE_DEFAULT 0x33
+		.default_value = EXPOSURE_DEFAULT,
+	    },
+	    .set = sd_setexposure,
+	    .get = sd_getexposure,
+	},
+	{
+#define GAIN_IDX 10
+	    {
+		.id      = V4L2_CID_GAIN,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gain",
+		.minimum = 0,
+		.maximum = 28,
+		.step    = 1,
+#define GAIN_DEFAULT 0x00
+		.default_value = GAIN_DEFAULT,
+	    },
+	    .set = sd_setgain,
+	    .get = sd_getgain,
+	},
+	{
+#define AUTOGAIN_IDX 11
+	    {
+		.id      = V4L2_CID_AUTOGAIN,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Auto Exposure",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+#define AUTO_EXPOSURE_DEFAULT 1
+		.default_value = AUTO_EXPOSURE_DEFAULT,
+	    },
+	    .set = sd_setautoexposure,
+	    .get = sd_getautoexposure,
+	},
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 240,
+		.sizeimage = 240 * 120,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 0 | MODE_JPEG},
+	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 160 * 120,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0 | MODE_RAW},
+	{160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+		.bytesperline = 240,
+		.sizeimage = 240 * 120,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0},
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 480,
+		.sizeimage = 480 * 240 ,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 1 | MODE_JPEG},
+	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 ,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1 | MODE_RAW},
+	{320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+		.bytesperline = 480,
+		.sizeimage = 480 * 240 ,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1},
+	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 960,
+		.sizeimage = 960 * 480,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 2 | MODE_JPEG},
+	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 2 | MODE_RAW},
+	{640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+		.bytesperline = 960,
+		.sizeimage = 960 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 2},
+};
+
+static const struct v4l2_pix_format sxga_mode[] = {
+	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 240,
+		.sizeimage = 240 * 120,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 0 | MODE_JPEG},
+	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 160 * 120,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0 | MODE_RAW},
+	{160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+		.bytesperline = 240,
+		.sizeimage = 240 * 120,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0},
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 480,
+		.sizeimage = 480 * 240 ,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 1 | MODE_JPEG},
+	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 ,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1 | MODE_RAW},
+	{320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+		.bytesperline = 480,
+		.sizeimage = 480 * 240 ,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1},
+	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 960,
+		.sizeimage = 960 * 480,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 2 | MODE_JPEG},
+	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 2 | MODE_RAW},
+	{640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+		.bytesperline = 960,
+		.sizeimage = 960 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 2},
+	{1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 1280,
+		.sizeimage = (1280 * 1024) + 64,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 3 | MODE_RAW | MODE_SXGA},
+};
+
+static const int hsv_red_x[] = {
+	41,  44,  46,  48,  50,  52,  54,  56,
+	58,  60,  62,  64,  66,  68,  70,  72,
+	74,  76,  78,  80,  81,  83,  85,  87,
+	88,  90,  92,  93,  95,  97,  98, 100,
+	101, 102, 104, 105, 107, 108, 109, 110,
+	112, 113, 114, 115, 116, 117, 118, 119,
+	120, 121, 122, 123, 123, 124, 125, 125,
+	126, 127, 127, 128, 128, 129, 129, 129,
+	130, 130, 130, 130, 131, 131, 131, 131,
+	131, 131, 131, 131, 130, 130, 130, 130,
+	129, 129, 129, 128, 128, 127, 127, 126,
+	125, 125, 124, 123, 122, 122, 121, 120,
+	119, 118, 117, 116, 115, 114, 112, 111,
+	110, 109, 107, 106, 105, 103, 102, 101,
+	99,  98,  96,  94,  93,  91,  90,  88,
+	86,  84,  83,  81,  79,  77,  75,  74,
+	72,  70,  68,  66,  64,  62,  60,  58,
+	56,  54,  52,  49,  47,  45,  43,  41,
+	39,  36,  34,  32,  30,  28,  25,  23,
+	21,  19,  16,  14,  12,   9,   7,   5,
+	3,   0,  -1,  -3,  -6,  -8, -10, -12,
+	-15, -17, -19, -22, -24, -26, -28, -30,
+	-33, -35, -37, -39, -41, -44, -46, -48,
+	-50, -52, -54, -56, -58, -60, -62, -64,
+	-66, -68, -70, -72, -74, -76, -78, -80,
+	-81, -83, -85, -87, -88, -90, -92, -93,
+	-95, -97, -98, -100, -101, -102, -104, -105,
+	-107, -108, -109, -110, -112, -113, -114, -115,
+	-116, -117, -118, -119, -120, -121, -122, -123,
+	-123, -124, -125, -125, -126, -127, -127, -128,
+	-128, -128, -128, -128, -128, -128, -128, -128,
+	-128, -128, -128, -128, -128, -128, -128, -128,
+	-128, -128, -128, -128, -128, -128, -128, -128,
+	-128, -127, -127, -126, -125, -125, -124, -123,
+	-122, -122, -121, -120, -119, -118, -117, -116,
+	-115, -114, -112, -111, -110, -109, -107, -106,
+	-105, -103, -102, -101, -99, -98, -96, -94,
+	-93, -91, -90, -88, -86, -84, -83, -81,
+	-79, -77, -75, -74, -72, -70, -68, -66,
+	-64, -62, -60, -58, -56, -54, -52, -49,
+	-47, -45, -43, -41, -39, -36, -34, -32,
+	-30, -28, -25, -23, -21, -19, -16, -14,
+	-12,  -9,  -7,  -5,  -3,   0,   1,   3,
+	6,   8,  10,  12,  15,  17,  19,  22,
+	24,  26,  28,  30,  33,  35,  37,  39, 41
+};
+
+static const int hsv_red_y[] = {
+	82,  80,  78,  76,  74,  73,  71,  69,
+	67,  65,  63,  61,  58,  56,  54,  52,
+	50,  48,  46,  44,  41,  39,  37,  35,
+	32,  30,  28,  26,  23,  21,  19,  16,
+	14,  12,  10,   7,   5,   3,   0,  -1,
+	-3,  -6,  -8, -10, -13, -15, -17, -19,
+	-22, -24, -26, -29, -31, -33, -35, -38,
+	-40, -42, -44, -46, -48, -51, -53, -55,
+	-57, -59, -61, -63, -65, -67, -69, -71,
+	-73, -75, -77, -79, -81, -82, -84, -86,
+	-88, -89, -91, -93, -94, -96, -98, -99,
+	-101, -102, -104, -105, -106, -108, -109, -110,
+	-112, -113, -114, -115, -116, -117, -119, -120,
+	-120, -121, -122, -123, -124, -125, -126, -126,
+	-127, -128, -128, -128, -128, -128, -128, -128,
+	-128, -128, -128, -128, -128, -128, -128, -128,
+	-128, -128, -128, -128, -128, -128, -128, -128,
+	-128, -128, -128, -128, -128, -128, -128, -128,
+	-127, -127, -126, -125, -125, -124, -123, -122,
+	-121, -120, -119, -118, -117, -116, -115, -114,
+	-113, -111, -110, -109, -107, -106, -105, -103,
+	-102, -100, -99, -97, -96, -94, -92, -91,
+	-89, -87, -85, -84, -82, -80, -78, -76,
+	-74, -73, -71, -69, -67, -65, -63, -61,
+	-58, -56, -54, -52, -50, -48, -46, -44,
+	-41, -39, -37, -35, -32, -30, -28, -26,
+	-23, -21, -19, -16, -14, -12, -10,  -7,
+	-5,  -3,   0,   1,   3,   6,   8,  10,
+	13,  15,  17,  19,  22,  24,  26,  29,
+	31,  33,  35,  38,  40,  42,  44,  46,
+	48,  51,  53,  55,  57,  59,  61,  63,
+	65,  67,  69,  71,  73,  75,  77,  79,
+	81,  82,  84,  86,  88,  89,  91,  93,
+	94,  96,  98,  99, 101, 102, 104, 105,
+	106, 108, 109, 110, 112, 113, 114, 115,
+	116, 117, 119, 120, 120, 121, 122, 123,
+	124, 125, 126, 126, 127, 128, 128, 129,
+	129, 130, 130, 131, 131, 131, 131, 132,
+	132, 132, 132, 132, 132, 132, 132, 132,
+	132, 132, 132, 131, 131, 131, 130, 130,
+	130, 129, 129, 128, 127, 127, 126, 125,
+	125, 124, 123, 122, 121, 120, 119, 118,
+	117, 116, 115, 114, 113, 111, 110, 109,
+	107, 106, 105, 103, 102, 100,  99,  97,
+	96, 94, 92, 91, 89, 87, 85, 84, 82
+};
+
+static const int hsv_green_x[] = {
+	-124, -124, -125, -125, -125, -125, -125, -125,
+	-125, -126, -126, -125, -125, -125, -125, -125,
+	-125, -124, -124, -124, -123, -123, -122, -122,
+	-121, -121, -120, -120, -119, -118, -117, -117,
+	-116, -115, -114, -113, -112, -111, -110, -109,
+	-108, -107, -105, -104, -103, -102, -100, -99,
+	-98, -96, -95, -93, -92, -91, -89, -87,
+	-86, -84, -83, -81, -79, -77, -76, -74,
+	-72, -70, -69, -67, -65, -63, -61, -59,
+	-57, -55, -53, -51, -49, -47, -45, -43,
+	-41, -39, -37, -35, -33, -30, -28, -26,
+	-24, -22, -20, -18, -15, -13, -11,  -9,
+	-7,  -4,  -2,   0,   1,   3,   6,   8,
+	10,  12,  14,  17,  19,  21,  23,  25,
+	27,  29,  32,  34,  36,  38,  40,  42,
+	44,  46,  48,  50,  52,  54,  56,  58,
+	60,  62,  64,  66,  68,  70,  71,  73,
+	75,  77,  78,  80,  82,  83,  85,  87,
+	88,  90,  91,  93,  94,  96,  97,  98,
+	100, 101, 102, 104, 105, 106, 107, 108,
+	109, 111, 112, 113, 113, 114, 115, 116,
+	117, 118, 118, 119, 120, 120, 121, 122,
+	122, 123, 123, 124, 124, 124, 125, 125,
+	125, 125, 125, 125, 125, 126, 126, 125,
+	125, 125, 125, 125, 125, 124, 124, 124,
+	123, 123, 122, 122, 121, 121, 120, 120,
+	119, 118, 117, 117, 116, 115, 114, 113,
+	112, 111, 110, 109, 108, 107, 105, 104,
+	103, 102, 100,  99,  98,  96,  95,  93,
+	92,  91,  89,  87,  86,  84,  83,  81,
+	79,  77,  76,  74,  72,  70,  69,  67,
+	65,  63,  61,  59,  57,  55,  53,  51,
+	49,  47,  45,  43,  41,  39,  37,  35,
+	33,  30,  28,  26,  24,  22,  20,  18,
+	15,  13,  11,   9,   7,   4,   2,   0,
+	-1,  -3,  -6,  -8, -10, -12, -14, -17,
+	-19, -21, -23, -25, -27, -29, -32, -34,
+	-36, -38, -40, -42, -44, -46, -48, -50,
+	-52, -54, -56, -58, -60, -62, -64, -66,
+	-68, -70, -71, -73, -75, -77, -78, -80,
+	-82, -83, -85, -87, -88, -90, -91, -93,
+	-94, -96, -97, -98, -100, -101, -102, -104,
+	-105, -106, -107, -108, -109, -111, -112, -113,
+	-113, -114, -115, -116, -117, -118, -118, -119,
+	-120, -120, -121, -122, -122, -123, -123, -124, -124
+};
+
+static const int hsv_green_y[] = {
+	-100, -99, -98, -97, -95, -94, -93, -91,
+	-90, -89, -87, -86, -84, -83, -81, -80,
+	-78, -76, -75, -73, -71, -70, -68, -66,
+	-64, -63, -61, -59, -57, -55, -53, -51,
+	-49, -48, -46, -44, -42, -40, -38, -36,
+	-34, -32, -30, -27, -25, -23, -21, -19,
+	-17, -15, -13, -11,  -9,  -7,  -4,  -2,
+	0,   1,   3,   5,   7,   9,  11,  14,
+	16,  18,  20,  22,  24,  26,  28,  30,
+	32,  34,  36,  38,  40,  42,  44,  46,
+	48,  50,  52,  54,  56,  58,  59,  61,
+	63,  65,  67,  68,  70,  72,  74,  75,
+	77,  78,  80,  82,  83,  85,  86,  88,
+	89,  90,  92,  93,  95,  96,  97,  98,
+	100, 101, 102, 103, 104, 105, 106, 107,
+	108, 109, 110, 111, 112, 112, 113, 114,
+	115, 115, 116, 116, 117, 117, 118, 118,
+	119, 119, 119, 120, 120, 120, 120, 120,
+	121, 121, 121, 121, 121, 121, 120, 120,
+	120, 120, 120, 119, 119, 119, 118, 118,
+	117, 117, 116, 116, 115, 114, 114, 113,
+	112, 111, 111, 110, 109, 108, 107, 106,
+	105, 104, 103, 102, 100,  99,  98,  97,
+	95,  94,  93,  91,  90,  89,  87,  86,
+	84,  83,  81,  80,  78,  76,  75,  73,
+	71,  70,  68,  66,  64,  63,  61,  59,
+	57,  55,  53,  51,  49,  48,  46,  44,
+	42,  40,  38,  36,  34,  32,  30,  27,
+	25,  23,  21,  19,  17,  15,  13,  11,
+	9,   7,   4,   2,   0,  -1,  -3,  -5,
+	-7,  -9, -11, -14, -16, -18, -20, -22,
+	-24, -26, -28, -30, -32, -34, -36, -38,
+	-40, -42, -44, -46, -48, -50, -52, -54,
+	-56, -58, -59, -61, -63, -65, -67, -68,
+	-70, -72, -74, -75, -77, -78, -80, -82,
+	-83, -85, -86, -88, -89, -90, -92, -93,
+	-95, -96, -97, -98, -100, -101, -102, -103,
+	-104, -105, -106, -107, -108, -109, -110, -111,
+	-112, -112, -113, -114, -115, -115, -116, -116,
+	-117, -117, -118, -118, -119, -119, -119, -120,
+	-120, -120, -120, -120, -121, -121, -121, -121,
+	-121, -121, -120, -120, -120, -120, -120, -119,
+	-119, -119, -118, -118, -117, -117, -116, -116,
+	-115, -114, -114, -113, -112, -111, -111, -110,
+	-109, -108, -107, -106, -105, -104, -103, -102, -100
+};
+
+static const int hsv_blue_x[] = {
+	112, 113, 114, 114, 115, 116, 117, 117,
+	118, 118, 119, 119, 120, 120, 120, 121,
+	121, 121, 122, 122, 122, 122, 122, 122,
+	122, 122, 122, 122, 122, 122, 121, 121,
+	121, 120, 120, 120, 119, 119, 118, 118,
+	117, 116, 116, 115, 114, 113, 113, 112,
+	111, 110, 109, 108, 107, 106, 105, 104,
+	103, 102, 100,  99,  98,  97,  95,  94,
+	93,  91,  90,  88,  87,  85,  84,  82,
+	80,  79,  77,  76,  74,  72,  70,  69,
+	67,  65,  63,  61,  60,  58,  56,  54,
+	52,  50,  48,  46,  44,  42,  40,  38,
+	36,  34,  32,  30,  28,  26,  24,  22,
+	19,  17,  15,  13,  11,   9,   7,   5,
+	2,   0,  -1,  -3,  -5,  -7,  -9, -12,
+	-14, -16, -18, -20, -22, -24, -26, -28,
+	-31, -33, -35, -37, -39, -41, -43, -45,
+	-47, -49, -51, -53, -54, -56, -58, -60,
+	-62, -64, -66, -67, -69, -71, -73, -74,
+	-76, -78, -79, -81, -83, -84, -86, -87,
+	-89, -90, -92, -93, -94, -96, -97, -98,
+	-99, -101, -102, -103, -104, -105, -106, -107,
+	-108, -109, -110, -111, -112, -113, -114, -114,
+	-115, -116, -117, -117, -118, -118, -119, -119,
+	-120, -120, -120, -121, -121, -121, -122, -122,
+	-122, -122, -122, -122, -122, -122, -122, -122,
+	-122, -122, -121, -121, -121, -120, -120, -120,
+	-119, -119, -118, -118, -117, -116, -116, -115,
+	-114, -113, -113, -112, -111, -110, -109, -108,
+	-107, -106, -105, -104, -103, -102, -100, -99,
+	-98, -97, -95, -94, -93, -91, -90, -88,
+	-87, -85, -84, -82, -80, -79, -77, -76,
+	-74, -72, -70, -69, -67, -65, -63, -61,
+	-60, -58, -56, -54, -52, -50, -48, -46,
+	-44, -42, -40, -38, -36, -34, -32, -30,
+	-28, -26, -24, -22, -19, -17, -15, -13,
+	-11,  -9,  -7,  -5,  -2,   0,   1,   3,
+	5,   7,   9,  12,  14,  16,  18,  20,
+	22,  24,  26,  28,  31,  33,  35,  37,
+	39,  41,  43,  45,  47,  49,  51,  53,
+	54,  56,  58,  60,  62,  64,  66,  67,
+	69,  71,  73,  74,  76,  78,  79,  81,
+	83,  84,  86,  87,  89,  90,  92,  93,
+	94,  96,  97,  98,  99, 101, 102, 103,
+	104, 105, 106, 107, 108, 109, 110, 111, 112
+};
+
+static const int hsv_blue_y[] = {
+	-11, -13, -15, -17, -19, -21, -23, -25,
+	-27, -29, -31, -33, -35, -37, -39, -41,
+	-43, -45, -46, -48, -50, -52, -54, -55,
+	-57, -59, -61, -62, -64, -66, -67, -69,
+	-71, -72, -74, -75, -77, -78, -80, -81,
+	-83, -84, -86, -87, -88, -90, -91, -92,
+	-93, -95, -96, -97, -98, -99, -100, -101,
+	-102, -103, -104, -105, -106, -106, -107, -108,
+	-109, -109, -110, -111, -111, -112, -112, -113,
+	-113, -114, -114, -114, -115, -115, -115, -115,
+	-116, -116, -116, -116, -116, -116, -116, -116,
+	-116, -115, -115, -115, -115, -114, -114, -114,
+	-113, -113, -112, -112, -111, -111, -110, -110,
+	-109, -108, -108, -107, -106, -105, -104, -103,
+	-102, -101, -100, -99, -98, -97, -96, -95,
+	-94, -93, -91, -90, -89, -88, -86, -85,
+	-84, -82, -81, -79, -78, -76, -75, -73,
+	-71, -70, -68, -67, -65, -63, -62, -60,
+	-58, -56, -55, -53, -51, -49, -47, -45,
+	-44, -42, -40, -38, -36, -34, -32, -30,
+	-28, -26, -24, -22, -20, -18, -16, -14,
+	-12, -10,  -8,  -6,  -4,  -2,   0,   1,
+	3,   5,   7,   9,  11,  13,  15,  17,
+	19,  21,  23,  25,  27,  29,  31,  33,
+	35,  37,  39,  41,  43,  45,  46,  48,
+	50,  52,  54,  55,  57,  59,  61,  62,
+	64,  66,  67,  69,  71,  72,  74,  75,
+	77,  78,  80,  81,  83,  84,  86,  87,
+	88,  90,  91,  92,  93,  95,  96,  97,
+	98,  99, 100, 101, 102, 103, 104, 105,
+	106, 106, 107, 108, 109, 109, 110, 111,
+	111, 112, 112, 113, 113, 114, 114, 114,
+	115, 115, 115, 115, 116, 116, 116, 116,
+	116, 116, 116, 116, 116, 115, 115, 115,
+	115, 114, 114, 114, 113, 113, 112, 112,
+	111, 111, 110, 110, 109, 108, 108, 107,
+	106, 105, 104, 103, 102, 101, 100,  99,
+	98,  97,  96,  95,  94,  93,  91,  90,
+	89,  88,  86,  85,  84,  82,  81,  79,
+	78,  76,  75,  73,  71,  70,  68,  67,
+	65,  63,  62,  60,  58,  56,  55,  53,
+	51,  49,  47,  45,  44,  42,  40,  38,
+	36,  34,  32,  30,  28,  26,  24,  22,
+	20,  18,  16,  14,  12,  10,   8,   6,
+	4,   2,   0,  -1,  -3,  -5,  -7,  -9, -11
+};
+
+static u16 i2c_ident[] = {
+	V4L2_IDENT_OV9650,
+	V4L2_IDENT_OV9655,
+	V4L2_IDENT_SOI968,
+	V4L2_IDENT_OV7660,
+	V4L2_IDENT_OV7670,
+	V4L2_IDENT_MT9V011,
+	V4L2_IDENT_MT9V111,
+	V4L2_IDENT_MT9V112,
+	V4L2_IDENT_MT9M001C12ST,
+	V4L2_IDENT_MT9M111,
+	V4L2_IDENT_HV7131R,
+};
+
+static u16 bridge_init[][2] = {
+	{0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
+	{0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
+	{0x1068, 0x30}, {0x1069, 0x20},	{0x106a, 0x10},
+	{0x106b, 0x08},	{0x1188, 0x87},	{0x11a1, 0x00},
+	{0x11a2, 0x00},	{0x11a3, 0x6a},	{0x11a4, 0x50},
+	{0x11ab, 0x00},	{0x11ac, 0x00},	{0x11ad, 0x50},
+	{0x11ae, 0x3c},	{0x118a, 0x04},	{0x0395, 0x04},
+	{0x11b8, 0x3a},	{0x118b, 0x0e},	{0x10f7, 0x05},
+	{0x10f8, 0x14},	{0x10fa, 0xff},	{0x10f9, 0x00},
+	{0x11ba, 0x0a},	{0x11a5, 0x2d},	{0x11a6, 0x2d},
+	{0x11a7, 0x3a},	{0x11a8, 0x05},	{0x11a9, 0x04},
+	{0x11aa, 0x3f},	{0x11af, 0x28},	{0x11b0, 0xd8},
+	{0x11b1, 0x14},	{0x11b2, 0xec},	{0x11b3, 0x32},
+	{0x11b4, 0xdd},	{0x11b5, 0x32},	{0x11b6, 0xdd},
+	{0x10e0, 0x2c},	{0x11bc, 0x40},	{0x11bd, 0x01},
+	{0x11be, 0xf0},	{0x11bf, 0x00},	{0x118c, 0x1f},
+	{0x118d, 0x1f},	{0x118e, 0x1f},	{0x118f, 0x1f},
+	{0x1180, 0x01},	{0x1181, 0x00},	{0x1182, 0x01},
+	{0x1183, 0x00},	{0x1184, 0x50},	{0x1185, 0x80}
+};
+
+/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
+static u8 ov_gain[] = {
+	0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
+	0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
+	0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
+	0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
+	0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
+	0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
+	0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
+	0x70 /* 8x */
+};
+
+/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
+static u16 micron1_gain[] = {
+	/* 1x   1.25x   1.5x    1.75x */
+	0x0020, 0x0028, 0x0030, 0x0038,
+	/* 2x   2.25x   2.5x    2.75x */
+	0x00a0, 0x00a4, 0x00a8, 0x00ac,
+	/* 3x   3.25x   3.5x    3.75x */
+	0x00b0, 0x00b4, 0x00b8, 0x00bc,
+	/* 4x   4.25x   4.5x    4.75x */
+	0x00c0, 0x00c4, 0x00c8, 0x00cc,
+	/* 5x   5.25x   5.5x    5.75x */
+	0x00d0, 0x00d4, 0x00d8, 0x00dc,
+	/* 6x   6.25x   6.5x    6.75x */
+	0x00e0, 0x00e4, 0x00e8, 0x00ec,
+	/* 7x   7.25x   7.5x    7.75x */
+	0x00f0, 0x00f4, 0x00f8, 0x00fc,
+	/* 8x */
+	0x01c0
+};
+
+/* mt9m001 sensor uses a different gain formula then other micron sensors */
+/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
+static u16 micron2_gain[] = {
+	/* 1x   1.25x   1.5x    1.75x */
+	0x0008, 0x000a, 0x000c, 0x000e,
+	/* 2x   2.25x   2.5x    2.75x */
+	0x0010, 0x0012, 0x0014, 0x0016,
+	/* 3x   3.25x   3.5x    3.75x */
+	0x0018, 0x001a, 0x001c, 0x001e,
+	/* 4x   4.25x   4.5x    4.75x */
+	0x0020, 0x0051, 0x0052, 0x0053,
+	/* 5x   5.25x   5.5x    5.75x */
+	0x0054, 0x0055, 0x0056, 0x0057,
+	/* 6x   6.25x   6.5x    6.75x */
+	0x0058, 0x0059, 0x005a, 0x005b,
+	/* 7x   7.25x   7.5x    7.75x */
+	0x005c, 0x005d, 0x005e, 0x005f,
+	/* 8x */
+	0x0060
+};
+
+/* Gain = .5 + bit[7:0] / 16 */
+static u8 hv7131r_gain[] = {
+	0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
+	0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
+	0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
+	0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
+	0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
+	0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
+	0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
+	0x78 /* 8x */
+};
+
+static u8 soi968_init[][2] = {
+	{0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
+	{0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
+	{0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
+	{0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
+	{0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
+	{0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
+	{0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13},
+	{0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
+	{0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
+	{0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
+	{0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
+};
+
+static u8 ov7660_init[][2] = {
+	{0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
+	{0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
+	{0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
+	{0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
+	{0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
+	{0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
+};
+
+static u8 ov7670_init[][2] = {
+	{0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
+	{0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
+	{0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
+	{0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
+	{0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
+	{0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
+	{0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
+	{0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
+	{0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
+	{0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
+	{0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
+	{0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
+	{0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
+	{0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
+	{0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
+	{0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
+	{0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
+	{0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
+	{0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
+	{0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
+	{0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
+	{0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
+	{0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
+	{0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
+	{0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
+	{0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
+	{0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
+	{0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
+	{0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
+	{0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
+	{0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
+	{0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
+	{0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
+	{0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
+	{0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
+	{0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
+	{0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
+	{0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
+	{0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
+	{0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
+	{0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
+	{0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
+	{0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
+	{0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
+	{0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
+	{0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
+	{0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
+	{0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
+	{0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
+	{0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
+	{0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
+	{0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
+	{0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
+	{0x93, 0x00},
+};
+
+static u8 ov9650_init[][2] = {
+	{0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
+	{0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
+	{0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
+	{0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
+	{0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
+	{0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
+	{0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
+	{0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
+	{0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
+	{0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
+	{0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
+	{0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
+	{0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
+	{0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
+	{0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
+	{0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
+	{0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
+	{0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
+	{0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
+	{0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
+	{0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
+	{0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
+	{0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
+	{0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
+	{0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
+	{0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
+	{0xaa, 0x92}, {0xab, 0x0a},
+};
+
+static u8 ov9655_init[][2] = {
+	{0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61},
+	{0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24},
+	{0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08},
+	{0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf},
+	{0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12},
+	{0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c},
+	{0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40},
+	{0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a},
+	{0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc},
+	{0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04},
+	{0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02},
+	{0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c},
+	{0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60},
+	{0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04},
+	{0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80},
+	{0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf},
+	{0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b},
+	{0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01},
+	{0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
+	{0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61},
+	{0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
+	{0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01},
+	{0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10},
+	{0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04},
+	{0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00},
+	{0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80},
+	{0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d},
+	{0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14},
+	{0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf},
+	{0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00},
+	{0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00},
+	{0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03},
+	{0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03},
+	{0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13},
+};
+
+static u16 mt9v112_init[][2] = {
+	{0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
+	{0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
+	{0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
+	{0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
+	{0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
+	{0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
+	{0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
+	{0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
+	{0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
+	{0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
+	{0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
+	{0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
+	{0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
+	{0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
+	{0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
+	{0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
+};
+
+static u16 mt9v111_init[][2] = {
+	{0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
+	{0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1},
+	{0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002},
+	{0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03},
+	{0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c},
+	{0x2d, 0xf0a0},	{0x2e, 0x0c64},	{0x2f, 0x0064},
+	{0x67, 0x4010},	{0x06, 0x301e},	{0x08, 0x0480},
+	{0x01, 0x0004},	{0x02, 0x0016}, {0x03, 0x01e6},
+	{0x04, 0x0286},	{0x05, 0x0004}, {0x06, 0x0000},
+	{0x07, 0x3002},	{0x08, 0x0008}, {0x0c, 0x0000},
+	{0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000},
+	{0x10, 0x0000},	{0x11, 0x0000},	{0x12, 0x00b0},
+	{0x13, 0x007c},	{0x14, 0x0000}, {0x15, 0x0000},
+	{0x16, 0x0000}, {0x17, 0x0000},	{0x18, 0x0000},
+	{0x19, 0x0000},	{0x1a, 0x0000},	{0x1b, 0x0000},
+	{0x1c, 0x0000},	{0x1d, 0x0000},	{0x30, 0x0000},
+	{0x30, 0x0005},	{0x31, 0x0000},	{0x02, 0x0016},
+	{0x03, 0x01e1},	{0x04, 0x0281}, {0x05, 0x0004},
+	{0x06, 0x0000},	{0x07, 0x3002},	{0x06, 0x002d},
+	{0x05, 0x0004},	{0x09, 0x0064},	{0x2b, 0x00a0},
+	{0x2c, 0x00a0},	{0x2d, 0x00a0},	{0x2e, 0x00a0},
+	{0x02, 0x0016},	{0x03, 0x01e1},	{0x04, 0x0281},
+	{0x05, 0x0004},	{0x06, 0x002d},	{0x07, 0x3002},
+	{0x0e, 0x0008},	{0x06, 0x002d},	{0x05, 0x0004},
+};
+
+static u16 mt9v011_init[][2] = {
+	{0x07, 0x0002},	{0x0d, 0x0001},	{0x0d, 0x0000},
+	{0x01, 0x0008},	{0x02, 0x0016},	{0x03, 0x01e1},
+	{0x04, 0x0281},	{0x05, 0x0083},	{0x06, 0x0006},
+	{0x0d, 0x0002}, {0x0a, 0x0000},	{0x0b, 0x0000},
+	{0x0c, 0x0000},	{0x0d, 0x0000},	{0x0e, 0x0000},
+	{0x0f, 0x0000},	{0x10, 0x0000},	{0x11, 0x0000},
+	{0x12, 0x0000},	{0x13, 0x0000},	{0x14, 0x0000},
+	{0x15, 0x0000},	{0x16, 0x0000},	{0x17, 0x0000},
+	{0x18, 0x0000},	{0x19, 0x0000},	{0x1a, 0x0000},
+	{0x1b, 0x0000},	{0x1c, 0x0000},	{0x1d, 0x0000},
+	{0x32, 0x0000},	{0x20, 0x1101},	{0x21, 0x0000},
+	{0x22, 0x0000},	{0x23, 0x0000},	{0x24, 0x0000},
+	{0x25, 0x0000},	{0x26, 0x0000},	{0x27, 0x0024},
+	{0x2f, 0xf7b0},	{0x30, 0x0005},	{0x31, 0x0000},
+	{0x32, 0x0000},	{0x33, 0x0000},	{0x34, 0x0100},
+	{0x3d, 0x068f},	{0x40, 0x01e0},	{0x41, 0x00d1},
+	{0x44, 0x0082},	{0x5a, 0x0000},	{0x5b, 0x0000},
+	{0x5c, 0x0000},	{0x5d, 0x0000},	{0x5e, 0x0000},
+	{0x5f, 0xa31d},	{0x62, 0x0611},	{0x0a, 0x0000},
+	{0x06, 0x0029},	{0x05, 0x0009},	{0x20, 0x1101},
+	{0x20, 0x1101},	{0x09, 0x0064},	{0x07, 0x0003},
+	{0x2b, 0x0033},	{0x2c, 0x00a0},	{0x2d, 0x00a0},
+	{0x2e, 0x0033},	{0x07, 0x0002},	{0x06, 0x0000},
+	{0x06, 0x0029},	{0x05, 0x0009},
+};
+
+static u16 mt9m001_init[][2] = {
+	{0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
+	{0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
+	{0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
+	{0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
+	{0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000},
+	{0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000},
+	{0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2},
+	{0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003},
+	{0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a},
+	{0x2e, 0x0029}, {0x07, 0x0002},
+};
+
+static u16 mt9m111_init[][2] = {
+	{0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009},
+	{0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300},
+	{0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200},
+	{0x06, 0x308e}, {0xf0, 0x0000},
+};
+
+static u8 hv7131r_init[][2] = {
+	{0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
+	{0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
+	{0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
+	{0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
+	{0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
+	{0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
+	{0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
+	{0x23, 0x09}, {0x01, 0x08},
+};
+
+int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int result;
+	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			0x00,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			reg,
+			0x00,
+			gspca_dev->usb_buf,
+			length,
+			500);
+	if (unlikely(result < 0 || result != length)) {
+		err("Read register failed 0x%02X", reg);
+		return -EIO;
+	}
+	return 0;
+}
+
+int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int result;
+	memcpy(gspca_dev->usb_buf, buffer, length);
+	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x08,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			reg,
+			0x00,
+			gspca_dev->usb_buf,
+			length,
+			500);
+	if (unlikely(result < 0 || result != length)) {
+		err("Write register failed index 0x%02X", reg);
+		return -EIO;
+	}
+	return 0;
+}
+
+int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
+{
+	u8 data[1] = {value};
+	return reg_w(gspca_dev, reg, data, 1);
+}
+
+int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
+{
+	int i;
+	reg_w(gspca_dev, 0x10c0, buffer, 8);
+	for (i = 0; i < 5; i++) {
+		reg_r(gspca_dev, 0x10c0, 1);
+		if (gspca_dev->usb_buf[0] & 0x04) {
+			if (gspca_dev->usb_buf[0] & 0x08)
+				return -1;
+			return 0;
+		}
+		msleep(1);
+	}
+	return -1;
+}
+
+int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	u8 row[8];
+
+	/*
+	 * from the point of view of the bridge, the length
+	 * includes the address
+	 */
+	row[0] = 0x81 | (2 << 4);
+	row[1] = sd->i2c_addr;
+	row[2] = reg;
+	row[3] = val;
+	row[4] = 0x00;
+	row[5] = 0x00;
+	row[6] = 0x00;
+	row[7] = 0x10;
+
+	return i2c_w(gspca_dev, row);
+}
+
+int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 row[8];
+
+	/*
+	 * from the point of view of the bridge, the length
+	 * includes the address
+	 */
+	row[0] = 0x81 | (3 << 4);
+	row[1] = sd->i2c_addr;
+	row[2] = reg;
+	row[3] = (val >> 8) & 0xff;
+	row[4] = val & 0xff;
+	row[5] = 0x00;
+	row[6] = 0x00;
+	row[7] = 0x10;
+
+	return i2c_w(gspca_dev, row);
+}
+
+int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 row[8];
+
+	row[0] = 0x81 | 0x10;
+	row[1] = sd->i2c_addr;
+	row[2] = reg;
+	row[3] = 0;
+	row[4] = 0;
+	row[5] = 0;
+	row[6] = 0;
+	row[7] = 0x10;
+	reg_w(gspca_dev, 0x10c0, row, 8);
+	msleep(1);
+	row[0] = 0x81 | (2 << 4) | 0x02;
+	row[2] = 0;
+	reg_w(gspca_dev, 0x10c0, row, 8);
+	msleep(1);
+	reg_r(gspca_dev, 0x10c2, 5);
+	*val = gspca_dev->usb_buf[3];
+	return 0;
+}
+
+int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 row[8];
+
+	row[0] = 0x81 | 0x10;
+	row[1] = sd->i2c_addr;
+	row[2] = reg;
+	row[3] = 0;
+	row[4] = 0;
+	row[5] = 0;
+	row[6] = 0;
+	row[7] = 0x10;
+	reg_w(gspca_dev, 0x10c0, row, 8);
+	msleep(1);
+	row[0] = 0x81 | (3 << 4) | 0x02;
+	row[2] = 0;
+	reg_w(gspca_dev, 0x10c0, row, 8);
+	msleep(1);
+	reg_r(gspca_dev, 0x10c2, 5);
+	*val = (gspca_dev->usb_buf[2] << 8) | gspca_dev->usb_buf[3];
+	return 0;
+}
+
+static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
+{
+	int i;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
+		if (i2c_w1(gspca_dev, ov9650_init[i][0],
+				ov9650_init[i][1]) < 0) {
+			err("OV9650 sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	sd->hstart = 1;
+	sd->vstart = 7;
+	return 0;
+}
+
+static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
+{
+	int i;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
+		if (i2c_w1(gspca_dev, ov9655_init[i][0],
+				ov9655_init[i][1]) < 0) {
+			err("OV9655 sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	/* disable hflip and vflip */
+	gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+	sd->hstart = 0;
+	sd->vstart = 7;
+	return 0;
+}
+
+static int soi968_init_sensor(struct gspca_dev *gspca_dev)
+{
+	int i;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
+		if (i2c_w1(gspca_dev, soi968_init[i][0],
+				soi968_init[i][1]) < 0) {
+			err("SOI968 sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	/* disable hflip and vflip */
+	gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+	sd->hstart = 60;
+	sd->vstart = 11;
+	return 0;
+}
+
+static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
+{
+	int i;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
+		if (i2c_w1(gspca_dev, ov7660_init[i][0],
+				ov7660_init[i][1]) < 0) {
+			err("OV7660 sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	/* disable hflip and vflip */
+	gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+	sd->hstart = 1;
+	sd->vstart = 1;
+	return 0;
+}
+
+static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
+{
+	int i;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
+		if (i2c_w1(gspca_dev, ov7670_init[i][0],
+				ov7670_init[i][1]) < 0) {
+			err("OV7670 sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	/* disable hflip and vflip */
+	gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+	sd->hstart = 0;
+	sd->vstart = 1;
+	return 0;
+}
+
+static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i;
+	u16 value;
+	int ret;
+
+	sd->i2c_addr = 0x5d;
+	ret = i2c_r2(gspca_dev, 0xff, &value);
+	if ((ret == 0) && (value == 0x8243)) {
+		for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
+			if (i2c_w2(gspca_dev, mt9v011_init[i][0],
+					mt9v011_init[i][1]) < 0) {
+				err("MT9V011 sensor initialization failed");
+				return -ENODEV;
+			}
+		}
+		sd->hstart = 2;
+		sd->vstart = 2;
+		sd->sensor = SENSOR_MT9V011;
+		info("MT9V011 sensor detected");
+		return 0;
+	}
+
+	sd->i2c_addr = 0x5c;
+	i2c_w2(gspca_dev, 0x01, 0x0004);
+	ret = i2c_r2(gspca_dev, 0xff, &value);
+	if ((ret == 0) && (value == 0x823a)) {
+		for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
+			if (i2c_w2(gspca_dev, mt9v111_init[i][0],
+					mt9v111_init[i][1]) < 0) {
+				err("MT9V111 sensor initialization failed");
+				return -ENODEV;
+			}
+		}
+		sd->hstart = 2;
+		sd->vstart = 2;
+		sd->sensor = SENSOR_MT9V111;
+		info("MT9V111 sensor detected");
+		return 0;
+	}
+
+	sd->i2c_addr = 0x5d;
+	ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
+	if (ret < 0) {
+		sd->i2c_addr = 0x48;
+		i2c_w2(gspca_dev, 0xf0, 0x0000);
+	}
+	ret = i2c_r2(gspca_dev, 0x00, &value);
+	if ((ret == 0) && (value == 0x1229)) {
+		for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
+			if (i2c_w2(gspca_dev, mt9v112_init[i][0],
+					mt9v112_init[i][1]) < 0) {
+				err("MT9V112 sensor initialization failed");
+				return -ENODEV;
+			}
+		}
+		sd->hstart = 6;
+		sd->vstart = 2;
+		sd->sensor = SENSOR_MT9V112;
+		info("MT9V112 sensor detected");
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i;
+	for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
+		if (i2c_w2(gspca_dev, mt9m111_init[i][0],
+				mt9m111_init[i][1]) < 0) {
+			err("MT9M111 sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	sd->hstart = 0;
+	sd->vstart = 2;
+	return 0;
+}
+
+static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i;
+	for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
+		if (i2c_w2(gspca_dev, mt9m001_init[i][0],
+				mt9m001_init[i][1]) < 0) {
+			err("MT9M001 sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	/* disable hflip and vflip */
+	gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+	sd->hstart = 2;
+	sd->vstart = 2;
+	return 0;
+}
+
+static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
+{
+	int i;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
+		if (i2c_w1(gspca_dev, hv7131r_init[i][0],
+				hv7131r_init[i][1]) < 0) {
+			err("HV7131R Sensor initialization failed");
+			return -ENODEV;
+		}
+	}
+	sd->hstart = 0;
+	sd->vstart = 1;
+	return 0;
+}
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+static int input_kthread(void *data)
+{
+	struct gspca_dev *gspca_dev = (struct gspca_dev *)data;
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	DECLARE_WAIT_QUEUE_HEAD(wait);
+	set_freezable();
+	for (;;) {
+		if (kthread_should_stop())
+			break;
+
+		if (reg_r(gspca_dev, 0x1005, 1) < 0)
+			continue;
+
+		input_report_key(sd->input_dev,
+				 KEY_CAMERA,
+				 gspca_dev->usb_buf[0] & sd->input_gpio);
+		input_sync(sd->input_dev);
+
+		wait_event_freezable_timeout(wait,
+					     kthread_should_stop(),
+					     msecs_to_jiffies(100));
+	}
+	return 0;
+}
+
+
+static int sn9c20x_input_init(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	if (sd->input_gpio == 0)
+		return 0;
+
+	sd->input_dev = input_allocate_device();
+	if (!sd->input_dev)
+		return -ENOMEM;
+
+	sd->input_dev->name = "SN9C20X Webcam";
+
+	sd->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s",
+					 gspca_dev->dev->bus->bus_name,
+					 gspca_dev->dev->devpath);
+
+	if (!sd->input_dev->phys)
+		return -ENOMEM;
+
+	usb_to_input_id(gspca_dev->dev, &sd->input_dev->id);
+	sd->input_dev->dev.parent = &gspca_dev->dev->dev;
+
+	set_bit(EV_KEY, sd->input_dev->evbit);
+	set_bit(KEY_CAMERA, sd->input_dev->keybit);
+
+	if (input_register_device(sd->input_dev))
+		return -EINVAL;
+
+	sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d",
+				     gspca_dev->vdev.minor);
+
+	if (IS_ERR(sd->input_task))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void sn9c20x_input_cleanup(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	if (sd->input_task != NULL && !IS_ERR(sd->input_task))
+		kthread_stop(sd->input_task);
+
+	if (sd->input_dev != NULL) {
+		input_unregister_device(sd->input_dev);
+		kfree(sd->input_dev->phys);
+		input_free_device(sd->input_dev);
+		sd->input_dev = NULL;
+	}
+}
+#endif
+
+static int set_cmatrix(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 hue_coord, hue_index = 180 + sd->hue;
+	u8 cmatrix[21];
+	memset(cmatrix, 0, 21);
+
+	cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
+	cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
+	cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
+	cmatrix[18] = sd->brightness - 0x80;
+
+	hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
+	cmatrix[6] = (unsigned char)(hue_coord & 0xff);
+	cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+	hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
+	cmatrix[8] = (unsigned char)(hue_coord & 0xff);
+	cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+	hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
+	cmatrix[10] = (unsigned char)(hue_coord & 0xff);
+	cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+	hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
+	cmatrix[12] = (unsigned char)(hue_coord & 0xff);
+	cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+	hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
+	cmatrix[14] = (unsigned char)(hue_coord & 0xff);
+	cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+	hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
+	cmatrix[16] = (unsigned char)(hue_coord & 0xff);
+	cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+	return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
+}
+
+static int set_gamma(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 gamma[17];
+	u8 gval = sd->gamma * 0xb8 / 0x100;
+
+
+	gamma[0] = 0x0a;
+	gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
+	gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
+	gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
+	gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
+	gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
+	gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
+	gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
+	gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
+	gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
+	gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
+	gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
+	gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
+	gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
+	gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
+	gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
+	gamma[16] = 0xf5;
+
+	return reg_w(gspca_dev, 0x1190, gamma, 17);
+}
+
+static int set_redblue(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	reg_w1(gspca_dev, 0x118c, sd->red);
+	reg_w1(gspca_dev, 0x118f, sd->blue);
+	return 0;
+}
+
+static int set_hvflip(struct gspca_dev *gspca_dev)
+{
+	u8 value, tslb;
+	u16 value2;
+	struct sd *sd = (struct sd *) gspca_dev;
+	switch (sd->sensor) {
+	case SENSOR_OV9650:
+		i2c_r1(gspca_dev, 0x1e, &value);
+		value &= ~0x30;
+		tslb = 0x01;
+		if (sd->hflip)
+			value |= 0x20;
+		if (sd->vflip) {
+			value |= 0x10;
+			tslb = 0x49;
+		}
+		i2c_w1(gspca_dev, 0x1e, value);
+		i2c_w1(gspca_dev, 0x3a, tslb);
+		break;
+	case SENSOR_MT9V111:
+	case SENSOR_MT9V011:
+		i2c_r2(gspca_dev, 0x20, &value2);
+		value2 &= ~0xc0a0;
+		if (sd->hflip)
+			value2 |= 0x8080;
+		if (sd->vflip)
+			value2 |= 0x4020;
+		i2c_w2(gspca_dev, 0x20, value2);
+		break;
+	case SENSOR_MT9M111:
+	case SENSOR_MT9V112:
+		i2c_r2(gspca_dev, 0x20, &value2);
+		value2 &= ~0x0003;
+		if (sd->hflip)
+			value2 |= 0x0002;
+		if (sd->vflip)
+			value2 |= 0x0001;
+		i2c_w2(gspca_dev, 0x20, value2);
+		break;
+	case SENSOR_HV7131R:
+		i2c_r1(gspca_dev, 0x01, &value);
+		value &= ~0x03;
+		if (sd->vflip)
+			value |= 0x01;
+		if (sd->hflip)
+			value |= 0x02;
+		i2c_w1(gspca_dev, 0x01, value);
+		break;
+	}
+	return 0;
+}
+
+static int set_exposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
+	switch (sd->sensor) {
+	case SENSOR_OV7660:
+	case SENSOR_OV7670:
+	case SENSOR_SOI968:
+	case SENSOR_OV9655:
+	case SENSOR_OV9650:
+		exp[0] |= (3 << 4);
+		exp[2] = 0x2d;
+		exp[3] = sd->exposure & 0xff;
+		exp[4] = sd->exposure >> 8;
+		break;
+	case SENSOR_MT9M001:
+	case SENSOR_MT9M111:
+	case SENSOR_MT9V112:
+	case SENSOR_MT9V111:
+	case SENSOR_MT9V011:
+		exp[0] |= (3 << 4);
+		exp[2] = 0x09;
+		exp[3] = sd->exposure >> 8;
+		exp[4] = sd->exposure & 0xff;
+		break;
+	case SENSOR_HV7131R:
+		exp[0] |= (4 << 4);
+		exp[2] = 0x25;
+		exp[3] = ((sd->exposure * 0xffffff) / 0xffff) >> 16;
+		exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8;
+		exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff;
+		break;
+	}
+	i2c_w(gspca_dev, exp);
+	return 0;
+}
+
+static int set_gain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
+	switch (sd->sensor) {
+	case SENSOR_OV7660:
+	case SENSOR_OV7670:
+	case SENSOR_SOI968:
+	case SENSOR_OV9655:
+	case SENSOR_OV9650:
+		gain[0] |= (2 << 4);
+		gain[3] = ov_gain[sd->gain];
+		break;
+	case SENSOR_MT9V011:
+	case SENSOR_MT9V111:
+		gain[0] |= (3 << 4);
+		gain[2] = 0x35;
+		gain[3] = micron1_gain[sd->gain] >> 8;
+		gain[4] = micron1_gain[sd->gain] & 0xff;
+		break;
+	case SENSOR_MT9V112:
+	case SENSOR_MT9M111:
+		gain[0] |= (3 << 4);
+		gain[2] = 0x2f;
+		gain[3] = micron1_gain[sd->gain] >> 8;
+		gain[4] = micron1_gain[sd->gain] & 0xff;
+		break;
+	case SENSOR_MT9M001:
+		gain[0] |= (3 << 4);
+		gain[2] = 0x2f;
+		gain[3] = micron2_gain[sd->gain] >> 8;
+		gain[4] = micron2_gain[sd->gain] & 0xff;
+		break;
+	case SENSOR_HV7131R:
+		gain[0] |= (2 << 4);
+		gain[2] = 0x30;
+		gain[3] = hv7131r_gain[sd->gain];
+		break;
+	}
+	i2c_w(gspca_dev, gain);
+	return 0;
+}
+
+static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->brightness = val;
+	if (gspca_dev->streaming)
+		return set_cmatrix(gspca_dev);
+	return 0;
+}
+
+static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->brightness;
+	return 0;
+}
+
+
+static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->contrast = val;
+	if (gspca_dev->streaming)
+		return set_cmatrix(gspca_dev);
+	return 0;
+}
+
+static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->contrast;
+	return 0;
+}
+
+static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->saturation = val;
+	if (gspca_dev->streaming)
+		return set_cmatrix(gspca_dev);
+	return 0;
+}
+
+static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->saturation;
+	return 0;
+}
+
+static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->hue = val;
+	if (gspca_dev->streaming)
+		return set_cmatrix(gspca_dev);
+	return 0;
+}
+
+static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->hue;
+	return 0;
+}
+
+static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->gamma = val;
+	if (gspca_dev->streaming)
+		return set_gamma(gspca_dev);
+	return 0;
+}
+
+static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->gamma;
+	return 0;
+}
+
+static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->red = val;
+	if (gspca_dev->streaming)
+		return set_redblue(gspca_dev);
+	return 0;
+}
+
+static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->red;
+	return 0;
+}
+
+static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->blue = val;
+	if (gspca_dev->streaming)
+		return set_redblue(gspca_dev);
+	return 0;
+}
+
+static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->blue;
+	return 0;
+}
+
+static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->hflip = val;
+	if (gspca_dev->streaming)
+		return set_hvflip(gspca_dev);
+	return 0;
+}
+
+static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->hflip;
+	return 0;
+}
+
+static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->vflip = val;
+	if (gspca_dev->streaming)
+		return set_hvflip(gspca_dev);
+	return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->vflip;
+	return 0;
+}
+
+static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->exposure = val;
+	if (gspca_dev->streaming)
+		return set_exposure(gspca_dev);
+	return 0;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->exposure;
+	return 0;
+}
+
+static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->gain = val;
+	if (gspca_dev->streaming)
+		return set_gain(gspca_dev);
+	return 0;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->gain;
+	return 0;
+}
+
+static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	sd->auto_exposure = val;
+	return 0;
+}
+
+static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	*val = sd->auto_exposure;
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
+			struct v4l2_dbg_register *reg)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_HOST:
+		if (reg->match.addr != 0)
+			return -EINVAL;
+		if (reg->reg < 0x1000 || reg->reg > 0x11ff)
+			return -EINVAL;
+		if (reg_r(gspca_dev, reg->reg, 1) < 0)
+			return -EINVAL;
+		reg->val = gspca_dev->usb_buf[0];
+		return 0;
+	case V4L2_CHIP_MATCH_I2C_ADDR:
+		if (reg->match.addr != sd->i2c_addr)
+			return -EINVAL;
+		if (sd->sensor >= SENSOR_MT9V011 &&
+		    sd->sensor <= SENSOR_MT9M111) {
+			if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
+				return -EINVAL;
+		} else {
+			if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
+				return -EINVAL;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
+			struct v4l2_dbg_register *reg)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_HOST:
+		if (reg->match.addr != 0)
+			return -EINVAL;
+		if (reg->reg < 0x1000 || reg->reg > 0x11ff)
+			return -EINVAL;
+		if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CHIP_MATCH_I2C_ADDR:
+		if (reg->match.addr != sd->i2c_addr)
+			return -EINVAL;
+		if (sd->sensor >= SENSOR_MT9V011 &&
+		    sd->sensor <= SENSOR_MT9M111) {
+			if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
+				return -EINVAL;
+		} else {
+			if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
+				return -EINVAL;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+#endif
+
+static int sd_chip_ident(struct gspca_dev *gspca_dev,
+			struct v4l2_dbg_chip_ident *chip)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	switch (chip->match.type) {
+	case V4L2_CHIP_MATCH_HOST:
+		if (chip->match.addr != 0)
+			return -EINVAL;
+		chip->revision = 0;
+		chip->ident = V4L2_IDENT_SN9C20X;
+		return 0;
+	case V4L2_CHIP_MATCH_I2C_ADDR:
+		if (chip->match.addr != sd->i2c_addr)
+			return -EINVAL;
+		chip->revision = 0;
+		chip->ident = i2c_ident[sd->sensor];
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int sd_config(struct gspca_dev *gspca_dev,
+			const struct usb_device_id *id)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	struct cam *cam;
+
+	cam = &gspca_dev->cam;
+
+	sd->sensor = (id->driver_info >> 8) & 0xff;
+	sd->i2c_addr = id->driver_info & 0xff;
+
+	switch (sd->sensor) {
+	case SENSOR_OV9650:
+		cam->cam_mode = sxga_mode;
+		cam->nmodes = ARRAY_SIZE(sxga_mode);
+		break;
+	default:
+		cam->cam_mode = vga_mode;
+		cam->nmodes = ARRAY_SIZE(vga_mode);
+	}
+
+	sd->old_step = 0;
+	sd->older_step = 0;
+	sd->exposure_step = 16;
+
+	sd->brightness = BRIGHTNESS_DEFAULT;
+	sd->contrast = CONTRAST_DEFAULT;
+	sd->saturation = SATURATION_DEFAULT;
+	sd->hue = HUE_DEFAULT;
+	sd->gamma = GAMMA_DEFAULT;
+	sd->red = RED_DEFAULT;
+	sd->blue = BLUE_DEFAULT;
+
+	sd->hflip = HFLIP_DEFAULT;
+	sd->vflip = VFLIP_DEFAULT;
+	sd->exposure = EXPOSURE_DEFAULT;
+	sd->gain = GAIN_DEFAULT;
+	sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
+
+	sd->quality = 95;
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+	sd->input_gpio = (id->driver_info >> 16) & 0xff;
+	if (sn9c20x_input_init(gspca_dev) < 0)
+		return -ENODEV;
+#endif
+	return 0;
+}
+
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i;
+	u8 value;
+	u8 i2c_init[9] =
+		{0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
+
+	for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
+		value = bridge_init[i][1];
+		if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
+			err("Device initialization failed");
+			return -ENODEV;
+		}
+	}
+
+	if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
+		err("Device initialization failed");
+		return -ENODEV;
+	}
+
+	switch (sd->sensor) {
+	case SENSOR_OV9650:
+		if (ov9650_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("OV9650 sensor detected");
+		break;
+	case SENSOR_OV9655:
+		if (ov9655_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("OV9655 sensor detected");
+		break;
+	case SENSOR_SOI968:
+		if (soi968_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("SOI968 sensor detected");
+		break;
+	case SENSOR_OV7660:
+		if (ov7660_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("OV7660 sensor detected");
+		break;
+	case SENSOR_OV7670:
+		if (ov7670_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("OV7670 sensor detected");
+		break;
+	case SENSOR_MT9VPRB:
+		if (mt9v_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		break;
+	case SENSOR_MT9M111:
+		if (mt9m111_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("MT9M111 sensor detected");
+		break;
+	case SENSOR_MT9M001:
+		if (mt9m001_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("MT9M001 sensor detected");
+		break;
+	case SENSOR_HV7131R:
+		if (hv7131r_init_sensor(gspca_dev) < 0)
+			return -ENODEV;
+		info("HV7131R sensor detected");
+		break;
+	default:
+		info("Unsupported Sensor");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 value;
+	switch (sd->sensor) {
+	case SENSOR_OV9650:
+		if (mode & MODE_SXGA) {
+			i2c_w1(gspca_dev, 0x17, 0x1b);
+			i2c_w1(gspca_dev, 0x18, 0xbc);
+			i2c_w1(gspca_dev, 0x19, 0x01);
+			i2c_w1(gspca_dev, 0x1a, 0x82);
+			i2c_r1(gspca_dev, 0x12, &value);
+			i2c_w1(gspca_dev, 0x12, value & 0x07);
+		} else {
+			i2c_w1(gspca_dev, 0x17, 0x24);
+			i2c_w1(gspca_dev, 0x18, 0xc5);
+			i2c_w1(gspca_dev, 0x19, 0x00);
+			i2c_w1(gspca_dev, 0x1a, 0x3c);
+			i2c_r1(gspca_dev, 0x12, &value);
+			i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
+		}
+		break;
+	}
+}
+
+#define HW_WIN(mode, hstart, vstart) \
+((const u8 []){hstart & 0xff, hstart >> 8, \
+vstart & 0xff, vstart >> 8, \
+(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
+(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
+
+#define CLR_WIN(width, height) \
+((const u8 [])\
+{0, width >> 2, 0, height >> 1,\
+((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+	int width = gspca_dev->width;
+	int height = gspca_dev->height;
+	u8 fmt, scale = 0;
+
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (sd->jpeg_hdr == NULL)
+		return -ENOMEM;
+
+	jpeg_define(sd->jpeg_hdr, height, width,
+			0x21);
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
+	if (mode & MODE_RAW)
+		fmt = 0x2d;
+	else if (mode & MODE_JPEG)
+		fmt = 0x2c;
+	else
+		fmt = 0x2f;
+
+	switch (mode & 0x0f) {
+	case 3:
+		scale = 0xc0;
+		info("Set 1280x1024");
+		break;
+	case 2:
+		scale = 0x80;
+		info("Set 640x480");
+		break;
+	case 1:
+		scale = 0x90;
+		info("Set 320x240");
+		break;
+	case 0:
+		scale = 0xa0;
+		info("Set 160x120");
+		break;
+	}
+
+	configure_sensor_output(gspca_dev, mode);
+	reg_w(gspca_dev, 0x1100, sd->jpeg_hdr + JPEG_QT0_OFFSET, 64);
+	reg_w(gspca_dev, 0x1140, sd->jpeg_hdr + JPEG_QT1_OFFSET, 64);
+	reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
+	reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
+	reg_w1(gspca_dev, 0x1189, scale);
+	reg_w1(gspca_dev, 0x10e0, fmt);
+
+	set_cmatrix(gspca_dev);
+	set_gamma(gspca_dev);
+	set_redblue(gspca_dev);
+	set_gain(gspca_dev);
+	set_exposure(gspca_dev);
+	set_hvflip(gspca_dev);
+
+	reg_r(gspca_dev, 0x1061, 1);
+	reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
+	return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+	reg_r(gspca_dev, 0x1061, 1);
+	reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
+}
+
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	kfree(sd->jpeg_hdr);
+}
+
+static void do_autoexposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int avg_lum, new_exp;
+
+	if (!sd->auto_exposure)
+		return;
+
+	avg_lum = atomic_read(&sd->avg_lum);
+
+	/*
+	 * some hardcoded values are present
+	 * like those for maximal/minimal exposure
+	 * and exposure steps
+	 */
+	if (avg_lum < MIN_AVG_LUM) {
+		if (sd->exposure > 0x1770)
+			return;
+
+		new_exp = sd->exposure + sd->exposure_step;
+		if (new_exp > 0x1770)
+			new_exp = 0x1770;
+		if (new_exp < 0x10)
+			new_exp = 0x10;
+		sd->exposure = new_exp;
+		set_exposure(gspca_dev);
+
+		sd->older_step = sd->old_step;
+		sd->old_step = 1;
+
+		if (sd->old_step ^ sd->older_step)
+			sd->exposure_step /= 2;
+		else
+			sd->exposure_step += 2;
+	}
+	if (avg_lum > MAX_AVG_LUM) {
+		if (sd->exposure < 0x10)
+			return;
+		new_exp = sd->exposure - sd->exposure_step;
+		if (new_exp > 0x1700)
+			new_exp = 0x1770;
+		if (new_exp < 0x10)
+			new_exp = 0x10;
+		sd->exposure = new_exp;
+		set_exposure(gspca_dev);
+		sd->older_step = sd->old_step;
+		sd->old_step = 0;
+
+		if (sd->old_step ^ sd->older_step)
+			sd->exposure_step /= 2;
+		else
+			sd->exposure_step += 2;
+	}
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			struct gspca_frame *frame,	/* target */
+			u8 *data,			/* isoc packet */
+			int len)			/* iso packet length */
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int avg_lum;
+	static unsigned char frame_header[] =
+		{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+	if (len == 64 && memcmp(data, frame_header, 6) == 0) {
+		avg_lum = ((data[35] >> 2) & 3) |
+			   (data[20] << 2) |
+			   (data[19] << 10);
+		avg_lum += ((data[35] >> 4) & 3) |
+			    (data[22] << 2) |
+			    (data[21] << 10);
+		avg_lum += ((data[35] >> 6) & 3) |
+			    (data[24] << 2) |
+			    (data[23] << 10);
+		avg_lum += (data[36] & 3) |
+			   (data[26] << 2) |
+			   (data[25] << 10);
+		avg_lum += ((data[36] >> 2) & 3) |
+			    (data[28] << 2) |
+			    (data[27] << 10);
+		avg_lum += ((data[36] >> 4) & 3) |
+			    (data[30] << 2) |
+			    (data[29] << 10);
+		avg_lum += ((data[36] >> 6) & 3) |
+			    (data[32] << 2) |
+			    (data[31] << 10);
+		avg_lum += ((data[44] >> 4) & 3) |
+			    (data[34] << 2) |
+			    (data[33] << 10);
+		avg_lum >>= 9;
+		atomic_set(&sd->avg_lum, avg_lum);
+		gspca_frame_add(gspca_dev, LAST_PACKET,
+				frame, data, len);
+		return;
+	}
+	if (gspca_dev->last_packet_type == LAST_PACKET) {
+		if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
+				& MODE_JPEG) {
+			gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+				sd->jpeg_hdr, JPEG_HDR_SZ);
+			gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+				data, len);
+		} else {
+			gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+				data, len);
+		}
+	} else {
+		gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+	}
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+	.name = MODULE_NAME,
+	.ctrls = sd_ctrls,
+	.nctrls = ARRAY_SIZE(sd_ctrls),
+	.config = sd_config,
+	.init = sd_init,
+	.start = sd_start,
+	.stopN = sd_stopN,
+	.stop0 = sd_stop0,
+	.pkt_scan = sd_pkt_scan,
+	.dq_callback = do_autoexposure,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.set_register = sd_dbg_s_register,
+	.get_register = sd_dbg_g_register,
+#endif
+	.get_chip_ident = sd_chip_ident,
+};
+
+#define SN9C20X(sensor, i2c_addr, button_mask) \
+	.driver_info =  (button_mask << 16) \
+			| (SENSOR_ ## sensor << 8) \
+			| (i2c_addr)
+
+static const __devinitdata struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
+	{USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
+	{USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, 0x10)},
+	{USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
+	{USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
+	{USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)},
+	{USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
+	{USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
+	{USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
+	{USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
+	{USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
+	{USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
+	{USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)},
+	{USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
+	{USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
+	{USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
+	{USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
+	{USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
+	{USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
+	{USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
+	{USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
+	{USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
+	{USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
+	{USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
+	{}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+		    const struct usb_device_id *id)
+{
+	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+				THIS_MODULE);
+}
+
+static void sd_disconnect(struct usb_interface *intf)
+{
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+	struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+	sn9c20x_input_cleanup(gspca_dev);
+#endif
+
+	gspca_disconnect(intf);
+}
+
+static struct usb_driver sd_driver = {
+	.name = MODULE_NAME,
+	.id_table = device_table,
+	.probe = sd_probe,
+	.disconnect = sd_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume = gspca_resume,
+	.reset_resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
+	info("registered");
+	return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+	info("deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/sonixb.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/sonixb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/sonixb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/sonixb.c	2009-09-09 18:13:59.000000000 -0400
@@ -877,6 +877,8 @@
 		cam->cam_mode = sif_mode;
 		cam->nmodes = ARRAY_SIZE(sif_mode);
 	}
+	cam->npkt = 36;			/* 36 packets per ISOC message */
+
 	sd->brightness = BRIGHTNESS_DEF;
 	sd->gain = GAIN_DEF;
 	sd->exposure = EXPOSURE_DEF;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/sonixj.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/sonixj.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/sonixj.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/sonixj.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,7 @@
 	u8 gamma;
 	u8 vflip;			/* ov7630/ov7648 only */
 	u8 infrared;			/* mt9v111 only */
+	u8 freq;			/* ov76xx only */
 	u8 quality;			/* image quality */
 #define QUALITY_MIN 60
 #define QUALITY_MAX 95
@@ -62,7 +63,6 @@
 #define BRIDGE_SN9C105 1
 #define BRIDGE_SN9C110 2
 #define BRIDGE_SN9C120 3
-#define BRIDGE_SN9C325 4
 	u8 sensor;			/* Type of image sensor chip */
 #define SENSOR_HV7131R 0
 #define SENSOR_MI0360 1
@@ -97,8 +97,11 @@
 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
+#define BRIGHTNESS_IDX 0
 	{
 	    {
 		.id      = V4L2_CID_BRIGHTNESS,
@@ -114,6 +117,7 @@
 	    .set = sd_setbrightness,
 	    .get = sd_getbrightness,
 	},
+#define CONTRAST_IDX 1
 	{
 	    {
 		.id      = V4L2_CID_CONTRAST,
@@ -129,20 +133,22 @@
 	    .set = sd_setcontrast,
 	    .get = sd_getcontrast,
 	},
+#define COLOR_IDX 2
 	{
 	    {
 		.id      = V4L2_CID_SATURATION,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
-		.name    = "Color",
+		.name    = "Saturation",
 		.minimum = 0,
 		.maximum = 40,
 		.step    = 1,
-#define COLOR_DEF 32
+#define COLOR_DEF 25
 		.default_value = COLOR_DEF,
 	    },
 	    .set = sd_setcolors,
 	    .get = sd_getcolors,
 	},
+#define BLUE_BALANCE_IDX 3
 	{
 	    {
 		.id      = V4L2_CID_BLUE_BALANCE,
@@ -157,6 +163,7 @@
 	    .set = sd_setblue_balance,
 	    .get = sd_getblue_balance,
 	},
+#define RED_BALANCE_IDX 4
 	{
 	    {
 		.id      = V4L2_CID_RED_BALANCE,
@@ -171,6 +178,7 @@
 	    .set = sd_setred_balance,
 	    .get = sd_getred_balance,
 	},
+#define GAMMA_IDX 5
 	{
 	    {
 		.id      = V4L2_CID_GAMMA,
@@ -185,7 +193,7 @@
 	    .set = sd_setgamma,
 	    .get = sd_getgamma,
 	},
-#define AUTOGAIN_IDX 5
+#define AUTOGAIN_IDX 6
 	{
 	    {
 		.id      = V4L2_CID_AUTOGAIN,
@@ -201,7 +209,7 @@
 	    .get = sd_getautogain,
 	},
 /* ov7630/ov7648 only */
-#define VFLIP_IDX 6
+#define VFLIP_IDX 7
 	{
 	    {
 		.id      = V4L2_CID_VFLIP,
@@ -210,14 +218,14 @@
 		.minimum = 0,
 		.maximum = 1,
 		.step    = 1,
-#define VFLIP_DEF 0			/* vflip def = 1 for ov7630 */
+#define VFLIP_DEF 0
 		.default_value = VFLIP_DEF,
 	    },
 	    .set = sd_setvflip,
 	    .get = sd_getvflip,
 	},
 /* mt9v111 only */
-#define INFRARED_IDX 7
+#define INFRARED_IDX 8
 	{
 	    {
 		.id      = V4L2_CID_INFRARED,
@@ -232,28 +240,44 @@
 	    .set = sd_setinfrared,
 	    .get = sd_getinfrared,
 	},
+/* ov7630/ov7648/ov7660 only */
+#define FREQ_IDX 9
+	{
+	    {
+		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
+		.type    = V4L2_CTRL_TYPE_MENU,
+		.name    = "Light frequency filter",
+		.minimum = 0,
+		.maximum = 2,	/* 0: 0, 1: 50Hz, 2:60Hz */
+		.step    = 1,
+#define FREQ_DEF 2
+		.default_value = FREQ_DEF,
+	    },
+	    .set = sd_setfreq,
+	    .get = sd_getfreq,
+	},
 };
 
 /* table of the disabled controls */
 static __u32 ctrl_dis[] = {
-	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+	(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
 						/* SENSOR_HV7131R 0 */
-	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+	(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
 						/* SENSOR_MI0360 1 */
-	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+	(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
 						/* SENSOR_MO4000 2 */
-	(1 << VFLIP_IDX),
+	(1 << VFLIP_IDX) | (1 << FREQ_IDX),
 						/* SENSOR_MT9V111 3 */
-	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+	(1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
 						/* SENSOR_OM6802 4 */
-	(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
+	(1 << INFRARED_IDX),
 						/* SENSOR_OV7630 5 */
 	(1 << INFRARED_IDX),
 						/* SENSOR_OV7648 6 */
 	(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
 						/* SENSOR_OV7660 7 */
-	(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
-						/* SENSOR_SP80708 8 */
+	(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) |
+			      (1 << FREQ_IDX),	/* SENSOR_SP80708 8 */
 };
 
 static const struct v4l2_pix_format vga_mode[] = {
@@ -269,7 +293,8 @@
 		.priv = 1},
 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 640,
-		.sizeimage = 640 * 480 * 3 / 8 + 590,
+		/* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
+		.sizeimage = 640 * 480 * 3 / 4 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = 0},
 };
@@ -354,9 +379,9 @@
 
 static const u8 sn_ov7660[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
-	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
+	0x00,	0x61,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
-	0x81,	0x21,	0x07,	0x00,	0x00,	0x00,	0x00,	0x10,
+	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	0x00,	0x01,	0x01,	0x08,	0x28,	0x1e,	0x20,
 /*	reg18	reg19	reg1a	reg1b */
@@ -605,7 +630,9 @@
 /* win: i2c_r from 00 to 80 */
 	{0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
 	{0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
-	{0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
+/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
+	0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
+	{0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
 	{0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
 	{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
 	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
@@ -639,9 +666,8 @@
 	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
 /* */
-	{0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
-	{0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
+/*	{0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
+/*	{0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
 /* */
 	{0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
 /*	{0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
@@ -674,7 +700,7 @@
 	{0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
 /*	{0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
 /*	{0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
-	{0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
+/*	{0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
 /*...*/
 /*	{0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
 /*	{0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10},   * COMN
@@ -757,6 +783,7 @@
 	{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
 	{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
 	{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
+	{0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
 /****** (some exchanges in the win trace) ******/
 	{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
 						/* bits[3..0]reserved */
@@ -1065,9 +1092,9 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	const u8 *reg9a;
 	static const u8 reg9a_def[] =
-		{0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
-	static const u8 reg9a_sn9c325[] =
-		{0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
+		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
+	static const u8 reg9a_spec[] =
+		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
 	static const u8 regd4[] = {0x60, 0x00, 0x00};
 
 	reg_w1(gspca_dev, 0xf1, 0x00);
@@ -1077,9 +1104,10 @@
 	reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
 	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
 	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);	/* jfm len was 3 */
-	switch (sd->bridge) {
-	case BRIDGE_SN9C325:
-		reg9a = reg9a_sn9c325;
+	switch (sd->sensor) {
+	case SENSOR_OV7660:
+	case SENSOR_SP80708:
+		reg9a = reg9a_spec;
 		break;
 	default:
 		reg9a = reg9a_def;
@@ -1104,7 +1132,6 @@
 		reg_w1(gspca_dev, 0x17, 0x64);
 		reg_w1(gspca_dev, 0x01, 0x42);
 		break;
-/*jfm: from win trace */
 	case SENSOR_OV7630:
 		reg_w1(gspca_dev, 0x01, 0x61);
 		reg_w1(gspca_dev, 0x17, 0xe2);
@@ -1114,18 +1141,15 @@
 	case SENSOR_OV7648:
 		reg_w1(gspca_dev, 0x01, 0x63);
 		reg_w1(gspca_dev, 0x17, 0x20);
+		reg_w1(gspca_dev, 0x01, 0x62);
 		reg_w1(gspca_dev, 0x01, 0x42);
 		break;
-/*jfm: from win trace */
 	case SENSOR_OV7660:
-		if (sd->bridge == BRIDGE_SN9C120) {
-			reg_w1(gspca_dev, 0x01, 0x61);
-			reg_w1(gspca_dev, 0x17, 0x20);
-			reg_w1(gspca_dev, 0x01, 0x60);
-			reg_w1(gspca_dev, 0x01, 0x40);
-			break;
-		}
-		/* fall thru */
+		reg_w1(gspca_dev, 0x01, 0x61);
+		reg_w1(gspca_dev, 0x17, 0x20);
+		reg_w1(gspca_dev, 0x01, 0x60);
+		reg_w1(gspca_dev, 0x01, 0x40);
+		break;
 	case SENSOR_SP80708:
 		reg_w1(gspca_dev, 0x01, 0x63);
 		reg_w1(gspca_dev, 0x17, 0x20);
@@ -1134,6 +1158,9 @@
 		mdelay(100);
 		reg_w1(gspca_dev, 0x02, 0x62);
 		break;
+/*	case SENSOR_HV7131R: */
+/*	case SENSOR_MI0360: */
+/*	case SENSOR_MO4000: */
 	default:
 		reg_w1(gspca_dev, 0x01, 0x43);
 		reg_w1(gspca_dev, 0x17, 0x61);
@@ -1280,6 +1307,7 @@
 	cam = &gspca_dev->cam;
 	cam->cam_mode = vga_mode;
 	cam->nmodes = ARRAY_SIZE(vga_mode);
+	cam->npkt = 24;			/* 24 packets per ISOC message */
 
 	sd->bridge = id->driver_info >> 16;
 	sd->sensor = id->driver_info >> 8;
@@ -1293,11 +1321,9 @@
 	sd->gamma = GAMMA_DEF;
 	sd->autogain = AUTOGAIN_DEF;
 	sd->ag_cnt = -1;
-	if (sd->sensor != SENSOR_OV7630)
-		sd->vflip = 0;
-	else
-		sd->vflip = 1;
+	sd->vflip = VFLIP_DEF;
 	sd->infrared = INFRARED_DEF;
+	sd->freq = FREQ_DEF;
 	sd->quality = QUALITY_DEF;
 	sd->jpegqual = 80;
 
@@ -1568,7 +1594,7 @@
 		else
 			comb = 0xa0;
 		if (sd->autogain)
-			comb |= 0x02;
+			comb |= 0x03;
 		i2c_w1(&sd->gspca_dev, 0x13, comb);
 		return;
 	    }
@@ -1584,12 +1610,15 @@
 {
 	u8 comn;
 
-	if (sd->sensor == SENSOR_OV7630)
+	if (sd->sensor == SENSOR_OV7630) {
 		comn = 0x02;
-	else
+		if (!sd->vflip)
+			comn |= 0x80;
+	} else {
 		comn = 0x06;
-	if (sd->vflip)
-		comn |= 0x80;
+		if (sd->vflip)
+			comn |= 0x80;
+	}
 	i2c_w1(&sd->gspca_dev, 0x75, comn);
 }
 
@@ -1601,6 +1630,60 @@
 		sd->infrared ? 0x66 : 0x64);
 }
 
+static void setfreq(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (gspca_dev->ctrl_dis & (1 << FREQ_IDX))
+		return;
+	if (sd->sensor == SENSOR_OV7660) {
+		switch (sd->freq) {
+		case 0: /* Banding filter disabled */
+			i2c_w1(gspca_dev, 0x13, 0xdf);
+			break;
+		case 1: /* 50 hz */
+			i2c_w1(gspca_dev, 0x13, 0xff);
+			i2c_w1(gspca_dev, 0x3b, 0x0a);
+			break;
+		case 2: /* 60 hz */
+			i2c_w1(gspca_dev, 0x13, 0xff);
+			i2c_w1(gspca_dev, 0x3b, 0x02);
+			break;
+		}
+	} else {
+		u8 reg2a = 0, reg2b = 0, reg2d = 0;
+
+		/* Get reg2a / reg2d base values */
+		switch (sd->sensor) {
+		case SENSOR_OV7630:
+			reg2a = 0x08;
+			reg2d = 0x01;
+			break;
+		case SENSOR_OV7648:
+			reg2a = 0x11;
+			reg2d = 0x81;
+			break;
+		}
+
+		switch (sd->freq) {
+		case 0: /* Banding filter disabled */
+			break;
+		case 1: /* 50 hz (filter on and framerate adj) */
+			reg2a |= 0x80;
+			reg2b = 0xac;
+			reg2d |= 0x04;
+			break;
+		case 2: /* 60 hz (filter on, no framerate adj) */
+			reg2a |= 0x80;
+			reg2d |= 0x04;
+			break;
+		}
+		i2c_w1(gspca_dev, 0x2a, reg2a);
+		i2c_w1(gspca_dev, 0x2b, reg2b);
+		i2c_w1(gspca_dev, 0x2d, reg2d);
+	}
+}
+
 static void setjpegqual(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1654,6 +1737,8 @@
 
 	/* create the JPEG header */
 	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (!sd->jpeg_hdr)
+		return -ENOMEM;
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x21);		/* JPEG 422 */
 	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
@@ -1683,13 +1768,9 @@
 	case SENSOR_OV7648:
 		reg17 = 0x20;
 		break;
-/*jfm: from win trace */
 	case SENSOR_OV7660:
-		if (sd->bridge == BRIDGE_SN9C120) {
-			reg17 = 0xa0;
-			break;
-		}
-		/* fall thru */
+		reg17 = 0xa0;
+		break;
 	default:
 		reg17 = 0x60;
 		break;
@@ -1714,16 +1795,17 @@
 		reg_w1(gspca_dev, 0x9a, 0x0a);
 		reg_w1(gspca_dev, 0x99, 0x60);
 		break;
+	case SENSOR_OV7660:
+		reg_w1(gspca_dev, 0x9a, 0x05);
+		if (sd->bridge == BRIDGE_SN9C105)
+			reg_w1(gspca_dev, 0x99, 0xff);
+		else
+			reg_w1(gspca_dev, 0x99, 0x5b);
+		break;
 	case SENSOR_SP80708:
 		reg_w1(gspca_dev, 0x9a, 0x05);
 		reg_w1(gspca_dev, 0x99, 0x59);
 		break;
-	case SENSOR_OV7660:
-		if (sd->bridge == BRIDGE_SN9C120) {
-			reg_w1(gspca_dev, 0x9a, 0x05);
-			break;
-		}
-		/* fall thru */
 	default:
 		reg_w1(gspca_dev, 0x9a, 0x08);
 		reg_w1(gspca_dev, 0x99, 0x59);
@@ -1830,6 +1912,7 @@
 	setbrightness(gspca_dev);
 	setcontrast(gspca_dev);
 	setautogain(gspca_dev);
+	setfreq(gspca_dev);
 	return 0;
 }
 
@@ -2133,6 +2216,24 @@
 	return 0;
 }
 
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->freq = val;
+	if (gspca_dev->streaming)
+		setfreq(gspca_dev);
+	return 0;
+}
+
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->freq;
+	return 0;
+}
+
 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
 			struct v4l2_jpegcompression *jcomp)
 {
@@ -2161,6 +2262,27 @@
 	return 0;
 }
 
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+			struct v4l2_querymenu *menu)
+{
+	switch (menu->id) {
+	case V4L2_CID_POWER_LINE_FREQUENCY:
+		switch (menu->index) {
+		case 0:		/* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
+			strcpy((char *) menu->name, "NoFliker");
+			return 0;
+		case 1:		/* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
+			strcpy((char *) menu->name, "50 Hz");
+			return 0;
+		case 2:		/* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
+			strcpy((char *) menu->name, "60 Hz");
+			return 0;
+		}
+		break;
+	}
+	return -EINVAL;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -2175,6 +2297,7 @@
 	.dq_callback = do_autogain,
 	.get_jcomp = sd_get_jcomp,
 	.set_jcomp = sd_set_jcomp,
+	.querymenu = sd_querymenu,
 };
 
 /* -- module initialisation -- */
@@ -2193,6 +2316,7 @@
 	{USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
 	{USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
 	{USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
+	{USB_DEVICE(0x06f8, 0x3008), BSI(SN9C105, OV7660, 0x21)},
 	{USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
 /* bw600.inf:
 	{USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
@@ -2211,7 +2335,12 @@
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
 #endif
+	{USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/
 /*	{USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
+	{USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/
+	{USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/
+	{USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/
+	{USB_DEVICE(0x0c45, 0x610e), BSI(SN9C120, OV7630, 0x21)}, /*sn9c128*/
 /*	{USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
 /*	{USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
 	{USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
@@ -2229,7 +2358,7 @@
 	{USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
 #endif
 	{USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
-/*	{USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
+	{USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)},
 	{USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)},
 	{}
 };
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca500.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca500.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca500.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca500.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,9 +32,6 @@
 struct sd {
 	struct gspca_dev gspca_dev;		/* !! must be the first item */
 
-	__u8 packet[ISO_MAX_SIZE + 128];
-				 /* !! no more than 128 ff in an ISO packet */
-
 	unsigned char brightness;
 	unsigned char contrast;
 	unsigned char colors;
@@ -673,6 +670,8 @@
 
 	/* create the JPEG header */
 	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (!sd->jpeg_hdr)
+		return -ENOMEM;
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x22);		/* JPEG 411 */
 	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
@@ -906,7 +905,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i;
-	__u8 *s, *d;
 	static __u8 ffd9[] = {0xff, 0xd9};
 
 /* frames are jpeg 4.1.1 without 0xff escape */
@@ -930,22 +928,19 @@
 	}
 
 	/* add 0x00 after 0xff */
-	for (i = len; --i >= 0; )
-		if (data[i] == 0xff)
-			break;
-	if (i < 0) {			/* no 0xff */
-		gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
-		return;
-	}
-	s = data;
-	d = sd->packet;
-	for (i = 0; i < len; i++) {
-		*d++ = *s++;
-		if (s[-1] == 0xff)
-			*d++ = 0x00;
-	}
-	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-			sd->packet, d - sd->packet);
+	i = 0;
+	do {
+		if (data[i] == 0xff) {
+			gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+					data, i + 1);
+			len -= i;
+			data += i;
+			*data = 0x00;
+			i = 0;
+		}
+		i++;
+	} while (i < len);
+	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca505.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca505.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca505.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca505.c	2009-09-09 18:13:59.000000000 -0400
@@ -637,19 +637,19 @@
 		cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
 	sd->brightness = BRIGHTNESS_DEF;
 
-	if (sd->subtype == Nxultra) {
-		if (write_vector(gspca_dev, spca505b_init_data))
-			return -EIO;
-	} else {
-		if (write_vector(gspca_dev, spca505_init_data))
-			return -EIO;
-	}
 	return 0;
 }
 
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (write_vector(gspca_dev,
+			 sd->subtype == Nxultra
+				? spca505b_init_data
+				: spca505_init_data))
+		return -EIO;
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca508.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca508.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca508.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca508.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * SPCA508 chip based cameras subdriver
  *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr>
  *
  * 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
@@ -30,9 +30,9 @@
 struct sd {
 	struct gspca_dev gspca_dev;		/* !! must be the first item */
 
-	unsigned char brightness;
+	u8 brightness;
 
-	char subtype;
+	u8 subtype;
 #define CreativeVista 0
 #define HamaUSBSightcam 1
 #define HamaUSBSightcam2 2
@@ -86,58 +86,34 @@
 };
 
 /* Frame packet header offsets for the spca508 */
-#define SPCA508_OFFSET_TYPE 1
-#define SPCA508_OFFSET_COMPRESS 2
-#define SPCA508_OFFSET_FRAMSEQ 8
-#define SPCA508_OFFSET_WIN1LUM 11
 #define SPCA508_OFFSET_DATA 37
 
-#define SPCA508_SNAPBIT 0x20
-#define SPCA508_SNAPCTRL 0x40
-/*************** I2c ****************/
-#define SPCA508_INDEX_I2C_BASE 0x8800
-
 /*
  * Initialization data: this is the first set-up data written to the
  * device (before the open data).
  */
 static const u16 spca508_init_data[][2] =
 {
-	/*  line   URB      value, index */
-	/* 44274  1804 */ {0x0000, 0x870b},
+	{0x0000, 0x870b},
 
-	/* 44299  1805 */ {0x0020, 0x8112},
-	/* Video drop enable, ISO streaming disable */
-	/* 44324  1806 */ {0x0003, 0x8111},
-	/* Reset compression & memory */
-	/* 44349  1807 */ {0x0000, 0x8110},
-	/* Disable all outputs */
-	/* 44372  1808 */ /* READ {0x0000, 0x8114} -> 0000: 00  */
-	/* 44398  1809 */ {0x0000, 0x8114},
-	/* SW GPIO data */
-	/* 44423  1810 */ {0x0008, 0x8110},
-	/* Enable charge pump output */
-	/* 44527  1811 */ {0x0002, 0x8116},
-	/* 200 kHz pump clock */
-	/* 44555  1812 */
-		/* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
-	/* 44590  1813 */ {0x0003, 0x8111},
-	/* Reset compression & memory */
-	/* 44615  1814 */ {0x0000, 0x8111},
-	/* Normal mode (not reset) */
-	/* 44640  1815 */ {0x0098, 0x8110},
-	/* Enable charge pump output, sync.serial,external 2x clock */
-	/* 44665  1816 */ {0x000d, 0x8114},
-	/* SW GPIO data */
-	/* 44690  1817 */ {0x0002, 0x8116},
-	/* 200 kHz pump clock */
-	/* 44715  1818 */ {0x0020, 0x8112},
-	/* Video drop enable, ISO streaming disable */
+	{0x0020, 0x8112},	/* Video drop enable, ISO streaming disable */
+	{0x0003, 0x8111},	/* Reset compression & memory */
+	{0x0000, 0x8110},	/* Disable all outputs */
+	/* READ {0x0000, 0x8114} -> 0000: 00  */
+	{0x0000, 0x8114},	/* SW GPIO data */
+	{0x0008, 0x8110},	/* Enable charge pump output */
+	{0x0002, 0x8116},	/* 200 kHz pump clock */
+	/* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
+	{0x0003, 0x8111},	/* Reset compression & memory */
+	{0x0000, 0x8111},	/* Normal mode (not reset) */
+	{0x0098, 0x8110},
+		/* Enable charge pump output, sync.serial,external 2x clock */
+	{0x000d, 0x8114},	/* SW GPIO data */
+	{0x0002, 0x8116},	/* 200 kHz pump clock */
+	{0x0020, 0x8112},	/* Video drop enable, ISO streaming disable */
 /* --------------------------------------- */
-	/* 44740  1819 */ {0x000f, 0x8402},
-	/* memory bank */
-	/* 44765  1820 */ {0x0000, 0x8403},
-	/* ... address */
+	{0x000f, 0x8402},	/* memory bank */
+	{0x0000, 0x8403},	/* ... address */
 /* --------------------------------------- */
 /* 0x88__ is Synchronous Serial Interface. */
 /* TBD: This table could be expressed more compactly */
@@ -145,446 +121,384 @@
 /* TBD: Should see if the values in spca50x_i2c_data */
 /* would work with the VQ110 instead of the values */
 /* below. */
-	/* 44790  1821 */ {0x00c0, 0x8804},
-	/* SSI slave addr */
-	/* 44815  1822 */ {0x0008, 0x8802},
-	/* 375 Khz SSI clock */
-	/* 44838  1823 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 44862  1824 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 44888  1825 */ {0x0008, 0x8802},
-	/* 375 Khz SSI clock */
-	/* 44913  1826 */ {0x0012, 0x8801},
-	/* SSI reg addr */
-	/* 44938  1827 */ {0x0080, 0x8800},
-	/* SSI data to write */
-	/* 44961  1828 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 44985  1829 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45009  1830 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 45035  1831 */ {0x0008, 0x8802},
-	/* 375 Khz SSI clock */
-	/* 45060  1832 */ {0x0012, 0x8801},
-	/* SSI reg addr */
-	/* 45085  1833 */ {0x0000, 0x8800},
-	/* SSI data to write */
-	/* 45108  1834 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45132  1835 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45156  1836 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 45182  1837 */ {0x0008, 0x8802},
-	/* 375 Khz SSI clock */
-	/* 45207  1838 */ {0x0011, 0x8801},
-	/* SSI reg addr */
-	/* 45232  1839 */ {0x0040, 0x8800},
-	/* SSI data to write */
-	/* 45255  1840 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45279  1841 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45303  1842 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 45329  1843 */ {0x0008, 0x8802},
-	/* 45354  1844 */ {0x0013, 0x8801},
-	/* 45379  1845 */ {0x0000, 0x8800},
-	/* 45402  1846 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45426  1847 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45450  1848 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 45476  1849 */ {0x0008, 0x8802},
-	/* 45501  1850 */ {0x0014, 0x8801},
-	/* 45526  1851 */ {0x0000, 0x8800},
-	/* 45549  1852 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45573  1853 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45597  1854 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 45623  1855 */ {0x0008, 0x8802},
-	/* 45648  1856 */ {0x0015, 0x8801},
-	/* 45673  1857 */ {0x0001, 0x8800},
-	/* 45696  1858 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45720  1859 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45744  1860 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 45770  1861 */ {0x0008, 0x8802},
-	/* 45795  1862 */ {0x0016, 0x8801},
-	/* 45820  1863 */ {0x0003, 0x8800},
-	/* 45843  1864 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45867  1865 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 45891  1866 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 45917  1867 */ {0x0008, 0x8802},
-	/* 45942  1868 */ {0x0017, 0x8801},
-	/* 45967  1869 */ {0x0036, 0x8800},
-	/* 45990  1870 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46014  1871 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46038  1872 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 46064  1873 */ {0x0008, 0x8802},
-	/* 46089  1874 */ {0x0018, 0x8801},
-	/* 46114  1875 */ {0x00ec, 0x8800},
-	/* 46137  1876 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46161  1877 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46185  1878 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 46211  1879 */ {0x0008, 0x8802},
-	/* 46236  1880 */ {0x001a, 0x8801},
-	/* 46261  1881 */ {0x0094, 0x8800},
-	/* 46284  1882 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46308  1883 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46332  1884 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 46358  1885 */ {0x0008, 0x8802},
-	/* 46383  1886 */ {0x001b, 0x8801},
-	/* 46408  1887 */ {0x0000, 0x8800},
-	/* 46431  1888 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46455  1889 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46479  1890 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 46505  1891 */ {0x0008, 0x8802},
-	/* 46530  1892 */ {0x0027, 0x8801},
-	/* 46555  1893 */ {0x00a2, 0x8800},
-	/* 46578  1894 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46602  1895 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46626  1896 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 46652  1897 */ {0x0008, 0x8802},
-	/* 46677  1898 */ {0x0028, 0x8801},
-	/* 46702  1899 */ {0x0040, 0x8800},
-	/* 46725  1900 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46749  1901 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46773  1902 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 46799  1903 */ {0x0008, 0x8802},
-	/* 46824  1904 */ {0x002a, 0x8801},
-	/* 46849  1905 */ {0x0084, 0x8800},
-	/* 46872  1906 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 46896  1907 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
-	/* 46920  1908 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 46946  1909 */ {0x0008, 0x8802},
-	/* 46971  1910 */ {0x002b, 0x8801},
-	/* 46996  1911 */ {0x00a8, 0x8800},
-	/* 47019  1912 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47043  1913 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47067  1914 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 47093  1915 */ {0x0008, 0x8802},
-	/* 47118  1916 */ {0x002c, 0x8801},
-	/* 47143  1917 */ {0x00fe, 0x8800},
-	/* 47166  1918 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47190  1919 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47214  1920 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 47240  1921 */ {0x0008, 0x8802},
-	/* 47265  1922 */ {0x002d, 0x8801},
-	/* 47290  1923 */ {0x0003, 0x8800},
-	/* 47313  1924 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47337  1925 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47361  1926 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 47387  1927 */ {0x0008, 0x8802},
-	/* 47412  1928 */ {0x0038, 0x8801},
-	/* 47437  1929 */ {0x0083, 0x8800},
-	/* 47460  1930 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47484  1931 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47508  1932 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 47534  1933 */ {0x0008, 0x8802},
-	/* 47559  1934 */ {0x0033, 0x8801},
-	/* 47584  1935 */ {0x0081, 0x8800},
-	/* 47607  1936 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47631  1937 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47655  1938 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 47681  1939 */ {0x0008, 0x8802},
-	/* 47706  1940 */ {0x0034, 0x8801},
-	/* 47731  1941 */ {0x004a, 0x8800},
-	/* 47754  1942 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47778  1943 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47802  1944 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 47828  1945 */ {0x0008, 0x8802},
-	/* 47853  1946 */ {0x0039, 0x8801},
-	/* 47878  1947 */ {0x0000, 0x8800},
-	/* 47901  1948 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47925  1949 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 47949  1950 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 47975  1951 */ {0x0008, 0x8802},
-	/* 48000  1952 */ {0x0010, 0x8801},
-	/* 48025  1953 */ {0x00a8, 0x8800},
-	/* 48048  1954 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48072  1955 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48096  1956 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 48122  1957 */ {0x0008, 0x8802},
-	/* 48147  1958 */ {0x0006, 0x8801},
-	/* 48172  1959 */ {0x0058, 0x8800},
-	/* 48195  1960 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48219  1961 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
-	/* 48243  1962 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 48269  1963 */ {0x0008, 0x8802},
-	/* 48294  1964 */ {0x0000, 0x8801},
-	/* 48319  1965 */ {0x0004, 0x8800},
-	/* 48342  1966 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48366  1967 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48390  1968 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 48416  1969 */ {0x0008, 0x8802},
-	/* 48441  1970 */ {0x0040, 0x8801},
-	/* 48466  1971 */ {0x0080, 0x8800},
-	/* 48489  1972 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48513  1973 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48537  1974 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 48563  1975 */ {0x0008, 0x8802},
-	/* 48588  1976 */ {0x0041, 0x8801},
-	/* 48613  1977 */ {0x000c, 0x8800},
-	/* 48636  1978 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48660  1979 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48684  1980 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 48710  1981 */ {0x0008, 0x8802},
-	/* 48735  1982 */ {0x0042, 0x8801},
-	/* 48760  1983 */ {0x000c, 0x8800},
-	/* 48783  1984 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48807  1985 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48831  1986 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 48857  1987 */ {0x0008, 0x8802},
-	/* 48882  1988 */ {0x0043, 0x8801},
-	/* 48907  1989 */ {0x0028, 0x8800},
-	/* 48930  1990 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48954  1991 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 48978  1992 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 49004  1993 */ {0x0008, 0x8802},
-	/* 49029  1994 */ {0x0044, 0x8801},
-	/* 49054  1995 */ {0x0080, 0x8800},
-	/* 49077  1996 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49101  1997 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49125  1998 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 49151  1999 */ {0x0008, 0x8802},
-	/* 49176  2000 */ {0x0045, 0x8801},
-	/* 49201  2001 */ {0x0020, 0x8800},
-	/* 49224  2002 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49248  2003 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49272  2004 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 49298  2005 */ {0x0008, 0x8802},
-	/* 49323  2006 */ {0x0046, 0x8801},
-	/* 49348  2007 */ {0x0020, 0x8800},
-	/* 49371  2008 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49395  2009 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49419  2010 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 49445  2011 */ {0x0008, 0x8802},
-	/* 49470  2012 */ {0x0047, 0x8801},
-	/* 49495  2013 */ {0x0080, 0x8800},
-	/* 49518  2014 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49542  2015 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49566  2016 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 49592  2017 */ {0x0008, 0x8802},
-	/* 49617  2018 */ {0x0048, 0x8801},
-	/* 49642  2019 */ {0x004c, 0x8800},
-	/* 49665  2020 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49689  2021 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49713  2022 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 49739  2023 */ {0x0008, 0x8802},
-	/* 49764  2024 */ {0x0049, 0x8801},
-	/* 49789  2025 */ {0x0084, 0x8800},
-	/* 49812  2026 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49836  2027 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49860  2028 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 49886  2029 */ {0x0008, 0x8802},
-	/* 49911  2030 */ {0x004a, 0x8801},
-	/* 49936  2031 */ {0x0084, 0x8800},
-	/* 49959  2032 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 49983  2033 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 50007  2034 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 50033  2035 */ {0x0008, 0x8802},
-	/* 50058  2036 */ {0x004b, 0x8801},
-	/* 50083  2037 */ {0x0084, 0x8800},
-	/* 50106  2038 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
+	{0x00c0, 0x8804},	/* SSI slave addr */
+	{0x0008, 0x8802},	/* 375 Khz SSI clock */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},	/* 375 Khz SSI clock */
+	{0x0012, 0x8801},	/* SSI reg addr */
+	{0x0080, 0x8800},	/* SSI data to write */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},	/* 375 Khz SSI clock */
+	{0x0012, 0x8801},	/* SSI reg addr */
+	{0x0000, 0x8800},	/* SSI data to write */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},	/* 375 Khz SSI clock */
+	{0x0011, 0x8801},	/* SSI reg addr */
+	{0x0040, 0x8800},	/* SSI data to write */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0013, 0x8801},
+	{0x0000, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0014, 0x8801},
+	{0x0000, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0015, 0x8801},
+	{0x0001, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0016, 0x8801},
+	{0x0003, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0017, 0x8801},
+	{0x0036, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0018, 0x8801},
+	{0x00ec, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x001a, 0x8801},
+	{0x0094, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x001b, 0x8801},
+	{0x0000, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0027, 0x8801},
+	{0x00a2, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0028, 0x8801},
+	{0x0040, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x002a, 0x8801},
+	{0x0084, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00 */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x002b, 0x8801},
+	{0x00a8, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x002c, 0x8801},
+	{0x00fe, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x002d, 0x8801},
+	{0x0003, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0038, 0x8801},
+	{0x0083, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0033, 0x8801},
+	{0x0081, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0034, 0x8801},
+	{0x004a, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0039, 0x8801},
+	{0x0000, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0010, 0x8801},
+	{0x00a8, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0006, 0x8801},
+	{0x0058, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00 */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0000, 0x8801},
+	{0x0004, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0040, 0x8801},
+	{0x0080, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0041, 0x8801},
+	{0x000c, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0042, 0x8801},
+	{0x000c, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0043, 0x8801},
+	{0x0028, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0044, 0x8801},
+	{0x0080, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0045, 0x8801},
+	{0x0020, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0046, 0x8801},
+	{0x0020, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0047, 0x8801},
+	{0x0080, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0048, 0x8801},
+	{0x004c, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x0049, 0x8801},
+	{0x0084, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x004a, 0x8801},
+	{0x0084, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x0008, 0x8802},
+	{0x004b, 0x8801},
+	{0x0084, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 	/* --------------------------------------- */
-	/* 50132  2039 */ {0x0012, 0x8700},
-	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
-	/* 50157  2040 */ {0x0000, 0x8701},
-	/* CKx1 clock delay adj */
-	/* 50182  2041 */ {0x0000, 0x8701},
-	/* CKx1 clock delay adj */
-	/* 50207  2042 */ {0x0001, 0x870c},
-	/* CKOx2 output */
+	{0x0012, 0x8700},	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
+	{0x0000, 0x8701},	/* CKx1 clock delay adj */
+	{0x0000, 0x8701},	/* CKx1 clock delay adj */
+	{0x0001, 0x870c},	/* CKOx2 output */
 	/* --------------------------------------- */
-	/* 50232  2043 */ {0x0080, 0x8600},
-	/* Line memory read counter (L) */
-	/* 50257  2044 */ {0x0001, 0x8606},
-	/* reserved */
-	/* 50282  2045 */ {0x0064, 0x8607},
-	/* Line memory read counter (H) 0x6480=25,728 */
-	/* 50307  2046 */ {0x002a, 0x8601},
-	/* CDSP sharp interpolation mode,
+	{0x0080, 0x8600},	/* Line memory read counter (L) */
+	{0x0001, 0x8606},	/* reserved */
+	{0x0064, 0x8607},	/* Line memory read counter (H) 0x6480=25,728 */
+	{0x002a, 0x8601},	/* CDSP sharp interpolation mode,
 	 *			line sel for color sep, edge enhance enab */
-	/* 50332  2047 */ {0x0000, 0x8602},
-	/* optical black level for user settng = 0 */
-	/* 50357  2048 */ {0x0080, 0x8600},
-	/* Line memory read counter (L) */
-	/* 50382  2049 */ {0x000a, 0x8603},
-	/* optical black level calc mode: auto; optical black offset = 10 */
-	/* 50407  2050 */ {0x00df, 0x865b},
-	/* Horiz offset for valid pixels (L)=0xdf */
-	/* 50432  2051 */ {0x0012, 0x865c},
-	/* Vert offset for valid lines (L)=0x12 */
+	{0x0000, 0x8602},	/* optical black level for user settng = 0 */
+	{0x0080, 0x8600},	/* Line memory read counter (L) */
+	{0x000a, 0x8603},	/* optical black level calc mode:
+				 * auto; optical black offset = 10 */
+	{0x00df, 0x865b},	/* Horiz offset for valid pixels (L)=0xdf */
+	{0x0012, 0x865c},	/* Vert offset for valid lines (L)=0x12 */
 
 /* The following two lines seem to be the "wrong" resolution. */
 /* But perhaps these indicate the actual size of the sensor */
 /* rather than the size of the current video mode. */
-	/* 50457  2052 */ {0x0058, 0x865d},
-	/* Horiz valid pixels (*4) (L) = 352 */
-	/* 50482  2053 */ {0x0048, 0x865e},
-	/* Vert valid lines (*4) (L) = 288 */
+	{0x0058, 0x865d},	/* Horiz valid pixels (*4) (L) = 352 */
+	{0x0048, 0x865e},	/* Vert valid lines (*4) (L) = 288 */
 
-	/* 50507  2054 */ {0x0015, 0x8608},
-	/* A11 Coef ... */
-	/* 50532  2055 */ {0x0030, 0x8609},
-	/* 50557  2056 */ {0x00fb, 0x860a},
-	/* 50582  2057 */ {0x003e, 0x860b},
-	/* 50607  2058 */ {0x00ce, 0x860c},
-	/* 50632  2059 */ {0x00f4, 0x860d},
-	/* 50657  2060 */ {0x00eb, 0x860e},
-	/* 50682  2061 */ {0x00dc, 0x860f},
-	/* 50707  2062 */ {0x0039, 0x8610},
-	/* 50732  2063 */ {0x0001, 0x8611},
-	/* R offset for white balance ... */
-	/* 50757  2064 */ {0x0000, 0x8612},
-	/* 50782  2065 */ {0x0001, 0x8613},
-	/* 50807  2066 */ {0x0000, 0x8614},
-	/* 50832  2067 */ {0x005b, 0x8651},
-	/* R gain for white balance ... */
-	/* 50857  2068 */ {0x0040, 0x8652},
-	/* 50882  2069 */ {0x0060, 0x8653},
-	/* 50907  2070 */ {0x0040, 0x8654},
-	/* 50932  2071 */ {0x0000, 0x8655},
-	/* 50957  2072 */ {0x0001, 0x863f},
-	/* Fixed gamma correction enable, USB control,
-	 *			 lum filter disable, lum noise clip disable */
-	/* 50982  2073 */ {0x00a1, 0x8656},
-	/* Window1 size 256x256, Windows2 size 64x64,
-	 *		 gamma look-up disable, new edge enhancement enable */
-	/* 51007  2074 */ {0x0018, 0x8657},
-	/* Edge gain high thresh */
-	/* 51032  2075 */ {0x0020, 0x8658},
-	/* Edge gain low thresh */
-	/* 51057  2076 */ {0x000a, 0x8659},
-	/* Edge bandwidth high threshold */
-	/* 51082  2077 */ {0x0005, 0x865a},
-	/* Edge bandwidth low threshold */
+	{0x0015, 0x8608},	/* A11 Coef ... */
+	{0x0030, 0x8609},
+	{0x00fb, 0x860a},
+	{0x003e, 0x860b},
+	{0x00ce, 0x860c},
+	{0x00f4, 0x860d},
+	{0x00eb, 0x860e},
+	{0x00dc, 0x860f},
+	{0x0039, 0x8610},
+	{0x0001, 0x8611},	/* R offset for white balance ... */
+	{0x0000, 0x8612},
+	{0x0001, 0x8613},
+	{0x0000, 0x8614},
+	{0x005b, 0x8651},	/* R gain for white balance ... */
+	{0x0040, 0x8652},
+	{0x0060, 0x8653},
+	{0x0040, 0x8654},
+	{0x0000, 0x8655},
+	{0x0001, 0x863f},	/* Fixed gamma correction enable, USB control,
+				 * lum filter disable, lum noise clip disable */
+	{0x00a1, 0x8656},	/* Window1 size 256x256, Windows2 size 64x64,
+				 * gamma look-up disable,
+				 * new edge enhancement enable */
+	{0x0018, 0x8657},	/* Edge gain high thresh */
+	{0x0020, 0x8658},	/* Edge gain low thresh */
+	{0x000a, 0x8659},	/* Edge bandwidth high threshold */
+	{0x0005, 0x865a},	/* Edge bandwidth low threshold */
 	/* -------------------------------- */
-	/* 51107  2078 */ {0x0030, 0x8112},
-	/* Video drop enable, ISO streaming enable */
-	/* 51130  2079 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 51154  2080 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 51180  2081 */ {0xa908, 0x8802},
-	/* 51205  2082 */ {0x0034, 0x8801},
-	/* SSI reg addr */
-	/* 51230  2083 */ {0x00ca, 0x8800},
+	{0x0030, 0x8112},	/* Video drop enable, ISO streaming enable */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0xa908, 0x8802},
+	{0x0034, 0x8801},	/* SSI reg addr */
+	{0x00ca, 0x8800},
 	/* SSI data to write */
-	/* 51253  2084 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 51277  2085 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 51301  2086 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 51327  2087 */ {0x1f08, 0x8802},
-	/* 51352  2088 */ {0x0006, 0x8801},
-	/* 51377  2089 */ {0x0080, 0x8800},
-	/* 51400  2090 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0x1f08, 0x8802},
+	{0x0006, 0x8801},
+	{0x0080, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
 /* ----- Read back coefs we wrote earlier. */
-	/* 51424  2091 */ /* READ { 0, 0x0000, 0x8608 } -> 0000: 15  */
-	/* 51448  2092 */ /* READ { 0, 0x0000, 0x8609 } -> 0000: 30  */
-	/* 51472  2093 */ /* READ { 0, 0x0000, 0x860a } -> 0000: fb  */
-	/* 51496  2094 */ /* READ { 0, 0x0000, 0x860b } -> 0000: 3e  */
-	/* 51520  2095 */ /* READ { 0, 0x0000, 0x860c } -> 0000: ce  */
-	/* 51544  2096 */ /* READ { 0, 0x0000, 0x860d } -> 0000: f4  */
-	/* 51568  2097 */ /* READ { 0, 0x0000, 0x860e } -> 0000: eb  */
-	/* 51592  2098 */ /* READ { 0, 0x0000, 0x860f } -> 0000: dc  */
-	/* 51616  2099 */ /* READ { 0, 0x0000, 0x8610 } -> 0000: 39  */
-	/* 51640  2100 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 51664  2101 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08  */
-	/* 51690  2102 */ {0xb008, 0x8802},
-	/* 51715  2103 */ {0x0006, 0x8801},
-	/* 51740  2104 */ {0x007d, 0x8800},
-	/* 51763  2105 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0000, 0x8608 } -> 0000: 15  */
+	/* READ { 0x0000, 0x8609 } -> 0000: 30  */
+	/* READ { 0x0000, 0x860a } -> 0000: fb  */
+	/* READ { 0x0000, 0x860b } -> 0000: 3e  */
+	/* READ { 0x0000, 0x860c } -> 0000: ce  */
+	/* READ { 0x0000, 0x860d } -> 0000: f4  */
+	/* READ { 0x0000, 0x860e } -> 0000: eb  */
+	/* READ { 0x0000, 0x860f } -> 0000: dc  */
+	/* READ { 0x0000, 0x8610 } -> 0000: 39  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 08  */
+	{0xb008, 0x8802},
+	{0x0006, 0x8801},
+	{0x007d, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
 
 	/* This chunk is seemingly redundant with */
 	/* earlier commands (A11 Coef...), but if I disable it, */
 	/* the image appears too dark.  Maybe there was some kind of */
 	/* reset since the earlier commands, so this is necessary again. */
-	/* 51789  2106 */ {0x0015, 0x8608},
-	/* 51814  2107 */ {0x0030, 0x8609},
-	/* 51839  2108 */ {0xfffb, 0x860a},
-	/* 51864  2109 */ {0x003e, 0x860b},
-	/* 51889  2110 */ {0xffce, 0x860c},
-	/* 51914  2111 */ {0xfff4, 0x860d},
-	/* 51939  2112 */ {0xffeb, 0x860e},
-	/* 51964  2113 */ {0xffdc, 0x860f},
-	/* 51989  2114 */ {0x0039, 0x8610},
-	/* 52014  2115 */ {0x0018, 0x8657},
+	{0x0015, 0x8608},
+	{0x0030, 0x8609},
+	{0xfffb, 0x860a},
+	{0x003e, 0x860b},
+	{0xffce, 0x860c},
+	{0xfff4, 0x860d},
+	{0xffeb, 0x860e},
+	{0xffdc, 0x860f},
+	{0x0039, 0x8610},
+	{0x0018, 0x8657},
 
-	/* 52039  2116 */ {0x0000, 0x8508},
-	/* Disable compression. */
+	{0x0000, 0x8508},	/* Disable compression. */
 	/* Previous line was:
-	 * 52039  2116 *  { 0, 0x0021, 0x8508 },  * Enable compression. */
-	/* 52064  2117 */ {0x0032, 0x850b},
-	/* compression stuff */
-	/* 52089  2118 */ {0x0003, 0x8509},
-	/* compression stuff */
-	/* 52114  2119 */ {0x0011, 0x850a},
-	/* compression stuff */
-	/* 52139  2120 */ {0x0021, 0x850d},
-	/* compression stuff */
-	/* 52164  2121 */ {0x0010, 0x850c},
-	/* compression stuff */
-	/* 52189  2122 */ {0x0003, 0x8500},
-	/* *** Video mode: 160x120 */
-	/* 52214  2123 */ {0x0001, 0x8501},
-	/* Hardware-dominated snap control */
-	/* 52239  2124 */ {0x0061, 0x8656},
-	/* Window1 size 128x128, Windows2 size 128x128,
-	 *		gamma look-up disable, new edge enhancement enable */
-	/* 52264  2125 */ {0x0018, 0x8617},
-	/* Window1 start X (*2) */
-	/* 52289  2126 */ {0x0008, 0x8618},
-	/* Window1 start Y (*2) */
-	/* 52314  2127 */ {0x0061, 0x8656},
-	/* Window1 size 128x128, Windows2 size 128x128,
-	 *		gamma look-up disable, new edge enhancement enable */
-	/* 52339  2128 */ {0x0058, 0x8619},
-	/* Window2 start X (*2) */
-	/* 52364  2129 */ {0x0008, 0x861a},
-	/* Window2 start Y (*2) */
-	/* 52389  2130 */ {0x00ff, 0x8615},
-	/* High lum thresh for white balance */
-	/* 52414  2131 */ {0x0000, 0x8616},
-	/* Low lum thresh for white balance */
-	/* 52439  2132 */ {0x0012, 0x8700},
-	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
-	/* 52464  2133 */ {0x0012, 0x8700},
-	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
-	/* 52487  2134 */ /* READ { 0, 0x0000, 0x8656 } -> 0000: 61  */
-	/* 52513  2135 */ {0x0028, 0x8802},
-	/* 375 Khz SSI clock, SSI r/w sync with VSYNC */
-	/* 52536  2136 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 52560  2137 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28  */
-	/* 52586  2138 */ {0x1f28, 0x8802},
-	/* 375 Khz SSI clock, SSI r/w sync with VSYNC */
-	/* 52611  2139 */ {0x0010, 0x8801},
-	/* SSI reg addr */
-	/* 52636  2140 */ {0x003e, 0x8800},
-	/* SSI data to write */
-	/* 52659  2141 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 52685  2142 */ {0x0028, 0x8802},
-	/* 52708  2143 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 52732  2144 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28  */
-	/* 52758  2145 */ {0x1f28, 0x8802},
-	/* 52783  2146 */ {0x0000, 0x8801},
-	/* 52808  2147 */ {0x001f, 0x8800},
-	/* 52831  2148 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 52857  2149 */ {0x0001, 0x8602},
-	/* optical black level for user settning = 1 */
+	{0x0021, 0x8508},	 * Enable compression. */
+	{0x0032, 0x850b},	/* compression stuff */
+	{0x0003, 0x8509},	/* compression stuff */
+	{0x0011, 0x850a},	/* compression stuff */
+	{0x0021, 0x850d},	/* compression stuff */
+	{0x0010, 0x850c},	/* compression stuff */
+	{0x0003, 0x8500},	/* *** Video mode: 160x120 */
+	{0x0001, 0x8501},	/* Hardware-dominated snap control */
+	{0x0061, 0x8656},	/* Window1 size 128x128, Windows2 size 128x128,
+				 * gamma look-up disable,
+				 * new edge enhancement enable */
+	{0x0018, 0x8617},	/* Window1 start X (*2) */
+	{0x0008, 0x8618},	/* Window1 start Y (*2) */
+	{0x0061, 0x8656},	/* Window1 size 128x128, Windows2 size 128x128,
+				 * gamma look-up disable,
+				 * new edge enhancement enable */
+	{0x0058, 0x8619},	/* Window2 start X (*2) */
+	{0x0008, 0x861a},	/* Window2 start Y (*2) */
+	{0x00ff, 0x8615},	/* High lum thresh for white balance */
+	{0x0000, 0x8616},	/* Low lum thresh for white balance */
+	{0x0012, 0x8700},	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
+	{0x0012, 0x8700},	/* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
+	/* READ { 0x0000, 0x8656 } -> 0000: 61  */
+	{0x0028, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 28  */
+	{0x1f28, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
+	{0x0010, 0x8801},	/* SSI reg addr */
+	{0x003e, 0x8800},	/* SSI data to write */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	{0x0028, 0x8802},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 28  */
+	{0x1f28, 0x8802},
+	{0x0000, 0x8801},
+	{0x001f, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	{0x0001, 0x8602},    /* optical black level for user settning = 1 */
 
 	/* Original: */
-	/* 52882  2150 */ {0x0023, 0x8700},
-	/* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
-	/* 52907  2151 */ {0x000f, 0x8602},
-	/* optical black level for user settning = 15 */
+	{0x0023, 0x8700},	/* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
+	{0x000f, 0x8602},    /* optical black level for user settning = 15 */
 
-	/* 52932  2152 */ {0x0028, 0x8802},
-	/* 52955  2153 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 52979  2154 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28  */
-	/* 53005  2155 */ {0x1f28, 0x8802},
-	/* 53030  2156 */ {0x0010, 0x8801},
-	/* 53055  2157 */ {0x007b, 0x8800},
-	/* 53078  2158 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00  */
-	/* 53104  2159 */ {0x002f, 0x8651},
-	/* R gain for white balance ... */
-	/* 53129  2160 */ {0x0080, 0x8653},
-	/* 53152  2161 */ /* READ { 0, 0x0000, 0x8655 } -> 0000: 00  */
-	/* 53178  2162 */ {0x0000, 0x8655},
+	{0x0028, 0x8802},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 28  */
+	{0x1f28, 0x8802},
+	{0x0010, 0x8801},
+	{0x007b, 0x8800},
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	{0x002f, 0x8651},	/* R gain for white balance ... */
+	{0x0080, 0x8653},
+	/* READ { 0x0000, 0x8655 } -> 0000: 00  */
+	{0x0000, 0x8655},
 
-	/* 53203  2163 */ {0x0030, 0x8112},
-	/* Video drop enable, ISO streaming enable */
-	/* 53228  2164 */ {0x0020, 0x8112},
-	/* Video drop enable, ISO streaming disable */
-	/* 53252  2165 */
-	     /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
+	{0x0030, 0x8112},	/* Video drop enable, ISO streaming enable */
+	{0x0020, 0x8112},	/* Video drop enable, ISO streaming disable */
+	/* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
 	{}
 };
 
@@ -592,27 +506,27 @@
  * Initialization data for Intel EasyPC Camera CS110
  */
 static const u16 spca508cs110_init_data[][2] = {
-	{0x0000, 0x870b}, /* Reset CTL3 */
-	{0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
-	{0x0000, 0x8111}, /* Normal operation on reset */
+	{0x0000, 0x870b},	/* Reset CTL3 */
+	{0x0003, 0x8111},	/* Soft Reset compression, memory, TG & CDSP */
+	{0x0000, 0x8111},	/* Normal operation on reset */
 	{0x0090, 0x8110},
 		 /* External Clock 2x & Synchronous Serial Interface Output */
-	{0x0020, 0x8112}, /* Video Drop packet enable */
-	{0x0000, 0x8114}, /* Software GPIO output data */
+	{0x0020, 0x8112},	/* Video Drop packet enable */
+	{0x0000, 0x8114},	/* Software GPIO output data */
 	{0x0001, 0x8114},
 	{0x0001, 0x8114},
 	{0x0001, 0x8114},
 	{0x0003, 0x8114},
 
 	/* Initial sequence Synchronous Serial Interface */
-	{0x000f, 0x8402}, /* Memory bank Address */
-	{0x0000, 0x8403}, /* Memory bank Address */
-	{0x00ba, 0x8804}, /* SSI Slave address */
-	{0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
-	{0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */
+	{0x000f, 0x8402},	/* Memory bank Address */
+	{0x0000, 0x8403},	/* Memory bank Address */
+	{0x00ba, 0x8804},	/* SSI Slave address */
+	{0x0010, 0x8802},	/* 93.75kHz SSI Clock Two DataByte */
+	{0x0010, 0x8802},	/* 93.75kHz SSI Clock two DataByte */
 
 	{0x0001, 0x8801},
-	{0x000a, 0x8805},/* a - NWG: Dunno what this is about */
+	{0x000a, 0x8805},	/* a - NWG: Dunno what this is about */
 	{0x0000, 0x8800},
 	{0x0010, 0x8802},
 
@@ -646,459 +560,459 @@
 	{0x0000, 0x8800},
 	{0x0010, 0x8802},
 
-	{0x0002, 0x8704}, /* External input CKIx1 */
-	{0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
-	{0x009a, 0x8600}, /* Line memory Read Counter (L) */
-	{0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */
-	{0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */
-	{0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */
+	{0x0002, 0x8704},	/* External input CKIx1 */
+	{0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
+	{0x009a, 0x8600},	/* Line memory Read Counter (L) */
+	{0x0001, 0x865b},	/* 1 Horizontal Offset for Valid Pixel(L) */
+	{0x0003, 0x865c},	/* 3 Vertical Offset for Valid Lines(L) */
+	{0x0058, 0x865d},	/* 58 Horizontal Valid Pixel Window(L) */
 
-	{0x0006, 0x8660}, /* Nibble data + input order */
+	{0x0006, 0x8660},	/* Nibble data + input order */
 
-	{0x000a, 0x8602}, /* Optical black level set to 0x0a */
-/* 1945 */ {0x0000, 0x8603}, /* Optical black level Offset */
+	{0x000a, 0x8602},	/* Optical black level set to 0x0a */
+	{0x0000, 0x8603},	/* Optical black level Offset */
 
-/* 1962 *  {0, 0x0000, 0x8611},  * 0 R  Offset for white Balance */
-/* 1963 *  {0, 0x0000, 0x8612},  * 1 Gr Offset for white Balance */
-/* 1964 *  {0, 0x0000, 0x8613},  * 1f B  Offset for white Balance */
-/* 1965 *  {0, 0x0000, 0x8614},  * f0 Gb Offset for white Balance */
+/*	{0x0000, 0x8611},	 * 0 R  Offset for white Balance */
+/*	{0x0000, 0x8612},	 * 1 Gr Offset for white Balance */
+/*	{0x0000, 0x8613},	 * 1f B  Offset for white Balance */
+/*	{0x0000, 0x8614},	 * f0 Gb Offset for white Balance */
 
-	{0x0040, 0x8651}, /* 2b BLUE gain for white balance  good at all 60 */
-	{0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */
-	{0x0035, 0x8653}, /* 26 RED gain for white balance */
-	{0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */
+	{0x0040, 0x8651},   /* 2b BLUE gain for white balance  good at all 60 */
+	{0x0030, 0x8652},	/* 41 Gr Gain for white Balance (L) */
+	{0x0035, 0x8653},	/* 26 RED gain for white balance */
+	{0x0035, 0x8654},	/* 40Gb Gain for white Balance (L) */
 	{0x0041, 0x863f},
 	      /* Fixed Gamma correction enabled (makes colours look better) */
 
-/* 2422 */ {0x0000, 0x8655},
-	/* High bits for white balance*****brightness control*** */
+	{0x0000, 0x8655},
+		/* High bits for white balance*****brightness control*** */
 	{}
 };
 
 static const u16 spca508_sightcam_init_data[][2] = {
 /* This line seems to setup the frame/canvas */
-	/*368  */ {0x000f, 0x8402},
+	{0x000f, 0x8402},
 
 /* Theese 6 lines are needed to startup the webcam */
-	/*398  */ {0x0090, 0x8110},
-	/*399  */ {0x0001, 0x8114},
-	/*400  */ {0x0001, 0x8114},
-	/*401  */ {0x0001, 0x8114},
-	/*402  */ {0x0003, 0x8114},
-	/*403  */ {0x0080, 0x8804},
+	{0x0090, 0x8110},
+	{0x0001, 0x8114},
+	{0x0001, 0x8114},
+	{0x0001, 0x8114},
+	{0x0003, 0x8114},
+	{0x0080, 0x8804},
 
 /* This part seems to make the pictures darker? (autobrightness?) */
-	/*436  */ {0x0001, 0x8801},
-	/*437  */ {0x0004, 0x8800},
-	/*439  */ {0x0003, 0x8801},
-	/*440  */ {0x00e0, 0x8800},
-	/*442  */ {0x0004, 0x8801},
-	/*443  */ {0x00b4, 0x8800},
-	/*445  */ {0x0005, 0x8801},
-	/*446  */ {0x0000, 0x8800},
+	{0x0001, 0x8801},
+	{0x0004, 0x8800},
+	{0x0003, 0x8801},
+	{0x00e0, 0x8800},
+	{0x0004, 0x8801},
+	{0x00b4, 0x8800},
+	{0x0005, 0x8801},
+	{0x0000, 0x8800},
 
-	/*448  */ {0x0006, 0x8801},
-	/*449  */ {0x00e0, 0x8800},
-	/*451  */ {0x0007, 0x8801},
-	/*452  */ {0x000c, 0x8800},
+	{0x0006, 0x8801},
+	{0x00e0, 0x8800},
+	{0x0007, 0x8801},
+	{0x000c, 0x8800},
 
 /* This section is just needed, it probably
  * does something like the previous section,
  * but the cam won't start if it's not included.
  */
-	/*484  */ {0x0014, 0x8801},
-	/*485  */ {0x0008, 0x8800},
-	/*487  */ {0x0015, 0x8801},
-	/*488  */ {0x0067, 0x8800},
-	/*490  */ {0x0016, 0x8801},
-	/*491  */ {0x0000, 0x8800},
-	/*493  */ {0x0017, 0x8801},
-	/*494  */ {0x0020, 0x8800},
-	/*496  */ {0x0018, 0x8801},
-	/*497  */ {0x0044, 0x8800},
+	{0x0014, 0x8801},
+	{0x0008, 0x8800},
+	{0x0015, 0x8801},
+	{0x0067, 0x8800},
+	{0x0016, 0x8801},
+	{0x0000, 0x8800},
+	{0x0017, 0x8801},
+	{0x0020, 0x8800},
+	{0x0018, 0x8801},
+	{0x0044, 0x8800},
 
 /* Makes the picture darker - and the
  * cam won't start if not included
  */
-	/*505  */ {0x001e, 0x8801},
-	/*506  */ {0x00ea, 0x8800},
-	/*508  */ {0x001f, 0x8801},
-	/*509  */ {0x0001, 0x8800},
-	/*511  */ {0x0003, 0x8801},
-	/*512  */ {0x00e0, 0x8800},
+	{0x001e, 0x8801},
+	{0x00ea, 0x8800},
+	{0x001f, 0x8801},
+	{0x0001, 0x8800},
+	{0x0003, 0x8801},
+	{0x00e0, 0x8800},
 
 /* seems to place the colors ontop of each other #1 */
-	/*517  */ {0x0006, 0x8704},
-	/*518  */ {0x0001, 0x870c},
-	/*519  */ {0x0016, 0x8600},
-	/*520  */ {0x0002, 0x8606},
+	{0x0006, 0x8704},
+	{0x0001, 0x870c},
+	{0x0016, 0x8600},
+	{0x0002, 0x8606},
 
 /* if not included the pictures becomes _very_ dark */
-	/*521  */ {0x0064, 0x8607},
-	/*522  */ {0x003a, 0x8601},
-	/*523  */ {0x0000, 0x8602},
+	{0x0064, 0x8607},
+	{0x003a, 0x8601},
+	{0x0000, 0x8602},
 
 /* seems to place the colors ontop of each other #2 */
-	/*524  */ {0x0016, 0x8600},
-	/*525  */ {0x0018, 0x8617},
-	/*526  */ {0x0008, 0x8618},
-	/*527  */ {0x00a1, 0x8656},
+	{0x0016, 0x8600},
+	{0x0018, 0x8617},
+	{0x0008, 0x8618},
+	{0x00a1, 0x8656},
 
 /* webcam won't start if not included */
-	/*528  */ {0x0007, 0x865b},
-	/*529  */ {0x0001, 0x865c},
-	/*530  */ {0x0058, 0x865d},
-	/*531  */ {0x0048, 0x865e},
+	{0x0007, 0x865b},
+	{0x0001, 0x865c},
+	{0x0058, 0x865d},
+	{0x0048, 0x865e},
 
 /* adjusts the colors */
-	/*541  */ {0x0049, 0x8651},
-	/*542  */ {0x0040, 0x8652},
-	/*543  */ {0x004c, 0x8653},
-	/*544  */ {0x0040, 0x8654},
+	{0x0049, 0x8651},
+	{0x0040, 0x8652},
+	{0x004c, 0x8653},
+	{0x0040, 0x8654},
 	{}
 };
 
 static const u16 spca508_sightcam2_init_data[][2] = {
-/* 35 */ {0x0020, 0x8112},
+	{0x0020, 0x8112},
 
-/* 36 */ {0x000f, 0x8402},
-/* 37 */ {0x0000, 0x8403},
+	{0x000f, 0x8402},
+	{0x0000, 0x8403},
 
-/* 38 */ {0x0008, 0x8201},
-/* 39 */ {0x0008, 0x8200},
-/* 40 */ {0x0001, 0x8200},
-/* 43 */ {0x0009, 0x8201},
-/* 44 */ {0x0008, 0x8200},
-/* 45 */ {0x0001, 0x8200},
-/* 48 */ {0x000a, 0x8201},
-/* 49 */ {0x0008, 0x8200},
-/* 50 */ {0x0001, 0x8200},
-/* 53 */ {0x000b, 0x8201},
-/* 54 */ {0x0008, 0x8200},
-/* 55 */ {0x0001, 0x8200},
-/* 58 */ {0x000c, 0x8201},
-/* 59 */ {0x0008, 0x8200},
-/* 60 */ {0x0001, 0x8200},
-/* 63 */ {0x000d, 0x8201},
-/* 64 */ {0x0008, 0x8200},
-/* 65 */ {0x0001, 0x8200},
-/* 68 */ {0x000e, 0x8201},
-/* 69 */ {0x0008, 0x8200},
-/* 70 */ {0x0001, 0x8200},
-/* 73 */ {0x0007, 0x8201},
-/* 74 */ {0x0008, 0x8200},
-/* 75 */ {0x0001, 0x8200},
-/* 78 */ {0x000f, 0x8201},
-/* 79 */ {0x0008, 0x8200},
-/* 80 */ {0x0001, 0x8200},
+	{0x0008, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x0009, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x000a, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x000b, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x000c, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x000d, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x000e, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x0007, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x000f, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
 
-/* 84 */ {0x0018, 0x8660},
-/* 85 */ {0x0010, 0x8201},
+	{0x0018, 0x8660},
+	{0x0010, 0x8201},
 
-/* 86 */ {0x0008, 0x8200},
-/* 87 */ {0x0001, 0x8200},
-/* 90 */ {0x0011, 0x8201},
-/* 91 */ {0x0008, 0x8200},
-/* 92 */ {0x0001, 0x8200},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x0011, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
 
-/* 95 */ {0x0000, 0x86b0},
-/* 96 */ {0x0034, 0x86b1},
-/* 97 */ {0x0000, 0x86b2},
-/* 98 */ {0x0049, 0x86b3},
-/* 99 */ {0x0000, 0x86b4},
-/* 100 */ {0x0000, 0x86b4},
+	{0x0000, 0x86b0},
+	{0x0034, 0x86b1},
+	{0x0000, 0x86b2},
+	{0x0049, 0x86b3},
+	{0x0000, 0x86b4},
+	{0x0000, 0x86b4},
 
-/* 101 */ {0x0012, 0x8201},
-/* 102 */ {0x0008, 0x8200},
-/* 103 */ {0x0001, 0x8200},
-/* 106 */ {0x0013, 0x8201},
-/* 107 */ {0x0008, 0x8200},
-/* 108 */ {0x0001, 0x8200},
+	{0x0012, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
+	{0x0013, 0x8201},
+	{0x0008, 0x8200},
+	{0x0001, 0x8200},
 
-/* 111 */ {0x0001, 0x86b0},
-/* 112 */ {0x00aa, 0x86b1},
-/* 113 */ {0x0000, 0x86b2},
-/* 114 */ {0x00e4, 0x86b3},
-/* 115 */ {0x0000, 0x86b4},
-/* 116 */ {0x0000, 0x86b4},
+	{0x0001, 0x86b0},
+	{0x00aa, 0x86b1},
+	{0x0000, 0x86b2},
+	{0x00e4, 0x86b3},
+	{0x0000, 0x86b4},
+	{0x0000, 0x86b4},
 
-/* 118 */ {0x0018, 0x8660},
+	{0x0018, 0x8660},
 
-/* 119 */ {0x0090, 0x8110},
-/* 120 */ {0x0001, 0x8114},
-/* 121 */ {0x0001, 0x8114},
-/* 122 */ {0x0001, 0x8114},
-/* 123 */ {0x0003, 0x8114},
+	{0x0090, 0x8110},
+	{0x0001, 0x8114},
+	{0x0001, 0x8114},
+	{0x0001, 0x8114},
+	{0x0003, 0x8114},
 
-/* 124 */ {0x0080, 0x8804},
-/* 157 */ {0x0003, 0x8801},
-/* 158 */ {0x0012, 0x8800},
-/* 160 */ {0x0004, 0x8801},
-/* 161 */ {0x0005, 0x8800},
-/* 163 */ {0x0005, 0x8801},
-/* 164 */ {0x0000, 0x8800},
-/* 166 */ {0x0006, 0x8801},
-/* 167 */ {0x0000, 0x8800},
-/* 169 */ {0x0007, 0x8801},
-/* 170 */ {0x0000, 0x8800},
-/* 172 */ {0x0008, 0x8801},
-/* 173 */ {0x0005, 0x8800},
-/* 175 */ {0x000a, 0x8700},
-/* 176 */ {0x000e, 0x8801},
-/* 177 */ {0x0004, 0x8800},
-/* 179 */ {0x0005, 0x8801},
-/* 180 */ {0x0047, 0x8800},
-/* 182 */ {0x0006, 0x8801},
-/* 183 */ {0x0000, 0x8800},
-/* 185 */ {0x0007, 0x8801},
-/* 186 */ {0x00c0, 0x8800},
-/* 188 */ {0x0008, 0x8801},
-/* 189 */ {0x0003, 0x8800},
-/* 191 */ {0x0013, 0x8801},
-/* 192 */ {0x0001, 0x8800},
-/* 194 */ {0x0009, 0x8801},
-/* 195 */ {0x0000, 0x8800},
-/* 197 */ {0x000a, 0x8801},
-/* 198 */ {0x0000, 0x8800},
-/* 200 */ {0x000b, 0x8801},
-/* 201 */ {0x0000, 0x8800},
-/* 203 */ {0x000c, 0x8801},
-/* 204 */ {0x0000, 0x8800},
-/* 206 */ {0x000e, 0x8801},
-/* 207 */ {0x0004, 0x8800},
-/* 209 */ {0x000f, 0x8801},
-/* 210 */ {0x0000, 0x8800},
-/* 212 */ {0x0010, 0x8801},
-/* 213 */ {0x0006, 0x8800},
-/* 215 */ {0x0011, 0x8801},
-/* 216 */ {0x0006, 0x8800},
-/* 218 */ {0x0012, 0x8801},
-/* 219 */ {0x0000, 0x8800},
-/* 221 */ {0x0013, 0x8801},
-/* 222 */ {0x0001, 0x8800},
+	{0x0080, 0x8804},
+	{0x0003, 0x8801},
+	{0x0012, 0x8800},
+	{0x0004, 0x8801},
+	{0x0005, 0x8800},
+	{0x0005, 0x8801},
+	{0x0000, 0x8800},
+	{0x0006, 0x8801},
+	{0x0000, 0x8800},
+	{0x0007, 0x8801},
+	{0x0000, 0x8800},
+	{0x0008, 0x8801},
+	{0x0005, 0x8800},
+	{0x000a, 0x8700},
+	{0x000e, 0x8801},
+	{0x0004, 0x8800},
+	{0x0005, 0x8801},
+	{0x0047, 0x8800},
+	{0x0006, 0x8801},
+	{0x0000, 0x8800},
+	{0x0007, 0x8801},
+	{0x00c0, 0x8800},
+	{0x0008, 0x8801},
+	{0x0003, 0x8800},
+	{0x0013, 0x8801},
+	{0x0001, 0x8800},
+	{0x0009, 0x8801},
+	{0x0000, 0x8800},
+	{0x000a, 0x8801},
+	{0x0000, 0x8800},
+	{0x000b, 0x8801},
+	{0x0000, 0x8800},
+	{0x000c, 0x8801},
+	{0x0000, 0x8800},
+	{0x000e, 0x8801},
+	{0x0004, 0x8800},
+	{0x000f, 0x8801},
+	{0x0000, 0x8800},
+	{0x0010, 0x8801},
+	{0x0006, 0x8800},
+	{0x0011, 0x8801},
+	{0x0006, 0x8800},
+	{0x0012, 0x8801},
+	{0x0000, 0x8800},
+	{0x0013, 0x8801},
+	{0x0001, 0x8800},
 
-/* 224 */ {0x000a, 0x8700},
-/* 225 */ {0x0000, 0x8702},
-/* 226 */ {0x0000, 0x8703},
-/* 227 */ {0x00c2, 0x8704},
-/* 228 */ {0x0001, 0x870c},
+	{0x000a, 0x8700},
+	{0x0000, 0x8702},
+	{0x0000, 0x8703},
+	{0x00c2, 0x8704},
+	{0x0001, 0x870c},
 
-/* 229 */ {0x0044, 0x8600},
-/* 230 */ {0x0002, 0x8606},
-/* 231 */ {0x0064, 0x8607},
-/* 232 */ {0x003a, 0x8601},
-/* 233 */ {0x0008, 0x8602},
-/* 234 */ {0x0044, 0x8600},
-/* 235 */ {0x0018, 0x8617},
-/* 236 */ {0x0008, 0x8618},
-/* 237 */ {0x00a1, 0x8656},
-/* 238 */ {0x0004, 0x865b},
-/* 239 */ {0x0002, 0x865c},
-/* 240 */ {0x0058, 0x865d},
-/* 241 */ {0x0048, 0x865e},
-/* 242 */ {0x0012, 0x8608},
-/* 243 */ {0x002c, 0x8609},
-/* 244 */ {0x0002, 0x860a},
-/* 245 */ {0x002c, 0x860b},
-/* 246 */ {0x00db, 0x860c},
-/* 247 */ {0x00f9, 0x860d},
-/* 248 */ {0x00f1, 0x860e},
-/* 249 */ {0x00e3, 0x860f},
-/* 250 */ {0x002c, 0x8610},
-/* 251 */ {0x006c, 0x8651},
-/* 252 */ {0x0041, 0x8652},
-/* 253 */ {0x0059, 0x8653},
-/* 254 */ {0x0040, 0x8654},
-/* 255 */ {0x00fa, 0x8611},
-/* 256 */ {0x00ff, 0x8612},
-/* 257 */ {0x00f8, 0x8613},
-/* 258 */ {0x0000, 0x8614},
-/* 259 */ {0x0001, 0x863f},
-/* 260 */ {0x0000, 0x8640},
-/* 261 */ {0x0026, 0x8641},
-/* 262 */ {0x0045, 0x8642},
-/* 263 */ {0x0060, 0x8643},
-/* 264 */ {0x0075, 0x8644},
-/* 265 */ {0x0088, 0x8645},
-/* 266 */ {0x009b, 0x8646},
-/* 267 */ {0x00b0, 0x8647},
-/* 268 */ {0x00c5, 0x8648},
-/* 269 */ {0x00d2, 0x8649},
-/* 270 */ {0x00dc, 0x864a},
-/* 271 */ {0x00e5, 0x864b},
-/* 272 */ {0x00eb, 0x864c},
-/* 273 */ {0x00f0, 0x864d},
-/* 274 */ {0x00f6, 0x864e},
-/* 275 */ {0x00fa, 0x864f},
-/* 276 */ {0x00ff, 0x8650},
-/* 277 */ {0x0060, 0x8657},
-/* 278 */ {0x0010, 0x8658},
-/* 279 */ {0x0018, 0x8659},
-/* 280 */ {0x0005, 0x865a},
-/* 281 */ {0x0018, 0x8660},
-/* 282 */ {0x0003, 0x8509},
-/* 283 */ {0x0011, 0x850a},
-/* 284 */ {0x0032, 0x850b},
-/* 285 */ {0x0010, 0x850c},
-/* 286 */ {0x0021, 0x850d},
-/* 287 */ {0x0001, 0x8500},
-/* 288 */ {0x0000, 0x8508},
-/* 289 */ {0x0012, 0x8608},
-/* 290 */ {0x002c, 0x8609},
-/* 291 */ {0x0002, 0x860a},
-/* 292 */ {0x0039, 0x860b},
-/* 293 */ {0x00d0, 0x860c},
-/* 294 */ {0x00f7, 0x860d},
-/* 295 */ {0x00ed, 0x860e},
-/* 296 */ {0x00db, 0x860f},
-/* 297 */ {0x0039, 0x8610},
-/* 298 */ {0x0012, 0x8657},
-/* 299 */ {0x000c, 0x8619},
-/* 300 */ {0x0004, 0x861a},
-/* 301 */ {0x00a1, 0x8656},
-/* 302 */ {0x00c8, 0x8615},
-/* 303 */ {0x0032, 0x8616},
+	{0x0044, 0x8600},
+	{0x0002, 0x8606},
+	{0x0064, 0x8607},
+	{0x003a, 0x8601},
+	{0x0008, 0x8602},
+	{0x0044, 0x8600},
+	{0x0018, 0x8617},
+	{0x0008, 0x8618},
+	{0x00a1, 0x8656},
+	{0x0004, 0x865b},
+	{0x0002, 0x865c},
+	{0x0058, 0x865d},
+	{0x0048, 0x865e},
+	{0x0012, 0x8608},
+	{0x002c, 0x8609},
+	{0x0002, 0x860a},
+	{0x002c, 0x860b},
+	{0x00db, 0x860c},
+	{0x00f9, 0x860d},
+	{0x00f1, 0x860e},
+	{0x00e3, 0x860f},
+	{0x002c, 0x8610},
+	{0x006c, 0x8651},
+	{0x0041, 0x8652},
+	{0x0059, 0x8653},
+	{0x0040, 0x8654},
+	{0x00fa, 0x8611},
+	{0x00ff, 0x8612},
+	{0x00f8, 0x8613},
+	{0x0000, 0x8614},
+	{0x0001, 0x863f},
+	{0x0000, 0x8640},
+	{0x0026, 0x8641},
+	{0x0045, 0x8642},
+	{0x0060, 0x8643},
+	{0x0075, 0x8644},
+	{0x0088, 0x8645},
+	{0x009b, 0x8646},
+	{0x00b0, 0x8647},
+	{0x00c5, 0x8648},
+	{0x00d2, 0x8649},
+	{0x00dc, 0x864a},
+	{0x00e5, 0x864b},
+	{0x00eb, 0x864c},
+	{0x00f0, 0x864d},
+	{0x00f6, 0x864e},
+	{0x00fa, 0x864f},
+	{0x00ff, 0x8650},
+	{0x0060, 0x8657},
+	{0x0010, 0x8658},
+	{0x0018, 0x8659},
+	{0x0005, 0x865a},
+	{0x0018, 0x8660},
+	{0x0003, 0x8509},
+	{0x0011, 0x850a},
+	{0x0032, 0x850b},
+	{0x0010, 0x850c},
+	{0x0021, 0x850d},
+	{0x0001, 0x8500},
+	{0x0000, 0x8508},
+	{0x0012, 0x8608},
+	{0x002c, 0x8609},
+	{0x0002, 0x860a},
+	{0x0039, 0x860b},
+	{0x00d0, 0x860c},
+	{0x00f7, 0x860d},
+	{0x00ed, 0x860e},
+	{0x00db, 0x860f},
+	{0x0039, 0x8610},
+	{0x0012, 0x8657},
+	{0x000c, 0x8619},
+	{0x0004, 0x861a},
+	{0x00a1, 0x8656},
+	{0x00c8, 0x8615},
+	{0x0032, 0x8616},
 
-/* 306 */ {0x0030, 0x8112},
-/* 313 */ {0x0020, 0x8112},
-/* 314 */ {0x0020, 0x8112},
-/* 315 */ {0x000f, 0x8402},
-/* 316 */ {0x0000, 0x8403},
+	{0x0030, 0x8112},
+	{0x0020, 0x8112},
+	{0x0020, 0x8112},
+	{0x000f, 0x8402},
+	{0x0000, 0x8403},
 
-/* 317 */ {0x0090, 0x8110},
-/* 318 */ {0x0001, 0x8114},
-/* 319 */ {0x0001, 0x8114},
-/* 320 */ {0x0001, 0x8114},
-/* 321 */ {0x0003, 0x8114},
-/* 322 */ {0x0080, 0x8804},
+	{0x0090, 0x8110},
+	{0x0001, 0x8114},
+	{0x0001, 0x8114},
+	{0x0001, 0x8114},
+	{0x0003, 0x8114},
+	{0x0080, 0x8804},
 
-/* 355 */ {0x0003, 0x8801},
-/* 356 */ {0x0012, 0x8800},
-/* 358 */ {0x0004, 0x8801},
-/* 359 */ {0x0005, 0x8800},
-/* 361 */ {0x0005, 0x8801},
-/* 362 */ {0x0047, 0x8800},
-/* 364 */ {0x0006, 0x8801},
-/* 365 */ {0x0000, 0x8800},
-/* 367 */ {0x0007, 0x8801},
-/* 368 */ {0x00c0, 0x8800},
-/* 370 */ {0x0008, 0x8801},
-/* 371 */ {0x0003, 0x8800},
-/* 373 */ {0x000a, 0x8700},
-/* 374 */ {0x000e, 0x8801},
-/* 375 */ {0x0004, 0x8800},
-/* 377 */ {0x0005, 0x8801},
-/* 378 */ {0x0047, 0x8800},
-/* 380 */ {0x0006, 0x8801},
-/* 381 */ {0x0000, 0x8800},
-/* 383 */ {0x0007, 0x8801},
-/* 384 */ {0x00c0, 0x8800},
-/* 386 */ {0x0008, 0x8801},
-/* 387 */ {0x0003, 0x8800},
-/* 389 */ {0x0013, 0x8801},
-/* 390 */ {0x0001, 0x8800},
-/* 392 */ {0x0009, 0x8801},
-/* 393 */ {0x0000, 0x8800},
-/* 395 */ {0x000a, 0x8801},
-/* 396 */ {0x0000, 0x8800},
-/* 398 */ {0x000b, 0x8801},
-/* 399 */ {0x0000, 0x8800},
-/* 401 */ {0x000c, 0x8801},
-/* 402 */ {0x0000, 0x8800},
-/* 404 */ {0x000e, 0x8801},
-/* 405 */ {0x0004, 0x8800},
-/* 407 */ {0x000f, 0x8801},
-/* 408 */ {0x0000, 0x8800},
-/* 410 */ {0x0010, 0x8801},
-/* 411 */ {0x0006, 0x8800},
-/* 413 */ {0x0011, 0x8801},
-/* 414 */ {0x0006, 0x8800},
-/* 416 */ {0x0012, 0x8801},
-/* 417 */ {0x0000, 0x8800},
-/* 419 */ {0x0013, 0x8801},
-/* 420 */ {0x0001, 0x8800},
-/* 422 */ {0x000a, 0x8700},
-/* 423 */ {0x0000, 0x8702},
-/* 424 */ {0x0000, 0x8703},
-/* 425 */ {0x00c2, 0x8704},
-/* 426 */ {0x0001, 0x870c},
-/* 427 */ {0x0044, 0x8600},
-/* 428 */ {0x0002, 0x8606},
-/* 429 */ {0x0064, 0x8607},
-/* 430 */ {0x003a, 0x8601},
-/* 431 */ {0x0008, 0x8602},
-/* 432 */ {0x0044, 0x8600},
-/* 433 */ {0x0018, 0x8617},
-/* 434 */ {0x0008, 0x8618},
-/* 435 */ {0x00a1, 0x8656},
-/* 436 */ {0x0004, 0x865b},
-/* 437 */ {0x0002, 0x865c},
-/* 438 */ {0x0058, 0x865d},
-/* 439 */ {0x0048, 0x865e},
-/* 440 */ {0x0012, 0x8608},
-/* 441 */ {0x002c, 0x8609},
-/* 442 */ {0x0002, 0x860a},
-/* 443 */ {0x002c, 0x860b},
-/* 444 */ {0x00db, 0x860c},
-/* 445 */ {0x00f9, 0x860d},
-/* 446 */ {0x00f1, 0x860e},
-/* 447 */ {0x00e3, 0x860f},
-/* 448 */ {0x002c, 0x8610},
-/* 449 */ {0x006c, 0x8651},
-/* 450 */ {0x0041, 0x8652},
-/* 451 */ {0x0059, 0x8653},
-/* 452 */ {0x0040, 0x8654},
-/* 453 */ {0x00fa, 0x8611},
-/* 454 */ {0x00ff, 0x8612},
-/* 455 */ {0x00f8, 0x8613},
-/* 456 */ {0x0000, 0x8614},
-/* 457 */ {0x0001, 0x863f},
-/* 458 */ {0x0000, 0x8640},
-/* 459 */ {0x0026, 0x8641},
-/* 460 */ {0x0045, 0x8642},
-/* 461 */ {0x0060, 0x8643},
-/* 462 */ {0x0075, 0x8644},
-/* 463 */ {0x0088, 0x8645},
-/* 464 */ {0x009b, 0x8646},
-/* 465 */ {0x00b0, 0x8647},
-/* 466 */ {0x00c5, 0x8648},
-/* 467 */ {0x00d2, 0x8649},
-/* 468 */ {0x00dc, 0x864a},
-/* 469 */ {0x00e5, 0x864b},
-/* 470 */ {0x00eb, 0x864c},
-/* 471 */ {0x00f0, 0x864d},
-/* 472 */ {0x00f6, 0x864e},
-/* 473 */ {0x00fa, 0x864f},
-/* 474 */ {0x00ff, 0x8650},
-/* 475 */ {0x0060, 0x8657},
-/* 476 */ {0x0010, 0x8658},
-/* 477 */ {0x0018, 0x8659},
-/* 478 */ {0x0005, 0x865a},
-/* 479 */ {0x0018, 0x8660},
-/* 480 */ {0x0003, 0x8509},
-/* 481 */ {0x0011, 0x850a},
-/* 482 */ {0x0032, 0x850b},
-/* 483 */ {0x0010, 0x850c},
-/* 484 */ {0x0021, 0x850d},
-/* 485 */ {0x0001, 0x8500},
-/* 486 */ {0x0000, 0x8508},
+	{0x0003, 0x8801},
+	{0x0012, 0x8800},
+	{0x0004, 0x8801},
+	{0x0005, 0x8800},
+	{0x0005, 0x8801},
+	{0x0047, 0x8800},
+	{0x0006, 0x8801},
+	{0x0000, 0x8800},
+	{0x0007, 0x8801},
+	{0x00c0, 0x8800},
+	{0x0008, 0x8801},
+	{0x0003, 0x8800},
+	{0x000a, 0x8700},
+	{0x000e, 0x8801},
+	{0x0004, 0x8800},
+	{0x0005, 0x8801},
+	{0x0047, 0x8800},
+	{0x0006, 0x8801},
+	{0x0000, 0x8800},
+	{0x0007, 0x8801},
+	{0x00c0, 0x8800},
+	{0x0008, 0x8801},
+	{0x0003, 0x8800},
+	{0x0013, 0x8801},
+	{0x0001, 0x8800},
+	{0x0009, 0x8801},
+	{0x0000, 0x8800},
+	{0x000a, 0x8801},
+	{0x0000, 0x8800},
+	{0x000b, 0x8801},
+	{0x0000, 0x8800},
+	{0x000c, 0x8801},
+	{0x0000, 0x8800},
+	{0x000e, 0x8801},
+	{0x0004, 0x8800},
+	{0x000f, 0x8801},
+	{0x0000, 0x8800},
+	{0x0010, 0x8801},
+	{0x0006, 0x8800},
+	{0x0011, 0x8801},
+	{0x0006, 0x8800},
+	{0x0012, 0x8801},
+	{0x0000, 0x8800},
+	{0x0013, 0x8801},
+	{0x0001, 0x8800},
+	{0x000a, 0x8700},
+	{0x0000, 0x8702},
+	{0x0000, 0x8703},
+	{0x00c2, 0x8704},
+	{0x0001, 0x870c},
+	{0x0044, 0x8600},
+	{0x0002, 0x8606},
+	{0x0064, 0x8607},
+	{0x003a, 0x8601},
+	{0x0008, 0x8602},
+	{0x0044, 0x8600},
+	{0x0018, 0x8617},
+	{0x0008, 0x8618},
+	{0x00a1, 0x8656},
+	{0x0004, 0x865b},
+	{0x0002, 0x865c},
+	{0x0058, 0x865d},
+	{0x0048, 0x865e},
+	{0x0012, 0x8608},
+	{0x002c, 0x8609},
+	{0x0002, 0x860a},
+	{0x002c, 0x860b},
+	{0x00db, 0x860c},
+	{0x00f9, 0x860d},
+	{0x00f1, 0x860e},
+	{0x00e3, 0x860f},
+	{0x002c, 0x8610},
+	{0x006c, 0x8651},
+	{0x0041, 0x8652},
+	{0x0059, 0x8653},
+	{0x0040, 0x8654},
+	{0x00fa, 0x8611},
+	{0x00ff, 0x8612},
+	{0x00f8, 0x8613},
+	{0x0000, 0x8614},
+	{0x0001, 0x863f},
+	{0x0000, 0x8640},
+	{0x0026, 0x8641},
+	{0x0045, 0x8642},
+	{0x0060, 0x8643},
+	{0x0075, 0x8644},
+	{0x0088, 0x8645},
+	{0x009b, 0x8646},
+	{0x00b0, 0x8647},
+	{0x00c5, 0x8648},
+	{0x00d2, 0x8649},
+	{0x00dc, 0x864a},
+	{0x00e5, 0x864b},
+	{0x00eb, 0x864c},
+	{0x00f0, 0x864d},
+	{0x00f6, 0x864e},
+	{0x00fa, 0x864f},
+	{0x00ff, 0x8650},
+	{0x0060, 0x8657},
+	{0x0010, 0x8658},
+	{0x0018, 0x8659},
+	{0x0005, 0x865a},
+	{0x0018, 0x8660},
+	{0x0003, 0x8509},
+	{0x0011, 0x850a},
+	{0x0032, 0x850b},
+	{0x0010, 0x850c},
+	{0x0021, 0x850d},
+	{0x0001, 0x8500},
+	{0x0000, 0x8508},
 
-/* 487 */ {0x0012, 0x8608},
-/* 488 */ {0x002c, 0x8609},
-/* 489 */ {0x0002, 0x860a},
-/* 490 */ {0x0039, 0x860b},
-/* 491 */ {0x00d0, 0x860c},
-/* 492 */ {0x00f7, 0x860d},
-/* 493 */ {0x00ed, 0x860e},
-/* 494 */ {0x00db, 0x860f},
-/* 495 */ {0x0039, 0x8610},
-/* 496 */ {0x0012, 0x8657},
-/* 497 */ {0x0064, 0x8619},
+	{0x0012, 0x8608},
+	{0x002c, 0x8609},
+	{0x0002, 0x860a},
+	{0x0039, 0x860b},
+	{0x00d0, 0x860c},
+	{0x00f7, 0x860d},
+	{0x00ed, 0x860e},
+	{0x00db, 0x860f},
+	{0x0039, 0x8610},
+	{0x0012, 0x8657},
+	{0x0064, 0x8619},
 
 /* This line starts it all, it is not needed here */
 /* since it has been build into the driver */
 /* jfm: don't start now */
-/* 590  *  {0x0030, 0x8112}, */
+/*	{0x0030, 0x8112}, */
 	{}
 };
 
@@ -1109,14 +1023,14 @@
 	{0x0008, 0x8200},	/* Clear register */
 	{0x0000, 0x870b},	/* Reset CTL3 */
 	{0x0020, 0x8112},	/* Video Drop packet enable */
-	{0x0003, 0x8111},  /* Soft Reset compression, memory, TG & CDSP */
+	{0x0003, 0x8111},	/* Soft Reset compression, memory, TG & CDSP */
 	{0x0000, 0x8110},	/* Disable everything */
 	{0x0000, 0x8114},	/* Software GPIO output data */
 	{0x0000, 0x8114},
 
 	{0x0003, 0x8111},
 	{0x0000, 0x8111},
-	{0x0090, 0x8110},  /* Enable: SSI output, External 2X clock output */
+	{0x0090, 0x8110},    /* Enable: SSI output, External 2X clock output */
 	{0x0020, 0x8112},
 	{0x0000, 0x8114},
 	{0x0001, 0x8114},
@@ -1129,191 +1043,143 @@
 	{0x00ba, 0x8804},	/* SSI Slave address */
 	{0x0010, 0x8802},	/* 93.75kHz SSI Clock Two DataByte */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},	/* Will write 2 bytes (DATA1+DATA2) */
 	{0x0020, 0x8801},	/* Register address for SSI read/write */
 	{0x0044, 0x8805},	/* DATA2 */
 	{0x0004, 0x8800},	/* DATA1 -> write triggered */
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0009, 0x8801},
 	{0x0042, 0x8805},
 	{0x0001, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x003c, 0x8801},
 	{0x0001, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0001, 0x8801},
 	{0x000a, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0002, 0x8801},
 	{0x0000, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0003, 0x8801},
 	{0x0027, 0x8805},
 	{0x0001, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0004, 0x8801},
 	{0x0065, 0x8805},
 	{0x0001, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0005, 0x8801},
 	{0x0003, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0006, 0x8801},
 	{0x001c, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0007, 0x8801},
 	{0x002a, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x000e, 0x8801},
 	{0x0000, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0028, 0x8801},
 	{0x002e, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0039, 0x8801},
 	{0x0013, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x003b, 0x8801},
 	{0x000c, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0035, 0x8801},
 	{0x0028, 0x8805},
 	{0x0000, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
-	/* READ { 0, 0x0001, 0x8802 } ->
-		0000: 10  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
+	/* READ { 0x0001, 0x8802 } -> 0000: 10  */
 	{0x0010, 0x8802},
 	{0x0009, 0x8801},
 	{0x0042, 0x8805},
 	{0x0001, 0x8800},
-	/* READ { 0, 0x0001, 0x8803 } ->
-		0000: 00  */
+	/* READ { 0x0001, 0x8803 } -> 0000: 00  */
 
 	{0x0050, 0x8703},
 	{0x0002, 0x8704},	/* External input CKIx1 */
 	{0x0001, 0x870c},	/* Select CKOx2 output */
 	{0x009a, 0x8600},	/* Line memory Read Counter (L) */
-	{0x0001, 0x8606},  /* 1 Line memory Read Counter (H) Result: (d)410 */
+	{0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
 	{0x0023, 0x8601},
 	{0x0010, 0x8602},
 	{0x000a, 0x8603},
-	{0x009A, 0x8600},
+	{0x009a, 0x8600},
 	{0x0001, 0x865b},	/* 1 Horizontal Offset for Valid Pixel(L) */
 	{0x0003, 0x865c},	/* Vertical offset for valid lines (L) */
 	{0x0058, 0x865d},	/* Horizontal valid pixels window (L) */
@@ -1329,7 +1195,7 @@
 	{0x0005, 0x860a},	/* ... */
 	{0x0025, 0x860b},
 	{0x00e1, 0x860c},
-	{0x00fa, 0x860D},
+	{0x00fa, 0x860d},
 	{0x00f4, 0x860e},
 	{0x00e8, 0x860f},
 	{0x0025, 0x8610},	/* A33 Coef. */
@@ -1344,11 +1210,12 @@
 	{0x0040, 0x8654},	/* Gb gain for white balance (L) */
 	{0x0001, 0x863f},	/* Enable fixed gamma correction */
 
-	{0x00a1, 0x8656},	/* Size - Window1: 256x256, Window2: 128x128 */
-	/* UV division: UV no change, Enable New edge enhancement */
+	{0x00a1, 0x8656},	/* Size - Window1: 256x256, Window2: 128x128,
+				 * UV division: UV no change,
+				 * Enable New edge enhancement */
 	{0x0018, 0x8657},	/* Edge gain high threshold */
 	{0x0020, 0x8658},	/* Edge gain low threshold */
-	{0x000A, 0x8659},	/* Edge bandwidth high threshold */
+	{0x000a, 0x8659},	/* Edge bandwidth high threshold */
 	{0x0005, 0x865a},	/* Edge bandwidth low threshold */
 	{0x0064, 0x8607},	/* UV filter enable */
 
@@ -1384,29 +1251,20 @@
 	{0x0000, 0x86b4},
 	{0x001e, 0x8660},
 
-	/* READ { 0, 0x0000, 0x8608 } ->
-		0000: 13  */
-	/* READ { 0, 0x0000, 0x8609 } ->
-		0000: 28  */
-	/* READ { 0, 0x0000, 0x8610 } ->
-		0000: 05  */
-	/* READ { 0, 0x0000, 0x8611 } ->
-		0000: 25  */
-	/* READ { 0, 0x0000, 0x8612 } ->
-		0000: e1  */
-	/* READ { 0, 0x0000, 0x8613 } ->
-		0000: fa  */
-	/* READ { 0, 0x0000, 0x8614 } ->
-		0000: f4  */
-	/* READ { 0, 0x0000, 0x8615 } ->
-		0000: e8  */
-	/* READ { 0, 0x0000, 0x8616 } ->
-		0000: 25  */
+	/* READ { 0x0000, 0x8608 } -> 0000: 13  */
+	/* READ { 0x0000, 0x8609 } -> 0000: 28  */
+	/* READ { 0x0000, 0x8610 } -> 0000: 05  */
+	/* READ { 0x0000, 0x8611 } -> 0000: 25  */
+	/* READ { 0x0000, 0x8612 } -> 0000: e1  */
+	/* READ { 0x0000, 0x8613 } -> 0000: fa  */
+	/* READ { 0x0000, 0x8614 } -> 0000: f4  */
+	/* READ { 0x0000, 0x8615 } -> 0000: e8  */
+	/* READ { 0x0000, 0x8616 } -> 0000: 25  */
 	{}
 };
 
 static int reg_write(struct usb_device *dev,
-			__u16 index, __u16 value)
+			u16 index, u16 value)
 {
 	int ret;
 
@@ -1425,7 +1283,7 @@
 /* read 1 byte */
 /* returns: negative is error, pos or zero is data */
 static int reg_read(struct gspca_dev *gspca_dev,
-			__u16 index)	/* wIndex */
+			u16 index)	/* wIndex */
 {
 	int ret;
 
@@ -1447,16 +1305,16 @@
 }
 
 static int write_vector(struct gspca_dev *gspca_dev,
-			const u16 data[][2])
+			const u16 (*data)[2])
 {
 	struct usb_device *dev = gspca_dev->dev;
-	int ret, i = 0;
+	int ret;
 
-	while (data[i][1] != 0) {
-		ret = reg_write(dev, data[i][1], data[i][0]);
+	while ((*data)[1] != 0) {
+		ret = reg_write(dev, (*data)[1], (*data)[0]);
 		if (ret < 0)
 			return ret;
-		i++;
+		data++;
 	}
 	return 0;
 }
@@ -1468,6 +1326,15 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam;
 	int data1, data2;
+	const u16 (*init_data)[2];
+	static const u16 (*(init_data_tb[]))[2] = {
+		spca508_vista_init_data,	/* CreativeVista 0 */
+		spca508_sightcam_init_data,	/* HamaUSBSightcam 1 */
+		spca508_sightcam2_init_data,	/* HamaUSBSightcam2 2 */
+		spca508cs110_init_data,		/* IntelEasyPCCamera 3 */
+		spca508cs110_init_data,		/* MicroInnovationIC200 4 */
+		spca508_init_data,		/* ViewQuestVQ110 5 */
+	};
 
 	/* Read from global register the USB product and vendor IDs, just to
 	 * prove that we can communicate with the device.  This works, which
@@ -1491,37 +1358,13 @@
 	sd->subtype = id->driver_info;
 	sd->brightness = BRIGHTNESS_DEF;
 
-	switch (sd->subtype) {
-	case ViewQuestVQ110:
-		if (write_vector(gspca_dev, spca508_init_data))
-			return -1;
-		break;
-	default:
-/*	case MicroInnovationIC200: */
-/*	case IntelEasyPCCamera: */
-		if (write_vector(gspca_dev, spca508cs110_init_data))
-			return -1;
-		break;
-	case HamaUSBSightcam:
-		if (write_vector(gspca_dev, spca508_sightcam_init_data))
-			return -1;
-		break;
-	case HamaUSBSightcam2:
-		if (write_vector(gspca_dev, spca508_sightcam2_init_data))
-			return -1;
-		break;
-	case CreativeVista:
-		if (write_vector(gspca_dev, spca508_vista_init_data))
-			return -1;
-		break;
-	}
-	return 0;			/* success */
+	init_data = init_data_tb[sd->subtype];
+	return write_vector(gspca_dev, init_data);
 }
 
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-/*	write_vector(gspca_dev, spca508_open_data); */
 	return 0;
 }
 
@@ -1529,7 +1372,7 @@
 {
 	int mode;
 
-	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 	reg_write(gspca_dev->dev, 0x8500, mode);
 	switch (mode) {
 	case 0:
@@ -1554,7 +1397,7 @@
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
-			__u8 *data,			/* isoc packet */
+			u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
 	switch (data[0]) {
@@ -1567,7 +1410,6 @@
 				data, len);
 		break;
 	case 0xff:			/* drop */
-/*		gspca_dev->last_packet_type = DISCARD_PACKET; */
 		break;
 	default:
 		data += 1;
@@ -1581,7 +1423,7 @@
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u8 brightness = sd->brightness;
+	u8 brightness = sd->brightness;
 
 	/* MX seem contrast */
 	reg_write(gspca_dev->dev, 0x8651, brightness);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca561.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca561.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/spca561.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/spca561.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,8 +34,8 @@
 
 	__u16 exposure;			/* rev12a only */
 #define EXPOSURE_MIN 1
-#define EXPOSURE_DEF 200
-#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */
+#define EXPOSURE_DEF 700		/* == 10 fps */
+#define EXPOSURE_MAX (2047 + 325)	/* see setexposure */
 
 	__u8 contrast;			/* rev72a only */
 #define CONTRAST_MIN 0x00
@@ -48,9 +48,9 @@
 #define BRIGHTNESS_MAX 0x3f
 
 	__u8 white;
-#define WHITE_MIN 1
-#define WHITE_DEF 0x40
-#define WHITE_MAX 0x7f
+#define HUE_MIN 1
+#define HUE_DEF 0x40
+#define HUE_MAX 0x7f
 
 	__u8 autogain;
 #define AUTOGAIN_MIN 0
@@ -58,9 +58,9 @@
 #define AUTOGAIN_MAX 1
 
 	__u8 gain;			/* rev12a only */
-#define GAIN_MIN 0x0
-#define GAIN_DEF 0x24
-#define GAIN_MAX 0x24
+#define GAIN_MIN 0
+#define GAIN_DEF 63
+#define GAIN_MAX 255
 
 #define EXPO12A_DEF 3
 	__u8 expo12a;		/* expo/gain? for rev 12a */
@@ -461,7 +461,7 @@
 	}
 	sd->brightness = BRIGHTNESS_DEF;
 	sd->contrast = CONTRAST_DEF;
-	sd->white = WHITE_DEF;
+	sd->white = HUE_DEF;
 	sd->exposure = EXPOSURE_DEF;
 	sd->autogain = AUTOGAIN_DEF;
 	sd->gain = GAIN_DEF;
@@ -549,8 +549,7 @@
 static void setexposure(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int expo;
-	int clock_divider;
+	int i, expo = 0;
 
 	/* Register 0x8309 controls exposure for the spca561,
 	   the basic exposure setting goes from 1-2047, where 1 is completely
@@ -564,16 +563,22 @@
 	   configure a divider for the base framerate which us used at the
 	   exposure setting of 1-300. These bits configure the base framerate
 	   according to the following formula: fps = 60 / (value + 2) */
-	if (sd->exposure < 2048) {
-		expo = sd->exposure;
-		clock_divider = 0;
-	} else {
-		/* Add 900 to make the 0 setting of the second part of the
-		   exposure equal to the 2047 setting of the first part. */
-		expo = (sd->exposure - 2048) + 900;
-		clock_divider = 3;
+
+	/* We choose to use the high bits setting the fixed framerate divisor
+	   asap, as setting high basic exposure setting without the fixed
+	   divider in combination with high gains makes the cam stop */
+	int table[] =  { 0, 450, 550, 625, EXPOSURE_MAX };
+
+	for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
+		if (sd->exposure <= table[i + 1]) {
+			expo  = sd->exposure - table[i];
+			if (i)
+				expo += 300;
+			expo |= i << 11;
+			break;
+		}
 	}
-	expo |= clock_divider << 11;
+
 	gspca_dev->usb_buf[0] = expo;
 	gspca_dev->usb_buf[1] = expo >> 8;
 	reg_w_buf(gspca_dev, 0x8309, 2);
@@ -584,7 +589,16 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	gspca_dev->usb_buf[0] = sd->gain;
+	/* gain reg low 6 bits  0-63 gain, bit 6 and 7, both double the
+	   sensitivity when set, so 31 + one of them set == 63, and 15
+	   with both of them set == 63 */
+	if (sd->gain < 64)
+		gspca_dev->usb_buf[0] = sd->gain;
+	else if (sd->gain < 128)
+		gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40;
+	else
+		gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0;
+
 	gspca_dev->usb_buf[1] = 0;
 	reg_w_buf(gspca_dev, 0x8335, 2);
 }
@@ -629,8 +643,7 @@
 	reg_w_buf(gspca_dev, 0x8391, 8);
 	reg_w_buf(gspca_dev, 0x8390, 8);
 	setwhite(gspca_dev);
-	setautogain(gspca_dev);
-/*	setgain(gspca_dev);		*/
+	setgain(gspca_dev);
 	setexposure(gspca_dev);
 	return 0;
 }
@@ -762,18 +775,6 @@
 			i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
 		}
 		break;
-	case Rev012A:
-		reg_r(gspca_dev, 0x8330, 2);
-		if (gspca_dev->usb_buf[1] > 0x08) {
-			gspca_dev->usb_buf[0] = ++sd->expo12a;
-			gspca_dev->usb_buf[1] = 0;
-			reg_w_buf(gspca_dev, 0x8339, 2);
-		} else if (gspca_dev->usb_buf[1] < 0x02) {
-			gspca_dev->usb_buf[0] = --sd->expo12a;
-			gspca_dev->usb_buf[1] = 0;
-			reg_w_buf(gspca_dev, 0x8339, 2);
-		}
-		break;
 	}
 }
 
@@ -928,13 +929,13 @@
 static struct ctrl sd_ctrls_12a[] = {
 	{
 	    {
-		.id = V4L2_CID_DO_WHITE_BALANCE,
+		.id = V4L2_CID_HUE,
 		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "White Balance",
-		.minimum = WHITE_MIN,
-		.maximum = WHITE_MAX,
+		.name = "Hue",
+		.minimum = HUE_MIN,
+		.maximum = HUE_MAX,
 		.step = 1,
-		.default_value = WHITE_DEF,
+		.default_value = HUE_DEF,
 	    },
 	    .set = sd_setwhite,
 	    .get = sd_getwhite,
@@ -954,19 +955,6 @@
 	},
 	{
 	    {
-		.id = V4L2_CID_AUTOGAIN,
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
-		.name = "Auto Gain",
-		.minimum = AUTOGAIN_MIN,
-		.maximum = AUTOGAIN_MAX,
-		.step = 1,
-		.default_value = AUTOGAIN_DEF,
-	    },
-	    .set = sd_setautogain,
-	    .get = sd_getautogain,
-	},
-	{
-	    {
 		.id = V4L2_CID_GAIN,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Gain",
@@ -983,13 +971,13 @@
 static struct ctrl sd_ctrls_72a[] = {
 	{
 	    {
-		.id = V4L2_CID_DO_WHITE_BALANCE,
+		.id = V4L2_CID_HUE,
 		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "White Balance",
-		.minimum = WHITE_MIN,
-		.maximum = WHITE_MAX,
+		.name = "Hue",
+		.minimum = HUE_MIN,
+		.maximum = HUE_MAX,
 		.step = 1,
-		.default_value = WHITE_DEF,
+		.default_value = HUE_DEF,
 	    },
 	    .set = sd_setwhite,
 	    .get = sd_getwhite,
@@ -1046,7 +1034,6 @@
 	.stopN = sd_stopN,
 	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
-/*	.dq_callback = do_autogain,	 * fixme */
 };
 static const struct sd_desc sd_desc_72a = {
 	.name = MODULE_NAME,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/sq905.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/sq905.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/sq905.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/sq905.c	2009-09-09 18:13:59.000000000 -0400
@@ -309,6 +309,7 @@
 	struct sd *dev = (struct sd *) gspca_dev;
 
 	/* We don't use the buffer gspca allocates so make it small. */
+	cam->bulk = 1;
 	cam->bulk_size = 64;
 
 	INIT_WORK(&dev->work_struct, sq905_dostream);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/sq905c.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/sq905c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/sq905c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/sq905c.c	2009-09-09 18:13:59.000000000 -0400
@@ -206,6 +206,7 @@
 		cam->nmodes = 1;
 	/* We don't use the buffer gspca allocates so make it small. */
 	cam->bulk_size = 32;
+	cam->bulk = 1;
 	INIT_WORK(&dev->work_struct, sq905c_dostream);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stk014.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/stk014.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stk014.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stk014.c	2009-09-09 18:13:59.000000000 -0400
@@ -333,6 +333,8 @@
 
 	/* create the JPEG header */
 	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (!sd->jpeg_hdr)
+		return -ENOMEM;
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x22);		/* JPEG 411 */
 	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/Makefile linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,8 @@
 gspca_stv06xx-objs := stv06xx.o \
 		      stv06xx_vv6410.o \
 		      stv06xx_hdcs.o \
-		      stv06xx_pb0100.o
+		      stv06xx_pb0100.o \
+		      stv06xx_st6422.o
 
 EXTRA_CFLAGS += -Idrivers/media/video/gspca
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -92,11 +92,10 @@
 {
 	int err = 0;
 
-	if (IS_850(sd)) {
+	if (sd->bridge == BRIDGE_STV610) {
 		struct usb_device *udev = sd->gspca_dev.dev;
 		__u8 *buf = sd->gspca_dev.usb_buf;
 
-		/* Quickam Web needs an extra packet */
 		buf[0] = 0;
 		err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				      0x04, 0x40, 0x1704, 0, buf, 1,
@@ -253,7 +252,7 @@
 
 	err = sd->sensor->init(sd);
 
-	if (dump_sensor)
+	if (dump_sensor && sd->sensor->dump)
 		sd->sensor->dump(sd);
 
 	return (err < 0) ? err : 0;
@@ -293,8 +292,6 @@
 		goto out;
 
 	err = sd->sensor->stop(sd);
-	if (err < 0)
-		goto out;
 
 out:
 	if (err < 0)
@@ -320,6 +317,8 @@
 			__u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+
 	PDEBUG(D_PACK, "Packet of length %d arrived", len);
 
 	/* A packet may contain several frames
@@ -345,14 +344,29 @@
 		if (len < chunk_len) {
 			PDEBUG(D_ERR, "URB packet length is smaller"
 				" than the specified chunk length");
+			gspca_dev->last_packet_type = DISCARD_PACKET;
 			return;
 		}
 
+		/* First byte seem to be 02=data 2nd byte is unknown??? */
+		if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200)
+			goto frame_data;
+
 		switch (id) {
 		case 0x0200:
 		case 0x4200:
+frame_data:
 			PDEBUG(D_PACK, "Frame data packet detected");
 
+			if (sd->to_skip) {
+				int skip = (sd->to_skip < chunk_len) ?
+					    sd->to_skip : chunk_len;
+				data += skip;
+				len -= skip;
+				chunk_len -= skip;
+				sd->to_skip -= skip;
+			}
+
 			gspca_frame_add(gspca_dev, INTER_PACKET, frame,
 					data, chunk_len);
 			break;
@@ -367,6 +381,9 @@
 			gspca_frame_add(gspca_dev, FIRST_PACKET,
 					frame, data, 0);
 
+			if (sd->bridge == BRIDGE_ST6422)
+				sd->to_skip = gspca_dev->width * 4;
+
 			if (chunk_len)
 				PDEBUG(D_ERR, "Chunk length is "
 					      "non-zero on a SOF");
@@ -397,8 +414,12 @@
 			/* Unknown chunk with 2 bytes of data,
 			   occurs 2-3 times per USB interrupt */
 			break;
+		case 0x42ff:
+			PDEBUG(D_PACK, "Chunk 0x42ff detected");
+			/* Special chunk seen sometimes on the ST6422 */
+			break;
 		default:
-			PDEBUG(D_PACK, "Unknown chunk %d detected", id);
+			PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
 			/* Unknown chunk */
 		}
 		data    += chunk_len;
@@ -430,11 +451,16 @@
 
 	cam = &gspca_dev->cam;
 	sd->desc = sd_desc;
+	sd->bridge = id->driver_info;
 	gspca_dev->sd_desc = &sd->desc;
 
 	if (dump_bridge)
 		stv06xx_dump_bridge(sd);
 
+	sd->sensor = &stv06xx_sensor_st6422;
+	if (!sd->sensor->probe(sd))
+		return 0;
+
 	sd->sensor = &stv06xx_sensor_vv6410;
 	if (!sd->sensor->probe(sd))
 		return 0;
@@ -459,9 +485,20 @@
 
 /* -- module initialisation -- */
 static const __devinitdata struct usb_device_id device_table[] = {
-	{USB_DEVICE(0x046d, 0x0840)}, /* QuickCam Express */
-	{USB_DEVICE(0x046d, 0x0850)}, /* LEGO cam / QuickCam Web */
-	{USB_DEVICE(0x046d, 0x0870)}, /* Dexxa WebCam USB */
+	/* QuickCam Express */
+	{USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
+	/* LEGO cam / QuickCam Web */
+	{USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
+	/* Dexxa WebCam USB */
+	{USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
+	/* QuickCam Messenger */
+	{USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
+	/* QuickCam Communicate */
+	{USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
+	/* QuickCam Messenger (new) */
+	{USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
+	/* QuickCam Messenger (new) */
+	{USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 },
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,10 +36,6 @@
 
 #define STV_ISOC_ENDPOINT_ADDR		0x81
 
-#ifndef V4L2_PIX_FMT_SGRBG8
-#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G')
-#endif
-
 #define STV_REG23 			0x0423
 
 /* Control registers of the STV0600 ASIC */
@@ -93,6 +89,17 @@
 
 	/* Sensor private data */
 	void *sensor_priv;
+
+	/* The first 4 lines produced by the stv6422 are no good, this keeps
+	   track of how many bytes we still need to skip during a frame */
+	int to_skip;
+
+	/* Bridge / Camera type */
+	u8 bridge;
+	#define BRIDGE_STV600 0
+	#define BRIDGE_STV602 1
+	#define BRIDGE_STV610 2
+	#define BRIDGE_ST6422 3 /* With integrated sensor */
 };
 
 int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,7 +64,7 @@
 	{
 		HDCS_1X00_DEF_WIDTH,
 		HDCS_1X00_DEF_HEIGHT,
-		V4L2_PIX_FMT_SBGGR8,
+		V4L2_PIX_FMT_SGRBG8,
 		V4L2_FIELD_NONE,
 		.sizeimage =
 			HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
@@ -80,7 +80,7 @@
 	{
 		HDCS_1020_DEF_WIDTH,
 		HDCS_1020_DEF_HEIGHT,
-		V4L2_PIX_FMT_SBGGR8,
+		V4L2_PIX_FMT_SGRBG8,
 		V4L2_FIELD_NONE,
 		.sizeimage =
 			HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
@@ -131,9 +131,11 @@
 		     (reg + len > 0xff)))
 		return -EINVAL;
 
-	for (i = 0; i < len; i++, reg++) {
-		regs[2*i] = reg;
-		regs[2*i+1] = vals[i];
+	for (i = 0; i < len; i++) {
+		regs[2 * i] = reg;
+		regs[2 * i + 1] = vals[i];
+		/* All addresses are shifted left one bit as bit 0 toggles r/w */
+		reg += 2;
 	}
 
 	return stv06xx_write_sensor_bytes(sd, regs, len);
@@ -174,7 +176,9 @@
 	}
 
 	ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
-	if (ret < 0)
+
+	/* Update the state if the write succeeded */
+	if (!ret)
 		hdcs->state = state;
 
 	return ret;
@@ -434,7 +438,7 @@
 	hdcs->exp.er = 100;
 
 	/*
-	 * Frame rate on HDCS-1000 0x46D:0x840 depends on PSMP:
+	 * Frame rate on HDCS-1000 with STV600 depends on PSMP:
 	 *  4 = doesn't work at all
 	 *  5 = 7.8 fps,
 	 *  6 = 6.9 fps,
@@ -443,7 +447,7 @@
 	 * 15 = 4.4 fps,
 	 * 31 = 2.8 fps
 	 *
-	 * Frame rate on HDCS-1000 0x46D:0x870 depends on PSMP:
+	 * Frame rate on HDCS-1000 with STV602 depends on PSMP:
 	 * 15 = doesn't work at all
 	 * 18 = doesn't work at all
 	 * 19 = 7.3 fps
@@ -453,7 +457,7 @@
 	 * 24 = 6.3 fps
 	 * 30 = 5.4 fps
 	 */
-	hdcs->psmp = IS_870(sd) ? 20 : 5;
+	hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
 
 	sd->sensor_priv = hdcs;
 
@@ -530,7 +534,7 @@
 	int i, err = 0;
 
 	/* Set the STV0602AA in STV0600 emulation mode */
-	if (IS_870(sd))
+	if (sd->bridge == BRIDGE_STV602)
 		stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
 
 	/* Execute the bridge init */
@@ -558,7 +562,7 @@
 		return err;
 
 	/* Set PGA sample duration
-	(was 0x7E for IS_870, but caused slow framerate with HDCS-1020) */
+	(was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
 	if (IS_1020(sd))
 		err = stv06xx_write_sensor(sd, HDCS_TCTRL,
 				(HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,14 +32,13 @@
 
 #include "stv06xx.h"
 
-#define IS_850(sd)	((sd)->gspca_dev.dev->descriptor.idProduct == 0x850)
-#define IS_870(sd)	((sd)->gspca_dev.dev->descriptor.idProduct == 0x870)
 #define IS_1020(sd)	((sd)->sensor == &stv06xx_sensor_hdcs1020)
 
 extern const struct stv06xx_sensor stv06xx_sensor_vv6410;
 extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00;
 extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
 extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
+extern const struct stv06xx_sensor stv06xx_sensor_st6422;
 
 struct stv06xx_sensor {
 	/* Defines the name of a sensor */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,453 @@
+/*
+ * Support for the sensor part which is integrated (I think) into the
+ * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
+ * but instead direct bridge writes.
+ *
+ * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Strongly based on qc-usb-messenger, which is:
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *		      Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ *
+ * 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 "stv06xx_st6422.h"
+
+static struct v4l2_pix_format st6422_mode[] = {
+	/* Note we actually get 124 lines of data, of which we skip the 4st
+	   4 as they are garbage */
+	{
+		162,
+		120,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.sizeimage = 162 * 120,
+		.bytesperline = 162,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1
+	},
+	/* Note we actually get 248 lines of data, of which we skip the 4st
+	   4 as they are garbage, and we tell the app it only gets the
+	   first 240 of the 244 lines it actually gets, so that it ignores
+	   the last 4. */
+	{
+		324,
+		240,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.sizeimage = 324 * 244,
+		.bytesperline = 324,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0
+	},
+};
+
+static const struct ctrl st6422_ctrl[] = {
+#define BRIGHTNESS_IDX 0
+	{
+		{
+			.id		= V4L2_CID_BRIGHTNESS,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Brightness",
+			.minimum	= 0,
+			.maximum	= 31,
+			.step		= 1,
+			.default_value  = 3
+		},
+		.set = st6422_set_brightness,
+		.get = st6422_get_brightness
+	},
+#define CONTRAST_IDX 1
+	{
+		{
+			.id		= V4L2_CID_CONTRAST,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Contrast",
+			.minimum	= 0,
+			.maximum	= 15,
+			.step		= 1,
+			.default_value  = 11
+		},
+		.set = st6422_set_contrast,
+		.get = st6422_get_contrast
+	},
+#define GAIN_IDX 2
+	{
+		{
+			.id		= V4L2_CID_GAIN,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Gain",
+			.minimum	= 0,
+			.maximum	= 255,
+			.step		= 1,
+			.default_value  = 64
+		},
+		.set = st6422_set_gain,
+		.get = st6422_get_gain
+	},
+#define EXPOSURE_IDX 3
+	{
+		{
+			.id		= V4L2_CID_EXPOSURE,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Exposure",
+			.minimum	= 0,
+			.maximum	= 1023,
+			.step		= 1,
+			.default_value  = 256
+		},
+		.set = st6422_set_exposure,
+		.get = st6422_get_exposure
+	},
+};
+
+static int st6422_probe(struct sd *sd)
+{
+	int i;
+	s32 *sensor_settings;
+
+	if (sd->bridge != BRIDGE_ST6422)
+		return -ENODEV;
+
+	info("st6422 sensor detected");
+
+	sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32),
+				  GFP_KERNEL);
+	if (!sensor_settings)
+		return -ENOMEM;
+
+	sd->gspca_dev.cam.cam_mode = st6422_mode;
+	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+	sd->desc.ctrls = st6422_ctrl;
+	sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
+	sd->sensor_priv = sensor_settings;
+
+	for (i = 0; i < sd->desc.nctrls; i++)
+		sensor_settings[i] = st6422_ctrl[i].qctrl.default_value;
+
+	return 0;
+}
+
+static int st6422_init(struct sd *sd)
+{
+	int err = 0, i;
+
+	const u16 st6422_bridge_init[][2] = {
+		{ STV_ISO_ENABLE, 0x00 }, /* disable capture */
+		{ 0x1436, 0x00 },
+		{ 0x1432, 0x03 },	/* 0x00-0x1F brightness */
+		{ 0x143a, 0xF9 },	/* 0x00-0x0F contrast */
+		{ 0x0509, 0x38 },	/* R */
+		{ 0x050a, 0x38 },	/* G */
+		{ 0x050b, 0x38 },	/* B */
+		{ 0x050c, 0x2A },
+		{ 0x050d, 0x01 },
+
+
+		{ 0x1431, 0x00 },	/* 0x00-0x07 ??? */
+		{ 0x1433, 0x34 },	/* 160x120, 0x00-0x01 night filter */
+		{ 0x1438, 0x18 },	/* 640x480 */
+/* 18 bayes */
+/* 10 compressed? */
+
+		{ 0x1439, 0x00 },
+/* antiflimmer??  0xa2 ger perfekt bild mot monitor */
+
+		{ 0x143b, 0x05 },
+		{ 0x143c, 0x00 },	/* 0x00-0x01 - ??? */
+
+
+/* shutter time 0x0000-0x03FF */
+/* low value  give good picures on moving objects (but requires much light) */
+/* high value gives good picures in darkness (but tends to be overexposed) */
+		{ 0x143e, 0x01 },
+		{ 0x143d, 0x00 },
+
+		{ 0x1442, 0xe2 },
+/* write: 1x1x xxxx */
+/* read:  1x1x xxxx */
+/*        bit 5 == button pressed and hold if 0 */
+/* write 0xe2,0xea */
+
+/* 0x144a */
+/* 0x00 init */
+/* bit 7 == button has been pressed, but not handled */
+
+/* interrupt */
+/* if(urb->iso_frame_desc[i].status == 0x80) { */
+/* if(urb->iso_frame_desc[i].status == 0x88) { */
+
+		{ 0x1500, 0xd0 },
+		{ 0x1500, 0xd0 },
+		{ 0x1500, 0x50 },	/* 0x00 - 0xFF  0x80 == compr ? */
+
+		{ 0x1501, 0xaf },
+/* high val-> ljus area blir morkare. */
+/* low val -> ljus area blir ljusare. */
+		{ 0x1502, 0xc2 },
+/* high val-> ljus area blir morkare. */
+/* low val -> ljus area blir ljusare. */
+		{ 0x1503, 0x45 },
+/* high val-> ljus area blir morkare. */
+/* low val -> ljus area blir ljusare. */
+
+		{ 0x1505, 0x02 },
+/* 2  : 324x248  80352 bytes */
+/* 7  : 248x162  40176 bytes */
+/* c+f: 162*124  20088 bytes */
+
+		{ 0x150e, 0x8e },
+		{ 0x150f, 0x37 },
+		{ 0x15c0, 0x00 },
+		{ 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
+		{ 0x15c3, 0x08 },	/* 0x04/0x14 ... test pictures ??? */
+
+
+		{ 0x143f, 0x01 },	/* commit settings */
+
+	};
+
+	for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
+		err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
+					       st6422_bridge_init[i][1]);
+	}
+
+	return err;
+}
+
+static void st6422_disconnect(struct sd *sd)
+{
+	sd->sensor = NULL;
+	kfree(sd->sensor_priv);
+}
+
+static int st6422_start(struct sd *sd)
+{
+	int err, packet_size;
+	struct cam *cam = &sd->gspca_dev.cam;
+	s32 *sensor_settings = sd->sensor_priv;
+	struct usb_host_interface *alt;
+	struct usb_interface *intf;
+
+	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+	if (!alt) {
+		PDEBUG(D_ERR, "Couldn't get altsetting");
+		return -EIO;
+	}
+
+	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+	err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
+	if (err < 0)
+		return err;
+
+	if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
+		err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
+	else
+		err = stv06xx_write_bridge(sd, 0x1505, 0x02);
+	if (err < 0)
+		return err;
+
+	err = st6422_set_brightness(&sd->gspca_dev,
+				    sensor_settings[BRIGHTNESS_IDX]);
+	if (err < 0)
+		return err;
+
+	err = st6422_set_contrast(&sd->gspca_dev,
+				  sensor_settings[CONTRAST_IDX]);
+	if (err < 0)
+		return err;
+
+	err = st6422_set_exposure(&sd->gspca_dev,
+				  sensor_settings[EXPOSURE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = st6422_set_gain(&sd->gspca_dev,
+			      sensor_settings[GAIN_IDX]);
+	if (err < 0)
+		return err;
+
+	PDEBUG(D_STREAM, "Starting stream");
+
+	return 0;
+}
+
+static int st6422_stop(struct sd *sd)
+{
+	PDEBUG(D_STREAM, "Halting stream");
+
+	return 0;
+}
+
+static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[BRIGHTNESS_IDX];
+
+	PDEBUG(D_V4L2, "Read brightness %d", *val);
+
+	return 0;
+}
+
+static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+	int err;
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[BRIGHTNESS_IDX] = val;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	/* val goes from 0 -> 31 */
+	PDEBUG(D_V4L2, "Set brightness to %d", val);
+	err = stv06xx_write_bridge(sd, 0x1432, val);
+	if (err < 0)
+		return err;
+
+	/* commit settings */
+	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+	return (err < 0) ? err : 0;
+}
+
+static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[CONTRAST_IDX];
+
+	PDEBUG(D_V4L2, "Read contrast %d", *val);
+
+	return 0;
+}
+
+static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val)
+{
+	int err;
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[CONTRAST_IDX] = val;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	/* Val goes from 0 -> 15 */
+	PDEBUG(D_V4L2, "Set contrast to %d\n", val);
+	err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val);
+	if (err < 0)
+		return err;
+
+	/* commit settings */
+	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+	return (err < 0) ? err : 0;
+}
+
+static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[GAIN_IDX];
+
+	PDEBUG(D_V4L2, "Read gain %d", *val);
+
+	return 0;
+}
+
+static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	int err;
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[GAIN_IDX] = val;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	PDEBUG(D_V4L2, "Set gain to %d", val);
+
+	/* Set red, green, blue, gain */
+	err = stv06xx_write_bridge(sd, 0x0509, val);
+	if (err < 0)
+		return err;
+
+	err = stv06xx_write_bridge(sd, 0x050a, val);
+	if (err < 0)
+		return err;
+
+	err = stv06xx_write_bridge(sd, 0x050b, val);
+	if (err < 0)
+		return err;
+
+	/* 2 mystery writes */
+	err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
+	if (err < 0)
+		return err;
+
+	err = stv06xx_write_bridge(sd, 0x050d, 0x01);
+	if (err < 0)
+		return err;
+
+	/* commit settings */
+	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+	return (err < 0) ? err : 0;
+}
+
+static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[EXPOSURE_IDX];
+
+	PDEBUG(D_V4L2, "Read exposure %d", *val);
+
+	return 0;
+}
+
+static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+	int err;
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[EXPOSURE_IDX] = val;
+
+	if (!gspca_dev->streaming)
+		return 0;
+
+	PDEBUG(D_V4L2, "Set exposure to %d\n", val);
+	err = stv06xx_write_bridge(sd, 0x143d, val & 0xff);
+	if (err < 0)
+		return err;
+
+	err = stv06xx_write_bridge(sd, 0x143e, val >> 8);
+	if (err < 0)
+		return err;
+
+	/* commit settings */
+	err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+	return (err < 0) ? err : 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Support for the sensor part which is integrated (I think) into the
+ * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
+ * but instead direct bridge writes.
+ *
+ * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Strongly based on qc-usb-messenger, which is:
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *		      Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ *
+ * 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 STV06XX_ST6422_H_
+#define STV06XX_ST6422_H_
+
+#include "stv06xx_sensor.h"
+
+static int st6422_probe(struct sd *sd);
+static int st6422_start(struct sd *sd);
+static int st6422_init(struct sd *sd);
+static int st6422_stop(struct sd *sd);
+static void st6422_disconnect(struct sd *sd);
+
+/* V4L2 controls supported by the driver */
+static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val);
+static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+
+const struct stv06xx_sensor stv06xx_sensor_st6422 = {
+	.name = "ST6422",
+	.init = st6422_init,
+	.probe = st6422_probe,
+	.start = st6422_start,
+	.stop = st6422_stop,
+	.disconnect = st6422_disconnect,
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c	2009-09-09 18:13:59.000000000 -0400
@@ -80,12 +80,26 @@
 			.minimum	= 0,
 			.maximum	= 15,
 			.step		= 1,
-			.default_value  = 0
+			.default_value  = 10
 		},
 		.set = vv6410_set_analog_gain,
 		.get = vv6410_get_analog_gain
+	},
+#define EXPOSURE_IDX 3
+	{
+		{
+			.id		= V4L2_CID_EXPOSURE,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "exposure",
+			.minimum	= 0,
+			.maximum	= 32768,
+			.step		= 1,
+			.default_value  = 20000
+		},
+		.set = vv6410_set_exposure,
+		.get = vv6410_get_exposure
 	}
-};
+	};
 
 static int vv6410_probe(struct sd *sd)
 {
@@ -121,6 +135,7 @@
 static int vv6410_init(struct sd *sd)
 {
 	int err = 0, i;
+	s32 *sensor_settings = sd->sensor_priv;
 
 	for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
 		/* if NULL then len contains single value */
@@ -142,6 +157,16 @@
 
 	err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
 					 ARRAY_SIZE(vv6410_sensor_init));
+	if (err < 0)
+		return err;
+
+	err = vv6410_set_exposure(&sd->gspca_dev,
+				   sensor_settings[EXPOSURE_IDX]);
+	if (err < 0)
+		return err;
+
+	err = vv6410_set_analog_gain(&sd->gspca_dev,
+				      sensor_settings[GAIN_IDX]);
 
 	return (err < 0) ? err : 0;
 }
@@ -318,3 +343,50 @@
 
 	return (err < 0) ? err : 0;
 }
+
+static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	*val = sensor_settings[EXPOSURE_IDX];
+
+	PDEBUG(D_V4L2, "Read exposure %d", *val);
+
+	return 0;
+}
+
+static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+	int err;
+	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+	unsigned int fine, coarse;
+
+	sensor_settings[EXPOSURE_IDX] = val;
+
+	val = (val * val >> 14) + val / 4;
+
+	fine = val % VV6410_CIF_LINELENGTH;
+	coarse = min(512, val / VV6410_CIF_LINELENGTH);
+
+	PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
+	       coarse, fine);
+
+	err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
+	if (err < 0)
+		goto out;
+
+	err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
+	if (err < 0)
+		goto out;
+
+	err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
+	if (err < 0)
+		goto out;
+
+	err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
+
+out:
+	return err;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h	2009-09-09 18:13:59.000000000 -0400
@@ -173,6 +173,8 @@
 #define VV6410_SUBSAMPLE		0x01
 #define VV6410_CROP_TO_QVGA		0x02
 
+#define VV6410_CIF_LINELENGTH		415
+
 static int vv6410_probe(struct sd *sd);
 static int vv6410_start(struct sd *sd);
 static int vv6410_init(struct sd *sd);
@@ -187,6 +189,8 @@
 static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
 static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val);
 static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
 
 const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
 	.name = "ST VV6410",
@@ -242,12 +246,6 @@
 	/* Pre-clock generator divide off */
 	{VV6410_DATAFORMAT,	BIT(7) | BIT(0)},
 
-	/* Exposure registers */
-	{VV6410_FINEH,		VV6410_FINE_EXPOSURE >> 8},
-	{VV6410_FINEL,		VV6410_FINE_EXPOSURE & 0xff},
-	{VV6410_COARSEH,	VV6410_COARSE_EXPOSURE >> 8},
-	{VV6410_COARSEL,	VV6410_COARSE_EXPOSURE & 0xff},
-	{VV6410_ANALOGGAIN,	0xf0 | VV6410_DEFAULT_GAIN},
 	{VV6410_CLKDIV,		VV6410_CLK_DIV_2},
 
 	/* System registers */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/sunplus.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/sunplus.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/sunplus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/sunplus.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,9 +32,6 @@
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
-	__u8 packet[ISO_MAX_SIZE + 128];
-				/* !! no more than 128 ff in an ISO packet */
-
 	unsigned char brightness;
 	unsigned char contrast;
 	unsigned char colors;
@@ -976,6 +973,8 @@
 
 	/* create the JPEG header */
 	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (!sd->jpeg_hdr)
+		return -ENOMEM;
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x22);		/* JPEG 411 */
 	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
@@ -1103,7 +1102,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i, sof = 0;
-	unsigned char *s, *d;
 	static unsigned char ffd9[] = {0xff, 0xd9};
 
 /* frames are jpeg 4.1.1 without 0xff escape */
@@ -1177,22 +1175,19 @@
 	}
 
 	/* add 0x00 after 0xff */
-	for (i = len; --i >= 0; )
-		if (data[i] == 0xff)
-			break;
-	if (i < 0) {			/* no 0xff */
-		gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
-		return;
-	}
-	s = data;
-	d = sd->packet;
-	for (i = 0; i < len; i++) {
-		*d++ = *s++;
-		if (s[-1] == 0xff)
-			*d++ = 0x00;
-	}
-	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-			sd->packet, d - sd->packet);
+	i = 0;
+	do {
+		if (data[i] == 0xff) {
+			gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+					data, i + 1);
+			len -= i;
+			data += i;
+			*data = 0x00;
+			i = 0;
+		}
+		i++;
+	} while (i < len);
+	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/t613.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/t613.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/t613.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/t613.c	2009-09-09 18:13:59.000000000 -0400
@@ -697,7 +697,7 @@
 		return -EINVAL;
 	}
 
-	if (sd->sensor != SENSOR_OTHER) {
+	if (sd->sensor == SENSOR_OM6802) {
 		reg_w_buf(gspca_dev, n1, sizeof n1);
 		i = 5;
 		while (--i >= 0) {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/vc032x.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/vc032x.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/vc032x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/vc032x.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,7 +42,7 @@
 	char bridge;
 #define BRIDGE_VC0321 0
 #define BRIDGE_VC0323 1
-	char sensor;
+	u8 sensor;
 #define SENSOR_HV7131R 0
 #define SENSOR_MI0360 1
 #define SENSOR_MI1310_SOC 2
@@ -159,17 +159,17 @@
 		.priv = 2},
 };
 static const struct v4l2_pix_format bi_mode[] = {
-	{320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+	{320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 320 * 240 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 2},
-	{640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+	{640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 		.bytesperline = 640,
 		.sizeimage = 640 * 480 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.priv = 1},
-	{1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+	{1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 		.bytesperline = 1280,
 		.sizeimage = 1280 * 1024 * 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
@@ -2453,6 +2453,17 @@
 	struct usb_device *dev = gspca_dev->dev;
 	struct cam *cam;
 	int sensor;
+	static u8 npkt[] = {	/* number of packets per ISOC message */
+		64,		/* HV7131R 0 */
+		32,		/* MI0360 1 */
+		32,		/* MI1310_SOC 2 */
+		64,		/* MI1320 3 */
+		128,		/* MI1320_SOC 4 */
+		32,		/* OV7660 5 */
+		64,		/* OV7670 6 */
+		128,		/* PO1200 7 */
+		128,		/* PO3130NC 8 */
+	};
 
 	cam = &gspca_dev->cam;
 	sd->bridge = id->driver_info;
@@ -2508,6 +2519,8 @@
 		case SENSOR_MI1320_SOC:
 			cam->cam_mode = bi_mode;
 			cam->nmodes = ARRAY_SIZE(bi_mode);
+			cam->input_flags = V4L2_IN_ST_VFLIP |
+					   V4L2_IN_ST_HFLIP;
 			break;
 		default:
 			cam->cam_mode = vc0323_mode;
@@ -2515,6 +2528,7 @@
 			break;
 		}
 	}
+	cam->npkt = npkt[sd->sensor];
 
 	sd->hflip = HFLIP_DEF;
 	sd->vflip = VFLIP_DEF;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/gspca/zc3xx.c linux-libre-2.6.31-gnu/drivers/media/video/gspca/zc3xx.c
--- linux-libre-2.6.30-gnu/drivers/media/video/gspca/zc3xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/gspca/zc3xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -6307,7 +6307,7 @@
 	retbyte = reg_r_i(gspca_dev, 0x0091);		/* read status */
 	retval = reg_r_i(gspca_dev, 0x0095);		/* read Lowbyte */
 	retval |= reg_r_i(gspca_dev, 0x0096) << 8;	/* read Hightbyte */
-	PDEBUG(D_USBO, "i2c r [%02x] -> %04x (%02x)",
+	PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)",
 			reg, retval, retbyte);
 	return retval;
 }
@@ -6868,7 +6868,6 @@
 	{0x8001, 0x13},
 	{0x8000, 0x14},		/* CS2102K */
 	{0x8400, 0x15},		/* TAS5130K */
-	{0x4001, 0x16},		/* ADCM2700 */
 };
 
 static int vga_3wr_probe(struct gspca_dev *gspca_dev)
@@ -6904,12 +6903,15 @@
 	retword |= reg_r(gspca_dev, 0x000a);
 	PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
 	reg_r(gspca_dev, 0x0010);
-	/* this is tested only once anyway */
-	for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
-		if (chipset_revision_sensor[i].revision == retword) {
-			sd->chip_revision = retword;
-			send_unknown(dev, SENSOR_PB0330);
-			return chipset_revision_sensor[i].internal_sensor_id;
+	/* value 0x4001 is meaningless */
+	if (retword != 0x4001) {
+		for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
+			if (chipset_revision_sensor[i].revision == retword) {
+				sd->chip_revision = retword;
+				send_unknown(dev, SENSOR_PB0330);
+				return chipset_revision_sensor[i]
+							.internal_sensor_id;
+			}
 		}
 	}
 
@@ -6980,12 +6982,12 @@
 	reg_w(dev, 0x01, 0x0001);
 	reg_w(dev, 0x03, 0x0012);
 	reg_w(dev, 0x01, 0x0012);
-	reg_w(dev, 0x05, 0x0001);
+	reg_w(dev, 0x05, 0x0012);
 	reg_w(dev, 0xd3, 0x008b);
 	retword = i2c_read(gspca_dev, 0x01);
 	if (retword != 0) {
 		PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
-		return retword;
+		return 0x16;			/* adcm2700 (6100/6200) */
 	}
 	return -1;
 }
@@ -7241,6 +7243,8 @@
 
 	/* create the JPEG header */
 	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	if (!sd->jpeg_hdr)
+		return -ENOMEM;
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x21);		/* JPEG 422 */
 	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/hdpvr/hdpvr-video.c linux-libre-2.6.31-gnu/drivers/media/video/hdpvr/hdpvr-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/hdpvr/hdpvr-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/hdpvr/hdpvr-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -181,7 +181,7 @@
 				 buff_list);
 		if (buf->status != BUFSTAT_AVAILABLE) {
 			v4l2_err(&dev->v4l2_dev,
-				 "buffer not marked as availbale\n");
+				 "buffer not marked as available\n");
 			ret = -EFAULT;
 			goto err;
 		}
@@ -1220,6 +1220,8 @@
 		V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I |
 		V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N |
 		V4L2_STD_PAL_60,
+	.current_norm 		= V4L2_STD_NTSC | V4L2_STD_PAL_M |
+		V4L2_STD_PAL_60,
 };
 
 int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/hexium_gemini.c linux-libre-2.6.31-gnu/drivers/media/video/hexium_gemini.c
--- linux-libre-2.6.30-gnu/drivers/media/video/hexium_gemini.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/hexium_gemini.c	2009-09-09 18:13:59.000000000 -0400
@@ -224,7 +224,7 @@
 {
 	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
 
-	if (i->index < 0 || i->index >= HEXIUM_INPUTS)
+	if (i->index >= HEXIUM_INPUTS)
 		return -EINVAL;
 
 	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/hexium_orion.c linux-libre-2.6.31-gnu/drivers/media/video/hexium_orion.c
--- linux-libre-2.6.30-gnu/drivers/media/video/hexium_orion.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/hexium_orion.c	2009-09-09 18:13:59.000000000 -0400
@@ -325,7 +325,7 @@
 {
 	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
 
-	if (i->index < 0 || i->index >= HEXIUM_INPUTS)
+	if (i->index >= HEXIUM_INPUTS)
 		return -EINVAL;
 
 	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ir-kbd-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/ir-kbd-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ir-kbd-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ir-kbd-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -74,7 +74,7 @@
 	int start, range, toggle, dev, code, ircode;
 
 	/* poll IR chip */
-	if (size != i2c_master_recv(&ir->c,buf,size))
+	if (size != i2c_master_recv(ir->c, buf, size))
 		return -EIO;
 
 	/* split rc5 data block ... */
@@ -137,7 +137,7 @@
 	unsigned char b;
 
 	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c,&b,1)) {
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
 		dprintk(1,"read error\n");
 		return -EIO;
 	}
@@ -151,7 +151,7 @@
 	unsigned char b;
 
 	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c,&b,1)) {
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
 		dprintk(1,"read error\n");
 		return -EIO;
 	}
@@ -171,7 +171,7 @@
 	unsigned char buf[4];
 
 	/* poll IR chip */
-	if (4 != i2c_master_recv(&ir->c,buf,4)) {
+	if (4 != i2c_master_recv(ir->c, buf, 4)) {
 		dprintk(1,"read error\n");
 		return -EIO;
 	}
@@ -195,7 +195,7 @@
 	unsigned char b;
 
 	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c,&b,1)) {
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
 		dprintk(1,"read error\n");
 		return -EIO;
 	}
@@ -222,12 +222,12 @@
 				     u32 *ir_key, u32 *ir_raw)
 {
 	unsigned char subaddr, key, keygroup;
-	struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
+	struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
 				   .buf = &subaddr, .len = 1},
-				 { .addr = ir->c.addr, .flags = I2C_M_RD,
+				 { .addr = ir->c->addr, .flags = I2C_M_RD,
 				  .buf = &key, .len = 1} };
 	subaddr = 0x0d;
-	if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+	if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
 		dprintk(1, "read error\n");
 		return -EIO;
 	}
@@ -237,7 +237,7 @@
 
 	subaddr = 0x0b;
 	msg[1].buf = &keygroup;
-	if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+	if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
 		dprintk(1, "read error\n");
 		return -EIO;
 	}
@@ -286,7 +286,7 @@
 
 	/* MSI TV@nywhere Plus requires more frequent polling
 	   otherwise it will miss some keypresses */
-	if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
+	if (ir->c->adapter->id == I2C_HW_SAA7134 && ir->c->addr == 0x30)
 		polling_interval = 50;
 
 	ir_key_poll(ir);
@@ -295,34 +295,15 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int ir_attach(struct i2c_adapter *adap, int addr,
-		      unsigned short flags, int kind);
-static int ir_detach(struct i2c_client *client);
-static int ir_probe(struct i2c_adapter *adap);
-
-static struct i2c_driver driver = {
-	.driver = {
-		.name   = "ir-kbd-i2c",
-	},
-	.id             = I2C_DRIVERID_INFRARED,
-	.attach_adapter = ir_probe,
-	.detach_client  = ir_detach,
-};
-
-static struct i2c_client client_template =
-{
-	.name = "unset",
-	.driver = &driver
-};
-
-static int ir_attach(struct i2c_adapter *adap, int addr,
-		     unsigned short flags, int kind)
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	IR_KEYTAB_TYPE *ir_codes = NULL;
-	char *name;
+	const char *name = NULL;
 	int ir_type;
 	struct IR_i2c *ir;
 	struct input_dev *input_dev;
+	struct i2c_adapter *adap = client->adapter;
+	unsigned short addr = client->addr;
 	int err;
 
 	ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
@@ -332,13 +313,9 @@
 		goto err_out_free;
 	}
 
-	ir->c = client_template;
+	ir->c = client;
 	ir->input = input_dev;
-
-	ir->c.adapter = adap;
-	ir->c.addr    = addr;
-
-	i2c_set_clientdata(&ir->c, ir);
+	i2c_set_clientdata(client, ir);
 
 	switch(addr) {
 	case 0x64:
@@ -403,44 +380,46 @@
 		ir_codes    = ir_codes_avermedia_cardbus;
 		break;
 	default:
-		/* shouldn't happen */
-		printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
+		dprintk(1, DEVNAME ": Unsupported i2c address 0x%02x\n", addr);
 		err = -ENODEV;
 		goto err_out_free;
 	}
 
-	/* Sets name */
-	snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
-	ir->ir_codes = ir_codes;
+	/* Let the caller override settings */
+	if (client->dev.platform_data) {
+		const struct IR_i2c_init_data *init_data =
+						client->dev.platform_data;
 
-	/* register i2c device
-	 * At device register, IR codes may be changed to be
-	 * board dependent.
-	 */
-	err = i2c_attach_client(&ir->c);
-	if (err)
-		goto err_out_free;
+		ir_codes = init_data->ir_codes;
+		name = init_data->name;
+		ir->get_key = init_data->get_key;
+	}
 
-	/* If IR not supported or disabled, unregisters driver */
-	if (ir->get_key == NULL) {
+	/* Make sure we are all setup before going on */
+	if (!name || !ir->get_key || !ir_codes) {
+		dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n",
+			addr);
 		err = -ENODEV;
-		goto err_out_detach;
+		goto err_out_free;
 	}
 
-	/* Phys addr can only be set after attaching (for ir->c.dev) */
+	/* Sets name */
+	snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name);
+	ir->ir_codes = ir_codes;
+
 	snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
-		 dev_name(&ir->c.adapter->dev),
-		 dev_name(&ir->c.dev));
+		 dev_name(&adap->dev),
+		 dev_name(&client->dev));
 
 	/* init + register input device */
 	ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
 	input_dev->id.bustype = BUS_I2C;
-	input_dev->name       = ir->c.name;
+	input_dev->name       = ir->name;
 	input_dev->phys       = ir->phys;
 
 	err = input_register_device(ir->input);
 	if (err)
-		goto err_out_detach;
+		goto err_out_free;
 
 	printk(DEVNAME ": %s detected at %s [%s]\n",
 	       ir->input->name, ir->input->phys, adap->name);
@@ -451,135 +430,42 @@
 
 	return 0;
 
- err_out_detach:
-	i2c_detach_client(&ir->c);
  err_out_free:
 	input_free_device(input_dev);
 	kfree(ir);
 	return err;
 }
 
-static int ir_detach(struct i2c_client *client)
+static int ir_remove(struct i2c_client *client)
 {
 	struct IR_i2c *ir = i2c_get_clientdata(client);
 
 	/* kill outstanding polls */
 	cancel_delayed_work_sync(&ir->work);
 
-	/* unregister devices */
+	/* unregister device */
 	input_unregister_device(ir->input);
-	i2c_detach_client(&ir->c);
 
 	/* free memory */
 	kfree(ir);
 	return 0;
 }
 
-static int ir_probe(struct i2c_adapter *adap)
-{
-
-	/* The external IR receiver is at i2c address 0x34 (0x35 for
-	   reads).  Future Hauppauge cards will have an internal
-	   receiver at 0x30 (0x31 for reads).  In theory, both can be
-	   fitted, and Hauppauge suggest an external overrides an
-	   internal.
-
-	   That's why we probe 0x1a (~0x34) first. CB
-	*/
-
-	static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
-	static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, 0x2d, -1 };
-	static const int probe_em28XX[] = { 0x30, 0x47, -1 };
-	static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
-	static const int probe_cx23885[] = { 0x6b, -1 };
-	const int *probe;
-	struct i2c_msg msg = {
-		.flags = I2C_M_RD,
-		.len = 0,
-		.buf = NULL,
-	};
-	int i, rc;
-
-	switch (adap->id) {
-	case I2C_HW_B_BT848:
-		probe = probe_bttv;
-		break;
-	case I2C_HW_B_CX2341X:
-		probe = probe_bttv;
-		break;
-	case I2C_HW_SAA7134:
-		probe = probe_saa7134;
-		break;
-	case I2C_HW_B_EM28XX:
-		probe = probe_em28XX;
-		break;
-	case I2C_HW_B_CX2388x:
-		probe = probe_cx88;
-		break;
-	case I2C_HW_B_CX23885:
-		probe = probe_cx23885;
-		break;
-	default:
-		return 0;
-	}
-
-	for (i = 0; -1 != probe[i]; i++) {
-		msg.addr = probe[i];
-		rc = i2c_transfer(adap, &msg, 1);
-		dprintk(1,"probe 0x%02x @ %s: %s\n",
-			probe[i], adap->name,
-			(1 == rc) ? "yes" : "no");
-		if (1 == rc) {
-			ir_attach(adap, probe[i], 0, 0);
-			return 0;
-		}
-	}
-
-	/* Special case for MSI TV@nywhere Plus remote */
-	if (adap->id == I2C_HW_SAA7134) {
-		u8 temp;
-
-		/* MSI TV@nywhere Plus controller doesn't seem to
-		   respond to probes unless we read something from
-		   an existing device. Weird... */
-
-		msg.addr = 0x50;
-		rc = i2c_transfer(adap, &msg, 1);
-			dprintk(1, "probe 0x%02x @ %s: %s\n",
-			msg.addr, adap->name,
-			(1 == rc) ? "yes" : "no");
-
-		/* Now do the probe. The controller does not respond
-		   to 0-byte reads, so we use a 1-byte read instead. */
-		msg.addr = 0x30;
-		msg.len = 1;
-		msg.buf = &temp;
-		rc = i2c_transfer(adap, &msg, 1);
-		dprintk(1, "probe 0x%02x @ %s: %s\n",
-			msg.addr, adap->name,
-			(1 == rc) ? "yes" : "no");
-		if (1 == rc)
-			ir_attach(adap, msg.addr, 0, 0);
-	}
-
-	/* Special case for AVerMedia Cardbus remote */
-	if (adap->id == I2C_HW_SAA7134) {
-		unsigned char subaddr, data;
-		struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0,
-					   .buf = &subaddr, .len = 1},
-					 { .addr = 0x40, .flags = I2C_M_RD,
-					   .buf = &data, .len = 1} };
-		subaddr = 0x0d;
-		rc = i2c_transfer(adap, msg, 2);
-		dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n",
-			msg[0].addr, subaddr, adap->name,
-			(2 == rc) ? "yes" : "no");
-		if (2 == rc)
-			ir_attach(adap, msg[0].addr, 0, 0);
-	}
+static const struct i2c_device_id ir_kbd_id[] = {
+	/* Generic entry for any IR receiver */
+	{ "ir_video", 0 },
+	/* IR device specific entries could be added here */
+	{ }
+};
 
-	return 0;
-}
+static struct i2c_driver driver = {
+	.driver = {
+		.name   = "ir-kbd-i2c",
+	},
+	.probe          = ir_probe,
+	.remove         = ir_remove,
+	.id_table       = ir_kbd_id,
+};
 
 /* ----------------------------------------------------------------------- */
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-controls.c linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-controls.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-controls.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-controls.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
     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 "ivtv-driver.h"
 #include "ivtv-cards.h"
@@ -60,6 +61,8 @@
 
 	switch (qctrl->id) {
 	/* Standard V4L2 controls */
+	case V4L2_CID_USER_CLASS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
 	case V4L2_CID_BRIGHTNESS:
 	case V4L2_CID_HUE:
 	case V4L2_CID_SATURATION:
@@ -279,7 +282,7 @@
 		idx = p.audio_properties & 0x03;
 		/* The audio clock of the digitizer must match the codec sample
 		   rate otherwise you get some very strange effects. */
-		if (idx < sizeof(freqs))
+		if (idx < ARRAY_SIZE(freqs))
 			ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
 		return err;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-driver.c linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-driver.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-driver.c	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-driver.c	2012-03-22 20:08:07.000000000 -0400
@@ -455,7 +455,7 @@
 			break;
 	}
 	if (tv.tuner_type == TUNER_ABSENT)
-		IVTV_ERR("tveeprom cannot autodetect tuner!");
+		IVTV_ERR("tveeprom cannot autodetect tuner!\n");
 
 	if (itv->options.tuner == -1)
 		itv->options.tuner = tv.tuner_type;
@@ -946,17 +946,14 @@
 	if (itv == NULL)
 		return -ENOMEM;
 	itv->pdev = pdev;
-	itv->instance = atomic_inc_return(&ivtv_instance) - 1;
+	itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv",
+						&ivtv_instance);
 
 	retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev);
 	if (retval) {
 		kfree(itv);
 		return retval;
 	}
-	/* "ivtv + PCI ID" is a bit of a mouthful, so use
-	   "ivtv + instance" instead. */
-	snprintf(itv->v4l2_dev.name, sizeof(itv->v4l2_dev.name),
-			"ivtv%d", itv->instance);
 	IVTV_INFO("Initializing card %d\n", itv->instance);
 
 	ivtv_process_options(itv);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -579,9 +579,11 @@
 	.name = "ivtv internal",
 };
 
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter + instantiate IR receiver */
 int init_ivtv_i2c(struct ivtv *itv)
 {
+	int retval;
+
 	IVTV_DEBUG_I2C("i2c init\n");
 
 	/* Sanity checks for the I2C hardware arrays. They must be the
@@ -619,9 +621,37 @@
 	ivtv_setsda(itv, 1);
 
 	if (itv->options.newi2c > 0)
-		return i2c_add_adapter(&itv->i2c_adap);
+		retval = i2c_add_adapter(&itv->i2c_adap);
 	else
-		return i2c_bit_add_bus(&itv->i2c_adap);
+		retval = i2c_bit_add_bus(&itv->i2c_adap);
+
+	/* Instantiate the IR receiver device, if present */
+	if (retval == 0) {
+		struct i2c_board_info info;
+		/* The external IR receiver is at i2c address 0x34 (0x35 for
+		   reads).  Future Hauppauge cards will have an internal
+		   receiver at 0x30 (0x31 for reads).  In theory, both can be
+		   fitted, and Hauppauge suggest an external overrides an
+		   internal.
+
+		   That's why we probe 0x1a (~0x34) first. CB
+		*/
+		const unsigned short addr_list[] = {
+			0x1a,	/* Hauppauge IR external */
+			0x18,	/* Hauppauge IR internal */
+			0x71,	/* Hauppauge IR (PVR150) */
+			0x64,	/* Pixelview IR */
+			0x30,	/* KNC ONE IR */
+			0x6b,	/* Adaptec IR */
+			I2C_CLIENT_END
+		};
+
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+		i2c_new_probed_device(&itv->i2c_adap, &info, addr_list);
+	}
+
+	return retval;
 }
 
 void exit_ivtv_i2c(struct ivtv *itv)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-ioctl.c linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-ioctl.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ivtv/ivtv-ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ivtv/ivtv-ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -709,7 +709,7 @@
 	else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
 			regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
 		reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
-	else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
+	else if (regs->reg < IVTV_ENCODER_SIZE)
 		reg_start = itv->enc_mem;
 	else
 		return -EINVAL;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/Kconfig linux-libre-2.6.31-gnu/drivers/media/video/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/video/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -312,6 +312,14 @@
 	  OV7670 VGA camera.  It currently only works with the M88ALP01
 	  controller.
 
+config VIDEO_MT9V011
+	tristate "Micron mt9v011 sensor support"
+	depends on I2C && VIDEO_V4L2
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Micron
+	  mt0v011 1.3 Mpixel camera.  It currently only works with the
+	  em28xx driver.
+
 config VIDEO_TCM825X
 	tristate "TCM825x camera sensor support"
 	depends on I2C && VIDEO_V4L2
@@ -440,6 +448,24 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called adv7175.
 
+config VIDEO_THS7303
+	tristate "THS7303 Video Amplifier"
+	depends on I2C
+	help
+	  Support for TI THS7303 video amplifier
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ths7303.
+
+config VIDEO_ADV7343
+	tristate "ADV7343 video encoder"
+	depends on I2C
+	help
+	  Support for Analog Devices I2C bus based ADV7343 encoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7343.
+
 comment "Video improvement chips"
 
 config VIDEO_UPD64031A
@@ -694,7 +720,7 @@
 
 config SOC_CAMERA
 	tristate "SoC camera support"
-	depends on VIDEO_V4L2 && HAS_DMA
+	depends on VIDEO_V4L2 && HAS_DMA && I2C
 	select VIDEOBUF_GEN
 	help
 	  SoC Camera is a common API to several cameras, not connecting
@@ -758,10 +784,14 @@
 	---help---
 	  This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface
 
+config MX3_VIDEO
+	bool
+
 config VIDEO_MX3
 	tristate "i.MX3x Camera Sensor Interface driver"
 	depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
 	select VIDEOBUF_DMA_CONTIG
+	select MX3_VIDEO
 	---help---
 	  This is a v4l2 driver for the i.MX3x Camera Sensor Interface
 
@@ -844,9 +874,13 @@
 	  module will be called w9968cf.
 
 config USB_OV511
-	tristate "USB OV511 Camera support"
+	tristate "USB OV511 Camera support (DEPRECATED)"
 	depends on VIDEO_V4L1
 	---help---
+	  This driver is DEPRECATED please use the gspca ov519 module
+	  instead. Note that for the ov511 / ov518 support of the gspca module
+	  you need atleast version 0.6.0 of libv4l.
+
 	  Say Y here if you want to connect this type of camera to your
 	  computer's USB port. See <file:Documentation/video4linux/ov511.txt>
 	  for more information and for a list of supported cameras.
@@ -886,6 +920,8 @@
 config USB_ZR364XX
 	tristate "USB ZR364XX Camera support"
 	depends on VIDEO_V4L2
+	select VIDEOBUF_GEN
+	select VIDEOBUF_VMALLOC
 	---help---
 	  Say Y here if you want to connect this type of camera to your
 	  computer's USB port.
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/Makefile linux-libre-2.6.31-gnu/drivers/media/video/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/video/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,8 @@
 
 videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o
 
+# V4L2 core modules
+
 obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
 ifeq ($(CONFIG_COMPAT),y)
   obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o
@@ -23,21 +25,15 @@
   obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
 endif
 
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+# All i2c modules must come first:
 
-obj-$(CONFIG_VIDEO_BT848) += bt8xx/
-obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
+obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
 obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
 obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
-
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
 obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
-obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
-obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
-obj-$(CONFIG_VIDEO_W9966) += w9966.o
-
 obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
 obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
 obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
@@ -49,16 +45,48 @@
 obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
+obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
 obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
 obj-$(CONFIG_VIDEO_BT819) += bt819.o
 obj-$(CONFIG_VIDEO_BT856) += bt856.o
 obj-$(CONFIG_VIDEO_BT866) += bt866.o
 obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
+obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
+obj-$(CONFIG_VIDEO_VINO) += indycam.o
+obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
+obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
+obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
+obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
+obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
+obj-$(CONFIG_VIDEO_M52790) += m52790.o
+obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
+obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
+obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
+obj-$(CONFIG_VIDEO_CX25840) += cx25840/
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
+obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
+obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
 
-obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m111.o
+obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o
+obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
+obj-$(CONFIG_SOC_CAMERA_TW9910)		+= tw9910.o
+
+# And now the v4l2 drivers:
 
+obj-$(CONFIG_VIDEO_BT848) += bt8xx/
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
+obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
+obj-$(CONFIG_VIDEO_W9966) += w9966.o
 obj-$(CONFIG_VIDEO_PMS) += pms.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o
 obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
 obj-$(CONFIG_VIDEO_CPIA) += cpia.o
 obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
@@ -69,17 +97,7 @@
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
-obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
-obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
-obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
-obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
-obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
-obj-$(CONFIG_VIDEO_M52790) += m52790.o
-obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
-obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
-obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
-obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
 obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
@@ -92,19 +110,12 @@
 obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
 obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
 obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
-obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
 
 obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
 
-obj-$(CONFIG_VIDEO_CX25840) += cx25840/
-obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
-obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 
 obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
-obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
-
-obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
 obj-$(CONFIG_USB_OV511)         += ov511.o
@@ -134,24 +145,21 @@
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
+obj-$(CONFIG_VIDEO_OMAP2)		+= omap2cam.o
+obj-$(CONFIG_SOC_CAMERA)		+= soc_camera.o
+obj-$(CONFIG_SOC_CAMERA_PLATFORM)	+= soc_camera_platform.o
+# soc-camera host drivers have to be linked after camera drivers
 obj-$(CONFIG_VIDEO_MX1)			+= mx1_camera.o
 obj-$(CONFIG_VIDEO_MX3)			+= mx3_camera.o
 obj-$(CONFIG_VIDEO_PXA27x)		+= pxa_camera.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o
-obj-$(CONFIG_VIDEO_OMAP2)		+= omap2cam.o
-obj-$(CONFIG_SOC_CAMERA)		+= soc_camera.o
-obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
-obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m111.o
-obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o
-obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
-obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
-obj-$(CONFIG_SOC_CAMERA_PLATFORM)	+= soc_camera_platform.o
-obj-$(CONFIG_SOC_CAMERA_TW9910)		+= tw9910.o
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828/
 
 obj-$(CONFIG_USB_VIDEO_CLASS)	+= uvc/
 
+obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mt9m001.c linux-libre-2.6.31-gnu/drivers/media/video/mt9m001.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mt9m001.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/mt9m001.c	2009-09-09 18:13:59.000000000 -0400
@@ -75,53 +75,50 @@
 	unsigned char autoexposure;
 };
 
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
 {
-	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
-	struct i2c_client *client = mt9m001->client;
 	s32 data = i2c_smbus_read_word_data(client, reg);
 	return data < 0 ? data : swab16(data);
 }
 
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
 		     const u16 data)
 {
-	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
-	return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
+	return i2c_smbus_write_word_data(client, reg, swab16(data));
 }
 
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
 		   const u16 data)
 {
 	int ret;
 
-	ret = reg_read(icd, reg);
+	ret = reg_read(client, reg);
 	if (ret < 0)
 		return ret;
-	return reg_write(icd, reg, ret | data);
+	return reg_write(client, reg, ret | data);
 }
 
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
 		     const u16 data)
 {
 	int ret;
 
-	ret = reg_read(icd, reg);
+	ret = reg_read(client, reg);
 	if (ret < 0)
 		return ret;
-	return reg_write(icd, reg, ret & ~data);
+	return reg_write(client, reg, ret & ~data);
 }
 
 static int mt9m001_init(struct soc_camera_device *icd)
 {
-	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
-	struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+	struct i2c_client *client = to_i2c_client(icd->control);
+	struct soc_camera_link *icl = client->dev.platform_data;
 	int ret;
 
 	dev_dbg(icd->vdev->parent, "%s\n", __func__);
 
 	if (icl->power) {
-		ret = icl->power(&mt9m001->client->dev, 1);
+		ret = icl->power(&client->dev, 1);
 		if (ret < 0) {
 			dev_err(icd->vdev->parent,
 				"Platform failed to power-on the camera.\n");
@@ -131,49 +128,53 @@
 
 	/* The camera could have been already on, we reset it additionally */
 	if (icl->reset)
-		ret = icl->reset(&mt9m001->client->dev);
+		ret = icl->reset(&client->dev);
 	else
 		ret = -ENODEV;
 
 	if (ret < 0) {
 		/* Either no platform reset, or platform reset failed */
-		ret = reg_write(icd, MT9M001_RESET, 1);
+		ret = reg_write(client, MT9M001_RESET, 1);
 		if (!ret)
-			ret = reg_write(icd, MT9M001_RESET, 0);
+			ret = reg_write(client, MT9M001_RESET, 0);
 	}
 	/* Disable chip, synchronous option update */
 	if (!ret)
-		ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+		ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
 
 	return ret;
 }
 
 static int mt9m001_release(struct soc_camera_device *icd)
 {
-	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
-	struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+	struct i2c_client *client = to_i2c_client(icd->control);
+	struct soc_camera_link *icl = client->dev.platform_data;
 
 	/* Disable the chip */
-	reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+	reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
 
 	if (icl->power)
-		icl->power(&mt9m001->client->dev, 0);
+		icl->power(&client->dev, 0);
 
 	return 0;
 }
 
 static int mt9m001_start_capture(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
+
 	/* Switch to master "normal" mode */
-	if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
+	if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
 		return -EIO;
 	return 0;
 }
 
 static int mt9m001_stop_capture(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
+
 	/* Stop sensor readout */
-	if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
+	if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
 		return -EIO;
 	return 0;
 }
@@ -222,28 +223,29 @@
 static int mt9m001_set_crop(struct soc_camera_device *icd,
 			    struct v4l2_rect *rect)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 	int ret;
 	const u16 hblank = 9, vblank = 25;
 
 	/* Blanking and start values - default... */
-	ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
+	ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
 	if (!ret)
-		ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
+		ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank);
 
 	/* The caller provides a supported format, as verified per
 	 * call to icd->try_fmt() */
 	if (!ret)
-		ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
+		ret = reg_write(client, MT9M001_COLUMN_START, rect->left);
 	if (!ret)
-		ret = reg_write(icd, MT9M001_ROW_START, rect->top);
+		ret = reg_write(client, MT9M001_ROW_START, rect->top);
 	if (!ret)
-		ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
+		ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect->width - 1);
 	if (!ret)
-		ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
+		ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
 				rect->height + icd->y_skip_top - 1);
 	if (!ret && mt9m001->autoexposure) {
-		ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
+		ret = reg_write(client, MT9M001_SHUTTER_WIDTH,
 				rect->height + icd->y_skip_top + vblank);
 		if (!ret) {
 			const struct v4l2_queryctrl *qctrl =
@@ -278,15 +280,9 @@
 {
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	if (pix->height < 32 + icd->y_skip_top)
-		pix->height = 32 + icd->y_skip_top;
-	if (pix->height > 1024 + icd->y_skip_top)
-		pix->height = 1024 + icd->y_skip_top;
-	if (pix->width < 48)
-		pix->width = 48;
-	if (pix->width > 1280)
-		pix->width = 1280;
-	pix->width &= ~0x01; /* has to be even, unsure why was ~3 */
+	v4l_bound_align_image(&pix->width, 48, 1280, 1,
+			      &pix->height, 32 + icd->y_skip_top,
+			      1024 + icd->y_skip_top, 0, 0);
 
 	return 0;
 }
@@ -312,16 +308,16 @@
 static int mt9m001_get_register(struct soc_camera_device *icd,
 				struct v4l2_dbg_register *reg)
 {
-	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 		return -EINVAL;
 
-	if (reg->match.addr != mt9m001->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
 	reg->size = 2;
-	reg->val = reg_read(icd, reg->reg);
+	reg->val = reg_read(client, reg->reg);
 
 	if (reg->val > 0xffff)
 		return -EIO;
@@ -332,15 +328,15 @@
 static int mt9m001_set_register(struct soc_camera_device *icd,
 				struct v4l2_dbg_register *reg)
 {
-	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 		return -EINVAL;
 
-	if (reg->match.addr != mt9m001->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
-	if (reg_write(icd, reg->reg, reg->val) < 0)
+	if (reg_write(client, reg->reg, reg->val) < 0)
 		return -EIO;
 
 	return 0;
@@ -416,12 +412,13 @@
 
 static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 	int data;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		data = reg_read(icd, MT9M001_READ_OPTIONS2);
+		data = reg_read(client, MT9M001_READ_OPTIONS2);
 		if (data < 0)
 			return -EIO;
 		ctrl->value = !!(data & 0x8000);
@@ -435,6 +432,7 @@
 
 static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 	const struct v4l2_queryctrl *qctrl;
 	int data;
@@ -447,9 +445,9 @@
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
 		if (ctrl->value)
-			data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
+			data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000);
 		else
-			data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
+			data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000);
 		if (data < 0)
 			return -EIO;
 		break;
@@ -463,7 +461,7 @@
 			data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
 
 			dev_dbg(&icd->dev, "Setting gain %d\n", data);
-			data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+			data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
 			if (data < 0)
 				return -EIO;
 		} else {
@@ -481,8 +479,8 @@
 				data = ((gain - 64) * 7 + 28) / 56 + 96;
 
 			dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
-				 reg_read(icd, MT9M001_GLOBAL_GAIN), data);
-			data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+				 reg_read(client, MT9M001_GLOBAL_GAIN), data);
+			data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
 			if (data < 0)
 				return -EIO;
 		}
@@ -500,8 +498,8 @@
 						 range / 2) / range + 1;
 
 			dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
-				 reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
-			if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
+				 reg_read(client, MT9M001_SHUTTER_WIDTH), shutter);
+			if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
 				return -EIO;
 			icd->exposure = ctrl->value;
 			mt9m001->autoexposure = 0;
@@ -510,7 +508,7 @@
 	case V4L2_CID_EXPOSURE_AUTO:
 		if (ctrl->value) {
 			const u16 vblank = 25;
-			if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
+			if (reg_write(client, MT9M001_SHUTTER_WIDTH, icd->height +
 				      icd->y_skip_top + vblank) < 0)
 				return -EIO;
 			qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
@@ -529,8 +527,9 @@
  * this wasn't our capture interface, so, we wait for the right one */
 static int mt9m001_video_probe(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
-	struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+	struct soc_camera_link *icl = client->dev.platform_data;
 	s32 data;
 	int ret;
 	unsigned long flags;
@@ -542,11 +541,11 @@
 		return -ENODEV;
 
 	/* Enable the chip */
-	data = reg_write(icd, MT9M001_CHIP_ENABLE, 1);
+	data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
 	dev_dbg(&icd->dev, "write: %d\n", data);
 
 	/* Read out the chip version register */
-	data = reg_read(icd, MT9M001_CHIP_VERSION);
+	data = reg_read(client, MT9M001_CHIP_VERSION);
 
 	/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
 	switch (data) {
@@ -604,10 +603,13 @@
 static void mt9m001_video_remove(struct soc_camera_device *icd)
 {
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+	struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
 
 	dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
 		icd->dev.parent, icd->vdev);
 	soc_camera_video_stop(icd);
+	if (icl->free_bus)
+		icl->free_bus(icl);
 }
 
 static int mt9m001_probe(struct i2c_client *client,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mt9m111.c linux-libre-2.6.31-gnu/drivers/media/video/mt9m111.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mt9m111.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/mt9m111.c	2009-09-09 18:13:59.000000000 -0400
@@ -113,10 +113,10 @@
  * mt9m111: Camera control register addresses (0x200..0x2ff not implemented)
  */
 
-#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg)
-#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val))
-#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val))
-#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val))
+#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg)
+#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val))
+#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val))
+#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val))
 
 #define MT9M111_MIN_DARK_ROWS	8
 #define MT9M111_MIN_DARK_COLS	24
@@ -184,58 +184,55 @@
 	return ret;
 }
 
-static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg)
+static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)
 {
-	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
-	struct i2c_client *client = mt9m111->client;
 	int ret;
 
 	ret = reg_page_map_set(client, reg);
 	if (!ret)
 		ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff)));
 
-	dev_dbg(&icd->dev, "read  reg.%03x -> %04x\n", reg, ret);
+	dev_dbg(&client->dev, "read  reg.%03x -> %04x\n", reg, ret);
 	return ret;
 }
 
-static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
 			     const u16 data)
 {
-	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
-	struct i2c_client *client = mt9m111->client;
 	int ret;
 
 	ret = reg_page_map_set(client, reg);
 	if (!ret)
-		ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff),
+		ret = i2c_smbus_write_word_data(client, (reg & 0xff),
 						swab16(data));
-	dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
+	dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
 	return ret;
 }
 
-static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_set(struct i2c_client *client, const u16 reg,
 			   const u16 data)
 {
 	int ret;
 
-	ret = mt9m111_reg_read(icd, reg);
+	ret = mt9m111_reg_read(client, reg);
 	if (ret >= 0)
-		ret = mt9m111_reg_write(icd, reg, ret | data);
+		ret = mt9m111_reg_write(client, reg, ret | data);
 	return ret;
 }
 
-static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
 			     const u16 data)
 {
 	int ret;
 
-	ret = mt9m111_reg_read(icd, reg);
-	return mt9m111_reg_write(icd, reg, ret & ~data);
+	ret = mt9m111_reg_read(client, reg);
+	return mt9m111_reg_write(client, reg, ret & ~data);
 }
 
 static int mt9m111_set_context(struct soc_camera_device *icd,
 			       enum mt9m111_context ctxt)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
 		| MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
 		| MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
@@ -252,6 +249,7 @@
 static int mt9m111_setup_rect(struct soc_camera_device *icd,
 			      struct v4l2_rect *rect)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 	int ret, is_raw_format;
 	int width = rect->width;
@@ -296,6 +294,7 @@
 
 static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	int ret;
 
 	ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
@@ -357,12 +356,13 @@
 
 static int mt9m111_enable(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
-	struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+	struct soc_camera_link *icl = client->dev.platform_data;
 	int ret;
 
 	if (icl->power) {
-		ret = icl->power(&mt9m111->client->dev, 1);
+		ret = icl->power(&client->dev, 1);
 		if (ret < 0) {
 			dev_err(icd->vdev->parent,
 				"Platform failed to power-on the camera.\n");
@@ -378,8 +378,9 @@
 
 static int mt9m111_disable(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
-	struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+	struct soc_camera_link *icl = client->dev.platform_data;
 	int ret;
 
 	ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
@@ -387,15 +388,15 @@
 		mt9m111->powered = 0;
 
 	if (icl->power)
-		icl->power(&mt9m111->client->dev, 0);
+		icl->power(&client->dev, 0);
 
 	return ret;
 }
 
 static int mt9m111_reset(struct soc_camera_device *icd)
 {
-	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
-	struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+	struct i2c_client *client = to_i2c_client(icd->control);
+	struct soc_camera_link *icl = client->dev.platform_data;
 	int ret;
 
 	ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
@@ -406,7 +407,7 @@
 				| MT9M111_RESET_RESET_SOC);
 
 	if (icl->reset)
-		icl->reset(&mt9m111->client->dev);
+		icl->reset(&client->dev);
 
 	return ret;
 }
@@ -562,15 +563,14 @@
 				struct v4l2_dbg_register *reg)
 {
 	int val;
-
-	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
 		return -EINVAL;
-	if (reg->match.addr != mt9m111->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
-	val = mt9m111_reg_read(icd, reg->reg);
+	val = mt9m111_reg_read(client, reg->reg);
 	reg->size = 2;
 	reg->val = (u64)val;
 
@@ -583,15 +583,15 @@
 static int mt9m111_set_register(struct soc_camera_device *icd,
 				struct v4l2_dbg_register *reg)
 {
-	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
 		return -EINVAL;
 
-	if (reg->match.addr != mt9m111->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
-	if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0)
+	if (mt9m111_reg_write(client, reg->reg, reg->val) < 0)
 		return -EIO;
 
 	return 0;
@@ -672,6 +672,7 @@
 
 static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 	int ret;
 
@@ -692,6 +693,7 @@
 
 static int mt9m111_get_global_gain(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	int data;
 
 	data = reg_read(GLOBAL_GAIN);
@@ -703,6 +705,7 @@
 
 static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	u16 val;
 
 	if (gain > 63 * 2 * 2)
@@ -721,6 +724,7 @@
 
 static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 	int ret;
 
@@ -737,6 +741,7 @@
 
 static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 	int ret;
 
@@ -754,6 +759,7 @@
 static int mt9m111_get_control(struct soc_camera_device *icd,
 			       struct v4l2_control *ctrl)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 	int data;
 
@@ -898,6 +904,7 @@
  */
 static int mt9m111_video_probe(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 	s32 data;
 	int ret;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mt9t031.c linux-libre-2.6.31-gnu/drivers/media/video/mt9t031.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mt9t031.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/mt9t031.c	2009-09-09 18:13:59.000000000 -0400
@@ -76,64 +76,61 @@
 	u16 yskip;
 };
 
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
 {
-	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
-	struct i2c_client *client = mt9t031->client;
 	s32 data = i2c_smbus_read_word_data(client, reg);
 	return data < 0 ? data : swab16(data);
 }
 
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
 		     const u16 data)
 {
-	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
-	return i2c_smbus_write_word_data(mt9t031->client, reg, swab16(data));
+	return i2c_smbus_write_word_data(client, reg, swab16(data));
 }
 
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
 		   const u16 data)
 {
 	int ret;
 
-	ret = reg_read(icd, reg);
+	ret = reg_read(client, reg);
 	if (ret < 0)
 		return ret;
-	return reg_write(icd, reg, ret | data);
+	return reg_write(client, reg, ret | data);
 }
 
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
 		     const u16 data)
 {
 	int ret;
 
-	ret = reg_read(icd, reg);
+	ret = reg_read(client, reg);
 	if (ret < 0)
 		return ret;
-	return reg_write(icd, reg, ret & ~data);
+	return reg_write(client, reg, ret & ~data);
 }
 
-static int set_shutter(struct soc_camera_device *icd, const u32 data)
+static int set_shutter(struct i2c_client *client, const u32 data)
 {
 	int ret;
 
-	ret = reg_write(icd, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
+	ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
 
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_SHUTTER_WIDTH, data & 0xffff);
+		ret = reg_write(client, MT9T031_SHUTTER_WIDTH, data & 0xffff);
 
 	return ret;
 }
 
-static int get_shutter(struct soc_camera_device *icd, u32 *data)
+static int get_shutter(struct i2c_client *client, u32 *data)
 {
 	int ret;
 
-	ret = reg_read(icd, MT9T031_SHUTTER_WIDTH_UPPER);
+	ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER);
 	*data = ret << 16;
 
 	if (ret >= 0)
-		ret = reg_read(icd, MT9T031_SHUTTER_WIDTH);
+		ret = reg_read(client, MT9T031_SHUTTER_WIDTH);
 	*data |= ret & 0xffff;
 
 	return ret < 0 ? ret : 0;
@@ -141,12 +138,12 @@
 
 static int mt9t031_init(struct soc_camera_device *icd)
 {
-	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
-	struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+	struct i2c_client *client = to_i2c_client(icd->control);
+	struct soc_camera_link *icl = client->dev.platform_data;
 	int ret;
 
 	if (icl->power) {
-		ret = icl->power(&mt9t031->client->dev, 1);
+		ret = icl->power(&client->dev, 1);
 		if (ret < 0) {
 			dev_err(icd->vdev->parent,
 				"Platform failed to power-on the camera.\n");
@@ -155,44 +152,48 @@
 	}
 
 	/* Disable chip output, synchronous option update */
-	ret = reg_write(icd, MT9T031_RESET, 1);
+	ret = reg_write(client, MT9T031_RESET, 1);
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_RESET, 0);
+		ret = reg_write(client, MT9T031_RESET, 0);
 	if (ret >= 0)
-		ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
+		ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
 
 	if (ret < 0 && icl->power)
-		icl->power(&mt9t031->client->dev, 0);
+		icl->power(&client->dev, 0);
 
 	return ret >= 0 ? 0 : -EIO;
 }
 
 static int mt9t031_release(struct soc_camera_device *icd)
 {
-	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
-	struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+	struct i2c_client *client = to_i2c_client(icd->control);
+	struct soc_camera_link *icl = client->dev.platform_data;
 
 	/* Disable the chip */
-	reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
+	reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
 
 	if (icl->power)
-		icl->power(&mt9t031->client->dev, 0);
+		icl->power(&client->dev, 0);
 
 	return 0;
 }
 
 static int mt9t031_start_capture(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
+
 	/* Switch to master "normal" mode */
-	if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
+	if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
 		return -EIO;
 	return 0;
 }
 
 static int mt9t031_stop_capture(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
+
 	/* Stop sensor readout */
-	if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
+	if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
 		return -EIO;
 	return 0;
 }
@@ -200,14 +201,16 @@
 static int mt9t031_set_bus_param(struct soc_camera_device *icd,
 				 unsigned long flags)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
+
 	/* The caller should have queried our parameters, check anyway */
 	if (flags & ~MT9T031_BUS_PARAM)
 		return -EINVAL;
 
 	if (flags & SOCAM_PCLK_SAMPLE_FALLING)
-		reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+		reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
 	else
-		reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+		reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
 
 	return 0;
 }
@@ -235,6 +238,7 @@
 static int mt9t031_set_params(struct soc_camera_device *icd,
 			      struct v4l2_rect *rect, u16 xskip, u16 yskip)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 	int ret;
 	u16 xbin, ybin, width, height, left, top;
@@ -277,22 +281,22 @@
 	}
 
 	/* Disable register update, reconfigure atomically */
-	ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1);
+	ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1);
 	if (ret < 0)
 		return ret;
 
 	/* Blanking and start values - default... */
-	ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank);
+	ret = reg_write(client, MT9T031_HORIZONTAL_BLANKING, hblank);
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank);
+		ret = reg_write(client, MT9T031_VERTICAL_BLANKING, vblank);
 
 	if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) {
 		/* Binning, skipping */
 		if (ret >= 0)
-			ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE,
+			ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE,
 					((xbin - 1) << 4) | (xskip - 1));
 		if (ret >= 0)
-			ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE,
+			ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
 					((ybin - 1) << 4) | (yskip - 1));
 	}
 	dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top);
@@ -300,16 +304,16 @@
 	/* The caller provides a supported format, as guaranteed by
 	 * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_COLUMN_START, left);
+		ret = reg_write(client, MT9T031_COLUMN_START, left);
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_ROW_START, top);
+		ret = reg_write(client, MT9T031_ROW_START, top);
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1);
+		ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1);
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_WINDOW_HEIGHT,
+		ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
 				height + icd->y_skip_top - 1);
 	if (ret >= 0 && mt9t031->autoexposure) {
-		ret = set_shutter(icd, height + icd->y_skip_top + vblank);
+		ret = set_shutter(client, height + icd->y_skip_top + vblank);
 		if (ret >= 0) {
 			const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
 			const struct v4l2_queryctrl *qctrl =
@@ -324,7 +328,7 @@
 
 	/* Re-enable register update, commit all changes */
 	if (ret >= 0)
-		ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1);
+		ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1);
 
 	return ret < 0 ? ret : 0;
 }
@@ -381,17 +385,9 @@
 {
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	if (pix->height < MT9T031_MIN_HEIGHT)
-		pix->height = MT9T031_MIN_HEIGHT;
-	if (pix->height > MT9T031_MAX_HEIGHT)
-		pix->height = MT9T031_MAX_HEIGHT;
-	if (pix->width < MT9T031_MIN_WIDTH)
-		pix->width = MT9T031_MIN_WIDTH;
-	if (pix->width > MT9T031_MAX_WIDTH)
-		pix->width = MT9T031_MAX_WIDTH;
-
-	pix->width &= ~0x01; /* has to be even */
-	pix->height &= ~0x01; /* has to be even */
+	v4l_bound_align_image(
+		&pix->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
+		&pix->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
 
 	return 0;
 }
@@ -417,15 +413,15 @@
 static int mt9t031_get_register(struct soc_camera_device *icd,
 				struct v4l2_dbg_register *reg)
 {
-	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 		return -EINVAL;
 
-	if (reg->match.addr != mt9t031->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
-	reg->val = reg_read(icd, reg->reg);
+	reg->val = reg_read(client, reg->reg);
 
 	if (reg->val > 0xffff)
 		return -EIO;
@@ -436,15 +432,15 @@
 static int mt9t031_set_register(struct soc_camera_device *icd,
 				struct v4l2_dbg_register *reg)
 {
-	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 		return -EINVAL;
 
-	if (reg->match.addr != mt9t031->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
-	if (reg_write(icd, reg->reg, reg->val) < 0)
+	if (reg_write(client, reg->reg, reg->val) < 0)
 		return -EIO;
 
 	return 0;
@@ -528,18 +524,19 @@
 
 static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 	int data;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		data = reg_read(icd, MT9T031_READ_MODE_2);
+		data = reg_read(client, MT9T031_READ_MODE_2);
 		if (data < 0)
 			return -EIO;
 		ctrl->value = !!(data & 0x8000);
 		break;
 	case V4L2_CID_HFLIP:
-		data = reg_read(icd, MT9T031_READ_MODE_2);
+		data = reg_read(client, MT9T031_READ_MODE_2);
 		if (data < 0)
 			return -EIO;
 		ctrl->value = !!(data & 0x4000);
@@ -553,6 +550,7 @@
 
 static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 	const struct v4l2_queryctrl *qctrl;
 	int data;
@@ -565,17 +563,17 @@
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
 		if (ctrl->value)
-			data = reg_set(icd, MT9T031_READ_MODE_2, 0x8000);
+			data = reg_set(client, MT9T031_READ_MODE_2, 0x8000);
 		else
-			data = reg_clear(icd, MT9T031_READ_MODE_2, 0x8000);
+			data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000);
 		if (data < 0)
 			return -EIO;
 		break;
 	case V4L2_CID_HFLIP:
 		if (ctrl->value)
-			data = reg_set(icd, MT9T031_READ_MODE_2, 0x4000);
+			data = reg_set(client, MT9T031_READ_MODE_2, 0x4000);
 		else
-			data = reg_clear(icd, MT9T031_READ_MODE_2, 0x4000);
+			data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000);
 		if (data < 0)
 			return -EIO;
 		break;
@@ -589,7 +587,7 @@
 			data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
 
 			dev_dbg(&icd->dev, "Setting gain %d\n", data);
-			data = reg_write(icd, MT9T031_GLOBAL_GAIN, data);
+			data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
 			if (data < 0)
 				return -EIO;
 		} else {
@@ -609,8 +607,8 @@
 				data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60;
 
 			dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n",
-				reg_read(icd, MT9T031_GLOBAL_GAIN), data);
-			data = reg_write(icd, MT9T031_GLOBAL_GAIN, data);
+				reg_read(client, MT9T031_GLOBAL_GAIN), data);
+			data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
 			if (data < 0)
 				return -EIO;
 		}
@@ -628,10 +626,10 @@
 					     range / 2) / range + 1;
 			u32 old;
 
-			get_shutter(icd, &old);
+			get_shutter(client, &old);
 			dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n",
 				old, shutter);
-			if (set_shutter(icd, shutter) < 0)
+			if (set_shutter(client, shutter) < 0)
 				return -EIO;
 			icd->exposure = ctrl->value;
 			mt9t031->autoexposure = 0;
@@ -641,7 +639,7 @@
 		if (ctrl->value) {
 			const u16 vblank = MT9T031_VERTICAL_BLANK;
 			const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
-			if (set_shutter(icd, icd->height +
+			if (set_shutter(client, icd->height +
 					icd->y_skip_top + vblank) < 0)
 				return -EIO;
 			qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
@@ -661,6 +659,7 @@
  * this wasn't our capture interface, so, we wait for the right one */
 static int mt9t031_video_probe(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 	s32 data;
 	int ret;
@@ -672,11 +671,11 @@
 		return -ENODEV;
 
 	/* Enable the chip */
-	data = reg_write(icd, MT9T031_CHIP_ENABLE, 1);
+	data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
 	dev_dbg(&icd->dev, "write: %d\n", data);
 
 	/* Read out the chip version register */
-	data = reg_read(icd, MT9T031_CHIP_VERSION);
+	data = reg_read(client, MT9T031_CHIP_VERSION);
 
 	switch (data) {
 	case 0x1621:
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mt9v011.c linux-libre-2.6.31-gnu/drivers/media/video/mt9v011.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mt9v011.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/mt9v011.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,634 @@
+/*
+ * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
+ *
+ * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+#include <media/v4l2-device.h>
+#include "mt9v011.h"
+#include <media/v4l2-i2c-drv.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("Micron mt9v011 sensor driver");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+/* supported controls */
+static struct v4l2_queryctrl mt9v011_qctrl[] = {
+	{
+		.id = V4L2_CID_GAIN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Gain",
+		.minimum = 0,
+		.maximum = (1 << 10) - 1,
+		.step = 1,
+		.default_value = 0x0020,
+		.flags = 0,
+	}, {
+		.id = V4L2_CID_RED_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red Balance",
+		.minimum = -1 << 9,
+		.maximum = (1 << 9) - 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+		.id = V4L2_CID_BLUE_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue Balance",
+		.minimum = -1 << 9,
+		.maximum = (1 << 9) - 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+		.id      = V4L2_CID_HFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Mirror",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+		.id      = V4L2_CID_VFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Vflip",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+	}
+};
+
+struct mt9v011 {
+	struct v4l2_subdev sd;
+	unsigned width, height;
+	unsigned xtal;
+	unsigned hflip:1;
+	unsigned vflip:1;
+
+	u16 global_gain, red_bal, blue_bal;
+};
+
+static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9v011, sd);
+}
+
+static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	__be16 buffer;
+	int rc, val;
+
+	rc = i2c_master_send(c, &addr, 1);
+	if (rc != 1)
+		v4l2_dbg(0, debug, sd,
+			 "i2c i/o error: rc == %d (should be 1)\n", rc);
+
+	msleep(10);
+
+	rc = i2c_master_recv(c, (char *)&buffer, 2);
+	if (rc != 2)
+		v4l2_dbg(0, debug, sd,
+			 "i2c i/o error: rc == %d (should be 2)\n", rc);
+
+	val = be16_to_cpu(buffer);
+
+	v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val);
+
+	return val;
+}
+
+static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr,
+				 u16 value)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer[3];
+	int rc;
+
+	buffer[0] = addr;
+	buffer[1] = value >> 8;
+	buffer[2] = value & 0xff;
+
+	v4l2_dbg(2, debug, sd,
+		 "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value);
+	rc = i2c_master_send(c, buffer, 3);
+	if (rc != 3)
+		v4l2_dbg(0, debug, sd,
+			 "i2c i/o error: rc == %d (should be 3)\n", rc);
+}
+
+
+struct i2c_reg_value {
+	unsigned char reg;
+	u16           value;
+};
+
+/*
+ * Values used at the original driver
+ * Some values are marked as Reserved at the datasheet
+ */
+static const struct i2c_reg_value mt9v011_init_default[] = {
+		{ R0D_MT9V011_RESET, 0x0001 },
+		{ R0D_MT9V011_RESET, 0x0000 },
+
+		{ R0C_MT9V011_SHUTTER_DELAY, 0x0000 },
+		{ R09_MT9V011_SHUTTER_WIDTH, 0x1fc },
+
+		{ R0A_MT9V011_CLK_SPEED, 0x0000 },
+		{ R1E_MT9V011_DIGITAL_ZOOM,  0x0000 },
+
+		{ R07_MT9V011_OUT_CTRL, 0x0002 },	/* chip enable */
+};
+
+static void set_balance(struct v4l2_subdev *sd)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	u16 green1_gain, green2_gain, blue_gain, red_gain;
+
+	green1_gain = core->global_gain;
+	green2_gain = core->global_gain;
+
+	blue_gain = core->global_gain +
+		    core->global_gain * core->blue_bal / (1 << 9);
+
+	red_gain = core->global_gain +
+		   core->global_gain * core->blue_bal / (1 << 9);
+
+	mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain);
+	mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN,  green1_gain);
+	mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain);
+	mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain);
+}
+
+static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned height, width, hblank, vblank, speed;
+	unsigned row_time, t_time;
+	u64 frames_per_ms;
+	unsigned tmp;
+
+	height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
+	width = mt9v011_read(sd, R04_MT9V011_WIDTH);
+	hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
+	vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
+	speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED);
+
+	row_time = (width + 113 + hblank) * (speed + 2);
+	t_time = row_time * (height + vblank + 1);
+
+	frames_per_ms = core->xtal * 1000l;
+	do_div(frames_per_ms, t_time);
+	tmp = frames_per_ms;
+
+	v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n",
+		tmp / 1000, tmp % 1000, t_time);
+
+	if (numerator && denominator) {
+		*numerator = 1000;
+		*denominator = (u32)frames_per_ms;
+	}
+}
+
+static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned height, width, hblank, vblank;
+	unsigned row_time, line_time;
+	u64 t_time, speed;
+
+	/* Avoid bogus calculus */
+	if (!numerator || !denominator)
+		return 0;
+
+	height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
+	width = mt9v011_read(sd, R04_MT9V011_WIDTH);
+	hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
+	vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
+
+	row_time = width + 113 + hblank;
+	line_time = height + vblank + 1;
+
+	t_time = core->xtal * ((u64)numerator);
+	/* round to the closest value */
+	t_time += denominator / 2;
+	do_div(t_time, denominator);
+
+	speed = t_time;
+	do_div(speed, row_time * line_time);
+
+	/* Avoid having a negative value for speed */
+	if (speed < 2)
+		speed = 0;
+	else
+		speed -= 2;
+
+	/* Avoid speed overflow */
+	if (speed > 15)
+		return 15;
+
+	return (u16)speed;
+}
+
+static void set_res(struct v4l2_subdev *sd)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned vstart, hstart;
+
+	/*
+	 * The mt9v011 doesn't have scaling. So, in order to select the desired
+	 * resolution, we're cropping at the middle of the sensor.
+	 * hblank and vblank should be adjusted, in order to warrant that
+	 * we'll preserve the line timings for 30 fps, no matter what resolution
+	 * is selected.
+	 * NOTE: datasheet says that width (and height) should be filled with
+	 * width-1. However, this doesn't work, since one pixel per line will
+	 * be missing.
+	 */
+
+	hstart = 14 + (640 - core->width) / 2;
+	mt9v011_write(sd, R02_MT9V011_COLSTART, hstart);
+	mt9v011_write(sd, R04_MT9V011_WIDTH, core->width);
+	mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width);
+
+	vstart = 8 + (480 - core->height) / 2;
+	mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart);
+	mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height);
+	mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height);
+
+	calc_fps(sd, NULL, NULL);
+};
+
+static void set_read_mode(struct v4l2_subdev *sd)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned mode = 0x1000;
+
+	if (core->hflip)
+		mode |= 0x4000;
+
+	if (core->vflip)
+		mode |= 0x8000;
+
+	mt9v011_write(sd, R20_MT9V011_READ_MODE, mode);
+}
+
+static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++)
+		mt9v011_write(sd, mt9v011_init_default[i].reg,
+			       mt9v011_init_default[i].value);
+
+	set_balance(sd);
+	set_res(sd);
+	set_read_mode(sd);
+
+	return 0;
+};
+
+static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+
+	v4l2_dbg(1, debug, sd, "g_ctrl called\n");
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		ctrl->value = core->global_gain;
+		return 0;
+	case V4L2_CID_RED_BALANCE:
+		ctrl->value = core->red_bal;
+		return 0;
+	case V4L2_CID_BLUE_BALANCE:
+		ctrl->value = core->blue_bal;
+		return 0;
+	case V4L2_CID_HFLIP:
+		ctrl->value = core->hflip ? 1 : 0;
+		return 0;
+	case V4L2_CID_VFLIP:
+		ctrl->value = core->vflip ? 1 : 0;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	int i;
+
+	v4l2_dbg(1, debug, sd, "queryctrl called\n");
+
+	for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++)
+		if (qc->id && qc->id == mt9v011_qctrl[i].id) {
+			memcpy(qc, &(mt9v011_qctrl[i]),
+			       sizeof(*qc));
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+
+static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	u8 i, n;
+	n = ARRAY_SIZE(mt9v011_qctrl);
+
+	for (i = 0; i < n; i++) {
+		if (ctrl->id != mt9v011_qctrl[i].id)
+			continue;
+		if (ctrl->value < mt9v011_qctrl[i].minimum ||
+		    ctrl->value > mt9v011_qctrl[i].maximum)
+			return -ERANGE;
+		v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n",
+					ctrl->id, ctrl->value);
+		break;
+	}
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		core->global_gain = ctrl->value;
+		break;
+	case V4L2_CID_RED_BALANCE:
+		core->red_bal = ctrl->value;
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		core->blue_bal = ctrl->value;
+		break;
+	case V4L2_CID_HFLIP:
+		core->hflip = ctrl->value;
+		set_read_mode(sd);
+		return 0;
+	case V4L2_CID_VFLIP:
+		core->vflip = ctrl->value;
+		set_read_mode(sd);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	set_balance(sd);
+
+	return 0;
+}
+
+static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
+{
+	if (fmt->index > 0)
+		return -EINVAL;
+
+	fmt->flags = 0;
+	strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG");
+	fmt->pixelformat = V4L2_PIX_FMT_SGRBG8;
+
+	return 0;
+}
+
+static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8)
+		return -EINVAL;
+
+	v4l_bound_align_image(&pix->width, 48, 639, 1,
+			      &pix->height, 32, 480, 1, 0);
+
+	return 0;
+}
+
+static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memset(cp, 0, sizeof(struct v4l2_captureparm));
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	calc_fps(sd,
+		 &cp->timeperframe.numerator,
+		 &cp->timeperframe.denominator);
+
+	return 0;
+}
+
+static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+	u16 speed;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (cp->extendedmode != 0)
+		return -EINVAL;
+
+	speed = calc_speed(sd, tpf->numerator, tpf->denominator);
+
+	mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed);
+	v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed);
+
+	/* Recalculate and update fps info */
+	calc_fps(sd, &tpf->numerator, &tpf->denominator);
+
+	return 0;
+}
+
+static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	struct mt9v011 *core = to_mt9v011(sd);
+	int rc;
+
+	rc = mt9v011_try_fmt(sd, fmt);
+	if (rc < 0)
+		return -EINVAL;
+
+	core->width = pix->width;
+	core->height = pix->height;
+
+	set_res(sd);
+
+	return 0;
+}
+
+static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned *xtal = data;
+
+	v4l2_dbg(1, debug, sd, "s_config called\n");
+
+	if (xtal) {
+		core->xtal = *xtal;
+		v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
+			 *xtal / 1000000, (*xtal / 1000) % 1000);
+	}
+
+	return 0;
+}
+
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9v011_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	reg->val = mt9v011_read(sd, reg->reg & 0xff);
+	reg->size = 2;
+
+	return 0;
+}
+
+static int mt9v011_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff);
+
+	return 0;
+}
+#endif
+
+static int mt9v011_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *chip)
+{
+	u16 version;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011,
+					  version);
+}
+
+static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
+	.queryctrl = mt9v011_queryctrl,
+	.g_ctrl = mt9v011_g_ctrl,
+	.s_ctrl = mt9v011_s_ctrl,
+	.reset = mt9v011_reset,
+	.s_config = mt9v011_s_config,
+	.g_chip_ident = mt9v011_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = mt9v011_g_register,
+	.s_register = mt9v011_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
+	.enum_fmt = mt9v011_enum_fmt,
+	.try_fmt = mt9v011_try_fmt,
+	.s_fmt = mt9v011_s_fmt,
+	.g_parm = mt9v011_g_parm,
+	.s_parm = mt9v011_s_parm,
+};
+
+static const struct v4l2_subdev_ops mt9v011_ops = {
+	.core  = &mt9v011_core_ops,
+	.video = &mt9v011_video_ops,
+};
+
+
+/****************************************************************************
+			I2C Client & Driver
+ ****************************************************************************/
+
+static int mt9v011_probe(struct i2c_client *c,
+			 const struct i2c_device_id *id)
+{
+	u16 version;
+	struct mt9v011 *core;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(c->adapter,
+	     I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
+
+	core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL);
+	if (!core)
+		return -ENOMEM;
+
+	sd = &core->sd;
+	v4l2_i2c_subdev_init(sd, c, &mt9v011_ops);
+
+	/* Check if the sensor is really a MT9V011 */
+	version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
+	if ((version != MT9V011_VERSION) &&
+	    (version != MT9V011_REV_B_VERSION)) {
+		v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n",
+			  version);
+		kfree(core);
+		return -EINVAL;
+	}
+
+	core->global_gain = 0x0024;
+	core->width  = 640;
+	core->height = 480;
+	core->xtal = 27000000;	/* Hz */
+
+	v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n",
+		 c->addr << 1, c->adapter->name, version);
+
+	return 0;
+}
+
+static int mt9v011_remove(struct i2c_client *c)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(c);
+
+	v4l2_dbg(1, debug, sd,
+		"mt9v011.c: removing mt9v011 adapter on address 0x%x\n",
+		c->addr << 1);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_mt9v011(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id mt9v011_id[] = {
+	{ "mt9v011", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v011_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "mt9v011",
+	.probe = mt9v011_probe,
+	.remove = mt9v011_remove,
+	.id_table = mt9v011_id,
+};
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mt9v011.h linux-libre-2.6.31-gnu/drivers/media/video/mt9v011.h
--- linux-libre-2.6.30-gnu/drivers/media/video/mt9v011.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/mt9v011.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
+ *
+ * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#ifndef MT9V011_H_
+#define MT9V011_H_
+
+#define R00_MT9V011_CHIP_VERSION	0x00
+#define R01_MT9V011_ROWSTART		0x01
+#define R02_MT9V011_COLSTART		0x02
+#define R03_MT9V011_HEIGHT		0x03
+#define R04_MT9V011_WIDTH		0x04
+#define R05_MT9V011_HBLANK		0x05
+#define R06_MT9V011_VBLANK		0x06
+#define R07_MT9V011_OUT_CTRL		0x07
+#define R09_MT9V011_SHUTTER_WIDTH	0x09
+#define R0A_MT9V011_CLK_SPEED		0x0a
+#define R0B_MT9V011_RESTART		0x0b
+#define R0C_MT9V011_SHUTTER_DELAY	0x0c
+#define R0D_MT9V011_RESET		0x0d
+#define R1E_MT9V011_DIGITAL_ZOOM	0x1e
+#define R20_MT9V011_READ_MODE		0x20
+#define R2B_MT9V011_GREEN_1_GAIN	0x2b
+#define R2C_MT9V011_BLUE_GAIN		0x2c
+#define R2D_MT9V011_RED_GAIN		0x2d
+#define R2E_MT9V011_GREEN_2_GAIN	0x2e
+#define R35_MT9V011_GLOBAL_GAIN		0x35
+#define RF1_MT9V011_CHIP_ENABLE		0xf1
+
+#define MT9V011_VERSION			0x8232
+#define MT9V011_REV_B_VERSION		0x8243
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mt9v022.c linux-libre-2.6.31-gnu/drivers/media/video/mt9v022.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mt9v022.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/mt9v022.c	2009-09-09 18:13:59.000000000 -0400
@@ -91,51 +91,49 @@
 	u16 chip_control;
 };
 
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
 {
-	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
-	struct i2c_client *client = mt9v022->client;
 	s32 data = i2c_smbus_read_word_data(client, reg);
 	return data < 0 ? data : swab16(data);
 }
 
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
 		     const u16 data)
 {
-	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
-	return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data));
+	return i2c_smbus_write_word_data(client, reg, swab16(data));
 }
 
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
 		   const u16 data)
 {
 	int ret;
 
-	ret = reg_read(icd, reg);
+	ret = reg_read(client, reg);
 	if (ret < 0)
 		return ret;
-	return reg_write(icd, reg, ret | data);
+	return reg_write(client, reg, ret | data);
 }
 
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
 		     const u16 data)
 {
 	int ret;
 
-	ret = reg_read(icd, reg);
+	ret = reg_read(client, reg);
 	if (ret < 0)
 		return ret;
-	return reg_write(icd, reg, ret & ~data);
+	return reg_write(client, reg, ret & ~data);
 }
 
 static int mt9v022_init(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
-	struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+	struct soc_camera_link *icl = client->dev.platform_data;
 	int ret;
 
 	if (icl->power) {
-		ret = icl->power(&mt9v022->client->dev, 1);
+		ret = icl->power(&client->dev, 1);
 		if (ret < 0) {
 			dev_err(icd->vdev->parent,
 				"Platform failed to power-on the camera.\n");
@@ -148,27 +146,27 @@
 	 * if available. Soft reset is done in video_probe().
 	 */
 	if (icl->reset)
-		icl->reset(&mt9v022->client->dev);
+		icl->reset(&client->dev);
 
 	/* Almost the default mode: master, parallel, simultaneous, and an
 	 * undocumented bit 0x200, which is present in table 7, but not in 8,
 	 * plus snapshot mode to disable scan for now */
 	mt9v022->chip_control |= 0x10;
-	ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+	ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
 	if (!ret)
-		ret = reg_write(icd, MT9V022_READ_MODE, 0x300);
+		ret = reg_write(client, MT9V022_READ_MODE, 0x300);
 
 	/* All defaults */
 	if (!ret)
 		/* AEC, AGC on */
-		ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
+		ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3);
 	if (!ret)
-		ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
+		ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
 	if (!ret)
 		/* default - auto */
-		ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
+		ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
 	if (!ret)
-		ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
+		ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
 
 	return ret;
 }
@@ -186,10 +184,11 @@
 
 static int mt9v022_start_capture(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
 	/* Switch to master "normal" mode */
 	mt9v022->chip_control &= ~0x10;
-	if (reg_write(icd, MT9V022_CHIP_CONTROL,
+	if (reg_write(client, MT9V022_CHIP_CONTROL,
 		      mt9v022->chip_control) < 0)
 		return -EIO;
 	return 0;
@@ -197,10 +196,11 @@
 
 static int mt9v022_stop_capture(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
 	/* Switch to snapshot mode */
 	mt9v022->chip_control |= 0x10;
-	if (reg_write(icd, MT9V022_CHIP_CONTROL,
+	if (reg_write(client, MT9V022_CHIP_CONTROL,
 		      mt9v022->chip_control) < 0)
 		return -EIO;
 	return 0;
@@ -209,8 +209,9 @@
 static int mt9v022_set_bus_param(struct soc_camera_device *icd,
 				 unsigned long flags)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
-	struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+	struct soc_camera_link *icl = client->dev.platform_data;
 	unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
 	int ret;
 	u16 pixclk = 0;
@@ -243,14 +244,14 @@
 	if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
 		pixclk |= 0x2;
 
-	ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
+	ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
 	if (ret < 0)
 		return ret;
 
 	if (!(flags & SOCAM_MASTER))
 		mt9v022->chip_control &= ~0x8;
 
-	ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+	ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
 	if (ret < 0)
 		return ret;
 
@@ -282,35 +283,36 @@
 static int mt9v022_set_crop(struct soc_camera_device *icd,
 			    struct v4l2_rect *rect)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	int ret;
 
 	/* Like in example app. Contradicts the datasheet though */
-	ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+	ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
 	if (ret >= 0) {
 		if (ret & 1) /* Autoexposure */
-			ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+			ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
 					rect->height + icd->y_skip_top + 43);
 		else
-			ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+			ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
 					rect->height + icd->y_skip_top + 43);
 	}
 	/* Setup frame format: defaults apart from width and height */
 	if (!ret)
-		ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
+		ret = reg_write(client, MT9V022_COLUMN_START, rect->left);
 	if (!ret)
-		ret = reg_write(icd, MT9V022_ROW_START, rect->top);
+		ret = reg_write(client, MT9V022_ROW_START, rect->top);
 	if (!ret)
 		/* Default 94, Phytec driver says:
 		 * "width + horizontal blank >= 660" */
-		ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
+		ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
 				rect->width > 660 - 43 ? 43 :
 				660 - rect->width);
 	if (!ret)
-		ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
+		ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
 	if (!ret)
-		ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
+		ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect->width);
 	if (!ret)
-		ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
+		ret = reg_write(client, MT9V022_WINDOW_HEIGHT,
 				rect->height + icd->y_skip_top);
 
 	if (ret < 0)
@@ -362,15 +364,9 @@
 {
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	if (pix->height < 32 + icd->y_skip_top)
-		pix->height = 32 + icd->y_skip_top;
-	if (pix->height > 480 + icd->y_skip_top)
-		pix->height = 480 + icd->y_skip_top;
-	if (pix->width < 48)
-		pix->width = 48;
-	if (pix->width > 752)
-		pix->width = 752;
-	pix->width &= ~0x03; /* ? */
+	v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */,
+			      &pix->height, 32 + icd->y_skip_top,
+			      480 + icd->y_skip_top, 0, 0);
 
 	return 0;
 }
@@ -396,16 +392,16 @@
 static int mt9v022_get_register(struct soc_camera_device *icd,
 				struct v4l2_dbg_register *reg)
 {
-	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 		return -EINVAL;
 
-	if (reg->match.addr != mt9v022->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
 	reg->size = 2;
-	reg->val = reg_read(icd, reg->reg);
+	reg->val = reg_read(client, reg->reg);
 
 	if (reg->val > 0xffff)
 		return -EIO;
@@ -416,15 +412,15 @@
 static int mt9v022_set_register(struct soc_camera_device *icd,
 				struct v4l2_dbg_register *reg)
 {
-	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+	struct i2c_client *client = to_i2c_client(icd->control);
 
 	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
 		return -EINVAL;
 
-	if (reg->match.addr != mt9v022->client->addr)
+	if (reg->match.addr != client->addr)
 		return -ENODEV;
 
-	if (reg_write(icd, reg->reg, reg->val) < 0)
+	if (reg_write(client, reg->reg, reg->val) < 0)
 		return -EIO;
 
 	return 0;
@@ -517,29 +513,30 @@
 static int mt9v022_get_control(struct soc_camera_device *icd,
 			       struct v4l2_control *ctrl)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	int data;
 
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
-		data = reg_read(icd, MT9V022_READ_MODE);
+		data = reg_read(client, MT9V022_READ_MODE);
 		if (data < 0)
 			return -EIO;
 		ctrl->value = !!(data & 0x10);
 		break;
 	case V4L2_CID_HFLIP:
-		data = reg_read(icd, MT9V022_READ_MODE);
+		data = reg_read(client, MT9V022_READ_MODE);
 		if (data < 0)
 			return -EIO;
 		ctrl->value = !!(data & 0x20);
 		break;
 	case V4L2_CID_EXPOSURE_AUTO:
-		data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+		data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
 		if (data < 0)
 			return -EIO;
 		ctrl->value = !!(data & 0x1);
 		break;
 	case V4L2_CID_AUTOGAIN:
-		data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+		data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
 		if (data < 0)
 			return -EIO;
 		ctrl->value = !!(data & 0x2);
@@ -552,6 +549,7 @@
 			       struct v4l2_control *ctrl)
 {
 	int data;
+	struct i2c_client *client = to_i2c_client(icd->control);
 	const struct v4l2_queryctrl *qctrl;
 
 	qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
@@ -562,17 +560,17 @@
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
 		if (ctrl->value)
-			data = reg_set(icd, MT9V022_READ_MODE, 0x10);
+			data = reg_set(client, MT9V022_READ_MODE, 0x10);
 		else
-			data = reg_clear(icd, MT9V022_READ_MODE, 0x10);
+			data = reg_clear(client, MT9V022_READ_MODE, 0x10);
 		if (data < 0)
 			return -EIO;
 		break;
 	case V4L2_CID_HFLIP:
 		if (ctrl->value)
-			data = reg_set(icd, MT9V022_READ_MODE, 0x20);
+			data = reg_set(client, MT9V022_READ_MODE, 0x20);
 		else
-			data = reg_clear(icd, MT9V022_READ_MODE, 0x20);
+			data = reg_clear(client, MT9V022_READ_MODE, 0x20);
 		if (data < 0)
 			return -EIO;
 		break;
@@ -593,12 +591,12 @@
 			/* The user wants to set gain manually, hope, she
 			 * knows, what she's doing... Switch AGC off. */
 
-			if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+			if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
 				return -EIO;
 
 			dev_info(&icd->dev, "Setting gain from %d to %lu\n",
-				 reg_read(icd, MT9V022_ANALOG_GAIN), gain);
-			if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0)
+				 reg_read(client, MT9V022_ANALOG_GAIN), gain);
+			if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0)
 				return -EIO;
 			icd->gain = ctrl->value;
 		}
@@ -614,13 +612,13 @@
 			/* The user wants to set shutter width manually, hope,
 			 * she knows, what she's doing... Switch AEC off. */
 
-			if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
+			if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
 				return -EIO;
 
 			dev_dbg(&icd->dev, "Shutter width from %d to %lu\n",
-				reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH),
+				reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
 				shutter);
-			if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+			if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
 				      shutter) < 0)
 				return -EIO;
 			icd->exposure = ctrl->value;
@@ -628,17 +626,17 @@
 		break;
 	case V4L2_CID_AUTOGAIN:
 		if (ctrl->value)
-			data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+			data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2);
 		else
-			data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+			data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2);
 		if (data < 0)
 			return -EIO;
 		break;
 	case V4L2_CID_EXPOSURE_AUTO:
 		if (ctrl->value)
-			data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+			data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
 		else
-			data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+			data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
 		if (data < 0)
 			return -EIO;
 		break;
@@ -650,8 +648,9 @@
  * this wasn't our capture interface, so, we wait for the right one */
 static int mt9v022_video_probe(struct soc_camera_device *icd)
 {
+	struct i2c_client *client = to_i2c_client(icd->control);
 	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
-	struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+	struct soc_camera_link *icl = client->dev.platform_data;
 	s32 data;
 	int ret;
 	unsigned long flags;
@@ -661,7 +660,7 @@
 		return -ENODEV;
 
 	/* Read out the chip version register */
-	data = reg_read(icd, MT9V022_CHIP_VERSION);
+	data = reg_read(client, MT9V022_CHIP_VERSION);
 
 	/* must be 0x1311 or 0x1313 */
 	if (data != 0x1311 && data != 0x1313) {
@@ -672,12 +671,12 @@
 	}
 
 	/* Soft reset */
-	ret = reg_write(icd, MT9V022_RESET, 1);
+	ret = reg_write(client, MT9V022_RESET, 1);
 	if (ret < 0)
 		goto ei2c;
 	/* 15 clock cycles */
 	udelay(200);
-	if (reg_read(icd, MT9V022_RESET)) {
+	if (reg_read(client, MT9V022_RESET)) {
 		dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
 		goto ei2c;
 	}
@@ -685,11 +684,11 @@
 	/* Set monochrome or colour sensor type */
 	if (sensor_type && (!strcmp("colour", sensor_type) ||
 			    !strcmp("color", sensor_type))) {
-		ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
+		ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
 		mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
 		icd->formats = mt9v022_colour_formats;
 	} else {
-		ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
+		ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
 		mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
 		icd->formats = mt9v022_monochrome_formats;
 	}
@@ -735,10 +734,13 @@
 static void mt9v022_video_remove(struct soc_camera_device *icd)
 {
 	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+	struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
 
 	dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
 		icd->dev.parent, icd->vdev);
 	soc_camera_video_stop(icd);
+	if (icl->free_bus)
+		icl->free_bus(icl);
 }
 
 static int mt9v022_probe(struct i2c_client *client,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mx1_camera.c linux-libre-2.6.31-gnu/drivers/media/video/mx1_camera.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mx1_camera.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/mx1_camera.c	2009-09-09 18:13:59.000000000 -0400
@@ -102,10 +102,10 @@
  * Interface. If anyone ever builds hardware to enable more than
  * one camera, they will have to modify this driver too */
 struct mx1_camera_dev {
+	struct soc_camera_host		soc_host;
 	struct soc_camera_device	*icd;
 	struct mx1_camera_pdata		*pdata;
 	struct mx1_buffer		*active;
-	struct device			*dev;
 	struct resource			*res;
 	struct clk			*clk;
 	struct list_head		capture;
@@ -219,7 +219,7 @@
 	int ret;
 
 	if (unlikely(!pcdev->active)) {
-		dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n");
+		dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
 		return -EFAULT;
 	}
 
@@ -229,11 +229,12 @@
 		vbuf->size, pcdev->res->start +
 		CSIRXR, DMA_MODE_READ);
 	if (unlikely(ret))
-		dev_err(pcdev->dev, "Failed to setup DMA sg list\n");
+		dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n");
 
 	return ret;
 }
 
+/* Called under spinlock_irqsave(&pcdev->lock, ...) */
 static void mx1_videobuf_queue(struct videobuf_queue *vq,
 						struct videobuf_buffer *vb)
 {
@@ -241,13 +242,10 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx1_camera_dev *pcdev = ici->priv;
 	struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-	unsigned long flags;
 
 	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		vb, vb->baddr, vb->bsize);
 
-	spin_lock_irqsave(&pcdev->lock, flags);
-
 	list_add_tail(&vb->queue, &pcdev->capture);
 
 	vb->state = VIDEOBUF_ACTIVE;
@@ -264,8 +262,6 @@
 			__raw_writel(temp, pcdev->base + CSICR1);
 		}
 	}
-
-	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
 static void mx1_videobuf_release(struct videobuf_queue *vq,
@@ -338,14 +334,14 @@
 	imx_dma_disable(channel);
 
 	if (unlikely(!pcdev->active)) {
-		dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n");
+		dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
 		goto out;
 	}
 
 	vb = &pcdev->active->vb;
 	buf = container_of(vb, struct mx1_buffer, vb);
 	WARN_ON(buf->inwork || list_empty(&vb->queue));
-	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+	dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		vb, vb->baddr, vb->bsize);
 
 	mx1_camera_wakeup(pcdev, vb, buf);
@@ -366,7 +362,7 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx1_camera_dev *pcdev = ici->priv;
 
-	videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, pcdev->dev,
+	videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev,
 					&pcdev->lock,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE,
 					V4L2_FIELD_NONE,
@@ -385,7 +381,7 @@
 	 * they get a nice Oops */
 	div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
 
-	dev_dbg(pcdev->dev, "System clock %lukHz, target freq %dkHz, "
+	dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, "
 		"divisor %lu\n", lcdclk / 1000, mclk / 1000, div);
 
 	return div;
@@ -395,7 +391,7 @@
 {
 	unsigned int csicr1 = CSICR1_EN;
 
-	dev_dbg(pcdev->dev, "Activate device\n");
+	dev_dbg(pcdev->soc_host.dev, "Activate device\n");
 
 	clk_enable(pcdev->clk);
 
@@ -411,7 +407,7 @@
 
 static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
 {
-	dev_dbg(pcdev->dev, "Deactivate device\n");
+	dev_dbg(pcdev->soc_host.dev, "Deactivate device\n");
 
 	/* Disable all CSI interface */
 	__raw_writel(0x00, pcdev->base + CSICR1);
@@ -550,7 +546,7 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
 	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+		dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
 		return -EINVAL;
 	}
 
@@ -633,12 +629,6 @@
 	.querycap	= mx1_camera_querycap,
 };
 
-/* Should be allocated dynamically too, but we have only one. */
-static struct soc_camera_host mx1_soc_camera_host = {
-	.drv_name	= DRIVER_NAME,
-	.ops		= &mx1_soc_camera_host_ops,
-};
-
 static struct fiq_handler fh = {
 	.name		= "csi_sof"
 };
@@ -673,7 +663,6 @@
 		goto exit_put_clk;
 	}
 
-	dev_set_drvdata(&pdev->dev, pcdev);
 	pcdev->res = res;
 	pcdev->clk = clk;
 
@@ -707,16 +696,15 @@
 	}
 	pcdev->irq = irq;
 	pcdev->base = base;
-	pcdev->dev = &pdev->dev;
 
 	/* request dma */
 	pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH);
 	if (pcdev->dma_chan < 0) {
-		dev_err(pcdev->dev, "Can't request DMA for MX1 CSI\n");
+		dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n");
 		err = -EBUSY;
 		goto exit_iounmap;
 	}
-	dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
+	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
 
 	imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL,
 			       pcdev);
@@ -729,7 +717,7 @@
 	/* request irq */
 	err = claim_fiq(&fh);
 	if (err) {
-		dev_err(pcdev->dev, "Camera interrupt register failed \n");
+		dev_err(&pdev->dev, "Camera interrupt register failed \n");
 		goto exit_free_dma;
 	}
 
@@ -746,10 +734,12 @@
 	mxc_set_irq_fiq(irq, 1);
 	enable_fiq(irq);
 
-	mx1_soc_camera_host.priv	= pcdev;
-	mx1_soc_camera_host.dev.parent	= &pdev->dev;
-	mx1_soc_camera_host.nr		= pdev->id;
-	err = soc_camera_host_register(&mx1_soc_camera_host);
+	pcdev->soc_host.drv_name	= DRIVER_NAME;
+	pcdev->soc_host.ops		= &mx1_soc_camera_host_ops;
+	pcdev->soc_host.priv		= pcdev;
+	pcdev->soc_host.dev		= &pdev->dev;
+	pcdev->soc_host.nr		= pdev->id;
+	err = soc_camera_host_register(&pcdev->soc_host);
 	if (err)
 		goto exit_free_irq;
 
@@ -777,7 +767,9 @@
 
 static int __exit mx1_camera_remove(struct platform_device *pdev)
 {
-	struct mx1_camera_dev *pcdev = platform_get_drvdata(pdev);
+	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+	struct mx1_camera_dev *pcdev = container_of(soc_host,
+					struct mx1_camera_dev, soc_host);
 	struct resource *res;
 
 	imx_dma_free(pcdev->dma_chan);
@@ -787,7 +779,7 @@
 
 	clk_put(pcdev->clk);
 
-	soc_camera_host_unregister(&mx1_soc_camera_host);
+	soc_camera_host_unregister(soc_host);
 
 	iounmap(pcdev->base);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mx3_camera.c linux-libre-2.6.31-gnu/drivers/media/video/mx3_camera.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mx3_camera.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/mx3_camera.c	2009-09-09 18:13:59.000000000 -0400
@@ -87,7 +87,6 @@
  * @soc_host:		embedded soc_host object
  */
 struct mx3_camera_dev {
-	struct device		*dev;
 	/*
 	 * i.MX3x is only supposed to handle one camera on its Camera Sensor
 	 * Interface. If anyone ever builds hardware to enable more than one
@@ -333,7 +332,10 @@
 	}
 }
 
-/* Called with .vb_lock held */
+/*
+ * Called with .vb_lock mutex held and
+ * under spinlock_irqsave(&mx3_cam->lock, ...)
+ */
 static void mx3_videobuf_queue(struct videobuf_queue *vq,
 			       struct videobuf_buffer *vb)
 {
@@ -347,7 +349,8 @@
 	struct idmac_video_param *video = &ichan->params.video;
 	const struct soc_camera_data_format *data_fmt = icd->current_fmt;
 	dma_cookie_t cookie;
-	unsigned long flags;
+
+	BUG_ON(!irqs_disabled());
 
 	/* This is the configuration of one sg-element */
 	video->out_pixel_fmt	= fourcc_to_ipu_pix(data_fmt->fourcc);
@@ -360,8 +363,6 @@
 	memset((void *)vb->baddr, 0xaa, vb->bsize);
 #endif
 
-	spin_lock_irqsave(&mx3_cam->lock, flags);
-
 	list_add_tail(&vb->queue, &mx3_cam->capture);
 
 	if (!mx3_cam->active) {
@@ -371,24 +372,23 @@
 		vb->state = VIDEOBUF_QUEUED;
 	}
 
-	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+	spin_unlock_irq(&mx3_cam->lock);
 
 	cookie = txd->tx_submit(txd);
 	dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg));
+
+	spin_lock_irq(&mx3_cam->lock);
+
 	if (cookie >= 0)
 		return;
 
 	/* Submit error */
 	vb->state = VIDEOBUF_PREPARED;
 
-	spin_lock_irqsave(&mx3_cam->lock, flags);
-
 	list_del_init(&vb->queue);
 
 	if (mx3_cam->active == buf)
 		mx3_cam->active = NULL;
-
-	spin_unlock_irqrestore(&mx3_cam->lock, flags);
 }
 
 /* Called with .vb_lock held */
@@ -431,7 +431,7 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 
-	videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev,
+	videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev,
 				       &mx3_cam->lock,
 				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
 				       V4L2_FIELD_NONE,
@@ -599,7 +599,8 @@
 		*flags |= SOCAM_DATAWIDTH_4;
 		break;
 	default:
-		dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth);
+		dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n",
+			 buswidth);
 		return -EINVAL;
 	}
 
@@ -614,7 +615,7 @@
 	unsigned long bus_flags, camera_flags;
 	int ret = test_platform_param(mx3_cam, depth, &bus_flags);
 
-	dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret);
+	dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret);
 
 	if (ret < 0)
 		return ret;
@@ -637,7 +638,7 @@
 	if (!rq)
 		return false;
 
-	pdata = rq->mx3_cam->dev->platform_data;
+	pdata = rq->mx3_cam->soc_host.dev->platform_data;
 
 	return rq->id == chan->chan_id &&
 		pdata->dma_dev == chan->device->dev;
@@ -697,7 +698,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = buswidth;
 			xlate++;
-			dev_dbg(&ici->dev, "Providing format %s using %s\n",
+			dev_dbg(ici->dev, "Providing format %s using %s\n",
 				mx3_camera_formats[0].name,
 				icd->formats[idx].name);
 		}
@@ -709,7 +710,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = buswidth;
 			xlate++;
-			dev_dbg(&ici->dev, "Providing format %s using %s\n",
+			dev_dbg(ici->dev, "Providing format %s using %s\n",
 				mx3_camera_formats[0].name,
 				icd->formats[idx].name);
 		}
@@ -722,7 +723,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = buswidth;
 			xlate++;
-			dev_dbg(&ici->dev,
+			dev_dbg(ici->dev,
 				"Providing format %s in pass-through mode\n",
 				icd->formats[idx].name);
 		}
@@ -829,7 +830,7 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
 	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+		dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
 		return -EINVAL;
 	}
 
@@ -866,7 +867,7 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (pixfmt && !xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+		dev_warn(ici->dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
@@ -933,11 +934,11 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+		dev_warn(ici->dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
-	dev_dbg(&ici->dev, "requested bus width %d bit: %d\n",
+	dev_dbg(ici->dev, "requested bus width %d bit: %d\n",
 		icd->buswidth, ret);
 
 	if (ret < 0)
@@ -947,7 +948,7 @@
 
 	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
 	if (!common_flags) {
-		dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n",
+		dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
 			camera_flags, bus_flags);
 		return -EINVAL;
 	}
@@ -1054,7 +1055,7 @@
 
 	csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF);
 
-	dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
+	dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
 
 	return 0;
 }
@@ -1074,7 +1075,7 @@
 	.set_bus_param	= mx3_camera_set_bus_param,
 };
 
-static int mx3_camera_probe(struct platform_device *pdev)
+static int __devinit mx3_camera_probe(struct platform_device *pdev)
 {
 	struct mx3_camera_dev *mx3_cam;
 	struct resource *res;
@@ -1102,8 +1103,6 @@
 		goto eclkget;
 	}
 
-	dev_set_drvdata(&pdev->dev, mx3_cam);
-
 	mx3_cam->pdata = pdev->dev.platform_data;
 	mx3_cam->platform_flags = mx3_cam->pdata->flags;
 	if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
@@ -1135,14 +1134,14 @@
 	}
 
 	mx3_cam->base	= base;
-	mx3_cam->dev	= &pdev->dev;
 
 	soc_host		= &mx3_cam->soc_host;
 	soc_host->drv_name	= MX3_CAM_DRV_NAME;
 	soc_host->ops		= &mx3_soc_camera_host_ops;
 	soc_host->priv		= mx3_cam;
-	soc_host->dev.parent	= &pdev->dev;
+	soc_host->dev		= &pdev->dev;
 	soc_host->nr		= pdev->id;
+
 	err = soc_camera_host_register(soc_host);
 	if (err)
 		goto ecamhostreg;
@@ -1165,11 +1164,13 @@
 
 static int __devexit mx3_camera_remove(struct platform_device *pdev)
 {
-	struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev);
+	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+	struct mx3_camera_dev *mx3_cam = container_of(soc_host,
+					struct mx3_camera_dev, soc_host);
 
 	clk_put(mx3_cam->clk);
 
-	soc_camera_host_unregister(&mx3_cam->soc_host);
+	soc_camera_host_unregister(soc_host);
 
 	iounmap(mx3_cam->base);
 
@@ -1194,11 +1195,11 @@
 		.name	= MX3_CAM_DRV_NAME,
 	},
 	.probe		= mx3_camera_probe,
-	.remove		= __exit_p(mx3_camera_remove),
+	.remove		= __devexit_p(mx3_camera_remove),
 };
 
 
-static int __devinit mx3_camera_init(void)
+static int __init mx3_camera_init(void)
 {
 	return platform_driver_register(&mx3_camera_driver);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/mxb.c linux-libre-2.6.31-gnu/drivers/media/video/mxb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/mxb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/mxb.c	2009-09-09 18:13:59.000000000 -0400
@@ -453,7 +453,7 @@
 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
 	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
-	if (i->index < 0 || i->index >= MXB_INPUTS)
+	if (i->index >= MXB_INPUTS)
 		return -EINVAL;
 	memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
 	return 0;
@@ -616,7 +616,7 @@
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
-	if (a->index < 0 || a->index > MXB_INPUTS) {
+	if (a->index > MXB_INPUTS) {
 		DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
 		return -EINVAL;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ov511.c linux-libre-2.6.31-gnu/drivers/media/video/ov511.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ov511.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ov511.c	2009-09-09 18:13:59.000000000 -0400
@@ -112,6 +112,8 @@
 static int fastset;
 static int force_palette;
 static int backlight;
+/* Bitmask marking allocated devices from 0 to OV511_MAX_UNIT_VIDEO */
+static unsigned long ov511_devused;
 static int unit_video[OV511_MAX_UNIT_VIDEO];
 static int remove_zeros;
 static int mirror;
@@ -209,8 +211,6 @@
 static struct usb_device_id device_table [] = {
 	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
 	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
-	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
-	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
 	{ USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
 	{ }  /* Terminating entry */
 };
@@ -5720,7 +5720,7 @@
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_interface_descriptor *idesc;
 	struct usb_ov511 *ov;
-	int i;
+	int i, rc, nr;
 
 	PDEBUG(1, "probing for device...");
 
@@ -5845,33 +5845,41 @@
 	ov->vdev->parent = &intf->dev;
 	video_set_drvdata(ov->vdev, ov);
 
-	for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
-		/* Minor 0 cannot be specified; assume user wants autodetect */
-		if (unit_video[i] == 0)
-			break;
+	mutex_lock(&ov->lock);
 
-		if (video_register_device(ov->vdev, VFL_TYPE_GRABBER,
-			unit_video[i]) >= 0) {
-			break;
-		}
-	}
+	/* Check to see next free device and mark as used */
+	nr = find_first_zero_bit(&ov511_devused, OV511_MAX_UNIT_VIDEO);
 
-	/* Use the next available one */
-	if ((ov->vdev->minor == -1) &&
-	    video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
+	/* Registers device */
+	if (unit_video[nr] != 0)
+		rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER,
+					   unit_video[nr]);
+	else
+		rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1);
+
+	if (rc < 0) {
 		err("video_register_device failed");
+		mutex_unlock(&ov->lock);
 		goto error;
 	}
 
+	/* Mark device as used */
+	ov511_devused |= 1 << nr;
+	ov->nr = nr;
+
 	dev_info(&intf->dev, "Device at %s registered to minor %d\n",
 		 ov->usb_path, ov->vdev->minor);
 
 	usb_set_intfdata(intf, ov);
 	if (ov_create_sysfs(ov->vdev)) {
 		err("ov_create_sysfs failed");
+		ov511_devused &= ~(1 << nr);
+		mutex_unlock(&ov->lock);
 		goto error;
 	}
 
+	mutex_lock(&ov->lock);
+
 	return 0;
 
 error:
@@ -5906,10 +5914,16 @@
 
 	PDEBUG(3, "");
 
+	mutex_lock(&ov->lock);
 	usb_set_intfdata (intf, NULL);
 
-	if (!ov)
+	if (!ov) {
+		mutex_unlock(&ov->lock);
 		return;
+	}
+
+	/* Free device number */
+	ov511_devused &= ~(1 << ov->nr);
 
 	if (ov->vdev)
 		video_unregister_device(ov->vdev);
@@ -5927,6 +5941,7 @@
 
 	ov->streaming = 0;
 	ov51x_unlink_isoc(ov);
+	mutex_unlock(&ov->lock);
 
 	ov->dev = NULL;
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ov511.h linux-libre-2.6.31-gnu/drivers/media/video/ov511.h
--- linux-libre-2.6.30-gnu/drivers/media/video/ov511.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ov511.h	2009-09-09 18:13:59.000000000 -0400
@@ -494,6 +494,9 @@
 	int has_decoder;	/* Device has a video decoder */
 	int pal;		/* Device is designed for PAL resolution */
 
+	/* ov511 device number ID */
+	int nr;			/* Stores a device number */
+
 	/* I2C interface */
 	struct mutex i2c_lock;	  /* Protect I2C controller regs */
 	unsigned char primary_i2c_slave;  /* I2C write id of sensor */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ov772x.c linux-libre-2.6.31-gnu/drivers/media/video/ov772x.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ov772x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/ov772x.c	2009-09-09 18:13:59.000000000 -0400
@@ -1067,10 +1067,12 @@
 	struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
 	int                        ret;
 
-	info = client->dev.platform_data;
-	if (!info)
+	if (!client->dev.platform_data)
 		return -EINVAL;
 
+	info = container_of(client->dev.platform_data,
+			    struct ov772x_camera_info, link);
+
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&adapter->dev,
 			"I2C-Adapter doesn't support "
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-audio.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-audio.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-audio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-audio.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,11 +48,13 @@
 						MSP_DSP_IN_SCART),
 };
 
-static const struct routing_scheme routing_schemes[] = {
-	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
-		.def = routing_scheme0,
-		.cnt = ARRAY_SIZE(routing_scheme0),
-	},
+static const struct routing_scheme routing_def0 = {
+	.def = routing_scheme0,
+	.cnt = ARRAY_SIZE(routing_scheme0),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
 };
 
 void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
@@ -65,7 +67,7 @@
 		pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo");
 
 		if ((sid < ARRAY_SIZE(routing_schemes)) &&
-		    ((sp = routing_schemes + sid) != NULL) &&
+		    ((sp = routing_schemes[sid]) != NULL) &&
 		    (hdw->input_val >= 0) &&
 		    (hdw->input_val < sp->cnt)) {
 			input = sp->def[hdw->input_val];
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c	2009-09-09 18:13:59.000000000 -0400
@@ -49,11 +49,13 @@
 	[PVR2_CVAL_INPUT_SVIDEO] =  0,
 };
 
-static const struct routing_scheme routing_schemes[] = {
-	[PVR2_ROUTING_SCHEME_ONAIR] = {
-		.def = routing_scheme1,
-		.cnt = ARRAY_SIZE(routing_scheme1),
-	},
+static const struct routing_scheme routing_def1 = {
+	.def = routing_scheme1,
+	.cnt = ARRAY_SIZE(routing_scheme1),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+	[PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
 };
 
 
@@ -65,12 +67,11 @@
 		u32 input;
 		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
 			   hdw->input_val);
-		if ((sid < ARRAY_SIZE(routing_schemes)) &&
-		    ((sp = routing_schemes + sid) != NULL) &&
-		    (hdw->input_val >= 0) &&
-		    (hdw->input_val < sp->cnt)) {
-			input = sp->def[hdw->input_val];
-		} else {
+		sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+			routing_schemes[sid] : NULL;
+		if ((sp == NULL) ||
+		    (hdw->input_val < 0) ||
+		    (hdw->input_val >= sp->cnt)) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 				   "*** WARNING *** subdev v4l2 set_input:"
 				   " Invalid routing scheme (%u)"
@@ -78,6 +79,7 @@
 				   sid, hdw->input_val);
 			return;
 		}
+		input = sp->def[hdw->input_val];
 		sd->ops->audio->s_routing(sd, input, 0, 0);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,6 +68,11 @@
 	},
 };
 
+static const struct routing_scheme routing_def0 = {
+	.def = routing_scheme0,
+	.cnt = ARRAY_SIZE(routing_scheme0),
+};
+
 /* Specific to gotview device */
 static const struct routing_scheme_item routing_schemegv[] = {
 	[PVR2_CVAL_INPUT_TV] = {
@@ -90,15 +95,14 @@
 	},
 };
 
-static const struct routing_scheme routing_schemes[] = {
-	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
-		.def = routing_scheme0,
-		.cnt = ARRAY_SIZE(routing_scheme0),
-	},
-	[PVR2_ROUTING_SCHEME_GOTVIEW] = {
-		.def = routing_schemegv,
-		.cnt = ARRAY_SIZE(routing_schemegv),
-	},
+static const struct routing_scheme routing_defgv = {
+	.def = routing_schemegv,
+	.cnt = ARRAY_SIZE(routing_schemegv),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
+	[PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv,
 };
 
 void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
@@ -110,13 +114,11 @@
 		const struct routing_scheme *sp;
 		unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
 
-		if ((sid < ARRAY_SIZE(routing_schemes)) &&
-		    ((sp = routing_schemes + sid) != NULL) &&
-		    (hdw->input_val >= 0) &&
-		    (hdw->input_val < sp->cnt)) {
-			vid_input = sp->def[hdw->input_val].vid;
-			aud_input = sp->def[hdw->input_val].aud;
-		} else {
+		sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+			routing_schemes[sid] : NULL;
+		if ((sp == NULL) ||
+		    (hdw->input_val < 0) ||
+		    (hdw->input_val >= sp->cnt)) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 				   "*** WARNING *** subdev cx2584x set_input:"
 				   " Invalid routing scheme (%u)"
@@ -124,7 +126,8 @@
 				   sid, hdw->input_val);
 			return;
 		}
-
+		vid_input = sp->def[hdw->input_val].vid;
+		aud_input = sp->def[hdw->input_val].aud;
 		pvr2_trace(PVR2_TRACE_CHIPS,
 			   "subdev cx2584x set_input vid=0x%x aud=0x%x",
 			   vid_input, aud_input);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-03-22 19:13:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-03-22 20:09:55.000000000 -0400
@@ -71,6 +71,7 @@
 		.flag_has_svideo = !0,
 		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
 		.led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+		.ir_scheme = PVR2_IR_SCHEME_29XXX,
 };
 
 
@@ -284,6 +285,11 @@
 	.output_mode    = TDA10048_PARALLEL_OUTPUT,
 	.fwbulkwritelen = TDA10048_BULKWRITE_50,
 	.inversion      = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_3300,
+	.dtv7_if_freq_khz = TDA10048_IF_3800,
+	.dtv8_if_freq_khz = TDA10048_IF_4300,
+	.clk_freq_khz   = TDA10048_CLK_16000,
+	.disable_gate_access = 1,
 };
 
 static struct tda829x_config tda829x_no_probe = {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.h linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.h
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.h	2009-09-09 18:13:59.000000000 -0400
@@ -69,6 +69,7 @@
 #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
 #define PVR2_ROUTING_SCHEME_GOTVIEW 1
 #define PVR2_ROUTING_SCHEME_ONAIR 2
+#define PVR2_ROUTING_SCHEME_AV400 3
 
 #define PVR2_DIGITAL_SCHEME_NONE 0
 #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
@@ -78,8 +79,10 @@
 #define PVR2_LED_SCHEME_HAUPPAUGE 1
 
 #define PVR2_IR_SCHEME_NONE 0
-#define PVR2_IR_SCHEME_24XXX 1
-#define PVR2_IR_SCHEME_ZILOG 2
+#define PVR2_IR_SCHEME_24XXX 1 /* FX2-controlled IR */
+#define PVR2_IR_SCHEME_ZILOG 2 /* HVR-1950 style (must be taken out of reset) */
+#define PVR2_IR_SCHEME_24XXX_MCE 3 /* 24xxx MCE device */
+#define PVR2_IR_SCHEME_29XXX 4 /* Original 29xxx device */
 
 /* This describes a particular hardware type (except for the USB device ID
    which must live in a separate structure due to environmental
@@ -162,19 +165,9 @@
 	   ensure that it is found. */
 	unsigned int flag_has_wm8775:1;
 
-	/* Indicate any specialized IR scheme that might need to be
-	   supported by this driver.  If not set, then it is assumed that
-	   IR can work without help from the driver (which is frequently
-	   the case).  This is otherwise set to one of
-	   PVR2_IR_SCHEME_xxxx.  For "xxxx", the value "24XXX" indicates a
-	   Hauppauge 24xxx class device which has an FPGA-hosted IR
-	   receiver that can only be reached via FX2 command codes.  In
-	   that case the pvrusb2 driver will emulate the behavior of the
-	   older 29xxx device's IR receiver (a "virtual" I2C chip) in terms
-	   of those command codes.  For the value "ZILOG", we're dealing
-	   with an IR chip that must be taken out of reset via another FX2
-	   command code (which is the case for HVR-1950 devices). */
-	unsigned int ir_scheme:2;
+	/* Indicate IR scheme of hardware.  If not set, then it is assumed
+	   that IR can work without any help from the driver. */
+	unsigned int ir_scheme:3;
 
 	/* These bits define which kinds of sources the device can handle.
 	   Note: Digital tuner presence is inferred by the
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c	2012-03-22 19:13:41.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c	2012-03-22 20:09:53.000000000 -0400
@@ -85,8 +85,8 @@
 module_param_array(tolerance,    int, NULL, 0444);
 MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
 
-/* US Broadcast channel 7 (175.25 MHz) */
-static int default_tv_freq    = 175250000L;
+/* US Broadcast channel 3 (61.25 MHz), to help with testing */
+static int default_tv_freq    = 61250000L;
 /* 104.3 MHz, a usable FM station for my area */
 static int default_radio_freq = 104300000L;
 
@@ -142,6 +142,15 @@
 };
 
 
+static const char *ir_scheme_names[] = {
+	[PVR2_IR_SCHEME_NONE] = "none",
+	[PVR2_IR_SCHEME_29XXX] = "29xxx",
+	[PVR2_IR_SCHEME_24XXX] = "24xxx (29xxx emulation)",
+	[PVR2_IR_SCHEME_24XXX_MCE] = "24xxx (MCE device)",
+	[PVR2_IR_SCHEME_ZILOG] = "Zilog",
+};
+
+
 /* Define the list of additional controls we'll dynamically construct based
    on query of the cx2341x module. */
 struct pvr2_mpeg_ids {
@@ -1978,6 +1987,34 @@
 }
 
 
+static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw)
+{
+	/*
+	  Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit of nuttiness
+	  for cx25840 causes that module to correctly set up its video
+	  scaling.  This is really a problem in the cx25840 module itself,
+	  but we work around it here.  The problem has not been seen in
+	  ivtv because there VBI is supported and set up.  We don't do VBI
+	  here (at least not yet) and thus we never attempted to even set
+	  it up.
+	*/
+	struct v4l2_format fmt;
+	if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) {
+		/* We're not using a cx25840 so don't enable the hack */
+		return;
+	}
+
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "Module ID %u:"
+		   " Executing cx25840 VBI hack",
+		   hdw->decoder_client_id);
+	memset(&fmt, 0, sizeof(fmt));
+	fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+	v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
+			     video, s_fmt, &fmt);
+}
+
+
 static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
 				const struct pvr2_device_client_desc *cd)
 {
@@ -2069,30 +2106,6 @@
 	/* client-specific setup... */
 	switch (mid) {
 	case PVR2_CLIENT_ID_CX25840:
-		hdw->decoder_client_id = mid;
-		{
-			/*
-			  Mike Isely <isely@pobox.com> 19-Nov-2006 - This
-			  bit of nuttiness for cx25840 causes that module
-			  to correctly set up its video scaling.  This is
-			  really a problem in the cx25840 module itself,
-			  but we work around it here.  The problem has not
-			  been seen in ivtv because there VBI is supported
-			  and set up.  We don't do VBI here (at least not
-			  yet) and thus we never attempted to even set it
-			  up.
-			*/
-			struct v4l2_format fmt;
-			pvr2_trace(PVR2_TRACE_INIT,
-				   "Module ID %u:"
-				   " Executing cx25840 VBI hack",
-				   mid);
-			memset(&fmt, 0, sizeof(fmt));
-			fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
-			v4l2_device_call_all(&hdw->v4l2_dev, mid,
-					     video, s_fmt, &fmt);
-		}
-		break;
 	case PVR2_CLIENT_ID_SAA7115:
 		hdw->decoder_client_id = mid;
 		break;
@@ -2170,7 +2183,7 @@
 	}
 
 	/* Take the IR chip out of reset, if appropriate */
-	if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_ZILOG) {
+	if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) {
 		pvr2_issue_simple_cmd(hdw,
 				      FX2CMD_HCW_ZILOG_RESET |
 				      (1 << 8) |
@@ -2193,6 +2206,8 @@
 		cptr->info->set_value(cptr,~0,cptr->info->default_value);
 	}
 
+	pvr2_hdw_cx25840_vbi_hack(hdw);
+
 	/* Set up special default values for the television and radio
 	   frequencies here.  It's not really important what these defaults
 	   are, but I set them to something usable in the Chicago area just
@@ -2451,6 +2466,7 @@
 				GFP_KERNEL);
 	if (!hdw->controls) goto fail;
 	hdw->hdw_desc = hdw_desc;
+	hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme;
 	for (idx = 0; idx < hdw->control_cnt; idx++) {
 		cptr = hdw->controls + idx;
 		cptr->hdw = hdw;
@@ -2944,6 +2960,7 @@
 			vs = hdw->std_mask_cur;
 			v4l2_device_call_all(&hdw->v4l2_dev, 0,
 					     core, s_std, vs);
+			pvr2_hdw_cx25840_vbi_hack(hdw);
 		}
 		hdw->tuner_signal_stale = !0;
 		hdw->cropcap_stale = !0;
@@ -4066,6 +4083,7 @@
 	if (hdw->decoder_client_id) {
 		v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
 				     core, reset, 0);
+		pvr2_hdw_cx25840_vbi_hack(hdw);
 		return 0;
 	}
 	pvr2_trace(PVR2_TRACE_INIT,
@@ -4809,6 +4827,12 @@
 			stats.buffers_processed,
 			stats.buffers_failed);
 	}
+	case 6: {
+		unsigned int id = hdw->ir_scheme_active;
+		return scnprintf(buf, acnt, "ir scheme: id=%d %s", id,
+				 (id >= ARRAY_SIZE(ir_scheme_names) ?
+				  "?" : ir_scheme_names[id]));
+	}
 	default: break;
 	}
 	return 0;
@@ -4825,65 +4849,35 @@
 	unsigned int tcnt = 0;
 	unsigned int ccnt;
 	struct i2c_client *client;
-	struct list_head *item;
-	void *cd;
 	const char *p;
 	unsigned int id;
 
-	ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:");
+	ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers and I2C clients:\n");
 	tcnt += ccnt;
 	v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
 		id = sd->grp_id;
 		p = NULL;
 		if (id < ARRAY_SIZE(module_names)) p = module_names[id];
 		if (p) {
-			ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p);
+			ccnt = scnprintf(buf + tcnt, acnt - tcnt, "  %s:", p);
 			tcnt += ccnt;
 		} else {
 			ccnt = scnprintf(buf + tcnt, acnt - tcnt,
-					 " (unknown id=%u)", id);
+					 "  (unknown id=%u):", id);
 			tcnt += ccnt;
 		}
-	}
-	ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
-	tcnt += ccnt;
-
-	ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n");
-	tcnt += ccnt;
-
-	mutex_lock(&hdw->i2c_adap.clist_lock);
-	list_for_each(item, &hdw->i2c_adap.clients) {
-		client = list_entry(item, struct i2c_client, list);
-		ccnt = scnprintf(buf + tcnt, acnt - tcnt,
-				 "  %s: i2c=%02x", client->name, client->addr);
-		tcnt += ccnt;
-		cd = i2c_get_clientdata(client);
-		v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
-			if (cd == sd) {
-				id = sd->grp_id;
-				p = NULL;
-				if (id < ARRAY_SIZE(module_names)) {
-					p = module_names[id];
-				}
-				if (p) {
-					ccnt = scnprintf(buf + tcnt,
-							 acnt - tcnt,
-							 " subdev=%s", p);
-					tcnt += ccnt;
-				} else {
-					ccnt = scnprintf(buf + tcnt,
-							 acnt - tcnt,
-							 " subdev= id %u)",
-							 id);
-					tcnt += ccnt;
-				}
-				break;
-			}
+		client = v4l2_get_subdevdata(sd);
+		if (client) {
+			ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+					 " %s @ %02x\n", client->name,
+					 client->addr);
+			tcnt += ccnt;
+		} else {
+			ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+					 " no i2c client\n");
+			tcnt += ccnt;
 		}
-		ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
-		tcnt += ccnt;
 	}
-	mutex_unlock(&hdw->i2c_adap.clist_lock);
 	return tcnt;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h	2009-09-09 18:13:59.000000000 -0400
@@ -200,6 +200,9 @@
 	int i2c_cx25840_hack_state;
 	int i2c_linked;
 
+	/* IR related */
+	unsigned int ir_scheme_active; /* IR scheme as seen from the outside */
+
 	/* Frequency table */
 	unsigned int freqTable[FREQTABLE_SIZE];
 	unsigned int freqProgSlot;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -42,6 +42,18 @@
 module_param_array(ir_mode, int, NULL, 0444);
 MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
 
+static int pvr2_disable_ir_video;
+module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video,
+		   int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(disable_autoload_ir_video,
+		 "1=do not try to autoload ir_video IR receiver");
+
+/* Mapping of IR schemes to known I2C addresses - if any */
+static const unsigned char ir_video_addresses[] = {
+	[PVR2_IR_SCHEME_29XXX] = 0x18,
+	[PVR2_IR_SCHEME_24XXX] = 0x18,
+};
+
 static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
 			  u8 i2c_addr,      /* I2C address we're talking to */
 			  u8 *data,         /* Data to write */
@@ -559,6 +571,31 @@
 	printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
 }
 
+static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
+{
+	struct i2c_board_info info;
+	unsigned char addr = 0;
+	if (pvr2_disable_ir_video) {
+		pvr2_trace(PVR2_TRACE_INFO,
+			   "Automatic binding of ir_video has been disabled.");
+		return;
+	}
+	if (hdw->ir_scheme_active < ARRAY_SIZE(ir_video_addresses)) {
+		addr = ir_video_addresses[hdw->ir_scheme_active];
+	}
+	if (!addr) {
+		/* The device either doesn't support I2C-based IR or we
+		   don't know (yet) how to operate IR on the device. */
+		return;
+	}
+	pvr2_trace(PVR2_TRACE_INFO,
+		   "Binding ir_video to i2c address 0x%02x.", addr);
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+	info.addr = addr;
+	i2c_new_device(&hdw->i2c_adap, &info);
+}
+
 void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
 {
 	unsigned int idx;
@@ -574,7 +611,9 @@
 		printk(KERN_INFO "%s: IR disabled\n",hdw->name);
 		hdw->i2c_func[0x18] = i2c_black_hole;
 	} else if (ir_mode[hdw->unit_number] == 1) {
-		if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) {
+		if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) {
+			/* Set up translation so that our IR looks like a
+			   29xxx device */
 			hdw->i2c_func[0x18] = i2c_24xxx_ir;
 		}
 	}
@@ -597,15 +636,23 @@
 	i2c_add_adapter(&hdw->i2c_adap);
 	if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
 		/* Probe for a different type of IR receiver on this
-		   device.  If present, disable the emulated IR receiver. */
+		   device.  This is really the only way to differentiate
+		   older 24xxx devices from 24xxx variants that include an
+		   IR blaster.  If the IR blaster is present, the IR
+		   receiver is part of that chip and thus we must disable
+		   the emulated IR receiver. */
 		if (do_i2c_probe(hdw, 0x71)) {
 			pvr2_trace(PVR2_TRACE_INFO,
 				   "Device has newer IR hardware;"
 				   " disabling unneeded virtual IR device");
 			hdw->i2c_func[0x18] = NULL;
+			/* Remember that this is a different device... */
+			hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE;
 		}
 	}
 	if (i2c_scan) do_i2c_scan(hdw);
+
+	pvr2_i2c_register_ir(hdw);
 }
 
 void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -539,7 +539,7 @@
 					 &sfp->attr_unit_number);
 	}
 	pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
-	sfp->class_dev->driver_data = NULL;
+	dev_set_drvdata(sfp->class_dev, NULL);
 	device_unregister(sfp->class_dev);
 	sfp->class_dev = NULL;
 }
@@ -549,7 +549,7 @@
 				     struct device_attribute *attr, char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	return scnprintf(buf,PAGE_SIZE,"%d\n",
 			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
@@ -561,7 +561,7 @@
 			     struct device_attribute *attr, char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	return scnprintf(buf,PAGE_SIZE,"%s\n",
 			 pvr2_hdw_get_bus_info(sfp->channel.hdw));
@@ -572,7 +572,7 @@
 			     struct device_attribute *attr, char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	return scnprintf(buf,PAGE_SIZE,"%s\n",
 			 pvr2_hdw_get_type(sfp->channel.hdw));
@@ -583,7 +583,7 @@
 			     struct device_attribute *attr, char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	return scnprintf(buf,PAGE_SIZE,"%s\n",
 			 pvr2_hdw_get_desc(sfp->channel.hdw));
@@ -595,7 +595,7 @@
 					   char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	return scnprintf(buf,PAGE_SIZE,"%d\n",
 			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
@@ -607,7 +607,7 @@
 				struct device_attribute *attr, char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	return scnprintf(buf,PAGE_SIZE,"%d\n",
 			 pvr2_hdw_get_unit_number(sfp->channel.hdw));
@@ -635,7 +635,7 @@
 	class_dev->parent = &usb_dev->dev;
 
 	sfp->class_dev = class_dev;
-	class_dev->driver_data = sfp;
+	dev_set_drvdata(class_dev, sfp);
 	ret = device_register(class_dev);
 	if (ret) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
@@ -792,7 +792,7 @@
 			      struct device_attribute *attr, char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	pvr2_hdw_trigger_module_log(sfp->channel.hdw);
 	return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
@@ -803,7 +803,7 @@
 			     struct device_attribute *attr, char *buf)
 {
 	struct pvr2_sysfs *sfp;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 	return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
 }
@@ -816,7 +816,7 @@
 	struct pvr2_sysfs *sfp;
 	int ret;
 
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	sfp = dev_get_drvdata(class_dev);
 	if (!sfp) return -EINVAL;
 
 	ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2009-09-09 18:13:59.000000000 -0400
@@ -90,7 +90,7 @@
 	.driver         = "pvrusb2",
 	.card           = "Hauppauge WinTV pvr-usb2",
 	.bus_info       = "usb",
-	.version        = KERNEL_VERSION(0,8,0),
+	.version        = KERNEL_VERSION(0, 9, 0),
 	.capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
 			   V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
 			   V4L2_CAP_READWRITE),
@@ -267,7 +267,7 @@
 		memset(&tmp,0,sizeof(tmp));
 		tmp.index = vi->index;
 		ret = 0;
-		if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+		if (vi->index >= fh->input_cnt) {
 			ret = -EINVAL;
 			break;
 		}
@@ -331,7 +331,7 @@
 	case VIDIOC_S_INPUT:
 	{
 		struct v4l2_input *vi = (struct v4l2_input *)arg;
-		if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
+		if (vi->index >= fh->input_cnt) {
 			ret = -ERANGE;
 			break;
 		}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,6 +54,11 @@
 	[PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2,
 };
 
+static const struct routing_scheme routing_def0 = {
+	.def = routing_scheme0,
+	.cnt = ARRAY_SIZE(routing_scheme0),
+};
+
 static const int routing_scheme1[] = {
 	[PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
 	[PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
@@ -61,15 +66,14 @@
 	[PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2, /* or SVIDEO0, it seems */
 };
 
-static const struct routing_scheme routing_schemes[] = {
-	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
-		.def = routing_scheme0,
-		.cnt = ARRAY_SIZE(routing_scheme0),
-	},
-	[PVR2_ROUTING_SCHEME_ONAIR] = {
-		.def = routing_scheme1,
-		.cnt = ARRAY_SIZE(routing_scheme1),
-	},
+static const struct routing_scheme routing_def1 = {
+	.def = routing_scheme1,
+	.cnt = ARRAY_SIZE(routing_scheme1),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
+	[PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
 };
 
 void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
@@ -81,12 +85,12 @@
 
 		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
 			   hdw->input_val);
-		if ((sid < ARRAY_SIZE(routing_schemes)) &&
-		    ((sp = routing_schemes + sid) != NULL) &&
-		    (hdw->input_val >= 0) &&
-		    (hdw->input_val < sp->cnt)) {
-			input = sp->def[hdw->input_val];
-		} else {
+
+		sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+			routing_schemes[sid] : NULL;
+		if ((sp == NULL) ||
+		    (hdw->input_val < 0) ||
+		    (hdw->input_val >= sp->cnt)) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 				   "*** WARNING *** subdev v4l2 set_input:"
 				   " Invalid routing scheme (%u)"
@@ -94,6 +98,7 @@
 				   sid, hdw->input_val);
 			return;
 		}
+		input = sp->def[hdw->input_val];
 		sd->ops->video->s_routing(sd, input, 0, 0);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pwc/pwc.h linux-libre-2.6.31-gnu/drivers/media/video/pwc/pwc.h
--- linux-libre-2.6.30-gnu/drivers/media/video/pwc/pwc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pwc/pwc.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,6 @@
 #include <linux/usb.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pwc/pwc-if.c linux-libre-2.6.31-gnu/drivers/media/video/pwc/pwc-if.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pwc/pwc-if.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pwc/pwc-if.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,7 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 #include <linux/usb/input.h>
 #endif
@@ -601,7 +602,7 @@
 
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 	if (pdev->button_dev) {
-		input_report_key(pdev->button_dev, BTN_0, down);
+		input_report_key(pdev->button_dev, KEY_CAMERA, down);
 		input_sync(pdev->button_dev);
 	}
 #endif
@@ -1783,7 +1784,7 @@
 		return -ENOMEM;
 	}
 	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
-	pdev->vdev->parent = &(udev->dev);
+	pdev->vdev->parent = &intf->dev;
 	strcpy(pdev->vdev->name, name);
 	video_set_drvdata(pdev->vdev, pdev);
 
@@ -1847,7 +1848,7 @@
 	usb_to_input_id(pdev->udev, &pdev->button_dev->id);
 	pdev->button_dev->dev.parent = &pdev->udev->dev;
 	pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
-	pdev->button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+	pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
 
 	rc = input_register_device(pdev->button_dev);
 	if (rc) {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pwc/pwc-v4l.c linux-libre-2.6.31-gnu/drivers/media/video/pwc/pwc-v4l.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pwc/pwc-v4l.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pwc/pwc-v4l.c	2009-09-09 18:13:59.000000000 -0400
@@ -1107,7 +1107,7 @@
 				return -EINVAL;
 			if (buf->memory != V4L2_MEMORY_MMAP)
 				return -EINVAL;
-			if (buf->index < 0 || buf->index >= pwc_mbufs)
+			if (buf->index >= pwc_mbufs)
 				return -EINVAL;
 
 			buf->flags |= V4L2_BUF_FLAG_QUEUED;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/pxa_camera.c linux-libre-2.6.31-gnu/drivers/media/video/pxa_camera.c
--- linux-libre-2.6.30-gnu/drivers/media/video/pxa_camera.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/pxa_camera.c	2009-09-09 18:13:59.000000000 -0400
@@ -163,13 +163,6 @@
 			CICR0_EOFM | CICR0_FOM)
 
 /*
- * YUV422P picture size should be a multiple of 16, so the heuristic aligns
- * height, width on 4 byte boundaries to reach the 16 multiple for the size.
- */
-#define YUV422P_X_Y_ALIGN 4
-#define YUV422P_SIZE_ALIGN YUV422P_X_Y_ALIGN * YUV422P_X_Y_ALIGN
-
-/*
  * Structures
  */
 enum pxa_camera_active_dma {
@@ -202,7 +195,7 @@
 };
 
 struct pxa_camera_dev {
-	struct device		*dev;
+	struct soc_camera_host	soc_host;
 	/* PXA27x is only supposed to handle one camera on its Quick Capture
 	 * interface. If anyone ever builds hardware to enable more than
 	 * one camera, they will have to modify this driver too */
@@ -261,7 +254,6 @@
 {
 	struct soc_camera_device *icd = vq->priv_data;
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	struct pxa_camera_dev *pcdev = ici->priv;
 	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
 	int i;
 
@@ -278,7 +270,7 @@
 
 	for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
 		if (buf->dmas[i].sg_cpu)
-			dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
+			dma_free_coherent(ici->dev, buf->dmas[i].sg_size,
 					  buf->dmas[i].sg_cpu,
 					  buf->dmas[i].sg_dma);
 		buf->dmas[i].sg_cpu = NULL;
@@ -338,14 +330,14 @@
 	int dma_len = 0, xfer_len = 0;
 
 	if (pxa_dma->sg_cpu)
-		dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
+		dma_free_coherent(pcdev->soc_host.dev, pxa_dma->sg_size,
 				  pxa_dma->sg_cpu, pxa_dma->sg_dma);
 
 	sglen = calculate_dma_sglen(*sg_first, dma->sglen,
 				    *sg_first_ofs, size);
 
 	pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
-	pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
+	pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->soc_host.dev, pxa_dma->sg_size,
 					     &pxa_dma->sg_dma, GFP_KERNEL);
 	if (!pxa_dma->sg_cpu)
 		return -ENOMEM;
@@ -353,7 +345,7 @@
 	pxa_dma->sglen = sglen;
 	offset = *sg_first_ofs;
 
-	dev_dbg(pcdev->dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
+	dev_dbg(pcdev->soc_host.dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
 		*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
 
 
@@ -376,7 +368,7 @@
 		pxa_dma->sg_cpu[i].ddadr =
 			pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
 
-		dev_vdbg(pcdev->dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
+		dev_vdbg(pcdev->soc_host.dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
 			 pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
 			 sg_dma_address(sg) + offset, xfer_len);
 		offset = 0;
@@ -488,7 +480,7 @@
 		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y,
 					   &sg, &next_ofs);
 		if (ret) {
-			dev_err(pcdev->dev,
+			dev_err(pcdev->soc_host.dev,
 				"DMA initialization for Y/RGB failed\n");
 			goto fail;
 		}
@@ -498,7 +490,7 @@
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1,
 						   size_u, &sg, &next_ofs);
 		if (ret) {
-			dev_err(pcdev->dev,
+			dev_err(pcdev->soc_host.dev,
 				"DMA initialization for U failed\n");
 			goto fail_u;
 		}
@@ -508,7 +500,7 @@
 			ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2,
 						   size_v, &sg, &next_ofs);
 		if (ret) {
-			dev_err(pcdev->dev,
+			dev_err(pcdev->soc_host.dev,
 				"DMA initialization for V failed\n");
 			goto fail_v;
 		}
@@ -522,10 +514,10 @@
 	return 0;
 
 fail_v:
-	dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
+	dma_free_coherent(pcdev->soc_host.dev, buf->dmas[1].sg_size,
 			  buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
 fail_u:
-	dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
+	dma_free_coherent(pcdev->soc_host.dev, buf->dmas[0].sg_size,
 			  buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
 fail:
 	free_buffer(vq, buf);
@@ -549,7 +541,7 @@
 	active = pcdev->active;
 
 	for (i = 0; i < pcdev->channels; i++) {
-		dev_dbg(pcdev->dev, "%s (channel=%d) ddadr=%08x\n", __func__,
+		dev_dbg(pcdev->soc_host.dev, "%s (channel=%d) ddadr=%08x\n", __func__,
 			i, active->dmas[i].sg_dma);
 		DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
 		DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
@@ -561,7 +553,7 @@
 	int i;
 
 	for (i = 0; i < pcdev->channels; i++) {
-		dev_dbg(pcdev->dev, "%s (channel=%d)\n", __func__, i);
+		dev_dbg(pcdev->soc_host.dev, "%s (channel=%d)\n", __func__, i);
 		DCSR(pcdev->dma_chans[i]) = 0;
 	}
 }
@@ -597,7 +589,7 @@
 {
 	unsigned long cicr0, cifr;
 
-	dev_dbg(pcdev->dev, "%s\n", __func__);
+	dev_dbg(pcdev->soc_host.dev, "%s\n", __func__);
 	/* Reset the FIFOs */
 	cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
 	__raw_writel(cifr, pcdev->base + CIFR);
@@ -617,9 +609,10 @@
 	__raw_writel(cicr0, pcdev->base + CICR0);
 
 	pcdev->active = NULL;
-	dev_dbg(pcdev->dev, "%s\n", __func__);
+	dev_dbg(pcdev->soc_host.dev, "%s\n", __func__);
 }
 
+/* Called under spinlock_irqsave(&pcdev->lock, ...) */
 static void pxa_videobuf_queue(struct videobuf_queue *vq,
 			       struct videobuf_buffer *vb)
 {
@@ -627,13 +620,10 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
 	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
-	unsigned long flags;
 
 	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d active=%p\n", __func__,
 		vb, vb->baddr, vb->bsize, pcdev->active);
 
-	spin_lock_irqsave(&pcdev->lock, flags);
-
 	list_add_tail(&vb->queue, &pcdev->capture);
 
 	vb->state = VIDEOBUF_ACTIVE;
@@ -641,8 +631,6 @@
 
 	if (!pcdev->active)
 		pxa_camera_start_capture(pcdev);
-
-	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
 static void pxa_videobuf_release(struct videobuf_queue *vq,
@@ -686,7 +674,7 @@
 	do_gettimeofday(&vb->ts);
 	vb->field_count++;
 	wake_up(&vb->done);
-	dev_dbg(pcdev->dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb);
+	dev_dbg(pcdev->soc_host.dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb);
 
 	if (list_empty(&pcdev->capture)) {
 		pxa_camera_stop_capture(pcdev);
@@ -722,7 +710,7 @@
 	for (i = 0; i < pcdev->channels; i++)
 		if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP)
 			is_dma_stopped = 0;
-	dev_dbg(pcdev->dev, "%s : top queued buffer=%p, dma_stopped=%d\n",
+	dev_dbg(pcdev->soc_host.dev, "%s : top queued buffer=%p, dma_stopped=%d\n",
 		__func__, pcdev->active, is_dma_stopped);
 	if (pcdev->active && is_dma_stopped)
 		pxa_camera_start_capture(pcdev);
@@ -747,12 +735,12 @@
 		overrun |= CISR_IFO_1 | CISR_IFO_2;
 
 	if (status & DCSR_BUSERR) {
-		dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
+		dev_err(pcdev->soc_host.dev, "DMA Bus Error IRQ!\n");
 		goto out;
 	}
 
 	if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
-		dev_err(pcdev->dev, "Unknown DMA IRQ source, "
+		dev_err(pcdev->soc_host.dev, "Unknown DMA IRQ source, "
 			"status: 0x%08x\n", status);
 		goto out;
 	}
@@ -776,7 +764,7 @@
 	buf = container_of(vb, struct pxa_buffer, vb);
 	WARN_ON(buf->inwork || list_empty(&vb->queue));
 
-	dev_dbg(pcdev->dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
+	dev_dbg(pcdev->soc_host.dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
 		__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
 		status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
 
@@ -787,7 +775,7 @@
 		 */
 		if (camera_status & overrun &&
 		    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
-			dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n",
+			dev_dbg(pcdev->soc_host.dev, "FIFO overrun! CISR: %x\n",
 				camera_status);
 			pxa_camera_stop_capture(pcdev);
 			pxa_camera_start_capture(pcdev);
@@ -854,7 +842,7 @@
 	/* mclk <= ciclk / 4 (27.4.2) */
 	if (mclk > lcdclk / 4) {
 		mclk = lcdclk / 4;
-		dev_warn(pcdev->dev, "Limiting master clock to %lu\n", mclk);
+		dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
 	}
 
 	/* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
@@ -864,7 +852,7 @@
 	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
 		pcdev->mclk = lcdclk / (2 * (div + 1));
 
-	dev_dbg(pcdev->dev, "LCD clock %luHz, target freq %luHz, "
+	dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
 		"divisor %u\n", lcdclk, mclk, div);
 
 	return div;
@@ -884,12 +872,12 @@
 	struct pxacamera_platform_data *pdata = pcdev->pdata;
 	u32 cicr4 = 0;
 
-	dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n",
+	dev_dbg(pcdev->soc_host.dev, "Registered platform device at %p data %p\n",
 		pcdev, pdata);
 
 	if (pdata && pdata->init) {
-		dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
-		pdata->init(pcdev->dev);
+		dev_dbg(pcdev->soc_host.dev, "%s: Init gpios\n", __func__);
+		pdata->init(pcdev->soc_host.dev);
 	}
 
 	/* disable all interrupts */
@@ -931,7 +919,7 @@
 	struct videobuf_buffer *vb;
 
 	status = __raw_readl(pcdev->base + CISR);
-	dev_dbg(pcdev->dev, "Camera interrupt status 0x%lx\n", status);
+	dev_dbg(pcdev->soc_host.dev, "Camera interrupt status 0x%lx\n", status);
 
 	if (!status)
 		return IRQ_NONE;
@@ -1259,7 +1247,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = buswidth;
 			xlate++;
-			dev_dbg(&ici->dev, "Providing format %s using %s\n",
+			dev_dbg(ici->dev, "Providing format %s using %s\n",
 				pxa_camera_formats[0].name,
 				icd->formats[idx].name);
 		}
@@ -1274,7 +1262,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = buswidth;
 			xlate++;
-			dev_dbg(&ici->dev, "Providing format %s packed\n",
+			dev_dbg(ici->dev, "Providing format %s packed\n",
 				icd->formats[idx].name);
 		}
 		break;
@@ -1286,7 +1274,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = icd->formats[idx].depth;
 			xlate++;
-			dev_dbg(&ici->dev,
+			dev_dbg(ici->dev,
 				"Providing format %s in pass-through mode\n",
 				icd->formats[idx].name);
 		}
@@ -1315,11 +1303,11 @@
 	icd->sense = NULL;
 
 	if (ret < 0) {
-		dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n",
+		dev_warn(ici->dev, "Failed to crop to %ux%u@%u:%u\n",
 			 rect->width, rect->height, rect->left, rect->top);
 	} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
 		if (sense.pixel_clock > sense.pixel_clock_max) {
-			dev_err(&ici->dev,
+			dev_err(ici->dev,
 				"pixel clock %lu set by the camera too high!",
 				sense.pixel_clock);
 			return -EIO;
@@ -1347,7 +1335,7 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
 	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+		dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
 		return -EINVAL;
 	}
 
@@ -1363,11 +1351,11 @@
 	icd->sense = NULL;
 
 	if (ret < 0) {
-		dev_warn(&ici->dev, "Failed to configure for format %x\n",
+		dev_warn(ici->dev, "Failed to configure for format %x\n",
 			 pix->pixelformat);
 	} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
 		if (sense.pixel_clock > sense.pixel_clock_max) {
-			dev_err(&ici->dev,
+			dev_err(ici->dev,
 				"pixel clock %lu set by the camera too high!",
 				sense.pixel_clock);
 			return -EIO;
@@ -1395,32 +1383,19 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+		dev_warn(ici->dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
-	/* limit to pxa hardware capabilities */
-	if (pix->height < 32)
-		pix->height = 32;
-	if (pix->height > 2048)
-		pix->height = 2048;
-	if (pix->width < 48)
-		pix->width = 48;
-	if (pix->width > 2048)
-		pix->width = 2048;
-	pix->width &= ~0x01;
-
 	/*
-	 * YUV422P planar format requires images size to be a 16 bytes
-	 * multiple. If not, zeros will be inserted between Y and U planes, and
-	 * U and V planes, and YUV422P standard would be violated.
+	 * Limit to pxa hardware capabilities.  YUV422P planar format requires
+	 * images size to be a multiple of 16 bytes.  If not, zeros will be
+	 * inserted between Y and U planes, and U and V planes, which violates
+	 * the YUV422P standard.
 	 */
-	if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P) {
-		if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN))
-			pix->height = ALIGN(pix->height, YUV422P_X_Y_ALIGN);
-		if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN))
-			pix->width = ALIGN(pix->width, YUV422P_X_Y_ALIGN);
-	}
+	v4l_bound_align_image(&pix->width, 48, 2048, 1,
+			      &pix->height, 32, 2048, 0,
+			      xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
 
 	pix->bytesperline = pix->width *
 		DIV_ROUND_UP(xlate->host_fmt->depth, 8);
@@ -1552,13 +1527,7 @@
 	.set_bus_param	= pxa_camera_set_bus_param,
 };
 
-/* Should be allocated dynamically too, but we have only one. */
-static struct soc_camera_host pxa_soc_camera_host = {
-	.drv_name		= PXA_CAM_DRV_NAME,
-	.ops			= &pxa_soc_camera_host_ops,
-};
-
-static int pxa_camera_probe(struct platform_device *pdev)
+static int __devinit pxa_camera_probe(struct platform_device *pdev)
 {
 	struct pxa_camera_dev *pcdev;
 	struct resource *res;
@@ -1586,7 +1555,6 @@
 		goto exit_kfree;
 	}
 
-	dev_set_drvdata(&pdev->dev, pcdev);
 	pcdev->res = res;
 
 	pcdev->pdata = pdev->dev.platform_data;
@@ -1607,7 +1575,7 @@
 		pcdev->mclk = 20000000;
 	}
 
-	pcdev->dev = &pdev->dev;
+	pcdev->soc_host.dev = &pdev->dev;
 	pcdev->mclk_divisor = mclk_get_divisor(pcdev);
 
 	INIT_LIST_HEAD(&pcdev->capture);
@@ -1616,13 +1584,13 @@
 	/*
 	 * Request the regions.
 	 */
-	if (!request_mem_region(res->start, res->end - res->start + 1,
+	if (!request_mem_region(res->start, resource_size(res),
 				PXA_CAM_DRV_NAME)) {
 		err = -EBUSY;
 		goto exit_clk;
 	}
 
-	base = ioremap(res->start, res->end - res->start + 1);
+	base = ioremap(res->start, resource_size(res));
 	if (!base) {
 		err = -ENOMEM;
 		goto exit_release;
@@ -1634,29 +1602,29 @@
 	err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
 			      pxa_camera_dma_irq_y, pcdev);
 	if (err < 0) {
-		dev_err(pcdev->dev, "Can't request DMA for Y\n");
+		dev_err(&pdev->dev, "Can't request DMA for Y\n");
 		goto exit_iounmap;
 	}
 	pcdev->dma_chans[0] = err;
-	dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
+	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
 
 	err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
 			      pxa_camera_dma_irq_u, pcdev);
 	if (err < 0) {
-		dev_err(pcdev->dev, "Can't request DMA for U\n");
+		dev_err(&pdev->dev, "Can't request DMA for U\n");
 		goto exit_free_dma_y;
 	}
 	pcdev->dma_chans[1] = err;
-	dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
+	dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
 
 	err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
 			      pxa_camera_dma_irq_v, pcdev);
 	if (err < 0) {
-		dev_err(pcdev->dev, "Can't request DMA for V\n");
+		dev_err(&pdev->dev, "Can't request DMA for V\n");
 		goto exit_free_dma_u;
 	}
 	pcdev->dma_chans[2] = err;
-	dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
+	dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
 
 	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
 	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
@@ -1666,14 +1634,16 @@
 	err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
 			  pcdev);
 	if (err) {
-		dev_err(pcdev->dev, "Camera interrupt register failed \n");
+		dev_err(&pdev->dev, "Camera interrupt register failed \n");
 		goto exit_free_dma;
 	}
 
-	pxa_soc_camera_host.priv	= pcdev;
-	pxa_soc_camera_host.dev.parent	= &pdev->dev;
-	pxa_soc_camera_host.nr		= pdev->id;
-	err = soc_camera_host_register(&pxa_soc_camera_host);
+	pcdev->soc_host.drv_name	= PXA_CAM_DRV_NAME;
+	pcdev->soc_host.ops		= &pxa_soc_camera_host_ops;
+	pcdev->soc_host.priv		= pcdev;
+	pcdev->soc_host.nr		= pdev->id;
+
+	err = soc_camera_host_register(&pcdev->soc_host);
 	if (err)
 		goto exit_free_irq;
 
@@ -1690,7 +1660,7 @@
 exit_iounmap:
 	iounmap(base);
 exit_release:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 exit_clk:
 	clk_put(pcdev->clk);
 exit_kfree:
@@ -1701,7 +1671,9 @@
 
 static int __devexit pxa_camera_remove(struct platform_device *pdev)
 {
-	struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
+	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+	struct pxa_camera_dev *pcdev = container_of(soc_host,
+					struct pxa_camera_dev, soc_host);
 	struct resource *res;
 
 	clk_put(pcdev->clk);
@@ -1711,12 +1683,12 @@
 	pxa_free_dma(pcdev->dma_chans[2]);
 	free_irq(pcdev->irq, pcdev);
 
-	soc_camera_host_unregister(&pxa_soc_camera_host);
+	soc_camera_host_unregister(soc_host);
 
 	iounmap(pcdev->base);
 
 	res = pcdev->res;
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 	kfree(pcdev);
 
@@ -1730,11 +1702,11 @@
 		.name	= PXA_CAM_DRV_NAME,
 	},
 	.probe		= pxa_camera_probe,
-	.remove		= __exit_p(pxa_camera_remove),
+	.remove		= __devexit_p(pxa_camera_remove),
 };
 
 
-static int __devinit pxa_camera_init(void)
+static int __init pxa_camera_init(void)
 {
 	return platform_driver_register(&pxa_camera_driver);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/s2255drv.c linux-libre-2.6.31-gnu/drivers/media/video/s2255drv.c
--- linux-libre-2.6.30-gnu/drivers/media/video/s2255drv.c	2012-03-22 19:14:08.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/s2255drv.c	2012-03-22 20:10:19.000000000 -0400
@@ -48,6 +48,7 @@
 #include <linux/videodev2.h>
 #include <linux/version.h>
 #include <linux/mm.h>
+#include <linux/smp_lock.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
@@ -77,6 +78,8 @@
 #define MAX_CHANNELS		4
 #define S2255_MARKER_FRAME	0x2255DA4AL
 #define S2255_MARKER_RESPONSE	0x2255ACACL
+#define S2255_RESPONSE_SETMODE  0x01
+#define S2255_RESPONSE_FW       0x10
 #define S2255_USB_XFER_SIZE	(16 * 1024)
 #define MAX_CHANNELS		4
 #define MAX_PIPE_BUFFERS	1
@@ -107,6 +110,8 @@
 #define SCALE_4CIFS	1	/* 640x480(NTSC) or 704x576(PAL) */
 #define SCALE_2CIFS	2	/* 640x240(NTSC) or 704x288(PAL) */
 #define SCALE_1CIFS	3	/* 320x240(NTSC) or 352x288(PAL) */
+/* SCALE_4CIFSI is the 2 fields interpolated into one */
+#define SCALE_4CIFSI	4	/* 640x480(NTSC) or 704x576(PAL) high quality */
 
 #define COLOR_YUVPL	1	/* YUV planar */
 #define COLOR_YUVPK	2	/* YUV packed */
@@ -178,9 +183,6 @@
 
 struct s2255_dmaqueue {
 	struct list_head	active;
-	/* thread for acquisition */
-	struct task_struct	*kthread;
-	int			frame;
 	struct s2255_dev	*dev;
 	int			channel;
 };
@@ -210,16 +212,11 @@
 	u32 max_transfer_size;
 	u32 cur_transfer_size;
 	u8 *transfer_buffer;
-	u32 transfer_flags;;
 	u32 state;
-	u32 prev_state;
-	u32 urb_size;
 	void *stream_urb;
 	void *dev;	/* back pointer to s2255_dev struct*/
 	u32 err_count;
-	u32 buf_index;
 	u32 idx;
-	u32 priority_set;
 };
 
 struct s2255_fmt; /*forward declaration */
@@ -239,13 +236,13 @@
 	struct list_head	s2255_devlist;
 	struct timer_list	timer;
 	struct s2255_fw	*fw_data;
-	int			board_num;
-	int			is_open;
 	struct s2255_pipeinfo	pipes[MAX_PIPE_BUFFERS];
 	struct s2255_bufferi		buffer[MAX_CHANNELS];
 	struct s2255_mode	mode[MAX_CHANNELS];
 	/* jpeg compression */
 	struct v4l2_jpegcompression jc[MAX_CHANNELS];
+	/* capture parameters (for high quality mode full size) */
+	struct v4l2_captureparm cap_parm[MAX_CHANNELS];
 	const struct s2255_fmt	*cur_fmt[MAX_CHANNELS];
 	int			cur_frame[MAX_CHANNELS];
 	int			last_frame[MAX_CHANNELS];
@@ -297,9 +294,10 @@
 	int			resources[MAX_CHANNELS];
 };
 
-#define CUR_USB_FWVER	774	/* current cypress EEPROM firmware version */
+/* current cypress EEPROM firmware version */
+#define S2255_CUR_USB_FWVER	((3 << 8) | 6)
 #define S2255_MAJOR_VERSION	1
-#define S2255_MINOR_VERSION	13
+#define S2255_MINOR_VERSION	14
 #define S2255_RELEASE		0
 #define S2255_VERSION		KERNEL_VERSION(S2255_MAJOR_VERSION, \
 					       S2255_MINOR_VERSION, \
@@ -1027,9 +1025,16 @@
 	fh->type = f->type;
 	norm = norm_minw(fh->dev->vdev[fh->channel]);
 	if (fh->width > norm_minw(fh->dev->vdev[fh->channel])) {
-		if (fh->height > norm_minh(fh->dev->vdev[fh->channel]))
-			fh->mode.scale = SCALE_4CIFS;
-		else
+		if (fh->height > norm_minh(fh->dev->vdev[fh->channel])) {
+			if (fh->dev->cap_parm[fh->channel].capturemode &
+			    V4L2_MODE_HIGHQUALITY) {
+				fh->mode.scale = SCALE_4CIFSI;
+				dprintk(2, "scale 4CIFSI\n");
+			} else {
+				fh->mode.scale = SCALE_4CIFS;
+				dprintk(2, "scale 4CIFS\n");
+			}
+		} else
 			fh->mode.scale = SCALE_2CIFS;
 
 	} else {
@@ -1130,6 +1135,7 @@
 	if (mode->format == FORMAT_NTSC) {
 		switch (mode->scale) {
 		case SCALE_4CIFS:
+		case SCALE_4CIFSI:
 			linesPerFrame = NUM_LINES_4CIFS_NTSC * 2;
 			pixelsPerLine = LINE_SZ_4CIFS_NTSC;
 			break;
@@ -1147,6 +1153,7 @@
 	} else if (mode->format == FORMAT_PAL) {
 		switch (mode->scale) {
 		case SCALE_4CIFS:
+		case SCALE_4CIFSI:
 			linesPerFrame = NUM_LINES_4CIFS_PAL * 2;
 			pixelsPerLine = LINE_SZ_4CIFS_PAL;
 			break;
@@ -1502,6 +1509,33 @@
 	dprintk(2, "setting jpeg quality %d\n", jc->quality);
 	return 0;
 }
+
+static int vidioc_g_parm(struct file *file, void *priv,
+			 struct v4l2_streamparm *sp)
+{
+	struct s2255_fh *fh = priv;
+	struct s2255_dev *dev = fh->dev;
+	if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	sp->parm.capture.capturemode = dev->cap_parm[fh->channel].capturemode;
+	dprintk(2, "getting parm %d\n", sp->parm.capture.capturemode);
+	return 0;
+}
+
+static int vidioc_s_parm(struct file *file, void *priv,
+			 struct v4l2_streamparm *sp)
+{
+	struct s2255_fh *fh = priv;
+	struct s2255_dev *dev = fh->dev;
+
+	if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	dev->cap_parm[fh->channel].capturemode = sp->parm.capture.capturemode;
+	dprintk(2, "setting param capture mode %d\n",
+		sp->parm.capture.capturemode);
+	return 0;
+}
 static int s2255_open(struct file *file)
 {
 	int minor = video_devdata(file)->minor;
@@ -1793,6 +1827,8 @@
 #endif
 	.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
 	.vidioc_g_jpegcomp = vidioc_g_jpegcomp,
+	.vidioc_s_parm = vidioc_s_parm,
+	.vidioc_g_parm = vidioc_g_parm,
 };
 
 static struct video_device template = {
@@ -1818,7 +1854,6 @@
 		INIT_LIST_HEAD(&dev->vidq[i].active);
 		dev->vidq[i].dev = dev;
 		dev->vidq[i].channel = i;
-		dev->vidq[i].kthread = NULL;
 		/* register 4 video devices */
 		dev->vdev[i] = video_device_alloc();
 		memcpy(dev->vdev[i], &template, sizeof(struct video_device));
@@ -1839,7 +1874,9 @@
 			return ret;
 		}
 	}
-	printk(KERN_INFO "Sensoray 2255 V4L driver\n");
+	printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n",
+	       S2255_MAJOR_VERSION,
+	       S2255_MINOR_VERSION);
 	return ret;
 }
 
@@ -1929,14 +1966,14 @@
 				if (!(cc >= 0 && cc < MAX_CHANNELS))
 					break;
 				switch (pdword[2]) {
-				case 0x01:
+				case S2255_RESPONSE_SETMODE:
 					/* check if channel valid */
 					/* set mode ready */
 					dev->setmode_ready[cc] = 1;
 					wake_up(&dev->wait_setmode[cc]);
 					dprintk(5, "setmode ready %d\n", cc);
 					break;
-				case 0x10:
+				case S2255_RESPONSE_FW:
 
 					dev->chn_ready |= (1 << cc);
 					if ((dev->chn_ready & 0x0f) != 0x0f)
@@ -2172,10 +2209,15 @@
 	/* query the firmware */
 	fw_ver = s2255_get_fx2fw(dev);
 
-	printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver);
-	if (fw_ver < CUR_USB_FWVER)
+	printk(KERN_INFO "2255 usb firmware version %d.%d\n",
+	       (fw_ver >> 8) & 0xff,
+	       fw_ver & 0xff);
+
+	if (fw_ver < S2255_CUR_USB_FWVER)
 		dev_err(&dev->udev->dev,
-			"usb firmware not up to date %d\n", fw_ver);
+			"usb firmware not up to date %d.%d\n",
+			(fw_ver >> 8) & 0xff,
+			fw_ver & 0xff);
 
 	for (j = 0; j < MAX_CHANNELS; j++) {
 		dev->b_acquire[j] = 0;
@@ -2240,8 +2282,10 @@
 		return;
 	}
 	status = purb->status;
-	if (status != 0) {
-		dprintk(2, "read_pipe_completion: err\n");
+	/* if shutting down, do not resubmit, exit immediately */
+	if (status == -ESHUTDOWN) {
+		dprintk(2, "read_pipe_completion: err shutdown\n");
+		pipe_info->err_count++;
 		return;
 	}
 
@@ -2250,9 +2294,13 @@
 		return;
 	}
 
-	s2255_read_video_callback(dev, pipe_info);
+	if (status == 0)
+		s2255_read_video_callback(dev, pipe_info);
+	else {
+		pipe_info->err_count++;
+		dprintk(1, "s2255drv: failed URB %d\n", status);
+	}
 
-	pipe_info->err_count = 0;
 	pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
 	/* reuse urb */
 	usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
@@ -2264,7 +2312,6 @@
 	if (pipe_info->state != 0) {
 		if (usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL)) {
 			dev_err(&dev->udev->dev, "error submitting urb\n");
-			usb_free_urb(pipe_info->stream_urb);
 		}
 	} else {
 		dprintk(2, "read pipe complete state 0\n");
@@ -2283,8 +2330,7 @@
 
 	for (i = 0; i < MAX_PIPE_BUFFERS; i++) {
 		pipe_info->state = 1;
-		pipe_info->buf_index = (u32) i;
-		pipe_info->priority_set = 0;
+		pipe_info->err_count = 0;
 		pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!pipe_info->stream_urb) {
 			dev_err(&dev->udev->dev,
@@ -2298,7 +2344,6 @@
 				  pipe_info->cur_transfer_size,
 				  read_pipe_completion, pipe_info);
 
-		pipe_info->urb_size = sizeof(pipe_info->stream_urb);
 		dprintk(4, "submitting URB %p\n", pipe_info->stream_urb);
 		retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
 		if (retval) {
@@ -2403,8 +2448,6 @@
 			if (pipe_info->state == 0)
 				continue;
 			pipe_info->state = 0;
-			pipe_info->prev_state = 1;
-
 		}
 	}
 
@@ -2542,7 +2585,9 @@
 	s2255_probe_v4l(dev);
 	usb_reset_device(dev->udev);
 	/* load 2255 board specific */
-	s2255_board_init(dev);
+	retval = s2255_board_init(dev);
+	if (retval)
+		goto error;
 
 	dprintk(4, "before probe done %p\n", dev);
 	spin_lock_init(&dev->slock);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa5246a.c linux-libre-2.6.31-gnu/drivers/media/video/saa5246a.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa5246a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa5246a.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,7 +43,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/videotext.h>
 #include <linux/videodev2.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa5249.c linux-libre-2.6.31-gnu/drivers/media/video/saa5249.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa5249.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa5249.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/videotext.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/Kconfig linux-libre-2.6.31-gnu/drivers/media/video/saa7134/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -44,6 +44,7 @@
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
 	select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+	select DVB_TDA10048 if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
 	---help---
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/Makefile linux-libre-2.6.31-gnu/drivers/media/video/saa7134/Makefile
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,8 +3,7 @@
 		saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o    \
 		saa7134-video.o saa7134-input.o
 
-obj-$(CONFIG_VIDEO_SAA7134) +=  saa7134.o saa7134-empress.o \
-				saa6752hs.o
+obj-$(CONFIG_VIDEO_SAA7134) +=  saa6752hs.o saa7134.o saa7134-empress.o
 
 obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-cards.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-cards.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-cards.c	2012-03-22 19:11:43.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-cards.c	2012-03-22 20:08:07.000000000 -0400
@@ -1669,6 +1669,39 @@
 			.amux = LINE1,
 		},
 	},
+	[SAA7134_BOARD_AVERMEDIA_CARDBUS_501] = {
+		/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
+		.name           = "AVerMedia Cardbus TV/Radio (E501R)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_ALPS_TSBE5_PAL,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr	= 0x61,
+		.radio_addr	= 0x60,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x08000000,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x08000000,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x08000000,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x08000000,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x00000000,
+		},
+	},
 	[SAA7134_BOARD_CINERGY400_CARDBUS] = {
 		.name           = "Terratec Cinergy 400 mobile",
 		.audio_clock    = 0x187de7,
@@ -3298,8 +3331,8 @@
 			.gpio = 0x0200100,
 		},
 	},
-	[SAA7134_BOARD_HAUPPAUGE_HVR1120] = {
-		.name           = "Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid",
+	[SAA7134_BOARD_HAUPPAUGE_HVR1150] = {
+		.name           = "Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_TDA8290,
 		.radio_type     = UNSET,
@@ -3330,14 +3363,16 @@
 			.gpio = 0x0800100, /* GPIO 23 HI for FM */
 		},
 	},
-	[SAA7134_BOARD_HAUPPAUGE_HVR1110R3] = {
-		.name           = "Hauppauge WinTV-HVR1110r3",
+	[SAA7134_BOARD_HAUPPAUGE_HVR1120] = {
+		.name           = "Hauppauge WinTV-HVR1120 DVB-T/Hybrid",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_TDA8290,
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.tuner_config   = 3,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.ts_type	= SAA7134_MPEG_TS_SERIAL,
 		.gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
 		.inputs         = {{
 			.name = name_tv,
@@ -4006,7 +4041,7 @@
 	[SAA7134_BOARD_BEHOLD_505FM] = {
 		/*       Beholder Intl. Ltd. 2008      */
 		/*Dmitry Belimov <d.belimov@gmail.com> */
-		.name           = "Beholder BeholdTV 505 FM/RDS",
+		.name           = "Beholder BeholdTV 505 FM",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
 		.radio_type     = UNSET,
@@ -4019,6 +4054,40 @@
 			.vmux = 3,
 			.amux = LINE2,
 			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_505RDS] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 505 RDS",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
 		},{
 			.name = name_comp1,
 			.vmux = 1,
@@ -4040,7 +4109,7 @@
 	[SAA7134_BOARD_BEHOLD_507_9FM] = {
 		/*       Beholder Intl. Ltd. 2008      */
 		/*Dmitry Belimov <d.belimov@gmail.com> */
-		.name           = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM",
+		.name           = "Beholder BeholdTV 507 FM / BeholdTV 509 FM",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
 		.radio_type     = UNSET,
@@ -4067,6 +4136,66 @@
 			.amux = LINE2,
 		},
 	},
+	[SAA7134_BOARD_BEHOLD_507RDS_MK5] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 507 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+			.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_507RDS_MK3] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 507 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+			.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
 	[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
 		/*       Beholder Intl. Ltd. 2008      */
 		/*Dmitry Belimov <d.belimov@gmail.com> */
@@ -4101,9 +4230,149 @@
 			.gpio = 0x000A8000,
 		},
 	},
-	[SAA7134_BOARD_BEHOLD_607_9FM] = {
+	[SAA7134_BOARD_BEHOLD_607FM_MK3] = {
 		/* Andrey Melnikoff <temnota@kmv.ru> */
-		.name           = "Beholder BeholdTV 607 / BeholdTV 609",
+		.name           = "Beholder BeholdTV 607 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609FM_MK3] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_607FM_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 607 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609FM_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_607RDS_MK3] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 607 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609RDS_MK3] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 RDS",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
 		.radio_type     = UNSET,
@@ -4115,6 +4384,62 @@
 			.vmux = 3,
 			.amux = TV,
 			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_607RDS_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 607 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609RDS_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
 		},{
 			.name = name_comp1,
 			.vmux = 1,
@@ -4133,6 +4458,7 @@
 		/* Igor Kuznetsov <igk@igk.ru> */
 		/* Andrey Melnikoff <temnota@kmv.ru> */
 		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		/* Alexey Osipov <lion-simba@pridelands.ru> */
 		.name           = "Beholder BeholdTV M6",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
@@ -4207,10 +4533,10 @@
 		/* Igor Kuznetsov <igk@igk.ru> */
 		/* Andrey Melnikoff <temnota@kmv.ru> */
 		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		/* Alexey Osipov <lion-simba@pridelands.ru> */
 		.name           = "Beholder BeholdTV M6 Extra",
 		.audio_clock    = 0x00187de7,
-		/* FIXME: Must be PHILIPS_FM1216ME_MK5*/
-		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
@@ -4465,7 +4791,6 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs = {{
 			.name   = name_tv,
 			.vmux   = 3,
@@ -4753,6 +5078,44 @@
 			.gpio = 0x01,
 		},
 	},
+	[SAA7134_BOARD_AVERMEDIA_STUDIO_507UA] = {
+		/* Andy Shevchenko <andy@smile.org.ua> */
+		.name           = "Avermedia AVerTV Studio 507UA",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* Should be MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x03,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x00,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x00,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x00,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x01,
+		},
+		.mute  = {
+			.name = name_mute,
+			.amux = LINE1,
+			.gpio = 0x00,
+		},
+	},
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -5027,6 +5390,13 @@
 		.subdevice    = 0xd6ee,
 		.driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS,
 	},{
+		/* AVerMedia CardBus */
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xb7e9,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_501,
+	}, {
 		/* TransGear 3000TV */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
@@ -5441,6 +5811,12 @@
 		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa11b,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x1043,
 		.subdevice    = 0x4876,
@@ -5486,31 +5862,31 @@
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x0070,
 		.subdevice    = 0x6706,
-		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x0070,
 		.subdevice    = 0x6707,
-		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x0070,
 		.subdevice    = 0x6708,
-		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x0070,
 		.subdevice    = 0x6709,
-		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x0070,
 		.subdevice    = 0x670a,
-		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -5647,14 +6023,8 @@
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
 		.subvendor    = 0x0000,
-		.subdevice    = 0x5051,
-		.driver_data  = SAA7134_BOARD_BEHOLD_505FM,
-	},{
-		.vendor       = PCI_VENDOR_ID_PHILIPS,
-		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-		.subvendor    = 0x0000,
 		.subdevice    = 0x505B,
-		.driver_data  = SAA7134_BOARD_BEHOLD_505FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_505RDS,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
@@ -5666,13 +6036,13 @@
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x0000,
 		.subdevice    = 0x5071,
-		.driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK3,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x0000,
 		.subdevice    = 0x507B,
-		.driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK5,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5696,49 +6066,49 @@
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6070,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK3,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6071,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK5,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6072,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK3,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6073,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK5,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6090,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK3,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6091,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK5,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6092,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK3,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x5ace,
 		.subdevice    = 0x6093,
-		.driver_data  = SAA7134_BOARD_BEHOLD_607_9FM,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK5,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -5832,6 +6202,12 @@
 	}, {
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf736,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x1043,
 		.subdevice    = 0x4878, /* REV:1.02G */
 		.driver_data  = SAA7134_BOARD_ASUSTeK_TIGER_3IN1,
@@ -5987,8 +6363,8 @@
 	switch (command) {
 	case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */
 		switch (dev->board) {
+		case SAA7134_BOARD_HAUPPAUGE_HVR1150:
 		case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-		case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
 			ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg);
 			break;
 		default:
@@ -6008,8 +6384,8 @@
 	int ret;
 
 	switch (dev->board) {
+	case SAA7134_BOARD_HAUPPAUGE_HVR1150:
 	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-	case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
 		/* tda8290 + tda18271 */
 		ret = saa7134_tda8290_18271_callback(dev, command, arg);
 		break;
@@ -6051,7 +6427,7 @@
 	switch (tv.model) {
 	case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */
 	case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
-	case 67201: /* WinTV-HVR1120 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
+	case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
 	case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
 	case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
 	case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
@@ -6059,7 +6435,7 @@
 	case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */
 	case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
 	case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
-	case 67651: /* WinTV-HVR1120 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
+	case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
 	case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
 		break;
 	default:
@@ -6114,7 +6490,6 @@
 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
-	case SAA7134_BOARD_VIDEOMATE_T750:
 	case SAA7134_BOARD_MANLI_MTV001:
 	case SAA7134_BOARD_MANLI_MTV002:
 	case SAA7134_BOARD_BEHOLD_409FM:
@@ -6142,7 +6517,10 @@
 	case SAA7134_BOARD_BEHOLD_407FM:
 	case SAA7134_BOARD_BEHOLD_409:
 	case SAA7134_BOARD_BEHOLD_505FM:
+	case SAA7134_BOARD_BEHOLD_505RDS:
 	case SAA7134_BOARD_BEHOLD_507_9FM:
+	case SAA7134_BOARD_BEHOLD_507RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_507RDS_MK5:
 	case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
 	case SAA7134_BOARD_REAL_ANGEL_220:
 	case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
@@ -6196,6 +6574,16 @@
 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
 		msleep(10);
 		break;
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+		/* power-down tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0);
+		msleep(10);
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0x08400000);
+		msleep(10);
+		dev->has_remote = SAA7134_REMOTE_I2C;
+		break;
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
 		saa7134_set_gpio(dev, 23, 0);
 		msleep(10);
@@ -6237,8 +6625,8 @@
 
 		saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00);
 		break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1150:
 	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-	case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
 		/* GPIO 26 high for digital, low for analog */
 		saa7134_set_gpio(dev, 26, 0);
 		msleep(1);
@@ -6253,7 +6641,14 @@
 	case SAA7134_BOARD_UPMOST_PURPLE_TV:
 	case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
 	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-	case SAA7134_BOARD_BEHOLD_607_9FM:
+	case SAA7134_BOARD_BEHOLD_607FM_MK3:
+	case SAA7134_BOARD_BEHOLD_607FM_MK5:
+	case SAA7134_BOARD_BEHOLD_609FM_MK3:
+	case SAA7134_BOARD_BEHOLD_609FM_MK5:
+	case SAA7134_BOARD_BEHOLD_607RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_607RDS_MK5:
+	case SAA7134_BOARD_BEHOLD_609RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_609RDS_MK5:
 	case SAA7134_BOARD_BEHOLD_M6:
 	case SAA7134_BOARD_BEHOLD_M63:
 	case SAA7134_BOARD_BEHOLD_M6_EXTRA:
@@ -6496,8 +6891,8 @@
 		       dev->name, saa7134_boards[dev->board].name);
 	       }
 	       break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1150:
 	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-	case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
 		hauppauge_eeprom(dev, dev->eedata+0x80);
 		break;
 	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
@@ -6635,6 +7030,7 @@
 
 	switch (dev->board) {
 	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
 	{
 		struct v4l2_priv_tun_config tea5767_cfg;
 		struct tea5767_ctrl ctl;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-core.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -331,6 +331,10 @@
 		dprintk("buffer_next %p\n",NULL);
 		saa7134_set_dmabits(dev);
 		del_timer(&q->timeout);
+
+		if (card_has_mpeg(dev))
+			if (dev->ts_started)
+				saa7134_ts_stop(dev);
 	}
 }
 
@@ -416,6 +420,19 @@
 		ctrl |= SAA7134_MAIN_CTRL_TE5;
 		irq  |= SAA7134_IRQ1_INTE_RA2_1 |
 			SAA7134_IRQ1_INTE_RA2_0;
+
+		/* dma: setup channel 5 (= TS) */
+
+		saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
+		saa_writeb(SAA7134_TS_DMA1,
+			((dev->ts.nr_packets - 1) >> 8) & 0xff);
+		/* TSNOPIT=0, TSCOLAP=0 */
+		saa_writeb(SAA7134_TS_DMA2,
+			(((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
+		saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+		saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
+						  SAA7134_RS_CONTROL_ME |
+						  (dev->ts.pt_ts.dma >> 12));
 	}
 
 	/* set task conditions + field handling */
@@ -775,7 +792,6 @@
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor   = -1;
 	vfd->v4l2_dev  = &dev->v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug   = video_debug;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-dvb.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-dvb.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-dvb.c	2012-03-22 19:13:56.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-dvb.c	2012-03-22 20:10:09.000000000 -0400
@@ -48,6 +48,7 @@
 #include "isl6405.h"
 #include "lnbp21.h"
 #include "tuner-simple.h"
+#include "tda10048.h"
 #include "tda18271.h"
 #include "lgdt3305.h"
 #include "tda8290.h"
@@ -978,6 +979,18 @@
 	.vsb_if_khz         = 3250,
 };
 
+static struct tda10048_config hcw_tda10048_config = {
+	.demod_address    = 0x10 >> 1,
+	.output_mode      = TDA10048_SERIAL_OUTPUT,
+	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
+	.inversion        = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_3300,
+	.dtv7_if_freq_khz = TDA10048_IF_3500,
+	.dtv8_if_freq_khz = TDA10048_IF_4000,
+	.clk_freq_khz     = TDA10048_CLK_16000,
+	.disable_gate_access = 1,
+};
+
 static struct tda18271_std_map hauppauge_tda18271_std_map = {
 	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
 		      .if_lvl = 1, .rfagc_top = 0x58, },
@@ -1106,6 +1119,19 @@
 					 &tda827x_cfg_2) < 0)
 			goto dettach_frontend;
 		break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+		fe0->dvb.frontend = dvb_attach(tda10048_attach,
+					       &hcw_tda10048_config,
+					       &dev->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda829x_attach, fe0->dvb.frontend,
+				   &dev->i2c_adap, 0x4b,
+				   &tda829x_no_probe);
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_adap,
+				   &hcw_tda18271_config);
+		}
+		break;
 	case SAA7134_BOARD_PHILIPS_TIGER:
 		if (configure_tda827x_fe(dev, &philips_tiger_config,
 					 &tda827x_cfg_0) < 0)
@@ -1121,7 +1147,7 @@
 					 &tda827x_cfg_1) < 0)
 			goto dettach_frontend;
 		break;
-	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1150:
 		fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
 					       &hcw_lgdt3305_config,
 					       &dev->i2c_adap);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-empress.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-empress.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-empress.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-empress.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/delay.h>
 
 #include "saa7134-reg.h"
@@ -255,6 +256,16 @@
 	return 0;
 }
 
+static int empress_try_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct saa7134_dev *dev = file->private_data;
+
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
+
+	return 0;
+}
 
 static int empress_reqbufs(struct file *file, void *priv,
 					struct v4l2_requestbuffers *p)
@@ -450,6 +461,7 @@
 static const struct v4l2_ioctl_ops ts_ioctl_ops = {
 	.vidioc_querycap		= empress_querycap,
 	.vidioc_enum_fmt_vid_cap	= empress_enum_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap		= empress_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap		= empress_s_fmt_vid_cap,
 	.vidioc_g_fmt_vid_cap		= empress_g_fmt_vid_cap,
 	.vidioc_reqbufs			= empress_reqbufs,
@@ -491,11 +503,8 @@
 
 	if (dev->nosignal) {
 		dprintk("no video signal\n");
-		ts_reset_encoder(dev);
 	} else {
 		dprintk("video signal acquired\n");
-		if (atomic_read(&dev->empress_users))
-			ts_init_encoder(dev);
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134.h linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134.h
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134.h	2009-09-09 18:13:59.000000000 -0400
@@ -252,7 +252,7 @@
 #define SAA7134_BOARD_BEHOLD_505FM	126
 #define SAA7134_BOARD_BEHOLD_507_9FM	127
 #define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128
-#define SAA7134_BOARD_BEHOLD_607_9FM	129
+#define SAA7134_BOARD_BEHOLD_607FM_MK3	129
 #define SAA7134_BOARD_BEHOLD_M6		130
 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
 #define SAA7134_BOARD_GENIUS_TVGO_A11MCE   132
@@ -278,8 +278,20 @@
 #define SAA7134_BOARD_ASUSTeK_TIGER         152
 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
-#define SAA7134_BOARD_HAUPPAUGE_HVR1120     155
-#define SAA7134_BOARD_HAUPPAUGE_HVR1110R3   156
+#define SAA7134_BOARD_HAUPPAUGE_HVR1150     155
+#define SAA7134_BOARD_HAUPPAUGE_HVR1120   156
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157
+#define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158
+#define SAA7134_BOARD_BEHOLD_505RDS         159
+#define SAA7134_BOARD_BEHOLD_507RDS_MK3     160
+#define SAA7134_BOARD_BEHOLD_507RDS_MK5     161
+#define SAA7134_BOARD_BEHOLD_607FM_MK5      162
+#define SAA7134_BOARD_BEHOLD_609FM_MK3      163
+#define SAA7134_BOARD_BEHOLD_609FM_MK5      164
+#define SAA7134_BOARD_BEHOLD_607RDS_MK3     165
+#define SAA7134_BOARD_BEHOLD_607RDS_MK5     166
+#define SAA7134_BOARD_BEHOLD_609RDS_MK3     167
+#define SAA7134_BOARD_BEHOLD_609RDS_MK5     168
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
@@ -364,6 +376,7 @@
 #define INTERLACE_OFF          2
 
 #define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
+#define TS_BUFFER_TIMEOUT  msecs_to_jiffies(1000)  /* 1 second */
 
 struct saa7134_dev;
 struct saa7134_dma;
@@ -480,12 +493,6 @@
 	void                       (*signal_change)(struct saa7134_dev *dev);
 };
 
-enum saa7134_ts_status {
-	SAA7134_TS_STOPPED,
-	SAA7134_TS_BUFF_DONE,
-	SAA7134_TS_STARTED,
-};
-
 /* global device status */
 struct saa7134_dev {
 	struct list_head           devlist;
@@ -580,8 +587,7 @@
 	/* SAA7134_MPEG_* */
 	struct saa7134_ts          ts;
 	struct saa7134_dmaqueue    ts_q;
-	enum saa7134_ts_status 	   ts_state;
-	unsigned int 		   buff_cnt;
+	int                        ts_started;
 	struct saa7134_mpeg_ops    *mops;
 
 	/* SAA7134_MPEG_EMPRESS only */
@@ -739,6 +745,9 @@
 
 int saa7134_ts_init_hw(struct saa7134_dev *dev);
 
+int saa7134_ts_start(struct saa7134_dev *dev);
+int saa7134_ts_stop(struct saa7134_dev *dev);
+
 /* ----------------------------------------------------------- */
 /* saa7134-vbi.c                                               */
 
@@ -786,7 +795,7 @@
 int  saa7134_input_init1(struct saa7134_dev *dev);
 void saa7134_input_fini(struct saa7134_dev *dev);
 void saa7134_input_irq(struct saa7134_dev *dev);
-void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
+void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
 void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir);
 void saa7134_ir_stop(struct saa7134_dev *dev);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-i2c.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-i2c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-i2c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-i2c.c	2009-09-09 18:13:59.000000000 -0400
@@ -259,7 +259,7 @@
 				/* workaround for a saa7134 i2c bug
 				 * needed to talk to the mt352 demux
 				 * thanks to pinnacle for the hint */
-				int quirk = 0xfd;
+				int quirk = 0xfe;
 				d1printk(" [%02x quirk]",quirk);
 				i2c_send_byte(dev,START,quirk);
 				i2c_recv_byte(dev);
@@ -321,33 +321,6 @@
 	return I2C_FUNC_SMBUS_EMUL;
 }
 
-static int attach_inform(struct i2c_client *client)
-{
-	struct saa7134_dev *dev = client->adapter->algo_data;
-
-	d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->driver.name, client->addr, client->name);
-
-	/* Am I an i2c remote control? */
-
-	switch (client->addr) {
-		case 0x7a:
-		case 0x47:
-		case 0x71:
-		case 0x2d:
-		case 0x30:
-		{
-			struct IR_i2c *ir = i2c_get_clientdata(client);
-			d1printk("%s i2c IR detected (%s).\n",
-				 client->driver->driver.name, ir->phys);
-			saa7134_set_i2c_ir(dev,ir);
-			break;
-		}
-	}
-
-	return 0;
-}
-
 static struct i2c_algorithm saa7134_algo = {
 	.master_xfer   = saa7134_i2c_xfer,
 	.functionality = functionality,
@@ -358,7 +331,6 @@
 	.name          = "saa7134",
 	.id            = I2C_HW_SAA7134,
 	.algo          = &saa7134_algo,
-	.client_register = attach_inform,
 };
 
 static struct i2c_client saa7134_client_template = {
@@ -433,6 +405,9 @@
 	saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
 	if (i2c_scan)
 		do_i2c_scan(dev->name,&dev->i2c_client);
+
+	/* Instantiate the IR receiver device, if present */
+	saa7134_probe_i2c_ir(dev);
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-input.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-input.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-input.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-input.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,7 +60,7 @@
 #define dprintk(fmt, arg...)	if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
-	printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
+	printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg)
 
 /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
 static int saa7134_rc5_irq(struct saa7134_dev *dev);
@@ -134,10 +134,10 @@
 	int gpio;
 
 	/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
-	struct saa7134_dev *dev = ir->c.adapter->algo_data;
+	struct saa7134_dev *dev = ir->c->adapter->algo_data;
 	if (dev == NULL) {
 		dprintk("get_key_msi_tvanywhere_plus: "
-			"gir->c.adapter->algo_data is NULL!\n");
+			"gir->c->adapter->algo_data is NULL!\n");
 		return -EIO;
 	}
 
@@ -156,7 +156,7 @@
 
 	/* GPIO says there is a button press. Get it. */
 
-	if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
 		i2cdprintk("read error\n");
 		return -EIO;
 	}
@@ -179,7 +179,7 @@
 	unsigned char b;
 
 	/* poll IR chip */
-	if (1 != i2c_master_recv(&ir->c,&b,1)) {
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
 		i2cdprintk("read error\n");
 		return -EIO;
 	}
@@ -202,7 +202,7 @@
 	unsigned char buf[5], cod4, code3, code4;
 
 	/* poll IR chip */
-	if (5 != i2c_master_recv(&ir->c,buf,5))
+	if (5 != i2c_master_recv(ir->c, buf, 5))
 		return -EIO;
 
 	cod4	= buf[4];
@@ -224,7 +224,7 @@
 	unsigned char data[12];
 	u32 gpio;
 
-	struct saa7134_dev *dev = ir->c.adapter->algo_data;
+	struct saa7134_dev *dev = ir->c->adapter->algo_data;
 
 	/* rising SAA7134_GPIO_GPRESCAN reads the status */
 	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
@@ -235,9 +235,9 @@
 	if (0x400000 & ~gpio)
 		return 0; /* No button press */
 
-	ir->c.addr = 0x5a >> 1;
+	ir->c->addr = 0x5a >> 1;
 
-	if (12 != i2c_master_recv(&ir->c, data, 12)) {
+	if (12 != i2c_master_recv(ir->c, data, 12)) {
 		i2cdprintk("read error\n");
 		return -EIO;
 	}
@@ -267,7 +267,7 @@
 	unsigned int start = 0,parity = 0,code = 0;
 
 	/* poll IR chip */
-	if (4 != i2c_master_recv(&ir->c, b, 4)) {
+	if (4 != i2c_master_recv(ir->c, b, 4)) {
 		i2cdprintk("read error\n");
 		return -EIO;
 	}
@@ -447,6 +447,7 @@
 	case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
 	case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
 	case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA:
 	case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
 	case SAA7134_BOARD_AVERMEDIA_M102:
 	case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
@@ -506,7 +507,10 @@
 	case SAA7134_BOARD_BEHOLD_407FM:
 	case SAA7134_BOARD_BEHOLD_409:
 	case SAA7134_BOARD_BEHOLD_505FM:
+	case SAA7134_BOARD_BEHOLD_505RDS:
 	case SAA7134_BOARD_BEHOLD_507_9FM:
+	case SAA7134_BOARD_BEHOLD_507RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_507RDS_MK5:
 		ir_codes     = ir_codes_manli;
 		mask_keycode = 0x003f00;
 		mask_keyup   = 0x004000;
@@ -678,55 +682,101 @@
 	dev->remote = NULL;
 }
 
-void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
+void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 {
+	struct i2c_board_info info;
+	struct IR_i2c_init_data init_data;
+	const unsigned short addr_list[] = {
+		0x7a, 0x47, 0x71, 0x2d,
+		I2C_CLIENT_END
+	};
+
+	struct i2c_msg msg_msi = {
+		.addr = 0x50,
+		.flags = I2C_M_RD,
+		.len = 0,
+		.buf = NULL,
+	};
+
+	int rc;
+
 	if (disable_ir) {
-		dprintk("Found supported i2c remote, but IR has been disabled\n");
-		ir->get_key=NULL;
+		dprintk("IR has been disabled, not probing for i2c remote\n");
 		return;
 	}
 
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
+	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
 	switch (dev->board) {
 	case SAA7134_BOARD_PINNACLE_PCTV_110i:
 	case SAA7134_BOARD_PINNACLE_PCTV_310i:
-		snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
+		init_data.name = "Pinnacle PCTV";
 		if (pinnacle_remote == 0) {
-			ir->get_key   = get_key_pinnacle_color;
-			ir->ir_codes = ir_codes_pinnacle_color;
+			init_data.get_key = get_key_pinnacle_color;
+			init_data.ir_codes = ir_codes_pinnacle_color;
 		} else {
-			ir->get_key   = get_key_pinnacle_grey;
-			ir->ir_codes = ir_codes_pinnacle_grey;
+			init_data.get_key = get_key_pinnacle_grey;
+			init_data.ir_codes = ir_codes_pinnacle_grey;
 		}
 		break;
 	case SAA7134_BOARD_UPMOST_PURPLE_TV:
-		snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
-		ir->get_key   = get_key_purpletv;
-		ir->ir_codes  = ir_codes_purpletv;
+		init_data.name = "Purple TV";
+		init_data.get_key = get_key_purpletv;
+		init_data.ir_codes = ir_codes_purpletv;
 		break;
 	case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
-		snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus");
-		ir->get_key  = get_key_msi_tvanywhere_plus;
-		ir->ir_codes = ir_codes_msi_tvanywhere_plus;
+		init_data.name = "MSI TV@nywhere Plus";
+		init_data.get_key = get_key_msi_tvanywhere_plus;
+		init_data.ir_codes = ir_codes_msi_tvanywhere_plus;
+		info.addr = 0x30;
+		/* MSI TV@nywhere Plus controller doesn't seem to
+		   respond to probes unless we read something from
+		   an existing device. Weird...
+		   REVISIT: might no longer be needed */
+		rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
+		dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n",
+			msg_msi.addr, dev->i2c_adap.name,
+			(1 == rc) ? "yes" : "no");
 		break;
 	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-		snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110");
-		ir->get_key   = get_key_hvr1110;
-		ir->ir_codes  = ir_codes_hauppauge_new;
+		init_data.name = "HVR 1110";
+		init_data.get_key = get_key_hvr1110;
+		init_data.ir_codes = ir_codes_hauppauge_new;
 		break;
-	case SAA7134_BOARD_BEHOLD_607_9FM:
+	case SAA7134_BOARD_BEHOLD_607FM_MK3:
+	case SAA7134_BOARD_BEHOLD_607FM_MK5:
+	case SAA7134_BOARD_BEHOLD_609FM_MK3:
+	case SAA7134_BOARD_BEHOLD_609FM_MK5:
+	case SAA7134_BOARD_BEHOLD_607RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_607RDS_MK5:
+	case SAA7134_BOARD_BEHOLD_609RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_609RDS_MK5:
 	case SAA7134_BOARD_BEHOLD_M6:
 	case SAA7134_BOARD_BEHOLD_M63:
 	case SAA7134_BOARD_BEHOLD_M6_EXTRA:
 	case SAA7134_BOARD_BEHOLD_H6:
-		snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV");
-		ir->get_key   = get_key_beholdm6xx;
-		ir->ir_codes  = ir_codes_behold;
+		init_data.name = "BeholdTV";
+		init_data.get_key = get_key_beholdm6xx;
+		init_data.ir_codes = ir_codes_behold;
 		break;
-	default:
-		dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+		info.addr = 0x40;
 		break;
 	}
 
+	if (init_data.name)
+		info.platform_data = &init_data;
+	/* No need to probe if address is known */
+	if (info.addr) {
+		i2c_new_device(&dev->i2c_adap, &info);
+		return;
+	}
+
+	/* Address not known, fallback to probing */
+	i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
 }
 
 static int saa7134_rc5_irq(struct saa7134_dev *dev)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-ts.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-ts.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-ts.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-ts.c	2009-09-09 18:13:59.000000000 -0400
@@ -65,35 +65,10 @@
 	/* start DMA */
 	saa7134_set_dmabits(dev);
 
-	mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT);
-
-	if (dev->ts_state == SAA7134_TS_BUFF_DONE) {
-		/* Clear TS cache */
-		dev->buff_cnt = 0;
-		saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-		saa_writeb(SAA7134_TS_SERIAL1, 0x03);
-		saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-		saa_writeb(SAA7134_TS_SERIAL1, 0x01);
-
-		/* TS clock non-inverted */
-		saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-
-		/* Start TS stream */
-		switch (saa7134_boards[dev->board].ts_type) {
-		case SAA7134_MPEG_TS_PARALLEL:
-			saa_writeb(SAA7134_TS_SERIAL0, 0x40);
-			saa_writeb(SAA7134_TS_PARALLEL, 0xec);
-			break;
-		case SAA7134_MPEG_TS_SERIAL:
-			saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
-			saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
-			saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
-			saa_writeb(SAA7134_TS_SERIAL1, 0x02);
-			break;
-		}
+	mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT);
 
-		dev->ts_state = SAA7134_TS_STARTED;
-	}
+	if (!dev->ts_started)
+		saa7134_ts_start(dev);
 
 	return 0;
 }
@@ -104,7 +79,6 @@
 	struct saa7134_dev *dev = q->priv_data;
 	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
 	unsigned int lines, llength, size;
-	u32 control;
 	int err;
 
 	dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
@@ -121,8 +95,11 @@
 	}
 
 	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+
 		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 
+		dprintk("buffer_prepare: needs_init\n");
+
 		buf->vb.width  = llength;
 		buf->vb.height = lines;
 		buf->vb.size   = size;
@@ -139,23 +116,6 @@
 			goto oops;
 	}
 
-	dev->buff_cnt++;
-
-	if (dev->buff_cnt == dev->ts.nr_bufs) {
-		dev->ts_state = SAA7134_TS_BUFF_DONE;
-		/* dma: setup channel 5 (= TS) */
-		control = SAA7134_RS_CONTROL_BURST_16 |
-			SAA7134_RS_CONTROL_ME |
-			(buf->pt->dma >> 12);
-
-		saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff);
-		saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff);
-		/* TSNOPIT=0, TSCOLAP=0 */
-		saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00);
-		saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
-		saa_writel(SAA7134_RS_CONTROL(5), control);
-	}
-
 	buf->vb.state = VIDEOBUF_PREPARED;
 	buf->activate = buffer_activate;
 	buf->vb.field = field;
@@ -175,8 +135,7 @@
 	if (0 == *count)
 		*count = dev->ts.nr_bufs;
 	*count = saa7134_buffer_count(*size,*count);
-	dev->buff_cnt = 0;
-	dev->ts_state = SAA7134_TS_STOPPED;
+
 	return 0;
 }
 
@@ -193,11 +152,9 @@
 	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
 	struct saa7134_dev *dev = q->priv_data;
 
-	if (dev->ts_state == SAA7134_TS_STARTED) {
-		/* Stop TS transport */
-		saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
-		dev->ts_state = SAA7134_TS_STOPPED;
-	}
+	if (dev->ts_started)
+		saa7134_ts_stop(dev);
+
 	saa7134_dma_free(q,buf);
 }
 
@@ -214,7 +171,7 @@
 
 static unsigned int tsbufs = 8;
 module_param(tsbufs, int, 0444);
-MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32");
+MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32");
 
 static unsigned int ts_nr_packets = 64;
 module_param(ts_nr_packets, int, 0444);
@@ -256,6 +213,7 @@
 	dev->ts_q.timeout.data     = (unsigned long)(&dev->ts_q);
 	dev->ts_q.dev              = dev;
 	dev->ts_q.need_two         = 1;
+	dev->ts_started            = 0;
 	saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
 
 	/* init TS hw */
@@ -264,13 +222,67 @@
 	return 0;
 }
 
+/* Function for stop TS */
+int saa7134_ts_stop(struct saa7134_dev *dev)
+{
+	dprintk("TS stop\n");
+
+	BUG_ON(!dev->ts_started);
+
+	/* Stop TS stream */
+	switch (saa7134_boards[dev->board].ts_type) {
+	case SAA7134_MPEG_TS_PARALLEL:
+		saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+		dev->ts_started = 0;
+		break;
+	case SAA7134_MPEG_TS_SERIAL:
+		saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+		dev->ts_started = 0;
+		break;
+	}
+	return 0;
+}
+
+/* Function for start TS */
+int saa7134_ts_start(struct saa7134_dev *dev)
+{
+	dprintk("TS start\n");
+
+	BUG_ON(dev->ts_started);
+
+	saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+	saa_writeb(SAA7134_TS_SERIAL1, 0x03);
+	saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+	saa_writeb(SAA7134_TS_SERIAL1, 0x01);
+
+	/* TS clock non-inverted */
+	saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+
+	/* Start TS stream */
+	switch (saa7134_boards[dev->board].ts_type) {
+	case SAA7134_MPEG_TS_PARALLEL:
+		saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+		saa_writeb(SAA7134_TS_PARALLEL, 0xec);
+		break;
+	case SAA7134_MPEG_TS_SERIAL:
+		saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
+		saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+		saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
+		saa_writeb(SAA7134_TS_SERIAL1, 0x02);
+		break;
+	}
+
+	dev->ts_started = 1;
+
+	return 0;
+}
+
 int saa7134_ts_fini(struct saa7134_dev *dev)
 {
 	saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts);
 	return 0;
 }
 
-
 void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
 {
 	enum v4l2_field field;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-video.c linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/saa7134/saa7134-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/saa7134/saa7134-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -1057,6 +1057,7 @@
 		buf->vb.field  = field;
 		buf->fmt       = fh->fmt;
 		buf->pt        = &fh->pt_cap;
+		dev->video_q.curr = NULL;
 
 		err = videobuf_iolock(q,&buf->vb,&dev->ovbuf);
 		if (err)
@@ -1423,11 +1424,13 @@
 {
 	struct saa7134_fh *fh = file->private_data;
 	struct videobuf_buffer *buf = NULL;
+	unsigned int rc = 0;
 
 	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
 		return videobuf_poll_stream(file, &fh->vbi, wait);
 
 	if (res_check(fh,RESOURCE_VIDEO)) {
+		mutex_lock(&fh->cap.vb_lock);
 		if (!list_empty(&fh->cap.stream))
 			buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
 	} else {
@@ -1446,13 +1449,14 @@
 	}
 
 	if (!buf)
-		return POLLERR;
+		goto err;
 
 	poll_wait(file, &buf->done, wait);
 	if (buf->state == VIDEOBUF_DONE ||
 	    buf->state == VIDEOBUF_ERROR)
-		return POLLIN|POLLRDNORM;
-	return 0;
+		rc = POLLIN|POLLRDNORM;
+	mutex_unlock(&fh->cap.vb_lock);
+	return rc;
 
 err:
 	mutex_unlock(&fh->cap.vb_lock);
@@ -1636,15 +1640,8 @@
 	}
 
 	f->fmt.pix.field = field;
-	if (f->fmt.pix.width  < 48)
-		f->fmt.pix.width  = 48;
-	if (f->fmt.pix.height < 32)
-		f->fmt.pix.height = 32;
-	if (f->fmt.pix.width > maxw)
-		f->fmt.pix.width = maxw;
-	if (f->fmt.pix.height > maxh)
-		f->fmt.pix.height = maxh;
-	f->fmt.pix.width &= ~0x03;
+	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+			      &f->fmt.pix.height, 32, maxh, 0, 0);
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/se401.c linux-libre-2.6.31-gnu/drivers/media/video/se401.c
--- linux-libre-2.6.30-gnu/drivers/media/video/se401.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/se401.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/usb.h>
 #include "se401.h"
@@ -38,7 +39,7 @@
 static int flickerless;
 static int video_nr = -1;
 
-static struct usb_device_id device_table [] = {
+static struct usb_device_id device_table[] = {
 	{ USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
 	{ USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
 	{ USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
@@ -53,7 +54,8 @@
 MODULE_DESCRIPTION("SE401 USB Camera Driver");
 MODULE_LICENSE("GPL");
 module_param(flickerless, int, 0);
-MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
+MODULE_PARM_DESC(flickerless,
+		"Net frequency to adjust exposure time to (0/50/60)");
 module_param(video_nr, int, 0);
 
 static struct usb_driver se401_driver;
@@ -78,8 +80,8 @@
 	adr = (unsigned long) mem;
 	while (size > 0) {
 		SetPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
+		adr +=  PAGE_SIZE;
+		size -=  PAGE_SIZE;
 	}
 
 	return mem;
@@ -95,8 +97,8 @@
 	adr = (unsigned long) mem;
 	while ((long) size > 0) {
 		ClearPageReserved(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
+		adr +=  PAGE_SIZE;
+		size -=  PAGE_SIZE;
 	}
 	vfree(mem);
 }
@@ -112,7 +114,7 @@
 static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
 			 unsigned short value, unsigned char *cp, int size)
 {
-	return usb_control_msg (
+	return usb_control_msg(
 		se401->dev,
 		set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
 		req,
@@ -132,7 +134,7 @@
 	   and the param in index, but in the logs of the windows driver they do
 	   this the other way around...
 	 */
-	return usb_control_msg (
+	return usb_control_msg(
 		se401->dev,
 		usb_sndctrlpipe(se401->dev, 0),
 		SE401_REQ_SET_EXT_FEATURE,
@@ -152,7 +154,7 @@
 	   wrong here to....
 	 */
 	unsigned char cp[2];
-	usb_control_msg (
+	usb_control_msg(
 		se401->dev,
 		usb_rcvctrlpipe(se401->dev, 0),
 		SE401_REQ_GET_EXT_FEATURE,
@@ -175,46 +177,51 @@
 
 static int se401_send_pict(struct usb_se401 *se401)
 {
-	se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */
-	se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */
-	se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */
-	se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */
-	se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */
-	se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */
-	se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */
+	/* integration time low */
+	se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);
+	/* integration time mid */
+	se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);
+	/* integration time mid */
+	se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);
+	/* reset level value */
+	se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
+	/* red color gain */
+	se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);
+	/* green color gain */
+	se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);
+	/* blue color gain */
+	se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);
 
 	return 0;
 }
 
 static void se401_set_exposure(struct usb_se401 *se401, int brightness)
 {
-	int integration=brightness<<5;
+	int integration = brightness << 5;
 
-	if (flickerless==50) {
-		integration=integration-integration%106667;
-	}
-	if (flickerless==60) {
-		integration=integration-integration%88889;
-	}
-	se401->brightness=integration>>5;
-	se401->expose_h=(integration>>16)&0xff;
-	se401->expose_m=(integration>>8)&0xff;
-	se401->expose_l=integration&0xff;
+	if (flickerless == 50)
+		integration = integration-integration % 106667;
+	if (flickerless == 60)
+		integration = integration-integration % 88889;
+	se401->brightness = integration >> 5;
+	se401->expose_h = (integration >> 16) & 0xff;
+	se401->expose_m = (integration >> 8) & 0xff;
+	se401->expose_l = integration & 0xff;
 }
 
 static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
 {
-	p->brightness=se401->brightness;
-	if (se401->enhance) {
-		p->whiteness=32768;
-	} else {
-		p->whiteness=0;
-	}
-	p->colour=65535;
-	p->contrast=65535;
-	p->hue=se401->rgain<<10;
-	p->palette=se401->palette;
-	p->depth=3; /* rgb24 */
+	p->brightness = se401->brightness;
+	if (se401->enhance)
+		p->whiteness = 32768;
+	else
+		p->whiteness = 0;
+
+	p->colour = 65535;
+	p->contrast = 65535;
+	p->hue = se401->rgain << 10;
+	p->palette = se401->palette;
+	p->depth = 3; /* rgb24 */
 	return 0;
 }
 
@@ -223,20 +230,19 @@
 {
 	if (p->palette != VIDEO_PALETTE_RGB24)
 		return 1;
-	se401->palette=p->palette;
-	if (p->hue!=se401->hue) {
-		se401->rgain= p->hue>>10;
-		se401->bgain= 0x40-(p->hue>>10);
-		se401->hue=p->hue;
+	se401->palette = p->palette;
+	if (p->hue != se401->hue) {
+		se401->rgain =  p->hue >> 10;
+		se401->bgain =  0x40-(p->hue >> 10);
+		se401->hue = p->hue;
 	}
-	if (p->brightness!=se401->brightness) {
+	if (p->brightness != se401->brightness)
 		se401_set_exposure(se401, p->brightness);
-	}
-	if (p->whiteness>=32768) {
-		se401->enhance=1;
-	} else {
-		se401->enhance=0;
-	}
+
+	if (p->whiteness >= 32768)
+		se401->enhance = 1;
+	else
+		se401->enhance = 0;
 	se401_send_pict(se401);
 	se401_send_pict(se401);
 	return 0;
@@ -249,7 +255,7 @@
 static void se401_auto_resetlevel(struct usb_se401 *se401)
 {
 	unsigned int ahrc, alrc;
-	int oldreset=se401->resetlevel;
+	int oldreset = se401->resetlevel;
 
 	/* For some reason this normally read-only register doesn't get reset
 	   to zero after reading them just once...
@@ -258,24 +264,24 @@
 	se401_get_feature(se401, HV7131_REG_HIREFNOL);
 	se401_get_feature(se401, HV7131_REG_LOREFNOH);
 	se401_get_feature(se401, HV7131_REG_LOREFNOL);
-	ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
+	ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
 	    se401_get_feature(se401, HV7131_REG_HIREFNOL);
-	alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
+	alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
 	    se401_get_feature(se401, HV7131_REG_LOREFNOL);
 
 	/* Not an exact science, but it seems to work pretty well... */
 	if (alrc > 10) {
-		while (alrc>=10 && se401->resetlevel < 63) {
+		while (alrc >= 10 && se401->resetlevel < 63) {
 			se401->resetlevel++;
-			alrc /=2;
+			alrc /= 2;
 		}
 	} else if (ahrc > 20) {
-		while (ahrc>=20 && se401->resetlevel > 0) {
+		while (ahrc >= 20 && se401->resetlevel > 0) {
 			se401->resetlevel--;
-			ahrc /=2;
+			ahrc /= 2;
 		}
 	}
-	if (se401->resetlevel!=oldreset)
+	if (se401->resetlevel != oldreset)
 		se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
 
 	return;
@@ -300,21 +306,22 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+		dbg("%s - urb shutting down with status: %d",
+							__func__, urb->status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+		dbg("%s - nonzero urb status received: %d",
+							__func__, urb->status);
 		goto exit;
 	}
 
-	if (urb->actual_length >=2) {
+	if (urb->actual_length  >= 2)
 		if (se401->button)
-			se401->buttonpressed=1;
-	}
+			se401->buttonpressed = 1;
 exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
+	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status)
-		err ("%s - usb_submit_urb failed with result %d",
+		err("%s - usb_submit_urb failed with result %d",
 		     __func__, status);
 }
 
@@ -336,55 +343,52 @@
 	   keeps sending them forever...
 	 */
 	if (length && !urb->status) {
-		se401->nullpackets=0;
-		switch(se401->scratch[se401->scratch_next].state) {
-			case BUFFER_READY:
-			case BUFFER_BUSY: {
-				se401->dropped++;
-				break;
-			}
-			case BUFFER_UNUSED: {
-				memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length);
-				se401->scratch[se401->scratch_next].state=BUFFER_READY;
-				se401->scratch[se401->scratch_next].offset=se401->bayeroffset;
-				se401->scratch[se401->scratch_next].length=length;
-				if (waitqueue_active(&se401->wq)) {
-					wake_up_interruptible(&se401->wq);
-				}
-				se401->scratch_overflow=0;
-				se401->scratch_next++;
-				if (se401->scratch_next>=SE401_NUMSCRATCH)
-					se401->scratch_next=0;
-				break;
-			}
-		}
-		se401->bayeroffset+=length;
-		if (se401->bayeroffset>=se401->cheight*se401->cwidth) {
-			se401->bayeroffset=0;
+		se401->nullpackets = 0;
+		switch (se401->scratch[se401->scratch_next].state) {
+		case BUFFER_READY:
+		case BUFFER_BUSY:
+			se401->dropped++;
+			break;
+		case BUFFER_UNUSED:
+			memcpy(se401->scratch[se401->scratch_next].data,
+				(unsigned char *)urb->transfer_buffer, length);
+			se401->scratch[se401->scratch_next].state
+							= BUFFER_READY;
+			se401->scratch[se401->scratch_next].offset
+							= se401->bayeroffset;
+			se401->scratch[se401->scratch_next].length = length;
+			if (waitqueue_active(&se401->wq))
+				wake_up_interruptible(&se401->wq);
+			se401->scratch_overflow = 0;
+			se401->scratch_next++;
+			if (se401->scratch_next >= SE401_NUMSCRATCH)
+				se401->scratch_next = 0;
+			break;
 		}
+		se401->bayeroffset += length;
+		if (se401->bayeroffset >= se401->cheight * se401->cwidth)
+			se401->bayeroffset = 0;
 	} else {
 		se401->nullpackets++;
-		if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
-			if (waitqueue_active(&se401->wq)) {
+		if (se401->nullpackets > SE401_MAX_NULLPACKETS)
+			if (waitqueue_active(&se401->wq))
 				wake_up_interruptible(&se401->wq);
-			}
-		}
 	}
 
 	/* Resubmit urb for new data */
-	urb->status=0;
-	urb->dev=se401->dev;
-	if(usb_submit_urb(urb, GFP_KERNEL))
+	urb->status = 0;
+	urb->dev = se401->dev;
+	if (usb_submit_urb(urb, GFP_KERNEL))
 		dev_info(&urb->dev->dev, "urb burned down\n");
 	return;
 }
 
 static void se401_send_size(struct usb_se401 *se401, int width, int height)
 {
-	int i=0;
-	int mode=0x03; /* No compression */
-	int sendheight=height;
-	int sendwidth=width;
+	int i = 0;
+	int mode = 0x03; /* No compression */
+	int sendheight = height;
+	int sendwidth = width;
 
 	/* JangGu compression can only be used with the camera supported sizes,
 	   but bayer seems to work with any size that fits on the sensor.
@@ -392,18 +396,21 @@
 	   4 or 16 times subcapturing, if not we use uncompressed bayer data
 	   but this will result in cutouts of the maximum size....
 	 */
-	while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height))
+	while (i < se401->sizes && !(se401->width[i] == width &&
+						se401->height[i] == height))
 		i++;
-	while (i<se401->sizes) {
-		if (se401->width[i]==width*2 && se401->height[i]==height*2) {
-			sendheight=se401->height[i];
-			sendwidth=se401->width[i];
-			mode=0x40;
+	while (i < se401->sizes) {
+		if (se401->width[i] == width * 2 &&
+				se401->height[i] == height * 2) {
+			sendheight = se401->height[i];
+			sendwidth = se401->width[i];
+			mode = 0x40;
 		}
-		if (se401->width[i]==width*4 && se401->height[i]==height*4) {
-			sendheight=se401->height[i];
-			sendwidth=se401->width[i];
-			mode=0x42;
+		if (se401->width[i] == width * 4 &&
+				se401->height[i] == height * 4) {
+			sendheight = se401->height[i];
+			sendwidth = se401->width[i];
+			mode = 0x42;
 		}
 		i++;
 	}
@@ -412,13 +419,10 @@
 	se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
 	se401_set_feature(se401, SE401_OPERATINGMODE, mode);
 
-	if (mode==0x03) {
-		se401->format=FMT_BAYER;
-	} else {
-		se401->format=FMT_JANGGU;
-	}
-
-	return;
+	if (mode == 0x03)
+		se401->format = FMT_BAYER;
+	else
+		se401->format = FMT_JANGGU;
 }
 
 /*
@@ -429,29 +433,31 @@
 static int se401_start_stream(struct usb_se401 *se401)
 {
 	struct urb *urb;
-	int err=0, i;
-	se401->streaming=1;
+	int err = 0, i;
+	se401->streaming = 1;
 
 	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
 	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
 
 	/* Set picture settings */
-	se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
+	/* windowed + pix intg */
+	se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);
 	se401_send_pict(se401);
 
 	se401_send_size(se401, se401->cwidth, se401->cheight);
 
-	se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0);
+	se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE,
+								0, NULL, 0);
 
 	/* Do some memory allocation */
-	for (i=0; i<SE401_NUMFRAMES; i++) {
-		se401->frame[i].data=se401->fbuf + i * se401->maxframesize;
-		se401->frame[i].curpix=0;
+	for (i = 0; i < SE401_NUMFRAMES; i++) {
+		se401->frame[i].data = se401->fbuf + i * se401->maxframesize;
+		se401->frame[i].curpix = 0;
 	}
-	for (i=0; i<SE401_NUMSBUF; i++) {
-		se401->sbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
+	for (i = 0; i < SE401_NUMSBUF; i++) {
+		se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
 		if (!se401->sbuf[i].data) {
-			for(i = i - 1; i >= 0; i--) {
+			for (i = i - 1; i >= 0; i--) {
 				kfree(se401->sbuf[i].data);
 				se401->sbuf[i].data = NULL;
 			}
@@ -459,26 +465,26 @@
 		}
 	}
 
-	se401->bayeroffset=0;
-	se401->scratch_next=0;
-	se401->scratch_use=0;
-	se401->scratch_overflow=0;
-	for (i=0; i<SE401_NUMSCRATCH; i++) {
-		se401->scratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
+	se401->bayeroffset = 0;
+	se401->scratch_next = 0;
+	se401->scratch_use = 0;
+	se401->scratch_overflow = 0;
+	for (i = 0; i < SE401_NUMSCRATCH; i++) {
+		se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
 		if (!se401->scratch[i].data) {
-			for(i = i - 1; i >= 0; i--) {
+			for (i = i - 1; i >= 0; i--) {
 				kfree(se401->scratch[i].data);
 				se401->scratch[i].data = NULL;
 			}
 			goto nomem_sbuf;
 		}
-		se401->scratch[i].state=BUFFER_UNUSED;
+		se401->scratch[i].state = BUFFER_UNUSED;
 	}
 
-	for (i=0; i<SE401_NUMSBUF; i++) {
-		urb=usb_alloc_urb(0, GFP_KERNEL);
-		if(!urb) {
-			for(i = i - 1; i >= 0; i--) {
+	for (i = 0; i < SE401_NUMSBUF; i++) {
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			for (i = i - 1; i >= 0; i--) {
 				usb_kill_urb(se401->urb[i]);
 				usb_free_urb(se401->urb[i]);
 				se401->urb[i] = NULL;
@@ -492,24 +498,24 @@
 			se401_video_irq,
 			se401);
 
-		se401->urb[i]=urb;
+		se401->urb[i] = urb;
 
-		err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
-		if(err)
+		err = usb_submit_urb(se401->urb[i], GFP_KERNEL);
+		if (err)
 			err("urb burned down");
 	}
 
-	se401->framecount=0;
+	se401->framecount = 0;
 
 	return 0;
 
  nomem_scratch:
-	for (i=0; i<SE401_NUMSCRATCH; i++) {
+	for (i = 0; i < SE401_NUMSCRATCH; i++) {
 		kfree(se401->scratch[i].data);
 		se401->scratch[i].data = NULL;
 	}
  nomem_sbuf:
-	for (i=0; i<SE401_NUMSBUF; i++) {
+	for (i = 0; i < SE401_NUMSBUF; i++) {
 		kfree(se401->sbuf[i].data);
 		se401->sbuf[i].data = NULL;
 	}
@@ -523,22 +529,23 @@
 	if (!se401->streaming || !se401->dev)
 		return 1;
 
-	se401->streaming=0;
+	se401->streaming = 0;
 
 	se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
 
 	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
 	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
 
-	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
-		usb_kill_urb(se401->urb[i]);
-		usb_free_urb(se401->urb[i]);
-		se401->urb[i]=NULL;
-		kfree(se401->sbuf[i].data);
-	}
-	for (i=0; i<SE401_NUMSCRATCH; i++) {
+	for (i = 0; i < SE401_NUMSBUF; i++)
+		if (se401->urb[i]) {
+			usb_kill_urb(se401->urb[i]);
+			usb_free_urb(se401->urb[i]);
+			se401->urb[i] = NULL;
+			kfree(se401->sbuf[i].data);
+		}
+	for (i = 0; i < SE401_NUMSCRATCH; i++) {
 		kfree(se401->scratch[i].data);
-		se401->scratch[i].data=NULL;
+		se401->scratch[i].data = NULL;
 	}
 
 	return 0;
@@ -546,9 +553,9 @@
 
 static int se401_set_size(struct usb_se401 *se401, int width, int height)
 {
-	int wasstreaming=se401->streaming;
+	int wasstreaming = se401->streaming;
 	/* Check to see if we need to change */
-	if (se401->cwidth==width && se401->cheight==height)
+	if (se401->cwidth == width && se401->cheight == height)
 		return 0;
 
 	/* Check for a valid mode */
@@ -556,16 +563,16 @@
 		return 1;
 	if ((width & 1) || (height & 1))
 		return 1;
-	if (width>se401->width[se401->sizes-1])
+	if (width > se401->width[se401->sizes-1])
 		return 1;
-	if (height>se401->height[se401->sizes-1])
+	if (height > se401->height[se401->sizes-1])
 		return 1;
 
 	/* Stop a current stream and start it again at the new size */
 	if (wasstreaming)
 		se401_stop_stream(se401);
-	se401->cwidth=width;
-	se401->cheight=height;
+	se401->cwidth = width;
+	se401->cheight = height;
 	if (wasstreaming)
 		se401_start_stream(se401);
 	return 0;
@@ -586,68 +593,68 @@
 static inline void enhance_picture(unsigned char *frame, int len)
 {
 	while (len--) {
-		*frame=(((*frame^255)*(*frame^255))/255)^255;
+		*frame = (((*frame^255)*(*frame^255))/255)^255;
 		frame++;
 	}
 }
 
 static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
 {
-	struct se401_frame *frame=&se401->frame[se401->curframe];
-	int linelength=se401->cwidth*3;
+	struct se401_frame *frame = &se401->frame[se401->curframe];
+	int linelength = se401->cwidth * 3;
 
 	if (frame->curlinepix >= linelength) {
-		frame->curlinepix=0;
-		frame->curline+=linelength;
+		frame->curlinepix = 0;
+		frame->curline += linelength;
 	}
 
 	/* First three are absolute, all others relative.
 	 * Format is rgb from right to left (mirrorred image),
 	 * we flip it to get bgr from left to right. */
-	if (frame->curlinepix < 3) {
-		*(frame->curline-frame->curlinepix)=1+data*4;
-	} else {
-		*(frame->curline-frame->curlinepix)=
-		    *(frame->curline-frame->curlinepix+3)+data*4;
-	}
+	if (frame->curlinepix < 3)
+		*(frame->curline-frame->curlinepix) = 1 + data * 4;
+	else
+		*(frame->curline-frame->curlinepix) =
+		    *(frame->curline-frame->curlinepix + 3) + data * 4;
 	frame->curlinepix++;
 }
 
-static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
+static inline void decode_JangGu_vlc(struct usb_se401 *se401,
+			unsigned char *data, int bit_exp, int packetlength)
 {
-	int pos=0;
-	int vlc_cod=0;
-	int vlc_size=0;
-	int vlc_data=0;
+	int pos = 0;
+	int vlc_cod = 0;
+	int vlc_size = 0;
+	int vlc_data = 0;
 	int bit_cur;
 	int bit;
-	data+=4;
+	data += 4;
 	while (pos < packetlength) {
-		bit_cur=8;
+		bit_cur = 8;
 		while (bit_cur && bit_exp) {
-			bit=((*data)>>(bit_cur-1))&1;
+			bit = ((*data) >> (bit_cur-1))&1;
 			if (!vlc_cod) {
 				if (bit) {
 					vlc_size++;
 				} else {
-					if (!vlc_size) {
+					if (!vlc_size)
 						decode_JangGu_integrate(se401, 0);
-					} else {
-						vlc_cod=2;
-						vlc_data=0;
+					else {
+						vlc_cod = 2;
+						vlc_data = 0;
 					}
 				}
 			} else {
-				if (vlc_cod==2) {
+				if (vlc_cod == 2) {
 					if (!bit)
-						vlc_data =  -(1<<vlc_size) + 1;
+						vlc_data =  -(1 << vlc_size) + 1;
 					vlc_cod--;
 				}
 				vlc_size--;
-				vlc_data+=bit<<vlc_size;
+				vlc_data += bit << vlc_size;
 				if (!vlc_size) {
 					decode_JangGu_integrate(se401, vlc_data);
-					vlc_cod=0;
+					vlc_cod = 0;
 				}
 			}
 			bit_cur--;
@@ -658,186 +665,188 @@
 	}
 }
 
-static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
+static inline void decode_JangGu(struct usb_se401 *se401,
+						struct se401_scratch *buffer)
 {
-	unsigned char *data=buffer->data;
-	int len=buffer->length;
-	int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
-	int datapos=0;
+	unsigned char *data = buffer->data;
+	int len = buffer->length;
+	int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size;
+	int datapos = 0;
 
 	/* New image? */
 	if (!se401->frame[se401->curframe].curpix) {
-		se401->frame[se401->curframe].curlinepix=0;
-		se401->frame[se401->curframe].curline=
+		se401->frame[se401->curframe].curlinepix = 0;
+		se401->frame[se401->curframe].curline =
 		    se401->frame[se401->curframe].data+
-		    se401->cwidth*3-1;
-		if (se401->frame[se401->curframe].grabstate==FRAME_READY)
-			se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
-		se401->vlcdatapos=0;
+		    se401->cwidth * 3 - 1;
+		if (se401->frame[se401->curframe].grabstate == FRAME_READY)
+			se401->frame[se401->curframe].grabstate = FRAME_GRABBING;
+		se401->vlcdatapos = 0;
 	}
 	while (datapos < len) {
-		size=1024-se401->vlcdatapos;
+		size = 1024 - se401->vlcdatapos;
 		if (size+datapos > len)
-			size=len-datapos;
+			size = len-datapos;
 		memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
-		se401->vlcdatapos+=size;
-		packetlength=0;
+		se401->vlcdatapos += size;
+		packetlength = 0;
 		if (se401->vlcdatapos >= 4) {
-			bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8);
-			pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8);
-			frameinfo=se401->vlcdata[0]&0xc0;
-			packetlength=((bit_exp+47)>>4)<<1;
+			bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8);
+			pix_exp = se401->vlcdata[1] +
+					((se401->vlcdata[0] & 0x3f) << 8);
+			frameinfo = se401->vlcdata[0] & 0xc0;
+			packetlength = ((bit_exp + 47) >> 4) << 1;
 			if (packetlength > 1024) {
-				se401->vlcdatapos=0;
-				datapos=len;
-				packetlength=0;
+				se401->vlcdatapos = 0;
+				datapos = len;
+				packetlength = 0;
 				se401->error++;
-				se401->frame[se401->curframe].curpix=0;
+				se401->frame[se401->curframe].curpix = 0;
 			}
 		}
 		if (packetlength && se401->vlcdatapos >= packetlength) {
-			decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength);
-			se401->frame[se401->curframe].curpix+=pix_exp*3;
-			datapos+=size-(se401->vlcdatapos-packetlength);
-			se401->vlcdatapos=0;
-			if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) {
-				if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) {
-					if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) {
-						se401->frame[se401->curframe].grabstate=FRAME_DONE;
+			decode_JangGu_vlc(se401, se401->vlcdata, bit_exp,
+								packetlength);
+			se401->frame[se401->curframe].curpix += pix_exp * 3;
+			datapos += size-(se401->vlcdatapos-packetlength);
+			se401->vlcdatapos = 0;
+			if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) {
+				if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) {
+					if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) {
+						se401->frame[se401->curframe].grabstate = FRAME_DONE;
 						se401->framecount++;
 						se401->readcount++;
 					}
-					if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
-						se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
-					}
-				} else {
+					if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY)
+						se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1);
+				} else
 					se401->error++;
-				}
-				se401->frame[se401->curframe].curpix=0;
-				datapos=len;
+				se401->frame[se401->curframe].curpix = 0;
+				datapos = len;
 			}
-		} else {
-			datapos+=size;
-		}
+		} else
+			datapos += size;
 	}
 }
 
-static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
+static inline void decode_bayer(struct usb_se401 *se401,
+						struct se401_scratch *buffer)
 {
-	unsigned char *data=buffer->data;
-	int len=buffer->length;
-	int offset=buffer->offset;
-	int datasize=se401->cwidth*se401->cheight;
-	struct se401_frame *frame=&se401->frame[se401->curframe];
+	unsigned char *data = buffer->data;
+	int len = buffer->length;
+	int offset = buffer->offset;
+	int datasize = se401->cwidth * se401->cheight;
+	struct se401_frame *frame = &se401->frame[se401->curframe];
+	unsigned char *framedata = frame->data, *curline, *nextline;
+	int width = se401->cwidth;
+	int blineoffset = 0, bline;
+	int linelength = width * 3, i;
 
-	unsigned char *framedata=frame->data, *curline, *nextline;
-	int width=se401->cwidth;
-	int blineoffset=0, bline;
-	int linelength=width*3, i;
 
+	if (frame->curpix == 0) {
+		if (frame->grabstate == FRAME_READY)
+			frame->grabstate = FRAME_GRABBING;
 
-	if (frame->curpix==0) {
-		if (frame->grabstate==FRAME_READY) {
-			frame->grabstate=FRAME_GRABBING;
-		}
-		frame->curline=framedata+linelength;
-		frame->curlinepix=0;
+		frame->curline = framedata + linelength;
+		frame->curlinepix = 0;
 	}
 
-	if (offset!=frame->curpix) {
+	if (offset != frame->curpix) {
 		/* Regard frame as lost :( */
-		frame->curpix=0;
+		frame->curpix = 0;
 		se401->error++;
 		return;
 	}
 
 	/* Check if we have to much data */
-	if (frame->curpix+len > datasize) {
-		len=datasize-frame->curpix;
-	}
-	if (se401->cheight%4)
-		blineoffset=1;
-	bline=frame->curpix/se401->cwidth+blineoffset;
+	if (frame->curpix + len > datasize)
+		len = datasize-frame->curpix;
 
-	curline=frame->curline;
-	nextline=curline+linelength;
-	if (nextline >= framedata+datasize*3)
-		nextline=curline;
+	if (se401->cheight % 4)
+		blineoffset = 1;
+	bline = frame->curpix / se401->cwidth+blineoffset;
+
+	curline = frame->curline;
+	nextline = curline + linelength;
+	if (nextline >= framedata+datasize * 3)
+		nextline = curline;
 	while (len) {
-		if (frame->curlinepix>=width) {
-			frame->curlinepix-=width;
-			bline=frame->curpix/width+blineoffset;
-			curline+=linelength*2;
-			nextline+=linelength*2;
-			if (curline >= framedata+datasize*3) {
+		if (frame->curlinepix >= width) {
+			frame->curlinepix -= width;
+			bline = frame->curpix / width + blineoffset;
+			curline += linelength*2;
+			nextline += linelength*2;
+			if (curline >= framedata+datasize * 3) {
 				frame->curlinepix++;
-				curline-=3;
-				nextline-=3;
+				curline -= 3;
+				nextline -= 3;
 				len--;
 				data++;
 				frame->curpix++;
 			}
 			if (nextline >= framedata+datasize*3)
-				nextline=curline;
+				nextline = curline;
 		}
-		if ((bline&1)) {
-			if ((frame->curlinepix&1)) {
-				*(curline+2)=*data;
-				*(curline-1)=*data;
-				*(nextline+2)=*data;
-				*(nextline-1)=*data;
+		if (bline & 1) {
+			if (frame->curlinepix & 1) {
+				*(curline + 2) = *data;
+				*(curline - 1) = *data;
+				*(nextline + 2) = *data;
+				*(nextline - 1) = *data;
 			} else {
-				*(curline+1)=
-					(*(curline+1)+*data)/2;
-				*(curline-2)=
-					(*(curline-2)+*data)/2;
-				*(nextline+1)=*data;
-				*(nextline-2)=*data;
+				*(curline + 1) =
+					(*(curline + 1) + *data) / 2;
+				*(curline-2) =
+					(*(curline - 2) + *data) / 2;
+				*(nextline + 1) = *data;
+				*(nextline - 2) = *data;
 			}
 		} else {
-			if ((frame->curlinepix&1)) {
-				*(curline+1)=
-					(*(curline+1)+*data)/2;
-				*(curline-2)=
-					(*(curline-2)+*data)/2;
-				*(nextline+1)=*data;
-				*(nextline-2)=*data;
+			if (frame->curlinepix & 1) {
+				*(curline + 1) =
+					(*(curline + 1) + *data) / 2;
+				*(curline - 2) =
+					(*(curline - 2) + *data) / 2;
+				*(nextline + 1) = *data;
+				*(nextline - 2) = *data;
 			} else {
-				*curline=*data;
-				*(curline-3)=*data;
-				*nextline=*data;
-				*(nextline-3)=*data;
+				*curline = *data;
+				*(curline - 3) = *data;
+				*nextline = *data;
+				*(nextline - 3) = *data;
 			}
 		}
 		frame->curlinepix++;
-		curline-=3;
-		nextline-=3;
+		curline -= 3;
+		nextline -= 3;
 		len--;
 		data++;
 		frame->curpix++;
 	}
-	frame->curline=curline;
+	frame->curline = curline;
 
-	if (frame->curpix>=datasize) {
+	if (frame->curpix >= datasize) {
 		/* Fix the top line */
-		framedata+=linelength;
-		for (i=0; i<linelength; i++) {
+		framedata += linelength;
+		for (i = 0; i < linelength; i++) {
 			framedata--;
-			*framedata=*(framedata+linelength);
+			*framedata = *(framedata + linelength);
 		}
 		/* Fix the left side (green is already present) */
-		for (i=0; i<se401->cheight; i++) {
-			*framedata=*(framedata+3);
-			*(framedata+1)=*(framedata+4);
-			*(framedata+2)=*(framedata+5);
-			framedata+=linelength;
+		for (i = 0; i < se401->cheight; i++) {
+			*framedata = *(framedata + 3);
+			*(framedata + 1) = *(framedata + 4);
+			*(framedata + 2) = *(framedata + 5);
+			framedata += linelength;
 		}
-		frame->curpix=0;
-		frame->grabstate=FRAME_DONE;
+		frame->curpix = 0;
+		frame->grabstate = FRAME_DONE;
 		se401->framecount++;
 		se401->readcount++;
-		if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
-			se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
+		if (se401->frame[(se401->curframe + 1) &
+		    (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) {
+			se401->curframe = (se401->curframe+1) &
+							(SE401_NUMFRAMES-1);
 		}
 	}
 }
@@ -845,72 +854,76 @@
 static int se401_newframe(struct usb_se401 *se401, int framenr)
 {
 	DECLARE_WAITQUEUE(wait, current);
-	int errors=0;
+	int errors = 0;
 
 	while (se401->streaming &&
-	    (se401->frame[framenr].grabstate==FRAME_READY ||
-	     se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
-		if(!se401->frame[framenr].curpix) {
+	    (se401->frame[framenr].grabstate == FRAME_READY ||
+	     se401->frame[framenr].grabstate == FRAME_GRABBING)) {
+		if (!se401->frame[framenr].curpix)
 			errors++;
-		}
+
 		wait_interruptible(
-		    se401->scratch[se401->scratch_use].state!=BUFFER_READY,
-		    &se401->wq,
-		    &wait
-		);
+		    se401->scratch[se401->scratch_use].state != BUFFER_READY,
+						    &se401->wq, &wait);
 		if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
-			se401->nullpackets=0;
+			se401->nullpackets = 0;
 			dev_info(&se401->dev->dev,
-				 "too many null length packets, restarting capture\n");
+			 "too many null length packets, restarting capture\n");
 			se401_stop_stream(se401);
 			se401_start_stream(se401);
 		} else {
-			if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
-				se401->frame[framenr].grabstate=FRAME_ERROR;
+			if (se401->scratch[se401->scratch_use].state !=
+								BUFFER_READY) {
+				se401->frame[framenr].grabstate = FRAME_ERROR;
 				return -EIO;
 			}
-			se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
-			if (se401->format==FMT_JANGGU) {
-				decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
-			} else {
-				decode_bayer(se401, &se401->scratch[se401->scratch_use]);
-			}
-			se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
+			se401->scratch[se401->scratch_use].state = BUFFER_BUSY;
+			if (se401->format == FMT_JANGGU)
+				decode_JangGu(se401,
+					&se401->scratch[se401->scratch_use]);
+			else
+				decode_bayer(se401,
+					&se401->scratch[se401->scratch_use]);
+
+			se401->scratch[se401->scratch_use].state =
+							BUFFER_UNUSED;
 			se401->scratch_use++;
-			if (se401->scratch_use>=SE401_NUMSCRATCH)
-				se401->scratch_use=0;
+			if (se401->scratch_use >= SE401_NUMSCRATCH)
+				se401->scratch_use = 0;
 			if (errors > SE401_MAX_ERRORS) {
-				errors=0;
+				errors = 0;
 				dev_info(&se401->dev->dev,
-					 "too many errors, restarting capture\n");
+				      "too many errors, restarting capture\n");
 				se401_stop_stream(se401);
 				se401_start_stream(se401);
 			}
 		}
 	}
 
-	if (se401->frame[framenr].grabstate==FRAME_DONE)
+	if (se401->frame[framenr].grabstate == FRAME_DONE)
 		if (se401->enhance)
-			enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
+			enhance_picture(se401->frame[framenr].data,
+					se401->cheight * se401->cwidth * 3);
 	return 0;
 }
 
-static void usb_se401_remove_disconnected (struct usb_se401 *se401)
+static void usb_se401_remove_disconnected(struct usb_se401 *se401)
 {
 	int i;
 
 	se401->dev = NULL;
 
-	for (i=0; i<SE401_NUMSBUF; i++)
+	for (i = 0; i < SE401_NUMSBUF; i++)
 		if (se401->urb[i]) {
 			usb_kill_urb(se401->urb[i]);
 			usb_free_urb(se401->urb[i]);
 			se401->urb[i] = NULL;
 			kfree(se401->sbuf[i].data);
 		}
-	for (i=0; i<SE401_NUMSCRATCH; i++) {
+
+	for (i = 0; i < SE401_NUMSCRATCH; i++)
 		kfree(se401->scratch[i].data);
-	}
+
 	if (se401->inturb) {
 		usb_kill_urb(se401->inturb);
 		usb_free_urb(se401->inturb);
@@ -965,11 +978,11 @@
 		dev_info(&se401->dev->dev, "device unregistered\n");
 		usb_se401_remove_disconnected(se401);
 	} else {
-		for (i=0; i<SE401_NUMFRAMES; i++)
-			se401->frame[i].grabstate=FRAME_UNUSED;
+		for (i = 0; i < SE401_NUMFRAMES; i++)
+			se401->frame[i].grabstate = FRAME_UNUSED;
 		if (se401->streaming)
 			se401_stop_stream(se401);
-		se401->user=0;
+		se401->user = 0;
 	}
 	file->private_data = NULL;
 	return 0;
@@ -1065,7 +1078,7 @@
 		memset(vm, 0, sizeof(*vm));
 		vm->size = SE401_NUMFRAMES * se401->maxframesize;
 		vm->frames = SE401_NUMFRAMES;
-		for (i=0; i<SE401_NUMFRAMES; i++)
+		for (i = 0; i < SE401_NUMFRAMES; i++)
 			vm->offsets[i] = se401->maxframesize * i;
 		return 0;
 	}
@@ -1083,16 +1096,16 @@
 		/* Is this according to the v4l spec??? */
 		if (se401_set_size(se401, vm->width, vm->height))
 			return -EINVAL;
-		se401->frame[vm->frame].grabstate=FRAME_READY;
+		se401->frame[vm->frame].grabstate = FRAME_READY;
 
 		if (!se401->streaming)
 			se401_start_stream(se401);
 
 		/* Set the picture properties */
-		if (se401->framecount==0)
+		if (se401->framecount == 0)
 			se401_send_pict(se401);
 		/* Calibrate the reset level after a few frames. */
-		if (se401->framecount%20==1)
+		if (se401->framecount % 20 == 1)
 			se401_auto_resetlevel(se401);
 
 		return 0;
@@ -1100,13 +1113,13 @@
 	case VIDIOCSYNC:
 	{
 		int *frame = arg;
-		int ret=0;
+		int ret = 0;
 
-		if(*frame <0 || *frame >= SE401_NUMFRAMES)
+		if (*frame < 0 || *frame >= SE401_NUMFRAMES)
 			return -EINVAL;
 
-		ret=se401_newframe(se401, *frame);
-		se401->frame[*frame].grabstate=FRAME_UNUSED;
+		ret = se401_newframe(se401, *frame);
+		se401->frame[*frame].grabstate = FRAME_UNUSED;
 		return ret;
 	}
 	case VIDIOCGFBUF:
@@ -1147,36 +1160,36 @@
 static ssize_t se401_read(struct file *file, char __user *buf,
 		     size_t count, loff_t *ppos)
 {
-	int realcount=count, ret=0;
+	int realcount = count, ret = 0;
 	struct video_device *dev = file->private_data;
 	struct usb_se401 *se401 = (struct usb_se401 *)dev;
 
 
-	if (se401->dev == NULL)
+	if (se401->dev ==  NULL)
 		return -EIO;
 	if (realcount > se401->cwidth*se401->cheight*3)
-		realcount=se401->cwidth*se401->cheight*3;
+		realcount = se401->cwidth*se401->cheight*3;
 
 	/* Shouldn't happen: */
-	if (se401->frame[0].grabstate==FRAME_GRABBING)
+	if (se401->frame[0].grabstate == FRAME_GRABBING)
 		return -EBUSY;
-	se401->frame[0].grabstate=FRAME_READY;
-	se401->frame[1].grabstate=FRAME_UNUSED;
-	se401->curframe=0;
+	se401->frame[0].grabstate = FRAME_READY;
+	se401->frame[1].grabstate = FRAME_UNUSED;
+	se401->curframe = 0;
 
 	if (!se401->streaming)
 		se401_start_stream(se401);
 
 	/* Set the picture properties */
-	if (se401->framecount==0)
+	if (se401->framecount == 0)
 		se401_send_pict(se401);
 	/* Calibrate the reset level after a few frames. */
-	if (se401->framecount%20==1)
+	if (se401->framecount%20 == 1)
 		se401_auto_resetlevel(se401);
 
-	ret=se401_newframe(se401, 0);
+	ret = se401_newframe(se401, 0);
 
-	se401->frame[0].grabstate=FRAME_UNUSED;
+	se401->frame[0].grabstate = FRAME_UNUSED;
 	if (ret)
 		return ret;
 	if (copy_to_user(buf, se401->frame[0].data, realcount))
@@ -1195,11 +1208,12 @@
 
 	mutex_lock(&se401->lock);
 
-	if (se401->dev == NULL) {
+	if (se401->dev ==  NULL) {
 		mutex_unlock(&se401->lock);
 		return -EIO;
 	}
-	if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+	if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1)
+							& ~(PAGE_SIZE - 1))) {
 		mutex_unlock(&se401->lock);
 		return -EINVAL;
 	}
@@ -1210,10 +1224,10 @@
 			mutex_unlock(&se401->lock);
 			return -EAGAIN;
 		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
+		start +=  PAGE_SIZE;
+		pos +=  PAGE_SIZE;
 		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
+			size -=  PAGE_SIZE;
 		else
 			size = 0;
 	}
@@ -1223,7 +1237,7 @@
 }
 
 static const struct v4l2_file_operations se401_fops = {
-	.owner =	THIS_MODULE,
+	.owner  = 	THIS_MODULE,
 	.open =         se401_open,
 	.release =      se401_close,
 	.read =         se401_read,
@@ -1241,71 +1255,76 @@
 /***************************/
 static int se401_init(struct usb_se401 *se401, int button)
 {
-	int i=0, rc;
+	int i = 0, rc;
 	unsigned char cp[0x40];
 	char temp[200];
+	int slen;
 
 	/* led on */
 	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
 
 	/* get camera descriptor */
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
-	if (cp[1]!=0x41) {
+	rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0,
+							cp, sizeof(cp));
+	if (cp[1] != 0x41) {
 		err("Wrong descriptor type");
 		return 1;
 	}
-	sprintf (temp, "ExtraFeatures: %d", cp[3]);
+	slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]);
 
-	se401->sizes=cp[4]+cp[5]*256;
-	se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+	se401->sizes = cp[4] + cp[5] * 256;
+	se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
 	if (!se401->width)
 		return 1;
-	se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+	se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
 	if (!se401->height) {
 		kfree(se401->width);
 		return 1;
 	}
-	for (i=0; i<se401->sizes; i++) {
-		    se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
-		    se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
+	for (i = 0; i < se401->sizes; i++) {
+		se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256;
+		se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256;
 	}
-	sprintf (temp, "%s Sizes:", temp);
-	for (i=0; i<se401->sizes; i++) {
-		sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
+	slen += snprintf(temp + slen, 200 - slen, " Sizes:");
+	for (i = 0; i < se401->sizes; i++) {
+		slen +=  snprintf(temp + slen, 200 - slen,
+			" %dx%d", se401->width[i], se401->height[i]);
 	}
 	dev_info(&se401->dev->dev, "%s\n", temp);
-	se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
+	se401->maxframesize = se401->width[se401->sizes-1] *
+					se401->height[se401->sizes - 1] * 3;
 
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
-	se401->cwidth=cp[0]+cp[1]*256;
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
-	se401->cheight=cp[0]+cp[1]*256;
+	rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
+	se401->cwidth = cp[0]+cp[1]*256;
+	rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
+	se401->cheight = cp[0]+cp[1]*256;
 
 	if (!(cp[2] & SE401_FORMAT_BAYER)) {
 		err("Bayer format not supported!");
 		return 1;
 	}
 	/* set output mode (BAYER) */
-	se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
+	se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE,
+						SE401_FORMAT_BAYER, NULL, 0);
 
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
-	se401->brightness=cp[0]+cp[1]*256;
+	rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
+	se401->brightness = cp[0]+cp[1]*256;
 	/* some default values */
-	se401->resetlevel=0x2d;
-	se401->rgain=0x20;
-	se401->ggain=0x20;
-	se401->bgain=0x20;
+	se401->resetlevel = 0x2d;
+	se401->rgain = 0x20;
+	se401->ggain = 0x20;
+	se401->bgain = 0x20;
 	se401_set_exposure(se401, 20000);
-	se401->palette=VIDEO_PALETTE_RGB24;
-	se401->enhance=1;
-	se401->dropped=0;
-	se401->error=0;
-	se401->framecount=0;
-	se401->readcount=0;
+	se401->palette = VIDEO_PALETTE_RGB24;
+	se401->enhance = 1;
+	se401->dropped = 0;
+	se401->error = 0;
+	se401->framecount = 0;
+	se401->readcount = 0;
 
 	/* Start interrupt transfers for snapshot button */
 	if (button) {
-		se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
+		se401->inturb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!se401->inturb) {
 			dev_info(&se401->dev->dev,
 				 "Allocation of inturb failed\n");
@@ -1323,7 +1342,7 @@
 			return 1;
 		}
 	} else
-		se401->inturb=NULL;
+		se401->inturb = NULL;
 
 	/* Flash the led */
 	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
@@ -1340,8 +1359,8 @@
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_interface_descriptor *interface;
 	struct usb_se401 *se401;
-	char *camera_name=NULL;
-	int button=1;
+	char *camera_name = NULL;
+	int button = 1;
 
 	/* We don't handle multi-config cameras */
 	if (dev->descriptor.bNumConfigurations != 1)
@@ -1350,22 +1369,22 @@
 	interface = &intf->cur_altsetting->desc;
 
 	/* Is it an se401? */
-	if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
-	    le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
-		camera_name="Endpoints/Aox SE401";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
-	    le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
-		camera_name="Philips PCVC665K";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
-	    le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
-		camera_name="Kensington VideoCAM 67014";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
-	    le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
-		camera_name="Kensington VideoCAM 6701(5/7)";
-	} else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
-	    le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
-		camera_name="Kensington VideoCAM 67016";
-		button=0;
+	if (le16_to_cpu(dev->descriptor.idVendor) ==  0x03e8 &&
+	    le16_to_cpu(dev->descriptor.idProduct) ==  0x0004) {
+		camera_name = "Endpoints/Aox SE401";
+	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x0471 &&
+	    le16_to_cpu(dev->descriptor.idProduct) ==  0x030b) {
+		camera_name = "Philips PCVC665K";
+	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x047d &&
+	    le16_to_cpu(dev->descriptor.idProduct) ==  0x5001) {
+		camera_name = "Kensington VideoCAM 67014";
+	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x047d &&
+	    le16_to_cpu(dev->descriptor.idProduct) ==  0x5002) {
+		camera_name = "Kensington VideoCAM 6701(5/7)";
+	} else if (le16_to_cpu(dev->descriptor.idVendor) ==  0x047d &&
+	    le16_to_cpu(dev->descriptor.idProduct) ==  0x5003) {
+		camera_name = "Kensington VideoCAM 67016";
+		button = 0;
 	} else
 		return -ENODEV;
 
@@ -1378,7 +1397,8 @@
 	/* We found one */
 	dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name);
 
-	if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
+	se401 = kzalloc(sizeof(*se401), GFP_KERNEL);
+	if (se401 ==  NULL) {
 		err("couldn't kmalloc se401 struct");
 		return -ENOMEM;
 	}
@@ -1396,12 +1416,14 @@
 	}
 
 	memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
-	memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
+	memcpy(se401->vdev.name, se401->camera_name,
+					strlen(se401->camera_name));
 	init_waitqueue_head(&se401->wq);
 	mutex_init(&se401->lock);
 	wmb();
 
-	if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+	if (video_register_device(&se401->vdev,
+					VFL_TYPE_GRABBER, video_nr) < 0) {
 		kfree(se401);
 		err("video_register_device failed");
 		return -EIO;
@@ -1409,20 +1431,20 @@
 	dev_info(&intf->dev, "registered new video device: video%d\n",
 		 se401->vdev.num);
 
-	usb_set_intfdata (intf, se401);
+	usb_set_intfdata(intf, se401);
 	return 0;
 }
 
 static void se401_disconnect(struct usb_interface *intf)
 {
-	struct usb_se401 *se401 = usb_get_intfdata (intf);
+	struct usb_se401 *se401 = usb_get_intfdata(intf);
 
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(intf, NULL);
 	if (se401) {
 		video_unregister_device(&se401->vdev);
-		if (!se401->user){
+		if (!se401->user)
 			usb_se401_remove_disconnected(se401);
-		} else {
+		else {
 			se401->frame[0].grabstate = FRAME_ERROR;
 			se401->frame[0].grabstate = FRAME_ERROR;
 
@@ -1435,10 +1457,10 @@
 }
 
 static struct usb_driver se401_driver = {
-	.name		= "se401",
-	.id_table	= device_table,
-	.probe		= se401_probe,
-	.disconnect	= se401_disconnect,
+	.name		 =  "se401",
+	.id_table	 =  device_table,
+	.probe		 =  se401_probe,
+	.disconnect	 =  se401_disconnect,
 };
 
 
@@ -1451,9 +1473,10 @@
 
 static int __init usb_se401_init(void)
 {
-	printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version);
+	printk(KERN_INFO "SE401 usb camera driver version %s registering\n",
+								version);
 	if (flickerless)
-		if (flickerless!=50 && flickerless!=60) {
+		if (flickerless != 50 && flickerless != 60) {
 			printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n");
 			return -1;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/se401.h linux-libre-2.6.31-gnu/drivers/media/video/se401.h
--- linux-libre-2.6.30-gnu/drivers/media/video/se401.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/se401.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
 #ifndef __LINUX_se401_H
 #define __LINUX_se401_H
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
@@ -12,9 +12,10 @@
 
 #ifdef se401_DEBUG
 #  define PDEBUG(level, fmt, args...) \
-if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
+if (debug >= level) \
+	info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
 #else
-#  define PDEBUG(level, fmt, args...) do {} while(0)
+#  define PDEBUG(level, fmt, args...) do {} while (0)
 #endif
 
 /* An almost drop-in replacement for sleep_on_interruptible */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/sh_mobile_ceu_camera.c linux-libre-2.6.31-gnu/drivers/media/video/sh_mobile_ceu_camera.c
--- linux-libre-2.6.30-gnu/drivers/media/video/sh_mobile_ceu_camera.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/sh_mobile_ceu_camera.c	2009-09-09 18:13:59.000000000 -0400
@@ -81,7 +81,6 @@
 };
 
 struct sh_mobile_ceu_dev {
-	struct device *dev;
 	struct soc_camera_host ici;
 	struct soc_camera_device *icd;
 
@@ -283,27 +282,24 @@
 	return ret;
 }
 
+/* Called under spinlock_irqsave(&pcdev->lock, ...) */
 static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
 					 struct videobuf_buffer *vb)
 {
 	struct soc_camera_device *icd = vq->priv_data;
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	unsigned long flags;
 
 	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
 		vb, vb->baddr, vb->bsize);
 
 	vb->state = VIDEOBUF_QUEUED;
-	spin_lock_irqsave(&pcdev->lock, flags);
 	list_add_tail(&vb->queue, &pcdev->capture);
 
 	if (!pcdev->active) {
 		pcdev->active = vb;
 		sh_mobile_ceu_capture(pcdev);
 	}
-
-	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
 static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq,
@@ -617,7 +613,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = icd->formats[idx].depth;
 			xlate++;
-			dev_dbg(&ici->dev, "Providing format %s using %s\n",
+			dev_dbg(ici->dev, "Providing format %s using %s\n",
 				sh_mobile_ceu_formats[k].name,
 				icd->formats[idx].name);
 		}
@@ -630,7 +626,7 @@
 			xlate->cam_fmt = icd->formats + idx;
 			xlate->buswidth = icd->formats[idx].depth;
 			xlate++;
-			dev_dbg(&ici->dev,
+			dev_dbg(ici->dev,
 				"Providing format %s in pass-through mode\n",
 				icd->formats[idx].name);
 		}
@@ -657,7 +653,7 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+		dev_warn(ici->dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
@@ -684,22 +680,14 @@
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+		dev_warn(ici->dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
 	/* FIXME: calculate using depth and bus width */
 
-	if (f->fmt.pix.height < 4)
-		f->fmt.pix.height = 4;
-	if (f->fmt.pix.height > 1920)
-		f->fmt.pix.height = 1920;
-	if (f->fmt.pix.width < 2)
-		f->fmt.pix.width = 2;
-	if (f->fmt.pix.width > 2560)
-		f->fmt.pix.width = 2560;
-	f->fmt.pix.width &= ~0x01;
-	f->fmt.pix.height &= ~0x03;
+	v4l_bound_align_image(&f->fmt.pix.width, 2, 2560, 1,
+			      &f->fmt.pix.height, 4, 1920, 2, 0);
 
 	f->fmt.pix.bytesperline = f->fmt.pix.width *
 		DIV_ROUND_UP(xlate->host_fmt->depth, 8);
@@ -782,7 +770,7 @@
 
 	videobuf_queue_dma_contig_init(q,
 				       &sh_mobile_ceu_videobuf_ops,
-				       &ici->dev, &pcdev->lock,
+				       ici->dev, &pcdev->lock,
 				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
 				       pcdev->is_interlaced ?
 				       V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
@@ -829,7 +817,6 @@
 		goto exit;
 	}
 
-	platform_set_drvdata(pdev, pcdev);
 	INIT_LIST_HEAD(&pcdev->capture);
 	spin_lock_init(&pcdev->lock);
 
@@ -840,7 +827,7 @@
 		goto exit_kfree;
 	}
 
-	base = ioremap_nocache(res->start, res->end - res->start + 1);
+	base = ioremap_nocache(res->start, resource_size(res));
 	if (!base) {
 		err = -ENXIO;
 		dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n");
@@ -850,13 +837,12 @@
 	pcdev->irq = irq;
 	pcdev->base = base;
 	pcdev->video_limit = 0; /* only enabled if second resource exists */
-	pcdev->dev = &pdev->dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (res) {
 		err = dma_declare_coherent_memory(&pdev->dev, res->start,
 						  res->start,
-						  (res->end - res->start) + 1,
+						  resource_size(res),
 						  DMA_MEMORY_MAP |
 						  DMA_MEMORY_EXCLUSIVE);
 		if (!err) {
@@ -865,7 +851,7 @@
 			goto exit_iounmap;
 		}
 
-		pcdev->video_limit = (res->end - res->start) + 1;
+		pcdev->video_limit = resource_size(res);
 	}
 
 	/* request irq */
@@ -885,7 +871,7 @@
 	}
 
 	pcdev->ici.priv = pcdev;
-	pcdev->ici.dev.parent = &pdev->dev;
+	pcdev->ici.dev = &pdev->dev;
 	pcdev->ici.nr = pdev->id;
 	pcdev->ici.drv_name = dev_name(&pdev->dev);
 	pcdev->ici.ops = &sh_mobile_ceu_host_ops;
@@ -913,9 +899,11 @@
 
 static int sh_mobile_ceu_remove(struct platform_device *pdev)
 {
-	struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev);
+	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+	struct sh_mobile_ceu_dev *pcdev = container_of(soc_host,
+					struct sh_mobile_ceu_dev, ici);
 
-	soc_camera_host_unregister(&pcdev->ici);
+	soc_camera_host_unregister(soc_host);
 	clk_put(pcdev->clk);
 	free_irq(pcdev->irq, pcdev);
 	if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/soc_camera.c linux-libre-2.6.31-gnu/drivers/media/video/soc_camera.c
--- linux-libre-2.6.30-gnu/drivers/media/video/soc_camera.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/soc_camera.c	2009-09-09 18:13:59.000000000 -0400
@@ -16,19 +16,21 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
-#include <linux/list.h>
 #include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 #include <linux/vmalloc.h>
 
+#include <media/soc_camera.h>
 #include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
 #include <media/videobuf-core.h>
-#include <media/soc_camera.h>
 
 /* Default to VGA resolution */
 #define DEFAULT_WIDTH	640
@@ -235,11 +237,11 @@
 		return -ENOMEM;
 
 	icd->num_user_formats = fmts;
-	fmts = 0;
 
 	dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts);
 
 	/* Second pass - actually fill data formats */
+	fmts = 0;
 	for (i = 0; i < icd->num_formats; i++)
 		if (!ici->ops->get_formats) {
 			icd->user_formats[i].host_fmt = icd->formats + i;
@@ -279,7 +281,7 @@
 		return ret;
 	} else if (!icd->current_fmt ||
 		   icd->current_fmt->fourcc != pix->pixelformat) {
-		dev_err(&ici->dev,
+		dev_err(ici->dev,
 			"Host driver hasn't set up current format correctly!\n");
 		return -EINVAL;
 	}
@@ -794,7 +796,7 @@
 
 	list_for_each_entry(icd, &devices, list) {
 		if (icd->iface == ici->nr) {
-			icd->dev.parent = &ici->dev;
+			icd->dev.parent = ici->dev;
 			device_register_link(icd);
 		}
 	}
@@ -818,7 +820,7 @@
 	list_for_each_entry(ici, &hosts, list) {
 		if (icd->iface == ici->nr) {
 			ret = 1;
-			icd->dev.parent = &ici->dev;
+			icd->dev.parent = ici->dev;
 			break;
 		}
 	}
@@ -875,8 +877,11 @@
 			(unsigned short)~0;
 
 		ret = soc_camera_init_user_formats(icd);
-		if (ret < 0)
+		if (ret < 0) {
+			if (icd->ops->remove)
+				icd->ops->remove(icd);
 			goto eiufmt;
+		}
 
 		icd->height	= DEFAULT_HEIGHT;
 		icd->width	= DEFAULT_WIDTH;
@@ -900,8 +905,10 @@
 {
 	struct soc_camera_device *icd = to_soc_camera_dev(dev);
 
+	mutex_lock(&icd->video_lock);
 	if (icd->ops->remove)
 		icd->ops->remove(icd);
+	mutex_unlock(&icd->video_lock);
 
 	soc_camera_free_user_formats(icd);
 
@@ -952,7 +959,6 @@
 
 int soc_camera_host_register(struct soc_camera_host *ici)
 {
-	int ret;
 	struct soc_camera_host *ix;
 
 	if (!ici || !ici->ops ||
@@ -965,12 +971,10 @@
 	    !ici->ops->reqbufs ||
 	    !ici->ops->add ||
 	    !ici->ops->remove ||
-	    !ici->ops->poll)
+	    !ici->ops->poll ||
+	    !ici->dev)
 		return -EINVAL;
 
-	/* Number might be equal to the platform device ID */
-	dev_set_name(&ici->dev, "camera_host%d", ici->nr);
-
 	mutex_lock(&list_lock);
 	list_for_each_entry(ix, &hosts, list) {
 		if (ix->nr == ici->nr) {
@@ -979,26 +983,14 @@
 		}
 	}
 
+	dev_set_drvdata(ici->dev, ici);
+
 	list_add_tail(&ici->list, &hosts);
 	mutex_unlock(&list_lock);
 
-	ici->dev.release = dummy_release;
-
-	ret = device_register(&ici->dev);
-
-	if (ret)
-		goto edevr;
-
 	scan_add_host(ici);
 
 	return 0;
-
-edevr:
-	mutex_lock(&list_lock);
-	list_del(&ici->list);
-	mutex_unlock(&list_lock);
-
-	return ret;
 }
 EXPORT_SYMBOL(soc_camera_host_register);
 
@@ -1012,7 +1004,7 @@
 	list_del(&ici->list);
 
 	list_for_each_entry(icd, &devices, list) {
-		if (icd->dev.parent == &ici->dev) {
+		if (icd->dev.parent == ici->dev) {
 			device_unregister(&icd->dev);
 			/* Not before device_unregister(), .remove
 			 * needs parent to call ici->ops->remove() */
@@ -1023,7 +1015,7 @@
 
 	mutex_unlock(&list_lock);
 
-	device_unregister(&ici->dev);
+	dev_set_drvdata(ici->dev, NULL);
 }
 EXPORT_SYMBOL(soc_camera_host_unregister);
 
@@ -1130,7 +1122,7 @@
 	vdev = video_device_alloc();
 	if (!vdev)
 		goto evidallocd;
-	dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
+	dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
 
 	strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
 
@@ -1158,6 +1150,7 @@
 }
 EXPORT_SYMBOL(soc_camera_video_start);
 
+/* Called from client .remove() methods with .video_lock held */
 void soc_camera_video_stop(struct soc_camera_device *icd)
 {
 	struct video_device *vdev = icd->vdev;
@@ -1167,13 +1160,62 @@
 	if (!icd->dev.parent || !vdev)
 		return;
 
-	mutex_lock(&icd->video_lock);
 	video_unregister_device(vdev);
 	icd->vdev = NULL;
-	mutex_unlock(&icd->video_lock);
 }
 EXPORT_SYMBOL(soc_camera_video_stop);
 
+static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
+{
+	struct soc_camera_link *icl = pdev->dev.platform_data;
+	struct i2c_adapter *adap;
+	struct i2c_client *client;
+
+	if (!icl)
+		return -EINVAL;
+
+	adap = i2c_get_adapter(icl->i2c_adapter_id);
+	if (!adap) {
+		dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n",
+			 icl->i2c_adapter_id);
+		/* -ENODEV and -ENXIO do not produce an error on probe()... */
+		return -ENOENT;
+	}
+
+	icl->board_info->platform_data = icl;
+	client = i2c_new_device(adap, icl->board_info);
+	if (!client) {
+		i2c_put_adapter(adap);
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, client);
+
+	return 0;
+}
+
+static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
+{
+	struct i2c_client *client = platform_get_drvdata(pdev);
+
+	if (!client)
+		return -ENODEV;
+
+	i2c_unregister_device(client);
+	i2c_put_adapter(client->adapter);
+
+	return 0;
+}
+
+static struct platform_driver __refdata soc_camera_pdrv = {
+	.probe	= soc_camera_pdrv_probe,
+	.remove	= __devexit_p(soc_camera_pdrv_remove),
+	.driver	= {
+		.name = "soc-camera-pdrv",
+		.owner = THIS_MODULE,
+	},
+};
+
 static int __init soc_camera_init(void)
 {
 	int ret = bus_register(&soc_camera_bus_type);
@@ -1183,8 +1225,14 @@
 	if (ret)
 		goto edrvr;
 
+	ret = platform_driver_register(&soc_camera_pdrv);
+	if (ret)
+		goto epdr;
+
 	return 0;
 
+epdr:
+	driver_unregister(&ic_drv);
 edrvr:
 	bus_unregister(&soc_camera_bus_type);
 	return ret;
@@ -1192,6 +1240,7 @@
 
 static void __exit soc_camera_exit(void)
 {
+	platform_driver_unregister(&soc_camera_pdrv);
 	driver_unregister(&ic_drv);
 	bus_unregister(&soc_camera_bus_type);
 }
@@ -1202,3 +1251,4 @@
 MODULE_DESCRIPTION("Image capture bus driver");
 MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:soc-camera-pdrv");
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/stk-webcam.c linux-libre-2.6.31-gnu/drivers/media/video/stk-webcam.c
--- linux-libre-2.6.30-gnu/drivers/media/video/stk-webcam.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/stk-webcam.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 
 #include <linux/usb.h>
 #include <linux/mm.h>
@@ -1049,8 +1050,8 @@
 		depth = 1;
 	else
 		depth = 2;
-	while (stk_sizes[i].m != dev->vsettings.mode
-			&& i < ARRAY_SIZE(stk_sizes))
+	while (i < ARRAY_SIZE(stk_sizes) &&
+			stk_sizes[i].m != dev->vsettings.mode)
 		i++;
 	if (i == ARRAY_SIZE(stk_sizes)) {
 		STK_ERROR("Something is broken in %s\n", __func__);
@@ -1137,7 +1138,7 @@
 	struct stk_camera *dev = priv;
 	struct stk_sio_buffer *sbuf;
 
-	if (buf->index < 0 || buf->index >= dev->n_sbufs)
+	if (buf->index >= dev->n_sbufs)
 		return -EINVAL;
 	sbuf = dev->sio_bufs + buf->index;
 	*buf = sbuf->v4lbuf;
@@ -1154,7 +1155,7 @@
 	if (buf->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 
-	if (buf->index < 0 || buf->index >= dev->n_sbufs)
+	if (buf->index >= dev->n_sbufs)
 		return -EINVAL;
 	sbuf = dev->sio_bufs + buf->index;
 	if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/stradis.c linux-libre-2.6.31-gnu/drivers/media/video/stradis.c
--- linux-libre-2.6.30-gnu/drivers/media/video/stradis.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/stradis.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/poll.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/stv680.c linux-libre-2.6.31-gnu/drivers/media/video/stv680.c
--- linux-libre-2.6.30-gnu/drivers/media/video/stv680.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/stv680.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,7 @@
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/videodev.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tcm825x.c linux-libre-2.6.31-gnu/drivers/media/video/tcm825x.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tcm825x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tcm825x.c	2009-09-09 18:13:59.000000000 -0400
@@ -878,7 +878,7 @@
 	return rval;
 }
 
-static int __exit tcm825x_remove(struct i2c_client *client)
+static int tcm825x_remove(struct i2c_client *client)
 {
 	struct tcm825x_sensor *sensor = i2c_get_clientdata(client);
 
@@ -902,7 +902,7 @@
 		.name = TCM825X_NAME,
 	},
 	.probe	= tcm825x_probe,
-	.remove	= __exit_p(tcm825x_remove),
+	.remove	= tcm825x_remove,
 	.id_table = tcm825x_id,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tda7432.c linux-libre-2.6.31-gnu/drivers/media/video/tda7432.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tda7432.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tda7432.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,20 +20,6 @@
  * loudness - set between 0 and 15 for varying degrees of loudness effect
  *
  * maxvol   - set maximium volume to +20db (1), default is 0db(0)
- *
- *
- *  Revision: 0.7 - maxvol module parm to set maximium volume 0db or +20db
- *  				store if muted so we can return it
- *  				change balance only if flaged to
- *  Revision: 0.6 - added tone controls
- *  Revision: 0.5 - Fixed odd balance problem
- *  Revision: 0.4 - added muting
- *  Revision: 0.3 - Fixed silly reversed volume controls.  :)
- *  Revision: 0.2 - Cleaned up #defines
- *			fixed volume control
- *          Added I2C_DRIVERID_TDA7432
- *			added loudness insmod control
- *  Revision: 0.1 - initial version
  */
 
 #include <linux/module.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tea6415c.c linux-libre-2.6.31-gnu/drivers/media/video/tea6415c.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tea6415c.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tea6415c.c	2009-09-09 18:13:59.000000000 -0400
@@ -141,7 +141,6 @@
 	.video = &tea6415c_video_ops,
 };
 
-/* this function is called by i2c_probe */
 static int tea6415c_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tea6420.c linux-libre-2.6.31-gnu/drivers/media/video/tea6420.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tea6420.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tea6420.c	2009-09-09 18:13:59.000000000 -0400
@@ -112,7 +112,6 @@
 	.audio = &tea6420_audio_ops,
 };
 
-/* this function is called by i2c_probe */
 static int tea6420_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/ths7303.c linux-libre-2.6.31-gnu/drivers/media/video/ths7303.c
--- linux-libre-2.6.30-gnu/drivers/media/video/ths7303.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/media/video/ths7303.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,151 @@
+/*
+ * ths7303- THS7303 Video Amplifier driver
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
+MODULE_AUTHOR("Chaithrika U S");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+/* following function is used to set ths7303 */
+static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	int err = 0;
+	u8 val;
+	struct i2c_client *client;
+
+	client = v4l2_get_subdevdata(sd);
+
+	if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
+		val = 0x02;
+		v4l2_dbg(1, debug, sd, "setting value for SDTV format\n");
+	} else {
+		val = 0x00;
+		v4l2_dbg(1, debug, sd, "disabling all channels\n");
+	}
+
+	err |= i2c_smbus_write_byte_data(client, 0x01, val);
+	err |= i2c_smbus_write_byte_data(client, 0x02, val);
+	err |= i2c_smbus_write_byte_data(client, 0x03, val);
+
+	if (err)
+		v4l2_err(sd, "write failed\n");
+
+	return err;
+}
+
+static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	return ths7303_setvalue(sd, norm);
+}
+
+static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_THS7303, 0);
+}
+
+static const struct v4l2_subdev_video_ops ths7303_video_ops = {
+	.s_std_output	= ths7303_s_std_output,
+};
+
+static const struct v4l2_subdev_core_ops ths7303_core_ops = {
+	.g_chip_ident = ths7303_g_chip_ident,
+};
+
+static const struct v4l2_subdev_ops ths7303_ops = {
+	.core	= &ths7303_core_ops,
+	.video 	= &ths7303_video_ops,
+};
+
+static int ths7303_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct v4l2_subdev *sd;
+	v4l2_std_id std_id = V4L2_STD_NTSC;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	if (sd == NULL)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
+
+	return ths7303_setvalue(sd, std_id);
+}
+
+static int ths7303_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+
+	return 0;
+}
+
+static const struct i2c_device_id ths7303_id[] = {
+	{"ths7303", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, ths7303_id);
+
+static struct i2c_driver ths7303_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "ths7303",
+	},
+	.probe		= ths7303_probe,
+	.remove		= ths7303_remove,
+	.id_table	= ths7303_id,
+};
+
+static int __init ths7303_init(void)
+{
+	return i2c_add_driver(&ths7303_driver);
+}
+
+static void __exit ths7303_exit(void)
+{
+	i2c_del_driver(&ths7303_driver);
+}
+
+module_init(ths7303_init);
+module_exit(ths7303_exit);
+
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tuner-core.c linux-libre-2.6.31-gnu/drivers/media/video/tuner-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tuner-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tuner-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -309,32 +309,6 @@
 	}
 }
 
-static void tuner_i2c_address_check(struct tuner *t)
-{
-	if ((t->type == UNSET || t->type == TUNER_ABSENT) ||
-	    ((t->i2c->addr < 0x64) || (t->i2c->addr > 0x6f)))
-		return;
-
-	/* We already know that the XC5000 can only be located at
-	 * i2c address 0x61, 0x62, 0x63 or 0x64 */
-	if ((t->type == TUNER_XC5000) &&
-	    ((t->i2c->addr <= 0x64)) && (t->i2c->addr >= 0x61))
-		return;
-
-	tuner_warn("====================== WARNING! ======================\n");
-	tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n");
-	tuner_warn("will soon be dropped. This message indicates that your\n");
-	tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n",
-		   t->name, t->i2c->addr);
-	tuner_warn("To ensure continued support for your device, please\n");
-	tuner_warn("send a copy of this message, along with full dmesg\n");
-	tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
-	tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
-	tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
-		   t->i2c->adapter->name, t->i2c->addr, t->type, t->name);
-	tuner_warn("====================== WARNING! ======================\n");
-}
-
 static struct xc5000_config xc5000_cfg;
 
 static void set_type(struct i2c_client *c, unsigned int type,
@@ -438,18 +412,12 @@
 		break;
 	case TUNER_XC5000:
 	{
-		struct dvb_tuner_ops *xc_tuner_ops;
-
 		xc5000_cfg.i2c_address	  = t->i2c->addr;
 		/* if_khz will be set when the digital dvb_attach() occurs */
 		xc5000_cfg.if_khz	  = 0;
 		if (!dvb_attach(xc5000_attach,
 				&t->fe, t->i2c->adapter, &xc5000_cfg))
 			goto attach_failed;
-
-		xc_tuner_ops = &t->fe.ops.tuner_ops;
-		if (xc_tuner_ops->init)
-			xc_tuner_ops->init(&t->fe);
 		break;
 	}
 	default:
@@ -490,7 +458,6 @@
 	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
 		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
 		  t->mode_mask);
-	tuner_i2c_address_check(t);
 	return;
 
 attach_failed:
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tveeprom.c linux-libre-2.6.31-gnu/drivers/media/video/tveeprom.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tveeprom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tveeprom.c	2009-09-09 18:13:59.000000000 -0400
@@ -184,7 +184,7 @@
 	{ TUNER_ABSENT,        		"Silicon TDA8275C1 8290 FM"},
 	{ TUNER_ABSENT,        		"Thompson DTT757"},
 	/* 80-89 */
-	{ TUNER_PHILIPS_FM1216ME_MK3, 	"Philips FQ1216LME MK3"},
+	{ TUNER_PHILIPS_FQ1216LME_MK3, 	"Philips FQ1216LME MK3"},
 	{ TUNER_LG_PAL_NEW_TAPC, 	"LG TAPC G701D"},
 	{ TUNER_LG_NTSC_NEW_TAPC, 	"LG TAPC H791F"},
 	{ TUNER_LG_PAL_NEW_TAPC, 	"TCL 2002MB 3"},
@@ -210,7 +210,7 @@
 	{ TUNER_TEA5767,       		"Philips TEA5768HL FM Radio"},
 	{ TUNER_ABSENT,        		"Panasonic ENV57H12D5"},
 	{ TUNER_PHILIPS_FM1236_MK3, 	"TCL MFNM05-4"},
-	{ TUNER_ABSENT,        		"TCL MNM05-4"},
+	{ TUNER_PHILIPS_FM1236_MK3,	"TCL MNM05-4"},
 	{ TUNER_PHILIPS_FM1216ME_MK3, 	"TCL MPE05-2"},
 	{ TUNER_ABSENT,        		"TCL MQNM05-4"},
 	{ TUNER_ABSENT,        		"LG TAPC-W701D"},
@@ -229,7 +229,7 @@
 	{ TUNER_ABSENT,        		"Samsung THPD5222FG30A"},
 	/* 120-129 */
 	{ TUNER_XC2028,        		"Xceive XC3028"},
-	{ TUNER_ABSENT,        		"Philips FQ1216LME MK5"},
+	{ TUNER_PHILIPS_FQ1216LME_MK3,	"Philips FQ1216LME MK5"},
 	{ TUNER_ABSENT,        		"Philips FQD1216LME"},
 	{ TUNER_ABSENT,        		"Conexant CX24118A"},
 	{ TUNER_ABSENT,        		"TCL DMF11WIP"},
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tvp514x.c linux-libre-2.6.31-gnu/drivers/media/video/tvp514x.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tvp514x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tvp514x.c	2009-09-09 18:13:59.000000000 -0400
@@ -692,7 +692,7 @@
 			break;	/* Input detected */
 	}
 
-	if ((current_std == STD_INVALID) || (try_count <= 0))
+	if ((current_std == STD_INVALID) || (try_count < 0))
 		return -EINVAL;
 
 	decoder->current_std = current_std;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/tw9910.c linux-libre-2.6.31-gnu/drivers/media/video/tw9910.c
--- linux-libre-2.6.30-gnu/drivers/media/video/tw9910.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/tw9910.c	2009-09-09 18:13:59.000000000 -0400
@@ -875,10 +875,12 @@
 	const struct tw9910_scale_ctrl *scale;
 	int                             i, ret;
 
-	info = client->dev.platform_data;
-	if (!info)
+	if (!client->dev.platform_data)
 		return -EINVAL;
 
+	info = container_of(client->dev.platform_data,
+			    struct tw9910_video_info, link);
+
 	if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent),
 				     I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&client->dev,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/Kconfig linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/Kconfig
--- linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -38,10 +38,13 @@
 	  module will be called konicawc.
 
 config USB_QUICKCAM_MESSENGER
-	tristate "USB Logitech Quickcam Messenger"
+	tristate "USB Logitech Quickcam Messenger (DEPRECATED)"
 	depends on VIDEO_V4L1
 	select VIDEO_USBVIDEO
 	---help---
+	  This driver is DEPRECATED please use the gspca stv06xx module
+	  instead.
+
 	  Say Y or M here to enable support for the USB Logitech Quickcam
 	  Messenger webcam.
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/konicawc.c linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/konicawc.c
--- linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/konicawc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/konicawc.c	2009-09-09 18:13:59.000000000 -0400
@@ -240,7 +240,7 @@
 	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT_MASK(EV_KEY);
-	input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+	input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
 
 	error = input_register_device(cam->input);
 	if (error) {
@@ -263,7 +263,7 @@
 static void konicawc_report_buttonstat(struct konicawc *cam)
 {
 	if (cam->input) {
-		input_report_key(cam->input, BTN_0, cam->buttonsts);
+		input_report_key(cam->input, KEY_CAMERA, cam->buttonsts);
 		input_sync(cam->input);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/quickcam_messenger.c linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/quickcam_messenger.c
--- linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/quickcam_messenger.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/quickcam_messenger.c	2009-09-09 18:13:59.000000000 -0400
@@ -103,7 +103,7 @@
 	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT_MASK(EV_KEY);
-	input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+	input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
 
 	error = input_register_device(cam->input);
 	if (error) {
@@ -126,7 +126,7 @@
 static void qcm_report_buttonstat(struct qcm *cam)
 {
 	if (cam->input) {
-		input_report_key(cam->input, BTN_0, cam->button_sts);
+		input_report_key(cam->input, KEY_CAMERA, cam->button_sts);
 		input_sync(cam->input);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/vicam.c linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/vicam.c
--- linux-libre-2.6.30-gnu/drivers/media/video/usbvideo/vicam.c	2012-03-22 19:14:11.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/usbvideo/vicam.c	2012-03-22 20:10:22.000000000 -0400
@@ -43,6 +43,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/usbvision/usbvision-core.c linux-libre-2.6.31-gnu/drivers/media/video/usbvision/usbvision-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/usbvision/usbvision-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/usbvision/usbvision-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -390,10 +390,9 @@
 
 void usbvision_scratch_free(struct usb_usbvision *usbvision)
 {
-	if (usbvision->scratch != NULL) {
-		vfree(usbvision->scratch);
-		usbvision->scratch = NULL;
-	}
+	vfree(usbvision->scratch);
+	usbvision->scratch = NULL;
+
 }
 
 /*
@@ -506,10 +505,9 @@
  */
 void usbvision_decompress_free(struct usb_usbvision *usbvision)
 {
-	if (usbvision->IntraFrameBuffer != NULL) {
-		vfree(usbvision->IntraFrameBuffer);
-		usbvision->IntraFrameBuffer = NULL;
-	}
+	vfree(usbvision->IntraFrameBuffer);
+	usbvision->IntraFrameBuffer = NULL;
+
 }
 
 /************************************************************
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/usbvision/usbvision-video.c linux-libre-2.6.31-gnu/drivers/media/video/usbvision/usbvision-video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/usbvision/usbvision-video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/usbvision/usbvision-video.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/highmem.h>
@@ -541,7 +542,7 @@
 	struct usb_usbvision *usbvision = video_drvdata(file);
 	int chan;
 
-	if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) )
+	if (vi->index >= usbvision->video_inputs)
 		return -EINVAL;
 	if (usbvision->have_tuner) {
 		chan = vi->index;
@@ -1794,7 +1795,7 @@
 	.name		= "usbvision",
 	.id_table	= usbvision_table,
 	.probe		= usbvision_probe,
-	.disconnect	= usbvision_disconnect
+	.disconnect	= __devexit_p(usbvision_disconnect),
 };
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_ctrl.c linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_ctrl.c
--- linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_ctrl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_ctrl.c	2009-09-09 18:13:59.000000000 -0400
@@ -1372,21 +1372,19 @@
 }
 
 /*
- * Prune an entity of its bogus controls. This currently includes processing
- * unit auto controls for which no corresponding manual control is available.
- * Such auto controls make little sense if any, and are known to crash at
- * least the SiGma Micro webcam.
+ * Prune an entity of its bogus controls using a blacklist. Bogus controls
+ * are currently the ones that crash the camera or unconditionally return an
+ * error when queried.
  */
 static void
-uvc_ctrl_prune_entity(struct uvc_entity *entity)
+uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity)
 {
 	static const struct {
-		u8 idx_manual;
-		u8 idx_auto;
+		struct usb_device_id id;
+		u8 index;
 	} blacklist[] = {
-		{ 2, 11 }, /* Hue */
-		{ 6, 12 }, /* White Balance Temperature */
-		{ 7, 13 }, /* White Balance Component */
+		{ { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
+		{ { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
 	};
 
 	u8 *controls;
@@ -1400,19 +1398,17 @@
 	size = entity->processing.bControlSize;
 
 	for (i = 0; i < ARRAY_SIZE(blacklist); ++i) {
-		if (blacklist[i].idx_auto >= 8 * size ||
-		    blacklist[i].idx_manual >= 8 * size)
+		if (!usb_match_id(dev->intf, &blacklist[i].id))
 			continue;
 
-		if (!uvc_test_bit(controls, blacklist[i].idx_auto) ||
-		     uvc_test_bit(controls, blacklist[i].idx_manual))
+		if (blacklist[i].index >= 8 * size ||
+		    !uvc_test_bit(controls, blacklist[i].index))
 			continue;
 
-		uvc_trace(UVC_TRACE_CONTROL, "Auto control %u/%u has no "
-			"matching manual control, removing it.\n", entity->id,
-			blacklist[i].idx_auto);
+		uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, "
+			"removing it.\n", entity->id, blacklist[i].index);
 
-		uvc_clear_bit(controls, blacklist[i].idx_auto);
+		uvc_clear_bit(controls, blacklist[i].index);
 	}
 }
 
@@ -1442,8 +1438,7 @@
 			bControlSize = entity->camera.bControlSize;
 		}
 
-		if (dev->quirks & UVC_QUIRK_PRUNE_CONTROLS)
-			uvc_ctrl_prune_entity(entity);
+		uvc_ctrl_prune_entity(dev, entity);
 
 		for (i = 0; i < bControlSize; ++i)
 			ncontrols += hweight8(bmControls[i]);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_driver.c linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_driver.c
--- linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_driver.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_driver.c	2009-09-09 18:13:59.000000000 -0400
@@ -289,10 +289,8 @@
 	struct uvc_format_desc *fmtdesc;
 	struct uvc_frame *frame;
 	const unsigned char *start = buffer;
-	unsigned char *_buffer;
 	unsigned int interval;
 	unsigned int i, n;
-	int _buflen;
 	__u8 ftype;
 
 	format->type = buffer[2];
@@ -303,7 +301,7 @@
 	case VS_FORMAT_FRAME_BASED:
 		n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28;
 		if (buflen < n) {
-			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d FORMAT error\n",
 			       dev->udev->devnum,
 			       alts->desc.bInterfaceNumber);
@@ -338,7 +336,7 @@
 
 	case VS_FORMAT_MJPEG:
 		if (buflen < 11) {
-			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d FORMAT error\n",
 			       dev->udev->devnum,
 			       alts->desc.bInterfaceNumber);
@@ -354,7 +352,7 @@
 
 	case VS_FORMAT_DV:
 		if (buflen < 9) {
-			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d FORMAT error\n",
 			       dev->udev->devnum,
 			       alts->desc.bInterfaceNumber);
@@ -372,7 +370,7 @@
 			strlcpy(format->name, "HD-DV", sizeof format->name);
 			break;
 		default:
-			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d: unknown DV format %u\n",
 			       dev->udev->devnum,
 			       alts->desc.bInterfaceNumber, buffer[8]);
@@ -401,7 +399,7 @@
 	case VS_FORMAT_STREAM_BASED:
 		/* Not supported yet. */
 	default:
-		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 		       "interface %d unsupported format %u\n",
 		       dev->udev->devnum, alts->desc.bInterfaceNumber,
 		       buffer[2]);
@@ -413,20 +411,11 @@
 	buflen -= buffer[0];
 	buffer += buffer[0];
 
-	/* Count the number of frame descriptors to test the bFrameIndex
-	 * field when parsing the descriptors. We can't rely on the
-	 * bNumFrameDescriptors field as some cameras don't initialize it
-	 * properly.
-	 */
-	for (_buflen = buflen, _buffer = buffer;
-	     _buflen > 2 && _buffer[2] == ftype;
-	     _buflen -= _buffer[0], _buffer += _buffer[0])
-		format->nframes++;
-
 	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
 	 * based formats have frame descriptors.
 	 */
 	while (buflen > 2 && buffer[2] == ftype) {
+		frame = &format->frame[format->nframes];
 		if (ftype != VS_FRAME_FRAME_BASED)
 			n = buflen > 25 ? buffer[25] : 0;
 		else
@@ -435,22 +424,12 @@
 		n = n ? n : 3;
 
 		if (buflen < 26 + 4*n) {
-			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d FRAME error\n", dev->udev->devnum,
 			       alts->desc.bInterfaceNumber);
 			return -EINVAL;
 		}
 
-		if (buffer[3] - 1 >= format->nframes) {
-			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
-			       "interface %d frame index %u out of range\n",
-			       dev->udev->devnum, alts->desc.bInterfaceNumber,
-			       buffer[3]);
-			return -EINVAL;
-		}
-
-		frame = &format->frame[buffer[3] - 1];
-
 		frame->bFrameIndex = buffer[3];
 		frame->bmCapabilities = buffer[4];
 		frame->wWidth = get_unaligned_le16(&buffer[5]);
@@ -507,6 +486,7 @@
 			10000000/frame->dwDefaultFrameInterval,
 			(100000000/frame->dwDefaultFrameInterval)%10);
 
+		format->nframes++;
 		buflen -= buffer[0];
 		buffer += buffer[0];
 	}
@@ -518,7 +498,7 @@
 
 	if (buflen > 2 && buffer[2] == VS_COLORFORMAT) {
 		if (buflen < 6) {
-			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d COLORFORMAT error\n",
 			       dev->udev->devnum,
 			       alts->desc.bInterfaceNumber);
@@ -664,7 +644,7 @@
 	_buflen = buflen;
 
 	/* Count the format and frame descriptors. */
-	while (_buflen > 2) {
+	while (_buflen > 2 && _buffer[1] == CS_INTERFACE) {
 		switch (_buffer[2]) {
 		case VS_FORMAT_UNCOMPRESSED:
 		case VS_FORMAT_MJPEG:
@@ -729,7 +709,7 @@
 	streaming->nformats = nformats;
 
 	/* Parse the format descriptors. */
-	while (buflen > 2) {
+	while (buflen > 2 && buffer[1] == CS_INTERFACE) {
 		switch (buffer[2]) {
 		case VS_FORMAT_UNCOMPRESSED:
 		case VS_FORMAT_MJPEG:
@@ -1316,7 +1296,7 @@
 			continue;
 
 		if (forward->extension.bNrInPins != 1) {
-			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has"
+			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has "
 				"more than 1 input pin.\n", entity->id);
 			return -1;
 		}
@@ -1614,6 +1594,7 @@
 	INIT_LIST_HEAD(&dev->entities);
 	INIT_LIST_HEAD(&dev->streaming);
 	kref_init(&dev->kref);
+	atomic_set(&dev->users, 0);
 
 	dev->udev = usb_get_dev(udev);
 	dev->intf = usb_get_intf(intf);
@@ -1864,11 +1845,29 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
-	/* ViMicro */
-	{ .match_flags		= USB_DEVICE_ID_MATCH_VENDOR
+	/* ViMicro Vega */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
 	  .idVendor		= 0x0ac8,
-	  .idProduct		= 0x0000,
+	  .idProduct		= 0x332d,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
+	/* ViMicro - Minoru3D */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x0ac8,
+	  .idProduct		= 0x3410,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
+	/* ViMicro Venus - Minoru3D */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x0ac8,
+	  .idProduct		= 0x3420,
 	  .bInterfaceClass	= USB_CLASS_VIDEO,
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
@@ -1927,7 +1926,7 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
-	/* Lenovo Thinkpad SL500 */
+	/* Lenovo Thinkpad SL400/SL500 */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
 	  .idVendor		= 0x17ef,
@@ -1936,6 +1935,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
+	/* Aveo Technology USB 2.0 Camera */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x1871,
+	  .idProduct		= 0x0306,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
 	/* Ecamm Pico iMage */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1945,6 +1953,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
+	/* FSC WebCam V30S */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x18ec,
+	  .idProduct		= 0x3288,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
 	/* Bodelin ProScopeHR */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_DEV_HI
@@ -1965,8 +1982,7 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
-				| UVC_QUIRK_IGNORE_SELECTOR_UNIT
-				| UVC_QUIRK_PRUNE_CONTROLS },
+				| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
 	/* Generic USB Video Class */
 	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
 	{}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_queue.c linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_queue.c
--- linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_queue.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_queue.c	2009-09-09 18:13:59.000000000 -0400
@@ -172,6 +172,20 @@
 	return 0;
 }
 
+/*
+ * Check if buffers have been allocated.
+ */
+int uvc_queue_allocated(struct uvc_video_queue *queue)
+{
+	int allocated;
+
+	mutex_lock(&queue->mutex);
+	allocated = queue->count != 0;
+	mutex_unlock(&queue->mutex);
+
+	return allocated;
+}
+
 static void __uvc_query_buffer(struct uvc_buffer *buf,
 		struct v4l2_buffer *v4l2_buf)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_status.c linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_status.c
--- linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_status.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_status.c	2009-09-09 18:13:59.000000000 -0400
@@ -145,8 +145,8 @@
 			break;
 
 		default:
-			uvc_printk(KERN_INFO, "unknown event type %u.\n",
-				dev->status[0]);
+			uvc_trace(UVC_TRACE_STATUS, "Unknown status event "
+				"type %u.\n", dev->status[0]);
 			break;
 		}
 	}
@@ -194,7 +194,7 @@
 		dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
 		dev, interval);
 
-	return usb_submit_urb(dev->int_urb, GFP_KERNEL);
+	return 0;
 }
 
 void uvc_status_cleanup(struct uvc_device *dev)
@@ -205,15 +205,30 @@
 	uvc_input_cleanup(dev);
 }
 
-int uvc_status_suspend(struct uvc_device *dev)
+int uvc_status_start(struct uvc_device *dev)
+{
+	if (dev->int_urb == NULL)
+		return 0;
+
+	return usb_submit_urb(dev->int_urb, GFP_KERNEL);
+}
+
+void uvc_status_stop(struct uvc_device *dev)
 {
 	usb_kill_urb(dev->int_urb);
+}
+
+int uvc_status_suspend(struct uvc_device *dev)
+{
+	if (atomic_read(&dev->users))
+		usb_kill_urb(dev->int_urb);
+
 	return 0;
 }
 
 int uvc_status_resume(struct uvc_device *dev)
 {
-	if (dev->int_urb == NULL)
+	if (dev->int_urb == NULL || atomic_read(&dev->users) == 0)
 		return 0;
 
 	return usb_submit_urb(dev->int_urb, GFP_NOIO);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_v4l2.c linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_v4l2.c
--- linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_v4l2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_v4l2.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,8 @@
 	struct uvc_menu_info *menu_info;
 	struct uvc_control_mapping *mapping;
 	struct uvc_control *ctrl;
+	u32 index = query_menu->index;
+	u32 id = query_menu->id;
 
 	ctrl = uvc_find_control(video, query_menu->id, &mapping);
 	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
@@ -54,6 +56,10 @@
 	if (query_menu->index >= mapping->menu_count)
 		return -EINVAL;
 
+	memset(query_menu, 0, sizeof(*query_menu));
+	query_menu->id = id;
+	query_menu->index = index;
+
 	menu_info = &mapping->menu_info[query_menu->index];
 	strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
 	return 0;
@@ -245,7 +251,7 @@
 	if (fmt->type != video->streaming->type)
 		return -EINVAL;
 
-	if (uvc_queue_streaming(&video->queue))
+	if (uvc_queue_allocated(&video->queue))
 		return -EBUSY;
 
 	ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame);
@@ -433,6 +439,15 @@
 		goto done;
 	}
 
+	if (atomic_inc_return(&video->dev->users) == 1) {
+		if ((ret = uvc_status_start(video->dev)) < 0) {
+			usb_autopm_put_interface(video->dev->intf);
+			atomic_dec(&video->dev->users);
+			kfree(handle);
+			goto done;
+		}
+	}
+
 	handle->device = video;
 	handle->state = UVC_HANDLE_PASSIVE;
 	file->private_data = handle;
@@ -467,6 +482,9 @@
 	kfree(handle);
 	file->private_data = NULL;
 
+	if (atomic_dec_return(&video->dev->users) == 0)
+		uvc_status_stop(video->dev);
+
 	usb_autopm_put_interface(video->dev->intf);
 	kref_put(&video->dev->kref, uvc_delete);
 	return 0;
@@ -512,7 +530,10 @@
 		memset(&xctrl, 0, sizeof xctrl);
 		xctrl.id = ctrl->id;
 
-		uvc_ctrl_begin(video);
+	       ret = uvc_ctrl_begin(video);
+	       if (ret < 0)
+			return ret;
+
 		ret = uvc_ctrl_get(video, &xctrl);
 		uvc_ctrl_rollback(video);
 		if (ret >= 0)
@@ -529,7 +550,10 @@
 		xctrl.id = ctrl->id;
 		xctrl.value = ctrl->value;
 
-		uvc_ctrl_begin(video);
+	       ret = uvc_ctrl_begin(video);
+	       if (ret < 0)
+			return ret;
+
 		ret = uvc_ctrl_set(video, &xctrl);
 		if (ret < 0) {
 			uvc_ctrl_rollback(video);
@@ -548,7 +572,10 @@
 		struct v4l2_ext_control *ctrl = ctrls->controls;
 		unsigned int i;
 
-		uvc_ctrl_begin(video);
+	       ret = uvc_ctrl_begin(video);
+	       if (ret < 0)
+			return ret;
+
 		for (i = 0; i < ctrls->count; ++ctrl, ++i) {
 			ret = uvc_ctrl_get(video, ctrl);
 			if (ret < 0) {
@@ -648,7 +675,7 @@
 
 	case VIDIOC_S_INPUT:
 	{
-		u8 input = *(u32 *)arg + 1;
+		u32 input = *(u32 *)arg + 1;
 
 		if ((ret = uvc_acquire_privileges(handle)) < 0)
 			return ret;
@@ -660,7 +687,7 @@
 			break;
 		}
 
-		if (input > video->selector->selector.bNrInPins)
+		if (input == 0 || input > video->selector->selector.bNrInPins)
 			return -EINVAL;
 
 		return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id,
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_video.c linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_video.c
--- linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvc_video.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvc_video.c	2009-09-09 18:13:59.000000000 -0400
@@ -65,7 +65,8 @@
 	struct uvc_streaming_control *ctrl)
 {
 	struct uvc_format *format;
-	struct uvc_frame *frame;
+	struct uvc_frame *frame = NULL;
+	unsigned int i;
 
 	if (ctrl->bFormatIndex <= 0 ||
 	    ctrl->bFormatIndex > video->streaming->nformats)
@@ -73,11 +74,15 @@
 
 	format = &video->streaming->format[ctrl->bFormatIndex - 1];
 
-	if (ctrl->bFrameIndex <= 0 ||
-	    ctrl->bFrameIndex > format->nframes)
-		return;
+	for (i = 0; i < format->nframes; ++i) {
+		if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
+			frame = &format->frame[i];
+			break;
+		}
+	}
 
-	frame = &format->frame[ctrl->bFrameIndex - 1];
+	if (frame == NULL)
+		return;
 
 	if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
 	     (ctrl->dwMaxVideoFrameSize == 0 &&
@@ -1089,7 +1094,7 @@
 	/* Zero bFrameIndex might be correct. Stream-based formats (including
 	 * MPEG-2 TS and DV) do not support frames but have a dummy frame
 	 * descriptor with bFrameIndex set to zero. If the default frame
-	 * descriptor is not found, use the first avalable frame.
+	 * descriptor is not found, use the first available frame.
 	 */
 	for (i = format->nframes; i > 0; --i) {
 		frame = &format->frame[i-1];
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvcvideo.h linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvcvideo.h
--- linux-libre-2.6.30-gnu/drivers/media/video/uvc/uvcvideo.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/uvc/uvcvideo.h	2009-09-09 18:13:59.000000000 -0400
@@ -313,7 +313,6 @@
 #define UVC_QUIRK_BUILTIN_ISIGHT	0x00000008
 #define UVC_QUIRK_STREAM_NO_FID		0x00000010
 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT	0x00000020
-#define UVC_QUIRK_PRUNE_CONTROLS	0x00000040
 #define UVC_QUIRK_FIX_BANDWIDTH		0x00000080
 
 /* Format flags */
@@ -634,6 +633,7 @@
 	enum uvc_device_state state;
 	struct kref kref;
 	struct list_head list;
+	atomic_t users;
 
 	/* Video control interface */
 	__u16 uvc_version;
@@ -747,6 +747,7 @@
 		struct uvc_buffer *buf);
 extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
 		struct file *file, poll_table *wait);
+extern int uvc_queue_allocated(struct uvc_video_queue *queue);
 static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 {
 	return queue->flags & UVC_QUEUE_STREAMING;
@@ -770,6 +771,8 @@
 /* Status */
 extern int uvc_status_init(struct uvc_device *dev);
 extern void uvc_status_cleanup(struct uvc_device *dev);
+extern int uvc_status_start(struct uvc_device *dev);
+extern void uvc_status_stop(struct uvc_device *dev);
 extern int uvc_status_suspend(struct uvc_device *dev);
 extern int uvc_status_resume(struct uvc_device *dev);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/v4l2-common.c linux-libre-2.6.31-gnu/drivers/media/video/v4l2-common.c
--- linux-libre-2.6.30-gnu/drivers/media/video/v4l2-common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/v4l2-common.c	2009-09-09 18:13:59.000000000 -0400
@@ -746,6 +746,7 @@
 		const struct v4l2_subdev_ops *ops)
 {
 	v4l2_subdev_init(sd, ops);
+	sd->flags |= V4L2_SUBDEV_FL_IS_I2C;
 	/* the owner is the same as the i2c_client's driver owner */
 	sd->owner = client->driver->driver.owner;
 	/* i2c_client and v4l2_subdev point to one another */
@@ -801,6 +802,17 @@
 	/* Decrease the module use count to match the first try_module_get. */
 	module_put(client->driver->driver.owner);
 
+	if (sd) {
+		/* We return errors from v4l2_subdev_call only if we have the
+		   callback as the .s_config is not mandatory */
+		int err = v4l2_subdev_call(sd, core, s_config, 0, NULL);
+
+		if (err && err != -ENOIOCTLCMD) {
+			v4l2_device_unregister_subdev(sd);
+			sd = NULL;
+		}
+	}
+
 error:
 	/* If we have a client but no subdev, then something went wrong and
 	   we must unregister the client. */
@@ -851,6 +863,17 @@
 	/* Decrease the module use count to match the first try_module_get. */
 	module_put(client->driver->driver.owner);
 
+	if (sd) {
+		/* We return errors from v4l2_subdev_call only if we have the
+		   callback as the .s_config is not mandatory */
+		int err = v4l2_subdev_call(sd, core, s_config, 0, NULL);
+
+		if (err && err != -ENOIOCTLCMD) {
+			v4l2_device_unregister_subdev(sd);
+			sd = NULL;
+		}
+	}
+
 error:
 	/* If we have a client but no subdev, then something went wrong and
 	   we must unregister the client. */
@@ -871,6 +894,89 @@
 }
 EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr);
 
+/* Load an i2c sub-device. */
+struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
+		struct i2c_adapter *adapter, const char *module_name,
+		struct i2c_board_info *info, const unsigned short *probe_addrs)
+{
+	struct v4l2_subdev *sd = NULL;
+	struct i2c_client *client;
+
+	BUG_ON(!v4l2_dev);
+
+	if (module_name)
+		request_module(module_name);
+
+	/* Create the i2c client */
+	if (info->addr == 0 && probe_addrs)
+		client = i2c_new_probed_device(adapter, info, probe_addrs);
+	else
+		client = i2c_new_device(adapter, info);
+
+	/* Note: by loading the module first we are certain that c->driver
+	   will be set if the driver was found. If the module was not loaded
+	   first, then the i2c core tries to delay-load the module for us,
+	   and then c->driver is still NULL until the module is finally
+	   loaded. This delay-load mechanism doesn't work if other drivers
+	   want to use the i2c device, so explicitly loading the module
+	   is the best alternative. */
+	if (client == NULL || client->driver == NULL)
+		goto error;
+
+	/* Lock the module so we can safely get the v4l2_subdev pointer */
+	if (!try_module_get(client->driver->driver.owner))
+		goto error;
+	sd = i2c_get_clientdata(client);
+
+	/* Register with the v4l2_device which increases the module's
+	   use count as well. */
+	if (v4l2_device_register_subdev(v4l2_dev, sd))
+		sd = NULL;
+	/* Decrease the module use count to match the first try_module_get. */
+	module_put(client->driver->driver.owner);
+
+	if (sd) {
+		/* We return errors from v4l2_subdev_call only if we have the
+		   callback as the .s_config is not mandatory */
+		int err = v4l2_subdev_call(sd, core, s_config,
+				info->irq, info->platform_data);
+
+		if (err && err != -ENOIOCTLCMD) {
+			v4l2_device_unregister_subdev(sd);
+			sd = NULL;
+		}
+	}
+
+error:
+	/* If we have a client but no subdev, then something went wrong and
+	   we must unregister the client. */
+	if (client && sd == NULL)
+		i2c_unregister_device(client);
+	return sd;
+}
+EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
+
+struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
+		struct i2c_adapter *adapter,
+		const char *module_name, const char *client_type,
+		int irq, void *platform_data,
+		u8 addr, const unsigned short *probe_addrs)
+{
+	struct i2c_board_info info;
+
+	/* Setup the i2c board info with the device type and
+	   the device address. */
+	memset(&info, 0, sizeof(info));
+	strlcpy(info.type, client_type, sizeof(info.type));
+	info.addr = addr;
+	info.irq = irq;
+	info.platform_data = platform_data;
+
+	return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name,
+			&info, probe_addrs);
+}
+EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg);
+
 /* Return i2c client address of v4l2_subdev. */
 unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
 {
@@ -897,8 +1003,7 @@
 	};
 	static const unsigned short tv_addrs[] = {
 		0x42, 0x43, 0x4a, 0x4b,		/* tda8290 */
-		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+		0x60, 0x61, 0x62, 0x63, 0x64,
 		I2C_CLIENT_END
 	};
 
@@ -916,4 +1021,78 @@
 }
 EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
 
-#endif
+#endif /* defined(CONFIG_I2C) */
+
+/* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
+ * and max don't have to be aligned, but there must be at least one valid
+ * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
+ * of 16 between 17 and 31.  */
+static unsigned int clamp_align(unsigned int x, unsigned int min,
+				unsigned int max, unsigned int align)
+{
+	/* Bits that must be zero to be aligned */
+	unsigned int mask = ~((1 << align) - 1);
+
+	/* Round to nearest aligned value */
+	if (align)
+		x = (x + (1 << (align - 1))) & mask;
+
+	/* Clamp to aligned value of min and max */
+	if (x < min)
+		x = (min + ~mask) & mask;
+	else if (x > max)
+		x = max & mask;
+
+	return x;
+}
+
+/* Bound an image to have a width between wmin and wmax, and height between
+ * hmin and hmax, inclusive.  Additionally, the width will be a multiple of
+ * 2^walign, the height will be a multiple of 2^halign, and the overall size
+ * (width*height) will be a multiple of 2^salign.  The image may be shrunk
+ * or enlarged to fit the alignment constraints.
+ *
+ * The width or height maximum must not be smaller than the corresponding
+ * minimum.  The alignments must not be so high there are no possible image
+ * sizes within the allowed bounds.  wmin and hmin must be at least 1
+ * (don't use 0).  If you don't care about a certain alignment, specify 0,
+ * as 2^0 is 1 and one byte alignment is equivalent to no alignment.  If
+ * you only want to adjust downward, specify a maximum that's the same as
+ * the initial value.
+ */
+void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
+			   unsigned int walign,
+			   u32 *h, unsigned int hmin, unsigned int hmax,
+			   unsigned int halign, unsigned int salign)
+{
+	*w = clamp_align(*w, wmin, wmax, walign);
+	*h = clamp_align(*h, hmin, hmax, halign);
+
+	/* Usually we don't need to align the size and are done now. */
+	if (!salign)
+		return;
+
+	/* How much alignment do we have? */
+	walign = __ffs(*w);
+	halign = __ffs(*h);
+	/* Enough to satisfy the image alignment? */
+	if (walign + halign < salign) {
+		/* Max walign where there is still a valid width */
+		unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
+		/* Max halign where there is still a valid height */
+		unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
+
+		/* up the smaller alignment until we have enough */
+		do {
+			if (halign >= hmaxa ||
+			    (walign <= halign && walign < wmaxa)) {
+				*w = clamp_align(*w, wmin, wmax, walign + 1);
+				walign = __ffs(*w);
+			} else {
+				*h = clamp_align(*h, hmin, hmax, halign + 1);
+				halign = __ffs(*h);
+			}
+		} while (halign + walign < salign);
+	}
+}
+EXPORT_SYMBOL_GPL(v4l_bound_align_image);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/v4l2-dev.c linux-libre-2.6.31-gnu/drivers/media/video/v4l2-dev.c
--- linux-libre-2.6.30-gnu/drivers/media/video/v4l2-dev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/v4l2-dev.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/v4l2-device.c linux-libre-2.6.31-gnu/drivers/media/video/v4l2-device.c
--- linux-libre-2.6.30-gnu/drivers/media/video/v4l2-device.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/v4l2-device.c	2009-09-09 18:13:59.000000000 -0400
@@ -49,6 +49,22 @@
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register);
 
+int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
+						atomic_t *instance)
+{
+	int num = atomic_inc_return(instance) - 1;
+	int len = strlen(basename);
+
+	if (basename[len - 1] >= '0' && basename[len - 1] <= '9')
+		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
+				"%s-%d", basename, num);
+	else
+		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
+				"%s%d", basename, num);
+	return num;
+}
+EXPORT_SYMBOL_GPL(v4l2_device_set_name);
+
 void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
 {
 	if (v4l2_dev->dev) {
@@ -67,8 +83,21 @@
 	v4l2_device_disconnect(v4l2_dev);
 
 	/* Unregister subdevs */
-	list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list)
+	list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
 		v4l2_device_unregister_subdev(sd);
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+		if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
+			struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+			/* We need to unregister the i2c client explicitly.
+			   We cannot rely on i2c_del_adapter to always
+			   unregister clients for us, since if the i2c bus
+			   is a platform bus, then it is never deleted. */
+			if (client)
+				i2c_unregister_device(client);
+		}
+#endif
+	}
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister);
 
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/v4l2-ioctl.c linux-libre-2.6.31-gnu/drivers/media/video/v4l2-ioctl.c
--- linux-libre-2.6.30-gnu/drivers/media/video/v4l2-ioctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/v4l2-ioctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -1081,8 +1081,10 @@
 		/* Calls the specific handler */
 		if (ops->vidioc_g_std)
 			ret = ops->vidioc_g_std(file, fh, id);
-		else
+		else if (vfd->current_norm)
 			*id = vfd->current_norm;
+		else
+			ret = -EINVAL;
 
 		if (!ret)
 			dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
@@ -1553,12 +1555,19 @@
 				break;
 			ret = ops->vidioc_g_parm(file, fh, p);
 		} else {
+			v4l2_std_id std = vfd->current_norm;
+
 			if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 				return -EINVAL;
 
-			v4l2_video_std_frame_period(vfd->current_norm,
-						    &p->parm.capture.timeperframe);
 			ret = 0;
+			if (ops->vidioc_g_std)
+				ret = ops->vidioc_g_std(file, fh, &std);
+			else if (std == 0)
+				ret = -EINVAL;
+			if (ret == 0)
+				v4l2_video_std_frame_period(std,
+						    &p->parm.capture.timeperframe);
 		}
 
 		dbgarg(cmd, "type=%d\n", p->type);
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/videobuf-core.c linux-libre-2.6.31-gnu/drivers/media/video/videobuf-core.c
--- linux-libre-2.6.30-gnu/drivers/media/video/videobuf-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/videobuf-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -118,6 +118,7 @@
 			 void *priv,
 			 struct videobuf_qtype_ops *int_ops)
 {
+	BUG_ON(!q);
 	memset(q, 0, sizeof(*q));
 	q->irqlock   = irqlock;
 	q->dev       = dev;
@@ -439,6 +440,7 @@
 	}
 
 	req->count = retval;
+	retval = 0;
 
  done:
 	mutex_unlock(&q->vb_lock);
@@ -454,7 +456,7 @@
 		dprintk(1, "querybuf: Wrong type.\n");
 		goto done;
 	}
-	if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) {
+	if (unlikely(b->index >= VIDEO_MAX_FRAME)) {
 		dprintk(1, "querybuf: index out of range.\n");
 		goto done;
 	}
@@ -495,7 +497,7 @@
 		dprintk(1, "qbuf: Wrong type.\n");
 		goto done;
 	}
-	if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
+	if (b->index >= VIDEO_MAX_FRAME) {
 		dprintk(1, "qbuf: index out of range.\n");
 		goto done;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/videobuf-dma-contig.c linux-libre-2.6.31-gnu/drivers/media/video/videobuf-dma-contig.c
--- linux-libre-2.6.30-gnu/drivers/media/video/videobuf-dma-contig.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/videobuf-dma-contig.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 #include <linux/dma-mapping.h>
 #include <media/videobuf-dma-contig.h>
 
@@ -25,6 +26,7 @@
 	void *vaddr;
 	dma_addr_t dma_handle;
 	unsigned long size;
+	int is_userptr;
 };
 
 #define MAGIC_DC_MEM 0x0733ac61
@@ -108,6 +110,82 @@
 	.close    = videobuf_vm_close,
 };
 
+/**
+ * videobuf_dma_contig_user_put() - reset pointer to user space buffer
+ * @mem: per-buffer private videobuf-dma-contig data
+ *
+ * This function resets the user space pointer
+ */
+static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory *mem)
+{
+	mem->is_userptr = 0;
+	mem->dma_handle = 0;
+	mem->size = 0;
+}
+
+/**
+ * videobuf_dma_contig_user_get() - setup user space memory pointer
+ * @mem: per-buffer private videobuf-dma-contig data
+ * @vb: video buffer to map
+ *
+ * This function validates and sets up a pointer to user space memory.
+ * Only physically contiguous pfn-mapped memory is accepted.
+ *
+ * Returns 0 if successful.
+ */
+static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem,
+					struct videobuf_buffer *vb)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long prev_pfn, this_pfn;
+	unsigned long pages_done, user_address;
+	int ret;
+
+	mem->size = PAGE_ALIGN(vb->size);
+	mem->is_userptr = 0;
+	ret = -EINVAL;
+
+	down_read(&mm->mmap_sem);
+
+	vma = find_vma(mm, vb->baddr);
+	if (!vma)
+		goto out_up;
+
+	if ((vb->baddr + mem->size) > vma->vm_end)
+		goto out_up;
+
+	pages_done = 0;
+	prev_pfn = 0; /* kill warning */
+	user_address = vb->baddr;
+
+	while (pages_done < (mem->size >> PAGE_SHIFT)) {
+		ret = follow_pfn(vma, user_address, &this_pfn);
+		if (ret)
+			break;
+
+		if (pages_done == 0)
+			mem->dma_handle = this_pfn << PAGE_SHIFT;
+		else if (this_pfn != (prev_pfn + 1))
+			ret = -EFAULT;
+
+		if (ret)
+			break;
+
+		prev_pfn = this_pfn;
+		user_address += PAGE_SIZE;
+		pages_done++;
+	}
+
+	if (!ret)
+		mem->is_userptr = 1;
+
+ out_up:
+	up_read(&current->mm->mmap_sem);
+
+	return ret;
+}
+
 static void *__videobuf_alloc(size_t size)
 {
 	struct videobuf_dma_contig_memory *mem;
@@ -154,12 +232,11 @@
 	case V4L2_MEMORY_USERPTR:
 		dev_dbg(q->dev, "%s memory method USERPTR\n", __func__);
 
-		/* The only USERPTR currently supported is the one needed for
-		   read() method.
-		 */
+		/* handle pointer from user space */
 		if (vb->baddr)
-			return -EINVAL;
+			return videobuf_dma_contig_user_get(mem, vb);
 
+		/* allocate memory for the read() method */
 		mem->size = PAGE_ALIGN(vb->size);
 		mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
 						&mem->dma_handle, GFP_KERNEL);
@@ -182,19 +259,6 @@
 	return 0;
 }
 
-static int __videobuf_sync(struct videobuf_queue *q,
-			   struct videobuf_buffer *buf)
-{
-	struct videobuf_dma_contig_memory *mem = buf->priv;
-
-	BUG_ON(!mem);
-	MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
-
-	dma_sync_single_for_cpu(q->dev, mem->dma_handle, mem->size,
-				DMA_FROM_DEVICE);
-	return 0;
-}
-
 static int __videobuf_mmap_free(struct videobuf_queue *q)
 {
 	unsigned int i;
@@ -356,7 +420,6 @@
 
 	.alloc        = __videobuf_alloc,
 	.iolock       = __videobuf_iolock,
-	.sync         = __videobuf_sync,
 	.mmap_free    = __videobuf_mmap_free,
 	.mmap_mapper  = __videobuf_mmap_mapper,
 	.video_copy_to_user = __videobuf_copy_to_user,
@@ -400,7 +463,7 @@
 	   So, it should free memory only if the memory were allocated for
 	   read() operation.
 	 */
-	if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
+	if (buf->memory != V4L2_MEMORY_USERPTR)
 		return;
 
 	if (!mem)
@@ -408,6 +471,13 @@
 
 	MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
 
+	/* handle user space pointer case */
+	if (buf->baddr) {
+		videobuf_dma_contig_user_put(mem);
+		return;
+	}
+
+	/* read() method */
 	dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
 	mem->vaddr = NULL;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/videobuf-dma-sg.c linux-libre-2.6.31-gnu/drivers/media/video/videobuf-dma-sg.c
--- linux-libre-2.6.30-gnu/drivers/media/video/videobuf-dma-sg.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/videobuf-dma-sg.c	2009-09-09 18:13:59.000000000 -0400
@@ -58,9 +58,10 @@
 	struct page *pg;
 	int i;
 
-	sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
+	sglist = vmalloc(nr_pages * sizeof(*sglist));
 	if (NULL == sglist)
 		return NULL;
+	memset(sglist, 0, nr_pages * sizeof(*sglist));
 	sg_init_table(sglist, nr_pages);
 	for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
 		pg = vmalloc_to_page(virt);
@@ -72,7 +73,7 @@
 	return sglist;
 
  err:
-	kfree(sglist);
+	vfree(sglist);
 	return NULL;
 }
 
@@ -84,7 +85,7 @@
 
 	if (NULL == pages[0])
 		return NULL;
-	sglist = kmalloc(nr_pages * sizeof(*sglist), GFP_KERNEL);
+	sglist = vmalloc(nr_pages * sizeof(*sglist));
 	if (NULL == sglist)
 		return NULL;
 	sg_init_table(sglist, nr_pages);
@@ -104,12 +105,12 @@
 
  nopage:
 	dprintk(2,"sgl: oops - no page\n");
-	kfree(sglist);
+	vfree(sglist);
 	return NULL;
 
  highmem:
 	dprintk(2,"sgl: oops - highmem page\n");
-	kfree(sglist);
+	vfree(sglist);
 	return NULL;
 }
 
@@ -230,7 +231,7 @@
 						(dma->vmalloc,dma->nr_pages);
 	}
 	if (dma->bus_addr) {
-		dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
+		dma->sglist = vmalloc(sizeof(*dma->sglist));
 		if (NULL != dma->sglist) {
 			dma->sglen  = 1;
 			sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK;
@@ -248,10 +249,10 @@
 		if (0 == dma->sglen) {
 			printk(KERN_WARNING
 			       "%s: videobuf_map_sg failed\n",__func__);
-			kfree(dma->sglist);
+			vfree(dma->sglist);
 			dma->sglist = NULL;
 			dma->sglen = 0;
-			return -EIO;
+			return -ENOMEM;
 		}
 	}
 	return 0;
@@ -274,7 +275,7 @@
 
 	dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
 
-	kfree(dma->sglist);
+	vfree(dma->sglist);
 	dma->sglist = NULL;
 	dma->sglen = 0;
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/vino.c linux-libre-2.6.31-gnu/drivers/media/video/vino.c
--- linux-libre-2.6.30-gnu/drivers/media/video/vino.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/vino.c	2009-09-09 18:13:59.000000000 -0400
@@ -868,9 +868,9 @@
 	dprintk("vino_sync_buffer():\n");
 
 	for (i = 0; i < fb->desc_table.page_count; i++)
-		dma_sync_single(NULL,
-				fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
-				PAGE_SIZE, DMA_FROM_DEVICE);
+		dma_sync_single_for_cpu(NULL,
+					fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+					PAGE_SIZE, DMA_FROM_DEVICE);
 }
 
 /* Framebuffer fifo functions (need to be locked externally) */
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/vivi.c linux-libre-2.6.31-gnu/drivers/media/video/vivi.c
--- linux-libre-2.6.30-gnu/drivers/media/video/vivi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/vivi.c	2009-09-09 18:13:59.000000000 -0400
@@ -343,6 +343,53 @@
 #define TO_U(r, g, b) \
 	(((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
 
+/* precalculate color bar values to speed up rendering */
+static void precalculate_bars(struct vivi_fh *fh)
+{
+	struct vivi_dev *dev = fh->dev;
+	unsigned char r, g, b;
+	int k, is_yuv;
+
+	fh->input = dev->input;
+
+	for (k = 0; k < 8; k++) {
+		r = bars[fh->input].bar[k][0];
+		g = bars[fh->input].bar[k][1];
+		b = bars[fh->input].bar[k][2];
+		is_yuv = 0;
+
+		switch (fh->fmt->fourcc) {
+		case V4L2_PIX_FMT_YUYV:
+		case V4L2_PIX_FMT_UYVY:
+			is_yuv = 1;
+			break;
+		case V4L2_PIX_FMT_RGB565:
+		case V4L2_PIX_FMT_RGB565X:
+			r >>= 3;
+			g >>= 2;
+			b >>= 3;
+			break;
+		case V4L2_PIX_FMT_RGB555:
+		case V4L2_PIX_FMT_RGB555X:
+			r >>= 3;
+			g >>= 3;
+			b >>= 3;
+			break;
+		}
+
+		if (is_yuv) {
+			fh->bars[k][0] = TO_Y(r, g, b);	/* Luma */
+			fh->bars[k][1] = TO_U(r, g, b);	/* Cb */
+			fh->bars[k][2] = TO_V(r, g, b);	/* Cr */
+		} else {
+			fh->bars[k][0] = r;
+			fh->bars[k][1] = g;
+			fh->bars[k][2] = b;
+		}
+	}
+
+}
+
 #define TSTAMP_MIN_Y	24
 #define TSTAMP_MAX_Y	(TSTAMP_MIN_Y + 15)
 #define TSTAMP_INPUT_X	10
@@ -755,6 +802,8 @@
 	buf->vb.height = fh->height;
 	buf->vb.field  = field;
 
+	precalculate_bars(fh);
+
 	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
 		rc = videobuf_iolock(vq, &buf->vb, NULL);
 		if (rc < 0)
@@ -883,15 +932,8 @@
 	maxh  = norm_maxh();
 
 	f->fmt.pix.field = field;
-	if (f->fmt.pix.height < 32)
-		f->fmt.pix.height = 32;
-	if (f->fmt.pix.height > maxh)
-		f->fmt.pix.height = maxh;
-	if (f->fmt.pix.width < 48)
-		f->fmt.pix.width = 48;
-	if (f->fmt.pix.width > maxw)
-		f->fmt.pix.width = maxw;
-	f->fmt.pix.width &= ~0x03;
+	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+			      &f->fmt.pix.height, 32, maxh, 0, 0);
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage =
@@ -900,53 +942,6 @@
 	return 0;
 }
 
-/* precalculate color bar values to speed up rendering */
-static void precalculate_bars(struct vivi_fh *fh)
-{
-	struct vivi_dev *dev = fh->dev;
-	unsigned char r, g, b;
-	int k, is_yuv;
-
-	fh->input = dev->input;
-
-	for (k = 0; k < 8; k++) {
-		r = bars[fh->input].bar[k][0];
-		g = bars[fh->input].bar[k][1];
-		b = bars[fh->input].bar[k][2];
-		is_yuv = 0;
-
-		switch (fh->fmt->fourcc) {
-		case V4L2_PIX_FMT_YUYV:
-		case V4L2_PIX_FMT_UYVY:
-			is_yuv = 1;
-			break;
-		case V4L2_PIX_FMT_RGB565:
-		case V4L2_PIX_FMT_RGB565X:
-			r >>= 3;
-			g >>= 2;
-			b >>= 3;
-			break;
-		case V4L2_PIX_FMT_RGB555:
-		case V4L2_PIX_FMT_RGB555X:
-			r >>= 3;
-			g >>= 3;
-			b >>= 3;
-			break;
-		}
-
-		if (is_yuv) {
-			fh->bars[k][0] = TO_Y(r, g, b);	/* Luma */
-			fh->bars[k][1] = TO_U(r, g, b);	/* Cb */
-			fh->bars[k][2] = TO_V(r, g, b);	/* Cr */
-		} else {
-			fh->bars[k][0] = r;
-			fh->bars[k][1] = g;
-			fh->bars[k][2] = b;
-		}
-	}
-
-}
-
 /*FIXME: This seems to be generic enough to be at videodev2 */
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 					struct v4l2_format *f)
@@ -972,8 +967,6 @@
 	fh->vb_vidq.field = f->fmt.pix.field;
 	fh->type          = f->type;
 
-	precalculate_bars(fh);
-
 	ret = 0;
 out:
 	mutex_unlock(&q->vb_lock);
@@ -1364,6 +1357,7 @@
 		goto unreg_dev;
 
 	*vfd = vivi_template;
+	vfd->debug = debug;
 
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
 	if (ret < 0)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/w9968cf.c linux-libre-2.6.31-gnu/drivers/media/video/w9968cf.c
--- linux-libre-2.6.30-gnu/drivers/media/video/w9968cf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/w9968cf.c	2009-09-09 18:13:59.000000000 -0400
@@ -460,7 +460,7 @@
 static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
 static int w9968cf_postprocess_frame(struct w9968cf_device*,
 				     struct w9968cf_frame_t*);
-static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h);
+static int w9968cf_adjust_window_size(struct w9968cf_device*, u32 *w, u32 *h);
 static void w9968cf_init_framelist(struct w9968cf_device*);
 static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num);
 static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**);
@@ -1763,8 +1763,7 @@
 	#define UNSC(x) ((x) >> 10)
 
 	/* Make sure we are using a supported resolution */
-	if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
-					      (u16*)&win.height)))
+	if ((err = w9968cf_adjust_window_size(cam, &win.width, &win.height)))
 		goto error;
 
 	/* Scaling factors */
@@ -1914,12 +1913,9 @@
   Return 0 on success, -1 otherwise.
   --------------------------------------------------------------------------*/
 static int
-w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height)
+w9968cf_adjust_window_size(struct w9968cf_device *cam, u32 *width, u32 *height)
 {
-	u16 maxw, maxh;
-
-	if ((*width < cam->minwidth) || (*height < cam->minheight))
-		return -ERANGE;
+	unsigned int maxw, maxh, align;
 
 	maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
 	       w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
@@ -1927,16 +1923,10 @@
 	maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
 	       w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight)
 			   : cam->maxheight;
+	align = (cam->vpp_flag & VPP_DECOMPRESSION) ? 4 : 0;
 
-	if (*width > maxw)
-		*width = maxw;
-	if (*height > maxh)
-		*height = maxh;
-
-	if (cam->vpp_flag & VPP_DECOMPRESSION) {
-		*width  &= ~15L; /* multiple of 16 */
-		*height &= ~15L;
-	}
+	v4l_bound_align_image(width, cam->minwidth, maxw, align,
+			      height, cam->minheight, maxh, align, 0);
 
 	PDBGG("Window size adjusted w=%u, h=%u ", *width, *height)
 
@@ -3043,8 +3033,8 @@
 		if (win.clipcount != 0 || win.flags != 0)
 			return -EINVAL;
 
-		if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
-						      (u16*)&win.height))) {
+		if ((err = w9968cf_adjust_window_size(cam, &win.width,
+						      &win.height))) {
 			DBG(4, "Resolution not supported (%ux%u). "
 			       "VIDIOCSWIN failed", win.width, win.height)
 			return err;
@@ -3116,6 +3106,7 @@
 	{
 		struct video_mmap mmap;
 		struct w9968cf_frame_t* fr;
+		u32 w, h;
 		int err = 0;
 
 		if (copy_from_user(&mmap, arg, sizeof(mmap)))
@@ -3164,8 +3155,10 @@
 		   }
 		}
 
-		if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width,
-						      (u16*)&mmap.height))) {
+		w = mmap.width; h = mmap.height;
+		err = w9968cf_adjust_window_size(cam, &w, &h);
+		mmap.width = w; mmap.height = h;
+		if (err) {
 			DBG(4, "Resolution not supported (%dx%d). "
 			       "VIDIOCMCAPTURE failed",
 			    mmap.width, mmap.height)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/zoran/zoran_card.c linux-libre-2.6.31-gnu/drivers/media/video/zoran/zoran_card.c
--- linux-libre-2.6.30-gnu/drivers/media/video/zoran/zoran_card.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/zoran/zoran_card.c	2009-09-09 18:13:59.000000000 -0400
@@ -1022,7 +1022,7 @@
 	zr->vbuf_bytesperline = 0;
 
 	/* Avoid nonsense settings from user for default input/norm */
-	if (default_norm < 0 && default_norm > 2)
+	if (default_norm < 0 || default_norm > 2)
 		default_norm = 0;
 	if (default_norm == 0) {
 		zr->norm = V4L2_STD_PAL;
@@ -1477,7 +1477,7 @@
 	.name = "zr36067",
 	.id_table = zr36067_pci_tbl,
 	.probe = zoran_probe,
-	.remove = zoran_remove,
+	.remove = __devexit_p(zoran_remove),
 };
 
 static int __init zoran_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/zoran/zoran_driver.c linux-libre-2.6.31-gnu/drivers/media/video/zoran/zoran_driver.c
--- linux-libre-2.6.30-gnu/drivers/media/video/zoran/zoran_driver.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/zoran/zoran_driver.c	2009-09-09 18:13:59.000000000 -0400
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
@@ -2088,16 +2089,10 @@
 		return -EINVAL;
 	}
 
-	bpp = (zoran_formats[i].depth + 7) / 8;
-	fmt->fmt.pix.width &= ~((bpp == 2) ? 1 : 3);
-	if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
-		fmt->fmt.pix.width = BUZ_MAX_WIDTH;
-	if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
-		fmt->fmt.pix.width = BUZ_MIN_WIDTH;
-	if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
-		fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
-	if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
-		fmt->fmt.pix.height = BUZ_MIN_HEIGHT;
+	bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
+	v4l_bound_align_image(
+		&fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2,
+		&fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0);
 	mutex_unlock(&zr->resource_lock);
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/media/video/zr364xx.c linux-libre-2.6.31-gnu/drivers/media/video/zr364xx.c
--- linux-libre-2.6.30-gnu/drivers/media/video/zr364xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/media/video/zr364xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -695,7 +695,7 @@
 	for (i = 0; i < 2; i++) {
 		err =
 		    send_control_msg(udev, 1, init[cam->method][i].value,
-				     0, init[i][cam->method].bytes,
+				     0, init[cam->method][i].bytes,
 				     init[cam->method][i].size);
 		if (err < 0) {
 			dev_err(&udev->dev, "error during release sequence\n");
@@ -882,9 +882,11 @@
 		video_unregister_device(cam->vdev);
 	cam->vdev = NULL;
 	kfree(cam->buffer);
-	if (cam->framebuf)
-		vfree(cam->framebuf);
+	cam->buffer = NULL;
+	vfree(cam->framebuf);
+	cam->framebuf = NULL;
 	kfree(cam);
+	cam = NULL;
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/memstick/core/mspro_block.c linux-libre-2.6.31-gnu/drivers/memstick/core/mspro_block.c
--- linux-libre-2.6.30-gnu/drivers/memstick/core/mspro_block.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/memstick/core/mspro_block.c	2009-09-09 18:13:59.000000000 -0400
@@ -672,15 +672,14 @@
 					       msb->req_sg);
 
 		if (!msb->seg_count) {
-			chunk = __blk_end_request(msb->block_req, -ENOMEM,
-					blk_rq_cur_bytes(msb->block_req));
+			chunk = __blk_end_request_cur(msb->block_req, -ENOMEM);
 			continue;
 		}
 
-		t_sec = msb->block_req->sector << 9;
+		t_sec = blk_rq_pos(msb->block_req) << 9;
 		sector_div(t_sec, msb->page_size);
 
-		count = msb->block_req->nr_sectors << 9;
+		count = blk_rq_bytes(msb->block_req);
 		count /= msb->page_size;
 
 		param.system = msb->system;
@@ -705,8 +704,8 @@
 		return 0;
 	}
 
-	dev_dbg(&card->dev, "elv_next\n");
-	msb->block_req = elv_next_request(msb->queue);
+	dev_dbg(&card->dev, "blk_fetch\n");
+	msb->block_req = blk_fetch_request(msb->queue);
 	if (!msb->block_req) {
 		dev_dbg(&card->dev, "issue end\n");
 		return -EAGAIN;
@@ -745,7 +744,7 @@
 					t_len *= msb->page_size;
 			}
 		} else
-			t_len = msb->block_req->nr_sectors << 9;
+			t_len = blk_rq_bytes(msb->block_req);
 
 		dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error);
 
@@ -825,8 +824,8 @@
 		return;
 
 	if (msb->eject) {
-		while ((req = elv_next_request(q)) != NULL)
-			__blk_end_request(req, -ENODEV, blk_rq_bytes(req));
+		while ((req = blk_fetch_request(q)) != NULL)
+			__blk_end_request_all(req, -ENODEV);
 
 		return;
 	}
@@ -1243,7 +1242,7 @@
 
 	sprintf(msb->disk->disk_name, "mspblk%d", disk_id);
 
-	blk_queue_hardsect_size(msb->queue, msb->page_size);
+	blk_queue_logical_block_size(msb->queue, msb->page_size);
 
 	capacity = be16_to_cpu(sys_info->user_block_count);
 	capacity *= be16_to_cpu(sys_info->block_size);
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/lsi/mpi_history.txt linux-libre-2.6.31-gnu/drivers/message/fusion/lsi/mpi_history.txt
--- linux-libre-2.6.30-gnu/drivers/message/fusion/lsi/mpi_history.txt	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/lsi/mpi_history.txt	2009-09-09 18:13:59.000000000 -0400
@@ -130,7 +130,7 @@
  *  08-08-01  01.02.01  Original release for v1.2 work.
  *                      New format for FWVersion and ProductId in
  *                      MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
- *  08-31-01  01.02.02  Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
+ *  08-31-01  01.02.02  Added event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
  *                      related structure and defines.
  *                      Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
  *                      Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
@@ -190,7 +190,7 @@
  *  10-11-06  01.05.12  Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
  *                      Added MaxInitiators field to PortFacts reply.
  *                      Added SAS Device Status Change ReasonCode for
- *                      asynchronous notificaiton.
+ *                      asynchronous notification.
  *                      Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
  *                      data structure.
  *                      Added new ImageType values for FWDownload and FWUpload
@@ -623,7 +623,7 @@
  *  11-02-00  01.01.01  Original release for post 1.0 work
  *  12-04-00  01.01.02  Added messages for Common Transport Send and
  *                      Primitive Send.
- *  01-09-01  01.01.03  Modifed some of the new flags to have an MPI prefix
+ *  01-09-01  01.01.03  Modified some of the new flags to have an MPI prefix
  *                      and modified the FcPrimitiveSend flags.
  *  01-25-01  01.01.04  Move InitiatorIndex in LinkServiceRsp reply to a larger
  *                      field.
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptbase.c linux-libre-2.6.31-gnu/drivers/message/fusion/mptbase.c
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptbase.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptbase.c	2009-09-09 18:13:59.000000000 -0400
@@ -146,7 +146,6 @@
 static MPT_RESETHANDLER		 MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 static struct mpt_pci_driver 	*MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 
-static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
 
 /*
  *  Driver Callback Index's
@@ -159,7 +158,8 @@
  *  Forward protos...
  */
 static irqreturn_t mpt_interrupt(int irq, void *bus_id);
-static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
+static int	mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
+		MPT_FRAME_HDR *reply);
 static int	mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
 			u32 *req, int replyBytes, u16 *u16reply, int maxwait,
 			int sleepFlag);
@@ -190,9 +190,9 @@
 static int	mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
 static void 	mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
 static void 	mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
-static void	mpt_timer_expired(unsigned long data);
 static void	mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
-static int	SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
+static int	SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch,
+	int sleepFlag);
 static int	SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
 static int	mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
 static int	mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
@@ -207,8 +207,8 @@
 #endif
 static void	mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
 
-//int		mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
-static int	ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
+static int	ProcessEventNotification(MPT_ADAPTER *ioc,
+		EventNotificationReply_t *evReply, int *evHandlers);
 static void	mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
 static void	mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
@@ -277,6 +277,56 @@
 }
 
 /**
+ * mpt_is_discovery_complete - determine if discovery has completed
+ * @ioc: per adatper instance
+ *
+ * Returns 1 when discovery completed, else zero.
+ */
+static int
+mpt_is_discovery_complete(MPT_ADAPTER *ioc)
+{
+	ConfigExtendedPageHeader_t hdr;
+	CONFIGPARMS cfg;
+	SasIOUnitPage0_t *buffer;
+	dma_addr_t dma_handle;
+	int rc = 0;
+
+	memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
+	memset(&cfg, 0, sizeof(CONFIGPARMS));
+	hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
+	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+	cfg.cfghdr.ehdr = &hdr;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if ((mpt_config(ioc, &cfg)))
+		goto out;
+	if (!hdr.ExtPageLength)
+		goto out;
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+	    &dma_handle);
+	if (!buffer)
+		goto out;
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+	if ((mpt_config(ioc, &cfg)))
+		goto out_free_consistent;
+
+	if (!(buffer->PhyData[0].PortFlags &
+	    MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS))
+		rc = 1;
+
+ out_free_consistent:
+	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
+	    buffer, dma_handle);
+ out:
+	return rc;
+}
+
+/**
  *	mpt_fault_reset_work - work performed on workq after ioc fault
  *	@work: input argument, used to derive ioc
  *
@@ -290,7 +340,7 @@
 	int		 rc;
 	unsigned long	 flags;
 
-	if (ioc->diagPending || !ioc->active)
+	if (ioc->ioc_reset_in_progress || !ioc->active)
 		goto out;
 
 	ioc_raw_state = mpt_GetIocState(ioc, 0);
@@ -307,6 +357,12 @@
 			printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
 			    "reset (%04xh)\n", ioc->name, ioc_raw_state &
 			    MPI_DOORBELL_DATA_MASK);
+	} else if (ioc->bus_type == SAS && ioc->sas_discovery_quiesce_io) {
+		if ((mpt_is_discovery_complete(ioc))) {
+			devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "clearing "
+			    "discovery_quiesce_io flag\n", ioc->name));
+			ioc->sas_discovery_quiesce_io = 0;
+		}
 	}
 
  out:
@@ -317,11 +373,11 @@
 		ioc = ioc->alt_ioc;
 
 	/* rearm the timer */
-	spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
 	if (ioc->reset_work_q)
 		queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
 			msecs_to_jiffies(MPT_POLLING_INTERVAL));
-	spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 }
 
 
@@ -501,9 +557,9 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mpt_base_reply - MPT base driver's callback routine
+ *	mptbase_reply - MPT base driver's callback routine
  *	@ioc: Pointer to MPT_ADAPTER structure
- *	@mf: Pointer to original MPT request frame
+ *	@req: Pointer to original MPT request frame
  *	@reply: Pointer to MPT reply frame (NULL if TurboReply)
  *
  *	MPT base driver's callback routine; all base driver
@@ -514,122 +570,49 @@
  *	should be freed, or 0 if it shouldn't.
  */
 static int
-mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
+mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
 {
+	EventNotificationReply_t *pEventReply;
+	u8 event;
+	int evHandlers;
 	int freereq = 1;
-	u8 func;
-
-	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name));
-#ifdef CONFIG_FUSION_LOGGING
-	if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
-			!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
-		dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n",
-		    ioc->name, mf));
-		DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf);
-	}
-#endif
-
-	func = reply->u.hdr.Function;
-	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n",
-			ioc->name, func));
 
-	if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
-		EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
-		int evHandlers = 0;
-		int results;
-
-		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
-		if (results != evHandlers) {
-			/* CHECKME! Any special handling needed here? */
-			devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
-					ioc->name, evHandlers, results));
-		}
-
-		/*
-		 *	Hmmm...  It seems that EventNotificationReply is an exception
-		 *	to the rule of one reply per request.
-		 */
-		if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
+	switch (reply->u.hdr.Function) {
+	case MPI_FUNCTION_EVENT_NOTIFICATION:
+		pEventReply = (EventNotificationReply_t *)reply;
+		evHandlers = 0;
+		ProcessEventNotification(ioc, pEventReply, &evHandlers);
+		event = le32_to_cpu(pEventReply->Event) & 0xFF;
+		if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)
 			freereq = 0;
-		} else {
-			devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
-				ioc->name, pEvReply));
-		}
-
-#ifdef CONFIG_PROC_FS
-//		LogEvent(ioc, pEvReply);
-#endif
-
-	} else if (func == MPI_FUNCTION_EVENT_ACK) {
-		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n",
-				ioc->name));
-	} else if (func == MPI_FUNCTION_CONFIG) {
-		CONFIGPARMS *pCfg;
-		unsigned long flags;
-
-		dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n",
-				ioc->name, mf, reply));
-
-		pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
-
-		if (pCfg) {
-			/* disable timer and remove from linked list */
-			del_timer(&pCfg->timer);
-
-			spin_lock_irqsave(&ioc->FreeQlock, flags);
-			list_del(&pCfg->linkage);
-			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
-			/*
-			 *	If IOC Status is SUCCESS, save the header
-			 *	and set the status code to GOOD.
-			 */
-			pCfg->status = MPT_CONFIG_ERROR;
-			if (reply) {
-				ConfigReply_t	*pReply = (ConfigReply_t *)reply;
-				u16		 status;
-
-				status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-				dcprintk(ioc, printk(MYIOC_s_NOTE_FMT "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
-				     ioc->name, status, le32_to_cpu(pReply->IOCLogInfo)));
-
-				pCfg->status = status;
-				if (status == MPI_IOCSTATUS_SUCCESS) {
-					if ((pReply->Header.PageType &
-					    MPI_CONFIG_PAGETYPE_MASK) ==
-					    MPI_CONFIG_PAGETYPE_EXTENDED) {
-						pCfg->cfghdr.ehdr->ExtPageLength =
-						    le16_to_cpu(pReply->ExtPageLength);
-						pCfg->cfghdr.ehdr->ExtPageType =
-						    pReply->ExtPageType;
-					}
-					pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
-
-					/* If this is a regular header, save PageLength. */
-					/* LMP Do this better so not using a reserved field! */
-					pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
-					pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
-					pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
-				}
-			}
-
-			/*
-			 *	Wake up the original calling thread
-			 */
-			pCfg->wait_done = 1;
-			wake_up(&mpt_waitq);
+		if (event != MPI_EVENT_EVENT_CHANGE)
+			break;
+	case MPI_FUNCTION_CONFIG:
+	case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
+		ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
+		if (reply) {
+			ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+			memcpy(ioc->mptbase_cmds.reply, reply,
+			    min(MPT_DEFAULT_FRAME_SIZE,
+				4 * reply->u.reply.MsgLength));
 		}
-	} else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
-		/* we should be always getting a reply frame */
-		memcpy(ioc->persist_reply_frame, reply,
-		    min(MPT_DEFAULT_FRAME_SIZE,
-		    4*reply->u.reply.MsgLength));
-		del_timer(&ioc->persist_timer);
-		ioc->persist_wait_done = 1;
-		wake_up(&mpt_waitq);
-	} else {
-		printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
-				ioc->name, func);
+		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
+			complete(&ioc->mptbase_cmds.done);
+		} else
+			freereq = 0;
+		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF)
+			freereq = 1;
+		break;
+	case MPI_FUNCTION_EVENT_ACK:
+		devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "EventAck reply received\n", ioc->name));
+		break;
+	default:
+		printk(MYIOC_s_ERR_FMT
+		    "Unexpected msg function (=%02Xh) reply received!\n",
+		    ioc->name, reply->u.hdr.Function);
+		break;
 	}
 
 	/*
@@ -988,17 +971,21 @@
 
 	/*  Put Request back on FreeQ!  */
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
-	mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
+	if (cpu_to_le32(mf->u.frame.linkage.arg1) == 0xdeadbeaf)
+		goto out;
+	/* signature to know if this mf is freed */
+	mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf);
 	list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
 #ifdef MFCNT
 	ioc->mfcnt--;
 #endif
+ out:
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mpt_add_sge - Place a simple SGE at address pAddr.
+ *	mpt_add_sge - Place a simple 32 bit SGE at address pAddr.
  *	@pAddr: virtual address for SGE
  *	@flagslength: SGE flags and data transfer length
  *	@dma_addr: Physical address
@@ -1006,23 +993,116 @@
  *	This routine places a MPT request frame back on the MPT adapter's
  *	FreeQ.
  */
-void
-mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
+static void
+mpt_add_sge(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
 {
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
-		SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
-		u32 tmp = dma_addr & 0xFFFFFFFF;
+	SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
+	pSge->FlagsLength = cpu_to_le32(flagslength);
+	pSge->Address = cpu_to_le32(dma_addr);
+}
 
-		pSge->FlagsLength = cpu_to_le32(flagslength);
-		pSge->Address.Low = cpu_to_le32(tmp);
-		tmp = (u32) ((u64)dma_addr >> 32);
-		pSge->Address.High = cpu_to_le32(tmp);
+/**
+ *	mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr.
+ *	@pAddr: virtual address for SGE
+ *	@flagslength: SGE flags and data transfer length
+ *	@dma_addr: Physical address
+ *
+ *	This routine places a MPT request frame back on the MPT adapter's
+ *	FreeQ.
+ **/
+static void
+mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
+{
+	SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
+	pSge->Address.Low = cpu_to_le32
+			(lower_32_bits((unsigned long)(dma_addr)));
+	pSge->Address.High = cpu_to_le32
+			(upper_32_bits((unsigned long)dma_addr));
+	pSge->FlagsLength = cpu_to_le32
+			((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
+}
 
-	} else {
-		SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
-		pSge->FlagsLength = cpu_to_le32(flagslength);
-		pSge->Address = cpu_to_le32(dma_addr);
+/**
+ *	mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr (1078 workaround).
+ *	@pAddr: virtual address for SGE
+ *	@flagslength: SGE flags and data transfer length
+ *	@dma_addr: Physical address
+ *
+ *	This routine places a MPT request frame back on the MPT adapter's
+ *	FreeQ.
+ **/
+static void
+mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
+{
+	SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
+	u32 tmp;
+
+	pSge->Address.Low = cpu_to_le32
+			(lower_32_bits((unsigned long)(dma_addr)));
+	tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+
+	/*
+	 * 1078 errata workaround for the 36GB limitation
+	 */
+	if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32)  == 9) {
+		flagslength |=
+		    MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS);
+		tmp |= (1<<31);
+		if (mpt_debug_level & MPT_DEBUG_36GB_MEM)
+			printk(KERN_DEBUG "1078 P0M2 addressing for "
+			    "addr = 0x%llx len = %d\n",
+			    (unsigned long long)dma_addr,
+			    MPI_SGE_LENGTH(flagslength));
 	}
+
+	pSge->Address.High = cpu_to_le32(tmp);
+	pSge->FlagsLength = cpu_to_le32(
+		(flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_add_chain - Place a 32 bit chain SGE at address pAddr.
+ *	@pAddr: virtual address for SGE
+ *	@next: nextChainOffset value (u32's)
+ *	@length: length of next SGL segment
+ *	@dma_addr: Physical address
+ *
+ */
+static void
+mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
+{
+		SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
+		pChain->Length = cpu_to_le16(length);
+		pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
+		pChain->NextChainOffset = next;
+		pChain->Address = cpu_to_le32(dma_addr);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr.
+ *	@pAddr: virtual address for SGE
+ *	@next: nextChainOffset value (u32's)
+ *	@length: length of next SGL segment
+ *	@dma_addr: Physical address
+ *
+ */
+static void
+mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
+{
+		SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
+		u32 tmp = dma_addr & 0xFFFFFFFF;
+
+		pChain->Length = cpu_to_le16(length);
+		pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
+				 MPI_SGE_FLAGS_64_BIT_ADDRESSING);
+
+		pChain->NextChainOffset = next;
+
+		pChain->Address.Low = cpu_to_le32(tmp);
+		tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+		pChain->Address.High = cpu_to_le32(tmp);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1225,7 +1305,7 @@
 	}
 	flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
 	flags_length |= ioc->HostPageBuffer_sz;
-	mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
+	ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
 	ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
 
 return 0;
@@ -1534,21 +1614,42 @@
 
 	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
 
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
-	    && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
-		    ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
-		    ioc->name));
-	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
-	    && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
-		dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
-		    ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
-		    ioc->name));
+	if (sizeof(dma_addr_t) > 4) {
+		const uint64_t required_mask = dma_get_required_mask
+		    (&pdev->dev);
+		if (required_mask > DMA_BIT_MASK(32)
+			&& !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+			&& !pci_set_consistent_dma_mask(pdev,
+						 DMA_BIT_MASK(64))) {
+			ioc->dma_mask = DMA_BIT_MASK(64);
+			dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
+				": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
+				ioc->name));
+		} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
+			&& !pci_set_consistent_dma_mask(pdev,
+						DMA_BIT_MASK(32))) {
+			ioc->dma_mask = DMA_BIT_MASK(32);
+			dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
+				": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
+				ioc->name));
+		} else {
+			printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
+			    ioc->name, pci_name(pdev));
+			return r;
+		}
 	} else {
-		printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
-		    ioc->name, pci_name(pdev));
-		pci_release_selected_regions(pdev, ioc->bars);
-		return r;
+		if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
+			&& !pci_set_consistent_dma_mask(pdev,
+						DMA_BIT_MASK(32))) {
+			ioc->dma_mask = DMA_BIT_MASK(32);
+			dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
+				": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
+				ioc->name));
+		} else {
+			printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
+			    ioc->name, pci_name(pdev));
+			return r;
+		}
 	}
 
 	mem_phys = msize = 0;
@@ -1632,6 +1733,7 @@
 
 	ioc->id = mpt_ids++;
 	sprintf(ioc->name, "ioc%d", ioc->id);
+	dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n"));
 
 	/*
 	 * set initial debug level
@@ -1650,14 +1752,36 @@
 		return r;
 	}
 
+	/*
+	 * Setting up proper handlers for scatter gather handling
+	 */
+	if (ioc->dma_mask == DMA_BIT_MASK(64)) {
+		if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
+			ioc->add_sge = &mpt_add_sge_64bit_1078;
+		else
+			ioc->add_sge = &mpt_add_sge_64bit;
+		ioc->add_chain = &mpt_add_chain_64bit;
+		ioc->sg_addr_size = 8;
+	} else {
+		ioc->add_sge = &mpt_add_sge;
+		ioc->add_chain = &mpt_add_chain;
+		ioc->sg_addr_size = 4;
+	}
+	ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
+
 	ioc->alloc_total = sizeof(MPT_ADAPTER);
 	ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;		/* avoid div by zero! */
 	ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
 
 	ioc->pcidev = pdev;
-	ioc->diagPending = 0;
-	spin_lock_init(&ioc->diagLock);
-	spin_lock_init(&ioc->initializing_hba_lock);
+
+	spin_lock_init(&ioc->taskmgmt_lock);
+	mutex_init(&ioc->internal_cmds.mutex);
+	init_completion(&ioc->internal_cmds.done);
+	mutex_init(&ioc->mptbase_cmds.mutex);
+	init_completion(&ioc->mptbase_cmds.done);
+	mutex_init(&ioc->taskmgmt_cmds.mutex);
+	init_completion(&ioc->taskmgmt_cmds.done);
 
 	/* Initialize the event logging.
 	 */
@@ -1670,16 +1794,13 @@
 	ioc->mfcnt = 0;
 #endif
 
+	ioc->sh = NULL;
 	ioc->cached_fw = NULL;
 
 	/* Initilize SCSI Config Data structure
 	 */
 	memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
 
-	/* Initialize the running configQ head.
-	 */
-	INIT_LIST_HEAD(&ioc->configQ);
-
 	/* Initialize the fc rport list head.
 	 */
 	INIT_LIST_HEAD(&ioc->fc_rports);
@@ -1690,9 +1811,8 @@
 
 	/* Initialize workqueue */
 	INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
-	spin_lock_init(&ioc->fault_reset_work_lock);
 
-	snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
+	snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN,
 		 "mpt_poll_%d", ioc->id);
 	ioc->reset_work_q =
 		create_singlethread_workqueue(ioc->reset_work_q_name);
@@ -1767,11 +1887,14 @@
 	case MPI_MANUFACTPAGE_DEVID_SAS1064:
 	case MPI_MANUFACTPAGE_DEVID_SAS1068:
 		ioc->errata_flag_1064 = 1;
+		ioc->bus_type = SAS;
+		break;
 
 	case MPI_MANUFACTPAGE_DEVID_SAS1064E:
 	case MPI_MANUFACTPAGE_DEVID_SAS1068E:
 	case MPI_MANUFACTPAGE_DEVID_SAS1078:
 		ioc->bus_type = SAS;
+		break;
 	}
 
 
@@ -1813,6 +1936,11 @@
 	 */
 	mpt_detect_bound_ports(ioc, pdev);
 
+	INIT_LIST_HEAD(&ioc->fw_event_list);
+	spin_lock_init(&ioc->fw_event_lock);
+	snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id);
+	ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
+
 	if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
 	    CAN_SLEEP)) != 0){
 		printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
@@ -1885,13 +2013,18 @@
 	/*
 	 * Stop polling ioc for fault condition
 	 */
-	spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
 	wq = ioc->reset_work_q;
 	ioc->reset_work_q = NULL;
-	spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 	cancel_delayed_work(&ioc->fault_reset_work);
 	destroy_workqueue(wq);
 
+	spin_lock_irqsave(&ioc->fw_event_lock, flags);
+	wq = ioc->fw_event_q;
+	ioc->fw_event_q = NULL;
+	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+	destroy_workqueue(wq);
 
 	sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
 	remove_proc_entry(pname, NULL);
@@ -1994,6 +2127,21 @@
 	if (err)
 		return err;
 
+	if (ioc->dma_mask == DMA_BIT_MASK(64)) {
+		if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
+			ioc->add_sge = &mpt_add_sge_64bit_1078;
+		else
+			ioc->add_sge = &mpt_add_sge_64bit;
+		ioc->add_chain = &mpt_add_chain_64bit;
+		ioc->sg_addr_size = 8;
+	} else {
+
+		ioc->add_sge = &mpt_add_sge;
+		ioc->add_chain = &mpt_add_chain;
+		ioc->sg_addr_size = 4;
+	}
+	ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
+
 	printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
 	    ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
 	    CHIPREG_READ32(&ioc->chip->Doorbell));
@@ -2091,12 +2239,16 @@
 	ioc->active = 0;
 
 	if (ioc->alt_ioc) {
-		if (ioc->alt_ioc->active)
+		if (ioc->alt_ioc->active ||
+		    reason == MPT_HOSTEVENT_IOC_RECOVER) {
 			reset_alt_ioc_active = 1;
-
-		/* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
-		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
-		ioc->alt_ioc->active = 0;
+			/* Disable alt-IOC's reply interrupts
+			 *  (and FreeQ) for a bit
+			 **/
+			CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
+				0xFFFFFFFF);
+			ioc->alt_ioc->active = 0;
+		}
 	}
 
 	hard = 1;
@@ -2117,9 +2269,11 @@
 			}
 
 		} else {
-			printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
+			printk(MYIOC_s_WARN_FMT
+			    "NOT READY WARNING!\n", ioc->name);
 		}
-		return -1;
+		ret = -1;
+		goto out;
 	}
 
 	/* hard_reset_done = 0 if a soft reset was performed
@@ -2129,7 +2283,9 @@
 		if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
 			alt_ioc_ready = 1;
 		else
-			printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
+			printk(MYIOC_s_WARN_FMT
+			    ": alt-ioc Not ready WARNING!\n",
+			    ioc->alt_ioc->name);
 	}
 
 	for (ii=0; ii<5; ii++) {
@@ -2150,7 +2306,8 @@
 	if (alt_ioc_ready) {
 		if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
 			dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-			    "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
+			    "Initial Alt IocFacts failed rc=%x\n",
+			    ioc->name, rc));
 			/* Retry - alt IOC was initialized once
 			 */
 			rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
@@ -2194,16 +2351,20 @@
 			    IRQF_SHARED, ioc->name, ioc);
 			if (rc < 0) {
 				printk(MYIOC_s_ERR_FMT "Unable to allocate "
-				    "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
+				    "interrupt %d!\n",
+				    ioc->name, ioc->pcidev->irq);
 				if (ioc->msi_enable)
 					pci_disable_msi(ioc->pcidev);
-				return -EBUSY;
+				ret = -EBUSY;
+				goto out;
 			}
 			irq_allocated = 1;
 			ioc->pci_irq = ioc->pcidev->irq;
 			pci_set_master(ioc->pcidev);		/* ?? */
-			dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
-			    "%d\n", ioc->name, ioc->pcidev->irq));
+			pci_set_drvdata(ioc->pcidev, ioc);
+			dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
+			    "installed at interrupt %d\n", ioc->name,
+			    ioc->pcidev->irq));
 		}
 	}
 
@@ -2212,17 +2373,22 @@
 	 * init as upper addresses are needed for init.
 	 * If fails, continue with alt-ioc processing
 	 */
+	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n",
+	    ioc->name));
 	if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
 		ret = -3;
 
 	/* May need to check/upload firmware & data here!
 	 * If fails, continue with alt-ioc processing
 	 */
+	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n",
+	    ioc->name));
 	if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
 		ret = -4;
 // NEW!
 	if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
-		printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
+		printk(MYIOC_s_WARN_FMT
+		    ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n",
 		    ioc->alt_ioc->name, rc);
 		alt_ioc_ready = 0;
 		reset_alt_ioc_active = 0;
@@ -2232,8 +2398,9 @@
 		if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 0;
-			printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
-			    ioc->alt_ioc->name, rc);
+			printk(MYIOC_s_WARN_FMT
+				": alt-ioc: (%d) init failure WARNING!\n",
+					ioc->alt_ioc->name, rc);
 		}
 	}
 
@@ -2269,28 +2436,36 @@
 		}
 	}
 
+	/*  Enable MPT base driver management of EventNotification
+	 *  and EventAck handling.
+	 */
+	if ((ret == 0) && (!ioc->facts.EventState)) {
+		dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
+			"SendEventNotification\n",
+		    ioc->name));
+		ret = SendEventNotification(ioc, 1, sleepFlag);	/* 1=Enable */
+	}
+
+	if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
+		rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag);
+
 	if (ret == 0) {
 		/* Enable! (reply interrupt) */
 		CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
 		ioc->active = 1;
 	}
-
-	if (reset_alt_ioc_active && ioc->alt_ioc) {
-		/* (re)Enable alt-IOC! (reply interrupt) */
-		dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
-		    ioc->alt_ioc->name));
-		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
-		ioc->alt_ioc->active = 1;
+	if (rc == 0) {	/* alt ioc */
+		if (reset_alt_ioc_active && ioc->alt_ioc) {
+			/* (re)Enable alt-IOC! (reply interrupt) */
+			dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc"
+				"reply irq re-enabled\n",
+				ioc->alt_ioc->name));
+			CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
+				MPI_HIM_DIM);
+			ioc->alt_ioc->active = 1;
+		}
 	}
 
-	/*  Enable MPT base driver management of EventNotification
-	 *  and EventAck handling.
-	 */
-	if ((ret == 0) && (!ioc->facts.EventState))
-		(void) SendEventNotification(ioc, 1);	/* 1=Enable EventNotification */
-
-	if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
-		(void) SendEventNotification(ioc->alt_ioc, 1);	/* 1=Enable EventNotification */
 
 	/*	Add additional "reason" check before call to GetLanConfigPages
 	 *	(combined with GetIoUnitPage2 call).  This prevents a somewhat
@@ -2306,8 +2481,9 @@
 		mutex_init(&ioc->raid_data.inactive_list_mutex);
 		INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
 
-		if (ioc->bus_type == SAS) {
+		switch (ioc->bus_type) {
 
+		case SAS:
 			/* clear persistency table */
 			if(ioc->facts.IOCExceptions &
 			    MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
@@ -2321,8 +2497,15 @@
 			 */
 			mpt_findImVolumes(ioc);
 
-		} else if (ioc->bus_type == FC) {
-			if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
+			/* Check, and possibly reset, the coalescing value
+			 */
+			mpt_read_ioc_pg_1(ioc);
+
+			break;
+
+		case FC:
+			if ((ioc->pfacts[0].ProtocolFlags &
+				MPI_PORTFACTS_PROTOCOL_LAN) &&
 			    (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
 				/*
 				 *  Pre-fetch the ports LAN MAC address!
@@ -2331,11 +2514,14 @@
 				(void) GetLanConfigPages(ioc);
 				a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
 				dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-				    "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-				    ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
-
+					"LanAddr = %02X:%02X:%02X"
+					":%02X:%02X:%02X\n",
+					ioc->name, a[5], a[4],
+					a[3], a[2], a[1], a[0]));
 			}
-		} else {
+			break;
+
+		case SPI:
 			/* Get NVRAM and adapter maximums from SPP 0 and 2
 			 */
 			mpt_GetScsiPortSettings(ioc, 0);
@@ -2354,6 +2540,8 @@
 			mpt_read_ioc_pg_1(ioc);
 
 			mpt_read_ioc_pg_4(ioc);
+
+			break;
 		}
 
 		GetIoUnitPage2(ioc);
@@ -2435,16 +2623,20 @@
 		if (_pcidev == peer) {
 			/* Paranoia checks */
 			if (ioc->alt_ioc != NULL) {
-				printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
-					ioc->name, ioc->alt_ioc->name);
+				printk(MYIOC_s_WARN_FMT
+				    "Oops, already bound (%s <==> %s)!\n",
+				    ioc->name, ioc->name, ioc->alt_ioc->name);
 				break;
 			} else if (ioc_srch->alt_ioc != NULL) {
-				printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
-					ioc_srch->name, ioc_srch->alt_ioc->name);
+				printk(MYIOC_s_WARN_FMT
+				    "Oops, already bound (%s <==> %s)!\n",
+				    ioc_srch->name, ioc_srch->name,
+				    ioc_srch->alt_ioc->name);
 				break;
 			}
-			dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
-				ioc->name, ioc_srch->name));
+			dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+				"FOUND! binding %s <==> %s\n",
+				ioc->name, ioc->name, ioc_srch->name));
 			ioc_srch->alt_ioc = ioc;
 			ioc->alt_ioc = ioc_srch;
 		}
@@ -2464,8 +2656,8 @@
 	int ret;
 
 	if (ioc->cached_fw != NULL) {
-		ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
-		    "adapter\n", __func__, ioc->name));
+		ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			"%s: Pushing FW onto adapter\n", __func__, ioc->name));
 		if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
 		    ioc->cached_fw, CAN_SLEEP)) < 0) {
 			printk(MYIOC_s_WARN_FMT
@@ -2474,11 +2666,30 @@
 		}
 	}
 
+	/*
+	 * Put the controller into ready state (if its not already)
+	 */
+	if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) {
+		if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET,
+		    CAN_SLEEP)) {
+			if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY)
+				printk(MYIOC_s_ERR_FMT "%s:  IOC msg unit "
+				    "reset failed to put ioc in ready state!\n",
+				    ioc->name, __func__);
+		} else
+			printk(MYIOC_s_ERR_FMT "%s:  IOC msg unit reset "
+			    "failed!\n", ioc->name, __func__);
+	}
+
+
 	/* Disable adapter interrupts! */
+	synchronize_irq(ioc->pcidev->irq);
 	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
 	ioc->active = 0;
+
 	/* Clear any lingering interrupt */
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	CHIPREG_READ32(&ioc->chip->IntStatus);
 
 	if (ioc->alloc != NULL) {
 		sz = ioc->alloc_sz;
@@ -2538,19 +2749,22 @@
 		if((ret = mpt_host_page_access_control(ioc,
 		    MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
 			printk(MYIOC_s_ERR_FMT
-			   "host page buffers free failed (%d)!\n",
-			    ioc->name, ret);
+			   ": %s: host page buffers free failed (%d)!\n",
+			    ioc->name, __func__, ret);
 		}
-		dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free  @ %p, sz=%d bytes\n",
-		 	ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
+		dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			"HostPageBuffer free  @ %p, sz=%d bytes\n",
+			ioc->name, ioc->HostPageBuffer,
+			ioc->HostPageBuffer_sz));
 		pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
 		    ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
 		ioc->HostPageBuffer = NULL;
 		ioc->HostPageBuffer_sz = 0;
 		ioc->alloc_total -= ioc->HostPageBuffer_sz;
 	}
-}
 
+	pci_set_drvdata(ioc->pcidev, NULL);
+}
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mpt_adapter_dispose - Free all resources associated with an MPT adapter
@@ -2690,8 +2904,12 @@
 	}
 
 	/* Is it already READY? */
-	if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
+	if (!statefault &&
+	    ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) {
+		dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
+		    "IOC is in READY state\n", ioc->name));
 		return 0;
+	}
 
 	/*
 	 *	Check to see if IOC is in FAULT state.
@@ -2764,8 +2982,9 @@
 
 		ii++; cntdn--;
 		if (!cntdn) {
-			printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
-					ioc->name, (int)((ii+5)/HZ));
+			printk(MYIOC_s_ERR_FMT
+				"Wait IOC_READY state (0x%x) timeout(%d)!\n",
+				ioc->name, ioc_state, (int)((ii+5)/HZ));
 			return -ETIME;
 		}
 
@@ -2778,9 +2997,8 @@
 	}
 
 	if (statefault < 3) {
-		printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
-				ioc->name,
-				statefault==1 ? "stuck handshake" : "IOC FAULT");
+		printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name,
+			statefault == 1 ? "stuck handshake" : "IOC FAULT");
 	}
 
 	return hard_reset_done;
@@ -2833,8 +3051,9 @@
 
 	/* IOC *must* NOT be in RESET state! */
 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
-		printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
-		    ioc->name, ioc->last_state );
+		printk(KERN_ERR MYNAM
+		    ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
+		    ioc->name, ioc->last_state);
 		return -44;
 	}
 
@@ -2896,7 +3115,7 @@
 		 *	Old: u16{Major(4),Minor(4),SubMinor(8)}
 		 *	New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
 		 */
-		if (facts->MsgVersion < 0x0102) {
+		if (facts->MsgVersion < MPI_VERSION_01_02) {
 			/*
 			 *	Handle old FC f/w style, convert to new...
 			 */
@@ -2908,9 +3127,11 @@
 			facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
 
 		facts->ProductID = le16_to_cpu(facts->ProductID);
+
 		if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
 		    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
 			ioc->ir_firmware = 1;
+
 		facts->CurrentHostMfaHighAddr =
 				le32_to_cpu(facts->CurrentHostMfaHighAddr);
 		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
@@ -2926,7 +3147,7 @@
 		 * to 14 in MPI-1.01.0x.
 		 */
 		if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
-		    facts->MsgVersion > 0x0100) {
+		    facts->MsgVersion > MPI_VERSION_01_00) {
 			facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
 		}
 
@@ -3108,6 +3329,7 @@
 
 	ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
 	ioc_init.MaxBuses = (U8)ioc->number_of_buses;
+
 	dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
 		   ioc->name, ioc->facts.MsgVersion));
 	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
@@ -3122,7 +3344,7 @@
 	}
 	ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);	/* in BYTES */
 
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
+	if (ioc->sg_addr_size == sizeof(u64)) {
 		/* Save the upper 32-bits of the request
 		 * (reply) and sense buffers.
 		 */
@@ -3325,11 +3547,10 @@
 	FWUpload_t		*prequest;
 	FWUploadReply_t		*preply;
 	FWUploadTCSGE_t		*ptcsge;
-	int			 sgeoffset;
 	u32			 flagsLength;
 	int			 ii, sz, reply_sz;
 	int			 cmdStatus;
-
+	int			request_size;
 	/* If the image size is 0, we are done.
 	 */
 	if ((sz = ioc->facts.FWImageSize) == 0)
@@ -3364,42 +3585,41 @@
 	ptcsge->ImageSize = cpu_to_le32(sz);
 	ptcsge++;
 
-	sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
-
 	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
-	mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
-
-	sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
-	    ioc->name, prequest, sgeoffset));
+	ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
+	request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) +
+	    ioc->SGE_size;
+	dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload "
+	    " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest,
+	    ioc->facts.FWImageSize, request_size));
 	DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
 
-	ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
-				reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
+	ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest,
+	    reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag);
 
-	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
+	dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed "
+	    "rc=%x \n", ioc->name, ii));
 
 	cmdStatus = -EFAULT;
 	if (ii == 0) {
 		/* Handshake transfer was complete and successful.
 		 * Check the Reply Frame.
 		 */
-		int status, transfer_sz;
-		status = le16_to_cpu(preply->IOCStatus);
-		if (status == MPI_IOCSTATUS_SUCCESS) {
-			transfer_sz = le32_to_cpu(preply->ActualImageSize);
-			if (transfer_sz == sz)
+		int status;
+		status = le16_to_cpu(preply->IOCStatus) &
+				MPI_IOCSTATUS_MASK;
+		if (status == MPI_IOCSTATUS_SUCCESS &&
+		    ioc->facts.FWImageSize ==
+		    le32_to_cpu(preply->ActualImageSize))
 				cmdStatus = 0;
-		}
 	}
 	dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
 			ioc->name, cmdStatus));
 
 
 	if (cmdStatus) {
-
-		ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n",
-			ioc->name));
+		ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, "
+		    "freeing image \n", ioc->name));
 		mpt_free_fw_memory(ioc);
 	}
 	kfree(prequest);
@@ -3723,6 +3943,10 @@
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
 	if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
+
+		if (!ignore)
+			return 0;
+
 		drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
 			"address=%p\n",  ioc->name, __func__,
 			&ioc->chip->Doorbell, &ioc->chip->Reset_1078));
@@ -3740,6 +3964,7 @@
 				"looking for READY STATE: doorbell=%x"
 			        " count=%d\n",
 				ioc->name, doorbell, count));
+
 			if (doorbell == MPI_IOC_STATE_READY) {
 				return 1;
 			}
@@ -3890,6 +4115,10 @@
 				doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
 				doorbell &= MPI_IOC_STATE_MASK;
 
+				drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+				    "looking for READY STATE: doorbell=%x"
+				    " count=%d\n", ioc->name, doorbell, count));
+
 				if (doorbell == MPI_IOC_STATE_READY) {
 					break;
 				}
@@ -3901,6 +4130,11 @@
 					mdelay (1000);
 				}
 			}
+
+			if (doorbell != MPI_IOC_STATE_READY)
+				printk(MYIOC_s_ERR_FMT "Failed to come READY "
+				    "after reset! IocState=%x", ioc->name,
+				    doorbell);
 		}
 	}
 
@@ -4019,8 +4253,9 @@
 			if (sleepFlag != CAN_SLEEP)
 				count *= 10;
 
-			printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
-			    ioc->name, (int)((count+5)/HZ));
+			printk(MYIOC_s_ERR_FMT
+			    "Wait IOC_READY state (0x%x) timeout(%d)!\n",
+			    ioc->name, state, (int)((count+5)/HZ));
 			return -ETIME;
 		}
 
@@ -4090,24 +4325,29 @@
 	 * num_sge = num sge in request frame + last chain buffer
 	 * scale = num sge per chain buffer if no chain element
 	 */
-	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-	if (sizeof(dma_addr_t) == sizeof(u64))
-		num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+	scale = ioc->req_sz / ioc->SGE_size;
+	if (ioc->sg_addr_size == sizeof(u64))
+		num_sge =  scale + (ioc->req_sz - 60) / ioc->SGE_size;
 	else
-		num_sge =  1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+		num_sge =  1 + scale + (ioc->req_sz - 64) / ioc->SGE_size;
 
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
+	if (ioc->sg_addr_size == sizeof(u64)) {
 		numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
-			(ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+			(ioc->req_sz - 60) / ioc->SGE_size;
 	} else {
-		numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
-			(ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+		numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) +
+		    scale + (ioc->req_sz - 64) / ioc->SGE_size;
 	}
 	dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
 		ioc->name, num_sge, numSGE));
 
-	if ( numSGE > MPT_SCSI_SG_DEPTH	)
-		numSGE = MPT_SCSI_SG_DEPTH;
+	if (ioc->bus_type == FC) {
+		if (numSGE > MPT_SCSI_FC_SG_DEPTH)
+			numSGE = MPT_SCSI_FC_SG_DEPTH;
+	} else {
+		if (numSGE > MPT_SCSI_SG_DEPTH)
+			numSGE = MPT_SCSI_SG_DEPTH;
+	}
 
 	num_chain = 1;
 	while (numSGE - num_sge > 0) {
@@ -4161,12 +4401,42 @@
 	dma_addr_t alloc_dma;
 	u8 *mem;
 	int i, reply_sz, sz, total_size, num_chain;
+	u64	dma_mask;
+
+	dma_mask = 0;
 
 	/*  Prime reply FIFO...  */
 
 	if (ioc->reply_frames == NULL) {
 		if ( (num_chain = initChainBuffers(ioc)) < 0)
 			return -1;
+		/*
+		 * 1078 errata workaround for the 36GB limitation
+		 */
+		if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 &&
+		    ioc->dma_mask > DMA_BIT_MASK(35)) {
+			if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32))
+			    && !pci_set_consistent_dma_mask(ioc->pcidev,
+			    DMA_BIT_MASK(32))) {
+				dma_mask = DMA_BIT_MASK(35);
+				d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+				    "setting 35 bit addressing for "
+				    "Request/Reply/Chain and Sense Buffers\n",
+				    ioc->name));
+			} else {
+				/*Reseting DMA mask to 64 bit*/
+				pci_set_dma_mask(ioc->pcidev,
+					DMA_BIT_MASK(64));
+				pci_set_consistent_dma_mask(ioc->pcidev,
+					DMA_BIT_MASK(64));
+
+				printk(MYIOC_s_ERR_FMT
+				    "failed setting 35 bit addressing for "
+				    "Request/Reply/Chain and Sense Buffers\n",
+				    ioc->name);
+				return -1;
+			}
+		}
 
 		total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
 		dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
@@ -4305,9 +4575,16 @@
 		alloc_dma += ioc->reply_sz;
 	}
 
+	if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
+	    ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev,
+	    ioc->dma_mask))
+		d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "restoring 64 bit addressing\n", ioc->name));
+
 	return 0;
 
 out_fail:
+
 	if (ioc->alloc != NULL) {
 		sz = ioc->alloc_sz;
 		pci_free_consistent(ioc->pcidev,
@@ -4324,6 +4601,13 @@
 				ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
 		ioc->sense_buf_pool = NULL;
 	}
+
+	if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
+	    DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(ioc->pcidev,
+	    DMA_BIT_MASK(64)))
+		d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "restoring 64 bit addressing\n", ioc->name));
+
 	return -1;
 }
 
@@ -4759,7 +5043,14 @@
 	SasIoUnitControlReply_t		*sasIoUnitCntrReply;
 	MPT_FRAME_HDR			*mf = NULL;
 	MPIHeader_t			*mpi_hdr;
+	int				ret = 0;
+	unsigned long 	 		timeleft;
+
+	mutex_lock(&ioc->mptbase_cmds.mutex);
 
+	/* init the internal cmd struct */
+	memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
+	INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
 
 	/* insure garbage is not sent to fw */
 	switch(persist_opcode) {
@@ -4769,17 +5060,19 @@
 		break;
 
 	default:
-		return -1;
-		break;
+		ret = -1;
+		goto out;
 	}
 
-	printk("%s: persist_opcode=%x\n",__func__, persist_opcode);
+	printk(KERN_DEBUG  "%s: persist_opcode=%x\n",
+		__func__, persist_opcode);
 
 	/* Get a MF for this command.
 	 */
 	if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
-		printk("%s: no msg frames!\n",__func__);
-		return -1;
+		printk(KERN_DEBUG "%s: no msg frames!\n", __func__);
+		ret = -1;
+		goto out;
         }
 
 	mpi_hdr = (MPIHeader_t *) mf;
@@ -4789,27 +5082,42 @@
 	sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
 	sasIoUnitCntrReq->Operation = persist_opcode;
 
-	init_timer(&ioc->persist_timer);
-	ioc->persist_timer.data = (unsigned long) ioc;
-	ioc->persist_timer.function = mpt_timer_expired;
-	ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
-	ioc->persist_wait_done=0;
-	add_timer(&ioc->persist_timer);
 	mpt_put_msg_frame(mpt_base_index, ioc, mf);
-	wait_event(mpt_waitq, ioc->persist_wait_done);
+	timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ);
+	if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		ret = -ETIME;
+		printk(KERN_DEBUG "%s: failed\n", __func__);
+		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			goto out;
+		if (!timeleft) {
+			printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n",
+			    ioc->name, __func__);
+			mpt_HardResetHandler(ioc, CAN_SLEEP);
+			mpt_free_msg_frame(ioc, mf);
+		}
+		goto out;
+	}
+
+	if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
+		ret = -1;
+		goto out;
+	}
 
 	sasIoUnitCntrReply =
-	    (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
+	    (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply;
 	if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
-		printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
-		    __func__,
-		    sasIoUnitCntrReply->IOCStatus,
+		printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
+		    __func__, sasIoUnitCntrReply->IOCStatus,
 		    sasIoUnitCntrReply->IOCLogInfo);
-		return -1;
-	}
+		printk(KERN_DEBUG "%s: failed\n", __func__);
+		ret = -1;
+	} else
+		printk(KERN_DEBUG "%s: success\n", __func__);
+ out:
 
-	printk("%s: success\n",__func__);
-	return 0;
+	CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
+	mutex_unlock(&ioc->mptbase_cmds.mutex);
+	return ret;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5394,17 +5702,20 @@
  *	-ENOMEM if pci_alloc failed
  **/
 int
-mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
+mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num,
+			RaidPhysDiskPage0_t *phys_disk)
 {
-	CONFIGPARMS		 	cfg;
-	ConfigPageHeader_t	 	hdr;
+	CONFIGPARMS			cfg;
+	ConfigPageHeader_t		hdr;
 	dma_addr_t			dma_handle;
 	pRaidPhysDiskPage0_t		buffer = NULL;
 	int				rc;
 
 	memset(&cfg, 0 , sizeof(CONFIGPARMS));
 	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+	memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t));
 
+	hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION;
 	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
 	cfg.cfghdr.hdr = &hdr;
 	cfg.physAddr = -1;
@@ -5451,6 +5762,161 @@
 }
 
 /**
+ *	mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num
+ *	@ioc: Pointer to a Adapter Structure
+ *	@phys_disk_num: io unit unique phys disk num generated by the ioc
+ *
+ *	Return:
+ *	returns number paths
+ **/
+int
+mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num)
+{
+	CONFIGPARMS		 	cfg;
+	ConfigPageHeader_t	 	hdr;
+	dma_addr_t			dma_handle;
+	pRaidPhysDiskPage1_t		buffer = NULL;
+	int				rc;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+
+	hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+	hdr.PageNumber = 1;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = 0;
+		goto out;
+	}
+
+	if (!hdr.PageLength) {
+		rc = 0;
+		goto out;
+	}
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer) {
+		rc = 0;
+		goto out;
+	}
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	cfg.pageAddr = phys_disk_num;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = 0;
+		goto out;
+	}
+
+	rc = buffer->NumPhysDiskPaths;
+ out:
+
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+
+	return rc;
+}
+EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);
+
+/**
+ *	mpt_raid_phys_disk_pg1 - returns phys disk page 1
+ *	@ioc: Pointer to a Adapter Structure
+ *	@phys_disk_num: io unit unique phys disk num generated by the ioc
+ *	@phys_disk: requested payload data returned
+ *
+ *	Return:
+ *	0 on success
+ *	-EFAULT if read of config page header fails or data pointer not NULL
+ *	-ENOMEM if pci_alloc failed
+ **/
+int
+mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
+		RaidPhysDiskPage1_t *phys_disk)
+{
+	CONFIGPARMS		 	cfg;
+	ConfigPageHeader_t	 	hdr;
+	dma_addr_t			dma_handle;
+	pRaidPhysDiskPage1_t		buffer = NULL;
+	int				rc;
+	int				i;
+	__le64				sas_address;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+	rc = 0;
+
+	hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+	hdr.PageNumber = 1;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	if (!hdr.PageLength) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+	cfg.pageAddr = phys_disk_num;
+
+	if (mpt_config(ioc, &cfg) != 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths;
+	phys_disk->PhysDiskNum = phys_disk_num;
+	for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) {
+		phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID;
+		phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus;
+		phys_disk->Path[i].OwnerIdentifier =
+				buffer->Path[i].OwnerIdentifier;
+		phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags);
+		memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64));
+		sas_address = le64_to_cpu(sas_address);
+		memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64));
+		memcpy(&sas_address,
+				&buffer->Path[i].OwnerWWID, sizeof(__le64));
+		sas_address = le64_to_cpu(sas_address);
+		memcpy(&phys_disk->Path[i].OwnerWWID,
+				&sas_address, sizeof(__le64));
+	}
+
+ out:
+
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+
+	return rc;
+}
+EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);
+
+
+/**
  *	mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
  *	@ioc: Pointer to a Adapter Strucutre
  *
@@ -5775,30 +6241,28 @@
  *	SendEventNotification - Send EventNotification (on or off) request to adapter
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@EvSwitch: Event switch flags
+ *	@sleepFlag: Specifies whether the process can sleep
  */
 static int
-SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
+SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag)
 {
-	EventNotification_t	*evnp;
-
-	evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
-	if (evnp == NULL) {
-		devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
-				ioc->name));
-		return 0;
-	}
-	memset(evnp, 0, sizeof(*evnp));
+	EventNotification_t	evn;
+	MPIDefaultReply_t	reply_buf;
 
-	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
+	memset(&evn, 0, sizeof(EventNotification_t));
+	memset(&reply_buf, 0, sizeof(MPIDefaultReply_t));
 
-	evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
-	evnp->ChainOffset = 0;
-	evnp->MsgFlags = 0;
-	evnp->Switch = EvSwitch;
+	evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION;
+	evn.Switch = EvSwitch;
+	evn.MsgContext = cpu_to_le32(mpt_base_index << 16);
 
-	mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
+	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "Sending EventNotification (%d) request %p\n",
+	    ioc->name, EvSwitch, &evn));
 
-	return 0;
+	return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t),
+	    (u32 *)&evn, sizeof(MPIDefaultReply_t), (u16 *)&reply_buf, 30,
+	    sleepFlag);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5814,7 +6278,7 @@
 
 	if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
 		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
-		    ioc->name,__func__));
+		    ioc->name, __func__));
 		return -1;
 	}
 
@@ -5851,12 +6315,19 @@
 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
 {
 	Config_t	*pReq;
+	ConfigReply_t	*pReply;
 	ConfigExtendedPageHeader_t  *pExtHdr = NULL;
 	MPT_FRAME_HDR	*mf;
-	unsigned long	 flags;
-	int		 ii, rc;
+	int		 ii;
 	int		 flagsLength;
-	int		 in_isr;
+	long		 timeout;
+	int		 ret;
+	u8		 page_type = 0, extend_page;
+	unsigned long 	 timeleft;
+	unsigned long	 flags;
+    int		 in_isr;
+	u8		 issue_hard_reset = 0;
+	u8		 retry_count = 0;
 
 	/*	Prevent calling wait_event() (below), if caller happens
 	 *	to be in ISR context, because that is fatal!
@@ -5866,15 +6337,43 @@
 		dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
 				ioc->name));
 		return -EPERM;
+    }
+
+	/* don't send a config page during diag reset */
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	if (ioc->ioc_reset_in_progress) {
+		dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: busy with host reset\n", ioc->name, __func__));
+		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+		return -EBUSY;
 	}
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+
+	/* don't send if no chance of success */
+	if (!ioc->active ||
+	    mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) {
+		dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: ioc not operational, %d, %xh\n",
+		    ioc->name, __func__, ioc->active,
+		    mpt_GetIocState(ioc, 0)));
+		return -EFAULT;
+	}
+
+ retry_config:
+	mutex_lock(&ioc->mptbase_cmds.mutex);
+	/* init the internal cmd struct */
+	memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE);
+	INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status)
 
 	/* Get and Populate a free Frame
 	 */
 	if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
-		dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
-				ioc->name));
-		return -EAGAIN;
+		dcprintk(ioc, printk(MYIOC_s_WARN_FMT
+		"mpt_config: no msg frames!\n", ioc->name));
+		ret = -EAGAIN;
+		goto out;
 	}
+
 	pReq = (Config_t *)mf;
 	pReq->Action = pCfg->action;
 	pReq->Reserved = 0;
@@ -5900,7 +6399,9 @@
 		pReq->ExtPageType = pExtHdr->ExtPageType;
 		pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
 
-		/* Page Length must be treated as a reserved field for the extended header. */
+		/* Page Length must be treated as a reserved field for the
+		 * extended header.
+		 */
 		pReq->Header.PageLength = 0;
 	}
 
@@ -5913,78 +6414,91 @@
 	else
 		flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
 
-	if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
+	if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) ==
+	    MPI_CONFIG_PAGETYPE_EXTENDED) {
 		flagsLength |= pExtHdr->ExtPageLength * 4;
-
-		dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
-			ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
-	}
-	else {
+		page_type = pReq->ExtPageType;
+		extend_page = 1;
+	} else {
 		flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
-
-		dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
-			ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
+		page_type = pReq->Header.PageType;
+		extend_page = 0;
 	}
 
-	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
-
-	/* Append pCfg pointer to end of mf
-	 */
-	*((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
-
-	/* Initalize the timer
-	 */
-	init_timer_on_stack(&pCfg->timer);
-	pCfg->timer.data = (unsigned long) ioc;
-	pCfg->timer.function = mpt_timer_expired;
-	pCfg->wait_done = 0;
-
-	/* Set the timer; ensure 10 second minimum */
-	if (pCfg->timeout < 10)
-		pCfg->timer.expires = jiffies + HZ*10;
-	else
-		pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
-
-	/* Add to end of Q, set timer and then issue this command */
-	spin_lock_irqsave(&ioc->FreeQlock, flags);
-	list_add_tail(&pCfg->linkage, &ioc->configQ);
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+	dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "Sending Config request type 0x%x, page 0x%x and action %d\n",
+	    ioc->name, page_type, pReq->Header.PageNumber, pReq->Action));
 
-	add_timer(&pCfg->timer);
+	ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
+	timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout;
 	mpt_put_msg_frame(mpt_base_index, ioc, mf);
-	wait_event(mpt_waitq, pCfg->wait_done);
-
-	/* mf has been freed - do not access */
+	timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done,
+		timeout);
+	if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		ret = -ETIME;
+		dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "Failed Sending Config request type 0x%x, page 0x%x,"
+		    " action %d, status %xh, time left %ld\n\n",
+			ioc->name, page_type, pReq->Header.PageNumber,
+			pReq->Action, ioc->mptbase_cmds.status, timeleft));
+		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			goto out;
+		if (!timeleft)
+			issue_hard_reset = 1;
+		goto out;
+	}
 
-	rc = pCfg->status;
+	if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
+		ret = -1;
+		goto out;
+	}
+	pReply = (ConfigReply_t	*)ioc->mptbase_cmds.reply;
+	ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+	if (ret == MPI_IOCSTATUS_SUCCESS) {
+		if (extend_page) {
+			pCfg->cfghdr.ehdr->ExtPageLength =
+			    le16_to_cpu(pReply->ExtPageLength);
+			pCfg->cfghdr.ehdr->ExtPageType =
+			    pReply->ExtPageType;
+		}
+		pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
+		pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
+		pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
+		pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
 
-	return rc;
-}
+	}
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mpt_timer_expired - Callback for timer process.
- *	Used only internal config functionality.
- *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- */
-static void
-mpt_timer_expired(unsigned long data)
-{
-	MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
+	if (retry_count)
+		printk(MYIOC_s_INFO_FMT "Retry completed "
+		    "ret=0x%x timeleft=%ld\n",
+		    ioc->name, ret, timeleft);
 
-	dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name));
+	dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n",
+	     ret, le32_to_cpu(pReply->IOCLogInfo)));
 
-	/* Perform a FW reload */
-	if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
-		printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
+out:
 
-	/* No more processing.
-	 * Hard reset clean-up will wake up
-	 * process and free all resources.
-	 */
-	dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name));
+	CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
+	mutex_unlock(&ioc->mptbase_cmds.mutex);
+	if (issue_hard_reset) {
+		issue_hard_reset = 0;
+		printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
+		    ioc->name, __func__);
+		mpt_HardResetHandler(ioc, CAN_SLEEP);
+		mpt_free_msg_frame(ioc, mf);
+		/* attempt one retry for a timed out command */
+		if (!retry_count) {
+			printk(MYIOC_s_INFO_FMT
+			    "Attempting Retry Config request"
+			    " type 0x%x, page 0x%x,"
+			    " action %d\n", ioc->name, page_type,
+			    pCfg->cfghdr.hdr->PageNumber, pCfg->action);
+			retry_count++;
+			goto retry_config;
+		}
+	}
+	return ret;
 
-	return;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5998,41 +6512,34 @@
 static int
 mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-	CONFIGPARMS *pCfg;
-	unsigned long flags;
-
-	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-	    ": IOC %s_reset routed to MPT base driver!\n",
-	    ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
-	    reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
-
-	if (reset_phase == MPT_IOC_SETUP_RESET) {
-		;
-	} else if (reset_phase == MPT_IOC_PRE_RESET) {
-		/* If the internal config Q is not empty -
-		 * delete timer. MF resources will be freed when
-		 * the FIFO's are primed.
-		 */
-		spin_lock_irqsave(&ioc->FreeQlock, flags);
-		list_for_each_entry(pCfg, &ioc->configQ, linkage)
-			del_timer(&pCfg->timer);
-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
-	} else {
-		CONFIGPARMS *pNext;
-
-		/* Search the configQ for internal commands.
-		 * Flush the Q, and wake up all suspended threads.
-		 */
-		spin_lock_irqsave(&ioc->FreeQlock, flags);
-		list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
-			list_del(&pCfg->linkage);
-
-			pCfg->status = MPT_CONFIG_ERROR;
-			pCfg->wait_done = 1;
-			wake_up(&mpt_waitq);
+	switch (reset_phase) {
+	case MPT_IOC_SETUP_RESET:
+		ioc->taskmgmt_quiesce_io = 1;
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
+		break;
+	case MPT_IOC_PRE_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
+		break;
+	case MPT_IOC_POST_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_POST_RESET\n",  ioc->name, __func__));
+/* wake up mptbase_cmds */
+		if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->mptbase_cmds.status |=
+			    MPT_MGMT_STATUS_DID_IOCRESET;
+			complete(&ioc->mptbase_cmds.done);
 		}
-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+/* wake up taskmgmt_cmds */
+		if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->taskmgmt_cmds.status |=
+				MPT_MGMT_STATUS_DID_IOCRESET;
+			complete(&ioc->taskmgmt_cmds.done);
+		}
+		break;
+	default:
+		break;
 	}
 
 	return 1;		/* currently means nothing really */
@@ -6344,6 +6851,59 @@
 
 	*size = y;
 }
+/**
+ *	mpt_set_taskmgmt_in_progress_flag - set flags associated with task managment
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	Returns 0 for SUCCESS or -1 if FAILED.
+ *
+ *	If -1 is return, then it was not possible to set the flags
+ **/
+int
+mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
+{
+	unsigned long	 flags;
+	int		 retval;
+
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress ||
+	    (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) {
+		retval = -1;
+		goto out;
+	}
+	retval = 0;
+	ioc->taskmgmt_in_progress = 1;
+	ioc->taskmgmt_quiesce_io = 1;
+	if (ioc->alt_ioc) {
+		ioc->alt_ioc->taskmgmt_in_progress = 1;
+		ioc->alt_ioc->taskmgmt_quiesce_io = 1;
+	}
+ out:
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+	return retval;
+}
+EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
+
+/**
+ *	mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task managment
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ **/
+void
+mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
+{
+	unsigned long	 flags;
+
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	ioc->taskmgmt_in_progress = 0;
+	ioc->taskmgmt_quiesce_io = 0;
+	if (ioc->alt_ioc) {
+		ioc->alt_ioc->taskmgmt_in_progress = 0;
+		ioc->alt_ioc->taskmgmt_quiesce_io = 0;
+	}
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+}
+EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
 
 
 /**
@@ -6397,7 +6957,9 @@
 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 {
 	int		 rc;
+	u8	 cb_idx;
 	unsigned long	 flags;
+	unsigned long	 time_count;
 
 	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
 #ifdef MFCNT
@@ -6410,14 +6972,15 @@
 	/* Reset the adapter. Prevent more than 1 call to
 	 * mpt_do_ioc_recovery at any instant in time.
 	 */
-	spin_lock_irqsave(&ioc->diagLock, flags);
-	if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
-		spin_unlock_irqrestore(&ioc->diagLock, flags);
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	if (ioc->ioc_reset_in_progress) {
+		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 		return 0;
-	} else {
-		ioc->diagPending = 1;
 	}
-	spin_unlock_irqrestore(&ioc->diagLock, flags);
+	ioc->ioc_reset_in_progress = 1;
+	if (ioc->alt_ioc)
+		ioc->alt_ioc->ioc_reset_in_progress = 1;
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 
 	/* FIXME: If do_ioc_recovery fails, repeat....
 	 */
@@ -6427,47 +6990,57 @@
 	 * Prevents timeouts occurring during a diagnostic reset...very bad.
 	 * For all other protocol drivers, this is a no-op.
 	 */
-	{
-		u8	 cb_idx;
-		int	 r = 0;
-
-		for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
-			if (MptResetHandlers[cb_idx]) {
-				dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
-						ioc->name, cb_idx));
-				r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
-				if (ioc->alt_ioc) {
-					dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
-							ioc->name, ioc->alt_ioc->name, cb_idx));
-					r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
-				}
-			}
+	for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+		if (MptResetHandlers[cb_idx]) {
+			mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
+			if (ioc->alt_ioc)
+				mpt_signal_reset(cb_idx, ioc->alt_ioc,
+					MPT_IOC_SETUP_RESET);
 		}
 	}
 
-	if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
-		printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
+	time_count = jiffies;
+	rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag);
+	if (rc != 0) {
+		printk(KERN_WARNING MYNAM
+		    ": WARNING - (%d) Cannot recover %s\n", rc, ioc->name);
+	} else {
+		if (ioc->hard_resets < -1)
+			ioc->hard_resets++;
 	}
-	ioc->reload_fw = 0;
-	if (ioc->alt_ioc)
-		ioc->alt_ioc->reload_fw = 0;
 
-	spin_lock_irqsave(&ioc->diagLock, flags);
-	ioc->diagPending = 0;
-	if (ioc->alt_ioc)
-		ioc->alt_ioc->diagPending = 0;
-	spin_unlock_irqrestore(&ioc->diagLock, flags);
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	ioc->ioc_reset_in_progress = 0;
+	ioc->taskmgmt_quiesce_io = 0;
+	ioc->taskmgmt_in_progress = 0;
+	if (ioc->alt_ioc) {
+		ioc->alt_ioc->ioc_reset_in_progress = 0;
+		ioc->alt_ioc->taskmgmt_quiesce_io = 0;
+		ioc->alt_ioc->taskmgmt_in_progress = 0;
+	}
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 
-	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
+	dtmprintk(ioc,
+	    printk(MYIOC_s_DEBUG_FMT
+		"HardResetHandler: completed (%d seconds): %s\n", ioc->name,
+		jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ?
+		"SUCCESS" : "FAILED")));
 
 	return rc;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#ifdef CONFIG_FUSION_LOGGING
 static void
-EventDescriptionStr(u8 event, u32 evData0, char *evStr)
+mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
 {
 	char *ds = NULL;
+	u32 evData0;
+	int ii;
+	u8 event;
+	char *evStr = ioc->evStr;
+
+	event = le32_to_cpu(pEventReply->Event) & 0xFF;
+	evData0 = le32_to_cpu(pEventReply->Data[0]);
 
 	switch(event) {
 	case MPI_EVENT_NONE:
@@ -6501,9 +7074,9 @@
 		if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
 			ds = "Loop State(LIP) Change";
 		else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
-			ds = "Loop State(LPE) Change";		/* ??? */
+			ds = "Loop State(LPE) Change";
 		else
-			ds = "Loop State(LPB) Change";		/* ??? */
+			ds = "Loop State(LPB) Change";
 		break;
 	case MPI_EVENT_LOGOUT:
 		ds = "Logout";
@@ -6703,28 +7276,65 @@
 	}
 	case MPI_EVENT_IR2:
 	{
+		u8 id = (u8)(evData0);
+		u8 channel = (u8)(evData0 >> 8);
+		u8 phys_num = (u8)(evData0 >> 24);
 		u8 ReasonCode = (u8)(evData0 >> 16);
+
 		switch (ReasonCode) {
 		case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
-			ds = "IR2: LD State Changed";
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: LD State Changed: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
 			break;
 		case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
-			ds = "IR2: PD State Changed";
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: PD State Changed "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
 			break;
 		case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
-			ds = "IR2: Bad Block Table Full";
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: Bad Block Table Full: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
 			break;
 		case MPI_EVENT_IR2_RC_PD_INSERTED:
-			ds = "IR2: PD Inserted";
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: PD Inserted: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
 			break;
 		case MPI_EVENT_IR2_RC_PD_REMOVED:
-			ds = "IR2: PD Removed";
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: PD Removed: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
 			break;
 		case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
-			ds = "IR2: Foreign CFG Detected";
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: Foreign CFG Detected: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
 			break;
 		case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
-			ds = "IR2: Rebuild Medium Error";
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: Rebuild Medium Error: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
+			break;
+		case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: Dual Port Added: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
+			break;
+		case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			    "IR2: Dual Port Removed: "
+			    "id=%d channel=%d phys_num=%d",
+			    id, channel, phys_num);
 			break;
 		default:
 			ds = "IR2";
@@ -6760,13 +7370,18 @@
 	case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
 	{
 		u8 reason = (u8)(evData0);
-		u8 port_num = (u8)(evData0 >> 8);
-		u16 handle = le16_to_cpu(evData0 >> 16);
 
-		snprintf(evStr, EVENT_DESCR_STR_SZ,
-		    "SAS Initiator Device Status Change: reason=0x%02x "
-		    "port=%d handle=0x%04x",
-		    reason, port_num, handle);
+		switch (reason) {
+		case MPI_EVENT_SAS_INIT_RC_ADDED:
+			ds = "SAS Initiator Status Change: Added";
+			break;
+		case MPI_EVENT_SAS_INIT_RC_REMOVED:
+			ds = "SAS Initiator Status Change: Deleted";
+			break;
+		default:
+			ds = "SAS Initiator Status Change";
+			break;
+		}
 		break;
 	}
 
@@ -6814,6 +7429,24 @@
 		break;
 	}
 
+	case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
+	{
+		u8 reason = (u8)(evData0);
+
+		switch (reason) {
+		case MPI_EVENT_SAS_EXP_RC_ADDED:
+			ds = "Expander Status Change: Added";
+			break;
+		case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING:
+			ds = "Expander Status Change: Deleted";
+			break;
+		default:
+			ds = "Expander Status Change";
+			break;
+		}
+		break;
+	}
+
 	/*
 	 *  MPT base "custom" events may be added here...
 	 */
@@ -6823,8 +7456,20 @@
 	}
 	if (ds)
 		strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
-}
 
+
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "MPT event:(%02Xh) : %s\n",
+	    ioc->name, event, evStr));
+
+	devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM
+	    ": Event data:\n"));
+	for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++)
+		devtverboseprintk(ioc, printk(" %08x",
+		    le32_to_cpu(pEventReply->Data[ii])));
+	devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
+}
+#endif
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	ProcessEventNotification - Route EventNotificationReply to all event handlers
@@ -6841,37 +7486,24 @@
 {
 	u16 evDataLen;
 	u32 evData0 = 0;
-//	u32 evCtx;
 	int ii;
 	u8 cb_idx;
 	int r = 0;
 	int handlers = 0;
-	char evStr[EVENT_DESCR_STR_SZ];
 	u8 event;
 
 	/*
 	 *  Do platform normalization of values
 	 */
 	event = le32_to_cpu(pEventReply->Event) & 0xFF;
-//	evCtx = le32_to_cpu(pEventReply->EventContext);
 	evDataLen = le16_to_cpu(pEventReply->EventDataLength);
 	if (evDataLen) {
 		evData0 = le32_to_cpu(pEventReply->Data[0]);
 	}
 
-	EventDescriptionStr(event, evData0, evStr);
-	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n",
-			ioc->name,
-			event,
-			evStr));
-
 #ifdef CONFIG_FUSION_LOGGING
-	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-	    ": Event data:\n", ioc->name));
-	for (ii = 0; ii < evDataLen; ii++)
-		devtverboseprintk(ioc, printk(" %08x",
-		    le32_to_cpu(pEventReply->Data[ii])));
-	devtverboseprintk(ioc, printk("\n"));
+	if (evDataLen)
+		mpt_display_event_info(ioc, pEventReply);
 #endif
 
 	/*
@@ -6926,8 +7558,9 @@
 	 */
 	for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
 		if (MptEvHandlers[cb_idx]) {
-			devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
-					ioc->name, cb_idx));
+			devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			    "Routing Event to event handler #%d\n",
+			    ioc->name, cb_idx));
 			r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
 			handlers++;
 		}
@@ -7011,8 +7644,6 @@
 	switch (info) {
 	case 0x00010000:
 		desc = "bug! MID not found";
-		if (ioc->reload_fw == 0)
-			ioc->reload_fw++;
 		break;
 
 	case 0x00020000:
@@ -7613,7 +8244,6 @@
 EXPORT_SYMBOL(mpt_put_msg_frame);
 EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
 EXPORT_SYMBOL(mpt_free_msg_frame);
-EXPORT_SYMBOL(mpt_add_sge);
 EXPORT_SYMBOL(mpt_send_handshake_request);
 EXPORT_SYMBOL(mpt_verify_adapter);
 EXPORT_SYMBOL(mpt_GetIocState);
@@ -7650,7 +8280,7 @@
 	/*  Register ourselves (mptbase) in order to facilitate
 	 *  EventNotification handling.
 	 */
-	mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
+	mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER);
 
 	/* Register for hard reset handling callbacks.
 	 */
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptbase.h linux-libre-2.6.31-gnu/drivers/message/fusion/mptbase.h
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptbase.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptbase.h	2009-09-09 18:13:59.000000000 -0400
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2008 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.04.07"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.07"
+#define MPT_LINUX_VERSION_COMMON	"3.04.10"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.09"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -104,6 +104,7 @@
 #endif
 
 #define MPT_NAME_LENGTH			32
+#define MPT_KOBJ_NAME_LEN		20
 
 #define MPT_PROCFS_MPTBASEDIR		"mpt"
 						/* chg it to "driver/fusion" ? */
@@ -134,6 +135,7 @@
 
 #define MPT_COALESCING_TIMEOUT		0x10
 
+
 /*
  * SCSI transfer rate defines.
  */
@@ -161,10 +163,10 @@
 /*
  * Set the MAX_SGE value based on user input.
  */
-#ifdef  CONFIG_FUSION_MAX_SGE
-#if     CONFIG_FUSION_MAX_SGE  < 16
+#ifdef CONFIG_FUSION_MAX_SGE
+#if CONFIG_FUSION_MAX_SGE  < 16
 #define MPT_SCSI_SG_DEPTH	16
-#elif   CONFIG_FUSION_MAX_SGE  > 128
+#elif CONFIG_FUSION_MAX_SGE  > 128
 #define MPT_SCSI_SG_DEPTH	128
 #else
 #define MPT_SCSI_SG_DEPTH	CONFIG_FUSION_MAX_SGE
@@ -173,6 +175,18 @@
 #define MPT_SCSI_SG_DEPTH	40
 #endif
 
+#ifdef CONFIG_FUSION_MAX_FC_SGE
+#if CONFIG_FUSION_MAX_FC_SGE  < 16
+#define MPT_SCSI_FC_SG_DEPTH	16
+#elif CONFIG_FUSION_MAX_FC_SGE  > 256
+#define MPT_SCSI_FC_SG_DEPTH	256
+#else
+#define MPT_SCSI_FC_SG_DEPTH	CONFIG_FUSION_MAX_FC_SGE
+#endif
+#else
+#define MPT_SCSI_FC_SG_DEPTH	40
+#endif
+
 /* debug print string length used for events and iocstatus */
 # define EVENT_DESCR_STR_SZ             100
 
@@ -431,38 +445,36 @@
  *	IOCTL structure and associated defines
  */
 
-#define MPT_IOCTL_STATUS_DID_IOCRESET	0x01	/* IOC Reset occurred on the current*/
-#define MPT_IOCTL_STATUS_RF_VALID	0x02	/* The Reply Frame is VALID */
-#define MPT_IOCTL_STATUS_TIMER_ACTIVE	0x04	/* The timer is running */
-#define MPT_IOCTL_STATUS_SENSE_VALID	0x08	/* Sense data is valid */
-#define MPT_IOCTL_STATUS_COMMAND_GOOD	0x10	/* Command Status GOOD */
-#define MPT_IOCTL_STATUS_TMTIMER_ACTIVE	0x20	/* The TM timer is running */
-#define MPT_IOCTL_STATUS_TM_FAILED	0x40	/* User TM request failed */
-
 #define MPTCTL_RESET_OK			0x01	/* Issue Bus Reset */
 
-typedef struct _MPT_IOCTL {
-	struct _MPT_ADAPTER	*ioc;
-	u8			 ReplyFrame[MPT_DEFAULT_FRAME_SIZE];	/* reply frame data */
-	u8			 sense[MPT_SENSE_BUFFER_ALLOC];
-	int			 wait_done;	/* wake-up value for this ioc */
-	u8			 rsvd;
-	u8			 status;	/* current command status */
-	u8			 reset;		/* 1 if bus reset allowed */
-	u8			 id;		/* target for reset */
-	struct mutex		 ioctl_mutex;
-} MPT_IOCTL;
+#define MPT_MGMT_STATUS_RF_VALID	0x01	/* The Reply Frame is VALID */
+#define MPT_MGMT_STATUS_COMMAND_GOOD	0x02	/* Command Status GOOD */
+#define MPT_MGMT_STATUS_PENDING		0x04	/* command is pending */
+#define MPT_MGMT_STATUS_DID_IOCRESET	0x08	/* IOC Reset occurred
+						   on the current*/
+#define MPT_MGMT_STATUS_SENSE_VALID	0x10	/* valid sense info */
+#define MPT_MGMT_STATUS_TIMER_ACTIVE	0x20	/* obsolete */
+#define MPT_MGMT_STATUS_FREE_MF		0x40	/* free the mf from
+						   complete routine */
 
-#define MPT_SAS_MGMT_STATUS_RF_VALID	0x02	/* The Reply Frame is VALID */
-#define MPT_SAS_MGMT_STATUS_COMMAND_GOOD	0x10	/* Command Status GOOD */
-#define MPT_SAS_MGMT_STATUS_TM_FAILED	0x40	/* User TM request failed */
+#define INITIALIZE_MGMT_STATUS(status) \
+	status = MPT_MGMT_STATUS_PENDING;
+#define CLEAR_MGMT_STATUS(status) \
+	status = 0;
+#define CLEAR_MGMT_PENDING_STATUS(status) \
+	status &= ~MPT_MGMT_STATUS_PENDING;
+#define SET_MGMT_MSG_CONTEXT(msg_context, value) \
+	msg_context = value;
 
-typedef struct _MPT_SAS_MGMT {
+typedef struct _MPT_MGMT {
 	struct mutex		 mutex;
 	struct completion	 done;
 	u8			 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
+	u8			 sense[MPT_SENSE_BUFFER_ALLOC];
 	u8			 status;	/* current command status */
-}MPT_SAS_MGMT;
+	int			 completion_code;
+	u32			 msg_context;
+} MPT_MGMT;
 
 /*
  *  Event Structure and define
@@ -564,6 +576,10 @@
 	u8		flags;
 };
 
+typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);
+typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,
+		dma_addr_t dma_addr);
+
 /*
  *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
  */
@@ -573,6 +589,10 @@
 	int			 pci_irq;	/* This irq           */
 	char			 name[MPT_NAME_LENGTH];	/* "iocN"             */
 	char			 prod_name[MPT_NAME_LENGTH];	/* "LSIFC9x9"         */
+#ifdef CONFIG_FUSION_LOGGING
+	/* used in mpt_display_event_info */
+	char			 evStr[EVENT_DESCR_STR_SZ];
+#endif
 	char			 board_name[16];
 	char			 board_assembly[16];
 	char			 board_tracer[16];
@@ -600,6 +620,10 @@
 	int			 reply_depth;	/* Num Allocated reply frames */
 	int			 reply_sz;	/* Reply frame size */
 	int			 num_chain;	/* Number of chain buffers */
+	MPT_ADD_SGE              add_sge;       /* Pointer to add_sge
+						   function */
+	MPT_ADD_CHAIN		 add_chain;	/* Pointer to add_chain
+						   function */
 		/* Pool of buffers for chaining. ReqToChain
 		 * and ChainToChain track index of chain buffers.
 		 * ChainBuffer (DMA) virt/phys addresses.
@@ -640,11 +664,8 @@
 	RaidCfgData		raid_data;	/* Raid config. data */
 	SasCfgData		sas_data;	/* Sas config. data */
 	FcCfgData		fc_data;	/* Fc config. data */
-	MPT_IOCTL		*ioctl;		/* ioctl data pointer */
 	struct proc_dir_entry	*ioc_dentry;
 	struct _MPT_ADAPTER	*alt_ioc;	/* ptr to 929 bound adapter port */
-	spinlock_t		 diagLock;	/* diagnostic reset lock */
-	int			 diagPending;
 	u32			 biosVersion;	/* BIOS version from IO Unit Page 2 */
 	int			 eventTypes;	/* Event logging parameters */
 	int			 eventContext;	/* Next event context */
@@ -652,7 +673,6 @@
 	struct _mpt_ioctl_events *events;	/* pointer to event log */
 	u8			*cached_fw;	/* Pointer to FW */
 	dma_addr_t	 	cached_fw_dma;
-	struct list_head	 configQ;	/* linked list of config. requests */
 	int			 hs_reply_idx;
 #ifndef MFCNT
 	u32			 pad0;
@@ -665,9 +685,6 @@
 	IOCFactsReply_t		 facts;
 	PortFactsReply_t	 pfacts[2];
 	FCPortPage0_t		 fc_port_page0[2];
-	struct timer_list	 persist_timer;	/* persist table timer */
-	int			 persist_wait_done; /* persist completion flag */
-	u8			 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */
 	LANPage0_t		 lan_cnfg_page0;
 	LANPage1_t		 lan_cnfg_page1;
 
@@ -682,23 +699,44 @@
 	int			 aen_event_read_flag; /* flag to indicate event log was read*/
 	u8			 FirstWhoInit;
 	u8			 upload_fw;	/* If set, do a fw upload */
-	u8			 reload_fw;	/* Force a FW Reload on next reset */
 	u8			 NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */
 	u8			 pad1[4];
 	u8			 DoneCtx;
 	u8			 TaskCtx;
 	u8			 InternalCtx;
-	spinlock_t		 initializing_hba_lock;
-	int 	 		 initializing_hba_lock_flag;
 	struct list_head	 list;
 	struct net_device	*netdev;
 	struct list_head	 sas_topology;
 	struct mutex		 sas_topology_mutex;
+
+	struct workqueue_struct	*fw_event_q;
+	struct list_head	 fw_event_list;
+	spinlock_t		 fw_event_lock;
+	u8			 fw_events_off; /* if '1', then ignore events */
+	char 			 fw_event_q_name[MPT_KOBJ_NAME_LEN];
+
 	struct mutex		 sas_discovery_mutex;
 	u8			 sas_discovery_runtime;
 	u8			 sas_discovery_ignore_events;
+
+	/* port_info object for the host */
+	struct mptsas_portinfo	*hba_port_info;
+	u64			 hba_port_sas_addr;
+	u16			 hba_port_num_phy;
+	struct list_head	 sas_device_info_list;
+	struct mutex		 sas_device_info_mutex;
+	u8			 old_sas_discovery_protocal;
+	u8			 sas_discovery_quiesce_io;
 	int			 sas_index; /* index refrencing */
-	MPT_SAS_MGMT		 sas_mgmt;
+	MPT_MGMT		 sas_mgmt;
+	MPT_MGMT		 mptbase_cmds; /* for sending config pages */
+	MPT_MGMT		 internal_cmds;
+	MPT_MGMT		 taskmgmt_cmds;
+	MPT_MGMT		 ioctl_cmds;
+	spinlock_t		 taskmgmt_lock; /* diagnostic reset lock */
+	int			 taskmgmt_in_progress;
+	u8			 taskmgmt_quiesce_io;
+	u8			 ioc_reset_in_progress;
 	struct work_struct	 sas_persist_task;
 
 	struct work_struct	 fc_setup_reset_work;
@@ -707,15 +745,27 @@
 	u8			 fc_link_speed[2];
 	spinlock_t		 fc_rescan_work_lock;
 	struct work_struct	 fc_rescan_work;
-	char			 fc_rescan_work_q_name[20];
+	char			 fc_rescan_work_q_name[MPT_KOBJ_NAME_LEN];
 	struct workqueue_struct *fc_rescan_work_q;
+
+	/* driver forced bus resets count */
+	unsigned long		  hard_resets;
+	/* fw/external bus resets count */
+	unsigned long		  soft_resets;
+	/* cmd timeouts */
+	unsigned long		  timeouts;
+
 	struct scsi_cmnd	**ScsiLookup;
 	spinlock_t		  scsi_lookup_lock;
-
-	char			 reset_work_q_name[20];
+	u64			dma_mask;
+	u32			  broadcast_aen_busy;
+	char			 reset_work_q_name[MPT_KOBJ_NAME_LEN];
 	struct workqueue_struct *reset_work_q;
 	struct delayed_work	 fault_reset_work;
-	spinlock_t		 fault_reset_work_lock;
+
+	u8			sg_addr_size;
+	u8			in_rescan;
+	u8			SGE_size;
 
 } MPT_ADAPTER;
 
@@ -753,13 +803,14 @@
 	dma_addr_t	Address;
 } MptSge_t;
 
-#define mpt_addr_size() \
-	((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SGE_FLAGS_64_BIT_ADDRESSING : \
-		MPI_SGE_FLAGS_32_BIT_ADDRESSING)
 
-#define mpt_msg_flags() \
-	((sizeof(dma_addr_t) == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \
-		MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32)
+#define mpt_msg_flags(ioc) \
+	(ioc->sg_addr_size == sizeof(u64)) ?		\
+	MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : 		\
+	MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32
+
+#define MPT_SGE_FLAGS_64_BIT_ADDRESSING \
+	(MPI_SGE_FLAGS_64_BIT_ADDRESSING << MPI_SGE_FLAGS_SHIFT)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -835,22 +886,14 @@
 		/* Pool of memory for holding SCpnts before doing
 		 * OS callbacks. freeQ is the free pool.
 		 */
-	u8			  tmPending;
-	u8			  resetPending;
 	u8			  negoNvram;		/* DV disabled, nego NVRAM */
 	u8			  pad1;
-	u8                        tmState;
 	u8			  rsvd[2];
 	MPT_FRAME_HDR		 *cmdPtr;		/* Ptr to nonOS request */
 	struct scsi_cmnd	 *abortSCpnt;
 	MPT_LOCAL_REPLY		  localReply;		/* internal cmd reply struct */
-	unsigned long		  hard_resets;		/* driver forced bus resets count */
-	unsigned long		  soft_resets;		/* fw/external bus resets count */
-	unsigned long		  timeouts;		/* cmd timeouts */
 	ushort			  sel_timeout[MPT_MAX_FC_DEVICES];
 	char 			  *info_kbuf;
-	wait_queue_head_t	  scandv_waitq;
-	int			  scandv_wait_done;
 	long			  last_queue_full;
 	u16			  tm_iocstatus;
 	u16			  spi_pending;
@@ -870,21 +913,16 @@
  * Generic structure passed to the base mpt_config function.
  */
 typedef struct _x_config_parms {
-	struct list_head	 linkage;	/* linked list */
-	struct timer_list	 timer;		/* timer function for this request  */
 	union {
 		ConfigExtendedPageHeader_t	*ehdr;
 		ConfigPageHeader_t	*hdr;
 	} cfghdr;
 	dma_addr_t		 physAddr;
-	int			 wait_done;	/* wait for this request */
 	u32			 pageAddr;	/* properly formatted */
+	u16			 status;
 	u8			 action;
 	u8			 dir;
 	u8			 timeout;	/* seconds */
-	u8			 pad1;
-	u16			 status;
-	u16			 pad2;
 } CONFIGPARMS;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -909,7 +947,6 @@
 extern void	 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
 extern void	 mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
 extern void	 mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
-extern void	 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
 
 extern int	 mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
 extern int	 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
@@ -922,6 +959,12 @@
 extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 extern int	 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
+extern int	mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
+		pRaidPhysDiskPage1_t phys_disk);
+extern int	mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc,
+		u8 phys_disk_num);
+extern int	 mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
+extern void	 mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
 extern void     mpt_halt_firmware(MPT_ADAPTER *ioc);
 
 
@@ -959,7 +1002,6 @@
 #define MPT_SGE_FLAGS_END_OF_BUFFER		(0x40000000)
 #define MPT_SGE_FLAGS_LOCAL_ADDRESS		(0x08000000)
 #define MPT_SGE_FLAGS_DIRECTION			(0x04000000)
-#define MPT_SGE_FLAGS_ADDRESSING		(mpt_addr_size() << MPI_SGE_FLAGS_SHIFT)
 #define MPT_SGE_FLAGS_END_OF_LIST		(0x01000000)
 
 #define MPT_SGE_FLAGS_TRANSACTION_ELEMENT	(0x00000000)
@@ -972,14 +1014,12 @@
 	 MPT_SGE_FLAGS_END_OF_BUFFER |	\
 	 MPT_SGE_FLAGS_END_OF_LIST |	\
 	 MPT_SGE_FLAGS_SIMPLE_ELEMENT |	\
-	 MPT_SGE_FLAGS_ADDRESSING | \
 	 MPT_TRANSFER_IOC_TO_HOST)
 #define MPT_SGE_FLAGS_SSIMPLE_WRITE \
 	(MPT_SGE_FLAGS_LAST_ELEMENT |	\
 	 MPT_SGE_FLAGS_END_OF_BUFFER |	\
 	 MPT_SGE_FLAGS_END_OF_LIST |	\
 	 MPT_SGE_FLAGS_SIMPLE_ELEMENT |	\
-	 MPT_SGE_FLAGS_ADDRESSING | \
 	 MPT_TRANSFER_HOST_TO_IOC)
 
 /*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptctl.c linux-libre-2.6.31-gnu/drivers/message/fusion/mptctl.c
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptctl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptctl.c	2009-09-09 18:13:59.000000000 -0400
@@ -84,6 +84,7 @@
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
+static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS;
 
 static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
 
@@ -127,10 +128,7 @@
 		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
 		struct buflist *buflist, MPT_ADAPTER *ioc);
-static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
-static int  mptctl_bus_reset(MPT_IOCTL *ioctl);
-static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
-static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
+static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function);
 
 /*
  * Reset Handler cleanup function
@@ -183,10 +181,10 @@
 	int rc = 0;
 
 	if (nonblock) {
-		if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
+		if (!mutex_trylock(&ioc->ioctl_cmds.mutex))
 			rc = -EAGAIN;
 	} else {
-		if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
+		if (mutex_lock_interruptible(&ioc->ioctl_cmds.mutex))
 			rc = -ERESTARTSYS;
 	}
 	return rc;
@@ -202,99 +200,78 @@
 static int
 mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
 {
-	char *sense_data;
-	int sz, req_index;
-	u16 iocStatus;
-	u8 cmd;
-
-	if (req)
-		 cmd = req->u.hdr.Function;
-	else
-		return 1;
-	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tcompleting mpi function (0x%02X), req=%p, "
-	    "reply=%p\n", ioc->name,  req->u.hdr.Function, req, reply));
-
-	if (ioc->ioctl) {
-
-		if (reply==NULL) {
-
-			dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_reply() NULL Reply "
-				"Function=%x!\n", ioc->name, cmd));
-
-			ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
-			ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+	char	*sense_data;
+	int	req_index;
+	int	sz;
 
-			/* We are done, issue wake up
-	 		*/
-			ioc->ioctl->wait_done = 1;
-			wake_up (&mptctl_wait);
-			return 1;
+	if (!req)
+		return 0;
 
-		}
+	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "completing mpi function "
+	    "(0x%02X), req=%p, reply=%p\n", ioc->name,  req->u.hdr.Function,
+	    req, reply));
 
-		/* Copy the reply frame (which much exist
-		 * for non-SCSI I/O) to the IOC structure.
-		 */
-		memcpy(ioc->ioctl->ReplyFrame, reply,
-			min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
-		ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
+	/*
+	 * Handling continuation of the same reply. Processing the first
+	 * reply, and eating the other replys that come later.
+	 */
+	if (ioc->ioctl_cmds.msg_context != req->u.hdr.MsgContext)
+		goto out_continuation;
 
-		/* Set the command status to GOOD if IOC Status is GOOD
-		 * OR if SCSI I/O cmd and data underrun or recovered error.
-		 */
-		iocStatus = le16_to_cpu(reply->u.reply.IOCStatus) & MPI_IOCSTATUS_MASK;
-		if (iocStatus  == MPI_IOCSTATUS_SUCCESS)
-			ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+	ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
 
-		if (iocStatus || reply->u.reply.IOCLogInfo)
-			dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tiocstatus (0x%04X), "
-				"loginfo (0x%08X)\n", ioc->name,
-				iocStatus,
-				le32_to_cpu(reply->u.reply.IOCLogInfo)));
+	if (!reply)
+		goto out;
 
-		if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
-			(cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+	ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+	sz = min(ioc->reply_sz, 4*reply->u.reply.MsgLength);
+	memcpy(ioc->ioctl_cmds.reply, reply, sz);
 
-			if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
-				dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-					"\tscsi_status (0x%02x), scsi_state (0x%02x), "
-					"tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name,
-					reply->u.sreply.SCSIStatus,
-					reply->u.sreply.SCSIState,
-					le16_to_cpu(reply->u.sreply.TaskTag),
-					le32_to_cpu(reply->u.sreply.TransferCount)));
+	if (reply->u.reply.IOCStatus || reply->u.reply.IOCLogInfo)
+		dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "iocstatus (0x%04X), loginfo (0x%08X)\n", ioc->name,
+		    le16_to_cpu(reply->u.reply.IOCStatus),
+		    le32_to_cpu(reply->u.reply.IOCLogInfo)));
 
-			ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+	if ((req->u.hdr.Function == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+		(req->u.hdr.Function ==
+		 MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
 
-			if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
-			(iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
-			ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
-			}
-		}
+		if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
+			dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			"scsi_status (0x%02x), scsi_state (0x%02x), "
+			"tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name,
+			reply->u.sreply.SCSIStatus,
+			reply->u.sreply.SCSIState,
+			le16_to_cpu(reply->u.sreply.TaskTag),
+			le32_to_cpu(reply->u.sreply.TransferCount)));
 
-		/* Copy the sense data - if present
-		 */
-		if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
-			(reply->u.sreply.SCSIState &
-			 MPI_SCSI_STATE_AUTOSENSE_VALID)){
+		if (reply->u.sreply.SCSIState &
+			MPI_SCSI_STATE_AUTOSENSE_VALID) {
 			sz = req->u.scsireq.SenseBufferLength;
 			req_index =
 			    le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
-			sense_data =
-			    ((u8 *)ioc->sense_buf_pool +
+			sense_data = ((u8 *)ioc->sense_buf_pool +
 			     (req_index * MPT_SENSE_BUFFER_ALLOC));
-			memcpy(ioc->ioctl->sense, sense_data, sz);
-			ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
+			memcpy(ioc->ioctl_cmds.sense, sense_data, sz);
+			ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_SENSE_VALID;
 		}
+	}
 
-		if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
-			mptctl_free_tm_flags(ioc);
-
-		/* We are done, issue wake up
-		 */
-		ioc->ioctl->wait_done = 1;
-		wake_up (&mptctl_wait);
+ out:
+	/* We are done, issue wake up
+	 */
+	if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) {
+		if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT)
+			mpt_clear_taskmgmt_in_progress_flag(ioc);
+		ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
+		complete(&ioc->ioctl_cmds.done);
 	}
+
+ out_continuation:
+	if (reply && (reply->u.reply.MsgFlags &
+	    MPI_MSGFLAGS_CONTINUATION_REPLY))
+		return 0;
 	return 1;
 }
 
@@ -304,30 +281,66 @@
  * Expecting an interrupt, however timed out.
  *
  */
-static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
+static void
+mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
-	int rc = 1;
+	unsigned long flags;
 
-	if (ioctl == NULL)
-		return;
-	dctlprintk(ioctl->ioc,
-		   printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n",
-		   ioctl->ioc->name, ioctl->ioc->id));
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
+		ioc->name, __func__));
 
-	ioctl->wait_done = 0;
-	if (ioctl->reset & MPTCTL_RESET_OK)
-		rc = mptctl_bus_reset(ioctl);
+	if (mpt_fwfault_debug)
+		mpt_halt_firmware(ioc);
 
-	if (rc) {
-		/* Issue a reset for this device.
-		 * The IOC is not responding.
-		 */
-		dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
-			 ioctl->ioc->name));
-		mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	if (ioc->ioc_reset_in_progress) {
+		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+		CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
+		mpt_free_msg_frame(ioc, mf);
+		return;
 	}
-	return;
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+
+
+	if (!mptctl_bus_reset(ioc, mf->u.hdr.Function))
+		return;
+
+	/* Issue a reset for this device.
+	 * The IOC is not responding.
+	 */
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
+		 ioc->name));
+	CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
+	mpt_HardResetHandler(ioc, CAN_SLEEP);
+	mpt_free_msg_frame(ioc, mf);
+}
 
+static int
+mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+{
+	if (!mf)
+		return 0;
+
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		"TaskMgmt completed (mf=%p, mr=%p)\n",
+		ioc->name, mf, mr));
+
+	ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
+
+	if (!mr)
+		goto out;
+
+	ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+	memcpy(ioc->taskmgmt_cmds.reply, mr,
+	    min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
+ out:
+	if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
+		mpt_clear_taskmgmt_in_progress_flag(ioc);
+		ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
+		complete(&ioc->taskmgmt_cmds.done);
+		return 1;
+	}
+	return 0;
 }
 
 /* mptctl_bus_reset
@@ -335,134 +348,151 @@
  * Bus reset code.
  *
  */
-static int mptctl_bus_reset(MPT_IOCTL *ioctl)
+static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
 {
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
-	MPT_SCSI_HOST	*hd;
+	SCSITaskMgmtReply_t *pScsiTmReply;
 	int		 ii;
-	int		 retval=0;
-
-
-	ioctl->reset &= ~MPTCTL_RESET_OK;
+	int		 retval;
+	unsigned long	 timeout;
+	unsigned long	 time_count;
+	u16		 iocstatus;
 
-	if (ioctl->ioc->sh == NULL)
+	/* bus reset is only good for SCSI IO, RAID PASSTHRU */
+	if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) ||
+	    (function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
+		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
+			"TaskMgmt, not SCSI_IO!!\n", ioc->name));
 		return -EPERM;
+	}
 
-	hd = shost_priv(ioctl->ioc->sh);
-	if (hd == NULL)
+	mutex_lock(&ioc->taskmgmt_cmds.mutex);
+	if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
+		mutex_unlock(&ioc->taskmgmt_cmds.mutex);
 		return -EPERM;
+	}
 
-	/* Single threading ....
-	 */
-	if (mptctl_set_tm_flags(hd) != 0)
-		return -EPERM;
+	retval = 0;
 
 	/* Send request
 	 */
-	if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) {
-		dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt, no msg frames!!\n",
-				ioctl->ioc->name));
-
-		mptctl_free_tm_flags(ioctl->ioc);
-		return -ENOMEM;
+	mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc);
+	if (mf == NULL) {
+		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
+			"TaskMgmt, no msg frames!!\n", ioc->name));
+		mpt_clear_taskmgmt_in_progress_flag(ioc);
+		retval = -ENOMEM;
+		goto mptctl_bus_reset_done;
 	}
 
-	dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
-			ioctl->ioc->name, mf));
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
+		ioc->name, mf));
 
 	pScsiTm = (SCSITaskMgmt_t *) mf;
-	pScsiTm->TargetID = ioctl->id;
-	pScsiTm->Bus = hd->port;	/* 0 */
-	pScsiTm->ChainOffset = 0;
+	memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
-	pScsiTm->Reserved = 0;
 	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
-	pScsiTm->Reserved1 = 0;
 	pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
-
+	pScsiTm->TargetID = 0;
+	pScsiTm->Bus = 0;
+	pScsiTm->ChainOffset = 0;
+	pScsiTm->Reserved = 0;
+	pScsiTm->Reserved1 = 0;
+	pScsiTm->TaskMsgContext = 0;
 	for (ii= 0; ii < 8; ii++)
 		pScsiTm->LUN[ii] = 0;
-
 	for (ii=0; ii < 7; ii++)
 		pScsiTm->Reserved2[ii] = 0;
 
-	pScsiTm->TaskMsgContext = 0;
-	dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT
-		"mptctl_bus_reset: issued.\n", ioctl->ioc->name));
-
-	DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf);
+	switch (ioc->bus_type) {
+	case FC:
+		timeout = 40;
+		break;
+	case SAS:
+		timeout = 30;
+		break;
+	case SPI:
+	default:
+		timeout = 2;
+		break;
+	}
 
-	ioctl->wait_done=0;
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		"TaskMgmt type=%d timeout=%ld\n",
+		ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
 
-	if ((ioctl->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
-	    (ioctl->ioc->facts.MsgVersion >= MPI_VERSION_01_05))
-		mpt_put_msg_frame_hi_pri(mptctl_id, ioctl->ioc, mf);
+	INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
+	CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
+	time_count = jiffies;
+	if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
+	    (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
+		mpt_put_msg_frame_hi_pri(mptctl_taskmgmt_id, ioc, mf);
 	else {
-		retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
-			sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
+		retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc,
+		    sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP);
 		if (retval != 0) {
-			dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!"
-				" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
-				hd->ioc, mf));
+			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+				"TaskMgmt send_handshake FAILED!"
+				" (ioc %p, mf %p, rc=%d) \n", ioc->name,
+				ioc, mf, retval));
+			mpt_clear_taskmgmt_in_progress_flag(ioc);
 			goto mptctl_bus_reset_done;
 		}
 	}
 
 	/* Now wait for the command to complete */
-	ii = wait_event_timeout(mptctl_wait,
-	     ioctl->wait_done == 1,
-	     HZ*5 /* 5 second timeout */);
+	ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
+	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "TaskMgmt failed\n", ioc->name));
+		mpt_free_msg_frame(ioc, mf);
+		mpt_clear_taskmgmt_in_progress_flag(ioc);
+		if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			retval = 0;
+		else
+			retval = -1; /* return failure */
+		goto mptctl_bus_reset_done;
+	}
 
-	if(ii <=0 && (ioctl->wait_done != 1 ))  {
-		mpt_free_msg_frame(hd->ioc, mf);
-		ioctl->wait_done = 0;
+	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "TaskMgmt failed\n", ioc->name));
 		retval = -1; /* return failure */
+		goto mptctl_bus_reset_done;
 	}
 
-mptctl_bus_reset_done:
-
-	mptctl_free_tm_flags(ioctl->ioc);
-	return retval;
-}
-
-static int
-mptctl_set_tm_flags(MPT_SCSI_HOST *hd) {
-	unsigned long flags;
+	pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, "
+	    "iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, "
+	    "term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus,
+	    pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+	    le16_to_cpu(pScsiTmReply->IOCStatus),
+	    le32_to_cpu(pScsiTmReply->IOCLogInfo),
+	    pScsiTmReply->ResponseCode,
+	    le32_to_cpu(pScsiTmReply->TerminationCount)));
 
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+	iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 
-	if (hd->tmState == TM_STATE_NONE) {
-		hd->tmState = TM_STATE_IN_PROGRESS;
-		hd->tmPending = 1;
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-	} else {
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		return -EBUSY;
+	if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
+	   iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED ||
+	   iocstatus == MPI_IOCSTATUS_SUCCESS)
+		retval = 0;
+	else {
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "TaskMgmt failed\n", ioc->name));
+		retval = -1; /* return failure */
 	}
 
-	return 0;
-}
-
-static void
-mptctl_free_tm_flags(MPT_ADAPTER *ioc)
-{
-	MPT_SCSI_HOST * hd;
-	unsigned long flags;
 
-	hd = shost_priv(ioc->sh);
-	if (hd == NULL)
-		return;
-
-	spin_lock_irqsave(&ioc->FreeQlock, flags);
-
-	hd->tmState = TM_STATE_NONE;
-	hd->tmPending = 0;
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
-	return;
+ mptctl_bus_reset_done:
+	mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+	CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
+	return retval;
 }
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /* mptctl_ioc_reset
  *
@@ -473,22 +503,23 @@
 static int
 mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-	MPT_IOCTL *ioctl = ioc->ioctl;
-	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC %s_reset routed to IOCTL driver!\n", ioc->name,
-		reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
-		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
-
-	if(ioctl == NULL)
-		return 1;
-
 	switch(reset_phase) {
 	case MPT_IOC_SETUP_RESET:
-		ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
+		break;
+	case MPT_IOC_PRE_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
 		break;
 	case MPT_IOC_POST_RESET:
-		ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET;
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
+		if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->ioctl_cmds.status |= MPT_MGMT_STATUS_DID_IOCRESET;
+			complete(&ioc->ioctl_cmds.done);
+		}
 		break;
-	case MPT_IOC_PRE_RESET:
 	default:
 		break;
 	}
@@ -642,7 +673,7 @@
 	else
 		ret = -EINVAL;
 
-	mutex_unlock(&iocp->ioctl->ioctl_mutex);
+	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
 	return ret;
 }
@@ -758,6 +789,7 @@
 	int			 sge_offset = 0;
 	u16			 iocstat;
 	pFWDownloadReply_t	 ReplyMsg = NULL;
+	unsigned long		 timeleft;
 
 	if (mpt_verify_adapter(ioc, &iocp) < 0) {
 		printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
@@ -841,8 +873,9 @@
 	 *	96		8
 	 *	64		4
 	 */
-	maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t))
-			/ (sizeof(dma_addr_t) + sizeof(u32));
+	maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) -
+			sizeof(FWDownloadTCSGE_t))
+			/ iocp->SGE_size;
 	if (numfrags > maxfrags) {
 		ret = -EMLINK;
 		goto fwdl_out;
@@ -870,7 +903,7 @@
 		if (nib == 0 || nib == 3) {
 			;
 		} else if (sgIn->Address) {
-			mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
+			iocp->add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);
 			n++;
 			if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
 				printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - "
@@ -882,7 +915,7 @@
 		}
 		sgIn++;
 		bl++;
-		sgOut += (sizeof(dma_addr_t) + sizeof(u32));
+		sgOut += iocp->SGE_size;
 	}
 
 	DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags);
@@ -891,16 +924,30 @@
 	 * Finally, perform firmware download.
 	 */
 	ReplyMsg = NULL;
+	SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, dlmsg->MsgContext);
+	INITIALIZE_MGMT_STATUS(iocp->ioctl_cmds.status)
 	mpt_put_msg_frame(mptctl_id, iocp, mf);
 
 	/* Now wait for the command to complete */
-	ret = wait_event_timeout(mptctl_wait,
-	     iocp->ioctl->wait_done == 1,
-	     HZ*60);
+retry_wait:
+	timeleft = wait_for_completion_timeout(&iocp->ioctl_cmds.done, HZ*60);
+	if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		ret = -ETIME;
+		printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
+		if (iocp->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
+			mpt_free_msg_frame(iocp, mf);
+			goto fwdl_out;
+		}
+		if (!timeleft)
+			mptctl_timeout_expired(iocp, mf);
+		else
+			goto retry_wait;
+		goto fwdl_out;
+	}
 
-	if(ret <=0 && (iocp->ioctl->wait_done != 1 )) {
-	/* Now we need to reset the board */
-		mptctl_timeout_expired(iocp->ioctl);
+	if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
+		printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
+		mpt_free_msg_frame(iocp, mf);
 		ret = -ENODATA;
 		goto fwdl_out;
 	}
@@ -908,7 +955,7 @@
 	if (sgl)
 		kfree_sgl(sgl, sgl_dma, buflist, iocp);
 
-	ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
+	ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply;
 	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
 	if (iocstat == MPI_IOCSTATUS_SUCCESS) {
 		printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name);
@@ -932,6 +979,9 @@
 	return 0;
 
 fwdl_out:
+
+	CLEAR_MGMT_STATUS(iocp->ioctl_cmds.status);
+	SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, 0);
         kfree_sgl(sgl, sgl_dma, buflist, iocp);
 	return ret;
 }
@@ -1003,7 +1053,7 @@
 	 *
 	 */
 	sgl = sglbuf;
-	sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1;
+	sg_spill = ((ioc->req_sz - sge_offset)/ioc->SGE_size) - 1;
 	while (bytes_allocd < bytes) {
 		this_alloc = min(alloc_sz, bytes-bytes_allocd);
 		buflist[buflist_ent].len = this_alloc;
@@ -1024,8 +1074,9 @@
 			dma_addr_t dma_addr;
 
 			bytes_allocd += this_alloc;
-			sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc);
-			dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);
+			sgl->FlagsLength = (0x10000000|sgdir|this_alloc);
+			dma_addr = pci_map_single(ioc->pcidev,
+				buflist[buflist_ent].kptr, this_alloc, dir);
 			sgl->Address = dma_addr;
 
 			fragcnt++;
@@ -1771,7 +1822,10 @@
 	int		msgContext;
 	u16		req_idx;
 	ulong 		timeout;
+	unsigned long	timeleft;
 	struct scsi_device *sdev;
+	unsigned long	 flags;
+	u8		 function;
 
 	/* bufIn and bufOut are used for user to kernel space transfers
 	 */
@@ -1784,24 +1838,23 @@
 				__FILE__, __LINE__, iocnum);
 		return -ENODEV;
 	}
-	if (!ioc->ioctl) {
-		printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
-			"No memory available during driver init.\n",
-				__FILE__, __LINE__);
-		return -ENOMEM;
-	} else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
+
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	if (ioc->ioc_reset_in_progress) {
+		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - "
-			"Busy with IOC Reset \n", __FILE__, __LINE__);
+			"Busy with diagnostic reset\n", __FILE__, __LINE__);
 		return -EBUSY;
 	}
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 
 	/* Verify that the final request frame will not be too large.
 	 */
 	sz = karg.dataSgeOffset * 4;
 	if (karg.dataInSize > 0)
-		sz += sizeof(dma_addr_t) + sizeof(u32);
+		sz += ioc->SGE_size;
 	if (karg.dataOutSize > 0)
-		sz += sizeof(dma_addr_t) + sizeof(u32);
+		sz += ioc->SGE_size;
 
 	if (sz > ioc->req_sz) {
 		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
@@ -1827,10 +1880,12 @@
 		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
 			"Unable to read MF from mpt_ioctl_command struct @ %p\n",
 			ioc->name, __FILE__, __LINE__, mfPtr);
+		function = -1;
 		rc = -EFAULT;
 		goto done_free_mem;
 	}
 	hdr->MsgContext = cpu_to_le32(msgContext);
+	function = hdr->Function;
 
 
 	/* Verify that this request is allowed.
@@ -1838,7 +1893,7 @@
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n",
 	    ioc->name, hdr->Function, mf));
 
-	switch (hdr->Function) {
+	switch (function) {
 	case MPI_FUNCTION_IOC_FACTS:
 	case MPI_FUNCTION_PORT_FACTS:
 		karg.dataOutSize  = karg.dataInSize = 0;
@@ -1893,7 +1948,7 @@
 			}
 
 			pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
-			pScsiReq->MsgFlags |= mpt_msg_flags();
+			pScsiReq->MsgFlags |= mpt_msg_flags(ioc);
 
 
 			/* verify that app has not requested
@@ -1935,8 +1990,6 @@
 			pScsiReq->Control = cpu_to_le32(scsidir | qtag);
 			pScsiReq->DataLength = cpu_to_le32(dataSize);
 
-			ioc->ioctl->reset = MPTCTL_RESET_OK;
-			ioc->ioctl->id = pScsiReq->TargetID;
 
 		} else {
 			printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
@@ -1979,7 +2032,7 @@
 			int dataSize;
 
 			pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
-			pScsiReq->MsgFlags |= mpt_msg_flags();
+			pScsiReq->MsgFlags |= mpt_msg_flags(ioc);
 
 
 			/* verify that app has not requested
@@ -2014,8 +2067,6 @@
 			pScsiReq->Control = cpu_to_le32(scsidir | qtag);
 			pScsiReq->DataLength = cpu_to_le32(dataSize);
 
-			ioc->ioctl->reset = MPTCTL_RESET_OK;
-			ioc->ioctl->id = pScsiReq->TargetID;
 		} else {
 			printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
 				"SCSI driver is not loaded. \n",
@@ -2026,20 +2077,17 @@
 		break;
 
 	case MPI_FUNCTION_SCSI_TASK_MGMT:
-		{
-			MPT_SCSI_HOST *hd = NULL;
-			if ((ioc->sh == NULL) || ((hd = shost_priv(ioc->sh)) == NULL)) {
-				printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
-					"SCSI driver not loaded or SCSI host not found. \n",
-					ioc->name, __FILE__, __LINE__);
-				rc = -EFAULT;
-				goto done_free_mem;
-			} else if (mptctl_set_tm_flags(hd) != 0) {
-				rc = -EPERM;
-				goto done_free_mem;
-			}
-		}
+	{
+		SCSITaskMgmt_t	*pScsiTm;
+		pScsiTm = (SCSITaskMgmt_t *)mf;
+		dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			"\tTaskType=0x%x MsgFlags=0x%x "
+			"TaskMsgContext=0x%x id=%d channel=%d\n",
+			ioc->name, pScsiTm->TaskType, le32_to_cpu
+			(pScsiTm->TaskMsgContext), pScsiTm->MsgFlags,
+			pScsiTm->TargetID, pScsiTm->Bus));
 		break;
+	}
 
 	case MPI_FUNCTION_IOC_INIT:
 		{
@@ -2123,8 +2171,7 @@
 			if (karg.dataInSize > 0) {
 				flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
 						MPI_SGE_FLAGS_END_OF_BUFFER |
-						MPI_SGE_FLAGS_DIRECTION |
-						mpt_addr_size() )
+						MPI_SGE_FLAGS_DIRECTION)
 						<< MPI_SGE_FLAGS_SHIFT;
 			} else {
 				flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
@@ -2141,8 +2188,8 @@
 				/* Set up this SGE.
 				 * Copy to MF and to sglbuf
 				 */
-				mpt_add_sge(psge, flagsLength, dma_addr_out);
-				psge += (sizeof(u32) + sizeof(dma_addr_t));
+				ioc->add_sge(psge, flagsLength, dma_addr_out);
+				psge += ioc->SGE_size;
 
 				/* Copy user data to kernel space.
 				 */
@@ -2175,18 +2222,25 @@
 				/* Set up this SGE
 				 * Copy to MF and to sglbuf
 				 */
-				mpt_add_sge(psge, flagsLength, dma_addr_in);
+				ioc->add_sge(psge, flagsLength, dma_addr_in);
 			}
 		}
 	} else  {
 		/* Add a NULL SGE
 		 */
-		mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
+		ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
 	}
 
-	ioc->ioctl->wait_done = 0;
+	SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, hdr->MsgContext);
+	INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
 	if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
 
+		mutex_lock(&ioc->taskmgmt_cmds.mutex);
+		if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
+			mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+			goto done_free_mem;
+		}
+
 		DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
 
 		if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
@@ -2197,10 +2251,11 @@
 				sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
 			if (rc != 0) {
 				dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				    "_send_handshake FAILED! (ioc %p, mf %p)\n",
+				    "send_handshake FAILED! (ioc %p, mf %p)\n",
 				    ioc->name, ioc, mf));
-				mptctl_free_tm_flags(ioc);
+				mpt_clear_taskmgmt_in_progress_flag(ioc);
 				rc = -ENODATA;
+				mutex_unlock(&ioc->taskmgmt_cmds.mutex);
 				goto done_free_mem;
 			}
 		}
@@ -2210,36 +2265,47 @@
 
 	/* Now wait for the command to complete */
 	timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
-	timeout = wait_event_timeout(mptctl_wait,
-	     ioc->ioctl->wait_done == 1,
-	     HZ*timeout);
-
-	if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
-	/* Now we need to reset the board */
-
-		if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
-			mptctl_free_tm_flags(ioc);
-
-		mptctl_timeout_expired(ioc->ioctl);
-		rc = -ENODATA;
+retry_wait:
+	timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
+				HZ*timeout);
+	if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		rc = -ETIME;
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: TIMED OUT!\n",
+		    ioc->name, __func__));
+		if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
+			if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
+				mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+			goto done_free_mem;
+		}
+		if (!timeleft) {
+			if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
+				mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+			mptctl_timeout_expired(ioc, mf);
+			mf = NULL;
+		} else
+			goto retry_wait;
 		goto done_free_mem;
 	}
 
+	if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
+		mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+
+
 	mf = NULL;
 
 	/* If a valid reply frame, copy to the user.
 	 * Offset 2: reply length in U32's
 	 */
-	if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+	if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
 		if (karg.maxReplyBytes < ioc->reply_sz) {
-			 sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
+			sz = min(karg.maxReplyBytes,
+				4*ioc->ioctl_cmds.reply[2]);
 		} else {
-			 sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
+			 sz = min(ioc->reply_sz, 4*ioc->ioctl_cmds.reply[2]);
 		}
-
 		if (sz > 0) {
 			if (copy_to_user(karg.replyFrameBufPtr,
-				 &ioc->ioctl->ReplyFrame, sz)){
+				 ioc->ioctl_cmds.reply, sz)){
 				 printk(MYIOC_s_ERR_FMT
 				     "%s@%d::mptctl_do_mpt_command - "
 				 "Unable to write out reply frame %p\n",
@@ -2252,10 +2318,11 @@
 
 	/* If valid sense data, copy to user.
 	 */
-	if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
+	if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_SENSE_VALID) {
 		sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
 		if (sz > 0) {
-			if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
+			if (copy_to_user(karg.senseDataPtr,
+				ioc->ioctl_cmds.sense, sz)) {
 				printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
 				"Unable to write sense data to user %p\n",
 				ioc->name, __FILE__, __LINE__,
@@ -2269,7 +2336,7 @@
 	/* If the overall status is _GOOD and data in, copy data
 	 * to user.
 	 */
-	if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
+	if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD) &&
 				(karg.dataInSize > 0) && (bufIn.kptr)) {
 
 		if (copy_to_user(karg.dataInBufPtr,
@@ -2284,9 +2351,8 @@
 
 done_free_mem:
 
-	ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
-		MPT_IOCTL_STATUS_SENSE_VALID |
-		MPT_IOCTL_STATUS_RF_VALID );
+	CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
+	SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
 
 	/* Free the allocated memory.
 	 */
@@ -2336,6 +2402,8 @@
 	ToolboxIstwiReadWriteRequest_t	*IstwiRWRequest;
 	MPT_FRAME_HDR		*mf = NULL;
 	MPIHeader_t		*mpi_hdr;
+	unsigned long		timeleft;
+	int			retval;
 
 	/* Reset long to int. Should affect IA64 and SPARC only
 	 */
@@ -2466,9 +2534,9 @@
 		MPT_SCSI_HOST *hd =  shost_priv(ioc->sh);
 
 		if (hd && (cim_rev == 1)) {
-			karg.hard_resets = hd->hard_resets;
-			karg.soft_resets = hd->soft_resets;
-			karg.timeouts = hd->timeouts;
+			karg.hard_resets = ioc->hard_resets;
+			karg.soft_resets = ioc->soft_resets;
+			karg.timeouts = ioc->timeouts;
 		}
 	}
 
@@ -2476,8 +2544,8 @@
 	 * Gather ISTWI(Industry Standard Two Wire Interface) Data
 	 */
 	if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
-		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
-		    ioc->name,__func__));
+		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
+			"%s, no msg frames!!\n", ioc->name, __func__));
 		goto out;
 	}
 
@@ -2498,22 +2566,29 @@
 	pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
 	if (!pbuf)
 		goto out;
-	mpt_add_sge((char *)&IstwiRWRequest->SGL,
+	ioc->add_sge((char *)&IstwiRWRequest->SGL,
 	    (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
 
-	ioc->ioctl->wait_done = 0;
+	retval = 0;
+	SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
+				IstwiRWRequest->MsgContext);
+	INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
 	mpt_put_msg_frame(mptctl_id, ioc, mf);
 
-	rc = wait_event_timeout(mptctl_wait,
-	     ioc->ioctl->wait_done == 1,
-	     HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */);
-
-	if(rc <=0 && (ioc->ioctl->wait_done != 1 )) {
-		/*
-		 * Now we need to reset the board
-		 */
-		mpt_free_msg_frame(ioc, mf);
-		mptctl_timeout_expired(ioc->ioctl);
+retry_wait:
+	timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
+			HZ*MPT_IOCTL_DEFAULT_TIMEOUT);
+	if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		retval = -ETIME;
+		printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name, __func__);
+		if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
+			mpt_free_msg_frame(ioc, mf);
+			goto out;
+		}
+		if (!timeleft)
+			mptctl_timeout_expired(ioc, mf);
+		else
+			goto retry_wait;
 		goto out;
 	}
 
@@ -2526,10 +2601,13 @@
 	 *   bays have drives in them
 	 * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3)
 	 */
-	if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID)
+	if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)
 		karg.rsvd = *(u32 *)pbuf;
 
  out:
+	CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
+	SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
+
 	if (pbuf)
 		pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
 
@@ -2753,7 +2831,7 @@
 
 	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
-	mutex_unlock(&iocp->ioctl->ioctl_mutex);
+	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
 	return ret;
 }
@@ -2807,7 +2885,7 @@
 	 */
 	ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
-	mutex_unlock(&iocp->ioctl->ioctl_mutex);
+	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
 	return ret;
 }
@@ -2859,21 +2937,10 @@
 static int
 mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	MPT_IOCTL *mem;
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
-	/*
-	 * Allocate and inite a MPT_IOCTL structure
-	*/
-	mem = kzalloc(sizeof(MPT_IOCTL), GFP_KERNEL);
-	if (!mem) {
-		mptctl_remove(pdev);
-		return -ENOMEM;
-	}
-
-	ioc->ioctl = mem;
-	ioc->ioctl->ioc = ioc;
-	mutex_init(&ioc->ioctl->ioctl_mutex);
+	mutex_init(&ioc->ioctl_cmds.mutex);
+	init_completion(&ioc->ioctl_cmds.done);
 	return 0;
 }
 
@@ -2887,9 +2954,6 @@
 static void
 mptctl_remove(struct pci_dev *pdev)
 {
-	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
-
-	kfree ( ioc->ioctl );
 }
 
 static struct mpt_pci_driver mptctl_driver = {
@@ -2929,6 +2993,7 @@
 		goto out_fail;
 	}
 
+	mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER);
 	mpt_reset_register(mptctl_id, mptctl_ioc_reset);
 	mpt_event_register(mptctl_id, mptctl_event_process);
 
@@ -2953,6 +3018,7 @@
 
 	/* De-register callback handler from base module */
 	mpt_deregister(mptctl_id);
+	mpt_reset_deregister(mptctl_taskmgmt_id);
 
         mpt_device_driver_deregister(MPTCTL_DRIVER);
 
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptdebug.h linux-libre-2.6.31-gnu/drivers/message/fusion/mptdebug.h
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptdebug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptdebug.h	2009-09-09 18:13:59.000000000 -0400
@@ -58,6 +58,7 @@
 #define MPT_DEBUG_FC			0x00080000
 #define MPT_DEBUG_SAS			0x00100000
 #define MPT_DEBUG_SAS_WIDE		0x00200000
+#define MPT_DEBUG_36GB_MEM              0x00400000
 
 /*
  * CONFIG_FUSION_LOGGING - enabled in Kconfig
@@ -135,6 +136,8 @@
 #define dsaswideprintk(IOC, CMD)		\
 	MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
 
+#define d36memprintk(IOC, CMD)		\
+	MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_36GB_MEM)
 
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptfc.c linux-libre-2.6.31-gnu/drivers/message/fusion/mptfc.c
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptfc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptfc.c	2009-09-09 18:13:59.000000000 -0400
@@ -1251,17 +1251,15 @@
 	 * A slightly different algorithm is required for
 	 * 64bit SGEs.
 	 */
-	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
+	scale = ioc->req_sz/ioc->SGE_size;
+	if (ioc->sg_addr_size == sizeof(u64)) {
 		numSGE = (scale - 1) *
 		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
+		  (ioc->req_sz - 60) / ioc->SGE_size;
 	} else {
 		numSGE = 1 + (scale - 1) *
 		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
+		  (ioc->req_sz - 64) / ioc->SGE_size;
 	}
 
 	if (numSGE < sh->sg_tablesize) {
@@ -1292,9 +1290,6 @@
 
 	/* Clear the TM flags
 	 */
-	hd->tmPending = 0;
-	hd->tmState = TM_STATE_NONE;
-	hd->resetPending = 0;
 	hd->abortSCpnt = NULL;
 
 	/* Clear the pointer used to store
@@ -1312,8 +1307,6 @@
 	hd->timer.data = (unsigned long) hd;
 	hd->timer.function = mptscsih_timer_expired;
 
-	init_waitqueue_head(&hd->scandv_waitq);
-	hd->scandv_wait_done = 0;
 	hd->last_queue_full = 0;
 
 	sh->transportt = mptfc_transport_template;
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptlan.c linux-libre-2.6.31-gnu/drivers/message/fusion/mptlan.c
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptlan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptlan.c	2009-09-09 18:13:59.000000000 -0400
@@ -703,7 +703,7 @@
 
 		printk (KERN_ERR "%s: no tx context available: %u\n",
 			__func__, priv->mpt_txfidx_tail);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	mf = mpt_get_msg_frame(LanCtx, mpt_dev);
@@ -713,7 +713,7 @@
 
 		printk (KERN_ERR "%s: Unable to alloc request frame\n",
 			__func__);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--];
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptsas.c linux-libre-2.6.31-gnu/drivers/message/fusion/mptsas.c
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptsas.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptsas.c	2009-09-09 18:13:59.000000000 -0400
@@ -93,8 +93,37 @@
 static u8	mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
 static u8	mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
 static u8	mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
+static u8	mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
 
-static void mptsas_hotplug_work(struct work_struct *work);
+static void mptsas_firmware_event_work(struct work_struct *work);
+static void mptsas_send_sas_event(struct fw_event_work *fw_event);
+static void mptsas_send_raid_event(struct fw_event_work *fw_event);
+static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
+static void mptsas_parse_device_info(struct sas_identify *identify,
+		struct mptsas_devinfo *device_info);
+static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
+		struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
+static struct mptsas_phyinfo	*mptsas_find_phyinfo_by_sas_address
+		(MPT_ADAPTER *ioc, u64 sas_address);
+static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
+	struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
+static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
+	struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
+static int mptsas_add_end_device(MPT_ADAPTER *ioc,
+	struct mptsas_phyinfo *phy_info);
+static void mptsas_del_end_device(MPT_ADAPTER *ioc,
+	struct mptsas_phyinfo *phy_info);
+static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
+static struct mptsas_portinfo	*mptsas_find_portinfo_by_sas_address
+		(MPT_ADAPTER *ioc, u64 sas_address);
+static void mptsas_expander_delete(MPT_ADAPTER *ioc,
+		struct mptsas_portinfo *port_info, u8 force);
+static void mptsas_send_expander_event(struct fw_event_work *fw_event);
+static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
+static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
+static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event);
+static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
+static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
 
 static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
 					MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@@ -218,30 +247,125 @@
 	    le16_to_cpu(pg1->AttachedDevHandle)));
 }
 
-static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
+/* inhibit sas firmware event handling */
+static void
+mptsas_fw_event_off(MPT_ADAPTER *ioc)
 {
-	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
-	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioc->fw_event_lock, flags);
+	ioc->fw_events_off = 1;
+	ioc->sas_discovery_quiesce_io = 0;
+	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+
 }
 
-static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
+/* enable sas firmware event handling */
+static void
+mptsas_fw_event_on(MPT_ADAPTER *ioc)
 {
-	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
-	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioc->fw_event_lock, flags);
+	ioc->fw_events_off = 0;
+	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
 
-static struct mptsas_portinfo *
-mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
+/* queue a sas firmware event */
+static void
+mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
+    unsigned long delay)
 {
-	struct list_head	*head = &ioc->sas_topology;
-	struct mptsas_portinfo	*pi = NULL;
+	unsigned long flags;
 
-	/* always the first entry on sas_topology list */
+	spin_lock_irqsave(&ioc->fw_event_lock, flags);
+	list_add_tail(&fw_event->list, &ioc->fw_event_list);
+	INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
+	    ioc->name, __func__, fw_event));
+	queue_delayed_work(ioc->fw_event_q, &fw_event->work,
+	    delay);
+	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
 
-	if (!list_empty(head))
-		pi = list_entry(head->next, struct mptsas_portinfo, list);
+/* requeue a sas firmware event */
+static void
+mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
+    unsigned long delay)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&ioc->fw_event_lock, flags);
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
+	    "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
+	fw_event->retries++;
+	queue_delayed_work(ioc->fw_event_q, &fw_event->work,
+	    msecs_to_jiffies(delay));
+	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
 
-	return pi;
+/* free memory assoicated to a sas firmware event */
+static void
+mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioc->fw_event_lock, flags);
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
+	    ioc->name, __func__, fw_event));
+	list_del(&fw_event->list);
+	kfree(fw_event);
+	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/* walk the firmware event queue, and either stop or wait for
+ * outstanding events to complete */
+static void
+mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
+{
+	struct fw_event_work *fw_event, *next;
+	struct mptsas_target_reset_event *target_reset_list, *n;
+	u8	flush_q;
+	MPT_SCSI_HOST	*hd = shost_priv(ioc->sh);
+
+	/* flush the target_reset_list */
+	if (!list_empty(&hd->target_reset_list)) {
+		list_for_each_entry_safe(target_reset_list, n,
+		    &hd->target_reset_list, list) {
+			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			    "%s: removing target reset for id=%d\n",
+			    ioc->name, __func__,
+			   target_reset_list->sas_event_data.TargetID));
+			list_del(&target_reset_list->list);
+			kfree(target_reset_list);
+		}
+	}
+
+	if (list_empty(&ioc->fw_event_list) ||
+	     !ioc->fw_event_q || in_interrupt())
+		return;
+
+	flush_q = 0;
+	list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
+		if (cancel_delayed_work(&fw_event->work))
+			mptsas_free_fw_event(ioc, fw_event);
+		else
+			flush_q = 1;
+	}
+	if (flush_q)
+		flush_workqueue(ioc->fw_event_q);
+}
+
+
+static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
+{
+	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
+}
+
+static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
+{
+	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
+	return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
 }
 
 /*
@@ -265,6 +389,38 @@
 	return rc;
 }
 
+/**
+ *	mptsas_find_portinfo_by_sas_address -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@handle:
+ *
+ *	This function should be called with the sas_topology_mutex already held
+ *
+ **/
+static struct mptsas_portinfo *
+mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
+{
+	struct mptsas_portinfo *port_info, *rc = NULL;
+	int i;
+
+	if (sas_address >= ioc->hba_port_sas_addr &&
+	    sas_address < (ioc->hba_port_sas_addr +
+	    ioc->hba_port_num_phy))
+		return ioc->hba_port_info;
+
+	mutex_lock(&ioc->sas_topology_mutex);
+	list_for_each_entry(port_info, &ioc->sas_topology, list)
+		for (i = 0; i < port_info->num_phys; i++)
+			if (port_info->phy_info[i].identify.sas_address ==
+			    sas_address) {
+				rc = port_info;
+				goto out;
+			}
+ out:
+	mutex_unlock(&ioc->sas_topology_mutex);
+	return rc;
+}
+
 /*
  * Returns true if there is a scsi end device
  */
@@ -308,6 +464,7 @@
 		if(phy_info->port_details != port_details)
 			continue;
 		memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
+		mptsas_set_rphy(ioc, phy_info, NULL);
 		phy_info->port_details = NULL;
 	}
 	kfree(port_details);
@@ -379,6 +536,285 @@
 		phy_info->port_details->starget = starget;
 }
 
+/**
+ *	mptsas_add_device_component -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@channel: fw mapped id's
+ *	@id:
+ *	@sas_address:
+ *	@device_info:
+ *
+ **/
+static void
+mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
+	u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
+{
+	struct mptsas_device_info	*sas_info, *next;
+	struct scsi_device	*sdev;
+	struct scsi_target	*starget;
+	struct sas_rphy	*rphy;
+
+	/*
+	 * Delete all matching devices out of the list
+	 */
+	mutex_lock(&ioc->sas_device_info_mutex);
+	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
+	    list) {
+		if (!sas_info->is_logical_volume &&
+		    (sas_info->sas_address == sas_address ||
+		    (sas_info->fw.channel == channel &&
+		     sas_info->fw.id == id))) {
+			list_del(&sas_info->list);
+			kfree(sas_info);
+		}
+	}
+
+	sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
+	if (!sas_info)
+		goto out;
+
+	/*
+	 * Set Firmware mapping
+	 */
+	sas_info->fw.id = id;
+	sas_info->fw.channel = channel;
+
+	sas_info->sas_address = sas_address;
+	sas_info->device_info = device_info;
+	sas_info->slot = slot;
+	sas_info->enclosure_logical_id = enclosure_logical_id;
+	INIT_LIST_HEAD(&sas_info->list);
+	list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
+
+	/*
+	 * Set OS mapping
+	 */
+	shost_for_each_device(sdev, ioc->sh) {
+		starget = scsi_target(sdev);
+		rphy = dev_to_rphy(starget->dev.parent);
+		if (rphy->identify.sas_address == sas_address) {
+			sas_info->os.id = starget->id;
+			sas_info->os.channel = starget->channel;
+		}
+	}
+
+ out:
+	mutex_unlock(&ioc->sas_device_info_mutex);
+	return;
+}
+
+/**
+ *	mptsas_add_device_component_by_fw -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@channel:  fw mapped id's
+ *	@id:
+ *
+ **/
+static void
+mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	struct mptsas_devinfo sas_device;
+	struct mptsas_enclosure enclosure_info;
+	int rc;
+
+	rc = mptsas_sas_device_pg0(ioc, &sas_device,
+	    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+	     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+	    (channel << 8) + id);
+	if (rc)
+		return;
+
+	memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
+	mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
+	    (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
+	     MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
+	     sas_device.handle_enclosure);
+
+	mptsas_add_device_component(ioc, sas_device.channel,
+	    sas_device.id, sas_device.sas_address, sas_device.device_info,
+	    sas_device.slot, enclosure_info.enclosure_logical_id);
+}
+
+/**
+ *	mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@channel: fw mapped id's
+ *	@id:
+ *
+ **/
+static void
+mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
+		struct scsi_target *starget)
+{
+	CONFIGPARMS			cfg;
+	ConfigPageHeader_t		hdr;
+	dma_addr_t			dma_handle;
+	pRaidVolumePage0_t		buffer = NULL;
+	int				i;
+	RaidPhysDiskPage0_t 		phys_disk;
+	struct mptsas_device_info	*sas_info, *next;
+
+	memset(&cfg, 0 , sizeof(CONFIGPARMS));
+	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
+	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+	/* assumption that all volumes on channel = 0 */
+	cfg.pageAddr = starget->id;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.timeout = 10;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!hdr.PageLength)
+		goto out;
+
+	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
+	    &dma_handle);
+
+	if (!buffer)
+		goto out;
+
+	cfg.physAddr = dma_handle;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+	if (mpt_config(ioc, &cfg) != 0)
+		goto out;
+
+	if (!buffer->NumPhysDisks)
+		goto out;
+
+	/*
+	 * Adding entry for hidden components
+	 */
+	for (i = 0; i < buffer->NumPhysDisks; i++) {
+
+		if (mpt_raid_phys_disk_pg0(ioc,
+		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+			continue;
+
+		mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
+		    phys_disk.PhysDiskID);
+
+		mutex_lock(&ioc->sas_device_info_mutex);
+		list_for_each_entry(sas_info, &ioc->sas_device_info_list,
+		    list) {
+			if (!sas_info->is_logical_volume &&
+			    (sas_info->fw.channel == phys_disk.PhysDiskBus &&
+			    sas_info->fw.id == phys_disk.PhysDiskID)) {
+				sas_info->is_hidden_raid_component = 1;
+				sas_info->volume_id = starget->id;
+			}
+		}
+		mutex_unlock(&ioc->sas_device_info_mutex);
+
+	}
+
+	/*
+	 * Delete all matching devices out of the list
+	 */
+	mutex_lock(&ioc->sas_device_info_mutex);
+	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
+	    list) {
+		if (sas_info->is_logical_volume && sas_info->fw.id ==
+		    starget->id) {
+			list_del(&sas_info->list);
+			kfree(sas_info);
+		}
+	}
+
+	sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
+	if (sas_info) {
+		sas_info->fw.id = starget->id;
+		sas_info->os.id = starget->id;
+		sas_info->os.channel = starget->channel;
+		sas_info->is_logical_volume = 1;
+		INIT_LIST_HEAD(&sas_info->list);
+		list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
+	}
+	mutex_unlock(&ioc->sas_device_info_mutex);
+
+ out:
+	if (buffer)
+		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
+		    dma_handle);
+}
+
+/**
+ *	mptsas_add_device_component_starget -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@starget:
+ *
+ **/
+static void
+mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
+	struct scsi_target *starget)
+{
+	VirtTarget	*vtarget;
+	struct sas_rphy	*rphy;
+	struct mptsas_phyinfo	*phy_info = NULL;
+	struct mptsas_enclosure	enclosure_info;
+
+	rphy = dev_to_rphy(starget->dev.parent);
+	vtarget = starget->hostdata;
+	phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+			rphy->identify.sas_address);
+	if (!phy_info)
+		return;
+
+	memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
+	mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
+		(MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
+		MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
+		phy_info->attached.handle_enclosure);
+
+	mptsas_add_device_component(ioc, phy_info->attached.channel,
+		phy_info->attached.id, phy_info->attached.sas_address,
+		phy_info->attached.device_info,
+		phy_info->attached.slot, enclosure_info.enclosure_logical_id);
+}
+
+/**
+ *	mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@channel: os mapped id's
+ *	@id:
+ *
+ **/
+static void
+mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
+{
+	struct mptsas_device_info	*sas_info, *next;
+
+	/*
+	 * Set is_cached flag
+	 */
+	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
+		list) {
+		if (sas_info->os.channel == channel && sas_info->os.id == id)
+			sas_info->is_cached = 1;
+	}
+}
+
+/**
+ *	mptsas_del_device_components - Cleaning the list
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ **/
+static void
+mptsas_del_device_components(MPT_ADAPTER *ioc)
+{
+	struct mptsas_device_info	*sas_info, *next;
+
+	mutex_lock(&ioc->sas_device_info_mutex);
+	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
+		list) {
+		list_del(&sas_info->list);
+		kfree(sas_info);
+	}
+	mutex_unlock(&ioc->sas_device_info_mutex);
+}
+
 
 /*
  * mptsas_setup_wide_ports
@@ -434,8 +870,8 @@
 		 * Forming a port
 		 */
 		if (!port_details) {
-			port_details = kzalloc(sizeof(*port_details),
-				GFP_KERNEL);
+			port_details = kzalloc(sizeof(struct
+				mptsas_portinfo_details), GFP_KERNEL);
 			if (!port_details)
 				goto out;
 			port_details->num_phys = 1;
@@ -523,15 +959,62 @@
 	VirtTarget 			*vtarget = NULL;
 
 	shost_for_each_device(sdev, ioc->sh) {
-		if ((vdevice = sdev->hostdata) == NULL)
+		vdevice = sdev->hostdata;
+		if ((vdevice == NULL) ||
+			(vdevice->vtarget == NULL))
+			continue;
+		if ((vdevice->vtarget->tflags &
+		    MPT_TARGET_FLAGS_RAID_COMPONENT ||
+		    vdevice->vtarget->raidVolume))
 			continue;
 		if (vdevice->vtarget->id == id &&
-		    vdevice->vtarget->channel == channel)
+			vdevice->vtarget->channel == channel)
 			vtarget = vdevice->vtarget;
 	}
 	return vtarget;
 }
 
+static void
+mptsas_queue_device_delete(MPT_ADAPTER *ioc,
+	MpiEventDataSasDeviceStatusChange_t *sas_event_data)
+{
+	struct fw_event_work *fw_event;
+	int sz;
+
+	sz = offsetof(struct fw_event_work, event_data) +
+	    sizeof(MpiEventDataSasDeviceStatusChange_t);
+	fw_event = kzalloc(sz, GFP_ATOMIC);
+	if (!fw_event) {
+		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
+		    ioc->name, __func__, __LINE__);
+		return;
+	}
+	memcpy(fw_event->event_data, sas_event_data,
+	    sizeof(MpiEventDataSasDeviceStatusChange_t));
+	fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
+	fw_event->ioc = ioc;
+	mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
+}
+
+static void
+mptsas_queue_rescan(MPT_ADAPTER *ioc)
+{
+	struct fw_event_work *fw_event;
+	int sz;
+
+	sz = offsetof(struct fw_event_work, event_data);
+	fw_event = kzalloc(sz, GFP_ATOMIC);
+	if (!fw_event) {
+		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
+		    ioc->name, __func__, __LINE__);
+		return;
+	}
+	fw_event->event = -1;
+	fw_event->ioc = ioc;
+	mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
+}
+
+
 /**
  * mptsas_target_reset
  *
@@ -550,13 +1033,21 @@
 {
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
-
-	if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
-		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
-		    ioc->name,__func__, __LINE__));
+	if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
 		return 0;
+
+
+	mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
+	if (mf == NULL) {
+		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
+			"%s, no msg frames @%d!!\n", ioc->name,
+			__func__, __LINE__));
+		goto out_fail;
 	}
 
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
+		ioc->name, mf));
+
 	/* Format the Request
 	 */
 	pScsiTm = (SCSITaskMgmt_t *) mf;
@@ -569,9 +1060,18 @@
 
 	DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
 
-	mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	   "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
+	   ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
+
+	mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
 
 	return 1;
+
+ out_fail:
+
+	mpt_clear_taskmgmt_in_progress_flag(ioc);
+	return 0;
 }
 
 /**
@@ -602,11 +1102,12 @@
 
 	vtarget->deleted = 1; /* block IO */
 
-	target_reset_list = kzalloc(sizeof(*target_reset_list),
+	target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
 	    GFP_ATOMIC);
 	if (!target_reset_list) {
-		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
-		    ioc->name,__func__, __LINE__));
+		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
+			"%s, failed to allocate mem @%d..!!\n",
+			ioc->name, __func__, __LINE__));
 		return;
 	}
 
@@ -614,84 +1115,101 @@
 		sizeof(*sas_event_data));
 	list_add_tail(&target_reset_list->list, &hd->target_reset_list);
 
-	if (hd->resetPending)
-		return;
+	target_reset_list->time_count = jiffies;
 
 	if (mptsas_target_reset(ioc, channel, id)) {
 		target_reset_list->target_reset_issued = 1;
-		hd->resetPending = 1;
 	}
 }
 
 /**
- * mptsas_dev_reset_complete
- *
- * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
- * enable work queue to finish off removing device from upper layers.
- * then send next TARGET_RESET in the queue.
- *
- * @ioc
+ *	mptsas_taskmgmt_complete - complete SAS task management function
+ *	@ioc: Pointer to MPT_ADAPTER structure
  *
+ *	Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work
+ *	queue to finish off removing device from upper layers. then send next
+ *	TARGET_RESET in the queue.
  **/
-static void
-mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
+static int
+mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
 	MPT_SCSI_HOST	*hd = shost_priv(ioc->sh);
         struct list_head *head = &hd->target_reset_list;
-	struct mptsas_target_reset_event *target_reset_list;
-	struct mptsas_hotplug_event *ev;
-	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
 	u8		id, channel;
-	__le64		sas_address;
+	struct mptsas_target_reset_event	*target_reset_list;
+	SCSITaskMgmtReply_t *pScsiTmReply;
+
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
+	    "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
+
+	pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
+	if (pScsiTmReply) {
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
+		    "\ttask_type = 0x%02X, iocstatus = 0x%04X "
+		    "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
+		    "term_cmnds = %d\n", ioc->name,
+		    pScsiTmReply->Bus, pScsiTmReply->TargetID,
+		    pScsiTmReply->TaskType,
+		    le16_to_cpu(pScsiTmReply->IOCStatus),
+		    le32_to_cpu(pScsiTmReply->IOCLogInfo),
+		    pScsiTmReply->ResponseCode,
+		    le32_to_cpu(pScsiTmReply->TerminationCount)));
+
+		if (pScsiTmReply->ResponseCode)
+			mptscsih_taskmgmt_response_code(ioc,
+			pScsiTmReply->ResponseCode);
+	}
+
+	if (pScsiTmReply && (pScsiTmReply->TaskType ==
+	    MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
+	     MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
+		ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
+		ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+		memcpy(ioc->taskmgmt_cmds.reply, mr,
+		    min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
+		if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
+			complete(&ioc->taskmgmt_cmds.done);
+			return 1;
+		}
+		return 0;
+	}
+
+	mpt_clear_taskmgmt_in_progress_flag(ioc);
 
 	if (list_empty(head))
-		return;
+		return 1;
 
-	target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
+	target_reset_list = list_entry(head->next,
+	    struct mptsas_target_reset_event, list);
 
-	sas_event_data = &target_reset_list->sas_event_data;
-	id = sas_event_data->TargetID;
-	channel = sas_event_data->Bus;
-	hd->resetPending = 0;
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "TaskMgmt: completed (%d seconds)\n",
+	    ioc->name, jiffies_to_msecs(jiffies -
+	    target_reset_list->time_count)/1000));
+
+	id = pScsiTmReply->TargetID;
+	channel = pScsiTmReply->Bus;
+	target_reset_list->time_count = jiffies;
 
 	/*
 	 * retry target reset
 	 */
 	if (!target_reset_list->target_reset_issued) {
-		if (mptsas_target_reset(ioc, channel, id)) {
+		if (mptsas_target_reset(ioc, channel, id))
 			target_reset_list->target_reset_issued = 1;
-			hd->resetPending = 1;
-		}
-		return;
+		return 1;
 	}
 
 	/*
 	 * enable work queue to remove device from upper layers
 	 */
 	list_del(&target_reset_list->list);
+	if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off)
+		mptsas_queue_device_delete(ioc,
+			&target_reset_list->sas_event_data);
 
-	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-	if (!ev) {
-		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
-		    ioc->name,__func__, __LINE__));
-		return;
-	}
-
-	INIT_WORK(&ev->work, mptsas_hotplug_work);
-	ev->ioc = ioc;
-	ev->handle = le16_to_cpu(sas_event_data->DevHandle);
-	ev->parent_handle =
-	    le16_to_cpu(sas_event_data->ParentDevHandle);
-	ev->channel = channel;
-	ev->id =id;
-	ev->phy_id = sas_event_data->PhyNum;
-	memcpy(&sas_address, &sas_event_data->SASAddress,
-	    sizeof(__le64));
-	ev->sas_address = le64_to_cpu(sas_address);
-	ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
-	ev->event_type = MPTSAS_DEL_DEVICE;
-	schedule_work(&ev->work);
-	kfree(target_reset_list);
 
 	/*
 	 * issue target reset to next device in the queue
@@ -699,34 +1217,19 @@
 
 	head = &hd->target_reset_list;
 	if (list_empty(head))
-		return;
+		return 1;
 
 	target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
 	    list);
 
-	sas_event_data = &target_reset_list->sas_event_data;
-	id = sas_event_data->TargetID;
-	channel = sas_event_data->Bus;
+	id = target_reset_list->sas_event_data.TargetID;
+	channel = target_reset_list->sas_event_data.Bus;
+	target_reset_list->time_count = jiffies;
 
-	if (mptsas_target_reset(ioc, channel, id)) {
+	if (mptsas_target_reset(ioc, channel, id))
 		target_reset_list->target_reset_issued = 1;
-		hd->resetPending = 1;
-	}
-}
 
-/**
- * mptsas_taskmgmt_complete
- *
- * @ioc
- * @mf
- * @mr
- *
- **/
-static int
-mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
-{
-	mptsas_dev_reset_complete(ioc);
-	return mptscsih_taskmgmt_complete(ioc, mf, mr);
+	return 1;
 }
 
 /**
@@ -740,37 +1243,59 @@
 mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
 	MPT_SCSI_HOST	*hd;
-	struct mptsas_target_reset_event *target_reset_list, *n;
 	int rc;
 
 	rc = mptscsih_ioc_reset(ioc, reset_phase);
+	if ((ioc->bus_type != SAS) || (!rc))
+		return rc;
 
-	if (ioc->bus_type != SAS)
-		goto out;
-
-	if (reset_phase != MPT_IOC_POST_RESET)
-		goto out;
-
-	if (!ioc->sh || !ioc->sh->hostdata)
-		goto out;
 	hd = shost_priv(ioc->sh);
 	if (!hd->ioc)
 		goto out;
 
-	if (list_empty(&hd->target_reset_list))
-		goto out;
-
-	/* flush the target_reset_list */
-	list_for_each_entry_safe(target_reset_list, n,
-	    &hd->target_reset_list, list) {
-		list_del(&target_reset_list->list);
-		kfree(target_reset_list);
+	switch (reset_phase) {
+	case MPT_IOC_SETUP_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
+		mptsas_fw_event_off(ioc);
+		break;
+	case MPT_IOC_PRE_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
+		break;
+	case MPT_IOC_POST_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
+		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
+			complete(&ioc->sas_mgmt.done);
+		}
+		mptsas_cleanup_fw_event_q(ioc);
+		mptsas_queue_rescan(ioc);
+		mptsas_fw_event_on(ioc);
+		break;
+	default:
+		break;
 	}
 
  out:
 	return rc;
 }
 
+
+/**
+ * enum device_state -
+ * @DEVICE_RETRY: need to retry the TUR
+ * @DEVICE_ERROR: TUR return error, don't add device
+ * @DEVICE_READY: device can be added
+ *
+ */
+enum device_state{
+	DEVICE_RETRY,
+	DEVICE_ERROR,
+	DEVICE_READY,
+};
+
 static int
 mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
 		u32 form, u32 form_specific)
@@ -836,15 +1361,308 @@
 	return error;
 }
 
+/**
+ *	mptsas_add_end_device - report a new end device to sas transport layer
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@phy_info: decribes attached device
+ *
+ *	return (0) success (1) failure
+ *
+ **/
+static int
+mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
+{
+	struct sas_rphy *rphy;
+	struct sas_port *port;
+	struct sas_identify identify;
+	char *ds = NULL;
+	u8 fw_id;
+
+	if (!phy_info) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: exit at line=%d\n", ioc->name,
+			 __func__, __LINE__));
+		return 1;
+	}
+
+	fw_id = phy_info->attached.id;
+
+	if (mptsas_get_rphy(phy_info)) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, fw_id, __LINE__));
+		return 2;
+	}
+
+	port = mptsas_get_port(phy_info);
+	if (!port) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, fw_id, __LINE__));
+		return 3;
+	}
+
+	if (phy_info->attached.device_info &
+	    MPI_SAS_DEVICE_INFO_SSP_TARGET)
+		ds = "ssp";
+	if (phy_info->attached.device_info &
+	    MPI_SAS_DEVICE_INFO_STP_TARGET)
+		ds = "stp";
+	if (phy_info->attached.device_info &
+	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+		ds = "sata";
+
+	printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
+	    " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
+	    phy_info->attached.channel, phy_info->attached.id,
+	    phy_info->attached.phy_id, (unsigned long long)
+	    phy_info->attached.sas_address);
+
+	mptsas_parse_device_info(&identify, &phy_info->attached);
+	rphy = sas_end_device_alloc(port);
+	if (!rphy) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, fw_id, __LINE__));
+		return 5; /* non-fatal: an rphy can be added later */
+	}
+
+	rphy->identify = identify;
+	if (sas_rphy_add(rphy)) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, fw_id, __LINE__));
+		sas_rphy_free(rphy);
+		return 6;
+	}
+	mptsas_set_rphy(ioc, phy_info, rphy);
+	return 0;
+}
+
+/**
+ *	mptsas_del_end_device - report a deleted end device to sas transport layer
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@phy_info: decribes attached device
+ *
+ **/
+static void
+mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
+{
+	struct sas_rphy *rphy;
+	struct sas_port *port;
+	struct mptsas_portinfo *port_info;
+	struct mptsas_phyinfo *phy_info_parent;
+	int i;
+	char *ds = NULL;
+	u8 fw_id;
+	u64 sas_address;
+
+	if (!phy_info)
+		return;
+
+	fw_id = phy_info->attached.id;
+	sas_address = phy_info->attached.sas_address;
+
+	if (!phy_info->port_details) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, fw_id, __LINE__));
+		return;
+	}
+	rphy = mptsas_get_rphy(phy_info);
+	if (!rphy) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, fw_id, __LINE__));
+		return;
+	}
+
+	if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
+		|| phy_info->attached.device_info
+			& MPI_SAS_DEVICE_INFO_SMP_INITIATOR
+		|| phy_info->attached.device_info
+			& MPI_SAS_DEVICE_INFO_STP_INITIATOR)
+		ds = "initiator";
+	if (phy_info->attached.device_info &
+	    MPI_SAS_DEVICE_INFO_SSP_TARGET)
+		ds = "ssp";
+	if (phy_info->attached.device_info &
+	    MPI_SAS_DEVICE_INFO_STP_TARGET)
+		ds = "stp";
+	if (phy_info->attached.device_info &
+	    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+		ds = "sata";
+
+	dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
+	    "removing %s device: fw_channel %d, fw_id %d, phy %d,"
+	    "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
+	    phy_info->attached.id, phy_info->attached.phy_id,
+	    (unsigned long long) sas_address);
+
+	port = mptsas_get_port(phy_info);
+	if (!port) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, fw_id, __LINE__));
+		return;
+	}
+	port_info = phy_info->portinfo;
+	phy_info_parent = port_info->phy_info;
+	for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
+		if (!phy_info_parent->phy)
+			continue;
+		if (phy_info_parent->attached.sas_address !=
+		    sas_address)
+			continue;
+		dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
+		    MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
+		    ioc->name, phy_info_parent->phy_id,
+		    phy_info_parent->phy);
+		sas_port_delete_phy(port, phy_info_parent->phy);
+	}
+
+	dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
+	    "delete port %d, sas_addr (0x%llx)\n", ioc->name,
+	     port->port_identifier, (unsigned long long)sas_address);
+	sas_port_delete(port);
+	mptsas_set_port(ioc, phy_info, NULL);
+	mptsas_port_delete(ioc, phy_info->port_details);
+}
+
+struct mptsas_phyinfo *
+mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
+	struct mptsas_devinfo *sas_device)
+{
+	struct mptsas_phyinfo *phy_info;
+	struct mptsas_portinfo *port_info;
+	int i;
+
+	phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+	    sas_device->sas_address);
+	if (!phy_info)
+		goto out;
+	port_info = phy_info->portinfo;
+	if (!port_info)
+		goto out;
+	mutex_lock(&ioc->sas_topology_mutex);
+	for (i = 0; i < port_info->num_phys; i++) {
+		if (port_info->phy_info[i].attached.sas_address !=
+			sas_device->sas_address)
+			continue;
+		port_info->phy_info[i].attached.channel = sas_device->channel;
+		port_info->phy_info[i].attached.id = sas_device->id;
+		port_info->phy_info[i].attached.sas_address =
+		    sas_device->sas_address;
+		port_info->phy_info[i].attached.handle = sas_device->handle;
+		port_info->phy_info[i].attached.handle_parent =
+		    sas_device->handle_parent;
+		port_info->phy_info[i].attached.handle_enclosure =
+		    sas_device->handle_enclosure;
+	}
+	mutex_unlock(&ioc->sas_topology_mutex);
+ out:
+	return phy_info;
+}
+
+/**
+ * mptsas_firmware_event_work - work thread for processing fw events
+ * @work: work queue payload containing info describing the event
+ * Context: user
+ *
+ */
+static void
+mptsas_firmware_event_work(struct work_struct *work)
+{
+	struct fw_event_work *fw_event =
+		container_of(work, struct fw_event_work, work.work);
+	MPT_ADAPTER *ioc = fw_event->ioc;
+
+	/* special rescan topology handling */
+	if (fw_event->event == -1) {
+		if (ioc->in_rescan) {
+			devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+				"%s: rescan ignored as it is in progress\n",
+				ioc->name, __func__));
+			return;
+		}
+		devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
+		    "reset\n", ioc->name, __func__));
+		ioc->in_rescan = 1;
+		mptsas_not_responding_devices(ioc);
+		mptsas_scan_sas_topology(ioc);
+		ioc->in_rescan = 0;
+		mptsas_free_fw_event(ioc, fw_event);
+		return;
+	}
+
+	/* events handling turned off during host reset */
+	if (ioc->fw_events_off) {
+		mptsas_free_fw_event(ioc, fw_event);
+		return;
+	}
+
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
+	    "event = (0x%02x)\n", ioc->name, __func__, fw_event,
+	    (fw_event->event & 0xFF)));
+
+	switch (fw_event->event) {
+	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+		mptsas_send_sas_event(fw_event);
+		break;
+	case MPI_EVENT_INTEGRATED_RAID:
+		mptsas_send_raid_event(fw_event);
+		break;
+	case MPI_EVENT_IR2:
+		mptsas_send_ir2_event(fw_event);
+		break;
+	case MPI_EVENT_PERSISTENT_TABLE_FULL:
+		mptbase_sas_persist_operation(ioc,
+		    MPI_SAS_OP_CLEAR_NOT_PRESENT);
+		mptsas_free_fw_event(ioc, fw_event);
+		break;
+	case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
+		mptsas_broadcast_primative_work(fw_event);
+		break;
+	case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
+		mptsas_send_expander_event(fw_event);
+		break;
+	case MPI_EVENT_SAS_PHY_LINK_STATUS:
+		mptsas_send_link_status_event(fw_event);
+		break;
+	case MPI_EVENT_QUEUE_FULL:
+		mptsas_handle_queue_full_event(fw_event);
+		break;
+	}
+}
+
+
+
 static int
 mptsas_slave_configure(struct scsi_device *sdev)
 {
+	struct Scsi_Host	*host = sdev->host;
+	MPT_SCSI_HOST	*hd = shost_priv(host);
+	MPT_ADAPTER	*ioc = hd->ioc;
+	VirtDevice	*vdevice = sdev->hostdata;
 
-	if (sdev->channel == MPTSAS_RAID_CHANNEL)
+	if (vdevice->vtarget->deleted) {
+		sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
+		vdevice->vtarget->deleted = 0;
+	}
+
+	/*
+	 * RAID volumes placed beyond the last expected port.
+	 * Ignore sending sas mode pages in that case..
+	 */
+	if (sdev->channel == MPTSAS_RAID_CHANNEL) {
+		mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
 		goto out;
+	}
 
 	sas_read_port_mode_page(sdev);
 
+	mptsas_add_device_component_starget(ioc, scsi_target(sdev));
+
  out:
 	return mptscsih_slave_configure(sdev);
 }
@@ -875,9 +1693,18 @@
 	 * RAID volumes placed beyond the last expected port.
 	 */
 	if (starget->channel == MPTSAS_RAID_CHANNEL) {
-		for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
-			if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
-				channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
+		if (!ioc->raid_data.pIocPg2) {
+			kfree(vtarget);
+			return -ENXIO;
+		}
+		for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+			if (id == ioc->raid_data.pIocPg2->
+					RaidVolume[i].VolumeID) {
+				channel = ioc->raid_data.pIocPg2->
+					RaidVolume[i].VolumeBus;
+			}
+		}
+		vtarget->raidVolume = 1;
 		goto out;
 	}
 
@@ -926,11 +1753,18 @@
 	struct sas_rphy		*rphy;
 	struct mptsas_portinfo	*p;
 	int 			 i;
-	MPT_ADAPTER *ioc = hd->ioc;
+	MPT_ADAPTER	*ioc = hd->ioc;
+	VirtTarget	*vtarget;
 
 	if (!starget->hostdata)
 		return;
 
+	vtarget = starget->hostdata;
+
+	mptsas_del_device_component_by_os(ioc, starget->channel,
+	    starget->id);
+
+
 	if (starget->channel == MPTSAS_RAID_CHANNEL)
 		goto out;
 
@@ -940,12 +1774,21 @@
 			if (p->phy_info[i].attached.sas_address !=
 					rphy->identify.sas_address)
 				continue;
+
+			starget_printk(KERN_INFO, starget, MYIOC_s_FMT
+			"delete device: fw_channel %d, fw_id %d, phy %d, "
+			"sas_addr 0x%llx\n", ioc->name,
+			p->phy_info[i].attached.channel,
+			p->phy_info[i].attached.id,
+			p->phy_info[i].attached.phy_id, (unsigned long long)
+			p->phy_info[i].attached.sas_address);
+
 			mptsas_set_starget(&p->phy_info[i], NULL);
-			goto out;
 		}
 	}
 
  out:
+	vtarget->starget = NULL;
 	kfree(starget->hostdata);
 	starget->hostdata = NULL;
 }
@@ -1008,6 +1851,8 @@
 static int
 mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
+	MPT_SCSI_HOST	*hd;
+	MPT_ADAPTER	*ioc;
 	VirtDevice	*vdevice = SCpnt->device->hostdata;
 
 	if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
@@ -1016,6 +1861,12 @@
 		return 0;
 	}
 
+	hd = shost_priv(SCpnt->device->host);
+	ioc = hd->ioc;
+
+	if (ioc->sas_discovery_quiesce_io)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
 //	scsi_print_command(SCpnt);
 
 	return mptscsih_qcmd(SCpnt,done);
@@ -1114,14 +1965,19 @@
 static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
 		MPT_FRAME_HDR *reply)
 {
-	ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
+	ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
 	if (reply != NULL) {
-		ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
+		ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
 		memcpy(ioc->sas_mgmt.reply, reply,
 		    min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
 	}
-	complete(&ioc->sas_mgmt.done);
-	return 1;
+
+	if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
+		ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
+		complete(&ioc->sas_mgmt.done);
+		return 1;
+	}
+	return 0;
 }
 
 static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
@@ -1160,6 +2016,7 @@
 		MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
 	req->PhyNum = phy->identify.phy_identifier;
 
+	INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
 	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
 
 	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
@@ -1174,7 +2031,7 @@
 
 	/* a reply frame is expected */
 	if ((ioc->sas_mgmt.status &
-	    MPT_IOCTL_STATUS_RF_VALID) == 0) {
+	    MPT_MGMT_STATUS_RF_VALID) == 0) {
 		error = -ENXIO;
 		goto out_unlock;
 	}
@@ -1191,6 +2048,7 @@
 	error = 0;
 
  out_unlock:
+	CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
 	mutex_unlock(&ioc->sas_mgmt.mutex);
  out:
 	return error;
@@ -1277,8 +2135,8 @@
 	/* do we need to support multiple segments? */
 	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
 		printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
-		    ioc->name, __func__, req->bio->bi_vcnt, req->data_len,
-		    rsp->bio->bi_vcnt, rsp->data_len);
+		    ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
+		    rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
 		return -EINVAL;
 	}
 
@@ -1295,7 +2153,7 @@
 	smpreq = (SmpPassthroughRequest_t *)mf;
 	memset(smpreq, 0, sizeof(*smpreq));
 
-	smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
+	smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
 	smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
 
 	if (rphy)
@@ -1304,7 +2162,7 @@
 		struct mptsas_portinfo *port_info;
 
 		mutex_lock(&ioc->sas_topology_mutex);
-		port_info = mptsas_get_hba_portinfo(ioc);
+		port_info = ioc->hba_port_info;
 		if (port_info && port_info->phy_info)
 			sas_address =
 				port_info->phy_info[0].phy->identify.sas_address;
@@ -1319,26 +2177,32 @@
 	/* request */
 	flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
 		       MPI_SGE_FLAGS_END_OF_BUFFER |
-		       MPI_SGE_FLAGS_DIRECTION |
-		       mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
-	flagsLength |= (req->data_len - 4);
+		       MPI_SGE_FLAGS_DIRECTION)
+		       << MPI_SGE_FLAGS_SHIFT;
+	flagsLength |= (blk_rq_bytes(req) - 4);
 
 	dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
-				      req->data_len, PCI_DMA_BIDIRECTIONAL);
+				      blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
 	if (!dma_addr_out)
 		goto put_mf;
-	mpt_add_sge(psge, flagsLength, dma_addr_out);
-	psge += (sizeof(u32) + sizeof(dma_addr_t));
+	ioc->add_sge(psge, flagsLength, dma_addr_out);
+	psge += ioc->SGE_size;
 
 	/* response */
-	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
-	flagsLength |= rsp->data_len + 4;
+	flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+		MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+		MPI_SGE_FLAGS_IOC_TO_HOST |
+		MPI_SGE_FLAGS_END_OF_BUFFER;
+
+	flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
+	flagsLength |= blk_rq_bytes(rsp) + 4;
 	dma_addr_in =  pci_map_single(ioc->pcidev, bio_data(rsp->bio),
-				      rsp->data_len, PCI_DMA_BIDIRECTIONAL);
+				      blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
 	if (!dma_addr_in)
 		goto unmap;
-	mpt_add_sge(psge, flagsLength, dma_addr_in);
+	ioc->add_sge(psge, flagsLength, dma_addr_in);
 
+	INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
 	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
 
 	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
@@ -1351,30 +2215,32 @@
 	}
 	mf = NULL;
 
-	if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
+	if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
 		SmpPassthroughReply_t *smprep;
 
 		smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
 		memcpy(req->sense, smprep, sizeof(*smprep));
 		req->sense_len = sizeof(*smprep);
-		req->data_len = 0;
-		rsp->data_len -= smprep->ResponseDataLength;
+		req->resid_len = 0;
+		rsp->resid_len -= smprep->ResponseDataLength;
 	} else {
-		printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
+		printk(MYIOC_s_ERR_FMT
+		    "%s: smp passthru reply failed to be returned\n",
 		    ioc->name, __func__);
 		ret = -ENXIO;
 	}
 unmap:
 	if (dma_addr_out)
-		pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
+		pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
 				 PCI_DMA_BIDIRECTIONAL);
 	if (dma_addr_in)
-		pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
+		pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
 				 PCI_DMA_BIDIRECTIONAL);
 put_mf:
 	if (mf)
 		mpt_free_msg_frame(ioc, mf);
 out_unlock:
+	CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
 	mutex_unlock(&ioc->sas_mgmt.mutex);
 out:
 	return ret;
@@ -1438,7 +2304,7 @@
 
 	port_info->num_phys = buffer->NumPhys;
 	port_info->phy_info = kcalloc(port_info->num_phys,
-		sizeof(*port_info->phy_info),GFP_KERNEL);
+		sizeof(struct mptsas_phyinfo), GFP_KERNEL);
 	if (!port_info->phy_info) {
 		error = -ENOMEM;
 		goto out_free_consistent;
@@ -1600,10 +2466,6 @@
 	__le64 sas_address;
 	int error=0;
 
-	if (ioc->sas_discovery_runtime &&
-		mptsas_is_end_device(device_info))
-			goto out;
-
 	hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
 	hdr.ExtPageLength = 0;
 	hdr.PageNumber = 0;
@@ -1644,6 +2506,7 @@
 
 	mptsas_print_device_pg0(ioc, buffer);
 
+	memset(device_info, 0, sizeof(struct mptsas_devinfo));
 	device_info->handle = le16_to_cpu(buffer->DevHandle);
 	device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
 	device_info->handle_enclosure =
@@ -1675,7 +2538,9 @@
 	SasExpanderPage0_t *buffer;
 	dma_addr_t dma_handle;
 	int i, error;
+	__le64 sas_address;
 
+	memset(port_info, 0, sizeof(struct mptsas_portinfo));
 	hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
 	hdr.ExtPageLength = 0;
 	hdr.PageNumber = 0;
@@ -1721,18 +2586,23 @@
 	}
 
 	/* save config data */
-	port_info->num_phys = buffer->NumPhys;
+	port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
 	port_info->phy_info = kcalloc(port_info->num_phys,
-		sizeof(*port_info->phy_info),GFP_KERNEL);
+		sizeof(struct mptsas_phyinfo), GFP_KERNEL);
 	if (!port_info->phy_info) {
 		error = -ENOMEM;
 		goto out_free_consistent;
 	}
 
+	memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
 	for (i = 0; i < port_info->num_phys; i++) {
 		port_info->phy_info[i].portinfo = port_info;
 		port_info->phy_info[i].handle =
 		    le16_to_cpu(buffer->DevHandle);
+		port_info->phy_info[i].identify.sas_address =
+		    le64_to_cpu(sas_address);
+		port_info->phy_info[i].identify.handle_parent =
+		    le16_to_cpu(buffer->ParentDevHandle);
 	}
 
  out_free_consistent:
@@ -1752,11 +2622,7 @@
 	dma_addr_t dma_handle;
 	int error=0;
 
-	if (ioc->sas_discovery_runtime &&
-		mptsas_is_end_device(&phy_info->attached))
-			goto out;
-
-	hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
+	hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
 	hdr.ExtPageLength = 0;
 	hdr.PageNumber = 1;
 	hdr.Reserved1 = 0;
@@ -1791,6 +2657,12 @@
 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 
 	error = mpt_config(ioc, &cfg);
+
+	if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
+		error = -ENODEV;
+		goto out;
+	}
+
 	if (error)
 		goto out_free_consistent;
 
@@ -2010,16 +2882,21 @@
 				goto out;
 			}
 			mptsas_set_port(ioc, phy_info, port);
-			dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-			    "sas_port_alloc: port=%p dev=%p port_id=%d\n",
-			    ioc->name, port, dev, port->port_identifier));
+			devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
+			    MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
+			    ioc->name, port->port_identifier,
+			    (unsigned long long)phy_info->
+			    attached.sas_address));
 		}
-		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
-		    ioc->name, phy_info->phy_id));
+		dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			"sas_port_add_phy: phy_id=%d\n",
+			ioc->name, phy_info->phy_id));
 		sas_port_add_phy(port, phy_info->phy);
 		phy_info->sas_port_add_phy = 0;
+		devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
+		    MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
+		     phy_info->phy_id, phy_info->phy));
 	}
-
 	if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
 
 		struct sas_rphy *rphy;
@@ -2032,18 +2909,17 @@
 		 * the adding/removing of devices that occur
 		 * after start of day.
 		 */
-		if (ioc->sas_discovery_runtime &&
-			mptsas_is_end_device(&phy_info->attached))
-				goto out;
+		if (mptsas_is_end_device(&phy_info->attached) &&
+		    phy_info->attached.handle_parent) {
+			goto out;
+		}
 
 		mptsas_parse_device_info(&identify, &phy_info->attached);
 		if (scsi_is_host_device(parent)) {
 			struct mptsas_portinfo *port_info;
 			int i;
 
-			mutex_lock(&ioc->sas_topology_mutex);
-			port_info = mptsas_get_hba_portinfo(ioc);
-			mutex_unlock(&ioc->sas_topology_mutex);
+			port_info = ioc->hba_port_info;
 
 			for (i = 0; i < port_info->num_phys; i++)
 				if (port_info->phy_info[i].identify.sas_address ==
@@ -2102,7 +2978,7 @@
 	struct mptsas_portinfo *port_info, *hba;
 	int error = -ENOMEM, i;
 
-	hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
+	hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
 	if (! hba)
 		goto out;
 
@@ -2112,9 +2988,10 @@
 
 	mptsas_sas_io_unit_pg1(ioc);
 	mutex_lock(&ioc->sas_topology_mutex);
-	port_info = mptsas_get_hba_portinfo(ioc);
+	port_info = ioc->hba_port_info;
 	if (!port_info) {
-		port_info = hba;
+		ioc->hba_port_info = port_info = hba;
+		ioc->hba_port_num_phy = port_info->num_phys;
 		list_add_tail(&port_info->list, &ioc->sas_topology);
 	} else {
 		for (i = 0; i < hba->num_phys; i++) {
@@ -2130,15 +3007,22 @@
 		hba = NULL;
 	}
 	mutex_unlock(&ioc->sas_topology_mutex);
+#if defined(CPQ_CIM)
+	ioc->num_ports = port_info->num_phys;
+#endif
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
 			(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
 			 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
-
+		port_info->phy_info[i].identify.handle =
+		    port_info->phy_info[i].handle;
 		mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
 			(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
 			 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
-			 port_info->phy_info[i].handle);
+			 port_info->phy_info[i].identify.handle);
+		if (!ioc->hba_port_sas_addr)
+			ioc->hba_port_sas_addr =
+			    port_info->phy_info[i].identify.sas_address;
 		port_info->phy_info[i].identify.phy_id =
 		    port_info->phy_info[i].phy_id = i;
 		if (port_info->phy_info[i].attached.handle)
@@ -2163,248 +3047,721 @@
 	return error;
 }
 
-static int
-mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
+static void
+mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
 {
-	struct mptsas_portinfo *port_info, *p, *ex;
-	struct device *parent;
-	struct sas_rphy *rphy;
-	int error = -ENOMEM, i, j;
-
-	ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
-	if (!ex)
-		goto out;
-
-	error = mptsas_sas_expander_pg0(ioc, ex,
-	    (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
-	     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
-	if (error)
-		goto out_free_port_info;
-
-	*handle = ex->phy_info[0].handle;
-
-	mutex_lock(&ioc->sas_topology_mutex);
-	port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
-	if (!port_info) {
-		port_info = ex;
-		list_add_tail(&port_info->list, &ioc->sas_topology);
-	} else {
-		for (i = 0; i < ex->num_phys; i++) {
-			port_info->phy_info[i].handle =
-				ex->phy_info[i].handle;
-			port_info->phy_info[i].port_id =
-				ex->phy_info[i].port_id;
-		}
-		kfree(ex->phy_info);
-		kfree(ex);
-		ex = NULL;
-	}
-	mutex_unlock(&ioc->sas_topology_mutex);
+	struct mptsas_portinfo *parent;
+	struct device *parent_dev;
+	struct sas_rphy	*rphy;
+	int		i;
+	u64		sas_address; /* expander sas address */
+	u32		handle;
 
+	handle = port_info->phy_info[0].handle;
+	sas_address = port_info->phy_info[0].identify.sas_address;
 	for (i = 0; i < port_info->num_phys; i++) {
 		mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
-			(MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
-			 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
+		    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
+		    MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
 
-		if (port_info->phy_info[i].identify.handle) {
-			mptsas_sas_device_pg0(ioc,
-				&port_info->phy_info[i].identify,
-				(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
-				 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
-				port_info->phy_info[i].identify.handle);
-			port_info->phy_info[i].identify.phy_id =
-			    port_info->phy_info[i].phy_id;
-		}
+		mptsas_sas_device_pg0(ioc,
+		    &port_info->phy_info[i].identify,
+		    (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+		    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+		    port_info->phy_info[i].identify.handle);
+		port_info->phy_info[i].identify.phy_id =
+		    port_info->phy_info[i].phy_id;
 
 		if (port_info->phy_info[i].attached.handle) {
 			mptsas_sas_device_pg0(ioc,
-				&port_info->phy_info[i].attached,
-				(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
-				 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
-				port_info->phy_info[i].attached.handle);
+			    &port_info->phy_info[i].attached,
+			    (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+			     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+			    port_info->phy_info[i].attached.handle);
 			port_info->phy_info[i].attached.phy_id =
 			    port_info->phy_info[i].phy_id;
 		}
 	}
 
-	parent = &ioc->sh->shost_gendev;
-	for (i = 0; i < port_info->num_phys; i++) {
-		mutex_lock(&ioc->sas_topology_mutex);
-		list_for_each_entry(p, &ioc->sas_topology, list) {
-			for (j = 0; j < p->num_phys; j++) {
-				if (port_info->phy_info[i].identify.handle !=
-						p->phy_info[j].attached.handle)
-					continue;
-				rphy = mptsas_get_rphy(&p->phy_info[j]);
-				parent = &rphy->dev;
-			}
-		}
+	mutex_lock(&ioc->sas_topology_mutex);
+	parent = mptsas_find_portinfo_by_handle(ioc,
+	    port_info->phy_info[0].identify.handle_parent);
+	if (!parent) {
 		mutex_unlock(&ioc->sas_topology_mutex);
+		return;
+	}
+	for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
+	    i++) {
+		if (parent->phy_info[i].attached.sas_address == sas_address) {
+			rphy = mptsas_get_rphy(&parent->phy_info[i]);
+			parent_dev = &rphy->dev;
+		}
 	}
+	mutex_unlock(&ioc->sas_topology_mutex);
 
 	mptsas_setup_wide_ports(ioc, port_info);
-
 	for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
-		mptsas_probe_one_phy(parent, &port_info->phy_info[i],
+		mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
 		    ioc->sas_index, 0);
+}
 
-	return 0;
+static void
+mptsas_expander_event_add(MPT_ADAPTER *ioc,
+    MpiEventDataSasExpanderStatusChange_t *expander_data)
+{
+	struct mptsas_portinfo *port_info;
+	int i;
+	__le64 sas_address;
 
- out_free_port_info:
-	if (ex) {
-		kfree(ex->phy_info);
-		kfree(ex);
+	port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
+	if (!port_info)
+		BUG();
+	port_info->num_phys = (expander_data->NumPhys) ?
+	    expander_data->NumPhys : 1;
+	port_info->phy_info = kcalloc(port_info->num_phys,
+	    sizeof(struct mptsas_phyinfo), GFP_KERNEL);
+	if (!port_info->phy_info)
+		BUG();
+	memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
+	for (i = 0; i < port_info->num_phys; i++) {
+		port_info->phy_info[i].portinfo = port_info;
+		port_info->phy_info[i].handle =
+		    le16_to_cpu(expander_data->DevHandle);
+		port_info->phy_info[i].identify.sas_address =
+		    le64_to_cpu(sas_address);
+		port_info->phy_info[i].identify.handle_parent =
+		    le16_to_cpu(expander_data->ParentDevHandle);
+	}
+
+	mutex_lock(&ioc->sas_topology_mutex);
+	list_add_tail(&port_info->list, &ioc->sas_topology);
+	mutex_unlock(&ioc->sas_topology_mutex);
+
+	printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
+	    "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
+	    (unsigned long long)sas_address);
+
+	mptsas_expander_refresh(ioc, port_info);
+}
+
+/**
+ * mptsas_delete_expander_siblings - remove siblings attached to expander
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @parent: the parent port_info object
+ * @expander: the expander port_info object
+ **/
+static void
+mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
+    *parent, struct mptsas_portinfo *expander)
+{
+	struct mptsas_phyinfo *phy_info;
+	struct mptsas_portinfo *port_info;
+	struct sas_rphy *rphy;
+	int i;
+
+	phy_info = expander->phy_info;
+	for (i = 0; i < expander->num_phys; i++, phy_info++) {
+		rphy = mptsas_get_rphy(phy_info);
+		if (!rphy)
+			continue;
+		if (rphy->identify.device_type == SAS_END_DEVICE)
+			mptsas_del_end_device(ioc, phy_info);
+	}
+
+	phy_info = expander->phy_info;
+	for (i = 0; i < expander->num_phys; i++, phy_info++) {
+		rphy = mptsas_get_rphy(phy_info);
+		if (!rphy)
+			continue;
+		if (rphy->identify.device_type ==
+		    MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+		    rphy->identify.device_type ==
+		    MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
+			port_info = mptsas_find_portinfo_by_sas_address(ioc,
+			    rphy->identify.sas_address);
+			if (!port_info)
+				continue;
+			if (port_info == parent) /* backlink rphy */
+				continue;
+			/*
+			Delete this expander even if the expdevpage is exists
+			because the parent expander is already deleted
+			*/
+			mptsas_expander_delete(ioc, port_info, 1);
+		}
+	}
+}
+
+
+/**
+ *	mptsas_expander_delete - remove this expander
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@port_info: expander port_info struct
+ *	@force: Flag to forcefully delete the expander
+ *
+ **/
+
+static void mptsas_expander_delete(MPT_ADAPTER *ioc,
+		struct mptsas_portinfo *port_info, u8 force)
+{
+
+	struct mptsas_portinfo *parent;
+	int		i;
+	u64		expander_sas_address;
+	struct mptsas_phyinfo *phy_info;
+	struct mptsas_portinfo buffer;
+	struct mptsas_portinfo_details *port_details;
+	struct sas_port *port;
+
+	if (!port_info)
+		return;
+
+	/* see if expander is still there before deleting */
+	mptsas_sas_expander_pg0(ioc, &buffer,
+	    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
+	    MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
+	    port_info->phy_info[0].identify.handle);
+
+	if (buffer.num_phys) {
+		kfree(buffer.phy_info);
+		if (!force)
+			return;
+	}
+
+
+	/*
+	 * Obtain the port_info instance to the parent port
+	 */
+	port_details = NULL;
+	expander_sas_address =
+	    port_info->phy_info[0].identify.sas_address;
+	parent = mptsas_find_portinfo_by_handle(ioc,
+	    port_info->phy_info[0].identify.handle_parent);
+	mptsas_delete_expander_siblings(ioc, parent, port_info);
+	if (!parent)
+		goto out;
+
+	/*
+	 * Delete rphys in the parent that point
+	 * to this expander.
+	 */
+	phy_info = parent->phy_info;
+	port = NULL;
+	for (i = 0; i < parent->num_phys; i++, phy_info++) {
+		if (!phy_info->phy)
+			continue;
+		if (phy_info->attached.sas_address !=
+		    expander_sas_address)
+			continue;
+		if (!port) {
+			port = mptsas_get_port(phy_info);
+			port_details = phy_info->port_details;
+		}
+		dev_printk(KERN_DEBUG, &phy_info->phy->dev,
+		    MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
+		    phy_info->phy_id, phy_info->phy);
+		sas_port_delete_phy(port, phy_info->phy);
+	}
+	if (port) {
+		dev_printk(KERN_DEBUG, &port->dev,
+		    MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
+		    ioc->name, port->port_identifier,
+		    (unsigned long long)expander_sas_address);
+		sas_port_delete(port);
+		mptsas_port_delete(ioc, port_details);
 	}
  out:
-	return error;
+
+	printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
+	    "sas_addr (0x%llx)\n",  ioc->name, port_info->num_phys,
+	    (unsigned long long)expander_sas_address);
+
+	/*
+	 * free link
+	 */
+	list_del(&port_info->list);
+	kfree(port_info->phy_info);
+	kfree(port_info);
 }
 
-/*
- * mptsas_delete_expander_phys
+
+/**
+ * mptsas_send_expander_event - expanders events
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @expander_data: event data
  *
  *
- * This will traverse topology, and remove expanders
- * that are no longer present
+ * This function handles adding, removing, and refreshing
+ * device handles within the expander objects.
  */
 static void
-mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
+mptsas_send_expander_event(struct fw_event_work *fw_event)
 {
-	struct mptsas_portinfo buffer;
-	struct mptsas_portinfo *port_info, *n, *parent;
-	struct mptsas_phyinfo *phy_info;
-	struct sas_port * port;
+	MPT_ADAPTER *ioc;
+	MpiEventDataSasExpanderStatusChange_t *expander_data;
+	struct mptsas_portinfo *port_info;
+	__le64 sas_address;
 	int i;
-	u64	expander_sas_address;
 
+	ioc = fw_event->ioc;
+	expander_data = (MpiEventDataSasExpanderStatusChange_t *)
+	    fw_event->event_data;
+	memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
+	port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
+
+	if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
+		if (port_info) {
+			for (i = 0; i < port_info->num_phys; i++) {
+				port_info->phy_info[i].portinfo = port_info;
+				port_info->phy_info[i].handle =
+				    le16_to_cpu(expander_data->DevHandle);
+				port_info->phy_info[i].identify.sas_address =
+				    le64_to_cpu(sas_address);
+				port_info->phy_info[i].identify.handle_parent =
+				    le16_to_cpu(expander_data->ParentDevHandle);
+			}
+			mptsas_expander_refresh(ioc, port_info);
+		} else if (!port_info && expander_data->NumPhys)
+			mptsas_expander_event_add(ioc, expander_data);
+	} else if (expander_data->ReasonCode ==
+	    MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
+		mptsas_expander_delete(ioc, port_info, 0);
+
+	mptsas_free_fw_event(ioc, fw_event);
+}
+
+
+/**
+ * mptsas_expander_add -
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @handle:
+ *
+ */
+struct mptsas_portinfo *
+mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
+{
+	struct mptsas_portinfo buffer, *port_info;
+	int i;
+
+	if ((mptsas_sas_expander_pg0(ioc, &buffer,
+	    (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
+	    MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
+		return NULL;
+
+	port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
+	if (!port_info) {
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+		"%s: exit at line=%d\n", ioc->name,
+		__func__, __LINE__));
+		return NULL;
+	}
+	port_info->num_phys = buffer.num_phys;
+	port_info->phy_info = buffer.phy_info;
+	for (i = 0; i < port_info->num_phys; i++)
+		port_info->phy_info[i].portinfo = port_info;
 	mutex_lock(&ioc->sas_topology_mutex);
-	list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
+	list_add_tail(&port_info->list, &ioc->sas_topology);
+	mutex_unlock(&ioc->sas_topology_mutex);
+	printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
+	    "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
+	    (unsigned long long)buffer.phy_info[0].identify.sas_address);
+	mptsas_expander_refresh(ioc, port_info);
+	return port_info;
+}
 
-		if (!(port_info->phy_info[0].identify.device_info &
-		    MPI_SAS_DEVICE_INFO_SMP_TARGET))
+static void
+mptsas_send_link_status_event(struct fw_event_work *fw_event)
+{
+	MPT_ADAPTER *ioc;
+	MpiEventDataSasPhyLinkStatus_t *link_data;
+	struct mptsas_portinfo *port_info;
+	struct mptsas_phyinfo *phy_info = NULL;
+	__le64 sas_address;
+	u8 phy_num;
+	u8 link_rate;
+
+	ioc = fw_event->ioc;
+	link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
+
+	memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
+	sas_address = le64_to_cpu(sas_address);
+	link_rate = link_data->LinkRates >> 4;
+	phy_num = link_data->PhyNum;
+
+	port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
+	if (port_info) {
+		phy_info = &port_info->phy_info[phy_num];
+		if (phy_info)
+			phy_info->negotiated_link_rate = link_rate;
+	}
+
+	if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
+	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
+
+		if (!port_info) {
+			if (ioc->old_sas_discovery_protocal) {
+				port_info = mptsas_expander_add(ioc,
+					le16_to_cpu(link_data->DevHandle));
+				if (port_info)
+					goto out;
+			}
+			goto out;
+		}
+
+		if (port_info == ioc->hba_port_info)
+			mptsas_probe_hba_phys(ioc);
+		else
+			mptsas_expander_refresh(ioc, port_info);
+	} else if (phy_info && phy_info->phy) {
+		if (link_rate ==  MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
+			phy_info->phy->negotiated_linkrate =
+			    SAS_PHY_DISABLED;
+		else if (link_rate ==
+		    MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
+			phy_info->phy->negotiated_linkrate =
+			    SAS_LINK_RATE_FAILED;
+		else
+			phy_info->phy->negotiated_linkrate =
+			    SAS_LINK_RATE_UNKNOWN;
+	}
+ out:
+	mptsas_free_fw_event(ioc, fw_event);
+}
+
+static void
+mptsas_not_responding_devices(MPT_ADAPTER *ioc)
+{
+	struct mptsas_portinfo buffer, *port_info;
+	struct mptsas_device_info	*sas_info;
+	struct mptsas_devinfo sas_device;
+	u32	handle;
+	VirtTarget *vtarget = NULL;
+	struct mptsas_phyinfo *phy_info;
+	u8 found_expander;
+	int retval, retry_count;
+	unsigned long flags;
+
+	mpt_findImVolumes(ioc);
+
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	if (ioc->ioc_reset_in_progress) {
+		dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		   "%s: exiting due to a parallel reset \n", ioc->name,
+		    __func__));
+		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+
+	/* devices, logical volumes */
+	mutex_lock(&ioc->sas_device_info_mutex);
+ redo_device_scan:
+	list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
+		if (sas_info->is_cached)
 			continue;
+		if (!sas_info->is_logical_volume) {
+			sas_device.handle = 0;
+			retry_count = 0;
+retry_page:
+			retval = mptsas_sas_device_pg0(ioc, &sas_device,
+				(MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
+				<< MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+				(sas_info->fw.channel << 8) +
+				sas_info->fw.id);
 
-		if (mptsas_sas_expander_pg0(ioc, &buffer,
-		     (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
-		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
-		     port_info->phy_info[0].handle)) {
+			if (sas_device.handle)
+				continue;
+			if (retval == -EBUSY) {
+				spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+				if (ioc->ioc_reset_in_progress) {
+					dfailprintk(ioc,
+					printk(MYIOC_s_DEBUG_FMT
+					"%s: exiting due to reset\n",
+					ioc->name, __func__));
+					spin_unlock_irqrestore
+					(&ioc->taskmgmt_lock, flags);
+					mutex_unlock(&ioc->
+					sas_device_info_mutex);
+					return;
+				}
+				spin_unlock_irqrestore(&ioc->taskmgmt_lock,
+				flags);
+			}
 
-			/*
-			 * Obtain the port_info instance to the parent port
-			 */
-			parent = mptsas_find_portinfo_by_handle(ioc,
-			    port_info->phy_info[0].identify.handle_parent);
+			if (retval && (retval != -ENODEV)) {
+				if (retry_count < 10) {
+					retry_count++;
+					goto retry_page;
+				} else {
+					devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+					"%s: Config page retry exceeded retry "
+					"count deleting device 0x%llx\n",
+					ioc->name, __func__,
+					sas_info->sas_address));
+				}
+			}
 
-			if (!parent)
-				goto next_port;
+			/* delete device */
+			vtarget = mptsas_find_vtarget(ioc,
+				sas_info->fw.channel, sas_info->fw.id);
 
-			expander_sas_address =
-				port_info->phy_info[0].identify.sas_address;
+			if (vtarget)
+				vtarget->deleted = 1;
 
-			/*
-			 * Delete rphys in the parent that point
-			 * to this expander.  The transport layer will
-			 * cleanup all the children.
-			 */
-			phy_info = parent->phy_info;
-			for (i = 0; i < parent->num_phys; i++, phy_info++) {
-				port = mptsas_get_port(phy_info);
-				if (!port)
-					continue;
-				if (phy_info->attached.sas_address !=
-					expander_sas_address)
-					continue;
-				dsaswideprintk(ioc,
-				    dev_printk(KERN_DEBUG, &port->dev,
-				    MYIOC_s_FMT "delete port (%d)\n", ioc->name,
-				    port->port_identifier));
-				sas_port_delete(port);
-				mptsas_port_delete(ioc, phy_info->port_details);
+			phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+					sas_info->sas_address);
+
+			if (phy_info) {
+				mptsas_del_end_device(ioc, phy_info);
+				goto redo_device_scan;
 			}
- next_port:
+		} else
+			mptsas_volume_delete(ioc, sas_info->fw.id);
+	}
+	mutex_unlock(&ioc->sas_device_info_mutex);
 
-			phy_info = port_info->phy_info;
-			for (i = 0; i < port_info->num_phys; i++, phy_info++)
-				mptsas_port_delete(ioc, phy_info->port_details);
+	/* expanders */
+	mutex_lock(&ioc->sas_topology_mutex);
+ redo_expander_scan:
+	list_for_each_entry(port_info, &ioc->sas_topology, list) {
 
-			list_del(&port_info->list);
-			kfree(port_info->phy_info);
-			kfree(port_info);
+		if (port_info->phy_info &&
+		    (!(port_info->phy_info[0].identify.device_info &
+		    MPI_SAS_DEVICE_INFO_SMP_TARGET)))
+			continue;
+		found_expander = 0;
+		handle = 0xFFFF;
+		while (!mptsas_sas_expander_pg0(ioc, &buffer,
+		    (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
+		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
+		    !found_expander) {
+
+			handle = buffer.phy_info[0].handle;
+			if (buffer.phy_info[0].identify.sas_address ==
+			    port_info->phy_info[0].identify.sas_address) {
+				found_expander = 1;
+			}
+			kfree(buffer.phy_info);
+		}
+
+		if (!found_expander) {
+			mptsas_expander_delete(ioc, port_info, 0);
+			goto redo_expander_scan;
 		}
-		/*
-		* Free this memory allocated from inside
-		* mptsas_sas_expander_pg0
-		*/
-		kfree(buffer.phy_info);
 	}
 	mutex_unlock(&ioc->sas_topology_mutex);
 }
 
-/*
- * Start of day discovery
- */
+/**
+ *	mptsas_probe_expanders - adding expanders
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ **/
+static void
+mptsas_probe_expanders(MPT_ADAPTER *ioc)
+{
+	struct mptsas_portinfo buffer, *port_info;
+	u32 			handle;
+	int i;
+
+	handle = 0xFFFF;
+	while (!mptsas_sas_expander_pg0(ioc, &buffer,
+	    (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
+	     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
+
+		handle = buffer.phy_info[0].handle;
+		port_info = mptsas_find_portinfo_by_sas_address(ioc,
+		    buffer.phy_info[0].identify.sas_address);
+
+		if (port_info) {
+			/* refreshing handles */
+			for (i = 0; i < buffer.num_phys; i++) {
+				port_info->phy_info[i].handle = handle;
+				port_info->phy_info[i].identify.handle_parent =
+				    buffer.phy_info[0].identify.handle_parent;
+			}
+			mptsas_expander_refresh(ioc, port_info);
+			kfree(buffer.phy_info);
+			continue;
+		}
+
+		port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
+		if (!port_info) {
+			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"%s: exit at line=%d\n", ioc->name,
+			__func__, __LINE__));
+			return;
+		}
+		port_info->num_phys = buffer.num_phys;
+		port_info->phy_info = buffer.phy_info;
+		for (i = 0; i < port_info->num_phys; i++)
+			port_info->phy_info[i].portinfo = port_info;
+		mutex_lock(&ioc->sas_topology_mutex);
+		list_add_tail(&port_info->list, &ioc->sas_topology);
+		mutex_unlock(&ioc->sas_topology_mutex);
+		printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
+		    "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
+	    (unsigned long long)buffer.phy_info[0].identify.sas_address);
+		mptsas_expander_refresh(ioc, port_info);
+	}
+}
+
+static void
+mptsas_probe_devices(MPT_ADAPTER *ioc)
+{
+	u16 handle;
+	struct mptsas_devinfo sas_device;
+	struct mptsas_phyinfo *phy_info;
+
+	handle = 0xFFFF;
+	while (!(mptsas_sas_device_pg0(ioc, &sas_device,
+	    MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+
+		handle = sas_device.handle;
+
+		if ((sas_device.device_info &
+		     (MPI_SAS_DEVICE_INFO_SSP_TARGET |
+		      MPI_SAS_DEVICE_INFO_STP_TARGET |
+		      MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
+			continue;
+
+		phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
+		if (!phy_info)
+			continue;
+
+		if (mptsas_get_rphy(phy_info))
+			continue;
+
+		mptsas_add_end_device(ioc, phy_info);
+	}
+}
+
+/**
+ *	mptsas_scan_sas_topology -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@sas_address:
+ *
+ **/
 static void
 mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
 {
-	u32 handle = 0xFFFF;
+	struct scsi_device *sdev;
 	int i;
 
-	mutex_lock(&ioc->sas_discovery_mutex);
 	mptsas_probe_hba_phys(ioc);
-	while (!mptsas_probe_expander_phys(ioc, &handle))
-		;
+	mptsas_probe_expanders(ioc);
+	mptsas_probe_devices(ioc);
+
 	/*
 	  Reporting RAID volumes.
 	*/
-	if (!ioc->ir_firmware)
-		goto out;
-	if (!ioc->raid_data.pIocPg2)
-		goto out;
-	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
-		goto out;
+	if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
+	    !ioc->raid_data.pIocPg2->NumActiveVolumes)
+		return;
 	for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
+		    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
+		if (sdev) {
+			scsi_device_put(sdev);
+			continue;
+		}
+		printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
+		    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
+		    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
 		scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
 		    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
 	}
- out:
-	mutex_unlock(&ioc->sas_discovery_mutex);
 }
 
-/*
- * Work queue thread to handle Runtime discovery
- * Mere purpose is the hot add/delete of expanders
- *(Mutex UNLOCKED)
- */
+
 static void
-__mptsas_discovery_work(MPT_ADAPTER *ioc)
+mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
 {
-	u32 handle = 0xFFFF;
+	MPT_ADAPTER *ioc;
+	EventDataQueueFull_t *qfull_data;
+	struct mptsas_device_info *sas_info;
+	struct scsi_device	*sdev;
+	int depth;
+	int id = -1;
+	int channel = -1;
+	int fw_id, fw_channel;
+	u16 current_depth;
 
-	ioc->sas_discovery_runtime=1;
-	mptsas_delete_expander_phys(ioc);
-	mptsas_probe_hba_phys(ioc);
-	while (!mptsas_probe_expander_phys(ioc, &handle))
-		;
-	ioc->sas_discovery_runtime=0;
-}
 
-/*
- * Work queue thread to handle Runtime discovery
- * Mere purpose is the hot add/delete of expanders
- *(Mutex LOCKED)
- */
-static void
-mptsas_discovery_work(struct work_struct *work)
-{
-	struct mptsas_discovery_event *ev =
-		container_of(work, struct mptsas_discovery_event, work);
-	MPT_ADAPTER *ioc = ev->ioc;
+	ioc = fw_event->ioc;
+	qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
+	fw_id = qfull_data->TargetID;
+	fw_channel = qfull_data->Bus;
+	current_depth = le16_to_cpu(qfull_data->CurrentDepth);
 
-	mutex_lock(&ioc->sas_discovery_mutex);
-	__mptsas_discovery_work(ioc);
-	mutex_unlock(&ioc->sas_discovery_mutex);
-	kfree(ev);
+	/* if hidden raid component, look for the volume id */
+	mutex_lock(&ioc->sas_device_info_mutex);
+	if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
+		list_for_each_entry(sas_info, &ioc->sas_device_info_list,
+		    list) {
+			if (sas_info->is_cached ||
+			    sas_info->is_logical_volume)
+				continue;
+			if (sas_info->is_hidden_raid_component &&
+			    (sas_info->fw.channel == fw_channel &&
+			    sas_info->fw.id == fw_id)) {
+				id = sas_info->volume_id;
+				channel = MPTSAS_RAID_CHANNEL;
+				goto out;
+			}
+		}
+	} else {
+		list_for_each_entry(sas_info, &ioc->sas_device_info_list,
+		    list) {
+			if (sas_info->is_cached ||
+			    sas_info->is_hidden_raid_component ||
+			    sas_info->is_logical_volume)
+				continue;
+			if (sas_info->fw.channel == fw_channel &&
+			    sas_info->fw.id == fw_id) {
+				id = sas_info->os.id;
+				channel = sas_info->os.channel;
+				goto out;
+			}
+		}
+
+	}
+
+ out:
+	mutex_unlock(&ioc->sas_device_info_mutex);
+
+	if (id != -1) {
+		shost_for_each_device(sdev, ioc->sh) {
+			if (sdev->id == id && sdev->channel == channel) {
+				if (current_depth > sdev->queue_depth) {
+					sdev_printk(KERN_INFO, sdev,
+					    "strange observation, the queue "
+					    "depth is (%d) meanwhile fw queue "
+					    "depth (%d)\n", sdev->queue_depth,
+					    current_depth);
+					continue;
+				}
+				depth = scsi_track_queue_full(sdev,
+				    current_depth - 1);
+				if (depth > 0)
+					sdev_printk(KERN_INFO, sdev,
+					"Queue depth reduced to (%d)\n",
+					   depth);
+				else if (depth < 0)
+					sdev_printk(KERN_INFO, sdev,
+					"Tagged Command Queueing is being "
+					"disabled\n");
+				else if (depth == 0)
+					sdev_printk(KERN_INFO, sdev,
+					"Queue depth not changed yet\n");
+			}
+		}
+	}
+
+	mptsas_free_fw_event(ioc, fw_event);
 }
 
+
 static struct mptsas_phyinfo *
 mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
 {
@@ -2429,69 +3786,80 @@
 	return phy_info;
 }
 
+/**
+ *	mptsas_find_phyinfo_by_phys_disk_num -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@phys_disk_num:
+ *	@channel:
+ *	@id:
+ *
+ **/
 static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
+mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
+	u8 channel, u8 id)
 {
-	struct mptsas_portinfo *port_info;
 	struct mptsas_phyinfo *phy_info = NULL;
+	struct mptsas_portinfo *port_info;
+	RaidPhysDiskPage1_t *phys_disk = NULL;
+	int num_paths;
+	u64 sas_address = 0;
 	int i;
 
-	mutex_lock(&ioc->sas_topology_mutex);
-	list_for_each_entry(port_info, &ioc->sas_topology, list) {
-		for (i = 0; i < port_info->num_phys; i++) {
-			if (!mptsas_is_end_device(
-				&port_info->phy_info[i].attached))
-				continue;
-			if (port_info->phy_info[i].attached.id != id)
-				continue;
-			if (port_info->phy_info[i].attached.channel != channel)
-				continue;
-			phy_info = &port_info->phy_info[i];
-			break;
+	phy_info = NULL;
+	if (!ioc->raid_data.pIocPg3)
+		return NULL;
+	/* dual port support */
+	num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
+	if (!num_paths)
+		goto out;
+	phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
+	   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
+	if (!phys_disk)
+		goto out;
+	mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
+	for (i = 0; i < num_paths; i++) {
+		if ((phys_disk->Path[i].Flags & 1) != 0)
+			/* entry no longer valid */
+			continue;
+		if ((id == phys_disk->Path[i].PhysDiskID) &&
+		    (channel == phys_disk->Path[i].PhysDiskBus)) {
+			memcpy(&sas_address, &phys_disk->Path[i].WWID,
+				sizeof(u64));
+			phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+					sas_address);
+			goto out;
 		}
 	}
-	mutex_unlock(&ioc->sas_topology_mutex);
-	return phy_info;
-}
 
-static struct mptsas_phyinfo *
-mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
-{
-	struct mptsas_portinfo *port_info;
-	struct mptsas_phyinfo *phy_info = NULL;
-	int i;
+ out:
+	kfree(phys_disk);
+	if (phy_info)
+		return phy_info;
 
+	/*
+	 * Extra code to handle RAID0 case, where the sas_address is not updated
+	 * in phys_disk_page_1 when hotswapped
+	 */
 	mutex_lock(&ioc->sas_topology_mutex);
 	list_for_each_entry(port_info, &ioc->sas_topology, list) {
-		for (i = 0; i < port_info->num_phys; i++) {
+		for (i = 0; i < port_info->num_phys && !phy_info; i++) {
 			if (!mptsas_is_end_device(
 				&port_info->phy_info[i].attached))
 				continue;
 			if (port_info->phy_info[i].attached.phys_disk_num == ~0)
 				continue;
-			if (port_info->phy_info[i].attached.phys_disk_num != id)
-				continue;
-			if (port_info->phy_info[i].attached.channel != channel)
-				continue;
-			phy_info = &port_info->phy_info[i];
-			break;
+			if ((port_info->phy_info[i].attached.phys_disk_num ==
+			    phys_disk_num) &&
+			    (port_info->phy_info[i].attached.id == id) &&
+			    (port_info->phy_info[i].attached.channel ==
+			     channel))
+				phy_info = &port_info->phy_info[i];
 		}
 	}
 	mutex_unlock(&ioc->sas_topology_mutex);
 	return phy_info;
 }
 
-/*
- * Work queue thread to clear the persitency table
- */
-static void
-mptsas_persist_clear_table(struct work_struct *work)
-{
-	MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
-
-	mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
-}
-
 static void
 mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
 {
@@ -2517,7 +3885,8 @@
 	pRaidVolumePage0_t		buffer = NULL;
 	RaidPhysDiskPage0_t 		phys_disk;
 	int				i;
-	struct mptsas_hotplug_event 	*ev;
+	struct mptsas_phyinfo	*phy_info;
+	struct mptsas_devinfo		sas_device;
 
 	memset(&cfg, 0 , sizeof(CONFIGPARMS));
 	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
@@ -2557,20 +3926,16 @@
 		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
 			continue;
 
-		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-		if (!ev) {
-			printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
-			goto out;
-		}
+		if (mptsas_sas_device_pg0(ioc, &sas_device,
+		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+			(phys_disk.PhysDiskBus << 8) +
+			phys_disk.PhysDiskID))
+			continue;
 
-		INIT_WORK(&ev->work, mptsas_hotplug_work);
-		ev->ioc = ioc;
-		ev->id = phys_disk.PhysDiskID;
-		ev->channel = phys_disk.PhysDiskBus;
-		ev->phys_disk_num_valid = 1;
-		ev->phys_disk_num = phys_disk.PhysDiskNum;
-		ev->event_type = MPTSAS_ADD_DEVICE;
-		schedule_work(&ev->work);
+		phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+		    sas_device.sas_address);
+		mptsas_add_end_device(ioc, phy_info);
 	}
 
  out:
@@ -2582,417 +3947,386 @@
  * Work queue thread to handle SAS hotplug events
  */
 static void
-mptsas_hotplug_work(struct work_struct *work)
+mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
+    struct mptsas_hotplug_event *hot_plug_info)
 {
-	struct mptsas_hotplug_event *ev =
-		container_of(work, struct mptsas_hotplug_event, work);
-
-	MPT_ADAPTER *ioc = ev->ioc;
 	struct mptsas_phyinfo *phy_info;
-	struct sas_rphy *rphy;
-	struct sas_port *port;
-	struct scsi_device *sdev;
 	struct scsi_target * starget;
-	struct sas_identify identify;
-	char *ds = NULL;
 	struct mptsas_devinfo sas_device;
 	VirtTarget *vtarget;
-	VirtDevice *vdevice;
+	int i;
 
-	mutex_lock(&ioc->sas_discovery_mutex);
-	switch (ev->event_type) {
-	case MPTSAS_DEL_DEVICE:
+	switch (hot_plug_info->event_type) {
 
-		phy_info = NULL;
-		if (ev->phys_disk_num_valid) {
-			if (ev->hidden_raid_component){
-				if (mptsas_sas_device_pg0(ioc, &sas_device,
-				    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
-				     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
-				    (ev->channel << 8) + ev->id)) {
-					dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-					"%s: exit at line=%d\n", ioc->name,
-						__func__, __LINE__));
-					break;
-				}
-				phy_info = mptsas_find_phyinfo_by_sas_address(
-				    ioc, sas_device.sas_address);
-			}else
-				phy_info = mptsas_find_phyinfo_by_phys_disk_num(
-				    ioc, ev->channel, ev->phys_disk_num);
+	case MPTSAS_ADD_PHYSDISK:
+
+		if (!ioc->raid_data.pIocPg2)
+			break;
+
+		for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
+			if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
+			    hot_plug_info->id) {
+				printk(MYIOC_s_WARN_FMT "firmware bug: unable "
+				    "to add hidden disk - target_id matchs "
+				    "volume_id\n", ioc->name);
+				mptsas_free_fw_event(ioc, fw_event);
+				return;
+			}
 		}
+		mpt_findImVolumes(ioc);
+
+	case MPTSAS_ADD_DEVICE:
+		memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
+		mptsas_sas_device_pg0(ioc, &sas_device,
+		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+		    MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+		    (hot_plug_info->channel << 8) +
+		    hot_plug_info->id);
+
+		if (!sas_device.handle)
+			return;
 
+		phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
 		if (!phy_info)
-			phy_info = mptsas_find_phyinfo_by_target(ioc,
-			    ev->channel, ev->id);
+			break;
 
-		/*
-		 * Sanity checks, for non-existing phys and remote rphys.
-		 */
-		if (!phy_info){
-			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-				__func__, __LINE__));
+		if (mptsas_get_rphy(phy_info))
 			break;
-		}
-		if (!phy_info->port_details) {
+
+		mptsas_add_end_device(ioc, phy_info);
+		break;
+
+	case MPTSAS_DEL_DEVICE:
+		phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
+		    hot_plug_info->sas_address);
+		mptsas_del_end_device(ioc, phy_info);
+		break;
+
+	case MPTSAS_DEL_PHYSDISK:
+
+		mpt_findImVolumes(ioc);
+
+		phy_info = mptsas_find_phyinfo_by_phys_disk_num(
+				ioc, hot_plug_info->phys_disk_num,
+				hot_plug_info->channel,
+				hot_plug_info->id);
+		mptsas_del_end_device(ioc, phy_info);
+		break;
+
+	case MPTSAS_ADD_PHYSDISK_REPROBE:
+
+		if (mptsas_sas_device_pg0(ioc, &sas_device,
+		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
+		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+		    (hot_plug_info->channel << 8) + hot_plug_info->id)) {
 			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
+			"%s: fw_id=%d exit at line=%d\n", ioc->name,
+				 __func__, hot_plug_info->id, __LINE__));
 			break;
 		}
-		rphy = mptsas_get_rphy(phy_info);
-		if (!rphy) {
+
+		phy_info = mptsas_find_phyinfo_by_sas_address(
+		    ioc, sas_device.sas_address);
+
+		if (!phy_info) {
 			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
+				"%s: fw_id=%d exit at line=%d\n", ioc->name,
+				 __func__, hot_plug_info->id, __LINE__));
 			break;
 		}
 
-		port = mptsas_get_port(phy_info);
-		if (!port) {
+		starget = mptsas_get_starget(phy_info);
+		if (!starget) {
 			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
+				"%s: fw_id=%d exit at line=%d\n", ioc->name,
+				 __func__, hot_plug_info->id, __LINE__));
 			break;
 		}
 
-		starget = mptsas_get_starget(phy_info);
-		if (starget) {
-			vtarget = starget->hostdata;
-
-			if (!vtarget) {
-				dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-					"%s: exit at line=%d\n", ioc->name,
-					__func__, __LINE__));
-				break;
-			}
-
-			/*
-			 * Handling  RAID components
-			 */
-			if (ev->phys_disk_num_valid &&
-			    ev->hidden_raid_component) {
-				printk(MYIOC_s_INFO_FMT
-				    "RAID Hidding: channel=%d, id=%d, "
-				    "physdsk %d \n", ioc->name, ev->channel,
-				    ev->id, ev->phys_disk_num);
-				vtarget->id = ev->phys_disk_num;
-				vtarget->tflags |=
-				    MPT_TARGET_FLAGS_RAID_COMPONENT;
-				mptsas_reprobe_target(starget, 1);
-				phy_info->attached.phys_disk_num =
-				    ev->phys_disk_num;
+		vtarget = starget->hostdata;
+		if (!vtarget) {
+			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+				"%s: fw_id=%d exit at line=%d\n", ioc->name,
+				 __func__, hot_plug_info->id, __LINE__));
 			break;
-			}
 		}
 
-		if (phy_info->attached.device_info &
-		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
-			ds = "ssp";
-		if (phy_info->attached.device_info &
-		    MPI_SAS_DEVICE_INFO_STP_TARGET)
-			ds = "stp";
-		if (phy_info->attached.device_info &
-		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
-			ds = "sata";
+		mpt_findImVolumes(ioc);
 
-		printk(MYIOC_s_INFO_FMT
-		       "removing %s device, channel %d, id %d, phy %d\n",
-		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
-		dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
-		    "delete port (%d)\n", ioc->name, port->port_identifier);
-		sas_port_delete(port);
-		mptsas_port_delete(ioc, phy_info->port_details);
+		starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
+		    "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
+		    ioc->name, hot_plug_info->channel, hot_plug_info->id,
+		    hot_plug_info->phys_disk_num, (unsigned long long)
+		    sas_device.sas_address);
+
+		vtarget->id = hot_plug_info->phys_disk_num;
+		vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+		phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
+		mptsas_reprobe_target(starget, 1);
 		break;
-	case MPTSAS_ADD_DEVICE:
 
-		if (ev->phys_disk_num_valid)
-			mpt_findImVolumes(ioc);
+	case MPTSAS_DEL_PHYSDISK_REPROBE:
 
-		/*
-		 * Refresh sas device pg0 data
-		 */
 		if (mptsas_sas_device_pg0(ioc, &sas_device,
 		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
 		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
-			(ev->channel << 8) + ev->id)) {
+			(hot_plug_info->channel << 8) + hot_plug_info->id)) {
 				dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-					"%s: exit at line=%d\n", ioc->name,
-					__func__, __LINE__));
+				    "%s: fw_id=%d exit at line=%d\n",
+				    ioc->name, __func__,
+				    hot_plug_info->id, __LINE__));
 			break;
 		}
 
-		__mptsas_discovery_work(ioc);
-
 		phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
 				sas_device.sas_address);
-
-		if (!phy_info || !phy_info->port_details) {
+		if (!phy_info) {
 			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
+			    "%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, hot_plug_info->id, __LINE__));
 			break;
 		}
 
 		starget = mptsas_get_starget(phy_info);
-		if (starget && (!ev->hidden_raid_component)){
-
-			vtarget = starget->hostdata;
-
-			if (!vtarget) {
-				dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				    "%s: exit at line=%d\n", ioc->name,
-				    __func__, __LINE__));
-				break;
-			}
-			/*
-			 * Handling  RAID components
-			 */
-			if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
-				printk(MYIOC_s_INFO_FMT
-				    "RAID Exposing: channel=%d, id=%d, "
-				    "physdsk %d \n", ioc->name, ev->channel,
-				    ev->id, ev->phys_disk_num);
-				vtarget->tflags &=
-				    ~MPT_TARGET_FLAGS_RAID_COMPONENT;
-				vtarget->id = ev->id;
-				mptsas_reprobe_target(starget, 0);
-				phy_info->attached.phys_disk_num = ~0;
-			}
+		if (!starget) {
+			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			    "%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, hot_plug_info->id, __LINE__));
 			break;
 		}
 
-		if (mptsas_get_rphy(phy_info)) {
+		vtarget = starget->hostdata;
+		if (!vtarget) {
 			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
-			if (ev->channel) printk("%d\n", __LINE__);
+			    "%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, hot_plug_info->id, __LINE__));
 			break;
 		}
 
-		port = mptsas_get_port(phy_info);
-		if (!port) {
+		if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
 			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
+			    "%s: fw_id=%d exit at line=%d\n", ioc->name,
+			 __func__, hot_plug_info->id, __LINE__));
 			break;
 		}
-		memcpy(&phy_info->attached, &sas_device,
-		    sizeof(struct mptsas_devinfo));
-
-		if (phy_info->attached.device_info &
-		    MPI_SAS_DEVICE_INFO_SSP_TARGET)
-			ds = "ssp";
-		if (phy_info->attached.device_info &
-		    MPI_SAS_DEVICE_INFO_STP_TARGET)
-			ds = "stp";
-		if (phy_info->attached.device_info &
-		    MPI_SAS_DEVICE_INFO_SATA_DEVICE)
-			ds = "sata";
 
-		printk(MYIOC_s_INFO_FMT
-		       "attaching %s device, channel %d, id %d, phy %d\n",
-		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+		mpt_findImVolumes(ioc);
 
-		mptsas_parse_device_info(&identify, &phy_info->attached);
-		rphy = sas_end_device_alloc(port);
-		if (!rphy) {
-			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
-			break; /* non-fatal: an rphy can be added later */
-		}
+		starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
+		    " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
+		    ioc->name, hot_plug_info->channel, hot_plug_info->id,
+		    hot_plug_info->phys_disk_num, (unsigned long long)
+		    sas_device.sas_address);
 
-		rphy->identify = identify;
-		if (sas_rphy_add(rphy)) {
-			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
-				"%s: exit at line=%d\n", ioc->name,
-			       	__func__, __LINE__));
-			sas_rphy_free(rphy);
-			break;
-		}
-		mptsas_set_rphy(ioc, phy_info, rphy);
+		vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+		vtarget->id = hot_plug_info->id;
+		phy_info->attached.phys_disk_num = ~0;
+		mptsas_reprobe_target(starget, 0);
+		mptsas_add_device_component_by_fw(ioc,
+		    hot_plug_info->channel, hot_plug_info->id);
 		break;
+
 	case MPTSAS_ADD_RAID:
-		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
-		    ev->id, 0);
-		if (sdev) {
-			scsi_device_put(sdev);
-			break;
-		}
-		printk(MYIOC_s_INFO_FMT
-		       "attaching raid volume, channel %d, id %d\n",
-		       ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
-		scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
+
 		mpt_findImVolumes(ioc);
+		printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
+		    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
+		    hot_plug_info->id);
+		scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
+		    hot_plug_info->id, 0);
 		break;
+
 	case MPTSAS_DEL_RAID:
-		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
-		    ev->id, 0);
-		if (!sdev)
-			break;
-		printk(MYIOC_s_INFO_FMT
-		       "removing raid volume, channel %d, id %d\n",
-		       ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
-		vdevice = sdev->hostdata;
-		scsi_remove_device(sdev);
-		scsi_device_put(sdev);
+
 		mpt_findImVolumes(ioc);
+		printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
+		    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
+		    hot_plug_info->id);
+		scsi_remove_device(hot_plug_info->sdev);
+		scsi_device_put(hot_plug_info->sdev);
 		break;
+
 	case MPTSAS_ADD_INACTIVE_VOLUME:
+
+		mpt_findImVolumes(ioc);
 		mptsas_adding_inactive_raid_components(ioc,
-		    ev->channel, ev->id);
+		    hot_plug_info->channel, hot_plug_info->id);
 		break;
-	case MPTSAS_IGNORE_EVENT:
+
 	default:
 		break;
 	}
 
-	mutex_unlock(&ioc->sas_discovery_mutex);
-	kfree(ev);
+	mptsas_free_fw_event(ioc, fw_event);
 }
 
 static void
-mptsas_send_sas_event(MPT_ADAPTER *ioc,
-		EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+mptsas_send_sas_event(struct fw_event_work *fw_event)
 {
-	struct mptsas_hotplug_event *ev;
-	u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
-	__le64 sas_address;
+	MPT_ADAPTER *ioc;
+	struct mptsas_hotplug_event hot_plug_info;
+	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
+	u32 device_info;
+	u64 sas_address;
+
+	ioc = fw_event->ioc;
+	sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
+	    fw_event->event_data;
+	device_info = le32_to_cpu(sas_event_data->DeviceInfo);
 
 	if ((device_info &
-	     (MPI_SAS_DEVICE_INFO_SSP_TARGET |
-	      MPI_SAS_DEVICE_INFO_STP_TARGET |
-	      MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
+		(MPI_SAS_DEVICE_INFO_SSP_TARGET |
+		MPI_SAS_DEVICE_INFO_STP_TARGET |
+		MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
+		mptsas_free_fw_event(ioc, fw_event);
+		return;
+	}
+
+	if (sas_event_data->ReasonCode ==
+		MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
+		mptbase_sas_persist_operation(ioc,
+		MPI_SAS_OP_CLEAR_NOT_PRESENT);
+		mptsas_free_fw_event(ioc, fw_event);
 		return;
+	}
 
 	switch (sas_event_data->ReasonCode) {
 	case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
-
-		mptsas_target_reset_queue(ioc, sas_event_data);
-		break;
-
 	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
-		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-		if (!ev) {
-			printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
-			break;
-		}
-
-		INIT_WORK(&ev->work, mptsas_hotplug_work);
-		ev->ioc = ioc;
-		ev->handle = le16_to_cpu(sas_event_data->DevHandle);
-		ev->parent_handle =
-		    le16_to_cpu(sas_event_data->ParentDevHandle);
-		ev->channel = sas_event_data->Bus;
-		ev->id = sas_event_data->TargetID;
-		ev->phy_id = sas_event_data->PhyNum;
+		memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
+		hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
+		hot_plug_info.channel = sas_event_data->Bus;
+		hot_plug_info.id = sas_event_data->TargetID;
+		hot_plug_info.phy_id = sas_event_data->PhyNum;
 		memcpy(&sas_address, &sas_event_data->SASAddress,
-		    sizeof(__le64));
-		ev->sas_address = le64_to_cpu(sas_address);
-		ev->device_info = device_info;
-
+		    sizeof(u64));
+		hot_plug_info.sas_address = le64_to_cpu(sas_address);
+		hot_plug_info.device_info = device_info;
 		if (sas_event_data->ReasonCode &
 		    MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
-			ev->event_type = MPTSAS_ADD_DEVICE;
+			hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
 		else
-			ev->event_type = MPTSAS_DEL_DEVICE;
-		schedule_work(&ev->work);
+			hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
+		mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
 		break;
+
 	case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
-	/*
-	 * Persistent table is full.
-	 */
-		INIT_WORK(&ioc->sas_persist_task,
-		    mptsas_persist_clear_table);
-		schedule_work(&ioc->sas_persist_task);
+		mptbase_sas_persist_operation(ioc,
+		    MPI_SAS_OP_CLEAR_NOT_PRESENT);
+		mptsas_free_fw_event(ioc, fw_event);
 		break;
-	/*
-	 * TODO, handle other events
-	 */
+
 	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-	case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+	/* TODO */
 	case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
-	case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
-	case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
-	case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
-	case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
+	/* TODO */
 	default:
+		mptsas_free_fw_event(ioc, fw_event);
 		break;
 	}
 }
+
 static void
-mptsas_send_raid_event(MPT_ADAPTER *ioc,
-		EVENT_DATA_RAID *raid_event_data)
+mptsas_send_raid_event(struct fw_event_work *fw_event)
 {
-	struct mptsas_hotplug_event *ev;
-	int status = le32_to_cpu(raid_event_data->SettingsStatus);
-	int state = (status >> 8) & 0xff;
+	MPT_ADAPTER *ioc;
+	EVENT_DATA_RAID *raid_event_data;
+	struct mptsas_hotplug_event hot_plug_info;
+	int status;
+	int state;
+	struct scsi_device *sdev = NULL;
+	VirtDevice *vdevice = NULL;
+	RaidPhysDiskPage0_t phys_disk;
 
-	if (ioc->bus_type != SAS)
-		return;
+	ioc = fw_event->ioc;
+	raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
+	status = le32_to_cpu(raid_event_data->SettingsStatus);
+	state = (status >> 8) & 0xff;
 
-	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-	if (!ev) {
-		printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
-		return;
+	memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
+	hot_plug_info.id = raid_event_data->VolumeID;
+	hot_plug_info.channel = raid_event_data->VolumeBus;
+	hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
+
+	if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
+	    raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
+	    raid_event_data->ReasonCode ==
+	    MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
+		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
+		    hot_plug_info.id, 0);
+		hot_plug_info.sdev = sdev;
+		if (sdev)
+			vdevice = sdev->hostdata;
 	}
 
-	INIT_WORK(&ev->work, mptsas_hotplug_work);
-	ev->ioc = ioc;
-	ev->id = raid_event_data->VolumeID;
-	ev->channel = raid_event_data->VolumeBus;
-	ev->event_type = MPTSAS_IGNORE_EVENT;
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
+	    "ReasonCode=%02x\n", ioc->name, __func__,
+	    raid_event_data->ReasonCode));
 
 	switch (raid_event_data->ReasonCode) {
 	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
-		ev->phys_disk_num_valid = 1;
-		ev->phys_disk_num = raid_event_data->PhysDiskNum;
-		ev->event_type = MPTSAS_ADD_DEVICE;
+		hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
 		break;
 	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
-		ev->phys_disk_num_valid = 1;
-		ev->phys_disk_num = raid_event_data->PhysDiskNum;
-		ev->hidden_raid_component = 1;
-		ev->event_type = MPTSAS_DEL_DEVICE;
+		hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
 		break;
 	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
 		switch (state) {
 		case MPI_PD_STATE_ONLINE:
 		case MPI_PD_STATE_NOT_COMPATIBLE:
-			ev->phys_disk_num_valid = 1;
-			ev->phys_disk_num = raid_event_data->PhysDiskNum;
-			ev->hidden_raid_component = 1;
-			ev->event_type = MPTSAS_ADD_DEVICE;
+			mpt_raid_phys_disk_pg0(ioc,
+			    raid_event_data->PhysDiskNum, &phys_disk);
+			hot_plug_info.id = phys_disk.PhysDiskID;
+			hot_plug_info.channel = phys_disk.PhysDiskBus;
+			hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
 			break;
+		case MPI_PD_STATE_FAILED:
 		case MPI_PD_STATE_MISSING:
 		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
 		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
 		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
-			ev->phys_disk_num_valid = 1;
-			ev->phys_disk_num = raid_event_data->PhysDiskNum;
-			ev->event_type = MPTSAS_DEL_DEVICE;
+			hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
 			break;
 		default:
 			break;
 		}
 		break;
 	case MPI_EVENT_RAID_RC_VOLUME_DELETED:
-		ev->event_type = MPTSAS_DEL_RAID;
+		if (!sdev)
+			break;
+		vdevice->vtarget->deleted = 1; /* block IO */
+		hot_plug_info.event_type = MPTSAS_DEL_RAID;
 		break;
 	case MPI_EVENT_RAID_RC_VOLUME_CREATED:
-		ev->event_type = MPTSAS_ADD_RAID;
+		if (sdev) {
+			scsi_device_put(sdev);
+			break;
+		}
+		hot_plug_info.event_type = MPTSAS_ADD_RAID;
 		break;
 	case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
+		if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
+			if (!sdev)
+				break;
+			vdevice->vtarget->deleted = 1; /* block IO */
+			hot_plug_info.event_type = MPTSAS_DEL_RAID;
+			break;
+		}
 		switch (state) {
 		case MPI_RAIDVOL0_STATUS_STATE_FAILED:
 		case MPI_RAIDVOL0_STATUS_STATE_MISSING:
-			ev->event_type = MPTSAS_DEL_RAID;
+			if (!sdev)
+				break;
+			vdevice->vtarget->deleted = 1; /* block IO */
+			hot_plug_info.event_type = MPTSAS_DEL_RAID;
 			break;
 		case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
 		case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
-			ev->event_type = MPTSAS_ADD_RAID;
+			if (sdev) {
+				scsi_device_put(sdev);
+				break;
+			}
+			hot_plug_info.event_type = MPTSAS_ADD_RAID;
 			break;
 		default:
 			break;
@@ -3001,32 +4335,188 @@
 	default:
 		break;
 	}
-	schedule_work(&ev->work);
+
+	if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
+		mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
+	else
+		mptsas_free_fw_event(ioc, fw_event);
 }
 
+/**
+ *	mptsas_issue_tm - send mptsas internal tm request
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@type: Task Management type
+ *	@channel: channel number for task management
+ *	@id: Logical Target ID for reset (if appropriate)
+ *	@lun: Logical unit for reset (if appropriate)
+ *	@task_context: Context for the task to be aborted
+ *	@timeout: timeout for task management control
+ *
+ *	return 0 on success and -1 on failure:
+ *
+ */
+static int
+mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
+	int task_context, ulong timeout, u8 *issue_reset)
+{
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+	int		 retval;
+	unsigned long	 timeleft;
+
+	*issue_reset = 0;
+	mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
+	if (mf == NULL) {
+		retval = -1; /* return failure */
+		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
+		    "msg frames!!\n", ioc->name));
+		goto out;
+	}
+
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
+	    "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
+	    "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
+	     type, timeout, channel, id, (unsigned long long)lun,
+	     task_context));
+
+	pScsiTm = (SCSITaskMgmt_t *) mf;
+	memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
+	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
+	pScsiTm->TaskType = type;
+	pScsiTm->MsgFlags = 0;
+	pScsiTm->TargetID = id;
+	pScsiTm->Bus = channel;
+	pScsiTm->ChainOffset = 0;
+	pScsiTm->Reserved = 0;
+	pScsiTm->Reserved1 = 0;
+	pScsiTm->TaskMsgContext = task_context;
+	int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
+
+	INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
+	CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
+	retval = 0;
+	mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
+
+	/* Now wait for the command to complete */
+	timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
+	    timeout*HZ);
+	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		retval = -1; /* return failure */
+		dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
+		    "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
+		mpt_free_msg_frame(ioc, mf);
+		if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			goto out;
+		*issue_reset = 1;
+		goto out;
+	}
+
+	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
+		retval = -1; /* return failure */
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "TaskMgmt request: failed with no reply\n", ioc->name));
+		goto out;
+	}
+
+ out:
+	CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
+	return retval;
+}
+
+/**
+ *	mptsas_broadcast_primative_work - Handle broadcast primitives
+ *	@work: work queue payload containing info describing the event
+ *
+ *	this will be handled in workqueue context.
+ */
 static void
-mptsas_send_discovery_event(MPT_ADAPTER *ioc,
-	EVENT_DATA_SAS_DISCOVERY *discovery_data)
+mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
 {
-	struct mptsas_discovery_event *ev;
+	MPT_ADAPTER *ioc = fw_event->ioc;
+	MPT_FRAME_HDR	*mf;
+	VirtDevice	*vdevice;
+	int			ii;
+	struct scsi_cmnd	*sc;
+	SCSITaskMgmtReply_t	*pScsiTmReply;
+	u8			issue_reset;
+	int			task_context;
+	u8			channel, id;
+	int			 lun;
+	u32			 termination_count;
+	u32			 query_count;
 
-	/*
-	 * DiscoveryStatus
-	 *
-	 * This flag will be non-zero when firmware
-	 * kicks off discovery, and return to zero
-	 * once its completed.
-	 */
-	if (discovery_data->DiscoveryStatus)
-		return;
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "%s - enter\n", ioc->name, __func__));
 
-	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-	if (!ev)
+	mutex_lock(&ioc->taskmgmt_cmds.mutex);
+	if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
+		mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+		mptsas_requeue_fw_event(ioc, fw_event, 1000);
 		return;
-	INIT_WORK(&ev->work, mptsas_discovery_work);
-	ev->ioc = ioc;
-	schedule_work(&ev->work);
-};
+	}
+
+	issue_reset = 0;
+	termination_count = 0;
+	query_count = 0;
+	mpt_findImVolumes(ioc);
+	pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
+
+	for (ii = 0; ii < ioc->req_depth; ii++) {
+		if (ioc->fw_events_off)
+			goto out;
+		sc = mptscsih_get_scsi_lookup(ioc, ii);
+		if (!sc)
+			continue;
+		mf = MPT_INDEX_2_MFPTR(ioc, ii);
+		if (!mf)
+			continue;
+		task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
+		vdevice = sc->device->hostdata;
+		if (!vdevice || !vdevice->vtarget)
+			continue;
+		if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
+			continue; /* skip hidden raid components */
+		if (vdevice->vtarget->raidVolume)
+			continue; /* skip hidden raid components */
+		channel = vdevice->vtarget->channel;
+		id = vdevice->vtarget->id;
+		lun = vdevice->lun;
+		if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
+		    channel, id, (u64)lun, task_context, 30, &issue_reset))
+			goto out;
+		query_count++;
+		termination_count +=
+		    le32_to_cpu(pScsiTmReply->TerminationCount);
+		if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
+		    (pScsiTmReply->ResponseCode ==
+		    MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
+		    pScsiTmReply->ResponseCode ==
+		    MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
+			continue;
+		if (mptsas_issue_tm(ioc,
+		    MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
+		    channel, id, (u64)lun, 0, 30, &issue_reset))
+			goto out;
+		termination_count +=
+		    le32_to_cpu(pScsiTmReply->TerminationCount);
+	}
+
+ out:
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "%s - exit, query_count = %d termination_count = %d\n",
+	    ioc->name, __func__, query_count, termination_count));
+
+	ioc->broadcast_aen_busy = 0;
+	mpt_clear_taskmgmt_in_progress_flag(ioc);
+	mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+
+	if (issue_reset) {
+		printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
+		    ioc->name, __func__);
+		mpt_HardResetHandler(ioc, CAN_SLEEP);
+	}
+	mptsas_free_fw_event(ioc, fw_event);
+}
 
 /*
  * mptsas_send_ir2_event - handle exposing hidden disk when
@@ -3037,76 +4527,159 @@
  *
  */
 static void
-mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
+mptsas_send_ir2_event(struct fw_event_work *fw_event)
 {
-	struct mptsas_hotplug_event *ev;
-
-	if (ir2_data->ReasonCode !=
-	    MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
-		return;
+	MPT_ADAPTER	*ioc;
+	struct mptsas_hotplug_event hot_plug_info;
+	MPI_EVENT_DATA_IR2	*ir2_data;
+	u8 reasonCode;
+	RaidPhysDiskPage0_t phys_disk;
 
-	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
-	if (!ev)
-		return;
+	ioc = fw_event->ioc;
+	ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
+	reasonCode = ir2_data->ReasonCode;
 
-	INIT_WORK(&ev->work, mptsas_hotplug_work);
-	ev->ioc = ioc;
-	ev->id = ir2_data->TargetID;
-	ev->channel = ir2_data->Bus;
-	ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
+	    "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
 
-	schedule_work(&ev->work);
-};
+	memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
+	hot_plug_info.id = ir2_data->TargetID;
+	hot_plug_info.channel = ir2_data->Bus;
+	switch (reasonCode) {
+	case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
+		hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
+		break;
+	case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
+		hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
+		hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
+		break;
+	case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
+		hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
+		mpt_raid_phys_disk_pg0(ioc,
+		    ir2_data->PhysDiskNum, &phys_disk);
+		hot_plug_info.id = phys_disk.PhysDiskID;
+		hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
+		break;
+	default:
+		mptsas_free_fw_event(ioc, fw_event);
+		return;
+	}
+	mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
+}
 
 static int
 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
 {
-	int rc=1;
-	u8 event = le32_to_cpu(reply->Event) & 0xFF;
-
-	if (!ioc->sh)
-		goto out;
+	u32 event = le32_to_cpu(reply->Event);
+	int sz, event_data_sz;
+	struct fw_event_work *fw_event;
+	unsigned long delay;
 
-	/*
-	 * sas_discovery_ignore_events
-	 *
-	 * This flag is to prevent anymore processing of
-	 * sas events once mptsas_remove function is called.
-	 */
-	if (ioc->sas_discovery_ignore_events) {
-		rc = mptscsih_event_process(ioc, reply);
-		goto out;
-	}
+	/* events turned off due to host reset or driver unloading */
+	if (ioc->fw_events_off)
+		return 0;
 
+	delay = msecs_to_jiffies(1);
 	switch (event) {
+	case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
+	{
+		EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
+		    (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
+		if (broadcast_event_data->Primitive !=
+		    MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
+			return 0;
+		if (ioc->broadcast_aen_busy)
+			return 0;
+		ioc->broadcast_aen_busy = 1;
+		break;
+	}
 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
-		mptsas_send_sas_event(ioc,
-			(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+	{
+		EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
+		    (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
+
+		if (sas_event_data->ReasonCode ==
+		    MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
+			mptsas_target_reset_queue(ioc, sas_event_data);
+			return 0;
+		}
 		break;
-	case MPI_EVENT_INTEGRATED_RAID:
-		mptsas_send_raid_event(ioc,
-			(EVENT_DATA_RAID *)reply->Data);
+	}
+	case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
+	{
+		MpiEventDataSasExpanderStatusChange_t *expander_data =
+		    (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
+
+		if (ioc->old_sas_discovery_protocal)
+			return 0;
+
+		if (expander_data->ReasonCode ==
+		    MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
+		    ioc->device_missing_delay)
+			delay = HZ * ioc->device_missing_delay;
 		break;
+	}
+	case MPI_EVENT_SAS_DISCOVERY:
+	{
+		u32 discovery_status;
+		EventDataSasDiscovery_t *discovery_data =
+		    (EventDataSasDiscovery_t *)reply->Data;
+
+		discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
+		ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
+		if (ioc->old_sas_discovery_protocal && !discovery_status)
+			mptsas_queue_rescan(ioc);
+		return 0;
+	}
+	case MPI_EVENT_INTEGRATED_RAID:
 	case MPI_EVENT_PERSISTENT_TABLE_FULL:
-		INIT_WORK(&ioc->sas_persist_task,
-		    mptsas_persist_clear_table);
-		schedule_work(&ioc->sas_persist_task);
-		break;
-	 case MPI_EVENT_SAS_DISCOVERY:
-		mptsas_send_discovery_event(ioc,
-			(EVENT_DATA_SAS_DISCOVERY *)reply->Data);
-		break;
 	case MPI_EVENT_IR2:
-		mptsas_send_ir2_event(ioc,
-		    (PTR_MPI_EVENT_DATA_IR2)reply->Data);
+	case MPI_EVENT_SAS_PHY_LINK_STATUS:
+	case MPI_EVENT_QUEUE_FULL:
 		break;
 	default:
-		rc = mptscsih_event_process(ioc, reply);
-		break;
+		return 0;
 	}
- out:
 
-	return rc;
+	event_data_sz = ((reply->MsgLength * 4) -
+	    offsetof(EventNotificationReply_t, Data));
+	sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
+	fw_event = kzalloc(sz, GFP_ATOMIC);
+	if (!fw_event) {
+		printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
+		 __func__, __LINE__);
+		return 0;
+	}
+	memcpy(fw_event->event_data, reply->Data, event_data_sz);
+	fw_event->event = event;
+	fw_event->ioc = ioc;
+	mptsas_add_fw_event(ioc, fw_event, delay);
+	return 0;
+}
+
+/* Delete a volume when no longer listed in ioc pg2
+ */
+static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
+{
+	struct scsi_device *sdev;
+	int i;
+
+	sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
+	if (!sdev)
+		return;
+	if (!ioc->raid_data.pIocPg2)
+		goto out;
+	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+		goto out;
+	for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
+		if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
+			goto release_sdev;
+ out:
+	printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
+	    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
+	scsi_remove_device(sdev);
+ release_sdev:
+	scsi_device_put(sdev);
 }
 
 static int
@@ -3128,6 +4701,7 @@
 		return r;
 
 	ioc = pci_get_drvdata(pdev);
+	mptsas_fw_event_off(ioc);
 	ioc->DoneCtx = mptsasDoneCtx;
 	ioc->TaskCtx = mptsasTaskCtx;
 	ioc->InternalCtx = mptsasInternalCtx;
@@ -3211,17 +4785,15 @@
 	 * A slightly different algorithm is required for
 	 * 64bit SGEs.
 	 */
-	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
+	scale = ioc->req_sz/ioc->SGE_size;
+	if (ioc->sg_addr_size == sizeof(u64)) {
 		numSGE = (scale - 1) *
 		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
+		  (ioc->req_sz - 60) / ioc->SGE_size;
 	} else {
 		numSGE = 1 + (scale - 1) *
 		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
+		  (ioc->req_sz - 64) / ioc->SGE_size;
 	}
 
 	if (numSGE < sh->sg_tablesize) {
@@ -3251,9 +4823,6 @@
 
 	/* Clear the TM flags
 	 */
-	hd->tmPending = 0;
-	hd->tmState = TM_STATE_NONE;
-	hd->resetPending = 0;
 	hd->abortSCpnt = NULL;
 
 	/* Clear the pointer used to store
@@ -3273,10 +4842,11 @@
 
 	ioc->sas_data.ptClear = mpt_pt_clear;
 
-	init_waitqueue_head(&hd->scandv_waitq);
-	hd->scandv_wait_done = 0;
 	hd->last_queue_full = 0;
 	INIT_LIST_HEAD(&hd->target_reset_list);
+	INIT_LIST_HEAD(&ioc->sas_device_info_list);
+	mutex_init(&ioc->sas_device_info_mutex);
+
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 	if (ioc->sas_data.ptClear==1) {
@@ -3291,8 +4861,11 @@
 		goto out_mptsas_probe;
 	}
 
+	/* older firmware doesn't support expander events */
+	if ((ioc->facts.HeaderVersion >> 8) < 0xE)
+		ioc->old_sas_discovery_protocal = 1;
 	mptsas_scan_sas_topology(ioc);
-
+	mptsas_fw_event_on(ioc);
 	return 0;
 
  out_mptsas_probe:
@@ -3301,12 +4874,25 @@
 	return error;
 }
 
+void
+mptsas_shutdown(struct pci_dev *pdev)
+{
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+
+	mptsas_fw_event_off(ioc);
+	mptsas_cleanup_fw_event_q(ioc);
+}
+
 static void __devexit mptsas_remove(struct pci_dev *pdev)
 {
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 	struct mptsas_portinfo *p, *n;
 	int i;
 
+	mptsas_shutdown(pdev);
+
+	mptsas_del_device_components(ioc);
+
 	ioc->sas_discovery_ignore_events = 1;
 	sas_remove_host(ioc->sh);
 
@@ -3315,11 +4901,12 @@
 		list_del(&p->list);
 		for (i = 0 ; i < p->num_phys ; i++)
 			mptsas_port_delete(ioc, p->phy_info[i].port_details);
+
 		kfree(p->phy_info);
 		kfree(p);
 	}
 	mutex_unlock(&ioc->sas_topology_mutex);
-
+	ioc->hba_port_info = NULL;
 	mptscsih_remove(pdev);
 }
 
@@ -3344,7 +4931,7 @@
 	.id_table	= mptsas_pci_table,
 	.probe		= mptsas_probe,
 	.remove		= __devexit_p(mptsas_remove),
-	.shutdown	= mptscsih_shutdown,
+	.shutdown	= mptsas_shutdown,
 #ifdef CONFIG_PM
 	.suspend	= mptscsih_suspend,
 	.resume		= mptscsih_resume,
@@ -3364,10 +4951,12 @@
 		return -ENODEV;
 
 	mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
-	mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
+	mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
 	mptsasInternalCtx =
 		mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
 	mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
+	mptsasDeviceResetCtx =
+		mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
 
 	mpt_event_register(mptsasDoneCtx, mptsas_event_process);
 	mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
@@ -3392,6 +4981,7 @@
 	mpt_deregister(mptsasInternalCtx);
 	mpt_deregister(mptsasTaskCtx);
 	mpt_deregister(mptsasDoneCtx);
+	mpt_deregister(mptsasDeviceResetCtx);
 }
 
 module_init(mptsas_init);
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptsas.h linux-libre-2.6.31-gnu/drivers/message/fusion/mptsas.h
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptsas.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptsas.h	2009-09-09 18:13:59.000000000 -0400
@@ -53,6 +53,7 @@
 	struct list_head 	list;
 	EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
 	u8	target_reset_issued;
+	unsigned long	 time_count;
 };
 
 enum mptsas_hotplug_action {
@@ -60,12 +61,37 @@
 	MPTSAS_DEL_DEVICE,
 	MPTSAS_ADD_RAID,
 	MPTSAS_DEL_RAID,
+	MPTSAS_ADD_PHYSDISK,
+	MPTSAS_ADD_PHYSDISK_REPROBE,
+	MPTSAS_DEL_PHYSDISK,
+	MPTSAS_DEL_PHYSDISK_REPROBE,
 	MPTSAS_ADD_INACTIVE_VOLUME,
 	MPTSAS_IGNORE_EVENT,
 };
 
+struct mptsas_mapping{
+	u8			id;
+	u8			channel;
+};
+
+struct mptsas_device_info {
+	struct list_head 	list;
+	struct mptsas_mapping	os;	/* operating system mapping*/
+	struct mptsas_mapping	fw;	/* firmware mapping */
+	u64			sas_address;
+	u32			device_info; /* specific bits for devices */
+	u16			slot;		/* enclosure slot id */
+	u64			enclosure_logical_id; /*enclosure address */
+	u8			is_logical_volume; /* is this logical volume */
+	/* this belongs to volume */
+	u8			is_hidden_raid_component;
+	/* this valid when is_hidden_raid_component set */
+	u8			volume_id;
+	/* cached data for a removed device */
+	u8			is_cached;
+};
+
 struct mptsas_hotplug_event {
-	struct work_struct	work;
 	MPT_ADAPTER		*ioc;
 	enum mptsas_hotplug_action event_type;
 	u64			sas_address;
@@ -73,11 +99,18 @@
 	u8			id;
 	u32			device_info;
 	u16			handle;
-	u16			parent_handle;
 	u8			phy_id;
-	u8			phys_disk_num_valid;	/* hrc (hidden raid component) */
 	u8			phys_disk_num;		/* hrc - unique index*/
-	u8			hidden_raid_component;	/* hrc - don't expose*/
+	struct scsi_device	*sdev;
+};
+
+struct fw_event_work {
+	struct list_head 	list;
+	struct delayed_work	 work;
+	MPT_ADAPTER	*ioc;
+	u32			event;
+	u8			retries;
+	u8			event_data[1];
 };
 
 struct mptsas_discovery_event {
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptscsih.c linux-libre-2.6.31-gnu/drivers/message/fusion/mptscsih.c
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptscsih.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptscsih.c	2009-09-09 18:13:59.000000000 -0400
@@ -80,7 +80,7 @@
 /*
  *  Other private/forward protos...
  */
-static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
+struct scsi_cmnd	*mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
 static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
 static void	mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
 static int	SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
@@ -92,18 +92,24 @@
 				 SCSIIORequest_t *pReq, int req_idx);
 static void	mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
 static void	mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
-static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
-static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
 
-static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
+int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id,
+		int lun, int ctx2abort, ulong timeout);
 
 int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
+void
+mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
+static int	mptscsih_get_completion_code(MPT_ADAPTER *ioc,
+		MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
 int		mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static void	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
 
+static int
+mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
+				SCSITaskMgmtReply_t *pScsiTmReply);
 void 		mptscsih_remove(struct pci_dev *);
 void 		mptscsih_shutdown(struct pci_dev *);
 #ifdef CONFIG_PM
@@ -113,69 +119,6 @@
 
 #define SNS_LEN(scp)	SCSI_SENSE_BUFFERSIZE
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_add_sge - Place a simple SGE at address pAddr.
- *	@pAddr: virtual address for SGE
- *	@flagslength: SGE flags and data transfer length
- *	@dma_addr: Physical address
- *
- *	This routine places a MPT request frame back on the MPT adapter's
- *	FreeQ.
- */
-static inline void
-mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
-{
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
-		SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
-		u32 tmp = dma_addr & 0xFFFFFFFF;
-
-		pSge->FlagsLength = cpu_to_le32(flagslength);
-		pSge->Address.Low = cpu_to_le32(tmp);
-		tmp = (u32) ((u64)dma_addr >> 32);
-		pSge->Address.High = cpu_to_le32(tmp);
-
-	} else {
-		SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
-		pSge->FlagsLength = cpu_to_le32(flagslength);
-		pSge->Address = cpu_to_le32(dma_addr);
-	}
-} /* mptscsih_add_sge() */
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_add_chain - Place a chain SGE at address pAddr.
- *	@pAddr: virtual address for SGE
- *	@next: nextChainOffset value (u32's)
- *	@length: length of next SGL segment
- *	@dma_addr: Physical address
- *
- *	This routine places a MPT request frame back on the MPT adapter's
- *	FreeQ.
- */
-static inline void
-mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
-{
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
-		SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
-		u32 tmp = dma_addr & 0xFFFFFFFF;
-
-		pChain->Length = cpu_to_le16(length);
-		pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
-
-		pChain->NextChainOffset = next;
-
-		pChain->Address.Low = cpu_to_le32(tmp);
-		tmp = (u32) ((u64)dma_addr >> 32);
-		pChain->Address.High = cpu_to_le32(tmp);
-	} else {
-		SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
-		pChain->Length = cpu_to_le16(length);
-		pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
-		pChain->NextChainOffset = next;
-		pChain->Address = cpu_to_le32(dma_addr);
-	}
-} /* mptscsih_add_chain() */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -281,10 +224,10 @@
 	 */
 
 nextSGEset:
-	numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
+	numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size);
 	numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
 
-	sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
+	sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir;
 
 	/* Get first (num - 1) SG elements
 	 * Skip any SG entries with a length of 0
@@ -293,17 +236,19 @@
 	for (ii=0; ii < (numSgeThisFrame-1); ii++) {
 		thisxfer = sg_dma_len(sg);
 		if (thisxfer == 0) {
-			sg = sg_next(sg); /* Get next SG element from the OS */
+			/* Get next SG element from the OS */
+			sg = sg_next(sg);
 			sg_done++;
 			continue;
 		}
 
 		v2 = sg_dma_address(sg);
-		mptscsih_add_sge(psge, sgflags | thisxfer, v2);
+		ioc->add_sge(psge, sgflags | thisxfer, v2);
 
-		sg = sg_next(sg);	/* Get next SG element from the OS */
-		psge += (sizeof(u32) + sizeof(dma_addr_t));
-		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
+		/* Get next SG element from the OS */
+		sg = sg_next(sg);
+		psge += ioc->SGE_size;
+		sgeOffset += ioc->SGE_size;
 		sg_done++;
 	}
 
@@ -320,12 +265,8 @@
 		thisxfer = sg_dma_len(sg);
 
 		v2 = sg_dma_address(sg);
-		mptscsih_add_sge(psge, sgflags | thisxfer, v2);
-		/*
-		sg = sg_next(sg);
-		psge += (sizeof(u32) + sizeof(dma_addr_t));
-		*/
-		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
+		ioc->add_sge(psge, sgflags | thisxfer, v2);
+		sgeOffset += ioc->SGE_size;
 		sg_done++;
 
 		if (chainSge) {
@@ -334,7 +275,8 @@
 			 * Update the chain element
 			 * Offset and Length fields.
 			 */
-			mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
+			ioc->add_chain((char *)chainSge, 0, sgeOffset,
+				ioc->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The current buffer is the original MF
 			 * and there is no Chain buffer.
@@ -367,7 +309,7 @@
 		 * set properly).
 		 */
 		if (sg_done) {
-			u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
+			u32 *ptmp = (u32 *) (psge - ioc->SGE_size);
 			sgflags = le32_to_cpu(*ptmp);
 			sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
 			*ptmp = cpu_to_le32(sgflags);
@@ -381,8 +323,9 @@
 			 * Old chain element is now complete.
 			 */
 			u8 nextChain = (u8) (sgeOffset >> 2);
-			sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
-			mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
+			sgeOffset += ioc->SGE_size;
+			ioc->add_chain((char *)chainSge, nextChain, sgeOffset,
+					 ioc->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The original MF buffer requires a chain buffer -
 			 * set the offset.
@@ -592,14 +535,15 @@
 	}
 
 	scsi_print_command(sc);
-	printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n",
-	    ioc->name, pScsiReply->Bus, pScsiReply->TargetID);
+	printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n",
+	    ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun);
 	printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
 	    "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
 	    scsi_get_resid(sc));
 	printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "
 	    "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),
 	    le32_to_cpu(pScsiReply->TransferCount), sc->result);
+
 	printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "
 	    "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
 	    ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,
@@ -654,16 +598,14 @@
 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
 	req_idx_MR = (mr != NULL) ?
 	    le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
+
+	/* Special case, where already freed message frame is received from
+	 * Firmware. It happens with Resetting IOC.
+	 * Return immediately. Do not care
+	 */
 	if ((req_idx != req_idx_MR) ||
-	    (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
-		printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
-		    ioc->name);
-		printk (MYIOC_s_ERR_FMT
-		    "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
-		    ioc->name, req_idx, req_idx_MR, mf, mr,
-		    mptscsih_get_scsi_lookup(ioc, req_idx_MR));
+	    (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf))
 		return 0;
-	}
 
 	sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
 	if (sc == NULL) {
@@ -810,12 +752,16 @@
 			 */
 
 		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
-		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
 			/* Linux handles an unsolicited DID_RESET better
 			 * than an unsolicited DID_ABORT.
 			 */
 			sc->result = DID_RESET << 16;
 
+		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
+			if (ioc->bus_type == FC)
+				sc->result = DID_ERROR << 16;
+			else
+				sc->result = DID_RESET << 16;
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
@@ -992,9 +938,9 @@
 		scsi_dma_unmap(sc);
 		sc->result = DID_RESET << 16;
 		sc->host_scribble = NULL;
-		sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
-		    "completing cmds: fw_channel %d, fw_id %d, sc=%p,"
-		    " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii);
+		dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
+		    "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, "
+		    "idx=%x\n", ioc->name, channel, id, sc, mf, ii));
 		sc->scsi_done(sc);
 	}
 }
@@ -1053,9 +999,11 @@
 			scsi_dma_unmap(sc);
 			sc->host_scribble = NULL;
 			sc->result = DID_NO_CONNECT << 16;
-			sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d,"
-			   "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel,
-			   vdevice->vtarget->id, sc, mf, ii);
+			dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device,
+			   MYIOC_s_FMT "completing cmds: fw_channel %d, "
+			   "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name,
+			   vdevice->vtarget->channel, vdevice->vtarget->id,
+			   sc, mf, ii));
 			sc->scsi_done(sc);
 			spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
 		}
@@ -1346,7 +1294,6 @@
 	MPT_FRAME_HDR		*mf;
 	SCSIIORequest_t		*pScsiReq;
 	VirtDevice		*vdevice = SCpnt->device->hostdata;
-	int	 lun;
 	u32	 datalen;
 	u32	 scsictl;
 	u32	 scsidir;
@@ -1357,13 +1304,12 @@
 
 	hd = shost_priv(SCpnt->device->host);
 	ioc = hd->ioc;
-	lun = SCpnt->device->lun;
 	SCpnt->scsi_done = done;
 
 	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
 		ioc->name, SCpnt, done));
 
-	if (hd->resetPending) {
+	if (ioc->taskmgmt_quiesce_io) {
 		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
 			ioc->name, SCpnt));
 		return SCSI_MLQUEUE_HOST_BUSY;
@@ -1422,7 +1368,7 @@
 	pScsiReq->CDBLength = SCpnt->cmd_len;
 	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
 	pScsiReq->Reserved = 0;
-	pScsiReq->MsgFlags = mpt_msg_flags();
+	pScsiReq->MsgFlags = mpt_msg_flags(ioc);
 	int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
 	pScsiReq->Control = cpu_to_le32(scsictl);
 
@@ -1448,7 +1394,8 @@
 	 */
 	if (datalen == 0) {
 		/* Add a NULL SGE */
-		mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
+		ioc->add_sge((char *)&pScsiReq->SGL,
+			MPT_SGE_FLAGS_SSIMPLE_READ | 0,
 			(dma_addr_t) -1);
 	} else {
 		/* Add a 32 or 64 bit SGE */
@@ -1528,8 +1475,8 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mptscsih_TMHandler - Generic handler for SCSI Task Management.
- *	@hd: Pointer to MPT SCSI HOST structure
+ *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
+ *	@hd: Pointer to MPT_SCSI_HOST structure
  *	@type: Task Management type
  *	@channel: channel number for task management
  *	@id: Logical Target ID for reset (if appropriate)
@@ -1537,145 +1484,68 @@
  *	@ctx2abort: Context for the task to be aborted (if appropriate)
  *	@timeout: timeout for task management control
  *
- *	Fall through to mpt_HardResetHandler if: not operational, too many
- *	failed TM requests or handshake failure.
+ *	Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
+ *	or a non-interrupt thread.  In the former, must not call schedule().
  *
- *	Remark: Currently invoked from a non-interrupt thread (_bh).
+ *	Not all fields are meaningfull for all task types.
  *
- *	Note: With old EH code, at most 1 SCSI TaskMgmt function per IOC
- *	will be active.
+ *	Returns 0 for SUCCESS, or FAILED.
  *
- *	Returns 0 for SUCCESS, or %FAILED.
  **/
 int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
+	int ctx2abort, ulong timeout)
 {
-	MPT_ADAPTER	*ioc;
-	int		 rc = -1;
+	MPT_FRAME_HDR	*mf;
+	SCSITaskMgmt_t	*pScsiTm;
+	int		 ii;
+	int		 retval;
+	MPT_ADAPTER 	*ioc = hd->ioc;
+	unsigned long	 timeleft;
+	u8		 issue_hard_reset;
 	u32		 ioc_raw_state;
-	unsigned long	 flags;
-
-	ioc = hd->ioc;
-	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name));
-
-	// SJR - CHECKME - Can we avoid this here?
-	// (mpt_HardResetHandler has this check...)
-	spin_lock_irqsave(&ioc->diagLock, flags);
-	if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
-		spin_unlock_irqrestore(&ioc->diagLock, flags);
-		return FAILED;
-	}
-	spin_unlock_irqrestore(&ioc->diagLock, flags);
-
-	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
-	 *  If we time out and not bus reset, then we return a FAILED status
-	 *  to the caller.
-	 *  The call to mptscsih_tm_pending_wait() will set the pending flag
-	 *  if we are
-	 *  successful. Otherwise, reload the FW.
-	 */
-	if (mptscsih_tm_pending_wait(hd) == FAILED) {
-		if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
-			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: "
-			   "Timed out waiting for last TM (%d) to complete! \n",
-			   ioc->name, hd->tmPending));
-			return FAILED;
-		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
-			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target "
-				"reset: Timed out waiting for last TM (%d) "
-				"to complete! \n", ioc->name,
-				hd->tmPending));
-			return FAILED;
-		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
-			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: "
-			   "Timed out waiting for last TM (%d) to complete! \n",
-			  ioc->name, hd->tmPending));
-			return FAILED;
-		}
-	} else {
-		spin_lock_irqsave(&ioc->FreeQlock, flags);
-		hd->tmPending |=  (1 << type);
-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-	}
+	unsigned long	 time_count;
 
+	issue_hard_reset = 0;
 	ioc_raw_state = mpt_GetIocState(ioc, 0);
 
 	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
 		printk(MYIOC_s_WARN_FMT
-			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",
+			"TaskMgmt type=%x: IOC Not operational (0x%x)!\n",
 			ioc->name, type, ioc_raw_state);
-		printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name);
+		printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
+		    ioc->name, __func__);
 		if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
-			printk(MYIOC_s_WARN_FMT "TMHandler: HardReset "
+			printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset "
 			    "FAILED!!\n", ioc->name);
-		return FAILED;
+		return 0;
 	}
 
 	if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
 		printk(MYIOC_s_WARN_FMT
-			"TM Handler for type=%x: ioc_state: "
+			"TaskMgmt type=%x: ioc_state: "
 			"DOORBELL_ACTIVE (0x%x)!\n",
 			ioc->name, type, ioc_raw_state);
 		return FAILED;
 	}
 
-	/* Isse the Task Mgmt request.
-	 */
-	if (hd->hard_resets < -1)
-		hd->hard_resets++;
-
-	rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
-	    ctx2abort, timeout);
-	if (rc)
-		printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
-		       ioc->name);
-	else
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",
-			   ioc->name));
-
-	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-			"TMHandler rc = %d!\n", ioc->name, rc));
-
-	return rc;
-}
-
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
- *	@hd: Pointer to MPT_SCSI_HOST structure
- *	@type: Task Management type
- *	@channel: channel number for task management
- *	@id: Logical Target ID for reset (if appropriate)
- *	@lun: Logical Unit for reset (if appropriate)
- *	@ctx2abort: Context for the task to be aborted (if appropriate)
- *	@timeout: timeout for task management control
- *
- *	Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
- *	or a non-interrupt thread.  In the former, must not call schedule().
- *
- *	Not all fields are meaningfull for all task types.
- *
- *	Returns 0 for SUCCESS, or FAILED.
- *
- **/
-static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
-{
-	MPT_FRAME_HDR	*mf;
-	SCSITaskMgmt_t	*pScsiTm;
-	int		 ii;
-	int		 retval;
-	MPT_ADAPTER 	*ioc = hd->ioc;
+	mutex_lock(&ioc->taskmgmt_cmds.mutex);
+	if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
+		mf = NULL;
+		retval = FAILED;
+		goto out;
+	}
 
 	/* Return Fail to calling function if no message frames available.
 	 */
 	if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
-		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
-				ioc->name));
-		return FAILED;
+		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+			"TaskMgmt no msg frames!!\n", ioc->name));
+		retval = FAILED;
+		mpt_clear_taskmgmt_in_progress_flag(ioc);
+		goto out;
 	}
-	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
 			ioc->name, mf));
 
 	/* Format the Request
@@ -1699,11 +1569,14 @@
 
 	pScsiTm->TaskMsgContext = ctx2abort;
 
-	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
-		"type=%d\n", ioc->name, ctx2abort, type));
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) "
+		"task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort,
+		type, timeout));
 
 	DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
 
+	INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
+	time_count = jiffies;
 	if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
 	    (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
 		mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
@@ -1711,47 +1584,50 @@
 		retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
 			sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
 		if (retval) {
-			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
-			" (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd,
-			ioc, mf, retval));
-			goto fail_out;
+			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+				"TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n",
+				ioc->name, mf, retval));
+			mpt_free_msg_frame(ioc, mf);
+			mpt_clear_taskmgmt_in_progress_flag(ioc);
+			goto out;
 		}
 	}
 
-	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
-		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
-			" (hd %p, ioc %p, mf %p) \n", ioc->name, hd,
-			ioc, mf));
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
-			 ioc->name));
-		retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
-			 ioc->name, retval));
-		goto fail_out;
+	timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
+		timeout*HZ);
+	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		retval = FAILED;
+		dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
+		    "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf));
+		mpt_clear_taskmgmt_in_progress_flag(ioc);
+		if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			goto out;
+		issue_hard_reset = 1;
+		goto out;
 	}
 
-	/*
-	 * Handle success case, see if theres a non-zero ioc_status.
-	 */
-	if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
-	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
-	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
-		retval = 0;
-	else
-		retval = FAILED;
+	retval = mptscsih_taskmgmt_reply(ioc, type,
+	    (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply);
 
-	return retval;
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "TaskMgmt completed (%d seconds)\n",
+	    ioc->name, jiffies_to_msecs(jiffies - time_count)/1000));
 
- fail_out:
+ out:
 
-	/*
-	 * Free task management mf, and corresponding tm flags
-	 */
-	mpt_free_msg_frame(ioc, mf);
-	hd->tmPending = 0;
-	hd->tmState = TM_STATE_NONE;
-	return FAILED;
+	CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
+	if (issue_hard_reset) {
+		printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
+			ioc->name, __func__);
+		retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
+		mpt_free_msg_frame(ioc, mf);
+	}
+
+	retval = (retval == 0) ? 0 : FAILED;
+	mutex_unlock(&ioc->taskmgmt_cmds.mutex);
+	return retval;
 }
+EXPORT_SYMBOL(mptscsih_IssueTaskMgmt);
 
 static int
 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
@@ -1838,13 +1714,8 @@
 		goto out;
 	}
 
-	if (hd->resetPending) {
-		retval = FAILED;
-		goto out;
-	}
-
-	if (hd->timeouts < -1)
-		hd->timeouts++;
+	if (ioc->timeouts < -1)
+		ioc->timeouts++;
 
 	if (mpt_fwfault_debug)
 		mpt_halt_firmware(ioc);
@@ -1861,22 +1732,30 @@
 
 	hd->abortSCpnt = SCpnt;
 
-	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-	    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
-	    ctx2abort, mptscsih_get_tm_timeout(ioc));
+	retval = mptscsih_IssueTaskMgmt(hd,
+			 MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+			 vdevice->vtarget->channel,
+			 vdevice->vtarget->id, vdevice->lun,
+			 ctx2abort, mptscsih_get_tm_timeout(ioc));
 
 	if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
-	    SCpnt->serial_number == sn)
+	    SCpnt->serial_number == sn) {
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "task abort: command still in active list! (sc=%p)\n",
+		    ioc->name, SCpnt));
 		retval = FAILED;
+	} else {
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "task abort: command cleared from active list! (sc=%p)\n",
+		    ioc->name, SCpnt));
+		retval = SUCCESS;
+	}
 
  out:
 	printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
-	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+	    ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt);
 
-	if (retval == 0)
-		return SUCCESS;
-	else
-		return FAILED;
+	return retval;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1909,14 +1788,9 @@
 	       ioc->name, SCpnt);
 	scsi_print_command(SCpnt);
 
-	if (hd->resetPending) {
-		retval = FAILED;
-		goto out;
-	}
-
 	vdevice = SCpnt->device->hostdata;
 	if (!vdevice || !vdevice->vtarget) {
-		retval = 0;
+		retval = SUCCESS;
 		goto out;
 	}
 
@@ -1927,9 +1801,11 @@
 		goto out;
 	}
 
-	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-	    vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
-	    mptscsih_get_tm_timeout(ioc));
+	retval = mptscsih_IssueTaskMgmt(hd,
+				MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+				vdevice->vtarget->channel,
+				vdevice->vtarget->id, 0, 0,
+				mptscsih_get_tm_timeout(ioc));
 
  out:
 	printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
@@ -1972,12 +1848,16 @@
 	       ioc->name, SCpnt);
 	scsi_print_command(SCpnt);
 
-	if (hd->timeouts < -1)
-		hd->timeouts++;
+	if (ioc->timeouts < -1)
+		ioc->timeouts++;
 
 	vdevice = SCpnt->device->hostdata;
-	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-	    vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
+	if (!vdevice || !vdevice->vtarget)
+		return SUCCESS;
+	retval = mptscsih_IssueTaskMgmt(hd,
+					MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+					vdevice->vtarget->channel, 0, 0, 0,
+					mptscsih_get_tm_timeout(ioc));
 
 	printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
 	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
@@ -2001,8 +1881,9 @@
 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 {
 	MPT_SCSI_HOST *  hd;
-	int              retval;
+	int              status = SUCCESS;
 	MPT_ADAPTER	*ioc;
+	int		retval;
 
 	/*  If we can't locate the host to reset, then we failed. */
 	if ((hd = shost_priv(SCpnt->device->host)) == NULL){
@@ -2021,86 +1902,71 @@
 	/*  If our attempts to reset the host failed, then return a failed
 	 *  status.  The host will be taken off line by the SCSI mid-layer.
 	 */
-	if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) {
-		retval = FAILED;
-	} else {
-		/*  Make sure TM pending is cleared and TM state is set to
-		 *  NONE.
-		 */
-		retval = 0;
-		hd->tmPending = 0;
-		hd->tmState = TM_STATE_NONE;
-	}
+    retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
+	if (retval < 0)
+		status = FAILED;
+	else
+		status = SUCCESS;
 
 	printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
 	    ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
 
-	return retval;
+	return status;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_tm_pending_wait - wait for pending task management request to complete
- *	@hd: Pointer to MPT host structure.
- *
- *	Returns {SUCCESS,FAILED}.
- */
 static int
-mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
+mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
+	SCSITaskMgmtReply_t *pScsiTmReply)
 {
-	unsigned long  flags;
-	int            loop_count = 4 * 10;  /* Wait 10 seconds */
-	int            status = FAILED;
-	MPT_ADAPTER	*ioc = hd->ioc;
+	u16			 iocstatus;
+	u32			 termination_count;
+	int			 retval;
 
-	do {
-		spin_lock_irqsave(&ioc->FreeQlock, flags);
-		if (hd->tmState == TM_STATE_NONE) {
-			hd->tmState = TM_STATE_IN_PROGRESS;
-			hd->tmPending = 1;
-			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-			status = SUCCESS;
-			break;
-		}
-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-		msleep(250);
-	} while (--loop_count);
+	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
+		retval = FAILED;
+		goto out;
+	}
 
-	return status;
-}
+	DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_tm_wait_for_completion - wait for completion of TM task
- *	@hd: Pointer to MPT host structure.
- *	@timeout: timeout value
- *
- *	Returns {SUCCESS,FAILED}.
- */
-static int
-mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
-{
-	unsigned long  flags;
-	int            loop_count = 4 * timeout;
-	int            status = FAILED;
-	MPT_ADAPTER	*ioc = hd->ioc;
+	iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+	termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
 
-	do {
-		spin_lock_irqsave(&ioc->FreeQlock, flags);
-		if(hd->tmPending == 0) {
-			status = SUCCESS;
-			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-			break;
-		}
-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-		msleep(250);
-	} while (--loop_count);
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n"
+	    "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n"
+	    "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus,
+	    pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus),
+	    le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode,
+	    termination_count));
 
-	return status;
+	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
+	    pScsiTmReply->ResponseCode)
+		mptscsih_taskmgmt_response_code(ioc,
+		    pScsiTmReply->ResponseCode);
+
+	if (iocstatus == MPI_IOCSTATUS_SUCCESS) {
+		retval = 0;
+		goto out;
+	}
+
+	retval = FAILED;
+	if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+		if (termination_count == 1)
+			retval = 0;
+		goto out;
+	}
+
+	if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
+	   iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
+		retval = 0;
+
+ out:
+	return retval;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static void
+void
 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
 {
 	char *desc;
@@ -2134,6 +2000,7 @@
 	printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
 		ioc->name, response_code, desc);
 }
+EXPORT_SYMBOL(mptscsih_taskmgmt_response_code);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -2150,97 +2017,28 @@
  *	Returns 1 indicating alloc'd request frame ptr should be freed.
  **/
 int
-mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf,
+	MPT_FRAME_HDR *mr)
 {
-	SCSITaskMgmtReply_t	*pScsiTmReply;
-	SCSITaskMgmt_t		*pScsiTmReq;
-	MPT_SCSI_HOST		*hd;
-	unsigned long		 flags;
-	u16			 iocstatus;
-	u8			 tmType;
-	u32			 termination_count;
-
-	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
-	    ioc->name, mf, mr));
-	if (!ioc->sh) {
-		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
-		    "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
-		return 1;
-	}
-
-	if (mr == NULL) {
-		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
-		    "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
-		return 1;
-	}
-
-	hd = shost_priv(ioc->sh);
-	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
-	pScsiTmReq = (SCSITaskMgmt_t*)mf;
-	tmType = pScsiTmReq->TaskType;
-	iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-	termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
+	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		"TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr));
 
-	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
-	    pScsiTmReply->ResponseCode)
-		mptscsih_taskmgmt_response_code(ioc,
-		    pScsiTmReply->ResponseCode);
-	DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
+	ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
 
-#ifdef CONFIG_FUSION_LOGGING
-	if ((ioc->debug_level & MPT_DEBUG_REPLY) ||
-				(ioc->debug_level & MPT_DEBUG_TM ))
-		printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
-			"iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
-			"term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus,
-			 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
-			le16_to_cpu(pScsiTmReply->IOCStatus),
-			le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
-			le32_to_cpu(pScsiTmReply->TerminationCount));
-#endif
-	if (!iocstatus) {
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name));
-			hd->abortSCpnt = NULL;
+	if (!mr)
 		goto out;
-	}
-
-	/* Error?  (anything non-zero?) */
-
-	/* clear flags and continue.
-	 */
-	switch (tmType) {
-
-	case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
-		if (termination_count == 1)
-			iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
-		hd->abortSCpnt = NULL;
-		break;
-
-	case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
-
-		/* If an internal command is present
-		 * or the TM failed - reload the FW.
-		 * FC FW may respond FAILED to an ABORT
-		 */
-		if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
-		    hd->cmdPtr)
-			if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
-				printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name);
-		break;
-
-	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
-	default:
-		break;
-	}
 
+	ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+	memcpy(ioc->taskmgmt_cmds.reply, mr,
+	    min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
  out:
-	spin_lock_irqsave(&ioc->FreeQlock, flags);
-	hd->tmPending = 0;
-	hd->tmState = TM_STATE_NONE;
-	hd->tm_iocstatus = iocstatus;
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
-	return 1;
+	if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
+		mpt_clear_taskmgmt_in_progress_flag(ioc);
+		ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
+		complete(&ioc->taskmgmt_cmds.done);
+		return 1;
+	}
+	return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2290,8 +2088,10 @@
 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
 	struct inactive_raid_component_info *component_info;
-	int i;
+	int i, j;
+	RaidPhysDiskPage1_t *phys_disk;
 	int rc = 0;
+	int num_paths;
 
 	if (!ioc->raid_data.pIocPg3)
 		goto out;
@@ -2303,6 +2103,45 @@
 		}
 	}
 
+	if (ioc->bus_type != SAS)
+		goto out;
+
+	/*
+	 * Check if dual path
+	 */
+	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+		num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
+		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
+		if (num_paths < 2)
+			continue;
+		phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
+		   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
+		if (!phys_disk)
+			continue;
+		if ((mpt_raid_phys_disk_pg1(ioc,
+		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
+		    phys_disk))) {
+			kfree(phys_disk);
+			continue;
+		}
+		for (j = 0; j < num_paths; j++) {
+			if ((phys_disk->Path[j].Flags &
+			    MPI_RAID_PHYSDISK1_FLAG_INVALID))
+				continue;
+			if ((phys_disk->Path[j].Flags &
+			    MPI_RAID_PHYSDISK1_FLAG_BROKEN))
+				continue;
+			if ((id == phys_disk->Path[j].PhysDiskID) &&
+			    (channel == phys_disk->Path[j].PhysDiskBus)) {
+				rc = 1;
+				kfree(phys_disk);
+				goto out;
+			}
+		}
+		kfree(phys_disk);
+	}
+
+
 	/*
 	 * Check inactive list for matching phys disks
 	 */
@@ -2327,8 +2166,10 @@
 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
 {
 	struct inactive_raid_component_info *component_info;
-	int i;
+	int i, j;
+	RaidPhysDiskPage1_t *phys_disk;
 	int rc = -ENXIO;
+	int num_paths;
 
 	if (!ioc->raid_data.pIocPg3)
 		goto out;
@@ -2340,6 +2181,44 @@
 		}
 	}
 
+	if (ioc->bus_type != SAS)
+		goto out;
+
+	/*
+	 * Check if dual path
+	 */
+	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+		num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
+		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
+		if (num_paths < 2)
+			continue;
+		phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
+		   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
+		if (!phys_disk)
+			continue;
+		if ((mpt_raid_phys_disk_pg1(ioc,
+		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
+		    phys_disk))) {
+			kfree(phys_disk);
+			continue;
+		}
+		for (j = 0; j < num_paths; j++) {
+			if ((phys_disk->Path[j].Flags &
+			    MPI_RAID_PHYSDISK1_FLAG_INVALID))
+				continue;
+			if ((phys_disk->Path[j].Flags &
+			    MPI_RAID_PHYSDISK1_FLAG_BROKEN))
+				continue;
+			if ((id == phys_disk->Path[j].PhysDiskID) &&
+			    (channel == phys_disk->Path[j].PhysDiskBus)) {
+				rc = phys_disk->PhysDiskNum;
+				kfree(phys_disk);
+				goto out;
+			}
+		}
+		kfree(phys_disk);
+	}
+
 	/*
 	 * Check inactive list for matching phys disks
 	 */
@@ -2457,7 +2336,6 @@
 		    sdev->ppr, sdev->inquiry_len));
 
 	vdevice->configured_lun = 1;
-	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 
 	dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		"Queue depth=%d, tflags=%x\n",
@@ -2469,6 +2347,7 @@
 		    ioc->name, vtarget->negoFlags, vtarget->maxOffset,
 		    vtarget->minSyncFactor));
 
+	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
 	dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		"tagged %d, simple %d, ordered %d\n",
 		ioc->name,sdev->tagged_supported, sdev->simple_tags,
@@ -2542,15 +2421,13 @@
 }
 
 /**
- * mptscsih_get_scsi_lookup
+ * mptscsih_get_scsi_lookup - retrieves scmd entry
  * @ioc: Pointer to MPT_ADAPTER structure
  * @i: index into the array
  *
- * retrieves scmd entry from ScsiLookup[] array list
- *
  * Returns the scsi_cmd pointer
- **/
-static struct scsi_cmnd *
+ */
+struct scsi_cmnd *
 mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
 {
 	unsigned long	flags;
@@ -2562,15 +2439,15 @@
 
 	return scmd;
 }
+EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
 
 /**
- * mptscsih_getclear_scsi_lookup
+ * mptscsih_getclear_scsi_lookup -  retrieves and clears scmd entry from ScsiLookup[] array list
  * @ioc: Pointer to MPT_ADAPTER structure
  * @i: index into the array
  *
- * retrieves and clears scmd entry from ScsiLookup[] array list
- *
  * Returns the scsi_cmd pointer
+ *
  **/
 static struct scsi_cmnd *
 mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
@@ -2635,94 +2512,33 @@
 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
 	MPT_SCSI_HOST	*hd;
-	unsigned long	 flags;
-
-	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-	    ": IOC %s_reset routed to SCSI host driver!\n",
-	    ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
-	    reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
 
-	/* If a FW reload request arrives after base installed but
-	 * before all scsi hosts have been attached, then an alt_ioc
-	 * may have a NULL sh pointer.
-	 */
 	if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
 		return 0;
-	else
-		hd = shost_priv(ioc->sh);
-
-	if (reset_phase == MPT_IOC_SETUP_RESET) {
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
-
-		/* Clean Up:
-		 * 1. Set Hard Reset Pending Flag
-		 * All new commands go to doneQ
-		 */
-		hd->resetPending = 1;
-
-	} else if (reset_phase == MPT_IOC_PRE_RESET) {
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name));
-
-		/* 2. Flush running commands
-		 *	Clean ScsiLookup (and associated memory)
-		 *	AND clean mytaskQ
-		 */
 
-		/* 2b. Reply to OS all known outstanding I/O commands.
-		 */
+	hd = shost_priv(ioc->sh);
+	switch (reset_phase) {
+	case MPT_IOC_SETUP_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
+		break;
+	case MPT_IOC_PRE_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
 		mptscsih_flush_running_cmds(hd);
-
-		/* 2c. If there was an internal command that
-		 * has not completed, configuration or io request,
-		 * free these resources.
-		 */
-		if (hd->cmdPtr) {
-			del_timer(&hd->timer);
-			mpt_free_msg_frame(ioc, hd->cmdPtr);
-		}
-
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name));
-
-	} else {
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name));
-
-		/* Once a FW reload begins, all new OS commands are
-		 * redirected to the doneQ w/ a reset status.
-		 * Init all control structures.
-		 */
-
-		/* 2. Chain Buffer initialization
-		 */
-
-		/* 4. Renegotiate to all devices, if SPI
-		 */
-
-		/* 5. Enable new commands to be posted
-		 */
-		spin_lock_irqsave(&ioc->FreeQlock, flags);
-		hd->tmPending = 0;
-		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-		hd->resetPending = 0;
-		hd->tmState = TM_STATE_NONE;
-
-		/* 6. If there was an internal command,
-		 * wake this process up.
-		 */
-		if (hd->cmdPtr) {
-			/*
-			 * Wake up the original calling thread
-			 */
-			hd->pLocal = &hd->localReply;
-			hd->pLocal->completion = MPT_SCANDV_DID_RESET;
-			hd->scandv_wait_done = 1;
-			wake_up(&hd->scandv_waitq);
-			hd->cmdPtr = NULL;
+		break;
+	case MPT_IOC_POST_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
+		if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->internal_cmds.status |=
+				MPT_MGMT_STATUS_DID_IOCRESET;
+			complete(&ioc->internal_cmds.done);
 		}
-
-		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name));
-
+		break;
+	default:
+		break;
 	}
-
 	return 1;		/* currently means nothing really */
 }
 
@@ -2730,55 +2546,16 @@
 int
 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
-	MPT_SCSI_HOST *hd;
 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
 
-	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
-			ioc->name, event));
-
-	if (ioc->sh == NULL ||
-		((hd = shost_priv(ioc->sh)) == NULL))
-		return 1;
-
-	switch (event) {
-	case MPI_EVENT_UNIT_ATTENTION:			/* 03 */
-		/* FIXME! */
-		break;
-	case MPI_EVENT_IOC_BUS_RESET:			/* 04 */
-	case MPI_EVENT_EXT_BUS_RESET:			/* 05 */
-		if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
-			hd->soft_resets++;
-		break;
-	case MPI_EVENT_LOGOUT:				/* 09 */
-		/* FIXME! */
-		break;
-
-	case MPI_EVENT_RESCAN:				/* 06 */
-		break;
-
-		/*
-		 *  CHECKME! Don't think we need to do
-		 *  anything for these, but...
-		 */
-	case MPI_EVENT_LINK_STATUS_CHANGE:		/* 07 */
-	case MPI_EVENT_LOOP_STATE_CHANGE:		/* 08 */
-		/*
-		 *  CHECKME!  Falling thru...
-		 */
-		break;
-
-	case MPI_EVENT_INTEGRATED_RAID:			/* 0B */
-		break;
+	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		"MPT event (=%02Xh) routed to SCSI host driver!\n",
+		ioc->name, event));
 
-	case MPI_EVENT_NONE:				/* 00 */
-	case MPI_EVENT_LOG_DATA:			/* 01 */
-	case MPI_EVENT_STATE_CHANGE:			/* 02 */
-	case MPI_EVENT_EVENT_CHANGE:			/* 0A */
-	default:
-		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n",
-		    ioc->name, event));
-		break;
-	}
+	if ((event == MPI_EVENT_IOC_BUS_RESET ||
+	    event == MPI_EVENT_EXT_BUS_RESET) &&
+	    (ioc->bus_type == SPI) && (ioc->soft_resets < -1))
+			ioc->soft_resets++;
 
 	return 1;		/* currently means nothing really */
 }
@@ -2809,153 +2586,44 @@
  *	Used ONLY for DV and other internal commands.
  */
 int
-mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
+mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
+				MPT_FRAME_HDR *reply)
 {
-	MPT_SCSI_HOST	*hd;
 	SCSIIORequest_t *pReq;
-	int		 completionCode;
+	SCSIIOReply_t	*pReply;
+	u8		 cmd;
 	u16		 req_idx;
+	u8	*sense_data;
+	int		 sz;
 
-	hd = shost_priv(ioc->sh);
-
-	if ((mf == NULL) ||
-	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
-		printk(MYIOC_s_ERR_FMT
-			"ScanDvComplete, %s req frame ptr! (=%p)\n",
-				ioc->name, mf?"BAD":"NULL", (void *) mf);
-		goto wakeup;
-	}
-
-	del_timer(&hd->timer);
-	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-	mptscsih_set_scsi_lookup(ioc, req_idx, NULL);
-	pReq = (SCSIIORequest_t *) mf;
+	ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
+	ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD;
+	if (!reply)
+		goto out;
 
-	if (mf != hd->cmdPtr) {
-		printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
-				ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
+	pReply = (SCSIIOReply_t *) reply;
+	pReq = (SCSIIORequest_t *) req;
+	ioc->internal_cmds.completion_code =
+	    mptscsih_get_completion_code(ioc, req, reply);
+	ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+	memcpy(ioc->internal_cmds.reply, reply,
+	    min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength));
+	cmd = reply->u.hdr.Function;
+	if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+	    (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) &&
+	    (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
+		req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
+		sense_data = ((u8 *)ioc->sense_buf_pool +
+		    (req_idx * MPT_SENSE_BUFFER_ALLOC));
+		sz = min_t(int, pReq->SenseBufferLength,
+		    MPT_SENSE_BUFFER_ALLOC);
+		memcpy(ioc->internal_cmds.sense, sense_data, sz);
 	}
-	hd->cmdPtr = NULL;
-
-	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
-			ioc->name, mf, mr, req_idx));
-
-	hd->pLocal = &hd->localReply;
-	hd->pLocal->scsiStatus = 0;
-
-	/* If target struct exists, clear sense valid flag.
-	 */
-	if (mr == NULL) {
-		completionCode = MPT_SCANDV_GOOD;
-	} else {
-		SCSIIOReply_t	*pReply;
-		u16		 status;
-		u8		 scsi_status;
-
-		pReply = (SCSIIOReply_t *) mr;
-
-		status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-		scsi_status = pReply->SCSIStatus;
-
-
-		switch(status) {
-
-		case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */
-			completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
-			break;
-
-		case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
-		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
-		case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */
-		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
-			completionCode = MPT_SCANDV_DID_RESET;
-			break;
-
-		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
-		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
-		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
-			if (pReply->Function == MPI_FUNCTION_CONFIG) {
-				ConfigReply_t *pr = (ConfigReply_t *)mr;
-				completionCode = MPT_SCANDV_GOOD;
-				hd->pLocal->header.PageVersion = pr->Header.PageVersion;
-				hd->pLocal->header.PageLength = pr->Header.PageLength;
-				hd->pLocal->header.PageNumber = pr->Header.PageNumber;
-				hd->pLocal->header.PageType = pr->Header.PageType;
-
-			} else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
-				/* If the RAID Volume request is successful,
-				 * return GOOD, else indicate that
-				 * some type of error occurred.
-				 */
-				MpiRaidActionReply_t	*pr = (MpiRaidActionReply_t *)mr;
-				if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
-					completionCode = MPT_SCANDV_GOOD;
-				else
-					completionCode = MPT_SCANDV_SOME_ERROR;
-				memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
-
-			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
-				u8		*sense_data;
-				int		 sz;
-
-				/* save sense data in global structure
-				 */
-				completionCode = MPT_SCANDV_SENSE;
-				hd->pLocal->scsiStatus = scsi_status;
-				sense_data = ((u8 *)ioc->sense_buf_pool +
-					(req_idx * MPT_SENSE_BUFFER_ALLOC));
-
-				sz = min_t(int, pReq->SenseBufferLength,
-							SCSI_STD_SENSE_BYTES);
-				memcpy(hd->pLocal->sense, sense_data, sz);
-
-				ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "  Check Condition, sense ptr %p\n",
-				    ioc->name, sense_data));
-			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
-				if (pReq->CDB[0] == INQUIRY)
-					completionCode = MPT_SCANDV_ISSUE_SENSE;
-				else
-					completionCode = MPT_SCANDV_DID_RESET;
-			}
-			else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
-				completionCode = MPT_SCANDV_DID_RESET;
-			else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
-				completionCode = MPT_SCANDV_DID_RESET;
-			else {
-				completionCode = MPT_SCANDV_GOOD;
-				hd->pLocal->scsiStatus = scsi_status;
-			}
-			break;
-
-		case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:		/* 0x0047 */
-			if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
-				completionCode = MPT_SCANDV_DID_RESET;
-			else
-				completionCode = MPT_SCANDV_SOME_ERROR;
-			break;
-
-		default:
-			completionCode = MPT_SCANDV_SOME_ERROR;
-			break;
-
-		}	/* switch(status) */
-
-	} /* end of address reply case */
-
-	hd->pLocal->completion = completionCode;
-
-	/* MF and RF are freed in mpt_interrupt
-	 */
-wakeup:
-	/* Free Chain buffers (will never chain) in scan or dv */
-	//mptscsih_freeChainBuffers(ioc, req_idx);
-
-	/*
-	 * Wake up the original calling thread
-	 */
-	hd->scandv_wait_done = 1;
-	wake_up(&hd->scandv_waitq);
-
+ out:
+	if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING))
+		return 0;
+	ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
+	complete(&ioc->internal_cmds.done);
 	return 1;
 }
 
@@ -3004,6 +2672,95 @@
 	return;
 }
 
+/**
+ *	mptscsih_get_completion_code -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@req: Pointer to original MPT request frame
+ *	@reply: Pointer to MPT reply frame (NULL if TurboReply)
+ *
+ **/
+static int
+mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
+				MPT_FRAME_HDR *reply)
+{
+	SCSIIOReply_t	*pReply;
+	MpiRaidActionReply_t *pr;
+	u8		 scsi_status;
+	u16		 status;
+	int		 completion_code;
+
+	pReply = (SCSIIOReply_t *)reply;
+	status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+	scsi_status = pReply->SCSIStatus;
+
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh,"
+	    "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState,
+	    scsi_status, le32_to_cpu(pReply->IOCLogInfo)));
+
+	switch (status) {
+
+	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */
+		completion_code = MPT_SCANDV_SELECTION_TIMEOUT;
+		break;
+
+	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
+	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
+	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */
+	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
+		completion_code = MPT_SCANDV_DID_RESET;
+		break;
+
+	case MPI_IOCSTATUS_BUSY:
+	case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
+		completion_code = MPT_SCANDV_BUSY;
+		break;
+
+	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
+	case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
+	case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
+		if (pReply->Function == MPI_FUNCTION_CONFIG) {
+			completion_code = MPT_SCANDV_GOOD;
+		} else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
+			pr = (MpiRaidActionReply_t *)reply;
+			if (le16_to_cpu(pr->ActionStatus) ==
+				MPI_RAID_ACTION_ASTATUS_SUCCESS)
+				completion_code = MPT_SCANDV_GOOD;
+			else
+				completion_code = MPT_SCANDV_SOME_ERROR;
+		} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)
+			completion_code = MPT_SCANDV_SENSE;
+		else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
+			if (req->u.scsireq.CDB[0] == INQUIRY)
+				completion_code = MPT_SCANDV_ISSUE_SENSE;
+			else
+				completion_code = MPT_SCANDV_DID_RESET;
+		} else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
+			completion_code = MPT_SCANDV_DID_RESET;
+		else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
+			completion_code = MPT_SCANDV_DID_RESET;
+		else if (scsi_status == MPI_SCSI_STATUS_BUSY)
+			completion_code = MPT_SCANDV_BUSY;
+		else
+			completion_code = MPT_SCANDV_GOOD;
+		break;
+
+	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:		/* 0x0047 */
+		if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
+			completion_code = MPT_SCANDV_DID_RESET;
+		else
+			completion_code = MPT_SCANDV_SOME_ERROR;
+		break;
+	default:
+		completion_code = MPT_SCANDV_SOME_ERROR;
+		break;
+
+	}	/* switch(status) */
+
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "  completionCode set to %08xh\n", ioc->name, completion_code));
+	return completion_code;
+}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -3030,22 +2787,27 @@
 {
 	MPT_FRAME_HDR	*mf;
 	SCSIIORequest_t	*pScsiReq;
-	SCSIIORequest_t	 ReqCopy;
 	int		 my_idx, ii, dir;
-	int		 rc, cmdTimeout;
-	int		in_isr;
+	int		 timeout;
 	char		 cmdLen;
 	char		 CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-	char		 cmd = io->cmd;
-	MPT_ADAPTER 	*ioc = hd->ioc;
+	u8		 cmd = io->cmd;
+	MPT_ADAPTER *ioc = hd->ioc;
+	int		 ret = 0;
+	unsigned long	 timeleft;
+	unsigned long	 flags;
 
-	in_isr = in_interrupt();
-	if (in_isr) {
-		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
-					ioc->name));
-		return -EPERM;
+	/* don't send internal command during diag reset */
+	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+	if (ioc->ioc_reset_in_progress) {
+		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+		dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			"%s: busy with host reset\n", ioc->name, __func__));
+		return MPT_SCANDV_BUSY;
 	}
+	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 
+	mutex_lock(&ioc->internal_cmds.mutex);
 
 	/* Set command specific information
 	 */
@@ -3055,13 +2817,13 @@
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
 		CDB[4] = io->size;
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	case TEST_UNIT_READY:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	case START_STOP:
@@ -3069,7 +2831,7 @@
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
 		CDB[4] = 1;	/*Spin up the disk */
-		cmdTimeout = 15;
+		timeout = 15;
 		break;
 
 	case REQUEST_SENSE:
@@ -3077,7 +2839,7 @@
 		CDB[0] = cmd;
 		CDB[4] = io->size;
 		dir = MPI_SCSIIO_CONTROL_READ;
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	case READ_BUFFER:
@@ -3096,7 +2858,7 @@
 		CDB[6] = (io->size >> 16) & 0xFF;
 		CDB[7] = (io->size >>  8) & 0xFF;
 		CDB[8] = io->size & 0xFF;
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	case WRITE_BUFFER:
@@ -3111,21 +2873,21 @@
 		CDB[6] = (io->size >> 16) & 0xFF;
 		CDB[7] = (io->size >>  8) & 0xFF;
 		CDB[8] = io->size & 0xFF;
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	case RESERVE:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	case RELEASE:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	case SYNCHRONIZE_CACHE:
@@ -3133,20 +2895,23 @@
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
 //		CDB[1] = 0x02;	/* set immediate bit */
-		cmdTimeout = 10;
+		timeout = 10;
 		break;
 
 	default:
 		/* Error Case */
-		return -EFAULT;
+		ret = -EFAULT;
+		goto out;
 	}
 
 	/* Get and Populate a free Frame
+	 * MsgContext set in mpt_get_msg_frame call
 	 */
 	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
-		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n",
-		    ioc->name));
-		return -EBUSY;
+		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n",
+		    ioc->name, __func__));
+		ret = MPT_SCANDV_BUSY;
+		goto out;
 	}
 
 	pScsiReq = (SCSIIORequest_t *) mf;
@@ -3172,7 +2937,7 @@
 
 	pScsiReq->Reserved = 0;
 
-	pScsiReq->MsgFlags = mpt_msg_flags();
+	pScsiReq->MsgFlags = mpt_msg_flags(ioc);
 	/* MsgContext set in mpt_get_msg_fram call  */
 
 	int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
@@ -3184,74 +2949,58 @@
 
 	if (cmd == REQUEST_SENSE) {
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
-		ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
-			ioc->name, cmd));
+		devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd));
 	}
 
-	for (ii=0; ii < 16; ii++)
+	for (ii = 0; ii < 16; ii++)
 		pScsiReq->CDB[ii] = CDB[ii];
 
 	pScsiReq->DataLength = cpu_to_le32(io->size);
 	pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
 
-	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
-			ioc->name, cmd, io->channel, io->id, io->lun));
-
-	if (dir == MPI_SCSIIO_CONTROL_READ) {
-		mpt_add_sge((char *) &pScsiReq->SGL,
-			MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
-			io->data_dma);
-	} else {
-		mpt_add_sge((char *) &pScsiReq->SGL,
-			MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
-			io->data_dma);
-	}
-
-	/* The ISR will free the request frame, but we need
-	 * the information to initialize the target. Duplicate.
-	 */
-	memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
-
-	/* Issue this command after:
-	 *	finish init
-	 *	add timer
-	 * Wait until the reply has been received
-	 *  ScsiScanDvCtx callback function will
-	 *	set hd->pLocal;
-	 *	set scandv_wait_done and call wake_up
-	 */
-	hd->pLocal = NULL;
-	hd->timer.expires = jiffies + HZ*cmdTimeout;
-	hd->scandv_wait_done = 0;
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+	    "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n",
+	    ioc->name, __func__, cmd, io->channel, io->id, io->lun));
 
-	/* Save cmd pointer, for resource free if timeout or
-	 * FW reload occurs
-	 */
-	hd->cmdPtr = mf;
+	if (dir == MPI_SCSIIO_CONTROL_READ)
+		ioc->add_sge((char *) &pScsiReq->SGL,
+		    MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma);
+	else
+		ioc->add_sge((char *) &pScsiReq->SGL,
+		    MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma);
 
-	add_timer(&hd->timer);
+	INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
 	mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
-	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
-
-	if (hd->pLocal) {
-		rc = hd->pLocal->completion;
-		hd->pLocal->skip = 0;
-
-		/* Always set fatal error codes in some cases.
-		 */
-		if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
-			rc = -ENXIO;
-		else if (rc == MPT_SCANDV_SOME_ERROR)
-			rc =  -rc;
-	} else {
-		rc = -EFAULT;
-		/* This should never happen. */
-		ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
-				ioc->name));
+	timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done,
+	    timeout*HZ);
+	if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		ret = MPT_SCANDV_DID_RESET;
+		dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__,
+		    cmd));
+		if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
+			mpt_free_msg_frame(ioc, mf);
+			goto out;
+		}
+		if (!timeleft) {
+			printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
+			    ioc->name, __func__);
+			mpt_HardResetHandler(ioc, CAN_SLEEP);
+			mpt_free_msg_frame(ioc, mf);
+		}
+		goto out;
 	}
 
-	return rc;
+	ret = ioc->internal_cmds.completion_code;
+	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n",
+			ioc->name, __func__, ret));
+
+ out:
+	CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
+	mutex_unlock(&ioc->internal_cmds.mutex);
+	return ret;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -3491,6 +3240,7 @@
 	&dev_attr_debug_level,
 	NULL,
 };
+
 EXPORT_SYMBOL(mptscsih_host_attrs);
 
 EXPORT_SYMBOL(mptscsih_remove);
@@ -3516,6 +3266,5 @@
 EXPORT_SYMBOL(mptscsih_ioc_reset);
 EXPORT_SYMBOL(mptscsih_change_queue_depth);
 EXPORT_SYMBOL(mptscsih_timer_expired);
-EXPORT_SYMBOL(mptscsih_TMHandler);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptscsih.h linux-libre-2.6.31-gnu/drivers/message/fusion/mptscsih.h
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptscsih.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptscsih.h	2009-09-09 18:13:59.000000000 -0400
@@ -60,6 +60,7 @@
 #define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
 #define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
 #define MPT_SCANDV_FALLBACK		(0x00000020)
+#define MPT_SCANDV_BUSY			(0x00000040)
 
 #define MPT_SCANDV_MAX_RETRIES		(10)
 
@@ -89,6 +90,7 @@
 
 #endif
 
+
 typedef struct _internal_cmd {
 	char		*data;		/* data pointer */
 	dma_addr_t	data_dma;	/* data dma address */
@@ -112,6 +114,8 @@
 extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
 extern const char * mptscsih_info(struct Scsi_Host *SChost);
 extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
+extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,
+	u8 id, int lun, int ctx2abort, ulong timeout);
 extern void mptscsih_slave_destroy(struct scsi_device *device);
 extern int mptscsih_slave_configure(struct scsi_device *device);
 extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
@@ -126,7 +130,8 @@
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern void mptscsih_timer_expired(unsigned long data);
-extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
 extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern struct device_attribute *mptscsih_host_attrs[];
+extern struct scsi_cmnd	*mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
+extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
diff -druN linux-libre-2.6.30-gnu/drivers/message/fusion/mptspi.c linux-libre-2.6.31-gnu/drivers/message/fusion/mptspi.c
--- linux-libre-2.6.30-gnu/drivers/message/fusion/mptspi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/fusion/mptspi.c	2009-09-09 18:13:59.000000000 -0400
@@ -300,7 +300,7 @@
 	flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
 		(IOCPage4Ptr->Header.PageLength + ii) * 4;
 
-	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+	ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
 
 	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
 		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
@@ -614,19 +614,24 @@
 	spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
 }
 
-static int
+int
 mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
 {
+	MPT_ADAPTER	*ioc = hd->ioc;
 	MpiRaidActionRequest_t	*pReq;
 	MPT_FRAME_HDR		*mf;
-	MPT_ADAPTER *ioc = hd->ioc;
+	int			ret;
+	unsigned long 	 	timeleft;
+
+	mutex_lock(&ioc->internal_cmds.mutex);
 
 	/* Get and Populate a free Frame
 	 */
 	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
-		ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
-					ioc->name));
-		return -EAGAIN;
+		dfailprintk(hd->ioc, printk(MYIOC_s_WARN_FMT
+			"%s: no msg frames!\n", ioc->name, __func__));
+		ret = -EAGAIN;
+		goto out;
 	}
 	pReq = (MpiRaidActionRequest_t *)mf;
 	if (quiesce)
@@ -643,29 +648,36 @@
 	pReq->Reserved2 = 0;
 	pReq->ActionDataWord = 0; /* Reserved for this action */
 
-	mpt_add_sge((char *)&pReq->ActionDataSGE,
+	ioc->add_sge((char *)&pReq->ActionDataSGE,
 		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
 
 	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
 			ioc->name, pReq->Action, channel, id));
 
-	hd->pLocal = NULL;
-	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
-	hd->scandv_wait_done = 0;
-
-	/* Save cmd pointer, for resource free if timeout or
-	 * FW reload occurs
-	 */
-	hd->cmdPtr = mf;
-
-	add_timer(&hd->timer);
+	INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
 	mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
-	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
+	timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 10*HZ);
+	if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		ret = -ETIME;
+		dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: TIMED OUT!\n",
+		    ioc->name, __func__));
+		if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			goto out;
+		if (!timeleft) {
+			printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
+			    ioc->name, __func__);
+			mpt_HardResetHandler(ioc, CAN_SLEEP);
+			mpt_free_msg_frame(ioc, mf);
+		}
+		goto out;
+	}
 
-	if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))
-		return -1;
+	ret = ioc->internal_cmds.completion_code;
 
-	return 0;
+ out:
+	CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
+	mutex_unlock(&ioc->internal_cmds.mutex);
+	return ret;
 }
 
 static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
@@ -1423,17 +1435,15 @@
 	 * A slightly different algorithm is required for
 	 * 64bit SGEs.
 	 */
-	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
+	scale = ioc->req_sz/ioc->SGE_size;
+	if (ioc->sg_addr_size == sizeof(u64)) {
 		numSGE = (scale - 1) *
 		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
+		  (ioc->req_sz - 60) / ioc->SGE_size;
 	} else {
 		numSGE = 1 + (scale - 1) *
 		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
+		  (ioc->req_sz - 64) / ioc->SGE_size;
 	}
 
 	if (numSGE < sh->sg_tablesize) {
@@ -1464,9 +1474,6 @@
 
 	/* Clear the TM flags
 	 */
-	hd->tmPending = 0;
-	hd->tmState = TM_STATE_NONE;
-	hd->resetPending = 0;
 	hd->abortSCpnt = NULL;
 
 	/* Clear the pointer used to store
@@ -1493,8 +1500,6 @@
 		mpt_saf_te));
 	ioc->spi_data.noQas = 0;
 
-	init_waitqueue_head(&hd->scandv_waitq);
-	hd->scandv_wait_done = 0;
 	hd->last_queue_full = 0;
 	hd->spi_pending = 0;
 
@@ -1514,7 +1519,7 @@
 	 * issue internal bus reset
 	 */
 	if (ioc->spi_data.bus_reset)
-		mptscsih_TMHandler(hd,
+		mptscsih_IssueTaskMgmt(hd,
 		    MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
 		    0, 0, 0, 0, 5);
 
diff -druN linux-libre-2.6.30-gnu/drivers/message/i2o/i2o_block.c linux-libre-2.6.31-gnu/drivers/message/i2o/i2o_block.c
--- linux-libre-2.6.30-gnu/drivers/message/i2o/i2o_block.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/message/i2o/i2o_block.c	2009-09-09 18:13:59.000000000 -0400
@@ -426,15 +426,9 @@
 	struct request_queue *q = req->q;
 	unsigned long flags;
 
-	if (blk_end_request(req, error, nr_bytes)) {
-		int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT);
-
-		if (blk_pc_request(req))
-			leftover = req->data_len;
-
+	if (blk_end_request(req, error, nr_bytes))
 		if (error)
-			blk_end_request(req, -EIO, leftover);
-	}
+			blk_end_request_all(req, -EIO);
 
 	spin_lock_irqsave(q->queue_lock, flags);
 
@@ -761,7 +755,7 @@
 			break;
 
 		case CACHE_SMARTFETCH:
-			if (req->nr_sectors > 16)
+			if (blk_rq_sectors(req) > 16)
 				ctl_flags = 0x201F0008;
 			else
 				ctl_flags = 0x001F0000;
@@ -781,13 +775,13 @@
 			ctl_flags = 0x001F0010;
 			break;
 		case CACHE_SMARTBACK:
-			if (req->nr_sectors > 16)
+			if (blk_rq_sectors(req) > 16)
 				ctl_flags = 0x001F0004;
 			else
 				ctl_flags = 0x001F0010;
 			break;
 		case CACHE_SMARTTHROUGH:
-			if (req->nr_sectors > 16)
+			if (blk_rq_sectors(req) > 16)
 				ctl_flags = 0x001F0004;
 			else
 				ctl_flags = 0x001F0010;
@@ -800,8 +794,9 @@
 	if (c->adaptec) {
 		u8 cmd[10];
 		u32 scsi_flags;
-		u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT;
+		u16 hwsec;
 
+		hwsec = queue_logical_block_size(req->q) >> KERNEL_SECTOR_SHIFT;
 		memset(cmd, 0, 10);
 
 		sgl_offset = SGL_OFFSET_12;
@@ -827,22 +822,22 @@
 
 		*mptr++ = cpu_to_le32(scsi_flags);
 
-		*((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
-		*((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
+		*((u32 *) & cmd[2]) = cpu_to_be32(blk_rq_pos(req) * hwsec);
+		*((u16 *) & cmd[7]) = cpu_to_be16(blk_rq_sectors(req) * hwsec);
 
 		memcpy(mptr, cmd, 10);
 		mptr += 4;
-		*mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
+		*mptr++ = cpu_to_le32(blk_rq_bytes(req));
 	} else
 #endif
 	{
 		msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
 		*mptr++ = cpu_to_le32(ctl_flags);
-		*mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
+		*mptr++ = cpu_to_le32(blk_rq_bytes(req));
 		*mptr++ =
-		    cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT));
+		    cpu_to_le32((u32) (blk_rq_pos(req) << KERNEL_SECTOR_SHIFT));
 		*mptr++ =
-		    cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT));
+		    cpu_to_le32(blk_rq_pos(req) >> (32 - KERNEL_SECTOR_SHIFT));
 	}
 
 	if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
@@ -883,7 +878,7 @@
 	struct request *req;
 
 	while (!blk_queue_plugged(q)) {
-		req = elv_next_request(q);
+		req = blk_peek_request(q);
 		if (!req)
 			break;
 
@@ -896,7 +891,7 @@
 
 			if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) {
 				if (!i2o_block_transfer(req)) {
-					blkdev_dequeue_request(req);
+					blk_start_request(req);
 					continue;
 				} else
 					osm_info("transfer error\n");
@@ -922,8 +917,10 @@
 				blk_stop_queue(q);
 				break;
 			}
-		} else
-			end_request(req, 0);
+		} else {
+			blk_start_request(req);
+			__blk_end_request_all(req, -EIO);
+		}
 	}
 };
 
@@ -1082,7 +1079,7 @@
 	 */
 	if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
 	    !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
-		blk_queue_hardsect_size(queue, le32_to_cpu(blocksize));
+		blk_queue_logical_block_size(queue, le32_to_cpu(blocksize));
 	} else
 		osm_warn("unable to get blocksize of %s\n", gd->disk_name);
 
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/ab3100-core.c linux-libre-2.6.31-gnu/drivers/mfd/ab3100-core.c
--- linux-libre-2.6.30-gnu/drivers/mfd/ab3100-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mfd/ab3100-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,991 @@
+/*
+ * Copyright (C) 2007-2009 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Low-level core for exclusive access to the AB3100 IC on the I2C bus
+ * and some basic chip-configuration.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/mfd/ab3100.h>
+
+/* These are the only registers inside AB3100 used in this main file */
+
+/* Interrupt event registers */
+#define AB3100_EVENTA1		0x21
+#define AB3100_EVENTA2		0x22
+#define AB3100_EVENTA3		0x23
+
+/* AB3100 DAC converter registers */
+#define AB3100_DIS		0x00
+#define AB3100_D0C		0x01
+#define AB3100_D1C		0x02
+#define AB3100_D2C		0x03
+#define AB3100_D3C		0x04
+
+/* Chip ID register */
+#define AB3100_CID		0x20
+
+/* AB3100 interrupt registers */
+#define AB3100_IMRA1		0x24
+#define AB3100_IMRA2		0x25
+#define AB3100_IMRA3		0x26
+#define AB3100_IMRB1		0x2B
+#define AB3100_IMRB2		0x2C
+#define AB3100_IMRB3		0x2D
+
+/* System Power Monitoring and control registers */
+#define AB3100_MCA		0x2E
+#define AB3100_MCB		0x2F
+
+/* SIM power up */
+#define AB3100_SUP		0x50
+
+/*
+ * I2C communication
+ *
+ * The AB3100 is usually assigned address 0x48 (7-bit)
+ * The chip is defined in the platform i2c_board_data section.
+ */
+static unsigned short normal_i2c[] = { 0x48, I2C_CLIENT_END };
+I2C_CLIENT_INSMOD_1(ab3100);
+
+u8 ab3100_get_chip_type(struct ab3100 *ab3100)
+{
+	u8 chip = ABUNKNOWN;
+
+	switch (ab3100->chip_id & 0xf0) {
+	case  0xa0:
+		chip = AB3000;
+		break;
+	case  0xc0:
+		chip = AB3100;
+		break;
+	}
+	return chip;
+}
+EXPORT_SYMBOL(ab3100_get_chip_type);
+
+int ab3100_set_register(struct ab3100 *ab3100, u8 reg, u8 regval)
+{
+	u8 regandval[2] = {reg, regval};
+	int err;
+
+	err = mutex_lock_interruptible(&ab3100->access_mutex);
+	if (err)
+		return err;
+
+	/*
+	 * A two-byte write message with the first byte containing the register
+	 * number and the second byte containing the value to be written
+	 * effectively sets a register in the AB3100.
+	 */
+	err = i2c_master_send(ab3100->i2c_client, regandval, 2);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (write register): %d\n",
+			err);
+	} else if (err != 2) {
+		dev_err(ab3100->dev,
+			"write error (write register) "
+			"%d bytes transferred (expected 2)\n",
+			err);
+		err = -EIO;
+	} else {
+		/* All is well */
+		err = 0;
+	}
+	mutex_unlock(&ab3100->access_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(ab3100_set_register);
+
+/*
+ * The test registers exist at an I2C bus address up one
+ * from the ordinary base. They are not supposed to be used
+ * in production code, but sometimes you have to do that
+ * anyway. It's currently only used from this file so declare
+ * it static and do not export.
+ */
+static int ab3100_set_test_register(struct ab3100 *ab3100,
+				    u8 reg, u8 regval)
+{
+	u8 regandval[2] = {reg, regval};
+	int err;
+
+	err = mutex_lock_interruptible(&ab3100->access_mutex);
+	if (err)
+		return err;
+
+	err = i2c_master_send(ab3100->testreg_client, regandval, 2);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (write test register): %d\n",
+			err);
+	} else if (err != 2) {
+		dev_err(ab3100->dev,
+			"write error (write test register) "
+			"%d bytes transferred (expected 2)\n",
+			err);
+		err = -EIO;
+	} else {
+		/* All is well */
+		err = 0;
+	}
+	mutex_unlock(&ab3100->access_mutex);
+
+	return err;
+}
+
+int ab3100_get_register(struct ab3100 *ab3100, u8 reg, u8 *regval)
+{
+	int err;
+
+	err = mutex_lock_interruptible(&ab3100->access_mutex);
+	if (err)
+		return err;
+
+	/*
+	 * AB3100 require an I2C "stop" command between each message, else
+	 * it will not work. The only way of achieveing this with the
+	 * message transport layer is to send the read and write messages
+	 * separately.
+	 */
+	err = i2c_master_send(ab3100->i2c_client, &reg, 1);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (send register address): %d\n",
+			err);
+		goto get_reg_out_unlock;
+	} else if (err != 1) {
+		dev_err(ab3100->dev,
+			"write error (send register address) "
+			"%d bytes transferred (expected 1)\n",
+			err);
+		err = -EIO;
+		goto get_reg_out_unlock;
+	} else {
+		/* All is well */
+		err = 0;
+	}
+
+	err = i2c_master_recv(ab3100->i2c_client, regval, 1);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (read register): %d\n",
+			err);
+		goto get_reg_out_unlock;
+	} else if (err != 1) {
+		dev_err(ab3100->dev,
+			"write error (read register) "
+			"%d bytes transferred (expected 1)\n",
+			err);
+		err = -EIO;
+		goto get_reg_out_unlock;
+	} else {
+		/* All is well */
+		err = 0;
+	}
+
+ get_reg_out_unlock:
+	mutex_unlock(&ab3100->access_mutex);
+	return err;
+}
+EXPORT_SYMBOL(ab3100_get_register);
+
+int ab3100_get_register_page(struct ab3100 *ab3100,
+			     u8 first_reg, u8 *regvals, u8 numregs)
+{
+	int err;
+
+	if (ab3100->chip_id == 0xa0 ||
+	    ab3100->chip_id == 0xa1)
+		/* These don't support paged reads */
+		return -EIO;
+
+	err = mutex_lock_interruptible(&ab3100->access_mutex);
+	if (err)
+		return err;
+
+	/*
+	 * Paged read also require an I2C "stop" command.
+	 */
+	err = i2c_master_send(ab3100->i2c_client, &first_reg, 1);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (send first register address): %d\n",
+			err);
+		goto get_reg_page_out_unlock;
+	} else if (err != 1) {
+		dev_err(ab3100->dev,
+			"write error (send first register address) "
+			"%d bytes transferred (expected 1)\n",
+			err);
+		err = -EIO;
+		goto get_reg_page_out_unlock;
+	}
+
+	err = i2c_master_recv(ab3100->i2c_client, regvals, numregs);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (read register page): %d\n",
+			err);
+		goto get_reg_page_out_unlock;
+	} else if (err != numregs) {
+		dev_err(ab3100->dev,
+			"write error (read register page) "
+			"%d bytes transferred (expected %d)\n",
+			err, numregs);
+		err = -EIO;
+		goto get_reg_page_out_unlock;
+	}
+
+	/* All is well */
+	err = 0;
+
+ get_reg_page_out_unlock:
+	mutex_unlock(&ab3100->access_mutex);
+	return err;
+}
+EXPORT_SYMBOL(ab3100_get_register_page);
+
+int ab3100_mask_and_set_register(struct ab3100 *ab3100,
+				 u8 reg, u8 andmask, u8 ormask)
+{
+	u8 regandval[2] = {reg, 0};
+	int err;
+
+	err = mutex_lock_interruptible(&ab3100->access_mutex);
+	if (err)
+		return err;
+
+	/* First read out the target register */
+	err = i2c_master_send(ab3100->i2c_client, &reg, 1);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (maskset send address): %d\n",
+			err);
+		goto get_maskset_unlock;
+	} else if (err != 1) {
+		dev_err(ab3100->dev,
+			"write error (maskset send address) "
+			"%d bytes transferred (expected 1)\n",
+			err);
+		err = -EIO;
+		goto get_maskset_unlock;
+	}
+
+	err = i2c_master_recv(ab3100->i2c_client, &regandval[1], 1);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (maskset read register): %d\n",
+			err);
+		goto get_maskset_unlock;
+	} else if (err != 1) {
+		dev_err(ab3100->dev,
+			"write error (maskset read register) "
+			"%d bytes transferred (expected 1)\n",
+			err);
+		err = -EIO;
+		goto get_maskset_unlock;
+	}
+
+	/* Modify the register */
+	regandval[1] &= andmask;
+	regandval[1] |= ormask;
+
+	/* Write the register */
+	err = i2c_master_send(ab3100->i2c_client, regandval, 2);
+	if (err < 0) {
+		dev_err(ab3100->dev,
+			"write error (write register): %d\n",
+			err);
+		goto get_maskset_unlock;
+	} else if (err != 2) {
+		dev_err(ab3100->dev,
+			"write error (write register) "
+			"%d bytes transferred (expected 2)\n",
+			err);
+		err = -EIO;
+		goto get_maskset_unlock;
+	}
+
+	/* All is well */
+	err = 0;
+
+ get_maskset_unlock:
+	mutex_unlock(&ab3100->access_mutex);
+	return err;
+}
+EXPORT_SYMBOL(ab3100_mask_and_set_register);
+
+/*
+ * Register a simple callback for handling any AB3100 events.
+ */
+int ab3100_event_register(struct ab3100 *ab3100,
+			  struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&ab3100->event_subscribers,
+					       nb);
+}
+EXPORT_SYMBOL(ab3100_event_register);
+
+/*
+ * Remove a previously registered callback.
+ */
+int ab3100_event_unregister(struct ab3100 *ab3100,
+			    struct notifier_block *nb)
+{
+  return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
+					    nb);
+}
+EXPORT_SYMBOL(ab3100_event_unregister);
+
+
+int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100,
+					     u32 *fatevent)
+{
+	if (!ab3100->startup_events_read)
+		return -EAGAIN; /* Try again later */
+	*fatevent = ab3100->startup_events;
+	return 0;
+}
+EXPORT_SYMBOL(ab3100_event_registers_startup_state_get);
+
+/* Interrupt handling worker */
+static void ab3100_work(struct work_struct *work)
+{
+	struct ab3100 *ab3100 = container_of(work, struct ab3100, work);
+	u8 event_regs[3];
+	u32 fatevent;
+	int err;
+
+	err = ab3100_get_register_page(ab3100, AB3100_EVENTA1,
+				       event_regs, 3);
+	if (err)
+		goto err_event_wq;
+
+	fatevent = (event_regs[0] << 16) |
+		(event_regs[1] << 8) |
+		event_regs[2];
+
+	if (!ab3100->startup_events_read) {
+		ab3100->startup_events = fatevent;
+		ab3100->startup_events_read = true;
+	}
+	/*
+	 * The notified parties will have to mask out the events
+	 * they're interested in and react to them. They will be
+	 * notified on all events, then they use the fatevent value
+	 * to determine if they're interested.
+	 */
+	blocking_notifier_call_chain(&ab3100->event_subscribers,
+				     fatevent, NULL);
+
+	dev_dbg(ab3100->dev,
+		"IRQ Event: 0x%08x\n", fatevent);
+
+	/* By now the IRQ should be acked and deasserted so enable it again */
+	enable_irq(ab3100->i2c_client->irq);
+	return;
+
+ err_event_wq:
+	dev_dbg(ab3100->dev,
+		"error in event workqueue\n");
+	/* Enable the IRQ anyway, what choice do we have? */
+	enable_irq(ab3100->i2c_client->irq);
+	return;
+}
+
+static irqreturn_t ab3100_irq_handler(int irq, void *data)
+{
+	struct ab3100 *ab3100 = data;
+	/*
+	 * Disable the IRQ and dispatch a worker to handle the
+	 * event. Since the chip resides on I2C this is slow
+	 * stuff and we will re-enable the interrupts once th
+	 * worker has finished.
+	 */
+	disable_irq(ab3100->i2c_client->irq);
+	schedule_work(&ab3100->work);
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_DEBUG_FS
+/*
+ * Some debugfs entries only exposed if we're using debug
+ */
+static int ab3100_registers_print(struct seq_file *s, void *p)
+{
+	struct ab3100 *ab3100 = s->private;
+	u8 value;
+	u8 reg;
+
+	seq_printf(s, "AB3100 registers:\n");
+
+	for (reg = 0; reg < 0xff; reg++) {
+		ab3100_get_register(ab3100, reg, &value);
+		seq_printf(s, "[0x%x]:  0x%x\n", reg, value);
+	}
+	return 0;
+}
+
+static int ab3100_registers_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ab3100_registers_print, inode->i_private);
+}
+
+static const struct file_operations ab3100_registers_fops = {
+	.open = ab3100_registers_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
+struct ab3100_get_set_reg_priv {
+	struct ab3100 *ab3100;
+	bool mode;
+};
+
+static int ab3100_get_set_reg_open_file(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int ab3100_get_set_reg(struct file *file,
+			      const char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	struct ab3100_get_set_reg_priv *priv = file->private_data;
+	struct ab3100 *ab3100 = priv->ab3100;
+	char buf[32];
+	int buf_size;
+	int regp;
+	unsigned long user_reg;
+	int err;
+	int i = 0;
+
+	/* Get userspace string and assure termination */
+	buf_size = min(count, (sizeof(buf)-1));
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	buf[buf_size] = 0;
+
+	/*
+	 * The idea is here to parse a string which is either
+	 * "0xnn" for reading a register, or "0xaa 0xbb" for
+	 * writing 0xbb to the register 0xaa. First move past
+	 * whitespace and then begin to parse the register.
+	 */
+	while ((i < buf_size) && (buf[i] == ' '))
+		i++;
+	regp = i;
+
+	/*
+	 * Advance pointer to end of string then terminate
+	 * the register string. This is needed to satisfy
+	 * the strict_strtoul() function.
+	 */
+	while ((i < buf_size) && (buf[i] != ' '))
+		i++;
+	buf[i] = '\0';
+
+	err = strict_strtoul(&buf[regp], 16, &user_reg);
+	if (err)
+		return err;
+	if (user_reg > 0xff)
+		return -EINVAL;
+
+	/* Either we read or we write a register here */
+	if (!priv->mode) {
+		/* Reading */
+		u8 reg = (u8) user_reg;
+		u8 regvalue;
+
+		ab3100_get_register(ab3100, reg, &regvalue);
+
+		dev_info(ab3100->dev,
+			 "debug read AB3100 reg[0x%02x]: 0x%02x\n",
+			 reg, regvalue);
+	} else {
+		int valp;
+		unsigned long user_value;
+		u8 reg = (u8) user_reg;
+		u8 value;
+		u8 regvalue;
+
+		/*
+		 * Writing, we need some value to write to
+		 * the register so keep parsing the string
+		 * from userspace.
+		 */
+		i++;
+		while ((i < buf_size) && (buf[i] == ' '))
+			i++;
+		valp = i;
+		while ((i < buf_size) && (buf[i] != ' '))
+			i++;
+		buf[i] = '\0';
+
+		err = strict_strtoul(&buf[valp], 16, &user_value);
+		if (err)
+			return err;
+		if (user_reg > 0xff)
+			return -EINVAL;
+
+		value = (u8) user_value;
+		ab3100_set_register(ab3100, reg, value);
+		ab3100_get_register(ab3100, reg, &regvalue);
+
+		dev_info(ab3100->dev,
+			 "debug write reg[0x%02x] with 0x%02x, "
+			 "after readback: 0x%02x\n",
+			 reg, value, regvalue);
+	}
+	return buf_size;
+}
+
+static const struct file_operations ab3100_get_set_reg_fops = {
+	.open = ab3100_get_set_reg_open_file,
+	.write = ab3100_get_set_reg,
+};
+
+static struct dentry *ab3100_dir;
+static struct dentry *ab3100_reg_file;
+static struct ab3100_get_set_reg_priv ab3100_get_priv;
+static struct dentry *ab3100_get_reg_file;
+static struct ab3100_get_set_reg_priv ab3100_set_priv;
+static struct dentry *ab3100_set_reg_file;
+
+static void ab3100_setup_debugfs(struct ab3100 *ab3100)
+{
+	int err;
+
+	ab3100_dir = debugfs_create_dir("ab3100", NULL);
+	if (!ab3100_dir)
+		goto exit_no_debugfs;
+
+	ab3100_reg_file = debugfs_create_file("registers",
+				S_IRUGO, ab3100_dir, ab3100,
+				&ab3100_registers_fops);
+	if (!ab3100_reg_file) {
+		err = -ENOMEM;
+		goto exit_destroy_dir;
+	}
+
+	ab3100_get_priv.ab3100 = ab3100;
+	ab3100_get_priv.mode = false;
+	ab3100_get_reg_file = debugfs_create_file("get_reg",
+				S_IWUGO, ab3100_dir, &ab3100_get_priv,
+				&ab3100_get_set_reg_fops);
+	if (!ab3100_get_reg_file) {
+		err = -ENOMEM;
+		goto exit_destroy_reg;
+	}
+
+	ab3100_set_priv.ab3100 = ab3100;
+	ab3100_set_priv.mode = true;
+	ab3100_set_reg_file = debugfs_create_file("set_reg",
+				S_IWUGO, ab3100_dir, &ab3100_set_priv,
+				&ab3100_get_set_reg_fops);
+	if (!ab3100_set_reg_file) {
+		err = -ENOMEM;
+		goto exit_destroy_get_reg;
+	}
+	return;
+
+ exit_destroy_get_reg:
+	debugfs_remove(ab3100_get_reg_file);
+ exit_destroy_reg:
+	debugfs_remove(ab3100_reg_file);
+ exit_destroy_dir:
+	debugfs_remove(ab3100_dir);
+ exit_no_debugfs:
+	return;
+}
+static inline void ab3100_remove_debugfs(void)
+{
+	debugfs_remove(ab3100_set_reg_file);
+	debugfs_remove(ab3100_get_reg_file);
+	debugfs_remove(ab3100_reg_file);
+	debugfs_remove(ab3100_dir);
+}
+#else
+static inline void ab3100_setup_debugfs(struct ab3100 *ab3100)
+{
+}
+static inline void ab3100_remove_debugfs(void)
+{
+}
+#endif
+
+/*
+ * Basic set-up, datastructure creation/destruction and I2C interface.
+ * This sets up a default config in the AB3100 chip so that it
+ * will work as expected.
+ */
+
+struct ab3100_init_setting {
+	u8 abreg;
+	u8 setting;
+};
+
+static const struct ab3100_init_setting __initdata
+ab3100_init_settings[] = {
+	{
+		.abreg = AB3100_MCA,
+		.setting = 0x01
+	}, {
+		.abreg = AB3100_MCB,
+		.setting = 0x30
+	}, {
+		.abreg = AB3100_IMRA1,
+		.setting = 0x00
+	}, {
+		.abreg = AB3100_IMRA2,
+		.setting = 0xFF
+	}, {
+		.abreg = AB3100_IMRA3,
+		.setting = 0x01
+	}, {
+		.abreg = AB3100_IMRB1,
+		.setting = 0xFF
+	}, {
+		.abreg = AB3100_IMRB2,
+		.setting = 0xFF
+	}, {
+		.abreg = AB3100_IMRB3,
+		.setting = 0xFF
+	}, {
+		.abreg = AB3100_SUP,
+		.setting = 0x00
+	}, {
+		.abreg = AB3100_DIS,
+		.setting = 0xF0
+	}, {
+		.abreg = AB3100_D0C,
+		.setting = 0x00
+	}, {
+		.abreg = AB3100_D1C,
+		.setting = 0x00
+	}, {
+		.abreg = AB3100_D2C,
+		.setting = 0x00
+	}, {
+		.abreg = AB3100_D3C,
+		.setting = 0x00
+	},
+};
+
+static int __init ab3100_setup(struct ab3100 *ab3100)
+{
+	int err = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ab3100_init_settings); i++) {
+		err = ab3100_set_register(ab3100,
+					  ab3100_init_settings[i].abreg,
+					  ab3100_init_settings[i].setting);
+		if (err)
+			goto exit_no_setup;
+	}
+
+	/*
+	 * Special trick to make the AB3100 use the 32kHz clock (RTC)
+	 * bit 3 in test registe 0x02 is a special, undocumented test
+	 * register bit that only exist in AB3100 P1E
+	 */
+	if (ab3100->chip_id == 0xc4) {
+		dev_warn(ab3100->dev,
+			 "AB3100 P1E variant detected, "
+			 "forcing chip to 32KHz\n");
+		err = ab3100_set_test_register(ab3100, 0x02, 0x08);
+	}
+
+ exit_no_setup:
+	return err;
+}
+
+/*
+ * Here we define all the platform devices that appear
+ * as children of the AB3100. These are regular platform
+ * devices with the IORESOURCE_IO .start and .end set
+ * to correspond to the internal AB3100 register range
+ * mapping to the corresponding subdevice.
+ */
+
+#define AB3100_DEVICE(devname, devid)				\
+static struct platform_device ab3100_##devname##_device = {	\
+	.name		= devid,				\
+	.id		= -1,					\
+}
+
+/*
+ * This lists all the subdevices and corresponding register
+ * ranges.
+ */
+AB3100_DEVICE(dac, "ab3100-dac");
+AB3100_DEVICE(leds, "ab3100-leds");
+AB3100_DEVICE(power, "ab3100-power");
+AB3100_DEVICE(regulators, "ab3100-regulators");
+AB3100_DEVICE(sim, "ab3100-sim");
+AB3100_DEVICE(uart, "ab3100-uart");
+AB3100_DEVICE(rtc, "ab3100-rtc");
+AB3100_DEVICE(charger, "ab3100-charger");
+AB3100_DEVICE(boost, "ab3100-boost");
+AB3100_DEVICE(adc, "ab3100-adc");
+AB3100_DEVICE(fuelgauge, "ab3100-fuelgauge");
+AB3100_DEVICE(vibrator, "ab3100-vibrator");
+AB3100_DEVICE(otp, "ab3100-otp");
+AB3100_DEVICE(codec, "ab3100-codec");
+
+static struct platform_device *
+ab3100_platform_devs[] = {
+	&ab3100_dac_device,
+	&ab3100_leds_device,
+	&ab3100_power_device,
+	&ab3100_regulators_device,
+	&ab3100_sim_device,
+	&ab3100_uart_device,
+	&ab3100_rtc_device,
+	&ab3100_charger_device,
+	&ab3100_boost_device,
+	&ab3100_adc_device,
+	&ab3100_fuelgauge_device,
+	&ab3100_vibrator_device,
+	&ab3100_otp_device,
+	&ab3100_codec_device,
+};
+
+struct ab_family_id {
+	u8	id;
+	char	*name;
+};
+
+static const struct ab_family_id ids[] __initdata = {
+	/* AB3100 */
+	{
+		.id = 0xc0,
+		.name = "P1A"
+	}, {
+		.id = 0xc1,
+		.name = "P1B"
+	}, {
+		.id = 0xc2,
+		.name = "P1C"
+	}, {
+		.id = 0xc3,
+		.name = "P1D"
+	}, {
+		.id = 0xc4,
+		.name = "P1E"
+	}, {
+		.id = 0xc5,
+		.name = "P1F/R1A"
+	}, {
+		.id = 0xc6,
+		.name = "P1G/R1A"
+	}, {
+		.id = 0xc7,
+		.name = "P2A/R2A"
+	}, {
+		.id = 0xc8,
+		.name = "P2B/R2B"
+	},
+	/* AB3000 variants, not supported */
+	{
+		.id = 0xa0
+	}, {
+		.id = 0xa1
+	}, {
+		.id = 0xa2
+	}, {
+		.id = 0xa3
+	}, {
+		.id = 0xa4
+	}, {
+		.id = 0xa5
+	}, {
+		.id = 0xa6
+	}, {
+		.id = 0xa7
+	},
+	/* Terminator */
+	{
+		.id = 0x00,
+	},
+};
+
+static int __init ab3100_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct ab3100 *ab3100;
+	int err;
+	int i;
+
+	ab3100 = kzalloc(sizeof(struct ab3100), GFP_KERNEL);
+	if (!ab3100) {
+		dev_err(&client->dev, "could not allocate AB3100 device\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize data structure */
+	mutex_init(&ab3100->access_mutex);
+	BLOCKING_INIT_NOTIFIER_HEAD(&ab3100->event_subscribers);
+
+	ab3100->i2c_client = client;
+	ab3100->dev = &ab3100->i2c_client->dev;
+
+	i2c_set_clientdata(client, ab3100);
+
+	/* Read chip ID register */
+	err = ab3100_get_register(ab3100, AB3100_CID,
+				  &ab3100->chip_id);
+	if (err) {
+		dev_err(&client->dev,
+			"could not communicate with the AB3100 analog "
+			"baseband chip\n");
+		goto exit_no_detect;
+	}
+
+	for (i = 0; ids[i].id != 0x0; i++) {
+		if (ids[i].id == ab3100->chip_id) {
+			if (ids[i].name != NULL) {
+				snprintf(&ab3100->chip_name[0],
+					 sizeof(ab3100->chip_name) - 1,
+					 "AB3100 %s",
+					 ids[i].name);
+				break;
+			} else {
+				dev_err(&client->dev,
+					"AB3000 is not supported\n");
+				goto exit_no_detect;
+			}
+		}
+	}
+
+	if (ids[i].id == 0x0) {
+		dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
+			ab3100->chip_id);
+		dev_err(&client->dev, "accepting it anyway. Please update "
+			"the driver.\n");
+		goto exit_no_detect;
+	}
+
+	dev_info(&client->dev, "Detected chip: %s\n",
+		 &ab3100->chip_name[0]);
+
+	/* Attach a second dummy i2c_client to the test register address */
+	ab3100->testreg_client = i2c_new_dummy(client->adapter,
+						     client->addr + 1);
+	if (!ab3100->testreg_client) {
+		err = -ENOMEM;
+		goto exit_no_testreg_client;
+	}
+
+	strlcpy(ab3100->testreg_client->name, id->name,
+		sizeof(ab3100->testreg_client->name));
+
+	err = ab3100_setup(ab3100);
+	if (err)
+		goto exit_no_setup;
+
+	INIT_WORK(&ab3100->work, ab3100_work);
+
+	/* This real unpredictable IRQ is of course sampled for entropy */
+	err = request_irq(client->irq, ab3100_irq_handler,
+			  IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+			  "AB3100 IRQ", ab3100);
+	if (err)
+		goto exit_no_irq;
+
+	/* Set parent and a pointer back to the container in device data */
+	for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) {
+		ab3100_platform_devs[i]->dev.parent =
+			&client->dev;
+		platform_set_drvdata(ab3100_platform_devs[i], ab3100);
+	}
+
+	/* Register the platform devices */
+	platform_add_devices(ab3100_platform_devs,
+			     ARRAY_SIZE(ab3100_platform_devs));
+
+	ab3100_setup_debugfs(ab3100);
+
+	return 0;
+
+ exit_no_irq:
+ exit_no_setup:
+	i2c_unregister_device(ab3100->testreg_client);
+ exit_no_testreg_client:
+ exit_no_detect:
+	kfree(ab3100);
+	return err;
+}
+
+static int __exit ab3100_remove(struct i2c_client *client)
+{
+	struct ab3100 *ab3100 = i2c_get_clientdata(client);
+	int i;
+
+	/* Unregister subdevices */
+	for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++)
+		platform_device_unregister(ab3100_platform_devs[i]);
+
+	ab3100_remove_debugfs();
+	i2c_unregister_device(ab3100->testreg_client);
+
+	/*
+	 * At this point, all subscribers should have unregistered
+	 * their notifiers so deactivate IRQ
+	 */
+	free_irq(client->irq, ab3100);
+	kfree(ab3100);
+	return 0;
+}
+
+static const struct i2c_device_id ab3100_id[] = {
+	{ "ab3100", ab3100 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ab3100_id);
+
+static struct i2c_driver ab3100_driver = {
+	.driver = {
+		.name	= "ab3100",
+		.owner	= THIS_MODULE,
+	},
+	.id_table	= ab3100_id,
+	.probe		= ab3100_probe,
+	.remove		= __exit_p(ab3100_remove),
+};
+
+static int __init ab3100_i2c_init(void)
+{
+	return i2c_add_driver(&ab3100_driver);
+}
+
+static void __exit ab3100_i2c_exit(void)
+{
+	i2c_del_driver(&ab3100_driver);
+}
+
+subsys_initcall(ab3100_i2c_init);
+module_exit(ab3100_i2c_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
+MODULE_DESCRIPTION("AB3100 core driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/asic3.c linux-libre-2.6.31-gnu/drivers/mfd/asic3.c
--- linux-libre-2.6.30-gnu/drivers/mfd/asic3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/asic3.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
@@ -24,6 +25,51 @@
 #include <linux/platform_device.h>
 
 #include <linux/mfd/asic3.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ds1wm.h>
+#include <linux/mfd/tmio.h>
+
+enum {
+	ASIC3_CLOCK_SPI,
+	ASIC3_CLOCK_OWM,
+	ASIC3_CLOCK_PWM0,
+	ASIC3_CLOCK_PWM1,
+	ASIC3_CLOCK_LED0,
+	ASIC3_CLOCK_LED1,
+	ASIC3_CLOCK_LED2,
+	ASIC3_CLOCK_SD_HOST,
+	ASIC3_CLOCK_SD_BUS,
+	ASIC3_CLOCK_SMBUS,
+	ASIC3_CLOCK_EX0,
+	ASIC3_CLOCK_EX1,
+};
+
+struct asic3_clk {
+	int enabled;
+	unsigned int cdex;
+	unsigned long rate;
+};
+
+#define INIT_CDEX(_name, _rate)	\
+	[ASIC3_CLOCK_##_name] = {		\
+		.cdex = CLOCK_CDEX_##_name,	\
+		.rate = _rate,			\
+	}
+
+struct asic3_clk asic3_clk_init[] __initdata = {
+	INIT_CDEX(SPI, 0),
+	INIT_CDEX(OWM, 5000000),
+	INIT_CDEX(PWM0, 0),
+	INIT_CDEX(PWM1, 0),
+	INIT_CDEX(LED0, 0),
+	INIT_CDEX(LED1, 0),
+	INIT_CDEX(LED2, 0),
+	INIT_CDEX(SD_HOST, 24576000),
+	INIT_CDEX(SD_BUS, 12288000),
+	INIT_CDEX(SMBUS, 0),
+	INIT_CDEX(EX0, 32768),
+	INIT_CDEX(EX1, 24576000),
+};
 
 struct asic3 {
 	void __iomem *mapping;
@@ -34,6 +80,8 @@
 	u16 irq_bothedge[4];
 	struct gpio_chip gpio;
 	struct device *dev;
+
+	struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
 };
 
 static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset);
@@ -52,6 +100,21 @@
 			(reg >> asic->bus_shift));
 }
 
+void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
+{
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&asic->lock, flags);
+	val = asic3_read_register(asic, reg);
+	if (set)
+		val |= bits;
+	else
+		val &= ~bits;
+	asic3_write_register(asic, reg, val);
+	spin_unlock_irqrestore(&asic->lock, flags);
+}
+
 /* IRQs */
 #define MAX_ASIC_ISR_LOOPS    20
 #define ASIC3_GPIO_BASE_INCR \
@@ -525,6 +588,240 @@
 	return gpiochip_remove(&asic->gpio);
 }
 
+static int asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
+{
+	unsigned long flags;
+	u32 cdex;
+
+	spin_lock_irqsave(&asic->lock, flags);
+	if (clk->enabled++ == 0) {
+		cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
+		cdex |= clk->cdex;
+		asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
+	}
+	spin_unlock_irqrestore(&asic->lock, flags);
+
+	return 0;
+}
+
+static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
+{
+	unsigned long flags;
+	u32 cdex;
+
+	WARN_ON(clk->enabled == 0);
+
+	spin_lock_irqsave(&asic->lock, flags);
+	if (--clk->enabled == 0) {
+		cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
+		cdex &= ~clk->cdex;
+		asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
+	}
+	spin_unlock_irqrestore(&asic->lock, flags);
+}
+
+/* MFD cells (SPI, PWM, LED, DS1WM, MMC) */
+static struct ds1wm_driver_data ds1wm_pdata = {
+	.active_high = 1,
+};
+
+static struct resource ds1wm_resources[] = {
+	{
+		.start = ASIC3_OWM_BASE,
+		.end   = ASIC3_OWM_BASE + 0x13,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = ASIC3_IRQ_OWM,
+		.start = ASIC3_IRQ_OWM,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static int ds1wm_enable(struct platform_device *pdev)
+{
+	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+	/* Turn on external clocks and the OWM clock */
+	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
+	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
+	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
+	msleep(1);
+
+	/* Reset and enable DS1WM */
+	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
+			   ASIC3_EXTCF_OWM_RESET, 1);
+	msleep(1);
+	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
+			   ASIC3_EXTCF_OWM_RESET, 0);
+	msleep(1);
+	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
+			   ASIC3_EXTCF_OWM_EN, 1);
+	msleep(1);
+
+	return 0;
+}
+
+static int ds1wm_disable(struct platform_device *pdev)
+{
+	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
+			   ASIC3_EXTCF_OWM_EN, 0);
+
+	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
+	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
+	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
+
+	return 0;
+}
+
+static struct mfd_cell asic3_cell_ds1wm = {
+	.name          = "ds1wm",
+	.enable        = ds1wm_enable,
+	.disable       = ds1wm_disable,
+	.driver_data   = &ds1wm_pdata,
+	.num_resources = ARRAY_SIZE(ds1wm_resources),
+	.resources     = ds1wm_resources,
+};
+
+static struct tmio_mmc_data asic3_mmc_data = {
+	.hclk = 24576000,
+};
+
+static struct resource asic3_mmc_resources[] = {
+	{
+		.start = ASIC3_SD_CTRL_BASE,
+		.end   = ASIC3_SD_CTRL_BASE + 0x3ff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = ASIC3_SD_CONFIG_BASE,
+		.end   = ASIC3_SD_CONFIG_BASE + 0x1ff,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = 0,
+		.end   = 0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int asic3_mmc_enable(struct platform_device *pdev)
+{
+	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+	/* Not sure if it must be done bit by bit, but leaving as-is */
+	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
+			   ASIC3_SDHWCTRL_LEVCD, 1);
+	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
+			   ASIC3_SDHWCTRL_LEVWP, 1);
+	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
+			   ASIC3_SDHWCTRL_SUSPEND, 0);
+	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
+			   ASIC3_SDHWCTRL_PCLR, 0);
+
+	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
+	/* CLK32 used for card detection and for interruption detection
+	 * when HCLK is stopped.
+	 */
+	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
+	msleep(1);
+
+	/* HCLK 24.576 MHz, BCLK 12.288 MHz: */
+	asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL),
+		CLOCK_SEL_CX | CLOCK_SEL_SD_HCLK_SEL);
+
+	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]);
+	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]);
+	msleep(1);
+
+	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
+			   ASIC3_EXTCF_SD_MEM_ENABLE, 1);
+
+	/* Enable SD card slot 3.3V power supply */
+	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
+			   ASIC3_SDHWCTRL_SDPWR, 1);
+
+	return 0;
+}
+
+static int asic3_mmc_disable(struct platform_device *pdev)
+{
+	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+	/* Put in suspend mode */
+	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
+			   ASIC3_SDHWCTRL_SUSPEND, 1);
+
+	/* Disable clocks */
+	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]);
+	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]);
+	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
+	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
+	return 0;
+}
+
+static struct mfd_cell asic3_cell_mmc = {
+	.name          = "tmio-mmc",
+	.enable        = asic3_mmc_enable,
+	.disable       = asic3_mmc_disable,
+	.driver_data   = &asic3_mmc_data,
+	.num_resources = ARRAY_SIZE(asic3_mmc_resources),
+	.resources     = asic3_mmc_resources,
+};
+
+static int __init asic3_mfd_probe(struct platform_device *pdev,
+				  struct resource *mem)
+{
+	struct asic3 *asic = platform_get_drvdata(pdev);
+	struct resource *mem_sdio;
+	int irq, ret;
+
+	mem_sdio = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mem_sdio)
+		dev_dbg(asic->dev, "no SDIO MEM resource\n");
+
+	irq = platform_get_irq(pdev, 1);
+	if (irq < 0)
+		dev_dbg(asic->dev, "no SDIO IRQ resource\n");
+
+	/* DS1WM */
+	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
+			   ASIC3_EXTCF_OWM_SMB, 0);
+
+	ds1wm_resources[0].start >>= asic->bus_shift;
+	ds1wm_resources[0].end   >>= asic->bus_shift;
+
+	asic3_cell_ds1wm.platform_data = &asic3_cell_ds1wm;
+	asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
+
+	/* MMC */
+	asic3_mmc_resources[0].start >>= asic->bus_shift;
+	asic3_mmc_resources[0].end   >>= asic->bus_shift;
+	asic3_mmc_resources[1].start >>= asic->bus_shift;
+	asic3_mmc_resources[1].end   >>= asic->bus_shift;
+
+	asic3_cell_mmc.platform_data = &asic3_cell_mmc;
+	asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc);
+
+	ret = mfd_add_devices(&pdev->dev, pdev->id,
+			&asic3_cell_ds1wm, 1, mem, asic->irq_base);
+	if (ret < 0)
+		goto out;
+
+	if (mem_sdio && (irq >= 0))
+		ret = mfd_add_devices(&pdev->dev, pdev->id,
+			&asic3_cell_mmc, 1, mem_sdio, irq);
+
+ out:
+	return ret;
+}
+
+static void asic3_mfd_remove(struct platform_device *pdev)
+{
+	mfd_remove_devices(&pdev->dev);
+}
 
 /* Core */
 static int __init asic3_probe(struct platform_device *pdev)
@@ -533,7 +830,6 @@
 	struct asic3 *asic;
 	struct resource *mem;
 	unsigned long clksel;
-	int map_size;
 	int ret = 0;
 
 	asic = kzalloc(sizeof(struct asic3), GFP_KERNEL);
@@ -553,8 +849,7 @@
 		goto out_free;
 	}
 
-	map_size = mem->end - mem->start + 1;
-	asic->mapping = ioremap(mem->start, map_size);
+	asic->mapping = ioremap(mem->start, resource_size(mem));
 	if (!asic->mapping) {
 		ret = -ENOMEM;
 		dev_err(asic->dev, "Couldn't ioremap\n");
@@ -564,7 +859,7 @@
 	asic->irq_base = pdata->irq_base;
 
 	/* calculate bus shift from mem resource */
-	asic->bus_shift = 2 - (map_size >> 12);
+	asic->bus_shift = 2 - (resource_size(mem) >> 12);
 
 	clksel = 0;
 	asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel);
@@ -590,6 +885,13 @@
 		goto out_irq;
 	}
 
+	/* Making a per-device copy is only needed for the
+	 * theoretical case of multiple ASIC3s on one board:
+	 */
+	memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init));
+
+	asic3_mfd_probe(pdev, mem);
+
 	dev_info(asic->dev, "ASIC3 Core driver\n");
 
 	return 0;
@@ -611,6 +913,8 @@
 	int ret;
 	struct asic3 *asic = platform_get_drvdata(pdev);
 
+	asic3_mfd_remove(pdev);
+
 	ret = asic3_gpio_remove(pdev);
 	if (ret < 0)
 		return ret;
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/da903x.c linux-libre-2.6.31-gnu/drivers/mfd/da903x.c
--- linux-libre-2.6.30-gnu/drivers/mfd/da903x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/da903x.c	2009-09-09 18:13:59.000000000 -0400
@@ -561,7 +561,7 @@
 {
 	return i2c_add_driver(&da903x_driver);
 }
-module_init(da903x_init);
+subsys_initcall(da903x_init);
 
 static void __exit da903x_exit(void)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/dm355evm_msp.c linux-libre-2.6.31-gnu/drivers/mfd/dm355evm_msp.c
--- linux-libre-2.6.30-gnu/drivers/mfd/dm355evm_msp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/dm355evm_msp.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,8 +32,7 @@
  * This driver was tested with firmware revision A4.
  */
 
-#if defined(CONFIG_KEYBOARD_DM355EVM) \
-		|| defined(CONFIG_KEYBOARD_DM355EVM_MODULE)
+#if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE)
 #define msp_has_keyboard()	true
 #else
 #define msp_has_keyboard()	false
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/ezx-pcap.c linux-libre-2.6.31-gnu/drivers/mfd/ezx-pcap.c
--- linux-libre-2.6.30-gnu/drivers/mfd/ezx-pcap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mfd/ezx-pcap.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,507 @@
+/*
+ * Driver for Motorola PCAP2 as present in EZX phones
+ *
+ * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
+ * Copyright (C) 2009 Daniel Ribeiro <drwyrm@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/ezx-pcap.h>
+#include <linux/spi/spi.h>
+
+#define PCAP_ADC_MAXQ		8
+struct pcap_adc_request {
+	u8 bank;
+	u8 ch[2];
+	u32 flags;
+	void (*callback)(void *, u16[]);
+	void *data;
+};
+
+struct pcap_adc_sync_request {
+	u16 res[2];
+	struct completion completion;
+};
+
+struct pcap_chip {
+	struct spi_device *spi;
+
+	/* IO */
+	u32 buf;
+	struct mutex io_mutex;
+
+	/* IRQ */
+	unsigned int irq_base;
+	u32 msr;
+	struct work_struct isr_work;
+	struct work_struct msr_work;
+	struct workqueue_struct *workqueue;
+
+	/* ADC */
+	struct pcap_adc_request *adc_queue[PCAP_ADC_MAXQ];
+	u8 adc_head;
+	u8 adc_tail;
+	struct mutex adc_mutex;
+};
+
+/* IO */
+static int ezx_pcap_putget(struct pcap_chip *pcap, u32 *data)
+{
+	struct spi_transfer t;
+	struct spi_message m;
+	int status;
+
+	memset(&t, 0, sizeof t);
+	spi_message_init(&m);
+	t.len = sizeof(u32);
+	spi_message_add_tail(&t, &m);
+
+	pcap->buf = *data;
+	t.tx_buf = (u8 *) &pcap->buf;
+	t.rx_buf = (u8 *) &pcap->buf;
+	status = spi_sync(pcap->spi, &m);
+
+	if (status == 0)
+		*data = pcap->buf;
+
+	return status;
+}
+
+int ezx_pcap_write(struct pcap_chip *pcap, u8 reg_num, u32 value)
+{
+	int ret;
+
+	mutex_lock(&pcap->io_mutex);
+	value &= PCAP_REGISTER_VALUE_MASK;
+	value |= PCAP_REGISTER_WRITE_OP_BIT
+		| (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
+	ret = ezx_pcap_putget(pcap, &value);
+	mutex_unlock(&pcap->io_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_write);
+
+int ezx_pcap_read(struct pcap_chip *pcap, u8 reg_num, u32 *value)
+{
+	int ret;
+
+	mutex_lock(&pcap->io_mutex);
+	*value = PCAP_REGISTER_READ_OP_BIT
+		| (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
+
+	ret = ezx_pcap_putget(pcap, value);
+	mutex_unlock(&pcap->io_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_read);
+
+/* IRQ */
+static inline unsigned int irq2pcap(struct pcap_chip *pcap, int irq)
+{
+	return 1 << (irq - pcap->irq_base);
+}
+
+int pcap_to_irq(struct pcap_chip *pcap, int irq)
+{
+	return pcap->irq_base + irq;
+}
+EXPORT_SYMBOL_GPL(pcap_to_irq);
+
+static void pcap_mask_irq(unsigned int irq)
+{
+	struct pcap_chip *pcap = get_irq_chip_data(irq);
+
+	pcap->msr |= irq2pcap(pcap, irq);
+	queue_work(pcap->workqueue, &pcap->msr_work);
+}
+
+static void pcap_unmask_irq(unsigned int irq)
+{
+	struct pcap_chip *pcap = get_irq_chip_data(irq);
+
+	pcap->msr &= ~irq2pcap(pcap, irq);
+	queue_work(pcap->workqueue, &pcap->msr_work);
+}
+
+static struct irq_chip pcap_irq_chip = {
+	.name	= "pcap",
+	.mask	= pcap_mask_irq,
+	.unmask	= pcap_unmask_irq,
+};
+
+static void pcap_msr_work(struct work_struct *work)
+{
+	struct pcap_chip *pcap = container_of(work, struct pcap_chip, msr_work);
+
+	ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
+}
+
+static void pcap_isr_work(struct work_struct *work)
+{
+	struct pcap_chip *pcap = container_of(work, struct pcap_chip, isr_work);
+	struct pcap_platform_data *pdata = pcap->spi->dev.platform_data;
+	u32 msr, isr, int_sel, service;
+	int irq;
+
+	ezx_pcap_read(pcap, PCAP_REG_MSR, &msr);
+	ezx_pcap_read(pcap, PCAP_REG_ISR, &isr);
+
+	/* We cant service/ack irqs that are assigned to port 2 */
+	if (!(pdata->config & PCAP_SECOND_PORT)) {
+		ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel);
+		isr &= ~int_sel;
+	}
+	ezx_pcap_write(pcap, PCAP_REG_ISR, isr);
+
+	local_irq_disable();
+	service = isr & ~msr;
+
+	for (irq = pcap->irq_base; service; service >>= 1, irq++) {
+		if (service & 1) {
+			struct irq_desc *desc = irq_to_desc(irq);
+
+			if (WARN(!desc, KERN_WARNING
+					"Invalid PCAP IRQ %d\n", irq))
+				break;
+
+			if (desc->status & IRQ_DISABLED)
+				note_interrupt(irq, desc, IRQ_NONE);
+			else
+				desc->handle_irq(irq, desc);
+		}
+	}
+	local_irq_enable();
+}
+
+static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pcap_chip *pcap = get_irq_data(irq);
+
+	desc->chip->ack(irq);
+	queue_work(pcap->workqueue, &pcap->isr_work);
+	return;
+}
+
+/* ADC */
+static void pcap_disable_adc(struct pcap_chip *pcap)
+{
+	u32 tmp;
+
+	ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
+	tmp &= ~(PCAP_ADC_ADEN|PCAP_ADC_BATT_I_ADC|PCAP_ADC_BATT_I_POLARITY);
+	ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
+}
+
+static void pcap_adc_trigger(struct pcap_chip *pcap)
+{
+	u32 tmp;
+	u8 head;
+
+	mutex_lock(&pcap->adc_mutex);
+	head = pcap->adc_head;
+	if (!pcap->adc_queue[head]) {
+		/* queue is empty, save power */
+		pcap_disable_adc(pcap);
+		mutex_unlock(&pcap->adc_mutex);
+		return;
+	}
+	mutex_unlock(&pcap->adc_mutex);
+
+	/* start conversion on requested bank */
+	tmp = pcap->adc_queue[head]->flags | PCAP_ADC_ADEN;
+
+	if (pcap->adc_queue[head]->bank == PCAP_ADC_BANK_1)
+		tmp |= PCAP_ADC_AD_SEL1;
+
+	ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
+	ezx_pcap_write(pcap, PCAP_REG_ADR, PCAP_ADR_ASC);
+}
+
+static irqreturn_t pcap_adc_irq(int irq, void *_pcap)
+{
+	struct pcap_chip *pcap = _pcap;
+	struct pcap_adc_request *req;
+	u16 res[2];
+	u32 tmp;
+
+	mutex_lock(&pcap->adc_mutex);
+	req = pcap->adc_queue[pcap->adc_head];
+
+	if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) {
+		mutex_unlock(&pcap->adc_mutex);
+		return IRQ_HANDLED;
+	}
+
+	/* read requested channels results */
+	ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
+	tmp &= ~(PCAP_ADC_ADA1_MASK | PCAP_ADC_ADA2_MASK);
+	tmp |= (req->ch[0] << PCAP_ADC_ADA1_SHIFT);
+	tmp |= (req->ch[1] << PCAP_ADC_ADA2_SHIFT);
+	ezx_pcap_write(pcap, PCAP_REG_ADC, tmp);
+	ezx_pcap_read(pcap, PCAP_REG_ADR, &tmp);
+	res[0] = (tmp & PCAP_ADR_ADD1_MASK) >> PCAP_ADR_ADD1_SHIFT;
+	res[1] = (tmp & PCAP_ADR_ADD2_MASK) >> PCAP_ADR_ADD2_SHIFT;
+
+	pcap->adc_queue[pcap->adc_head] = NULL;
+	pcap->adc_head = (pcap->adc_head + 1) & (PCAP_ADC_MAXQ - 1);
+	mutex_unlock(&pcap->adc_mutex);
+
+	/* pass the results and release memory */
+	req->callback(req->data, res);
+	kfree(req);
+
+	/* trigger next conversion (if any) on queue */
+	pcap_adc_trigger(pcap);
+
+	return IRQ_HANDLED;
+}
+
+int pcap_adc_async(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[],
+						void *callback, void *data)
+{
+	struct pcap_adc_request *req;
+
+	/* This will be freed after we have a result */
+	req = kmalloc(sizeof(struct pcap_adc_request), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	req->bank = bank;
+	req->flags = flags;
+	req->ch[0] = ch[0];
+	req->ch[1] = ch[1];
+	req->callback = callback;
+	req->data = data;
+
+	mutex_lock(&pcap->adc_mutex);
+	if (pcap->adc_queue[pcap->adc_tail]) {
+		mutex_unlock(&pcap->adc_mutex);
+		kfree(req);
+		return -EBUSY;
+	}
+	pcap->adc_queue[pcap->adc_tail] = req;
+	pcap->adc_tail = (pcap->adc_tail + 1) & (PCAP_ADC_MAXQ - 1);
+	mutex_unlock(&pcap->adc_mutex);
+
+	/* start conversion */
+	pcap_adc_trigger(pcap);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pcap_adc_async);
+
+static void pcap_adc_sync_cb(void *param, u16 res[])
+{
+	struct pcap_adc_sync_request *req = param;
+
+	req->res[0] = res[0];
+	req->res[1] = res[1];
+	complete(&req->completion);
+}
+
+int pcap_adc_sync(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[],
+								u16 res[])
+{
+	struct pcap_adc_sync_request sync_data;
+	int ret;
+
+	init_completion(&sync_data.completion);
+	ret = pcap_adc_async(pcap, bank, flags, ch, pcap_adc_sync_cb,
+								&sync_data);
+	if (ret)
+		return ret;
+	wait_for_completion(&sync_data.completion);
+	res[0] = sync_data.res[0];
+	res[1] = sync_data.res[1];
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pcap_adc_sync);
+
+/* subdevs */
+static int pcap_remove_subdev(struct device *dev, void *unused)
+{
+	platform_device_unregister(to_platform_device(dev));
+	return 0;
+}
+
+static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
+						struct pcap_subdev *subdev)
+{
+	struct platform_device *pdev;
+
+	pdev = platform_device_alloc(subdev->name, subdev->id);
+	pdev->dev.parent = &pcap->spi->dev;
+	pdev->dev.platform_data = subdev->platform_data;
+	platform_set_drvdata(pdev, pcap);
+
+	return platform_device_add(pdev);
+}
+
+static int __devexit ezx_pcap_remove(struct spi_device *spi)
+{
+	struct pcap_chip *pcap = dev_get_drvdata(&spi->dev);
+	struct pcap_platform_data *pdata = spi->dev.platform_data;
+	int i, adc_irq;
+
+	/* remove all registered subdevs */
+	device_for_each_child(&spi->dev, NULL, pcap_remove_subdev);
+
+	/* cleanup ADC */
+	adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
+				PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE);
+	free_irq(adc_irq, pcap);
+	mutex_lock(&pcap->adc_mutex);
+	for (i = 0; i < PCAP_ADC_MAXQ; i++)
+		kfree(pcap->adc_queue[i]);
+	mutex_unlock(&pcap->adc_mutex);
+
+	/* cleanup irqchip */
+	for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
+		set_irq_chip_and_handler(i, NULL, NULL);
+
+	destroy_workqueue(pcap->workqueue);
+
+	kfree(pcap);
+
+	return 0;
+}
+
+static int __devinit ezx_pcap_probe(struct spi_device *spi)
+{
+	struct pcap_platform_data *pdata = spi->dev.platform_data;
+	struct pcap_chip *pcap;
+	int i, adc_irq;
+	int ret = -ENODEV;
+
+	/* platform data is required */
+	if (!pdata)
+		goto ret;
+
+	pcap = kzalloc(sizeof(*pcap), GFP_KERNEL);
+	if (!pcap) {
+		ret = -ENOMEM;
+		goto ret;
+	}
+
+	mutex_init(&pcap->io_mutex);
+	mutex_init(&pcap->adc_mutex);
+	INIT_WORK(&pcap->isr_work, pcap_isr_work);
+	INIT_WORK(&pcap->msr_work, pcap_msr_work);
+	dev_set_drvdata(&spi->dev, pcap);
+
+	/* setup spi */
+	spi->bits_per_word = 32;
+	spi->mode = SPI_MODE_0 | (pdata->config & PCAP_CS_AH ? SPI_CS_HIGH : 0);
+	ret = spi_setup(spi);
+	if (ret)
+		goto free_pcap;
+
+	pcap->spi = spi;
+
+	/* setup irq */
+	pcap->irq_base = pdata->irq_base;
+	pcap->workqueue = create_singlethread_workqueue("pcapd");
+	if (!pcap->workqueue) {
+		dev_err(&spi->dev, "cant create pcap thread\n");
+		goto free_pcap;
+	}
+
+	/* redirect interrupts to AP, except adcdone2 */
+	if (!(pdata->config & PCAP_SECOND_PORT))
+		ezx_pcap_write(pcap, PCAP_REG_INT_SEL,
+					(1 << PCAP_IRQ_ADCDONE2));
+
+	/* setup irq chip */
+	for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) {
+		set_irq_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq);
+		set_irq_chip_data(i, pcap);
+#ifdef CONFIG_ARM
+		set_irq_flags(i, IRQF_VALID);
+#else
+		set_irq_noprobe(i);
+#endif
+	}
+
+	/* mask/ack all PCAP interrupts */
+	ezx_pcap_write(pcap, PCAP_REG_MSR, PCAP_MASK_ALL_INTERRUPT);
+	ezx_pcap_write(pcap, PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER);
+	pcap->msr = PCAP_MASK_ALL_INTERRUPT;
+
+	set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING);
+	set_irq_data(spi->irq, pcap);
+	set_irq_chained_handler(spi->irq, pcap_irq_handler);
+	set_irq_wake(spi->irq, 1);
+
+	/* ADC */
+	adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
+					PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE);
+
+	ret = request_irq(adc_irq, pcap_adc_irq, 0, "ADC", pcap);
+	if (ret)
+		goto free_irqchip;
+
+	/* setup subdevs */
+	for (i = 0; i < pdata->num_subdevs; i++) {
+		ret = pcap_add_subdev(pcap, &pdata->subdevs[i]);
+		if (ret)
+			goto remove_subdevs;
+	}
+
+	/* board specific quirks */
+	if (pdata->init)
+		pdata->init(pcap);
+
+	return 0;
+
+remove_subdevs:
+	device_for_each_child(&spi->dev, NULL, pcap_remove_subdev);
+/* free_adc: */
+	free_irq(adc_irq, pcap);
+free_irqchip:
+	for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
+		set_irq_chip_and_handler(i, NULL, NULL);
+/* destroy_workqueue: */
+	destroy_workqueue(pcap->workqueue);
+free_pcap:
+	kfree(pcap);
+ret:
+	return ret;
+}
+
+static struct spi_driver ezxpcap_driver = {
+	.probe	= ezx_pcap_probe,
+	.remove = __devexit_p(ezx_pcap_remove),
+	.driver = {
+		.name	= "ezx-pcap",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ezx_pcap_init(void)
+{
+	return spi_register_driver(&ezxpcap_driver);
+}
+
+static void __exit ezx_pcap_exit(void)
+{
+	spi_unregister_driver(&ezxpcap_driver);
+}
+
+module_init(ezx_pcap_init);
+module_exit(ezx_pcap_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
+MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver");
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/htc-pasic3.c linux-libre-2.6.31-gnu/drivers/mfd/htc-pasic3.c
--- linux-libre-2.6.30-gnu/drivers/mfd/htc-pasic3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/htc-pasic3.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,7 +35,7 @@
  */
 void pasic3_write_register(struct device *dev, u32 reg, u8 val)
 {
-	struct pasic3_data *asic = dev->driver_data;
+	struct pasic3_data *asic = dev_get_drvdata(dev);
 	int bus_shift = asic->bus_shift;
 	void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
 	void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
@@ -50,7 +50,7 @@
  */
 u8 pasic3_read_register(struct device *dev, u32 reg)
 {
-	struct pasic3_data *asic = dev->driver_data;
+	struct pasic3_data *asic = dev_get_drvdata(dev);
 	int bus_shift = asic->bus_shift;
 	void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
 	void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/Kconfig linux-libre-2.6.31-gnu/drivers/mfd/Kconfig
--- linux-libre-2.6.30-gnu/drivers/mfd/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 config MFD_ASIC3
 	bool "Support for Compaq ASIC3"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
+	select MFD_CORE
 	 ---help---
 	  This driver supports the ASIC3 multifunction chip found on many
 	  PDAs (mainly iPAQ and HTC based ones)
@@ -152,7 +153,7 @@
 	depends on I2C
 	help
 	  Support for the Wolfson Microelecronics WM8400 PMIC and audio
-	  CODEC.  This driver adds provides common support for accessing
+	  CODEC.  This driver provides common support for accessing
 	  the device, additional drivers must be enabled in order to use
 	  the functionality of the device.
 
@@ -241,6 +242,27 @@
 	 Say yes here if you want to include support GPIO for pins on
 	 the PCF50633 chip.
 
+config AB3100_CORE
+	tristate "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
+	depends on I2C
+	default y if ARCH_U300
+	help
+	  Select this to enable the AB3100 Mixed Signal IC core
+	  functionality. This connects to a AB3100 on the I2C bus
+	  and expose a number of symbols needed for dependent devices
+	  to read and write registers and subscribe to events from
+	  this multi-functional IC. This is needed to use other features
+	  of the AB3100 such as battery-backed RTC, charging control,
+	  LEDs, vibrator, system power and temperature, power management
+	  and ALSA sound.
+
+config EZX_PCAP
+	bool "PCAP Support"
+	depends on GENERIC_HARDIRQS && SPI_MASTER
+	help
+	  This enables the PCAP ASIC present on EZX Phones. This is
+	  needed for MMC, TouchScreen, Sound, USB, etc..
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/Makefile linux-libre-2.6.31-gnu/drivers/mfd/Makefile
--- linux-libre-2.6.30-gnu/drivers/mfd/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,8 @@
 
 obj-$(CONFIG_MFD_CORE)		+= mfd-core.o
 
+obj-$(CONFIG_EZX_PCAP)		+= ezx-pcap.o
+
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
@@ -40,4 +42,5 @@
 
 obj-$(CONFIG_MFD_PCF50633)	+= pcf50633-core.o
 obj-$(CONFIG_PCF50633_ADC)	+= pcf50633-adc.o
-obj-$(CONFIG_PCF50633_GPIO)	+= pcf50633-gpio.o
\ No newline at end of file
+obj-$(CONFIG_PCF50633_GPIO)	+= pcf50633-gpio.o
+obj-$(CONFIG_AB3100_CORE)	+= ab3100-core.o
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/pcf50633-core.c linux-libre-2.6.31-gnu/drivers/mfd/pcf50633-core.c
--- linux-libre-2.6.30-gnu/drivers/mfd/pcf50633-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/pcf50633-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -618,7 +618,7 @@
 
 		pdev->dev.parent = pcf->dev;
 		pdev->dev.platform_data = &pdata->reg_init_data[i];
-		pdev->dev.driver_data = pcf;
+		dev_set_drvdata(&pdev->dev, pcf);
 		pcf->regulator_pdev[i] = pdev;
 
 		platform_device_add(pdev);
@@ -705,5 +705,5 @@
 MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
 MODULE_LICENSE("GPL");
 
-module_init(pcf50633_init);
+subsys_initcall(pcf50633_init);
 module_exit(pcf50633_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/pcf50633-gpio.c linux-libre-2.6.31-gnu/drivers/mfd/pcf50633-gpio.c
--- linux-libre-2.6.30-gnu/drivers/mfd/pcf50633-gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/pcf50633-gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/gpio.h>
@@ -116,3 +117,5 @@
 	return pcf50633_reg_set_bit_mask(pcf, reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(pcf50633_gpio_power_supply_set);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/sm501.c linux-libre-2.6.31-gnu/drivers/mfd/sm501.c
--- linux-libre-2.6.30-gnu/drivers/mfd/sm501.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/sm501.c	2009-09-09 18:13:59.000000000 -0400
@@ -367,7 +367,8 @@
 		break;
 
 	default:
-		return -1;
+		gate = -1;
+		goto already;
 	}
 
 	writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/t7l66xb.c linux-libre-2.6.31-gnu/drivers/mfd/t7l66xb.c
--- linux-libre-2.6.30-gnu/drivers/mfd/t7l66xb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/t7l66xb.c	2009-09-09 18:13:59.000000000 -0400
@@ -108,6 +108,10 @@
 
 /*--------------------------------------------------------------------------*/
 
+static struct tmio_mmc_data t7166xb_mmc_data = {
+	.hclk = 24000000,
+};
+
 static const struct resource t7l66xb_mmc_resources[] = {
 	{
 		.start = 0x800,
@@ -149,6 +153,7 @@
 		.name = "tmio-mmc",
 		.enable = t7l66xb_mmc_enable,
 		.disable = t7l66xb_mmc_disable,
+		.driver_data = &t7166xb_mmc_data,
 		.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
 		.resources = t7l66xb_mmc_resources,
 	},
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/tc6387xb.c linux-libre-2.6.31-gnu/drivers/mfd/tc6387xb.c
--- linux-libre-2.6.30-gnu/drivers/mfd/tc6387xb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/tc6387xb.c	2009-09-09 18:13:59.000000000 -0400
@@ -75,6 +75,10 @@
 
 /*--------------------------------------------------------------------------*/
 
+static struct tmio_mmc_data tc6387xb_mmc_data = {
+	.hclk = 24000000,
+};
+
 static struct resource tc6387xb_mmc_resources[] = {
 	{
 		.start = 0x800,
@@ -98,6 +102,7 @@
 		.name = "tmio-mmc",
 		.enable = tc6387xb_mmc_enable,
 		.disable = tc6387xb_mmc_disable,
+		.driver_data = &tc6387xb_mmc_data,
 		.num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
 		.resources = tc6387xb_mmc_resources,
 	},
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/tc6393xb.c linux-libre-2.6.31-gnu/drivers/mfd/tc6393xb.c
--- linux-libre-2.6.30-gnu/drivers/mfd/tc6393xb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/tc6393xb.c	2009-09-09 18:13:59.000000000 -0400
@@ -136,6 +136,10 @@
 	return 0;
 }
 
+static struct tmio_mmc_data tc6393xb_mmc_data = {
+	.hclk = 24000000,
+};
+
 static struct resource __devinitdata tc6393xb_nand_resources[] = {
 	{
 		.start	= 0x1000,
@@ -351,6 +355,7 @@
 	},
 	[TC6393XB_CELL_MMC] = {
 		.name = "tmio-mmc",
+		.driver_data = &tc6393xb_mmc_data,
 		.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
 		.resources = tc6393xb_mmc_resources,
 	},
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/twl4030-core.c linux-libre-2.6.31-gnu/drivers/mfd/twl4030-core.c
--- linux-libre-2.6.30-gnu/drivers/mfd/twl4030-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/twl4030-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -101,6 +101,12 @@
 #define twl_has_usb()	false
 #endif
 
+#if defined(CONFIG_TWL4030_WATCHDOG) || \
+	defined(CONFIG_TWL4030_WATCHDOG_MODULE)
+#define twl_has_watchdog()        true
+#else
+#define twl_has_watchdog()        false
+#endif
 
 /* Triton Core internal information (BEGIN) */
 
@@ -526,6 +532,12 @@
 		usb_transceiver = child;
 	}
 
+	if (twl_has_watchdog()) {
+		child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+	}
+
 	if (twl_has_regulator()) {
 		/*
 		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
@@ -647,7 +659,7 @@
 	return e;
 }
 
-static void __init clocks_init(struct device *dev)
+static void clocks_init(struct device *dev)
 {
 	int e = 0;
 	struct clk *osc;
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/twl4030-irq.c linux-libre-2.6.31-gnu/drivers/mfd/twl4030-irq.c
--- linux-libre-2.6.30-gnu/drivers/mfd/twl4030-irq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/twl4030-irq.c	2009-09-09 18:13:59.000000000 -0400
@@ -180,14 +180,9 @@
 static int twl4030_irq_thread(void *data)
 {
 	long irq = (long)data;
-	struct irq_desc *desc = irq_to_desc(irq);
 	static unsigned i2c_errors;
 	static const unsigned max_i2c_errors = 100;
 
-	if (!desc) {
-		pr_err("twl4030: Invalid IRQ: %ld\n", irq);
-		return -EINVAL;
-	}
 
 	current->flags |= PF_NOFREEZE;
 
@@ -240,7 +235,7 @@
 		}
 		local_irq_enable();
 
-		desc->chip->unmask(irq);
+		enable_irq(irq);
 	}
 
 	return 0;
@@ -255,25 +250,13 @@
  * thread.  All we do here is acknowledge and mask the interrupt and wakeup
  * the kernel thread.
  */
-static void handle_twl4030_pih(unsigned int irq, irq_desc_t *desc)
+static irqreturn_t handle_twl4030_pih(int irq, void *devid)
 {
 	/* Acknowledge, clear *AND* mask the interrupt... */
-	desc->chip->ack(irq);
-	complete(&irq_event);
-}
-
-static struct task_struct *start_twl4030_irq_thread(long irq)
-{
-	struct task_struct *thread;
-
-	init_completion(&irq_event);
-	thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq");
-	if (!thread)
-		pr_err("twl4030: could not create irq %ld thread!\n", irq);
-
-	return thread;
+	disable_irq_nosync(irq);
+	complete(devid);
+	return IRQ_HANDLED;
 }
-
 /*----------------------------------------------------------------------*/
 
 /*
@@ -734,18 +717,28 @@
 	}
 
 	/* install an irq handler to demultiplex the TWL4030 interrupt */
-	task = start_twl4030_irq_thread(irq_num);
-	if (!task) {
-		pr_err("twl4030: irq thread FAIL\n");
-		status = -ESRCH;
-		goto fail;
-	}
 
-	set_irq_data(irq_num, task);
-	set_irq_chained_handler(irq_num, handle_twl4030_pih);
 
-	return status;
+	init_completion(&irq_event);
 
+	status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED,
+				"TWL4030-PIH", &irq_event);
+	if (status < 0) {
+		pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
+		goto fail_rqirq;
+	}
+
+	task = kthread_run(twl4030_irq_thread, (void *)irq_num, "twl4030-irq");
+	if (IS_ERR(task)) {
+		pr_err("twl4030: could not create irq %d thread!\n", irq_num);
+		status = PTR_ERR(task);
+		goto fail_kthread;
+	}
+	return status;
+fail_kthread:
+	free_irq(irq_num, &irq_event);
+fail_rqirq:
+	/* clean up twl4030_sih_setup */
 fail:
 	for (i = irq_base; i < irq_end; i++)
 		set_irq_chip_and_handler(i, NULL, NULL);
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/ucb1400_core.c linux-libre-2.6.31-gnu/drivers/mfd/ucb1400_core.c
--- linux-libre-2.6.30-gnu/drivers/mfd/ucb1400_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/ucb1400_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,6 +23,26 @@
 #include <linux/module.h>
 #include <linux/ucb1400.h>
 
+unsigned int ucb1400_adc_read(struct snd_ac97 *ac97, u16 adc_channel,
+		int adcsync)
+{
+	unsigned int val;
+
+	if (adcsync)
+		adc_channel |= UCB_ADC_SYNC_ENA;
+
+	ucb1400_reg_write(ac97, UCB_ADC_CR, UCB_ADC_ENA | adc_channel);
+	ucb1400_reg_write(ac97, UCB_ADC_CR, UCB_ADC_ENA | adc_channel |
+			UCB_ADC_START);
+
+	while (!((val = ucb1400_reg_read(ac97, UCB_ADC_DATA))
+				& UCB_ADC_DAT_VALID))
+		schedule_timeout_uninterruptible(1);
+
+	return val & UCB_ADC_DAT_MASK;
+}
+EXPORT_SYMBOL_GPL(ucb1400_adc_read);
+
 static int ucb1400_core_probe(struct device *dev)
 {
 	int err;
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/wm8350-regmap.c linux-libre-2.6.31-gnu/drivers/mfd/wm8350-regmap.c
--- linux-libre-2.6.30-gnu/drivers/mfd/wm8350-regmap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/wm8350-regmap.c	2009-09-09 18:13:59.000000000 -0400
@@ -3186,7 +3186,7 @@
 	/*  read    write volatile */
 	{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R0   - Reset/ID */
 	{ 0x7CFF, 0x0C00, 0x7FFF }, /* R1   - ID */
-	{ 0x0000, 0x0000, 0x0000 }, /* R2 */
+	{ 0x007F, 0x0000, 0x0000 }, /* R2   - ROM Mask ID */
 	{ 0xBE3B, 0xBE3B, 0x8000 }, /* R3   - System Control 1 */
 	{ 0xFEF7, 0xFEF7, 0xF800 }, /* R4   - System Control 2 */
 	{ 0x80FF, 0x80FF, 0x8000 }, /* R5   - System Hibernate */
@@ -3411,7 +3411,7 @@
 	{ 0x0000, 0x0000, 0x0000 }, /* R224 */
 	{ 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
 	{ 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */
-	{ 0x0000, 0x0000, 0xFFFF }, /* R227 */
+	{ 0x34FE, 0x0000, 0xFFFF }, /* R227 */
 	{ 0x0000, 0x0000, 0x0000 }, /* R228 */
 	{ 0x0000, 0x0000, 0x0000 }, /* R229 */
 	{ 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */
diff -druN linux-libre-2.6.30-gnu/drivers/mfd/wm8400-core.c linux-libre-2.6.31-gnu/drivers/mfd/wm8400-core.c
--- linux-libre-2.6.30-gnu/drivers/mfd/wm8400-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mfd/wm8400-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -265,7 +265,7 @@
 
 	mutex_init(&wm8400->io_lock);
 
-	wm8400->dev->driver_data = wm8400;
+	dev_set_drvdata(wm8400->dev, wm8400);
 
 	/* Check that this is actually a WM8400 */
 	ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
@@ -460,7 +460,7 @@
 
 	return ret;
 }
-module_init(wm8400_module_init);
+subsys_initcall(wm8400_module_init);
 
 static void __exit wm8400_module_exit(void)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/misc/c2port/core.c linux-libre-2.6.31-gnu/drivers/misc/c2port/core.c
--- linux-libre-2.6.30-gnu/drivers/misc/c2port/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/c2port/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
+#include <linux/kmemcheck.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/idr.h>
@@ -891,6 +892,7 @@
 		return ERR_PTR(-EINVAL);
 
 	c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL);
+	kmemcheck_annotate_bitfield(c2dev, flags);
 	if (unlikely(!c2dev))
 		return ERR_PTR(-ENOMEM);
 
diff -druN linux-libre-2.6.30-gnu/drivers/misc/cb710/core.c linux-libre-2.6.31-gnu/drivers/misc/cb710/core.c
--- linux-libre-2.6.30-gnu/drivers/misc/cb710/core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/misc/cb710/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,357 @@
+/*
+ *  cb710/core.c
+ *
+ *  Copyright by Michał Mirosław, 2008-2009
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/cb710.h>
+
+static DEFINE_IDA(cb710_ida);
+static DEFINE_SPINLOCK(cb710_ida_lock);
+
+void cb710_pci_update_config_reg(struct pci_dev *pdev,
+	int reg, uint32_t mask, uint32_t xor)
+{
+	u32 rval;
+
+	pci_read_config_dword(pdev, reg, &rval);
+	rval = (rval & mask) ^ xor;
+	pci_write_config_dword(pdev, reg, rval);
+}
+EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg);
+
+/* Some magic writes based on Windows driver init code */
+static int __devinit cb710_pci_configure(struct pci_dev *pdev)
+{
+	unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+	struct pci_dev *pdev0 = pci_get_slot(pdev->bus, devfn);
+	u32 val;
+
+	cb710_pci_update_config_reg(pdev, 0x48,
+		~0x000000FF, 0x0000003F);
+
+	pci_read_config_dword(pdev, 0x48, &val);
+	if (val & 0x80000000)
+		return 0;
+
+	if (!pdev0)
+		return -ENODEV;
+
+	if (pdev0->vendor == PCI_VENDOR_ID_ENE
+	    && pdev0->device == PCI_DEVICE_ID_ENE_720) {
+		cb710_pci_update_config_reg(pdev0, 0x8C,
+			~0x00F00000, 0x00100000);
+		cb710_pci_update_config_reg(pdev0, 0xB0,
+			~0x08000000, 0x08000000);
+	}
+
+	cb710_pci_update_config_reg(pdev0, 0x8C,
+		~0x00000F00, 0x00000200);
+	cb710_pci_update_config_reg(pdev0, 0x90,
+		~0x00060000, 0x00040000);
+
+	pci_dev_put(pdev0);
+
+	return 0;
+}
+
+static irqreturn_t cb710_irq_handler(int irq, void *data)
+{
+	struct cb710_chip *chip = data;
+	struct cb710_slot *slot = &chip->slot[0];
+	irqreturn_t handled = IRQ_NONE;
+	unsigned nr;
+
+	spin_lock(&chip->irq_lock); /* incl. smp_rmb() */
+
+	for (nr = chip->slots; nr; ++slot, --nr) {
+		cb710_irq_handler_t handler_func = slot->irq_handler;
+		if (handler_func && handler_func(slot))
+			handled = IRQ_HANDLED;
+	}
+
+	spin_unlock(&chip->irq_lock);
+
+	return handled;
+}
+
+static void cb710_release_slot(struct device *dev)
+{
+#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
+	struct cb710_slot *slot = cb710_pdev_to_slot(to_platform_device(dev));
+	struct cb710_chip *chip = cb710_slot_to_chip(slot);
+
+	/* slot struct can be freed now */
+	atomic_dec(&chip->slot_refs_count);
+#endif
+}
+
+static int __devinit cb710_register_slot(struct cb710_chip *chip,
+	unsigned slot_mask, unsigned io_offset, const char *name)
+{
+	int nr = chip->slots;
+	struct cb710_slot *slot = &chip->slot[nr];
+	int err;
+
+	dev_dbg(cb710_chip_dev(chip),
+		"register: %s.%d; slot %d; mask %d; IO offset: 0x%02X\n",
+		name, chip->platform_id, nr, slot_mask, io_offset);
+
+	/* slot->irq_handler == NULL here; this needs to be
+	 * seen before platform_device_register() */
+	++chip->slots;
+	smp_wmb();
+
+	slot->iobase = chip->iobase + io_offset;
+	slot->pdev.name = name;
+	slot->pdev.id = chip->platform_id;
+	slot->pdev.dev.parent = &chip->pdev->dev;
+	slot->pdev.dev.release = cb710_release_slot;
+
+	err = platform_device_register(&slot->pdev);
+
+#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
+	atomic_inc(&chip->slot_refs_count);
+#endif
+
+	if (err) {
+		/* device_initialize() called from platform_device_register()
+		 * wants this on error path */
+		platform_device_put(&slot->pdev);
+
+		/* slot->irq_handler == NULL here anyway, so no lock needed */
+		--chip->slots;
+		return err;
+	}
+
+	chip->slot_mask |= slot_mask;
+
+	return 0;
+}
+
+static void cb710_unregister_slot(struct cb710_chip *chip,
+	unsigned slot_mask)
+{
+	int nr = chip->slots - 1;
+
+	if (!(chip->slot_mask & slot_mask))
+		return;
+
+	platform_device_unregister(&chip->slot[nr].pdev);
+
+	/* complementary to spin_unlock() in cb710_set_irq_handler() */
+	smp_rmb();
+	BUG_ON(chip->slot[nr].irq_handler != NULL);
+
+	/* slot->irq_handler == NULL here, so no lock needed */
+	--chip->slots;
+	chip->slot_mask &= ~slot_mask;
+}
+
+void cb710_set_irq_handler(struct cb710_slot *slot,
+	cb710_irq_handler_t handler)
+{
+	struct cb710_chip *chip = cb710_slot_to_chip(slot);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->irq_lock, flags);
+	slot->irq_handler = handler;
+	spin_unlock_irqrestore(&chip->irq_lock, flags);
+}
+EXPORT_SYMBOL_GPL(cb710_set_irq_handler);
+
+#ifdef CONFIG_PM
+
+static int cb710_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct cb710_chip *chip = pci_get_drvdata(pdev);
+
+	free_irq(pdev->irq, chip);
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	if (state.event & PM_EVENT_SLEEP)
+		pci_set_power_state(pdev, PCI_D3cold);
+	return 0;
+}
+
+static int cb710_resume(struct pci_dev *pdev)
+{
+	struct cb710_chip *chip = pci_get_drvdata(pdev);
+	int err;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	err = pcim_enable_device(pdev);
+	if (err)
+		return err;
+
+	return devm_request_irq(&pdev->dev, pdev->irq,
+		cb710_irq_handler, IRQF_SHARED, KBUILD_MODNAME, chip);
+}
+
+#endif /* CONFIG_PM */
+
+static int __devinit cb710_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	struct cb710_chip *chip;
+	unsigned long flags;
+	u32 val;
+	int err;
+	int n = 0;
+
+	err = cb710_pci_configure(pdev);
+	if (err)
+		return err;
+
+	/* this is actually magic... */
+	pci_read_config_dword(pdev, 0x48, &val);
+	if (!(val & 0x80000000)) {
+		pci_write_config_dword(pdev, 0x48, val|0x71000000);
+		pci_read_config_dword(pdev, 0x48, &val);
+	}
+
+	dev_dbg(&pdev->dev, "PCI config[0x48] = 0x%08X\n", val);
+	if (!(val & 0x70000000))
+		return -ENODEV;
+	val = (val >> 28) & 7;
+	if (val & CB710_SLOT_MMC)
+		++n;
+	if (val & CB710_SLOT_MS)
+		++n;
+	if (val & CB710_SLOT_SM)
+		++n;
+
+	chip = devm_kzalloc(&pdev->dev,
+		sizeof(*chip) + n * sizeof(*chip->slot), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	err = pcim_enable_device(pdev);
+	if (err)
+		return err;
+
+	err = pcim_iomap_regions(pdev, 0x0001, KBUILD_MODNAME);
+	if (err)
+		return err;
+
+	chip->pdev = pdev;
+	chip->iobase = pcim_iomap_table(pdev)[0];
+
+	pci_set_drvdata(pdev, chip);
+
+	err = devm_request_irq(&pdev->dev, pdev->irq,
+		cb710_irq_handler, IRQF_SHARED, KBUILD_MODNAME, chip);
+	if (err)
+		return err;
+
+	do {
+		if (!ida_pre_get(&cb710_ida, GFP_KERNEL))
+			return -ENOMEM;
+
+		spin_lock_irqsave(&cb710_ida_lock, flags);
+		err = ida_get_new(&cb710_ida, &chip->platform_id);
+		spin_unlock_irqrestore(&cb710_ida_lock, flags);
+
+		if (err && err != -EAGAIN)
+			return err;
+	} while (err);
+
+
+	dev_info(&pdev->dev, "id %d, IO 0x%p, IRQ %d\n",
+		chip->platform_id, chip->iobase, pdev->irq);
+
+	if (val & CB710_SLOT_MMC) {	/* MMC/SD slot */
+		err = cb710_register_slot(chip,
+			CB710_SLOT_MMC, 0x00, "cb710-mmc");
+		if (err)
+			return err;
+	}
+
+	if (val & CB710_SLOT_MS) {	/* MemoryStick slot */
+		err = cb710_register_slot(chip,
+			CB710_SLOT_MS, 0x40, "cb710-ms");
+		if (err)
+			goto unreg_mmc;
+	}
+
+	if (val & CB710_SLOT_SM) {	/* SmartMedia slot */
+		err = cb710_register_slot(chip,
+			CB710_SLOT_SM, 0x60, "cb710-sm");
+		if (err)
+			goto unreg_ms;
+	}
+
+	return 0;
+unreg_ms:
+	cb710_unregister_slot(chip, CB710_SLOT_MS);
+unreg_mmc:
+	cb710_unregister_slot(chip, CB710_SLOT_MMC);
+
+#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
+	BUG_ON(atomic_read(&chip->slot_refs_count) != 0);
+#endif
+	return err;
+}
+
+static void __devexit cb710_remove_one(struct pci_dev *pdev)
+{
+	struct cb710_chip *chip = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	cb710_unregister_slot(chip, CB710_SLOT_SM);
+	cb710_unregister_slot(chip, CB710_SLOT_MS);
+	cb710_unregister_slot(chip, CB710_SLOT_MMC);
+#ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
+	BUG_ON(atomic_read(&chip->slot_refs_count) != 0);
+#endif
+
+	spin_lock_irqsave(&cb710_ida_lock, flags);
+	ida_remove(&cb710_ida, chip->platform_id);
+	spin_unlock_irqrestore(&cb710_ida_lock, flags);
+}
+
+static const struct pci_device_id cb710_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_CB710_FLASH,
+		PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0, }
+};
+
+static struct pci_driver cb710_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = cb710_pci_tbl,
+	.probe = cb710_probe,
+	.remove = __devexit_p(cb710_remove_one),
+#ifdef CONFIG_PM
+	.suspend = cb710_suspend,
+	.resume = cb710_resume,
+#endif
+};
+
+static int __init cb710_init_module(void)
+{
+	return pci_register_driver(&cb710_driver);
+}
+
+static void __exit cb710_cleanup_module(void)
+{
+	pci_unregister_driver(&cb710_driver);
+	ida_destroy(&cb710_ida);
+}
+
+module_init(cb710_init_module);
+module_exit(cb710_cleanup_module);
+
+MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>");
+MODULE_DESCRIPTION("ENE CB710 memory card reader driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, cb710_pci_tbl);
diff -druN linux-libre-2.6.30-gnu/drivers/misc/cb710/debug.c linux-libre-2.6.31-gnu/drivers/misc/cb710/debug.c
--- linux-libre-2.6.30-gnu/drivers/misc/cb710/debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/misc/cb710/debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,119 @@
+/*
+ *  cb710/debug.c
+ *
+ *  Copyright by Michał Mirosław, 2008-2009
+ *
+ * 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.
+ */
+#include <linux/cb710.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define CB710_REG_COUNT		0x80
+
+static const u16 allow[CB710_REG_COUNT/16] = {
+	0xFFF0, 0xFFFF, 0xFFFF, 0xFFFF,
+	0xFFF0, 0xFFFF, 0xFFFF, 0xFFFF,
+};
+static const char *const prefix[ARRAY_SIZE(allow)] = {
+	"MMC", "MMC", "MMC", "MMC",
+	"MS?", "MS?", "SM?", "SM?"
+};
+
+static inline int allow_reg_read(unsigned block, unsigned offset, unsigned bits)
+{
+	unsigned mask = (1 << bits/8) - 1;
+	offset *= bits/8;
+	return ((allow[block] >> offset) & mask) == mask;
+}
+
+#define CB710_READ_REGS_TEMPLATE(t)					\
+static void cb710_read_regs_##t(void __iomem *iobase,			\
+	u##t *reg, unsigned select)					\
+{									\
+	unsigned i, j;							\
+									\
+	for (i = 0; i < ARRAY_SIZE(allow); ++i, reg += 16/(t/8)) {	\
+		if (!(select & (1 << i)))					\
+			continue;					\
+									\
+		for (j = 0; j < 0x10/(t/8); ++j) {			\
+			if (!allow_reg_read(i, j, t))			\
+				continue;				\
+			reg[j] = ioread##t(iobase			\
+				+ (i << 4) + (j * (t/8)));		\
+		}							\
+	}								\
+}
+
+static const char cb710_regf_8[] = "%02X";
+static const char cb710_regf_16[] = "%04X";
+static const char cb710_regf_32[] = "%08X";
+static const char cb710_xes[] = "xxxxxxxx";
+
+#define CB710_DUMP_REGS_TEMPLATE(t)					\
+static void cb710_dump_regs_##t(struct device *dev,			\
+	const u##t *reg, unsigned select)				\
+{									\
+	const char *const xp = &cb710_xes[8 - t/4];			\
+	const char *const format = cb710_regf_##t;			\
+									\
+	char msg[100], *p;						\
+	unsigned i, j;							\
+									\
+	for (i = 0; i < ARRAY_SIZE(allow); ++i, reg += 16/(t/8)) {	\
+		if (!(select & (1 << i)))				\
+			continue;					\
+		p = msg;						\
+		for (j = 0; j < 0x10/(t/8); ++j) {			\
+			*p++ = ' ';					\
+			if (j == 8/(t/8))				\
+				*p++ = ' ';				\
+			if (allow_reg_read(i, j, t))			\
+				p += sprintf(p, format, reg[j]);	\
+			else						\
+				p += sprintf(p, "%s", xp);		\
+		}							\
+		dev_dbg(dev, "%s 0x%02X %s\n", prefix[i], i << 4, msg);	\
+	}								\
+}
+
+#define CB710_READ_AND_DUMP_REGS_TEMPLATE(t)				\
+static void cb710_read_and_dump_regs_##t(struct cb710_chip *chip,	\
+	unsigned select)						\
+{									\
+	u##t regs[CB710_REG_COUNT/sizeof(u##t)];			\
+									\
+	memset(&regs, 0, sizeof(regs));					\
+	cb710_read_regs_##t(chip->iobase, regs, select);		\
+	cb710_dump_regs_##t(cb710_chip_dev(chip), regs, select);	\
+}
+
+#define CB710_REG_ACCESS_TEMPLATES(t)		\
+  CB710_READ_REGS_TEMPLATE(t)			\
+  CB710_DUMP_REGS_TEMPLATE(t)			\
+  CB710_READ_AND_DUMP_REGS_TEMPLATE(t)
+
+CB710_REG_ACCESS_TEMPLATES(8)
+CB710_REG_ACCESS_TEMPLATES(16)
+CB710_REG_ACCESS_TEMPLATES(32)
+
+void cb710_dump_regs(struct cb710_chip *chip, unsigned select)
+{
+	if (!(select & CB710_DUMP_REGS_MASK))
+		select = CB710_DUMP_REGS_ALL;
+	if (!(select & CB710_DUMP_ACCESS_MASK))
+		select |= CB710_DUMP_ACCESS_8;
+
+	if (select & CB710_DUMP_ACCESS_32)
+		cb710_read_and_dump_regs_32(chip, select);
+	if (select & CB710_DUMP_ACCESS_16)
+		cb710_read_and_dump_regs_16(chip, select);
+	if (select & CB710_DUMP_ACCESS_8)
+		cb710_read_and_dump_regs_8(chip, select);
+}
+EXPORT_SYMBOL_GPL(cb710_dump_regs);
+
diff -druN linux-libre-2.6.30-gnu/drivers/misc/cb710/Kconfig linux-libre-2.6.31-gnu/drivers/misc/cb710/Kconfig
--- linux-libre-2.6.30-gnu/drivers/misc/cb710/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/misc/cb710/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,25 @@
+config CB710_CORE
+	tristate "ENE CB710/720 Flash memory card reader support"
+	depends on PCI
+	help
+	  This option enables support for PCI ENE CB710/720 Flash memory card
+	  reader found in some laptops (ie. some versions of HP Compaq nx9500).
+
+	  You will also have to select some flash card format drivers (MMC/SD,
+	  MemoryStick).
+
+	  This driver can also be built as a module. If so, the module
+	  will be called cb710.
+
+config CB710_DEBUG
+	bool "Enable driver debugging"
+	depends on CB710_CORE != n
+	default n
+	help
+	  This is an option for use by developers; most people should
+	  say N here.  This adds a lot of debugging output to dmesg.
+
+config CB710_DEBUG_ASSUMPTIONS
+	bool
+	depends on CB710_CORE != n
+	default y
diff -druN linux-libre-2.6.30-gnu/drivers/misc/cb710/Makefile linux-libre-2.6.31-gnu/drivers/misc/cb710/Makefile
--- linux-libre-2.6.30-gnu/drivers/misc/cb710/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/misc/cb710/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,8 @@
+ifeq ($(CONFIG_CB710_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
+obj-$(CONFIG_CB710_CORE)	+= cb710.o
+
+cb710-y				:= core.o sgbuf2.o
+cb710-$(CONFIG_CB710_DEBUG)	+= debug.o
diff -druN linux-libre-2.6.30-gnu/drivers/misc/cb710/sgbuf2.c linux-libre-2.6.31-gnu/drivers/misc/cb710/sgbuf2.c
--- linux-libre-2.6.30-gnu/drivers/misc/cb710/sgbuf2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/misc/cb710/sgbuf2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,146 @@
+/*
+ *  cb710/sgbuf2.c
+ *
+ *  Copyright by Michał Mirosław, 2008-2009
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cb710.h>
+
+static bool sg_dwiter_next(struct sg_mapping_iter *miter)
+{
+	if (sg_miter_next(miter)) {
+		miter->consumed = 0;
+		return true;
+	} else
+		return false;
+}
+
+static bool sg_dwiter_is_at_end(struct sg_mapping_iter *miter)
+{
+	return miter->length == miter->consumed && !sg_dwiter_next(miter);
+}
+
+static uint32_t sg_dwiter_read_buffer(struct sg_mapping_iter *miter)
+{
+	size_t len, left = 4;
+	uint32_t data;
+	void *addr = &data;
+
+	do {
+		len = min(miter->length - miter->consumed, left);
+		memcpy(addr, miter->addr + miter->consumed, len);
+		miter->consumed += len;
+		left -= len;
+		if (!left)
+			return data;
+		addr += len;
+	} while (sg_dwiter_next(miter));
+
+	memset(addr, 0, left);
+	return data;
+}
+
+static inline bool needs_unaligned_copy(const void *ptr)
+{
+#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
+	return false;
+#else
+	return ((ptr - NULL) & 3) != 0;
+#endif
+}
+
+static bool sg_dwiter_get_next_block(struct sg_mapping_iter *miter, uint32_t **ptr)
+{
+	size_t len;
+
+	if (sg_dwiter_is_at_end(miter))
+		return true;
+
+	len = miter->length - miter->consumed;
+
+	if (likely(len >= 4 && !needs_unaligned_copy(
+			miter->addr + miter->consumed))) {
+		*ptr = miter->addr + miter->consumed;
+		miter->consumed += 4;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * cb710_sg_dwiter_read_next_block() - get next 32-bit word from sg buffer
+ * @miter: sg mapping iterator used for reading
+ *
+ * Description:
+ *   Returns 32-bit word starting at byte pointed to by @miter@
+ *   handling any alignment issues.  Bytes past the buffer's end
+ *   are not accessed (read) but are returned as zeroes.  @miter@
+ *   is advanced by 4 bytes or to the end of buffer whichever is
+ *   closer.
+ *
+ * Context:
+ *   Same requirements as in sg_miter_next().
+ *
+ * Returns:
+ *   32-bit word just read.
+ */
+uint32_t cb710_sg_dwiter_read_next_block(struct sg_mapping_iter *miter)
+{
+	uint32_t *ptr = NULL;
+
+	if (likely(sg_dwiter_get_next_block(miter, &ptr)))
+		return ptr ? *ptr : 0;
+
+	return sg_dwiter_read_buffer(miter);
+}
+EXPORT_SYMBOL_GPL(cb710_sg_dwiter_read_next_block);
+
+static void sg_dwiter_write_slow(struct sg_mapping_iter *miter, uint32_t data)
+{
+	size_t len, left = 4;
+	void *addr = &data;
+
+	do {
+		len = min(miter->length - miter->consumed, left);
+		memcpy(miter->addr, addr, len);
+		miter->consumed += len;
+		left -= len;
+		if (!left)
+			return;
+		addr += len;
+	} while (sg_dwiter_next(miter));
+}
+
+/**
+ * cb710_sg_dwiter_write_next_block() - write next 32-bit word to sg buffer
+ * @miter: sg mapping iterator used for writing
+ *
+ * Description:
+ *   Writes 32-bit word starting at byte pointed to by @miter@
+ *   handling any alignment issues.  Bytes which would be written
+ *   past the buffer's end are silently discarded. @miter@ is
+ *   advanced by 4 bytes or to the end of buffer whichever is closer.
+ *
+ * Context:
+ *   Same requirements as in sg_miter_next().
+ */
+void cb710_sg_dwiter_write_next_block(struct sg_mapping_iter *miter, uint32_t data)
+{
+	uint32_t *ptr = NULL;
+
+	if (likely(sg_dwiter_get_next_block(miter, &ptr))) {
+		if (ptr)
+			*ptr = data;
+		else
+			return;
+	} else
+		sg_dwiter_write_slow(miter, data);
+}
+EXPORT_SYMBOL_GPL(cb710_sg_dwiter_write_next_block);
+
diff -druN linux-libre-2.6.30-gnu/drivers/misc/eeprom/at25.c linux-libre-2.6.31-gnu/drivers/misc/eeprom/at25.c
--- linux-libre-2.6.30-gnu/drivers/misc/eeprom/at25.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/eeprom/at25.c	2009-09-09 18:13:59.000000000 -0400
@@ -173,6 +173,7 @@
 		unsigned	segment;
 		unsigned	offset = (unsigned) off;
 		u8		*cp = bounce + 1;
+		int		sr;
 
 		*cp = AT25_WREN;
 		status = spi_write(at25->spi, cp, 1);
@@ -214,7 +215,6 @@
 		timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);
 		retries = 0;
 		do {
-			int	sr;
 
 			sr = spi_w8r8(at25->spi, AT25_RDSR);
 			if (sr < 0 || (sr & AT25_SR_nRDY)) {
@@ -228,7 +228,7 @@
 				break;
 		} while (retries++ < 3 || time_before_eq(jiffies, timeout));
 
-		if (time_after(jiffies, timeout)) {
+		if ((sr < 0) || (sr & AT25_SR_nRDY)) {
 			dev_err(&at25->spi->dev,
 				"write %d bytes offset %d, "
 				"timeout after %u msecs\n",
diff -druN linux-libre-2.6.30-gnu/drivers/misc/eeprom/Kconfig linux-libre-2.6.31-gnu/drivers/misc/eeprom/Kconfig
--- linux-libre-2.6.30-gnu/drivers/misc/eeprom/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/eeprom/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,20 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called eeprom.
 
+config EEPROM_MAX6875
+	tristate "Maxim MAX6874/5 power supply supervisor"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get read-only support for the user EEPROM of
+	  the Maxim MAX6874/5 EEPROM-programmable, quad power-supply
+	  sequencer/supervisor.
+
+	  All other features of this chip should be accessed via i2c-dev.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called max6875.
+
+
 config EEPROM_93CX6
 	tristate "EEPROM 93CX6 support"
 	help
diff -druN linux-libre-2.6.30-gnu/drivers/misc/eeprom/Makefile linux-libre-2.6.31-gnu/drivers/misc/eeprom/Makefile
--- linux-libre-2.6.30-gnu/drivers/misc/eeprom/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/eeprom/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,5 @@
 obj-$(CONFIG_EEPROM_AT24)	+= at24.o
 obj-$(CONFIG_EEPROM_AT25)	+= at25.o
 obj-$(CONFIG_EEPROM_LEGACY)	+= eeprom.o
+obj-$(CONFIG_EEPROM_MAX6875)	+= max6875.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
diff -druN linux-libre-2.6.30-gnu/drivers/misc/eeprom/max6875.c linux-libre-2.6.31-gnu/drivers/misc/eeprom/max6875.c
--- linux-libre-2.6.30-gnu/drivers/misc/eeprom/max6875.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/misc/eeprom/max6875.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,246 @@
+/*
+    max6875.c - driver for MAX6874/MAX6875
+
+    Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+
+    Based on eeprom.c
+
+    The MAX6875 has a bank of registers and two banks of EEPROM.
+    Address ranges are defined as follows:
+     * 0x0000 - 0x0046 = configuration registers
+     * 0x8000 - 0x8046 = configuration EEPROM
+     * 0x8100 - 0x82FF = user EEPROM
+
+    This driver makes the user EEPROM available for read.
+
+    The registers & config EEPROM should be accessed via i2c-dev.
+
+    The MAX6875 ignores the lowest address bit, so each chip responds to
+    two addresses - 0x50/0x51 and 0x52/0x53.
+
+    Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
+    address, so this driver is destructive if loaded for the wrong EEPROM chip.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; version 2 of the License.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(max6875);
+
+/* The MAX6875 can only read/write 16 bytes at a time */
+#define SLICE_SIZE			16
+#define SLICE_BITS			4
+
+/* USER EEPROM is at addresses 0x8100 - 0x82FF */
+#define USER_EEPROM_BASE		0x8100
+#define USER_EEPROM_SIZE		0x0200
+#define USER_EEPROM_SLICES		32
+
+/* MAX6875 commands */
+#define MAX6875_CMD_BLK_READ		0x84
+
+/* Each client has this additional data */
+struct max6875_data {
+	struct i2c_client	*fake_client;
+	struct mutex		update_lock;
+
+	u32			valid;
+	u8			data[USER_EEPROM_SIZE];
+	unsigned long		last_updated[USER_EEPROM_SLICES];
+};
+
+static void max6875_update_slice(struct i2c_client *client, int slice)
+{
+	struct max6875_data *data = i2c_get_clientdata(client);
+	int i, j, addr;
+	u8 *buf;
+
+	if (slice >= USER_EEPROM_SLICES)
+		return;
+
+	mutex_lock(&data->update_lock);
+
+	buf = &data->data[slice << SLICE_BITS];
+
+	if (!(data->valid & (1 << slice)) ||
+	    time_after(jiffies, data->last_updated[slice])) {
+
+		dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
+
+		data->valid &= ~(1 << slice);
+
+		addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
+
+		/* select the eeprom address */
+		if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
+			dev_err(&client->dev, "address set failed\n");
+			goto exit_up;
+		}
+
+		if (i2c_check_functionality(client->adapter,
+					    I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+			if (i2c_smbus_read_i2c_block_data(client,
+							  MAX6875_CMD_BLK_READ,
+							  SLICE_SIZE,
+							  buf) != SLICE_SIZE) {
+				goto exit_up;
+			}
+		} else {
+			for (i = 0; i < SLICE_SIZE; i++) {
+				j = i2c_smbus_read_byte(client);
+				if (j < 0) {
+					goto exit_up;
+				}
+				buf[i] = j;
+			}
+		}
+		data->last_updated[slice] = jiffies;
+		data->valid |= (1 << slice);
+	}
+exit_up:
+	mutex_unlock(&data->update_lock);
+}
+
+static ssize_t max6875_read(struct kobject *kobj,
+			    struct bin_attribute *bin_attr,
+			    char *buf, loff_t off, size_t count)
+{
+	struct i2c_client *client = kobj_to_i2c_client(kobj);
+	struct max6875_data *data = i2c_get_clientdata(client);
+	int slice, max_slice;
+
+	if (off > USER_EEPROM_SIZE)
+		return 0;
+
+	if (off + count > USER_EEPROM_SIZE)
+		count = USER_EEPROM_SIZE - off;
+
+	/* refresh slices which contain requested bytes */
+	max_slice = (off + count - 1) >> SLICE_BITS;
+	for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
+		max6875_update_slice(client, slice);
+
+	memcpy(buf, &data->data[off], count);
+
+	return count;
+}
+
+static struct bin_attribute user_eeprom_attr = {
+	.attr = {
+		.name = "eeprom",
+		.mode = S_IRUGO,
+	},
+	.size = USER_EEPROM_SIZE,
+	.read = max6875_read,
+};
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max6875_detect(struct i2c_client *client, int kind,
+			  struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+				     | I2C_FUNC_SMBUS_READ_BYTE))
+		return -ENODEV;
+
+	/* Only check even addresses */
+	if (client->addr & 1)
+		return -ENODEV;
+
+	strlcpy(info->type, "max6875", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+static int max6875_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct max6875_data *data;
+	int err;
+
+	if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
+		return -ENOMEM;
+
+	/* A fake client is created on the odd address */
+	data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1);
+	if (!data->fake_client) {
+		err = -ENOMEM;
+		goto exit_kfree;
+	}
+
+	/* Init real i2c_client */
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr);
+	if (err)
+		goto exit_remove_fake;
+
+	return 0;
+
+exit_remove_fake:
+	i2c_unregister_device(data->fake_client);
+exit_kfree:
+	kfree(data);
+	return err;
+}
+
+static int max6875_remove(struct i2c_client *client)
+{
+	struct max6875_data *data = i2c_get_clientdata(client);
+
+	i2c_unregister_device(data->fake_client);
+
+	sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
+	kfree(data);
+
+	return 0;
+}
+
+static const struct i2c_device_id max6875_id[] = {
+	{ "max6875", 0 },
+	{ }
+};
+
+static struct i2c_driver max6875_driver = {
+	.driver = {
+		.name	= "max6875",
+	},
+	.probe		= max6875_probe,
+	.remove		= max6875_remove,
+	.id_table	= max6875_id,
+
+	.detect		= max6875_detect,
+	.address_data	= &addr_data,
+};
+
+static int __init max6875_init(void)
+{
+	return i2c_add_driver(&max6875_driver);
+}
+
+static void __exit max6875_exit(void)
+{
+	i2c_del_driver(&max6875_driver);
+}
+
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("MAX6875 driver");
+MODULE_LICENSE("GPL");
+
+module_init(max6875_init);
+module_exit(max6875_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/misc/Kconfig linux-libre-2.6.31-gnu/drivers/misc/Kconfig
--- linux-libre-2.6.30-gnu/drivers/misc/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -235,5 +235,6 @@
 
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
+source "drivers/misc/cb710/Kconfig"
 
 endif # MISC_DEVICES
diff -druN linux-libre-2.6.30-gnu/drivers/misc/Makefile linux-libre-2.6.31-gnu/drivers/misc/Makefile
--- linux-libre-2.6.30-gnu/drivers/misc/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -21,3 +21,4 @@
 obj-$(CONFIG_ISL29003)		+= isl29003.o
 obj-$(CONFIG_C2PORT)		+= c2port/
 obj-y				+= eeprom/
+obj-y				+= cb710/
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grufault.c linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grufault.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grufault.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grufault.c	2009-09-09 18:13:59.000000000 -0400
@@ -166,7 +166,8 @@
  * the GRU, atomic operations must be used to clear bits.
  */
 static void get_clear_fault_map(struct gru_state *gru,
-				struct gru_tlb_fault_map *map)
+				struct gru_tlb_fault_map *imap,
+				struct gru_tlb_fault_map *dmap)
 {
 	unsigned long i, k;
 	struct gru_tlb_fault_map *tfm;
@@ -177,7 +178,11 @@
 		k = tfm->fault_bits[i];
 		if (k)
 			k = xchg(&tfm->fault_bits[i], 0UL);
-		map->fault_bits[i] = k;
+		imap->fault_bits[i] = k;
+		k = tfm->done_bits[i];
+		if (k)
+			k = xchg(&tfm->done_bits[i], 0UL);
+		dmap->fault_bits[i] = k;
 	}
 
 	/*
@@ -334,6 +339,12 @@
 	 * Might be a hardware race OR a stupid user. Ignore FMM because FMM
 	 * is a transient state.
 	 */
+	if (tfh->status != TFHSTATUS_EXCEPTION) {
+		gru_flush_cache(tfh);
+		if (tfh->status != TFHSTATUS_EXCEPTION)
+			goto failnoexception;
+		STAT(tfh_stale_on_fault);
+	}
 	if (tfh->state == TFHSTATE_IDLE)
 		goto failidle;
 	if (tfh->state == TFHSTATE_MISS_FMM && cb)
@@ -401,8 +412,17 @@
 	gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state);
 	return 0;
 
+failnoexception:
+	/* TFH status did not show exception pending */
+	gru_flush_cache(tfh);
+	if (cb)
+		gru_flush_cache(cb);
+	STAT(tlb_dropin_fail_no_exception);
+	gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n", tfh, tfh->status, tfh->state);
+	return 0;
+
 failidle:
-	/* TFH was idle  - no miss pending */
+	/* TFH state was idle  - no miss pending */
 	gru_flush_cache(tfh);
 	if (cb)
 		gru_flush_cache(cb);
@@ -438,7 +458,7 @@
 irqreturn_t gru_intr(int irq, void *dev_id)
 {
 	struct gru_state *gru;
-	struct gru_tlb_fault_map map;
+	struct gru_tlb_fault_map imap, dmap;
 	struct gru_thread_state *gts;
 	struct gru_tlb_fault_handle *tfh = NULL;
 	int cbrnum, ctxnum;
@@ -451,11 +471,15 @@
 			raw_smp_processor_id(), irq);
 		return IRQ_NONE;
 	}
-	get_clear_fault_map(gru, &map);
-	gru_dbg(grudev, "irq %d, gru %x, map 0x%lx\n", irq, gru->gs_gid,
-		map.fault_bits[0]);
+	get_clear_fault_map(gru, &imap, &dmap);
 
-	for_each_cbr_in_tfm(cbrnum, map.fault_bits) {
+	for_each_cbr_in_tfm(cbrnum, dmap.fault_bits) {
+		complete(gru->gs_blade->bs_async_wq);
+		gru_dbg(grudev, "gid %d, cbr_done %d, done %d\n",
+			gru->gs_gid, cbrnum, gru->gs_blade->bs_async_wq->done);
+	}
+
+	for_each_cbr_in_tfm(cbrnum, imap.fault_bits) {
 		tfh = get_tfh_by_index(gru, cbrnum);
 		prefetchw(tfh);	/* Helps on hdw, required for emulator */
 
@@ -472,7 +496,9 @@
 		 * This is running in interrupt context. Trylock the mmap_sem.
 		 * If it fails, retry the fault in user context.
 		 */
-		if (down_read_trylock(&gts->ts_mm->mmap_sem)) {
+		if (!gts->ts_force_cch_reload &&
+					down_read_trylock(&gts->ts_mm->mmap_sem)) {
+			gts->ustats.fmm_tlbdropin++;
 			gru_try_dropin(gts, tfh, NULL);
 			up_read(&gts->ts_mm->mmap_sem);
 		} else {
@@ -491,6 +517,7 @@
 	struct gru_mm_struct *gms = gts->ts_gms;
 	int ret;
 
+	gts->ustats.upm_tlbdropin++;
 	while (1) {
 		wait_event(gms->ms_wait_queue,
 			   atomic_read(&gms->ms_range_active) == 0);
@@ -546,8 +573,8 @@
 	 * CCH may contain stale data if ts_force_cch_reload is set.
 	 */
 	if (gts->ts_gru && gts->ts_force_cch_reload) {
-		gru_update_cch(gts, 0);
 		gts->ts_force_cch_reload = 0;
+		gru_update_cch(gts, 0);
 	}
 
 	ret = -EAGAIN;
@@ -589,20 +616,26 @@
 	} else if (gts->ts_gru) {
 		cbrnum = thread_cbr_number(gts, ucbnum);
 		cbe = get_cbe_by_index(gts->ts_gru, cbrnum);
-		prefetchw(cbe);/* Harmless on hardware, required for emulator */
+		gru_flush_cache(cbe);	/* CBE not coherent */
 		excdet.opc = cbe->opccpy;
 		excdet.exopc = cbe->exopccpy;
 		excdet.ecause = cbe->ecause;
 		excdet.exceptdet0 = cbe->idef1upd;
 		excdet.exceptdet1 = cbe->idef3upd;
+		excdet.cbrstate = cbe->cbrstate;
+		excdet.cbrexecstatus = cbe->cbrexecstatus;
+		gru_flush_cache(cbe);
 		ret = 0;
 	} else {
 		ret = -EAGAIN;
 	}
 	gru_unlock_gts(gts);
 
-	gru_dbg(grudev, "address 0x%lx, ecause 0x%x\n", excdet.cb,
-		excdet.ecause);
+	gru_dbg(grudev,
+		"cb 0x%lx, op %d, exopc %d, cbrstate %d, cbrexecstatus 0x%x, ecause 0x%x, "
+		"exdet0 0x%lx, exdet1 0x%x\n",
+		excdet.cb, excdet.opc, excdet.exopc, excdet.cbrstate, excdet.cbrexecstatus,
+		excdet.ecause, excdet.exceptdet0, excdet.exceptdet1);
 	if (!ret && copy_to_user((void __user *)arg, &excdet, sizeof(excdet)))
 		ret = -EFAULT;
 	return ret;
@@ -627,7 +660,7 @@
 			if (gts && mutex_trylock(&gts->ts_ctxlock)) {
 				spin_unlock(&gru->gs_lock);
 				gru_unload_context(gts, 1);
-				gru_unlock_gts(gts);
+				mutex_unlock(&gts->ts_ctxlock);
 				spin_lock(&gru->gs_lock);
 			}
 		}
@@ -669,6 +702,7 @@
 {
 	struct gru_thread_state *gts;
 	struct gru_flush_tlb_req req;
+	struct gru_mm_struct *gms;
 
 	STAT(user_flush_tlb);
 	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
@@ -681,8 +715,34 @@
 	if (!gts)
 		return -EINVAL;
 
-	gru_flush_tlb_range(gts->ts_gms, req.vaddr, req.len);
+	gms = gts->ts_gms;
 	gru_unlock_gts(gts);
+	gru_flush_tlb_range(gms, req.vaddr, req.len);
+
+	return 0;
+}
+
+/*
+ * Fetch GSEG statisticss
+ */
+long gru_get_gseg_statistics(unsigned long arg)
+{
+	struct gru_thread_state *gts;
+	struct gru_get_gseg_statistics_req req;
+
+	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
+		return -EFAULT;
+
+	gts = gru_find_lock_gts(req.gseg);
+	if (gts) {
+		memcpy(&req.stats, &gts->ustats, sizeof(gts->ustats));
+		gru_unlock_gts(gts);
+	} else {
+		memset(&req.stats, 0, sizeof(gts->ustats));
+	}
+
+	if (copy_to_user((void __user *)arg, &req, sizeof(req)))
+		return -EFAULT;
 
 	return 0;
 }
@@ -691,18 +751,34 @@
  * Register the current task as the user of the GSEG slice.
  * Needed for TLB fault interrupt targeting.
  */
-int gru_set_task_slice(long address)
+int gru_set_context_option(unsigned long arg)
 {
 	struct gru_thread_state *gts;
+	struct gru_set_context_option_req req;
+	int ret = 0;
 
-	STAT(set_task_slice);
-	gru_dbg(grudev, "address 0x%lx\n", address);
-	gts = gru_alloc_locked_gts(address);
+	STAT(set_context_option);
+	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
+		return -EFAULT;
+	gru_dbg(grudev, "op %d, gseg 0x%lx, value1 0x%lx\n", req.op, req.gseg, req.val1);
+
+	gts = gru_alloc_locked_gts(req.gseg);
 	if (!gts)
 		return -EINVAL;
 
-	gts->ts_tgid_owner = current->tgid;
+	switch (req.op) {
+	case sco_gseg_owner:
+ 		/* Register the current task as the GSEG owner */
+		gts->ts_tgid_owner = current->tgid;
+		break;
+	case sco_cch_req_slice:
+ 		/* Set the CCH slice option */
+		gts->ts_cch_req_slice = req.val1 & 3;
+		break;
+	default:
+		ret = -EINVAL;
+	}
 	gru_unlock_gts(gts);
 
-	return 0;
+	return ret;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grufile.c linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grufile.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grufile.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grufile.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/io.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/miscdevice.h>
@@ -46,6 +45,7 @@
 
 struct gru_blade_state *gru_base[GRU_MAX_BLADES] __read_mostly;
 unsigned long gru_start_paddr __read_mostly;
+void *gru_start_vaddr __read_mostly;
 unsigned long gru_end_paddr __read_mostly;
 unsigned int gru_max_gids __read_mostly;
 struct gru_stats_s gru_stats;
@@ -135,11 +135,9 @@
 	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
 		return -EFAULT;
 
-	if (req.data_segment_bytes == 0 ||
-				req.data_segment_bytes > max_user_dsr_bytes)
+	if (req.data_segment_bytes > max_user_dsr_bytes)
 		return -EINVAL;
-	if (!req.control_blocks || !req.maximum_thread_count ||
-				req.control_blocks > max_user_cbrs)
+	if (req.control_blocks > max_user_cbrs || !req.maximum_thread_count)
 		return -EINVAL;
 
 	if (!(req.options & GRU_OPT_MISS_MASK))
@@ -184,41 +182,6 @@
 }
 
 /*
- * Get GRU chiplet status
- */
-static long gru_get_chiplet_status(unsigned long arg)
-{
-	struct gru_state *gru;
-	struct gru_chiplet_info info;
-
-	if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
-		return -EFAULT;
-
-	if (info.node == -1)
-		info.node = numa_node_id();
-	if (info.node >= num_possible_nodes() ||
-			info.chiplet >= GRU_CHIPLETS_PER_HUB ||
-			info.node < 0 || info.chiplet < 0)
-		return -EINVAL;
-
-	info.blade = uv_node_to_blade_id(info.node);
-	gru = get_gru(info.blade, info.chiplet);
-
-	info.total_dsr_bytes = GRU_NUM_DSR_BYTES;
-	info.total_cbr = GRU_NUM_CB;
-	info.total_user_dsr_bytes = GRU_NUM_DSR_BYTES -
-		gru->gs_reserved_dsr_bytes;
-	info.total_user_cbr = GRU_NUM_CB - gru->gs_reserved_cbrs;
-	info.free_user_dsr_bytes = hweight64(gru->gs_dsr_map) *
-			GRU_DSR_AU_BYTES;
-	info.free_user_cbr = hweight64(gru->gs_cbr_map) * GRU_CBR_AU_SIZE;
-
-	if (copy_to_user((void __user *)arg, &info, sizeof(info)))
-		return -EFAULT;
-	return 0;
-}
-
-/*
  * gru_file_unlocked_ioctl
  *
  * Called to update file attributes via IOCTL calls.
@@ -234,8 +197,8 @@
 	case GRU_CREATE_CONTEXT:
 		err = gru_create_new_context(arg);
 		break;
-	case GRU_SET_TASK_SLICE:
-		err = gru_set_task_slice(arg);
+	case GRU_SET_CONTEXT_OPTION:
+		err = gru_set_context_option(arg);
 		break;
 	case GRU_USER_GET_EXCEPTION_DETAIL:
 		err = gru_get_exception_detail(arg);
@@ -243,18 +206,24 @@
 	case GRU_USER_UNLOAD_CONTEXT:
 		err = gru_user_unload_context(arg);
 		break;
-	case GRU_GET_CHIPLET_STATUS:
-		err = gru_get_chiplet_status(arg);
-		break;
 	case GRU_USER_FLUSH_TLB:
 		err = gru_user_flush_tlb(arg);
 		break;
 	case GRU_USER_CALL_OS:
 		err = gru_handle_user_call_os(arg);
 		break;
+	case GRU_GET_GSEG_STATISTICS:
+		err = gru_get_gseg_statistics(arg);
+		break;
+	case GRU_KTEST:
+		err = gru_ktest(arg);
+		break;
 	case GRU_GET_CONFIG_INFO:
 		err = gru_get_config_info(arg);
 		break;
+	case GRU_DUMP_CHIPLET_STATE:
+		err = gru_dump_chiplet_request(arg);
+		break;
 	}
 	return err;
 }
@@ -282,7 +251,6 @@
 	gru_dbg(grudev, "bid %d, nid %d, gid %d, vaddr %p (0x%lx)\n",
 		bid, nid, gru->gs_gid, gru->gs_gru_base_vaddr,
 		gru->gs_gru_base_paddr);
-	gru_kservices_init(gru);
 }
 
 static int gru_init_tables(unsigned long gru_base_paddr, void *gru_base_vaddr)
@@ -302,13 +270,14 @@
 		pnode = uv_node_to_pnode(nid);
 		if (bid < 0 || gru_base[bid])
 			continue;
-		page = alloc_pages_node(nid, GFP_KERNEL, order);
+		page = alloc_pages_exact_node(nid, GFP_KERNEL, order);
 		if (!page)
 			goto fail;
 		gru_base[bid] = page_address(page);
 		memset(gru_base[bid], 0, sizeof(struct gru_blade_state));
 		gru_base[bid]->bs_lru_gru = &gru_base[bid]->bs_grus[0];
 		spin_lock_init(&gru_base[bid]->bs_lock);
+		init_rwsem(&gru_base[bid]->bs_kgts_sema);
 
 		dsrbytes = 0;
 		cbrs = 0;
@@ -372,7 +341,6 @@
 {
 	int ret, irq, chip;
 	char id[10];
-	void *gru_start_vaddr;
 
 	if (!is_uv_system())
 		return 0;
@@ -422,6 +390,7 @@
 		printk(KERN_ERR "%s: init tables failed\n", GRU_DRIVER_ID_STR);
 		goto exit3;
 	}
+	gru_kservices_init();
 
 	printk(KERN_INFO "%s: v%s\n", GRU_DRIVER_ID_STR,
 	       GRU_DRIVER_VERSION_STR);
@@ -440,7 +409,7 @@
 
 static void __exit gru_exit(void)
 {
-	int i, bid, gid;
+	int i, bid;
 	int order = get_order(sizeof(struct gru_state) *
 			      GRU_CHIPLETS_PER_BLADE);
 
@@ -449,10 +418,7 @@
 
 	for (i = 0; i < GRU_CHIPLETS_PER_BLADE; i++)
 		free_irq(IRQ_GRU + i, NULL);
-
-	foreach_gid(gid)
-		gru_kservices_exit(GID_TO_GRU(gid));
-
+	gru_kservices_exit();
 	for (bid = 0; bid < GRU_MAX_BLADES; bid++)
 		free_pages((unsigned long)gru_base[bid], order);
 
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gruhandles.c linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gruhandles.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gruhandles.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gruhandles.c	2009-09-09 18:13:59.000000000 -0400
@@ -57,7 +57,7 @@
 static int wait_instruction_complete(void *h, enum mcs_op opc)
 {
 	int status;
-	cycles_t start_time = get_cycles();
+	unsigned long start_time = get_cycles();
 
 	while (1) {
 		cpu_relax();
@@ -65,25 +65,16 @@
 		if (status != CCHSTATUS_ACTIVE)
 			break;
 		if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time))
-			panic("GRU %p is malfunctioning\n", h);
+			panic("GRU %p is malfunctioning: start %ld, end %ld\n",
+			      h, start_time, (unsigned long)get_cycles());
 	}
 	if (gru_options & OPT_STATS)
 		update_mcs_stats(opc, get_cycles() - start_time);
 	return status;
 }
 
-int cch_allocate(struct gru_context_configuration_handle *cch,
-		int asidval, int sizeavail, unsigned long cbrmap,
-		unsigned long dsrmap)
+int cch_allocate(struct gru_context_configuration_handle *cch)
 {
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		cch->asid[i] = (asidval++);
-		cch->sizeavail[i] = sizeavail;
-	}
-	cch->dsr_allocation_map = dsrmap;
-	cch->cbr_allocation_map = cbrmap;
 	cch->opc = CCHOP_ALLOCATE;
 	start_instruction(cch);
 	return wait_instruction_complete(cch, cchop_allocate);
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gruhandles.h linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gruhandles.h
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gruhandles.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gruhandles.h	2009-09-09 18:13:59.000000000 -0400
@@ -39,7 +39,6 @@
 #define GRU_NUM_CBE		128
 #define GRU_NUM_TFH		128
 #define GRU_NUM_CCH		16
-#define GRU_NUM_GSH		1
 
 /* Maximum resource counts that can be reserved by user programs */
 #define GRU_NUM_USER_CBR	GRU_NUM_CBE
@@ -56,7 +55,6 @@
 #define GRU_CBE_BASE		(GRU_MCS_BASE + 0x10000)
 #define GRU_TFH_BASE		(GRU_MCS_BASE + 0x18000)
 #define GRU_CCH_BASE		(GRU_MCS_BASE + 0x20000)
-#define GRU_GSH_BASE		(GRU_MCS_BASE + 0x30000)
 
 /* User gseg constants */
 #define GRU_GSEG_STRIDE		(4 * 1024 * 1024)
@@ -251,15 +249,15 @@
 	unsigned int fill1:9;
 
 	unsigned int status:2;
-	unsigned int fill2:1;
-	unsigned int color:1;
+	unsigned int fill2:2;
 	unsigned int state:3;
 	unsigned int fill3:1;
 
-	unsigned int cause:7;		/* DW 0 - high 32 */
+	unsigned int cause:6;
+	unsigned int cb_int:1;
 	unsigned int fill4:1;
 
-	unsigned int indexway:12;
+	unsigned int indexway:12;	/* DW 0 - high 32 */
 	unsigned int fill5:4;
 
 	unsigned int ctxnum:4;
@@ -457,21 +455,7 @@
 	CBRSTATE_BUSY_INTERRUPT,
 };
 
-/* CBE cbrexecstatus bits */
-#define CBR_EXS_ABORT_OCC_BIT			0
-#define CBR_EXS_INT_OCC_BIT			1
-#define CBR_EXS_PENDING_BIT			2
-#define CBR_EXS_QUEUED_BIT			3
-#define CBR_EXS_TLBHW_BIT			4
-#define CBR_EXS_EXCEPTION_BIT			5
-
-#define CBR_EXS_ABORT_OCC			(1 << CBR_EXS_ABORT_OCC_BIT)
-#define CBR_EXS_INT_OCC				(1 << CBR_EXS_INT_OCC_BIT)
-#define CBR_EXS_PENDING				(1 << CBR_EXS_PENDING_BIT)
-#define CBR_EXS_QUEUED				(1 << CBR_EXS_QUEUED_BIT)
-#define CBR_EXS_TLBHW				(1 << CBR_EXS_TLBHW_BIT)
-#define CBR_EXS_EXCEPTION			(1 << CBR_EXS_EXCEPTION_BIT)
-
+/* CBE cbrexecstatus bits  - defined in gru_instructions.h*/
 /* CBE ecause bits  - defined in gru_instructions.h */
 
 /*
@@ -495,9 +479,7 @@
 /* minimum TLB purge count to ensure a full purge */
 #define GRUMAXINVAL		1024UL
 
-int cch_allocate(struct gru_context_configuration_handle *cch,
-       int asidval, int sizeavail, unsigned long cbrmap, unsigned long dsrmap);
-
+int cch_allocate(struct gru_context_configuration_handle *cch);
 int cch_start(struct gru_context_configuration_handle *cch);
 int cch_interrupt(struct gru_context_configuration_handle *cch);
 int cch_deallocate(struct gru_context_configuration_handle *cch);
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gru_instructions.h linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gru_instructions.h
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gru_instructions.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gru_instructions.h	2009-09-09 18:13:59.000000000 -0400
@@ -81,6 +81,8 @@
 	int		exopc;
 	long		exceptdet0;
 	int		exceptdet1;
+	int		cbrstate;
+	int		cbrexecstatus;
 };
 
 /*
@@ -107,7 +109,8 @@
     unsigned char		reserved2: 2;
     unsigned char		istatus:   2;
     unsigned char		isubstatus:4;
-    unsigned char		reserved3: 2;
+    unsigned char		reserved3: 1;
+    unsigned char		tlb_fault_color: 1;
     /* DW 1 */
     unsigned long		idef4;		/* 42 bits: TRi1, BufSize */
     /* DW 2-6 */
@@ -250,17 +253,37 @@
 #define CBE_CAUSE_HA_RESPONSE_FATAL		(1 << 13)
 #define CBE_CAUSE_HA_RESPONSE_NON_FATAL		(1 << 14)
 #define CBE_CAUSE_ADDRESS_SPACE_DECODE_ERROR	(1 << 15)
-#define CBE_CAUSE_RESPONSE_DATA_ERROR		(1 << 16)
-#define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR	(1 << 17)
+#define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR	(1 << 16)
+#define CBE_CAUSE_RA_RESPONSE_DATA_ERROR	(1 << 17)
+#define CBE_CAUSE_HA_RESPONSE_DATA_ERROR	(1 << 18)
+
+/* CBE cbrexecstatus bits */
+#define CBR_EXS_ABORT_OCC_BIT			0
+#define CBR_EXS_INT_OCC_BIT			1
+#define CBR_EXS_PENDING_BIT			2
+#define CBR_EXS_QUEUED_BIT			3
+#define CBR_EXS_TLB_INVAL_BIT			4
+#define CBR_EXS_EXCEPTION_BIT			5
+
+#define CBR_EXS_ABORT_OCC			(1 << CBR_EXS_ABORT_OCC_BIT)
+#define CBR_EXS_INT_OCC				(1 << CBR_EXS_INT_OCC_BIT)
+#define CBR_EXS_PENDING				(1 << CBR_EXS_PENDING_BIT)
+#define CBR_EXS_QUEUED				(1 << CBR_EXS_QUEUED_BIT)
+#define CBR_TLB_INVAL				(1 << CBR_EXS_TLB_INVAL_BIT)
+#define CBR_EXS_EXCEPTION			(1 << CBR_EXS_EXCEPTION_BIT)
 
 /*
  * Exceptions are retried for the following cases. If any OTHER bits are set
  * in ecause, the exception is not retryable.
  */
-#define EXCEPTION_RETRY_BITS (CBE_CAUSE_RESPONSE_DATA_ERROR |		\
-			      CBE_CAUSE_RA_REQUEST_TIMEOUT |		\
+#define EXCEPTION_RETRY_BITS (CBE_CAUSE_EXECUTION_HW_ERROR |		\
 			      CBE_CAUSE_TLBHW_ERROR |			\
-			      CBE_CAUSE_HA_REQUEST_TIMEOUT)
+			      CBE_CAUSE_RA_REQUEST_TIMEOUT |		\
+			      CBE_CAUSE_RA_RESPONSE_NON_FATAL |		\
+			      CBE_CAUSE_HA_RESPONSE_NON_FATAL |		\
+			      CBE_CAUSE_RA_RESPONSE_DATA_ERROR |	\
+			      CBE_CAUSE_HA_RESPONSE_DATA_ERROR		\
+			      )
 
 /* Message queue head structure */
 union gru_mesqhead {
@@ -600,9 +623,11 @@
 	return cbs->isubstatus;
 }
 
-/* Check the status of a CB. If the CB is in UPM mode, call the
- * OS to handle the UPM status.
- * Returns the CB status field value (0 for normal completion)
+/*
+ * User interface to check an instruction status. UPM and exceptions
+ * are handled automatically. However, this function does NOT wait
+ * for an active instruction to complete.
+ *
  */
 static inline int gru_check_status(void *cb)
 {
@@ -610,34 +635,31 @@
 	int ret;
 
 	ret = cbs->istatus;
-	if (ret == CBS_CALL_OS)
+	if (ret != CBS_ACTIVE)
 		ret = gru_check_status_proc(cb);
 	return ret;
 }
 
-/* Wait for CB to complete.
- * Returns the CB status field value (0 for normal completion)
+/*
+ * User interface (via inline function) to wait for an instruction
+ * to complete. Completion status (IDLE or EXCEPTION is returned
+ * to the user. Exception due to hardware errors are automatically
+ * retried before returning an exception.
+ *
  */
 static inline int gru_wait(void *cb)
 {
-	struct gru_control_block_status *cbs = (void *)cb;
-	int ret = cbs->istatus;
-
-	if (ret != CBS_IDLE)
-		ret = gru_wait_proc(cb);
-	return ret;
+	return gru_wait_proc(cb);
 }
 
-/* Wait for CB to complete. Aborts program if error. (Note: error does NOT
+/*
+ * Wait for CB to complete. Aborts program if error. (Note: error does NOT
  * mean TLB mis - only fatal errors such as memory parity error or user
  * bugs will cause termination.
  */
 static inline void gru_wait_abort(void *cb)
 {
-	struct gru_control_block_status *cbs = (void *)cb;
-
-	if (cbs->istatus != CBS_IDLE)
-		gru_wait_abort_proc(cb);
+	gru_wait_abort_proc(cb);
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grukdump.c linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grukdump.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grukdump.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grukdump.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,232 @@
+/*
+ * SN Platform GRU Driver
+ *
+ *            Dump GRU State
+ *
+ *  Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ *  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/mm.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <asm/uv/uv_hub.h>
+#include "gru.h"
+#include "grutables.h"
+#include "gruhandles.h"
+#include "grulib.h"
+
+#define CCH_LOCK_ATTEMPTS	10
+
+static int gru_user_copy_handle(void __user **dp, void *s)
+{
+	if (copy_to_user(*dp, s, GRU_HANDLE_BYTES))
+		return -1;
+	*dp += GRU_HANDLE_BYTES;
+	return 0;
+}
+
+static int gru_dump_context_data(void *grubase,
+			struct gru_context_configuration_handle *cch,
+			void __user *ubuf, int ctxnum, int dsrcnt)
+{
+	void *cb, *cbe, *tfh, *gseg;
+	int i, scr;
+
+	gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
+	cb = gseg + GRU_CB_BASE;
+	cbe = grubase + GRU_CBE_BASE;
+	tfh = grubase + GRU_TFH_BASE;
+
+	for_each_cbr_in_allocation_map(i, &cch->cbr_allocation_map, scr) {
+		if (gru_user_copy_handle(&ubuf, cb))
+			goto fail;
+		if (gru_user_copy_handle(&ubuf, tfh + i * GRU_HANDLE_STRIDE))
+			goto fail;
+		if (gru_user_copy_handle(&ubuf, cbe + i * GRU_HANDLE_STRIDE))
+			goto fail;
+		cb += GRU_HANDLE_STRIDE;
+	}
+	if (dsrcnt)
+		memcpy(ubuf, gseg + GRU_DS_BASE, dsrcnt * GRU_HANDLE_STRIDE);
+	return 0;
+
+fail:
+	return -EFAULT;
+}
+
+static int gru_dump_tfm(struct gru_state *gru,
+		void __user *ubuf, void __user *ubufend)
+{
+	struct gru_tlb_fault_map *tfm;
+	int i, ret, bytes;
+
+	bytes = GRU_NUM_TFM * GRU_CACHE_LINE_BYTES;
+	if (bytes > ubufend - ubuf)
+		ret = -EFBIG;
+
+	for (i = 0; i < GRU_NUM_TFM; i++) {
+		tfm = get_tfm(gru->gs_gru_base_vaddr, i);
+		if (gru_user_copy_handle(&ubuf, tfm))
+			goto fail;
+	}
+	return GRU_NUM_TFM * GRU_CACHE_LINE_BYTES;
+
+fail:
+	return -EFAULT;
+}
+
+static int gru_dump_tgh(struct gru_state *gru,
+		void __user *ubuf, void __user *ubufend)
+{
+	struct gru_tlb_global_handle *tgh;
+	int i, ret, bytes;
+
+	bytes = GRU_NUM_TGH * GRU_CACHE_LINE_BYTES;
+	if (bytes > ubufend - ubuf)
+		ret = -EFBIG;
+
+	for (i = 0; i < GRU_NUM_TGH; i++) {
+		tgh = get_tgh(gru->gs_gru_base_vaddr, i);
+		if (gru_user_copy_handle(&ubuf, tgh))
+			goto fail;
+	}
+	return GRU_NUM_TGH * GRU_CACHE_LINE_BYTES;
+
+fail:
+	return -EFAULT;
+}
+
+static int gru_dump_context(struct gru_state *gru, int ctxnum,
+		void __user *ubuf, void __user *ubufend, char data_opt,
+		char lock_cch)
+{
+	struct gru_dump_context_header hdr;
+	struct gru_dump_context_header __user *uhdr = ubuf;
+	struct gru_context_configuration_handle *cch, *ubufcch;
+	struct gru_thread_state *gts;
+	int try, cch_locked, cbrcnt = 0, dsrcnt = 0, bytes = 0, ret = 0;
+	void *grubase;
+
+	memset(&hdr, 0, sizeof(hdr));
+	grubase = gru->gs_gru_base_vaddr;
+	cch = get_cch(grubase, ctxnum);
+	for (try = 0; try < CCH_LOCK_ATTEMPTS; try++) {
+		cch_locked =  trylock_cch_handle(cch);
+		if (cch_locked)
+			break;
+		msleep(1);
+	}
+
+	ubuf += sizeof(hdr);
+	ubufcch = ubuf;
+	if (gru_user_copy_handle(&ubuf, cch))
+		goto fail;
+	if (cch_locked)
+		ubufcch->delresp = 0;
+	bytes = sizeof(hdr) + GRU_CACHE_LINE_BYTES;
+
+	if (cch_locked || !lock_cch) {
+		gts = gru->gs_gts[ctxnum];
+		if (gts && gts->ts_vma) {
+			hdr.pid = gts->ts_tgid_owner;
+			hdr.vaddr = gts->ts_vma->vm_start;
+		}
+		if (cch->state != CCHSTATE_INACTIVE) {
+			cbrcnt = hweight64(cch->cbr_allocation_map) *
+						GRU_CBR_AU_SIZE;
+			dsrcnt = data_opt ? hweight32(cch->dsr_allocation_map) *
+						GRU_DSR_AU_CL : 0;
+		}
+		bytes += (3 * cbrcnt + dsrcnt) * GRU_CACHE_LINE_BYTES;
+		if (bytes > ubufend - ubuf)
+			ret = -EFBIG;
+		else
+			ret = gru_dump_context_data(grubase, cch, ubuf, ctxnum,
+							dsrcnt);
+
+	}
+	if (cch_locked)
+		unlock_cch_handle(cch);
+	if (ret)
+		return ret;
+
+	hdr.magic = GRU_DUMP_MAGIC;
+	hdr.gid = gru->gs_gid;
+	hdr.ctxnum = ctxnum;
+	hdr.cbrcnt = cbrcnt;
+	hdr.dsrcnt = dsrcnt;
+	hdr.cch_locked = cch_locked;
+	if (!ret && copy_to_user((void __user *)uhdr, &hdr, sizeof(hdr)))
+		ret = -EFAULT;
+
+	return ret ? ret : bytes;
+
+fail:
+	unlock_cch_handle(cch);
+	return -EFAULT;
+}
+
+int gru_dump_chiplet_request(unsigned long arg)
+{
+	struct gru_state *gru;
+	struct gru_dump_chiplet_state_req req;
+	void __user *ubuf;
+	void __user *ubufend;
+	int ctxnum, ret, cnt = 0;
+
+	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
+		return -EFAULT;
+
+	/* Currently, only dump by gid is implemented */
+	if (req.gid >= gru_max_gids || req.gid < 0)
+		return -EINVAL;
+
+	gru = GID_TO_GRU(req.gid);
+	ubuf = req.buf;
+	ubufend = req.buf + req.buflen;
+
+	ret = gru_dump_tfm(gru, ubuf, ubufend);
+	if (ret < 0)
+		goto fail;
+	ubuf += ret;
+
+	ret = gru_dump_tgh(gru, ubuf, ubufend);
+	if (ret < 0)
+		goto fail;
+	ubuf += ret;
+
+	for (ctxnum = 0; ctxnum < GRU_NUM_CCH; ctxnum++) {
+		if (req.ctxnum == ctxnum || req.ctxnum < 0) {
+			ret = gru_dump_context(gru, ctxnum, ubuf, ubufend,
+						req.data_opt, req.lock_cch);
+			if (ret < 0)
+				goto fail;
+			ubuf += ret;
+			cnt++;
+		}
+	}
+
+	if (copy_to_user((void __user *)arg, &req, sizeof(req)))
+		return -EFAULT;
+	return cnt;
+
+fail:
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grukservices.c linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grukservices.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grukservices.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grukservices.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,13 +24,13 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/miscdevice.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
+#include <linux/delay.h>
 #include "gru.h"
 #include "grulib.h"
 #include "grutables.h"
@@ -45,18 +45,66 @@
  * resources. This will likely be replaced when we better understand the
  * kernel/user requirements.
  *
- * At boot time, the kernel permanently reserves a fixed number of
- * CBRs/DSRs for each cpu to use. The resources are all taken from
- * the GRU chiplet 1 on the blade. This leaves the full set of resources
- * of chiplet 0 available to be allocated to a single user.
+ * Blade percpu resources reserved for kernel use. These resources are
+ * reserved whenever the the kernel context for the blade is loaded. Note
+ * that the kernel context is not guaranteed to be always available. It is
+ * loaded on demand & can be stolen by a user if the user demand exceeds the
+ * kernel demand. The kernel can always reload the kernel context but
+ * a SLEEP may be required!!!.
+ *
+ * Async Overview:
+ *
+ * 	Each blade has one "kernel context" that owns GRU kernel resources
+ * 	located on the blade. Kernel drivers use GRU resources in this context
+ * 	for sending messages, zeroing memory, etc.
+ *
+ * 	The kernel context is dynamically loaded on demand. If it is not in
+ * 	use by the kernel, the kernel context can be unloaded & given to a user.
+ * 	The kernel context will be reloaded when needed. This may require that
+ * 	a context be stolen from a user.
+ * 		NOTE: frequent unloading/reloading of the kernel context is
+ * 		expensive. We are depending on batch schedulers, cpusets, sane
+ * 		drivers or some other mechanism to prevent the need for frequent
+ *	 	stealing/reloading.
+ *
+ * 	The kernel context consists of two parts:
+ * 		- 1 CB & a few DSRs that are reserved for each cpu on the blade.
+ * 		  Each cpu has it's own private resources & does not share them
+ * 		  with other cpus. These resources are used serially, ie,
+ * 		  locked, used & unlocked  on each call to a function in
+ * 		  grukservices.
+ * 		  	(Now that we have dynamic loading of kernel contexts, I
+ * 		  	 may rethink this & allow sharing between cpus....)
+ *
+ *		- Additional resources can be reserved long term & used directly
+ *		  by UV drivers located in the kernel. Drivers using these GRU
+ *		  resources can use asynchronous GRU instructions that send
+ *		  interrupts on completion.
+ *		  	- these resources must be explicitly locked/unlocked
+ *		  	- locked resources prevent (obviously) the kernel
+ *		  	  context from being unloaded.
+ *			- drivers using these resource directly issue their own
+ *			  GRU instruction and must wait/check completion.
+ *
+ * 		  When these resources are reserved, the caller can optionally
+ * 		  associate a wait_queue with the resources and use asynchronous
+ * 		  GRU instructions. When an async GRU instruction completes, the
+ * 		  driver will do a wakeup on the event.
+ *
  */
 
-/* Blade percpu resources PERMANENTLY reserved for kernel use */
+
+#define ASYNC_HAN_TO_BID(h)	((h) - 1)
+#define ASYNC_BID_TO_HAN(b)	((b) + 1)
+#define ASYNC_HAN_TO_BS(h)	gru_base[ASYNC_HAN_TO_BID(h)]
+#define KCB_TO_GID(cb)		((cb - gru_start_vaddr) /		\
+					(GRU_SIZE * GRU_CHIPLETS_PER_BLADE))
+#define KCB_TO_BS(cb)		gru_base[KCB_TO_GID(cb)]
+
 #define GRU_NUM_KERNEL_CBR	1
 #define GRU_NUM_KERNEL_DSR_BYTES 256
 #define GRU_NUM_KERNEL_DSR_CL	(GRU_NUM_KERNEL_DSR_BYTES /		\
 					GRU_CACHE_LINE_BYTES)
-#define KERNEL_CTXNUM           15
 
 /* GRU instruction attributes for all instructions */
 #define IMA			IMA_CB_DELAY
@@ -98,6 +146,108 @@
 
 #define HSTATUS(mq, h)	((mq) + offsetof(struct message_queue, hstatus[h]))
 
+/*
+ * Reload the blade's kernel context into a GRU chiplet. Called holding
+ * the bs_kgts_sema for READ. Will steal user contexts if necessary.
+ */
+static void gru_load_kernel_context(struct gru_blade_state *bs, int blade_id)
+{
+	struct gru_state *gru;
+	struct gru_thread_state *kgts;
+	void *vaddr;
+	int ctxnum, ncpus;
+
+	up_read(&bs->bs_kgts_sema);
+	down_write(&bs->bs_kgts_sema);
+
+	if (!bs->bs_kgts)
+		bs->bs_kgts = gru_alloc_gts(NULL, 0, 0, 0, 0);
+	kgts = bs->bs_kgts;
+
+	if (!kgts->ts_gru) {
+		STAT(load_kernel_context);
+		ncpus = uv_blade_nr_possible_cpus(blade_id);
+		kgts->ts_cbr_au_count = GRU_CB_COUNT_TO_AU(
+			GRU_NUM_KERNEL_CBR * ncpus + bs->bs_async_cbrs);
+		kgts->ts_dsr_au_count = GRU_DS_BYTES_TO_AU(
+			GRU_NUM_KERNEL_DSR_BYTES * ncpus +
+				bs->bs_async_dsr_bytes);
+		while (!gru_assign_gru_context(kgts, blade_id)) {
+			msleep(1);
+			gru_steal_context(kgts, blade_id);
+		}
+		gru_load_context(kgts);
+		gru = bs->bs_kgts->ts_gru;
+		vaddr = gru->gs_gru_base_vaddr;
+		ctxnum = kgts->ts_ctxnum;
+		bs->kernel_cb = get_gseg_base_address_cb(vaddr, ctxnum, 0);
+		bs->kernel_dsr = get_gseg_base_address_ds(vaddr, ctxnum, 0);
+	}
+	downgrade_write(&bs->bs_kgts_sema);
+}
+
+/*
+ * Free all kernel contexts that are not currently in use.
+ *   Returns 0 if all freed, else number of inuse context.
+ */
+static int gru_free_kernel_contexts(void)
+{
+	struct gru_blade_state *bs;
+	struct gru_thread_state *kgts;
+	int bid, ret = 0;
+
+	for (bid = 0; bid < GRU_MAX_BLADES; bid++) {
+		bs = gru_base[bid];
+		if (!bs)
+			continue;
+		if (down_write_trylock(&bs->bs_kgts_sema)) {
+			kgts = bs->bs_kgts;
+			if (kgts && kgts->ts_gru)
+				gru_unload_context(kgts, 0);
+			kfree(kgts);
+			bs->bs_kgts = NULL;
+			up_write(&bs->bs_kgts_sema);
+		} else {
+			ret++;
+		}
+	}
+	return ret;
+}
+
+/*
+ * Lock & load the kernel context for the specified blade.
+ */
+static struct gru_blade_state *gru_lock_kernel_context(int blade_id)
+{
+	struct gru_blade_state *bs;
+
+	STAT(lock_kernel_context);
+	bs = gru_base[blade_id];
+
+	down_read(&bs->bs_kgts_sema);
+	if (!bs->bs_kgts || !bs->bs_kgts->ts_gru)
+		gru_load_kernel_context(bs, blade_id);
+	return bs;
+
+}
+
+/*
+ * Unlock the kernel context for the specified blade. Context is not
+ * unloaded but may be stolen before next use.
+ */
+static void gru_unlock_kernel_context(int blade_id)
+{
+	struct gru_blade_state *bs;
+
+	bs = gru_base[blade_id];
+	up_read(&bs->bs_kgts_sema);
+	STAT(unlock_kernel_context);
+}
+
+/*
+ * Reserve & get pointers to the DSR/CBRs reserved for the current cpu.
+ * 	- returns with preemption disabled
+ */
 static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr)
 {
 	struct gru_blade_state *bs;
@@ -105,30 +255,148 @@
 
 	BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES);
 	preempt_disable();
-	bs = gru_base[uv_numa_blade_id()];
+	bs = gru_lock_kernel_context(uv_numa_blade_id());
 	lcpu = uv_blade_processor_id();
 	*cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE;
 	*dsr = bs->kernel_dsr + lcpu * GRU_NUM_KERNEL_DSR_BYTES;
 	return 0;
 }
 
+/*
+ * Free the current cpus reserved DSR/CBR resources.
+ */
 static void gru_free_cpu_resources(void *cb, void *dsr)
 {
+	gru_unlock_kernel_context(uv_numa_blade_id());
 	preempt_enable();
 }
 
+/*
+ * Reserve GRU resources to be used asynchronously.
+ *   Note: currently supports only 1 reservation per blade.
+ *
+ * 	input:
+ * 		blade_id  - blade on which resources should be reserved
+ * 		cbrs	  - number of CBRs
+ * 		dsr_bytes - number of DSR bytes needed
+ *	output:
+ *		handle to identify resource
+ *		(0 = async resources already reserved)
+ */
+unsigned long gru_reserve_async_resources(int blade_id, int cbrs, int dsr_bytes,
+			struct completion *cmp)
+{
+	struct gru_blade_state *bs;
+	struct gru_thread_state *kgts;
+	int ret = 0;
+
+	bs = gru_base[blade_id];
+
+	down_write(&bs->bs_kgts_sema);
+
+	/* Verify no resources already reserved */
+	if (bs->bs_async_dsr_bytes + bs->bs_async_cbrs)
+		goto done;
+	bs->bs_async_dsr_bytes = dsr_bytes;
+	bs->bs_async_cbrs = cbrs;
+	bs->bs_async_wq = cmp;
+	kgts = bs->bs_kgts;
+
+	/* Resources changed. Unload context if already loaded */
+	if (kgts && kgts->ts_gru)
+		gru_unload_context(kgts, 0);
+	ret = ASYNC_BID_TO_HAN(blade_id);
+
+done:
+	up_write(&bs->bs_kgts_sema);
+	return ret;
+}
+
+/*
+ * Release async resources previously reserved.
+ *
+ *	input:
+ *		han - handle to identify resources
+ */
+void gru_release_async_resources(unsigned long han)
+{
+	struct gru_blade_state *bs = ASYNC_HAN_TO_BS(han);
+
+	down_write(&bs->bs_kgts_sema);
+	bs->bs_async_dsr_bytes = 0;
+	bs->bs_async_cbrs = 0;
+	bs->bs_async_wq = NULL;
+	up_write(&bs->bs_kgts_sema);
+}
+
+/*
+ * Wait for async GRU instructions to complete.
+ *
+ *	input:
+ *		han - handle to identify resources
+ */
+void gru_wait_async_cbr(unsigned long han)
+{
+	struct gru_blade_state *bs = ASYNC_HAN_TO_BS(han);
+
+	wait_for_completion(bs->bs_async_wq);
+	mb();
+}
+
+/*
+ * Lock previous reserved async GRU resources
+ *
+ *	input:
+ *		han - handle to identify resources
+ *	output:
+ *		cb  - pointer to first CBR
+ *		dsr - pointer to first DSR
+ */
+void gru_lock_async_resource(unsigned long han,  void **cb, void **dsr)
+{
+	struct gru_blade_state *bs = ASYNC_HAN_TO_BS(han);
+	int blade_id = ASYNC_HAN_TO_BID(han);
+	int ncpus;
+
+	gru_lock_kernel_context(blade_id);
+	ncpus = uv_blade_nr_possible_cpus(blade_id);
+	if (cb)
+		*cb = bs->kernel_cb + ncpus * GRU_HANDLE_STRIDE;
+	if (dsr)
+		*dsr = bs->kernel_dsr + ncpus * GRU_NUM_KERNEL_DSR_BYTES;
+}
+
+/*
+ * Unlock previous reserved async GRU resources
+ *
+ *	input:
+ *		han - handle to identify resources
+ */
+void gru_unlock_async_resource(unsigned long han)
+{
+	int blade_id = ASYNC_HAN_TO_BID(han);
+
+	gru_unlock_kernel_context(blade_id);
+}
+
+/*----------------------------------------------------------------------*/
 int gru_get_cb_exception_detail(void *cb,
 		struct control_block_extended_exc_detail *excdet)
 {
 	struct gru_control_block_extended *cbe;
+	struct gru_blade_state *bs;
+	int cbrnum;
 
-	cbe = get_cbe(GRUBASE(cb), get_cb_number(cb));
-	prefetchw(cbe);	/* Harmless on hardware, required for emulator */
+	bs = KCB_TO_BS(cb);
+	cbrnum = thread_cbr_number(bs->bs_kgts, get_cb_number(cb));
+	cbe = get_cbe(GRUBASE(cb), cbrnum);
+	gru_flush_cache(cbe);	/* CBE not coherent */
 	excdet->opc = cbe->opccpy;
 	excdet->exopc = cbe->exopccpy;
 	excdet->ecause = cbe->ecause;
 	excdet->exceptdet0 = cbe->idef1upd;
 	excdet->exceptdet1 = cbe->idef3upd;
+	gru_flush_cache(cbe);
 	return 0;
 }
 
@@ -167,13 +435,13 @@
 	int retry = EXCEPTION_RETRY_LIMIT;
 
 	while (1)  {
-		if (gru_get_cb_message_queue_substatus(cb))
-			break;
 		if (gru_wait_idle_or_exception(gen) == CBS_IDLE)
 			return CBS_IDLE;
-
+		if (gru_get_cb_message_queue_substatus(cb))
+			return CBS_EXCEPTION;
 		gru_get_cb_exception_detail(cb, &excdet);
-		if (excdet.ecause & ~EXCEPTION_RETRY_BITS)
+		if ((excdet.ecause & ~EXCEPTION_RETRY_BITS) ||
+				(excdet.cbrexecstatus & CBR_EXS_ABORT_OCC))
 			break;
 		if (retry-- == 0)
 			break;
@@ -416,6 +684,29 @@
 				mqd->interrupt_vector);
 }
 
+/*
+ * Handle a PUT failure. Note: if message was a 2-line message, one of the
+ * lines might have successfully have been written. Before sending the
+ * message, "present" must be cleared in BOTH lines to prevent the receiver
+ * from prematurely seeing the full message.
+ */
+static int send_message_put_nacked(void *cb, struct gru_message_queue_desc *mqd,
+			void *mesg, int lines)
+{
+	unsigned long m;
+
+	m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6);
+	if (lines == 2) {
+		gru_vset(cb, m, 0, XTYPE_CL, lines, 1, IMA);
+		if (gru_wait(cb) != CBS_IDLE)
+			return MQE_UNEXPECTED_CB_ERR;
+	}
+	gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
+	if (gru_wait(cb) != CBS_IDLE)
+		return MQE_UNEXPECTED_CB_ERR;
+	send_message_queue_interrupt(mqd);
+	return MQE_OK;
+}
 
 /*
  * Handle a gru_mesq failure. Some of these failures are software recoverable
@@ -425,7 +716,6 @@
 				void *mesg, int lines)
 {
 	int substatus, ret = 0;
-	unsigned long m;
 
 	substatus = gru_get_cb_message_queue_substatus(cb);
 	switch (substatus) {
@@ -447,14 +737,7 @@
 		break;
 	case CBSS_PUT_NACKED:
 		STAT(mesq_send_put_nacked);
-		m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6);
-		gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
-		if (gru_wait(cb) == CBS_IDLE) {
-			ret = MQE_OK;
-			send_message_queue_interrupt(mqd);
-		} else {
-			ret = MQE_UNEXPECTED_CB_ERR;
-		}
+		ret = send_message_put_nacked(cb, mqd, mesg, lines);
 		break;
 	default:
 		BUG();
@@ -597,115 +880,177 @@
 
 /* ------------------- KERNEL QUICKTESTS RUN AT STARTUP ----------------*/
 /* 	Temp - will delete after we gain confidence in the GRU		*/
-static __cacheline_aligned unsigned long word0;
-static __cacheline_aligned unsigned long word1;
 
-static int quicktest(struct gru_state *gru)
+static int quicktest0(unsigned long arg)
 {
+	unsigned long word0;
+	unsigned long word1;
 	void *cb;
-	void *ds;
+	void *dsr;
 	unsigned long *p;
+	int ret = -EIO;
 
-	cb = get_gseg_base_address_cb(gru->gs_gru_base_vaddr, KERNEL_CTXNUM, 0);
-	ds = get_gseg_base_address_ds(gru->gs_gru_base_vaddr, KERNEL_CTXNUM, 0);
-	p = ds;
+	if (gru_get_cpu_resources(GRU_CACHE_LINE_BYTES, &cb, &dsr))
+		return MQE_BUG_NO_RESOURCES;
+	p = dsr;
 	word0 = MAGIC;
+	word1 = 0;
 
-	gru_vload(cb, uv_gpa(&word0), 0, XTYPE_DW, 1, 1, IMA);
-	if (gru_wait(cb) != CBS_IDLE)
-		BUG();
+	gru_vload(cb, uv_gpa(&word0), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
+	if (gru_wait(cb) != CBS_IDLE) {
+		printk(KERN_DEBUG "GRU quicktest0: CBR failure 1\n");
+		goto done;
+	}
 
-	if (*(unsigned long *)ds != MAGIC)
-		BUG();
-	gru_vstore(cb, uv_gpa(&word1), 0, XTYPE_DW, 1, 1, IMA);
-	if (gru_wait(cb) != CBS_IDLE)
-		BUG();
+	if (*p != MAGIC) {
+		printk(KERN_DEBUG "GRU: quicktest0 bad magic 0x%lx\n", *p);
+		goto done;
+	}
+	gru_vstore(cb, uv_gpa(&word1), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
+	if (gru_wait(cb) != CBS_IDLE) {
+		printk(KERN_DEBUG "GRU quicktest0: CBR failure 2\n");
+		goto done;
+	}
 
-	if (word0 != word1 || word0 != MAGIC) {
-		printk
-		    ("GRU quicktest err: gid %d, found 0x%lx, expected 0x%lx\n",
-		     gru->gs_gid, word1, MAGIC);
-		BUG();		/* ZZZ should not be fatal */
+	if (word0 != word1 || word1 != MAGIC) {
+		printk(KERN_DEBUG
+		       "GRU quicktest0 err: found 0x%lx, expected 0x%lx\n",
+		     word1, MAGIC);
+		goto done;
 	}
+	ret = 0;
 
-	return 0;
+done:
+	gru_free_cpu_resources(cb, dsr);
+	return ret;
 }
 
+#define ALIGNUP(p, q)	((void *)(((unsigned long)(p) + (q) - 1) & ~(q - 1)))
 
-int gru_kservices_init(struct gru_state *gru)
+static int quicktest1(unsigned long arg)
 {
-	struct gru_blade_state *bs;
-	struct gru_context_configuration_handle *cch;
-	unsigned long cbr_map, dsr_map;
-	int err, num, cpus_possible;
+	struct gru_message_queue_desc mqd;
+	void *p, *mq;
+	unsigned long *dw;
+	int i, ret = -EIO;
+	char mes[GRU_CACHE_LINE_BYTES], *m;
 
-	/*
-	 * Currently, resources are reserved ONLY on the second chiplet
-	 * on each blade. This leaves ALL resources on chiplet 0 available
-	 * for user code.
-	 */
-	bs = gru->gs_blade;
-	if (gru != &bs->bs_grus[1])
-		return 0;
+	/* Need  1K cacheline aligned that does not cross page boundary */
+	p = kmalloc(4096, 0);
+	mq = ALIGNUP(p, 1024);
+	memset(mes, 0xee, sizeof(mes));
+	dw = mq;
 
-	cpus_possible = uv_blade_nr_possible_cpus(gru->gs_blade_id);
+	gru_create_message_queue(&mqd, mq, 8 * GRU_CACHE_LINE_BYTES, 0, 0, 0);
+	for (i = 0; i < 6; i++) {
+		mes[8] = i;
+		do {
+			ret = gru_send_message_gpa(&mqd, mes, sizeof(mes));
+		} while (ret == MQE_CONGESTION);
+		if (ret)
+			break;
+	}
+	if (ret != MQE_QUEUE_FULL || i != 4)
+		goto done;
 
-	num = GRU_NUM_KERNEL_CBR * cpus_possible;
-	cbr_map = gru_reserve_cb_resources(gru, GRU_CB_COUNT_TO_AU(num), NULL);
-	gru->gs_reserved_cbrs += num;
+	for (i = 0; i < 6; i++) {
+		m = gru_get_next_message(&mqd);
+		if (!m || m[8] != i)
+			break;
+		gru_free_message(&mqd, m);
+	}
+	ret = (i == 4) ? 0 : -EIO;
 
-	num = GRU_NUM_KERNEL_DSR_BYTES * cpus_possible;
-	dsr_map = gru_reserve_ds_resources(gru, GRU_DS_BYTES_TO_AU(num), NULL);
-	gru->gs_reserved_dsr_bytes += num;
+done:
+	kfree(p);
+	return ret;
+}
 
-	gru->gs_active_contexts++;
-	__set_bit(KERNEL_CTXNUM, &gru->gs_context_map);
-	cch = get_cch(gru->gs_gru_base_vaddr, KERNEL_CTXNUM);
+static int quicktest2(unsigned long arg)
+{
+	static DECLARE_COMPLETION(cmp);
+	unsigned long han;
+	int blade_id = 0;
+	int numcb = 4;
+	int ret = 0;
+	unsigned long *buf;
+	void *cb0, *cb;
+	int i, k, istatus, bytes;
 
-	bs->kernel_cb = get_gseg_base_address_cb(gru->gs_gru_base_vaddr,
-					KERNEL_CTXNUM, 0);
-	bs->kernel_dsr = get_gseg_base_address_ds(gru->gs_gru_base_vaddr,
-					KERNEL_CTXNUM, 0);
+	bytes = numcb * 4 * 8;
+	buf = kmalloc(bytes, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
-	lock_cch_handle(cch);
-	cch->tfm_fault_bit_enable = 0;
-	cch->tlb_int_enable = 0;
-	cch->tfm_done_bit_enable = 0;
-	cch->unmap_enable = 1;
-	err = cch_allocate(cch, 0, 0, cbr_map, dsr_map);
-	if (err) {
-		gru_dbg(grudev,
-			"Unable to allocate kernel CCH: gid %d, err %d\n",
-			gru->gs_gid, err);
-		BUG();
-	}
-	if (cch_start(cch)) {
-		gru_dbg(grudev, "Unable to start kernel CCH: gid %d, err %d\n",
-			gru->gs_gid, err);
-		BUG();
+	ret = -EBUSY;
+	han = gru_reserve_async_resources(blade_id, numcb, 0, &cmp);
+	if (!han)
+		goto done;
+
+	gru_lock_async_resource(han, &cb0, NULL);
+	memset(buf, 0xee, bytes);
+	for (i = 0; i < numcb; i++)
+		gru_vset(cb0 + i * GRU_HANDLE_STRIDE, uv_gpa(&buf[i * 4]), 0,
+				XTYPE_DW, 4, 1, IMA_INTERRUPT);
+
+	ret = 0;
+	for (k = 0; k < numcb; k++) {
+		gru_wait_async_cbr(han);
+		for (i = 0; i < numcb; i++) {
+			cb = cb0 + i * GRU_HANDLE_STRIDE;
+			istatus = gru_check_status(cb);
+			if (istatus == CBS_ACTIVE)
+				continue;
+			if (istatus == CBS_EXCEPTION)
+				ret = -EFAULT;
+			else if (buf[i] || buf[i + 1] || buf[i + 2] ||
+					buf[i + 3])
+				ret = -EIO;
+		}
 	}
-	unlock_cch_handle(cch);
+	BUG_ON(cmp.done);
 
-	if (gru_options & GRU_QUICKLOOK)
-		quicktest(gru);
-	return 0;
+	gru_unlock_async_resource(han);
+	gru_release_async_resources(han);
+done:
+	kfree(buf);
+	return ret;
 }
 
-void gru_kservices_exit(struct gru_state *gru)
+/*
+ * Debugging only. User hook for various kernel tests
+ * of driver & gru.
+ */
+int gru_ktest(unsigned long arg)
 {
-	struct gru_context_configuration_handle *cch;
-	struct gru_blade_state *bs;
+	int ret = -EINVAL;
 
-	bs = gru->gs_blade;
-	if (gru != &bs->bs_grus[1])
-		return;
+	switch (arg & 0xff) {
+	case 0:
+		ret = quicktest0(arg);
+		break;
+	case 1:
+		ret = quicktest1(arg);
+		break;
+	case 2:
+		ret = quicktest2(arg);
+		break;
+	case 99:
+		ret = gru_free_kernel_contexts();
+		break;
+	}
+	return ret;
 
-	cch = get_cch(gru->gs_gru_base_vaddr, KERNEL_CTXNUM);
-	lock_cch_handle(cch);
-	if (cch_interrupt_sync(cch))
-		BUG();
-	if (cch_deallocate(cch))
+}
+
+int gru_kservices_init(void)
+{
+	return 0;
+}
+
+void gru_kservices_exit(void)
+{
+	if (gru_free_kernel_contexts())
 		BUG();
-	unlock_cch_handle(cch);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grukservices.h linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grukservices.h
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grukservices.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grukservices.h	2009-09-09 18:13:59.000000000 -0400
@@ -146,4 +146,55 @@
 extern int gru_copy_gpa(unsigned long dest_gpa, unsigned long src_gpa,
 							unsigned int bytes);
 
+/*
+ * Reserve GRU resources to be used asynchronously.
+ *
+ * 	input:
+ * 		blade_id  - blade on which resources should be reserved
+ * 		cbrs	  - number of CBRs
+ * 		dsr_bytes - number of DSR bytes needed
+ * 		cmp	  - completion structure for waiting for
+ * 			    async completions
+ *	output:
+ *		handle to identify resource
+ *		(0 = no resources)
+ */
+extern unsigned long gru_reserve_async_resources(int blade_id, int cbrs, int dsr_bytes,
+				struct completion *cmp);
+
+/*
+ * Release async resources previously reserved.
+ *
+ *	input:
+ *		han - handle to identify resources
+ */
+extern void gru_release_async_resources(unsigned long han);
+
+/*
+ * Wait for async GRU instructions to complete.
+ *
+ *	input:
+ *		han - handle to identify resources
+ */
+extern void gru_wait_async_cbr(unsigned long han);
+
+/*
+ * Lock previous reserved async GRU resources
+ *
+ *	input:
+ *		han - handle to identify resources
+ *	output:
+ *		cb  - pointer to first CBR
+ *		dsr - pointer to first DSR
+ */
+extern void gru_lock_async_resource(unsigned long han,  void **cb, void **dsr);
+
+/*
+ * Unlock previous reserved async GRU resources
+ *
+ *	input:
+ *		han - handle to identify resources
+ */
+extern void gru_unlock_async_resource(unsigned long han);
+
 #endif 		/* __GRU_KSERVICES_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grulib.h linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grulib.h
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grulib.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grulib.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,8 +32,8 @@
 /* Set Number of Request Blocks */
 #define GRU_CREATE_CONTEXT		_IOWR(GRU_IOCTL_NUM, 1, void *)
 
-/* Register task as using the slice */
-#define GRU_SET_TASK_SLICE		_IOWR(GRU_IOCTL_NUM, 5, void *)
+/*  Set Context Options */
+#define GRU_SET_CONTEXT_OPTION		_IOWR(GRU_IOCTL_NUM, 4, void *)
 
 /* Fetch exception detail */
 #define GRU_USER_GET_EXCEPTION_DETAIL	_IOWR(GRU_IOCTL_NUM, 6, void *)
@@ -44,8 +44,11 @@
 /* For user unload context */
 #define GRU_USER_UNLOAD_CONTEXT		_IOWR(GRU_IOCTL_NUM, 9, void *)
 
-/* For fetching GRU chiplet status */
-#define GRU_GET_CHIPLET_STATUS		_IOWR(GRU_IOCTL_NUM, 10, void *)
+/* For dumpping GRU chiplet state */
+#define GRU_DUMP_CHIPLET_STATE		_IOWR(GRU_IOCTL_NUM, 11, void *)
+
+/* For getting gseg statistics */
+#define GRU_GET_GSEG_STATISTICS		_IOWR(GRU_IOCTL_NUM, 12, void *)
 
 /* For user TLB flushing (primarily for tests) */
 #define GRU_USER_FLUSH_TLB		_IOWR(GRU_IOCTL_NUM, 50, void *)
@@ -53,8 +56,26 @@
 /* Get some config options (primarily for tests & emulator) */
 #define GRU_GET_CONFIG_INFO		_IOWR(GRU_IOCTL_NUM, 51, void *)
 
+/* Various kernel self-tests */
+#define GRU_KTEST			_IOWR(GRU_IOCTL_NUM, 52, void *)
+
 #define CONTEXT_WINDOW_BYTES(th)        (GRU_GSEG_PAGESIZE * (th))
 #define THREAD_POINTER(p, th)		(p + GRU_GSEG_PAGESIZE * (th))
+#define GSEG_START(cb)			((void *)((unsigned long)(cb) & ~(GRU_GSEG_PAGESIZE - 1)))
+
+/*
+ * Statictics kept on a per-GTS basis.
+ */
+struct gts_statistics {
+	unsigned long	fmm_tlbdropin;
+	unsigned long	upm_tlbdropin;
+	unsigned long	context_stolen;
+};
+
+struct gru_get_gseg_statistics_req {
+	unsigned long		gseg;
+	struct gts_statistics	stats;
+};
 
 /*
  * Structure used to pass TLB flush parameters to the driver
@@ -75,6 +96,16 @@
 };
 
 /*
+ * Structure used to set context options
+ */
+enum {sco_gseg_owner, sco_cch_req_slice};
+struct gru_set_context_option_req {
+	unsigned long	gseg;
+	int		op;
+	unsigned long	val1;
+};
+
+/*
  * Structure used to pass TLB flush parameters to the driver
  */
 struct gru_flush_tlb_req {
@@ -84,6 +115,36 @@
 };
 
 /*
+ * Structure used to pass TLB flush parameters to the driver
+ */
+enum {dcs_pid, dcs_gid};
+struct gru_dump_chiplet_state_req {
+	unsigned int	op;
+	unsigned int	gid;
+	int		ctxnum;
+	char		data_opt;
+	char		lock_cch;
+	pid_t		pid;
+	void		*buf;
+	size_t		buflen;
+	/* ---- output --- */
+	unsigned int	num_contexts;
+};
+
+#define GRU_DUMP_MAGIC	0x3474ab6c
+struct gru_dump_context_header {
+	unsigned int	magic;
+	unsigned int	gid;
+	unsigned char	ctxnum;
+	unsigned char	cbrcnt;
+	unsigned char	dsrcnt;
+	pid_t		pid;
+	unsigned long	vaddr;
+	int		cch_locked;
+	unsigned long	data[0];
+};
+
+/*
  * GRU configuration info (temp - for testing)
  */
 struct gru_config_info {
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grumain.c linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grumain.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grumain.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grumain.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,11 +3,21 @@
  *
  *            DRIVER TABLE MANAGER + GRU CONTEXT LOAD/UNLOAD
  *
- * 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) 2008 Silicon Graphics, Inc.  All Rights Reserved.
  *
- * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ *  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>
@@ -96,7 +106,7 @@
 	gid = gru->gs_gid;
 again:
 	for (i = 0; i < GRU_NUM_CCH; i++) {
-		if (!gru->gs_gts[i])
+		if (!gru->gs_gts[i] || is_kernel_context(gru->gs_gts[i]))
 			continue;
 		inuse_asid = gru->gs_gts[i]->ts_gms->ms_asids[gid].mt_asid;
 		gru_dbg(grudev, "gid %d, gts %p, gms %p, inuse 0x%x, cxt %d\n",
@@ -150,7 +160,7 @@
 	unsigned long bits = 0;
 	int i;
 
-	do {
+	while (n--) {
 		i = find_first_bit(p, mmax);
 		if (i == mmax)
 			BUG();
@@ -158,7 +168,7 @@
 		__set_bit(i, &bits);
 		if (idx)
 			*idx++ = i;
-	} while (--n);
+	}
 	return bits;
 }
 
@@ -299,38 +309,39 @@
 /*
  * Allocate a thread state structure.
  */
-static struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
-					      struct gru_vma_data *vdata,
-					      int tsid)
+struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
+		int cbr_au_count, int dsr_au_count, int options, int tsid)
 {
 	struct gru_thread_state *gts;
 	int bytes;
 
-	bytes = DSR_BYTES(vdata->vd_dsr_au_count) +
-				CBR_BYTES(vdata->vd_cbr_au_count);
+	bytes = DSR_BYTES(dsr_au_count) + CBR_BYTES(cbr_au_count);
 	bytes += sizeof(struct gru_thread_state);
-	gts = kzalloc(bytes, GFP_KERNEL);
+	gts = kmalloc(bytes, GFP_KERNEL);
 	if (!gts)
 		return NULL;
 
 	STAT(gts_alloc);
+	memset(gts, 0, sizeof(struct gru_thread_state)); /* zero out header */
 	atomic_set(&gts->ts_refcnt, 1);
 	mutex_init(&gts->ts_ctxlock);
-	gts->ts_cbr_au_count = vdata->vd_cbr_au_count;
-	gts->ts_dsr_au_count = vdata->vd_dsr_au_count;
-	gts->ts_user_options = vdata->vd_user_options;
+	gts->ts_cbr_au_count = cbr_au_count;
+	gts->ts_dsr_au_count = dsr_au_count;
+	gts->ts_user_options = options;
 	gts->ts_tsid = tsid;
-	gts->ts_user_options = vdata->vd_user_options;
 	gts->ts_ctxnum = NULLCTX;
-	gts->ts_mm = current->mm;
-	gts->ts_vma = vma;
 	gts->ts_tlb_int_select = -1;
-	gts->ts_gms = gru_register_mmu_notifier();
+	gts->ts_cch_req_slice = -1;
 	gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT);
-	if (!gts->ts_gms)
-		goto err;
+	if (vma) {
+		gts->ts_mm = current->mm;
+		gts->ts_vma = vma;
+		gts->ts_gms = gru_register_mmu_notifier();
+		if (!gts->ts_gms)
+			goto err;
+	}
 
-	gru_dbg(grudev, "alloc vdata %p, new gts %p\n", vdata, gts);
+	gru_dbg(grudev, "alloc gts %p\n", gts);
 	return gts;
 
 err:
@@ -381,7 +392,8 @@
 	struct gru_vma_data *vdata = vma->vm_private_data;
 	struct gru_thread_state *gts, *ngts;
 
-	gts = gru_alloc_gts(vma, vdata, tsid);
+	gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count, vdata->vd_dsr_au_count,
+			    vdata->vd_user_options, tsid);
 	if (!gts)
 		return NULL;
 
@@ -458,7 +470,8 @@
 }
 
 static void gru_load_context_data(void *save, void *grubase, int ctxnum,
-				  unsigned long cbrmap, unsigned long dsrmap)
+				  unsigned long cbrmap, unsigned long dsrmap,
+				  int data_valid)
 {
 	void *gseg, *cb, *cbe;
 	unsigned long length;
@@ -471,12 +484,22 @@
 	gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
 
 	for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
-		save += gru_copy_handle(cb, save);
-		save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save);
+		if (data_valid) {
+			save += gru_copy_handle(cb, save);
+			save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE,
+						save);
+		} else {
+			memset(cb, 0, GRU_CACHE_LINE_BYTES);
+			memset(cbe + i * GRU_HANDLE_STRIDE, 0,
+						GRU_CACHE_LINE_BYTES);
+		}
 		cb += GRU_HANDLE_STRIDE;
 	}
 
-	memcpy(gseg + GRU_DS_BASE, save, length);
+	if (data_valid)
+		memcpy(gseg + GRU_DS_BASE, save, length);
+	else
+		memset(gseg + GRU_DS_BASE, 0, length);
 }
 
 static void gru_unload_context_data(void *save, void *grubase, int ctxnum,
@@ -506,7 +529,8 @@
 	struct gru_context_configuration_handle *cch;
 	int ctxnum = gts->ts_ctxnum;
 
-	zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
+	if (!is_kernel_context(gts))
+		zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
 	cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
 
 	gru_dbg(grudev, "gts %p\n", gts);
@@ -514,11 +538,14 @@
 	if (cch_interrupt_sync(cch))
 		BUG();
 
-	gru_unload_mm_tracker(gru, gts);
-	if (savestate)
+	if (!is_kernel_context(gts))
+		gru_unload_mm_tracker(gru, gts);
+	if (savestate) {
 		gru_unload_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr,
 					ctxnum, gts->ts_cbr_map,
 					gts->ts_dsr_map);
+		gts->ts_data_valid = 1;
+	}
 
 	if (cch_deallocate(cch))
 		BUG();
@@ -526,24 +553,22 @@
 	unlock_cch_handle(cch);
 
 	gru_free_gru_context(gts);
-	STAT(unload_context);
 }
 
 /*
  * Load a GRU context by copying it from the thread data structure in memory
  * to the GRU.
  */
-static void gru_load_context(struct gru_thread_state *gts)
+void gru_load_context(struct gru_thread_state *gts)
 {
 	struct gru_state *gru = gts->ts_gru;
 	struct gru_context_configuration_handle *cch;
-	int err, asid, ctxnum = gts->ts_ctxnum;
+	int i, err, asid, ctxnum = gts->ts_ctxnum;
 
 	gru_dbg(grudev, "gts %p\n", gts);
 	cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
 
 	lock_cch_handle(cch);
-	asid = gru_load_mm_tracker(gru, gts);
 	cch->tfm_fault_bit_enable =
 	    (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
 	     || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
@@ -552,9 +577,32 @@
 		gts->ts_tlb_int_select = gru_cpu_fault_map_id();
 		cch->tlb_int_select = gts->ts_tlb_int_select;
 	}
+	if (gts->ts_cch_req_slice >= 0) {
+		cch->req_slice_set_enable = 1;
+		cch->req_slice = gts->ts_cch_req_slice;
+	} else {
+		cch->req_slice_set_enable =0;
+	}
 	cch->tfm_done_bit_enable = 0;
-	err = cch_allocate(cch, asid, gts->ts_sizeavail, gts->ts_cbr_map,
-				gts->ts_dsr_map);
+	cch->dsr_allocation_map = gts->ts_dsr_map;
+	cch->cbr_allocation_map = gts->ts_cbr_map;
+
+	if (is_kernel_context(gts)) {
+		cch->unmap_enable = 1;
+		cch->tfm_done_bit_enable = 1;
+		cch->cb_int_enable = 1;
+	} else {
+		cch->unmap_enable = 0;
+		cch->tfm_done_bit_enable = 0;
+		cch->cb_int_enable = 0;
+		asid = gru_load_mm_tracker(gru, gts);
+		for (i = 0; i < 8; i++) {
+			cch->asid[i] = asid + i;
+			cch->sizeavail[i] = gts->ts_sizeavail;
+		}
+	}
+
+	err = cch_allocate(cch);
 	if (err) {
 		gru_dbg(grudev,
 			"err %d: cch %p, gts %p, cbr 0x%lx, dsr 0x%lx\n",
@@ -563,13 +611,11 @@
 	}
 
 	gru_load_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr, ctxnum,
-			      gts->ts_cbr_map, gts->ts_dsr_map);
+			gts->ts_cbr_map, gts->ts_dsr_map, gts->ts_data_valid);
 
 	if (cch_start(cch))
 		BUG();
 	unlock_cch_handle(cch);
-
-	STAT(load_context);
 }
 
 /*
@@ -599,6 +645,9 @@
 				cch->sizeavail[i] = gts->ts_sizeavail;
 			gts->ts_tlb_int_select = gru_cpu_fault_map_id();
 			cch->tlb_int_select = gru_cpu_fault_map_id();
+			cch->tfm_fault_bit_enable =
+			  (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
+			    || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
 		} else {
 			for (i = 0; i < 8; i++)
 				cch->asid[i] = 0;
@@ -642,7 +691,28 @@
 #define next_gru(b, g)	(((g) < &(b)->bs_grus[GRU_CHIPLETS_PER_BLADE - 1]) ?  \
 				 ((g)+1) : &(b)->bs_grus[0])
 
-static void gru_steal_context(struct gru_thread_state *gts)
+static int is_gts_stealable(struct gru_thread_state *gts,
+		struct gru_blade_state *bs)
+{
+	if (is_kernel_context(gts))
+		return down_write_trylock(&bs->bs_kgts_sema);
+	else
+		return mutex_trylock(&gts->ts_ctxlock);
+}
+
+static void gts_stolen(struct gru_thread_state *gts,
+		struct gru_blade_state *bs)
+{
+	if (is_kernel_context(gts)) {
+		up_write(&bs->bs_kgts_sema);
+		STAT(steal_kernel_context);
+	} else {
+		mutex_unlock(&gts->ts_ctxlock);
+		STAT(steal_user_context);
+	}
+}
+
+void gru_steal_context(struct gru_thread_state *gts, int blade_id)
 {
 	struct gru_blade_state *blade;
 	struct gru_state *gru, *gru0;
@@ -652,8 +722,7 @@
 	cbr = gts->ts_cbr_au_count;
 	dsr = gts->ts_dsr_au_count;
 
-	preempt_disable();
-	blade = gru_base[uv_numa_blade_id()];
+	blade = gru_base[blade_id];
 	spin_lock(&blade->bs_lock);
 
 	ctxnum = next_ctxnum(blade->bs_lru_ctxnum);
@@ -676,7 +745,7 @@
 			 * success are high. If trylock fails, try to steal a
 			 * different GSEG.
 			 */
-			if (ngts && mutex_trylock(&ngts->ts_ctxlock))
+			if (ngts && is_gts_stealable(ngts, blade))
 				break;
 			ngts = NULL;
 			flag = 1;
@@ -690,13 +759,12 @@
 	blade->bs_lru_gru = gru;
 	blade->bs_lru_ctxnum = ctxnum;
 	spin_unlock(&blade->bs_lock);
-	preempt_enable();
 
 	if (ngts) {
-		STAT(steal_context);
+		gts->ustats.context_stolen++;
 		ngts->ts_steal_jiffies = jiffies;
-		gru_unload_context(ngts, 1);
-		mutex_unlock(&ngts->ts_ctxlock);
+		gru_unload_context(ngts, is_kernel_context(ngts) ? 0 : 1);
+		gts_stolen(ngts, blade);
 	} else {
 		STAT(steal_context_failed);
 	}
@@ -710,17 +778,17 @@
 /*
  * Scan the GRUs on the local blade & assign a GRU context.
  */
-static struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts)
+struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts,
+						int blade)
 {
 	struct gru_state *gru, *grux;
 	int i, max_active_contexts;
 
-	preempt_disable();
 
 again:
 	gru = NULL;
 	max_active_contexts = GRU_NUM_CCH;
-	for_each_gru_on_blade(grux, uv_numa_blade_id(), i) {
+	for_each_gru_on_blade(grux, blade, i) {
 		if (check_gru_resources(grux, gts->ts_cbr_au_count,
 					gts->ts_dsr_au_count,
 					max_active_contexts)) {
@@ -760,7 +828,6 @@
 		STAT(assign_context_failed);
 	}
 
-	preempt_enable();
 	return gru;
 }
 
@@ -775,6 +842,7 @@
 {
 	struct gru_thread_state *gts;
 	unsigned long paddr, vaddr;
+	int blade_id;
 
 	vaddr = (unsigned long)vmf->virtual_address;
 	gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n",
@@ -789,8 +857,10 @@
 again:
 	mutex_lock(&gts->ts_ctxlock);
 	preempt_disable();
+	blade_id = uv_numa_blade_id();
+
 	if (gts->ts_gru) {
-		if (gts->ts_gru->gs_blade_id != uv_numa_blade_id()) {
+		if (gts->ts_gru->gs_blade_id != blade_id) {
 			STAT(migrated_nopfn_unload);
 			gru_unload_context(gts, 1);
 		} else {
@@ -800,12 +870,15 @@
 	}
 
 	if (!gts->ts_gru) {
-		if (!gru_assign_gru_context(gts)) {
-			mutex_unlock(&gts->ts_ctxlock);
+		STAT(load_user_context);
+		if (!gru_assign_gru_context(gts, blade_id)) {
 			preempt_enable();
+			mutex_unlock(&gts->ts_ctxlock);
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(GRU_ASSIGN_DELAY);  /* true hack ZZZ */
+			blade_id = uv_numa_blade_id();
 			if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies)
-				gru_steal_context(gts);
+				gru_steal_context(gts, blade_id);
 			goto again;
 		}
 		gru_load_context(gts);
@@ -815,8 +888,8 @@
 				vma->vm_page_prot);
 	}
 
-	mutex_unlock(&gts->ts_ctxlock);
 	preempt_enable();
+	mutex_unlock(&gts->ts_ctxlock);
 
 	return VM_FAULT_NOPAGE;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gruprocfs.c linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gruprocfs.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/gruprocfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/gruprocfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,9 +51,12 @@
 	printstat(s, assign_context);
 	printstat(s, assign_context_failed);
 	printstat(s, free_context);
-	printstat(s, load_context);
-	printstat(s, unload_context);
-	printstat(s, steal_context);
+	printstat(s, load_user_context);
+	printstat(s, load_kernel_context);
+	printstat(s, lock_kernel_context);
+	printstat(s, unlock_kernel_context);
+	printstat(s, steal_user_context);
+	printstat(s, steal_kernel_context);
 	printstat(s, steal_context_failed);
 	printstat(s, nopfn);
 	printstat(s, break_cow);
@@ -70,7 +73,7 @@
 	printstat(s, user_flush_tlb);
 	printstat(s, user_unload_context);
 	printstat(s, user_exception);
-	printstat(s, set_task_slice);
+	printstat(s, set_context_option);
 	printstat(s, migrate_check);
 	printstat(s, migrated_retarget);
 	printstat(s, migrated_unload);
@@ -84,6 +87,9 @@
 	printstat(s, tlb_dropin_fail_range_active);
 	printstat(s, tlb_dropin_fail_idle);
 	printstat(s, tlb_dropin_fail_fmm);
+	printstat(s, tlb_dropin_fail_no_exception);
+	printstat(s, tlb_dropin_fail_no_exception_war);
+	printstat(s, tfh_stale_on_fault);
 	printstat(s, mmu_invalidate_range);
 	printstat(s, mmu_invalidate_page);
 	printstat(s, mmu_clear_flush_young);
@@ -158,8 +164,7 @@
 	unsigned long val;
 	char buf[80];
 
-	if (copy_from_user
-	    (buf, userbuf, count < sizeof(buf) ? count : sizeof(buf)))
+	if (strncpy_from_user(buf, userbuf, sizeof(buf) - 1) < 0)
 		return -EFAULT;
 	buf[count - 1] = '\0';
 	if (!strict_strtoul(buf, 10, &val))
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grutables.h linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grutables.h
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/grutables.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/grutables.h	2009-09-09 18:13:59.000000000 -0400
@@ -148,11 +148,13 @@
 #include <linux/wait.h>
 #include <linux/mmu_notifier.h>
 #include "gru.h"
+#include "grulib.h"
 #include "gruhandles.h"
 
 extern struct gru_stats_s gru_stats;
 extern struct gru_blade_state *gru_base[];
 extern unsigned long gru_start_paddr, gru_end_paddr;
+extern void *gru_start_vaddr;
 extern unsigned int gru_max_gids;
 
 #define GRU_MAX_BLADES		MAX_NUMNODES
@@ -174,9 +176,12 @@
 	atomic_long_t assign_context;
 	atomic_long_t assign_context_failed;
 	atomic_long_t free_context;
-	atomic_long_t load_context;
-	atomic_long_t unload_context;
-	atomic_long_t steal_context;
+	atomic_long_t load_user_context;
+	atomic_long_t load_kernel_context;
+	atomic_long_t lock_kernel_context;
+	atomic_long_t unlock_kernel_context;
+	atomic_long_t steal_user_context;
+	atomic_long_t steal_kernel_context;
 	atomic_long_t steal_context_failed;
 	atomic_long_t nopfn;
 	atomic_long_t break_cow;
@@ -193,7 +198,7 @@
 	atomic_long_t user_flush_tlb;
 	atomic_long_t user_unload_context;
 	atomic_long_t user_exception;
-	atomic_long_t set_task_slice;
+	atomic_long_t set_context_option;
 	atomic_long_t migrate_check;
 	atomic_long_t migrated_retarget;
 	atomic_long_t migrated_unload;
@@ -207,6 +212,9 @@
 	atomic_long_t tlb_dropin_fail_range_active;
 	atomic_long_t tlb_dropin_fail_idle;
 	atomic_long_t tlb_dropin_fail_fmm;
+	atomic_long_t tlb_dropin_fail_no_exception;
+	atomic_long_t tlb_dropin_fail_no_exception_war;
+	atomic_long_t tfh_stale_on_fault;
 	atomic_long_t mmu_invalidate_range;
 	atomic_long_t mmu_invalidate_page;
 	atomic_long_t mmu_clear_flush_young;
@@ -253,7 +261,6 @@
 
 #define OPT_DPRINT	1
 #define OPT_STATS	2
-#define GRU_QUICKLOOK	4
 
 
 #define IRQ_GRU			110	/* Starting IRQ number for interrupts */
@@ -373,6 +380,7 @@
 						   required for contest */
 	unsigned char		ts_cbr_au_count;/* Number of CBR resources
 						   required for contest */
+	char			ts_cch_req_slice;/* CCH packet slice */
 	char			ts_blade;	/* If >= 0, migrate context if
 						   ref from diferent blade */
 	char			ts_force_cch_reload;
@@ -380,6 +388,9 @@
 						   after migration */
 	char			ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each
 							  allocated CB */
+	int			ts_data_valid;	/* Indicates if ts_gdata has
+						   valid data */
+	struct gts_statistics	ustats;		/* User statistics */
 	unsigned long		ts_gdata[0];	/* save area for GRU data (CB,
 						   DS, CBE) */
 };
@@ -452,6 +463,14 @@
 							   reserved cb */
 	void			*kernel_dsr;		/* First kernel
 							   reserved DSR */
+	struct rw_semaphore	bs_kgts_sema;		/* lock for kgts */
+	struct gru_thread_state *bs_kgts;		/* GTS for kernel use */
+
+	/* ---- the following are used for managing kernel async GRU CBRs --- */
+	int			bs_async_dsr_bytes;	/* DSRs for async */
+	int			bs_async_cbrs;		/* CBRs AU for async */
+	struct completion	*bs_async_wq;
+
 	/* ---- the following are protected by the bs_lock spinlock ---- */
 	spinlock_t		bs_lock;		/* lock used for
 							   stealing contexts */
@@ -552,6 +571,12 @@
 
 /* Lock hierarchy checking enabled only in emulator */
 
+/* 0 = lock failed, 1 = locked */
+static inline int __trylock_handle(void *h)
+{
+	return !test_and_set_bit(1, h);
+}
+
 static inline void __lock_handle(void *h)
 {
 	while (test_and_set_bit(1, h))
@@ -563,6 +588,11 @@
 	clear_bit(1, h);
 }
 
+static inline int trylock_cch_handle(struct gru_context_configuration_handle *cch)
+{
+	return __trylock_handle(cch);
+}
+
 static inline void lock_cch_handle(struct gru_context_configuration_handle *cch)
 {
 	__lock_handle(cch);
@@ -584,6 +614,11 @@
 	__unlock_handle(tgh);
 }
 
+static inline int is_kernel_context(struct gru_thread_state *gts)
+{
+	return !gts->ts_mm;
+}
+
 /*-----------------------------------------------------------------------------
  * Function prototypes & externs
  */
@@ -598,24 +633,32 @@
 				*vma, int tsid);
 extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct
 				*vma, int tsid);
+extern struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts,
+		int blade);
+extern void gru_load_context(struct gru_thread_state *gts);
+extern void gru_steal_context(struct gru_thread_state *gts, int blade_id);
 extern void gru_unload_context(struct gru_thread_state *gts, int savestate);
 extern int gru_update_cch(struct gru_thread_state *gts, int force_unload);
 extern void gts_drop(struct gru_thread_state *gts);
 extern void gru_tgh_flush_init(struct gru_state *gru);
-extern int gru_kservices_init(struct gru_state *gru);
-extern void gru_kservices_exit(struct gru_state *gru);
+extern int gru_kservices_init(void);
+extern void gru_kservices_exit(void);
+extern int gru_dump_chiplet_request(unsigned long arg);
+extern long gru_get_gseg_statistics(unsigned long arg);
 extern irqreturn_t gru_intr(int irq, void *dev_id);
 extern int gru_handle_user_call_os(unsigned long address);
 extern int gru_user_flush_tlb(unsigned long arg);
 extern int gru_user_unload_context(unsigned long arg);
 extern int gru_get_exception_detail(unsigned long arg);
-extern int gru_set_task_slice(long address);
+extern int gru_set_context_option(unsigned long address);
 extern int gru_cpu_fault_map_id(void);
 extern struct vm_area_struct *gru_find_vma(unsigned long vaddr);
 extern void gru_flush_all_tlb(struct gru_state *gru);
 extern int gru_proc_init(void);
 extern void gru_proc_exit(void);
 
+extern struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
+		int cbr_au_count, int dsr_au_count, int options, int tsid);
 extern unsigned long gru_reserve_cb_resources(struct gru_state *gru,
 		int cbr_au_count, char *cbmap);
 extern unsigned long gru_reserve_ds_resources(struct gru_state *gru,
@@ -624,6 +667,7 @@
 extern struct gru_mm_struct *gru_register_mmu_notifier(void);
 extern void gru_drop_mmu_notifier(struct gru_mm_struct *gms);
 
+extern int gru_ktest(unsigned long arg);
 extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start,
 					unsigned long len);
 
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/Makefile linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/Makefile
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-gru/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-gru/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,5 +3,5 @@
 endif
 
 obj-$(CONFIG_SGI_GRU) := gru.o
-gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o
+gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o grukdump.o
 
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-xp/xpc_uv.c linux-libre-2.6.31-gnu/drivers/misc/sgi-xp/xpc_uv.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-xp/xpc_uv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-xp/xpc_uv.c	2009-09-09 18:13:59.000000000 -0400
@@ -232,7 +232,7 @@
 	mq->mmr_blade = uv_cpu_to_blade_id(cpu);
 
 	nid = cpu_to_node(cpu);
-	page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+	page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
 				pg_order);
 	if (page == NULL) {
 		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
diff -druN linux-libre-2.6.30-gnu/drivers/misc/sgi-xp/xpnet.c linux-libre-2.6.31-gnu/drivers/misc/sgi-xp/xpnet.c
--- linux-libre-2.6.30-gnu/drivers/misc/sgi-xp/xpnet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/misc/sgi-xp/xpnet.c	2009-09-09 18:13:59.000000000 -0400
@@ -235,7 +235,7 @@
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	dev_dbg(xpnet, "passing skb to network layer\n"
-		KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+		"\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
 		"skb->end=0x%p skb->len=%d\n",
 		(void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
 		skb_end_pointer(skb), skb->len);
@@ -399,7 +399,7 @@
 	msg->buf_pa = xp_pa((void *)start_addr);
 
 	dev_dbg(xpnet, "sending XPC message to %d:%d\n"
-		KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
+		"msg->buf_pa=0x%lx, msg->size=%u, "
 		"msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
 		dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
 		msg->leadin_ignore, msg->tailout_ignore);
@@ -450,7 +450,8 @@
 			 "packet\n", sizeof(struct xpnet_pending_msg));
 
 		dev->stats.tx_errors++;
-		return -ENOMEM;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
 	}
 
 	/* get the beginning of the first cacheline and end of last */
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/card/block.c linux-libre-2.6.31-gnu/drivers/mmc/card/block.c
--- linux-libre-2.6.30-gnu/drivers/mmc/card/block.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/card/block.c	2009-09-09 18:13:59.000000000 -0400
@@ -147,7 +147,8 @@
 static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 {
 	int err;
-	__be32 blocks;
+	u32 result;
+	__be32 *blocks;
 
 	struct mmc_request mrq;
 	struct mmc_command cmd;
@@ -199,14 +200,21 @@
 	mrq.cmd = &cmd;
 	mrq.data = &data;
 
-	sg_init_one(&sg, &blocks, 4);
+	blocks = kmalloc(4, GFP_KERNEL);
+	if (!blocks)
+		return (u32)-1;
+
+	sg_init_one(&sg, blocks, 4);
 
 	mmc_wait_for_req(card->host, &mrq);
 
+	result = ntohl(*blocks);
+	kfree(blocks);
+
 	if (cmd.error || data.error)
-		return (u32)-1;
+		result = (u32)-1;
 
-	return ntohl(blocks);
+	return result;
 }
 
 static u32 get_card_status(struct mmc_card *card, struct request *req)
@@ -243,7 +251,7 @@
 		brq.mrq.cmd = &brq.cmd;
 		brq.mrq.data = &brq.data;
 
-		brq.cmd.arg = req->sector;
+		brq.cmd.arg = blk_rq_pos(req);
 		if (!mmc_card_blockaddr(card))
 			brq.cmd.arg <<= 9;
 		brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -251,7 +259,7 @@
 		brq.stop.opcode = MMC_STOP_TRANSMISSION;
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-		brq.data.blocks = req->nr_sectors;
+		brq.data.blocks = blk_rq_sectors(req);
 
 		/*
 		 * The block layer doesn't support all sector count
@@ -301,7 +309,7 @@
 		 * Adjust the sg list so it is the same size as the
 		 * request.
 		 */
-		if (brq.data.blocks != req->nr_sectors) {
+		if (brq.data.blocks != blk_rq_sectors(req)) {
 			int i, data_size = brq.data.blocks << 9;
 			struct scatterlist *sg;
 
@@ -352,8 +360,8 @@
 			printk(KERN_ERR "%s: error %d transferring data,"
 			       " sector %u, nr %u, card status %#x\n",
 			       req->rq_disk->disk_name, brq.data.error,
-			       (unsigned)req->sector,
-			       (unsigned)req->nr_sectors, status);
+			       (unsigned)blk_rq_pos(req),
+			       (unsigned)blk_rq_sectors(req), status);
 		}
 
 		if (brq.stop.error) {
@@ -521,7 +529,7 @@
 
 	sprintf(md->disk->disk_name, "mmcblk%d", devidx);
 
-	blk_queue_hardsect_size(md->queue.queue, 512);
+	blk_queue_logical_block_size(md->queue.queue, 512);
 
 	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
 		/*
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/card/queue.c linux-libre-2.6.31-gnu/drivers/mmc/card/queue.c
--- linux-libre-2.6.30-gnu/drivers/mmc/card/queue.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/card/queue.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,7 +55,7 @@
 		spin_lock_irq(q->queue_lock);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (!blk_queue_plugged(q))
-			req = elv_next_request(q);
+			req = blk_fetch_request(q);
 		mq->req = req;
 		spin_unlock_irq(q->queue_lock);
 
@@ -88,16 +88,11 @@
 {
 	struct mmc_queue *mq = q->queuedata;
 	struct request *req;
-	int ret;
 
 	if (!mq) {
 		printk(KERN_ERR "MMC: killing requests for dead queue\n");
-		while ((req = elv_next_request(q)) != NULL) {
-			do {
-				ret = __blk_end_request(req, -EIO,
-							blk_rq_cur_bytes(req));
-			} while (ret);
-		}
+		while ((req = blk_fetch_request(q)) != NULL)
+			__blk_end_request_all(req, -EIO);
 		return;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/core/core.c linux-libre-2.6.31-gnu/drivers/mmc/core/core.c
--- linux-libre-2.6.30-gnu/drivers/mmc/core/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/core/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -708,7 +708,13 @@
 	 */
 	mmc_delay(10);
 
-	host->ios.clock = host->f_min;
+	if (host->f_min > 400000) {
+		pr_warning("%s: Minimum clock frequency too high for "
+				"identification mode\n", mmc_hostname(host));
+		host->ios.clock = host->f_min;
+	} else
+		host->ios.clock = 400000;
+
 	host->ios.power_mode = MMC_POWER_ON;
 	mmc_set_ios(host);
 
@@ -855,61 +861,72 @@
 
 	mmc_bus_get(host);
 
-	if (host->bus_ops == NULL) {
-		/*
-		 * Only we can add a new handler, so it's safe to
-		 * release the lock here.
-		 */
+	/* if there is a card registered, check whether it is still present */
+	if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead)
+		host->bus_ops->detect(host);
+
+	mmc_bus_put(host);
+
+
+	mmc_bus_get(host);
+
+	/* if there still is a card present, stop here */
+	if (host->bus_ops != NULL) {
 		mmc_bus_put(host);
+		goto out;
+	}
 
-		if (host->ops->get_cd && host->ops->get_cd(host) == 0)
-			goto out;
+	/* detect a newly inserted card */
 
-		mmc_claim_host(host);
+	/*
+	 * Only we can add a new handler, so it's safe to
+	 * release the lock here.
+	 */
+	mmc_bus_put(host);
 
-		mmc_power_up(host);
-		mmc_go_idle(host);
+	if (host->ops->get_cd && host->ops->get_cd(host) == 0)
+		goto out;
 
-		mmc_send_if_cond(host, host->ocr_avail);
+	mmc_claim_host(host);
 
-		/*
-		 * First we search for SDIO...
-		 */
-		err = mmc_send_io_op_cond(host, 0, &ocr);
-		if (!err) {
-			if (mmc_attach_sdio(host, ocr))
-				mmc_power_off(host);
-			goto out;
-		}
+	mmc_power_up(host);
+	mmc_go_idle(host);
 
-		/*
-		 * ...then normal SD...
-		 */
-		err = mmc_send_app_op_cond(host, 0, &ocr);
-		if (!err) {
-			if (mmc_attach_sd(host, ocr))
-				mmc_power_off(host);
-			goto out;
-		}
+	mmc_send_if_cond(host, host->ocr_avail);
 
-		/*
-		 * ...and finally MMC.
-		 */
-		err = mmc_send_op_cond(host, 0, &ocr);
-		if (!err) {
-			if (mmc_attach_mmc(host, ocr))
-				mmc_power_off(host);
-			goto out;
-		}
+	/*
+	 * First we search for SDIO...
+	 */
+	err = mmc_send_io_op_cond(host, 0, &ocr);
+	if (!err) {
+		if (mmc_attach_sdio(host, ocr))
+			mmc_power_off(host);
+		goto out;
+	}
 
-		mmc_release_host(host);
-		mmc_power_off(host);
-	} else {
-		if (host->bus_ops->detect && !host->bus_dead)
-			host->bus_ops->detect(host);
+	/*
+	 * ...then normal SD...
+	 */
+	err = mmc_send_app_op_cond(host, 0, &ocr);
+	if (!err) {
+		if (mmc_attach_sd(host, ocr))
+			mmc_power_off(host);
+		goto out;
+	}
 
-		mmc_bus_put(host);
+	/*
+	 * ...and finally MMC.
+	 */
+	err = mmc_send_op_cond(host, 0, &ocr);
+	if (!err) {
+		if (mmc_attach_mmc(host, ocr))
+			mmc_power_off(host);
+		goto out;
 	}
+
+	mmc_release_host(host);
+	mmc_power_off(host);
+
 out:
 	if (host->caps & MMC_CAP_NEEDS_POLL)
 		mmc_schedule_delayed_work(&host->detect, HZ);
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/atmel-mci.c linux-libre-2.6.31-gnu/drivers/mmc/host/atmel-mci.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/atmel-mci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/atmel-mci.c	2009-09-09 18:13:59.000000000 -0400
@@ -177,6 +177,7 @@
  *	available.
  * @wp_pin: GPIO pin used for card write protect sending, or negative
  *	if not available.
+ * @detect_is_active_high: The state of the detect pin when it is active.
  * @detect_timer: Timer used for debouncing @detect_pin interrupts.
  */
 struct atmel_mci_slot {
@@ -196,6 +197,7 @@
 
 	int			detect_pin;
 	int			wp_pin;
+	bool			detect_is_active_high;
 
 	struct timer_list	detect_timer;
 };
@@ -924,7 +926,8 @@
 	struct atmel_mci_slot	*slot = mmc_priv(mmc);
 
 	if (gpio_is_valid(slot->detect_pin)) {
-		present = !gpio_get_value(slot->detect_pin);
+		present = !(gpio_get_value(slot->detect_pin) ^
+			    slot->detect_is_active_high);
 		dev_dbg(&mmc->class_dev, "card is %spresent\n",
 				present ? "" : "not ");
 	}
@@ -1028,7 +1031,8 @@
 		return;
 
 	enable_irq(gpio_to_irq(slot->detect_pin));
-	present = !gpio_get_value(slot->detect_pin);
+	present = !(gpio_get_value(slot->detect_pin) ^
+		    slot->detect_is_active_high);
 	present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags);
 
 	dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n",
@@ -1456,6 +1460,7 @@
 	slot->host = host;
 	slot->detect_pin = slot_data->detect_pin;
 	slot->wp_pin = slot_data->wp_pin;
+	slot->detect_is_active_high = slot_data->detect_is_active_high;
 	slot->sdc_reg = sdc_reg;
 
 	mmc->ops = &atmci_ops;
@@ -1477,7 +1482,8 @@
 		if (gpio_request(slot->detect_pin, "mmc_detect")) {
 			dev_dbg(&mmc->class_dev, "no detect pin available\n");
 			slot->detect_pin = -EBUSY;
-		} else if (gpio_get_value(slot->detect_pin)) {
+		} else if (gpio_get_value(slot->detect_pin) ^
+				slot->detect_is_active_high) {
 			clear_bit(ATMCI_CARD_PRESENT, &slot->flags);
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/atmel-mci-regs.h linux-libre-2.6.31-gnu/drivers/mmc/host/atmel-mci-regs.h
--- linux-libre-2.6.30-gnu/drivers/mmc/host/atmel-mci-regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/atmel-mci-regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -7,6 +7,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+/*
+ * Superset of MCI IP registers integrated in Atmel AVR32 and AT91 Processors
+ * Registers and bitfields marked with [2] are only available in MCI2
+ */
+
 #ifndef __DRIVERS_MMC_ATMEL_MCI_H__
 #define __DRIVERS_MMC_ATMEL_MCI_H__
 
@@ -14,11 +20,17 @@
 #define MCI_CR			0x0000	/* Control */
 # define MCI_CR_MCIEN		(  1 <<  0)	/* MCI Enable */
 # define MCI_CR_MCIDIS		(  1 <<  1)	/* MCI Disable */
+# define MCI_CR_PWSEN		(  1 <<  2)	/* Power Save Enable */
+# define MCI_CR_PWSDIS		(  1 <<  3)	/* Power Save Disable */
 # define MCI_CR_SWRST		(  1 <<  7)	/* Software Reset */
 #define MCI_MR			0x0004	/* Mode */
 # define MCI_MR_CLKDIV(x)	((x) <<  0)	/* Clock Divider */
+# define MCI_MR_PWSDIV(x)	((x) <<  8)	/* Power Saving Divider */
 # define MCI_MR_RDPROOF		(  1 << 11)	/* Read Proof */
 # define MCI_MR_WRPROOF		(  1 << 12)	/* Write Proof */
+# define MCI_MR_PDCFBYTE	(  1 << 13)	/* Force Byte Transfer */
+# define MCI_MR_PDCPADV		(  1 << 14)	/* Padding Value */
+# define MCI_MR_PDCMODE		(  1 << 15)	/* PDC-oriented Mode */
 #define MCI_DTOR		0x0008	/* Data Timeout */
 # define MCI_DTOCYC(x)		((x) <<  0)	/* Data Timeout Cycles */
 # define MCI_DTOMUL(x)		((x) <<  4)	/* Data Timeout Multiplier */
@@ -28,6 +40,7 @@
 # define MCI_SDCSEL_MASK	(  3 <<  0)
 # define MCI_SDCBUS_1BIT	(  0 <<  6)	/* 1-bit data bus */
 # define MCI_SDCBUS_4BIT	(  2 <<  6)	/* 4-bit data bus */
+# define MCI_SDCBUS_8BIT	(  3 <<  6)	/* 8-bit data bus[2] */
 # define MCI_SDCBUS_MASK	(  3 <<  6)
 #define MCI_ARGR		0x0010	/* Command Argument */
 #define MCI_CMDR		0x0014	/* Command */
@@ -56,6 +69,9 @@
 #define MCI_BLKR		0x0018	/* Block */
 # define MCI_BCNT(x)		((x) <<  0)	/* Data Block Count */
 # define MCI_BLKLEN(x)		((x) << 16)	/* Data Block Length */
+#define MCI_CSTOR		0x001c	/* Completion Signal Timeout[2] */
+# define MCI_CSTOCYC(x)		((x) <<  0)	/* CST cycles */
+# define MCI_CSTOMUL(x)		((x) <<  4)	/* CST multiplier */
 #define MCI_RSPR		0x0020	/* Response 0 */
 #define MCI_RSPR1		0x0024	/* Response 1 */
 #define MCI_RSPR2		0x0028	/* Response 2 */
@@ -83,7 +99,24 @@
 # define MCI_DTOE		(  1 <<  22)	/* Data Time-Out Error */
 # define MCI_OVRE		(  1 <<  30)	/* RX Overrun Error */
 # define MCI_UNRE		(  1 <<  31)	/* TX Underrun Error */
+#define MCI_DMA			0x0050	/* DMA Configuration[2] */
+# define MCI_DMA_OFFSET(x)	((x) <<  0)	/* DMA Write Buffer Offset */
+# define MCI_DMA_CHKSIZE(x)	((x) <<  4)	/* DMA Channel Read and Write Chunk Size */
+# define MCI_DMAEN		(  1 <<  8)	/* DMA Hardware Handshaking Enable */
+#define MCI_CFG			0x0054	/* Configuration[2] */
+# define MCI_CFG_FIFOMODE_1DATA	(  1 <<  0)	/* MCI Internal FIFO control mode */
+# define MCI_CFG_FERRCTRL_COR	(  1 <<  4)	/* Flow Error flag reset control mode */
+# define MCI_CFG_HSMODE		(  1 <<  8)	/* High Speed Mode */
+# define MCI_CFG_LSYNC		(  1 << 12)	/* Synchronize on the last block */
+#define MCI_WPMR		0x00e4	/* Write Protection Mode[2] */
+# define MCI_WP_EN		(  1 <<  0)	/* WP Enable */
+# define MCI_WP_KEY		(0x4d4349 << 8)	/* WP Key */
+#define MCI_WPSR		0x00e8	/* Write Protection Status[2] */
+# define MCI_GET_WP_VS(x)	((x) & 0x0f)
+# define MCI_GET_WP_VSRC(x)	(((x) >> 8) & 0xffff)
+#define MCI_FIFO_APERTURE	0x0200	/* FIFO Aperture[2] */
 
+/* This is not including the FIFO Aperture on MCI2 */
 #define MCI_REGS_SIZE		0x100
 
 /* Register access macros */
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/cb710-mmc.c linux-libre-2.6.31-gnu/drivers/mmc/host/cb710-mmc.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/cb710-mmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/cb710-mmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,804 @@
+/*
+ *  cb710/mmc.c
+ *
+ *  Copyright by Michał Mirosław, 2008-2009
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include "cb710-mmc.h"
+
+static const u8 cb710_clock_divider_log2[8] = {
+/*	1, 2, 4, 8, 16, 32, 128, 512 */
+	0, 1, 2, 3,  4,  5,   7,   9
+};
+#define CB710_MAX_DIVIDER_IDX	\
+	(ARRAY_SIZE(cb710_clock_divider_log2) - 1)
+
+static const u8 cb710_src_freq_mhz[16] = {
+	33, 10, 20, 25, 30, 35, 40, 45,
+	50, 55, 60, 65, 70, 75, 80, 85
+};
+
+static void cb710_mmc_set_clock(struct mmc_host *mmc, int hz)
+{
+	struct cb710_slot *slot = cb710_mmc_to_slot(mmc);
+	struct pci_dev *pdev = cb710_slot_to_chip(slot)->pdev;
+	u32 src_freq_idx;
+	u32 divider_idx;
+	int src_hz;
+
+	/* this is magic, unverifiable for me, unless I get
+	 * MMC card with cables connected to bus signals */
+	pci_read_config_dword(pdev, 0x48, &src_freq_idx);
+	src_freq_idx = (src_freq_idx >> 16) & 0xF;
+	src_hz = cb710_src_freq_mhz[src_freq_idx] * 1000000;
+
+	for (divider_idx = 0; divider_idx < CB710_MAX_DIVIDER_IDX; ++divider_idx) {
+		if (hz >= src_hz >> cb710_clock_divider_log2[divider_idx])
+			break;
+	}
+
+	if (src_freq_idx)
+		divider_idx |= 0x8;
+
+	cb710_pci_update_config_reg(pdev, 0x40, ~0xF0000000, divider_idx << 28);
+
+	dev_dbg(cb710_slot_dev(slot),
+		"clock set to %d Hz, wanted %d Hz; flag = %d\n",
+		src_hz >> cb710_clock_divider_log2[divider_idx & 7],
+		hz, (divider_idx & 8) != 0);
+}
+
+static void __cb710_mmc_enable_irq(struct cb710_slot *slot,
+	unsigned short enable, unsigned short mask)
+{
+	/* clear global IE
+	 * - it gets set later if any interrupt sources are enabled */
+	mask |= CB710_MMC_IE_IRQ_ENABLE;
+
+	/* look like interrupt is fired whenever
+	 * WORD[0x0C] & WORD[0x10] != 0;
+	 * -> bit 15 port 0x0C seems to be global interrupt enable
+	 */
+
+	enable = (cb710_read_port_16(slot, CB710_MMC_IRQ_ENABLE_PORT)
+		& ~mask) | enable;
+
+	if (enable)
+		enable |= CB710_MMC_IE_IRQ_ENABLE;
+
+	cb710_write_port_16(slot, CB710_MMC_IRQ_ENABLE_PORT, enable);
+}
+
+static void cb710_mmc_enable_irq(struct cb710_slot *slot,
+	unsigned short enable, unsigned short mask)
+{
+	struct cb710_mmc_reader *reader = mmc_priv(cb710_slot_to_mmc(slot));
+	unsigned long flags;
+
+	spin_lock_irqsave(&reader->irq_lock, flags);
+	/* this is the only thing irq_lock protects */
+	__cb710_mmc_enable_irq(slot, enable, mask);
+	spin_unlock_irqrestore(&reader->irq_lock, flags);
+}
+
+static void cb710_mmc_reset_events(struct cb710_slot *slot)
+{
+	cb710_write_port_8(slot, CB710_MMC_STATUS0_PORT, 0xFF);
+	cb710_write_port_8(slot, CB710_MMC_STATUS1_PORT, 0xFF);
+	cb710_write_port_8(slot, CB710_MMC_STATUS2_PORT, 0xFF);
+}
+
+static int cb710_mmc_is_card_inserted(struct cb710_slot *slot)
+{
+	return cb710_read_port_8(slot, CB710_MMC_STATUS3_PORT)
+		& CB710_MMC_S3_CARD_DETECTED;
+}
+
+static void cb710_mmc_enable_4bit_data(struct cb710_slot *slot, int enable)
+{
+	dev_dbg(cb710_slot_dev(slot), "configuring %d-data-line%s mode\n",
+		enable ? 4 : 1, enable ? "s" : "");
+	if (enable)
+		cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT,
+			CB710_MMC_C1_4BIT_DATA_BUS, 0);
+	else
+		cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT,
+			0, CB710_MMC_C1_4BIT_DATA_BUS);
+}
+
+static int cb710_check_event(struct cb710_slot *slot, u8 what)
+{
+	u16 status;
+
+	status = cb710_read_port_16(slot, CB710_MMC_STATUS_PORT);
+
+	if (status & CB710_MMC_S0_FIFO_UNDERFLOW) {
+		/* it is just a guess, so log it */
+		dev_dbg(cb710_slot_dev(slot),
+			"CHECK : ignoring bit 6 in status %04X\n", status);
+		cb710_write_port_8(slot, CB710_MMC_STATUS0_PORT,
+			CB710_MMC_S0_FIFO_UNDERFLOW);
+		status &= ~CB710_MMC_S0_FIFO_UNDERFLOW;
+	}
+
+	if (status & CB710_MMC_STATUS_ERROR_EVENTS) {
+		dev_dbg(cb710_slot_dev(slot),
+			"CHECK : returning EIO on status %04X\n", status);
+		cb710_write_port_8(slot, CB710_MMC_STATUS0_PORT, status & 0xFF);
+		cb710_write_port_8(slot, CB710_MMC_STATUS1_PORT,
+			CB710_MMC_S1_RESET);
+		return -EIO;
+	}
+
+	/* 'what' is a bit in MMC_STATUS1 */
+	if ((status >> 8) & what) {
+		cb710_write_port_8(slot, CB710_MMC_STATUS1_PORT, what);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int cb710_wait_for_event(struct cb710_slot *slot, u8 what)
+{
+	int err = 0;
+	unsigned limit = 2000000;	/* FIXME: real timeout */
+
+#ifdef CONFIG_CB710_DEBUG
+	u32 e, x;
+	e = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT);
+#endif
+
+	while (!(err = cb710_check_event(slot, what))) {
+		if (!--limit) {
+			cb710_dump_regs(cb710_slot_to_chip(slot),
+				CB710_DUMP_REGS_MMC);
+			err = -ETIMEDOUT;
+			break;
+		}
+		udelay(1);
+	}
+
+#ifdef CONFIG_CB710_DEBUG
+	x = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT);
+
+	limit = 2000000 - limit;
+	if (limit > 100)
+		dev_dbg(cb710_slot_dev(slot),
+			"WAIT10: waited %d loops, what %d, entry val %08X, exit val %08X\n",
+			limit, what, e, x);
+#endif
+	return err < 0 ? err : 0;
+}
+
+
+static int cb710_wait_while_busy(struct cb710_slot *slot, uint8_t mask)
+{
+	unsigned limit = 500000;	/* FIXME: real timeout */
+	int err = 0;
+
+#ifdef CONFIG_CB710_DEBUG
+	u32 e, x;
+	e = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT);
+#endif
+
+	while (cb710_read_port_8(slot, CB710_MMC_STATUS2_PORT) & mask) {
+		if (!--limit) {
+			cb710_dump_regs(cb710_slot_to_chip(slot),
+				CB710_DUMP_REGS_MMC);
+			err = -ETIMEDOUT;
+			break;
+		}
+		udelay(1);
+	}
+
+#ifdef CONFIG_CB710_DEBUG
+	x = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT);
+
+	limit = 500000 - limit;
+	if (limit > 100)
+		dev_dbg(cb710_slot_dev(slot),
+			"WAIT12: waited %d loops, mask %02X, entry val %08X, exit val %08X\n",
+			limit, mask, e, x);
+#endif
+	return 0;
+}
+
+static void cb710_mmc_set_transfer_size(struct cb710_slot *slot,
+	size_t count, size_t blocksize)
+{
+	cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20);
+	cb710_write_port_32(slot, CB710_MMC_TRANSFER_SIZE_PORT,
+		((count - 1) << 16)|(blocksize - 1));
+
+	dev_vdbg(cb710_slot_dev(slot), "set up for %zu block%s of %zu bytes\n",
+		count, count == 1 ? "" : "s", blocksize);
+}
+
+static void cb710_mmc_fifo_hack(struct cb710_slot *slot)
+{
+	/* without this, received data is prepended with 8-bytes of zeroes */
+	u32 r1, r2;
+	int ok = 0;
+
+	r1 = cb710_read_port_32(slot, CB710_MMC_DATA_PORT);
+	r2 = cb710_read_port_32(slot, CB710_MMC_DATA_PORT);
+	if (cb710_read_port_8(slot, CB710_MMC_STATUS0_PORT)
+	    & CB710_MMC_S0_FIFO_UNDERFLOW) {
+		cb710_write_port_8(slot, CB710_MMC_STATUS0_PORT,
+			CB710_MMC_S0_FIFO_UNDERFLOW);
+		ok = 1;
+	}
+
+	dev_dbg(cb710_slot_dev(slot),
+		"FIFO-read-hack: expected STATUS0 bit was %s\n",
+		ok ? "set." : "NOT SET!");
+	dev_dbg(cb710_slot_dev(slot),
+		"FIFO-read-hack: dwords ignored: %08X %08X - %s\n",
+		r1, r2, (r1|r2) ? "BAD (NOT ZERO)!" : "ok");
+}
+
+static int cb710_mmc_receive_pio(struct cb710_slot *slot,
+	struct sg_mapping_iter *miter, size_t dw_count)
+{
+	if (!(cb710_read_port_8(slot, CB710_MMC_STATUS2_PORT) & CB710_MMC_S2_FIFO_READY)) {
+		int err = cb710_wait_for_event(slot,
+			CB710_MMC_S1_PIO_TRANSFER_DONE);
+		if (err)
+			return err;
+	}
+
+	cb710_sg_dwiter_write_from_io(miter,
+		slot->iobase + CB710_MMC_DATA_PORT, dw_count);
+
+	return 0;
+}
+
+static bool cb710_is_transfer_size_supported(struct mmc_data *data)
+{
+	return !(data->blksz & 15 && (data->blocks != 1 || data->blksz != 8));
+}
+
+static int cb710_mmc_receive(struct cb710_slot *slot, struct mmc_data *data)
+{
+	struct sg_mapping_iter miter;
+	size_t len, blocks = data->blocks;
+	int err = 0;
+
+	/* TODO: I don't know how/if the hardware handles non-16B-boundary blocks
+	 * except single 8B block */
+	if (unlikely(data->blksz & 15 && (data->blocks != 1 || data->blksz != 8)))
+		return -EINVAL;
+
+	sg_miter_start(&miter, data->sg, data->sg_len, SG_MITER_TO_SG);
+
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG2_PORT,
+		15, CB710_MMC_C2_READ_PIO_SIZE_MASK);
+
+	cb710_mmc_fifo_hack(slot);
+
+	while (blocks-- > 0) {
+		len = data->blksz;
+
+		while (len >= 16) {
+			err = cb710_mmc_receive_pio(slot, &miter, 4);
+			if (err)
+				goto out;
+			len -= 16;
+		}
+
+		if (!len)
+			continue;
+
+		cb710_modify_port_8(slot, CB710_MMC_CONFIG2_PORT,
+			len - 1, CB710_MMC_C2_READ_PIO_SIZE_MASK);
+
+		len = (len >= 8) ? 4 : 2;
+		err = cb710_mmc_receive_pio(slot, &miter, len);
+		if (err)
+			goto out;
+	}
+out:
+	sg_miter_stop(&miter);
+	return err;
+}
+
+static int cb710_mmc_send(struct cb710_slot *slot, struct mmc_data *data)
+{
+	struct sg_mapping_iter miter;
+	size_t len, blocks = data->blocks;
+	int err = 0;
+
+	/* TODO: I don't know how/if the hardware handles multiple
+	 * non-16B-boundary blocks */
+	if (unlikely(data->blocks > 1 && data->blksz & 15))
+		return -EINVAL;
+
+	sg_miter_start(&miter, data->sg, data->sg_len, SG_MITER_FROM_SG);
+
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG2_PORT,
+		0, CB710_MMC_C2_READ_PIO_SIZE_MASK);
+
+	while (blocks-- > 0) {
+		len = (data->blksz + 15) >> 4;
+		do {
+			if (!(cb710_read_port_8(slot, CB710_MMC_STATUS2_PORT)
+			    & CB710_MMC_S2_FIFO_EMPTY)) {
+				err = cb710_wait_for_event(slot,
+					CB710_MMC_S1_PIO_TRANSFER_DONE);
+				if (err)
+					goto out;
+			}
+			cb710_sg_dwiter_read_to_io(&miter,
+				slot->iobase + CB710_MMC_DATA_PORT, 4);
+		} while (--len);
+	}
+out:
+	sg_miter_stop(&miter);
+	return err;
+}
+
+static u16 cb710_encode_cmd_flags(struct cb710_mmc_reader *reader,
+	struct mmc_command *cmd)
+{
+	unsigned int flags = cmd->flags;
+	u16 cb_flags = 0;
+
+	/* Windows driver returned 0 for commands for which no response
+	 * is expected. It happened that there were only two such commands
+	 * used: MMC_GO_IDLE_STATE and MMC_GO_INACTIVE_STATE so it might
+	 * as well be a bug in that driver.
+	 *
+	 * Original driver set bit 14 for MMC/SD application
+	 * commands. There's no difference 'on the wire' and
+	 * it apparently works without it anyway.
+	 */
+
+	switch (flags & MMC_CMD_MASK) {
+	case MMC_CMD_AC:	cb_flags = CB710_MMC_CMD_AC;	break;
+	case MMC_CMD_ADTC:	cb_flags = CB710_MMC_CMD_ADTC;	break;
+	case MMC_CMD_BC:	cb_flags = CB710_MMC_CMD_BC;	break;
+	case MMC_CMD_BCR:	cb_flags = CB710_MMC_CMD_BCR;	break;
+	}
+
+	if (flags & MMC_RSP_BUSY)
+		cb_flags |= CB710_MMC_RSP_BUSY;
+
+	cb_flags |= cmd->opcode << CB710_MMC_CMD_CODE_SHIFT;
+
+	if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
+		cb_flags |= CB710_MMC_DATA_READ;
+
+	if (flags & MMC_RSP_PRESENT) {
+		/* Windows driver set 01 at bits 4,3 except for
+		 * MMC_SET_BLOCKLEN where it set 10. Maybe the
+		 * hardware can do something special about this
+		 * command? The original driver looks buggy/incomplete
+		 * anyway so we ignore this for now.
+		 *
+		 * I assume that 00 here means no response is expected.
+		 */
+		cb_flags |= CB710_MMC_RSP_PRESENT;
+
+		if (flags & MMC_RSP_136)
+			cb_flags |= CB710_MMC_RSP_136;
+		if (!(flags & MMC_RSP_CRC))
+			cb_flags |= CB710_MMC_RSP_NO_CRC;
+	}
+
+	return cb_flags;
+}
+
+static void cb710_receive_response(struct cb710_slot *slot,
+	struct mmc_command *cmd)
+{
+	unsigned rsp_opcode, wanted_opcode;
+
+	/* Looks like final byte with CRC is always stripped (same as SDHCI) */
+	if (cmd->flags & MMC_RSP_136) {
+		u32 resp[4];
+
+		resp[0] = cb710_read_port_32(slot, CB710_MMC_RESPONSE3_PORT);
+		resp[1] = cb710_read_port_32(slot, CB710_MMC_RESPONSE2_PORT);
+		resp[2] = cb710_read_port_32(slot, CB710_MMC_RESPONSE1_PORT);
+		resp[3] = cb710_read_port_32(slot, CB710_MMC_RESPONSE0_PORT);
+		rsp_opcode = resp[0] >> 24;
+
+		cmd->resp[0] = (resp[0] << 8)|(resp[1] >> 24);
+		cmd->resp[1] = (resp[1] << 8)|(resp[2] >> 24);
+		cmd->resp[2] = (resp[2] << 8)|(resp[3] >> 24);
+		cmd->resp[3] = (resp[3] << 8);
+	} else {
+		rsp_opcode = cb710_read_port_32(slot, CB710_MMC_RESPONSE1_PORT) & 0x3F;
+		cmd->resp[0] = cb710_read_port_32(slot, CB710_MMC_RESPONSE0_PORT);
+	}
+
+	wanted_opcode = (cmd->flags & MMC_RSP_OPCODE) ? cmd->opcode : 0x3F;
+	if (rsp_opcode != wanted_opcode)
+		cmd->error = -EILSEQ;
+}
+
+static int cb710_mmc_transfer_data(struct cb710_slot *slot,
+	struct mmc_data *data)
+{
+	int error, to;
+
+	if (data->flags & MMC_DATA_READ)
+		error = cb710_mmc_receive(slot, data);
+	else
+		error = cb710_mmc_send(slot, data);
+
+	to = cb710_wait_for_event(slot, CB710_MMC_S1_DATA_TRANSFER_DONE);
+	if (!error)
+		error = to;
+
+	if (!error)
+		data->bytes_xfered = data->blksz * data->blocks;
+	return error;
+}
+
+static int cb710_mmc_command(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct cb710_slot *slot = cb710_mmc_to_slot(mmc);
+	struct cb710_mmc_reader *reader = mmc_priv(mmc);
+	struct mmc_data *data = cmd->data;
+
+	u16 cb_cmd = cb710_encode_cmd_flags(reader, cmd);
+	dev_dbg(cb710_slot_dev(slot), "cmd request: 0x%04X\n", cb_cmd);
+
+	if (data) {
+		if (!cb710_is_transfer_size_supported(data)) {
+			data->error = -EINVAL;
+			return -1;
+		}
+		cb710_mmc_set_transfer_size(slot, data->blocks, data->blksz);
+	}
+
+	cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20|CB710_MMC_S2_BUSY_10);
+	cb710_write_port_16(slot, CB710_MMC_CMD_TYPE_PORT, cb_cmd);
+	cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20);
+	cb710_write_port_32(slot, CB710_MMC_CMD_PARAM_PORT, cmd->arg);
+	cb710_mmc_reset_events(slot);
+	cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG0_PORT, 0x01, 0);
+
+	cmd->error = cb710_wait_for_event(slot, CB710_MMC_S1_COMMAND_SENT);
+	if (cmd->error)
+		return -1;
+
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		cb710_receive_response(slot, cmd);
+		if (cmd->error)
+			return -1;
+	}
+
+	if (data)
+		data->error = cb710_mmc_transfer_data(slot, data);
+	return 0;
+}
+
+static void cb710_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct cb710_slot *slot = cb710_mmc_to_slot(mmc);
+	struct cb710_mmc_reader *reader = mmc_priv(mmc);
+
+	WARN_ON(reader->mrq != NULL);
+
+	reader->mrq = mrq;
+	cb710_mmc_enable_irq(slot, CB710_MMC_IE_TEST_MASK, 0);
+
+	if (cb710_mmc_is_card_inserted(slot)) {
+		if (!cb710_mmc_command(mmc, mrq->cmd) && mrq->stop)
+			cb710_mmc_command(mmc, mrq->stop);
+		mdelay(1);
+	} else {
+		mrq->cmd->error = -ENOMEDIUM;
+	}
+
+	tasklet_schedule(&reader->finish_req_tasklet);
+}
+
+static int cb710_mmc_powerup(struct cb710_slot *slot)
+{
+#ifdef CONFIG_CB710_DEBUG
+	struct cb710_chip *chip = cb710_slot_to_chip(slot);
+#endif
+	int err;
+
+	/* a lot of magic; see comment in cb710_mmc_set_clock() */
+	dev_dbg(cb710_slot_dev(slot), "bus powerup\n");
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	err = cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20);
+	if (unlikely(err))
+		return err;
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT, 0x80, 0);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG3_PORT, 0x80, 0);
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	mdelay(1);
+	dev_dbg(cb710_slot_dev(slot), "after delay 1\n");
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	err = cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20);
+	if (unlikely(err))
+		return err;
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT, 0x09, 0);
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	mdelay(1);
+	dev_dbg(cb710_slot_dev(slot), "after delay 2\n");
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	err = cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20);
+	if (unlikely(err))
+		return err;
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT, 0, 0x08);
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	mdelay(2);
+	dev_dbg(cb710_slot_dev(slot), "after delay 3\n");
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG0_PORT, 0x06, 0);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT, 0x70, 0);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG2_PORT, 0x80, 0);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG3_PORT, 0x03, 0);
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	err = cb710_wait_while_busy(slot, CB710_MMC_S2_BUSY_20);
+	if (unlikely(err))
+		return err;
+	/* This port behaves weird: quick byte reads of 0x08,0x09 return
+	 * 0xFF,0x00 after writing 0xFFFF to 0x08; it works correctly when
+	 * read/written from userspace...  What am I missing here?
+	 * (it doesn't depend on write-to-read delay) */
+	cb710_write_port_16(slot, CB710_MMC_CONFIGB_PORT, 0xFFFF);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG0_PORT, 0x06, 0);
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+	dev_dbg(cb710_slot_dev(slot), "bus powerup finished\n");
+
+	return cb710_check_event(slot, 0);
+}
+
+static void cb710_mmc_powerdown(struct cb710_slot *slot)
+{
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG1_PORT, 0, 0x81);
+	cb710_modify_port_8(slot, CB710_MMC_CONFIG3_PORT, 0, 0x80);
+}
+
+static void cb710_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct cb710_slot *slot = cb710_mmc_to_slot(mmc);
+	struct cb710_mmc_reader *reader = mmc_priv(mmc);
+	int err;
+
+	cb710_mmc_set_clock(mmc, ios->clock);
+
+	if (!cb710_mmc_is_card_inserted(slot)) {
+		dev_dbg(cb710_slot_dev(slot),
+			"no card inserted - ignoring bus powerup request\n");
+		ios->power_mode = MMC_POWER_OFF;
+	}
+
+	if (ios->power_mode != reader->last_power_mode)
+	switch (ios->power_mode) {
+	case MMC_POWER_ON:
+		err = cb710_mmc_powerup(slot);
+		if (err) {
+			dev_warn(cb710_slot_dev(slot),
+				"powerup failed (%d)- retrying\n", err);
+			cb710_mmc_powerdown(slot);
+			udelay(1);
+			err = cb710_mmc_powerup(slot);
+			if (err)
+				dev_warn(cb710_slot_dev(slot),
+					"powerup retry failed (%d) - expect errors\n",
+					err);
+		}
+		reader->last_power_mode = MMC_POWER_ON;
+		break;
+	case MMC_POWER_OFF:
+		cb710_mmc_powerdown(slot);
+		reader->last_power_mode = MMC_POWER_OFF;
+		break;
+	case MMC_POWER_UP:
+	default:
+		/* ignore */;
+	}
+
+	cb710_mmc_enable_4bit_data(slot, ios->bus_width != MMC_BUS_WIDTH_1);
+
+	cb710_mmc_enable_irq(slot, CB710_MMC_IE_TEST_MASK, 0);
+}
+
+static int cb710_mmc_get_ro(struct mmc_host *mmc)
+{
+	struct cb710_slot *slot = cb710_mmc_to_slot(mmc);
+
+	return cb710_read_port_8(slot, CB710_MMC_STATUS3_PORT)
+		& CB710_MMC_S3_WRITE_PROTECTED;
+}
+
+static int cb710_mmc_irq_handler(struct cb710_slot *slot)
+{
+	struct mmc_host *mmc = cb710_slot_to_mmc(slot);
+	struct cb710_mmc_reader *reader = mmc_priv(mmc);
+	u32 status, config1, config2, irqen;
+
+	status = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT);
+	irqen = cb710_read_port_32(slot, CB710_MMC_IRQ_ENABLE_PORT);
+	config2 = cb710_read_port_32(slot, CB710_MMC_CONFIGB_PORT);
+	config1 = cb710_read_port_32(slot, CB710_MMC_CONFIG_PORT);
+
+	dev_dbg(cb710_slot_dev(slot), "interrupt; status: %08X, "
+		"ie: %08X, c2: %08X, c1: %08X\n",
+		status, irqen, config2, config1);
+
+	if (status & (CB710_MMC_S1_CARD_CHANGED << 8)) {
+		/* ack the event */
+		cb710_write_port_8(slot, CB710_MMC_STATUS1_PORT,
+			CB710_MMC_S1_CARD_CHANGED);
+		if ((irqen & CB710_MMC_IE_CISTATUS_MASK)
+		    == CB710_MMC_IE_CISTATUS_MASK)
+			mmc_detect_change(mmc, HZ/5);
+	} else {
+		dev_dbg(cb710_slot_dev(slot), "unknown interrupt (test)\n");
+		spin_lock(&reader->irq_lock);
+		__cb710_mmc_enable_irq(slot, 0, CB710_MMC_IE_TEST_MASK);
+		spin_unlock(&reader->irq_lock);
+	}
+
+	return 1;
+}
+
+static void cb710_mmc_finish_request_tasklet(unsigned long data)
+{
+	struct mmc_host *mmc = (void *)data;
+	struct cb710_mmc_reader *reader = mmc_priv(mmc);
+	struct mmc_request *mrq = reader->mrq;
+
+	reader->mrq = NULL;
+	mmc_request_done(mmc, mrq);
+}
+
+static const struct mmc_host_ops cb710_mmc_host = {
+	.request = cb710_mmc_request,
+	.set_ios = cb710_mmc_set_ios,
+	.get_ro = cb710_mmc_get_ro
+};
+
+#ifdef CONFIG_PM
+
+static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
+	struct mmc_host *mmc = cb710_slot_to_mmc(slot);
+	int err;
+
+	err = mmc_suspend_host(mmc, state);
+	if (err)
+		return err;
+
+	cb710_mmc_enable_irq(slot, 0, ~0);
+	return 0;
+}
+
+static int cb710_mmc_resume(struct platform_device *pdev)
+{
+	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
+	struct mmc_host *mmc = cb710_slot_to_mmc(slot);
+
+	cb710_mmc_enable_irq(slot, 0, ~0);
+
+	return mmc_resume_host(mmc);
+}
+
+#endif /* CONFIG_PM */
+
+static int __devinit cb710_mmc_init(struct platform_device *pdev)
+{
+	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
+	struct cb710_chip *chip = cb710_slot_to_chip(slot);
+	struct mmc_host *mmc;
+	struct cb710_mmc_reader *reader;
+	int err;
+	u32 val;
+
+	mmc = mmc_alloc_host(sizeof(*reader), cb710_slot_dev(slot));
+	if (!mmc)
+		return -ENOMEM;
+
+	dev_set_drvdata(&pdev->dev, mmc);
+
+	/* harmless (maybe) magic */
+	pci_read_config_dword(chip->pdev, 0x48, &val);
+	val = cb710_src_freq_mhz[(val >> 16) & 0xF];
+	dev_dbg(cb710_slot_dev(slot), "source frequency: %dMHz\n", val);
+	val *= 1000000;
+
+	mmc->ops = &cb710_mmc_host;
+	mmc->f_max = val;
+	mmc->f_min = val >> cb710_clock_divider_log2[CB710_MAX_DIVIDER_IDX];
+	mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_4_BIT_DATA;
+
+	reader = mmc_priv(mmc);
+
+	tasklet_init(&reader->finish_req_tasklet,
+		cb710_mmc_finish_request_tasklet, (unsigned long)mmc);
+	spin_lock_init(&reader->irq_lock);
+	cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
+
+	cb710_mmc_enable_irq(slot, 0, ~0);
+	cb710_set_irq_handler(slot, cb710_mmc_irq_handler);
+
+	err = mmc_add_host(mmc);
+	if (unlikely(err))
+		goto err_free_mmc;
+
+	dev_dbg(cb710_slot_dev(slot), "mmc_hostname is %s\n",
+		mmc_hostname(mmc));
+
+	cb710_mmc_enable_irq(slot, CB710_MMC_IE_CARD_INSERTION_STATUS, 0);
+
+	return 0;
+
+err_free_mmc:
+	dev_dbg(cb710_slot_dev(slot), "mmc_add_host() failed: %d\n", err);
+
+	mmc_free_host(mmc);
+	return err;
+}
+
+static int __devexit cb710_mmc_exit(struct platform_device *pdev)
+{
+	struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
+	struct mmc_host *mmc = cb710_slot_to_mmc(slot);
+	struct cb710_mmc_reader *reader = mmc_priv(mmc);
+
+	cb710_mmc_enable_irq(slot, 0, CB710_MMC_IE_CARD_INSERTION_STATUS);
+
+	mmc_remove_host(mmc);
+
+	/* IRQs should be disabled now, but let's stay on the safe side */
+	cb710_mmc_enable_irq(slot, 0, ~0);
+	cb710_set_irq_handler(slot, NULL);
+
+	/* clear config ports - just in case */
+	cb710_write_port_32(slot, CB710_MMC_CONFIG_PORT, 0);
+	cb710_write_port_16(slot, CB710_MMC_CONFIGB_PORT, 0);
+
+	tasklet_kill(&reader->finish_req_tasklet);
+
+	mmc_free_host(mmc);
+	return 0;
+}
+
+static struct platform_driver cb710_mmc_driver = {
+	.driver.name = "cb710-mmc",
+	.probe = cb710_mmc_init,
+	.remove = __devexit_p(cb710_mmc_exit),
+#ifdef CONFIG_PM
+	.suspend = cb710_mmc_suspend,
+	.resume = cb710_mmc_resume,
+#endif
+};
+
+static int __init cb710_mmc_init_module(void)
+{
+	return platform_driver_register(&cb710_mmc_driver);
+}
+
+static void __exit cb710_mmc_cleanup_module(void)
+{
+	platform_driver_unregister(&cb710_mmc_driver);
+}
+
+module_init(cb710_mmc_init_module);
+module_exit(cb710_mmc_cleanup_module);
+
+MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>");
+MODULE_DESCRIPTION("ENE CB710 memory card reader driver - MMC/SD part");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cb710-mmc");
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/cb710-mmc.h linux-libre-2.6.31-gnu/drivers/mmc/host/cb710-mmc.h
--- linux-libre-2.6.30-gnu/drivers/mmc/host/cb710-mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/cb710-mmc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ *  cb710/cb710-mmc.h
+ *
+ *  Copyright by Michał Mirosław, 2008-2009
+ *
+ * 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.
+ */
+#ifndef LINUX_CB710_MMC_H
+#define LINUX_CB710_MMC_H
+
+#include <linux/cb710.h>
+
+/* per-MMC-reader structure */
+struct cb710_mmc_reader {
+	struct tasklet_struct finish_req_tasklet;
+	struct mmc_request *mrq;
+	spinlock_t irq_lock;
+	unsigned char last_power_mode;
+};
+
+/* some device struct walking */
+
+static inline struct mmc_host *cb710_slot_to_mmc(struct cb710_slot *slot)
+{
+	return dev_get_drvdata(&slot->pdev.dev);
+}
+
+static inline struct cb710_slot *cb710_mmc_to_slot(struct mmc_host *mmc)
+{
+	struct platform_device *pdev = container_of(mmc_dev(mmc),
+		struct platform_device, dev);
+	return cb710_pdev_to_slot(pdev);
+}
+
+/* registers (this might be all wrong ;) */
+
+#define CB710_MMC_DATA_PORT		0x00
+
+#define CB710_MMC_CONFIG_PORT		0x04
+#define CB710_MMC_CONFIG0_PORT		0x04
+#define CB710_MMC_CONFIG1_PORT		0x05
+#define   CB710_MMC_C1_4BIT_DATA_BUS		0x40
+#define CB710_MMC_CONFIG2_PORT		0x06
+#define   CB710_MMC_C2_READ_PIO_SIZE_MASK	0x0F	/* N-1 */
+#define CB710_MMC_CONFIG3_PORT		0x07
+
+#define CB710_MMC_CONFIGB_PORT		0x08
+
+#define CB710_MMC_IRQ_ENABLE_PORT	0x0C
+#define   CB710_MMC_IE_TEST_MASK		0x00BF
+#define   CB710_MMC_IE_CARD_INSERTION_STATUS	0x1000
+#define   CB710_MMC_IE_IRQ_ENABLE		0x8000
+#define   CB710_MMC_IE_CISTATUS_MASK		\
+		(CB710_MMC_IE_CARD_INSERTION_STATUS|CB710_MMC_IE_IRQ_ENABLE)
+
+#define CB710_MMC_STATUS_PORT		0x10
+#define   CB710_MMC_STATUS_ERROR_EVENTS		0x60FF
+#define CB710_MMC_STATUS0_PORT		0x10
+#define   CB710_MMC_S0_FIFO_UNDERFLOW		0x40
+#define CB710_MMC_STATUS1_PORT		0x11
+#define   CB710_MMC_S1_COMMAND_SENT		0x01
+#define   CB710_MMC_S1_DATA_TRANSFER_DONE	0x02
+#define   CB710_MMC_S1_PIO_TRANSFER_DONE	0x04
+#define   CB710_MMC_S1_CARD_CHANGED		0x10
+#define   CB710_MMC_S1_RESET			0x20
+#define CB710_MMC_STATUS2_PORT		0x12
+#define   CB710_MMC_S2_FIFO_READY		0x01
+#define   CB710_MMC_S2_FIFO_EMPTY		0x02
+#define   CB710_MMC_S2_BUSY_10			0x10
+#define   CB710_MMC_S2_BUSY_20			0x20
+#define CB710_MMC_STATUS3_PORT		0x13
+#define   CB710_MMC_S3_CARD_DETECTED		0x02
+#define   CB710_MMC_S3_WRITE_PROTECTED		0x04
+
+#define CB710_MMC_CMD_TYPE_PORT		0x14
+#define   CB710_MMC_RSP_TYPE_MASK		0x0007
+#define     CB710_MMC_RSP_R1			(0)
+#define     CB710_MMC_RSP_136			(5)
+#define     CB710_MMC_RSP_NO_CRC		(2)
+#define   CB710_MMC_RSP_PRESENT_MASK		0x0018
+#define     CB710_MMC_RSP_NONE			(0 << 3)
+#define     CB710_MMC_RSP_PRESENT		(1 << 3)
+#define     CB710_MMC_RSP_PRESENT_X		(2 << 3)
+#define   CB710_MMC_CMD_TYPE_MASK		0x0060
+#define     CB710_MMC_CMD_BC			(0 << 5)
+#define     CB710_MMC_CMD_BCR			(1 << 5)
+#define     CB710_MMC_CMD_AC			(2 << 5)
+#define     CB710_MMC_CMD_ADTC			(3 << 5)
+#define   CB710_MMC_DATA_READ			0x0080
+#define   CB710_MMC_CMD_CODE_MASK		0x3F00
+#define   CB710_MMC_CMD_CODE_SHIFT		8
+#define   CB710_MMC_IS_APP_CMD			0x4000
+#define   CB710_MMC_RSP_BUSY			0x8000
+
+#define CB710_MMC_CMD_PARAM_PORT	0x18
+#define CB710_MMC_TRANSFER_SIZE_PORT	0x1C
+#define CB710_MMC_RESPONSE0_PORT	0x20
+#define CB710_MMC_RESPONSE1_PORT	0x24
+#define CB710_MMC_RESPONSE2_PORT	0x28
+#define CB710_MMC_RESPONSE3_PORT	0x2C
+
+#endif /* LINUX_CB710_MMC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/imxmmc.c linux-libre-2.6.31-gnu/drivers/mmc/host/imxmmc.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/imxmmc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/imxmmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -652,7 +652,7 @@
 	set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
 	tasklet_schedule(&host->tasklet);
 
-	return IRQ_RETVAL(handled);;
+	return IRQ_RETVAL(handled);
 }
 
 static void imxmci_tasklet_fnc(unsigned long data)
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/Kconfig linux-libre-2.6.31-gnu/drivers/mmc/host/Kconfig
--- linux-libre-2.6.30-gnu/drivers/mmc/host/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -83,6 +83,42 @@
 
 	  If unsure, say N.
 
+config MMC_SDHCI_PLTFM
+	tristate "SDHCI support on the platform specific bus"
+	depends on MMC_SDHCI
+	help
+	  This selects the platform specific bus support for Secure Digital Host
+	  Controller Interface.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_SDHCI_S3C
+	tristate "SDHCI support on Samsung S3C SoC"
+	depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX)
+	help
+	  This selects the Secure Digital Host Controller Interface (SDHCI)
+	  often referrered to as the HSMMC block in some of the Samsung S3C
+	  range of SoC.
+
+	  Note, due to the problems with DMA, the DMA support is only
+	  available with CONFIG_EXPERIMENTAL is selected.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_SDHCI_S3C_DMA
+	bool "DMA support on S3C SDHCI"
+	depends on MMC_SDHCI_S3C && EXPERIMENTAL
+	help
+	  Enable DMA support on the Samsung S3C SDHCI glue. The DMA
+	  has proved to be problematic if the controller encounters
+	  certain errors, and thus should be treated with care.
+
+	  YMMV.
+
 config MMC_OMAP
 	tristate "TI OMAP Multimedia Card Interface support"
 	depends on ARCH_OMAP
@@ -155,7 +191,7 @@
 
 config MMC_IMX
 	tristate "Motorola i.MX Multimedia Card Interface support"
-	depends on ARCH_IMX
+	depends on ARCH_MX1
 	help
 	  This selects the Motorola i.MX Multimedia card Interface.
 	  If you have a i.MX platform with a Multimedia Card slot,
@@ -237,7 +273,31 @@
 
 config MMC_TMIO
 	tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
-	depends on MFD_TMIO
+	depends on MFD_TMIO || MFD_ASIC3
 	help
 	  This provides support for the SD/MMC cell found in TC6393XB,
-	  T7L66XB and also ipaq ASIC3
+	  T7L66XB and also HTC ASIC3
+
+config MMC_CB710
+	tristate "ENE CB710 MMC/SD Interface support"
+	depends on PCI
+	select CB710_CORE
+	help
+	  This option enables support for MMC/SD part of ENE CB710/720 Flash
+	  memory card reader found in some laptops (ie. some versions of
+	  HP Compaq nx9500).
+
+	  This driver can also be built as a module. If so, the module
+	  will be called cb710-mmc.
+
+config MMC_VIA_SDMMC
+	tristate "VIA SD/MMC Card Reader Driver"
+	depends on PCI
+	help
+	  This selects the VIA SD/MMC Card Reader driver, say Y or M here.
+	  VIA provides one multi-functional card reader which integrated into
+	  some motherboards manufactured by VIA. This card reader supports
+	  SD/MMC/SDHC.
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/Makefile linux-libre-2.6.31-gnu/drivers/mmc/host/Makefile
--- linux-libre-2.6.30-gnu/drivers/mmc/host/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,8 @@
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
 obj-$(CONFIG_MMC_RICOH_MMC)	+= ricoh_mmc.o
 obj-$(CONFIG_MMC_SDHCI_OF)	+= sdhci-of.o
+obj-$(CONFIG_MMC_SDHCI_PLTFM)	+= sdhci-pltfm.o
+obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
@@ -29,4 +31,9 @@
 obj-$(CONFIG_MMC_S3C)   	+= s3cmci.o
 obj-$(CONFIG_MMC_SDRICOH_CS)	+= sdricoh_cs.o
 obj-$(CONFIG_MMC_TMIO)		+= tmio_mmc.o
+obj-$(CONFIG_MMC_CB710)	+= cb710-mmc.o
+obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
 
+ifeq ($(CONFIG_CB710_DEBUG),y)
+	CFLAGS-cb710-mmc	+= -DDEBUG
+endif
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/mmci.c linux-libre-2.6.31-gnu/drivers/mmc/host/mmci.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/mmci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/mmci.c	2009-09-09 18:13:59.000000000 -0400
@@ -546,7 +546,7 @@
 		host->mclk = clk_get_rate(host->clk);
 		DBG(host, "eventual mclk rate: %u Hz\n", host->mclk);
 	}
-	host->base = ioremap(dev->res.start, SZ_4K);
+	host->base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!host->base) {
 		ret = -ENOMEM;
 		goto clk_disable;
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/mmc_spi.c linux-libre-2.6.31-gnu/drivers/mmc/host/mmc_spi.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/mmc_spi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/mmc_spi.c	2009-09-09 18:13:59.000000000 -0400
@@ -97,6 +97,14 @@
  */
 #define r1b_timeout		(HZ * 3)
 
+/* One of the critical speed parameters is the amount of data which may
+ * be transfered in one command. If this value is too low, the SD card
+ * controller has to do multiple partial block writes (argggh!). With
+ * today (2008) SD cards there is little speed gain if we transfer more
+ * than 64 KBytes at a time. So use this value until there is any indication
+ * that we should do more here.
+ */
+#define MMC_SPI_BLOCKSATONCE	128
 
 /****************************************************************************/
 
@@ -327,15 +335,16 @@
 
 	/* Status byte: the entire seven-bit R1 response.  */
 	if (cmd->resp[0] != 0) {
-		if ((R1_SPI_PARAMETER | R1_SPI_ADDRESS
-				      | R1_SPI_ILLEGAL_COMMAND)
+		if ((R1_SPI_PARAMETER | R1_SPI_ADDRESS)
 				& cmd->resp[0])
-			value = -EINVAL;
+			value = -EFAULT; /* Bad address */
+		else if (R1_SPI_ILLEGAL_COMMAND & cmd->resp[0])
+			value = -ENOSYS; /* Function not implemented */
 		else if (R1_SPI_COM_CRC & cmd->resp[0])
-			value = -EILSEQ;
+			value = -EILSEQ; /* Illegal byte sequence */
 		else if ((R1_SPI_ERASE_SEQ | R1_SPI_ERASE_RESET)
 				& cmd->resp[0])
-			value = -EIO;
+			value = -EIO;    /* I/O error */
 		/* else R1_SPI_IDLE, "it's resetting" */
 	}
 
@@ -1304,6 +1313,12 @@
 	struct mmc_spi_host	*host;
 	int			status;
 
+	/* We rely on full duplex transfers, mostly to reduce
+	 * per-transfer overheads (by making fewer transfers).
+	 */
+	if (spi->master->flags & SPI_MASTER_HALF_DUPLEX)
+		return -EINVAL;
+
 	/* MMC and SD specs only seem to care that sampling is on the
 	 * rising edge ... meaning SPI modes 0 or 3.  So either SPI mode
 	 * should be legit.  We'll use mode 0 since the steady state is 0,
@@ -1366,6 +1381,10 @@
 
 	mmc->ops = &mmc_spi_ops;
 	mmc->max_blk_size = MMC_SPI_BLOCKSIZE;
+	mmc->max_hw_segs = MMC_SPI_BLOCKSATONCE;
+	mmc->max_phys_segs = MMC_SPI_BLOCKSATONCE;
+	mmc->max_req_size = MMC_SPI_BLOCKSATONCE * MMC_SPI_BLOCKSIZE;
+	mmc->max_blk_count = MMC_SPI_BLOCKSATONCE;
 
 	mmc->caps = MMC_CAP_SPI;
 
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/mvsdio.c linux-libre-2.6.31-gnu/drivers/mmc/host/mvsdio.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/mvsdio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/mvsdio.c	2009-09-09 18:13:59.000000000 -0400
@@ -384,7 +384,7 @@
 				u16 val[2] = {0, 0};
 				val[0] = mvsd_read(MVSD_FIFO);
 				val[1] = mvsd_read(MVSD_FIFO);
-				memcpy(p, &val, s);
+				memcpy(p, ((void *)&val) + 4 - s, s);
 				s = 0;
 				intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
 			}
@@ -423,7 +423,7 @@
 		if (s < 4) {
 			if (s && (intr_status & MVSD_NOR_TX_AVAIL)) {
 				u16 val[2] = {0, 0};
-				memcpy(&val, p, s);
+				memcpy(((void *)&val) + 4 - s, p, s);
 				mvsd_write(MVSD_FIFO, val[0]);
 				mvsd_write(MVSD_FIFO, val[1]);
 				s = 0;
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/mxcmmc.c linux-libre-2.6.31-gnu/drivers/mmc/host/mxcmmc.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/mxcmmc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/mxcmmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -746,8 +746,6 @@
 	}
 
 	mmc->f_min = clk_get_rate(host->clk) >> 16;
-	if (mmc->f_min < 400000)
-		mmc->f_min = 400000;
 	mmc->f_max = clk_get_rate(host->clk) >> 1;
 
 	/* recommended in data sheet */
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/omap.c linux-libre-2.6.31-gnu/drivers/mmc/host/omap.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/omap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/omap.c	2009-09-09 18:13:59.000000000 -0400
@@ -1593,7 +1593,6 @@
 #endif
 
 static struct platform_driver mmc_omap_driver = {
-	.probe		= mmc_omap_probe,
 	.remove		= mmc_omap_remove,
 	.suspend	= mmc_omap_suspend,
 	.resume		= mmc_omap_resume,
@@ -1605,7 +1604,7 @@
 
 static int __init mmc_omap_init(void)
 {
-	return platform_driver_register(&mmc_omap_driver);
+	return platform_driver_probe(&mmc_omap_driver, mmc_omap_probe);
 }
 
 static void __exit mmc_omap_exit(void)
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/omap_hsmmc.c linux-libre-2.6.31-gnu/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/omap_hsmmc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/omap_hsmmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -1073,7 +1073,6 @@
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
 	mmc->max_seg_size = mmc->max_req_size;
 
-	mmc->ocr_avail = mmc_slot(host).ocr_mask;
 	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
 
 	if (pdata->slots[host->slot_id].wires >= 8)
@@ -1110,13 +1109,14 @@
 		goto err_irq;
 	}
 
+	/* initialize power supplies, gpios, etc */
 	if (pdata->init != NULL) {
 		if (pdata->init(&pdev->dev) != 0) {
-			dev_dbg(mmc_dev(host->mmc),
-				"Unable to configure MMC IRQs\n");
+			dev_dbg(mmc_dev(host->mmc), "late init error\n");
 			goto err_irq_cd_init;
 		}
 	}
+	mmc->ocr_avail = mmc_slot(host).ocr_mask;
 
 	/* Request IRQ for card detect */
 	if ((mmc_slot(host).card_detect_irq)) {
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/pxamci.c linux-libre-2.6.31-gnu/drivers/mmc/host/pxamci.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/pxamci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/pxamci.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/mmc/host.h>
 #include <linux/io.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/sizes.h>
 
@@ -67,8 +68,42 @@
 	unsigned int		dma_dir;
 	unsigned int		dma_drcmrrx;
 	unsigned int		dma_drcmrtx;
+
+	struct regulator	*vcc;
 };
 
+static inline void pxamci_init_ocr(struct pxamci_host *host)
+{
+#ifdef CONFIG_REGULATOR
+	host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
+
+	if (IS_ERR(host->vcc))
+		host->vcc = NULL;
+	else {
+		host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc);
+		if (host->pdata && host->pdata->ocr_mask)
+			dev_warn(mmc_dev(host->mmc),
+				"ocr_mask/setpower will not be used\n");
+	}
+#endif
+	if (host->vcc == NULL) {
+		/* fall-back to platform data */
+		host->mmc->ocr_avail = host->pdata ?
+			host->pdata->ocr_mask :
+			MMC_VDD_32_33 | MMC_VDD_33_34;
+	}
+}
+
+static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd)
+{
+#ifdef CONFIG_REGULATOR
+	if (host->vcc)
+		mmc_regulator_set_ocr(host->vcc, vdd);
+#endif
+	if (!host->vcc && host->pdata && host->pdata->setpower)
+		host->pdata->setpower(mmc_dev(host->mmc), vdd);
+}
+
 static void pxamci_stop_clock(struct pxamci_host *host)
 {
 	if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
@@ -133,12 +168,12 @@
 
 	if (data->flags & MMC_DATA_READ) {
 		host->dma_dir = DMA_FROM_DEVICE;
-		dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
+		dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC;
 		DRCMR(host->dma_drcmrtx) = 0;
 		DRCMR(host->dma_drcmrrx) = host->dma | DRCMR_MAPVLD;
 	} else {
 		host->dma_dir = DMA_TO_DEVICE;
-		dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
+		dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
 		DRCMR(host->dma_drcmrrx) = 0;
 		DRCMR(host->dma_drcmrtx) = host->dma | DRCMR_MAPVLD;
 	}
@@ -438,8 +473,7 @@
 	if (host->power_mode != ios->power_mode) {
 		host->power_mode = ios->power_mode;
 
-		if (host->pdata && host->pdata->setpower)
-			host->pdata->setpower(mmc_dev(mmc), ios->vdd);
+		pxamci_set_power(host, ios->vdd);
 
 		if (ios->power_mode == MMC_POWER_ON)
 			host->cmdat |= CMDAT_INIT;
@@ -562,9 +596,8 @@
 	mmc->f_max = (cpu_is_pxa300() || cpu_is_pxa310()) ? 26000000
 							  : host->clkrate;
 
-	mmc->ocr_avail = host->pdata ?
-			 host->pdata->ocr_mask :
-			 MMC_VDD_32_33|MMC_VDD_33_34;
+	pxamci_init_ocr(host);
+
 	mmc->caps = 0;
 	host->cmdat = 0;
 	if (!cpu_is_pxa25x()) {
@@ -661,6 +694,9 @@
 	if (mmc) {
 		struct pxamci_host *host = mmc_priv(mmc);
 
+		if (host->vcc)
+			regulator_put(host->vcc);
+
 		if (host->pdata && host->pdata->exit)
 			host->pdata->exit(&pdev->dev, mmc);
 
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/s3cmci.c linux-libre-2.6.31-gnu/drivers/mmc/host/s3cmci.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/s3cmci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/s3cmci.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/cpufreq.h>
+#include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 
@@ -789,11 +790,11 @@
 
 	last_source = source;
 
-	s3c2410_dma_devconfig(host->dma, source, 3,
+	s3c2410_dma_devconfig(host->dma, source,
 			      host->mem->start + host->sdidata);
 
 	if (!setup_ok) {
-		s3c2410_dma_config(host->dma, 4, 0);
+		s3c2410_dma_config(host->dma, 4);
 		s3c2410_dma_set_buffdone_fn(host->dma,
 					    s3cmci_dma_done_callback);
 		s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
@@ -1121,7 +1122,7 @@
 	case MMC_POWER_OFF:
 	default:
 		s3c2410_gpio_setpin(S3C2410_GPE5, 0);
-		s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
+		s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPIO_OUTPUT);
 
 		if (host->is2440)
 			mci_con |= S3C2440_SDICON_SDRESET;
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci.c linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci.c	2009-09-09 18:13:59.000000000 -0400
@@ -78,6 +78,11 @@
 		sdhci_readl(host, SDHCI_CAPABILITIES),
 		sdhci_readl(host, SDHCI_MAX_CURRENT));
 
+	if (host->flags & SDHCI_USE_ADMA)
+		printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
+		       readl(host->ioaddr + SDHCI_ADMA_ERROR),
+		       readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
+
 	printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
 }
 
@@ -579,7 +584,7 @@
 	 * longer to time out, but that's much better than having a too-short
 	 * timeout value.
 	 */
-	if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL))
+	if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
 		return 0xE;
 
 	/* timeout in us */
@@ -768,8 +773,14 @@
 	}
 
 	if (!(host->flags & SDHCI_REQ_USE_DMA)) {
-		sg_miter_start(&host->sg_miter,
-			data->sg, data->sg_len, SG_MITER_ATOMIC);
+		int flags;
+
+		flags = SG_MITER_ATOMIC;
+		if (host->data->flags & MMC_DATA_READ)
+			flags |= SG_MITER_TO_SG;
+		else
+			flags |= SG_MITER_FROM_SG;
+		sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
 		host->blocks = data->blocks;
 	}
 
@@ -1005,12 +1016,34 @@
 {
 	u8 pwr;
 
-	if (host->power == power)
+	if (power == (unsigned short)-1)
+		pwr = 0;
+	else {
+		switch (1 << power) {
+		case MMC_VDD_165_195:
+			pwr = SDHCI_POWER_180;
+			break;
+		case MMC_VDD_29_30:
+		case MMC_VDD_30_31:
+			pwr = SDHCI_POWER_300;
+			break;
+		case MMC_VDD_32_33:
+		case MMC_VDD_33_34:
+			pwr = SDHCI_POWER_330;
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	if (host->pwr == pwr)
 		return;
 
-	if (power == (unsigned short)-1) {
+	host->pwr = pwr;
+
+	if (pwr == 0) {
 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
-		goto out;
+		return;
 	}
 
 	/*
@@ -1020,35 +1053,23 @@
 	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 
-	pwr = SDHCI_POWER_ON;
-
-	switch (1 << power) {
-	case MMC_VDD_165_195:
-		pwr |= SDHCI_POWER_180;
-		break;
-	case MMC_VDD_29_30:
-	case MMC_VDD_30_31:
-		pwr |= SDHCI_POWER_300;
-		break;
-	case MMC_VDD_32_33:
-	case MMC_VDD_33_34:
-		pwr |= SDHCI_POWER_330;
-		break;
-	default:
-		BUG();
-	}
-
 	/*
 	 * At least the Marvell CaFe chip gets confused if we set the voltage
 	 * and set turn on power at the same time, so set the voltage first.
 	 */
-	if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
-		sdhci_writeb(host, pwr & ~SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
+	if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
+		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+
+	pwr |= SDHCI_POWER_ON;
 
 	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-out:
-	host->power = power;
+	/*
+	 * Some controllers need an extra 10ms delay of 10ms before they
+	 * can apply clock after applying power
+	 */
+	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
+		mdelay(10);
 }
 
 /*****************************************************************************\
@@ -1374,6 +1395,35 @@
 		sdhci_finish_command(host);
 }
 
+#ifdef DEBUG
+static void sdhci_show_adma_error(struct sdhci_host *host)
+{
+	const char *name = mmc_hostname(host->mmc);
+	u8 *desc = host->adma_desc;
+	__le32 *dma;
+	__le16 *len;
+	u8 attr;
+
+	sdhci_dumpregs(host);
+
+	while (true) {
+		dma = (__le32 *)(desc + 4);
+		len = (__le16 *)(desc + 2);
+		attr = *desc;
+
+		DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
+		    name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr);
+
+		desc += 8;
+
+		if (attr & 2)
+			break;
+	}
+}
+#else
+static void sdhci_show_adma_error(struct sdhci_host *host) { }
+#endif
+
 static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 {
 	BUG_ON(intmask == 0);
@@ -1403,8 +1453,11 @@
 		host->data->error = -ETIMEDOUT;
 	else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT))
 		host->data->error = -EILSEQ;
-	else if (intmask & SDHCI_INT_ADMA_ERROR)
+	else if (intmask & SDHCI_INT_ADMA_ERROR) {
+		printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc));
+		sdhci_show_adma_error(host);
 		host->data->error = -EIO;
+	}
 
 	if (host->data->error)
 		sdhci_finish_data(host);
@@ -1719,9 +1772,15 @@
 	 * Set host parameters.
 	 */
 	mmc->ops = &sdhci_ops;
-	mmc->f_min = host->max_clk / 256;
+	if (host->ops->get_min_clock)
+		mmc->f_min = host->ops->get_min_clock(host);
+	else
+		mmc->f_min = host->max_clk / 256;
 	mmc->f_max = host->max_clk;
-	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
+	mmc->caps = MMC_CAP_SDIO_IRQ;
+
+	if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
+		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
 	if (caps & SDHCI_CAN_DO_HISPD)
 		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
@@ -1794,7 +1853,7 @@
 	/*
 	 * Maximum block count.
 	 */
-	mmc->max_blk_count = 65535;
+	mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
 
 	/*
 	 * Init tasklets.
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci.h linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci.h
--- linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci.h	2009-09-09 18:13:59.000000000 -0400
@@ -226,6 +226,12 @@
 #define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET		(1<<19)
 /* Controller has to be forced to use block size of 2048 bytes */
 #define SDHCI_QUIRK_FORCE_BLK_SZ_2048			(1<<20)
+/* Controller cannot do multi-block transfers */
+#define SDHCI_QUIRK_NO_MULTIBLOCK			(1<<21)
+/* Controller can only handle 1-bit data transfers */
+#define SDHCI_QUIRK_FORCE_1_BIT_DATA			(1<<22)
+/* Controller needs 10ms delay between applying power and clock */
+#define SDHCI_QUIRK_DELAY_AFTER_POWER			(1<<23)
 
 	int			irq;		/* Device IRQ */
 	void __iomem *		ioaddr;		/* Mapped address */
@@ -255,7 +261,7 @@
 	unsigned int		timeout_clk;	/* Timeout freq (KHz) */
 
 	unsigned int		clock;		/* Current clock (MHz) */
-	unsigned short		power;		/* Current voltage */
+	u8			pwr;		/* Current voltage */
 
 	struct mmc_request	*mrq;		/* Current request */
 	struct mmc_command	*cmd;		/* Current command */
@@ -296,6 +302,7 @@
 
 	int		(*enable_dma)(struct sdhci_host *host);
 	unsigned int	(*get_max_clock)(struct sdhci_host *host);
+	unsigned int	(*get_min_clock)(struct sdhci_host *host);
 	unsigned int	(*get_timeout_clock)(struct sdhci_host *host);
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-of.c linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-of.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-of.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-of.c	2009-09-09 18:13:59.000000000 -0400
@@ -158,6 +158,13 @@
 	return of_host->clock;
 }
 
+static unsigned int esdhc_get_min_clock(struct sdhci_host *host)
+{
+	struct sdhci_of_host *of_host = sdhci_priv(host);
+
+	return of_host->clock / 256 / 16;
+}
+
 static unsigned int esdhc_get_timeout_clock(struct sdhci_host *host)
 {
 	struct sdhci_of_host *of_host = sdhci_priv(host);
@@ -184,6 +191,7 @@
 		.set_clock = esdhc_set_clock,
 		.enable_dma = esdhc_enable_dma,
 		.get_max_clock = esdhc_get_max_clock,
+		.get_min_clock = esdhc_get_min_clock,
 		.get_timeout_clock = esdhc_get_timeout_clock,
 	},
 };
@@ -226,7 +234,7 @@
 		return -ENODEV;
 
 	host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
-	if (!host)
+	if (IS_ERR(host))
 		return -ENOMEM;
 
 	of_host = sdhci_priv(host);
@@ -250,6 +258,9 @@
 		host->ops = &sdhci_of_data->ops;
 	}
 
+	if (of_get_property(np, "sdhci,1-bit-only", NULL))
+		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
+
 	clk = of_get_property(np, "clock-frequency", &size);
 	if (clk && size == sizeof(*clk) && *clk)
 		of_host->clock = *clk;
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-pci.c linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-pci.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -284,6 +284,18 @@
 	.resume		= jmicron_resume,
 };
 
+static int via_probe(struct sdhci_pci_chip *chip)
+{
+	if (chip->pdev->revision == 0x10)
+		chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER;
+
+	return 0;
+}
+
+static const struct sdhci_pci_fixes sdhci_via = {
+	.probe		= via_probe,
+};
+
 static const struct pci_device_id pci_ids[] __devinitdata = {
 	{
 		.vendor		= PCI_VENDOR_ID_RICOH,
@@ -349,6 +361,14 @@
 		.driver_data	= (kernel_ulong_t)&sdhci_jmicron,
 	},
 
+	{
+		.vendor		= PCI_VENDOR_ID_VIA,
+		.device		= 0x95d0,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_via,
+	},
+
 	{	/* Generic SD host controller */
 		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
 	},
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-pltfm.c linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-pltfm.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-pltfm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-pltfm.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * sdhci-pltfm.c Support for SDHCI platform devices
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * SDHCI platform devices
+ *
+ * Inspired by sdhci-pci.c, by Pierre Ossman
+ */
+
+#include <linux/delay.h>
+#include <linux/highmem.h>
+#include <linux/platform_device.h>
+
+#include <linux/mmc/host.h>
+
+#include <linux/io.h>
+
+#include "sdhci.h"
+
+/*****************************************************************************\
+ *                                                                           *
+ * SDHCI core callbacks                                                      *
+ *                                                                           *
+\*****************************************************************************/
+
+static struct sdhci_ops sdhci_pltfm_ops = {
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Device probing/removal                                                    *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
+{
+	struct sdhci_host *host;
+	struct resource *iomem;
+	int ret;
+
+	BUG_ON(pdev == NULL);
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iomem) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (resource_size(iomem) != 0x100)
+		dev_err(&pdev->dev, "Invalid iomem size. You may "
+			"experience problems.\n");
+
+	if (pdev->dev.parent)
+		host = sdhci_alloc_host(pdev->dev.parent, 0);
+	else
+		host = sdhci_alloc_host(&pdev->dev, 0);
+
+	if (IS_ERR(host)) {
+		ret = PTR_ERR(host);
+		goto err;
+	}
+
+	host->hw_name = "platform";
+	host->ops = &sdhci_pltfm_ops;
+	host->irq = platform_get_irq(pdev, 0);
+
+	if (!request_mem_region(iomem->start, resource_size(iomem),
+		mmc_hostname(host->mmc))) {
+		dev_err(&pdev->dev, "cannot request region\n");
+		ret = -EBUSY;
+		goto err_request;
+	}
+
+	host->ioaddr = ioremap(iomem->start, resource_size(iomem));
+	if (!host->ioaddr) {
+		dev_err(&pdev->dev, "failed to remap registers\n");
+		ret = -ENOMEM;
+		goto err_remap;
+	}
+
+	ret = sdhci_add_host(host);
+	if (ret)
+		goto err_add_host;
+
+	platform_set_drvdata(pdev, host);
+
+	return 0;
+
+err_add_host:
+	iounmap(host->ioaddr);
+err_remap:
+	release_mem_region(iomem->start, resource_size(iomem));
+err_request:
+	sdhci_free_host(host);
+err:
+	printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret);
+	return ret;
+}
+
+static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	int dead;
+	u32 scratch;
+
+	dead = 0;
+	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+	if (scratch == (u32)-1)
+		dead = 1;
+
+	sdhci_remove_host(host, dead);
+	iounmap(host->ioaddr);
+	release_mem_region(iomem->start, resource_size(iomem));
+	sdhci_free_host(host);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver sdhci_pltfm_driver = {
+	.driver = {
+		.name	= "sdhci",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_pltfm_probe,
+	.remove		= __devexit_p(sdhci_pltfm_remove),
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Driver init/exit                                                          *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __init sdhci_drv_init(void)
+{
+	return platform_driver_register(&sdhci_pltfm_driver);
+}
+
+static void __exit sdhci_drv_exit(void)
+{
+	platform_driver_unregister(&sdhci_pltfm_driver);
+}
+
+module_init(sdhci_drv_init);
+module_exit(sdhci_drv_exit);
+
+MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sdhci");
+
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-s3c.c linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-s3c.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/sdhci-s3c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/sdhci-s3c.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,428 @@
+/* linux/drivers/mmc/host/sdhci-s3c.c
+ *
+ * Copyright 2008 Openmoko Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * SDHCI (HSMMC) support for Samsung SoC
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <linux/mmc/host.h>
+
+#include <plat/sdhci.h>
+#include <plat/regs-sdhci.h>
+
+#include "sdhci.h"
+
+#define MAX_BUS_CLK	(4)
+
+/**
+ * struct sdhci_s3c - S3C SDHCI instance
+ * @host: The SDHCI host created
+ * @pdev: The platform device we where created from.
+ * @ioarea: The resource created when we claimed the IO area.
+ * @pdata: The platform data for this controller.
+ * @cur_clk: The index of the current bus clock.
+ * @clk_io: The clock for the internal bus interface.
+ * @clk_bus: The clocks that are available for the SD/MMC bus clock.
+ */
+struct sdhci_s3c {
+	struct sdhci_host	*host;
+	struct platform_device	*pdev;
+	struct resource		*ioarea;
+	struct s3c_sdhci_platdata *pdata;
+	unsigned int		cur_clk;
+
+	struct clk		*clk_io;
+	struct clk		*clk_bus[MAX_BUS_CLK];
+};
+
+static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
+{
+	return sdhci_priv(host);
+}
+
+/**
+ * get_curclk - convert ctrl2 register to clock source number
+ * @ctrl2: Control2 register value.
+ */
+static u32 get_curclk(u32 ctrl2)
+{
+	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+	ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
+
+	return ctrl2;
+}
+
+static void sdhci_s3c_check_sclk(struct sdhci_host *host)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+	u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
+
+	if (get_curclk(tmp) != ourhost->cur_clk) {
+		dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
+
+		tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+		tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
+		writel(tmp, host->ioaddr + 0x80);
+	}
+}
+
+/**
+ * sdhci_s3c_get_max_clk - callback to get maximum clock frequency.
+ * @host: The SDHCI host instance.
+ *
+ * Callback to return the maximum clock rate acheivable by the controller.
+*/
+static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+	struct clk *busclk;
+	unsigned int rate, max;
+	int clk;
+
+	/* note, a reset will reset the clock source */
+
+	sdhci_s3c_check_sclk(host);
+
+	for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
+		busclk = ourhost->clk_bus[clk];
+		if (!busclk)
+			continue;
+
+		rate = clk_get_rate(busclk);
+		if (rate > max)
+			max = rate;
+	}
+
+	return max;
+}
+
+static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host)
+{
+	return sdhci_s3c_get_max_clk(host) / 1000000;
+}
+
+/**
+ * sdhci_s3c_consider_clock - consider one the bus clocks for current setting
+ * @ourhost: Our SDHCI instance.
+ * @src: The source clock index.
+ * @wanted: The clock frequency wanted.
+ */
+static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
+					     unsigned int src,
+					     unsigned int wanted)
+{
+	unsigned long rate;
+	struct clk *clksrc = ourhost->clk_bus[src];
+	int div;
+
+	if (!clksrc)
+		return UINT_MAX;
+
+	rate = clk_get_rate(clksrc);
+
+	for (div = 1; div < 256; div *= 2) {
+		if ((rate / div) <= wanted)
+			break;
+	}
+
+	dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
+		src, rate, wanted, rate / div);
+
+	return (wanted - (rate / div));
+}
+
+/**
+ * sdhci_s3c_set_clock - callback on clock change
+ * @host: The SDHCI host being changed
+ * @clock: The clock rate being requested.
+ *
+ * When the card's clock is going to be changed, look at the new frequency
+ * and find the best clock source to go with it.
+*/
+static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+	unsigned int best = UINT_MAX;
+	unsigned int delta;
+	int best_src = 0;
+	int src;
+	u32 ctrl;
+
+	/* don't bother if the clock is going off. */
+	if (clock == 0)
+		return;
+
+	for (src = 0; src < MAX_BUS_CLK; src++) {
+		delta = sdhci_s3c_consider_clock(ourhost, src, clock);
+		if (delta < best) {
+			best = delta;
+			best_src = src;
+		}
+	}
+
+	dev_dbg(&ourhost->pdev->dev,
+		"selected source %d, clock %d, delta %d\n",
+		 best_src, clock, best);
+
+	/* select the new clock source */
+
+	if (ourhost->cur_clk != best_src) {
+		struct clk *clk = ourhost->clk_bus[best_src];
+
+		/* turn clock off to card before changing clock source */
+		writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
+
+		ourhost->cur_clk = best_src;
+		host->max_clk = clk_get_rate(clk);
+		host->timeout_clk = sdhci_s3c_get_timeout_clk(host);
+
+		ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
+		ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+		ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
+		writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
+	}
+
+	/* reconfigure the hardware for new clock rate */
+
+	{
+		struct mmc_ios ios;
+
+		ios.clock = clock;
+
+		if (ourhost->pdata->cfg_card)
+			(ourhost->pdata->cfg_card)(ourhost->pdev, host->ioaddr,
+						   &ios, NULL);
+	}
+}
+
+static struct sdhci_ops sdhci_s3c_ops = {
+	.get_max_clock		= sdhci_s3c_get_max_clk,
+	.get_timeout_clock	= sdhci_s3c_get_timeout_clk,
+	.set_clock		= sdhci_s3c_set_clock,
+};
+
+static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
+{
+	struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct sdhci_host *host;
+	struct sdhci_s3c *sc;
+	struct resource *res;
+	int ret, irq, ptr, clks;
+
+	if (!pdata) {
+		dev_err(dev, "no device data specified\n");
+		return -ENOENT;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "no irq specified\n");
+		return irq;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "no memory specified\n");
+		return -ENOENT;
+	}
+
+	host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
+	if (IS_ERR(host)) {
+		dev_err(dev, "sdhci_alloc_host() failed\n");
+		return PTR_ERR(host);
+	}
+
+	sc = sdhci_priv(host);
+
+	sc->host = host;
+	sc->pdev = pdev;
+	sc->pdata = pdata;
+
+	platform_set_drvdata(pdev, host);
+
+	sc->clk_io = clk_get(dev, "hsmmc");
+	if (IS_ERR(sc->clk_io)) {
+		dev_err(dev, "failed to get io clock\n");
+		ret = PTR_ERR(sc->clk_io);
+		goto err_io_clk;
+	}
+
+	/* enable the local io clock and keep it running for the moment. */
+	clk_enable(sc->clk_io);
+
+	for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
+		struct clk *clk;
+		char *name = pdata->clocks[ptr];
+
+		if (name == NULL)
+			continue;
+
+		clk = clk_get(dev, name);
+		if (IS_ERR(clk)) {
+			dev_err(dev, "failed to get clock %s\n", name);
+			continue;
+		}
+
+		clks++;
+		sc->clk_bus[ptr] = clk;
+		clk_enable(clk);
+
+		dev_info(dev, "clock source %d: %s (%ld Hz)\n",
+			 ptr, name, clk_get_rate(clk));
+	}
+
+	if (clks == 0) {
+		dev_err(dev, "failed to find any bus clocks\n");
+		ret = -ENOENT;
+		goto err_no_busclks;
+	}
+
+	sc->ioarea = request_mem_region(res->start, resource_size(res),
+					mmc_hostname(host->mmc));
+	if (!sc->ioarea) {
+		dev_err(dev, "failed to reserve register area\n");
+		ret = -ENXIO;
+		goto err_req_regs;
+	}
+
+	host->ioaddr = ioremap_nocache(res->start, resource_size(res));
+	if (!host->ioaddr) {
+		dev_err(dev, "failed to map registers\n");
+		ret = -ENXIO;
+		goto err_req_regs;
+	}
+
+	/* Ensure we have minimal gpio selected CMD/CLK/Detect */
+	if (pdata->cfg_gpio)
+		pdata->cfg_gpio(pdev, pdata->max_width);
+
+	host->hw_name = "samsung-hsmmc";
+	host->ops = &sdhci_s3c_ops;
+	host->quirks = 0;
+	host->irq = irq;
+
+	/* Setup quirks for the controller */
+
+	/* Currently with ADMA enabled we are getting some length
+	 * interrupts that are not being dealt with, do disable
+	 * ADMA until this is sorted out. */
+	host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
+	host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE;
+
+#ifndef CONFIG_MMC_SDHCI_S3C_DMA
+
+	/* we currently see overruns on errors, so disable the SDMA
+	 * support as well. */
+	host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
+
+	/* PIO currently has problems with multi-block IO */
+	host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+
+#endif /* CONFIG_MMC_SDHCI_S3C_DMA */
+
+	/* It seems we do not get an DATA transfer complete on non-busy
+	 * transfers, not sure if this is a problem with this specific
+	 * SDHCI block, or a missing configuration that needs to be set. */
+	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
+
+	host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
+			 SDHCI_QUIRK_32BIT_DMA_SIZE);
+
+	ret = sdhci_add_host(host);
+	if (ret) {
+		dev_err(dev, "sdhci_add_host() failed\n");
+		goto err_add_host;
+	}
+
+	return 0;
+
+ err_add_host:
+	release_resource(sc->ioarea);
+	kfree(sc->ioarea);
+
+ err_req_regs:
+	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
+		clk_disable(sc->clk_bus[ptr]);
+		clk_put(sc->clk_bus[ptr]);
+	}
+
+ err_no_busclks:
+	clk_disable(sc->clk_io);
+	clk_put(sc->clk_io);
+
+ err_io_clk:
+	sdhci_free_host(host);
+
+	return ret;
+}
+
+static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
+{
+	struct sdhci_host *host = platform_get_drvdata(dev);
+
+	sdhci_suspend_host(host, pm);
+	return 0;
+}
+
+static int sdhci_s3c_resume(struct platform_device *dev)
+{
+	struct sdhci_host *host = platform_get_drvdata(dev);
+
+	sdhci_resume_host(host);
+	return 0;
+}
+
+#else
+#define sdhci_s3c_suspend NULL
+#define sdhci_s3c_resume NULL
+#endif
+
+static struct platform_driver sdhci_s3c_driver = {
+	.probe		= sdhci_s3c_probe,
+	.remove		= __devexit_p(sdhci_s3c_remove),
+	.suspend	= sdhci_s3c_suspend,
+	.resume	        = sdhci_s3c_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "s3c-sdhci",
+	},
+};
+
+static int __init sdhci_s3c_init(void)
+{
+	return platform_driver_register(&sdhci_s3c_driver);
+}
+
+static void __exit sdhci_s3c_exit(void)
+{
+	platform_driver_unregister(&sdhci_s3c_driver);
+}
+
+module_init(sdhci_s3c_init);
+module_exit(sdhci_s3c_exit);
+
+MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:s3c-sdhci");
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/tmio_mmc.c linux-libre-2.6.31-gnu/drivers/mmc/host/tmio_mmc.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/tmio_mmc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/tmio_mmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,7 +10,7 @@
  *
  * Driver for the MMC / SD / SDIO cell found in:
  *
- * TC6393XB TC6391XB TC6387XB T7L66XB
+ * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
  *
  * This driver draws mainly on scattered spec sheets, Reverse engineering
  * of the toshiba e800  SD driver and some parts of the 2.4 ASIC3 driver (4 bit
@@ -35,69 +35,47 @@
 
 #include "tmio_mmc.h"
 
-/*
- * Fixme - documentation conflicts on what the clock values are for the
- * various dividers.
- * One document I have says that its a divisor of a 24MHz clock, another 33.
- * This probably depends on HCLK for a given platform, so we may need to
- * require HCLK be passed to us from the MFD core.
- *
- */
-
 static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
 {
-	void __iomem *cnf = host->cnf;
-	void __iomem *ctl = host->ctl;
 	u32 clk = 0, clock;
 
 	if (new_clock) {
-		for (clock = 46875, clk = 0x100; new_clock >= (clock<<1); ) {
+		for (clock = host->mmc->f_min, clk = 0x80000080;
+			new_clock >= (clock<<1); clk >>= 1)
 			clock <<= 1;
-			clk >>= 1;
-		}
-		if (clk & 0x1)
-			clk = 0x20000;
-
-		clk >>= 2;
-		tmio_iowrite8((clk & 0x8000) ? 0 : 1, cnf + CNF_SD_CLK_MODE);
 		clk |= 0x100;
 	}
 
-	tmio_iowrite16(clk, ctl + CTL_SD_CARD_CLK_CTL);
+	sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22);
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
 }
 
 static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
 {
-	void __iomem *ctl = host->ctl;
-
-	tmio_iowrite16(0x0000, ctl + CTL_CLK_AND_WAIT_CTL);
+	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
 	msleep(10);
-	tmio_iowrite16(tmio_ioread16(ctl + CTL_SD_CARD_CLK_CTL) & ~0x0100,
-	       ctl + CTL_SD_CARD_CLK_CTL);
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
+		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
 	msleep(10);
 }
 
 static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
 {
-	void __iomem *ctl = host->ctl;
-
-	tmio_iowrite16(tmio_ioread16(ctl + CTL_SD_CARD_CLK_CTL) | 0x0100,
-	       ctl + CTL_SD_CARD_CLK_CTL);
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
+		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
 	msleep(10);
-	tmio_iowrite16(0x0100, ctl + CTL_CLK_AND_WAIT_CTL);
+	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
 	msleep(10);
 }
 
 static void reset(struct tmio_mmc_host *host)
 {
-	void __iomem *ctl = host->ctl;
-
 	/* FIXME - should we set stop clock reg here */
-	tmio_iowrite16(0x0000, ctl + CTL_RESET_SD);
-	tmio_iowrite16(0x0000, ctl + CTL_RESET_SDIO);
+	sd_ctrl_write16(host, CTL_RESET_SD, 0x0000);
+	sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
 	msleep(10);
-	tmio_iowrite16(0x0001, ctl + CTL_RESET_SD);
-	tmio_iowrite16(0x0001, ctl + CTL_RESET_SDIO);
+	sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
+	sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
 	msleep(10);
 }
 
@@ -129,13 +107,12 @@
 static int
 tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
 {
-	void __iomem *ctl = host->ctl;
 	struct mmc_data *data = host->data;
 	int c = cmd->opcode;
 
 	/* Command 12 is handled by hardware */
 	if (cmd->opcode == 12 && !cmd->arg) {
-		tmio_iowrite16(0x001, ctl + CTL_STOP_INTERNAL_ACTION);
+		sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
 		return 0;
 	}
 
@@ -160,18 +137,18 @@
 	if (data) {
 		c |= DATA_PRESENT;
 		if (data->blocks > 1) {
-			tmio_iowrite16(0x100, ctl + CTL_STOP_INTERNAL_ACTION);
+			sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100);
 			c |= TRANSFER_MULTI;
 		}
 		if (data->flags & MMC_DATA_READ)
 			c |= TRANSFER_READ;
 	}
 
-	enable_mmc_irqs(ctl, TMIO_MASK_CMD);
+	enable_mmc_irqs(host, TMIO_MASK_CMD);
 
 	/* Fire off the command */
-	tmio_iowrite32(cmd->arg, ctl + CTL_ARG_REG);
-	tmio_iowrite16(c, ctl + CTL_SD_CMD);
+	sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg);
+	sd_ctrl_write16(host, CTL_SD_CMD, c);
 
 	return 0;
 }
@@ -183,7 +160,6 @@
  */
 static inline void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
 {
-	void __iomem *ctl = host->ctl;
 	struct mmc_data *data = host->data;
 	unsigned short *buf;
 	unsigned int count;
@@ -206,9 +182,9 @@
 
 	/* Transfer the data */
 	if (data->flags & MMC_DATA_READ)
-		tmio_ioread16_rep(ctl + CTL_SD_DATA_PORT, buf, count >> 1);
+		sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
 	else
-		tmio_iowrite16_rep(ctl + CTL_SD_DATA_PORT, buf, count >> 1);
+		sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
 
 	host->sg_off += count;
 
@@ -222,7 +198,6 @@
 
 static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
 {
-	void __iomem *ctl = host->ctl;
 	struct mmc_data *data = host->data;
 	struct mmc_command *stop;
 
@@ -251,13 +226,13 @@
 	 */
 
 	if (data->flags & MMC_DATA_READ)
-		disable_mmc_irqs(ctl, TMIO_MASK_READOP);
+		disable_mmc_irqs(host, TMIO_MASK_READOP);
 	else
-		disable_mmc_irqs(ctl, TMIO_MASK_WRITEOP);
+		disable_mmc_irqs(host, TMIO_MASK_WRITEOP);
 
 	if (stop) {
 		if (stop->opcode == 12 && !stop->arg)
-			tmio_iowrite16(0x000, ctl + CTL_STOP_INTERNAL_ACTION);
+			sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
 		else
 			BUG();
 	}
@@ -268,9 +243,8 @@
 static inline void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
 	unsigned int stat)
 {
-	void __iomem *ctl = host->ctl, *addr;
 	struct mmc_command *cmd = host->cmd;
-	int i;
+	int i, addr;
 
 	if (!host->cmd) {
 		pr_debug("Spurious CMD irq\n");
@@ -284,8 +258,8 @@
 	 * modify the order of the response for short response command types.
 	 */
 
-	for (i = 3, addr = ctl + CTL_RESPONSE ; i >= 0 ; i--, addr += 4)
-		cmd->resp[i] = tmio_ioread32(addr);
+	for (i = 3, addr = CTL_RESPONSE ; i >= 0 ; i--, addr += 4)
+		cmd->resp[i] = sd_ctrl_read32(host, addr);
 
 	if (cmd->flags &  MMC_RSP_136) {
 		cmd->resp[0] = (cmd->resp[0] << 8) | (cmd->resp[1] >> 24);
@@ -307,9 +281,9 @@
 	 */
 	if (host->data && !cmd->error) {
 		if (host->data->flags & MMC_DATA_READ)
-			enable_mmc_irqs(ctl, TMIO_MASK_READOP);
+			enable_mmc_irqs(host, TMIO_MASK_READOP);
 		else
-			enable_mmc_irqs(ctl, TMIO_MASK_WRITEOP);
+			enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
 	} else {
 		tmio_mmc_finish_request(host);
 	}
@@ -321,20 +295,19 @@
 static irqreturn_t tmio_mmc_irq(int irq, void *devid)
 {
 	struct tmio_mmc_host *host = devid;
-	void __iomem *ctl = host->ctl;
 	unsigned int ireg, irq_mask, status;
 
 	pr_debug("MMC IRQ begin\n");
 
-	status = tmio_ioread32(ctl + CTL_STATUS);
-	irq_mask = tmio_ioread32(ctl + CTL_IRQ_MASK);
+	status = sd_ctrl_read32(host, CTL_STATUS);
+	irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
 	ireg = status & TMIO_MASK_IRQ & ~irq_mask;
 
 	pr_debug_status(status);
 	pr_debug_status(ireg);
 
 	if (!ireg) {
-		disable_mmc_irqs(ctl, status & ~irq_mask);
+		disable_mmc_irqs(host, status & ~irq_mask);
 
 		pr_debug("tmio_mmc: Spurious irq, disabling! "
 			"0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
@@ -346,7 +319,7 @@
 	while (ireg) {
 		/* Card insert / remove attempts */
 		if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
-			ack_mmc_irqs(ctl, TMIO_STAT_CARD_INSERT |
+			ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
 				TMIO_STAT_CARD_REMOVE);
 			mmc_detect_change(host->mmc, 0);
 		}
@@ -358,25 +331,25 @@
 
 		/* Command completion */
 		if (ireg & TMIO_MASK_CMD) {
-			ack_mmc_irqs(ctl, TMIO_MASK_CMD);
+			ack_mmc_irqs(host, TMIO_MASK_CMD);
 			tmio_mmc_cmd_irq(host, status);
 		}
 
 		/* Data transfer */
 		if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
-			ack_mmc_irqs(ctl, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
+			ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
 			tmio_mmc_pio_irq(host);
 		}
 
 		/* Data transfer completion */
 		if (ireg & TMIO_STAT_DATAEND) {
-			ack_mmc_irqs(ctl, TMIO_STAT_DATAEND);
+			ack_mmc_irqs(host, TMIO_STAT_DATAEND);
 			tmio_mmc_data_irq(host);
 		}
 
 		/* Check status - keep going until we've handled it all */
-		status = tmio_ioread32(ctl + CTL_STATUS);
-		irq_mask = tmio_ioread32(ctl + CTL_IRQ_MASK);
+		status = sd_ctrl_read32(host, CTL_STATUS);
+		irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
 		ireg = status & TMIO_MASK_IRQ & ~irq_mask;
 
 		pr_debug("Status at end of loop: %08x\n", status);
@@ -391,8 +364,6 @@
 static int tmio_mmc_start_data(struct tmio_mmc_host *host,
 	struct mmc_data *data)
 {
-	void __iomem *ctl = host->ctl;
-
 	pr_debug("setup data transfer: blocksize %08x  nr_blocks %d\n",
 	    data->blksz, data->blocks);
 
@@ -407,8 +378,8 @@
 	host->data = data;
 
 	/* Set transfer length / blocksize */
-	tmio_iowrite16(data->blksz,  ctl + CTL_SD_XFER_LEN);
-	tmio_iowrite16(data->blocks, ctl + CTL_XFER_BLK_COUNT);
+	sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
+	sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
 
 	return 0;
 }
@@ -449,8 +420,6 @@
 static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct tmio_mmc_host *host = mmc_priv(mmc);
-	void __iomem *cnf = host->cnf;
-	void __iomem *ctl = host->ctl;
 
 	if (ios->clock)
 		tmio_mmc_set_clock(host, ios->clock);
@@ -458,12 +427,12 @@
 	/* Power sequence - OFF -> ON -> UP */
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF: /* power down SD bus */
-		tmio_iowrite8(0x00, cnf + CNF_PWR_CTL_2);
+		sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
 		tmio_mmc_clk_stop(host);
 		break;
 	case MMC_POWER_ON: /* power up SD bus */
 
-		tmio_iowrite8(0x02, cnf + CNF_PWR_CTL_2);
+		sd_config_write8(host, CNF_PWR_CTL_2, 0x02);
 		break;
 	case MMC_POWER_UP: /* start bus clock */
 		tmio_mmc_clk_start(host);
@@ -472,10 +441,10 @@
 
 	switch (ios->bus_width) {
 	case MMC_BUS_WIDTH_1:
-		tmio_iowrite16(0x80e0, ctl + CTL_SD_MEM_CARD_OPT);
+		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
 	break;
 	case MMC_BUS_WIDTH_4:
-		tmio_iowrite16(0x00e0, ctl + CTL_SD_MEM_CARD_OPT);
+		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
 	break;
 	}
 
@@ -486,9 +455,8 @@
 static int tmio_mmc_get_ro(struct mmc_host *mmc)
 {
 	struct tmio_mmc_host *host = mmc_priv(mmc);
-	void __iomem *ctl = host->ctl;
 
-	return (tmio_ioread16(ctl + CTL_STATUS) & TMIO_STAT_WRPROTECT) ? 0 : 1;
+	return (sd_ctrl_read16(host, CTL_STATUS) & TMIO_STAT_WRPROTECT) ? 0 : 1;
 }
 
 static struct mmc_host_ops tmio_mmc_ops = {
@@ -518,13 +486,8 @@
 	struct mfd_cell	*cell = (struct mfd_cell *)dev->dev.platform_data;
 	struct mmc_host *mmc = platform_get_drvdata(dev);
 	struct tmio_mmc_host *host = mmc_priv(mmc);
-	void __iomem *cnf = host->cnf;
 	int ret = 0;
 
-	/* Enable the MMC/SD Control registers */
-	tmio_iowrite16(SDCREN, cnf + CNF_CMD);
-	tmio_iowrite32(dev->resource[0].start & 0xfffe, cnf + CNF_CTL_BASE);
-
 	/* Tell the MFD core we are ready to be enabled */
 	if (cell->enable) {
 		ret = cell->enable(dev);
@@ -532,6 +495,11 @@
 			goto out;
 	}
 
+	/* Enable the MMC/SD Control registers */
+	sd_config_write16(host, CNF_CMD, SDCREN);
+	sd_config_write32(host, CNF_CTL_BASE,
+		(dev->resource[0].start >> host->bus_shift) & 0xfffe);
+
 	mmc_resume_host(mmc);
 
 out:
@@ -545,20 +513,25 @@
 static int __devinit tmio_mmc_probe(struct platform_device *dev)
 {
 	struct mfd_cell	*cell = (struct mfd_cell *)dev->dev.platform_data;
+	struct tmio_mmc_data *pdata;
 	struct resource *res_ctl, *res_cnf;
 	struct tmio_mmc_host *host;
 	struct mmc_host *mmc;
-	int ret = -ENOMEM;
+	int ret = -EINVAL;
 
 	if (dev->num_resources != 3)
 		goto out;
 
 	res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1);
-	if (!res_ctl || !res_cnf) {
-		ret = -EINVAL;
+	if (!res_ctl || !res_cnf)
 		goto out;
-	}
+
+	pdata = cell->driver_data;
+	if (!pdata || !pdata->hclk)
+		goto out;
+
+	ret = -ENOMEM;
 
 	mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &dev->dev);
 	if (!mmc)
@@ -568,6 +541,9 @@
 	host->mmc = mmc;
 	platform_set_drvdata(dev, mmc);
 
+	/* SD control register space size is 0x200, 0x400 for bus_shift=1 */
+	host->bus_shift = resource_size(res_ctl) >> 10;
+
 	host->ctl = ioremap(res_ctl->start, resource_size(res_ctl));
 	if (!host->ctl)
 		goto host_free;
@@ -578,15 +554,10 @@
 
 	mmc->ops = &tmio_mmc_ops;
 	mmc->caps = MMC_CAP_4_BIT_DATA;
-	mmc->f_min = 46875; /* 24000000 / 512 */
-	mmc->f_max = 24000000;
+	mmc->f_max = pdata->hclk;
+	mmc->f_min = mmc->f_max / 512;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
-	/* Enable the MMC/SD Control registers */
-	tmio_iowrite16(SDCREN, host->cnf + CNF_CMD);
-	tmio_iowrite32(dev->resource[0].start & 0xfffe,
-		host->cnf + CNF_CTL_BASE);
-
 	/* Tell the MFD core we are ready to be enabled */
 	if (cell->enable) {
 		ret = cell->enable(dev);
@@ -594,14 +565,19 @@
 			goto unmap_cnf;
 	}
 
+	/* Enable the MMC/SD Control registers */
+	sd_config_write16(host, CNF_CMD, SDCREN);
+	sd_config_write32(host, CNF_CTL_BASE,
+		(dev->resource[0].start >> host->bus_shift) & 0xfffe);
+
 	/* Disable SD power during suspend */
-	tmio_iowrite8(0x01, host->cnf + CNF_PWR_CTL_3);
+	sd_config_write8(host, CNF_PWR_CTL_3, 0x01);
 
 	/* The below is required but why? FIXME */
-	tmio_iowrite8(0x1f, host->cnf + CNF_STOP_CLK_CTL);
+	sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f);
 
 	/* Power down SD bus*/
-	tmio_iowrite8(0x0,  host->cnf + CNF_PWR_CTL_2);
+	sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
 
 	tmio_mmc_clk_stop(host);
 	reset(host);
@@ -612,22 +588,20 @@
 	else
 		goto unmap_cnf;
 
-	disable_mmc_irqs(host->ctl, TMIO_MASK_ALL);
+	disable_mmc_irqs(host, TMIO_MASK_ALL);
 
-	ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED, "tmio-mmc",
-		host);
+	ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
+		IRQF_TRIGGER_FALLING, "tmio-mmc", host);
 	if (ret)
 		goto unmap_cnf;
 
-	set_irq_type(host->irq, IRQ_TYPE_EDGE_FALLING);
-
 	mmc_add_host(mmc);
 
 	printk(KERN_INFO "%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
 	       (unsigned long)host->ctl, host->irq);
 
 	/* Unmask the IRQs we want to know about */
-	enable_mmc_irqs(host->ctl,  TMIO_MASK_IRQ);
+	enable_mmc_irqs(host, TMIO_MASK_IRQ);
 
 	return 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/tmio_mmc.h linux-libre-2.6.31-gnu/drivers/mmc/host/tmio_mmc.h
--- linux-libre-2.6.30-gnu/drivers/mmc/host/tmio_mmc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/tmio_mmc.h	2009-09-09 18:13:59.000000000 -0400
@@ -83,34 +83,36 @@
 		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
 #define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
 
-#define enable_mmc_irqs(ctl, i) \
+
+#define enable_mmc_irqs(host, i) \
 	do { \
 		u32 mask;\
-		mask  = tmio_ioread32((ctl) + CTL_IRQ_MASK); \
+		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
 		mask &= ~((i) & TMIO_MASK_IRQ); \
-		tmio_iowrite32(mask, (ctl) + CTL_IRQ_MASK); \
+		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
 	} while (0)
 
-#define disable_mmc_irqs(ctl, i) \
+#define disable_mmc_irqs(host, i) \
 	do { \
 		u32 mask;\
-		mask  = tmio_ioread32((ctl) + CTL_IRQ_MASK); \
+		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
 		mask |= ((i) & TMIO_MASK_IRQ); \
-		tmio_iowrite32(mask, (ctl) + CTL_IRQ_MASK); \
+		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
 	} while (0)
 
-#define ack_mmc_irqs(ctl, i) \
+#define ack_mmc_irqs(host, i) \
 	do { \
 		u32 mask;\
-		mask  = tmio_ioread32((ctl) + CTL_STATUS); \
+		mask  = sd_ctrl_read32((host), CTL_STATUS); \
 		mask &= ~((i) & TMIO_MASK_IRQ); \
-		tmio_iowrite32(mask, (ctl) + CTL_STATUS); \
+		sd_ctrl_write32((host), CTL_STATUS, mask); \
 	} while (0)
 
 
 struct tmio_mmc_host {
 	void __iomem *cnf;
 	void __iomem *ctl;
+	unsigned long bus_shift;
 	struct mmc_command      *cmd;
 	struct mmc_request      *mrq;
 	struct mmc_data         *data;
@@ -123,6 +125,63 @@
 	unsigned int            sg_off;
 };
 
+#include <linux/io.h>
+
+static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
+{
+	return readw(host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
+		u16 *buf, int count)
+{
+	readsw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
+{
+	return readw(host->ctl + (addr << host->bus_shift)) |
+	       readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
+}
+
+static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr,
+		u16 val)
+{
+	writew(val, host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
+		u16 *buf, int count)
+{
+	writesw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr,
+		u32 val)
+{
+	writew(val, host->ctl + (addr << host->bus_shift));
+	writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
+}
+
+static inline void sd_config_write8(struct tmio_mmc_host *host, int addr,
+		u8 val)
+{
+	writeb(val, host->cnf + (addr << host->bus_shift));
+}
+
+static inline void sd_config_write16(struct tmio_mmc_host *host, int addr,
+		u16 val)
+{
+	writew(val, host->cnf + (addr << host->bus_shift));
+}
+
+static inline void sd_config_write32(struct tmio_mmc_host *host, int addr,
+		u32 val)
+{
+	writew(val, host->cnf + (addr << host->bus_shift));
+	writew(val >> 16, host->cnf + ((addr + 2) << host->bus_shift));
+}
+
 #include <linux/scatterlist.h>
 #include <linux/blkdev.h>
 
diff -druN linux-libre-2.6.30-gnu/drivers/mmc/host/via-sdmmc.c linux-libre-2.6.31-gnu/drivers/mmc/host/via-sdmmc.c
--- linux-libre-2.6.30-gnu/drivers/mmc/host/via-sdmmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mmc/host/via-sdmmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1362 @@
+/*
+ *  drivers/mmc/host/via-sdmmc.c - VIA SD/MMC Card Reader driver
+ *  Copyright (c) 2008, VIA Technologies Inc. All Rights Reserved.
+ *
+ * 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/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+
+#include <linux/mmc/host.h>
+
+#define DRV_NAME	"via_sdmmc"
+
+#define PCI_DEVICE_ID_VIA_9530	0x9530
+
+#define VIA_CRDR_SDC_OFF	0x200
+#define VIA_CRDR_DDMA_OFF	0x400
+#define VIA_CRDR_PCICTRL_OFF	0x600
+
+#define VIA_CRDR_MIN_CLOCK	375000
+#define VIA_CRDR_MAX_CLOCK	48000000
+
+/*
+ * PCI registers
+ */
+
+#define VIA_CRDR_PCI_WORK_MODE	0x40
+#define VIA_CRDR_PCI_DBG_MODE	0x41
+
+/*
+ * SDC MMIO Registers
+ */
+
+#define VIA_CRDR_SDCTRL			0x0
+#define VIA_CRDR_SDCTRL_START		0x01
+#define VIA_CRDR_SDCTRL_WRITE		0x04
+#define VIA_CRDR_SDCTRL_SINGLE_WR	0x10
+#define VIA_CRDR_SDCTRL_SINGLE_RD	0x20
+#define VIA_CRDR_SDCTRL_MULTI_WR	0x30
+#define VIA_CRDR_SDCTRL_MULTI_RD	0x40
+#define VIA_CRDR_SDCTRL_STOP		0x70
+
+#define VIA_CRDR_SDCTRL_RSP_NONE	0x0
+#define VIA_CRDR_SDCTRL_RSP_R1		0x10000
+#define VIA_CRDR_SDCTRL_RSP_R2		0x20000
+#define VIA_CRDR_SDCTRL_RSP_R3		0x30000
+#define VIA_CRDR_SDCTRL_RSP_R1B		0x90000
+
+#define VIA_CRDR_SDCARG 	0x4
+
+#define VIA_CRDR_SDBUSMODE	0x8
+#define VIA_CRDR_SDMODE_4BIT	0x02
+#define VIA_CRDR_SDMODE_CLK_ON	0x40
+
+#define VIA_CRDR_SDBLKLEN	0xc
+/*
+ * Bit 0 -Bit 10 : Block length. So, the maximum block length should be 2048.
+ * Bit 11 - Bit 13 : Reserved.
+ * GPIDET : Select GPI pin to detect card, GPI means CR_CD# in top design.
+ * INTEN : Enable SD host interrupt.
+ * Bit 16 - Bit 31 : Block count. So, the maximun block count should be 65536.
+ */
+#define VIA_CRDR_SDBLKLEN_GPIDET	0x2000
+#define VIA_CRDR_SDBLKLEN_INTEN		0x8000
+#define VIA_CRDR_MAX_BLOCK_COUNT	65536
+#define VIA_CRDR_MAX_BLOCK_LENGTH	2048
+
+#define VIA_CRDR_SDRESP0	0x10
+#define VIA_CRDR_SDRESP1	0x14
+#define VIA_CRDR_SDRESP2	0x18
+#define VIA_CRDR_SDRESP3	0x1c
+
+#define VIA_CRDR_SDCURBLKCNT	0x20
+
+#define VIA_CRDR_SDINTMASK	0x24
+/*
+ * MBDIE : Multiple Blocks transfer Done Interrupt Enable
+ * BDDIE : Block Data transfer Done Interrupt Enable
+ * CIRIE : Card Insertion or Removal Interrupt Enable
+ * CRDIE : Command-Response transfer Done Interrupt Enable
+ * CRTOIE : Command-Response response TimeOut Interrupt Enable
+ * ASCRDIE : Auto Stop Command-Response transfer Done Interrupt Enable
+ * DTIE : Data access Timeout Interrupt Enable
+ * SCIE : reSponse CRC error Interrupt Enable
+ * RCIE : Read data CRC error Interrupt Enable
+ * WCIE : Write data CRC error Interrupt Enable
+ */
+#define VIA_CRDR_SDINTMASK_MBDIE	0x10
+#define VIA_CRDR_SDINTMASK_BDDIE	0x20
+#define VIA_CRDR_SDINTMASK_CIRIE	0x80
+#define VIA_CRDR_SDINTMASK_CRDIE	0x200
+#define VIA_CRDR_SDINTMASK_CRTOIE	0x400
+#define VIA_CRDR_SDINTMASK_ASCRDIE	0x800
+#define VIA_CRDR_SDINTMASK_DTIE		0x1000
+#define VIA_CRDR_SDINTMASK_SCIE		0x2000
+#define VIA_CRDR_SDINTMASK_RCIE		0x4000
+#define VIA_CRDR_SDINTMASK_WCIE		0x8000
+
+#define VIA_CRDR_SDACTIVE_INTMASK \
+	(VIA_CRDR_SDINTMASK_MBDIE | VIA_CRDR_SDINTMASK_CIRIE \
+	| VIA_CRDR_SDINTMASK_CRDIE | VIA_CRDR_SDINTMASK_CRTOIE \
+	| VIA_CRDR_SDINTMASK_DTIE | VIA_CRDR_SDINTMASK_SCIE \
+	| VIA_CRDR_SDINTMASK_RCIE | VIA_CRDR_SDINTMASK_WCIE)
+
+#define VIA_CRDR_SDSTATUS	0x28
+/*
+ * CECC : Reserved
+ * WP : SD card Write Protect status
+ * SLOTD : Reserved
+ * SLOTG : SD SLOT status(Gpi pin status)
+ * MBD : Multiple Blocks transfer Done interrupt status
+ * BDD : Block Data transfer Done interrupt status
+ * CD : Reserved
+ * CIR : Card Insertion or Removal interrupt detected on GPI pin
+ * IO : Reserved
+ * CRD : Command-Response transfer Done interrupt status
+ * CRTO : Command-Response response TimeOut interrupt status
+ * ASCRDIE : Auto Stop Command-Response transfer Done interrupt status
+ * DT : Data access Timeout interrupt status
+ * SC : reSponse CRC error interrupt status
+ * RC : Read data CRC error interrupt status
+ * WC : Write data CRC error interrupt status
+ */
+#define VIA_CRDR_SDSTS_CECC		0x01
+#define VIA_CRDR_SDSTS_WP		0x02
+#define VIA_CRDR_SDSTS_SLOTD		0x04
+#define VIA_CRDR_SDSTS_SLOTG		0x08
+#define VIA_CRDR_SDSTS_MBD		0x10
+#define VIA_CRDR_SDSTS_BDD		0x20
+#define VIA_CRDR_SDSTS_CD		0x40
+#define VIA_CRDR_SDSTS_CIR		0x80
+#define VIA_CRDR_SDSTS_IO		0x100
+#define VIA_CRDR_SDSTS_CRD		0x200
+#define VIA_CRDR_SDSTS_CRTO		0x400
+#define VIA_CRDR_SDSTS_ASCRDIE		0x800
+#define VIA_CRDR_SDSTS_DT		0x1000
+#define VIA_CRDR_SDSTS_SC		0x2000
+#define VIA_CRDR_SDSTS_RC		0x4000
+#define VIA_CRDR_SDSTS_WC		0x8000
+
+#define VIA_CRDR_SDSTS_IGN_MASK\
+	(VIA_CRDR_SDSTS_BDD | VIA_CRDR_SDSTS_ASCRDIE | VIA_CRDR_SDSTS_IO)
+#define VIA_CRDR_SDSTS_INT_MASK \
+	(VIA_CRDR_SDSTS_MBD | VIA_CRDR_SDSTS_BDD | VIA_CRDR_SDSTS_CD \
+	| VIA_CRDR_SDSTS_CIR | VIA_CRDR_SDSTS_IO | VIA_CRDR_SDSTS_CRD \
+	| VIA_CRDR_SDSTS_CRTO | VIA_CRDR_SDSTS_ASCRDIE | VIA_CRDR_SDSTS_DT \
+	| VIA_CRDR_SDSTS_SC | VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC)
+#define VIA_CRDR_SDSTS_W1C_MASK \
+	(VIA_CRDR_SDSTS_CECC | VIA_CRDR_SDSTS_MBD | VIA_CRDR_SDSTS_BDD \
+	| VIA_CRDR_SDSTS_CD | VIA_CRDR_SDSTS_CIR | VIA_CRDR_SDSTS_CRD \
+	| VIA_CRDR_SDSTS_CRTO | VIA_CRDR_SDSTS_ASCRDIE | VIA_CRDR_SDSTS_DT \
+	| VIA_CRDR_SDSTS_SC | VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC)
+#define  VIA_CRDR_SDSTS_CMD_MASK \
+	(VIA_CRDR_SDSTS_CRD | VIA_CRDR_SDSTS_CRTO | VIA_CRDR_SDSTS_SC)
+#define  VIA_CRDR_SDSTS_DATA_MASK\
+	(VIA_CRDR_SDSTS_MBD | VIA_CRDR_SDSTS_DT \
+	| VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC)
+
+#define VIA_CRDR_SDSTATUS2	0x2a
+/*
+ * CFE : Enable SD host automatic Clock FReezing
+ */
+#define VIA_CRDR_SDSTS_CFE		0x80
+
+#define VIA_CRDR_SDRSPTMO	0x2C
+
+#define VIA_CRDR_SDCLKSEL	0x30
+
+#define VIA_CRDR_SDEXTCTRL	0x34
+#define VIS_CRDR_SDEXTCTRL_AUTOSTOP_SD	0x01
+#define VIS_CRDR_SDEXTCTRL_SHIFT_9	0x02
+#define VIS_CRDR_SDEXTCTRL_MMC_8BIT	0x04
+#define VIS_CRDR_SDEXTCTRL_RELD_BLK	0x08
+#define VIS_CRDR_SDEXTCTRL_BAD_CMDA	0x10
+#define VIS_CRDR_SDEXTCTRL_BAD_DATA	0x20
+#define VIS_CRDR_SDEXTCTRL_AUTOSTOP_SPI	0x40
+#define VIA_CRDR_SDEXTCTRL_HISPD	0x80
+/* 0x38-0xFF reserved */
+
+/*
+ * Data DMA Control Registers
+ */
+
+#define VIA_CRDR_DMABASEADD	0x0
+#define VIA_CRDR_DMACOUNTER	0x4
+
+#define VIA_CRDR_DMACTRL	0x8
+/*
+ * DIR :Transaction Direction
+ * 0 : From card to memory
+ * 1 : From memory to card
+ */
+#define VIA_CRDR_DMACTRL_DIR		0x100
+#define VIA_CRDR_DMACTRL_ENIRQ		0x10000
+#define VIA_CRDR_DMACTRL_SFTRST		0x1000000
+
+#define VIA_CRDR_DMASTS		0xc
+
+#define VIA_CRDR_DMASTART	0x10
+/*0x14-0xFF reserved*/
+
+/*
+ * PCI Control Registers
+ */
+
+/*0x0 - 0x1 reserved*/
+#define VIA_CRDR_PCICLKGATT	0x2
+/*
+ * SFTRST :
+ * 0 : Soft reset all the controller and it will be de-asserted automatically
+ * 1 : Soft reset is de-asserted
+ */
+#define VIA_CRDR_PCICLKGATT_SFTRST	0x01
+/*
+ * 3V3 : Pad power select
+ * 0 : 1.8V
+ * 1 : 3.3V
+ * NOTE : No mater what the actual value should be, this bit always
+ * read as 0. This is a hardware bug.
+ */
+#define VIA_CRDR_PCICLKGATT_3V3	0x10
+/*
+ * PAD_PWRON : Pad Power on/off select
+ * 0 : Power off
+ * 1 : Power on
+  * NOTE : No mater what the actual value should be, this bit always
+ * read as 0. This is a hardware bug.
+ */
+#define VIA_CRDR_PCICLKGATT_PAD_PWRON	0x20
+
+#define VIA_CRDR_PCISDCCLK	0x5
+
+#define VIA_CRDR_PCIDMACLK	0x7
+#define VIA_CRDR_PCIDMACLK_SDC		0x2
+
+#define VIA_CRDR_PCIINTCTRL	0x8
+#define VIA_CRDR_PCIINTCTRL_SDCIRQEN	0x04
+
+#define VIA_CRDR_PCIINTSTATUS	0x9
+#define VIA_CRDR_PCIINTSTATUS_SDC	0x04
+
+#define  VIA_CRDR_PCITMOCTRL	0xa
+#define VIA_CRDR_PCITMOCTRL_NO		0x0
+#define VIA_CRDR_PCITMOCTRL_32US	0x1
+#define VIA_CRDR_PCITMOCTRL_256US	0x2
+#define VIA_CRDR_PCITMOCTRL_1024US	0x3
+#define VIA_CRDR_PCITMOCTRL_256MS	0x4
+#define VIA_CRDR_PCITMOCTRL_512MS	0x5
+#define VIA_CRDR_PCITMOCTRL_1024MS	0x6
+
+/*0xB-0xFF reserved*/
+
+enum PCI_HOST_CLK_CONTROL {
+	PCI_CLK_375K = 0x03,
+	PCI_CLK_8M = 0x04,
+	PCI_CLK_12M = 0x00,
+	PCI_CLK_16M = 0x05,
+	PCI_CLK_24M = 0x01,
+	PCI_CLK_33M = 0x06,
+	PCI_CLK_48M = 0x02
+};
+
+struct sdhcreg {
+	u32 sdcontrol_reg;
+	u32 sdcmdarg_reg;
+	u32 sdbusmode_reg;
+	u32 sdblklen_reg;
+	u32 sdresp_reg[4];
+	u32 sdcurblkcnt_reg;
+	u32 sdintmask_reg;
+	u32 sdstatus_reg;
+	u32 sdrsptmo_reg;
+	u32 sdclksel_reg;
+	u32 sdextctrl_reg;
+};
+
+struct pcictrlreg {
+	u8 reserve[2];
+	u8 pciclkgat_reg;
+	u8 pcinfcclk_reg;
+	u8 pcimscclk_reg;
+	u8 pcisdclk_reg;
+	u8 pcicaclk_reg;
+	u8 pcidmaclk_reg;
+	u8 pciintctrl_reg;
+	u8 pciintstatus_reg;
+	u8 pcitmoctrl_reg;
+	u8 Resv;
+};
+
+struct via_crdr_mmc_host {
+	struct mmc_host *mmc;
+	struct mmc_request *mrq;
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+
+	void __iomem *mmiobase;
+	void __iomem *sdhc_mmiobase;
+	void __iomem *ddma_mmiobase;
+	void __iomem *pcictrl_mmiobase;
+
+	struct pcictrlreg pm_pcictrl_reg;
+	struct sdhcreg pm_sdhc_reg;
+
+	struct work_struct carddet_work;
+	struct tasklet_struct finish_tasklet;
+
+	struct timer_list timer;
+	spinlock_t lock;
+	u8 power;
+	int reject;
+	unsigned int quirks;
+};
+
+/* some devices need a very long delay for power to stabilize */
+#define VIA_CRDR_QUIRK_300MS_PWRDELAY	0x0001
+
+static struct pci_device_id via_ids[] = {
+	{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_9530,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, via_ids);
+
+static void via_print_sdchc(struct via_crdr_mmc_host *host)
+{
+	void __iomem *addrbase = host->sdhc_mmiobase;
+
+	pr_debug("SDC MMIO Registers:\n");
+	pr_debug("SDCONTROL=%08x, SDCMDARG=%08x, SDBUSMODE=%08x\n",
+		 readl(addrbase + VIA_CRDR_SDCTRL),
+		 readl(addrbase + VIA_CRDR_SDCARG),
+		 readl(addrbase + VIA_CRDR_SDBUSMODE));
+	pr_debug("SDBLKLEN=%08x, SDCURBLKCNT=%08x, SDINTMASK=%08x\n",
+		 readl(addrbase + VIA_CRDR_SDBLKLEN),
+		 readl(addrbase + VIA_CRDR_SDCURBLKCNT),
+		 readl(addrbase + VIA_CRDR_SDINTMASK));
+	pr_debug("SDSTATUS=%08x, SDCLKSEL=%08x, SDEXTCTRL=%08x\n",
+		 readl(addrbase + VIA_CRDR_SDSTATUS),
+		 readl(addrbase + VIA_CRDR_SDCLKSEL),
+		 readl(addrbase + VIA_CRDR_SDEXTCTRL));
+}
+
+static void via_print_pcictrl(struct via_crdr_mmc_host *host)
+{
+	void __iomem *addrbase = host->pcictrl_mmiobase;
+
+	pr_debug("PCI Control Registers:\n");
+	pr_debug("PCICLKGATT=%02x, PCISDCCLK=%02x, PCIDMACLK=%02x\n",
+		 readb(addrbase + VIA_CRDR_PCICLKGATT),
+		 readb(addrbase + VIA_CRDR_PCISDCCLK),
+		 readb(addrbase + VIA_CRDR_PCIDMACLK));
+	pr_debug("PCIINTCTRL=%02x, PCIINTSTATUS=%02x\n",
+		 readb(addrbase + VIA_CRDR_PCIINTCTRL),
+		 readb(addrbase + VIA_CRDR_PCIINTSTATUS));
+}
+
+static void via_save_pcictrlreg(struct via_crdr_mmc_host *host)
+{
+	struct pcictrlreg *pm_pcictrl_reg;
+	void __iomem *addrbase;
+
+	pm_pcictrl_reg = &(host->pm_pcictrl_reg);
+	addrbase = host->pcictrl_mmiobase;
+
+	pm_pcictrl_reg->pciclkgat_reg = readb(addrbase + VIA_CRDR_PCICLKGATT);
+	pm_pcictrl_reg->pciclkgat_reg |=
+		VIA_CRDR_PCICLKGATT_3V3 | VIA_CRDR_PCICLKGATT_PAD_PWRON;
+	pm_pcictrl_reg->pcisdclk_reg = readb(addrbase + VIA_CRDR_PCISDCCLK);
+	pm_pcictrl_reg->pcidmaclk_reg = readb(addrbase + VIA_CRDR_PCIDMACLK);
+	pm_pcictrl_reg->pciintctrl_reg = readb(addrbase + VIA_CRDR_PCIINTCTRL);
+	pm_pcictrl_reg->pciintstatus_reg =
+		readb(addrbase + VIA_CRDR_PCIINTSTATUS);
+	pm_pcictrl_reg->pcitmoctrl_reg = readb(addrbase + VIA_CRDR_PCITMOCTRL);
+}
+
+static void via_restore_pcictrlreg(struct via_crdr_mmc_host *host)
+{
+	struct pcictrlreg *pm_pcictrl_reg;
+	void __iomem *addrbase;
+
+	pm_pcictrl_reg = &(host->pm_pcictrl_reg);
+	addrbase = host->pcictrl_mmiobase;
+
+	writeb(pm_pcictrl_reg->pciclkgat_reg, addrbase + VIA_CRDR_PCICLKGATT);
+	writeb(pm_pcictrl_reg->pcisdclk_reg, addrbase + VIA_CRDR_PCISDCCLK);
+	writeb(pm_pcictrl_reg->pcidmaclk_reg, addrbase + VIA_CRDR_PCIDMACLK);
+	writeb(pm_pcictrl_reg->pciintctrl_reg, addrbase + VIA_CRDR_PCIINTCTRL);
+	writeb(pm_pcictrl_reg->pciintstatus_reg,
+		addrbase + VIA_CRDR_PCIINTSTATUS);
+	writeb(pm_pcictrl_reg->pcitmoctrl_reg, addrbase + VIA_CRDR_PCITMOCTRL);
+}
+
+static void via_save_sdcreg(struct via_crdr_mmc_host *host)
+{
+	struct sdhcreg *pm_sdhc_reg;
+	void __iomem *addrbase;
+
+	pm_sdhc_reg = &(host->pm_sdhc_reg);
+	addrbase = host->sdhc_mmiobase;
+
+	pm_sdhc_reg->sdcontrol_reg = readl(addrbase + VIA_CRDR_SDCTRL);
+	pm_sdhc_reg->sdcmdarg_reg = readl(addrbase + VIA_CRDR_SDCARG);
+	pm_sdhc_reg->sdbusmode_reg = readl(addrbase + VIA_CRDR_SDBUSMODE);
+	pm_sdhc_reg->sdblklen_reg = readl(addrbase + VIA_CRDR_SDBLKLEN);
+	pm_sdhc_reg->sdcurblkcnt_reg = readl(addrbase + VIA_CRDR_SDCURBLKCNT);
+	pm_sdhc_reg->sdintmask_reg = readl(addrbase + VIA_CRDR_SDINTMASK);
+	pm_sdhc_reg->sdstatus_reg = readl(addrbase + VIA_CRDR_SDSTATUS);
+	pm_sdhc_reg->sdrsptmo_reg = readl(addrbase + VIA_CRDR_SDRSPTMO);
+	pm_sdhc_reg->sdclksel_reg = readl(addrbase + VIA_CRDR_SDCLKSEL);
+	pm_sdhc_reg->sdextctrl_reg = readl(addrbase + VIA_CRDR_SDEXTCTRL);
+}
+
+static void via_restore_sdcreg(struct via_crdr_mmc_host *host)
+{
+	struct sdhcreg *pm_sdhc_reg;
+	void __iomem *addrbase;
+
+	pm_sdhc_reg = &(host->pm_sdhc_reg);
+	addrbase = host->sdhc_mmiobase;
+
+	writel(pm_sdhc_reg->sdcontrol_reg, addrbase + VIA_CRDR_SDCTRL);
+	writel(pm_sdhc_reg->sdcmdarg_reg, addrbase + VIA_CRDR_SDCARG);
+	writel(pm_sdhc_reg->sdbusmode_reg, addrbase + VIA_CRDR_SDBUSMODE);
+	writel(pm_sdhc_reg->sdblklen_reg, addrbase + VIA_CRDR_SDBLKLEN);
+	writel(pm_sdhc_reg->sdcurblkcnt_reg, addrbase + VIA_CRDR_SDCURBLKCNT);
+	writel(pm_sdhc_reg->sdintmask_reg, addrbase + VIA_CRDR_SDINTMASK);
+	writel(pm_sdhc_reg->sdstatus_reg, addrbase + VIA_CRDR_SDSTATUS);
+	writel(pm_sdhc_reg->sdrsptmo_reg, addrbase + VIA_CRDR_SDRSPTMO);
+	writel(pm_sdhc_reg->sdclksel_reg, addrbase + VIA_CRDR_SDCLKSEL);
+	writel(pm_sdhc_reg->sdextctrl_reg, addrbase + VIA_CRDR_SDEXTCTRL);
+}
+
+static void via_pwron_sleep(struct via_crdr_mmc_host *sdhost)
+{
+	if (sdhost->quirks & VIA_CRDR_QUIRK_300MS_PWRDELAY)
+		msleep(300);
+	else
+		msleep(3);
+}
+
+static void via_set_ddma(struct via_crdr_mmc_host *host,
+			 dma_addr_t dmaaddr, u32 count, int dir, int enirq)
+{
+	void __iomem *addrbase;
+	u32 ctrl_data = 0;
+
+	if (enirq)
+		ctrl_data |= VIA_CRDR_DMACTRL_ENIRQ;
+
+	if (dir)
+		ctrl_data |= VIA_CRDR_DMACTRL_DIR;
+
+	addrbase = host->ddma_mmiobase;
+
+	writel(dmaaddr, addrbase + VIA_CRDR_DMABASEADD);
+	writel(count, addrbase + VIA_CRDR_DMACOUNTER);
+	writel(ctrl_data, addrbase + VIA_CRDR_DMACTRL);
+	writel(0x01, addrbase + VIA_CRDR_DMASTART);
+
+	/* It seems that our DMA can not work normally with 375kHz clock */
+	/* FIXME: don't brute-force 8MHz but use PIO at 375kHz !! */
+	addrbase = host->pcictrl_mmiobase;
+	if (readb(addrbase + VIA_CRDR_PCISDCCLK) == PCI_CLK_375K) {
+		dev_info(host->mmc->parent, "forcing card speed to 8MHz\n");
+		writeb(PCI_CLK_8M, addrbase + VIA_CRDR_PCISDCCLK);
+	}
+}
+
+static void via_sdc_preparedata(struct via_crdr_mmc_host *host,
+				struct mmc_data *data)
+{
+	void __iomem *addrbase;
+	u32 blk_reg;
+	int count;
+
+	WARN_ON(host->data);
+
+	/* Sanity checks */
+	BUG_ON(data->blksz > host->mmc->max_blk_size);
+	BUG_ON(data->blocks > host->mmc->max_blk_count);
+
+	host->data = data;
+
+	count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+		((data->flags & MMC_DATA_READ) ?
+		PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE));
+	BUG_ON(count != 1);
+
+	via_set_ddma(host, sg_dma_address(data->sg), sg_dma_len(data->sg),
+		(data->flags & MMC_DATA_WRITE) ? 1 : 0, 1);
+
+	addrbase = host->sdhc_mmiobase;
+
+	blk_reg = data->blksz - 1;
+	blk_reg |= VIA_CRDR_SDBLKLEN_GPIDET | VIA_CRDR_SDBLKLEN_INTEN;
+	blk_reg |= (data->blocks) << 16;
+
+	writel(blk_reg, addrbase + VIA_CRDR_SDBLKLEN);
+}
+
+static void via_sdc_get_response(struct via_crdr_mmc_host *host,
+				 struct mmc_command *cmd)
+{
+	void __iomem *addrbase = host->sdhc_mmiobase;
+	u32 dwdata0 = readl(addrbase + VIA_CRDR_SDRESP0);
+	u32 dwdata1 = readl(addrbase + VIA_CRDR_SDRESP1);
+	u32 dwdata2 = readl(addrbase + VIA_CRDR_SDRESP2);
+	u32 dwdata3 = readl(addrbase + VIA_CRDR_SDRESP3);
+
+	if (cmd->flags & MMC_RSP_136) {
+		cmd->resp[0] = ((u8) (dwdata1)) |
+		    (((u8) (dwdata0 >> 24)) << 8) |
+		    (((u8) (dwdata0 >> 16)) << 16) |
+		    (((u8) (dwdata0 >> 8)) << 24);
+
+		cmd->resp[1] = ((u8) (dwdata2)) |
+		    (((u8) (dwdata1 >> 24)) << 8) |
+		    (((u8) (dwdata1 >> 16)) << 16) |
+		    (((u8) (dwdata1 >> 8)) << 24);
+
+		cmd->resp[2] = ((u8) (dwdata3)) |
+		    (((u8) (dwdata2 >> 24)) << 8) |
+		    (((u8) (dwdata2 >> 16)) << 16) |
+		    (((u8) (dwdata2 >> 8)) << 24);
+
+		cmd->resp[3] = 0xff |
+		    ((((u8) (dwdata3 >> 24))) << 8) |
+		    (((u8) (dwdata3 >> 16)) << 16) |
+		    (((u8) (dwdata3 >> 8)) << 24);
+	} else {
+		dwdata0 >>= 8;
+		cmd->resp[0] = ((dwdata0 & 0xff) << 24) |
+		    (((dwdata0 >> 8) & 0xff) << 16) |
+		    (((dwdata0 >> 16) & 0xff) << 8) | (dwdata1 & 0xff);
+
+		dwdata1 >>= 8;
+		cmd->resp[1] = ((dwdata1 & 0xff) << 24) |
+		    (((dwdata1 >> 8) & 0xff) << 16) |
+		    (((dwdata1 >> 16) & 0xff) << 8);
+	}
+}
+
+static void via_sdc_send_command(struct via_crdr_mmc_host *host,
+				 struct mmc_command *cmd)
+{
+	void __iomem *addrbase;
+	struct mmc_data *data;
+	u32 cmdctrl = 0;
+
+	WARN_ON(host->cmd);
+
+	data = cmd->data;
+	mod_timer(&host->timer, jiffies + HZ);
+	host->cmd = cmd;
+
+	/*Command index*/
+	cmdctrl = cmd->opcode << 8;
+
+	/*Response type*/
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		cmdctrl |= VIA_CRDR_SDCTRL_RSP_NONE;
+		break;
+	case MMC_RSP_R1:
+		cmdctrl |= VIA_CRDR_SDCTRL_RSP_R1;
+		break;
+	case MMC_RSP_R1B:
+		cmdctrl |= VIA_CRDR_SDCTRL_RSP_R1B;
+		break;
+	case MMC_RSP_R2:
+		cmdctrl |= VIA_CRDR_SDCTRL_RSP_R2;
+		break;
+	case MMC_RSP_R3:
+		cmdctrl |= VIA_CRDR_SDCTRL_RSP_R3;
+		break;
+	default:
+		pr_err("%s: cmd->flag is not valid\n", mmc_hostname(host->mmc));
+		break;
+	}
+
+	if (!(cmd->data))
+		goto nodata;
+
+	via_sdc_preparedata(host, data);
+
+	/*Command control*/
+	if (data->blocks > 1) {
+		if (data->flags & MMC_DATA_WRITE) {
+			cmdctrl |= VIA_CRDR_SDCTRL_WRITE;
+			cmdctrl |= VIA_CRDR_SDCTRL_MULTI_WR;
+		} else {
+			cmdctrl |= VIA_CRDR_SDCTRL_MULTI_RD;
+		}
+	} else {
+		if (data->flags & MMC_DATA_WRITE) {
+			cmdctrl |= VIA_CRDR_SDCTRL_WRITE;
+			cmdctrl |= VIA_CRDR_SDCTRL_SINGLE_WR;
+		} else {
+			cmdctrl |= VIA_CRDR_SDCTRL_SINGLE_RD;
+		}
+	}
+
+nodata:
+	if (cmd == host->mrq->stop)
+		cmdctrl |= VIA_CRDR_SDCTRL_STOP;
+
+	cmdctrl |= VIA_CRDR_SDCTRL_START;
+
+	addrbase = host->sdhc_mmiobase;
+	writel(cmd->arg, addrbase + VIA_CRDR_SDCARG);
+	writel(cmdctrl, addrbase + VIA_CRDR_SDCTRL);
+}
+
+static void via_sdc_finish_data(struct via_crdr_mmc_host *host)
+{
+	struct mmc_data *data;
+
+	BUG_ON(!host->data);
+
+	data = host->data;
+	host->data = NULL;
+
+	if (data->error)
+		data->bytes_xfered = 0;
+	else
+		data->bytes_xfered = data->blocks * data->blksz;
+
+	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+		((data->flags & MMC_DATA_READ) ?
+		PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE));
+
+	if (data->stop)
+		via_sdc_send_command(host, data->stop);
+	else
+		tasklet_schedule(&host->finish_tasklet);
+}
+
+static void via_sdc_finish_command(struct via_crdr_mmc_host *host)
+{
+	via_sdc_get_response(host, host->cmd);
+
+	host->cmd->error = 0;
+
+	if (!host->cmd->data)
+		tasklet_schedule(&host->finish_tasklet);
+
+	host->cmd = NULL;
+}
+
+static void via_sdc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	void __iomem *addrbase;
+	struct via_crdr_mmc_host *host;
+	unsigned long flags;
+	u16 status;
+
+	host = mmc_priv(mmc);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	addrbase = host->pcictrl_mmiobase;
+	writeb(VIA_CRDR_PCIDMACLK_SDC, addrbase + VIA_CRDR_PCIDMACLK);
+
+	status = readw(host->sdhc_mmiobase + VIA_CRDR_SDSTATUS);
+	status &= VIA_CRDR_SDSTS_W1C_MASK;
+	writew(status, host->sdhc_mmiobase + VIA_CRDR_SDSTATUS);
+
+	WARN_ON(host->mrq != NULL);
+	host->mrq = mrq;
+
+	status = readw(host->sdhc_mmiobase + VIA_CRDR_SDSTATUS);
+	if (!(status & VIA_CRDR_SDSTS_SLOTG) || host->reject) {
+		host->mrq->cmd->error = -ENOMEDIUM;
+		tasklet_schedule(&host->finish_tasklet);
+	} else {
+		via_sdc_send_command(host, mrq->cmd);
+	}
+
+	mmiowb();
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void via_sdc_set_power(struct via_crdr_mmc_host *host,
+			      unsigned short power, unsigned int on)
+{
+	unsigned long flags;
+	u8 gatt;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->power = (1 << power);
+
+	gatt = readb(host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	if (host->power == MMC_VDD_165_195)
+		gatt &= ~VIA_CRDR_PCICLKGATT_3V3;
+	else
+		gatt |= VIA_CRDR_PCICLKGATT_3V3;
+	if (on)
+		gatt |= VIA_CRDR_PCICLKGATT_PAD_PWRON;
+	else
+		gatt &= ~VIA_CRDR_PCICLKGATT_PAD_PWRON;
+	writeb(gatt, host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+
+	mmiowb();
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	via_pwron_sleep(host);
+}
+
+static void via_sdc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct via_crdr_mmc_host *host;
+	unsigned long flags;
+	void __iomem *addrbase;
+	u32 org_data, sdextctrl;
+	u8 clock;
+
+	host = mmc_priv(mmc);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	addrbase = host->sdhc_mmiobase;
+	org_data = readl(addrbase + VIA_CRDR_SDBUSMODE);
+	sdextctrl = readl(addrbase + VIA_CRDR_SDEXTCTRL);
+
+	if (ios->bus_width == MMC_BUS_WIDTH_1)
+		org_data &= ~VIA_CRDR_SDMODE_4BIT;
+	else
+		org_data |= VIA_CRDR_SDMODE_4BIT;
+
+	if (ios->power_mode == MMC_POWER_OFF)
+		org_data &= ~VIA_CRDR_SDMODE_CLK_ON;
+	else
+		org_data |= VIA_CRDR_SDMODE_CLK_ON;
+
+	if (ios->timing == MMC_TIMING_SD_HS)
+		sdextctrl |= VIA_CRDR_SDEXTCTRL_HISPD;
+	else
+		sdextctrl &= ~VIA_CRDR_SDEXTCTRL_HISPD;
+
+	writel(org_data, addrbase + VIA_CRDR_SDBUSMODE);
+	writel(sdextctrl, addrbase + VIA_CRDR_SDEXTCTRL);
+
+	if (ios->clock >= 48000000)
+		clock = PCI_CLK_48M;
+	else if (ios->clock >= 33000000)
+		clock = PCI_CLK_33M;
+	else if (ios->clock >= 24000000)
+		clock = PCI_CLK_24M;
+	else if (ios->clock >= 16000000)
+		clock = PCI_CLK_16M;
+	else if (ios->clock >= 12000000)
+		clock = PCI_CLK_12M;
+	else if (ios->clock >=  8000000)
+		clock = PCI_CLK_8M;
+	else
+		clock = PCI_CLK_375K;
+
+	addrbase = host->pcictrl_mmiobase;
+	if (readb(addrbase + VIA_CRDR_PCISDCCLK) != clock)
+		writeb(clock, addrbase + VIA_CRDR_PCISDCCLK);
+
+	mmiowb();
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (ios->power_mode != MMC_POWER_OFF)
+		via_sdc_set_power(host, ios->vdd, 1);
+	else
+		via_sdc_set_power(host, ios->vdd, 0);
+}
+
+static int via_sdc_get_ro(struct mmc_host *mmc)
+{
+	struct via_crdr_mmc_host *host;
+	unsigned long flags;
+	u16 status;
+
+	host = mmc_priv(mmc);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	status = readw(host->sdhc_mmiobase + VIA_CRDR_SDSTATUS);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return !(status & VIA_CRDR_SDSTS_WP);
+}
+
+static const struct mmc_host_ops via_sdc_ops = {
+	.request = via_sdc_request,
+	.set_ios = via_sdc_set_ios,
+	.get_ro = via_sdc_get_ro,
+};
+
+static void via_reset_pcictrl(struct via_crdr_mmc_host *host)
+{
+	void __iomem *addrbase;
+	unsigned long flags;
+	u8 gatt;
+
+	addrbase = host->pcictrl_mmiobase;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	via_save_pcictrlreg(host);
+	via_save_sdcreg(host);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	gatt = VIA_CRDR_PCICLKGATT_PAD_PWRON;
+	if (host->power == MMC_VDD_165_195)
+		gatt &= VIA_CRDR_PCICLKGATT_3V3;
+	else
+		gatt |= VIA_CRDR_PCICLKGATT_3V3;
+	writeb(gatt, host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	via_pwron_sleep(host);
+	gatt |= VIA_CRDR_PCICLKGATT_SFTRST;
+	writeb(gatt, host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	msleep(3);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	via_restore_pcictrlreg(host);
+	via_restore_sdcreg(host);
+
+	mmiowb();
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void via_sdc_cmd_isr(struct via_crdr_mmc_host *host, u16 intmask)
+{
+	BUG_ON(intmask == 0);
+
+	if (!host->cmd) {
+		pr_err("%s: Got command interrupt 0x%x even "
+		       "though no command operation was in progress.\n",
+		       mmc_hostname(host->mmc), intmask);
+		return;
+	}
+
+	if (intmask & VIA_CRDR_SDSTS_CRTO)
+		host->cmd->error = -ETIMEDOUT;
+	else if (intmask & VIA_CRDR_SDSTS_SC)
+		host->cmd->error = -EILSEQ;
+
+	if (host->cmd->error)
+		tasklet_schedule(&host->finish_tasklet);
+	else if (intmask & VIA_CRDR_SDSTS_CRD)
+		via_sdc_finish_command(host);
+}
+
+static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask)
+{
+	BUG_ON(intmask == 0);
+
+	if (intmask & VIA_CRDR_SDSTS_DT)
+		host->data->error = -ETIMEDOUT;
+	else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC))
+		host->data->error = -EILSEQ;
+
+	via_sdc_finish_data(host);
+}
+
+static irqreturn_t via_sdc_isr(int irq, void *dev_id)
+{
+	struct via_crdr_mmc_host *sdhost = dev_id;
+	void __iomem *addrbase;
+	u8 pci_status;
+	u16 sd_status;
+	irqreturn_t result;
+
+	if (!sdhost)
+		return IRQ_NONE;
+
+	spin_lock(&sdhost->lock);
+
+	addrbase = sdhost->pcictrl_mmiobase;
+	pci_status = readb(addrbase + VIA_CRDR_PCIINTSTATUS);
+	if (!(pci_status & VIA_CRDR_PCIINTSTATUS_SDC)) {
+		result = IRQ_NONE;
+		goto out;
+	}
+
+	addrbase = sdhost->sdhc_mmiobase;
+	sd_status = readw(addrbase + VIA_CRDR_SDSTATUS);
+	sd_status &= VIA_CRDR_SDSTS_INT_MASK;
+	sd_status &= ~VIA_CRDR_SDSTS_IGN_MASK;
+	if (!sd_status) {
+		result = IRQ_NONE;
+		goto out;
+	}
+
+	if (sd_status & VIA_CRDR_SDSTS_CIR) {
+		writew(sd_status & VIA_CRDR_SDSTS_CIR,
+			addrbase + VIA_CRDR_SDSTATUS);
+
+		schedule_work(&sdhost->carddet_work);
+	}
+
+	sd_status &= ~VIA_CRDR_SDSTS_CIR;
+	if (sd_status & VIA_CRDR_SDSTS_CMD_MASK) {
+		writew(sd_status & VIA_CRDR_SDSTS_CMD_MASK,
+			addrbase + VIA_CRDR_SDSTATUS);
+		via_sdc_cmd_isr(sdhost, sd_status & VIA_CRDR_SDSTS_CMD_MASK);
+	}
+	if (sd_status & VIA_CRDR_SDSTS_DATA_MASK) {
+		writew(sd_status & VIA_CRDR_SDSTS_DATA_MASK,
+			addrbase + VIA_CRDR_SDSTATUS);
+		via_sdc_data_isr(sdhost, sd_status & VIA_CRDR_SDSTS_DATA_MASK);
+	}
+
+	sd_status &= ~(VIA_CRDR_SDSTS_CMD_MASK | VIA_CRDR_SDSTS_DATA_MASK);
+	if (sd_status) {
+		pr_err("%s: Unexpected interrupt 0x%x\n",
+		       mmc_hostname(sdhost->mmc), sd_status);
+		writew(sd_status, addrbase + VIA_CRDR_SDSTATUS);
+	}
+
+	result = IRQ_HANDLED;
+
+	mmiowb();
+out:
+	spin_unlock(&sdhost->lock);
+
+	return result;
+}
+
+static void via_sdc_timeout(unsigned long ulongdata)
+{
+	struct via_crdr_mmc_host *sdhost;
+	unsigned long flags;
+
+	sdhost = (struct via_crdr_mmc_host *)ulongdata;
+
+	spin_lock_irqsave(&sdhost->lock, flags);
+
+	if (sdhost->mrq) {
+		pr_err("%s: Timeout waiting for hardware interrupt."
+		       "cmd:0x%x\n", mmc_hostname(sdhost->mmc),
+		       sdhost->mrq->cmd->opcode);
+
+		if (sdhost->data) {
+			writel(VIA_CRDR_DMACTRL_SFTRST,
+				sdhost->ddma_mmiobase + VIA_CRDR_DMACTRL);
+			sdhost->data->error = -ETIMEDOUT;
+			via_sdc_finish_data(sdhost);
+		} else {
+			if (sdhost->cmd)
+				sdhost->cmd->error = -ETIMEDOUT;
+			else
+				sdhost->mrq->cmd->error = -ETIMEDOUT;
+			tasklet_schedule(&sdhost->finish_tasklet);
+		}
+	}
+
+	mmiowb();
+	spin_unlock_irqrestore(&sdhost->lock, flags);
+}
+
+static void via_sdc_tasklet_finish(unsigned long param)
+{
+	struct via_crdr_mmc_host *host;
+	unsigned long flags;
+	struct mmc_request *mrq;
+
+	host = (struct via_crdr_mmc_host *)param;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	del_timer(&host->timer);
+	mrq = host->mrq;
+	host->mrq = NULL;
+	host->cmd = NULL;
+	host->data = NULL;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+static void via_sdc_card_detect(struct work_struct *work)
+{
+	struct via_crdr_mmc_host *host;
+	void __iomem *addrbase;
+	unsigned long flags;
+	u16 status;
+
+	host = container_of(work, struct via_crdr_mmc_host, carddet_work);
+
+	addrbase = host->ddma_mmiobase;
+	writel(VIA_CRDR_DMACTRL_SFTRST, addrbase + VIA_CRDR_DMACTRL);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	addrbase = host->pcictrl_mmiobase;
+	writeb(VIA_CRDR_PCIDMACLK_SDC, addrbase + VIA_CRDR_PCIDMACLK);
+
+	addrbase = host->sdhc_mmiobase;
+	status = readw(addrbase + VIA_CRDR_SDSTATUS);
+	if (!(status & VIA_CRDR_SDSTS_SLOTG)) {
+		if (host->mrq) {
+			pr_err("%s: Card removed during transfer!\n",
+			       mmc_hostname(host->mmc));
+			host->mrq->cmd->error = -ENOMEDIUM;
+			tasklet_schedule(&host->finish_tasklet);
+		}
+
+		mmiowb();
+		spin_unlock_irqrestore(&host->lock, flags);
+
+		via_reset_pcictrl(host);
+
+		spin_lock_irqsave(&host->lock, flags);
+	}
+
+	mmiowb();
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	via_print_pcictrl(host);
+	via_print_sdchc(host);
+
+	mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+}
+
+static void via_init_mmc_host(struct via_crdr_mmc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+	void __iomem *addrbase;
+	u32 lenreg;
+	u32 status;
+
+	init_timer(&host->timer);
+	host->timer.data = (unsigned long)host;
+	host->timer.function = via_sdc_timeout;
+
+	spin_lock_init(&host->lock);
+
+	mmc->f_min = VIA_CRDR_MIN_CLOCK;
+	mmc->f_max = VIA_CRDR_MAX_CLOCK;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED;
+	mmc->ops = &via_sdc_ops;
+
+	/*Hardware cannot do scatter lists*/
+	mmc->max_hw_segs = 1;
+	mmc->max_phys_segs = 1;
+
+	mmc->max_blk_size = VIA_CRDR_MAX_BLOCK_LENGTH;
+	mmc->max_blk_count = VIA_CRDR_MAX_BLOCK_COUNT;
+
+	mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count;
+	mmc->max_req_size = mmc->max_seg_size;
+
+	INIT_WORK(&host->carddet_work, via_sdc_card_detect);
+
+	tasklet_init(&host->finish_tasklet, via_sdc_tasklet_finish,
+		     (unsigned long)host);
+
+	addrbase = host->sdhc_mmiobase;
+	writel(0x0, addrbase + VIA_CRDR_SDINTMASK);
+	msleep(1);
+
+	lenreg = VIA_CRDR_SDBLKLEN_GPIDET | VIA_CRDR_SDBLKLEN_INTEN;
+	writel(lenreg, addrbase + VIA_CRDR_SDBLKLEN);
+
+	status = readw(addrbase + VIA_CRDR_SDSTATUS);
+	status &= VIA_CRDR_SDSTS_W1C_MASK;
+	writew(status, addrbase + VIA_CRDR_SDSTATUS);
+
+	status = readw(addrbase + VIA_CRDR_SDSTATUS2);
+	status |= VIA_CRDR_SDSTS_CFE;
+	writew(status, addrbase + VIA_CRDR_SDSTATUS2);
+
+	writeb(0x0, addrbase + VIA_CRDR_SDEXTCTRL);
+
+	writel(VIA_CRDR_SDACTIVE_INTMASK, addrbase + VIA_CRDR_SDINTMASK);
+	msleep(1);
+}
+
+static int __devinit via_sd_probe(struct pci_dev *pcidev,
+				    const struct pci_device_id *id)
+{
+	struct mmc_host *mmc;
+	struct via_crdr_mmc_host *sdhost;
+	u32 base, len;
+	u8 rev, gatt;
+	int ret;
+
+	pci_read_config_byte(pcidev, PCI_CLASS_REVISION, &rev);
+	pr_info(DRV_NAME
+		": VIA SDMMC controller found at %s [%04x:%04x] (rev %x)\n",
+		pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device,
+		(int)rev);
+
+	ret = pci_enable_device(pcidev);
+	if (ret)
+		return ret;
+
+	ret = pci_request_regions(pcidev, DRV_NAME);
+	if (ret)
+		goto disable;
+
+	pci_write_config_byte(pcidev, VIA_CRDR_PCI_WORK_MODE, 0);
+	pci_write_config_byte(pcidev, VIA_CRDR_PCI_DBG_MODE, 0);
+
+	mmc = mmc_alloc_host(sizeof(struct via_crdr_mmc_host), &pcidev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto release;
+	}
+
+	sdhost = mmc_priv(mmc);
+	sdhost->mmc = mmc;
+	dev_set_drvdata(&pcidev->dev, sdhost);
+
+	len = pci_resource_len(pcidev, 0);
+	base = pci_resource_start(pcidev, 0);
+	sdhost->mmiobase = ioremap_nocache(base, len);
+	if (!sdhost->mmiobase) {
+		ret = -ENOMEM;
+		goto free_mmc_host;
+	}
+
+	sdhost->sdhc_mmiobase =
+		sdhost->mmiobase + VIA_CRDR_SDC_OFF;
+	sdhost->ddma_mmiobase =
+		sdhost->mmiobase + VIA_CRDR_DDMA_OFF;
+	sdhost->pcictrl_mmiobase =
+		sdhost->mmiobase + VIA_CRDR_PCICTRL_OFF;
+
+	sdhost->power = MMC_VDD_165_195;
+
+	gatt = VIA_CRDR_PCICLKGATT_3V3 | VIA_CRDR_PCICLKGATT_PAD_PWRON;
+	writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	via_pwron_sleep(sdhost);
+	gatt |= VIA_CRDR_PCICLKGATT_SFTRST;
+	writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	msleep(3);
+
+	via_init_mmc_host(sdhost);
+
+	ret =
+	    request_irq(pcidev->irq, via_sdc_isr, IRQF_SHARED, DRV_NAME,
+			sdhost);
+	if (ret)
+		goto unmap;
+
+	writeb(VIA_CRDR_PCIINTCTRL_SDCIRQEN,
+	       sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL);
+	writeb(VIA_CRDR_PCITMOCTRL_1024MS,
+	       sdhost->pcictrl_mmiobase + VIA_CRDR_PCITMOCTRL);
+
+	/* device-specific quirks */
+	if (pcidev->subsystem_vendor == PCI_VENDOR_ID_LENOVO &&
+	    pcidev->subsystem_device == 0x3891)
+		sdhost->quirks = VIA_CRDR_QUIRK_300MS_PWRDELAY;
+
+	mmc_add_host(mmc);
+
+	return 0;
+
+unmap:
+	iounmap(sdhost->mmiobase);
+free_mmc_host:
+	dev_set_drvdata(&pcidev->dev, NULL);
+	mmc_free_host(mmc);
+release:
+	pci_release_regions(pcidev);
+disable:
+	pci_disable_device(pcidev);
+
+	return ret;
+}
+
+static void __devexit via_sd_remove(struct pci_dev *pcidev)
+{
+	struct via_crdr_mmc_host *sdhost = pci_get_drvdata(pcidev);
+	unsigned long flags;
+	u8 gatt;
+
+	spin_lock_irqsave(&sdhost->lock, flags);
+
+	/* Ensure we don't accept more commands from mmc layer */
+	sdhost->reject = 1;
+
+	/* Disable generating further interrupts */
+	writeb(0x0, sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL);
+	mmiowb();
+
+	if (sdhost->mrq) {
+		printk(KERN_ERR "%s: Controller removed during "
+			"transfer\n", mmc_hostname(sdhost->mmc));
+
+		/* make sure all DMA is stopped */
+		writel(VIA_CRDR_DMACTRL_SFTRST,
+			sdhost->ddma_mmiobase + VIA_CRDR_DMACTRL);
+		mmiowb();
+		sdhost->mrq->cmd->error = -ENOMEDIUM;
+		if (sdhost->mrq->stop)
+			sdhost->mrq->stop->error = -ENOMEDIUM;
+		tasklet_schedule(&sdhost->finish_tasklet);
+	}
+	spin_unlock_irqrestore(&sdhost->lock, flags);
+
+	mmc_remove_host(sdhost->mmc);
+
+	free_irq(pcidev->irq, sdhost);
+
+	del_timer_sync(&sdhost->timer);
+
+	tasklet_kill(&sdhost->finish_tasklet);
+
+	/* switch off power */
+	gatt = readb(sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	gatt &= ~VIA_CRDR_PCICLKGATT_PAD_PWRON;
+	writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+
+	iounmap(sdhost->mmiobase);
+	dev_set_drvdata(&pcidev->dev, NULL);
+	mmc_free_host(sdhost->mmc);
+	pci_release_regions(pcidev);
+	pci_disable_device(pcidev);
+
+	pr_info(DRV_NAME
+		": VIA SDMMC controller at %s [%04x:%04x] has been removed\n",
+		pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device);
+}
+
+#ifdef CONFIG_PM
+
+static void via_init_sdc_pm(struct via_crdr_mmc_host *host)
+{
+	struct sdhcreg *pm_sdhcreg;
+	void __iomem *addrbase;
+	u32 lenreg;
+	u16 status;
+
+	pm_sdhcreg = &(host->pm_sdhc_reg);
+	addrbase = host->sdhc_mmiobase;
+
+	writel(0x0, addrbase + VIA_CRDR_SDINTMASK);
+
+	lenreg = VIA_CRDR_SDBLKLEN_GPIDET | VIA_CRDR_SDBLKLEN_INTEN;
+	writel(lenreg, addrbase + VIA_CRDR_SDBLKLEN);
+
+	status = readw(addrbase + VIA_CRDR_SDSTATUS);
+	status &= VIA_CRDR_SDSTS_W1C_MASK;
+	writew(status, addrbase + VIA_CRDR_SDSTATUS);
+
+	status = readw(addrbase + VIA_CRDR_SDSTATUS2);
+	status |= VIA_CRDR_SDSTS_CFE;
+	writew(status, addrbase + VIA_CRDR_SDSTATUS2);
+
+	writel(pm_sdhcreg->sdcontrol_reg, addrbase + VIA_CRDR_SDCTRL);
+	writel(pm_sdhcreg->sdcmdarg_reg, addrbase + VIA_CRDR_SDCARG);
+	writel(pm_sdhcreg->sdintmask_reg, addrbase + VIA_CRDR_SDINTMASK);
+	writel(pm_sdhcreg->sdrsptmo_reg, addrbase + VIA_CRDR_SDRSPTMO);
+	writel(pm_sdhcreg->sdclksel_reg, addrbase + VIA_CRDR_SDCLKSEL);
+	writel(pm_sdhcreg->sdextctrl_reg, addrbase + VIA_CRDR_SDEXTCTRL);
+
+	via_print_pcictrl(host);
+	via_print_sdchc(host);
+}
+
+static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state)
+{
+	struct via_crdr_mmc_host *host;
+	int ret = 0;
+
+	host = pci_get_drvdata(pcidev);
+
+	via_save_pcictrlreg(host);
+	via_save_sdcreg(host);
+
+	ret = mmc_suspend_host(host->mmc, state);
+
+	pci_save_state(pcidev);
+	pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
+	pci_disable_device(pcidev);
+	pci_set_power_state(pcidev, pci_choose_state(pcidev, state));
+
+	return ret;
+}
+
+static int via_sd_resume(struct pci_dev *pcidev)
+{
+	struct via_crdr_mmc_host *sdhost;
+	int ret = 0;
+	u8 gatt;
+
+	sdhost = pci_get_drvdata(pcidev);
+
+	gatt = VIA_CRDR_PCICLKGATT_PAD_PWRON;
+	if (sdhost->power == MMC_VDD_165_195)
+		gatt &= ~VIA_CRDR_PCICLKGATT_3V3;
+	else
+		gatt |= VIA_CRDR_PCICLKGATT_3V3;
+	writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	via_pwron_sleep(sdhost);
+	gatt |= VIA_CRDR_PCICLKGATT_SFTRST;
+	writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT);
+	msleep(3);
+
+	msleep(100);
+
+	pci_set_power_state(pcidev, PCI_D0);
+	pci_restore_state(pcidev);
+	ret = pci_enable_device(pcidev);
+	if (ret)
+		return ret;
+
+	via_restore_pcictrlreg(sdhost);
+	via_init_sdc_pm(sdhost);
+
+	ret = mmc_resume_host(sdhost->mmc);
+
+	return ret;
+}
+
+#else /* CONFIG_PM */
+
+#define via_sd_suspend NULL
+#define via_sd_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct pci_driver via_sd_driver = {
+	.name = DRV_NAME,
+	.id_table = via_ids,
+	.probe = via_sd_probe,
+	.remove = __devexit_p(via_sd_remove),
+	.suspend = via_sd_suspend,
+	.resume = via_sd_resume,
+};
+
+static int __init via_sd_drv_init(void)
+{
+	pr_info(DRV_NAME ": VIA SD/MMC Card Reader driver "
+		"(C) 2008 VIA Technologies, Inc.\n");
+
+	return pci_register_driver(&via_sd_driver);
+}
+
+static void __exit via_sd_drv_exit(void)
+{
+	pci_unregister_driver(&via_sd_driver);
+}
+
+module_init(via_sd_drv_init);
+module_exit(via_sd_drv_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("VIA Technologies Inc.");
+MODULE_DESCRIPTION("VIA SD/MMC Card Interface driver");
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/chips/cfi_cmdset_0001.c linux-libre-2.6.31-gnu/drivers/mtd/chips/cfi_cmdset_0001.c
--- linux-libre-2.6.30-gnu/drivers/mtd/chips/cfi_cmdset_0001.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/chips/cfi_cmdset_0001.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,6 +46,7 @@
 #define MANUFACTURER_INTEL	0x0089
 #define I82802AB	0x00ad
 #define I82802AC	0x00ac
+#define PF38F4476	0x881c
 #define MANUFACTURER_ST         0x0020
 #define M50LPW080       0x002F
 #define M50FLW080A	0x0080
@@ -315,10 +316,20 @@
 	{ 0, 0, NULL, NULL }
 };
 
+static void cfi_fixup_major_minor(struct cfi_private *cfi,
+						struct cfi_pri_intelext *extp)
+{
+	if (cfi->mfr == MANUFACTURER_INTEL &&
+			cfi->id == PF38F4476 && extp->MinorVersion == '3')
+		extp->MinorVersion = '1';
+}
+
 static inline struct cfi_pri_intelext *
 read_pri_intelext(struct map_info *map, __u16 adr)
 {
+	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_pri_intelext *extp;
+	unsigned int extra_size = 0;
 	unsigned int extp_size = sizeof(*extp);
 
  again:
@@ -326,6 +337,8 @@
 	if (!extp)
 		return NULL;
 
+	cfi_fixup_major_minor(cfi, extp);
+
 	if (extp->MajorVersion != '1' ||
 	    (extp->MinorVersion < '0' || extp->MinorVersion > '5')) {
 		printk(KERN_ERR "  Unknown Intel/Sharp Extended Query "
@@ -340,19 +353,24 @@
 	extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
 	extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);
 
-	if (extp->MajorVersion == '1' && extp->MinorVersion >= '3') {
-		unsigned int extra_size = 0;
-		int nb_parts, i;
+	if (extp->MinorVersion >= '0') {
+		extra_size = 0;
 
 		/* Protection Register info */
 		extra_size += (extp->NumProtectionFields - 1) *
 			      sizeof(struct cfi_intelext_otpinfo);
+	}
 
+	if (extp->MinorVersion >= '1') {
 		/* Burst Read info */
 		extra_size += 2;
 		if (extp_size < sizeof(*extp) + extra_size)
 			goto need_more;
-		extra_size += extp->extra[extra_size-1];
+		extra_size += extp->extra[extra_size - 1];
+	}
+
+	if (extp->MinorVersion >= '3') {
+		int nb_parts, i;
 
 		/* Number of hardware-partitions */
 		extra_size += 1;
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/chips/jedec_probe.c linux-libre-2.6.31-gnu/drivers/mtd/chips/jedec_probe.c
--- linux-libre-2.6.30-gnu/drivers/mtd/chips/jedec_probe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/chips/jedec_probe.c	2009-09-09 18:13:59.000000000 -0400
@@ -166,6 +166,7 @@
 #define SST39LF040	0x00D7
 #define SST39SF010A	0x00B5
 #define SST39SF020A	0x00B6
+#define SST39SF040	0x00B7
 #define SST49LF004B	0x0060
 #define SST49LF040B	0x0050
 #define SST49LF008A	0x005a
@@ -1393,6 +1394,18 @@
 		}
 	}, {
 		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST39SF040,
+		.name		= "SST 39SF040",
+		.devtypes	= CFI_DEVICETYPE_X8,
+		.uaddr		= MTD_UADDR_0x5555_0x2AAA,
+		.dev_size	= SIZE_512KiB,
+		.cmd_set	= P_ID_AMD_STD,
+		.nr_regions	= 1,
+		.regions	= {
+			ERASEINFO(0x01000,128),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_SST,
 		.dev_id		= SST49LF040B,
 		.name		= "SST 49LF040B",
 		.devtypes	= CFI_DEVICETYPE_X8,
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/cmdlinepart.c linux-libre-2.6.31-gnu/drivers/mtd/cmdlinepart.c
--- linux-libre-2.6.30-gnu/drivers/mtd/cmdlinepart.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/cmdlinepart.c	2009-09-09 18:13:59.000000000 -0400
@@ -194,7 +194,7 @@
 	parts[this_part].name = extra_mem;
 	extra_mem += name_len + 1;
 
-	dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n",
+	dbg(("partition %d: name <%s>, offset %llx, size %llx, mask flags %x\n",
 	     this_part,
 	     parts[this_part].name,
 	     parts[this_part].offset,
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/devices/Kconfig linux-libre-2.6.31-gnu/drivers/mtd/devices/Kconfig
--- linux-libre-2.6.30-gnu/drivers/mtd/devices/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/devices/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -49,7 +49,7 @@
 	  If you want to compile this driver as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/kbuild/modules.txt>.
-	  The module will be called ms02-nv.ko.
+	  The module will be called ms02-nv.
 
 config MTD_DATAFLASH
 	tristate "Support for AT45xxx DataFlash"
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/devices/m25p80.c linux-libre-2.6.31-gnu/drivers/mtd/devices/m25p80.c
--- linux-libre-2.6.30-gnu/drivers/mtd/devices/m25p80.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/devices/m25p80.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,7 +54,7 @@
 #define	SR_SRWD			0x80	/* SR write protect */
 
 /* Define max times to check status register before we give up. */
-#define	MAX_READY_WAIT_JIFFIES	(10 * HZ)	/* eg. M25P128 specs 6s max sector erase */
+#define	MAX_READY_WAIT_JIFFIES	(40 * HZ)	/* M25P16 specs 40s max chip erase */
 #define	CMD_SIZE		4
 
 #ifdef CONFIG_M25PXX_USE_FAST_READ
@@ -500,6 +500,9 @@
 	{ "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
 	{ "at26df321",  0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
 
+	/* Macronix */
+	{ "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, },
+
 	/* Spansion -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
 	 */
@@ -528,6 +531,7 @@
 	{ "m25p64",  0x202017,  0, 64 * 1024, 128, },
 	{ "m25p128", 0x202018, 0, 256 * 1024, 64, },
 
+	{ "m45pe10", 0x204011,  0, 64 * 1024, 2, },
 	{ "m45pe80", 0x204014,  0, 64 * 1024, 16, },
 	{ "m45pe16", 0x204015,  0, 64 * 1024, 32, },
 
@@ -732,7 +736,7 @@
 			flash->partitioned = 1;
 			return add_mtd_partitions(&flash->mtd, parts, nr_parts);
 		}
-	} else if (data->nr_parts)
+	} else if (data && data->nr_parts)
 		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
 				data->nr_parts, data->name);
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/inftlcore.c linux-libre-2.6.31-gnu/drivers/mtd/inftlcore.c
--- linux-libre-2.6.30-gnu/drivers/mtd/inftlcore.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/inftlcore.c	2009-09-09 18:13:59.000000000 -0400
@@ -226,7 +226,7 @@
 	if (!desperate && inftl->numfreeEUNs < 2) {
 		DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free "
 			"EUNs (%d)\n", inftl->numfreeEUNs);
-		return 0xffff;
+		return BLOCK_NIL;
 	}
 
 	/* Scan for a free block */
@@ -281,7 +281,8 @@
 	silly = MAX_LOOPS;
 	while (thisEUN < inftl->nb_blocks) {
 		for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) {
-			if ((BlockMap[block] != 0xffff) || BlockDeleted[block])
+			if ((BlockMap[block] != BLOCK_NIL) ||
+			    BlockDeleted[block])
 				continue;
 
 			if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
@@ -525,7 +526,7 @@
 			if (!silly--) {
 				printk(KERN_WARNING "INFTL: infinite loop in "
 					"Virtual Unit Chain 0x%x\n", thisVUC);
-				return 0xffff;
+				return BLOCK_NIL;
 			}
 
 			/* Skip to next block in chain */
@@ -549,7 +550,7 @@
 			 * waiting to be picked up. We're going to have to fold
 			 * a chain to make room.
 			 */
-			thisEUN = INFTL_makefreeblock(inftl, 0xffff);
+			thisEUN = INFTL_makefreeblock(inftl, BLOCK_NIL);
 
 			/*
 			 * Hopefully we free something, lets try again.
@@ -631,7 +632,7 @@
 
 	printk(KERN_WARNING "INFTL: error folding to make room for Virtual "
 		"Unit Chain 0x%x\n", thisVUC);
-	return 0xffff;
+	return BLOCK_NIL;
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/Kconfig linux-libre-2.6.31-gnu/drivers/mtd/Kconfig
--- linux-libre-2.6.30-gnu/drivers/mtd/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -154,7 +154,8 @@
 
 	  You will still need the parsing functions to be called by the driver
 	  for your particular device. It won't happen automatically. The
-	  'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
+	  'armflash' map driver (CONFIG_MTD_ARM_INTEGRATOR) does this, for
+	  example.
 
 config MTD_OF_PARTS
 	tristate "Flash partition map based on OF description"
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/bfin-async-flash.c linux-libre-2.6.31-gnu/drivers/mtd/maps/bfin-async-flash.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/bfin-async-flash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/bfin-async-flash.c	2009-09-09 18:13:59.000000000 -0400
@@ -40,6 +40,9 @@
 	uint32_t flash_ambctl0, flash_ambctl1;
 	uint32_t save_ambctl0, save_ambctl1;
 	unsigned long irq_flags;
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *parts;
+#endif
 };
 
 static void switch_to_flash(struct async_state *state)
@@ -170,6 +173,7 @@
 	if (ret > 0) {
 		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
 		add_mtd_partitions(state->mtd, pdata->parts, ret);
+		state->parts = pdata->parts;
 
 	} else if (pdata->nr_parts) {
 		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
@@ -193,6 +197,7 @@
 	gpio_free(state->enet_flash_pin);
 #ifdef CONFIG_MTD_PARTITIONS
 	del_mtd_partitions(state->mtd);
+	kfree(state->parts);
 #endif
 	map_destroy(state->mtd);
 	kfree(state);
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/integrator-flash.c linux-libre-2.6.31-gnu/drivers/mtd/maps/integrator-flash.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/integrator-flash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/integrator-flash.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,27 +36,31 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/concat.h>
 
 #include <asm/mach/flash.h>
 #include <mach/hardware.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_ARCH_P720T
-#define FLASH_BASE		(0x04000000)
-#define FLASH_SIZE		(64*1024*1024)
-#endif
+struct armflash_subdev_info {
+	char			*name;
+	struct mtd_info		*mtd;
+	struct map_info		map;
+	struct flash_platform_data *plat;
+};
 
 struct armflash_info {
-	struct flash_platform_data *plat;
 	struct resource		*res;
 	struct mtd_partition	*parts;
 	struct mtd_info		*mtd;
-	struct map_info		map;
+	int			nr_subdev;
+	struct armflash_subdev_info subdev[0];
 };
 
 static void armflash_set_vpp(struct map_info *map, int on)
 {
-	struct armflash_info *info = container_of(map, struct armflash_info, map);
+	struct armflash_subdev_info *info =
+		container_of(map, struct armflash_subdev_info, map);
 
 	if (info->plat && info->plat->set_vpp)
 		info->plat->set_vpp(on);
@@ -64,32 +68,17 @@
 
 static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL };
 
-static int armflash_probe(struct platform_device *dev)
+static int armflash_subdev_probe(struct armflash_subdev_info *subdev,
+				 struct resource *res)
 {
-	struct flash_platform_data *plat = dev->dev.platform_data;
-	struct resource *res = dev->resource;
-	unsigned int size = res->end - res->start + 1;
-	struct armflash_info *info;
-	int err;
+	struct flash_platform_data *plat = subdev->plat;
+	resource_size_t size = res->end - res->start + 1;
 	void __iomem *base;
+	int err = 0;
 
-	info = kzalloc(sizeof(struct armflash_info), GFP_KERNEL);
-	if (!info) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	info->plat = plat;
-	if (plat && plat->init) {
-		err = plat->init();
-		if (err)
-			goto no_resource;
-	}
-
-	info->res = request_mem_region(res->start, size, "armflash");
-	if (!info->res) {
+	if (!request_mem_region(res->start, size, subdev->name)) {
 		err = -EBUSY;
-		goto no_resource;
+		goto out;
 	}
 
 	base = ioremap(res->start, size);
@@ -101,27 +90,140 @@
 	/*
 	 * look for CFI based flash parts fitted to this board
 	 */
-	info->map.size		= size;
-	info->map.bankwidth	= plat->width;
-	info->map.phys		= res->start;
-	info->map.virt		= base;
-	info->map.name		= dev_name(&dev->dev);
-	info->map.set_vpp	= armflash_set_vpp;
+	subdev->map.size	= size;
+	subdev->map.bankwidth	= plat->width;
+	subdev->map.phys	= res->start;
+	subdev->map.virt	= base;
+	subdev->map.name	= subdev->name;
+	subdev->map.set_vpp	= armflash_set_vpp;
 
-	simple_map_init(&info->map);
+	simple_map_init(&subdev->map);
 
 	/*
 	 * Also, the CFI layer automatically works out what size
 	 * of chips we have, and does the necessary identification
 	 * for us automatically.
 	 */
-	info->mtd = do_map_probe(plat->map_name, &info->map);
-	if (!info->mtd) {
+	subdev->mtd = do_map_probe(plat->map_name, &subdev->map);
+	if (!subdev->mtd) {
 		err = -ENXIO;
 		goto no_device;
 	}
 
-	info->mtd->owner = THIS_MODULE;
+	subdev->mtd->owner = THIS_MODULE;
+
+	/* Successful? */
+	if (err == 0)
+		return err;
+
+	if (subdev->mtd)
+		map_destroy(subdev->mtd);
+ no_device:
+	iounmap(base);
+ no_mem:
+	release_mem_region(res->start, size);
+ out:
+	return err;
+}
+
+static void armflash_subdev_remove(struct armflash_subdev_info *subdev)
+{
+	if (subdev->mtd)
+		map_destroy(subdev->mtd);
+	if (subdev->map.virt)
+		iounmap(subdev->map.virt);
+	kfree(subdev->name);
+	subdev->name = NULL;
+	release_mem_region(subdev->map.phys, subdev->map.size);
+}
+
+static int armflash_probe(struct platform_device *dev)
+{
+	struct flash_platform_data *plat = dev->dev.platform_data;
+	unsigned int size;
+	struct armflash_info *info;
+	int i, nr, err;
+
+	/* Count the number of devices */
+	for (nr = 0; ; nr++)
+		if (!platform_get_resource(dev, IORESOURCE_MEM, nr))
+			break;
+	if (nr == 0) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	size = sizeof(struct armflash_info) +
+		sizeof(struct armflash_subdev_info) * nr;
+	info = kzalloc(size, GFP_KERNEL);
+	if (!info) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if (plat && plat->init) {
+		err = plat->init();
+		if (err)
+			goto no_resource;
+	}
+
+	for (i = 0; i < nr; i++) {
+		struct armflash_subdev_info *subdev = &info->subdev[i];
+		struct resource *res;
+
+		res = platform_get_resource(dev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
+
+		if (nr == 1)
+			/* No MTD concatenation, just use the default name */
+			subdev->name = kstrdup(dev_name(&dev->dev), GFP_KERNEL);
+		else
+			subdev->name = kasprintf(GFP_KERNEL, "%s-%d",
+						 dev_name(&dev->dev), i);
+		if (!subdev->name) {
+			err = -ENOMEM;
+			break;
+		}
+		subdev->plat = plat;
+
+		err = armflash_subdev_probe(subdev, res);
+		if (err) {
+			kfree(subdev->name);
+			subdev->name = NULL;
+			break;
+		}
+	}
+	info->nr_subdev = i;
+
+	if (err)
+		goto subdev_err;
+
+	if (info->nr_subdev == 1)
+		info->mtd = info->subdev[0].mtd;
+	else if (info->nr_subdev > 1) {
+#ifdef CONFIG_MTD_CONCAT
+		struct mtd_info *cdev[info->nr_subdev];
+
+		/*
+		 * We detected multiple devices.  Concatenate them together.
+		 */
+		for (i = 0; i < info->nr_subdev; i++)
+			cdev[i] = info->subdev[i].mtd;
+
+		info->mtd = mtd_concat_create(cdev, info->nr_subdev,
+					      dev_name(&dev->dev));
+		if (info->mtd == NULL)
+			err = -ENXIO;
+#else
+		printk(KERN_ERR "armflash: multiple devices found but "
+		       "MTD concat support disabled.\n");
+		err = -ENXIO;
+#endif
+	}
+
+	if (err < 0)
+		goto cleanup;
 
 	err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
 	if (err > 0) {
@@ -131,28 +233,30 @@
 			       "mtd partition registration failed: %d\n", err);
 	}
 
-	if (err == 0)
+	if (err == 0) {
 		platform_set_drvdata(dev, info);
+		return err;
+	}
 
 	/*
-	 * If we got an error, free all resources.
+	 * We got an error, free all resources.
 	 */
-	if (err < 0) {
-		if (info->mtd) {
-			del_mtd_partitions(info->mtd);
-			map_destroy(info->mtd);
-		}
-		kfree(info->parts);
-
- no_device:
-		iounmap(base);
- no_mem:
-		release_mem_region(res->start, size);
- no_resource:
-		if (plat && plat->exit)
-			plat->exit();
-		kfree(info);
+ cleanup:
+	if (info->mtd) {
+		del_mtd_partitions(info->mtd);
+#ifdef CONFIG_MTD_CONCAT
+		if (info->mtd != info->subdev[0].mtd)
+			mtd_concat_destroy(info->mtd);
+#endif
 	}
+	kfree(info->parts);
+ subdev_err:
+	for (i = info->nr_subdev - 1; i >= 0; i--)
+		armflash_subdev_remove(&info->subdev[i]);
+ no_resource:
+	if (plat && plat->exit)
+		plat->exit();
+	kfree(info);
  out:
 	return err;
 }
@@ -160,22 +264,26 @@
 static int armflash_remove(struct platform_device *dev)
 {
 	struct armflash_info *info = platform_get_drvdata(dev);
+	struct flash_platform_data *plat = dev->dev.platform_data;
+	int i;
 
 	platform_set_drvdata(dev, NULL);
 
 	if (info) {
 		if (info->mtd) {
 			del_mtd_partitions(info->mtd);
-			map_destroy(info->mtd);
+#ifdef CONFIG_MTD_CONCAT
+			if (info->mtd != info->subdev[0].mtd)
+				mtd_concat_destroy(info->mtd);
+#endif
 		}
 		kfree(info->parts);
 
-		iounmap(info->map.virt);
-		release_resource(info->res);
-		kfree(info->res);
+		for (i = info->nr_subdev - 1; i >= 0; i--)
+			armflash_subdev_remove(&info->subdev[i]);
 
-		if (info->plat && info->plat->exit)
-			info->plat->exit();
+		if (plat && plat->exit)
+			plat->exit();
 
 		kfree(info);
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/Kconfig linux-libre-2.6.31-gnu/drivers/mtd/maps/Kconfig
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -105,15 +105,6 @@
 	default "0x02000000"
 	depends on MSP_FLASH_MAP_LIMIT_32M
 
-config MTD_PMC_MSP_RAMROOT
-	tristate "Embedded RAM block device for root on PMC-Sierra MSP"
-	depends on PMC_MSP_EMBEDDED_ROOTFS && \
-			(MTD_BLOCK || MTD_BLOCK_RO) && \
-			MTD_RAM
-	help
-	  This provides support for the embedded root file system
-          on PMC MSP devices.  This memory is mapped as a MTD block device.
-
 config MTD_SUN_UFLASH
 	tristate "Sun Microsystems userflash support"
 	depends on SPARC && MTD_CFI && PCI
@@ -270,7 +261,7 @@
 
 config MTD_DILNETPC
 	tristate "CFI Flash device mapped on DIL/Net PC"
-	depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT
+	depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
 	help
 	  MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
 	  For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
@@ -293,13 +284,6 @@
 
 	  BE VERY CAREFUL.
 
-config MTD_SBC8240
-	tristate "Flash device on SBC8240"
-	depends on MTD_JEDECPROBE && 8260
-	help
-          Flash access on the SBC8240 board from Wind River.  See
-          <http://www.windriver.com/products/sbc8240/>
-
 config MTD_TQM8XXL
 	tristate "CFI Flash device mapped on TQM8XXL"
 	depends on MTD_CFI && TQM8xxL
@@ -501,7 +485,7 @@
 	  If compiled as a module, it will be called bfin-async-flash.
 
 config MTD_UCLINUX
-	tristate "Generic uClinux RAM/ROM filesystem support"
+	bool "Generic uClinux RAM/ROM filesystem support"
 	depends on MTD_PARTITIONS && MTD_RAM && !MMU
 	help
 	  Map driver to support image based filesystems for uClinux.
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/Makefile linux-libre-2.6.31-gnu/drivers/mtd/maps/Makefile
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,6 @@
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.o
 obj-$(CONFIG_MTD_PMC_MSP_EVM)   += pmcmsp-flash.o
-obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o
 obj-$(CONFIG_MTD_PCMCIA)	+= pcmciamtd.o
 obj-$(CONFIG_MTD_RPXLITE)	+= rpxlite.o
 obj-$(CONFIG_MTD_TQM8XXL)	+= tqm8xxl.o
@@ -51,7 +50,6 @@
 obj-$(CONFIG_MTD_NETtel)	+= nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)	+= scb2_flash.o
 obj-$(CONFIG_MTD_H720X)		+= h720x-flash.o
-obj-$(CONFIG_MTD_SBC8240)	+= sbc8240.o
 obj-$(CONFIG_MTD_IXP4XX)	+= ixp4xx.o
 obj-$(CONFIG_MTD_IXP2000)	+= ixp2000.o
 obj-$(CONFIG_MTD_WRSBC8260)	+= wr_sbc82xx_flash.o
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/physmap.c linux-libre-2.6.31-gnu/drivers/mtd/maps/physmap.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/physmap.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/physmap.c	2009-09-09 18:13:59.000000000 -0400
@@ -195,42 +195,6 @@
 }
 
 #ifdef CONFIG_PM
-static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct physmap_flash_info *info = platform_get_drvdata(dev);
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
-		if (info->mtd[i]->suspend) {
-			ret = info->mtd[i]->suspend(info->mtd[i]);
-			if (ret)
-				goto fail;
-		}
-
-	return 0;
-fail:
-	for (--i; i >= 0; --i)
-		if (info->mtd[i]->suspend) {
-			BUG_ON(!info->mtd[i]->resume);
-			info->mtd[i]->resume(info->mtd[i]);
-		}
-
-	return ret;
-}
-
-static int physmap_flash_resume(struct platform_device *dev)
-{
-	struct physmap_flash_info *info = platform_get_drvdata(dev);
-	int i;
-
-	for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
-		if (info->mtd[i]->resume)
-			info->mtd[i]->resume(info->mtd[i]);
-
-	return 0;
-}
-
 static void physmap_flash_shutdown(struct platform_device *dev)
 {
 	struct physmap_flash_info *info = platform_get_drvdata(dev);
@@ -242,16 +206,12 @@
 				info->mtd[i]->resume(info->mtd[i]);
 }
 #else
-#define physmap_flash_suspend NULL
-#define physmap_flash_resume NULL
 #define physmap_flash_shutdown NULL
 #endif
 
 static struct platform_driver physmap_flash_driver = {
 	.probe		= physmap_flash_probe,
 	.remove		= physmap_flash_remove,
-	.suspend	= physmap_flash_suspend,
-	.resume		= physmap_flash_resume,
 	.shutdown	= physmap_flash_shutdown,
 	.driver		= {
 		.name	= "physmap-flash",
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/physmap_of.c linux-libre-2.6.31-gnu/drivers/mtd/maps/physmap_of.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/physmap_of.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/physmap_of.c	2009-09-09 18:13:59.000000000 -0400
@@ -20,16 +20,23 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/concat.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
+struct of_flash_list {
+	struct mtd_info *mtd;
+	struct map_info map;
+	struct resource *res;
+};
+
 struct of_flash {
-	struct mtd_info		*mtd;
-	struct map_info		map;
-	struct resource		*res;
+	struct mtd_info		*cmtd;
 #ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition	*parts;
 #endif
+	int list_size; /* number of elements in of_flash_list */
+	struct of_flash_list	list[0];
 };
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -88,30 +95,44 @@
 static int of_flash_remove(struct of_device *dev)
 {
 	struct of_flash *info;
+	int i;
 
 	info = dev_get_drvdata(&dev->dev);
 	if (!info)
 		return 0;
 	dev_set_drvdata(&dev->dev, NULL);
 
-	if (info->mtd) {
+#ifdef CONFIG_MTD_CONCAT
+	if (info->cmtd != info->list[0].mtd) {
+		del_mtd_device(info->cmtd);
+		mtd_concat_destroy(info->cmtd);
+	}
+#endif
+
+	if (info->cmtd) {
 		if (OF_FLASH_PARTS(info)) {
-			del_mtd_partitions(info->mtd);
+			del_mtd_partitions(info->cmtd);
 			kfree(OF_FLASH_PARTS(info));
 		} else {
-			del_mtd_device(info->mtd);
+			del_mtd_device(info->cmtd);
 		}
-		map_destroy(info->mtd);
 	}
 
-	if (info->map.virt)
-		iounmap(info->map.virt);
+	for (i = 0; i < info->list_size; i++) {
+		if (info->list[i].mtd)
+			map_destroy(info->list[i].mtd);
 
-	if (info->res) {
-		release_resource(info->res);
-		kfree(info->res);
+		if (info->list[i].map.virt)
+			iounmap(info->list[i].map.virt);
+
+		if (info->list[i].res) {
+			release_resource(info->list[i].res);
+			kfree(info->list[i].res);
+		}
 	}
 
+	kfree(info);
+
 	return 0;
 }
 
@@ -164,68 +185,130 @@
 	const char *probe_type = match->data;
 	const u32 *width;
 	int err;
+	int i;
+	int count;
+	const u32 *p;
+	int reg_tuple_size;
+	struct mtd_info **mtd_list = NULL;
 
-	err = -ENXIO;
-	if (of_address_to_resource(dp, 0, &res)) {
-		dev_err(&dev->dev, "Can't get IO address from device tree\n");
+	reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
+
+	/*
+	 * Get number of "reg" tuples. Scan for MTD devices on area's
+	 * described by each "reg" region. This makes it possible (including
+	 * the concat support) to support the Intel P30 48F4400 chips which
+	 * consists internally of 2 non-identical NOR chips on one die.
+	 */
+	p = of_get_property(dp, "reg", &count);
+	if (count % reg_tuple_size != 0) {
+		dev_err(&dev->dev, "Malformed reg property on %s\n",
+				dev->node->full_name);
+		err = -EINVAL;
 		goto err_out;
 	}
-
-       	dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
-		(unsigned long long)res.start, (unsigned long long)res.end);
+	count /= reg_tuple_size;
 
 	err = -ENOMEM;
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = kzalloc(sizeof(struct of_flash) +
+		       sizeof(struct of_flash_list) * count, GFP_KERNEL);
+	if (!info)
+		goto err_out;
+
+	mtd_list = kzalloc(sizeof(struct mtd_info) * count, GFP_KERNEL);
 	if (!info)
 		goto err_out;
 
 	dev_set_drvdata(&dev->dev, info);
 
-	err = -EBUSY;
-	info->res = request_mem_region(res.start, res.end - res.start + 1,
-				       dev_name(&dev->dev));
-	if (!info->res)
-		goto err_out;
+	for (i = 0; i < count; i++) {
+		err = -ENXIO;
+		if (of_address_to_resource(dp, i, &res)) {
+			dev_err(&dev->dev, "Can't get IO address from device"
+				" tree\n");
+			goto err_out;
+		}
 
-	err = -ENXIO;
-	width = of_get_property(dp, "bank-width", NULL);
-	if (!width) {
-		dev_err(&dev->dev, "Can't get bank width from device tree\n");
-		goto err_out;
-	}
+		dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
+			(unsigned long long)res.start,
+			(unsigned long long)res.end);
 
-	info->map.name = dev_name(&dev->dev);
-	info->map.phys = res.start;
-	info->map.size = res.end - res.start + 1;
-	info->map.bankwidth = *width;
+		err = -EBUSY;
+		info->list[i].res = request_mem_region(res.start, res.end -
+						       res.start + 1,
+						       dev_name(&dev->dev));
+		if (!info->list[i].res)
+			goto err_out;
 
-	err = -ENOMEM;
-	info->map.virt = ioremap(info->map.phys, info->map.size);
-	if (!info->map.virt) {
-		dev_err(&dev->dev, "Failed to ioremap() flash region\n");
-		goto err_out;
-	}
+		err = -ENXIO;
+		width = of_get_property(dp, "bank-width", NULL);
+		if (!width) {
+			dev_err(&dev->dev, "Can't get bank width from device"
+				" tree\n");
+			goto err_out;
+		}
 
-	simple_map_init(&info->map);
+		info->list[i].map.name = dev_name(&dev->dev);
+		info->list[i].map.phys = res.start;
+		info->list[i].map.size = res.end - res.start + 1;
+		info->list[i].map.bankwidth = *width;
 
-	if (probe_type)
-		info->mtd = do_map_probe(probe_type, &info->map);
-	else
-		info->mtd = obsolete_probe(dev, &info->map);
+		err = -ENOMEM;
+		info->list[i].map.virt = ioremap(info->list[i].map.phys,
+						 info->list[i].map.size);
+		if (!info->list[i].map.virt) {
+			dev_err(&dev->dev, "Failed to ioremap() flash"
+				" region\n");
+			goto err_out;
+		}
 
-	err = -ENXIO;
-	if (!info->mtd) {
-		dev_err(&dev->dev, "do_map_probe() failed\n");
-		goto err_out;
+		simple_map_init(&info->list[i].map);
+
+		if (probe_type) {
+			info->list[i].mtd = do_map_probe(probe_type,
+							 &info->list[i].map);
+		} else {
+			info->list[i].mtd = obsolete_probe(dev,
+							   &info->list[i].map);
+		}
+		mtd_list[i] = info->list[i].mtd;
+
+		err = -ENXIO;
+		if (!info->list[i].mtd) {
+			dev_err(&dev->dev, "do_map_probe() failed\n");
+			goto err_out;
+		} else {
+			info->list_size++;
+		}
+		info->list[i].mtd->owner = THIS_MODULE;
+		info->list[i].mtd->dev.parent = &dev->dev;
 	}
-	info->mtd->owner = THIS_MODULE;
-	info->mtd->dev.parent = &dev->dev;
+
+	err = 0;
+	if (info->list_size == 1) {
+		info->cmtd = info->list[0].mtd;
+	} else if (info->list_size > 1) {
+		/*
+		 * We detected multiple devices. Concatenate them together.
+		 */
+#ifdef CONFIG_MTD_CONCAT
+		info->cmtd = mtd_concat_create(mtd_list, info->list_size,
+					       dev_name(&dev->dev));
+		if (info->cmtd == NULL)
+			err = -ENXIO;
+#else
+		printk(KERN_ERR "physmap_of: multiple devices "
+		       "found but MTD concat support disabled.\n");
+		err = -ENXIO;
+#endif
+	}
+	if (err)
+		goto err_out;
 
 #ifdef CONFIG_MTD_PARTITIONS
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	err = parse_mtd_partitions(info->mtd, part_probe_types,
-	                           &info->parts, 0);
+	err = parse_mtd_partitions(info->cmtd, part_probe_types,
+				   &info->parts, 0);
 	if (err < 0)
 		return err;
 
@@ -244,15 +327,19 @@
 	}
 
 	if (err > 0)
-		add_mtd_partitions(info->mtd, info->parts, err);
+		add_mtd_partitions(info->cmtd, info->parts, err);
 	else
 #endif
-		add_mtd_device(info->mtd);
+		add_mtd_device(info->cmtd);
+
+	kfree(mtd_list);
 
 	return 0;
 
 err_out:
+	kfree(mtd_list);
 	of_flash_remove(dev);
+
 	return err;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/pmcmsp-ramroot.c linux-libre-2.6.31-gnu/drivers/mtd/maps/pmcmsp-ramroot.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/pmcmsp-ramroot.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/pmcmsp-ramroot.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,104 +0,0 @@
-/*
- * Mapping of the rootfs in a physical region of memory
- *
- * Copyright (C) 2005-2007 PMC-Sierra Inc.
- * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
- *
- *  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/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/root_dev.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-
-#include <asm/io.h>
-
-#include <msp_prom.h>
-
-static struct mtd_info *rr_mtd;
-
-struct map_info rr_map = {
-	.name = "ramroot",
-	.bankwidth = 4,
-};
-
-static int __init init_rrmap(void)
-{
-	void *ramroot_start;
-	unsigned long ramroot_size;
-
-	/* Check for supported rootfs types */
-	if (get_ramroot(&ramroot_start, &ramroot_size)) {
-		rr_map.phys = CPHYSADDR(ramroot_start);
-		rr_map.size = ramroot_size;
-
-		printk(KERN_NOTICE
-			"PMC embedded root device: 0x%08lx @ 0x%08lx\n",
-			rr_map.size, (unsigned long)rr_map.phys);
-	} else {
-		printk(KERN_ERR
-			"init_rrmap: no supported embedded rootfs detected!\n");
-		return -ENXIO;
-	}
-
-	/* Map rootfs to I/O space for block device driver */
-	rr_map.virt = ioremap(rr_map.phys, rr_map.size);
-	if (!rr_map.virt) {
-		printk(KERN_ERR "Failed to ioremap\n");
-		return -EIO;
-	}
-
-	simple_map_init(&rr_map);
-
-	rr_mtd = do_map_probe("map_ram", &rr_map);
-	if (rr_mtd) {
-		rr_mtd->owner = THIS_MODULE;
-
-		add_mtd_device(rr_mtd);
-
-		return 0;
-	}
-
-	iounmap(rr_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_rrmap(void)
-{
-	del_mtd_device(rr_mtd);
-	map_destroy(rr_mtd);
-
-	iounmap(rr_map.virt);
-	rr_map.virt = NULL;
-}
-
-MODULE_AUTHOR("PMC-Sierra, Inc");
-MODULE_DESCRIPTION("MTD map driver for embedded PMC-Sierra MSP filesystem");
-MODULE_LICENSE("GPL");
-
-module_init(init_rrmap);
-module_exit(cleanup_rrmap);
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/pxa2xx-flash.c linux-libre-2.6.31-gnu/drivers/mtd/maps/pxa2xx-flash.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/pxa2xx-flash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/pxa2xx-flash.c	2009-09-09 18:13:59.000000000 -0400
@@ -140,24 +140,6 @@
 }
 
 #ifdef CONFIG_PM
-static int pxa2xx_flash_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
-	int ret = 0;
-
-	if (info->mtd && info->mtd->suspend)
-		ret = info->mtd->suspend(info->mtd);
-	return ret;
-}
-
-static int pxa2xx_flash_resume(struct platform_device *dev)
-{
-	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
-
-	if (info->mtd && info->mtd->resume)
-		info->mtd->resume(info->mtd);
-	return 0;
-}
 static void pxa2xx_flash_shutdown(struct platform_device *dev)
 {
 	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);
@@ -166,8 +148,6 @@
 		info->mtd->resume(info->mtd);
 }
 #else
-#define pxa2xx_flash_suspend NULL
-#define pxa2xx_flash_resume NULL
 #define pxa2xx_flash_shutdown NULL
 #endif
 
@@ -178,8 +158,6 @@
 	},
 	.probe		= pxa2xx_flash_probe,
 	.remove		= __devexit_p(pxa2xx_flash_remove),
-	.suspend	= pxa2xx_flash_suspend,
-	.resume		= pxa2xx_flash_resume,
 	.shutdown	= pxa2xx_flash_shutdown,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/rbtx4939-flash.c linux-libre-2.6.31-gnu/drivers/mtd/maps/rbtx4939-flash.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/rbtx4939-flash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/rbtx4939-flash.c	2009-09-09 18:13:59.000000000 -0400
@@ -145,25 +145,6 @@
 }
 
 #ifdef CONFIG_PM
-static int rbtx4939_flash_suspend(struct platform_device *dev,
-				  pm_message_t state)
-{
-	struct rbtx4939_flash_info *info = platform_get_drvdata(dev);
-
-	if (info->mtd->suspend)
-		return info->mtd->suspend(info->mtd);
-	return 0;
-}
-
-static int rbtx4939_flash_resume(struct platform_device *dev)
-{
-	struct rbtx4939_flash_info *info = platform_get_drvdata(dev);
-
-	if (info->mtd->resume)
-		info->mtd->resume(info->mtd);
-	return 0;
-}
-
 static void rbtx4939_flash_shutdown(struct platform_device *dev)
 {
 	struct rbtx4939_flash_info *info = platform_get_drvdata(dev);
@@ -173,16 +154,12 @@
 			info->mtd->resume(info->mtd);
 }
 #else
-#define rbtx4939_flash_suspend NULL
-#define rbtx4939_flash_resume NULL
 #define rbtx4939_flash_shutdown NULL
 #endif
 
 static struct platform_driver rbtx4939_flash_driver = {
 	.probe		= rbtx4939_flash_probe,
 	.remove		= rbtx4939_flash_remove,
-	.suspend	= rbtx4939_flash_suspend,
-	.resume		= rbtx4939_flash_resume,
 	.shutdown	= rbtx4939_flash_shutdown,
 	.driver		= {
 		.name	= "rbtx4939-flash",
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/sa1100-flash.c linux-libre-2.6.31-gnu/drivers/mtd/maps/sa1100-flash.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/sa1100-flash.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/sa1100-flash.c	2009-09-09 18:13:59.000000000 -0400
@@ -415,25 +415,6 @@
 }
 
 #ifdef CONFIG_PM
-static int sa1100_mtd_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct sa_info *info = platform_get_drvdata(dev);
-	int ret = 0;
-
-	if (info)
-		ret = info->mtd->suspend(info->mtd);
-
-	return ret;
-}
-
-static int sa1100_mtd_resume(struct platform_device *dev)
-{
-	struct sa_info *info = platform_get_drvdata(dev);
-	if (info)
-		info->mtd->resume(info->mtd);
-	return 0;
-}
-
 static void sa1100_mtd_shutdown(struct platform_device *dev)
 {
 	struct sa_info *info = platform_get_drvdata(dev);
@@ -441,16 +422,12 @@
 		info->mtd->resume(info->mtd);
 }
 #else
-#define sa1100_mtd_suspend NULL
-#define sa1100_mtd_resume  NULL
 #define sa1100_mtd_shutdown NULL
 #endif
 
 static struct platform_driver sa1100_mtd_driver = {
 	.probe		= sa1100_mtd_probe,
 	.remove		= __exit_p(sa1100_mtd_remove),
-	.suspend	= sa1100_mtd_suspend,
-	.resume		= sa1100_mtd_resume,
 	.shutdown	= sa1100_mtd_shutdown,
 	.driver		= {
 		.name	= "sa1100-mtd",
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/sbc8240.c linux-libre-2.6.31-gnu/drivers/mtd/maps/sbc8240.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/sbc8240.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/sbc8240.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,250 +0,0 @@
-/*
- * Handle mapping of the flash memory access routines on the SBC8240 board.
- *
- * Carolyn Smith, Tektronix, Inc.
- *
- * This code is GPLed
- */
-
-/*
- * The SBC8240 has 2 flash banks.
- * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors.
- * It contains the U-Boot code (7 sectors) and the environment (1 sector).
- * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector,
- * 2 x 8 KiB sectors, 1 x 16 KiB sectors.
- * Both parts are JEDEC compatible.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/cfi.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
-#include <linux/mtd/partitions.h>
-#endif
-
-#define	DEBUG
-
-#ifdef	DEBUG
-# define debugk(fmt,args...)	printk(fmt ,##args)
-#else
-# define debugk(fmt,args...)
-#endif
-
-
-#define WINDOW_ADDR0	0xFFF00000		/* 512 KiB */
-#define WINDOW_SIZE0	0x00080000
-#define BUSWIDTH0	1
-
-#define WINDOW_ADDR1	0xFF000000		/* 4 MiB */
-#define WINDOW_SIZE1	0x00400000
-#define BUSWIDTH1	8
-
-#define MSG_PREFIX "sbc8240:"	/* prefix for our printk()'s */
-#define MTDID	   "sbc8240-%d"	/* for mtdparts= partitioning */
-
-
-static struct map_info sbc8240_map[2] = {
-	{
-		.name           = "sbc8240 Flash Bank #0",
-		.size           = WINDOW_SIZE0,
-		.bankwidth       = BUSWIDTH0,
-	},
-	{
-		.name           = "sbc8240 Flash Bank #1",
-		.size           = WINDOW_SIZE1,
-		.bankwidth       = BUSWIDTH1,
-	}
-};
-
-#define NUM_FLASH_BANKS	ARRAY_SIZE(sbc8240_map)
-
-/*
- * The following defines the partition layout of SBC8240 boards.
- *
- * See include/linux/mtd/partitions.h for definition of the
- * mtd_partition structure.
- *
- * The *_max_flash_size is the maximum possible mapped flash size
- * which is not necessarily the actual flash size. It must correspond
- * to the value specified in the mapping definition defined by the
- * "struct map_desc *_io_desc" for the corresponding machine.
- */
-
-#ifdef CONFIG_MTD_PARTITIONS
-
-static struct mtd_partition sbc8240_uboot_partitions [] = {
-	/* Bank 0 */
-	{
-		.name =	"U-boot",			/* U-Boot Firmware	*/
-		.offset =	0,
-		.size =	0x00070000,			/*  7 x 64 KiB sectors 	*/
-		.mask_flags = MTD_WRITEABLE,		/*  force read-only	*/
-	},
-	{
-		.name =	"environment",			/* U-Boot environment	*/
-		.offset =	0x00070000,
-		.size =	0x00010000,			/*  1 x 64 KiB sector	*/
-	},
-};
-
-static struct mtd_partition sbc8240_fs_partitions [] = {
-	{
-		.name =	"jffs",				/* JFFS  filesystem	*/
-		.offset =	0,
-		.size =	0x003C0000,			/*  4 * 15 * 64KiB	*/
-	},
-	{
-		.name =	"tmp32",
-		.offset =	0x003C0000,
-		.size =	0x00020000,			/*  4 * 32KiB		*/
-	},
-	{
-		.name =	"tmp8a",
-		.offset =	0x003E0000,
-		.size =	0x00008000,			/*  4 * 8KiB		*/
-	},
-	{
-		.name =	"tmp8b",
-		.offset =	0x003E8000,
-		.size =	0x00008000,			/*  4 * 8KiB		*/
-	},
-	{
-		.name =	"tmp16",
-		.offset =	0x003F0000,
-		.size =	0x00010000,			/*  4 * 16KiB		*/
-	}
-};
-
-/* trivial struct to describe partition information */
-struct mtd_part_def
-{
-	int nums;
-	unsigned char *type;
-	struct mtd_partition* mtd_part;
-};
-
-static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];
-static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
-
-
-#endif	/* CONFIG_MTD_PARTITIONS */
-
-
-static int __init init_sbc8240_mtd (void)
-{
-	static struct _cjs {
-		u_long addr;
-		u_long size;
-	} pt[NUM_FLASH_BANKS] = {
-		{
-			.addr = WINDOW_ADDR0,
-			.size = WINDOW_SIZE0
-		},
-		{
-			.addr = WINDOW_ADDR1,
-			.size = WINDOW_SIZE1
-		},
-	};
-
-	int devicesfound = 0;
-	int i,j;
-
-	for (i = 0; i < NUM_FLASH_BANKS; i++) {
-		printk (KERN_NOTICE MSG_PREFIX
-			"Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr);
-
-		sbc8240_map[i].map_priv_1 =
-			(unsigned long) ioremap (pt[i].addr, pt[i].size);
-		if (!sbc8240_map[i].map_priv_1) {
-			printk (MSG_PREFIX "failed to ioremap\n");
-			for (j = 0; j < i; j++) {
-				iounmap((void *) sbc8240_map[j].map_priv_1);
-				sbc8240_map[j].map_priv_1 = 0;
-			}
-			return -EIO;
-		}
-		simple_map_init(&sbc8240_mtd[i]);
-
-		sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);
-
-		if (sbc8240_mtd[i]) {
-			sbc8240_mtd[i]->module = THIS_MODULE;
-			devicesfound++;
-		} else {
-			if (sbc8240_map[i].map_priv_1) {
-				iounmap((void *) sbc8240_map[i].map_priv_1);
-				sbc8240_map[i].map_priv_1 = 0;
-			}
-		}
-	}
-
-	if (!devicesfound) {
-		printk(KERN_NOTICE MSG_PREFIX
-		       "No suppported flash chips found!\n");
-		return -ENXIO;
-	}
-
-#ifdef CONFIG_MTD_PARTITIONS
-	sbc8240_part_banks[0].mtd_part   = sbc8240_uboot_partitions;
-	sbc8240_part_banks[0].type       = "static image";
-	sbc8240_part_banks[0].nums       = ARRAY_SIZE(sbc8240_uboot_partitions);
-	sbc8240_part_banks[1].mtd_part   = sbc8240_fs_partitions;
-	sbc8240_part_banks[1].type       = "static file system";
-	sbc8240_part_banks[1].nums       = ARRAY_SIZE(sbc8240_fs_partitions);
-
-	for (i = 0; i < NUM_FLASH_BANKS; i++) {
-
-		if (!sbc8240_mtd[i]) continue;
-		if (sbc8240_part_banks[i].nums == 0) {
-			printk (KERN_NOTICE MSG_PREFIX
-				"No partition info available, registering whole device\n");
-			add_mtd_device(sbc8240_mtd[i]);
-		} else {
-			printk (KERN_NOTICE MSG_PREFIX
-				"Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name);
-			add_mtd_partitions (sbc8240_mtd[i],
-					    sbc8240_part_banks[i].mtd_part,
-					    sbc8240_part_banks[i].nums);
-		}
-	}
-#else
-	printk(KERN_NOTICE MSG_PREFIX
-	       "Registering %d flash banks at once\n", devicesfound);
-
-	for (i = 0; i < devicesfound; i++) {
-		add_mtd_device(sbc8240_mtd[i]);
-	}
-#endif	/* CONFIG_MTD_PARTITIONS */
-
-	return devicesfound == 0 ? -ENXIO : 0;
-}
-
-static void __exit cleanup_sbc8240_mtd (void)
-{
-	int i;
-
-	for (i = 0; i < NUM_FLASH_BANKS; i++) {
-		if (sbc8240_mtd[i]) {
-			del_mtd_device (sbc8240_mtd[i]);
-			map_destroy (sbc8240_mtd[i]);
-		}
-		if (sbc8240_map[i].map_priv_1) {
-			iounmap ((void *) sbc8240_map[i].map_priv_1);
-			sbc8240_map[i].map_priv_1 = 0;
-		}
-	}
-}
-
-module_init (init_sbc8240_mtd);
-module_exit (cleanup_sbc8240_mtd);
-
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");
-MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");
-
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/maps/uclinux.c linux-libre-2.6.31-gnu/drivers/mtd/maps/uclinux.c
--- linux-libre-2.6.30-gnu/drivers/mtd/maps/uclinux.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/maps/uclinux.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,15 +22,19 @@
 
 /****************************************************************************/
 
+extern char _ebss;
+
 struct map_info uclinux_ram_map = {
 	.name = "RAM",
+	.phys = (unsigned long)&_ebss,
+	.size = 0,
 };
 
-struct mtd_info *uclinux_ram_mtdinfo;
+static struct mtd_info *uclinux_ram_mtdinfo;
 
 /****************************************************************************/
 
-struct mtd_partition uclinux_romfs[] = {
+static struct mtd_partition uclinux_romfs[] = {
 	{ .name = "ROMfs" }
 };
 
@@ -38,7 +42,7 @@
 
 /****************************************************************************/
 
-int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
+static int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
 	size_t *retlen, void **virt, resource_size_t *phys)
 {
 	struct map_info *map = mtd->priv;
@@ -55,12 +59,10 @@
 {
 	struct mtd_info *mtd;
 	struct map_info *mapp;
-	extern char _ebss;
-	unsigned long addr = (unsigned long) &_ebss;
 
 	mapp = &uclinux_ram_map;
-	mapp->phys = addr;
-	mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8))));
+	if (!mapp->size)
+		mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(mapp->phys + 8))));
 	mapp->bankwidth = 4;
 
 	printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/mtd_blkdevs.c linux-libre-2.6.31-gnu/drivers/mtd/mtd_blkdevs.c
--- linux-libre-2.6.30-gnu/drivers/mtd/mtd_blkdevs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/mtd_blkdevs.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,40 +47,41 @@
 	unsigned long block, nsect;
 	char *buf;
 
-	block = req->sector << 9 >> tr->blkshift;
-	nsect = req->current_nr_sectors << 9 >> tr->blkshift;
+	block = blk_rq_pos(req) << 9 >> tr->blkshift;
+	nsect = blk_rq_cur_bytes(req) >> tr->blkshift;
 
 	buf = req->buffer;
 
 	if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
 	    req->cmd[0] == REQ_LB_OP_DISCARD)
-		return !tr->discard(dev, block, nsect);
+		return tr->discard(dev, block, nsect);
 
 	if (!blk_fs_request(req))
-		return 0;
+		return -EIO;
 
-	if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk))
-		return 0;
+	if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
+	    get_capacity(req->rq_disk))
+		return -EIO;
 
 	switch(rq_data_dir(req)) {
 	case READ:
 		for (; nsect > 0; nsect--, block++, buf += tr->blksize)
 			if (tr->readsect(dev, block, buf))
-				return 0;
-		return 1;
+				return -EIO;
+		return 0;
 
 	case WRITE:
 		if (!tr->writesect)
-			return 0;
+			return -EIO;
 
 		for (; nsect > 0; nsect--, block++, buf += tr->blksize)
 			if (tr->writesect(dev, block, buf))
-				return 0;
-		return 1;
+				return -EIO;
+		return 0;
 
 	default:
 		printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
-		return 0;
+		return -EIO;
 	}
 }
 
@@ -88,19 +89,18 @@
 {
 	struct mtd_blktrans_ops *tr = arg;
 	struct request_queue *rq = tr->blkcore_priv->rq;
+	struct request *req = NULL;
 
 	/* we might get involved when memory gets low, so use PF_MEMALLOC */
 	current->flags |= PF_MEMALLOC;
 
 	spin_lock_irq(rq->queue_lock);
+
 	while (!kthread_should_stop()) {
-		struct request *req;
 		struct mtd_blktrans_dev *dev;
-		int res = 0;
-
-		req = elv_next_request(rq);
+		int res;
 
-		if (!req) {
+		if (!req && !(req = blk_fetch_request(rq))) {
 			set_current_state(TASK_INTERRUPTIBLE);
 			spin_unlock_irq(rq->queue_lock);
 			schedule();
@@ -119,8 +119,13 @@
 
 		spin_lock_irq(rq->queue_lock);
 
-		end_request(req, res);
+		if (!__blk_end_request_cur(req, res))
+			req = NULL;
 	}
+
+	if (req)
+		__blk_end_request_all(req, -EIO);
+
 	spin_unlock_irq(rq->queue_lock);
 
 	return 0;
@@ -139,7 +144,7 @@
 	struct mtd_blktrans_ops *tr = dev->tr;
 	int ret = -ENODEV;
 
-	if (!try_module_get(dev->mtd->owner))
+	if (!get_mtd_device(NULL, dev->mtd->index))
 		goto out;
 
 	if (!try_module_get(tr->owner))
@@ -153,7 +158,7 @@
 	ret = 0;
 	if (tr->open && (ret = tr->open(dev))) {
 		dev->mtd->usecount--;
-		module_put(dev->mtd->owner);
+		put_mtd_device(dev->mtd);
 	out_tr:
 		module_put(tr->owner);
 	}
@@ -172,7 +177,7 @@
 
 	if (!ret) {
 		dev->mtd->usecount--;
-		module_put(dev->mtd->owner);
+		put_mtd_device(dev->mtd);
 		module_put(tr->owner);
 	}
 
@@ -286,7 +291,7 @@
 	gd->private_data = new;
 	new->blkcore_priv = gd;
 	gd->queue = tr->blkcore_priv->rq;
-	gd->driverfs_dev = new->mtd->dev.parent;
+	gd->driverfs_dev = &new->mtd->dev;
 
 	if (new->readonly)
 		set_disk_ro(gd, 1);
@@ -373,7 +378,7 @@
 	}
 
 	tr->blkcore_priv->rq->queuedata = tr;
-	blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize);
+	blk_queue_logical_block_size(tr->blkcore_priv->rq, tr->blksize);
 	if (tr->discard)
 		blk_queue_set_discard(tr->blkcore_priv->rq,
 				      blktrans_discard_request);
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/mtdblock.c linux-libre-2.6.31-gnu/drivers/mtd/mtdblock.c
--- linux-libre-2.6.30-gnu/drivers/mtd/mtdblock.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/mtdblock.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,8 @@
 	enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
 } *mtdblks[MAX_MTD_DEVICES];
 
+static struct mutex mtdblks_lock;
+
 /*
  * Cache stuff...
  *
@@ -270,15 +272,19 @@
 
 	DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
 
+	mutex_lock(&mtdblks_lock);
 	if (mtdblks[dev]) {
 		mtdblks[dev]->count++;
+		mutex_unlock(&mtdblks_lock);
 		return 0;
 	}
 
 	/* OK, it's not open. Create cache info for it */
 	mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
-	if (!mtdblk)
+	if (!mtdblk) {
+		mutex_unlock(&mtdblks_lock);
 		return -ENOMEM;
+	}
 
 	mtdblk->count = 1;
 	mtdblk->mtd = mtd;
@@ -291,6 +297,7 @@
 	}
 
 	mtdblks[dev] = mtdblk;
+	mutex_unlock(&mtdblks_lock);
 
 	DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
 
@@ -304,6 +311,8 @@
 
    	DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
 
+	mutex_lock(&mtdblks_lock);
+
 	mutex_lock(&mtdblk->cache_mutex);
 	write_cached_data(mtdblk);
 	mutex_unlock(&mtdblk->cache_mutex);
@@ -316,6 +325,9 @@
 		vfree(mtdblk->cache_data);
 		kfree(mtdblk);
 	}
+
+	mutex_unlock(&mtdblks_lock);
+
 	DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
 
 	return 0;
@@ -376,6 +388,8 @@
 
 static int __init init_mtdblock(void)
 {
+	mutex_init(&mtdblks_lock);
+
 	return register_mtd_blktrans(&mtdblock_tr);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/mtdchar.c linux-libre-2.6.31-gnu/drivers/mtd/mtdchar.c
--- linux-libre-2.6.30-gnu/drivers/mtd/mtdchar.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/mtdchar.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
+#include <linux/compat.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/compatmac.h>
@@ -355,6 +356,100 @@
 # define otp_select_filemode(f,m)	-EOPNOTSUPP
 #endif
 
+static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
+	uint64_t start, uint32_t length, void __user *ptr,
+	uint32_t __user *retp)
+{
+	struct mtd_oob_ops ops;
+	uint32_t retlen;
+	int ret = 0;
+
+	if (!(file->f_mode & FMODE_WRITE))
+		return -EPERM;
+
+	if (length > 4096)
+		return -EINVAL;
+
+	if (!mtd->write_oob)
+		ret = -EOPNOTSUPP;
+	else
+		ret = access_ok(VERIFY_READ, ptr, length) ? 0 : EFAULT;
+
+	if (ret)
+		return ret;
+
+	ops.ooblen = length;
+	ops.ooboffs = start & (mtd->oobsize - 1);
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_PLACE;
+
+	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
+		return -EINVAL;
+
+	ops.oobbuf = kmalloc(length, GFP_KERNEL);
+	if (!ops.oobbuf)
+		return -ENOMEM;
+
+	if (copy_from_user(ops.oobbuf, ptr, length)) {
+		kfree(ops.oobbuf);
+		return -EFAULT;
+	}
+
+	start &= ~((uint64_t)mtd->oobsize - 1);
+	ret = mtd->write_oob(mtd, start, &ops);
+
+	if (ops.oobretlen > 0xFFFFFFFFU)
+		ret = -EOVERFLOW;
+	retlen = ops.oobretlen;
+	if (copy_to_user(retp, &retlen, sizeof(length)))
+		ret = -EFAULT;
+
+	kfree(ops.oobbuf);
+	return ret;
+}
+
+static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
+	uint32_t length, void __user *ptr, uint32_t __user *retp)
+{
+	struct mtd_oob_ops ops;
+	int ret = 0;
+
+	if (length > 4096)
+		return -EINVAL;
+
+	if (!mtd->read_oob)
+		ret = -EOPNOTSUPP;
+	else
+		ret = access_ok(VERIFY_WRITE, ptr,
+				length) ? 0 : -EFAULT;
+	if (ret)
+		return ret;
+
+	ops.ooblen = length;
+	ops.ooboffs = start & (mtd->oobsize - 1);
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_PLACE;
+
+	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
+		return -EINVAL;
+
+	ops.oobbuf = kmalloc(length, GFP_KERNEL);
+	if (!ops.oobbuf)
+		return -ENOMEM;
+
+	start &= ~((uint64_t)mtd->oobsize - 1);
+	ret = mtd->read_oob(mtd, start, &ops);
+
+	if (put_user(ops.oobretlen, retp))
+		ret = -EFAULT;
+	else if (ops.oobretlen && copy_to_user(ptr, ops.oobbuf,
+					    ops.oobretlen))
+		ret = -EFAULT;
+
+	kfree(ops.oobbuf);
+	return ret;
+}
+
 static int mtd_ioctl(struct inode *inode, struct file *file,
 		     u_int cmd, u_long arg)
 {
@@ -417,6 +512,7 @@
 		break;
 
 	case MEMERASE:
+	case MEMERASE64:
 	{
 		struct erase_info *erase;
 
@@ -427,20 +523,32 @@
 		if (!erase)
 			ret = -ENOMEM;
 		else {
-			struct erase_info_user einfo;
-
 			wait_queue_head_t waitq;
 			DECLARE_WAITQUEUE(wait, current);
 
 			init_waitqueue_head(&waitq);
 
-			if (copy_from_user(&einfo, argp,
-				    sizeof(struct erase_info_user))) {
-				kfree(erase);
-				return -EFAULT;
+			if (cmd == MEMERASE64) {
+				struct erase_info_user64 einfo64;
+
+				if (copy_from_user(&einfo64, argp,
+					    sizeof(struct erase_info_user64))) {
+					kfree(erase);
+					return -EFAULT;
+				}
+				erase->addr = einfo64.start;
+				erase->len = einfo64.length;
+			} else {
+				struct erase_info_user einfo32;
+
+				if (copy_from_user(&einfo32, argp,
+					    sizeof(struct erase_info_user))) {
+					kfree(erase);
+					return -EFAULT;
+				}
+				erase->addr = einfo32.start;
+				erase->len = einfo32.length;
 			}
-			erase->addr = einfo.start;
-			erase->len = einfo.length;
 			erase->mtd = mtd;
 			erase->callback = mtdchar_erase_callback;
 			erase->priv = (unsigned long)&waitq;
@@ -474,100 +582,56 @@
 	case MEMWRITEOOB:
 	{
 		struct mtd_oob_buf buf;
-		struct mtd_oob_ops ops;
-		struct mtd_oob_buf __user *user_buf = argp;
-	        uint32_t retlen;
-
-		if(!(file->f_mode & FMODE_WRITE))
-			return -EPERM;
-
-		if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
-			return -EFAULT;
-
-		if (buf.length > 4096)
-			return -EINVAL;
-
-		if (!mtd->write_oob)
-			ret = -EOPNOTSUPP;
-		else
-			ret = access_ok(VERIFY_READ, buf.ptr,
-					buf.length) ? 0 : EFAULT;
-
-		if (ret)
-			return ret;
-
-		ops.ooblen = buf.length;
-		ops.ooboffs = buf.start & (mtd->oobsize - 1);
-		ops.datbuf = NULL;
-		ops.mode = MTD_OOB_PLACE;
-
-		if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
-			return -EINVAL;
-
-		ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
-		if (!ops.oobbuf)
-			return -ENOMEM;
-
-		if (copy_from_user(ops.oobbuf, buf.ptr, buf.length)) {
-			kfree(ops.oobbuf);
-			return -EFAULT;
-		}
-
-		buf.start &= ~(mtd->oobsize - 1);
-		ret = mtd->write_oob(mtd, buf.start, &ops);
+		struct mtd_oob_buf __user *buf_user = argp;
 
-		if (ops.oobretlen > 0xFFFFFFFFU)
-			ret = -EOVERFLOW;
-		retlen = ops.oobretlen;
-		if (copy_to_user(&user_buf->length, &retlen, sizeof(buf.length)))
+		/* NOTE: writes return length to buf_user->length */
+		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
-
-		kfree(ops.oobbuf);
+		else
+			ret = mtd_do_writeoob(file, mtd, buf.start, buf.length,
+				buf.ptr, &buf_user->length);
 		break;
-
 	}
 
 	case MEMREADOOB:
 	{
 		struct mtd_oob_buf buf;
-		struct mtd_oob_ops ops;
-
-		if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
-			return -EFAULT;
-
-		if (buf.length > 4096)
-			return -EINVAL;
+		struct mtd_oob_buf __user *buf_user = argp;
 
-		if (!mtd->read_oob)
-			ret = -EOPNOTSUPP;
+		/* NOTE: writes return length to buf_user->start */
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
 		else
-			ret = access_ok(VERIFY_WRITE, buf.ptr,
-					buf.length) ? 0 : -EFAULT;
-		if (ret)
-			return ret;
-
-		ops.ooblen = buf.length;
-		ops.ooboffs = buf.start & (mtd->oobsize - 1);
-		ops.datbuf = NULL;
-		ops.mode = MTD_OOB_PLACE;
+			ret = mtd_do_readoob(mtd, buf.start, buf.length,
+				buf.ptr, &buf_user->start);
+		break;
+	}
 
-		if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
-			return -EINVAL;
+	case MEMWRITEOOB64:
+	{
+		struct mtd_oob_buf64 buf;
+		struct mtd_oob_buf64 __user *buf_user = argp;
 
-		ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
-		if (!ops.oobbuf)
-			return -ENOMEM;
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+		else
+			ret = mtd_do_writeoob(file, mtd, buf.start, buf.length,
+				(void __user *)(uintptr_t)buf.usr_ptr,
+				&buf_user->length);
+		break;
+	}
 
-		buf.start &= ~(mtd->oobsize - 1);
-		ret = mtd->read_oob(mtd, buf.start, &ops);
+	case MEMREADOOB64:
+	{
+		struct mtd_oob_buf64 buf;
+		struct mtd_oob_buf64 __user *buf_user = argp;
 
-		if (put_user(ops.oobretlen, (uint32_t __user *)argp))
-			ret = -EFAULT;
-		else if (ops.oobretlen && copy_to_user(buf.ptr, ops.oobbuf,
-						    ops.oobretlen))
+		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
-
-		kfree(ops.oobbuf);
+		else
+			ret = mtd_do_readoob(mtd, buf.start, buf.length,
+				(void __user *)(uintptr_t)buf.usr_ptr,
+				&buf_user->length);
 		break;
 	}
 
@@ -758,6 +822,68 @@
 	return ret;
 } /* memory_ioctl */
 
+#ifdef CONFIG_COMPAT
+
+struct mtd_oob_buf32 {
+	u_int32_t start;
+	u_int32_t length;
+	compat_caddr_t ptr;	/* unsigned char* */
+};
+
+#define MEMWRITEOOB32		_IOWR('M', 3, struct mtd_oob_buf32)
+#define MEMREADOOB32		_IOWR('M', 4, struct mtd_oob_buf32)
+
+static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct mtd_file_info *mfi = file->private_data;
+	struct mtd_info *mtd = mfi->mtd;
+	void __user *argp = compat_ptr(arg);
+	int ret = 0;
+
+	lock_kernel();
+
+	switch (cmd) {
+	case MEMWRITEOOB32:
+	{
+		struct mtd_oob_buf32 buf;
+		struct mtd_oob_buf32 __user *buf_user = argp;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+		else
+			ret = mtd_do_writeoob(file, mtd, buf.start,
+				buf.length, compat_ptr(buf.ptr),
+				&buf_user->length);
+		break;
+	}
+
+	case MEMREADOOB32:
+	{
+		struct mtd_oob_buf32 buf;
+		struct mtd_oob_buf32 __user *buf_user = argp;
+
+		/* NOTE: writes return length to buf->start */
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+		else
+			ret = mtd_do_readoob(mtd, buf.start,
+				buf.length, compat_ptr(buf.ptr),
+				&buf_user->start);
+		break;
+	}
+	default:
+		ret = mtd_ioctl(inode, file, cmd, (unsigned long)argp);
+	}
+
+	unlock_kernel();
+
+	return ret;
+}
+
+#endif /* CONFIG_COMPAT */
+
 /*
  * try to determine where a shared mapping can be made
  * - only supported for NOMMU at the moment (MMU can't doesn't copy private
@@ -817,6 +943,9 @@
 	.read		= mtd_read,
 	.write		= mtd_write,
 	.ioctl		= mtd_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= mtd_compat_ioctl,
+#endif
 	.open		= mtd_open,
 	.release	= mtd_close,
 	.mmap		= mtd_mmap,
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/mtdcore.c linux-libre-2.6.31-gnu/drivers/mtd/mtdcore.c
--- linux-libre-2.6.30-gnu/drivers/mtd/mtdcore.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/mtdcore.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,8 +23,15 @@
 
 #include "mtdcore.h"
 
+static int mtd_cls_suspend(struct device *dev, pm_message_t state);
+static int mtd_cls_resume(struct device *dev);
 
-static struct class *mtd_class;
+static struct class mtd_class = {
+	.name = "mtd",
+	.owner = THIS_MODULE,
+	.suspend = mtd_cls_suspend,
+	.resume = mtd_cls_resume,
+};
 
 /* These are exported solely for the purpose of mtd_blkdevs.c. You
    should not use them for _anything_ else */
@@ -52,7 +59,26 @@
 
 	/* remove /dev/mtdXro node if needed */
 	if (index)
-		device_destroy(mtd_class, index + 1);
+		device_destroy(&mtd_class, index + 1);
+}
+
+static int mtd_cls_suspend(struct device *dev, pm_message_t state)
+{
+	struct mtd_info *mtd = dev_to_mtd(dev);
+
+	if (mtd && mtd->suspend)
+		return mtd->suspend(mtd);
+	else
+		return 0;
+}
+
+static int mtd_cls_resume(struct device *dev)
+{
+	struct mtd_info *mtd = dev_to_mtd(dev);
+	
+	if (mtd && mtd->resume)
+		mtd->resume(mtd);
+	return 0;
 }
 
 static ssize_t mtd_type_show(struct device *dev,
@@ -269,16 +295,17 @@
 			 * physical device.
 			 */
 			mtd->dev.type = &mtd_devtype;
-			mtd->dev.class = mtd_class;
+			mtd->dev.class = &mtd_class;
 			mtd->dev.devt = MTD_DEVT(i);
 			dev_set_name(&mtd->dev, "mtd%d", i);
+			dev_set_drvdata(&mtd->dev, mtd);
 			if (device_register(&mtd->dev) != 0) {
 				mtd_table[i] = NULL;
 				break;
 			}
 
 			if (MTD_DEVT(i))
-				device_create(mtd_class, mtd->dev.parent,
+				device_create(&mtd_class, mtd->dev.parent,
 						MTD_DEVT(i) + 1,
 						NULL, "mtd%dro", i);
 
@@ -604,11 +631,12 @@
 
 static int __init init_mtd(void)
 {
-	mtd_class = class_create(THIS_MODULE, "mtd");
+	int ret;
+	ret = class_register(&mtd_class);
 
-	if (IS_ERR(mtd_class)) {
-		pr_err("Error creating mtd class.\n");
-		return PTR_ERR(mtd_class);
+	if (ret) {
+		pr_err("Error registering mtd class: %d\n", ret);
+		return ret;
 	}
 #ifdef CONFIG_PROC_FS
 	if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))
@@ -623,7 +651,7 @@
         if (proc_mtd)
 		remove_proc_entry( "mtd", NULL);
 #endif /* CONFIG_PROC_FS */
-	class_destroy(mtd_class);
+	class_unregister(&mtd_class);
 }
 
 module_init(init_mtd);
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/mtdpart.c linux-libre-2.6.31-gnu/drivers/mtd/mtdpart.c
--- linux-libre-2.6.30-gnu/drivers/mtd/mtdpart.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/mtdpart.c	2009-09-09 18:13:59.000000000 -0400
@@ -27,9 +27,7 @@
 	struct mtd_info mtd;
 	struct mtd_info *master;
 	uint64_t offset;
-	int index;
 	struct list_head list;
-	int registered;
 };
 
 /*
@@ -321,8 +319,7 @@
 	list_for_each_entry_safe(slave, next, &mtd_partitions, list)
 		if (slave->master == master) {
 			list_del(&slave->list);
-			if (slave->registered)
-				del_mtd_device(&slave->mtd);
+			del_mtd_device(&slave->mtd);
 			kfree(slave);
 		}
 
@@ -395,7 +392,7 @@
 		slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
 	if (master->sync)
 		slave->mtd.sync = part_sync;
-	if (!partno && master->suspend && master->resume) {
+	if (!partno && !master->dev.class && master->suspend && master->resume) {
 			slave->mtd.suspend = part_suspend;
 			slave->mtd.resume = part_resume;
 	}
@@ -412,7 +409,6 @@
 	slave->mtd.erase = part_erase;
 	slave->master = master;
 	slave->offset = part->offset;
-	slave->index = partno;
 
 	if (slave->offset == MTDPART_OFS_APPEND)
 		slave->offset = cur_offset;
@@ -500,15 +496,9 @@
 	}
 
 out_register:
-	if (part->mtdp) {
-		/* store the object pointer (caller may or may not register it*/
-		*part->mtdp = &slave->mtd;
-		slave->registered = 0;
-	} else {
-		/* register our partition */
-		add_mtd_device(&slave->mtd);
-		slave->registered = 1;
-	}
+	/* register our partition */
+	add_mtd_device(&slave->mtd);
+
 	return slave;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/atmel_nand.c linux-libre-2.6.31-gnu/drivers/mtd/nand/atmel_nand.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/atmel_nand.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/atmel_nand.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -47,6 +48,9 @@
 #define no_ecc		0
 #endif
 
+static int on_flash_bbt = 0;
+module_param(on_flash_bbt, int, 0);
+
 /* Register access macros */
 #define ecc_readl(add, reg)				\
 	__raw_readl(add + ATMEL_ECC_##reg)
@@ -459,12 +463,17 @@
 
 	if (host->board->det_pin) {
 		if (gpio_get_value(host->board->det_pin)) {
-			printk("No SmartMedia card inserted.\n");
+			printk(KERN_INFO "No SmartMedia card inserted.\n");
 			res = ENXIO;
 			goto err_no_card;
 		}
 	}
 
+	if (on_flash_bbt) {
+		printk(KERN_INFO "atmel_nand: Use On Flash BBT\n");
+		nand_chip->options |= NAND_USE_FLASH_BBT;
+	}
+
 	/* first scan to find the device and get the page size */
 	if (nand_scan_ident(mtd, 1)) {
 		res = -ENXIO;
@@ -525,7 +534,7 @@
 							 &num_partitions);
 
 	if ((!partitions) || (num_partitions == 0)) {
-		printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
+		printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
 		res = ENXIO;
 		goto err_no_partitions;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/bf5xx_nand.c linux-libre-2.6.31-gnu/drivers/mtd/nand/bf5xx_nand.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/bf5xx_nand.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/bf5xx_nand.c	2009-09-09 18:13:59.000000000 -0400
@@ -458,7 +458,7 @@
 	return IRQ_HANDLED;
 }
 
-static int bf5xx_nand_dma_rw(struct mtd_info *mtd,
+static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
 				uint8_t *buf, int is_read)
 {
 	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
@@ -496,11 +496,20 @@
 	/* setup DMA register with Blackfin DMA API */
 	set_dma_config(CH_NFC, 0x0);
 	set_dma_start_addr(CH_NFC, (unsigned long) buf);
+
+/* The DMAs have different size on BF52x and BF54x */
+#ifdef CONFIG_BF52x
+	set_dma_x_count(CH_NFC, (page_size >> 1));
+	set_dma_x_modify(CH_NFC, 2);
+	val = DI_EN | WDSIZE_16;
+#endif
+
+#ifdef CONFIG_BF54x
 	set_dma_x_count(CH_NFC, (page_size >> 2));
 	set_dma_x_modify(CH_NFC, 4);
-
-	/* setup write or read operation */
 	val = DI_EN | WDSIZE_32;
+#endif
+	/* setup write or read operation */
 	if (is_read)
 		val |= WNR;
 	set_dma_config(CH_NFC, val);
@@ -512,8 +521,6 @@
 	else
 		bfin_write_NFC_PGCTL(0x2);
 	wait_for_completion(&info->dma_completion);
-
-	return 0;
 }
 
 static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/davinci_nand.c linux-libre-2.6.31-gnu/drivers/mtd/nand/davinci_nand.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/davinci_nand.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/davinci_nand.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,7 +44,7 @@
  * and some flavors of secondary chipselect (e.g. based on A12) as used
  * with multichip packages.
  *
- * The 1-bit ECC hardware is supported, but not yet the newer 4-bit ECC
+ * The 1-bit ECC hardware is supported, as well as the newer 4-bit ECC
  * available on chips like the DM355 and OMAP-L137 and needed with the
  * more error-prone MLC NAND chips.
  *
@@ -54,11 +54,14 @@
 struct davinci_nand_info {
 	struct mtd_info		mtd;
 	struct nand_chip	chip;
+	struct nand_ecclayout	ecclayout;
 
 	struct device		*dev;
 	struct clk		*clk;
 	bool			partitioned;
 
+	bool			is_readmode;
+
 	void __iomem		*base;
 	void __iomem		*vaddr;
 
@@ -73,6 +76,7 @@
 };
 
 static DEFINE_SPINLOCK(davinci_nand_lock);
+static bool ecc4_busy;
 
 #define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd)
 
@@ -218,6 +222,192 @@
 /*----------------------------------------------------------------------*/
 
 /*
+ * 4-bit hardware ECC ... context maintained over entire AEMIF
+ *
+ * This is a syndrome engine, but we avoid NAND_ECC_HW_SYNDROME
+ * since that forces use of a problematic "infix OOB" layout.
+ * Among other things, it trashes manufacturer bad block markers.
+ * Also, and specific to this hardware, it ECC-protects the "prepad"
+ * in the OOB ... while having ECC protection for parts of OOB would
+ * seem useful, the current MTD stack sometimes wants to update the
+ * OOB without recomputing ECC.
+ */
+
+static void nand_davinci_hwctl_4bit(struct mtd_info *mtd, int mode)
+{
+	struct davinci_nand_info *info = to_davinci_nand(mtd);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&davinci_nand_lock, flags);
+
+	/* Start 4-bit ECC calculation for read/write */
+	val = davinci_nand_readl(info, NANDFCR_OFFSET);
+	val &= ~(0x03 << 4);
+	val |= (info->core_chipsel << 4) | BIT(12);
+	davinci_nand_writel(info, NANDFCR_OFFSET, val);
+
+	info->is_readmode = (mode == NAND_ECC_READ);
+
+	spin_unlock_irqrestore(&davinci_nand_lock, flags);
+}
+
+/* Read raw ECC code after writing to NAND. */
+static void
+nand_davinci_readecc_4bit(struct davinci_nand_info *info, u32 code[4])
+{
+	const u32 mask = 0x03ff03ff;
+
+	code[0] = davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET) & mask;
+	code[1] = davinci_nand_readl(info, NAND_4BIT_ECC2_OFFSET) & mask;
+	code[2] = davinci_nand_readl(info, NAND_4BIT_ECC3_OFFSET) & mask;
+	code[3] = davinci_nand_readl(info, NAND_4BIT_ECC4_OFFSET) & mask;
+}
+
+/* Terminate read ECC; or return ECC (as bytes) of data written to NAND. */
+static int nand_davinci_calculate_4bit(struct mtd_info *mtd,
+		const u_char *dat, u_char *ecc_code)
+{
+	struct davinci_nand_info *info = to_davinci_nand(mtd);
+	u32 raw_ecc[4], *p;
+	unsigned i;
+
+	/* After a read, terminate ECC calculation by a dummy read
+	 * of some 4-bit ECC register.  ECC covers everything that
+	 * was read; correct() just uses the hardware state, so
+	 * ecc_code is not needed.
+	 */
+	if (info->is_readmode) {
+		davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET);
+		return 0;
+	}
+
+	/* Pack eight raw 10-bit ecc values into ten bytes, making
+	 * two passes which each convert four values (in upper and
+	 * lower halves of two 32-bit words) into five bytes.  The
+	 * ROM boot loader uses this same packing scheme.
+	 */
+	nand_davinci_readecc_4bit(info, raw_ecc);
+	for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
+		*ecc_code++ =   p[0]        & 0xff;
+		*ecc_code++ = ((p[0] >>  8) & 0x03) | ((p[0] >> 14) & 0xfc);
+		*ecc_code++ = ((p[0] >> 22) & 0x0f) | ((p[1] <<  4) & 0xf0);
+		*ecc_code++ = ((p[1] >>  4) & 0x3f) | ((p[1] >> 10) & 0xc0);
+		*ecc_code++ =  (p[1] >> 18) & 0xff;
+	}
+
+	return 0;
+}
+
+/* Correct up to 4 bits in data we just read, using state left in the
+ * hardware plus the ecc_code computed when it was first written.
+ */
+static int nand_davinci_correct_4bit(struct mtd_info *mtd,
+		u_char *data, u_char *ecc_code, u_char *null)
+{
+	int i;
+	struct davinci_nand_info *info = to_davinci_nand(mtd);
+	unsigned short ecc10[8];
+	unsigned short *ecc16;
+	u32 syndrome[4];
+	unsigned num_errors, corrected;
+
+	/* All bytes 0xff?  It's an erased page; ignore its ECC. */
+	for (i = 0; i < 10; i++) {
+		if (ecc_code[i] != 0xff)
+			goto compare;
+	}
+	return 0;
+
+compare:
+	/* Unpack ten bytes into eight 10 bit values.  We know we're
+	 * little-endian, and use type punning for less shifting/masking.
+	 */
+	if (WARN_ON(0x01 & (unsigned) ecc_code))
+		return -EINVAL;
+	ecc16 = (unsigned short *)ecc_code;
+
+	ecc10[0] =  (ecc16[0] >>  0) & 0x3ff;
+	ecc10[1] = ((ecc16[0] >> 10) & 0x3f) | ((ecc16[1] << 6) & 0x3c0);
+	ecc10[2] =  (ecc16[1] >>  4) & 0x3ff;
+	ecc10[3] = ((ecc16[1] >> 14) & 0x3)  | ((ecc16[2] << 2) & 0x3fc);
+	ecc10[4] =  (ecc16[2] >>  8)         | ((ecc16[3] << 8) & 0x300);
+	ecc10[5] =  (ecc16[3] >>  2) & 0x3ff;
+	ecc10[6] = ((ecc16[3] >> 12) & 0xf)  | ((ecc16[4] << 4) & 0x3f0);
+	ecc10[7] =  (ecc16[4] >>  6) & 0x3ff;
+
+	/* Tell ECC controller about the expected ECC codes. */
+	for (i = 7; i >= 0; i--)
+		davinci_nand_writel(info, NAND_4BIT_ECC_LOAD_OFFSET, ecc10[i]);
+
+	/* Allow time for syndrome calculation ... then read it.
+	 * A syndrome of all zeroes 0 means no detected errors.
+	 */
+	davinci_nand_readl(info, NANDFSR_OFFSET);
+	nand_davinci_readecc_4bit(info, syndrome);
+	if (!(syndrome[0] | syndrome[1] | syndrome[2] | syndrome[3]))
+		return 0;
+
+	/* Start address calculation, and wait for it to complete.
+	 * We _could_ start reading more data while this is working,
+	 * to speed up the overall page read.
+	 */
+	davinci_nand_writel(info, NANDFCR_OFFSET,
+			davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13));
+	for (;;) {
+		u32	fsr = davinci_nand_readl(info, NANDFSR_OFFSET);
+
+		switch ((fsr >> 8) & 0x0f) {
+		case 0:		/* no error, should not happen */
+			return 0;
+		case 1:		/* five or more errors detected */
+			return -EIO;
+		case 2:		/* error addresses computed */
+		case 3:
+			num_errors = 1 + ((fsr >> 16) & 0x03);
+			goto correct;
+		default:	/* still working on it */
+			cpu_relax();
+			continue;
+		}
+	}
+
+correct:
+	/* correct each error */
+	for (i = 0, corrected = 0; i < num_errors; i++) {
+		int error_address, error_value;
+
+		if (i > 1) {
+			error_address = davinci_nand_readl(info,
+						NAND_ERR_ADD2_OFFSET);
+			error_value = davinci_nand_readl(info,
+						NAND_ERR_ERRVAL2_OFFSET);
+		} else {
+			error_address = davinci_nand_readl(info,
+						NAND_ERR_ADD1_OFFSET);
+			error_value = davinci_nand_readl(info,
+						NAND_ERR_ERRVAL1_OFFSET);
+		}
+
+		if (i & 1) {
+			error_address >>= 16;
+			error_value >>= 16;
+		}
+		error_address &= 0x3ff;
+		error_address = (512 + 7) - error_address;
+
+		if (error_address < 512) {
+			data[error_address] ^= error_value;
+			corrected++;
+		}
+	}
+
+	return corrected;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
  * NOTE:  NAND boot requires ALE == EM_A[1], CLE == EM_A[2], so that's
  * how these chips are normally wired.  This translates to both 8 and 16
  * bit busses using ALE == BIT(3) in byte addresses, and CLE == BIT(4).
@@ -294,6 +484,23 @@
 
 /*----------------------------------------------------------------------*/
 
+/* An ECC layout for using 4-bit ECC with small-page flash, storing
+ * ten ECC bytes plus the manufacturer's bad block marker byte, and
+ * and not overlapping the default BBT markers.
+ */
+static struct nand_ecclayout hwecc4_small __initconst = {
+	.eccbytes = 10,
+	.eccpos = { 0, 1, 2, 3, 4,
+		/* offset 5 holds the badblock marker */
+		6, 7,
+		13, 14, 15, },
+	.oobfree = {
+		{.offset = 8, .length = 5, },
+		{.offset = 16, },
+	},
+};
+
+
 static int __init nand_davinci_probe(struct platform_device *pdev)
 {
 	struct davinci_nand_pdata	*pdata = pdev->dev.platform_data;
@@ -306,6 +513,10 @@
 	uint32_t			val;
 	nand_ecc_modes_t		ecc_mode;
 
+	/* insist on board-specific configuration */
+	if (!pdata)
+		return -ENODEV;
+
 	/* which external chipselect will we be managing? */
 	if (pdev->id < 0 || pdev->id > 3)
 		return -ENODEV;
@@ -351,7 +562,7 @@
 	info->chip.select_chip	= nand_davinci_select_chip;
 
 	/* options such as NAND_USE_FLASH_BBT or 16-bit widths */
-	info->chip.options	= pdata ? pdata->options : 0;
+	info->chip.options	= pdata->options;
 
 	info->ioaddr		= (uint32_t __force) vaddr;
 
@@ -360,14 +571,8 @@
 	info->mask_chipsel	= pdata->mask_chipsel;
 
 	/* use nandboot-capable ALE/CLE masks by default */
-	if (pdata && pdata->mask_ale)
-		info->mask_ale	= pdata->mask_cle;
-	else
-		info->mask_ale	= MASK_ALE;
-	if (pdata && pdata->mask_cle)
-		info->mask_cle	= pdata->mask_cle;
-	else
-		info->mask_cle	= MASK_CLE;
+	info->mask_ale		= pdata->mask_cle ? : MASK_ALE;
+	info->mask_cle		= pdata->mask_cle ? : MASK_CLE;
 
 	/* Set address of hardware control function */
 	info->chip.cmd_ctrl	= nand_davinci_hwcontrol;
@@ -377,30 +582,44 @@
 	info->chip.read_buf     = nand_davinci_read_buf;
 	info->chip.write_buf    = nand_davinci_write_buf;
 
-	/* use board-specific ECC config; else, the best available */
-	if (pdata)
-		ecc_mode = pdata->ecc_mode;
-	else
-		ecc_mode = NAND_ECC_HW;
+	/* Use board-specific ECC config */
+	ecc_mode		= pdata->ecc_mode;
 
+	ret = -EINVAL;
 	switch (ecc_mode) {
 	case NAND_ECC_NONE:
 	case NAND_ECC_SOFT:
+		pdata->ecc_bits = 0;
 		break;
 	case NAND_ECC_HW:
-		info->chip.ecc.calculate = nand_davinci_calculate_1bit;
-		info->chip.ecc.correct = nand_davinci_correct_1bit;
-		info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
+		if (pdata->ecc_bits == 4) {
+			/* No sanity checks:  CPUs must support this,
+			 * and the chips may not use NAND_BUSWIDTH_16.
+			 */
+
+			/* No sharing 4-bit hardware between chipselects yet */
+			spin_lock_irq(&davinci_nand_lock);
+			if (ecc4_busy)
+				ret = -EBUSY;
+			else
+				ecc4_busy = true;
+			spin_unlock_irq(&davinci_nand_lock);
+
+			if (ret == -EBUSY)
+				goto err_ecc;
+
+			info->chip.ecc.calculate = nand_davinci_calculate_4bit;
+			info->chip.ecc.correct = nand_davinci_correct_4bit;
+			info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
+			info->chip.ecc.bytes = 10;
+		} else {
+			info->chip.ecc.calculate = nand_davinci_calculate_1bit;
+			info->chip.ecc.correct = nand_davinci_correct_1bit;
+			info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
+			info->chip.ecc.bytes = 3;
+		}
 		info->chip.ecc.size = 512;
-		info->chip.ecc.bytes = 3;
 		break;
-	case NAND_ECC_HW_SYNDROME:
-		/* FIXME implement */
-		info->chip.ecc.size = 512;
-		info->chip.ecc.bytes = 10;
-
-		dev_warn(&pdev->dev, "4-bit ECC nyet supported\n");
-		/* FALL THROUGH */
 	default:
 		ret = -EINVAL;
 		goto err_ecc;
@@ -441,12 +660,56 @@
 	spin_unlock_irq(&davinci_nand_lock);
 
 	/* Scan to find existence of the device(s) */
-	ret = nand_scan(&info->mtd, pdata->mask_chipsel ? 2 : 1);
+	ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1);
 	if (ret < 0) {
 		dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
 		goto err_scan;
 	}
 
+	/* Update ECC layout if needed ... for 1-bit HW ECC, the default
+	 * is OK, but it allocates 6 bytes when only 3 are needed (for
+	 * each 512 bytes).  For the 4-bit HW ECC, that default is not
+	 * usable:  10 bytes are needed, not 6.
+	 */
+	if (pdata->ecc_bits == 4) {
+		int	chunks = info->mtd.writesize / 512;
+
+		if (!chunks || info->mtd.oobsize < 16) {
+			dev_dbg(&pdev->dev, "too small\n");
+			ret = -EINVAL;
+			goto err_scan;
+		}
+
+		/* For small page chips, preserve the manufacturer's
+		 * badblock marking data ... and make sure a flash BBT
+		 * table marker fits in the free bytes.
+		 */
+		if (chunks == 1) {
+			info->ecclayout = hwecc4_small;
+			info->ecclayout.oobfree[1].length =
+				info->mtd.oobsize - 16;
+			goto syndrome_done;
+		}
+
+		/* For large page chips we'll be wanting to use a
+		 * not-yet-implemented mode that reads OOB data
+		 * before reading the body of the page, to avoid
+		 * the "infix OOB" model of NAND_ECC_HW_SYNDROME
+		 * (and preserve manufacturer badblock markings).
+		 */
+		dev_warn(&pdev->dev, "no 4-bit ECC support yet "
+				"for large page NAND\n");
+		ret = -EIO;
+		goto err_scan;
+
+syndrome_done:
+		info->chip.ecc.layout = &info->ecclayout;
+	}
+
+	ret = nand_scan_tail(&info->mtd);
+	if (ret < 0)
+		goto err_scan;
+
 	if (mtd_has_partitions()) {
 		struct mtd_partition	*mtd_parts = NULL;
 		int			mtd_parts_nb = 0;
@@ -455,22 +718,11 @@
 			static const char *probes[] __initconst =
 				{ "cmdlinepart", NULL };
 
-			const char		*master_name;
-
-			/* Set info->mtd.name = 0 temporarily */
-			master_name		= info->mtd.name;
-			info->mtd.name		= (char *)0;
-
-			/* info->mtd.name == 0, means: don't bother checking
-			   <mtd-id> */
 			mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
 							    &mtd_parts, 0);
-
-			/* Restore info->mtd.name */
-			info->mtd.name = master_name;
 		}
 
-		if (mtd_parts_nb <= 0 && pdata) {
+		if (mtd_parts_nb <= 0) {
 			mtd_parts = pdata->parts;
 			mtd_parts_nb = pdata->nr_parts;
 		}
@@ -483,7 +735,7 @@
 				info->partitioned = true;
 		}
 
-	} else if (pdata && pdata->nr_parts) {
+	} else if (pdata->nr_parts) {
 		dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n",
 				pdata->nr_parts, info->mtd.name);
 	}
@@ -509,6 +761,11 @@
 err_clk_enable:
 	clk_put(info->clk);
 
+	spin_lock_irq(&davinci_nand_lock);
+	if (ecc_mode == NAND_ECC_HW_SYNDROME)
+		ecc4_busy = false;
+	spin_unlock_irq(&davinci_nand_lock);
+
 err_ecc:
 err_clk:
 err_ioremap:
@@ -532,6 +789,11 @@
 	else
 		status = del_mtd_device(&info->mtd);
 
+	spin_lock_irq(&davinci_nand_lock);
+	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
+		ecc4_busy = false;
+	spin_unlock_irq(&davinci_nand_lock);
+
 	iounmap(info->base);
 	iounmap(info->vaddr);
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/Kconfig linux-libre-2.6.31-gnu/drivers/mtd/nand/Kconfig
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -74,6 +74,12 @@
 	help
 	  Support for NAND flash on Amstrad E3 (Delta).
 
+config MTD_NAND_OMAP2
+	tristate "NAND Flash device on OMAP2 and OMAP3"
+	depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3)
+	help
+          Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
+
 config MTD_NAND_TS7250
 	tristate "NAND Flash device on TS-7250 board"
 	depends on MACH_TS72XX
@@ -139,27 +145,27 @@
 	  This enables the NAND flash driver on the PPChameleon EVB Board.
 
 config MTD_NAND_S3C2410
-	tristate "NAND Flash support for S3C2410/S3C2440 SoC"
-	depends on ARCH_S3C2410
+	tristate "NAND Flash support for Samsung S3C SoCs"
+	depends on ARCH_S3C2410 || ARCH_S3C64XX
 	help
-	  This enables the NAND flash controller on the S3C2410 and S3C2440
+	  This enables the NAND flash controller on the S3C24xx and S3C64xx
 	  SoCs
 
 	  No board specific support is done by this driver, each board
 	  must advertise a platform_device for the driver to attach.
 
 config MTD_NAND_S3C2410_DEBUG
-	bool "S3C2410 NAND driver debug"
+	bool "Samsung S3C NAND driver debug"
 	depends on MTD_NAND_S3C2410
 	help
-	  Enable debugging of the S3C2410 NAND driver
+	  Enable debugging of the S3C NAND driver
 
 config MTD_NAND_S3C2410_HWECC
-	bool "S3C2410 NAND Hardware ECC"
+	bool "Samsung S3C NAND Hardware ECC"
 	depends on MTD_NAND_S3C2410
 	help
-	  Enable the use of the S3C2410's internal ECC generator when
-	  using NAND. Early versions of the chip have had problems with
+	  Enable the use of the controller's internal ECC generator when
+	  using NAND. Early versions of the chips have had problems with
 	  incorrect ECC generation, and if using these, the default of
 	  software ECC is preferable.
 
@@ -171,7 +177,7 @@
 	 NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
 
 config MTD_NAND_S3C2410_CLKSTOP
-	bool "S3C2410 NAND IDLE clock stop"
+	bool "Samsung S3C NAND IDLE clock stop"
 	depends on MTD_NAND_S3C2410
 	default n
 	help
@@ -260,7 +266,7 @@
 	help
           This enables the driver for the NAND flash device found on the
           Basler eXcite Smart Camera. If built as a module, the driver
-          will be named "excite_nandflash.ko".
+          will be named excite_nandflash.
 
 config MTD_NAND_CAFE
 	tristate "NAND support for OLPC CAFÉ chip"
@@ -282,7 +288,7 @@
 	  controller is enabled for NAND, and currently requires that
 	  the controller be in MMIO mode.
 
-	  If you say "m", the module will be called "cs553x_nand.ko".
+	  If you say "m", the module will be called cs553x_nand.
 
 config MTD_NAND_ATMEL
 	tristate "Support for NAND Flash / SmartMedia on AT91 and AVR32"
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/Makefile linux-libre-2.6.31-gnu/drivers/mtd/nand/Makefile
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
 obj-$(CONFIG_MTD_NAND_ATMEL)		+= atmel_nand.o
 obj-$(CONFIG_MTD_NAND_GPIO)		+= gpio.o
+obj-$(CONFIG_MTD_NAND_OMAP2) 		+= omap2.o
 obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+= excite_nandflash.o
 obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/mxc_nand.c linux-libre-2.6.31-gnu/drivers/mtd/nand/mxc_nand.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/mxc_nand.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/mxc_nand.c	2009-09-09 18:13:59.000000000 -0400
@@ -138,7 +138,14 @@
 static struct nand_ecclayout nand_hw_eccoob_16 = {
 	.eccbytes = 5,
 	.eccpos = {6, 7, 8, 9, 10},
-	.oobfree = {{0, 6}, {12, 4}, }
+	.oobfree = {{0, 5}, {11, 5}, }
+};
+
+static struct nand_ecclayout nand_hw_eccoob_64 = {
+	.eccbytes = 20,
+	.eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
+		   38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
+	.oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
 };
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -192,7 +199,7 @@
 			}
 			udelay(1);
 		}
-		if (max_retries <= 0)
+		if (max_retries < 0)
 			DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
 			      __func__, param);
 	}
@@ -795,9 +802,13 @@
 		send_addr(host, (page_addr & 0xff), false);
 
 		if (host->pagesize_2k) {
-			send_addr(host, (page_addr >> 8) & 0xFF, false);
-			if (mtd->size >= 0x40000000)
+			if (mtd->size >= 0x10000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, false);
 				send_addr(host, (page_addr >> 16) & 0xff, true);
+			} else
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, true);
 		} else {
 			/* One more address cycle for higher density devices */
 			if (mtd->size >= 0x4000000) {
@@ -923,7 +934,6 @@
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.size = 512;
 		this->ecc.bytes = 3;
-		this->ecc.layout = &nand_hw_eccoob_8;
 		tmp = readw(host->regs + NFC_CONFIG1);
 		tmp |= NFC_ECC_EN;
 		writew(tmp, host->regs + NFC_CONFIG1);
@@ -957,12 +967,44 @@
 		this->ecc.layout = &nand_hw_eccoob_16;
 	}
 
-	host->pagesize_2k = 0;
+	/* first scan to find the device and get the page size */
+	if (nand_scan_ident(mtd, 1)) {
+		err = -ENXIO;
+		goto escan;
+	}
 
-	/* Scan to find existence of the device */
-	if (nand_scan(mtd, 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0,
-		      "MXC_ND: Unable to find any NAND device.\n");
+	host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;
+
+	if (this->ecc.mode == NAND_ECC_HW) {
+		switch (mtd->oobsize) {
+		case 8:
+			this->ecc.layout = &nand_hw_eccoob_8;
+			break;
+		case 16:
+			this->ecc.layout = &nand_hw_eccoob_16;
+			break;
+		case 64:
+			this->ecc.layout = &nand_hw_eccoob_64;
+			break;
+		default:
+			/* page size not handled by HW ECC */
+			/* switching back to soft ECC */
+			this->ecc.size = 512;
+			this->ecc.bytes = 3;
+			this->ecc.layout = &nand_hw_eccoob_8;
+			this->ecc.mode = NAND_ECC_SOFT;
+			this->ecc.calculate = NULL;
+			this->ecc.correct = NULL;
+			this->ecc.hwctl = NULL;
+			tmp = readw(host->regs + NFC_CONFIG1);
+			tmp &= ~NFC_ECC_EN;
+			writew(tmp, host->regs + NFC_CONFIG1);
+			break;
+		}
+	}
+
+	/* second phase scan */
+	if (nand_scan_tail(mtd)) {
 		err = -ENXIO;
 		goto escan;
 	}
@@ -985,7 +1027,7 @@
 	return 0;
 
 escan:
-	free_irq(host->irq, NULL);
+	free_irq(host->irq, host);
 eirq:
 	iounmap(host->regs);
 eres:
@@ -1005,7 +1047,7 @@
 	platform_set_drvdata(pdev, NULL);
 
 	nand_release(&host->mtd);
-	free_irq(host->irq, NULL);
+	free_irq(host->irq, host);
 	iounmap(host->regs);
 	kfree(host);
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/nand_base.c linux-libre-2.6.31-gnu/drivers/mtd/nand/nand_base.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/nand_base.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/nand_base.c	2009-09-09 18:13:59.000000000 -0400
@@ -2756,7 +2756,8 @@
 	 * the out of band area
 	 */
 	chip->ecc.layout->oobavail = 0;
-	for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
+	for (i = 0; chip->ecc.layout->oobfree[i].length
+			&& i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)
 		chip->ecc.layout->oobavail +=
 			chip->ecc.layout->oobfree[i].length;
 	mtd->oobavail = chip->ecc.layout->oobavail;
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/nand_ecc.c linux-libre-2.6.31-gnu/drivers/mtd/nand/nand_ecc.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/nand_ecc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/nand_ecc.c	2009-09-09 18:13:59.000000000 -0400
@@ -428,8 +428,8 @@
 int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
 		      unsigned char *read_ecc, unsigned char *calc_ecc)
 {
-	unsigned char b0, b1, b2;
-	unsigned char byte_addr, bit_addr;
+	unsigned char b0, b1, b2, bit_addr;
+	unsigned int byte_addr;
 	/* 256 or 512 bytes/ecc  */
 	const uint32_t eccsize_mult =
 			(((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/omap2.c linux-libre-2.6.31-gnu/drivers/mtd/nand/omap2.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/omap2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/omap2.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,779 @@
+/*
+ * Copyright © 2004 Texas Instruments, Jian Zhang <jzhang@ti.com>
+ * Copyright © 2004 Micron Technology Inc.
+ * Copyright © 2004 David Brownell
+ *
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/io.h>
+
+#include <asm/dma.h>
+
+#include <mach/gpmc.h>
+#include <mach/nand.h>
+
+#define GPMC_IRQ_STATUS		0x18
+#define GPMC_ECC_CONFIG		0x1F4
+#define GPMC_ECC_CONTROL	0x1F8
+#define GPMC_ECC_SIZE_CONFIG	0x1FC
+#define GPMC_ECC1_RESULT	0x200
+
+#define	DRIVER_NAME	"omap2-nand"
+
+/* size (4 KiB) for IO mapping */
+#define	NAND_IO_SIZE	SZ_4K
+
+#define	NAND_WP_OFF	0
+#define NAND_WP_BIT	0x00000010
+#define WR_RD_PIN_MONITORING	0x00600000
+
+#define	GPMC_BUF_FULL	0x00000001
+#define	GPMC_BUF_EMPTY	0x00000000
+
+#define NAND_Ecc_P1e		(1 << 0)
+#define NAND_Ecc_P2e		(1 << 1)
+#define NAND_Ecc_P4e		(1 << 2)
+#define NAND_Ecc_P8e		(1 << 3)
+#define NAND_Ecc_P16e		(1 << 4)
+#define NAND_Ecc_P32e		(1 << 5)
+#define NAND_Ecc_P64e		(1 << 6)
+#define NAND_Ecc_P128e		(1 << 7)
+#define NAND_Ecc_P256e		(1 << 8)
+#define NAND_Ecc_P512e		(1 << 9)
+#define NAND_Ecc_P1024e		(1 << 10)
+#define NAND_Ecc_P2048e		(1 << 11)
+
+#define NAND_Ecc_P1o		(1 << 16)
+#define NAND_Ecc_P2o		(1 << 17)
+#define NAND_Ecc_P4o		(1 << 18)
+#define NAND_Ecc_P8o		(1 << 19)
+#define NAND_Ecc_P16o		(1 << 20)
+#define NAND_Ecc_P32o		(1 << 21)
+#define NAND_Ecc_P64o		(1 << 22)
+#define NAND_Ecc_P128o		(1 << 23)
+#define NAND_Ecc_P256o		(1 << 24)
+#define NAND_Ecc_P512o		(1 << 25)
+#define NAND_Ecc_P1024o		(1 << 26)
+#define NAND_Ecc_P2048o		(1 << 27)
+
+#define TF(value)	(value ? 1 : 0)
+
+#define P2048e(a)	(TF(a & NAND_Ecc_P2048e)	<< 0)
+#define P2048o(a)	(TF(a & NAND_Ecc_P2048o)	<< 1)
+#define P1e(a)		(TF(a & NAND_Ecc_P1e)		<< 2)
+#define P1o(a)		(TF(a & NAND_Ecc_P1o)		<< 3)
+#define P2e(a)		(TF(a & NAND_Ecc_P2e)		<< 4)
+#define P2o(a)		(TF(a & NAND_Ecc_P2o)		<< 5)
+#define P4e(a)		(TF(a & NAND_Ecc_P4e)		<< 6)
+#define P4o(a)		(TF(a & NAND_Ecc_P4o)		<< 7)
+
+#define P8e(a)		(TF(a & NAND_Ecc_P8e)		<< 0)
+#define P8o(a)		(TF(a & NAND_Ecc_P8o)		<< 1)
+#define P16e(a)		(TF(a & NAND_Ecc_P16e)		<< 2)
+#define P16o(a)		(TF(a & NAND_Ecc_P16o)		<< 3)
+#define P32e(a)		(TF(a & NAND_Ecc_P32e)		<< 4)
+#define P32o(a)		(TF(a & NAND_Ecc_P32o)		<< 5)
+#define P64e(a)		(TF(a & NAND_Ecc_P64e)		<< 6)
+#define P64o(a)		(TF(a & NAND_Ecc_P64o)		<< 7)
+
+#define P128e(a)	(TF(a & NAND_Ecc_P128e)		<< 0)
+#define P128o(a)	(TF(a & NAND_Ecc_P128o)		<< 1)
+#define P256e(a)	(TF(a & NAND_Ecc_P256e)		<< 2)
+#define P256o(a)	(TF(a & NAND_Ecc_P256o)		<< 3)
+#define P512e(a)	(TF(a & NAND_Ecc_P512e)		<< 4)
+#define P512o(a)	(TF(a & NAND_Ecc_P512o)		<< 5)
+#define P1024e(a)	(TF(a & NAND_Ecc_P1024e)	<< 6)
+#define P1024o(a)	(TF(a & NAND_Ecc_P1024o)	<< 7)
+
+#define P8e_s(a)	(TF(a & NAND_Ecc_P8e)		<< 0)
+#define P8o_s(a)	(TF(a & NAND_Ecc_P8o)		<< 1)
+#define P16e_s(a)	(TF(a & NAND_Ecc_P16e)		<< 2)
+#define P16o_s(a)	(TF(a & NAND_Ecc_P16o)		<< 3)
+#define P1e_s(a)	(TF(a & NAND_Ecc_P1e)		<< 4)
+#define P1o_s(a)	(TF(a & NAND_Ecc_P1o)		<< 5)
+#define P2e_s(a)	(TF(a & NAND_Ecc_P2e)		<< 6)
+#define P2o_s(a)	(TF(a & NAND_Ecc_P2o)		<< 7)
+
+#define P4e_s(a)	(TF(a & NAND_Ecc_P4e)		<< 0)
+#define P4o_s(a)	(TF(a & NAND_Ecc_P4o)		<< 1)
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
+struct omap_nand_info {
+	struct nand_hw_control		controller;
+	struct omap_nand_platform_data	*pdata;
+	struct mtd_info			mtd;
+	struct mtd_partition		*parts;
+	struct nand_chip		nand;
+	struct platform_device		*pdev;
+
+	int				gpmc_cs;
+	unsigned long			phys_base;
+	void __iomem			*gpmc_cs_baseaddr;
+	void __iomem			*gpmc_baseaddr;
+};
+
+/**
+ * omap_nand_wp - This function enable or disable the Write Protect feature
+ * @mtd: MTD device structure
+ * @mode: WP ON/OFF
+ */
+static void omap_nand_wp(struct mtd_info *mtd, int mode)
+{
+	struct omap_nand_info *info = container_of(mtd,
+						struct omap_nand_info, mtd);
+
+	unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
+
+	if (mode)
+		config &= ~(NAND_WP_BIT);	/* WP is ON */
+	else
+		config |= (NAND_WP_BIT);	/* WP is OFF */
+
+	__raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
+}
+
+/**
+ * omap_hwcontrol - hardware specific access to control-lines
+ * @mtd: MTD device structure
+ * @cmd: command to device
+ * @ctrl:
+ * NAND_NCE: bit 0 -> don't care
+ * NAND_CLE: bit 1 -> Command Latch
+ * NAND_ALE: bit 2 -> Address Latch
+ *
+ * NOTE: boards may use different bits for these!!
+ */
+static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct omap_nand_info *info = container_of(mtd,
+					struct omap_nand_info, mtd);
+	switch (ctrl) {
+	case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
+		info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
+						GPMC_CS_NAND_COMMAND;
+		info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
+						GPMC_CS_NAND_DATA;
+		break;
+
+	case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
+		info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
+						GPMC_CS_NAND_ADDRESS;
+		info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
+						GPMC_CS_NAND_DATA;
+		break;
+
+	case NAND_CTRL_CHANGE | NAND_NCE:
+		info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
+						GPMC_CS_NAND_DATA;
+		info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
+						GPMC_CS_NAND_DATA;
+		break;
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		__raw_writeb(cmd, info->nand.IO_ADDR_W);
+}
+
+/**
+ * omap_read_buf16 - read data from NAND controller into buffer
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
+ */
+static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct nand_chip *nand = mtd->priv;
+
+	__raw_readsw(nand->IO_ADDR_R, buf, len / 2);
+}
+
+/**
+ * omap_write_buf16 - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
+{
+	struct omap_nand_info *info = container_of(mtd,
+						struct omap_nand_info, mtd);
+	u16 *p = (u16 *) buf;
+
+	/* FIXME try bursts of writesw() or DMA ... */
+	len >>= 1;
+
+	while (len--) {
+		writew(*p++, info->nand.IO_ADDR_W);
+
+		while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
+						GPMC_STATUS) & GPMC_BUF_FULL))
+			;
+	}
+}
+/**
+ * omap_verify_buf - Verify chip data against buffer
+ * @mtd: MTD device structure
+ * @buf: buffer containing the data to compare
+ * @len: number of bytes to compare
+ */
+static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+							mtd);
+	u16 *p = (u16 *) buf;
+
+	len >>= 1;
+	while (len--) {
+		if (*p++ != cpu_to_le16(readw(info->nand.IO_ADDR_R)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
+/**
+ * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
+ * @mtd: MTD device structure
+ */
+static void omap_hwecc_init(struct mtd_info *mtd)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+							mtd);
+	struct nand_chip *chip = mtd->priv;
+	unsigned long val = 0x0;
+
+	/* Read from ECC Control Register */
+	val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+	/* Clear all ECC | Enable Reg1 */
+	val = ((0x00000001<<8) | 0x00000001);
+	__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+
+	/* Read from ECC Size Config Register */
+	val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
+	/* ECCSIZE1=512 | Select eccResultsize[0-3] */
+	val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
+	__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
+}
+
+/**
+ * gen_true_ecc - This function will generate true ECC value
+ * @ecc_buf: buffer to store ecc code
+ *
+ * This generated true ECC value can be used when correcting
+ * data read from NAND flash memory core
+ */
+static void gen_true_ecc(u8 *ecc_buf)
+{
+	u32 tmp = ecc_buf[0] | (ecc_buf[1] << 16) |
+		((ecc_buf[2] & 0xF0) << 20) | ((ecc_buf[2] & 0x0F) << 8);
+
+	ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) |
+			P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
+	ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) |
+			P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
+	ecc_buf[2] = ~(P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) |
+			P1e(tmp) | P2048o(tmp) | P2048e(tmp));
+}
+
+/**
+ * omap_compare_ecc - Detect (2 bits) and correct (1 bit) error in data
+ * @ecc_data1:  ecc code from nand spare area
+ * @ecc_data2:  ecc code from hardware register obtained from hardware ecc
+ * @page_data:  page data
+ *
+ * This function compares two ECC's and indicates if there is an error.
+ * If the error can be corrected it will be corrected to the buffer.
+ */
+static int omap_compare_ecc(u8 *ecc_data1,	/* read from NAND memory */
+			    u8 *ecc_data2,	/* read from register */
+			    u8 *page_data)
+{
+	uint	i;
+	u8	tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
+	u8	comp0_bit[8], comp1_bit[8], comp2_bit[8];
+	u8	ecc_bit[24];
+	u8	ecc_sum = 0;
+	u8	find_bit = 0;
+	uint	find_byte = 0;
+	int	isEccFF;
+
+	isEccFF = ((*(u32 *)ecc_data1 & 0xFFFFFF) == 0xFFFFFF);
+
+	gen_true_ecc(ecc_data1);
+	gen_true_ecc(ecc_data2);
+
+	for (i = 0; i <= 2; i++) {
+		*(ecc_data1 + i) = ~(*(ecc_data1 + i));
+		*(ecc_data2 + i) = ~(*(ecc_data2 + i));
+	}
+
+	for (i = 0; i < 8; i++) {
+		tmp0_bit[i]     = *ecc_data1 % 2;
+		*ecc_data1	= *ecc_data1 / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		tmp1_bit[i]	 = *(ecc_data1 + 1) % 2;
+		*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		tmp2_bit[i]	 = *(ecc_data1 + 2) % 2;
+		*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		comp0_bit[i]     = *ecc_data2 % 2;
+		*ecc_data2       = *ecc_data2 / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		comp1_bit[i]     = *(ecc_data2 + 1) % 2;
+		*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		comp2_bit[i]     = *(ecc_data2 + 2) % 2;
+		*(ecc_data2 + 2) = *(ecc_data2 + 2) / 2;
+	}
+
+	for (i = 0; i < 6; i++)
+		ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
+
+	for (i = 0; i < 8; i++)
+		ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
+
+	for (i = 0; i < 8; i++)
+		ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
+
+	ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
+	ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
+
+	for (i = 0; i < 24; i++)
+		ecc_sum += ecc_bit[i];
+
+	switch (ecc_sum) {
+	case 0:
+		/* Not reached because this function is not called if
+		 *  ECC values are equal
+		 */
+		return 0;
+
+	case 1:
+		/* Uncorrectable error */
+		DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
+		return -1;
+
+	case 11:
+		/* UN-Correctable error */
+		DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR B\n");
+		return -1;
+
+	case 12:
+		/* Correctable error */
+		find_byte = (ecc_bit[23] << 8) +
+			    (ecc_bit[21] << 7) +
+			    (ecc_bit[19] << 6) +
+			    (ecc_bit[17] << 5) +
+			    (ecc_bit[15] << 4) +
+			    (ecc_bit[13] << 3) +
+			    (ecc_bit[11] << 2) +
+			    (ecc_bit[9]  << 1) +
+			    ecc_bit[7];
+
+		find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
+
+		DEBUG(MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at "
+				"offset: %d, bit: %d\n", find_byte, find_bit);
+
+		page_data[find_byte] ^= (1 << find_bit);
+
+		return 0;
+	default:
+		if (isEccFF) {
+			if (ecc_data2[0] == 0 &&
+			    ecc_data2[1] == 0 &&
+			    ecc_data2[2] == 0)
+				return 0;
+		}
+		DEBUG(MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
+		return -1;
+	}
+}
+
+/**
+ * omap_correct_data - Compares the ECC read with HW generated ECC
+ * @mtd: MTD device structure
+ * @dat: page data
+ * @read_ecc: ecc read from nand flash
+ * @calc_ecc: ecc read from HW ECC registers
+ *
+ * Compares the ecc read from nand spare area with ECC registers values
+ * and if ECC's mismached, it will call 'omap_compare_ecc' for error detection
+ * and correction.
+ */
+static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
+				u_char *read_ecc, u_char *calc_ecc)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+							mtd);
+	int blockCnt = 0, i = 0, ret = 0;
+
+	/* Ex NAND_ECC_HW12_2048 */
+	if ((info->nand.ecc.mode == NAND_ECC_HW) &&
+			(info->nand.ecc.size  == 2048))
+		blockCnt = 4;
+	else
+		blockCnt = 1;
+
+	for (i = 0; i < blockCnt; i++) {
+		if (memcmp(read_ecc, calc_ecc, 3) != 0) {
+			ret = omap_compare_ecc(read_ecc, calc_ecc, dat);
+			if (ret < 0)
+				return ret;
+		}
+		read_ecc += 3;
+		calc_ecc += 3;
+		dat      += 512;
+	}
+	return 0;
+}
+
+/**
+ * omap_calcuate_ecc - Generate non-inverted ECC bytes.
+ * @mtd: MTD device structure
+ * @dat: The pointer to data on which ecc is computed
+ * @ecc_code: The ecc_code buffer
+ *
+ * Using noninverted ECC can be considered ugly since writing a blank
+ * page ie. padding will clear the ECC bytes. This is no problem as long
+ * nobody is trying to write data on the seemingly unused page. Reading
+ * an erased page will produce an ECC mismatch between generated and read
+ * ECC bytes that has to be dealt with separately.
+ */
+static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+				u_char *ecc_code)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+							mtd);
+	unsigned long val = 0x0;
+	unsigned long reg;
+
+	/* Start Reading from HW ECC1_Result = 0x200 */
+	reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
+	val = __raw_readl(reg);
+	*ecc_code++ = val;          /* P128e, ..., P1e */
+	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
+	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+	reg += 4;
+
+	return 0;
+}
+
+/**
+ * omap_enable_hwecc - This function enables the hardware ecc functionality
+ * @mtd: MTD device structure
+ * @mode: Read/Write mode
+ */
+static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+							mtd);
+	struct nand_chip *chip = mtd->priv;
+	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		__raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+		/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+		val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
+		break;
+	case NAND_ECC_READSYN:
+		 __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+		/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+		val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
+		break;
+	case NAND_ECC_WRITE:
+		__raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
+		/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+		val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
+		break;
+	default:
+		DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
+					mode);
+		break;
+	}
+
+	__raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
+}
+#endif
+
+/**
+ * omap_wait - wait until the command is done
+ * @mtd: MTD device structure
+ * @chip: NAND Chip structure
+ *
+ * Wait function is called during Program and erase operations and
+ * the way it is called from MTD layer, we should wait till the NAND
+ * chip is ready after the programming/erase operation has completed.
+ *
+ * Erase can take up to 400ms and program up to 20ms according to
+ * general NAND and SmartMedia specs
+ */
+static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	struct nand_chip *this = mtd->priv;
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+							mtd);
+	unsigned long timeo = jiffies;
+	int status = NAND_STATUS_FAIL, state = this->state;
+
+	if (state == FL_ERASING)
+		timeo += (HZ * 400) / 1000;
+	else
+		timeo += (HZ * 20) / 1000;
+
+	this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
+						GPMC_CS_NAND_COMMAND;
+	this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
+
+	__raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
+
+	while (time_before(jiffies, timeo)) {
+		status = __raw_readb(this->IO_ADDR_R);
+		if (status & NAND_STATUS_READY)
+			break;
+		cond_resched();
+	}
+	return status;
+}
+
+/**
+ * omap_dev_ready - calls the platform specific dev_ready function
+ * @mtd: MTD device structure
+ */
+static int omap_dev_ready(struct mtd_info *mtd)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+							mtd);
+	unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+
+	if ((val & 0x100) == 0x100) {
+		/* Clear IRQ Interrupt */
+		val |= 0x100;
+		val &= ~(0x0);
+		__raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
+	} else {
+		unsigned int cnt = 0;
+		while (cnt++ < 0x1FF) {
+			if  ((val & 0x100) == 0x100)
+				return 0;
+			val = __raw_readl(info->gpmc_baseaddr +
+							GPMC_IRQ_STATUS);
+		}
+	}
+
+	return 1;
+}
+
+static int __devinit omap_nand_probe(struct platform_device *pdev)
+{
+	struct omap_nand_info		*info;
+	struct omap_nand_platform_data	*pdata;
+	int				err;
+	unsigned long 			val;
+
+
+	pdata = pdev->dev.platform_data;
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "platform data missing\n");
+		return -ENODEV;
+	}
+
+	info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, info);
+
+	spin_lock_init(&info->controller.lock);
+	init_waitqueue_head(&info->controller.wq);
+
+	info->pdev = pdev;
+
+	info->gpmc_cs		= pdata->cs;
+	info->gpmc_baseaddr	= pdata->gpmc_baseaddr;
+	info->gpmc_cs_baseaddr	= pdata->gpmc_cs_baseaddr;
+
+	info->mtd.priv		= &info->nand;
+	info->mtd.name		= dev_name(&pdev->dev);
+	info->mtd.owner		= THIS_MODULE;
+
+	err = gpmc_cs_request(info->gpmc_cs, NAND_IO_SIZE, &info->phys_base);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+		goto out_free_info;
+	}
+
+	/* Enable RD PIN Monitoring Reg */
+	if (pdata->dev_ready) {
+		val  = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1);
+		val |= WR_RD_PIN_MONITORING;
+		gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1, val);
+	}
+
+	val  = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG7);
+	val &= ~(0xf << 8);
+	val |=  (0xc & 0xf) << 8;
+	gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG7, val);
+
+	/* NAND write protect off */
+	omap_nand_wp(&info->mtd, NAND_WP_OFF);
+
+	if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
+				pdev->dev.driver->name)) {
+		err = -EBUSY;
+		goto out_free_cs;
+	}
+
+	info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
+	if (!info->nand.IO_ADDR_R) {
+		err = -ENOMEM;
+		goto out_release_mem_region;
+	}
+	info->nand.controller = &info->controller;
+
+	info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
+	info->nand.cmd_ctrl  = omap_hwcontrol;
+
+	/* REVISIT:  only supports 16-bit NAND flash */
+
+	info->nand.read_buf   = omap_read_buf16;
+	info->nand.write_buf  = omap_write_buf16;
+	info->nand.verify_buf = omap_verify_buf;
+
+	/*
+	 * If RDY/BSY line is connected to OMAP then use the omap ready
+	 * funcrtion and the generic nand_wait function which reads the status
+	 * register after monitoring the RDY/BSY line.Otherwise use a standard
+	 * chip delay which is slightly more than tR (AC Timing) of the NAND
+	 * device and read status register until you get a failure or success
+	 */
+	if (pdata->dev_ready) {
+		info->nand.dev_ready = omap_dev_ready;
+		info->nand.chip_delay = 0;
+	} else {
+		info->nand.waitfunc = omap_wait;
+		info->nand.chip_delay = 50;
+	}
+
+	info->nand.options  |= NAND_SKIP_BBTSCAN;
+	if ((gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1) & 0x3000)
+								== 0x1000)
+		info->nand.options  |= NAND_BUSWIDTH_16;
+
+#ifdef CONFIG_MTD_NAND_OMAP_HWECC
+	info->nand.ecc.bytes		= 3;
+	info->nand.ecc.size		= 512;
+	info->nand.ecc.calculate	= omap_calculate_ecc;
+	info->nand.ecc.hwctl		= omap_enable_hwecc;
+	info->nand.ecc.correct		= omap_correct_data;
+	info->nand.ecc.mode		= NAND_ECC_HW;
+
+	/* init HW ECC */
+	omap_hwecc_init(&info->mtd);
+#else
+	info->nand.ecc.mode = NAND_ECC_SOFT;
+#endif
+
+	/* DIP switches on some boards change between 8 and 16 bit
+	 * bus widths for flash.  Try the other width if the first try fails.
+	 */
+	if (nand_scan(&info->mtd, 1)) {
+		info->nand.options ^= NAND_BUSWIDTH_16;
+		if (nand_scan(&info->mtd, 1)) {
+			err = -ENXIO;
+			goto out_release_mem_region;
+		}
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
+	if (err > 0)
+		add_mtd_partitions(&info->mtd, info->parts, err);
+	else if (pdata->parts)
+		add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
+	else
+#endif
+		add_mtd_device(&info->mtd);
+
+	platform_set_drvdata(pdev, &info->mtd);
+
+	return 0;
+
+out_release_mem_region:
+	release_mem_region(info->phys_base, NAND_IO_SIZE);
+out_free_cs:
+	gpmc_cs_free(info->gpmc_cs);
+out_free_info:
+	kfree(info);
+
+	return err;
+}
+
+static int omap_nand_remove(struct platform_device *pdev)
+{
+	struct mtd_info *mtd = platform_get_drvdata(pdev);
+	struct omap_nand_info *info = mtd->priv;
+
+	platform_set_drvdata(pdev, NULL);
+	/* Release NAND device, its internal structures and partitions */
+	nand_release(&info->mtd);
+	iounmap(info->nand.IO_ADDR_R);
+	kfree(&info->mtd);
+	return 0;
+}
+
+static struct platform_driver omap_nand_driver = {
+	.probe		= omap_nand_probe,
+	.remove		= omap_nand_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init omap_nand_init(void)
+{
+	printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME);
+	return platform_driver_register(&omap_nand_driver);
+}
+
+static void __exit omap_nand_exit(void)
+{
+	platform_driver_unregister(&omap_nand_driver);
+}
+
+module_init(omap_nand_init);
+module_exit(omap_nand_exit);
+
+MODULE_ALIAS(DRIVER_NAME);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards");
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/orion_nand.c linux-libre-2.6.31-gnu/drivers/mtd/nand/orion_nand.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/orion_nand.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/orion_nand.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,6 +47,28 @@
 	writeb(cmd, nc->IO_ADDR_W + offs);
 }
 
+static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	void __iomem *io_base = chip->IO_ADDR_R;
+	uint64_t *buf64;
+	int i = 0;
+
+	while (len && (unsigned long)buf & 7) {
+		*buf++ = readb(io_base);
+		len--;
+	}
+	buf64 = (uint64_t *)buf;
+	while (i < len/8) {
+		uint64_t x;
+		asm volatile ("ldrd\t%0, [%1]" : "=&r" (x) : "r" (io_base));
+		buf64[i++] = x;
+	}
+	i *= 8;
+	while (i < len)
+		buf[i++] = readb(io_base);
+}
+
 static int __init orion_nand_probe(struct platform_device *pdev)
 {
 	struct mtd_info *mtd;
@@ -83,6 +105,7 @@
 	nc->priv = board;
 	nc->IO_ADDR_R = nc->IO_ADDR_W = io_base;
 	nc->cmd_ctrl = orion_nand_cmd_ctrl;
+	nc->read_buf = orion_nand_read_buf;
 	nc->ecc.mode = NAND_ECC_SOFT;
 
 	if (board->chip_delay)
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/plat_nand.c linux-libre-2.6.31-gnu/drivers/mtd/nand/plat_nand.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/plat_nand.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/plat_nand.c	2009-09-09 18:13:59.000000000 -0400
@@ -61,6 +61,8 @@
 	data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
 	data->chip.dev_ready = pdata->ctrl.dev_ready;
 	data->chip.select_chip = pdata->ctrl.select_chip;
+	data->chip.write_buf = pdata->ctrl.write_buf;
+	data->chip.read_buf = pdata->ctrl.read_buf;
 	data->chip.chip_delay = pdata->chip.chip_delay;
 	data->chip.options |= pdata->chip.options;
 
@@ -70,6 +72,13 @@
 
 	platform_set_drvdata(pdev, data);
 
+	/* Handle any platform specific setup */
+	if (pdata->ctrl.probe) {
+		res = pdata->ctrl.probe(pdev);
+		if (res)
+			goto out;
+	}
+
 	/* Scan to find existance of the device */
 	if (nand_scan(&data->mtd, 1)) {
 		res = -ENXIO;
@@ -86,6 +95,8 @@
 			return 0;
 		}
 	}
+	if (pdata->chip.set_parts)
+		pdata->chip.set_parts(data->mtd.size, &pdata->chip);
 	if (pdata->chip.partitions) {
 		data->parts = pdata->chip.partitions;
 		res = add_mtd_partitions(&data->mtd, data->parts,
@@ -99,6 +110,8 @@
 
 	nand_release(&data->mtd);
 out:
+	if (pdata->ctrl.remove)
+		pdata->ctrl.remove(pdev);
 	platform_set_drvdata(pdev, NULL);
 	iounmap(data->io_base);
 	kfree(data);
@@ -111,15 +124,15 @@
 static int __devexit plat_nand_remove(struct platform_device *pdev)
 {
 	struct plat_nand_data *data = platform_get_drvdata(pdev);
-#ifdef CONFIG_MTD_PARTITIONS
 	struct platform_nand_data *pdata = pdev->dev.platform_data;
-#endif
 
 	nand_release(&data->mtd);
 #ifdef CONFIG_MTD_PARTITIONS
 	if (data->parts && data->parts != pdata->chip.partitions)
 		kfree(data->parts);
 #endif
+	if (pdata->ctrl.remove)
+		pdata->ctrl.remove(pdev);
 	iounmap(data->io_base);
 	kfree(data);
 
@@ -128,7 +141,7 @@
 
 static struct platform_driver plat_nand_driver = {
 	.probe		= plat_nand_probe,
-	.remove		= plat_nand_remove,
+	.remove		= __devexit_p(plat_nand_remove),
 	.driver		= {
 		.name	= "gen_nand",
 		.owner	= THIS_MODULE,
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/s3c2410.c linux-libre-2.6.31-gnu/drivers/mtd/nand/s3c2410.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/s3c2410.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/s3c2410.c	2009-09-09 18:13:59.000000000 -0400
@@ -74,6 +74,14 @@
 
 struct s3c2410_nand_info;
 
+/**
+ * struct s3c2410_nand_mtd - driver MTD structure
+ * @mtd: The MTD instance to pass to the MTD layer.
+ * @chip: The NAND chip information.
+ * @set: The platform information supplied for this set of NAND chips.
+ * @info: Link back to the hardware information.
+ * @scan_res: The result from calling nand_scan_ident().
+*/
 struct s3c2410_nand_mtd {
 	struct mtd_info			mtd;
 	struct nand_chip		chip;
@@ -90,6 +98,21 @@
 
 /* overview of the s3c2410 nand state */
 
+/**
+ * struct s3c2410_nand_info - NAND controller state.
+ * @mtds: An array of MTD instances on this controoler.
+ * @platform: The platform data for this board.
+ * @device: The platform device we bound to.
+ * @area: The IO area resource that came from request_mem_region().
+ * @clk: The clock resource for this controller.
+ * @regs: The area mapped for the hardware registers described by @area.
+ * @sel_reg: Pointer to the register controlling the NAND selection.
+ * @sel_bit: The bit in @sel_reg to select the NAND chip.
+ * @mtd_count: The number of MTDs created from this controller.
+ * @save_sel: The contents of @sel_reg to be saved over suspend.
+ * @clk_rate: The clock rate from @clk.
+ * @cpu_type: The exact type of this controller.
+ */
 struct s3c2410_nand_info {
 	/* mtd info */
 	struct nand_hw_control		controller;
@@ -145,12 +168,19 @@
 
 #define NS_IN_KHZ 1000000
 
+/**
+ * s3c_nand_calc_rate - calculate timing data.
+ * @wanted: The cycle time in nanoseconds.
+ * @clk: The clock rate in kHz.
+ * @max: The maximum divider value.
+ *
+ * Calculate the timing value from the given parameters.
+ */
 static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
 {
 	int result;
 
-	result = (wanted * clk) / NS_IN_KHZ;
-	result++;
+	result = DIV_ROUND_UP((wanted * clk), NS_IN_KHZ);
 
 	pr_debug("result %d from %ld, %d\n", result, clk, wanted);
 
@@ -169,13 +199,21 @@
 
 /* controller setup */
 
+/**
+ * s3c2410_nand_setrate - setup controller timing information.
+ * @info: The controller instance.
+ *
+ * Given the information supplied by the platform, calculate and set
+ * the necessary timing registers in the hardware to generate the
+ * necessary timing cycles to the hardware.
+ */
 static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
 {
 	struct s3c2410_platform_nand *plat = info->platform;
 	int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
 	int tacls, twrph0, twrph1;
 	unsigned long clkrate = clk_get_rate(info->clk);
-	unsigned long set, cfg, mask;
+	unsigned long uninitialized_var(set), cfg, uninitialized_var(mask);
 	unsigned long flags;
 
 	/* calculate the timing information for the controller */
@@ -215,9 +253,9 @@
 
 	case TYPE_S3C2440:
 	case TYPE_S3C2412:
-		mask = (S3C2410_NFCONF_TACLS(tacls_max - 1) |
-			S3C2410_NFCONF_TWRPH0(7) |
-			S3C2410_NFCONF_TWRPH1(7));
+		mask = (S3C2440_NFCONF_TACLS(tacls_max - 1) |
+			S3C2440_NFCONF_TWRPH0(7) |
+			S3C2440_NFCONF_TWRPH1(7));
 
 		set = S3C2440_NFCONF_TACLS(tacls - 1);
 		set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
@@ -225,14 +263,9 @@
 		break;
 
 	default:
-		/* keep compiler happy */
-		mask = 0;
-		set = 0;
 		BUG();
 	}
 
-	dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
-
 	local_irq_save(flags);
 
 	cfg = readl(info->regs + S3C2410_NFCONF);
@@ -242,9 +275,18 @@
 
 	local_irq_restore(flags);
 
+	dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
+
 	return 0;
 }
 
+/**
+ * s3c2410_nand_inithw - basic hardware initialisation
+ * @info: The hardware state.
+ *
+ * Do the basic initialisation of the hardware, using s3c2410_nand_setrate()
+ * to setup the hardware access speeds and set the controller to be enabled.
+*/
 static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
 {
 	int ret;
@@ -268,8 +310,19 @@
 	return 0;
 }
 
-/* select chip */
-
+/**
+ * s3c2410_nand_select_chip - select the given nand chip
+ * @mtd: The MTD instance for this chip.
+ * @chip: The chip number.
+ *
+ * This is called by the MTD layer to either select a given chip for the
+ * @mtd instance, or to indicate that the access has finished and the
+ * chip can be de-selected.
+ *
+ * The routine ensures that the nFCE line is correctly setup, and any
+ * platform specific selection code is called to route nFCE to the specific
+ * chip.
+ */
 static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
 {
 	struct s3c2410_nand_info *info;
@@ -530,7 +583,16 @@
 static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-	readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
+
+	readsl(info->regs + S3C2440_NFDATA, buf, len >> 2);
+
+	/* cleanup if we've got less than a word to do */
+	if (len & 3) {
+		buf += len & ~3;
+
+		for (; len & 3; len--)
+			*buf++ = readb(info->regs + S3C2440_NFDATA);
+	}
 }
 
 static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
@@ -542,7 +604,16 @@
 static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-	writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
+
+	writesl(info->regs + S3C2440_NFDATA, buf, len >> 2);
+
+	/* cleanup any fractional write */
+	if (len & 3) {
+		buf += len & ~3;
+
+		for (; len & 3; len--, buf++)
+			writeb(*buf, info->regs + S3C2440_NFDATA);
+	}
 }
 
 /* cpufreq driver support */
@@ -593,7 +664,7 @@
 
 /* device management functions */
 
-static int s3c2410_nand_remove(struct platform_device *pdev)
+static int s3c24xx_nand_remove(struct platform_device *pdev)
 {
 	struct s3c2410_nand_info *info = to_nand_info(pdev);
 
@@ -645,17 +716,31 @@
 }
 
 #ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_mtd *mtd,
 				      struct s3c2410_nand_set *set)
 {
+	struct mtd_partition *part_info;
+	int nr_part = 0;
+
 	if (set == NULL)
 		return add_mtd_device(&mtd->mtd);
 
-	if (set->nr_partitions > 0 && set->partitions != NULL) {
-		return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
+	if (set->nr_partitions == 0) {
+		mtd->mtd.name = set->name;
+		nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
+						&part_info, 0);
+	} else {
+		if (set->nr_partitions > 0 && set->partitions != NULL) {
+			nr_part = set->nr_partitions;
+			part_info = set->partitions;
+		}
 	}
 
+	if (nr_part > 0 && part_info)
+		return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
+
 	return add_mtd_device(&mtd->mtd);
 }
 #else
@@ -667,11 +752,16 @@
 }
 #endif
 
-/* s3c2410_nand_init_chip
+/**
+ * s3c2410_nand_init_chip - initialise a single instance of an chip
+ * @info: The base NAND controller the chip is on.
+ * @nmtd: The new controller MTD instance to fill in.
+ * @set: The information passed from the board specific platform data.
  *
- * init a single instance of an chip
-*/
-
+ * Initialise the given @nmtd from the information in @info and @set. This
+ * readies the structure for use with the MTD layer functions by ensuring
+ * all pointers are setup and the necessary control routines selected.
+ */
 static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 				   struct s3c2410_nand_mtd *nmtd,
 				   struct s3c2410_nand_set *set)
@@ -757,14 +847,40 @@
 
 	if (set->disable_ecc)
 		chip->ecc.mode	= NAND_ECC_NONE;
+
+	switch (chip->ecc.mode) {
+	case NAND_ECC_NONE:
+		dev_info(info->device, "NAND ECC disabled\n");
+		break;
+	case NAND_ECC_SOFT:
+		dev_info(info->device, "NAND soft ECC\n");
+		break;
+	case NAND_ECC_HW:
+		dev_info(info->device, "NAND hardware ECC\n");
+		break;
+	default:
+		dev_info(info->device, "NAND ECC UNKNOWN\n");
+		break;
+	}
+
+	/* If you use u-boot BBT creation code, specifying this flag will
+	 * let the kernel fish out the BBT from the NAND, and also skip the
+	 * full NAND scan that can take 1/2s or so. Little things... */
+	if (set->flash_bbt)
+		chip->options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
 }
 
-/* s3c2410_nand_update_chip
+/**
+ * s3c2410_nand_update_chip - post probe update
+ * @info: The controller instance.
+ * @nmtd: The driver version of the MTD instance.
  *
- * post-probe chip update, to change any items, such as the
- * layout for large page nand
- */
-
+ * This routine is called after the chip probe has succesfully completed
+ * and the relevant per-chip information updated. This call ensure that
+ * we update the internal state accordingly.
+ *
+ * The internal state is currently limited to the ECC state information.
+*/
 static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 				     struct s3c2410_nand_mtd *nmtd)
 {
@@ -773,33 +889,33 @@
 	dev_dbg(info->device, "chip %p => page shift %d\n",
 		chip, chip->page_shift);
 
-	if (hardware_ecc) {
+	if (chip->ecc.mode != NAND_ECC_HW)
+		return;
+
 		/* change the behaviour depending on wether we are using
 		 * the large or small page nand device */
 
-		if (chip->page_shift > 10) {
-			chip->ecc.size	    = 256;
-			chip->ecc.bytes	    = 3;
-		} else {
-			chip->ecc.size	    = 512;
-			chip->ecc.bytes	    = 3;
-			chip->ecc.layout    = &nand_hw_eccoob;
-		}
+	if (chip->page_shift > 10) {
+		chip->ecc.size	    = 256;
+		chip->ecc.bytes	    = 3;
+	} else {
+		chip->ecc.size	    = 512;
+		chip->ecc.bytes	    = 3;
+		chip->ecc.layout    = &nand_hw_eccoob;
 	}
 }
 
-/* s3c2410_nand_probe
+/* s3c24xx_nand_probe
  *
  * called by device layer when it finds a device matching
  * one our driver can handled. This code checks to see if
  * it can allocate all necessary resources then calls the
  * nand layer to look for devices
 */
-
-static int s3c24xx_nand_probe(struct platform_device *pdev,
-			      enum s3c_cpu_type cpu_type)
+static int s3c24xx_nand_probe(struct platform_device *pdev)
 {
 	struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
+	enum s3c_cpu_type cpu_type; 
 	struct s3c2410_nand_info *info;
 	struct s3c2410_nand_mtd *nmtd;
 	struct s3c2410_nand_set *sets;
@@ -809,6 +925,8 @@
 	int nr_sets;
 	int setno;
 
+	cpu_type = platform_get_device_id(pdev)->driver_data;
+
 	pr_debug("s3c2410_nand_probe(%p)\n", pdev);
 
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -922,7 +1040,7 @@
 	return 0;
 
  exit_error:
-	s3c2410_nand_remove(pdev);
+	s3c24xx_nand_remove(pdev);
 
 	if (err == 0)
 		err = -EINVAL;
@@ -983,50 +1101,33 @@
 
 /* driver device registration */
 
-static int s3c2410_nand_probe(struct platform_device *dev)
-{
-	return s3c24xx_nand_probe(dev, TYPE_S3C2410);
-}
-
-static int s3c2440_nand_probe(struct platform_device *dev)
-{
-	return s3c24xx_nand_probe(dev, TYPE_S3C2440);
-}
-
-static int s3c2412_nand_probe(struct platform_device *dev)
-{
-	return s3c24xx_nand_probe(dev, TYPE_S3C2412);
-}
-
-static struct platform_driver s3c2410_nand_driver = {
-	.probe		= s3c2410_nand_probe,
-	.remove		= s3c2410_nand_remove,
-	.suspend	= s3c24xx_nand_suspend,
-	.resume		= s3c24xx_nand_resume,
-	.driver		= {
-		.name	= "s3c2410-nand",
-		.owner	= THIS_MODULE,
+static struct platform_device_id s3c24xx_driver_ids[] = {
+	{
+		.name		= "s3c2410-nand",
+		.driver_data	= TYPE_S3C2410,
+	}, {
+		.name		= "s3c2440-nand",
+		.driver_data	= TYPE_S3C2440,
+	}, {
+		.name		= "s3c2412-nand",
+		.driver_data	= TYPE_S3C2412,
+	}, {
+		.name		= "s3c6400-nand",
+		.driver_data	= TYPE_S3C2412, /* compatible with 2412 */
 	},
+	{ }
 };
 
-static struct platform_driver s3c2440_nand_driver = {
-	.probe		= s3c2440_nand_probe,
-	.remove		= s3c2410_nand_remove,
-	.suspend	= s3c24xx_nand_suspend,
-	.resume		= s3c24xx_nand_resume,
-	.driver		= {
-		.name	= "s3c2440-nand",
-		.owner	= THIS_MODULE,
-	},
-};
+MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
 
-static struct platform_driver s3c2412_nand_driver = {
-	.probe		= s3c2412_nand_probe,
-	.remove		= s3c2410_nand_remove,
+static struct platform_driver s3c24xx_nand_driver = {
+	.probe		= s3c24xx_nand_probe,
+	.remove		= s3c24xx_nand_remove,
 	.suspend	= s3c24xx_nand_suspend,
 	.resume		= s3c24xx_nand_resume,
+	.id_table	= s3c24xx_driver_ids,
 	.driver		= {
-		.name	= "s3c2412-nand",
+		.name	= "s3c24xx-nand",
 		.owner	= THIS_MODULE,
 	},
 };
@@ -1035,16 +1136,12 @@
 {
 	printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");
 
-	platform_driver_register(&s3c2412_nand_driver);
-	platform_driver_register(&s3c2440_nand_driver);
-	return platform_driver_register(&s3c2410_nand_driver);
+	return platform_driver_register(&s3c24xx_nand_driver);
 }
 
 static void __exit s3c2410_nand_exit(void)
 {
-	platform_driver_unregister(&s3c2412_nand_driver);
-	platform_driver_unregister(&s3c2440_nand_driver);
-	platform_driver_unregister(&s3c2410_nand_driver);
+	platform_driver_unregister(&s3c24xx_nand_driver);
 }
 
 module_init(s3c2410_nand_init);
@@ -1053,6 +1150,3 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
-MODULE_ALIAS("platform:s3c2410-nand");
-MODULE_ALIAS("platform:s3c2412-nand");
-MODULE_ALIAS("platform:s3c2440-nand");
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nand/txx9ndfmc.c linux-libre-2.6.31-gnu/drivers/mtd/nand/txx9ndfmc.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nand/txx9ndfmc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nand/txx9ndfmc.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,7 +64,7 @@
 	struct nand_chip chip;
 	struct mtd_info mtd;
 	int cs;
-	char mtdname[BUS_ID_SIZE + 2];
+	const char *mtdname;
 };
 
 #define MAX_TXX9NDFMC_DEV	4
@@ -334,16 +334,23 @@
 
 		if (plat->ch_mask != 1) {
 			txx9_priv->cs = i;
-			sprintf(txx9_priv->mtdname, "%s.%u",
-				dev_name(&dev->dev), i);
+			txx9_priv->mtdname = kasprintf(GFP_KERNEL, "%s.%u",
+						       dev_name(&dev->dev), i);
 		} else {
 			txx9_priv->cs = -1;
-			strcpy(txx9_priv->mtdname, dev_name(&dev->dev));
+			txx9_priv->mtdname = kstrdup(dev_name(&dev->dev),
+						     GFP_KERNEL);
+		}
+		if (!txx9_priv->mtdname) {
+			kfree(txx9_priv);
+			dev_err(&dev->dev, "Unable to allocate MTD name.\n");
+			continue;
 		}
 		if (plat->wide_mask & (1 << i))
 			chip->options |= NAND_BUSWIDTH_16;
 
 		if (nand_scan(mtd, 1)) {
+			kfree(txx9_priv->mtdname);
 			kfree(txx9_priv);
 			continue;
 		}
@@ -385,6 +392,7 @@
 		kfree(drvdata->parts[i]);
 #endif
 		del_mtd_device(mtd);
+		kfree(txx9_priv->mtdname);
 		kfree(txx9_priv);
 	}
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/nftlcore.c linux-libre-2.6.31-gnu/drivers/mtd/nftlcore.c
--- linux-libre-2.6.30-gnu/drivers/mtd/nftlcore.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/nftlcore.c	2009-09-09 18:13:59.000000000 -0400
@@ -135,16 +135,17 @@
 int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
 		  size_t *retlen, uint8_t *buf)
 {
+	loff_t mask = mtd->writesize - 1;
 	struct mtd_oob_ops ops;
 	int res;
 
 	ops.mode = MTD_OOB_PLACE;
-	ops.ooboffs = offs & (mtd->writesize - 1);
+	ops.ooboffs = offs & mask;
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	ops.datbuf = NULL;
 
-	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	res = mtd->read_oob(mtd, offs & ~mask, &ops);
 	*retlen = ops.oobretlen;
 	return res;
 }
@@ -155,16 +156,17 @@
 int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
 		   size_t *retlen, uint8_t *buf)
 {
+	loff_t mask = mtd->writesize - 1;
 	struct mtd_oob_ops ops;
 	int res;
 
 	ops.mode = MTD_OOB_PLACE;
-	ops.ooboffs = offs & (mtd->writesize - 1);
+	ops.ooboffs = offs & mask;
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	ops.datbuf = NULL;
 
-	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	res = mtd->write_oob(mtd, offs & ~mask, &ops);
 	*retlen = ops.oobretlen;
 	return res;
 }
@@ -177,17 +179,18 @@
 static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
 		      size_t *retlen, uint8_t *buf, uint8_t *oob)
 {
+	loff_t mask = mtd->writesize - 1;
 	struct mtd_oob_ops ops;
 	int res;
 
 	ops.mode = MTD_OOB_PLACE;
-	ops.ooboffs = offs;
+	ops.ooboffs = offs & mask;
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = oob;
 	ops.datbuf = buf;
 	ops.len = len;
 
-	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	res = mtd->write_oob(mtd, offs & ~mask, &ops);
 	*retlen = ops.retlen;
 	return res;
 }
@@ -208,7 +211,7 @@
 	/* Normally, we force a fold to happen before we run out of free blocks completely */
 	if (!desperate && nftl->numfreeEUNs < 2) {
 		DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n");
-		return 0xffff;
+		return BLOCK_NIL;
 	}
 
 	/* Scan for a free block */
@@ -230,11 +233,11 @@
 			printk("Argh! No free blocks found! LastFreeEUN = %d, "
 			       "FirstEUN = %d\n", nftl->LastFreeEUN,
 			       le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));
-			return 0xffff;
+			return BLOCK_NIL;
 		}
 	} while (pot != nftl->LastFreeEUN);
 
-	return 0xffff;
+	return BLOCK_NIL;
 }
 
 static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
@@ -431,7 +434,7 @@
 
 	/* add the header so that it is now a valid chain */
 	oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
-	oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
+	oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL;
 
 	nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
 		       8, &retlen, (char *)&oob.u);
@@ -515,7 +518,7 @@
 	if (ChainLength < 2) {
 		printk(KERN_WARNING "No Virtual Unit Chains available for folding. "
 		       "Failing request\n");
-		return 0xffff;
+		return BLOCK_NIL;
 	}
 
 	return NFTL_foldchain (nftl, LongestChain, pendingblock);
@@ -578,7 +581,7 @@
 				printk(KERN_WARNING
 				       "Infinite loop in Virtual Unit Chain 0x%x\n",
 				       thisVUC);
-				return 0xffff;
+				return BLOCK_NIL;
 			}
 
 			/* Skip to next block in chain */
@@ -601,7 +604,7 @@
 			//u16 startEUN = nftl->EUNtable[thisVUC];
 
 			//printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
-			writeEUN = NFTL_makefreeblock(nftl, 0xffff);
+			writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL);
 
 			if (writeEUN == BLOCK_NIL) {
 				/* OK, we accept that the above comment is
@@ -673,7 +676,7 @@
 
 	printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n",
 	       thisVUC);
-	return 0xffff;
+	return BLOCK_NIL;
 }
 
 static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/onenand/omap2.c linux-libre-2.6.31-gnu/drivers/mtd/onenand/omap2.c
--- linux-libre-2.6.30-gnu/drivers/mtd/onenand/omap2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/onenand/omap2.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,7 +39,6 @@
 #include <mach/gpmc.h>
 #include <mach/onenand.h>
 #include <mach/gpio.h>
-#include <mach/pm.h>
 
 #include <mach/dma.h>
 
@@ -267,7 +266,7 @@
 
 	if (ONENAND_CURRENT_BUFFERRAM(this)) {
 		if (area == ONENAND_DATARAM)
-			return mtd->writesize;
+			return this->writesize;
 		if (area == ONENAND_SPARERAM)
 			return mtd->oobsize;
 	}
@@ -566,7 +565,7 @@
 				      NULL, __adjust_timing);
 }
 
-static void __devexit omap2_onenand_shutdown(struct platform_device *pdev)
+static void omap2_onenand_shutdown(struct platform_device *pdev)
 {
 	struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 
@@ -771,6 +770,7 @@
 	}
 	iounmap(c->onenand.base);
 	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+	gpmc_cs_free(c->gpmc_cs);
 	kfree(c);
 
 	return 0;
@@ -778,7 +778,7 @@
 
 static struct platform_driver omap2_onenand_driver = {
 	.probe		= omap2_onenand_probe,
-	.remove		= omap2_onenand_remove,
+	.remove		= __devexit_p(omap2_onenand_remove),
 	.shutdown	= omap2_onenand_shutdown,
 	.driver		= {
 		.name	= DRIVER_NAME,
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/onenand/onenand_base.c linux-libre-2.6.31-gnu/drivers/mtd/onenand/onenand_base.c
--- linux-libre-2.6.30-gnu/drivers/mtd/onenand/onenand_base.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/onenand/onenand_base.c	2009-09-09 18:13:59.000000000 -0400
@@ -9,6 +9,10 @@
  *	auto-placement support, read-while load support, various fixes
  *	Copyright (C) Nokia Corporation, 2007
  *
+ *	Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com>
+ *	Flex-OneNAND support
+ *	Copyright (C) Samsung Electronics, 2008
+ *
  * 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.
@@ -16,6 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
@@ -27,6 +32,38 @@
 
 #include <asm/io.h>
 
+/* Default Flex-OneNAND boundary and lock respectively */
+static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };
+
+module_param_array(flex_bdry, int, NULL, 0400);
+MODULE_PARM_DESC(flex_bdry,	"SLC Boundary information for Flex-OneNAND"
+				"Syntax:flex_bdry=DIE_BDRY,LOCK,..."
+				"DIE_BDRY: SLC boundary of the die"
+				"LOCK: Locking information for SLC boundary"
+				"    : 0->Set boundary in unlocked status"
+				"    : 1->Set boundary in locked status");
+
+/**
+ *  onenand_oob_128 - oob info for Flex-Onenand with 4KB page
+ *  For now, we expose only 64 out of 80 ecc bytes
+ */
+static struct nand_ecclayout onenand_oob_128 = {
+	.eccbytes	= 64,
+	.eccpos		= {
+		6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+		22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+		38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+		54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+		70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+		86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+		102, 103, 104, 105
+		},
+	.oobfree	= {
+		{2, 4}, {18, 4}, {34, 4}, {50, 4},
+		{66, 4}, {82, 4}, {98, 4}, {114, 4}
+	}
+};
+
 /**
  * onenand_oob_64 - oob info for large (2KB) page
  */
@@ -65,6 +102,14 @@
 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 48 */
 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 64 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 80 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 96 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 112 */
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,	/* 128 */
 };
 
 /**
@@ -171,6 +216,70 @@
 }
 
 /**
+ * flexonenand_block- For given address return block number
+ * @param this         - OneNAND device structure
+ * @param addr		- Address for which block number is needed
+ */
+static unsigned flexonenand_block(struct onenand_chip *this, loff_t addr)
+{
+	unsigned boundary, blk, die = 0;
+
+	if (ONENAND_IS_DDP(this) && addr >= this->diesize[0]) {
+		die = 1;
+		addr -= this->diesize[0];
+	}
+
+	boundary = this->boundary[die];
+
+	blk = addr >> (this->erase_shift - 1);
+	if (blk > boundary)
+		blk = (blk + boundary + 1) >> 1;
+
+	blk += die ? this->density_mask : 0;
+	return blk;
+}
+
+inline unsigned onenand_block(struct onenand_chip *this, loff_t addr)
+{
+	if (!FLEXONENAND(this))
+		return addr >> this->erase_shift;
+	return flexonenand_block(this, addr);
+}
+
+/**
+ * flexonenand_addr - Return address of the block
+ * @this:		OneNAND device structure
+ * @block:		Block number on Flex-OneNAND
+ *
+ * Return address of the block
+ */
+static loff_t flexonenand_addr(struct onenand_chip *this, int block)
+{
+	loff_t ofs = 0;
+	int die = 0, boundary;
+
+	if (ONENAND_IS_DDP(this) && block >= this->density_mask) {
+		block -= this->density_mask;
+		die = 1;
+		ofs = this->diesize[0];
+	}
+
+	boundary = this->boundary[die];
+	ofs += (loff_t)block << (this->erase_shift - 1);
+	if (block > (boundary + 1))
+		ofs += (loff_t)(block - boundary - 1) << (this->erase_shift - 1);
+	return ofs;
+}
+
+loff_t onenand_addr(struct onenand_chip *this, int block)
+{
+	if (!FLEXONENAND(this))
+		return (loff_t)block << this->erase_shift;
+	return flexonenand_addr(this, block);
+}
+EXPORT_SYMBOL(onenand_addr);
+
+/**
  * onenand_get_density - [DEFAULT] Get OneNAND density
  * @param dev_id	OneNAND device ID
  *
@@ -183,6 +292,22 @@
 }
 
 /**
+ * flexonenand_region - [Flex-OneNAND] Return erase region of addr
+ * @param mtd		MTD device structure
+ * @param addr		address whose erase region needs to be identified
+ */
+int flexonenand_region(struct mtd_info *mtd, loff_t addr)
+{
+	int i;
+
+	for (i = 0; i < mtd->numeraseregions; i++)
+		if (addr < mtd->eraseregions[i].offset)
+			break;
+	return i - 1;
+}
+EXPORT_SYMBOL(flexonenand_region);
+
+/**
  * onenand_command - [DEFAULT] Send command to OneNAND device
  * @param mtd		MTD device structure
  * @param cmd		the command to be sent
@@ -207,16 +332,28 @@
 		page = -1;
 		break;
 
+	case FLEXONENAND_CMD_PI_ACCESS:
+		/* addr contains die index */
+		block = addr * this->density_mask;
+		page = -1;
+		break;
+
 	case ONENAND_CMD_ERASE:
 	case ONENAND_CMD_BUFFERRAM:
 	case ONENAND_CMD_OTP_ACCESS:
-		block = (int) (addr >> this->erase_shift);
+		block = onenand_block(this, addr);
 		page = -1;
 		break;
 
+	case FLEXONENAND_CMD_READ_PI:
+		cmd = ONENAND_CMD_READ;
+		block = addr * this->density_mask;
+		page = 0;
+		break;
+
 	default:
-		block = (int) (addr >> this->erase_shift);
-		page = (int) (addr >> this->page_shift);
+		block = onenand_block(this, addr);
+		page = (int) (addr - onenand_addr(this, block)) >> this->page_shift;
 
 		if (ONENAND_IS_2PLANE(this)) {
 			/* Make the even block number */
@@ -236,7 +373,7 @@
 		value = onenand_bufferram_address(this, block);
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
 
-		if (ONENAND_IS_2PLANE(this))
+		if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this))
 			/* It is always BufferRAM0 */
 			ONENAND_SET_BUFFERRAM0(this);
 		else
@@ -258,13 +395,18 @@
 
 	if (page != -1) {
 		/* Now we use page size operation */
-		int sectors = 4, count = 4;
+		int sectors = 0, count = 0;
 		int dataram;
 
 		switch (cmd) {
+		case FLEXONENAND_CMD_RECOVER_LSB:
 		case ONENAND_CMD_READ:
 		case ONENAND_CMD_READOOB:
-			dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
+			if (ONENAND_IS_MLC(this))
+				/* It is always BufferRAM0 */
+				dataram = ONENAND_SET_BUFFERRAM0(this);
+			else
+				dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
 			break;
 
 		default:
@@ -293,6 +435,30 @@
 }
 
 /**
+ * onenand_read_ecc - return ecc status
+ * @param this		onenand chip structure
+ */
+static inline int onenand_read_ecc(struct onenand_chip *this)
+{
+	int ecc, i, result = 0;
+
+	if (!FLEXONENAND(this))
+		return this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+
+	for (i = 0; i < 4; i++) {
+		ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i);
+		if (likely(!ecc))
+			continue;
+		if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR)
+			return ONENAND_ECC_2BIT_ALL;
+		else
+			result = ONENAND_ECC_1BIT_ALL;
+	}
+
+	return result;
+}
+
+/**
  * onenand_wait - [DEFAULT] wait until the command is done
  * @param mtd		MTD device structure
  * @param state		state to select the max. timeout value
@@ -331,14 +497,14 @@
 	 * power off recovery (POR) test, it should read ECC status first
 	 */
 	if (interrupt & ONENAND_INT_READ) {
-		int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+		int ecc = onenand_read_ecc(this);
 		if (ecc) {
 			if (ecc & ONENAND_ECC_2BIT_ALL) {
 				printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
 				mtd->ecc_stats.failed++;
 				return -EBADMSG;
 			} else if (ecc & ONENAND_ECC_1BIT_ALL) {
-				printk(KERN_INFO "onenand_wait: correctable ECC error = 0x%04x\n", ecc);
+				printk(KERN_DEBUG "onenand_wait: correctable ECC error = 0x%04x\n", ecc);
 				mtd->ecc_stats.corrected++;
 			}
 		}
@@ -656,7 +822,7 @@
 
 	if (found && ONENAND_IS_DDP(this)) {
 		/* Select DataRAM for DDP */
-		int block = (int) (addr >> this->erase_shift);
+		int block = onenand_block(this, addr);
 		int value = onenand_bufferram_address(this, block);
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
 	}
@@ -816,6 +982,149 @@
 }
 
 /**
+ * onenand_recover_lsb - [Flex-OneNAND] Recover LSB page data
+ * @param mtd		MTD device structure
+ * @param addr		address to recover
+ * @param status	return value from onenand_wait / onenand_bbt_wait
+ *
+ * MLC NAND Flash cell has paired pages - LSB page and MSB page. LSB page has
+ * lower page address and MSB page has higher page address in paired pages.
+ * If power off occurs during MSB page program, the paired LSB page data can
+ * become corrupt. LSB page recovery read is a way to read LSB page though page
+ * data are corrupted. When uncorrectable error occurs as a result of LSB page
+ * read after power up, issue LSB page recovery read.
+ */
+static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
+{
+	struct onenand_chip *this = mtd->priv;
+	int i;
+
+	/* Recovery is only for Flex-OneNAND */
+	if (!FLEXONENAND(this))
+		return status;
+
+	/* check if we failed due to uncorrectable error */
+	if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
+		return status;
+
+	/* check if address lies in MLC region */
+	i = flexonenand_region(mtd, addr);
+	if (mtd->eraseregions[i].erasesize < (1 << this->erase_shift))
+		return status;
+
+	/* We are attempting to reread, so decrement stats.failed
+	 * which was incremented by onenand_wait due to read failure
+	 */
+	printk(KERN_INFO "onenand_recover_lsb: Attempting to recover from uncorrectable read\n");
+	mtd->ecc_stats.failed--;
+
+	/* Issue the LSB page recovery command */
+	this->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr, this->writesize);
+	return this->wait(mtd, FL_READING);
+}
+
+/**
+ * onenand_mlc_read_ops_nolock - MLC OneNAND read main and/or out-of-band
+ * @param mtd		MTD device structure
+ * @param from		offset to read from
+ * @param ops:		oob operation description structure
+ *
+ * MLC OneNAND / Flex-OneNAND has 4KB page size and 4KB dataram.
+ * So, read-while-load is not present.
+ */
+static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from,
+				struct mtd_oob_ops *ops)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct mtd_ecc_stats stats;
+	size_t len = ops->len;
+	size_t ooblen = ops->ooblen;
+	u_char *buf = ops->datbuf;
+	u_char *oobbuf = ops->oobbuf;
+	int read = 0, column, thislen;
+	int oobread = 0, oobcolumn, thisooblen, oobsize;
+	int ret = 0;
+	int writesize = this->writesize;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_mlc_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+
+	if (ops->mode == MTD_OOB_AUTO)
+		oobsize = this->ecclayout->oobavail;
+	else
+		oobsize = mtd->oobsize;
+
+	oobcolumn = from & (mtd->oobsize - 1);
+
+	/* Do not allow reads past end of device */
+	if (from + len > mtd->size) {
+		printk(KERN_ERR "onenand_mlc_read_ops_nolock: Attempt read beyond end of device\n");
+		ops->retlen = 0;
+		ops->oobretlen = 0;
+		return -EINVAL;
+	}
+
+	stats = mtd->ecc_stats;
+
+	while (read < len) {
+		cond_resched();
+
+		thislen = min_t(int, writesize, len - read);
+
+		column = from & (writesize - 1);
+		if (column + thislen > writesize)
+			thislen = writesize - column;
+
+		if (!onenand_check_bufferram(mtd, from)) {
+			this->command(mtd, ONENAND_CMD_READ, from, writesize);
+
+			ret = this->wait(mtd, FL_READING);
+			if (unlikely(ret))
+				ret = onenand_recover_lsb(mtd, from, ret);
+			onenand_update_bufferram(mtd, from, !ret);
+			if (ret == -EBADMSG)
+				ret = 0;
+		}
+
+		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
+		if (oobbuf) {
+			thisooblen = oobsize - oobcolumn;
+			thisooblen = min_t(int, thisooblen, ooblen - oobread);
+
+			if (ops->mode == MTD_OOB_AUTO)
+				onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
+			else
+				this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
+			oobread += thisooblen;
+			oobbuf += thisooblen;
+			oobcolumn = 0;
+		}
+
+		read += thislen;
+		if (read == len)
+			break;
+
+		from += thislen;
+		buf += thislen;
+	}
+
+	/*
+	 * Return success, if no ECC failures, else -EBADMSG
+	 * fs driver will take care of that, because
+	 * retlen == desired len and result == -EBADMSG
+	 */
+	ops->retlen = read;
+	ops->oobretlen = oobread;
+
+	if (ret)
+		return ret;
+
+	if (mtd->ecc_stats.failed - stats.failed)
+		return -EBADMSG;
+
+	return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+}
+
+/**
  * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band
  * @param mtd		MTD device structure
  * @param from		offset to read from
@@ -962,7 +1271,7 @@
 	size_t len = ops->ooblen;
 	mtd_oob_mode_t mode = ops->mode;
 	u_char *buf = ops->oobbuf;
-	int ret = 0;
+	int ret = 0, readcmd;
 
 	from += ops->ooboffs;
 
@@ -993,17 +1302,22 @@
 
 	stats = mtd->ecc_stats;
 
+	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+
 	while (read < len) {
 		cond_resched();
 
 		thislen = oobsize - column;
 		thislen = min_t(int, thislen, len);
 
-		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
+		this->command(mtd, readcmd, from, mtd->oobsize);
 
 		onenand_update_bufferram(mtd, from, 0);
 
 		ret = this->wait(mtd, FL_READING);
+		if (unlikely(ret))
+			ret = onenand_recover_lsb(mtd, from, ret);
+
 		if (ret && ret != -EBADMSG) {
 			printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
 			break;
@@ -1053,6 +1367,7 @@
 static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
 	size_t *retlen, u_char *buf)
 {
+	struct onenand_chip *this = mtd->priv;
 	struct mtd_oob_ops ops = {
 		.len	= len,
 		.ooblen	= 0,
@@ -1062,7 +1377,9 @@
 	int ret;
 
 	onenand_get_device(mtd, FL_READING);
-	ret = onenand_read_ops_nolock(mtd, from, &ops);
+	ret = ONENAND_IS_MLC(this) ?
+		onenand_mlc_read_ops_nolock(mtd, from, &ops) :
+		onenand_read_ops_nolock(mtd, from, &ops);
 	onenand_release_device(mtd);
 
 	*retlen = ops.retlen;
@@ -1080,6 +1397,7 @@
 static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
 			    struct mtd_oob_ops *ops)
 {
+	struct onenand_chip *this = mtd->priv;
 	int ret;
 
 	switch (ops->mode) {
@@ -1094,7 +1412,9 @@
 
 	onenand_get_device(mtd, FL_READING);
 	if (ops->datbuf)
-		ret = onenand_read_ops_nolock(mtd, from, ops);
+		ret = ONENAND_IS_MLC(this) ?
+			onenand_mlc_read_ops_nolock(mtd, from, ops) :
+			onenand_read_ops_nolock(mtd, from, ops);
 	else
 		ret = onenand_read_oob_nolock(mtd, from, ops);
 	onenand_release_device(mtd);
@@ -1128,11 +1448,11 @@
 	ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
 
 	if (interrupt & ONENAND_INT_READ) {
-		int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+		int ecc = onenand_read_ecc(this);
 		if (ecc & ONENAND_ECC_2BIT_ALL) {
 			printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
 				", controller error 0x%04x\n", ecc, ctrl);
-			return ONENAND_BBT_READ_ERROR;
+			return ONENAND_BBT_READ_ECC_ERROR;
 		}
 	} else {
 		printk(KERN_ERR "onenand_bbt_wait: read timeout!"
@@ -1163,7 +1483,7 @@
 {
 	struct onenand_chip *this = mtd->priv;
 	int read = 0, thislen, column;
-	int ret = 0;
+	int ret = 0, readcmd;
 	size_t len = ops->ooblen;
 	u_char *buf = ops->oobbuf;
 
@@ -1183,17 +1503,22 @@
 
 	column = from & (mtd->oobsize - 1);
 
+	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+
 	while (read < len) {
 		cond_resched();
 
 		thislen = mtd->oobsize - column;
 		thislen = min_t(int, thislen, len);
 
-		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
+		this->command(mtd, readcmd, from, mtd->oobsize);
 
 		onenand_update_bufferram(mtd, from, 0);
 
-		ret = onenand_bbt_wait(mtd, FL_READING);
+		ret = this->bbt_wait(mtd, FL_READING);
+		if (unlikely(ret))
+			ret = onenand_recover_lsb(mtd, from, ret);
+
 		if (ret)
 			break;
 
@@ -1230,9 +1555,11 @@
 {
 	struct onenand_chip *this = mtd->priv;
 	u_char *oob_buf = this->oob_buf;
-	int status, i;
+	int status, i, readcmd;
 
-	this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
+	readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
+
+	this->command(mtd, readcmd, to, mtd->oobsize);
 	onenand_update_bufferram(mtd, to, 0);
 	status = this->wait(mtd, FL_READING);
 	if (status)
@@ -1633,7 +1960,7 @@
 {
 	struct onenand_chip *this = mtd->priv;
 	int column, ret = 0, oobsize;
-	int written = 0;
+	int written = 0, oobcmd;
 	u_char *oobbuf;
 	size_t len = ops->ooblen;
 	const u_char *buf = ops->oobbuf;
@@ -1675,6 +2002,8 @@
 
 	oobbuf = this->oob_buf;
 
+	oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
+
 	/* Loop until all data write */
 	while (written < len) {
 		int thislen = min_t(int, oobsize, len - written);
@@ -1692,7 +2021,14 @@
 			memcpy(oobbuf + column, buf, thislen);
 		this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
 
-		this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
+		if (ONENAND_IS_MLC(this)) {
+			/* Set main area of DataRAM to 0xff*/
+			memset(this->page_buf, 0xff, mtd->writesize);
+			this->write_bufferram(mtd, ONENAND_DATARAM,
+					 this->page_buf, 0, mtd->writesize);
+		}
+
+		this->command(mtd, oobcmd, to, mtd->oobsize);
 
 		onenand_update_bufferram(mtd, to, 0);
 		if (ONENAND_IS_2PLANE(this)) {
@@ -1815,29 +2151,48 @@
 {
 	struct onenand_chip *this = mtd->priv;
 	unsigned int block_size;
-	loff_t addr;
-	int len;
-	int ret = 0;
+	loff_t addr = instr->addr;
+	loff_t len = instr->len;
+	int ret = 0, i;
+	struct mtd_erase_region_info *region = NULL;
+	loff_t region_end = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len);
 
-	block_size = (1 << this->erase_shift);
-
-	/* Start address must align on block boundary */
-	if (unlikely(instr->addr & (block_size - 1))) {
-		printk(KERN_ERR "onenand_erase: Unaligned address\n");
+	/* Do not allow erase past end of device */
+	if (unlikely((len + addr) > mtd->size)) {
+		printk(KERN_ERR "onenand_erase: Erase past end of device\n");
 		return -EINVAL;
 	}
 
-	/* Length must align on block boundary */
-	if (unlikely(instr->len & (block_size - 1))) {
-		printk(KERN_ERR "onenand_erase: Length not block aligned\n");
-		return -EINVAL;
+	if (FLEXONENAND(this)) {
+		/* Find the eraseregion of this address */
+		i = flexonenand_region(mtd, addr);
+		region = &mtd->eraseregions[i];
+
+		block_size = region->erasesize;
+		region_end = region->offset + region->erasesize * region->numblocks;
+
+		/* Start address within region must align on block boundary.
+		 * Erase region's start offset is always block start address.
+		 */
+		if (unlikely((addr - region->offset) & (block_size - 1))) {
+			printk(KERN_ERR "onenand_erase: Unaligned address\n");
+			return -EINVAL;
+		}
+	} else {
+		block_size = 1 << this->erase_shift;
+
+		/* Start address must align on block boundary */
+		if (unlikely(addr & (block_size - 1))) {
+			printk(KERN_ERR "onenand_erase: Unaligned address\n");
+			return -EINVAL;
+		}
 	}
 
-	/* Do not allow erase past end of device */
-	if (unlikely((instr->len + instr->addr) > mtd->size)) {
-		printk(KERN_ERR "onenand_erase: Erase past end of device\n");
+	/* Length must align on block boundary */
+	if (unlikely(len & (block_size - 1))) {
+		printk(KERN_ERR "onenand_erase: Length not block aligned\n");
 		return -EINVAL;
 	}
 
@@ -1847,9 +2202,6 @@
 	onenand_get_device(mtd, FL_ERASING);
 
 	/* Loop throught the pages */
-	len = instr->len;
-	addr = instr->addr;
-
 	instr->state = MTD_ERASING;
 
 	while (len) {
@@ -1869,7 +2221,8 @@
 		ret = this->wait(mtd, FL_ERASING);
 		/* Check, if it is write protected */
 		if (ret) {
-			printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));
+			printk(KERN_ERR "onenand_erase: Failed erase, block %d\n",
+						 onenand_block(this, addr));
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr = addr;
 			goto erase_exit;
@@ -1877,6 +2230,22 @@
 
 		len -= block_size;
 		addr += block_size;
+
+		if (addr == region_end) {
+			if (!len)
+				break;
+			region++;
+
+			block_size = region->erasesize;
+			region_end = region->offset + region->erasesize * region->numblocks;
+
+			if (len & (block_size - 1)) {
+				/* FIXME: This should be handled at MTD partitioning level. */
+				printk(KERN_ERR "onenand_erase: Unaligned address\n");
+				goto erase_exit;
+			}
+		}
+
 	}
 
 	instr->state = MTD_ERASE_DONE;
@@ -1955,13 +2324,17 @@
 	int block;
 
 	/* Get block number */
-	block = ((int) ofs) >> bbm->bbt_erase_shift;
+	block = onenand_block(this, ofs);
         if (bbm->bbt)
                 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
         /* We write two bytes, so we dont have to mess with 16 bit access */
         ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
-        return onenand_write_oob_nolock(mtd, ofs, &ops);
+	/* FIXME : What to do when marking SLC block in partition
+	 * 	   with MLC erasesize? For now, it is not advisable to
+	 *	   create partitions containing both SLC and MLC regions.
+	 */
+	return onenand_write_oob_nolock(mtd, ofs, &ops);
 }
 
 /**
@@ -2005,8 +2378,8 @@
 	int start, end, block, value, status;
 	int wp_status_mask;
 
-	start = ofs >> this->erase_shift;
-	end = len >> this->erase_shift;
+	start = onenand_block(this, ofs);
+	end = onenand_block(this, ofs + len) - 1;
 
 	if (cmd == ONENAND_CMD_LOCK)
 		wp_status_mask = ONENAND_WP_LS;
@@ -2018,7 +2391,7 @@
 		/* Set start block address */
 		this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
 		/* Set end block address */
-		this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS);
+		this->write_word(end, this->base +  ONENAND_REG_END_BLOCK_ADDRESS);
 		/* Write lock command */
 		this->command(mtd, cmd, 0, 0);
 
@@ -2039,7 +2412,7 @@
 	}
 
 	/* Block lock scheme */
-	for (block = start; block < start + end; block++) {
+	for (block = start; block < end + 1; block++) {
 		/* Set block address */
 		value = onenand_block_address(this, block);
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
@@ -2147,7 +2520,7 @@
 {
 	struct onenand_chip *this = mtd->priv;
 	loff_t ofs = 0;
-	size_t len = this->chipsize;
+	loff_t len = mtd->size;
 
 	if (this->options & ONENAND_HAS_UNLOCK_ALL) {
 		/* Set start block address */
@@ -2163,12 +2536,16 @@
 		    & ONENAND_CTRL_ONGO)
 			continue;
 
+		/* Don't check lock status */
+		if (this->options & ONENAND_SKIP_UNLOCK_CHECK)
+			return;
+
 		/* Check lock status */
 		if (onenand_check_lock_status(this))
 			return;
 
 		/* Workaround for all block unlock in DDP */
-		if (ONENAND_IS_DDP(this)) {
+		if (ONENAND_IS_DDP(this) && !FLEXONENAND(this)) {
 			/* All blocks on another chip */
 			ofs = this->chipsize >> 1;
 			len = this->chipsize >> 1;
@@ -2210,7 +2587,9 @@
 	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
 	this->wait(mtd, FL_OTPING);
 
-	ret = onenand_read_ops_nolock(mtd, from, &ops);
+	ret = ONENAND_IS_MLC(this) ?
+		onenand_mlc_read_ops_nolock(mtd, from, &ops) :
+		onenand_read_ops_nolock(mtd, from, &ops);
 
 	/* Exit OTP access mode */
 	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -2277,21 +2656,32 @@
 		size_t *retlen, u_char *buf)
 {
 	struct onenand_chip *this = mtd->priv;
-	struct mtd_oob_ops ops = {
-		.mode = MTD_OOB_PLACE,
-		.ooblen = len,
-		.oobbuf = buf,
-		.ooboffs = 0,
-	};
+	struct mtd_oob_ops ops;
 	int ret;
 
 	/* Enter OTP access mode */
 	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
 	this->wait(mtd, FL_OTPING);
 
-	ret = onenand_write_oob_nolock(mtd, from, &ops);
-
-	*retlen = ops.oobretlen;
+	if (FLEXONENAND(this)) {
+		/*
+		 * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of
+		 * main area of page 49.
+		 */
+		ops.len = mtd->writesize;
+		ops.ooblen = 0;
+		ops.datbuf = buf;
+		ops.oobbuf = NULL;
+		ret = onenand_write_ops_nolock(mtd, mtd->writesize * 49, &ops);
+		*retlen = ops.retlen;
+	} else {
+		ops.mode = MTD_OOB_PLACE;
+		ops.ooblen = len;
+		ops.oobbuf = buf;
+		ops.ooboffs = 0;
+		ret = onenand_write_oob_nolock(mtd, from, &ops);
+		*retlen = ops.oobretlen;
+	}
 
 	/* Exit OTP access mode */
 	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
@@ -2475,27 +2865,34 @@
 			size_t len)
 {
 	struct onenand_chip *this = mtd->priv;
-	u_char *oob_buf = this->oob_buf;
+	u_char *buf = FLEXONENAND(this) ? this->page_buf : this->oob_buf;
 	size_t retlen;
 	int ret;
 
-	memset(oob_buf, 0xff, mtd->oobsize);
+	memset(buf, 0xff, FLEXONENAND(this) ? this->writesize
+						 : mtd->oobsize);
 	/*
 	 * Note: OTP lock operation
 	 *       OTP block : 0xXXFC
 	 *       1st block : 0xXXF3 (If chip support)
 	 *       Both      : 0xXXF0 (If chip support)
 	 */
-	oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
+	if (FLEXONENAND(this))
+		buf[FLEXONENAND_OTP_LOCK_OFFSET] = 0xFC;
+	else
+		buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
 
 	/*
 	 * Write lock mark to 8th word of sector0 of page0 of the spare0.
 	 * We write 16 bytes spare area instead of 2 bytes.
+	 * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of
+	 * main area of page 49.
 	 */
+
 	from = 0;
-	len = 16;
+	len = FLEXONENAND(this) ? mtd->writesize : 16;
 
-	ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER);
+	ret = onenand_otp_walk(mtd, from, len, &retlen, buf, do_otp_lock, MTD_OTP_USER);
 
 	return ret ? : retlen;
 }
@@ -2542,6 +2939,14 @@
 		break;
 	}
 
+	if (ONENAND_IS_MLC(this))
+		this->options &= ~ONENAND_HAS_2PLANE;
+
+	if (FLEXONENAND(this)) {
+		this->options &= ~ONENAND_HAS_CONT_LOCK;
+		this->options |= ONENAND_HAS_UNLOCK_ALL;
+	}
+
 	if (this->options & ONENAND_HAS_CONT_LOCK)
 		printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
 	if (this->options & ONENAND_HAS_UNLOCK_ALL)
@@ -2559,14 +2964,16 @@
  */
 static void onenand_print_device_info(int device, int version)
 {
-        int vcc, demuxed, ddp, density;
+	int vcc, demuxed, ddp, density, flexonenand;
 
         vcc = device & ONENAND_DEVICE_VCC_MASK;
         demuxed = device & ONENAND_DEVICE_IS_DEMUX;
         ddp = device & ONENAND_DEVICE_IS_DDP;
         density = onenand_get_density(device);
-        printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
-                demuxed ? "" : "Muxed ",
+	flexonenand = device & DEVICE_IS_FLEXONENAND;
+	printk(KERN_INFO "%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
+		demuxed ? "" : "Muxed ",
+		flexonenand ? "Flex-" : "",
                 ddp ? "(DDP)" : "",
                 (16 << density),
                 vcc ? "2.65/3.3" : "1.8",
@@ -2576,6 +2983,7 @@
 
 static const struct onenand_manufacturers onenand_manuf_ids[] = {
         {ONENAND_MFR_SAMSUNG, "Samsung"},
+	{ONENAND_MFR_NUMONYX, "Numonyx"},
 };
 
 /**
@@ -2605,6 +3013,261 @@
 }
 
 /**
+* flexonenand_get_boundary	- Reads the SLC boundary
+* @param onenand_info		- onenand info structure
+**/
+static int flexonenand_get_boundary(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned die, bdry;
+	int ret, syscfg, locked;
+
+	/* Disable ECC */
+	syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
+	this->write_word((syscfg | 0x0100), this->base + ONENAND_REG_SYS_CFG1);
+
+	for (die = 0; die < this->dies; die++) {
+		this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
+		this->wait(mtd, FL_SYNCING);
+
+		this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
+		ret = this->wait(mtd, FL_READING);
+
+		bdry = this->read_word(this->base + ONENAND_DATARAM);
+		if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
+			locked = 0;
+		else
+			locked = 1;
+		this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
+
+		this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+		ret = this->wait(mtd, FL_RESETING);
+
+		printk(KERN_INFO "Die %d boundary: %d%s\n", die,
+		       this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
+	}
+
+	/* Enable ECC */
+	this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
+	return 0;
+}
+
+/**
+ * flexonenand_get_size - Fill up fields in onenand_chip and mtd_info
+ * 			  boundary[], diesize[], mtd->size, mtd->erasesize
+ * @param mtd		- MTD device structure
+ */
+static void flexonenand_get_size(struct mtd_info *mtd)
+{
+	struct onenand_chip *this = mtd->priv;
+	int die, i, eraseshift, density;
+	int blksperdie, maxbdry;
+	loff_t ofs;
+
+	density = onenand_get_density(this->device_id);
+	blksperdie = ((loff_t)(16 << density) << 20) >> (this->erase_shift);
+	blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
+	maxbdry = blksperdie - 1;
+	eraseshift = this->erase_shift - 1;
+
+	mtd->numeraseregions = this->dies << 1;
+
+	/* This fills up the device boundary */
+	flexonenand_get_boundary(mtd);
+	die = ofs = 0;
+	i = -1;
+	for (; die < this->dies; die++) {
+		if (!die || this->boundary[die-1] != maxbdry) {
+			i++;
+			mtd->eraseregions[i].offset = ofs;
+			mtd->eraseregions[i].erasesize = 1 << eraseshift;
+			mtd->eraseregions[i].numblocks =
+							this->boundary[die] + 1;
+			ofs += mtd->eraseregions[i].numblocks << eraseshift;
+			eraseshift++;
+		} else {
+			mtd->numeraseregions -= 1;
+			mtd->eraseregions[i].numblocks +=
+							this->boundary[die] + 1;
+			ofs += (this->boundary[die] + 1) << (eraseshift - 1);
+		}
+		if (this->boundary[die] != maxbdry) {
+			i++;
+			mtd->eraseregions[i].offset = ofs;
+			mtd->eraseregions[i].erasesize = 1 << eraseshift;
+			mtd->eraseregions[i].numblocks = maxbdry ^
+							 this->boundary[die];
+			ofs += mtd->eraseregions[i].numblocks << eraseshift;
+			eraseshift--;
+		} else
+			mtd->numeraseregions -= 1;
+	}
+
+	/* Expose MLC erase size except when all blocks are SLC */
+	mtd->erasesize = 1 << this->erase_shift;
+	if (mtd->numeraseregions == 1)
+		mtd->erasesize >>= 1;
+
+	printk(KERN_INFO "Device has %d eraseregions\n", mtd->numeraseregions);
+	for (i = 0; i < mtd->numeraseregions; i++)
+		printk(KERN_INFO "[offset: 0x%08x, erasesize: 0x%05x,"
+			" numblocks: %04u]\n",
+			(unsigned int) mtd->eraseregions[i].offset,
+			mtd->eraseregions[i].erasesize,
+			mtd->eraseregions[i].numblocks);
+
+	for (die = 0, mtd->size = 0; die < this->dies; die++) {
+		this->diesize[die] = (loff_t)blksperdie << this->erase_shift;
+		this->diesize[die] -= (loff_t)(this->boundary[die] + 1)
+						 << (this->erase_shift - 1);
+		mtd->size += this->diesize[die];
+	}
+}
+
+/**
+ * flexonenand_check_blocks_erased - Check if blocks are erased
+ * @param mtd_info	- mtd info structure
+ * @param start		- first erase block to check
+ * @param end		- last erase block to check
+ *
+ * Converting an unerased block from MLC to SLC
+ * causes byte values to change. Since both data and its ECC
+ * have changed, reads on the block give uncorrectable error.
+ * This might lead to the block being detected as bad.
+ *
+ * Avoid this by ensuring that the block to be converted is
+ * erased.
+ */
+static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int end)
+{
+	struct onenand_chip *this = mtd->priv;
+	int i, ret;
+	int block;
+	struct mtd_oob_ops ops = {
+		.mode = MTD_OOB_PLACE,
+		.ooboffs = 0,
+		.ooblen	= mtd->oobsize,
+		.datbuf	= NULL,
+		.oobbuf	= this->oob_buf,
+	};
+	loff_t addr;
+
+	printk(KERN_DEBUG "Check blocks from %d to %d\n", start, end);
+
+	for (block = start; block <= end; block++) {
+		addr = flexonenand_addr(this, block);
+		if (onenand_block_isbad_nolock(mtd, addr, 0))
+			continue;
+
+		/*
+		 * Since main area write results in ECC write to spare,
+		 * it is sufficient to check only ECC bytes for change.
+		 */
+		ret = onenand_read_oob_nolock(mtd, addr, &ops);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < mtd->oobsize; i++)
+			if (this->oob_buf[i] != 0xff)
+				break;
+
+		if (i != mtd->oobsize) {
+			printk(KERN_WARNING "Block %d not erased.\n", block);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * flexonenand_set_boundary	- Writes the SLC boundary
+ * @param mtd			- mtd info structure
+ */
+int flexonenand_set_boundary(struct mtd_info *mtd, int die,
+				    int boundary, int lock)
+{
+	struct onenand_chip *this = mtd->priv;
+	int ret, density, blksperdie, old, new, thisboundary;
+	loff_t addr;
+
+	/* Change only once for SDP Flex-OneNAND */
+	if (die && (!ONENAND_IS_DDP(this)))
+		return 0;
+
+	/* boundary value of -1 indicates no required change */
+	if (boundary < 0 || boundary == this->boundary[die])
+		return 0;
+
+	density = onenand_get_density(this->device_id);
+	blksperdie = ((16 << density) << 20) >> this->erase_shift;
+	blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
+
+	if (boundary >= blksperdie) {
+		printk(KERN_ERR "flexonenand_set_boundary: Invalid boundary value. "
+				"Boundary not changed.\n");
+		return -EINVAL;
+	}
+
+	/* Check if converting blocks are erased */
+	old = this->boundary[die] + (die * this->density_mask);
+	new = boundary + (die * this->density_mask);
+	ret = flexonenand_check_blocks_erased(mtd, min(old, new) + 1, max(old, new));
+	if (ret) {
+		printk(KERN_ERR "flexonenand_set_boundary: Please erase blocks before boundary change\n");
+		return ret;
+	}
+
+	this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
+	this->wait(mtd, FL_SYNCING);
+
+	/* Check is boundary is locked */
+	this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
+	ret = this->wait(mtd, FL_READING);
+
+	thisboundary = this->read_word(this->base + ONENAND_DATARAM);
+	if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
+		printk(KERN_ERR "flexonenand_set_boundary: boundary locked\n");
+		ret = 1;
+		goto out;
+	}
+
+	printk(KERN_INFO "flexonenand_set_boundary: Changing die %d boundary: %d%s\n",
+			die, boundary, lock ? "(Locked)" : "(Unlocked)");
+
+	addr = die ? this->diesize[0] : 0;
+
+	boundary &= FLEXONENAND_PI_MASK;
+	boundary |= lock ? 0 : (3 << FLEXONENAND_PI_UNLOCK_SHIFT);
+
+	this->command(mtd, ONENAND_CMD_ERASE, addr, 0);
+	ret = this->wait(mtd, FL_ERASING);
+	if (ret) {
+		printk(KERN_ERR "flexonenand_set_boundary: Failed PI erase for Die %d\n", die);
+		goto out;
+	}
+
+	this->write_word(boundary, this->base + ONENAND_DATARAM);
+	this->command(mtd, ONENAND_CMD_PROG, addr, 0);
+	ret = this->wait(mtd, FL_WRITING);
+	if (ret) {
+		printk(KERN_ERR "flexonenand_set_boundary: Failed PI write for Die %d\n", die);
+		goto out;
+	}
+
+	this->command(mtd, FLEXONENAND_CMD_PI_UPDATE, die, 0);
+	ret = this->wait(mtd, FL_WRITING);
+out:
+	this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND);
+	this->wait(mtd, FL_RESETING);
+	if (!ret)
+		/* Recalculate device size on boundary change*/
+		flexonenand_get_size(mtd);
+
+	return ret;
+}
+
+/**
  * onenand_probe - [OneNAND Interface] Probe the OneNAND device
  * @param mtd		MTD device structure
  *
@@ -2621,7 +3284,7 @@
 	/* Save system configuration 1 */
 	syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
 	/* Clear Sync. Burst Read mode to read BootRAM */
-	this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ), this->base + ONENAND_REG_SYS_CFG1);
+	this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE), this->base + ONENAND_REG_SYS_CFG1);
 
 	/* Send the command for reading device ID from BootRAM */
 	this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);
@@ -2646,6 +3309,7 @@
 	maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
 	dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
 	ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
+	this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
 
 	/* Check OneNAND device */
 	if (maf_id != bram_maf_id || dev_id != bram_dev_id)
@@ -2657,29 +3321,55 @@
 	this->version_id = ver_id;
 
 	density = onenand_get_density(dev_id);
+	if (FLEXONENAND(this)) {
+		this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
+		/* Maximum possible erase regions */
+		mtd->numeraseregions = this->dies << 1;
+		mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info)
+					* (this->dies << 1), GFP_KERNEL);
+		if (!mtd->eraseregions)
+			return -ENOMEM;
+	}
+
+	/*
+	 * For Flex-OneNAND, chipsize represents maximum possible device size.
+	 * mtd->size represents the actual device size.
+	 */
 	this->chipsize = (16 << density) << 20;
-	/* Set density mask. it is used for DDP */
-	if (ONENAND_IS_DDP(this))
-		this->density_mask = (1 << (density + 6));
-	else
-		this->density_mask = 0;
 
 	/* OneNAND page size & block size */
 	/* The data buffer size is equal to page size */
 	mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
+	/* We use the full BufferRAM */
+	if (ONENAND_IS_MLC(this))
+		mtd->writesize <<= 1;
+
 	mtd->oobsize = mtd->writesize >> 5;
 	/* Pages per a block are always 64 in OneNAND */
 	mtd->erasesize = mtd->writesize << 6;
+	/*
+	 * Flex-OneNAND SLC area has 64 pages per block.
+	 * Flex-OneNAND MLC area has 128 pages per block.
+	 * Expose MLC erase size to find erase_shift and page_mask.
+	 */
+	if (FLEXONENAND(this))
+		mtd->erasesize <<= 1;
 
 	this->erase_shift = ffs(mtd->erasesize) - 1;
 	this->page_shift = ffs(mtd->writesize) - 1;
 	this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
+	/* Set density mask. it is used for DDP */
+	if (ONENAND_IS_DDP(this))
+		this->density_mask = this->chipsize >> (this->erase_shift + 1);
 	/* It's real page size */
 	this->writesize = mtd->writesize;
 
 	/* REVIST: Multichip handling */
 
-	mtd->size = this->chipsize;
+	if (FLEXONENAND(this))
+		flexonenand_get_size(mtd);
+	else
+		mtd->size = this->chipsize;
 
 	/* Check OneNAND features */
 	onenand_check_features(mtd);
@@ -2734,7 +3424,7 @@
  */
 int onenand_scan(struct mtd_info *mtd, int maxchips)
 {
-	int i;
+	int i, ret;
 	struct onenand_chip *this = mtd->priv;
 
 	if (!this->read_word)
@@ -2746,6 +3436,10 @@
 		this->command = onenand_command;
 	if (!this->wait)
 		onenand_setup_wait(mtd);
+	if (!this->bbt_wait)
+		this->bbt_wait = onenand_bbt_wait;
+	if (!this->unlock_all)
+		this->unlock_all = onenand_unlock_all;
 
 	if (!this->read_bufferram)
 		this->read_bufferram = onenand_read_bufferram;
@@ -2796,6 +3490,10 @@
 	 * Allow subpage writes up to oobsize.
 	 */
 	switch (mtd->oobsize) {
+	case 128:
+		this->ecclayout = &onenand_oob_128;
+		mtd->subpage_sft = 0;
+		break;
 	case 64:
 		this->ecclayout = &onenand_oob_64;
 		mtd->subpage_sft = 2;
@@ -2859,9 +3557,18 @@
 	mtd->owner = THIS_MODULE;
 
 	/* Unlock whole block */
-	onenand_unlock_all(mtd);
+	this->unlock_all(mtd);
 
-	return this->scan_bbt(mtd);
+	ret = this->scan_bbt(mtd);
+	if ((!FLEXONENAND(this)) || ret)
+		return ret;
+
+	/* Change Flex-OneNAND boundaries if required */
+	for (i = 0; i < MAX_DIES; i++)
+		flexonenand_set_boundary(mtd, i, flex_bdry[2 * i],
+						 flex_bdry[(2 * i) + 1]);
+
+	return 0;
 }
 
 /**
@@ -2890,6 +3597,7 @@
 		kfree(this->page_buf);
 	if (this->options & ONENAND_OOBBUF_ALLOC)
 		kfree(this->oob_buf);
+	kfree(mtd->eraseregions);
 }
 
 EXPORT_SYMBOL_GPL(onenand_scan);
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/onenand/onenand_bbt.c linux-libre-2.6.31-gnu/drivers/mtd/onenand/onenand_bbt.c
--- linux-libre-2.6.30-gnu/drivers/mtd/onenand/onenand_bbt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/onenand/onenand_bbt.c	2009-09-09 18:13:59.000000000 -0400
@@ -63,6 +63,7 @@
 	loff_t from;
 	size_t readlen, ooblen;
 	struct mtd_oob_ops ops;
+	int rgn;
 
 	printk(KERN_INFO "Scanning device for bad blocks\n");
 
@@ -76,7 +77,7 @@
 	/* Note that numblocks is 2 * (real numblocks) here;
 	 * see i += 2 below as it makses shifting and masking less painful
 	 */
-	numblocks = mtd->size >> (bbm->bbt_erase_shift - 1);
+	numblocks = this->chipsize >> (bbm->bbt_erase_shift - 1);
 	startblock = 0;
 	from = 0;
 
@@ -106,7 +107,12 @@
 			}
 		}
 		i += 2;
-		from += (1 << bbm->bbt_erase_shift);
+
+		if (FLEXONENAND(this)) {
+			rgn = flexonenand_region(mtd, from);
+			from += mtd->eraseregions[rgn].erasesize;
+		} else
+			from += (1 << bbm->bbt_erase_shift);
 	}
 
 	return 0;
@@ -143,7 +149,7 @@
 	uint8_t res;
 
 	/* Get block number * 2 */
-	block = (int) (offs >> (bbm->bbt_erase_shift - 1));
+	block = (int) (onenand_block(this, offs) << 1);
 	res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
 	DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
@@ -178,7 +184,7 @@
 	struct bbm_info *bbm = this->bbm;
 	int len, ret = 0;
 
-	len = mtd->size >> (this->erase_shift + 2);
+	len = this->chipsize >> (this->erase_shift + 2);
 	/* Allocate memory (2bit per block) and clear the memory bad block table */
 	bbm->bbt = kzalloc(len, GFP_KERNEL);
 	if (!bbm->bbt) {
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/onenand/onenand_sim.c linux-libre-2.6.31-gnu/drivers/mtd/onenand/onenand_sim.c
--- linux-libre-2.6.30-gnu/drivers/mtd/onenand/onenand_sim.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/onenand/onenand_sim.c	2009-09-09 18:13:59.000000000 -0400
@@ -6,6 +6,10 @@
  *  Copyright © 2005-2007 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
+ *  Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com>
+ *  Flex-OneNAND simulator support
+ *  Copyright (C) Samsung Electronics, 2008
+ *
  * 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.
@@ -24,16 +28,38 @@
 #ifndef CONFIG_ONENAND_SIM_MANUFACTURER
 #define CONFIG_ONENAND_SIM_MANUFACTURER         0xec
 #endif
+
 #ifndef CONFIG_ONENAND_SIM_DEVICE_ID
 #define CONFIG_ONENAND_SIM_DEVICE_ID            0x04
 #endif
+
+#define CONFIG_FLEXONENAND ((CONFIG_ONENAND_SIM_DEVICE_ID >> 9) & 1)
+
 #ifndef CONFIG_ONENAND_SIM_VERSION_ID
 #define CONFIG_ONENAND_SIM_VERSION_ID           0x1e
 #endif
 
+#ifndef CONFIG_ONENAND_SIM_TECHNOLOGY_ID
+#define CONFIG_ONENAND_SIM_TECHNOLOGY_ID CONFIG_FLEXONENAND
+#endif
+
+/* Initial boundary values for Flex-OneNAND Simulator */
+#ifndef CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY
+#define CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY	0x01
+#endif
+
+#ifndef CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY
+#define CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY	0x01
+#endif
+
 static int manuf_id	= CONFIG_ONENAND_SIM_MANUFACTURER;
 static int device_id	= CONFIG_ONENAND_SIM_DEVICE_ID;
 static int version_id	= CONFIG_ONENAND_SIM_VERSION_ID;
+static int technology_id = CONFIG_ONENAND_SIM_TECHNOLOGY_ID;
+static int boundary[] = {
+	CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY,
+	CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY,
+};
 
 struct onenand_flash {
 	void __iomem *base;
@@ -57,12 +83,18 @@
 	(writew(v, this->base + ONENAND_REG_WP_STATUS))
 
 /* It has all 0xff chars */
-#define MAX_ONENAND_PAGESIZE		(2048 + 64)
+#define MAX_ONENAND_PAGESIZE		(4096 + 128)
 static unsigned char *ffchars;
 
+#if CONFIG_FLEXONENAND
+#define PARTITION_NAME "Flex-OneNAND simulator partition"
+#else
+#define PARTITION_NAME "OneNAND simulator partition"
+#endif
+
 static struct mtd_partition os_partitions[] = {
 	{
-		.name		= "OneNAND simulator partition",
+		.name		= PARTITION_NAME,
 		.offset		= 0,
 		.size		= MTDPART_SIZ_FULL,
 	},
@@ -104,6 +136,7 @@
 
 	switch (cmd) {
 	case ONENAND_CMD_UNLOCK:
+	case ONENAND_CMD_UNLOCK_ALL:
 		if (block_lock_scheme)
 			ONENAND_SET_WP_STATUS(ONENAND_WP_US, this);
 		else
@@ -228,10 +261,12 @@
 {
 	struct mtd_info *mtd = &info->mtd;
 	struct onenand_flash *flash = this->priv;
-	int main_offset, spare_offset;
+	int main_offset, spare_offset, die = 0;
 	void __iomem *src;
 	void __iomem *dest;
 	unsigned int i;
+	static int pi_operation;
+	int erasesize, rgn;
 
 	if (dataram) {
 		main_offset = mtd->writesize;
@@ -241,10 +276,27 @@
 		spare_offset = 0;
 	}
 
+	if (pi_operation) {
+		die = readw(this->base + ONENAND_REG_START_ADDRESS2);
+		die >>= ONENAND_DDP_SHIFT;
+	}
+
 	switch (cmd) {
+	case FLEXONENAND_CMD_PI_ACCESS:
+		pi_operation = 1;
+		break;
+
+	case ONENAND_CMD_RESET:
+		pi_operation = 0;
+		break;
+
 	case ONENAND_CMD_READ:
 		src = ONENAND_CORE(flash) + offset;
 		dest = ONENAND_MAIN_AREA(this, main_offset);
+		if (pi_operation) {
+			writew(boundary[die], this->base + ONENAND_DATARAM);
+			break;
+		}
 		memcpy(dest, src, mtd->writesize);
 		/* Fall through */
 
@@ -257,6 +309,10 @@
 	case ONENAND_CMD_PROG:
 		src = ONENAND_MAIN_AREA(this, main_offset);
 		dest = ONENAND_CORE(flash) + offset;
+		if (pi_operation) {
+			boundary[die] = readw(this->base + ONENAND_DATARAM);
+			break;
+		}
 		/* To handle partial write */
 		for (i = 0; i < (1 << mtd->subpage_sft); i++) {
 			int off = i * this->subpagesize;
@@ -284,9 +340,18 @@
 		break;
 
 	case ONENAND_CMD_ERASE:
-		memset(ONENAND_CORE(flash) + offset, 0xff, mtd->erasesize);
+		if (pi_operation)
+			break;
+
+		if (FLEXONENAND(this)) {
+			rgn = flexonenand_region(mtd, offset);
+			erasesize = mtd->eraseregions[rgn].erasesize;
+		} else
+			erasesize = mtd->erasesize;
+
+		memset(ONENAND_CORE(flash) + offset, 0xff, erasesize);
 		memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff,
-		       (mtd->erasesize >> 5));
+		       (erasesize >> 5));
 		break;
 
 	default:
@@ -339,7 +404,7 @@
 	}
 
 	if (block != -1)
-		offset += block << this->erase_shift;
+		offset = onenand_addr(this, block);
 
 	if (page != -1)
 		offset += page << this->page_shift;
@@ -390,6 +455,7 @@
 	}
 
 	density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+	density &= ONENAND_DEVICE_DENSITY_MASK;
 	size = ((16 << 20) << density);
 
 	ONENAND_CORE(flash) = vmalloc(size + (size >> 5));
@@ -405,8 +471,9 @@
 	writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID);
 	writew(device_id, flash->base + ONENAND_REG_DEVICE_ID);
 	writew(version_id, flash->base + ONENAND_REG_VERSION_ID);
+	writew(technology_id, flash->base + ONENAND_REG_TECHNOLOGY);
 
-	if (density < 2)
+	if (density < 2 && (!CONFIG_FLEXONENAND))
 		buffer_size = 0x0400;	/* 1KiB page */
 	else
 		buffer_size = 0x0800;	/* 2KiB page */
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/build.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/build.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/build.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/build.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/miscdevice.h>
 #include <linux/log2.h>
 #include <linux/kthread.h>
+#include <linux/reboot.h>
 #include "ubi.h"
 
 /* Maximum length of the 'mtd=' parameter */
@@ -122,6 +123,94 @@
 	__ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL);
 
 /**
+ * ubi_volume_notify - send a volume change notification.
+ * @ubi: UBI device description object
+ * @vol: volume description object of the changed volume
+ * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
+ *
+ * This is a helper function which notifies all subscribers about a volume
+ * change event (creation, removal, re-sizing, re-naming, updating). Returns
+ * zero in case of success and a negative error code in case of failure.
+ */
+int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype)
+{
+	struct ubi_notification nt;
+
+	ubi_do_get_device_info(ubi, &nt.di);
+	ubi_do_get_volume_info(ubi, vol, &nt.vi);
+	return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt);
+}
+
+/**
+ * ubi_notify_all - send a notification to all volumes.
+ * @ubi: UBI device description object
+ * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
+ * @nb: the notifier to call
+ *
+ * This function walks all volumes of UBI device @ubi and sends the @ntype
+ * notification for each volume. If @nb is %NULL, then all registered notifiers
+ * are called, otherwise only the @nb notifier is called. Returns the number of
+ * sent notifications.
+ */
+int ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb)
+{
+	struct ubi_notification nt;
+	int i, count = 0;
+
+	ubi_do_get_device_info(ubi, &nt.di);
+
+	mutex_lock(&ubi->device_mutex);
+	for (i = 0; i < ubi->vtbl_slots; i++) {
+		/*
+		 * Since the @ubi->device is locked, and we are not going to
+		 * change @ubi->volumes, we do not have to lock
+		 * @ubi->volumes_lock.
+		 */
+		if (!ubi->volumes[i])
+			continue;
+
+		ubi_do_get_volume_info(ubi, ubi->volumes[i], &nt.vi);
+		if (nb)
+			nb->notifier_call(nb, ntype, &nt);
+		else
+			blocking_notifier_call_chain(&ubi_notifiers, ntype,
+						     &nt);
+		count += 1;
+	}
+	mutex_unlock(&ubi->device_mutex);
+
+	return count;
+}
+
+/**
+ * ubi_enumerate_volumes - send "add" notification for all existing volumes.
+ * @nb: the notifier to call
+ *
+ * This function walks all UBI devices and volumes and sends the
+ * %UBI_VOLUME_ADDED notification for each volume. If @nb is %NULL, then all
+ * registered notifiers are called, otherwise only the @nb notifier is called.
+ * Returns the number of sent notifications.
+ */
+int ubi_enumerate_volumes(struct notifier_block *nb)
+{
+	int i, count = 0;
+
+	/*
+	 * Since the @ubi_devices_mutex is locked, and we are not going to
+	 * change @ubi_devices, we do not have to lock @ubi_devices_lock.
+	 */
+	for (i = 0; i < UBI_MAX_DEVICES; i++) {
+		struct ubi_device *ubi = ubi_devices[i];
+
+		if (!ubi)
+			continue;
+		count += ubi_notify_all(ubi, UBI_VOLUME_ADDED, nb);
+	}
+
+	return count;
+}
+
+/**
  * ubi_get_device - get UBI device.
  * @ubi_num: UBI device number
  *
@@ -380,7 +469,7 @@
  * @ubi: UBI device description object
  *
  * This function returns zero in case of success and a negative error code in
- * case of failure. Note, this function destroys all volumes if it failes.
+ * case of failure. Note, this function destroys all volumes if it fails.
  */
 static int uif_init(struct ubi_device *ubi)
 {
@@ -568,6 +657,11 @@
 	if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
 		ubi->bad_allowed = 1;
 
+	if (ubi->mtd->type == MTD_NORFLASH) {
+		ubi_assert(ubi->mtd->writesize == 1);
+		ubi->nor_flash = 1;
+	}
+
 	ubi->min_io_size = ubi->mtd->writesize;
 	ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
 
@@ -633,6 +727,15 @@
 	}
 
 	/*
+	 * Set maximum amount of physical erroneous eraseblocks to be 10%.
+	 * Erroneous PEB are those which have read errors.
+	 */
+	ubi->max_erroneous = ubi->peb_count / 10;
+	if (ubi->max_erroneous < 16)
+		ubi->max_erroneous = 16;
+	dbg_msg("max_erroneous    %d", ubi->max_erroneous);
+
+	/*
 	 * It may happen that EC and VID headers are situated in one minimal
 	 * I/O unit. In this case we can only accept this UBI image in
 	 * read-only mode.
@@ -726,6 +829,34 @@
 }
 
 /**
+ * ubi_reboot_notifier - halt UBI transactions immediately prior to a reboot.
+ * @n: reboot notifier object
+ * @state: SYS_RESTART, SYS_HALT, or SYS_POWER_OFF
+ * @cmd: pointer to command string for RESTART2
+ *
+ * This function stops the UBI background thread so that the flash device
+ * remains quiescent when Linux restarts the system. Any queued work will be
+ * discarded, but this function will block until do_work() finishes if an
+ * operation is already in progress.
+ *
+ * This function solves a real-life problem observed on NOR flashes when an
+ * PEB erase operation starts, then the system is rebooted before the erase is
+ * finishes, and the boot loader gets confused and dies. So we prefer to finish
+ * the ongoing operation before rebooting.
+ */
+static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state,
+			       void *cmd)
+{
+	struct ubi_device *ubi;
+
+	ubi = container_of(n, struct ubi_device, reboot_notifier);
+	if (ubi->bgt_thread)
+		kthread_stop(ubi->bgt_thread);
+	ubi_sync(ubi->ubi_num);
+	return NOTIFY_DONE;
+}
+
+/**
  * ubi_attach_mtd_dev - attach an MTD device.
  * @mtd: MTD device description object
  * @ubi_num: number to assign to the new UBI device
@@ -806,8 +937,7 @@
 
 	mutex_init(&ubi->buf_mutex);
 	mutex_init(&ubi->ckvol_mutex);
-	mutex_init(&ubi->mult_mutex);
-	mutex_init(&ubi->volumes_mutex);
+	mutex_init(&ubi->device_mutex);
 	spin_lock_init(&ubi->volumes_lock);
 
 	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
@@ -825,7 +955,7 @@
 	if (!ubi->peb_buf2)
 		goto out_free;
 
-#ifdef CONFIG_MTD_UBI_DEBUG
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 	mutex_init(&ubi->dbg_buf_mutex);
 	ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
 	if (!ubi->dbg_peb_buf)
@@ -871,12 +1001,25 @@
 	ubi_msg("number of PEBs reserved for bad PEB handling: %d",
 		ubi->beb_rsvd_pebs);
 	ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
+	ubi_msg("image sequence number: %d", ubi->image_seq);
 
+	/*
+	 * The below lock makes sure we do not race with 'ubi_thread()' which
+	 * checks @ubi->thread_enabled. Otherwise we may fail to wake it up.
+	 */
+	spin_lock(&ubi->wl_lock);
 	if (!DBG_DISABLE_BGT)
 		ubi->thread_enabled = 1;
 	wake_up_process(ubi->bgt_thread);
+	spin_unlock(&ubi->wl_lock);
+
+	/* Flash device priority is 0 - UBI needs to shut down first */
+	ubi->reboot_notifier.priority = 1;
+	ubi->reboot_notifier.notifier_call = ubi_reboot_notifier;
+	register_reboot_notifier(&ubi->reboot_notifier);
 
 	ubi_devices[ubi_num] = ubi;
+	ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
 	return ubi_num;
 
 out_uif:
@@ -892,7 +1035,7 @@
 out_free:
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
-#ifdef CONFIG_MTD_UBI_DEBUG
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 	vfree(ubi->dbg_peb_buf);
 #endif
 	kfree(ubi);
@@ -919,13 +1062,13 @@
 	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
 		return -EINVAL;
 
-	spin_lock(&ubi_devices_lock);
-	ubi = ubi_devices[ubi_num];
-	if (!ubi) {
-		spin_unlock(&ubi_devices_lock);
+	ubi = ubi_get_device(ubi_num);
+	if (!ubi)
 		return -EINVAL;
-	}
 
+	spin_lock(&ubi_devices_lock);
+	put_device(&ubi->dev);
+	ubi->ref_count -= 1;
 	if (ubi->ref_count) {
 		if (!anyway) {
 			spin_unlock(&ubi_devices_lock);
@@ -939,12 +1082,14 @@
 	spin_unlock(&ubi_devices_lock);
 
 	ubi_assert(ubi_num == ubi->ubi_num);
+	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
 	dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
 
 	/*
 	 * Before freeing anything, we have to stop the background thread to
 	 * prevent it from doing anything on this device while we are freeing.
 	 */
+	unregister_reboot_notifier(&ubi->reboot_notifier);
 	if (ubi->bgt_thread)
 		kthread_stop(ubi->bgt_thread);
 
@@ -961,7 +1106,7 @@
 	put_mtd_device(ubi->mtd);
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
-#ifdef CONFIG_MTD_UBI_DEBUG
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 	vfree(ubi->dbg_peb_buf);
 #endif
 	ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/cdev.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/cdev.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/cdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/cdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -113,7 +113,8 @@
 	else
 		mode = UBI_READONLY;
 
-	dbg_gen("open volume %d, mode %d", vol_id, mode);
+	dbg_gen("open device %d, volume %d, mode %d",
+	        ubi_num, vol_id, mode);
 
 	desc = ubi_open_volume(ubi_num, vol_id, mode);
 	if (IS_ERR(desc))
@@ -128,7 +129,8 @@
 	struct ubi_volume_desc *desc = file->private_data;
 	struct ubi_volume *vol = desc->vol;
 
-	dbg_gen("release volume %d, mode %d", vol->vol_id, desc->mode);
+	dbg_gen("release device %d, volume %d, mode %d",
+		vol->ubi->ubi_num, vol->vol_id, desc->mode);
 
 	if (vol->updating) {
 		ubi_warn("update of volume %d not finished, volume is damaged",
@@ -393,7 +395,7 @@
 			vol->corrupted = 1;
 		}
 		vol->checked = 1;
-		ubi_gluebi_updated(vol);
+		ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED);
 		revoke_exclusive(desc, UBI_READWRITE);
 	}
 
@@ -558,7 +560,7 @@
 		break;
 	}
 
-	/* Set volume property command*/
+	/* Set volume property command */
 	case UBI_IOCSETPROP:
 	{
 		struct ubi_set_prop_req req;
@@ -571,9 +573,9 @@
 		}
 		switch (req.property) {
 		case UBI_PROP_DIRECT_WRITE:
-			mutex_lock(&ubi->volumes_mutex);
+			mutex_lock(&ubi->device_mutex);
 			desc->vol->direct_writes = !!req.value;
-			mutex_unlock(&ubi->volumes_mutex);
+			mutex_unlock(&ubi->device_mutex);
 			break;
 		default:
 			err = -EINVAL;
@@ -810,9 +812,9 @@
 			re->desc->vol->vol_id, re->desc->vol->name);
 	}
 
-	mutex_lock(&ubi->volumes_mutex);
+	mutex_lock(&ubi->device_mutex);
 	err = ubi_rename_volumes(ubi, &rename_list);
-	mutex_unlock(&ubi->volumes_mutex);
+	mutex_unlock(&ubi->device_mutex);
 
 out_free:
 	list_for_each_entry_safe(re, re1, &rename_list, list) {
@@ -856,9 +858,9 @@
 		if (err)
 			break;
 
-		mutex_lock(&ubi->volumes_mutex);
+		mutex_lock(&ubi->device_mutex);
 		err = ubi_create_volume(ubi, &req);
-		mutex_unlock(&ubi->volumes_mutex);
+		mutex_unlock(&ubi->device_mutex);
 		if (err)
 			break;
 
@@ -887,9 +889,9 @@
 			break;
 		}
 
-		mutex_lock(&ubi->volumes_mutex);
+		mutex_lock(&ubi->device_mutex);
 		err = ubi_remove_volume(desc, 0);
-		mutex_unlock(&ubi->volumes_mutex);
+		mutex_unlock(&ubi->device_mutex);
 
 		/*
 		 * The volume is deleted (unless an error occurred), and the
@@ -926,9 +928,9 @@
 		pebs = div_u64(req.bytes + desc->vol->usable_leb_size - 1,
 			       desc->vol->usable_leb_size);
 
-		mutex_lock(&ubi->volumes_mutex);
+		mutex_lock(&ubi->device_mutex);
 		err = ubi_resize_volume(desc, pebs);
-		mutex_unlock(&ubi->volumes_mutex);
+		mutex_unlock(&ubi->device_mutex);
 		ubi_close_volume(desc);
 		break;
 	}
@@ -952,9 +954,7 @@
 			break;
 		}
 
-		mutex_lock(&ubi->mult_mutex);
 		err = rename_volumes(ubi, req);
-		mutex_unlock(&ubi->mult_mutex);
 		kfree(req);
 		break;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/debug.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/debug.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/debug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,6 +44,8 @@
 	       be32_to_cpu(ec_hdr->vid_hdr_offset));
 	printk(KERN_DEBUG "\tdata_offset    %d\n",
 	       be32_to_cpu(ec_hdr->data_offset));
+	printk(KERN_DEBUG "\timage_seq      %d\n",
+	       be32_to_cpu(ec_hdr->image_seq));
 	printk(KERN_DEBUG "\thdr_crc        %#08x\n",
 	       be32_to_cpu(ec_hdr->hdr_crc));
 	printk(KERN_DEBUG "erase counter header hexdump:\n");
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/debug.h linux-libre-2.6.31-gnu/drivers/mtd/ubi/debug.h
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/debug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/debug.h	2009-09-09 18:13:59.000000000 -0400
@@ -93,6 +93,12 @@
 #define UBI_IO_DEBUG 0
 #endif
 
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
+#else
+#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#endif
+
 #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
 #define DBG_DISABLE_BGT 1
 #else
@@ -167,6 +173,7 @@
 #define ubi_dbg_is_bitflip()       0
 #define ubi_dbg_is_write_failure() 0
 #define ubi_dbg_is_erase_failure() 0
+#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
 
 #endif /* !CONFIG_MTD_UBI_DEBUG */
 #endif /* !__UBI_DEBUG_H__ */
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/eba.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/eba.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/eba.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/eba.c	2009-09-09 18:13:59.000000000 -0400
@@ -419,8 +419,9 @@
 				 * not implemented.
 				 */
 				if (err == UBI_IO_BAD_VID_HDR) {
-					ubi_warn("bad VID header at PEB %d, LEB"
-						 "%d:%d", pnum, vol_id, lnum);
+					ubi_warn("corrupted VID header at PEB "
+						 "%d, LEB %d:%d", pnum, vol_id,
+						 lnum);
 					err = -EBADMSG;
 				} else
 					ubi_ro_mode(ubi);
@@ -940,6 +941,33 @@
 }
 
 /**
+ * is_error_sane - check whether a read error is sane.
+ * @err: code of the error happened during reading
+ *
+ * This is a helper function for 'ubi_eba_copy_leb()' which is called when we
+ * cannot read data from the target PEB (an error @err happened). If the error
+ * code is sane, then we treat this error as non-fatal. Otherwise the error is
+ * fatal and UBI will be switched to R/O mode later.
+ *
+ * The idea is that we try not to switch to R/O mode if the read error is
+ * something which suggests there was a real read problem. E.g., %-EIO. Or a
+ * memory allocation failed (-%ENOMEM). Otherwise, it is safer to switch to R/O
+ * mode, simply because we do not know what happened at the MTD level, and we
+ * cannot handle this. E.g., the underlying driver may have become crazy, and
+ * it is safer to switch to R/O mode to preserve the data.
+ *
+ * And bear in mind, this is about reading from the target PEB, i.e. the PEB
+ * which we have just written.
+ */
+static int is_error_sane(int err)
+{
+	if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_VID_HDR ||
+	    err == -ETIMEDOUT)
+		return 0;
+	return 1;
+}
+
+/**
  * ubi_eba_copy_leb - copy logical eraseblock.
  * @ubi: UBI device description object
  * @from: physical eraseblock number from where to copy
@@ -950,12 +978,7 @@
  * physical eraseblock @to. The @vid_hdr buffer may be changed by this
  * function. Returns:
  *   o %0 in case of success;
- *   o %1 if the operation was canceled because the volume is being deleted
- *        or because the PEB was put meanwhile;
- *   o %2 if the operation was canceled because there was a write error to the
- *        target PEB;
- *   o %-EAGAIN if the operation was canceled because a bit-flip was detected
- *     in the target PEB;
+ *   o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_CANCEL_BITFLIPS, etc;
  *   o a negative error code in case of failure.
  */
 int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
@@ -968,7 +991,7 @@
 	vol_id = be32_to_cpu(vid_hdr->vol_id);
 	lnum = be32_to_cpu(vid_hdr->lnum);
 
-	dbg_eba("copy LEB %d:%d, PEB %d to PEB %d", vol_id, lnum, from, to);
+	dbg_wl("copy LEB %d:%d, PEB %d to PEB %d", vol_id, lnum, from, to);
 
 	if (vid_hdr->vol_type == UBI_VID_STATIC) {
 		data_size = be32_to_cpu(vid_hdr->data_size);
@@ -986,13 +1009,12 @@
 	 * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish.
 	 */
 	vol = ubi->volumes[idx];
+	spin_unlock(&ubi->volumes_lock);
 	if (!vol) {
 		/* No need to do further work, cancel */
-		dbg_eba("volume %d is being removed, cancel", vol_id);
-		spin_unlock(&ubi->volumes_lock);
-		return 1;
+		dbg_wl("volume %d is being removed, cancel", vol_id);
+		return MOVE_CANCEL_RACE;
 	}
-	spin_unlock(&ubi->volumes_lock);
 
 	/*
 	 * We do not want anybody to write to this logical eraseblock while we
@@ -1004,12 +1026,13 @@
 	 * (@from). This task locks the LEB and goes sleep in the
 	 * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are
 	 * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the
-	 * LEB is already locked, we just do not move it and return %1.
+	 * LEB is already locked, we just do not move it and return
+	 * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later.
 	 */
 	err = leb_write_trylock(ubi, vol_id, lnum);
 	if (err) {
-		dbg_eba("contention on LEB %d:%d, cancel", vol_id, lnum);
-		return err;
+		dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum);
+		return MOVE_CANCEL_RACE;
 	}
 
 	/*
@@ -1018,25 +1041,26 @@
 	 * cancel it.
 	 */
 	if (vol->eba_tbl[lnum] != from) {
-		dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to "
-			"PEB %d, cancel", vol_id, lnum, from,
-			vol->eba_tbl[lnum]);
-		err = 1;
+		dbg_wl("LEB %d:%d is no longer mapped to PEB %d, mapped to "
+		       "PEB %d, cancel", vol_id, lnum, from,
+		       vol->eba_tbl[lnum]);
+		err = MOVE_CANCEL_RACE;
 		goto out_unlock_leb;
 	}
 
 	/*
 	 * OK, now the LEB is locked and we can safely start moving it. Since
-	 * this function utilizes the @ubi->peb1_buf buffer which is shared
-	 * with some other functions, so lock the buffer by taking the
+	 * this function utilizes the @ubi->peb_buf1 buffer which is shared
+	 * with some other functions - we lock the buffer by taking the
 	 * @ubi->buf_mutex.
 	 */
 	mutex_lock(&ubi->buf_mutex);
-	dbg_eba("read %d bytes of data", aldata_size);
+	dbg_wl("read %d bytes of data", aldata_size);
 	err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size);
 	if (err && err != UBI_IO_BITFLIPS) {
 		ubi_warn("error %d while reading data from PEB %d",
 			 err, from);
+		err = MOVE_SOURCE_RD_ERR;
 		goto out_unlock_buf;
 	}
 
@@ -1059,7 +1083,7 @@
 	cond_resched();
 
 	/*
-	 * It may turn out to me that the whole @from physical eraseblock
+	 * It may turn out to be that the whole @from physical eraseblock
 	 * contains only 0xFF bytes. Then we have to only write the VID header
 	 * and do not write any data. This also means we should not set
 	 * @vid_hdr->copy_flag, @vid_hdr->data_size, and @vid_hdr->data_crc.
@@ -1074,7 +1098,7 @@
 	err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
 	if (err) {
 		if (err == -EIO)
-			err = 2;
+			err = MOVE_TARGET_WR_ERR;
 		goto out_unlock_buf;
 	}
 
@@ -1083,10 +1107,13 @@
 	/* Read the VID header back and check if it was written correctly */
 	err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
 	if (err) {
-		if (err != UBI_IO_BITFLIPS)
-			ubi_warn("cannot read VID header back from PEB %d", to);
-		else
-			err = -EAGAIN;
+		if (err != UBI_IO_BITFLIPS) {
+			ubi_warn("error %d while reading VID header back from "
+				  "PEB %d", err, to);
+			if (is_error_sane(err))
+				err = MOVE_TARGET_RD_ERR;
+		} else
+			err = MOVE_CANCEL_BITFLIPS;
 		goto out_unlock_buf;
 	}
 
@@ -1094,7 +1121,7 @@
 		err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
 		if (err) {
 			if (err == -EIO)
-				err = 2;
+				err = MOVE_TARGET_WR_ERR;
 			goto out_unlock_buf;
 		}
 
@@ -1107,11 +1134,13 @@
 
 		err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
 		if (err) {
-			if (err != UBI_IO_BITFLIPS)
-				ubi_warn("cannot read data back from PEB %d",
-					 to);
-			else
-				err = -EAGAIN;
+			if (err != UBI_IO_BITFLIPS) {
+				ubi_warn("error %d while reading data back "
+					 "from PEB %d", err, to);
+				if (is_error_sane(err))
+					err = MOVE_TARGET_RD_ERR;
+			} else
+				err = MOVE_CANCEL_BITFLIPS;
 			goto out_unlock_buf;
 		}
 
@@ -1225,6 +1254,7 @@
 		if (!ubi->volumes[i])
 			continue;
 		kfree(ubi->volumes[i]->eba_tbl);
+		ubi->volumes[i]->eba_tbl = NULL;
 	}
 	return err;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/gluebi.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/gluebi.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/gluebi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/gluebi.c	2009-09-09 18:13:59.000000000 -0400
@@ -19,17 +19,71 @@
  */
 
 /*
- * This file includes implementation of fake MTD devices for each UBI volume.
- * This sounds strange, but it is in fact quite useful to make MTD-oriented
- * software (including all the legacy software) to work on top of UBI.
+ * This is a small driver which implements fake MTD devices on top of UBI
+ * volumes. This sounds strange, but it is in fact quite useful to make
+ * MTD-oriented software (including all the legacy software) work on top of
+ * UBI.
  *
  * Gluebi emulates MTD devices of "MTD_UBIVOLUME" type. Their minimal I/O unit
- * size (mtd->writesize) is equivalent to the UBI minimal I/O unit. The
+ * size (@mtd->writesize) is equivalent to the UBI minimal I/O unit. The
  * eraseblock size is equivalent to the logical eraseblock size of the volume.
  */
 
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/sched.h>
 #include <linux/math64.h>
-#include "ubi.h"
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mtd/ubi.h>
+#include <linux/mtd/mtd.h>
+#include "ubi-media.h"
+
+#define err_msg(fmt, ...)                                   \
+	printk(KERN_DEBUG "gluebi (pid %d): %s: " fmt "\n", \
+	       current->pid, __func__, ##__VA_ARGS__)
+
+/**
+ * struct gluebi_device - a gluebi device description data structure.
+ * @mtd: emulated MTD device description object
+ * @refcnt: gluebi device reference count
+ * @desc: UBI volume descriptor
+ * @ubi_num: UBI device number this gluebi device works on
+ * @vol_id: ID of UBI volume this gluebi device works on
+ * @list: link in a list of gluebi devices
+ */
+struct gluebi_device {
+	struct mtd_info mtd;
+	int refcnt;
+	struct ubi_volume_desc *desc;
+	int ubi_num;
+	int vol_id;
+	struct list_head list;
+};
+
+/* List of all gluebi devices */
+static LIST_HEAD(gluebi_devices);
+static DEFINE_MUTEX(devices_mutex);
+
+/**
+ * find_gluebi_nolock - find a gluebi device.
+ * @ubi_num: UBI device number
+ * @vol_id: volume ID
+ *
+ * This function seraches for gluebi device corresponding to UBI device
+ * @ubi_num and UBI volume @vol_id. Returns the gluebi device description
+ * object in case of success and %NULL in case of failure. The caller has to
+ * have the &devices_mutex locked.
+ */
+static struct gluebi_device *find_gluebi_nolock(int ubi_num, int vol_id)
+{
+	struct gluebi_device *gluebi;
+
+	list_for_each_entry(gluebi, &gluebi_devices, list)
+		if (gluebi->ubi_num == ubi_num && gluebi->vol_id == vol_id)
+			return gluebi;
+	return NULL;
+}
 
 /**
  * gluebi_get_device - get MTD device reference.
@@ -41,15 +95,18 @@
  */
 static int gluebi_get_device(struct mtd_info *mtd)
 {
-	struct ubi_volume *vol;
+	struct gluebi_device *gluebi;
+	int ubi_mode = UBI_READONLY;
 
-	vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
 
-	/*
-	 * We do not introduce locks for gluebi reference count because the
-	 * get_device()/put_device() calls are already serialized at MTD.
-	 */
-	if (vol->gluebi_refcount > 0) {
+	if (mtd->flags & MTD_WRITEABLE)
+		ubi_mode = UBI_READWRITE;
+
+	gluebi = container_of(mtd, struct gluebi_device, mtd);
+	mutex_lock(&devices_mutex);
+	if (gluebi->refcnt > 0) {
 		/*
 		 * The MTD device is already referenced and this is just one
 		 * more reference. MTD allows many users to open the same
@@ -58,7 +115,8 @@
 		 * open the UBI volume again - just increase the reference
 		 * counter and return.
 		 */
-		vol->gluebi_refcount += 1;
+		gluebi->refcnt += 1;
+		mutex_unlock(&devices_mutex);
 		return 0;
 	}
 
@@ -66,11 +124,15 @@
 	 * This is the first reference to this UBI volume via the MTD device
 	 * interface. Open the corresponding volume in read-write mode.
 	 */
-	vol->gluebi_desc = ubi_open_volume(vol->ubi->ubi_num, vol->vol_id,
-					   UBI_READWRITE);
-	if (IS_ERR(vol->gluebi_desc))
-		return PTR_ERR(vol->gluebi_desc);
-	vol->gluebi_refcount += 1;
+	gluebi->desc = ubi_open_volume(gluebi->ubi_num, gluebi->vol_id,
+				       ubi_mode);
+	if (IS_ERR(gluebi->desc)) {
+		mutex_unlock(&devices_mutex);
+		module_put(THIS_MODULE);
+		return PTR_ERR(gluebi->desc);
+	}
+	gluebi->refcnt += 1;
+	mutex_unlock(&devices_mutex);
 	return 0;
 }
 
@@ -83,13 +145,15 @@
  */
 static void gluebi_put_device(struct mtd_info *mtd)
 {
-	struct ubi_volume *vol;
+	struct gluebi_device *gluebi;
 
-	vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
-	vol->gluebi_refcount -= 1;
-	ubi_assert(vol->gluebi_refcount >= 0);
-	if (vol->gluebi_refcount == 0)
-		ubi_close_volume(vol->gluebi_desc);
+	gluebi = container_of(mtd, struct gluebi_device, mtd);
+	mutex_lock(&devices_mutex);
+	gluebi->refcnt -= 1;
+	if (gluebi->refcnt == 0)
+		ubi_close_volume(gluebi->desc);
+	module_put(THIS_MODULE);
+	mutex_unlock(&devices_mutex);
 }
 
 /**
@@ -107,16 +171,12 @@
 		       size_t *retlen, unsigned char *buf)
 {
 	int err = 0, lnum, offs, total_read;
-	struct ubi_volume *vol;
-	struct ubi_device *ubi;
-
-	dbg_gen("read %zd bytes from offset %lld", len, from);
+	struct gluebi_device *gluebi;
 
 	if (len < 0 || from < 0 || from + len > mtd->size)
 		return -EINVAL;
 
-	vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
-	ubi = vol->ubi;
+	gluebi = container_of(mtd, struct gluebi_device, mtd);
 
 	lnum = div_u64_rem(from, mtd->erasesize, &offs);
 	total_read = len;
@@ -126,7 +186,7 @@
 		if (to_read > total_read)
 			to_read = total_read;
 
-		err = ubi_eba_read_leb(ubi, vol, lnum, buf, offs, to_read, 0);
+		err = ubi_read(gluebi->desc, lnum, buf, offs, to_read);
 		if (err)
 			break;
 
@@ -152,21 +212,17 @@
  * case of failure.
  */
 static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
-		       size_t *retlen, const u_char *buf)
+			size_t *retlen, const u_char *buf)
 {
 	int err = 0, lnum, offs, total_written;
-	struct ubi_volume *vol;
-	struct ubi_device *ubi;
-
-	dbg_gen("write %zd bytes to offset %lld", len, to);
+	struct gluebi_device *gluebi;
 
 	if (len < 0 || to < 0 || len + to > mtd->size)
 		return -EINVAL;
 
-	vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
-	ubi = vol->ubi;
+	gluebi = container_of(mtd, struct gluebi_device, mtd);
 
-	if (ubi->ro_mode)
+	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 
 	lnum = div_u64_rem(to, mtd->erasesize, &offs);
@@ -181,8 +237,7 @@
 		if (to_write > total_written)
 			to_write = total_written;
 
-		err = ubi_eba_write_leb(ubi, vol, lnum, buf, offs, to_write,
-					UBI_UNKNOWN);
+		err = ubi_write(gluebi->desc, lnum, buf, offs, to_write);
 		if (err)
 			break;
 
@@ -207,41 +262,36 @@
 static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	int err, i, lnum, count;
-	struct ubi_volume *vol;
-	struct ubi_device *ubi;
-
-	dbg_gen("erase %llu bytes at offset %llu", (unsigned long long)instr->len,
-		 (unsigned long long)instr->addr);
+	struct gluebi_device *gluebi;
 
 	if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize)
 		return -EINVAL;
-
 	if (instr->len < 0 || instr->addr + instr->len > mtd->size)
 		return -EINVAL;
-
 	if (mtd_mod_by_ws(instr->addr, mtd) || mtd_mod_by_ws(instr->len, mtd))
 		return -EINVAL;
 
 	lnum = mtd_div_by_eb(instr->addr, mtd);
 	count = mtd_div_by_eb(instr->len, mtd);
 
-	vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
-	ubi = vol->ubi;
+	gluebi = container_of(mtd, struct gluebi_device, mtd);
 
-	if (ubi->ro_mode)
+	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 
-	for (i = 0; i < count; i++) {
-		err = ubi_eba_unmap_leb(ubi, vol, lnum + i);
+	for (i = 0; i < count - 1; i++) {
+		err = ubi_leb_unmap(gluebi->desc, lnum + i);
 		if (err)
 			goto out_err;
 	}
-
 	/*
 	 * MTD erase operations are synchronous, so we have to make sure the
 	 * physical eraseblock is wiped out.
+	 *
+	 * Thus, perform leb_erase instead of leb_unmap operation - leb_erase
+	 * will wait for the end of operations
 	 */
-	err = ubi_wl_flush(ubi);
+	err = ubi_leb_erase(gluebi->desc, lnum + i);
 	if (err)
 		goto out_err;
 
@@ -256,28 +306,39 @@
 }
 
 /**
- * ubi_create_gluebi - initialize gluebi for an UBI volume.
- * @ubi: UBI device description object
- * @vol: volume description object
+ * gluebi_create - create a gluebi device for an UBI volume.
+ * @di: UBI device description object
+ * @vi: UBI volume description object
  *
- * This function is called when an UBI volume is created in order to create
+ * This function is called when a new UBI volume is created in order to create
  * corresponding fake MTD device. Returns zero in case of success and a
  * negative error code in case of failure.
  */
-int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
+static int gluebi_create(struct ubi_device_info *di,
+			 struct ubi_volume_info *vi)
 {
-	struct mtd_info *mtd = &vol->gluebi_mtd;
+	struct gluebi_device *gluebi, *g;
+	struct mtd_info *mtd;
 
-	mtd->name = kmemdup(vol->name, vol->name_len + 1, GFP_KERNEL);
-	if (!mtd->name)
+	gluebi = kzalloc(sizeof(struct gluebi_device), GFP_KERNEL);
+	if (!gluebi)
 		return -ENOMEM;
 
+	mtd = &gluebi->mtd;
+	mtd->name = kmemdup(vi->name, vi->name_len + 1, GFP_KERNEL);
+	if (!mtd->name) {
+		kfree(gluebi);
+		return -ENOMEM;
+	}
+
+	gluebi->vol_id = vi->vol_id;
+	gluebi->ubi_num = vi->ubi_num;
 	mtd->type = MTD_UBIVOLUME;
-	if (!ubi->ro_mode)
+	if (!di->ro_mode)
 		mtd->flags = MTD_WRITEABLE;
-	mtd->writesize  = ubi->min_io_size;
 	mtd->owner      = THIS_MODULE;
-	mtd->erasesize  = vol->usable_leb_size;
+	mtd->writesize  = di->min_io_size;
+	mtd->erasesize  = vi->usable_leb_size;
 	mtd->read       = gluebi_read;
 	mtd->write      = gluebi_write;
 	mtd->erase      = gluebi_erase;
@@ -285,60 +346,196 @@
 	mtd->put_device = gluebi_put_device;
 
 	/*
-	 * In case of dynamic volume, MTD device size is just volume size. In
+	 * In case of dynamic a volume, MTD device size is just volume size. In
 	 * case of a static volume the size is equivalent to the amount of data
 	 * bytes.
 	 */
-	if (vol->vol_type == UBI_DYNAMIC_VOLUME)
-		mtd->size = (long long)vol->usable_leb_size * vol->reserved_pebs;
+	if (vi->vol_type == UBI_DYNAMIC_VOLUME)
+		mtd->size = (unsigned long long)vi->usable_leb_size * vi->size;
 	else
-		mtd->size = vol->used_bytes;
+		mtd->size = vi->used_bytes;
+
+	/* Just a sanity check - make sure this gluebi device does not exist */
+	mutex_lock(&devices_mutex);
+	g = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
+	if (g)
+		err_msg("gluebi MTD device %d form UBI device %d volume %d "
+			"already exists", g->mtd.index, vi->ubi_num,
+			vi->vol_id);
+	mutex_unlock(&devices_mutex);
 
 	if (add_mtd_device(mtd)) {
-		ubi_err("cannot not add MTD device");
+		err_msg("cannot add MTD device");
 		kfree(mtd->name);
+		kfree(gluebi);
 		return -ENFILE;
 	}
 
-	dbg_gen("added mtd%d (\"%s\"), size %llu, EB size %u",
-		mtd->index, mtd->name, (unsigned long long)mtd->size, mtd->erasesize);
+	mutex_lock(&devices_mutex);
+	list_add_tail(&gluebi->list, &gluebi_devices);
+	mutex_unlock(&devices_mutex);
 	return 0;
 }
 
 /**
- * ubi_destroy_gluebi - close gluebi for an UBI volume.
- * @vol: volume description object
+ * gluebi_remove - remove a gluebi device.
+ * @vi: UBI volume description object
  *
- * This function is called when an UBI volume is removed in order to remove
+ * This function is called when an UBI volume is removed and it removes
  * corresponding fake MTD device. Returns zero in case of success and a
  * negative error code in case of failure.
  */
-int ubi_destroy_gluebi(struct ubi_volume *vol)
+static int gluebi_remove(struct ubi_volume_info *vi)
 {
-	int err;
-	struct mtd_info *mtd = &vol->gluebi_mtd;
+	int err = 0;
+	struct mtd_info *mtd;
+	struct gluebi_device *gluebi;
 
-	dbg_gen("remove mtd%d", mtd->index);
-	err = del_mtd_device(mtd);
+	mutex_lock(&devices_mutex);
+	gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
+	if (!gluebi) {
+		err_msg("got remove notification for unknown UBI device %d "
+			"volume %d", vi->ubi_num, vi->vol_id);
+		err = -ENOENT;
+	} else if (gluebi->refcnt)
+		err = -EBUSY;
+	else
+		list_del(&gluebi->list);
+	mutex_unlock(&devices_mutex);
 	if (err)
 		return err;
+
+	mtd = &gluebi->mtd;
+	err = del_mtd_device(mtd);
+	if (err) {
+		err_msg("cannot remove fake MTD device %d, UBI device %d, "
+			"volume %d, error %d", mtd->index, gluebi->ubi_num,
+			gluebi->vol_id, err);
+		mutex_lock(&devices_mutex);
+		list_add_tail(&gluebi->list, &gluebi_devices);
+		mutex_unlock(&devices_mutex);
+		return err;
+	}
+
 	kfree(mtd->name);
+	kfree(gluebi);
 	return 0;
 }
 
 /**
- * ubi_gluebi_updated - UBI volume was updated notifier.
- * @vol: volume description object
+ * gluebi_updated - UBI volume was updated notifier.
+ * @vi: volume info structure
  *
- * This function is called every time an UBI volume is updated. This function
- * does nothing if volume @vol is dynamic, and changes MTD device size if the
+ * This function is called every time an UBI volume is updated. It does nothing
+ * if te volume @vol is dynamic, and changes MTD device size if the
  * volume is static. This is needed because static volumes cannot be read past
- * data they contain.
+ * data they contain. This function returns zero in case of success and a
+ * negative error code in case of error.
  */
-void ubi_gluebi_updated(struct ubi_volume *vol)
+static int gluebi_updated(struct ubi_volume_info *vi)
 {
-	struct mtd_info *mtd = &vol->gluebi_mtd;
+	struct gluebi_device *gluebi;
 
-	if (vol->vol_type == UBI_STATIC_VOLUME)
-		mtd->size = vol->used_bytes;
+	mutex_lock(&devices_mutex);
+	gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
+	if (!gluebi) {
+		mutex_unlock(&devices_mutex);
+		err_msg("got update notification for unknown UBI device %d "
+			"volume %d", vi->ubi_num, vi->vol_id);
+		return -ENOENT;
+	}
+
+	if (vi->vol_type == UBI_STATIC_VOLUME)
+		gluebi->mtd.size = vi->used_bytes;
+	mutex_unlock(&devices_mutex);
+	return 0;
+}
+
+/**
+ * gluebi_resized - UBI volume was re-sized notifier.
+ * @vi: volume info structure
+ *
+ * This function is called every time an UBI volume is re-size. It changes the
+ * corresponding fake MTD device size. This function returns zero in case of
+ * success and a negative error code in case of error.
+ */
+static int gluebi_resized(struct ubi_volume_info *vi)
+{
+	struct gluebi_device *gluebi;
+
+	mutex_lock(&devices_mutex);
+	gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
+	if (!gluebi) {
+		mutex_unlock(&devices_mutex);
+		err_msg("got update notification for unknown UBI device %d "
+			"volume %d", vi->ubi_num, vi->vol_id);
+		return -ENOENT;
+	}
+	gluebi->mtd.size = vi->used_bytes;
+	mutex_unlock(&devices_mutex);
+	return 0;
+}
+
+/**
+ * gluebi_notify - UBI notification handler.
+ * @nb: registered notifier block
+ * @l: notification type
+ * @ptr: pointer to the &struct ubi_notification object
+ */
+static int gluebi_notify(struct notifier_block *nb, unsigned long l,
+			 void *ns_ptr)
+{
+	struct ubi_notification *nt = ns_ptr;
+
+	switch (l) {
+	case UBI_VOLUME_ADDED:
+		gluebi_create(&nt->di, &nt->vi);
+		break;
+	case UBI_VOLUME_REMOVED:
+		gluebi_remove(&nt->vi);
+		break;
+	case UBI_VOLUME_RESIZED:
+		gluebi_resized(&nt->vi);
+		break;
+	case UBI_VOLUME_UPDATED:
+		gluebi_updated(&nt->vi);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block gluebi_notifier = {
+	.notifier_call	= gluebi_notify,
+};
+
+static int __init ubi_gluebi_init(void)
+{
+	return ubi_register_volume_notifier(&gluebi_notifier, 0);
 }
+
+static void __exit ubi_gluebi_exit(void)
+{
+	struct gluebi_device *gluebi, *g;
+
+	list_for_each_entry_safe(gluebi, g, &gluebi_devices, list) {
+		int err;
+		struct mtd_info *mtd = &gluebi->mtd;
+
+		err = del_mtd_device(mtd);
+		if (err)
+			err_msg("error %d while removing gluebi MTD device %d, "
+				"UBI device %d, volume %d - ignoring", err,
+				mtd->index, gluebi->ubi_num, gluebi->vol_id);
+		kfree(mtd->name);
+		kfree(gluebi);
+	}
+	ubi_unregister_volume_notifier(&gluebi_notifier);
+}
+
+module_init(ubi_gluebi_init);
+module_exit(ubi_gluebi_exit);
+MODULE_DESCRIPTION("MTD emulation layer over UBI volumes");
+MODULE_AUTHOR("Artem Bityutskiy, Joern Engel");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/io.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/io.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/io.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,15 +98,12 @@
 static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
 				  const struct ubi_vid_hdr *vid_hdr);
-static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
-				 int len);
 #else
 #define paranoid_check_not_bad(ubi, pnum) 0
 #define paranoid_check_peb_ec_hdr(ubi, pnum)  0
 #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr)  0
 #define paranoid_check_peb_vid_hdr(ubi, pnum) 0
 #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0
-#define paranoid_check_all_ff(ubi, pnum, offset, len) 0
 #endif
 
 /**
@@ -242,7 +239,7 @@
 		return err > 0 ? -EINVAL : err;
 
 	/* The area we are writing to has to contain all 0xFF bytes */
-	err = paranoid_check_all_ff(ubi, pnum, offset, len);
+	err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
 	if (err)
 		return err > 0 ? -EINVAL : err;
 
@@ -269,8 +266,8 @@
 	addr = (loff_t)pnum * ubi->peb_size + offset;
 	err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf);
 	if (err) {
-		ubi_err("error %d while writing %d bytes to PEB %d:%d, written"
-			" %zd bytes", err, len, pnum, offset, written);
+		ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
+			"%zd bytes", err, len, pnum, offset, written);
 		ubi_dbg_dump_stack();
 	} else
 		ubi_assert(written == len);
@@ -348,7 +345,7 @@
 		return -EIO;
 	}
 
-	err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size);
+	err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
 	if (err)
 		return err > 0 ? -EINVAL : err;
 
@@ -457,6 +454,54 @@
 }
 
 /**
+ * nor_erase_prepare - prepare a NOR flash PEB for erasure.
+ * @ubi: UBI device description object
+ * @pnum: physical eraseblock number to prepare
+ *
+ * NOR flash, or at least some of them, have peculiar embedded PEB erasure
+ * algorithm: the PEB is first filled with zeroes, then it is erased. And
+ * filling with zeroes starts from the end of the PEB. This was observed with
+ * Spansion S29GL512N NOR flash.
+ *
+ * This means that in case of a power cut we may end up with intact data at the
+ * beginning of the PEB, and all zeroes at the end of PEB. In other words, the
+ * EC and VID headers are OK, but a large chunk of data at the end of PEB is
+ * zeroed. This makes UBI mistakenly treat this PEB as used and associate it
+ * with an LEB, which leads to subsequent failures (e.g., UBIFS fails).
+ *
+ * This function is called before erasing NOR PEBs and it zeroes out EC and VID
+ * magic numbers in order to invalidate them and prevent the failures. Returns
+ * zero in case of success and a negative error code in case of failure.
+ */
+static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
+{
+	int err;
+	size_t written;
+	loff_t addr;
+	uint32_t data = 0;
+
+	addr = (loff_t)pnum * ubi->peb_size;
+	err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
+	if (err) {
+		ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
+			"%zd bytes", err, pnum, 0, written);
+		ubi_dbg_dump_stack();
+		return err;
+	}
+
+	addr += ubi->vid_hdr_aloffset;
+	err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
+	if (err) {
+		ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
+			"%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written);
+		ubi_dbg_dump_stack();
+		return err;
+	}
+
+	return 0;
+}
+
+/**
  * ubi_io_sync_erase - synchronously erase a physical eraseblock.
  * @ubi: UBI device description object
  * @pnum: physical eraseblock number to erase
@@ -487,6 +532,12 @@
 		return -EROFS;
 	}
 
+	if (ubi->nor_flash) {
+		err = nor_erase_prepare(ubi, pnum);
+		if (err)
+			return err;
+	}
+
 	if (torture) {
 		ret = torture_peb(ubi, pnum);
 		if (ret < 0)
@@ -670,16 +721,6 @@
 		if (read_err != -EBADMSG &&
 		    check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
 			/* The physical eraseblock is supposedly empty */
-
-			/*
-			 * The below is just a paranoid check, it has to be
-			 * compiled out if paranoid checks are disabled.
-			 */
-			err = paranoid_check_all_ff(ubi, pnum, 0,
-						    ubi->peb_size);
-			if (err)
-				return err > 0 ? UBI_IO_BAD_EC_HDR : err;
-
 			if (verbose)
 				ubi_warn("no EC header found at PEB %d, "
 					 "only 0xFF bytes", pnum);
@@ -755,6 +796,7 @@
 	ec_hdr->version = UBI_VERSION;
 	ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset);
 	ec_hdr->data_offset = cpu_to_be32(ubi->leb_start);
+	ec_hdr->image_seq = cpu_to_be32(ubi->image_seq);
 	crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
 	ec_hdr->hdr_crc = cpu_to_be32(crc);
 
@@ -902,7 +944,7 @@
  * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
  *   and corrected by the flash driver; this is harmless but may indicate that
  *   this eraseblock may become bad soon;
- * o %UBI_IO_BAD_VID_HRD if the volume identifier header is corrupted (a CRC
+ * o %UBI_IO_BAD_VID_HDR if the volume identifier header is corrupted (a CRC
  *   error detected);
  * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID
  *   header there);
@@ -950,16 +992,6 @@
 		if (read_err != -EBADMSG &&
 		    check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
 			/* The physical eraseblock is supposedly free */
-
-			/*
-			 * The below is just a paranoid check, it has to be
-			 * compiled out if paranoid checks are disabled.
-			 */
-			err = paranoid_check_all_ff(ubi, pnum, ubi->leb_start,
-						    ubi->leb_size);
-			if (err)
-				return err > 0 ? UBI_IO_BAD_VID_HDR : err;
-
 			if (verbose)
 				ubi_warn("no VID header found at PEB %d, "
 					 "only 0xFF bytes", pnum);
@@ -1233,7 +1265,7 @@
 }
 
 /**
- * paranoid_check_all_ff - check that a region of flash is empty.
+ * ubi_dbg_check_all_ff - check that a region of flash is empty.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
  * @offset: the starting offset within the physical eraseblock to check
@@ -1243,8 +1275,7 @@
  * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
  * code if an error occurred.
  */
-static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
-				 int len)
+int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
 {
 	size_t read;
 	int err;
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/kapi.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/kapi.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/kapi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/kapi.c	2009-09-09 18:13:59.000000000 -0400
@@ -26,6 +26,24 @@
 #include "ubi.h"
 
 /**
+ * ubi_do_get_device_info - get information about UBI device.
+ * @ubi: UBI device description object
+ * @di: the information is stored here
+ *
+ * This function is the same as 'ubi_get_device_info()', but it assumes the UBI
+ * device is locked and cannot disappear.
+ */
+void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di)
+{
+	di->ubi_num = ubi->ubi_num;
+	di->leb_size = ubi->leb_size;
+	di->min_io_size = ubi->min_io_size;
+	di->ro_mode = ubi->ro_mode;
+	di->cdev = ubi->cdev.dev;
+}
+EXPORT_SYMBOL_GPL(ubi_do_get_device_info);
+
+/**
  * ubi_get_device_info - get information about UBI device.
  * @ubi_num: UBI device number
  * @di: the information is stored here
@@ -39,33 +57,24 @@
 
 	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
 		return -EINVAL;
-
 	ubi = ubi_get_device(ubi_num);
 	if (!ubi)
 		return -ENODEV;
-
-	di->ubi_num = ubi->ubi_num;
-	di->leb_size = ubi->leb_size;
-	di->min_io_size = ubi->min_io_size;
-	di->ro_mode = ubi->ro_mode;
-	di->cdev = ubi->cdev.dev;
-
+	ubi_do_get_device_info(ubi, di);
 	ubi_put_device(ubi);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ubi_get_device_info);
 
 /**
- * ubi_get_volume_info - get information about UBI volume.
- * @desc: volume descriptor
+ * ubi_do_get_volume_info - get information about UBI volume.
+ * @ubi: UBI device description object
+ * @vol: volume description object
  * @vi: the information is stored here
  */
-void ubi_get_volume_info(struct ubi_volume_desc *desc,
-			 struct ubi_volume_info *vi)
+void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
+			    struct ubi_volume_info *vi)
 {
-	const struct ubi_volume *vol = desc->vol;
-	const struct ubi_device *ubi = vol->ubi;
-
 	vi->vol_id = vol->vol_id;
 	vi->ubi_num = ubi->ubi_num;
 	vi->size = vol->reserved_pebs;
@@ -79,6 +88,17 @@
 	vi->name = vol->name;
 	vi->cdev = vol->cdev.dev;
 }
+
+/**
+ * ubi_get_volume_info - get information about UBI volume.
+ * @desc: volume descriptor
+ * @vi: the information is stored here
+ */
+void ubi_get_volume_info(struct ubi_volume_desc *desc,
+			 struct ubi_volume_info *vi)
+{
+	ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi);
+}
 EXPORT_SYMBOL_GPL(ubi_get_volume_info);
 
 /**
@@ -106,7 +126,7 @@
 	struct ubi_device *ubi;
 	struct ubi_volume *vol;
 
-	dbg_gen("open device %d volume %d, mode %d", ubi_num, vol_id, mode);
+	dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode);
 
 	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
 		return ERR_PTR(-EINVAL);
@@ -196,6 +216,8 @@
 	kfree(desc);
 out_put_ubi:
 	ubi_put_device(ubi);
+	dbg_err("cannot open device %d, volume %d, error %d",
+		ubi_num, vol_id, err);
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(ubi_open_volume);
@@ -215,7 +237,7 @@
 	struct ubi_device *ubi;
 	struct ubi_volume_desc *ret;
 
-	dbg_gen("open volume %s, mode %d", name, mode);
+	dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode);
 
 	if (!name)
 		return ERR_PTR(-EINVAL);
@@ -266,7 +288,8 @@
 	struct ubi_volume *vol = desc->vol;
 	struct ubi_device *ubi = vol->ubi;
 
-	dbg_gen("close volume %d, mode %d", vol->vol_id, desc->mode);
+	dbg_gen("close device %d, volume %d, mode %d",
+		ubi->ubi_num, vol->vol_id, desc->mode);
 
 	spin_lock(&ubi->volumes_lock);
 	switch (desc->mode) {
@@ -558,7 +581,7 @@
 EXPORT_SYMBOL_GPL(ubi_leb_unmap);
 
 /**
- * ubi_leb_map - map logical erasblock to a physical eraseblock.
+ * ubi_leb_map - map logical eraseblock to a physical eraseblock.
  * @desc: volume descriptor
  * @lnum: logical eraseblock number
  * @dtype: expected data type
@@ -656,3 +679,59 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ubi_sync);
+
+BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
+
+/**
+ * ubi_register_volume_notifier - register a volume notifier.
+ * @nb: the notifier description object
+ * @ignore_existing: if non-zero, do not send "added" notification for all
+ *                   already existing volumes
+ *
+ * This function registers a volume notifier, which means that
+ * 'nb->notifier_call()' will be invoked when an UBI  volume is created,
+ * removed, re-sized, re-named, or updated. The first argument of the function
+ * is the notification type. The second argument is pointer to a
+ * &struct ubi_notification object which describes the notification event.
+ * Using UBI API from the volume notifier is prohibited.
+ *
+ * This function returns zero in case of success and a negative error code
+ * in case of failure.
+ */
+int ubi_register_volume_notifier(struct notifier_block *nb,
+				 int ignore_existing)
+{
+	int err;
+
+	err = blocking_notifier_chain_register(&ubi_notifiers, nb);
+	if (err != 0)
+		return err;
+	if (ignore_existing)
+		return 0;
+
+	/*
+	 * We are going to walk all UBI devices and all volumes, and
+	 * notify the user about existing volumes by the %UBI_VOLUME_ADDED
+	 * event. We have to lock the @ubi_devices_mutex to make sure UBI
+	 * devices do not disappear.
+	 */
+	mutex_lock(&ubi_devices_mutex);
+	ubi_enumerate_volumes(nb);
+	mutex_unlock(&ubi_devices_mutex);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ubi_register_volume_notifier);
+
+/**
+ * ubi_unregister_volume_notifier - unregister the volume notifier.
+ * @nb: the notifier description object
+ *
+ * This function unregisters volume notifier @nm and returns zero in case of
+ * success and a negative error code in case of failure.
+ */
+int ubi_unregister_volume_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&ubi_notifiers, nb);
+}
+EXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier);
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/Kconfig linux-libre-2.6.31-gnu/drivers/mtd/ubi/Kconfig
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -49,15 +49,16 @@
 	  reserved. Leave the default value if unsure.
 
 config MTD_UBI_GLUEBI
-	bool "Emulate MTD devices"
+	tristate "MTD devices emulation driver (gluebi)"
 	default n
 	depends on MTD_UBI
 	help
-	   This option enables MTD devices emulation on top of UBI volumes: for
-	   each UBI volumes an MTD device is created, and all I/O to this MTD
-	   device is redirected to the UBI volume. This is handy to make
-	   MTD-oriented software (like JFFS2) work on top of UBI. Do not enable
-	   this if no legacy software will be used.
+	   This option enables gluebi - an additional driver which emulates MTD
+	   devices on top of UBI volumes: for each UBI volumes an MTD device is
+	   created, and all I/O to this MTD device is redirected to the UBI
+	   volume. This is handy to make MTD-oriented software (like JFFS2)
+	   work on top of UBI. Do not enable this unless you use legacy
+	   software.
 
 source "drivers/mtd/ubi/Kconfig.debug"
 endmenu
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/Makefile linux-libre-2.6.31-gnu/drivers/mtd/ubi/Makefile
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,4 +4,4 @@
 ubi-y += misc.o
 
 ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
-ubi-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
+obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/scan.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/scan.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/scan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/scan.c	2009-09-09 18:13:59.000000000 -0400
@@ -757,6 +757,8 @@
 	si->is_empty = 0;
 
 	if (!ec_corr) {
+		int image_seq;
+
 		/* Make sure UBI version is OK */
 		if (ech->version != UBI_VERSION) {
 			ubi_err("this UBI version is %d, image version is %d",
@@ -778,6 +780,29 @@
 			ubi_dbg_dump_ec_hdr(ech);
 			return -EINVAL;
 		}
+
+		/*
+		 * Make sure that all PEBs have the same image sequence number.
+		 * This allows us to detect situations when users flash UBI
+		 * images incorrectly, so that the flash has the new UBI image
+		 * and leftovers from the old one. This feature was added
+		 * relatively recently, and the sequence number was always
+		 * zero, because old UBI implementations always set it to zero.
+		 * For this reasons, we do not panic if some PEBs have zero
+		 * sequence number, while other PEBs have non-zero sequence
+		 * number.
+		 */
+		image_seq = be32_to_cpu(ech->image_seq);
+		if (!si->image_seq_set) {
+			ubi->image_seq = image_seq;
+			si->image_seq_set = 1;
+		} else if (ubi->image_seq && ubi->image_seq != image_seq) {
+			ubi_err("bad image sequence number %d in PEB %d, "
+				"expected %d", image_seq, pnum, ubi->image_seq);
+			ubi_dbg_dump_ec_hdr(ech);
+			return -EINVAL;
+		}
+
 	}
 
 	/* OK, we've done with the EC header, let's look at the VID header */
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/scan.h linux-libre-2.6.31-gnu/drivers/mtd/ubi/scan.h
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/scan.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/scan.h	2009-09-09 18:13:59.000000000 -0400
@@ -102,6 +102,7 @@
  * @mean_ec: mean erase counter value
  * @ec_sum: a temporary variable used when calculating @mean_ec
  * @ec_count: a temporary variable used when calculating @mean_ec
+ * @image_seq_set: indicates @ubi->image_seq is known
  *
  * This data structure contains the result of scanning and may be used by other
  * UBI sub-systems to build final UBI data structures, further error-recovery
@@ -124,6 +125,7 @@
 	int mean_ec;
 	uint64_t ec_sum;
 	int ec_count;
+	int image_seq_set;
 };
 
 struct ubi_device;
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/ubi.h linux-libre-2.6.31-gnu/drivers/mtd/ubi/ubi.h
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/ubi.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/ubi.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/device.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
+#include <linux/notifier.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/ubi.h>
 
@@ -100,6 +101,28 @@
 	UBI_IO_BITFLIPS
 };
 
+/*
+ * Return codes of the 'ubi_eba_copy_leb()' function.
+ *
+ * MOVE_CANCEL_RACE: canceled because the volume is being deleted, the source
+ *                   PEB was put meanwhile, or there is I/O on the source PEB
+ * MOVE_SOURCE_RD_ERR: canceled because there was a read error from the source
+ *                     PEB
+ * MOVE_TARGET_RD_ERR: canceled because there was a read error from the target
+ *                     PEB
+ * MOVE_TARGET_WR_ERR: canceled because there was a write error to the target
+ *                     PEB
+ * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the
+ *                       target PEB
+ */
+enum {
+	MOVE_CANCEL_RACE = 1,
+	MOVE_SOURCE_RD_ERR,
+	MOVE_TARGET_RD_ERR,
+	MOVE_TARGET_WR_ERR,
+	MOVE_CANCEL_BITFLIPS,
+};
+
 /**
  * struct ubi_wl_entry - wear-leveling entry.
  * @u.rb: link in the corresponding (free/used) RB-tree
@@ -208,10 +231,6 @@
  * @changing_leb: %1 if the atomic LEB change ioctl command is in progress
  * @direct_writes: %1 if direct writes are enabled for this volume
  *
- * @gluebi_desc: gluebi UBI volume descriptor
- * @gluebi_refcount: reference count of the gluebi MTD device
- * @gluebi_mtd: MTD device description object of the gluebi MTD device
- *
  * The @corrupted field indicates that the volume's contents is corrupted.
  * Since UBI protects only static volumes, this field is not relevant to
  * dynamic volumes - it is user's responsibility to assure their data
@@ -255,17 +274,6 @@
 	unsigned int updating:1;
 	unsigned int changing_leb:1;
 	unsigned int direct_writes:1;
-
-#ifdef CONFIG_MTD_UBI_GLUEBI
-	/*
-	 * Gluebi-related stuff may be compiled out.
-	 * Note: this should not be built into UBI but should be a separate
-	 * ubimtd driver which works on top of UBI and emulates MTD devices.
-	 */
-	struct ubi_volume_desc *gluebi_desc;
-	int gluebi_refcount;
-	struct mtd_info gluebi_mtd;
-#endif
 };
 
 /**
@@ -293,6 +301,7 @@
  *                @vol->readers, @vol->writers, @vol->exclusive,
  *                @vol->ref_count, @vol->mapping and @vol->eba_tbl.
  * @ref_count: count of references on the UBI device
+ * @image_seq: image sequence number recorded on EC headers
  *
  * @rsvd_pebs: count of reserved physical eraseblocks
  * @avail_pebs: count of available physical eraseblocks
@@ -305,9 +314,9 @@
  * @vtbl_slots: how many slots are available in the volume table
  * @vtbl_size: size of the volume table in bytes
  * @vtbl: in-RAM volume table copy
- * @volumes_mutex: protects on-flash volume table and serializes volume
- *                 changes, like creation, deletion, update, re-size,
- *                 re-name and set property
+ * @device_mutex: protects on-flash volume table and serializes volume
+ *                creation, deletion, update, re-size, re-name and set
+ *                property
  *
  * @max_ec: current highest erase counter value
  * @mean_ec: current mean erase counter value
@@ -318,14 +327,15 @@
  * @alc_mutex: serializes "atomic LEB change" operations
  *
  * @used: RB-tree of used physical eraseblocks
+ * @erroneous: RB-tree of erroneous used physical eraseblocks
  * @free: RB-tree of free physical eraseblocks
  * @scrub: RB-tree of physical eraseblocks which need scrubbing
  * @pq: protection queue (contain physical eraseblocks which are temporarily
  *      protected from the wear-leveling worker)
  * @pq_head: protection queue head
  * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from,
- * 	     @move_to, @move_to_put @erase_pending, @wl_scheduled and @works
- * 	     fields
+ * 	     @move_to, @move_to_put @erase_pending, @wl_scheduled, @works,
+ * 	     @erroneous, and @erroneous_peb_count fields
  * @move_mutex: serializes eraseblock moves
  * @work_sem: synchronizes the WL worker with use tasks
  * @wl_scheduled: non-zero if the wear-leveling was scheduled
@@ -339,12 +349,15 @@
  * @bgt_thread: background thread description object
  * @thread_enabled: if the background thread is enabled
  * @bgt_name: background thread name
+ * @reboot_notifier: notifier to terminate background thread before rebooting
  *
  * @flash_size: underlying MTD device size (in bytes)
  * @peb_count: count of physical eraseblocks on the MTD device
  * @peb_size: physical eraseblock size
  * @bad_peb_count: count of bad physical eraseblocks
  * @good_peb_count: count of good physical eraseblocks
+ * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous
+ * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks
  * @min_io_size: minimal input/output unit size of the underlying MTD device
  * @hdrs_min_io_size: minimal I/O unit size used for VID and EC headers
  * @ro_mode: if the UBI device is in read-only mode
@@ -360,13 +373,13 @@
  * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
  * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
  *               not
+ * @nor_flash: non-zero if working on top of NOR flash
  * @mtd: MTD device descriptor
  *
  * @peb_buf1: a buffer of PEB size used for different purposes
  * @peb_buf2: another buffer of PEB size used for different purposes
  * @buf_mutex: protects @peb_buf1 and @peb_buf2
  * @ckvol_mutex: serializes static volume checking when opening
- * @mult_mutex: serializes operations on multiple volumes, like re-naming
  * @dbg_peb_buf: buffer of PEB size used for debugging
  * @dbg_buf_mutex: protects @dbg_peb_buf
  */
@@ -379,6 +392,7 @@
 	struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT];
 	spinlock_t volumes_lock;
 	int ref_count;
+	int image_seq;
 
 	int rsvd_pebs;
 	int avail_pebs;
@@ -389,7 +403,7 @@
 	int vtbl_slots;
 	int vtbl_size;
 	struct ubi_vtbl_record *vtbl;
-	struct mutex volumes_mutex;
+	struct mutex device_mutex;
 
 	int max_ec;
 	/* Note, mean_ec is not updated run-time - should be fixed */
@@ -403,6 +417,7 @@
 
 	/* Wear-leveling sub-system's stuff */
 	struct rb_root used;
+	struct rb_root erroneous;
 	struct rb_root free;
 	struct rb_root scrub;
 	struct list_head pq[UBI_PROT_QUEUE_LEN];
@@ -420,6 +435,7 @@
 	struct task_struct *bgt_thread;
 	int thread_enabled;
 	char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
+	struct notifier_block reboot_notifier;
 
 	/* I/O sub-system's stuff */
 	long long flash_size;
@@ -427,6 +443,8 @@
 	int peb_size;
 	int bad_peb_count;
 	int good_peb_count;
+	int erroneous_peb_count;
+	int max_erroneous;
 	int min_io_size;
 	int hdrs_min_io_size;
 	int ro_mode;
@@ -437,15 +455,15 @@
 	int vid_hdr_offset;
 	int vid_hdr_aloffset;
 	int vid_hdr_shift;
-	int bad_allowed;
+	unsigned int bad_allowed:1;
+	unsigned int nor_flash:1;
 	struct mtd_info *mtd;
 
 	void *peb_buf1;
 	void *peb_buf2;
 	struct mutex buf_mutex;
 	struct mutex ckvol_mutex;
-	struct mutex mult_mutex;
-#ifdef CONFIG_MTD_UBI_DEBUG
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 	void *dbg_peb_buf;
 	struct mutex dbg_buf_mutex;
 #endif
@@ -457,6 +475,7 @@
 extern const struct file_operations ubi_vol_cdev_operations;
 extern struct class *ubi_class;
 extern struct mutex ubi_devices_mutex;
+extern struct blocking_notifier_head ubi_notifiers;
 
 /* vtbl.c */
 int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
@@ -489,17 +508,6 @@
 int ubi_check_volume(struct ubi_device *ubi, int vol_id);
 void ubi_calculate_reserved(struct ubi_device *ubi);
 
-/* gluebi.c */
-#ifdef CONFIG_MTD_UBI_GLUEBI
-int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol);
-int ubi_destroy_gluebi(struct ubi_volume *vol);
-void ubi_gluebi_updated(struct ubi_volume *vol);
-#else
-#define ubi_create_gluebi(ubi, vol) 0
-#define ubi_destroy_gluebi(vol) 0
-#define ubi_gluebi_updated(vol)
-#endif
-
 /* eba.c */
 int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
 		      int lnum);
@@ -549,6 +557,16 @@
 void ubi_put_device(struct ubi_device *ubi);
 struct ubi_device *ubi_get_by_major(int major);
 int ubi_major2num(int major);
+int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol,
+		      int ntype);
+int ubi_notify_all(struct ubi_device *ubi, int ntype,
+		   struct notifier_block *nb);
+int ubi_enumerate_volumes(struct notifier_block *nb);
+
+/* kapi.c */
+void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di);
+void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
+			    struct ubi_volume_info *vi);
 
 /*
  * ubi_rb_for_each_entry - walk an RB-tree.
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/ubi-media.h linux-libre-2.6.31-gnu/drivers/mtd/ubi/ubi-media.h
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/ubi-media.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/ubi-media.h	2009-09-09 18:13:59.000000000 -0400
@@ -129,6 +129,7 @@
  * @ec: the erase counter
  * @vid_hdr_offset: where the VID header starts
  * @data_offset: where the user data start
+ * @image_seq: image sequence number
  * @padding2: reserved for future, zeroes
  * @hdr_crc: erase counter header CRC checksum
  *
@@ -144,6 +145,14 @@
  * volume identifier header and user data, relative to the beginning of the
  * physical eraseblock. These values have to be the same for all physical
  * eraseblocks.
+ *
+ * The @image_seq field is used to validate a UBI image that has been prepared
+ * for a UBI device. The @image_seq value can be any value, but it must be the
+ * same on all eraseblocks. UBI will ensure that all new erase counter headers
+ * also contain this value, and will check the value when scanning at start-up.
+ * One way to make use of @image_seq is to increase its value by one every time
+ * an image is flashed over an existing image, then, if the flashing does not
+ * complete, UBI will detect the error when scanning.
  */
 struct ubi_ec_hdr {
 	__be32  magic;
@@ -152,7 +161,8 @@
 	__be64  ec; /* Warning: the current limit is 31-bit anyway! */
 	__be32  vid_hdr_offset;
 	__be32  data_offset;
-	__u8    padding2[36];
+	__be32  image_seq;
+	__u8    padding2[32];
 	__be32  hdr_crc;
 } __attribute__ ((packed));
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/upd.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/upd.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/upd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/upd.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,10 +68,10 @@
 	       sizeof(struct ubi_vtbl_record));
 	vtbl_rec.upd_marker = 1;
 
-	mutex_lock(&ubi->volumes_mutex);
+	mutex_lock(&ubi->device_mutex);
 	err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
-	mutex_unlock(&ubi->volumes_mutex);
 	vol->upd_marker = 1;
+	mutex_unlock(&ubi->device_mutex);
 	return err;
 }
 
@@ -109,10 +109,10 @@
 			vol->last_eb_bytes = vol->usable_leb_size;
 	}
 
-	mutex_lock(&ubi->volumes_mutex);
+	mutex_lock(&ubi->device_mutex);
 	err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
-	mutex_unlock(&ubi->volumes_mutex);
 	vol->upd_marker = 0;
+	mutex_unlock(&ubi->device_mutex);
 	return err;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/vmt.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/vmt.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/vmt.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/vmt.c	2009-09-09 18:13:59.000000000 -0400
@@ -198,7 +198,7 @@
  * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume
  * and saves it in @req->vol_id. Returns zero in case of success and a negative
  * error code in case of failure. Note, the caller has to have the
- * @ubi->volumes_mutex locked.
+ * @ubi->device_mutex locked.
  */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 {
@@ -232,8 +232,8 @@
 		req->vol_id = vol_id;
 	}
 
-	dbg_gen("volume ID %d, %llu bytes, type %d, name %s",
-		vol_id, (unsigned long long)req->bytes,
+	dbg_gen("create device %d, volume %d, %llu bytes, type %d, name %s",
+		ubi->ubi_num, vol_id, (unsigned long long)req->bytes,
 		(int)req->vol_type, req->name);
 
 	/* Ensure that this volume does not exist */
@@ -317,10 +317,6 @@
 		goto out_mapping;
 	}
 
-	err = ubi_create_gluebi(ubi, vol);
-	if (err)
-		goto out_cdev;
-
 	vol->dev.release = vol_release;
 	vol->dev.parent = &ubi->dev;
 	vol->dev.devt = dev;
@@ -330,7 +326,7 @@
 	err = device_register(&vol->dev);
 	if (err) {
 		ubi_err("cannot register device");
-		goto out_gluebi;
+		goto out_cdev;
 	}
 
 	err = volume_sysfs_init(ubi, vol);
@@ -358,7 +354,9 @@
 	ubi->vol_count += 1;
 	spin_unlock(&ubi->volumes_lock);
 
-	err = paranoid_check_volumes(ubi);
+	ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED);
+	if (paranoid_check_volumes(ubi))
+		dbg_err("check failed while creating volume %d", vol_id);
 	return err;
 
 out_sysfs:
@@ -373,10 +371,6 @@
 	do_free = 0;
 	get_device(&vol->dev);
 	volume_sysfs_close(vol);
-out_gluebi:
-	if (ubi_destroy_gluebi(vol))
-		dbg_err("cannot destroy gluebi for volume %d:%d",
-			ubi->ubi_num, vol_id);
 out_cdev:
 	cdev_del(&vol->cdev);
 out_mapping:
@@ -403,7 +397,7 @@
  *
  * This function removes volume described by @desc. The volume has to be opened
  * in "exclusive" mode. Returns zero in case of success and a negative error
- * code in case of failure. The caller has to have the @ubi->volumes_mutex
+ * code in case of failure. The caller has to have the @ubi->device_mutex
  * locked.
  */
 int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
@@ -412,7 +406,7 @@
 	struct ubi_device *ubi = vol->ubi;
 	int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs;
 
-	dbg_gen("remove UBI volume %d", vol_id);
+	dbg_gen("remove device %d, volume %d", ubi->ubi_num, vol_id);
 	ubi_assert(desc->mode == UBI_EXCLUSIVE);
 	ubi_assert(vol == ubi->volumes[vol_id]);
 
@@ -431,10 +425,6 @@
 	ubi->volumes[vol_id] = NULL;
 	spin_unlock(&ubi->volumes_lock);
 
-	err = ubi_destroy_gluebi(vol);
-	if (err)
-		goto out_err;
-
 	if (!no_vtbl) {
 		err = ubi_change_vtbl_record(ubi, vol_id, NULL);
 		if (err)
@@ -465,8 +455,10 @@
 	ubi->vol_count -= 1;
 	spin_unlock(&ubi->volumes_lock);
 
-	if (!no_vtbl)
-		err = paranoid_check_volumes(ubi);
+	ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED);
+	if (!no_vtbl && paranoid_check_volumes(ubi))
+		dbg_err("check failed while removing volume %d", vol_id);
+
 	return err;
 
 out_err:
@@ -485,7 +477,7 @@
  *
  * This function re-sizes the volume and returns zero in case of success, and a
  * negative error code in case of failure. The caller has to have the
- * @ubi->volumes_mutex locked.
+ * @ubi->device_mutex locked.
  */
 int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
 {
@@ -498,8 +490,8 @@
 	if (ubi->ro_mode)
 		return -EROFS;
 
-	dbg_gen("re-size volume %d to from %d to %d PEBs",
-		vol_id, vol->reserved_pebs, reserved_pebs);
+	dbg_gen("re-size device %d, volume %d to from %d to %d PEBs",
+		ubi->ubi_num, vol_id, vol->reserved_pebs, reserved_pebs);
 
 	if (vol->vol_type == UBI_STATIC_VOLUME &&
 	    reserved_pebs < vol->used_ebs) {
@@ -587,7 +579,9 @@
 			(long long)vol->used_ebs * vol->usable_leb_size;
 	}
 
-	err = paranoid_check_volumes(ubi);
+	ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED);
+	if (paranoid_check_volumes(ubi))
+		dbg_err("check failed while re-sizing volume %d", vol_id);
 	return err;
 
 out_acc:
@@ -632,11 +626,12 @@
 			vol->name_len = re->new_name_len;
 			memcpy(vol->name, re->new_name, re->new_name_len + 1);
 			spin_unlock(&ubi->volumes_lock);
+			ubi_volume_notify(ubi, vol, UBI_VOLUME_RENAMED);
 		}
 	}
 
-	if (!err)
-		err = paranoid_check_volumes(ubi);
+	if (!err && paranoid_check_volumes(ubi))
+		;
 	return err;
 }
 
@@ -667,10 +662,6 @@
 		return err;
 	}
 
-	err = ubi_create_gluebi(ubi, vol);
-	if (err)
-		goto out_cdev;
-
 	vol->dev.release = vol_release;
 	vol->dev.parent = &ubi->dev;
 	vol->dev.devt = dev;
@@ -678,21 +669,19 @@
 	dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
 	err = device_register(&vol->dev);
 	if (err)
-		goto out_gluebi;
+		goto out_cdev;
 
 	err = volume_sysfs_init(ubi, vol);
 	if (err) {
 		cdev_del(&vol->cdev);
-		err = ubi_destroy_gluebi(vol);
 		volume_sysfs_close(vol);
 		return err;
 	}
 
-	err = paranoid_check_volumes(ubi);
+	if (paranoid_check_volumes(ubi))
+		dbg_err("check failed while adding volume %d", vol_id);
 	return err;
 
-out_gluebi:
-	err = ubi_destroy_gluebi(vol);
 out_cdev:
 	cdev_del(&vol->cdev);
 	return err;
@@ -708,12 +697,9 @@
  */
 void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
 {
-	int err;
-
 	dbg_gen("free volume %d", vol->vol_id);
 
 	ubi->volumes[vol->vol_id] = NULL;
-	err = ubi_destroy_gluebi(vol);
 	cdev_del(&vol->cdev);
 	volume_sysfs_close(vol);
 }
@@ -868,6 +854,7 @@
 	if (vol)
 		ubi_dbg_dump_vol_info(vol);
 	ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
+	dump_stack();
 	spin_unlock(&ubi->volumes_lock);
 	return -EINVAL;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/mtd/ubi/wl.c linux-libre-2.6.31-gnu/drivers/mtd/ubi/wl.c
--- linux-libre-2.6.30-gnu/drivers/mtd/ubi/wl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/mtd/ubi/wl.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,8 +55,8 @@
  *
  * As it was said, for the UBI sub-system all physical eraseblocks are either
  * "free" or "used". Free eraseblock are kept in the @wl->free RB-tree, while
- * used eraseblocks are kept in @wl->used or @wl->scrub RB-trees, or
- * (temporarily) in the @wl->pq queue.
+ * used eraseblocks are kept in @wl->used, @wl->erroneous, or @wl->scrub
+ * RB-trees, as well as (temporarily) in the @wl->pq queue.
  *
  * When the WL sub-system returns a physical eraseblock, the physical
  * eraseblock is protected from being moved for some "time". For this reason,
@@ -83,6 +83,8 @@
  * used. The former state corresponds to the @wl->free tree. The latter state
  * is split up on several sub-states:
  * o the WL movement is allowed (@wl->used tree);
+ * o the WL movement is disallowed (@wl->erroneous) because the PEB is
+ *   erroneous - e.g., there was a read error;
  * o the WL movement is temporarily prohibited (@wl->pq queue);
  * o scrubbing is needed (@wl->scrub tree).
  *
@@ -457,6 +459,14 @@
 	dbg_wl("PEB %d EC %d", e->pnum, e->ec);
 	prot_queue_add(ubi, e);
 	spin_unlock(&ubi->wl_lock);
+
+	err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
+				   ubi->peb_size - ubi->vid_hdr_aloffset);
+	if (err) {
+		ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
+		return err > 0 ? -EINVAL : err;
+	}
+
 	return e->pnum;
 }
 
@@ -653,7 +663,8 @@
 static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 				int cancel)
 {
-	int err, scrubbing = 0, torture = 0;
+	int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
+	int vol_id = -1, uninitialized_var(lnum);
 	struct ubi_wl_entry *e1, *e2;
 	struct ubi_vid_hdr *vid_hdr;
 
@@ -738,68 +749,78 @@
 			/*
 			 * We are trying to move PEB without a VID header. UBI
 			 * always write VID headers shortly after the PEB was
-			 * given, so we have a situation when it did not have
-			 * chance to write it down because it was preempted.
-			 * Just re-schedule the work, so that next time it will
-			 * likely have the VID header in place.
+			 * given, so we have a situation when it has not yet
+			 * had a chance to write it, because it was preempted.
+			 * So add this PEB to the protection queue so far,
+			 * because presumably more data will be written there
+			 * (including the missing VID header), and then we'll
+			 * move it.
 			 */
 			dbg_wl("PEB %d has no VID header", e1->pnum);
+			protect = 1;
 			goto out_not_moved;
 		}
 
 		ubi_err("error %d while reading VID header from PEB %d",
 			err, e1->pnum);
-		if (err > 0)
-			err = -EIO;
 		goto out_error;
 	}
 
+	vol_id = be32_to_cpu(vid_hdr->vol_id);
+	lnum = be32_to_cpu(vid_hdr->lnum);
+
 	err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vid_hdr);
 	if (err) {
-		if (err == -EAGAIN)
+		if (err == MOVE_CANCEL_RACE) {
+			/*
+			 * The LEB has not been moved because the volume is
+			 * being deleted or the PEB has been put meanwhile. We
+			 * should prevent this PEB from being selected for
+			 * wear-leveling movement again, so put it to the
+			 * protection queue.
+			 */
+			protect = 1;
 			goto out_not_moved;
-		if (err < 0)
-			goto out_error;
-		if (err == 2) {
-			/* Target PEB write error, torture it */
+		}
+
+		if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
+		    err == MOVE_TARGET_RD_ERR) {
+			/*
+			 * Target PEB had bit-flips or write error - torture it.
+			 */
 			torture = 1;
 			goto out_not_moved;
 		}
 
-		/*
-		 * The LEB has not been moved because the volume is being
-		 * deleted or the PEB has been put meanwhile. We should prevent
-		 * this PEB from being selected for wear-leveling movement
-		 * again, so put it to the protection queue.
-		 */
-
-		dbg_wl("canceled moving PEB %d", e1->pnum);
-		ubi_assert(err == 1);
-
-		ubi_free_vid_hdr(ubi, vid_hdr);
-		vid_hdr = NULL;
-
-		spin_lock(&ubi->wl_lock);
-		prot_queue_add(ubi, e1);
-		ubi_assert(!ubi->move_to_put);
-		ubi->move_from = ubi->move_to = NULL;
-		ubi->wl_scheduled = 0;
-		spin_unlock(&ubi->wl_lock);
+		if (err == MOVE_SOURCE_RD_ERR) {
+			/*
+			 * An error happened while reading the source PEB. Do
+			 * not switch to R/O mode in this case, and give the
+			 * upper layers a possibility to recover from this,
+			 * e.g. by unmapping corresponding LEB. Instead, just
+			 * put this PEB to the @ubi->erroneous list to prevent
+			 * UBI from trying to move it over and over again.
+			 */
+			if (ubi->erroneous_peb_count > ubi->max_erroneous) {
+				ubi_err("too many erroneous eraseblocks (%d)",
+					ubi->erroneous_peb_count);
+				goto out_error;
+			}
+			erroneous = 1;
+			goto out_not_moved;
+		}
 
-		e1 = NULL;
-		err = schedule_erase(ubi, e2, 0);
-		if (err)
+		if (err < 0)
 			goto out_error;
-		mutex_unlock(&ubi->move_mutex);
-		return 0;
+
+		ubi_assert(0);
 	}
 
 	/* The PEB has been successfully moved */
-	ubi_free_vid_hdr(ubi, vid_hdr);
-	vid_hdr = NULL;
 	if (scrubbing)
-		ubi_msg("scrubbed PEB %d, data moved to PEB %d",
-			e1->pnum, e2->pnum);
+		ubi_msg("scrubbed PEB %d (LEB %d:%d), data moved to PEB %d",
+			e1->pnum, vol_id, lnum, e2->pnum);
+	ubi_free_vid_hdr(ubi, vid_hdr);
 
 	spin_lock(&ubi->wl_lock);
 	if (!ubi->move_to_put) {
@@ -812,8 +833,10 @@
 
 	err = schedule_erase(ubi, e1, 0);
 	if (err) {
-		e1 = NULL;
-		goto out_error;
+		kmem_cache_free(ubi_wl_entry_slab, e1);
+		if (e2)
+			kmem_cache_free(ubi_wl_entry_slab, e2);
+		goto out_ro;
 	}
 
 	if (e2) {
@@ -821,10 +844,13 @@
 		 * Well, the target PEB was put meanwhile, schedule it for
 		 * erasure.
 		 */
-		dbg_wl("PEB %d was put meanwhile, erase", e2->pnum);
+		dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase",
+		       e2->pnum, vol_id, lnum);
 		err = schedule_erase(ubi, e2, 0);
-		if (err)
-			goto out_error;
+		if (err) {
+			kmem_cache_free(ubi_wl_entry_slab, e2);
+			goto out_ro;
+		}
 	}
 
 	dbg_wl("done");
@@ -837,11 +863,19 @@
 	 * have been changed, schedule it for erasure.
 	 */
 out_not_moved:
-	dbg_wl("canceled moving PEB %d", e1->pnum);
-	ubi_free_vid_hdr(ubi, vid_hdr);
-	vid_hdr = NULL;
+	if (vol_id != -1)
+		dbg_wl("cancel moving PEB %d (LEB %d:%d) to PEB %d (%d)",
+		       e1->pnum, vol_id, lnum, e2->pnum, err);
+	else
+		dbg_wl("cancel moving PEB %d to PEB %d (%d)",
+		       e1->pnum, e2->pnum, err);
 	spin_lock(&ubi->wl_lock);
-	if (scrubbing)
+	if (protect)
+		prot_queue_add(ubi, e1);
+	else if (erroneous) {
+		wl_tree_add(e1, &ubi->erroneous);
+		ubi->erroneous_peb_count += 1;
+	} else if (scrubbing)
 		wl_tree_add(e1, &ubi->scrub);
 	else
 		wl_tree_add(e1, &ubi->used);
@@ -850,32 +884,36 @@
 	ubi->wl_scheduled = 0;
 	spin_unlock(&ubi->wl_lock);
 
-	e1 = NULL;
+	ubi_free_vid_hdr(ubi, vid_hdr);
 	err = schedule_erase(ubi, e2, torture);
-	if (err)
-		goto out_error;
-
+	if (err) {
+		kmem_cache_free(ubi_wl_entry_slab, e2);
+		goto out_ro;
+	}
 	mutex_unlock(&ubi->move_mutex);
 	return 0;
 
 out_error:
-	ubi_err("error %d while moving PEB %d to PEB %d",
-		err, e1->pnum, e2->pnum);
-
-	ubi_free_vid_hdr(ubi, vid_hdr);
+	if (vol_id != -1)
+		ubi_err("error %d while moving PEB %d to PEB %d",
+			err, e1->pnum, e2->pnum);
+	else
+		ubi_err("error %d while moving PEB %d (LEB %d:%d) to PEB %d",
+			err, e1->pnum, vol_id, lnum, e2->pnum);
 	spin_lock(&ubi->wl_lock);
 	ubi->move_from = ubi->move_to = NULL;
 	ubi->move_to_put = ubi->wl_scheduled = 0;
 	spin_unlock(&ubi->wl_lock);
 
-	if (e1)
-		kmem_cache_free(ubi_wl_entry_slab, e1);
-	if (e2)
-		kmem_cache_free(ubi_wl_entry_slab, e2);
-	ubi_ro_mode(ubi);
+	ubi_free_vid_hdr(ubi, vid_hdr);
+	kmem_cache_free(ubi_wl_entry_slab, e1);
+	kmem_cache_free(ubi_wl_entry_slab, e2);
 
+out_ro:
+	ubi_ro_mode(ubi);
 	mutex_unlock(&ubi->move_mutex);
-	return err;
+	ubi_assert(err != 0);
+	return err < 0 ? err : -EIO;
 
 out_cancel:
 	ubi->wl_scheduled = 0;
@@ -1015,7 +1053,7 @@
 		/*
 		 * If this is not %-EIO, we have no idea what to do. Scheduling
 		 * this physical eraseblock for erasure again would cause
-		 * errors again and again. Well, lets switch to RO mode.
+		 * errors again and again. Well, lets switch to R/O mode.
 		 */
 		goto out_ro;
 	}
@@ -1043,10 +1081,9 @@
 		ubi_err("no reserved physical eraseblocks");
 		goto out_ro;
 	}
-
 	spin_unlock(&ubi->volumes_lock);
-	ubi_msg("mark PEB %d as bad", pnum);
 
+	ubi_msg("mark PEB %d as bad", pnum);
 	err = ubi_io_mark_bad(ubi, pnum);
 	if (err)
 		goto out_ro;
@@ -1056,7 +1093,9 @@
 	ubi->bad_peb_count += 1;
 	ubi->good_peb_count -= 1;
 	ubi_calculate_reserved(ubi);
-	if (ubi->beb_rsvd_pebs == 0)
+	if (ubi->beb_rsvd_pebs)
+		ubi_msg("%d PEBs left in the reserve", ubi->beb_rsvd_pebs);
+	else
 		ubi_warn("last PEB from the reserved pool was used");
 	spin_unlock(&ubi->volumes_lock);
 
@@ -1125,6 +1164,13 @@
 		} else if (in_wl_tree(e, &ubi->scrub)) {
 			paranoid_check_in_wl_tree(e, &ubi->scrub);
 			rb_erase(&e->u.rb, &ubi->scrub);
+		} else if (in_wl_tree(e, &ubi->erroneous)) {
+			paranoid_check_in_wl_tree(e, &ubi->erroneous);
+			rb_erase(&e->u.rb, &ubi->erroneous);
+			ubi->erroneous_peb_count -= 1;
+			ubi_assert(ubi->erroneous_peb_count >= 0);
+			/* Erroneous PEBs should be tortured */
+			torture = 1;
 		} else {
 			err = prot_queue_del(ubi, e->pnum);
 			if (err) {
@@ -1373,7 +1419,7 @@
 	struct ubi_scan_leb *seb, *tmp;
 	struct ubi_wl_entry *e;
 
-	ubi->used = ubi->free = ubi->scrub = RB_ROOT;
+	ubi->used = ubi->erroneous = ubi->free = ubi->scrub = RB_ROOT;
 	spin_lock_init(&ubi->wl_lock);
 	mutex_init(&ubi->move_mutex);
 	init_rwsem(&ubi->work_sem);
@@ -1511,6 +1557,7 @@
 	cancel_pending(ubi);
 	protection_queue_destroy(ubi);
 	tree_destroy(&ubi->used);
+	tree_destroy(&ubi->erroneous);
 	tree_destroy(&ubi->free);
 	tree_destroy(&ubi->scrub);
 	kfree(ubi->lookuptbl);
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c501.c linux-libre-2.6.31-gnu/drivers/net/3c501.c
--- linux-libre-2.6.30-gnu/drivers/net/3c501.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c501.c	2009-09-09 18:13:59.000000000 -0400
@@ -281,7 +281,7 @@
 		autoirq = probe_irq_off(irq_mask);
 
 		if (autoirq == 0) {
-			printk(KERN_WARNING "%s probe at %#x failed to detect IRQ line.\n",
+			pr_warning("%s probe at %#x failed to detect IRQ line.\n",
 				mname, ioaddr);
 			release_region(ioaddr, EL1_IO_EXTENT);
 			return -EAGAIN;
@@ -297,16 +297,16 @@
 	if (autoirq)
 		dev->irq = autoirq;
 
-	printk(KERN_INFO "%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
+	pr_info("%s: %s EtherLink at %#lx, using %sIRQ %d.\n",
 			dev->name, mname, dev->base_addr,
 			autoirq ? "auto":"assigned ", dev->irq);
 
 #ifdef CONFIG_IP_MULTICAST
-	printk(KERN_WARNING "WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
+	pr_warning("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
 #endif
 
 	if (el_debug)
-		printk(KERN_DEBUG "%s", version);
+		pr_debug("%s", version);
 
 	lp = netdev_priv(dev);
 	memset(lp, 0, sizeof(struct net_local));
@@ -343,7 +343,7 @@
 	unsigned long flags;
 
 	if (el_debug > 2)
-		printk(KERN_DEBUG "%s: Doing el_open()...", dev->name);
+		pr_debug("%s: Doing el_open()...\n", dev->name);
 
 	retval = request_irq(dev->irq, &el_interrupt, 0, dev->name, dev);
 	if (retval)
@@ -374,7 +374,7 @@
 	int ioaddr = dev->base_addr;
 
 	if (el_debug)
-		printk(KERN_DEBUG "%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
+		pr_debug("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
 			dev->name, inb(TX_STATUS),
 			inb(AX_STATUS), inb(RX_STATUS));
 	dev->stats.tx_errors++;
@@ -483,14 +483,13 @@
 			lp->loading = 0;
 			dev->trans_start = jiffies;
 			if (el_debug > 2)
-				printk(KERN_DEBUG " queued xmit.\n");
+				pr_debug(" queued xmit.\n");
 			dev_kfree_skb(skb);
 			return 0;
 		}
 		/* A receive upset our load, despite our best efforts */
 		if (el_debug > 2)
-			printk(KERN_DEBUG "%s: burped during tx load.\n",
-				dev->name);
+			pr_debug("%s: burped during tx load.\n", dev->name);
 		spin_lock_irqsave(&lp->lock, flags);
 	} while (1);
 }
@@ -540,11 +539,10 @@
 	 */
 
 	if (el_debug > 3)
-		printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x",
-							dev->name, axsr);
+		pr_debug("%s: el_interrupt() aux=%#02x\n", dev->name, axsr);
 
 	if (lp->loading == 1 && !lp->txing)
-		printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n",
+		pr_warning("%s: Inconsistent state loading while not in tx\n",
 			dev->name);
 
 	if (lp->txing) {
@@ -555,19 +553,17 @@
 		int txsr = inb(TX_STATUS);
 
 		if (lp->loading == 1) {
-			if (el_debug > 2) {
-				printk(KERN_DEBUG "%s: Interrupt while loading [",
-					dev->name);
-				printk(" txsr=%02x gp=%04x rp=%04x]\n",
-					txsr, inw(GP_LOW), inw(RX_LOW));
-			}
+			if (el_debug > 2)
+				pr_debug("%s: Interrupt while loading [txsr=%02x gp=%04x rp=%04x]\n",
+					dev->name, txsr, inw(GP_LOW), inw(RX_LOW));
+
 			/* Force a reload */
 			lp->loading = 2;
 			spin_unlock(&lp->lock);
 			goto out;
 		}
 		if (el_debug > 6)
-			printk(KERN_DEBUG " txsr=%02x gp=%04x rp=%04x",
+			pr_debug("%s: txsr=%02x gp=%04x rp=%04x\n", dev->name,
 					txsr, inw(GP_LOW), inw(RX_LOW));
 
 		if ((axsr & 0x80) && (txsr & TX_READY) == 0) {
@@ -576,7 +572,7 @@
 			 *	on trying or reset immediately ?
 			 */
 			if (el_debug > 1)
-				printk(KERN_DEBUG "%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n",
+				pr_debug("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x gp=%03x rp=%03x.\n",
 					dev->name, txsr, axsr,
 					inw(ioaddr + EL1_DATAPTR),
 					inw(ioaddr + EL1_RXPTR));
@@ -587,7 +583,7 @@
 			 *	Timed out
 			 */
 			if (el_debug)
-				printk(KERN_DEBUG "%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name);
+				pr_debug("%s: Transmit failed 16 times, Ethernet jammed?\n", dev->name);
 			outb(AX_SYS, AX_CMD);
 			lp->txing = 0;
 			dev->stats.tx_aborted_errors++;
@@ -598,7 +594,7 @@
 			 */
 
 			if (el_debug > 6)
-				printk(KERN_DEBUG " retransmitting after a collision.\n");
+				pr_debug("%s: retransmitting after a collision.\n", dev->name);
 			/*
 			 *	Poor little chip can't reset its own start
 			 *	pointer
@@ -616,9 +612,8 @@
 			 */
 			dev->stats.tx_packets++;
 			if (el_debug > 6)
-				printk(KERN_DEBUG " Tx succeeded %s\n",
-					(txsr & TX_RDY) ? "." :
-							"but tx is busy!");
+				pr_debug("%s: Tx succeeded %s\n", dev->name,
+					(txsr & TX_RDY) ? "." : "but tx is busy!");
 			/*
 			 *	This is safe the interrupt is atomic WRT itself.
 			 */
@@ -633,7 +628,8 @@
 
 		int rxsr = inb(RX_STATUS);
 		if (el_debug > 5)
-			printk(KERN_DEBUG " rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS), inw(RX_LOW));
+			pr_debug("%s: rxsr=%02x txsr=%02x rp=%04x\n",
+				dev->name, rxsr, inb(TX_STATUS), inw(RX_LOW));
 		/*
 		 *	Just reading rx_status fixes most errors.
 		 */
@@ -643,7 +639,7 @@
 			/* Handled to avoid board lock-up. */
 			dev->stats.rx_length_errors++;
 			if (el_debug > 5)
-				printk(KERN_DEBUG " runt.\n");
+				pr_debug("%s: runt.\n", dev->name);
 		} else if (rxsr & RX_GOOD) {
 			/*
 			 *	Receive worked.
@@ -654,12 +650,10 @@
 			 *	Nothing?  Something is broken!
 			 */
 			if (el_debug > 2)
-				printk(KERN_DEBUG "%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
+				pr_debug("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
 					dev->name, rxsr);
 			el_reset(dev);
 		}
-		if (el_debug > 3)
-			printk(KERN_DEBUG ".\n");
 	}
 
 	/*
@@ -695,11 +689,11 @@
 	pkt_len = inw(RX_LOW);
 
 	if (el_debug > 4)
-		printk(KERN_DEBUG " el_receive %d.\n", pkt_len);
+		pr_debug(" el_receive %d.\n", pkt_len);
 
 	if (pkt_len < 60 || pkt_len > 1536) {
 		if (el_debug)
-			printk(KERN_DEBUG "%s: bogus packet, length=%d\n",
+			pr_debug("%s: bogus packet, length=%d\n",
 						dev->name, pkt_len);
 		dev->stats.rx_over_errors++;
 		return;
@@ -718,8 +712,7 @@
 
 	outw(0x00, GP_LOW);
 	if (skb == NULL) {
-		printk(KERN_INFO "%s: Memory squeeze, dropping packet.\n",
-								dev->name);
+		pr_info("%s: Memory squeeze, dropping packet.\n", dev->name);
 		dev->stats.rx_dropped++;
 		return;
 	} else {
@@ -753,7 +746,7 @@
 	int ioaddr = dev->base_addr;
 
 	if (el_debug > 2)
-		printk(KERN_INFO "3c501 reset...");
+		pr_info("3c501 reset...\n");
 	outb(AX_RESET, AX_CMD);		/* Reset the chip */
 	/* Aux control, irq and loopback enabled */
 	outb(AX_LOOP, AX_CMD);
@@ -787,7 +780,7 @@
 	int ioaddr = dev->base_addr;
 
 	if (el_debug > 2)
-		printk(KERN_INFO "%s: Shutting down Ethernet card at %#x.\n",
+		pr_info("%s: Shutting down Ethernet card at %#x.\n",
 						dev->name, ioaddr);
 
 	netif_stop_queue(dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c503.c linux-libre-2.6.31-gnu/drivers/net/3c503.c
--- linux-libre-2.6.30-gnu/drivers/net/3c503.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c503.c	2009-09-09 18:13:59.000000000 -0400
@@ -234,16 +234,16 @@
     }
 
     if (ei_debug  &&  version_printed++ == 0)
-	printk(version);
+	pr_debug("%s", version);
 
     dev->base_addr = ioaddr;
 
-    printk("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);
+    pr_info("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);
 
     /* Retrieve and print the ethernet address. */
     for (i = 0; i < 6; i++)
 	dev->dev_addr[i] = inb(ioaddr + i);
-    printk("%pM", dev->dev_addr);
+    pr_cont("%pM", dev->dev_addr);
 
     /* Map the 8390 back into the window. */
     outb(ECNTRL_THIN, ioaddr + 0x406);
@@ -256,7 +256,8 @@
     outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
 
     /* Probe for, turn on and clear the board's shared memory. */
-    if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg);
+    if (ei_debug > 2)
+	pr_cont(" memory jumpers %2.2x ", membase_reg);
     outb(EGACFR_NORM, ioaddr + 0x405);	/* Enable RAM */
 
     /* This should be probed for (or set via an ioctl()) at run-time.
@@ -268,7 +269,7 @@
 #else
     ei_status.interface_num = dev->mem_end & 0xf;
 #endif
-    printk(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");
+    pr_cont(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");
 
     if ((membase_reg & 0xf0) == 0) {
 	dev->mem_start = 0;
@@ -292,7 +293,7 @@
 		writel(test_val, mem_base + i);
 		if (readl(mem_base) != 0xba5eba5e
 		    || readl(mem_base + i) != test_val) {
-		    printk("3c503: memory failure or memory address conflict.\n");
+		    pr_warning("3c503: memory failure or memory address conflict.\n");
 		    dev->mem_start = 0;
 		    ei_status.name = "3c503-PIO";
 		    iounmap(mem_base);
@@ -344,7 +345,7 @@
     if (dev->irq == 2)
 	dev->irq = 9;
     else if (dev->irq > 5 && dev->irq != 9) {
-	printk("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
+	pr_warning("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
 	       dev->irq);
 	dev->irq = 0;
     }
@@ -359,7 +360,7 @@
 	goto out1;
 
     if (dev->mem_start)
-	printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
+	pr_info("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
 		dev->name, ei_status.name, (wordlength+1)<<3,
 		dev->mem_start, dev->mem_end-1);
 
@@ -367,7 +368,7 @@
     {
 	ei_status.tx_start_page = EL2_MB1_START_PG;
 	ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
-	printk("\n%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
+	pr_info("%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
 	       dev->name, ei_status.name, (wordlength+1)<<3);
     }
     release_region(ioaddr + 0x400, 8);
@@ -435,15 +436,16 @@
 el2_reset_8390(struct net_device *dev)
 {
     if (ei_debug > 1) {
-	printk("%s: Resetting the 3c503 board...", dev->name);
-	printk("%#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
+	pr_debug("%s: Resetting the 3c503 board...", dev->name);
+	pr_cont(" %#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
 	       E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));
     }
     outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);
     ei_status.txing = 0;
     outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
     el2_init_card(dev);
-    if (ei_debug > 1) printk("done\n");
+    if (ei_debug > 1)
+	pr_cont("done\n");
 }
 
 /* Initialize the 3c503 GA registers after a reset. */
@@ -529,7 +531,7 @@
         {
             if(!boguscount--)
             {
-                printk("%s: FIFO blocked in el2_block_output.\n", dev->name);
+                pr_notice("%s: FIFO blocked in el2_block_output.\n", dev->name);
                 el2_reset_8390(dev);
                 goto blocked;
             }
@@ -581,7 +583,7 @@
     {
         if(!boguscount--)
         {
-            printk("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
+            pr_notice("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
             memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr));
             el2_reset_8390(dev);
             goto blocked;
@@ -645,7 +647,7 @@
         {
             if(!boguscount--)
             {
-                printk("%s: FIFO blocked in el2_block_input.\n", dev->name);
+                pr_notice("%s: FIFO blocked in el2_block_input.\n", dev->name);
                 el2_reset_8390(dev);
                 goto blocked;
             }
@@ -707,7 +709,7 @@
 	for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
 		if (io[this_dev] == 0)  {
 			if (this_dev != 0) break; /* only autoprobe 1st one */
-			printk(KERN_NOTICE "3c503.c: Presently autoprobing (not recommended) for a single card.\n");
+			pr_notice("3c503.c: Presently autoprobing (not recommended) for a single card.\n");
 		}
 		dev = alloc_eip_netdev();
 		if (!dev)
@@ -720,7 +722,7 @@
 			continue;
 		}
 		free_netdev(dev);
-		printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
+		pr_warning("3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
 		break;
 	}
 	if (found)
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c505.c linux-libre-2.6.31-gnu/drivers/net/3c505.c
--- linux-libre-2.6.30-gnu/drivers/net/3c505.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c505.c	2009-09-09 18:13:59.000000000 -0400
@@ -126,26 +126,25 @@
  *
  *********************************************************/
 
-static const char filename[] = __FILE__;
+#define filename __FILE__
 
-static const char timeout_msg[] = "*** timeout at %s:%s (line %d) ***\n";
+#define timeout_msg "*** timeout at %s:%s (line %d) ***\n"
 #define TIMEOUT_MSG(lineno) \
-	printk(timeout_msg, filename,__func__,(lineno))
+	pr_notice(timeout_msg, filename, __func__, (lineno))
 
-static const char invalid_pcb_msg[] =
-"*** invalid pcb length %d at %s:%s (line %d) ***\n";
+#define invalid_pcb_msg "*** invalid pcb length %d at %s:%s (line %d) ***\n"
 #define INVALID_PCB_MSG(len) \
-	printk(invalid_pcb_msg, (len),filename,__func__,__LINE__)
+	pr_notice(invalid_pcb_msg, (len), filename, __func__, __LINE__)
 
-static char search_msg[] __initdata = KERN_INFO "%s: Looking for 3c505 adapter at address %#x...";
+#define search_msg "%s: Looking for 3c505 adapter at address %#x..."
 
-static char stilllooking_msg[] __initdata = "still looking...";
+#define stilllooking_msg "still looking..."
 
-static char found_msg[] __initdata = "found.\n";
+#define found_msg "found.\n"
 
-static char notfound_msg[] __initdata = "not found (reason = %d)\n";
+#define notfound_msg "not found (reason = %d)\n"
 
-static char couldnot_msg[] __initdata = KERN_INFO "%s: 3c505 not found\n";
+#define couldnot_msg "%s: 3c505 not found\n"
 
 /*********************************************************
  *
@@ -284,7 +283,7 @@
 
 	outb_control(orig_hcr, dev);
 	if (!start_receive(dev, &adapter->tx_pcb))
-		printk(KERN_ERR "%s: start receive command failed \n", dev->name);
+		pr_err("%s: start receive command failed\n", dev->name);
 }
 
 /* Check to make sure that a DMA transfer hasn't timed out.  This should
@@ -296,7 +295,9 @@
 	elp_device *adapter = netdev_priv(dev);
 	if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) {
 		unsigned long flags, f;
-		printk(KERN_ERR "%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma));
+		pr_err("%s: DMA %s timed out, %d bytes left\n", dev->name,
+			adapter->current_dma.direction ? "download" : "upload",
+			get_dma_residue(dev->dma));
 		spin_lock_irqsave(&adapter->lock, flags);
 		adapter->dmaing = 0;
 		adapter->busy = 0;
@@ -321,7 +322,7 @@
 		if (inb_status(base_addr) & HCRE)
 			return false;
 	}
-	printk(KERN_WARNING "3c505: send_pcb_slow timed out\n");
+	pr_warning("3c505: send_pcb_slow timed out\n");
 	return true;
 }
 
@@ -333,7 +334,7 @@
 		if (inb_status(base_addr) & HCRE)
 			return false;
 	}
-	printk(KERN_WARNING "3c505: send_pcb_fast timed out\n");
+	pr_warning("3c505: send_pcb_fast timed out\n");
 	return true;
 }
 
@@ -386,7 +387,7 @@
 	/* Avoid contention */
 	if (test_and_set_bit(1, &adapter->send_pcb_semaphore)) {
 		if (elp_debug >= 3) {
-			printk(KERN_DEBUG "%s: send_pcb entered while threaded\n", dev->name);
+			pr_debug("%s: send_pcb entered while threaded\n", dev->name);
 		}
 		return false;
 	}
@@ -424,14 +425,15 @@
 
 		case ASF_PCB_NAK:
 #ifdef ELP_DEBUG
-			printk(KERN_DEBUG "%s: send_pcb got NAK\n", dev->name);
+			pr_debug("%s: send_pcb got NAK\n", dev->name);
 #endif
 			goto abort;
 		}
 	}
 
 	if (elp_debug >= 1)
-		printk(KERN_DEBUG "%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr));
+		pr_debug("%s: timeout waiting for PCB acknowledge (status %02x)\n",
+			dev->name, inb_status(dev->base_addr));
 	goto abort;
 
       sti_abort:
@@ -481,7 +483,7 @@
 	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
 	if (time_after_eq(jiffies, timeout)) {
 		TIMEOUT_MSG(__LINE__);
-		printk(KERN_INFO "%s: status %02x\n", dev->name, stat);
+		pr_info("%s: status %02x\n", dev->name, stat);
 		return false;
 	}
 	pcb->length = inb_command(dev->base_addr);
@@ -518,7 +520,7 @@
 	/* safety check total length vs data length */
 	if (total_length != (pcb->length + 2)) {
 		if (elp_debug >= 2)
-			printk(KERN_WARNING "%s: mangled PCB received\n", dev->name);
+			pr_warning("%s: mangled PCB received\n", dev->name);
 		set_hsf(dev, HSF_PCB_NAK);
 		return false;
 	}
@@ -527,7 +529,7 @@
 		if (test_and_set_bit(0, (void *) &adapter->busy)) {
 			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {
 				set_hsf(dev, HSF_PCB_NAK);
-				printk(KERN_WARNING "%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
+				pr_warning("%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
 				pcb->command = 0;
 				return true;
 			} else {
@@ -552,7 +554,7 @@
 	elp_device *adapter = netdev_priv(dev);
 
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: restarting receiver\n", dev->name);
+		pr_debug("%s: restarting receiver\n", dev->name);
 	tx_pcb->command = CMD_RECEIVE_PACKET;
 	tx_pcb->length = sizeof(struct Rcv_pkt);
 	tx_pcb->data.rcv_pkt.buf_seg
@@ -586,7 +588,7 @@
 	skb = dev_alloc_skb(rlen + 2);
 
 	if (!skb) {
-		printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name);
+		pr_warning("%s: memory squeeze, dropping packet\n", dev->name);
 		target = adapter->dma_buffer;
 		adapter->current_dma.target = NULL;
 		/* FIXME: stats */
@@ -604,7 +606,8 @@
 
 	/* if this happens, we die */
 	if (test_and_set_bit(0, (void *) &adapter->dmaing))
-		printk(KERN_ERR "%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction);
+		pr_err("%s: rx blocked, DMA in progress, dir %d\n",
+			dev->name, adapter->current_dma.direction);
 
 	adapter->current_dma.direction = 0;
 	adapter->current_dma.length = rlen;
@@ -623,14 +626,14 @@
 	release_dma_lock(flags);
 
 	if (elp_debug >= 3) {
-		printk(KERN_DEBUG "%s: rx DMA transfer started\n", dev->name);
+		pr_debug("%s: rx DMA transfer started\n", dev->name);
 	}
 
 	if (adapter->rx_active)
 		adapter->rx_active--;
 
 	if (!adapter->busy)
-		printk(KERN_WARNING "%s: receive_packet called, busy not set.\n", dev->name);
+		pr_warning("%s: receive_packet called, busy not set.\n", dev->name);
 }
 
 /******************************************************
@@ -655,12 +658,13 @@
 		 * has a DMA transfer finished?
 		 */
 		if (inb_status(dev->base_addr) & DONE) {
-			if (!adapter->dmaing) {
-				printk(KERN_WARNING "%s: phantom DMA completed\n", dev->name);
-			}
-			if (elp_debug >= 3) {
-				printk(KERN_DEBUG "%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));
-			}
+			if (!adapter->dmaing)
+				pr_warning("%s: phantom DMA completed\n", dev->name);
+
+			if (elp_debug >= 3)
+				pr_debug("%s: %s DMA complete, status %02x\n", dev->name,
+					adapter->current_dma.direction ? "tx" : "rx",
+					inb_status(dev->base_addr));
 
 			outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
 			if (adapter->current_dma.direction) {
@@ -682,7 +686,7 @@
 				int t = adapter->rx_backlog.length[adapter->rx_backlog.out];
 				adapter->rx_backlog.out = backlog_next(adapter->rx_backlog.out);
 				if (elp_debug >= 2)
-					printk(KERN_DEBUG "%s: receiving backlogged packet (%d)\n", dev->name, t);
+					pr_debug("%s: receiving backlogged packet (%d)\n", dev->name, t);
 				receive_packet(dev, t);
 			} else {
 				adapter->busy = 0;
@@ -713,21 +717,23 @@
 					len = adapter->irx_pcb.data.rcv_resp.pkt_len;
 					dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
 					if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
-						printk(KERN_ERR "%s: interrupt - packet not received correctly\n", dev->name);
+						pr_err("%s: interrupt - packet not received correctly\n", dev->name);
 					} else {
 						if (elp_debug >= 3) {
-							printk(KERN_DEBUG "%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
+							pr_debug("%s: interrupt - packet received of length %i (%i)\n",
+								dev->name, len, dlen);
 						}
 						if (adapter->irx_pcb.command == 0xff) {
 							if (elp_debug >= 2)
-								printk(KERN_DEBUG "%s: adding packet to backlog (len = %d)\n", dev->name, dlen);
+								pr_debug("%s: adding packet to backlog (len = %d)\n",
+									dev->name, dlen);
 							adapter->rx_backlog.length[adapter->rx_backlog.in] = dlen;
 							adapter->rx_backlog.in = backlog_next(adapter->rx_backlog.in);
 						} else {
 							receive_packet(dev, dlen);
 						}
 						if (elp_debug >= 3)
-							printk(KERN_DEBUG "%s: packet received\n", dev->name);
+							pr_debug("%s: packet received\n", dev->name);
 					}
 					break;
 
@@ -737,7 +743,7 @@
 				case CMD_CONFIGURE_82586_RESPONSE:
 					adapter->got[CMD_CONFIGURE_82586] = 1;
 					if (elp_debug >= 3)
-						printk(KERN_DEBUG "%s: interrupt - configure response received\n", dev->name);
+						pr_debug("%s: interrupt - configure response received\n", dev->name);
 					break;
 
 					/*
@@ -746,7 +752,7 @@
 				case CMD_CONFIGURE_ADAPTER_RESPONSE:
 					adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1;
 					if (elp_debug >= 3)
-						printk(KERN_DEBUG "%s: Adapter memory configuration %s.\n", dev->name,
+						pr_debug("%s: Adapter memory configuration %s.\n", dev->name,
 						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
 					break;
 
@@ -756,7 +762,7 @@
 				case CMD_LOAD_MULTICAST_RESPONSE:
 					adapter->got[CMD_LOAD_MULTICAST_LIST] = 1;
 					if (elp_debug >= 3)
-						printk(KERN_DEBUG "%s: Multicast address list loading %s.\n", dev->name,
+						pr_debug("%s: Multicast address list loading %s.\n", dev->name,
 						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
 					break;
 
@@ -766,7 +772,7 @@
 				case CMD_SET_ADDRESS_RESPONSE:
 					adapter->got[CMD_SET_STATION_ADDRESS] = 1;
 					if (elp_debug >= 3)
-						printk(KERN_DEBUG "%s: Ethernet address setting %s.\n", dev->name,
+						pr_debug("%s: Ethernet address setting %s.\n", dev->name,
 						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
 					break;
 
@@ -783,7 +789,7 @@
 					dev->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res;
 					adapter->got[CMD_NETWORK_STATISTICS] = 1;
 					if (elp_debug >= 3)
-						printk(KERN_DEBUG "%s: interrupt - statistics response received\n", dev->name);
+						pr_debug("%s: interrupt - statistics response received\n", dev->name);
 					break;
 
 					/*
@@ -791,17 +797,17 @@
 					 */
 				case CMD_TRANSMIT_PACKET_COMPLETE:
 					if (elp_debug >= 3)
-						printk(KERN_DEBUG "%s: interrupt - packet sent\n", dev->name);
+						pr_debug("%s: interrupt - packet sent\n", dev->name);
 					if (!netif_running(dev))
 						break;
 					switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
 					case 0xffff:
 						dev->stats.tx_aborted_errors++;
-						printk(KERN_INFO "%s: transmit timed out, network cable problem?\n", dev->name);
+						pr_info("%s: transmit timed out, network cable problem?\n", dev->name);
 						break;
 					case 0xfffe:
 						dev->stats.tx_fifo_errors++;
-						printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name);
+						pr_info("%s: transmit timed out, FIFO underrun\n", dev->name);
 						break;
 					}
 					netif_wake_queue(dev);
@@ -811,11 +817,12 @@
 					 * some unknown PCB
 					 */
 				default:
-					printk(KERN_DEBUG "%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command);
+					pr_debug("%s: unknown PCB received - %2.2x\n",
+						dev->name, adapter->irx_pcb.command);
 					break;
 				}
 			} else {
-				printk(KERN_WARNING "%s: failed to read PCB on interrupt\n", dev->name);
+				pr_warning("%s: failed to read PCB on interrupt\n", dev->name);
 				adapter_reset(dev);
 			}
 		}
@@ -844,13 +851,13 @@
 	int retval;
 
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: request to open device\n", dev->name);
+		pr_debug("%s: request to open device\n", dev->name);
 
 	/*
 	 * make sure we actually found the device
 	 */
 	if (adapter == NULL) {
-		printk(KERN_ERR "%s: Opening a non-existent physical device\n", dev->name);
+		pr_err("%s: Opening a non-existent physical device\n", dev->name);
 		return -EAGAIN;
 	}
 	/*
@@ -880,17 +887,17 @@
 	 * install our interrupt service routine
 	 */
 	if ((retval = request_irq(dev->irq, &elp_interrupt, 0, dev->name, dev))) {
-		printk(KERN_ERR "%s: could not allocate IRQ%d\n", dev->name, dev->irq);
+		pr_err("%s: could not allocate IRQ%d\n", dev->name, dev->irq);
 		return retval;
 	}
 	if ((retval = request_dma(dev->dma, dev->name))) {
 		free_irq(dev->irq, dev);
-		printk(KERN_ERR "%s: could not allocate DMA%d channel\n", dev->name, dev->dma);
+		pr_err("%s: could not allocate DMA%d channel\n", dev->name, dev->dma);
 		return retval;
 	}
 	adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE);
 	if (!adapter->dma_buffer) {
-		printk(KERN_ERR "%s: could not allocate DMA buffer\n", dev->name);
+		pr_err("%s: could not allocate DMA buffer\n", dev->name);
 		free_dma(dev->dma);
 		free_irq(dev->irq, dev);
 		return -ENOMEM;
@@ -906,7 +913,7 @@
 	 * configure adapter memory: we need 10 multicast addresses, default==0
 	 */
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: sending 3c505 memory configuration command\n", dev->name);
+		pr_debug("%s: sending 3c505 memory configuration command\n", dev->name);
 	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
 	adapter->tx_pcb.data.memconf.cmd_q = 10;
 	adapter->tx_pcb.data.memconf.rcv_q = 20;
@@ -917,7 +924,7 @@
 	adapter->tx_pcb.length = sizeof(struct Memconf);
 	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
-		printk(KERN_ERR "%s: couldn't send memory configuration command\n", dev->name);
+		pr_err("%s: couldn't send memory configuration command\n", dev->name);
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
 		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
@@ -930,13 +937,13 @@
 	 * configure adapter to receive broadcast messages and wait for response
 	 */
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name);
+		pr_debug("%s: sending 82586 configure command\n", dev->name);
 	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
 	adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
 	adapter->tx_pcb.length = 2;
 	adapter->got[CMD_CONFIGURE_82586] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
-		printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name);
+		pr_err("%s: couldn't send 82586 configure command\n", dev->name);
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
 		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
@@ -952,7 +959,7 @@
 	 */
 	prime_rx(dev);
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: %d receive PCBs active\n", dev->name, adapter->rx_active);
+		pr_debug("%s: %d receive PCBs active\n", dev->name, adapter->rx_active);
 
 	/*
 	 * device is now officially open!
@@ -982,7 +989,7 @@
 
 	if (test_and_set_bit(0, (void *) &adapter->busy)) {
 		if (elp_debug >= 2)
-			printk(KERN_DEBUG "%s: transmit blocked\n", dev->name);
+			pr_debug("%s: transmit blocked\n", dev->name);
 		return false;
 	}
 
@@ -1004,7 +1011,7 @@
 	}
 	/* if this happens, we die */
 	if (test_and_set_bit(0, (void *) &adapter->dmaing))
-		printk(KERN_DEBUG "%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);
+		pr_debug("%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);
 
 	adapter->current_dma.direction = 1;
 	adapter->current_dma.start_time = jiffies;
@@ -1030,7 +1037,7 @@
 	release_dma_lock(flags);
 
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: DMA transfer started\n", dev->name);
+		pr_debug("%s: DMA transfer started\n", dev->name);
 
 	return true;
 }
@@ -1044,9 +1051,10 @@
 	int stat;
 
 	stat = inb_status(dev->base_addr);
-	printk(KERN_WARNING "%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");
+	pr_warning("%s: transmit timed out, lost %s?\n", dev->name,
+		   (stat & ACRF) ? "interrupt" : "command");
 	if (elp_debug >= 1)
-		printk(KERN_DEBUG "%s: status %#02x\n", dev->name, stat);
+		pr_debug("%s: status %#02x\n", dev->name, stat);
 	dev->trans_start = jiffies;
 	dev->stats.tx_dropped++;
 	netif_wake_queue(dev);
@@ -1068,7 +1076,7 @@
 	check_3c505_dma(dev);
 
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: request to send packet of length %d\n", dev->name, (int) skb->len);
+		pr_debug("%s: request to send packet of length %d\n", dev->name, (int) skb->len);
 
 	netif_stop_queue(dev);
 
@@ -1077,13 +1085,13 @@
 	 */
 	if (!send_packet(dev, skb)) {
 		if (elp_debug >= 2) {
-			printk(KERN_DEBUG "%s: failed to transmit packet\n", dev->name);
+			pr_debug("%s: failed to transmit packet\n", dev->name);
 		}
 		spin_unlock_irqrestore(&adapter->lock, flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: packet of length %d sent\n", dev->name, (int) skb->len);
+		pr_debug("%s: packet of length %d sent\n", dev->name, (int) skb->len);
 
 	/*
 	 * start the transmit timeout
@@ -1107,7 +1115,7 @@
 	elp_device *adapter = netdev_priv(dev);
 
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: request for stats\n", dev->name);
+		pr_debug("%s: request for stats\n", dev->name);
 
 	/* If the device is closed, just return the latest stats we have,
 	   - we cannot ask from the adapter without interrupts */
@@ -1119,7 +1127,7 @@
 	adapter->tx_pcb.length = 0;
 	adapter->got[CMD_NETWORK_STATISTICS] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
-		printk(KERN_ERR "%s: couldn't send get statistics command\n", dev->name);
+		pr_err("%s: couldn't send get statistics command\n", dev->name);
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
 		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
@@ -1169,7 +1177,7 @@
 	elp_device *adapter = netdev_priv(dev);
 
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: request to close device\n", dev->name);
+		pr_debug("%s: request to close device\n", dev->name);
 
 	netif_stop_queue(dev);
 
@@ -1213,7 +1221,7 @@
 	unsigned long flags;
 
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: request to set multicast list\n", dev->name);
+		pr_debug("%s: request to set multicast list\n", dev->name);
 
 	spin_lock_irqsave(&adapter->lock, flags);
 
@@ -1228,7 +1236,7 @@
 		}
 		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
 		if (!send_pcb(dev, &adapter->tx_pcb))
-			printk(KERN_ERR "%s: couldn't send set_multicast command\n", dev->name);
+			pr_err("%s: couldn't send set_multicast command\n", dev->name);
 		else {
 			unsigned long timeout = jiffies + TIMEOUT;
 			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));
@@ -1247,14 +1255,14 @@
 	 * and wait for response
 	 */
 	if (elp_debug >= 3)
-		printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name);
+		pr_debug("%s: sending 82586 configure command\n", dev->name);
 	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
 	adapter->tx_pcb.length = 2;
 	adapter->got[CMD_CONFIGURE_82586] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
 	{
 		spin_unlock_irqrestore(&adapter->lock, flags);
-		printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name);
+		pr_err("%s: couldn't send 82586 configure command\n", dev->name);
 	}
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
@@ -1283,17 +1291,17 @@
 	orig_HSR = inb_status(addr);
 
 	if (elp_debug > 0)
-		printk(search_msg, name, addr);
+		pr_debug(search_msg, name, addr);
 
 	if (orig_HSR == 0xff) {
 		if (elp_debug > 0)
-			printk(notfound_msg, 1);
+			pr_cont(notfound_msg, 1);
 		goto out;
 	}
 
 	/* Wait for a while; the adapter may still be booting up */
 	if (elp_debug > 0)
-		printk(stilllooking_msg);
+		pr_cont(stilllooking_msg);
 
 	if (orig_HSR & DIR) {
 		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
@@ -1301,7 +1309,7 @@
 		msleep(300);
 		if (inb_status(addr) & DIR) {
 			if (elp_debug > 0)
-				printk(notfound_msg, 2);
+				pr_cont(notfound_msg, 2);
 			goto out;
 		}
 	} else {
@@ -1310,7 +1318,7 @@
 		msleep(300);
 		if (!(inb_status(addr) & DIR)) {
 			if (elp_debug > 0)
-				printk(notfound_msg, 3);
+				pr_cont(notfound_msg, 3);
 			goto out;
 		}
 	}
@@ -1318,7 +1326,7 @@
 	 * It certainly looks like a 3c505.
 	 */
 	if (elp_debug > 0)
-		printk(found_msg);
+		pr_cont(found_msg);
 
 	return 0;
 out:
@@ -1349,7 +1357,7 @@
 
 	/* could not find an adapter */
 	if (elp_debug > 0)
-		printk(couldnot_msg, dev->name);
+		pr_debug(couldnot_msg, dev->name);
 
 	return 0;		/* Because of this, the layer above will return -ENODEV */
 }
@@ -1424,16 +1432,16 @@
 			/* Nope, it's ignoring the command register.  This means that
 			 * either it's still booting up, or it's died.
 			 */
-			printk(KERN_ERR "%s: command register wouldn't drain, ", dev->name);
+			pr_err("%s: command register wouldn't drain, ", dev->name);
 			if ((inb_status(dev->base_addr) & 7) == 3) {
 				/* If the adapter status is 3, it *could* still be booting.
 				 * Give it the benefit of the doubt for 10 seconds.
 				 */
-				printk("assuming 3c505 still starting\n");
+				pr_cont("assuming 3c505 still starting\n");
 				timeout = jiffies + 10*HZ;
 				while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7));
 				if (inb_status(dev->base_addr) & 7) {
-					printk(KERN_ERR "%s: 3c505 failed to start\n", dev->name);
+					pr_err("%s: 3c505 failed to start\n", dev->name);
 				} else {
 					okay = 1;  /* It started */
 				}
@@ -1441,7 +1449,7 @@
 				/* Otherwise, it must just be in a strange
 				 * state.  We probably need to kick it.
 				 */
-				printk("3c505 is sulking\n");
+				pr_cont("3c505 is sulking\n");
 			}
 		}
 		for (tries = 0; tries < 5 && okay; tries++) {
@@ -1454,18 +1462,19 @@
 			adapter->tx_pcb.length = 0;
 			cookie = probe_irq_on();
 			if (!send_pcb(dev, &adapter->tx_pcb)) {
-				printk(KERN_ERR "%s: could not send first PCB\n", dev->name);
+				pr_err("%s: could not send first PCB\n", dev->name);
 				probe_irq_off(cookie);
 				continue;
 			}
 			if (!receive_pcb(dev, &adapter->rx_pcb)) {
-				printk(KERN_ERR "%s: could not read first PCB\n", dev->name);
+				pr_err("%s: could not read first PCB\n", dev->name);
 				probe_irq_off(cookie);
 				continue;
 			}
 			if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) ||
 			    (adapter->rx_pcb.length != 6)) {
-				printk(KERN_ERR "%s: first PCB wrong (%d, %d)\n", dev->name, adapter->rx_pcb.command, adapter->rx_pcb.length);
+				pr_err("%s: first PCB wrong (%d, %d)\n", dev->name,
+					adapter->rx_pcb.command, adapter->rx_pcb.length);
 				probe_irq_off(cookie);
 				continue;
 			}
@@ -1474,32 +1483,32 @@
 		/* It's broken.  Do a hard reset to re-initialise the board,
 		 * and try again.
 		 */
-		printk(KERN_INFO "%s: resetting adapter\n", dev->name);
+		pr_info("%s: resetting adapter\n", dev->name);
 		outb_control(adapter->hcr_val | FLSH | ATTN, dev);
 		outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev);
 	}
-	printk(KERN_ERR "%s: failed to initialise 3c505\n", dev->name);
+	pr_err("%s: failed to initialise 3c505\n", dev->name);
 	goto out;
 
       okay:
 	if (dev->irq) {		/* Is there a preset IRQ? */
 		int rpt = probe_irq_off(cookie);
 		if (dev->irq != rpt) {
-			printk(KERN_WARNING "%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);
+			pr_warning("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);
 		}
 		/* if dev->irq == probe_irq_off(cookie), all is well */
 	} else		       /* No preset IRQ; just use what we can detect */
 		dev->irq = probe_irq_off(cookie);
 	switch (dev->irq) {    /* Legal, sane? */
 	case 0:
-		printk(KERN_ERR "%s: IRQ probe failed: check 3c505 jumpers.\n",
+		pr_err("%s: IRQ probe failed: check 3c505 jumpers.\n",
 		       dev->name);
 		goto out;
 	case 1:
 	case 6:
 	case 8:
 	case 13:
-		printk(KERN_ERR "%s: Impossible IRQ %d reported by probe_irq_off().\n",
+		pr_err("%s: Impossible IRQ %d reported by probe_irq_off().\n",
 		       dev->name, dev->irq);
 		       goto out;
 	}
@@ -1521,7 +1530,7 @@
 			dev->dma = dev->mem_start & 7;
 		}
 		else {
-			printk(KERN_WARNING "%s: warning, DMA channel not specified, using default\n", dev->name);
+			pr_warning("%s: warning, DMA channel not specified, using default\n", dev->name);
 			dev->dma = ELP_DMA;
 		}
 	}
@@ -1529,11 +1538,8 @@
 	/*
 	 * print remainder of startup message
 	 */
-	printk(KERN_INFO "%s: 3c505 at %#lx, irq %d, dma %d, "
-	       "addr %pM, ",
-	       dev->name, dev->base_addr, dev->irq, dev->dma,
-	       dev->dev_addr);
-
+	pr_info("%s: 3c505 at %#lx, irq %d, dma %d, addr %pM, ",
+		dev->name, dev->base_addr, dev->irq, dev->dma, dev->dev_addr);
 	/*
 	 * read more information from the adapter
 	 */
@@ -1544,9 +1550,10 @@
 	    !receive_pcb(dev, &adapter->rx_pcb) ||
 	    (adapter->rx_pcb.command != CMD_ADAPTER_INFO_RESPONSE) ||
 	    (adapter->rx_pcb.length != 10)) {
-		printk("not responding to second PCB\n");
+		pr_cont("not responding to second PCB\n");
 	}
-	printk("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers, adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz);
+	pr_cont("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers,
+		adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz);
 
 	/*
 	 * reconfigure the adapter memory to better suit our purposes
@@ -1563,10 +1570,10 @@
 	    !receive_pcb(dev, &adapter->rx_pcb) ||
 	    (adapter->rx_pcb.command != CMD_CONFIGURE_ADAPTER_RESPONSE) ||
 	    (adapter->rx_pcb.length != 2)) {
-		printk(KERN_ERR "%s: could not configure adapter memory\n", dev->name);
+		pr_err("%s: could not configure adapter memory\n", dev->name);
 	}
 	if (adapter->rx_pcb.data.configure) {
-		printk(KERN_ERR "%s: adapter configuration failed\n", dev->name);
+		pr_err("%s: adapter configuration failed\n", dev->name);
 	}
 
 	dev->netdev_ops = &elp_netdev_ops;
@@ -1631,17 +1638,17 @@
 			dev->dma = dma[this_dev];
 		} else {
 			dev->dma = ELP_DMA;
-			printk(KERN_WARNING "3c505.c: warning, using default DMA channel,\n");
+			pr_warning("3c505.c: warning, using default DMA channel,\n");
 		}
 		if (io[this_dev] == 0) {
 			if (this_dev) {
 				free_netdev(dev);
 				break;
 			}
-			printk(KERN_NOTICE "3c505.c: module autoprobe not recommended, give io=xx.\n");
+			pr_notice("3c505.c: module autoprobe not recommended, give io=xx.\n");
 		}
 		if (elplus_setup(dev) != 0) {
-			printk(KERN_WARNING "3c505.c: Failed to register card at 0x%x.\n", io[this_dev]);
+			pr_warning("3c505.c: Failed to register card at 0x%x.\n", io[this_dev]);
 			free_netdev(dev);
 			break;
 		}
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c507.c linux-libre-2.6.31-gnu/drivers/net/3c507.c
--- linux-libre-2.6.30-gnu/drivers/net/3c507.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c507.c	2009-09-09 18:13:59.000000000 -0400
@@ -364,7 +364,7 @@
 
 static int __init el16_probe1(struct net_device *dev, int ioaddr)
 {
-	static unsigned char init_ID_done, version_printed;
+	static unsigned char init_ID_done;
 	int i, irq, irqval, retval;
 	struct net_local *lp;
 
@@ -391,10 +391,7 @@
 		goto out;
 	}
 
-	if (net_debug  &&  version_printed++ == 0)
-		printk(version);
-
-	printk("%s: 3c507 at %#x,", dev->name, ioaddr);
+	pr_info("%s: 3c507 at %#x,", dev->name, ioaddr);
 
 	/* We should make a few more checks here, like the first three octets of
 	   the S.A. for the manufacturer's code. */
@@ -403,7 +400,8 @@
 
 	irqval = request_irq(irq, &el16_interrupt, 0, DRV_NAME, dev);
 	if (irqval) {
-		printk(KERN_ERR "3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval);
+		pr_cont("\n");
+		pr_err("3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval);
 		retval = -EAGAIN;
 		goto out;
 	}
@@ -414,7 +412,7 @@
 	outb(0x01, ioaddr + MISC_CTRL);
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(ioaddr + i);
-	printk(" %pM", dev->dev_addr);
+	pr_cont(" %pM", dev->dev_addr);
 
 	if (mem_start)
 		net_debug = mem_start & 7;
@@ -443,18 +441,18 @@
 	dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0;
 	dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
 
-	printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq,
+	pr_cont(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq,
 		   dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1);
 
 	if (net_debug)
-		printk(version);
+		pr_debug("%s", version);
 
 	lp = netdev_priv(dev);
  	memset(lp, 0, sizeof(*lp));
 	spin_lock_init(&lp->lock);
 	lp->base = ioremap(dev->mem_start, RX_BUF_END);
 	if (!lp->base) {
-		printk(KERN_ERR "3c507: unable to remap memory\n");
+		pr_err("3c507: unable to remap memory\n");
 		retval = -EAGAIN;
 		goto out1;
 	}
@@ -488,20 +486,20 @@
 	void __iomem *shmem = lp->base;
 
 	if (net_debug > 1)
-		printk ("%s: transmit timed out, %s?  ", dev->name,
+		pr_debug("%s: transmit timed out, %s?  ", dev->name,
 			readw(shmem + iSCB_STATUS) & 0x8000 ? "IRQ conflict" :
 			"network cable problem");
 	/* Try to restart the adaptor. */
 	if (lp->last_restart == dev->stats.tx_packets) {
 		if (net_debug > 1)
-			printk ("Resetting board.\n");
+			pr_cont("Resetting board.\n");
 		/* Completely reset the adaptor. */
 		init_82586_mem (dev);
 		lp->tx_pkts_in_ring = 0;
 	} else {
 		/* Issue the channel attention signal and hope it "gets better". */
 		if (net_debug > 1)
-			printk ("Kicking board.\n");
+			pr_cont("Kicking board.\n");
 		writew(0xf000 | CUC_START | RX_START, shmem + iSCB_CMD);
 		outb (0, ioaddr + SIGNAL_CA);	/* Issue channel-attn. */
 		lp->last_restart = dev->stats.tx_packets;
@@ -553,7 +551,8 @@
 	void __iomem *shmem;
 
 	if (dev == NULL) {
-		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
+		pr_err("%s: net_interrupt(): irq %d for unknown device.\n",
+			dev->name, irq);
 		return IRQ_NONE;
 	}
 
@@ -566,7 +565,7 @@
 	status = readw(shmem+iSCB_STATUS);
 
 	if (net_debug > 4) {
-		printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
+		pr_debug("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
 	}
 
 	/* Disable the 82586's input to the interrupt line. */
@@ -577,7 +576,7 @@
 	  unsigned short tx_status = readw(shmem+lp->tx_reap);
 	  if (!(tx_status & 0x8000)) {
 		if (net_debug > 5)
-			printk("Tx command incomplete (%#x).\n", lp->tx_reap);
+			pr_debug("Tx command incomplete (%#x).\n", lp->tx_reap);
 		break;
 	  }
 	  /* Tx unsuccessful or some interesting status bit set. */
@@ -591,7 +590,7 @@
 	  }
 	  dev->stats.tx_packets++;
 	  if (net_debug > 5)
-		  printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
+		  pr_debug("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
 	  lp->tx_reap += TX_BUF_SIZE;
 	  if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
 		lp->tx_reap = TX_BUF_START;
@@ -606,7 +605,7 @@
 
 	if (status & 0x4000) { /* Packet received. */
 		if (net_debug > 5)
-			printk("Received packet, rx_head %04x.\n", lp->rx_head);
+			pr_debug("Received packet, rx_head %04x.\n", lp->rx_head);
 		el16_rx(dev);
 	}
 
@@ -615,7 +614,7 @@
 
 	if ((status & 0x0700) != 0x0200 && netif_running(dev)) {
 		if (net_debug)
-			printk("%s: Command unit stopped, status %04x, restarting.\n",
+			pr_debug("%s: Command unit stopped, status %04x, restarting.\n",
 				   dev->name, status);
 		/* If this ever occurs we should really re-write the idle loop, reset
 		   the Tx list, and do a complete restart of the command unit.
@@ -627,7 +626,7 @@
 		/* The Rx unit is not ready, it must be hung.  Restart the receiver by
 		   initializing the rx buffers, and issuing an Rx start command. */
 		if (net_debug)
-			printk("%s: Rx unit stopped, status %04x, restarting.\n",
+			pr_debug("%s: Rx unit stopped, status %04x, restarting.\n",
 				   dev->name, status);
 		init_rx_bufs(dev);
 		writew(RX_BUF_START,shmem+iSCB_RFA);
@@ -753,9 +752,8 @@
 		int boguscnt = 50;
 		while (readw(shmem+iSCB_STATUS) == 0)
 			if (--boguscnt == 0) {
-				printk("%s: i82586 initialization timed out with status %04x, "
-					   "cmd %04x.\n", dev->name,
-					   readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD));
+				pr_warning("%s: i82586 initialization timed out with status %04x, cmd %04x.\n",
+					dev->name, readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD));
 				break;
 			}
 		/* Issue channel-attn -- the 82586 won't start. */
@@ -765,7 +763,7 @@
 	/* Disable loopback and enable interrupts. */
 	outb(0x84, ioaddr + MISC_CTRL);
 	if (net_debug > 4)
-		printk("%s: Initialized 82586, status %04x.\n", dev->name,
+		pr_debug("%s: Initialized 82586, status %04x.\n", dev->name,
 			   readw(shmem+iSCB_STATUS));
 	return;
 }
@@ -810,7 +808,7 @@
 		lp->tx_head = TX_BUF_START;
 
 	if (net_debug > 4) {
-		printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
+		pr_debug("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
 			   dev->name, ioaddr, length, tx_block, lp->tx_head);
 	}
 
@@ -838,7 +836,7 @@
 
 		if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
 			|| (pkt_len & 0xC000) != 0xC000) {
-			printk(KERN_ERR "%s: Rx frame at %#x corrupted, "
+			pr_err("%s: Rx frame at %#x corrupted, "
 			       "status %04x cmd %04x next %04x "
 			       "data-buf @%04x %04x.\n",
 			       dev->name, rx_head, frame_status, rfd_cmd,
@@ -858,8 +856,7 @@
 			pkt_len &= 0x3fff;
 			skb = dev_alloc_skb(pkt_len+2);
 			if (skb == NULL) {
-				printk(KERN_ERR "%s: Memory squeeze, "
-				       "dropping packet.\n",
+				pr_err("%s: Memory squeeze, dropping packet.\n",
 				       dev->name);
 				dev->stats.rx_dropped++;
 				break;
@@ -926,7 +923,7 @@
 int __init init_module(void)
 {
 	if (io == 0)
-		printk("3c507: You should not use auto-probing with insmod!\n");
+		pr_notice("3c507: You should not use auto-probing with insmod!\n");
 	dev_3c507 = el16_probe(-1);
 	return IS_ERR(dev_3c507) ? PTR_ERR(dev_3c507) : 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c509.c linux-libre-2.6.31-gnu/drivers/net/3c509.c
--- linux-libre-2.6.30-gnu/drivers/net/3c509.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c509.c	2009-09-09 18:13:59.000000000 -0400
@@ -257,7 +257,7 @@
 			    && !memcmp(phys_addr, el3_devs[i]->dev_addr,
 				       ETH_ALEN)) {
 				if (el3_debug > 3)
-					printk(KERN_DEBUG "3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+					pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
 						phys_addr[0] & 0xff, phys_addr[0] >> 8,
 						phys_addr[1] & 0xff, phys_addr[1] >> 8,
 						phys_addr[2] & 0xff, phys_addr[2] >> 8);
@@ -578,19 +578,18 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		printk(KERN_ERR "Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
+		pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
 			dev->base_addr, dev->irq);
 		release_region(dev->base_addr, EL3_IO_EXTENT);
 		return err;
 	}
 
-	printk(KERN_INFO "%s: 3c5x9 found at %#3.3lx, %s port, "
-	       "address %pM, IRQ %d.\n",
+	pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n",
 	       dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
 	       dev->dev_addr, dev->irq);
 
 	if (el3_debug > 0)
-		printk(KERN_INFO "%s", version);
+		pr_info("%s", version);
 	return 0;
 
 }
@@ -629,8 +628,8 @@
 	irq = pos5 & 0x0f;
 
 
-	printk(KERN_INFO "3c529: found %s at slot %d\n",
-		   el3_mca_adapter_names[mdev->index], slot + 1);
+	pr_info("3c529: found %s at slot %d\n",
+		el3_mca_adapter_names[mdev->index], slot + 1);
 
 	/* claim the slot */
 	strncpy(mdev->name, el3_mca_adapter_names[mdev->index],
@@ -642,7 +641,7 @@
 	irq = mca_device_transform_irq(mdev, irq);
 	ioaddr = mca_device_transform_ioport(mdev, ioaddr);
 	if (el3_debug > 2) {
-			printk(KERN_DEBUG "3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
+		pr_debug("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
 	}
 	EL3WINDOW(0);
 	for (i = 0; i < 3; i++)
@@ -657,11 +656,11 @@
 	netdev_boot_setup_check(dev);
 
 	el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
-	device->driver_data = dev;
+	dev_set_drvdata(device, dev);
 	err = el3_common_init(dev);
 
 	if (err) {
-		device->driver_data = NULL;
+		dev_set_drvdata(device, NULL);
 		free_netdev(dev);
 		return -ENOMEM;
 	}
@@ -725,12 +724,12 @@
 
 /* This remove works for all device types.
  *
- * The net dev must be stored in the driver_data field */
+ * The net dev must be stored in the driver data field */
 static int __devexit el3_device_remove (struct device *device)
 {
 	struct net_device *dev;
 
-	dev  = device->driver_data;
+	dev = dev_get_drvdata(device);
 
 	el3_common_remove (dev);
 	return 0;
@@ -765,7 +764,7 @@
 		word = (word << 1) + (inb(id_port) & 0x01);
 
 	if (el3_debug > 3)
-		printk(KERN_DEBUG "  3c509 EEPROM word %d %#4.4x.\n", index, word);
+		pr_debug("  3c509 EEPROM word %d %#4.4x.\n", index, word);
 
 	return word;
 }
@@ -787,13 +786,13 @@
 
 	EL3WINDOW(0);
 	if (el3_debug > 3)
-		printk(KERN_DEBUG "%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
+		pr_debug("%s: Opening, IRQ %d	 status@%x %4.4x.\n", dev->name,
 			   dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
 
 	el3_up(dev);
 
 	if (el3_debug > 3)
-		printk(KERN_DEBUG "%s: Opened 3c509  IRQ %d  status %4.4x.\n",
+		pr_debug("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
 			   dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
 
 	return 0;
@@ -805,8 +804,7 @@
 	int ioaddr = dev->base_addr;
 
 	/* Transmitter timeout, serious problems. */
-	printk(KERN_WARNING "%s: transmit timed out, Tx_status %2.2x status %4.4x "
-		   "Tx FIFO room %d.\n",
+	pr_warning("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d.\n",
 		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
 		   inw(ioaddr + TX_FREE));
 	dev->stats.tx_errors++;
@@ -830,7 +828,7 @@
 	dev->stats.tx_bytes += skb->len;
 
 	if (el3_debug > 4) {
-		printk(KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
+		pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
 			   dev->name, skb->len, inw(ioaddr + EL3_STATUS));
 	}
 #if 0
@@ -839,7 +837,7 @@
 		ushort status = inw(ioaddr + EL3_STATUS);
 		if (status & 0x0001 		/* IRQ line active, missed one. */
 			&& inw(ioaddr + EL3_STATUS) & 1) { 			/* Make sure. */
-			printk(KERN_DEBUG "%s: Missed interrupt, status then %04x now %04x"
+			pr_debug("%s: Missed interrupt, status then %04x now %04x"
 				   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
 				   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
 				   inw(ioaddr + RX_STATUS));
@@ -913,7 +911,7 @@
 
 	if (el3_debug > 4) {
 		status = inw(ioaddr + EL3_STATUS);
-		printk(KERN_DEBUG "%s: interrupt, status %4.4x.\n", dev->name, status);
+		pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status);
 	}
 
 	while ((status = inw(ioaddr + EL3_STATUS)) &
@@ -924,7 +922,7 @@
 
 		if (status & TxAvailable) {
 			if (el3_debug > 5)
-				printk(KERN_DEBUG "	TX room bit was handled.\n");
+				pr_debug("	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
 			netif_wake_queue (dev);
@@ -962,7 +960,7 @@
 		}
 
 		if (--i < 0) {
-			printk(KERN_ERR "%s: Infinite loop in interrupt, status %4.4x.\n",
+			pr_err("%s: Infinite loop in interrupt, status %4.4x.\n",
 				   dev->name, status);
 			/* Clear all interrupts. */
 			outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
@@ -973,7 +971,7 @@
 	}
 
 	if (el3_debug > 4) {
-		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", dev->name,
+		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name,
 			   inw(ioaddr + EL3_STATUS));
 	}
 	spin_unlock(&lp->lock);
@@ -1021,7 +1019,7 @@
 	int ioaddr = dev->base_addr;
 
 	if (el3_debug > 5)
-		printk("   Updating the statistics.\n");
+		pr_debug("   Updating the statistics.\n");
 	/* Turn off statistics updates while reading. */
 	outw(StatsDisable, ioaddr + EL3_CMD);
 	/* Switch to the stats window, and read everything. */
@@ -1051,7 +1049,7 @@
 	short rx_status;
 
 	if (el3_debug > 5)
-		printk("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
 			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
 	while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
 		if (rx_status & 0x4000) { /* Error, update stats. */
@@ -1073,7 +1071,7 @@
 
 			skb = dev_alloc_skb(pkt_len+5);
 			if (el3_debug > 4)
-				printk("Receiving packet size %d status %4.4x.\n",
+				pr_debug("Receiving packet size %d status %4.4x.\n",
 					   pkt_len, rx_status);
 			if (skb != NULL) {
 				skb_reserve(skb, 2);     /* Align IP on 16 byte */
@@ -1092,12 +1090,12 @@
 			outw(RxDiscard, ioaddr + EL3_CMD);
 			dev->stats.rx_dropped++;
 			if (el3_debug)
-				printk("%s: Couldn't allocate a sk_buff of size %d.\n",
+				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n",
 					   dev->name, pkt_len);
 		}
 		inw(ioaddr + EL3_STATUS); 				/* Delay. */
 		while (inw(ioaddr + EL3_STATUS) & 0x1000)
-			printk(KERN_DEBUG "	Waiting for 3c509 to discard packet, status %x.\n",
+			pr_debug("	Waiting for 3c509 to discard packet, status %x.\n",
 				   inw(ioaddr + EL3_STATUS) );
 	}
 
@@ -1118,7 +1116,7 @@
 		static int old;
 		if (old != dev->mc_count) {
 			old = dev->mc_count;
-			printk("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count);
+			pr_debug("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count);
 		}
 	}
 	spin_lock_irqsave(&lp->lock, flags);
@@ -1141,7 +1139,7 @@
 	struct el3_private *lp = netdev_priv(dev);
 
 	if (el3_debug > 2)
-		printk("%s: Shutting down ethercard.\n", dev->name);
+		pr_debug("%s: Shutting down ethercard.\n", dev->name);
 
 	el3_down(dev);
 
@@ -1388,30 +1386,30 @@
 		EL3WINDOW(4);
 		net_diag = inw(ioaddr + WN4_NETDIAG);
 		net_diag = (net_diag | FD_ENABLE); /* temporarily assume full-duplex will be set */
-		printk("%s: ", dev->name);
+		pr_info("%s: ", dev->name);
 		switch (dev->if_port & 0x0c) {
 			case 12:
 				/* force full-duplex mode if 3c5x9b */
 				if (sw_info & 0x000f) {
-					printk("Forcing 3c5x9b full-duplex mode");
+					pr_cont("Forcing 3c5x9b full-duplex mode");
 					break;
 				}
 			case 8:
 				/* set full-duplex mode based on eeprom config setting */
 				if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
-					printk("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
+					pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
 					break;
 				}
 			default:
 				/* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */
-				printk("Setting 3c5x9/3c5x9B half-duplex mode");
+				pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
 				net_diag = (net_diag & ~FD_ENABLE); /* disable full duplex */
 		}
 
 		outw(net_diag, ioaddr + WN4_NETDIAG);
-		printk(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info);
+		pr_cont(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info);
 		if (el3_debug > 3)
-			printk("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag);
+			pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag);
 		/* Enable link beat and jabber check. */
 		outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
 	}
@@ -1455,7 +1453,7 @@
 	struct el3_private *lp;
 	int ioaddr;
 
-	dev = pdev->driver_data;
+	dev = dev_get_drvdata(pdev);
 	lp = netdev_priv(dev);
 	ioaddr = dev->base_addr;
 
@@ -1479,7 +1477,7 @@
 	struct el3_private *lp;
 	int ioaddr;
 
-	dev = pdev->driver_data;
+	dev = dev_get_drvdata(pdev);
 	lp = netdev_priv(dev);
 	ioaddr = dev->base_addr;
 
@@ -1539,7 +1537,7 @@
 	}
 	if (id_port >= 0x200) {
 		id_port = 0;
-		printk(KERN_ERR "No I/O port available for 3c509 activation.\n");
+		pr_err("No I/O port available for 3c509 activation.\n");
 	} else {
 		ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
 		if (!ret)
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c515.c linux-libre-2.6.31-gnu/drivers/net/3c515.c
--- linux-libre-2.6.30-gnu/drivers/net/3c515.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c515.c	2009-09-09 18:13:59.000000000 -0400
@@ -420,7 +420,7 @@
 	if (debug >= 0)
 		corkscrew_debug = debug;
 	if (corkscrew_debug)
-		printk(version);
+		pr_debug("%s", version);
 	while (corkscrew_scan(-1))
 		found++;
 	return found ? 0 : -ENODEV;
@@ -437,7 +437,7 @@
 
 	if (corkscrew_debug > 0 && !printed) {
 		printed = 1;
-		printk(version);
+		pr_debug("%s", version);
 	}
 
 	return dev;
@@ -516,7 +516,7 @@
 			if (pnp_device_attach(idev) < 0)
 				continue;
 			if (pnp_activate_dev(idev) < 0) {
-				printk("pnp activate failed (out of resources?)\n");
+				pr_warning("pnp activate failed (out of resources?)\n");
 				pnp_device_detach(idev);
 				continue;
 			}
@@ -531,9 +531,9 @@
 				continue;
 			}
 			if(corkscrew_debug)
-				printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n",
+				pr_debug("ISAPNP reports %s at i/o 0x%x, irq %d\n",
 					(char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
-			printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
+			pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
 		     		inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
 			/* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */
 			SET_NETDEV_DEV(dev, &idev->dev);
@@ -552,7 +552,7 @@
 		if (!check_device(ioaddr))
 			continue;
 
-		printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
+		pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
 		     inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
 		err = corkscrew_setup(dev, ioaddr, NULL, cards_found++);
 		if (!err)
@@ -625,7 +625,7 @@
 	list_add(&vp->list, &root_corkscrew_dev);
 #endif
 
-	printk(KERN_INFO "%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr);
+	pr_info("%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr);
 
 	spin_lock_init(&vp->lock);
 
@@ -648,19 +648,19 @@
 	}
 	checksum = (checksum ^ (checksum >> 8)) & 0xff;
 	if (checksum != 0x00)
-		printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
-	printk(" %pM", dev->dev_addr);
+		pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
+	pr_cont(" %pM", dev->dev_addr);
 	if (eeprom[16] == 0x11c7) {	/* Corkscrew */
 		if (request_dma(dev->dma, "3c515")) {
-			printk(", DMA %d allocation failed", dev->dma);
+			pr_cont(", DMA %d allocation failed", dev->dma);
 			dev->dma = 0;
 		} else
-			printk(", DMA %d", dev->dma);
+			pr_cont(", DMA %d", dev->dma);
 	}
-	printk(", IRQ %d\n", dev->irq);
+	pr_cont(", IRQ %d\n", dev->irq);
 	/* Tell them about an invalid IRQ. */
 	if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15))
-		printk(KERN_WARNING " *** Warning: this IRQ is unlikely to work! ***\n");
+		pr_warning(" *** Warning: this IRQ is unlikely to work! ***\n");
 
 	{
 		char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
@@ -669,9 +669,9 @@
 		vp->available_media = inw(ioaddr + Wn3_Options);
 		config = inl(ioaddr + Wn3_Config);
 		if (corkscrew_debug > 1)
-			printk(KERN_INFO "  Internal config register is %4.4x, transceivers %#x.\n",
+			pr_info("  Internal config register is %4.4x, transceivers %#x.\n",
 				config, inw(ioaddr + Wn3_Options));
-		printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+		pr_info("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
 			8 << config & Ram_size,
 			config & Ram_width ? "word" : "byte",
 			ram_split[(config & Ram_split) >> Ram_split_shift],
@@ -682,7 +682,7 @@
 		dev->if_port = vp->default_media;
 	}
 	if (vp->media_override != 7) {
-		printk(KERN_INFO "  Media override to transceiver type %d (%s).\n",
+		pr_info("  Media override to transceiver type %d (%s).\n",
 		       vp->media_override,
 		       media_tbl[vp->media_override].name);
 		dev->if_port = vp->media_override;
@@ -718,7 +718,7 @@
 
 	if (vp->media_override != 7) {
 		if (corkscrew_debug > 1)
-			printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
+			pr_info("%s: Media override to transceiver %d (%s).\n",
 				dev->name, vp->media_override,
 				media_tbl[vp->media_override].name);
 		dev->if_port = vp->media_override;
@@ -729,7 +729,7 @@
 			dev->if_port = media_tbl[dev->if_port].next;
 
 		if (corkscrew_debug > 1)
-			printk("%s: Initial media type %s.\n",
+			pr_debug("%s: Initial media type %s.\n",
 			       dev->name, media_tbl[dev->if_port].name);
 
 		init_timer(&vp->timer);
@@ -744,7 +744,7 @@
 	outl(config, ioaddr + Wn3_Config);
 
 	if (corkscrew_debug > 1) {
-		printk("%s: corkscrew_open() InternalConfig %8.8x.\n",
+		pr_debug("%s: corkscrew_open() InternalConfig %8.8x.\n",
 		       dev->name, config);
 	}
 
@@ -777,7 +777,7 @@
 
 	if (corkscrew_debug > 1) {
 		EL3WINDOW(4);
-		printk("%s: corkscrew_open() irq %d media status %4.4x.\n",
+		pr_debug("%s: corkscrew_open() irq %d media status %4.4x.\n",
 		       dev->name, dev->irq, inw(ioaddr + Wn4_Media));
 	}
 
@@ -814,8 +814,7 @@
 	if (vp->full_bus_master_rx) {	/* Boomerang bus master. */
 		vp->cur_rx = vp->dirty_rx = 0;
 		if (corkscrew_debug > 2)
-			printk("%s:  Filling in the Rx ring.\n",
-			       dev->name);
+			pr_debug("%s:  Filling in the Rx ring.\n", dev->name);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			struct sk_buff *skb;
 			if (i < (RX_RING_SIZE - 1))
@@ -833,7 +832,9 @@
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 			vp->rx_ring[i].addr = isa_virt_to_bus(skb->data);
 		}
-		vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
+		if (i != 0)
+			vp->rx_ring[i - 1].next =
+				isa_virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
 		outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
 	}
 	if (vp->full_bus_master_tx) {	/* Boomerang bus master Tx. */
@@ -877,7 +878,7 @@
 	int ok = 0;
 
 	if (corkscrew_debug > 1)
-		printk("%s: Media selection timer tick happened, %s.\n",
+		pr_debug("%s: Media selection timer tick happened, %s.\n",
 		       dev->name, media_tbl[dev->if_port].name);
 
 	spin_lock_irqsave(&vp->lock, flags);
@@ -894,12 +895,12 @@
 			if (media_status & Media_LnkBeat) {
 				ok = 1;
 				if (corkscrew_debug > 1)
-					printk("%s: Media %s has link beat, %x.\n",
+					pr_debug("%s: Media %s has link beat, %x.\n",
 						dev->name,
 						media_tbl[dev->if_port].name,
 						media_status);
 			} else if (corkscrew_debug > 1)
-				printk("%s: Media %s is has no link beat, %x.\n",
+				pr_debug("%s: Media %s is has no link beat, %x.\n",
 					dev->name,
 					media_tbl[dev->if_port].name,
 					media_status);
@@ -907,7 +908,7 @@
 			break;
 		default:	/* Other media types handled by Tx timeouts. */
 			if (corkscrew_debug > 1)
-				printk("%s: Media %s is has no indication, %x.\n",
+				pr_debug("%s: Media %s is has no indication, %x.\n",
 					dev->name,
 					media_tbl[dev->if_port].name,
 					media_status);
@@ -925,12 +926,12 @@
 			if (dev->if_port == 8) {	/* Go back to default. */
 				dev->if_port = vp->default_media;
 				if (corkscrew_debug > 1)
-					printk("%s: Media selection failing, using default %s port.\n",
+					pr_debug("%s: Media selection failing, using default %s port.\n",
 						dev->name,
 						media_tbl[dev->if_port].name);
 			} else {
 				if (corkscrew_debug > 1)
-					printk("%s: Media selection failed, now trying %s port.\n",
+					pr_debug("%s: Media selection failed, now trying %s port.\n",
 						dev->name,
 						media_tbl[dev->if_port].name);
 				vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
@@ -953,7 +954,7 @@
 
 	spin_unlock_irqrestore(&vp->lock, flags);
 	if (corkscrew_debug > 1)
-		printk("%s: Media selection timer finished, %s.\n",
+		pr_debug("%s: Media selection timer finished, %s.\n",
 		       dev->name, media_tbl[dev->if_port].name);
 
 #endif				/* AUTOMEDIA */
@@ -966,23 +967,21 @@
 	struct corkscrew_private *vp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
 
-	printk(KERN_WARNING
-	       "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+	pr_warning("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
 	       dev->name, inb(ioaddr + TxStatus),
 	       inw(ioaddr + EL3_STATUS));
 	/* Slight code bloat to be user friendly. */
 	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
-		printk(KERN_WARNING
-		       "%s: Transmitter encountered 16 collisions -- network"
+		pr_warning("%s: Transmitter encountered 16 collisions --"
 		       " network cable problem?\n", dev->name);
 #ifndef final_version
-	printk("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
+	pr_debug("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
 	       vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx,
 	       vp->cur_tx);
-	printk("  Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
+	pr_debug("  Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
 	       &vp->tx_ring[0]);
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		printk("  %d: %p  length %8.8x status %8.8x\n", i,
+		pr_debug("  %d: %p  length %8.8x status %8.8x\n", i,
 		       &vp->tx_ring[i],
 		       vp->tx_ring[i].length, vp->tx_ring[i].status);
 	}
@@ -1017,13 +1016,13 @@
 		int i;
 
 		if (vp->tx_full)	/* No room to transmit with */
-			return 1;
+			return NETDEV_TX_BUSY;
 		if (vp->cur_tx != 0)
 			prev_entry = &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE];
 		else
 			prev_entry = NULL;
 		if (corkscrew_debug > 3)
-			printk("%s: Trying to send a packet, Tx index %d.\n",
+			pr_debug("%s: Trying to send a packet, Tx index %d.\n",
 				dev->name, vp->cur_tx);
 		/* vp->tx_full = 1; */
 		vp->tx_skbuff[entry] = skb;
@@ -1102,7 +1101,7 @@
 		while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
 			if (tx_status & 0x3C) {	/* A Tx-disabling error occurred.  */
 				if (corkscrew_debug > 2)
-					printk("%s: Tx error, status %2.2x.\n",
+					pr_debug("%s: Tx error, status %2.2x.\n",
 						dev->name, tx_status);
 				if (tx_status & 0x04)
 					dev->stats.tx_fifo_errors++;
@@ -1143,7 +1142,7 @@
 	status = inw(ioaddr + EL3_STATUS);
 
 	if (corkscrew_debug > 4)
-		printk("%s: interrupt, status %4.4x, timer %d.\n",
+		pr_debug("%s: interrupt, status %4.4x, timer %d.\n",
 			dev->name, status, latency);
 	if ((status & 0xE000) != 0xE000) {
 		static int donedidthis;
@@ -1151,7 +1150,7 @@
 		   Ignore a single early interrupt, but don't hang the machine for
 		   other interrupt problems. */
 		if (donedidthis++ > 100) {
-			printk(KERN_ERR "%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
+			pr_err("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
 				   dev->name, status, netif_running(dev));
 			free_irq(dev->irq, dev);
 			dev->irq = -1;
@@ -1160,14 +1159,14 @@
 
 	do {
 		if (corkscrew_debug > 5)
-			printk("%s: In interrupt loop, status %4.4x.\n",
+			pr_debug("%s: In interrupt loop, status %4.4x.\n",
 			       dev->name, status);
 		if (status & RxComplete)
 			corkscrew_rx(dev);
 
 		if (status & TxAvailable) {
 			if (corkscrew_debug > 5)
-				printk("	TX room bit was handled.\n");
+				pr_debug("	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
 			netif_wake_queue(dev);
@@ -1212,19 +1211,20 @@
 			if (status & StatsFull) {	/* Empty statistics. */
 				static int DoneDidThat;
 				if (corkscrew_debug > 4)
-					printk("%s: Updating stats.\n", dev->name);
+					pr_debug("%s: Updating stats.\n", dev->name);
 				update_stats(ioaddr, dev);
 				/* DEBUG HACK: Disable statistics as an interrupt source. */
 				/* This occurs when we have the wrong media type! */
 				if (DoneDidThat == 0 && inw(ioaddr + EL3_STATUS) & StatsFull) {
 					int win, reg;
-					printk("%s: Updating stats failed, disabling stats as an"
-					     " interrupt source.\n", dev->name);
+					pr_notice("%s: Updating stats failed, disabling stats as an interrupt source.\n",
+						dev->name);
 					for (win = 0; win < 8; win++) {
 						EL3WINDOW(win);
-						printk("\n Vortex window %d:", win);
+						pr_notice("Vortex window %d:", win);
 						for (reg = 0; reg < 16; reg++)
-							printk(" %2.2x", inb(ioaddr + reg));
+							pr_cont(" %2.2x", inb(ioaddr + reg));
+						pr_cont("\n");
 					}
 					EL3WINDOW(7);
 					outw(SetIntrEnb | TxAvailable |
@@ -1246,9 +1246,8 @@
 		}
 
 		if (--i < 0) {
-			printk(KERN_ERR "%s: Too much work in interrupt, status %4.4x.  "
-			     "Disabling functions (%4.4x).\n", dev->name,
-			     status, SetStatusEnb | ((~status) & 0x7FE));
+			pr_err("%s: Too much work in interrupt, status %4.4x. Disabling functions (%4.4x).\n",
+				dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
 			/* Disable all pending interrupts. */
 			outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
 			outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
@@ -1262,7 +1261,7 @@
 	spin_unlock(&lp->lock);
 
 	if (corkscrew_debug > 4)
-		printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
+		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
 	return IRQ_HANDLED;
 }
 
@@ -1273,13 +1272,13 @@
 	short rx_status;
 
 	if (corkscrew_debug > 5)
-		printk("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
 		     inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
 	while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
 		if (rx_status & 0x4000) {	/* Error, update stats. */
 			unsigned char rx_error = inb(ioaddr + RxErrors);
 			if (corkscrew_debug > 2)
-				printk(" Rx error: status %2.2x.\n",
+				pr_debug(" Rx error: status %2.2x.\n",
 				       rx_error);
 			dev->stats.rx_errors++;
 			if (rx_error & 0x01)
@@ -1299,7 +1298,7 @@
 
 			skb = dev_alloc_skb(pkt_len + 5 + 2);
 			if (corkscrew_debug > 4)
-				printk("Receiving packet size %d status %4.4x.\n",
+				pr_debug("Receiving packet size %d status %4.4x.\n",
 				     pkt_len, rx_status);
 			if (skb != NULL) {
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
@@ -1318,7 +1317,7 @@
 						break;
 				continue;
 			} else if (corkscrew_debug)
-				printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
+				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
 		}
 		outw(RxDiscard, ioaddr + EL3_CMD);
 		dev->stats.rx_dropped++;
@@ -1338,13 +1337,13 @@
 	int rx_status;
 
 	if (corkscrew_debug > 5)
-		printk("   In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
+		pr_debug("   In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
 			inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
 	while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
 		if (rx_status & RxDError) {	/* Error, update stats. */
 			unsigned char rx_error = rx_status >> 16;
 			if (corkscrew_debug > 2)
-				printk(" Rx error: status %2.2x.\n",
+				pr_debug(" Rx error: status %2.2x.\n",
 				       rx_error);
 			dev->stats.rx_errors++;
 			if (rx_error & 0x01)
@@ -1364,7 +1363,7 @@
 
 			dev->stats.rx_bytes += pkt_len;
 			if (corkscrew_debug > 4)
-				printk("Receiving packet size %d status %4.4x.\n",
+				pr_debug("Receiving packet size %d status %4.4x.\n",
 				     pkt_len, rx_status);
 
 			/* Check if the packet is long enough to just accept without
@@ -1385,7 +1384,7 @@
 				temp = skb_put(skb, pkt_len);
 				/* Remove this checking code for final release. */
 				if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp)
-					    printk("%s: Warning -- the skbuff addresses do not match"
+					pr_warning("%s: Warning -- the skbuff addresses do not match"
 					     " in boomerang_rx: %p vs. %p / %p.\n",
 					     dev->name,
 					     isa_bus_to_virt(vp->
@@ -1427,12 +1426,11 @@
 	netif_stop_queue(dev);
 
 	if (corkscrew_debug > 1) {
-		printk("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n",
+		pr_debug("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n",
 		     dev->name, inw(ioaddr + EL3_STATUS),
 		     inb(ioaddr + TxStatus));
-		printk("%s: corkscrew close stats: rx_nocopy %d rx_copy %d"
-		       " tx_queued %d.\n", dev->name, rx_nocopy, rx_copy,
-		       queued_packet);
+		pr_debug("%s: corkscrew close stats: rx_nocopy %d rx_copy %d tx_queued %d.\n",
+			dev->name, rx_nocopy, rx_copy, queued_packet);
 	}
 
 	del_timer(&vp->timer);
@@ -1534,7 +1532,7 @@
 
 	if (dev->flags & IFF_PROMISC) {
 		if (corkscrew_debug > 3)
-			printk("%s: Setting promiscuous mode.\n",
+			pr_debug("%s: Setting promiscuous mode.\n",
 			       dev->name);
 		new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm;
 	} else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) {
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c523.c linux-libre-2.6.31-gnu/drivers/net/3c523.c
--- linux-libre-2.6.30-gnu/drivers/net/3c523.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c523.c	2009-09-09 18:13:59.000000000 -0400
@@ -176,7 +176,7 @@
     if(!p->scb->cmd) break; \
     DELAY_16(); \
     if(i == 1023) { \
-      printk(KERN_WARNING "%s:%d: scb_cmd timed out .. resetting i82586\n",\
+      pr_warning("%s:%d: scb_cmd timed out .. resetting i82586\n",\
       	dev->name,__LINE__); \
       elmc_id_reset586(); } } }
 
@@ -291,7 +291,7 @@
 	ret = request_irq(dev->irq, &elmc_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			  dev->name, dev);
 	if (ret) {
-		printk(KERN_ERR "%s: couldn't get irq %d\n", dev->name, dev->irq);
+		pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq);
 		elmc_id_reset586();
 		return ret;
 	}
@@ -371,9 +371,9 @@
 
 	DELAY(2);
 
-	if (p->iscp->busy) {
-		printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name);
-	}
+	if (p->iscp->busy)
+		pr_err("%s: Init-Problems (alloc).\n", dev->name);
+
 	memset((char *) p->scb, 0, sizeof(struct scb_struct));
 }
 
@@ -470,7 +470,7 @@
 	mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
 
 	/* if we get this far, adapter has been found - carry on */
-	printk(KERN_INFO "%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
+	pr_info("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
 
 	/* Now we extract configuration info from the card.
 	   The 3c523 provides information in two of the POS registers, but
@@ -507,7 +507,7 @@
 	memset(pr, 0, sizeof(struct priv));
 	pr->slot = slot;
 
-	printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
+	pr_info("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
 	       dev->base_addr);
 
 	/* Determine if we're using the on-board transceiver (i.e. coax) or
@@ -529,7 +529,7 @@
 
 	size = 0x4000;		/* check for 16K mem */
 	if (!check586(dev, dev->mem_start, size)) {
-		printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
+		pr_err("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
 		       dev->mem_start);
 		retval = -ENODEV;
 		goto err_out;
@@ -546,7 +546,7 @@
 	pr->num_recv_buffs = NUM_RECV_BUFFS_16;
 
 	/* dump all the assorted information */
-	printk(KERN_INFO "%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
+	pr_info("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
 	       dev->irq, dev->if_port ? "ex" : "in",
 	       dev->mem_start, dev->mem_end - 1);
 
@@ -555,7 +555,7 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = inb(dev->base_addr + i);
 
-	printk(KERN_INFO "%s: hardware address %pM\n",
+	pr_info("%s: hardware address %pM\n",
 	       dev->name, dev->dev_addr);
 
 	dev->netdev_ops = &netdev_ops;
@@ -660,7 +660,7 @@
 	}
 
 	if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) {
-		printk(KERN_WARNING "%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
+		pr_warning("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
 		return 1;
 	}
 	/*
@@ -686,7 +686,8 @@
 	}
 
 	if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) {
-		printk(KERN_WARNING "%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status);
+		pr_warning("%s (elmc): individual address setup command failed: %04x\n",
+			dev->name, ias_cmd->cmd_status);
 		return 1;
 	}
 	/*
@@ -707,7 +708,7 @@
 	s = jiffies;
 	while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
 		if (time_after(jiffies, s + 30*HZ/100)) {
-			printk(KERN_WARNING "%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
+			pr_warning("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
 			result = 1;
 			break;
 		}
@@ -723,14 +724,14 @@
 		if (result & TDR_LNK_OK) {
 			/* empty */
 		} else if (result & TDR_XCVR_PRB) {
-			printk(KERN_WARNING "%s: TDR: Transceiver problem!\n", dev->name);
+			pr_warning("%s: TDR: Transceiver problem!\n", dev->name);
 		} else if (result & TDR_ET_OPN) {
-			printk(KERN_WARNING "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+			pr_warning("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
 		} else if (result & TDR_ET_SRT) {
 			if (result & TDR_TIMEMASK)	/* time == 0 -> strange :-) */
-				printk(KERN_WARNING "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+				pr_warning("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
 		} else {
-			printk(KERN_WARNING "%s: TDR: Unknown status %04x\n", dev->name, result);
+			pr_warning("%s: TDR: Unknown status %04x\n", dev->name, result);
 		}
 	}
 	/*
@@ -774,11 +775,11 @@
 		/* I don't understand this: do we really need memory after the init? */
 		int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
 		if (len <= 0) {
-			printk(KERN_ERR "%s: Ooooops, no memory for MC-Setup!\n", dev->name);
+			pr_err("%s: Ooooops, no memory for MC-Setup!\n", dev->name);
 		} else {
 			if (len < num_addrs) {
 				num_addrs = len;
-				printk(KERN_WARNING "%s: Sorry, can only apply %d MC-Address(es).\n",
+				pr_warning("%s: Sorry, can only apply %d MC-Address(es).\n",
 				       dev->name, num_addrs);
 			}
 			mc_cmd = (struct mcsetup_cmd_struct *) ptr;
@@ -799,7 +800,7 @@
 					break;
 			}
 			if (!(mc_cmd->cmd_status & STAT_COMPL)) {
-				printk(KERN_WARNING "%s: Can't apply multicast-address-list.\n", dev->name);
+				pr_warning("%s: Can't apply multicast-address-list.\n", dev->name);
 			}
 		}
 	}
@@ -812,7 +813,7 @@
 		p->xmit_buffs[i] = (struct tbd_struct *) ptr;	/* TBD */
 		ptr = (char *) ptr + sizeof(struct tbd_struct);
 		if ((void *) ptr > (void *) p->iscp) {
-			printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name);
+			pr_err("%s: not enough shared-mem for your configuration!\n", dev->name);
 			return 1;
 		}
 		memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct));
@@ -936,7 +937,8 @@
 		if (stat & STAT_CNA) {
 			/* CU went 'not ready' */
 			if (netif_running(dev)) {
-				printk(KERN_WARNING "%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+				pr_warning("%s: oops! CU has left active state. stat: %04x/%04x.\n",
+					dev->name, (int) stat, (int) p->scb->status);
 			}
 		}
 #endif
@@ -951,7 +953,8 @@
 				p->scb->cmd = RUC_RESUME;
 				elmc_attn586();
 			} else {
-				printk(KERN_WARNING "%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+				pr_warning("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",
+					dev->name, (int) stat, (int) p->scb->status);
 				elmc_rnr_int(dev);
 			}
 		}
@@ -995,11 +998,11 @@
 					dev->stats.rx_dropped++;
 				}
 			} else {
-				printk(KERN_WARNING "%s: received oversized frame.\n", dev->name);
+				pr_warning("%s: received oversized frame.\n", dev->name);
 				dev->stats.rx_dropped++;
 			}
 		} else {	/* frame !(ok), only with 'save-bad-frames' */
-			printk(KERN_WARNING "%s: oops! rfd-error-status: %04x\n", dev->name, status);
+			pr_warning("%s: oops! rfd-error-status: %04x\n", dev->name, status);
 			dev->stats.rx_errors++;
 		}
 		p->rfd_top->status = 0;
@@ -1028,7 +1031,7 @@
 	alloc_rfa(dev, (char *) p->rfd_first);
 	startrecv586(dev);	/* restart RU */
 
-	printk(KERN_WARNING "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
+	pr_warning("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
 
 }
 
@@ -1043,7 +1046,7 @@
 
 	status = p->xmit_cmds[p->xmit_last]->cmd_status;
 	if (!(status & STAT_COMPL)) {
-		printk(KERN_WARNING "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
+		pr_warning("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
 	}
 	if (status & STAT_OK) {
 		dev->stats.tx_packets++;
@@ -1051,18 +1054,18 @@
 	} else {
 		dev->stats.tx_errors++;
 		if (status & TCMD_LATECOLL) {
-			printk(KERN_WARNING "%s: late collision detected.\n", dev->name);
+			pr_warning("%s: late collision detected.\n", dev->name);
 			dev->stats.collisions++;
 		} else if (status & TCMD_NOCARRIER) {
 			dev->stats.tx_carrier_errors++;
-			printk(KERN_WARNING "%s: no carrier detected.\n", dev->name);
+			pr_warning("%s: no carrier detected.\n", dev->name);
 		} else if (status & TCMD_LOSTCTS) {
-			printk(KERN_WARNING "%s: loss of CTS detected.\n", dev->name);
+			pr_warning("%s: loss of CTS detected.\n", dev->name);
 		} else if (status & TCMD_UNDERRUN) {
 			dev->stats.tx_fifo_errors++;
-			printk(KERN_WARNING "%s: DMA underrun detected.\n", dev->name);
+			pr_warning("%s: DMA underrun detected.\n", dev->name);
 		} else if (status & TCMD_MAXCOLL) {
-			printk(KERN_WARNING "%s: Max. collisions exceeded.\n", dev->name);
+			pr_warning("%s: Max. collisions exceeded.\n", dev->name);
 			dev->stats.collisions += 16;
 		}
 	}
@@ -1099,10 +1102,11 @@
 	struct priv *p = netdev_priv(dev);
 	/* COMMAND-UNIT active? */
 	if (p->scb->status & CU_ACTIVE) {
-#ifdef DEBUG
-		printk("%s: strange ... timeout with CU active?!?\n", dev->name);
-		printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point);
-#endif
+		pr_debug("%s: strange ... timeout with CU active?!?\n", dev->name);
+		pr_debug("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name,
+			(int)p->xmit_cmds[0]->cmd_status,
+			(int)p->nop_cmds[0]->cmd_status,
+			(int)p->nop_cmds[1]->cmd_status, (int)p->nop_point);
 		p->scb->cmd = CUC_ABORT;
 		elmc_attn586();
 		WAIT_4_SCB_CMD();
@@ -1112,10 +1116,10 @@
 		WAIT_4_SCB_CMD();
 		netif_wake_queue(dev);
 	} else {
-#ifdef DEBUG
-		printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status);
-		printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
-#endif
+		pr_debug("%s: xmitter timed out, try to restart! stat: %04x\n",
+			dev->name, p->scb->status);
+		pr_debug("%s: command-stats: %04x %04x\n", dev->name,
+			p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
 		elmc_close(dev);
 		elmc_open(dev);
 	}
@@ -1162,7 +1166,7 @@
 			break;
 		}
 		if (i == 15) {
-			printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name);
+			pr_warning("%s: Can't start transmit-command.\n", dev->name);
 		}
 	}
 #else
@@ -1287,11 +1291,12 @@
 		free_netdev(dev);
 		if (io[this_dev]==0)
 			break;
-		printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]);
+		pr_warning("3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]);
 	}
 
 	if(found==0) {
-		if(io[0]==0) printk(KERN_NOTICE "3c523.c: No 3c523 cards found\n");
+		if (io[0]==0)
+			pr_notice("3c523.c: No 3c523 cards found\n");
 		return -ENXIO;
 	} else return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c527.c linux-libre-2.6.31-gnu/drivers/net/3c527.c
--- linux-libre-2.6.30-gnu/drivers/net/3c527.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c527.c	2009-09-09 18:13:59.000000000 -0400
@@ -125,8 +125,6 @@
 #define NET_DEBUG 2
 #endif
 
-#undef DEBUG_IRQ
-
 static unsigned int mc32_debug = NET_DEBUG;
 
 /* The number of low I/O ports used by the ethercard. */
@@ -351,15 +349,15 @@
 	/* Time to play MCA games */
 
 	if (mc32_debug  &&  version_printed++ == 0)
-		printk(KERN_DEBUG "%s", version);
+		pr_debug("%s", version);
 
-	printk(KERN_INFO "%s: %s found in slot %d:", dev->name, cardname, slot);
+	pr_info("%s: %s found in slot %d: ", dev->name, cardname, slot);
 
 	POS = mca_read_stored_pos(slot, 2);
 
 	if(!(POS&1))
 	{
-		printk(" disabled.\n");
+		pr_cont("disabled.\n");
 		return -ENODEV;
 	}
 
@@ -370,7 +368,7 @@
 	POS = mca_read_stored_pos(slot, 4);
 	if(!(POS&1))
 	{
-		printk("memory window disabled.\n");
+		pr_cont("memory window disabled.\n");
 		return -ENODEV;
 	}
 
@@ -379,7 +377,7 @@
 	i=(POS>>4)&3;
 	if(i==3)
 	{
-		printk("invalid memory window.\n");
+		pr_cont("invalid memory window.\n");
 		return -ENODEV;
 	}
 
@@ -392,11 +390,11 @@
 
 	if(!request_region(dev->base_addr, MC32_IO_EXTENT, cardname))
 	{
-		printk("io 0x%3lX, which is busy.\n", dev->base_addr);
+		pr_cont("io 0x%3lX, which is busy.\n", dev->base_addr);
 		return -EBUSY;
 	}
 
-	printk("io 0x%3lX irq %d mem 0x%lX (%dK)\n",
+	pr_cont("io 0x%3lX irq %d mem 0x%lX (%dK)\n",
 		dev->base_addr, dev->irq, dev->mem_start, i/1024);
 
 
@@ -416,7 +414,7 @@
 		dev->dev_addr[i] = mca_read_pos(slot,3);
 	}
 
-	printk("%s: Address %pM", dev->name, dev->dev_addr);
+	pr_info("%s: Address %pM ", dev->name, dev->dev_addr);
 
 	mca_write_pos(slot, 6, 0);
 	mca_write_pos(slot, 7, 0);
@@ -424,9 +422,9 @@
 	POS = mca_read_stored_pos(slot, 4);
 
 	if(POS&2)
-		printk(" : BNC port selected.\n");
+		pr_cont(": BNC port selected.\n");
 	else
-		printk(" : AUI port selected.\n");
+		pr_cont(": AUI port selected.\n");
 
 	POS=inb(dev->base_addr+HOST_CTRL);
 	POS|=HOST_CTRL_ATTN|HOST_CTRL_RESET;
@@ -447,7 +445,7 @@
 	err = request_irq(dev->irq, &mc32_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DRV_NAME, dev);
 	if (err) {
 		release_region(dev->base_addr, MC32_IO_EXTENT);
-		printk(KERN_ERR "%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
+		pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
 		goto err_exit_ports;
 	}
 
@@ -463,7 +461,7 @@
 		i++;
 		if(i == 1000)
 		{
-			printk(KERN_ERR "%s: failed to boot adapter.\n", dev->name);
+			pr_err("%s: failed to boot adapter.\n", dev->name);
 			err = -ENODEV;
 			goto err_exit_irq;
 		}
@@ -475,10 +473,10 @@
 	if(base>0)
 	{
 		if(base < 0x0C)
-			printk(KERN_ERR "%s: %s%s.\n", dev->name, failures[base-1],
+			pr_err("%s: %s%s.\n", dev->name, failures[base-1],
 				base<0x0A?" test failure":"");
 		else
-			printk(KERN_ERR "%s: unknown failure %d.\n", dev->name, base);
+			pr_err("%s: unknown failure %d.\n", dev->name, base);
 		err = -ENODEV;
 		goto err_exit_irq;
 	}
@@ -494,7 +492,7 @@
 			udelay(50);
 			if(n>100)
 			{
-				printk(KERN_ERR "%s: mailbox read fail (%d).\n", dev->name, i);
+				pr_err("%s: mailbox read fail (%d).\n", dev->name, i);
 				err = -ENODEV;
 				goto err_exit_irq;
 			}
@@ -527,7 +525,7 @@
 	init_completion(&lp->execution_cmd);
 	init_completion(&lp->xceiver_cmd);
 
-	printk("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n",
+	pr_info("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n",
 		dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base);
 
 	dev->netdev_ops		= &netdev_ops;
@@ -939,7 +937,7 @@
 	 */
 
 	if(mc32_command(dev, 8, descnumbuffs, 4)) {
-		printk("%s: %s rejected our buffer configuration!\n",
+		pr_info("%s: %s rejected our buffer configuration!\n",
 	 	       dev->name, cardname);
 		mc32_close(dev);
 		return -ENOBUFS;
@@ -995,7 +993,7 @@
 
 static void mc32_timeout(struct net_device *dev)
 {
-	printk(KERN_WARNING "%s: transmit timed out?\n", dev->name);
+	pr_warning("%s: transmit timed out?\n", dev->name);
 	/* Try to restart the adaptor. */
 	netif_wake_queue(dev);
 }
@@ -1032,7 +1030,7 @@
 	netif_stop_queue(dev);
 
 	if(atomic_read(&lp->tx_count)==0) {
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	if (skb_padto(skb, ETH_ZLEN)) {
@@ -1335,11 +1333,9 @@
 	{
 		status=inb(ioaddr+HOST_CMD);
 
-#ifdef DEBUG_IRQ
-		printk("Status TX%d RX%d EX%d OV%d BC%d\n",
+		pr_debug("Status TX%d RX%d EX%d OV%d BC%d\n",
 			(status&7), (status>>3)&7, (status>>6)&1,
 			(status>>7)&1, boguscount);
-#endif
 
 		switch(status&7)
 		{
@@ -1354,7 +1350,7 @@
 				complete(&lp->xceiver_cmd);
 				break;
 			default:
-				printk("%s: strange tx ack %d\n", dev->name, status&7);
+				pr_notice("%s: strange tx ack %d\n", dev->name, status&7);
 		}
 		status>>=3;
 		switch(status&7)
@@ -1376,7 +1372,7 @@
 				mc32_start_transceiver(dev);
 				break;
 			default:
-				printk("%s: strange rx ack %d\n",
+				pr_notice("%s: strange rx ack %d\n",
 					dev->name, status&7);
 		}
 		status>>=3;
diff -druN linux-libre-2.6.30-gnu/drivers/net/3c59x.c linux-libre-2.6.31-gnu/drivers/net/3c59x.c
--- linux-libre-2.6.30-gnu/drivers/net/3c59x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/3c59x.c	2009-09-09 18:13:59.000000000 -0400
@@ -235,6 +235,7 @@
 	CH_3C900B_FL,
 	CH_3C905_1,
 	CH_3C905_2,
+	CH_3C905B_TX,
 	CH_3C905B_1,
 
 	CH_3C905B_2,
@@ -307,6 +308,8 @@
 	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
 	{"3c905 Boomerang 100baseT4",
 	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
+	{"3C905B-TX Fast Etherlink XL PCI",
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 	{"3c905B Cyclone 100baseTx",
 	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 
@@ -389,6 +392,7 @@
 	{ 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL },
 	{ 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 },
 	{ 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 },
+	{ 0x10B7, 0x9054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_TX },
 	{ 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 },
 
 	{ 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
@@ -828,14 +832,14 @@
 		pci_restore_state(pdev);
 		err = pci_enable_device(pdev);
 		if (err) {
-			printk(KERN_WARNING "%s: Could not enable device \n",
+			pr_warning("%s: Could not enable device\n",
 				dev->name);
 			return err;
 		}
 		pci_set_master(pdev);
 		if (request_irq(dev->irq, vp->full_bus_master_rx ?
 				&boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) {
-			printk(KERN_WARNING "%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
+			pr_warning("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
 			pci_disable_device(pdev);
 			return -EBUSY;
 		}
@@ -894,7 +898,7 @@
 	dev = eisa_get_drvdata(edev);
 
 	if (!dev) {
-		printk("vortex_eisa_remove called for Compaq device!\n");
+		pr_err("vortex_eisa_remove called for Compaq device!\n");
 		BUG();
 	}
 
@@ -1051,7 +1055,7 @@
 	struct eisa_device *edev = NULL;
 
 	if (!printed_version) {
-		printk (version);
+		pr_info("%s", version);
 		printed_version = 1;
 	}
 
@@ -1068,7 +1072,7 @@
 	dev = alloc_etherdev(sizeof(*vp));
 	retval = -ENOMEM;
 	if (!dev) {
-		printk (KERN_ERR PFX "unable to allocate etherdev, aborting\n");
+		pr_err(PFX "unable to allocate etherdev, aborting\n");
 		goto out;
 	}
 	SET_NETDEV_DEV(dev, gendev);
@@ -1100,9 +1104,9 @@
 
 	print_info = (vortex_debug > 1);
 	if (print_info)
-		printk (KERN_INFO "See Documentation/networking/vortex.txt\n");
+		pr_info("See Documentation/networking/vortex.txt\n");
 
-	printk(KERN_INFO "%s: 3Com %s %s at %p.\n",
+	pr_info("%s: 3Com %s %s at %p.\n",
 	       print_name,
 	       pdev ? "PCI" : "EISA",
 	       vci->name,
@@ -1144,10 +1148,9 @@
 			   chip only. */
 			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 			if (pci_latency < new_latency) {
-				printk(KERN_INFO "%s: Overriding PCI latency"
-					" timer (CFLT) setting of %d, new value is %d.\n",
+				pr_info("%s: Overriding PCI latency timer (CFLT) setting of %d, new value is %d.\n",
 					print_name, pci_latency, new_latency);
-					pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
 			}
 		}
 	}
@@ -1236,17 +1239,17 @@
 		checksum = (checksum ^ (checksum >> 8)) & 0xff;
 	}
 	if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO))
-		printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
+		pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
 	for (i = 0; i < 3; i++)
 		((__be16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 	if (print_info)
-		printk(" %pM", dev->dev_addr);
+		pr_cont(" %pM", dev->dev_addr);
 	/* Unfortunately an all zero eeprom passes the checksum and this
 	   gets found in the wild in failure cases. Crypto is hard 8) */
 	if (!is_valid_ether_addr(dev->dev_addr)) {
 		retval = -EINVAL;
-		printk(KERN_ERR "*** EEPROM MAC address is invalid.\n");
+		pr_err("*** EEPROM MAC address is invalid.\n");
 		goto free_ring;	/* With every pack */
 	}
 	EL3WINDOW(2);
@@ -1254,17 +1257,17 @@
 		iowrite8(dev->dev_addr[i], ioaddr + i);
 
 	if (print_info)
-		printk(", IRQ %d\n", dev->irq);
+		pr_cont(", IRQ %d\n", dev->irq);
 	/* Tell them about an invalid IRQ. */
 	if (dev->irq <= 0 || dev->irq >= nr_irqs)
-		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
+		pr_warning(" *** Warning: IRQ %d is unlikely to work! ***\n",
 			   dev->irq);
 
 	EL3WINDOW(4);
 	step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
 	if (print_info) {
-		printk(KERN_INFO "  product code %02x%02x rev %02x.%d date %02d-"
-			"%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
+		pr_info("  product code %02x%02x rev %02x.%d date %02d-%02d-%02d\n",
+			eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
 			step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);
 	}
 
@@ -1279,8 +1282,7 @@
 		}
 
 		if (print_info) {
-			printk(KERN_INFO "%s: CardBus functions mapped "
-				"%16.16llx->%p\n",
+			pr_info("%s: CardBus functions mapped %16.16llx->%p\n",
 				print_name,
 				(unsigned long long)pci_resource_start(pdev, 2),
 				vp->cb_fn_base);
@@ -1307,7 +1309,7 @@
 	if (vp->info1 & 0x8000) {
 		vp->full_duplex = 1;
 		if (print_info)
-			printk(KERN_INFO "Full duplex capable\n");
+			pr_info("Full duplex capable\n");
 	}
 
 	{
@@ -1319,9 +1321,9 @@
 			vp->available_media = 0x40;
 		config = ioread32(ioaddr + Wn3_Config);
 		if (print_info) {
-			printk(KERN_DEBUG "  Internal config register is %4.4x, "
-				   "transceivers %#x.\n", config, ioread16(ioaddr + Wn3_Options));
-			printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+			pr_debug("  Internal config register is %4.4x, transceivers %#x.\n",
+				config, ioread16(ioaddr + Wn3_Options));
+			pr_info("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
 				   8 << RAM_SIZE(config),
 				   RAM_WIDTH(config) ? "word" : "byte",
 				   ram_split[RAM_SPLIT(config)],
@@ -1336,7 +1338,7 @@
 	}
 
 	if (vp->media_override != 7) {
-		printk(KERN_INFO "%s:  Media override to transceiver type %d (%s).\n",
+		pr_info("%s:  Media override to transceiver type %d (%s).\n",
 				print_name, vp->media_override,
 				media_tbl[vp->media_override].name);
 		dev->if_port = vp->media_override;
@@ -1369,8 +1371,8 @@
 			if (mii_status  &&  mii_status != 0xffff) {
 				vp->phys[phy_idx++] = phyx;
 				if (print_info) {
-					printk(KERN_INFO "  MII transceiver found at address %d,"
-						" status %4x.\n", phyx, mii_status);
+					pr_info("  MII transceiver found at address %d, status %4x.\n",
+						phyx, mii_status);
 				}
 				if ((mii_status & 0x0040) == 0)
 					mii_preamble_required++;
@@ -1378,7 +1380,7 @@
 		}
 		mii_preamble_required--;
 		if (phy_idx == 0) {
-			printk(KERN_WARNING"  ***WARNING*** No MII transceivers found!\n");
+			pr_warning("  ***WARNING*** No MII transceivers found!\n");
 			vp->phys[0] = 24;
 		} else {
 			vp->advertising = mdio_read(dev, vp->phys[0], MII_ADVERTISE);
@@ -1394,7 +1396,7 @@
 	if (vp->capabilities & CapBusMaster) {
 		vp->full_bus_master_tx = 1;
 		if (print_info) {
-			printk(KERN_INFO "  Enabling bus-master transmits and %s receives.\n",
+			pr_info("  Enabling bus-master transmits and %s receives.\n",
 			(vp->info2 & 1) ? "early" : "whole-frame" );
 		}
 		vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
@@ -1414,7 +1416,7 @@
 		dev->netdev_ops =  &vortex_netdev_ops;
 
 	if (print_info) {
-		printk(KERN_INFO "%s: scatter/gather %sabled. h/w checksums %sabled\n",
+		pr_info("%s: scatter/gather %sabled. h/w checksums %sabled\n",
 				print_name,
 				(dev->features & NETIF_F_SG) ? "en":"dis",
 				(dev->features & NETIF_F_IP_CSUM) ? "en":"dis");
@@ -1442,7 +1444,7 @@
 	if (vp->must_free_region)
 		release_region(dev->base_addr, vci->io_size);
 	free_netdev(dev);
-	printk(KERN_ERR PFX "vortex_probe1 fails.  Returns %d\n", retval);
+	pr_err(PFX "vortex_probe1 fails.  Returns %d\n", retval);
 out:
 	return retval;
 }
@@ -1464,13 +1466,13 @@
 	for (i = 0; i < 100000; i++) {
 		if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) {
 			if (vortex_debug > 1)
-				printk(KERN_INFO "%s: command 0x%04x took %d usecs\n",
+				pr_info("%s: command 0x%04x took %d usecs\n",
 					   dev->name, cmd, i * 10);
 			return;
 		}
 		udelay(10);
 	}
-	printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n",
+	pr_err("%s: command 0x%04x did not complete! Status=0x%x\n",
 			   dev->name, cmd, ioread16(ioaddr + EL3_STATUS));
 }
 
@@ -1480,7 +1482,7 @@
 	struct vortex_private *vp = netdev_priv(dev);
 	void __iomem *ioaddr = vp->ioaddr;
 
-	printk(KERN_INFO "%s:  setting %s-duplex.\n",
+	pr_info("%s:  setting %s-duplex.\n",
 		dev->name, (vp->full_duplex) ? "full" : "half");
 
 	EL3WINDOW(3);
@@ -1522,7 +1524,7 @@
 			pci_restore_state(VORTEX_PCI(vp));
 		err = pci_enable_device(VORTEX_PCI(vp));
 		if (err) {
-			printk(KERN_WARNING "%s: Could not enable device \n",
+			pr_warning("%s: Could not enable device\n",
 				dev->name);
 			goto err_out;
 		}
@@ -1533,14 +1535,14 @@
 	config = ioread32(ioaddr + Wn3_Config);
 
 	if (vp->media_override != 7) {
-		printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
+		pr_info("%s: Media override to transceiver %d (%s).\n",
 			   dev->name, vp->media_override,
 			   media_tbl[vp->media_override].name);
 		dev->if_port = vp->media_override;
 	} else if (vp->autoselect) {
 		if (vp->has_nway) {
 			if (vortex_debug > 1)
-				printk(KERN_INFO "%s: using NWAY device table, not %d\n",
+				pr_info("%s: using NWAY device table, not %d\n",
 								dev->name, dev->if_port);
 			dev->if_port = XCVR_NWAY;
 		} else {
@@ -1549,13 +1551,13 @@
 			while (! (vp->available_media & media_tbl[dev->if_port].mask))
 				dev->if_port = media_tbl[dev->if_port].next;
 			if (vortex_debug > 1)
-				printk(KERN_INFO "%s: first available media type: %s\n",
+				pr_info("%s: first available media type: %s\n",
 					dev->name, media_tbl[dev->if_port].name);
 		}
 	} else {
 		dev->if_port = vp->default_media;
 		if (vortex_debug > 1)
-			printk(KERN_INFO "%s: using default media %s\n",
+			pr_info("%s: using default media %s\n",
 				dev->name, media_tbl[dev->if_port].name);
 	}
 
@@ -1570,13 +1572,13 @@
 	vp->rx_oom_timer.function = rx_oom_timer;
 
 	if (vortex_debug > 1)
-		printk(KERN_DEBUG "%s: Initial media type %s.\n",
+		pr_debug("%s: Initial media type %s.\n",
 			   dev->name, media_tbl[dev->if_port].name);
 
 	vp->full_duplex = vp->mii.force_media;
 	config = BFINS(config, dev->if_port, 20, 4);
 	if (vortex_debug > 6)
-		printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config);
+		pr_debug("vortex_up(): writing 0x%x to InternalConfig\n", config);
 	iowrite32(config, ioaddr + Wn3_Config);
 
 	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
@@ -1602,7 +1604,7 @@
 
 	if (vortex_debug > 1) {
 		EL3WINDOW(4);
-		printk(KERN_DEBUG "%s: vortex_up() irq %d media status %4.4x.\n",
+		pr_debug("%s: vortex_up() irq %d media status %4.4x.\n",
 			   dev->name, dev->irq, ioread16(ioaddr + Wn4_Media));
 	}
 
@@ -1704,13 +1706,13 @@
 	/* Use the now-standard shared IRQ implementation. */
 	if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ?
 				&boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev))) {
-		printk(KERN_ERR "%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
+		pr_err("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
 		goto err;
 	}
 
 	if (vp->full_bus_master_rx) { /* Boomerang bus master. */
 		if (vortex_debug > 2)
-			printk(KERN_DEBUG "%s:  Filling in the Rx ring.\n", dev->name);
+			pr_debug("%s:  Filling in the Rx ring.\n", dev->name);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			struct sk_buff *skb;
 			vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1));
@@ -1728,7 +1730,7 @@
 		}
 		if (i != RX_RING_SIZE) {
 			int j;
-			printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name);
+			pr_emerg("%s: no memory for rx ring\n", dev->name);
 			for (j = 0; j < i; j++) {
 				if (vp->rx_skbuff[j]) {
 					dev_kfree_skb(vp->rx_skbuff[j]);
@@ -1750,7 +1752,7 @@
 	free_irq(dev->irq, dev);
 err:
 	if (vortex_debug > 1)
-		printk(KERN_ERR "%s: vortex_open() fails: returning %d\n", dev->name, retval);
+		pr_err("%s: vortex_open() fails: returning %d\n", dev->name, retval);
 out:
 	return retval;
 }
@@ -1766,9 +1768,9 @@
 	int media_status, old_window;
 
 	if (vortex_debug > 2) {
-		printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
+		pr_debug("%s: Media selection timer tick happened, %s.\n",
 			   dev->name, media_tbl[dev->if_port].name);
-		printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo);
+		pr_debug("dev->watchdog_timeo=%d\n", dev->watchdog_timeo);
 	}
 
 	disable_irq_lockdep(dev->irq);
@@ -1781,12 +1783,12 @@
 			netif_carrier_on(dev);
 			ok = 1;
 			if (vortex_debug > 1)
-				printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",
+				pr_debug("%s: Media %s has link beat, %x.\n",
 					   dev->name, media_tbl[dev->if_port].name, media_status);
 		} else {
 			netif_carrier_off(dev);
 			if (vortex_debug > 1) {
-				printk(KERN_DEBUG "%s: Media %s has no link beat, %x.\n",
+				pr_debug("%s: Media %s has no link beat, %x.\n",
 					   dev->name, media_tbl[dev->if_port].name, media_status);
 			}
 		}
@@ -1802,7 +1804,7 @@
 		break;
 	  default:					/* Other media types handled by Tx timeouts. */
 		if (vortex_debug > 1)
-		  printk(KERN_DEBUG "%s: Media %s has no indication, %x.\n",
+		  pr_debug("%s: Media %s has no indication, %x.\n",
 				 dev->name, media_tbl[dev->if_port].name, media_status);
 		ok = 1;
 	}
@@ -1822,13 +1824,11 @@
 		if (dev->if_port == XCVR_Default) { /* Go back to default. */
 		  dev->if_port = vp->default_media;
 		  if (vortex_debug > 1)
-			printk(KERN_DEBUG "%s: Media selection failing, using default "
-				   "%s port.\n",
+			pr_debug("%s: Media selection failing, using default %s port.\n",
 				   dev->name, media_tbl[dev->if_port].name);
 		} else {
 			if (vortex_debug > 1)
-				printk(KERN_DEBUG "%s: Media selection failed, now trying "
-					   "%s port.\n",
+				pr_debug("%s: Media selection failed, now trying %s port.\n",
 					   dev->name, media_tbl[dev->if_port].name);
 			next_tick = media_tbl[dev->if_port].wait;
 		}
@@ -1843,13 +1843,13 @@
 		iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
 			 ioaddr + EL3_CMD);
 		if (vortex_debug > 1)
-			printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config);
+			pr_debug("wrote 0x%08x to Wn3_Config\n", config);
 		/* AKPM: FIXME: Should reset Rx & Tx here.  P60 of 3c90xc.pdf */
 	}
 
 leave_media_alone:
 	if (vortex_debug > 2)
-	  printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
+	  pr_debug("%s: Media selection timer finished, %s.\n",
 			 dev->name, media_tbl[dev->if_port].name);
 
 	EL3WINDOW(old_window);
@@ -1865,21 +1865,21 @@
 	struct vortex_private *vp = netdev_priv(dev);
 	void __iomem *ioaddr = vp->ioaddr;
 
-	printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+	pr_err("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
 		   dev->name, ioread8(ioaddr + TxStatus),
 		   ioread16(ioaddr + EL3_STATUS));
 	EL3WINDOW(4);
-	printk(KERN_ERR "  diagnostics: net %04x media %04x dma %08x fifo %04x\n",
+	pr_err("  diagnostics: net %04x media %04x dma %08x fifo %04x\n",
 			ioread16(ioaddr + Wn4_NetDiag),
 			ioread16(ioaddr + Wn4_Media),
 			ioread32(ioaddr + PktStatus),
 			ioread16(ioaddr + Wn4_FIFODiag));
 	/* Slight code bloat to be user friendly. */
 	if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88)
-		printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
+		pr_err("%s: Transmitter encountered 16 collisions --"
 			   " network cable problem?\n", dev->name);
 	if (ioread16(ioaddr + EL3_STATUS) & IntLatch) {
-		printk(KERN_ERR "%s: Interrupt posted but not delivered --"
+		pr_err("%s: Interrupt posted but not delivered --"
 			   " IRQ blocked by another device?\n", dev->name);
 		/* Bad idea here.. but we might as well handle a few events. */
 		{
@@ -1903,7 +1903,7 @@
 
 	dev->stats.tx_errors++;
 	if (vp->full_bus_master_tx) {
-		printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n", dev->name);
+		pr_debug("%s: Resetting the Tx ring pointer.\n", dev->name);
 		if (vp->cur_tx - vp->dirty_tx > 0  &&  ioread32(ioaddr + DownListPtr) == 0)
 			iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
 				 ioaddr + DownListPtr);
@@ -1938,7 +1938,7 @@
 	unsigned char tx_status = 0;
 
 	if (vortex_debug > 2) {
-		printk(KERN_ERR "%s: vortex_error(), status=0x%x\n", dev->name, status);
+		pr_err("%s: vortex_error(), status=0x%x\n", dev->name, status);
 	}
 
 	if (status & TxComplete) {			/* Really "TxError" for us. */
@@ -1946,10 +1946,10 @@
 		/* Presumably a tx-timeout. We must merely re-enable. */
 		if (vortex_debug > 2
 			|| (tx_status != 0x88 && vortex_debug > 0)) {
-			printk(KERN_ERR "%s: Transmit error, Tx status register %2.2x.\n",
+			pr_err("%s: Transmit error, Tx status register %2.2x.\n",
 				   dev->name, tx_status);
 			if (tx_status == 0x82) {
-				printk(KERN_ERR "Probably a duplex mismatch.  See "
+				pr_err("Probably a duplex mismatch.  See "
 						"Documentation/networking/vortex.txt\n");
 			}
 			dump_tx_ring(dev);
@@ -1975,13 +1975,13 @@
 	if (status & StatsFull) {			/* Empty statistics. */
 		static int DoneDidThat;
 		if (vortex_debug > 4)
-			printk(KERN_DEBUG "%s: Updating stats.\n", dev->name);
+			pr_debug("%s: Updating stats.\n", dev->name);
 		update_stats(ioaddr, dev);
 		/* HACK: Disable statistics as an interrupt source. */
 		/* This occurs when we have the wrong media type! */
 		if (DoneDidThat == 0  &&
 			ioread16(ioaddr + EL3_STATUS) & StatsFull) {
-			printk(KERN_WARNING "%s: Updating statistics failed, disabling "
+			pr_warning("%s: Updating statistics failed, disabling "
 				   "stats as an interrupt source.\n", dev->name);
 			EL3WINDOW(5);
 			iowrite16(SetIntrEnb | (ioread16(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
@@ -1998,7 +1998,7 @@
 		u16 fifo_diag;
 		EL3WINDOW(4);
 		fifo_diag = ioread16(ioaddr + Wn4_FIFODiag);
-		printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n",
+		pr_err("%s: Host error, FIFO diagnostic register %4.4x.\n",
 			   dev->name, fifo_diag);
 		/* Adapter failure requires Tx/Rx reset and reinit. */
 		if (vp->full_bus_master_tx) {
@@ -2006,7 +2006,7 @@
 			/* 0x80000000 PCI master abort. */
 			/* 0x40000000 PCI target abort. */
 			if (vortex_debug)
-				printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
+				pr_err("%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
 
 			/* In this case, blow the card away */
 			/* Must not enter D3 or we can't legally issue the reset! */
@@ -2075,7 +2075,7 @@
 		while (--i > 0	&&	(tx_status = ioread8(ioaddr + TxStatus)) > 0) {
 			if (tx_status & 0x3C) {		/* A Tx-disabling error occurred.  */
 				if (vortex_debug > 2)
-				  printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n",
+				  pr_debug("%s: Tx error, status %2.2x.\n",
 						 dev->name, tx_status);
 				if (tx_status & 0x04) dev->stats.tx_fifo_errors++;
 				if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
@@ -2101,17 +2101,17 @@
 	unsigned long flags;
 
 	if (vortex_debug > 6) {
-		printk(KERN_DEBUG "boomerang_start_xmit()\n");
-		printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
+		pr_debug("boomerang_start_xmit()\n");
+		pr_debug("%s: Trying to send a packet, Tx index %d.\n",
 			   dev->name, vp->cur_tx);
 	}
 
 	if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
 		if (vortex_debug > 0)
-			printk(KERN_WARNING "%s: BUG! Tx Ring full, refusing to send buffer.\n",
+			pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n",
 				   dev->name);
 		netif_stop_queue(dev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	vp->tx_skbuff[entry] = skb;
@@ -2204,7 +2204,7 @@
 	status = ioread16(ioaddr + EL3_STATUS);
 
 	if (vortex_debug > 6)
-		printk("vortex_interrupt(). status=0x%4x\n", status);
+		pr_debug("vortex_interrupt(). status=0x%4x\n", status);
 
 	if ((status & IntLatch) == 0)
 		goto handler_exit;		/* No interrupt: shared IRQs cause this */
@@ -2219,19 +2219,19 @@
 		goto handler_exit;
 
 	if (vortex_debug > 4)
-		printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
+		pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n",
 			   dev->name, status, ioread8(ioaddr + Timer));
 
 	do {
 		if (vortex_debug > 5)
-				printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
+				pr_debug("%s: In interrupt loop, status %4.4x.\n",
 					   dev->name, status);
 		if (status & RxComplete)
 			vortex_rx(dev);
 
 		if (status & TxAvailable) {
 			if (vortex_debug > 5)
-				printk(KERN_DEBUG "	TX room bit was handled.\n");
+				pr_debug("	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			iowrite16(AckIntr | TxAvailable, ioaddr + EL3_CMD);
 			netif_wake_queue (dev);
@@ -2263,8 +2263,8 @@
 		}
 
 		if (--work_done < 0) {
-			printk(KERN_WARNING "%s: Too much work in interrupt, status "
-				   "%4.4x.\n", dev->name, status);
+			pr_warning("%s: Too much work in interrupt, status %4.4x.\n",
+				dev->name, status);
 			/* Disable all pending interrupts. */
 			do {
 				vp->deferred |= status;
@@ -2281,7 +2281,7 @@
 	} while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
 
 	if (vortex_debug > 4)
-		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
+		pr_debug("%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
 handler_exit:
 	spin_unlock(&vp->lock);
@@ -2313,14 +2313,14 @@
 	status = ioread16(ioaddr + EL3_STATUS);
 
 	if (vortex_debug > 6)
-		printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status);
+		pr_debug("boomerang_interrupt. status=0x%4x\n", status);
 
 	if ((status & IntLatch) == 0)
 		goto handler_exit;		/* No interrupt: shared IRQs can cause this */
 
 	if (status == 0xffff) {		/* h/w no longer present (hotplug)? */
 		if (vortex_debug > 1)
-			printk(KERN_DEBUG "boomerang_interrupt(1): status = 0xffff\n");
+			pr_debug("boomerang_interrupt(1): status = 0xffff\n");
 		goto handler_exit;
 	}
 
@@ -2330,16 +2330,16 @@
 	}
 
 	if (vortex_debug > 4)
-		printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
+		pr_debug("%s: interrupt, status %4.4x, latency %d ticks.\n",
 			   dev->name, status, ioread8(ioaddr + Timer));
 	do {
 		if (vortex_debug > 5)
-				printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
+				pr_debug("%s: In interrupt loop, status %4.4x.\n",
 					   dev->name, status);
 		if (status & UpComplete) {
 			iowrite16(AckIntr | UpComplete, ioaddr + EL3_CMD);
 			if (vortex_debug > 5)
-				printk(KERN_DEBUG "boomerang_interrupt->boomerang_rx\n");
+				pr_debug("boomerang_interrupt->boomerang_rx\n");
 			boomerang_rx(dev);
 		}
 
@@ -2374,7 +2374,7 @@
 					dev_kfree_skb_irq(skb);
 					vp->tx_skbuff[entry] = NULL;
 				} else {
-					printk(KERN_DEBUG "boomerang_interrupt: no skb!\n");
+					pr_debug("boomerang_interrupt: no skb!\n");
 				}
 				/* dev->stats.tx_packets++;  Counted below. */
 				dirty_tx++;
@@ -2382,7 +2382,7 @@
 			vp->dirty_tx = dirty_tx;
 			if (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1) {
 				if (vortex_debug > 6)
-					printk(KERN_DEBUG "boomerang_interrupt: wake queue\n");
+					pr_debug("boomerang_interrupt: wake queue\n");
 				netif_wake_queue (dev);
 			}
 		}
@@ -2392,8 +2392,8 @@
 			vortex_error(dev, status);
 
 		if (--work_done < 0) {
-			printk(KERN_WARNING "%s: Too much work in interrupt, status "
-				   "%4.4x.\n", dev->name, status);
+			pr_warning("%s: Too much work in interrupt, status %4.4x.\n",
+				dev->name, status);
 			/* Disable all pending interrupts. */
 			do {
 				vp->deferred |= status;
@@ -2413,7 +2413,7 @@
 	} while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch);
 
 	if (vortex_debug > 4)
-		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
+		pr_debug("%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
 handler_exit:
 	spin_unlock(&vp->lock);
@@ -2428,13 +2428,13 @@
 	short rx_status;
 
 	if (vortex_debug > 5)
-		printk(KERN_DEBUG "vortex_rx(): status %4.4x, rx_status %4.4x.\n",
+		pr_debug("vortex_rx(): status %4.4x, rx_status %4.4x.\n",
 			   ioread16(ioaddr+EL3_STATUS), ioread16(ioaddr+RxStatus));
 	while ((rx_status = ioread16(ioaddr + RxStatus)) > 0) {
 		if (rx_status & 0x4000) { /* Error, update stats. */
 			unsigned char rx_error = ioread8(ioaddr + RxErrors);
 			if (vortex_debug > 2)
-				printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
+				pr_debug(" Rx error: status %2.2x.\n", rx_error);
 			dev->stats.rx_errors++;
 			if (rx_error & 0x01)  dev->stats.rx_over_errors++;
 			if (rx_error & 0x02)  dev->stats.rx_length_errors++;
@@ -2448,7 +2448,7 @@
 
 			skb = dev_alloc_skb(pkt_len + 5);
 			if (vortex_debug > 4)
-				printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
+				pr_debug("Receiving packet size %d status %4.4x.\n",
 					   pkt_len, rx_status);
 			if (skb != NULL) {
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
@@ -2478,8 +2478,8 @@
 						break;
 				continue;
 			} else if (vortex_debug > 0)
-				printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of "
-					   "size %d.\n", dev->name, pkt_len);
+				pr_notice("%s: No memory to allocate a sk_buff of size %d.\n",
+					dev->name, pkt_len);
 			dev->stats.rx_dropped++;
 		}
 		issue_and_wait(dev, RxDiscard);
@@ -2498,7 +2498,7 @@
 	int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
 
 	if (vortex_debug > 5)
-		printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS));
+		pr_debug("boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS));
 
 	while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
 		if (--rx_work_limit < 0)
@@ -2506,7 +2506,7 @@
 		if (rx_status & RxDError) { /* Error, update stats. */
 			unsigned char rx_error = rx_status >> 16;
 			if (vortex_debug > 2)
-				printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
+				pr_debug(" Rx error: status %2.2x.\n", rx_error);
 			dev->stats.rx_errors++;
 			if (rx_error & 0x01)  dev->stats.rx_over_errors++;
 			if (rx_error & 0x02)  dev->stats.rx_length_errors++;
@@ -2520,7 +2520,7 @@
 			dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr);
 
 			if (vortex_debug > 4)
-				printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
+				pr_debug("Receiving packet size %d status %4.4x.\n",
 					   pkt_len, rx_status);
 
 			/* Check if the packet is long enough to just accept without
@@ -2566,7 +2566,7 @@
 			if (skb == NULL) {
 				static unsigned long last_jif;
 				if (time_after(jiffies, last_jif + 10 * HZ)) {
-					printk(KERN_WARNING "%s: memory shortage\n", dev->name);
+					pr_warning("%s: memory shortage\n", dev->name);
 					last_jif = jiffies;
 				}
 				if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)
@@ -2598,7 +2598,7 @@
 	if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)	/* This test is redundant, but makes me feel good */
 		boomerang_rx(dev);
 	if (vortex_debug > 1) {
-		printk(KERN_DEBUG "%s: rx_oom_timer %s\n", dev->name,
+		pr_debug("%s: rx_oom_timer %s\n", dev->name,
 			((vp->cur_rx - vp->dirty_rx) != RX_RING_SIZE) ? "succeeded" : "retrying");
 	}
 	spin_unlock_irq(&vp->lock);
@@ -2655,9 +2655,9 @@
 		vortex_down(dev, 1);
 
 	if (vortex_debug > 1) {
-		printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
+		pr_debug("%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
 			   dev->name, ioread16(ioaddr + EL3_STATUS), ioread8(ioaddr + TxStatus));
-		printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d"
+		pr_debug("%s: vortex close stats: rx_nocopy %d rx_copy %d"
 			   " tx_queued %d Rx pre-checksummed %d.\n",
 			   dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits);
 	}
@@ -2666,8 +2666,7 @@
 	if (vp->rx_csumhits &&
 	    (vp->drv_flags & HAS_HWCKSM) == 0 &&
 	    (vp->card_idx >= MAX_UNITS || hw_checksums[vp->card_idx] == -1)) {
-			printk(KERN_WARNING "%s supports hardware checksums, and we're "
-						"not using them!\n", dev->name);
+		pr_warning("%s supports hardware checksums, and we're not using them!\n", dev->name);
 	}
 #endif
 
@@ -2717,22 +2716,24 @@
 			int i;
 			int stalled = ioread32(ioaddr + PktStatus) & 0x04;	/* Possible racy. But it's only debug stuff */
 
-			printk(KERN_ERR "  Flags; bus-master %d, dirty %d(%d) current %d(%d)\n",
+			pr_err("  Flags; bus-master %d, dirty %d(%d) current %d(%d)\n",
 					vp->full_bus_master_tx,
 					vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
 					vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
-			printk(KERN_ERR "  Transmit list %8.8x vs. %p.\n",
+			pr_err("  Transmit list %8.8x vs. %p.\n",
 				   ioread32(ioaddr + DownListPtr),
 				   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
 			issue_and_wait(dev, DownStall);
 			for (i = 0; i < TX_RING_SIZE; i++) {
-				printk(KERN_ERR "  %d: @%p  length %8.8x status %8.8x\n", i,
-					   &vp->tx_ring[i],
+				unsigned int length;
+
 #if DO_ZEROCOPY
-					   le32_to_cpu(vp->tx_ring[i].frag[0].length),
+				length = le32_to_cpu(vp->tx_ring[i].frag[0].length);
 #else
-					   le32_to_cpu(vp->tx_ring[i].length),
+				length = le32_to_cpu(vp->tx_ring[i].length);
 #endif
+				pr_err("  %d: @%p  length %8.8x status %8.8x\n",
+					   i, &vp->tx_ring[i], length,
 					   le32_to_cpu(vp->tx_ring[i].status));
 			}
 			if (!stalled)
@@ -2970,7 +2971,7 @@
 
 	if (dev->flags & IFF_PROMISC) {
 		if (vortex_debug > 3)
-			printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name);
+			pr_notice("%s: Setting promiscuous mode.\n", dev->name);
 		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
 	} else	if ((dev->mc_list)  ||  (dev->flags & IFF_ALLMULTI)) {
 		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
@@ -3145,8 +3146,7 @@
 		iowrite16(RxEnable, ioaddr + EL3_CMD);
 
 		if (pci_enable_wake(VORTEX_PCI(vp), PCI_D3hot, 1)) {
-			printk(KERN_INFO "%s: WOL not supported.\n",
-					pci_name(VORTEX_PCI(vp)));
+			pr_info("%s: WOL not supported.\n", pci_name(VORTEX_PCI(vp)));
 
 			vp->enable_wol = 0;
 			return;
@@ -3164,7 +3164,7 @@
 	struct vortex_private *vp;
 
 	if (!dev) {
-		printk("vortex_remove_one called for Compaq device!\n");
+		pr_err("vortex_remove_one called for Compaq device!\n");
 		BUG();
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/7990.c linux-libre-2.6.31-gnu/drivers/net/7990.c
--- linux-libre-2.6.30-gnu/drivers/net/7990.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/7990.c	2009-09-09 18:13:59.000000000 -0400
@@ -541,7 +541,7 @@
 	unsigned long flags;
 
         if (!TX_BUFFS_AVAIL)
-                return -1;
+                return NETDEV_TX_LOCKED;
 
 	netif_stop_queue (dev);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/8139cp.c linux-libre-2.6.31-gnu/drivers/net/8139cp.c
--- linux-libre-2.6.30-gnu/drivers/net/8139cp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/8139cp.c	2009-09-09 18:13:59.000000000 -0400
@@ -471,8 +471,7 @@
 			    u32 status, u32 len)
 {
 	if (netif_msg_rx_err (cp))
-		printk (KERN_DEBUG
-			"%s: rx err, slot %d status 0x%x len %d\n",
+		pr_debug("%s: rx err, slot %d status 0x%x len %d\n",
 			cp->dev->name, rx_tail, status, len);
 	cp->dev->stats.rx_errors++;
 	if (status & RxErrFrame)
@@ -516,7 +515,7 @@
 		dma_addr_t mapping;
 		struct sk_buff *skb, *new_skb;
 		struct cp_desc *desc;
-		unsigned buflen;
+		const unsigned buflen = cp->rx_buf_sz;
 
 		skb = cp->rx_skb[rx_tail];
 		BUG_ON(!skb);
@@ -547,11 +546,10 @@
 		}
 
 		if (netif_msg_rx_status(cp))
-			printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
+			pr_debug("%s: rx slot %d status 0x%x len %d\n",
 			       dev->name, rx_tail, status, len);
 
-		buflen = cp->rx_buf_sz + NET_IP_ALIGN;
-		new_skb = netdev_alloc_skb(dev, buflen);
+		new_skb = netdev_alloc_skb(dev, buflen + NET_IP_ALIGN);
 		if (!new_skb) {
 			dev->stats.rx_dropped++;
 			goto rx_next;
@@ -626,7 +624,7 @@
 		return IRQ_NONE;
 
 	if (netif_msg_intr(cp))
-		printk(KERN_DEBUG "%s: intr, status %04x cmd %02x cpcmd %04x\n",
+		pr_debug("%s: intr, status %04x cmd %02x cpcmd %04x\n",
 		        dev->name, status, cpr8(Cmd), cpr16(CpCmd));
 
 	cpw16(IntrStatus, status & ~cp_rx_intr_mask);
@@ -658,7 +656,7 @@
 
 		pci_read_config_word(cp->pdev, PCI_STATUS, &pci_status);
 		pci_write_config_word(cp->pdev, PCI_STATUS, pci_status);
-		printk(KERN_ERR "%s: PCI bus error, status=%04x, PCI status=%04x\n",
+		pr_err("%s: PCI bus error, status=%04x, PCI status=%04x\n",
 		       dev->name, status, pci_status);
 
 		/* TODO: reset hardware */
@@ -705,7 +703,7 @@
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
 				if (netif_msg_tx_err(cp))
-					printk(KERN_DEBUG "%s: tx err, status 0x%x\n",
+					pr_debug("%s: tx err, status 0x%x\n",
 					       cp->dev->name, status);
 				cp->dev->stats.tx_errors++;
 				if (status & TxOWC)
@@ -722,7 +720,7 @@
 				cp->dev->stats.tx_packets++;
 				cp->dev->stats.tx_bytes += skb->len;
 				if (netif_msg_tx_done(cp))
-					printk(KERN_DEBUG "%s: tx done, slot %d\n", cp->dev->name, tx_tail);
+					pr_debug("%s: tx done, slot %d\n", cp->dev->name, tx_tail);
 			}
 			dev_kfree_skb_irq(skb);
 		}
@@ -755,9 +753,9 @@
 	if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
 		spin_unlock_irqrestore(&cp->lock, intr_flags);
-		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
+		pr_err(PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 #if CP_VLAN_TAG_USED
@@ -882,7 +880,7 @@
 	}
 	cp->tx_head = entry;
 	if (netif_msg_tx_queued(cp))
-		printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
+		pr_debug("%s: tx queued, slot %d, skblen %d\n",
 		       dev->name, entry, skb->len);
 	if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
 		netif_stop_queue(dev);
@@ -996,7 +994,7 @@
 		schedule_timeout_uninterruptible(10);
 	}
 
-	printk(KERN_ERR "%s: hardware reset timeout\n", cp->dev->name);
+	pr_err("%s: hardware reset timeout\n", cp->dev->name);
 }
 
 static inline void cp_start_hw (struct cp_private *cp)
@@ -1166,7 +1164,7 @@
 	int rc;
 
 	if (netif_msg_ifup(cp))
-		printk(KERN_DEBUG "%s: enabling interface\n", dev->name);
+		pr_debug("%s: enabling interface\n", dev->name);
 
 	rc = cp_alloc_rings(cp);
 	if (rc)
@@ -1201,7 +1199,7 @@
 	napi_disable(&cp->napi);
 
 	if (netif_msg_ifdown(cp))
-		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
+		pr_debug("%s: disabling interface\n", dev->name);
 
 	spin_lock_irqsave(&cp->lock, flags);
 
@@ -1224,7 +1222,7 @@
 	unsigned long flags;
 	int rc;
 
-	printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n",
+	pr_warning("%s: Transmit timeout, status %2x %4x %4x %4x\n",
 	       dev->name, cpr8(Cmd), cpr16(CpCmd),
 	       cpr16(IntrStatus), cpr16(IntrMask));
 
@@ -1873,7 +1871,7 @@
 #ifndef MODULE
 	static int version_printed;
 	if (version_printed++ == 0)
-		printk("%s", version);
+		pr_info("%s", version);
 #endif
 
 	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
@@ -1995,8 +1993,7 @@
 	if (rc)
 		goto err_out_iomap;
 
-	printk (KERN_INFO "%s: RTL-8139C+ at 0x%lx, "
-		"%pM, IRQ %d\n",
+	pr_info("%s: RTL-8139C+ at 0x%lx, %pM, IRQ %d\n",
 		dev->name,
 		dev->base_addr,
 		dev->dev_addr,
@@ -2113,7 +2110,7 @@
 static int __init cp_init (void)
 {
 #ifdef MODULE
-	printk("%s", version);
+	pr_info("%s", version);
 #endif
 	return pci_register_driver(&cp_driver);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/8139too.c linux-libre-2.6.31-gnu/drivers/net/8139too.c
--- linux-libre-2.6.30-gnu/drivers/net/8139too.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/8139too.c	2009-09-09 18:13:59.000000000 -0400
@@ -126,19 +126,12 @@
 #undef RTL8139_NDEBUG
 
 
-#if RTL8139_DEBUG
-/* note: prints function name for you */
-#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-#else
-#  define DPRINTK(fmt, args...)
-#endif
-
 #ifdef RTL8139_NDEBUG
 #  define assert(expr) do {} while (0)
 #else
 #  define assert(expr) \
         if(unlikely(!(expr))) {				        \
-        printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n",	\
+        pr_err("Assertion failed! %s,%s,%s,line=%d\n",	\
 	#expr, __FILE__, __func__, __LINE__);			\
         }
 #endif
@@ -784,8 +777,8 @@
 
 	/* set this immediately, we need to know before
 	 * we talk to the chip directly */
-	DPRINTK("PIO region size == 0x%02X\n", pio_len);
-	DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
+	pr_debug("PIO region size == 0x%02lX\n", pio_len);
+	pr_debug("MMIO region size == 0x%02lX\n", mmio_len);
 
 retry:
 	if (use_io) {
@@ -865,19 +858,17 @@
 		}
 
 	/* if unknown chip, assume array element #0, original RTL-8139 in this case */
-	dev_printk (KERN_DEBUG, &pdev->dev,
-		    "unknown chip version, assuming RTL-8139\n");
-	dev_printk (KERN_DEBUG, &pdev->dev,
-		    "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
+	dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
+	dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
 	tp->chipset = 0;
 
 match:
-	DPRINTK ("chipset id (%d) == index %d, '%s'\n",
+	pr_debug("chipset id (%d) == index %d, '%s'\n",
 		 version, i, rtl_chip_info[i].name);
 
 	if (tp->chipset >= CH_8139B) {
 		u8 new_tmp8 = tmp8 = RTL_R8 (Config1);
-		DPRINTK("PCI PM wakeup\n");
+		pr_debug("PCI PM wakeup\n");
 		if ((rtl_chip_info[tp->chipset].flags & HasLWake) &&
 		    (tmp8 & LWAKE))
 			new_tmp8 &= ~LWAKE;
@@ -896,7 +887,7 @@
 			}
 		}
 	} else {
-		DPRINTK("Old chip wakeup\n");
+		pr_debug("Old chip wakeup\n");
 		tmp8 = RTL_R8 (Config1);
 		tmp8 &= ~(SLEEP | PWRDN);
 		RTL_W8 (Config1, tmp8);
@@ -917,6 +908,7 @@
 	.ndo_open		= rtl8139_open,
 	.ndo_stop		= rtl8139_close,
 	.ndo_get_stats		= rtl8139_get_stats,
+	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address 	= rtl8139_set_mac_address,
 	.ndo_start_xmit		= rtl8139_start_xmit,
@@ -949,7 +941,7 @@
 	{
 		static int printed_version;
 		if (!printed_version++)
-			printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
+			pr_info(RTL8139_DRIVER_NAME "\n");
 	}
 #endif
 
@@ -965,7 +957,7 @@
 	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 &&
 	    pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS &&
 	    pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) {
-		printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n");
+		pr_info("8139too: OQO Model 2 detected. Forcing PIO\n");
 		use_io = 1;
 	}
 
@@ -1018,21 +1010,20 @@
 	tp->mii.reg_num_mask = 0x1f;
 
 	/* dev is fully set up and ready to use now */
-	DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
+	pr_debug("about to register device named %s (%p)...\n", dev->name, dev);
 	i = register_netdev (dev);
 	if (i) goto err_out;
 
 	pci_set_drvdata (pdev, dev);
 
-	printk (KERN_INFO "%s: %s at 0x%lx, "
-		"%pM, IRQ %d\n",
+	pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n",
 		dev->name,
 		board_info[ent->driver_data].name,
 		dev->base_addr,
 		dev->dev_addr,
 		dev->irq);
 
-	printk (KERN_DEBUG "%s:  Identified 8139 chip type '%s'\n",
+	pr_debug("%s:  Identified 8139 chip type '%s'\n",
 		dev->name, rtl_chip_info[tp->chipset].name);
 
 	/* Find the connected MII xcvrs.
@@ -1046,14 +1037,12 @@
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				u16 advertising = mdio_read(dev, phy, 4);
 				tp->phys[phy_idx++] = phy;
-				printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x "
-					   "advertising %4.4x.\n",
+				pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n",
 					   dev->name, phy, mii_status, advertising);
 			}
 		}
 		if (phy_idx == 0) {
-			printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "
-				   "transceiver.\n",
+			pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n",
 				   dev->name);
 			tp->phys[0] = 32;
 		}
@@ -1073,13 +1062,13 @@
 	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)
 		tp->mii.full_duplex = full_duplex[board_idx];
 	if (tp->mii.full_duplex) {
-		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
+		pr_info("%s: Media type forced to Full Duplex.\n", dev->name);
 		/* Changing the MII-advertised media because might prevent
 		   re-connection. */
 		tp->mii.force_media = 1;
 	}
 	if (tp->default_port) {
-		printk(KERN_INFO "  Forcing %dMbps %s-duplex operation.\n",
+		pr_info("  Forcing %dMbps %s-duplex operation.\n",
 			   (option & 0x20 ? 100 : 10),
 			   (option & 0x10 ? "full" : "half"));
 		mdio_write(dev, tp->phys[0], 0,
@@ -1342,7 +1331,7 @@
 	netif_start_queue (dev);
 
 	if (netif_msg_ifup(tp))
-		printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d"
+		pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d"
 			" GP Pins %2.2x %s-duplex.\n", dev->name,
 			(unsigned long long)pci_resource_start (tp->pci_dev, 1),
 			dev->irq, RTL_R8 (MediaStatus),
@@ -1404,7 +1393,7 @@
 		RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic);
 	}
 
-	DPRINTK("init buffer addresses\n");
+	pr_debug("init buffer addresses\n");
 
 	/* Lock Config[01234] and BMCR register writes */
 	RTL_W8 (Cfg9346, Cfg9346_Lock);
@@ -1566,14 +1555,13 @@
 			tp->mii.full_duplex = duplex;
 
 			if (mii_lpa) {
-				printk (KERN_INFO
-					"%s: Setting %s-duplex based on MII #%d link"
+				pr_info("%s: Setting %s-duplex based on MII #%d link"
 					" partner ability of %4.4x.\n",
 					dev->name,
 					tp->mii.full_duplex ? "full" : "half",
 					tp->phys[0], mii_lpa);
 			} else {
-				printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",
+				pr_info("%s: media is unconnected, link down, or incompatible connection\n",
 				       dev->name);
 			}
 #if 0
@@ -1588,11 +1576,11 @@
 
 	rtl8139_tune_twister (dev, tp);
 
-	DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",
+	pr_debug("%s: Media selection tick, Link partner %4.4x.\n",
 		 dev->name, RTL_R16 (NWayLPAR));
-	DPRINTK ("%s:  Other registers are IntMask %4.4x IntStatus %4.4x\n",
+	pr_debug("%s:  Other registers are IntMask %4.4x IntStatus %4.4x\n",
 		 dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus));
-	DPRINTK ("%s:  Chip config %2.2x %2.2x.\n",
+	pr_debug("%s:  Chip config %2.2x %2.2x.\n",
 		 dev->name, RTL_R8 (Config0),
 		 RTL_R8 (Config1));
 }
@@ -1652,14 +1640,14 @@
 	int i;
 	u8 tmp8;
 
-	printk (KERN_DEBUG "%s: Transmit timeout, status %2.2x %4.4x %4.4x "
-		"media %2.2x.\n", dev->name, RTL_R8 (ChipCmd),
+	pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n",
+		dev->name, RTL_R8 (ChipCmd),
 		RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus));
 	/* Emit info to figure out what went wrong. */
-	printk (KERN_DEBUG "%s: Tx queue start entry %ld  dirty entry %ld.\n",
+	pr_debug("%s: Tx queue start entry %ld  dirty entry %ld.\n",
 		dev->name, tp->cur_tx, tp->dirty_tx);
 	for (i = 0; i < NUM_TX_DESC; i++)
-		printk (KERN_DEBUG "%s:  Tx descriptor %d is %8.8lx.%s\n",
+		pr_debug("%s:  Tx descriptor %d is %8.8lx.%s\n",
 			dev->name, i, RTL_R32 (TxStatus0 + (i * 4)),
 			i == tp->dirty_tx % NUM_TX_DESC ?
 				" (queue head)" : "");
@@ -1741,7 +1729,7 @@
 	spin_unlock_irqrestore(&tp->lock, flags);
 
 	if (netif_msg_tx_queued(tp))
-		printk (KERN_DEBUG "%s: Queued Tx packet size %u to slot %d.\n",
+		pr_debug("%s: Queued Tx packet size %u to slot %d.\n",
 			dev->name, len, entry);
 
 	return 0;
@@ -1772,7 +1760,7 @@
 		if (txstatus & (TxOutOfWindow | TxAborted)) {
 			/* There was an major error, log it. */
 			if (netif_msg_tx_err(tp))
-				printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+				pr_debug("%s: Transmit error, Tx status %8.8x.\n",
 					dev->name, txstatus);
 			dev->stats.tx_errors++;
 			if (txstatus & TxAborted) {
@@ -1803,7 +1791,7 @@
 
 #ifndef RTL8139_NDEBUG
 	if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
-		printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n",
+		pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n",
 		        dev->name, dirty_tx, tp->cur_tx);
 		dirty_tx += NUM_TX_DESC;
 	}
@@ -1828,12 +1816,12 @@
 #endif
 
 	if (netif_msg_rx_err (tp))
-		printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n",
+		pr_debug("%s: Ethernet frame had errors, status %8.8x.\n",
 			dev->name, rx_status);
 	dev->stats.rx_errors++;
 	if (!(rx_status & RxStatusOK)) {
 		if (rx_status & RxTooLong) {
-			DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
+			pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n",
 			 	dev->name, rx_status);
 			/* A.C.: The chip hangs here. */
 		}
@@ -1866,7 +1854,7 @@
 			break;
 	}
 	if (tmp_work <= 0)
-		printk (KERN_WARNING PFX "rx stop wait too long\n");
+		pr_warning(PFX "rx stop wait too long\n");
 	/* restart receive */
 	tmp_work = 200;
 	while (--tmp_work > 0) {
@@ -1877,7 +1865,7 @@
 			break;
 	}
 	if (tmp_work <= 0)
-		printk (KERN_WARNING PFX "tx/rx enable wait too long\n");
+		pr_warning(PFX "tx/rx enable wait too long\n");
 
 	/* and reinitialize all rx related registers */
 	RTL_W8_F (Cfg9346, Cfg9346_Unlock);
@@ -1888,7 +1876,7 @@
 	RTL_W32 (RxConfig, tp->rx_config);
 	tp->cur_rx = 0;
 
-	DPRINTK("init buffer addresses\n");
+	pr_debug("init buffer addresses\n");
 
 	/* Lock Config[01234] and BMCR register writes */
 	RTL_W8 (Cfg9346, Cfg9346_Lock);
@@ -1942,7 +1930,7 @@
 	unsigned int cur_rx = tp->cur_rx;
 	unsigned int rx_size = 0;
 
-	DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
+	pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
 		 " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx,
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
@@ -1962,17 +1950,17 @@
 		pkt_size = rx_size - 4;
 
 		if (netif_msg_rx_status(tp))
-			printk(KERN_DEBUG "%s:  rtl8139_rx() status %4.4x, size %4.4x,"
+			pr_debug("%s:  rtl8139_rx() status %4.4x, size %4.4x,"
 				" cur %4.4x.\n", dev->name, rx_status,
 			 rx_size, cur_rx);
 #if RTL8139_DEBUG > 2
 		{
 			int i;
-			DPRINTK ("%s: Frame contents ", dev->name);
+			pr_debug("%s: Frame contents ", dev->name);
 			for (i = 0; i < 70; i++)
-				printk (" %2.2x",
+				pr_cont(" %2.2x",
 					rx_ring[ring_offset + i]);
-			printk (".\n");
+			pr_cont(".\n");
 		}
 #endif
 
@@ -1984,12 +1972,12 @@
 			if (!tp->fifo_copy_timeout)
 				tp->fifo_copy_timeout = jiffies + 2;
 			else if (time_after(jiffies, tp->fifo_copy_timeout)) {
-				DPRINTK ("%s: hung FIFO. Reset.", dev->name);
+				pr_debug("%s: hung FIFO. Reset.", dev->name);
 				rx_size = 0;
 				goto no_early_rx;
 			}
 			if (netif_msg_intr(tp)) {
-				printk(KERN_DEBUG "%s: fifo copy in progress.",
+				pr_debug("%s: fifo copy in progress.",
 				       dev->name);
 			}
 			tp->xstats.early_rx++;
@@ -2033,8 +2021,7 @@
 			netif_receive_skb (skb);
 		} else {
 			if (net_ratelimit())
-				printk (KERN_WARNING
-					"%s: Memory squeeze, dropping packet.\n",
+				pr_warning("%s: Memory squeeze, dropping packet.\n",
 					dev->name);
 			dev->stats.rx_dropped++;
 		}
@@ -2049,12 +2036,10 @@
 	if (unlikely(!received || rx_size == 0xfff0))
 		rtl8139_isr_ack(tp);
 
-#if RTL8139_DEBUG > 1
-	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
+	pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
 		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
-#endif
 
 	tp->cur_rx = cur_rx;
 
@@ -2075,7 +2060,7 @@
 				     void __iomem *ioaddr,
 				     int status, int link_changed)
 {
-	DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",
+	pr_debug("%s: Abnormal interrupt, status %8.8x.\n",
 		 dev->name, status);
 
 	assert (dev != NULL);
@@ -2104,7 +2089,7 @@
 		pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status);
 		pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status);
 
-		printk (KERN_ERR "%s: PCI Bus error %4.4x.\n",
+		pr_err("%s: PCI Bus error %4.4x.\n",
 			dev->name, pci_cmd_status);
 	}
 }
@@ -2198,7 +2183,7 @@
  out:
 	spin_unlock (&tp->lock);
 
-	DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
+	pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n",
 		 dev->name, RTL_R16 (IntrStatus));
 	return IRQ_RETVAL(handled);
 }
@@ -2249,7 +2234,7 @@
 	napi_disable(&tp->napi);
 
 	if (netif_msg_ifdown(tp))
-		printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
+		pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n",
 			dev->name, RTL_R16 (IntrStatus));
 
 	spin_lock_irqsave (&tp->lock, flags);
@@ -2292,11 +2277,11 @@
    other threads or interrupts aren't messing with the 8139.  */
 static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
-	void __iomem *ioaddr = np->mmio_addr;
+	struct rtl8139_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
 
-	spin_lock_irq(&np->lock);
-	if (rtl_chip_info[np->chipset].flags & HasLWake) {
+	spin_lock_irq(&tp->lock);
+	if (rtl_chip_info[tp->chipset].flags & HasLWake) {
 		u8 cfg3 = RTL_R8 (Config3);
 		u8 cfg5 = RTL_R8 (Config5);
 
@@ -2317,7 +2302,7 @@
 		if (cfg5 & Cfg5_BWF)
 			wol->wolopts |= WAKE_BCAST;
 	}
-	spin_unlock_irq(&np->lock);
+	spin_unlock_irq(&tp->lock);
 }
 
 
@@ -2326,19 +2311,19 @@
    aren't messing with the 8139.  */
 static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
-	void __iomem *ioaddr = np->mmio_addr;
+	struct rtl8139_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
 	u32 support;
 	u8 cfg3, cfg5;
 
-	support = ((rtl_chip_info[np->chipset].flags & HasLWake)
+	support = ((rtl_chip_info[tp->chipset].flags & HasLWake)
 		   ? (WAKE_PHY | WAKE_MAGIC
 		      | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)
 		   : 0);
 	if (wol->wolopts & ~support)
 		return -EINVAL;
 
-	spin_lock_irq(&np->lock);
+	spin_lock_irq(&tp->lock);
 	cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic);
 	if (wol->wolopts & WAKE_PHY)
 		cfg3 |= Cfg3_LinkUp;
@@ -2359,87 +2344,87 @@
 	if (wol->wolopts & WAKE_BCAST)
 		cfg5 |= Cfg5_BWF;
 	RTL_W8 (Config5, cfg5);	/* need not unlock via Cfg9346 */
-	spin_unlock_irq(&np->lock);
+	spin_unlock_irq(&tp->lock);
 
 	return 0;
 }
 
 static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
+	struct rtl8139_private *tp = netdev_priv(dev);
 	strcpy(info->driver, DRV_NAME);
 	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, pci_name(np->pci_dev));
-	info->regdump_len = np->regs_len;
+	strcpy(info->bus_info, pci_name(tp->pci_dev));
+	info->regdump_len = tp->regs_len;
 }
 
 static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
-	spin_lock_irq(&np->lock);
-	mii_ethtool_gset(&np->mii, cmd);
-	spin_unlock_irq(&np->lock);
+	struct rtl8139_private *tp = netdev_priv(dev);
+	spin_lock_irq(&tp->lock);
+	mii_ethtool_gset(&tp->mii, cmd);
+	spin_unlock_irq(&tp->lock);
 	return 0;
 }
 
 static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
+	struct rtl8139_private *tp = netdev_priv(dev);
 	int rc;
-	spin_lock_irq(&np->lock);
-	rc = mii_ethtool_sset(&np->mii, cmd);
-	spin_unlock_irq(&np->lock);
+	spin_lock_irq(&tp->lock);
+	rc = mii_ethtool_sset(&tp->mii, cmd);
+	spin_unlock_irq(&tp->lock);
 	return rc;
 }
 
 static int rtl8139_nway_reset(struct net_device *dev)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
-	return mii_nway_restart(&np->mii);
+	struct rtl8139_private *tp = netdev_priv(dev);
+	return mii_nway_restart(&tp->mii);
 }
 
 static u32 rtl8139_get_link(struct net_device *dev)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
-	return mii_link_ok(&np->mii);
+	struct rtl8139_private *tp = netdev_priv(dev);
+	return mii_link_ok(&tp->mii);
 }
 
 static u32 rtl8139_get_msglevel(struct net_device *dev)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
-	return np->msg_enable;
+	struct rtl8139_private *tp = netdev_priv(dev);
+	return tp->msg_enable;
 }
 
 static void rtl8139_set_msglevel(struct net_device *dev, u32 datum)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
-	np->msg_enable = datum;
+	struct rtl8139_private *tp = netdev_priv(dev);
+	tp->msg_enable = datum;
 }
 
 static int rtl8139_get_regs_len(struct net_device *dev)
 {
-	struct rtl8139_private *np;
+	struct rtl8139_private *tp;
 	/* TODO: we are too slack to do reg dumping for pio, for now */
 	if (use_io)
 		return 0;
-	np = netdev_priv(dev);
-	return np->regs_len;
+	tp = netdev_priv(dev);
+	return tp->regs_len;
 }
 
 static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
 {
-	struct rtl8139_private *np;
+	struct rtl8139_private *tp;
 
 	/* TODO: we are too slack to do reg dumping for pio, for now */
 	if (use_io)
 		return;
-	np = netdev_priv(dev);
+	tp = netdev_priv(dev);
 
 	regs->version = RTL_REGS_VER;
 
-	spin_lock_irq(&np->lock);
-	memcpy_fromio(regbuf, np->mmio_addr, regs->len);
-	spin_unlock_irq(&np->lock);
+	spin_lock_irq(&tp->lock);
+	memcpy_fromio(regbuf, tp->mmio_addr, regs->len);
+	spin_unlock_irq(&tp->lock);
 }
 
 static int rtl8139_get_sset_count(struct net_device *dev, int sset)
@@ -2454,12 +2439,12 @@
 
 static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
+	struct rtl8139_private *tp = netdev_priv(dev);
 
-	data[0] = np->xstats.early_rx;
-	data[1] = np->xstats.tx_buf_mapped;
-	data[2] = np->xstats.tx_timeouts;
-	data[3] = np->xstats.rx_lost_in_ring;
+	data[0] = tp->xstats.early_rx;
+	data[1] = tp->xstats.tx_buf_mapped;
+	data[2] = tp->xstats.tx_timeouts;
+	data[3] = tp->xstats.rx_lost_in_ring;
 }
 
 static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -2486,15 +2471,15 @@
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
+	struct rtl8139_private *tp = netdev_priv(dev);
 	int rc;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	spin_lock_irq(&np->lock);
-	rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL);
-	spin_unlock_irq(&np->lock);
+	spin_lock_irq(&tp->lock);
+	rc = generic_mii_ioctl(&tp->mii, if_mii(rq), cmd, NULL);
+	spin_unlock_irq(&tp->lock);
 
 	return rc;
 }
@@ -2527,7 +2512,7 @@
 	int i, rx_mode;
 	u32 tmp;
 
-	DPRINTK ("%s:   rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n",
+	pr_debug("%s:   rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n",
 			dev->name, dev->flags, RTL_R32 (RxConfig));
 
 	/* Note: do not reorder, GCC is clever about common statements. */
@@ -2643,7 +2628,7 @@
 	 * even if no 8139 board is found.
 	 */
 #ifdef MODULE
-	printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
+	pr_info(RTL8139_DRIVER_NAME "\n");
 #endif
 
 	return pci_register_driver(&rtl8139_pci_driver);
diff -druN linux-libre-2.6.30-gnu/drivers/net/82596.c linux-libre-2.6.31-gnu/drivers/net/82596.c
--- linux-libre-2.6.30-gnu/drivers/net/82596.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/82596.c	2009-09-09 18:13:59.000000000 -0400
@@ -122,13 +122,13 @@
 #define ISCP_BUSY	0x00010000
 #define MACH_IS_APRICOT	0
 #else
-#define WSWAPrfd(x)     ((struct i596_rfd *)(x))
-#define WSWAPrbd(x)     ((struct i596_rbd *)(x))
-#define WSWAPiscp(x)    ((struct i596_iscp *)(x))
-#define WSWAPscb(x)     ((struct i596_scb *)(x))
-#define WSWAPcmd(x)     ((struct i596_cmd *)(x))
-#define WSWAPtbd(x)     ((struct i596_tbd *)(x))
-#define WSWAPchar(x)    ((char *)(x))
+#define WSWAPrfd(x)     ((struct i596_rfd *)((long)x))
+#define WSWAPrbd(x)     ((struct i596_rbd *)((long)x))
+#define WSWAPiscp(x)    ((struct i596_iscp *)((long)x))
+#define WSWAPscb(x)     ((struct i596_scb *)((long)x))
+#define WSWAPcmd(x)     ((struct i596_cmd *)((long)x))
+#define WSWAPtbd(x)     ((struct i596_tbd *)((long)x))
+#define WSWAPchar(x)    ((char *)((long)x))
 #define ISCP_BUSY	0x0001
 #define MACH_IS_APRICOT	1
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/8390.c linux-libre-2.6.31-gnu/drivers/net/8390.c
--- linux-libre-2.6.30-gnu/drivers/net/8390.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/8390.c	2009-09-09 18:13:59.000000000 -0400
@@ -74,14 +74,8 @@
 struct net_device *__alloc_ei_netdev(int size)
 {
 	struct net_device *dev = ____alloc_ei_netdev(size);
-#ifdef CONFIG_COMPAT_NET_DEV_OPS
-	if (dev) {
-		dev->hard_start_xmit = ei_start_xmit;
-		dev->get_stats	= ei_get_stats;
-		dev->set_multicast_list = ei_set_multicast_list;
-		dev->tx_timeout = ei_tx_timeout;
-	}
-#endif
+	if (dev)
+		dev->netdev_ops = &ei_netdev_ops;
 	return dev;
 }
 EXPORT_SYMBOL(__alloc_ei_netdev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/8390p.c linux-libre-2.6.31-gnu/drivers/net/8390p.c
--- linux-libre-2.6.30-gnu/drivers/net/8390p.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/8390p.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,14 +79,8 @@
 struct net_device *__alloc_eip_netdev(int size)
 {
 	struct net_device *dev = ____alloc_ei_netdev(size);
-#ifdef CONFIG_COMPAT_NET_DEV_OPS
-	if (dev) {
-		dev->hard_start_xmit = eip_start_xmit;
-		dev->get_stats	= eip_get_stats;
-		dev->set_multicast_list = eip_set_multicast_list;
-		dev->tx_timeout = eip_tx_timeout;
-	}
-#endif
+	if (dev)
+		dev->netdev_ops = &eip_netdev_ops;
 	return dev;
 }
 EXPORT_SYMBOL(__alloc_eip_netdev);
@@ -97,16 +91,15 @@
 }
 EXPORT_SYMBOL(NS8390p_init);
 
-#if defined(MODULE)
-
-int init_module(void)
+static int __init NS8390p_init_module(void)
 {
 	return 0;
 }
 
-void cleanup_module(void)
+static void __exit NS8390p_cleanup_module(void)
 {
 }
 
-#endif /* MODULE */
+module_init(NS8390p_init_module);
+module_exit(NS8390p_cleanup_module);
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/net/a2065.c linux-libre-2.6.31-gnu/drivers/net/a2065.c
--- linux-libre-2.6.30-gnu/drivers/net/a2065.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/a2065.c	2009-09-09 18:13:59.000000000 -0400
@@ -564,21 +564,13 @@
 
 	if (!TX_BUFFS_AVAIL){
 		local_irq_restore(flags);
-		return -1;
+		return NETDEV_TX_LOCKED;
 	}
 
 #ifdef DEBUG_DRIVER
 	/* dump the packet */
-	{
-		int i;
-
-		for (i = 0; i < 64; i++) {
-			if ((i % 16) == 0)
-				printk("\n" KERN_DEBUG);
-			printk ("%2.2x ", skb->data [i]);
-		}
-		printk("\n");
-	}
+	print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
+		       16, 1, skb->data, 64, true);
 #endif
 	entry = lp->tx_new & lp->tx_ring_mod_mask;
 	ib->btx_ring [entry].length = (-skblen) | 0xf000;
diff -druN linux-libre-2.6.30-gnu/drivers/net/acenic.c linux-libre-2.6.31-gnu/drivers/net/acenic.c
--- linux-libre-2.6.30-gnu/drivers/net/acenic.c	2012-03-22 19:14:15.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/acenic.c	2012-03-22 20:10:26.000000000 -0400
@@ -2573,7 +2573,6 @@
 			netif_wake_queue(dev);
 	}
 
-	dev->trans_start = jiffies;
 	return NETDEV_TX_OK;
 
 overflow:
diff -druN linux-libre-2.6.30-gnu/drivers/net/appletalk/ipddp.c linux-libre-2.6.31-gnu/drivers/net/appletalk/ipddp.c
--- linux-libre-2.6.30-gnu/drivers/net/appletalk/ipddp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/appletalk/ipddp.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,6 +39,7 @@
 static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n";
 
 static struct ipddp_route *ipddp_route_list;
+static DEFINE_SPINLOCK(ipddp_route_lock);
 
 #ifdef CONFIG_IPDDP_ENCAP
 static int ipddp_mode = IPDDP_ENCAP;
@@ -50,7 +51,7 @@
 static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev);
 static int ipddp_create(struct ipddp_route *new_rt);
 static int ipddp_delete(struct ipddp_route *rt);
-static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt);
+static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt);
 static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 static const struct net_device_ops ipddp_netdev_ops = {
@@ -71,6 +72,7 @@
 	if (!dev)
 		return ERR_PTR(-ENOMEM);
 
+	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 	strcpy(dev->name, "ipddp%d");
 
 	if (version_printed++ == 0)
@@ -113,11 +115,13 @@
  */
 static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	__be32 paddr = ((struct rtable*)skb->dst)->rt_gateway;
+	__be32 paddr = skb_rtable(skb)->rt_gateway;
         struct ddpehdr *ddp;
         struct ipddp_route *rt;
         struct atalk_addr *our_addr;
 
+	spin_lock(&ipddp_route_lock);
+
 	/*
          * Find appropriate route to use, based only on IP number.
          */
@@ -126,8 +130,10 @@
                 if(rt->ip == paddr)
                         break;
         }
-        if(rt == NULL)
+        if(rt == NULL) {
+		spin_unlock(&ipddp_route_lock);
                 return 0;
+	}
 
         our_addr = atalk_find_dev_addr(rt->dev);
 
@@ -173,6 +179,8 @@
         if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
                 dev_kfree_skb(skb);
 
+	spin_unlock(&ipddp_route_lock);
+
         return 0;
 }
 
@@ -195,7 +203,9 @@
                 return -ENETUNREACH;
         }
 
-	if (ipddp_find_route(rt)) {
+	spin_lock_bh(&ipddp_route_lock);
+	if (__ipddp_find_route(rt)) {
+		spin_unlock_bh(&ipddp_route_lock);
 		kfree(rt);
 		return -EEXIST;
 	}
@@ -203,6 +213,8 @@
         rt->next = ipddp_route_list;
         ipddp_route_list = rt;
 
+	spin_unlock_bh(&ipddp_route_lock);
+
         return 0;
 }
 
@@ -215,6 +227,7 @@
         struct ipddp_route **r = &ipddp_route_list;
         struct ipddp_route *tmp;
 
+	spin_lock_bh(&ipddp_route_lock);
         while((tmp = *r) != NULL)
         {
                 if(tmp->ip == rt->ip
@@ -222,19 +235,21 @@
                         && tmp->at.s_node == rt->at.s_node)
                 {
                         *r = tmp->next;
+			spin_unlock_bh(&ipddp_route_lock);
                         kfree(tmp);
                         return 0;
                 }
                 r = &tmp->next;
         }
 
+	spin_unlock_bh(&ipddp_route_lock);
         return (-ENOENT);
 }
 
 /*
  * Find a routing entry, we only return a FULL match
  */
-static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt)
+static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt)
 {
         struct ipddp_route *f;
 
@@ -252,7 +267,7 @@
 static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
         struct ipddp_route __user *rt = ifr->ifr_data;
-        struct ipddp_route rcp;
+        struct ipddp_route rcp, rcp2, *rp;
 
         if(!capable(CAP_NET_ADMIN))
                 return -EPERM;
@@ -266,9 +281,19 @@
                         return (ipddp_create(&rcp));
 
                 case SIOCFINDIPDDPRT:
-                        if(copy_to_user(rt, ipddp_find_route(&rcp), sizeof(struct ipddp_route)))
-                                return -EFAULT;
-                        return 0;
+			spin_lock_bh(&ipddp_route_lock);
+			rp = __ipddp_find_route(&rcp);
+			if (rp)
+				memcpy(&rcp2, rp, sizeof(rcp2));
+			spin_unlock_bh(&ipddp_route_lock);
+
+			if (rp) {
+				if (copy_to_user(rt, &rcp2,
+						 sizeof(struct ipddp_route)))
+					return -EFAULT;
+				return 0;
+			} else
+				return -ENOENT;
 
                 case SIOCDELIPDDPRT:
                         return (ipddp_delete(&rcp));
diff -druN linux-libre-2.6.30-gnu/drivers/net/appletalk/ltpc.c linux-libre-2.6.31-gnu/drivers/net/appletalk/ltpc.c
--- linux-libre-2.6.30-gnu/drivers/net/appletalk/ltpc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/appletalk/ltpc.c	2009-09-09 18:13:59.000000000 -0400
@@ -1220,7 +1220,7 @@
 		if (ints[0] > 2) {
 			dma = ints[3];
 		}
-		/* ignore any other paramters */
+		/* ignore any other parameters */
 	}
 	return 1;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/arcnet/arcnet.c linux-libre-2.6.31-gnu/drivers/net/arcnet/arcnet.c
--- linux-libre-2.6.30-gnu/drivers/net/arcnet/arcnet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/arcnet/arcnet.c	2009-09-09 18:13:59.000000000 -0400
@@ -158,15 +158,12 @@
 void arcnet_dump_skb(struct net_device *dev,
 		     struct sk_buff *skb, char *desc)
 {
-	int i;
+	char hdr[32];
 
-	printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc);
-	for (i = 0; i < skb->len; i++) {
-		if (i % 16 == 0)
-			printk("\n" KERN_DEBUG "[%04X] ", i);
-		printk("%02X ", ((u_char *) skb->data)[i]);
-	}
-	printk("\n");
+	/* dump the packet */
+	snprintf(hdr, sizeof(hdr), "%6s:%s skb->data:", dev->name, desc);
+	print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET,
+		       16, 1, skb->data, skb->len, true);
 }
 
 EXPORT_SYMBOL(arcnet_dump_skb);
@@ -184,6 +181,7 @@
 	int i, length;
 	unsigned long flags = 0;
 	static uint8_t buf[512];
+	char hdr[32];
 
 	/* hw.copy_from_card expects IRQ context so take the IRQ lock
 	   to keep it single threaded */
@@ -197,14 +195,10 @@
 	/* if the offset[0] byte is nonzero, this is a 256-byte packet */
 	length = (buf[2] ? 256 : 512);
 
-	printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc);
-	for (i = 0; i < length; i++) {
-		if (i % 16 == 0)
-			printk("\n" KERN_DEBUG "[%04X] ", i);
-		printk("%02X ", buf[i]);
-	}
-	printk("\n");
-
+	/* dump the packet */
+	snprintf(hdr, sizeof(hdr), "%6s:%s packet dump:", dev->name, desc);
+	print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET,
+		       16, 1, buf, length, true);
 }
 
 #else
diff -druN linux-libre-2.6.30-gnu/drivers/net/arm/at91_ether.c linux-libre-2.6.31-gnu/drivers/net/arm/at91_ether.c
--- linux-libre-2.6.30-gnu/drivers/net/arm/at91_ether.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/arm/at91_ether.c	2009-09-09 18:13:59.000000000 -0400
@@ -829,7 +829,7 @@
 		dev->trans_start = jiffies;
 	} else {
 		printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
-		return 1;	/* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
+		return NETDEV_TX_BUSY;	/* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
 				on this skb, he also reports -ENETDOWN and printk's, so either
 				we free and return(0) or don't free and return 1 */
 	}
@@ -1228,7 +1228,6 @@
 #endif
 
 static struct platform_driver at91ether_driver = {
-	.probe		= at91ether_probe,
 	.remove		= __devexit_p(at91ether_remove),
 	.suspend	= at91ether_suspend,
 	.resume		= at91ether_resume,
@@ -1240,7 +1239,7 @@
 
 static int __init at91ether_init(void)
 {
-	return platform_driver_register(&at91ether_driver);
+	return platform_driver_probe(&at91ether_driver, at91ether_probe);
 }
 
 static void __exit at91ether_exit(void)
diff -druN linux-libre-2.6.30-gnu/drivers/net/arm/ep93xx_eth.c linux-libre-2.6.31-gnu/drivers/net/arm/ep93xx_eth.c
--- linux-libre-2.6.30-gnu/drivers/net/arm/ep93xx_eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/arm/ep93xx_eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -253,7 +253,7 @@
 		skb = dev_alloc_skb(length + 2);
 		if (likely(skb != NULL)) {
 			skb_reserve(skb, 2);
-			dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr,
+			dma_sync_single_for_cpu(NULL, ep->descs->rdesc[entry].buf_addr,
 						length, DMA_FROM_DEVICE);
 			skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
 			skb_put(skb, length);
@@ -331,7 +331,7 @@
 	ep->descs->tdesc[entry].tdesc1 =
 		TDESC1_EOF | (entry << 16) | (skb->len & 0xfff);
 	skb_copy_and_csum_dev(skb, ep->tx_buf[entry]);
-	dma_sync_single(NULL, ep->descs->tdesc[entry].buf_addr,
+	dma_sync_single_for_cpu(NULL, ep->descs->tdesc[entry].buf_addr,
 				skb->len, DMA_TO_DEVICE);
 	dev_kfree_skb(skb);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/arm/ether3.c linux-libre-2.6.31-gnu/drivers/net/arm/ether3.c
--- linux-libre-2.6.30-gnu/drivers/net/arm/ether3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/arm/ether3.c	2009-09-09 18:13:59.000000000 -0400
@@ -526,7 +526,7 @@
 
 	if (priv(dev)->tx_tail == next_ptr) {
 		local_irq_restore(flags);
-		return 1;	/* unable to queue */
+		return NETDEV_TX_BUSY;	/* unable to queue */
 	}
 
 	dev->trans_start = jiffies;
diff -druN linux-libre-2.6.30-gnu/drivers/net/arm/ixp4xx_eth.c linux-libre-2.6.31-gnu/drivers/net/arm/ixp4xx_eth.c
--- linux-libre-2.6.30-gnu/drivers/net/arm/ixp4xx_eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/arm/ixp4xx_eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -456,7 +456,8 @@
 	debug_desc(phys, desc);
 	BUG_ON(phys & 0x1F);
 	qmgr_put_entry(queue, phys);
-	BUG_ON(qmgr_stat_overflow(queue));
+	/* Don't check for queue overflow here, we've allocated sufficient
+	   length and queues >= 32 don't support this check anyway. */
 }
 
 
@@ -512,8 +513,8 @@
 #endif
 			napi_complete(napi);
 			qmgr_enable_irq(rxq);
-			if (!qmgr_stat_empty(rxq) &&
-			    napi_reschedule(napi)) {
+			if (!qmgr_stat_below_low_watermark(rxq) &&
+			    napi_reschedule(napi)) { /* not empty again */
 #if DEBUG_RX
 				printk(KERN_DEBUG "%s: eth_poll"
 				       " napi_reschedule successed\n",
@@ -561,8 +562,8 @@
 		dma_unmap_single(&dev->dev, desc->data - NET_IP_ALIGN,
 				 RX_BUFF_SIZE, DMA_FROM_DEVICE);
 #else
-		dma_sync_single(&dev->dev, desc->data - NET_IP_ALIGN,
-				RX_BUFF_SIZE, DMA_FROM_DEVICE);
+		dma_sync_single_for_cpu(&dev->dev, desc->data - NET_IP_ALIGN,
+					RX_BUFF_SIZE, DMA_FROM_DEVICE);
 		memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n],
 			      ALIGN(NET_IP_ALIGN + desc->pkt_len, 4) / 4);
 #endif
@@ -630,9 +631,9 @@
 			port->tx_buff_tab[n_desc] = NULL;
 		}
 
-		start = qmgr_stat_empty(port->plat->txreadyq);
+		start = qmgr_stat_below_low_watermark(port->plat->txreadyq);
 		queue_put_desc(port->plat->txreadyq, phys, desc);
-		if (start) {
+		if (start) { /* TX-ready queue was empty */
 #if DEBUG_TX
 			printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n",
 			       port->netdev->name);
@@ -708,13 +709,14 @@
 	queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc);
 	dev->trans_start = jiffies;
 
-	if (qmgr_stat_empty(txreadyq)) {
+	if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */
 #if DEBUG_TX
 		printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name);
 #endif
 		netif_stop_queue(dev);
 		/* we could miss TX ready interrupt */
-		if (!qmgr_stat_empty(txreadyq)) {
+		/* really empty in fact */
+		if (!qmgr_stat_below_low_watermark(txreadyq)) {
 #if DEBUG_TX
 			printk(KERN_DEBUG "%s: eth_xmit ready again\n",
 			       dev->name);
@@ -814,29 +816,29 @@
 	int err;
 
 	err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0,
-			    "%s:RX-free", port->netdev->name);
+				 "%s:RX-free", port->netdev->name);
 	if (err)
 		return err;
 
 	err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0,
-			    "%s:RX", port->netdev->name);
+				 "%s:RX", port->netdev->name);
 	if (err)
 		goto rel_rxfree;
 
 	err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0,
-			    "%s:TX", port->netdev->name);
+				 "%s:TX", port->netdev->name);
 	if (err)
 		goto rel_rx;
 
 	err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0,
-			    "%s:TX-ready", port->netdev->name);
+				 "%s:TX-ready", port->netdev->name);
 	if (err)
 		goto rel_tx;
 
 	/* TX-done queue handles skbs sent out by the NPEs */
 	if (!ports_open) {
 		err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0,
-				    "%s:TX-done", DRV_NAME);
+					 "%s:TX-done", DRV_NAME);
 		if (err)
 			goto rel_txready;
 	}
@@ -1140,7 +1142,9 @@
 	.ndo_start_xmit = eth_xmit,
 	.ndo_set_multicast_list = eth_set_mcast_list,
 	.ndo_do_ioctl = eth_ioctl,
-
+	.ndo_change_mtu = eth_change_mtu,
+	.ndo_set_mac_address = eth_mac_addr,
+	.ndo_validate_addr = eth_validate_addr,
 };
 
 static int __devinit eth_init_one(struct platform_device *pdev)
@@ -1149,7 +1153,7 @@
 	struct net_device *dev;
 	struct eth_plat_info *plat = pdev->dev.platform_data;
 	u32 regs_phys;
-	char phy_id[BUS_ID_SIZE];
+	char phy_id[MII_BUS_ID_SIZE + 3];
 	int err;
 
 	if (!(dev = alloc_etherdev(sizeof(struct port))))
@@ -1207,7 +1211,7 @@
 	__raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
 	udelay(50);
 
-	snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy);
+	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy);
 	port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
 				   PHY_INTERFACE_MODE_MII);
 	if ((err = IS_ERR(port->phydev)))
diff -druN linux-libre-2.6.30-gnu/drivers/net/arm/Kconfig linux-libre-2.6.31-gnu/drivers/net/arm/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/arm/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/arm/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -63,3 +63,11 @@
 	help
 	  Say Y here if you want to use built-in Ethernet ports
 	  on IXP4xx processor.
+
+config W90P910_ETH
+	tristate "Nuvoton w90p910 Ethernet support"
+	depends on ARM && ARCH_W90X900
+	select PHYLIB
+	help
+	  Say Y here if you want to use built-in Ethernet ports
+	  on w90p910 processor.
diff -druN linux-libre-2.6.30-gnu/drivers/net/arm/Makefile linux-libre-2.6.31-gnu/drivers/net/arm/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/arm/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/arm/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -11,3 +11,4 @@
 obj-$(CONFIG_ARM_KS8695_ETHER)	+= ks8695net.o
 obj-$(CONFIG_EP93XX_ETH)	+= ep93xx_eth.o
 obj-$(CONFIG_IXP4XX_ETH)	+= ixp4xx_eth.o
+obj-$(CONFIG_W90P910_ETH)	+= w90p910_ether.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/arm/w90p910_ether.c linux-libre-2.6.31-gnu/drivers/net/arm/w90p910_ether.c
--- linux-libre-2.6.30-gnu/drivers/net/arm/w90p910_ether.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/arm/w90p910_ether.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 2008-2009 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#define DRV_MODULE_NAME		"w90p910-emc"
+#define DRV_MODULE_VERSION	"0.1"
+
+/* Ethernet MAC Registers */
+#define REG_CAMCMR		0x00
+#define REG_CAMEN		0x04
+#define REG_CAMM_BASE		0x08
+#define REG_CAML_BASE		0x0c
+#define REG_TXDLSA		0x88
+#define REG_RXDLSA		0x8C
+#define REG_MCMDR		0x90
+#define REG_MIID		0x94
+#define REG_MIIDA		0x98
+#define REG_FFTCR		0x9C
+#define REG_TSDR		0xa0
+#define REG_RSDR		0xa4
+#define REG_DMARFC		0xa8
+#define REG_MIEN		0xac
+#define REG_MISTA		0xb0
+#define REG_CTXDSA		0xcc
+#define REG_CTXBSA		0xd0
+#define REG_CRXDSA		0xd4
+#define REG_CRXBSA		0xd8
+
+/* mac controller bit */
+#define MCMDR_RXON		0x01
+#define MCMDR_ACP		(0x01 << 3)
+#define MCMDR_SPCRC		(0x01 << 5)
+#define MCMDR_TXON		(0x01 << 8)
+#define MCMDR_FDUP		(0x01 << 18)
+#define MCMDR_ENMDC		(0x01 << 19)
+#define MCMDR_OPMOD		(0x01 << 20)
+#define SWR			(0x01 << 24)
+
+/* cam command regiser */
+#define CAMCMR_AUP		0x01
+#define CAMCMR_AMP		(0x01 << 1)
+#define CAMCMR_ABP		(0x01 << 2)
+#define CAMCMR_CCAM		(0x01 << 3)
+#define CAMCMR_ECMP		(0x01 << 4)
+#define CAM0EN			0x01
+
+/* mac mii controller bit */
+#define MDCCR			(0x0a << 20)
+#define PHYAD			(0x01 << 8)
+#define PHYWR			(0x01 << 16)
+#define PHYBUSY			(0x01 << 17)
+#define PHYPRESP		(0x01 << 18)
+#define CAM_ENTRY_SIZE		0x08
+
+/* rx and tx status */
+#define TXDS_TXCP		(0x01 << 19)
+#define RXDS_CRCE		(0x01 << 17)
+#define RXDS_PTLE		(0x01 << 19)
+#define RXDS_RXGD		(0x01 << 20)
+#define RXDS_ALIE		(0x01 << 21)
+#define RXDS_RP			(0x01 << 22)
+
+/* mac interrupt status*/
+#define MISTA_EXDEF		(0x01 << 19)
+#define MISTA_TXBERR		(0x01 << 24)
+#define MISTA_TDU		(0x01 << 23)
+#define MISTA_RDU		(0x01 << 10)
+#define MISTA_RXBERR		(0x01 << 11)
+
+#define ENSTART			0x01
+#define ENRXINTR		0x01
+#define ENRXGD			(0x01 << 4)
+#define ENRXBERR		(0x01 << 11)
+#define ENTXINTR		(0x01 << 16)
+#define ENTXCP			(0x01 << 18)
+#define ENTXABT			(0x01 << 21)
+#define ENTXBERR		(0x01 << 24)
+#define ENMDC			(0x01 << 19)
+#define PHYBUSY			(0x01 << 17)
+#define MDCCR_VAL		0xa00000
+
+/* rx and tx owner bit */
+#define RX_OWEN_DMA		(0x01 << 31)
+#define RX_OWEN_CPU		(~(0x03 << 30))
+#define TX_OWEN_DMA		(0x01 << 31)
+#define TX_OWEN_CPU		(~(0x01 << 31))
+
+/* tx frame desc controller bit */
+#define MACTXINTEN		0x04
+#define CRCMODE			0x02
+#define PADDINGMODE		0x01
+
+/* fftcr controller bit */
+#define TXTHD 			(0x03 << 8)
+#define BLENGTH			(0x01 << 20)
+
+/* global setting for driver */
+#define RX_DESC_SIZE		50
+#define TX_DESC_SIZE		10
+#define MAX_RBUFF_SZ		0x600
+#define MAX_TBUFF_SZ		0x600
+#define TX_TIMEOUT		50
+#define DELAY			1000
+#define CAM0			0x0
+
+static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg);
+
+struct w90p910_rxbd {
+	unsigned int sl;
+	unsigned int buffer;
+	unsigned int reserved;
+	unsigned int next;
+};
+
+struct w90p910_txbd {
+	unsigned int mode;
+	unsigned int buffer;
+	unsigned int sl;
+	unsigned int next;
+};
+
+struct recv_pdesc {
+	struct w90p910_rxbd desclist[RX_DESC_SIZE];
+	char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ];
+};
+
+struct tran_pdesc {
+	struct w90p910_txbd desclist[TX_DESC_SIZE];
+	char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ];
+};
+
+struct  w90p910_ether {
+	struct recv_pdesc *rdesc;
+	struct recv_pdesc *rdesc_phys;
+	struct tran_pdesc *tdesc;
+	struct tran_pdesc *tdesc_phys;
+	struct net_device_stats stats;
+	struct platform_device *pdev;
+	struct sk_buff *skb;
+	struct clk *clk;
+	struct clk *rmiiclk;
+	struct mii_if_info mii;
+	struct timer_list check_timer;
+	void __iomem *reg;
+	unsigned int rxirq;
+	unsigned int txirq;
+	unsigned int cur_tx;
+	unsigned int cur_rx;
+	unsigned int finish_tx;
+	unsigned int rx_packets;
+	unsigned int rx_bytes;
+	unsigned int start_tx_ptr;
+	unsigned int start_rx_ptr;
+	unsigned int linkflag;
+	spinlock_t lock;
+};
+
+static void update_linkspeed_register(struct net_device *dev,
+				unsigned int speed, unsigned int duplex)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = __raw_readl(ether->reg + REG_MCMDR);
+
+	if (speed == SPEED_100) {
+		/* 100 full/half duplex */
+		if (duplex == DUPLEX_FULL) {
+			val |= (MCMDR_OPMOD | MCMDR_FDUP);
+		} else {
+			val |= MCMDR_OPMOD;
+			val &= ~MCMDR_FDUP;
+		}
+	} else {
+		/* 10 full/half duplex */
+		if (duplex == DUPLEX_FULL) {
+			val |= MCMDR_FDUP;
+			val &= ~MCMDR_OPMOD;
+		} else {
+			val &= ~(MCMDR_FDUP | MCMDR_OPMOD);
+		}
+	}
+
+	__raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void update_linkspeed(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	struct platform_device *pdev;
+	unsigned int bmsr, bmcr, lpa, speed, duplex;
+
+	pdev = ether->pdev;
+
+	if (!mii_link_ok(&ether->mii)) {
+		ether->linkflag = 0x0;
+		netif_carrier_off(dev);
+		dev_warn(&pdev->dev, "%s: Link down.\n", dev->name);
+		return;
+	}
+
+	if (ether->linkflag == 1)
+		return;
+
+	bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR);
+	bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR);
+
+	if (bmcr & BMCR_ANENABLE) {
+		if (!(bmsr & BMSR_ANEGCOMPLETE))
+			return;
+
+		lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA);
+
+		if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF))
+			speed = SPEED_100;
+		else
+			speed = SPEED_10;
+
+		if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL))
+			duplex = DUPLEX_FULL;
+		else
+			duplex = DUPLEX_HALF;
+
+	} else {
+		speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+		duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+	}
+
+	update_linkspeed_register(dev, speed, duplex);
+
+	dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed,
+			(duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
+	ether->linkflag = 0x01;
+
+	netif_carrier_on(dev);
+}
+
+static void w90p910_check_link(unsigned long dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	update_linkspeed(dev);
+	mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
+}
+
+static void w90p910_write_cam(struct net_device *dev,
+				unsigned int x, unsigned char *pval)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int msw, lsw;
+
+	msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
+
+	lsw = (pval[4] << 24) | (pval[5] << 16);
+
+	__raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE);
+	__raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
+}
+
+static void w90p910_init_desc(struct net_device *dev)
+{
+	struct w90p910_ether *ether;
+	struct w90p910_txbd  *tdesc, *tdesc_phys;
+	struct w90p910_rxbd  *rdesc, *rdesc_phys;
+	unsigned int i, j;
+
+	ether = netdev_priv(dev);
+
+	ether->tdesc = (struct tran_pdesc *)
+			dma_alloc_coherent(NULL, sizeof(struct tran_pdesc),
+				(dma_addr_t *) &ether->tdesc_phys, GFP_KERNEL);
+
+	ether->rdesc = (struct recv_pdesc *)
+			dma_alloc_coherent(NULL, sizeof(struct recv_pdesc),
+				(dma_addr_t *) &ether->rdesc_phys, GFP_KERNEL);
+
+	for (i = 0; i < TX_DESC_SIZE; i++) {
+		tdesc = &(ether->tdesc->desclist[i]);
+
+		j = ((i + 1) / TX_DESC_SIZE);
+
+		if (j != 0) {
+			tdesc_phys = &(ether->tdesc_phys->desclist[0]);
+			ether->start_tx_ptr = (unsigned int)tdesc_phys;
+			tdesc->next = (unsigned int)ether->start_tx_ptr;
+		} else {
+			tdesc_phys = &(ether->tdesc_phys->desclist[i+1]);
+			tdesc->next = (unsigned int)tdesc_phys;
+		}
+
+		tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i];
+		tdesc->sl = 0;
+		tdesc->mode = 0;
+	}
+
+	for (i = 0; i < RX_DESC_SIZE; i++) {
+		rdesc = &(ether->rdesc->desclist[i]);
+
+		j = ((i + 1) / RX_DESC_SIZE);
+
+		if (j != 0) {
+			rdesc_phys = &(ether->rdesc_phys->desclist[0]);
+			ether->start_rx_ptr = (unsigned int)rdesc_phys;
+			rdesc->next = (unsigned int)ether->start_rx_ptr;
+		} else {
+			rdesc_phys = &(ether->rdesc_phys->desclist[i+1]);
+			rdesc->next = (unsigned int)rdesc_phys;
+		}
+
+		rdesc->sl = RX_OWEN_DMA;
+		rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i];
+	  }
+}
+
+static void w90p910_set_fifo_threshold(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = TXTHD | BLENGTH;
+	__raw_writel(val, ether->reg + REG_FFTCR);
+}
+
+static void w90p910_return_default_idle(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = __raw_readl(ether->reg + REG_MCMDR);
+	val |= SWR;
+	__raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_trigger_rx(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	__raw_writel(ENSTART, ether->reg + REG_RSDR);
+}
+
+static void w90p910_trigger_tx(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	__raw_writel(ENSTART, ether->reg + REG_TSDR);
+}
+
+static void w90p910_enable_mac_interrupt(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP;
+	val |= ENTXBERR | ENRXBERR | ENTXABT;
+
+	__raw_writel(val, ether->reg + REG_MIEN);
+}
+
+static void w90p910_get_and_clear_int(struct net_device *dev,
+							unsigned int *val)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	*val = __raw_readl(ether->reg + REG_MISTA);
+	__raw_writel(*val, ether->reg + REG_MISTA);
+}
+
+static void w90p910_set_global_maccmd(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = __raw_readl(ether->reg + REG_MCMDR);
+	val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC;
+	__raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_enable_cam(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	w90p910_write_cam(dev, CAM0, dev->dev_addr);
+
+	val = __raw_readl(ether->reg + REG_CAMEN);
+	val |= CAM0EN;
+	__raw_writel(val, ether->reg + REG_CAMEN);
+}
+
+static void w90p910_enable_cam_command(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP;
+	__raw_writel(val, ether->reg + REG_CAMCMR);
+}
+
+static void w90p910_enable_tx(struct net_device *dev, unsigned int enable)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = __raw_readl(ether->reg + REG_MCMDR);
+
+	if (enable)
+		val |= MCMDR_TXON;
+	else
+		val &= ~MCMDR_TXON;
+
+	__raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_enable_rx(struct net_device *dev, unsigned int enable)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	unsigned int val;
+
+	val = __raw_readl(ether->reg + REG_MCMDR);
+
+	if (enable)
+		val |= MCMDR_RXON;
+	else
+		val &= ~MCMDR_RXON;
+
+	__raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_set_curdest(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	__raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA);
+	__raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA);
+}
+
+static void w90p910_reset_mac(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	spin_lock(&ether->lock);
+
+	w90p910_enable_tx(dev, 0);
+	w90p910_enable_rx(dev, 0);
+	w90p910_set_fifo_threshold(dev);
+	w90p910_return_default_idle(dev);
+
+	if (!netif_queue_stopped(dev))
+		netif_stop_queue(dev);
+
+	w90p910_init_desc(dev);
+
+	dev->trans_start = jiffies;
+	ether->cur_tx = 0x0;
+	ether->finish_tx = 0x0;
+	ether->cur_rx = 0x0;
+
+	w90p910_set_curdest(dev);
+	w90p910_enable_cam(dev);
+	w90p910_enable_cam_command(dev);
+	w90p910_enable_mac_interrupt(dev);
+	w90p910_enable_tx(dev, 1);
+	w90p910_enable_rx(dev, 1);
+	w90p910_trigger_tx(dev);
+	w90p910_trigger_rx(dev);
+
+	dev->trans_start = jiffies;
+
+	if (netif_queue_stopped(dev))
+		netif_wake_queue(dev);
+
+	spin_unlock(&ether->lock);
+}
+
+static void w90p910_mdio_write(struct net_device *dev,
+					int phy_id, int reg, int data)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	struct platform_device *pdev;
+	unsigned int val, i;
+
+	pdev = ether->pdev;
+
+	__raw_writel(data, ether->reg + REG_MIID);
+
+	val = (phy_id << 0x08) | reg;
+	val |= PHYBUSY | PHYWR | MDCCR_VAL;
+	__raw_writel(val, ether->reg + REG_MIIDA);
+
+	for (i = 0; i < DELAY; i++) {
+		if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
+			break;
+	}
+
+	if (i == DELAY)
+		dev_warn(&pdev->dev, "mdio write timed out\n");
+}
+
+static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	struct platform_device *pdev;
+	unsigned int val, i, data;
+
+	pdev = ether->pdev;
+
+	val = (phy_id << 0x08) | reg;
+	val |= PHYBUSY | MDCCR_VAL;
+	__raw_writel(val, ether->reg + REG_MIIDA);
+
+	for (i = 0; i < DELAY; i++) {
+		if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
+			break;
+	}
+
+	if (i == DELAY) {
+		dev_warn(&pdev->dev, "mdio read timed out\n");
+		data = 0xffff;
+	} else {
+		data = __raw_readl(ether->reg + REG_MIID);
+	}
+
+	return data;
+}
+
+static int set_mac_address(struct net_device *dev, void *addr)
+{
+	struct sockaddr *address = addr;
+
+	if (!is_valid_ether_addr(address->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
+	w90p910_write_cam(dev, CAM0, dev->dev_addr);
+
+	return 0;
+}
+
+static int w90p910_ether_close(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd),
+				ether->rdesc, (dma_addr_t)ether->rdesc_phys);
+	dma_free_writecombine(NULL, sizeof(struct w90p910_txbd),
+				ether->tdesc, (dma_addr_t)ether->tdesc_phys);
+
+	netif_stop_queue(dev);
+
+	del_timer_sync(&ether->check_timer);
+	clk_disable(ether->rmiiclk);
+	clk_disable(ether->clk);
+
+	free_irq(ether->txirq, dev);
+	free_irq(ether->rxirq, dev);
+
+	return 0;
+}
+
+static struct net_device_stats *w90p910_ether_stats(struct net_device *dev)
+{
+	struct w90p910_ether *ether;
+
+	ether = netdev_priv(dev);
+
+	return &ether->stats;
+}
+
+static int w90p910_send_frame(struct net_device *dev,
+					unsigned char *data, int length)
+{
+	struct w90p910_ether *ether;
+	struct w90p910_txbd *txbd;
+	struct platform_device *pdev;
+	unsigned char *buffer;
+
+	ether = netdev_priv(dev);
+	pdev = ether->pdev;
+
+	txbd = &ether->tdesc->desclist[ether->cur_tx];
+	buffer = ether->tdesc->tran_buf[ether->cur_tx];
+	if (length > 1514) {
+		dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
+		length = 1514;
+	}
+
+	txbd->sl = length & 0xFFFF;
+
+	memcpy(buffer, data, length);
+
+	txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN;
+
+	w90p910_enable_tx(dev, 1);
+
+	w90p910_trigger_tx(dev);
+
+	ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE;
+	txbd = &ether->tdesc->desclist[ether->cur_tx];
+
+	dev->trans_start = jiffies;
+
+	if (txbd->mode & TX_OWEN_DMA)
+		netif_stop_queue(dev);
+
+	return 0;
+}
+
+static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
+		ether->skb = skb;
+		dev_kfree_skb_irq(skb);
+		return 0;
+	}
+	return -1;
+}
+
+static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
+{
+	struct w90p910_ether *ether;
+	struct w90p910_txbd  *txbd;
+	struct platform_device *pdev;
+	struct tran_pdesc *tran_pdesc;
+	struct net_device *dev;
+	unsigned int cur_entry, entry, status;
+
+	dev = (struct net_device *)dev_id;
+	ether = netdev_priv(dev);
+	pdev = ether->pdev;
+
+	spin_lock(&ether->lock);
+
+	w90p910_get_and_clear_int(dev, &status);
+
+	cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
+
+	tran_pdesc = ether->tdesc_phys;
+	entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+
+	while (entry != cur_entry) {
+		txbd = &ether->tdesc->desclist[ether->finish_tx];
+
+		ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE;
+
+		if (txbd->sl & TXDS_TXCP) {
+			ether->stats.tx_packets++;
+			ether->stats.tx_bytes += txbd->sl & 0xFFFF;
+		} else {
+			ether->stats.tx_errors++;
+		}
+
+		txbd->sl = 0x0;
+		txbd->mode = 0x0;
+
+		if (netif_queue_stopped(dev))
+			netif_wake_queue(dev);
+
+		entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+	}
+
+	if (status & MISTA_EXDEF) {
+		dev_err(&pdev->dev, "emc defer exceed interrupt\n");
+	} else if (status & MISTA_TXBERR) {
+			dev_err(&pdev->dev, "emc bus error interrupt\n");
+			w90p910_reset_mac(dev);
+		} else if (status & MISTA_TDU) {
+				if (netif_queue_stopped(dev))
+					netif_wake_queue(dev);
+			}
+
+	spin_unlock(&ether->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void netdev_rx(struct net_device *dev)
+{
+	struct w90p910_ether *ether;
+	struct w90p910_rxbd *rxbd;
+	struct platform_device *pdev;
+	struct recv_pdesc *rdesc_phys;
+	struct sk_buff *skb;
+	unsigned char *data;
+	unsigned int length, status, val, entry;
+
+	ether = netdev_priv(dev);
+	pdev = ether->pdev;
+	rdesc_phys = ether->rdesc_phys;
+
+	rxbd = &ether->rdesc->desclist[ether->cur_rx];
+
+	do {
+		val = __raw_readl(ether->reg + REG_CRXDSA);
+		entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx];
+
+		if (val == entry)
+			break;
+
+		status = rxbd->sl;
+		length = status & 0xFFFF;
+
+		if (status & RXDS_RXGD) {
+			data = ether->rdesc->recv_buf[ether->cur_rx];
+			skb = dev_alloc_skb(length+2);
+			if (!skb) {
+				dev_err(&pdev->dev, "get skb buffer error\n");
+				ether->stats.rx_dropped++;
+				return;
+			}
+
+			skb->dev = dev;
+			skb_reserve(skb, 2);
+			skb_put(skb, length);
+			skb_copy_to_linear_data(skb, data, length);
+			skb->protocol = eth_type_trans(skb, dev);
+			ether->stats.rx_packets++;
+			ether->stats.rx_bytes += length;
+			netif_rx(skb);
+		} else {
+			ether->stats.rx_errors++;
+
+			if (status & RXDS_RP) {
+				dev_err(&pdev->dev, "rx runt err\n");
+				ether->stats.rx_length_errors++;
+			} else if (status & RXDS_CRCE) {
+					dev_err(&pdev->dev, "rx crc err\n");
+					ether->stats.rx_crc_errors++;
+				}
+
+			if (status & RXDS_ALIE) {
+				dev_err(&pdev->dev, "rx aligment err\n");
+				ether->stats.rx_frame_errors++;
+			} else if (status & RXDS_PTLE) {
+					dev_err(&pdev->dev, "rx longer err\n");
+					ether->stats.rx_over_errors++;
+				}
+			}
+
+		rxbd->sl = RX_OWEN_DMA;
+		rxbd->reserved = 0x0;
+		ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE;
+		rxbd = &ether->rdesc->desclist[ether->cur_rx];
+
+		dev->last_rx = jiffies;
+	} while (1);
+}
+
+static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev;
+	struct w90p910_ether  *ether;
+	struct platform_device *pdev;
+	unsigned int status;
+
+	dev = (struct net_device *)dev_id;
+	ether = netdev_priv(dev);
+	pdev = ether->pdev;
+
+	spin_lock(&ether->lock);
+
+	w90p910_get_and_clear_int(dev, &status);
+
+	if (status & MISTA_RDU) {
+		netdev_rx(dev);
+
+		w90p910_trigger_rx(dev);
+
+		spin_unlock(&ether->lock);
+		return IRQ_HANDLED;
+	} else if (status & MISTA_RXBERR) {
+			dev_err(&pdev->dev, "emc rx bus error\n");
+			w90p910_reset_mac(dev);
+		}
+
+	netdev_rx(dev);
+	spin_unlock(&ether->lock);
+	return IRQ_HANDLED;
+}
+
+static int w90p910_ether_open(struct net_device *dev)
+{
+	struct w90p910_ether *ether;
+	struct platform_device *pdev;
+
+	ether = netdev_priv(dev);
+	pdev = ether->pdev;
+
+	w90p910_reset_mac(dev);
+	w90p910_set_fifo_threshold(dev);
+	w90p910_set_curdest(dev);
+	w90p910_enable_cam(dev);
+	w90p910_enable_cam_command(dev);
+	w90p910_enable_mac_interrupt(dev);
+	w90p910_set_global_maccmd(dev);
+	w90p910_enable_rx(dev, 1);
+
+	ether->rx_packets = 0x0;
+	ether->rx_bytes = 0x0;
+
+	if (request_irq(ether->txirq, w90p910_tx_interrupt,
+						0x0, pdev->name, dev)) {
+		dev_err(&pdev->dev, "register irq tx failed\n");
+		return -EAGAIN;
+	}
+
+	if (request_irq(ether->rxirq, w90p910_rx_interrupt,
+						0x0, pdev->name, dev)) {
+		dev_err(&pdev->dev, "register irq rx failed\n");
+		return -EAGAIN;
+	}
+
+	mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
+	netif_start_queue(dev);
+	w90p910_trigger_rx(dev);
+
+	dev_info(&pdev->dev, "%s is OPENED\n", dev->name);
+
+	return 0;
+}
+
+static void w90p910_ether_set_multicast_list(struct net_device *dev)
+{
+	struct w90p910_ether *ether;
+	unsigned int rx_mode;
+
+	ether = netdev_priv(dev);
+
+	if (dev->flags & IFF_PROMISC)
+		rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
+	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_list)
+			rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
+		else
+				rx_mode = CAMCMR_ECMP | CAMCMR_ABP;
+	__raw_writel(rx_mode, ether->reg + REG_CAMCMR);
+}
+
+static int w90p910_ether_ioctl(struct net_device *dev,
+						struct ifreq *ifr, int cmd)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	struct mii_ioctl_data *data = if_mii(ifr);
+
+	return generic_mii_ioctl(&ether->mii, data, cmd, NULL);
+}
+
+static void w90p910_get_drvinfo(struct net_device *dev,
+					struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_MODULE_NAME);
+	strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	return mii_ethtool_gset(&ether->mii, cmd);
+}
+
+static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	return mii_ethtool_sset(&ether->mii, cmd);
+}
+
+static int w90p910_nway_reset(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	return mii_nway_restart(&ether->mii);
+}
+
+static u32 w90p910_get_link(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	return mii_link_ok(&ether->mii);
+}
+
+static const struct ethtool_ops w90p910_ether_ethtool_ops = {
+	.get_settings	= w90p910_get_settings,
+	.set_settings	= w90p910_set_settings,
+	.get_drvinfo	= w90p910_get_drvinfo,
+	.nway_reset	= w90p910_nway_reset,
+	.get_link	= w90p910_get_link,
+};
+
+static const struct net_device_ops w90p910_ether_netdev_ops = {
+	.ndo_open		= w90p910_ether_open,
+	.ndo_stop		= w90p910_ether_close,
+	.ndo_start_xmit		= w90p910_ether_start_xmit,
+	.ndo_get_stats		= w90p910_ether_stats,
+	.ndo_set_multicast_list	= w90p910_ether_set_multicast_list,
+	.ndo_set_mac_address	= set_mac_address,
+	.ndo_do_ioctl		= w90p910_ether_ioctl,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+};
+
+static void __init get_mac_address(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+	struct platform_device *pdev;
+	char addr[6];
+
+	pdev = ether->pdev;
+
+	addr[0] = 0x00;
+	addr[1] = 0x02;
+	addr[2] = 0xac;
+	addr[3] = 0x55;
+	addr[4] = 0x88;
+	addr[5] = 0xa8;
+
+	if (is_valid_ether_addr(addr))
+		memcpy(dev->dev_addr, &addr, 0x06);
+	else
+		dev_err(&pdev->dev, "invalid mac address\n");
+}
+
+static int w90p910_ether_setup(struct net_device *dev)
+{
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	ether_setup(dev);
+	dev->netdev_ops = &w90p910_ether_netdev_ops;
+	dev->ethtool_ops = &w90p910_ether_ethtool_ops;
+
+	dev->tx_queue_len = 16;
+	dev->dma = 0x0;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	get_mac_address(dev);
+
+	spin_lock_init(&ether->lock);
+
+	ether->cur_tx = 0x0;
+	ether->cur_rx = 0x0;
+	ether->finish_tx = 0x0;
+	ether->linkflag = 0x0;
+	ether->mii.phy_id = 0x01;
+	ether->mii.phy_id_mask = 0x1f;
+	ether->mii.reg_num_mask = 0x1f;
+	ether->mii.dev = dev;
+	ether->mii.mdio_read = w90p910_mdio_read;
+	ether->mii.mdio_write = w90p910_mdio_write;
+
+	setup_timer(&ether->check_timer, w90p910_check_link,
+						(unsigned long)dev);
+
+	return 0;
+}
+
+static int __devinit w90p910_ether_probe(struct platform_device *pdev)
+{
+	struct w90p910_ether *ether;
+	struct net_device *dev;
+	struct resource *res;
+	int error;
+
+	dev = alloc_etherdev(sizeof(struct w90p910_ether));
+	if (!dev)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get I/O memory\n");
+		error = -ENXIO;
+		goto failed_free;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		error = -EBUSY;
+		goto failed_free;
+	}
+
+	ether = netdev_priv(dev);
+
+	ether->reg = ioremap(res->start, resource_size(res));
+	if (ether->reg == NULL) {
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
+		error = -ENXIO;
+		goto failed_free_mem;
+	}
+
+	ether->txirq = platform_get_irq(pdev, 0);
+	if (ether->txirq < 0) {
+		dev_err(&pdev->dev, "failed to get ether tx irq\n");
+		error = -ENXIO;
+		goto failed_free_io;
+	}
+
+	ether->rxirq = platform_get_irq(pdev, 1);
+	if (ether->rxirq < 0) {
+		dev_err(&pdev->dev, "failed to get ether rx irq\n");
+		error = -ENXIO;
+		goto failed_free_txirq;
+	}
+
+	platform_set_drvdata(pdev, dev);
+
+	ether->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ether->clk)) {
+		dev_err(&pdev->dev, "failed to get ether clock\n");
+		error = PTR_ERR(ether->clk);
+		goto failed_free_rxirq;
+	}
+
+	ether->rmiiclk = clk_get(&pdev->dev, "RMII");
+	if (IS_ERR(ether->rmiiclk)) {
+		dev_err(&pdev->dev, "failed to get ether clock\n");
+		error = PTR_ERR(ether->rmiiclk);
+		goto failed_put_clk;
+	}
+
+	ether->pdev = pdev;
+
+	w90p910_ether_setup(dev);
+
+	error = register_netdev(dev);
+	if (error != 0) {
+		dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n");
+		error = -ENODEV;
+		goto failed_put_rmiiclk;
+	}
+
+	return 0;
+failed_put_rmiiclk:
+	clk_put(ether->rmiiclk);
+failed_put_clk:
+	clk_put(ether->clk);
+failed_free_rxirq:
+	free_irq(ether->rxirq, pdev);
+	platform_set_drvdata(pdev, NULL);
+failed_free_txirq:
+	free_irq(ether->txirq, pdev);
+failed_free_io:
+	iounmap(ether->reg);
+failed_free_mem:
+	release_mem_region(res->start, resource_size(res));
+failed_free:
+	free_netdev(dev);
+	return error;
+}
+
+static int __devexit w90p910_ether_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct w90p910_ether *ether = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	clk_put(ether->rmiiclk);
+	clk_put(ether->clk);
+	del_timer_sync(&ether->check_timer);
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(dev);
+	return 0;
+}
+
+static struct platform_driver w90p910_ether_driver = {
+	.probe		= w90p910_ether_probe,
+	.remove		= __devexit_p(w90p910_ether_remove),
+	.driver		= {
+		.name	= "nuc900-emc",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init w90p910_ether_init(void)
+{
+	return platform_driver_register(&w90p910_ether_driver);
+}
+
+static void __exit w90p910_ether_exit(void)
+{
+	platform_driver_unregister(&w90p910_ether_driver);
+}
+
+module_init(w90p910_ether_init);
+module_exit(w90p910_ether_exit);
+
+MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
+MODULE_DESCRIPTION("w90p910 MAC driver!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:nuc900-emc");
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/at1700.c linux-libre-2.6.31-gnu/drivers/net/at1700.c
--- linux-libre-2.6.30-gnu/drivers/net/at1700.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/at1700.c	2009-09-09 18:13:59.000000000 -0400
@@ -318,7 +318,7 @@
 				pos3 = mca_read_stored_pos( slot, 3 );
 				pos4 = mca_read_stored_pos( slot, 4 );
 
-				for (l_i = 0; l_i < 0x09; l_i++)
+				for (l_i = 0; l_i < 8; l_i++)
 					if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i])
 						break;
 				ioaddr = at1700_mca_probe_list[l_i];
diff -druN linux-libre-2.6.30-gnu/drivers/net/atl1c/atl1c_ethtool.c linux-libre-2.6.31-gnu/drivers/net/atl1c/atl1c_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/atl1c/atl1c_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atl1c/atl1c_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -232,11 +232,11 @@
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 
-	strncpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
-	strncpy(drvinfo->version, atl1c_driver_version,
+	strlcpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
+	strlcpy(drvinfo->version, atl1c_driver_version,
 		sizeof(drvinfo->version));
-	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+	strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
 		sizeof(drvinfo->bus_info));
 	drvinfo->n_stats = 0;
 	drvinfo->testinfo_len = 0;
@@ -271,7 +271,7 @@
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 
 	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
-			    WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
+			    WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
 		return -EOPNOTSUPP;
 	/* these settings will always override what we currently have */
 	adapter->wol = 0;
@@ -281,6 +281,8 @@
 	if (wol->wolopts & WAKE_PHY)
 		adapter->wol |= AT_WUFC_LNKC;
 
+	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/atl1c/atl1c.h linux-libre-2.6.31-gnu/drivers/net/atl1c/atl1c.h
--- linux-libre-2.6.30-gnu/drivers/net/atl1c/atl1c.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atl1c/atl1c.h	2009-09-09 18:13:59.000000000 -0400
@@ -188,14 +188,14 @@
 #define RRS_HDS_TYPE_DATA	2
 
 #define RRS_IS_NO_HDS_TYPE(flag) \
-	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0)
+	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0)
 
 #define RRS_IS_HDS_HEAD(flag) \
-	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
 			RRS_HDS_TYPE_HEAD)
 
 #define RRS_IS_HDS_DATA(flag) \
-	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+	((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
 			RRS_HDS_TYPE_DATA)
 
 /* rrs word 3 bit 0:31 */
@@ -245,7 +245,7 @@
 #define RRS_PACKET_TYPE_802_3  	1
 #define RRS_PACKET_TYPE_ETH	0
 #define RRS_PACKET_IS_ETH(word) \
-	(((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \
+	((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \
 			RRS_PACKET_TYPE_ETH)
 #define RRS_RXD_IS_VALID(word) \
 	((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
diff -druN linux-libre-2.6.30-gnu/drivers/net/atl1c/atl1c_main.c linux-libre-2.6.31-gnu/drivers/net/atl1c/atl1c_main.c
--- linux-libre-2.6.30-gnu/drivers/net/atl1c/atl1c_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atl1c/atl1c_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -164,6 +164,24 @@
 }
 
 /*
+ * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads
+ * of the idle status register until the device is actually idle
+ */
+static u32 atl1c_wait_until_idle(struct atl1c_hw *hw)
+{
+	int timeout;
+	u32 data;
+
+	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+		AT_READ_REG(hw, REG_IDLE_STATUS, &data);
+		if ((data & IDLE_STATUS_MASK) == 0)
+			return 0;
+		msleep(1);
+	}
+	return data;
+}
+
+/*
  * atl1c_phy_config - Timer Call-back
  * @data: pointer to netdev cast into an unsigned long
  */
@@ -220,11 +238,11 @@
 		/* link down */
 		if (netif_carrier_ok(netdev)) {
 			hw->hibernate = true;
-			atl1c_set_aspm(hw, false);
 			if (atl1c_stop_mac(hw) != 0)
 				if (netif_msg_hw(adapter))
 					dev_warn(&pdev->dev,
 						"stop mac failed\n");
+			atl1c_set_aspm(hw, false);
 		}
 		netif_carrier_off(netdev);
 	} else {
@@ -240,10 +258,10 @@
 		    adapter->link_duplex != duplex) {
 			adapter->link_speed  = speed;
 			adapter->link_duplex = duplex;
+			atl1c_set_aspm(hw, true);
 			atl1c_enable_tx_ctrl(hw);
 			atl1c_enable_rx_ctrl(hw);
 			atl1c_setup_mac_ctrl(adapter);
-			atl1c_set_aspm(hw, true);
 			if (netif_msg_link(adapter))
 				dev_info(&pdev->dev,
 					"%s: %s NIC Link is Up<%d Mbps %s>\n",
@@ -1106,7 +1124,6 @@
 static int atl1c_stop_mac(struct atl1c_hw *hw)
 {
 	u32 data;
-	int timeout;
 
 	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
 	data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN |
@@ -1117,25 +1134,13 @@
 	data &= ~TXQ_CTRL_EN;
 	AT_WRITE_REG(hw, REG_TWSI_CTRL, data);
 
-	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
-		AT_READ_REG(hw, REG_IDLE_STATUS, &data);
-		if ((data & (IDLE_STATUS_RXQ_NO_IDLE |
-			IDLE_STATUS_TXQ_NO_IDLE)) == 0)
-			break;
-		msleep(1);
-	}
+	atl1c_wait_until_idle(hw);
 
 	AT_READ_REG(hw, REG_MAC_CTRL, &data);
 	data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN);
 	AT_WRITE_REG(hw, REG_MAC_CTRL, data);
 
-	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
-		AT_READ_REG(hw, REG_IDLE_STATUS, &data);
-		if ((data & IDLE_STATUS_MASK) == 0)
-			return 0;
-		msleep(1);
-	}
-	return data;
+	return (int)atl1c_wait_until_idle(hw);
 }
 
 static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
@@ -1178,8 +1183,6 @@
 {
 	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
 	struct pci_dev *pdev = adapter->pdev;
-	u32 idle_status_data = 0;
-	int timeout = 0;
 	int ret;
 
 	AT_WRITE_REG(hw, REG_IMR, 0);
@@ -1198,15 +1201,10 @@
 	AT_WRITE_FLUSH(hw);
 	msleep(10);
 	/* Wait at least 10ms for All module to be Idle */
-	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
-		AT_READ_REG(hw, REG_IDLE_STATUS, &idle_status_data);
-		if ((idle_status_data & IDLE_STATUS_MASK) == 0)
-			break;
-		msleep(1);
-	}
-	if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+
+	if (atl1c_wait_until_idle(hw)) {
 		dev_err(&pdev->dev,
-			"MAC state machine cann't be idle since"
+			"MAC state machine can't be idle since"
 			" disabled for 10ms second\n");
 		return -1;
 	}
@@ -1242,9 +1240,7 @@
 
 	AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
 
-	pm_ctrl_data &= PM_CTRL_SERDES_PD_EX_L1;
-	pm_ctrl_data |= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
-	pm_ctrl_data |= ~PM_CTRL_SERDES_L1_EN;
+	pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
 	pm_ctrl_data &=  ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
 			PM_CTRL_L1_ENTRY_TIMER_SHIFT);
 
@@ -1254,19 +1250,11 @@
 		pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
 		pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
 
-		if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) {
-			pm_ctrl_data |= AT_ASPM_L1_TIMER <<
-				PM_CTRL_L1_ENTRY_TIMER_SHIFT;
-			pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
-		} else
-			pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
-
-		if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
-			pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;
-		else
-			pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
-
+		pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
+		pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
 	} else {
+		pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
+		pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
 		pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
 		pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
 
@@ -1701,7 +1689,7 @@
 		if (likely(RRS_RXD_IS_VALID(rrs->word3))) {
 			rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) &
 				RRS_RX_RFD_CNT_MASK;
-			if (unlikely(rfd_num) != 1)
+			if (unlikely(rfd_num != 1))
 				/* TODO support mul rfd*/
 				if (netif_msg_rx_err(adapter))
 					dev_warn(&pdev->dev,
@@ -2123,7 +2111,6 @@
 	atl1c_tx_map(adapter, skb, tpd, type);
 	atl1c_tx_queue(adapter, skb, tpd, type);
 
-	netdev->trans_start = jiffies;
 	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 	return NETDEV_TX_OK;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/atl1e/atl1e_ethtool.c linux-libre-2.6.31-gnu/drivers/net/atl1e/atl1e_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/atl1e/atl1e_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atl1e/atl1e_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -365,6 +365,8 @@
 	if (wol->wolopts & WAKE_PHY)
 		adapter->wol |= AT_WUFC_LNKC;
 
+	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/atl1e/atl1e.h linux-libre-2.6.31-gnu/drivers/net/atl1e/atl1e.h
--- linux-libre-2.6.30-gnu/drivers/net/atl1e/atl1e.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atl1e/atl1e.h	2009-09-09 18:13:59.000000000 -0400
@@ -429,7 +429,6 @@
 	struct mii_if_info  mii;    /* MII interface info */
 	struct atl1e_hw        hw;
 	struct atl1e_hw_stats  hw_stats;
-	struct net_device_stats net_stats;
 
 	bool have_msi;
 	u32 wol;
diff -druN linux-libre-2.6.30-gnu/drivers/net/atl1e/atl1e_main.c linux-libre-2.6.31-gnu/drivers/net/atl1e/atl1e_main.c
--- linux-libre-2.6.30-gnu/drivers/net/atl1e/atl1e_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atl1e/atl1e_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -1154,7 +1154,7 @@
 {
 	struct atl1e_adapter *adapter = netdev_priv(netdev);
 	struct atl1e_hw_stats  *hw_stats = &adapter->hw_stats;
-	struct net_device_stats *net_stats = &adapter->net_stats;
+	struct net_device_stats *net_stats = &netdev->stats;
 
 	net_stats->rx_packets = hw_stats->rx_ok;
 	net_stats->tx_packets = hw_stats->tx_ok;
@@ -1182,7 +1182,7 @@
 	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
 	net_stats->tx_window_errors  = hw_stats->tx_late_col;
 
-	return &adapter->net_stats;
+	return net_stats;
 }
 
 static void atl1e_update_hw_stats(struct atl1e_adapter *adapter)
@@ -1310,7 +1310,7 @@
 
 		/* link event */
 		if (status & (ISR_GPHY | ISR_MANUAL)) {
-			adapter->net_stats.tx_carrier_errors++;
+			netdev->stats.tx_carrier_errors++;
 			atl1e_link_chg_event(adapter);
 			break;
 		}
@@ -1602,7 +1602,7 @@
 	}
 
 	if (skb_is_gso(skb)) {
-		if (skb->protocol == ntohs(ETH_P_IP) ||
+		if (skb->protocol == htons(ETH_P_IP) ||
 		   (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) {
 			proto_hdr_len = skb_transport_offset(skb) +
 					tcp_hdrlen(skb);
@@ -1795,8 +1795,7 @@
 			memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
 
 			tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
-			if (tx_buffer->skb)
-				BUG();
+			BUG_ON(tx_buffer->skb);
 
 			tx_buffer->skb = NULL;
 			tx_buffer->length =
@@ -1879,7 +1878,7 @@
 				TPD_VLAN_SHIFT;
 	}
 
-	if (skb->protocol == ntohs(ETH_P_8021Q))
+	if (skb->protocol == htons(ETH_P_8021Q))
 		tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT;
 
 	if (skb_network_offset(skb) != ETH_HLEN)
@@ -1895,7 +1894,7 @@
 	atl1e_tx_map(adapter, skb, tpd);
 	atl1e_tx_queue(adapter, tpd_req, tpd);
 
-	netdev->trans_start = jiffies;
+	netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
 	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 	return NETDEV_TX_OK;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/atlx/atl1.c linux-libre-2.6.31-gnu/drivers/net/atlx/atl1.c
--- linux-libre-2.6.30-gnu/drivers/net/atlx/atl1.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atlx/atl1.c	2009-09-09 18:13:59.000000000 -0400
@@ -2213,8 +2213,7 @@
 	nr_frags = skb_shinfo(skb)->nr_frags;
 	next_to_use = atomic_read(&tpd_ring->next_to_use);
 	buffer_info = &tpd_ring->buffer_info[next_to_use];
-	if (unlikely(buffer_info->skb))
-		BUG();
+	BUG_ON(buffer_info->skb);
 	/* put skb in last TPD */
 	buffer_info->skb = NULL;
 
@@ -2280,8 +2279,8 @@
 			ATL1_MAX_TX_BUF_LEN;
 		for (i = 0; i < nseg; i++) {
 			buffer_info = &tpd_ring->buffer_info[next_to_use];
-			if (unlikely(buffer_info->skb))
-				BUG();
+			BUG_ON(buffer_info->skb);
+
 			buffer_info->skb = NULL;
 			buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
 				ATL1_MAX_TX_BUF_LEN : buf_len;
@@ -2383,7 +2382,7 @@
 
 	mss = skb_shinfo(skb)->gso_size;
 	if (mss) {
-		if (skb->protocol == ntohs(ETH_P_IP)) {
+		if (skb->protocol == htons(ETH_P_IP)) {
 			proto_hdr_len = (skb_transport_offset(skb) +
 					 tcp_hdrlen(skb));
 			if (unlikely(proto_hdr_len > len)) {
@@ -2438,7 +2437,6 @@
 	atl1_tx_queue(adapter, count, ptpd);
 	atl1_update_mailbox(adapter);
 	mmiowb();
-	netdev->trans_start = jiffies;
 	return NETDEV_TX_OK;
 }
 
@@ -3380,11 +3378,11 @@
 {
 	struct atl1_adapter *adapter = netdev_priv(netdev);
 
-	strncpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
-	strncpy(drvinfo->version, ATLX_DRIVER_VERSION,
+	strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
+	strlcpy(drvinfo->version, ATLX_DRIVER_VERSION,
 		sizeof(drvinfo->version));
-	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+	strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
 		sizeof(drvinfo->bus_info));
 	drvinfo->eedump_len = ATL1_EEDUMP_LEN;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/atlx/atl2.c linux-libre-2.6.31-gnu/drivers/net/atlx/atl2.c
--- linux-libre-2.6.30-gnu/drivers/net/atlx/atl2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/atlx/atl2.c	2009-09-09 18:13:59.000000000 -0400
@@ -2071,7 +2071,7 @@
 	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
 		return -EOPNOTSUPP;
 
-	if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST))
+	if (wol->wolopts & (WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
 		return -EOPNOTSUPP;
 
 	/* these settings will always override what we currently have */
diff -druN linux-libre-2.6.30-gnu/drivers/net/au1000_eth.c linux-libre-2.6.31-gnu/drivers/net/au1000_eth.c
--- linux-libre-2.6.30-gnu/drivers/net/au1000_eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/au1000_eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -957,7 +957,7 @@
 		/* We've wrapped around and the transmitter is still busy */
 		netif_stop_queue(dev);
 		aup->tx_full = 1;
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	else if (buff_stat & TX_T_DONE) {
 		update_tx_stats(dev, ptxd->status);
diff -druN linux-libre-2.6.30-gnu/drivers/net/b44.c linux-libre-2.6.31-gnu/drivers/net/b44.c
--- linux-libre-2.6.30-gnu/drivers/net/b44.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/b44.c	2009-09-09 18:13:59.000000000 -0400
@@ -782,7 +782,7 @@
 		drop_it:
 			b44_recycle_rx(bp, cons, bp->rx_prod);
 		drop_it_no_recycle:
-			bp->stats.rx_dropped++;
+			bp->dev->stats.rx_dropped++;
 			goto next_pkt;
 		}
 
@@ -952,9 +952,10 @@
 	int rc = NETDEV_TX_OK;
 	dma_addr_t mapping;
 	u32 len, entry, ctrl;
+	unsigned long flags;
 
 	len = skb->len;
-	spin_lock_irq(&bp->lock);
+	spin_lock_irqsave(&bp->lock, flags);
 
 	/* This is a hard error, log it. */
 	if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) {
@@ -1027,7 +1028,7 @@
 	dev->trans_start = jiffies;
 
 out_unlock:
-	spin_unlock_irq(&bp->lock);
+	spin_unlock_irqrestore(&bp->lock, flags);
 
 	return rc;
 
@@ -1647,7 +1648,7 @@
 static struct net_device_stats *b44_get_stats(struct net_device *dev)
 {
 	struct b44 *bp = netdev_priv(dev);
-	struct net_device_stats *nstat = &bp->stats;
+	struct net_device_stats *nstat = &dev->stats;
 	struct b44_hw_stats *hwstat = &bp->hw_stats;
 
 	/* Convert HW stats into netdevice stats. */
diff -druN linux-libre-2.6.30-gnu/drivers/net/b44.h linux-libre-2.6.31-gnu/drivers/net/b44.h
--- linux-libre-2.6.30-gnu/drivers/net/b44.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/b44.h	2009-09-09 18:13:59.000000000 -0400
@@ -97,7 +97,7 @@
 #define B44_DMARX_STAT	0x021CUL /* DMA RX Current Active Desc. + Status */
 #define  DMARX_STAT_CDMASK	0x00000fff /* Current Descriptor Mask */
 #define  DMARX_STAT_SMASK	0x0000f000 /* State Mask */
-#define  DMARX_STAT_SDISABLED	0x00000000 /* State Disbaled */
+#define  DMARX_STAT_SDISABLED	0x00000000 /* State Disabled */
 #define  DMARX_STAT_SACTIVE	0x00001000 /* State Active */
 #define  DMARX_STAT_SIDLE	0x00002000 /* State Idle Wait */
 #define  DMARX_STAT_SSTOPPED	0x00003000 /* State Stopped */
@@ -384,7 +384,6 @@
 
 	struct timer_list	timer;
 
-	struct net_device_stats	stats;
 	struct b44_hw_stats	hw_stats;
 
 	struct ssb_device	*sdev;
diff -druN linux-libre-2.6.30-gnu/drivers/net/benet/be_cmds.c linux-libre-2.6.31-gnu/drivers/net/benet/be_cmds.c
--- linux-libre-2.6.30-gnu/drivers/net/benet/be_cmds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/benet/be_cmds.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,133 @@
 
 #include "be.h"
 
+static void be_mcc_notify(struct be_ctrl_info *ctrl)
+{
+	struct be_queue_info *mccq = &ctrl->mcc_obj.q;
+	u32 val = 0;
+
+	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
+	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
+	iowrite32(val, ctrl->db + DB_MCCQ_OFFSET);
+}
+
+/* To check if valid bit is set, check the entire word as we don't know
+ * the endianness of the data (old entry is host endian while a new entry is
+ * little endian) */
+static inline bool be_mcc_compl_is_new(struct be_mcc_cq_entry *compl)
+{
+	if (compl->flags != 0) {
+		compl->flags = le32_to_cpu(compl->flags);
+		BUG_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0);
+		return true;
+	} else {
+		return false;
+	}
+}
+
+/* Need to reset the entire word that houses the valid bit */
+static inline void be_mcc_compl_use(struct be_mcc_cq_entry *compl)
+{
+	compl->flags = 0;
+}
+
+static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
+	struct be_mcc_cq_entry *compl)
+{
+	u16 compl_status, extd_status;
+
+	/* Just swap the status to host endian; mcc tag is opaquely copied
+	 * from mcc_wrb */
+	be_dws_le_to_cpu(compl, 4);
+
+	compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
+				CQE_STATUS_COMPL_MASK;
+	if (compl_status != MCC_STATUS_SUCCESS) {
+		extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
+				CQE_STATUS_EXTD_MASK;
+		printk(KERN_WARNING DRV_NAME
+			" error in cmd completion: status(compl/extd)=%d/%d\n",
+			compl_status, extd_status);
+		return -1;
+	}
+	return 0;
+}
+
+/* Link state evt is a string of bytes; no need for endian swapping */
+static void be_async_link_state_process(struct be_ctrl_info *ctrl,
+		struct be_async_event_link_state *evt)
+{
+	ctrl->async_cb(ctrl->adapter_ctxt,
+		evt->port_link_status == ASYNC_EVENT_LINK_UP ? true : false);
+}
+
+static inline bool is_link_state_evt(u32 trailer)
+{
+	return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
+		ASYNC_TRAILER_EVENT_CODE_MASK) ==
+				ASYNC_EVENT_CODE_LINK_STATE);
+}
+
+static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl)
+{
+	struct be_queue_info *mcc_cq = &ctrl->mcc_obj.cq;
+	struct be_mcc_cq_entry *compl = queue_tail_node(mcc_cq);
+
+	if (be_mcc_compl_is_new(compl)) {
+		queue_tail_inc(mcc_cq);
+		return compl;
+	}
+	return NULL;
+}
+
+void be_process_mcc(struct be_ctrl_info *ctrl)
+{
+	struct be_mcc_cq_entry *compl;
+	int num = 0;
+
+	spin_lock_bh(&ctrl->mcc_cq_lock);
+	while ((compl = be_mcc_compl_get(ctrl))) {
+		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
+			/* Interpret flags as an async trailer */
+			BUG_ON(!is_link_state_evt(compl->flags));
+
+			/* Interpret compl as a async link evt */
+			be_async_link_state_process(ctrl,
+				(struct be_async_event_link_state *) compl);
+		} else {
+			be_mcc_compl_process(ctrl, compl);
+			atomic_dec(&ctrl->mcc_obj.q.used);
+		}
+		be_mcc_compl_use(compl);
+		num++;
+	}
+	if (num)
+		be_cq_notify(ctrl, ctrl->mcc_obj.cq.id, true, num);
+	spin_unlock_bh(&ctrl->mcc_cq_lock);
+}
+
+/* Wait till no more pending mcc requests are present */
+static void be_mcc_wait_compl(struct be_ctrl_info *ctrl)
+{
+#define mcc_timeout		50000 /* 5s timeout */
+	int i;
+	for (i = 0; i < mcc_timeout; i++) {
+		be_process_mcc(ctrl);
+		if (atomic_read(&ctrl->mcc_obj.q.used) == 0)
+			break;
+		udelay(100);
+	}
+	if (i == mcc_timeout)
+		printk(KERN_WARNING DRV_NAME "mcc poll timed out\n");
+}
+
+/* Notify MCC requests and wait for completion */
+static void be_mcc_notify_wait(struct be_ctrl_info *ctrl)
+{
+	be_mcc_notify(ctrl);
+	be_mcc_wait_compl(ctrl);
+}
+
 static int be_mbox_db_ready_wait(void __iomem *db)
 {
 	int cnt = 0, wait = 5;
@@ -44,11 +171,11 @@
 
 /*
  * Insert the mailbox address into the doorbell in two steps
+ * Polls on the mbox doorbell till a command completion (or a timeout) occurs
  */
 static int be_mbox_db_ring(struct be_ctrl_info *ctrl)
 {
 	int status;
-	u16 compl_status, extd_status;
 	u32 val = 0;
 	void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
 	struct be_dma_mem *mbox_mem = &ctrl->mbox_mem;
@@ -79,24 +206,17 @@
 	if (status != 0)
 		return status;
 
-	/* compl entry has been made now */
-	be_dws_le_to_cpu(cqe, sizeof(*cqe));
-	if (!(cqe->flags & CQE_FLAGS_VALID_MASK)) {
-		printk(KERN_WARNING DRV_NAME ": ERROR invalid mbox compl\n");
+	/* A cq entry has been made now */
+	if (be_mcc_compl_is_new(cqe)) {
+		status = be_mcc_compl_process(ctrl, &mbox->cqe);
+		be_mcc_compl_use(cqe);
+		if (status)
+			return status;
+	} else {
+		printk(KERN_WARNING DRV_NAME "invalid mailbox completion\n");
 		return -1;
 	}
-
-	compl_status = (cqe->status >> CQE_STATUS_COMPL_SHIFT) &
-				CQE_STATUS_COMPL_MASK;
-	if (compl_status != MCC_STATUS_SUCCESS) {
-		extd_status = (cqe->status >> CQE_STATUS_EXTD_SHIFT) &
-				CQE_STATUS_EXTD_MASK;
-		printk(KERN_WARNING DRV_NAME
-			": ERROR in cmd compl. status(compl/extd)=%d/%d\n",
-			compl_status, extd_status);
-	}
-
-	return compl_status;
+	return 0;
 }
 
 static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage)
@@ -235,6 +355,18 @@
 	return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
 }
 
+static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq)
+{
+	struct be_mcc_wrb *wrb = NULL;
+	if (atomic_read(&mccq->used) < mccq->len) {
+		wrb = queue_head_node(mccq);
+		queue_head_inc(mccq);
+		atomic_inc(&mccq->used);
+		memset(wrb, 0, sizeof(*wrb));
+	}
+	return wrb;
+}
+
 int be_cmd_eq_create(struct be_ctrl_info *ctrl,
 		struct be_queue_info *eq, int eq_delay)
 {
@@ -244,7 +376,7 @@
 	struct be_dma_mem *q_mem = &eq->dma_mem;
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -272,7 +404,7 @@
 		eq->id = le16_to_cpu(resp->eq_id);
 		eq->created = true;
 	}
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -284,7 +416,7 @@
 	struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -304,7 +436,7 @@
 	if (!status)
 		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -315,7 +447,7 @@
 	struct be_cmd_req_pmac_add *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -332,7 +464,7 @@
 		*pmac_id = le32_to_cpu(resp->pmac_id);
 	}
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -342,7 +474,7 @@
 	struct be_cmd_req_pmac_del *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -354,7 +486,7 @@
 	req->pmac_id = cpu_to_le32(pmac_id);
 
 	status = be_mbox_db_ring(ctrl);
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 
 	return status;
 }
@@ -370,7 +502,7 @@
 	void *ctxt = &req->context;
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -388,7 +520,7 @@
 	AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
 	AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
 	AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
-	AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 0);
+	AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
 	AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func);
 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
@@ -399,7 +531,56 @@
 		cq->id = le16_to_cpu(resp->cq_id);
 		cq->created = true;
 	}
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
+
+	return status;
+}
+
+static u32 be_encoded_q_len(int q_len)
+{
+	u32 len_encoded = fls(q_len); /* log2(len) + 1 */
+	if (len_encoded == 16)
+		len_encoded = 0;
+	return len_encoded;
+}
+
+int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
+			struct be_queue_info *mccq,
+			struct be_queue_info *cq)
+{
+	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+	struct be_cmd_req_mcc_create *req = embedded_payload(wrb);
+	struct be_dma_mem *q_mem = &mccq->dma_mem;
+	void *ctxt = &req->context;
+	int status;
+
+	spin_lock(&ctrl->mbox_lock);
+	memset(wrb, 0, sizeof(*wrb));
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+
+	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
+
+	AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, ctrl->pci_func);
+	AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
+	AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
+		be_encoded_q_len(mccq->len));
+	AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id);
+
+	be_dws_cpu_to_le(ctxt, sizeof(req->context));
+
+	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
+
+	status = be_mbox_db_ring(ctrl);
+	if (!status) {
+		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
+		mccq->id = le16_to_cpu(resp->id);
+		mccq->created = true;
+	}
+	spin_unlock(&ctrl->mbox_lock);
 
 	return status;
 }
@@ -415,7 +596,7 @@
 	int status;
 	u32 len_encoded;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -446,7 +627,7 @@
 		txq->id = le16_to_cpu(resp->cid);
 		txq->created = true;
 	}
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 
 	return status;
 }
@@ -460,7 +641,7 @@
 	struct be_dma_mem *q_mem = &rxq->dma_mem;
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -482,7 +663,7 @@
 		rxq->id = le16_to_cpu(resp->id);
 		rxq->created = true;
 	}
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 
 	return status;
 }
@@ -496,7 +677,7 @@
 	u8 subsys = 0, opcode = 0;
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 
 	memset(wrb, 0, sizeof(*wrb));
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -518,6 +699,10 @@
 		subsys = CMD_SUBSYSTEM_ETH;
 		opcode = OPCODE_ETH_RX_DESTROY;
 		break;
+	case QTYPE_MCCQ:
+		subsys = CMD_SUBSYSTEM_COMMON;
+		opcode = OPCODE_COMMON_MCC_DESTROY;
+		break;
 	default:
 		printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n");
 		status = -1;
@@ -528,7 +713,7 @@
 
 	status = be_mbox_db_ring(ctrl);
 err:
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 
 	return status;
 }
@@ -541,7 +726,7 @@
 	struct be_cmd_req_if_create *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -562,7 +747,7 @@
 			*pmac_id = le32_to_cpu(resp->pmac_id);
 	}
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -572,7 +757,7 @@
 	struct be_cmd_req_if_destroy *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -583,7 +768,7 @@
 	req->interface_id = cpu_to_le32(interface_id);
 	status = be_mbox_db_ring(ctrl);
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 
 	return status;
 }
@@ -598,7 +783,7 @@
 	struct be_sge *sge = nonembedded_sgl(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	memset(req, 0, sizeof(*req));
@@ -617,18 +802,20 @@
 		be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats));
 	}
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
 int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
-			struct be_link_info *link)
+			bool *link_up)
 {
 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
 	struct be_cmd_req_link_status *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
+
+	*link_up = false;
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -639,14 +826,11 @@
 	status = be_mbox_db_ring(ctrl);
 	if (!status) {
 		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
-		link->speed = resp->mac_speed;
-		link->duplex = resp->mac_duplex;
-		link->fault = resp->mac_fault;
-	} else {
-		link->speed = PHY_LINK_SPEED_ZERO;
+		if (resp->mac_speed != PHY_LINK_SPEED_ZERO)
+			*link_up = true;
 	}
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -656,7 +840,7 @@
 	struct be_cmd_req_get_fw_version *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -670,7 +854,7 @@
 		strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);
 	}
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -681,7 +865,7 @@
 	struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -696,7 +880,7 @@
 
 	status = be_mbox_db_ring(ctrl);
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -707,7 +891,7 @@
 	struct be_cmd_req_vlan_config *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 	memset(wrb, 0, sizeof(*wrb));
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
@@ -726,18 +910,22 @@
 
 	status = be_mbox_db_ring(ctrl);
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
+/* Use MCC for this command as it may be called in BH context */
 int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_promiscuous_config *req = embedded_payload(wrb);
-	int status;
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_promiscuous_config *req;
 
-	spin_lock(&ctrl->cmd_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock_bh(&ctrl->mcc_lock);
+
+	wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
+	BUG_ON(!wrb);
+
+	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -749,21 +937,29 @@
 	else
 		req->port0_promiscuous = en;
 
-	status = be_mbox_db_ring(ctrl);
+	be_mcc_notify_wait(ctrl);
 
-	spin_unlock(&ctrl->cmd_lock);
-	return status;
+	spin_unlock_bh(&ctrl->mcc_lock);
+	return 0;
 }
 
-int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table,
-			u32 num, bool promiscuous)
+/*
+ * Use MCC for this command as it may be called in BH context
+ * (mc == NULL) => multicast promiscous
+ */
+int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
+		struct dev_mc_list *mc_list, u32 mc_count)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_mcast_mac_config *req = embedded_payload(wrb);
-	int status;
+#define BE_MAX_MC		32 /* set mcast promisc if > 32 */
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_mcast_mac_config *req;
 
-	spin_lock(&ctrl->cmd_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock_bh(&ctrl->mcc_lock);
+
+	wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
+	BUG_ON(!wrb);
+
+	req = embedded_payload(wrb);
 
 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
 
@@ -771,17 +967,23 @@
 		OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req));
 
 	req->interface_id = if_id;
-	req->promiscuous = promiscuous;
-	if (!promiscuous) {
-		req->num_mac = cpu_to_le16(num);
-		if (num)
-			memcpy(req->mac, mac_table, ETH_ALEN * num);
+	if (mc_list && mc_count <= BE_MAX_MC) {
+		int i;
+		struct dev_mc_list *mc;
+
+		req->num_mac = cpu_to_le16(mc_count);
+
+		for (mc = mc_list, i = 0; mc; mc = mc->next, i++)
+			memcpy(req->mac[i].byte, mc->dmi_addr, ETH_ALEN);
+	} else {
+		req->promiscuous = 1;
 	}
 
-	status = be_mbox_db_ring(ctrl);
+	be_mcc_notify_wait(ctrl);
 
-	spin_unlock(&ctrl->cmd_lock);
-	return status;
+	spin_unlock_bh(&ctrl->mcc_lock);
+
+	return 0;
 }
 
 int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc)
@@ -790,7 +992,7 @@
 	struct be_cmd_req_set_flow_control *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 
 	memset(wrb, 0, sizeof(*wrb));
 
@@ -804,7 +1006,7 @@
 
 	status = be_mbox_db_ring(ctrl);
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -814,7 +1016,7 @@
 	struct be_cmd_req_get_flow_control *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 
 	memset(wrb, 0, sizeof(*wrb));
 
@@ -831,7 +1033,7 @@
 		*rx_fc = le16_to_cpu(resp->rx_flow_control);
 	}
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
@@ -841,7 +1043,7 @@
 	struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb);
 	int status;
 
-	spin_lock(&ctrl->cmd_lock);
+	spin_lock(&ctrl->mbox_lock);
 
 	memset(wrb, 0, sizeof(*wrb));
 
@@ -856,6 +1058,6 @@
 		*port_num = le32_to_cpu(resp->phys_port);
 	}
 
-	spin_unlock(&ctrl->cmd_lock);
+	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/benet/be_cmds.h linux-libre-2.6.31-gnu/drivers/net/benet/be_cmds.h
--- linux-libre-2.6.30-gnu/drivers/net/benet/be_cmds.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/benet/be_cmds.h	2009-09-09 18:13:59.000000000 -0400
@@ -76,6 +76,34 @@
 	u32 flags;		/* dword 3 */
 };
 
+/* When the async bit of mcc_compl is set, the last 4 bytes of
+ * mcc_compl is interpreted as follows:
+ */
+#define ASYNC_TRAILER_EVENT_CODE_SHIFT	8	/* bits 8 - 15 */
+#define ASYNC_TRAILER_EVENT_CODE_MASK	0xFF
+#define ASYNC_EVENT_CODE_LINK_STATE	0x1
+struct be_async_event_trailer {
+	u32 code;
+};
+
+enum {
+	ASYNC_EVENT_LINK_DOWN 	= 0x0,
+	ASYNC_EVENT_LINK_UP 	= 0x1
+};
+
+/* When the event code of an async trailer is link-state, the mcc_compl
+ * must be interpreted as follows
+ */
+struct be_async_event_link_state {
+	u8 physical_port;
+	u8 port_link_status;
+	u8 port_duplex;
+	u8 port_speed;
+	u8 port_fault;
+	u8 rsvd0[7];
+	struct be_async_event_trailer trailer;
+} __packed;
+
 struct be_mcc_mailbox {
 	struct be_mcc_wrb wrb;
 	struct be_mcc_cq_entry cqe;
@@ -101,6 +129,7 @@
 #define OPCODE_COMMON_FIRMWARE_CONFIG			42
 #define OPCODE_COMMON_NTWK_INTERFACE_CREATE 		50
 #define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 		51
+#define OPCODE_COMMON_MCC_DESTROY        		53
 #define OPCODE_COMMON_CQ_DESTROY        		54
 #define OPCODE_COMMON_EQ_DESTROY        		55
 #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG		58
@@ -269,6 +298,38 @@
 	u16 rsvd0;
 } __packed;
 
+/******************** Create MCCQ ***************************/
+/* Pseudo amap definition in which each bit of the actual structure is defined
+ * as a byte: used to calculate offset/shift/mask of each field */
+struct amap_mcc_context {
+	u8 con_index[14];
+	u8 rsvd0[2];
+	u8 ring_size[4];
+	u8 fetch_wrb;
+	u8 fetch_r2t;
+	u8 cq_id[10];
+	u8 prod_index[14];
+	u8 fid[8];
+	u8 pdid[9];
+	u8 valid;
+	u8 rsvd1[32];
+	u8 rsvd2[32];
+} __packed;
+
+struct be_cmd_req_mcc_create {
+	struct be_cmd_req_hdr hdr;
+	u16 num_pages;
+	u16 rsvd0;
+	u8 context[sizeof(struct amap_mcc_context) / 8];
+	struct phys_addr pages[8];
+} __packed;
+
+struct be_cmd_resp_mcc_create {
+	struct be_cmd_resp_hdr hdr;
+	u16 id;
+	u16 rsvd0;
+} __packed;
+
 /******************** Create TxQ ***************************/
 #define BE_ETH_TX_RING_TYPE_STANDARD    	2
 #define BE_ULP1_NUM				1
@@ -341,7 +402,8 @@
 	QTYPE_EQ = 1,
 	QTYPE_CQ,
 	QTYPE_TXQ,
-	QTYPE_RXQ
+	QTYPE_RXQ,
+	QTYPE_MCCQ
 };
 
 struct be_cmd_req_q_destroy {
@@ -546,12 +608,6 @@
 	u32 rsvd;
 };
 
-struct be_link_info {
-	u8 duplex;
-	u8 speed;
-	u8 fault;
-};
-
 enum {
 	PHY_LINK_DUPLEX_NONE = 0x0,
 	PHY_LINK_DUPLEX_HALF = 0x1,
@@ -657,6 +713,9 @@
 			struct be_queue_info *cq, struct be_queue_info *eq,
 			bool sol_evts, bool no_delay,
 			int num_cqe_dma_coalesce);
+extern int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
+			struct be_queue_info *mccq,
+			struct be_queue_info *cq);
 extern int be_cmd_txq_create(struct be_ctrl_info *ctrl,
 			struct be_queue_info *txq,
 			struct be_queue_info *cq);
@@ -667,7 +726,7 @@
 extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
 			int type);
 extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
-			struct be_link_info *link);
+			bool *link_up);
 extern int be_cmd_reset(struct be_ctrl_info *ctrl);
 extern int be_cmd_get_stats(struct be_ctrl_info *ctrl,
 			struct be_dma_mem *nonemb_cmd);
@@ -679,10 +738,11 @@
 			bool promiscuous);
 extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl,
 			u8 port_num, bool en);
-extern int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id,
-			u8 *mac_table, u32 num, bool promiscuous);
+extern int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
+			struct dev_mc_list *mc_list, u32 mc_count);
 extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl,
 			u32 tx_fc, u32 rx_fc);
 extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl,
 			u32 *tx_fc, u32 *rx_fc);
 extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num);
+extern void be_process_mcc(struct be_ctrl_info *ctrl);
diff -druN linux-libre-2.6.30-gnu/drivers/net/benet/be_ethtool.c linux-libre-2.6.31-gnu/drivers/net/benet/be_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/benet/be_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/benet/be_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -162,8 +162,8 @@
 		return -EINVAL;
 
 	adapter->max_rx_coal = coalesce->rx_max_coalesced_frames;
-	if (adapter->max_rx_coal > MAX_SKB_FRAGS)
-		adapter->max_rx_coal = MAX_SKB_FRAGS - 1;
+	if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME)
+		adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME;
 
 	/* if AIC is being turned on now, start with an EQD of 0 */
 	if (rx_eq->enable_aic == 0 &&
diff -druN linux-libre-2.6.30-gnu/drivers/net/benet/be.h linux-libre-2.6.31-gnu/drivers/net/benet/be.h
--- linux-libre-2.6.30-gnu/drivers/net/benet/be.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/benet/be.h	2009-09-09 18:13:59.000000000 -0400
@@ -65,7 +65,7 @@
 #define TX_CQ_LEN		1024
 #define RX_Q_LEN		1024	/* Does not support any other value */
 #define RX_CQ_LEN		1024
-#define MCC_Q_LEN		64	/* total size not to exceed 8 pages */
+#define MCC_Q_LEN		128	/* total size not to exceed 8 pages */
 #define MCC_CQ_LEN		256
 
 #define BE_NAPI_WEIGHT		64
@@ -73,7 +73,7 @@
 #define RX_FRAGS_REFILL_WM	(RX_Q_LEN - MAX_RX_POST)
 
 #define BE_MAX_LRO_DESCRIPTORS  16
-#define BE_MAX_FRAGS_PER_FRAME  16
+#define BE_MAX_FRAGS_PER_FRAME  (min((u32) 16, (u32) MAX_SKB_FRAGS))
 
 struct be_dma_mem {
 	void *va;
@@ -91,6 +91,61 @@
 	atomic_t used;	/* Number of valid elements in the queue */
 };
 
+static inline u32 MODULO(u16 val, u16 limit)
+{
+	BUG_ON(limit & (limit - 1));
+	return val & (limit - 1);
+}
+
+static inline void index_adv(u16 *index, u16 val, u16 limit)
+{
+	*index = MODULO((*index + val), limit);
+}
+
+static inline void index_inc(u16 *index, u16 limit)
+{
+	*index = MODULO((*index + 1), limit);
+}
+
+static inline void *queue_head_node(struct be_queue_info *q)
+{
+	return q->dma_mem.va + q->head * q->entry_size;
+}
+
+static inline void *queue_tail_node(struct be_queue_info *q)
+{
+	return q->dma_mem.va + q->tail * q->entry_size;
+}
+
+static inline void queue_head_inc(struct be_queue_info *q)
+{
+	index_inc(&q->head, q->len);
+}
+
+static inline void queue_tail_inc(struct be_queue_info *q)
+{
+	index_inc(&q->tail, q->len);
+}
+
+
+struct be_eq_obj {
+	struct be_queue_info q;
+	char desc[32];
+
+	/* Adaptive interrupt coalescing (AIC) info */
+	bool enable_aic;
+	u16 min_eqd;		/* in usecs */
+	u16 max_eqd;		/* in usecs */
+	u16 cur_eqd;		/* in usecs */
+
+	struct napi_struct napi;
+};
+
+struct be_mcc_obj {
+	struct be_queue_info q;
+	struct be_queue_info cq;
+};
+
 struct be_ctrl_info {
 	u8 __iomem *csr;
 	u8 __iomem *db;		/* Door Bell */
@@ -98,11 +153,20 @@
 	int pci_func;
 
 	/* Mbox used for cmd request/response */
-	spinlock_t cmd_lock;	/* For serializing cmds to BE card */
+	spinlock_t mbox_lock;	/* For serializing mbox cmds to BE card */
 	struct be_dma_mem mbox_mem;
 	/* Mbox mem is adjusted to align to 16 bytes. The allocated addr
 	 * is stored for freeing purpose */
 	struct be_dma_mem mbox_mem_alloced;
+
+	/* MCC Rings */
+	struct be_mcc_obj mcc_obj;
+	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
+	spinlock_t mcc_cq_lock;
+
+	/* MCC Async callback */
+	void (*async_cb)(void *adapter, bool link_up);
+	void *adapter_ctxt;
 };
 
 #include "be_cmds.h"
@@ -150,19 +214,6 @@
 	struct be_dma_mem cmd;
 };
 
-struct be_eq_obj {
-	struct be_queue_info q;
-	char desc[32];
-
-	/* Adaptive interrupt coalescing (AIC) info */
-	bool enable_aic;
-	u16 min_eqd;		/* in usecs */
-	u16 max_eqd;		/* in usecs */
-	u16 cur_eqd;		/* in usecs */
-
-	struct napi_struct napi;
-};
-
 struct be_tx_obj {
 	struct be_queue_info q;
 	struct be_queue_info cq;
@@ -225,8 +276,9 @@
 	u32 if_handle;		/* Used to configure filtering */
 	u32 pmac_id;		/* MAC addr handle used by BE card */
 
-	struct be_link_info link;
+	bool link_up;
 	u32 port_num;
+	bool promiscuous;
 };
 
 extern struct ethtool_ops be_ethtool_ops;
@@ -235,22 +287,6 @@
 
 #define BE_SET_NETDEV_OPS(netdev, ops)	(netdev->netdev_ops = ops)
 
-static inline u32 MODULO(u16 val, u16 limit)
-{
-	BUG_ON(limit & (limit - 1));
-	return val & (limit - 1);
-}
-
-static inline void index_adv(u16 *index, u16 val, u16 limit)
-{
-	*index = MODULO((*index + val), limit);
-}
-
-static inline void index_inc(u16 *index, u16 limit)
-{
-	*index = MODULO((*index + 1), limit);
-}
-
 #define PAGE_SHIFT_4K		12
 #define PAGE_SIZE_4K		(1 << PAGE_SHIFT_4K)
 
@@ -339,4 +375,6 @@
 	return val;
 }
 
+extern void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
+		u16 num_popped);
 #endif				/* BE_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/benet/be_hw.h linux-libre-2.6.31-gnu/drivers/net/benet/be_hw.h
--- linux-libre-2.6.30-gnu/drivers/net/benet/be_hw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/benet/be_hw.h	2009-09-09 18:13:59.000000000 -0400
@@ -55,13 +55,17 @@
 #define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK  	0x7 	/* bits 26 - 28 */
 #define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT	26
 
+/********* ISR0 Register offset **********/
+#define CEV_ISR0_OFFSET 			0xC18
+#define CEV_ISR_SIZE				4
+
 /********* Event Q door bell *************/
 #define DB_EQ_OFFSET			DB_CQ_OFFSET
 #define DB_EQ_RING_ID_MASK		0x1FF	/* bits 0 - 8 */
 /* Clear the interrupt for this eq */
 #define DB_EQ_CLR_SHIFT			(9)	/* bit 9 */
 /* Must be 1 */
-#define DB_EQ_EVNT_SHIFT			(10)	/* bit 10 */
+#define DB_EQ_EVNT_SHIFT		(10)	/* bit 10 */
 /* Number of event entries processed */
 #define DB_EQ_NUM_POPPED_SHIFT		(16)	/* bits 16 - 28 */
 /* Rearm bit */
@@ -88,6 +92,12 @@
 /* Number of rx frags posted */
 #define DB_RQ_NUM_POSTED_SHIFT		(24)	/* bits 24 - 31 */
 
+/********** MCC door bell ************/
+#define DB_MCCQ_OFFSET 			0x140
+#define DB_MCCQ_RING_ID_MASK		0x7FF	/* bits 0 - 10 */
+/* Number of entries posted */
+#define DB_MCCQ_NUM_POSTED_SHIFT	(16)	/* bits 16 - 29 */
+
 /*
  * BE descriptors: host memory data structures whose formats
  * are hardwired in BE silicon.
diff -druN linux-libre-2.6.30-gnu/drivers/net/benet/be_main.c linux-libre-2.6.31-gnu/drivers/net/benet/be_main.c
--- linux-libre-2.6.30-gnu/drivers/net/benet/be_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/benet/be_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -60,26 +60,6 @@
 	return 0;
 }
 
-static inline void *queue_head_node(struct be_queue_info *q)
-{
-	return q->dma_mem.va + q->head * q->entry_size;
-}
-
-static inline void *queue_tail_node(struct be_queue_info *q)
-{
-	return q->dma_mem.va + q->tail * q->entry_size;
-}
-
-static inline void queue_head_inc(struct be_queue_info *q)
-{
-	index_inc(&q->head, q->len);
-}
-
-static inline void queue_tail_inc(struct be_queue_info *q)
-{
-	index_inc(&q->tail, q->len);
-}
-
 static void be_intr_set(struct be_ctrl_info *ctrl, bool enable)
 {
 	u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
@@ -127,7 +107,7 @@
 	iowrite32(val, ctrl->db + DB_EQ_OFFSET);
 }
 
-static void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid,
+void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid,
 		bool arm, u16 num_popped)
 {
 	u32 val = 0;
@@ -168,6 +148,7 @@
 	struct be_port_rxf_stats *port_stats =
 			&rxf_stats->port[adapter->port_num];
 	struct net_device_stats *dev_stats = &adapter->stats.net_stats;
+	struct be_erx_stats *erx_stats = &hw_stats->erx;
 
 	dev_stats->rx_packets = port_stats->rx_total_frames;
 	dev_stats->tx_packets = port_stats->tx_unicastframes +
@@ -181,29 +162,33 @@
 	dev_stats->rx_errors = port_stats->rx_crc_errors +
 		port_stats->rx_alignment_symbol_errors +
 		port_stats->rx_in_range_errors +
-		port_stats->rx_out_range_errors + port_stats->rx_frame_too_long;
-
-	/*  packet transmit problems */
-	dev_stats->tx_errors = 0;
-
-	/*  no space in linux buffers */
-	dev_stats->rx_dropped = 0;
-
-	/* no space available in linux */
-	dev_stats->tx_dropped = 0;
+		port_stats->rx_out_range_errors +
+		port_stats->rx_frame_too_long +
+		port_stats->rx_dropped_too_small +
+		port_stats->rx_dropped_too_short +
+		port_stats->rx_dropped_header_too_small +
+		port_stats->rx_dropped_tcp_length +
+		port_stats->rx_dropped_runt +
+		port_stats->rx_tcp_checksum_errs +
+		port_stats->rx_ip_checksum_errs +
+		port_stats->rx_udp_checksum_errs;
 
-	dev_stats->multicast = port_stats->tx_multicastframes;
-	dev_stats->collisions = 0;
+	/*  no space in linux buffers: best possible approximation */
+	dev_stats->rx_dropped = erx_stats->rx_drops_no_fragments[0];
 
 	/* detailed rx errors */
 	dev_stats->rx_length_errors = port_stats->rx_in_range_errors +
-		port_stats->rx_out_range_errors + port_stats->rx_frame_too_long;
+		port_stats->rx_out_range_errors +
+		port_stats->rx_frame_too_long;
+
 	/* receive ring buffer overflow */
 	dev_stats->rx_over_errors = 0;
+
 	dev_stats->rx_crc_errors = port_stats->rx_crc_errors;
 
 	/* frame alignment errors */
 	dev_stats->rx_frame_errors = port_stats->rx_alignment_symbol_errors;
+
 	/* receiver fifo overrun */
 	/* drops_no_pbuf is no per i/f, it's per BE card */
 	dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow +
@@ -211,6 +196,16 @@
 					rxf_stats->rx_drops_no_pbuf;
 	/* receiver missed packetd */
 	dev_stats->rx_missed_errors = 0;
+
+	/*  packet transmit problems */
+	dev_stats->tx_errors = 0;
+
+	/* no space available in linux */
+	dev_stats->tx_dropped = 0;
+
+	dev_stats->multicast = port_stats->tx_multicastframes;
+	dev_stats->collisions = 0;
+
 	/* detailed tx_errors */
 	dev_stats->tx_aborted_errors = 0;
 	dev_stats->tx_carrier_errors = 0;
@@ -219,28 +214,24 @@
 	dev_stats->tx_window_errors = 0;
 }
 
-static void be_link_status_update(struct be_adapter *adapter)
+void be_link_status_update(void *ctxt, bool link_up)
 {
-	struct be_link_info *prev = &adapter->link;
-	struct be_link_info now = { 0 };
+	struct be_adapter *adapter = ctxt;
 	struct net_device *netdev = adapter->netdev;
 
-	be_cmd_link_status_query(&adapter->ctrl, &now);
-
 	/* If link came up or went down */
-	if (now.speed != prev->speed && (now.speed == PHY_LINK_SPEED_ZERO ||
-			prev->speed == PHY_LINK_SPEED_ZERO)) {
-		if (now.speed == PHY_LINK_SPEED_ZERO) {
-			netif_stop_queue(netdev);
-			netif_carrier_off(netdev);
-			printk(KERN_INFO "%s: Link down\n", netdev->name);
-		} else {
+	if (adapter->link_up != link_up) {
+		if (link_up) {
 			netif_start_queue(netdev);
 			netif_carrier_on(netdev);
 			printk(KERN_INFO "%s: Link up\n", netdev->name);
+		} else {
+			netif_stop_queue(netdev);
+			netif_carrier_off(netdev);
+			printk(KERN_INFO "%s: Link down\n", netdev->name);
 		}
+		adapter->link_up = link_up;
 	}
-	*prev = now;
 }
 
 /* Update the EQ delay n BE based on the RX frags consumed / sec */
@@ -337,13 +328,10 @@
 /* Determine number of WRB entries needed to xmit data in an skb */
 static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy)
 {
-	int cnt = 0;
-	while (skb) {
-		if (skb->len > skb->data_len)
-			cnt++;
-		cnt += skb_shinfo(skb)->nr_frags;
-		skb = skb_shinfo(skb)->frag_list;
-	}
+	int cnt = (skb->len > skb->data_len);
+
+	cnt += skb_shinfo(skb)->nr_frags;
+
 	/* to account for hdr wrb */
 	cnt++;
 	if (cnt & 1) {
@@ -409,31 +397,28 @@
 	hdr = queue_head_node(txq);
 	queue_head_inc(txq);
 
-	while (skb) {
-		if (skb->len > skb->data_len) {
-			int len = skb->len - skb->data_len;
-			busaddr = pci_map_single(pdev, skb->data, len,
-					PCI_DMA_TODEVICE);
-			wrb = queue_head_node(txq);
-			wrb_fill(wrb, busaddr, len);
-			be_dws_cpu_to_le(wrb, sizeof(*wrb));
-			queue_head_inc(txq);
-			copied += len;
-		}
+	if (skb->len > skb->data_len) {
+		int len = skb->len - skb->data_len;
+		busaddr = pci_map_single(pdev, skb->data, len,
+					 PCI_DMA_TODEVICE);
+		wrb = queue_head_node(txq);
+		wrb_fill(wrb, busaddr, len);
+		be_dws_cpu_to_le(wrb, sizeof(*wrb));
+		queue_head_inc(txq);
+		copied += len;
+	}
 
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			struct skb_frag_struct *frag =
-				&skb_shinfo(skb)->frags[i];
-			busaddr = pci_map_page(pdev, frag->page,
-					frag->page_offset,
-					frag->size, PCI_DMA_TODEVICE);
-			wrb = queue_head_node(txq);
-			wrb_fill(wrb, busaddr, frag->size);
-			be_dws_cpu_to_le(wrb, sizeof(*wrb));
-			queue_head_inc(txq);
-			copied += frag->size;
-		}
-		skb = skb_shinfo(skb)->frag_list;
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		struct skb_frag_struct *frag =
+			&skb_shinfo(skb)->frags[i];
+		busaddr = pci_map_page(pdev, frag->page,
+				       frag->page_offset,
+				       frag->size, PCI_DMA_TODEVICE);
+		wrb = queue_head_node(txq);
+		wrb_fill(wrb, busaddr, frag->size);
+		be_dws_cpu_to_le(wrb, sizeof(*wrb));
+		queue_head_inc(txq);
+		copied += frag->size;
 	}
 
 	if (dummy_wrb) {
@@ -478,8 +463,6 @@
 
 	be_txq_notify(&adapter->ctrl, txq->id, wrb_cnt);
 
-	netdev->trans_start = jiffies;
-
 	be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
 	return NETDEV_TX_OK;
 }
@@ -562,47 +545,32 @@
 	be_vid_config(netdev);
 }
 
-static void be_set_multicast_filter(struct net_device *netdev)
+static void be_set_multicast_list(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct dev_mc_list *mc_ptr;
-	u8 mac_addr[32][ETH_ALEN];
-	int i = 0;
+	struct be_ctrl_info *ctrl = &adapter->ctrl;
 
-	if (netdev->flags & IFF_ALLMULTI) {
-		/* set BE in Multicast promiscuous */
-		be_cmd_mcast_mac_set(&adapter->ctrl,
-					adapter->if_handle, NULL, 0, true);
-		return;
+	if (netdev->flags & IFF_PROMISC) {
+		be_cmd_promiscuous_config(ctrl, adapter->port_num, 1);
+		adapter->promiscuous = true;
+		goto done;
 	}
 
-	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
-		memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN);
-		if (++i >= 32) {
-			be_cmd_mcast_mac_set(&adapter->ctrl,
-				adapter->if_handle, &mac_addr[0][0], i, false);
-			i = 0;
-		}
-
+	/* BE was previously in promiscous mode; disable it */
+	if (adapter->promiscuous) {
+		adapter->promiscuous = false;
+		be_cmd_promiscuous_config(ctrl, adapter->port_num, 0);
 	}
 
-	if (i) {
-		/* reset the promiscuous mode also. */
-		be_cmd_mcast_mac_set(&adapter->ctrl,
-			adapter->if_handle, &mac_addr[0][0], i, false);
+	if (netdev->flags & IFF_ALLMULTI) {
+		be_cmd_multicast_set(ctrl, adapter->if_handle, NULL, 0);
+		goto done;
 	}
-}
-
-static void be_set_multicast_list(struct net_device *netdev)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
 
-	if (netdev->flags & IFF_PROMISC) {
-		be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 1);
-	} else {
-		be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 0);
-		be_set_multicast_filter(netdev);
-	}
+	be_cmd_multicast_set(ctrl, adapter->if_handle, netdev->mc_list,
+		netdev->mc_count);
+done:
+	return;
 }
 
 static void be_rx_rate_update(struct be_adapter *adapter)
@@ -637,6 +605,22 @@
 	stats->be_rx_bytes += pktsize;
 }
 
+static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
+{
+	u8 l4_cksm, ip_version, ipcksm, tcpf = 0, udpf = 0, ipv6_chk;
+
+	l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp);
+	ipcksm = AMAP_GET_BITS(struct amap_eth_rx_compl, ipcksm, rxcp);
+	ip_version = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp);
+	if (ip_version) {
+		tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
+		udpf = AMAP_GET_BITS(struct amap_eth_rx_compl, udpf, rxcp);
+	}
+	ipv6_chk = (ip_version && (tcpf || udpf));
+
+	return ((l4_cksm && ipv6_chk && ipcksm) && cso) ? false : true;
+}
+
 static struct be_rx_page_info *
 get_rx_page_info(struct be_adapter *adapter, u16 frag_idx)
 {
@@ -682,8 +666,8 @@
 {
 	struct be_queue_info *rxq = &adapter->rx_obj.q;
 	struct be_rx_page_info *page_info;
-	u16 rxq_idx, i, num_rcvd;
-	u32 pktsize, hdr_len, curr_frag_len;
+	u16 rxq_idx, i, num_rcvd, j;
+	u32 pktsize, hdr_len, curr_frag_len, size;
 	u8 *start;
 
 	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
@@ -720,28 +704,40 @@
 
 	if (pktsize <= rx_frag_size) {
 		BUG_ON(num_rcvd != 1);
-		return;
+		goto done;
 	}
 
 	/* More frags present for this completion */
-	pktsize -= curr_frag_len; /* account for above copied frag */
-	for (i = 1; i < num_rcvd; i++) {
+	size = pktsize;
+	for (i = 1, j = 0; i < num_rcvd; i++) {
+		size -= curr_frag_len;
 		index_inc(&rxq_idx, rxq->len);
 		page_info = get_rx_page_info(adapter, rxq_idx);
 
-		curr_frag_len = min(pktsize, rx_frag_size);
+		curr_frag_len = min(size, rx_frag_size);
 
-		skb_shinfo(skb)->frags[i].page = page_info->page;
-		skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset;
-		skb_shinfo(skb)->frags[i].size = curr_frag_len;
+		/* Coalesce all frags from the same physical page in one slot */
+		if (page_info->page_offset == 0) {
+			/* Fresh page */
+			j++;
+			skb_shinfo(skb)->frags[j].page = page_info->page;
+			skb_shinfo(skb)->frags[j].page_offset =
+							page_info->page_offset;
+			skb_shinfo(skb)->frags[j].size = 0;
+			skb_shinfo(skb)->nr_frags++;
+		} else {
+			put_page(page_info->page);
+		}
+
+		skb_shinfo(skb)->frags[j].size += curr_frag_len;
 		skb->len += curr_frag_len;
 		skb->data_len += curr_frag_len;
-		skb_shinfo(skb)->nr_frags++;
-		pktsize -= curr_frag_len;
 
 		memset(page_info, 0, sizeof(*page_info));
 	}
+	BUG_ON(j > MAX_SKB_FRAGS);
 
+done:
 	be_rx_stats_update(adapter, pktsize, num_rcvd);
 	return;
 }
@@ -752,9 +748,7 @@
 {
 	struct sk_buff *skb;
 	u32 vtp, vid;
-	int l4_cksm;
 
-	l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp);
 	vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
 
 	skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN);
@@ -769,10 +763,10 @@
 
 	skb_fill_rx_data(adapter, skb, rxcp);
 
-	if (l4_cksm && adapter->rx_csum)
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	else
+	if (do_pkt_csum(rxcp, adapter->rx_csum))
 		skb->ip_summed = CHECKSUM_NONE;
+	else
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 	skb->truesize = skb->len + sizeof(struct sk_buff);
 	skb->protocol = eth_type_trans(skb, adapter->netdev);
@@ -803,7 +797,7 @@
 	struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME];
 	struct be_queue_info *rxq = &adapter->rx_obj.q;
 	u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
-	u16 i, rxq_idx = 0, vid;
+	u16 i, rxq_idx = 0, vid, j;
 
 	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
 	pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
@@ -811,20 +805,28 @@
 	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
 
 	remaining = pkt_size;
-	for (i = 0; i < num_rcvd; i++) {
+	for (i = 0, j = -1; i < num_rcvd; i++) {
 		page_info = get_rx_page_info(adapter, rxq_idx);
 
 		curr_frag_len = min(remaining, rx_frag_size);
 
-		rx_frags[i].page = page_info->page;
-		rx_frags[i].page_offset = page_info->page_offset;
-		rx_frags[i].size = curr_frag_len;
-		remaining -= curr_frag_len;
+		/* Coalesce all frags from the same physical page in one slot */
+		if (i == 0 || page_info->page_offset == 0) {
+			/* First frag or Fresh page */
+			j++;
+			rx_frags[j].page = page_info->page;
+			rx_frags[j].page_offset = page_info->page_offset;
+			rx_frags[j].size = 0;
+		} else {
+			put_page(page_info->page);
+		}
+		rx_frags[j].size += curr_frag_len;
 
+		remaining -= curr_frag_len;
 		index_inc(&rxq_idx, rxq->len);
-
 		memset(page_info, 0, sizeof(*page_info));
 	}
+	BUG_ON(j > MAX_SKB_FRAGS);
 
 	if (likely(!vlanf)) {
 		lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size,
@@ -854,12 +856,19 @@
 
 	be_dws_le_to_cpu(rxcp, sizeof(*rxcp));
 
-	rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0;
-
 	queue_tail_inc(&adapter->rx_obj.cq);
 	return rxcp;
 }
 
+/* To reset the valid bit, we need to reset the whole word as
+ * when walking the queue the valid entries are little-endian
+ * and invalid entries are host endian
+ */
+static inline void be_rx_compl_reset(struct be_eth_rx_compl *rxcp)
+{
+	rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0;
+}
+
 static inline struct page *be_alloc_pages(u32 size)
 {
 	gfp_t alloc_flags = GFP_ATOMIC;
@@ -931,10 +940,8 @@
 	return;
 }
 
-static struct be_eth_tx_compl *
-be_tx_compl_get(struct be_adapter *adapter)
+static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)
 {
-	struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
 	struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq);
 
 	if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0)
@@ -991,6 +998,7 @@
 	/* First cleanup pending rx completions */
 	while ((rxcp = be_rx_compl_get(adapter)) != NULL) {
 		be_rx_compl_discard(adapter, rxcp);
+		be_rx_compl_reset(rxcp);
 		be_cq_notify(&adapter->ctrl, rx_cq->id, true, 1);
 	}
 
@@ -1021,13 +1029,71 @@
 	}
 }
 
+static void be_mcc_queues_destroy(struct be_adapter *adapter)
+{
+	struct be_queue_info *q;
+	struct be_ctrl_info *ctrl = &adapter->ctrl;
+
+	q = &ctrl->mcc_obj.q;
+	if (q->created)
+		be_cmd_q_destroy(ctrl, q, QTYPE_MCCQ);
+	be_queue_free(adapter, q);
+
+	q = &ctrl->mcc_obj.cq;
+	if (q->created)
+		be_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+	be_queue_free(adapter, q);
+}
+
+/* Must be called only after TX qs are created as MCC shares TX EQ */
+static int be_mcc_queues_create(struct be_adapter *adapter)
+{
+	struct be_queue_info *q, *cq;
+	struct be_ctrl_info *ctrl = &adapter->ctrl;
+
+	/* Alloc MCC compl queue */
+	cq = &ctrl->mcc_obj.cq;
+	if (be_queue_alloc(adapter, cq, MCC_CQ_LEN,
+			sizeof(struct be_mcc_cq_entry)))
+		goto err;
+
+	/* Ask BE to create MCC compl queue; share TX's eq */
+	if (be_cmd_cq_create(ctrl, cq, &adapter->tx_eq.q, false, true, 0))
+		goto mcc_cq_free;
+
+	/* Alloc MCC queue */
+	q = &ctrl->mcc_obj.q;
+	if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb)))
+		goto mcc_cq_destroy;
+
+	/* Ask BE to create MCC queue */
+	if (be_cmd_mccq_create(ctrl, q, cq))
+		goto mcc_q_free;
+
+	return 0;
+
+mcc_q_free:
+	be_queue_free(adapter, q);
+mcc_cq_destroy:
+	be_cmd_q_destroy(ctrl, cq, QTYPE_CQ);
+mcc_cq_free:
+	be_queue_free(adapter, cq);
+err:
+	return -1;
+}
+
 static void be_tx_queues_destroy(struct be_adapter *adapter)
 {
 	struct be_queue_info *q;
 
 	q = &adapter->tx_obj.q;
-	if (q->created)
+	if (q->created) {
 		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_TXQ);
+
+		/* No more tx completions can be rcvd now; clean up if there
+		 * are any pending completions or pending tx requests */
+		be_tx_q_clean(adapter);
+	}
 	be_queue_free(adapter, q);
 
 	q = &adapter->tx_obj.cq;
@@ -1035,10 +1101,6 @@
 		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ);
 	be_queue_free(adapter, q);
 
-	/* No more tx completions can be rcvd now; clean up if there are
-	 * any pending completions or pending tx requests */
-	be_tx_q_clean(adapter);
-
 	q = &adapter->tx_eq.q;
 	if (q->created)
 		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ);
@@ -1212,15 +1274,17 @@
 {
 	struct be_adapter *adapter = dev;
 	struct be_ctrl_info *ctrl = &adapter->ctrl;
-	int rx, tx;
+        int isr;
 
-	tx = event_handle(ctrl, &adapter->tx_eq);
-	rx = event_handle(ctrl, &adapter->rx_eq);
+	isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
+                      ctrl->pci_func * CEV_ISR_SIZE);
+	if (!isr)
+                return IRQ_NONE;
 
-	if (rx || tx)
-		return IRQ_HANDLED;
-	else
-		return IRQ_NONE;
+        event_handle(ctrl, &adapter->tx_eq);
+        event_handle(ctrl, &adapter->rx_eq);
+
+        return IRQ_HANDLED;
 }
 
 static irqreturn_t be_msix_rx(int irq, void *dev)
@@ -1232,7 +1296,7 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t be_msix_tx(int irq, void *dev)
+static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
 {
 	struct be_adapter *adapter = dev;
 
@@ -1272,6 +1336,8 @@
 			be_rx_compl_process_lro(adapter, rxcp);
 		else
 			be_rx_compl_process(adapter, rxcp);
+
+		be_rx_compl_reset(rxcp);
 	}
 
 	lro_flush_all(&adapter->rx_obj.lro_mgr);
@@ -1291,40 +1357,51 @@
 	return work_done;
 }
 
-/* For TX we don't honour budget; consume everything */
-int be_poll_tx(struct napi_struct *napi, int budget)
+void be_process_tx(struct be_adapter *adapter)
 {
-	struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
-	struct be_adapter *adapter =
-		container_of(tx_eq, struct be_adapter, tx_eq);
-	struct be_tx_obj *tx_obj = &adapter->tx_obj;
-	struct be_queue_info *tx_cq = &tx_obj->cq;
-	struct be_queue_info *txq = &tx_obj->q;
+	struct be_queue_info *txq = &adapter->tx_obj.q;
+	struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
 	struct be_eth_tx_compl *txcp;
 	u32 num_cmpl = 0;
 	u16 end_idx;
 
-	while ((txcp = be_tx_compl_get(adapter))) {
+	while ((txcp = be_tx_compl_get(tx_cq))) {
 		end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
 					wrb_index, txcp);
 		be_tx_compl_process(adapter, end_idx);
 		num_cmpl++;
 	}
 
-	/* As Tx wrbs have been freed up, wake up netdev queue if
-	 * it was stopped due to lack of tx wrbs.
-	 */
-	if (netif_queue_stopped(adapter->netdev) &&
+	if (num_cmpl) {
+		be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl);
+
+		/* As Tx wrbs have been freed up, wake up netdev queue if
+		 * it was stopped due to lack of tx wrbs.
+		 */
+		if (netif_queue_stopped(adapter->netdev) &&
 			atomic_read(&txq->used) < txq->len / 2) {
-		netif_wake_queue(adapter->netdev);
+			netif_wake_queue(adapter->netdev);
+		}
+
+		drvr_stats(adapter)->be_tx_events++;
+		drvr_stats(adapter)->be_tx_compl += num_cmpl;
 	}
+}
+
+/* As TX and MCC share the same EQ check for both TX and MCC completions.
+ * For TX/MCC we don't honour budget; consume everything
+ */
+static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
+{
+	struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
+	struct be_adapter *adapter =
+		container_of(tx_eq, struct be_adapter, tx_eq);
 
 	napi_complete(napi);
 
-	be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl);
+	be_process_tx(adapter);
 
-	drvr_stats(adapter)->be_tx_events++;
-	drvr_stats(adapter)->be_tx_compl += num_cmpl;
+	be_process_mcc(&adapter->ctrl);
 
 	return 1;
 }
@@ -1335,9 +1412,6 @@
 		container_of(work, struct be_adapter, work.work);
 	int status;
 
-	/* Check link */
-	be_link_status_update(adapter);
-
 	/* Get Stats */
 	status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd);
 	if (!status)
@@ -1386,7 +1460,7 @@
 
 	sprintf(tx_eq->desc, "%s-tx", netdev->name);
 	vec = be_msix_vec_get(adapter, tx_eq->q.id);
-	status = request_irq(vec, be_msix_tx, 0, tx_eq->desc, adapter);
+	status = request_irq(vec, be_msix_tx_mcc, 0, tx_eq->desc, adapter);
 	if (status)
 		goto err;
 
@@ -1462,6 +1536,39 @@
 	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	struct be_eq_obj *rx_eq = &adapter->rx_eq;
 	struct be_eq_obj *tx_eq = &adapter->tx_eq;
+	bool link_up;
+	int status;
+
+	/* First time posting */
+	be_post_rx_frags(adapter);
+
+	napi_enable(&rx_eq->napi);
+	napi_enable(&tx_eq->napi);
+
+	be_irq_register(adapter);
+
+	be_intr_set(ctrl, true);
+
+	/* The evt queues are created in unarmed state; arm them */
+	be_eq_notify(ctrl, rx_eq->q.id, true, false, 0);
+	be_eq_notify(ctrl, tx_eq->q.id, true, false, 0);
+
+	/* Rx compl queue may be in unarmed state; rearm it */
+	be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0);
+
+	status = be_cmd_link_status_query(ctrl, &link_up);
+	if (status)
+		return status;
+	be_link_status_update(adapter, link_up);
+
+	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
+	return 0;
+}
+
+static int be_setup(struct be_adapter *adapter)
+{
+	struct be_ctrl_info *ctrl = &adapter->ctrl;
+	struct net_device *netdev = adapter->netdev;
 	u32 if_flags;
 	int status;
 
@@ -1488,29 +1595,14 @@
 	if (status != 0)
 		goto tx_qs_destroy;
 
-	/* First time posting */
-	be_post_rx_frags(adapter);
-
-	napi_enable(&rx_eq->napi);
-	napi_enable(&tx_eq->napi);
-
-	be_irq_register(adapter);
-
-	be_intr_set(ctrl, true);
-
-	/* The evt queues are created in the unarmed state; arm them */
-	be_eq_notify(ctrl, rx_eq->q.id, true, false, 0);
-	be_eq_notify(ctrl, tx_eq->q.id, true, false, 0);
-
-	/* The compl queues are created in the unarmed state; arm them */
-	be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0);
-	be_cq_notify(ctrl, adapter->tx_obj.cq.id, true, 0);
-
-	be_link_status_update(adapter);
+	status = be_mcc_queues_create(adapter);
+	if (status != 0)
+		goto rx_qs_destroy;
 
-	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
 	return 0;
 
+rx_qs_destroy:
+	be_rx_queues_destroy(adapter);
 tx_qs_destroy:
 	be_tx_queues_destroy(adapter);
 if_destroy:
@@ -1519,6 +1611,19 @@
 	return status;
 }
 
+static int be_clear(struct be_adapter *adapter)
+{
+	struct be_ctrl_info *ctrl = &adapter->ctrl;
+
+	be_rx_queues_destroy(adapter);
+	be_tx_queues_destroy(adapter);
+
+	be_cmd_if_destroy(ctrl, adapter->if_handle);
+
+	be_mcc_queues_destroy(adapter);
+	return 0;
+}
+
 static int be_close(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
@@ -1527,11 +1632,11 @@
 	struct be_eq_obj *tx_eq = &adapter->tx_eq;
 	int vec;
 
-	cancel_delayed_work(&adapter->work);
+	cancel_delayed_work_sync(&adapter->work);
 
 	netif_stop_queue(netdev);
 	netif_carrier_off(netdev);
-	adapter->link.speed = PHY_LINK_SPEED_ZERO;
+	adapter->link_up = false;
 
 	be_intr_set(ctrl, false);
 
@@ -1548,10 +1653,6 @@
 	napi_disable(&rx_eq->napi);
 	napi_disable(&tx_eq->napi);
 
-	be_rx_queues_destroy(adapter);
-	be_tx_queues_destroy(adapter);
-
-	be_cmd_if_destroy(ctrl, adapter->if_handle);
 	return 0;
 }
 
@@ -1626,10 +1727,12 @@
 
 	netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
 		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM |
-		NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+		NETIF_F_IPV6_CSUM;
 
 	netdev->flags |= IFF_MULTICAST;
 
+	adapter->rx_csum = true;
+
 	BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
 
 	SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
@@ -1638,7 +1741,7 @@
 
 	netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx,
 		BE_NAPI_WEIGHT);
-	netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx,
+	netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
 		BE_NAPI_WEIGHT);
 
 	netif_carrier_off(netdev);
@@ -1720,7 +1823,12 @@
 	mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
 	mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
 	memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
-	spin_lock_init(&ctrl->cmd_lock);
+	spin_lock_init(&ctrl->mbox_lock);
+	spin_lock_init(&ctrl->mcc_lock);
+	spin_lock_init(&ctrl->mcc_cq_lock);
+
+	ctrl->async_cb = be_link_status_update;
+	ctrl->adapter_ctxt = adapter;
 
 	val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
 	ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) &
@@ -1758,6 +1866,8 @@
 
 	unregister_netdev(adapter->netdev);
 
+	be_clear(adapter);
+
 	be_stats_cleanup(adapter);
 
 	be_ctrl_cleanup(adapter);
@@ -1855,13 +1965,18 @@
 	be_netdev_init(netdev);
 	SET_NETDEV_DEV(netdev, &adapter->pdev->dev);
 
+	status = be_setup(adapter);
+	if (status)
+		goto stats_clean;
 	status = register_netdev(netdev);
 	if (status != 0)
-		goto stats_clean;
+		goto unsetup;
 
 	dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
 	return 0;
 
+unsetup:
+	be_clear(adapter);
 stats_clean:
 	be_stats_cleanup(adapter);
 ctrl_clean:
@@ -1886,6 +2001,7 @@
 	if (netif_running(netdev)) {
 		rtnl_lock();
 		be_close(netdev);
+		be_clear(adapter);
 		rtnl_unlock();
 	}
 
@@ -1912,6 +2028,7 @@
 
 	if (netif_running(netdev)) {
 		rtnl_lock();
+		be_setup(adapter);
 		be_open(netdev);
 		rtnl_unlock();
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/net/bfin_mac.c linux-libre-2.6.31-gnu/drivers/net/bfin_mac.c
--- linux-libre-2.6.30-gnu/drivers/net/bfin_mac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bfin_mac.c	2009-09-09 18:13:59.000000000 -0400
@@ -194,13 +194,13 @@
 		struct dma_descriptor *b = &(r->desc_b);
 
 		/* allocate a new skb for next time receive */
-		new_skb = dev_alloc_skb(PKT_BUF_SZ + 2);
+		new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
 		if (!new_skb) {
 			printk(KERN_NOTICE DRV_NAME
 			       ": init: low on mem - packet dropped\n");
 			goto init_error;
 		}
-		skb_reserve(new_skb, 2);
+		skb_reserve(new_skb, NET_IP_ALIGN);
 		r->skb = new_skb;
 
 		/*
@@ -566,9 +566,9 @@
 	 */
 	if (current_tx_ptr->next->next == tx_list_head) {
 		while (tx_list_head->status.status_word == 0) {
-			mdelay(1);
+			udelay(10);
 			if (tx_list_head->status.status_word != 0
-			    || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) {
+			    || !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) {
 				goto adjust_head;
 			}
 			if (timeout_cnt-- < 0) {
@@ -606,93 +606,41 @@
 				struct net_device *dev)
 {
 	u16 *data;
-
+	u32 data_align = (unsigned long)(skb->data) & 0x3;
 	current_tx_ptr->skb = skb;
 
-	if (ANOMALY_05000285) {
-		/*
-		 * TXDWA feature is not avaible to older revision < 0.3 silicon
-		 * of BF537
-		 *
-		 * Only if data buffer is ODD WORD alignment, we do not
-		 * need to memcpy
-		 */
-		u32 data_align = (u32)(skb->data) & 0x3;
-		if (data_align == 0x2) {
-			/* move skb->data to current_tx_ptr payload */
-			data = (u16 *)(skb->data) - 1;
-			*data = (u16)(skb->len);
-			current_tx_ptr->desc_a.start_addr = (u32)data;
-			/* this is important! */
-			blackfin_dcache_flush_range((u32)data,
-					(u32)((u8 *)data + skb->len + 4));
-		} else {
-			*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
-			memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
-				skb->len);
-			current_tx_ptr->desc_a.start_addr =
-				(u32)current_tx_ptr->packet;
-			if (current_tx_ptr->status.status_word != 0)
-				current_tx_ptr->status.status_word = 0;
-			blackfin_dcache_flush_range(
-				(u32)current_tx_ptr->packet,
-				(u32)(current_tx_ptr->packet + skb->len + 2));
-		}
+	if (data_align == 0x2) {
+		/* move skb->data to current_tx_ptr payload */
+		data = (u16 *)(skb->data) - 1;
+				*data = (u16)(skb->len);
+		current_tx_ptr->desc_a.start_addr = (u32)data;
+		/* this is important! */
+		blackfin_dcache_flush_range((u32)data,
+				(u32)((u8 *)data + skb->len + 4));
 	} else {
-		/*
-		 * TXDWA feature is avaible to revision < 0.3 silicon of
-		 * BF537 and always avaible to BF52x
-		 */
-		u32 data_align = (u32)(skb->data) & 0x3;
-		if (data_align == 0x0) {
-			u16 sysctl = bfin_read_EMAC_SYSCTL();
-			sysctl |= TXDWA;
-			bfin_write_EMAC_SYSCTL(sysctl);
-
-			/* move skb->data to current_tx_ptr payload */
-			data = (u16 *)(skb->data) - 2;
-			*data = (u16)(skb->len);
-			current_tx_ptr->desc_a.start_addr = (u32)data;
-			/* this is important! */
-			blackfin_dcache_flush_range(
-					(u32)data,
-					(u32)((u8 *)data + skb->len + 4));
-		} else if (data_align == 0x2) {
-			u16 sysctl = bfin_read_EMAC_SYSCTL();
-			sysctl &= ~TXDWA;
-			bfin_write_EMAC_SYSCTL(sysctl);
-
-			/* move skb->data to current_tx_ptr payload */
-			data = (u16 *)(skb->data) - 1;
-			*data = (u16)(skb->len);
-			current_tx_ptr->desc_a.start_addr = (u32)data;
-			/* this is important! */
-			blackfin_dcache_flush_range(
-					(u32)data,
-					(u32)((u8 *)data + skb->len + 4));
-		} else {
-			u16 sysctl = bfin_read_EMAC_SYSCTL();
-			sysctl &= ~TXDWA;
-			bfin_write_EMAC_SYSCTL(sysctl);
-
-			*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
-			memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
-				skb->len);
-			current_tx_ptr->desc_a.start_addr =
-				(u32)current_tx_ptr->packet;
-			if (current_tx_ptr->status.status_word != 0)
-				current_tx_ptr->status.status_word = 0;
-			blackfin_dcache_flush_range(
-				(u32)current_tx_ptr->packet,
-				(u32)(current_tx_ptr->packet + skb->len + 2));
-		}
+		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
+		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
+			skb->len);
+		current_tx_ptr->desc_a.start_addr =
+			(u32)current_tx_ptr->packet;
+		if (current_tx_ptr->status.status_word != 0)
+			current_tx_ptr->status.status_word = 0;
+		blackfin_dcache_flush_range(
+			(u32)current_tx_ptr->packet,
+			(u32)(current_tx_ptr->packet + skb->len + 2));
 	}
 
+	/* make sure the internal data buffers in the core are drained
+	 * so that the DMA descriptors are completely written when the
+	 * DMA engine goes to fetch them below
+	 */
+	SSYNC();
+
 	/* enable this packet's dma */
 	current_tx_ptr->desc_a.config |= DMAEN;
 
 	/* tx dma is running, just return */
-	if (bfin_read_DMA2_IRQ_STATUS() & 0x08)
+	if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
 		goto out;
 
 	/* tx dma is not running */
@@ -718,7 +666,7 @@
 
 	/* allocate a new skb for next time receive */
 	skb = current_rx_ptr->skb;
-	new_skb = dev_alloc_skb(PKT_BUF_SZ + 2);
+	new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
 	if (!new_skb) {
 		printk(KERN_NOTICE DRV_NAME
 		       ": rx: low on mem - packet dropped\n");
@@ -726,7 +674,7 @@
 		goto out;
 	}
 	/* reserve 2 bytes for RXDWA padding */
-	skb_reserve(new_skb, 2);
+	skb_reserve(new_skb, NET_IP_ALIGN);
 	current_rx_ptr->skb = new_skb;
 	current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
 
@@ -1022,7 +970,8 @@
 {
 	struct net_device *ndev;
 	struct bfin_mac_local *lp;
-	int rc, i;
+	struct platform_device *pd;
+	int rc;
 
 	ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
 	if (!ndev) {
@@ -1047,13 +996,6 @@
 		goto out_err_probe_mac;
 	}
 
-	/* set the GPIO pins to Ethernet mode */
-	rc = peripheral_request_list(pin_req, DRV_NAME);
-	if (rc) {
-		dev_err(&pdev->dev, "Requesting peripherals failed!\n");
-		rc = -EFAULT;
-		goto out_err_setup_pin_mux;
-	}
 
 	/*
 	 * Is it valid? (Did bootloader initialize it?)
@@ -1069,26 +1011,14 @@
 
 	setup_mac_addr(ndev->dev_addr);
 
-	/* MDIO bus initial */
-	lp->mii_bus = mdiobus_alloc();
-	if (lp->mii_bus == NULL)
-		goto out_err_mdiobus_alloc;
-
-	lp->mii_bus->priv = ndev;
-	lp->mii_bus->read = bfin_mdiobus_read;
-	lp->mii_bus->write = bfin_mdiobus_write;
-	lp->mii_bus->reset = bfin_mdiobus_reset;
-	lp->mii_bus->name = "bfin_mac_mdio";
-	snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "0");
-	lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-	for (i = 0; i < PHY_MAX_ADDR; ++i)
-		lp->mii_bus->irq[i] = PHY_POLL;
-
-	rc = mdiobus_register(lp->mii_bus);
-	if (rc) {
-		dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
-		goto out_err_mdiobus_register;
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n");
+		rc = -ENODEV;
+		goto out_err_probe_mac;
 	}
+	pd = pdev->dev.platform_data;
+	lp->mii_bus = platform_get_drvdata(pd);
+	lp->mii_bus->priv = ndev;
 
 	rc = mii_probe(ndev);
 	if (rc) {
@@ -1107,7 +1037,7 @@
 	/* now, enable interrupts */
 	/* register irq handler */
 	rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
-			IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev);
+			IRQF_DISABLED, "EMAC_RX", ndev);
 	if (rc) {
 		dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
 		rc = -EBUSY;
@@ -1130,11 +1060,8 @@
 out_err_request_irq:
 out_err_mii_probe:
 	mdiobus_unregister(lp->mii_bus);
-out_err_mdiobus_register:
 	mdiobus_free(lp->mii_bus);
-out_err_mdiobus_alloc:
 	peripheral_free_list(pin_req);
-out_err_setup_pin_mux:
 out_err_probe_mac:
 	platform_set_drvdata(pdev, NULL);
 	free_netdev(ndev);
@@ -1149,8 +1076,7 @@
 
 	platform_set_drvdata(pdev, NULL);
 
-	mdiobus_unregister(lp->mii_bus);
-	mdiobus_free(lp->mii_bus);
+	lp->mii_bus->priv = NULL;
 
 	unregister_netdev(ndev);
 
@@ -1188,6 +1114,74 @@
 #define bfin_mac_resume NULL
 #endif	/* CONFIG_PM */
 
+static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
+{
+	struct mii_bus *miibus;
+	int rc, i;
+
+	/*
+	 * We are setting up a network card,
+	 * so set the GPIO pins to Ethernet mode
+	 */
+	rc = peripheral_request_list(pin_req, DRV_NAME);
+	if (rc) {
+		dev_err(&pdev->dev, "Requesting peripherals failed!\n");
+		return rc;
+	}
+
+	rc = -ENOMEM;
+	miibus = mdiobus_alloc();
+	if (miibus == NULL)
+		goto out_err_alloc;
+	miibus->read = bfin_mdiobus_read;
+	miibus->write = bfin_mdiobus_write;
+	miibus->reset = bfin_mdiobus_reset;
+
+	miibus->parent = &pdev->dev;
+	miibus->name = "bfin_mii_bus";
+	snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
+	miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	if (miibus->irq == NULL)
+		goto out_err_alloc;
+	for (i = 0; i < PHY_MAX_ADDR; ++i)
+		miibus->irq[i] = PHY_POLL;
+
+	rc = mdiobus_register(miibus);
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
+		goto out_err_mdiobus_register;
+	}
+
+	platform_set_drvdata(pdev, miibus);
+	return 0;
+
+out_err_mdiobus_register:
+	mdiobus_free(miibus);
+out_err_alloc:
+	peripheral_free_list(pin_req);
+
+	return rc;
+}
+
+static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
+{
+	struct mii_bus *miibus = platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, NULL);
+	mdiobus_unregister(miibus);
+	mdiobus_free(miibus);
+	peripheral_free_list(pin_req);
+	return 0;
+}
+
+static struct platform_driver bfin_mii_bus_driver = {
+	.probe = bfin_mii_bus_probe,
+	.remove = __devexit_p(bfin_mii_bus_remove),
+	.driver = {
+		.name = "bfin_mii_bus",
+		.owner	= THIS_MODULE,
+	},
+};
+
 static struct platform_driver bfin_mac_driver = {
 	.probe = bfin_mac_probe,
 	.remove = __devexit_p(bfin_mac_remove),
@@ -1201,7 +1195,11 @@
 
 static int __init bfin_mac_init(void)
 {
-	return platform_driver_register(&bfin_mac_driver);
+	int ret;
+	ret = platform_driver_register(&bfin_mii_bus_driver);
+	if (!ret)
+		return platform_driver_register(&bfin_mac_driver);
+	return -ENODEV;
 }
 
 module_init(bfin_mac_init);
@@ -1209,6 +1207,7 @@
 static void __exit bfin_mac_cleanup(void)
 {
 	platform_driver_unregister(&bfin_mac_driver);
+	platform_driver_unregister(&bfin_mii_bus_driver);
 }
 
 module_exit(bfin_mac_cleanup);
diff -druN linux-libre-2.6.30-gnu/drivers/net/bmac.c linux-libre-2.6.31-gnu/drivers/net/bmac.c
--- linux-libre-2.6.30-gnu/drivers/net/bmac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -428,10 +428,11 @@
 	printk(KERN_DEBUG "phy registers:");
 	for (addr = 0; addr < 32; ++addr) {
 		if ((addr & 7) == 0)
-			printk("\n" KERN_DEBUG);
-		printk(" %.4x", bmac_mif_read(dev, addr));
+			printk(KERN_DEBUG);
+		printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr));
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
+
 	if (bp->is_bmac_plus) {
 		unsigned int capable, ctrl;
 
@@ -1247,6 +1248,16 @@
 	.get_link		= ethtool_op_get_link,
 };
 
+static const struct net_device_ops bmac_netdev_ops = {
+	.ndo_open		= bmac_open,
+	.ndo_stop		= bmac_close,
+	.ndo_start_xmit		= bmac_output,
+	.ndo_set_multicast_list	= bmac_set_multicast,
+	.ndo_set_mac_address	= bmac_set_address,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
 static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
 {
 	int j, rev, ret;
@@ -1308,12 +1319,8 @@
 	bmac_enable_and_reset_chip(dev);
 	bmwrite(dev, INTDISABLE, DisableAll);
 
-	dev->open = bmac_open;
-	dev->stop = bmac_close;
+	dev->netdev_ops = &bmac_netdev_ops;
 	dev->ethtool_ops = &bmac_ethtool_ops;
-	dev->hard_start_xmit = bmac_output;
-	dev->set_multicast_list = bmac_set_multicast;
-	dev->set_mac_address = bmac_set_address;
 
 	bmac_get_station_address(dev, addr);
 	if (bmac_verify_checksum(dev) != 0)
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2.c linux-libre-2.6.31-gnu/drivers/net/bnx2.c
--- linux-libre-2.6.30-gnu/drivers/net/bnx2.c	2012-03-22 19:14:29.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2.c	2012-03-22 20:10:38.000000000 -0400
@@ -48,7 +48,12 @@
 #include <linux/cache.h>
 #include <linux/firmware.h>
 #include <linux/log2.h>
+#include <linux/list.h>
 
+#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
+#define BCM_CNIC 1
+#include "cnic_if.h"
+#endif
 #include "bnx2.h"
 #include "bnx2_fw.h"
 
@@ -312,6 +317,160 @@
 	spin_unlock_bh(&bp->indirect_lock);
 }
 
+#ifdef BCM_CNIC
+static int
+bnx2_drv_ctl(struct net_device *dev, struct drv_ctl_info *info)
+{
+	struct bnx2 *bp = netdev_priv(dev);
+	struct drv_ctl_io *io = &info->data.io;
+
+	switch (info->cmd) {
+	case DRV_CTL_IO_WR_CMD:
+		bnx2_reg_wr_ind(bp, io->offset, io->data);
+		break;
+	case DRV_CTL_IO_RD_CMD:
+		io->data = bnx2_reg_rd_ind(bp, io->offset);
+		break;
+	case DRV_CTL_CTX_WR_CMD:
+		bnx2_ctx_wr(bp, io->cid_addr, io->offset, io->data);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void bnx2_setup_cnic_irq_info(struct bnx2 *bp)
+{
+	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+	int sb_id;
+
+	if (bp->flags & BNX2_FLAG_USING_MSIX) {
+		cp->drv_state |= CNIC_DRV_STATE_USING_MSIX;
+		bnapi->cnic_present = 0;
+		sb_id = bp->irq_nvecs;
+		cp->irq_arr[0].irq_flags |= CNIC_IRQ_FL_MSIX;
+	} else {
+		cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
+		bnapi->cnic_tag = bnapi->last_status_idx;
+		bnapi->cnic_present = 1;
+		sb_id = 0;
+		cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
+	}
+
+	cp->irq_arr[0].vector = bp->irq_tbl[sb_id].vector;
+	cp->irq_arr[0].status_blk = (void *)
+		((unsigned long) bnapi->status_blk.msi +
+		(BNX2_SBLK_MSIX_ALIGN_SIZE * sb_id));
+	cp->irq_arr[0].status_blk_num = sb_id;
+	cp->num_irq = 1;
+}
+
+static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops,
+			      void *data)
+{
+	struct bnx2 *bp = netdev_priv(dev);
+	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+	if (ops == NULL)
+		return -EINVAL;
+
+	if (cp->drv_state & CNIC_DRV_STATE_REGD)
+		return -EBUSY;
+
+	bp->cnic_data = data;
+	rcu_assign_pointer(bp->cnic_ops, ops);
+
+	cp->num_irq = 0;
+	cp->drv_state = CNIC_DRV_STATE_REGD;
+
+	bnx2_setup_cnic_irq_info(bp);
+
+	return 0;
+}
+
+static int bnx2_unregister_cnic(struct net_device *dev)
+{
+	struct bnx2 *bp = netdev_priv(dev);
+	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+	mutex_lock(&bp->cnic_lock);
+	cp->drv_state = 0;
+	bnapi->cnic_present = 0;
+	rcu_assign_pointer(bp->cnic_ops, NULL);
+	mutex_unlock(&bp->cnic_lock);
+	synchronize_rcu();
+	return 0;
+}
+
+struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
+{
+	struct bnx2 *bp = netdev_priv(dev);
+	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+	cp->drv_owner = THIS_MODULE;
+	cp->chip_id = bp->chip_id;
+	cp->pdev = bp->pdev;
+	cp->io_base = bp->regview;
+	cp->drv_ctl = bnx2_drv_ctl;
+	cp->drv_register_cnic = bnx2_register_cnic;
+	cp->drv_unregister_cnic = bnx2_unregister_cnic;
+
+	return cp;
+}
+EXPORT_SYMBOL(bnx2_cnic_probe);
+
+static void
+bnx2_cnic_stop(struct bnx2 *bp)
+{
+	struct cnic_ops *c_ops;
+	struct cnic_ctl_info info;
+
+	mutex_lock(&bp->cnic_lock);
+	c_ops = bp->cnic_ops;
+	if (c_ops) {
+		info.cmd = CNIC_CTL_STOP_CMD;
+		c_ops->cnic_ctl(bp->cnic_data, &info);
+	}
+	mutex_unlock(&bp->cnic_lock);
+}
+
+static void
+bnx2_cnic_start(struct bnx2 *bp)
+{
+	struct cnic_ops *c_ops;
+	struct cnic_ctl_info info;
+
+	mutex_lock(&bp->cnic_lock);
+	c_ops = bp->cnic_ops;
+	if (c_ops) {
+		if (!(bp->flags & BNX2_FLAG_USING_MSIX)) {
+			struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+
+			bnapi->cnic_tag = bnapi->last_status_idx;
+		}
+		info.cmd = CNIC_CTL_START_CMD;
+		c_ops->cnic_ctl(bp->cnic_data, &info);
+	}
+	mutex_unlock(&bp->cnic_lock);
+}
+
+#else
+
+static void
+bnx2_cnic_stop(struct bnx2 *bp)
+{
+}
+
+static void
+bnx2_cnic_start(struct bnx2 *bp)
+{
+}
+
+#endif
+
 static int
 bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
 {
@@ -485,6 +644,7 @@
 static void
 bnx2_netif_stop(struct bnx2 *bp)
 {
+	bnx2_cnic_stop(bp);
 	bnx2_disable_int_sync(bp);
 	if (netif_running(bp->dev)) {
 		bnx2_napi_disable(bp);
@@ -501,6 +661,7 @@
 			netif_tx_wake_all_queues(bp->dev);
 			bnx2_napi_enable(bp);
 			bnx2_enable_int(bp);
+			bnx2_cnic_start(bp);
 		}
 	}
 }
@@ -542,8 +703,7 @@
 						    rxr->rx_desc_mapping[j]);
 			rxr->rx_desc_ring[j] = NULL;
 		}
-		if (rxr->rx_buf_ring)
-			vfree(rxr->rx_buf_ring);
+		vfree(rxr->rx_buf_ring);
 		rxr->rx_buf_ring = NULL;
 
 		for (j = 0; j < bp->rx_max_pg_ring; j++) {
@@ -553,8 +713,7 @@
 						    rxr->rx_pg_desc_mapping[j]);
 			rxr->rx_pg_desc_ring[j] = NULL;
 		}
-		if (rxr->rx_pg_ring)
-			vfree(rxr->rx_pg_ring);
+		vfree(rxr->rx_pg_ring);
 		rxr->rx_pg_ring = NULL;
 	}
 }
@@ -2627,14 +2786,15 @@
 		tx_buf = &txr->tx_buf_ring[sw_ring_cons];
 		skb = tx_buf->skb;
 
+		/* prefetch skb_end_pointer() to speedup skb_shinfo(skb) */
+		prefetch(&skb->end);
+
 		/* partial BD completions possible with TSO packets */
-		if (skb_is_gso(skb)) {
+		if (tx_buf->is_gso) {
 			u16 last_idx, last_ring_idx;
 
-			last_idx = sw_cons +
-				skb_shinfo(skb)->nr_frags + 1;
-			last_ring_idx = sw_ring_cons +
-				skb_shinfo(skb)->nr_frags + 1;
+			last_idx = sw_cons + tx_buf->nr_frags + 1;
+			last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1;
 			if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) {
 				last_idx++;
 			}
@@ -2646,7 +2806,7 @@
 		skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
 
 		tx_buf->skb = NULL;
-		last = skb_shinfo(skb)->nr_frags;
+		last = tx_buf->nr_frags;
 
 		for (i = 0; i < last; i++) {
 			sw_cons = NEXT_TX_BD(sw_cons);
@@ -2659,7 +2819,8 @@
 		if (tx_pkt == budget)
 			break;
 
-		hw_cons = bnx2_get_hw_tx_cons(bnapi);
+		if (hw_cons == sw_cons)
+			hw_cons = bnx2_get_hw_tx_cons(bnapi);
 	}
 
 	txr->hw_tx_cons = hw_cons;
@@ -3161,6 +3322,11 @@
 	if (bnx2_has_fast_work(bnapi))
 		return 1;
 
+#ifdef BCM_CNIC
+	if (bnapi->cnic_present && (bnapi->cnic_tag != sblk->status_idx))
+		return 1;
+#endif
+
 	if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
 	    (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
 		return 1;
@@ -3190,6 +3356,23 @@
 	bp->idle_chk_status_idx = bnapi->last_status_idx;
 }
 
+#ifdef BCM_CNIC
+static void bnx2_poll_cnic(struct bnx2 *bp, struct bnx2_napi *bnapi)
+{
+	struct cnic_ops *c_ops;
+
+	if (!bnapi->cnic_present)
+		return;
+
+	rcu_read_lock();
+	c_ops = rcu_dereference(bp->cnic_ops);
+	if (c_ops)
+		bnapi->cnic_tag = c_ops->cnic_handler(bp->cnic_data,
+						      bnapi->status_blk.msi);
+	rcu_read_unlock();
+}
+#endif
+
 static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
 {
 	struct status_block *sblk = bnapi->status_blk.msi;
@@ -3264,6 +3447,10 @@
 
 		work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
 
+#ifdef BCM_CNIC
+		bnx2_poll_cnic(bp, bnapi);
+#endif
+
 		/* bnapi->last_status_idx is used below to tell the hw how
 		 * much work has been processed, so we must read it before
 		 * checking for more work.
@@ -3305,7 +3492,7 @@
 {
 	struct bnx2 *bp = netdev_priv(dev);
 	u32 rx_mode, sort_mode;
-	struct dev_addr_list *uc_ptr;
+	struct netdev_hw_addr *ha;
 	int i;
 
 	if (!netif_running(dev))
@@ -3364,21 +3551,19 @@
 		sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
 	}
 
-	uc_ptr = NULL;
-	if (dev->uc_count > BNX2_MAX_UNICAST_ADDRESSES) {
+	if (dev->uc.count > BNX2_MAX_UNICAST_ADDRESSES) {
 		rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
 		sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
 			     BNX2_RPM_SORT_USER0_PROM_VLAN;
 	} else if (!(dev->flags & IFF_PROMISC)) {
-		uc_ptr = dev->uc_list;
-
 		/* Add all entries into to the match filter list */
-		for (i = 0; i < dev->uc_count; i++) {
-			bnx2_set_mac_addr(bp, uc_ptr->da_addr,
+		i = 0;
+		list_for_each_entry(ha, &dev->uc.list, list) {
+			bnx2_set_mac_addr(bp, ha->addr,
 					  i + BNX2_START_UNICAST_ADDRESS_INDEX);
 			sort_mode |= (1 <<
 				      (i + BNX2_START_UNICAST_ADDRESS_INDEX));
-			uc_ptr = uc_ptr->next;
+			i++;
 		}
 
 	}
@@ -4629,8 +4814,11 @@
 	val = REG_RD(bp, BNX2_MQ_CONFIG);
 	val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
 	val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
-	if (CHIP_ID(bp) == CHIP_ID_5709_A0 || CHIP_ID(bp) == CHIP_ID_5709_A1)
-		val |= BNX2_MQ_CONFIG_HALT_DIS;
+	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		val |= BNX2_MQ_CONFIG_BIN_MQ_MODE;
+		if (CHIP_REV(bp) == CHIP_REV_Ax)
+			val |= BNX2_MQ_CONFIG_HALT_DIS;
+	}
 
 	REG_WR(bp, BNX2_MQ_CONFIG, val);
 
@@ -5483,7 +5671,7 @@
 		dev_kfree_skb(skb);
 		return -EIO;
 	}
-	map = skb_shinfo(skb)->dma_maps[0];
+	map = skb_shinfo(skb)->dma_head;
 
 	REG_WR(bp, BNX2_HC_COMMAND,
 	       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
@@ -6163,7 +6351,7 @@
 	}
 
 	sp = skb_shinfo(skb);
-	mapping = sp->dma_maps[0];
+	mapping = sp->dma_head;
 
 	tx_buf = &txr->tx_buf_ring[ring_prod];
 	tx_buf->skb = skb;
@@ -6176,6 +6364,8 @@
 	txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START;
 
 	last_frag = skb_shinfo(skb)->nr_frags;
+	tx_buf->nr_frags = last_frag;
+	tx_buf->is_gso = skb_is_gso(skb);
 
 	for (i = 0; i < last_frag; i++) {
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -6185,7 +6375,7 @@
 		txbd = &txr->tx_desc_ring[ring_prod];
 
 		len = frag->size;
-		mapping = sp->dma_maps[i + 1];
+		mapping = sp->dma_maps[i];
 
 		txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
 		txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
@@ -6204,7 +6394,6 @@
 	mmiowb();
 
 	txr->tx_prod = prod;
-	dev->trans_start = jiffies;
 
 	if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) {
 		netif_tx_stop_queue(txq);
@@ -6635,6 +6824,14 @@
 	return 0;
 }
 
+static u32
+bnx2_get_link(struct net_device *dev)
+{
+	struct bnx2 *bp = netdev_priv(dev);
+
+	return bp->link_up;
+}
+
 static int
 bnx2_get_eeprom_len(struct net_device *dev)
 {
@@ -7202,7 +7399,7 @@
 	.get_wol		= bnx2_get_wol,
 	.set_wol		= bnx2_set_wol,
 	.nway_reset		= bnx2_nway_reset,
-	.get_link		= ethtool_op_get_link,
+	.get_link		= bnx2_get_link,
 	.get_eeprom_len		= bnx2_get_eeprom_len,
 	.get_eeprom		= bnx2_get_eeprom,
 	.set_eeprom		= bnx2_set_eeprom,
@@ -7465,10 +7662,13 @@
 
 	spin_lock_init(&bp->phy_lock);
 	spin_lock_init(&bp->indirect_lock);
+#ifdef BCM_CNIC
+	mutex_init(&bp->cnic_lock);
+#endif
 	INIT_WORK(&bp->reset_task, bnx2_reset_task);
 
 	dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
-	mem_len = MB_GET_CID_ADDR(TX_TSS_CID + TX_MAX_TSS_RINGS);
+	mem_len = MB_GET_CID_ADDR(TX_TSS_CID + TX_MAX_TSS_RINGS + 1);
 	dev->mem_end = dev->mem_start + mem_len;
 	dev->irq = pdev->irq;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2.h linux-libre-2.6.31-gnu/drivers/net/bnx2.h
--- linux-libre-2.6.30-gnu/drivers/net/bnx2.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2.h	2009-09-09 18:13:59.000000000 -0400
@@ -361,6 +361,9 @@
 #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE	 (1<<28)
 
 #define BNX2_L2CTX_HOST_BDIDX				0x00000004
+#define BNX2_L2CTX_STATUSB_NUM_SHIFT			 16
+#define BNX2_L2CTX_STATUSB_NUM(sb_id)			 \
+	(((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_STATUSB_NUM_SHIFT) : 0)
 #define BNX2_L2CTX_HOST_BSEQ				0x00000008
 #define BNX2_L2CTX_NX_BSEQ				0x0000000c
 #define BNX2_L2CTX_NX_BDHADDR_HI			0x00000010
@@ -5900,6 +5903,7 @@
 #define BNX2_RXP_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
 
 #define BNX2_RXP_SCRATCH				0x000e0000
+#define BNX2_RXP_SCRATCH_RXP_FLOOD			 0x000e0024
 #define BNX2_RXP_SCRATCH_RSS_TBL_SZ			 0x000e0038
 #define BNX2_RXP_SCRATCH_RSS_TBL			 0x000e003c
 #define BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES		 128
@@ -6552,6 +6556,8 @@
 
 struct sw_tx_bd {
 	struct sk_buff		*skb;
+	unsigned short		is_gso;
+	unsigned short		nr_frags;
 };
 
 #define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
@@ -6678,6 +6684,11 @@
 	u32 			last_status_idx;
 	u32			int_num;
 
+#ifdef BCM_CNIC
+	u32			cnic_tag;
+	int			cnic_present;
+#endif
+
 	struct bnx2_rx_ring_info	rx_ring;
 	struct bnx2_tx_ring_info	tx_ring;
 };
@@ -6727,6 +6738,11 @@
 	int		tx_ring_size;
 	u32		tx_wake_thresh;
 
+#ifdef BCM_CNIC
+	struct cnic_ops		*cnic_ops;
+	void			*cnic_data;
+#endif
+
 	/* End of fields used in the performance code paths. */
 
 	unsigned int		current_interval;
@@ -6885,6 +6901,11 @@
 
 	u32			idle_chk_status_idx;
 
+#ifdef BCM_CNIC
+	struct mutex		cnic_lock;
+	struct cnic_eth_dev	cnic_eth_dev;
+#endif
+
 	const struct firmware	*mips_firmware;
 	const struct firmware	*rv2p_firmware;
 };
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2x_fw_file_hdr.h linux-libre-2.6.31-gnu/drivers/net/bnx2x_fw_file_hdr.h
--- linux-libre-2.6.30-gnu/drivers/net/bnx2x_fw_file_hdr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2x_fw_file_hdr.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,37 @@
+/* bnx2x_fw_file_hdr.h: FW binary file header structure.
+ *
+ * Copyright (c) 2007-2009 Broadcom 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.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov <vladz@broadcom.com>
+ * Based on the original idea of John Wright <john.wright@hp.com>.
+ */
+
+#ifndef BNX2X_INIT_FILE_HDR_H
+#define BNX2X_INIT_FILE_HDR_H
+
+struct bnx2x_fw_file_section {
+	__be32 len;
+	__be32 offset;
+};
+
+struct bnx2x_fw_file_hdr {
+	struct bnx2x_fw_file_section init_ops;
+	struct bnx2x_fw_file_section init_ops_offsets;
+	struct bnx2x_fw_file_section init_data;
+	struct bnx2x_fw_file_section tsem_int_table_data;
+	struct bnx2x_fw_file_section tsem_pram_data;
+	struct bnx2x_fw_file_section usem_int_table_data;
+	struct bnx2x_fw_file_section usem_pram_data;
+	struct bnx2x_fw_file_section csem_int_table_data;
+	struct bnx2x_fw_file_section csem_pram_data;
+	struct bnx2x_fw_file_section xsem_int_table_data;
+	struct bnx2x_fw_file_section xsem_pram_data;
+	struct bnx2x_fw_file_section fw_version;
+};
+
+#endif /* BNX2X_INIT_FILE_HDR_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2x.h linux-libre-2.6.31-gnu/drivers/net/bnx2x.h
--- linux-libre-2.6.30-gnu/drivers/net/bnx2x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2x.h	2009-09-09 18:13:59.000000000 -0400
@@ -902,6 +902,8 @@
 	u16			rx_quick_cons_trip;
 	u16			rx_ticks_int;
 	u16			rx_ticks;
+/* Maximal coalescing timeout in us */
+#define BNX2X_MAX_COALESCE_TOUT		(0xf0*12)
 
 	u32			lin_cnt;
 
@@ -965,6 +967,21 @@
 	int			gunzip_outlen;
 #define FW_BUF_SIZE			0x8000
 
+	struct raw_op          *init_ops;
+	/* Init blocks offsets inside init_ops */
+	u16                    *init_ops_offsets;
+	/* Data blob - has 32 bit granularity */
+	u32                    *init_data;
+	/* Zipped PRAM blobs - raw data */
+	const u8               *tsem_int_table_data;
+	const u8               *tsem_pram_data;
+	const u8               *usem_int_table_data;
+	const u8               *usem_pram_data;
+	const u8               *xsem_int_table_data;
+	const u8               *xsem_pram_data;
+	const u8               *csem_int_table_data;
+	const u8               *csem_pram_data;
+        const struct firmware  *firmware;
 };
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2x_init.h linux-libre-2.6.31-gnu/drivers/net/bnx2x_init.h
--- linux-libre-2.6.30-gnu/drivers/net/bnx2x_init.h	2012-03-22 19:14:36.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2x_init.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,5 @@
 /* bnx2x_init.h: Broadcom Everest network driver.
+ *               Structures and macroes needed during the initialization.
  *
  * Copyright (c) 2007-2009 Broadcom Corporation
  *
@@ -8,6 +9,7 @@
  *
  * Maintained by: Eilon Greenstein <eilong@broadcom.com>
  * Written by: Eliezer Tamir
+ * Modified by: Vladislav Zolotarov <vladz@broadcom.com>
  */
 
 #ifndef BNX2X_INIT_H
@@ -45,33 +47,71 @@
 #define OP_WR_64		0x8 /* write 64 bit pattern */
 #define OP_WB			0x9 /* copy a string using DMAE */
 
-/* Operation specific for E1 */
-#define OP_RD_E1		0xa /* read single register */
-#define OP_WR_E1		0xb /* write single register */
-#define OP_IW_E1		0xc /* write single register using mailbox */
-#define OP_SW_E1		0xd /* copy a string to the device */
-#define OP_SI_E1		0xe /* copy a string using mailbox */
-#define OP_ZR_E1		0xf /* clear memory */
-#define OP_ZP_E1		0x10 /* unzip then copy with DMAE */
-#define OP_WR_64_E1		0x11 /* write 64 bit pattern on E1 */
-#define OP_WB_E1		0x12 /* copy a string using DMAE */
+/* FPGA and EMUL specific operations */
+#define OP_WR_EMUL		0xa /* write single register on Emulation */
+#define OP_WR_FPGA		0xb /* write single register on FPGA */
+#define OP_WR_ASIC		0xc /* write single register on ASIC */
 
-/* Operation specific for E1H */
-#define OP_RD_E1H		0x13 /* read single register */
-#define OP_WR_E1H		0x14 /* write single register */
-#define OP_IW_E1H		0x15 /* write single register using mailbox */
-#define OP_SW_E1H		0x16 /* copy a string to the device */
-#define OP_SI_E1H		0x17 /* copy a string using mailbox */
-#define OP_ZR_E1H		0x18 /* clear memory */
-#define OP_ZP_E1H		0x19 /* unzip then copy with DMAE */
-#define OP_WR_64_E1H		0x1a /* write 64 bit pattern on E1H */
-#define OP_WB_E1H		0x1b /* copy a string using DMAE */
+/* Init stages */
+#define COMMON_STAGE            0
+#define PORT0_STAGE     	1
+#define PORT1_STAGE     	2
+/* Never reorder FUNCx stages !!! */
+#define FUNC0_STAGE     	3
+#define FUNC1_STAGE     	4
+#define FUNC2_STAGE     	5
+#define FUNC3_STAGE     	6
+#define FUNC4_STAGE     	7
+#define FUNC5_STAGE     	8
+#define FUNC6_STAGE     	9
+#define FUNC7_STAGE     	10
+#define STAGE_IDX_MAX   	11
 
-/* FPGA and EMUL specific operations */
-#define OP_WR_EMUL_E1H		0x1c /* write single register on E1H Emul */
-#define OP_WR_EMUL		0x1d /* write single register on Emulation */
-#define OP_WR_FPGA		0x1e /* write single register on FPGA */
-#define OP_WR_ASIC		0x1f /* write single register on ASIC */
+#define STAGE_START     	0
+#define STAGE_END       	1
+
+
+/* Indices of blocks */
+#define PRS_BLOCK               0
+#define SRCH_BLOCK              1
+#define TSDM_BLOCK              2
+#define TCM_BLOCK               3
+#define BRB1_BLOCK              4
+#define TSEM_BLOCK              5
+#define PXPCS_BLOCK             6
+#define EMAC0_BLOCK             7
+#define EMAC1_BLOCK             8
+#define DBU_BLOCK               9
+#define MISC_BLOCK              10
+#define DBG_BLOCK               11
+#define NIG_BLOCK               12
+#define MCP_BLOCK               13
+#define UPB_BLOCK               14
+#define CSDM_BLOCK              15
+#define USDM_BLOCK              16
+#define CCM_BLOCK               17
+#define UCM_BLOCK               18
+#define USEM_BLOCK              19
+#define CSEM_BLOCK              20
+#define XPB_BLOCK               21
+#define DQ_BLOCK                22
+#define TIMERS_BLOCK            23
+#define XSDM_BLOCK              24
+#define QM_BLOCK                25
+#define PBF_BLOCK               26
+#define XCM_BLOCK               27
+#define XSEM_BLOCK              28
+#define CDU_BLOCK               29
+#define DMAE_BLOCK              30
+#define PXP_BLOCK               31
+#define CFC_BLOCK               32
+#define HC_BLOCK                33
+#define PXP2_BLOCK              34
+#define MISC_AEU_BLOCK          35
+
+/* Returns the index of start or end of a specific block stage in ops array*/
+#define BLOCK_OPS_IDX(block, stage, end) \
+       (2*(((block)*STAGE_IDX_MAX) + (stage)) + (end))
 
 
 struct raw_op {
@@ -118,112 +158,6 @@
 	struct raw_op		raw;
 };
 
-#include "bnx2x_init_values.h"
-
-static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
-static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len);
-
-static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
-			      u32 len)
-{
-	int i;
-
-	for (i = 0; i < len; i++) {
-		REG_WR(bp, addr + i*4, data[i]);
-		if (!(i % 10000)) {
-			touch_softlockup_watchdog();
-			cpu_relax();
-		}
-	}
-}
-
-static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
-			      u16 len)
-{
-	int i;
-
-	for (i = 0; i < len; i++) {
-		REG_WR_IND(bp, addr + i*4, data[i]);
-		if (!(i % 10000)) {
-			touch_softlockup_watchdog();
-			cpu_relax();
-		}
-	}
-}
-
-static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
-{
-	int offset = 0;
-
-	if (bp->dmae_ready) {
-		while (len > DMAE_LEN32_WR_MAX) {
-			bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
-					 addr + offset, DMAE_LEN32_WR_MAX);
-			offset += DMAE_LEN32_WR_MAX * 4;
-			len -= DMAE_LEN32_WR_MAX;
-		}
-		bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
-				 addr + offset, len);
-	} else
-		bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len);
-}
-
-static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
-{
-	u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4));
-	u32 buf_len32 = buf_len / 4;
-	int i;
-
-	memset(bp->gunzip_buf, fill, buf_len);
-
-	for (i = 0; i < len; i += buf_len32) {
-		u32 cur_len = min(buf_len32, len - i);
-
-		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
-	}
-}
-
-static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
-			     u32 len64)
-{
-	u32 buf_len32 = FW_BUF_SIZE / 4;
-	u32 len = len64 * 2;
-	u64 data64 = 0;
-	int i;
-
-	/* 64 bit value is in a blob: first low DWORD, then high DWORD */
-	data64 = HILO_U64((*(data + 1)), (*data));
-	len64 = min((u32)(FW_BUF_SIZE/8), len64);
-	for (i = 0; i < len64; i++) {
-		u64 *pdata = ((u64 *)(bp->gunzip_buf)) + i;
-
-		*pdata = data64;
-	}
-
-	for (i = 0; i < len; i += buf_len32) {
-		u32 cur_len = min(buf_len32, len - i);
-
-		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
-	}
-}
-
-/*********************************************************
-   There are different blobs for each PRAM section.
-   In addition, each blob write operation is divided into a few operations
-   in order to decrease the amount of phys. contiguous buffer needed.
-   Thus, when we select a blob the address may be with some offset
-   from the beginning of PRAM section.
-   The same holds for the INT_TABLE sections.
-**********************************************************/
-#define IF_IS_INT_TABLE_ADDR(base, addr) \
-			if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
-
-#define IF_IS_PRAM_ADDR(base, addr) \
-			if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
-
-/*(DEBLOBBED)*/
-
-
 /****************************************************************************
 * PXP
 ****************************************************************************/
@@ -387,111 +321,6 @@
 		PXP2_REG_RQ_BW_WR_UBOUND30}
 };
 
-static void bnx2x_init_pxp(struct bnx2x *bp)
-{
-	u16 devctl;
-	int r_order, w_order;
-	u32 val, i;
-
-	pci_read_config_word(bp->pdev,
-			     bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
-	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
-	w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
-	if (bp->mrrs == -1)
-		r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
-	else {
-		DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs);
-		r_order = bp->mrrs;
-	}
-
-	if (r_order > MAX_RD_ORD) {
-		DP(NETIF_MSG_HW, "read order of %d  order adjusted to %d\n",
-		   r_order, MAX_RD_ORD);
-		r_order = MAX_RD_ORD;
-	}
-	if (w_order > MAX_WR_ORD) {
-		DP(NETIF_MSG_HW, "write order of %d  order adjusted to %d\n",
-		   w_order, MAX_WR_ORD);
-		w_order = MAX_WR_ORD;
-	}
-	if (CHIP_REV_IS_FPGA(bp)) {
-		DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n");
-		w_order = 0;
-	}
-	DP(NETIF_MSG_HW, "read order %d  write order %d\n", r_order, w_order);
-
-	for (i = 0; i < NUM_RD_Q-1; i++) {
-		REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);
-		REG_WR(bp, read_arb_addr[i].add,
-		       read_arb_data[i][r_order].add);
-		REG_WR(bp, read_arb_addr[i].ubound,
-		       read_arb_data[i][r_order].ubound);
-	}
-
-	for (i = 0; i < NUM_WR_Q-1; i++) {
-		if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||
-		    (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {
-
-			REG_WR(bp, write_arb_addr[i].l,
-			       write_arb_data[i][w_order].l);
-
-			REG_WR(bp, write_arb_addr[i].add,
-			       write_arb_data[i][w_order].add);
-
-			REG_WR(bp, write_arb_addr[i].ubound,
-			       write_arb_data[i][w_order].ubound);
-		} else {
-
-			val = REG_RD(bp, write_arb_addr[i].l);
-			REG_WR(bp, write_arb_addr[i].l,
-			       val | (write_arb_data[i][w_order].l << 10));
-
-			val = REG_RD(bp, write_arb_addr[i].add);
-			REG_WR(bp, write_arb_addr[i].add,
-			       val | (write_arb_data[i][w_order].add << 10));
-
-			val = REG_RD(bp, write_arb_addr[i].ubound);
-			REG_WR(bp, write_arb_addr[i].ubound,
-			       val | (write_arb_data[i][w_order].ubound << 7));
-		}
-	}
-
-	val =  write_arb_data[NUM_WR_Q-1][w_order].add;
-	val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10;
-	val += write_arb_data[NUM_WR_Q-1][w_order].l << 17;
-	REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val);
-
-	val =  read_arb_data[NUM_RD_Q-1][r_order].add;
-	val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10;
-	val += read_arb_data[NUM_RD_Q-1][r_order].l << 17;
-	REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);
-
-	REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);
-	REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order);
-	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
-	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
-
-	if (r_order == MAX_RD_ORD)
-		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
-
-	REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
-
-	if (CHIP_IS_E1H(bp)) {
-		val = ((w_order == 0) ? 2 : 3);
-		REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_QM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
-		REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */
-		REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
-	}
-}
-
 
 /****************************************************************************
 * CDU
@@ -515,128 +344,12 @@
 	(0x80 | ((_type) & 0xf << 3) | (CDU_CRC8(_cid, _region, _type) & 0x7))
 #define CDU_RSRVD_INVALIDATE_CONTEXT_VALUE(_val)	((_val) & ~0x80)
 
-/*****************************************************************************
- * Description:
- *         Calculates crc 8 on a word value: polynomial 0-1-2-8
- *         Code was translated from Verilog.
- ****************************************************************************/
-static u8 calc_crc8(u32 data, u8 crc)
-{
-	u8 D[32];
-	u8 NewCRC[8];
-	u8 C[8];
-	u8 crc_res;
-	u8 i;
-
-	/* split the data into 31 bits */
-	for (i = 0; i < 32; i++) {
-		D[i] = data & 1;
-		data = data >> 1;
-	}
-
-	/* split the crc into 8 bits */
-	for (i = 0; i < 8; i++) {
-		C[i] = crc & 1;
-		crc = crc >> 1;
-	}
-
-	NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
-		D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
-		C[6] ^ C[7];
-	NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
-		D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
-		D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6];
-	NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
-		D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
-		C[0] ^ C[1] ^ C[4] ^ C[5];
-	NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
-		D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
-		C[1] ^ C[2] ^ C[5] ^ C[6];
-	NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
-		D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
-		C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
-	NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
-		D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
-		C[3] ^ C[4] ^ C[7];
-	NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
-		D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
-		C[5];
-	NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
-		D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
-		C[6];
-
-	crc_res = 0;
-	for (i = 0; i < 8; i++)
-		crc_res |= (NewCRC[i] << i);
-
-	return crc_res;
-}
 
 /* registers addresses are not in order
    so these arrays help simplify the code */
-static const int cm_start[E1H_FUNC_MAX][9] = {
-	{MISC_FUNC0_START, TCM_FUNC0_START, UCM_FUNC0_START, CCM_FUNC0_START,
-	 XCM_FUNC0_START, TSEM_FUNC0_START, USEM_FUNC0_START, CSEM_FUNC0_START,
-	 XSEM_FUNC0_START},
-	{MISC_FUNC1_START, TCM_FUNC1_START, UCM_FUNC1_START, CCM_FUNC1_START,
-	 XCM_FUNC1_START, TSEM_FUNC1_START, USEM_FUNC1_START, CSEM_FUNC1_START,
-	 XSEM_FUNC1_START},
-	{MISC_FUNC2_START, TCM_FUNC2_START, UCM_FUNC2_START, CCM_FUNC2_START,
-	 XCM_FUNC2_START, TSEM_FUNC2_START, USEM_FUNC2_START, CSEM_FUNC2_START,
-	 XSEM_FUNC2_START},
-	{MISC_FUNC3_START, TCM_FUNC3_START, UCM_FUNC3_START, CCM_FUNC3_START,
-	 XCM_FUNC3_START, TSEM_FUNC3_START, USEM_FUNC3_START, CSEM_FUNC3_START,
-	 XSEM_FUNC3_START},
-	{MISC_FUNC4_START, TCM_FUNC4_START, UCM_FUNC4_START, CCM_FUNC4_START,
-	 XCM_FUNC4_START, TSEM_FUNC4_START, USEM_FUNC4_START, CSEM_FUNC4_START,
-	 XSEM_FUNC4_START},
-	{MISC_FUNC5_START, TCM_FUNC5_START, UCM_FUNC5_START, CCM_FUNC5_START,
-	 XCM_FUNC5_START, TSEM_FUNC5_START, USEM_FUNC5_START, CSEM_FUNC5_START,
-	 XSEM_FUNC5_START},
-	{MISC_FUNC6_START, TCM_FUNC6_START, UCM_FUNC6_START, CCM_FUNC6_START,
-	 XCM_FUNC6_START, TSEM_FUNC6_START, USEM_FUNC6_START, CSEM_FUNC6_START,
-	 XSEM_FUNC6_START},
-	{MISC_FUNC7_START, TCM_FUNC7_START, UCM_FUNC7_START, CCM_FUNC7_START,
-	 XCM_FUNC7_START, TSEM_FUNC7_START, USEM_FUNC7_START, CSEM_FUNC7_START,
-	 XSEM_FUNC7_START}
-};
-
-static const int cm_end[E1H_FUNC_MAX][9] = {
-	{MISC_FUNC0_END, TCM_FUNC0_END, UCM_FUNC0_END, CCM_FUNC0_END,
-	 XCM_FUNC0_END, TSEM_FUNC0_END, USEM_FUNC0_END, CSEM_FUNC0_END,
-	 XSEM_FUNC0_END},
-	{MISC_FUNC1_END, TCM_FUNC1_END, UCM_FUNC1_END, CCM_FUNC1_END,
-	 XCM_FUNC1_END, TSEM_FUNC1_END, USEM_FUNC1_END, CSEM_FUNC1_END,
-	 XSEM_FUNC1_END},
-	{MISC_FUNC2_END, TCM_FUNC2_END, UCM_FUNC2_END, CCM_FUNC2_END,
-	 XCM_FUNC2_END, TSEM_FUNC2_END, USEM_FUNC2_END, CSEM_FUNC2_END,
-	 XSEM_FUNC2_END},
-	{MISC_FUNC3_END, TCM_FUNC3_END, UCM_FUNC3_END, CCM_FUNC3_END,
-	 XCM_FUNC3_END, TSEM_FUNC3_END, USEM_FUNC3_END, CSEM_FUNC3_END,
-	 XSEM_FUNC3_END},
-	{MISC_FUNC4_END, TCM_FUNC4_END, UCM_FUNC4_END, CCM_FUNC4_END,
-	 XCM_FUNC4_END, TSEM_FUNC4_END, USEM_FUNC4_END, CSEM_FUNC4_END,
-	 XSEM_FUNC4_END},
-	{MISC_FUNC5_END, TCM_FUNC5_END, UCM_FUNC5_END, CCM_FUNC5_END,
-	 XCM_FUNC5_END, TSEM_FUNC5_END, USEM_FUNC5_END, CSEM_FUNC5_END,
-	 XSEM_FUNC5_END},
-	{MISC_FUNC6_END, TCM_FUNC6_END, UCM_FUNC6_END, CCM_FUNC6_END,
-	 XCM_FUNC6_END, TSEM_FUNC6_END, USEM_FUNC6_END, CSEM_FUNC6_END,
-	 XSEM_FUNC6_END},
-	{MISC_FUNC7_END, TCM_FUNC7_END, UCM_FUNC7_END, CCM_FUNC7_END,
-	 XCM_FUNC7_END, TSEM_FUNC7_END, USEM_FUNC7_END, CSEM_FUNC7_END,
-	 XSEM_FUNC7_END},
-};
-
-static const int hc_limits[E1H_FUNC_MAX][2] = {
-	{HC_FUNC0_START, HC_FUNC0_END},
-	{HC_FUNC1_START, HC_FUNC1_END},
-	{HC_FUNC2_START, HC_FUNC2_END},
-	{HC_FUNC3_START, HC_FUNC3_END},
-	{HC_FUNC4_START, HC_FUNC4_END},
-	{HC_FUNC5_START, HC_FUNC5_END},
-	{HC_FUNC6_START, HC_FUNC6_END},
-	{HC_FUNC7_START, HC_FUNC7_END}
+static const int cm_blocks[9] = {
+	MISC_BLOCK, TCM_BLOCK,  UCM_BLOCK,  CCM_BLOCK, XCM_BLOCK,
+	TSEM_BLOCK, USEM_BLOCK, CSEM_BLOCK, XSEM_BLOCK
 };
 
 #endif /* BNX2X_INIT_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2x_init_ops.h linux-libre-2.6.31-gnu/drivers/net/bnx2x_init_ops.h
--- linux-libre-2.6.30-gnu/drivers/net/bnx2x_init_ops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2x_init_ops.h	2012-03-22 20:10:51.000000000 -0400
@@ -0,0 +1,353 @@
+/* bnx2x_init_ops.h: Broadcom Everest network driver.
+ *               Static functions needed during the initialization.
+ *               This file is "included" in bnx2x_main.c.
+ *
+ * Copyright (c) 2007-2009 Broadcom 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.
+ *
+ * Maintained by: Eilon Greenstein <eilong@broadcom.com>
+ * Written by: Vladislav Zolotarov <vladz@broadcom.com>
+ */
+#ifndef BNX2X_INIT_OPS_H
+#define BNX2X_INIT_OPS_H
+
+static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
+static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
+
+static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr, const u32 *data,
+			      u32 len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		REG_WR(bp, addr + i*4, data[i]);
+		if (!(i % 10000)) {
+			touch_softlockup_watchdog();
+			cpu_relax();
+		}
+	}
+}
+
+static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data,
+			      u16 len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		REG_WR_IND(bp, addr + i*4, data[i]);
+		if (!(i % 10000)) {
+			touch_softlockup_watchdog();
+			cpu_relax();
+		}
+	}
+}
+
+static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len)
+{
+	int offset = 0;
+
+	if (bp->dmae_ready) {
+		while (len > DMAE_LEN32_WR_MAX) {
+			bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+					 addr + offset, DMAE_LEN32_WR_MAX);
+			offset += DMAE_LEN32_WR_MAX * 4;
+			len -= DMAE_LEN32_WR_MAX;
+		}
+		bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+				 addr + offset, len);
+	} else
+		bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len);
+}
+
+static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
+{
+	u32 buf_len = (((len * 4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len * 4));
+	u32 buf_len32 = buf_len / 4;
+	int i;
+
+	memset(bp->gunzip_buf, fill, buf_len);
+
+	for (i = 0; i < len; i += buf_len32) {
+		u32 cur_len = min(buf_len32, len - i);
+
+		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
+	}
+}
+
+static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, const u32 *data,
+			     u32 len64)
+{
+	u32 buf_len32 = FW_BUF_SIZE / 4;
+	u32 len = len64 * 2;
+	u64 data64 = 0;
+	int i;
+
+	/* 64 bit value is in a blob: first low DWORD, then high DWORD */
+	data64 = HILO_U64((*(data + 1)), (*data));
+	len64 = min((u32)(FW_BUF_SIZE/8), len64);
+	for (i = 0; i < len64; i++) {
+		u64 *pdata = ((u64 *)(bp->gunzip_buf)) + i;
+
+		*pdata = data64;
+	}
+
+	for (i = 0; i < len; i += buf_len32) {
+		u32 cur_len = min(buf_len32, len - i);
+
+		bnx2x_write_big_buf(bp, addr + i * 4, cur_len);
+	}
+}
+
+/*********************************************************
+   There are different blobs for each PRAM section.
+   In addition, each blob write operation is divided into a few operations
+   in order to decrease the amount of phys. contiguous buffer needed.
+   Thus, when we select a blob the address may be with some offset
+   from the beginning of PRAM section.
+   The same holds for the INT_TABLE sections.
+**********************************************************/
+#define IF_IS_INT_TABLE_ADDR(base, addr) \
+			if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
+
+#define IF_IS_PRAM_ADDR(base, addr) \
+			if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
+
+static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr, const u8 *data)
+{
+	IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr)
+		data = bp->tsem_int_table_data;
+	else IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr)
+		data = bp->csem_int_table_data;
+	else IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr)
+		data = bp->usem_int_table_data;
+	else IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr)
+		data = bp->xsem_int_table_data;
+	else IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr)
+		data = bp->tsem_pram_data;
+	else IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr)
+		data = bp->csem_pram_data;
+	else IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr)
+		data = bp->usem_pram_data;
+	else IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr)
+		data = bp->xsem_pram_data;
+
+	return data;
+}
+
+static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
+{
+	int offset = 0;
+
+	if (bp->dmae_ready) {
+		while (len > DMAE_LEN32_WR_MAX) {
+			bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+					 addr + offset, DMAE_LEN32_WR_MAX);
+			offset += DMAE_LEN32_WR_MAX * 4;
+			len -= DMAE_LEN32_WR_MAX;
+		}
+		bnx2x_write_dmae(bp, bp->gunzip_mapping + offset,
+				 addr + offset, len);
+	} else
+		bnx2x_init_ind_wr(bp, addr, bp->gunzip_buf, len);
+}
+
+/*(DEBLOBBED)*/
+
+static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr,
+			     u32 len, u32 blob_off)
+{
+	int rc, i;
+        const u8 *data = NULL;
+
+	data = bnx2x_sel_blob(bp, addr, data) + 4*blob_off;
+
+	if (data == NULL) {
+		panic("Blob not found for addr 0x%x\n", addr);
+		return;
+	}
+
+	rc = bnx2x_gunzip(bp, data, len);
+	if (rc) {
+		BNX2X_ERR("gunzip failed ! addr 0x%x rc %d\n", addr, rc);
+		BNX2X_ERR("blob_offset=0x%x\n", blob_off);
+		return;
+	}
+
+	/* gunzip_outlen is in dwords */
+	len = bp->gunzip_outlen;
+	for (i = 0; i < len; i++)
+		((u32 *)bp->gunzip_buf)[i] =
+			cpu_to_le32(((u32 *)bp->gunzip_buf)[i]);
+
+	bnx2x_write_big_buf_wb(bp, addr, len);
+}
+
+/*(DEBLOBBED)*/
+
+/* PXP */
+static void bnx2x_init_pxp(struct bnx2x *bp)
+{
+	u16 devctl;
+	int r_order, w_order;
+	u32 val, i;
+
+	pci_read_config_word(bp->pdev,
+			     bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
+	DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
+	w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+	if (bp->mrrs == -1)
+		r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+	else {
+		DP(NETIF_MSG_HW, "force read order to %d\n", bp->mrrs);
+		r_order = bp->mrrs;
+	}
+
+	if (r_order > MAX_RD_ORD) {
+		DP(NETIF_MSG_HW, "read order of %d  order adjusted to %d\n",
+		   r_order, MAX_RD_ORD);
+		r_order = MAX_RD_ORD;
+	}
+	if (w_order > MAX_WR_ORD) {
+		DP(NETIF_MSG_HW, "write order of %d  order adjusted to %d\n",
+		   w_order, MAX_WR_ORD);
+		w_order = MAX_WR_ORD;
+	}
+	if (CHIP_REV_IS_FPGA(bp)) {
+		DP(NETIF_MSG_HW, "write order adjusted to 1 for FPGA\n");
+		w_order = 0;
+	}
+	DP(NETIF_MSG_HW, "read order %d  write order %d\n", r_order, w_order);
+
+	for (i = 0; i < NUM_RD_Q-1; i++) {
+		REG_WR(bp, read_arb_addr[i].l, read_arb_data[i][r_order].l);
+		REG_WR(bp, read_arb_addr[i].add,
+		       read_arb_data[i][r_order].add);
+		REG_WR(bp, read_arb_addr[i].ubound,
+		       read_arb_data[i][r_order].ubound);
+	}
+
+	for (i = 0; i < NUM_WR_Q-1; i++) {
+		if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) ||
+		    (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) {
+
+			REG_WR(bp, write_arb_addr[i].l,
+			       write_arb_data[i][w_order].l);
+
+			REG_WR(bp, write_arb_addr[i].add,
+			       write_arb_data[i][w_order].add);
+
+			REG_WR(bp, write_arb_addr[i].ubound,
+			       write_arb_data[i][w_order].ubound);
+		} else {
+
+			val = REG_RD(bp, write_arb_addr[i].l);
+			REG_WR(bp, write_arb_addr[i].l,
+			       val | (write_arb_data[i][w_order].l << 10));
+
+			val = REG_RD(bp, write_arb_addr[i].add);
+			REG_WR(bp, write_arb_addr[i].add,
+			       val | (write_arb_data[i][w_order].add << 10));
+
+			val = REG_RD(bp, write_arb_addr[i].ubound);
+			REG_WR(bp, write_arb_addr[i].ubound,
+			       val | (write_arb_data[i][w_order].ubound << 7));
+		}
+	}
+
+	val =  write_arb_data[NUM_WR_Q-1][w_order].add;
+	val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10;
+	val += write_arb_data[NUM_WR_Q-1][w_order].l << 17;
+	REG_WR(bp, PXP2_REG_PSWRQ_BW_RD, val);
+
+	val =  read_arb_data[NUM_RD_Q-1][r_order].add;
+	val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10;
+	val += read_arb_data[NUM_RD_Q-1][r_order].l << 17;
+	REG_WR(bp, PXP2_REG_PSWRQ_BW_WR, val);
+
+	REG_WR(bp, PXP2_REG_RQ_WR_MBS0, w_order);
+	REG_WR(bp, PXP2_REG_RQ_WR_MBS1, w_order);
+	REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
+	REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
+
+	if (r_order == MAX_RD_ORD)
+		REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
+
+	REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
+
+	if (CHIP_IS_E1H(bp)) {
+		val = ((w_order == 0) ? 2 : 3);
+		REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_TSDM_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_XSDM_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_QM_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
+		REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */
+		REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
+	}
+}
+
+/*****************************************************************************
+ * Description:
+ *         Calculates crc 8 on a word value: polynomial 0-1-2-8
+ *         Code was translated from Verilog.
+ ****************************************************************************/
+static u8 calc_crc8(u32 data, u8 crc)
+{
+	u8 D[32];
+	u8 NewCRC[8];
+	u8 C[8];
+	u8 crc_res;
+	u8 i;
+
+	/* split the data into 31 bits */
+	for (i = 0; i < 32; i++) {
+		D[i] = data & 1;
+		data = data >> 1;
+	}
+
+	/* split the crc into 8 bits */
+	for (i = 0; i < 8; i++) {
+		C[i] = crc & 1;
+		crc = crc >> 1;
+	}
+
+	NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^
+		D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^
+		C[6] ^ C[7];
+	NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^
+		D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^
+		D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6];
+	NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^
+		D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^
+		C[0] ^ C[1] ^ C[4] ^ C[5];
+	NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^
+		D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^
+		C[1] ^ C[2] ^ C[5] ^ C[6];
+	NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^
+		D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^
+		C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7];
+	NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^
+		D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^
+		C[3] ^ C[4] ^ C[7];
+	NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^
+		D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^
+		C[5];
+	NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^
+		D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^
+		C[6];
+
+	crc_res = 0;
+	for (i = 0; i < 8; i++)
+		crc_res |= (NewCRC[i] << i);
+
+	return crc_res;
+}
+
+#endif /* BNX2X_INIT_OPS_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2x_init_values.h linux-libre-2.6.31-gnu/drivers/net/bnx2x_init_values.h
--- linux-libre-2.6.30-gnu/drivers/net/bnx2x_init_values.h	2012-03-22 19:14:34.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2x_init_values.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,2535 +0,0 @@
-#ifndef __BNX2X_INIT_VALUES_H__
-#define __BNX2X_INIT_VALUES_H__
-
-/* bnx2x_init_values.h: Broadcom NX2 10G network driver.
- *
- * Copyright (c) 2007-2009 Broadcom 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, except as noted below.
- *
- * This file contains firmware data derived from proprietary unpublished
- * source code, Copyright (c) 2007-2009 Broadcom Corporation.
- *
- * Permission is hereby granted for the distribution of this firmware data
- * in hexadecimal or equivalent format, provided this copyright notice is
- * accompanying it.
- *
- *
- * This array contains the list of operations needed to initialize the chip.
- *
- * For each block in the chip there are three init stages:
- * common - HW used by both ports,
- * port1 and port2 - initialization for a specific Ethernet port.
- * When a port is opened or closed, the management CPU tells the driver
- * whether to init/disable common HW in addition to the port HW.
- * This way the first port going up will first initializes the common HW,
- * and the last port going down also resets the common HW
- *
- * For each init stage/block there is a list of actions needed in a format:
- * {operation, register, data}
- * where:
- * OP_WR - write a value to the chip.
- * OP_RD - read a register (usually a clear on read register).
- * OP_SW - string write, write a section of consecutive addresses to the chip.
- * OP_SI - copy a string using indirect writes.
- * OP_ZR - clear a range of memory.
- * OP_ZP - unzip and copy using DMAE.
- * OP_WB - string copy using DMAE.
- *
- * The #defines mark the stages.
- *
- */
-
-static const struct raw_op init_ops[] = {
-#define PRS_COMMON_START        0
-	{OP_WR, PRS_REG_INC_VALUE, 0xf},
-	{OP_WR, PRS_REG_EVENT_ID_1, 0x45},
-	{OP_WR, PRS_REG_EVENT_ID_2, 0x84},
-	{OP_WR, PRS_REG_EVENT_ID_3, 0x6},
-	{OP_WR, PRS_REG_NO_MATCH_EVENT_ID, 0x4},
-	{OP_WR, PRS_REG_CM_HDR_TYPE_0, 0x0},
-	{OP_WR, PRS_REG_CM_HDR_TYPE_1, 0x12170000},
-	{OP_WR, PRS_REG_CM_HDR_TYPE_2, 0x22170000},
-	{OP_WR, PRS_REG_CM_HDR_TYPE_3, 0x32170000},
-	{OP_ZR, PRS_REG_CM_HDR_TYPE_4, 0x5},
-	{OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_1, 0x12150000},
-	{OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_2, 0x22150000},
-	{OP_WR, PRS_REG_CM_HDR_LOOPBACK_TYPE_3, 0x32150000},
-	{OP_ZR, PRS_REG_CM_HDR_LOOPBACK_TYPE_4, 0x4},
-	{OP_WR, PRS_REG_CM_NO_MATCH_HDR, 0x2100000},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_0, 0x100000},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_1, 0x10100000},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_2, 0x20100000},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_3, 0x30100000},
-	{OP_ZR_E1, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_4, 0x4},
-	{OP_WR_E1H, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_4, 0x40100000},
-	{OP_ZR_E1H, PRS_REG_CM_HDR_FLUSH_NO_LOAD_TYPE_5, 0x3},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_0, 0x100000},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_1, 0x12140000},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_2, 0x22140000},
-	{OP_WR, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_3, 0x32140000},
-	{OP_ZR_E1, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_4, 0x4},
-	{OP_WR_E1H, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_4, 0x42140000},
-	{OP_ZR_E1H, PRS_REG_CM_HDR_FLUSH_LOAD_TYPE_5, 0x3},
-	{OP_RD, PRS_REG_NUM_OF_PACKETS, 0x0},
-	{OP_RD, PRS_REG_NUM_OF_CFC_FLUSH_MESSAGES, 0x0},
-	{OP_RD, PRS_REG_NUM_OF_TRANSPARENT_FLUSH_MESSAGES, 0x0},
-	{OP_RD, PRS_REG_NUM_OF_DEAD_CYCLES, 0x0},
-	{OP_WR_E1H, PRS_REG_FCOE_TYPE, 0x8906},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_0, 0xff},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_1, 0xff},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_2, 0xff},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_3, 0xff},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_4, 0xff},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_5, 0xff},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_6, 0xff},
-	{OP_WR, PRS_REG_FLUSH_REGIONS_TYPE_7, 0xff},
-	{OP_WR, PRS_REG_PURE_REGIONS, 0x3e},
-	{OP_WR, PRS_REG_PACKET_REGIONS_TYPE_0, 0x0},
-	{OP_WR, PRS_REG_PACKET_REGIONS_TYPE_1, 0x3f},
-	{OP_WR, PRS_REG_PACKET_REGIONS_TYPE_2, 0x3f},
-	{OP_WR, PRS_REG_PACKET_REGIONS_TYPE_3, 0x3f},
-	{OP_WR_E1, PRS_REG_PACKET_REGIONS_TYPE_4, 0x0},
-	{OP_WR_E1H, PRS_REG_PACKET_REGIONS_TYPE_4, 0x3f},
-	{OP_WR, PRS_REG_PACKET_REGIONS_TYPE_5, 0x3f},
-	{OP_WR, PRS_REG_PACKET_REGIONS_TYPE_6, 0x3f},
-	{OP_WR, PRS_REG_PACKET_REGIONS_TYPE_7, 0x3f},
-#define PRS_COMMON_END          52
-#define SRCH_COMMON_START       52
-	{OP_WR_E1H, SRC_REG_E1HMF_ENABLE, 0x1},
-#define SRCH_COMMON_END         53
-#define TSDM_COMMON_START       53
-	{OP_WR_E1, TSDM_REG_CFC_RSP_START_ADDR, 0x411},
-	{OP_WR_E1H, TSDM_REG_CFC_RSP_START_ADDR, 0x211},
-	{OP_WR_E1, TSDM_REG_CMP_COUNTER_START_ADDR, 0x400},
-	{OP_WR_E1H, TSDM_REG_CMP_COUNTER_START_ADDR, 0x200},
-	{OP_WR_E1, TSDM_REG_Q_COUNTER_START_ADDR, 0x404},
-	{OP_WR_E1H, TSDM_REG_Q_COUNTER_START_ADDR, 0x204},
-	{OP_WR_E1, TSDM_REG_PCK_END_MSG_START_ADDR, 0x419},
-	{OP_WR_E1H, TSDM_REG_PCK_END_MSG_START_ADDR, 0x219},
-	{OP_WR, TSDM_REG_CMP_COUNTER_MAX0, 0xffff},
-	{OP_WR, TSDM_REG_CMP_COUNTER_MAX1, 0xffff},
-	{OP_WR, TSDM_REG_CMP_COUNTER_MAX2, 0xffff},
-	{OP_WR, TSDM_REG_CMP_COUNTER_MAX3, 0xffff},
-	{OP_ZR_E1, TSDM_REG_AGG_INT_EVENT_0, 0x2},
-	{OP_WR_E1H, TSDM_REG_AGG_INT_EVENT_0, 0x20},
-	{OP_WR_E1H, TSDM_REG_AGG_INT_EVENT_1, 0x0},
-	{OP_WR, TSDM_REG_AGG_INT_EVENT_2, 0x34},
-	{OP_WR, TSDM_REG_AGG_INT_EVENT_3, 0x35},
-	{OP_ZR_E1, TSDM_REG_AGG_INT_EVENT_4, 0x7c},
-	{OP_ZR_E1H, TSDM_REG_AGG_INT_EVENT_4, 0x1c},
-	{OP_WR_E1H, TSDM_REG_AGG_INT_T_0, 0x1},
-	{OP_ZR_E1H, TSDM_REG_AGG_INT_T_1, 0x5f},
-	{OP_WR, TSDM_REG_ENABLE_IN1, 0x7ffffff},
-	{OP_WR, TSDM_REG_ENABLE_IN2, 0x3f},
-	{OP_WR, TSDM_REG_ENABLE_OUT1, 0x7ffffff},
-	{OP_WR, TSDM_REG_ENABLE_OUT2, 0xf},
-	{OP_RD, TSDM_REG_NUM_OF_Q0_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q1_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q3_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q4_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q5_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q6_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q7_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q8_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q9_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q10_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_Q11_CMD, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_PKT_END_MSG, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0},
-	{OP_RD, TSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0},
-	{OP_WR_E1, TSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1},
-	{OP_WR_ASIC, TSDM_REG_TIMER_TICK, 0x3e8},
-	{OP_WR_EMUL, TSDM_REG_TIMER_TICK, 0x1},
-	{OP_WR_FPGA, TSDM_REG_TIMER_TICK, 0xa},
-#define TSDM_COMMON_END         96
-#define TCM_COMMON_START        96
-	{OP_WR, TCM_REG_XX_MAX_LL_SZ, 0x20},
-	{OP_WR, TCM_REG_XX_OVFL_EVNT_ID, 0x32},
-	{OP_WR, TCM_REG_TQM_TCM_HDR_P, 0x2150020},
-	{OP_WR, TCM_REG_TQM_TCM_HDR_S, 0x2150020},
-	{OP_WR, TCM_REG_TM_TCM_HDR, 0x30},
-	{OP_WR, TCM_REG_ERR_TCM_HDR, 0x8100000},
-	{OP_WR, TCM_REG_ERR_EVNT_ID, 0x33},
-	{OP_WR, TCM_REG_EXPR_EVNT_ID, 0x30},
-	{OP_WR, TCM_REG_STOP_EVNT_ID, 0x31},
-	{OP_WR, TCM_REG_STORM_WEIGHT, 0x2},
-	{OP_WR, TCM_REG_PRS_WEIGHT, 0x5},
-	{OP_WR, TCM_REG_PBF_WEIGHT, 0x6},
-	{OP_WR, TCM_REG_USEM_WEIGHT, 0x2},
-	{OP_WR, TCM_REG_CSEM_WEIGHT, 0x2},
-	{OP_WR, TCM_REG_CP_WEIGHT, 0x0},
-	{OP_WR, TCM_REG_TSDM_WEIGHT, 0x5},
-	{OP_WR, TCM_REG_TQM_P_WEIGHT, 0x2},
-	{OP_WR, TCM_REG_TQM_S_WEIGHT, 0x2},
-	{OP_WR, TCM_REG_TM_WEIGHT, 0x2},
-	{OP_WR, TCM_REG_TCM_TQM_USE_Q, 0x1},
-	{OP_WR, TCM_REG_GR_ARB_TYPE, 0x1},
-	{OP_WR, TCM_REG_GR_LD0_PR, 0x1},
-	{OP_WR, TCM_REG_GR_LD1_PR, 0x2},
-	{OP_WR, TCM_REG_CFC_INIT_CRD, 0x1},
-	{OP_WR, TCM_REG_FIC0_INIT_CRD, 0x40},
-	{OP_WR, TCM_REG_FIC1_INIT_CRD, 0x40},
-	{OP_WR, TCM_REG_TQM_INIT_CRD, 0x20},
-	{OP_WR, TCM_REG_XX_INIT_CRD, 0x13},
-	{OP_WR, TCM_REG_XX_MSG_NUM, 0x20},
-	{OP_ZR, TCM_REG_XX_TABLE, 0xa},
-	{OP_SW, TCM_REG_XX_DESCR_TABLE, 0x200000},
-	{OP_WR, TCM_REG_N_SM_CTX_LD_0, 0x7},
-	{OP_WR, TCM_REG_N_SM_CTX_LD_1, 0x7},
-	{OP_WR, TCM_REG_N_SM_CTX_LD_2, 0x8},
-	{OP_WR, TCM_REG_N_SM_CTX_LD_3, 0x8},
-	{OP_ZR_E1, TCM_REG_N_SM_CTX_LD_4, 0x4},
-	{OP_WR_E1H, TCM_REG_N_SM_CTX_LD_4, 0x1},
-	{OP_ZR_E1H, TCM_REG_N_SM_CTX_LD_5, 0x3},
-	{OP_WR, TCM_REG_TCM_REG0_SZ, 0x6},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM0_0, 0xd},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM0_1, 0x2d},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM1_0, 0x7},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM1_1, 0x27},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM2_0, 0x7},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM2_1, 0x27},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM3_0, 0x7},
-	{OP_WR_E1, TCM_REG_PHYS_QNUM3_1, 0x27},
-	{OP_WR, TCM_REG_TCM_STORM0_IFEN, 0x1},
-	{OP_WR, TCM_REG_TCM_STORM1_IFEN, 0x1},
-	{OP_WR, TCM_REG_TCM_TQM_IFEN, 0x1},
-	{OP_WR, TCM_REG_STORM_TCM_IFEN, 0x1},
-	{OP_WR, TCM_REG_TQM_TCM_IFEN, 0x1},
-	{OP_WR, TCM_REG_TSDM_IFEN, 0x1},
-	{OP_WR, TCM_REG_TM_TCM_IFEN, 0x1},
-	{OP_WR, TCM_REG_PRS_IFEN, 0x1},
-	{OP_WR, TCM_REG_PBF_IFEN, 0x1},
-	{OP_WR, TCM_REG_USEM_IFEN, 0x1},
-	{OP_WR, TCM_REG_CSEM_IFEN, 0x1},
-	{OP_WR, TCM_REG_CDU_AG_WR_IFEN, 0x1},
-	{OP_WR, TCM_REG_CDU_AG_RD_IFEN, 0x1},
-	{OP_WR, TCM_REG_CDU_SM_WR_IFEN, 0x1},
-	{OP_WR, TCM_REG_CDU_SM_RD_IFEN, 0x1},
-	{OP_WR, TCM_REG_TCM_CFC_IFEN, 0x1},
-#define TCM_COMMON_END          159
-#define TCM_FUNC0_START         159
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0xd},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x7},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x7},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x7},
-#define TCM_FUNC0_END           163
-#define TCM_FUNC1_START         163
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x2d},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x27},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x27},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x27},
-#define TCM_FUNC1_END           167
-#define TCM_FUNC2_START         167
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x1d},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x17},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x17},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x17},
-#define TCM_FUNC2_END           171
-#define TCM_FUNC3_START         171
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x3d},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x37},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x37},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x37},
-#define TCM_FUNC3_END           175
-#define TCM_FUNC4_START         175
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x4d},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x47},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x47},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x47},
-#define TCM_FUNC4_END           179
-#define TCM_FUNC5_START         179
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x6d},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x67},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x67},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x67},
-#define TCM_FUNC5_END           183
-#define TCM_FUNC6_START         183
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_0, 0x5d},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_0, 0x57},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_0, 0x57},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_0, 0x57},
-#define TCM_FUNC6_END           187
-#define TCM_FUNC7_START         187
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM0_1, 0x7d},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM1_1, 0x77},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM2_1, 0x77},
-	{OP_WR_E1H, TCM_REG_PHYS_QNUM3_1, 0x77},
-#define TCM_FUNC7_END           191
-#define BRB1_COMMON_START       191
-	{OP_SW, BRB1_REG_LL_RAM, 0x2000020},
-	{OP_WR, BRB1_REG_SOFT_RESET, 0x1},
-	{OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_4, 0x0},
-	{OP_SW, BRB1_REG_FREE_LIST_PRS_CRDT, 0x30220},
-	{OP_WR, BRB1_REG_SOFT_RESET, 0x0},
-#define BRB1_COMMON_END         196
-#define BRB1_PORT0_START        196
-	{OP_WR_E1, BRB1_REG_PAUSE_LOW_THRESHOLD_0, 0xb8},
-	{OP_WR_E1, BRB1_REG_PAUSE_HIGH_THRESHOLD_0, 0x114},
-	{OP_RD, BRB1_REG_NUM_OF_PAUSE_CYCLES_0, 0x0},
-	{OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_0, 0x0},
-#define BRB1_PORT0_END          200
-#define BRB1_PORT1_START        200
-	{OP_WR_E1, BRB1_REG_PAUSE_LOW_THRESHOLD_1, 0xb8},
-	{OP_WR_E1, BRB1_REG_PAUSE_HIGH_THRESHOLD_1, 0x114},
-	{OP_RD, BRB1_REG_NUM_OF_PAUSE_CYCLES_1, 0x0},
-	{OP_RD, BRB1_REG_NUM_OF_FULL_CYCLES_1, 0x0},
-#define BRB1_PORT1_END          204
-#define TSEM_COMMON_START       204
-	{OP_RD, TSEM_REG_MSG_NUM_FIC0, 0x0},
-	{OP_RD, TSEM_REG_MSG_NUM_FIC1, 0x0},
-	{OP_RD, TSEM_REG_MSG_NUM_FOC0, 0x0},
-	{OP_RD, TSEM_REG_MSG_NUM_FOC1, 0x0},
-	{OP_RD, TSEM_REG_MSG_NUM_FOC2, 0x0},
-	{OP_RD, TSEM_REG_MSG_NUM_FOC3, 0x0},
-	{OP_WR, TSEM_REG_ARB_ELEMENT0, 0x1},
-	{OP_WR, TSEM_REG_ARB_ELEMENT1, 0x2},
-	{OP_WR, TSEM_REG_ARB_ELEMENT2, 0x3},
-	{OP_WR, TSEM_REG_ARB_ELEMENT3, 0x0},
-	{OP_WR, TSEM_REG_ARB_ELEMENT4, 0x4},
-	{OP_WR, TSEM_REG_ARB_CYCLE_SIZE, 0x1},
-	{OP_WR, TSEM_REG_TS_0_AS, 0x0},
-	{OP_WR, TSEM_REG_TS_1_AS, 0x1},
-	{OP_WR, TSEM_REG_TS_2_AS, 0x4},
-	{OP_WR, TSEM_REG_TS_3_AS, 0x0},
-	{OP_WR, TSEM_REG_TS_4_AS, 0x1},
-	{OP_WR, TSEM_REG_TS_5_AS, 0x3},
-	{OP_WR, TSEM_REG_TS_6_AS, 0x0},
-	{OP_WR, TSEM_REG_TS_7_AS, 0x1},
-	{OP_WR, TSEM_REG_TS_8_AS, 0x4},
-	{OP_WR, TSEM_REG_TS_9_AS, 0x0},
-	{OP_WR, TSEM_REG_TS_10_AS, 0x1},
-	{OP_WR, TSEM_REG_TS_11_AS, 0x3},
-	{OP_WR, TSEM_REG_TS_12_AS, 0x0},
-	{OP_WR, TSEM_REG_TS_13_AS, 0x1},
-	{OP_WR, TSEM_REG_TS_14_AS, 0x4},
-	{OP_WR, TSEM_REG_TS_15_AS, 0x0},
-	{OP_WR, TSEM_REG_TS_16_AS, 0x4},
-	{OP_WR, TSEM_REG_TS_17_AS, 0x3},
-	{OP_ZR, TSEM_REG_TS_18_AS, 0x2},
-	{OP_WR, TSEM_REG_ENABLE_IN, 0x3fff},
-	{OP_WR, TSEM_REG_ENABLE_OUT, 0x3ff},
-	{OP_WR, TSEM_REG_FIC0_DISABLE, 0x0},
-	{OP_WR, TSEM_REG_FIC1_DISABLE, 0x0},
-	{OP_WR, TSEM_REG_PAS_DISABLE, 0x0},
-	{OP_WR, TSEM_REG_THREADS_LIST, 0xff},
-	{OP_ZR, TSEM_REG_PASSIVE_BUFFER, 0x400},
-	{OP_WR, TSEM_REG_FAST_MEMORY + 0x18bc0, 0x1},
-	{OP_WR, TSEM_REG_FAST_MEMORY + 0x18000, 0x34},
-	{OP_WR, TSEM_REG_FAST_MEMORY + 0x18040, 0x18},
-	{OP_WR, TSEM_REG_FAST_MEMORY + 0x18080, 0xc},
-	{OP_WR, TSEM_REG_FAST_MEMORY + 0x180c0, 0x20},
-	{OP_WR_ASIC, TSEM_REG_FAST_MEMORY + 0x18300, 0x7a120},
-	{OP_WR_EMUL, TSEM_REG_FAST_MEMORY + 0x18300, 0x138},
-	{OP_WR_FPGA, TSEM_REG_FAST_MEMORY + 0x18300, 0x1388},
-	{OP_WR, TSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2000, 0xb2},
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x11480, 0x1},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x23c8, 0xc1},
-	{OP_WR_EMUL_E1H, TSEM_REG_FAST_MEMORY + 0x11480, 0x0},
-	{OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x23c8 + 0x304, 0x10223},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x1000, 0x2b3},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1020, 0xc8},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x1000 + 0xacc, 0x10223},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1000, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xa020, 0xc8},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1c18, 0x4},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xa000, 0x2},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1c10, 0x2},
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x1ad0, 0x0},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x800, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x1ad8, 0x4},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x808, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3678, 0x6},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x810, 0x4},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3670, 0x2},
-	{OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb0, 0x40224},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5000, 0x2},
-	{OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x4cb0, 0x80228},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5008, 0x4},
-	{OP_ZP_E1, TSEM_REG_INT_TABLE, 0x930000},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5018, 0x4},
-	{OP_WR_64_E1, TSEM_REG_INT_TABLE + 0x360, 0x140230},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5028, 0x4},
-	{OP_ZP_E1, TSEM_REG_PRAM, 0x324f0000},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5038, 0x4},
-	{OP_ZP_E1, TSEM_REG_PRAM + 0x8000, 0x33250c94},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5048, 0x4},
-	{OP_ZP_E1, TSEM_REG_PRAM + 0x10000, 0xe4d195e},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5058, 0x4},
-	{OP_WR_64_E1, TSEM_REG_PRAM + 0x11e00, 0x5c400232},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5068, 0x4},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5078, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4000, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4008, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x62c0, 0x200224},
-	{OP_ZP_E1H, TSEM_REG_INT_TABLE, 0x9b0000},
-	{OP_WR_64_E1H, TSEM_REG_INT_TABLE + 0x398, 0xd0244},
-	{OP_ZP_E1H, TSEM_REG_PRAM, 0x325e0000},
-	{OP_ZP_E1H, TSEM_REG_PRAM + 0x8000, 0x35960c98},
-	{OP_ZP_E1H, TSEM_REG_PRAM + 0x10000, 0x1aea19fe},
-	{OP_WR_64_E1H, TSEM_REG_PRAM + 0x143d0, 0x57860246},
-#define TSEM_COMMON_END         297
-#define TSEM_PORT0_START        297
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x22c8, 0x20},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x2000, 0x16c},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x4000, 0x16c},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb000, 0x28},
-	{OP_WR_E1, TSEM_REG_FAST_MEMORY + 0x4b60, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb140, 0xc},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1400, 0xa},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x32c0, 0x12},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1450, 0x6},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3350, 0x64},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1500, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x8108, 0x2},
-	{OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1500 + 0x8, 0x50234},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1500 + 0x1c, 0x7},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1570, 0x12},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x9c0, 0x4c},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x800, 0x2},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x820, 0xe},
-	{OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb0, 0x20239},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2908, 0x2},
-#define TSEM_PORT0_END          317
-#define TSEM_PORT1_START        317
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2348, 0x20},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x25b0, 0x16c},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x45b0, 0x16c},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb0a0, 0x28},
-	{OP_WR_E1, TSEM_REG_FAST_MEMORY + 0x4b64, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0xb170, 0xc},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1428, 0xa},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3308, 0x12},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1468, 0x6},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x34e0, 0x64},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1538, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x8110, 0x2},
-	{OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1538 + 0x8, 0x5023b},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x1538 + 0x1c, 0x7},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x15b8, 0x12},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0xaf0, 0x4c},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x808, 0x2},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x858, 0xe},
-	{OP_SW_E1, TSEM_REG_FAST_MEMORY + 0x1fb8, 0x20240},
-	{OP_ZR_E1, TSEM_REG_FAST_MEMORY + 0x2910, 0x2},
-#define TSEM_PORT1_END          337
-#define TSEM_FUNC0_START        337
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b60, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3000, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3000 + 0x8, 0x50248},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3000 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x31c0, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5000, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5080, 0x12},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4000, 0x2},
-#define TSEM_FUNC0_END          345
-#define TSEM_FUNC1_START        345
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b64, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3038, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3038 + 0x8, 0x5024d},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3038 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x31e0, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5010, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x50c8, 0x12},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x4008, 0x2},
-#define TSEM_FUNC1_END          353
-#define TSEM_FUNC2_START        353
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b68, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3070, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3070 + 0x8, 0x50252},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3070 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3200, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5020, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5110, 0x12},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4010, 0x20257},
-#define TSEM_FUNC2_END          361
-#define TSEM_FUNC3_START        361
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b6c, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30a8, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x30a8 + 0x8, 0x50259},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30a8 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3220, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5030, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5158, 0x12},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4018, 0x2025e},
-#define TSEM_FUNC3_END          369
-#define TSEM_FUNC4_START        369
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b70, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30e0, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x30e0 + 0x8, 0x50260},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x30e0 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3240, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5040, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x51a0, 0x12},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4020, 0x20265},
-#define TSEM_FUNC4_END          377
-#define TSEM_FUNC5_START        377
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b74, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3118, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3118 + 0x8, 0x50267},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3118 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3260, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5050, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x51e8, 0x12},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4028, 0x2026c},
-#define TSEM_FUNC5_END          385
-#define TSEM_FUNC6_START        385
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b78, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3150, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3150 + 0x8, 0x5026e},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3150 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3280, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5060, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5230, 0x12},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4030, 0x20273},
-#define TSEM_FUNC6_END          393
-#define TSEM_FUNC7_START        393
-	{OP_WR_E1H, TSEM_REG_FAST_MEMORY + 0x2b7c, 0x0},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3188, 0x2},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x3188 + 0x8, 0x50275},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x3188 + 0x1c, 0x7},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x32a0, 0x8},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5070, 0x2},
-	{OP_ZR_E1H, TSEM_REG_FAST_MEMORY + 0x5278, 0x12},
-	{OP_SW_E1H, TSEM_REG_FAST_MEMORY + 0x4038, 0x2027a},
-#define TSEM_FUNC7_END          401
-#define MISC_COMMON_START       401
-	{OP_WR_E1, MISC_REG_GRC_TIMEOUT_EN, 0x1},
-	{OP_WR, MISC_REG_PLL_STORM_CTRL_1, 0x71d2911},
-	{OP_WR, MISC_REG_PLL_STORM_CTRL_2, 0x0},
-	{OP_WR, MISC_REG_PLL_STORM_CTRL_3, 0x9c0424},
-	{OP_WR, MISC_REG_PLL_STORM_CTRL_4, 0x0},
-	{OP_WR, MISC_REG_LCPLL_CTRL_1, 0x209},
-	{OP_WR_E1, MISC_REG_SPIO, 0xff000000},
-#define MISC_COMMON_END         408
-#define MISC_FUNC0_START        408
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0},
-#define MISC_FUNC0_END          409
-#define MISC_FUNC1_START        409
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0},
-#define MISC_FUNC1_END          410
-#define MISC_FUNC2_START        410
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0},
-#define MISC_FUNC2_END          411
-#define MISC_FUNC3_START        411
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0},
-#define MISC_FUNC3_END          412
-#define MISC_FUNC4_START        412
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0},
-#define MISC_FUNC4_END          413
-#define MISC_FUNC5_START        413
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0},
-#define MISC_FUNC5_END          414
-#define MISC_FUNC6_START        414
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P0, 0x0},
-#define MISC_FUNC6_END          415
-#define MISC_FUNC7_START        415
-	{OP_WR_E1H, MISC_REG_NIG_WOL_P1, 0x0},
-#define MISC_FUNC7_END          416
-#define NIG_COMMON_START        416
-	{OP_WR, NIG_REG_PBF_LB_IN_EN, 0x1},
-	{OP_WR, NIG_REG_PRS_REQ_IN_EN, 0x1},
-	{OP_WR, NIG_REG_EGRESS_DEBUG_IN_EN, 0x1},
-	{OP_WR, NIG_REG_BRB_LB_OUT_EN, 0x1},
-	{OP_WR, NIG_REG_PRS_EOP_OUT_EN, 0x1},
-#define NIG_COMMON_END          421
-#define NIG_PORT0_START         421
-	{OP_WR, NIG_REG_LLH0_CM_HEADER, 0x300000},
-	{OP_WR, NIG_REG_LLH0_EVENT_ID, 0x28},
-	{OP_WR, NIG_REG_LLH0_ERROR_MASK, 0x0},
-	{OP_WR, NIG_REG_LLH0_XCM_MASK, 0x4},
-	{OP_WR, NIG_REG_LLH0_BRB1_NOT_MCP, 0x1},
-	{OP_WR, NIG_REG_STATUS_INTERRUPT_PORT0, 0x0},
-	{OP_WR_E1H, NIG_REG_LLH0_CLS_TYPE, 0x1},
-	{OP_WR, NIG_REG_LLH0_XCM_INIT_CREDIT, 0x30},
-	{OP_WR, NIG_REG_BRB0_PAUSE_IN_EN, 0x1},
-	{OP_WR, NIG_REG_EGRESS_PBF0_IN_EN, 0x1},
-	{OP_WR, NIG_REG_BRB0_OUT_EN, 0x1},
-	{OP_WR, NIG_REG_XCM0_OUT_EN, 0x1},
-#define NIG_PORT0_END           433
-#define NIG_PORT1_START         433
-	{OP_WR, NIG_REG_LLH1_CM_HEADER, 0x300000},
-	{OP_WR, NIG_REG_LLH1_EVENT_ID, 0x28},
-	{OP_WR, NIG_REG_LLH1_ERROR_MASK, 0x0},
-	{OP_WR, NIG_REG_LLH1_XCM_MASK, 0x4},
-	{OP_WR, NIG_REG_LLH1_BRB1_NOT_MCP, 0x1},
-	{OP_WR, NIG_REG_STATUS_INTERRUPT_PORT1, 0x0},
-	{OP_WR_E1H, NIG_REG_LLH1_CLS_TYPE, 0x1},
-	{OP_WR, NIG_REG_LLH1_XCM_INIT_CREDIT, 0x30},
-	{OP_WR, NIG_REG_BRB1_PAUSE_IN_EN, 0x1},
-	{OP_WR, NIG_REG_EGRESS_PBF1_IN_EN, 0x1},
-	{OP_WR, NIG_REG_BRB1_OUT_EN, 0x1},
-	{OP_WR, NIG_REG_XCM1_OUT_EN, 0x1},
-#define NIG_PORT1_END           445
-#define UPB_COMMON_START        445
-	{OP_WR, GRCBASE_UPB + PB_REG_CONTROL, 0x20},
-#define UPB_COMMON_END          446
-#define CSDM_COMMON_START       446
-	{OP_WR_E1, CSDM_REG_CFC_RSP_START_ADDR, 0xa11},
-	{OP_WR_E1H, CSDM_REG_CFC_RSP_START_ADDR, 0x211},
-	{OP_WR_E1, CSDM_REG_CMP_COUNTER_START_ADDR, 0xa00},
-	{OP_WR_E1H, CSDM_REG_CMP_COUNTER_START_ADDR, 0x200},
-	{OP_WR_E1, CSDM_REG_Q_COUNTER_START_ADDR, 0xa04},
-	{OP_WR_E1H, CSDM_REG_Q_COUNTER_START_ADDR, 0x204},
-	{OP_WR, CSDM_REG_CMP_COUNTER_MAX0, 0xffff},
-	{OP_WR, CSDM_REG_CMP_COUNTER_MAX1, 0xffff},
-	{OP_WR, CSDM_REG_CMP_COUNTER_MAX2, 0xffff},
-	{OP_WR, CSDM_REG_CMP_COUNTER_MAX3, 0xffff},
-	{OP_WR, CSDM_REG_AGG_INT_EVENT_0, 0xc6},
-	{OP_WR, CSDM_REG_AGG_INT_EVENT_1, 0x0},
-	{OP_WR, CSDM_REG_AGG_INT_EVENT_2, 0x34},
-	{OP_WR, CSDM_REG_AGG_INT_EVENT_3, 0x35},
-	{OP_ZR, CSDM_REG_AGG_INT_EVENT_4, 0x1c},
-	{OP_WR, CSDM_REG_AGG_INT_T_0, 0x1},
-	{OP_ZR, CSDM_REG_AGG_INT_T_1, 0x5f},
-	{OP_WR, CSDM_REG_ENABLE_IN1, 0x7ffffff},
-	{OP_WR, CSDM_REG_ENABLE_IN2, 0x3f},
-	{OP_WR, CSDM_REG_ENABLE_OUT1, 0x7ffffff},
-	{OP_WR, CSDM_REG_ENABLE_OUT2, 0xf},
-	{OP_RD, CSDM_REG_NUM_OF_Q0_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q1_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q3_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q4_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q5_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q6_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q7_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q8_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q9_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q10_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_Q11_CMD, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_PKT_END_MSG, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0},
-	{OP_RD, CSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0},
-	{OP_WR_E1, CSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1},
-	{OP_WR_ASIC, CSDM_REG_TIMER_TICK, 0x3e8},
-	{OP_WR_EMUL, CSDM_REG_TIMER_TICK, 0x1},
-	{OP_WR_FPGA, CSDM_REG_TIMER_TICK, 0xa},
-#define CSDM_COMMON_END         485
-#define USDM_COMMON_START       485
-	{OP_WR_E1, USDM_REG_CFC_RSP_START_ADDR, 0xa11},
-	{OP_WR_E1H, USDM_REG_CFC_RSP_START_ADDR, 0x411},
-	{OP_WR_E1, USDM_REG_CMP_COUNTER_START_ADDR, 0xa00},
-	{OP_WR_E1H, USDM_REG_CMP_COUNTER_START_ADDR, 0x400},
-	{OP_WR_E1, USDM_REG_Q_COUNTER_START_ADDR, 0xa04},
-	{OP_WR_E1H, USDM_REG_Q_COUNTER_START_ADDR, 0x404},
-	{OP_WR_E1, USDM_REG_PCK_END_MSG_START_ADDR, 0xa21},
-	{OP_WR_E1H, USDM_REG_PCK_END_MSG_START_ADDR, 0x421},
-	{OP_WR, USDM_REG_CMP_COUNTER_MAX0, 0xffff},
-	{OP_WR, USDM_REG_CMP_COUNTER_MAX1, 0xffff},
-	{OP_WR, USDM_REG_CMP_COUNTER_MAX2, 0xffff},
-	{OP_WR, USDM_REG_CMP_COUNTER_MAX3, 0xffff},
-	{OP_WR, USDM_REG_AGG_INT_EVENT_0, 0x46},
-	{OP_WR, USDM_REG_AGG_INT_EVENT_1, 0x5},
-	{OP_WR, USDM_REG_AGG_INT_EVENT_2, 0x34},
-	{OP_WR, USDM_REG_AGG_INT_EVENT_3, 0x35},
-	{OP_ZR_E1, USDM_REG_AGG_INT_EVENT_4, 0x5c},
-	{OP_WR_E1H, USDM_REG_AGG_INT_EVENT_4, 0x7},
-	{OP_ZR_E1H, USDM_REG_AGG_INT_EVENT_5, 0x5b},
-	{OP_WR, USDM_REG_AGG_INT_MODE_0, 0x1},
-	{OP_ZR_E1, USDM_REG_AGG_INT_MODE_1, 0x1f},
-	{OP_ZR_E1H, USDM_REG_AGG_INT_MODE_1, 0x3},
-	{OP_WR_E1H, USDM_REG_AGG_INT_MODE_4, 0x1},
-	{OP_ZR_E1H, USDM_REG_AGG_INT_MODE_5, 0x1b},
-	{OP_WR, USDM_REG_ENABLE_IN1, 0x7ffffff},
-	{OP_WR, USDM_REG_ENABLE_IN2, 0x3f},
-	{OP_WR, USDM_REG_ENABLE_OUT1, 0x7ffffff},
-	{OP_WR, USDM_REG_ENABLE_OUT2, 0xf},
-	{OP_RD, USDM_REG_NUM_OF_Q0_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q1_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q2_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q3_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q4_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q5_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q6_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q7_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q8_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q9_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q10_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_Q11_CMD, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_PKT_END_MSG, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0},
-	{OP_RD, USDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0},
-	{OP_WR_E1, USDM_REG_INIT_CREDIT_PXP_CTRL, 0x1},
-	{OP_WR_ASIC, USDM_REG_TIMER_TICK, 0x3e8},
-	{OP_WR_EMUL, USDM_REG_TIMER_TICK, 0x1},
-	{OP_WR_FPGA, USDM_REG_TIMER_TICK, 0xa},
-#define USDM_COMMON_END         532
-#define CCM_COMMON_START        532
-	{OP_WR, CCM_REG_XX_OVFL_EVNT_ID, 0x32},
-	{OP_WR, CCM_REG_CQM_CCM_HDR_P, 0x2150020},
-	{OP_WR, CCM_REG_CQM_CCM_HDR_S, 0x2150020},
-	{OP_WR, CCM_REG_ERR_CCM_HDR, 0x8100000},
-	{OP_WR, CCM_REG_ERR_EVNT_ID, 0x33},
-	{OP_WR, CCM_REG_STORM_WEIGHT, 0x2},
-	{OP_WR, CCM_REG_TSEM_WEIGHT, 0x0},
-	{OP_WR, CCM_REG_XSEM_WEIGHT, 0x5},
-	{OP_WR, CCM_REG_USEM_WEIGHT, 0x5},
-	{OP_ZR, CCM_REG_PBF_WEIGHT, 0x2},
-	{OP_WR, CCM_REG_CSDM_WEIGHT, 0x2},
-	{OP_WR, CCM_REG_CQM_P_WEIGHT, 0x3},
-	{OP_WR, CCM_REG_CQM_S_WEIGHT, 0x2},
-	{OP_WR, CCM_REG_CCM_CQM_USE_Q, 0x1},
-	{OP_WR, CCM_REG_CNT_AUX1_Q, 0x2},
-	{OP_WR, CCM_REG_CNT_AUX2_Q, 0x2},
-	{OP_WR, CCM_REG_INV_DONE_Q, 0x1},
-	{OP_WR, CCM_REG_GR_ARB_TYPE, 0x1},
-	{OP_WR, CCM_REG_GR_LD0_PR, 0x1},
-	{OP_WR, CCM_REG_GR_LD1_PR, 0x2},
-	{OP_WR, CCM_REG_CFC_INIT_CRD, 0x1},
-	{OP_WR, CCM_REG_CQM_INIT_CRD, 0x20},
-	{OP_WR, CCM_REG_FIC0_INIT_CRD, 0x40},
-	{OP_WR, CCM_REG_FIC1_INIT_CRD, 0x40},
-	{OP_WR, CCM_REG_XX_INIT_CRD, 0x3},
-	{OP_WR, CCM_REG_XX_MSG_NUM, 0x18},
-	{OP_ZR, CCM_REG_XX_TABLE, 0x12},
-	{OP_SW_E1, CCM_REG_XX_DESCR_TABLE, 0x240242},
-	{OP_SW_E1H, CCM_REG_XX_DESCR_TABLE, 0x24027c},
-	{OP_WR, CCM_REG_N_SM_CTX_LD_0, 0x1},
-	{OP_WR, CCM_REG_N_SM_CTX_LD_1, 0x2},
-	{OP_WR, CCM_REG_N_SM_CTX_LD_2, 0x8},
-	{OP_WR, CCM_REG_N_SM_CTX_LD_3, 0x8},
-	{OP_ZR, CCM_REG_N_SM_CTX_LD_4, 0x4},
-	{OP_WR, CCM_REG_CCM_REG0_SZ, 0x4},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM0_0, 0x9},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM0_1, 0x29},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM1_0, 0xa},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM1_1, 0x2a},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM2_0, 0x7},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM2_1, 0x27},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM3_0, 0x7},
-	{OP_WR_E1, CCM_REG_QOS_PHYS_QNUM3_1, 0x27},
-	{OP_WR_E1, CCM_REG_PHYS_QNUM1_0, 0xc},
-	{OP_WR_E1, CCM_REG_PHYS_QNUM1_1, 0x2c},
-	{OP_WR_E1, CCM_REG_PHYS_QNUM2_0, 0xc},
-	{OP_WR_E1, CCM_REG_PHYS_QNUM2_1, 0x2c},
-	{OP_WR_E1, CCM_REG_PHYS_QNUM3_0, 0xc},
-	{OP_WR_E1, CCM_REG_PHYS_QNUM3_1, 0x2c},
-	{OP_WR, CCM_REG_CCM_STORM0_IFEN, 0x1},
-	{OP_WR, CCM_REG_CCM_STORM1_IFEN, 0x1},
-	{OP_WR, CCM_REG_CCM_CQM_IFEN, 0x1},
-	{OP_WR, CCM_REG_STORM_CCM_IFEN, 0x1},
-	{OP_WR, CCM_REG_CQM_CCM_IFEN, 0x1},
-	{OP_WR, CCM_REG_CSDM_IFEN, 0x1},
-	{OP_WR, CCM_REG_TSEM_IFEN, 0x1},
-	{OP_WR, CCM_REG_XSEM_IFEN, 0x1},
-	{OP_WR, CCM_REG_USEM_IFEN, 0x1},
-	{OP_WR, CCM_REG_PBF_IFEN, 0x1},
-	{OP_WR, CCM_REG_CDU_AG_WR_IFEN, 0x1},
-	{OP_WR, CCM_REG_CDU_AG_RD_IFEN, 0x1},
-	{OP_WR, CCM_REG_CDU_SM_WR_IFEN, 0x1},
-	{OP_WR, CCM_REG_CDU_SM_RD_IFEN, 0x1},
-	{OP_WR, CCM_REG_CCM_CFC_IFEN, 0x1},
-#define CCM_COMMON_END          596
-#define CCM_FUNC0_START         596
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x9},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0xa},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x7},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x7},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0xc},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0xb},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x7},
-#define CCM_FUNC0_END           603
-#define CCM_FUNC1_START         603
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x29},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x2a},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x27},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x27},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x2c},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x2b},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x27},
-#define CCM_FUNC1_END           610
-#define CCM_FUNC2_START         610
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x19},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x1a},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x17},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x17},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x1c},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x1b},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x17},
-#define CCM_FUNC2_END           617
-#define CCM_FUNC3_START         617
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x39},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x3a},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x37},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x37},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x3c},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x3b},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x37},
-#define CCM_FUNC3_END           624
-#define CCM_FUNC4_START         624
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x49},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x4a},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x47},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x47},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x4c},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x4b},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x47},
-#define CCM_FUNC4_END           631
-#define CCM_FUNC5_START         631
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x69},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x6a},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x67},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x67},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x6c},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x6b},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x67},
-#define CCM_FUNC5_END           638
-#define CCM_FUNC6_START         638
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_0, 0x59},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_0, 0x5a},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_0, 0x57},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_0, 0x57},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_0, 0x5c},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_0, 0x5b},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_0, 0x57},
-#define CCM_FUNC6_END           645
-#define CCM_FUNC7_START         645
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM0_1, 0x79},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM1_1, 0x7a},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM2_1, 0x77},
-	{OP_WR_E1H, CCM_REG_QOS_PHYS_QNUM3_1, 0x77},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM1_1, 0x7c},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM2_1, 0x7b},
-	{OP_WR_E1H, CCM_REG_PHYS_QNUM3_1, 0x77},
-#define CCM_FUNC7_END           652
-#define UCM_COMMON_START        652
-	{OP_WR, UCM_REG_XX_OVFL_EVNT_ID, 0x32},
-	{OP_WR, UCM_REG_UQM_UCM_HDR_P, 0x2150020},
-	{OP_WR, UCM_REG_UQM_UCM_HDR_S, 0x2150020},
-	{OP_WR, UCM_REG_TM_UCM_HDR, 0x30},
-	{OP_WR, UCM_REG_ERR_UCM_HDR, 0x8100000},
-	{OP_WR, UCM_REG_ERR_EVNT_ID, 0x33},
-	{OP_WR, UCM_REG_EXPR_EVNT_ID, 0x30},
-	{OP_WR, UCM_REG_STOP_EVNT_ID, 0x31},
-	{OP_WR, UCM_REG_STORM_WEIGHT, 0x2},
-	{OP_WR, UCM_REG_TSEM_WEIGHT, 0x4},
-	{OP_WR, UCM_REG_CSEM_WEIGHT, 0x0},
-	{OP_WR, UCM_REG_XSEM_WEIGHT, 0x2},
-	{OP_WR, UCM_REG_DORQ_WEIGHT, 0x2},
-	{OP_WR, UCM_REG_CP_WEIGHT, 0x0},
-	{OP_WR, UCM_REG_USDM_WEIGHT, 0x2},
-	{OP_WR, UCM_REG_UQM_P_WEIGHT, 0x7},
-	{OP_WR, UCM_REG_UQM_S_WEIGHT, 0x2},
-	{OP_WR, UCM_REG_TM_WEIGHT, 0x2},
-	{OP_WR, UCM_REG_UCM_UQM_USE_Q, 0x1},
-	{OP_WR, UCM_REG_INV_CFLG_Q, 0x1},
-	{OP_WR, UCM_REG_GR_ARB_TYPE, 0x1},
-	{OP_WR, UCM_REG_GR_LD0_PR, 0x1},
-	{OP_WR, UCM_REG_GR_LD1_PR, 0x2},
-	{OP_WR, UCM_REG_CFC_INIT_CRD, 0x1},
-	{OP_WR, UCM_REG_FIC0_INIT_CRD, 0x40},
-	{OP_WR, UCM_REG_FIC1_INIT_CRD, 0x40},
-	{OP_WR, UCM_REG_TM_INIT_CRD, 0x4},
-	{OP_WR, UCM_REG_UQM_INIT_CRD, 0x20},
-	{OP_WR, UCM_REG_XX_INIT_CRD, 0xe},
-	{OP_WR, UCM_REG_XX_MSG_NUM, 0x1b},
-	{OP_ZR, UCM_REG_XX_TABLE, 0x12},
-	{OP_SW_E1, UCM_REG_XX_DESCR_TABLE, 0x1b0266},
-	{OP_SW_E1H, UCM_REG_XX_DESCR_TABLE, 0x1b02a0},
-	{OP_WR, UCM_REG_N_SM_CTX_LD_0, 0x10},
-	{OP_WR, UCM_REG_N_SM_CTX_LD_1, 0x7},
-	{OP_WR, UCM_REG_N_SM_CTX_LD_2, 0xf},
-	{OP_WR, UCM_REG_N_SM_CTX_LD_3, 0x10},
-	{OP_ZR_E1, UCM_REG_N_SM_CTX_LD_4, 0x4},
-	{OP_WR_E1H, UCM_REG_N_SM_CTX_LD_4, 0xb},
-	{OP_ZR_E1H, UCM_REG_N_SM_CTX_LD_5, 0x3},
-	{OP_WR, UCM_REG_UCM_REG0_SZ, 0x3},
-	{OP_WR_E1, UCM_REG_PHYS_QNUM0_0, 0xf},
-	{OP_WR_E1, UCM_REG_PHYS_QNUM0_1, 0x2f},
-	{OP_WR_E1, UCM_REG_PHYS_QNUM1_0, 0xe},
-	{OP_WR_E1, UCM_REG_PHYS_QNUM1_1, 0x2e},
-	{OP_WR, UCM_REG_UCM_STORM0_IFEN, 0x1},
-	{OP_WR, UCM_REG_UCM_STORM1_IFEN, 0x1},
-	{OP_WR, UCM_REG_UCM_UQM_IFEN, 0x1},
-	{OP_WR, UCM_REG_STORM_UCM_IFEN, 0x1},
-	{OP_WR, UCM_REG_UQM_UCM_IFEN, 0x1},
-	{OP_WR, UCM_REG_USDM_IFEN, 0x1},
-	{OP_WR, UCM_REG_TM_UCM_IFEN, 0x1},
-	{OP_WR, UCM_REG_UCM_TM_IFEN, 0x1},
-	{OP_WR, UCM_REG_TSEM_IFEN, 0x1},
-	{OP_WR, UCM_REG_CSEM_IFEN, 0x1},
-	{OP_WR, UCM_REG_XSEM_IFEN, 0x1},
-	{OP_WR, UCM_REG_DORQ_IFEN, 0x1},
-	{OP_WR, UCM_REG_CDU_AG_WR_IFEN, 0x1},
-	{OP_WR, UCM_REG_CDU_AG_RD_IFEN, 0x1},
-	{OP_WR, UCM_REG_CDU_SM_WR_IFEN, 0x1},
-	{OP_WR, UCM_REG_CDU_SM_RD_IFEN, 0x1},
-	{OP_WR, UCM_REG_UCM_CFC_IFEN, 0x1},
-#define UCM_COMMON_END          714
-#define UCM_FUNC0_START         714
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0xf},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0xe},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0},
-#define UCM_FUNC0_END           718
-#define UCM_FUNC1_START         718
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x2f},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x2e},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0},
-#define UCM_FUNC1_END           722
-#define UCM_FUNC2_START         722
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x1f},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x1e},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0},
-#define UCM_FUNC2_END           726
-#define UCM_FUNC3_START         726
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x3f},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x3e},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0},
-#define UCM_FUNC3_END           730
-#define UCM_FUNC4_START         730
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x4f},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x4e},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0},
-#define UCM_FUNC4_END           734
-#define UCM_FUNC5_START         734
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x6f},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x6e},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0},
-#define UCM_FUNC5_END           738
-#define UCM_FUNC6_START         738
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_0, 0x5f},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_0, 0x5e},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_0, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_0, 0x0},
-#define UCM_FUNC6_END           742
-#define UCM_FUNC7_START         742
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM0_1, 0x7f},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM1_1, 0x7e},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM2_1, 0x0},
-	{OP_WR_E1H, UCM_REG_PHYS_QNUM3_1, 0x0},
-#define UCM_FUNC7_END           746
-#define USEM_COMMON_START       746
-	{OP_RD, USEM_REG_MSG_NUM_FIC0, 0x0},
-	{OP_RD, USEM_REG_MSG_NUM_FIC1, 0x0},
-	{OP_RD, USEM_REG_MSG_NUM_FOC0, 0x0},
-	{OP_RD, USEM_REG_MSG_NUM_FOC1, 0x0},
-	{OP_RD, USEM_REG_MSG_NUM_FOC2, 0x0},
-	{OP_RD, USEM_REG_MSG_NUM_FOC3, 0x0},
-	{OP_WR, USEM_REG_ARB_ELEMENT0, 0x1},
-	{OP_WR, USEM_REG_ARB_ELEMENT1, 0x2},
-	{OP_WR, USEM_REG_ARB_ELEMENT2, 0x3},
-	{OP_WR, USEM_REG_ARB_ELEMENT3, 0x0},
-	{OP_WR, USEM_REG_ARB_ELEMENT4, 0x4},
-	{OP_WR, USEM_REG_ARB_CYCLE_SIZE, 0x1},
-	{OP_WR, USEM_REG_TS_0_AS, 0x0},
-	{OP_WR, USEM_REG_TS_1_AS, 0x1},
-	{OP_WR, USEM_REG_TS_2_AS, 0x4},
-	{OP_WR, USEM_REG_TS_3_AS, 0x0},
-	{OP_WR, USEM_REG_TS_4_AS, 0x1},
-	{OP_WR, USEM_REG_TS_5_AS, 0x3},
-	{OP_WR, USEM_REG_TS_6_AS, 0x0},
-	{OP_WR, USEM_REG_TS_7_AS, 0x1},
-	{OP_WR, USEM_REG_TS_8_AS, 0x4},
-	{OP_WR, USEM_REG_TS_9_AS, 0x0},
-	{OP_WR, USEM_REG_TS_10_AS, 0x1},
-	{OP_WR, USEM_REG_TS_11_AS, 0x3},
-	{OP_WR, USEM_REG_TS_12_AS, 0x0},
-	{OP_WR, USEM_REG_TS_13_AS, 0x1},
-	{OP_WR, USEM_REG_TS_14_AS, 0x4},
-	{OP_WR, USEM_REG_TS_15_AS, 0x0},
-	{OP_WR, USEM_REG_TS_16_AS, 0x4},
-	{OP_WR, USEM_REG_TS_17_AS, 0x3},
-	{OP_ZR, USEM_REG_TS_18_AS, 0x2},
-	{OP_WR, USEM_REG_ENABLE_IN, 0x3fff},
-	{OP_WR, USEM_REG_ENABLE_OUT, 0x3ff},
-	{OP_WR, USEM_REG_FIC0_DISABLE, 0x0},
-	{OP_WR, USEM_REG_FIC1_DISABLE, 0x0},
-	{OP_WR, USEM_REG_PAS_DISABLE, 0x0},
-	{OP_WR, USEM_REG_THREADS_LIST, 0xffff},
-	{OP_ZR, USEM_REG_PASSIVE_BUFFER, 0x800},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x18bc0, 0x1},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x18000, 0x1a},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x18040, 0x4e},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x18080, 0x10},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x180c0, 0x20},
-	{OP_WR_ASIC, USEM_REG_FAST_MEMORY + 0x18300, 0x7a120},
-	{OP_WR_EMUL, USEM_REG_FAST_MEMORY + 0x18300, 0x138},
-	{OP_WR_FPGA, USEM_REG_FAST_MEMORY + 0x18300, 0x1388},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x183c0, 0x1f4},
-	{OP_WR_ASIC, USEM_REG_FAST_MEMORY + 0x18380, 0x1dcd6500},
-	{OP_WR_EMUL, USEM_REG_FAST_MEMORY + 0x18380, 0x4c4b4},
-	{OP_WR_FPGA, USEM_REG_FAST_MEMORY + 0x18380, 0x4c4b40},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5000, 0xc2},
-	{OP_WR_EMUL_E1H, USEM_REG_FAST_MEMORY + 0x11480, 0x0},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1020, 0xc8},
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x11480, 0x1},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1000, 0x2},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2000, 0x102},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4640, 0x40},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8980, 0xc8},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x57f0, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8960, 0x2},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x57d8, 0x5},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3228, 0x4},
-	{OP_SW_E1, USEM_REG_FAST_MEMORY + 0x57d8 + 0x14, 0x10281},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3200, 0x9},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1c60, 0x20},
-	{OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x3200 + 0x24, 0x102bb},
-	{OP_SW_E1, USEM_REG_FAST_MEMORY + 0x2830, 0x20282},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3180, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x400},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4000, 0x2},
-	{OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x4000 + 0x8, 0x102bc},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4000 + 0xc, 0x3},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b68, 0x2},
-	{OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x6b68 + 0x8, 0x202bd},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b10, 0x2},
-	{OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x74c0, 0x202bf},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x1000000},
-	{OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c00, 0x100284},
-	{OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c00, 0x1002c1},
-	{OP_WR, USEM_REG_FAST_MEMORY + 0x10800, 0x0},
-	{OP_SW_E1, USEM_REG_FAST_MEMORY + 0x10c40, 0x100294},
-	{OP_SW_E1H, USEM_REG_FAST_MEMORY + 0x10c40, 0x1002d1},
-	{OP_ZP_E1, USEM_REG_INT_TABLE, 0xc30000},
-	{OP_ZP_E1H, USEM_REG_INT_TABLE, 0xd20000},
-	{OP_WR_64_E1, USEM_REG_INT_TABLE + 0x368, 0x1302a4},
-	{OP_WR_64_E1H, USEM_REG_INT_TABLE + 0x3a8, 0xb02e1},
-	{OP_ZP_E1, USEM_REG_PRAM, 0x314c0000},
-	{OP_ZP_E1H, USEM_REG_PRAM, 0x31b60000},
-	{OP_ZP_E1, USEM_REG_PRAM + 0x8000, 0x35ef0c53},
-	{OP_ZP_E1H, USEM_REG_PRAM + 0x8000, 0x36500c6e},
-	{OP_ZP_E1, USEM_REG_PRAM + 0x10000, 0x361319cf},
-	{OP_ZP_E1H, USEM_REG_PRAM + 0x10000, 0x37591a02},
-	{OP_ZP_E1, USEM_REG_PRAM + 0x18000, 0x7112754},
-	{OP_ZP_E1H, USEM_REG_PRAM + 0x18000, 0x286127d9},
-	{OP_WR_64_E1, USEM_REG_PRAM + 0x18ee0, 0x4e2402a6},
-	{OP_WR_64_E1H, USEM_REG_PRAM + 0x1ff40, 0x401802e3},
-#define USEM_COMMON_END         842
-#define USEM_PORT0_START        842
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1400, 0xa0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9000, 0xa0},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1900, 0x10},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9500, 0x40},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1980, 0x30},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9700, 0x3c},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4740, 0xb4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2450, 0xb4},
-	{OP_WR_E1, USEM_REG_FAST_MEMORY + 0x1d90, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2ad0, 0x2},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b40, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3080, 0x20},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b60, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x8000, 0x12c},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5318, 0x98},
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x3238, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5000, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5100, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5200, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5300, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5400, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5500, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5600, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5700, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5800, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5900, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a00, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b00, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c00, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d00, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e00, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f00, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6b78, 0x52},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e08, 0xc},
-#define USEM_PORT0_END          876
-#define USEM_PORT1_START        876
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1680, 0xa0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9280, 0xa0},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1940, 0x10},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x9600, 0x40},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1a40, 0x30},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x97f0, 0x3c},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x4a10, 0xb4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2720, 0xb4},
-	{OP_WR_E1, USEM_REG_FAST_MEMORY + 0x1d94, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x2ad8, 0x2},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1b50, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3100, 0x20},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x1be0, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x84b0, 0x12c},
-	{OP_ZR_E1, USEM_REG_FAST_MEMORY + 0x5578, 0x98},
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x323c, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5080, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5180, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5280, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5380, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5480, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5580, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5680, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5780, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5880, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5980, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5a80, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5b80, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5c80, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5d80, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5e80, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x5f80, 0x20},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6cc0, 0x52},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x6e38, 0xc},
-#define USEM_PORT1_END          910
-#define USEM_FUNC0_START        910
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a30, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3000, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4018, 0x2},
-#define USEM_FUNC0_END          913
-#define USEM_FUNC1_START        913
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a34, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3010, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4028, 0x2},
-#define USEM_FUNC1_END          916
-#define USEM_FUNC2_START        916
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a38, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3020, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4038, 0x2},
-#define USEM_FUNC2_END          919
-#define USEM_FUNC3_START        919
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a3c, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3030, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4048, 0x2},
-#define USEM_FUNC3_END          922
-#define USEM_FUNC4_START        922
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a40, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3040, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4058, 0x2},
-#define USEM_FUNC4_END          925
-#define USEM_FUNC5_START        925
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a44, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3050, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4068, 0x2},
-#define USEM_FUNC5_END          928
-#define USEM_FUNC6_START        928
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a48, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3060, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4078, 0x2},
-#define USEM_FUNC6_END          931
-#define USEM_FUNC7_START        931
-	{OP_WR_E1H, USEM_REG_FAST_MEMORY + 0x2a4c, 0x0},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x3070, 0x4},
-	{OP_ZR_E1H, USEM_REG_FAST_MEMORY + 0x4088, 0x2},
-#define USEM_FUNC7_END          934
-#define CSEM_COMMON_START       934
-	{OP_RD, CSEM_REG_MSG_NUM_FIC0, 0x0},
-	{OP_RD, CSEM_REG_MSG_NUM_FIC1, 0x0},
-	{OP_RD, CSEM_REG_MSG_NUM_FOC0, 0x0},
-	{OP_RD, CSEM_REG_MSG_NUM_FOC1, 0x0},
-	{OP_RD, CSEM_REG_MSG_NUM_FOC2, 0x0},
-	{OP_RD, CSEM_REG_MSG_NUM_FOC3, 0x0},
-	{OP_WR, CSEM_REG_ARB_ELEMENT0, 0x1},
-	{OP_WR, CSEM_REG_ARB_ELEMENT1, 0x2},
-	{OP_WR, CSEM_REG_ARB_ELEMENT2, 0x3},
-	{OP_WR, CSEM_REG_ARB_ELEMENT3, 0x0},
-	{OP_WR, CSEM_REG_ARB_ELEMENT4, 0x4},
-	{OP_WR, CSEM_REG_ARB_CYCLE_SIZE, 0x1},
-	{OP_WR, CSEM_REG_TS_0_AS, 0x0},
-	{OP_WR, CSEM_REG_TS_1_AS, 0x1},
-	{OP_WR, CSEM_REG_TS_2_AS, 0x4},
-	{OP_WR, CSEM_REG_TS_3_AS, 0x0},
-	{OP_WR, CSEM_REG_TS_4_AS, 0x1},
-	{OP_WR, CSEM_REG_TS_5_AS, 0x3},
-	{OP_WR, CSEM_REG_TS_6_AS, 0x0},
-	{OP_WR, CSEM_REG_TS_7_AS, 0x1},
-	{OP_WR, CSEM_REG_TS_8_AS, 0x4},
-	{OP_WR, CSEM_REG_TS_9_AS, 0x0},
-	{OP_WR, CSEM_REG_TS_10_AS, 0x1},
-	{OP_WR, CSEM_REG_TS_11_AS, 0x3},
-	{OP_WR, CSEM_REG_TS_12_AS, 0x0},
-	{OP_WR, CSEM_REG_TS_13_AS, 0x1},
-	{OP_WR, CSEM_REG_TS_14_AS, 0x4},
-	{OP_WR, CSEM_REG_TS_15_AS, 0x0},
-	{OP_WR, CSEM_REG_TS_16_AS, 0x4},
-	{OP_WR, CSEM_REG_TS_17_AS, 0x3},
-	{OP_ZR, CSEM_REG_TS_18_AS, 0x2},
-	{OP_WR, CSEM_REG_ENABLE_IN, 0x3fff},
-	{OP_WR, CSEM_REG_ENABLE_OUT, 0x3ff},
-	{OP_WR, CSEM_REG_FIC0_DISABLE, 0x0},
-	{OP_WR, CSEM_REG_FIC1_DISABLE, 0x0},
-	{OP_WR, CSEM_REG_PAS_DISABLE, 0x0},
-	{OP_WR, CSEM_REG_THREADS_LIST, 0xffff},
-	{OP_ZR, CSEM_REG_PASSIVE_BUFFER, 0x800},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x18bc0, 0x1},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x18000, 0x10},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x18040, 0x12},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x18080, 0x30},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x180c0, 0xe},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x5000, 0x42},
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x11480, 0x1},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1020, 0xc8},
-	{OP_WR_EMUL_E1H, CSEM_REG_FAST_MEMORY + 0x11480, 0x0},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1000, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x1000, 0x42},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2000, 0xc0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x7020, 0xc8},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3070, 0x80},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x7000, 0x2},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x4280, 0x4},
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x11e8, 0x0},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x25c0, 0x240},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3000, 0xc0},
-	{OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x2ec8, 0x802a8},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4070, 0x80},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x5280, 0x4},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6700, 0x100},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x9000, 0x400},
-	{OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x6b08, 0x2002e5},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x13fffff},
-	{OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c00, 0x1002b0},
-	{OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c00, 0x100305},
-	{OP_WR, CSEM_REG_FAST_MEMORY + 0x10800, 0x0},
-	{OP_SW_E1, CSEM_REG_FAST_MEMORY + 0x10c40, 0x1002c0},
-	{OP_SW_E1H, CSEM_REG_FAST_MEMORY + 0x10c40, 0x100315},
-	{OP_ZP_E1, CSEM_REG_INT_TABLE, 0x710000},
-	{OP_ZP_E1H, CSEM_REG_INT_TABLE, 0x740000},
-	{OP_WR_64_E1, CSEM_REG_INT_TABLE + 0x380, 0x1002d0},
-	{OP_WR_64_E1H, CSEM_REG_INT_TABLE + 0x380, 0x100325},
-	{OP_ZP_E1, CSEM_REG_PRAM, 0x32290000},
-	{OP_ZP_E1H, CSEM_REG_PRAM, 0x32260000},
-	{OP_ZP_E1, CSEM_REG_PRAM + 0x8000, 0x23630c8b},
-	{OP_ZP_E1H, CSEM_REG_PRAM + 0x8000, 0x246e0c8a},
-	{OP_WR_64_E1, CSEM_REG_PRAM + 0xc930, 0x654002d2},
-	{OP_WR_64_E1H, CSEM_REG_PRAM + 0xcbb0, 0x64f00327},
-#define CSEM_COMMON_END         1014
-#define CSEM_PORT0_START        1014
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1400, 0xa0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8000, 0xa0},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1900, 0x10},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8500, 0x40},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1980, 0x30},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8700, 0x3c},
-	{OP_WR_E1, CSEM_REG_FAST_MEMORY + 0x5118, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4040, 0x6},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2300, 0xe},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3040, 0x6},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2410, 0x30},
-#define CSEM_PORT0_END          1025
-#define CSEM_PORT1_START        1025
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1680, 0xa0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8280, 0xa0},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1940, 0x10},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x8600, 0x40},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x1a40, 0x30},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x87f0, 0x3c},
-	{OP_WR_E1, CSEM_REG_FAST_MEMORY + 0x511c, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x4058, 0x6},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x2338, 0xe},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x3058, 0x6},
-	{OP_ZR_E1, CSEM_REG_FAST_MEMORY + 0x24d0, 0x30},
-#define CSEM_PORT1_END          1036
-#define CSEM_FUNC0_START        1036
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1148, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3300, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6040, 0x30},
-#define CSEM_FUNC0_END          1039
-#define CSEM_FUNC1_START        1039
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x114c, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3308, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6100, 0x30},
-#define CSEM_FUNC1_END          1042
-#define CSEM_FUNC2_START        1042
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1150, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3310, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x61c0, 0x30},
-#define CSEM_FUNC2_END          1045
-#define CSEM_FUNC3_START        1045
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1154, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3318, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6280, 0x30},
-#define CSEM_FUNC3_END          1048
-#define CSEM_FUNC4_START        1048
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1158, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3320, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6340, 0x30},
-#define CSEM_FUNC4_END          1051
-#define CSEM_FUNC5_START        1051
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x115c, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3328, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6400, 0x30},
-#define CSEM_FUNC5_END          1054
-#define CSEM_FUNC6_START        1054
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1160, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3330, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x64c0, 0x30},
-#define CSEM_FUNC6_END          1057
-#define CSEM_FUNC7_START        1057
-	{OP_WR_E1H, CSEM_REG_FAST_MEMORY + 0x1164, 0x0},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x3338, 0x2},
-	{OP_ZR_E1H, CSEM_REG_FAST_MEMORY + 0x6580, 0x30},
-#define CSEM_FUNC7_END          1060
-#define XPB_COMMON_START        1060
-	{OP_WR, GRCBASE_XPB + PB_REG_CONTROL, 0x20},
-#define XPB_COMMON_END          1061
-#define DQ_COMMON_START         1061
-	{OP_WR, DORQ_REG_MODE_ACT, 0x2},
-	{OP_WR, DORQ_REG_NORM_CID_OFST, 0x3},
-	{OP_WR, DORQ_REG_OUTST_REQ, 0x4},
-	{OP_WR, DORQ_REG_DPM_CID_ADDR, 0x8},
-	{OP_WR, DORQ_REG_RSP_INIT_CRD, 0x2},
-	{OP_WR, DORQ_REG_NORM_CMHEAD_TX, 0x90},
-	{OP_WR, DORQ_REG_CMHEAD_RX, 0x90},
-	{OP_WR, DORQ_REG_SHRT_CMHEAD, 0x800090},
-	{OP_WR, DORQ_REG_ERR_CMHEAD, 0x8140000},
-	{OP_WR, DORQ_REG_AGG_CMD0, 0x8a},
-	{OP_WR, DORQ_REG_AGG_CMD1, 0x80},
-	{OP_WR, DORQ_REG_AGG_CMD2, 0x90},
-	{OP_WR, DORQ_REG_AGG_CMD3, 0x80},
-	{OP_WR, DORQ_REG_SHRT_ACT_CNT, 0x6},
-	{OP_WR, DORQ_REG_DQ_FIFO_FULL_TH, 0x7d0},
-	{OP_WR, DORQ_REG_DQ_FIFO_AFULL_TH, 0x76c},
-	{OP_WR, DORQ_REG_REGN, 0x7c1004},
-	{OP_WR, DORQ_REG_IF_EN, 0xf},
-#define DQ_COMMON_END           1079
-#define TIMERS_COMMON_START     1079
-	{OP_ZR, TM_REG_CLIN_PRIOR0_CLIENT, 0x2},
-	{OP_WR, TM_REG_LIN_SETCLR_FIFO_ALFULL_THR, 0x1c},
-	{OP_WR, TM_REG_CFC_AC_CRDCNT_VAL, 0x1},
-	{OP_WR, TM_REG_CFC_CLD_CRDCNT_VAL, 0x1},
-	{OP_WR, TM_REG_CLOUT_CRDCNT0_VAL, 0x1},
-	{OP_WR, TM_REG_CLOUT_CRDCNT1_VAL, 0x1},
-	{OP_WR, TM_REG_CLOUT_CRDCNT2_VAL, 0x1},
-	{OP_WR, TM_REG_EXP_CRDCNT_VAL, 0x1},
-	{OP_WR_E1, TM_REG_PCIARB_CRDCNT_VAL, 0x1},
-	{OP_WR_E1H, TM_REG_PCIARB_CRDCNT_VAL, 0x2},
-	{OP_WR_ASIC, TM_REG_TIMER_TICK_SIZE, 0x3d090},
-	{OP_WR_EMUL, TM_REG_TIMER_TICK_SIZE, 0x9c},
-	{OP_WR_FPGA, TM_REG_TIMER_TICK_SIZE, 0x9c4},
-	{OP_WR, TM_REG_CL0_CONT_REGION, 0x8},
-	{OP_WR, TM_REG_CL1_CONT_REGION, 0xc},
-	{OP_WR, TM_REG_CL2_CONT_REGION, 0x10},
-	{OP_WR, TM_REG_TM_CONTEXT_REGION, 0x20},
-	{OP_WR, TM_REG_EN_TIMERS, 0x1},
-	{OP_WR, TM_REG_EN_REAL_TIME_CNT, 0x1},
-	{OP_WR, TM_REG_EN_CL0_INPUT, 0x1},
-	{OP_WR, TM_REG_EN_CL1_INPUT, 0x1},
-	{OP_WR, TM_REG_EN_CL2_INPUT, 0x1},
-#define TIMERS_COMMON_END       1101
-#define TIMERS_PORT0_START      1101
-	{OP_WR, TM_REG_LIN0_LOGIC_ADDR, 0x0},
-	{OP_WR, TM_REG_LIN0_PHY_ADDR_VALID, 0x0},
-	{OP_ZR, TM_REG_LIN0_PHY_ADDR, 0x2},
-#define TIMERS_PORT0_END        1104
-#define TIMERS_PORT1_START      1104
-	{OP_WR, TM_REG_LIN1_LOGIC_ADDR, 0x0},
-	{OP_WR, TM_REG_LIN1_PHY_ADDR_VALID, 0x0},
-	{OP_ZR, TM_REG_LIN1_PHY_ADDR, 0x2},
-#define TIMERS_PORT1_END        1107
-#define XSDM_COMMON_START       1107
-	{OP_WR_E1, XSDM_REG_CFC_RSP_START_ADDR, 0x614},
-	{OP_WR_E1H, XSDM_REG_CFC_RSP_START_ADDR, 0x424},
-	{OP_WR_E1, XSDM_REG_CMP_COUNTER_START_ADDR, 0x600},
-	{OP_WR_E1H, XSDM_REG_CMP_COUNTER_START_ADDR, 0x410},
-	{OP_WR_E1, XSDM_REG_Q_COUNTER_START_ADDR, 0x604},
-	{OP_WR_E1H, XSDM_REG_Q_COUNTER_START_ADDR, 0x414},
-	{OP_WR, XSDM_REG_CMP_COUNTER_MAX0, 0xffff},
-	{OP_WR, XSDM_REG_CMP_COUNTER_MAX1, 0xffff},
-	{OP_WR, XSDM_REG_CMP_COUNTER_MAX2, 0xffff},
-	{OP_WR, XSDM_REG_CMP_COUNTER_MAX3, 0xffff},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_0, 0x20},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_1, 0x20},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_2, 0x34},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_3, 0x35},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_4, 0x23},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_5, 0x24},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_6, 0x25},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_7, 0x26},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_8, 0x27},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_9, 0x29},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_10, 0x2a},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_11, 0x2b},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_12, 0x2c},
-	{OP_WR, XSDM_REG_AGG_INT_EVENT_13, 0x2d},
-	{OP_ZR, XSDM_REG_AGG_INT_EVENT_14, 0x52},
-	{OP_WR, XSDM_REG_AGG_INT_MODE_0, 0x1},
-	{OP_ZR, XSDM_REG_AGG_INT_MODE_1, 0x1f},
-	{OP_WR, XSDM_REG_ENABLE_IN1, 0x7ffffff},
-	{OP_WR, XSDM_REG_ENABLE_IN2, 0x3f},
-	{OP_WR, XSDM_REG_ENABLE_OUT1, 0x7ffffff},
-	{OP_WR, XSDM_REG_ENABLE_OUT2, 0xf},
-	{OP_RD, XSDM_REG_NUM_OF_Q0_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q1_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q3_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q4_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q5_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q6_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q7_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q8_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q9_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q10_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_Q11_CMD, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_PKT_END_MSG, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_PXP_ASYNC_REQ, 0x0},
-	{OP_RD, XSDM_REG_NUM_OF_ACK_AFTER_PLACE, 0x0},
-	{OP_WR_E1, XSDM_REG_INIT_CREDIT_PXP_CTRL, 0x1},
-	{OP_WR_ASIC, XSDM_REG_TIMER_TICK, 0x3e8},
-	{OP_WR_EMUL, XSDM_REG_TIMER_TICK, 0x1},
-	{OP_WR_FPGA, XSDM_REG_TIMER_TICK, 0xa},
-#define XSDM_COMMON_END         1156
-#define QM_COMMON_START         1156
-	{OP_WR, QM_REG_ACTCTRINITVAL_0, 0x6},
-	{OP_WR, QM_REG_ACTCTRINITVAL_1, 0x5},
-	{OP_WR, QM_REG_ACTCTRINITVAL_2, 0xa},
-	{OP_WR, QM_REG_ACTCTRINITVAL_3, 0x5},
-	{OP_WR, QM_REG_PCIREQAT, 0x2},
-	{OP_WR, QM_REG_CMINITCRD_0, 0x4},
-	{OP_WR, QM_REG_CMINITCRD_1, 0x4},
-	{OP_WR, QM_REG_CMINITCRD_2, 0x4},
-	{OP_WR, QM_REG_CMINITCRD_3, 0x4},
-	{OP_WR, QM_REG_CMINITCRD_4, 0x4},
-	{OP_WR, QM_REG_CMINITCRD_5, 0x4},
-	{OP_WR, QM_REG_CMINITCRD_6, 0x4},
-	{OP_WR, QM_REG_CMINITCRD_7, 0x4},
-	{OP_WR, QM_REG_OUTLDREQ, 0x4},
-	{OP_WR, QM_REG_CTXREG_0, 0x7c},
-	{OP_WR, QM_REG_CTXREG_1, 0x3d},
-	{OP_WR, QM_REG_CTXREG_2, 0x3f},
-	{OP_WR, QM_REG_CTXREG_3, 0x9c},
-	{OP_WR, QM_REG_ENSEC, 0x7},
-	{OP_ZR, QM_REG_QVOQIDX_0, 0x5},
-	{OP_WR, QM_REG_WRRWEIGHTS_0, 0x1010101},
-	{OP_WR, QM_REG_QVOQIDX_5, 0x0},
-	{OP_WR, QM_REG_QVOQIDX_6, 0x4},
-	{OP_WR, QM_REG_QVOQIDX_7, 0x4},
-	{OP_WR, QM_REG_QVOQIDX_8, 0x2},
-	{OP_WR, QM_REG_WRRWEIGHTS_1, 0x8012004},
-	{OP_WR, QM_REG_QVOQIDX_9, 0x5},
-	{OP_WR, QM_REG_QVOQIDX_10, 0x5},
-	{OP_WR, QM_REG_QVOQIDX_11, 0x5},
-	{OP_WR, QM_REG_QVOQIDX_12, 0x5},
-	{OP_WR, QM_REG_WRRWEIGHTS_2, 0x20081001},
-	{OP_WR, QM_REG_QVOQIDX_13, 0x8},
-	{OP_WR, QM_REG_QVOQIDX_14, 0x6},
-	{OP_WR, QM_REG_QVOQIDX_15, 0x7},
-	{OP_WR, QM_REG_QVOQIDX_16, 0x0},
-	{OP_WR, QM_REG_WRRWEIGHTS_3, 0x1010120},
-	{OP_ZR, QM_REG_QVOQIDX_17, 0x4},
-	{OP_WR, QM_REG_WRRWEIGHTS_4, 0x1010101},
-	{OP_ZR_E1, QM_REG_QVOQIDX_21, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_21, 0x0},
-	{OP_WR_E1, QM_REG_WRRWEIGHTS_5, 0x1010101},
-	{OP_WR_E1H, QM_REG_QVOQIDX_22, 0x4},
-	{OP_ZR_E1, QM_REG_QVOQIDX_25, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_23, 0x4},
-	{OP_WR_E1, QM_REG_WRRWEIGHTS_6, 0x1010101},
-	{OP_WR_E1H, QM_REG_QVOQIDX_24, 0x2},
-	{OP_ZR_E1, QM_REG_QVOQIDX_29, 0x3},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_5, 0x8012004},
-	{OP_WR_E1H, QM_REG_QVOQIDX_25, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_26, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_27, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_28, 0x5},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_6, 0x20081001},
-	{OP_WR_E1H, QM_REG_QVOQIDX_29, 0x8},
-	{OP_WR_E1H, QM_REG_QVOQIDX_30, 0x6},
-	{OP_WR_E1H, QM_REG_QVOQIDX_31, 0x7},
-	{OP_WR, QM_REG_QVOQIDX_32, 0x1},
-	{OP_WR_E1, QM_REG_WRRWEIGHTS_7, 0x1010101},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_7, 0x1010120},
-	{OP_WR, QM_REG_QVOQIDX_33, 0x1},
-	{OP_WR, QM_REG_QVOQIDX_34, 0x1},
-	{OP_WR, QM_REG_QVOQIDX_35, 0x1},
-	{OP_WR, QM_REG_QVOQIDX_36, 0x1},
-	{OP_WR, QM_REG_WRRWEIGHTS_8, 0x1010101},
-	{OP_WR, QM_REG_QVOQIDX_37, 0x1},
-	{OP_WR, QM_REG_QVOQIDX_38, 0x4},
-	{OP_WR, QM_REG_QVOQIDX_39, 0x4},
-	{OP_WR, QM_REG_QVOQIDX_40, 0x2},
-	{OP_WR, QM_REG_WRRWEIGHTS_9, 0x8012004},
-	{OP_WR, QM_REG_QVOQIDX_41, 0x5},
-	{OP_WR, QM_REG_QVOQIDX_42, 0x5},
-	{OP_WR, QM_REG_QVOQIDX_43, 0x5},
-	{OP_WR, QM_REG_QVOQIDX_44, 0x5},
-	{OP_WR, QM_REG_WRRWEIGHTS_10, 0x20081001},
-	{OP_WR, QM_REG_QVOQIDX_45, 0x8},
-	{OP_WR, QM_REG_QVOQIDX_46, 0x6},
-	{OP_WR, QM_REG_QVOQIDX_47, 0x7},
-	{OP_WR, QM_REG_QVOQIDX_48, 0x1},
-	{OP_WR, QM_REG_WRRWEIGHTS_11, 0x1010120},
-	{OP_WR, QM_REG_QVOQIDX_49, 0x1},
-	{OP_WR, QM_REG_QVOQIDX_50, 0x1},
-	{OP_WR, QM_REG_QVOQIDX_51, 0x1},
-	{OP_WR, QM_REG_QVOQIDX_52, 0x1},
-	{OP_WR, QM_REG_WRRWEIGHTS_12, 0x1010101},
-	{OP_WR, QM_REG_QVOQIDX_53, 0x1},
-	{OP_WR_E1, QM_REG_QVOQIDX_54, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_54, 0x4},
-	{OP_WR_E1, QM_REG_QVOQIDX_55, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_55, 0x4},
-	{OP_WR_E1, QM_REG_QVOQIDX_56, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_56, 0x2},
-	{OP_WR_E1, QM_REG_WRRWEIGHTS_13, 0x1010101},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_13, 0x8012004},
-	{OP_WR_E1, QM_REG_QVOQIDX_57, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_57, 0x5},
-	{OP_WR_E1, QM_REG_QVOQIDX_58, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_58, 0x5},
-	{OP_WR_E1, QM_REG_QVOQIDX_59, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_59, 0x5},
-	{OP_WR_E1, QM_REG_QVOQIDX_60, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_60, 0x5},
-	{OP_WR_E1, QM_REG_WRRWEIGHTS_14, 0x1010101},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_14, 0x20081001},
-	{OP_WR_E1, QM_REG_QVOQIDX_61, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_61, 0x8},
-	{OP_WR_E1, QM_REG_QVOQIDX_62, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_62, 0x6},
-	{OP_WR_E1, QM_REG_QVOQIDX_63, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_63, 0x7},
-	{OP_WR_E1, QM_REG_WRRWEIGHTS_15, 0x1010101},
-	{OP_WR_E1H, QM_REG_QVOQIDX_64, 0x0},
-	{OP_WR_E1, QM_REG_VOQQMASK_0_LSB, 0xffff003f},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_15, 0x1010120},
-	{OP_ZR_E1, QM_REG_VOQQMASK_0_MSB, 0x2},
-	{OP_ZR_E1H, QM_REG_QVOQIDX_65, 0x4},
-	{OP_WR_E1, QM_REG_VOQQMASK_1_MSB, 0xffff003f},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_16, 0x1010101},
-	{OP_WR_E1, QM_REG_VOQQMASK_2_LSB, 0x100},
-	{OP_WR_E1H, QM_REG_QVOQIDX_69, 0x0},
-	{OP_WR_E1, QM_REG_VOQQMASK_2_MSB, 0x100},
-	{OP_WR_E1H, QM_REG_QVOQIDX_70, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_71, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_72, 0x2},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_17, 0x8012004},
-	{OP_WR_E1H, QM_REG_QVOQIDX_73, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_74, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_75, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_76, 0x5},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_18, 0x20081001},
-	{OP_WR_E1H, QM_REG_QVOQIDX_77, 0x8},
-	{OP_WR_E1H, QM_REG_QVOQIDX_78, 0x6},
-	{OP_WR_E1H, QM_REG_QVOQIDX_79, 0x7},
-	{OP_WR_E1H, QM_REG_QVOQIDX_80, 0x0},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_19, 0x1010120},
-	{OP_ZR_E1H, QM_REG_QVOQIDX_81, 0x4},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_20, 0x1010101},
-	{OP_WR_E1H, QM_REG_QVOQIDX_85, 0x0},
-	{OP_WR_E1H, QM_REG_QVOQIDX_86, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_87, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_88, 0x2},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_21, 0x8012004},
-	{OP_WR_E1H, QM_REG_QVOQIDX_89, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_90, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_91, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_92, 0x5},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_22, 0x20081001},
-	{OP_WR_E1H, QM_REG_QVOQIDX_93, 0x8},
-	{OP_WR_E1H, QM_REG_QVOQIDX_94, 0x6},
-	{OP_WR_E1H, QM_REG_QVOQIDX_95, 0x7},
-	{OP_WR_E1H, QM_REG_QVOQIDX_96, 0x1},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_23, 0x1010120},
-	{OP_WR_E1H, QM_REG_QVOQIDX_97, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_98, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_99, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_100, 0x1},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_24, 0x1010101},
-	{OP_WR_E1H, QM_REG_QVOQIDX_101, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_102, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_103, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_104, 0x2},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_25, 0x8012004},
-	{OP_WR_E1H, QM_REG_QVOQIDX_105, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_106, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_107, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_108, 0x5},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_26, 0x20081001},
-	{OP_WR_E1H, QM_REG_QVOQIDX_109, 0x8},
-	{OP_WR_E1H, QM_REG_QVOQIDX_110, 0x6},
-	{OP_WR_E1H, QM_REG_QVOQIDX_111, 0x7},
-	{OP_WR_E1H, QM_REG_QVOQIDX_112, 0x1},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_27, 0x1010120},
-	{OP_WR_E1H, QM_REG_QVOQIDX_113, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_114, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_115, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_116, 0x1},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_28, 0x1010101},
-	{OP_WR_E1H, QM_REG_QVOQIDX_117, 0x1},
-	{OP_WR_E1H, QM_REG_QVOQIDX_118, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_119, 0x4},
-	{OP_WR_E1H, QM_REG_QVOQIDX_120, 0x2},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_29, 0x8012004},
-	{OP_WR_E1H, QM_REG_QVOQIDX_121, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_122, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_123, 0x5},
-	{OP_WR_E1H, QM_REG_QVOQIDX_124, 0x5},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_30, 0x20081001},
-	{OP_WR_E1H, QM_REG_QVOQIDX_125, 0x8},
-	{OP_WR_E1H, QM_REG_QVOQIDX_126, 0x6},
-	{OP_WR_E1H, QM_REG_QVOQIDX_127, 0x7},
-	{OP_WR_E1H, QM_REG_WRRWEIGHTS_31, 0x1010120},
-	{OP_WR_E1H, QM_REG_VOQQMASK_0_LSB, 0x3f003f},
-	{OP_WR_E1H, QM_REG_VOQQMASK_0_MSB, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_0_LSB_EXT_A, 0x3f003f},
-	{OP_WR_E1H, QM_REG_VOQQMASK_0_MSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_1_LSB, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_1_MSB, 0x3f003f},
-	{OP_WR_E1H, QM_REG_VOQQMASK_1_LSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_1_MSB_EXT_A, 0x3f003f},
-	{OP_WR_E1H, QM_REG_VOQQMASK_2_LSB, 0x1000100},
-	{OP_WR_E1H, QM_REG_VOQQMASK_2_MSB, 0x1000100},
-	{OP_WR_E1H, QM_REG_VOQQMASK_2_LSB_EXT_A, 0x1000100},
-	{OP_WR_E1H, QM_REG_VOQQMASK_2_MSB_EXT_A, 0x1000100},
-	{OP_ZR, QM_REG_VOQQMASK_3_LSB, 0x2},
-	{OP_WR_E1, QM_REG_VOQQMASK_4_LSB, 0xc0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_3_LSB_EXT_A, 0x0},
-	{OP_WR_E1, QM_REG_VOQQMASK_4_MSB, 0xc0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_3_MSB_EXT_A, 0x0},
-	{OP_WR_E1, QM_REG_VOQQMASK_5_LSB, 0x1e00},
-	{OP_WR_E1H, QM_REG_VOQQMASK_4_LSB, 0xc000c0},
-	{OP_WR_E1, QM_REG_VOQQMASK_5_MSB, 0x1e00},
-	{OP_WR_E1H, QM_REG_VOQQMASK_4_MSB, 0xc000c0},
-	{OP_WR_E1, QM_REG_VOQQMASK_6_LSB, 0x4000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_4_LSB_EXT_A, 0xc000c0},
-	{OP_WR_E1, QM_REG_VOQQMASK_6_MSB, 0x4000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_4_MSB_EXT_A, 0xc000c0},
-	{OP_WR_E1, QM_REG_VOQQMASK_7_LSB, 0x8000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_5_LSB, 0x1e001e00},
-	{OP_WR_E1, QM_REG_VOQQMASK_7_MSB, 0x8000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_5_MSB, 0x1e001e00},
-	{OP_WR_E1, QM_REG_VOQQMASK_8_LSB, 0x2000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_5_LSB_EXT_A, 0x1e001e00},
-	{OP_WR_E1, QM_REG_VOQQMASK_8_MSB, 0x2000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_5_MSB_EXT_A, 0x1e001e00},
-	{OP_ZR_E1, QM_REG_VOQQMASK_9_LSB, 0x7},
-	{OP_WR_E1H, QM_REG_VOQQMASK_6_LSB, 0x40004000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_6_MSB, 0x40004000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_6_LSB_EXT_A, 0x40004000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_6_MSB_EXT_A, 0x40004000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_7_LSB, 0x80008000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_7_MSB, 0x80008000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_7_LSB_EXT_A, 0x80008000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_7_MSB_EXT_A, 0x80008000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_8_LSB, 0x20002000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_8_MSB, 0x20002000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_8_LSB_EXT_A, 0x20002000},
-	{OP_WR_E1H, QM_REG_VOQQMASK_8_MSB_EXT_A, 0x20002000},
-	{OP_ZR_E1H, QM_REG_VOQQMASK_9_LSB, 0x2},
-	{OP_WR_E1H, QM_REG_VOQQMASK_9_LSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_9_MSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_10_LSB, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_10_MSB, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_10_LSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_10_MSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_11_LSB, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_11_MSB, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_11_LSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQQMASK_11_MSB_EXT_A, 0x0},
-	{OP_WR_E1H, QM_REG_VOQPORT_0, 0x0},
-	{OP_WR, QM_REG_VOQPORT_1, 0x1},
-	{OP_ZR, QM_REG_VOQPORT_2, 0xa},
-	{OP_WR, QM_REG_CMINTVOQMASK_0, 0xc08},
-	{OP_WR, QM_REG_CMINTVOQMASK_1, 0x40},
-	{OP_WR, QM_REG_CMINTVOQMASK_2, 0x100},
-	{OP_WR, QM_REG_CMINTVOQMASK_3, 0x20},
-	{OP_WR, QM_REG_CMINTVOQMASK_4, 0x17},
-	{OP_WR, QM_REG_CMINTVOQMASK_5, 0x80},
-	{OP_WR, QM_REG_CMINTVOQMASK_6, 0x200},
-	{OP_WR, QM_REG_CMINTVOQMASK_7, 0x0},
-	{OP_WR_E1, QM_REG_HWAEMPTYMASK_LSB, 0xffff01ff},
-	{OP_WR_E1H, QM_REG_HWAEMPTYMASK_LSB, 0x1ff01ff},
-	{OP_WR_E1, QM_REG_HWAEMPTYMASK_MSB, 0xffff01ff},
-	{OP_WR_E1H, QM_REG_HWAEMPTYMASK_MSB, 0x1ff01ff},
-	{OP_WR_E1H, QM_REG_HWAEMPTYMASK_LSB_EXT_A, 0x1ff01ff},
-	{OP_WR_E1H, QM_REG_HWAEMPTYMASK_MSB_EXT_A, 0x1ff01ff},
-	{OP_WR, QM_REG_ENBYPVOQMASK, 0x13},
-	{OP_WR, QM_REG_VOQCREDITAFULLTHR, 0x13f},
-	{OP_WR, QM_REG_VOQINITCREDIT_0, 0x140},
-	{OP_WR, QM_REG_VOQINITCREDIT_1, 0x140},
-	{OP_ZR, QM_REG_VOQINITCREDIT_2, 0x2},
-	{OP_WR, QM_REG_VOQINITCREDIT_4, 0xc0},
-	{OP_ZR, QM_REG_VOQINITCREDIT_5, 0x7},
-	{OP_WR, QM_REG_TASKCRDCOST_0, 0x48},
-	{OP_WR, QM_REG_TASKCRDCOST_1, 0x48},
-	{OP_ZR, QM_REG_TASKCRDCOST_2, 0x2},
-	{OP_WR, QM_REG_TASKCRDCOST_4, 0x48},
-	{OP_ZR, QM_REG_TASKCRDCOST_5, 0x7},
-	{OP_WR, QM_REG_BYTECRDINITVAL, 0x8000},
-	{OP_WR, QM_REG_BYTECRDCOST, 0x25e4},
-	{OP_WR, QM_REG_BYTECREDITAFULLTHR, 0x7fff},
-	{OP_WR_E1, QM_REG_ENBYTECRD_LSB, 0x7},
-	{OP_WR_E1H, QM_REG_ENBYTECRD_LSB, 0x70007},
-	{OP_WR_E1, QM_REG_ENBYTECRD_MSB, 0x7},
-	{OP_WR_E1H, QM_REG_ENBYTECRD_MSB, 0x70007},
-	{OP_WR_E1H, QM_REG_ENBYTECRD_LSB_EXT_A, 0x70007},
-	{OP_WR_E1H, QM_REG_ENBYTECRD_MSB_EXT_A, 0x70007},
-	{OP_WR, QM_REG_BYTECRDPORT_LSB, 0x0},
-	{OP_WR, QM_REG_BYTECRDPORT_MSB, 0xffffffff},
-	{OP_WR_E1, QM_REG_FUNCNUMSEL_LSB, 0x0},
-	{OP_WR_E1H, QM_REG_BYTECRDPORT_LSB_EXT_A, 0x0},
-	{OP_WR_E1, QM_REG_FUNCNUMSEL_MSB, 0xffffffff},
-	{OP_WR_E1H, QM_REG_BYTECRDPORT_MSB_EXT_A, 0xffffffff},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_0, 0x0},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_1, 0x2},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_2, 0x1},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_3, 0x3},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_4, 0x4},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_5, 0x6},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_6, 0x5},
-	{OP_WR_E1H, QM_REG_PQ2PCIFUNC_7, 0x7},
-	{OP_WR, QM_REG_CMINTEN, 0xff},
-#define QM_COMMON_END           1456
-#define PBF_COMMON_START        1456
-	{OP_WR, PBF_REG_INIT, 0x1},
-	{OP_WR, PBF_REG_INIT_P4, 0x1},
-	{OP_WR, PBF_REG_MAC_LB_ENABLE, 0x1},
-	{OP_WR, PBF_REG_IF_ENABLE_REG, 0x7fff},
-	{OP_WR, PBF_REG_INIT_P4, 0x0},
-	{OP_WR, PBF_REG_INIT, 0x0},
-	{OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P4, 0x0},
-#define PBF_COMMON_END          1463
-#define PBF_PORT0_START         1463
-	{OP_WR, PBF_REG_INIT_P0, 0x1},
-	{OP_WR, PBF_REG_MAC_IF0_ENABLE, 0x1},
-	{OP_WR, PBF_REG_INIT_P0, 0x0},
-	{OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P0, 0x0},
-#define PBF_PORT0_END           1467
-#define PBF_PORT1_START         1467
-	{OP_WR, PBF_REG_INIT_P1, 0x1},
-	{OP_WR, PBF_REG_MAC_IF1_ENABLE, 0x1},
-	{OP_WR, PBF_REG_INIT_P1, 0x0},
-	{OP_WR, PBF_REG_DISABLE_NEW_TASK_PROC_P1, 0x0},
-#define PBF_PORT1_END           1471
-#define XCM_COMMON_START        1471
-	{OP_WR, XCM_REG_XX_OVFL_EVNT_ID, 0x32},
-	{OP_WR, XCM_REG_XQM_XCM_HDR_P, 0x3150020},
-	{OP_WR, XCM_REG_XQM_XCM_HDR_S, 0x3150020},
-	{OP_WR, XCM_REG_TM_XCM_HDR, 0x1000030},
-	{OP_WR, XCM_REG_ERR_XCM_HDR, 0x8100000},
-	{OP_WR, XCM_REG_ERR_EVNT_ID, 0x33},
-	{OP_WR, XCM_REG_EXPR_EVNT_ID, 0x30},
-	{OP_WR, XCM_REG_STOP_EVNT_ID, 0x31},
-	{OP_WR, XCM_REG_STORM_WEIGHT, 0x3},
-	{OP_WR, XCM_REG_TSEM_WEIGHT, 0x6},
-	{OP_WR, XCM_REG_CSEM_WEIGHT, 0x3},
-	{OP_WR, XCM_REG_USEM_WEIGHT, 0x3},
-	{OP_WR, XCM_REG_DORQ_WEIGHT, 0x2},
-	{OP_WR, XCM_REG_PBF_WEIGHT, 0x0},
-	{OP_WR, XCM_REG_NIG0_WEIGHT, 0x2},
-	{OP_WR, XCM_REG_CP_WEIGHT, 0x0},
-	{OP_WR, XCM_REG_XSDM_WEIGHT, 0x6},
-	{OP_WR, XCM_REG_XQM_P_WEIGHT, 0x4},
-	{OP_WR, XCM_REG_XQM_S_WEIGHT, 0x2},
-	{OP_WR, XCM_REG_TM_WEIGHT, 0x2},
-	{OP_WR, XCM_REG_XCM_XQM_USE_Q, 0x1},
-	{OP_WR, XCM_REG_XQM_BYP_ACT_UPD, 0x6},
-	{OP_WR, XCM_REG_UNA_GT_NXT_Q, 0x0},
-	{OP_WR, XCM_REG_AUX1_Q, 0x2},
-	{OP_WR, XCM_REG_AUX_CNT_FLG_Q_19, 0x1},
-	{OP_WR, XCM_REG_GR_ARB_TYPE, 0x1},
-	{OP_WR, XCM_REG_GR_LD0_PR, 0x1},
-	{OP_WR, XCM_REG_GR_LD1_PR, 0x2},
-	{OP_WR, XCM_REG_CFC_INIT_CRD, 0x1},
-	{OP_WR, XCM_REG_FIC0_INIT_CRD, 0x40},
-	{OP_WR, XCM_REG_FIC1_INIT_CRD, 0x40},
-	{OP_WR, XCM_REG_TM_INIT_CRD, 0x4},
-	{OP_WR, XCM_REG_XQM_INIT_CRD, 0x20},
-	{OP_WR, XCM_REG_XX_INIT_CRD, 0x2},
-	{OP_WR_E1, XCM_REG_XX_MSG_NUM, 0x1f},
-	{OP_WR_E1H, XCM_REG_XX_MSG_NUM, 0x20},
-	{OP_ZR, XCM_REG_XX_TABLE, 0x12},
-	{OP_SW_E1, XCM_REG_XX_DESCR_TABLE, 0x1f02d4},
-	{OP_SW_E1H, XCM_REG_XX_DESCR_TABLE, 0x1f0329},
-	{OP_WR, XCM_REG_N_SM_CTX_LD_0, 0xf},
-	{OP_WR, XCM_REG_N_SM_CTX_LD_1, 0x7},
-	{OP_WR, XCM_REG_N_SM_CTX_LD_2, 0xb},
-	{OP_WR, XCM_REG_N_SM_CTX_LD_3, 0xe},
-	{OP_ZR_E1, XCM_REG_N_SM_CTX_LD_4, 0x4},
-	{OP_WR_E1H, XCM_REG_N_SM_CTX_LD_4, 0xe},
-	{OP_ZR_E1H, XCM_REG_N_SM_CTX_LD_5, 0x3},
-	{OP_WR, XCM_REG_XCM_REG0_SZ, 0x4},
-	{OP_WR, XCM_REG_XCM_STORM0_IFEN, 0x1},
-	{OP_WR, XCM_REG_XCM_STORM1_IFEN, 0x1},
-	{OP_WR, XCM_REG_XCM_XQM_IFEN, 0x1},
-	{OP_WR, XCM_REG_STORM_XCM_IFEN, 0x1},
-	{OP_WR, XCM_REG_XQM_XCM_IFEN, 0x1},
-	{OP_WR, XCM_REG_XSDM_IFEN, 0x1},
-	{OP_WR, XCM_REG_TM_XCM_IFEN, 0x1},
-	{OP_WR, XCM_REG_XCM_TM_IFEN, 0x1},
-	{OP_WR, XCM_REG_TSEM_IFEN, 0x1},
-	{OP_WR, XCM_REG_CSEM_IFEN, 0x1},
-	{OP_WR, XCM_REG_USEM_IFEN, 0x1},
-	{OP_WR, XCM_REG_DORQ_IFEN, 0x1},
-	{OP_WR, XCM_REG_PBF_IFEN, 0x1},
-	{OP_WR, XCM_REG_NIG0_IFEN, 0x1},
-	{OP_WR, XCM_REG_NIG1_IFEN, 0x1},
-	{OP_WR, XCM_REG_CDU_AG_WR_IFEN, 0x1},
-	{OP_WR, XCM_REG_CDU_AG_RD_IFEN, 0x1},
-	{OP_WR, XCM_REG_CDU_SM_WR_IFEN, 0x1},
-	{OP_WR, XCM_REG_CDU_SM_RD_IFEN, 0x1},
-	{OP_WR, XCM_REG_XCM_CFC_IFEN, 0x1},
-#define XCM_COMMON_END          1538
-#define XCM_PORT0_START         1538
-	{OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
-	{OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
-	{OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
-	{OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_CMD00, 0x2},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_CMD10, 0x2},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
-#define XCM_PORT0_END           1546
-#define XCM_PORT1_START         1546
-	{OP_WR_E1, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
-	{OP_WR_E1, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
-	{OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
-	{OP_WR_E1, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_CMD01, 0x2},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_CMD11, 0x2},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
-	{OP_WR_E1, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
-#define XCM_PORT1_END           1554
-#define XCM_FUNC0_START         1554
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC0_END           1563
-#define XCM_FUNC1_START         1563
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC1_END           1572
-#define XCM_FUNC2_START         1572
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC2_END           1581
-#define XCM_FUNC3_START         1581
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC3_END           1590
-#define XCM_FUNC4_START         1590
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC4_END           1599
-#define XCM_FUNC5_START         1599
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC5_END           1608
-#define XCM_FUNC6_START         1608
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_0, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD10, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD00, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD10, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL00, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL10, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_0, 0x0},
-#define XCM_FUNC6_END           1617
-#define XCM_FUNC7_START         1617
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_TMR_VAL_1, 0xc8},
-	{OP_WR_E1H, XCM_REG_GLB_DEL_ACK_MAX_CNT_1, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD01, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD11, 0x0},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD01, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_CMD11, 0x2},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL01, 0xff},
-	{OP_WR_E1H, XCM_REG_WU_DA_CNT_UPD_VAL11, 0xff},
-	{OP_WR_E1H, XCM_REG_PHYS_QNUM3_1, 0x0},
-#define XCM_FUNC7_END           1626
-#define XSEM_COMMON_START       1626
-	{OP_RD, XSEM_REG_MSG_NUM_FIC0, 0x0},
-	{OP_RD, XSEM_REG_MSG_NUM_FIC1, 0x0},
-	{OP_RD, XSEM_REG_MSG_NUM_FOC0, 0x0},
-	{OP_RD, XSEM_REG_MSG_NUM_FOC1, 0x0},
-	{OP_RD, XSEM_REG_MSG_NUM_FOC2, 0x0},
-	{OP_RD, XSEM_REG_MSG_NUM_FOC3, 0x0},
-	{OP_WR, XSEM_REG_ARB_ELEMENT0, 0x1},
-	{OP_WR, XSEM_REG_ARB_ELEMENT1, 0x2},
-	{OP_WR, XSEM_REG_ARB_ELEMENT2, 0x3},
-	{OP_WR, XSEM_REG_ARB_ELEMENT3, 0x0},
-	{OP_WR, XSEM_REG_ARB_ELEMENT4, 0x4},
-	{OP_WR, XSEM_REG_ARB_CYCLE_SIZE, 0x1},
-	{OP_WR, XSEM_REG_TS_0_AS, 0x0},
-	{OP_WR, XSEM_REG_TS_1_AS, 0x1},
-	{OP_WR, XSEM_REG_TS_2_AS, 0x4},
-	{OP_WR, XSEM_REG_TS_3_AS, 0x0},
-	{OP_WR, XSEM_REG_TS_4_AS, 0x1},
-	{OP_WR, XSEM_REG_TS_5_AS, 0x3},
-	{OP_WR, XSEM_REG_TS_6_AS, 0x0},
-	{OP_WR, XSEM_REG_TS_7_AS, 0x1},
-	{OP_WR, XSEM_REG_TS_8_AS, 0x4},
-	{OP_WR, XSEM_REG_TS_9_AS, 0x0},
-	{OP_WR, XSEM_REG_TS_10_AS, 0x1},
-	{OP_WR, XSEM_REG_TS_11_AS, 0x3},
-	{OP_WR, XSEM_REG_TS_12_AS, 0x0},
-	{OP_WR, XSEM_REG_TS_13_AS, 0x1},
-	{OP_WR, XSEM_REG_TS_14_AS, 0x4},
-	{OP_WR, XSEM_REG_TS_15_AS, 0x0},
-	{OP_WR, XSEM_REG_TS_16_AS, 0x4},
-	{OP_WR, XSEM_REG_TS_17_AS, 0x3},
-	{OP_ZR, XSEM_REG_TS_18_AS, 0x2},
-	{OP_WR, XSEM_REG_ENABLE_IN, 0x3fff},
-	{OP_WR, XSEM_REG_ENABLE_OUT, 0x3ff},
-	{OP_WR, XSEM_REG_FIC0_DISABLE, 0x0},
-	{OP_WR, XSEM_REG_FIC1_DISABLE, 0x0},
-	{OP_WR, XSEM_REG_PAS_DISABLE, 0x0},
-	{OP_WR, XSEM_REG_THREADS_LIST, 0xffff},
-	{OP_ZR, XSEM_REG_PASSIVE_BUFFER, 0x800},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x18bc0, 0x1},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x18000, 0x0},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x18040, 0x18},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x18080, 0xc},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x180c0, 0x66},
-	{OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18300, 0x7a120},
-	{OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18300, 0x138},
-	{OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18300, 0x1388},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x183c0, 0x1f4},
-	{OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18340, 0x1f4},
-	{OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18340, 0x0},
-	{OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18340, 0x5},
-	{OP_WR_EMUL, XSEM_REG_FAST_MEMORY + 0x18380, 0x4c4b4},
-	{OP_WR_ASIC, XSEM_REG_FAST_MEMORY + 0x18380, 0x1dcd6500},
-	{OP_WR_EMUL_E1H, XSEM_REG_FAST_MEMORY + 0x11480, 0x0},
-	{OP_WR_FPGA, XSEM_REG_FAST_MEMORY + 0x18380, 0x4c4b40},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3d60, 0x4},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x11480, 0x1},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d60 + 0x10, 0x202f3},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x29c8, 0x4},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3000, 0x48},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29c8 + 0x10, 0x20348},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1020, 0xc8},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2080, 0x48},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1000, 0x2},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x9020, 0xc8},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3128, 0x8e},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x9000, 0x2},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3368, 0x0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x21a8, 0x86},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3370, 0x202f5},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2000, 0x20},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3b90, 0x402f7},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x23c8, 0x0},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3e20, 0x202fb},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x23d0, 0x2034a},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1518, 0x1},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2498, 0x4034c},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1830, 0x0},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2c20, 0x0},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1838, 0x0},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x2c10, 0x0},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1820, 0x202fd},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2c08, 0x20350},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4ac0, 0x2},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3010, 0x1},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b00, 0x4},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x4040, 0x10},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x1f48, 0x202ff},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x4000, 0x100352},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6ac0, 0x2},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b00, 0x4},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x8408, 0x20362},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x0},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c00, 0x100301},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c00, 0x100364},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x1000000},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80311},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c40, 0x80374},
-	{OP_WR, XSEM_REG_FAST_MEMORY + 0x10800, 0x2000000},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x10c60, 0x80319},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x10c60, 0x8037c},
-	{OP_ZP_E1, XSEM_REG_INT_TABLE, 0xb50000},
-	{OP_ZP_E1H, XSEM_REG_INT_TABLE, 0xbd0000},
-	{OP_WR_64_E1, XSEM_REG_INT_TABLE + 0x368, 0x130321},
-	{OP_WR_64_E1H, XSEM_REG_INT_TABLE + 0x3a8, 0xb0384},
-	{OP_ZP_E1, XSEM_REG_PRAM, 0x33660000},
-	{OP_ZP_E1H, XSEM_REG_PRAM, 0x34060000},
-	{OP_ZP_E1, XSEM_REG_PRAM + 0x8000, 0x38b30cda},
-	{OP_ZP_E1H, XSEM_REG_PRAM + 0x8000, 0x37960d02},
-	{OP_ZP_E1, XSEM_REG_PRAM + 0x10000, 0x3bb11b07},
-	{OP_ZP_E1H, XSEM_REG_PRAM + 0x10000, 0x3bc31ae8},
-	{OP_ZP_E1, XSEM_REG_PRAM + 0x18000, 0x2a2629f4},
-	{OP_ZP_E1H, XSEM_REG_PRAM + 0x18000, 0x382629d9},
-	{OP_WR_64_E1, XSEM_REG_PRAM + 0x1d6c0, 0x45280323},
-	{OP_ZP_E1H, XSEM_REG_PRAM + 0x20000, 0x124537e3},
-	{OP_WR_64_E1H, XSEM_REG_PRAM + 0x22220, 0x3bbc0386},
-#define XSEM_COMMON_END         1741
-#define XSEM_PORT0_START        1741
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3ba0, 0x14},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc000, 0xfc},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3c40, 0x24},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x24a8, 0x14},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1400, 0xa},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2548, 0x24},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1450, 0x6},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2668, 0x24},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3378, 0xfc},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2788, 0x24},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b58, 0x0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x28a8, 0x24},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d78, 0x20325},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa000, 0x28},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d88, 0x100327},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa140, 0xc},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1500, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29e0, 0x20388},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1508, 0x1},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3000, 0x1},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5020, 0x2},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5030, 0x2},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5000, 0x2},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5010, 0x2},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x5040, 0x0},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x5208, 0x1},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x5048, 0xe},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ac8, 0x2038a},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50b8, 0x1},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6b10, 0x42},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ac8, 0x20337},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d20, 0x4},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4b10, 0x42},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d20, 0x4},
-#define XSEM_PORT0_END          1775
-#define XSEM_PORT1_START        1775
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3bf0, 0x14},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xc3f0, 0xfc},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3cd0, 0x24},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x24f8, 0x14},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1428, 0xa},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x25d8, 0x24},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x1468, 0x6},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x26f8, 0x24},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x3768, 0xfc},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2818, 0x24},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x3b5c, 0x0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x2938, 0x24},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3d80, 0x20339},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa0a0, 0x28},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x3dc8, 0x10033b},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0xa170, 0xc},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x1504, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29e8, 0x2038c},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x150c, 0x1},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x3004, 0x1},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5028, 0x2},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5038, 0x2},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5008, 0x2},
-	{OP_ZR, XSEM_REG_FAST_MEMORY + 0x5018, 0x2},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x5044, 0x0},
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0x520c, 0x1},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x5080, 0xe},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x6ad0, 0x2038e},
-	{OP_WR_E1, XSEM_REG_FAST_MEMORY + 0x50bc, 0x1},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6c18, 0x42},
-	{OP_SW_E1, XSEM_REG_FAST_MEMORY + 0x4ad0, 0x2034b},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x6d30, 0x4},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4c18, 0x42},
-	{OP_ZR_E1, XSEM_REG_FAST_MEMORY + 0x4d30, 0x4},
-#define XSEM_PORT1_END          1809
-#define XSEM_FUNC0_START        1809
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e0, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x29f0, 0x100390},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5048, 0xe},
-#define XSEM_FUNC0_END          1812
-#define XSEM_FUNC1_START        1812
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e4, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a30, 0x1003a0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5080, 0xe},
-#define XSEM_FUNC1_END          1815
-#define XSEM_FUNC2_START        1815
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7e8, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2a70, 0x1003b0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50b8, 0xe},
-#define XSEM_FUNC2_END          1818
-#define XSEM_FUNC3_START        1818
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7ec, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2ab0, 0x1003c0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x50f0, 0xe},
-#define XSEM_FUNC3_END          1821
-#define XSEM_FUNC4_START        1821
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f0, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2af0, 0x1003d0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5128, 0xe},
-#define XSEM_FUNC4_END          1824
-#define XSEM_FUNC5_START        1824
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f4, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2b30, 0x1003e0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5160, 0xe},
-#define XSEM_FUNC5_END          1827
-#define XSEM_FUNC6_START        1827
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7f8, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2b70, 0x1003f0},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x5198, 0xe},
-#define XSEM_FUNC6_END          1830
-#define XSEM_FUNC7_START        1830
-	{OP_WR_E1H, XSEM_REG_FAST_MEMORY + 0xc7fc, 0x0},
-	{OP_SW_E1H, XSEM_REG_FAST_MEMORY + 0x2bb0, 0x100400},
-	{OP_ZR_E1H, XSEM_REG_FAST_MEMORY + 0x51d0, 0xe},
-#define XSEM_FUNC7_END          1833
-#define CDU_COMMON_START        1833
-	{OP_WR, CDU_REG_CDU_CONTROL0, 0x1},
-	{OP_WR_E1H, CDU_REG_MF_MODE, 0x1},
-	{OP_WR, CDU_REG_CDU_CHK_MASK0, 0x3d000},
-	{OP_WR, CDU_REG_CDU_CHK_MASK1, 0x3d},
-	{OP_WB_E1, CDU_REG_L1TT, 0x200034d},
-	{OP_WB_E1H, CDU_REG_L1TT, 0x2000410},
-	{OP_WB_E1, CDU_REG_MATT, 0x20054d},
-	{OP_WB_E1H, CDU_REG_MATT, 0x280610},
-	{OP_ZR_E1, CDU_REG_MATT + 0x80, 0x2},
-	{OP_WB_E1, CDU_REG_MATT + 0x88, 0x6056d},
-	{OP_ZR, CDU_REG_MATT + 0xa0, 0x18},
-#define CDU_COMMON_END          1844
-#define DMAE_COMMON_START       1844
-	{OP_ZR, DMAE_REG_CMD_MEM, 0xe0},
-	{OP_WR, DMAE_REG_CRC16C_INIT, 0x0},
-	{OP_WR, DMAE_REG_CRC16T10_INIT, 0x1},
-	{OP_WR_E1, DMAE_REG_PXP_REQ_INIT_CRD, 0x1},
-	{OP_WR_E1H, DMAE_REG_PXP_REQ_INIT_CRD, 0x2},
-	{OP_WR, DMAE_REG_PCI_IFEN, 0x1},
-	{OP_WR, DMAE_REG_GRC_IFEN, 0x1},
-#define DMAE_COMMON_END         1851
-#define PXP_COMMON_START        1851
-	{OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x400, 0x50573},
-	{OP_WB_E1H, PXP_REG_HST_INBOUND_INT + 0x400, 0x50638},
-	{OP_WB_E1, PXP_REG_HST_INBOUND_INT + 0x420, 0x50578},
-	{OP_WB_E1H, PXP_REG_HST_INBOUND_INT, 0x5063d},
-	{OP_WB_E1, PXP_REG_HST_INBOUND_INT, 0x5057d},
-	{OP_WB_E1H, PXP_REG_HST_INBOUND_INT + 0x20, 0x50642},
-#define PXP_COMMON_END          1857
-#define CFC_COMMON_START        1857
-	{OP_ZR_E1H, CFC_REG_LINK_LIST, 0x100},
-	{OP_WR, CFC_REG_CONTROL0, 0x10},
-	{OP_WR, CFC_REG_DISABLE_ON_ERROR, 0x3fff},
-	{OP_WR, CFC_REG_INTERFACES, 0x280000},
-	{OP_WR, CFC_REG_LCREQ_WEIGHTS, 0x84924a},
-	{OP_WR, CFC_REG_INTERFACES, 0x0},
-#define CFC_COMMON_END          1863
-#define HC_COMMON_START         1863
-	{OP_ZR_E1, HC_REG_USTORM_ADDR_FOR_COALESCE, 0x4},
-#define HC_COMMON_END           1864
-#define HC_PORT0_START          1864
-	{OP_WR_E1, HC_REG_CONFIG_0, 0x1080},
-	{OP_ZR_E1, HC_REG_UC_RAM_ADDR_0, 0x2},
-	{OP_WR_E1, HC_REG_ATTN_NUM_P0, 0x10},
-	{OP_WR_E1, HC_REG_LEADING_EDGE_0, 0xffff},
-	{OP_WR_E1, HC_REG_TRAILING_EDGE_0, 0xffff},
-	{OP_WR_E1, HC_REG_AGG_INT_0, 0x0},
-	{OP_WR_E1, HC_REG_ATTN_IDX, 0x0},
-	{OP_ZR_E1, HC_REG_ATTN_BIT, 0x2},
-	{OP_WR_E1, HC_REG_VQID_0, 0x2b5},
-	{OP_WR_E1, HC_REG_PCI_CONFIG_0, 0x0},
-	{OP_ZR_E1, HC_REG_P0_PROD_CONS, 0x4a},
-	{OP_WR_E1, HC_REG_INT_MASK, 0x1ffff},
-	{OP_ZR_E1, HC_REG_PBA_COMMAND, 0x2},
-	{OP_WR_E1, HC_REG_CONFIG_0, 0x1a80},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS, 0x24},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_PORT0_END            1882
-#define HC_PORT1_START          1882
-	{OP_WR_E1, HC_REG_CONFIG_1, 0x1080},
-	{OP_ZR_E1, HC_REG_UC_RAM_ADDR_1, 0x2},
-	{OP_WR_E1, HC_REG_ATTN_NUM_P1, 0x10},
-	{OP_WR_E1, HC_REG_LEADING_EDGE_1, 0xffff},
-	{OP_WR_E1, HC_REG_TRAILING_EDGE_1, 0xffff},
-	{OP_WR_E1, HC_REG_AGG_INT_1, 0x0},
-	{OP_WR_E1, HC_REG_ATTN_IDX + 0x4, 0x0},
-	{OP_ZR_E1, HC_REG_ATTN_BIT + 0x8, 0x2},
-	{OP_WR_E1, HC_REG_VQID_1, 0x2b5},
-	{OP_WR_E1, HC_REG_PCI_CONFIG_1, 0x0},
-	{OP_ZR_E1, HC_REG_P1_PROD_CONS, 0x4a},
-	{OP_WR_E1, HC_REG_INT_MASK + 0x4, 0x1ffff},
-	{OP_ZR_E1, HC_REG_PBA_COMMAND + 0x8, 0x2},
-	{OP_WR_E1, HC_REG_CONFIG_1, 0x1a80},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
-	{OP_ZR_E1, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_PORT1_END            1900
-#define HC_FUNC0_START          1900
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x0},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_0, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0},
-	{OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC0_END            1915
-#define HC_FUNC1_START          1915
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x1},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_1, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0},
-	{OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC1_END            1930
-#define HC_FUNC2_START          1930
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x2},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_0, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0},
-	{OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC2_END            1945
-#define HC_FUNC3_START          1945
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x3},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_1, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0},
-	{OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC3_END            1960
-#define HC_FUNC4_START          1960
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x4},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_0, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0},
-	{OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC4_END            1975
-#define HC_FUNC5_START          1975
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x5},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_1, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0},
-	{OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC5_END            1990
-#define HC_FUNC6_START          1990
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P0, 0x6},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P0, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_0, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_0, 0x0},
-	{OP_ZR_E1H, HC_REG_P0_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_0, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x120, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x370, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x5c0, 0x4a},
-#define HC_FUNC6_END            2005
-#define HC_FUNC7_START          2005
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1080},
-	{OP_WR_E1H, HC_REG_FUNC_NUM_P1, 0x7},
-	{OP_WR_E1H, HC_REG_ATTN_NUM_P1, 0x10},
-	{OP_WR_E1H, HC_REG_ATTN_IDX + 0x4, 0x0},
-	{OP_ZR_E1H, HC_REG_ATTN_BIT + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_VQID_1, 0x2b5},
-	{OP_WR_E1H, HC_REG_PCI_CONFIG_1, 0x0},
-	{OP_ZR_E1H, HC_REG_P1_PROD_CONS, 0x4a},
-	{OP_WR_E1H, HC_REG_INT_MASK + 0x4, 0x1ffff},
-	{OP_ZR_E1H, HC_REG_PBA_COMMAND + 0x8, 0x2},
-	{OP_WR_E1H, HC_REG_CONFIG_1, 0x1a80},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x90, 0x24},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x248, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x498, 0x4a},
-	{OP_ZR_E1H, HC_REG_STATISTIC_COUNTERS + 0x6e8, 0x4a},
-#define HC_FUNC7_END            2020
-#define PXP2_COMMON_START       2020
-	{OP_WR_E1H, PXP2_REG_RQ_DRAM_ALIGN, 0x1},
-	{OP_WR, PXP2_REG_PGL_CONTROL0, 0xe38340},
-	{OP_WR, PXP2_REG_PGL_CONTROL1, 0x3c10},
-	{OP_WR_E1H, PXP2_REG_RQ_ELT_DISABLE, 0x1},
-	{OP_WR_E1H, PXP2_REG_WR_REV_MODE, 0x0},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_0, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_1, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_2, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_3, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_4, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_5, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_6, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_TSDM_7, 0xffffffff},
-	{OP_WR_E1, PXP2_REG_PGL_INT_USDM_1, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_USDM_2, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_USDM_3, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_USDM_4, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_USDM_5, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_USDM_6, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_USDM_7, 0xffffffff},
-	{OP_WR_E1H, PXP2_REG_PGL_INT_XSDM_1, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_XSDM_2, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_XSDM_3, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_XSDM_4, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_XSDM_5, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_XSDM_6, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_XSDM_7, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_0, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_1, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_2, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_3, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_4, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_5, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_6, 0xffffffff},
-	{OP_WR, PXP2_REG_PGL_INT_CSDM_7, 0xffffffff},
-	{OP_WR_E1, PXP2_REG_PGL_INT_XSDM_0, 0xffff3330},
-	{OP_WR_E1H, PXP2_REG_PGL_INT_XSDM_0, 0xff802000},
-	{OP_WR_E1, PXP2_REG_PGL_INT_XSDM_1, 0xffff3340},
-	{OP_WR_E1H, PXP2_REG_PGL_INT_USDM_0, 0xf0005000},
-	{OP_WR_E1, PXP2_REG_PGL_INT_USDM_0, 0xf0003000},
-	{OP_WR_E1H, PXP2_REG_PGL_INT_USDM_1, 0xf0008000},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ6, 0x8},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ9, 0x8},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ10, 0x8},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ11, 0x2},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ17, 0x4},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ18, 0x5},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ19, 0x4},
-	{OP_WR, PXP2_REG_RD_MAX_BLKS_VQ22, 0x0},
-	{OP_WR, PXP2_REG_RD_START_INIT, 0x1},
-	{OP_WR, PXP2_REG_WR_DMAE_TH, 0x3f},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD0, 0x40},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD1, 0x1808},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD2, 0x803},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD3, 0x803},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD4, 0x40},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD5, 0x3},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD6, 0x803},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD7, 0x803},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD8, 0x803},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD9, 0x10003},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD10, 0x803},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD11, 0x803},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD12, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD13, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD14, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD15, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD16, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD17, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD18, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD19, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD20, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD22, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD23, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD24, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD25, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD26, 0x3},
-	{OP_WR, PXP2_REG_RQ_BW_RD_ADD27, 0x3},
-	{OP_WR, PXP2_REG_PSWRQ_BW_ADD28, 0x2403},
-	{OP_WR, PXP2_REG_RQ_BW_WR_ADD29, 0x2f},
-	{OP_WR, PXP2_REG_RQ_BW_WR_ADD30, 0x9},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND0, 0x19},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB1, 0x184},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB2, 0x183},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB3, 0x306},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND4, 0x19},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND5, 0x6},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB6, 0x306},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB7, 0x306},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB8, 0x306},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB9, 0xc86},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB10, 0x306},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB11, 0x306},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND12, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND13, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND14, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND15, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND16, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND17, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND18, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND19, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND20, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND22, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND23, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND24, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND25, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND26, 0x6},
-	{OP_WR, PXP2_REG_RQ_BW_RD_UBOUND27, 0x6},
-	{OP_WR, PXP2_REG_PSWRQ_BW_UB28, 0x306},
-	{OP_WR, PXP2_REG_RQ_BW_WR_UBOUND29, 0x13},
-	{OP_WR, PXP2_REG_RQ_BW_WR_UBOUND30, 0x6},
-	{OP_WR, PXP2_REG_PSWRQ_BW_L1, 0x1004},
-	{OP_WR, PXP2_REG_PSWRQ_BW_L2, 0x1004},
-	{OP_WR, PXP2_REG_PSWRQ_BW_RD, 0x106440},
-	{OP_WR, PXP2_REG_PSWRQ_BW_WR, 0x106440},
-	{OP_WR_E1H, PXP2_REG_RQ_ILT_MODE, 0x1},
-	{OP_WR, PXP2_REG_RQ_RBC_DONE, 0x1},
-#define PXP2_COMMON_END         2137
-#define MISC_AEU_COMMON_START   2137
-	{OP_ZR, MISC_REG_AEU_GENERAL_ATTN_0, 0x16},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE1_NIG_0, 0x55540000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE2_NIG_0, 0x55555555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE3_NIG_0, 0x5555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_NIG_0, 0xf0000000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE1_PXP_0, 0x55540000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE2_PXP_0, 0x55555555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE3_PXP_0, 0x5555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_PXP_0, 0xf0000000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE1_NIG_1, 0x55540000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE2_NIG_1, 0x55555555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE3_NIG_1, 0x5555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_NIG_1, 0xf0000000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE1_PXP_1, 0x0},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE2_PXP_1, 0x10000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE3_PXP_1, 0x5014},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_PXP_1, 0x0},
-	{OP_WR_E1H, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0xc00},
-	{OP_WR_E1H, MISC_REG_AEU_GENERAL_MASK, 0x3},
-#define MISC_AEU_COMMON_END     2156
-#define MISC_AEU_PORT0_START    2156
-	{OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xbf5c0000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, 0xff5c0000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0, 0xfff51fef},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_0, 0xfff55fff},
-	{OP_WR, MISC_REG_AEU_ENABLE3_FUNC_0_OUT_0, 0xffff},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, 0x500003e0},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, 0xf00003e0},
-	{OP_WR, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1, 0x0},
-	{OP_WR, MISC_REG_AEU_ENABLE2_FUNC_0_OUT_1, 0xa000},
-	{OP_ZR, MISC_REG_AEU_ENABLE3_FUNC_0_OUT_1, 0x5},
-	{OP_WR, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_2, 0xfe00000},
-	{OP_ZR_E1, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_3, 0x14},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_3, 0x7},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE1_NIG_0, 0x55540000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_4, 0x400},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE2_NIG_0, 0x55555555},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_5, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE3_NIG_0, 0x5555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_5, 0x1000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE4_NIG_0, 0x0},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_6, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE1_PXP_0, 0x55540000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_6, 0x4000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE2_PXP_0, 0x55555555},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_7, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE3_PXP_0, 0x5555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_0_OUT_7, 0x10000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE4_PXP_0, 0x0},
-	{OP_ZR_E1H, MISC_REG_AEU_INVERTER_1_FUNC_0, 0x4},
-	{OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_0, 0x0},
-	{OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_0, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_0, 0x7},
-#define MISC_AEU_PORT0_END      2188
-#define MISC_AEU_PORT1_START    2188
-	{OP_WR_E1, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xbf5c0000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0, 0xff5c0000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0, 0xfff51fef},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_0, 0xfff55fff},
-	{OP_WR, MISC_REG_AEU_ENABLE3_FUNC_1_OUT_0, 0xffff},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, 0x500003e0},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, 0xf00003e0},
-	{OP_WR, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1, 0x0},
-	{OP_WR, MISC_REG_AEU_ENABLE2_FUNC_1_OUT_1, 0xa000},
-	{OP_ZR, MISC_REG_AEU_ENABLE3_FUNC_1_OUT_1, 0x5},
-	{OP_WR, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_2, 0xfe00000},
-	{OP_ZR_E1, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_3, 0x14},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_3, 0x7},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE1_NIG_1, 0x55540000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_4, 0x800},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE2_NIG_1, 0x55555555},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_5, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE3_NIG_1, 0x5555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_5, 0x2000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE4_NIG_1, 0x0},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_6, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE1_PXP_1, 0x55540000},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_6, 0x8000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE2_PXP_1, 0x55555555},
-	{OP_ZR_E1H, MISC_REG_AEU_ENABLE1_FUNC_1_OUT_7, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE3_PXP_1, 0x5555},
-	{OP_WR_E1H, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_7, 0x20000},
-	{OP_WR_E1, MISC_REG_AEU_ENABLE4_PXP_1, 0x0},
-	{OP_ZR_E1H, MISC_REG_AEU_INVERTER_1_FUNC_1, 0x4},
-	{OP_WR_E1, MISC_REG_AEU_INVERTER_1_FUNC_1, 0x0},
-	{OP_ZR_E1, MISC_REG_AEU_INVERTER_2_FUNC_1, 0x3},
-	{OP_WR_E1, MISC_REG_AEU_MASK_ATTN_FUNC_1, 0x7},
-#define MISC_AEU_PORT1_END      2220
-
-};
-
-/*(DEBLOBBED)*/
-
-#endif /*__BNX2X_INIT_VALUES_H__*/
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2x_link.c linux-libre-2.6.31-gnu/drivers/net/bnx2x_link.c
--- linux-libre-2.6.30-gnu/drivers/net/bnx2x_link.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2x_link.c	2009-09-09 18:13:59.000000000 -0400
@@ -4212,13 +4212,14 @@
 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
 			      u8 *version, u16 len)
 {
-	struct bnx2x *bp = params->bp;
+	struct bnx2x *bp;
 	u32 ext_phy_type = 0;
 	u32 spirom_ver = 0;
 	u8 status = 0 ;
 
 	if (version == NULL || params == NULL)
 		return -EINVAL;
+	bp = params->bp;
 
 	spirom_ver = REG_RD(bp, params->shmem_base +
 		   offsetof(struct shmem_region,
diff -druN linux-libre-2.6.30-gnu/drivers/net/bnx2x_main.c linux-libre-2.6.31-gnu/drivers/net/bnx2x_main.c
--- linux-libre-2.6.30-gnu/drivers/net/bnx2x_main.c	2012-03-22 19:14:36.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bnx2x_main.c	2012-03-22 20:10:45.000000000 -0400
@@ -53,15 +53,22 @@
 
 #include "bnx2x.h"
 #include "bnx2x_init.h"
+#include "bnx2x_init_ops.h"
 #include "bnx2x_dump.h"
 #define bnx2x_init_block(bp, start, end) \
   return (printk(KERN_ERR PFX "%s: Missing Free firmware\n", bp->dev->name),\
 	  -EINVAL)
 
-#define DRV_MODULE_VERSION	"1.48.105"
-#define DRV_MODULE_RELDATE	"2009/03/02"
+#define DRV_MODULE_VERSION	"1.48.105-1"
+#define DRV_MODULE_RELDATE	"2009/04/22"
 #define BNX2X_BC_VER		0x040200
 
+#include <linux/firmware.h>
+#include "bnx2x_fw_file_hdr.h"
+/* FW files */
+#define FW_FILE_PREFIX_E1		"/*(DEBLOBBED)*/"
+#define FW_FILE_PREFIX_E1H		"/*(DEBLOBBED)*/"
+
 /* Time in jiffies before concluding the transmitter is hung */
 #define TX_TIMEOUT		(5*HZ)
 
@@ -480,8 +487,9 @@
 
 	mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104);
 	mark = ((mark + 0x3) & ~0x3);
-	printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark);
+	printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark);
 
+	printk(KERN_ERR PFX);
 	for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) {
 		for (word = 0; word < 8; word++)
 			data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH +
@@ -496,7 +504,7 @@
 		data[8] = 0x0;
 		printk(KERN_CONT "%s", (char *)data);
 	}
-	printk("\n" KERN_ERR PFX "end of fw dump\n");
+	printk(KERN_ERR PFX "end of fw dump\n");
 }
 
 static void bnx2x_panic_dump(struct bnx2x *bp)
@@ -1542,7 +1550,7 @@
 						    len, cqe, comp_ring_cons);
 #ifdef BNX2X_STOP_ON_ERROR
 					if (bp->panic)
-						return -EINVAL;
+						return 0;
 #endif
 
 					bnx2x_update_sge_prod(fp,
@@ -4430,7 +4438,7 @@
 		REG_WR16(bp, BAR_USTRORM_INTMEM +
 			 USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
 						     U_SB_ETH_RX_CQ_INDEX),
-			 bp->rx_ticks ? 0 : 1);
+			 (bp->rx_ticks/12) ? 0 : 1);
 
 		/* HC_INDEX_C_ETH_TX_CQ_CONS */
 		REG_WR8(bp, BAR_CSTRORM_INTMEM +
@@ -4440,7 +4448,7 @@
 		REG_WR16(bp, BAR_CSTRORM_INTMEM +
 			 CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
 						     C_SB_ETH_TX_CQ_INDEX),
-			 bp->tx_ticks ? 0 : 1);
+			 (bp->tx_ticks/12) ? 0 : 1);
 	}
 }
 
@@ -5235,13 +5243,15 @@
 	}
 }
 
-static int bnx2x_gunzip(struct bnx2x *bp, u8 *zbuf, int len)
+static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len)
 {
 	int n, rc;
 
 	/* check gzip header */
-	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
+	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) {
+		BNX2X_ERR("Bad gzip header\n");
 		return -EINVAL;
+	}
 
 	n = 10;
 
@@ -5250,7 +5260,7 @@
 	if (zbuf[3] & FNAME)
 		while ((zbuf[n++] != 0) && (n < len));
 
-	bp->strm->next_in = zbuf + n;
+	bp->strm->next_in = (typeof(bp->strm->next_in))zbuf + n;
 	bp->strm->avail_in = len - n;
 	bp->strm->next_out = bp->gunzip_buf;
 	bp->strm->avail_out = FW_BUF_SIZE;
@@ -5372,8 +5382,8 @@
 	msleep(50);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
 	msleep(50);
-	bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
-	bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
 
 	DP(NETIF_MSG_HW, "part2\n");
 
@@ -5437,8 +5447,8 @@
 	msleep(50);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x03);
 	msleep(50);
-	bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
-	bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
 #ifndef BCM_ISCSI
 	/* set NIC mode */
 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
@@ -5513,7 +5523,7 @@
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
 
-	bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END);
+	bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE);
 	if (CHIP_IS_E1H(bp))
 		REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp));
 
@@ -5521,14 +5531,14 @@
 	msleep(30);
 	REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
 
-	bnx2x_init_block(bp, PXP_COMMON_START, PXP_COMMON_END);
+	bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE);
 	if (CHIP_IS_E1(bp)) {
 		/* enable HW interrupt from PXP on USDM overflow
 		   bit 16 on INT_MASK_0 */
 		REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
 	}
 
-	bnx2x_init_block(bp, PXP2_COMMON_START, PXP2_COMMON_END);
+	bnx2x_init_block(bp, PXP2_BLOCK, COMMON_STAGE);
 	bnx2x_init_pxp(bp);
 
 #ifdef __BIG_ENDIAN
@@ -5574,60 +5584,60 @@
 	REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
 	REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
 
-	bnx2x_init_block(bp, DMAE_COMMON_START, DMAE_COMMON_END);
+	bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE);
 
 	/* clean the DMAE memory */
 	bp->dmae_ready = 1;
 	bnx2x_init_fill(bp, TSEM_REG_PRAM, 0, 8);
 
-	bnx2x_init_block(bp, TCM_COMMON_START, TCM_COMMON_END);
-	bnx2x_init_block(bp, UCM_COMMON_START, UCM_COMMON_END);
-	bnx2x_init_block(bp, CCM_COMMON_START, CCM_COMMON_END);
-	bnx2x_init_block(bp, XCM_COMMON_START, XCM_COMMON_END);
+	bnx2x_init_block(bp, TCM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, UCM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, CCM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, XCM_BLOCK, COMMON_STAGE);
 
 	bnx2x_read_dmae(bp, XSEM_REG_PASSIVE_BUFFER, 3);
 	bnx2x_read_dmae(bp, CSEM_REG_PASSIVE_BUFFER, 3);
 	bnx2x_read_dmae(bp, TSEM_REG_PASSIVE_BUFFER, 3);
 	bnx2x_read_dmae(bp, USEM_REG_PASSIVE_BUFFER, 3);
 
-	bnx2x_init_block(bp, QM_COMMON_START, QM_COMMON_END);
+	bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE);
 	/* soft reset pulse */
 	REG_WR(bp, QM_REG_SOFT_RESET, 1);
 	REG_WR(bp, QM_REG_SOFT_RESET, 0);
 
 #ifdef BCM_ISCSI
-	bnx2x_init_block(bp, TIMERS_COMMON_START, TIMERS_COMMON_END);
+	bnx2x_init_block(bp, TIMERS_BLOCK, COMMON_STAGE);
 #endif
 
-	bnx2x_init_block(bp, DQ_COMMON_START, DQ_COMMON_END);
+	bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE);
 	REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT);
 	if (!CHIP_REV_IS_SLOW(bp)) {
 		/* enable hw interrupt from doorbell Q */
 		REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
 	}
 
-	bnx2x_init_block(bp, BRB1_COMMON_START, BRB1_COMMON_END);
-	bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+	bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
 	REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
 	/* set NIC mode */
 	REG_WR(bp, PRS_REG_NIC_MODE, 1);
 	if (CHIP_IS_E1H(bp))
 		REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp));
 
-	bnx2x_init_block(bp, TSDM_COMMON_START, TSDM_COMMON_END);
-	bnx2x_init_block(bp, CSDM_COMMON_START, CSDM_COMMON_END);
-	bnx2x_init_block(bp, USDM_COMMON_START, USDM_COMMON_END);
-	bnx2x_init_block(bp, XSDM_COMMON_START, XSDM_COMMON_END);
+	bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, USDM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, XSDM_BLOCK, COMMON_STAGE);
 
 	bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
 	bnx2x_init_fill(bp, USTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
 	bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
 	bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR, 0, STORM_INTMEM_SIZE(bp));
 
-	bnx2x_init_block(bp, TSEM_COMMON_START, TSEM_COMMON_END);
-	bnx2x_init_block(bp, USEM_COMMON_START, USEM_COMMON_END);
-	bnx2x_init_block(bp, CSEM_COMMON_START, CSEM_COMMON_END);
-	bnx2x_init_block(bp, XSEM_COMMON_START, XSEM_COMMON_END);
+	bnx2x_init_block(bp, TSEM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, USEM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE);
 
 	/* sync semi rtc */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
@@ -5635,16 +5645,16 @@
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
 	       0x80000000);
 
-	bnx2x_init_block(bp, UPB_COMMON_START, UPB_COMMON_END);
-	bnx2x_init_block(bp, XPB_COMMON_START, XPB_COMMON_END);
-	bnx2x_init_block(bp, PBF_COMMON_START, PBF_COMMON_END);
+	bnx2x_init_block(bp, UPB_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
 
 	REG_WR(bp, SRC_REG_SOFT_RST, 1);
 	for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4) {
 		REG_WR(bp, i, 0xc0cac01a);
 		/* TODO: replace with something meaningful */
 	}
-	bnx2x_init_block(bp, SRCH_COMMON_START, SRCH_COMMON_END);
+	bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE);
 	REG_WR(bp, SRC_REG_SOFT_RST, 0);
 
 	if (sizeof(union cdu_context) != 1024)
@@ -5652,7 +5662,7 @@
 		printk(KERN_ALERT PFX "please adjust the size of"
 		       " cdu_context(%ld)\n", (long)sizeof(union cdu_context));
 
-	bnx2x_init_block(bp, CDU_COMMON_START, CDU_COMMON_END);
+	bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE);
 	val = (4 << 24) + (0 << 12) + 1024;
 	REG_WR(bp, CDU_REG_CDU_GLOBAL_PARAMS, val);
 	if (CHIP_IS_E1(bp)) {
@@ -5661,7 +5671,7 @@
 		REG_WR(bp, CDU_REG_CDU_DEBUG, 0);
 	}
 
-	bnx2x_init_block(bp, CFC_COMMON_START, CFC_COMMON_END);
+	bnx2x_init_block(bp, CFC_BLOCK, COMMON_STAGE);
 	REG_WR(bp, CFC_REG_INIT_REG, 0x7FF);
 	/* enable context validation interrupt from CFC */
 	REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
@@ -5669,20 +5679,25 @@
 	/* set the thresholds to prevent CFC/CDU race */
 	REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
 
-	bnx2x_init_block(bp, HC_COMMON_START, HC_COMMON_END);
-	bnx2x_init_block(bp, MISC_AEU_COMMON_START, MISC_AEU_COMMON_END);
+	bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
+	bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
 
 	/* PXPCS COMMON comes here */
+	bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
 	/* Reset PCIE errors for debug */
 	REG_WR(bp, 0x2814, 0xffffffff);
 	REG_WR(bp, 0x3820, 0xffffffff);
 
 	/* EMAC0 COMMON comes here */
+	bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
 	/* EMAC1 COMMON comes here */
+	bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
 	/* DBU COMMON comes here */
+	bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
 	/* DBG COMMON comes here */
+	bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
 
-	bnx2x_init_block(bp, NIG_COMMON_START, NIG_COMMON_END);
+	bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
 	if (CHIP_IS_E1H(bp)) {
 		REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp));
 		REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp));
@@ -5766,6 +5781,7 @@
 static int bnx2x_init_port(struct bnx2x *bp)
 {
 	int port = BP_PORT(bp);
+	int init_stage = port ? PORT1_STAGE : PORT0_STAGE;
 	u32 low, high;
 	u32 val;
 
@@ -5774,7 +5790,9 @@
 	REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0);
 
 	/* Port PXP comes here */
+	bnx2x_init_block(bp, PXP_BLOCK, init_stage);
 	/* Port PXP2 comes here */
+	bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
 #ifdef BCM_ISCSI
 	/* Port0  1
 	 * Port1  385 */
@@ -5801,21 +5819,19 @@
 	REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i));
 #endif
 	/* Port CMs come here */
-	bnx2x_init_block(bp, (port ? XCM_PORT1_START : XCM_PORT0_START),
-			     (port ? XCM_PORT1_END : XCM_PORT0_END));
+	bnx2x_init_block(bp, XCM_BLOCK, init_stage);
 
 	/* Port QM comes here */
 #ifdef BCM_ISCSI
 	REG_WR(bp, TM_REG_LIN0_SCAN_TIME + func*4, 1024/64*20);
 	REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + func*4, 31);
 
-	bnx2x_init_block(bp, func ? TIMERS_PORT1_START : TIMERS_PORT0_START,
-			     func ? TIMERS_PORT1_END : TIMERS_PORT0_END);
+	bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
 #endif
 	/* Port DQ comes here */
+	bnx2x_init_block(bp, DQ_BLOCK, init_stage);
 
-	bnx2x_init_block(bp, (port ? BRB1_PORT1_START : BRB1_PORT0_START),
-			     (port ? BRB1_PORT1_END : BRB1_PORT0_END));
+	bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
 	if (CHIP_REV_IS_SLOW(bp) && !CHIP_IS_E1H(bp)) {
 		/* no pause for emulation and FPGA */
 		low = 0;
@@ -5840,25 +5856,27 @@
 
 
 	/* Port PRS comes here */
+	bnx2x_init_block(bp, PRS_BLOCK, init_stage);
 	/* Port TSDM comes here */
+	bnx2x_init_block(bp, TSDM_BLOCK, init_stage);
 	/* Port CSDM comes here */
+	bnx2x_init_block(bp, CSDM_BLOCK, init_stage);
 	/* Port USDM comes here */
+	bnx2x_init_block(bp, USDM_BLOCK, init_stage);
 	/* Port XSDM comes here */
+	bnx2x_init_block(bp, XSDM_BLOCK, init_stage);
 
-	bnx2x_init_block(bp, port ? TSEM_PORT1_START : TSEM_PORT0_START,
-			     port ? TSEM_PORT1_END : TSEM_PORT0_END);
-	bnx2x_init_block(bp, port ? USEM_PORT1_START : USEM_PORT0_START,
-			     port ? USEM_PORT1_END : USEM_PORT0_END);
-	bnx2x_init_block(bp, port ? CSEM_PORT1_START : CSEM_PORT0_START,
-			     port ? CSEM_PORT1_END : CSEM_PORT0_END);
-	bnx2x_init_block(bp, port ? XSEM_PORT1_START : XSEM_PORT0_START,
-			     port ? XSEM_PORT1_END : XSEM_PORT0_END);
+	bnx2x_init_block(bp, TSEM_BLOCK, init_stage);
+	bnx2x_init_block(bp, USEM_BLOCK, init_stage);
+	bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
+	bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
 
 	/* Port UPB comes here */
+	bnx2x_init_block(bp, UPB_BLOCK, init_stage);
 	/* Port XPB comes here */
+	bnx2x_init_block(bp, XPB_BLOCK, init_stage);
 
-	bnx2x_init_block(bp, port ? PBF_PORT1_START : PBF_PORT0_START,
-			     port ? PBF_PORT1_END : PBF_PORT0_END);
+	bnx2x_init_block(bp, PBF_BLOCK, init_stage);
 
 	/* configure PBF to work without PAUSE mtu 9000 */
 	REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
@@ -5888,18 +5906,17 @@
 	/* Port SRCH comes here */
 #endif
 	/* Port CDU comes here */
+	bnx2x_init_block(bp, CDU_BLOCK, init_stage);
 	/* Port CFC comes here */
+	bnx2x_init_block(bp, CFC_BLOCK, init_stage);
 
 	if (CHIP_IS_E1(bp)) {
 		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
 		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
 	}
-	bnx2x_init_block(bp, port ? HC_PORT1_START : HC_PORT0_START,
-			     port ? HC_PORT1_END : HC_PORT0_END);
+	bnx2x_init_block(bp, HC_BLOCK, init_stage);
 
-	bnx2x_init_block(bp, port ? MISC_AEU_PORT1_START :
-				    MISC_AEU_PORT0_START,
-			     port ? MISC_AEU_PORT1_END : MISC_AEU_PORT0_END);
+	bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage);
 	/* init aeu_mask_attn_func_0/1:
 	 *  - SF mode: bits 3-7 are masked. only bits 0-2 are in use
 	 *  - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
@@ -5908,13 +5925,17 @@
 	       (IS_E1HMF(bp) ? 0xF7 : 0x7));
 
 	/* Port PXPCS comes here */
+	bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
 	/* Port EMAC0 comes here */
+	bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
 	/* Port EMAC1 comes here */
+	bnx2x_init_block(bp, EMAC1_BLOCK, init_stage);
 	/* Port DBU comes here */
+	bnx2x_init_block(bp, DBU_BLOCK, init_stage);
 	/* Port DBG comes here */
+	bnx2x_init_block(bp, DBG_BLOCK, init_stage);
 
-	bnx2x_init_block(bp, port ? NIG_PORT1_START : NIG_PORT0_START,
-			     port ? NIG_PORT1_END : NIG_PORT0_END);
+	bnx2x_init_block(bp, NIG_BLOCK, init_stage);
 
 	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
 
@@ -5934,7 +5955,9 @@
 	}
 
 	/* Port MCP comes here */
+	bnx2x_init_block(bp, MCP_BLOCK, init_stage);
 	/* Port DMAE comes here */
+	bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
 
 	switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
@@ -6039,7 +6062,7 @@
 	if (CHIP_IS_E1H(bp)) {
 		for (i = 0; i < 9; i++)
 			bnx2x_init_block(bp,
-					 cm_start[func][i], cm_end[func][i]);
+					 cm_blocks[i], FUNC0_STAGE + func);
 
 		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
 		REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov);
@@ -6052,7 +6075,7 @@
 		REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
 		REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
 	}
-	bnx2x_init_block(bp, hc_limits[func][0], hc_limits[func][1]);
+	bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
 
 	/* Reset PCIE errors for debug */
 	REG_WR(bp, 0x2114, 0xffffffff);
@@ -7335,7 +7358,7 @@
 #ifdef BNX2X_STOP_ON_ERROR
 	BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
 		  " so reset not done to allow debug dump,\n"
-	 KERN_ERR " you will need to reboot when done\n");
+		  " you will need to reboot when done\n");
 	return;
 #endif
 
@@ -8618,6 +8641,14 @@
 	return 0;
 }
 
+static u32
+bnx2x_get_link(struct net_device *dev)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+
+	return bp->link_vars.link_up;
+}
+
 static int bnx2x_get_eeprom_len(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
@@ -9042,12 +9073,12 @@
 	struct bnx2x *bp = netdev_priv(dev);
 
 	bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
-	if (bp->rx_ticks > 3000)
-		bp->rx_ticks = 3000;
+	if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT)
+		bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT;
 
 	bp->tx_ticks = (u16) coal->tx_coalesce_usecs;
-	if (bp->tx_ticks > 0x3000)
-		bp->tx_ticks = 0x3000;
+	if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT)
+		bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT;
 
 	if (netif_running(dev))
 		bnx2x_update_coalesce(bp);
@@ -10015,7 +10046,7 @@
 	.get_msglevel		= bnx2x_get_msglevel,
 	.set_msglevel		= bnx2x_set_msglevel,
 	.nway_reset		= bnx2x_nway_reset,
-	.get_link		= ethtool_op_get_link,
+	.get_link		= bnx2x_get_link,
 	.get_eeprom_len		= bnx2x_get_eeprom_len,
 	.get_eeprom		= bnx2x_get_eeprom,
 	.set_eeprom		= bnx2x_set_eeprom,
@@ -10598,7 +10629,6 @@
 	mmiowb();
 
 	fp->tx_bd_prod += nbd;
-	dev->trans_start = jiffies;
 
 	if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
 		/* We want bnx2x_tx_int to "see" the updated tx_bd_prod
@@ -11085,6 +11115,129 @@
 	val = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
 	return val;
 }
+/*(DEBLOBBED)*/
+
+static void inline be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
+{
+	u32 i;
+	const __be32 *source = (const __be32*)_source;
+	u32 *target = (u32*)_target;
+
+	for (i = 0; i < n/4; i++)
+		target[i] = be32_to_cpu(source[i]);
+}
+
+/*
+   Ops array is stored in the following format:
+   {op(8bit), offset(24bit, big endian), data(32bit, big endian)}
+ */
+static void inline bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
+{
+	u32 i, j, tmp;
+	const __be32 *source = (const __be32*)_source;
+	struct raw_op *target = (struct raw_op*)_target;
+
+	for (i = 0, j = 0; i < n/8; i++, j+=2) {
+		tmp = be32_to_cpu(source[j]);
+		target[i].op = (tmp >> 24) & 0xff;
+		target[i].offset =  tmp & 0xffffff;
+		target[i].raw_data = be32_to_cpu(source[j+1]);
+	}
+}
+static void inline be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
+{
+	u32 i;
+	u16 *target = (u16*)_target;
+	const __be16 *source = (const __be16*)_source;
+
+	for (i = 0; i < n/2; i++)
+		target[i] = be16_to_cpu(source[i]);
+}
+
+#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \
+	do {   \
+		u32 len = be32_to_cpu(fw_hdr->arr.len);   \
+		bp->arr = kmalloc(len, GFP_KERNEL);  \
+		if (!bp->arr) { \
+			printk(KERN_ERR PFX "Failed to allocate %d bytes for "#arr"\n", len); \
+			goto lbl; \
+		} \
+		func(bp->firmware->data + \
+			be32_to_cpu(fw_hdr->arr.offset), \
+			(u8*)bp->arr, len); \
+	} while (0)
+
+
+static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
+{
+	char fw_file_name[40] = {0};
+        int rc, offset;
+	struct bnx2x_fw_file_hdr *fw_hdr;
+
+	/* Create a FW file name */
+	if (CHIP_IS_E1(bp))
+                offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1);
+	else
+		offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H);
+
+	/*(DEBLOBBED)*/
+
+	printk(KERN_INFO PFX "Loading %s\n", fw_file_name);
+
+	rc = reject_firmware(&bp->firmware, fw_file_name, dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Can't load firmware file %s\n", fw_file_name);
+		goto reject_firmware_exit;
+	}
+
+	/*(DEBLOBBED)*/
+	if (rc) {
+		printk(KERN_ERR PFX "Corrupt firmware file %s\n", fw_file_name);
+		goto reject_firmware_exit;
+	}
+
+	fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data;
+
+	/* Initialize the pointers to the init arrays */
+	/* Blob */
+	BNX2X_ALLOC_AND_SET(init_data, reject_firmware_exit, be32_to_cpu_n);
+
+	/* Opcodes */
+	BNX2X_ALLOC_AND_SET(init_ops, init_ops_alloc_err, bnx2x_prep_ops);
+
+	/* Offsets */
+	BNX2X_ALLOC_AND_SET(init_ops_offsets, init_offsets_alloc_err, be16_to_cpu_n);
+
+	/* STORMs firmware */
+	bp->tsem_int_table_data = bp->firmware->data +
+		be32_to_cpu(fw_hdr->tsem_int_table_data.offset);
+	bp->tsem_pram_data      = bp->firmware->data +
+		be32_to_cpu(fw_hdr->tsem_pram_data.offset);
+	bp->usem_int_table_data = bp->firmware->data +
+		be32_to_cpu(fw_hdr->usem_int_table_data.offset);
+	bp->usem_pram_data      = bp->firmware->data +
+		be32_to_cpu(fw_hdr->usem_pram_data.offset);
+	bp->xsem_int_table_data = bp->firmware->data +
+		be32_to_cpu(fw_hdr->xsem_int_table_data.offset);
+	bp->xsem_pram_data      = bp->firmware->data +
+		be32_to_cpu(fw_hdr->xsem_pram_data.offset);
+	bp->csem_int_table_data = bp->firmware->data +
+		be32_to_cpu(fw_hdr->csem_int_table_data.offset);
+	bp->csem_pram_data      = bp->firmware->data +
+		be32_to_cpu(fw_hdr->csem_pram_data.offset);
+
+	return 0;
+init_offsets_alloc_err:
+	kfree(bp->init_ops);
+init_ops_alloc_err:
+	kfree(bp->init_data);
+reject_firmware_exit:
+	release_firmware(bp->firmware);
+
+	return rc;
+}
+
+
 
 static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
@@ -11119,6 +11272,13 @@
 	if (rc)
 		goto init_one_exit;
 
+	/* Set init arrays */
+	rc = bnx2x_init_firmware(bp, &pdev->dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Error loading firmware\n");
+		goto init_one_exit;
+	}
+
 	rc = register_netdev(dev);
 	if (rc) {
 		dev_err(&pdev->dev, "Cannot register net device\n");
@@ -11166,6 +11326,11 @@
 
 	unregister_netdev(dev);
 
+	kfree(bp->init_ops_offsets);
+	kfree(bp->init_ops);
+	kfree(bp->init_data);
+	release_firmware(bp->firmware);
+
 	if (bp->regview)
 		iounmap(bp->regview);
 
@@ -11415,13 +11580,20 @@
 
 static int __init bnx2x_init(void)
 {
+	int ret;
+
 	bnx2x_wq = create_singlethread_workqueue("bnx2x");
 	if (bnx2x_wq == NULL) {
 		printk(KERN_ERR PFX "Cannot create workqueue\n");
 		return -ENOMEM;
 	}
 
-	return pci_register_driver(&bnx2x_pci_driver);
+	ret = pci_register_driver(&bnx2x_pci_driver);
+	if (ret) {
+		printk(KERN_ERR PFX "Cannot register driver\n");
+		destroy_workqueue(bnx2x_wq);
+	}
+	return ret;
 }
 
 static void __exit bnx2x_cleanup(void)
@@ -11434,3 +11606,4 @@
 module_init(bnx2x_init);
 module_exit(bnx2x_cleanup);
 
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/bonding/bond_3ad.c linux-libre-2.6.31-gnu/drivers/net/bonding/bond_3ad.c
--- linux-libre-2.6.30-gnu/drivers/net/bonding/bond_3ad.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bonding/bond_3ad.c	2009-09-09 18:13:59.000000000 -0400
@@ -1850,9 +1850,10 @@
  * Can be called only after the mac address of the bond is set.
  */
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
-{                         
+{
 	// check that the bond is not initialized yet
-	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->dev->dev_addr))) {
+	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
+				bond->dev->dev_addr)) {
 
 		aggregator_identifier = 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/bonding/bond_3ad.h linux-libre-2.6.31-gnu/drivers/net/bonding/bond_3ad.h
--- linux-libre-2.6.30-gnu/drivers/net/bonding/bond_3ad.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bonding/bond_3ad.h	2009-09-09 18:13:59.000000000 -0400
@@ -26,10 +26,10 @@
 #include <asm/byteorder.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/if_ether.h>
 
 // General definitions
-#define BOND_ETH_P_LACPDU       0x8809
-#define PKT_TYPE_LACPDU         cpu_to_be16(BOND_ETH_P_LACPDU)
+#define PKT_TYPE_LACPDU         cpu_to_be16(ETH_P_SLOW)
 #define AD_TIMER_INTERVAL       100 /*msec*/
 
 #define MULTICAST_LACPDU_ADDR    {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
diff -druN linux-libre-2.6.30-gnu/drivers/net/bonding/bonding.h linux-libre-2.6.31-gnu/drivers/net/bonding/bonding.h
--- linux-libre-2.6.30-gnu/drivers/net/bonding/bonding.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bonding/bonding.h	2009-09-09 18:13:59.000000000 -0400
@@ -286,8 +286,7 @@
 static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
 	struct bonding *bond = netdev_priv(slave->dev->master);
-	if (bond->params.mode != BOND_MODE_TLB &&
-	    bond->params.mode != BOND_MODE_ALB)
+	if (!bond_is_lb(bond))
 		slave->state = BOND_STATE_BACKUP;
 	slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
 	if (slave_do_arp_validate(bond, slave))
@@ -322,8 +321,7 @@
 
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
 int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
-int bond_create(char *name, struct bond_params *params);
-void bond_destroy(struct bonding *bond);
+int bond_create(const char *name);
 int  bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev);
 int bond_create_sysfs(void);
 void bond_destroy_sysfs(void);
@@ -350,12 +348,8 @@
 extern const struct bond_parm_tbl xmit_hashtype_tbl[];
 extern const struct bond_parm_tbl arp_validate_tbl[];
 extern const struct bond_parm_tbl fail_over_mac_tbl[];
-extern struct bond_params bonding_defaults;
 extern struct bond_parm_tbl ad_select_tbl[];
 
-/* exported from bond_sysfs.c */
-extern struct rw_semaphore bonding_rwsem;
-
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 void bond_send_unsolicited_na(struct bonding *bond);
 void bond_register_ipv6_notifier(void);
diff -druN linux-libre-2.6.30-gnu/drivers/net/bonding/bond_main.c linux-libre-2.6.31-gnu/drivers/net/bonding/bond_main.c
--- linux-libre-2.6.30-gnu/drivers/net/bonding/bond_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bonding/bond_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,10 +51,10 @@
 #include <linux/ctype.h>
 #include <linux/inet.h>
 #include <linux/bitops.h>
+#include <linux/io.h>
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
@@ -89,19 +89,19 @@
 static int num_grat_arp = 1;
 static int num_unsol_na = 1;
 static int miimon	= BOND_LINK_MON_INTERV;
-static int updelay	= 0;
-static int downdelay	= 0;
+static int updelay;
+static int downdelay;
 static int use_carrier	= 1;
-static char *mode	= NULL;
-static char *primary	= NULL;
-static char *lacp_rate	= NULL;
-static char *ad_select  = NULL;
-static char *xmit_hash_policy = NULL;
+static char *mode;
+static char *primary;
+static char *lacp_rate;
+static char *ad_select;
+static char *xmit_hash_policy;
 static int arp_interval = BOND_LINK_ARP_INTERV;
-static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
-static char *arp_validate = NULL;
-static char *fail_over_mac = NULL;
-struct bond_params bonding_defaults;
+static char *arp_ip_target[BOND_MAX_ARP_TARGETS];
+static char *arp_validate;
+static char *fail_over_mac;
+static struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -151,14 +151,14 @@
 LIST_HEAD(bond_dev_list);
 
 #ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *bond_proc_dir = NULL;
+static struct proc_dir_entry *bond_proc_dir;
 #endif
 
-static __be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
-static int arp_ip_count	= 0;
+static __be32 arp_target[BOND_MAX_ARP_TARGETS];
+static int arp_ip_count;
 static int bond_mode	= BOND_MODE_ROUNDROBIN;
-static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2;
-static int lacp_fast	= 0;
+static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
+static int lacp_fast;
 
 
 const struct bond_parm_tbl bond_lacp_tbl[] = {
@@ -210,6 +210,7 @@
 /*-------------------------- Forward declarations ---------------------------*/
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
+static int bond_init(struct net_device *bond_dev);
 static void bond_deinit(struct net_device *bond_dev);
 
 /*---------------------------- General routines -----------------------------*/
@@ -221,7 +222,7 @@
 		[BOND_MODE_ACTIVEBACKUP] = "fault-tolerance (active-backup)",
 		[BOND_MODE_XOR] = "load balancing (xor)",
 		[BOND_MODE_BROADCAST] = "fault-tolerance (broadcast)",
-		[BOND_MODE_8023AD]= "IEEE 802.3ad Dynamic link aggregation",
+		[BOND_MODE_8023AD] = "IEEE 802.3ad Dynamic link aggregation",
 		[BOND_MODE_TLB] = "transmit load balancing",
 		[BOND_MODE_ALB] = "adaptive load balancing",
 	};
@@ -246,12 +247,11 @@
 	struct vlan_entry *vlan;
 
 	pr_debug("bond: %s, vlan id %d\n",
-		(bond ? bond->dev->name: "None"), vlan_id);
+		(bond ? bond->dev->name : "None"), vlan_id);
 
 	vlan = kzalloc(sizeof(struct vlan_entry), GFP_KERNEL);
-	if (!vlan) {
+	if (!vlan)
 		return -ENOMEM;
-	}
 
 	INIT_LIST_HEAD(&vlan->vlan_list);
 	vlan->vlan_id = vlan_id;
@@ -351,16 +351,15 @@
  *
  * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL,
  * or @curr->next otherwise (even if it is @curr itself again).
- * 
+ *
  * Caller must hold bond->lock
  */
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
 {
 	struct vlan_entry *next, *last;
 
-	if (list_empty(&bond->vlan_list)) {
+	if (list_empty(&bond->vlan_list))
 		return NULL;
-	}
 
 	if (!curr) {
 		next = list_entry(bond->vlan_list.next,
@@ -382,11 +381,11 @@
 
 /**
  * bond_dev_queue_xmit - Prepare skb for xmit.
- * 
+ *
  * @bond: bond device that got this skb for tx.
  * @skb: hw accel VLAN tagged skb to transmit
  * @slave_dev: slave that is supposed to xmit this skbuff
- * 
+ *
  * When the bond gets an skb to transmit that is
  * already hardware accelerated VLAN tagged, and it
  * needs to relay this skb to a slave that is not
@@ -394,7 +393,8 @@
  * i.e. strip the hwaccel tag and re-insert it as part
  * of the payload.
  */
-int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev)
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
+			struct net_device *slave_dev)
 {
 	unsigned short uninitialized_var(vlan_id);
 
@@ -428,7 +428,7 @@
  * b. The operation is protected by the RTNL semaphore in the 8021q code,
  * c. Holding a lock with BH disabled while directly calling a base driver
  *    entry point is generally a BAD idea.
- * 
+ *
  * The design of synchronization/protection for this operation in the 8021q
  * module is good for one or more VLAN devices over a single physical device
  * and cannot be extended for a teaming solution like bonding, so there is a
@@ -443,7 +443,8 @@
  * @bond_dev: bonding net device that got called
  * @grp: vlan group being registered
  */
-static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp)
+static void bond_vlan_rx_register(struct net_device *bond_dev,
+				  struct vlan_group *grp)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave;
@@ -485,7 +486,7 @@
 
 	res = bond_add_vlan(bond, vid);
 	if (res) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Error: Failed to add vlan id %d\n",
 		       bond_dev->name, vid);
 	}
@@ -520,7 +521,7 @@
 
 	res = bond_del_vlan(bond, vid);
 	if (res) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Error: Failed to remove vlan id %d\n",
 		       bond_dev->name, vid);
 	}
@@ -551,7 +552,8 @@
 	write_unlock_bh(&bond->lock);
 }
 
-static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev)
+static void bond_del_vlans_from_slave(struct bonding *bond,
+				      struct net_device *slave_dev)
 {
 	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
 	struct vlan_entry *vlan;
@@ -673,7 +675,7 @@
  * if <dev> supports MII link status reporting, check its link status.
  *
  * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(),
- * depening upon the setting of the use_carrier parameter.
+ * depending upon the setting of the use_carrier parameter.
  *
  * Return either BMSR_LSTATUS, meaning that the link is up (or we
  * can't tell and just pretend it is), or 0, meaning that the link is
@@ -685,16 +687,29 @@
  * It'd be nice if there was a good way to tell if a driver supports
  * netif_carrier, but there really isn't.
  */
-static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
+static int bond_check_dev_link(struct bonding *bond,
+			       struct net_device *slave_dev, int reporting)
 {
 	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	static int (*ioctl)(struct net_device *, struct ifreq *, int);
 	struct ifreq ifr;
 	struct mii_ioctl_data *mii;
 
 	if (bond->params.use_carrier)
 		return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
 
+	/* Try to get link status using Ethtool first. */
+	if (slave_dev->ethtool_ops) {
+		if (slave_dev->ethtool_ops->get_link) {
+			u32 link;
+
+			link = slave_dev->ethtool_ops->get_link(slave_dev);
+
+			return link ? BMSR_LSTATUS : 0;
+		}
+	}
+
+	/* Ethtool can't be used, fallback to MII ioctls. */
 	ioctl = slave_ops->ndo_do_ioctl;
 	if (ioctl) {
 		/* TODO: set pointer to correct ioctl on a per team member */
@@ -714,23 +729,8 @@
 		mii = if_mii(&ifr);
 		if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
 			mii->reg_num = MII_BMSR;
-			if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) == 0) {
-				return (mii->val_out & BMSR_LSTATUS);
-			}
-		}
-	}
-
-	/*
-	 * Some drivers cache ETHTOOL_GLINK for a period of time so we only
-	 * attempt to get link status from it if the above MII ioctls fail.
-	 */
-	if (slave_dev->ethtool_ops) {
-		if (slave_dev->ethtool_ops->get_link) {
-			u32 link;
-
-			link = slave_dev->ethtool_ops->get_link(slave_dev);
-
-			return link ? BMSR_LSTATUS : 0;
+			if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) == 0)
+				return mii->val_out & BMSR_LSTATUS;
 		}
 	}
 
@@ -740,7 +740,7 @@
 	 * cannot report link status).  If not reporting, pretend
 	 * we're ok.
 	 */
-	return (reporting ? -1 : BMSR_LSTATUS);
+	return reporting ? -1 : BMSR_LSTATUS;
 }
 
 /*----------------------------- Multicast list ------------------------------*/
@@ -748,7 +748,8 @@
 /*
  * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise
  */
-static inline int bond_is_dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
+static inline int bond_is_dmi_same(const struct dev_mc_list *dmi1,
+				   const struct dev_mc_list *dmi2)
 {
 	return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 &&
 			dmi1->dmi_addrlen == dmi2->dmi_addrlen;
@@ -757,14 +758,14 @@
 /*
  * returns dmi entry if found, NULL otherwise
  */
-static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list)
+static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi,
+						 struct dev_mc_list *mc_list)
 {
 	struct dev_mc_list *idmi;
 
 	for (idmi = mc_list; idmi; idmi = idmi->next) {
-		if (bond_is_dmi_same(dmi, idmi)) {
+		if (bond_is_dmi_same(dmi, idmi))
 			return idmi;
-		}
 	}
 
 	return NULL;
@@ -826,15 +827,14 @@
 {
 	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
-		if (bond->curr_active_slave) {
+		if (bond->curr_active_slave)
 			dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0);
-		}
 	} else {
 		struct slave *slave;
 		int i;
-		bond_for_each_slave(bond, slave, i) {
+
+		bond_for_each_slave(bond, slave, i)
 			dev_mc_add(slave->dev, addr, alen, 0);
-		}
 	}
 }
 
@@ -846,9 +846,9 @@
 {
 	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
-		if (bond->curr_active_slave) {
-			dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0);
-		}
+		if (bond->curr_active_slave)
+			dev_mc_delete(bond->curr_active_slave->dev, addr,
+				      alen, 0);
 	} else {
 		struct slave *slave;
 		int i;
@@ -872,9 +872,8 @@
 	rcu_read_lock();
 	in_dev = __in_dev_get_rcu(bond->dev);
 	if (in_dev) {
-		for (im = in_dev->mc_list; im; im = im->next) {
+		for (im = in_dev->mc_list; im; im = im->next)
 			ip_mc_rejoin_group(im);
-		}
 	}
 
 	rcu_read_unlock();
@@ -893,7 +892,8 @@
 		kfree(dmi);
 		dmi = bond->mc_list;
 	}
-        bond->mc_list = NULL;
+
+	bond->mc_list = NULL;
 }
 
 /*
@@ -926,14 +926,14 @@
 /*
  * flush all members of flush->mc_list from device dev->mc_list
  */
-static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev)
+static void bond_mc_list_flush(struct net_device *bond_dev,
+			       struct net_device *slave_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct dev_mc_list *dmi;
 
-	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
+	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next)
 		dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-	}
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* del lacpdu mc addr from mc list */
@@ -950,44 +950,40 @@
  * old active slaves (if any) according to the multicast mode, and
  * promiscuous flags unconditionally.
  */
-static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct slave *old_active)
+static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
+			 struct slave *old_active)
 {
 	struct dev_mc_list *dmi;
 
-	if (!USES_PRIMARY(bond->params.mode)) {
+	if (!USES_PRIMARY(bond->params.mode))
 		/* nothing to do -  mc list is already up-to-date on
 		 * all slaves
 		 */
 		return;
-	}
 
 	if (old_active) {
-		if (bond->dev->flags & IFF_PROMISC) {
+		if (bond->dev->flags & IFF_PROMISC)
 			dev_set_promiscuity(old_active->dev, -1);
-		}
 
-		if (bond->dev->flags & IFF_ALLMULTI) {
+		if (bond->dev->flags & IFF_ALLMULTI)
 			dev_set_allmulti(old_active->dev, -1);
-		}
 
-		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
-			dev_mc_delete(old_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		}
+		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next)
+			dev_mc_delete(old_active->dev, dmi->dmi_addr,
+				      dmi->dmi_addrlen, 0);
 	}
 
 	if (new_active) {
 		/* FIXME: Signal errors upstream. */
-		if (bond->dev->flags & IFF_PROMISC) {
+		if (bond->dev->flags & IFF_PROMISC)
 			dev_set_promiscuity(new_active->dev, 1);
-		}
 
-		if (bond->dev->flags & IFF_ALLMULTI) {
+		if (bond->dev->flags & IFF_ALLMULTI)
 			dev_set_allmulti(new_active->dev, 1);
-		}
 
-		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
-			dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		}
+		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next)
+			dev_mc_add(new_active->dev, dmi->dmi_addr,
+				   dmi->dmi_addrlen, 0);
 		bond_resend_igmp_join_requests(bond);
 	}
 }
@@ -1041,7 +1037,7 @@
 
 		rv = dev_set_mac_address(new_active->dev, &saddr);
 		if (rv) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: Error %d setting MAC of slave %s\n",
 			       bond->dev->name, -rv, new_active->dev->name);
 			goto out;
@@ -1055,7 +1051,7 @@
 
 		rv = dev_set_mac_address(old_active->dev, &saddr);
 		if (rv)
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: Error %d setting MAC of slave %s\n",
 			       bond->dev->name, -rv, new_active->dev->name);
 out:
@@ -1063,7 +1059,7 @@
 		write_lock_bh(&bond->curr_slave_lock);
 		break;
 	default:
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: bond_do_fail_over_mac impossible: bad policy %d\n",
 		       bond->dev->name, bond->params.fail_over_mac);
 		break;
@@ -1088,17 +1084,17 @@
 	new_active = old_active = bond->curr_active_slave;
 
 	if (!new_active) { /* there were no active slaves left */
-		if (bond->slave_cnt > 0) {  /* found one slave */
+		if (bond->slave_cnt > 0)   /* found one slave */
 			new_active = bond->first_slave;
-		} else {
+		else
 			return NULL; /* still no slave, return NULL */
-		}
 	}
 
-	/* first try the primary link; if arping, a link must tx/rx traffic
-	 * before it can be considered the curr_active_slave - also, we would skip
-	 * slaves between the curr_active_slave and primary_slave that may be up
-	 * and able to arp
+	/*
+	 * first try the primary link; if arping, a link must tx/rx
+	 * traffic before it can be considered the curr_active_slave.
+	 * also, we would skip slaves between the curr_active_slave
+	 * and primary_slave that may be up and able to arp
 	 */
 	if ((bond->primary_slave) &&
 	    (!bond->params.arp_interval) &&
@@ -1146,16 +1142,15 @@
 {
 	struct slave *old_active = bond->curr_active_slave;
 
-	if (old_active == new_active) {
+	if (old_active == new_active)
 		return;
-	}
 
 	if (new_active) {
 		new_active->jiffies = jiffies;
 
 		if (new_active->link == BOND_LINK_BACK) {
 			if (USES_PRIMARY(bond->params.mode)) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: making interface %s the new "
 				       "active one %d ms earlier.\n",
 				       bond->dev->name, new_active->dev->name,
@@ -1165,15 +1160,14 @@
 			new_active->delay = 0;
 			new_active->link = BOND_LINK_UP;
 
-			if (bond->params.mode == BOND_MODE_8023AD) {
+			if (bond->params.mode == BOND_MODE_8023AD)
 				bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
-			}
 
 			if (bond_is_lb(bond))
 				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
 		} else {
 			if (USES_PRIMARY(bond->params.mode)) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: making interface %s the new "
 				       "active one.\n",
 				       bond->dev->name, new_active->dev->name);
@@ -1181,9 +1175,8 @@
 		}
 	}
 
-	if (USES_PRIMARY(bond->params.mode)) {
+	if (USES_PRIMARY(bond->params.mode))
 		bond_mc_swap(bond, new_active, old_active);
-	}
 
 	if (bond_is_lb(bond)) {
 		bond_alb_handle_active_change(bond, new_active);
@@ -1196,9 +1189,8 @@
 	}
 
 	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
-		if (old_active) {
+		if (old_active)
 			bond_set_slave_inactive_flags(old_active);
-		}
 
 		if (new_active) {
 			bond_set_slave_active_flags(new_active);
@@ -1228,7 +1220,7 @@
  * bond_select_active_slave - select a new active slave, if needed
  * @bond: our bonding struct
  *
- * This functions shoud be called when one of the following occurs:
+ * This functions should be called when one of the following occurs:
  * - The old curr_active_slave has been released or lost its link.
  * - The primary_slave has got its link back.
  * - A slave has got its link back and there's no old curr_active_slave.
@@ -1248,11 +1240,11 @@
 			return;
 
 		if (netif_carrier_ok(bond->dev)) {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: first active interface up!\n",
 			       bond->dev->name);
 		} else {
-			printk(KERN_INFO DRV_NAME ": %s: "
+			pr_info(DRV_NAME ": %s: "
 			       "now running without any active interface !\n",
 			       bond->dev->name);
 		}
@@ -1294,13 +1286,11 @@
  */
 static void bond_detach_slave(struct bonding *bond, struct slave *slave)
 {
-	if (slave->next) {
+	if (slave->next)
 		slave->next->prev = slave->prev;
-	}
 
-	if (slave->prev) {
+	if (slave->prev)
 		slave->prev->next = slave->next;
-	}
 
 	if (bond->first_slave == slave) { /* slave is the first slave */
 		if (bond->slave_cnt > 1) { /* there are more slave */
@@ -1331,7 +1321,7 @@
 	(NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | \
 	 NETIF_F_HW_VLAN_FILTER)
 
-/* 
+/*
  * Compute the common dev->feature set available to all slaves.  Some
  * feature bits are managed elsewhere, so preserve those feature bits
  * on the master device.
@@ -1399,14 +1389,14 @@
 
 	if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
 		slave_ops->ndo_do_ioctl == NULL) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": %s: Warning: no link monitoring support for %s\n",
 		       bond_dev->name, slave_dev->name);
 	}
 
 	/* bond must be initialized by bond_open() before enslaving */
 	if (!(bond_dev->flags & IFF_UP)) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 			" %s: master_dev is not up in bond_enslave\n",
 			bond_dev->name);
 	}
@@ -1422,14 +1412,14 @@
 	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
 		pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
 		if (!list_empty(&bond->vlan_list)) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: Error: cannot enslave VLAN "
 			       "challenged slave %s on VLAN enabled "
 			       "bond %s\n", bond_dev->name, slave_dev->name,
 			       bond_dev->name);
 			return -EPERM;
 		} else {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: Warning: enslaved VLAN challenged "
 			       "slave %s. Adding VLANs will be blocked as "
 			       "long as %s is part of bond %s\n",
@@ -1449,12 +1439,12 @@
 
 	/*
 	 * Old ifenslave binaries are no longer supported.  These can
-	 * be identified with moderate accurary by the state of the slave:
+	 * be identified with moderate accuracy by the state of the slave:
 	 * the current ifenslave will set the interface down prior to
 	 * enslaving it; the old ifenslave will not.
 	 */
 	if ((slave_dev->flags & IFF_UP)) {
-		printk(KERN_ERR DRV_NAME ": %s is up. "
+		pr_err(DRV_NAME ": %s is up. "
 		       "This may be due to an out of date ifenslave.\n",
 		       slave_dev->name);
 		res = -EPERM;
@@ -1469,10 +1459,18 @@
 	 * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
 	 */
 	if (bond->slave_cnt == 0) {
-		if (slave_dev->type != ARPHRD_ETHER)
-			bond_setup_by_slave(bond_dev, slave_dev);
+		if (bond_dev->type != slave_dev->type) {
+			dev_close(bond_dev);
+			pr_debug("%s: change device type from %d to %d\n",
+				bond_dev->name, bond_dev->type, slave_dev->type);
+			if (slave_dev->type != ARPHRD_ETHER)
+				bond_setup_by_slave(bond_dev, slave_dev);
+			else
+				ether_setup(bond_dev);
+			dev_open(bond_dev);
+		}
 	} else if (bond_dev->type != slave_dev->type) {
-		printk(KERN_ERR DRV_NAME ": %s ether type (%d) is different "
+		pr_err(DRV_NAME ": %s ether type (%d) is different "
 			"from other slaves (%d), can not enslave it.\n",
 			slave_dev->name,
 			slave_dev->type, bond_dev->type);
@@ -1482,14 +1480,14 @@
 
 	if (slave_ops->ndo_set_mac_address == NULL) {
 		if (bond->slave_cnt == 0) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: Warning: The first slave device "
 			       "specified does not support setting the MAC "
 			       "address. Setting fail_over_mac to active.",
 			       bond_dev->name);
 			bond->params.fail_over_mac = BOND_FOM_ACTIVE;
 		} else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 				": %s: Error: The slave device specified "
 				"does not support setting the MAC address, "
 				"but fail_over_mac is not set to active.\n"
@@ -1539,7 +1537,7 @@
 	/* open the slave since the application closed it */
 	res = dev_open(slave_dev);
 	if (res) {
-		pr_debug("Openning slave %s failed\n", slave_dev->name);
+		pr_debug("Opening slave %s failed\n", slave_dev->name);
 		goto err_unset_master;
 	}
 
@@ -1551,9 +1549,8 @@
 		 * it might fail and we do not want to have to undo everything
 		 */
 		res = bond_alb_init_slave(bond, new_slave);
-		if (res) {
+		if (res)
 			goto err_close;
-		}
 	}
 
 	/* If the mode USES_PRIMARY, then the new slave gets the
@@ -1578,9 +1575,9 @@
 
 		netif_addr_lock_bh(bond_dev);
 		/* upload master's mc_list to new slave */
-		for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
-			dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		}
+		for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next)
+			dev_mc_add(slave_dev, dmi->dmi_addr,
+				   dmi->dmi_addrlen, 0);
 		netif_addr_unlock_bh(bond_dev);
 	}
 
@@ -1621,7 +1618,7 @@
 			 * supported); thus, we don't need to change
 			 * the messages for netif_carrier.
 			 */
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: Warning: MII and ETHTOOL support not "
 			       "available for interface %s, and "
 			       "arp_interval/arp_ip_target module parameters "
@@ -1630,7 +1627,7 @@
 			       bond_dev->name, slave_dev->name);
 		} else if (link_reporting == -1) {
 			/* unable get link status using mii/ethtool */
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: Warning: can't get link status from "
 			       "interface %s; the network driver associated "
 			       "with this interface does not support MII or "
@@ -1662,13 +1659,13 @@
 
 	if (bond_update_speed_duplex(new_slave) &&
 	    (new_slave->link != BOND_LINK_DOWN)) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": %s: Warning: failed to get speed and duplex from %s, "
 		       "assumed to be 100Mb/sec and Full.\n",
 		       bond_dev->name, new_slave->dev->name);
 
 		if (bond->params.mode == BOND_MODE_8023AD) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: Warning: Operation of 802.3ad mode requires ETHTOOL "
 			       "support in base driver for proper aggregator "
 			       "selection.\n", bond_dev->name);
@@ -1677,9 +1674,8 @@
 
 	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
 		/* if there is a primary slave, remember it */
-		if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
+		if (strcmp(bond->params.primary, new_slave->dev->name) == 0)
 			bond->primary_slave = new_slave;
-		}
 	}
 
 	write_lock_bh(&bond->curr_slave_lock);
@@ -1726,9 +1722,9 @@
 		 * anyway (it holds no special properties of the bond device),
 		 * so we can change it without calling change_active_interface()
 		 */
-		if (!bond->curr_active_slave) {
+		if (!bond->curr_active_slave)
 			bond->curr_active_slave = new_slave;
-		}
+
 		break;
 	} /* switch(bond_mode) */
 
@@ -1742,7 +1738,7 @@
 	if (res)
 		goto err_close;
 
-	printk(KERN_INFO DRV_NAME
+	pr_info(DRV_NAME
 	       ": %s: enslaving %s as a%s interface with a%s link.\n",
 	       bond_dev->name, slave_dev->name,
 	       new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
@@ -1774,7 +1770,7 @@
 
 err_undo_flags:
 	bond_dev->features = old_features;
- 
+
 	return res;
 }
 
@@ -1799,7 +1795,7 @@
 	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
 	    (slave_dev->master != bond_dev)) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Error: cannot release %s.\n",
 		       bond_dev->name, slave_dev->name);
 		return -EINVAL;
@@ -1810,7 +1806,7 @@
 	slave = bond_get_slave_by_dev(bond, slave_dev);
 	if (!slave) {
 		/* not a slave of this bond */
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: %s not enslaved\n",
 		       bond_dev->name, slave_dev->name);
 		write_unlock_bh(&bond->lock);
@@ -1821,7 +1817,7 @@
 		mac_addr_differ = memcmp(bond_dev->dev_addr, slave->perm_hwaddr,
 					 ETH_ALEN);
 		if (!mac_addr_differ && (bond->slave_cnt > 1))
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: Warning: the permanent HWaddr of %s - "
 			       "%pM - is still in use by %s. "
 			       "Set the HWaddr of %s to a different address "
@@ -1839,7 +1835,7 @@
 		bond_3ad_unbind_slave(slave);
 	}
 
-	printk(KERN_INFO DRV_NAME
+	pr_info(DRV_NAME
 	       ": %s: releasing %s interface %s\n",
 	       bond_dev->name,
 	       (slave->state == BOND_STATE_ACTIVE)
@@ -1855,13 +1851,11 @@
 
 	bond_compute_features(bond);
 
-	if (bond->primary_slave == slave) {
+	if (bond->primary_slave == slave)
 		bond->primary_slave = NULL;
-	}
 
-	if (oldcurrent == slave) {
+	if (oldcurrent == slave)
 		bond_change_active_slave(bond, NULL);
-	}
 
 	if (bond_is_lb(bond)) {
 		/* Must be called only after the slave has been
@@ -1903,18 +1897,18 @@
 		if (list_empty(&bond->vlan_list)) {
 			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 		} else {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: Warning: clearing HW address of %s while it "
 			       "still has VLANs.\n",
 			       bond_dev->name, bond_dev->name);
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": %s: When re-adding slaves, make sure the bond's "
 			       "HW address matches its VLANs'.\n",
 			       bond_dev->name);
 		}
 	} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
 		   !bond_has_challenged_slaves(bond)) {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: last VLAN challenged slave %s "
 		       "left bond %s. VLAN blocking is removed\n",
 		       bond_dev->name, slave_dev->name, bond_dev->name);
@@ -1934,14 +1928,12 @@
 	 */
 	if (!USES_PRIMARY(bond->params.mode)) {
 		/* unset promiscuity level from slave */
-		if (bond_dev->flags & IFF_PROMISC) {
+		if (bond_dev->flags & IFF_PROMISC)
 			dev_set_promiscuity(slave_dev, -1);
-		}
 
 		/* unset allmulti level from slave */
-		if (bond_dev->flags & IFF_ALLMULTI) {
+		if (bond_dev->flags & IFF_ALLMULTI)
 			dev_set_allmulti(slave_dev, -1);
-		}
 
 		/* flush master's mc_list from slave */
 		netif_addr_lock_bh(bond_dev);
@@ -1974,41 +1966,36 @@
 * Destroy a bonding device.
 * Must be under rtnl_lock when this function is called.
 */
-void bond_destroy(struct bonding *bond)
-{
-	bond_deinit(bond->dev);
-	bond_destroy_sysfs_entry(bond);
-	unregister_netdevice(bond->dev);
-}
-
-static void bond_destructor(struct net_device *bond_dev)
+static void bond_uninit(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 
+	bond_deinit(bond_dev);
+	bond_destroy_sysfs_entry(bond);
+
 	if (bond->wq)
 		destroy_workqueue(bond->wq);
 
 	netif_addr_lock_bh(bond_dev);
 	bond_mc_list_destroy(bond);
 	netif_addr_unlock_bh(bond_dev);
-
-	free_netdev(bond_dev);
 }
 
 /*
-* First release a slave and than destroy the bond if no more slaves iare left.
+* First release a slave and than destroy the bond if no more slaves are left.
 * Must be under rtnl_lock when this function is called.
 */
-int  bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev)
+int  bond_release_and_destroy(struct net_device *bond_dev,
+			      struct net_device *slave_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	int ret;
 
 	ret = bond_release(bond_dev, slave_dev);
 	if ((ret == 0) && (bond->slave_cnt == 0)) {
-		printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n",
+		pr_info(DRV_NAME ": %s: destroying bond %s.\n",
 		       bond_dev->name, bond_dev->name);
-		bond_destroy(bond);
+		unregister_netdevice(bond_dev);
 	}
 	return ret;
 }
@@ -2027,9 +2014,8 @@
 
 	netif_carrier_off(bond_dev);
 
-	if (bond->slave_cnt == 0) {
+	if (bond->slave_cnt == 0)
 		goto out;
-	}
 
 	bond->current_arp_slave = NULL;
 	bond->primary_slave = NULL;
@@ -2039,9 +2025,8 @@
 		/* Inform AD package of unbinding of slave
 		 * before slave is detached from the list.
 		 */
-		if (bond->params.mode == BOND_MODE_8023AD) {
+		if (bond->params.mode == BOND_MODE_8023AD)
 			bond_3ad_unbind_slave(slave);
-		}
 
 		slave_dev = slave->dev;
 		bond_detach_slave(bond, slave);
@@ -2070,14 +2055,12 @@
 		 */
 		if (!USES_PRIMARY(bond->params.mode)) {
 			/* unset promiscuity level from slave */
-			if (bond_dev->flags & IFF_PROMISC) {
+			if (bond_dev->flags & IFF_PROMISC)
 				dev_set_promiscuity(slave_dev, -1);
-			}
 
 			/* unset allmulti level from slave */
-			if (bond_dev->flags & IFF_ALLMULTI) {
+			if (bond_dev->flags & IFF_ALLMULTI)
 				dev_set_allmulti(slave_dev, -1);
-			}
 
 			/* flush master's mc_list from slave */
 			netif_addr_lock_bh(bond_dev);
@@ -2112,20 +2095,20 @@
 	 */
 	memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
 
-	if (list_empty(&bond->vlan_list)) {
+	if (list_empty(&bond->vlan_list))
 		bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
-	} else {
-		printk(KERN_WARNING DRV_NAME
+	else {
+		pr_warning(DRV_NAME
 		       ": %s: Warning: clearing HW address of %s while it "
 		       "still has VLANs.\n",
 		       bond_dev->name, bond_dev->name);
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": %s: When re-adding slaves, make sure the bond's "
 		       "HW address matches its VLANs'.\n",
 		       bond_dev->name);
 	}
 
-	printk(KERN_INFO DRV_NAME
+	pr_info(DRV_NAME
 	       ": %s: released all slaves\n",
 	       bond_dev->name);
 
@@ -2143,8 +2126,8 @@
  *  - <slave_dev> is already active.
  *  - The link state of <slave_dev> is not BOND_LINK_UP.
  *  - <slave_dev> is not running.
- * In these cases, this fuction does nothing.
- * In the other cases, currnt_slave pointer is changed and 0 is returned.
+ * In these cases, this function does nothing.
+ * In the other cases, current_slave pointer is changed and 0 is returned.
  */
 static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_device *slave_dev)
 {
@@ -2153,15 +2136,12 @@
 	struct slave *new_active = NULL;
 	int res = 0;
 
-	if (!USES_PRIMARY(bond->params.mode)) {
+	if (!USES_PRIMARY(bond->params.mode))
 		return -EINVAL;
-	}
 
 	/* Verify that master_dev is indeed the master of slave_dev */
-	if (!(slave_dev->flags & IFF_SLAVE) ||
-	    (slave_dev->master != bond_dev)) {
+	if (!(slave_dev->flags & IFF_SLAVE) || (slave_dev->master != bond_dev))
 		return -EINVAL;
-	}
 
 	read_lock(&bond->lock);
 
@@ -2186,9 +2166,8 @@
 		write_lock_bh(&bond->curr_slave_lock);
 		bond_change_active_slave(bond, new_active);
 		write_unlock_bh(&bond->curr_slave_lock);
-	} else {
+	} else
 		res = -EINVAL;
-	}
 
 	read_unlock(&bond->lock);
 
@@ -2240,6 +2219,9 @@
 {
 	struct slave *slave;
 	int i, link_state, commit = 0;
+	bool ignore_updelay;
+
+	ignore_updelay = !bond->curr_active_slave ? true : false;
 
 	bond_for_each_slave(bond, slave, i) {
 		slave->new_link = BOND_LINK_NOCHANGE;
@@ -2254,7 +2236,7 @@
 			slave->link = BOND_LINK_FAIL;
 			slave->delay = bond->params.downdelay;
 			if (slave->delay) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: link status down for %s"
 				       "interface %s, disabling it in %d ms.\n",
 				       bond->dev->name,
@@ -2273,7 +2255,7 @@
 				 */
 				slave->link = BOND_LINK_UP;
 				slave->jiffies = jiffies;
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: link status up again after %d "
 				       "ms for interface %s.\n",
 				       bond->dev->name,
@@ -2300,10 +2282,11 @@
 			slave->delay = bond->params.updelay;
 
 			if (slave->delay) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: link status up for "
 				       "interface %s, enabling it in %d ms.\n",
 				       bond->dev->name, slave->dev->name,
+				       ignore_updelay ? 0 :
 				       bond->params.updelay *
 				       bond->params.miimon);
 			}
@@ -2311,7 +2294,7 @@
 		case BOND_LINK_BACK:
 			if (!link_state) {
 				slave->link = BOND_LINK_DOWN;
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: link status down again after %d "
 				       "ms for interface %s.\n",
 				       bond->dev->name,
@@ -2322,9 +2305,13 @@
 				continue;
 			}
 
+			if (ignore_updelay)
+				slave->delay = 0;
+
 			if (slave->delay <= 0) {
 				slave->new_link = BOND_LINK_UP;
 				commit++;
+				ignore_updelay = false;
 				continue;
 			}
 
@@ -2361,7 +2348,7 @@
 				slave->state = BOND_STATE_BACKUP;
 			}
 
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: link status definitely "
 			       "up for interface %s.\n",
 			       bond->dev->name, slave->dev->name);
@@ -2390,7 +2377,7 @@
 			    bond->params.mode == BOND_MODE_8023AD)
 				bond_set_slave_inactive_flags(slave);
 
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: link status definitely down for "
 			       "interface %s, disabling it\n",
 			       bond->dev->name, slave->dev->name);
@@ -2399,8 +2386,7 @@
 				bond_3ad_handle_link_change(slave,
 							    BOND_LINK_DOWN);
 
-			if (bond->params.mode == BOND_MODE_TLB ||
-			    bond->params.mode == BOND_MODE_ALB)
+			if (bond_is_lb(bond))
 				bond_alb_handle_link_change(bond, slave,
 							    BOND_LINK_DOWN);
 
@@ -2410,7 +2396,7 @@
 			continue;
 
 		default:
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: invalid new link %d on slave %s\n",
 			       bond->dev->name, slave->new_link,
 			       slave->dev->name);
@@ -2531,18 +2517,18 @@
 
 	pr_debug("arp %d on slave %s: dst %x src %x vid %d\n", arp_op,
 	       slave_dev->name, dest_ip, src_ip, vlan_id);
-	       
+
 	skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
 			 NULL, slave_dev->dev_addr, NULL);
 
 	if (!skb) {
-		printk(KERN_ERR DRV_NAME ": ARP packet allocation failed\n");
+		pr_err(DRV_NAME ": ARP packet allocation failed\n");
 		return;
 	}
 	if (vlan_id) {
 		skb = vlan_put_tag(skb, vlan_id);
 		if (!skb) {
-			printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n");
+			pr_err(DRV_NAME ": failed to insert VLAN tag\n");
 			return;
 		}
 	}
@@ -2582,7 +2568,7 @@
 		rv = ip_route_output_key(&init_net, &rt, &fl);
 		if (rv) {
 			if (net_ratelimit()) {
-				printk(KERN_WARNING DRV_NAME
+				pr_warning(DRV_NAME
 			     ": %s: no route to arp_ip_target %pI4\n",
 				       bond->dev->name, &fl.fl4_dst);
 			}
@@ -2619,7 +2605,7 @@
 		}
 
 		if (net_ratelimit()) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 	       ": %s: no path to arp_ip_target %pI4 via rt.dev %s\n",
 			       bond->dev->name, &fl.fl4_dst,
 			       rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
@@ -2767,13 +2753,11 @@
 
 	delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
 
-	if (bond->kill_timers) {
+	if (bond->kill_timers)
 		goto out;
-	}
 
-	if (bond->slave_cnt == 0) {
+	if (bond->slave_cnt == 0)
 		goto re_arm;
-	}
 
 	read_lock(&bond->curr_slave_lock);
 	oldcurrent = bond->curr_active_slave;
@@ -2789,7 +2773,7 @@
 	 */
 	bond_for_each_slave(bond, slave, i) {
 		if (slave->link != BOND_LINK_UP) {
-			if (time_before_eq(jiffies, slave->dev->trans_start + delta_in_ticks) &&
+			if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) &&
 			    time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) {
 
 				slave->link  = BOND_LINK_UP;
@@ -2801,14 +2785,14 @@
 				 * is closed.
 				 */
 				if (!oldcurrent) {
-					printk(KERN_INFO DRV_NAME
+					pr_info(DRV_NAME
 					       ": %s: link status definitely "
 					       "up for interface %s, ",
 					       bond->dev->name,
 					       slave->dev->name);
 					do_failover = 1;
 				} else {
-					printk(KERN_INFO DRV_NAME
+					pr_info(DRV_NAME
 					       ": %s: interface %s is now up\n",
 					       bond->dev->name,
 					       slave->dev->name);
@@ -2821,24 +2805,22 @@
 			 * when the source ip is 0, so don't take the link down
 			 * if we don't know our ip yet
 			 */
-			if (time_after_eq(jiffies, slave->dev->trans_start + 2*delta_in_ticks) ||
+			if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) ||
 			    (time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) {
 
 				slave->link  = BOND_LINK_DOWN;
 				slave->state = BOND_STATE_BACKUP;
 
-				if (slave->link_failure_count < UINT_MAX) {
+				if (slave->link_failure_count < UINT_MAX)
 					slave->link_failure_count++;
-				}
 
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: interface %s is now down.\n",
 				       bond->dev->name,
 				       slave->dev->name);
 
-				if (slave == oldcurrent) {
+				if (slave == oldcurrent)
 					do_failover = 1;
-				}
 			}
 		}
 
@@ -2849,9 +2831,8 @@
 		 * do - all replies will be rx'ed on same link causing slaves
 		 * to be unstable during low/no traffic periods
 		 */
-		if (IS_UP(slave->dev)) {
+		if (IS_UP(slave->dev))
 			bond_arp_send_all(bond, slave);
-		}
 	}
 
 	if (do_failover) {
@@ -2932,7 +2913,7 @@
 		 *    the bond has an IP address)
 		 */
 		if ((slave->state == BOND_STATE_ACTIVE) &&
-		    (time_after_eq(jiffies, slave->dev->trans_start +
+		    (time_after_eq(jiffies, dev_trans_start(slave->dev) +
 				    2 * delta_in_ticks) ||
 		      (time_after_eq(jiffies, slave_last_rx(bond, slave)
 				     + 2 * delta_in_ticks)))) {
@@ -2976,13 +2957,13 @@
 			write_lock_bh(&bond->curr_slave_lock);
 
 			if (!bond->curr_active_slave &&
-			    time_before_eq(jiffies, slave->dev->trans_start +
+			    time_before_eq(jiffies, dev_trans_start(slave->dev) +
 					   delta_in_ticks)) {
 				slave->link = BOND_LINK_UP;
 				bond_change_active_slave(bond, slave);
 				bond->current_arp_slave = NULL;
 
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: %s is up and now the "
 				       "active interface\n",
 				       bond->dev->name, slave->dev->name);
@@ -2998,7 +2979,7 @@
 				bond_set_slave_inactive_flags(slave);
 				bond->current_arp_slave = NULL;
 
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: backup interface %s is now up\n",
 				       bond->dev->name, slave->dev->name);
 			}
@@ -3014,7 +2995,7 @@
 			slave->link = BOND_LINK_DOWN;
 
 			if (slave == bond->curr_active_slave) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: link status down for active "
 				       "interface %s, disabling it\n",
 				       bond->dev->name, slave->dev->name);
@@ -3033,7 +3014,7 @@
 				bond->current_arp_slave = NULL;
 
 			} else if (slave->state == BOND_STATE_BACKUP) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: backup interface %s is now down\n",
 				       bond->dev->name, slave->dev->name);
 
@@ -3042,7 +3023,7 @@
 			break;
 
 		default:
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: impossible: new_link %d on slave %s\n",
 			       bond->dev->name, slave->new_link,
 			       slave->dev->name);
@@ -3076,7 +3057,7 @@
 	read_lock(&bond->curr_slave_lock);
 
 	if (bond->current_arp_slave && bond->curr_active_slave)
-		printk("PROBE: c_arp %s && cas %s BAD\n",
+		pr_info(DRV_NAME "PROBE: c_arp %s && cas %s BAD\n",
 		       bond->current_arp_slave->dev->name,
 		       bond->curr_active_slave->dev->name);
 
@@ -3126,7 +3107,7 @@
 
 			bond_set_slave_inactive_flags(slave);
 
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: backup interface %s is now down.\n",
 			       bond->dev->name, slave->dev->name);
 		}
@@ -3176,9 +3157,8 @@
 	bond_ab_arp_probe(bond);
 
 re_arm:
-	if (bond->params.arp_interval) {
+	if (bond->params.arp_interval)
 		queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
-	}
 out:
 	read_unlock(&bond->lock);
 }
@@ -3200,14 +3180,12 @@
 	read_lock(&dev_base_lock);
 	read_lock(&bond->lock);
 
-	if (*pos == 0) {
+	if (*pos == 0)
 		return SEQ_START_TOKEN;
-	}
 
 	bond_for_each_slave(bond, slave, i) {
-		if (++off == *pos) {
+		if (++off == *pos)
 			return slave;
-		}
 	}
 
 	return NULL;
@@ -3219,9 +3197,8 @@
 	struct slave *slave = v;
 
 	++*pos;
-	if (v == SEQ_START_TOKEN) {
+	if (v == SEQ_START_TOKEN)
 		return bond->first_slave;
-	}
 
 	slave = slave->next;
 
@@ -3284,14 +3261,14 @@
 
 
 	/* ARP information */
-	if(bond->params.arp_interval > 0) {
-		int printed=0;
+	if (bond->params.arp_interval > 0) {
+		int printed = 0;
 		seq_printf(seq, "ARP Polling Interval (ms): %d\n",
 				bond->params.arp_interval);
 
 		seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
 
-		for(i = 0; (i < BOND_MAX_ARP_TARGETS) ;i++) {
+		for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
 			if (!bond->params.arp_targets[i])
 				break;
 			if (printed)
@@ -3331,7 +3308,8 @@
 	}
 }
 
-static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
+static void bond_info_show_slave(struct seq_file *seq,
+				 const struct slave *slave)
 {
 	struct bonding *bond = seq->private;
 
@@ -3347,12 +3325,11 @@
 		const struct aggregator *agg
 			= SLAVE_AD_INFO(slave).port.aggregator;
 
-		if (agg) {
+		if (agg)
 			seq_printf(seq, "Aggregator ID: %d\n",
 				   agg->aggregator_identifier);
-		} else {
+		else
 			seq_puts(seq, "Aggregator ID: N/A\n");
-		}
 	}
 }
 
@@ -3361,9 +3338,8 @@
 	if (v == SEQ_START_TOKEN) {
 		seq_printf(seq, "%s\n", version);
 		bond_info_show_master(seq);
-	} else {
+	} else
 		bond_info_show_slave(seq, v);
-	}
 
 	return 0;
 }
@@ -3408,13 +3384,12 @@
 		bond->proc_entry = proc_create_data(bond_dev->name,
 						    S_IRUGO, bond_proc_dir,
 						    &bond_info_fops, bond);
-		if (bond->proc_entry == NULL) {
-			printk(KERN_WARNING DRV_NAME
+		if (bond->proc_entry == NULL)
+			pr_warning(DRV_NAME
 			       ": Warning: Cannot create /proc/net/%s/%s\n",
 			       DRV_NAME, bond_dev->name);
-		} else {
+		else
 			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
-		}
 	}
 
 	return 0;
@@ -3437,7 +3412,7 @@
 	if (!bond_proc_dir) {
 		bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net);
 		if (!bond_proc_dir)
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 				": Warning: cannot create /proc/net/%s\n",
 				DRV_NAME);
 	}
@@ -3453,8 +3428,28 @@
 		bond_proc_dir = NULL;
 	}
 }
+
+#else /* !CONFIG_PROC_FS */
+
+static int bond_create_proc_entry(struct bonding *bond)
+{
+}
+
+static void bond_remove_proc_entry(struct bonding *bond)
+{
+}
+
+static void bond_create_proc_dir(void)
+{
+}
+
+static void bond_destroy_proc_dir(void)
+{
+}
+
 #endif /* CONFIG_PROC_FS */
 
+
 /*-------------------------- netdev event handling --------------------------*/
 
 /*
@@ -3462,18 +3457,17 @@
  */
 static int bond_event_changename(struct bonding *bond)
 {
-#ifdef CONFIG_PROC_FS
 	bond_remove_proc_entry(bond);
 	bond_create_proc_entry(bond);
-#endif
-	down_write(&(bonding_rwsem));
-        bond_destroy_sysfs_entry(bond);
-        bond_create_sysfs_entry(bond);
-	up_write(&(bonding_rwsem));
+
+	bond_destroy_sysfs_entry(bond);
+	bond_create_sysfs_entry(bond);
+
 	return NOTIFY_DONE;
 }
 
-static int bond_master_netdev_event(unsigned long event, struct net_device *bond_dev)
+static int bond_master_netdev_event(unsigned long event,
+				    struct net_device *bond_dev)
 {
 	struct bonding *event_bond = netdev_priv(bond_dev);
 
@@ -3490,7 +3484,8 @@
 	return NOTIFY_DONE;
 }
 
-static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
+static int bond_slave_netdev_event(unsigned long event,
+				   struct net_device *slave_dev)
 {
 	struct net_device *bond_dev = slave_dev->master;
 	struct bonding *bond = netdev_priv(bond_dev);
@@ -3568,7 +3563,8 @@
  * locks for us to safely manipulate the slave devices (RTNL lock,
  * dev_probe_lock).
  */
-static int bond_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+static int bond_netdev_event(struct notifier_block *this,
+			     unsigned long event, void *ptr)
 {
 	struct net_device *event_dev = (struct net_device *)ptr;
 
@@ -3923,9 +3919,9 @@
 	switch (cmd) {
 	case SIOCGMIIPHY:
 		mii = if_mii(ifr);
-		if (!mii) {
+		if (!mii)
 			return -EINVAL;
-		}
+
 		mii->phy_id = 0;
 		/* Fall Through */
 	case SIOCGMIIREG:
@@ -3934,18 +3930,18 @@
 		 * instead of SIOCGMIIPHY.
 		 */
 		mii = if_mii(ifr);
-		if (!mii) {
+		if (!mii)
 			return -EINVAL;
-		}
+
 
 		if (mii->reg_num == 1) {
 			struct bonding *bond = netdev_priv(bond_dev);
 			mii->val_out = 0;
 			read_lock(&bond->lock);
 			read_lock(&bond->curr_slave_lock);
-			if (netif_carrier_ok(bond->dev)) {
+			if (netif_carrier_ok(bond->dev))
 				mii->val_out = BMSR_LSTATUS;
-			}
+
 			read_unlock(&bond->curr_slave_lock);
 			read_unlock(&bond->lock);
 		}
@@ -3955,32 +3951,26 @@
 	case SIOCBONDINFOQUERY:
 		u_binfo = (struct ifbond __user *)ifr->ifr_data;
 
-		if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) {
+		if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond)))
 			return -EFAULT;
-		}
 
 		res = bond_info_query(bond_dev, &k_binfo);
-		if (res == 0) {
-			if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) {
-				return -EFAULT;
-			}
-		}
+		if (res == 0 &&
+		    copy_to_user(u_binfo, &k_binfo, sizeof(ifbond)))
+			return -EFAULT;
 
 		return res;
 	case BOND_SLAVE_INFO_QUERY_OLD:
 	case SIOCBONDSLAVEINFOQUERY:
 		u_sinfo = (struct ifslave __user *)ifr->ifr_data;
 
-		if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) {
+		if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave)))
 			return -EFAULT;
-		}
 
 		res = bond_slave_info_query(bond_dev, &k_sinfo);
-		if (res == 0) {
-			if (copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) {
-				return -EFAULT;
-			}
-		}
+		if (res == 0 &&
+		    copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave)))
+			return -EFAULT;
 
 		return res;
 	default:
@@ -3988,18 +3978,16 @@
 		break;
 	}
 
-	if (!capable(CAP_NET_ADMIN)) {
+	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
-	}
 
-	down_write(&(bonding_rwsem));
 	slave_dev = dev_get_by_name(&init_net, ifr->ifr_slave);
 
 	pr_debug("slave_dev=%p: \n", slave_dev);
 
-	if (!slave_dev) {
+	if (!slave_dev)
 		res = -ENODEV;
-	} else {
+	else {
 		pr_debug("slave_dev->name=%s: \n", slave_dev->name);
 		switch (cmd) {
 		case BOND_ENSLAVE_OLD:
@@ -4025,7 +4013,6 @@
 		dev_put(slave_dev);
 	}
 
-	up_write(&(bonding_rwsem));
 	return res;
 }
 
@@ -4037,30 +4024,30 @@
 	/*
 	 * Do promisc before checking multicast_mode
 	 */
-	if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC)) {
+	if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC))
 		/*
 		 * FIXME: Need to handle the error when one of the multi-slaves
 		 * encounters error.
 		 */
 		bond_set_promiscuity(bond, 1);
-	}
 
-	if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC)) {
+
+	if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC))
 		bond_set_promiscuity(bond, -1);
-	}
+
 
 	/* set allmulti flag to slaves */
-	if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI)) {
+	if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI))
 		/*
 		 * FIXME: Need to handle the error when one of the multi-slaves
 		 * encounters error.
 		 */
 		bond_set_allmulti(bond, 1);
-	}
 
-	if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI)) {
+
+	if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI))
 		bond_set_allmulti(bond, -1);
-	}
+
 
 	read_lock(&bond->lock);
 
@@ -4068,16 +4055,14 @@
 
 	/* looking for addresses to add to slaves' mc list */
 	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
-		if (!bond_mc_list_find_dmi(dmi, bond->mc_list)) {
+		if (!bond_mc_list_find_dmi(dmi, bond->mc_list))
 			bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen);
-		}
 	}
 
 	/* looking for addresses to delete from slaves' list */
 	for (dmi = bond->mc_list; dmi; dmi = dmi->next) {
-		if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list)) {
+		if (!bond_mc_list_find_dmi(dmi, bond_dev->mc_list))
 			bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen);
-		}
 	}
 
 	/* save master's multicast list */
@@ -4197,9 +4182,8 @@
 	if (bond->params.fail_over_mac == BOND_FOM_ACTIVE)
 		return 0;
 
-	if (!is_valid_ether_addr(sa->sa_data)) {
+	if (!is_valid_ether_addr(sa->sa_data))
 		return -EADDRNOTAVAIL;
-	}
 
 	/* Can't hold bond->lock with bh disabled here since
 	 * some base drivers panic. On the other hand we can't
@@ -4270,9 +4254,8 @@
 
 	read_lock(&bond->lock);
 
-	if (!BOND_IS_OK(bond)) {
+	if (!BOND_IS_OK(bond))
 		goto out;
-	}
 
 	/*
 	 * Concurrent TX may collide on rr_tx_counter; we accept that
@@ -4282,9 +4265,8 @@
 
 	bond_for_each_slave(bond, slave, i) {
 		slave_no--;
-		if (slave_no < 0) {
+		if (slave_no < 0)
 			break;
-		}
 	}
 
 	start_at = slave;
@@ -4319,9 +4301,8 @@
 	read_lock(&bond->lock);
 	read_lock(&bond->curr_slave_lock);
 
-	if (!BOND_IS_OK(bond)) {
+	if (!BOND_IS_OK(bond))
 		goto out;
-	}
 
 	if (!bond->curr_active_slave)
 		goto out;
@@ -4329,10 +4310,10 @@
 	res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
 
 out:
-	if (res) {
+	if (res)
 		/* no suitable interface, frame not sent */
 		dev_kfree_skb(skb);
-	}
+
 	read_unlock(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	return 0;
@@ -4353,17 +4334,15 @@
 
 	read_lock(&bond->lock);
 
-	if (!BOND_IS_OK(bond)) {
+	if (!BOND_IS_OK(bond))
 		goto out;
-	}
 
 	slave_no = bond->xmit_hash_policy(skb, bond_dev, bond->slave_cnt);
 
 	bond_for_each_slave(bond, slave, i) {
 		slave_no--;
-		if (slave_no < 0) {
+		if (slave_no < 0)
 			break;
-		}
 	}
 
 	start_at = slave;
@@ -4399,17 +4378,15 @@
 
 	read_lock(&bond->lock);
 
-	if (!BOND_IS_OK(bond)) {
+	if (!BOND_IS_OK(bond))
 		goto out;
-	}
 
 	read_lock(&bond->curr_slave_lock);
 	start_at = bond->curr_active_slave;
 	read_unlock(&bond->curr_slave_lock);
 
-	if (!start_at) {
+	if (!start_at)
 		goto out;
-	}
 
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
@@ -4418,7 +4395,7 @@
 			if (tx_dev) {
 				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 				if (!skb2) {
-					printk(KERN_ERR DRV_NAME
+					pr_err(DRV_NAME
 					       ": %s: Error: bond_xmit_broadcast(): "
 					       "skb_clone() failed\n",
 					       bond_dev->name);
@@ -4435,15 +4412,14 @@
 		}
 	}
 
-	if (tx_dev) {
+	if (tx_dev)
 		res = bond_dev_queue_xmit(bond, skb, tx_dev);
-	}
 
 out:
-	if (res) {
+	if (res)
 		/* no suitable interface, frame not sent */
 		dev_kfree_skb(skb);
-	}
+
 	/* frame sent to all suitable interfaces */
 	read_unlock(&bond->lock);
 	return 0;
@@ -4487,7 +4463,7 @@
 		return bond_alb_xmit(skb, dev);
 	default:
 		/* Should never happen, mode already checked */
-		printk(KERN_ERR DRV_NAME ": %s: Error: Unknown bonding mode %d\n",
+		pr_err(DRV_NAME ": %s: Error: Unknown bonding mode %d\n",
 		     dev->name, bond->params.mode);
 		WARN_ON_ONCE(1);
 		dev_kfree_skb(skb);
@@ -4524,7 +4500,7 @@
 		break;
 	default:
 		/* Should never happen, mode already checked */
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Error: Unknown bonding mode %d\n",
 		       bond_dev->name,
 		       mode);
@@ -4551,6 +4527,8 @@
 };
 
 static const struct net_device_ops bond_netdev_ops = {
+	.ndo_init		= bond_init,
+	.ndo_uninit		= bond_uninit,
 	.ndo_open		= bond_open,
 	.ndo_stop		= bond_close,
 	.ndo_start_xmit		= bond_start_xmit,
@@ -4565,48 +4543,34 @@
 	.ndo_vlan_rx_kill_vid	= bond_vlan_rx_kill_vid,
 };
 
-/*
- * Does not allocate but creates a /proc entry.
- * Allowed to fail.
- */
-static int bond_init(struct net_device *bond_dev, struct bond_params *params)
+static void bond_setup(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 
-	pr_debug("Begin bond_init for %s\n", bond_dev->name);
-
 	/* initialize rwlocks */
 	rwlock_init(&bond->lock);
 	rwlock_init(&bond->curr_slave_lock);
 
-	bond->params = *params; /* copy params struct */
-
-	bond->wq = create_singlethread_workqueue(bond_dev->name);
-	if (!bond->wq)
-		return -ENOMEM;
+	bond->params = bonding_defaults;
 
 	/* Initialize pointers */
-	bond->first_slave = NULL;
-	bond->curr_active_slave = NULL;
-	bond->current_arp_slave = NULL;
-	bond->primary_slave = NULL;
 	bond->dev = bond_dev;
-	bond->send_grat_arp = 0;
-	bond->send_unsol_na = 0;
-	bond->setup_by_slave = 0;
 	INIT_LIST_HEAD(&bond->vlan_list);
 
 	/* Initialize the device entry points */
+	ether_setup(bond_dev);
 	bond_dev->netdev_ops = &bond_netdev_ops;
 	bond_dev->ethtool_ops = &bond_ethtool_ops;
 	bond_set_mode_ops(bond, bond->params.mode);
 
-	bond_dev->destructor = bond_destructor;
+	bond_dev->destructor = free_netdev;
 
 	/* Initialize the device options */
 	bond_dev->tx_queue_len = 0;
 	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
 	bond_dev->priv_flags |= IFF_BONDING;
+	bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+
 	if (bond->params.arp_interval)
 		bond_dev->priv_flags |= IFF_MASTER_ARPMON;
 
@@ -4631,12 +4595,6 @@
 			       NETIF_F_HW_VLAN_RX |
 			       NETIF_F_HW_VLAN_FILTER);
 
-#ifdef CONFIG_PROC_FS
-	bond_create_proc_entry(bond);
-#endif
-	list_add_tail(&bond->bond_list, &bond_dev_list);
-
-	return 0;
 }
 
 static void bond_work_cancel_all(struct bonding *bond)
@@ -4671,9 +4629,7 @@
 
 	bond_work_cancel_all(bond);
 
-#ifdef CONFIG_PROC_FS
 	bond_remove_proc_entry(bond);
-#endif
 }
 
 /* Unregister and free all bond devices.
@@ -4689,12 +4645,10 @@
 		bond_work_cancel_all(bond);
 		/* Release the bonded slaves */
 		bond_release_all(bond_dev);
-		bond_destroy(bond);
+		unregister_netdevice(bond_dev);
 	}
 
-#ifdef CONFIG_PROC_FS
 	bond_destroy_proc_dir();
-#endif
 }
 
 /*------------------------- Module initialization ---------------------------*/
@@ -4742,7 +4696,7 @@
 	if (mode) {
 		bond_mode = bond_parse_parm(mode, bond_mode_tbl);
 		if (bond_mode == -1) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": Error: Invalid bonding mode \"%s\"\n",
 			       mode == NULL ? "NULL" : mode);
 			return -EINVAL;
@@ -4752,16 +4706,16 @@
 	if (xmit_hash_policy) {
 		if ((bond_mode != BOND_MODE_XOR) &&
 		    (bond_mode != BOND_MODE_8023AD)) {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": xor_mode param is irrelevant in mode %s\n",
 			       bond_mode_name(bond_mode));
 		} else {
 			xmit_hashtype = bond_parse_parm(xmit_hash_policy,
 							xmit_hashtype_tbl);
 			if (xmit_hashtype == -1) {
-				printk(KERN_ERR DRV_NAME
-			       	": Error: Invalid xmit_hash_policy \"%s\"\n",
-			       	xmit_hash_policy == NULL ? "NULL" :
+				pr_err(DRV_NAME
+				       ": Error: Invalid xmit_hash_policy \"%s\"\n",
+				       xmit_hash_policy == NULL ? "NULL" :
 				       xmit_hash_policy);
 				return -EINVAL;
 			}
@@ -4770,13 +4724,13 @@
 
 	if (lacp_rate) {
 		if (bond_mode != BOND_MODE_8023AD) {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": lacp_rate param is irrelevant in mode %s\n",
 			       bond_mode_name(bond_mode));
 		} else {
 			lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl);
 			if (lacp_fast == -1) {
-				printk(KERN_ERR DRV_NAME
+				pr_err(DRV_NAME
 				       ": Error: Invalid lacp rate \"%s\"\n",
 				       lacp_rate == NULL ? "NULL" : lacp_rate);
 				return -EINVAL;
@@ -4787,14 +4741,14 @@
 	if (ad_select) {
 		params->ad_select = bond_parse_parm(ad_select, ad_select_tbl);
 		if (params->ad_select == -1) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": Error: Invalid ad_select \"%s\"\n",
 			       ad_select == NULL ? "NULL" : ad_select);
 			return -EINVAL;
 		}
 
 		if (bond_mode != BOND_MODE_8023AD) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": ad_select param only affects 802.3ad mode\n");
 		}
 	} else {
@@ -4802,7 +4756,7 @@
 	}
 
 	if (max_bonds < 0 || max_bonds > INT_MAX) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: max_bonds (%d) not in range %d-%d, so it "
 		       "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
 		       max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
@@ -4810,7 +4764,7 @@
 	}
 
 	if (miimon < 0) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: miimon module parameter (%d), "
 		       "not in range 0-%d, so it was reset to %d\n",
 		       miimon, INT_MAX, BOND_LINK_MON_INTERV);
@@ -4818,7 +4772,7 @@
 	}
 
 	if (updelay < 0) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: updelay module parameter (%d), "
 		       "not in range 0-%d, so it was reset to 0\n",
 		       updelay, INT_MAX);
@@ -4826,7 +4780,7 @@
 	}
 
 	if (downdelay < 0) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: downdelay module parameter (%d), "
 		       "not in range 0-%d, so it was reset to 0\n",
 		       downdelay, INT_MAX);
@@ -4834,7 +4788,7 @@
 	}
 
 	if ((use_carrier != 0) && (use_carrier != 1)) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: use_carrier module parameter (%d), "
 		       "not of valid value (0/1), so it was set to 1\n",
 		       use_carrier);
@@ -4842,14 +4796,14 @@
 	}
 
 	if (num_grat_arp < 0 || num_grat_arp > 255) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: num_grat_arp (%d) not in range 0-255 so it "
 		       "was reset to 1 \n", num_grat_arp);
 		num_grat_arp = 1;
 	}
 
 	if (num_unsol_na < 0 || num_unsol_na > 255) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: num_unsol_na (%d) not in range 0-255 so it "
 		       "was reset to 1 \n", num_unsol_na);
 		num_unsol_na = 1;
@@ -4858,12 +4812,12 @@
 	/* reset values for 802.3ad */
 	if (bond_mode == BOND_MODE_8023AD) {
 		if (!miimon) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: miimon must be specified, "
 			       "otherwise bonding will not detect link "
 			       "failure, speed and duplex which are "
 			       "essential for 802.3ad operation\n");
-			printk(KERN_WARNING "Forcing miimon to 100msec\n");
+			pr_warning("Forcing miimon to 100msec\n");
 			miimon = 100;
 		}
 	}
@@ -4872,12 +4826,12 @@
 	if ((bond_mode == BOND_MODE_TLB) ||
 	    (bond_mode == BOND_MODE_ALB)) {
 		if (!miimon) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: miimon must be specified, "
 			       "otherwise bonding will not detect link "
 			       "failure and link speed which are essential "
 			       "for TLB/ALB load balancing\n");
-			printk(KERN_WARNING "Forcing miimon to 100msec\n");
+			pr_warning("Forcing miimon to 100msec\n");
 			miimon = 100;
 		}
 	}
@@ -4897,7 +4851,7 @@
 			/* just warn the user the up/down delay will have
 			 * no effect since miimon is zero...
 			 */
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: miimon module parameter not set "
 			       "and updelay (%d) or downdelay (%d) module "
 			       "parameter is set; updelay and downdelay have "
@@ -4907,7 +4861,7 @@
 	} else {
 		/* don't allow arp monitoring */
 		if (arp_interval) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: miimon (%d) and arp_interval (%d) "
 			       "can't be used simultaneously, disabling ARP "
 			       "monitoring\n",
@@ -4916,7 +4870,7 @@
 		}
 
 		if ((updelay % miimon) != 0) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: updelay (%d) is not a multiple "
 			       "of miimon (%d), updelay rounded to %d ms\n",
 			       updelay, miimon, (updelay / miimon) * miimon);
@@ -4925,7 +4879,7 @@
 		updelay /= miimon;
 
 		if ((downdelay % miimon) != 0) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: downdelay (%d) is not a multiple "
 			       "of miimon (%d), downdelay rounded to %d ms\n",
 			       downdelay, miimon,
@@ -4936,7 +4890,7 @@
 	}
 
 	if (arp_interval < 0) {
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: arp_interval module parameter (%d) "
 		       ", not in range 0-%d, so it was reset to %d\n",
 		       arp_interval, INT_MAX, BOND_LINK_ARP_INTERV);
@@ -4949,7 +4903,7 @@
 		/* not complete check, but should be good enough to
 		   catch mistakes */
 		if (!isdigit(arp_ip_target[arp_ip_count][0])) {
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: bad arp_ip_target module parameter "
 			       "(%s), ARP monitoring will not be performed\n",
 			       arp_ip_target[arp_ip_count]);
@@ -4962,7 +4916,7 @@
 
 	if (arp_interval && !arp_ip_count) {
 		/* don't allow arping if no arp_ip_target given... */
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: arp_interval module parameter (%d) "
 		       "specified without providing an arp_ip_target "
 		       "parameter, arp_interval was reset to 0\n",
@@ -4972,12 +4926,12 @@
 
 	if (arp_validate) {
 		if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
-			printk(KERN_ERR DRV_NAME
-	       ": arp_validate only supported in active-backup mode\n");
+			pr_err(DRV_NAME
+			       ": arp_validate only supported in active-backup mode\n");
 			return -EINVAL;
 		}
 		if (!arp_interval) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": arp_validate requires arp_interval\n");
 			return -EINVAL;
 		}
@@ -4985,7 +4939,7 @@
 		arp_validate_value = bond_parse_parm(arp_validate,
 						     arp_validate_tbl);
 		if (arp_validate_value == -1) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": Error: invalid arp_validate \"%s\"\n",
 			       arp_validate == NULL ? "NULL" : arp_validate);
 			return -EINVAL;
@@ -4994,20 +4948,20 @@
 		arp_validate_value = 0;
 
 	if (miimon) {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": MII link monitoring set to %d ms\n",
 		       miimon);
 	} else if (arp_interval) {
 		int i;
 
-		printk(KERN_INFO DRV_NAME
-		       ": ARP monitoring set to %d ms, validate %s, with %d target(s):",
+		pr_info(DRV_NAME ": ARP monitoring set to %d ms,"
+		       " validate %s, with %d target(s):",
 		       arp_interval,
 		       arp_validate_tbl[arp_validate_value].modename,
 		       arp_ip_count);
 
 		for (i = 0; i < arp_ip_count; i++)
-			printk (" %s", arp_ip_target[i]);
+			printk(" %s", arp_ip_target[i]);
 
 		printk("\n");
 
@@ -5015,7 +4969,7 @@
 		/* miimon and arp_interval not set, we need one so things
 		 * work as expected, see bonding.txt for details
 		 */
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: either miimon or arp_interval and "
 		       "arp_ip_target module parameters must be specified, "
 		       "otherwise bonding will not detect link failures! see "
@@ -5026,7 +4980,7 @@
 		/* currently, using a primary only makes sense
 		 * in active backup, TLB or ALB modes
 		 */
-		printk(KERN_WARNING DRV_NAME
+		pr_warning(DRV_NAME
 		       ": Warning: %s primary device specified but has no "
 		       "effect in %s mode\n",
 		       primary, bond_mode_name(bond_mode));
@@ -5037,14 +4991,14 @@
 		fail_over_mac_value = bond_parse_parm(fail_over_mac,
 						      fail_over_mac_tbl);
 		if (fail_over_mac_value == -1) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": Error: invalid fail_over_mac \"%s\"\n",
 			       arp_validate == NULL ? "NULL" : arp_validate);
 			return -EINVAL;
 		}
 
 		if (bond_mode != BOND_MODE_ACTIVEBACKUP)
-			printk(KERN_WARNING DRV_NAME
+			pr_warning(DRV_NAME
 			       ": Warning: fail_over_mac only affects "
 			       "active-backup mode.\n");
 	} else {
@@ -5094,37 +5048,53 @@
 	netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
 }
 
+/*
+ * Called from registration process
+ */
+static int bond_init(struct net_device *bond_dev)
+{
+	struct bonding *bond = netdev_priv(bond_dev);
+
+	pr_debug("Begin bond_init for %s\n", bond_dev->name);
+
+	bond->wq = create_singlethread_workqueue(bond_dev->name);
+	if (!bond->wq)
+		return -ENOMEM;
+
+	bond_set_lockdep_class(bond_dev);
+
+	netif_carrier_off(bond_dev);
+
+	bond_create_proc_entry(bond);
+	list_add_tail(&bond->bond_list, &bond_dev_list);
+
+	return 0;
+}
+
 /* Create a new bond based on the specified name and bonding parameters.
  * If name is NULL, obtain a suitable "bond%d" name for us.
  * Caller must NOT hold rtnl_lock; we need to release it here before we
  * set up our sysfs entries.
  */
-int bond_create(char *name, struct bond_params *params)
+int bond_create(const char *name)
 {
 	struct net_device *bond_dev;
-	struct bonding *bond;
 	int res;
 
 	rtnl_lock();
-	down_write(&bonding_rwsem);
-
 	/* Check to see if the bond already exists. */
-	if (name) {
-		list_for_each_entry(bond, &bond_dev_list, bond_list)
-			if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
-				printk(KERN_ERR DRV_NAME
-			       ": cannot add bond %s; it already exists\n",
-				       name);
-				res = -EPERM;
-				goto out_rtnl;
-			}
+	/* FIXME: pass netns from caller */
+	if (name && __dev_get_by_name(&init_net, name)) {
+		pr_err(DRV_NAME ": cannot add bond %s; already exists\n",
+		       name);
+		res = -EEXIST;
+		goto out_rtnl;
 	}
 
 	bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
-				ether_setup);
+				bond_setup);
 	if (!bond_dev) {
-		printk(KERN_ERR DRV_NAME
-		       ": %s: eek! can't alloc netdev!\n",
+		pr_err(DRV_NAME ": %s: eek! can't alloc netdev!\n",
 		       name);
 		res = -ENOMEM;
 		goto out_rtnl;
@@ -5136,43 +5106,24 @@
 			goto out_netdev;
 	}
 
-	/* bond_init() must be called after dev_alloc_name() (for the
-	 * /proc files), but before register_netdevice(), because we
-	 * need to set function pointers.
-	 */
-
-	res = bond_init(bond_dev, params);
-	if (res < 0) {
-		goto out_netdev;
-	}
-
 	res = register_netdevice(bond_dev);
-	if (res < 0) {
+	if (res < 0)
 		goto out_bond;
-	}
-
-	bond_set_lockdep_class(bond_dev);
 
-	netif_carrier_off(bond_dev);
-
-	up_write(&bonding_rwsem);
-	rtnl_unlock(); /* allows sysfs registration of net device */
 	res = bond_create_sysfs_entry(netdev_priv(bond_dev));
 	if (res < 0)
 		goto out_unreg;
 
+	rtnl_unlock();
 	return 0;
 
 out_unreg:
-	rtnl_lock();
-	down_write(&bonding_rwsem);
 	unregister_netdevice(bond_dev);
 out_bond:
 	bond_deinit(bond_dev);
 out_netdev:
 	free_netdev(bond_dev);
 out_rtnl:
-	up_write(&bonding_rwsem);
 	rtnl_unlock();
 	return res;
 }
@@ -5182,21 +5133,16 @@
 	int i;
 	int res;
 
-	printk(KERN_INFO "%s", version);
+	pr_info("%s", version);
 
 	res = bond_check_params(&bonding_defaults);
-	if (res) {
+	if (res)
 		goto out;
-	}
 
-#ifdef CONFIG_PROC_FS
 	bond_create_proc_dir();
-#endif
-
-	init_rwsem(&bonding_rwsem);
 
 	for (i = 0; i < max_bonds; i++) {
-		res = bond_create(NULL, &bonding_defaults);
+		res = bond_create(NULL);
 		if (res)
 			goto err;
 	}
@@ -5238,13 +5184,3 @@
 MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
 MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others");
-MODULE_SUPPORTED_DEVICE("most ethernet devices");
-
-/*
- * Local variables:
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/bonding/bond_sysfs.c linux-libre-2.6.31-gnu/drivers/net/bonding/bond_sysfs.c
--- linux-libre-2.6.30-gnu/drivers/net/bonding/bond_sysfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/bonding/bond_sysfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,3 @@
-
 /*
  * Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
  *
@@ -34,33 +33,14 @@
 #include <linux/ctype.h>
 #include <linux/inet.h>
 #include <linux/rtnetlink.h>
+#include <linux/etherdevice.h>
 #include <net/net_namespace.h>
 
 #include "bonding.h"
 
-#define to_dev(obj)	container_of(obj,struct device,kobj)
+#define to_dev(obj)	container_of(obj, struct device, kobj)
 #define to_bond(cd)	((struct bonding *)(netdev_priv(to_net_dev(cd))))
 
-/*---------------------------- Declarations -------------------------------*/
-
-static int expected_refcount = -1;
-/*--------------------------- Data Structures -----------------------------*/
-
-/* Bonding sysfs lock.  Why can't we just use the subsystem lock?
- * Because kobject_register tries to acquire the subsystem lock.  If
- * we already hold the lock (which we would if the user was creating
- * a new bond through the sysfs interface), we deadlock.
- * This lock is only needed when deleting a bond - we need to make sure
- * that we don't collide with an ongoing ioctl.
- */
-
-struct rw_semaphore bonding_rwsem;
-
-
-
-
-/*------------------------------ Functions --------------------------------*/
-
 /*
  * "show" function for the bond_masters attribute.
  * The class parameter is ignored.
@@ -70,7 +50,7 @@
 	int res = 0;
 	struct bonding *bond;
 
-	down_read(&(bonding_rwsem));
+	rtnl_lock();
 
 	list_for_each_entry(bond, &bond_dev_list, bond_list) {
 		if (res > (PAGE_SIZE - IFNAMSIZ)) {
@@ -84,10 +64,22 @@
 	}
 	if (res)
 		buf[res-1] = '\n'; /* eat the leftover space */
-	up_read(&(bonding_rwsem));
+
+	rtnl_unlock();
 	return res;
 }
 
+static struct net_device *bond_get_by_name(const char *ifname)
+{
+	struct bonding *bond;
+
+	list_for_each_entry(bond, &bond_dev_list, bond_list) {
+		if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
+			return bond->dev;
+	}
+	return NULL;
+}
+
 /*
  * "store" function for the bond_masters attribute.  This is what
  * creates and deletes entire bonds.
@@ -96,12 +88,12 @@
  *
  */
 
-static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count)
+static ssize_t bonding_store_bonds(struct class *cls,
+				   const char *buffer, size_t count)
 {
 	char command[IFNAMSIZ + 1] = {0, };
 	char *ifname;
 	int rv, res = count;
-	struct bonding *bond;
 
 	sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
 	ifname = command + 1;
@@ -110,67 +102,48 @@
 		goto err_no_cmd;
 
 	if (command[0] == '+') {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 			": %s is being created...\n", ifname);
-		rv = bond_create(ifname, &bonding_defaults);
+		rv = bond_create(ifname);
 		if (rv) {
-			printk(KERN_INFO DRV_NAME ": Bond creation failed.\n");
+			pr_info(DRV_NAME ": Bond creation failed.\n");
 			res = rv;
 		}
-		goto out;
-	}
+	} else if (command[0] == '-') {
+		struct net_device *bond_dev;
 
-	if (command[0] == '-') {
 		rtnl_lock();
-		down_write(&bonding_rwsem);
-
-		list_for_each_entry(bond, &bond_dev_list, bond_list)
-			if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
-				/* check the ref count on the bond's kobject.
-				 * If it's > expected, then there's a file open,
-				 * and we have to fail.
-				 */
-				if (atomic_read(&bond->dev->dev.kobj.kref.refcount)
-							> expected_refcount){
-					printk(KERN_INFO DRV_NAME
-						": Unable remove bond %s due to open references.\n",
-						ifname);
-					res = -EPERM;
-					goto out_unlock;
-				}
-				printk(KERN_INFO DRV_NAME
-					": %s is being deleted...\n",
-					bond->dev->name);
-				bond_destroy(bond);
-				goto out_unlock;
-			}
-
-		printk(KERN_ERR DRV_NAME
-			": unable to delete non-existent bond %s\n", ifname);
-		res = -ENODEV;
-		goto out_unlock;
-	}
-
-err_no_cmd:
-	printk(KERN_ERR DRV_NAME
-		": no command found in bonding_masters. Use +ifname or -ifname.\n");
-	return -EPERM;
-
-out_unlock:
-	up_write(&bonding_rwsem);
-	rtnl_unlock();
+		bond_dev = bond_get_by_name(ifname);
+		if (bond_dev) {
+			pr_info(DRV_NAME ": %s is being deleted...\n",
+				ifname);
+			unregister_netdevice(bond_dev);
+		} else {
+			pr_err(DRV_NAME ": unable to delete non-existent %s\n",
+			       ifname);
+			res = -ENODEV;
+		}
+		rtnl_unlock();
+	} else
+		goto err_no_cmd;
 
 	/* Always return either count or an error.  If you return 0, you'll
 	 * get called forever, which is bad.
 	 */
-out:
 	return res;
+
+err_no_cmd:
+	pr_err(DRV_NAME ": no command found in bonding_masters."
+	       " Use +ifname or -ifname.\n");
+	return -EPERM;
 }
+
 /* class attribute for bond_masters file.  This ends up in /sys/class/net */
 static CLASS_ATTR(bonding_masters,  S_IWUSR | S_IRUGO,
 		  bonding_show_bonds, bonding_store_bonds);
 
-int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave)
+int bond_create_slave_symlinks(struct net_device *master,
+			       struct net_device *slave)
 {
 	char linkname[IFNAMSIZ+7];
 	int ret = 0;
@@ -181,19 +154,20 @@
 	if (ret)
 		return ret;
 	/* next, create a link from the master to the slave */
-	sprintf(linkname,"slave_%s",slave->name);
+	sprintf(linkname, "slave_%s", slave->name);
 	ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
 				linkname);
 	return ret;
 
 }
 
-void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave)
+void bond_destroy_slave_symlinks(struct net_device *master,
+				 struct net_device *slave)
 {
 	char linkname[IFNAMSIZ+7];
 
 	sysfs_remove_link(&(slave->dev.kobj), "master");
-	sprintf(linkname,"slave_%s",slave->name);
+	sprintf(linkname, "slave_%s", slave->name);
 	sysfs_remove_link(&(master->dev.kobj), linkname);
 }
 
@@ -251,8 +225,8 @@
 
 	/* Note:  We can't hold bond->lock here, as bond_create grabs it. */
 
-	rtnl_lock();
-	down_write(&(bonding_rwsem));
+	if (!rtnl_trylock())
+		return restart_syscall();
 
 	sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
 	ifname = command + 1;
@@ -264,46 +238,47 @@
 
 		/* Got a slave name in ifname.  Is it already in the list? */
 		found = 0;
-		read_lock(&bond->lock);
-		bond_for_each_slave(bond, slave, i)
-			if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
-				printk(KERN_ERR DRV_NAME
-				       ": %s: Interface %s is already enslaved!\n",
-				       bond->dev->name, ifname);
-				ret = -EPERM;
-				read_unlock(&bond->lock);
-				goto out;
-			}
 
-		read_unlock(&bond->lock);
-		printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
-		       bond->dev->name, ifname);
-		dev = dev_get_by_name(&init_net, ifname);
+		/* FIXME: get netns from sysfs object */
+		dev = __dev_get_by_name(&init_net, ifname);
 		if (!dev) {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: Interface %s does not exist!\n",
 			       bond->dev->name, ifname);
-			ret = -EPERM;
+			ret = -ENODEV;
 			goto out;
 		}
-		else
-			dev_put(dev);
 
 		if (dev->flags & IFF_UP) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: Error: Unable to enslave %s "
 			       "because it is already up.\n",
 			       bond->dev->name, dev->name);
 			ret = -EPERM;
 			goto out;
 		}
+
+		read_lock(&bond->lock);
+		bond_for_each_slave(bond, slave, i)
+			if (slave->dev == dev) {
+				pr_err(DRV_NAME
+				       ": %s: Interface %s is already enslaved!\n",
+				       bond->dev->name, ifname);
+				ret = -EPERM;
+				read_unlock(&bond->lock);
+				goto out;
+			}
+		read_unlock(&bond->lock);
+
+		pr_info(DRV_NAME ": %s: Adding slave %s.\n",
+			bond->dev->name, ifname);
+
 		/* If this is the first slave, then we need to set
 		   the master's hardware address to be the same as the
 		   slave's. */
-		if (!(*((u32 *) & (bond->dev->dev_addr[0])))) {
+		if (is_zero_ether_addr(bond->dev->dev_addr))
 			memcpy(bond->dev->dev_addr, dev->dev_addr,
 			       dev->addr_len);
-		}
 
 		/* Set the slave's MTU to match the bond */
 		original_mtu = dev->mtu;
@@ -317,9 +292,9 @@
 		bond_for_each_slave(bond, slave, i)
 			if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
 				slave->original_mtu = original_mtu;
-		if (res) {
+		if (res)
 			ret = res;
-		}
+
 		goto out;
 	}
 
@@ -333,7 +308,7 @@
 				break;
 			}
 		if (dev) {
-			printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
+			pr_info(DRV_NAME ": %s: Removing slave %s\n",
 				bond->dev->name, dev->name);
 				res = bond_release(bond->dev, dev);
 			if (res) {
@@ -342,9 +317,9 @@
 			}
 			/* set the slave MTU to the default */
 			dev_set_mtu(dev, original_mtu);
-		}
-		else {
-			printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n",
+		} else {
+			pr_err(DRV_NAME ": unable to remove non-existent"
+			       " slave %s for bond %s.\n",
 				ifname, bond->dev->name);
 			ret = -ENODEV;
 		}
@@ -352,16 +327,16 @@
 	}
 
 err_no_cmd:
-	printk(KERN_ERR DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name);
+	pr_err(DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name);
 	ret = -EPERM;
 
 out:
-	up_write(&(bonding_rwsem));
 	rtnl_unlock();
 	return ret;
 }
 
-static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
+static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves,
+		   bonding_store_slaves);
 
 /*
  * Show and set the bonding mode.  The bond interface must be down to
@@ -385,16 +360,15 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		printk(KERN_ERR DRV_NAME
-		       ": unable to update mode of %s because interface is up.\n",
-		       bond->dev->name);
+		pr_err(DRV_NAME ": unable to update mode of %s"
+		       " because interface is up.\n", bond->dev->name);
 		ret = -EPERM;
 		goto out;
 	}
 
 	new_value = bond_parse_parm(buf, bond_mode_tbl);
 	if (new_value < 0)  {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Ignoring invalid mode value %.*s.\n",
 		       bond->dev->name,
 		       (int)strlen(buf) - 1, buf);
@@ -409,17 +383,19 @@
 
 		bond->params.mode = new_value;
 		bond_set_mode_ops(bond, bond->params.mode);
-		printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n",
-			bond->dev->name, bond_mode_tbl[new_value].modename, new_value);
+		pr_info(DRV_NAME ": %s: setting mode to %s (%d).\n",
+		       bond->dev->name, bond_mode_tbl[new_value].modename,
+		       new_value);
 	}
 out:
 	return ret;
 }
-static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
+		   bonding_show_mode, bonding_store_mode);
 
 /*
- * Show and set the bonding transmit hash method.  The bond interface must be down to
- * change the xmit hash policy.
+ * Show and set the bonding transmit hash method.
+ * The bond interface must be down to change the xmit hash policy.
  */
 static ssize_t bonding_show_xmit_hash(struct device *d,
 				      struct device_attribute *attr,
@@ -440,7 +416,7 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       "%s: Interface is up. Unable to update xmit policy.\n",
 		       bond->dev->name);
 		ret = -EPERM;
@@ -449,7 +425,7 @@
 
 	new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
 	if (new_value < 0)  {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
 		       bond->dev->name,
 		       (int)strlen(buf) - 1, buf);
@@ -458,13 +434,15 @@
 	} else {
 		bond->params.xmit_policy = new_value;
 		bond_set_mode_ops(bond, bond->params.mode);
-		printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
-			bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value);
+		pr_info(DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
+			bond->dev->name,
+			xmit_hashtype_tbl[new_value].modename, new_value);
 	}
 out:
 	return ret;
 }
-static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
+static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR,
+		   bonding_show_xmit_hash, bonding_store_xmit_hash);
 
 /*
  * Show and set arp_validate.
@@ -489,39 +467,41 @@
 
 	new_value = bond_parse_parm(buf, arp_validate_tbl);
 	if (new_value < 0) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Ignoring invalid arp_validate value %s\n",
 		       bond->dev->name, buf);
 		return -EINVAL;
 	}
 	if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: arp_validate only supported in active-backup mode.\n",
 		       bond->dev->name);
 		return -EINVAL;
 	}
-	printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
+	pr_info(DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
 	       bond->dev->name, arp_validate_tbl[new_value].modename,
 	       new_value);
 
-	if (!bond->params.arp_validate && new_value) {
+	if (!bond->params.arp_validate && new_value)
 		bond_register_arp(bond);
-	} else if (bond->params.arp_validate && !new_value) {
+	else if (bond->params.arp_validate && !new_value)
 		bond_unregister_arp(bond);
-	}
 
 	bond->params.arp_validate = new_value;
 
 	return count;
 }
 
-static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
+static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate,
+		   bonding_store_arp_validate);
 
 /*
  * Show and store fail_over_mac.  User only allowed to change the
  * value when there are no slaves.
  */
-static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf)
+static ssize_t bonding_show_fail_over_mac(struct device *d,
+					  struct device_attribute *attr,
+					  char *buf)
 {
 	struct bonding *bond = to_bond(d);
 
@@ -530,13 +510,15 @@
 		       bond->params.fail_over_mac);
 }
 
-static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t bonding_store_fail_over_mac(struct device *d,
+					   struct device_attribute *attr,
+					   const char *buf, size_t count)
 {
 	int new_value;
 	struct bonding *bond = to_bond(d);
 
 	if (bond->slave_cnt != 0) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Can't alter fail_over_mac with slaves in bond.\n",
 		       bond->dev->name);
 		return -EPERM;
@@ -544,21 +526,22 @@
 
 	new_value = bond_parse_parm(buf, fail_over_mac_tbl);
 	if (new_value < 0) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Ignoring invalid fail_over_mac value %s.\n",
 		       bond->dev->name, buf);
 		return -EINVAL;
 	}
 
 	bond->params.fail_over_mac = new_value;
-	printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %s (%d).\n",
+	pr_info(DRV_NAME ": %s: Setting fail_over_mac to %s (%d).\n",
 	       bond->dev->name, fail_over_mac_tbl[new_value].modename,
 	       new_value);
 
 	return count;
 }
 
-static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac);
+static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR,
+		   bonding_show_fail_over_mac, bonding_store_fail_over_mac);
 
 /*
  * Show and set the arp timer interval.  There are two tricky bits
@@ -583,28 +566,28 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: no arp_interval value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
 		       bond->dev->name, new_value, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	printk(KERN_INFO DRV_NAME
+	pr_info(DRV_NAME
 	       ": %s: Setting ARP monitoring interval to %d.\n",
 	       bond->dev->name, new_value);
 	bond->params.arp_interval = new_value;
 	if (bond->params.arp_interval)
 		bond->dev->priv_flags |= IFF_MASTER_ARPMON;
 	if (bond->params.miimon) {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: ARP monitoring cannot be used with MII monitoring. "
 		       "%s Disabling MII monitoring.\n",
 		       bond->dev->name, bond->dev->name);
@@ -615,7 +598,7 @@
 		}
 	}
 	if (!bond->params.arp_targets[0]) {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: ARP monitoring has been set up, "
 		       "but no ARP targets have been specified.\n",
 		       bond->dev->name);
@@ -641,7 +624,8 @@
 out:
 	return ret;
 }
-static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
+static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
+		   bonding_show_arp_interval, bonding_store_arp_interval);
 
 /*
  * Show and set the arp targets.
@@ -677,7 +661,7 @@
 	/* look for adds */
 	if (buf[0] == '+') {
 		if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: invalid ARP target %pI4 specified for addition\n",
 			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
@@ -686,14 +670,14 @@
 		/* look for an empty slot to put the target in, and check for dupes */
 		for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
 			if (targets[i] == newtarget) { /* duplicate */
-				printk(KERN_ERR DRV_NAME
+				pr_err(DRV_NAME
 				       ": %s: ARP target %pI4 is already present\n",
 				       bond->dev->name, &newtarget);
 				ret = -EINVAL;
 				goto out;
 			}
 			if (targets[i] == 0) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: adding ARP target %pI4.\n",
 				       bond->dev->name, &newtarget);
 				done = 1;
@@ -701,17 +685,16 @@
 			}
 		}
 		if (!done) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: ARP target table is full!\n",
 			       bond->dev->name);
 			ret = -EINVAL;
 			goto out;
 		}
 
-	}
-	else if (buf[0] == '-')	{
+	} else if (buf[0] == '-')	{
 		if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
-			printk(KERN_ERR DRV_NAME
+			pr_err(DRV_NAME
 			       ": %s: invalid ARP target %pI4 specified for removal\n",
 			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
@@ -721,7 +704,7 @@
 		for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
 			if (targets[i] == newtarget) {
 				int j;
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: removing ARP target %pI4.\n",
 				       bond->dev->name, &newtarget);
 				for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++)
@@ -732,15 +715,15 @@
 			}
 		}
 		if (!done) {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: unable to remove nonexistent ARP target %pI4.\n",
 			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
 			goto out;
 		}
-	}
-	else {
-		printk(KERN_ERR DRV_NAME ": no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
+	} else {
+		pr_err(DRV_NAME ": no command found in arp_ip_targets file"
+		       " for bond %s. Use +<addr> or -<addr>.\n",
 			bond->dev->name);
 		ret = -EPERM;
 		goto out;
@@ -773,7 +756,7 @@
 	struct bonding *bond = to_bond(d);
 
 	if (!(bond->params.miimon)) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Unable to set down delay as MII monitoring is disabled\n",
 		       bond->dev->name);
 		ret = -EPERM;
@@ -781,14 +764,14 @@
 	}
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: no down delay value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
 		       bond->dev->name, new_value, 1, INT_MAX);
 		ret = -EINVAL;
@@ -803,15 +786,17 @@
 			       bond->params.miimon);
 		}
 		bond->params.downdelay = new_value / bond->params.miimon;
-		printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n",
-		       bond->dev->name, bond->params.downdelay * bond->params.miimon);
+		pr_info(DRV_NAME ": %s: Setting down delay to %d.\n",
+		       bond->dev->name,
+		       bond->params.downdelay * bond->params.miimon);
 
 	}
 
 out:
 	return ret;
 }
-static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
+static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR,
+		   bonding_show_downdelay, bonding_store_downdelay);
 
 static ssize_t bonding_show_updelay(struct device *d,
 				    struct device_attribute *attr,
@@ -831,7 +816,7 @@
 	struct bonding *bond = to_bond(d);
 
 	if (!(bond->params.miimon)) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Unable to set up delay as MII monitoring is disabled\n",
 		       bond->dev->name);
 		ret = -EPERM;
@@ -839,14 +824,14 @@
 	}
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: no up delay value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
 		       bond->dev->name, new_value, 1, INT_MAX);
 		ret = -EINVAL;
@@ -861,7 +846,7 @@
 			       bond->params.miimon);
 		}
 		bond->params.updelay = new_value / bond->params.miimon;
-		printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n",
+		pr_info(DRV_NAME ": %s: Setting up delay to %d.\n",
 		       bond->dev->name, bond->params.updelay * bond->params.miimon);
 
 	}
@@ -869,7 +854,8 @@
 out:
 	return ret;
 }
-static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
+static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR,
+		   bonding_show_updelay, bonding_store_updelay);
 
 /*
  * Show and set the LACP interval.  Interface must be down, and the mode
@@ -894,7 +880,7 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Unable to update LACP rate because interface is up.\n",
 		       bond->dev->name);
 		ret = -EPERM;
@@ -902,7 +888,7 @@
 	}
 
 	if (bond->params.mode != BOND_MODE_8023AD) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
 		       bond->dev->name);
 		ret = -EPERM;
@@ -913,19 +899,20 @@
 
 	if ((new_value == 1) || (new_value == 0)) {
 		bond->params.lacp_fast = new_value;
-		printk(KERN_INFO DRV_NAME
-		       ": %s: Setting LACP rate to %s (%d).\n",
-		       bond->dev->name, bond_lacp_tbl[new_value].modename, new_value);
+		pr_info(DRV_NAME ": %s: Setting LACP rate to %s (%d).\n",
+			bond->dev->name, bond_lacp_tbl[new_value].modename,
+			new_value);
 	} else {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Ignoring invalid LACP rate value %.*s.\n",
-		     	bond->dev->name, (int)strlen(buf) - 1, buf);
+		       bond->dev->name, (int)strlen(buf) - 1, buf);
 		ret = -EINVAL;
 	}
 out:
 	return ret;
 }
-static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
+static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR,
+		   bonding_show_lacp, bonding_store_lacp);
 
 static ssize_t bonding_show_ad_select(struct device *d,
 				      struct device_attribute *attr,
@@ -947,7 +934,7 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Unable to update ad_select because interface "
 		       "is up.\n", bond->dev->name);
 		ret = -EPERM;
@@ -958,12 +945,12 @@
 
 	if (new_value != -1) {
 		bond->params.ad_select = new_value;
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: Setting ad_select to %s (%d).\n",
 		       bond->dev->name, ad_select_tbl[new_value].modename,
 		       new_value);
 	} else {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Ignoring invalid ad_select value %.*s.\n",
 		       bond->dev->name, (int)strlen(buf) - 1, buf);
 		ret = -EINVAL;
@@ -971,8 +958,8 @@
 out:
 	return ret;
 }
-
-static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select);
+static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
+		   bonding_show_ad_select, bonding_store_ad_select);
 
 /*
  * Show and set the number of grat ARP to send after a failover event.
@@ -994,14 +981,14 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: no num_grat_arp value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0 || new_value > 255) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
 		       bond->dev->name, new_value);
 		ret = -EINVAL;
@@ -1012,10 +999,11 @@
 out:
 	return ret;
 }
-static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp);
+static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
+		   bonding_show_n_grat_arp, bonding_store_n_grat_arp);
 
 /*
- * Show and set the number of unsolicted NA's to send after a failover event.
+ * Show and set the number of unsolicited NA's to send after a failover event.
  */
 static ssize_t bonding_show_n_unsol_na(struct device *d,
 				       struct device_attribute *attr,
@@ -1034,25 +1022,26 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: no num_unsol_na value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
+
 	if (new_value < 0 || new_value > 255) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
 		       bond->dev->name, new_value);
 		ret = -EINVAL;
 		goto out;
-	} else {
+	} else
 		bond->params.num_unsol_na = new_value;
-	}
 out:
 	return ret;
 }
-static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, bonding_show_n_unsol_na, bonding_store_n_unsol_na);
+static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR,
+		   bonding_show_n_unsol_na, bonding_store_n_unsol_na);
 
 /*
  * Show and set the MII monitor interval.  There are two tricky bits
@@ -1077,37 +1066,37 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: no miimon value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
 		       bond->dev->name, new_value, 1, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: Setting MII monitoring interval to %d.\n",
 		       bond->dev->name, new_value);
 		bond->params.miimon = new_value;
-		if(bond->params.updelay)
-			printk(KERN_INFO DRV_NAME
+		if (bond->params.updelay)
+			pr_info(DRV_NAME
 			      ": %s: Note: Updating updelay (to %d) "
 			      "since it is a multiple of the miimon value.\n",
 			      bond->dev->name,
 			      bond->params.updelay * bond->params.miimon);
-		if(bond->params.downdelay)
-			printk(KERN_INFO DRV_NAME
+		if (bond->params.downdelay)
+			pr_info(DRV_NAME
 			      ": %s: Note: Updating downdelay (to %d) "
 			      "since it is a multiple of the miimon value.\n",
 			      bond->dev->name,
 			      bond->params.downdelay * bond->params.miimon);
 		if (bond->params.arp_interval) {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: MII monitoring cannot be used with "
 			       "ARP monitoring. Disabling ARP monitoring...\n",
 			       bond->dev->name);
@@ -1141,7 +1130,8 @@
 out:
 	return ret;
 }
-static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
+static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
+		   bonding_show_miimon, bonding_store_miimon);
 
 /*
  * Show and set the primary slave.  The store function is much
@@ -1171,12 +1161,13 @@
 	struct slave *slave;
 	struct bonding *bond = to_bond(d);
 
-	rtnl_lock();
+	if (!rtnl_trylock())
+		return restart_syscall();
 	read_lock(&bond->lock);
 	write_lock_bh(&bond->curr_slave_lock);
 
 	if (!USES_PRIMARY(bond->params.mode)) {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: Unable to set primary slave; %s is in mode %d\n",
 		       bond->dev->name, bond->dev->name, bond->params.mode);
 	} else {
@@ -1184,7 +1175,7 @@
 			if (strnicmp
 			    (slave->dev->name, buf,
 			     strlen(slave->dev->name)) == 0) {
-				printk(KERN_INFO DRV_NAME
+				pr_info(DRV_NAME
 				       ": %s: Setting %s as primary slave.\n",
 				       bond->dev->name, slave->dev->name);
 				bond->primary_slave = slave;
@@ -1196,13 +1187,13 @@
 		/* if we got here, then we didn't match the name of any slave */
 
 		if (strlen(buf) == 0 || buf[0] == '\n') {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: Setting primary slave to None.\n",
 			       bond->dev->name);
 			bond->primary_slave = NULL;
 				bond_select_active_slave(bond);
 		} else {
-			printk(KERN_INFO DRV_NAME
+			pr_info(DRV_NAME
 			       ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
 			       bond->dev->name, (int)strlen(buf) - 1, buf);
 		}
@@ -1214,7 +1205,8 @@
 
 	return count;
 }
-static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
+static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR,
+		   bonding_show_primary, bonding_store_primary);
 
 /*
  * Show and set the use_carrier flag.
@@ -1237,7 +1229,7 @@
 
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		printk(KERN_ERR DRV_NAME
+		pr_err(DRV_NAME
 		       ": %s: no use_carrier value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
@@ -1245,17 +1237,18 @@
 	}
 	if ((new_value == 0) || (new_value == 1)) {
 		bond->params.use_carrier = new_value;
-		printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n",
+		pr_info(DRV_NAME ": %s: Setting use_carrier to %d.\n",
 		       bond->dev->name, new_value);
 	} else {
-		printk(KERN_INFO DRV_NAME
+		pr_info(DRV_NAME
 		       ": %s: Ignoring invalid use_carrier value %d.\n",
 		       bond->dev->name, new_value);
 	}
 out:
 	return count;
 }
-static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
+static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR,
+		   bonding_show_carrier, bonding_store_carrier);
 
 
 /*
@@ -1284,19 +1277,20 @@
 {
 	int i;
 	struct slave *slave;
-        struct slave *old_active = NULL;
-        struct slave *new_active = NULL;
+	struct slave *old_active = NULL;
+	struct slave *new_active = NULL;
 	struct bonding *bond = to_bond(d);
 
-	rtnl_lock();
+	if (!rtnl_trylock())
+		return restart_syscall();
 	read_lock(&bond->lock);
 	write_lock_bh(&bond->curr_slave_lock);
 
-	if (!USES_PRIMARY(bond->params.mode)) {
-		printk(KERN_INFO DRV_NAME
-		       ": %s: Unable to change active slave; %s is in mode %d\n",
-		       bond->dev->name, bond->dev->name, bond->params.mode);
-	} else {
+	if (!USES_PRIMARY(bond->params.mode))
+		pr_info(DRV_NAME ": %s: Unable to change active slave;"
+			" %s is in mode %d\n",
+			bond->dev->name, bond->dev->name, bond->params.mode);
+	else {
 		bond_for_each_slave(bond, slave, i) {
 			if (strnicmp
 			    (slave->dev->name, buf,
@@ -1335,18 +1329,18 @@
 		/* if we got here, then we didn't match the name of any slave */
 
 		if (strlen(buf) == 0 || buf[0] == '\n') {
-			printk(KERN_INFO DRV_NAME
-			       ": %s: Setting active slave to None.\n",
-			       bond->dev->name);
+			pr_info(DRV_NAME
+				": %s: Setting active slave to None.\n",
+				bond->dev->name);
 			bond->primary_slave = NULL;
-				bond_select_active_slave(bond);
+			bond_select_active_slave(bond);
 		} else {
-			printk(KERN_INFO DRV_NAME
-			       ": %s: Unable to set %.*s as active slave as it is not a slave.\n",
-			       bond->dev->name, (int)strlen(buf) - 1, buf);
+			pr_info(DRV_NAME ": %s: Unable to set %.*s"
+				" as active slave as it is not a slave.\n",
+				bond->dev->name, (int)strlen(buf) - 1, buf);
 		}
 	}
-out:
+ out:
 	write_unlock_bh(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	rtnl_unlock();
@@ -1354,7 +1348,8 @@
 	return count;
 
 }
-static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
+static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR,
+		   bonding_show_active_slave, bonding_store_active_slave);
 
 
 /*
@@ -1371,7 +1366,7 @@
 	curr = bond->curr_active_slave;
 	read_unlock(&bond->curr_slave_lock);
 
-	return sprintf(buf, "%s\n", (curr) ? "up" : "down");
+	return sprintf(buf, "%s\n", curr ? "up" : "down");
 }
 static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
 
@@ -1388,7 +1383,9 @@
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
-		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.aggregator_id);
+		count = sprintf(buf, "%d\n",
+				(bond_3ad_get_active_agg_info(bond, &ad_info))
+				?  0 : ad_info.aggregator_id);
 	}
 
 	return count;
@@ -1408,7 +1405,9 @@
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
-		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0: ad_info.ports);
+		count = sprintf(buf, "%d\n",
+				(bond_3ad_get_active_agg_info(bond, &ad_info))
+				?  0 : ad_info.ports);
 	}
 
 	return count;
@@ -1428,7 +1427,9 @@
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
-		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.actor_key);
+		count = sprintf(buf, "%d\n",
+				(bond_3ad_get_active_agg_info(bond, &ad_info))
+				?  0 : ad_info.actor_key);
 	}
 
 	return count;
@@ -1448,7 +1449,9 @@
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
-		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.partner_key);
+		count = sprintf(buf, "%d\n",
+				(bond_3ad_get_active_agg_info(bond, &ad_info))
+				?  0 : ad_info.partner_key);
 	}
 
 	return count;
@@ -1468,9 +1471,8 @@
 
 	if (bond->params.mode == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
-		if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
+		if (!bond_3ad_get_active_agg_info(bond, &ad_info))
 			count = sprintf(buf, "%pM\n", ad_info.partner_system);
-		}
 	}
 
 	return count;
@@ -1538,6 +1540,7 @@
 			printk(KERN_ERR
 			       "network device named %s already exists in sysfs",
 			       class_attr_bonding_masters.attr.name);
+		ret = 0;
 	}
 
 	return ret;
@@ -1562,12 +1565,8 @@
 	int err;
 
 	err = sysfs_create_group(&(dev->dev.kobj), &bonding_group);
-	if (err) {
+	if (err)
 		printk(KERN_EMERG "eek! didn't create group!\n");
-	}
-
-	if (expected_refcount < 1)
-		expected_refcount = atomic_read(&bond->dev->dev.kobj.kref.refcount);
 
 	return err;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/dev.c linux-libre-2.6.31-gnu/drivers/net/can/dev.c
--- linux-libre-2.6.30-gnu/drivers/net/can/dev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/dev.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
+ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/netlink.h>
+#include <net/rtnetlink.h>
+
+#define MOD_DESC "CAN device driver interface"
+
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+
+#ifdef CONFIG_CAN_CALC_BITTIMING
+#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
+
+/*
+ * Bit-timing calculation derived from:
+ *
+ * Code based on LinCAN sources and H8S2638 project
+ * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
+ * Copyright 2005      Stanislav Marek
+ * email: pisa@cmp.felk.cvut.cz
+ *
+ * Calculates proper bit-timing parameters for a specified bit-rate
+ * and sample-point, which can then be used to set the bit-timing
+ * registers of the CAN controller. You can find more information
+ * in the header file linux/can/netlink.h.
+ */
+static int can_update_spt(const struct can_bittiming_const *btc,
+			  int sampl_pt, int tseg, int *tseg1, int *tseg2)
+{
+	*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
+	if (*tseg2 < btc->tseg2_min)
+		*tseg2 = btc->tseg2_min;
+	if (*tseg2 > btc->tseg2_max)
+		*tseg2 = btc->tseg2_max;
+	*tseg1 = tseg - *tseg2;
+	if (*tseg1 > btc->tseg1_max) {
+		*tseg1 = btc->tseg1_max;
+		*tseg2 = tseg - *tseg1;
+	}
+	return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
+}
+
+static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	const struct can_bittiming_const *btc = priv->bittiming_const;
+	long rate, best_rate = 0;
+	long best_error = 1000000000, error = 0;
+	int best_tseg = 0, best_brp = 0, brp = 0;
+	int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
+	int spt_error = 1000, spt = 0, sampl_pt;
+	u64 v64;
+
+	if (!priv->bittiming_const)
+		return -ENOTSUPP;
+
+	/* Use CIA recommended sample points */
+	if (bt->sample_point) {
+		sampl_pt = bt->sample_point;
+	} else {
+		if (bt->bitrate > 800000)
+			sampl_pt = 750;
+		else if (bt->bitrate > 500000)
+			sampl_pt = 800;
+		else
+			sampl_pt = 875;
+	}
+
+	/* tseg even = round down, odd = round up */
+	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
+	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
+		tsegall = 1 + tseg / 2;
+		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
+		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
+		/* chose brp step which is possible in system */
+		brp = (brp / btc->brp_inc) * btc->brp_inc;
+		if ((brp < btc->brp_min) || (brp > btc->brp_max))
+			continue;
+		rate = priv->clock.freq / (brp * tsegall);
+		error = bt->bitrate - rate;
+		/* tseg brp biterror */
+		if (error < 0)
+			error = -error;
+		if (error > best_error)
+			continue;
+		best_error = error;
+		if (error == 0) {
+			spt = can_update_spt(btc, sampl_pt, tseg / 2,
+					     &tseg1, &tseg2);
+			error = sampl_pt - spt;
+			if (error < 0)
+				error = -error;
+			if (error > spt_error)
+				continue;
+			spt_error = error;
+		}
+		best_tseg = tseg / 2;
+		best_brp = brp;
+		best_rate = rate;
+		if (error == 0)
+			break;
+	}
+
+	if (best_error) {
+		/* Error in one-tenth of a percent */
+		error = (best_error * 1000) / bt->bitrate;
+		if (error > CAN_CALC_MAX_ERROR) {
+			dev_err(dev->dev.parent,
+				"bitrate error %ld.%ld%% too high\n",
+				error / 10, error % 10);
+			return -EDOM;
+		} else {
+			dev_warn(dev->dev.parent, "bitrate error %ld.%ld%%\n",
+				 error / 10, error % 10);
+		}
+	}
+
+	/* real sample point */
+	bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg,
+					  &tseg1, &tseg2);
+
+	v64 = (u64)best_brp * 1000000000UL;
+	do_div(v64, priv->clock.freq);
+	bt->tq = (u32)v64;
+	bt->prop_seg = tseg1 / 2;
+	bt->phase_seg1 = tseg1 - bt->prop_seg;
+	bt->phase_seg2 = tseg2;
+	bt->sjw = 1;
+	bt->brp = best_brp;
+	/* real bit-rate */
+	bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));
+
+	return 0;
+}
+#else /* !CONFIG_CAN_CALC_BITTIMING */
+static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
+{
+	dev_err(dev->dev.parent, "bit-timing calculation not available\n");
+	return -EINVAL;
+}
+#endif /* CONFIG_CAN_CALC_BITTIMING */
+
+/*
+ * Checks the validity of the specified bit-timing parameters prop_seg,
+ * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
+ * prescaler value brp. You can find more information in the header
+ * file linux/can/netlink.h.
+ */
+static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	const struct can_bittiming_const *btc = priv->bittiming_const;
+	int tseg1, alltseg;
+	u64 brp64;
+
+	if (!priv->bittiming_const)
+		return -ENOTSUPP;
+
+	tseg1 = bt->prop_seg + bt->phase_seg1;
+	if (!bt->sjw)
+		bt->sjw = 1;
+	if (bt->sjw > btc->sjw_max ||
+	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
+	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
+		return -ERANGE;
+
+	brp64 = (u64)priv->clock.freq * (u64)bt->tq;
+	if (btc->brp_inc > 1)
+		do_div(brp64, btc->brp_inc);
+	brp64 += 500000000UL - 1;
+	do_div(brp64, 1000000000UL); /* the practicable BRP */
+	if (btc->brp_inc > 1)
+		brp64 *= btc->brp_inc;
+	bt->brp = (u32)brp64;
+
+	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
+		return -EINVAL;
+
+	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
+	bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
+	bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
+
+	return 0;
+}
+
+int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int err;
+
+	/* Check if the CAN device has bit-timing parameters */
+	if (priv->bittiming_const) {
+
+		/* Non-expert mode? Check if the bitrate has been pre-defined */
+		if (!bt->tq)
+			/* Determine bit-timing parameters */
+			err = can_calc_bittiming(dev, bt);
+		else
+			/* Check bit-timing params and calculate proper brp */
+			err = can_fixup_bittiming(dev, bt);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+/*
+ * Local echo of CAN messages
+ *
+ * CAN network devices *should* support a local echo functionality
+ * (see Documentation/networking/can.txt). To test the handling of CAN
+ * interfaces that do not support the local echo both driver types are
+ * implemented. In the case that the driver does not support the echo
+ * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
+ * to perform the echo as a fallback solution.
+ */
+static void can_flush_echo_skb(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	int i;
+
+	for (i = 0; i < CAN_ECHO_SKB_MAX; i++) {
+		if (priv->echo_skb[i]) {
+			kfree_skb(priv->echo_skb[i]);
+			priv->echo_skb[i] = NULL;
+			stats->tx_dropped++;
+			stats->tx_aborted_errors++;
+		}
+	}
+}
+
+/*
+ * Put the skb on the stack to be looped backed locally lateron
+ *
+ * The function is typically called in the start_xmit function
+ * of the device driver. The driver must protect access to
+ * priv->echo_skb, if necessary.
+ */
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	/* check flag whether this packet has to be looped back */
+	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) {
+		kfree_skb(skb);
+		return;
+	}
+
+	if (!priv->echo_skb[idx]) {
+		struct sock *srcsk = skb->sk;
+
+		if (atomic_read(&skb->users) != 1) {
+			struct sk_buff *old_skb = skb;
+
+			skb = skb_clone(old_skb, GFP_ATOMIC);
+			kfree_skb(old_skb);
+			if (!skb)
+				return;
+		} else
+			skb_orphan(skb);
+
+		skb->sk = srcsk;
+
+		/* make settings for echo to reduce code in irq context */
+		skb->protocol = htons(ETH_P_CAN);
+		skb->pkt_type = PACKET_BROADCAST;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->dev = dev;
+
+		/* save this skb for tx interrupt echo handling */
+		priv->echo_skb[idx] = skb;
+	} else {
+		/* locking problem with netif_stop_queue() ?? */
+		dev_err(dev->dev.parent, "%s: BUG! echo_skb is occupied!\n",
+			__func__);
+		kfree_skb(skb);
+	}
+}
+EXPORT_SYMBOL_GPL(can_put_echo_skb);
+
+/*
+ * Get the skb from the stack and loop it back locally
+ *
+ * The function is typically called when the TX done interrupt
+ * is handled in the device driver. The driver must protect
+ * access to priv->echo_skb, if necessary.
+ */
+void can_get_echo_skb(struct net_device *dev, int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if ((dev->flags & IFF_ECHO) && priv->echo_skb[idx]) {
+		netif_rx(priv->echo_skb[idx]);
+		priv->echo_skb[idx] = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(can_get_echo_skb);
+
+/*
+ * CAN device restart for bus-off recovery
+ */
+void can_restart(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	int err;
+
+	BUG_ON(netif_carrier_ok(dev));
+
+	/*
+	 * No synchronization needed because the device is bus-off and
+	 * no messages can come in or go out.
+	 */
+	can_flush_echo_skb(dev);
+
+	/* send restart message upstream */
+	skb = dev_alloc_skb(sizeof(struct can_frame));
+	if (skb == NULL) {
+		err = -ENOMEM;
+		goto restart;
+	}
+	skb->dev = dev;
+	skb->protocol = htons(ETH_P_CAN);
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+	memset(cf, 0, sizeof(struct can_frame));
+	cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
+	cf->can_dlc = CAN_ERR_DLC;
+
+	netif_rx(skb);
+
+	dev->last_rx = jiffies;
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+restart:
+	dev_dbg(dev->dev.parent, "restarted\n");
+	priv->can_stats.restarts++;
+
+	/* Now restart the device */
+	err = priv->do_set_mode(dev, CAN_MODE_START);
+
+	netif_carrier_on(dev);
+	if (err)
+		dev_err(dev->dev.parent, "Error %d during restart", err);
+}
+
+int can_restart_now(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	/*
+	 * A manual restart is only permitted if automatic restart is
+	 * disabled and the device is in the bus-off state
+	 */
+	if (priv->restart_ms)
+		return -EINVAL;
+	if (priv->state != CAN_STATE_BUS_OFF)
+		return -EBUSY;
+
+	/* Runs as soon as possible in the timer context */
+	mod_timer(&priv->restart_timer, jiffies);
+
+	return 0;
+}
+
+/*
+ * CAN bus-off
+ *
+ * This functions should be called when the device goes bus-off to
+ * tell the netif layer that no more packets can be sent or received.
+ * If enabled, a timer is started to trigger bus-off recovery.
+ */
+void can_bus_off(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	dev_dbg(dev->dev.parent, "bus-off\n");
+
+	netif_carrier_off(dev);
+	priv->can_stats.bus_off++;
+
+	if (priv->restart_ms)
+		mod_timer(&priv->restart_timer,
+			  jiffies + (priv->restart_ms * HZ) / 1000);
+}
+EXPORT_SYMBOL_GPL(can_bus_off);
+
+static void can_setup(struct net_device *dev)
+{
+	dev->type = ARPHRD_CAN;
+	dev->mtu = sizeof(struct can_frame);
+	dev->hard_header_len = 0;
+	dev->addr_len = 0;
+	dev->tx_queue_len = 10;
+
+	/* New-style flags. */
+	dev->flags = IFF_NOARP;
+	dev->features = NETIF_F_NO_CSUM;
+}
+
+/*
+ * Allocate and setup space for the CAN network device
+ */
+struct net_device *alloc_candev(int sizeof_priv)
+{
+	struct net_device *dev;
+	struct can_priv *priv;
+
+	dev = alloc_netdev(sizeof_priv, "can%d", can_setup);
+	if (!dev)
+		return NULL;
+
+	priv = netdev_priv(dev);
+
+	priv->state = CAN_STATE_STOPPED;
+
+	init_timer(&priv->restart_timer);
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_candev);
+
+/*
+ * Free space of the CAN network device
+ */
+void free_candev(struct net_device *dev)
+{
+	free_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(free_candev);
+
+/*
+ * Common open function when the device gets opened.
+ *
+ * This function should be called in the open function of the device
+ * driver.
+ */
+int open_candev(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (!priv->bittiming.tq && !priv->bittiming.bitrate) {
+		dev_err(dev->dev.parent, "bit-timing not yet defined\n");
+		return -EINVAL;
+	}
+
+	/* Switch carrier on if device was stopped while in bus-off state */
+	if (!netif_carrier_ok(dev))
+		netif_carrier_on(dev);
+
+	setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(open_candev);
+
+/*
+ * Common close function for cleanup before the device gets closed.
+ *
+ * This function should be called in the close function of the device
+ * driver.
+ */
+void close_candev(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (del_timer_sync(&priv->restart_timer))
+		dev_put(dev);
+	can_flush_echo_skb(dev);
+}
+EXPORT_SYMBOL_GPL(close_candev);
+
+/*
+ * CAN netlink interface
+ */
+static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
+	[IFLA_CAN_STATE]	= { .type = NLA_U32 },
+	[IFLA_CAN_CTRLMODE]	= { .len = sizeof(struct can_ctrlmode) },
+	[IFLA_CAN_RESTART_MS]	= { .type = NLA_U32 },
+	[IFLA_CAN_RESTART]	= { .type = NLA_U32 },
+	[IFLA_CAN_BITTIMING]	= { .len = sizeof(struct can_bittiming) },
+	[IFLA_CAN_BITTIMING_CONST]
+				= { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_CAN_CLOCK]	= { .len = sizeof(struct can_clock) },
+};
+
+static int can_changelink(struct net_device *dev,
+			  struct nlattr *tb[], struct nlattr *data[])
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int err;
+
+	/* We need synchronization with dev->stop() */
+	ASSERT_RTNL();
+
+	if (data[IFLA_CAN_CTRLMODE]) {
+		struct can_ctrlmode *cm;
+
+		/* Do not allow changing controller mode while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+		priv->ctrlmode &= ~cm->mask;
+		priv->ctrlmode |= cm->flags;
+	}
+
+	if (data[IFLA_CAN_BITTIMING]) {
+		struct can_bittiming bt;
+
+		/* Do not allow changing bittiming while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
+		if ((!bt.bitrate && !bt.tq) || (bt.bitrate && bt.tq))
+			return -EINVAL;
+		err = can_get_bittiming(dev, &bt);
+		if (err)
+			return err;
+		memcpy(&priv->bittiming, &bt, sizeof(bt));
+
+		if (priv->do_set_bittiming) {
+			/* Finally, set the bit-timing registers */
+			err = priv->do_set_bittiming(dev);
+			if (err)
+				return err;
+		}
+	}
+
+	if (data[IFLA_CAN_RESTART_MS]) {
+		/* Do not allow changing restart delay while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
+	}
+
+	if (data[IFLA_CAN_RESTART]) {
+		/* Do not allow a restart while not running */
+		if (!(dev->flags & IFF_UP))
+			return -EINVAL;
+		err = can_restart_now(dev);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
+	enum can_state state = priv->state;
+
+	if (priv->do_get_state)
+		priv->do_get_state(dev, &state);
+	NLA_PUT_U32(skb, IFLA_CAN_STATE, state);
+	NLA_PUT(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm);
+	NLA_PUT_U32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms);
+	NLA_PUT(skb, IFLA_CAN_BITTIMING,
+		sizeof(priv->bittiming), &priv->bittiming);
+	NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock);
+	if (priv->bittiming_const)
+		NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST,
+			sizeof(*priv->bittiming_const), priv->bittiming_const);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	NLA_PUT(skb, IFLA_INFO_XSTATS,
+		sizeof(priv->can_stats), &priv->can_stats);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int can_newlink(struct net_device *dev,
+		       struct nlattr *tb[], struct nlattr *data[])
+{
+	return -EOPNOTSUPP;
+}
+
+static struct rtnl_link_ops can_link_ops __read_mostly = {
+	.kind		= "can",
+	.maxtype	= IFLA_CAN_MAX,
+	.policy		= can_policy,
+	.setup		= can_setup,
+	.newlink	= can_newlink,
+	.changelink	= can_changelink,
+	.fill_info	= can_fill_info,
+	.fill_xstats	= can_fill_xstats,
+};
+
+/*
+ * Register the CAN network device
+ */
+int register_candev(struct net_device *dev)
+{
+	dev->rtnl_link_ops = &can_link_ops;
+	return register_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(register_candev);
+
+/*
+ * Unregister the CAN network device
+ */
+void unregister_candev(struct net_device *dev)
+{
+	unregister_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_candev);
+
+static __init int can_dev_init(void)
+{
+	int err;
+
+	err = rtnl_link_register(&can_link_ops);
+	if (!err)
+		printk(KERN_INFO MOD_DESC "\n");
+
+	return err;
+}
+module_init(can_dev_init);
+
+static __exit void can_dev_exit(void)
+{
+	rtnl_link_unregister(&can_link_ops);
+}
+module_exit(can_dev_exit);
+
+MODULE_ALIAS_RTNL_LINK("can");
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/Kconfig linux-libre-2.6.31-gnu/drivers/net/can/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/can/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/can/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,68 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called vcan.
 
+config CAN_DEV
+	tristate "Platform CAN drivers with Netlink support"
+	depends on CAN
+	default Y
+	---help---
+	  Enables the common framework for platform CAN drivers with Netlink
+	  support. This is the standard library for CAN drivers.
+	  If unsure, say Y.
+
+config CAN_CALC_BITTIMING
+	bool "CAN bit-timing calculation"
+	depends on CAN_DEV
+	default Y
+	---help---
+	  If enabled, CAN bit-timing parameters will be calculated for the
+	  bit-rate specified via Netlink argument "bitrate" when the device
+	  get started. This works fine for the most common CAN controllers
+	  with standard bit-rates but may fail for exotic bit-rates or CAN
+	  source clock frequencies. Disabling saves some space, but then the
+	  bit-timing parameters must be specified directly using the Netlink
+	  arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
+	  If unsure, say Y.
+
+config CAN_SJA1000
+	depends on CAN_DEV && HAS_IOMEM
+	tristate "Philips SJA1000"
+	---help---
+	  Driver for the SJA1000 CAN controllers from Philips or NXP
+
+config CAN_SJA1000_PLATFORM
+	depends on CAN_SJA1000
+	tristate "Generic Platform Bus based SJA1000 driver"
+	---help---
+	  This driver adds support for the SJA1000 chips connected to
+	  the "platform bus" (Linux abstraction for directly to the
+	  processor attached devices).  Which can be found on various
+	  boards from Phytec (http://www.phytec.de) like the PCM027,
+	  PCM038.
+
+config CAN_SJA1000_OF_PLATFORM
+	depends on CAN_SJA1000 && PPC_OF
+	tristate "Generic OF Platform Bus based SJA1000 driver"
+	---help---
+	  This driver adds support for the SJA1000 chips connected to
+	  the OpenFirmware "platform bus" found on embedded systems with
+	  OpenFirmware bindings, e.g. if you have a PowerPC based system
+	  you may want to enable this option.
+
+config CAN_EMS_PCI
+	tristate "EMS CPC-PCI and CPC-PCIe Card"
+	depends on PCI && CAN_SJA1000
+	---help---
+	  This driver is for the one or two channel CPC-PCI and CPC-PCIe
+	  cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
+config CAN_KVASER_PCI
+	tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
+	depends on PCI && CAN_SJA1000
+	---help---
+	  This driver is for the the PCIcanx and PCIcan cards (1, 2 or
+	  4 channel) from Kvaser (http://www.kvaser.com).
+
 config CAN_DEBUG_DEVICES
 	bool "CAN devices debugging messages"
 	depends on CAN
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/Makefile linux-libre-2.6.31-gnu/drivers/net/can/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/can/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/can/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -3,3 +3,10 @@
 #
 
 obj-$(CONFIG_CAN_VCAN)		+= vcan.o
+
+obj-$(CONFIG_CAN_DEV)		+= can-dev.o
+can-dev-y			:= dev.o
+
+obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
+
+ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/sja1000/ems_pci.c linux-libre-2.6.31-gnu/drivers/net/can/sja1000/ems_pci.c
--- linux-libre-2.6.30-gnu/drivers/net/can/sja1000/ems_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/sja1000/ems_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
+ * Copyright (C) 2008 Markus Plessing <plessing@ems-wuensche.com>
+ * Copyright (C) 2008 Sebastian Haas <haas@ems-wuensche.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/io.h>
+
+#include "sja1000.h"
+
+#define DRV_NAME  "ems_pci"
+
+MODULE_AUTHOR("Sebastian Haas <haas@ems-wuenche.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe CAN cards");
+MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe CAN card");
+MODULE_LICENSE("GPL v2");
+
+#define EMS_PCI_MAX_CHAN 2
+
+struct ems_pci_card {
+	int channels;
+
+	struct pci_dev *pci_dev;
+	struct net_device *net_dev[EMS_PCI_MAX_CHAN];
+
+	void __iomem *conf_addr;
+	void __iomem *base_addr;
+};
+
+#define EMS_PCI_CAN_CLOCK (16000000 / 2)
+
+/*
+ * Register definitions and descriptions are from LinCAN 0.3.3.
+ *
+ * PSB4610 PITA-2 bridge control registers
+ */
+#define PITA2_ICR           0x00	/* Interrupt Control Register */
+#define PITA2_ICR_INT0      0x00000002	/* [RC] INT0 Active/Clear */
+#define PITA2_ICR_INT0_EN   0x00020000	/* [RW] Enable INT0 */
+
+#define PITA2_MISC          0x1c	/* Miscellaneous Register */
+#define PITA2_MISC_CONFIG   0x04000000	/* Multiplexed parallel interface */
+
+/*
+ * The board configuration is probably following:
+ * RX1 is connected to ground.
+ * TX1 is not connected.
+ * CLKO is not connected.
+ * Setting the OCR register to 0xDA is a good idea.
+ * This means  normal output mode , push-pull and the correct polarity.
+ */
+#define EMS_PCI_OCR         (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
+
+/*
+ * In the CDR register, you should set CBP to 1.
+ * You will probably also want to set the clock divider value to 7
+ * (meaning direct oscillator output) because the second SJA1000 chip
+ * is driven by the first one CLKOUT output.
+ */
+#define EMS_PCI_CDR             (CDR_CBP | CDR_CLKOUT_MASK)
+#define EMS_PCI_MEM_SIZE        4096  /* Size of the remapped io-memory */
+#define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
+#define EMS_PCI_CAN_CTRL_SIZE   0x200 /* memory size for each controller */
+
+#define EMS_PCI_PORT_BYTES  0x4     /* Each register occupies 4 bytes */
+
+#define EMS_PCI_VENDOR_ID   0x110a  /* PCI device and vendor ID */
+#define EMS_PCI_DEVICE_ID   0x2104
+
+static struct pci_device_id ems_pci_tbl[] = {
+	{EMS_PCI_VENDOR_ID, EMS_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{0,}
+};
+MODULE_DEVICE_TABLE(pci, ems_pci_tbl);
+
+/*
+ * Helper to read internal registers from card logic (not CAN)
+ */
+static u8 ems_pci_readb(struct ems_pci_card *card, unsigned int port)
+{
+	return readb(card->base_addr + (port * EMS_PCI_PORT_BYTES));
+}
+
+static u8 ems_pci_read_reg(const struct sja1000_priv *priv, int port)
+{
+	return readb(priv->reg_base + (port * EMS_PCI_PORT_BYTES));
+}
+
+static void ems_pci_write_reg(const struct sja1000_priv *priv, int port, u8 val)
+{
+	writeb(val, priv->reg_base + (port * EMS_PCI_PORT_BYTES));
+}
+
+static void ems_pci_post_irq(const struct sja1000_priv *priv)
+{
+	struct ems_pci_card *card = (struct ems_pci_card *)priv->priv;
+
+	/* reset int flag of pita */
+	writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, card->conf_addr
+		+ PITA2_ICR);
+}
+
+/*
+ * Check if a CAN controller is present at the specified location
+ * by trying to set 'em into the PeliCAN mode
+ */
+static inline int ems_pci_check_chan(const struct sja1000_priv *priv)
+{
+	unsigned char res;
+
+	/* Make sure SJA1000 is in reset mode */
+	ems_pci_write_reg(priv, REG_MOD, 1);
+
+	ems_pci_write_reg(priv, REG_CDR, CDR_PELICAN);
+
+	/* read reset-values */
+	res = ems_pci_read_reg(priv, REG_CDR);
+
+	if (res == CDR_PELICAN)
+		return 1;
+
+	return 0;
+}
+
+static void ems_pci_del_card(struct pci_dev *pdev)
+{
+	struct ems_pci_card *card = pci_get_drvdata(pdev);
+	struct net_device *dev;
+	int i = 0;
+
+	for (i = 0; i < card->channels; i++) {
+		dev = card->net_dev[i];
+
+		if (!dev)
+			continue;
+
+		dev_info(&pdev->dev, "Removing %s.\n", dev->name);
+		unregister_sja1000dev(dev);
+		free_sja1000dev(dev);
+	}
+
+	if (card->base_addr != NULL)
+		pci_iounmap(card->pci_dev, card->base_addr);
+
+	if (card->conf_addr != NULL)
+		pci_iounmap(card->pci_dev, card->conf_addr);
+
+	kfree(card);
+
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+static void ems_pci_card_reset(struct ems_pci_card *card)
+{
+	/* Request board reset */
+	writeb(0, card->base_addr);
+}
+
+/*
+ * Probe PCI device for EMS CAN signature and register each available
+ * CAN channel to SJA1000 Socket-CAN subsystem.
+ */
+static int __devinit ems_pci_add_card(struct pci_dev *pdev,
+					const struct pci_device_id *ent)
+{
+	struct sja1000_priv *priv;
+	struct net_device *dev;
+	struct ems_pci_card *card;
+	int err, i;
+
+	/* Enabling PCI device */
+	if (pci_enable_device(pdev) < 0) {
+		dev_err(&pdev->dev, "Enabling PCI device failed\n");
+		return -ENODEV;
+	}
+
+	/* Allocating card structures to hold addresses, ... */
+	card = kzalloc(sizeof(struct ems_pci_card), GFP_KERNEL);
+	if (card == NULL) {
+		dev_err(&pdev->dev, "Unable to allocate memory\n");
+		pci_disable_device(pdev);
+		return -ENOMEM;
+	}
+
+	pci_set_drvdata(pdev, card);
+
+	card->pci_dev = pdev;
+
+	card->channels = 0;
+
+	/* Remap PITA configuration space, and controller memory area */
+	card->conf_addr = pci_iomap(pdev, 0, EMS_PCI_MEM_SIZE);
+	if (card->conf_addr == NULL) {
+		err = -ENOMEM;
+		goto failure_cleanup;
+	}
+
+	card->base_addr = pci_iomap(pdev, 1, EMS_PCI_MEM_SIZE);
+	if (card->base_addr == NULL) {
+		err = -ENOMEM;
+		goto failure_cleanup;
+	}
+
+	/* Configure PITA-2 parallel interface (enable MUX) */
+	writel(PITA2_MISC_CONFIG, card->conf_addr + PITA2_MISC);
+
+	/* Check for unique EMS CAN signature */
+	if (ems_pci_readb(card, 0) != 0x55 ||
+	    ems_pci_readb(card, 1) != 0xAA ||
+	    ems_pci_readb(card, 2) != 0x01 ||
+	    ems_pci_readb(card, 3) != 0xCB ||
+	    ems_pci_readb(card, 4) != 0x11) {
+		dev_err(&pdev->dev, "Not EMS Dr. Thomas Wuensche interface\n");
+		err = -ENODEV;
+		goto failure_cleanup;
+	}
+
+	ems_pci_card_reset(card);
+
+	/* Detect available channels */
+	for (i = 0; i < EMS_PCI_MAX_CHAN; i++) {
+		dev = alloc_sja1000dev(0);
+		if (dev == NULL) {
+			err = -ENOMEM;
+			goto failure_cleanup;
+		}
+
+		card->net_dev[i] = dev;
+		priv = netdev_priv(dev);
+		priv->priv = card;
+		priv->irq_flags = IRQF_SHARED;
+
+		dev->irq = pdev->irq;
+		priv->reg_base = card->base_addr + EMS_PCI_CAN_BASE_OFFSET
+					+ (i * EMS_PCI_CAN_CTRL_SIZE);
+
+		/* Check if channel is present */
+		if (ems_pci_check_chan(priv)) {
+			priv->read_reg  = ems_pci_read_reg;
+			priv->write_reg = ems_pci_write_reg;
+			priv->post_irq  = ems_pci_post_irq;
+			priv->can.clock.freq = EMS_PCI_CAN_CLOCK;
+			priv->ocr = EMS_PCI_OCR;
+			priv->cdr = EMS_PCI_CDR;
+
+			SET_NETDEV_DEV(dev, &pdev->dev);
+
+			/* Enable interrupts from card */
+			writel(PITA2_ICR_INT0_EN, card->conf_addr + PITA2_ICR);
+
+			/* Register SJA1000 device */
+			err = register_sja1000dev(dev);
+			if (err) {
+				dev_err(&pdev->dev, "Registering device failed "
+							"(err=%d)\n", err);
+				free_sja1000dev(dev);
+				goto failure_cleanup;
+			}
+
+			card->channels++;
+
+			dev_info(&pdev->dev, "Channel #%d at 0x%p, irq %d\n",
+					i + 1, priv->reg_base, dev->irq);
+		} else {
+			free_sja1000dev(dev);
+		}
+	}
+
+	return 0;
+
+failure_cleanup:
+	dev_err(&pdev->dev, "Error: %d. Cleaning Up.\n", err);
+
+	ems_pci_del_card(pdev);
+
+	return err;
+}
+
+static struct pci_driver ems_pci_driver = {
+	.name = DRV_NAME,
+	.id_table = ems_pci_tbl,
+	.probe = ems_pci_add_card,
+	.remove = ems_pci_del_card,
+};
+
+static int __init ems_pci_init(void)
+{
+	return pci_register_driver(&ems_pci_driver);
+}
+
+static void __exit ems_pci_exit(void)
+{
+	pci_unregister_driver(&ems_pci_driver);
+}
+
+module_init(ems_pci_init);
+module_exit(ems_pci_exit);
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/sja1000/kvaser_pci.c linux-libre-2.6.31-gnu/drivers/net/can/sja1000/kvaser_pci.c
--- linux-libre-2.6.30-gnu/drivers/net/can/sja1000/kvaser_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/sja1000/kvaser_pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2008 Per Dalen <per.dalen@cnw.se>
+ *
+ * Parts of this software are based on (derived) the following:
+ *
+ * - Kvaser linux driver, version 4.72 BETA
+ *   Copyright (C) 2002-2007 KVASER AB
+ *
+ * - Lincan driver, version 0.3.3, OCERA project
+ *   Copyright (C) 2004 Pavel Pisa
+ *   Copyright (C) 2001 Arnaud Westenberg
+ *
+ * - Socketcan SJA1000 drivers
+ *   Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
+ *   Copyright (c) 2002-2007 Volkswagen Group Electronic Research
+ *   Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
+ *   38106 Braunschweig, GERMANY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/io.h>
+
+#include "sja1000.h"
+
+#define DRV_NAME  "kvaser_pci"
+
+MODULE_AUTHOR("Per Dalen <per.dalen@cnw.se>");
+MODULE_DESCRIPTION("Socket-CAN driver for KVASER PCAN PCI cards");
+MODULE_SUPPORTED_DEVICE("KVASER PCAN PCI CAN card");
+MODULE_LICENSE("GPL v2");
+
+#define MAX_NO_OF_CHANNELS        4 /* max no of channels on a single card */
+
+struct kvaser_pci {
+	int channel;
+	struct pci_dev *pci_dev;
+	struct net_device *slave_dev[MAX_NO_OF_CHANNELS-1];
+	void __iomem *conf_addr;
+	void __iomem *res_addr;
+	int no_channels;
+	u8 xilinx_ver;
+};
+
+#define KVASER_PCI_CAN_CLOCK      (16000000 / 2)
+
+/*
+ * The board configuration is probably following:
+ * RX1 is connected to ground.
+ * TX1 is not connected.
+ * CLKO is not connected.
+ * Setting the OCR register to 0xDA is a good idea.
+ * This means  normal output mode , push-pull and the correct polarity.
+ */
+#define KVASER_PCI_OCR            (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
+
+/*
+ * In the CDR register, you should set CBP to 1.
+ * You will probably also want to set the clock divider value to 0
+ * (meaning divide-by-2), the Pelican bit, and the clock-off bit
+ * (you will have no need for CLKOUT anyway).
+ */
+#define KVASER_PCI_CDR            (CDR_CBP | CDR_CLKOUT_MASK)
+
+/*
+ * These register values are valid for revision 14 of the Xilinx logic.
+ */
+#define XILINX_VERINT             7   /* Lower nibble simulate interrupts,
+					 high nibble version number. */
+
+#define XILINX_PRESUMED_VERSION   14
+
+/*
+ * Important S5920 registers
+ */
+#define S5920_INTCSR              0x38
+#define S5920_PTCR                0x60
+#define INTCSR_ADDON_INTENABLE_M  0x2000
+
+
+#define KVASER_PCI_PORT_BYTES     0x20
+
+#define PCI_CONFIG_PORT_SIZE      0x80      /* size of the config io-memory */
+#define PCI_PORT_SIZE             0x80      /* size of a channel io-memory */
+#define PCI_PORT_XILINX_SIZE      0x08      /* size of a xilinx io-memory */
+
+#define KVASER_PCI_VENDOR_ID1     0x10e8    /* the PCI device and vendor IDs */
+#define KVASER_PCI_DEVICE_ID1     0x8406
+
+#define KVASER_PCI_VENDOR_ID2     0x1a07    /* the PCI device and vendor IDs */
+#define KVASER_PCI_DEVICE_ID2     0x0008
+
+static struct pci_device_id kvaser_pci_tbl[] = {
+	{KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,},
+	{KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,},
+	{ 0,}
+};
+
+MODULE_DEVICE_TABLE(pci, kvaser_pci_tbl);
+
+static u8 kvaser_pci_read_reg(const struct sja1000_priv *priv, int port)
+{
+	return ioread8(priv->reg_base + port);
+}
+
+static void kvaser_pci_write_reg(const struct sja1000_priv *priv,
+				 int port, u8 val)
+{
+	iowrite8(val, priv->reg_base + port);
+}
+
+static void kvaser_pci_disable_irq(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct kvaser_pci *board = priv->priv;
+	u32 intcsr;
+
+	/* Disable interrupts from card */
+	intcsr = ioread32(board->conf_addr + S5920_INTCSR);
+	intcsr &= ~INTCSR_ADDON_INTENABLE_M;
+	iowrite32(intcsr, board->conf_addr + S5920_INTCSR);
+}
+
+static void kvaser_pci_enable_irq(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct kvaser_pci *board = priv->priv;
+	u32 tmp_en_io;
+
+	/* Enable interrupts from card */
+	tmp_en_io = ioread32(board->conf_addr + S5920_INTCSR);
+	tmp_en_io |= INTCSR_ADDON_INTENABLE_M;
+	iowrite32(tmp_en_io, board->conf_addr + S5920_INTCSR);
+}
+
+static int number_of_sja1000_chip(void __iomem *base_addr)
+{
+	u8 status;
+	int i;
+
+	for (i = 0; i < MAX_NO_OF_CHANNELS; i++) {
+		/* reset chip */
+		iowrite8(MOD_RM, base_addr +
+			 (i * KVASER_PCI_PORT_BYTES) + REG_MOD);
+		status = ioread8(base_addr +
+				 (i * KVASER_PCI_PORT_BYTES) + REG_MOD);
+		/* check reset bit */
+		if (!(status & MOD_RM))
+			break;
+	}
+
+	return i;
+}
+
+static void kvaser_pci_del_chan(struct net_device *dev)
+{
+	struct sja1000_priv *priv;
+	struct kvaser_pci *board;
+	int i;
+
+	if (!dev)
+		return;
+	priv = netdev_priv(dev);
+	board = priv->priv;
+	if (!board)
+		return;
+
+	dev_info(&board->pci_dev->dev, "Removing device %s\n",
+		 dev->name);
+
+	/* Disable PCI interrupts */
+	kvaser_pci_disable_irq(dev);
+
+	for (i = 0; i < board->no_channels - 1; i++) {
+		if (board->slave_dev[i]) {
+			dev_info(&board->pci_dev->dev, "Removing device %s\n",
+				 board->slave_dev[i]->name);
+			unregister_sja1000dev(board->slave_dev[i]);
+			free_sja1000dev(board->slave_dev[i]);
+		}
+	}
+	unregister_sja1000dev(dev);
+
+	pci_iounmap(board->pci_dev, priv->reg_base);
+	pci_iounmap(board->pci_dev, board->conf_addr);
+	pci_iounmap(board->pci_dev, board->res_addr);
+
+	free_sja1000dev(dev);
+}
+
+static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
+			       struct net_device **master_dev,
+			       void __iomem *conf_addr,
+			       void __iomem *res_addr,
+			       void __iomem *base_addr)
+{
+	struct net_device *dev;
+	struct sja1000_priv *priv;
+	struct kvaser_pci *board;
+	int err, init_step;
+
+	dev = alloc_sja1000dev(sizeof(struct kvaser_pci));
+	if (dev == NULL)
+		return -ENOMEM;
+
+	priv = netdev_priv(dev);
+	board = priv->priv;
+
+	board->pci_dev = pdev;
+	board->channel = channel;
+
+	/* S5920 */
+	board->conf_addr = conf_addr;
+
+	/* XILINX board wide address */
+	board->res_addr = res_addr;
+
+	if (channel == 0) {
+		board->xilinx_ver =
+			ioread8(board->res_addr + XILINX_VERINT) >> 4;
+		init_step = 2;
+
+		/* Assert PTADR# - we're in passive mode so the other bits are
+		   not important */
+		iowrite32(0x80808080UL, board->conf_addr + S5920_PTCR);
+
+		/* Enable interrupts from card */
+		kvaser_pci_enable_irq(dev);
+	} else {
+		struct sja1000_priv *master_priv = netdev_priv(*master_dev);
+		struct kvaser_pci *master_board = master_priv->priv;
+		master_board->slave_dev[channel - 1] = dev;
+		master_board->no_channels = channel + 1;
+		board->xilinx_ver = master_board->xilinx_ver;
+	}
+
+	priv->reg_base = base_addr + channel * KVASER_PCI_PORT_BYTES;
+
+	priv->read_reg = kvaser_pci_read_reg;
+	priv->write_reg = kvaser_pci_write_reg;
+
+	priv->can.clock.freq = KVASER_PCI_CAN_CLOCK;
+
+	priv->ocr = KVASER_PCI_OCR;
+	priv->cdr = KVASER_PCI_CDR;
+
+	priv->irq_flags = IRQF_SHARED;
+	dev->irq = pdev->irq;
+
+	init_step = 4;
+
+	dev_info(&pdev->dev, "reg_base=%p conf_addr=%p irq=%d\n",
+		 priv->reg_base, board->conf_addr, dev->irq);
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	/* Register SJA1000 device */
+	err = register_sja1000dev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "Registering device failed (err=%d)\n",
+			err);
+		goto failure;
+	}
+
+	if (channel == 0)
+		*master_dev = dev;
+
+	return 0;
+
+failure:
+	kvaser_pci_del_chan(dev);
+	return err;
+}
+
+static int __devinit kvaser_pci_init_one(struct pci_dev *pdev,
+					 const struct pci_device_id *ent)
+{
+	int err;
+	struct net_device *master_dev = NULL;
+	struct sja1000_priv *priv;
+	struct kvaser_pci *board;
+	int no_channels;
+	void __iomem *base_addr = NULL;
+	void __iomem *conf_addr = NULL;
+	void __iomem *res_addr = NULL;
+	int i;
+
+	dev_info(&pdev->dev, "initializing device %04x:%04x\n",
+		 pdev->vendor, pdev->device);
+
+	err = pci_enable_device(pdev);
+	if (err)
+		goto failure;
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err)
+		goto failure_release_pci;
+
+	/* S5920 */
+	conf_addr = pci_iomap(pdev, 0, PCI_CONFIG_PORT_SIZE);
+	if (conf_addr == NULL) {
+		err = -ENODEV;
+		goto failure_release_regions;
+	}
+
+	/* XILINX board wide address */
+	res_addr = pci_iomap(pdev, 2, PCI_PORT_XILINX_SIZE);
+	if (res_addr == NULL) {
+		err = -ENOMEM;
+		goto failure_iounmap;
+	}
+
+	base_addr = pci_iomap(pdev, 1, PCI_PORT_SIZE);
+	if (base_addr == NULL) {
+		err = -ENOMEM;
+		goto failure_iounmap;
+	}
+
+	no_channels = number_of_sja1000_chip(base_addr);
+	if (no_channels == 0) {
+		err = -ENOMEM;
+		goto failure_iounmap;
+	}
+
+	for (i = 0; i < no_channels; i++) {
+		err = kvaser_pci_add_chan(pdev, i, &master_dev,
+					  conf_addr, res_addr,
+					  base_addr);
+		if (err)
+			goto failure_cleanup;
+	}
+
+	priv = netdev_priv(master_dev);
+	board = priv->priv;
+
+	dev_info(&pdev->dev, "xilinx version=%d number of channels=%d\n",
+		 board->xilinx_ver, board->no_channels);
+
+	pci_set_drvdata(pdev, master_dev);
+	return 0;
+
+failure_cleanup:
+	kvaser_pci_del_chan(master_dev);
+
+failure_iounmap:
+	if (conf_addr != NULL)
+		pci_iounmap(pdev, conf_addr);
+	if (res_addr != NULL)
+		pci_iounmap(pdev, res_addr);
+	if (base_addr != NULL)
+		pci_iounmap(pdev, base_addr);
+
+failure_release_regions:
+	pci_release_regions(pdev);
+
+failure_release_pci:
+	pci_disable_device(pdev);
+
+failure:
+	return err;
+
+}
+
+static void __devexit kvaser_pci_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	kvaser_pci_del_chan(dev);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver kvaser_pci_driver = {
+	.name = DRV_NAME,
+	.id_table = kvaser_pci_tbl,
+	.probe = kvaser_pci_init_one,
+	.remove = __devexit_p(kvaser_pci_remove_one),
+};
+
+static int __init kvaser_pci_init(void)
+{
+	return pci_register_driver(&kvaser_pci_driver);
+}
+
+static void __exit kvaser_pci_exit(void)
+{
+	pci_unregister_driver(&kvaser_pci_driver);
+}
+
+module_init(kvaser_pci_init);
+module_exit(kvaser_pci_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/sja1000/Makefile linux-libre-2.6.31-gnu/drivers/net/can/sja1000/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/can/sja1000/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/sja1000/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,11 @@
+#
+#  Makefile for the SJA1000 CAN controller drivers.
+#
+
+obj-$(CONFIG_CAN_SJA1000) += sja1000.o
+obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
+obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
+obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
+obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
+
+ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000.c linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000.c
--- linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,636 @@
+/*
+ * sja1000.c -  Philips SJA1000 network device driver
+ *
+ * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
+ * 38106 Braunschweig, GERMANY
+ *
+ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Volkswagen nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * The provided data structures and external interfaces from this code
+ * are not restricted to be used by modules with a GPL compatible license.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#include "sja1000.h"
+
+#define DRV_NAME "sja1000"
+
+MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver");
+
+static struct can_bittiming_const sja1000_bittiming_const = {
+	.name = DRV_NAME,
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 64,
+	.brp_inc = 1,
+};
+
+static int sja1000_probe_chip(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+
+	if (priv->reg_base && (priv->read_reg(priv, 0) == 0xFF)) {
+		printk(KERN_INFO "%s: probing @0x%lX failed\n",
+		       DRV_NAME, dev->base_addr);
+		return 0;
+	}
+	return -1;
+}
+
+static void set_reset_mode(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	unsigned char status = priv->read_reg(priv, REG_MOD);
+	int i;
+
+	/* disable interrupts */
+	priv->write_reg(priv, REG_IER, IRQ_OFF);
+
+	for (i = 0; i < 100; i++) {
+		/* check reset bit */
+		if (status & MOD_RM) {
+			priv->can.state = CAN_STATE_STOPPED;
+			return;
+		}
+
+		priv->write_reg(priv, REG_MOD, MOD_RM);	/* reset chip */
+		udelay(10);
+		status = priv->read_reg(priv, REG_MOD);
+	}
+
+	dev_err(dev->dev.parent, "setting SJA1000 into reset mode failed!\n");
+}
+
+static void set_normal_mode(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	unsigned char status = priv->read_reg(priv, REG_MOD);
+	int i;
+
+	for (i = 0; i < 100; i++) {
+		/* check reset bit */
+		if ((status & MOD_RM) == 0) {
+			priv->can.state = CAN_STATE_ERROR_ACTIVE;
+			/* enable all interrupts */
+			priv->write_reg(priv, REG_IER, IRQ_ALL);
+			return;
+		}
+
+		/* set chip to normal mode */
+		priv->write_reg(priv, REG_MOD, 0x00);
+		udelay(10);
+		status = priv->read_reg(priv, REG_MOD);
+	}
+
+	dev_err(dev->dev.parent, "setting SJA1000 into normal mode failed!\n");
+}
+
+static void sja1000_start(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+
+	/* leave reset mode */
+	if (priv->can.state != CAN_STATE_STOPPED)
+		set_reset_mode(dev);
+
+	/* Clear error counters and error code capture */
+	priv->write_reg(priv, REG_TXERR, 0x0);
+	priv->write_reg(priv, REG_RXERR, 0x0);
+	priv->read_reg(priv, REG_ECC);
+
+	/* leave reset mode */
+	set_normal_mode(dev);
+}
+
+static int sja1000_set_mode(struct net_device *dev, enum can_mode mode)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+
+	if (!priv->open_time)
+		return -EINVAL;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		sja1000_start(dev);
+		if (netif_queue_stopped(dev))
+			netif_wake_queue(dev);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int sja1000_set_bittiming(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	u8 btr0, btr1;
+
+	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
+	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
+		(((bt->phase_seg2 - 1) & 0x7) << 4);
+	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+		btr1 |= 0x80;
+
+	dev_info(dev->dev.parent,
+		 "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
+
+	priv->write_reg(priv, REG_BTR0, btr0);
+	priv->write_reg(priv, REG_BTR1, btr1);
+
+	return 0;
+}
+
+/*
+ * initialize SJA1000 chip:
+ *   - reset chip
+ *   - set output mode
+ *   - set baudrate
+ *   - enable interrupts
+ *   - start operating mode
+ */
+static void chipset_init(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+
+	/* set clock divider and output control register */
+	priv->write_reg(priv, REG_CDR, priv->cdr | CDR_PELICAN);
+
+	/* set acceptance filter (accept all) */
+	priv->write_reg(priv, REG_ACCC0, 0x00);
+	priv->write_reg(priv, REG_ACCC1, 0x00);
+	priv->write_reg(priv, REG_ACCC2, 0x00);
+	priv->write_reg(priv, REG_ACCC3, 0x00);
+
+	priv->write_reg(priv, REG_ACCM0, 0xFF);
+	priv->write_reg(priv, REG_ACCM1, 0xFF);
+	priv->write_reg(priv, REG_ACCM2, 0xFF);
+	priv->write_reg(priv, REG_ACCM3, 0xFF);
+
+	priv->write_reg(priv, REG_OCR, priv->ocr | OCR_MODE_NORMAL);
+}
+
+/*
+ * transmit a CAN message
+ * message layout in the sk_buff should be like this:
+ * xx xx xx xx	 ff	 ll   00 11 22 33 44 55 66 77
+ * [  can-id ] [flags] [len] [can data (up to 8 bytes]
+ */
+static int sja1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	uint8_t fi;
+	uint8_t dlc;
+	canid_t id;
+	uint8_t dreg;
+	int i;
+
+	netif_stop_queue(dev);
+
+	fi = dlc = cf->can_dlc;
+	id = cf->can_id;
+
+	if (id & CAN_RTR_FLAG)
+		fi |= FI_RTR;
+
+	if (id & CAN_EFF_FLAG) {
+		fi |= FI_FF;
+		dreg = EFF_BUF;
+		priv->write_reg(priv, REG_FI, fi);
+		priv->write_reg(priv, REG_ID1, (id & 0x1fe00000) >> (5 + 16));
+		priv->write_reg(priv, REG_ID2, (id & 0x001fe000) >> (5 + 8));
+		priv->write_reg(priv, REG_ID3, (id & 0x00001fe0) >> 5);
+		priv->write_reg(priv, REG_ID4, (id & 0x0000001f) << 3);
+	} else {
+		dreg = SFF_BUF;
+		priv->write_reg(priv, REG_FI, fi);
+		priv->write_reg(priv, REG_ID1, (id & 0x000007f8) >> 3);
+		priv->write_reg(priv, REG_ID2, (id & 0x00000007) << 5);
+	}
+
+	for (i = 0; i < dlc; i++)
+		priv->write_reg(priv, dreg++, cf->data[i]);
+
+	stats->tx_bytes += dlc;
+	dev->trans_start = jiffies;
+
+	can_put_echo_skb(skb, dev, 0);
+
+	priv->write_reg(priv, REG_CMR, CMD_TR);
+
+	return 0;
+}
+
+static void sja1000_rx(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	uint8_t fi;
+	uint8_t dreg;
+	canid_t id;
+	uint8_t dlc;
+	int i;
+
+	skb = dev_alloc_skb(sizeof(struct can_frame));
+	if (skb == NULL)
+		return;
+	skb->dev = dev;
+	skb->protocol = htons(ETH_P_CAN);
+
+	fi = priv->read_reg(priv, REG_FI);
+	dlc = fi & 0x0F;
+
+	if (fi & FI_FF) {
+		/* extended frame format (EFF) */
+		dreg = EFF_BUF;
+		id = (priv->read_reg(priv, REG_ID1) << (5 + 16))
+		    | (priv->read_reg(priv, REG_ID2) << (5 + 8))
+		    | (priv->read_reg(priv, REG_ID3) << 5)
+		    | (priv->read_reg(priv, REG_ID4) >> 3);
+		id |= CAN_EFF_FLAG;
+	} else {
+		/* standard frame format (SFF) */
+		dreg = SFF_BUF;
+		id = (priv->read_reg(priv, REG_ID1) << 3)
+		    | (priv->read_reg(priv, REG_ID2) >> 5);
+	}
+
+	if (fi & FI_RTR)
+		id |= CAN_RTR_FLAG;
+
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+	memset(cf, 0, sizeof(struct can_frame));
+	cf->can_id = id;
+	cf->can_dlc = dlc;
+	for (i = 0; i < dlc; i++)
+		cf->data[i] = priv->read_reg(priv, dreg++);
+
+	while (i < 8)
+		cf->data[i++] = 0;
+
+	/* release receive buffer */
+	priv->write_reg(priv, REG_CMR, CMD_RRB);
+
+	netif_rx(skb);
+
+	dev->last_rx = jiffies;
+	stats->rx_packets++;
+	stats->rx_bytes += dlc;
+}
+
+static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	enum can_state state = priv->can.state;
+	uint8_t ecc, alc;
+
+	skb = dev_alloc_skb(sizeof(struct can_frame));
+	if (skb == NULL)
+		return -ENOMEM;
+	skb->dev = dev;
+	skb->protocol = htons(ETH_P_CAN);
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+	memset(cf, 0, sizeof(struct can_frame));
+	cf->can_id = CAN_ERR_FLAG;
+	cf->can_dlc = CAN_ERR_DLC;
+
+	if (isrc & IRQ_DOI) {
+		/* data overrun interrupt */
+		dev_dbg(dev->dev.parent, "data overrun interrupt\n");
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+		stats->rx_over_errors++;
+		stats->rx_errors++;
+		priv->write_reg(priv, REG_CMR, CMD_CDO);	/* clear bit */
+	}
+
+	if (isrc & IRQ_EI) {
+		/* error warning interrupt */
+		dev_dbg(dev->dev.parent, "error warning interrupt\n");
+
+		if (status & SR_BS) {
+			state = CAN_STATE_BUS_OFF;
+			cf->can_id |= CAN_ERR_BUSOFF;
+			can_bus_off(dev);
+		} else if (status & SR_ES) {
+			state = CAN_STATE_ERROR_WARNING;
+		} else
+			state = CAN_STATE_ERROR_ACTIVE;
+	}
+	if (isrc & IRQ_BEI) {
+		/* bus error interrupt */
+		priv->can.can_stats.bus_error++;
+		stats->rx_errors++;
+
+		ecc = priv->read_reg(priv, REG_ECC);
+
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+		switch (ecc & ECC_MASK) {
+		case ECC_BIT:
+			cf->data[2] |= CAN_ERR_PROT_BIT;
+			break;
+		case ECC_FORM:
+			cf->data[2] |= CAN_ERR_PROT_FORM;
+			break;
+		case ECC_STUFF:
+			cf->data[2] |= CAN_ERR_PROT_STUFF;
+			break;
+		default:
+			cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+			cf->data[3] = ecc & ECC_SEG;
+			break;
+		}
+		/* Error occured during transmission? */
+		if ((ecc & ECC_DIR) == 0)
+			cf->data[2] |= CAN_ERR_PROT_TX;
+	}
+	if (isrc & IRQ_EPI) {
+		/* error passive interrupt */
+		dev_dbg(dev->dev.parent, "error passive interrupt\n");
+		if (status & SR_ES)
+			state = CAN_STATE_ERROR_PASSIVE;
+		else
+			state = CAN_STATE_ERROR_ACTIVE;
+	}
+	if (isrc & IRQ_ALI) {
+		/* arbitration lost interrupt */
+		dev_dbg(dev->dev.parent, "arbitration lost interrupt\n");
+		alc = priv->read_reg(priv, REG_ALC);
+		priv->can.can_stats.arbitration_lost++;
+		stats->rx_errors++;
+		cf->can_id |= CAN_ERR_LOSTARB;
+		cf->data[0] = alc & 0x1f;
+	}
+
+	if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
+					 state == CAN_STATE_ERROR_PASSIVE)) {
+		uint8_t rxerr = priv->read_reg(priv, REG_RXERR);
+		uint8_t txerr = priv->read_reg(priv, REG_TXERR);
+		cf->can_id |= CAN_ERR_CRTL;
+		if (state == CAN_STATE_ERROR_WARNING) {
+			priv->can.can_stats.error_warning++;
+			cf->data[1] = (txerr > rxerr) ?
+				CAN_ERR_CRTL_TX_WARNING :
+				CAN_ERR_CRTL_RX_WARNING;
+		} else {
+			priv->can.can_stats.error_passive++;
+			cf->data[1] = (txerr > rxerr) ?
+				CAN_ERR_CRTL_TX_PASSIVE :
+				CAN_ERR_CRTL_RX_PASSIVE;
+		}
+	}
+
+	priv->can.state = state;
+
+	netif_rx(skb);
+
+	dev->last_rx = jiffies;
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	return 0;
+}
+
+irqreturn_t sja1000_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	uint8_t isrc, status;
+	int n = 0;
+
+	/* Shared interrupts and IRQ off? */
+	if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
+		return IRQ_NONE;
+
+	if (priv->pre_irq)
+		priv->pre_irq(priv);
+
+	while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
+		n++;
+		status = priv->read_reg(priv, REG_SR);
+
+		if (isrc & IRQ_WUI)
+			dev_warn(dev->dev.parent, "wakeup interrupt\n");
+
+		if (isrc & IRQ_TI) {
+			/* transmission complete interrupt */
+			stats->tx_packets++;
+			can_get_echo_skb(dev, 0);
+			netif_wake_queue(dev);
+		}
+		if (isrc & IRQ_RI) {
+			/* receive interrupt */
+			while (status & SR_RBS) {
+				sja1000_rx(dev);
+				status = priv->read_reg(priv, REG_SR);
+			}
+		}
+		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
+			/* error interrupt */
+			if (sja1000_err(dev, isrc, status))
+				break;
+		}
+	}
+
+	if (priv->post_irq)
+		priv->post_irq(priv);
+
+	if (n >= SJA1000_MAX_IRQ)
+		dev_dbg(dev->dev.parent, "%d messages handled in ISR", n);
+
+	return (n) ? IRQ_HANDLED : IRQ_NONE;
+}
+EXPORT_SYMBOL_GPL(sja1000_interrupt);
+
+static int sja1000_open(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+	int err;
+
+	/* set chip into reset mode */
+	set_reset_mode(dev);
+
+	/* common open */
+	err = open_candev(dev);
+	if (err)
+		return err;
+
+	/* register interrupt handler, if not done by the device driver */
+	if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) {
+		err = request_irq(dev->irq, &sja1000_interrupt, priv->irq_flags,
+				  dev->name, (void *)dev);
+		if (err) {
+			close_candev(dev);
+			return -EAGAIN;
+		}
+	}
+
+	/* init and start chi */
+	sja1000_start(dev);
+	priv->open_time = jiffies;
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int sja1000_close(struct net_device *dev)
+{
+	struct sja1000_priv *priv = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	set_reset_mode(dev);
+
+	if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER))
+		free_irq(dev->irq, (void *)dev);
+
+	close_candev(dev);
+
+	priv->open_time = 0;
+
+	return 0;
+}
+
+struct net_device *alloc_sja1000dev(int sizeof_priv)
+{
+	struct net_device *dev;
+	struct sja1000_priv *priv;
+
+	dev = alloc_candev(sizeof(struct sja1000_priv) + sizeof_priv);
+	if (!dev)
+		return NULL;
+
+	priv = netdev_priv(dev);
+
+	priv->dev = dev;
+	priv->can.bittiming_const = &sja1000_bittiming_const;
+	priv->can.do_set_bittiming = sja1000_set_bittiming;
+	priv->can.do_set_mode = sja1000_set_mode;
+
+	if (sizeof_priv)
+		priv->priv = (void *)priv + sizeof(struct sja1000_priv);
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_sja1000dev);
+
+void free_sja1000dev(struct net_device *dev)
+{
+	free_candev(dev);
+}
+EXPORT_SYMBOL_GPL(free_sja1000dev);
+
+static const struct net_device_ops sja1000_netdev_ops = {
+       .ndo_open               = sja1000_open,
+       .ndo_stop               = sja1000_close,
+       .ndo_start_xmit         = sja1000_start_xmit,
+};
+
+int register_sja1000dev(struct net_device *dev)
+{
+	if (!sja1000_probe_chip(dev))
+		return -ENODEV;
+
+	dev->flags |= IFF_ECHO;	/* we support local echo */
+	dev->netdev_ops = &sja1000_netdev_ops;
+
+	set_reset_mode(dev);
+	chipset_init(dev);
+
+	return register_candev(dev);
+}
+EXPORT_SYMBOL_GPL(register_sja1000dev);
+
+void unregister_sja1000dev(struct net_device *dev)
+{
+	set_reset_mode(dev);
+	unregister_candev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_sja1000dev);
+
+static __init int sja1000_init(void)
+{
+	printk(KERN_INFO "%s CAN netdevice driver\n", DRV_NAME);
+
+	return 0;
+}
+
+module_init(sja1000_init);
+
+static __exit void sja1000_exit(void)
+{
+	printk(KERN_INFO "%s: driver removed\n", DRV_NAME);
+}
+
+module_exit(sja1000_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000.h linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000.h
--- linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,181 @@
+/*
+ * sja1000.h -  Philips SJA1000 network device driver
+ *
+ * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
+ * 38106 Braunschweig, GERMANY
+ *
+ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Volkswagen nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * The provided data structures and external interfaces from this code
+ * are not restricted to be used by modules with a GPL compatible license.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ *
+ */
+
+#ifndef SJA1000_DEV_H
+#define SJA1000_DEV_H
+
+#include <linux/can/dev.h>
+#include <linux/can/platform/sja1000.h>
+
+#define SJA1000_MAX_IRQ 20	/* max. number of interrupts handled in ISR */
+
+/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
+#define REG_MOD		0x00
+#define REG_CMR		0x01
+#define REG_SR		0x02
+#define REG_IR		0x03
+#define REG_IER		0x04
+#define REG_ALC		0x0B
+#define REG_ECC		0x0C
+#define REG_EWL		0x0D
+#define REG_RXERR	0x0E
+#define REG_TXERR	0x0F
+#define REG_ACCC0	0x10
+#define REG_ACCC1	0x11
+#define REG_ACCC2	0x12
+#define REG_ACCC3	0x13
+#define REG_ACCM0	0x14
+#define REG_ACCM1	0x15
+#define REG_ACCM2	0x16
+#define REG_ACCM3	0x17
+#define REG_RMC		0x1D
+#define REG_RBSA	0x1E
+
+/* Common registers - manual section 6.5 */
+#define REG_BTR0	0x06
+#define REG_BTR1	0x07
+#define REG_OCR		0x08
+#define REG_CDR		0x1F
+
+#define REG_FI		0x10
+#define SFF_BUF		0x13
+#define EFF_BUF		0x15
+
+#define FI_FF		0x80
+#define FI_RTR		0x40
+
+#define REG_ID1		0x11
+#define REG_ID2		0x12
+#define REG_ID3		0x13
+#define REG_ID4		0x14
+
+#define CAN_RAM		0x20
+
+/* mode register */
+#define MOD_RM		0x01
+#define MOD_LOM		0x02
+#define MOD_STM		0x04
+#define MOD_AFM		0x08
+#define MOD_SM		0x10
+
+/* commands */
+#define CMD_SRR		0x10
+#define CMD_CDO		0x08
+#define CMD_RRB		0x04
+#define CMD_AT		0x02
+#define CMD_TR		0x01
+
+/* interrupt sources */
+#define IRQ_BEI		0x80
+#define IRQ_ALI		0x40
+#define IRQ_EPI		0x20
+#define IRQ_WUI		0x10
+#define IRQ_DOI		0x08
+#define IRQ_EI		0x04
+#define IRQ_TI		0x02
+#define IRQ_RI		0x01
+#define IRQ_ALL		0xFF
+#define IRQ_OFF		0x00
+
+/* status register content */
+#define SR_BS		0x80
+#define SR_ES		0x40
+#define SR_TS		0x20
+#define SR_RS		0x10
+#define SR_TCS		0x08
+#define SR_TBS		0x04
+#define SR_DOS		0x02
+#define SR_RBS		0x01
+
+#define SR_CRIT (SR_BS|SR_ES)
+
+/* ECC register */
+#define ECC_SEG		0x1F
+#define ECC_DIR		0x20
+#define ECC_ERR		6
+#define ECC_BIT		0x00
+#define ECC_FORM	0x40
+#define ECC_STUFF	0x80
+#define ECC_MASK	0xc0
+
+/*
+ * Flags for sja1000priv.flags
+ */
+#define SJA1000_CUSTOM_IRQ_HANDLER 0x1
+
+/*
+ * SJA1000 private data structure
+ */
+struct sja1000_priv {
+	struct can_priv can;	/* must be the first member */
+	int open_time;
+	struct sk_buff *echo_skb;
+
+	/* the lower-layer is responsible for appropriate locking */
+	u8 (*read_reg) (const struct sja1000_priv *priv, int reg);
+	void (*write_reg) (const struct sja1000_priv *priv, int reg, u8 val);
+	void (*pre_irq) (const struct sja1000_priv *priv);
+	void (*post_irq) (const struct sja1000_priv *priv);
+
+	void *priv;		/* for board-specific data */
+	struct net_device *dev;
+
+	void __iomem *reg_base;	 /* ioremap'ed address to registers */
+	unsigned long irq_flags; /* for request_irq() */
+
+	u16 flags;		/* custom mode flags */
+	u8 ocr;			/* output control register */
+	u8 cdr;			/* clock divider register */
+};
+
+struct net_device *alloc_sja1000dev(int sizeof_priv);
+void free_sja1000dev(struct net_device *dev);
+int register_sja1000dev(struct net_device *dev);
+void unregister_sja1000dev(struct net_device *dev);
+
+irqreturn_t sja1000_interrupt(int irq, void *dev_id);
+
+#endif /* SJA1000_DEV_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000_of_platform.c linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000_of_platform.c
--- linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000_of_platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000_of_platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,235 @@
+/*
+ * Driver for SJA1000 CAN controllers on the OpenFirmware platform bus
+ *
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This is a generic driver for SJA1000 chips on the OpenFirmware platform
+ * bus found on embedded PowerPC systems. You need a SJA1000 CAN node
+ * definition in your flattened device tree source (DTS) file similar to:
+ *
+ *   can@3,100 {
+ *           compatible = "nxp,sja1000";
+ *           reg = <3 0x100 0x80>;
+ *           interrupts = <2 0>;
+ *           interrupt-parent = <&mpic>;
+ *           nxp,external-clock-frequency = <16000000>;
+ *   };
+ *
+ * See "Documentation/powerpc/dts-bindings/can/sja1000.txt" for further
+ * information.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+
+#include "sja1000.h"
+
+#define DRV_NAME "sja1000_of_platform"
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the OF platform bus");
+MODULE_LICENSE("GPL v2");
+
+#define SJA1000_OFP_CAN_CLOCK  (16000000 / 2)
+
+#define SJA1000_OFP_OCR        OCR_TX0_PULLDOWN
+#define SJA1000_OFP_CDR        (CDR_CBP | CDR_CLK_OFF)
+
+static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg)
+{
+	return in_8(priv->reg_base + reg);
+}
+
+static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
+				  int reg, u8 val)
+{
+	out_8(priv->reg_base + reg, val);
+}
+
+static int __devexit sja1000_ofp_remove(struct of_device *ofdev)
+{
+	struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct device_node *np = ofdev->node;
+	struct resource res;
+
+	dev_set_drvdata(&ofdev->dev, NULL);
+
+	unregister_sja1000dev(dev);
+	free_sja1000dev(dev);
+	iounmap(priv->reg_base);
+	irq_dispose_mapping(dev->irq);
+
+	of_address_to_resource(np, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+
+	return 0;
+}
+
+static int __devinit sja1000_ofp_probe(struct of_device *ofdev,
+				       const struct of_device_id *id)
+{
+	struct device_node *np = ofdev->node;
+	struct net_device *dev;
+	struct sja1000_priv *priv;
+	struct resource res;
+	const u32 *prop;
+	int err, irq, res_size, prop_size;
+	void __iomem *base;
+
+	err = of_address_to_resource(np, 0, &res);
+	if (err) {
+		dev_err(&ofdev->dev, "invalid address\n");
+		return err;
+	}
+
+	res_size = resource_size(&res);
+
+	if (!request_mem_region(res.start, res_size, DRV_NAME)) {
+		dev_err(&ofdev->dev, "couldn't request %#llx..%#llx\n",
+			(unsigned long long)res.start,
+			(unsigned long long)res.end);
+		return -EBUSY;
+	}
+
+	base = ioremap_nocache(res.start, res_size);
+	if (!base) {
+		dev_err(&ofdev->dev, "couldn't ioremap %#llx..%#llx\n",
+			(unsigned long long)res.start,
+			(unsigned long long)res.end);
+		err = -ENOMEM;
+		goto exit_release_mem;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq == NO_IRQ) {
+		dev_err(&ofdev->dev, "no irq found\n");
+		err = -ENODEV;
+		goto exit_unmap_mem;
+	}
+
+	dev = alloc_sja1000dev(0);
+	if (!dev) {
+		err = -ENOMEM;
+		goto exit_dispose_irq;
+	}
+
+	priv = netdev_priv(dev);
+
+	priv->read_reg = sja1000_ofp_read_reg;
+	priv->write_reg = sja1000_ofp_write_reg;
+
+	prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
+	if (prop && (prop_size ==  sizeof(u32)))
+		priv->can.clock.freq = *prop / 2;
+	else
+		priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
+
+	prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
+	if (prop && (prop_size == sizeof(u32)))
+		priv->ocr |= *prop & OCR_MODE_MASK;
+	else
+		priv->ocr |= OCR_MODE_NORMAL; /* default */
+
+	prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
+	if (prop && (prop_size == sizeof(u32)))
+		priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+	else
+		priv->ocr |= OCR_TX0_PULLDOWN; /* default */
+
+	prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
+	if (prop && (prop_size == sizeof(u32)) && *prop) {
+		u32 divider = priv->can.clock.freq * 2 / *prop;
+
+		if (divider > 1)
+			priv->cdr |= divider / 2 - 1;
+		else
+			priv->cdr |= CDR_CLKOUT_MASK;
+	} else {
+		priv->cdr |= CDR_CLK_OFF; /* default */
+	}
+
+	prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
+	if (!prop)
+		priv->cdr |= CDR_CBP; /* default */
+
+	priv->irq_flags = IRQF_SHARED;
+	priv->reg_base = base;
+
+	dev->irq = irq;
+
+	dev_info(&ofdev->dev,
+		 "reg_base=0x%p irq=%d clock=%d ocr=0x%02x cdr=0x%02x\n",
+		 priv->reg_base, dev->irq, priv->can.clock.freq,
+		 priv->ocr, priv->cdr);
+
+	dev_set_drvdata(&ofdev->dev, dev);
+	SET_NETDEV_DEV(dev, &ofdev->dev);
+
+	err = register_sja1000dev(dev);
+	if (err) {
+		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
+			DRV_NAME, err);
+		goto exit_free_sja1000;
+	}
+
+	return 0;
+
+exit_free_sja1000:
+	free_sja1000dev(dev);
+exit_dispose_irq:
+	irq_dispose_mapping(irq);
+exit_unmap_mem:
+	iounmap(base);
+exit_release_mem:
+	release_mem_region(res.start, res_size);
+
+	return err;
+}
+
+static struct of_device_id __devinitdata sja1000_ofp_table[] = {
+	{.compatible = "nxp,sja1000"},
+	{},
+};
+
+static struct of_platform_driver sja1000_ofp_driver = {
+	.owner = THIS_MODULE,
+	.name = DRV_NAME,
+	.probe = sja1000_ofp_probe,
+	.remove = __devexit_p(sja1000_ofp_remove),
+	.match_table = sja1000_ofp_table,
+};
+
+static int __init sja1000_ofp_init(void)
+{
+	return of_register_platform_driver(&sja1000_ofp_driver);
+}
+module_init(sja1000_ofp_init);
+
+static void __exit sja1000_ofp_exit(void)
+{
+	return of_unregister_platform_driver(&sja1000_ofp_driver);
+};
+module_exit(sja1000_ofp_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000_platform.c linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000_platform.c
--- linux-libre-2.6.30-gnu/drivers/net/can/sja1000/sja1000_platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/can/sja1000/sja1000_platform.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2005 Sascha Hauer, Pengutronix
+ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/platform/sja1000.h>
+#include <linux/io.h>
+
+#include "sja1000.h"
+
+#define DRV_NAME "sja1000_platform"
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
+MODULE_LICENSE("GPL v2");
+
+static u8 sp_read_reg(const struct sja1000_priv *priv, int reg)
+{
+	return ioread8(priv->reg_base + reg);
+}
+
+static void sp_write_reg(const struct sja1000_priv *priv, int reg, u8 val)
+{
+	iowrite8(val, priv->reg_base + reg);
+}
+
+static int sp_probe(struct platform_device *pdev)
+{
+	int err;
+	void __iomem *addr;
+	struct net_device *dev;
+	struct sja1000_priv *priv;
+	struct resource *res_mem, *res_irq;
+	struct sja1000_platform_data *pdata;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data provided!\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_mem || !res_irq) {
+		err = -ENODEV;
+		goto exit;
+	}
+
+	if (!request_mem_region(res_mem->start, resource_size(res_mem),
+				DRV_NAME)) {
+		err = -EBUSY;
+		goto exit;
+	}
+
+	addr = ioremap_nocache(res_mem->start, resource_size(res_mem));
+	if (!addr) {
+		err = -ENOMEM;
+		goto exit_release;
+	}
+
+	dev = alloc_sja1000dev(0);
+	if (!dev) {
+		err = -ENOMEM;
+		goto exit_iounmap;
+	}
+	priv = netdev_priv(dev);
+
+	dev->irq = res_irq->start;
+	priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
+	priv->reg_base = addr;
+	priv->read_reg = sp_read_reg;
+	priv->write_reg = sp_write_reg;
+	priv->can.clock.freq = pdata->clock;
+	priv->ocr = pdata->ocr;
+	priv->cdr = pdata->cdr;
+
+	dev_set_drvdata(&pdev->dev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	err = register_sja1000dev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
+			DRV_NAME, err);
+		goto exit_free;
+	}
+
+	dev_info(&pdev->dev, "%s device registered (reg_base=%p, irq=%d)\n",
+		 DRV_NAME, priv->reg_base, dev->irq);
+	return 0;
+
+ exit_free:
+	free_sja1000dev(dev);
+ exit_iounmap:
+	iounmap(addr);
+ exit_release:
+	release_mem_region(res_mem->start, resource_size(res_mem));
+ exit:
+	return err;
+}
+
+static int sp_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = dev_get_drvdata(&pdev->dev);
+	struct sja1000_priv *priv = netdev_priv(dev);
+	struct resource *res;
+
+	unregister_sja1000dev(dev);
+	dev_set_drvdata(&pdev->dev, NULL);
+
+	if (priv->reg_base)
+		iounmap(priv->reg_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	free_sja1000dev(dev);
+
+	return 0;
+}
+
+static struct platform_driver sp_driver = {
+	.probe = sp_probe,
+	.remove = sp_remove,
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init sp_init(void)
+{
+	return platform_driver_register(&sp_driver);
+}
+
+static void __exit sp_exit(void)
+{
+	platform_driver_unregister(&sp_driver);
+}
+
+module_init(sp_init);
+module_exit(sp_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/cassini.c linux-libre-2.6.31-gnu/drivers/net/cassini.c
--- linux-libre-2.6.30-gnu/drivers/net/cassini.c	2012-03-22 19:14:46.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cassini.c	2012-03-22 20:10:55.000000000 -0400
@@ -2934,7 +2934,7 @@
 	 *      individual queues.
 	 */
 	if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb))
-		return 1;
+		return NETDEV_TX_BUSY;
 	dev->trans_start = jiffies;
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/common.h linux-libre-2.6.31-gnu/drivers/net/chelsio/common.h
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/common.h	2009-09-09 18:13:59.000000000 -0400
@@ -46,7 +46,7 @@
 #include <linux/pci.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
-#include <linux/mii.h>
+#include <linux/mdio.h>
 #include <linux/crc32.h>
 #include <linux/init.h>
 #include <asm/io.h>
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/cphy.h linux-libre-2.6.31-gnu/drivers/net/chelsio/cphy.h
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/cphy.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/cphy.h	2009-09-09 18:13:59.000000000 -0400
@@ -43,10 +43,11 @@
 
 struct mdio_ops {
 	void (*init)(adapter_t *adapter, const struct board_info *bi);
-	int  (*read)(adapter_t *adapter, int phy_addr, int mmd_addr,
-		     int reg_addr, unsigned int *val);
-	int  (*write)(adapter_t *adapter, int phy_addr, int mmd_addr,
-		      int reg_addr, unsigned int val);
+	int  (*read)(struct net_device *dev, int phy_addr, int mmd_addr,
+		     u16 reg_addr);
+	int  (*write)(struct net_device *dev, int phy_addr, int mmd_addr,
+		      u16 reg_addr, u16 val);
+	unsigned mode_support;
 };
 
 /* PHY interrupt types */
@@ -83,11 +84,12 @@
 	int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex);
 	int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
 			       int *duplex, int *fc);
+
+	u32 mmds;
 };
 
 /* A PHY instance */
 struct cphy {
-	int addr;                            /* PHY address */
 	int state;	/* Link status state machine */
 	adapter_t *adapter;                  /* associated adapter */
 
@@ -101,56 +103,61 @@
 	u32 elmer_gpo;
 
 	const struct cphy_ops *ops;            /* PHY operations */
-	int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr,
-			 int reg_addr, unsigned int *val);
-	int (*mdio_write)(adapter_t *adapter, int phy_addr, int mmd_addr,
-			  int reg_addr, unsigned int val);
+	struct mdio_if_info mdio;
 	struct cphy_instance *instance;
 };
 
 /* Convenience MDIO read/write wrappers */
-static inline int mdio_read(struct cphy *cphy, int mmd, int reg,
-			    unsigned int *valp)
+static inline int cphy_mdio_read(struct cphy *cphy, int mmd, int reg,
+				 unsigned int *valp)
 {
-	return cphy->mdio_read(cphy->adapter, cphy->addr, mmd, reg, valp);
+	int rc = cphy->mdio.mdio_read(cphy->mdio.dev, cphy->mdio.prtad, mmd,
+				      reg);
+	*valp = (rc >= 0) ? rc : -1;
+	return (rc >= 0) ? 0 : rc;
 }
 
-static inline int mdio_write(struct cphy *cphy, int mmd, int reg,
-			     unsigned int val)
+static inline int cphy_mdio_write(struct cphy *cphy, int mmd, int reg,
+				  unsigned int val)
 {
-	return cphy->mdio_write(cphy->adapter, cphy->addr, mmd, reg, val);
+	return cphy->mdio.mdio_write(cphy->mdio.dev, cphy->mdio.prtad, mmd,
+				     reg, val);
 }
 
 static inline int simple_mdio_read(struct cphy *cphy, int reg,
 				   unsigned int *valp)
 {
-	return mdio_read(cphy, 0, reg, valp);
+	return cphy_mdio_read(cphy, MDIO_DEVAD_NONE, reg, valp);
 }
 
 static inline int simple_mdio_write(struct cphy *cphy, int reg,
 				    unsigned int val)
 {
-	return mdio_write(cphy, 0, reg, val);
+	return cphy_mdio_write(cphy, MDIO_DEVAD_NONE, reg, val);
 }
 
 /* Convenience initializer */
-static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
+static inline void cphy_init(struct cphy *phy, struct net_device *dev,
 			     int phy_addr, struct cphy_ops *phy_ops,
 			     const struct mdio_ops *mdio_ops)
 {
+	struct adapter *adapter = netdev_priv(dev);
 	phy->adapter = adapter;
-	phy->addr    = phy_addr;
 	phy->ops     = phy_ops;
 	if (mdio_ops) {
-		phy->mdio_read  = mdio_ops->read;
-		phy->mdio_write = mdio_ops->write;
+		phy->mdio.prtad = phy_addr;
+		phy->mdio.mmds = phy_ops->mmds;
+		phy->mdio.mode_support = mdio_ops->mode_support;
+		phy->mdio.mdio_read = mdio_ops->read;
+		phy->mdio.mdio_write = mdio_ops->write;
 	}
+	phy->mdio.dev = dev;
 }
 
 /* Operations of the PHY-instance factory */
 struct gphy {
 	/* Construct a PHY instance with the given PHY address */
-	struct cphy *(*create)(adapter_t *adapter, int phy_addr,
+	struct cphy *(*create)(struct net_device *dev, int phy_addr,
 			       const struct mdio_ops *mdio_ops);
 
 	/*
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/cxgb2.c linux-libre-2.6.31-gnu/drivers/net/chelsio/cxgb2.c
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/cxgb2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/cxgb2.c	2009-09-09 18:13:59.000000000 -0400
@@ -589,7 +589,7 @@
 	}
 
 	cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-	cmd->phy_address = p->phy->addr;
+	cmd->phy_address = p->phy->mdio.prtad;
 	cmd->transceiver = XCVR_EXTERNAL;
 	cmd->autoneg = p->link_config.autoneg;
 	cmd->maxtxpkt = 0;
@@ -849,39 +849,9 @@
 static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
 	struct adapter *adapter = dev->ml_priv;
-	struct mii_ioctl_data *data = if_mii(req);
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = adapter->port[dev->if_port].phy->addr;
-		/* FALLTHRU */
-	case SIOCGMIIREG: {
-		struct cphy *phy = adapter->port[dev->if_port].phy;
-		u32 val;
-
-		if (!phy->mdio_read)
-			return -EOPNOTSUPP;
-		phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,
-			       &val);
-		data->val_out = val;
-		break;
-	}
-	case SIOCSMIIREG: {
-		struct cphy *phy = adapter->port[dev->if_port].phy;
-
-		if (!capable(CAP_NET_ADMIN))
-		    return -EPERM;
-		if (!phy->mdio_write)
-			return -EOPNOTSUPP;
-		phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,
-			        data->val_in);
-		break;
-	}
+	struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
 
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
+	return mdio_mii_ioctl(mdio, if_mii(req), cmd);
 }
 
 static int t1_change_mtu(struct net_device *dev, int new_mtu)
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/mv88e1xxx.c linux-libre-2.6.31-gnu/drivers/net/chelsio/mv88e1xxx.c
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/mv88e1xxx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/mv88e1xxx.c	2009-09-09 18:13:59.000000000 -0400
@@ -353,15 +353,16 @@
 	.get_link_status      = mv88e1xxx_get_link_status,
 };
 
-static struct cphy *mv88e1xxx_phy_create(adapter_t *adapter, int phy_addr,
+static struct cphy *mv88e1xxx_phy_create(struct net_device *dev, int phy_addr,
 					 const struct mdio_ops *mdio_ops)
 {
+	struct adapter *adapter = netdev_priv(dev);
 	struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
 
 	if (!cphy)
 		return NULL;
 
-	cphy_init(cphy, adapter, phy_addr, &mv88e1xxx_ops, mdio_ops);
+	cphy_init(cphy, dev, phy_addr, &mv88e1xxx_ops, mdio_ops);
 
 	/* Configure particular PHY's to run in a different mode. */
 	if ((board_info(adapter)->caps & SUPPORTED_TP) &&
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/mv88x201x.c linux-libre-2.6.31-gnu/drivers/net/chelsio/mv88x201x.c
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/mv88x201x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/mv88x201x.c	2009-09-09 18:13:59.000000000 -0400
@@ -53,7 +53,7 @@
 	 * Writing these bits maps control to another
 	 * register. mmd(0x1) addr(0x7)
 	 */
-	mdio_write(cphy, 0x3, 0x8304, 0xdddd);
+	cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8304, 0xdddd);
 	return 0;
 }
 
@@ -62,14 +62,14 @@
 	u32 led = 0;
 #define LINK_ENABLE_BIT 0x1
 
-	mdio_read(cphy, 0x1, 0x7, &led);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led);
 
 	if (do_enable & LINK_ENABLE_BIT) {
 		led |= LINK_ENABLE_BIT;
-		mdio_write(cphy, 0x1, 0x7, led);
+		cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
 	} else {
 		led &= ~LINK_ENABLE_BIT;
-		mdio_write(cphy, 0x1, 0x7, led);
+		cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
 	}
 	return 0;
 }
@@ -86,7 +86,8 @@
 static int mv88x201x_interrupt_enable(struct cphy *cphy)
 {
 	/* Enable PHY LASI interrupts. */
-	mdio_write(cphy, 0x1, 0x9002, 0x1);
+	cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
+			MDIO_PMA_LASI_LSALARM);
 
 	/* Enable Marvell interrupts through Elmer0. */
 	if (t1_is_asic(cphy->adapter)) {
@@ -102,7 +103,7 @@
 static int mv88x201x_interrupt_disable(struct cphy *cphy)
 {
 	/* Disable PHY LASI interrupts. */
-	mdio_write(cphy, 0x1, 0x9002, 0x0);
+	cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0x0);
 
 	/* Disable Marvell interrupts through Elmer0. */
 	if (t1_is_asic(cphy->adapter)) {
@@ -122,25 +123,25 @@
 
 #ifdef MV88x2010_LINK_STATUS_BUGS
 	/* Required to read twice before clear takes affect. */
-	mdio_read(cphy, 0x1, 0x9003, &val);
-	mdio_read(cphy, 0x1, 0x9004, &val);
-	mdio_read(cphy, 0x1, 0x9005, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
 
 	/* Read this register after the others above it else
 	 * the register doesn't clear correctly.
 	 */
-	mdio_read(cphy, 0x1, 0x1, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
 #endif
 
 	/* Clear link status. */
-	mdio_read(cphy, 0x1, 0x1, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
 	/* Clear PHY LASI interrupts. */
-	mdio_read(cphy, 0x1, 0x9005, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
 
 #ifdef MV88x2010_LINK_STATUS_BUGS
 	/* Do it again. */
-	mdio_read(cphy, 0x1, 0x9003, &val);
-	mdio_read(cphy, 0x1, 0x9004, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val);
 #endif
 
 	/* Clear Marvell interrupts through Elmer0. */
@@ -172,13 +173,12 @@
 				     int *speed, int *duplex, int *fc)
 {
 	u32 val = 0;
-#define LINK_STATUS_BIT 0x4
 
 	if (link_ok) {
 		/* Read link status. */
-		mdio_read(cphy, 0x1, 0x1, &val);
-		val &= LINK_STATUS_BIT;
-		*link_ok = (val == LINK_STATUS_BIT);
+		cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
+		val &= MDIO_STAT1_LSTATUS;
+		*link_ok = (val == MDIO_STAT1_LSTATUS);
 		/* Turn on/off Link LED */
 		led_link(cphy, *link_ok);
 	}
@@ -205,9 +205,11 @@
 	.interrupt_handler = mv88x201x_interrupt_handler,
 	.get_link_status   = mv88x201x_get_link_status,
 	.set_loopback      = mv88x201x_set_loopback,
+	.mmds              = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
+			      MDIO_DEVS_PHYXS | MDIO_DEVS_WIS),
 };
 
-static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
+static struct cphy *mv88x201x_phy_create(struct net_device *dev, int phy_addr,
 					 const struct mdio_ops *mdio_ops)
 {
 	u32 val;
@@ -216,15 +218,15 @@
 	if (!cphy)
 		return NULL;
 
-	cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops);
+	cphy_init(cphy, dev, phy_addr, &mv88x201x_ops, mdio_ops);
 
 	/* Commands the PHY to enable XFP's clock. */
-	mdio_read(cphy, 0x3, 0x8300, &val);
-	mdio_write(cphy, 0x3, 0x8300, val | 1);
+	cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val);
+	cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1);
 
 	/* Clear link status. Required because of a bug in the PHY.  */
-	mdio_read(cphy, 0x1, 0x8, &val);
-	mdio_read(cphy, 0x3, 0x8, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val);
 
 	/* Allows for Link,Ack LED turn on/off */
 	led_init(cphy);
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/my3126.c linux-libre-2.6.31-gnu/drivers/net/chelsio/my3126.c
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/my3126.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/my3126.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,11 +43,11 @@
 	adapter = cphy->adapter;
 
 	if (cphy->count == 50) {
-		mdio_read(cphy, 0x1, 0x1, &val);
+		cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
 		val16 = (u16) val;
 		status = cphy->bmsr ^ val16;
 
-		if (status & BMSR_LSTATUS)
+		if (status & MDIO_STAT1_LSTATUS)
 			t1_link_changed(adapter, 0);
 		cphy->bmsr = val16;
 
@@ -114,14 +114,14 @@
 	adapter_t *adapter;
 
 	adapter = cphy->adapter;
-	mdio_read(cphy, 0x1, 0x1, &val);
+	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
 	val16 = (u16) val;
 
 	/* Populate elmer_gpo with the register value */
 	t1_tpi_read(adapter, A_ELMER0_GPO, &val);
 	cphy->elmer_gpo = val;
 
-	*link_ok = (val16 & BMSR_LSTATUS);
+	*link_ok = (val16 & MDIO_STAT1_LSTATUS);
 
 	if (*link_ok) {
 		/* Turn on the LED. */
@@ -163,9 +163,11 @@
 	.interrupt_handler	= my3126_interrupt_handler,
 	.get_link_status	= my3126_get_link_status,
 	.set_loopback		= my3126_set_loopback,
+	.mmds			= (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
+				   MDIO_DEVS_PHYXS),
 };
 
-static struct cphy *my3126_phy_create(adapter_t *adapter,
+static struct cphy *my3126_phy_create(struct net_device *dev,
 			int phy_addr, const struct mdio_ops *mdio_ops)
 {
 	struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);
@@ -173,7 +175,7 @@
 	if (!cphy)
 		return NULL;
 
-	cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops);
+	cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops);
 	INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
 	cphy->bmsr = 0;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/sge.c linux-libre-2.6.31-gnu/drivers/net/chelsio/sge.c
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/sge.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/sge.c	2009-09-09 18:13:59.000000000 -0400
@@ -1149,8 +1149,8 @@
 				 unsigned int len, unsigned int gen,
 				 unsigned int eop)
 {
-	if (unlikely(len > SGE_TX_DESC_MAX_PLEN))
-		BUG();
+	BUG_ON(len > SGE_TX_DESC_MAX_PLEN);
+
 	e->addr_lo = (u32)mapping;
 	e->addr_hi = (u64)mapping >> 32;
 	e->len_gen = V_CMD_LEN(len) | V_CMD_GEN1(gen);
@@ -1879,7 +1879,6 @@
 		cpl->vlan_valid = 0;
 
 send:
-	dev->trans_start = jiffies;
 	ret = t1_sge_tx(skb, adapter, 0, dev);
 
 	/* If transmit busy, and we reallocated skb's due to headroom limit,
diff -druN linux-libre-2.6.30-gnu/drivers/net/chelsio/subr.c linux-libre-2.6.31-gnu/drivers/net/chelsio/subr.c
--- linux-libre-2.6.30-gnu/drivers/net/chelsio/subr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/chelsio/subr.c	2009-09-09 18:13:59.000000000 -0400
@@ -284,32 +284,29 @@
 /*
  * Elmer MI1 MDIO read/write operations.
  */
-static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr,
-			 int reg_addr, unsigned int *valp)
+static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr,
+			 u16 reg_addr)
 {
+	struct adapter *adapter = dev->ml_priv;
 	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
-
-	if (mmd_addr)
-		return -EINVAL;
+	unsigned int val;
 
 	spin_lock(&adapter->tpi_lock);
 	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 	__t1_tpi_write(adapter,
 			A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ);
 	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
-	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
+	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
 	spin_unlock(&adapter->tpi_lock);
-	return 0;
+	return val;
 }
 
-static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
-			  int reg_addr, unsigned int val)
+static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
+			  u16 reg_addr, u16 val)
 {
+	struct adapter *adapter = dev->ml_priv;
 	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
 
-	if (mmd_addr)
-		return -EINVAL;
-
 	spin_lock(&adapter->tpi_lock);
 	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 	__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
@@ -324,16 +321,19 @@
 static const struct mdio_ops mi1_mdio_ops = {
 	.init = mi1_mdio_init,
 	.read = mi1_mdio_read,
-	.write = mi1_mdio_write
+	.write = mi1_mdio_write,
+	.mode_support = MDIO_SUPPORTS_C22
 };
 #endif
 
 #endif
 
-static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
-			     int reg_addr, unsigned int *valp)
+static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
+			     u16 reg_addr)
 {
+	struct adapter *adapter = dev->ml_priv;
 	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
+	unsigned int val;
 
 	spin_lock(&adapter->tpi_lock);
 
@@ -350,14 +350,15 @@
 	mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 
 	/* Read the data. */
-	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
+	__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
 	spin_unlock(&adapter->tpi_lock);
-	return 0;
+	return val;
 }
 
-static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
-			      int reg_addr, unsigned int val)
+static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr,
+			      int mmd_addr, u16 reg_addr, u16 val)
 {
+	struct adapter *adapter = dev->ml_priv;
 	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
 
 	spin_lock(&adapter->tpi_lock);
@@ -380,7 +381,8 @@
 static const struct mdio_ops mi1_mdio_ext_ops = {
 	.init = mi1_mdio_init,
 	.read = mi1_mdio_ext_read,
-	.write = mi1_mdio_ext_write
+	.write = mi1_mdio_ext_write,
+	.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
 };
 
 enum {
@@ -1133,8 +1135,8 @@
 		struct cmac *mac;
 		int phy_addr = bi->mdio_phybaseaddr + i;
 
-		adapter->port[i].phy = bi->gphy->create(adapter, phy_addr,
-							bi->mdio_ops);
+		adapter->port[i].phy = bi->gphy->create(adapter->port[i].dev,
+							phy_addr, bi->mdio_ops);
 		if (!adapter->port[i].phy) {
 			CH_ERR("%s: PHY %d initialization failed\n",
 			       adapter->name, i);
diff -druN linux-libre-2.6.30-gnu/drivers/net/cnic.c linux-libre-2.6.31-gnu/drivers/net/cnic.c
--- linux-libre-2.6.30-gnu/drivers/net/cnic.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/cnic.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2799 @@
+/* cnic.c: Broadcom CNIC core network driver.
+ *
+ * Copyright (c) 2006-2009 Broadcom 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.
+ *
+ * Original skeleton written by: John(Zongxi) Chen (zongxi@broadcom.com)
+ * Modified and maintained by: Michael Chan <mchan@broadcom.com>
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/uio_driver.h>
+#include <linux/in.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define BCM_VLAN 1
+#endif
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/route.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <scsi/iscsi_if.h>
+
+#include "cnic_if.h"
+#include "bnx2.h"
+#include "cnic.h"
+#include "cnic_defs.h"
+
+#define DRV_MODULE_NAME		"cnic"
+#define PFX DRV_MODULE_NAME	": "
+
+static char version[] __devinitdata =
+	"Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) "
+	      "Chen (zongxi@broadcom.com");
+MODULE_DESCRIPTION("Broadcom NetXtreme II CNIC Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CNIC_MODULE_VERSION);
+
+static LIST_HEAD(cnic_dev_list);
+static DEFINE_RWLOCK(cnic_dev_lock);
+static DEFINE_MUTEX(cnic_lock);
+
+static struct cnic_ulp_ops *cnic_ulp_tbl[MAX_CNIC_ULP_TYPE];
+
+static int cnic_service_bnx2(void *, void *);
+static int cnic_ctl(void *, struct cnic_ctl_info *);
+
+static struct cnic_ops cnic_bnx2_ops = {
+	.cnic_owner	= THIS_MODULE,
+	.cnic_handler	= cnic_service_bnx2,
+	.cnic_ctl	= cnic_ctl,
+};
+
+static void cnic_shutdown_bnx2_rx_ring(struct cnic_dev *);
+static void cnic_init_bnx2_tx_ring(struct cnic_dev *);
+static void cnic_init_bnx2_rx_ring(struct cnic_dev *);
+static int cnic_cm_set_pg(struct cnic_sock *);
+
+static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
+{
+	struct cnic_dev *dev = uinfo->priv;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (cp->uio_dev != -1)
+		return -EBUSY;
+
+	cp->uio_dev = iminor(inode);
+
+	cnic_shutdown_bnx2_rx_ring(dev);
+
+	cnic_init_bnx2_tx_ring(dev);
+	cnic_init_bnx2_rx_ring(dev);
+
+	return 0;
+}
+
+static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
+{
+	struct cnic_dev *dev = uinfo->priv;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	cp->uio_dev = -1;
+	return 0;
+}
+
+static inline void cnic_hold(struct cnic_dev *dev)
+{
+	atomic_inc(&dev->ref_count);
+}
+
+static inline void cnic_put(struct cnic_dev *dev)
+{
+	atomic_dec(&dev->ref_count);
+}
+
+static inline void csk_hold(struct cnic_sock *csk)
+{
+	atomic_inc(&csk->ref_count);
+}
+
+static inline void csk_put(struct cnic_sock *csk)
+{
+	atomic_dec(&csk->ref_count);
+}
+
+static struct cnic_dev *cnic_from_netdev(struct net_device *netdev)
+{
+	struct cnic_dev *cdev;
+
+	read_lock(&cnic_dev_lock);
+	list_for_each_entry(cdev, &cnic_dev_list, list) {
+		if (netdev == cdev->netdev) {
+			cnic_hold(cdev);
+			read_unlock(&cnic_dev_lock);
+			return cdev;
+		}
+	}
+	read_unlock(&cnic_dev_lock);
+	return NULL;
+}
+
+static inline void ulp_get(struct cnic_ulp_ops *ulp_ops)
+{
+	atomic_inc(&ulp_ops->ref_count);
+}
+
+static inline void ulp_put(struct cnic_ulp_ops *ulp_ops)
+{
+	atomic_dec(&ulp_ops->ref_count);
+}
+
+static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	struct drv_ctl_info info;
+	struct drv_ctl_io *io = &info.data.io;
+
+	info.cmd = DRV_CTL_CTX_WR_CMD;
+	io->cid_addr = cid_addr;
+	io->offset = off;
+	io->data = val;
+	ethdev->drv_ctl(dev->netdev, &info);
+}
+
+static void cnic_reg_wr_ind(struct cnic_dev *dev, u32 off, u32 val)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	struct drv_ctl_info info;
+	struct drv_ctl_io *io = &info.data.io;
+
+	info.cmd = DRV_CTL_IO_WR_CMD;
+	io->offset = off;
+	io->data = val;
+	ethdev->drv_ctl(dev->netdev, &info);
+}
+
+static u32 cnic_reg_rd_ind(struct cnic_dev *dev, u32 off)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	struct drv_ctl_info info;
+	struct drv_ctl_io *io = &info.data.io;
+
+	info.cmd = DRV_CTL_IO_RD_CMD;
+	io->offset = off;
+	ethdev->drv_ctl(dev->netdev, &info);
+	return io->data;
+}
+
+static int cnic_in_use(struct cnic_sock *csk)
+{
+	return test_bit(SK_F_INUSE, &csk->flags);
+}
+
+static void cnic_kwq_completion(struct cnic_dev *dev, u32 count)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	struct drv_ctl_info info;
+
+	info.cmd = DRV_CTL_COMPLETION_CMD;
+	info.data.comp.comp_count = count;
+	ethdev->drv_ctl(dev->netdev, &info);
+}
+
+static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
+			   struct cnic_sock *csk)
+{
+	struct iscsi_path path_req;
+	char *buf = NULL;
+	u16 len = 0;
+	u32 msg_type = ISCSI_KEVENT_IF_DOWN;
+	struct cnic_ulp_ops *ulp_ops;
+
+	if (cp->uio_dev == -1)
+		return -ENODEV;
+
+	if (csk) {
+		len = sizeof(path_req);
+		buf = (char *) &path_req;
+		memset(&path_req, 0, len);
+
+		msg_type = ISCSI_KEVENT_PATH_REQ;
+		path_req.handle = (u64) csk->l5_cid;
+		if (test_bit(SK_F_IPV6, &csk->flags)) {
+			memcpy(&path_req.dst.v6_addr, &csk->dst_ip[0],
+			       sizeof(struct in6_addr));
+			path_req.ip_addr_len = 16;
+		} else {
+			memcpy(&path_req.dst.v4_addr, &csk->dst_ip[0],
+			       sizeof(struct in_addr));
+			path_req.ip_addr_len = 4;
+		}
+		path_req.vlan_id = csk->vlan_id;
+		path_req.pmtu = csk->mtu;
+	}
+
+	rcu_read_lock();
+	ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
+	if (ulp_ops)
+		ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len);
+	rcu_read_unlock();
+	return 0;
+}
+
+static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
+				  char *buf, u16 len)
+{
+	int rc = -EINVAL;
+
+	switch (msg_type) {
+	case ISCSI_UEVENT_PATH_UPDATE: {
+		struct cnic_local *cp;
+		u32 l5_cid;
+		struct cnic_sock *csk;
+		struct iscsi_path *path_resp;
+
+		if (len < sizeof(*path_resp))
+			break;
+
+		path_resp = (struct iscsi_path *) buf;
+		cp = dev->cnic_priv;
+		l5_cid = (u32) path_resp->handle;
+		if (l5_cid >= MAX_CM_SK_TBL_SZ)
+			break;
+
+		csk = &cp->csk_tbl[l5_cid];
+		csk_hold(csk);
+		if (cnic_in_use(csk)) {
+			memcpy(csk->ha, path_resp->mac_addr, 6);
+			if (test_bit(SK_F_IPV6, &csk->flags))
+				memcpy(&csk->src_ip[0], &path_resp->src.v6_addr,
+				       sizeof(struct in6_addr));
+			else
+				memcpy(&csk->src_ip[0], &path_resp->src.v4_addr,
+				       sizeof(struct in_addr));
+			if (is_valid_ether_addr(csk->ha))
+				cnic_cm_set_pg(csk);
+		}
+		csk_put(csk);
+		rc = 0;
+	}
+	}
+
+	return rc;
+}
+
+static int cnic_offld_prep(struct cnic_sock *csk)
+{
+	if (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags))
+		return 0;
+
+	if (!test_bit(SK_F_CONNECT_START, &csk->flags)) {
+		clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int cnic_close_prep(struct cnic_sock *csk)
+{
+	clear_bit(SK_F_CONNECT_START, &csk->flags);
+	smp_mb__after_clear_bit();
+
+	if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
+		while (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags))
+			msleep(1);
+
+		return 1;
+	}
+	return 0;
+}
+
+static int cnic_abort_prep(struct cnic_sock *csk)
+{
+	clear_bit(SK_F_CONNECT_START, &csk->flags);
+	smp_mb__after_clear_bit();
+
+	while (test_and_set_bit(SK_F_OFFLD_SCHED, &csk->flags))
+		msleep(1);
+
+	if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) {
+		csk->state = L4_KCQE_OPCODE_VALUE_RESET_COMP;
+		return 1;
+	}
+
+	return 0;
+}
+
+static void cnic_uio_stop(void)
+{
+	struct cnic_dev *dev;
+
+	read_lock(&cnic_dev_lock);
+	list_for_each_entry(dev, &cnic_dev_list, list) {
+		struct cnic_local *cp = dev->cnic_priv;
+
+		if (cp->cnic_uinfo)
+			cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+	}
+	read_unlock(&cnic_dev_lock);
+}
+
+int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
+{
+	struct cnic_dev *dev;
+
+	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+		printk(KERN_ERR PFX "cnic_register_driver: Bad type %d\n",
+		       ulp_type);
+		return -EINVAL;
+	}
+	mutex_lock(&cnic_lock);
+	if (cnic_ulp_tbl[ulp_type]) {
+		printk(KERN_ERR PFX "cnic_register_driver: Type %d has already "
+				    "been registered\n", ulp_type);
+		mutex_unlock(&cnic_lock);
+		return -EBUSY;
+	}
+
+	read_lock(&cnic_dev_lock);
+	list_for_each_entry(dev, &cnic_dev_list, list) {
+		struct cnic_local *cp = dev->cnic_priv;
+
+		clear_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]);
+	}
+	read_unlock(&cnic_dev_lock);
+
+	atomic_set(&ulp_ops->ref_count, 0);
+	rcu_assign_pointer(cnic_ulp_tbl[ulp_type], ulp_ops);
+	mutex_unlock(&cnic_lock);
+
+	/* Prevent race conditions with netdev_event */
+	rtnl_lock();
+	read_lock(&cnic_dev_lock);
+	list_for_each_entry(dev, &cnic_dev_list, list) {
+		struct cnic_local *cp = dev->cnic_priv;
+
+		if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[ulp_type]))
+			ulp_ops->cnic_init(dev);
+	}
+	read_unlock(&cnic_dev_lock);
+	rtnl_unlock();
+
+	return 0;
+}
+
+int cnic_unregister_driver(int ulp_type)
+{
+	struct cnic_dev *dev;
+	struct cnic_ulp_ops *ulp_ops;
+	int i = 0;
+
+	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+		printk(KERN_ERR PFX "cnic_unregister_driver: Bad type %d\n",
+		       ulp_type);
+		return -EINVAL;
+	}
+	mutex_lock(&cnic_lock);
+	ulp_ops = cnic_ulp_tbl[ulp_type];
+	if (!ulp_ops) {
+		printk(KERN_ERR PFX "cnic_unregister_driver: Type %d has not "
+				    "been registered\n", ulp_type);
+		goto out_unlock;
+	}
+	read_lock(&cnic_dev_lock);
+	list_for_each_entry(dev, &cnic_dev_list, list) {
+		struct cnic_local *cp = dev->cnic_priv;
+
+		if (rcu_dereference(cp->ulp_ops[ulp_type])) {
+			printk(KERN_ERR PFX "cnic_unregister_driver: Type %d "
+			       "still has devices registered\n", ulp_type);
+			read_unlock(&cnic_dev_lock);
+			goto out_unlock;
+		}
+	}
+	read_unlock(&cnic_dev_lock);
+
+	if (ulp_type == CNIC_ULP_ISCSI)
+		cnic_uio_stop();
+
+	rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL);
+
+	mutex_unlock(&cnic_lock);
+	synchronize_rcu();
+	while ((atomic_read(&ulp_ops->ref_count) != 0) && (i < 20)) {
+		msleep(100);
+		i++;
+	}
+
+	if (atomic_read(&ulp_ops->ref_count) != 0)
+		printk(KERN_WARNING PFX "%s: Failed waiting for ref count to go"
+					" to zero.\n", dev->netdev->name);
+	return 0;
+
+out_unlock:
+	mutex_unlock(&cnic_lock);
+	return -EINVAL;
+}
+
+static int cnic_start_hw(struct cnic_dev *);
+static void cnic_stop_hw(struct cnic_dev *);
+
+static int cnic_register_device(struct cnic_dev *dev, int ulp_type,
+				void *ulp_ctx)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_ulp_ops *ulp_ops;
+
+	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+		printk(KERN_ERR PFX "cnic_register_device: Bad type %d\n",
+		       ulp_type);
+		return -EINVAL;
+	}
+	mutex_lock(&cnic_lock);
+	if (cnic_ulp_tbl[ulp_type] == NULL) {
+		printk(KERN_ERR PFX "cnic_register_device: Driver with type %d "
+				    "has not been registered\n", ulp_type);
+		mutex_unlock(&cnic_lock);
+		return -EAGAIN;
+	}
+	if (rcu_dereference(cp->ulp_ops[ulp_type])) {
+		printk(KERN_ERR PFX "cnic_register_device: Type %d has already "
+		       "been registered to this device\n", ulp_type);
+		mutex_unlock(&cnic_lock);
+		return -EBUSY;
+	}
+
+	clear_bit(ULP_F_START, &cp->ulp_flags[ulp_type]);
+	cp->ulp_handle[ulp_type] = ulp_ctx;
+	ulp_ops = cnic_ulp_tbl[ulp_type];
+	rcu_assign_pointer(cp->ulp_ops[ulp_type], ulp_ops);
+	cnic_hold(dev);
+
+	if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
+		if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[ulp_type]))
+			ulp_ops->cnic_start(cp->ulp_handle[ulp_type]);
+
+	mutex_unlock(&cnic_lock);
+
+	return 0;
+
+}
+EXPORT_SYMBOL(cnic_register_driver);
+
+static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int i = 0;
+
+	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+		printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n",
+		       ulp_type);
+		return -EINVAL;
+	}
+	mutex_lock(&cnic_lock);
+	if (rcu_dereference(cp->ulp_ops[ulp_type])) {
+		rcu_assign_pointer(cp->ulp_ops[ulp_type], NULL);
+		cnic_put(dev);
+	} else {
+		printk(KERN_ERR PFX "cnic_unregister_device: device not "
+		       "registered to this ulp type %d\n", ulp_type);
+		mutex_unlock(&cnic_lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&cnic_lock);
+
+	synchronize_rcu();
+
+	while (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]) &&
+	       i < 20) {
+		msleep(100);
+		i++;
+	}
+	if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]))
+		printk(KERN_WARNING PFX "%s: Failed waiting for ULP up call"
+					" to complete.\n", dev->netdev->name);
+
+	return 0;
+}
+EXPORT_SYMBOL(cnic_unregister_driver);
+
+static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id)
+{
+	id_tbl->start = start_id;
+	id_tbl->max = size;
+	id_tbl->next = 0;
+	spin_lock_init(&id_tbl->lock);
+	id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);
+	if (!id_tbl->table)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void cnic_free_id_tbl(struct cnic_id_tbl *id_tbl)
+{
+	kfree(id_tbl->table);
+	id_tbl->table = NULL;
+}
+
+static int cnic_alloc_id(struct cnic_id_tbl *id_tbl, u32 id)
+{
+	int ret = -1;
+
+	id -= id_tbl->start;
+	if (id >= id_tbl->max)
+		return ret;
+
+	spin_lock(&id_tbl->lock);
+	if (!test_bit(id, id_tbl->table)) {
+		set_bit(id, id_tbl->table);
+		ret = 0;
+	}
+	spin_unlock(&id_tbl->lock);
+	return ret;
+}
+
+/* Returns -1 if not successful */
+static u32 cnic_alloc_new_id(struct cnic_id_tbl *id_tbl)
+{
+	u32 id;
+
+	spin_lock(&id_tbl->lock);
+	id = find_next_zero_bit(id_tbl->table, id_tbl->max, id_tbl->next);
+	if (id >= id_tbl->max) {
+		id = -1;
+		if (id_tbl->next != 0) {
+			id = find_first_zero_bit(id_tbl->table, id_tbl->next);
+			if (id >= id_tbl->next)
+				id = -1;
+		}
+	}
+
+	if (id < id_tbl->max) {
+		set_bit(id, id_tbl->table);
+		id_tbl->next = (id + 1) & (id_tbl->max - 1);
+		id += id_tbl->start;
+	}
+
+	spin_unlock(&id_tbl->lock);
+
+	return id;
+}
+
+static void cnic_free_id(struct cnic_id_tbl *id_tbl, u32 id)
+{
+	if (id == -1)
+		return;
+
+	id -= id_tbl->start;
+	if (id >= id_tbl->max)
+		return;
+
+	clear_bit(id, id_tbl->table);
+}
+
+static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma)
+{
+	int i;
+
+	if (!dma->pg_arr)
+		return;
+
+	for (i = 0; i < dma->num_pages; i++) {
+		if (dma->pg_arr[i]) {
+			pci_free_consistent(dev->pcidev, BCM_PAGE_SIZE,
+					    dma->pg_arr[i], dma->pg_map_arr[i]);
+			dma->pg_arr[i] = NULL;
+		}
+	}
+	if (dma->pgtbl) {
+		pci_free_consistent(dev->pcidev, dma->pgtbl_size,
+				    dma->pgtbl, dma->pgtbl_map);
+		dma->pgtbl = NULL;
+	}
+	kfree(dma->pg_arr);
+	dma->pg_arr = NULL;
+	dma->num_pages = 0;
+}
+
+static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma)
+{
+	int i;
+	u32 *page_table = dma->pgtbl;
+
+	for (i = 0; i < dma->num_pages; i++) {
+		/* Each entry needs to be in big endian format. */
+		*page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32);
+		page_table++;
+		*page_table = (u32) dma->pg_map_arr[i];
+		page_table++;
+	}
+}
+
+static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
+			  int pages, int use_pg_tbl)
+{
+	int i, size;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	size = pages * (sizeof(void *) + sizeof(dma_addr_t));
+	dma->pg_arr = kzalloc(size, GFP_ATOMIC);
+	if (dma->pg_arr == NULL)
+		return -ENOMEM;
+
+	dma->pg_map_arr = (dma_addr_t *) (dma->pg_arr + pages);
+	dma->num_pages = pages;
+
+	for (i = 0; i < pages; i++) {
+		dma->pg_arr[i] = pci_alloc_consistent(dev->pcidev,
+						      BCM_PAGE_SIZE,
+						      &dma->pg_map_arr[i]);
+		if (dma->pg_arr[i] == NULL)
+			goto error;
+	}
+	if (!use_pg_tbl)
+		return 0;
+
+	dma->pgtbl_size = ((pages * 8) + BCM_PAGE_SIZE - 1) &
+			  ~(BCM_PAGE_SIZE - 1);
+	dma->pgtbl = pci_alloc_consistent(dev->pcidev, dma->pgtbl_size,
+					  &dma->pgtbl_map);
+	if (dma->pgtbl == NULL)
+		goto error;
+
+	cp->setup_pgtbl(dev, dma);
+
+	return 0;
+
+error:
+	cnic_free_dma(dev, dma);
+	return -ENOMEM;
+}
+
+static void cnic_free_resc(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int i = 0;
+
+	if (cp->cnic_uinfo) {
+		while (cp->uio_dev != -1 && i < 15) {
+			msleep(100);
+			i++;
+		}
+		uio_unregister_device(cp->cnic_uinfo);
+		kfree(cp->cnic_uinfo);
+		cp->cnic_uinfo = NULL;
+	}
+
+	if (cp->l2_buf) {
+		pci_free_consistent(dev->pcidev, cp->l2_buf_size,
+				    cp->l2_buf, cp->l2_buf_map);
+		cp->l2_buf = NULL;
+	}
+
+	if (cp->l2_ring) {
+		pci_free_consistent(dev->pcidev, cp->l2_ring_size,
+				    cp->l2_ring, cp->l2_ring_map);
+		cp->l2_ring = NULL;
+	}
+
+	for (i = 0; i < cp->ctx_blks; i++) {
+		if (cp->ctx_arr[i].ctx) {
+			pci_free_consistent(dev->pcidev, cp->ctx_blk_size,
+					    cp->ctx_arr[i].ctx,
+					    cp->ctx_arr[i].mapping);
+			cp->ctx_arr[i].ctx = NULL;
+		}
+	}
+	kfree(cp->ctx_arr);
+	cp->ctx_arr = NULL;
+	cp->ctx_blks = 0;
+
+	cnic_free_dma(dev, &cp->gbl_buf_info);
+	cnic_free_dma(dev, &cp->conn_buf_info);
+	cnic_free_dma(dev, &cp->kwq_info);
+	cnic_free_dma(dev, &cp->kcq_info);
+	kfree(cp->iscsi_tbl);
+	cp->iscsi_tbl = NULL;
+	kfree(cp->ctx_tbl);
+	cp->ctx_tbl = NULL;
+
+	cnic_free_id_tbl(&cp->cid_tbl);
+}
+
+static int cnic_alloc_context(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+
+	if (CHIP_NUM(cp) == CHIP_NUM_5709) {
+		int i, k, arr_size;
+
+		cp->ctx_blk_size = BCM_PAGE_SIZE;
+		cp->cids_per_blk = BCM_PAGE_SIZE / 128;
+		arr_size = BNX2_MAX_CID / cp->cids_per_blk *
+			   sizeof(struct cnic_ctx);
+		cp->ctx_arr = kzalloc(arr_size, GFP_KERNEL);
+		if (cp->ctx_arr == NULL)
+			return -ENOMEM;
+
+		k = 0;
+		for (i = 0; i < 2; i++) {
+			u32 j, reg, off, lo, hi;
+
+			if (i == 0)
+				off = BNX2_PG_CTX_MAP;
+			else
+				off = BNX2_ISCSI_CTX_MAP;
+
+			reg = cnic_reg_rd_ind(dev, off);
+			lo = reg >> 16;
+			hi = reg & 0xffff;
+			for (j = lo; j < hi; j += cp->cids_per_blk, k++)
+				cp->ctx_arr[k].cid = j;
+		}
+
+		cp->ctx_blks = k;
+		if (cp->ctx_blks >= (BNX2_MAX_CID / cp->cids_per_blk)) {
+			cp->ctx_blks = 0;
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < cp->ctx_blks; i++) {
+			cp->ctx_arr[i].ctx =
+				pci_alloc_consistent(dev->pcidev, BCM_PAGE_SIZE,
+						     &cp->ctx_arr[i].mapping);
+			if (cp->ctx_arr[i].ctx == NULL)
+				return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct uio_info *uinfo;
+	int ret;
+
+	ret = cnic_alloc_dma(dev, &cp->kwq_info, KWQ_PAGE_CNT, 1);
+	if (ret)
+		goto error;
+	cp->kwq = (struct kwqe **) cp->kwq_info.pg_arr;
+
+	ret = cnic_alloc_dma(dev, &cp->kcq_info, KCQ_PAGE_CNT, 1);
+	if (ret)
+		goto error;
+	cp->kcq = (struct kcqe **) cp->kcq_info.pg_arr;
+
+	ret = cnic_alloc_context(dev);
+	if (ret)
+		goto error;
+
+	cp->l2_ring_size = 2 * BCM_PAGE_SIZE;
+	cp->l2_ring = pci_alloc_consistent(dev->pcidev, cp->l2_ring_size,
+					   &cp->l2_ring_map);
+	if (!cp->l2_ring)
+		goto error;
+
+	cp->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
+	cp->l2_buf_size = PAGE_ALIGN(cp->l2_buf_size);
+	cp->l2_buf = pci_alloc_consistent(dev->pcidev, cp->l2_buf_size,
+					   &cp->l2_buf_map);
+	if (!cp->l2_buf)
+		goto error;
+
+	uinfo = kzalloc(sizeof(*uinfo), GFP_ATOMIC);
+	if (!uinfo)
+		goto error;
+
+	uinfo->mem[0].addr = dev->netdev->base_addr;
+	uinfo->mem[0].internal_addr = dev->regview;
+	uinfo->mem[0].size = dev->netdev->mem_end - dev->netdev->mem_start;
+	uinfo->mem[0].memtype = UIO_MEM_PHYS;
+
+	uinfo->mem[1].addr = (unsigned long) cp->status_blk & PAGE_MASK;
+	if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
+		uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9;
+	else
+		uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE;
+	uinfo->mem[1].memtype = UIO_MEM_LOGICAL;
+
+	uinfo->mem[2].addr = (unsigned long) cp->l2_ring;
+	uinfo->mem[2].size = cp->l2_ring_size;
+	uinfo->mem[2].memtype = UIO_MEM_LOGICAL;
+
+	uinfo->mem[3].addr = (unsigned long) cp->l2_buf;
+	uinfo->mem[3].size = cp->l2_buf_size;
+	uinfo->mem[3].memtype = UIO_MEM_LOGICAL;
+
+	uinfo->name = "bnx2_cnic";
+	uinfo->version = CNIC_MODULE_VERSION;
+	uinfo->irq = UIO_IRQ_CUSTOM;
+
+	uinfo->open = cnic_uio_open;
+	uinfo->release = cnic_uio_close;
+
+	uinfo->priv = dev;
+
+	ret = uio_register_device(&dev->pcidev->dev, uinfo);
+	if (ret) {
+		kfree(uinfo);
+		goto error;
+	}
+
+	cp->cnic_uinfo = uinfo;
+
+	return 0;
+
+error:
+	cnic_free_resc(dev);
+	return ret;
+}
+
+static inline u32 cnic_kwq_avail(struct cnic_local *cp)
+{
+	return cp->max_kwq_idx -
+		((cp->kwq_prod_idx - cp->kwq_con_idx) & cp->max_kwq_idx);
+}
+
+static int cnic_submit_bnx2_kwqes(struct cnic_dev *dev, struct kwqe *wqes[],
+				  u32 num_wqes)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct kwqe *prod_qe;
+	u16 prod, sw_prod, i;
+
+	if (!test_bit(CNIC_F_CNIC_UP, &dev->flags))
+		return -EAGAIN;		/* bnx2 is down */
+
+	spin_lock_bh(&cp->cnic_ulp_lock);
+	if (num_wqes > cnic_kwq_avail(cp) &&
+	    !(cp->cnic_local_flags & CNIC_LCL_FL_KWQ_INIT)) {
+		spin_unlock_bh(&cp->cnic_ulp_lock);
+		return -EAGAIN;
+	}
+
+	cp->cnic_local_flags &= ~CNIC_LCL_FL_KWQ_INIT;
+
+	prod = cp->kwq_prod_idx;
+	sw_prod = prod & MAX_KWQ_IDX;
+	for (i = 0; i < num_wqes; i++) {
+		prod_qe = &cp->kwq[KWQ_PG(sw_prod)][KWQ_IDX(sw_prod)];
+		memcpy(prod_qe, wqes[i], sizeof(struct kwqe));
+		prod++;
+		sw_prod = prod & MAX_KWQ_IDX;
+	}
+	cp->kwq_prod_idx = prod;
+
+	CNIC_WR16(dev, cp->kwq_io_addr, cp->kwq_prod_idx);
+
+	spin_unlock_bh(&cp->cnic_ulp_lock);
+	return 0;
+}
+
+static void service_kcqes(struct cnic_dev *dev, int num_cqes)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int i, j;
+
+	i = 0;
+	j = 1;
+	while (num_cqes) {
+		struct cnic_ulp_ops *ulp_ops;
+		int ulp_type;
+		u32 kcqe_op_flag = cp->completed_kcq[i]->kcqe_op_flag;
+		u32 kcqe_layer = kcqe_op_flag & KCQE_FLAGS_LAYER_MASK;
+
+		if (unlikely(kcqe_op_flag & KCQE_RAMROD_COMPLETION))
+			cnic_kwq_completion(dev, 1);
+
+		while (j < num_cqes) {
+			u32 next_op = cp->completed_kcq[i + j]->kcqe_op_flag;
+
+			if ((next_op & KCQE_FLAGS_LAYER_MASK) != kcqe_layer)
+				break;
+
+			if (unlikely(next_op & KCQE_RAMROD_COMPLETION))
+				cnic_kwq_completion(dev, 1);
+			j++;
+		}
+
+		if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L5_RDMA)
+			ulp_type = CNIC_ULP_RDMA;
+		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L5_ISCSI)
+			ulp_type = CNIC_ULP_ISCSI;
+		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L4)
+			ulp_type = CNIC_ULP_L4;
+		else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L2)
+			goto end;
+		else {
+			printk(KERN_ERR PFX "%s: Unknown type of KCQE(0x%x)\n",
+			       dev->netdev->name, kcqe_op_flag);
+			goto end;
+		}
+
+		rcu_read_lock();
+		ulp_ops = rcu_dereference(cp->ulp_ops[ulp_type]);
+		if (likely(ulp_ops)) {
+			ulp_ops->indicate_kcqes(cp->ulp_handle[ulp_type],
+						  cp->completed_kcq + i, j);
+		}
+		rcu_read_unlock();
+end:
+		num_cqes -= j;
+		i += j;
+		j = 1;
+	}
+	return;
+}
+
+static u16 cnic_bnx2_next_idx(u16 idx)
+{
+	return idx + 1;
+}
+
+static u16 cnic_bnx2_hw_idx(u16 idx)
+{
+	return idx;
+}
+
+static int cnic_get_kcqes(struct cnic_dev *dev, u16 hw_prod, u16 *sw_prod)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	u16 i, ri, last;
+	struct kcqe *kcqe;
+	int kcqe_cnt = 0, last_cnt = 0;
+
+	i = ri = last = *sw_prod;
+	ri &= MAX_KCQ_IDX;
+
+	while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) {
+		kcqe = &cp->kcq[KCQ_PG(ri)][KCQ_IDX(ri)];
+		cp->completed_kcq[kcqe_cnt++] = kcqe;
+		i = cp->next_idx(i);
+		ri = i & MAX_KCQ_IDX;
+		if (likely(!(kcqe->kcqe_op_flag & KCQE_FLAGS_NEXT))) {
+			last_cnt = kcqe_cnt;
+			last = i;
+		}
+	}
+
+	*sw_prod = last;
+	return last_cnt;
+}
+
+static void cnic_chk_bnx2_pkt_rings(struct cnic_local *cp)
+{
+	u16 rx_cons = *cp->rx_cons_ptr;
+	u16 tx_cons = *cp->tx_cons_ptr;
+
+	if (cp->tx_cons != tx_cons || cp->rx_cons != rx_cons) {
+		cp->tx_cons = tx_cons;
+		cp->rx_cons = rx_cons;
+		uio_event_notify(cp->cnic_uinfo);
+	}
+}
+
+static int cnic_service_bnx2(void *data, void *status_blk)
+{
+	struct cnic_dev *dev = data;
+	struct status_block *sblk = status_blk;
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 status_idx = sblk->status_idx;
+	u16 hw_prod, sw_prod;
+	int kcqe_cnt;
+
+	if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
+		return status_idx;
+
+	cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
+
+	hw_prod = sblk->status_completion_producer_index;
+	sw_prod = cp->kcq_prod_idx;
+	while (sw_prod != hw_prod) {
+		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
+		if (kcqe_cnt == 0)
+			goto done;
+
+		service_kcqes(dev, kcqe_cnt);
+
+		/* Tell compiler that status_blk fields can change. */
+		barrier();
+		if (status_idx != sblk->status_idx) {
+			status_idx = sblk->status_idx;
+			cp->kwq_con_idx = *cp->kwq_con_idx_ptr;
+			hw_prod = sblk->status_completion_producer_index;
+		} else
+			break;
+	}
+
+done:
+	CNIC_WR16(dev, cp->kcq_io_addr, sw_prod);
+
+	cp->kcq_prod_idx = sw_prod;
+
+	cnic_chk_bnx2_pkt_rings(cp);
+	return status_idx;
+}
+
+static void cnic_service_bnx2_msix(unsigned long data)
+{
+	struct cnic_dev *dev = (struct cnic_dev *) data;
+	struct cnic_local *cp = dev->cnic_priv;
+	struct status_block_msix *status_blk = cp->bnx2_status_blk;
+	u32 status_idx = status_blk->status_idx;
+	u16 hw_prod, sw_prod;
+	int kcqe_cnt;
+
+	cp->kwq_con_idx = status_blk->status_cmd_consumer_index;
+
+	hw_prod = status_blk->status_completion_producer_index;
+	sw_prod = cp->kcq_prod_idx;
+	while (sw_prod != hw_prod) {
+		kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod);
+		if (kcqe_cnt == 0)
+			goto done;
+
+		service_kcqes(dev, kcqe_cnt);
+
+		/* Tell compiler that status_blk fields can change. */
+		barrier();
+		if (status_idx != status_blk->status_idx) {
+			status_idx = status_blk->status_idx;
+			cp->kwq_con_idx = status_blk->status_cmd_consumer_index;
+			hw_prod = status_blk->status_completion_producer_index;
+		} else
+			break;
+	}
+
+done:
+	CNIC_WR16(dev, cp->kcq_io_addr, sw_prod);
+	cp->kcq_prod_idx = sw_prod;
+
+	cnic_chk_bnx2_pkt_rings(cp);
+
+	cp->last_status_idx = status_idx;
+	CNIC_WR(dev, BNX2_PCICFG_INT_ACK_CMD, cp->int_num |
+		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
+}
+
+static irqreturn_t cnic_irq(int irq, void *dev_instance)
+{
+	struct cnic_dev *dev = dev_instance;
+	struct cnic_local *cp = dev->cnic_priv;
+	u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX;
+
+	if (cp->ack_int)
+		cp->ack_int(dev);
+
+	prefetch(cp->status_blk);
+	prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]);
+
+	if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags)))
+		tasklet_schedule(&cp->cnic_irq_task);
+
+	return IRQ_HANDLED;
+}
+
+static void cnic_ulp_stop(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int if_type;
+
+	if (cp->cnic_uinfo)
+		cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+
+	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
+		struct cnic_ulp_ops *ulp_ops;
+
+		mutex_lock(&cnic_lock);
+		ulp_ops = cp->ulp_ops[if_type];
+		if (!ulp_ops) {
+			mutex_unlock(&cnic_lock);
+			continue;
+		}
+		set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+		mutex_unlock(&cnic_lock);
+
+		if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type]))
+			ulp_ops->cnic_stop(cp->ulp_handle[if_type]);
+
+		clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+	}
+}
+
+static void cnic_ulp_start(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int if_type;
+
+	for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
+		struct cnic_ulp_ops *ulp_ops;
+
+		mutex_lock(&cnic_lock);
+		ulp_ops = cp->ulp_ops[if_type];
+		if (!ulp_ops || !ulp_ops->cnic_start) {
+			mutex_unlock(&cnic_lock);
+			continue;
+		}
+		set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+		mutex_unlock(&cnic_lock);
+
+		if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[if_type]))
+			ulp_ops->cnic_start(cp->ulp_handle[if_type]);
+
+		clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+	}
+}
+
+static int cnic_ctl(void *data, struct cnic_ctl_info *info)
+{
+	struct cnic_dev *dev = data;
+
+	switch (info->cmd) {
+	case CNIC_CTL_STOP_CMD:
+		cnic_hold(dev);
+
+		cnic_ulp_stop(dev);
+		cnic_stop_hw(dev);
+
+		cnic_put(dev);
+		break;
+	case CNIC_CTL_START_CMD:
+		cnic_hold(dev);
+
+		if (!cnic_start_hw(dev))
+			cnic_ulp_start(dev);
+
+		cnic_put(dev);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void cnic_ulp_init(struct cnic_dev *dev)
+{
+	int i;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) {
+		struct cnic_ulp_ops *ulp_ops;
+
+		mutex_lock(&cnic_lock);
+		ulp_ops = cnic_ulp_tbl[i];
+		if (!ulp_ops || !ulp_ops->cnic_init) {
+			mutex_unlock(&cnic_lock);
+			continue;
+		}
+		ulp_get(ulp_ops);
+		mutex_unlock(&cnic_lock);
+
+		if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[i]))
+			ulp_ops->cnic_init(dev);
+
+		ulp_put(ulp_ops);
+	}
+}
+
+static void cnic_ulp_exit(struct cnic_dev *dev)
+{
+	int i;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) {
+		struct cnic_ulp_ops *ulp_ops;
+
+		mutex_lock(&cnic_lock);
+		ulp_ops = cnic_ulp_tbl[i];
+		if (!ulp_ops || !ulp_ops->cnic_exit) {
+			mutex_unlock(&cnic_lock);
+			continue;
+		}
+		ulp_get(ulp_ops);
+		mutex_unlock(&cnic_lock);
+
+		if (test_and_clear_bit(ULP_F_INIT, &cp->ulp_flags[i]))
+			ulp_ops->cnic_exit(dev);
+
+		ulp_put(ulp_ops);
+	}
+}
+
+static int cnic_cm_offload_pg(struct cnic_sock *csk)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct l4_kwq_offload_pg *l4kwqe;
+	struct kwqe *wqes[1];
+
+	l4kwqe = (struct l4_kwq_offload_pg *) &csk->kwqe1;
+	memset(l4kwqe, 0, sizeof(*l4kwqe));
+	wqes[0] = (struct kwqe *) l4kwqe;
+
+	l4kwqe->op_code = L4_KWQE_OPCODE_VALUE_OFFLOAD_PG;
+	l4kwqe->flags =
+		L4_LAYER_CODE << L4_KWQ_OFFLOAD_PG_LAYER_CODE_SHIFT;
+	l4kwqe->l2hdr_nbytes = ETH_HLEN;
+
+	l4kwqe->da0 = csk->ha[0];
+	l4kwqe->da1 = csk->ha[1];
+	l4kwqe->da2 = csk->ha[2];
+	l4kwqe->da3 = csk->ha[3];
+	l4kwqe->da4 = csk->ha[4];
+	l4kwqe->da5 = csk->ha[5];
+
+	l4kwqe->sa0 = dev->mac_addr[0];
+	l4kwqe->sa1 = dev->mac_addr[1];
+	l4kwqe->sa2 = dev->mac_addr[2];
+	l4kwqe->sa3 = dev->mac_addr[3];
+	l4kwqe->sa4 = dev->mac_addr[4];
+	l4kwqe->sa5 = dev->mac_addr[5];
+
+	l4kwqe->etype = ETH_P_IP;
+	l4kwqe->ipid_count = DEF_IPID_COUNT;
+	l4kwqe->host_opaque = csk->l5_cid;
+
+	if (csk->vlan_id) {
+		l4kwqe->pg_flags |= L4_KWQ_OFFLOAD_PG_VLAN_TAGGING;
+		l4kwqe->vlan_tag = csk->vlan_id;
+		l4kwqe->l2hdr_nbytes += 4;
+	}
+
+	return dev->submit_kwqes(dev, wqes, 1);
+}
+
+static int cnic_cm_update_pg(struct cnic_sock *csk)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct l4_kwq_update_pg *l4kwqe;
+	struct kwqe *wqes[1];
+
+	l4kwqe = (struct l4_kwq_update_pg *) &csk->kwqe1;
+	memset(l4kwqe, 0, sizeof(*l4kwqe));
+	wqes[0] = (struct kwqe *) l4kwqe;
+
+	l4kwqe->opcode = L4_KWQE_OPCODE_VALUE_UPDATE_PG;
+	l4kwqe->flags =
+		L4_LAYER_CODE << L4_KWQ_UPDATE_PG_LAYER_CODE_SHIFT;
+	l4kwqe->pg_cid = csk->pg_cid;
+
+	l4kwqe->da0 = csk->ha[0];
+	l4kwqe->da1 = csk->ha[1];
+	l4kwqe->da2 = csk->ha[2];
+	l4kwqe->da3 = csk->ha[3];
+	l4kwqe->da4 = csk->ha[4];
+	l4kwqe->da5 = csk->ha[5];
+
+	l4kwqe->pg_host_opaque = csk->l5_cid;
+	l4kwqe->pg_valids = L4_KWQ_UPDATE_PG_VALIDS_DA;
+
+	return dev->submit_kwqes(dev, wqes, 1);
+}
+
+static int cnic_cm_upload_pg(struct cnic_sock *csk)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct l4_kwq_upload *l4kwqe;
+	struct kwqe *wqes[1];
+
+	l4kwqe = (struct l4_kwq_upload *) &csk->kwqe1;
+	memset(l4kwqe, 0, sizeof(*l4kwqe));
+	wqes[0] = (struct kwqe *) l4kwqe;
+
+	l4kwqe->opcode = L4_KWQE_OPCODE_VALUE_UPLOAD_PG;
+	l4kwqe->flags =
+		L4_LAYER_CODE << L4_KWQ_UPLOAD_LAYER_CODE_SHIFT;
+	l4kwqe->cid = csk->pg_cid;
+
+	return dev->submit_kwqes(dev, wqes, 1);
+}
+
+static int cnic_cm_conn_req(struct cnic_sock *csk)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct l4_kwq_connect_req1 *l4kwqe1;
+	struct l4_kwq_connect_req2 *l4kwqe2;
+	struct l4_kwq_connect_req3 *l4kwqe3;
+	struct kwqe *wqes[3];
+	u8 tcp_flags = 0;
+	int num_wqes = 2;
+
+	l4kwqe1 = (struct l4_kwq_connect_req1 *) &csk->kwqe1;
+	l4kwqe2 = (struct l4_kwq_connect_req2 *) &csk->kwqe2;
+	l4kwqe3 = (struct l4_kwq_connect_req3 *) &csk->kwqe3;
+	memset(l4kwqe1, 0, sizeof(*l4kwqe1));
+	memset(l4kwqe2, 0, sizeof(*l4kwqe2));
+	memset(l4kwqe3, 0, sizeof(*l4kwqe3));
+
+	l4kwqe3->op_code = L4_KWQE_OPCODE_VALUE_CONNECT3;
+	l4kwqe3->flags =
+		L4_LAYER_CODE << L4_KWQ_CONNECT_REQ3_LAYER_CODE_SHIFT;
+	l4kwqe3->ka_timeout = csk->ka_timeout;
+	l4kwqe3->ka_interval = csk->ka_interval;
+	l4kwqe3->ka_max_probe_count = csk->ka_max_probe_count;
+	l4kwqe3->tos = csk->tos;
+	l4kwqe3->ttl = csk->ttl;
+	l4kwqe3->snd_seq_scale = csk->snd_seq_scale;
+	l4kwqe3->pmtu = csk->mtu;
+	l4kwqe3->rcv_buf = csk->rcv_buf;
+	l4kwqe3->snd_buf = csk->snd_buf;
+	l4kwqe3->seed = csk->seed;
+
+	wqes[0] = (struct kwqe *) l4kwqe1;
+	if (test_bit(SK_F_IPV6, &csk->flags)) {
+		wqes[1] = (struct kwqe *) l4kwqe2;
+		wqes[2] = (struct kwqe *) l4kwqe3;
+		num_wqes = 3;
+
+		l4kwqe1->conn_flags = L4_KWQ_CONNECT_REQ1_IP_V6;
+		l4kwqe2->op_code = L4_KWQE_OPCODE_VALUE_CONNECT2;
+		l4kwqe2->flags =
+			L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT |
+			L4_LAYER_CODE << L4_KWQ_CONNECT_REQ2_LAYER_CODE_SHIFT;
+		l4kwqe2->src_ip_v6_2 = be32_to_cpu(csk->src_ip[1]);
+		l4kwqe2->src_ip_v6_3 = be32_to_cpu(csk->src_ip[2]);
+		l4kwqe2->src_ip_v6_4 = be32_to_cpu(csk->src_ip[3]);
+		l4kwqe2->dst_ip_v6_2 = be32_to_cpu(csk->dst_ip[1]);
+		l4kwqe2->dst_ip_v6_3 = be32_to_cpu(csk->dst_ip[2]);
+		l4kwqe2->dst_ip_v6_4 = be32_to_cpu(csk->dst_ip[3]);
+		l4kwqe3->mss = l4kwqe3->pmtu - sizeof(struct ipv6hdr) -
+			       sizeof(struct tcphdr);
+	} else {
+		wqes[1] = (struct kwqe *) l4kwqe3;
+		l4kwqe3->mss = l4kwqe3->pmtu - sizeof(struct iphdr) -
+			       sizeof(struct tcphdr);
+	}
+
+	l4kwqe1->op_code = L4_KWQE_OPCODE_VALUE_CONNECT1;
+	l4kwqe1->flags =
+		(L4_LAYER_CODE << L4_KWQ_CONNECT_REQ1_LAYER_CODE_SHIFT) |
+		 L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT;
+	l4kwqe1->cid = csk->cid;
+	l4kwqe1->pg_cid = csk->pg_cid;
+	l4kwqe1->src_ip = be32_to_cpu(csk->src_ip[0]);
+	l4kwqe1->dst_ip = be32_to_cpu(csk->dst_ip[0]);
+	l4kwqe1->src_port = be16_to_cpu(csk->src_port);
+	l4kwqe1->dst_port = be16_to_cpu(csk->dst_port);
+	if (csk->tcp_flags & SK_TCP_NO_DELAY_ACK)
+		tcp_flags |= L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK;
+	if (csk->tcp_flags & SK_TCP_KEEP_ALIVE)
+		tcp_flags |= L4_KWQ_CONNECT_REQ1_KEEP_ALIVE;
+	if (csk->tcp_flags & SK_TCP_NAGLE)
+		tcp_flags |= L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE;
+	if (csk->tcp_flags & SK_TCP_TIMESTAMP)
+		tcp_flags |= L4_KWQ_CONNECT_REQ1_TIME_STAMP;
+	if (csk->tcp_flags & SK_TCP_SACK)
+		tcp_flags |= L4_KWQ_CONNECT_REQ1_SACK;
+	if (csk->tcp_flags & SK_TCP_SEG_SCALING)
+		tcp_flags |= L4_KWQ_CONNECT_REQ1_SEG_SCALING;
+
+	l4kwqe1->tcp_flags = tcp_flags;
+
+	return dev->submit_kwqes(dev, wqes, num_wqes);
+}
+
+static int cnic_cm_close_req(struct cnic_sock *csk)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct l4_kwq_close_req *l4kwqe;
+	struct kwqe *wqes[1];
+
+	l4kwqe = (struct l4_kwq_close_req *) &csk->kwqe2;
+	memset(l4kwqe, 0, sizeof(*l4kwqe));
+	wqes[0] = (struct kwqe *) l4kwqe;
+
+	l4kwqe->op_code = L4_KWQE_OPCODE_VALUE_CLOSE;
+	l4kwqe->flags = L4_LAYER_CODE << L4_KWQ_CLOSE_REQ_LAYER_CODE_SHIFT;
+	l4kwqe->cid = csk->cid;
+
+	return dev->submit_kwqes(dev, wqes, 1);
+}
+
+static int cnic_cm_abort_req(struct cnic_sock *csk)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct l4_kwq_reset_req *l4kwqe;
+	struct kwqe *wqes[1];
+
+	l4kwqe = (struct l4_kwq_reset_req *) &csk->kwqe2;
+	memset(l4kwqe, 0, sizeof(*l4kwqe));
+	wqes[0] = (struct kwqe *) l4kwqe;
+
+	l4kwqe->op_code = L4_KWQE_OPCODE_VALUE_RESET;
+	l4kwqe->flags = L4_LAYER_CODE << L4_KWQ_RESET_REQ_LAYER_CODE_SHIFT;
+	l4kwqe->cid = csk->cid;
+
+	return dev->submit_kwqes(dev, wqes, 1);
+}
+
+static int cnic_cm_create(struct cnic_dev *dev, int ulp_type, u32 cid,
+			  u32 l5_cid, struct cnic_sock **csk, void *context)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_sock *csk1;
+
+	if (l5_cid >= MAX_CM_SK_TBL_SZ)
+		return -EINVAL;
+
+	csk1 = &cp->csk_tbl[l5_cid];
+	if (atomic_read(&csk1->ref_count))
+		return -EAGAIN;
+
+	if (test_and_set_bit(SK_F_INUSE, &csk1->flags))
+		return -EBUSY;
+
+	csk1->dev = dev;
+	csk1->cid = cid;
+	csk1->l5_cid = l5_cid;
+	csk1->ulp_type = ulp_type;
+	csk1->context = context;
+
+	csk1->ka_timeout = DEF_KA_TIMEOUT;
+	csk1->ka_interval = DEF_KA_INTERVAL;
+	csk1->ka_max_probe_count = DEF_KA_MAX_PROBE_COUNT;
+	csk1->tos = DEF_TOS;
+	csk1->ttl = DEF_TTL;
+	csk1->snd_seq_scale = DEF_SND_SEQ_SCALE;
+	csk1->rcv_buf = DEF_RCV_BUF;
+	csk1->snd_buf = DEF_SND_BUF;
+	csk1->seed = DEF_SEED;
+
+	*csk = csk1;
+	return 0;
+}
+
+static void cnic_cm_cleanup(struct cnic_sock *csk)
+{
+	if (csk->src_port) {
+		struct cnic_dev *dev = csk->dev;
+		struct cnic_local *cp = dev->cnic_priv;
+
+		cnic_free_id(&cp->csk_port_tbl, csk->src_port);
+		csk->src_port = 0;
+	}
+}
+
+static void cnic_close_conn(struct cnic_sock *csk)
+{
+	if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) {
+		cnic_cm_upload_pg(csk);
+		clear_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags);
+	}
+	cnic_cm_cleanup(csk);
+}
+
+static int cnic_cm_destroy(struct cnic_sock *csk)
+{
+	if (!cnic_in_use(csk))
+		return -EINVAL;
+
+	csk_hold(csk);
+	clear_bit(SK_F_INUSE, &csk->flags);
+	smp_mb__after_clear_bit();
+	while (atomic_read(&csk->ref_count) != 1)
+		msleep(1);
+	cnic_cm_cleanup(csk);
+
+	csk->flags = 0;
+	csk_put(csk);
+	return 0;
+}
+
+static inline u16 cnic_get_vlan(struct net_device *dev,
+				struct net_device **vlan_dev)
+{
+	if (dev->priv_flags & IFF_802_1Q_VLAN) {
+		*vlan_dev = vlan_dev_real_dev(dev);
+		return vlan_dev_vlan_id(dev);
+	}
+	*vlan_dev = dev;
+	return 0;
+}
+
+static int cnic_get_v4_route(struct sockaddr_in *dst_addr,
+			     struct dst_entry **dst)
+{
+#if defined(CONFIG_INET)
+	struct flowi fl;
+	int err;
+	struct rtable *rt;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.nl_u.ip4_u.daddr = dst_addr->sin_addr.s_addr;
+
+	err = ip_route_output_key(&init_net, &rt, &fl);
+	if (!err)
+		*dst = &rt->u.dst;
+	return err;
+#else
+	return -ENETUNREACH;
+#endif
+}
+
+static int cnic_get_v6_route(struct sockaddr_in6 *dst_addr,
+			     struct dst_entry **dst)
+{
+#if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE))
+	struct flowi fl;
+
+	memset(&fl, 0, sizeof(fl));
+	ipv6_addr_copy(&fl.fl6_dst, &dst_addr->sin6_addr);
+	if (ipv6_addr_type(&fl.fl6_dst) & IPV6_ADDR_LINKLOCAL)
+		fl.oif = dst_addr->sin6_scope_id;
+
+	*dst = ip6_route_output(&init_net, NULL, &fl);
+	if (*dst)
+		return 0;
+#endif
+
+	return -ENETUNREACH;
+}
+
+static struct cnic_dev *cnic_cm_select_dev(struct sockaddr_in *dst_addr,
+					   int ulp_type)
+{
+	struct cnic_dev *dev = NULL;
+	struct dst_entry *dst;
+	struct net_device *netdev = NULL;
+	int err = -ENETUNREACH;
+
+	if (dst_addr->sin_family == AF_INET)
+		err = cnic_get_v4_route(dst_addr, &dst);
+	else if (dst_addr->sin_family == AF_INET6) {
+		struct sockaddr_in6 *dst_addr6 =
+			(struct sockaddr_in6 *) dst_addr;
+
+		err = cnic_get_v6_route(dst_addr6, &dst);
+	} else
+		return NULL;
+
+	if (err)
+		return NULL;
+
+	if (!dst->dev)
+		goto done;
+
+	cnic_get_vlan(dst->dev, &netdev);
+
+	dev = cnic_from_netdev(netdev);
+
+done:
+	dst_release(dst);
+	if (dev)
+		cnic_put(dev);
+	return dev;
+}
+
+static int cnic_resolve_addr(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	return cnic_send_nlmsg(cp, ISCSI_KEVENT_PATH_REQ, csk);
+}
+
+static int cnic_get_route(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct cnic_local *cp = dev->cnic_priv;
+	int is_v6, err, rc = -ENETUNREACH;
+	struct dst_entry *dst;
+	struct net_device *realdev;
+	u32 local_port;
+
+	if (saddr->local.v6.sin6_family == AF_INET6 &&
+	    saddr->remote.v6.sin6_family == AF_INET6)
+		is_v6 = 1;
+	else if (saddr->local.v4.sin_family == AF_INET &&
+		 saddr->remote.v4.sin_family == AF_INET)
+		is_v6 = 0;
+	else
+		return -EINVAL;
+
+	clear_bit(SK_F_IPV6, &csk->flags);
+
+	if (is_v6) {
+#if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE))
+		set_bit(SK_F_IPV6, &csk->flags);
+		err = cnic_get_v6_route(&saddr->remote.v6, &dst);
+		if (err)
+			return err;
+
+		if (!dst || dst->error || !dst->dev)
+			goto err_out;
+
+		memcpy(&csk->dst_ip[0], &saddr->remote.v6.sin6_addr,
+		       sizeof(struct in6_addr));
+		csk->dst_port = saddr->remote.v6.sin6_port;
+		local_port = saddr->local.v6.sin6_port;
+#else
+		return rc;
+#endif
+
+	} else {
+		err = cnic_get_v4_route(&saddr->remote.v4, &dst);
+		if (err)
+			return err;
+
+		if (!dst || dst->error || !dst->dev)
+			goto err_out;
+
+		csk->dst_ip[0] = saddr->remote.v4.sin_addr.s_addr;
+		csk->dst_port = saddr->remote.v4.sin_port;
+		local_port = saddr->local.v4.sin_port;
+	}
+
+	csk->vlan_id = cnic_get_vlan(dst->dev, &realdev);
+	if (realdev != dev->netdev)
+		goto err_out;
+
+	if (local_port >= CNIC_LOCAL_PORT_MIN &&
+	    local_port < CNIC_LOCAL_PORT_MAX) {
+		if (cnic_alloc_id(&cp->csk_port_tbl, local_port))
+			local_port = 0;
+	} else
+		local_port = 0;
+
+	if (!local_port) {
+		local_port = cnic_alloc_new_id(&cp->csk_port_tbl);
+		if (local_port == -1) {
+			rc = -ENOMEM;
+			goto err_out;
+		}
+	}
+	csk->src_port = local_port;
+
+	csk->mtu = dst_mtu(dst);
+	rc = 0;
+
+err_out:
+	dst_release(dst);
+	return rc;
+}
+
+static void cnic_init_csk_state(struct cnic_sock *csk)
+{
+	csk->state = 0;
+	clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
+	clear_bit(SK_F_CLOSING, &csk->flags);
+}
+
+static int cnic_cm_connect(struct cnic_sock *csk, struct cnic_sockaddr *saddr)
+{
+	int err = 0;
+
+	if (!cnic_in_use(csk))
+		return -EINVAL;
+
+	if (test_and_set_bit(SK_F_CONNECT_START, &csk->flags))
+		return -EINVAL;
+
+	cnic_init_csk_state(csk);
+
+	err = cnic_get_route(csk, saddr);
+	if (err)
+		goto err_out;
+
+	err = cnic_resolve_addr(csk, saddr);
+	if (!err)
+		return 0;
+
+err_out:
+	clear_bit(SK_F_CONNECT_START, &csk->flags);
+	return err;
+}
+
+static int cnic_cm_abort(struct cnic_sock *csk)
+{
+	struct cnic_local *cp = csk->dev->cnic_priv;
+	u32 opcode;
+
+	if (!cnic_in_use(csk))
+		return -EINVAL;
+
+	if (cnic_abort_prep(csk))
+		return cnic_cm_abort_req(csk);
+
+	/* Getting here means that we haven't started connect, or
+	 * connect was not successful.
+	 */
+
+	csk->state = L4_KCQE_OPCODE_VALUE_RESET_COMP;
+	if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
+		opcode = csk->state;
+	else
+		opcode = L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD;
+	cp->close_conn(csk, opcode);
+
+	return 0;
+}
+
+static int cnic_cm_close(struct cnic_sock *csk)
+{
+	if (!cnic_in_use(csk))
+		return -EINVAL;
+
+	if (cnic_close_prep(csk)) {
+		csk->state = L4_KCQE_OPCODE_VALUE_CLOSE_COMP;
+		return cnic_cm_close_req(csk);
+	}
+	return 0;
+}
+
+static void cnic_cm_upcall(struct cnic_local *cp, struct cnic_sock *csk,
+			   u8 opcode)
+{
+	struct cnic_ulp_ops *ulp_ops;
+	int ulp_type = csk->ulp_type;
+
+	rcu_read_lock();
+	ulp_ops = rcu_dereference(cp->ulp_ops[ulp_type]);
+	if (ulp_ops) {
+		if (opcode == L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE)
+			ulp_ops->cm_connect_complete(csk);
+		else if (opcode == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)
+			ulp_ops->cm_close_complete(csk);
+		else if (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED)
+			ulp_ops->cm_remote_abort(csk);
+		else if (opcode == L4_KCQE_OPCODE_VALUE_RESET_COMP)
+			ulp_ops->cm_abort_complete(csk);
+		else if (opcode == L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED)
+			ulp_ops->cm_remote_close(csk);
+	}
+	rcu_read_unlock();
+}
+
+static int cnic_cm_set_pg(struct cnic_sock *csk)
+{
+	if (cnic_offld_prep(csk)) {
+		if (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
+			cnic_cm_update_pg(csk);
+		else
+			cnic_cm_offload_pg(csk);
+	}
+	return 0;
+}
+
+static void cnic_cm_process_offld_pg(struct cnic_dev *dev, struct l4_kcq *kcqe)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 l5_cid = kcqe->pg_host_opaque;
+	u8 opcode = kcqe->op_code;
+	struct cnic_sock *csk = &cp->csk_tbl[l5_cid];
+
+	csk_hold(csk);
+	if (!cnic_in_use(csk))
+		goto done;
+
+	if (opcode == L4_KCQE_OPCODE_VALUE_UPDATE_PG) {
+		clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
+		goto done;
+	}
+	csk->pg_cid = kcqe->pg_cid;
+	set_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags);
+	cnic_cm_conn_req(csk);
+
+done:
+	csk_put(csk);
+}
+
+static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct l4_kcq *l4kcqe = (struct l4_kcq *) kcqe;
+	u8 opcode = l4kcqe->op_code;
+	u32 l5_cid;
+	struct cnic_sock *csk;
+
+	if (opcode == L4_KCQE_OPCODE_VALUE_OFFLOAD_PG ||
+	    opcode == L4_KCQE_OPCODE_VALUE_UPDATE_PG) {
+		cnic_cm_process_offld_pg(dev, l4kcqe);
+		return;
+	}
+
+	l5_cid = l4kcqe->conn_id;
+	if (opcode & 0x80)
+		l5_cid = l4kcqe->cid;
+	if (l5_cid >= MAX_CM_SK_TBL_SZ)
+		return;
+
+	csk = &cp->csk_tbl[l5_cid];
+	csk_hold(csk);
+
+	if (!cnic_in_use(csk)) {
+		csk_put(csk);
+		return;
+	}
+
+	switch (opcode) {
+	case L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE:
+		if (l4kcqe->status == 0)
+			set_bit(SK_F_OFFLD_COMPLETE, &csk->flags);
+
+		smp_mb__before_clear_bit();
+		clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
+		cnic_cm_upcall(cp, csk, opcode);
+		break;
+
+	case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED:
+		if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags))
+			csk->state = opcode;
+		/* fall through */
+	case L4_KCQE_OPCODE_VALUE_CLOSE_COMP:
+	case L4_KCQE_OPCODE_VALUE_RESET_COMP:
+		cp->close_conn(csk, opcode);
+		break;
+
+	case L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED:
+		cnic_cm_upcall(cp, csk, opcode);
+		break;
+	}
+	csk_put(csk);
+}
+
+static void cnic_cm_indicate_kcqe(void *data, struct kcqe *kcqe[], u32 num)
+{
+	struct cnic_dev *dev = data;
+	int i;
+
+	for (i = 0; i < num; i++)
+		cnic_cm_process_kcqe(dev, kcqe[i]);
+}
+
+static struct cnic_ulp_ops cm_ulp_ops = {
+	.indicate_kcqes		= cnic_cm_indicate_kcqe,
+};
+
+static void cnic_cm_free_mem(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+
+	kfree(cp->csk_tbl);
+	cp->csk_tbl = NULL;
+	cnic_free_id_tbl(&cp->csk_port_tbl);
+}
+
+static int cnic_cm_alloc_mem(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+
+	cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ,
+			      GFP_KERNEL);
+	if (!cp->csk_tbl)
+		return -ENOMEM;
+
+	if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE,
+			     CNIC_LOCAL_PORT_MIN)) {
+		cnic_cm_free_mem(dev);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode)
+{
+	if ((opcode == csk->state) ||
+	    (opcode == L4_KCQE_OPCODE_VALUE_RESET_RECEIVED &&
+	     csk->state == L4_KCQE_OPCODE_VALUE_CLOSE_COMP)) {
+		if (!test_and_set_bit(SK_F_CLOSING, &csk->flags))
+			return 1;
+	}
+	return 0;
+}
+
+static void cnic_close_bnx2_conn(struct cnic_sock *csk, u32 opcode)
+{
+	struct cnic_dev *dev = csk->dev;
+	struct cnic_local *cp = dev->cnic_priv;
+
+	clear_bit(SK_F_CONNECT_START, &csk->flags);
+	if (cnic_ready_to_close(csk, opcode)) {
+		cnic_close_conn(csk);
+		cnic_cm_upcall(cp, csk, opcode);
+	}
+}
+
+static void cnic_cm_stop_bnx2_hw(struct cnic_dev *dev)
+{
+}
+
+static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev)
+{
+	u32 seed;
+
+	get_random_bytes(&seed, 4);
+	cnic_ctx_wr(dev, 45, 0, seed);
+	return 0;
+}
+
+static int cnic_cm_open(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int err;
+
+	err = cnic_cm_alloc_mem(dev);
+	if (err)
+		return err;
+
+	err = cp->start_cm(dev);
+
+	if (err)
+		goto err_out;
+
+	dev->cm_create = cnic_cm_create;
+	dev->cm_destroy = cnic_cm_destroy;
+	dev->cm_connect = cnic_cm_connect;
+	dev->cm_abort = cnic_cm_abort;
+	dev->cm_close = cnic_cm_close;
+	dev->cm_select_dev = cnic_cm_select_dev;
+
+	cp->ulp_handle[CNIC_ULP_L4] = dev;
+	rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], &cm_ulp_ops);
+	return 0;
+
+err_out:
+	cnic_cm_free_mem(dev);
+	return err;
+}
+
+static int cnic_cm_shutdown(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int i;
+
+	cp->stop_cm(dev);
+
+	if (!cp->csk_tbl)
+		return 0;
+
+	for (i = 0; i < MAX_CM_SK_TBL_SZ; i++) {
+		struct cnic_sock *csk = &cp->csk_tbl[i];
+
+		clear_bit(SK_F_INUSE, &csk->flags);
+		cnic_cm_cleanup(csk);
+	}
+	cnic_cm_free_mem(dev);
+
+	return 0;
+}
+
+static void cnic_init_context(struct cnic_dev *dev, u32 cid)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 cid_addr;
+	int i;
+
+	if (CHIP_NUM(cp) == CHIP_NUM_5709)
+		return;
+
+	cid_addr = GET_CID_ADDR(cid);
+
+	for (i = 0; i < CTX_SIZE; i += 4)
+		cnic_ctx_wr(dev, cid_addr, i, 0);
+}
+
+static int cnic_setup_5709_context(struct cnic_dev *dev, int valid)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	int ret = 0, i;
+	u32 valid_bit = valid ? BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID : 0;
+
+	if (CHIP_NUM(cp) != CHIP_NUM_5709)
+		return 0;
+
+	for (i = 0; i < cp->ctx_blks; i++) {
+		int j;
+		u32 idx = cp->ctx_arr[i].cid / cp->cids_per_blk;
+		u32 val;
+
+		memset(cp->ctx_arr[i].ctx, 0, BCM_PAGE_SIZE);
+
+		CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA0,
+			(cp->ctx_arr[i].mapping & 0xffffffff) | valid_bit);
+		CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA1,
+			(u64) cp->ctx_arr[i].mapping >> 32);
+		CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_CTRL, idx |
+			BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
+		for (j = 0; j < 10; j++) {
+
+			val = CNIC_RD(dev, BNX2_CTX_HOST_PAGE_TBL_CTRL);
+			if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ))
+				break;
+			udelay(5);
+		}
+		if (val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) {
+			ret = -EBUSY;
+			break;
+		}
+	}
+	return ret;
+}
+
+static void cnic_free_irq(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+
+	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
+		cp->disable_int_sync(dev);
+		tasklet_disable(&cp->cnic_irq_task);
+		free_irq(ethdev->irq_arr[0].vector, dev);
+	}
+}
+
+static int cnic_init_bnx2_irq(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+
+	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
+		int err, i = 0;
+		int sblk_num = cp->status_blk_num;
+		u32 base = ((sblk_num - 1) * BNX2_HC_SB_CONFIG_SIZE) +
+			   BNX2_HC_SB_CONFIG_1;
+
+		CNIC_WR(dev, base, BNX2_HC_SB_CONFIG_1_ONE_SHOT);
+
+		CNIC_WR(dev, base + BNX2_HC_COMP_PROD_TRIP_OFF, (2 << 16) | 8);
+		CNIC_WR(dev, base + BNX2_HC_COM_TICKS_OFF, (64 << 16) | 220);
+		CNIC_WR(dev, base + BNX2_HC_CMD_TICKS_OFF, (64 << 16) | 220);
+
+		cp->bnx2_status_blk = cp->status_blk;
+		cp->last_status_idx = cp->bnx2_status_blk->status_idx;
+		tasklet_init(&cp->cnic_irq_task, &cnic_service_bnx2_msix,
+			     (unsigned long) dev);
+		err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0,
+				  "cnic", dev);
+		if (err) {
+			tasklet_disable(&cp->cnic_irq_task);
+			return err;
+		}
+		while (cp->bnx2_status_blk->status_completion_producer_index &&
+		       i < 10) {
+			CNIC_WR(dev, BNX2_HC_COALESCE_NOW,
+				1 << (11 + sblk_num));
+			udelay(10);
+			i++;
+			barrier();
+		}
+		if (cp->bnx2_status_blk->status_completion_producer_index) {
+			cnic_free_irq(dev);
+			goto failed;
+		}
+
+	} else {
+		struct status_block *sblk = cp->status_blk;
+		u32 hc_cmd = CNIC_RD(dev, BNX2_HC_COMMAND);
+		int i = 0;
+
+		while (sblk->status_completion_producer_index && i < 10) {
+			CNIC_WR(dev, BNX2_HC_COMMAND,
+				hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+			udelay(10);
+			i++;
+			barrier();
+		}
+		if (sblk->status_completion_producer_index)
+			goto failed;
+
+	}
+	return 0;
+
+failed:
+	printk(KERN_ERR PFX "%s: " "KCQ index not resetting to 0.\n",
+	       dev->netdev->name);
+	return -EBUSY;
+}
+
+static void cnic_enable_bnx2_int(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+
+	if (!(ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX))
+		return;
+
+	CNIC_WR(dev, BNX2_PCICFG_INT_ACK_CMD, cp->int_num |
+		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
+}
+
+static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+
+	if (!(ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX))
+		return;
+
+	CNIC_WR(dev, BNX2_PCICFG_INT_ACK_CMD, cp->int_num |
+		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+	CNIC_RD(dev, BNX2_PCICFG_INT_ACK_CMD);
+	synchronize_irq(ethdev->irq_arr[0].vector);
+}
+
+static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	u32 cid_addr, tx_cid, sb_id;
+	u32 val, offset0, offset1, offset2, offset3;
+	int i;
+	struct tx_bd *txbd;
+	dma_addr_t buf_map;
+	struct status_block *s_blk = cp->status_blk;
+
+	sb_id = cp->status_blk_num;
+	tx_cid = 20;
+	cnic_init_context(dev, tx_cid);
+	cnic_init_context(dev, tx_cid + 1);
+	cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2;
+	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
+		struct status_block_msix *sblk = cp->status_blk;
+
+		tx_cid = TX_TSS_CID + sb_id - 1;
+		cnic_init_context(dev, tx_cid);
+		CNIC_WR(dev, BNX2_TSCH_TSS_CFG, (sb_id << 24) |
+			(TX_TSS_CID << 7));
+		cp->tx_cons_ptr = &sblk->status_tx_quick_consumer_index;
+	}
+	cp->tx_cons = *cp->tx_cons_ptr;
+
+	cid_addr = GET_CID_ADDR(tx_cid);
+	if (CHIP_NUM(cp) == CHIP_NUM_5709) {
+		u32 cid_addr2 = GET_CID_ADDR(tx_cid + 4) + 0x40;
+
+		for (i = 0; i < PHY_CTX_SIZE; i += 4)
+			cnic_ctx_wr(dev, cid_addr2, i, 0);
+
+		offset0 = BNX2_L2CTX_TYPE_XI;
+		offset1 = BNX2_L2CTX_CMD_TYPE_XI;
+		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
+		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI;
+	} else {
+		offset0 = BNX2_L2CTX_TYPE;
+		offset1 = BNX2_L2CTX_CMD_TYPE;
+		offset2 = BNX2_L2CTX_TBDR_BHADDR_HI;
+		offset3 = BNX2_L2CTX_TBDR_BHADDR_LO;
+	}
+	val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2;
+	cnic_ctx_wr(dev, cid_addr, offset0, val);
+
+	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
+	cnic_ctx_wr(dev, cid_addr, offset1, val);
+
+	txbd = (struct tx_bd *) cp->l2_ring;
+
+	buf_map = cp->l2_buf_map;
+	for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
+		txbd->tx_bd_haddr_hi = (u64) buf_map >> 32;
+		txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
+	}
+	val = (u64) cp->l2_ring_map >> 32;
+	cnic_ctx_wr(dev, cid_addr, offset2, val);
+	txbd->tx_bd_haddr_hi = val;
+
+	val = (u64) cp->l2_ring_map & 0xffffffff;
+	cnic_ctx_wr(dev, cid_addr, offset3, val);
+	txbd->tx_bd_haddr_lo = val;
+}
+
+static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	u32 cid_addr, sb_id, val, coal_reg, coal_val;
+	int i;
+	struct rx_bd *rxbd;
+	struct status_block *s_blk = cp->status_blk;
+
+	sb_id = cp->status_blk_num;
+	cnic_init_context(dev, 2);
+	cp->rx_cons_ptr = &s_blk->status_rx_quick_consumer_index2;
+	coal_reg = BNX2_HC_COMMAND;
+	coal_val = CNIC_RD(dev, coal_reg);
+	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
+		struct status_block_msix *sblk = cp->status_blk;
+
+		cp->rx_cons_ptr = &sblk->status_rx_quick_consumer_index;
+		coal_reg = BNX2_HC_COALESCE_NOW;
+		coal_val = 1 << (11 + sb_id);
+	}
+	i = 0;
+	while (!(*cp->rx_cons_ptr != 0) && i < 10) {
+		CNIC_WR(dev, coal_reg, coal_val);
+		udelay(10);
+		i++;
+		barrier();
+	}
+	cp->rx_cons = *cp->rx_cons_ptr;
+
+	cid_addr = GET_CID_ADDR(2);
+	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE |
+	      BNX2_L2CTX_CTX_TYPE_SIZE_L2 | (0x02 << 8);
+	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_CTX_TYPE, val);
+
+	if (sb_id == 0)
+		val = 2 << BNX2_L2CTX_STATUSB_NUM_SHIFT;
+	else
+		val = BNX2_L2CTX_STATUSB_NUM(sb_id);
+	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
+
+	rxbd = (struct rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE);
+	for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
+		dma_addr_t buf_map;
+		int n = (i % cp->l2_rx_ring_size) + 1;
+
+		buf_map = cp->l2_buf_map + (n * cp->l2_single_buf_size);
+		rxbd->rx_bd_len = cp->l2_single_buf_size;
+		rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
+		rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32;
+		rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
+	}
+	val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) >> 32;
+	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
+	rxbd->rx_bd_haddr_hi = val;
+
+	val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+	cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
+	rxbd->rx_bd_haddr_lo = val;
+
+	val = cnic_reg_rd_ind(dev, BNX2_RXP_SCRATCH_RXP_FLOOD);
+	cnic_reg_wr_ind(dev, BNX2_RXP_SCRATCH_RXP_FLOOD, val | (1 << 2));
+}
+
+static void cnic_shutdown_bnx2_rx_ring(struct cnic_dev *dev)
+{
+	struct kwqe *wqes[1], l2kwqe;
+
+	memset(&l2kwqe, 0, sizeof(l2kwqe));
+	wqes[0] = &l2kwqe;
+	l2kwqe.kwqe_op_flag = (L2_LAYER_CODE << KWQE_FLAGS_LAYER_SHIFT) |
+			      (L2_KWQE_OPCODE_VALUE_FLUSH <<
+			       KWQE_OPCODE_SHIFT) | 2;
+	dev->submit_kwqes(dev, wqes, 1);
+}
+
+static void cnic_set_bnx2_mac(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	u32 val;
+
+	val = cp->func << 2;
+
+	cp->shmem_base = cnic_reg_rd_ind(dev, BNX2_SHM_HDR_ADDR_0 + val);
+
+	val = cnic_reg_rd_ind(dev, cp->shmem_base +
+			      BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER);
+	dev->mac_addr[0] = (u8) (val >> 8);
+	dev->mac_addr[1] = (u8) val;
+
+	CNIC_WR(dev, BNX2_EMAC_MAC_MATCH4, val);
+
+	val = cnic_reg_rd_ind(dev, cp->shmem_base +
+			      BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER);
+	dev->mac_addr[2] = (u8) (val >> 24);
+	dev->mac_addr[3] = (u8) (val >> 16);
+	dev->mac_addr[4] = (u8) (val >> 8);
+	dev->mac_addr[5] = (u8) val;
+
+	CNIC_WR(dev, BNX2_EMAC_MAC_MATCH5, val);
+
+	val = 4 | BNX2_RPM_SORT_USER2_BC_EN;
+	if (CHIP_NUM(cp) != CHIP_NUM_5709)
+		val |= BNX2_RPM_SORT_USER2_PROM_VLAN;
+
+	CNIC_WR(dev, BNX2_RPM_SORT_USER2, 0x0);
+	CNIC_WR(dev, BNX2_RPM_SORT_USER2, val);
+	CNIC_WR(dev, BNX2_RPM_SORT_USER2, val | BNX2_RPM_SORT_USER2_ENA);
+}
+
+static int cnic_start_bnx2_hw(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	struct status_block *sblk = cp->status_blk;
+	u32 val;
+	int err;
+
+	cnic_set_bnx2_mac(dev);
+
+	val = CNIC_RD(dev, BNX2_MQ_CONFIG);
+	val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
+	if (BCM_PAGE_BITS > 12)
+		val |= (12 - 8)  << 4;
+	else
+		val |= (BCM_PAGE_BITS - 8)  << 4;
+
+	CNIC_WR(dev, BNX2_MQ_CONFIG, val);
+
+	CNIC_WR(dev, BNX2_HC_COMP_PROD_TRIP, (2 << 16) | 8);
+	CNIC_WR(dev, BNX2_HC_COM_TICKS, (64 << 16) | 220);
+	CNIC_WR(dev, BNX2_HC_CMD_TICKS, (64 << 16) | 220);
+
+	err = cnic_setup_5709_context(dev, 1);
+	if (err)
+		return err;
+
+	cnic_init_context(dev, KWQ_CID);
+	cnic_init_context(dev, KCQ_CID);
+
+	cp->kwq_cid_addr = GET_CID_ADDR(KWQ_CID);
+	cp->kwq_io_addr = MB_GET_CID_ADDR(KWQ_CID) + L5_KRNLQ_HOST_QIDX;
+
+	cp->max_kwq_idx = MAX_KWQ_IDX;
+	cp->kwq_prod_idx = 0;
+	cp->kwq_con_idx = 0;
+	cp->cnic_local_flags |= CNIC_LCL_FL_KWQ_INIT;
+
+	if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708)
+		cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15;
+	else
+		cp->kwq_con_idx_ptr = &sblk->status_cmd_consumer_index;
+
+	/* Initialize the kernel work queue context. */
+	val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
+	      (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_TYPE, val);
+
+	val = (BCM_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
+	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
+
+	val = ((BCM_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
+	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
+
+	val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32);
+	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
+
+	val = (u32) cp->kwq_info.pgtbl_map;
+	cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
+
+	cp->kcq_cid_addr = GET_CID_ADDR(KCQ_CID);
+	cp->kcq_io_addr = MB_GET_CID_ADDR(KCQ_CID) + L5_KRNLQ_HOST_QIDX;
+
+	cp->kcq_prod_idx = 0;
+
+	/* Initialize the kernel complete queue context. */
+	val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
+	      (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_TYPE, val);
+
+	val = (BCM_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
+	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
+
+	val = ((BCM_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
+	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
+
+	val = (u32) ((u64) cp->kcq_info.pgtbl_map >> 32);
+	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_HI, val);
+
+	val = (u32) cp->kcq_info.pgtbl_map;
+	cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_PGTBL_HADDR_LO, val);
+
+	cp->int_num = 0;
+	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
+		u32 sb_id = cp->status_blk_num;
+		u32 sb = BNX2_L2CTX_STATUSB_NUM(sb_id);
+
+		cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT;
+		cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
+		cnic_ctx_wr(dev, cp->kcq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
+	}
+
+	/* Enable Commnad Scheduler notification when we write to the
+	 * host producer index of the kernel contexts. */
+	CNIC_WR(dev, BNX2_MQ_KNL_CMD_MASK1, 2);
+
+	/* Enable Command Scheduler notification when we write to either
+	 * the Send Queue or Receive Queue producer indexes of the kernel
+	 * bypass contexts. */
+	CNIC_WR(dev, BNX2_MQ_KNL_BYP_CMD_MASK1, 7);
+	CNIC_WR(dev, BNX2_MQ_KNL_BYP_WRITE_MASK1, 7);
+
+	/* Notify COM when the driver post an application buffer. */
+	CNIC_WR(dev, BNX2_MQ_KNL_RX_V2P_MASK2, 0x2000);
+
+	/* Set the CP and COM doorbells.  These two processors polls the
+	 * doorbell for a non zero value before running.  This must be done
+	 * after setting up the kernel queue contexts. */
+	cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 1);
+	cnic_reg_wr_ind(dev, BNX2_COM_SCRATCH + 0x20, 1);
+
+	cnic_init_bnx2_tx_ring(dev);
+	cnic_init_bnx2_rx_ring(dev);
+
+	err = cnic_init_bnx2_irq(dev);
+	if (err) {
+		printk(KERN_ERR PFX "%s: cnic_init_irq failed\n",
+		       dev->netdev->name);
+		cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0);
+		cnic_reg_wr_ind(dev, BNX2_COM_SCRATCH + 0x20, 0);
+		return err;
+	}
+
+	return 0;
+}
+
+static int cnic_register_netdev(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	int err;
+
+	if (!ethdev)
+		return -ENODEV;
+
+	if (ethdev->drv_state & CNIC_DRV_STATE_REGD)
+		return 0;
+
+	err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev);
+	if (err)
+		printk(KERN_ERR PFX "%s: register_cnic failed\n",
+		       dev->netdev->name);
+
+	return err;
+}
+
+static void cnic_unregister_netdev(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+
+	if (!ethdev)
+		return;
+
+	ethdev->drv_unregister_cnic(dev->netdev);
+}
+
+static int cnic_start_hw(struct cnic_dev *dev)
+{
+	struct cnic_local *cp = dev->cnic_priv;
+	struct cnic_eth_dev *ethdev = cp->ethdev;
+	int err;
+
+	if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
+		return -EALREADY;
+
+	dev->regview = ethdev->io_base;
+	cp->chip_id = ethdev->chip_id;
+	pci_dev_get(dev->pcidev);
+	cp->func = PCI_FUNC(dev->pcidev->devfn);
+	cp->status_blk = ethdev->irq_arr[0].status_blk;
+	cp->status_blk_num = ethdev->irq_arr[0].status_blk_num;
+
+	err = cp->alloc_resc(dev);
+	if (err) {
+		printk(KERN_ERR PFX "%s: allocate resource failure\n",
+		       dev->netdev->name);
+		goto err1;
+	}
+
+	err = cp->start_hw(dev);
+	if (err)
+		goto err1;
+
+	err = cnic_cm_open(dev);
+	if (err)
+		goto err1;
+
+	set_bit(CNIC_F_CNIC_UP, &dev->flags);
+
+	cp->enable_int(dev);
+
+	return 0;
+
+err1:
+	cp->free_resc(dev);
+	pci_dev_put(dev->pcidev);
+	return err;
+}
+
+static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
+{
+	cnic_disable_bnx2_int_sync(dev);
+
+	cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0);
+	cnic_reg_wr_ind(dev, BNX2_COM_SCRATCH + 0x20, 0);
+
+	cnic_init_context(dev, KWQ_CID);
+	cnic_init_context(dev, KCQ_CID);
+
+	cnic_setup_5709_context(dev, 0);
+	cnic_free_irq(dev);
+
+	cnic_free_resc(dev);
+}
+
+static void cnic_stop_hw(struct cnic_dev *dev)
+{
+	if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
+		struct cnic_local *cp = dev->cnic_priv;
+
+		clear_bit(CNIC_F_CNIC_UP, &dev->flags);
+		rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL);
+		synchronize_rcu();
+		cnic_cm_shutdown(dev);
+		cp->stop_hw(dev);
+		pci_dev_put(dev->pcidev);
+	}
+}
+
+static void cnic_free_dev(struct cnic_dev *dev)
+{
+	int i = 0;
+
+	while ((atomic_read(&dev->ref_count) != 0) && i < 10) {
+		msleep(100);
+		i++;
+	}
+	if (atomic_read(&dev->ref_count) != 0)
+		printk(KERN_ERR PFX "%s: Failed waiting for ref count to go"
+				    " to zero.\n", dev->netdev->name);
+
+	printk(KERN_INFO PFX "Removed CNIC device: %s\n", dev->netdev->name);
+	dev_put(dev->netdev);
+	kfree(dev);
+}
+
+static struct cnic_dev *cnic_alloc_dev(struct net_device *dev,
+				       struct pci_dev *pdev)
+{
+	struct cnic_dev *cdev;
+	struct cnic_local *cp;
+	int alloc_size;
+
+	alloc_size = sizeof(struct cnic_dev) + sizeof(struct cnic_local);
+
+	cdev = kzalloc(alloc_size , GFP_KERNEL);
+	if (cdev == NULL) {
+		printk(KERN_ERR PFX "%s: allocate dev struct failure\n",
+		       dev->name);
+		return NULL;
+	}
+
+	cdev->netdev = dev;
+	cdev->cnic_priv = (char *)cdev + sizeof(struct cnic_dev);
+	cdev->register_device = cnic_register_device;
+	cdev->unregister_device = cnic_unregister_device;
+	cdev->iscsi_nl_msg_recv = cnic_iscsi_nl_msg_recv;
+
+	cp = cdev->cnic_priv;
+	cp->dev = cdev;
+	cp->uio_dev = -1;
+	cp->l2_single_buf_size = 0x400;
+	cp->l2_rx_ring_size = 3;
+
+	spin_lock_init(&cp->cnic_ulp_lock);
+
+	printk(KERN_INFO PFX "Added CNIC device: %s\n", dev->name);
+
+	return cdev;
+}
+
+static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
+{
+	struct pci_dev *pdev;
+	struct cnic_dev *cdev;
+	struct cnic_local *cp;
+	struct cnic_eth_dev *ethdev = NULL;
+	struct cnic_eth_dev *(*probe)(struct net_device *) = NULL;
+
+	probe = symbol_get(bnx2_cnic_probe);
+	if (probe) {
+		ethdev = (*probe)(dev);
+		symbol_put(bnx2_cnic_probe);
+	}
+	if (!ethdev)
+		return NULL;
+
+	pdev = ethdev->pdev;
+	if (!pdev)
+		return NULL;
+
+	dev_hold(dev);
+	pci_dev_get(pdev);
+	if (pdev->device == PCI_DEVICE_ID_NX2_5709 ||
+	    pdev->device == PCI_DEVICE_ID_NX2_5709S) {
+		u8 rev;
+
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+		if (rev < 0x10) {
+			pci_dev_put(pdev);
+			goto cnic_err;
+		}
+	}
+	pci_dev_put(pdev);
+
+	cdev = cnic_alloc_dev(dev, pdev);
+	if (cdev == NULL)
+		goto cnic_err;
+
+	set_bit(CNIC_F_BNX2_CLASS, &cdev->flags);
+	cdev->submit_kwqes = cnic_submit_bnx2_kwqes;
+
+	cp = cdev->cnic_priv;
+	cp->ethdev = ethdev;
+	cdev->pcidev = pdev;
+
+	cp->cnic_ops = &cnic_bnx2_ops;
+	cp->start_hw = cnic_start_bnx2_hw;
+	cp->stop_hw = cnic_stop_bnx2_hw;
+	cp->setup_pgtbl = cnic_setup_page_tbl;
+	cp->alloc_resc = cnic_alloc_bnx2_resc;
+	cp->free_resc = cnic_free_resc;
+	cp->start_cm = cnic_cm_init_bnx2_hw;
+	cp->stop_cm = cnic_cm_stop_bnx2_hw;
+	cp->enable_int = cnic_enable_bnx2_int;
+	cp->disable_int_sync = cnic_disable_bnx2_int_sync;
+	cp->close_conn = cnic_close_bnx2_conn;
+	cp->next_idx = cnic_bnx2_next_idx;
+	cp->hw_idx = cnic_bnx2_hw_idx;
+	return cdev;
+
+cnic_err:
+	dev_put(dev);
+	return NULL;
+}
+
+static struct cnic_dev *is_cnic_dev(struct net_device *dev)
+{
+	struct ethtool_drvinfo drvinfo;
+	struct cnic_dev *cdev = NULL;
+
+	if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
+
+		if (!strcmp(drvinfo.driver, "bnx2"))
+			cdev = init_bnx2_cnic(dev);
+		if (cdev) {
+			write_lock(&cnic_dev_lock);
+			list_add(&cdev->list, &cnic_dev_list);
+			write_unlock(&cnic_dev_lock);
+		}
+	}
+	return cdev;
+}
+
+/**
+ * netdev event handler
+ */
+static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
+							 void *ptr)
+{
+	struct net_device *netdev = ptr;
+	struct cnic_dev *dev;
+	int if_type;
+	int new_dev = 0;
+
+	dev = cnic_from_netdev(netdev);
+
+	if (!dev && (event == NETDEV_REGISTER || event == NETDEV_UP)) {
+		/* Check for the hot-plug device */
+		dev = is_cnic_dev(netdev);
+		if (dev) {
+			new_dev = 1;
+			cnic_hold(dev);
+		}
+	}
+	if (dev) {
+		struct cnic_local *cp = dev->cnic_priv;
+
+		if (new_dev)
+			cnic_ulp_init(dev);
+		else if (event == NETDEV_UNREGISTER)
+			cnic_ulp_exit(dev);
+		else if (event == NETDEV_UP) {
+			if (cnic_register_netdev(dev) != 0) {
+				cnic_put(dev);
+				goto done;
+			}
+			if (!cnic_start_hw(dev))
+				cnic_ulp_start(dev);
+		}
+
+		rcu_read_lock();
+		for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
+			struct cnic_ulp_ops *ulp_ops;
+			void *ctx;
+
+			ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
+			if (!ulp_ops || !ulp_ops->indicate_netevent)
+				continue;
+
+			ctx = cp->ulp_handle[if_type];
+
+			ulp_ops->indicate_netevent(ctx, event);
+		}
+		rcu_read_unlock();
+
+		if (event == NETDEV_GOING_DOWN) {
+			cnic_ulp_stop(dev);
+			cnic_stop_hw(dev);
+			cnic_unregister_netdev(dev);
+		} else if (event == NETDEV_UNREGISTER) {
+			write_lock(&cnic_dev_lock);
+			list_del_init(&dev->list);
+			write_unlock(&cnic_dev_lock);
+
+			cnic_put(dev);
+			cnic_free_dev(dev);
+			goto done;
+		}
+		cnic_put(dev);
+	}
+done:
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block cnic_netdev_notifier = {
+	.notifier_call = cnic_netdev_event
+};
+
+static void cnic_release(void)
+{
+	struct cnic_dev *dev;
+
+	while (!list_empty(&cnic_dev_list)) {
+		dev = list_entry(cnic_dev_list.next, struct cnic_dev, list);
+		if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
+			cnic_ulp_stop(dev);
+			cnic_stop_hw(dev);
+		}
+
+		cnic_ulp_exit(dev);
+		cnic_unregister_netdev(dev);
+		list_del_init(&dev->list);
+		cnic_free_dev(dev);
+	}
+}
+
+static int __init cnic_init(void)
+{
+	int rc = 0;
+
+	printk(KERN_INFO "%s", version);
+
+	rc = register_netdevice_notifier(&cnic_netdev_notifier);
+	if (rc) {
+		cnic_release();
+		return rc;
+	}
+
+	return 0;
+}
+
+static void __exit cnic_exit(void)
+{
+	unregister_netdevice_notifier(&cnic_netdev_notifier);
+	cnic_release();
+	return;
+}
+
+module_init(cnic_init);
+module_exit(cnic_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/cnic_defs.h linux-libre-2.6.31-gnu/drivers/net/cnic_defs.h
--- linux-libre-2.6.30-gnu/drivers/net/cnic_defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/cnic_defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,580 @@
+
+/* cnic.c: Broadcom CNIC core network driver.
+ *
+ * Copyright (c) 2006-2009 Broadcom 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.
+ *
+ */
+
+#ifndef CNIC_DEFS_H
+#define CNIC_DEFS_H
+
+/* KWQ (kernel work queue) request op codes */
+#define L2_KWQE_OPCODE_VALUE_FLUSH                  (4)
+
+#define L4_KWQE_OPCODE_VALUE_CONNECT1               (50)
+#define L4_KWQE_OPCODE_VALUE_CONNECT2               (51)
+#define L4_KWQE_OPCODE_VALUE_CONNECT3               (52)
+#define L4_KWQE_OPCODE_VALUE_RESET                  (53)
+#define L4_KWQE_OPCODE_VALUE_CLOSE                  (54)
+#define L4_KWQE_OPCODE_VALUE_UPDATE_SECRET          (60)
+#define L4_KWQE_OPCODE_VALUE_INIT_ULP               (61)
+
+#define L4_KWQE_OPCODE_VALUE_OFFLOAD_PG             (1)
+#define L4_KWQE_OPCODE_VALUE_UPDATE_PG              (9)
+#define L4_KWQE_OPCODE_VALUE_UPLOAD_PG              (14)
+
+#define L5CM_RAMROD_CMD_ID_BASE			(0x80)
+#define L5CM_RAMROD_CMD_ID_TCP_CONNECT		(L5CM_RAMROD_CMD_ID_BASE + 3)
+#define L5CM_RAMROD_CMD_ID_CLOSE		(L5CM_RAMROD_CMD_ID_BASE + 12)
+#define L5CM_RAMROD_CMD_ID_ABORT		(L5CM_RAMROD_CMD_ID_BASE + 13)
+#define L5CM_RAMROD_CMD_ID_SEARCHER_DELETE	(L5CM_RAMROD_CMD_ID_BASE + 14)
+#define L5CM_RAMROD_CMD_ID_TERMINATE_OFFLOAD	(L5CM_RAMROD_CMD_ID_BASE + 15)
+
+/* KCQ (kernel completion queue) response op codes */
+#define L4_KCQE_OPCODE_VALUE_CLOSE_COMP             (53)
+#define L4_KCQE_OPCODE_VALUE_RESET_COMP             (54)
+#define L4_KCQE_OPCODE_VALUE_FW_TCP_UPDATE          (55)
+#define L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE       (56)
+#define L4_KCQE_OPCODE_VALUE_RESET_RECEIVED         (57)
+#define L4_KCQE_OPCODE_VALUE_CLOSE_RECEIVED         (58)
+#define L4_KCQE_OPCODE_VALUE_INIT_ULP               (61)
+
+#define L4_KCQE_OPCODE_VALUE_OFFLOAD_PG             (1)
+#define L4_KCQE_OPCODE_VALUE_UPDATE_PG              (9)
+#define L4_KCQE_OPCODE_VALUE_UPLOAD_PG              (14)
+
+/* KCQ (kernel completion queue) completion status */
+#define L4_KCQE_COMPLETION_STATUS_SUCCESS		    (0)
+#define L4_KCQE_COMPLETION_STATUS_TIMEOUT        (0x93)
+
+#define L4_LAYER_CODE (4)
+#define L2_LAYER_CODE (2)
+
+/*
+ * L4 KCQ CQE
+ */
+struct l4_kcq {
+	u32 cid;
+	u32 pg_cid;
+	u32 conn_id;
+	u32 pg_host_opaque;
+#if defined(__BIG_ENDIAN)
+	u16 status;
+	u16 reserved1;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved1;
+	u16 status;
+#endif
+	u32 reserved2[2];
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KCQ_RESERVED3 (0x7<<0)
+#define L4_KCQ_RESERVED3_SHIFT 0
+#define L4_KCQ_RAMROD_COMPLETION (0x1<<3) /* Everest only */
+#define L4_KCQ_RAMROD_COMPLETION_SHIFT 3
+#define L4_KCQ_LAYER_CODE (0x7<<4)
+#define L4_KCQ_LAYER_CODE_SHIFT 4
+#define L4_KCQ_RESERVED4 (0x1<<7)
+#define L4_KCQ_RESERVED4_SHIFT 7
+	u8 op_code;
+	u16 qe_self_seq;
+#elif defined(__LITTLE_ENDIAN)
+	u16 qe_self_seq;
+	u8 op_code;
+	u8 flags;
+#define L4_KCQ_RESERVED3 (0xF<<0)
+#define L4_KCQ_RESERVED3_SHIFT 0
+#define L4_KCQ_RAMROD_COMPLETION (0x1<<3) /* Everest only */
+#define L4_KCQ_RAMROD_COMPLETION_SHIFT 3
+#define L4_KCQ_LAYER_CODE (0x7<<4)
+#define L4_KCQ_LAYER_CODE_SHIFT 4
+#define L4_KCQ_RESERVED4 (0x1<<7)
+#define L4_KCQ_RESERVED4_SHIFT 7
+#endif
+};
+
+
+/*
+ * L4 KCQ CQE PG upload
+ */
+struct l4_kcq_upload_pg {
+	u32 pg_cid;
+#if defined(__BIG_ENDIAN)
+	u16 pg_status;
+	u16 pg_ipid_count;
+#elif defined(__LITTLE_ENDIAN)
+	u16 pg_ipid_count;
+	u16 pg_status;
+#endif
+	u32 reserved1[5];
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KCQ_UPLOAD_PG_RESERVED3 (0xF<<0)
+#define L4_KCQ_UPLOAD_PG_RESERVED3_SHIFT 0
+#define L4_KCQ_UPLOAD_PG_LAYER_CODE (0x7<<4)
+#define L4_KCQ_UPLOAD_PG_LAYER_CODE_SHIFT 4
+#define L4_KCQ_UPLOAD_PG_RESERVED4 (0x1<<7)
+#define L4_KCQ_UPLOAD_PG_RESERVED4_SHIFT 7
+	u8 op_code;
+	u16 qe_self_seq;
+#elif defined(__LITTLE_ENDIAN)
+	u16 qe_self_seq;
+	u8 op_code;
+	u8 flags;
+#define L4_KCQ_UPLOAD_PG_RESERVED3 (0xF<<0)
+#define L4_KCQ_UPLOAD_PG_RESERVED3_SHIFT 0
+#define L4_KCQ_UPLOAD_PG_LAYER_CODE (0x7<<4)
+#define L4_KCQ_UPLOAD_PG_LAYER_CODE_SHIFT 4
+#define L4_KCQ_UPLOAD_PG_RESERVED4 (0x1<<7)
+#define L4_KCQ_UPLOAD_PG_RESERVED4_SHIFT 7
+#endif
+};
+
+
+/*
+ * Gracefully close the connection request
+ */
+struct l4_kwq_close_req {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_CLOSE_REQ_RESERVED1 (0xF<<0)
+#define L4_KWQ_CLOSE_REQ_RESERVED1_SHIFT 0
+#define L4_KWQ_CLOSE_REQ_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CLOSE_REQ_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	u8 op_code;
+	u8 flags;
+#define L4_KWQ_CLOSE_REQ_RESERVED1 (0xF<<0)
+#define L4_KWQ_CLOSE_REQ_RESERVED1_SHIFT 0
+#define L4_KWQ_CLOSE_REQ_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CLOSE_REQ_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CLOSE_REQ_LINKED_WITH_NEXT_SHIFT 7
+#endif
+	u32 cid;
+	u32 reserved2[6];
+};
+
+
+/*
+ * The first request to be passed in order to establish connection in option2
+ */
+struct l4_kwq_connect_req1 {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_CONNECT_REQ1_RESERVED1 (0xF<<0)
+#define L4_KWQ_CONNECT_REQ1_RESERVED1_SHIFT 0
+#define L4_KWQ_CONNECT_REQ1_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CONNECT_REQ1_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u8 reserved0;
+	u8 conn_flags;
+#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE (0x1<<0)
+#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE_SHIFT 0
+#define L4_KWQ_CONNECT_REQ1_IP_V6 (0x1<<1)
+#define L4_KWQ_CONNECT_REQ1_IP_V6_SHIFT 1
+#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG (0x1<<2)
+#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG_SHIFT 2
+#define L4_KWQ_CONNECT_REQ1_RSRV (0x1F<<3)
+#define L4_KWQ_CONNECT_REQ1_RSRV_SHIFT 3
+#elif defined(__LITTLE_ENDIAN)
+	u8 conn_flags;
+#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE (0x1<<0)
+#define L4_KWQ_CONNECT_REQ1_IS_PG_HOST_OPAQUE_SHIFT 0
+#define L4_KWQ_CONNECT_REQ1_IP_V6 (0x1<<1)
+#define L4_KWQ_CONNECT_REQ1_IP_V6_SHIFT 1
+#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG (0x1<<2)
+#define L4_KWQ_CONNECT_REQ1_PASSIVE_FLAG_SHIFT 2
+#define L4_KWQ_CONNECT_REQ1_RSRV (0x1F<<3)
+#define L4_KWQ_CONNECT_REQ1_RSRV_SHIFT 3
+	u8 reserved0;
+	u8 op_code;
+	u8 flags;
+#define L4_KWQ_CONNECT_REQ1_RESERVED1 (0xF<<0)
+#define L4_KWQ_CONNECT_REQ1_RESERVED1_SHIFT 0
+#define L4_KWQ_CONNECT_REQ1_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CONNECT_REQ1_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CONNECT_REQ1_LINKED_WITH_NEXT_SHIFT 7
+#endif
+	u32 cid;
+	u32 pg_cid;
+	u32 src_ip;
+	u32 dst_ip;
+#if defined(__BIG_ENDIAN)
+	u16 dst_port;
+	u16 src_port;
+#elif defined(__LITTLE_ENDIAN)
+	u16 src_port;
+	u16 dst_port;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 rsrv1[3];
+	u8 tcp_flags;
+#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK (0x1<<0)
+#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK_SHIFT 0
+#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE (0x1<<1)
+#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE_SHIFT 1
+#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE (0x1<<2)
+#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE_SHIFT 2
+#define L4_KWQ_CONNECT_REQ1_TIME_STAMP (0x1<<3)
+#define L4_KWQ_CONNECT_REQ1_TIME_STAMP_SHIFT 3
+#define L4_KWQ_CONNECT_REQ1_SACK (0x1<<4)
+#define L4_KWQ_CONNECT_REQ1_SACK_SHIFT 4
+#define L4_KWQ_CONNECT_REQ1_SEG_SCALING (0x1<<5)
+#define L4_KWQ_CONNECT_REQ1_SEG_SCALING_SHIFT 5
+#define L4_KWQ_CONNECT_REQ1_RESERVED2 (0x3<<6)
+#define L4_KWQ_CONNECT_REQ1_RESERVED2_SHIFT 6
+#elif defined(__LITTLE_ENDIAN)
+	u8 tcp_flags;
+#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK (0x1<<0)
+#define L4_KWQ_CONNECT_REQ1_NO_DELAY_ACK_SHIFT 0
+#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE (0x1<<1)
+#define L4_KWQ_CONNECT_REQ1_KEEP_ALIVE_SHIFT 1
+#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE (0x1<<2)
+#define L4_KWQ_CONNECT_REQ1_NAGLE_ENABLE_SHIFT 2
+#define L4_KWQ_CONNECT_REQ1_TIME_STAMP (0x1<<3)
+#define L4_KWQ_CONNECT_REQ1_TIME_STAMP_SHIFT 3
+#define L4_KWQ_CONNECT_REQ1_SACK (0x1<<4)
+#define L4_KWQ_CONNECT_REQ1_SACK_SHIFT 4
+#define L4_KWQ_CONNECT_REQ1_SEG_SCALING (0x1<<5)
+#define L4_KWQ_CONNECT_REQ1_SEG_SCALING_SHIFT 5
+#define L4_KWQ_CONNECT_REQ1_RESERVED2 (0x3<<6)
+#define L4_KWQ_CONNECT_REQ1_RESERVED2_SHIFT 6
+	u8 rsrv1[3];
+#endif
+	u32 rsrv2;
+};
+
+
+/*
+ * The second ( optional )request to be passed in order to establish
+ * connection in option2 - for IPv6 only
+ */
+struct l4_kwq_connect_req2 {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_CONNECT_REQ2_RESERVED1 (0xF<<0)
+#define L4_KWQ_CONNECT_REQ2_RESERVED1_SHIFT 0
+#define L4_KWQ_CONNECT_REQ2_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CONNECT_REQ2_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u8 reserved0;
+	u8 rsrv;
+#elif defined(__LITTLE_ENDIAN)
+	u8 rsrv;
+	u8 reserved0;
+	u8 op_code;
+	u8 flags;
+#define L4_KWQ_CONNECT_REQ2_RESERVED1 (0xF<<0)
+#define L4_KWQ_CONNECT_REQ2_RESERVED1_SHIFT 0
+#define L4_KWQ_CONNECT_REQ2_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CONNECT_REQ2_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CONNECT_REQ2_LINKED_WITH_NEXT_SHIFT 7
+#endif
+	u32 reserved2;
+	u32 src_ip_v6_2;
+	u32 src_ip_v6_3;
+	u32 src_ip_v6_4;
+	u32 dst_ip_v6_2;
+	u32 dst_ip_v6_3;
+	u32 dst_ip_v6_4;
+};
+
+
+/*
+ * The third ( and last )request to be passed in order to establish
+ * connection in option2
+ */
+struct l4_kwq_connect_req3 {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_CONNECT_REQ3_RESERVED1 (0xF<<0)
+#define L4_KWQ_CONNECT_REQ3_RESERVED1_SHIFT 0
+#define L4_KWQ_CONNECT_REQ3_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CONNECT_REQ3_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	u8 op_code;
+	u8 flags;
+#define L4_KWQ_CONNECT_REQ3_RESERVED1 (0xF<<0)
+#define L4_KWQ_CONNECT_REQ3_RESERVED1_SHIFT 0
+#define L4_KWQ_CONNECT_REQ3_LAYER_CODE (0x7<<4)
+#define L4_KWQ_CONNECT_REQ3_LAYER_CODE_SHIFT 4
+#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_CONNECT_REQ3_LINKED_WITH_NEXT_SHIFT 7
+#endif
+	u32 ka_timeout;
+	u32 ka_interval ;
+#if defined(__BIG_ENDIAN)
+	u8 snd_seq_scale;
+	u8 ttl;
+	u8 tos;
+	u8 ka_max_probe_count;
+#elif defined(__LITTLE_ENDIAN)
+	u8 ka_max_probe_count;
+	u8 tos;
+	u8 ttl;
+	u8 snd_seq_scale;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 pmtu;
+	u16 mss;
+#elif defined(__LITTLE_ENDIAN)
+	u16 mss;
+	u16 pmtu;
+#endif
+	u32 rcv_buf;
+	u32 snd_buf;
+	u32 seed;
+};
+
+
+/*
+ * a KWQE request to offload a PG connection
+ */
+struct l4_kwq_offload_pg {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_OFFLOAD_PG_RESERVED1 (0xF<<0)
+#define L4_KWQ_OFFLOAD_PG_RESERVED1_SHIFT 0
+#define L4_KWQ_OFFLOAD_PG_LAYER_CODE (0x7<<4)
+#define L4_KWQ_OFFLOAD_PG_LAYER_CODE_SHIFT 4
+#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	u8 op_code;
+	u8 flags;
+#define L4_KWQ_OFFLOAD_PG_RESERVED1 (0xF<<0)
+#define L4_KWQ_OFFLOAD_PG_RESERVED1_SHIFT 0
+#define L4_KWQ_OFFLOAD_PG_LAYER_CODE (0x7<<4)
+#define L4_KWQ_OFFLOAD_PG_LAYER_CODE_SHIFT 4
+#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_OFFLOAD_PG_LINKED_WITH_NEXT_SHIFT 7
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 l2hdr_nbytes;
+	u8 pg_flags;
+#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP (0x1<<0)
+#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP_SHIFT 0
+#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING (0x1<<1)
+#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING_SHIFT 1
+#define L4_KWQ_OFFLOAD_PG_RESERVED2 (0x3F<<2)
+#define L4_KWQ_OFFLOAD_PG_RESERVED2_SHIFT 2
+	u8 da0;
+	u8 da1;
+#elif defined(__LITTLE_ENDIAN)
+	u8 da1;
+	u8 da0;
+	u8 pg_flags;
+#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP (0x1<<0)
+#define L4_KWQ_OFFLOAD_PG_SNAP_ENCAP_SHIFT 0
+#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING (0x1<<1)
+#define L4_KWQ_OFFLOAD_PG_VLAN_TAGGING_SHIFT 1
+#define L4_KWQ_OFFLOAD_PG_RESERVED2 (0x3F<<2)
+#define L4_KWQ_OFFLOAD_PG_RESERVED2_SHIFT 2
+	u8 l2hdr_nbytes;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 da2;
+	u8 da3;
+	u8 da4;
+	u8 da5;
+#elif defined(__LITTLE_ENDIAN)
+	u8 da5;
+	u8 da4;
+	u8 da3;
+	u8 da2;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 sa0;
+	u8 sa1;
+	u8 sa2;
+	u8 sa3;
+#elif defined(__LITTLE_ENDIAN)
+	u8 sa3;
+	u8 sa2;
+	u8 sa1;
+	u8 sa0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 sa4;
+	u8 sa5;
+	u16 etype;
+#elif defined(__LITTLE_ENDIAN)
+	u16 etype;
+	u8 sa5;
+	u8 sa4;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 vlan_tag;
+	u16 ipid_start;
+#elif defined(__LITTLE_ENDIAN)
+	u16 ipid_start;
+	u16 vlan_tag;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 ipid_count;
+	u16 reserved3;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved3;
+	u16 ipid_count;
+#endif
+	u32 host_opaque;
+};
+
+
+/*
+ * Abortively close the connection request
+ */
+struct l4_kwq_reset_req {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_RESET_REQ_RESERVED1 (0xF<<0)
+#define L4_KWQ_RESET_REQ_RESERVED1_SHIFT 0
+#define L4_KWQ_RESET_REQ_LAYER_CODE (0x7<<4)
+#define L4_KWQ_RESET_REQ_LAYER_CODE_SHIFT 4
+#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	u8 op_code;
+	u8 flags;
+#define L4_KWQ_RESET_REQ_RESERVED1 (0xF<<0)
+#define L4_KWQ_RESET_REQ_RESERVED1_SHIFT 0
+#define L4_KWQ_RESET_REQ_LAYER_CODE (0x7<<4)
+#define L4_KWQ_RESET_REQ_LAYER_CODE_SHIFT 4
+#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_RESET_REQ_LINKED_WITH_NEXT_SHIFT 7
+#endif
+	u32 cid;
+	u32 reserved2[6];
+};
+
+
+/*
+ * a KWQE request to update a PG connection
+ */
+struct l4_kwq_update_pg {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_UPDATE_PG_RESERVED1 (0xF<<0)
+#define L4_KWQ_UPDATE_PG_RESERVED1_SHIFT 0
+#define L4_KWQ_UPDATE_PG_LAYER_CODE (0x7<<4)
+#define L4_KWQ_UPDATE_PG_LAYER_CODE_SHIFT 4
+#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT_SHIFT 7
+	u8 opcode;
+	u16 oper16;
+#elif defined(__LITTLE_ENDIAN)
+	u16 oper16;
+	u8 opcode;
+	u8 flags;
+#define L4_KWQ_UPDATE_PG_RESERVED1 (0xF<<0)
+#define L4_KWQ_UPDATE_PG_RESERVED1_SHIFT 0
+#define L4_KWQ_UPDATE_PG_LAYER_CODE (0x7<<4)
+#define L4_KWQ_UPDATE_PG_LAYER_CODE_SHIFT 4
+#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_UPDATE_PG_LINKED_WITH_NEXT_SHIFT 7
+#endif
+	u32 pg_cid;
+	u32 pg_host_opaque;
+#if defined(__BIG_ENDIAN)
+	u8 pg_valids;
+#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT (0x1<<0)
+#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT_SHIFT 0
+#define L4_KWQ_UPDATE_PG_VALIDS_DA (0x1<<1)
+#define L4_KWQ_UPDATE_PG_VALIDS_DA_SHIFT 1
+#define L4_KWQ_UPDATE_PG_RESERVERD2 (0x3F<<2)
+#define L4_KWQ_UPDATE_PG_RESERVERD2_SHIFT 2
+	u8 pg_unused_a;
+	u16 pg_ipid_count;
+#elif defined(__LITTLE_ENDIAN)
+	u16 pg_ipid_count;
+	u8 pg_unused_a;
+	u8 pg_valids;
+#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT (0x1<<0)
+#define L4_KWQ_UPDATE_PG_VALIDS_IPID_COUNT_SHIFT 0
+#define L4_KWQ_UPDATE_PG_VALIDS_DA (0x1<<1)
+#define L4_KWQ_UPDATE_PG_VALIDS_DA_SHIFT 1
+#define L4_KWQ_UPDATE_PG_RESERVERD2 (0x3F<<2)
+#define L4_KWQ_UPDATE_PG_RESERVERD2_SHIFT 2
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 reserverd3;
+	u8 da0;
+	u8 da1;
+#elif defined(__LITTLE_ENDIAN)
+	u8 da1;
+	u8 da0;
+	u16 reserverd3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 da2;
+	u8 da3;
+	u8 da4;
+	u8 da5;
+#elif defined(__LITTLE_ENDIAN)
+	u8 da5;
+	u8 da4;
+	u8 da3;
+	u8 da2;
+#endif
+	u32 reserved4;
+	u32 reserved5;
+};
+
+
+/*
+ * a KWQE request to upload a PG or L4 context
+ */
+struct l4_kwq_upload {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define L4_KWQ_UPLOAD_RESERVED1 (0xF<<0)
+#define L4_KWQ_UPLOAD_RESERVED1_SHIFT 0
+#define L4_KWQ_UPLOAD_LAYER_CODE (0x7<<4)
+#define L4_KWQ_UPLOAD_LAYER_CODE_SHIFT 4
+#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT_SHIFT 7
+	u8 opcode;
+	u16 oper16;
+#elif defined(__LITTLE_ENDIAN)
+	u16 oper16;
+	u8 opcode;
+	u8 flags;
+#define L4_KWQ_UPLOAD_RESERVED1 (0xF<<0)
+#define L4_KWQ_UPLOAD_RESERVED1_SHIFT 0
+#define L4_KWQ_UPLOAD_LAYER_CODE (0x7<<4)
+#define L4_KWQ_UPLOAD_LAYER_CODE_SHIFT 4
+#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT (0x1<<7)
+#define L4_KWQ_UPLOAD_LINKED_WITH_NEXT_SHIFT 7
+#endif
+	u32 cid;
+	u32 reserved2[6];
+};
+
+#endif /* CNIC_DEFS_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/cnic.h linux-libre-2.6.31-gnu/drivers/net/cnic.h
--- linux-libre-2.6.30-gnu/drivers/net/cnic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/cnic.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,300 @@
+/* cnic.h: Broadcom CNIC core network driver.
+ *
+ * Copyright (c) 2006-2009 Broadcom 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.
+ *
+ */
+
+
+#ifndef CNIC_H
+#define CNIC_H
+
+#define KWQ_PAGE_CNT	4
+#define KCQ_PAGE_CNT	16
+
+#define KWQ_CID 		24
+#define KCQ_CID 		25
+
+/*
+ *	krnlq_context definition
+ */
+#define L5_KRNLQ_FLAGS	0x00000000
+#define L5_KRNLQ_SIZE	0x00000000
+#define L5_KRNLQ_TYPE	0x00000000
+#define KRNLQ_FLAGS_PG_SZ					(0xf<<0)
+#define KRNLQ_FLAGS_PG_SZ_256					(0<<0)
+#define KRNLQ_FLAGS_PG_SZ_512					(1<<0)
+#define KRNLQ_FLAGS_PG_SZ_1K					(2<<0)
+#define KRNLQ_FLAGS_PG_SZ_2K					(3<<0)
+#define KRNLQ_FLAGS_PG_SZ_4K					(4<<0)
+#define KRNLQ_FLAGS_PG_SZ_8K					(5<<0)
+#define KRNLQ_FLAGS_PG_SZ_16K					(6<<0)
+#define KRNLQ_FLAGS_PG_SZ_32K					(7<<0)
+#define KRNLQ_FLAGS_PG_SZ_64K					(8<<0)
+#define KRNLQ_FLAGS_PG_SZ_128K					(9<<0)
+#define KRNLQ_FLAGS_PG_SZ_256K					(10<<0)
+#define KRNLQ_FLAGS_PG_SZ_512K					(11<<0)
+#define KRNLQ_FLAGS_PG_SZ_1M					(12<<0)
+#define KRNLQ_FLAGS_PG_SZ_2M					(13<<0)
+#define KRNLQ_FLAGS_QE_SELF_SEQ					(1<<15)
+#define KRNLQ_SIZE_TYPE_SIZE	((((0x28 + 0x1f) & ~0x1f) / 0x20) << 16)
+#define KRNLQ_TYPE_TYPE						(0xf<<28)
+#define KRNLQ_TYPE_TYPE_EMPTY					(0<<28)
+#define KRNLQ_TYPE_TYPE_KRNLQ					(6<<28)
+
+#define L5_KRNLQ_HOST_QIDX		0x00000004
+#define L5_KRNLQ_HOST_FW_QIDX		0x00000008
+#define L5_KRNLQ_NX_QE_SELF_SEQ 	0x0000000c
+#define L5_KRNLQ_QE_SELF_SEQ_MAX	0x0000000c
+#define L5_KRNLQ_NX_QE_HADDR_HI 	0x00000010
+#define L5_KRNLQ_NX_QE_HADDR_LO 	0x00000014
+#define L5_KRNLQ_PGTBL_PGIDX		0x00000018
+#define L5_KRNLQ_NX_PG_QIDX 		0x00000018
+#define L5_KRNLQ_PGTBL_NPAGES		0x0000001c
+#define L5_KRNLQ_QIDX_INCR		0x0000001c
+#define L5_KRNLQ_PGTBL_HADDR_HI 	0x00000020
+#define L5_KRNLQ_PGTBL_HADDR_LO 	0x00000024
+
+#define BNX2_PG_CTX_MAP			0x1a0034
+#define BNX2_ISCSI_CTX_MAP		0x1a0074
+
+struct cnic_redirect_entry {
+	struct dst_entry *old_dst;
+	struct dst_entry *new_dst;
+};
+
+#define MAX_COMPLETED_KCQE	64
+
+#define MAX_CNIC_L5_CONTEXT	256
+
+#define MAX_CM_SK_TBL_SZ	MAX_CNIC_L5_CONTEXT
+
+#define MAX_ISCSI_TBL_SZ	256
+
+#define CNIC_LOCAL_PORT_MIN	60000
+#define CNIC_LOCAL_PORT_MAX	61000
+#define CNIC_LOCAL_PORT_RANGE	(CNIC_LOCAL_PORT_MAX - CNIC_LOCAL_PORT_MIN)
+
+#define KWQE_CNT (BCM_PAGE_SIZE / sizeof(struct kwqe))
+#define KCQE_CNT (BCM_PAGE_SIZE / sizeof(struct kcqe))
+#define MAX_KWQE_CNT (KWQE_CNT - 1)
+#define MAX_KCQE_CNT (KCQE_CNT - 1)
+
+#define MAX_KWQ_IDX	((KWQ_PAGE_CNT * KWQE_CNT) - 1)
+#define MAX_KCQ_IDX	((KCQ_PAGE_CNT * KCQE_CNT) - 1)
+
+#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BCM_PAGE_BITS - 5))
+#define KWQ_IDX(x) ((x) & MAX_KWQE_CNT)
+
+#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BCM_PAGE_BITS - 5))
+#define KCQ_IDX(x) ((x) & MAX_KCQE_CNT)
+
+#define BNX2X_NEXT_KCQE(x) (((x) & (MAX_KCQE_CNT - 1)) ==		\
+		(MAX_KCQE_CNT - 1)) ?					\
+		(x) + 2 : (x) + 1
+
+#define BNX2X_KWQ_DATA_PG(cp, x) ((x) / (cp)->kwq_16_data_pp)
+#define BNX2X_KWQ_DATA_IDX(cp, x) ((x) % (cp)->kwq_16_data_pp)
+#define BNX2X_KWQ_DATA(cp, x)						\
+	&(cp)->kwq_16_data[BNX2X_KWQ_DATA_PG(cp, x)][BNX2X_KWQ_DATA_IDX(cp, x)]
+
+#define DEF_IPID_COUNT		0xc001
+
+#define DEF_KA_TIMEOUT		10000
+#define DEF_KA_INTERVAL		300000
+#define DEF_KA_MAX_PROBE_COUNT	3
+#define DEF_TOS			0
+#define DEF_TTL			0xfe
+#define DEF_SND_SEQ_SCALE	0
+#define DEF_RCV_BUF		0xffff
+#define DEF_SND_BUF		0xffff
+#define DEF_SEED		0
+#define DEF_MAX_RT_TIME		500
+#define DEF_MAX_DA_COUNT	2
+#define DEF_SWS_TIMER		1000
+#define DEF_MAX_CWND		0xffff
+
+struct cnic_ctx {
+	u32		cid;
+	void		*ctx;
+	dma_addr_t	mapping;
+};
+
+#define BNX2_MAX_CID		0x2000
+
+struct cnic_dma {
+	int		num_pages;
+	void		**pg_arr;
+	dma_addr_t	*pg_map_arr;
+	int		pgtbl_size;
+	u32		*pgtbl;
+	dma_addr_t	pgtbl_map;
+};
+
+struct cnic_id_tbl {
+	spinlock_t	lock;
+	u32		start;
+	u32		max;
+	u32		next;
+	unsigned long	*table;
+};
+
+#define CNIC_KWQ16_DATA_SIZE	128
+
+struct kwqe_16_data {
+	u8	data[CNIC_KWQ16_DATA_SIZE];
+};
+
+struct cnic_iscsi {
+	struct cnic_dma		task_array_info;
+	struct cnic_dma		r2tq_info;
+	struct cnic_dma		hq_info;
+};
+
+struct cnic_context {
+	u32			cid;
+	struct kwqe_16_data	*kwqe_data;
+	dma_addr_t		kwqe_data_mapping;
+	wait_queue_head_t	waitq;
+	int			wait_cond;
+	unsigned long		timestamp;
+	u32			ctx_flags;
+#define	CTX_FL_OFFLD_START	0x00000001
+	u8			ulp_proto_id;
+	union {
+		struct cnic_iscsi	*iscsi;
+	} proto;
+};
+
+struct cnic_local {
+
+	spinlock_t cnic_ulp_lock;
+	void *ulp_handle[MAX_CNIC_ULP_TYPE];
+	unsigned long ulp_flags[MAX_CNIC_ULP_TYPE];
+#define ULP_F_INIT	0
+#define ULP_F_START	1
+#define ULP_F_CALL_PENDING	2
+	struct cnic_ulp_ops *ulp_ops[MAX_CNIC_ULP_TYPE];
+
+	/* protected by ulp_lock */
+	u32 cnic_local_flags;
+#define	CNIC_LCL_FL_KWQ_INIT	0x00000001
+
+	struct cnic_dev *dev;
+
+	struct cnic_eth_dev *ethdev;
+
+	void		*l2_ring;
+	dma_addr_t	l2_ring_map;
+	int		l2_ring_size;
+	int		l2_rx_ring_size;
+
+	void		*l2_buf;
+	dma_addr_t	l2_buf_map;
+	int		l2_buf_size;
+	int		l2_single_buf_size;
+
+	u16		*rx_cons_ptr;
+	u16		*tx_cons_ptr;
+	u16		rx_cons;
+	u16		tx_cons;
+
+	u32 kwq_cid_addr;
+	u32 kcq_cid_addr;
+
+	struct cnic_dma		kwq_info;
+	struct kwqe		**kwq;
+
+	struct cnic_dma		kwq_16_data_info;
+
+	u16		max_kwq_idx;
+
+	u16		kwq_prod_idx;
+	u32		kwq_io_addr;
+
+	u16		*kwq_con_idx_ptr;
+	u16		kwq_con_idx;
+
+	struct cnic_dma	kcq_info;
+	struct kcqe	**kcq;
+
+	u16		kcq_prod_idx;
+	u32		kcq_io_addr;
+
+	void				*status_blk;
+	struct status_block_msix	*bnx2_status_blk;
+	struct host_status_block	*bnx2x_status_blk;
+
+	u32				status_blk_num;
+	u32				int_num;
+	u32				last_status_idx;
+	struct tasklet_struct		cnic_irq_task;
+
+	struct kcqe		*completed_kcq[MAX_COMPLETED_KCQE];
+
+	struct cnic_sock	*csk_tbl;
+	struct cnic_id_tbl	csk_port_tbl;
+
+	struct cnic_dma		conn_buf_info;
+	struct cnic_dma		gbl_buf_info;
+
+	struct cnic_iscsi	*iscsi_tbl;
+	struct cnic_context	*ctx_tbl;
+	struct cnic_id_tbl	cid_tbl;
+	int			max_iscsi_conn;
+	atomic_t		iscsi_conn;
+
+	/* per connection parameters */
+	int			num_iscsi_tasks;
+	int			num_ccells;
+	int			task_array_size;
+	int			r2tq_size;
+	int			hq_size;
+	int			num_cqs;
+
+	struct cnic_ctx		*ctx_arr;
+	int			ctx_blks;
+	int			ctx_blk_size;
+	int			cids_per_blk;
+
+	u32			chip_id;
+	int			func;
+	u32			shmem_base;
+
+	u32			uio_dev;
+	struct uio_info		*cnic_uinfo;
+
+	struct cnic_ops		*cnic_ops;
+	int			(*start_hw)(struct cnic_dev *);
+	void			(*stop_hw)(struct cnic_dev *);
+	void			(*setup_pgtbl)(struct cnic_dev *,
+					       struct cnic_dma *);
+	int			(*alloc_resc)(struct cnic_dev *);
+	void			(*free_resc)(struct cnic_dev *);
+	int			(*start_cm)(struct cnic_dev *);
+	void			(*stop_cm)(struct cnic_dev *);
+	void			(*enable_int)(struct cnic_dev *);
+	void			(*disable_int_sync)(struct cnic_dev *);
+	void			(*ack_int)(struct cnic_dev *);
+	void			(*close_conn)(struct cnic_sock *, u32 opcode);
+	u16			(*next_idx)(u16);
+	u16			(*hw_idx)(u16);
+};
+
+struct bnx2x_bd_chain_next {
+	u32	addr_lo;
+	u32	addr_hi;
+	u8	reserved[8];
+};
+
+#define ISCSI_RAMROD_CMD_ID_UPDATE_CONN		(ISCSI_KCQE_OPCODE_UPDATE_CONN)
+#define ISCSI_RAMROD_CMD_ID_INIT		(ISCSI_KCQE_OPCODE_INIT)
+
+#define CDU_REGION_NUMBER_XCM_AG 2
+#define CDU_REGION_NUMBER_UCM_AG 4
+
+#endif
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/cnic_if.h linux-libre-2.6.31-gnu/drivers/net/cnic_if.h
--- linux-libre-2.6.30-gnu/drivers/net/cnic_if.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/cnic_if.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,302 @@
+/* cnic_if.h: Broadcom CNIC core network driver.
+ *
+ * Copyright (c) 2006 Broadcom 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.
+ *
+ */
+
+
+#ifndef CNIC_IF_H
+#define CNIC_IF_H
+
+#define CNIC_MODULE_VERSION	"2.0.0"
+#define CNIC_MODULE_RELDATE	"May 21, 2009"
+
+#define CNIC_ULP_RDMA		0
+#define CNIC_ULP_ISCSI		1
+#define CNIC_ULP_L4		2
+#define MAX_CNIC_ULP_TYPE_EXT	2
+#define MAX_CNIC_ULP_TYPE	3
+
+struct kwqe {
+	u32 kwqe_op_flag;
+
+#define KWQE_OPCODE_MASK	0x00ff0000
+#define KWQE_OPCODE_SHIFT	16
+#define KWQE_FLAGS_LAYER_SHIFT	28
+#define KWQE_OPCODE(x)		((x & KWQE_OPCODE_MASK) >> KWQE_OPCODE_SHIFT)
+
+	u32 kwqe_info0;
+	u32 kwqe_info1;
+	u32 kwqe_info2;
+	u32 kwqe_info3;
+	u32 kwqe_info4;
+	u32 kwqe_info5;
+	u32 kwqe_info6;
+};
+
+struct kwqe_16 {
+	u32 kwqe_info0;
+	u32 kwqe_info1;
+	u32 kwqe_info2;
+	u32 kwqe_info3;
+};
+
+struct kcqe {
+	u32 kcqe_info0;
+	u32 kcqe_info1;
+	u32 kcqe_info2;
+	u32 kcqe_info3;
+	u32 kcqe_info4;
+	u32 kcqe_info5;
+	u32 kcqe_info6;
+	u32 kcqe_op_flag;
+		#define KCQE_RAMROD_COMPLETION		(0x1<<27) /* Everest */
+		#define KCQE_FLAGS_LAYER_MASK		(0x7<<28)
+		#define KCQE_FLAGS_LAYER_MASK_MISC	(0<<28)
+		#define KCQE_FLAGS_LAYER_MASK_L2	(2<<28)
+		#define KCQE_FLAGS_LAYER_MASK_L3	(3<<28)
+		#define KCQE_FLAGS_LAYER_MASK_L4	(4<<28)
+		#define KCQE_FLAGS_LAYER_MASK_L5_RDMA	(5<<28)
+		#define KCQE_FLAGS_LAYER_MASK_L5_ISCSI	(6<<28)
+		#define KCQE_FLAGS_NEXT 		(1<<31)
+		#define KCQE_FLAGS_OPCODE_MASK		(0xff<<16)
+		#define KCQE_FLAGS_OPCODE_SHIFT		(16)
+		#define KCQE_OPCODE(op)			\
+		(((op) & KCQE_FLAGS_OPCODE_MASK) >> KCQE_FLAGS_OPCODE_SHIFT)
+};
+
+#define MAX_CNIC_CTL_DATA	64
+#define MAX_DRV_CTL_DATA	64
+
+#define CNIC_CTL_STOP_CMD		1
+#define CNIC_CTL_START_CMD		2
+#define CNIC_CTL_COMPLETION_CMD		3
+
+#define DRV_CTL_IO_WR_CMD		0x101
+#define DRV_CTL_IO_RD_CMD		0x102
+#define DRV_CTL_CTX_WR_CMD		0x103
+#define DRV_CTL_CTXTBL_WR_CMD		0x104
+#define DRV_CTL_COMPLETION_CMD		0x105
+
+struct cnic_ctl_completion {
+	u32	cid;
+};
+
+struct drv_ctl_completion {
+	u32	comp_count;
+};
+
+struct cnic_ctl_info {
+	int	cmd;
+	union {
+		struct cnic_ctl_completion comp;
+		char bytes[MAX_CNIC_CTL_DATA];
+	} data;
+};
+
+struct drv_ctl_io {
+	u32		cid_addr;
+	u32		offset;
+	u32		data;
+	dma_addr_t	dma_addr;
+};
+
+struct drv_ctl_info {
+	int	cmd;
+	union {
+		struct drv_ctl_completion comp;
+		struct drv_ctl_io io;
+		char bytes[MAX_DRV_CTL_DATA];
+	} data;
+};
+
+struct cnic_ops {
+	struct module	*cnic_owner;
+	/* Calls to these functions are protected by RCU.  When
+	 * unregistering, we wait for any calls to complete before
+	 * continuing.
+	 */
+	int		(*cnic_handler)(void *, void *);
+	int		(*cnic_ctl)(void *, struct cnic_ctl_info *);
+};
+
+#define MAX_CNIC_VEC	8
+
+struct cnic_irq {
+	unsigned int	vector;
+	void		*status_blk;
+	u32		status_blk_num;
+	u32		irq_flags;
+#define CNIC_IRQ_FL_MSIX		0x00000001
+};
+
+struct cnic_eth_dev {
+	struct module	*drv_owner;
+	u32		drv_state;
+#define CNIC_DRV_STATE_REGD		0x00000001
+#define CNIC_DRV_STATE_USING_MSIX	0x00000002
+	u32		chip_id;
+	u32		max_kwqe_pending;
+	struct pci_dev	*pdev;
+	void __iomem	*io_base;
+
+	u32		ctx_tbl_offset;
+	u32		ctx_tbl_len;
+	int		ctx_blk_size;
+	u32		starting_cid;
+	u32		max_iscsi_conn;
+	u32		max_fcoe_conn;
+	u32		max_rdma_conn;
+	u32		reserved0[2];
+
+	int		num_irq;
+	struct cnic_irq	irq_arr[MAX_CNIC_VEC];
+	int		(*drv_register_cnic)(struct net_device *,
+					     struct cnic_ops *, void *);
+	int		(*drv_unregister_cnic)(struct net_device *);
+	int		(*drv_submit_kwqes_32)(struct net_device *,
+					       struct kwqe *[], u32);
+	int		(*drv_submit_kwqes_16)(struct net_device *,
+					       struct kwqe_16 *[], u32);
+	int		(*drv_ctl)(struct net_device *, struct drv_ctl_info *);
+	unsigned long	reserved1[2];
+};
+
+struct cnic_sockaddr {
+	union {
+		struct sockaddr_in	v4;
+		struct sockaddr_in6	v6;
+	} local;
+	union {
+		struct sockaddr_in	v4;
+		struct sockaddr_in6	v6;
+	} remote;
+};
+
+struct cnic_sock {
+	struct cnic_dev *dev;
+	void	*context;
+	u32	src_ip[4];
+	u32	dst_ip[4];
+	u16	src_port;
+	u16	dst_port;
+	u16	vlan_id;
+	unsigned char old_ha[6];
+	unsigned char ha[6];
+	u32	mtu;
+	u32	cid;
+	u32	l5_cid;
+	u32	pg_cid;
+	int	ulp_type;
+
+	u32	ka_timeout;
+	u32	ka_interval;
+	u8	ka_max_probe_count;
+	u8	tos;
+	u8	ttl;
+	u8	snd_seq_scale;
+	u32	rcv_buf;
+	u32	snd_buf;
+	u32	seed;
+
+	unsigned long	tcp_flags;
+#define SK_TCP_NO_DELAY_ACK	0x1
+#define SK_TCP_KEEP_ALIVE	0x2
+#define SK_TCP_NAGLE		0x4
+#define SK_TCP_TIMESTAMP	0x8
+#define SK_TCP_SACK		0x10
+#define SK_TCP_SEG_SCALING	0x20
+	unsigned long	flags;
+#define SK_F_INUSE		0
+#define SK_F_OFFLD_COMPLETE	1
+#define SK_F_OFFLD_SCHED	2
+#define SK_F_PG_OFFLD_COMPLETE	3
+#define SK_F_CONNECT_START	4
+#define SK_F_IPV6		5
+#define SK_F_CLOSING		7
+
+	atomic_t ref_count;
+	u32 state;
+	struct kwqe kwqe1;
+	struct kwqe kwqe2;
+	struct kwqe kwqe3;
+};
+
+struct cnic_dev {
+	struct net_device	*netdev;
+	struct pci_dev		*pcidev;
+	void __iomem		*regview;
+	struct list_head	list;
+
+	int (*register_device)(struct cnic_dev *dev, int ulp_type,
+			       void *ulp_ctx);
+	int (*unregister_device)(struct cnic_dev *dev, int ulp_type);
+	int (*submit_kwqes)(struct cnic_dev *dev, struct kwqe *wqes[],
+				u32 num_wqes);
+	int (*submit_kwqes_16)(struct cnic_dev *dev, struct kwqe_16 *wqes[],
+				u32 num_wqes);
+
+	int (*cm_create)(struct cnic_dev *, int, u32, u32, struct cnic_sock **,
+			 void *);
+	int (*cm_destroy)(struct cnic_sock *);
+	int (*cm_connect)(struct cnic_sock *, struct cnic_sockaddr *);
+	int (*cm_abort)(struct cnic_sock *);
+	int (*cm_close)(struct cnic_sock *);
+	struct cnic_dev *(*cm_select_dev)(struct sockaddr_in *, int ulp_type);
+	int (*iscsi_nl_msg_recv)(struct cnic_dev *dev, u32 msg_type,
+				 char *data, u16 data_size);
+	unsigned long	flags;
+#define CNIC_F_CNIC_UP		1
+#define CNIC_F_BNX2_CLASS	3
+#define CNIC_F_BNX2X_CLASS	4
+	atomic_t	ref_count;
+	u8		mac_addr[6];
+
+	int		max_iscsi_conn;
+	int		max_fcoe_conn;
+	int		max_rdma_conn;
+
+	void		*cnic_priv;
+};
+
+#define CNIC_WR(dev, off, val)		writel(val, dev->regview + off)
+#define CNIC_WR16(dev, off, val)	writew(val, dev->regview + off)
+#define CNIC_WR8(dev, off, val)		writeb(val, dev->regview + off)
+#define CNIC_RD(dev, off)		readl(dev->regview + off)
+#define CNIC_RD16(dev, off)		readw(dev->regview + off)
+
+struct cnic_ulp_ops {
+	/* Calls to these functions are protected by RCU.  When
+	 * unregistering, we wait for any calls to complete before
+	 * continuing.
+	 */
+
+	void (*cnic_init)(struct cnic_dev *dev);
+	void (*cnic_exit)(struct cnic_dev *dev);
+	void (*cnic_start)(void *ulp_ctx);
+	void (*cnic_stop)(void *ulp_ctx);
+	void (*indicate_kcqes)(void *ulp_ctx, struct kcqe *cqes[],
+				u32 num_cqes);
+	void (*indicate_netevent)(void *ulp_ctx, unsigned long event);
+	void (*cm_connect_complete)(struct cnic_sock *);
+	void (*cm_close_complete)(struct cnic_sock *);
+	void (*cm_abort_complete)(struct cnic_sock *);
+	void (*cm_remote_close)(struct cnic_sock *);
+	void (*cm_remote_abort)(struct cnic_sock *);
+	void (*iscsi_nl_send_msg)(struct cnic_dev *dev, u32 msg_type,
+				  char *data, u16 data_size);
+	struct module *owner;
+	atomic_t ref_count;
+};
+
+extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops);
+
+extern int cnic_unregister_driver(int ulp_type);
+
+extern struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/cpmac.c linux-libre-2.6.31-gnu/drivers/net/cpmac.c
--- linux-libre-2.6.30-gnu/drivers/net/cpmac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cpmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -202,7 +202,7 @@
 	void __iomem *regs;
 	struct mii_bus *mii_bus;
 	struct phy_device *phy;
-	char phy_name[BUS_ID_SIZE];
+	char phy_name[MII_BUS_ID_SIZE + 3];
 	int oldlink, oldspeed, oldduplex;
 	u32 msg_enable;
 	struct net_device *dev;
@@ -615,13 +615,13 @@
 
 		dev_kfree_skb_irq(desc->skb);
 		desc->skb = NULL;
-		if (netif_subqueue_stopped(dev, queue))
+		if (__netif_subqueue_stopped(dev, queue))
 			netif_wake_subqueue(dev, queue);
 	} else {
 		if (netif_msg_tx_err(priv) && net_ratelimit())
 			printk(KERN_WARNING
 			       "%s: end_xmit: spurious interrupt\n", dev->name);
-		if (netif_subqueue_stopped(dev, queue))
+		if (__netif_subqueue_stopped(dev, queue))
 			netif_wake_subqueue(dev, queue);
 	}
 }
@@ -731,7 +731,6 @@
 
 static void cpmac_hw_error(struct work_struct *work)
 {
-	int i;
 	struct cpmac_priv *priv =
 		container_of(work, struct cpmac_priv, reset_work);
 
@@ -818,7 +817,6 @@
 
 static void cpmac_tx_timeout(struct net_device *dev)
 {
-	int i;
 	struct cpmac_priv *priv = netdev_priv(dev);
 
 	spin_lock(&priv->lock);
@@ -1093,11 +1091,24 @@
 	return 0;
 }
 
+static const struct net_device_ops cpmac_netdev_ops = {
+	.ndo_open		= cpmac_open,
+	.ndo_stop		= cpmac_stop,
+	.ndo_start_xmit		= cpmac_start_xmit,
+	.ndo_tx_timeout		= cpmac_tx_timeout,
+	.ndo_set_multicast_list	= cpmac_set_multicast_list,
+	.ndo_do_ioctl		= cpmac_ioctl,
+	.ndo_set_config		= cpmac_config,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
 static int external_switch;
 
 static int __devinit cpmac_probe(struct platform_device *pdev)
 {
-	int rc, phy_id, i;
+	int rc, phy_id;
 	char *mdio_bus_id = "0";
 	struct resource *mem;
 	struct cpmac_priv *priv;
@@ -1143,14 +1154,8 @@
 
 	dev->irq = platform_get_irq_byname(pdev, "irq");
 
-	dev->open               = cpmac_open;
-	dev->stop               = cpmac_stop;
-	dev->set_config         = cpmac_config;
-	dev->hard_start_xmit    = cpmac_start_xmit;
-	dev->do_ioctl           = cpmac_ioctl;
-	dev->set_multicast_list = cpmac_set_multicast_list;
-	dev->tx_timeout         = cpmac_tx_timeout;
-	dev->ethtool_ops        = &cpmac_ethtool_ops;
+	dev->netdev_ops = &cpmac_netdev_ops;
+	dev->ethtool_ops = &cpmac_ethtool_ops;
 
 	netif_napi_add(dev, &priv->napi, cpmac_poll, 64);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/cs89x0.c linux-libre-2.6.31-gnu/drivers/net/cs89x0.c
--- linux-libre-2.6.30-gnu/drivers/net/cs89x0.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cs89x0.c	2009-09-09 18:13:59.000000000 -0400
@@ -1524,6 +1524,7 @@
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *lp = netdev_priv(dev);
+	unsigned long flags;
 
 	if (net_debug > 3) {
 		printk("%s: sent %d byte packet of type %x\n",
@@ -1535,7 +1536,7 @@
                   ask the chip to start transmitting before the
                   whole packet has been completely uploaded. */
 
-	spin_lock_irq(&lp->lock);
+	spin_lock_irqsave(&lp->lock, flags);
 	netif_stop_queue(dev);
 
 	/* initiate a transmit sequence */
@@ -1549,13 +1550,13 @@
 		 * we're waiting for TxOk, so return 1 and requeue this packet.
 		 */
 
-		spin_unlock_irq(&lp->lock);
+		spin_unlock_irqrestore(&lp->lock, flags);
 		if (net_debug) printk("cs89x0: Tx buffer not free!\n");
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	/* Write the contents of the packet */
 	writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
-	spin_unlock_irq(&lp->lock);
+	spin_unlock_irqrestore(&lp->lock, flags);
 	lp->stats.tx_bytes += skb->len;
 	dev->trans_start = jiffies;
 	dev_kfree_skb (skb);
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/adapter.h linux-libre-2.6.31-gnu/drivers/net/cxgb3/adapter.h
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/adapter.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/adapter.h	2009-09-09 18:13:59.000000000 -0400
@@ -195,7 +195,7 @@
 	struct sge_rspq rspq;
 	struct sge_fl fl[SGE_RXQ_PER_SET];
 	struct sge_txq txq[SGE_TXQ_PER_SET];
-	struct napi_gro_fraginfo lro_frag_tbl;
+	int nomem;
 	int lro_enabled;
 	void *lro_va;
 	struct net_device *netdev;
@@ -253,6 +253,8 @@
 	struct mutex mdio_lock;
 	spinlock_t stats_lock;
 	spinlock_t work_lock;
+
+	struct sk_buff *nofail_skb;
 };
 
 static inline u32 t3_read_reg(struct adapter *adapter, u32 reg_addr)
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/ael1002.c linux-libre-2.6.31-gnu/drivers/net/cxgb3/ael1002.c
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/ael1002.c	2012-03-22 19:14:53.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/ael1002.c	2012-03-22 20:11:04.000000000 -0400
@@ -33,14 +33,6 @@
 #include "regs.h"
 
 enum {
-	PMD_RSD     = 10,   /* PMA/PMD receive signal detect register */
-	PCS_STAT1_X = 24,   /* 10GBASE-X PCS status 1 register */
-	PCS_STAT1_R = 32,   /* 10GBASE-R PCS status 1 register */
-	XS_LN_STAT  = 24    /* XS lane status register */
-};
-
-enum {
-	AEL100X_TX_DISABLE = 9,
 	AEL100X_TX_CONFIG1 = 0xc002,
 	AEL1002_PWR_DOWN_HI = 0xc011,
 	AEL1002_PWR_DOWN_LO = 0xc012,
@@ -52,12 +44,33 @@
 	AEL_I2C_STAT = 0xc30c,
 	AEL2005_GPIO_CTRL = 0xc214,
 	AEL2005_GPIO_STAT = 0xc215,
+
+	AEL2020_GPIO_INTR   = 0xc103,	/* Latch High (LH) */
+	AEL2020_GPIO_CTRL   = 0xc108,	/* Store Clear (SC) */
+	AEL2020_GPIO_STAT   = 0xc10c,	/* Read Only (RO) */
+	AEL2020_GPIO_CFG    = 0xc110,	/* Read Write (RW) */
+
+	AEL2020_GPIO_SDA    = 0,	/* IN: i2c serial data */
+	AEL2020_GPIO_MODDET = 1,	/* IN: Module Detect */
+	AEL2020_GPIO_0      = 3,	/* IN: unassigned */
+	AEL2020_GPIO_1      = 2,	/* OUT: unassigned */
+	AEL2020_GPIO_LSTAT  = AEL2020_GPIO_1, /* wired to link status LED */
 };
 
 enum { edc_none, edc_sr, edc_twinax };
 
 /* PHY module I2C device address */
-#define MODULE_DEV_ADDR 0xa0
+enum {
+	MODULE_DEV_ADDR	= 0xa0,
+	SFF_DEV_ADDR	= 0xa2,
+};
+
+/* PHY transceiver type */
+enum {
+	phy_transtype_unknown = 0,
+	phy_transtype_sfp     = 3,
+	phy_transtype_xfp     = 6,
+};
 
 #define AEL2005_MODDET_IRQ 4
 
@@ -74,8 +87,8 @@
 
 	for (err = 0; rv->mmd_addr && !err; rv++) {
 		if (rv->clear_bits == 0xffff)
-			err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
-					 rv->set_bits);
+			err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr,
+					    rv->set_bits);
 		else
 			err = t3_mdio_change_bits(phy, rv->mmd_addr,
 						  rv->reg_addr, rv->clear_bits,
@@ -86,21 +99,54 @@
 
 static void ael100x_txon(struct cphy *phy)
 {
-	int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
+	int tx_on_gpio =
+		phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
 
 	msleep(100);
 	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
 	msleep(30);
 }
 
+/*
+ * Read an 8-bit word from a device attached to the PHY's i2c bus.
+ */
+static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
+{
+	int i, err;
+	unsigned int stat, data;
+
+	err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL,
+			    (dev_addr << 8) | (1 << 8) | word_addr);
+	if (err)
+		return err;
+
+	for (i = 0; i < 200; i++) {
+		msleep(1);
+		err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat);
+		if (err)
+			return err;
+		if ((stat & 3) == 1) {
+			err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA,
+					   &data);
+			if (err)
+				return err;
+			return data >> 8;
+		}
+	}
+	CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %#x.%#x timed out\n",
+		phy->mdio.prtad, dev_addr, word_addr);
+	return -ETIMEDOUT;
+}
+
 static int ael1002_power_down(struct cphy *phy, int enable)
 {
 	int err;
 
-	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
+	err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable);
 	if (!err)
-		err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
-					  BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
+		err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
+				    MDIO_MMD_PMAPMD, MDIO_CTRL1,
+				    MDIO_CTRL1_LPOWER, enable);
 	return err;
 }
 
@@ -109,11 +155,11 @@
 	int err;
 
 	if ((err = ael1002_power_down(phy, 0)) ||
-	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
-	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
-	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
-	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
-	    (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
+	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) ||
+	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) ||
+	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) ||
+	    (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) ||
+	    (err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN,
 				       0, 1 << 5)))
 		return err;
 	return 0;
@@ -132,12 +178,15 @@
 {
 	if (link_ok) {
 		unsigned int stat0, stat1, stat2;
-		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
+		int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
+				       MDIO_PMA_RXDET, &stat0);
 
 		if (!err)
-			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
+			err = t3_mdio_read(phy, MDIO_MMD_PCS,
+					   MDIO_PCS_10GBRT_STAT1, &stat1);
 		if (!err)
-			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
+			err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
+					   MDIO_PHYXS_LNSTAT, &stat2);
 		if (err)
 			return err;
 		*link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
@@ -157,6 +206,7 @@
 	.intr_handler = ael1002_intr_noop,
 	.get_link_status = get_link_status_r,
 	.power_down = ael1002_power_down,
+	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
 };
 
 int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -171,13 +221,13 @@
 
 static int ael1006_reset(struct cphy *phy, int wait)
 {
-	return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
+	return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait);
 }
 
 static int ael1006_power_down(struct cphy *phy, int enable)
 {
-	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
-				   BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
+	return mdio_set_flag(&phy->mdio, phy->mdio.prtad, MDIO_MMD_PMAPMD,
+			     MDIO_CTRL1, MDIO_CTRL1_LPOWER, enable);
 }
 
 static struct cphy_ops ael1006_ops = {
@@ -188,6 +238,7 @@
 	.intr_handler = t3_phy_lasi_intr_handler,
 	.get_link_status = get_link_status_r,
 	.power_down = ael1006_power_down,
+	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
 };
 
 int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -200,12 +251,57 @@
 	return 0;
 }
 
+/*
+ * Decode our module type.
+ */
+static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
+{
+	int v;
+
+	if (delay_ms)
+		msleep(delay_ms);
+
+	/* see SFF-8472 for below */
+	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
+	if (v < 0)
+		return v;
+
+	if (v == 0x10)
+		return phy_modtype_sr;
+	if (v == 0x20)
+		return phy_modtype_lr;
+	if (v == 0x40)
+		return phy_modtype_lrm;
+
+	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
+	if (v < 0)
+		return v;
+	if (v != 4)
+		goto unknown;
+
+	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
+	if (v < 0)
+		return v;
+
+	if (v & 0x80) {
+		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
+		if (v < 0)
+			return v;
+		return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
+	}
+unknown:
+	return phy_modtype_unknown;
+}
+
+/*
+ * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
+ */
 static int ael2005_setup_sr_edc(struct cphy *phy)
 {
 	static struct reg_val regs[] = {
-		{ MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
-		{ MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
-		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
+		{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
+		{ MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
+		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
 		{ 0, 0, 0, 0 }
 	};
 	/*(DEBLOBBED)*/
@@ -228,12 +324,12 @@
 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
 {
 	static struct reg_val regs[] = {
-		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
+		{ MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
 		{ 0, 0, 0, 0 }
 	};
 	static struct reg_val preemphasis[] = {
-		{ MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
-		{ MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
+		{ MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
+		{ MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
 		{ 0, 0, 0, 0 }
 	};
 	/*(DEBLOBBED)*/
@@ -255,125 +351,66 @@
 	return err;
 }
 
-static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
-{
-	int i, err;
-	unsigned int stat, data;
-
-	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
-			 (dev_addr << 8) | (1 << 8) | word_addr);
-	if (err)
-		return err;
-
-	for (i = 0; i < 5; i++) {
-		msleep(1);
-		err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
-		if (err)
-			return err;
-		if ((stat & 3) == 1) {
-			err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
-					&data);
-			if (err)
-				return err;
-			return data >> 8;
-		}
-	}
-	CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n",
-		phy->addr, word_addr);
-	return -ETIMEDOUT;
-}
-
-static int get_module_type(struct cphy *phy, int delay_ms)
+static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
 {
 	int v;
 	unsigned int stat;
 
-	v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
+	v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat);
 	if (v)
 		return v;
 
 	if (stat & (1 << 8))			/* module absent */
 		return phy_modtype_none;
 
-	if (delay_ms)
-		msleep(delay_ms);
-
-	/* see SFF-8472 for below */
-	v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3);
-	if (v < 0)
-		return v;
-
-	if (v == 0x10)
-		return phy_modtype_sr;
-	if (v == 0x20)
-		return phy_modtype_lr;
-	if (v == 0x40)
-		return phy_modtype_lrm;
-
-	v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6);
-	if (v < 0)
-		return v;
-	if (v != 4)
-		goto unknown;
-
-	v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10);
-	if (v < 0)
-		return v;
-
-	if (v & 0x80) {
-		v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
-		if (v < 0)
-			return v;
-		return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
-	}
-unknown:
-	return phy_modtype_unknown;
+	return ael2xxx_get_module_type(phy, delay_ms);
 }
 
 static int ael2005_intr_enable(struct cphy *phy)
 {
-	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
+	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200);
 	return err ? err : t3_phy_lasi_intr_enable(phy);
 }
 
 static int ael2005_intr_disable(struct cphy *phy)
 {
-	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
+	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100);
 	return err ? err : t3_phy_lasi_intr_disable(phy);
 }
 
 static int ael2005_intr_clear(struct cphy *phy)
 {
-	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
+	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00);
 	return err ? err : t3_phy_lasi_intr_clear(phy);
 }
 
 static int ael2005_reset(struct cphy *phy, int wait)
 {
 	static struct reg_val regs0[] = {
-		{ MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
-		{ MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
-		{ MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
-		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
-		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
-		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
-		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
+		{ MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
+		{ MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
+		{ MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
+		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
+		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 },
+		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
+		{ MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
 		{ 0, 0, 0, 0 }
 	};
 	static struct reg_val regs1[] = {
-		{ MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
-		{ MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
+		{ MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
+		{ MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
 		{ 0, 0, 0, 0 }
 	};
 
 	int err;
 	unsigned int lasi_ctrl;
 
-	err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
+	err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
+			   &lasi_ctrl);
 	if (err)
 		return err;
 
-	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
+	err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0);
 	if (err)
 		return err;
 
@@ -385,7 +422,7 @@
 
 	msleep(50);
 
-	err = get_module_type(phy, 0);
+	err = ael2005_get_module_type(phy, 0);
 	if (err < 0)
 		return err;
 	phy->modtype = err;
@@ -412,18 +449,18 @@
 	unsigned int stat;
 	int ret, edc_needed, cause = 0;
 
-	ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
+	ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat);
 	if (ret)
 		return ret;
 
 	if (stat & AEL2005_MODDET_IRQ) {
-		ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
-				 0xd00);
+		ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL,
+				    0xd00);
 		if (ret)
 			return ret;
 
 		/* modules have max 300 ms init time after hot plug */
-		ret = get_module_type(phy, 300);
+		ret = ael2005_get_module_type(phy, 300);
 		if (ret < 0)
 			return ret;
 
@@ -459,6 +496,7 @@
 	.intr_handler    = ael2005_intr_handler,
 	.get_link_status = get_link_status_r,
 	.power_down      = ael1002_power_down,
+	.mmds            = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
 };
 
 int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -468,11 +506,269 @@
 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
 		  SUPPORTED_IRQ, "10GBASE-R");
 	msleep(125);
-	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
+	return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0,
 				   1 << 5);
 }
 
 /*
+ * Setup EDC and other parameters for operation with an optical module.
+ */
+static int ael2020_setup_sr_edc(struct cphy *phy)
+{
+	static struct reg_val regs[] = {
+		/* set CDR offset to 10 */
+		{ MDIO_MMD_PMAPMD, 0xcc01, 0xffff, 0x488a },
+
+		/* adjust 10G RX bias current */
+		{ MDIO_MMD_PMAPMD, 0xcb1b, 0xffff, 0x0200 },
+		{ MDIO_MMD_PMAPMD, 0xcb1c, 0xffff, 0x00f0 },
+		{ MDIO_MMD_PMAPMD, 0xcc06, 0xffff, 0x00e0 },
+
+		/* end */
+		{ 0, 0, 0, 0 }
+	};
+	int err;
+
+	err = set_phy_regs(phy, regs);
+	msleep(50);
+	if (err)
+		return err;
+
+	phy->priv = edc_sr;
+	return 0;
+}
+
+/*
+ * Setup EDC and other parameters for operation with an TWINAX module.
+ */
+static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
+{
+	/* set uC to 40MHz */
+	static struct reg_val uCclock40MHz[] = {
+		{ MDIO_MMD_PMAPMD, 0xff28, 0xffff, 0x4001 },
+		{ MDIO_MMD_PMAPMD, 0xff2a, 0xffff, 0x0002 },
+		{ 0, 0, 0, 0 }
+	};
+
+	/* activate uC clock */
+	static struct reg_val uCclockActivate[] = {
+		{ MDIO_MMD_PMAPMD, 0xd000, 0xffff, 0x5200 },
+		{ 0, 0, 0, 0 }
+	};
+
+	/* set PC to start of SRAM and activate uC */
+	static struct reg_val uCactivate[] = {
+		{ MDIO_MMD_PMAPMD, 0xd080, 0xffff, 0x0100 },
+		{ MDIO_MMD_PMAPMD, 0xd092, 0xffff, 0x0000 },
+		{ 0, 0, 0, 0 }
+	};
+
+	/* TWINAX EDC firmware */
+	/*(DEBLOBBED)*/
+	int i, err;
+
+	/* set uC clock and activate it */
+	err = set_phy_regs(phy, uCclock40MHz);
+	msleep(500);
+	if (err)
+		return err;
+	err = set_phy_regs(phy, uCclockActivate);
+	msleep(500);
+	if (err)
+		return err;
+
+	/* write TWINAX EDC firmware into PHY */
+	/*(DEBLOBBED)*/
+	/* activate uC */
+	err = set_phy_regs(phy, uCactivate);
+	if (!err)
+		phy->priv = edc_twinax;
+	return err;
+}
+
+/*
+ * Return Module Type.
+ */
+static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
+{
+	int v;
+	unsigned int stat;
+
+	v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_STAT, &stat);
+	if (v)
+		return v;
+
+	if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
+		/* module absent */
+		return phy_modtype_none;
+	}
+
+	return ael2xxx_get_module_type(phy, delay_ms);
+}
+
+/*
+ * Enable PHY interrupts.  We enable "Module Detection" interrupts (on any
+ * state transition) and then generic Link Alarm Status Interrupt (LASI).
+ */
+static int ael2020_intr_enable(struct cphy *phy)
+{
+	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
+				0x2 << (AEL2020_GPIO_MODDET*4));
+	return err ? err : t3_phy_lasi_intr_enable(phy);
+}
+
+/*
+ * Disable PHY interrupts.  The mirror of the above ...
+ */
+static int ael2020_intr_disable(struct cphy *phy)
+{
+	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
+				0x1 << (AEL2020_GPIO_MODDET*4));
+	return err ? err : t3_phy_lasi_intr_disable(phy);
+}
+
+/*
+ * Clear PHY interrupt state.
+ */
+static int ael2020_intr_clear(struct cphy *phy)
+{
+	/*
+	 * The GPIO Interrupt register on the AEL2020 is a "Latching High"
+	 * (LH) register which is cleared to the current state when it's read.
+	 * Thus, we simply read the register and discard the result.
+	 */
+	unsigned int stat;
+	int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
+	return err ? err : t3_phy_lasi_intr_clear(phy);
+}
+
+/*
+ * Reset the PHY and put it into a canonical operating state.
+ */
+static int ael2020_reset(struct cphy *phy, int wait)
+{
+	static struct reg_val regs0[] = {
+		/* Erratum #2: CDRLOL asserted, causing PMA link down status */
+		{ MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 },
+
+		/* force XAUI to send LF when RX_LOS is asserted */
+		{ MDIO_MMD_PMAPMD, 0xcd40, 0xffff, 0x0001 },
+
+		/* RX_LOS pin is active high */
+		{ MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS,
+			0x0020, 0x0020 },
+
+		/* output Module's Loss Of Signal (LOS) to LED */
+		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
+			0xffff, 0x0004 },
+		{ MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
+			0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
+
+		/* end */
+		{ 0, 0, 0, 0 }
+	};
+	int err;
+	unsigned int lasi_ctrl;
+
+	/* grab current interrupt state */
+	err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
+			   &lasi_ctrl);
+	if (err)
+		return err;
+
+	err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 125);
+	if (err)
+		return err;
+	msleep(100);
+
+	/* basic initialization for all module types */
+	phy->priv = edc_none;
+	err = set_phy_regs(phy, regs0);
+	if (err)
+		return err;
+
+	/* determine module type and perform appropriate initialization */
+	err = ael2020_get_module_type(phy, 0);
+	if (err < 0)
+		return err;
+	phy->modtype = (u8)err;
+	if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
+		err = ael2020_setup_twinax_edc(phy, err);
+	else
+		err = ael2020_setup_sr_edc(phy);
+	if (err)
+		return err;
+
+	/* reset wipes out interrupts, reenable them if they were on */
+	if (lasi_ctrl & 1)
+		err = ael2005_intr_enable(phy);
+	return err;
+}
+
+/*
+ * Handle a PHY interrupt.
+ */
+static int ael2020_intr_handler(struct cphy *phy)
+{
+	unsigned int stat;
+	int ret, edc_needed, cause = 0;
+
+	ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
+	if (ret)
+		return ret;
+
+	if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
+		/* modules have max 300 ms init time after hot plug */
+		ret = ael2020_get_module_type(phy, 300);
+		if (ret < 0)
+			return ret;
+
+		phy->modtype = (u8)ret;
+		if (ret == phy_modtype_none)
+			edc_needed = phy->priv;       /* on unplug retain EDC */
+		else if (ret == phy_modtype_twinax ||
+			 ret == phy_modtype_twinax_long)
+			edc_needed = edc_twinax;
+		else
+			edc_needed = edc_sr;
+
+		if (edc_needed != phy->priv) {
+			ret = ael2020_reset(phy, 0);
+			return ret ? ret : cphy_cause_module_change;
+		}
+		cause = cphy_cause_module_change;
+	}
+
+	ret = t3_phy_lasi_intr_handler(phy);
+	if (ret < 0)
+		return ret;
+
+	ret |= cause;
+	return ret ? ret : cphy_cause_link_change;
+}
+
+static struct cphy_ops ael2020_ops = {
+	.reset           = ael2020_reset,
+	.intr_enable     = ael2020_intr_enable,
+	.intr_disable    = ael2020_intr_disable,
+	.intr_clear      = ael2020_intr_clear,
+	.intr_handler    = ael2020_intr_handler,
+	.get_link_status = get_link_status_r,
+	.power_down      = ael1002_power_down,
+	.mmds		 = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
+};
+
+int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
+			const struct mdio_ops *mdio_ops)
+{
+	cphy_init(phy, adapter, phy_addr, &ael2020_ops, mdio_ops,
+		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
+		  SUPPORTED_IRQ, "10GBASE-R");
+	msleep(125);
+	return 0;
+}
+
+/*
  * Get link status for a 10GBASE-X device.
  */
 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
@@ -480,12 +776,15 @@
 {
 	if (link_ok) {
 		unsigned int stat0, stat1, stat2;
-		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
+		int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
+				       MDIO_PMA_RXDET, &stat0);
 
 		if (!err)
-			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
+			err = t3_mdio_read(phy, MDIO_MMD_PCS,
+					   MDIO_PCS_10GBX_STAT1, &stat1);
 		if (!err)
-			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
+			err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
+					   MDIO_PHYXS_LNSTAT, &stat2);
 		if (err)
 			return err;
 		*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
@@ -505,6 +804,7 @@
 	.intr_handler = t3_phy_lasi_intr_handler,
 	.get_link_status = get_link_status_x,
 	.power_down = ael1006_power_down,
+	.mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
 };
 
 int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
@@ -520,9 +820,10 @@
 	 * Some cards where the PHY is supposed to be at address 0 actually
 	 * have it at 1.
 	 */
-	if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
+	if (!phy_addr &&
+	    !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) &&
 	    stat == 0xffff)
-		phy->addr = 1;
+		phy->mdio.prtad = 1;
 	return 0;
 }
 
@@ -536,15 +837,16 @@
 {
 	if (link_ok) {
 		unsigned int status;
+		int prtad = phy->mdio.prtad;
 
 		status = t3_read_reg(phy->adapter,
-				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
+				     XGM_REG(A_XGM_SERDES_STAT0, prtad)) |
 		    t3_read_reg(phy->adapter,
-				XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
+				    XGM_REG(A_XGM_SERDES_STAT1, prtad)) |
 		    t3_read_reg(phy->adapter,
-				XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
+				XGM_REG(A_XGM_SERDES_STAT2, prtad)) |
 		    t3_read_reg(phy->adapter,
-				XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
+				XGM_REG(A_XGM_SERDES_STAT3, prtad));
 		*link_ok = !(status & F_LOWSIG0);
 	}
 	if (speed)
@@ -572,7 +874,7 @@
 int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
 			    int phy_addr, const struct mdio_ops *mdio_ops)
 {
-	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
+	cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops,
 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
 		  "10GBASE-CX4");
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/aq100x.c linux-libre-2.6.31-gnu/drivers/net/cxgb3/aq100x.c
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/aq100x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/aq100x.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "common.h"
+#include "regs.h"
+
+enum {
+	/* MDIO_DEV_PMA_PMD registers */
+	AQ_LINK_STAT	= 0xe800,
+	AQ_IMASK_PMA	= 0xf000,
+
+	/* MDIO_DEV_XGXS registers */
+	AQ_XAUI_RX_CFG	= 0xc400,
+	AQ_XAUI_TX_CFG	= 0xe400,
+
+	/* MDIO_DEV_ANEG registers */
+	AQ_1G_CTRL	= 0xc400,
+	AQ_ANEG_STAT	= 0xc800,
+
+	/* MDIO_DEV_VEND1 registers */
+	AQ_FW_VERSION	= 0x0020,
+	AQ_IFLAG_GLOBAL	= 0xfc00,
+	AQ_IMASK_GLOBAL	= 0xff00,
+};
+
+enum {
+	IMASK_PMA	= 1 << 2,
+	IMASK_GLOBAL	= 1 << 15,
+	ADV_1G_FULL	= 1 << 15,
+	ADV_1G_HALF	= 1 << 14,
+	ADV_10G_FULL	= 1 << 12,
+	AQ_RESET	= (1 << 14) | (1 << 15),
+	AQ_LOWPOWER	= 1 << 12,
+};
+
+static int aq100x_reset(struct cphy *phy, int wait)
+{
+	/*
+	 * Ignore the caller specified wait time; always wait for the reset to
+	 * complete. Can take up to 3s.
+	 */
+	int err = t3_phy_reset(phy, MDIO_MMD_VEND1, 3000);
+
+	if (err)
+		CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n",
+			phy->mdio.prtad, err);
+
+	return err;
+}
+
+static int aq100x_intr_enable(struct cphy *phy)
+{
+	int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AQ_IMASK_PMA, IMASK_PMA);
+	if (err)
+		return err;
+
+	err = t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, IMASK_GLOBAL);
+	return err;
+}
+
+static int aq100x_intr_disable(struct cphy *phy)
+{
+	return t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, 0);
+}
+
+static int aq100x_intr_clear(struct cphy *phy)
+{
+	unsigned int v;
+
+	t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &v);
+	t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v);
+
+	return 0;
+}
+
+static int aq100x_intr_handler(struct cphy *phy)
+{
+	int err;
+	unsigned int cause, v;
+
+	err = t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &cause);
+	if (err)
+		return err;
+
+	/* Read (and reset) the latching version of the status */
+	t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v);
+
+	return cphy_cause_link_change;
+}
+
+static int aq100x_power_down(struct cphy *phy, int off)
+{
+	return mdio_set_flag(&phy->mdio, phy->mdio.prtad,
+			     MDIO_MMD_PMAPMD, MDIO_CTRL1,
+			     MDIO_CTRL1_LPOWER, off);
+}
+
+static int aq100x_autoneg_enable(struct cphy *phy)
+{
+	int err;
+
+	err = aq100x_power_down(phy, 0);
+	if (!err)
+		err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
+				    MDIO_MMD_AN, MDIO_CTRL1,
+				    BMCR_ANENABLE | BMCR_ANRESTART, 1);
+
+	return err;
+}
+
+static int aq100x_autoneg_restart(struct cphy *phy)
+{
+	int err;
+
+	err = aq100x_power_down(phy, 0);
+	if (!err)
+		err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
+				    MDIO_MMD_AN, MDIO_CTRL1,
+				    BMCR_ANENABLE | BMCR_ANRESTART, 1);
+
+	return err;
+}
+
+static int aq100x_advertise(struct cphy *phy, unsigned int advertise_map)
+{
+	unsigned int adv;
+	int err;
+
+	/* 10G advertisement */
+	adv = 0;
+	if (advertise_map & ADVERTISED_10000baseT_Full)
+		adv |= ADV_10G_FULL;
+	err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+				  ADV_10G_FULL, adv);
+	if (err)
+		return err;
+
+	/* 1G advertisement */
+	adv = 0;
+	if (advertise_map & ADVERTISED_1000baseT_Full)
+		adv |= ADV_1G_FULL;
+	if (advertise_map & ADVERTISED_1000baseT_Half)
+		adv |= ADV_1G_HALF;
+	err = t3_mdio_change_bits(phy, MDIO_MMD_AN, AQ_1G_CTRL,
+				  ADV_1G_FULL | ADV_1G_HALF, adv);
+	if (err)
+		return err;
+
+	/* 100M, pause advertisement */
+	adv = 0;
+	if (advertise_map & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise_map & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	if (advertise_map & ADVERTISED_Pause)
+		adv |= ADVERTISE_PAUSE_CAP;
+	if (advertise_map & ADVERTISED_Asym_Pause)
+		adv |= ADVERTISE_PAUSE_ASYM;
+	err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
+				  0xfe0, adv);
+
+	return err;
+}
+
+static int aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
+{
+	return mdio_set_flag(&phy->mdio, phy->mdio.prtad,
+			     MDIO_MMD_PMAPMD, MDIO_CTRL1,
+			     BMCR_LOOPBACK, enable);
+}
+
+static int aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
+{
+	/* no can do */
+	return -1;
+}
+
+static int aq100x_get_link_status(struct cphy *phy, int *link_ok,
+				  int *speed, int *duplex, int *fc)
+{
+	int err;
+	unsigned int v;
+
+	if (link_ok) {
+		err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AQ_LINK_STAT, &v);
+		if (err)
+			return err;
+
+		*link_ok = v & 1;
+		if (!*link_ok)
+			return 0;
+	}
+
+	err = t3_mdio_read(phy, MDIO_MMD_AN, AQ_ANEG_STAT, &v);
+	if (err)
+		return err;
+
+	if (speed) {
+		switch (v & 0x6) {
+		case 0x6:
+			*speed = SPEED_10000;
+			break;
+		case 0x4:
+			*speed = SPEED_1000;
+			break;
+		case 0x2:
+			*speed = SPEED_100;
+			break;
+		case 0x0:
+			*speed = SPEED_10;
+			break;
+		}
+	}
+
+	if (duplex)
+		*duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
+
+	return 0;
+}
+
+static struct cphy_ops aq100x_ops = {
+	.reset             = aq100x_reset,
+	.intr_enable       = aq100x_intr_enable,
+	.intr_disable      = aq100x_intr_disable,
+	.intr_clear        = aq100x_intr_clear,
+	.intr_handler      = aq100x_intr_handler,
+	.autoneg_enable    = aq100x_autoneg_enable,
+	.autoneg_restart   = aq100x_autoneg_restart,
+	.advertise         = aq100x_advertise,
+	.set_loopback      = aq100x_set_loopback,
+	.set_speed_duplex  = aq100x_set_speed_duplex,
+	.get_link_status   = aq100x_get_link_status,
+	.power_down        = aq100x_power_down,
+	.mmds 		   = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
+};
+
+int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
+		       const struct mdio_ops *mdio_ops)
+{
+	unsigned int v, v2, gpio, wait;
+	int err;
+
+	cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops,
+		  SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
+		  SUPPORTED_Autoneg | SUPPORTED_AUI, "1000/10GBASE-T");
+
+	/*
+	 * The PHY has been out of reset ever since the system powered up.  So
+	 * we do a hard reset over here.
+	 */
+	gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
+	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
+	msleep(1);
+	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
+
+	/*
+	 * Give it enough time to load the firmware and get ready for mdio.
+	 */
+	msleep(1000);
+	wait = 500; /* in 10ms increments */
+	do {
+		err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
+		if (err || v == 0xffff) {
+
+			/* Allow prep_adapter to succeed when ffff is read */
+
+			CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
+				phy_addr, err, v);
+			goto done;
+		}
+
+		v &= AQ_RESET;
+		if (v)
+			msleep(10);
+	} while (v && --wait);
+	if (v) {
+		CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
+			phy_addr, v);
+
+		goto done; /* let prep_adapter succeed */
+	}
+
+	/* Datasheet says 3s max but this has been observed */
+	wait = (500 - wait) * 10 + 1000;
+	if (wait > 3000)
+		CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait);
+
+	/* Firmware version check. */
+	t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v);
+	if (v != 30) {
+		CH_WARN(adapter, "PHY%d: unsupported firmware %d\n",
+			phy_addr, v);
+		return 0; /* allow t3_prep_adapter to succeed */
+	}
+
+	/*
+	 * The PHY should start in really-low-power mode.  Prepare it for normal
+	 * operations.
+	 */
+	err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
+	if (err)
+		return err;
+	if (v & AQ_LOWPOWER) {
+		err = t3_mdio_change_bits(phy, MDIO_MMD_VEND1, MDIO_CTRL1,
+					  AQ_LOWPOWER, 0);
+		if (err)
+			return err;
+		msleep(10);
+	} else
+		CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
+			phy_addr);
+
+	/*
+	 * Verify XAUI settings, but let prep succeed no matter what.
+	 */
+	v = v2 = 0;
+	t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_RX_CFG, &v);
+	t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_TX_CFG, &v2);
+	if (v != 0x1b || v2 != 0x1b)
+		CH_WARN(adapter,
+			"PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n",
+			phy_addr, v, v2);
+
+done:
+	return err;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/common.h linux-libre-2.6.31-gnu/drivers/net/cxgb3/common.h
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/common.h	2009-09-09 18:13:59.000000000 -0400
@@ -39,7 +39,7 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
-#include <linux/mii.h>
+#include <linux/mdio.h>
 #include "version.h"
 
 #define CH_ERR(adap, fmt, ...)   dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__)
@@ -184,10 +184,11 @@
 struct adapter;
 
 struct mdio_ops {
-	int (*read)(struct adapter *adapter, int phy_addr, int mmd_addr,
-		    int reg_addr, unsigned int *val);
-	int (*write)(struct adapter *adapter, int phy_addr, int mmd_addr,
-		     int reg_addr, unsigned int val);
+	int (*read)(struct net_device *dev, int phy_addr, int mmd_addr,
+		    u16 reg_addr);
+	int (*write)(struct net_device *dev, int phy_addr, int mmd_addr,
+		     u16 reg_addr, u16 val);
+	unsigned mode_support;
 };
 
 struct adapter_info {
@@ -520,27 +521,6 @@
 	MAC_RXFIFO_SIZE = 32768
 };
 
-/* IEEE 802.3 specified MDIO devices */
-enum {
-	MDIO_DEV_PMA_PMD = 1,
-	MDIO_DEV_WIS = 2,
-	MDIO_DEV_PCS = 3,
-	MDIO_DEV_XGXS = 4,
-	MDIO_DEV_ANEG = 7,
-	MDIO_DEV_VEND1 = 30,
-	MDIO_DEV_VEND2 = 31
-};
-
-/* LASI control and status registers */
-enum {
-	RX_ALARM_CTRL = 0x9000,
-	TX_ALARM_CTRL = 0x9001,
-	LASI_CTRL = 0x9002,
-	RX_ALARM_STAT = 0x9003,
-	TX_ALARM_STAT = 0x9004,
-	LASI_STAT = 0x9005
-};
-
 /* PHY loopback direction */
 enum {
 	PHY_LOOPBACK_TX = 1,
@@ -583,11 +563,12 @@
 	int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
 			       int *duplex, int *fc);
 	int (*power_down)(struct cphy *phy, int enable);
+
+	u32 mmds;
 };
 
 /* A PHY instance */
 struct cphy {
-	u8 addr;			/* PHY address */
 	u8 modtype;			/* PHY module type */
 	short priv;			/* scratch pad */
 	unsigned int caps;		/* PHY capabilities */
@@ -595,23 +576,23 @@
 	const char *desc;		/* PHY description */
 	unsigned long fifo_errors;	/* FIFO over/under-flows */
 	const struct cphy_ops *ops;	/* PHY operations */
-	int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr,
-			 int reg_addr, unsigned int *val);
-	int (*mdio_write)(struct adapter *adapter, int phy_addr, int mmd_addr,
-			  int reg_addr, unsigned int val);
+	struct mdio_if_info mdio;
 };
 
 /* Convenience MDIO read/write wrappers */
-static inline int mdio_read(struct cphy *phy, int mmd, int reg,
-			    unsigned int *valp)
+static inline int t3_mdio_read(struct cphy *phy, int mmd, int reg,
+			       unsigned int *valp)
 {
-	return phy->mdio_read(phy->adapter, phy->addr, mmd, reg, valp);
+	int rc = phy->mdio.mdio_read(phy->mdio.dev, phy->mdio.prtad, mmd, reg);
+	*valp = (rc >= 0) ? rc : -1;
+	return (rc >= 0) ? 0 : rc;
 }
 
-static inline int mdio_write(struct cphy *phy, int mmd, int reg,
-			     unsigned int val)
+static inline int t3_mdio_write(struct cphy *phy, int mmd, int reg,
+				unsigned int val)
 {
-	return phy->mdio_write(phy->adapter, phy->addr, mmd, reg, val);
+	return phy->mdio.mdio_write(phy->mdio.dev, phy->mdio.prtad, mmd,
+				    reg, val);
 }
 
 /* Convenience initializer */
@@ -620,14 +601,16 @@
 			     const struct mdio_ops *mdio_ops,
 			      unsigned int caps, const char *desc)
 {
-	phy->addr = phy_addr;
 	phy->caps = caps;
 	phy->adapter = adapter;
 	phy->desc = desc;
 	phy->ops = phy_ops;
 	if (mdio_ops) {
-		phy->mdio_read = mdio_ops->read;
-		phy->mdio_write = mdio_ops->write;
+		phy->mdio.prtad = phy_addr;
+		phy->mdio.mmds = phy_ops->mmds;
+		phy->mdio.mode_support = mdio_ops->mode_support;
+		phy->mdio.mdio_read = mdio_ops->read;
+		phy->mdio.mdio_write = mdio_ops->write;
 	}
 }
 
@@ -819,8 +802,12 @@
 			int phy_addr, const struct mdio_ops *mdio_ops);
 int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
 			int phy_addr, const struct mdio_ops *mdio_ops);
+int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter,
+			int phy_addr, const struct mdio_ops *mdio_ops);
 int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
 		       const struct mdio_ops *mdio_ops);
 int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
 			    int phy_addr, const struct mdio_ops *mdio_ops);
+int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter,
+			    int phy_addr, const struct mdio_ops *mdio_ops);
 #endif				/* __CHELSIO_COMMON_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/cxgb3_main.c linux-libre-2.6.31-gnu/drivers/net/cxgb3/cxgb3_main.c
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/cxgb3_main.c	2012-03-22 19:14:50.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/cxgb3_main.c	2012-03-22 20:10:59.000000000 -0400
@@ -37,7 +37,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
-#include <linux/mii.h>
+#include <linux/mdio.h>
 #include <linux/sockios.h>
 #include <linux/workqueue.h>
 #include <linux/proc_fs.h>
@@ -91,6 +91,8 @@
 	CH_DEVICE(0x31, 3),	/* T3B20 */
 	CH_DEVICE(0x32, 1),	/* T3B02 */
 	CH_DEVICE(0x35, 6),	/* T3C20-derived T3C10 */
+	CH_DEVICE(0x36, 3),	/* S320E-CR */
+	CH_DEVICE(0x37, 7),	/* N320E-G2 */
 	{0,}
 };
 
@@ -431,40 +433,78 @@
 	for (i = 0; i < 16; i++) {
 		struct cpl_smt_write_req *req;
 
-		skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
+		skb = alloc_skb(sizeof(*req), GFP_KERNEL);
+		if (!skb)
+			skb = adap->nofail_skb;
+		if (!skb)
+			goto alloc_skb_fail;
+
 		req = (struct cpl_smt_write_req *)__skb_put(skb, sizeof(*req));
 		memset(req, 0, sizeof(*req));
 		req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
 		OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i));
 		req->iff = i;
 		t3_mgmt_tx(adap, skb);
+		if (skb == adap->nofail_skb) {
+			await_mgmt_replies(adap, cnt, i + 1);
+			adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
+			if (!adap->nofail_skb)
+				goto alloc_skb_fail;
+		}
 	}
 
 	for (i = 0; i < 2048; i++) {
 		struct cpl_l2t_write_req *req;
 
-		skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
+		skb = alloc_skb(sizeof(*req), GFP_KERNEL);
+		if (!skb)
+			skb = adap->nofail_skb;
+		if (!skb)
+			goto alloc_skb_fail;
+
 		req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req));
 		memset(req, 0, sizeof(*req));
 		req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
 		OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, i));
 		req->params = htonl(V_L2T_W_IDX(i));
 		t3_mgmt_tx(adap, skb);
+		if (skb == adap->nofail_skb) {
+			await_mgmt_replies(adap, cnt, 16 + i + 1);
+			adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
+			if (!adap->nofail_skb)
+				goto alloc_skb_fail;
+		}
 	}
 
 	for (i = 0; i < 2048; i++) {
 		struct cpl_rte_write_req *req;
 
-		skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
+		skb = alloc_skb(sizeof(*req), GFP_KERNEL);
+		if (!skb)
+			skb = adap->nofail_skb;
+		if (!skb)
+			goto alloc_skb_fail;
+
 		req = (struct cpl_rte_write_req *)__skb_put(skb, sizeof(*req));
 		memset(req, 0, sizeof(*req));
 		req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
 		OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RTE_WRITE_REQ, i));
 		req->l2t_idx = htonl(V_L2T_W_IDX(i));
 		t3_mgmt_tx(adap, skb);
+		if (skb == adap->nofail_skb) {
+			await_mgmt_replies(adap, cnt, 16 + 2048 + i + 1);
+			adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
+			if (!adap->nofail_skb)
+				goto alloc_skb_fail;
+		}
 	}
 
-	skb = alloc_skb(sizeof(*greq), GFP_KERNEL | __GFP_NOFAIL);
+	skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
+	if (!skb)
+		skb = adap->nofail_skb;
+	if (!skb)
+		goto alloc_skb_fail;
+
 	greq = (struct cpl_set_tcb_field *)__skb_put(skb, sizeof(*greq));
 	memset(greq, 0, sizeof(*greq));
 	greq->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
@@ -473,8 +513,17 @@
 	t3_mgmt_tx(adap, skb);
 
 	i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1);
+	if (skb == adap->nofail_skb) {
+		i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1);
+		adap->nofail_skb = alloc_skb(sizeof(*greq), GFP_KERNEL);
+	}
+
 	t3_tp_set_offload_mode(adap, 0);
 	return i;
+
+alloc_skb_fail:
+	t3_tp_set_offload_mode(adap, 0);
+	return -ENOMEM;
 }
 
 /**
@@ -593,8 +642,7 @@
 		struct port_info *pi = netdev_priv(dev);
 
 		pi->qs = &adap->sge.qs[pi->first_qset];
-		for (j = pi->first_qset; j < pi->first_qset + pi->nqsets;
-		     ++j, ++qset_idx) {
+		for (j = 0; j < pi->nqsets; ++j, ++qset_idx) {
 			set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO);
 			err = t3_sge_alloc_qset(adap, qset_idx, 1,
 				(adap->flags & USING_MSIX) ? qset_idx + 1 :
@@ -869,7 +917,12 @@
 	struct mngt_pktsched_wr *req;
 	int ret;
 
-	skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
+	skb = alloc_skb(sizeof(*req), GFP_KERNEL);
+	if (!skb)
+		skb = adap->nofail_skb;
+	if (!skb)
+		return -ENOMEM;
+
 	req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req));
 	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT));
 	req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET;
@@ -879,6 +932,12 @@
 	req->max = hi;
 	req->binding = port;
 	ret = t3_mgmt_tx(adap, skb);
+	if (skb == adap->nofail_skb) {
+		adap->nofail_skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
+					     GFP_KERNEL);
+		if (!adap->nofail_skb)
+			ret = -ENOMEM;
+	}
 
 	return ret;
 }
@@ -1593,7 +1652,7 @@
 	}
 
 	cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
-	cmd->phy_address = p->phy.addr;
+	cmd->phy_address = p->phy.mdio.prtad;
 	cmd->transceiver = XCVR_EXTERNAL;
 	cmd->autoneg = p->link_config.autoneg;
 	cmd->maxtxpkt = 0;
@@ -2308,70 +2367,25 @@
 	struct mii_ioctl_data *data = if_mii(req);
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
-	int ret, mmd;
 
 	switch (cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = pi->phy.addr;
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		/* Convert phy_id from older PRTAD/DEVAD format */
+		if (is_10G(adapter) &&
+		    !mdio_phy_id_is_c45(data->phy_id) &&
+		    (data->phy_id & 0x1f00) &&
+		    !(data->phy_id & 0xe0e0))
+			data->phy_id = mdio_phy_id_c45(data->phy_id >> 8,
+						       data->phy_id & 0x1f);
 		/* FALLTHRU */
-	case SIOCGMIIREG:{
-		u32 val;
-		struct cphy *phy = &pi->phy;
-
-		if (!phy->mdio_read)
-			return -EOPNOTSUPP;
-		if (is_10G(adapter)) {
-			mmd = data->phy_id >> 8;
-			if (!mmd)
-				mmd = MDIO_DEV_PCS;
-			else if (mmd > MDIO_DEV_VEND2)
-				return -EINVAL;
-
-			ret =
-				phy->mdio_read(adapter, data->phy_id & 0x1f,
-						mmd, data->reg_num, &val);
-		} else
-			ret =
-				phy->mdio_read(adapter, data->phy_id & 0x1f,
-						0, data->reg_num & 0x1f,
-						&val);
-		if (!ret)
-			data->val_out = val;
-		break;
-	}
-	case SIOCSMIIREG:{
-		struct cphy *phy = &pi->phy;
-
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (!phy->mdio_write)
-			return -EOPNOTSUPP;
-		if (is_10G(adapter)) {
-			mmd = data->phy_id >> 8;
-			if (!mmd)
-				mmd = MDIO_DEV_PCS;
-			else if (mmd > MDIO_DEV_VEND2)
-				return -EINVAL;
-
-			ret =
-				phy->mdio_write(adapter,
-						data->phy_id & 0x1f, mmd,
-						data->reg_num,
-						data->val_in);
-		} else
-			ret =
-				phy->mdio_write(adapter,
-						data->phy_id & 0x1f, 0,
-						data->reg_num & 0x1f,
-						data->val_in);
-		break;
-	}
+	case SIOCGMIIPHY:
+		return mdio_mii_ioctl(&pi->phy.mdio, data, cmd);
 	case SIOCCHIOCTL:
 		return cxgb_extension_ioctl(dev, req->ifr_data);
 	default:
 		return -EOPNOTSUPP;
 	}
-	return ret;
 }
 
 static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
@@ -3063,6 +3077,14 @@
 		goto out_disable_device;
 	}
 
+	adapter->nofail_skb =
+		alloc_skb(sizeof(struct cpl_set_tcb_field), GFP_KERNEL);
+	if (!adapter->nofail_skb) {
+		dev_err(&pdev->dev, "cannot allocate nofail buffer\n");
+		err = -ENOMEM;
+		goto out_free_adapter;
+	}
+
 	adapter->regs = ioremap_nocache(mmio_start, mmio_len);
 	if (!adapter->regs) {
 		dev_err(&pdev->dev, "cannot map device registers\n");
@@ -3106,7 +3128,6 @@
 		netdev->mem_start = mmio_start;
 		netdev->mem_end = mmio_start + mmio_len - 1;
 		netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
-		netdev->features |= NETIF_F_LLTX;
 		netdev->features |= NETIF_F_GRO;
 		if (pci_using_dac)
 			netdev->features |= NETIF_F_HIGHDMA;
@@ -3220,6 +3241,8 @@
 				free_netdev(adapter->port[i]);
 
 		iounmap(adapter->regs);
+		if (adapter->nofail_skb)
+			kfree_skb(adapter->nofail_skb);
 		kfree(adapter);
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/cxgb3_offload.c linux-libre-2.6.31-gnu/drivers/net/cxgb3/cxgb3_offload.c
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/cxgb3_offload.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/cxgb3_offload.c	2009-09-09 18:13:59.000000000 -0400
@@ -566,13 +566,31 @@
 		spin_unlock_bh(&td->tid_release_lock);
 
 		skb = alloc_skb(sizeof(struct cpl_tid_release),
-				GFP_KERNEL | __GFP_NOFAIL);
+				GFP_KERNEL);
+		if (!skb)
+			skb = td->nofail_skb;
+		if (!skb) {
+			spin_lock_bh(&td->tid_release_lock);
+			p->ctx = (void *)td->tid_release_list;
+			td->tid_release_list = (struct t3c_tid_entry *)p;
+			break;
+		}
 		mk_tid_release(skb, p - td->tid_maps.tid_tab);
 		cxgb3_ofld_send(tdev, skb);
 		p->ctx = NULL;
+		if (skb == td->nofail_skb)
+			td->nofail_skb =
+				alloc_skb(sizeof(struct cpl_tid_release),
+					GFP_KERNEL);
 		spin_lock_bh(&td->tid_release_lock);
 	}
+	td->release_list_incomplete = (td->tid_release_list == NULL) ? 0 : 1;
 	spin_unlock_bh(&td->tid_release_lock);
+
+	if (!td->nofail_skb)
+		td->nofail_skb =
+			alloc_skb(sizeof(struct cpl_tid_release),
+				GFP_KERNEL);
 }
 
 /* use ctx as a next pointer in the tid release list */
@@ -585,7 +603,7 @@
 	p->ctx = (void *)td->tid_release_list;
 	p->client = NULL;
 	td->tid_release_list = p;
-	if (!p->ctx)
+	if (!p->ctx || td->release_list_incomplete)
 		schedule_work(&td->tid_release_task);
 	spin_unlock_bh(&td->tid_release_lock);
 }
@@ -1274,6 +1292,9 @@
 	if (list_empty(&adapter_list))
 		register_netevent_notifier(&nb);
 
+	t->nofail_skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_KERNEL);
+	t->release_list_incomplete = 0;
+
 	add_adapter(adapter);
 	return 0;
 
@@ -1298,6 +1319,8 @@
 	T3C_DATA(tdev) = NULL;
 	t3_free_l2t(L2DATA(tdev));
 	L2DATA(tdev) = NULL;
+	if (t->nofail_skb)
+		kfree_skb(t->nofail_skb);
 	kfree(t);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/cxgb3_offload.h linux-libre-2.6.31-gnu/drivers/net/cxgb3/cxgb3_offload.h
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/cxgb3_offload.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/cxgb3_offload.h	2009-09-09 18:13:59.000000000 -0400
@@ -191,6 +191,9 @@
 	struct t3c_tid_entry *tid_release_list;
 	spinlock_t tid_release_lock;
 	struct work_struct tid_release_task;
+
+	struct sk_buff *nofail_skb;
+	unsigned int release_list_incomplete;
 };
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/Makefile linux-libre-2.6.31-gnu/drivers/net/cxgb3/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -5,4 +5,4 @@
 obj-$(CONFIG_CHELSIO_T3) += cxgb3.o
 
 cxgb3-objs := cxgb3_main.o ael1002.o vsc8211.o t3_hw.o mc5.o \
-	      xgmac.o sge.o l2t.o cxgb3_offload.o
+	      xgmac.o sge.o l2t.o cxgb3_offload.o aq100x.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/sge.c linux-libre-2.6.31-gnu/drivers/net/cxgb3/sge.c
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/sge.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/sge.c	2009-09-09 18:13:59.000000000 -0400
@@ -653,7 +653,8 @@
 	q->txq_stopped = 0;
 	q->tx_reclaim_timer.function = NULL; /* for t3_stop_sge_timers() */
 	q->rx_reclaim_timer.function = NULL;
-	q->lro_frag_tbl.nr_frags = q->lro_frag_tbl.len = 0;
+	q->nomem = 0;
+	napi_free_frags(&q->napi);
 }
 
 
@@ -1239,7 +1240,6 @@
 	q = &qs->txq[TXQ_ETH];
 	txq = netdev_get_tx_queue(dev, qidx);
 
-	spin_lock(&q->lock);
 	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
 
 	credits = q->size - q->in_use;
@@ -1250,7 +1250,6 @@
 		dev_err(&adap->pdev->dev,
 			"%s: Tx ring %u full while queue awake!\n",
 			dev->name, q->cntxt_id & 7);
-		spin_unlock(&q->lock);
 		return NETDEV_TX_BUSY;
 	}
 
@@ -1284,9 +1283,6 @@
 	if (vlan_tx_tag_present(skb) && pi->vlan_grp)
 		qs->port_stats[SGE_PSTAT_VLANINS]++;
 
-	dev->trans_start = jiffies;
-	spin_unlock(&q->lock);
-
 	/*
 	 * We do not use Tx completion interrupts to free DMAd Tx packets.
 	 * This is good for performamce but means that we rely on new Tx
@@ -2073,20 +2069,19 @@
 			 struct sge_fl *fl, int len, int complete)
 {
 	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+	struct sk_buff *skb = NULL;
 	struct cpl_rx_pkt *cpl;
-	struct skb_frag_struct *rx_frag = qs->lro_frag_tbl.frags;
-	int nr_frags = qs->lro_frag_tbl.nr_frags;
-	int frag_len = qs->lro_frag_tbl.len;
+	struct skb_frag_struct *rx_frag;
+	int nr_frags;
 	int offset = 0;
 
-	if (!nr_frags) {
-		offset = 2 + sizeof(struct cpl_rx_pkt);
-		qs->lro_va = cpl = sd->pg_chunk.va + 2;
+	if (!qs->nomem) {
+		skb = napi_get_frags(&qs->napi);
+		qs->nomem = !skb;
 	}
 
 	fl->credits--;
 
-	len -= offset;
 	pci_dma_sync_single_for_cpu(adap->pdev,
 				    pci_unmap_addr(sd, dma_addr),
 				    fl->buf_size - SGE_PG_RSVD,
@@ -2099,21 +2094,38 @@
 			       fl->alloc_size,
 			       PCI_DMA_FROMDEVICE);
 
+	if (!skb) {
+		put_page(sd->pg_chunk.page);
+		if (complete)
+			qs->nomem = 0;
+		return;
+	}
+
+	rx_frag = skb_shinfo(skb)->frags;
+	nr_frags = skb_shinfo(skb)->nr_frags;
+
+	if (!nr_frags) {
+		offset = 2 + sizeof(struct cpl_rx_pkt);
+		qs->lro_va = sd->pg_chunk.va + 2;
+	}
+	len -= offset;
+
 	prefetch(qs->lro_va);
 
 	rx_frag += nr_frags;
 	rx_frag->page = sd->pg_chunk.page;
 	rx_frag->page_offset = sd->pg_chunk.offset + offset;
 	rx_frag->size = len;
-	frag_len += len;
-	qs->lro_frag_tbl.nr_frags++;
-	qs->lro_frag_tbl.len = frag_len;
 
+	skb->len += len;
+	skb->data_len += len;
+	skb->truesize += len;
+	skb_shinfo(skb)->nr_frags++;
 
 	if (!complete)
 		return;
 
-	qs->lro_frag_tbl.ip_summed = CHECKSUM_UNNECESSARY;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	cpl = qs->lro_va;
 
 	if (unlikely(cpl->vlan_valid)) {
@@ -2122,15 +2134,11 @@
 		struct vlan_group *grp = pi->vlan_grp;
 
 		if (likely(grp != NULL)) {
-			vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan),
-				       &qs->lro_frag_tbl);
-			goto out;
+			vlan_gro_frags(&qs->napi, grp, ntohs(cpl->vlan));
+			return;
 		}
 	}
-	napi_gro_frags(&qs->napi, &qs->lro_frag_tbl);
-
-out:
-	qs->lro_frag_tbl.nr_frags = qs->lro_frag_tbl.len = 0;
+	napi_gro_frags(&qs->napi);
 }
 
 /**
@@ -2299,8 +2307,6 @@
 			if (fl->use_pages) {
 				void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
 
-				prefetch(&qs->lro_frag_tbl);
-
 				prefetch(addr);
 #if L1_CACHE_BYTES < 128
 				prefetch(addr + L1_CACHE_BYTES);
@@ -2846,11 +2852,12 @@
 	unsigned int tbd[SGE_TXQ_PER_SET] = {0, 0};
 	unsigned long next_period;
 
-	if (spin_trylock(&qs->txq[TXQ_ETH].lock)) {
-		tbd[TXQ_ETH] = reclaim_completed_tx(adap, &qs->txq[TXQ_ETH],
-						    TX_RECLAIM_TIMER_CHUNK);
-		spin_unlock(&qs->txq[TXQ_ETH].lock);
+	if (__netif_tx_trylock(qs->tx_q)) {
+                tbd[TXQ_ETH] = reclaim_completed_tx(adap, &qs->txq[TXQ_ETH],
+                                                     TX_RECLAIM_TIMER_CHUNK);
+		__netif_tx_unlock(qs->tx_q);
 	}
+
 	if (spin_trylock(&qs->txq[TXQ_OFLD].lock)) {
 		tbd[TXQ_OFLD] = reclaim_completed_tx(adap, &qs->txq[TXQ_OFLD],
 						     TX_RECLAIM_TIMER_CHUNK);
@@ -2858,8 +2865,8 @@
 	}
 
 	next_period = TX_RECLAIM_PERIOD >>
-		      (max(tbd[TXQ_ETH], tbd[TXQ_OFLD]) /
-		       TX_RECLAIM_TIMER_CHUNK);
+                      (max(tbd[TXQ_ETH], tbd[TXQ_OFLD]) /
+                      TX_RECLAIM_TIMER_CHUNK);
 	mod_timer(&qs->tx_reclaim_timer, jiffies + next_period);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/t3_hw.c linux-libre-2.6.31-gnu/drivers/net/cxgb3/t3_hw.c
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/t3_hw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/t3_hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -204,35 +204,33 @@
 /*
  * MI1 read/write operations for clause 22 PHYs.
  */
-static int t3_mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr,
-		       int reg_addr, unsigned int *valp)
+static int t3_mi1_read(struct net_device *dev, int phy_addr, int mmd_addr,
+		       u16 reg_addr)
 {
+	struct port_info *pi = netdev_priv(dev);
+	struct adapter *adapter = pi->adapter;
 	int ret;
 	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);
 
-	if (mmd_addr)
-		return -EINVAL;
-
 	mutex_lock(&adapter->mdio_lock);
 	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
 	t3_write_reg(adapter, A_MI1_ADDR, addr);
 	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2));
 	ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
 	if (!ret)
-		*valp = t3_read_reg(adapter, A_MI1_DATA);
+		ret = t3_read_reg(adapter, A_MI1_DATA);
 	mutex_unlock(&adapter->mdio_lock);
 	return ret;
 }
 
-static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr,
-		     int reg_addr, unsigned int val)
+static int t3_mi1_write(struct net_device *dev, int phy_addr, int mmd_addr,
+			u16 reg_addr, u16 val)
 {
+	struct port_info *pi = netdev_priv(dev);
+	struct adapter *adapter = pi->adapter;
 	int ret;
 	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);
 
-	if (mmd_addr)
-		return -EINVAL;
-
 	mutex_lock(&adapter->mdio_lock);
 	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
 	t3_write_reg(adapter, A_MI1_ADDR, addr);
@@ -244,8 +242,9 @@
 }
 
 static const struct mdio_ops mi1_mdio_ops = {
-	t3_mi1_read,
-	t3_mi1_write
+	.read = t3_mi1_read,
+	.write = t3_mi1_write,
+	.mode_support = MDIO_SUPPORTS_C22
 };
 
 /*
@@ -268,9 +267,11 @@
 /*
  * MI1 read/write operations for indirect-addressed PHYs.
  */
-static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr,
-			int reg_addr, unsigned int *valp)
+static int mi1_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
+			u16 reg_addr)
 {
+	struct port_info *pi = netdev_priv(dev);
+	struct adapter *adapter = pi->adapter;
 	int ret;
 
 	mutex_lock(&adapter->mdio_lock);
@@ -280,15 +281,17 @@
 		ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
 				      MDIO_ATTEMPTS, 10);
 		if (!ret)
-			*valp = t3_read_reg(adapter, A_MI1_DATA);
+			ret = t3_read_reg(adapter, A_MI1_DATA);
 	}
 	mutex_unlock(&adapter->mdio_lock);
 	return ret;
 }
 
-static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr,
-			 int reg_addr, unsigned int val)
+static int mi1_ext_write(struct net_device *dev, int phy_addr, int mmd_addr,
+			 u16 reg_addr, u16 val)
 {
+	struct port_info *pi = netdev_priv(dev);
+	struct adapter *adapter = pi->adapter;
 	int ret;
 
 	mutex_lock(&adapter->mdio_lock);
@@ -304,8 +307,9 @@
 }
 
 static const struct mdio_ops mi1_mdio_ext_ops = {
-	mi1_ext_read,
-	mi1_ext_write
+	.read = mi1_ext_read,
+	.write = mi1_ext_write,
+	.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
 };
 
 /**
@@ -325,10 +329,10 @@
 	int ret;
 	unsigned int val;
 
-	ret = mdio_read(phy, mmd, reg, &val);
+	ret = t3_mdio_read(phy, mmd, reg, &val);
 	if (!ret) {
 		val &= ~clear;
-		ret = mdio_write(phy, mmd, reg, val | set);
+		ret = t3_mdio_write(phy, mmd, reg, val | set);
 	}
 	return ret;
 }
@@ -348,15 +352,16 @@
 	int err;
 	unsigned int ctl;
 
-	err = t3_mdio_change_bits(phy, mmd, MII_BMCR, BMCR_PDOWN, BMCR_RESET);
+	err = t3_mdio_change_bits(phy, mmd, MDIO_CTRL1, MDIO_CTRL1_LPOWER,
+				  MDIO_CTRL1_RESET);
 	if (err || !wait)
 		return err;
 
 	do {
-		err = mdio_read(phy, mmd, MII_BMCR, &ctl);
+		err = t3_mdio_read(phy, mmd, MDIO_CTRL1, &ctl);
 		if (err)
 			return err;
-		ctl &= BMCR_RESET;
+		ctl &= MDIO_CTRL1_RESET;
 		if (ctl)
 			msleep(1);
 	} while (ctl && --wait);
@@ -377,7 +382,7 @@
 	int err;
 	unsigned int val = 0;
 
-	err = mdio_read(phy, 0, MII_CTRL1000, &val);
+	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_CTRL1000, &val);
 	if (err)
 		return err;
 
@@ -387,7 +392,7 @@
 	if (advert & ADVERTISED_1000baseT_Full)
 		val |= ADVERTISE_1000FULL;
 
-	err = mdio_write(phy, 0, MII_CTRL1000, val);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_CTRL1000, val);
 	if (err)
 		return err;
 
@@ -404,7 +409,7 @@
 		val |= ADVERTISE_PAUSE_CAP;
 	if (advert & ADVERTISED_Asym_Pause)
 		val |= ADVERTISE_PAUSE_ASYM;
-	return mdio_write(phy, 0, MII_ADVERTISE, val);
+	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
 }
 
 /**
@@ -427,7 +432,7 @@
 		val |= ADVERTISE_1000XPAUSE;
 	if (advert & ADVERTISED_Asym_Pause)
 		val |= ADVERTISE_1000XPSE_ASYM;
-	return mdio_write(phy, 0, MII_ADVERTISE, val);
+	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
 }
 
 /**
@@ -444,7 +449,7 @@
 	int err;
 	unsigned int ctl;
 
-	err = mdio_read(phy, 0, MII_BMCR, &ctl);
+	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_BMCR, &ctl);
 	if (err)
 		return err;
 
@@ -462,34 +467,36 @@
 	}
 	if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */
 		ctl |= BMCR_ANENABLE;
-	return mdio_write(phy, 0, MII_BMCR, ctl);
+	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_BMCR, ctl);
 }
 
 int t3_phy_lasi_intr_enable(struct cphy *phy)
 {
-	return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
+	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
+			     MDIO_PMA_LASI_LSALARM);
 }
 
 int t3_phy_lasi_intr_disable(struct cphy *phy)
 {
-	return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
+	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
 }
 
 int t3_phy_lasi_intr_clear(struct cphy *phy)
 {
 	u32 val;
 
-	return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
+	return t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
 }
 
 int t3_phy_lasi_intr_handler(struct cphy *phy)
 {
 	unsigned int status;
-	int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
+	int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT,
+			       &status);
 
 	if (err)
 		return err;
-	return (status & 1) ?  cphy_cause_link_change : 0;
+	return (status & MDIO_PMA_LASI_LSALARM) ? cphy_cause_link_change : 0;
 }
 
 static const struct adapter_info t3_adap_info[] = {
@@ -519,6 +526,11 @@
 	 F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
 	 { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
 	 &mi1_mdio_ext_ops, "Chelsio T310" },
+	{1, 0, 0,
+	 F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
+	 F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL,
+	 { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
+	 &mi1_mdio_ext_ops, "Chelsio N320E-G2" },
 };
 
 /*
@@ -545,6 +557,8 @@
 	{ t3_qt2045_phy_prep },
 	{ t3_ael1006_phy_prep },
 	{ NULL },
+	{ t3_aq100x_phy_prep },
+	{ t3_ael2020_phy_prep },
 };
 
 #define VPD_ENTRY(name, len) \
@@ -3864,6 +3878,7 @@
 			return -EINVAL;
 		}
 
+		p->phy.mdio.dev = adapter->port[i];
 		ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
 				    ai->mdio_ops);
 		if (ret)
@@ -3923,7 +3938,7 @@
 			;
 
 		pti = &port_types[adapter->params.vpd.port_type[j]];
-		ret = pti->phy_prep(&p->phy, adapter, p->phy.addr, NULL);
+		ret = pti->phy_prep(&p->phy, adapter, p->phy.mdio.prtad, NULL);
 		if (ret)
 			return ret;
 		p->phy.ops->power_down(&p->phy, 1);
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/version.h linux-libre-2.6.31-gnu/drivers/net/cxgb3/version.h
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/version.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/version.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,10 +35,10 @@
 #define DRV_DESC "Chelsio T3 Network Driver"
 #define DRV_NAME "cxgb3"
 /* Driver version */
-#define DRV_VERSION "1.1.2-ko"
+#define DRV_VERSION "1.1.3-ko"
 
 /* Firmware version */
 #define FW_VERSION_MAJOR 7
-#define FW_VERSION_MINOR 1
+#define FW_VERSION_MINOR 4
 #define FW_VERSION_MICRO 0
 #endif				/* __CHELSIO_VERSION_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/cxgb3/vsc8211.c linux-libre-2.6.31-gnu/drivers/net/cxgb3/vsc8211.c
--- linux-libre-2.6.30-gnu/drivers/net/cxgb3/vsc8211.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/cxgb3/vsc8211.c	2009-09-09 18:13:59.000000000 -0400
@@ -91,17 +91,18 @@
  */
 static int vsc8211_reset(struct cphy *cphy, int wait)
 {
-	return t3_phy_reset(cphy, 0, 0);
+	return t3_phy_reset(cphy, MDIO_DEVAD_NONE, 0);
 }
 
 static int vsc8211_intr_enable(struct cphy *cphy)
 {
-	return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, INTR_MASK);
+	return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE,
+			     INTR_MASK);
 }
 
 static int vsc8211_intr_disable(struct cphy *cphy)
 {
-	return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, 0);
+	return t3_mdio_write(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_ENABLE, 0);
 }
 
 static int vsc8211_intr_clear(struct cphy *cphy)
@@ -109,18 +110,20 @@
 	u32 val;
 
 	/* Clear PHY interrupts by reading the register. */
-	return mdio_read(cphy, 0, VSC8211_INTR_STATUS, &val);
+	return t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &val);
 }
 
 static int vsc8211_autoneg_enable(struct cphy *cphy)
 {
-	return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE,
+	return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR,
+				   BMCR_PDOWN | BMCR_ISOLATE,
 				   BMCR_ANENABLE | BMCR_ANRESTART);
 }
 
 static int vsc8211_autoneg_restart(struct cphy *cphy)
 {
-	return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE,
+	return t3_mdio_change_bits(cphy, MDIO_DEVAD_NONE, MII_BMCR,
+				   BMCR_PDOWN | BMCR_ISOLATE,
 				   BMCR_ANRESTART);
 }
 
@@ -130,9 +133,9 @@
 	unsigned int bmcr, status, lpa, adv;
 	int err, sp = -1, dplx = -1, pause = 0;
 
-	err = mdio_read(cphy, 0, MII_BMCR, &bmcr);
+	err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr);
 	if (!err)
-		err = mdio_read(cphy, 0, MII_BMSR, &status);
+		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status);
 	if (err)
 		return err;
 
@@ -142,7 +145,8 @@
 		 * once more to get the current link state.
 		 */
 		if (!(status & BMSR_LSTATUS))
-			err = mdio_read(cphy, 0, MII_BMSR, &status);
+			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR,
+					   &status);
 		if (err)
 			return err;
 		*link_ok = (status & BMSR_LSTATUS) != 0;
@@ -156,7 +160,8 @@
 		else
 			sp = SPEED_10;
 	} else if (status & BMSR_ANEGCOMPLETE) {
-		err = mdio_read(cphy, 0, VSC8211_AUX_CTRL_STAT, &status);
+		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_AUX_CTRL_STAT,
+				   &status);
 		if (err)
 			return err;
 
@@ -170,9 +175,11 @@
 			sp = SPEED_1000;
 
 		if (fc && dplx == DUPLEX_FULL) {
-			err = mdio_read(cphy, 0, MII_LPA, &lpa);
+			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA,
+					   &lpa);
 			if (!err)
-				err = mdio_read(cphy, 0, MII_ADVERTISE, &adv);
+				err = t3_mdio_read(cphy, MDIO_DEVAD_NONE,
+						   MII_ADVERTISE, &adv);
 			if (err)
 				return err;
 
@@ -202,9 +209,9 @@
 	unsigned int bmcr, status, lpa, adv;
 	int err, sp = -1, dplx = -1, pause = 0;
 
-	err = mdio_read(cphy, 0, MII_BMCR, &bmcr);
+	err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMCR, &bmcr);
 	if (!err)
-		err = mdio_read(cphy, 0, MII_BMSR, &status);
+		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR, &status);
 	if (err)
 		return err;
 
@@ -214,7 +221,8 @@
 		 * once more to get the current link state.
 		 */
 		if (!(status & BMSR_LSTATUS))
-			err = mdio_read(cphy, 0, MII_BMSR, &status);
+			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_BMSR,
+					   &status);
 		if (err)
 			return err;
 		*link_ok = (status & BMSR_LSTATUS) != 0;
@@ -228,9 +236,10 @@
 		else
 			sp = SPEED_10;
 	} else if (status & BMSR_ANEGCOMPLETE) {
-		err = mdio_read(cphy, 0, MII_LPA, &lpa);
+		err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_LPA, &lpa);
 		if (!err)
-			err = mdio_read(cphy, 0, MII_ADVERTISE, &adv);
+			err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, MII_ADVERTISE,
+					   &adv);
 		if (err)
 			return err;
 
@@ -270,23 +279,23 @@
 {
 	int err;
 
-	err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0x52b5);
 	if (err)
 		return err;
 
-	err = mdio_write(phy, 0, 18, 0x12);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 18, 0x12);
 	if (err)
 		return err;
 
-	err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 17, enable ? 0x2803 : 0x3003);
 	if (err)
 		return err;
 
-	err = mdio_write(phy, 0, 16, 0x87fa);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, 16, 0x87fa);
 	if (err)
 		return err;
 
-	err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0);
 	if (err)
 		return err;
 
@@ -315,7 +324,7 @@
 	unsigned int cause;
 	int err, cphy_cause = 0;
 
-	err = mdio_read(cphy, 0, VSC8211_INTR_STATUS, &cause);
+	err = t3_mdio_read(cphy, MDIO_DEVAD_NONE, VSC8211_INTR_STATUS, &cause);
 	if (err)
 		return err;
 
@@ -367,12 +376,13 @@
 		  SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
 	msleep(20);       /* PHY needs ~10ms to start responding to MDIO */
 
-	err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val);
+	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL, &val);
 	if (err)
 		return err;
 	if (val & VSC_CTRL_MEDIA_MODE_HI) {
 		/* copper interface, just need to configure the LEDs */
-		return mdio_write(phy, 0, VSC8211_LED_CTRL, 0x100);
+		return t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_LED_CTRL,
+				     0x100);
 	}
 
 	phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
@@ -380,20 +390,20 @@
 	phy->desc = "1000BASE-X";
 	phy->ops = &vsc8211_fiber_ops;
 
-	err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 1);
 	if (err)
 		return err;
 
-	err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_SIGDET_CTRL, 1);
 	if (err)
 		return err;
 
-	err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_PAGE_AXS, 0);
 	if (err)
 		return err;
 
-	err = mdio_write(phy, 0, VSC8211_EXT_CTRL,
-			 val | VSC_CTRL_CLAUSE37_VIEW);
+	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, VSC8211_EXT_CTRL,
+			    val | VSC_CTRL_CLAUSE37_VIEW);
 	if (err)
 		return err;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/davinci_emac.c linux-libre-2.6.31-gnu/drivers/net/davinci_emac.c
--- linux-libre-2.6.30-gnu/drivers/net/davinci_emac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/davinci_emac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2837 @@
+/*
+ * DaVinci Ethernet Medium Access Controller
+ *
+ * DaVinci EMAC is based upon CPPI 3.0 TI DMA engine
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ---------------------------------------------------------------------------
+ * History:
+ * 0-5 A number of folks worked on this driver in bits and pieces but the major
+ *     contribution came from Suraj Iyer and Anant Gole
+ * 6.0 Anant Gole - rewrote the driver as per Linux conventions
+ * 6.1 Chaithrika U S - added support for Gigabit and RMII features,
+ *     PHY layer usage
+ */
+
+/** Pending Items in this driver:
+ * 1. Use Linux cache infrastcture for DMA'ed memory (dma_xxx functions)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/highmem.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/phy.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/irq.h>
+#include <asm/page.h>
+
+#include <mach/emac.h>
+
+static int debug_level;
+module_param(debug_level, int, 0);
+MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
+
+/* Netif debug messages possible */
+#define DAVINCI_EMAC_DEBUG	(NETIF_MSG_DRV | \
+				NETIF_MSG_PROBE | \
+				NETIF_MSG_LINK | \
+				NETIF_MSG_TIMER | \
+				NETIF_MSG_IFDOWN | \
+				NETIF_MSG_IFUP | \
+				NETIF_MSG_RX_ERR | \
+				NETIF_MSG_TX_ERR | \
+				NETIF_MSG_TX_QUEUED | \
+				NETIF_MSG_INTR | \
+				NETIF_MSG_TX_DONE | \
+				NETIF_MSG_RX_STATUS | \
+				NETIF_MSG_PKTDATA | \
+				NETIF_MSG_HW | \
+				NETIF_MSG_WOL)
+
+/* version info */
+#define EMAC_MAJOR_VERSION	6
+#define EMAC_MINOR_VERSION	1
+#define EMAC_MODULE_VERSION	"6.1"
+MODULE_VERSION(EMAC_MODULE_VERSION);
+static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
+
+/* Configuration items */
+#define EMAC_DEF_PASS_CRC		(0) /* Do not pass CRC upto frames */
+#define EMAC_DEF_QOS_EN			(0) /* EMAC proprietary QoS disabled */
+#define EMAC_DEF_NO_BUFF_CHAIN		(0) /* No buffer chain */
+#define EMAC_DEF_MACCTRL_FRAME_EN	(0) /* Discard Maccontrol frames */
+#define EMAC_DEF_SHORT_FRAME_EN		(0) /* Discard short frames */
+#define EMAC_DEF_ERROR_FRAME_EN		(0) /* Discard error frames */
+#define EMAC_DEF_PROM_EN		(0) /* Promiscous disabled */
+#define EMAC_DEF_PROM_CH		(0) /* Promiscous channel is 0 */
+#define EMAC_DEF_BCAST_EN		(1) /* Broadcast enabled */
+#define EMAC_DEF_BCAST_CH		(0) /* Broadcast channel is 0 */
+#define EMAC_DEF_MCAST_EN		(1) /* Multicast enabled */
+#define EMAC_DEF_MCAST_CH		(0) /* Multicast channel is 0 */
+
+#define EMAC_DEF_TXPRIO_FIXED		(1) /* TX Priority is fixed */
+#define EMAC_DEF_TXPACING_EN		(0) /* TX pacing NOT supported*/
+
+#define EMAC_DEF_BUFFER_OFFSET		(0) /* Buffer offset to DMA (future) */
+#define EMAC_DEF_MIN_ETHPKTSIZE		(60) /* Minimum ethernet pkt size */
+#define EMAC_DEF_MAX_FRAME_SIZE		(1500 + 14 + 4 + 4)
+#define EMAC_DEF_TX_CH			(0) /* Default 0th channel */
+#define EMAC_DEF_RX_CH			(0) /* Default 0th channel */
+#define EMAC_DEF_MDIO_TICK_MS		(10) /* typically 1 tick=1 ms) */
+#define EMAC_DEF_MAX_TX_CH		(1) /* Max TX channels configured */
+#define EMAC_DEF_MAX_RX_CH		(1) /* Max RX channels configured */
+#define EMAC_POLL_WEIGHT		(64) /* Default NAPI poll weight */
+
+/* Buffer descriptor parameters */
+#define EMAC_DEF_TX_MAX_SERVICE		(32) /* TX max service BD's */
+#define EMAC_DEF_RX_MAX_SERVICE		(64) /* should = netdev->weight */
+
+/* EMAC register related defines */
+#define EMAC_ALL_MULTI_REG_VALUE	(0xFFFFFFFF)
+#define EMAC_NUM_MULTICAST_BITS		(64)
+#define EMAC_TEARDOWN_VALUE		(0xFFFFFFFC)
+#define EMAC_TX_CONTROL_TX_ENABLE_VAL	(0x1)
+#define EMAC_RX_CONTROL_RX_ENABLE_VAL	(0x1)
+#define EMAC_MAC_HOST_ERR_INTMASK_VAL	(0x2)
+#define EMAC_RX_UNICAST_CLEAR_ALL	(0xFF)
+#define EMAC_INT_MASK_CLEAR		(0xFF)
+
+/* RX MBP register bit positions */
+#define EMAC_RXMBP_PASSCRC_MASK		BIT(30)
+#define EMAC_RXMBP_QOSEN_MASK		BIT(29)
+#define EMAC_RXMBP_NOCHAIN_MASK		BIT(28)
+#define EMAC_RXMBP_CMFEN_MASK		BIT(24)
+#define EMAC_RXMBP_CSFEN_MASK		BIT(23)
+#define EMAC_RXMBP_CEFEN_MASK		BIT(22)
+#define EMAC_RXMBP_CAFEN_MASK		BIT(21)
+#define EMAC_RXMBP_PROMCH_SHIFT		(16)
+#define EMAC_RXMBP_PROMCH_MASK		(0x7 << 16)
+#define EMAC_RXMBP_BROADEN_MASK		BIT(13)
+#define EMAC_RXMBP_BROADCH_SHIFT	(8)
+#define EMAC_RXMBP_BROADCH_MASK		(0x7 << 8)
+#define EMAC_RXMBP_MULTIEN_MASK		BIT(5)
+#define EMAC_RXMBP_MULTICH_SHIFT	(0)
+#define EMAC_RXMBP_MULTICH_MASK		(0x7)
+#define EMAC_RXMBP_CHMASK		(0x7)
+
+/* EMAC register definitions/bit maps used */
+# define EMAC_MBP_RXPROMISC		(0x00200000)
+# define EMAC_MBP_PROMISCCH(ch)		(((ch) & 0x7) << 16)
+# define EMAC_MBP_RXBCAST		(0x00002000)
+# define EMAC_MBP_BCASTCHAN(ch)		(((ch) & 0x7) << 8)
+# define EMAC_MBP_RXMCAST		(0x00000020)
+# define EMAC_MBP_MCASTCHAN(ch)		((ch) & 0x7)
+
+/* EMAC mac_control register */
+#define EMAC_MACCONTROL_TXPTYPE		(0x200)
+#define EMAC_MACCONTROL_TXPACEEN	(0x40)
+#define EMAC_MACCONTROL_MIIEN		(0x20)
+#define EMAC_MACCONTROL_GIGABITEN	(0x80)
+#define EMAC_MACCONTROL_GIGABITEN_SHIFT (7)
+#define EMAC_MACCONTROL_FULLDUPLEXEN	(0x1)
+#define EMAC_MACCONTROL_RMIISPEED_MASK	BIT(15)
+
+/* GIGABIT MODE related bits */
+#define EMAC_DM646X_MACCONTORL_GMIIEN	BIT(5)
+#define EMAC_DM646X_MACCONTORL_GIG	BIT(7)
+#define EMAC_DM646X_MACCONTORL_GIGFORCE	BIT(17)
+
+/* EMAC mac_status register */
+#define EMAC_MACSTATUS_TXERRCODE_MASK	(0xF00000)
+#define EMAC_MACSTATUS_TXERRCODE_SHIFT	(20)
+#define EMAC_MACSTATUS_TXERRCH_MASK	(0x7)
+#define EMAC_MACSTATUS_TXERRCH_SHIFT	(16)
+#define EMAC_MACSTATUS_RXERRCODE_MASK	(0xF000)
+#define EMAC_MACSTATUS_RXERRCODE_SHIFT	(12)
+#define EMAC_MACSTATUS_RXERRCH_MASK	(0x7)
+#define EMAC_MACSTATUS_RXERRCH_SHIFT	(8)
+
+/* EMAC RX register masks */
+#define EMAC_RX_MAX_LEN_MASK		(0xFFFF)
+#define EMAC_RX_BUFFER_OFFSET_MASK	(0xFFFF)
+
+/* MAC_IN_VECTOR (0x180) register bit fields */
+#define EMAC_DM644X_MAC_IN_VECTOR_HOST_INT	      (0x20000)
+#define EMAC_DM644X_MAC_IN_VECTOR_STATPEND_INT	      (0x10000)
+#define EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC	      (0x0100)
+#define EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC	      (0x01)
+
+/** NOTE:: For DM646x the IN_VECTOR has changed */
+#define EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC	BIT(EMAC_DEF_RX_CH)
+#define EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC	BIT(16 + EMAC_DEF_TX_CH)
+
+/* CPPI bit positions */
+#define EMAC_CPPI_SOP_BIT		BIT(31)
+#define EMAC_CPPI_EOP_BIT		BIT(30)
+#define EMAC_CPPI_OWNERSHIP_BIT		BIT(29)
+#define EMAC_CPPI_EOQ_BIT		BIT(28)
+#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT BIT(27)
+#define EMAC_CPPI_PASS_CRC_BIT		BIT(26)
+#define EMAC_RX_BD_BUF_SIZE		(0xFFFF)
+#define EMAC_BD_LENGTH_FOR_CACHE	(16) /* only CPPI bytes */
+#define EMAC_RX_BD_PKT_LENGTH_MASK	(0xFFFF)
+
+/* Max hardware defines */
+#define EMAC_MAX_TXRX_CHANNELS		 (8)  /* Max hardware channels */
+#define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */
+
+/* EMAC Peripheral Device Register Memory Layout structure */
+#define EMAC_TXIDVER		0x0
+#define EMAC_TXCONTROL		0x4
+#define EMAC_TXTEARDOWN		0x8
+#define EMAC_RXIDVER		0x10
+#define EMAC_RXCONTROL		0x14
+#define EMAC_RXTEARDOWN		0x18
+#define EMAC_TXINTSTATRAW	0x80
+#define EMAC_TXINTSTATMASKED	0x84
+#define EMAC_TXINTMASKSET	0x88
+#define EMAC_TXINTMASKCLEAR	0x8C
+#define EMAC_MACINVECTOR	0x90
+
+#define EMAC_DM646X_MACEOIVECTOR	0x94
+
+#define EMAC_RXINTSTATRAW	0xA0
+#define EMAC_RXINTSTATMASKED	0xA4
+#define EMAC_RXINTMASKSET	0xA8
+#define EMAC_RXINTMASKCLEAR	0xAC
+#define EMAC_MACINTSTATRAW	0xB0
+#define EMAC_MACINTSTATMASKED	0xB4
+#define EMAC_MACINTMASKSET	0xB8
+#define EMAC_MACINTMASKCLEAR	0xBC
+
+#define EMAC_RXMBPENABLE	0x100
+#define EMAC_RXUNICASTSET	0x104
+#define EMAC_RXUNICASTCLEAR	0x108
+#define EMAC_RXMAXLEN		0x10C
+#define EMAC_RXBUFFEROFFSET	0x110
+#define EMAC_RXFILTERLOWTHRESH	0x114
+
+#define EMAC_MACCONTROL		0x160
+#define EMAC_MACSTATUS		0x164
+#define EMAC_EMCONTROL		0x168
+#define EMAC_FIFOCONTROL	0x16C
+#define EMAC_MACCONFIG		0x170
+#define EMAC_SOFTRESET		0x174
+#define EMAC_MACSRCADDRLO	0x1D0
+#define EMAC_MACSRCADDRHI	0x1D4
+#define EMAC_MACHASH1		0x1D8
+#define EMAC_MACHASH2		0x1DC
+#define EMAC_MACADDRLO		0x500
+#define EMAC_MACADDRHI		0x504
+#define EMAC_MACINDEX		0x508
+
+/* EMAC HDP and Completion registors */
+#define EMAC_TXHDP(ch)		(0x600 + (ch * 4))
+#define EMAC_RXHDP(ch)		(0x620 + (ch * 4))
+#define EMAC_TXCP(ch)		(0x640 + (ch * 4))
+#define EMAC_RXCP(ch)		(0x660 + (ch * 4))
+
+/* EMAC statistics registers */
+#define EMAC_RXGOODFRAMES	0x200
+#define EMAC_RXBCASTFRAMES	0x204
+#define EMAC_RXMCASTFRAMES	0x208
+#define EMAC_RXPAUSEFRAMES	0x20C
+#define EMAC_RXCRCERRORS	0x210
+#define EMAC_RXALIGNCODEERRORS	0x214
+#define EMAC_RXOVERSIZED	0x218
+#define EMAC_RXJABBER		0x21C
+#define EMAC_RXUNDERSIZED	0x220
+#define EMAC_RXFRAGMENTS	0x224
+#define EMAC_RXFILTERED		0x228
+#define EMAC_RXQOSFILTERED	0x22C
+#define EMAC_RXOCTETS		0x230
+#define EMAC_TXGOODFRAMES	0x234
+#define EMAC_TXBCASTFRAMES	0x238
+#define EMAC_TXMCASTFRAMES	0x23C
+#define EMAC_TXPAUSEFRAMES	0x240
+#define EMAC_TXDEFERRED		0x244
+#define EMAC_TXCOLLISION	0x248
+#define EMAC_TXSINGLECOLL	0x24C
+#define EMAC_TXMULTICOLL	0x250
+#define EMAC_TXEXCESSIVECOLL	0x254
+#define EMAC_TXLATECOLL		0x258
+#define EMAC_TXUNDERRUN		0x25C
+#define EMAC_TXCARRIERSENSE	0x260
+#define EMAC_TXOCTETS		0x264
+#define EMAC_NETOCTETS		0x280
+#define EMAC_RXSOFOVERRUNS	0x284
+#define EMAC_RXMOFOVERRUNS	0x288
+#define EMAC_RXDMAOVERRUNS	0x28C
+
+/* EMAC DM644x control registers */
+#define EMAC_CTRL_EWCTL		(0x4)
+#define EMAC_CTRL_EWINTTCNT	(0x8)
+
+/* EMAC MDIO related */
+/* Mask & Control defines */
+#define MDIO_CONTROL_CLKDIV	(0xFF)
+#define MDIO_CONTROL_ENABLE	BIT(30)
+#define MDIO_USERACCESS_GO	BIT(31)
+#define MDIO_USERACCESS_WRITE	BIT(30)
+#define MDIO_USERACCESS_READ	(0)
+#define MDIO_USERACCESS_REGADR	(0x1F << 21)
+#define MDIO_USERACCESS_PHYADR	(0x1F << 16)
+#define MDIO_USERACCESS_DATA	(0xFFFF)
+#define MDIO_USERPHYSEL_LINKSEL	BIT(7)
+#define MDIO_VER_MODID		(0xFFFF << 16)
+#define MDIO_VER_REVMAJ		(0xFF   << 8)
+#define MDIO_VER_REVMIN		(0xFF)
+
+#define MDIO_USERACCESS(inst)	(0x80 + (inst * 8))
+#define MDIO_USERPHYSEL(inst)	(0x84 + (inst * 8))
+#define MDIO_CONTROL		(0x04)
+
+/* EMAC DM646X control module registers */
+#define EMAC_DM646X_CMRXINTEN	(0x14)
+#define EMAC_DM646X_CMTXINTEN	(0x18)
+
+/* EMAC EOI codes for C0 */
+#define EMAC_DM646X_MAC_EOI_C0_RXEN	(0x01)
+#define EMAC_DM646X_MAC_EOI_C0_TXEN	(0x02)
+
+/** net_buf_obj: EMAC network bufferdata structure
+ *
+ * EMAC network buffer data structure
+ */
+struct emac_netbufobj {
+	void *buf_token;
+	char *data_ptr;
+	int length;
+};
+
+/** net_pkt_obj: EMAC network packet data structure
+ *
+ * EMAC network packet data structure - supports buffer list (for future)
+ */
+struct emac_netpktobj {
+	void *pkt_token; /* data token may hold tx/rx chan id */
+	struct emac_netbufobj *buf_list; /* array of network buffer objects */
+	int num_bufs;
+	int pkt_length;
+};
+
+/** emac_tx_bd: EMAC TX Buffer descriptor data structure
+ *
+ * EMAC TX Buffer descriptor data structure
+ */
+struct emac_tx_bd {
+	int h_next;
+	int buff_ptr;
+	int off_b_len;
+	int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */
+	struct emac_tx_bd __iomem *next;
+	void *buf_token;
+};
+
+/** emac_txch: EMAC TX Channel data structure
+ *
+ * EMAC TX Channel data structure
+ */
+struct emac_txch {
+	/* Config related */
+	u32 num_bd;
+	u32 service_max;
+
+	/* CPPI specific */
+	u32 alloc_size;
+	void __iomem *bd_mem;
+	struct emac_tx_bd __iomem *bd_pool_head;
+	struct emac_tx_bd __iomem *active_queue_head;
+	struct emac_tx_bd __iomem *active_queue_tail;
+	struct emac_tx_bd __iomem *last_hw_bdprocessed;
+	u32 queue_active;
+	u32 teardown_pending;
+	u32 *tx_complete;
+
+	/** statistics */
+	u32 proc_count;     /* TX: # of times emac_tx_bdproc is called */
+	u32 mis_queued_packets;
+	u32 queue_reinit;
+	u32 end_of_queue_add;
+	u32 out_of_tx_bd;
+	u32 no_active_pkts; /* IRQ when there were no packets to process */
+	u32 active_queue_count;
+};
+
+/** emac_rx_bd: EMAC RX Buffer descriptor data structure
+ *
+ * EMAC RX Buffer descriptor data structure
+ */
+struct emac_rx_bd {
+	int h_next;
+	int buff_ptr;
+	int off_b_len;
+	int mode;
+	struct emac_rx_bd __iomem *next;
+	void *data_ptr;
+	void *buf_token;
+};
+
+/** emac_rxch: EMAC RX Channel data structure
+ *
+ * EMAC RX Channel data structure
+ */
+struct emac_rxch {
+	/* configuration info */
+	u32 num_bd;
+	u32 service_max;
+	u32 buf_size;
+	char mac_addr[6];
+
+	/** CPPI specific */
+	u32 alloc_size;
+	void __iomem *bd_mem;
+	struct emac_rx_bd __iomem *bd_pool_head;
+	struct emac_rx_bd __iomem *active_queue_head;
+	struct emac_rx_bd __iomem *active_queue_tail;
+	u32 queue_active;
+	u32 teardown_pending;
+
+	/* packet and buffer objects */
+	struct emac_netpktobj pkt_queue;
+	struct emac_netbufobj buf_queue;
+
+	/** statistics */
+	u32 proc_count; /* number of times emac_rx_bdproc is called */
+	u32 processed_bd;
+	u32 recycled_bd;
+	u32 out_of_rx_bd;
+	u32 out_of_rx_buffers;
+	u32 queue_reinit;
+	u32 end_of_queue_add;
+	u32 end_of_queue;
+	u32 mis_queued_packets;
+};
+
+/* emac_priv: EMAC private data structure
+ *
+ * EMAC adapter private data structure
+ */
+struct emac_priv {
+	u32 msg_enable;
+	struct net_device *ndev;
+	struct platform_device *pdev;
+	struct napi_struct napi;
+	char mac_addr[6];
+	spinlock_t tx_lock;
+	spinlock_t rx_lock;
+	void __iomem *remap_addr;
+	u32 emac_base_phys;
+	void __iomem *emac_base;
+	void __iomem *ctrl_base;
+	void __iomem *emac_ctrl_ram;
+	u32 ctrl_ram_size;
+	struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
+	struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
+	u32 link; /* 1=link on, 0=link off */
+	u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */
+	u32 duplex; /* Link duplex: 0=Half, 1=Full */
+	u32 rx_buf_size;
+	u32 isr_count;
+	u8 rmii_en;
+	u8 version;
+	struct net_device_stats net_dev_stats;
+	u32 mac_hash1;
+	u32 mac_hash2;
+	u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
+	u32 rx_addr_type;
+	/* periodic timer required for MDIO polling */
+	struct timer_list periodic_timer;
+	u32 periodic_ticks;
+	u32 timer_active;
+	u32 phy_mask;
+	/* mii_bus,phy members */
+	struct mii_bus *mii_bus;
+	struct phy_device *phydev;
+	spinlock_t lock;
+};
+
+/* clock frequency for EMAC */
+static struct clk *emac_clk;
+static unsigned long emac_bus_frequency;
+static unsigned long mdio_max_freq;
+
+/* EMAC internal utility function */
+static inline u32 emac_virt_to_phys(void __iomem *addr)
+{
+	return (u32 __force) io_v2p(addr);
+}
+
+/* Cache macros - Packet buffers would be from skb pool which is cached */
+#define EMAC_VIRT_NOCACHE(addr) (addr)
+#define EMAC_CACHE_INVALIDATE(addr, size) \
+	dma_cache_maint((void *)addr, size, DMA_FROM_DEVICE)
+#define EMAC_CACHE_WRITEBACK(addr, size) \
+	dma_cache_maint((void *)addr, size, DMA_TO_DEVICE)
+#define EMAC_CACHE_WRITEBACK_INVALIDATE(addr, size) \
+	dma_cache_maint((void *)addr, size, DMA_BIDIRECTIONAL)
+
+/* DM644x does not have BD's in cached memory - so no cache functions */
+#define BD_CACHE_INVALIDATE(addr, size)
+#define BD_CACHE_WRITEBACK(addr, size)
+#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size)
+
+/* EMAC TX Host Error description strings */
+static char *emac_txhost_errcodes[16] = {
+	"No error", "SOP error", "Ownership bit not set in SOP buffer",
+	"Zero Next Buffer Descriptor Pointer Without EOP",
+	"Zero Buffer Pointer", "Zero Buffer Length", "Packet Length Error",
+	"Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
+	"Reserved", "Reserved", "Reserved", "Reserved"
+};
+
+/* EMAC RX Host Error description strings */
+static char *emac_rxhost_errcodes[16] = {
+	"No error", "Reserved", "Ownership bit not set in input buffer",
+	"Reserved", "Zero Buffer Pointer", "Reserved", "Reserved",
+	"Reserved", "Reserved", "Reserved", "Reserved", "Reserved",
+	"Reserved", "Reserved", "Reserved", "Reserved"
+};
+
+/* Helper macros */
+#define emac_read(reg)		  ioread32(priv->emac_base + (reg))
+#define emac_write(reg, val)      iowrite32(val, priv->emac_base + (reg))
+
+#define emac_ctrl_read(reg)	  ioread32((priv->ctrl_base + (reg)))
+#define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg)))
+
+#define emac_mdio_read(reg)	  ioread32(bus->priv + (reg))
+#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg)))
+
+/**
+ * emac_dump_regs: Dump important EMAC registers to debug terminal
+ * @priv: The DaVinci EMAC private adapter structure
+ *
+ * Executes ethtool set cmd & sets phy mode
+ *
+ */
+static void emac_dump_regs(struct emac_priv *priv)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+
+	/* Print important registers in EMAC */
+	dev_info(emac_dev, "EMAC Basic registers\n");
+	dev_info(emac_dev, "EMAC: EWCTL: %08X, EWINTTCNT: %08X\n",
+		emac_ctrl_read(EMAC_CTRL_EWCTL),
+		emac_ctrl_read(EMAC_CTRL_EWINTTCNT));
+	dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n",
+		emac_read(EMAC_TXIDVER),
+		((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"),
+		emac_read(EMAC_RXIDVER),
+		((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled"));
+	dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\
+		"TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW),
+		emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET));
+	dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\
+		"RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW),
+		emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET));
+	dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\
+		"MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW),
+		emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR));
+	dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n",
+		emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL));
+	dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\
+		"RXMaxLen=%08X\n", emac_read(EMAC_RXMBPENABLE),
+		emac_read(EMAC_RXUNICASTSET), emac_read(EMAC_RXMAXLEN));
+	dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\
+		"MacConfig=%08X\n", emac_read(EMAC_MACCONTROL),
+		emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG));
+	dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n",
+		emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0)));
+	dev_info(emac_dev, "EMAC Statistics\n");
+	dev_info(emac_dev, "EMAC: rx_good_frames:%d\n",
+		emac_read(EMAC_RXGOODFRAMES));
+	dev_info(emac_dev, "EMAC: rx_broadcast_frames:%d\n",
+		emac_read(EMAC_RXBCASTFRAMES));
+	dev_info(emac_dev, "EMAC: rx_multicast_frames:%d\n",
+		emac_read(EMAC_RXMCASTFRAMES));
+	dev_info(emac_dev, "EMAC: rx_pause_frames:%d\n",
+		emac_read(EMAC_RXPAUSEFRAMES));
+	dev_info(emac_dev, "EMAC: rx_crcerrors:%d\n",
+		emac_read(EMAC_RXCRCERRORS));
+	dev_info(emac_dev, "EMAC: rx_align_code_errors:%d\n",
+		emac_read(EMAC_RXALIGNCODEERRORS));
+	dev_info(emac_dev, "EMAC: rx_oversized_frames:%d\n",
+		emac_read(EMAC_RXOVERSIZED));
+	dev_info(emac_dev, "EMAC: rx_jabber_frames:%d\n",
+		emac_read(EMAC_RXJABBER));
+	dev_info(emac_dev, "EMAC: rx_undersized_frames:%d\n",
+		emac_read(EMAC_RXUNDERSIZED));
+	dev_info(emac_dev, "EMAC: rx_fragments:%d\n",
+		emac_read(EMAC_RXFRAGMENTS));
+	dev_info(emac_dev, "EMAC: rx_filtered_frames:%d\n",
+		emac_read(EMAC_RXFILTERED));
+	dev_info(emac_dev, "EMAC: rx_qos_filtered_frames:%d\n",
+		emac_read(EMAC_RXQOSFILTERED));
+	dev_info(emac_dev, "EMAC: rx_octets:%d\n",
+		emac_read(EMAC_RXOCTETS));
+	dev_info(emac_dev, "EMAC: tx_goodframes:%d\n",
+		emac_read(EMAC_TXGOODFRAMES));
+	dev_info(emac_dev, "EMAC: tx_bcastframes:%d\n",
+		emac_read(EMAC_TXBCASTFRAMES));
+	dev_info(emac_dev, "EMAC: tx_mcastframes:%d\n",
+		emac_read(EMAC_TXMCASTFRAMES));
+	dev_info(emac_dev, "EMAC: tx_pause_frames:%d\n",
+		emac_read(EMAC_TXPAUSEFRAMES));
+	dev_info(emac_dev, "EMAC: tx_deferred_frames:%d\n",
+		emac_read(EMAC_TXDEFERRED));
+	dev_info(emac_dev, "EMAC: tx_collision_frames:%d\n",
+		emac_read(EMAC_TXCOLLISION));
+	dev_info(emac_dev, "EMAC: tx_single_coll_frames:%d\n",
+		emac_read(EMAC_TXSINGLECOLL));
+	dev_info(emac_dev, "EMAC: tx_mult_coll_frames:%d\n",
+		emac_read(EMAC_TXMULTICOLL));
+	dev_info(emac_dev, "EMAC: tx_excessive_collisions:%d\n",
+		emac_read(EMAC_TXEXCESSIVECOLL));
+	dev_info(emac_dev, "EMAC: tx_late_collisions:%d\n",
+		emac_read(EMAC_TXLATECOLL));
+	dev_info(emac_dev, "EMAC: tx_underrun:%d\n",
+		emac_read(EMAC_TXUNDERRUN));
+	dev_info(emac_dev, "EMAC: tx_carrier_sense_errors:%d\n",
+		emac_read(EMAC_TXCARRIERSENSE));
+	dev_info(emac_dev, "EMAC: tx_octets:%d\n",
+		emac_read(EMAC_TXOCTETS));
+	dev_info(emac_dev, "EMAC: net_octets:%d\n",
+		emac_read(EMAC_NETOCTETS));
+	dev_info(emac_dev, "EMAC: rx_sof_overruns:%d\n",
+		emac_read(EMAC_RXSOFOVERRUNS));
+	dev_info(emac_dev, "EMAC: rx_mof_overruns:%d\n",
+		emac_read(EMAC_RXMOFOVERRUNS));
+	dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n",
+		emac_read(EMAC_RXDMAOVERRUNS));
+}
+
+/*************************************************************************
+ *  EMAC MDIO/Phy Functionality
+ *************************************************************************/
+/**
+ * emac_get_drvinfo: Get EMAC driver information
+ * @ndev: The DaVinci EMAC network adapter
+ * @info: ethtool info structure containing name and version
+ *
+ * Returns EMAC driver information (name and version)
+ *
+ */
+static void emac_get_drvinfo(struct net_device *ndev,
+			     struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, emac_version_string);
+	strcpy(info->version, EMAC_MODULE_VERSION);
+}
+
+/**
+ * emac_get_settings: Get EMAC settings
+ * @ndev: The DaVinci EMAC network adapter
+ * @ecmd: ethtool command
+ *
+ * Executes ethool get command
+ *
+ */
+static int emac_get_settings(struct net_device *ndev,
+			     struct ethtool_cmd *ecmd)
+{
+	struct emac_priv *priv = netdev_priv(ndev);
+	if (priv->phy_mask)
+		return phy_ethtool_gset(priv->phydev, ecmd);
+	else
+		return -EOPNOTSUPP;
+
+}
+
+/**
+ * emac_set_settings: Set EMAC settings
+ * @ndev: The DaVinci EMAC network adapter
+ * @ecmd: ethtool command
+ *
+ * Executes ethool set command
+ *
+ */
+static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+{
+	struct emac_priv *priv = netdev_priv(ndev);
+	if (priv->phy_mask)
+		return phy_ethtool_sset(priv->phydev, ecmd);
+	else
+		return -EOPNOTSUPP;
+
+}
+
+/**
+ * ethtool_ops: DaVinci EMAC Ethtool structure
+ *
+ * Ethtool support for EMAC adapter
+ *
+ */
+static const struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = emac_get_drvinfo,
+	.get_settings = emac_get_settings,
+	.set_settings = emac_set_settings,
+	.get_link = ethtool_op_get_link,
+};
+
+/**
+ * emac_update_phystatus: Update Phy status
+ * @priv: The DaVinci EMAC private adapter structure
+ *
+ * Updates phy status and takes action for network queue if required
+ * based upon link status
+ *
+ */
+static void emac_update_phystatus(struct emac_priv *priv)
+{
+	u32 mac_control;
+	u32 new_duplex;
+	u32 cur_duplex;
+	struct net_device *ndev = priv->ndev;
+
+	mac_control = emac_read(EMAC_MACCONTROL);
+	cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ?
+			DUPLEX_FULL : DUPLEX_HALF;
+	if (priv->phy_mask)
+		new_duplex = priv->phydev->duplex;
+	else
+		new_duplex = DUPLEX_FULL;
+
+	/* We get called only if link has changed (speed/duplex/status) */
+	if ((priv->link) && (new_duplex != cur_duplex)) {
+		priv->duplex = new_duplex;
+		if (DUPLEX_FULL == priv->duplex)
+			mac_control |= (EMAC_MACCONTROL_FULLDUPLEXEN);
+		else
+			mac_control &= ~(EMAC_MACCONTROL_FULLDUPLEXEN);
+	}
+
+	if (priv->speed == SPEED_1000 && (priv->version == EMAC_VERSION_2)) {
+		mac_control = emac_read(EMAC_MACCONTROL);
+		mac_control |= (EMAC_DM646X_MACCONTORL_GMIIEN |
+				EMAC_DM646X_MACCONTORL_GIG |
+				EMAC_DM646X_MACCONTORL_GIGFORCE);
+	} else {
+		/* Clear the GIG bit and GIGFORCE bit */
+		mac_control &= ~(EMAC_DM646X_MACCONTORL_GIGFORCE |
+					EMAC_DM646X_MACCONTORL_GIG);
+
+		if (priv->rmii_en && (priv->speed == SPEED_100))
+			mac_control |= EMAC_MACCONTROL_RMIISPEED_MASK;
+		else
+			mac_control &= ~EMAC_MACCONTROL_RMIISPEED_MASK;
+	}
+
+	/* Update mac_control if changed */
+	emac_write(EMAC_MACCONTROL, mac_control);
+
+	if (priv->link) {
+		/* link ON */
+		if (!netif_carrier_ok(ndev))
+			netif_carrier_on(ndev);
+	/* reactivate the transmit queue if it is stopped */
+		if (netif_running(ndev) && netif_queue_stopped(ndev))
+			netif_wake_queue(ndev);
+	} else {
+		/* link OFF */
+		if (netif_carrier_ok(ndev))
+			netif_carrier_off(ndev);
+		if (!netif_queue_stopped(ndev))
+			netif_stop_queue(ndev);
+	}
+}
+
+/**
+ * hash_get: Calculate hash value from mac address
+ * @addr: mac address to delete from hash table
+ *
+ * Calculates hash value from mac address
+ *
+ */
+static u32 hash_get(u8 *addr)
+{
+	u32 hash;
+	u8 tmpval;
+	int cnt;
+	hash = 0;
+
+	for (cnt = 0; cnt < 2; cnt++) {
+		tmpval = *addr++;
+		hash ^= (tmpval >> 2) ^ (tmpval << 4);
+		tmpval = *addr++;
+		hash ^= (tmpval >> 4) ^ (tmpval << 2);
+		tmpval = *addr++;
+		hash ^= (tmpval >> 6) ^ (tmpval);
+	}
+
+	return hash & 0x3F;
+}
+
+/**
+ * hash_add: Hash function to add mac addr from hash table
+ * @priv: The DaVinci EMAC private adapter structure
+ * mac_addr: mac address to delete from hash table
+ *
+ * Adds mac address to the internal hash table
+ *
+ */
+static int hash_add(struct emac_priv *priv, u8 *mac_addr)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+	u32 rc = 0;
+	u32 hash_bit;
+	u32 hash_value = hash_get(mac_addr);
+
+	if (hash_value >= EMAC_NUM_MULTICAST_BITS) {
+		if (netif_msg_drv(priv)) {
+			dev_err(emac_dev, "DaVinci EMAC: hash_add(): Invalid "\
+				"Hash %08x, should not be greater than %08x",
+				hash_value, (EMAC_NUM_MULTICAST_BITS - 1));
+		}
+		return -1;
+	}
+
+	/* set the hash bit only if not previously set */
+	if (priv->multicast_hash_cnt[hash_value] == 0) {
+		rc = 1; /* hash value changed */
+		if (hash_value < 32) {
+			hash_bit = BIT(hash_value);
+			priv->mac_hash1 |= hash_bit;
+		} else {
+			hash_bit = BIT((hash_value - 32));
+			priv->mac_hash2 |= hash_bit;
+		}
+	}
+
+	/* incr counter for num of mcast addr's mapped to "this" hash bit */
+	++priv->multicast_hash_cnt[hash_value];
+
+	return rc;
+}
+
+/**
+ * hash_del: Hash function to delete mac addr from hash table
+ * @priv: The DaVinci EMAC private adapter structure
+ * mac_addr: mac address to delete from hash table
+ *
+ * Removes mac address from the internal hash table
+ *
+ */
+static int hash_del(struct emac_priv *priv, u8 *mac_addr)
+{
+	u32 hash_value;
+	u32 hash_bit;
+
+	hash_value = hash_get(mac_addr);
+	if (priv->multicast_hash_cnt[hash_value] > 0) {
+		/* dec cntr for num of mcast addr's mapped to this hash bit */
+		--priv->multicast_hash_cnt[hash_value];
+	}
+
+	/* if counter still > 0, at least one multicast address refers
+	 * to this hash bit. so return 0 */
+	if (priv->multicast_hash_cnt[hash_value] > 0)
+		return 0;
+
+	if (hash_value < 32) {
+		hash_bit = BIT(hash_value);
+		priv->mac_hash1 &= ~hash_bit;
+	} else {
+		hash_bit = BIT((hash_value - 32));
+		priv->mac_hash2 &= ~hash_bit;
+	}
+
+	/* return 1 to indicate change in mac_hash registers reqd */
+	return 1;
+}
+
+/* EMAC multicast operation */
+#define EMAC_MULTICAST_ADD	0
+#define EMAC_MULTICAST_DEL	1
+#define EMAC_ALL_MULTI_SET	2
+#define EMAC_ALL_MULTI_CLR	3
+
+/**
+ * emac_add_mcast: Set multicast address in the EMAC adapter (Internal)
+ * @priv: The DaVinci EMAC private adapter structure
+ * @action: multicast operation to perform
+ * mac_addr: mac address to set
+ *
+ * Set multicast addresses in EMAC adapter - internal function
+ *
+ */
+static void emac_add_mcast(struct emac_priv *priv, u32 action, u8 *mac_addr)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+	int update = -1;
+
+	switch (action) {
+	case EMAC_MULTICAST_ADD:
+		update = hash_add(priv, mac_addr);
+		break;
+	case EMAC_MULTICAST_DEL:
+		update = hash_del(priv, mac_addr);
+		break;
+	case EMAC_ALL_MULTI_SET:
+		update = 1;
+		priv->mac_hash1 = EMAC_ALL_MULTI_REG_VALUE;
+		priv->mac_hash2 = EMAC_ALL_MULTI_REG_VALUE;
+		break;
+	case EMAC_ALL_MULTI_CLR:
+		update = 1;
+		priv->mac_hash1 = 0;
+		priv->mac_hash2 = 0;
+		memset(&(priv->multicast_hash_cnt[0]), 0,
+		sizeof(priv->multicast_hash_cnt[0]) *
+		       EMAC_NUM_MULTICAST_BITS);
+		break;
+	default:
+		if (netif_msg_drv(priv))
+			dev_err(emac_dev, "DaVinci EMAC: add_mcast"\
+				": bad operation %d", action);
+		break;
+	}
+
+	/* write to the hardware only if the register status chances */
+	if (update > 0) {
+		emac_write(EMAC_MACHASH1, priv->mac_hash1);
+		emac_write(EMAC_MACHASH2, priv->mac_hash2);
+	}
+}
+
+/**
+ * emac_dev_mcast_set: Set multicast address in the EMAC adapter
+ * @ndev: The DaVinci EMAC network adapter
+ *
+ * Set multicast addresses in EMAC adapter
+ *
+ */
+static void emac_dev_mcast_set(struct net_device *ndev)
+{
+	u32 mbp_enable;
+	struct emac_priv *priv = netdev_priv(ndev);
+
+	mbp_enable = emac_read(EMAC_RXMBPENABLE);
+	if (ndev->flags & IFF_PROMISC) {
+		mbp_enable &= (~EMAC_MBP_PROMISCCH(EMAC_DEF_PROM_CH));
+		mbp_enable |= (EMAC_MBP_RXPROMISC);
+	} else {
+		mbp_enable = (mbp_enable & ~EMAC_MBP_RXPROMISC);
+		if ((ndev->flags & IFF_ALLMULTI) ||
+		    (ndev->mc_count > EMAC_DEF_MAX_MULTICAST_ADDRESSES)) {
+			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
+			emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL);
+		}
+		if (ndev->mc_count > 0) {
+			struct dev_mc_list *mc_ptr;
+			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
+			emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL);
+			/* program multicast address list into EMAC hardware */
+			for (mc_ptr = ndev->mc_list; mc_ptr;
+			     mc_ptr = mc_ptr->next) {
+				emac_add_mcast(priv, EMAC_MULTICAST_ADD,
+					       (u8 *)mc_ptr->dmi_addr);
+			}
+		} else {
+			mbp_enable = (mbp_enable & ~EMAC_MBP_RXMCAST);
+			emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL);
+		}
+	}
+	/* Set mbp config register */
+	emac_write(EMAC_RXMBPENABLE, mbp_enable);
+}
+
+/*************************************************************************
+ *  EMAC Hardware manipulation
+ *************************************************************************/
+
+/**
+ * emac_int_disable: Disable EMAC module interrupt (from adapter)
+ * @priv: The DaVinci EMAC private adapter structure
+ *
+ * Disable EMAC interrupt on the adapter
+ *
+ */
+static void emac_int_disable(struct emac_priv *priv)
+{
+	if (priv->version == EMAC_VERSION_2) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+
+		/* Program C0_Int_En to zero to turn off
+		* interrupts to the CPU */
+		emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0x0);
+		emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0x0);
+		/* NOTE: Rx Threshold and Misc interrupts are not disabled */
+
+		local_irq_restore(flags);
+
+	} else {
+		/* Set DM644x control registers for interrupt control */
+		emac_ctrl_write(EMAC_CTRL_EWCTL, 0x0);
+	}
+}
+
+/**
+ * emac_int_enable: Enable EMAC module interrupt (from adapter)
+ * @priv: The DaVinci EMAC private adapter structure
+ *
+ * Enable EMAC interrupt on the adapter
+ *
+ */
+static void emac_int_enable(struct emac_priv *priv)
+{
+	if (priv->version == EMAC_VERSION_2) {
+		emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0xff);
+		emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0xff);
+
+		/* In addition to turning on interrupt Enable, we need
+		 * ack by writing appropriate values to the EOI
+		 * register */
+
+		/* NOTE: Rx Threshold and Misc interrupts are not enabled */
+
+		/* ack rxen only then a new pulse will be generated */
+		emac_write(EMAC_DM646X_MACEOIVECTOR,
+			EMAC_DM646X_MAC_EOI_C0_RXEN);
+
+		/* ack txen- only then a new pulse will be generated */
+		emac_write(EMAC_DM646X_MACEOIVECTOR,
+			EMAC_DM646X_MAC_EOI_C0_TXEN);
+
+	} else {
+		/* Set DM644x control registers for interrupt control */
+		emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1);
+	}
+}
+
+/**
+ * emac_irq: EMAC interrupt handler
+ * @irq: interrupt number
+ * @dev_id: EMAC network adapter data structure ptr
+ *
+ * EMAC Interrupt handler - we only schedule NAPI and not process any packets
+ * here. EVen the interrupt status is checked (TX/RX/Err) in NAPI poll function
+ *
+ * Returns interrupt handled condition
+ */
+static irqreturn_t emac_irq(int irq, void *dev_id)
+{
+	struct net_device *ndev = (struct net_device *)dev_id;
+	struct emac_priv *priv = netdev_priv(ndev);
+
+	++priv->isr_count;
+	if (likely(netif_running(priv->ndev))) {
+		emac_int_disable(priv);
+		napi_schedule(&priv->napi);
+	} else {
+		/* we are closing down, so dont process anything */
+	}
+	return IRQ_HANDLED;
+}
+
+/** EMAC on-chip buffer descriptor memory
+ *
+ * WARNING: Please note that the on chip memory is used for both TX and RX
+ * buffer descriptor queues and is equally divided between TX and RX desc's
+ * If the number of TX or RX descriptors change this memory pointers need
+ * to be adjusted. If external memory is allocated then these pointers can
+ * pointer to the memory
+ *
+ */
+#define EMAC_TX_BD_MEM(priv)	((priv)->emac_ctrl_ram)
+#define EMAC_RX_BD_MEM(priv)	((priv)->emac_ctrl_ram + \
+				(((priv)->ctrl_ram_size) >> 1))
+
+/**
+ * emac_init_txch: TX channel initialization
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ *
+ * Called during device init to setup a TX channel (allocate buffer desc
+ * create free pool and keep ready for transmission
+ *
+ * Returns success(0) or mem alloc failures error code
+ */
+static int emac_init_txch(struct emac_priv *priv, u32 ch)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+	u32 cnt, bd_size;
+	void __iomem *mem;
+	struct emac_tx_bd __iomem *curr_bd;
+	struct emac_txch *txch = NULL;
+
+	txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL);
+	if (NULL == txch) {
+		dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed");
+		return -ENOMEM;
+	}
+	priv->txch[ch] = txch;
+	txch->service_max = EMAC_DEF_TX_MAX_SERVICE;
+	txch->active_queue_head = NULL;
+	txch->active_queue_tail = NULL;
+	txch->queue_active = 0;
+	txch->teardown_pending = 0;
+
+	/* allocate memory for TX CPPI channel on a 4 byte boundry */
+	txch->tx_complete = kzalloc(txch->service_max * sizeof(u32),
+				    GFP_KERNEL);
+	if (NULL == txch->tx_complete) {
+		dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed");
+		kfree(txch);
+		return -ENOMEM;
+	}
+
+	/* allocate buffer descriptor pool align every BD on four word
+	 * boundry for future requirements */
+	bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF;
+	txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
+	txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF);
+
+	/* alloc TX BD memory */
+	txch->bd_mem = EMAC_TX_BD_MEM(priv);
+	__memzero((void __force *)txch->bd_mem, txch->alloc_size);
+
+	/* initialize the BD linked list */
+	mem = (void __force __iomem *)
+			(((u32 __force) txch->bd_mem + 0xF) & ~0xF);
+	txch->bd_pool_head = NULL;
+	for (cnt = 0; cnt < txch->num_bd; cnt++) {
+		curr_bd = mem + (cnt * bd_size);
+		curr_bd->next = txch->bd_pool_head;
+		txch->bd_pool_head = curr_bd;
+	}
+
+	/* reset statistics counters */
+	txch->out_of_tx_bd = 0;
+	txch->no_active_pkts = 0;
+	txch->active_queue_count = 0;
+
+	return 0;
+}
+
+/**
+ * emac_cleanup_txch: Book-keep function to clean TX channel resources
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: TX channel number
+ *
+ * Called to clean up TX channel resources
+ *
+ */
+static void emac_cleanup_txch(struct emac_priv *priv, u32 ch)
+{
+	struct emac_txch *txch = priv->txch[ch];
+
+	if (txch) {
+		if (txch->bd_mem)
+			txch->bd_mem = NULL;
+		kfree(txch->tx_complete);
+		kfree(txch);
+		priv->txch[ch] = NULL;
+	}
+}
+
+/**
+ * emac_net_tx_complete: TX packet completion function
+ * @priv: The DaVinci EMAC private adapter structure
+ * @net_data_tokens: packet token - skb pointer
+ * @num_tokens: number of skb's to free
+ * @ch: TX channel number
+ *
+ * Frees the skb once packet is transmitted
+ *
+ */
+static int emac_net_tx_complete(struct emac_priv *priv,
+				void **net_data_tokens,
+				int num_tokens, u32 ch)
+{
+	u32 cnt;
+
+	if (unlikely(num_tokens && netif_queue_stopped(priv->ndev)))
+		netif_start_queue(priv->ndev);
+	for (cnt = 0; cnt < num_tokens; cnt++) {
+		struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt];
+		if (skb == NULL)
+			continue;
+		priv->net_dev_stats.tx_packets++;
+		priv->net_dev_stats.tx_bytes += skb->len;
+		dev_kfree_skb_any(skb);
+	}
+	return 0;
+}
+
+/**
+ * emac_txch_teardown: TX channel teardown
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: TX channel number
+ *
+ * Called to teardown TX channel
+ *
+ */
+static void emac_txch_teardown(struct emac_priv *priv, u32 ch)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+	u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
+	struct emac_txch *txch = priv->txch[ch];
+	struct emac_tx_bd __iomem *curr_bd;
+
+	while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
+	       EMAC_TEARDOWN_VALUE) {
+		/* wait till tx teardown complete */
+		cpu_relax(); /* TODO: check if this helps ... */
+		--teardown_cnt;
+		if (0 == teardown_cnt) {
+			dev_err(emac_dev, "EMAC: TX teardown aborted\n");
+			break;
+		}
+	}
+	emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE);
+
+	/* process sent packets and return skb's to upper layer */
+	if (1 == txch->queue_active) {
+		curr_bd = txch->active_queue_head;
+		while (curr_bd != NULL) {
+			emac_net_tx_complete(priv, (void __force *)
+					&curr_bd->buf_token, 1, ch);
+			if (curr_bd != txch->active_queue_tail)
+				curr_bd = curr_bd->next;
+			else
+				break;
+		}
+		txch->bd_pool_head = txch->active_queue_head;
+		txch->active_queue_head =
+		txch->active_queue_tail = NULL;
+	}
+}
+
+/**
+ * emac_stop_txch: Stop TX channel operation
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: TX channel number
+ *
+ * Called to stop TX channel operation
+ *
+ */
+static void emac_stop_txch(struct emac_priv *priv, u32 ch)
+{
+	struct emac_txch *txch = priv->txch[ch];
+
+	if (txch) {
+		txch->teardown_pending = 1;
+		emac_write(EMAC_TXTEARDOWN, 0);
+		emac_txch_teardown(priv, ch);
+		txch->teardown_pending = 0;
+		emac_write(EMAC_TXINTMASKCLEAR, BIT(ch));
+	}
+}
+
+/**
+ * emac_tx_bdproc: TX buffer descriptor (packet) processing
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: TX channel number to process buffer descriptors for
+ * @budget: number of packets allowed to process
+ * @pending: indication to caller that packets are pending to process
+ *
+ * Processes TX buffer descriptors after packets are transmitted - checks
+ * ownership bit on the TX * descriptor and requeues it to free pool & frees
+ * the SKB buffer. Only "budget" number of packets are processed and
+ * indication of pending packets provided to the caller
+ *
+ * Returns number of packets processed
+ */
+static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+	unsigned long flags;
+	u32 frame_status;
+	u32 pkts_processed = 0;
+	u32 tx_complete_cnt = 0;
+	struct emac_tx_bd __iomem *curr_bd;
+	struct emac_txch *txch = priv->txch[ch];
+	u32 *tx_complete_ptr = txch->tx_complete;
+
+	if (unlikely(1 == txch->teardown_pending)) {
+		if (netif_msg_tx_err(priv) && net_ratelimit()) {
+			dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\
+				"teardown pending\n");
+		}
+		return 0;  /* dont handle any pkt completions */
+	}
+
+	++txch->proc_count;
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	curr_bd = txch->active_queue_head;
+	if (NULL == curr_bd) {
+		emac_write(EMAC_TXCP(ch),
+			   emac_virt_to_phys(txch->last_hw_bdprocessed));
+		txch->no_active_pkts++;
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
+		return 0;
+	}
+	BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+	frame_status = curr_bd->mode;
+	while ((curr_bd) &&
+	      ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
+	      (pkts_processed < budget)) {
+		emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd));
+		txch->active_queue_head = curr_bd->next;
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			if (curr_bd->next) {	/* misqueued packet */
+				emac_write(EMAC_TXHDP(ch), curr_bd->h_next);
+				++txch->mis_queued_packets;
+			} else {
+				txch->queue_active = 0; /* end of queue */
+			}
+		}
+		*tx_complete_ptr = (u32) curr_bd->buf_token;
+		++tx_complete_ptr;
+		++tx_complete_cnt;
+		curr_bd->next = txch->bd_pool_head;
+		txch->bd_pool_head = curr_bd;
+		--txch->active_queue_count;
+		pkts_processed++;
+		txch->last_hw_bdprocessed = curr_bd;
+		curr_bd = txch->active_queue_head;
+		if (curr_bd) {
+			BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+			frame_status = curr_bd->mode;
+		}
+	} /* end of pkt processing loop */
+
+	emac_net_tx_complete(priv,
+			     (void *)&txch->tx_complete[0],
+			     tx_complete_cnt, ch);
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+	return pkts_processed;
+}
+
+#define EMAC_ERR_TX_OUT_OF_BD -1
+
+/**
+ * emac_send: EMAC Transmit function (internal)
+ * @priv: The DaVinci EMAC private adapter structure
+ * @pkt: packet pointer (contains skb ptr)
+ * @ch: TX channel number
+ *
+ * Called by the transmit function to queue the packet in EMAC hardware queue
+ *
+ * Returns success(0) or error code (typically out of desc's)
+ */
+static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
+{
+	unsigned long flags;
+	struct emac_tx_bd __iomem *curr_bd;
+	struct emac_txch *txch;
+	struct emac_netbufobj *buf_list;
+
+	txch = priv->txch[ch];
+	buf_list = pkt->buf_list;   /* get handle to the buffer array */
+
+	/* check packet size and pad if short */
+	if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) {
+		buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length);
+		pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE;
+	}
+
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	curr_bd = txch->bd_pool_head;
+	if (curr_bd == NULL) {
+		txch->out_of_tx_bd++;
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
+		return EMAC_ERR_TX_OUT_OF_BD;
+	}
+
+	txch->bd_pool_head = curr_bd->next;
+	curr_bd->buf_token = buf_list->buf_token;
+	/* FIXME buff_ptr = dma_map_single(... data_ptr ...) */
+	curr_bd->buff_ptr = virt_to_phys(buf_list->data_ptr);
+	curr_bd->off_b_len = buf_list->length;
+	curr_bd->h_next = 0;
+	curr_bd->next = NULL;
+	curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT |
+			 EMAC_CPPI_EOP_BIT | pkt->pkt_length);
+
+	/* flush the packet from cache if write back cache is present */
+	BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+
+	/* send the packet */
+	if (txch->active_queue_head == NULL) {
+		txch->active_queue_head = curr_bd;
+		txch->active_queue_tail = curr_bd;
+		if (1 != txch->queue_active) {
+			emac_write(EMAC_TXHDP(ch),
+					emac_virt_to_phys(curr_bd));
+			txch->queue_active = 1;
+		}
+		++txch->queue_reinit;
+	} else {
+		register struct emac_tx_bd __iomem *tail_bd;
+		register u32 frame_status;
+
+		tail_bd = txch->active_queue_tail;
+		tail_bd->next = curr_bd;
+		txch->active_queue_tail = curr_bd;
+		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
+		tail_bd->h_next = (int)emac_virt_to_phys(curr_bd);
+		frame_status = tail_bd->mode;
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			emac_write(EMAC_TXHDP(ch), emac_virt_to_phys(curr_bd));
+			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
+			tail_bd->mode = frame_status;
+			++txch->end_of_queue_add;
+		}
+	}
+	txch->active_queue_count++;
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+	return 0;
+}
+
+/**
+ * emac_dev_xmit: EMAC Transmit function
+ * @skb: SKB pointer
+ * @ndev: The DaVinci EMAC network adapter
+ *
+ * Called by the system to transmit a packet  - we queue the packet in
+ * EMAC hardware transmit queue
+ *
+ * Returns success(NETDEV_TX_OK) or error code (typically out of desc's)
+ */
+static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct device *emac_dev = &ndev->dev;
+	int ret_code;
+	struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */
+	struct emac_netpktobj tx_packet;  /* packet object */
+	struct emac_priv *priv = netdev_priv(ndev);
+
+	/* If no link, return */
+	if (unlikely(!priv->link)) {
+		if (netif_msg_tx_err(priv) && net_ratelimit())
+			dev_err(emac_dev, "DaVinci EMAC: No link to transmit");
+		return NETDEV_TX_BUSY;
+	}
+
+	/* Build the buffer and packet objects - Since only single fragment is
+	 * supported, need not set length and token in both packet & object.
+	 * Doing so for completeness sake & to show that this needs to be done
+	 * in multifragment case
+	 */
+	tx_packet.buf_list = &tx_buf;
+	tx_packet.num_bufs = 1; /* only single fragment supported */
+	tx_packet.pkt_length = skb->len;
+	tx_packet.pkt_token = (void *)skb;
+	tx_buf.length = skb->len;
+	tx_buf.buf_token = (void *)skb;
+	tx_buf.data_ptr = skb->data;
+	EMAC_CACHE_WRITEBACK((unsigned long)skb->data, skb->len);
+	ndev->trans_start = jiffies;
+	ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH);
+	if (unlikely(ret_code != 0)) {
+		if (ret_code == EMAC_ERR_TX_OUT_OF_BD) {
+			if (netif_msg_tx_err(priv) && net_ratelimit())
+				dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\
+					" err. Out of TX BD's");
+			netif_stop_queue(priv->ndev);
+		}
+		priv->net_dev_stats.tx_dropped++;
+		return NETDEV_TX_BUSY;
+	}
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * emac_dev_tx_timeout: EMAC Transmit timeout function
+ * @ndev: The DaVinci EMAC network adapter
+ *
+ * Called when system detects that a skb timeout period has expired
+ * potentially due to a fault in the adapter in not being able to send
+ * it out on the wire. We teardown the TX channel assuming a hardware
+ * error and re-initialize the TX channel for hardware operation
+ *
+ */
+static void emac_dev_tx_timeout(struct net_device *ndev)
+{
+	struct emac_priv *priv = netdev_priv(ndev);
+	struct device *emac_dev = &ndev->dev;
+
+	if (netif_msg_tx_err(priv))
+		dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX");
+
+	priv->net_dev_stats.tx_errors++;
+	emac_int_disable(priv);
+	emac_stop_txch(priv, EMAC_DEF_TX_CH);
+	emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
+	emac_init_txch(priv, EMAC_DEF_TX_CH);
+	emac_write(EMAC_TXHDP(0), 0);
+	emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH));
+	emac_int_enable(priv);
+}
+
+/**
+ * emac_net_alloc_rx_buf: Allocate a skb for RX
+ * @priv: The DaVinci EMAC private adapter structure
+ * @buf_size: size of SKB data buffer to allocate
+ * @data_token: data token returned (skb handle for storing in buffer desc)
+ * @ch: RX channel number
+ *
+ * Called during RX channel setup - allocates skb buffer of required size
+ * and provides the skb handle and allocated buffer data pointer to caller
+ *
+ * Returns skb data pointer or 0 on failure to alloc skb
+ */
+static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size,
+		void **data_token, u32 ch)
+{
+	struct net_device *ndev = priv->ndev;
+	struct device *emac_dev = &ndev->dev;
+	struct sk_buff *p_skb;
+
+	p_skb = dev_alloc_skb(buf_size);
+	if (unlikely(NULL == p_skb)) {
+		if (netif_msg_rx_err(priv) && net_ratelimit())
+			dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb");
+		return NULL;
+	}
+
+	/* set device pointer in skb and reserve space for extra bytes */
+	p_skb->dev = ndev;
+	skb_reserve(p_skb, NET_IP_ALIGN);
+	*data_token = (void *) p_skb;
+	EMAC_CACHE_WRITEBACK_INVALIDATE((unsigned long)p_skb->data, buf_size);
+	return p_skb->data;
+}
+
+/**
+ * emac_init_rxch: RX channel initialization
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ * @param: mac address for RX channel
+ *
+ * Called during device init to setup a RX channel (allocate buffers and
+ * buffer descriptors, create queue and keep ready for reception
+ *
+ * Returns success(0) or mem alloc failures error code
+ */
+static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+	u32 cnt, bd_size;
+	void __iomem *mem;
+	struct emac_rx_bd __iomem *curr_bd;
+	struct emac_rxch *rxch = NULL;
+
+	rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL);
+	if (NULL == rxch) {
+		dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed");
+		return -ENOMEM;
+	}
+	priv->rxch[ch] = rxch;
+	rxch->buf_size = priv->rx_buf_size;
+	rxch->service_max = EMAC_DEF_RX_MAX_SERVICE;
+	rxch->queue_active = 0;
+	rxch->teardown_pending = 0;
+
+	/* save mac address */
+	for (cnt = 0; cnt < 6; cnt++)
+		rxch->mac_addr[cnt] = param[cnt];
+
+	/* allocate buffer descriptor pool align every BD on four word
+	 * boundry for future requirements */
+	bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF;
+	rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
+	rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF);
+	rxch->bd_mem = EMAC_RX_BD_MEM(priv);
+	__memzero((void __force *)rxch->bd_mem, rxch->alloc_size);
+	rxch->pkt_queue.buf_list = &rxch->buf_queue;
+
+	/* allocate RX buffer and initialize the BD linked list */
+	mem = (void __force __iomem *)
+			(((u32 __force) rxch->bd_mem + 0xF) & ~0xF);
+	rxch->active_queue_head = NULL;
+	rxch->active_queue_tail = mem;
+	for (cnt = 0; cnt < rxch->num_bd; cnt++) {
+		curr_bd = mem + (cnt * bd_size);
+		/* for future use the last parameter contains the BD ptr */
+		curr_bd->data_ptr = emac_net_alloc_rx_buf(priv,
+				    rxch->buf_size,
+				    (void __force **)&curr_bd->buf_token,
+				    EMAC_DEF_RX_CH);
+		if (curr_bd->data_ptr == NULL) {
+			dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \
+				"failed for ch %d\n", ch);
+			kfree(rxch);
+			return -ENOMEM;
+		}
+
+		/* populate the hardware descriptor */
+		curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head);
+		/* FIXME buff_ptr = dma_map_single(... data_ptr ...) */
+		curr_bd->buff_ptr = virt_to_phys(curr_bd->data_ptr);
+		curr_bd->off_b_len = rxch->buf_size;
+		curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
+
+		/* write back to hardware memory */
+		BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd,
+					      EMAC_BD_LENGTH_FOR_CACHE);
+		curr_bd->next = rxch->active_queue_head;
+		rxch->active_queue_head = curr_bd;
+	}
+
+	/* At this point rxCppi->activeQueueHead points to the first
+	   RX BD ready to be given to RX HDP and rxch->active_queue_tail
+	   points to the last RX BD
+	 */
+	return 0;
+}
+
+/**
+ * emac_rxch_teardown: RX channel teardown
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ *
+ * Called during device stop to teardown RX channel
+ *
+ */
+static void emac_rxch_teardown(struct emac_priv *priv, u32 ch)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+	u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
+
+	while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
+	       EMAC_TEARDOWN_VALUE) {
+		/* wait till tx teardown complete */
+		cpu_relax(); /* TODO: check if this helps ... */
+		--teardown_cnt;
+		if (0 == teardown_cnt) {
+			dev_err(emac_dev, "EMAC: RX teardown aborted\n");
+			break;
+		}
+	}
+	emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE);
+}
+
+/**
+ * emac_stop_rxch: Stop RX channel operation
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ *
+ * Called during device stop to stop RX channel operation
+ *
+ */
+static void emac_stop_rxch(struct emac_priv *priv, u32 ch)
+{
+	struct emac_rxch *rxch = priv->rxch[ch];
+
+	if (rxch) {
+		rxch->teardown_pending = 1;
+		emac_write(EMAC_RXTEARDOWN, ch);
+		/* wait for teardown complete */
+		emac_rxch_teardown(priv, ch);
+		rxch->teardown_pending = 0;
+		emac_write(EMAC_RXINTMASKCLEAR, BIT(ch));
+	}
+}
+
+/**
+ * emac_cleanup_rxch: Book-keep function to clean RX channel resources
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ *
+ * Called during device stop to clean up RX channel resources
+ *
+ */
+static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch)
+{
+	struct emac_rxch *rxch = priv->rxch[ch];
+	struct emac_rx_bd __iomem *curr_bd;
+
+	if (rxch) {
+		/* free the receive buffers previously allocated */
+		curr_bd = rxch->active_queue_head;
+		while (curr_bd) {
+			if (curr_bd->buf_token) {
+				dev_kfree_skb_any((struct sk_buff *)\
+						  curr_bd->buf_token);
+			}
+			curr_bd = curr_bd->next;
+		}
+		if (rxch->bd_mem)
+			rxch->bd_mem = NULL;
+		kfree(rxch);
+		priv->rxch[ch] = NULL;
+	}
+}
+
+/**
+ * emac_set_type0addr: Set EMAC Type0 mac address
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ * @mac_addr: MAC address to set in device
+ *
+ * Called internally to set Type0 mac address of the adapter (Device)
+ *
+ * Returns success (0) or appropriate error code (none as of now)
+ */
+static void emac_set_type0addr(struct emac_priv *priv, u32 ch, char *mac_addr)
+{
+	u32 val;
+	val = ((mac_addr[5] << 8) | (mac_addr[4]));
+	emac_write(EMAC_MACSRCADDRLO, val);
+
+	val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \
+	       (mac_addr[1] << 8) | (mac_addr[0]));
+	emac_write(EMAC_MACSRCADDRHI, val);
+	val = emac_read(EMAC_RXUNICASTSET);
+	val |= BIT(ch);
+	emac_write(EMAC_RXUNICASTSET, val);
+	val = emac_read(EMAC_RXUNICASTCLEAR);
+	val &= ~BIT(ch);
+	emac_write(EMAC_RXUNICASTCLEAR, val);
+}
+
+/**
+ * emac_set_type1addr: Set EMAC Type1 mac address
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ * @mac_addr: MAC address to set in device
+ *
+ * Called internally to set Type1 mac address of the adapter (Device)
+ *
+ * Returns success (0) or appropriate error code (none as of now)
+ */
+static void emac_set_type1addr(struct emac_priv *priv, u32 ch, char *mac_addr)
+{
+	u32 val;
+	emac_write(EMAC_MACINDEX, ch);
+	val = ((mac_addr[5] << 8) | mac_addr[4]);
+	emac_write(EMAC_MACADDRLO, val);
+	val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \
+	       (mac_addr[1] << 8) | (mac_addr[0]));
+	emac_write(EMAC_MACADDRHI, val);
+	emac_set_type0addr(priv, ch, mac_addr);
+}
+
+/**
+ * emac_set_type2addr: Set EMAC Type2 mac address
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ * @mac_addr: MAC address to set in device
+ * @index: index into RX address entries
+ * @match: match parameter for RX address matching logic
+ *
+ * Called internally to set Type2 mac address of the adapter (Device)
+ *
+ * Returns success (0) or appropriate error code (none as of now)
+ */
+static void emac_set_type2addr(struct emac_priv *priv, u32 ch,
+			       char *mac_addr, int index, int match)
+{
+	u32 val;
+	emac_write(EMAC_MACINDEX, index);
+	val = ((mac_addr[3] << 24) | (mac_addr[2] << 16) | \
+	       (mac_addr[1] << 8) | (mac_addr[0]));
+	emac_write(EMAC_MACADDRHI, val);
+	val = ((mac_addr[5] << 8) | mac_addr[4] | ((ch & 0x7) << 16) | \
+	       (match << 19) | BIT(20));
+	emac_write(EMAC_MACADDRLO, val);
+	emac_set_type0addr(priv, ch, mac_addr);
+}
+
+/**
+ * emac_setmac: Set mac address in the adapter (internal function)
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number
+ * @mac_addr: MAC address to set in device
+ *
+ * Called internally to set the mac address of the adapter (Device)
+ *
+ * Returns success (0) or appropriate error code (none as of now)
+ */
+static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr)
+{
+	struct device *emac_dev = &priv->ndev->dev;
+
+	if (priv->rx_addr_type == 0) {
+		emac_set_type0addr(priv, ch, mac_addr);
+	} else if (priv->rx_addr_type == 1) {
+		u32 cnt;
+		for (cnt = 0; cnt < EMAC_MAX_TXRX_CHANNELS; cnt++)
+			emac_set_type1addr(priv, ch, mac_addr);
+	} else if (priv->rx_addr_type == 2) {
+		emac_set_type2addr(priv, ch, mac_addr, ch, 1);
+		emac_set_type0addr(priv, ch, mac_addr);
+	} else {
+		if (netif_msg_drv(priv))
+			dev_err(emac_dev, "DaVinci EMAC: Wrong addressing\n");
+	}
+}
+
+/**
+ * emac_dev_setmac_addr: Set mac address in the adapter
+ * @ndev: The DaVinci EMAC network adapter
+ * @addr: MAC address to set in device
+ *
+ * Called by the system to set the mac address of the adapter (Device)
+ *
+ * Returns success (0) or appropriate error code (none as of now)
+ */
+static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
+{
+	struct emac_priv *priv = netdev_priv(ndev);
+	struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH];
+	struct device *emac_dev = &priv->ndev->dev;
+	struct sockaddr *sa = addr;
+
+	if (!is_valid_ether_addr(sa->sa_data))
+		return -EINVAL;
+
+	/* Store mac addr in priv and rx channel and set it in EMAC hw */
+	memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
+	memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
+
+	/* If the interface is down - rxch is NULL. */
+	/* MAC address is configured only after the interface is enabled. */
+	if (netif_running(ndev)) {
+		memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
+		emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+	}
+
+	if (netif_msg_drv(priv))
+		dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n",
+					priv->mac_addr);
+
+	return 0;
+}
+
+/**
+ * emac_addbd_to_rx_queue: Recycle RX buffer descriptor
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number to process buffer descriptors for
+ * @curr_bd: current buffer descriptor
+ * @buffer: buffer pointer for descriptor
+ * @buf_token: buffer token (stores skb information)
+ *
+ * Prepares the recycled buffer descriptor and addes it to hardware
+ * receive queue - if queue empty this descriptor becomes the head
+ * else addes the descriptor to end of queue
+ *
+ */
+static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
+		struct emac_rx_bd __iomem *curr_bd,
+		char *buffer, void *buf_token)
+{
+	struct emac_rxch *rxch = priv->rxch[ch];
+
+	/* populate the hardware descriptor */
+	curr_bd->h_next = 0;
+	/* FIXME buff_ptr = dma_map_single(... buffer ...) */
+	curr_bd->buff_ptr = virt_to_phys(buffer);
+	curr_bd->off_b_len = rxch->buf_size;
+	curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
+	curr_bd->next = NULL;
+	curr_bd->data_ptr = buffer;
+	curr_bd->buf_token = buf_token;
+
+	/* write back  */
+	BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+	if (rxch->active_queue_head == NULL) {
+		rxch->active_queue_head = curr_bd;
+		rxch->active_queue_tail = curr_bd;
+		if (0 != rxch->queue_active) {
+			emac_write(EMAC_RXHDP(ch),
+				   emac_virt_to_phys(rxch->active_queue_head));
+			rxch->queue_active = 1;
+		}
+	} else {
+		struct emac_rx_bd __iomem *tail_bd;
+		u32 frame_status;
+
+		tail_bd = rxch->active_queue_tail;
+		rxch->active_queue_tail = curr_bd;
+		tail_bd->next = curr_bd;
+		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
+		tail_bd->h_next = emac_virt_to_phys(curr_bd);
+		frame_status = tail_bd->mode;
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			emac_write(EMAC_RXHDP(ch),
+					emac_virt_to_phys(curr_bd));
+			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
+			tail_bd->mode = frame_status;
+			++rxch->end_of_queue_add;
+		}
+	}
+	++rxch->recycled_bd;
+}
+
+/**
+ * emac_net_rx_cb: Prepares packet and sends to upper layer
+ * @priv: The DaVinci EMAC private adapter structure
+ * @net_pkt_list: Network packet list (received packets)
+ *
+ * Invalidates packet buffer memory and sends the received packet to upper
+ * layer
+ *
+ * Returns success or appropriate error code (none as of now)
+ */
+static int emac_net_rx_cb(struct emac_priv *priv,
+			  struct emac_netpktobj *net_pkt_list)
+{
+	struct sk_buff *p_skb;
+	p_skb = (struct sk_buff *)net_pkt_list->pkt_token;
+	/* set length of packet */
+	skb_put(p_skb, net_pkt_list->pkt_length);
+	EMAC_CACHE_INVALIDATE((unsigned long)p_skb->data, p_skb->len);
+	p_skb->protocol = eth_type_trans(p_skb, priv->ndev);
+	p_skb->dev->last_rx = jiffies;
+	netif_receive_skb(p_skb);
+	priv->net_dev_stats.rx_bytes += net_pkt_list->pkt_length;
+	priv->net_dev_stats.rx_packets++;
+	return 0;
+}
+
+/**
+ * emac_rx_bdproc: RX buffer descriptor (packet) processing
+ * @priv: The DaVinci EMAC private adapter structure
+ * @ch: RX channel number to process buffer descriptors for
+ * @budget: number of packets allowed to process
+ * @pending: indication to caller that packets are pending to process
+ *
+ * Processes RX buffer descriptors - checks ownership bit on the RX buffer
+ * descriptor, sends the receive packet to upper layer, allocates a new SKB
+ * and recycles the buffer descriptor (requeues it in hardware RX queue).
+ * Only "budget" number of packets are processed and indication of pending
+ * packets provided to the caller.
+ *
+ * Returns number of packets processed (and indication of pending packets)
+ */
+static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
+{
+	unsigned long flags;
+	u32 frame_status;
+	u32 pkts_processed = 0;
+	char *new_buffer;
+	struct emac_rx_bd __iomem *curr_bd;
+	struct emac_rx_bd __iomem *last_bd;
+	struct emac_netpktobj *curr_pkt, pkt_obj;
+	struct emac_netbufobj buf_obj;
+	struct emac_netbufobj *rx_buf_obj;
+	void *new_buf_token;
+	struct emac_rxch *rxch = priv->rxch[ch];
+
+	if (unlikely(1 == rxch->teardown_pending))
+		return 0;
+	++rxch->proc_count;
+	spin_lock_irqsave(&priv->rx_lock, flags);
+	pkt_obj.buf_list = &buf_obj;
+	curr_pkt = &pkt_obj;
+	curr_bd = rxch->active_queue_head;
+	BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+	frame_status = curr_bd->mode;
+
+	while ((curr_bd) &&
+	       ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
+	       (pkts_processed < budget)) {
+
+		new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size,
+					&new_buf_token, EMAC_DEF_RX_CH);
+		if (unlikely(NULL == new_buffer)) {
+			++rxch->out_of_rx_buffers;
+			goto end_emac_rx_bdproc;
+		}
+
+		/* populate received packet data structure */
+		rx_buf_obj = &curr_pkt->buf_list[0];
+		rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr;
+		rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE;
+		rx_buf_obj->buf_token = curr_bd->buf_token;
+		curr_pkt->pkt_token = curr_pkt->buf_list->buf_token;
+		curr_pkt->num_bufs = 1;
+		curr_pkt->pkt_length =
+			(frame_status & EMAC_RX_BD_PKT_LENGTH_MASK);
+		emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd));
+		++rxch->processed_bd;
+		last_bd = curr_bd;
+		curr_bd = last_bd->next;
+		rxch->active_queue_head = curr_bd;
+
+		/* check if end of RX queue ? */
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			if (curr_bd) {
+				++rxch->mis_queued_packets;
+				emac_write(EMAC_RXHDP(ch),
+					   emac_virt_to_phys(curr_bd));
+			} else {
+				++rxch->end_of_queue;
+				rxch->queue_active = 0;
+			}
+		}
+
+		/* recycle BD */
+		emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer,
+				       new_buf_token);
+
+		/* return the packet to the user - BD ptr passed in
+		 * last parameter for potential *future* use */
+		spin_unlock_irqrestore(&priv->rx_lock, flags);
+		emac_net_rx_cb(priv, curr_pkt);
+		spin_lock_irqsave(&priv->rx_lock, flags);
+		curr_bd = rxch->active_queue_head;
+		if (curr_bd) {
+			BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+			frame_status = curr_bd->mode;
+		}
+		++pkts_processed;
+	}
+
+end_emac_rx_bdproc:
+	spin_unlock_irqrestore(&priv->rx_lock, flags);
+	return pkts_processed;
+}
+
+/**
+ * emac_hw_enable: Enable EMAC hardware for packet transmission/reception
+ * @priv: The DaVinci EMAC private adapter structure
+ *
+ * Enables EMAC hardware for packet processing - enables PHY, enables RX
+ * for packet reception and enables device interrupts and then NAPI
+ *
+ * Returns success (0) or appropriate error code (none right now)
+ */
+static int emac_hw_enable(struct emac_priv *priv)
+{
+	u32 ch, val, mbp_enable, mac_control;
+
+	/* Soft reset */
+	emac_write(EMAC_SOFTRESET, 1);
+	while (emac_read(EMAC_SOFTRESET))
+		cpu_relax();
+
+	/* Disable interrupt & Set pacing for more interrupts initially */
+	emac_int_disable(priv);
+
+	/* Full duplex enable bit set when auto negotiation happens */
+	mac_control =
+		(((EMAC_DEF_TXPRIO_FIXED) ? (EMAC_MACCONTROL_TXPTYPE) : 0x0) |
+		((priv->speed == 1000) ? EMAC_MACCONTROL_GIGABITEN : 0x0) |
+		((EMAC_DEF_TXPACING_EN) ? (EMAC_MACCONTROL_TXPACEEN) : 0x0) |
+		((priv->duplex == DUPLEX_FULL) ? 0x1 : 0));
+	emac_write(EMAC_MACCONTROL, mac_control);
+
+	mbp_enable =
+		(((EMAC_DEF_PASS_CRC) ? (EMAC_RXMBP_PASSCRC_MASK) : 0x0) |
+		((EMAC_DEF_QOS_EN) ? (EMAC_RXMBP_QOSEN_MASK) : 0x0) |
+		 ((EMAC_DEF_NO_BUFF_CHAIN) ? (EMAC_RXMBP_NOCHAIN_MASK) : 0x0) |
+		 ((EMAC_DEF_MACCTRL_FRAME_EN) ? (EMAC_RXMBP_CMFEN_MASK) : 0x0) |
+		 ((EMAC_DEF_SHORT_FRAME_EN) ? (EMAC_RXMBP_CSFEN_MASK) : 0x0) |
+		 ((EMAC_DEF_ERROR_FRAME_EN) ? (EMAC_RXMBP_CEFEN_MASK) : 0x0) |
+		 ((EMAC_DEF_PROM_EN) ? (EMAC_RXMBP_CAFEN_MASK) : 0x0) |
+		 ((EMAC_DEF_PROM_CH & EMAC_RXMBP_CHMASK) << \
+			EMAC_RXMBP_PROMCH_SHIFT) |
+		 ((EMAC_DEF_BCAST_EN) ? (EMAC_RXMBP_BROADEN_MASK) : 0x0) |
+		 ((EMAC_DEF_BCAST_CH & EMAC_RXMBP_CHMASK) << \
+			EMAC_RXMBP_BROADCH_SHIFT) |
+		 ((EMAC_DEF_MCAST_EN) ? (EMAC_RXMBP_MULTIEN_MASK) : 0x0) |
+		 ((EMAC_DEF_MCAST_CH & EMAC_RXMBP_CHMASK) << \
+			EMAC_RXMBP_MULTICH_SHIFT));
+	emac_write(EMAC_RXMBPENABLE, mbp_enable);
+	emac_write(EMAC_RXMAXLEN, (EMAC_DEF_MAX_FRAME_SIZE &
+				   EMAC_RX_MAX_LEN_MASK));
+	emac_write(EMAC_RXBUFFEROFFSET, (EMAC_DEF_BUFFER_OFFSET &
+					 EMAC_RX_BUFFER_OFFSET_MASK));
+	emac_write(EMAC_RXFILTERLOWTHRESH, 0);
+	emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL);
+	priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF;
+
+	val = emac_read(EMAC_TXCONTROL);
+	val |= EMAC_TX_CONTROL_TX_ENABLE_VAL;
+	emac_write(EMAC_TXCONTROL, val);
+	val = emac_read(EMAC_RXCONTROL);
+	val |= EMAC_RX_CONTROL_RX_ENABLE_VAL;
+	emac_write(EMAC_RXCONTROL, val);
+	emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL);
+
+	for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) {
+		emac_write(EMAC_TXHDP(ch), 0);
+		emac_write(EMAC_TXINTMASKSET, BIT(ch));
+	}
+	for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) {
+		struct emac_rxch *rxch = priv->rxch[ch];
+		emac_setmac(priv, ch, rxch->mac_addr);
+		emac_write(EMAC_RXINTMASKSET, BIT(ch));
+		rxch->queue_active = 1;
+		emac_write(EMAC_RXHDP(ch),
+			   emac_virt_to_phys(rxch->active_queue_head));
+	}
+
+	/* Enable MII */
+	val = emac_read(EMAC_MACCONTROL);
+	val |= (EMAC_MACCONTROL_MIIEN);
+	emac_write(EMAC_MACCONTROL, val);
+
+	/* Enable NAPI and interrupts */
+	napi_enable(&priv->napi);
+	emac_int_enable(priv);
+	return 0;
+
+}
+
+/**
+ * emac_poll: EMAC NAPI Poll function
+ * @ndev: The DaVinci EMAC network adapter
+ * @budget: Number of receive packets to process (as told by NAPI layer)
+ *
+ * NAPI Poll function implemented to process packets as per budget. We check
+ * the type of interrupt on the device and accordingly call the TX or RX
+ * packet processing functions. We follow the budget for RX processing and
+ * also put a cap on number of TX pkts processed through config param. The
+ * NAPI schedule function is called if more packets pending.
+ *
+ * Returns number of packets received (in most cases; else TX pkts - rarely)
+ */
+static int emac_poll(struct napi_struct *napi, int budget)
+{
+	unsigned int mask;
+	struct emac_priv *priv = container_of(napi, struct emac_priv, napi);
+	struct net_device *ndev = priv->ndev;
+	struct device *emac_dev = &ndev->dev;
+	u32 status = 0;
+	u32 num_pkts = 0;
+
+	if (!netif_running(ndev))
+		return 0;
+
+	/* Check interrupt vectors and call packet processing */
+	status = emac_read(EMAC_MACINVECTOR);
+
+	mask = EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC;
+
+	if (priv->version == EMAC_VERSION_2)
+		mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC;
+
+	if (status & mask) {
+		num_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH,
+					  EMAC_DEF_TX_MAX_SERVICE);
+	} /* TX processing */
+
+	if (num_pkts)
+		return budget;
+
+	mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC;
+
+	if (priv->version == EMAC_VERSION_2)
+		mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC;
+
+	if (status & mask) {
+		num_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget);
+	} /* RX processing */
+
+	if (num_pkts < budget) {
+		napi_complete(napi);
+		emac_int_enable(priv);
+	}
+
+	if (unlikely(status & EMAC_DM644X_MAC_IN_VECTOR_HOST_INT)) {
+		u32 ch, cause;
+		dev_err(emac_dev, "DaVinci EMAC: Fatal Hardware Error\n");
+		netif_stop_queue(ndev);
+		napi_disable(&priv->napi);
+
+		status = emac_read(EMAC_MACSTATUS);
+		cause = ((status & EMAC_MACSTATUS_TXERRCODE_MASK) >>
+			 EMAC_MACSTATUS_TXERRCODE_SHIFT);
+		if (cause) {
+			ch = ((status & EMAC_MACSTATUS_TXERRCH_MASK) >>
+			      EMAC_MACSTATUS_TXERRCH_SHIFT);
+			if (net_ratelimit()) {
+				dev_err(emac_dev, "TX Host error %s on ch=%d\n",
+					&emac_txhost_errcodes[cause][0], ch);
+			}
+		}
+		cause = ((status & EMAC_MACSTATUS_RXERRCODE_MASK) >>
+			 EMAC_MACSTATUS_RXERRCODE_SHIFT);
+		if (cause) {
+			ch = ((status & EMAC_MACSTATUS_RXERRCH_MASK) >>
+			      EMAC_MACSTATUS_RXERRCH_SHIFT);
+			if (netif_msg_hw(priv) && net_ratelimit())
+				dev_err(emac_dev, "RX Host error %s on ch=%d\n",
+					&emac_rxhost_errcodes[cause][0], ch);
+		}
+	} /* Host error processing */
+
+	return num_pkts;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * emac_poll_controller: EMAC Poll controller function
+ * @ndev: The DaVinci EMAC network adapter
+ *
+ * Polled functionality used by netconsole and others in non interrupt mode
+ *
+ */
+void emac_poll_controller(struct net_device *ndev)
+{
+	struct emac_priv *priv = netdev_priv(ndev);
+
+	emac_int_disable(priv);
+	emac_irq(ndev->irq, priv);
+	emac_int_enable(priv);
+}
+#endif
+
+/* PHY/MII bus related */
+
+/* Wait until mdio is ready for next command */
+#define MDIO_WAIT_FOR_USER_ACCESS\
+		while ((emac_mdio_read((MDIO_USERACCESS(0))) &\
+			MDIO_USERACCESS_GO) != 0)
+
+static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg)
+{
+	unsigned int phy_data = 0;
+	unsigned int phy_control;
+
+	/* Wait until mdio is ready for next command */
+	MDIO_WAIT_FOR_USER_ACCESS;
+
+	phy_control = (MDIO_USERACCESS_GO |
+		       MDIO_USERACCESS_READ |
+		       ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
+		       ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
+		       (phy_data & MDIO_USERACCESS_DATA));
+	emac_mdio_write(MDIO_USERACCESS(0), phy_control);
+
+	/* Wait until mdio is ready for next command */
+	MDIO_WAIT_FOR_USER_ACCESS;
+
+	return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA;
+
+}
+
+static int emac_mii_write(struct mii_bus *bus, int phy_id,
+			  int phy_reg, u16 phy_data)
+{
+
+	unsigned int control;
+
+	/*  until mdio is ready for next command */
+	MDIO_WAIT_FOR_USER_ACCESS;
+
+	control = (MDIO_USERACCESS_GO |
+		   MDIO_USERACCESS_WRITE |
+		   ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
+		   ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
+		   (phy_data & MDIO_USERACCESS_DATA));
+	emac_mdio_write(MDIO_USERACCESS(0), control);
+
+	return 0;
+}
+
+static int emac_mii_reset(struct mii_bus *bus)
+{
+	unsigned int clk_div;
+	int mdio_bus_freq = emac_bus_frequency;
+
+	if (mdio_max_freq & mdio_bus_freq)
+		clk_div = ((mdio_bus_freq / mdio_max_freq) - 1);
+	else
+		clk_div = 0xFF;
+
+	clk_div &= MDIO_CONTROL_CLKDIV;
+
+	/* Set enable and clock divider in MDIOControl */
+	emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE));
+
+	return 0;
+
+}
+
+static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL };
+
+/* emac_driver: EMAC MII bus structure */
+
+static struct mii_bus *emac_mii;
+
+static void emac_adjust_link(struct net_device *ndev)
+{
+	struct emac_priv *priv = netdev_priv(ndev);
+	struct phy_device *phydev = priv->phydev;
+	unsigned long flags;
+	int new_state = 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (phydev->link) {
+		/* check the mode of operation - full/half duplex */
+		if (phydev->duplex != priv->duplex) {
+			new_state = 1;
+			priv->duplex = phydev->duplex;
+		}
+		if (phydev->speed != priv->speed) {
+			new_state = 1;
+			priv->speed = phydev->speed;
+		}
+		if (!priv->link) {
+			new_state = 1;
+			priv->link = 1;
+		}
+
+	} else if (priv->link) {
+		new_state = 1;
+		priv->link = 0;
+		priv->speed = 0;
+		priv->duplex = ~0;
+	}
+	if (new_state) {
+		emac_update_phystatus(priv);
+		phy_print_status(priv->phydev);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/*************************************************************************
+ *  Linux Driver Model
+ *************************************************************************/
+
+/**
+ * emac_devioctl: EMAC adapter ioctl
+ * @ndev: The DaVinci EMAC network adapter
+ * @ifrq: request parameter
+ * @cmd: command parameter
+ *
+ * EMAC driver ioctl function
+ *
+ * Returns success(0) or appropriate error code
+ */
+static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
+{
+	dev_warn(&ndev->dev, "DaVinci EMAC: ioctl not supported\n");
+
+	if (!(netif_running(ndev)))
+		return -EINVAL;
+
+	/* TODO: Add phy read and write and private statistics get feature */
+
+	return -EOPNOTSUPP;
+}
+
+/**
+ * emac_dev_open: EMAC device open
+ * @ndev: The DaVinci EMAC network adapter
+ *
+ * Called when system wants to start the interface. We init TX/RX channels
+ * and enable the hardware for packet reception/transmission and start the
+ * network queue.
+ *
+ * Returns 0 for a successful open, or appropriate error code
+ */
+static int emac_dev_open(struct net_device *ndev)
+{
+	struct device *emac_dev = &ndev->dev;
+	u32 rc, cnt, ch;
+	int phy_addr;
+	struct resource *res;
+	int q, m;
+	int i = 0;
+	int k = 0;
+	struct emac_priv *priv = netdev_priv(ndev);
+
+	netif_carrier_off(ndev);
+	for (cnt = 0; cnt <= ETH_ALEN; cnt++)
+		ndev->dev_addr[cnt] = priv->mac_addr[cnt];
+
+	/* Configuration items */
+	priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN;
+
+	/* Clear basic hardware */
+	for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) {
+		emac_write(EMAC_TXHDP(ch), 0);
+		emac_write(EMAC_RXHDP(ch), 0);
+		emac_write(EMAC_RXHDP(ch), 0);
+		emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
+		emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
+	}
+	priv->mac_hash1 = 0;
+	priv->mac_hash2 = 0;
+	emac_write(EMAC_MACHASH1, 0);
+	emac_write(EMAC_MACHASH2, 0);
+
+	/* multi ch not supported - open 1 TX, 1RX ch by default */
+	rc = emac_init_txch(priv, EMAC_DEF_TX_CH);
+	if (0 != rc) {
+		dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed");
+		return rc;
+	}
+	rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr);
+	if (0 != rc) {
+		dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed");
+		return rc;
+	}
+
+	/* Request IRQ */
+
+	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
+		for (i = res->start; i <= res->end; i++) {
+			if (request_irq(i, emac_irq, IRQF_DISABLED,
+					ndev->name, ndev))
+				goto rollback;
+		}
+		k++;
+	}
+
+	/* Start/Enable EMAC hardware */
+	emac_hw_enable(priv);
+
+	/* find the first phy */
+	priv->phydev = NULL;
+	if (priv->phy_mask) {
+		emac_mii_reset(priv->mii_bus);
+		for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+			if (priv->mii_bus->phy_map[phy_addr]) {
+				priv->phydev = priv->mii_bus->phy_map[phy_addr];
+				break;
+			}
+		}
+
+		if (!priv->phydev) {
+			printk(KERN_ERR "%s: no PHY found\n", ndev->name);
+			return -1;
+		}
+
+		priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev),
+				&emac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+
+		if (IS_ERR(priv->phydev)) {
+			printk(KERN_ERR "%s: Could not attach to PHY\n",
+								ndev->name);
+			return PTR_ERR(priv->phydev);
+		}
+
+		priv->link = 0;
+		priv->speed = 0;
+		priv->duplex = ~0;
+
+		printk(KERN_INFO "%s: attached PHY driver [%s] "
+			"(mii_bus:phy_addr=%s, id=%x)\n", ndev->name,
+			priv->phydev->drv->name, dev_name(&priv->phydev->dev),
+			priv->phydev->phy_id);
+	} else{
+		/* No PHY , fix the link, speed and duplex settings */
+		priv->link = 1;
+		priv->speed = SPEED_100;
+		priv->duplex = DUPLEX_FULL;
+		emac_update_phystatus(priv);
+	}
+
+	if (!netif_running(ndev)) /* debug only - to avoid compiler warning */
+		emac_dump_regs(priv);
+
+	if (netif_msg_drv(priv))
+		dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name);
+
+	if (priv->phy_mask)
+		phy_start(priv->phydev);
+
+	return 0;
+
+rollback:
+
+	dev_err(emac_dev, "DaVinci EMAC: request_irq() failed");
+
+	for (q = k; k >= 0; k--) {
+		for (m = i; m >= res->start; m--)
+			free_irq(m, ndev);
+		res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1);
+		m = res->end;
+	}
+	return -EBUSY;
+}
+
+/**
+ * emac_dev_stop: EMAC device stop
+ * @ndev: The DaVinci EMAC network adapter
+ *
+ * Called when system wants to stop or down the interface. We stop the network
+ * queue, disable interrupts and cleanup TX/RX channels.
+ *
+ * We return the statistics in net_device_stats structure pulled from emac
+ */
+static int emac_dev_stop(struct net_device *ndev)
+{
+	struct resource *res;
+	int i = 0;
+	int irq_num;
+	struct emac_priv *priv = netdev_priv(ndev);
+	struct device *emac_dev = &ndev->dev;
+
+	/* inform the upper layers. */
+	netif_stop_queue(ndev);
+	napi_disable(&priv->napi);
+
+	netif_carrier_off(ndev);
+	emac_int_disable(priv);
+	emac_stop_txch(priv, EMAC_DEF_TX_CH);
+	emac_stop_rxch(priv, EMAC_DEF_RX_CH);
+	emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
+	emac_cleanup_rxch(priv, EMAC_DEF_RX_CH);
+	emac_write(EMAC_SOFTRESET, 1);
+
+	if (priv->phydev)
+		phy_disconnect(priv->phydev);
+
+	/* Free IRQ */
+	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) {
+		for (irq_num = res->start; irq_num <= res->end; irq_num++)
+			free_irq(irq_num, priv->ndev);
+		i++;
+	}
+
+	if (netif_msg_drv(priv))
+		dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
+
+	return 0;
+}
+
+/**
+ * emac_dev_getnetstats: EMAC get statistics function
+ * @ndev: The DaVinci EMAC network adapter
+ *
+ * Called when system wants to get statistics from the device.
+ *
+ * We return the statistics in net_device_stats structure pulled from emac
+ */
+static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
+{
+	struct emac_priv *priv = netdev_priv(ndev);
+
+	/* update emac hardware stats and reset the registers*/
+
+	priv->net_dev_stats.multicast += emac_read(EMAC_RXMCASTFRAMES);
+	emac_write(EMAC_RXMCASTFRAMES, EMAC_ALL_MULTI_REG_VALUE);
+
+	priv->net_dev_stats.collisions += (emac_read(EMAC_TXCOLLISION) +
+					   emac_read(EMAC_TXSINGLECOLL) +
+					   emac_read(EMAC_TXMULTICOLL));
+	emac_write(EMAC_TXCOLLISION, EMAC_ALL_MULTI_REG_VALUE);
+	emac_write(EMAC_TXSINGLECOLL, EMAC_ALL_MULTI_REG_VALUE);
+	emac_write(EMAC_TXMULTICOLL, EMAC_ALL_MULTI_REG_VALUE);
+
+	priv->net_dev_stats.rx_length_errors += (emac_read(EMAC_RXOVERSIZED) +
+						emac_read(EMAC_RXJABBER) +
+						emac_read(EMAC_RXUNDERSIZED));
+	emac_write(EMAC_RXOVERSIZED, EMAC_ALL_MULTI_REG_VALUE);
+	emac_write(EMAC_RXJABBER, EMAC_ALL_MULTI_REG_VALUE);
+	emac_write(EMAC_RXUNDERSIZED, EMAC_ALL_MULTI_REG_VALUE);
+
+	priv->net_dev_stats.rx_over_errors += (emac_read(EMAC_RXSOFOVERRUNS) +
+					       emac_read(EMAC_RXMOFOVERRUNS));
+	emac_write(EMAC_RXSOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+	emac_write(EMAC_RXMOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+
+	priv->net_dev_stats.rx_fifo_errors += emac_read(EMAC_RXDMAOVERRUNS);
+	emac_write(EMAC_RXDMAOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+
+	priv->net_dev_stats.tx_carrier_errors +=
+		emac_read(EMAC_TXCARRIERSENSE);
+	emac_write(EMAC_TXCARRIERSENSE, EMAC_ALL_MULTI_REG_VALUE);
+
+	priv->net_dev_stats.tx_fifo_errors = emac_read(EMAC_TXUNDERRUN);
+	emac_write(EMAC_TXUNDERRUN, EMAC_ALL_MULTI_REG_VALUE);
+
+	return &priv->net_dev_stats;
+}
+
+static const struct net_device_ops emac_netdev_ops = {
+	.ndo_open		= emac_dev_open,
+	.ndo_stop		= emac_dev_stop,
+	.ndo_start_xmit		= emac_dev_xmit,
+	.ndo_set_multicast_list	= emac_dev_mcast_set,
+	.ndo_set_mac_address	= emac_dev_setmac_addr,
+	.ndo_do_ioctl		= emac_devioctl,
+	.ndo_tx_timeout		= emac_dev_tx_timeout,
+	.ndo_get_stats		= emac_dev_getnetstats,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= emac_poll_controller,
+#endif
+};
+
+/**
+ * davinci_emac_probe: EMAC device probe
+ * @pdev: The DaVinci EMAC device that we are removing
+ *
+ * Called when probing for emac devicesr. We get details of instances and
+ * resource information from platform init and register a network device
+ * and allocate resources necessary for driver to perform
+ */
+static int __devinit davinci_emac_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct resource *res;
+	struct net_device *ndev;
+	struct emac_priv *priv;
+	unsigned long size;
+	struct emac_platform_data *pdata;
+	struct device *emac_dev;
+
+	/* obtain emac clock from kernel */
+	emac_clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(emac_clk)) {
+		printk(KERN_ERR "DaVinci EMAC: Failed to get EMAC clock\n");
+		return -EBUSY;
+	}
+	emac_bus_frequency = clk_get_rate(emac_clk);
+	/* TODO: Probe PHY here if possible */
+
+	ndev = alloc_etherdev(sizeof(struct emac_priv));
+	if (!ndev) {
+		printk(KERN_ERR "DaVinci EMAC: Error allocating net_device\n");
+		clk_put(emac_clk);
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, ndev);
+	priv = netdev_priv(ndev);
+	priv->pdev = pdev;
+	priv->ndev = ndev;
+	priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG);
+
+	spin_lock_init(&priv->tx_lock);
+	spin_lock_init(&priv->rx_lock);
+	spin_lock_init(&priv->lock);
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		printk(KERN_ERR "DaVinci EMAC: No platfrom data\n");
+		return -ENODEV;
+	}
+
+	/* MAC addr and PHY mask , RMII enable info from platform_data */
+	memcpy(priv->mac_addr, pdata->mac_addr, 6);
+	priv->phy_mask = pdata->phy_mask;
+	priv->rmii_en = pdata->rmii_en;
+	priv->version = pdata->version;
+	emac_dev = &ndev->dev;
+	/* Get EMAC platform data */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(emac_dev, "DaVinci EMAC: Error getting res\n");
+		rc = -ENOENT;
+		goto probe_quit;
+	}
+
+	priv->emac_base_phys = res->start + pdata->ctrl_reg_offset;
+	size = res->end - res->start + 1;
+	if (!request_mem_region(res->start, size, ndev->name)) {
+		dev_err(emac_dev, "DaVinci EMAC: failed request_mem_region() \
+					 for regs\n");
+		rc = -ENXIO;
+		goto probe_quit;
+	}
+
+	priv->remap_addr = ioremap(res->start, size);
+	if (!priv->remap_addr) {
+		dev_err(emac_dev, "Unable to map IO\n");
+		rc = -ENOMEM;
+		release_mem_region(res->start, size);
+		goto probe_quit;
+	}
+	priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
+	ndev->base_addr = (unsigned long)priv->remap_addr;
+
+	priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
+	priv->ctrl_ram_size = pdata->ctrl_ram_size;
+	priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(emac_dev, "DaVinci EMAC: Error getting irq res\n");
+		rc = -ENOENT;
+		goto no_irq_res;
+	}
+	ndev->irq = res->start;
+
+	if (!is_valid_ether_addr(priv->mac_addr)) {
+		/* Use random MAC if none passed */
+		random_ether_addr(priv->mac_addr);
+		printk(KERN_WARNING "%s: using random MAC addr: %pM\n",
+				__func__, priv->mac_addr);
+	}
+
+	ndev->netdev_ops = &emac_netdev_ops;
+	SET_ETHTOOL_OPS(ndev, &ethtool_ops);
+	netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
+
+	/* register the network device */
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	rc = register_netdev(ndev);
+	if (rc) {
+		dev_err(emac_dev, "DaVinci EMAC: Error in register_netdev\n");
+		rc = -ENODEV;
+		goto netdev_reg_err;
+	}
+
+	clk_enable(emac_clk);
+
+	/* MII/Phy intialisation, mdio bus registration */
+	emac_mii = mdiobus_alloc();
+	if (emac_mii == NULL) {
+		dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n");
+		rc = -ENOMEM;
+		goto mdio_alloc_err;
+	}
+
+	priv->mii_bus = emac_mii;
+	emac_mii->name  = "emac-mii",
+	emac_mii->read  = emac_mii_read,
+	emac_mii->write = emac_mii_write,
+	emac_mii->reset = emac_mii_reset,
+	emac_mii->irq   = mii_irqs,
+	emac_mii->phy_mask = ~(priv->phy_mask);
+	emac_mii->parent = &pdev->dev;
+	emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset;
+	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id);
+	mdio_max_freq = pdata->mdio_max_freq;
+	emac_mii->reset(emac_mii);
+
+	/* Register the MII bus */
+	rc = mdiobus_register(emac_mii);
+	if (rc)
+		goto mdiobus_quit;
+
+	if (netif_msg_probe(priv)) {
+		dev_notice(emac_dev, "DaVinci EMAC Probe found device "\
+			   "(regs: %p, irq: %d)\n",
+			   (void *)priv->emac_base_phys, ndev->irq);
+	}
+	return 0;
+
+mdiobus_quit:
+	mdiobus_free(emac_mii);
+
+netdev_reg_err:
+mdio_alloc_err:
+no_irq_res:
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+	iounmap(priv->remap_addr);
+
+probe_quit:
+	clk_put(emac_clk);
+	free_netdev(ndev);
+	return rc;
+}
+
+/**
+ * davinci_emac_remove: EMAC device remove
+ * @pdev: The DaVinci EMAC device that we are removing
+ *
+ * Called when removing the device driver. We disable clock usage and release
+ * the resources taken up by the driver and unregister network device
+ */
+static int __devexit davinci_emac_remove(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct emac_priv *priv = netdev_priv(ndev);
+
+	dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n");
+
+	platform_set_drvdata(pdev, NULL);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mdiobus_unregister(priv->mii_bus);
+	mdiobus_free(priv->mii_bus);
+
+	release_mem_region(res->start, res->end - res->start + 1);
+
+	unregister_netdev(ndev);
+	free_netdev(ndev);
+	iounmap(priv->remap_addr);
+
+	clk_disable(emac_clk);
+	clk_put(emac_clk);
+
+	return 0;
+}
+
+/**
+ * davinci_emac_driver: EMAC platform driver structure
+ *
+ * We implement only probe and remove functions - suspend/resume and
+ * others not supported by this module
+ */
+static struct platform_driver davinci_emac_driver = {
+	.driver = {
+		.name	 = "davinci_emac",
+		.owner	 = THIS_MODULE,
+	},
+	.probe = davinci_emac_probe,
+	.remove = __devexit_p(davinci_emac_remove),
+};
+
+/**
+ * davinci_emac_init: EMAC driver module init
+ *
+ * Called when initializing the driver. We register the driver with
+ * the platform.
+ */
+static int __init davinci_emac_init(void)
+{
+	return platform_driver_register(&davinci_emac_driver);
+}
+module_init(davinci_emac_init);
+
+/**
+ * davinci_emac_exit: EMAC driver module exit
+ *
+ * Called when exiting the driver completely. We unregister the driver with
+ * the platform and exit
+ */
+static void __exit davinci_emac_exit(void)
+{
+	platform_driver_unregister(&davinci_emac_driver);
+}
+module_exit(davinci_emac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("DaVinci EMAC Maintainer: Anant Gole <anantgole@ti.com>");
+MODULE_AUTHOR("DaVinci EMAC Maintainer: Chaithrika U S <chaithrika@ti.com>");
+MODULE_DESCRIPTION("DaVinci EMAC Ethernet driver");
diff -druN linux-libre-2.6.30-gnu/drivers/net/de600.c linux-libre-2.6.31-gnu/drivers/net/de600.c
--- linux-libre-2.6.30-gnu/drivers/net/de600.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/de600.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,14 +38,6 @@
 /* Add more time here if your adapter won't work OK: */
 #define DE600_SLOW_DOWN	udelay(delay_time)
 
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifdef DE600_DEBUG
-#define PRINTK(x) if (de600_debug >= 2) printk x
-#else
-#define DE600_DEBUG 0
-#define PRINTK(x) /**/
-#endif
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -67,10 +59,6 @@
 
 #include "de600.h"
 
-static unsigned int de600_debug = DE600_DEBUG;
-module_param(de600_debug, int, 0);
-MODULE_PARM_DESC(de600_debug, "DE-600 debug level (0-2)");
-
 static unsigned int check_lost = 1;
 module_param(check_lost, bool, 0);
 MODULE_PARM_DESC(check_lost, "If set then check for unplugged de600");
@@ -180,20 +168,20 @@
 	if (free_tx_pages <= 0) {	/* Do timeouts, to avoid hangs. */
 		tickssofar = jiffies - dev->trans_start;
 		if (tickssofar < 5)
-			return 1;
+			return NETDEV_TX_BUSY;
 		/* else */
 		printk(KERN_WARNING "%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem");
 		/* Restart the adapter. */
 		spin_lock_irqsave(&de600_lock, flags);
 		if (adapter_init(dev)) {
 			spin_unlock_irqrestore(&de600_lock, flags);
-			return 1;
+			return NETDEV_TX_BUSY;
 		}
 		spin_unlock_irqrestore(&de600_lock, flags);
 	}
 
 	/* Start real output */
-	PRINTK(("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages));
+	pr_debug("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages);
 
 	if ((len = skb->len) < RUNT)
 		len = RUNT;
@@ -211,7 +199,7 @@
 		if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) {
 			if (adapter_init(dev)) {
 				spin_unlock_irqrestore(&de600_lock, flags);
-				return 1;
+				return NETDEV_TX_BUSY;
 			}
 		}
 	}
@@ -259,7 +247,7 @@
 	irq_status = de600_read_status(dev);
 
 	do {
-		PRINTK(("de600_interrupt (%02X)\n", irq_status));
+		pr_debug("de600_interrupt (%02X)\n", irq_status);
 
 		if (irq_status & RX_GOOD)
 			de600_rx_intr(dev);
@@ -407,8 +395,7 @@
 
 	printk(KERN_INFO "%s: D-Link DE-600 pocket adapter", dev->name);
 	/* Alpha testers must have the version number to report bugs. */
-	if (de600_debug > 1)
-		printk(version);
+	pr_debug("%s", version);
 
 	/* probe for adapter */
 	err = -ENODEV;
diff -druN linux-libre-2.6.30-gnu/drivers/net/de620.c linux-libre-2.6.31-gnu/drivers/net/de620.c
--- linux-libre-2.6.30-gnu/drivers/net/de620.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/de620.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,6 @@
  * Compile-time options: (see below for descriptions)
  * -DDE620_IO=0x378	(lpt1)
  * -DDE620_IRQ=7	(lpt1)
- * -DDE602_DEBUG=...
  * -DSHUTDOWN_WHEN_LOST
  * -DCOUNT_LOOPS
  * -DLOWSPEED
@@ -98,15 +97,6 @@
 #define SHUTDOWN_WHEN_LOST
  */
 
-/*
- * Enable debugging by "-DDE620_DEBUG=3" when compiling,
- * OR by enabling the following #define
- *
- * use 0 for production, 1 for verification, >2 for debug
- *
-#define DE620_DEBUG 3
- */
-
 #ifdef LOWSPEED
 /*
  * Enable this #define if you want to see debugging output that show how long
@@ -160,14 +150,6 @@
 #define RUNT 60		/* Too small Ethernet packet */
 #define GIANT 1514	/* largest legal size packet, no fcs */
 
-#ifdef DE620_DEBUG /* Compile-time configurable */
-#define PRINTK(x) if (de620_debug >= 2) printk x
-#else
-#define DE620_DEBUG 0
-#define PRINTK(x) /**/
-#endif
-
-
 /*
  * Force media with insmod:
  *	insmod de620.o bnc=1
@@ -186,8 +168,6 @@
 static int irq = DE620_IRQ;
 static int clone = DE620_CLONE;
 
-static unsigned int de620_debug = DE620_DEBUG;
-
 static spinlock_t de620_lock;
 
 module_param(bnc, int, 0);
@@ -195,13 +175,11 @@
 module_param(io, int, 0);
 module_param(irq, int, 0);
 module_param(clone, int, 0);
-module_param(de620_debug, int, 0);
 MODULE_PARM_DESC(bnc, "DE-620 set BNC medium (0-1)");
 MODULE_PARM_DESC(utp, "DE-620 set UTP medium (0-1)");
 MODULE_PARM_DESC(io, "DE-620 I/O base address,required");
 MODULE_PARM_DESC(irq, "DE-620 IRQ number,required");
 MODULE_PARM_DESC(clone, "Check also for non-D-Link DE-620 clones (0-1)");
-MODULE_PARM_DESC(de620_debug, "DE-620 debug level (0-2)");
 
 /***********************************************
  *                                             *
@@ -533,9 +511,9 @@
 
 	/* Start real output */
 
-	spin_lock_irqsave(&de620_lock, flags)
-	PRINTK(("de620_start_xmit: len=%d, bufs 0x%02x\n",
-		(int)skb->len, using_txbuf));
+	spin_lock_irqsave(&de620_lock, flags);
+	pr_debug("de620_start_xmit: len=%d, bufs 0x%02x\n",
+		(int)skb->len, using_txbuf);
 
 	/* select a free tx buffer. if there is one... */
 	switch (using_txbuf) {
@@ -553,7 +531,7 @@
 	case (TXBF0 | TXBF1): /* NONE!!! */
 		printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name);
 		spin_unlock_irqrestore(&de620_lock, flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	de620_write_block(dev, buffer, skb->len, len-skb->len);
 
@@ -585,12 +563,12 @@
 	/* Read the status register (_not_ the status port) */
 	irq_status = de620_get_register(dev, R_STS);
 
-	PRINTK(("de620_interrupt (%2.2X)\n", irq_status));
+	pr_debug("de620_interrupt (%2.2X)\n", irq_status);
 
 	if (irq_status & RXGOOD) {
 		do {
 			again = de620_rx_intr(dev);
-			PRINTK(("again=%d\n", again));
+			pr_debug("again=%d\n", again);
 		}
 		while (again && (++bogus_count < 100));
 	}
@@ -622,7 +600,7 @@
 	byte pagelink;
 	byte curr_page;
 
-	PRINTK(("de620_rx_intr: next_rx_page = %d\n", next_rx_page));
+	pr_debug("de620_rx_intr: next_rx_page = %d\n", next_rx_page);
 
 	/* Tell the adapter that we are going to read data, and from where */
 	de620_send_command(dev, W_CR | RRN);
@@ -631,8 +609,9 @@
 
 	/* Deep breath, and away we goooooo */
 	de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf));
-	PRINTK(("page status=0x%02x, nextpage=%d, packetsize=%d\n",
-	header_buf.status, header_buf.Rx_NextPage, header_buf.Rx_ByteCount));
+	pr_debug("page status=0x%02x, nextpage=%d, packetsize=%d\n",
+		header_buf.status, header_buf.Rx_NextPage,
+		header_buf.Rx_ByteCount);
 
 	/* Plausible page header? */
 	pagelink = header_buf.Rx_NextPage;
@@ -683,7 +662,7 @@
 			buffer = skb_put(skb,size);
 			/* copy the packet into the buffer */
 			de620_read_block(dev, buffer, size);
-			PRINTK(("Read %d bytes\n", size));
+			pr_debug("Read %d bytes\n", size);
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb); /* deliver it "upstairs" */
 			/* count all receives */
@@ -696,7 +675,7 @@
 	/* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */
 	curr_page = de620_get_register(dev, R_CPR);
 	de620_set_register(dev, W_NPRF, next_rx_page);
-	PRINTK(("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page));
+	pr_debug("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page);
 
 	return (next_rx_page != curr_page); /* That was slightly tricky... */
 }
@@ -830,8 +809,7 @@
 		netdev_boot_setup_check(dev);
 	}
 
-	if (de620_debug)
-		printk(version);
+	pr_debug("%s", version);
 
 	printk(KERN_INFO "D-Link DE-620 pocket adapter");
 
@@ -878,14 +856,13 @@
 	/* base_addr and irq are already set, see above! */
 
 	/* dump eeprom */
-	if (de620_debug) {
-		printk("\nEEPROM contents:\n");
-		printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size);
-		printk("NodeID = %pM\n", nic_data.NodeID);
-		printk("Model = %d\n", nic_data.Model);
-		printk("Media = %d\n", nic_data.Media);
-		printk("SCR = 0x%02x\n", nic_data.SCR);
-	}
+	pr_debug("\nEEPROM contents:\n"
+		"RAM_Size = 0x%02X\n"
+		"NodeID = %pM\n"
+		"Model = %d\n"
+		"Media = %d\n"
+		"SCR = 0x%02x\n", nic_data.RAM_Size, nic_data.NodeID,
+		nic_data.Model, nic_data.Media, nic_data.SCR);
 
 	err = register_netdev(dev);
 	if (err)
diff -druN linux-libre-2.6.30-gnu/drivers/net/declance.c linux-libre-2.6.31-gnu/drivers/net/declance.c
--- linux-libre-2.6.30-gnu/drivers/net/declance.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/declance.c	2009-09-09 18:13:59.000000000 -0400
@@ -895,6 +895,7 @@
 	struct lance_private *lp = netdev_priv(dev);
 	volatile struct lance_regs *ll = lp->ll;
 	volatile u16 *ib = (volatile u16 *)dev->mem_start;
+	unsigned long flags;
 	int entry, len;
 
 	len = skb->len;
@@ -907,6 +908,8 @@
 
 	dev->stats.tx_bytes += len;
 
+	spin_lock_irqsave(&lp->lock, flags);
+
 	entry = lp->tx_new;
 	*lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len);
 	*lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0;
@@ -925,6 +928,8 @@
 	/* Kick the lance: transmit now */
 	writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
 
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/defxx.c linux-libre-2.6.31-gnu/drivers/net/defxx.c
--- linux-libre-2.6.30-gnu/drivers/net/defxx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/defxx.c	2009-09-09 18:13:59.000000000 -0400
@@ -3318,7 +3318,7 @@
 	{
 		skb_pull(skb,3);
 		spin_unlock_irqrestore(&bp->lock, flags);
-		return(1);			/* requeue packet for later */
+		return NETDEV_TX_BUSY;	/* requeue packet for later */
 	}
 
 	/*
diff -druN linux-libre-2.6.30-gnu/drivers/net/depca.c linux-libre-2.6.31-gnu/drivers/net/depca.c
--- linux-libre-2.6.30-gnu/drivers/net/depca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/depca.c	2009-09-09 18:13:59.000000000 -0400
@@ -810,7 +810,7 @@
 
 	dev->mem_start = 0;
 
-	device->driver_data = dev;
+	dev_set_drvdata(device, dev);
 	SET_NETDEV_DEV (dev, device);
 
 	status = register_netdev(dev);
@@ -957,7 +957,7 @@
 		if (TX_BUFFS_AVAIL)
 			netif_start_queue(dev);
 	} else
-		status = -1;
+		status = NETDEV_TX_LOCKED;
 
       out:
 	return status;
@@ -1614,7 +1614,7 @@
 	struct depca_private *lp;
 	int bus;
 
-	dev  = device->driver_data;
+	dev  = dev_get_drvdata(device);
 	lp   = netdev_priv(dev);
 
 	unregister_netdev (dev);
@@ -1839,7 +1839,7 @@
 
 		lp->tx_new = (++end) & lp->txRingMask;	/* update current pointers */
 	} else {
-		status = -1;
+		status = NETDEV_TX_LOCKED;
 	}
 
 	return status;
diff -druN linux-libre-2.6.30-gnu/drivers/net/dl2k.c linux-libre-2.6.31-gnu/drivers/net/dl2k.c
--- linux-libre-2.6.30-gnu/drivers/net/dl2k.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/dl2k.c	2009-09-09 18:13:59.000000000 -0400
@@ -268,8 +268,9 @@
 		printk(KERN_INFO "tx_coalesce:\t%d packets\n",
 				tx_coalesce);
 	if (np->coalesce)
-		printk(KERN_INFO "rx_coalesce:\t%d packets\n"
-		       KERN_INFO "rx_timeout: \t%d ns\n",
+		printk(KERN_INFO
+		       "rx_coalesce:\t%d packets\n"
+		       "rx_timeout: \t%d ns\n",
 				np->rx_coalesce, np->rx_timeout*640);
 	if (np->vlan)
 		printk(KERN_INFO "vlan(id):\t%d\n", np->vlan);
@@ -539,7 +540,7 @@
 		dev->name, readl (ioaddr + TxStatus));
 	rio_free_tx(dev, 0);
 	dev->if_port = 0;
-	dev->trans_start = jiffies;
+	dev->trans_start = jiffies; /* prevent tx timeout */
 }
 
  /* allocate and initialize Tx and Rx descriptors */
@@ -610,7 +611,7 @@
 
 	if (np->link_status == 0) {	/* Link Down */
 		dev_kfree_skb(skb);
-		return 0;
+		return NETDEV_TX_OK;
 	}
 	ioaddr = dev->base_addr;
 	entry = np->cur_tx % TX_RING_SIZE;
@@ -665,9 +666,7 @@
 		writel (0, dev->base_addr + TFDListPtr1);
 	}
 
-	/* NETDEV WATCHDOG timer */
-	dev->trans_start = jiffies;
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 static irqreturn_t
@@ -1524,9 +1523,9 @@
 			printk (KERN_INFO "Operating at 10 Mbps, ");
 		}
 		if (bmcr & MII_BMCR_DUPLEX_MODE) {
-			printk ("Full duplex\n");
+			printk (KERN_CONT "Full duplex\n");
 		} else {
-			printk ("Half duplex\n");
+			printk (KERN_CONT "Half duplex\n");
 		}
 	}
 	if (np->tx_flow)
@@ -1616,9 +1615,9 @@
 		}
 		if (np->full_duplex) {
 			bmcr |= MII_BMCR_DUPLEX_MODE;
-			printk ("Full duplex\n");
+			printk (KERN_CONT "Full duplex\n");
 		} else {
-			printk ("Half duplex\n");
+			printk (KERN_CONT "Half duplex\n");
 		}
 #if 0
 		/* Set 1000BaseT Master/Slave setting */
@@ -1671,9 +1670,9 @@
 		__u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR);
 		printk (KERN_INFO "Operating at 1000 Mbps, ");
 		if (bmcr & MII_BMCR_DUPLEX_MODE) {
-			printk ("Full duplex\n");
+			printk (KERN_CONT "Full duplex\n");
 		} else {
-			printk ("Half duplex\n");
+			printk (KERN_CONT "Half duplex\n");
 		}
 	}
 	if (np->tx_flow)
diff -druN linux-libre-2.6.30-gnu/drivers/net/dm9000.c linux-libre-2.6.31-gnu/drivers/net/dm9000.c
--- linux-libre-2.6.30-gnu/drivers/net/dm9000.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/dm9000.c	2009-09-09 18:13:59.000000000 -0400
@@ -756,7 +756,7 @@
 	dm9000_dbg(db, 3, "%s:\n", __func__);
 
 	if (db->tx_pkt_cnt > 1)
-		return 1;
+		return NETDEV_TX_BUSY;
 
 	spin_lock_irqsave(&db->lock, flags);
 
@@ -1170,6 +1170,21 @@
 	return 0;
 }
 
+static const struct net_device_ops dm9000_netdev_ops = {
+	.ndo_open		= dm9000_open,
+	.ndo_stop		= dm9000_stop,
+	.ndo_start_xmit		= dm9000_start_xmit,
+	.ndo_tx_timeout		= dm9000_timeout,
+	.ndo_set_multicast_list	= dm9000_hash_table,
+	.ndo_do_ioctl		= dm9000_ioctl,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= dm9000_poll_controller,
+#endif
+};
+
 #define res_size(_r) (((_r)->end - (_r)->start) + 1)
 
 /*
@@ -1339,18 +1354,9 @@
 	/* driver system function */
 	ether_setup(ndev);
 
-	ndev->open		 = &dm9000_open;
-	ndev->hard_start_xmit    = &dm9000_start_xmit;
-	ndev->tx_timeout         = &dm9000_timeout;
-	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
-	ndev->stop		 = &dm9000_stop;
-	ndev->set_multicast_list = &dm9000_hash_table;
-	ndev->ethtool_ops	 = &dm9000_ethtool_ops;
-	ndev->do_ioctl		 = &dm9000_ioctl;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	ndev->poll_controller	 = &dm9000_poll_controller;
-#endif
+	ndev->netdev_ops	= &dm9000_netdev_ops;
+	ndev->watchdog_timeo	= msecs_to_jiffies(watchdog);
+	ndev->ethtool_ops	= &dm9000_ethtool_ops;
 
 	db->msg_enable       = NETIF_MSG_LINK;
 	db->mii.phy_id_mask  = 0x1f;
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000/e1000_main.c linux-libre-2.6.31-gnu/drivers/net/e1000/e1000_main.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000/e1000_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000/e1000_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -498,6 +498,8 @@
 
 	e1000_irq_enable(adapter);
 
+	netif_wake_queue(adapter->netdev);
+
 	/* fire a link change interrupt to start the watchdog */
 	ew32(ICS, E1000_ICS_LSC);
 	return 0;
@@ -1234,15 +1236,14 @@
 	    !e1000_check_mng_mode(hw))
 		e1000_get_hw_control(adapter);
 
-	/* tell the stack to leave us alone until e1000_open() is called */
-	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-
 	strcpy(netdev->name, "eth%d");
 	err = register_netdev(netdev);
 	if (err)
 		goto err_register;
 
+	/* carrier off reporting is important to ethtool even BEFORE open */
+	netif_carrier_off(netdev);
+
 	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
 
 	cards_found++;
@@ -1441,6 +1442,8 @@
 	if (test_bit(__E1000_TESTING, &adapter->flags))
 		return -EBUSY;
 
+	netif_carrier_off(netdev);
+
 	/* allocate transmit descriptors */
 	err = e1000_setup_all_tx_resources(adapter);
 	if (err)
@@ -2182,12 +2185,16 @@
 	/* Free all the Rx ring sk_buffs */
 	for (i = 0; i < rx_ring->count; i++) {
 		buffer_info = &rx_ring->buffer_info[i];
-		if (buffer_info->skb) {
+		if (buffer_info->dma) {
 			pci_unmap_single(pdev,
 					 buffer_info->dma,
 					 buffer_info->length,
 					 PCI_DMA_FROMDEVICE);
+		}
 
+		buffer_info->dma = 0;
+
+		if (buffer_info->skb) {
 			dev_kfree_skb(buffer_info->skb);
 			buffer_info->skb = NULL;
 		}
@@ -2327,7 +2334,8 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	struct dev_addr_list *uc_ptr;
+	struct netdev_hw_addr *ha;
+	bool use_uc = false;
 	struct dev_addr_list *mc_ptr;
 	u32 rctl;
 	u32 hash_value;
@@ -2366,12 +2374,11 @@
 			rctl |= E1000_RCTL_VFE;
 	}
 
-	uc_ptr = NULL;
-	if (netdev->uc_count > rar_entries - 1) {
+	if (netdev->uc.count > rar_entries - 1) {
 		rctl |= E1000_RCTL_UPE;
 	} else if (!(netdev->flags & IFF_PROMISC)) {
 		rctl &= ~E1000_RCTL_UPE;
-		uc_ptr = netdev->uc_list;
+		use_uc = true;
 	}
 
 	ew32(RCTL, rctl);
@@ -2389,13 +2396,20 @@
 	 * if there are not 14 addresses, go ahead and clear the filters
 	 * -- with 82571 controllers only 0-13 entries are filled here
 	 */
+	i = 1;
+	if (use_uc)
+		list_for_each_entry(ha, &netdev->uc.list, list) {
+			if (i == rar_entries)
+				break;
+			e1000_rar_set(hw, ha->addr, i++);
+		}
+
+	WARN_ON(i == rar_entries);
+
 	mc_ptr = netdev->mc_list;
 
-	for (i = 1; i < rar_entries; i++) {
-		if (uc_ptr) {
-			e1000_rar_set(hw, uc_ptr->da_addr, i);
-			uc_ptr = uc_ptr->next;
-		} else if (mc_ptr) {
+	for (; i < rar_entries; i++) {
+		if (mc_ptr) {
 			e1000_rar_set(hw, mc_ptr->da_addr, i);
 			mc_ptr = mc_ptr->next;
 		} else {
@@ -2405,7 +2419,6 @@
 			E1000_WRITE_FLUSH();
 		}
 	}
-	WARN_ON(uc_ptr != NULL);
 
 	/* load any remaining addresses into the hash table */
 
@@ -2590,7 +2603,6 @@
 			ew32(TCTL, tctl);
 
 			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
 			mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ));
 			adapter->smartspeed = 0;
 		} else {
@@ -2607,7 +2619,6 @@
 			printk(KERN_INFO "e1000: %s NIC Link is Down\n",
 			       netdev->name);
 			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
 			mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ));
 
 			/* 80003ES2LAN workaround--
@@ -2645,6 +2656,8 @@
 			 * (Do the reset outside of interrupt context). */
 			adapter->tx_timeout_count++;
 			schedule_work(&adapter->reset_task);
+			/* return immediately since reset is imminent */
+			return;
 		}
 	}
 
@@ -2989,7 +3002,7 @@
 			size -= 4;
 
 		buffer_info->length = size;
-		buffer_info->dma = map[0] + offset;
+		buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
 		buffer_info->time_stamp = jiffies;
 		buffer_info->next_to_watch = i;
 
@@ -3030,7 +3043,7 @@
 				size -= 4;
 
 			buffer_info->length = size;
-			buffer_info->dma = map[f + 1] + offset;
+			buffer_info->dma = map[f] + offset;
 			buffer_info->time_stamp = jiffies;
 			buffer_info->next_to_watch = i;
 
@@ -3362,7 +3375,6 @@
 
 	if (count) {
 		e1000_tx_queue(adapter, tx_ring, tx_flags, count);
-		netdev->trans_start = jiffies;
 		/* Make sure there is space in the ring for the next send. */
 		e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
 
@@ -4025,6 +4037,7 @@
 		                 buffer_info->dma,
 		                 buffer_info->length,
 		                 PCI_DMA_FROMDEVICE);
+		buffer_info->dma = 0;
 
 		length = le16_to_cpu(rx_desc->length);
 		/* !EOP means multiple descriptors were used to store a single
@@ -4214,6 +4227,7 @@
 			pci_unmap_single(pdev, buffer_info->dma,
 					 adapter->rx_buffer_len,
 					 PCI_DMA_FROMDEVICE);
+			buffer_info->dma = 0;
 
 			break; /* while !buffer_info->skb */
 		}
@@ -4809,6 +4823,9 @@
 
 	netif_device_detach(netdev);
 
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
 	if (netif_running(netdev))
 		e1000_down(adapter);
 	pci_disable_device(pdev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/82571.c linux-libre-2.6.31-gnu/drivers/net/e1000e/82571.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/82571.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/82571.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,6 +71,7 @@
 static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
 static s32 e1000_led_on_82574(struct e1000_hw *hw);
+static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
 
 /**
  *  e1000_init_phy_params_82571 - Init PHY func ptrs.
@@ -212,6 +213,9 @@
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_mac_info *mac = &hw->mac;
 	struct e1000_mac_operations *func = &mac->ops;
+	u32 swsm = 0;
+	u32 swsm2 = 0;
+	bool force_clear_smbi = false;
 
 	/* Set media type */
 	switch (adapter->pdev->device) {
@@ -276,6 +280,50 @@
 		break;
 	}
 
+	/*
+	 * Ensure that the inter-port SWSM.SMBI lock bit is clear before
+	 * first NVM or PHY acess. This should be done for single-port
+	 * devices, and for one port only on dual-port devices so that
+	 * for those devices we can still use the SMBI lock to synchronize
+	 * inter-port accesses to the PHY & NVM.
+	 */
+	switch (hw->mac.type) {
+	case e1000_82571:
+	case e1000_82572:
+		swsm2 = er32(SWSM2);
+
+		if (!(swsm2 & E1000_SWSM2_LOCK)) {
+			/* Only do this for the first interface on this card */
+			ew32(SWSM2,
+			    swsm2 | E1000_SWSM2_LOCK);
+			force_clear_smbi = true;
+		} else
+			force_clear_smbi = false;
+		break;
+	default:
+		force_clear_smbi = true;
+		break;
+	}
+
+	if (force_clear_smbi) {
+		/* Make sure SWSM.SMBI is clear */
+		swsm = er32(SWSM);
+		if (swsm & E1000_SWSM_SMBI) {
+			/* This bit should not be set on a first interface, and
+			 * indicates that the bootagent or EFI code has
+			 * improperly left this bit enabled
+			 */
+			hw_dbg(hw, "Please update your 82571 Bootagent\n");
+		}
+		ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
+	}
+
+	/*
+	 * Initialze device specific counter of SMBI acquisition
+	 * timeouts.
+	 */
+	 hw->dev_spec.e82571.smb_counter = 0;
+
 	return 0;
 }
 
@@ -341,8 +389,10 @@
 			if (e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1,
 				       &eeprom_data) < 0)
 				break;
-			if (eeprom_data & NVM_WORD1A_ASPM_MASK)
-				adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES;
+			if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) {
+				adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
+				adapter->max_hw_frame_size = DEFAULT_JUMBO;
+			}
 		}
 		break;
 	default:
@@ -411,11 +461,37 @@
 static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
 {
 	u32 swsm;
-	s32 timeout = hw->nvm.word_size + 1;
+	s32 sw_timeout = hw->nvm.word_size + 1;
+	s32 fw_timeout = hw->nvm.word_size + 1;
 	s32 i = 0;
 
+	/*
+	 * If we have timedout 3 times on trying to acquire
+	 * the inter-port SMBI semaphore, there is old code
+	 * operating on the other port, and it is not
+	 * releasing SMBI. Modify the number of times that
+	 * we try for the semaphore to interwork with this
+	 * older code.
+	 */
+	if (hw->dev_spec.e82571.smb_counter > 2)
+		sw_timeout = 1;
+
+	/* Get the SW semaphore */
+	while (i < sw_timeout) {
+		swsm = er32(SWSM);
+		if (!(swsm & E1000_SWSM_SMBI))
+			break;
+
+		udelay(50);
+		i++;
+	}
+
+	if (i == sw_timeout) {
+		hw_dbg(hw, "Driver can't access device - SMBI bit is set.\n");
+		hw->dev_spec.e82571.smb_counter++;
+	}
 	/* Get the FW semaphore. */
-	for (i = 0; i < timeout; i++) {
+	for (i = 0; i < fw_timeout; i++) {
 		swsm = er32(SWSM);
 		ew32(SWSM, swsm | E1000_SWSM_SWESMBI);
 
@@ -426,9 +502,9 @@
 		udelay(50);
 	}
 
-	if (i == timeout) {
+	if (i == fw_timeout) {
 		/* Release semaphores */
-		e1000e_put_hw_semaphore(hw);
+		e1000_put_hw_semaphore_82571(hw);
 		hw_dbg(hw, "Driver can't access the NVM\n");
 		return -E1000_ERR_NVM;
 	}
@@ -447,9 +523,7 @@
 	u32 swsm;
 
 	swsm = er32(SWSM);
-
-	swsm &= ~E1000_SWSM_SWESMBI;
-
+	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
 	ew32(SWSM, swsm);
 }
 
@@ -1585,6 +1659,7 @@
 static struct e1000_mac_operations e82571_mac_ops = {
 	/* .check_mng_mode: mac type dependent */
 	/* .check_for_link: media type dependent */
+	.id_led_init		= e1000e_id_led_init,
 	.cleanup_led		= e1000e_cleanup_led_generic,
 	.clear_hw_cntrs		= e1000_clear_hw_cntrs_82571,
 	.get_bus_info		= e1000e_get_bus_info_pcie,
@@ -1596,6 +1671,7 @@
 	.init_hw		= e1000_init_hw_82571,
 	.setup_link		= e1000_setup_link_82571,
 	/* .setup_physical_interface: media type dependent */
+	.setup_led		= e1000e_setup_led_generic,
 };
 
 static struct e1000_phy_operations e82_phy_ops_igp = {
@@ -1672,6 +1748,7 @@
 				  | FLAG_TARC_SPEED_MODE_BIT /* errata */
 				  | FLAG_APME_CHECK_PORT_B,
 	.pba			= 38,
+	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
 	.phy_ops		= &e82_phy_ops_igp,
@@ -1688,6 +1765,7 @@
 				  | FLAG_HAS_CTRLEXT_ON_LOAD
 				  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
 	.pba			= 38,
+	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
 	.phy_ops		= &e82_phy_ops_igp,
@@ -1706,6 +1784,7 @@
 				  | FLAG_HAS_ERT
 				  | FLAG_HAS_SWSM_ON_LOAD,
 	.pba			= 20,
+	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
 	.phy_ops		= &e82_phy_ops_m88,
@@ -1724,6 +1803,7 @@
 				  | FLAG_HAS_AMT
 				  | FLAG_HAS_CTRLEXT_ON_LOAD,
 	.pba			= 20,
+	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
 	.phy_ops		= &e82_phy_ops_bm,
@@ -1740,6 +1820,7 @@
 				  | FLAG_HAS_AMT
 				  | FLAG_HAS_CTRLEXT_ON_LOAD,
 	.pba			= 20,
+	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_82571,
 	.mac_ops		= &e82571_mac_ops,
 	.phy_ops		= &e82_phy_ops_bm,
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/defines.h linux-libre-2.6.31-gnu/drivers/net/e1000e/defines.h
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/defines.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/defines.h	2009-09-09 18:13:59.000000000 -0400
@@ -56,6 +56,7 @@
 /* Wake Up Control */
 #define E1000_WUC_APME       0x00000001 /* APM Enable */
 #define E1000_WUC_PME_EN     0x00000002 /* PME Enable */
+#define E1000_WUC_PHY_WAKE   0x00000100 /* if PHY supports wakeup */
 
 /* Wake Up Filter Control */
 #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
@@ -65,6 +66,13 @@
 #define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
 #define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
 
+/* Wake Up Status */
+#define E1000_WUS_LNKC         E1000_WUFC_LNKC
+#define E1000_WUS_MAG          E1000_WUFC_MAG
+#define E1000_WUS_EX           E1000_WUFC_EX
+#define E1000_WUS_MC           E1000_WUFC_MC
+#define E1000_WUS_BC           E1000_WUFC_BC
+
 /* Extended Device Control */
 #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
 #define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
@@ -77,6 +85,7 @@
 #define E1000_CTRL_EXT_IAME           0x08000000 /* Interrupt acknowledge Auto-mask */
 #define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000 /* Clear Interrupt timers after IMS clear */
 #define E1000_CTRL_EXT_PBA_CLR        0x80000000 /* PBA Clear */
+#define E1000_CTRL_EXT_PHYPDEN        0x00100000
 
 /* Receive Descriptor bit definitions */
 #define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
@@ -140,6 +149,7 @@
 #define E1000_RCTL_DTYP_PS        0x00000400    /* Packet Split descriptor */
 #define E1000_RCTL_RDMTS_HALF     0x00000000    /* Rx desc min threshold size */
 #define E1000_RCTL_MO_SHIFT       12            /* multicast offset shift */
+#define E1000_RCTL_MO_3           0x00003000    /* multicast offset 15:4 */
 #define E1000_RCTL_BAM            0x00008000    /* broadcast enable */
 /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
 #define E1000_RCTL_SZ_2048        0x00000000    /* Rx buffer size 2048 */
@@ -153,6 +163,7 @@
 #define E1000_RCTL_VFE            0x00040000    /* vlan filter enable */
 #define E1000_RCTL_CFIEN          0x00080000    /* canonical form enable */
 #define E1000_RCTL_CFI            0x00100000    /* canonical form indicator */
+#define E1000_RCTL_PMCF           0x00800000    /* pass MAC control frames */
 #define E1000_RCTL_BSEX           0x02000000    /* Buffer size extension */
 #define E1000_RCTL_SECRC          0x04000000    /* Strip Ethernet CRC */
 
@@ -227,6 +238,7 @@
 #define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
 #define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
 #define E1000_STATUS_LAN_INIT_DONE 0x00000200   /* Lan Init Completion by NVM */
+#define E1000_STATUS_PHYRA      0x00000400      /* PHY Reset Asserted */
 #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
 
 /* Constants used to interpret the masked PCI-X bus speed. */
@@ -255,11 +267,16 @@
 #define AUTONEG_ADVERTISE_SPEED_DEFAULT   E1000_ALL_SPEED_DUPLEX
 
 /* LED Control */
+#define E1000_PHY_LED0_MODE_MASK          0x00000007
+#define E1000_PHY_LED0_IVRT               0x00000008
+#define E1000_PHY_LED0_MASK               0x0000001F
+
 #define E1000_LEDCTL_LED0_MODE_MASK       0x0000000F
 #define E1000_LEDCTL_LED0_MODE_SHIFT      0
 #define E1000_LEDCTL_LED0_IVRT            0x00000040
 #define E1000_LEDCTL_LED0_BLINK           0x00000080
 
+#define E1000_LEDCTL_MODE_LINK_UP       0x2
 #define E1000_LEDCTL_MODE_LED_ON        0xE
 #define E1000_LEDCTL_MODE_LED_OFF       0xF
 
@@ -360,6 +377,8 @@
 #define E1000_SWSM_SWESMBI      0x00000002 /* FW Semaphore bit */
 #define E1000_SWSM_DRV_LOAD     0x00000008 /* Driver Loaded Bit */
 
+#define E1000_SWSM2_LOCK        0x00000002 /* Secondary driver semaphore bit */
+
 /* Interrupt Cause Read */
 #define E1000_ICR_TXDW          0x00000001 /* Transmit desc written back */
 #define E1000_ICR_LSC           0x00000004 /* Link Status Change */
@@ -469,6 +488,8 @@
 #define AUTO_READ_DONE_TIMEOUT      10
 
 /* Flow Control */
+#define E1000_FCRTH_RTH  0x0000FFF8     /* Mask Bits[15:3] for RTH */
+#define E1000_FCRTL_RTL  0x0000FFF8     /* Mask Bits[15:3] for RTL */
 #define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */
 
 /* Transmit Configuration Word */
@@ -555,6 +576,8 @@
 #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
 #define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
 
+#define PHY_CONTROL_LB   0x4000 /* PHY Loopback bit */
+
 /* NVM Control */
 #define E1000_EECD_SK        0x00000001 /* NVM Clock */
 #define E1000_EECD_CS        0x00000002 /* NVM Chip Select */
@@ -674,6 +697,8 @@
 #define IFE_C_E_PHY_ID       0x02A80310
 #define BME1000_E_PHY_ID     0x01410CB0
 #define BME1000_E_PHY_ID_R2  0x01410CB1
+#define I82577_E_PHY_ID      0x01540050
+#define I82578_E_PHY_ID      0x004DD040
 
 /* M88E1000 Specific Registers */
 #define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
@@ -727,6 +752,9 @@
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK  0x0E00
 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X    0x0800
 
+#define I82578_EPSCR_DOWNSHIFT_ENABLE          0x0020
+#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK    0x001C
+
 /* BME1000 PHY Specific Control Register */
 #define BME1000_PSCR_ENABLE_DOWNSHIFT   0x0800 /* 1 = enable downshift */
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/e1000.h linux-libre-2.6.31-gnu/drivers/net/e1000e/e1000.h
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/e1000.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/e1000.h	2009-09-09 18:13:59.000000000 -0400
@@ -62,7 +62,7 @@
 	e_printk(KERN_NOTICE, adapter, format, ## arg)
 
 
-/* Interrupt modes, as used by the IntMode paramter */
+/* Interrupt modes, as used by the IntMode parameter */
 #define E1000E_INT_MODE_LEGACY		0
 #define E1000E_INT_MODE_MSI		1
 #define E1000E_INT_MODE_MSIX		2
@@ -96,6 +96,51 @@
 /* Number of packet split data buffers (not including the header buffer) */
 #define PS_PAGE_BUFFERS			(MAX_PS_BUFFERS - 1)
 
+#define DEFAULT_JUMBO			9234
+
+/* BM/HV Specific Registers */
+#define BM_PORT_CTRL_PAGE                 769
+
+#define PHY_UPPER_SHIFT                   21
+#define BM_PHY_REG(page, reg) \
+	(((reg) & MAX_PHY_REG_ADDRESS) |\
+	 (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\
+	 (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)))
+
+/* PHY Wakeup Registers and defines */
+#define BM_RCTL         PHY_REG(BM_WUC_PAGE, 0)
+#define BM_WUC          PHY_REG(BM_WUC_PAGE, 1)
+#define BM_WUFC         PHY_REG(BM_WUC_PAGE, 2)
+#define BM_WUS          PHY_REG(BM_WUC_PAGE, 3)
+#define BM_RAR_L(_i)    (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2)))
+#define BM_RAR_M(_i)    (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2)))
+#define BM_RAR_H(_i)    (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2)))
+#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2)))
+#define BM_MTA(_i)      (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1)))
+
+#define BM_RCTL_UPE           0x0001          /* Unicast Promiscuous Mode */
+#define BM_RCTL_MPE           0x0002          /* Multicast Promiscuous Mode */
+#define BM_RCTL_MO_SHIFT      3               /* Multicast Offset Shift */
+#define BM_RCTL_MO_MASK       (3 << 3)        /* Multicast Offset Mask */
+#define BM_RCTL_BAM           0x0020          /* Broadcast Accept Mode */
+#define BM_RCTL_PMCF          0x0040          /* Pass MAC Control Frames */
+#define BM_RCTL_RFCE          0x0080          /* Rx Flow Control Enable */
+
+#define HV_SCC_UPPER		PHY_REG(778, 16) /* Single Collision Count */
+#define HV_SCC_LOWER		PHY_REG(778, 17)
+#define HV_ECOL_UPPER		PHY_REG(778, 18) /* Excessive Collision Count */
+#define HV_ECOL_LOWER		PHY_REG(778, 19)
+#define HV_MCC_UPPER		PHY_REG(778, 20) /* Multiple Collision Count */
+#define HV_MCC_LOWER		PHY_REG(778, 21)
+#define HV_LATECOL_UPPER	PHY_REG(778, 23) /* Late Collision Count */
+#define HV_LATECOL_LOWER	PHY_REG(778, 24)
+#define HV_COLC_UPPER		PHY_REG(778, 25) /* Collision Count */
+#define HV_COLC_LOWER		PHY_REG(778, 26)
+#define HV_DC_UPPER		PHY_REG(778, 27) /* Defer Count */
+#define HV_DC_LOWER		PHY_REG(778, 28)
+#define HV_TNCRS_UPPER		PHY_REG(778, 29) /* Transmit with no CRS */
+#define HV_TNCRS_LOWER		PHY_REG(778, 30)
+
 enum e1000_boards {
 	board_82571,
 	board_82572,
@@ -106,6 +151,7 @@
 	board_ich8lan,
 	board_ich9lan,
 	board_ich10lan,
+	board_pchlan,
 };
 
 struct e1000_queue_stats {
@@ -293,6 +339,7 @@
 	u32 eeprom_wol;
 	u32 wol;
 	u32 pba;
+	u32 max_hw_frame_size;
 
 	bool fc_autoneg;
 
@@ -302,6 +349,7 @@
 	unsigned int flags2;
 	struct work_struct downshift_task;
 	struct work_struct update_phy_task;
+	struct work_struct led_blink_task;
 };
 
 struct e1000_info {
@@ -309,6 +357,7 @@
 	unsigned int		flags;
 	unsigned int            flags2;
 	u32			pba;
+	u32			max_hw_frame_size;
 	s32			(*get_variants)(struct e1000_adapter *);
 	struct e1000_mac_operations *mac_ops;
 	struct e1000_phy_operations *phy_ops;
@@ -351,6 +400,7 @@
 
 /* CRC Stripping defines */
 #define FLAG2_CRC_STRIPPING               (1 << 0)
+#define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
 
 #define E1000_RX_DESC_PS(R, i)	    \
 	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
@@ -404,6 +454,7 @@
 extern struct e1000_info e1000_ich8_info;
 extern struct e1000_info e1000_ich9_info;
 extern struct e1000_info e1000_ich10_info;
+extern struct e1000_info e1000_pch_info;
 extern struct e1000_info e1000_es2_info;
 
 extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
@@ -425,6 +476,7 @@
 extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
 extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
 extern s32 e1000e_check_for_serdes_link(struct e1000_hw *hw);
+extern s32 e1000e_setup_led_generic(struct e1000_hw *hw);
 extern s32 e1000e_cleanup_led_generic(struct e1000_hw *hw);
 extern s32 e1000e_led_on_generic(struct e1000_hw *hw);
 extern s32 e1000e_led_off_generic(struct e1000_hw *hw);
@@ -493,6 +545,15 @@
 extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 extern s32 e1000e_check_downshift(struct e1000_hw *hw);
+extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow);
+extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
+extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
+extern s32 e1000_check_polarity_82577(struct e1000_hw *hw);
+extern s32 e1000_get_phy_info_82577(struct e1000_hw *hw);
+extern s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw);
+extern s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
 
 static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/es2lan.c linux-libre-2.6.31-gnu/drivers/net/e1000e/es2lan.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/es2lan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/es2lan.c	2009-09-09 18:13:59.000000000 -0400
@@ -1366,6 +1366,7 @@
 }
 
 static struct e1000_mac_operations es2_mac_ops = {
+	.id_led_init		= e1000e_id_led_init,
 	.check_mng_mode		= e1000e_check_mng_mode_generic,
 	/* check_for_link dependent on media type */
 	.cleanup_led		= e1000e_cleanup_led_generic,
@@ -1379,6 +1380,7 @@
 	.init_hw		= e1000_init_hw_80003es2lan,
 	.setup_link		= e1000e_setup_link,
 	/* setup_physical_interface dependent on media type */
+	.setup_led		= e1000e_setup_led_generic,
 };
 
 static struct e1000_phy_operations es2_phy_ops = {
@@ -1422,6 +1424,7 @@
 				  | FLAG_DISABLE_FC_PAUSE_TIME /* errata */
 				  | FLAG_TIPG_MEDIUM_FOR_80003ESLAN,
 	.pba			= 38,
+	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_80003es2lan,
 	.mac_ops		= &es2_mac_ops,
 	.phy_ops		= &es2_phy_ops,
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/ethtool.c linux-libre-2.6.31-gnu/drivers/net/e1000e/ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -167,6 +167,15 @@
 
 	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
 			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+
+	/* MDI-X => 2; MDI =>1; Invalid =>0 */
+	if ((hw->phy.media_type == e1000_media_type_copper) &&
+	    !hw->mac.get_link_status)
+		ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
+		                                      ETH_TP_MDI;
+	else
+		ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
+
 	return 0;
 }
 
@@ -776,6 +785,7 @@
 	u32 after;
 	u32 i;
 	u32 toggle;
+	u32 mask;
 
 	/*
 	 * The status register is Read Only, so a write should fail.
@@ -788,17 +798,9 @@
 	case e1000_80003es2lan:
 		toggle = 0x7FFFF3FF;
 		break;
-	case e1000_82573:
-	case e1000_82574:
-	case e1000_82583:
-	case e1000_ich8lan:
-	case e1000_ich9lan:
-	case e1000_ich10lan:
+        default:
 		toggle = 0x7FFFF033;
 		break;
-	default:
-		toggle = 0xFFFFF833;
-		break;
 	}
 
 	before = er32(STATUS);
@@ -844,11 +846,18 @@
 		REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF);
 	REG_PATTERN_TEST(E1000_TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
 	REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);
+	mask = 0x8003FFFF;
+	switch (mac->type) {
+	case e1000_ich10lan:
+	case e1000_pchlan:
+		mask |= (1 << 18);
+		break;
+	default:
+		break;
+	}
 	for (i = 0; i < mac->rar_entry_count; i++)
 		REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),
-				       ((mac->type == e1000_ich10lan) ?
-					   0x8007FFFF : 0x8003FFFF),
-				       0xFFFFFFFF);
+		                       mask, 0xFFFFFFFF);
 
 	for (i = 0; i < mac->mta_reg_count; i++)
 		REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
@@ -1786,15 +1795,22 @@
 /* bit defines for adapter->led_status */
 #define E1000_LED_ON		0
 
-static void e1000_led_blink_callback(unsigned long data)
+static void e1000e_led_blink_task(struct work_struct *work)
 {
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	struct e1000_adapter *adapter = container_of(work,
+	                                struct e1000_adapter, led_blink_task);
 
 	if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
 		adapter->hw.mac.ops.led_off(&adapter->hw);
 	else
 		adapter->hw.mac.ops.led_on(&adapter->hw);
+}
 
+static void e1000_led_blink_callback(unsigned long data)
+{
+	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+
+	schedule_work(&adapter->led_blink_task);
 	mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
 }
 
@@ -1807,7 +1823,9 @@
 		data = INT_MAX;
 
 	if ((hw->phy.type == e1000_phy_ife) ||
+	    (hw->mac.type == e1000_pchlan) ||
 	    (hw->mac.type == e1000_82574)) {
+		INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task);
 		if (!adapter->blink_timer.function) {
 			init_timer(&adapter->blink_timer);
 			adapter->blink_timer.function =
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/hw.h linux-libre-2.6.31-gnu/drivers/net/e1000e/hw.h
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/hw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/hw.h	2009-09-09 18:13:59.000000000 -0400
@@ -193,7 +193,11 @@
 	E1000_RXCSUM   = 0x05000, /* Rx Checksum Control - RW */
 	E1000_RFCTL    = 0x05008, /* Receive Filter Control */
 	E1000_MTA      = 0x05200, /* Multicast Table Array - RW Array */
-	E1000_RA       = 0x05400, /* Receive Address - RW Array */
+	E1000_RAL_BASE = 0x05400, /* Receive Address Low - RW */
+#define E1000_RAL(_n)   (E1000_RAL_BASE + ((_n) * 8))
+#define E1000_RA        (E1000_RAL(0))
+	E1000_RAH_BASE = 0x05404, /* Receive Address High - RW */
+#define E1000_RAH(_n)   (E1000_RAH_BASE + ((_n) * 8))
 	E1000_VFTA     = 0x05600, /* VLAN Filter Table Array - RW Array */
 	E1000_WUC      = 0x05800, /* Wakeup Control - RW */
 	E1000_WUFC     = 0x05808, /* Wakeup Filter Control - RW */
@@ -210,6 +214,8 @@
 	E1000_FACTPS    = 0x05B30, /* Function Active and Power State to MNG */
 	E1000_SWSM      = 0x05B50, /* SW Semaphore */
 	E1000_FWSM      = 0x05B54, /* FW Semaphore */
+	E1000_SWSM2     = 0x05B58, /* Driver-only SW semaphore */
+	E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */
 	E1000_HICR      = 0x08F00, /* Host Interface Control */
 };
 
@@ -253,7 +259,7 @@
 #define IGP01E1000_PLHR_SS_DOWNGRADE	0x8000
 
 #define IGP01E1000_PSSR_POLARITY_REVERSED	0x0002
-#define IGP01E1000_PSSR_MDIX			0x0008
+#define IGP01E1000_PSSR_MDIX			0x0800
 #define IGP01E1000_PSSR_SPEED_MASK		0xC000
 #define IGP01E1000_PSSR_SPEED_1000MBPS		0xC000
 
@@ -297,6 +303,9 @@
 #define E1000_KMRNCTRLSTA_REN		0x00200000
 #define E1000_KMRNCTRLSTA_DIAG_OFFSET	0x3    /* Kumeran Diagnostic */
 #define E1000_KMRNCTRLSTA_DIAG_NELPBK	0x1000 /* Nearend Loopback mode */
+#define E1000_KMRNCTRLSTA_K1_CONFIG	0x7
+#define E1000_KMRNCTRLSTA_K1_ENABLE	0x140E
+#define E1000_KMRNCTRLSTA_K1_DISABLE	0x1400
 
 #define IFE_PHY_EXTENDED_STATUS_CONTROL	0x10
 #define IFE_PHY_SPECIAL_CONTROL		0x11 /* 100BaseTx PHY Special Control */
@@ -368,6 +377,10 @@
 #define E1000_DEV_ID_ICH10_R_BM_V		0x10CE
 #define E1000_DEV_ID_ICH10_D_BM_LM		0x10DE
 #define E1000_DEV_ID_ICH10_D_BM_LF		0x10DF
+#define E1000_DEV_ID_PCH_M_HV_LM		0x10EA
+#define E1000_DEV_ID_PCH_M_HV_LC		0x10EB
+#define E1000_DEV_ID_PCH_D_HV_DM		0x10EF
+#define E1000_DEV_ID_PCH_D_HV_DC		0x10F0
 
 #define E1000_REVISION_4 4
 
@@ -383,6 +396,7 @@
 	e1000_ich8lan,
 	e1000_ich9lan,
 	e1000_ich10lan,
+	e1000_pchlan,
 };
 
 enum e1000_media_type {
@@ -417,6 +431,8 @@
 	e1000_phy_igp_3,
 	e1000_phy_ife,
 	e1000_phy_bm,
+	e1000_phy_82578,
+	e1000_phy_82577,
 };
 
 enum e1000_bus_width {
@@ -720,6 +736,7 @@
 
 /* Function pointers and static data for the MAC. */
 struct e1000_mac_operations {
+	s32  (*id_led_init)(struct e1000_hw *);
 	bool (*check_mng_mode)(struct e1000_hw *);
 	s32  (*check_for_link)(struct e1000_hw *);
 	s32  (*cleanup_led)(struct e1000_hw *);
@@ -733,11 +750,13 @@
 	s32  (*init_hw)(struct e1000_hw *);
 	s32  (*setup_link)(struct e1000_hw *);
 	s32  (*setup_physical_interface)(struct e1000_hw *);
+	s32  (*setup_led)(struct e1000_hw *);
 };
 
 /* Function pointers for the PHY. */
 struct e1000_phy_operations {
 	s32  (*acquire_phy)(struct e1000_hw *);
+	s32  (*check_polarity)(struct e1000_hw *);
 	s32  (*check_reset_block)(struct e1000_hw *);
 	s32  (*commit_phy)(struct e1000_hw *);
 	s32  (*force_speed_duplex)(struct e1000_hw *);
@@ -869,6 +888,7 @@
 struct e1000_dev_spec_82571 {
 	bool laa_is_present;
 	bool alt_mac_addr_is_present;
+	u32 smb_counter;
 };
 
 struct e1000_shadow_ram {
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/ich8lan.c linux-libre-2.6.31-gnu/drivers/net/e1000e/ich8lan.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/ich8lan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/ich8lan.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,6 +48,10 @@
  * 82567LF-3 Gigabit Network Connection
  * 82567LM-3 Gigabit Network Connection
  * 82567LM-4 Gigabit Network Connection
+ * 82577LM Gigabit Network Connection
+ * 82577LC Gigabit Network Connection
+ * 82578DM Gigabit Network Connection
+ * 82578DC Gigabit Network Connection
  */
 
 #include <linux/netdevice.h>
@@ -116,6 +120,8 @@
 #define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300
 #define IGP3_VR_CTRL_MODE_SHUTDOWN	0x0200
 
+#define HV_LED_CONFIG		PHY_REG(768, 30) /* LED Configuration */
+
 /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
 /* Offset 04h HSFSTS */
 union ich8_hws_flash_status {
@@ -186,6 +192,14 @@
 static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
 static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
 static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
+static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
+static s32 e1000_led_on_ich8lan(struct e1000_hw *hw);
+static s32 e1000_led_off_ich8lan(struct e1000_hw *hw);
+static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw);
+static s32 e1000_setup_led_pchlan(struct e1000_hw *hw);
+static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
+static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
+static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
 
 static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
 {
@@ -213,6 +227,41 @@
 #define ew32flash(reg,val)	__ew32flash(hw, (reg), (val))
 
 /**
+ *  e1000_init_phy_params_pchlan - Initialize PHY function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  Initialize family-specific PHY parameters and function pointers.
+ **/
+static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val = 0;
+
+	phy->addr                     = 1;
+	phy->reset_delay_us           = 100;
+
+	phy->ops.check_polarity       = e1000_check_polarity_ife_ich8lan;
+	phy->ops.read_phy_reg         = e1000_read_phy_reg_hv;
+	phy->ops.write_phy_reg        = e1000_write_phy_reg_hv;
+	phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+	phy->id = e1000_phy_unknown;
+	e1000e_get_phy_id(hw);
+	phy->type = e1000e_get_phy_type_from_id(phy->id);
+
+	if (phy->type == e1000_phy_82577) {
+		phy->ops.check_polarity = e1000_check_polarity_82577;
+		phy->ops.force_speed_duplex =
+			e1000_phy_force_speed_duplex_82577;
+		phy->ops.get_cable_length   = e1000_get_cable_length_82577;
+		phy->ops.get_phy_info = e1000_get_phy_info_82577;
+		phy->ops.commit_phy = e1000e_phy_sw_reset;
+	}
+
+	return ret_val;
+}
+
+/**
  *  e1000_init_phy_params_ich8lan - Initialize PHY function pointers
  *  @hw: pointer to the HW structure
  *
@@ -273,6 +322,8 @@
 		break;
 	}
 
+	phy->ops.check_polarity = e1000_check_polarity_ife_ich8lan;
+
 	return 0;
 }
 
@@ -287,9 +338,7 @@
 {
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	u32 gfpreg;
-	u32 sector_base_addr;
-	u32 sector_end_addr;
+	u32 gfpreg, sector_base_addr, sector_end_addr;
 	u16 i;
 
 	/* Can't read flash registers if the register set isn't mapped. */
@@ -358,6 +407,36 @@
 	/* Set if manageability features are enabled. */
 	mac->arc_subsystem_valid = 1;
 
+	/* LED operations */
+	switch (mac->type) {
+	case e1000_ich8lan:
+	case e1000_ich9lan:
+	case e1000_ich10lan:
+		/* ID LED init */
+		mac->ops.id_led_init = e1000e_id_led_init;
+		/* setup LED */
+		mac->ops.setup_led = e1000e_setup_led_generic;
+		/* cleanup LED */
+		mac->ops.cleanup_led = e1000_cleanup_led_ich8lan;
+		/* turn on/off LED */
+		mac->ops.led_on = e1000_led_on_ich8lan;
+		mac->ops.led_off = e1000_led_off_ich8lan;
+		break;
+	case e1000_pchlan:
+		/* ID LED init */
+		mac->ops.id_led_init = e1000_id_led_init_pchlan;
+		/* setup LED */
+		mac->ops.setup_led = e1000_setup_led_pchlan;
+		/* cleanup LED */
+		mac->ops.cleanup_led = e1000_cleanup_led_pchlan;
+		/* turn on/off LED */
+		mac->ops.led_on = e1000_led_on_pchlan;
+		mac->ops.led_off = e1000_led_off_pchlan;
+		break;
+	default:
+		break;
+	}
+
 	/* Enable PCS Lock-loss workaround for ICH8 */
 	if (mac->type == e1000_ich8lan)
 		e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, 1);
@@ -365,6 +444,95 @@
 	return 0;
 }
 
+/**
+ *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks to see of the link status of the hardware has changed.  If a
+ *  change in link status has been detected, then we read the PHY registers
+ *  to get the current speed/duplex if link exists.
+ **/
+static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
+{
+	struct e1000_mac_info *mac = &hw->mac;
+	s32 ret_val;
+	bool link;
+
+	/*
+	 * We only want to go out to the PHY registers to see if Auto-Neg
+	 * has completed and/or if our link status has changed.  The
+	 * get_link_status flag is set upon receiving a Link Status
+	 * Change or Rx Sequence Error interrupt.
+	 */
+	if (!mac->get_link_status) {
+		ret_val = 0;
+		goto out;
+	}
+
+	if (hw->mac.type == e1000_pchlan) {
+		ret_val = e1000e_write_kmrn_reg(hw,
+		                                   E1000_KMRNCTRLSTA_K1_CONFIG,
+		                                   E1000_KMRNCTRLSTA_K1_ENABLE);
+		if (ret_val)
+			goto out;
+	}
+
+	/*
+	 * First we want to see if the MII Status Register reports
+	 * link.  If so, then we want to get the current speed/duplex
+	 * of the PHY.
+	 */
+	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+	if (ret_val)
+		goto out;
+
+	if (!link)
+		goto out; /* No link detected */
+
+	mac->get_link_status = false;
+
+	if (hw->phy.type == e1000_phy_82578) {
+		ret_val = e1000_link_stall_workaround_hv(hw);
+		if (ret_val)
+			goto out;
+	}
+
+	/*
+	 * Check if there was DownShift, must be checked
+	 * immediately after link-up
+	 */
+	e1000e_check_downshift(hw);
+
+	/*
+	 * If we are forcing speed/duplex, then we simply return since
+	 * we have already determined whether we have link or not.
+	 */
+	if (!mac->autoneg) {
+		ret_val = -E1000_ERR_CONFIG;
+		goto out;
+	}
+
+	/*
+	 * Auto-Neg is enabled.  Auto Speed Detection takes care
+	 * of MAC speed/duplex configuration.  So we only need to
+	 * configure Collision Distance in the MAC.
+	 */
+	e1000e_config_collision_dist(hw);
+
+	/*
+	 * Configure Flow Control now that Auto-Neg has completed.
+	 * First, we need to restore the desired flow control
+	 * settings because we may have had to re-autoneg with a
+	 * different link partner.
+	 */
+	ret_val = e1000e_config_fc_after_link_up(hw);
+	if (ret_val)
+		hw_dbg(hw, "Error configuring flow control\n");
+
+out:
+	return ret_val;
+}
+
 static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
@@ -378,10 +546,18 @@
 	if (rc)
 		return rc;
 
-	rc = e1000_init_phy_params_ich8lan(hw);
+	if (hw->mac.type == e1000_pchlan)
+		rc = e1000_init_phy_params_pchlan(hw);
+	else
+		rc = e1000_init_phy_params_ich8lan(hw);
 	if (rc)
 		return rc;
 
+	if (adapter->hw.phy.type == e1000_phy_ife) {
+		adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES;
+		adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;
+	}
+
 	if ((adapter->hw.mac.type == e1000_ich8lan) &&
 	    (adapter->hw.phy.type == e1000_phy_igp_3))
 		adapter->flags |= FLAG_LSC_GIG_SPEED_DROP;
@@ -401,8 +577,8 @@
  **/
 static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 {
-	u32 extcnf_ctrl;
-	u32 timeout = PHY_CFG_TIMEOUT;
+	u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT;
+	s32 ret_val = 0;
 
 	might_sleep();
 
@@ -410,25 +586,46 @@
 
 	while (timeout) {
 		extcnf_ctrl = er32(EXTCNF_CTRL);
-		extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
-		ew32(EXTCNF_CTRL, extcnf_ctrl);
+		if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG))
+			break;
+
+		mdelay(1);
+		timeout--;
+	}
+
+	if (!timeout) {
+		hw_dbg(hw, "SW/FW/HW has locked the resource for too long.\n");
+		ret_val = -E1000_ERR_CONFIG;
+		goto out;
+	}
+
+	timeout = PHY_CFG_TIMEOUT * 2;
 
+	extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
+	ew32(EXTCNF_CTRL, extcnf_ctrl);
+
+	while (timeout) {
 		extcnf_ctrl = er32(EXTCNF_CTRL);
 		if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
 			break;
+
 		mdelay(1);
 		timeout--;
 	}
 
 	if (!timeout) {
-		hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
+		hw_dbg(hw, "Failed to acquire the semaphore.\n");
 		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
 		ew32(EXTCNF_CTRL, extcnf_ctrl);
-		mutex_unlock(&nvm_mutex);
-		return -E1000_ERR_CONFIG;
+		ret_val = -E1000_ERR_CONFIG;
+		goto out;
 	}
 
-	return 0;
+out:
+	if (ret_val)
+		mutex_unlock(&nvm_mutex);
+
+	return ret_val;
 }
 
 /**
@@ -555,6 +752,85 @@
 }
 
 /**
+ *  e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
+ *  done after every PHY reset.
+ **/
+static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+
+	if (hw->mac.type != e1000_pchlan)
+		return ret_val;
+
+	if (((hw->phy.type == e1000_phy_82577) &&
+	     ((hw->phy.revision == 1) || (hw->phy.revision == 2))) ||
+	    ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) {
+		/* Disable generation of early preamble */
+		ret_val = e1e_wphy(hw, PHY_REG(769, 25), 0x4431);
+		if (ret_val)
+			return ret_val;
+
+		/* Preamble tuning for SSC */
+		ret_val = e1e_wphy(hw, PHY_REG(770, 16), 0xA204);
+		if (ret_val)
+			return ret_val;
+	}
+
+	if (hw->phy.type == e1000_phy_82578) {
+		/*
+		 * Return registers to default by doing a soft reset then
+		 * writing 0x3140 to the control register.
+		 */
+		if (hw->phy.revision < 2) {
+			e1000e_phy_sw_reset(hw);
+			ret_val = e1e_wphy(hw, PHY_CONTROL, 0x3140);
+		}
+	}
+
+	/* Select page 0 */
+	ret_val = hw->phy.ops.acquire_phy(hw);
+	if (ret_val)
+		return ret_val;
+	hw->phy.addr = 1;
+	e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+	hw->phy.ops.release_phy(hw);
+
+	return ret_val;
+}
+
+/**
+ *  e1000_lan_init_done_ich8lan - Check for PHY config completion
+ *  @hw: pointer to the HW structure
+ *
+ *  Check the appropriate indication the MAC has finished configuring the
+ *  PHY after a software reset.
+ **/
+static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
+{
+	u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT;
+
+	/* Wait for basic configuration completes before proceeding */
+	do {
+		data = er32(STATUS);
+		data &= E1000_STATUS_LAN_INIT_DONE;
+		udelay(100);
+	} while ((!data) && --loop);
+
+	/*
+	 * If basic configuration is incomplete before the above loop
+	 * count reaches 0, loading the configuration from NVM will
+	 * leave the PHY in a bad state possibly resulting in no link.
+	 */
+	if (loop == 0)
+		hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n");
+
+	/* Clear the Init Done bit for the next init event */
+	data = er32(STATUS);
+	data &= ~E1000_STATUS_LAN_INIT_DONE;
+	ew32(STATUS, data);
+}
+
+/**
  *  e1000_phy_hw_reset_ich8lan - Performs a PHY reset
  *  @hw: pointer to the HW structure
  *
@@ -568,13 +844,21 @@
 	u32 i;
 	u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;
 	s32 ret_val;
-	u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT;
 	u16 word_addr, reg_data, reg_addr, phy_page = 0;
 
 	ret_val = e1000e_phy_hw_reset_generic(hw);
 	if (ret_val)
 		return ret_val;
 
+	/* Allow time for h/w to get to a quiescent state after reset */
+	mdelay(10);
+
+	if (hw->mac.type == e1000_pchlan) {
+		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
+		if (ret_val)
+			return ret_val;
+	}
+
 	/*
 	 * Initialize the PHY from the NVM on ICH platforms.  This
 	 * is needed due to an issue where the NVM configuration is
@@ -596,26 +880,8 @@
 		if (!(data & sw_cfg_mask))
 			return 0;
 
-		/* Wait for basic configuration completes before proceeding*/
-		do {
-			data = er32(STATUS);
-			data &= E1000_STATUS_LAN_INIT_DONE;
-			udelay(100);
-		} while ((!data) && --loop);
-
-		/*
-		 * If basic configuration is incomplete before the above loop
-		 * count reaches 0, loading the configuration from NVM will
-		 * leave the PHY in a bad state possibly resulting in no link.
-		 */
-		if (loop == 0) {
-			hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n");
-		}
-
-		/* Clear the Init Done bit for the next init event */
-		data = er32(STATUS);
-		data &= ~E1000_STATUS_LAN_INIT_DONE;
-		ew32(STATUS, data);
+		/* Wait for basic configuration completes before proceeding */
+		e1000_lan_init_done_ich8lan(hw);
 
 		/*
 		 * Make sure HW does not configure LCD from PHY
@@ -701,7 +967,7 @@
 	phy->polarity_correction = (!(data & IFE_PSC_AUTO_POLARITY_DISABLE));
 
 	if (phy->polarity_correction) {
-		ret_val = e1000_check_polarity_ife_ich8lan(hw);
+		ret_val = phy->ops.check_polarity(hw);
 		if (ret_val)
 			return ret_val;
 	} else {
@@ -741,6 +1007,8 @@
 		break;
 	case e1000_phy_igp_3:
 	case e1000_phy_bm:
+	case e1000_phy_82578:
+	case e1000_phy_82577:
 		return e1000e_get_phy_info_igp(hw);
 		break;
 	default:
@@ -814,12 +1082,14 @@
 		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
 		ew32(PHY_CTRL, phy_ctrl);
 
+		if (phy->type != e1000_phy_igp_3)
+			return 0;
+
 		/*
 		 * Call gig speed drop workaround on LPLU before accessing
 		 * any PHY registers
 		 */
-		if ((hw->mac.type == e1000_ich8lan) &&
-		    (hw->phy.type == e1000_phy_igp_3))
+		if (hw->mac.type == e1000_ich8lan)
 			e1000e_gig_downshift_workaround_ich8lan(hw);
 
 		/* When LPLU is enabled, we should disable SmartSpeed */
@@ -832,6 +1102,9 @@
 		phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
 		ew32(PHY_CTRL, phy_ctrl);
 
+		if (phy->type != e1000_phy_igp_3)
+			return 0;
+
 		/*
 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
 		 * during Dx states where the power conservation is most
@@ -891,6 +1164,10 @@
 	if (!active) {
 		phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
 		ew32(PHY_CTRL, phy_ctrl);
+
+		if (phy->type != e1000_phy_igp_3)
+			return 0;
+
 		/*
 		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
 		 * during Dx states where the power conservation is most
@@ -926,12 +1203,14 @@
 		phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
 		ew32(PHY_CTRL, phy_ctrl);
 
+		if (phy->type != e1000_phy_igp_3)
+			return 0;
+
 		/*
 		 * Call gig speed drop workaround on LPLU before accessing
 		 * any PHY registers
 		 */
-		if ((hw->mac.type == e1000_ich8lan) &&
-		    (hw->phy.type == e1000_phy_igp_3))
+		if (hw->mac.type == e1000_ich8lan)
 			e1000e_gig_downshift_workaround_ich8lan(hw);
 
 		/* When LPLU is enabled, we should disable SmartSpeed */
@@ -1028,7 +1307,7 @@
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
 	u32 act_offset;
-	s32 ret_val;
+	s32 ret_val = 0;
 	u32 bank = 0;
 	u16 i, word;
 
@@ -1043,12 +1322,15 @@
 		goto out;
 
 	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
-	if (ret_val)
-		goto release;
+	if (ret_val) {
+		hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n");
+		bank = 0;
+	}
 
 	act_offset = (bank) ? nvm->flash_bank_size : 0;
 	act_offset += offset;
 
+	ret_val = 0;
 	for (i = 0; i < words; i++) {
 		if ((dev_spec->shadow_ram) &&
 		    (dev_spec->shadow_ram[offset+i].modified)) {
@@ -1063,7 +1345,6 @@
 		}
 	}
 
-release:
 	e1000_release_swflag_ich8lan(hw);
 
 out:
@@ -1314,7 +1595,6 @@
 {
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-	s32 ret_val;
 	u16 i;
 
 	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
@@ -1323,17 +1603,11 @@
 		return -E1000_ERR_NVM;
 	}
 
-	ret_val = e1000_acquire_swflag_ich8lan(hw);
-	if (ret_val)
-		return ret_val;
-
 	for (i = 0; i < words; i++) {
 		dev_spec->shadow_ram[offset+i].modified = 1;
 		dev_spec->shadow_ram[offset+i].value = data[i];
 	}
 
-	e1000_release_swflag_ich8lan(hw);
-
 	return 0;
 }
 
@@ -1374,8 +1648,8 @@
 	 */
 	ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
 	if (ret_val) {
-		e1000_release_swflag_ich8lan(hw);
-		goto out;
+		hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n");
+		bank = 0;
 	}
 
 	if (bank == 0) {
@@ -1758,19 +2032,15 @@
 		break;
 	case 1:
 		sector_size = ICH_FLASH_SEG_SIZE_4K;
-		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K;
+		iteration = 1;
 		break;
 	case 2:
-		if (hw->mac.type == e1000_ich9lan) {
-			sector_size = ICH_FLASH_SEG_SIZE_8K;
-			iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K;
-		} else {
-			return -E1000_ERR_NVM;
-		}
+		sector_size = ICH_FLASH_SEG_SIZE_8K;
+		iteration = 1;
 		break;
 	case 3:
 		sector_size = ICH_FLASH_SEG_SIZE_64K;
-		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K;
+		iteration = 1;
 		break;
 	default:
 		return -E1000_ERR_NVM;
@@ -1778,7 +2048,7 @@
 
 	/* Start with the base address, then add the sector offset. */
 	flash_linear_addr = hw->nvm.flash_base_addr;
-	flash_linear_addr += (bank) ? (sector_size * iteration) : 0;
+	flash_linear_addr += (bank) ? flash_bank_size : 0;
 
 	for (j = 0; j < iteration ; j++) {
 		do {
@@ -1852,6 +2122,79 @@
 }
 
 /**
+ *  e1000_id_led_init_pchlan - store LED configurations
+ *  @hw: pointer to the HW structure
+ *
+ *  PCH does not control LEDs via the LEDCTL register, rather it uses
+ *  the PHY LED configuration register.
+ *
+ *  PCH also does not have an "always on" or "always off" mode which
+ *  complicates the ID feature.  Instead of using the "on" mode to indicate
+ *  in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()),
+ *  use "link_up" mode.  The LEDs will still ID on request if there is no
+ *  link based on logic in e1000_led_[on|off]_pchlan().
+ **/
+static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
+{
+	struct e1000_mac_info *mac = &hw->mac;
+	s32 ret_val;
+	const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP;
+	const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT;
+	u16 data, i, temp, shift;
+
+	/* Get default ID LED modes */
+	ret_val = hw->nvm.ops.valid_led_default(hw, &data);
+	if (ret_val)
+		goto out;
+
+	mac->ledctl_default = er32(LEDCTL);
+	mac->ledctl_mode1 = mac->ledctl_default;
+	mac->ledctl_mode2 = mac->ledctl_default;
+
+	for (i = 0; i < 4; i++) {
+		temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK;
+		shift = (i * 5);
+		switch (temp) {
+		case ID_LED_ON1_DEF2:
+		case ID_LED_ON1_ON2:
+		case ID_LED_ON1_OFF2:
+			mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
+			mac->ledctl_mode1 |= (ledctl_on << shift);
+			break;
+		case ID_LED_OFF1_DEF2:
+		case ID_LED_OFF1_ON2:
+		case ID_LED_OFF1_OFF2:
+			mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
+			mac->ledctl_mode1 |= (ledctl_off << shift);
+			break;
+		default:
+			/* Do nothing */
+			break;
+		}
+		switch (temp) {
+		case ID_LED_DEF1_ON2:
+		case ID_LED_ON1_ON2:
+		case ID_LED_OFF1_ON2:
+			mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
+			mac->ledctl_mode2 |= (ledctl_on << shift);
+			break;
+		case ID_LED_DEF1_OFF2:
+		case ID_LED_ON1_OFF2:
+		case ID_LED_OFF1_OFF2:
+			mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
+			mac->ledctl_mode2 |= (ledctl_off << shift);
+			break;
+		default:
+			/* Do nothing */
+			break;
+		}
+	}
+
+out:
+	return ret_val;
+}
+
+/**
  *  e1000_get_bus_info_ich8lan - Get/Set the bus type and width
  *  @hw: pointer to the HW structure
  *
@@ -1923,6 +2266,12 @@
 	ctrl = er32(CTRL);
 
 	if (!e1000_check_reset_block(hw)) {
+		/* Clear PHY Reset Asserted bit */
+		if (hw->mac.type >= e1000_pchlan) {
+			u32 status = er32(STATUS);
+			ew32(STATUS, status & ~E1000_STATUS_PHYRA);
+		}
+
 		/*
 		 * PHY HW reset requires MAC CORE reset at the same
 		 * time to make sure the interface between MAC and the
@@ -1936,23 +2285,34 @@
 	ew32(CTRL, (ctrl | E1000_CTRL_RST));
 	msleep(20);
 
-	if (!ret_val) {
-		/* release the swflag because it is not reset by
-		 * hardware reset
-		 */
+	if (!ret_val)
 		e1000_release_swflag_ich8lan(hw);
-	}
 
-	ret_val = e1000e_get_auto_rd_done(hw);
-	if (ret_val) {
-		/*
-		 * When auto config read does not complete, do not
-		 * return with an error. This can happen in situations
-		 * where there is no eeprom and prevents getting link.
-		 */
-		hw_dbg(hw, "Auto Read Done did not complete\n");
+	if (ctrl & E1000_CTRL_PHY_RST)
+		ret_val = hw->phy.ops.get_cfg_done(hw);
+
+	if (hw->mac.type >= e1000_ich10lan) {
+		e1000_lan_init_done_ich8lan(hw);
+	} else {
+		ret_val = e1000e_get_auto_rd_done(hw);
+		if (ret_val) {
+			/*
+			 * When auto config read does not complete, do not
+			 * return with an error. This can happen in situations
+			 * where there is no eeprom and prevents getting link.
+			 */
+			hw_dbg(hw, "Auto Read Done did not complete\n");
+		}
 	}
 
+	/*
+	 * For PCH, this write will make sure that any noise
+	 * will be detected as a CRC error and be dropped rather than show up
+	 * as a bad packet to the DMA engine.
+	 */
+	if (hw->mac.type == e1000_pchlan)
+		ew32(CRC_OFFSET, 0x65656565);
+
 	ew32(IMC, 0xffffffff);
 	icr = er32(ICR);
 
@@ -1960,6 +2320,9 @@
 	kab |= E1000_KABGTXD_BGSQLBIAS;
 	ew32(KABGTXD, kab);
 
+	if (hw->mac.type == e1000_pchlan)
+		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
+
 	return ret_val;
 }
 
@@ -1985,7 +2348,7 @@
 	e1000_initialize_hw_bits_ich8lan(hw);
 
 	/* Initialize identification LED */
-	ret_val = e1000e_id_led_init(hw);
+	ret_val = mac->ops.id_led_init(hw);
 	if (ret_val) {
 		hw_dbg(hw, "Error initializing identification LED\n");
 		return ret_val;
@@ -1999,6 +2362,18 @@
 	for (i = 0; i < mac->mta_reg_count; i++)
 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
 
+	/*
+	 * The 82578 Rx buffer will stall if wakeup is enabled in host and
+	 * the ME.  Reading the BM_WUC register will clear the host wakeup bit.
+	 * Reset the phy after disabling host wakeup to reset the Rx buffer.
+	 */
+	if (hw->phy.type == e1000_phy_82578) {
+		hw->phy.ops.read_phy_reg(hw, BM_WUC, &i);
+		ret_val = e1000_phy_hw_reset_ich8lan(hw);
+		if (ret_val)
+			return ret_val;
+	}
+
 	/* Setup link and flow control */
 	ret_val = e1000_setup_link_ich8lan(hw);
 
@@ -2054,6 +2429,9 @@
 	/* Extended Device Control */
 	reg = er32(CTRL_EXT);
 	reg |= (1 << 22);
+	/* Enable PHY low-power state when MAC is at D3 w/o WoL */
+	if (hw->mac.type >= e1000_pchlan)
+		reg |= E1000_CTRL_EXT_PHYPDEN;
 	ew32(CTRL_EXT, reg);
 
 	/* Transmit Descriptor Control 0 */
@@ -2112,8 +2490,13 @@
 	 * the default flow control setting, so we explicitly
 	 * set it to full.
 	 */
-	if (hw->fc.requested_mode == e1000_fc_default)
-		hw->fc.requested_mode = e1000_fc_full;
+	if (hw->fc.requested_mode == e1000_fc_default) {
+		/* Workaround h/w hang when Tx flow control enabled */
+		if (hw->mac.type == e1000_pchlan)
+			hw->fc.requested_mode = e1000_fc_rx_pause;
+		else
+			hw->fc.requested_mode = e1000_fc_full;
+	}
 
 	/*
 	 * Save off the requested flow control mode for use later.  Depending
@@ -2130,6 +2513,14 @@
 		return ret_val;
 
 	ew32(FCTTV, hw->fc.pause_time);
+	if ((hw->phy.type == e1000_phy_82578) ||
+	    (hw->phy.type == e1000_phy_82577)) {
+		ret_val = hw->phy.ops.write_phy_reg(hw,
+		                             PHY_REG(BM_PORT_CTRL_PAGE, 27),
+		                             hw->fc.pause_time);
+		if (ret_val)
+			return ret_val;
+	}
 
 	return e1000e_set_fc_watermarks(hw);
 }
@@ -2169,18 +2560,26 @@
 	if (ret_val)
 		return ret_val;
 
-	if (hw->phy.type == e1000_phy_igp_3) {
+	switch (hw->phy.type) {
+	case e1000_phy_igp_3:
 		ret_val = e1000e_copper_link_setup_igp(hw);
 		if (ret_val)
 			return ret_val;
-	} else if (hw->phy.type == e1000_phy_bm) {
+		break;
+	case e1000_phy_bm:
+	case e1000_phy_82578:
 		ret_val = e1000e_copper_link_setup_m88(hw);
 		if (ret_val)
 			return ret_val;
-	}
-
-	if (hw->phy.type == e1000_phy_ife) {
-		ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &reg_data);
+		break;
+	case e1000_phy_82577:
+		ret_val = e1000_copper_link_setup_82577(hw);
+		if (ret_val)
+			return ret_val;
+		break;
+	case e1000_phy_ife:
+		ret_val = hw->phy.ops.read_phy_reg(hw, IFE_PHY_MDIX_CONTROL,
+		                               &reg_data);
 		if (ret_val)
 			return ret_val;
 
@@ -2198,9 +2597,13 @@
 			reg_data |= IFE_PMC_AUTO_MDIX;
 			break;
 		}
-		ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, reg_data);
+		ret_val = hw->phy.ops.write_phy_reg(hw, IFE_PHY_MDIX_CONTROL,
+		                                reg_data);
 		if (ret_val)
 			return ret_val;
+		break;
+	default:
+		break;
 	}
 	return e1000e_setup_copper_link(hw);
 }
@@ -2224,6 +2627,14 @@
 	if (ret_val)
 		return ret_val;
 
+	if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
+		ret_val = e1000e_write_kmrn_reg(hw,
+		                                  E1000_KMRNCTRLSTA_K1_CONFIG,
+		                                  E1000_KMRNCTRLSTA_K1_DISABLE);
+		if (ret_val)
+			return ret_val;
+	}
+
 	if ((hw->mac.type == e1000_ich8lan) &&
 	    (hw->phy.type == e1000_phy_igp_3) &&
 	    (*speed == SPEED_1000)) {
@@ -2417,18 +2828,26 @@
  *  'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
  *  to a lower speed.
  *
- *  Should only be called for ICH9 and ICH10 devices.
+ *  Should only be called for applicable parts.
  **/
 void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
 {
 	u32 phy_ctrl;
 
-	if ((hw->mac.type == e1000_ich10lan) ||
-	    (hw->mac.type == e1000_ich9lan)) {
+	switch (hw->mac.type) {
+	case e1000_ich9lan:
+	case e1000_ich10lan:
+	case e1000_pchlan:
 		phy_ctrl = er32(PHY_CTRL);
 		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
 		            E1000_PHY_CTRL_GBE_DISABLE;
 		ew32(PHY_CTRL, phy_ctrl);
+
+		/* Workaround SWFLAG unexpectedly set during S0->Sx */
+		if (hw->mac.type == e1000_pchlan)
+			udelay(500);
+	default:
+		break;
 	}
 
 	return;
@@ -2482,23 +2901,120 @@
 }
 
 /**
+ *  e1000_setup_led_pchlan - Configures SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This prepares the SW controllable LED for use.
+ **/
+static s32 e1000_setup_led_pchlan(struct e1000_hw *hw)
+{
+	return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG,
+					(u16)hw->mac.ledctl_mode1);
+}
+
+/**
+ *  e1000_cleanup_led_pchlan - Restore the default LED operation
+ *  @hw: pointer to the HW structure
+ *
+ *  Return the LED back to the default configuration.
+ **/
+static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw)
+{
+	return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG,
+					(u16)hw->mac.ledctl_default);
+}
+
+/**
+ *  e1000_led_on_pchlan - Turn LEDs on
+ *  @hw: pointer to the HW structure
+ *
+ *  Turn on the LEDs.
+ **/
+static s32 e1000_led_on_pchlan(struct e1000_hw *hw)
+{
+	u16 data = (u16)hw->mac.ledctl_mode2;
+	u32 i, led;
+
+	/*
+	 * If no link, then turn LED on by setting the invert bit
+	 * for each LED that's mode is "link_up" in ledctl_mode2.
+	 */
+	if (!(er32(STATUS) & E1000_STATUS_LU)) {
+		for (i = 0; i < 3; i++) {
+			led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
+			if ((led & E1000_PHY_LED0_MODE_MASK) !=
+			    E1000_LEDCTL_MODE_LINK_UP)
+				continue;
+			if (led & E1000_PHY_LED0_IVRT)
+				data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
+			else
+				data |= (E1000_PHY_LED0_IVRT << (i * 5));
+		}
+	}
+
+	return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG, data);
+}
+
+/**
+ *  e1000_led_off_pchlan - Turn LEDs off
+ *  @hw: pointer to the HW structure
+ *
+ *  Turn off the LEDs.
+ **/
+static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
+{
+	u16 data = (u16)hw->mac.ledctl_mode1;
+	u32 i, led;
+
+	/*
+	 * If no link, then turn LED off by clearing the invert bit
+	 * for each LED that's mode is "link_up" in ledctl_mode1.
+	 */
+	if (!(er32(STATUS) & E1000_STATUS_LU)) {
+		for (i = 0; i < 3; i++) {
+			led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
+			if ((led & E1000_PHY_LED0_MODE_MASK) !=
+			    E1000_LEDCTL_MODE_LINK_UP)
+				continue;
+			if (led & E1000_PHY_LED0_IVRT)
+				data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
+			else
+				data |= (E1000_PHY_LED0_IVRT << (i * 5));
+		}
+	}
+
+	return hw->phy.ops.write_phy_reg(hw, HV_LED_CONFIG, data);
+}
+
+/**
  *  e1000_get_cfg_done_ich8lan - Read config done bit
  *  @hw: pointer to the HW structure
  *
  *  Read the management control register for the config done bit for
  *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
  *  to read the config done bit, so an error is *ONLY* logged and returns
- *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
+ *  0.  If we were to return with error, EEPROM-less silicon
  *  would not be able to be reset or change link.
  **/
 static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
 {
 	u32 bank = 0;
 
+	if (hw->mac.type >= e1000_pchlan) {
+		u32 status = er32(STATUS);
+
+		if (status & E1000_STATUS_PHYRA)
+			ew32(STATUS, status & ~E1000_STATUS_PHYRA);
+		else
+			hw_dbg(hw,
+			       "PHY Reset Asserted not set - needs delay\n");
+	}
+
 	e1000e_get_cfg_done(hw);
 
 	/* If EEPROM is not marked present, init the IGP 3 PHY manually */
-	if (hw->mac.type != e1000_ich10lan) {
+	if ((hw->mac.type != e1000_ich10lan) &&
+	    (hw->mac.type != e1000_pchlan)) {
 		if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
 		    (hw->phy.type == e1000_phy_igp_3)) {
 			e1000e_phy_init_script_igp3(hw);
@@ -2524,6 +3040,7 @@
 static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
 {
 	u32 temp;
+	u16 phy_data;
 
 	e1000e_clear_hw_cntrs_base(hw);
 
@@ -2541,22 +3058,42 @@
 	temp = er32(IAC);
 	temp = er32(ICRXOC);
 
+	/* Clear PHY statistics registers */
+	if ((hw->phy.type == e1000_phy_82578) ||
+	    (hw->phy.type == e1000_phy_82577)) {
+		hw->phy.ops.read_phy_reg(hw, HV_SCC_UPPER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_SCC_LOWER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_ECOL_UPPER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_ECOL_LOWER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_MCC_UPPER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_MCC_LOWER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_LATECOL_UPPER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_LATECOL_LOWER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_COLC_UPPER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_COLC_LOWER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_DC_UPPER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_DC_LOWER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_TNCRS_UPPER, &phy_data);
+		hw->phy.ops.read_phy_reg(hw, HV_TNCRS_LOWER, &phy_data);
+	}
 }
 
 static struct e1000_mac_operations ich8_mac_ops = {
+	.id_led_init		= e1000e_id_led_init,
 	.check_mng_mode		= e1000_check_mng_mode_ich8lan,
-	.check_for_link		= e1000e_check_for_copper_link,
-	.cleanup_led		= e1000_cleanup_led_ich8lan,
+	.check_for_link		= e1000_check_for_copper_link_ich8lan,
+	/* cleanup_led dependent on mac type */
 	.clear_hw_cntrs		= e1000_clear_hw_cntrs_ich8lan,
 	.get_bus_info		= e1000_get_bus_info_ich8lan,
 	.get_link_up_info	= e1000_get_link_up_info_ich8lan,
-	.led_on			= e1000_led_on_ich8lan,
-	.led_off		= e1000_led_off_ich8lan,
+	/* led_on dependent on mac type */
+	/* led_off dependent on mac type */
 	.update_mc_addr_list	= e1000e_update_mc_addr_list_generic,
 	.reset_hw		= e1000_reset_hw_ich8lan,
 	.init_hw		= e1000_init_hw_ich8lan,
 	.setup_link		= e1000_setup_link_ich8lan,
 	.setup_physical_interface= e1000_setup_copper_link_ich8lan,
+	/* id_led_init dependent on mac type */
 };
 
 static struct e1000_phy_operations ich8_phy_ops = {
@@ -2595,6 +3132,7 @@
 				  | FLAG_HAS_FLASH
 				  | FLAG_APME_IN_WUC,
 	.pba			= 8,
+	.max_hw_frame_size	= ETH_FRAME_LEN + ETH_FCS_LEN,
 	.get_variants		= e1000_get_variants_ich8lan,
 	.mac_ops		= &ich8_mac_ops,
 	.phy_ops		= &ich8_phy_ops,
@@ -2613,6 +3151,7 @@
 				  | FLAG_HAS_FLASH
 				  | FLAG_APME_IN_WUC,
 	.pba			= 10,
+	.max_hw_frame_size	= DEFAULT_JUMBO,
 	.get_variants		= e1000_get_variants_ich8lan,
 	.mac_ops		= &ich8_mac_ops,
 	.phy_ops		= &ich8_phy_ops,
@@ -2631,6 +3170,25 @@
 				  | FLAG_HAS_FLASH
 				  | FLAG_APME_IN_WUC,
 	.pba			= 10,
+	.max_hw_frame_size	= DEFAULT_JUMBO,
+	.get_variants		= e1000_get_variants_ich8lan,
+	.mac_ops		= &ich8_mac_ops,
+	.phy_ops		= &ich8_phy_ops,
+	.nvm_ops		= &ich8_nvm_ops,
+};
+
+struct e1000_info e1000_pch_info = {
+	.mac			= e1000_pchlan,
+	.flags			= FLAG_IS_ICH
+				  | FLAG_HAS_WOL
+				  | FLAG_RX_CSUM_ENABLED
+				  | FLAG_HAS_CTRLEXT_ON_LOAD
+				  | FLAG_HAS_AMT
+				  | FLAG_HAS_FLASH
+				  | FLAG_HAS_JUMBO_FRAMES
+				  | FLAG_APME_IN_WUC,
+	.pba			= 26,
+	.max_hw_frame_size	= 4096,
 	.get_variants		= e1000_get_variants_ich8lan,
 	.mac_ops		= &ich8_mac_ops,
 	.phy_ops		= &ich8_phy_ops,
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/lib.c linux-libre-2.6.31-gnu/drivers/net/e1000e/lib.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/lib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/lib.c	2009-09-09 18:13:59.000000000 -0400
@@ -1406,6 +1406,38 @@
 }
 
 /**
+ *  e1000e_setup_led_generic - Configures SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This prepares the SW controllable LED for use and saves the current state
+ *  of the LED so it can be later restored.
+ **/
+s32 e1000e_setup_led_generic(struct e1000_hw *hw)
+{
+	u32 ledctl;
+
+	if (hw->mac.ops.setup_led != e1000e_setup_led_generic) {
+		return -E1000_ERR_CONFIG;
+	}
+
+	if (hw->phy.media_type == e1000_media_type_fiber) {
+		ledctl = er32(LEDCTL);
+		hw->mac.ledctl_default = ledctl;
+		/* Turn off LED0 */
+		ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
+		            E1000_LEDCTL_LED0_BLINK |
+		            E1000_LEDCTL_LED0_MODE_MASK);
+		ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
+		           E1000_LEDCTL_LED0_MODE_SHIFT);
+		ew32(LEDCTL, ledctl);
+	} else if (hw->phy.media_type == e1000_media_type_copper) {
+		ew32(LEDCTL, hw->mac.ledctl_mode1);
+	}
+
+	return 0;
+}
+
+/**
  *  e1000e_cleanup_led_generic - Set LED config to default operation
  *  @hw: pointer to the HW structure
  *
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/netdev.c linux-libre-2.6.31-gnu/drivers/net/e1000e/netdev.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/netdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/netdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -48,7 +48,7 @@
 
 #include "e1000.h"
 
-#define DRV_VERSION "0.3.3.4-k4"
+#define DRV_VERSION "1.0.2-k2"
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -62,6 +62,7 @@
 	[board_ich8lan]		= &e1000_ich8_info,
 	[board_ich9lan]		= &e1000_ich9_info,
 	[board_ich10lan]	= &e1000_ich10_info,
+	[board_pchlan]		= &e1000_pch_info,
 };
 
 #ifdef DEBUG
@@ -1996,7 +1997,7 @@
 	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *poll_dev = adapter->netdev;
-	int tx_cleaned = 0, work_done = 0;
+	int tx_cleaned = 1, work_done = 0;
 
 	adapter = netdev_priv(poll_dev);
 
@@ -2255,8 +2256,6 @@
 		ew32(TARC(1), tarc);
 	}
 
-	e1000e_config_collision_dist(hw);
-
 	/* Setup Transmit Descriptor Settings for eop descriptor */
 	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
 
@@ -2269,6 +2268,8 @@
 
 	ew32(TCTL, tctl);
 
+	e1000e_config_collision_dist(hw);
+
 	adapter->tx_queue_len = adapter->netdev->tx_queue_len;
 }
 
@@ -2308,6 +2309,23 @@
 	if (adapter->flags2 & FLAG2_CRC_STRIPPING)
 		rctl |= E1000_RCTL_SECRC;
 
+	/* Workaround Si errata on 82577 PHY - configure IPG for jumbos */
+	if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) {
+		u16 phy_data;
+
+		e1e_rphy(hw, PHY_REG(770, 26), &phy_data);
+		phy_data &= 0xfff8;
+		phy_data |= (1 << 2);
+		e1e_wphy(hw, PHY_REG(770, 26), phy_data);
+
+		e1e_rphy(hw, 22, &phy_data);
+		phy_data &= 0x0fff;
+		phy_data |= (1 << 14);
+		e1e_wphy(hw, 0x10, 0x2823);
+		e1e_wphy(hw, 0x11, 0x0003);
+		e1e_wphy(hw, 22, phy_data);
+	}
+
 	/* Setup buffer sizes */
 	rctl &= ~E1000_RCTL_SZ_4096;
 	rctl |= E1000_RCTL_BSEX;
@@ -2751,23 +2769,25 @@
 	/*
 	 * flow control settings
 	 *
-	 * The high water mark must be low enough to fit one full frame
+	 * The high water mark must be low enough to fit two full frame
 	 * (or the size used for early receive) above it in the Rx FIFO.
 	 * Set it to the lower of:
 	 * - 90% of the Rx FIFO size, and
 	 * - the full Rx FIFO size minus the early receive size (for parts
 	 *   with ERT support assuming ERT set to E1000_ERT_2048), or
-	 * - the full Rx FIFO size minus one full frame
+	 * - the full Rx FIFO size minus two full frames
 	 */
-	if (adapter->flags & FLAG_HAS_ERT)
+	if ((adapter->flags & FLAG_HAS_ERT) &&
+	    (adapter->netdev->mtu > ETH_DATA_LEN))
 		hwm = min(((pba << 10) * 9 / 10),
 			  ((pba << 10) - (E1000_ERT_2048 << 3)));
 	else
 		hwm = min(((pba << 10) * 9 / 10),
-			  ((pba << 10) - adapter->max_frame_size));
+			  ((pba << 10) - (2 * adapter->max_frame_size)));
 
-	fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */
-	fc->low_water = fc->high_water - 8;
+	fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
+	fc->low_water = (fc->high_water - (2 * adapter->max_frame_size));
+	fc->low_water &= E1000_FCRTL_RTL; /* 8-byte granularity */
 
 	if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
 		fc->pause_time = 0xFFFF;
@@ -2787,6 +2807,8 @@
 		e1000_get_hw_control(adapter);
 
 	ew32(WUC, 0);
+	if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)
+		e1e_wphy(&adapter->hw, BM_WUC, 0);
 
 	if (mac->ops.init_hw(hw))
 		e_err("Hardware Error\n");
@@ -2799,7 +2821,8 @@
 	e1000e_reset_adaptive(hw);
 	e1000_get_phy_info(hw);
 
-	if (!(adapter->flags & FLAG_SMART_POWER_DOWN)) {
+	if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) &&
+	    !(adapter->flags & FLAG_SMART_POWER_DOWN)) {
 		u16 phy_data = 0;
 		/*
 		 * speed up time to link by disabling smart power down, ignore
@@ -2826,6 +2849,8 @@
 		e1000_configure_msix(adapter);
 	e1000_irq_enable(adapter);
 
+	netif_wake_queue(adapter->netdev);
+
 	/* fire a link change interrupt to start the watchdog */
 	ew32(ICS, E1000_ICS_LSC);
 	return 0;
@@ -2848,7 +2873,7 @@
 	ew32(RCTL, rctl & ~E1000_RCTL_EN);
 	/* flush and sleep below */
 
-	netif_tx_stop_all_queues(netdev);
+	netif_stop_queue(netdev);
 
 	/* disable transmits in the hardware */
 	tctl = er32(TCTL);
@@ -3072,6 +3097,8 @@
 	if (test_bit(__E1000_TESTING, &adapter->state))
 		return -EBUSY;
 
+	netif_carrier_off(netdev);
+
 	/* allocate transmit descriptors */
 	err = e1000e_setup_tx_resources(adapter);
 	if (err)
@@ -3128,7 +3155,7 @@
 
 	e1000_irq_enable(adapter);
 
-	netif_tx_start_all_queues(netdev);
+	netif_start_queue(netdev);
 
 	/* fire a link status change interrupt to start the watchdog */
 	ew32(ICS, E1000_ICS_LSC);
@@ -3262,6 +3289,7 @@
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
+	u16 phy_data;
 
 	/*
 	 * Prevent stats update while adapter is being reset, or if the pci
@@ -3281,11 +3309,34 @@
 	adapter->stats.roc += er32(ROC);
 
 	adapter->stats.mpc += er32(MPC);
-	adapter->stats.scc += er32(SCC);
-	adapter->stats.ecol += er32(ECOL);
-	adapter->stats.mcc += er32(MCC);
-	adapter->stats.latecol += er32(LATECOL);
-	adapter->stats.dc += er32(DC);
+	if ((hw->phy.type == e1000_phy_82578) ||
+	    (hw->phy.type == e1000_phy_82577)) {
+		e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
+		adapter->stats.scc += phy_data;
+
+		e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
+		e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
+		adapter->stats.ecol += phy_data;
+
+		e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
+		adapter->stats.mcc += phy_data;
+
+		e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
+		e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
+		adapter->stats.latecol += phy_data;
+
+		e1e_rphy(hw, HV_DC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_DC_LOWER, &phy_data);
+		adapter->stats.dc += phy_data;
+	} else {
+		adapter->stats.scc += er32(SCC);
+		adapter->stats.ecol += er32(ECOL);
+		adapter->stats.mcc += er32(MCC);
+		adapter->stats.latecol += er32(LATECOL);
+		adapter->stats.dc += er32(DC);
+	}
 	adapter->stats.xonrxc += er32(XONRXC);
 	adapter->stats.xontxc += er32(XONTXC);
 	adapter->stats.xoffrxc += er32(XOFFRXC);
@@ -3303,13 +3354,28 @@
 
 	hw->mac.tx_packet_delta = er32(TPT);
 	adapter->stats.tpt += hw->mac.tx_packet_delta;
-	hw->mac.collision_delta = er32(COLC);
+	if ((hw->phy.type == e1000_phy_82578) ||
+	    (hw->phy.type == e1000_phy_82577)) {
+		e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
+		e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
+		hw->mac.collision_delta = phy_data;
+	} else {
+		hw->mac.collision_delta = er32(COLC);
+	}
 	adapter->stats.colc += hw->mac.collision_delta;
 
 	adapter->stats.algnerrc += er32(ALGNERRC);
 	adapter->stats.rxerrc += er32(RXERRC);
-	if ((hw->mac.type != e1000_82574) && (hw->mac.type != e1000_82583))
-		adapter->stats.tncrs += er32(TNCRS);
+	if ((hw->phy.type == e1000_phy_82578) ||
+	    (hw->phy.type == e1000_phy_82577)) {
+		e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
+		e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
+		adapter->stats.tncrs += phy_data;
+	} else {
+		if ((hw->mac.type != e1000_82574) &&
+		    (hw->mac.type != e1000_82583))
+			adapter->stats.tncrs += er32(TNCRS);
+	}
 	adapter->stats.cexterr += er32(CEXTERR);
 	adapter->stats.tsctc += er32(TSCTC);
 	adapter->stats.tsctfc += er32(TSCTFC);
@@ -3598,7 +3664,6 @@
 				phy->ops.cfg_on_link_up(hw);
 
 			netif_carrier_on(netdev);
-			netif_tx_wake_all_queues(netdev);
 
 			if (!test_bit(__E1000_DOWN, &adapter->state))
 				mod_timer(&adapter->phy_info_timer,
@@ -3612,7 +3677,6 @@
 			printk(KERN_INFO "e1000e: %s NIC Link is Down\n",
 			       adapter->netdev->name);
 			netif_carrier_off(netdev);
-			netif_tx_stop_all_queues(netdev);
 			if (!test_bit(__E1000_DOWN, &adapter->state))
 				mod_timer(&adapter->phy_info_timer,
 					  round_jiffies(jiffies + 2 * HZ));
@@ -3649,6 +3713,8 @@
 			 */
 			adapter->tx_timeout_count++;
 			schedule_work(&adapter->reset_task);
+			/* return immediately since reset is imminent */
+			return;
 		}
 	}
 
@@ -3850,7 +3916,7 @@
 		buffer_info->length = size;
 		buffer_info->time_stamp = jiffies;
 		buffer_info->next_to_watch = i;
-		buffer_info->dma = map[0] + offset;
+		buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
 		count++;
 
 		len -= size;
@@ -3881,7 +3947,7 @@
 			buffer_info->length = size;
 			buffer_info->time_stamp = jiffies;
 			buffer_info->next_to_watch = i;
-			buffer_info->dma = map[f + 1] + offset;
+			buffer_info->dma = map[f] + offset;
 
 			len -= size;
 			offset += size;
@@ -4145,7 +4211,6 @@
 	count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss);
 	if (count) {
 		e1000_tx_queue(adapter, tx_flags, count);
-		netdev->trans_start = jiffies;
 		/* Make sure there is space in the ring for the next send. */
 		e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2);
 
@@ -4206,27 +4271,17 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
-	if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) ||
-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		e_err("Invalid MTU setting\n");
+	/* Jumbo frame support */
+	if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) &&
+	    !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
+		e_err("Jumbo Frames not supported.\n");
 		return -EINVAL;
 	}
 
-	/* Jumbo frame size limits */
-	if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) {
-		if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
-			e_err("Jumbo Frames not supported.\n");
-			return -EINVAL;
-		}
-		if (adapter->hw.phy.type == e1000_phy_ife) {
-			e_err("Jumbo Frames not supported.\n");
-			return -EINVAL;
-		}
-	}
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
-	if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
-		e_err("MTU > 9216 not supported.\n");
+	/* Supported frame sizes */
+	if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) ||
+	    (max_frame > adapter->max_hw_frame_size)) {
+		e_err("Unsupported MTU setting\n");
 		return -EINVAL;
 	}
 
@@ -4346,6 +4401,81 @@
 	}
 }
 
+static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 i, mac_reg;
+	u16 phy_reg;
+	int retval = 0;
+
+	/* copy MAC RARs to PHY RARs */
+	for (i = 0; i < adapter->hw.mac.rar_entry_count; i++) {
+		mac_reg = er32(RAL(i));
+		e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
+		e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
+		mac_reg = er32(RAH(i));
+		e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
+		e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0xFFFF));
+	}
+
+	/* copy MAC MTA to PHY MTA */
+	for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
+		mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i);
+		e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF));
+		e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF));
+	}
+
+	/* configure PHY Rx Control register */
+	e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg);
+	mac_reg = er32(RCTL);
+	if (mac_reg & E1000_RCTL_UPE)
+		phy_reg |= BM_RCTL_UPE;
+	if (mac_reg & E1000_RCTL_MPE)
+		phy_reg |= BM_RCTL_MPE;
+	phy_reg &= ~(BM_RCTL_MO_MASK);
+	if (mac_reg & E1000_RCTL_MO_3)
+		phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT)
+				<< BM_RCTL_MO_SHIFT);
+	if (mac_reg & E1000_RCTL_BAM)
+		phy_reg |= BM_RCTL_BAM;
+	if (mac_reg & E1000_RCTL_PMCF)
+		phy_reg |= BM_RCTL_PMCF;
+	mac_reg = er32(CTRL);
+	if (mac_reg & E1000_CTRL_RFCE)
+		phy_reg |= BM_RCTL_RFCE;
+	e1e_wphy(&adapter->hw, BM_RCTL, phy_reg);
+
+	/* enable PHY wakeup in MAC register */
+	ew32(WUFC, wufc);
+	ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
+
+	/* configure and enable PHY wakeup in PHY registers */
+	e1e_wphy(&adapter->hw, BM_WUFC, wufc);
+	e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
+
+	/* activate PHY wakeup */
+	retval = hw->phy.ops.acquire_phy(hw);
+	if (retval) {
+		e_err("Could not acquire PHY\n");
+		return retval;
+	}
+	e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
+	                         (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
+	retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
+	if (retval) {
+		e_err("Could not read PHY page 769\n");
+		goto out;
+	}
+	phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
+	retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+	if (retval)
+		e_err("Could not set PHY Host Wakeup bit\n");
+out:
+	hw->phy.ops.release_phy(hw);
+
+	return retval;
+}
+
 static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
@@ -4388,8 +4518,9 @@
 		#define E1000_CTRL_ADVD3WUC 0x00100000
 		/* phy power management enable */
 		#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
-		ctrl |= E1000_CTRL_ADVD3WUC |
-			E1000_CTRL_EN_PHY_PWR_MGMT;
+		ctrl |= E1000_CTRL_ADVD3WUC;
+		if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP))
+			ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT;
 		ew32(CTRL, ctrl);
 
 		if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
@@ -4407,8 +4538,16 @@
 		/* Allow time for pending master requests to run */
 		e1000e_disable_pcie_master(&adapter->hw);
 
-		ew32(WUC, E1000_WUC_PME_EN);
-		ew32(WUFC, wufc);
+		if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) {
+			/* enable wakeup by the PHY */
+			retval = e1000_init_phy_wakeup(adapter, wufc);
+			if (retval)
+				return retval;
+		} else {
+			/* enable wakeup by the MAC */
+			ew32(WUFC, wufc);
+			ew32(WUC, E1000_WUC_PME_EN);
+		}
 	} else {
 		ew32(WUC, 0);
 		ew32(WUFC, 0);
@@ -4417,7 +4556,8 @@
 	*enable_wake = !!wufc;
 
 	/* make sure adapter isn't asleep if manageability is enabled */
-	if (adapter->flags & FLAG_MNG_PT_ENABLED)
+	if ((adapter->flags & FLAG_MNG_PT_ENABLED) ||
+	    (hw->mac.ops.check_mng_mode(hw)))
 		*enable_wake = true;
 
 	if (adapter->hw.phy.type == e1000_phy_igp_3)
@@ -4530,14 +4670,6 @@
 		return err;
 	}
 
-	/* AER (Advanced Error Reporting) hooks */
-	err = pci_enable_pcie_error_reporting(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
-		                    "0x%x\n", err);
-		/* non-fatal, continue */
-	}
-
 	pci_set_master(pdev);
 
 	pci_enable_wake(pdev, PCI_D3hot, 0);
@@ -4551,8 +4683,37 @@
 	}
 
 	e1000e_power_up_phy(adapter);
+
+	/* report the system wakeup cause from S3/S4 */
+	if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) {
+		u16 phy_data;
+
+		e1e_rphy(&adapter->hw, BM_WUS, &phy_data);
+		if (phy_data) {
+			e_info("PHY Wakeup cause - %s\n",
+				phy_data & E1000_WUS_EX ? "Unicast Packet" :
+				phy_data & E1000_WUS_MC ? "Multicast Packet" :
+				phy_data & E1000_WUS_BC ? "Broadcast Packet" :
+				phy_data & E1000_WUS_MAG ? "Magic Packet" :
+				phy_data & E1000_WUS_LNKC ? "Link Status "
+				" Change" : "other");
+		}
+		e1e_wphy(&adapter->hw, BM_WUS, ~0);
+	} else {
+		u32 wus = er32(WUS);
+		if (wus) {
+			e_info("MAC Wakeup cause - %s\n",
+				wus & E1000_WUS_EX ? "Unicast Packet" :
+				wus & E1000_WUS_MC ? "Multicast Packet" :
+				wus & E1000_WUS_BC ? "Broadcast Packet" :
+				wus & E1000_WUS_MAG ? "Magic Packet" :
+				wus & E1000_WUS_LNKC ? "Link Status Change" :
+				"other");
+		}
+		ew32(WUS, ~0);
+	}
+
 	e1000e_reset(adapter);
-	ew32(WUS, ~0);
 
 	e1000_init_manageability(adapter);
 
@@ -4616,6 +4777,9 @@
 
 	netif_device_detach(netdev);
 
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
 	if (netif_running(netdev))
 		e1000e_down(adapter);
 	pci_disable_device(pdev);
@@ -4818,6 +4982,14 @@
 	if (err)
 		goto err_pci_reg;
 
+	/* AER (Advanced Error Reporting) hooks */
+	err = pci_enable_pcie_error_reporting(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
+		        "0x%x\n", err);
+		/* non-fatal, continue */
+	}
+
 	pci_set_master(pdev);
 	/* PCI config space info */
 	err = pci_save_state(pdev);
@@ -4842,6 +5014,7 @@
 	adapter->flags2 = ei->flags2;
 	adapter->hw.adapter = adapter;
 	adapter->hw.mac.type = ei->mac;
+	adapter->max_hw_frame_size = ei->max_hw_frame_size;
 	adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
 
 	mmio_start = pci_resource_start(pdev, 0);
@@ -4997,6 +5170,8 @@
 		/* APME bit in EEPROM is mapped to WUC.APME */
 		eeprom_data = er32(WUC);
 		eeprom_apme_mask = E1000_WUC_APME;
+		if (eeprom_data & E1000_WUC_PHY_WAKE)
+			adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP;
 	} else if (adapter->flags & FLAG_APME_IN_CTRL3) {
 		if (adapter->flags & FLAG_APME_CHECK_PORT_B &&
 		    (adapter->hw.bus.func == 1))
@@ -5037,15 +5212,14 @@
 	if (!(adapter->flags & FLAG_HAS_AMT))
 		e1000_get_hw_control(adapter);
 
-	/* tell the stack to leave us alone until e1000_open() is called */
-	netif_carrier_off(netdev);
-	netif_tx_stop_all_queues(netdev);
-
 	strcpy(netdev->name, "eth%d");
 	err = register_netdev(netdev);
 	if (err)
 		goto err_register;
 
+	/* carrier off reporting is important to ethtool even BEFORE open */
+	netif_carrier_off(netdev);
+
 	e1000_print_device_info(adapter);
 
 	return 0;
@@ -5199,6 +5373,11 @@
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan },
 
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan },
+
 	{ }	/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/param.c linux-libre-2.6.31-gnu/drivers/net/e1000e/param.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/param.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/param.c	2009-09-09 18:13:59.000000000 -0400
@@ -427,6 +427,8 @@
 			e1000_validate_option(&crc_stripping, &opt, adapter);
 			if (crc_stripping == OPTION_ENABLED)
 				adapter->flags2 |= FLAG2_CRC_STRIPPING;
+		} else {
+			adapter->flags2 |= FLAG2_CRC_STRIPPING;
 		}
 	}
 	{ /* Kumeran Lock Loss Workaround */
diff -druN linux-libre-2.6.30-gnu/drivers/net/e1000e/phy.c linux-libre-2.6.31-gnu/drivers/net/e1000e/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/e1000e/phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e1000e/phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,9 @@
 static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
 static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
 					  u16 *data, bool read);
+static u32 e1000_get_phy_addr_for_hv_page(u32 page);
+static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
+                                          u16 *data, bool read);
 
 /* Cable length tables */
 static const u16 e1000_m88_cable_length_table[] =
@@ -54,6 +57,55 @@
 #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
 		ARRAY_SIZE(e1000_igp_2_cable_length_table)
 
+#define BM_PHY_REG_PAGE(offset) \
+	((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF))
+#define BM_PHY_REG_NUM(offset) \
+	((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\
+	 (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\
+		~MAX_PHY_REG_ADDRESS)))
+
+#define HV_INTC_FC_PAGE_START             768
+#define I82578_ADDR_REG                   29
+#define I82577_ADDR_REG                   16
+#define I82577_CFG_REG                    22
+#define I82577_CFG_ASSERT_CRS_ON_TX       (1 << 15)
+#define I82577_CFG_ENABLE_DOWNSHIFT       (3 << 10) /* auto downshift 100/10 */
+#define I82577_CTRL_REG                   23
+#define I82577_CTRL_DOWNSHIFT_MASK        (7 << 10)
+
+/* 82577 specific PHY registers */
+#define I82577_PHY_CTRL_2            18
+#define I82577_PHY_STATUS_2          26
+#define I82577_PHY_DIAG_STATUS       31
+
+/* I82577 PHY Status 2 */
+#define I82577_PHY_STATUS2_REV_POLARITY   0x0400
+#define I82577_PHY_STATUS2_MDIX           0x0800
+#define I82577_PHY_STATUS2_SPEED_MASK     0x0300
+#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200
+
+/* I82577 PHY Control 2 */
+#define I82577_PHY_CTRL2_AUTO_MDIX        0x0400
+#define I82577_PHY_CTRL2_FORCE_MDI_MDIX   0x0200
+
+/* I82577 PHY Diagnostics Status */
+#define I82577_DSTATUS_CABLE_LENGTH       0x03FC
+#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
+
+/* BM PHY Copper Specific Control 1 */
+#define BM_CS_CTRL1                       16
+
+/* BM PHY Copper Specific Status */
+#define BM_CS_STATUS                      17
+#define BM_CS_STATUS_LINK_UP              0x0400
+#define BM_CS_STATUS_RESOLVED             0x0800
+#define BM_CS_STATUS_SPEED_MASK           0xC000
+#define BM_CS_STATUS_SPEED_1000           0x8000
+
+#define HV_MUX_DATA_CTRL               PHY_REG(776, 16)
+#define HV_MUX_DATA_CTRL_GEN_TO_MAC    0x0400
+#define HV_MUX_DATA_CTRL_FORCE_SPEED   0x0004
+
 /**
  *  e1000e_check_reset_block_generic - Check if PHY reset is blocked
  *  @hw: pointer to the HW structure
@@ -82,23 +134,48 @@
 s32 e1000e_get_phy_id(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
+	s32 ret_val = 0;
 	u16 phy_id;
+	u16 retry_count = 0;
 
-	ret_val = e1e_rphy(hw, PHY_ID1, &phy_id);
-	if (ret_val)
-		return ret_val;
+	if (!(phy->ops.read_phy_reg))
+		goto out;
 
-	phy->id = (u32)(phy_id << 16);
-	udelay(20);
-	ret_val = e1e_rphy(hw, PHY_ID2, &phy_id);
-	if (ret_val)
-		return ret_val;
+	while (retry_count < 2) {
+		ret_val = e1e_rphy(hw, PHY_ID1, &phy_id);
+		if (ret_val)
+			goto out;
 
-	phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
-	phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
+		phy->id = (u32)(phy_id << 16);
+		udelay(20);
+		ret_val = e1e_rphy(hw, PHY_ID2, &phy_id);
+		if (ret_val)
+			goto out;
 
-	return 0;
+		phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
+		phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
+
+		if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
+			goto out;
+
+		/*
+		 * If the PHY ID is still unknown, we may have an 82577i
+		 * without link.  We will try again after setting Slow
+		 * MDIC mode. No harm in trying again in this case since
+		 * the PHY ID is unknown at this point anyway
+		 */
+		ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
+		if (ret_val)
+			goto out;
+
+		retry_count++;
+	}
+out:
+	/* Revert to MDIO fast mode, if applicable */
+	if (retry_count)
+		ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+
+	return ret_val;
 }
 
 /**
@@ -410,6 +487,43 @@
 }
 
 /**
+ *  e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets up Carrier-sense on Transmit and downshift values.
+ **/
+s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data;
+
+	/* Enable CRS on TX. This must be set for half-duplex operation. */
+	ret_val = phy->ops.read_phy_reg(hw, I82577_CFG_REG, &phy_data);
+	if (ret_val)
+		goto out;
+
+	phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
+
+	/* Enable downshift */
+	phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
+
+	ret_val = phy->ops.write_phy_reg(hw, I82577_CFG_REG, phy_data);
+	if (ret_val)
+		goto out;
+
+	/* Set number of link attempts before downshift */
+	ret_val = phy->ops.read_phy_reg(hw, I82577_CTRL_REG, &phy_data);
+	if (ret_val)
+		goto out;
+	phy_data &= ~I82577_CTRL_DOWNSHIFT_MASK;
+	ret_val = phy->ops.write_phy_reg(hw, I82577_CTRL_REG, phy_data);
+
+out:
+	return ret_val;
+}
+
+/**
  *  e1000e_copper_link_setup_m88 - Setup m88 PHY's for copper link
  *  @hw: pointer to the HW structure
  *
@@ -427,8 +541,8 @@
 	if (ret_val)
 		return ret_val;
 
-	/* For newer PHYs this bit is downshift enable */
-	if (phy->type == e1000_phy_m88)
+	/* For BM PHY this bit is downshift enable */
+	if (phy->type != e1000_phy_bm)
 		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
 	/*
@@ -520,10 +634,27 @@
 
 	/* Commit the changes. */
 	ret_val = e1000e_commit_phy(hw);
-	if (ret_val)
+	if (ret_val) {
 		hw_dbg(hw, "Error committing the PHY changes\n");
+		return ret_val;
+	}
 
-	return ret_val;
+	if (phy->type == e1000_phy_82578) {
+		ret_val = phy->ops.read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+		                            &phy_data);
+		if (ret_val)
+			return ret_val;
+
+		/* 82578 PHY - set the downshift count to 1x. */
+		phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
+		phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
+		ret_val = phy->ops.write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+		                             phy_data);
+		if (ret_val)
+			return ret_val;
+	}
+
+	return 0;
 }
 
 /**
@@ -1251,6 +1382,8 @@
 	switch (phy->type) {
 	case e1000_phy_m88:
 	case e1000_phy_gg82563:
+	case e1000_phy_82578:
+	case e1000_phy_82577:
 		offset	= M88E1000_PHY_SPEC_STATUS;
 		mask	= M88E1000_PSSR_DOWNSHIFT;
 		break;
@@ -1398,7 +1531,12 @@
 		 */
 		ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
 		if (ret_val)
-			break;
+			/*
+			 * If the first read fails, another entity may have
+			 * ownership of the resources, wait and try again to
+			 * see if they have relinquished the resources yet.
+			 */
+			udelay(usec_interval);
 		ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
 		if (ret_val)
 			break;
@@ -1886,6 +2024,12 @@
 	case BME1000_E_PHY_ID_R2:
 		phy_type = e1000_phy_bm;
 		break;
+	case I82578_E_PHY_ID:
+		phy_type = e1000_phy_82578;
+		break;
+	case I82577_E_PHY_ID:
+		phy_type = e1000_phy_82577;
+		break;
 	default:
 		phy_type = e1000_phy_unknown;
 		break;
@@ -2181,11 +2325,16 @@
 					  u16 *data, bool read)
 {
 	s32 ret_val;
-	u16 reg = ((u16)offset) & PHY_REG_MASK;
+	u16 reg = BM_PHY_REG_NUM(offset);
 	u16 phy_reg = 0;
 	u8  phy_acquired = 1;
 
 
+	/* Gig must be disabled for MDIO accesses to page 800 */
+	if ((hw->mac.type == e1000_pchlan) &&
+	   (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
+		hw_dbg(hw, "Attempting to access page 800 while gig enabled\n");
+
 	ret_val = hw->phy.ops.acquire_phy(hw);
 	if (ret_val) {
 		phy_acquired = 0;
@@ -2289,3 +2438,529 @@
 
 	return 0;
 }
+
+s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow)
+{
+	s32 ret_val = 0;
+	u16 data = 0;
+
+	ret_val = hw->phy.ops.acquire_phy(hw);
+	if (ret_val)
+		return ret_val;
+
+	/* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */
+	hw->phy.addr = 1;
+	ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
+				         (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+	if (ret_val) {
+		hw->phy.ops.release_phy(hw);
+		return ret_val;
+	}
+	ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1,
+	                                   (0x2180 | (slow << 10)));
+
+	/* dummy read when reverting to fast mode - throw away result */
+	if (!slow)
+		e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
+
+	hw->phy.ops.release_phy(hw);
+
+	return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_hv -  Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and storing the retrieved information in data.  Release any acquired
+ *  semaphore before exiting.
+ **/
+s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+	s32 ret_val;
+	u16 page = BM_PHY_REG_PAGE(offset);
+	u16 reg = BM_PHY_REG_NUM(offset);
+	bool in_slow_mode = false;
+
+	/* Workaround failure in MDIO access while cable is disconnected */
+	if ((hw->phy.type == e1000_phy_82577) &&
+	    !(er32(STATUS) & E1000_STATUS_LU)) {
+		ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
+		if (ret_val)
+			goto out;
+
+		in_slow_mode = true;
+	}
+
+	/* Page 800 works differently than the rest so it has its own func */
+	if (page == BM_WUC_PAGE) {
+		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
+		                                         data, true);
+		goto out;
+	}
+
+	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
+		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
+		                                         data, true);
+		goto out;
+	}
+
+	ret_val = hw->phy.ops.acquire_phy(hw);
+	if (ret_val)
+		goto out;
+
+	hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+
+	if (page == HV_INTC_FC_PAGE_START)
+		page = 0;
+
+	if (reg > MAX_PHY_MULTI_PAGE_REG) {
+		if ((hw->phy.type != e1000_phy_82578) ||
+		    ((reg != I82578_ADDR_REG) &&
+		     (reg != I82578_ADDR_REG + 1))) {
+			u32 phy_addr = hw->phy.addr;
+
+			hw->phy.addr = 1;
+
+			/* Page is shifted left, PHY expects (page x 32) */
+			ret_val = e1000e_write_phy_reg_mdic(hw,
+			                             IGP01E1000_PHY_PAGE_SELECT,
+			                             (page << IGP_PAGE_SHIFT));
+			if (ret_val) {
+				hw->phy.ops.release_phy(hw);
+				goto out;
+			}
+			hw->phy.addr = phy_addr;
+		}
+	}
+
+	ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
+	                                  data);
+	hw->phy.ops.release_phy(hw);
+
+out:
+	/* Revert to MDIO fast mode, if applicable */
+	if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
+		ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+
+	return ret_val;
+}
+
+/**
+ *  e1000_write_phy_reg_hv - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+	s32 ret_val;
+	u16 page = BM_PHY_REG_PAGE(offset);
+	u16 reg = BM_PHY_REG_NUM(offset);
+	bool in_slow_mode = false;
+
+	/* Workaround failure in MDIO access while cable is disconnected */
+	if ((hw->phy.type == e1000_phy_82577) &&
+	    !(er32(STATUS) & E1000_STATUS_LU)) {
+		ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
+		if (ret_val)
+			goto out;
+
+		in_slow_mode = true;
+	}
+
+	/* Page 800 works differently than the rest so it has its own func */
+	if (page == BM_WUC_PAGE) {
+		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
+		                                         &data, false);
+		goto out;
+	}
+
+	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
+		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
+		                                         &data, false);
+		goto out;
+	}
+
+	ret_val = hw->phy.ops.acquire_phy(hw);
+	if (ret_val)
+		goto out;
+
+	hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+
+	if (page == HV_INTC_FC_PAGE_START)
+		page = 0;
+
+	/*
+	 * Workaround MDIO accesses being disabled after entering IEEE Power
+	 * Down (whenever bit 11 of the PHY Control register is set)
+	 */
+	if ((hw->phy.type == e1000_phy_82578) &&
+	    (hw->phy.revision >= 1) &&
+	    (hw->phy.addr == 2) &&
+	    ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
+	    (data & (1 << 11))) {
+		u16 data2 = 0x7EFF;
+		hw->phy.ops.release_phy(hw);
+		ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
+		                                         &data2, false);
+		if (ret_val)
+			goto out;
+
+		ret_val = hw->phy.ops.acquire_phy(hw);
+		if (ret_val)
+			goto out;
+	}
+
+	if (reg > MAX_PHY_MULTI_PAGE_REG) {
+		if ((hw->phy.type != e1000_phy_82578) ||
+		    ((reg != I82578_ADDR_REG) &&
+		     (reg != I82578_ADDR_REG + 1))) {
+			u32 phy_addr = hw->phy.addr;
+
+			hw->phy.addr = 1;
+
+			/* Page is shifted left, PHY expects (page x 32) */
+			ret_val = e1000e_write_phy_reg_mdic(hw,
+			                             IGP01E1000_PHY_PAGE_SELECT,
+			                             (page << IGP_PAGE_SHIFT));
+			if (ret_val) {
+				hw->phy.ops.release_phy(hw);
+				goto out;
+			}
+			hw->phy.addr = phy_addr;
+		}
+	}
+
+	ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
+	                                  data);
+	hw->phy.ops.release_phy(hw);
+
+out:
+	/* Revert to MDIO fast mode, if applicable */
+	if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
+		ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+
+	return ret_val;
+}
+
+/**
+ *  e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
+ *  @page: page to be accessed
+ **/
+static u32 e1000_get_phy_addr_for_hv_page(u32 page)
+{
+	u32 phy_addr = 2;
+
+	if (page >= HV_INTC_FC_PAGE_START)
+		phy_addr = 1;
+
+	return phy_addr;
+}
+
+/**
+ *  e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read or written
+ *  @data: pointer to the data to be read or written
+ *  @read: determines if operation is read or written
+ *
+ *  Acquires semaphore, if necessary, then reads the PHY register at offset
+ *  and storing the retreived information in data.  Release any acquired
+ *  semaphores before exiting.  Note that the procedure to read these regs
+ *  uses the address port and data port to read/write.
+ **/
+static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
+                                          u16 *data, bool read)
+{
+	s32 ret_val;
+	u32 addr_reg = 0;
+	u32 data_reg = 0;
+	u8  phy_acquired = 1;
+
+	/* This takes care of the difference with desktop vs mobile phy */
+	addr_reg = (hw->phy.type == e1000_phy_82578) ?
+	           I82578_ADDR_REG : I82577_ADDR_REG;
+	data_reg = addr_reg + 1;
+
+	ret_val = hw->phy.ops.acquire_phy(hw);
+	if (ret_val) {
+		hw_dbg(hw, "Could not acquire PHY\n");
+		phy_acquired = 0;
+		goto out;
+	}
+
+	/* All operations in this function are phy address 2 */
+	hw->phy.addr = 2;
+
+	/* masking with 0x3F to remove the page from offset */
+	ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
+	if (ret_val) {
+		hw_dbg(hw, "Could not write PHY the HV address register\n");
+		goto out;
+	}
+
+	/* Read or write the data value next */
+	if (read)
+		ret_val = e1000e_read_phy_reg_mdic(hw, data_reg, data);
+	else
+		ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
+
+	if (ret_val) {
+		hw_dbg(hw, "Could not read data value from HV data register\n");
+		goto out;
+	}
+
+out:
+	if (phy_acquired == 1)
+		hw->phy.ops.release_phy(hw);
+	return ret_val;
+}
+
+/**
+ *  e1000_link_stall_workaround_hv - Si workaround
+ *  @hw: pointer to the HW structure
+ *
+ *  This function works around a Si bug where the link partner can get
+ *  a link up indication before the PHY does.  If small packets are sent
+ *  by the link partner they can be placed in the packet buffer without
+ *  being properly accounted for by the PHY and will stall preventing
+ *  further packets from being received.  The workaround is to clear the
+ *  packet buffer after the PHY detects link up.
+ **/
+s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 data;
+
+	if (hw->phy.type != e1000_phy_82578)
+		goto out;
+
+	/* Do not apply workaround if in PHY loopback bit 14 set */
+	hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &data);
+	if (data & PHY_CONTROL_LB)
+		goto out;
+
+	/* check if link is up and at 1Gbps */
+	ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data);
+	if (ret_val)
+		goto out;
+
+	data &= BM_CS_STATUS_LINK_UP |
+	        BM_CS_STATUS_RESOLVED |
+	        BM_CS_STATUS_SPEED_MASK;
+
+	if (data != (BM_CS_STATUS_LINK_UP |
+	             BM_CS_STATUS_RESOLVED |
+	             BM_CS_STATUS_SPEED_1000))
+		goto out;
+
+	mdelay(200);
+
+	/* flush the packets in the fifo buffer */
+	ret_val = hw->phy.ops.write_phy_reg(hw, HV_MUX_DATA_CTRL,
+	                                HV_MUX_DATA_CTRL_GEN_TO_MAC |
+	                                HV_MUX_DATA_CTRL_FORCE_SPEED);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.write_phy_reg(hw, HV_MUX_DATA_CTRL,
+	                                HV_MUX_DATA_CTRL_GEN_TO_MAC);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  e1000_check_polarity_82577 - Checks the polarity.
+ *  @hw: pointer to the HW structure
+ *
+ *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
+ *
+ *  Polarity is determined based on the PHY specific status register.
+ **/
+s32 e1000_check_polarity_82577(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+
+	ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_STATUS_2, &data);
+
+	if (!ret_val)
+		phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
+		                      ? e1000_rev_polarity_reversed
+		                      : e1000_rev_polarity_normal;
+
+	return ret_val;
+}
+
+/**
+ *  e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the PHY setup function to force speed and duplex.  Clears the
+ *  auto-crossover to force MDI manually.  Waits for link and returns
+ *  successful if link up is successful, else -E1000_ERR_PHY (-2).
+ **/
+s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data;
+	bool link;
+
+	ret_val = phy->ops.read_phy_reg(hw, PHY_CONTROL, &phy_data);
+	if (ret_val)
+		goto out;
+
+	e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
+
+	ret_val = phy->ops.write_phy_reg(hw, PHY_CONTROL, phy_data);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * Clear Auto-Crossover to force MDI manually.  82577 requires MDI
+	 * forced whenever speed and duplex are forced.
+	 */
+	ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_CTRL_2, &phy_data);
+	if (ret_val)
+		goto out;
+
+	phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX;
+	phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX;
+
+	ret_val = phy->ops.write_phy_reg(hw, I82577_PHY_CTRL_2, phy_data);
+	if (ret_val)
+		goto out;
+
+	hw_dbg(hw, "I82577_PHY_CTRL_2: %X\n", phy_data);
+
+	udelay(1);
+
+	if (phy->autoneg_wait_to_complete) {
+		hw_dbg(hw, "Waiting for forced speed/duplex link on 82577 phy\n");
+
+		ret_val = e1000e_phy_has_link_generic(hw,
+		                                     PHY_FORCE_LIMIT,
+		                                     100000,
+		                                     &link);
+		if (ret_val)
+			goto out;
+
+		if (!link)
+			hw_dbg(hw, "Link taking longer than expected.\n");
+
+		/* Try once more */
+		ret_val = e1000e_phy_has_link_generic(hw,
+		                                     PHY_FORCE_LIMIT,
+		                                     100000,
+		                                     &link);
+		if (ret_val)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  e1000_get_phy_info_82577 - Retrieve I82577 PHY information
+ *  @hw: pointer to the HW structure
+ *
+ *  Read PHY status to determine if link is up.  If link is up, then
+ *  set/determine 10base-T extended distance and polarity correction.  Read
+ *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
+ *  determine on the cable length, local and remote receiver.
+ **/
+s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+	bool link;
+
+	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+	if (ret_val)
+		goto out;
+
+	if (!link) {
+		hw_dbg(hw, "Phy info is only valid if link is up\n");
+		ret_val = -E1000_ERR_CONFIG;
+		goto out;
+	}
+
+	phy->polarity_correction = true;
+
+	ret_val = e1000_check_polarity_82577(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_STATUS_2, &data);
+	if (ret_val)
+		goto out;
+
+	phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false;
+
+	if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
+	    I82577_PHY_STATUS2_SPEED_1000MBPS) {
+		ret_val = hw->phy.ops.get_cable_length(hw);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.read_phy_reg(hw, PHY_1000T_STATUS, &data);
+		if (ret_val)
+			goto out;
+
+		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
+		                ? e1000_1000t_rx_status_ok
+		                : e1000_1000t_rx_status_not_ok;
+
+		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
+		                 ? e1000_1000t_rx_status_ok
+		                 : e1000_1000t_rx_status_not_ok;
+	} else {
+		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
+		phy->local_rx = e1000_1000t_rx_status_undefined;
+		phy->remote_rx = e1000_1000t_rx_status_undefined;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
+ *  @hw: pointer to the HW structure
+ *
+ * Reads the diagnostic status register and verifies result is valid before
+ * placing it in the phy_cable_length field.
+ **/
+s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data, length;
+
+	ret_val = phy->ops.read_phy_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
+	if (ret_val)
+		goto out;
+
+	length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
+	         I82577_DSTATUS_CABLE_LENGTH_SHIFT;
+
+	if (length == E1000_CABLE_LENGTH_UNDEFINED)
+		ret_val = E1000_ERR_PHY;
+
+	phy->cable_length = length;
+
+out:
+	return ret_val;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/e100.c linux-libre-2.6.31-gnu/drivers/net/e100.c
--- linux-libre-2.6.30-gnu/drivers/net/e100.c	2012-03-22 19:14:57.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/e100.c	2012-03-22 20:11:07.000000000 -0400
@@ -143,6 +143,8 @@
  *	FIXES:
  * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com>
  *	- Stratus87247: protect MDI control register manipulations
+ * 2009/06/01 - Andreas Mohr <andi at lisas dot de>
+ *      - add clean lowlevel I/O emulation for cards with MII-lacking PHYs
  */
 
 #include <linux/module.h>
@@ -370,6 +372,7 @@
 
 enum eeprom_offsets {
 	eeprom_cnfg_mdix  = 0x03,
+	eeprom_phy_iface  = 0x06,
 	eeprom_id         = 0x0A,
 	eeprom_config_asf = 0x0D,
 	eeprom_smbus_addr = 0x90,
@@ -379,6 +382,18 @@
 	eeprom_mdix_enabled = 0x0080,
 };
 
+enum eeprom_phy_iface {
+	NoSuchPhy = 0,
+	I82553AB,
+	I82553C,
+	I82503,
+	DP83840,
+	S80C240,
+	S80C24,
+	I82555,
+	DP83840A = 10,
+};
+
 enum eeprom_id {
 	eeprom_id_wol = 0x0020,
 };
@@ -543,6 +558,7 @@
 	u32 msg_enable				____cacheline_aligned;
 	struct net_device *netdev;
 	struct pci_dev *pdev;
+	u16 (*mdio_ctrl)(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data);
 
 	struct rx *rxs				____cacheline_aligned;
 	struct rx *rx_to_use;
@@ -897,7 +913,21 @@
 	return err;
 }
 
-static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
+static int mdio_read(struct net_device *netdev, int addr, int reg)
+{
+	struct nic *nic = netdev_priv(netdev);
+	return nic->mdio_ctrl(nic, addr, mdi_read, reg, 0);
+}
+
+static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
+{
+	struct nic *nic = netdev_priv(netdev);
+
+	nic->mdio_ctrl(nic, addr, mdi_write, reg, data);
+}
+
+/* the standard mdio_ctrl() function for usual MII-compliant hardware */
+static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
 {
 	u32 data_out = 0;
 	unsigned int i;
@@ -936,30 +966,83 @@
 	return (u16)data_out;
 }
 
-static int mdio_read(struct net_device *netdev, int addr, int reg)
+/* slightly tweaked mdio_ctrl() function for phy_82552_v specifics */
+static u16 mdio_ctrl_phy_82552_v(struct nic *nic,
+				 u32 addr,
+				 u32 dir,
+				 u32 reg,
+				 u16 data)
 {
-	return mdio_ctrl(netdev_priv(netdev), addr, mdi_read, reg, 0);
+	if ((reg == MII_BMCR) && (dir == mdi_write)) {
+		if (data & (BMCR_ANRESTART | BMCR_ANENABLE)) {
+			u16 advert = mdio_read(nic->netdev, nic->mii.phy_id,
+							MII_ADVERTISE);
+
+			/*
+			 * Workaround Si issue where sometimes the part will not
+			 * autoneg to 100Mbps even when advertised.
+			 */
+			if (advert & ADVERTISE_100FULL)
+				data |= BMCR_SPEED100 | BMCR_FULLDPLX;
+			else if (advert & ADVERTISE_100HALF)
+				data |= BMCR_SPEED100;
+		}
+	}
+	return mdio_ctrl_hw(nic, addr, dir, reg, data);
 }
 
-static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
+/* Fully software-emulated mdio_ctrl() function for cards without
+ * MII-compliant PHYs.
+ * For now, this is mainly geared towards 80c24 support; in case of further
+ * requirements for other types (i82503, ...?) either extend this mechanism
+ * or split it, whichever is cleaner.
+ */
+static u16 mdio_ctrl_phy_mii_emulated(struct nic *nic,
+				      u32 addr,
+				      u32 dir,
+				      u32 reg,
+				      u16 data)
 {
-	struct nic *nic = netdev_priv(netdev);
-
-	if  ((nic->phy == phy_82552_v) && (reg == MII_BMCR) &&
-	     (data & (BMCR_ANRESTART | BMCR_ANENABLE))) {
-		u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
+	/* might need to allocate a netdev_priv'ed register array eventually
+	 * to be able to record state changes, but for now
+	 * some fully hardcoded register handling ought to be ok I guess. */
 
-		/*
-		 * Workaround Si issue where sometimes the part will not
-		 * autoneg to 100Mbps even when advertised.
-		 */
-		if (advert & ADVERTISE_100FULL)
-			data |= BMCR_SPEED100 | BMCR_FULLDPLX;
-		else if (advert & ADVERTISE_100HALF)
-			data |= BMCR_SPEED100;
+	if (dir == mdi_read) {
+		switch (reg) {
+		case MII_BMCR:
+			/* Auto-negotiation, right? */
+			return  BMCR_ANENABLE |
+				BMCR_FULLDPLX;
+		case MII_BMSR:
+			return	BMSR_LSTATUS /* for mii_link_ok() */ |
+				BMSR_ANEGCAPABLE |
+				BMSR_10FULL;
+		case MII_ADVERTISE:
+			/* 80c24 is a "combo card" PHY, right? */
+			return	ADVERTISE_10HALF |
+				ADVERTISE_10FULL;
+		default:
+			DPRINTK(HW, DEBUG,
+		"%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
+		dir == mdi_read ? "READ" : "WRITE", addr, reg, data);
+			return 0xFFFF;
+		}
+	} else {
+		switch (reg) {
+		default:
+			DPRINTK(HW, DEBUG,
+		"%s:addr=%d, reg=%d, data=0x%04X: unimplemented emulation!\n",
+		dir == mdi_read ? "READ" : "WRITE", addr, reg, data);
+			return 0xFFFF;
+		}
 	}
-
-	mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data);
+}
+static inline int e100_phy_supports_mii(struct nic *nic)
+{
+	/* for now, just check it by comparing whether we
+	   are using MII software emulation.
+	*/
+	return (nic->mdio_ctrl != mdio_ctrl_phy_mii_emulated);
 }
 
 static void e100_get_defaults(struct nic *nic)
@@ -1011,7 +1094,8 @@
 	config->standard_stat_counter = 0x1;	/* 1=standard, 0=extended */
 	config->rx_discard_short_frames = 0x1;	/* 1=discard, 0=pass */
 	config->tx_underrun_retry = 0x3;	/* # of underrun retries */
-	config->mii_mode = 0x1;			/* 1=MII mode, 0=503 mode */
+	if (e100_phy_supports_mii(nic))
+		config->mii_mode = 1;           /* 1=MII mode, 0=i82503 mode */
 	config->pad10 = 0x6;
 	config->no_source_addr_insertion = 0x1;	/* 1=no, 0=yes */
 	config->preamble_length = 0x2;		/* 0=1, 1=3, 2=7, 3=15 bytes */
@@ -1269,6 +1353,42 @@
 		offsetof(struct mem, dump_buf));
 }
 
+static int e100_phy_check_without_mii(struct nic *nic)
+{
+	u8 phy_type;
+	int without_mii;
+
+	phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f;
+
+	switch (phy_type) {
+	case NoSuchPhy: /* Non-MII PHY; UNTESTED! */
+	case I82503: /* Non-MII PHY; UNTESTED! */
+	case S80C24: /* Non-MII PHY; tested and working */
+		/* paragraph from the FreeBSD driver, "FXP_PHY_80C24":
+		 * The Seeq 80c24 AutoDUPLEX(tm) Ethernet Interface Adapter
+		 * doesn't have a programming interface of any sort.  The
+		 * media is sensed automatically based on how the link partner
+		 * is configured.  This is, in essence, manual configuration.
+		 */
+		DPRINTK(PROBE, INFO,
+			 "found MII-less i82503 or 80c24 or other PHY\n");
+
+		nic->mdio_ctrl = mdio_ctrl_phy_mii_emulated;
+		nic->mii.phy_id = 0; /* is this ok for an MII-less PHY? */
+
+		/* these might be needed for certain MII-less cards...
+		 * nic->flags |= ich;
+		 * nic->flags |= ich_10h_workaround; */
+
+		without_mii = 1;
+		break;
+	default:
+		without_mii = 0;
+		break;
+	}
+	return without_mii;
+}
+
 #define NCONFIG_AUTO_SWITCH	0x0080
 #define MII_NSC_CONG		MII_RESV1
 #define NSC_CONG_ENABLE		0x0100
@@ -1289,9 +1409,21 @@
 		if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
 			break;
 	}
-	DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
-	if (addr == 32)
-		return -EAGAIN;
+	if (addr == 32) {
+		/* uhoh, no PHY detected: check whether we seem to be some
+		 * weird, rare variant which is *known* to not have any MII.
+		 * But do this AFTER MII checking only, since this does
+		 * lookup of EEPROM values which may easily be unreliable. */
+		if (e100_phy_check_without_mii(nic))
+			return 0; /* simply return and hope for the best */
+		else {
+			/* for unknown cases log a fatal error */
+			DPRINTK(HW, ERR,
+				"Failed to locate any known PHY, aborting.\n");
+			return -EAGAIN;
+		}
+	} else
+		DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
 
 	/* Isolate all the PHY ids */
 	for (addr = 0; addr < 32; addr++)
@@ -1319,6 +1451,9 @@
 	if (nic->phy == phy_82552_v) {
 		u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
 
+		/* assign special tweaked mdio_ctrl() function */
+		nic->mdio_ctrl = mdio_ctrl_phy_82552_v;
+
 		/* Workaround Si not advertising flow-control during autoneg */
 		advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 		mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);
@@ -1580,7 +1715,7 @@
 		/* This is a hard error - log it. */
 		DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n");
 		netif_stop_queue(netdev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	netdev->trans_start = jiffies;
@@ -1761,6 +1896,9 @@
 
 			if (ioread8(&nic->csr->scb.status) & rus_no_res)
 				nic->ru_running = RU_SUSPENDED;
+		pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
+					       sizeof(struct rfd),
+					       PCI_DMA_FROMDEVICE);
 		return -ENODATA;
 	}
 
@@ -2584,6 +2722,7 @@
 	nic->netdev = netdev;
 	nic->pdev = pdev;
 	nic->msg_enable = (1 << debug) - 1;
+	nic->mdio_ctrl = mdio_ctrl_hw;
 	pci_set_drvdata(pdev, netdev);
 
 	if ((err = pci_enable_device(pdev))) {
@@ -2758,12 +2897,13 @@
 
 static int __e100_power_off(struct pci_dev *pdev, bool wake)
 {
-	if (wake) {
+	if (wake)
 		return pci_prepare_to_sleep(pdev);
-	} else {
-		pci_wake_from_d3(pdev, false);
-		return pci_set_power_state(pdev, PCI_D3hot);
-	}
+
+	pci_wake_from_d3(pdev, false);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -2784,7 +2924,7 @@
 	/* ack any pending wake events, disable PME */
 	pci_enable_wake(pdev, 0, 0);
 
-	/* disbale reverse auto-negotiation */
+	/* disable reverse auto-negotiation */
 	if (nic->phy == phy_82552_v) {
 		u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
 		                           E100_82552_SMARTSPEED);
@@ -2821,12 +2961,13 @@
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
 
-	/* Similar to calling e100_down(), but avoids adapter I/O. */
-	e100_close(netdev);
-
-	/* Detach; put netif into a state similar to hotplug unplug. */
-	napi_enable(&nic->napi);
 	netif_device_detach(netdev);
+
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	if (netif_running(netdev))
+		e100_down(nic);
 	pci_disable_device(pdev);
 
 	/* Request a slot reset. */
diff -druN linux-libre-2.6.30-gnu/drivers/net/eepro.c linux-libre-2.6.31-gnu/drivers/net/eepro.c
--- linux-libre-2.6.30-gnu/drivers/net/eepro.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/eepro.c	2009-09-09 18:13:59.000000000 -0400
@@ -1784,7 +1784,7 @@
 		printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
 	}
 
-	for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) {
+	for (i = 0; i < MAX_EEPRO && io[i] != -1; i++) {
 		dev = alloc_etherdev(sizeof(struct eepro_local));
 		if (!dev)
 			break;
diff -druN linux-libre-2.6.30-gnu/drivers/net/eexpress.c linux-libre-2.6.31-gnu/drivers/net/eexpress.c
--- linux-libre-2.6.30-gnu/drivers/net/eexpress.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/eexpress.c	2009-09-09 18:13:59.000000000 -0400
@@ -1474,13 +1474,13 @@
 	outw(0x0000, ioaddr + 0x800c);
 	outw(0x0000, ioaddr + 0x800e);
 
-	for (i = 0; i < (sizeof(start_code)); i+=32) {
+	for (i = 0; i < ARRAY_SIZE(start_code) * 2; i+=32) {
 		int j;
 		outw(i, ioaddr + SM_PTR);
-		for (j = 0; j < 16; j+=2)
+		for (j = 0; j < 16 && (i+j)/2 < ARRAY_SIZE(start_code); j+=2)
 			outw(start_code[(i+j)/2],
 			     ioaddr+0x4000+j);
-		for (j = 0; j < 16; j+=2)
+		for (j = 0; j < 16 && (i+j+16)/2 < ARRAY_SIZE(start_code); j+=2)
 			outw(start_code[(i+j+16)/2],
 			     ioaddr+0x8000+j);
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/net/ehea/ehea.h linux-libre-2.6.31-gnu/drivers/net/ehea/ehea.h
--- linux-libre-2.6.30-gnu/drivers/net/ehea/ehea.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ehea/ehea.h	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0101"
+#define DRV_VERSION	"EHEA_0102"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -268,7 +268,7 @@
 };
 
 /*
- * Event Queue attributes, passed as paramter
+ * Event Queue attributes, passed as parameter
  */
 struct ehea_eq_attr {
 	u32 type;
diff -druN linux-libre-2.6.30-gnu/drivers/net/ehea/ehea_main.c linux-libre-2.6.31-gnu/drivers/net/ehea/ehea_main.c
--- linux-libre-2.6.30-gnu/drivers/net/ehea/ehea_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ehea/ehea_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -1545,6 +1545,9 @@
 {
 	int ret, i;
 
+	if (pr->qp)
+		netif_napi_del(&pr->napi);
+
 	ret = ehea_destroy_qp(pr->qp);
 
 	if (!ret) {
@@ -3080,7 +3083,9 @@
 	.ndo_poll_controller	= ehea_netpoll,
 #endif
 	.ndo_get_stats		= ehea_get_stats,
+	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= ehea_set_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list	= ehea_set_multicast_list,
 	.ndo_change_mtu		= ehea_change_mtu,
 	.ndo_vlan_rx_register	= ehea_vlan_rx_register,
@@ -3261,7 +3266,7 @@
 			       struct device_attribute *attr,
 			       const char *buf, size_t count)
 {
-	struct ehea_adapter *adapter = dev->driver_data;
+	struct ehea_adapter *adapter = dev_get_drvdata(dev);
 	struct ehea_port *port;
 	struct device_node *eth_dn = NULL;
 	int i;
@@ -3316,7 +3321,7 @@
 				struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	struct ehea_adapter *adapter = dev->driver_data;
+	struct ehea_adapter *adapter = dev_get_drvdata(dev);
 	struct ehea_port *port;
 	int i;
 	u32 logical_port_id;
@@ -3404,7 +3409,7 @@
 
 	adapter->pd = EHEA_PD_ID;
 
-	dev->dev.driver_data = adapter;
+	dev_set_drvdata(&dev->dev, adapter);
 
 
 	/* initialize adapter and ports */
@@ -3468,7 +3473,7 @@
 
 static int __devexit ehea_remove(struct of_device *dev)
 {
-	struct ehea_adapter *adapter = dev->dev.driver_data;
+	struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev);
 	int i;
 
 	for (i = 0; i < EHEA_MAX_PORTS; i++)
diff -druN linux-libre-2.6.30-gnu/drivers/net/enic/enic_main.c linux-libre-2.6.31-gnu/drivers/net/enic/enic_main.c
--- linux-libre-2.6.30-gnu/drivers/net/enic/enic_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/enic/enic_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -661,8 +661,6 @@
 	if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + 1)
 		netif_stop_queue(netdev);
 
-	netdev->trans_start = jiffies;
-
 	spin_unlock_irqrestore(&enic->wq_lock[0], flags);
 
 	return NETDEV_TX_OK;
diff -druN linux-libre-2.6.30-gnu/drivers/net/epic100.c linux-libre-2.6.31-gnu/drivers/net/epic100.c
--- linux-libre-2.6.30-gnu/drivers/net/epic100.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/epic100.c	2009-09-09 18:13:59.000000000 -0400
@@ -338,8 +338,7 @@
 #ifndef MODULE
 	static int printed_version;
 	if (!printed_version++)
-		printk (KERN_INFO "%s" KERN_INFO "%s",
-			version, version2);
+		printk(KERN_INFO "%s%s", version, version2);
 #endif
 
 	card_idx++;
@@ -1600,7 +1599,7 @@
 {
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
-	printk (KERN_INFO "%s" KERN_INFO "%s",
+	printk (KERN_INFO "%s%s",
 		version, version2);
 #endif
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/eql.c linux-libre-2.6.31-gnu/drivers/net/eql.c
--- linux-libre-2.6.30-gnu/drivers/net/eql.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/eql.c	2009-09-09 18:13:59.000000000 -0400
@@ -194,6 +194,7 @@
 
 	dev->type       	= ARPHRD_SLIP;
 	dev->tx_queue_len 	= 5;		/* Hands them off fast */
+	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
 }
 
 static int eql_open(struct net_device *dev)
diff -druN linux-libre-2.6.30-gnu/drivers/net/ethoc.c linux-libre-2.6.31-gnu/drivers/net/ethoc.c
--- linux-libre-2.6.30-gnu/drivers/net/ethoc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ethoc.c	2009-09-09 18:13:59.000000000 -0400
@@ -811,7 +811,7 @@
 
 	if (unlikely(skb->len > ETHOC_BUFSIZ)) {
 		priv->stats.tx_errors++;
-		return -EMSGSIZE;
+		goto out;
 	}
 
 	entry = priv->cur_tx % priv->num_tx;
@@ -840,9 +840,9 @@
 	}
 
 	dev->trans_start = jiffies;
-	dev_kfree_skb(skb);
-
 	spin_unlock_irq(&priv->lock);
+out:
+	dev_kfree_skb(skb);
 	return NETDEV_TX_OK;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ewrk3.c linux-libre-2.6.31-gnu/drivers/net/ewrk3.c
--- linux-libre-2.6.30-gnu/drivers/net/ewrk3.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ewrk3.c	2009-09-09 18:13:59.000000000 -0400
@@ -873,7 +873,7 @@
 err_out:
 	ENABLE_IRQs;
 	spin_unlock_irq (&lp->hw_lock);
-	return 1;
+	return NETDEV_TX_BUSY;
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/net/fealnx.c linux-libre-2.6.31-gnu/drivers/net/fealnx.c
--- linux-libre-2.6.30-gnu/drivers/net/fealnx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fealnx.c	2009-09-09 18:13:59.000000000 -0400
@@ -584,7 +584,8 @@
 	if (np->flags == HAS_MII_XCVR) {
 		int phy, phy_idx = 0;
 
-		for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
+		for (phy = 1; phy < 32 && phy_idx < ARRAY_SIZE(np->phys);
+			       phy++) {
 			int mii_status = mdio_read(dev, phy, 1);
 
 			if (mii_status != 0xffff && mii_status != 0x0000) {
@@ -1209,17 +1210,20 @@
 	unsigned long flags;
 	int i;
 
-	printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
-	       " resetting...\n", dev->name, ioread32(ioaddr + ISR));
+	printk(KERN_WARNING
+	       "%s: Transmit timed out, status %8.8x, resetting...\n",
+	       dev->name, ioread32(ioaddr + ISR));
 
 	{
 		printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
 		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int) np->rx_ring[i].status);
-		printk("\n" KERN_DEBUG "  Tx ring %p: ", np->tx_ring);
+			printk(KERN_CONT " %8.8x",
+			       (unsigned int) np->rx_ring[i].status);
+		printk(KERN_CONT "\n");
+		printk(KERN_DEBUG "  Tx ring %p: ", np->tx_ring);
 		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" %4.4x", np->tx_ring[i].status);
-		printk("\n");
+			printk(KERN_CONT " %4.4x", np->tx_ring[i].status);
+		printk(KERN_CONT "\n");
 	}
 
 	spin_lock_irqsave(&np->lock, flags);
diff -druN linux-libre-2.6.30-gnu/drivers/net/fec.c linux-libre-2.6.31-gnu/drivers/net/fec.c
--- linux-libre-2.6.30-gnu/drivers/net/fec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fec.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,8 +86,7 @@
 #endif
 #endif /* CONFIG_M5272 */
 
-/* Forward declarations of some structures to support different PHYs
-*/
+/* Forward declarations of some structures to support different PHYs */
 
 typedef struct {
 	uint mii_data;
@@ -123,8 +122,7 @@
 #error "FEC: descriptor ring size constants too large"
 #endif
 
-/* Interrupt events/masks.
-*/
+/* Interrupt events/masks. */
 #define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */
 #define FEC_ENET_BABR	((uint)0x40000000)	/* Babbling receiver */
 #define FEC_ENET_BABT	((uint)0x20000000)	/* Babbling transmitter */
@@ -165,7 +163,7 @@
  */
 struct fec_enet_private {
 	/* Hardware registers of the FEC device */
-	volatile fec_t	*hwp;
+	void __iomem *hwp;
 
 	struct net_device *netdev;
 
@@ -174,16 +172,20 @@
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	unsigned char *tx_bounce[TX_RING_SIZE];
 	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
+	struct	sk_buff* rx_skbuff[RX_RING_SIZE];
 	ushort	skb_cur;
 	ushort	skb_dirty;
 
-	/* CPM dual port RAM relative addresses.
-	*/
+	/* CPM dual port RAM relative addresses */
 	dma_addr_t	bd_dma;
-	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
-	cbd_t	*tx_bd_base;
-	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
-	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
+	/* Address of Rx and Tx buffers */
+	struct bufdesc	*rx_bd_base;
+	struct bufdesc	*tx_bd_base;
+	/* The next free ring entry */
+	struct bufdesc	*cur_rx, *cur_tx; 
+	/* The ring entries to be free()ed */
+	struct bufdesc	*dirty_tx;
+
 	uint	tx_full;
 	/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
 	spinlock_t hw_lock;
@@ -209,17 +211,13 @@
 	int	full_duplex;
 };
 
-static int fec_enet_open(struct net_device *dev);
-static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void fec_enet_mii(struct net_device *dev);
 static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
 static void fec_enet_tx(struct net_device *dev);
 static void fec_enet_rx(struct net_device *dev);
 static int fec_enet_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
 static void fec_restart(struct net_device *dev, int duplex);
 static void fec_stop(struct net_device *dev);
-static void fec_set_mac_address(struct net_device *dev);
 
 
 /* MII processing.  We keep this as simple as possible.  Requests are
@@ -241,19 +239,16 @@
 static int	mii_queue(struct net_device *dev, int request,
 				void (*func)(uint, struct net_device *));
 
-/* Make MII read/write commands for the FEC.
-*/
+/* Make MII read/write commands for the FEC */
 #define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
 #define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | \
 						(VAL & 0xffff))
 #define mk_mii_end	0
 
-/* Transmitter timeout.
-*/
-#define TX_TIMEOUT (2*HZ)
+/* Transmitter timeout */
+#define TX_TIMEOUT (2 * HZ)
 
-/* Register definitions for the PHY.
-*/
+/* Register definitions for the PHY */
 
 #define MII_REG_CR          0  /* Control Register                         */
 #define MII_REG_SR          1  /* Status Register                          */
@@ -288,18 +283,15 @@
 static int
 fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct fec_enet_private *fep;
-	volatile fec_t	*fecp;
-	volatile cbd_t	*bdp;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	struct bufdesc *bdp;
+	void *bufaddr;
 	unsigned short	status;
 	unsigned long flags;
 
-	fep = netdev_priv(dev);
-	fecp = (volatile fec_t*)dev->base_addr;
-
 	if (!fep->link) {
 		/* Link is down or autonegotiation is in progress. */
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	spin_lock_irqsave(&fep->hw_lock, flags);
@@ -307,40 +299,36 @@
 	bdp = fep->cur_tx;
 
 	status = bdp->cbd_sc;
-#ifndef final_version
+
 	if (status & BD_ENET_TX_READY) {
 		/* Ooops.  All transmit buffers are full.  Bail out.
 		 * This should not happen, since dev->tbusy should be set.
 		 */
 		printk("%s: tx queue full!.\n", dev->name);
 		spin_unlock_irqrestore(&fep->hw_lock, flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
-#endif
 
-	/* Clear all of the status flags.
-	 */
+	/* Clear all of the status flags */
 	status &= ~BD_ENET_TX_STATS;
 
-	/* Set buffer length and buffer pointer.
-	*/
-	bdp->cbd_bufaddr = __pa(skb->data);
+	/* Set buffer length and buffer pointer */
+	bufaddr = skb->data;
 	bdp->cbd_datlen = skb->len;
 
 	/*
-	 *	On some FEC implementations data must be aligned on
-	 *	4-byte boundaries. Use bounce buffers to copy data
-	 *	and get it aligned. Ugh.
+	 * On some FEC implementations data must be aligned on
+	 * 4-byte boundaries. Use bounce buffers to copy data
+	 * and get it aligned. Ugh.
 	 */
-	if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+	if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
 		unsigned int index;
 		index = bdp - fep->tx_bd_base;
 		memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
-		bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+		bufaddr = fep->tx_bounce[index];
 	}
 
-	/* Save skb pointer.
-	*/
+	/* Save skb pointer */
 	fep->tx_skbuff[fep->skb_cur] = skb;
 
 	dev->stats.tx_bytes += skb->len;
@@ -349,13 +337,12 @@
 	/* Push the data cache so the CPM does not get stale memory
 	 * data.
 	 */
-	dma_sync_single(NULL, bdp->cbd_bufaddr,
-			bdp->cbd_datlen, DMA_TO_DEVICE);
+	bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
+			FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
 	 */
-
 	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
 			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
 	bdp->cbd_sc = status;
@@ -363,22 +350,20 @@
 	dev->trans_start = jiffies;
 
 	/* Trigger transmission start */
-	fecp->fec_x_des_active = 0;
+	writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
-	/* If this was the last BD in the ring, start at the beginning again.
-	*/
-	if (status & BD_ENET_TX_WRAP) {
+	/* If this was the last BD in the ring, start at the beginning again. */
+	if (status & BD_ENET_TX_WRAP)
 		bdp = fep->tx_bd_base;
-	} else {
+	else
 		bdp++;
-	}
 
 	if (bdp == fep->dirty_tx) {
 		fep->tx_full = 1;
 		netif_stop_queue(dev);
 	}
 
-	fep->cur_tx = (cbd_t *)bdp;
+	fep->cur_tx = bdp;
 
 	spin_unlock_irqrestore(&fep->hw_lock, flags);
 
@@ -390,75 +375,33 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 
-	printk("%s: transmit timed out.\n", dev->name);
 	dev->stats.tx_errors++;
-#ifndef final_version
-	{
-	int	i;
-	cbd_t	*bdp;
-
-	printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n",
-	       (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "",
-	       (unsigned long)fep->dirty_tx,
-	       (unsigned long)fep->cur_rx);
 
-	bdp = fep->tx_bd_base;
-	printk(" tx: %u buffers\n",  TX_RING_SIZE);
-	for (i = 0 ; i < TX_RING_SIZE; i++) {
-		printk("  %08x: %04x %04x %08x\n",
-		       (uint) bdp,
-		       bdp->cbd_sc,
-		       bdp->cbd_datlen,
-		       (int) bdp->cbd_bufaddr);
-		bdp++;
-	}
-
-	bdp = fep->rx_bd_base;
-	printk(" rx: %lu buffers\n",  (unsigned long) RX_RING_SIZE);
-	for (i = 0 ; i < RX_RING_SIZE; i++) {
-		printk("  %08x: %04x %04x %08x\n",
-		       (uint) bdp,
-		       bdp->cbd_sc,
-		       bdp->cbd_datlen,
-		       (int) bdp->cbd_bufaddr);
-		bdp++;
-	}
-	}
-#endif
 	fec_restart(dev, fep->full_duplex);
 	netif_wake_queue(dev);
 }
 
-/* The interrupt handler.
- * This is called from the MPC core interrupt.
- */
 static irqreturn_t
 fec_enet_interrupt(int irq, void * dev_id)
 {
 	struct	net_device *dev = dev_id;
-	volatile fec_t	*fecp;
+	struct fec_enet_private *fep = netdev_priv(dev);
 	uint	int_events;
 	irqreturn_t ret = IRQ_NONE;
 
-	fecp = (volatile fec_t*)dev->base_addr;
-
-	/* Get the interrupt events that caused us to be here.
-	*/
 	do {
-		int_events = fecp->fec_ievent;
-		fecp->fec_ievent = int_events;
+		int_events = readl(fep->hwp + FEC_IEVENT);
+		writel(int_events, fep->hwp + FEC_IEVENT);
 
-		/* Handle receive event in its own function.
-		 */
 		if (int_events & FEC_ENET_RXF) {
 			ret = IRQ_HANDLED;
 			fec_enet_rx(dev);
 		}
 
 		/* Transmit OK, or non-fatal error. Update the buffer
-		   descriptors. FEC handles all errors, we just discover
-		   them as part of the transmit process.
-		*/
+		 * descriptors. FEC handles all errors, we just discover
+		 * them as part of the transmit process.
+		 */
 		if (int_events & FEC_ENET_TXF) {
 			ret = IRQ_HANDLED;
 			fec_enet_tx(dev);
@@ -479,7 +422,7 @@
 fec_enet_tx(struct net_device *dev)
 {
 	struct	fec_enet_private *fep;
-	volatile cbd_t	*bdp;
+	struct bufdesc *bdp;
 	unsigned short status;
 	struct	sk_buff	*skb;
 
@@ -488,7 +431,11 @@
 	bdp = fep->dirty_tx;
 
 	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
-		if (bdp == fep->cur_tx && fep->tx_full == 0) break;
+		if (bdp == fep->cur_tx && fep->tx_full == 0)
+			break;
+
+		dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+		bdp->cbd_bufaddr = 0;
 
 		skb = fep->tx_skbuff[fep->skb_dirty];
 		/* Check for errors. */
@@ -510,31 +457,27 @@
 			dev->stats.tx_packets++;
 		}
 
-#ifndef final_version
 		if (status & BD_ENET_TX_READY)
 			printk("HEY! Enet xmit interrupt and TX_READY.\n");
-#endif
+
 		/* Deferred means some collisions occurred during transmit,
 		 * but we eventually sent the packet OK.
 		 */
 		if (status & BD_ENET_TX_DEF)
 			dev->stats.collisions++;
 
-		/* Free the sk buffer associated with this last transmit.
-		 */
+		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
 		fep->tx_skbuff[fep->skb_dirty] = NULL;
 		fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;
 
-		/* Update pointer to next buffer descriptor to be transmitted.
-		 */
+		/* Update pointer to next buffer descriptor to be transmitted */
 		if (status & BD_ENET_TX_WRAP)
 			bdp = fep->tx_bd_base;
 		else
 			bdp++;
 
-		/* Since we have freed up a buffer, the ring is no longer
-		 * full.
+		/* Since we have freed up a buffer, the ring is no longer full
 		 */
 		if (fep->tx_full) {
 			fep->tx_full = 0;
@@ -542,7 +485,7 @@
 				netif_wake_queue(dev);
 		}
 	}
-	fep->dirty_tx = (cbd_t *)bdp;
+	fep->dirty_tx = bdp;
 	spin_unlock_irq(&fep->hw_lock);
 }
 
@@ -555,9 +498,8 @@
 static void
 fec_enet_rx(struct net_device *dev)
 {
-	struct	fec_enet_private *fep;
-	volatile fec_t	*fecp;
-	volatile cbd_t *bdp;
+	struct	fec_enet_private *fep = netdev_priv(dev);
+	struct bufdesc *bdp;
 	unsigned short status;
 	struct	sk_buff	*skb;
 	ushort	pkt_len;
@@ -567,9 +509,6 @@
 	flush_cache_all();
 #endif
 
-	fep = netdev_priv(dev);
-	fecp = (volatile fec_t*)dev->base_addr;
-
 	spin_lock_irq(&fep->hw_lock);
 
 	/* First, grab all of the stats for the incoming packet.
@@ -577,143 +516,121 @@
 	 */
 	bdp = fep->cur_rx;
 
-while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
+	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
 
-#ifndef final_version
-	/* Since we have allocated space to hold a complete frame,
-	 * the last indicator should be set.
-	 */
-	if ((status & BD_ENET_RX_LAST) == 0)
-		printk("FEC ENET: rcv is not +last\n");
-#endif
+		/* Since we have allocated space to hold a complete frame,
+		 * the last indicator should be set.
+		 */
+		if ((status & BD_ENET_RX_LAST) == 0)
+			printk("FEC ENET: rcv is not +last\n");
 
-	if (!fep->opened)
-		goto rx_processing_done;
+		if (!fep->opened)
+			goto rx_processing_done;
 
-	/* Check for errors. */
-	if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
+		/* Check for errors. */
+		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
 			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-		dev->stats.rx_errors++;
-		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
-		/* Frame too long or too short. */
-			dev->stats.rx_length_errors++;
+			dev->stats.rx_errors++;
+			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
+				/* Frame too long or too short. */
+				dev->stats.rx_length_errors++;
+			}
+			if (status & BD_ENET_RX_NO)	/* Frame alignment */
+				dev->stats.rx_frame_errors++;
+			if (status & BD_ENET_RX_CR)	/* CRC Error */
+				dev->stats.rx_crc_errors++;
+			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
+				dev->stats.rx_fifo_errors++;
 		}
-		if (status & BD_ENET_RX_NO)	/* Frame alignment */
-			dev->stats.rx_frame_errors++;
-		if (status & BD_ENET_RX_CR)	/* CRC Error */
-			dev->stats.rx_crc_errors++;
-		if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-			dev->stats.rx_fifo_errors++;
-	}
-
-	/* Report late collisions as a frame error.
-	 * On this error, the BD is closed, but we don't know what we
-	 * have in the buffer.  So, just drop this frame on the floor.
-	 */
-	if (status & BD_ENET_RX_CL) {
-		dev->stats.rx_errors++;
-		dev->stats.rx_frame_errors++;
-		goto rx_processing_done;
-	}
 
-	/* Process the incoming frame.
-	 */
-	dev->stats.rx_packets++;
-	pkt_len = bdp->cbd_datlen;
-	dev->stats.rx_bytes += pkt_len;
-	data = (__u8*)__va(bdp->cbd_bufaddr);
-
-	dma_sync_single(NULL, (unsigned long)__pa(data),
-			pkt_len - 4, DMA_FROM_DEVICE);
+		/* Report late collisions as a frame error.
+		 * On this error, the BD is closed, but we don't know what we
+		 * have in the buffer.  So, just drop this frame on the floor.
+		 */
+		if (status & BD_ENET_RX_CL) {
+			dev->stats.rx_errors++;
+			dev->stats.rx_frame_errors++;
+			goto rx_processing_done;
+		}
 
-	/* This does 16 byte alignment, exactly what we need.
-	 * The packet length includes FCS, but we don't want to
-	 * include that when passing upstream as it messes up
-	 * bridging applications.
-	 */
-	skb = dev_alloc_skb(pkt_len-4);
+		/* Process the incoming frame. */
+		dev->stats.rx_packets++;
+		pkt_len = bdp->cbd_datlen;
+		dev->stats.rx_bytes += pkt_len;
+		data = (__u8*)__va(bdp->cbd_bufaddr);
 
-	if (skb == NULL) {
-		printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-		dev->stats.rx_dropped++;
-	} else {
-		skb_put(skb,pkt_len-4);	/* Make room */
-		skb_copy_to_linear_data(skb, data, pkt_len-4);
-		skb->protocol=eth_type_trans(skb,dev);
-		netif_rx(skb);
-	}
-  rx_processing_done:
+	        dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
+        			DMA_FROM_DEVICE);
 
-	/* Clear the status flags for this buffer.
-	*/
-	status &= ~BD_ENET_RX_STATS;
+		/* This does 16 byte alignment, exactly what we need.
+		 * The packet length includes FCS, but we don't want to
+		 * include that when passing upstream as it messes up
+		 * bridging applications.
+		 */
+		skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN);
 
-	/* Mark the buffer empty.
-	*/
-	status |= BD_ENET_RX_EMPTY;
-	bdp->cbd_sc = status;
+		if (unlikely(!skb)) {
+			printk("%s: Memory squeeze, dropping packet.\n",
+					dev->name);
+			dev->stats.rx_dropped++;
+		} else {
+			skb_reserve(skb, NET_IP_ALIGN);
+			skb_put(skb, pkt_len - 4);	/* Make room */
+			skb_copy_to_linear_data(skb, data, pkt_len - 4);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+		}
 
-	/* Update BD pointer to next entry.
-	*/
-	if (status & BD_ENET_RX_WRAP)
-		bdp = fep->rx_bd_base;
-	else
-		bdp++;
+        	bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
+			DMA_FROM_DEVICE);
+rx_processing_done:
+		/* Clear the status flags for this buffer */
+		status &= ~BD_ENET_RX_STATS;
 
-#if 1
-	/* Doing this here will keep the FEC running while we process
-	 * incoming frames.  On a heavily loaded network, we should be
-	 * able to keep up at the expense of system resources.
-	 */
-	fecp->fec_r_des_active = 0;
-#endif
-   } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */
-	fep->cur_rx = (cbd_t *)bdp;
+		/* Mark the buffer empty */
+		status |= BD_ENET_RX_EMPTY;
+		bdp->cbd_sc = status;
 
-#if 0
-	/* Doing this here will allow us to process all frames in the
-	 * ring before the FEC is allowed to put more there.  On a heavily
-	 * loaded network, some frames may be lost.  Unfortunately, this
-	 * increases the interrupt overhead since we can potentially work
-	 * our way back to the interrupt return only to come right back
-	 * here.
-	 */
-	fecp->fec_r_des_active = 0;
-#endif
+		/* Update BD pointer to next entry */
+		if (status & BD_ENET_RX_WRAP)
+			bdp = fep->rx_bd_base;
+		else
+			bdp++;
+		/* Doing this here will keep the FEC running while we process
+		 * incoming frames.  On a heavily loaded network, we should be
+		 * able to keep up at the expense of system resources.
+		 */
+		writel(0, fep->hwp + FEC_R_DES_ACTIVE);
+	}
+	fep->cur_rx = bdp;
 
 	spin_unlock_irq(&fep->hw_lock);
 }
 
-
 /* called from interrupt context */
 static void
 fec_enet_mii(struct net_device *dev)
 {
 	struct	fec_enet_private *fep;
-	volatile fec_t	*ep;
 	mii_list_t	*mip;
-	uint		mii_reg;
 
 	fep = netdev_priv(dev);
 	spin_lock_irq(&fep->mii_lock);
 
-	ep = fep->hwp;
-	mii_reg = ep->fec_mii_data;
-
 	if ((mip = mii_head) == NULL) {
 		printk("MII and no head!\n");
 		goto unlock;
 	}
 
 	if (mip->mii_func != NULL)
-		(*(mip->mii_func))(mii_reg, dev);
+		(*(mip->mii_func))(readl(fep->hwp + FEC_MII_DATA), dev);
 
 	mii_head = mip->mii_next;
 	mip->mii_next = mii_free;
 	mii_free = mip;
 
 	if ((mip = mii_head) != NULL)
-		ep->fec_mii_data = mip->mii_regval;
+		writel(mip->mii_regval, fep->hwp + FEC_MII_DATA);
 
 unlock:
 	spin_unlock_irq(&fep->mii_lock);
@@ -727,8 +644,7 @@
 	mii_list_t	*mip;
 	int		retval;
 
-	/* Add PHY address to register command.
-	*/
+	/* Add PHY address to register command */
 	fep = netdev_priv(dev);
 	spin_lock_irqsave(&fep->mii_lock, flags);
 
@@ -745,7 +661,7 @@
 			mii_tail = mip;
 		} else {
 			mii_head = mii_tail = mip;
-			fep->hwp->fec_mii_data = regval;
+			writel(regval, fep->hwp + FEC_MII_DATA);
 		}
 	} else {
 		retval = 1;
@@ -1246,11 +1162,8 @@
 static void __inline__ fec_get_mac(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile fec_t *fecp;
 	unsigned char *iap, tmpaddr[ETH_ALEN];
 
-	fecp = fep->hwp;
-
 	if (FEC_FLASHMAC) {
 		/*
 		 * Get MAC address from FLASH.
@@ -1264,8 +1177,8 @@
 		    (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
 			iap = fec_mac_default;
 	} else {
-		*((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;
-		*((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);
+		*((unsigned long *) &tmpaddr[0]) = readl(fep->hwp + FEC_ADDR_LOW);
+		*((unsigned short *) &tmpaddr[4]) = (readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
 		iap = &tmpaddr[0];
 	}
 
@@ -1375,11 +1288,6 @@
 		fec_restart(dev, duplex);
 	} else
 		fec_stop(dev);
-
-#if 0
-	enable_irq(fep->mii_irq);
-#endif
-
 }
 
 /* mii_queue_relink is called in interrupt context from mii_link_interrupt */
@@ -1388,12 +1296,12 @@
 	struct fec_enet_private *fep = netdev_priv(dev);
 
 	/*
-	** We cannot queue phy_task twice in the workqueue.  It
-	** would cause an endless loop in the workqueue.
-	** Fortunately, if the last mii_relink entry has not yet been
-	** executed now, it will do the job for the current interrupt,
-	** which is just what we want.
-	*/
+	 * We cannot queue phy_task twice in the workqueue.  It
+	 * would cause an endless loop in the workqueue.
+	 * Fortunately, if the last mii_relink entry has not yet been
+	 * executed now, it will do the job for the current interrupt,
+	 * which is just what we want.
+	 */
 	if (fep->mii_phy_task_queued)
 		return;
 
@@ -1424,8 +1332,7 @@
 	{ mk_mii_end, }
 	};
 
-/* Read remainder of PHY ID.
-*/
+/* Read remainder of PHY ID. */
 static void
 mii_discover_phy3(uint mii_reg, struct net_device *dev)
 {
@@ -1457,17 +1364,14 @@
 mii_discover_phy(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep;
-	volatile fec_t *fecp;
 	uint phytype;
 
 	fep = netdev_priv(dev);
-	fecp = fep->hwp;
 
 	if (fep->phy_addr < 32) {
 		if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) {
 
-			/* Got first part of ID, now get remainder.
-			*/
+			/* Got first part of ID, now get remainder */
 			fep->phy_id = phytype << 16;
 			mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
 							mii_discover_phy3);
@@ -1479,15 +1383,15 @@
 	} else {
 		printk("FEC: No PHY device found.\n");
 		/* Disable external MII interface */
-		fecp->fec_mii_speed = fep->phy_speed = 0;
+		writel(0, fep->hwp + FEC_MII_SPEED);
+		fep->phy_speed = 0;
 #ifdef HAVE_mii_link_interrupt
 		fec_disable_phy_intr();
 #endif
 	}
 }
 
-/* This interrupt occurs when the PHY detects a link change.
-*/
+/* This interrupt occurs when the PHY detects a link change */
 #ifdef HAVE_mii_link_interrupt
 static irqreturn_t
 mii_link_interrupt(int irq, void * dev_id)
@@ -1497,10 +1401,6 @@
 
 	fec_phy_ack_intr();
 
-#if 0
-	disable_irq(fep->mii_irq);  /* disable now, enable later */
-#endif
-
 	mii_do_cmd(dev, fep->phy->ack_int);
 	mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
 
@@ -1508,19 +1408,91 @@
 }
 #endif
 
+static void fec_enet_free_buffers(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+	int i;
+	struct sk_buff *skb;
+	struct bufdesc	*bdp;
+
+	bdp = fep->rx_bd_base;
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		skb = fep->rx_skbuff[i];
+
+		if (bdp->cbd_bufaddr)
+			dma_unmap_single(&dev->dev, bdp->cbd_bufaddr,
+					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+		if (skb)
+			dev_kfree_skb(skb);
+		bdp++;
+	}
+
+	bdp = fep->tx_bd_base;
+	for (i = 0; i < TX_RING_SIZE; i++)
+		kfree(fep->tx_bounce[i]);
+}
+
+static int fec_enet_alloc_buffers(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+	int i;
+	struct sk_buff *skb;
+	struct bufdesc	*bdp;
+
+	bdp = fep->rx_bd_base;
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
+		if (!skb) {
+			fec_enet_free_buffers(dev);
+			return -ENOMEM;
+		}
+		fep->rx_skbuff[i] = skb;
+
+		bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+		bdp->cbd_sc = BD_ENET_RX_EMPTY;
+		bdp++;
+	}
+
+	/* Set the last buffer to wrap. */
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	bdp = fep->tx_bd_base;
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+
+		bdp->cbd_sc = 0;
+		bdp->cbd_bufaddr = 0;
+		bdp++;
+	}
+
+	/* Set the last buffer to wrap. */
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	return 0;
+}
+
 static int
 fec_enet_open(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
+	int ret;
 
 	/* I should reset the ring buffers here, but I don't yet know
 	 * a simple way to do that.
 	 */
-	fec_set_mac_address(dev);
+
+	ret = fec_enet_alloc_buffers(dev);
+	if (ret)
+		return ret;
 
 	fep->sequence_done = 0;
 	fep->link = 0;
 
+	fec_restart(dev, 1);
+
 	if (fep->phy) {
 		mii_do_cmd(dev, fep->phy->ack_int);
 		mii_do_cmd(dev, fep->phy->config);
@@ -1537,21 +1509,17 @@
 			schedule();
 
 		mii_do_cmd(dev, fep->phy->startup);
-
-		/* Set the initial link state to true. A lot of hardware
-		 * based on this device does not implement a PHY interrupt,
-		 * so we are never notified of link change.
-		 */
-		fep->link = 1;
-	} else {
-		fep->link = 1; /* lets just try it and see */
-		/* no phy,  go full duplex,  it's most likely a hub chip */
-		fec_restart(dev, 1);
 	}
 
+	/* Set the initial link state to true. A lot of hardware
+	 * based on this device does not implement a PHY interrupt,
+	 * so we are never notified of link change.
+	 */
+	fep->link = 1;
+
 	netif_start_queue(dev);
 	fep->opened = 1;
-	return 0;		/* Success */
+	return 0;
 }
 
 static int
@@ -1559,12 +1527,13 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 
-	/* Don't know what to do yet.
-	*/
+	/* Don't know what to do yet. */
 	fep->opened = 0;
 	netif_stop_queue(dev);
 	fec_stop(dev);
 
+        fec_enet_free_buffers(dev);
+
 	return 0;
 }
 
@@ -1583,87 +1552,103 @@
 
 static void set_multicast_list(struct net_device *dev)
 {
-	struct fec_enet_private *fep;
-	volatile fec_t *ep;
+	struct fec_enet_private *fep = netdev_priv(dev);
 	struct dev_mc_list *dmi;
-	unsigned int i, j, bit, data, crc;
+	unsigned int i, j, bit, data, crc, tmp;
 	unsigned char hash;
 
-	fep = netdev_priv(dev);
-	ep = fep->hwp;
-
-	if (dev->flags&IFF_PROMISC) {
-		ep->fec_r_cntrl |= 0x0008;
-	} else {
+	if (dev->flags & IFF_PROMISC) {
+		tmp = readl(fep->hwp + FEC_R_CNTRL);
+		tmp |= 0x8;
+		writel(tmp, fep->hwp + FEC_R_CNTRL);
+		return;
+	}
 
-		ep->fec_r_cntrl &= ~0x0008;
+	tmp = readl(fep->hwp + FEC_R_CNTRL);
+	tmp &= ~0x8;
+	writel(tmp, fep->hwp + FEC_R_CNTRL);
 
-		if (dev->flags & IFF_ALLMULTI) {
-			/* Catch all multicast addresses, so set the
-			 * filter to all 1's.
-			 */
-			ep->fec_grp_hash_table_high = 0xffffffff;
-			ep->fec_grp_hash_table_low = 0xffffffff;
-		} else {
-			/* Clear filter and add the addresses in hash register.
-			*/
-			ep->fec_grp_hash_table_high = 0;
-			ep->fec_grp_hash_table_low = 0;
+	if (dev->flags & IFF_ALLMULTI) {
+		/* Catch all multicast addresses, so set the
+		 * filter to all 1's
+		 */
+		writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+		writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 
-			dmi = dev->mc_list;
+		return;
+	}
 
-			for (j = 0; j < dev->mc_count; j++, dmi = dmi->next)
-			{
-				/* Only support group multicast for now.
-				*/
-				if (!(dmi->dmi_addr[0] & 1))
-					continue;
+	/* Clear filter and add the addresses in hash register
+	 */
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 
-				/* calculate crc32 value of mac address
-				*/
-				crc = 0xffffffff;
+	dmi = dev->mc_list;
 
-				for (i = 0; i < dmi->dmi_addrlen; i++)
-				{
-					data = dmi->dmi_addr[i];
-					for (bit = 0; bit < 8; bit++, data >>= 1)
-					{
-						crc = (crc >> 1) ^
-						(((crc ^ data) & 1) ? CRC32_POLY : 0);
-					}
-				}
+	for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) {
+		/* Only support group multicast for now */
+		if (!(dmi->dmi_addr[0] & 1))
+			continue;
 
-				/* only upper 6 bits (HASH_BITS) are used
-				   which point to specific bit in he hash registers
-				*/
-				hash = (crc >> (32 - HASH_BITS)) & 0x3f;
+		/* calculate crc32 value of mac address */
+		crc = 0xffffffff;
 
-				if (hash > 31)
-					ep->fec_grp_hash_table_high |= 1 << (hash - 32);
-				else
-					ep->fec_grp_hash_table_low |= 1 << hash;
+		for (i = 0; i < dmi->dmi_addrlen; i++) {
+			data = dmi->dmi_addr[i];
+			for (bit = 0; bit < 8; bit++, data >>= 1) {
+				crc = (crc >> 1) ^
+				(((crc ^ data) & 1) ? CRC32_POLY : 0);
 			}
 		}
+
+		/* only upper 6 bits (HASH_BITS) are used
+		 * which point to specific bit in he hash registers
+		 */
+		hash = (crc >> (32 - HASH_BITS)) & 0x3f;
+
+		if (hash > 31) {
+			tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+			tmp |= 1 << (hash - 32);
+			writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+		} else {
+			tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+			tmp |= 1 << hash;
+			writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+		}
 	}
 }
 
-/* Set a MAC change in hardware.
- */
-static void
-fec_set_mac_address(struct net_device *dev)
+/* Set a MAC change in hardware. */
+static int
+fec_set_mac_address(struct net_device *dev, void *p)
 {
-	volatile fec_t *fecp;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	struct sockaddr *addr = p;
 
-	fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
 
-	/* Set station address. */
-	fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
-		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
-	fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
-		(dev->dev_addr[4] << 24);
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
+	writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
+		fep->hwp + FEC_ADDR_LOW);
+	writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
+		fep + FEC_ADDR_HIGH);
+	return 0;
 }
 
+static const struct net_device_ops fec_netdev_ops = {
+	.ndo_open		= fec_enet_open,
+	.ndo_stop		= fec_enet_close,
+	.ndo_start_xmit		= fec_enet_start_xmit,
+	.ndo_set_multicast_list = set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_tx_timeout		= fec_timeout,
+	.ndo_set_mac_address	= fec_set_mac_address,
+};
+
  /*
   * XXX:  We need to clean up on failure exits here.
   *
@@ -1672,17 +1657,13 @@
 int __init fec_enet_init(struct net_device *dev, int index)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	unsigned long	mem_addr;
-	volatile cbd_t	*bdp;
-	cbd_t		*cbd_base;
-	volatile fec_t	*fecp;
-	int 		i, j;
+	struct bufdesc *cbd_base;
+	int i;
 
-	/* Allocate memory for buffer descriptors.
-	*/
-	mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE,
-			&fep->bd_dma, GFP_KERNEL);
-	if (mem_addr == 0) {
+	/* Allocate memory for buffer descriptors. */
+	cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
+			GFP_KERNEL);
+	if (!cbd_base) {
 		printk("FEC: allocate descriptor memory failed?\n");
 		return -ENOMEM;
 	}
@@ -1690,146 +1671,47 @@
 	spin_lock_init(&fep->hw_lock);
 	spin_lock_init(&fep->mii_lock);
 
-	/* Create an Ethernet device instance.
-	*/
-	fecp = (volatile fec_t *)dev->base_addr;
-
 	fep->index = index;
-	fep->hwp = fecp;
+	fep->hwp = (void __iomem *)dev->base_addr;
 	fep->netdev = dev;
 
-	/* Whack a reset.  We should wait for this.
-	*/
-	fecp->fec_ecntrl = 1;
-	udelay(10);
-
 	/* Set the Ethernet address */
 #ifdef CONFIG_M5272
 	fec_get_mac(dev);
 #else
 	{
 		unsigned long l;
-		l = fecp->fec_addr_low;
+		l = readl(fep->hwp + FEC_ADDR_LOW);
 		dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24);
 		dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16);
 		dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8);
 		dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0);
-		l = fecp->fec_addr_high;
+		l = readl(fep->hwp + FEC_ADDR_HIGH);
 		dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24);
 		dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16);
 	}
 #endif
 
-	cbd_base = (cbd_t *)mem_addr;
-
-	/* Set receive and transmit descriptor base.
-	*/
+	/* Set receive and transmit descriptor base. */
 	fep->rx_bd_base = cbd_base;
 	fep->tx_bd_base = cbd_base + RX_RING_SIZE;
 
-	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
-	fep->cur_rx = fep->rx_bd_base;
-
-	fep->skb_cur = fep->skb_dirty = 0;
-
-	/* Initialize the receive buffer descriptors.
-	*/
-	bdp = fep->rx_bd_base;
-	for (i=0; i<FEC_ENET_RX_PAGES; i++) {
-
-		/* Allocate a page.
-		*/
-		mem_addr = __get_free_page(GFP_KERNEL);
-		/* XXX: missing check for allocation failure */
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY;
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			mem_addr += FEC_ENET_RX_FRSIZE;
-			bdp++;
-		}
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	/* ...and the same for transmmit.
-	*/
-	bdp = fep->tx_bd_base;
-	for (i=0, j=FEC_ENET_TX_FRPPG; i<TX_RING_SIZE; i++) {
-		if (j >= FEC_ENET_TX_FRPPG) {
-			mem_addr = __get_free_page(GFP_KERNEL);
-			j = 1;
-		} else {
-			mem_addr += FEC_ENET_TX_FRSIZE;
-			j++;
-		}
-		fep->tx_bounce[i] = (unsigned char *) mem_addr;
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp++;
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	/* Set receive and transmit descriptor base.
-	*/
-	fecp->fec_r_des_start = fep->bd_dma;
-	fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
-				* RX_RING_SIZE;
-
 #ifdef HAVE_mii_link_interrupt
 	fec_request_mii_intr(dev);
 #endif
-
-	fecp->fec_grp_hash_table_high = 0;
-	fecp->fec_grp_hash_table_low = 0;
-	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
-	fecp->fec_ecntrl = 2;
-	fecp->fec_r_des_active = 0;
-#ifndef CONFIG_M5272
-	fecp->fec_hash_table_high = 0;
-	fecp->fec_hash_table_low = 0;
-#endif
-
-	/* The FEC Ethernet specific entries in the device structure. */
-	dev->open = fec_enet_open;
-	dev->hard_start_xmit = fec_enet_start_xmit;
-	dev->tx_timeout = fec_timeout;
+	/* The FEC Ethernet specific entries in the device structure */
 	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->stop = fec_enet_close;
-	dev->set_multicast_list = set_multicast_list;
+	dev->netdev_ops = &fec_netdev_ops;
 
 	for (i=0; i<NMII-1; i++)
 		mii_cmds[i].mii_next = &mii_cmds[i+1];
 	mii_free = mii_cmds;
 
-	/* setup MII interface */
-	fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
-	fecp->fec_x_cntrl = 0x00;
-
-	/*
-	 * Set MII speed to 2.5 MHz
-	 */
+	/* Set MII speed to 2.5 MHz */
 	fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
 					/ 2500000) / 2) & 0x3F) << 1;
-	fecp->fec_mii_speed = fep->phy_speed;
 	fec_restart(dev, 0);
 
-	/* Clear and enable interrupts */
-	fecp->fec_ievent = 0xffc00000;
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
-
 	/* Queue up command to detect the PHY and initialize the
 	 * remainder of the interface.
 	 */
@@ -1847,145 +1729,118 @@
 static void
 fec_restart(struct net_device *dev, int duplex)
 {
-	struct fec_enet_private *fep;
-	volatile cbd_t *bdp;
-	volatile fec_t *fecp;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	struct bufdesc *bdp;
 	int i;
 
-	fep = netdev_priv(dev);
-	fecp = fep->hwp;
-
-	/* Whack a reset.  We should wait for this.
-	*/
-	fecp->fec_ecntrl = 1;
+	/* Whack a reset.  We should wait for this. */
+	writel(1, fep->hwp + FEC_ECNTRL);
 	udelay(10);
 
-	/* Clear any outstanding interrupt.
-	*/
-	fecp->fec_ievent = 0xffc00000;
-
-	/* Set station address.
-	*/
-	fec_set_mac_address(dev);
+	/* Clear any outstanding interrupt. */
+	writel(0xffc00000, fep->hwp + FEC_IEVENT);
 
-	/* Reset all multicast.
-	*/
-	fecp->fec_grp_hash_table_high = 0;
-	fecp->fec_grp_hash_table_low = 0;
+	/* Reset all multicast.	*/
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+#ifndef CONFIG_M5272
+	writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
+	writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
+#endif
 
-	/* Set maximum receive buffer size.
-	*/
-	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+	/* Set maximum receive buffer size. */
+	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
-	/* Set receive and transmit descriptor base.
-	*/
-	fecp->fec_r_des_start = fep->bd_dma;
-	fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
-				* RX_RING_SIZE;
+	/* Set receive and transmit descriptor base. */
+	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
+	writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
+			fep->hwp + FEC_X_DES_START);
 
 	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
 	fep->cur_rx = fep->rx_bd_base;
 
-	/* Reset SKB transmit buffers.
-	*/
+	/* Reset SKB transmit buffers. */
 	fep->skb_cur = fep->skb_dirty = 0;
-	for (i=0; i<=TX_RING_MOD_MASK; i++) {
-		if (fep->tx_skbuff[i] != NULL) {
+	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
+		if (fep->tx_skbuff[i]) {
 			dev_kfree_skb_any(fep->tx_skbuff[i]);
 			fep->tx_skbuff[i] = NULL;
 		}
 	}
 
-	/* Initialize the receive buffer descriptors.
-	*/
+	/* Initialize the receive buffer descriptors. */
 	bdp = fep->rx_bd_base;
-	for (i=0; i<RX_RING_SIZE; i++) {
+	for (i = 0; i < RX_RING_SIZE; i++) {
 
-		/* Initialize the BD for every fragment in the page.
-		*/
+		/* Initialize the BD for every fragment in the page. */
 		bdp->cbd_sc = BD_ENET_RX_EMPTY;
 		bdp++;
 	}
 
-	/* Set the last buffer to wrap.
-	*/
+	/* Set the last buffer to wrap */
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
-	/* ...and the same for transmmit.
-	*/
+	/* ...and the same for transmit */
 	bdp = fep->tx_bd_base;
-	for (i=0; i<TX_RING_SIZE; i++) {
+	for (i = 0; i < TX_RING_SIZE; i++) {
 
-		/* Initialize the BD for every fragment in the page.
-		*/
+		/* Initialize the BD for every fragment in the page. */
 		bdp->cbd_sc = 0;
 		bdp->cbd_bufaddr = 0;
 		bdp++;
 	}
 
-	/* Set the last buffer to wrap.
-	*/
+	/* Set the last buffer to wrap */
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
-	/* Enable MII mode.
-	*/
+	/* Enable MII mode */
 	if (duplex) {
-		fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;/* MII enable */
-		fecp->fec_x_cntrl = 0x04;		  /* FD enable */
+		/* MII enable / FD enable */
+		writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL);
+		writel(0x04, fep->hwp + FEC_X_CNTRL);
 	} else {
-		/* MII enable|No Rcv on Xmit */
-		fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x06;
-		fecp->fec_x_cntrl = 0x00;
+		/* MII enable / No Rcv on Xmit */
+		writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL);
+		writel(0x0, fep->hwp + FEC_X_CNTRL);
 	}
 	fep->full_duplex = duplex;
 
-	/* Set MII speed.
-	*/
-	fecp->fec_mii_speed = fep->phy_speed;
+	/* Set MII speed */
+	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
-	/* And last, enable the transmit and receive processing.
-	*/
-	fecp->fec_ecntrl = 2;
-	fecp->fec_r_des_active = 0;
+	/* And last, enable the transmit and receive processing */
+	writel(2, fep->hwp + FEC_ECNTRL);
+	writel(0, fep->hwp + FEC_R_DES_ACTIVE);
 
-	/* Enable interrupts we wish to service.
-	*/
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
+	/* Enable interrupts we wish to service */
+	writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII,
+			fep->hwp + FEC_IMASK);
 }
 
 static void
 fec_stop(struct net_device *dev)
 {
-	volatile fec_t *fecp;
-	struct fec_enet_private *fep;
-
-	fep = netdev_priv(dev);
-	fecp = fep->hwp;
+	struct fec_enet_private *fep = netdev_priv(dev);
 
-	/*
-	** We cannot expect a graceful transmit stop without link !!!
-	*/
-	if (fep->link)
-		{
-		fecp->fec_x_cntrl = 0x01;	/* Graceful transmit stop */
+	/* We cannot expect a graceful transmit stop without link !!! */
+	if (fep->link) {
+		writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
 		udelay(10);
-		if (!(fecp->fec_ievent & FEC_ENET_GRA))
+		if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
 			printk("fec_stop : Graceful transmit stop did not complete !\n");
-		}
+	}
 
-	/* Whack a reset.  We should wait for this.
-	*/
-	fecp->fec_ecntrl = 1;
+	/* Whack a reset.  We should wait for this. */
+	writel(1, fep->hwp + FEC_ECNTRL);
 	udelay(10);
 
-	/* Clear outstanding MII command interrupts.
-	*/
-	fecp->fec_ievent = FEC_ENET_MII;
+	/* Clear outstanding MII command interrupts. */
+	writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
 
-	fecp->fec_imask = FEC_ENET_MII;
-	fecp->fec_mii_speed = fep->phy_speed;
+	writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 }
 
 static int __devinit
diff -druN linux-libre-2.6.30-gnu/drivers/net/fec.h linux-libre-2.6.31-gnu/drivers/net/fec.h
--- linux-libre-2.6.30-gnu/drivers/net/fec.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fec.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,82 +20,55 @@
  *	registers in the same peripheral device on different models
  *	of the ColdFire!
  */
-typedef struct fec {
-	unsigned long	fec_reserved0;
-	unsigned long	fec_ievent;		/* Interrupt event reg */
-	unsigned long	fec_imask;		/* Interrupt mask reg */
-	unsigned long	fec_reserved1;
-	unsigned long	fec_r_des_active;	/* Receive descriptor reg */
-	unsigned long	fec_x_des_active;	/* Transmit descriptor reg */
-	unsigned long	fec_reserved2[3];
-	unsigned long	fec_ecntrl;		/* Ethernet control reg */
-	unsigned long	fec_reserved3[6];
-	unsigned long	fec_mii_data;		/* MII manage frame reg */
-	unsigned long	fec_mii_speed;		/* MII speed control reg */
-	unsigned long	fec_reserved4[7];
-	unsigned long	fec_mib_ctrlstat;	/* MIB control/status reg */
-	unsigned long	fec_reserved5[7];
-	unsigned long	fec_r_cntrl;		/* Receive control reg */
-	unsigned long	fec_reserved6[15];
-	unsigned long	fec_x_cntrl;		/* Transmit Control reg */
-	unsigned long	fec_reserved7[7];
-	unsigned long	fec_addr_low;		/* Low 32bits MAC address */
-	unsigned long	fec_addr_high;		/* High 16bits MAC address */
-	unsigned long	fec_opd;		/* Opcode + Pause duration */
-	unsigned long	fec_reserved8[10];
-	unsigned long	fec_hash_table_high;	/* High 32bits hash table */
-	unsigned long	fec_hash_table_low;	/* Low 32bits hash table */
-	unsigned long	fec_grp_hash_table_high;/* High 32bits hash table */
-	unsigned long	fec_grp_hash_table_low;	/* Low 32bits hash table */
-	unsigned long	fec_reserved9[7];
-	unsigned long	fec_x_wmrk;		/* FIFO transmit water mark */
-	unsigned long	fec_reserved10;
-	unsigned long	fec_r_bound;		/* FIFO receive bound reg */
-	unsigned long	fec_r_fstart;		/* FIFO receive start reg */
-	unsigned long	fec_reserved11[11];
-	unsigned long	fec_r_des_start;	/* Receive descriptor ring */
-	unsigned long	fec_x_des_start;	/* Transmit descriptor ring */
-	unsigned long	fec_r_buff_size;	/* Maximum receive buff size */
-} fec_t;
+#define FEC_IEVENT		0x004 /* Interrupt event reg */
+#define FEC_IMASK		0x008 /* Interrupt mask reg */
+#define FEC_R_DES_ACTIVE	0x010 /* Receive descriptor reg */
+#define FEC_X_DES_ACTIVE	0x014 /* Transmit descriptor reg */
+#define FEC_ECNTRL		0x024 /* Ethernet control reg */
+#define FEC_MII_DATA		0x040 /* MII manage frame reg */
+#define FEC_MII_SPEED		0x044 /* MII speed control reg */
+#define FEC_MIB_CTRLSTAT	0x064 /* MIB control/status reg */
+#define FEC_R_CNTRL		0x084 /* Receive control reg */
+#define FEC_X_CNTRL		0x0c4 /* Transmit Control reg */
+#define FEC_ADDR_LOW		0x0e4 /* Low 32bits MAC address */
+#define FEC_ADDR_HIGH		0x0e8 /* High 16bits MAC address */
+#define FEC_OPD			0x0ec /* Opcode + Pause duration */
+#define FEC_HASH_TABLE_HIGH	0x118 /* High 32bits hash table */
+#define FEC_HASH_TABLE_LOW	0x11c /* Low 32bits hash table */
+#define FEC_GRP_HASH_TABLE_HIGH	0x120 /* High 32bits hash table */
+#define FEC_GRP_HASH_TABLE_LOW	0x124 /* Low 32bits hash table */
+#define FEC_X_WMRK		0x144 /* FIFO transmit water mark */
+#define FEC_R_BOUND		0x14c /* FIFO receive bound reg */
+#define FEC_R_FSTART		0x150 /* FIFO receive start reg */
+#define FEC_R_DES_START		0x180 /* Receive descriptor ring */
+#define FEC_X_DES_START		0x184 /* Transmit descriptor ring */
+#define FEC_R_BUFF_SIZE		0x188 /* Maximum receive buff size */
 
 #else
 
-/*
- *	Define device register set address map.
- */
-typedef struct fec {
-	unsigned long	fec_ecntrl;		/* Ethernet control reg */
-	unsigned long	fec_ievent;		/* Interrupt even reg */
-	unsigned long	fec_imask;		/* Interrupt mask reg */
-	unsigned long	fec_ivec;		/* Interrupt vec status reg */
-	unsigned long	fec_r_des_active;	/* Receive descriptor reg */
-	unsigned long	fec_x_des_active;	/* Transmit descriptor reg */
-	unsigned long	fec_reserved1[10];
-	unsigned long	fec_mii_data;		/* MII manage frame reg */
-	unsigned long	fec_mii_speed;		/* MII speed control reg */
-	unsigned long	fec_reserved2[17];
-	unsigned long	fec_r_bound;		/* FIFO receive bound reg */
-	unsigned long	fec_r_fstart;		/* FIFO receive start reg */
-	unsigned long	fec_reserved3[4];
-	unsigned long	fec_x_wmrk;		/* FIFO transmit water mark */
-	unsigned long	fec_reserved4;
-	unsigned long	fec_x_fstart;		/* FIFO transmit start reg */
-	unsigned long	fec_reserved5[21];
-	unsigned long	fec_r_cntrl;		/* Receive control reg */
-	unsigned long	fec_max_frm_len;	/* Maximum frame length reg */
-	unsigned long	fec_reserved6[14];
-	unsigned long	fec_x_cntrl;		/* Transmit Control reg */
-	unsigned long	fec_reserved7[158];
-	unsigned long	fec_addr_low;		/* Low 32bits MAC address */
-	unsigned long	fec_addr_high;		/* High 16bits MAC address */
-	unsigned long	fec_grp_hash_table_high;/* High 32bits hash table */
-	unsigned long	fec_grp_hash_table_low;	/* Low 32bits hash table */
-	unsigned long	fec_r_des_start;	/* Receive descriptor ring */
-	unsigned long	fec_x_des_start;	/* Transmit descriptor ring */
-	unsigned long	fec_r_buff_size;	/* Maximum receive buff size */
-	unsigned long	reserved8[9];
-	unsigned long	fec_fifo_ram[112];	/* FIFO RAM buffer */
-} fec_t;
+#define FEC_ECNTRL		0x000 /* Ethernet control reg */
+#define FEC_IEVENT		0x004 /* Interrupt even reg */
+#define FEC_IMASK		0x008 /* Interrupt mask reg */
+#define FEC_IVEC		0x00c /* Interrupt vec status reg */
+#define FEC_R_DES_ACTIVE	0x010 /* Receive descriptor reg */
+#define FEC_X_DES_ACTIVE	0x014 /* Transmit descriptor reg */
+#define FEC_MII_DATA		0x040 /* MII manage frame reg */
+#define FEC_MII_SPEED		0x044 /* MII speed control reg */
+#define FEC_R_BOUND		0x08c /* FIFO receive bound reg */
+#define FEC_R_FSTART		0x090 /* FIFO receive start reg */
+#define FEC_X_WMRK		0x0a4 /* FIFO transmit water mark */
+#define FEC_X_FSTART		0x0ac /* FIFO transmit start reg */
+#define FEC_R_CNTRL		0x104 /* Receive control reg */
+#define FEC_MAX_FRM_LEN		0x108 /* Maximum frame length reg */
+#define FEC_X_CNTRL		0x144 /* Transmit Control reg */
+#define FEC_ADDR_LOW		0x3c0 /* Low 32bits MAC address */
+#define FEC_ADDR_HIGH		0x3c4 /* High 16bits MAC address */
+#define FEC_GRP_HASH_TABLE_HIGH	0x3c8 /* High 32bits hash table */
+#define FEC_GRP_HASH_TABLE_LOW	0x3cc /* Low 32bits hash table */
+#define FEC_R_DES_START		0x3d0 /* Receive descriptor ring */
+#define FEC_X_DES_START		0x3d4 /* Transmit descriptor ring */
+#define FEC_R_BUFF_SIZE		0x3d8 /* Maximum receive buff size */
+#define FEC_FIFO_RAM		0x400 /* FIFO RAM buffer */
 
 #endif /* CONFIG_M5272 */
 
@@ -104,17 +77,17 @@
  *	Define the buffer descriptor structure.
  */
 #ifdef CONFIG_ARCH_MXC
-typedef struct bufdesc {
+struct bufdesc {
 	unsigned short cbd_datlen;	/* Data length */
 	unsigned short cbd_sc;	/* Control and status info */
 	unsigned long cbd_bufaddr;	/* Buffer address */
-} cbd_t;
+};
 #else
-typedef struct bufdesc {
+struct bufdesc {
 	unsigned short	cbd_sc;			/* Control and status info */
 	unsigned short	cbd_datlen;		/* Data length */
 	unsigned long	cbd_bufaddr;		/* Buffer address */
-} cbd_t;
+};
 #endif
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/net/fec_mpc52xx.c linux-libre-2.6.31-gnu/drivers/net/fec_mpc52xx.c
--- linux-libre-2.6.30-gnu/drivers/net/fec_mpc52xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fec_mpc52xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/hardirq.h>
 #include <linux/delay.h>
 #include <linux/of_device.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
 #include <linux/netdevice.h>
@@ -43,11 +44,9 @@
 
 #define DRIVER_NAME "mpc52xx-fec"
 
-#define FEC5200_PHYADDR_NONE	(-1)
-#define FEC5200_PHYADDR_7WIRE	(-2)
-
 /* Private driver data structure */
 struct mpc52xx_fec_priv {
+	struct net_device *ndev;
 	int duplex;
 	int speed;
 	int r_irq;
@@ -59,10 +58,11 @@
 	int msg_enable;
 
 	/* MDIO link details */
-	int phy_addr;
-	unsigned int phy_speed;
+	unsigned int mdio_speed;
+	struct device_node *phy_node;
 	struct phy_device *phydev;
 	enum phy_state link;
+	int seven_wire_mode;
 };
 
 
@@ -211,85 +211,25 @@
 		phy_print_status(phydev);
 }
 
-static int mpc52xx_fec_init_phy(struct net_device *dev)
-{
-	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
-	struct phy_device *phydev;
-	char phy_id[BUS_ID_SIZE];
-
-	snprintf(phy_id, sizeof(phy_id), "%x:%02x",
-			(unsigned int)dev->base_addr, priv->phy_addr);
-
-	priv->link = PHY_DOWN;
-	priv->speed = 0;
-	priv->duplex = -1;
-
-	phydev = phy_connect(dev, phy_id, &mpc52xx_fec_adjust_link, 0, PHY_INTERFACE_MODE_MII);
-	if (IS_ERR(phydev)) {
-		dev_err(&dev->dev, "phy_connect failed\n");
-		return PTR_ERR(phydev);
-	}
-	dev_info(&dev->dev, "attached phy %i to driver %s\n",
-			phydev->addr, phydev->drv->name);
-
-	priv->phydev = phydev;
-
-	return 0;
-}
-
-static int mpc52xx_fec_phy_start(struct net_device *dev)
-{
-	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
-	int err;
-
-	if (priv->phy_addr < 0)
-		return 0;
-
-	err = mpc52xx_fec_init_phy(dev);
-	if (err) {
-		dev_err(&dev->dev, "mpc52xx_fec_init_phy failed\n");
-		return err;
-	}
-
-	/* reset phy - this also wakes it from PDOWN */
-	phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
-	phy_start(priv->phydev);
-
-	return 0;
-}
-
-static void mpc52xx_fec_phy_stop(struct net_device *dev)
-{
-	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
-
-	if (!priv->phydev)
-		return;
-
-	phy_disconnect(priv->phydev);
-	/* power down phy */
-	phy_stop(priv->phydev);
-	phy_write(priv->phydev, MII_BMCR, BMCR_PDOWN);
-}
-
-static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv)
-{
-	struct mpc52xx_fec __iomem *fec = priv->fec;
-
-	if (priv->phydev)
-		return;
-
-	out_be32(&fec->mii_speed, priv->phy_speed);
-}
-
 static int mpc52xx_fec_open(struct net_device *dev)
 {
 	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
 	int err = -EBUSY;
 
+	if (priv->phy_node) {
+		priv->phydev = of_phy_connect(priv->ndev, priv->phy_node,
+					      mpc52xx_fec_adjust_link, 0, 0);
+		if (!priv->phydev) {
+			dev_err(&dev->dev, "of_phy_connect failed\n");
+			return -ENODEV;
+		}
+		phy_start(priv->phydev);
+	}
+
 	if (request_irq(dev->irq, &mpc52xx_fec_interrupt, IRQF_SHARED,
 	                DRIVER_NAME "_ctrl", dev)) {
 		dev_err(&dev->dev, "ctrl interrupt request failed\n");
-		goto out;
+		goto free_phy;
 	}
 	if (request_irq(priv->r_irq, &mpc52xx_fec_rx_interrupt, 0,
 	                DRIVER_NAME "_rx", dev)) {
@@ -311,10 +251,6 @@
 		goto free_irqs;
 	}
 
-	err = mpc52xx_fec_phy_start(dev);
-	if (err)
-		goto free_skbs;
-
 	bcom_enable(priv->rx_dmatsk);
 	bcom_enable(priv->tx_dmatsk);
 
@@ -324,16 +260,18 @@
 
 	return 0;
 
- free_skbs:
-	mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk);
-
  free_irqs:
 	free_irq(priv->t_irq, dev);
  free_2irqs:
 	free_irq(priv->r_irq, dev);
  free_ctrl_irq:
 	free_irq(dev->irq, dev);
- out:
+ free_phy:
+	if (priv->phydev) {
+		phy_stop(priv->phydev);
+		phy_disconnect(priv->phydev);
+		priv->phydev = NULL;
+	}
 
 	return err;
 }
@@ -352,7 +290,12 @@
 	free_irq(priv->r_irq, dev);
 	free_irq(priv->t_irq, dev);
 
-	mpc52xx_fec_phy_stop(dev);
+	if (priv->phydev) {
+		/* power down phy */
+		phy_stop(priv->phydev);
+		phy_disconnect(priv->phydev);
+		priv->phydev = NULL;
+	}
 
 	return 0;
 }
@@ -366,6 +309,7 @@
 {
 	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
 	struct bcom_fec_bd *bd;
+	unsigned long flags;
 
 	if (bcom_queue_full(priv->tx_dmatsk)) {
 		if (net_ratelimit())
@@ -373,7 +317,7 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	spin_lock_irq(&priv->lock);
+	spin_lock_irqsave(&priv->lock, flags);
 	dev->trans_start = jiffies;
 
 	bd = (struct bcom_fec_bd *)
@@ -389,7 +333,7 @@
 		netif_stop_queue(dev);
 	}
 
-	spin_unlock_irq(&priv->lock);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return NETDEV_TX_OK;
 }
@@ -696,7 +640,7 @@
 	/* set phy speed.
 	 * this can't be done in phy driver, since it needs to be called
 	 * before fec stuff (even on resume) */
-	mpc52xx_fec_phy_hw_init(priv);
+	out_be32(&fec->mii_speed, priv->mdio_speed);
 }
 
 /**
@@ -732,7 +676,7 @@
 	rcntrl = FEC_RX_BUFFER_SIZE << 16;	/* max frame length */
 	rcntrl |= FEC_RCNTRL_FCE;
 
-	if (priv->phy_addr != FEC5200_PHYADDR_7WIRE)
+	if (!priv->seven_wire_mode)
 		rcntrl |= FEC_RCNTRL_MII_MODE;
 
 	if (priv->duplex == DUPLEX_FULL)
@@ -798,8 +742,6 @@
 
 	/* Stop FEC */
 	out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~FEC_ECNTRL_ETHER_EN);
-
-	return;
 }
 
 /* reset fec and bestcomm tasks */
@@ -817,9 +759,11 @@
 
 	mpc52xx_fec_hw_init(dev);
 
-	phy_stop(priv->phydev);
-	phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
-	phy_start(priv->phydev);
+	if (priv->phydev) {
+		phy_stop(priv->phydev);
+		phy_write(priv->phydev, MII_BMCR, BMCR_RESET);
+		phy_start(priv->phydev);
+	}
 
 	bcom_fec_rx_reset(priv->rx_dmatsk);
 	bcom_fec_tx_reset(priv->tx_dmatsk);
@@ -919,8 +863,6 @@
 	struct net_device *ndev;
 	struct mpc52xx_fec_priv *priv = NULL;
 	struct resource mem;
-	struct device_node *phy_node;
-	const phandle *phy_handle;
 	const u32 *prop;
 	int prop_size;
 
@@ -933,6 +875,7 @@
 		return -ENOMEM;
 
 	priv = netdev_priv(ndev);
+	priv->ndev = ndev;
 
 	/* Reserve FEC control zone */
 	rv = of_address_to_resource(op->node, 0, &mem);
@@ -956,6 +899,7 @@
 	ndev->ethtool_ops	= &mpc52xx_fec_ethtool_ops;
 	ndev->watchdog_timeo	= FEC_WATCHDOG_TIMEOUT;
 	ndev->base_addr		= mem.start;
+	SET_NETDEV_DEV(ndev, &op->dev);
 
 	spin_lock_init(&priv->lock);
 
@@ -1003,14 +947,9 @@
 	 */
 
 	/* Start with safe defaults for link connection */
-	priv->phy_addr = FEC5200_PHYADDR_NONE;
 	priv->speed = 100;
 	priv->duplex = DUPLEX_HALF;
-	priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
-
-	/* the 7-wire property means don't use MII mode */
-	if (of_find_property(op->node, "fsl,7-wire-mode", NULL))
-		priv->phy_addr = FEC5200_PHYADDR_7WIRE;
+	priv->mdio_speed = ((mpc5xxx_get_bus_frequency(op->node) >> 20) / 5) << 1;
 
 	/* The current speed preconfigures the speed of the MII link */
 	prop = of_get_property(op->node, "current-speed", &prop_size);
@@ -1019,43 +958,23 @@
 		priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF;
 	}
 
-	/* If there is a phy handle, setup link to that phy */
-	phy_handle = of_get_property(op->node, "phy-handle", &prop_size);
-	if (phy_handle && (prop_size >= sizeof(phandle))) {
-		phy_node = of_find_node_by_phandle(*phy_handle);
-		prop = of_get_property(phy_node, "reg", &prop_size);
-		if (prop && (prop_size >= sizeof(u32)))
-			if ((*prop >= 0) && (*prop < PHY_MAX_ADDR))
-				priv->phy_addr = *prop;
-		of_node_put(phy_node);
+	/* If there is a phy handle, then get the PHY node */
+	priv->phy_node = of_parse_phandle(op->node, "phy-handle", 0);
+
+	/* the 7-wire property means don't use MII mode */
+	if (of_find_property(op->node, "fsl,7-wire-mode", NULL)) {
+		priv->seven_wire_mode = 1;
+		dev_info(&ndev->dev, "using 7-wire PHY mode\n");
 	}
 
 	/* Hardware init */
 	mpc52xx_fec_hw_init(ndev);
-
 	mpc52xx_fec_reset_stats(ndev);
 
-	SET_NETDEV_DEV(ndev, &op->dev);
-
-	/* Register the new network device */
 	rv = register_netdev(ndev);
 	if (rv < 0)
 		goto probe_error;
 
-	/* Now report the link setup */
-	switch (priv->phy_addr) {
-	 case FEC5200_PHYADDR_NONE:
-		dev_info(&ndev->dev, "Fixed speed MII link: %i%cD\n",
-			 priv->speed, priv->duplex ? 'F' : 'H');
-		break;
-	 case FEC5200_PHYADDR_7WIRE:
-		dev_info(&ndev->dev, "using 7-wire PHY mode\n");
-		break;
-	 default:
-		dev_info(&ndev->dev, "Using PHY at MDIO address %i\n",
-			 priv->phy_addr);
-	}
-
 	/* We're done ! */
 	dev_set_drvdata(&op->dev, ndev);
 
@@ -1065,6 +984,10 @@
 	/* Error handling - free everything that might be allocated */
 probe_error:
 
+	if (priv->phy_node)
+		of_node_put(priv->phy_node);
+	priv->phy_node = NULL;
+
 	irq_dispose_mapping(ndev->irq);
 
 	if (priv->rx_dmatsk)
@@ -1093,6 +1016,10 @@
 
 	unregister_netdev(ndev);
 
+	if (priv->phy_node)
+		of_node_put(priv->phy_node);
+	priv->phy_node = NULL;
+
 	irq_dispose_mapping(ndev->irq);
 
 	bcom_fec_rx_release(priv->rx_dmatsk);
diff -druN linux-libre-2.6.30-gnu/drivers/net/fec_mpc52xx_phy.c linux-libre-2.6.31-gnu/drivers/net/fec_mpc52xx_phy.c
--- linux-libre-2.6.30-gnu/drivers/net/fec_mpc52xx_phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fec_mpc52xx_phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,12 +14,14 @@
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <linux/of_platform.h>
+#include <linux/of_mdio.h>
 #include <asm/io.h>
 #include <asm/mpc52xx.h>
 #include "fec_mpc52xx.h"
 
 struct mpc52xx_fec_mdio_priv {
 	struct mpc52xx_fec __iomem *regs;
+	int mdio_irqs[PHY_MAX_ADDR];
 };
 
 static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id,
@@ -27,7 +29,7 @@
 {
 	struct mpc52xx_fec_mdio_priv *priv = bus->priv;
 	struct mpc52xx_fec __iomem *fec;
-	int tries = 100;
+	int tries = 3;
 
 	value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK;
 	value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK;
@@ -38,7 +40,7 @@
 
 	/* wait for it to finish, this takes about 23 us on lite5200b */
 	while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries)
-		udelay(5);
+		msleep(1);
 
 	if (!tries)
 		return -ETIMEDOUT;
@@ -64,7 +66,6 @@
 {
 	struct device *dev = &of->dev;
 	struct device_node *np = of->node;
-	struct device_node *child = NULL;
 	struct mii_bus *bus;
 	struct mpc52xx_fec_mdio_priv *priv;
 	struct resource res = {};
@@ -85,22 +86,7 @@
 	bus->write = mpc52xx_fec_mdio_write;
 
 	/* setup irqs */
-	bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL);
-	if (bus->irq == NULL) {
-		err = -ENOMEM;
-		goto out_free;
-	}
-	for (i=0; i<PHY_MAX_ADDR; i++)
-		bus->irq[i] = PHY_POLL;
-
-	while ((child = of_get_next_child(np, child)) != NULL) {
-		int irq = irq_of_parse_and_map(child, 0);
-		if (irq != NO_IRQ) {
-			const u32 *id = of_get_property(child, "reg", NULL);
-			if (id)
-				bus->irq[*id] = irq;
-		}
-	}
+	bus->irq = priv->mdio_irqs;
 
 	/* setup registers */
 	err = of_address_to_resource(np, 0, &res);
@@ -120,9 +106,9 @@
 
 	/* set MII speed */
 	out_be32(&priv->regs->mii_speed,
-		((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);
+		((mpc5xxx_get_bus_frequency(of->node) >> 20) / 5) << 1);
 
-	err = mdiobus_register(bus);
+	err = of_mdiobus_register(bus, np);
 	if (err)
 		goto out_unmap;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/forcedeth.c linux-libre-2.6.31-gnu/drivers/net/forcedeth.c
--- linux-libre-2.6.30-gnu/drivers/net/forcedeth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/forcedeth.c	2009-09-09 18:13:59.000000000 -0400
@@ -77,27 +77,31 @@
  * Hardware access:
  */
 
-#define DEV_NEED_TIMERIRQ          0x000001  /* set the timer irq flag in the irq mask */
-#define DEV_NEED_LINKTIMER         0x000002  /* poll link settings. Relies on the timer irq */
-#define DEV_HAS_LARGEDESC          0x000004  /* device supports jumbo frames and needs packet format 2 */
-#define DEV_HAS_HIGH_DMA           0x000008  /* device supports 64bit dma */
-#define DEV_HAS_CHECKSUM           0x000010  /* device supports tx and rx checksum offloads */
-#define DEV_HAS_VLAN               0x000020  /* device supports vlan tagging and striping */
-#define DEV_HAS_MSI                0x000040  /* device supports MSI */
-#define DEV_HAS_MSI_X              0x000080  /* device supports MSI-X */
-#define DEV_HAS_POWER_CNTRL        0x000100  /* device supports power savings */
-#define DEV_HAS_STATISTICS_V1      0x000200  /* device supports hw statistics version 1 */
-#define DEV_HAS_STATISTICS_V2      0x000600  /* device supports hw statistics version 2 */
-#define DEV_HAS_STATISTICS_V3      0x000e00  /* device supports hw statistics version 3 */
-#define DEV_HAS_TEST_EXTENDED      0x001000  /* device supports extended diagnostic test */
-#define DEV_HAS_MGMT_UNIT          0x002000  /* device supports management unit */
-#define DEV_HAS_CORRECT_MACADDR    0x004000  /* device supports correct mac address order */
-#define DEV_HAS_COLLISION_FIX      0x008000  /* device supports tx collision fix */
-#define DEV_HAS_PAUSEFRAME_TX_V1   0x010000  /* device supports tx pause frames version 1 */
-#define DEV_HAS_PAUSEFRAME_TX_V2   0x020000  /* device supports tx pause frames version 2 */
-#define DEV_HAS_PAUSEFRAME_TX_V3   0x040000  /* device supports tx pause frames version 3 */
-#define DEV_NEED_TX_LIMIT          0x080000  /* device needs to limit tx */
-#define DEV_HAS_GEAR_MODE          0x100000  /* device supports gear mode */
+#define DEV_NEED_TIMERIRQ          0x0000001  /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER         0x0000002  /* poll link settings. Relies on the timer irq */
+#define DEV_HAS_LARGEDESC          0x0000004  /* device supports jumbo frames and needs packet format 2 */
+#define DEV_HAS_HIGH_DMA           0x0000008  /* device supports 64bit dma */
+#define DEV_HAS_CHECKSUM           0x0000010  /* device supports tx and rx checksum offloads */
+#define DEV_HAS_VLAN               0x0000020  /* device supports vlan tagging and striping */
+#define DEV_HAS_MSI                0x0000040  /* device supports MSI */
+#define DEV_HAS_MSI_X              0x0000080  /* device supports MSI-X */
+#define DEV_HAS_POWER_CNTRL        0x0000100  /* device supports power savings */
+#define DEV_HAS_STATISTICS_V1      0x0000200  /* device supports hw statistics version 1 */
+#define DEV_HAS_STATISTICS_V2      0x0000600  /* device supports hw statistics version 2 */
+#define DEV_HAS_STATISTICS_V3      0x0000e00  /* device supports hw statistics version 3 */
+#define DEV_HAS_TEST_EXTENDED      0x0001000  /* device supports extended diagnostic test */
+#define DEV_HAS_MGMT_UNIT          0x0002000  /* device supports management unit */
+#define DEV_HAS_CORRECT_MACADDR    0x0004000  /* device supports correct mac address order */
+#define DEV_HAS_COLLISION_FIX      0x0008000  /* device supports tx collision fix */
+#define DEV_HAS_PAUSEFRAME_TX_V1   0x0010000  /* device supports tx pause frames version 1 */
+#define DEV_HAS_PAUSEFRAME_TX_V2   0x0020000  /* device supports tx pause frames version 2 */
+#define DEV_HAS_PAUSEFRAME_TX_V3   0x0040000  /* device supports tx pause frames version 3 */
+#define DEV_NEED_TX_LIMIT          0x0080000  /* device needs to limit tx */
+#define DEV_NEED_TX_LIMIT2         0x0180000  /* device needs to limit tx, expect for some revs */
+#define DEV_HAS_GEAR_MODE          0x0200000  /* device supports gear mode */
+#define DEV_NEED_PHY_INIT_FIX      0x0400000  /* device needs specific phy workaround */
+#define DEV_NEED_LOW_POWER_FIX     0x0800000  /* device needs special power up workaround */
+#define DEV_NEED_MSI_FIX           0x1000000  /* device needs msi workaround */
 
 enum {
 	NvRegIrqStatus = 0x000,
@@ -343,6 +347,7 @@
 #define NVREG_POWERSTATE2_POWERUP_MASK		0x0F15
 #define NVREG_POWERSTATE2_POWERUP_REV_A3	0x0001
 #define NVREG_POWERSTATE2_PHY_RESET		0x0004
+#define NVREG_POWERSTATE2_GATE_CLOCKS		0x0F00
 };
 
 /* Big endian: should work, but is untested */
@@ -714,7 +719,8 @@
 struct nv_skb_map {
 	struct sk_buff *skb;
 	dma_addr_t dma;
-	unsigned int dma_len;
+	unsigned int dma_len:31;
+	unsigned int dma_single:1;
 	struct ring_desc_ex *first_tx_desc;
 	struct nv_skb_map *next_tx_ctx;
 };
@@ -1023,6 +1029,23 @@
 		return 1;
 }
 
+static void nv_txrx_gate(struct net_device *dev, bool gate)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	u32 powerstate;
+
+	if (!np->mac_in_use &&
+	    (np->driver_data & DEV_HAS_POWER_CNTRL)) {
+		powerstate = readl(base + NvRegPowerState2);
+		if (gate)
+			powerstate |= NVREG_POWERSTATE2_GATE_CLOCKS;
+		else
+			powerstate &= ~NVREG_POWERSTATE2_GATE_CLOCKS;
+		writel(powerstate, base + NvRegPowerState2);
+	}
+}
+
 static void nv_enable_irq(struct net_device *dev)
 {
 	struct fe_priv *np = get_nvpriv(dev);
@@ -1253,14 +1276,7 @@
 			}
 		}
 		if (np->phy_model == PHY_MODEL_REALTEK_8201) {
-			if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
+			if (np->driver_data & DEV_NEED_PHY_INIT_FIX) {
 				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
 				phy_reserved |= PHY_REALTEK_INIT7;
 				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
@@ -1451,14 +1467,7 @@
 			}
 		}
 		if (np->phy_model == PHY_MODEL_REALTEK_8201) {
-			if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
-			    np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
+			if (np->driver_data & DEV_NEED_PHY_INIT_FIX) {
 				phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
 				phy_reserved |= PHY_REALTEK_INIT7;
 				if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
@@ -1904,6 +1913,7 @@
 		np->tx_skb[i].skb = NULL;
 		np->tx_skb[i].dma = 0;
 		np->tx_skb[i].dma_len = 0;
+		np->tx_skb[i].dma_single = 0;
 		np->tx_skb[i].first_tx_desc = NULL;
 		np->tx_skb[i].next_tx_ctx = NULL;
 	}
@@ -1922,23 +1932,30 @@
 		return nv_alloc_rx_optimized(dev);
 }
 
-static int nv_release_txskb(struct net_device *dev, struct nv_skb_map* tx_skb)
+static void nv_unmap_txskb(struct fe_priv *np, struct nv_skb_map *tx_skb)
 {
-	struct fe_priv *np = netdev_priv(dev);
-
 	if (tx_skb->dma) {
-		pci_unmap_page(np->pci_dev, tx_skb->dma,
-			       tx_skb->dma_len,
-			       PCI_DMA_TODEVICE);
+		if (tx_skb->dma_single)
+			pci_unmap_single(np->pci_dev, tx_skb->dma,
+					 tx_skb->dma_len,
+					 PCI_DMA_TODEVICE);
+		else
+			pci_unmap_page(np->pci_dev, tx_skb->dma,
+				       tx_skb->dma_len,
+				       PCI_DMA_TODEVICE);
 		tx_skb->dma = 0;
 	}
+}
+
+static int nv_release_txskb(struct fe_priv *np, struct nv_skb_map *tx_skb)
+{
+	nv_unmap_txskb(np, tx_skb);
 	if (tx_skb->skb) {
 		dev_kfree_skb_any(tx_skb->skb);
 		tx_skb->skb = NULL;
 		return 1;
-	} else {
-		return 0;
 	}
+	return 0;
 }
 
 static void nv_drain_tx(struct net_device *dev)
@@ -1956,10 +1973,11 @@
 			np->tx_ring.ex[i].bufhigh = 0;
 			np->tx_ring.ex[i].buflow = 0;
 		}
-		if (nv_release_txskb(dev, &np->tx_skb[i]))
+		if (nv_release_txskb(np, &np->tx_skb[i]))
 			dev->stats.tx_dropped++;
 		np->tx_skb[i].dma = 0;
 		np->tx_skb[i].dma_len = 0;
+		np->tx_skb[i].dma_single = 0;
 		np->tx_skb[i].first_tx_desc = NULL;
 		np->tx_skb[i].next_tx_ctx = NULL;
 	}
@@ -2163,6 +2181,7 @@
 		np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
 						PCI_DMA_TODEVICE);
 		np->put_tx_ctx->dma_len = bcnt;
+		np->put_tx_ctx->dma_single = 1;
 		put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma);
 		put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 
@@ -2188,6 +2207,7 @@
 			np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
 							   PCI_DMA_TODEVICE);
 			np->put_tx_ctx->dma_len = bcnt;
+			np->put_tx_ctx->dma_single = 0;
 			put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma);
 			put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 
@@ -2283,6 +2303,7 @@
 		np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
 						PCI_DMA_TODEVICE);
 		np->put_tx_ctx->dma_len = bcnt;
+		np->put_tx_ctx->dma_single = 1;
 		put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
 		put_tx->buflow = cpu_to_le32(dma_low(np->put_tx_ctx->dma));
 		put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
@@ -2309,6 +2330,7 @@
 			np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
 							   PCI_DMA_TODEVICE);
 			np->put_tx_ctx->dma_len = bcnt;
+			np->put_tx_ctx->dma_single = 0;
 			put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma));
 			put_tx->buflow = cpu_to_le32(dma_low(np->put_tx_ctx->dma));
 			put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
@@ -2426,10 +2448,7 @@
 		dprintk(KERN_DEBUG "%s: nv_tx_done: flags 0x%x.\n",
 					dev->name, flags);
 
-		pci_unmap_page(np->pci_dev, np->get_tx_ctx->dma,
-			       np->get_tx_ctx->dma_len,
-			       PCI_DMA_TODEVICE);
-		np->get_tx_ctx->dma = 0;
+		nv_unmap_txskb(np, np->get_tx_ctx);
 
 		if (np->desc_ver == DESC_VER_1) {
 			if (flags & NV_TX_LASTPACKET) {
@@ -2494,10 +2513,7 @@
 		dprintk(KERN_DEBUG "%s: nv_tx_done_optimized: flags 0x%x.\n",
 					dev->name, flags);
 
-		pci_unmap_page(np->pci_dev, np->get_tx_ctx->dma,
-			       np->get_tx_ctx->dma_len,
-			       PCI_DMA_TODEVICE);
-		np->get_tx_ctx->dma = 0;
+		nv_unmap_txskb(np, np->get_tx_ctx);
 
 		if (flags & NV_TX2_LASTPACKET) {
 			if (!(flags & NV_TX2_ERROR))
@@ -3403,12 +3419,14 @@
 		if (!netif_carrier_ok(dev)) {
 			netif_carrier_on(dev);
 			printk(KERN_INFO "%s: link up.\n", dev->name);
+			nv_txrx_gate(dev, false);
 			nv_start_rx(dev);
 		}
 	} else {
 		if (netif_carrier_ok(dev)) {
 			netif_carrier_off(dev);
 			printk(KERN_INFO "%s: link down.\n", dev->name);
+			nv_txrx_gate(dev, true);
 			nv_stop_rx(dev);
 		}
 	}
@@ -3496,11 +3514,13 @@
 	nv_msi_workaround(np);
 
 #ifdef CONFIG_FORCEDETH_NAPI
-	napi_schedule(&np->napi);
-
-	/* Disable furthur irq's
-	   (msix not enabled with napi) */
-	writel(0, base + NvRegIrqMask);
+	if (napi_schedule_prep(&np->napi)) {
+		/*
+		 * Disable further irq's (msix not enabled with napi)
+		 */
+		writel(0, base + NvRegIrqMask);
+		__napi_schedule(&np->napi);
+	}
 
 #else
 	do
@@ -3597,12 +3617,13 @@
 	nv_msi_workaround(np);
 
 #ifdef CONFIG_FORCEDETH_NAPI
-	napi_schedule(&np->napi);
-
-	/* Disable furthur irq's
-	   (msix not enabled with napi) */
-	writel(0, base + NvRegIrqMask);
-
+	if (napi_schedule_prep(&np->napi)) {
+		/*
+		 * Disable further irq's (msix not enabled with napi)
+		 */
+		writel(0, base + NvRegIrqMask);
+		__napi_schedule(&np->napi);
+	}
 #else
 	do
 	{
@@ -5081,7 +5102,7 @@
 		dprintk(KERN_DEBUG "%s: loopback - did not receive test packet\n", dev->name);
 	}
 
-	pci_unmap_page(np->pci_dev, test_dma_addr,
+	pci_unmap_single(np->pci_dev, test_dma_addr,
 		       (skb_end_pointer(tx_skb) - tx_skb->data),
 		       PCI_DMA_TODEVICE);
 	dev_kfree_skb_any(tx_skb);
@@ -5336,6 +5357,7 @@
 	mii_rw(dev, np->phyaddr, MII_BMCR,
 	       mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN);
 
+	nv_txrx_gate(dev, false);
 	/* erase previous misconfiguration */
 	if (np->driver_data & DEV_HAS_POWER_CNTRL)
 		nv_mac_reset(dev);
@@ -5523,12 +5545,14 @@
 	nv_drain_rxtx(dev);
 
 	if (np->wolenabled || !phy_power_down) {
+		nv_txrx_gate(dev, false);
 		writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
 		nv_start_rx(dev);
 	} else {
 		/* power down phy */
 		mii_rw(dev, np->phyaddr, MII_BMCR,
 		       mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ)|BMCR_PDOWN);
+		nv_txrx_gate(dev, true);
 	}
 
 	/* FIXME: power down nic */
@@ -5821,8 +5845,7 @@
 		/* take phy and nic out of low power mode */
 		powerstate = readl(base + NvRegPowerState2);
 		powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
-		if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) &&
+		if ((id->driver_data & DEV_NEED_LOW_POWER_FIX) &&
 		    pci_dev->revision >= 0xA3)
 			powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
 		writel(powerstate, base + NvRegPowerState2);
@@ -5878,14 +5901,7 @@
 	/* Limit the number of tx's outstanding for hw bug */
 	if (id->driver_data & DEV_NEED_TX_LIMIT) {
 		np->tx_limit = 1;
-		if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
-		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_39) &&
+		if ((id->driver_data & DEV_NEED_TX_LIMIT2) &&
 		    pci_dev->revision >= 0xA2)
 			np->tx_limit = 0;
 	}
@@ -6135,7 +6151,8 @@
 	for (i = 0;i <= np->register_size/sizeof(u32); i++)
 		writel(np->saved_config_space[i], base+i*sizeof(u32));
 
-	pci_write_config_dword(pdev, NV_MSI_PRIV_OFFSET, NV_MSI_PRIV_VALUE);
+	if (np->driver_data & DEV_NEED_MSI_FIX)
+		pci_write_config_dword(pdev, NV_MSI_PRIV_OFFSET, NV_MSI_PRIV_VALUE);
 
 	/* restore phy state, including autoneg */
 	phy_init(dev);
@@ -6184,160 +6201,164 @@
 
 static struct pci_device_id pci_tbl[] = {
 	{	/* nForce Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1),
+		PCI_DEVICE(0x10DE, 0x01C3),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce2 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_2),
+		PCI_DEVICE(0x10DE, 0x0066),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce3 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_3),
+		PCI_DEVICE(0x10DE, 0x00D6),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce3 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
+		PCI_DEVICE(0x10DE, 0x0086),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* nForce3 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
+		PCI_DEVICE(0x10DE, 0x008C),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* nForce3 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
+		PCI_DEVICE(0x10DE, 0x00E6),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* nForce3 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
+		PCI_DEVICE(0x10DE, 0x00DF),
 		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
 	},
 	{	/* CK804 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
+		PCI_DEVICE(0x10DE, 0x0056),
 		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT,
 	},
 	{	/* CK804 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
+		PCI_DEVICE(0x10DE, 0x0057),
 		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT,
 	},
 	{	/* MCP04 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
+		PCI_DEVICE(0x10DE, 0x0037),
 		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT,
 	},
 	{	/* MCP04 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
+		PCI_DEVICE(0x10DE, 0x0038),
 		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1|DEV_NEED_TX_LIMIT,
 	},
 	{	/* MCP51 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1,
+		PCI_DEVICE(0x10DE, 0x0268),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1|DEV_NEED_LOW_POWER_FIX,
 	},
 	{	/* MCP51 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1,
+		PCI_DEVICE(0x10DE, 0x0269),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1|DEV_NEED_LOW_POWER_FIX,
 	},
 	{	/* MCP55 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT,
+		PCI_DEVICE(0x10DE, 0x0372),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP55 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT,
+		PCI_DEVICE(0x10DE, 0x0373),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_NEED_TX_LIMIT|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP61 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		PCI_DEVICE(0x10DE, 0x03E5),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP61 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		PCI_DEVICE(0x10DE, 0x03E6),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP61 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		PCI_DEVICE(0x10DE, 0x03EE),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP61 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+		PCI_DEVICE(0x10DE, 0x03EF),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP65 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0450),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP65 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0451),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP65 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0452),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP65 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0453),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP67 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x054C),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP67 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x054D),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP67 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x054E),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP67 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x054F),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP73 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x07DC),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP73 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x07DD),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP73 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x07DE),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP73 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x07DF),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0760),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0761),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0762),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP77 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0763),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0AB0),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0AB1),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0AB2),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
 	},
 	{	/* MCP79 Ethernet Controller */
-		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
-		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+		PCI_DEVICE(0x10DE, 0x0AB3),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT2|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX|DEV_NEED_MSI_FIX,
+	},
+	{	/* MCP89 Ethernet Controller */
+		PCI_DEVICE(0x10DE, 0x0D7D),
+		.driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE|DEV_NEED_PHY_INIT_FIX,
 	},
 	{0,},
 };
diff -druN linux-libre-2.6.30-gnu/drivers/net/fs_enet/fs_enet.h linux-libre-2.6.31-gnu/drivers/net/fs_enet/fs_enet.h
--- linux-libre-2.6.30-gnu/drivers/net/fs_enet/fs_enet.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fs_enet/fs_enet.h	2009-09-09 18:13:59.000000000 -0400
@@ -194,9 +194,4 @@
 
 /*******************************************************************/
 
-/* handy pointer to the immap */
-extern void __iomem *fs_enet_immap;
-
-/*******************************************************************/
-
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/fs_enet/fs_enet-main.c linux-libre-2.6.31-gnu/drivers/net/fs_enet/fs_enet-main.c
--- linux-libre-2.6.30-gnu/drivers/net/fs_enet/fs_enet-main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fs_enet/fs_enet-main.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,8 @@
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 
@@ -752,16 +754,16 @@
 	fep->oldlink = 0;
 	fep->oldspeed = 0;
 	fep->oldduplex = -1;
-	if(fep->fpi->bus_id)
-		phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0,
+
+	phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,
 				PHY_INTERFACE_MODE_MII);
-	else {
-		printk("No phy bus ID specified in BSP code\n");
-		return -EINVAL;
+	if (!phydev) {
+		phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link,
+						   PHY_INTERFACE_MODE_MII);
 	}
-	if (IS_ERR(phydev)) {
-		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
-		return PTR_ERR(phydev);
+	if (!phydev) {
+		dev_err(&dev->dev, "Could not attach to PHY\n");
+		return -ENODEV;
 	}
 
 	fep->phydev = phydev;
@@ -938,81 +940,6 @@
 
 /**************************************************************************************/
 
-/* handy pointer to the immap */
-void __iomem *fs_enet_immap = NULL;
-
-static int setup_immap(void)
-{
-#ifdef CONFIG_CPM1
-	fs_enet_immap = ioremap(IMAP_ADDR, 0x4000);
-	WARN_ON(!fs_enet_immap);
-#elif defined(CONFIG_CPM2)
-	fs_enet_immap = cpm2_immr;
-#endif
-
-	return 0;
-}
-
-static void cleanup_immap(void)
-{
-#if defined(CONFIG_CPM1)
-	iounmap(fs_enet_immap);
-#endif
-}
-
-/**************************************************************************************/
-
-static int __devinit find_phy(struct device_node *np,
-                              struct fs_platform_info *fpi)
-{
-	struct device_node *phynode, *mdionode;
-	int ret = 0, len, bus_id;
-	const u32 *data;
-
-	data  = of_get_property(np, "fixed-link", NULL);
-	if (data) {
-		snprintf(fpi->bus_id, 16, "%x:%02x", 0, *data);
-		return 0;
-	}
-
-	data = of_get_property(np, "phy-handle", &len);
-	if (!data || len != 4)
-		return -EINVAL;
-
-	phynode = of_find_node_by_phandle(*data);
-	if (!phynode)
-		return -EINVAL;
-
-	data = of_get_property(phynode, "reg", &len);
-	if (!data || len != 4) {
-		ret = -EINVAL;
-		goto out_put_phy;
-	}
-
-	mdionode = of_get_parent(phynode);
-	if (!mdionode) {
-		ret = -EINVAL;
-		goto out_put_phy;
-	}
-
-	bus_id = of_get_gpio(mdionode, 0);
-	if (bus_id < 0) {
-		struct resource res;
-		ret = of_address_to_resource(mdionode, 0, &res);
-		if (ret)
-			goto out_put_mdio;
-		bus_id = res.start;
-	}
-
-	snprintf(fpi->bus_id, 16, "%x:%02x", bus_id, *data);
-
-out_put_mdio:
-	of_node_put(mdionode);
-out_put_phy:
-	of_node_put(phynode);
-	return ret;
-}
-
 #ifdef CONFIG_FS_ENET_HAS_FEC
 #define IS_FEC(match) ((match)->data == &fs_fec_ops)
 #else
@@ -1062,9 +989,9 @@
 	fpi->rx_copybreak = 240;
 	fpi->use_napi = 1;
 	fpi->napi_weight = 17;
-
-	ret = find_phy(ofdev->node, fpi);
-	if (ret)
+	fpi->phy_node = of_parse_phandle(ofdev->node, "phy-handle", 0);
+	if ((!fpi->phy_node) && (!of_get_property(ofdev->node, "fixed-link",
+						  NULL)))
 		goto out_free_fpi;
 
 	privsize = sizeof(*fep) +
@@ -1077,6 +1004,7 @@
 		goto out_free_fpi;
 	}
 
+	SET_NETDEV_DEV(ndev, &ofdev->dev);
 	dev_set_drvdata(&ofdev->dev, ndev);
 
 	fep = netdev_priv(ndev);
@@ -1136,6 +1064,7 @@
 out_free_dev:
 	free_netdev(ndev);
 	dev_set_drvdata(&ofdev->dev, NULL);
+	of_node_put(fpi->phy_node);
 out_free_fpi:
 	kfree(fpi);
 	return ret;
@@ -1151,7 +1080,7 @@
 	fep->ops->free_bd(ndev);
 	fep->ops->cleanup_data(ndev);
 	dev_set_drvdata(fep->dev, NULL);
-
+	of_node_put(fep->fpi->phy_node);
 	free_netdev(ndev);
 	return 0;
 }
@@ -1191,25 +1120,12 @@
 
 static int __init fs_init(void)
 {
-	int r = setup_immap();
-	if (r != 0)
-		return r;
-
-	r = of_register_platform_driver(&fs_enet_driver);
-	if (r != 0)
-		goto out;
-
-	return 0;
-
-out:
-	cleanup_immap();
-	return r;
+	return of_register_platform_driver(&fs_enet_driver);
 }
 
 static void __exit fs_cleanup(void)
 {
 	of_unregister_platform_driver(&fs_enet_driver);
-	cleanup_immap();
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druN linux-libre-2.6.30-gnu/drivers/net/fs_enet/mac-fec.c linux-libre-2.6.31-gnu/drivers/net/fs_enet/mac-fec.c
--- linux-libre-2.6.30-gnu/drivers/net/fs_enet/mac-fec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fs_enet/mac-fec.c	2009-09-09 18:13:59.000000000 -0400
@@ -245,10 +245,6 @@
 
 static void restart(struct net_device *dev)
 {
-#ifdef CONFIG_DUET
-	immap_t *immap = fs_enet_immap;
-	u32 cptr;
-#endif
 	struct fs_enet_private *fep = netdev_priv(dev);
 	fec_t __iomem *fecp = fep->fec.fecp;
 	const struct fs_platform_info *fpi = fep->fpi;
@@ -315,36 +311,6 @@
 	FW(fecp, ievent, 0xffc0);
 	FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
 
-	/*
-	 * adjust to speed (only for DUET & RMII)
-	 */
-#ifdef CONFIG_DUET
-	if (fpi->use_rmii) {
-		cptr = in_be32(&immap->im_cpm.cp_cptr);
-		switch (fs_get_fec_index(fpi->fs_no)) {
-		case 0:
-			cptr |= 0x100;
-			if (fep->speed == 10)
-				cptr |= 0x0000010;
-			else if (fep->speed == 100)
-				cptr &= ~0x0000010;
-			break;
-		case 1:
-			cptr |= 0x80;
-			if (fep->speed == 10)
-				cptr |= 0x0000008;
-			else if (fep->speed == 100)
-				cptr &= ~0x0000008;
-			break;
-		default:
-			BUG();	/* should never happen */
-			break;
-		}
-		out_be32(&immap->im_cpm.cp_cptr, cptr);
-	}
-#endif
-
-
 	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
 	/*
 	 * adjust to duplex mode
diff -druN linux-libre-2.6.30-gnu/drivers/net/fs_enet/mii-bitbang.c linux-libre-2.6.31-gnu/drivers/net/fs_enet/mii-bitbang.c
--- linux-libre-2.6.30-gnu/drivers/net/fs_enet/mii-bitbang.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fs_enet/mii-bitbang.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/mii.h>
 #include <linux/platform_device.h>
 #include <linux/mdio-bitbang.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
 #include "fs_enet.h"
@@ -149,31 +150,12 @@
 	return 0;
 }
 
-static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
-{
-	const u32 *data;
-	int len, id, irq;
-
-	data = of_get_property(np, "reg", &len);
-	if (!data || len != 4)
-		return;
-
-	id = *data;
-	bus->phy_mask &= ~(1 << id);
-
-	irq = of_irq_to_resource(np, 0, NULL);
-	if (irq != NO_IRQ)
-		bus->irq[id] = irq;
-}
-
 static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
                                         const struct of_device_id *match)
 {
-	struct device_node *np = NULL;
 	struct mii_bus *new_bus;
 	struct bb_info *bitbang;
 	int ret = -ENOMEM;
-	int i;
 
 	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
 	if (!bitbang)
@@ -196,17 +178,10 @@
 	if (!new_bus->irq)
 		goto out_unmap_regs;
 
-	for (i = 0; i < PHY_MAX_ADDR; i++)
-		new_bus->irq[i] = -1;
-
-	while ((np = of_get_next_child(ofdev->node, np)))
-		if (!strcmp(np->type, "ethernet-phy"))
-			add_phy(new_bus, np);
-
 	new_bus->parent = &ofdev->dev;
 	dev_set_drvdata(&ofdev->dev, new_bus);
 
-	ret = mdiobus_register(new_bus);
+	ret = of_mdiobus_register(new_bus, ofdev->node);
 	if (ret)
 		goto out_free_irqs;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/fs_enet/mii-fec.c linux-libre-2.6.31-gnu/drivers/net/fs_enet/mii-fec.c
--- linux-libre-2.6.30-gnu/drivers/net/fs_enet/mii-fec.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fs_enet/mii-fec.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,8 +54,7 @@
 	fec_t __iomem *fecp = fec->fecp;
 	int i, ret = -1;
 
-	if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
-		BUG();
+	BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
 
 	/* Add PHY address to register command.  */
 	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
@@ -79,8 +78,7 @@
 	int i;
 
 	/* this must never happen */
-	if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
-		BUG();
+	BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0);
 
 	/* Add PHY address to register command.  */
 	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
@@ -102,23 +100,6 @@
 	return 0;
 }
 
-static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
-{
-	const u32 *data;
-	int len, id, irq;
-
-	data = of_get_property(np, "reg", &len);
-	if (!data || len != 4)
-		return;
-
-	id = *data;
-	bus->phy_mask &= ~(1 << id);
-
-	irq = of_irq_to_resource(np, 0, NULL);
-	if (irq != NO_IRQ)
-		bus->irq[id] = irq;
-}
-
 static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
                                         const struct of_device_id *match)
 {
@@ -165,17 +146,10 @@
 	if (!new_bus->irq)
 		goto out_unmap_regs;
 
-	for (i = 0; i < PHY_MAX_ADDR; i++)
-		new_bus->irq[i] = -1;
-
-	while ((np = of_get_next_child(ofdev->node, np)))
-		if (!strcmp(np->type, "ethernet-phy"))
-			add_phy(new_bus, np);
-
 	new_bus->parent = &ofdev->dev;
 	dev_set_drvdata(&ofdev->dev, new_bus);
 
-	ret = mdiobus_register(new_bus);
+	ret = of_mdiobus_register(new_bus, ofdev->node);
 	if (ret)
 		goto out_free_irqs;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/fsl_pq_mdio.c linux-libre-2.6.31-gnu/drivers/net/fsl_pq_mdio.c
--- linux-libre-2.6.30-gnu/drivers/net/fsl_pq_mdio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/fsl_pq_mdio.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/of.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
 #include <asm/io.h>
@@ -154,44 +155,6 @@
 	return 0;
 }
 
-/* Allocate an array which provides irq #s for each PHY on the given bus */
-static int *create_irq_map(struct device_node *np)
-{
-	int *irqs;
-	int i;
-	struct device_node *child = NULL;
-
-	irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
-
-	if (!irqs)
-		return NULL;
-
-	for (i = 0; i < PHY_MAX_ADDR; i++)
-		irqs[i] = PHY_POLL;
-
-	while ((child = of_get_next_child(np, child)) != NULL) {
-		int irq = irq_of_parse_and_map(child, 0);
-		const u32 *id;
-
-		if (irq == NO_IRQ)
-			continue;
-
-		id = of_get_property(child, "reg", NULL);
-
-		if (!id)
-			continue;
-
-		if (*id < PHY_MAX_ADDR && *id >= 0)
-			irqs[*id] = irq;
-		else
-			printk(KERN_WARNING "%s: "
-					"%d is not a valid PHY address\n",
-					np->full_name, *id);
-	}
-
-	return irqs;
-}
-
 void fsl_pq_mdio_bus_name(char *name, struct device_node *np)
 {
 	const u32 *addr;
@@ -225,7 +188,7 @@
 }
 
 
-#ifdef CONFIG_GIANFAR
+#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
 static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
 {
 	struct gfar __iomem *enet_regs;
@@ -243,7 +206,7 @@
 #endif
 
 
-#ifdef CONFIG_UCC_GETH
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
 static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id)
 {
 	struct device_node *np = NULL;
@@ -315,7 +278,7 @@
 
 	new_bus->priv = (void __force *)regs;
 
-	new_bus->irq = create_irq_map(np);
+	new_bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
 
 	if (NULL == new_bus->irq) {
 		err = -ENOMEM;
@@ -328,7 +291,7 @@
 	if (of_device_is_compatible(np, "fsl,gianfar-mdio") ||
 			of_device_is_compatible(np, "fsl,gianfar-tbi") ||
 			of_device_is_compatible(np, "gianfar")) {
-#ifdef CONFIG_GIANFAR
+#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
 		tbipa = get_gfar_tbipa(regs);
 #else
 		err = -ENODEV;
@@ -336,15 +299,19 @@
 #endif
 	} else if (of_device_is_compatible(np, "fsl,ucc-mdio") ||
 			of_device_is_compatible(np, "ucc_geth_phy")) {
-#ifdef CONFIG_UCC_GETH
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
 		u32 id;
+		static u32 mii_mng_master;
 
 		tbipa = &regs->utbipar;
 
 		if ((err = get_ucc_id_for_range(addr, addr + size, &id)))
 			goto err_free_irqs;
 
-		ucc_set_qe_mux_mii_mng(id - 1);
+		if (!mii_mng_master) {
+			mii_mng_master = id;
+			ucc_set_qe_mux_mii_mng(id - 1);
+		}
 #else
 		err = -ENODEV;
 		goto err_free_irqs;
@@ -384,15 +351,7 @@
 
 	out_be32(tbipa, tbiaddr);
 
-	/*
-	 * The TBIPHY-only buses will find PHYs at every address,
-	 * so we mask them all but the TBI
-	 */
-	if (of_device_is_compatible(np, "fsl,gianfar-tbi"))
-		new_bus->phy_mask = ~(1 << tbiaddr);
-
-	err = mdiobus_register(new_bus);
-
+	err = of_mdiobus_register(new_bus, np);
 	if (err) {
 		printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
 				new_bus->name);
@@ -460,10 +419,10 @@
 {
 	return of_register_platform_driver(&fsl_pq_mdio_driver);
 }
+module_init(fsl_pq_mdio_init);
 
 void fsl_pq_mdio_exit(void)
 {
 	of_unregister_platform_driver(&fsl_pq_mdio_driver);
 }
-subsys_initcall_sync(fsl_pq_mdio_init);
 module_exit(fsl_pq_mdio_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/gianfar.c linux-libre-2.6.31-gnu/drivers/net/gianfar.c
--- linux-libre-2.6.30-gnu/drivers/net/gianfar.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/gianfar.c	2009-09-09 18:13:59.000000000 -0400
@@ -75,6 +75,7 @@
 #include <linux/if_vlan.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
@@ -155,6 +156,8 @@
 	.ndo_tx_timeout = gfar_timeout,
 	.ndo_do_ioctl = gfar_ioctl,
 	.ndo_vlan_rx_register = gfar_vlan_rx_register,
+	.ndo_set_mac_address = eth_mac_addr,
+	.ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = gfar_netpoll,
 #endif
@@ -168,17 +171,13 @@
 
 static int gfar_of_init(struct net_device *dev)
 {
-	struct device_node *phy, *mdio;
-	const unsigned int *id;
 	const char *model;
 	const char *ctype;
 	const void *mac_addr;
-	const phandle *ph;
 	u64 addr, size;
 	int err = 0;
 	struct gfar_private *priv = netdev_priv(dev);
 	struct device_node *np = priv->node;
-	char bus_name[MII_BUS_ID_SIZE];
 	const u32 *stash;
 	const u32 *stash_len;
 	const u32 *stash_idx;
@@ -264,66 +263,10 @@
 	if (of_get_property(np, "fsl,magic-packet", NULL))
 		priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
 
-	ph = of_get_property(np, "phy-handle", NULL);
-	if (ph == NULL) {
-		u32 *fixed_link;
-
-		fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
-		if (!fixed_link) {
-			err = -ENODEV;
-			goto err_out;
-		}
-
-		snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id),
-				PHY_ID_FMT, "0", fixed_link[0]);
-	} else {
-		phy = of_find_node_by_phandle(*ph);
-
-		if (phy == NULL) {
-			err = -ENODEV;
-			goto err_out;
-		}
-
-		mdio = of_get_parent(phy);
-
-		id = of_get_property(phy, "reg", NULL);
-
-		of_node_put(phy);
-
-		fsl_pq_mdio_bus_name(bus_name, mdio);
-		of_node_put(mdio);
-		snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x",
-				bus_name, *id);
-	}
+	priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
 
 	/* Find the TBI PHY.  If it's not there, we don't support SGMII */
-	ph = of_get_property(np, "tbi-handle", NULL);
-	if (ph) {
-		struct device_node *tbi = of_find_node_by_phandle(*ph);
-		struct of_device *ofdev;
-		struct mii_bus *bus;
-
-		if (!tbi)
-			return 0;
-
-		mdio = of_get_parent(tbi);
-		if (!mdio)
-			return 0;
-
-		ofdev = of_find_device_by_node(mdio);
-
-		of_node_put(mdio);
-
-		id = of_get_property(tbi, "reg", NULL);
-		if (!id)
-			return 0;
-
-		of_node_put(tbi);
-
-		bus = dev_get_drvdata(&ofdev->dev);
-
-		priv->tbiphy = bus->phy_map[*id];
-	}
+	priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
 
 	return 0;
 
@@ -529,6 +472,10 @@
 register_fail:
 	iounmap(priv->regs);
 regs_fail:
+	if (priv->phy_node)
+		of_node_put(priv->phy_node);
+	if (priv->tbi_node)
+		of_node_put(priv->tbi_node);
 	free_netdev(dev);
 	return err;
 }
@@ -537,8 +484,14 @@
 {
 	struct gfar_private *priv = dev_get_drvdata(&ofdev->dev);
 
+	if (priv->phy_node)
+		of_node_put(priv->phy_node);
+	if (priv->tbi_node)
+		of_node_put(priv->tbi_node);
+
 	dev_set_drvdata(&ofdev->dev, NULL);
 
+	unregister_netdev(priv->ndev);
 	iounmap(priv->regs);
 	free_netdev(priv->ndev);
 
@@ -690,7 +643,6 @@
 	uint gigabit_support =
 		priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
 		SUPPORTED_1000baseT_Full : 0;
-	struct phy_device *phydev;
 	phy_interface_t interface;
 
 	priv->oldlink = 0;
@@ -699,21 +651,22 @@
 
 	interface = gfar_get_interface(dev);
 
-	phydev = phy_connect(dev, priv->phy_bus_id, &adjust_link, 0, interface);
+	priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0,
+				      interface);
+	if (!priv->phydev)
+		priv->phydev = of_phy_connect_fixed_link(dev, &adjust_link,
+							 interface);
+	if (!priv->phydev) {
+		dev_err(&dev->dev, "could not attach to PHY\n");
+		return -ENODEV;
+	}
 
 	if (interface == PHY_INTERFACE_MODE_SGMII)
 		gfar_configure_serdes(dev);
 
-	if (IS_ERR(phydev)) {
-		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
-		return PTR_ERR(phydev);
-	}
-
 	/* Remove any features not supported by the controller */
-	phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
-	phydev->advertising = phydev->supported;
-
-	priv->phydev = phydev;
+	priv->phydev->supported &= (GFAR_SUPPORTED | gigabit_support);
+	priv->phydev->advertising = priv->phydev->supported;
 
 	return 0;
 }
@@ -730,10 +683,17 @@
 static void gfar_configure_serdes(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
+	struct phy_device *tbiphy;
 
-	if (!priv->tbiphy) {
-		printk(KERN_WARNING "SGMII mode requires that the device "
-				"tree specify a tbi-handle\n");
+	if (!priv->tbi_node) {
+		dev_warn(&dev->dev, "error: SGMII mode requires that the "
+				    "device tree specify a tbi-handle\n");
+		return;
+	}
+
+	tbiphy = of_phy_find_device(priv->tbi_node);
+	if (!tbiphy) {
+		dev_err(&dev->dev, "error: Could not get TBI device\n");
 		return;
 	}
 
@@ -743,17 +703,17 @@
 	 * everything for us?  Resetting it takes the link down and requires
 	 * several seconds for it to come back.
 	 */
-	if (phy_read(priv->tbiphy, MII_BMSR) & BMSR_LSTATUS)
+	if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS)
 		return;
 
 	/* Single clk mode, mii mode off(for serdes communication) */
-	phy_write(priv->tbiphy, MII_TBICON, TBICON_CLK_SELECT);
+	phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT);
 
-	phy_write(priv->tbiphy, MII_ADVERTISE,
+	phy_write(tbiphy, MII_ADVERTISE,
 			ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
 			ADVERTISE_1000XPSE_ASYM);
 
-	phy_write(priv->tbiphy, MII_BMCR, BMCR_ANENABLE |
+	phy_write(tbiphy, MII_BMCR, BMCR_ANENABLE |
 			BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
 }
 
@@ -977,6 +937,7 @@
 	struct gfar __iomem *regs = priv->regs;
 	int err = 0;
 	u32 rctrl = 0;
+	u32 tctrl = 0;
 	u32 attrs = 0;
 
 	gfar_write(&regs->imask, IMASK_INIT_CLEAR);
@@ -1152,11 +1113,19 @@
 		rctrl |= RCTRL_PADDING(priv->padding);
 	}
 
+	/* keep vlan related bits if it's enabled */
+	if (priv->vlgrp) {
+		rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
+		tctrl |= TCTRL_VLINS;
+	}
+
 	/* Init rctrl based on our settings */
 	gfar_write(&priv->regs->rctrl, rctrl);
 
 	if (dev->features & NETIF_F_IP_CSUM)
-		gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);
+		tctrl |= TCTRL_INIT_CSUM;
+
+	gfar_write(&priv->regs->tctrl, tctrl);
 
 	/* Set the extraction length and index */
 	attrs = ATTRELI_EL(priv->rx_stash_size) |
@@ -1242,7 +1211,8 @@
 static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
 {
 	struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN);
-	cacheable_memzero(fcb, GMAC_FCB_LEN);
+
+	memset(fcb, 0, GMAC_FCB_LEN);
 
 	return fcb;
 }
@@ -1490,7 +1460,6 @@
 
 		/* Enable VLAN tag extraction */
 		tempval = gfar_read(&priv->regs->rctrl);
-		tempval |= RCTRL_VLEX;
 		tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
 		gfar_write(&priv->regs->rctrl, tempval);
 	} else {
diff -druN linux-libre-2.6.30-gnu/drivers/net/gianfar_ethtool.c linux-libre-2.6.31-gnu/drivers/net/gianfar_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/gianfar_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/gianfar_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -366,9 +366,8 @@
 		return -EINVAL;
 	}
 
-	priv->rxic = mk_ic_value(
-		gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs),
-		cvals->rx_max_coalesced_frames);
+	priv->rxic = mk_ic_value(cvals->rx_max_coalesced_frames,
+		gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs));
 
 	/* Set up tx coalescing */
 	if ((cvals->tx_coalesce_usecs == 0) ||
@@ -390,9 +389,8 @@
 		return -EINVAL;
 	}
 
-	priv->txic = mk_ic_value(
-		gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs),
-		cvals->tx_max_coalesced_frames);
+	priv->txic = mk_ic_value(cvals->tx_max_coalesced_frames,
+		gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
 
 	gfar_write(&priv->regs->rxic, 0);
 	if (priv->rxcoalescing)
diff -druN linux-libre-2.6.30-gnu/drivers/net/gianfar.h linux-libre-2.6.31-gnu/drivers/net/gianfar.h
--- linux-libre-2.6.30-gnu/drivers/net/gianfar.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/gianfar.h	2009-09-09 18:13:59.000000000 -0400
@@ -779,7 +779,8 @@
 	spinlock_t bflock;
 
 	phy_interface_t interface;
-	char	phy_bus_id[BUS_ID_SIZE];
+	struct device_node *phy_node;
+	struct device_node *tbi_node;
 	u32 device_flags;
 	unsigned char rx_csum_enable:1,
 		extended_hash:1,
@@ -793,7 +794,6 @@
 
 	/* PHY stuff */
 	struct phy_device *phydev;
-	struct phy_device *tbiphy;
 	struct mii_bus *mii_bus;
 	int oldspeed;
 	int oldduplex;
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamachi.c linux-libre-2.6.31-gnu/drivers/net/hamachi.c
--- linux-libre-2.6.30-gnu/drivers/net/hamachi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamachi.c	2009-09-09 18:13:59.000000000 -0400
@@ -173,8 +173,8 @@
 
 static const char version[] __devinitconst =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
-KERN_INFO "   Some modifications by Eric kasten <kasten@nscl.msu.edu>\n"
-KERN_INFO "   Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n";
+"   Some modifications by Eric kasten <kasten@nscl.msu.edu>\n"
+"   Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n";
 
 
 /* IP_MF appears to be only defined in <netinet/ip.h>, however,
@@ -1080,11 +1080,14 @@
 	{
 		printk(KERN_DEBUG "  Rx ring %p: ", hmp->rx_ring);
 		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length));
-		printk("\n"KERN_DEBUG"  Tx ring %p: ", hmp->tx_ring);
+			printk(KERN_CONT " %8.8x",
+			       le32_to_cpu(hmp->rx_ring[i].status_n_length));
+		printk(KERN_CONT "\n");
+		printk(KERN_DEBUG"  Tx ring %p: ", hmp->tx_ring);
 		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length));
-		printk("\n");
+			printk(KERN_CONT " %4.4x",
+			       le32_to_cpu(hmp->tx_ring[i].status_n_length));
+		printk(KERN_CONT "\n");
 	}
 
 	/* Reinit the hardware and make sure the Rx and Tx processes
@@ -1163,7 +1166,7 @@
 	hmp->rx_ring[RX_RING_SIZE-1].status_n_length |= cpu_to_le32(DescEndRing);
 
 	/* Trigger an immediate transmit demand. */
-	dev->trans_start = jiffies;
+	dev->trans_start = jiffies; /* prevent tx timeout */
 	hmp->stats.tx_errors++;
 
 	/* Restart the chip's Tx/Rx processes . */
@@ -1280,7 +1283,7 @@
 		status=readw(hmp->base + TxStatus);
 		if( !(status & 0x0001) || (status & 0x0002))
 			writew(0x0001, hmp->base + TxCmd);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Caution: the write order is important here, set the field
@@ -1364,7 +1367,6 @@
 		hmp->tx_full = 1;
 		netif_stop_queue(dev);
 	}
-	dev->trans_start = jiffies;
 
 	if (hamachi_debug > 4) {
 		printk(KERN_DEBUG "%s: Hamachi transmit frame #%d queued in slot %d.\n",
@@ -1754,13 +1756,13 @@
 
 #ifdef __i386__
 	if (hamachi_debug > 2) {
-		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
+		printk(KERN_DEBUG "  Tx ring at %8.8x:\n",
 			   (int)hmp->tx_ring_dma);
 		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" %c #%d desc. %8.8x %8.8x.\n",
+			printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x.\n",
 				   readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ',
 				   i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr);
-		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
+		printk(KERN_DEBUG "  Rx ring %8.8x:\n",
 			   (int)hmp->rx_ring_dma);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n",
@@ -1771,7 +1773,7 @@
 					u16 *addr = (u16 *)
 						hmp->rx_skbuff[i]->data;
 					int j;
-
+					printk(KERN_DEBUG "Addr: ");
 					for (j = 0; j < 0x50; j++)
 						printk(" %4.4x", addr[j]);
 					printk("\n");
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/6pack.c linux-libre-2.6.31-gnu/drivers/net/hamradio/6pack.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/6pack.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/6pack.c	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,7 @@
  *		devices like TTY. It interfaces between a raw TTY and the
  *		kernel's AX.25 protocol layers.
  *
- * Authors:	Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ * Authors:	Andreas Könsgen <ajk@comnets.uni-bremen.de>
  *              Ralf Baechle DL5RB <ralf@linux-mips.org>
  *
  * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_epp.c linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_epp.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_epp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_epp.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,7 +68,7 @@
 
 static const char bc_drvname[] = "baycom_epp";
 static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
@@ -777,7 +777,7 @@
 		return 0;
 	}
 	if (bc->skb)
-		return -1;
+		return NETDEV_TX_LOCKED;
 	/* strip KISS byte */
 	if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) {
 		dev_kfree_skb(skb);
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_par.c linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_par.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_par.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_par.c	2009-09-09 18:13:59.000000000 -0400
@@ -102,7 +102,7 @@
 
 static const char bc_drvname[] = "baycom_par";
 static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_ser_fdx.c linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_ser_fdx.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_ser_fdx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_ser_fdx.c	2009-09-09 18:13:59.000000000 -0400
@@ -91,7 +91,7 @@
 
 static const char bc_drvname[] = "baycom_ser_fdx";
 static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_ser_hdx.c linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_ser_hdx.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/baycom_ser_hdx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/baycom_ser_hdx.c	2009-09-09 18:13:59.000000000 -0400
@@ -79,7 +79,7 @@
 
 static const char bc_drvname[] = "baycom_ser_hdx";
 static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/bpqether.c linux-libre-2.6.31-gnu/drivers/net/hamradio/bpqether.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/bpqether.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/bpqether.c	2009-09-09 18:13:59.000000000 -0400
@@ -260,7 +260,7 @@
 	 */
 	if (!netif_running(dev)) {
 		kfree_skb(skb);
-		return -ENODEV;
+		return NETDEV_TX_OK;
 	}
 
 	skb_pull(skb, 1);
@@ -274,7 +274,7 @@
 		if ((newskb = skb_realloc_headroom(skb, AX25_BPQ_HEADER_LEN)) == NULL) {
 			printk(KERN_WARNING "bpqether: out of memory\n");
 			kfree_skb(skb);
-			return -ENOMEM;
+			return NETDEV_TX_OK;
 		}
 
 		if (skb->sk != NULL)
@@ -294,7 +294,7 @@
 	if ((dev = bpq_get_ether_dev(dev)) == NULL) {
 		dev->stats.tx_dropped++;
 		kfree_skb(skb);
-		return -ENODEV;
+		return NETDEV_TX_OK;
 	}
 
 	skb->protocol = ax25_type_trans(skb, dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/hdlcdrv.c linux-libre-2.6.31-gnu/drivers/net/hamradio/hdlcdrv.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/hdlcdrv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/hdlcdrv.c	2009-09-09 18:13:59.000000000 -0400
@@ -409,7 +409,7 @@
 		return 0;
 	}
 	if (sm->skb)
-		return -1;
+		return NETDEV_TX_LOCKED;
 	netif_stop_queue(dev);
 	sm->skb = skb;
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/hamradio/mkiss.c linux-libre-2.6.31-gnu/drivers/net/hamradio/mkiss.c
--- linux-libre-2.6.30-gnu/drivers/net/hamradio/mkiss.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hamradio/mkiss.c	2009-09-09 18:13:59.000000000 -0400
@@ -531,7 +531,7 @@
 
 	if (!netif_running(dev))  {
 		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	if (netif_queue_stopped(dev)) {
@@ -541,7 +541,7 @@
 		 */
 		if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
 			/* 20 sec timeout not reached */
-			return 1;
+			return NETDEV_TX_BUSY;
 		}
 
 		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
diff -druN linux-libre-2.6.30-gnu/drivers/net/hp100.c linux-libre-2.6.31-gnu/drivers/net/hp100.c
--- linux-libre-2.6.30-gnu/drivers/net/hp100.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hp100.c	2009-09-09 18:13:59.000000000 -0400
@@ -1495,13 +1495,8 @@
 	hp100_outw(0x4210, TRACE);
 	printk("hp100: %s: start_xmit_bm\n", dev->name);
 #endif
-
-	if (skb == NULL) {
-		return 0;
-	}
-
 	if (skb->len <= 0)
-		return 0;
+		goto drop;
 
 	if (lp->chip == HP100_CHIPID_SHASTA && skb_padto(skb, ETH_ZLEN))
 		return 0;
@@ -1514,10 +1509,10 @@
 #endif
 		/* not waited long enough since last tx? */
 		if (time_before(jiffies, dev->trans_start + HZ))
-			return -EAGAIN;
+			goto drop;
 
 		if (hp100_check_lan(dev))
-			return -EIO;
+			goto drop;
 
 		if (lp->lan_type == HP100_LAN_100 && lp->hub_status < 0) {
 			/* we have a 100Mb/s adapter but it isn't connected to hub */
@@ -1551,7 +1546,7 @@
 		}
 
 		dev->trans_start = jiffies;
-		return -EAGAIN;
+		goto drop;
 	}
 
 	/*
@@ -1591,6 +1586,10 @@
 	dev->trans_start = jiffies;
 
 	return 0;
+
+drop:
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
 }
 
 
@@ -1648,16 +1647,11 @@
 	hp100_outw(0x4212, TRACE);
 	printk("hp100: %s: start_xmit\n", dev->name);
 #endif
-
-	if (skb == NULL) {
-		return 0;
-	}
-
 	if (skb->len <= 0)
-		return 0;
+		goto drop;
 
 	if (hp100_check_lan(dev))
-		return -EIO;
+		goto drop;
 
 	/* If there is not enough free memory on the card... */
 	i = hp100_inl(TX_MEM_FREE) & 0x7fffffff;
@@ -1671,7 +1665,7 @@
 			printk("hp100: %s: trans_start timing problem\n",
 			       dev->name);
 #endif
-			return -EAGAIN;
+			goto drop;
 		}
 		if (lp->lan_type == HP100_LAN_100 && lp->hub_status < 0) {
 			/* we have a 100Mb/s adapter but it isn't connected to hub */
@@ -1705,7 +1699,7 @@
 			}
 		}
 		dev->trans_start = jiffies;
-		return -EAGAIN;
+		goto drop;
 	}
 
 	for (i = 0; i < 6000 && (hp100_inb(OPTION_MSW) & HP100_TX_CMD); i++) {
@@ -1759,6 +1753,11 @@
 #endif
 
 	return 0;
+
+drop:
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+
 }
 
 
@@ -2864,7 +2863,7 @@
 	printk("hp100: %s: EISA adapter found at 0x%x\n", dev->name,
 	       dev->base_addr);
 #endif
-	gendev->driver_data = dev;
+	dev_set_drvdata(gendev, dev);
 	return 0;
  out1:
 	free_netdev(dev);
@@ -2873,7 +2872,7 @@
 
 static int __devexit hp100_eisa_remove (struct device *gendev)
 {
-	struct net_device *dev = gendev->driver_data;
+	struct net_device *dev = dev_get_drvdata(gendev);
 	cleanup_dev(dev);
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/hplance.c linux-libre-2.6.31-gnu/drivers/net/hplance.c
--- linux-libre-2.6.30-gnu/drivers/net/hplance.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/hplance.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,6 +71,19 @@
 	.remove    = __devexit_p(hplance_remove_one),
 };
 
+static const struct net_device_ops hplance_netdev_ops = {
+	.ndo_open		= hplance_open,
+	.ndo_stop		= hplance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_multicast_list	= lance_set_multicast,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= lance_poll,
+#endif
+};
+
 /* Find all the HP Lance boards and initialise them... */
 static int __devinit hplance_init_one(struct dio_dev *d,
 				const struct dio_device_id *ent)
@@ -135,13 +148,7 @@
 
         /* Fill the dev fields */
         dev->base_addr = va;
-        dev->open = &hplance_open;
-        dev->stop = &hplance_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-        dev->poll_controller = lance_poll;
-#endif
-        dev->hard_start_xmit = &lance_start_xmit;
-        dev->set_multicast_list = &lance_set_multicast;
+        dev->netdev_ops = &hplance_netdev_ops;
         dev->dma = 0;
 
         for (i=0; i<6; i++) {
diff -druN linux-libre-2.6.30-gnu/drivers/net/ibmlana.c linux-libre-2.6.31-gnu/drivers/net/ibmlana.c
--- linux-libre-2.6.30-gnu/drivers/net/ibmlana.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ibmlana.c	2009-09-09 18:13:59.000000000 -0400
@@ -815,7 +815,7 @@
 static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	ibmlana_priv *priv = netdev_priv(dev);
-	int retval = 0, tmplen, addr;
+	int tmplen, addr;
 	unsigned long flags;
 	tda_t tda;
 	int baddr;
@@ -824,7 +824,6 @@
 	   the upper layer is in deep desperation and we simply ignore the frame. */
 
 	if (priv->txusedcnt >= TXBUFCNT) {
-		retval = -EIO;
 		dev->stats.tx_dropped++;
 		goto tx_done;
 	}
@@ -874,7 +873,7 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 tx_done:
 	dev_kfree_skb(skb);
-	return retval;
+	return NETDEV_TX_OK;
 }
 
 /* switch receiver mode. */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ibm_newemac/core.c linux-libre-2.6.31-gnu/drivers/net/ibm_newemac/core.c
--- linux-libre-2.6.30-gnu/drivers/net/ibm_newemac/core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ibm_newemac/core.c	2009-09-09 18:13:59.000000000 -0400
@@ -1305,6 +1305,8 @@
 
 	free_irq(dev->emac_irq, dev);
 
+	netif_carrier_off(ndev);
+
 	return 0;
 }
 
@@ -1484,7 +1486,7 @@
  stop_queue:
 	netif_stop_queue(ndev);
 	DBG2(dev, "stopped TX queue" NL);
-	return 1;
+	return NETDEV_TX_BUSY;
 }
 
 /* Tx lock BHs */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ibm_newemac/rgmii.c linux-libre-2.6.31-gnu/drivers/net/ibm_newemac/rgmii.c
--- linux-libre-2.6.30-gnu/drivers/net/ibm_newemac/rgmii.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ibm_newemac/rgmii.c	2009-09-09 18:13:59.000000000 -0400
@@ -188,11 +188,12 @@
 void rgmii_detach(struct of_device *ofdev, int input)
 {
 	struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
-	struct rgmii_regs __iomem *p = dev->base;
-
-	mutex_lock(&dev->lock);
+	struct rgmii_regs __iomem *p;
 
 	BUG_ON(!dev || dev->users == 0);
+	p = dev->base;
+
+	mutex_lock(&dev->lock);
 
 	RGMII_DBG(dev, "detach(%d)" NL, input);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ibmveth.c linux-libre-2.6.31-gnu/drivers/net/ibmveth.c
--- linux-libre-2.6.30-gnu/drivers/net/ibmveth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ibmveth.c	2009-09-09 18:13:59.000000000 -0400
@@ -1203,6 +1203,20 @@
 	return ret;
 }
 
+static const struct net_device_ops ibmveth_netdev_ops = {
+	.ndo_open		= ibmveth_open,
+	.ndo_stop		= ibmveth_close,
+	.ndo_start_xmit		= ibmveth_start_xmit,
+	.ndo_set_multicast_list	= ibmveth_set_multicast_list,
+	.ndo_do_ioctl		= ibmveth_ioctl,
+	.ndo_change_mtu		= ibmveth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= ibmveth_poll_controller,
+#endif
+};
+
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
 	int rc, i;
@@ -1241,7 +1255,7 @@
 		return -ENOMEM;
 
 	adapter = netdev_priv(netdev);
-	dev->dev.driver_data = netdev;
+	dev_set_drvdata(&dev->dev, netdev);
 
 	adapter->vdev = dev;
 	adapter->netdev = netdev;
@@ -1265,21 +1279,13 @@
 	memcpy(&adapter->mac_addr, mac_addr_p, 6);
 
 	netdev->irq = dev->irq;
-	netdev->open               = ibmveth_open;
-	netdev->stop               = ibmveth_close;
-	netdev->hard_start_xmit    = ibmveth_start_xmit;
-	netdev->set_multicast_list = ibmveth_set_multicast_list;
-	netdev->do_ioctl           = ibmveth_ioctl;
-	netdev->ethtool_ops           = &netdev_ethtool_ops;
-	netdev->change_mtu         = ibmveth_change_mtu;
+	netdev->netdev_ops = &ibmveth_netdev_ops;
+	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	netdev->poll_controller = ibmveth_poll_controller;
-#endif
  	netdev->features |= NETIF_F_LLTX;
 	spin_lock_init(&adapter->stats_lock);
 
-	memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
+	memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
 
 	for(i = 0; i<IbmVethNumBufferPools; i++) {
 		struct kobject *kobj = &adapter->rx_buff_pool[i].kobj;
@@ -1335,7 +1341,7 @@
 
 static int __devexit ibmveth_remove(struct vio_dev *dev)
 {
-	struct net_device *netdev = dev->dev.driver_data;
+	struct net_device *netdev = dev_get_drvdata(&dev->dev);
 	struct ibmveth_adapter *adapter = netdev_priv(netdev);
 	int i;
 
@@ -1368,8 +1374,8 @@
 static int ibmveth_show(struct seq_file *seq, void *v)
 {
 	struct ibmveth_adapter *adapter = seq->private;
-	char *current_mac = ((char*) &adapter->netdev->dev_addr);
-	char *firmware_mac = ((char*) &adapter->mac_addr) ;
+	char *current_mac = (char *) adapter->netdev->dev_addr;
+	char *firmware_mac = (char *) &adapter->mac_addr;
 
 	seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
 
@@ -1468,8 +1474,8 @@
 	struct ibmveth_buff_pool *pool = container_of(kobj,
 						      struct ibmveth_buff_pool,
 						      kobj);
-	struct net_device *netdev =
-	    container_of(kobj->parent, struct device, kobj)->driver_data;
+	struct net_device *netdev = dev_get_drvdata(
+	    container_of(kobj->parent, struct device, kobj));
 	struct ibmveth_adapter *adapter = netdev_priv(netdev);
 	long value = simple_strtol(buf, NULL, 10);
 	long rc;
diff -druN linux-libre-2.6.30-gnu/drivers/net/ifb.c linux-libre-2.6.31-gnu/drivers/net/ifb.c
--- linux-libre-2.6.30-gnu/drivers/net/ifb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ifb.c	2009-09-09 18:13:59.000000000 -0400
@@ -156,6 +156,7 @@
 
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
+	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 	random_ether_addr(dev->dev_addr);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/e1000_82575.c linux-libre-2.6.31-gnu/drivers/net/igb/e1000_82575.c
--- linux-libre-2.6.30-gnu/drivers/net/igb/e1000_82575.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/e1000_82575.c	2009-09-09 18:13:59.000000000 -0400
@@ -190,6 +190,10 @@
 		phy->ops.write_reg          = igb_write_phy_reg_igp;
 	}
 
+	/* set lan id */
+	hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >>
+	               E1000_STATUS_FUNC_SHIFT;
+
 	/* Set phy->phy_addr and phy->id. */
 	ret_val = igb_get_phy_id_82575(hw);
 	if (ret_val)
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/e1000_82575.h linux-libre-2.6.31-gnu/drivers/net/igb/e1000_82575.h
--- linux-libre-2.6.30-gnu/drivers/net/igb/e1000_82575.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/e1000_82575.h	2009-09-09 18:13:59.000000000 -0400
@@ -130,6 +130,7 @@
 #define E1000_ADVTXD_MACLEN_SHIFT    9  /* Adv ctxt desc mac len shift */
 #define E1000_ADVTXD_TUCMD_IPV4    0x00000400  /* IP Packet Type: 1=IPv4 */
 #define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800  /* L4 Packet TYPE of TCP */
+#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
 /* IPSec Encrypt Enable for ESP */
 #define E1000_ADVTXD_L4LEN_SHIFT     8  /* Adv ctxt L4LEN shift */
 #define E1000_ADVTXD_MSS_SHIFT      16  /* Adv ctxt MSS shift */
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/e1000_defines.h linux-libre-2.6.31-gnu/drivers/net/igb/e1000_defines.h
--- linux-libre-2.6.30-gnu/drivers/net/igb/e1000_defines.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/e1000_defines.h	2009-09-09 18:13:59.000000000 -0400
@@ -289,8 +289,9 @@
 #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
 
 /* Receive Checksum Control */
+#define E1000_RXCSUM_IPOFL     0x00000100   /* IPv4 checksum offload */
 #define E1000_RXCSUM_TUOFL     0x00000200   /* TCP / UDP checksum offload */
-#define E1000_RXCSUM_IPPCSE    0x00001000   /* IP payload checksum enable */
+#define E1000_RXCSUM_CRCOFL    0x00000800   /* CRC32 offload enable */
 #define E1000_RXCSUM_PCSD      0x00002000   /* packet checksum disabled */
 
 /* Header split receive */
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/e1000_mbx.c linux-libre-2.6.31-gnu/drivers/net/igb/e1000_mbx.c
--- linux-libre-2.6.30-gnu/drivers/net/igb/e1000_mbx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/e1000_mbx.c	2009-09-09 18:13:59.000000000 -0400
@@ -140,13 +140,13 @@
 	struct e1000_mbx_info *mbx = &hw->mbx;
 	int countdown = mbx->timeout;
 
-	if (!mbx->ops.check_for_msg)
+	if (!countdown || !mbx->ops.check_for_msg)
 		goto out;
 
 	while (mbx->ops.check_for_msg(hw, mbx_id)) {
+		countdown--;
 		if (!countdown)
 			break;
-		countdown--;
 		udelay(mbx->usec_delay);
 	}
 out:
@@ -165,13 +165,13 @@
 	struct e1000_mbx_info *mbx = &hw->mbx;
 	int countdown = mbx->timeout;
 
-	if (!mbx->ops.check_for_ack)
+	if (!countdown || !mbx->ops.check_for_ack)
 		goto out;
 
 	while (mbx->ops.check_for_ack(hw, mbx_id)) {
+		countdown--;
 		if (!countdown)
 			break;
-		countdown--;
 		udelay(mbx->usec_delay);
 	}
 out:
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/e1000_phy.h linux-libre-2.6.31-gnu/drivers/net/igb/e1000_phy.h
--- linux-libre-2.6.30-gnu/drivers/net/igb/e1000_phy.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/e1000_phy.h	2009-09-09 18:13:59.000000000 -0400
@@ -80,7 +80,7 @@
 #define IGP02E1000_PM_D3_LPLU             0x0004 /* For all other states */
 #define IGP01E1000_PLHR_SS_DOWNGRADE      0x8000
 #define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
-#define IGP01E1000_PSSR_MDIX              0x0008
+#define IGP01E1000_PSSR_MDIX              0x0800
 #define IGP01E1000_PSSR_SPEED_MASK        0xC000
 #define IGP01E1000_PSSR_SPEED_1000MBPS    0xC000
 #define IGP02E1000_PHY_CHANNEL_NUM        4
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/e1000_regs.h linux-libre-2.6.31-gnu/drivers/net/igb/e1000_regs.h
--- linux-libre-2.6.30-gnu/drivers/net/igb/e1000_regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/e1000_regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -142,6 +142,7 @@
 #define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
 #define E1000_ETQF(_n)  (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
 
+#define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
 /* Split and Replication RX Control - RW */
 /*
  * Convenience macros
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/igb_ethtool.c linux-libre-2.6.31-gnu/drivers/net/igb/igb_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/igb/igb_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/igb_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -64,6 +64,7 @@
 	{ "rx_crc_errors", IGB_STAT(stats.crcerrs) },
 	{ "rx_frame_errors", IGB_STAT(net_stats.rx_frame_errors) },
 	{ "rx_no_buffer_count", IGB_STAT(stats.rnbc) },
+	{ "rx_queue_drop_packet_count", IGB_STAT(net_stats.rx_fifo_errors) },
 	{ "rx_missed_errors", IGB_STAT(stats.mpc) },
 	{ "tx_aborted_errors", IGB_STAT(stats.ecol) },
 	{ "tx_carrier_errors", IGB_STAT(stats.tncrs) },
@@ -96,9 +97,10 @@
 };
 
 #define IGB_QUEUE_STATS_LEN \
-	((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues + \
-	 ((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \
-	(sizeof(struct igb_queue_stats) / sizeof(u64)))
+	(((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues)* \
+	  (sizeof(struct igb_rx_queue_stats) / sizeof(u64))) + \
+	 ((((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \
+	  (sizeof(struct igb_tx_queue_stats) / sizeof(u64))))
 #define IGB_GLOBAL_STATS_LEN	\
 	sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)
 #define IGB_STATS_LEN (IGB_GLOBAL_STATS_LEN + IGB_QUEUE_STATS_LEN)
@@ -275,13 +277,17 @@
 static u32 igb_get_rx_csum(struct net_device *netdev)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
-	return adapter->rx_csum;
+	return !(adapter->flags & IGB_FLAG_RX_CSUM_DISABLED);
 }
 
 static int igb_set_rx_csum(struct net_device *netdev, u32 data)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
-	adapter->rx_csum = data;
+
+	if (data)
+		adapter->flags &= ~IGB_FLAG_RX_CSUM_DISABLED;
+	else
+		adapter->flags |= IGB_FLAG_RX_CSUM_DISABLED;
 
 	return 0;
 }
@@ -293,10 +299,16 @@
 
 static int igb_set_tx_csum(struct net_device *netdev, u32 data)
 {
-	if (data)
+	struct igb_adapter *adapter = netdev_priv(netdev);
+
+	if (data) {
 		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-	else
-		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+		if (adapter->hw.mac.type == e1000_82576)
+			netdev->features |= NETIF_F_SCTP_CSUM;
+	} else {
+		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+		                      NETIF_F_SCTP_CSUM);
+	}
 
 	return 0;
 }
@@ -1950,7 +1962,8 @@
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	u64 *queue_stat;
-	int stat_count = sizeof(struct igb_queue_stats) / sizeof(u64);
+	int stat_count_tx = sizeof(struct igb_tx_queue_stats) / sizeof(u64);
+	int stat_count_rx = sizeof(struct igb_rx_queue_stats) / sizeof(u64);
 	int j;
 	int i;
 
@@ -1963,14 +1976,14 @@
 	for (j = 0; j < adapter->num_tx_queues; j++) {
 		int k;
 		queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats;
-		for (k = 0; k < stat_count; k++)
+		for (k = 0; k < stat_count_tx; k++)
 			data[i + k] = queue_stat[k];
 		i += k;
 	}
 	for (j = 0; j < adapter->num_rx_queues; j++) {
 		int k;
 		queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats;
-		for (k = 0; k < stat_count; k++)
+		for (k = 0; k < stat_count_rx; k++)
 			data[i + k] = queue_stat[k];
 		i += k;
 	}
@@ -2004,6 +2017,8 @@
 			p += ETH_GSTRING_LEN;
 			sprintf(p, "rx_queue_%u_bytes", i);
 			p += ETH_GSTRING_LEN;
+			sprintf(p, "rx_queue_%u_drops", i);
+			p += ETH_GSTRING_LEN;
 		}
 /*		BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */
 		break;
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/igb.h linux-libre-2.6.31-gnu/drivers/net/igb/igb.h
--- linux-libre-2.6.30-gnu/drivers/net/igb/igb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/igb.h	2009-09-09 18:13:59.000000000 -0400
@@ -137,9 +137,15 @@
 	};
 };
 
-struct igb_queue_stats {
+struct igb_tx_queue_stats {
+	u64 packets;
+	u64 bytes;
+};
+
+struct igb_rx_queue_stats {
 	u64 packets;
 	u64 bytes;
+	u64 drops;
 };
 
 struct igb_ring {
@@ -167,12 +173,13 @@
 	union {
 		/* TX */
 		struct {
-			struct igb_queue_stats tx_stats;
+			struct igb_tx_queue_stats tx_stats;
 			bool detect_tx_hung;
 		};
 		/* RX */
 		struct {
-			struct igb_queue_stats rx_stats;
+			struct igb_rx_queue_stats rx_stats;
+			u64 rx_queue_drops;
 			struct napi_struct napi;
 			int set_itr;
 			struct igb_ring *buddy;
@@ -238,7 +245,6 @@
 	u64 hw_csum_err;
 	u64 hw_csum_good;
 	u32 alloc_rx_buff_failed;
-	bool rx_csum;
 	u32 gorc;
 	u64 gorc_old;
 	u16 rx_ps_hdr_size;
@@ -286,6 +292,7 @@
 #define IGB_FLAG_DCA_ENABLED       (1 << 1)
 #define IGB_FLAG_QUAD_PORT_A       (1 << 2)
 #define IGB_FLAG_NEED_CTX_IDX      (1 << 3)
+#define IGB_FLAG_RX_CSUM_DISABLED  (1 << 4)
 
 enum e1000_state_t {
 	__IGB_TESTING,
diff -druN linux-libre-2.6.30-gnu/drivers/net/igb/igb_main.c linux-libre-2.6.31-gnu/drivers/net/igb/igb_main.c
--- linux-libre-2.6.30-gnu/drivers/net/igb/igb_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igb/igb_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -127,14 +127,48 @@
 static void igb_ping_all_vfs(struct igb_adapter *);
 static void igb_msg_task(struct igb_adapter *);
 static int igb_rcv_msg_from_vf(struct igb_adapter *, u32);
-static inline void igb_set_rah_pool(struct e1000_hw *, int , int);
 static void igb_set_mc_list_pools(struct igb_adapter *, int, u16);
 static void igb_vmm_control(struct igb_adapter *);
-static inline void igb_set_vmolr(struct e1000_hw *, int);
-static inline int igb_set_vf_rlpml(struct igb_adapter *, int, int);
 static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
 static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
 
+static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
+{
+	u32 reg_data;
+
+	reg_data = rd32(E1000_VMOLR(vfn));
+	reg_data |= E1000_VMOLR_BAM |	 /* Accept broadcast */
+	            E1000_VMOLR_ROPE |   /* Accept packets matched in UTA */
+	            E1000_VMOLR_ROMPE |  /* Accept packets matched in MTA */
+	            E1000_VMOLR_AUPE |   /* Accept untagged packets */
+	            E1000_VMOLR_STRVLAN; /* Strip vlan tags */
+	wr32(E1000_VMOLR(vfn), reg_data);
+}
+
+static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
+                                 int vfn)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 vmolr;
+
+	vmolr = rd32(E1000_VMOLR(vfn));
+	vmolr &= ~E1000_VMOLR_RLPML_MASK;
+	vmolr |= size | E1000_VMOLR_LPE;
+	wr32(E1000_VMOLR(vfn), vmolr);
+
+	return 0;
+}
+
+static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
+{
+	u32 reg_data;
+
+	reg_data = rd32(E1000_RAH(entry));
+	reg_data &= ~E1000_RAH_POOL_MASK;
+	reg_data |= E1000_RAH_POOL_1 << pool;;
+	wr32(E1000_RAH(entry), reg_data);
+}
+
 #ifdef CONFIG_PM
 static int igb_suspend(struct pci_dev *, pm_message_t);
 static int igb_resume(struct pci_dev *);
@@ -942,6 +976,8 @@
 	rd32(E1000_ICR);
 	igb_irq_enable(adapter);
 
+	netif_tx_start_all_queues(adapter->netdev);
+
 	/* Fire a link change interrupt to start the watchdog. */
 	wr32(E1000_ICS, E1000_ICS_LSC);
 	return 0;
@@ -994,6 +1030,11 @@
 		igb_reset(adapter);
 	igb_clean_all_tx_rings(adapter);
 	igb_clean_all_rx_rings(adapter);
+#ifdef CONFIG_IGB_DCA
+
+	/* since we reset the hardware DCA settings were cleared */
+	igb_setup_dca(adapter);
+#endif
 }
 
 void igb_reinit_locked(struct igb_adapter *adapter)
@@ -1343,6 +1384,9 @@
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+	if (adapter->hw.mac.type == e1000_82576)
+		netdev->features |= NETIF_F_SCTP_CSUM;
+
 	adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw);
 
 	/* before reading the NVM, reset the controller to put the device in a
@@ -1390,8 +1434,6 @@
 
 	igb_validate_mdi_setting(hw);
 
-	adapter->rx_csum = 1;
-
 	/* Initial Wake on LAN setting If APM wake is enabled in the EEPROM,
 	 * enable the ACPI Magic Packet filter
 	 */
@@ -1442,22 +1484,18 @@
 	 * driver. */
 	igb_get_hw_control(adapter);
 
-	/* tell the stack to leave us alone until igb_open() is called */
-	netif_carrier_off(netdev);
-	netif_tx_stop_all_queues(netdev);
-
 	strcpy(netdev->name, "eth%d");
 	err = register_netdev(netdev);
 	if (err)
 		goto err_register;
 
+	/* carrier off reporting is important to ethtool even BEFORE open */
+	netif_carrier_off(netdev);
+
 #ifdef CONFIG_IGB_DCA
 	if (dca_add_requester(&pdev->dev) == 0) {
 		adapter->flags |= IGB_FLAG_DCA_ENABLED;
 		dev_info(&pdev->dev, "DCA enabled\n");
-		/* Always use CB2 mode, difference is masked
-		 * in the CB driver. */
-		wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2);
 		igb_setup_dca(adapter);
 	}
 #endif
@@ -1699,6 +1737,8 @@
 	if (test_bit(__IGB_TESTING, &adapter->state))
 		return -EBUSY;
 
+	netif_carrier_off(netdev);
+
 	/* allocate transmit descriptors */
 	err = igb_setup_all_tx_resources(adapter);
 	if (err)
@@ -2231,29 +2271,24 @@
 		mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX |
 			 E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);
 
-
 		wr32(E1000_MRQC, mrqc);
-
-		/* Multiqueue and raw packet checksumming are mutually
-		 * exclusive.  Note that this not the same as TCP/IP
-		 * checksumming, which works fine. */
-		rxcsum = rd32(E1000_RXCSUM);
-		rxcsum |= E1000_RXCSUM_PCSD;
-		wr32(E1000_RXCSUM, rxcsum);
-	} else {
+	} else if (adapter->vfs_allocated_count) {
 		/* Enable multi-queue for sr-iov */
-		if (adapter->vfs_allocated_count)
-			wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ);
-		/* Enable Receive Checksum Offload for TCP and UDP */
-		rxcsum = rd32(E1000_RXCSUM);
-		if (adapter->rx_csum)
-			rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE;
-		else
-			rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPPCSE);
-
-		wr32(E1000_RXCSUM, rxcsum);
+		wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ);
 	}
 
+	/* Enable Receive Checksum Offload for TCP and UDP */
+	rxcsum = rd32(E1000_RXCSUM);
+	/* Disable raw packet checksumming */
+	rxcsum |= E1000_RXCSUM_PCSD;
+
+	if (adapter->hw.mac.type == e1000_82576)
+		/* Enable Receive Checksum Offload for SCTP */
+		rxcsum |= E1000_RXCSUM_CRCOFL;
+
+	/* Don't need to set TUOFL or IPOFL, they default to 1 */
+	wr32(E1000_RXCSUM, rxcsum);
+
 	/* Set the default pool for the PF's first queue */
 	igb_configure_vt_default_pool(adapter);
 
@@ -2661,7 +2696,6 @@
 			}
 
 			netif_carrier_on(netdev);
-			netif_tx_wake_all_queues(netdev);
 
 			igb_ping_all_vfs(adapter);
 
@@ -2678,7 +2712,6 @@
 			printk(KERN_INFO "igb: %s NIC Link is Down\n",
 			       netdev->name);
 			netif_carrier_off(netdev);
-			netif_tx_stop_all_queues(netdev);
 
 			igb_ping_all_vfs(adapter);
 
@@ -2712,6 +2745,8 @@
 			 * (Do the reset outside of interrupt context). */
 			adapter->tx_timeout_count++;
 			schedule_work(&adapter->reset_task);
+			/* return immediately since reset is imminent */
+			return;
 		}
 	}
 
@@ -2895,13 +2930,13 @@
 	switch (current_itr) {
 	/* counts and packets in update_itr are dependent on these numbers */
 	case lowest_latency:
-		new_itr = 70000;
+		new_itr = 56;  /* aka 70,000 ints/sec */
 		break;
 	case low_latency:
-		new_itr = 20000; /* aka hwitr = ~200 */
+		new_itr = 196; /* aka 20,000 ints/sec */
 		break;
 	case bulk_latency:
-		new_itr = 4000;
+		new_itr = 980; /* aka 4,000 ints/sec */
 		break;
 	default:
 		break;
@@ -2920,7 +2955,8 @@
 		 * by adding intermediate steps when interrupt rate is
 		 * increasing */
 		new_itr = new_itr > adapter->itr ?
-			     min(adapter->itr + (new_itr >> 2), new_itr) :
+			     max((new_itr * adapter->itr) /
+			         (new_itr + (adapter->itr >> 2)), new_itr) :
 			     new_itr;
 		/* Don't write the value here; it resets the adapter's
 		 * internal timer, and causes us to delay far longer than
@@ -2929,7 +2965,7 @@
 		 * ends up being correct.
 		 */
 		adapter->itr = new_itr;
-		adapter->rx_ring->itr_val = 1000000000 / (new_itr * 256);
+		adapter->rx_ring->itr_val = new_itr;
 		adapter->rx_ring->set_itr = 1;
 	}
 
@@ -3068,11 +3104,15 @@
 				tu_cmd |= E1000_ADVTXD_TUCMD_IPV4;
 				if (ip_hdr(skb)->protocol == IPPROTO_TCP)
 					tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+				else if (ip_hdr(skb)->protocol == IPPROTO_SCTP)
+					tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP;
 				break;
 			case cpu_to_be16(ETH_P_IPV6):
 				/* XXX what about other V6 headers?? */
 				if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
 					tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+				else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP)
+					tu_cmd |= E1000_ADVTXD_TUCMD_L4T_SCTP;
 				break;
 			default:
 				if (unlikely(net_ratelimit()))
@@ -3133,8 +3173,7 @@
 	/* set time_stamp *before* dma to help avoid a possible race */
 	buffer_info->time_stamp = jiffies;
 	buffer_info->next_to_watch = i;
-	buffer_info->dma = map[count];
-	count++;
+	buffer_info->dma = skb_shinfo(skb)->dma_head;
 
 	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
 		struct skb_frag_struct *frag;
@@ -3158,7 +3197,7 @@
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
 
-	return count;
+	return count + 1;
 }
 
 static inline void igb_tx_queue_adv(struct igb_adapter *adapter,
@@ -3338,7 +3377,6 @@
 	if (count) {
 		igb_tx_queue_adv(adapter, tx_ring, tx_flags, count,
 			         skb->len, hdr_len);
-		netdev->trans_start = jiffies;
 		/* Make sure there is space in the ring for the next send. */
 		igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4);
 	} else {
@@ -3582,8 +3620,35 @@
 
 	/* Rx Errors */
 
+	if (hw->mac.type != e1000_82575) {
+		u32 rqdpc_tmp;
+		u64 rqdpc_total = 0;
+		int i;
+		/* Read out drops stats per RX queue.  Notice RQDPC (Receive
+		 * Queue Drop Packet Count) stats only gets incremented, if
+		 * the DROP_EN but it set (in the SRRCTL register for that
+		 * queue).  If DROP_EN bit is NOT set, then the some what
+		 * equivalent count is stored in RNBC (not per queue basis).
+		 * Also note the drop count is due to lack of available
+		 * descriptors.
+		 */
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0xFFF;
+			adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp;
+			rqdpc_total += adapter->rx_ring[i].rx_stats.drops;
+		}
+		adapter->net_stats.rx_fifo_errors = rqdpc_total;
+	}
+
+	/* Note RNBC (Receive No Buffers Count) is an not an exact
+	 * drop count as the hardware FIFO might save the day.  Thats
+	 * one of the reason for saving it in rx_fifo_errors, as its
+	 * potentially not a true drop.
+	 */
+	adapter->net_stats.rx_fifo_errors += adapter->stats.rnbc;
+
 	/* RLEC on some newer hardware can be incorrect so build
-	* our own version based on RUC and ROC */
+	 * our own version based on RUC and ROC */
 	adapter->net_stats.rx_errors = adapter->stats.rxerrc +
 		adapter->stats.crcerrs + adapter->stats.algnerrc +
 		adapter->stats.ruc + adapter->stats.roc +
@@ -3767,11 +3832,15 @@
 
 static void igb_setup_dca(struct igb_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	int i;
 
 	if (!(adapter->flags & IGB_FLAG_DCA_ENABLED))
 		return;
 
+	/* Always use CB2 mode, difference is masked in the CB driver. */
+	wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2);
+
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		adapter->tx_ring[i].cpu = -1;
 		igb_update_tx_dca(&adapter->tx_ring[i]);
@@ -4434,20 +4503,12 @@
 	bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP));
 
 	skb_record_rx_queue(skb, ring->queue_index);
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
-		if (vlan_extracted)
-			vlan_gro_receive(&ring->napi, adapter->vlgrp,
-			                 le16_to_cpu(rx_desc->wb.upper.vlan),
-			                 skb);
-		else
-			napi_gro_receive(&ring->napi, skb);
-	} else {
-		if (vlan_extracted)
-			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-			                  le16_to_cpu(rx_desc->wb.upper.vlan));
-		else
-			netif_receive_skb(skb);
-	}
+	if (vlan_extracted)
+		vlan_gro_receive(&ring->napi, adapter->vlgrp,
+		                 le16_to_cpu(rx_desc->wb.upper.vlan),
+		                 skb);
+	else
+		napi_gro_receive(&ring->napi, skb);
 }
 
 static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
@@ -4456,19 +4517,28 @@
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Ignore Checksum bit is set or checksum is disabled through ethtool */
-	if ((status_err & E1000_RXD_STAT_IXSM) || !adapter->rx_csum)
+	if ((status_err & E1000_RXD_STAT_IXSM) ||
+	    (adapter->flags & IGB_FLAG_RX_CSUM_DISABLED))
 		return;
 	/* TCP/UDP checksum error bit is set */
 	if (status_err &
 	    (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) {
+		/*
+		 * work around errata with sctp packets where the TCPE aka
+		 * L4E bit is set incorrectly on 64 byte (60 byte w/o crc)
+		 * packets, (aka let the stack check the crc32c)
+		 */
+		if (!((adapter->hw.mac.type == e1000_82576) &&
+		      (skb->len == 60)))
+			adapter->hw_csum_err++;
 		/* let the stack verify checksum errors */
-		adapter->hw_csum_err++;
 		return;
 	}
 	/* It must be a TCP or UDP packet with a valid checksum */
 	if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
+	dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err);
 	adapter->hw_csum_good++;
 }
 
@@ -4513,11 +4583,12 @@
 		cleaned = true;
 		cleaned_count++;
 
+		/* this is the fast path for the non-packet split case */
 		if (!adapter->rx_ps_hdr_size) {
 			pci_unmap_single(pdev, buffer_info->dma,
-					 adapter->rx_buffer_len +
-					   NET_IP_ALIGN,
+					 adapter->rx_buffer_len,
 					 PCI_DMA_FROMDEVICE);
+			buffer_info->dma = 0;
 			skb_put(skb, length);
 			goto send_up;
 		}
@@ -4534,8 +4605,9 @@
 
 		if (!skb_shinfo(skb)->nr_frags) {
 			pci_unmap_single(pdev, buffer_info->dma,
-					 adapter->rx_ps_hdr_size + NET_IP_ALIGN,
+					 adapter->rx_ps_hdr_size,
 					 PCI_DMA_FROMDEVICE);
+			buffer_info->dma = 0;
 			skb_put(skb, hlen);
 		}
 
@@ -4677,7 +4749,6 @@
 		bufsz = adapter->rx_ps_hdr_size;
 	else
 		bufsz = adapter->rx_buffer_len;
-	bufsz += NET_IP_ALIGN;
 
 	while (cleaned_count--) {
 		rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
@@ -4701,7 +4772,7 @@
 		}
 
 		if (!buffer_info->skb) {
-			skb = netdev_alloc_skb(netdev, bufsz);
+			skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN);
 			if (!skb) {
 				adapter->alloc_rx_buff_failed++;
 				goto no_buffers;
@@ -5302,6 +5373,9 @@
 
 	netif_device_detach(netdev);
 
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
 	if (netif_running(netdev))
 		igb_down(adapter);
 	pci_disable_device(pdev);
@@ -5378,43 +5452,6 @@
 	igb_get_hw_control(adapter);
 }
 
-static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
-{
-	u32 reg_data;
-
-	reg_data = rd32(E1000_VMOLR(vfn));
-	reg_data |= E1000_VMOLR_BAM |	 /* Accept broadcast */
-	            E1000_VMOLR_ROPE |   /* Accept packets matched in UTA */
-	            E1000_VMOLR_ROMPE |  /* Accept packets matched in MTA */
-	            E1000_VMOLR_AUPE |   /* Accept untagged packets */
-	            E1000_VMOLR_STRVLAN; /* Strip vlan tags */
-	wr32(E1000_VMOLR(vfn), reg_data);
-}
-
-static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
-                                 int vfn)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 vmolr;
-
-	vmolr = rd32(E1000_VMOLR(vfn));
-	vmolr &= ~E1000_VMOLR_RLPML_MASK;
-	vmolr |= size | E1000_VMOLR_LPE;
-	wr32(E1000_VMOLR(vfn), vmolr);
-
-	return 0;
-}
-
-static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
-{
-	u32 reg_data;
-
-	reg_data = rd32(E1000_RAH(entry));
-	reg_data &= ~E1000_RAH_POOL_MASK;
-	reg_data |= E1000_RAH_POOL_1 << pool;;
-	wr32(E1000_RAH(entry), reg_data);
-}
-
 static void igb_set_mc_list_pools(struct igb_adapter *adapter,
 				  int entry_count, u16 total_rar_filters)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/net/igbvf/ethtool.c linux-libre-2.6.31-gnu/drivers/net/igbvf/ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/igbvf/ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igbvf/ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,6 +133,24 @@
 	return -EOPNOTSUPP;
 }
 
+static u32 igbvf_get_rx_csum(struct net_device *netdev)
+{
+	struct igbvf_adapter *adapter = netdev_priv(netdev);
+	return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED);
+}
+
+static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
+{
+	struct igbvf_adapter *adapter = netdev_priv(netdev);
+
+	if (data)
+		adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
+	else
+		adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
+
+	return 0;
+}
+
 static u32 igbvf_get_tx_csum(struct net_device *netdev)
 {
 	return ((netdev->features & NETIF_F_IP_CSUM) != 0);
@@ -150,8 +168,6 @@
 static int igbvf_set_tso(struct net_device *netdev, u32 data)
 {
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
-	int i;
-	struct net_device *v_netdev;
 
 	if (data) {
 		netdev->features |= NETIF_F_TSO;
@@ -159,24 +175,10 @@
 	} else {
 		netdev->features &= ~NETIF_F_TSO;
 		netdev->features &= ~NETIF_F_TSO6;
-		/* disable TSO on all VLANs if they're present */
-		if (!adapter->vlgrp)
-			goto tso_out;
-		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
-			v_netdev = vlan_group_get_device(adapter->vlgrp, i);
-			if (!v_netdev)
-				continue;
-
-			v_netdev->features &= ~NETIF_F_TSO;
-			v_netdev->features &= ~NETIF_F_TSO6;
-			vlan_group_set_device(adapter->vlgrp, i, v_netdev);
-		}
 	}
 
-tso_out:
 	dev_info(&adapter->pdev->dev, "TSO is %s\n",
 	         data ? "Enabled" : "Disabled");
-	adapter->flags |= FLAG_TSO_FORCE;
 	return 0;
 }
 
@@ -517,6 +519,8 @@
 	.set_ringparam		= igbvf_set_ringparam,
 	.get_pauseparam		= igbvf_get_pauseparam,
 	.set_pauseparam		= igbvf_set_pauseparam,
+	.get_rx_csum            = igbvf_get_rx_csum,
+	.set_rx_csum            = igbvf_set_rx_csum,
 	.get_tx_csum		= igbvf_get_tx_csum,
 	.set_tx_csum		= igbvf_set_tx_csum,
 	.get_sg			= ethtool_op_get_sg,
diff -druN linux-libre-2.6.30-gnu/drivers/net/igbvf/igbvf.h linux-libre-2.6.31-gnu/drivers/net/igbvf/igbvf.h
--- linux-libre-2.6.30-gnu/drivers/net/igbvf/igbvf.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igbvf/igbvf.h	2009-09-09 18:13:59.000000000 -0400
@@ -45,7 +45,7 @@
 /* Interrupt defines */
 #define IGBVF_START_ITR                 648 /* ~6000 ints/sec */
 
-/* Interrupt modes, as used by the IntMode paramter */
+/* Interrupt modes, as used by the IntMode parameter */
 #define IGBVF_INT_MODE_LEGACY           0
 #define IGBVF_INT_MODE_MSI              1
 #define IGBVF_INT_MODE_MSIX             2
@@ -286,11 +286,7 @@
 };
 
 /* hardware capability, feature, and workaround flags */
-#define FLAG_HAS_HW_VLAN_FILTER           (1 << 0)
-#define FLAG_HAS_JUMBO_FRAMES             (1 << 1)
-#define FLAG_MSI_ENABLED                  (1 << 2)
-#define FLAG_RX_CSUM_ENABLED              (1 << 3)
-#define FLAG_TSO_FORCE                    (1 << 4)
+#define IGBVF_FLAG_RX_CSUM_DISABLED             (1 << 0)
 
 #define IGBVF_RX_DESC_ADV(R, i)     \
 	(&((((R).desc))[i].rx_desc))
diff -druN linux-libre-2.6.30-gnu/drivers/net/igbvf/netdev.c linux-libre-2.6.31-gnu/drivers/net/igbvf/netdev.c
--- linux-libre-2.6.30-gnu/drivers/net/igbvf/netdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igbvf/netdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -58,8 +58,7 @@
 
 static struct igbvf_info igbvf_vf_info = {
 	.mac                    = e1000_vfadapt,
-	.flags                  = FLAG_HAS_JUMBO_FRAMES
-	                          | FLAG_RX_CSUM_ENABLED,
+	.flags                  = 0,
 	.pba                    = 10,
 	.init_ops               = e1000_init_function_pointers_vf,
 };
@@ -107,8 +106,10 @@
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Ignore Checksum bit is set or checksum is disabled through ethtool */
-	if ((status_err & E1000_RXD_STAT_IXSM))
+	if ((status_err & E1000_RXD_STAT_IXSM) ||
+	    (adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED))
 		return;
+
 	/* TCP/UDP checksum error bit is set */
 	if (status_err &
 	    (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) {
@@ -116,6 +117,7 @@
 		adapter->hw_csum_err++;
 		return;
 	}
+
 	/* It must be a TCP or UDP packet with a valid checksum */
 	if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1279,7 +1281,7 @@
 	/* Setup the HW Tx Head and Tail descriptor pointers */
 	ew32(TDLEN(0), tx_ring->count * sizeof(union e1000_adv_tx_desc));
 	tdba = tx_ring->dma;
-	ew32(TDBAL(0), (tdba & DMA_32BIT_MASK));
+	ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32)));
 	ew32(TDBAH(0), (tdba >> 32));
 	ew32(TDH(0), 0);
 	ew32(TDT(0), 0);
@@ -1365,7 +1367,7 @@
 	 * the Base and Length of the Rx Descriptor Ring
 	 */
 	rdba = rx_ring->dma;
-	ew32(RDBAL(0), (rdba & DMA_32BIT_MASK));
+	ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32)));
 	ew32(RDBAH(0), (rdba >> 32));
 	ew32(RDLEN(0), rx_ring->count * sizeof(union e1000_adv_rx_desc));
 	rx_ring->head = E1000_RDH(0);
@@ -2117,8 +2119,7 @@
 	/* set time_stamp *before* dma to help avoid a possible race */
 	buffer_info->time_stamp = jiffies;
 	buffer_info->next_to_watch = i;
-	buffer_info->dma = map[count];
-	count++;
+	buffer_info->dma = skb_shinfo(skb)->dma_head;
 
 	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
 		struct skb_frag_struct *frag;
@@ -2142,7 +2143,7 @@
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
 
-	return count;
+	return count + 1;
 }
 
 static inline void igbvf_tx_queue_adv(struct igbvf_adapter *adapter,
@@ -2268,7 +2269,6 @@
 	if (count) {
 		igbvf_tx_queue_adv(adapter, tx_ring, tx_flags, count,
 		                   skb->len, hdr_len);
-		netdev->trans_start = jiffies;
 		/* Make sure there is space in the ring for the next send. */
 		igbvf_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 4);
 	} else {
@@ -2351,15 +2351,6 @@
 		return -EINVAL;
 	}
 
-	/* Jumbo frame size limits */
-	if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) {
-		if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
-			dev_err(&adapter->pdev->dev,
-			        "Jumbo Frames not supported.\n");
-			return -EINVAL;
-		}
-	}
-
 #define MAX_STD_JUMBO_FRAME_SIZE 9234
 	if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
 		dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n");
@@ -2637,15 +2628,16 @@
 		return err;
 
 	pci_using_dac = 0;
-	err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
 	if (!err) {
-		err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
 		if (!err)
 			pci_using_dac = 1;
 	} else {
-		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (err) {
-			err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+			err = pci_set_consistent_dma_mask(pdev,
+							  DMA_BIT_MASK(32));
 			if (err) {
 				dev_err(&pdev->dev, "No usable DMA "
 				        "configuration, aborting\n");
diff -druN linux-libre-2.6.30-gnu/drivers/net/igbvf/vf.c linux-libre-2.6.31-gnu/drivers/net/igbvf/vf.c
--- linux-libre-2.6.30-gnu/drivers/net/igbvf/vf.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/igbvf/vf.c	2009-09-09 18:13:59.000000000 -0400
@@ -274,6 +274,8 @@
 
 	err = mbx->ops.read_posted(hw, msgbuf, 2);
 
+	msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
+
 	/* if nacked the vlan was rejected */
 	if (!err && (msgbuf[0] == (E1000_VF_SET_VLAN | E1000_VT_MSGTYPE_NACK)))
 		err = -E1000_ERR_MAC_INIT;
@@ -317,6 +319,8 @@
 	if (!ret_val)
 		ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
 
+	msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
+
 	/* if nacked the address was rejected, use "perm_addr" */
 	if (!ret_val &&
 	    (msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
diff -druN linux-libre-2.6.30-gnu/drivers/net/ioc3-eth.c linux-libre-2.6.31-gnu/drivers/net/ioc3-eth.c
--- linux-libre-2.6.30-gnu/drivers/net/ioc3-eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ioc3-eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -530,7 +530,7 @@
 	 *   case where the checksum is right the higher layers will still
 	 *   drop the packet as appropriate.
 	 */
-	if (eh->h_proto != ntohs(ETH_P_IP))
+	if (eh->h_proto != htons(ETH_P_IP))
 		return;
 
 	ih = (struct iphdr *) ((char *)eh + ETH_HLEN);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ipg.h linux-libre-2.6.31-gnu/drivers/net/ipg.h
--- linux-libre-2.6.30-gnu/drivers/net/ipg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ipg.h	2009-09-09 18:13:59.000000000 -0400
@@ -514,7 +514,7 @@
 #define		IPG_DMALIST_ALIGN_PAD	0x07
 #define		IPG_MULTICAST_HASHTABLE_SIZE	0x40
 
-/* Number of miliseconds to wait after issuing a software reset.
+/* Number of milliseconds to wait after issuing a software reset.
  * 0x05 <= IPG_AC_RESETWAIT to account for proper 10Mbps operation.
  */
 #define         IPG_AC_RESETWAIT             0x05
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/au1k_ir.c linux-libre-2.6.31-gnu/drivers/net/irda/au1k_ir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/au1k_ir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/au1k_ir.c	2009-09-09 18:13:59.000000000 -0400
@@ -198,6 +198,14 @@
 	return io->head ? 0 : -ENOMEM;
 }
 
+static const struct net_device_ops au1k_irda_netdev_ops = {
+	.ndo_open		= au1k_irda_start,
+	.ndo_stop		= au1k_irda_stop,
+	.ndo_start_xmit		= au1k_irda_hard_xmit,
+	.ndo_tx_timeout		= au1k_tx_timeout,
+	.ndo_do_ioctl		= au1k_irda_ioctl,
+};
+
 static int au1k_irda_net_init(struct net_device *dev)
 {
 	struct au1k_private *aup = netdev_priv(dev);
@@ -209,11 +217,7 @@
 	if (err)
 		goto out1;
 
-	dev->open = au1k_irda_start;
-	dev->hard_start_xmit = au1k_irda_hard_xmit;
-	dev->stop = au1k_irda_stop;
-	dev->do_ioctl = au1k_irda_ioctl;
-	dev->tx_timeout = au1k_tx_timeout;
+	dev->netdev_ops = &au1k_irda_netdev_ops;
 
 	irda_init_max_qos_capabilies(&aup->qos);
 
@@ -504,13 +508,13 @@
 		printk(KERN_DEBUG "%s: tx_full\n", dev->name);
 		netif_stop_queue(dev);
 		aup->tx_full = 1;
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) {
 		printk(KERN_DEBUG "%s: tx_full\n", dev->name);
 		netif_stop_queue(dev);
 		aup->tx_full = 1;
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	pDB = aup->tx_db_inuse[aup->tx_head];
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/bfin_sir.c linux-libre-2.6.31-gnu/drivers/net/irda/bfin_sir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/bfin_sir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/irda/bfin_sir.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,824 @@
+/*
+ * Blackfin Infra-red Driver
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+#include "bfin_sir.h"
+
+#ifdef CONFIG_SIR_BFIN_DMA
+#define DMA_SIR_RX_XCNT        10
+#define DMA_SIR_RX_YCNT        (PAGE_SIZE / DMA_SIR_RX_XCNT)
+#define DMA_SIR_RX_FLUSH_JIFS  (HZ * 4 / 250)
+#endif
+
+#if ANOMALY_05000447
+static int max_rate = 57600;
+#else
+static int max_rate = 115200;
+#endif
+
+static void turnaround_delay(unsigned long last_jif, int mtt)
+{
+	long ticks;
+
+	mtt = mtt < 10000 ? 10000 : mtt;
+	ticks = 1 + mtt / (USEC_PER_SEC / HZ);
+	schedule_timeout_uninterruptible(ticks);
+}
+
+static void __devinit bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev)
+{
+	int i;
+	struct resource *res;
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		res = &pdev->resource[i];
+		switch (res->flags) {
+		case IORESOURCE_MEM:
+			sp->membase   = (void __iomem *)res->start;
+			break;
+		case IORESOURCE_IRQ:
+			sp->irq = res->start;
+			break;
+		case IORESOURCE_DMA:
+			sp->rx_dma_channel = res->start;
+			sp->tx_dma_channel = res->end;
+			break;
+		default:
+			break;
+		}
+	}
+
+	sp->clk = get_sclk();
+#ifdef CONFIG_SIR_BFIN_DMA
+	sp->tx_done        = 1;
+	init_timer(&(sp->rx_dma_timer));
+#endif
+}
+
+static void bfin_sir_stop_tx(struct bfin_sir_port *port)
+{
+#ifdef CONFIG_SIR_BFIN_DMA
+	disable_dma(port->tx_dma_channel);
+#endif
+
+	while (!(SIR_UART_GET_LSR(port) & THRE)) {
+		cpu_relax();
+		continue;
+	}
+
+	SIR_UART_STOP_TX(port);
+}
+
+static void bfin_sir_enable_tx(struct bfin_sir_port *port)
+{
+	SIR_UART_ENABLE_TX(port);
+}
+
+static void bfin_sir_stop_rx(struct bfin_sir_port *port)
+{
+	SIR_UART_STOP_RX(port);
+}
+
+static void bfin_sir_enable_rx(struct bfin_sir_port *port)
+{
+	SIR_UART_ENABLE_RX(port);
+}
+
+static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed)
+{
+	int ret = -EINVAL;
+	unsigned int quot;
+	unsigned short val, lsr, lcr;
+	static int utime;
+	int count = 10;
+
+	lcr = WLS(8);
+
+	switch (speed) {
+	case 9600:
+	case 19200:
+	case 38400:
+	case 57600:
+	case 115200:
+
+		quot = (port->clk + (8 * speed)) / (16 * speed)\
+						- ANOMALY_05000230;
+
+		do {
+			udelay(utime);
+			lsr = SIR_UART_GET_LSR(port);
+		} while (!(lsr & TEMT) && count--);
+
+		/* The useconds for 1 bits to transmit */
+		utime = 1000000 / speed + 1;
+
+		/* Clear UCEN bit to reset the UART state machine
+		 * and control registers
+		 */
+		val = SIR_UART_GET_GCTL(port);
+		val &= ~UCEN;
+		SIR_UART_PUT_GCTL(port, val);
+
+		/* Set DLAB in LCR to Access THR RBR IER */
+		SIR_UART_SET_DLAB(port);
+		SSYNC();
+
+		SIR_UART_PUT_DLL(port, quot & 0xFF);
+		SIR_UART_PUT_DLH(port, (quot >> 8) & 0xFF);
+		SSYNC();
+
+		/* Clear DLAB in LCR */
+		SIR_UART_CLEAR_DLAB(port);
+		SSYNC();
+
+		SIR_UART_PUT_LCR(port, lcr);
+
+		val = SIR_UART_GET_GCTL(port);
+		val |= UCEN;
+		SIR_UART_PUT_GCTL(port, val);
+
+		ret = 0;
+		break;
+	default:
+		printk(KERN_WARNING "bfin_sir: Invalid speed %d\n", speed);
+		break;
+	}
+
+	val = SIR_UART_GET_GCTL(port);
+	/* If not add the 'RPOLC', we can't catch the receive interrupt.
+	 * It's related with the HW layout and the IR transiver.
+	 */
+	val |= IREN | RPOLC;
+	SIR_UART_PUT_GCTL(port, val);
+	return ret;
+}
+
+static int bfin_sir_is_receiving(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+
+	if (!(SIR_UART_GET_IER(port) & ERBFI))
+		return 0;
+	return self->rx_buff.state != OUTSIDE_FRAME;
+}
+
+#ifdef CONFIG_SIR_BFIN_PIO
+static void bfin_sir_tx_chars(struct net_device *dev)
+{
+	unsigned int chr;
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+
+	if (self->tx_buff.len != 0) {
+		chr = *(self->tx_buff.data);
+		SIR_UART_PUT_CHAR(port, chr);
+		self->tx_buff.data++;
+		self->tx_buff.len--;
+	} else {
+		self->stats.tx_packets++;
+		self->stats.tx_bytes += self->tx_buff.data - self->tx_buff.head;
+		if (self->newspeed) {
+			bfin_sir_set_speed(port, self->newspeed);
+			self->speed = self->newspeed;
+			self->newspeed = 0;
+		}
+		bfin_sir_stop_tx(port);
+		bfin_sir_enable_rx(port);
+		/* I'm hungry! */
+		netif_wake_queue(dev);
+	}
+}
+
+static void bfin_sir_rx_chars(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+	unsigned char ch;
+
+	SIR_UART_CLEAR_LSR(port);
+	ch = SIR_UART_GET_CHAR(port);
+	async_unwrap_char(dev, &self->stats, &self->rx_buff, ch);
+	dev->last_rx = jiffies;
+}
+
+static irqreturn_t bfin_sir_rx_int(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+
+	spin_lock(&self->lock);
+	while ((SIR_UART_GET_LSR(port) & DR))
+		bfin_sir_rx_chars(dev);
+	spin_unlock(&self->lock);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t bfin_sir_tx_int(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+
+	spin_lock(&self->lock);
+	if (SIR_UART_GET_LSR(port) & THRE)
+		bfin_sir_tx_chars(dev);
+	spin_unlock(&self->lock);
+
+	return IRQ_HANDLED;
+}
+#endif /* CONFIG_SIR_BFIN_PIO */
+
+#ifdef CONFIG_SIR_BFIN_DMA
+static void bfin_sir_dma_tx_chars(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+
+	if (!port->tx_done)
+		return;
+	port->tx_done = 0;
+
+	if (self->tx_buff.len == 0) {
+		self->stats.tx_packets++;
+		if (self->newspeed) {
+			bfin_sir_set_speed(port, self->newspeed);
+			self->speed = self->newspeed;
+			self->newspeed = 0;
+		}
+		bfin_sir_enable_rx(port);
+		port->tx_done = 1;
+		netif_wake_queue(dev);
+		return;
+	}
+
+	blackfin_dcache_flush_range((unsigned long)(self->tx_buff.data),
+		(unsigned long)(self->tx_buff.data+self->tx_buff.len));
+	set_dma_config(port->tx_dma_channel,
+		set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP,
+			INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8,
+			DMA_SYNC_RESTART));
+	set_dma_start_addr(port->tx_dma_channel,
+		(unsigned long)(self->tx_buff.data));
+	set_dma_x_count(port->tx_dma_channel, self->tx_buff.len);
+	set_dma_x_modify(port->tx_dma_channel, 1);
+	enable_dma(port->tx_dma_channel);
+}
+
+static irqreturn_t bfin_sir_dma_tx_int(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+
+	spin_lock(&self->lock);
+	if (!(get_dma_curr_irqstat(port->tx_dma_channel) & DMA_RUN)) {
+		clear_dma_irqstat(port->tx_dma_channel);
+		bfin_sir_stop_tx(port);
+
+		self->stats.tx_packets++;
+		self->stats.tx_bytes += self->tx_buff.len;
+		self->tx_buff.len = 0;
+		if (self->newspeed) {
+			bfin_sir_set_speed(port, self->newspeed);
+			self->speed = self->newspeed;
+			self->newspeed = 0;
+		}
+		bfin_sir_enable_rx(port);
+		/* I'm hungry! */
+		netif_wake_queue(dev);
+		port->tx_done = 1;
+	}
+	spin_unlock(&self->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void bfin_sir_dma_rx_chars(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+	int i;
+
+	SIR_UART_CLEAR_LSR(port);
+
+	for (i = port->rx_dma_buf.head; i < port->rx_dma_buf.tail; i++)
+		async_unwrap_char(dev, &self->stats, &self->rx_buff, port->rx_dma_buf.buf[i]);
+}
+
+void bfin_sir_rx_dma_timeout(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+	int x_pos, pos;
+	unsigned long flags;
+
+	spin_lock_irqsave(&self->lock, flags);
+	x_pos = DMA_SIR_RX_XCNT - get_dma_curr_xcount(port->rx_dma_channel);
+	if (x_pos == DMA_SIR_RX_XCNT)
+		x_pos = 0;
+
+	pos = port->rx_dma_nrows * DMA_SIR_RX_XCNT + x_pos;
+
+	if (pos > port->rx_dma_buf.tail) {
+		port->rx_dma_buf.tail = pos;
+		bfin_sir_dma_rx_chars(dev);
+		port->rx_dma_buf.head = port->rx_dma_buf.tail;
+	}
+	spin_unlock_irqrestore(&self->lock, flags);
+}
+
+static irqreturn_t bfin_sir_dma_rx_int(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+	unsigned short irqstat;
+
+	spin_lock(&self->lock);
+
+	port->rx_dma_nrows++;
+	port->rx_dma_buf.tail = DMA_SIR_RX_XCNT * port->rx_dma_nrows;
+	bfin_sir_dma_rx_chars(dev);
+	if (port->rx_dma_nrows >= DMA_SIR_RX_YCNT) {
+		port->rx_dma_nrows = 0;
+		port->rx_dma_buf.tail = 0;
+	}
+	port->rx_dma_buf.head = port->rx_dma_buf.tail;
+
+	irqstat = get_dma_curr_irqstat(port->rx_dma_channel);
+	clear_dma_irqstat(port->rx_dma_channel);
+	spin_unlock(&self->lock);
+
+	mod_timer(&port->rx_dma_timer, jiffies + DMA_SIR_RX_FLUSH_JIFS);
+	return IRQ_HANDLED;
+}
+#endif /* CONFIG_SIR_BFIN_DMA */
+
+static int bfin_sir_startup(struct bfin_sir_port *port, struct net_device *dev)
+{
+#ifdef CONFIG_SIR_BFIN_DMA
+	dma_addr_t dma_handle;
+#endif /* CONFIG_SIR_BFIN_DMA */
+
+	if (request_dma(port->rx_dma_channel, "BFIN_UART_RX") < 0) {
+		dev_warn(&dev->dev, "Unable to attach SIR RX DMA channel\n");
+		return -EBUSY;
+	}
+
+	if (request_dma(port->tx_dma_channel, "BFIN_UART_TX") < 0) {
+		dev_warn(&dev->dev, "Unable to attach SIR TX DMA channel\n");
+		free_dma(port->rx_dma_channel);
+		return -EBUSY;
+	}
+
+#ifdef CONFIG_SIR_BFIN_DMA
+
+	set_dma_callback(port->rx_dma_channel, bfin_sir_dma_rx_int, dev);
+	set_dma_callback(port->tx_dma_channel, bfin_sir_dma_tx_int, dev);
+
+	port->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA);
+	port->rx_dma_buf.head = 0;
+	port->rx_dma_buf.tail = 0;
+	port->rx_dma_nrows = 0;
+
+	set_dma_config(port->rx_dma_channel,
+				set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO,
+									INTR_ON_ROW, DIMENSION_2D,
+									DATA_SIZE_8, DMA_SYNC_RESTART));
+	set_dma_x_count(port->rx_dma_channel, DMA_SIR_RX_XCNT);
+	set_dma_x_modify(port->rx_dma_channel, 1);
+	set_dma_y_count(port->rx_dma_channel, DMA_SIR_RX_YCNT);
+	set_dma_y_modify(port->rx_dma_channel, 1);
+	set_dma_start_addr(port->rx_dma_channel, (unsigned long)port->rx_dma_buf.buf);
+	enable_dma(port->rx_dma_channel);
+
+	port->rx_dma_timer.data = (unsigned long)(dev);
+	port->rx_dma_timer.function = (void *)bfin_sir_rx_dma_timeout;
+
+#else
+
+	if (request_irq(port->irq, bfin_sir_rx_int, IRQF_DISABLED, "BFIN_SIR_RX", dev)) {
+		dev_warn(&dev->dev, "Unable to attach SIR RX interrupt\n");
+		return -EBUSY;
+	}
+
+	if (request_irq(port->irq+1, bfin_sir_tx_int, IRQF_DISABLED, "BFIN_SIR_TX", dev)) {
+		dev_warn(&dev->dev, "Unable to attach SIR TX interrupt\n");
+		free_irq(port->irq, dev);
+		return -EBUSY;
+	}
+#endif
+
+	return 0;
+}
+
+static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev)
+{
+	unsigned short val;
+
+	bfin_sir_stop_rx(port);
+	SIR_UART_DISABLE_INTS(port);
+
+	val = SIR_UART_GET_GCTL(port);
+	val &= ~(UCEN | IREN | RPOLC);
+	SIR_UART_PUT_GCTL(port, val);
+
+#ifdef CONFIG_SIR_BFIN_DMA
+	disable_dma(port->tx_dma_channel);
+	disable_dma(port->rx_dma_channel);
+	del_timer(&(port->rx_dma_timer));
+	dma_free_coherent(NULL, PAGE_SIZE, port->rx_dma_buf.buf, 0);
+#else
+	free_irq(port->irq+1, dev);
+	free_irq(port->irq, dev);
+#endif
+	free_dma(port->tx_dma_channel);
+	free_dma(port->rx_dma_channel);
+}
+
+#ifdef CONFIG_PM
+static int bfin_sir_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct bfin_sir_port *sir_port;
+	struct net_device *dev;
+	struct bfin_sir_self *self;
+
+	sir_port = platform_get_drvdata(pdev);
+	if (!sir_port)
+		return 0;
+
+	dev = sir_port->dev;
+	self = netdev_priv(dev);
+	if (self->open) {
+		flush_work(&self->work);
+		bfin_sir_shutdown(self->sir_port, dev);
+		netif_device_detach(dev);
+	}
+
+	return 0;
+}
+static int bfin_sir_resume(struct platform_device *pdev)
+{
+	struct bfin_sir_port *sir_port;
+	struct net_device *dev;
+	struct bfin_sir_self *self;
+	struct bfin_sir_port *port;
+
+	sir_port = platform_get_drvdata(pdev);
+	if (!sir_port)
+		return 0;
+
+	dev = sir_port->dev;
+	self = netdev_priv(dev);
+	port = self->sir_port;
+	if (self->open) {
+		if (self->newspeed) {
+			self->speed = self->newspeed;
+			self->newspeed = 0;
+		}
+		bfin_sir_startup(port, dev);
+		bfin_sir_set_speed(port, 9600);
+		bfin_sir_enable_rx(port);
+		netif_device_attach(dev);
+	}
+	return 0;
+}
+#else
+#define bfin_sir_suspend   NULL
+#define bfin_sir_resume    NULL
+#endif
+
+static void bfin_sir_send_work(struct work_struct *work)
+{
+	struct bfin_sir_self  *self = container_of(work, struct bfin_sir_self, work);
+	struct net_device *dev = self->sir_port->dev;
+	struct bfin_sir_port *port = self->sir_port;
+	unsigned short val;
+	int tx_cnt = 10;
+
+	while (bfin_sir_is_receiving(dev) && --tx_cnt)
+		turnaround_delay(dev->last_rx, self->mtt);
+
+	bfin_sir_stop_rx(port);
+
+	/* To avoid losting RX interrupt, we reset IR function before
+	 * sending data. We also can set the speed, which will
+	 * reset all the UART.
+	 */
+	val = SIR_UART_GET_GCTL(port);
+	val &= ~(IREN | RPOLC);
+	SIR_UART_PUT_GCTL(port, val);
+	SSYNC();
+	val |= IREN | RPOLC;
+	SIR_UART_PUT_GCTL(port, val);
+	SSYNC();
+	/* bfin_sir_set_speed(port, self->speed); */
+
+#ifdef CONFIG_SIR_BFIN_DMA
+	bfin_sir_dma_tx_chars(dev);
+#endif
+	bfin_sir_enable_tx(port);
+	dev->trans_start = jiffies;
+}
+
+static int bfin_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+	int speed = irda_get_next_speed(skb);
+
+	netif_stop_queue(dev);
+
+	self->mtt = irda_get_mtt(skb);
+
+	if (speed != self->speed && speed != -1)
+		self->newspeed = speed;
+
+	self->tx_buff.data = self->tx_buff.head;
+	if (skb->len == 0)
+		self->tx_buff.len = 0;
+	else
+		self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, self->tx_buff.truesize);
+
+	schedule_work(&self->work);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static int bfin_sir_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+	struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+	int ret = 0;
+
+	switch (cmd) {
+	case SIOCSBANDWIDTH:
+		if (capable(CAP_NET_ADMIN)) {
+			if (self->open) {
+				ret = bfin_sir_set_speed(port, rq->ifr_baudrate);
+				bfin_sir_enable_rx(port);
+			} else {
+				dev_warn(&dev->dev, "SIOCSBANDWIDTH: !netif_running\n");
+				ret = 0;
+			}
+		}
+		break;
+
+	case SIOCSMEDIABUSY:
+		ret = -EPERM;
+		if (capable(CAP_NET_ADMIN)) {
+			irda_device_set_media_busy(dev, TRUE);
+			ret = 0;
+		}
+		break;
+
+	case SIOCGRECEIVING:
+		rq->ifr_receiving = bfin_sir_is_receiving(dev);
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+static struct net_device_stats *bfin_sir_stats(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+
+	return &self->stats;
+}
+
+static int bfin_sir_open(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+	struct bfin_sir_port *port = self->sir_port;
+	int err = -ENOMEM;
+
+	self->newspeed = 0;
+	self->speed = 9600;
+
+	spin_lock_init(&self->lock);
+
+	err = bfin_sir_startup(port, dev);
+	if (err)
+		goto err_startup;
+
+	bfin_sir_set_speed(port, 9600);
+
+	self->irlap = irlap_open(dev, &self->qos, DRIVER_NAME);
+	if (!self->irlap)
+		goto err_irlap;
+
+	INIT_WORK(&self->work, bfin_sir_send_work);
+
+	/*
+	 * Now enable the interrupt then start the queue
+	 */
+	self->open = 1;
+	bfin_sir_enable_rx(port);
+
+	netif_start_queue(dev);
+
+	return 0;
+
+err_irlap:
+	self->open = 0;
+	bfin_sir_shutdown(port, dev);
+err_startup:
+	return err;
+}
+
+static int bfin_sir_stop(struct net_device *dev)
+{
+	struct bfin_sir_self *self = netdev_priv(dev);
+
+	flush_work(&self->work);
+	bfin_sir_shutdown(self->sir_port, dev);
+
+	if (self->rxskb) {
+		dev_kfree_skb(self->rxskb);
+		self->rxskb = NULL;
+	}
+
+	/* Stop IrLAP */
+	if (self->irlap) {
+		irlap_close(self->irlap);
+		self->irlap = NULL;
+	}
+
+	netif_stop_queue(dev);
+	self->open = 0;
+
+	return 0;
+}
+
+static int bfin_sir_init_iobuf(iobuff_t *io, int size)
+{
+	io->head = kmalloc(size, GFP_KERNEL);
+	if (!io->head)
+		return -ENOMEM;
+	io->truesize = size;
+	io->in_frame = FALSE;
+	io->state    = OUTSIDE_FRAME;
+	io->data     = io->head;
+	return 0;
+}
+
+static const struct net_device_ops bfin_sir_ndo = {
+	.ndo_open		= bfin_sir_open,
+	.ndo_stop		= bfin_sir_stop,
+	.ndo_start_xmit		= bfin_sir_hard_xmit,
+	.ndo_do_ioctl		= bfin_sir_ioctl,
+	.ndo_get_stats		= bfin_sir_stats,
+};
+
+static int __devinit bfin_sir_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct bfin_sir_self *self;
+	unsigned int baudrate_mask;
+	struct bfin_sir_port *sir_port;
+	int err;
+
+	if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(per) && \
+				per[pdev->id][3] == pdev->id) {
+		err = peripheral_request_list(per[pdev->id], DRIVER_NAME);
+		if (err)
+			return err;
+	} else {
+		dev_err(&pdev->dev, "Invalid pdev id, please check board file\n");
+		return -ENODEV;
+	}
+
+	err = -ENOMEM;
+	sir_port = kmalloc(sizeof(*sir_port), GFP_KERNEL);
+	if (!sir_port)
+		goto err_mem_0;
+
+	bfin_sir_init_ports(sir_port, pdev);
+
+	dev = alloc_irdadev(sizeof(*self));
+	if (!dev)
+		goto err_mem_1;
+
+	self = netdev_priv(dev);
+	self->dev = &pdev->dev;
+	self->sir_port = sir_port;
+	sir_port->dev = dev;
+
+	err = bfin_sir_init_iobuf(&self->rx_buff, IRDA_SKB_MAX_MTU);
+	if (err)
+		goto err_mem_2;
+	err = bfin_sir_init_iobuf(&self->tx_buff, IRDA_SIR_MAX_FRAME);
+	if (err)
+		goto err_mem_3;
+
+	dev->netdev_ops = &bfin_sir_ndo;
+	dev->irq = sir_port->irq;
+
+	irda_init_max_qos_capabilies(&self->qos);
+
+	baudrate_mask = IR_9600;
+
+	switch (max_rate) {
+	case 115200:
+		baudrate_mask |= IR_115200;
+	case 57600:
+		baudrate_mask |= IR_57600;
+	case 38400:
+		baudrate_mask |= IR_38400;
+	case 19200:
+		baudrate_mask |= IR_19200;
+	case 9600:
+		break;
+	default:
+		dev_warn(&pdev->dev, "Invalid maximum baud rate, using 9600\n");
+	}
+
+	self->qos.baud_rate.bits &= baudrate_mask;
+
+	self->qos.min_turn_time.bits = 1; /* 10 ms or more */
+
+	irda_qos_bits_to_value(&self->qos);
+
+	err = register_netdev(dev);
+
+	if (err) {
+		kfree(self->tx_buff.head);
+err_mem_3:
+		kfree(self->rx_buff.head);
+err_mem_2:
+		free_netdev(dev);
+err_mem_1:
+		kfree(sir_port);
+err_mem_0:
+		peripheral_free_list(per[pdev->id]);
+	} else
+		platform_set_drvdata(pdev, sir_port);
+
+	return err;
+}
+
+static int __devexit bfin_sir_remove(struct platform_device *pdev)
+{
+	struct bfin_sir_port *sir_port;
+	struct net_device *dev = NULL;
+	struct bfin_sir_self *self;
+
+	sir_port = platform_get_drvdata(pdev);
+	if (!sir_port)
+		return 0;
+	dev = sir_port->dev;
+	self = netdev_priv(dev);
+	unregister_netdev(dev);
+	kfree(self->tx_buff.head);
+	kfree(self->rx_buff.head);
+	free_netdev(dev);
+	kfree(sir_port);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver bfin_ir_driver = {
+	.probe   = bfin_sir_probe,
+	.remove  = __devexit_p(bfin_sir_remove),
+	.suspend = bfin_sir_suspend,
+	.resume  = bfin_sir_resume,
+	.driver  = {
+		.name = DRIVER_NAME,
+	},
+};
+
+static int __init bfin_sir_init(void)
+{
+	return platform_driver_register(&bfin_ir_driver);
+}
+
+static void __exit bfin_sir_exit(void)
+{
+	platform_driver_unregister(&bfin_ir_driver);
+}
+
+module_init(bfin_sir_init);
+module_exit(bfin_sir_exit);
+
+module_param(max_rate, int, 0);
+MODULE_PARM_DESC(max_rate, "Maximum baud rate (115200, 57600, 38400, 19200, 9600)");
+
+MODULE_AUTHOR("Graf Yang <graf.yang@analog.com>");
+MODULE_DESCRIPTION("Blackfin IrDA driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/bfin_sir.h linux-libre-2.6.31-gnu/drivers/net/irda/bfin_sir.h
--- linux-libre-2.6.30-gnu/drivers/net/irda/bfin_sir.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/irda/bfin_sir.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,148 @@
+/*
+ * Blackfin Infra-red Driver
+ *
+ * Copyright 2006-2009 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ */
+
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+
+#include <asm/irq.h>
+#include <asm/cacheflush.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#ifdef CONFIG_SIR_BFIN_DMA
+struct dma_rx_buf {
+	char *buf;
+	int head;
+	int tail;
+};
+#endif
+
+struct bfin_sir_port {
+	unsigned char __iomem   *membase;
+	unsigned int            irq;
+	unsigned int            lsr;
+	unsigned long           clk;
+	struct net_device       *dev;
+#ifdef CONFIG_SIR_BFIN_DMA
+	int                     tx_done;
+	struct dma_rx_buf       rx_dma_buf;
+	struct timer_list       rx_dma_timer;
+	int                     rx_dma_nrows;
+#endif
+	unsigned int            tx_dma_channel;
+	unsigned int            rx_dma_channel;
+};
+
+struct bfin_sir_port_res {
+	unsigned long   base_addr;
+	int             irq;
+	unsigned int    rx_dma_channel;
+	unsigned int    tx_dma_channel;
+};
+
+struct bfin_sir_self {
+	struct bfin_sir_port    *sir_port;
+	spinlock_t              lock;
+	unsigned int            open;
+	int                     speed;
+	int                     newspeed;
+
+	struct sk_buff          *txskb;
+	struct sk_buff          *rxskb;
+	struct net_device_stats stats;
+	struct device           *dev;
+	struct irlap_cb         *irlap;
+	struct qos_info         qos;
+
+	iobuff_t                tx_buff;
+	iobuff_t                rx_buff;
+
+	struct work_struct      work;
+	int                     mtt;
+};
+
+#define DRIVER_NAME "bfin_sir"
+
+#define SIR_UART_GET_CHAR(port)    bfin_read16((port)->membase + OFFSET_RBR)
+#define SIR_UART_GET_DLL(port)     bfin_read16((port)->membase + OFFSET_DLL)
+#define SIR_UART_GET_DLH(port)     bfin_read16((port)->membase + OFFSET_DLH)
+#define SIR_UART_GET_LCR(port)     bfin_read16((port)->membase + OFFSET_LCR)
+#define SIR_UART_GET_GCTL(port)    bfin_read16((port)->membase + OFFSET_GCTL)
+
+#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
+#define SIR_UART_PUT_DLL(port, v)  bfin_write16(((port)->membase + OFFSET_DLL), v)
+#define SIR_UART_PUT_DLH(port, v)  bfin_write16(((port)->membase + OFFSET_DLH), v)
+#define SIR_UART_PUT_LCR(port, v)  bfin_write16(((port)->membase + OFFSET_LCR), v)
+#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
+
+#ifdef CONFIG_BF54x
+#define SIR_UART_GET_LSR(port)     bfin_read16((port)->membase + OFFSET_LSR)
+#define SIR_UART_GET_IER(port)     bfin_read16((port)->membase + OFFSET_IER_SET)
+#define SIR_UART_SET_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER_SET), v)
+#define SIR_UART_CLEAR_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v)
+#define SIR_UART_PUT_LSR(port, v)  bfin_write16(((port)->membase + OFFSET_LSR), v)
+#define SIR_UART_CLEAR_LSR(port)   bfin_write16(((port)->membase + OFFSET_LSR), -1)
+
+#define SIR_UART_SET_DLAB(port)
+#define SIR_UART_CLEAR_DLAB(port)
+
+#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_SET_IER(port, v)
+#define SIR_UART_DISABLE_INTS(port)   SIR_UART_CLEAR_IER(port, 0xF)
+#define SIR_UART_STOP_TX(port)     do { SIR_UART_PUT_LSR(port, TFI); SIR_UART_CLEAR_IER(port, ETBEI); } while (0)
+#define SIR_UART_ENABLE_TX(port)   do { SIR_UART_SET_IER(port, ETBEI); } while (0)
+#define SIR_UART_STOP_RX(port)     do { SIR_UART_CLEAR_IER(port, ERBFI); } while (0)
+#define SIR_UART_ENABLE_RX(port)   do { SIR_UART_SET_IER(port, ERBFI); } while (0)
+#else
+
+#define SIR_UART_GET_IIR(port)     bfin_read16((port)->membase + OFFSET_IIR)
+#define SIR_UART_GET_IER(port)     bfin_read16((port)->membase + OFFSET_IER)
+#define SIR_UART_PUT_IER(port, v)  bfin_write16(((port)->membase + OFFSET_IER), v)
+
+#define SIR_UART_SET_DLAB(port)    do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) | DLAB); } while (0)
+#define SIR_UART_CLEAR_DLAB(port)  do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) & ~DLAB); } while (0)
+
+#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_PUT_IER(port, v)
+#define SIR_UART_DISABLE_INTS(port)   SIR_UART_PUT_IER(port, 0)
+#define SIR_UART_STOP_TX(port)     do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ETBEI); } while (0)
+#define SIR_UART_ENABLE_TX(port)   do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ETBEI); } while (0)
+#define SIR_UART_STOP_RX(port)     do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ERBFI); } while (0)
+#define SIR_UART_ENABLE_RX(port)   do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ERBFI); } while (0)
+
+static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
+{
+	unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
+	port->lsr |= (lsr & (BI|FE|PE|OE));
+	return lsr | port->lsr;
+}
+
+static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
+{
+	port->lsr = 0;
+	bfin_read16(port->membase + OFFSET_LSR);
+}
+#endif
+
+static const unsigned short per[][4] = {
+	/* rx pin      tx pin     NULL  uart_number */
+	{P_UART0_RX, P_UART0_TX,    0,    0},
+	{P_UART1_RX, P_UART1_TX,    0,    1},
+	{P_UART2_RX, P_UART2_TX,    0,    2},
+	{P_UART3_RX, P_UART3_TX,    0,    3},
+};
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/donauboe.c linux-libre-2.6.31-gnu/drivers/net/irda/donauboe.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/donauboe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/donauboe.c	2009-09-09 18:13:59.000000000 -0400
@@ -994,11 +994,11 @@
 
   /* change speed pending, wait for its execution */
   if (self->new_speed)
-      return -EBUSY;
+      return NETDEV_TX_BUSY;
 
   /* device stopped (apm) wait for restart */
   if (self->stopped)
-      return -EBUSY;
+      return NETDEV_TX_BUSY;
 
   toshoboe_checkstuck (self);
 
@@ -1049,7 +1049,7 @@
       if (self->txpending)
         {
 	  spin_unlock_irqrestore(&self->spinlock, flags);
-          return -EBUSY;
+          return NETDEV_TX_BUSY;
         }
 
       /* If in SIR mode we need to generate a string of XBOFs */
@@ -1105,7 +1105,7 @@
           ,skb->len, self->ring->tx[self->txs].control, self->txpending);
       toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
       spin_unlock_irqrestore(&self->spinlock, flags);
-      return -EBUSY;
+      return NETDEV_TX_BUSY;
     }
 
   if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_SIRON)
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/irda-usb.c linux-libre-2.6.31-gnu/drivers/net/irda/irda-usb.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/irda-usb.c	2012-03-22 19:15:54.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/irda-usb.c	2012-03-22 20:11:49.000000000 -0400
@@ -389,7 +389,6 @@
 	s32 speed;
 	s16 xbofs;
 	int res, mtt;
-	int	err = 1;	/* Failed */
 
 	IRDA_DEBUG(4, "%s() on %s\n", __func__, netdev->name);
 
@@ -430,7 +429,6 @@
 			irda_usb_change_speed_xbofs(self);
 			netdev->trans_start = jiffies;
 			/* Will netif_wake_queue() in callback */
-			err = 0;	/* No error */
 			goto drop;
 		}
 	}
@@ -542,7 +540,7 @@
 	/* Drop silently the skb and exit */
 	dev_kfree_skb(skb);
 	spin_unlock_irqrestore(&self->lock, flags);
-	return err;		/* Usually 1 */
+	return NETDEV_TX_OK;
 }
 
 /*------------------------------------------------------------------*/
@@ -1856,6 +1854,42 @@
 	IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __func__);
 }
 
+#ifdef CONFIG_PM
+/* USB suspend, so power off the transmitter/receiver */
+static int irda_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct irda_usb_cb *self = usb_get_intfdata(intf);
+	int i;
+
+	netif_device_detach(self->netdev);
+
+	if (self->tx_urb != NULL)
+		usb_kill_urb(self->tx_urb);
+	if (self->speed_urb != NULL)
+		usb_kill_urb(self->speed_urb);
+	for (i = 0; i < self->max_rx_urb; i++) {
+		if (self->rx_urb[i] != NULL)
+			usb_kill_urb(self->rx_urb[i]);
+	}
+	return 0;
+}
+
+/* Coming out of suspend, so reset hardware */
+static int irda_usb_resume(struct usb_interface *intf)
+{
+	struct irda_usb_cb *self = usb_get_intfdata(intf);
+	int i;
+
+	for (i = 0; i < self->max_rx_urb; i++) {
+		if (self->rx_urb[i] != NULL)
+			usb_submit_urb(self->rx_urb[i], GFP_KERNEL);
+	}
+
+	netif_device_attach(self->netdev);
+	return 0;
+}
+#endif
+
 /*------------------------------------------------------------------*/
 /*
  * USB device callbacks
@@ -1865,6 +1899,10 @@
 	.probe		= irda_usb_probe,
 	.disconnect	= irda_usb_disconnect,
 	.id_table	= dongles,
+#ifdef CONFIG_PM
+	.suspend	= irda_usb_suspend,
+	.resume		= irda_usb_resume,
+#endif
 };
 
 /************************* MODULE CALLBACKS *************************/
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/irtty-sir.c linux-libre-2.6.31-gnu/drivers/net/irda/irtty-sir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/irtty-sir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/irtty-sir.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,7 +31,6 @@
 #include <linux/tty.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/Kconfig linux-libre-2.6.31-gnu/drivers/net/irda/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/irda/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -17,6 +17,51 @@
 
 	  If unsure, say Y.
 
+config BFIN_SIR
+	tristate "Blackfin SIR on UART"
+	depends on BLACKFIN && IRDA
+	default n
+	help
+	  Say Y here if your want to enable SIR function on Blackfin UART
+	  devices.
+
+	  To activate this driver you can start irattach like:
+	  "irattach irda0 -s"
+
+	  Saying M, it will be built as a module named bfin_sir.
+
+	  Note that you need to turn off one of the serial drivers for SIR
+	  to use that UART.
+
+config BFIN_SIR0
+	bool "Blackfin SIR on UART0"
+	depends on BFIN_SIR && !SERIAL_BFIN_UART0
+
+config BFIN_SIR1
+	bool "Blackfin SIR on UART1"
+	depends on BFIN_SIR && !SERIAL_BFIN_UART1 && (!BF531 && !BF532 && !BF533 && !BF561)
+
+config BFIN_SIR2
+	bool "Blackfin SIR on UART2"
+	depends on BFIN_SIR && !SERIAL_BFIN_UART2 && (BF54x || BF538 || BF539)
+
+config BFIN_SIR3
+	bool "Blackfin SIR on UART3"
+	depends on BFIN_SIR && !SERIAL_BFIN_UART3 && (BF54x)
+
+choice
+	prompt "SIR Mode"
+	depends on BFIN_SIR
+	default SIR_BFIN_DMA
+
+config SIR_BFIN_DMA
+	bool "DMA mode"
+	depends on !DMA_UNCACHED_NONE
+
+config SIR_BFIN_PIO
+	bool "PIO mode"
+endchoice
+
 comment "Dongle support"
 
 config DONGLE
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/kingsun-sir.c linux-libre-2.6.31-gnu/drivers/net/irda/kingsun-sir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/kingsun-sir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/kingsun-sir.c	2009-09-09 18:13:59.000000000 -0400
@@ -156,9 +156,6 @@
 	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 */
@@ -197,7 +194,7 @@
 	dev_kfree_skb(skb);
 	spin_unlock(&kingsun->lock);
 
-	return ret;
+	return NETDEV_TX_OK;
 }
 
 /* Receive callback function */
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/ks959-sir.c linux-libre-2.6.31-gnu/drivers/net/irda/ks959-sir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/ks959-sir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/ks959-sir.c	2009-09-09 18:13:59.000000000 -0400
@@ -391,9 +391,6 @@
 	unsigned 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 */
@@ -428,7 +425,7 @@
 	dev_kfree_skb(skb);
 	spin_unlock(&kingsun->lock);
 
-	return ret;
+	return NETDEV_TX_OK;
 }
 
 /* Receive callback function */
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/ksdazzle-sir.c linux-libre-2.6.31-gnu/drivers/net/irda/ksdazzle-sir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/ksdazzle-sir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/ksdazzle-sir.c	2009-09-09 18:13:59.000000000 -0400
@@ -304,9 +304,6 @@
 	unsigned 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 */
@@ -341,7 +338,7 @@
 	dev_kfree_skb(skb);
 	spin_unlock(&kingsun->lock);
 
-	return ret;
+	return NETDEV_TX_OK;
 }
 
 /* Receive callback function */
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/Makefile linux-libre-2.6.31-gnu/drivers/net/irda/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/irda/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -21,6 +21,7 @@
 obj-$(CONFIG_AU1000_FIR)	+= au1k_ir.o
 # SIR drivers
 obj-$(CONFIG_IRTTY_SIR)		+= irtty-sir.o	sir-dev.o
+obj-$(CONFIG_BFIN_SIR)		+= bfin_sir.o
 # dongle drivers for SIR drivers
 obj-$(CONFIG_ESI_DONGLE)	+= esi-sir.o
 obj-$(CONFIG_TEKRAM_DONGLE)	+= tekram-sir.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/mcs7780.c linux-libre-2.6.31-gnu/drivers/net/irda/mcs7780.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/mcs7780.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/mcs7780.c	2009-09-09 18:13:59.000000000 -0400
@@ -824,10 +824,6 @@
 	int wraplen;
 	int ret = 0;
 
-
-	if (skb == NULL || ndev == NULL)
-		return -EINVAL;
-
 	netif_stop_queue(ndev);
 	mcs = netdev_priv(ndev);
 
@@ -870,7 +866,7 @@
 
 	dev_kfree_skb(skb);
 	spin_unlock_irqrestore(&mcs->lock, flags);
-	return ret;
+	return NETDEV_TX_OK;
 }
 
 static const struct net_device_ops mcs_netdev_ops = {
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/pxaficp_ir.c linux-libre-2.6.31-gnu/drivers/net/irda/pxaficp_ir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/pxaficp_ir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/pxaficp_ir.c	2009-09-09 18:13:59.000000000 -0400
@@ -14,6 +14,7 @@
  */
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 
@@ -797,6 +798,13 @@
 	return io->head ? 0 : -ENOMEM;
 }
 
+static const struct net_device_ops pxa_irda_netdev_ops = {
+	.ndo_open		= pxa_irda_start,
+	.ndo_stop		= pxa_irda_stop,
+	.ndo_start_xmit		= pxa_irda_hard_xmit,
+	.ndo_do_ioctl		= pxa_irda_ioctl,
+};
+
 static int pxa_irda_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
@@ -819,6 +827,7 @@
 	if (!dev)
 		goto err_mem_3;
 
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	si = netdev_priv(dev);
 	si->dev = &pdev->dev;
 	si->pdata = pdev->dev.platform_data;
@@ -845,10 +854,7 @@
 	if (err)
 		goto err_startup;
 
-	dev->hard_start_xmit	= pxa_irda_hard_xmit;
-	dev->open		= pxa_irda_start;
-	dev->stop		= pxa_irda_stop;
-	dev->do_ioctl		= pxa_irda_ioctl;
+	dev->netdev_ops = &pxa_irda_netdev_ops;
 
 	irda_init_max_qos_capabilies(&si->qos);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/sa1100_ir.c linux-libre-2.6.31-gnu/drivers/net/irda/sa1100_ir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/sa1100_ir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/sa1100_ir.c	2009-09-09 18:13:59.000000000 -0400
@@ -875,6 +875,13 @@
 	return io->head ? 0 : -ENOMEM;
 }
 
+static const struct net_device_ops sa1100_irda_netdev_ops = {
+	.ndo_open		= sa1100_irda_start,
+	.ndo_stop		= sa1100_irda_stop,
+	.ndo_start_xmit		= sa1100_irda_hard_xmit,
+	.ndo_do_ioctl		= sa1100_irda_ioctl,
+};
+
 static int sa1100_irda_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
@@ -913,11 +920,8 @@
 	if (err)
 		goto err_mem_5;
 
-	dev->hard_start_xmit	= sa1100_irda_hard_xmit;
-	dev->open		= sa1100_irda_start;
-	dev->stop		= sa1100_irda_stop;
-	dev->do_ioctl		= sa1100_irda_ioctl;
-	dev->irq		= IRQ_Ser2ICP;
+	dev->netdev_ops	= &sa1100_irda_netdev_ops;
+	dev->irq	= IRQ_Ser2ICP;
 
 	irda_init_max_qos_capabilies(&si->qos);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/sir_dev.c linux-libre-2.6.31-gnu/drivers/net/irda/sir_dev.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/sir_dev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/sir_dev.c	2009-09-09 18:13:59.000000000 -0400
@@ -607,7 +607,7 @@
 				 * stopped so the network layer will retry after the
 				 * fsm completes and wakes the queue.
 				 */
-				 return 1;
+				 return NETDEV_TX_BUSY;
 			}
 			else if (unlikely(err)) {
 				/* other fatal error - forget the speed change and
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/smsc-ircc2.c linux-libre-2.6.31-gnu/drivers/net/irda/smsc-ircc2.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/smsc-ircc2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/smsc-ircc2.c	2009-09-09 18:13:59.000000000 -0400
@@ -2124,7 +2124,7 @@
 	while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT))
 		udelay(1);
 
-	if (count == 0)
+	if (count < 0)
 		IRDA_DEBUG(0, "%s(): stuck transmitter\n", __func__);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/irda/w83977af_ir.c linux-libre-2.6.31-gnu/drivers/net/irda/w83977af_ir.c
--- linux-libre-2.6.30-gnu/drivers/net/irda/w83977af_ir.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/irda/w83977af_ir.c	2009-09-09 18:13:59.000000000 -0400
@@ -115,7 +115,7 @@
 
 	IRDA_DEBUG(0, "%s()\n", __func__ );
 
-	for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) {
+	for (i=0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) {
 		if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
 			return 0;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/net/isa-skeleton.c linux-libre-2.6.31-gnu/drivers/net/isa-skeleton.c
--- linux-libre-2.6.30-gnu/drivers/net/isa-skeleton.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/isa-skeleton.c	2009-09-09 18:13:59.000000000 -0400
@@ -430,7 +430,8 @@
 	 * hardware interrupt handler.  Queue flow control is
 	 * thus managed under this lock as well.
 	 */
-	spin_lock_irq(&np->lock);
+	unsigned long flags;
+	spin_lock_irqsave(&np->lock, flags);
 
 	add_to_tx_ring(np, skb, length);
 	dev->trans_start = jiffies;
@@ -446,7 +447,7 @@
 	 * is when the transmit statistics are updated.
 	 */
 
-	spin_unlock_irq(&np->lock);
+	spin_unlock_irqrestore(&np->lock, flags);
 #else
 	/* This is the case for older hardware which takes
 	 * a single transmit buffer at a time, and it is
diff -druN linux-libre-2.6.30-gnu/drivers/net/iseries_veth.c linux-libre-2.6.31-gnu/drivers/net/iseries_veth.c
--- linux-libre-2.6.30-gnu/drivers/net/iseries_veth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/iseries_veth.c	2009-09-09 18:13:59.000000000 -0400
@@ -1021,6 +1021,16 @@
 	.get_link = veth_get_link,
 };
 
+static const struct net_device_ops veth_netdev_ops = {
+	.ndo_open		= veth_open,
+	.ndo_stop		= veth_close,
+	.ndo_start_xmit		= veth_start_xmit,
+	.ndo_change_mtu		= veth_change_mtu,
+	.ndo_set_multicast_list	= veth_set_multicast_list,
+	.ndo_set_mac_address	= NULL,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
 static struct net_device *veth_probe_one(int vlan,
 		struct vio_dev *vio_dev)
 {
@@ -1067,12 +1077,7 @@
 
 	memcpy(&port->mac_addr, mac_addr, ETH_ALEN);
 
-	dev->open = veth_open;
-	dev->hard_start_xmit = veth_start_xmit;
-	dev->stop = veth_close;
-	dev->change_mtu = veth_change_mtu;
-	dev->set_mac_address = NULL;
-	dev->set_multicast_list = veth_set_multicast_list;
+	dev->netdev_ops = &veth_netdev_ops;
 	SET_ETHTOOL_OPS(dev, &ops);
 
 	SET_NETDEV_DEV(dev, vdev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_hw.c linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_hw.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_hw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -192,7 +192,7 @@
 		vendor_name[i] = ixgb_read_phy_reg(hw,
 						   MDIO_PMA_PMD_XPAK_VENDOR_NAME
 						   + i, IXGB_PHY_ADDRESS,
-						   MDIO_PMA_PMD_DID);
+						   MDIO_MMD_PMAPMD);
 	}
 
 	/* Determine the actual vendor */
@@ -1225,15 +1225,15 @@
 		u16 mdio_reg;
 
 		ixgb_write_phy_reg(hw,
-					MDIO_PMA_PMD_CR1,
-					IXGB_PHY_ADDRESS,
-					MDIO_PMA_PMD_DID,
-					MDIO_PMA_PMD_CR1_RESET);
+				   MDIO_CTRL1,
+				   IXGB_PHY_ADDRESS,
+				   MDIO_MMD_PMAPMD,
+				   MDIO_CTRL1_RESET);
 
-		mdio_reg = ixgb_read_phy_reg( hw,
-						MDIO_PMA_PMD_CR1,
-						IXGB_PHY_ADDRESS,
-						MDIO_PMA_PMD_DID);
+		mdio_reg = ixgb_read_phy_reg(hw,
+					     MDIO_CTRL1,
+					     IXGB_PHY_ADDRESS,
+					     MDIO_MMD_PMAPMD);
 	}
 
 	return;
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_hw.h linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_hw.h
--- linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_hw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_hw.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,8 @@
 #ifndef _IXGB_HW_H_
 #define _IXGB_HW_H_
 
+#include <linux/mdio.h>
+
 #include "ixgb_osdep.h"
 
 /* Enums */
@@ -507,18 +509,6 @@
 /* Definitions for the optics devices on the MDIO bus. */
 #define IXGB_PHY_ADDRESS             0x0	/* Single PHY, multiple "Devices" */
 
-/* Standard five-bit Device IDs.  See IEEE 802.3ae, clause 45 */
-#define MDIO_PMA_PMD_DID        0x01
-#define MDIO_WIS_DID            0x02
-#define MDIO_PCS_DID            0x03
-#define MDIO_XGXS_DID           0x04
-
-/* Standard PMA/PMD registers and bit definitions. */
-/* Note: This is a very limited set of definitions,      */
-/* only implemented features are defined.                */
-#define MDIO_PMA_PMD_CR1        0x0000
-#define MDIO_PMA_PMD_CR1_RESET  0x8000
-
 #define MDIO_PMA_PMD_XPAK_VENDOR_NAME       0x803A	/* XPAK/XENPAK devices only */
 
 /* Vendor-specific MDIO registers */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_main.c linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_main.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -266,6 +266,8 @@
 	napi_enable(&adapter->napi);
 	ixgb_irq_enable(adapter);
 
+	netif_wake_queue(netdev);
+
 	mod_timer(&adapter->watchdog_timer, jiffies);
 
 	return 0;
@@ -471,10 +473,8 @@
 	if (err)
 		goto err_register;
 
-	/* we're going to reset, so assume we have no link for now */
-
+	/* carrier off reporting is important to ethtool even BEFORE open */
 	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
 
 	DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n");
 	ixgb_check_options(adapter);
@@ -592,6 +592,8 @@
 	if (err)
 		goto err_setup_tx;
 
+	netif_carrier_off(netdev);
+
 	/* allocate receive descriptors */
 
 	err = ixgb_setup_rx_resources(adapter);
@@ -602,6 +604,8 @@
 	if (err)
 		goto err_up;
 
+	netif_start_queue(netdev);
+
 	return 0;
 
 err_up:
@@ -1116,7 +1120,6 @@
 			adapter->link_speed = 10000;
 			adapter->link_duplex = FULL_DUPLEX;
 			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
 		}
 	} else {
 		if (netif_carrier_ok(netdev)) {
@@ -1125,8 +1128,6 @@
 			printk(KERN_INFO "ixgb: %s NIC Link is Down\n",
 			       netdev->name);
 			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-
 		}
 	}
 
@@ -1139,6 +1140,8 @@
 			 * to get done, so reset controller to flush Tx.
 			 * (Do the reset outside of interrupt context). */
 			schedule_work(&adapter->tx_timeout_task);
+			/* return immediately since reset is imminent */
+			return;
 		}
 	}
 
@@ -1297,7 +1300,7 @@
 		buffer_info->length = size;
 		WARN_ON(buffer_info->dma != 0);
 		buffer_info->time_stamp = jiffies;
-		buffer_info->dma = map[0] + offset;
+		buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
 			pci_map_single(adapter->pdev,
 				skb->data + offset,
 				size,
@@ -1337,7 +1340,7 @@
 
 			buffer_info->length = size;
 			buffer_info->time_stamp = jiffies;
-			buffer_info->dma = map[f + 1] + offset;
+			buffer_info->dma = map[f] + offset;
 			buffer_info->next_to_watch = 0;
 
 			len -= size;
@@ -1485,7 +1488,6 @@
 
 	if (count) {
 		ixgb_tx_queue(adapter, count, vlan_id, tx_flags);
-		netdev->trans_start = jiffies;
 		/* Make sure there is space in the ring for the next send. */
 		ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_osdep.h linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_osdep.h
--- linux-libre-2.6.30-gnu/drivers/net/ixgb/ixgb_osdep.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgb/ixgb_osdep.h	2009-09-09 18:13:59.000000000 -0400
@@ -40,7 +40,7 @@
 #include <linux/sched.h>
 
 #undef ASSERT
-#define ASSERT(x)	if (!(x)) BUG()
+#define ASSERT(x)	BUG_ON(!(x))
 #define MSGOUT(S, A, B)	printk(KERN_DEBUG S "\n", A, B)
 
 #ifdef DBG
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_82598.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_82598.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_82598.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_82598.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,6 +50,51 @@
                                        u8 *eeprom_data);
 
 /**
+ *  ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
+ *  @hw: pointer to the HW structure
+ *
+ *  The defaults for 82598 should be in the range of 50us to 50ms,
+ *  however the hardware default for these parts is 500us to 1ms which is less
+ *  than the 10ms recommended by the pci-e spec.  To address this we need to
+ *  increase the value to either 10ms to 250ms for capability version 1 config,
+ *  or 16ms to 55ms for version 2.
+ **/
+void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
+{
+	struct ixgbe_adapter *adapter = hw->back;
+	u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
+	u16 pcie_devctl2;
+
+	/* only take action if timeout value is defaulted to 0 */
+	if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
+		goto out;
+
+	/*
+	 * if capababilities version is type 1 we can write the
+	 * timeout of 10ms to 250ms through the GCR register
+	 */
+	if (!(gcr & IXGBE_GCR_CAP_VER2)) {
+		gcr |= IXGBE_GCR_CMPL_TMOUT_10ms;
+		goto out;
+	}
+
+	/*
+	 * for version 2 capabilities we need to write the config space
+	 * directly in order to set the completion timeout value for
+	 * 16ms to 55ms
+	 */
+	pci_read_config_word(adapter->pdev,
+	                     IXGBE_PCI_DEVICE_CONTROL2, &pcie_devctl2);
+	pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
+	pci_write_config_word(adapter->pdev,
+	                      IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
+out:
+	/* disable completion timeout resend */
+	gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND;
+	IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr);
+}
+
+/**
  *  ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
  *  @hw: pointer to hardware structure
  *
@@ -75,18 +120,49 @@
 static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
+
+	/* Call PHY identify routine to get the phy type */
+	ixgbe_identify_phy_generic(hw);
+
+	mac->mcft_size = IXGBE_82598_MC_TBL_SIZE;
+	mac->vft_size = IXGBE_82598_VFT_TBL_SIZE;
+	mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
+	mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
+	mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
+	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
+
+	return 0;
+}
+
+/**
+ *  ixgbe_init_phy_ops_82598 - PHY/SFP specific init
+ *  @hw: pointer to hardware structure
+ *
+ *  Initialize any function pointers that were not able to be
+ *  set during get_invariants because the PHY/SFP type was
+ *  not known.  Perform the SFP init if necessary.
+ *
+ **/
+s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
+{
+	struct ixgbe_mac_info *mac = &hw->mac;
 	struct ixgbe_phy_info *phy = &hw->phy;
 	s32 ret_val = 0;
 	u16 list_offset, data_offset;
 
-	/* Set the bus information prior to PHY identification */
-	mac->ops.get_bus_info(hw);
+	/* Identify the PHY */
+	phy->ops.identify(hw);
 
-	/* Call PHY identify routine to get the phy type */
-	ixgbe_identify_phy_generic(hw);
+	/* Overwrite the link function pointers if copper PHY */
+	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
+		mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
+		mac->ops.setup_link_speed =
+		                     &ixgbe_setup_copper_link_speed_82598;
+		mac->ops.get_link_capabilities =
+		                  &ixgbe_get_copper_link_capabilities_82598;
+	}
 
-	/* PHY Init */
-	switch (phy->type) {
+	switch (hw->phy.type) {
 	case ixgbe_phy_tn:
 		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
 		phy->ops.get_firmware_version =
@@ -106,8 +182,8 @@
 
 		/* Check to see if SFP+ module is supported */
 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
-		                                              &list_offset,
-		                                              &data_offset);
+		                                            &list_offset,
+		                                            &data_offset);
 		if (ret_val != 0) {
 			ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
 			goto out;
@@ -117,22 +193,27 @@
 		break;
 	}
 
-	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
-		mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
-		mac->ops.setup_link_speed =
-		                     &ixgbe_setup_copper_link_speed_82598;
-		mac->ops.get_link_capabilities =
-		                     &ixgbe_get_copper_link_capabilities_82598;
-	}
+out:
+	return ret_val;
+}
 
-	mac->mcft_size = IXGBE_82598_MC_TBL_SIZE;
-	mac->vft_size = IXGBE_82598_VFT_TBL_SIZE;
-	mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
-	mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
-	mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
-	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
+/**
+ *  ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx
+ *  @hw: pointer to hardware structure
+ *
+ *  Starts the hardware using the generic start_hw function.
+ *  Then set pcie completion timeout
+ **/
+s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
+{
+	s32 ret_val = 0;
+
+	ret_val = ixgbe_start_hw_generic(hw);
+
+	/* set the completion timeout for interface */
+	if (ret_val == 0)
+		ixgbe_set_pcie_completion_timeout(hw);
 
-out:
 	return ret_val;
 }
 
@@ -149,12 +230,19 @@
                                              bool *autoneg)
 {
 	s32 status = 0;
+	u32 autoc = 0;
 
 	/*
 	 * Determine link capabilities based on the stored value of AUTOC,
-	 * which represents EEPROM defaults.
+	 * which represents EEPROM defaults.  If AUTOC value has not been
+	 * stored, use the current register value.
 	 */
-	switch (hw->mac.orig_autoc & IXGBE_AUTOC_LMS_MASK) {
+	if (hw->mac.orig_link_settings_stored)
+		autoc = hw->mac.orig_autoc;
+	else
+		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
 		*autoneg = false;
@@ -173,9 +261,9 @@
 	case IXGBE_AUTOC_LMS_KX4_AN:
 	case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP)
+		if (autoc & IXGBE_AUTOC_KX4_SUPP)
 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP)
+		if (autoc & IXGBE_AUTOC_KX_SUPP)
 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
 		*autoneg = true;
 		break;
@@ -206,14 +294,13 @@
 	*speed = 0;
 	*autoneg = true;
 
-	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
-	                              IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+	status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD,
 	                              &speed_ability);
 
 	if (status == 0) {
-		if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
+		if (speed_ability & MDIO_SPEED_10G)
 		    *speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
+		if (speed_ability & MDIO_PMA_SPEED_1000)
 		    *speed |= IXGBE_LINK_SPEED_1GB_FULL;
 	}
 
@@ -271,6 +358,17 @@
 	u32 rmcs_reg;
 	u32 reg;
 
+#ifdef CONFIG_DCB
+	if (hw->fc.requested_mode == ixgbe_fc_pfc)
+		goto out;
+
+#endif /* CONFIG_DCB */
+	/* Negotiate the fc mode to use */
+	ret_val = ixgbe_fc_autoneg(hw);
+	if (ret_val)
+		goto out;
+
+	/* Disable any previous flow control settings */
 	fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
 	fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
 
@@ -282,14 +380,20 @@
 	 * 0: Flow control is completely disabled
 	 * 1: Rx flow control is enabled (we can receive pause frames,
 	 *    but not send pause frames).
-	 * 2:  Tx flow control is enabled (we can send pause frames but
+	 * 2: Tx flow control is enabled (we can send pause frames but
 	 *     we do not support receiving pause frames).
 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
 	 * other: Invalid.
+#ifdef CONFIG_DCB
+	 * 4: Priority Flow Control is enabled.
+#endif
 	 */
 	switch (hw->fc.current_mode) {
 	case ixgbe_fc_none:
-		/* Flow control completely disabled by software override. */
+		/*
+		 * Flow control is disabled by software override or autoneg.
+		 * The code below will actually disable it in the HW.
+		 */
 		break;
 	case ixgbe_fc_rx_pause:
 		/*
@@ -314,6 +418,11 @@
 		fctrl_reg |= IXGBE_FCTRL_RFCE;
 		rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
 		break;
+#ifdef CONFIG_DCB
+	case ixgbe_fc_pfc:
+		goto out;
+		break;
+#endif /* CONFIG_DCB */
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
 		ret_val = -IXGBE_ERR_CONFIG;
@@ -321,7 +430,8 @@
 		break;
 	}
 
-	/* Enable 802.3x based flow control settings. */
+	/* Set 802.3x based flow control settings. */
+	fctrl_reg |= IXGBE_FCTRL_DPF;
 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg);
 	IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
 
@@ -340,7 +450,7 @@
 	}
 
 	/* Configure pause time (2 TCs per register) */
-	reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num));
+	reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
 	if ((packetbuf_num & 1) == 0)
 		reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
 	else
@@ -354,77 +464,6 @@
 }
 
 /**
- *  ixgbe_setup_fc_82598 - Configure flow control settings
- *  @hw: pointer to hardware structure
- *  @packetbuf_num: packet buffer number (0-7)
- *
- *  Configures the flow control settings based on SW configuration.  This
- *  function is used for 802.3x flow control configuration only.
- **/
-static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
-{
-	s32 ret_val = 0;
-	ixgbe_link_speed speed;
-	bool link_up;
-
-	/* Validate the packetbuf configuration */
-	if (packetbuf_num < 0 || packetbuf_num > 7) {
-		hw_dbg(hw, "Invalid packet buffer number [%d], expected range is"
-		          " 0-7\n", packetbuf_num);
-		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-		goto out;
-	}
-
-	/*
-	 * Validate the water mark configuration.  Zero water marks are invalid
-	 * because it causes the controller to just blast out fc packets.
-	 */
-	if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
-		hw_dbg(hw, "Invalid water mark configuration\n");
-		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-		goto out;
-	}
-
-	/*
-	 * Validate the requested mode.  Strict IEEE mode does not allow
-	 * ixgbe_fc_rx_pause because it will cause testing anomalies.
-	 */
-	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
-		hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
-		ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-		goto out;
-	}
-
-	/*
-	 * 10gig parts do not have a word in the EEPROM to determine the
-	 * default flow control setting, so we explicitly set it to full.
-	 */
-	if (hw->fc.requested_mode == ixgbe_fc_default)
-		hw->fc.requested_mode = ixgbe_fc_full;
-
-	/*
-	 * Save off the requested flow control mode for use later.  Depending
-	 * on the link partner's capabilities, we may or may not use this mode.
-	 */
-
-	hw->fc.current_mode = hw->fc.requested_mode;
-
-	/* Decide whether to use autoneg or not. */
-	hw->mac.ops.check_link(hw, &speed, &link_up, false);
-	if (!hw->fc.disable_fc_autoneg && hw->phy.multispeed_fiber &&
-	    (speed == IXGBE_LINK_SPEED_1GB_FULL))
-		ret_val = ixgbe_fc_autoneg(hw);
-
-	if (ret_val)
-		goto out;
-
-	ret_val = ixgbe_fc_enable_82598(hw, packetbuf_num);
-
-out:
-	return ret_val;
-}
-
-/**
  *  ixgbe_setup_mac_link_82598 - Configures MAC link settings
  *  @hw: pointer to hardware structure
  *
@@ -463,13 +502,6 @@
 		}
 	}
 
-	/*
-	 * We want to save off the original Flow Control configuration just in
-	 * case we get disconnected and then reconnected into a different hub
-	 * or switch with different Flow Control capabilities.
-	 */
-	ixgbe_setup_fc_82598(hw, 0);
-
 	/* Add delay to filter out noises during initial link setup */
 	msleep(50);
 
@@ -500,9 +532,9 @@
 	 * clear indicates active; set indicates inactive.
 	 */
 	if (hw->phy.type == ixgbe_phy_nl) {
-		hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
-		hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
-		hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
+		hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg);
+		hw->phy.ops.read_reg(hw, 0xC79F, MDIO_MMD_PMAPMD, &link_reg);
+		hw->phy.ops.read_reg(hw, 0xC00C, MDIO_MMD_PMAPMD,
 		                     &adapt_comp_reg);
 		if (link_up_wait_to_complete) {
 			for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
@@ -515,10 +547,10 @@
 				}
 				msleep(100);
 				hw->phy.ops.read_reg(hw, 0xC79F,
-				                     IXGBE_TWINAX_DEV,
+				                     MDIO_MMD_PMAPMD,
 				                     &link_reg);
 				hw->phy.ops.read_reg(hw, 0xC00C,
-				                     IXGBE_TWINAX_DEV,
+				                     MDIO_MMD_PMAPMD,
 				                     &adapt_comp_reg);
 			}
 		} else {
@@ -556,6 +588,11 @@
 	else
 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
 
+	/* if link is down, zero out the current_mode */
+	if (*link_up == false) {
+		hw->fc.current_mode = ixgbe_fc_none;
+		hw->fc.fc_was_autonegged = false;
+	}
 out:
 	return 0;
 }
@@ -673,6 +710,7 @@
 static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
 {
 	s32 status = 0;
+	s32 phy_status = 0;
 	u32 ctrl;
 	u32 gheccr;
 	u32 i;
@@ -716,14 +754,27 @@
 	}
 
 	/* Reset PHY */
-	if (hw->phy.reset_disable == false)
+	if (hw->phy.reset_disable == false) {
+		/* PHY ops must be identified and initialized prior to reset */
+
+		/* Init PHY and function pointers, perform SFP setup */
+		phy_status = hw->phy.ops.init(hw);
+		if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+			goto reset_hw_out;
+		else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
+			goto no_phy_reset;
+
+
 		hw->phy.ops.reset(hw);
+	}
 
+no_phy_reset:
 	/*
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	if (ixgbe_disable_pcie_master(hw) != 0) {
+	status = ixgbe_disable_pcie_master(hw);
+	if (status != 0) {
 		status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
 		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
 	}
@@ -767,9 +818,19 @@
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
 	}
 
+	/*
+	 * Store MAC address from RAR0, clear receive address registers, and
+	 * clear the multicast table
+	 */
+	hw->mac.ops.init_rx_addrs(hw);
+
 	/* Store the permanent mac address */
 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
 
+reset_hw_out:
+	if (phy_status)
+		status = phy_status;
+
 	return status;
 }
 
@@ -954,14 +1015,14 @@
 		sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
 		hw->phy.ops.write_reg(hw,
 		                      IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
-		                      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+		                      MDIO_MMD_PMAPMD,
 		                      sfp_addr);
 
 		/* Poll status */
 		for (i = 0; i < 100; i++) {
 			hw->phy.ops.read_reg(hw,
 			                     IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
-			                     IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+			                     MDIO_MMD_PMAPMD,
 			                     &sfp_stat);
 			sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
 			if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
@@ -977,7 +1038,7 @@
 
 		/* Read data */
 		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
-		                     IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
+		                     MDIO_MMD_PMAPMD, &sfp_data);
 
 		*eeprom_data = (u8)(sfp_data >> 8);
 	} else {
@@ -998,35 +1059,56 @@
 static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
 {
 	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
+	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
+	u16 ext_ability = 0;
 
-	switch (hw->device_id) {
-	case IXGBE_DEV_ID_82598:
-		/* Default device ID is mezzanine card KX/KX4 */
-		physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
-				  IXGBE_PHYSICAL_LAYER_1000BASE_KX);
-		break;
-	case IXGBE_DEV_ID_82598_BX:
-		physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX;
-	case IXGBE_DEV_ID_82598EB_CX4:
-	case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
-		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
-		break;
-	case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
-		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+	hw->phy.ops.identify(hw);
+
+	/* Copper PHY must be checked before AUTOC LMS to determine correct
+	 * physical layer because 10GBase-T PHYs use LMS = KX4/KX */
+	if (hw->phy.type == ixgbe_phy_tn ||
+	    hw->phy.type == ixgbe_phy_cu_unknown) {
+		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
+				     &ext_ability);
+		if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
+		if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+		goto out;
+	}
+
+	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
+	case IXGBE_AUTOC_LMS_1G_AN:
+	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
+		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX)
+			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+		else
+			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX;
 		break;
-	case IXGBE_DEV_ID_82598AF_DUAL_PORT:
-	case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
-	case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
-		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
+		if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4)
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
+		else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4)
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
+		else /* XAUI */
+			physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
 		break;
-	case IXGBE_DEV_ID_82598EB_XF_LR:
-		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+	case IXGBE_AUTOC_LMS_KX4_AN:
+	case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
+		if (autoc & IXGBE_AUTOC_KX_SUPP)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+		if (autoc & IXGBE_AUTOC_KX4_SUPP)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
 		break;
-	case IXGBE_DEV_ID_82598AT:
-		physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
-		                  IXGBE_PHYSICAL_LAYER_1000BASE_T);
+	default:
 		break;
-	case IXGBE_DEV_ID_82598EB_SFP_LOM:
+	}
+
+	if (hw->phy.type == ixgbe_phy_nl) {
 		hw->phy.ops.identify_sfp(hw);
 
 		switch (hw->phy.sfp_type) {
@@ -1043,20 +1125,32 @@
 			physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
 			break;
 		}
-		break;
+	}
 
+	switch (hw->device_id) {
+	case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
+		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+		break;
+	case IXGBE_DEV_ID_82598AF_DUAL_PORT:
+	case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
+	case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
+		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+		break;
+	case IXGBE_DEV_ID_82598EB_XF_LR:
+		physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+		break;
 	default:
-		physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
 		break;
 	}
 
+out:
 	return physical_layer;
 }
 
 static struct ixgbe_mac_operations mac_ops_82598 = {
 	.init_hw		= &ixgbe_init_hw_generic,
 	.reset_hw		= &ixgbe_reset_hw_82598,
-	.start_hw		= &ixgbe_start_hw_generic,
+	.start_hw		= &ixgbe_start_hw_82598,
 	.clear_hw_cntrs		= &ixgbe_clear_hw_cntrs_generic,
 	.get_media_type		= &ixgbe_get_media_type_82598,
 	.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598,
@@ -1086,7 +1180,7 @@
 	.disable_mc		= &ixgbe_disable_mc_generic,
 	.clear_vfta		= &ixgbe_clear_vfta_82598,
 	.set_vfta		= &ixgbe_set_vfta_82598,
-	.setup_fc		= &ixgbe_setup_fc_82598,
+	.fc_enable		= &ixgbe_fc_enable_82598,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
@@ -1099,6 +1193,7 @@
 static struct ixgbe_phy_operations phy_ops_82598 = {
 	.identify		= &ixgbe_identify_phy_generic,
 	.identify_sfp		= &ixgbe_identify_sfp_module_generic,
+	.init			= &ixgbe_init_phy_ops_82598,
 	.reset			= &ixgbe_reset_phy_generic,
 	.read_reg		= &ixgbe_read_phy_reg_generic,
 	.write_reg		= &ixgbe_write_phy_reg_generic,
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_82599.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_82599.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_82599.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_82599.c	2009-09-09 18:13:59.000000000 -0400
@@ -71,10 +71,10 @@
 s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw);
 s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val);
 s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val);
-s32 ixgbe_start_hw_rev_0_82599(struct ixgbe_hw *hw);
 s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
 s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw);
 u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
+static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
 
 void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 {
@@ -100,22 +100,36 @@
 
 	if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
 		ixgbe_init_mac_link_ops_82599(hw);
+
+		hw->phy.ops.reset = NULL;
+
 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
 		                                              &data_offset);
 
 		if (ret_val != 0)
 			goto setup_sfp_out;
 
+		/* PHY config will finish before releasing the semaphore */
+		ret_val = ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+		if (ret_val != 0) {
+			ret_val = IXGBE_ERR_SWFW_SYNC;
+			goto setup_sfp_out;
+		}
+
 		hw->eeprom.ops.read(hw, ++data_offset, &data_value);
 		while (data_value != 0xffff) {
 			IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
 			IXGBE_WRITE_FLUSH(hw);
 			hw->eeprom.ops.read(hw, ++data_offset, &data_value);
 		}
-		/* Now restart DSP */
-		IXGBE_WRITE_REG(hw, IXGBE_CORECTL, 0x00000102);
-		IXGBE_WRITE_REG(hw, IXGBE_CORECTL, 0x00000b1d);
-		IXGBE_WRITE_FLUSH(hw);
+		/* Now restart DSP by setting Restart_AN */
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC,
+		    (IXGBE_READ_REG(hw, IXGBE_AUTOC) | IXGBE_AUTOC_AN_RESTART));
+
+		/* Release the semaphore */
+		ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+		/* Delay obtaining semaphore again to allow FW access */
+		msleep(hw->eeprom.semaphore_delay);
 	}
 
 setup_sfp_out:
@@ -146,51 +160,60 @@
 static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
-	struct ixgbe_phy_info *phy = &hw->phy;
-	s32 ret_val;
 
-	/* Set the bus information prior to PHY identification */
-	mac->ops.get_bus_info(hw);
+	ixgbe_init_mac_link_ops_82599(hw);
 
-	/* Call PHY identify routine to get the Cu or SFI phy type */
-	ret_val = phy->ops.identify(hw);
+	mac->mcft_size = IXGBE_82599_MC_TBL_SIZE;
+	mac->vft_size = IXGBE_82599_VFT_TBL_SIZE;
+	mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES;
+	mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES;
+	mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES;
+	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw);
 
-	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
-		goto get_invariants_out;
+	return 0;
+}
 
-	ixgbe_init_mac_link_ops_82599(hw);
+/**
+ *  ixgbe_init_phy_ops_82599 - PHY/SFP specific init
+ *  @hw: pointer to hardware structure
+ *
+ *  Initialize any function pointers that were not able to be
+ *  set during get_invariants because the PHY/SFP type was
+ *  not known.  Perform the SFP init if necessary.
+ *
+ **/
+s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
+{
+	struct ixgbe_mac_info *mac = &hw->mac;
+	struct ixgbe_phy_info *phy = &hw->phy;
+	s32 ret_val = 0;
 
-	/* Setup SFP module if there is one present. */
-	ret_val = mac->ops.setup_sfp(hw);
+	/* Identify the PHY or SFP module */
+	ret_val = phy->ops.identify(hw);
+
+	/* Setup function pointers based on detected SFP module and speeds */
+	ixgbe_init_mac_link_ops_82599(hw);
 
 	/* If copper media, overwrite with copper function pointers */
 	if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
 		mac->ops.setup_link = &ixgbe_setup_copper_link_82599;
 		mac->ops.setup_link_speed =
-		                  &ixgbe_setup_copper_link_speed_82599;
+		                     &ixgbe_setup_copper_link_speed_82599;
 		mac->ops.get_link_capabilities =
 		                  &ixgbe_get_copper_link_capabilities_82599;
 	}
 
-	/* PHY Init */
+	/* Set necessary function pointers based on phy type */
 	switch (hw->phy.type) {
 	case ixgbe_phy_tn:
 		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
 		phy->ops.get_firmware_version =
-		                  &ixgbe_get_phy_firmware_version_tnx;
+		             &ixgbe_get_phy_firmware_version_tnx;
 		break;
 	default:
 		break;
 	}
 
-	mac->mcft_size = IXGBE_82599_MC_TBL_SIZE;
-	mac->vft_size = IXGBE_82599_VFT_TBL_SIZE;
-	mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES;
-	mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES;
-	mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES;
-	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw);
-
-get_invariants_out:
 	return ret_val;
 }
 
@@ -207,8 +230,19 @@
                                       bool *negotiation)
 {
 	s32 status = 0;
+	u32 autoc = 0;
 
-	switch (hw->mac.orig_autoc & IXGBE_AUTOC_LMS_MASK) {
+	/*
+	 * Determine link capabilities based on the stored value of AUTOC,
+	 * which represents EEPROM defaults.  If AUTOC value has not been
+	 * stored, use the current register value.
+	 */
+	if (hw->mac.orig_link_settings_stored)
+		autoc = hw->mac.orig_autoc;
+	else
+		autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
 	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
 		*negotiation = false;
@@ -232,22 +266,22 @@
 	case IXGBE_AUTOC_LMS_KX4_KX_KR:
 	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP)
+		if (autoc & IXGBE_AUTOC_KR_SUPP)
 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP)
+		if (autoc & IXGBE_AUTOC_KX4_SUPP)
 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP)
+		if (autoc & IXGBE_AUTOC_KX_SUPP)
 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
 		*negotiation = true;
 		break;
 
 	case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
 		*speed = IXGBE_LINK_SPEED_100_FULL;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP)
+		if (autoc & IXGBE_AUTOC_KR_SUPP)
 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP)
+		if (autoc & IXGBE_AUTOC_KX4_SUPP)
 			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (hw->mac.orig_autoc & IXGBE_AUTOC_KX_SUPP)
+		if (autoc & IXGBE_AUTOC_KX_SUPP)
 			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
 		*negotiation = true;
 		break;
@@ -291,14 +325,13 @@
 	*speed = 0;
 	*autoneg = true;
 
-	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
-	                              IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+	status = hw->phy.ops.read_reg(hw, MDIO_SPEED, MDIO_MMD_PMAPMD,
 	                              &speed_ability);
 
 	if (status == 0) {
-		if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
+		if (speed_ability & MDIO_SPEED_10G)
 		    *speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
+		if (speed_ability & MDIO_PMA_SPEED_1000)
 		    *speed |= IXGBE_LINK_SPEED_1GB_FULL;
 	}
 
@@ -323,8 +356,8 @@
 	}
 
 	switch (hw->device_id) {
-	case IXGBE_DEV_ID_82599:
 	case IXGBE_DEV_ID_82599_KX4:
+	case IXGBE_DEV_ID_82599_XAUI_LOM:
 		/* Default device ID is mezzanine card KX/KX4 */
 		media_type = ixgbe_media_type_backplane;
 		break;
@@ -380,9 +413,6 @@
 		}
 	}
 
-	/* Set up flow control */
-	status = ixgbe_setup_fc_generic(hw, 0);
-
 	/* Add delay to filter out noises during initial link setup */
 	msleep(50);
 
@@ -428,11 +458,31 @@
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 	bool link_up = false;
 	bool negotiation;
+	int i;
 
 	/* Mask off requested but non-supported speeds */
 	hw->mac.ops.get_link_capabilities(hw, &phy_link_speed, &negotiation);
 	speed &= phy_link_speed;
 
+	 /* Set autoneg_advertised value based on input link speed */
+	hw->phy.autoneg_advertised = 0;
+
+	if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
+	/*
+	 * When the driver changes the link speeds that it can support,
+	 * it sets autotry_restart to true to indicate that we need to
+	 * initiate a new autotry session with the link partner.  To do
+	 * so, we set the speed then disable and re-enable the tx laser, to
+	 * alert the link partner that it also needs to restart autotry on its
+	 * end.  This is consistent with true clause 37 autoneg, which also
+	 * involves a loss of signal.
+	 */
+
 	/*
 	 * Try each speed one by one, highest priority first.  We do this in
 	 * software because 10gb fiber doesn't support speed autonegotiation.
@@ -441,21 +491,52 @@
 		speedcnt++;
 		highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
 
-		/* Set hardware SDP's */
+		/* If we already have link at this speed, just jump out */
+		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+
+		if ((phy_link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
+			goto out;
+
+		/* Set the module link speed */
 		esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
 
-		ixgbe_setup_mac_link_speed_82599(hw,
-		                                 IXGBE_LINK_SPEED_10GB_FULL,
-		                                 autoneg,
-		                                 autoneg_wait_to_complete);
-
-		msleep(50);
+		/* Allow module to change analog characteristics (1G->10G) */
+		msleep(40);
 
-		/* If we have link, just jump out */
-		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
-		if (link_up)
+		status = ixgbe_setup_mac_link_speed_82599(hw,
+		                                     IXGBE_LINK_SPEED_10GB_FULL,
+		                                     autoneg,
+		                                     autoneg_wait_to_complete);
+		if (status != 0)
 			goto out;
+
+		/* Flap the tx laser if it has not already been done */
+		if (hw->mac.autotry_restart) {
+			/* Disable tx laser; allow 100us to go dark per spec */
+			esdp_reg |= IXGBE_ESDP_SDP3;
+			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+			udelay(100);
+
+			/* Enable tx laser; allow 2ms to light up per spec */
+			esdp_reg &= ~IXGBE_ESDP_SDP3;
+			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+			msleep(2);
+
+			hw->mac.autotry_restart = false;
+		}
+
+		/* The controller may take up to 500ms at 10g to acquire link */
+		for (i = 0; i < 5; i++) {
+			/* Wait for the link partner to also set speed */
+			msleep(100);
+
+			/* If we have link, just jump out */
+			hw->mac.ops.check_link(hw, &phy_link_speed,
+			                       &link_up, false);
+			if (link_up)
+				goto out;
+		}
 	}
 
 	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
@@ -463,16 +544,44 @@
 		if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
 			highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
 
-		/* Set hardware SDP's */
+		/* If we already have link at this speed, just jump out */
+		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+
+		if ((phy_link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
+			goto out;
+
+		/* Set the module link speed */
 		esdp_reg &= ~IXGBE_ESDP_SDP5;
 		esdp_reg |= IXGBE_ESDP_SDP5_DIR;
 		IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
 
-		ixgbe_setup_mac_link_speed_82599(
-			hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg,
-			autoneg_wait_to_complete);
+		/* Allow module to change analog characteristics (10G->1G) */
+		msleep(40);
 
-		msleep(50);
+		status = ixgbe_setup_mac_link_speed_82599(hw,
+		                                      IXGBE_LINK_SPEED_1GB_FULL,
+		                                      autoneg,
+		                                      autoneg_wait_to_complete);
+		if (status != 0)
+			goto out;
+
+		/* Flap the tx laser if it has not already been done */
+		if (hw->mac.autotry_restart) {
+			/* Disable tx laser; allow 100us to go dark per spec */
+			esdp_reg |= IXGBE_ESDP_SDP3;
+			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+			udelay(100);
+
+			/* Enable tx laser; allow 2ms to light up per spec */
+			esdp_reg &= ~IXGBE_ESDP_SDP3;
+			IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+			msleep(2);
+
+			hw->mac.autotry_restart = false;
+		}
+
+		/* Wait for the link partner to also set speed */
+		msleep(100);
 
 		/* If we have link, just jump out */
 		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
@@ -538,6 +647,11 @@
 	else
 		*speed = IXGBE_LINK_SPEED_100_FULL;
 
+	/* if link is down, zero out the current_mode */
+	if (*link_up == false) {
+		hw->fc.current_mode = ixgbe_fc_none;
+		hw->fc.fc_was_autonegged = false;
+	}
 
 	return 0;
 }
@@ -558,6 +672,8 @@
 	s32 status = 0;
 	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+	u32 start_autoc = autoc;
+	u32 orig_autoc = 0;
 	u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
 	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
 	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
@@ -571,15 +687,25 @@
 
 	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
 		status = IXGBE_ERR_LINK_SETUP;
-	} else if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
-	           link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
-	           link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
+		goto out;
+	}
+
+	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
+	if (hw->mac.orig_link_settings_stored)
+		orig_autoc = hw->mac.orig_autoc;
+	else
+		orig_autoc = autoc;
+
+
+	if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
+	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
+	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
 		/* Set KX4/KX/KR support according to speed requested */
 		autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
 		if (speed & IXGBE_LINK_SPEED_10GB_FULL)
-			if (hw->mac.orig_autoc & IXGBE_AUTOC_KX4_SUPP)
+			if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
 				autoc |= IXGBE_AUTOC_KX4_SUPP;
-			if (hw->mac.orig_autoc & IXGBE_AUTOC_KR_SUPP)
+			if (orig_autoc & IXGBE_AUTOC_KR_SUPP)
 				autoc |= IXGBE_AUTOC_KR_SUPP;
 		if (speed & IXGBE_LINK_SPEED_1GB_FULL)
 			autoc |= IXGBE_AUTOC_KX_SUPP;
@@ -605,7 +731,7 @@
 		}
 	}
 
-	if (status == 0) {
+	if (autoc != start_autoc) {
 		/* Restart link */
 		autoc |= IXGBE_AUTOC_AN_RESTART;
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
@@ -632,13 +758,11 @@
 			}
 		}
 
-		/* Set up flow control */
-		status = ixgbe_setup_fc_generic(hw, 0);
-
 		/* Add delay to filter out noises during initial link setup */
 		msleep(50);
 	}
 
+out:
 	return status;
 }
 
@@ -705,14 +829,30 @@
 	/* Call adapter stop to disable tx/rx and clear interrupts */
 	hw->mac.ops.stop_adapter(hw);
 
+	/* PHY ops must be identified and initialized prior to reset */
+
+	/* Init PHY and function pointers, perform SFP setup */
+	status = hw->phy.ops.init(hw);
+
+	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+		goto reset_hw_out;
+
+	/* Setup SFP module if there is one present. */
+	if (hw->phy.sfp_setup_needed) {
+		status = hw->mac.ops.setup_sfp(hw);
+		hw->phy.sfp_setup_needed = false;
+	}
+
 	/* Reset PHY */
-	hw->phy.ops.reset(hw);
+	if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
+		hw->phy.ops.reset(hw);
 
 	/*
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	if (ixgbe_disable_pcie_master(hw) != 0) {
+	status = ixgbe_disable_pcie_master(hw);
+	if (status != 0) {
 		status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
 		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
 	}
@@ -770,9 +910,30 @@
 		}
 	}
 
+	/*
+	 * Store MAC address from RAR0, clear receive address registers, and
+	 * clear the multicast table.  Also reset num_rar_entries to 128,
+	 * since we modify this value when programming the SAN MAC address.
+	 */
+	hw->mac.num_rar_entries = 128;
+	hw->mac.ops.init_rx_addrs(hw);
+
 	/* Store the permanent mac address */
 	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
 
+	/* Store the permanent SAN mac address */
+	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
+
+	/* Add the SAN MAC address to the RAR only if it's a valid address */
+	if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+		hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
+		                    hw->mac.san_addr, 0, IXGBE_RAH_AV);
+
+		/* Reserve the last RAR for the SAN MAC address */
+		hw->mac.num_rar_entries--;
+	}
+
+reset_hw_out:
 	return status;
 }
 
@@ -1004,6 +1165,931 @@
 }
 
 /**
+ *  ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
+ *  @hw: pointer to hardware structure
+ **/
+s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
+{
+	int i;
+	u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
+	fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
+
+	/*
+	 * Before starting reinitialization process,
+	 * FDIRCMD.CMD must be zero.
+	 */
+	for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
+		if (!(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
+		      IXGBE_FDIRCMD_CMD_MASK))
+			break;
+		udelay(10);
+	}
+	if (i >= IXGBE_FDIRCMD_CMD_POLL) {
+		hw_dbg(hw ,"Flow Director previous command isn't complete, "
+		       "aborting table re-initialization. \n");
+		return IXGBE_ERR_FDIR_REINIT_FAILED;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
+	IXGBE_WRITE_FLUSH(hw);
+	/*
+	 * 82599 adapters flow director init flow cannot be restarted,
+	 * Workaround 82599 silicon errata by performing the following steps
+	 * before re-writing the FDIRCTRL control register with the same value.
+	 * - write 1 to bit 8 of FDIRCMD register &
+	 * - write 0 to bit 8 of FDIRCMD register
+	 */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+	                (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
+	                 IXGBE_FDIRCMD_CLEARHT));
+	IXGBE_WRITE_FLUSH(hw);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+	                (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
+	                 ~IXGBE_FDIRCMD_CLEARHT));
+	IXGBE_WRITE_FLUSH(hw);
+	/*
+	 * Clear FDIR Hash register to clear any leftover hashes
+	 * waiting to be programmed.
+	 */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00);
+	IXGBE_WRITE_FLUSH(hw);
+
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
+	IXGBE_WRITE_FLUSH(hw);
+
+	/* Poll init-done after we write FDIRCTRL register */
+	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
+		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
+		                   IXGBE_FDIRCTRL_INIT_DONE)
+			break;
+		udelay(10);
+	}
+	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
+		hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
+		return IXGBE_ERR_FDIR_REINIT_FAILED;
+	}
+
+	/* Clear FDIR statistics registers (read to clear) */
+	IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT);
+	IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT);
+	IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
+	IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+	IXGBE_READ_REG(hw, IXGBE_FDIRLEN);
+
+	return 0;
+}
+
+/**
+ *  ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ *  @hw: pointer to hardware structure
+ *  @pballoc: which mode to allocate filters with
+ **/
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
+{
+	u32 fdirctrl = 0;
+	u32 pbsize;
+	int i;
+
+	/*
+	 * Before enabling Flow Director, the Rx Packet Buffer size
+	 * must be reduced.  The new value is the current size minus
+	 * flow director memory usage size.
+	 */
+	pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
+	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
+	    (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
+
+	/*
+	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
+	 * intialized to zero for non DCB mode otherwise actual total RX PB
+	 * would be bigger than programmed and filter space would run into
+	 * the PB 0 region.
+	 */
+	for (i = 1; i < 8; i++)
+		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+
+	/* Send interrupt when 64 filters are left */
+	fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
+
+	/* Set the maximum length per hash bucket to 0xA filters */
+	fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
+
+	switch (pballoc) {
+	case IXGBE_FDIR_PBALLOC_64K:
+		/* 8k - 1 signature filters */
+		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+		break;
+	case IXGBE_FDIR_PBALLOC_128K:
+		/* 16k - 1 signature filters */
+		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+		break;
+	case IXGBE_FDIR_PBALLOC_256K:
+		/* 32k - 1 signature filters */
+		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+		break;
+	default:
+		/* bad value */
+		return IXGBE_ERR_CONFIG;
+	};
+
+	/* Move the flexible bytes to use the ethertype - shift 6 words */
+	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+
+	fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
+
+	/* Prime the keys for hashing */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
+	                htonl(IXGBE_ATR_BUCKET_HASH_KEY));
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
+	                htonl(IXGBE_ATR_SIGNATURE_HASH_KEY));
+
+	/*
+	 * Poll init-done after we write the register.  Estimated times:
+	 *      10G: PBALLOC = 11b, timing is 60us
+	 *       1G: PBALLOC = 11b, timing is 600us
+	 *     100M: PBALLOC = 11b, timing is 6ms
+	 *
+	 *     Multiple these timings by 4 if under full Rx load
+	 *
+	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
+	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
+	 * this might not finish in our poll time, but we can live with that
+	 * for now.
+	 */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
+	IXGBE_WRITE_FLUSH(hw);
+	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
+		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
+		                   IXGBE_FDIRCTRL_INIT_DONE)
+			break;
+		msleep(1);
+	}
+	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
+		hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
+
+	return 0;
+}
+
+/**
+ *  ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ *  @hw: pointer to hardware structure
+ *  @pballoc: which mode to allocate filters with
+ **/
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
+{
+	u32 fdirctrl = 0;
+	u32 pbsize;
+	int i;
+
+	/*
+	 * Before enabling Flow Director, the Rx Packet Buffer size
+	 * must be reduced.  The new value is the current size minus
+	 * flow director memory usage size.
+	 */
+	pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
+	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
+	    (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
+
+	/*
+	 * The defaults in the HW for RX PB 1-7 are not zero and so should be
+	 * intialized to zero for non DCB mode otherwise actual total RX PB
+	 * would be bigger than programmed and filter space would run into
+	 * the PB 0 region.
+	 */
+	for (i = 1; i < 8; i++)
+		IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+
+	/* Send interrupt when 64 filters are left */
+	fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
+
+	switch (pballoc) {
+	case IXGBE_FDIR_PBALLOC_64K:
+		/* 2k - 1 perfect filters */
+		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+		break;
+	case IXGBE_FDIR_PBALLOC_128K:
+		/* 4k - 1 perfect filters */
+		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+		break;
+	case IXGBE_FDIR_PBALLOC_256K:
+		/* 8k - 1 perfect filters */
+		fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+		break;
+	default:
+		/* bad value */
+		return IXGBE_ERR_CONFIG;
+	};
+
+	/* Turn perfect match filtering on */
+	fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
+	fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
+
+	/* Move the flexible bytes to use the ethertype - shift 6 words */
+	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+
+	/* Prime the keys for hashing */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
+	                htonl(IXGBE_ATR_BUCKET_HASH_KEY));
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
+	                htonl(IXGBE_ATR_SIGNATURE_HASH_KEY));
+
+	/*
+	 * Poll init-done after we write the register.  Estimated times:
+	 *      10G: PBALLOC = 11b, timing is 60us
+	 *       1G: PBALLOC = 11b, timing is 600us
+	 *     100M: PBALLOC = 11b, timing is 6ms
+	 *
+	 *     Multiple these timings by 4 if under full Rx load
+	 *
+	 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
+	 * 1 msec per poll time.  If we're at line rate and drop to 100M, then
+	 * this might not finish in our poll time, but we can live with that
+	 * for now.
+	 */
+
+	/* Set the maximum length per hash bucket to 0xA filters */
+	fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
+
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
+	IXGBE_WRITE_FLUSH(hw);
+	for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
+		if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
+		                   IXGBE_FDIRCTRL_INIT_DONE)
+			break;
+		msleep(1);
+	}
+	if (i >= IXGBE_FDIR_INIT_DONE_POLL)
+		hw_dbg(hw, "Flow Director Perfect poll time exceeded!\n");
+
+	return 0;
+}
+
+
+/**
+ *  ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
+ *  @stream: input bitstream to compute the hash on
+ *  @key: 32-bit hash key
+ **/
+u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key)
+{
+	/*
+	 * The algorithm is as follows:
+	 *    Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
+	 *    where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
+	 *    and A[n] x B[n] is bitwise AND between same length strings
+	 *
+	 *    K[n] is 16 bits, defined as:
+	 *       for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
+	 *       for n modulo 32 < 15, K[n] =
+	 *             K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
+	 *
+	 *    S[n] is 16 bits, defined as:
+	 *       for n >= 15, S[n] = S[n:n - 15]
+	 *       for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
+	 *
+	 *    To simplify for programming, the algorithm is implemented
+	 *    in software this way:
+	 *
+	 *    Key[31:0], Stream[335:0]
+	 *
+	 *    tmp_key[11 * 32 - 1:0] = 11{Key[31:0] = key concatenated 11 times
+	 *    int_key[350:0] = tmp_key[351:1]
+	 *    int_stream[365:0] = Stream[14:0] | Stream[335:0] | Stream[335:321]
+	 *
+	 *    hash[15:0] = 0;
+	 *    for (i = 0; i < 351; i++) {
+	 *        if (int_key[i])
+	 *            hash ^= int_stream[(i + 15):i];
+	 *    }
+	 */
+
+	union {
+		u64    fill[6];
+		u32    key[11];
+		u8     key_stream[44];
+	} tmp_key;
+
+	u8   *stream = (u8 *)atr_input;
+	u8   int_key[44];      /* upper-most bit unused */
+	u8   hash_str[46];     /* upper-most 2 bits unused */
+	u16  hash_result = 0;
+	int  i, j, k, h;
+
+	/*
+	 * Initialize the fill member to prevent warnings
+	 * on some compilers
+	 */
+	 tmp_key.fill[0] = 0;
+
+	/* First load the temporary key stream */
+	for (i = 0; i < 6; i++) {
+		u64 fillkey = ((u64)key << 32) | key;
+		tmp_key.fill[i] = fillkey;
+	}
+
+	/*
+	 * Set the interim key for the hashing.  Bit 352 is unused, so we must
+	 * shift and compensate when building the key.
+	 */
+
+	int_key[0] = tmp_key.key_stream[0] >> 1;
+	for (i = 1, j = 0; i < 44; i++) {
+		unsigned int this_key = tmp_key.key_stream[j] << 7;
+		j++;
+		int_key[i] = (u8)(this_key | (tmp_key.key_stream[j] >> 1));
+	}
+
+	/*
+	 * Set the interim bit string for the hashing.  Bits 368 and 367 are
+	 * unused, so shift and compensate when building the string.
+	 */
+	hash_str[0] = (stream[40] & 0x7f) >> 1;
+	for (i = 1, j = 40; i < 46; i++) {
+		unsigned int this_str = stream[j] << 7;
+		j++;
+		if (j > 41)
+			j = 0;
+		hash_str[i] = (u8)(this_str | (stream[j] >> 1));
+	}
+
+	/*
+	 * Now compute the hash.  i is the index into hash_str, j is into our
+	 * key stream, k is counting the number of bits, and h interates within
+	 * each byte.
+	 */
+	for (i = 45, j = 43, k = 0; k < 351 && i >= 2 && j >= 0; i--, j--) {
+		for (h = 0; h < 8 && k < 351; h++, k++) {
+			if (int_key[j] & (1 << h)) {
+				/*
+				 * Key bit is set, XOR in the current 16-bit
+				 * string.  Example of processing:
+				 *    h = 0,
+				 *      tmp = (hash_str[i - 2] & 0 << 16) |
+				 *            (hash_str[i - 1] & 0xff << 8) |
+				 *            (hash_str[i] & 0xff >> 0)
+				 *      So tmp = hash_str[15 + k:k], since the
+				 *      i + 2 clause rolls off the 16-bit value
+				 *    h = 7,
+				 *      tmp = (hash_str[i - 2] & 0x7f << 9) |
+				 *            (hash_str[i - 1] & 0xff << 1) |
+				 *            (hash_str[i] & 0x80 >> 7)
+				 */
+				int tmp = (hash_str[i] >> h);
+				tmp |= (hash_str[i - 1] << (8 - h));
+				tmp |= (int)(hash_str[i - 2] & ((1 << h) - 1))
+				             << (16 - h);
+				hash_result ^= (u16)tmp;
+			}
+		}
+	}
+
+	return hash_result;
+}
+
+/**
+ *  ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream
+ *  @input: input stream to modify
+ *  @vlan: the VLAN id to load
+ **/
+s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
+{
+	input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8;
+	input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address
+ *  @input: input stream to modify
+ *  @src_addr: the IP address to load
+ **/
+s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
+{
+	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24;
+	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] =
+	                                               (src_addr >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] =
+	                                                (src_addr >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET] = src_addr & 0xff;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address
+ *  @input: input stream to modify
+ *  @dst_addr: the IP address to load
+ **/
+s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
+{
+	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24;
+	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] =
+	                                               (dst_addr >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] =
+	                                                (dst_addr >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET] = dst_addr & 0xff;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address
+ *  @input: input stream to modify
+ *  @src_addr_1: the first 4 bytes of the IP address to load
+ *  @src_addr_2: the second 4 bytes of the IP address to load
+ *  @src_addr_3: the third 4 bytes of the IP address to load
+ *  @src_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
+                                 u32 src_addr_1, u32 src_addr_2,
+                                 u32 src_addr_3, u32 src_addr_4)
+{
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] =
+	                                               (src_addr_4 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] =
+	                                              (src_addr_4 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24;
+
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] =
+	                                               (src_addr_3 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] =
+	                                              (src_addr_3 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24;
+
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] =
+	                                               (src_addr_2 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] =
+	                                              (src_addr_2 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24;
+
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] =
+	                                               (src_addr_1 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] =
+	                                              (src_addr_1 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address
+ *  @input: input stream to modify
+ *  @dst_addr_1: the first 4 bytes of the IP address to load
+ *  @dst_addr_2: the second 4 bytes of the IP address to load
+ *  @dst_addr_3: the third 4 bytes of the IP address to load
+ *  @dst_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
+                                 u32 dst_addr_1, u32 dst_addr_2,
+                                 u32 dst_addr_3, u32 dst_addr_4)
+{
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] =
+	                                               (dst_addr_4 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] =
+	                                              (dst_addr_4 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24;
+
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] =
+	                                               (dst_addr_3 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] =
+	                                              (dst_addr_3 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24;
+
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] =
+	                                               (dst_addr_2 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] =
+	                                              (dst_addr_2 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24;
+
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] =
+	                                               (dst_addr_1 >> 8) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] =
+	                                              (dst_addr_1 >> 16) & 0xff;
+	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_src_port_82599 - Sets the source port
+ *  @input: input stream to modify
+ *  @src_port: the source port to load
+ **/
+s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
+{
+	input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8;
+	input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_dst_port_82599 - Sets the destination port
+ *  @input: input stream to modify
+ *  @dst_port: the destination port to load
+ **/
+s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port)
+{
+	input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8;
+	input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_flex_byte_82599 - Sets the flexible bytes
+ *  @input: input stream to modify
+ *  @flex_bytes: the flexible bytes to load
+ **/
+s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
+{
+	input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8;
+	input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool
+ *  @input: input stream to modify
+ *  @vm_pool: the Virtual Machine pool to load
+ **/
+s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool)
+{
+	input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type
+ *  @input: input stream to modify
+ *  @l4type: the layer 4 type value to load
+ **/
+s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type)
+{
+	input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_vlan_id_82599 - Gets the VLAN id from the ATR input stream
+ *  @input: input stream to search
+ *  @vlan: the VLAN id to load
+ **/
+s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan)
+{
+	*vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET];
+	*vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_src_ipv4_82599 - Gets the source IPv4 address
+ *  @input: input stream to search
+ *  @src_addr: the IP address to load
+ **/
+s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr)
+{
+	*src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET];
+	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8;
+	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16;
+	*src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] << 24;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_dst_ipv4_82599 - Gets the destination IPv4 address
+ *  @input: input stream to search
+ *  @dst_addr: the IP address to load
+ **/
+s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr)
+{
+	*dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET];
+	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8;
+	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16;
+	*dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] << 24;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_src_ipv6_82599 - Gets the source IPv6 address
+ *  @input: input stream to search
+ *  @src_addr_1: the first 4 bytes of the IP address to load
+ *  @src_addr_2: the second 4 bytes of the IP address to load
+ *  @src_addr_3: the third 4 bytes of the IP address to load
+ *  @src_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
+                                 u32 *src_addr_1, u32 *src_addr_2,
+                                 u32 *src_addr_3, u32 *src_addr_4)
+{
+	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12];
+	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8;
+	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16;
+	*src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] << 24;
+
+	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8];
+	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] << 8;
+	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] << 16;
+	*src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] << 24;
+
+	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4];
+	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] << 8;
+	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] << 16;
+	*src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] << 24;
+
+	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET];
+	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] << 8;
+	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] << 16;
+	*src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] << 24;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address
+ *  @input: input stream to search
+ *  @dst_addr_1: the first 4 bytes of the IP address to load
+ *  @dst_addr_2: the second 4 bytes of the IP address to load
+ *  @dst_addr_3: the third 4 bytes of the IP address to load
+ *  @dst_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
+                                 u32 *dst_addr_1, u32 *dst_addr_2,
+                                 u32 *dst_addr_3, u32 *dst_addr_4)
+{
+	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12];
+	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8;
+	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16;
+	*dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24;
+
+	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8];
+	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8;
+	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16;
+	*dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24;
+
+	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4];
+	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8;
+	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16;
+	*dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24;
+
+	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET];
+	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8;
+	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16;
+	*dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_src_port_82599 - Gets the source port
+ *  @input: input stream to modify
+ *  @src_port: the source port to load
+ *
+ *  Even though the input is given in big-endian, the FDIRPORT registers
+ *  expect the ports to be programmed in little-endian.  Hence the need to swap
+ *  endianness when retrieving the data.  This can be confusing since the
+ *  internal hash engine expects it to be big-endian.
+ **/
+s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port)
+{
+	*src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8;
+	*src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1];
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_dst_port_82599 - Gets the destination port
+ *  @input: input stream to modify
+ *  @dst_port: the destination port to load
+ *
+ *  Even though the input is given in big-endian, the FDIRPORT registers
+ *  expect the ports to be programmed in little-endian.  Hence the need to swap
+ *  endianness when retrieving the data.  This can be confusing since the
+ *  internal hash engine expects it to be big-endian.
+ **/
+s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port)
+{
+	*dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8;
+	*dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1];
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_flex_byte_82599 - Gets the flexible bytes
+ *  @input: input stream to modify
+ *  @flex_bytes: the flexible bytes to load
+ **/
+s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte)
+{
+	*flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET];
+	*flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8;
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool
+ *  @input: input stream to modify
+ *  @vm_pool: the Virtual Machine pool to load
+ **/
+s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool)
+{
+	*vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET];
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type
+ *  @input: input stream to modify
+ *  @l4type: the layer 4 type value to load
+ **/
+s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type)
+{
+	*l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET];
+
+	return 0;
+}
+
+/**
+ *  ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter
+ *  @hw: pointer to hardware structure
+ *  @stream: input bitstream
+ *  @queue: queue index to direct traffic to
+ **/
+s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+                                          struct ixgbe_atr_input *input,
+                                          u8 queue)
+{
+	u64  fdirhashcmd;
+	u64  fdircmd;
+	u32  fdirhash;
+	u16  bucket_hash, sig_hash;
+	u8   l4type;
+
+	bucket_hash = ixgbe_atr_compute_hash_82599(input,
+	                                           IXGBE_ATR_BUCKET_HASH_KEY);
+
+	/* bucket_hash is only 15 bits */
+	bucket_hash &= IXGBE_ATR_HASH_MASK;
+
+	sig_hash = ixgbe_atr_compute_hash_82599(input,
+	                                        IXGBE_ATR_SIGNATURE_HASH_KEY);
+
+	/* Get the l4type in order to program FDIRCMD properly */
+	/* lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 */
+	ixgbe_atr_get_l4type_82599(input, &l4type);
+
+	/*
+	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
+	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
+	 */
+	fdirhash = sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
+
+	fdircmd = (IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
+	           IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN);
+
+	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
+	case IXGBE_ATR_L4TYPE_TCP:
+		fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
+		break;
+	case IXGBE_ATR_L4TYPE_UDP:
+		fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
+		break;
+	case IXGBE_ATR_L4TYPE_SCTP:
+		fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+		break;
+	default:
+		hw_dbg(hw, "Error on l4type input\n");
+		return IXGBE_ERR_CONFIG;
+	}
+
+	if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK)
+		fdircmd |= IXGBE_FDIRCMD_IPV6;
+
+	fdircmd |= ((u64)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT);
+	fdirhashcmd = ((fdircmd << 32) | fdirhash);
+
+	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
+
+	return 0;
+}
+
+/**
+ *  ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
+ *  @hw: pointer to hardware structure
+ *  @input: input bitstream
+ *  @queue: queue index to direct traffic to
+ *
+ *  Note that the caller to this function must lock before calling, since the
+ *  hardware writes must be protected from one another.
+ **/
+s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
+                                        struct ixgbe_atr_input *input,
+                                        u16 soft_id,
+                                        u8 queue)
+{
+	u32 fdircmd = 0;
+	u32 fdirhash;
+	u32 src_ipv4, dst_ipv4;
+	u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4;
+	u16 src_port, dst_port, vlan_id, flex_bytes;
+	u16 bucket_hash;
+	u8  l4type;
+
+	/* Get our input values */
+	ixgbe_atr_get_l4type_82599(input, &l4type);
+
+	/*
+	 * Check l4type formatting, and bail out before we touch the hardware
+	 * if there's a configuration issue
+	 */
+	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
+	case IXGBE_ATR_L4TYPE_TCP:
+		fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
+		break;
+	case IXGBE_ATR_L4TYPE_UDP:
+		fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
+		break;
+	case IXGBE_ATR_L4TYPE_SCTP:
+		fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+		break;
+	default:
+		hw_dbg(hw, "Error on l4type input\n");
+		return IXGBE_ERR_CONFIG;
+	}
+
+	bucket_hash = ixgbe_atr_compute_hash_82599(input,
+	                                           IXGBE_ATR_BUCKET_HASH_KEY);
+
+	/* bucket_hash is only 15 bits */
+	bucket_hash &= IXGBE_ATR_HASH_MASK;
+
+	ixgbe_atr_get_vlan_id_82599(input, &vlan_id);
+	ixgbe_atr_get_src_port_82599(input, &src_port);
+	ixgbe_atr_get_dst_port_82599(input, &dst_port);
+	ixgbe_atr_get_flex_byte_82599(input, &flex_bytes);
+
+	fdirhash = soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
+
+	/* Now figure out if we're IPv4 or IPv6 */
+	if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK) {
+		/* IPv6 */
+		ixgbe_atr_get_src_ipv6_82599(input, &src_ipv6_1, &src_ipv6_2,
+	                                     &src_ipv6_3, &src_ipv6_4);
+
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), src_ipv6_1);
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), src_ipv6_2);
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), src_ipv6_3);
+		/* The last 4 bytes is the same register as IPv4 */
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv6_4);
+
+		fdircmd |= IXGBE_FDIRCMD_IPV6;
+		fdircmd |= IXGBE_FDIRCMD_IPv6DMATCH;
+	} else {
+		/* IPv4 */
+		ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4);
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4);
+
+	}
+
+	ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, dst_ipv4);
+
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id |
+	                            (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT)));
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port |
+	                       (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
+
+	fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW;
+	fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE;
+	fdircmd |= IXGBE_FDIRCMD_LAST;
+	fdircmd |= IXGBE_FDIRCMD_QUEUE_EN;
+	fdircmd |= queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
+
+	return 0;
+}
+/**
  *  ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
  *  @hw: pointer to hardware structure
  *  @reg: analog register to read
@@ -1056,8 +2142,9 @@
 s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw)
 {
 	u32 q_num;
+	s32 ret_val;
 
-	ixgbe_start_hw_generic(hw);
+	ret_val = ixgbe_start_hw_generic(hw);
 
 	/* Clear the rate limiters */
 	for (q_num = 0; q_num < hw->mac.max_tx_queues; q_num++) {
@@ -1066,7 +2153,13 @@
 	}
 	IXGBE_WRITE_FLUSH(hw);
 
-	return 0;
+	/* We need to run link autotry after the driver loads */
+	hw->mac.autotry_restart = true;
+
+	if (ret_val == 0)
+		ret_val = ixgbe_verify_fw_version_82599(hw);
+
+	return ret_val;
 }
 
 /**
@@ -1093,53 +2186,100 @@
 u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
 {
 	u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+	u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+	u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
+	u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
+	u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
+	u16 ext_ability = 0;
 	u8 comp_codes_10g = 0;
 
-	switch (hw->device_id) {
-	case IXGBE_DEV_ID_82599:
-	case IXGBE_DEV_ID_82599_KX4:
-		/* Default device ID is mezzanine card KX/KX4 */
-		physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
-		                  IXGBE_PHYSICAL_LAYER_1000BASE_KX);
+	hw->phy.ops.identify(hw);
+
+	if (hw->phy.type == ixgbe_phy_tn ||
+	    hw->phy.type == ixgbe_phy_cu_unknown) {
+		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
+				     &ext_ability);
+		if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
+		if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+		goto out;
+	}
+
+	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
+	case IXGBE_AUTOC_LMS_1G_AN:
+	case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
+		if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
+			physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
+			    IXGBE_PHYSICAL_LAYER_1000BASE_BX;
+			goto out;
+		} else
+			/* SFI mode so read SFP module */
+			goto sfp_check;
 		break;
-	case IXGBE_DEV_ID_82599_SFP:
-		hw->phy.ops.identify_sfp(hw);
+	case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
+		if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
+		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
+		else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI)
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI;
+		goto out;
+		break;
+	case IXGBE_AUTOC_LMS_10G_SERIAL:
+		if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
+			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
+			goto out;
+		} else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
+			goto sfp_check;
+		break;
+	case IXGBE_AUTOC_LMS_KX4_KX_KR:
+	case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
+		if (autoc & IXGBE_AUTOC_KX_SUPP)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+		if (autoc & IXGBE_AUTOC_KX4_SUPP)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
+		if (autoc & IXGBE_AUTOC_KR_SUPP)
+			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
+		goto out;
+		break;
+	default:
+		goto out;
+		break;
+	}
 
-		switch (hw->phy.sfp_type) {
-		case ixgbe_sfp_type_da_cu:
-		case ixgbe_sfp_type_da_cu_core0:
-		case ixgbe_sfp_type_da_cu_core1:
-			physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
-			break;
-		case ixgbe_sfp_type_sr:
+sfp_check:
+	/* SFP check must be done last since DA modules are sometimes used to
+	 * test KR mode -  we need to id KR mode correctly before SFP module.
+	 * Call identify_sfp because the pluggable module may have changed */
+	hw->phy.ops.identify_sfp(hw);
+	if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
+		goto out;
+
+	switch (hw->phy.type) {
+	case ixgbe_phy_tw_tyco:
+	case ixgbe_phy_tw_unknown:
+		physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+		break;
+	case ixgbe_phy_sfp_avago:
+	case ixgbe_phy_sfp_ftl:
+	case ixgbe_phy_sfp_intel:
+	case ixgbe_phy_sfp_unknown:
+		hw->phy.ops.read_i2c_eeprom(hw,
+		      IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
+		if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-			break;
-		case ixgbe_sfp_type_lr:
+		else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
 			physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-			break;
-		case ixgbe_sfp_type_srlr_core0:
-		case ixgbe_sfp_type_srlr_core1:
-			hw->phy.ops.read_i2c_eeprom(hw,
-			                            IXGBE_SFF_10GBE_COMP_CODES,
-			                            &comp_codes_10g);
-			if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
-				physical_layer =
-				                IXGBE_PHYSICAL_LAYER_10GBASE_SR;
-			else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
-				physical_layer =
-				                IXGBE_PHYSICAL_LAYER_10GBASE_LR;
-			else
-				physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-		default:
-			physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
-			break;
-		}
 		break;
 	default:
-		physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
 		break;
 	}
 
+out:
 	return physical_layer;
 }
 
@@ -1187,6 +2327,138 @@
 	return 0;
 }
 
+/**
+ *  ixgbe_get_device_caps_82599 - Get additional device capabilities
+ *  @hw: pointer to hardware structure
+ *  @device_caps: the EEPROM word with the extra device capabilities
+ *
+ *  This function will read the EEPROM location for the device capabilities,
+ *  and return the word through device_caps.
+ **/
+s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps)
+{
+	hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
+
+	return 0;
+}
+
+/**
+ *  ixgbe_get_san_mac_addr_offset_82599 - SAN MAC address offset for 82599
+ *  @hw: pointer to hardware structure
+ *  @san_mac_offset: SAN MAC address offset
+ *
+ *  This function will read the EEPROM location for the SAN MAC address
+ *  pointer, and returns the value at that location.  This is used in both
+ *  get and set mac_addr routines.
+ **/
+s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw,
+                                        u16 *san_mac_offset)
+{
+	/*
+	 * First read the EEPROM pointer to see if the MAC addresses are
+	 * available.
+	 */
+	hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset);
+
+	return 0;
+}
+
+/**
+ *  ixgbe_get_san_mac_addr_82599 - SAN MAC address retrieval for 82599
+ *  @hw: pointer to hardware structure
+ *  @san_mac_addr: SAN MAC address
+ *
+ *  Reads the SAN MAC address from the EEPROM, if it's available.  This is
+ *  per-port, so set_lan_id() must be called before reading the addresses.
+ *  set_lan_id() is called by identify_sfp(), but this cannot be relied
+ *  upon for non-SFP connections, so we must call it here.
+ **/
+s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr)
+{
+	u16 san_mac_data, san_mac_offset;
+	u8 i;
+
+	/*
+	 * First read the EEPROM pointer to see if the MAC addresses are
+	 * available.  If they're not, no point in calling set_lan_id() here.
+	 */
+	ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset);
+
+	if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
+		/*
+		 * No addresses available in this EEPROM.  It's not an
+		 * error though, so just wipe the local address and return.
+		 */
+		for (i = 0; i < 6; i++)
+			san_mac_addr[i] = 0xFF;
+
+		goto san_mac_addr_out;
+	}
+
+	/* make sure we know which port we need to program */
+	hw->mac.ops.set_lan_id(hw);
+	/* apply the port offset to the address offset */
+	(hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
+	                 (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
+	for (i = 0; i < 3; i++) {
+		hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data);
+		san_mac_addr[i * 2] = (u8)(san_mac_data);
+		san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
+		san_mac_offset++;
+	}
+
+san_mac_addr_out:
+	return 0;
+}
+
+/**
+ *  ixgbe_verify_fw_version_82599 - verify fw version for 82599
+ *  @hw: pointer to hardware structure
+ *
+ *  Verifies that installed the firmware version is 0.6 or higher
+ *  for SFI devices. All 82599 SFI devices should have version 0.6 or higher.
+ *
+ *  Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or
+ *  if the FW version is not supported.
+ **/
+static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
+{
+	s32 status = IXGBE_ERR_EEPROM_VERSION;
+	u16 fw_offset, fw_ptp_cfg_offset;
+	u16 fw_version = 0;
+
+	/* firmware check is only necessary for SFI devices */
+	if (hw->phy.media_type != ixgbe_media_type_fiber) {
+		status = 0;
+		goto fw_version_out;
+	}
+
+	/* get the offset to the Firmware Module block */
+	hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
+
+	if ((fw_offset == 0) || (fw_offset == 0xFFFF))
+		goto fw_version_out;
+
+	/* get the offset to the Pass Through Patch Configuration block */
+	hw->eeprom.ops.read(hw, (fw_offset +
+	                         IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR),
+	                         &fw_ptp_cfg_offset);
+
+	if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
+		goto fw_version_out;
+
+	/* get the firmware version */
+	hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset +
+	                         IXGBE_FW_PATCH_VERSION_4),
+	                         &fw_version);
+
+	if (fw_version > 0x5)
+		status = 0;
+
+fw_version_out:
+	return status;
+}
+
 static struct ixgbe_mac_operations mac_ops_82599 = {
 	.init_hw                = &ixgbe_init_hw_generic,
 	.reset_hw               = &ixgbe_reset_hw_82599,
@@ -1196,6 +2468,8 @@
 	.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82599,
 	.enable_rx_dma          = &ixgbe_enable_rx_dma_82599,
 	.get_mac_addr           = &ixgbe_get_mac_addr_generic,
+	.get_san_mac_addr       = &ixgbe_get_san_mac_addr_82599,
+	.get_device_caps        = &ixgbe_get_device_caps_82599,
 	.stop_adapter           = &ixgbe_stop_adapter_generic,
 	.get_bus_info           = &ixgbe_get_bus_info_generic,
 	.set_lan_id             = &ixgbe_set_lan_id_multi_port_pcie,
@@ -1220,7 +2494,7 @@
 	.disable_mc             = &ixgbe_disable_mc_generic,
 	.clear_vfta             = &ixgbe_clear_vfta_82599,
 	.set_vfta               = &ixgbe_set_vfta_82599,
-	.setup_fc               = &ixgbe_setup_fc_generic,
+	.fc_enable               = &ixgbe_fc_enable_generic,
 	.init_uta_tables        = &ixgbe_init_uta_tables_82599,
 	.setup_sfp              = &ixgbe_setup_sfp_modules_82599,
 };
@@ -1236,6 +2510,7 @@
 static struct ixgbe_phy_operations phy_ops_82599 = {
 	.identify               = &ixgbe_identify_phy_82599,
 	.identify_sfp           = &ixgbe_identify_sfp_module_generic,
+	.init			= &ixgbe_init_phy_ops_82599,
 	.reset                  = &ixgbe_reset_phy_generic,
 	.read_reg               = &ixgbe_read_phy_reg_generic,
 	.write_reg              = &ixgbe_write_phy_reg_generic,
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_common.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_common.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_common.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,8 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
 
 #include "ixgbe.h"
 #include "ixgbe_common.h"
@@ -71,12 +73,6 @@
 	/* Identify the PHY */
 	hw->phy.ops.identify(hw);
 
-	/*
-	 * Store MAC address from RAR0, clear receive address registers, and
-	 * clear the multicast table
-	 */
-	hw->mac.ops.init_rx_addrs(hw);
-
 	/* Clear the VLAN filter table */
 	hw->mac.ops.clear_vfta(hw);
 
@@ -89,6 +85,9 @@
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
 	IXGBE_WRITE_FLUSH(hw);
 
+	/* Setup flow control */
+	ixgbe_setup_fc(hw, 0);
+
 	/* Clear adapter stopped flag */
 	hw->adapter_stopped = false;
 
@@ -107,13 +106,17 @@
  **/
 s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
 {
+	s32 status;
+
 	/* Reset the hardware */
-	hw->mac.ops.reset_hw(hw);
+	status = hw->mac.ops.reset_hw(hw);
 
-	/* Start the HW */
-	hw->mac.ops.start_hw(hw);
+	if (status == 0) {
+		/* Start the HW */
+		status = hw->mac.ops.start_hw(hw);
+	}
 
-	return 0;
+	return status;
 }
 
 /**
@@ -1362,15 +1365,14 @@
  *  Drivers using secondary unicast addresses must set user_set_promisc when
  *  manually putting the device into promiscuous mode.
  **/
-s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
-                              u32 addr_count, ixgbe_mc_addr_itr next)
+s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
+				      struct list_head *uc_list)
 {
-	u8 *addr;
 	u32 i;
 	u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
 	u32 uc_addr_in_use;
 	u32 fctrl;
-	u32 vmdq;
+	struct netdev_hw_addr *ha;
 
 	/*
 	 * Clear accounting of old secondary address list,
@@ -1388,10 +1390,9 @@
 	}
 
 	/* Add the new addresses */
-	for (i = 0; i < addr_count; i++) {
+	list_for_each_entry(ha, uc_list, list) {
 		hw_dbg(hw, " Adding the secondary addresses:\n");
-		addr = next(hw, &addr_list, &vmdq);
-		ixgbe_add_uc_addr(hw, addr, vmdq);
+		ixgbe_add_uc_addr(hw, ha->addr, 0);
 	}
 
 	if (hw->addr_ctrl.overflow_promisc) {
@@ -1583,19 +1584,30 @@
 }
 
 /**
- *  ixgbe_fc_enable - Enable flow control
+ *  ixgbe_fc_enable_generic - Enable flow control
  *  @hw: pointer to hardware structure
  *  @packetbuf_num: packet buffer number (0-7)
  *
  *  Enable flow control according to the current settings.
  **/
-s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
 {
 	s32 ret_val = 0;
-	u32 mflcn_reg;
-	u32 fccfg_reg;
+	u32 mflcn_reg, fccfg_reg;
 	u32 reg;
+	u32 rx_pba_size;
+
+#ifdef CONFIG_DCB
+	if (hw->fc.requested_mode == ixgbe_fc_pfc)
+		goto out;
+
+#endif /* CONFIG_DCB */
+	/* Negotiate the fc mode to use */
+	ret_val = ixgbe_fc_autoneg(hw);
+	if (ret_val)
+		goto out;
 
+	/* Disable any previous flow control settings */
 	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
 	mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
 
@@ -1615,7 +1627,10 @@
 	 */
 	switch (hw->fc.current_mode) {
 	case ixgbe_fc_none:
-		/* Flow control completely disabled by software override. */
+		/*
+		 * Flow control is disabled by software override or autoneg.
+		 * The code below will actually disable it in the HW.
+		 */
 		break;
 	case ixgbe_fc_rx_pause:
 		/*
@@ -1644,7 +1659,7 @@
 	case ixgbe_fc_pfc:
 		goto out;
 		break;
-#endif
+#endif /* CONFIG_DCB */
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
 		ret_val = -IXGBE_ERR_CONFIG;
@@ -1652,25 +1667,48 @@
 		break;
 	}
 
-	/* Enable 802.3x based flow control settings. */
+	/* Set 802.3x based flow control settings. */
+	mflcn_reg |= IXGBE_MFLCN_DPF;
 	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
 	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
 
-	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
-	if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
-		if (hw->fc.send_xon)
-			IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num),
-			                (hw->fc.low_water | IXGBE_FCRTL_XONE));
-		else
-			IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num),
-			                hw->fc.low_water);
+	reg = IXGBE_READ_REG(hw, IXGBE_MTQC);
+	/* Thresholds are different for link flow control when in DCB mode */
+	if (reg & IXGBE_MTQC_RT_ENA) {
+		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
 
-		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num),
-		                (hw->fc.high_water | IXGBE_FCRTH_FCEN));
+		/* Always disable XON for LFC when in DCB mode */
+		reg = (rx_pba_size >> 5) & 0xFFE0;
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg);
+
+		reg = (rx_pba_size >> 2) & 0xFFE0;
+		if (hw->fc.current_mode & ixgbe_fc_tx_pause)
+			reg |= IXGBE_FCRTH_FCEN;
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg);
+	} else {
+		/*
+		 * Set up and enable Rx high/low water mark thresholds,
+		 * enable XON.
+		 */
+		if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
+			if (hw->fc.send_xon) {
+				IXGBE_WRITE_REG(hw,
+				              IXGBE_FCRTL_82599(packetbuf_num),
+			                      (hw->fc.low_water |
+				              IXGBE_FCRTL_XONE));
+			} else {
+				IXGBE_WRITE_REG(hw,
+				              IXGBE_FCRTL_82599(packetbuf_num),
+				              hw->fc.low_water);
+			}
+
+			IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num),
+			               (hw->fc.high_water | IXGBE_FCRTH_FCEN));
+		}
 	}
 
 	/* Configure pause time (2 TCs per register) */
-	reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num));
+	reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
 	if ((packetbuf_num & 1) == 0)
 		reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
 	else
@@ -1687,100 +1725,41 @@
  *  ixgbe_fc_autoneg - Configure flow control
  *  @hw: pointer to hardware structure
  *
- *  Negotiates flow control capabilities with link partner using autoneg and
- *  applies the results.
+ *  Compares our advertised flow control capabilities to those advertised by
+ *  our link partner, and determines the proper flow control mode to use.
  **/
 s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 {
 	s32 ret_val = 0;
-	u32 i, reg, pcs_anadv_reg, pcs_lpab_reg;
-
-	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+	ixgbe_link_speed speed;
+	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+	bool link_up;
 
 	/*
-	 * The possible values of fc.current_mode are:
-	 * 0:  Flow control is completely disabled
-	 * 1:  Rx flow control is enabled (we can receive pause frames,
-	 *     but not send pause frames).
-	 * 2:  Tx flow control is enabled (we can send pause frames but
-	 *     we do not support receiving pause frames).
-	 * 3:  Both Rx and Tx flow control (symmetric) are enabled.
-	 * 4:  Priority Flow Control is enabled.
-	 * other: Invalid.
+	 * AN should have completed when the cable was plugged in.
+	 * Look for reasons to bail out.  Bail out if:
+	 * - FC autoneg is disabled, or if
+	 * - we don't have multispeed fiber, or if
+	 * - we're not running at 1G, or if
+	 * - link is not up, or if
+	 * - link is up but AN did not complete, or if
+	 * - link is up and AN completed but timed out
+	 *
+	 * Since we're being called from an LSC, link is already know to be up.
+	 * So use link_up_wait_to_complete=false.
 	 */
-	switch (hw->fc.current_mode) {
-	case ixgbe_fc_none:
-		/* Flow control completely disabled by software override. */
-		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-		break;
-	case ixgbe_fc_rx_pause:
-		/*
-		 * Rx Flow control is enabled and Tx Flow control is
-		 * disabled by software override. Since there really
-		 * isn't a way to advertise that we are capable of RX
-		 * Pause ONLY, we will advertise that we support both
-		 * symmetric and asymmetric Rx PAUSE.  Later, we will
-		 * disable the adapter's ability to send PAUSE frames.
-		 */
-		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-		break;
-	case ixgbe_fc_tx_pause:
-		/*
-		 * Tx Flow control is enabled, and Rx Flow control is
-		 * disabled by software override.
-		 */
-		reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
-		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
-		break;
-	case ixgbe_fc_full:
-		/* Flow control (both Rx and Tx) is enabled by SW override. */
-		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-		break;
-#ifdef CONFIG_DCB
-	case ixgbe_fc_pfc:
-		goto out;
-		break;
-#endif
-	default:
-		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = -IXGBE_ERR_CONFIG;
-		goto out;
-		break;
-	}
-
-	IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
-	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
-
-	/* Set PCS register for autoneg */
-	/* Enable and restart autoneg */
-	reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
-
-	/* Disable AN timeout */
-	if (hw->fc.strict_ieee)
-		reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
-
-	hw_dbg(hw, "Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg);
-	IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
-
-	/* See if autonegotiation has succeeded */
-	hw->mac.autoneg_succeeded = 0;
-	for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
-		msleep(10);
-		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-		if ((reg & (IXGBE_PCS1GLSTA_LINK_OK |
-		     IXGBE_PCS1GLSTA_AN_COMPLETE)) ==
-		    (IXGBE_PCS1GLSTA_LINK_OK |
-		     IXGBE_PCS1GLSTA_AN_COMPLETE)) {
-			if (!(reg & IXGBE_PCS1GLSTA_AN_TIMED_OUT))
-				hw->mac.autoneg_succeeded = 1;
-			break;
-		}
-	}
+	hw->mac.ops.check_link(hw, &speed, &link_up, false);
+	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
 
-	if (!hw->mac.autoneg_succeeded) {
-		/* Autoneg failed to achieve a link, so we turn fc off */
-		hw->fc.current_mode = ixgbe_fc_none;
-		hw_dbg(hw, "Flow Control = NONE.\n");
+	if (hw->fc.disable_fc_autoneg ||
+	    !hw->phy.multispeed_fiber ||
+	    (speed != IXGBE_LINK_SPEED_1GB_FULL) ||
+	    !link_up ||
+	    ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+	    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+		hw->fc.fc_was_autonegged = false;
+		hw->fc.current_mode = hw->fc.requested_mode;
+		hw_dbg(hw, "Autoneg FC was skipped.\n");
 		goto out;
 	}
 
@@ -1823,21 +1802,23 @@
 		hw_dbg(hw, "Flow Control = NONE.\n");
 	}
 
+	/* Record that current_mode is the result of a successful autoneg */
+	hw->fc.fc_was_autonegged = true;
+
 out:
 	return ret_val;
 }
 
 /**
- *  ixgbe_setup_fc_generic - Set up flow control
+ *  ixgbe_setup_fc - Set up flow control
  *  @hw: pointer to hardware structure
  *
- *  Sets up flow control.
+ *  Called at init time to set up flow control.
  **/
-s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 {
 	s32 ret_val = 0;
-	ixgbe_link_speed speed;
-	bool link_up;
+	u32 reg;
 
 #ifdef CONFIG_DCB
 	if (hw->fc.requested_mode == ixgbe_fc_pfc) {
@@ -1866,7 +1847,7 @@
 
 	/*
 	 * Validate the requested mode.  Strict IEEE mode does not allow
-	 * ixgbe_fc_rx_pause because it will cause testing anomalies.
+	 * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
 	 */
 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
 		hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict "
@@ -1883,21 +1864,77 @@
 		hw->fc.requested_mode = ixgbe_fc_full;
 
 	/*
-	 * Save off the requested flow control mode for use later.  Depending
-	 * on the link partner's capabilities, we may or may not use this mode.
+	 * Set up the 1G flow control advertisement registers so the HW will be
+	 * able to do fc autoneg once the cable is plugged in.  If we end up
+	 * using 10g instead, this is harmless.
 	 */
-	hw->fc.current_mode = hw->fc.requested_mode;
-
-	/* Decide whether to use autoneg or not. */
-	hw->mac.ops.check_link(hw, &speed, &link_up, false);
-	if (!hw->fc.disable_fc_autoneg && hw->phy.multispeed_fiber &&
-	    (speed == IXGBE_LINK_SPEED_1GB_FULL))
-		ret_val = ixgbe_fc_autoneg(hw);
+	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
 
-	if (ret_val)
+	/*
+	 * The possible values of fc.requested_mode are:
+	 * 0: Flow control is completely disabled
+	 * 1: Rx flow control is enabled (we can receive pause frames,
+	 *    but not send pause frames).
+	 * 2: Tx flow control is enabled (we can send pause frames but
+	 *    we do not support receiving pause frames).
+	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
+#ifdef CONFIG_DCB
+	 * 4: Priority Flow Control is enabled.
+#endif
+	 * other: Invalid.
+	 */
+	switch (hw->fc.requested_mode) {
+	case ixgbe_fc_none:
+		/* Flow control completely disabled by software override. */
+		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		break;
+	case ixgbe_fc_rx_pause:
+		/*
+		 * Rx Flow control is enabled and Tx Flow control is
+		 * disabled by software override. Since there really
+		 * isn't a way to advertise that we are capable of RX
+		 * Pause ONLY, we will advertise that we support both
+		 * symmetric and asymmetric Rx PAUSE.  Later, we will
+		 * disable the adapter's ability to send PAUSE frames.
+		 */
+		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		break;
+	case ixgbe_fc_tx_pause:
+		/*
+		 * Tx Flow control is enabled, and Rx Flow control is
+		 * disabled by software override.
+		 */
+		reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
+		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+		break;
+	case ixgbe_fc_full:
+		/* Flow control (both Rx and Tx) is enabled by SW override. */
+		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		break;
+#ifdef CONFIG_DCB
+	case ixgbe_fc_pfc:
 		goto out;
+		break;
+#endif /* CONFIG_DCB */
+	default:
+		hw_dbg(hw, "Flow control param set incorrectly\n");
+		ret_val = -IXGBE_ERR_CONFIG;
+		goto out;
+		break;
+	}
 
-	ret_val = ixgbe_fc_enable(hw, packetbuf_num);
+	IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+
+	/* Enable and restart autoneg to inform the link partner */
+	reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
+
+	/* Disable AN timeout */
+	if (hw->fc.strict_ieee)
+		reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+	hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
 
 out:
 	return ret_val;
@@ -2044,6 +2081,7 @@
 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
 	if (!link_up) {
+		autoc_reg |= IXGBE_AUTOC_AN_RESTART;
 		autoc_reg |= IXGBE_AUTOC_FLU;
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
 		msleep(10);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_common.h linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_common.h
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_common.h	2009-09-09 18:13:59.000000000 -0400
@@ -59,13 +59,13 @@
 s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
                                       u32 mc_addr_count,
                                       ixgbe_mc_addr_itr func);
-s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
-                                      u32 addr_count, ixgbe_mc_addr_itr func);
+s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
+				      struct list_head *uc_list);
 s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
 s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
-s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
-s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packtetbuf_num);
+s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packtetbuf_num);
 s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);
 
 s32 ixgbe_validate_mac_addr(u8 *mac_addr);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c	2009-09-09 18:13:59.000000000 -0400
@@ -294,6 +294,9 @@
 	u32 reg, rx_pba_size;
 	u8  i;
 
+	if (!dcb_config->pfc_mode_enable)
+		goto out;
+
 	/* Enable Transmit Priority Flow Control */
 	reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
 	reg &= ~IXGBE_RMCS_TFCE_802_3X;
@@ -341,6 +344,7 @@
 	/* Configure flow control refresh threshold value */
 	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
 
+out:
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c	2009-09-09 18:13:59.000000000 -0400
@@ -295,7 +295,7 @@
 	/* If PFC is disabled globally then fall back to LFC. */
 	if (!dcb_config->pfc_mode_enable) {
 		for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
-			hw->mac.ops.setup_fc(hw, i);
+			hw->mac.ops.fc_enable(hw, i);
 		goto out;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,15 +28,22 @@
 
 #include "ixgbe.h"
 #include <linux/dcbnl.h>
+#include "ixgbe_dcb_82598.h"
+#include "ixgbe_dcb_82599.h"
 
 /* Callbacks for DCB netlink in the kernel */
 #define BIT_DCB_MODE	0x01
 #define BIT_PFC		0x02
 #define BIT_PG_RX	0x04
 #define BIT_PG_TX	0x08
-#define BIT_BCN         0x10
+#define BIT_RESETLINK   0x40
 #define BIT_LINKSPEED   0x80
 
+/* Responses for the DCB_C_SET_ALL command */
+#define DCB_HW_CHG_RST  0  /* DCB configuration changed with reset */
+#define DCB_NO_HW_CHG   1  /* DCB configuration did not change */
+#define DCB_HW_CHG      2  /* DCB configuration changed, no reset */
+
 int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
                        struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max)
 {
@@ -99,8 +106,6 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n");
-
 	return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
 }
 
@@ -109,8 +114,6 @@
 	u8 err = 0;
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n");
-
 	if (state > 0) {
 		/* Turn on DCB */
 		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
@@ -124,36 +127,59 @@
 
 		if (netif_running(netdev))
 			netdev->netdev_ops->ndo_stop(netdev);
-		ixgbe_reset_interrupt_capability(adapter);
-		ixgbe_napi_del_all(adapter);
-		INIT_LIST_HEAD(&netdev->napi_list);
-		kfree(adapter->tx_ring);
-		kfree(adapter->rx_ring);
-		adapter->tx_ring = NULL;
-		adapter->rx_ring = NULL;
+		ixgbe_clear_interrupt_scheme(adapter);
 
-		adapter->hw.fc.requested_mode = ixgbe_fc_pfc;
+		if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+			adapter->last_lfc_mode = adapter->hw.fc.current_mode;
+			adapter->hw.fc.requested_mode = ixgbe_fc_none;
+		}
 		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+		if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+			adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+			adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+		}
 		adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+#ifdef IXGBE_FCOE
+		/* Turn on FCoE offload */
+		if ((adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) &&
+		    (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))) {
+			adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
+			adapter->ring_feature[RING_F_FCOE].indices =
+				IXGBE_FCRETA_SIZE;
+			netdev->features |= NETIF_F_FCOE_CRC;
+			netdev->features |= NETIF_F_FSO;
+			netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
+		}
+#endif /* IXGBE_FCOE */
 		ixgbe_init_interrupt_scheme(adapter);
 		if (netif_running(netdev))
 			netdev->netdev_ops->ndo_open(netdev);
 	} else {
 		/* Turn off DCB */
 		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			adapter->hw.fc.requested_mode = ixgbe_fc_default;
 			if (netif_running(netdev))
 				netdev->netdev_ops->ndo_stop(netdev);
-			ixgbe_reset_interrupt_capability(adapter);
-			ixgbe_napi_del_all(adapter);
-			INIT_LIST_HEAD(&netdev->napi_list);
-			kfree(adapter->tx_ring);
-			kfree(adapter->rx_ring);
-			adapter->tx_ring = NULL;
-			adapter->rx_ring = NULL;
+			ixgbe_clear_interrupt_scheme(adapter);
 
+			adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+			adapter->temp_dcb_cfg.pfc_mode_enable = false;
+			adapter->dcb_cfg.pfc_mode_enable = false;
 			adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
 			adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+			if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+				adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+
+#ifdef IXGBE_FCOE
+			/* Turn off FCoE offload */
+			if (adapter->flags & (IXGBE_FLAG_FCOE_CAPABLE |
+			     IXGBE_FLAG_FCOE_ENABLED)) {
+				adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+				adapter->ring_feature[RING_F_FCOE].indices = 0;
+				netdev->features &= ~NETIF_F_FCOE_CRC;
+				netdev->features &= ~NETIF_F_FSO;
+				netdev->fcoe_ddp_xid = 0;
+			}
+#endif /* IXGBE_FCOE */
 			ixgbe_init_interrupt_scheme(adapter);
 			if (netif_running(netdev))
 				netdev->netdev_ops->ndo_open(netdev);
@@ -167,10 +193,17 @@
 					 u8 *perm_addr)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	int i;
+	int i, j;
+
+	memset(perm_addr, 0xff, MAX_ADDR_LEN);
 
 	for (i = 0; i < netdev->addr_len; i++)
 		perm_addr[i] = adapter->hw.mac.perm_addr[i];
+
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		for (j = 0; j < netdev->addr_len; j++, i++)
+			perm_addr[i] = adapter->hw.mac.san_addr[j];
+	}
 }
 
 static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
@@ -197,8 +230,10 @@
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
 	     adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
-	     adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
+	     adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) {
 		adapter->dcb_set_bitmap |= BIT_PG_TX;
+		adapter->dcb_set_bitmap |= BIT_RESETLINK;
+	}
 }
 
 static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
@@ -209,8 +244,10 @@
 	adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
 
 	if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
-	    adapter->dcb_cfg.bw_percentage[0][bwg_id])
+	    adapter->dcb_cfg.bw_percentage[0][bwg_id]) {
 		adapter->dcb_set_bitmap |= BIT_PG_RX;
+		adapter->dcb_set_bitmap |= BIT_RESETLINK;
+	}
 }
 
 static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
@@ -237,8 +274,10 @@
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
 	     adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
-	     adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
+	     adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) {
 		adapter->dcb_set_bitmap |= BIT_PG_RX;
+		adapter->dcb_set_bitmap |= BIT_RESETLINK;
+	}
 }
 
 static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
@@ -249,8 +288,10 @@
 	adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
 
 	if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
-	    adapter->dcb_cfg.bw_percentage[1][bwg_id])
+	    adapter->dcb_cfg.bw_percentage[1][bwg_id]) {
 		adapter->dcb_set_bitmap |= BIT_PG_RX;
+		adapter->dcb_set_bitmap |= BIT_RESETLINK;
+	}
 }
 
 static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
@@ -319,28 +360,60 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	int ret;
 
-	adapter->dcb_set_bitmap &= ~BIT_BCN;	/* no set for BCN */
 	if (!adapter->dcb_set_bitmap)
-		return 1;
+		return DCB_NO_HW_CHG;
 
-	while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
-		msleep(1);
+	/*
+	 * Only take down the adapter if the configuration change
+	 * requires a reset.
+	 */
+	if (adapter->dcb_set_bitmap & BIT_RESETLINK) {
+		while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
+			msleep(1);
 
-	if (netif_running(netdev))
-		ixgbe_down(adapter);
+		if (netif_running(netdev))
+			ixgbe_down(adapter);
+	}
 
 	ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
 				 adapter->ring_feature[RING_F_DCB].indices);
 	if (ret) {
-		clear_bit(__IXGBE_RESETTING, &adapter->state);
-		return ret;
+		if (adapter->dcb_set_bitmap & BIT_RESETLINK)
+			clear_bit(__IXGBE_RESETTING, &adapter->state);
+		return DCB_NO_HW_CHG;
 	}
 
-	if (netif_running(netdev))
-		ixgbe_up(adapter);
+	if (adapter->dcb_cfg.pfc_mode_enable) {
+		if ((adapter->hw.mac.type != ixgbe_mac_82598EB) &&
+			(adapter->hw.fc.current_mode != ixgbe_fc_pfc))
+			adapter->last_lfc_mode = adapter->hw.fc.current_mode;
+		adapter->hw.fc.requested_mode = ixgbe_fc_pfc;
+	} else {
+		if (adapter->hw.mac.type != ixgbe_mac_82598EB)
+			adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+		else
+			adapter->hw.fc.requested_mode = ixgbe_fc_none;
+	}
+
+	if (adapter->dcb_set_bitmap & BIT_RESETLINK) {
+		if (netif_running(netdev))
+			ixgbe_up(adapter);
+		ret = DCB_HW_CHG_RST;
+	} else if (adapter->dcb_set_bitmap & BIT_PFC) {
+		if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+			ixgbe_dcb_config_pfc_82598(&adapter->hw,
+			                           &adapter->dcb_cfg);
+		else if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+			ixgbe_dcb_config_pfc_82599(&adapter->hw,
+			                           &adapter->dcb_cfg);
+		ret = DCB_HW_CHG;
+	}
+	if (adapter->dcb_cfg.pfc_mode_enable)
+		adapter->hw.fc.current_mode = ixgbe_fc_pfc;
 
+	if (adapter->dcb_set_bitmap & BIT_RESETLINK)
+		clear_bit(__IXGBE_RESETTING, &adapter->state);
 	adapter->dcb_set_bitmap = 0x00;
-	clear_bit(__IXGBE_RESETTING, &adapter->state);
 	return ret;
 }
 
@@ -416,11 +489,17 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
+	return adapter->dcb_cfg.pfc_mode_enable;
 }
 
 static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
 {
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+	adapter->temp_dcb_cfg.pfc_mode_enable = state;
+	if (adapter->temp_dcb_cfg.pfc_mode_enable !=
+		adapter->dcb_cfg.pfc_mode_enable)
+		adapter->dcb_set_bitmap |= BIT_PFC;
 	return;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_ethtool.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -67,6 +67,9 @@
 	{"rx_over_errors", IXGBE_STAT(net_stats.rx_over_errors)},
 	{"rx_crc_errors", IXGBE_STAT(net_stats.rx_crc_errors)},
 	{"rx_frame_errors", IXGBE_STAT(net_stats.rx_frame_errors)},
+	{"hw_rsc_count", IXGBE_STAT(rsc_count)},
+	{"fdir_match", IXGBE_STAT(stats.fdirmatch)},
+	{"fdir_miss", IXGBE_STAT(stats.fdirmiss)},
 	{"rx_fifo_errors", IXGBE_STAT(net_stats.rx_fifo_errors)},
 	{"rx_missed_errors", IXGBE_STAT(net_stats.rx_missed_errors)},
 	{"tx_aborted_errors", IXGBE_STAT(net_stats.tx_aborted_errors)},
@@ -90,6 +93,14 @@
 	{"alloc_rx_page_failed", IXGBE_STAT(alloc_rx_page_failed)},
 	{"alloc_rx_buff_failed", IXGBE_STAT(alloc_rx_buff_failed)},
 	{"rx_no_dma_resources", IXGBE_STAT(hw_rx_no_dma_resources)},
+#ifdef IXGBE_FCOE
+	{"fcoe_bad_fccrc", IXGBE_STAT(stats.fccrc)},
+	{"rx_fcoe_dropped", IXGBE_STAT(stats.fcoerpdc)},
+	{"rx_fcoe_packets", IXGBE_STAT(stats.fcoeprc)},
+	{"rx_fcoe_dwords", IXGBE_STAT(stats.fcoedwrc)},
+	{"tx_fcoe_packets", IXGBE_STAT(stats.fcoeptc)},
+	{"tx_fcoe_dwords", IXGBE_STAT(stats.fcoedwtc)},
+#endif /* IXGBE_FCOE */
 };
 
 #define IXGBE_QUEUE_STATS_LEN \
@@ -109,6 +120,13 @@
                          IXGBE_PB_STATS_LEN + \
                          IXGBE_QUEUE_STATS_LEN)
 
+static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = {
+	"Register test  (offline)", "Eeprom test    (offline)",
+	"Interrupt test (offline)", "Loopback test  (offline)",
+	"Link test   (on/offline)"
+};
+#define IXGBE_TEST_LEN sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN
+
 static int ixgbe_get_settings(struct net_device *netdev,
                               struct ethtool_cmd *ecmd)
 {
@@ -120,11 +138,12 @@
 	ecmd->supported = SUPPORTED_10000baseT_Full;
 	ecmd->autoneg = AUTONEG_ENABLE;
 	ecmd->transceiver = XCVR_EXTERNAL;
-	if (hw->phy.media_type == ixgbe_media_type_copper) {
+	if ((hw->phy.media_type == ixgbe_media_type_copper) ||
+	    (hw->phy.multispeed_fiber)) {
 		ecmd->supported |= (SUPPORTED_1000baseT_Full |
-		                    SUPPORTED_TP | SUPPORTED_Autoneg);
+		                    SUPPORTED_Autoneg);
 
-		ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg);
+		ecmd->advertising = ADVERTISED_Autoneg;
 		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
 			ecmd->advertising |= ADVERTISED_10000baseT_Full;
 		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
@@ -139,7 +158,15 @@
 			ecmd->advertising |= (ADVERTISED_10000baseT_Full |
 					      ADVERTISED_1000baseT_Full);
 
-		ecmd->port = PORT_TP;
+		if (hw->phy.media_type == ixgbe_media_type_copper) {
+			ecmd->supported |= SUPPORTED_TP;
+			ecmd->advertising |= ADVERTISED_TP;
+			ecmd->port = PORT_TP;
+		} else {
+			ecmd->supported |= SUPPORTED_FIBRE;
+			ecmd->advertising |= ADVERTISED_FIBRE;
+			ecmd->port = PORT_FIBRE;
+		}
 	} else if (hw->phy.media_type == ixgbe_media_type_backplane) {
 		/* Set as FIBRE until SERDES defined in kernel */
 		switch (hw->device_id) {
@@ -187,16 +214,10 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 advertised, old;
-	s32 err;
+	s32 err = 0;
 
-	switch (hw->phy.media_type) {
-	case ixgbe_media_type_fiber:
-		if ((ecmd->autoneg == AUTONEG_ENABLE) ||
-		    (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL))
-			return -EINVAL;
-		/* in this case we currently only support 10Gb/FULL */
-		break;
-	case ixgbe_media_type_copper:
+	if ((hw->phy.media_type == ixgbe_media_type_copper) ||
+	    (hw->phy.multispeed_fiber)) {
 		/* 10000/copper and 1000/copper must autoneg
 		 * this function does not support any duplex forcing, but can
 		 * limit the advertising of the adapter to only 10000 or 1000 */
@@ -212,20 +233,24 @@
 			advertised |= IXGBE_LINK_SPEED_1GB_FULL;
 
 		if (old == advertised)
-			break;
+			return err;
 		/* this sets the link speed and restarts auto-neg */
+		hw->mac.autotry_restart = true;
 		err = hw->mac.ops.setup_link_speed(hw, advertised, true, true);
 		if (err) {
 			DPRINTK(PROBE, INFO,
 			        "setup link failed with code %d\n", err);
 			hw->mac.ops.setup_link_speed(hw, old, true, true);
 		}
-		break;
-	default:
-		break;
+	} else {
+		/* in this case we currently only support 10Gb/FULL */
+		if ((ecmd->autoneg == AUTONEG_ENABLE) ||
+		    (ecmd->advertising != ADVERTISED_10000baseT_Full) ||
+		    (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL))
+			return -EINVAL;
 	}
 
-	return 0;
+	return err;
 }
 
 static void ixgbe_get_pauseparam(struct net_device *netdev,
@@ -245,6 +270,13 @@
 	else
 		pause->autoneg = 1;
 
+#ifdef CONFIG_DCB
+	if (hw->fc.current_mode == ixgbe_fc_pfc) {
+		pause->rx_pause = 0;
+		pause->tx_pause = 0;
+	}
+
+#endif
 	if (hw->fc.current_mode == ixgbe_fc_rx_pause) {
 		pause->rx_pause = 1;
 	} else if (hw->fc.current_mode == ixgbe_fc_tx_pause) {
@@ -260,24 +292,46 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_fc_info fc;
+
+#ifdef CONFIG_DCB
+	if (adapter->dcb_cfg.pfc_mode_enable ||
+		((hw->mac.type == ixgbe_mac_82598EB) &&
+		(adapter->flags & IXGBE_FLAG_DCB_ENABLED)))
+		return -EINVAL;
+
+#endif
+
+	fc = hw->fc;
 
 	if (pause->autoneg != AUTONEG_ENABLE)
-		hw->fc.disable_fc_autoneg = true;
+		fc.disable_fc_autoneg = true;
 	else
-		hw->fc.disable_fc_autoneg = false;
+		fc.disable_fc_autoneg = false;
 
 	if (pause->rx_pause && pause->tx_pause)
-		hw->fc.requested_mode = ixgbe_fc_full;
+		fc.requested_mode = ixgbe_fc_full;
 	else if (pause->rx_pause && !pause->tx_pause)
-		hw->fc.requested_mode = ixgbe_fc_rx_pause;
+		fc.requested_mode = ixgbe_fc_rx_pause;
 	else if (!pause->rx_pause && pause->tx_pause)
-		hw->fc.requested_mode = ixgbe_fc_tx_pause;
+		fc.requested_mode = ixgbe_fc_tx_pause;
 	else if (!pause->rx_pause && !pause->tx_pause)
-		hw->fc.requested_mode = ixgbe_fc_none;
+		fc.requested_mode = ixgbe_fc_none;
 	else
 		return -EINVAL;
 
-	hw->mac.ops.setup_fc(hw, 0);
+#ifdef CONFIG_DCB
+	adapter->last_lfc_mode = fc.requested_mode;
+#endif
+
+	/* if the thing changed then we'll update and use new autoneg */
+	if (memcmp(&fc, &hw->fc, sizeof(struct ixgbe_fc_info))) {
+		hw->fc = fc;
+		if (netif_running(netdev))
+			ixgbe_reinit_locked(adapter);
+		else
+			ixgbe_reset(adapter);
+	}
 
 	return 0;
 }
@@ -311,10 +365,17 @@
 
 static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
 {
-	if (data)
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+	if (data) {
 		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-	else
+		if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+			netdev->features |= NETIF_F_SCTP_CSUM;
+	} else {
 		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+		if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+			netdev->features &= ~NETIF_F_SCTP_CSUM;
+	}
 
 	return 0;
 }
@@ -710,6 +771,7 @@
 	strncpy(drvinfo->fw_version, firmware_version, 32);
 	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
 	drvinfo->n_stats = IXGBE_STATS_LEN;
+	drvinfo->testinfo_len = IXGBE_TEST_LEN;
 	drvinfo->regdump_len = ixgbe_get_regs_len(netdev);
 }
 
@@ -781,7 +843,6 @@
 				}
 				goto err_setup;
 			}
-			temp_tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
 		}
 		need_update = true;
 	}
@@ -811,7 +872,6 @@
 				}
 				goto err_setup;
 			}
-			temp_rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
 		}
 		need_update = true;
 	}
@@ -851,6 +911,8 @@
 static int ixgbe_get_sset_count(struct net_device *netdev, int sset)
 {
 	switch (sset) {
+	case ETH_SS_TEST:
+		return IXGBE_TEST_LEN;
 	case ETH_SS_STATS:
 		return IXGBE_STATS_LEN;
 	default:
@@ -905,6 +967,10 @@
 	int i;
 
 	switch (stringset) {
+	case ETH_SS_TEST:
+		memcpy(data, *ixgbe_gstrings_test,
+		       IXGBE_TEST_LEN * ETH_GSTRING_LEN);
+		break;
 	case ETH_SS_STATS:
 		for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
 			memcpy(p, ixgbe_gstrings_stats[i].stat_string,
@@ -942,6 +1008,815 @@
 	}
 }
 
+static int ixgbe_link_test(struct ixgbe_adapter *adapter, u64 *data)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	bool link_up;
+	u32 link_speed = 0;
+	*data = 0;
+
+	hw->mac.ops.check_link(hw, &link_speed, &link_up, true);
+	if (link_up)
+		return *data;
+	else
+		*data = 1;
+	return *data;
+}
+
+/* ethtool register test data */
+struct ixgbe_reg_test {
+	u16 reg;
+	u8  array_len;
+	u8  test_type;
+	u32 mask;
+	u32 write;
+};
+
+/* In the hardware, registers are laid out either singly, in arrays
+ * spaced 0x40 bytes apart, or in contiguous tables.  We assume
+ * most tests take place on arrays or single registers (handled
+ * as a single-element array) and special-case the tables.
+ * Table tests are always pattern tests.
+ *
+ * We also make provision for some required setup steps by specifying
+ * registers to be written without any read-back testing.
+ */
+
+#define PATTERN_TEST	1
+#define SET_READ_TEST	2
+#define WRITE_NO_TEST	3
+#define TABLE32_TEST	4
+#define TABLE64_TEST_LO	5
+#define TABLE64_TEST_HI	6
+
+/* default 82599 register test */
+static struct ixgbe_reg_test reg_test_82599[] = {
+	{ IXGBE_FCRTL_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
+	{ IXGBE_FCRTH_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
+	{ IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 },
+	{ IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
+	{ IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+	{ IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE },
+	{ IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+	{ IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 },
+	{ IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
+	{ IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+	{ IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFF80 },
+	{ IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000001, 0x00000001 },
+	{ IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x8001FFFF, 0x800CFFFF },
+	{ IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ 0, 0, 0, 0 }
+};
+
+/* default 82598 register test */
+static struct ixgbe_reg_test reg_test_82598[] = {
+	{ IXGBE_FCRTL(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
+	{ IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
+	{ IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 },
+	{ IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+	{ IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+	/* Enable all four RX queues before testing. */
+	{ IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE },
+	/* RDH is read-only for 82598, only test RDT. */
+	{ IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+	{ IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 },
+	{ IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 },
+	{ IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_TIPG, 1, PATTERN_TEST, 0x000000FF, 0x000000FF },
+	{ IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+	{ IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+	{ IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000003, 0x00000003 },
+	{ IXGBE_DTXCTL, 1, SET_READ_TEST, 0x00000005, 0x00000005 },
+	{ IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x800CFFFF, 0x800CFFFF },
+	{ IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ 0, 0, 0, 0 }
+};
+
+#define REG_PATTERN_TEST(R, M, W)                                             \
+{                                                                             \
+	u32 pat, val, before;                                                 \
+	const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
+	for (pat = 0; pat < ARRAY_SIZE(_test); pat++) {                       \
+		before = readl(adapter->hw.hw_addr + R);                      \
+		writel((_test[pat] & W), (adapter->hw.hw_addr + R));          \
+		val = readl(adapter->hw.hw_addr + R);                         \
+		if (val != (_test[pat] & W & M)) {                            \
+			DPRINTK(DRV, ERR, "pattern test reg %04X failed: got "\
+					  "0x%08X expected 0x%08X\n",         \
+				R, val, (_test[pat] & W & M));                \
+			*data = R;                                            \
+			writel(before, adapter->hw.hw_addr + R);              \
+			return 1;                                             \
+		}                                                             \
+		writel(before, adapter->hw.hw_addr + R);                      \
+	}                                                                     \
+}
+
+#define REG_SET_AND_CHECK(R, M, W)                                            \
+{                                                                             \
+	u32 val, before;                                                      \
+	before = readl(adapter->hw.hw_addr + R);                              \
+	writel((W & M), (adapter->hw.hw_addr + R));                           \
+	val = readl(adapter->hw.hw_addr + R);                                 \
+	if ((W & M) != (val & M)) {                                           \
+		DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
+				 "expected 0x%08X\n", R, (val & M), (W & M)); \
+		*data = R;                                                    \
+		writel(before, (adapter->hw.hw_addr + R));                    \
+		return 1;                                                     \
+	}                                                                     \
+	writel(before, (adapter->hw.hw_addr + R));                            \
+}
+
+static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
+{
+	struct ixgbe_reg_test *test;
+	u32 value, before, after;
+	u32 i, toggle;
+
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		toggle = 0x7FFFF30F;
+		test = reg_test_82599;
+	} else {
+		toggle = 0x7FFFF3FF;
+		test = reg_test_82598;
+	}
+
+	/*
+	 * Because the status register is such a special case,
+	 * we handle it separately from the rest of the register
+	 * tests.  Some bits are read-only, some toggle, and some
+	 * are writeable on newer MACs.
+	 */
+	before = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS);
+	value = (IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, toggle);
+	after = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle;
+	if (value != after) {
+		DPRINTK(DRV, ERR, "failed STATUS register test got: "
+		        "0x%08X expected: 0x%08X\n", after, value);
+		*data = 1;
+		return 1;
+	}
+	/* restore previous status */
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, before);
+
+	/*
+	 * Perform the remainder of the register test, looping through
+	 * the test table until we either fail or reach the null entry.
+	 */
+	while (test->reg) {
+		for (i = 0; i < test->array_len; i++) {
+			switch (test->test_type) {
+			case PATTERN_TEST:
+				REG_PATTERN_TEST(test->reg + (i * 0x40),
+						test->mask,
+						test->write);
+				break;
+			case SET_READ_TEST:
+				REG_SET_AND_CHECK(test->reg + (i * 0x40),
+						test->mask,
+						test->write);
+				break;
+			case WRITE_NO_TEST:
+				writel(test->write,
+				       (adapter->hw.hw_addr + test->reg)
+				       + (i * 0x40));
+				break;
+			case TABLE32_TEST:
+				REG_PATTERN_TEST(test->reg + (i * 4),
+						test->mask,
+						test->write);
+				break;
+			case TABLE64_TEST_LO:
+				REG_PATTERN_TEST(test->reg + (i * 8),
+						test->mask,
+						test->write);
+				break;
+			case TABLE64_TEST_HI:
+				REG_PATTERN_TEST((test->reg + 4) + (i * 8),
+						test->mask,
+						test->write);
+				break;
+			}
+		}
+		test++;
+	}
+
+	*data = 0;
+	return 0;
+}
+
+static int ixgbe_eeprom_test(struct ixgbe_adapter *adapter, u64 *data)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	if (hw->eeprom.ops.validate_checksum(hw, NULL))
+		*data = 1;
+	else
+		*data = 0;
+	return *data;
+}
+
+static irqreturn_t ixgbe_test_intr(int irq, void *data)
+{
+	struct net_device *netdev = (struct net_device *) data;
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+	adapter->test_icr |= IXGBE_READ_REG(&adapter->hw, IXGBE_EICR);
+
+	return IRQ_HANDLED;
+}
+
+static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data)
+{
+	struct net_device *netdev = adapter->netdev;
+	u32 mask, i = 0, shared_int = true;
+	u32 irq = adapter->pdev->irq;
+
+	*data = 0;
+
+	/* Hook up test interrupt handler just for this test */
+	if (adapter->msix_entries) {
+		/* NOTE: we don't test MSI-X interrupts here, yet */
+		return 0;
+	} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+		shared_int = false;
+		if (request_irq(irq, &ixgbe_test_intr, 0, netdev->name,
+				netdev)) {
+			*data = 1;
+			return -1;
+		}
+	} else if (!request_irq(irq, &ixgbe_test_intr, IRQF_PROBE_SHARED,
+	                        netdev->name, netdev)) {
+		shared_int = false;
+	} else if (request_irq(irq, &ixgbe_test_intr, IRQF_SHARED,
+	                       netdev->name, netdev)) {
+		*data = 1;
+		return -1;
+	}
+	DPRINTK(HW, INFO, "testing %s interrupt\n",
+		(shared_int ? "shared" : "unshared"));
+
+	/* Disable all the interrupts */
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF);
+	msleep(10);
+
+	/* Test each interrupt */
+	for (; i < 10; i++) {
+		/* Interrupt to test */
+		mask = 1 << i;
+
+		if (!shared_int) {
+			/*
+			 * Disable the interrupts to be reported in
+			 * the cause register and then force the same
+			 * interrupt and see if one gets posted.  If
+			 * an interrupt was posted to the bus, the
+			 * test failed.
+			 */
+			adapter->test_icr = 0;
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC,
+			                ~mask & 0x00007FFF);
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
+			                ~mask & 0x00007FFF);
+			msleep(10);
+
+			if (adapter->test_icr & mask) {
+				*data = 3;
+				break;
+			}
+		}
+
+		/*
+		 * Enable the interrupt to be reported in the cause
+		 * register and then force the same interrupt and see
+		 * if one gets posted.  If an interrupt was not posted
+		 * to the bus, the test failed.
+		 */
+		adapter->test_icr = 0;
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
+		msleep(10);
+
+		if (!(adapter->test_icr &mask)) {
+			*data = 4;
+			break;
+		}
+
+		if (!shared_int) {
+			/*
+			 * Disable the other interrupts to be reported in
+			 * the cause register and then force the other
+			 * interrupts and see if any get posted.  If
+			 * an interrupt was posted to the bus, the
+			 * test failed.
+			 */
+			adapter->test_icr = 0;
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC,
+			                ~mask & 0x00007FFF);
+			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
+			                ~mask & 0x00007FFF);
+			msleep(10);
+
+			if (adapter->test_icr) {
+				*data = 5;
+				break;
+			}
+		}
+	}
+
+	/* Disable all the interrupts */
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF);
+	msleep(10);
+
+	/* Unhook test interrupt handler */
+	free_irq(irq, netdev);
+
+	return *data;
+}
+
+static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
+	struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct pci_dev *pdev = adapter->pdev;
+	u32 reg_ctl;
+	int i;
+
+	/* shut down the DMA engines now so they can be reinitialized later */
+
+	/* first Rx */
+	reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+	reg_ctl &= ~IXGBE_RXCTRL_RXEN;
+	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_ctl);
+	reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(0));
+	reg_ctl &= ~IXGBE_RXDCTL_ENABLE;
+	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(0), reg_ctl);
+
+	/* now Tx */
+	reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(0));
+	reg_ctl &= ~IXGBE_TXDCTL_ENABLE;
+	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(0), reg_ctl);
+	if (hw->mac.type == ixgbe_mac_82599EB) {
+		reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
+		reg_ctl &= ~IXGBE_DMATXCTL_TE;
+		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl);
+	}
+
+	ixgbe_reset(adapter);
+
+	if (tx_ring->desc && tx_ring->tx_buffer_info) {
+		for (i = 0; i < tx_ring->count; i++) {
+			struct ixgbe_tx_buffer *buf =
+					&(tx_ring->tx_buffer_info[i]);
+			if (buf->dma)
+				pci_unmap_single(pdev, buf->dma, buf->length,
+				                 PCI_DMA_TODEVICE);
+			if (buf->skb)
+				dev_kfree_skb(buf->skb);
+		}
+	}
+
+	if (rx_ring->desc && rx_ring->rx_buffer_info) {
+		for (i = 0; i < rx_ring->count; i++) {
+			struct ixgbe_rx_buffer *buf =
+					&(rx_ring->rx_buffer_info[i]);
+			if (buf->dma)
+				pci_unmap_single(pdev, buf->dma,
+						 IXGBE_RXBUFFER_2048,
+						 PCI_DMA_FROMDEVICE);
+			if (buf->skb)
+				dev_kfree_skb(buf->skb);
+		}
+	}
+
+	if (tx_ring->desc) {
+		pci_free_consistent(pdev, tx_ring->size, tx_ring->desc,
+		                    tx_ring->dma);
+		tx_ring->desc = NULL;
+	}
+	if (rx_ring->desc) {
+		pci_free_consistent(pdev, rx_ring->size, rx_ring->desc,
+		                    rx_ring->dma);
+		rx_ring->desc = NULL;
+	}
+
+	kfree(tx_ring->tx_buffer_info);
+	tx_ring->tx_buffer_info = NULL;
+	kfree(rx_ring->rx_buffer_info);
+	rx_ring->rx_buffer_info = NULL;
+
+	return;
+}
+
+static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
+	struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	u32 rctl, reg_data;
+	int i, ret_val;
+
+	/* Setup Tx descriptor ring and Tx buffers */
+
+	if (!tx_ring->count)
+		tx_ring->count = IXGBE_DEFAULT_TXD;
+
+	tx_ring->tx_buffer_info = kcalloc(tx_ring->count,
+	                                  sizeof(struct ixgbe_tx_buffer),
+	                                  GFP_KERNEL);
+	if (!(tx_ring->tx_buffer_info)) {
+		ret_val = 1;
+		goto err_nomem;
+	}
+
+	tx_ring->size = tx_ring->count * sizeof(struct ixgbe_legacy_tx_desc);
+	tx_ring->size = ALIGN(tx_ring->size, 4096);
+	if (!(tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
+						   &tx_ring->dma))) {
+		ret_val = 2;
+		goto err_nomem;
+	}
+	tx_ring->next_to_use = tx_ring->next_to_clean = 0;
+
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAL(0),
+			((u64) tx_ring->dma & 0x00000000FFFFFFFF));
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAH(0),
+			((u64) tx_ring->dma >> 32));
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDLEN(0),
+			tx_ring->count * sizeof(struct ixgbe_legacy_tx_desc));
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDH(0), 0);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), 0);
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+	reg_data |= IXGBE_HLREG0_TXPADEN;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL);
+		reg_data |= IXGBE_DMATXCTL_TE;
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data);
+	}
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(0));
+	reg_data |= IXGBE_TXDCTL_ENABLE;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(0), reg_data);
+
+	for (i = 0; i < tx_ring->count; i++) {
+		struct ixgbe_legacy_tx_desc *desc = IXGBE_TX_DESC(*tx_ring, i);
+		struct sk_buff *skb;
+		unsigned int size = 1024;
+
+		skb = alloc_skb(size, GFP_KERNEL);
+		if (!skb) {
+			ret_val = 3;
+			goto err_nomem;
+		}
+		skb_put(skb, size);
+		tx_ring->tx_buffer_info[i].skb = skb;
+		tx_ring->tx_buffer_info[i].length = skb->len;
+		tx_ring->tx_buffer_info[i].dma =
+			pci_map_single(pdev, skb->data, skb->len,
+					PCI_DMA_TODEVICE);
+		desc->buffer_addr = cpu_to_le64(tx_ring->tx_buffer_info[i].dma);
+		desc->lower.data = cpu_to_le32(skb->len);
+		desc->lower.data |= cpu_to_le32(IXGBE_TXD_CMD_EOP |
+		                                IXGBE_TXD_CMD_IFCS |
+		                                IXGBE_TXD_CMD_RS);
+		desc->upper.data = 0;
+	}
+
+	/* Setup Rx Descriptor ring and Rx buffers */
+
+	if (!rx_ring->count)
+		rx_ring->count = IXGBE_DEFAULT_RXD;
+
+	rx_ring->rx_buffer_info = kcalloc(rx_ring->count,
+	                                  sizeof(struct ixgbe_rx_buffer),
+	                                  GFP_KERNEL);
+	if (!(rx_ring->rx_buffer_info)) {
+		ret_val = 4;
+		goto err_nomem;
+	}
+
+	rx_ring->size = rx_ring->count * sizeof(struct ixgbe_legacy_rx_desc);
+	rx_ring->size = ALIGN(rx_ring->size, 4096);
+	if (!(rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size,
+						   &rx_ring->dma))) {
+		ret_val = 5;
+		goto err_nomem;
+	}
+	rx_ring->next_to_use = rx_ring->next_to_clean = 0;
+
+	rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl & ~IXGBE_RXCTRL_RXEN);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAL(0),
+			((u64)rx_ring->dma & 0xFFFFFFFF));
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAH(0),
+			((u64) rx_ring->dma >> 32));
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDLEN(0), rx_ring->size);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDH(0), 0);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), 0);
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+	reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+	reg_data &= ~IXGBE_HLREG0_LPBK;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RDRXCTL);
+#define IXGBE_RDRXCTL_RDMTS_MASK    0x00000003 /* Receive Descriptor Minimum
+                                                  Threshold Size mask */
+	reg_data &= ~IXGBE_RDRXCTL_RDMTS_MASK;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDRXCTL, reg_data);
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MCSTCTRL);
+#define IXGBE_MCSTCTRL_MO_MASK      0x00000003 /* Multicast Offset mask */
+	reg_data &= ~IXGBE_MCSTCTRL_MO_MASK;
+	reg_data |= adapter->hw.mac.mc_filter_type;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_MCSTCTRL, reg_data);
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(0));
+	reg_data |= IXGBE_RXDCTL_ENABLE;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data);
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		int j = adapter->rx_ring[0].reg_idx;
+		u32 k;
+		for (k = 0; k < 10; k++) {
+			if (IXGBE_READ_REG(&adapter->hw,
+			                   IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE)
+				break;
+			else
+				msleep(1);
+		}
+	}
+
+	rctl |= IXGBE_RXCTRL_RXEN | IXGBE_RXCTRL_DMBYPS;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl);
+
+	for (i = 0; i < rx_ring->count; i++) {
+		struct ixgbe_legacy_rx_desc *rx_desc =
+					IXGBE_RX_DESC(*rx_ring, i);
+		struct sk_buff *skb;
+
+		skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
+		if (!skb) {
+			ret_val = 6;
+			goto err_nomem;
+		}
+		skb_reserve(skb, NET_IP_ALIGN);
+		rx_ring->rx_buffer_info[i].skb = skb;
+		rx_ring->rx_buffer_info[i].dma =
+			pci_map_single(pdev, skb->data, IXGBE_RXBUFFER_2048,
+			               PCI_DMA_FROMDEVICE);
+		rx_desc->buffer_addr =
+				cpu_to_le64(rx_ring->rx_buffer_info[i].dma);
+		memset(skb->data, 0x00, skb->len);
+	}
+
+	return 0;
+
+err_nomem:
+	ixgbe_free_desc_rings(adapter);
+	return ret_val;
+}
+
+static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 reg_data;
+
+	/* right now we only support MAC loopback in the driver */
+
+	/* Setup MAC loopback */
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+	reg_data |= IXGBE_HLREG0_LPBK;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC);
+	reg_data &= ~IXGBE_AUTOC_LMS_MASK;
+	reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data);
+
+	/* Disable Atlas Tx lanes; re-enabled in reset path */
+	if (hw->mac.type == ixgbe_mac_82598EB) {
+		u8 atlas;
+
+		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &atlas);
+		atlas |= IXGBE_ATLAS_PDN_TX_REG_EN;
+		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, atlas);
+
+		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &atlas);
+		atlas |= IXGBE_ATLAS_PDN_TX_10G_QL_ALL;
+		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, atlas);
+
+		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &atlas);
+		atlas |= IXGBE_ATLAS_PDN_TX_1G_QL_ALL;
+		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, atlas);
+
+		hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &atlas);
+		atlas |= IXGBE_ATLAS_PDN_TX_AN_QL_ALL;
+		hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, atlas);
+	}
+
+	return 0;
+}
+
+static void ixgbe_loopback_cleanup(struct ixgbe_adapter *adapter)
+{
+	u32 reg_data;
+
+	reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+	reg_data &= ~IXGBE_HLREG0_LPBK;
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+}
+
+static void ixgbe_create_lbtest_frame(struct sk_buff *skb,
+                                      unsigned int frame_size)
+{
+	memset(skb->data, 0xFF, frame_size);
+	frame_size &= ~1;
+	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
+	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
+	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
+}
+
+static int ixgbe_check_lbtest_frame(struct sk_buff *skb,
+                                    unsigned int frame_size)
+{
+	frame_size &= ~1;
+	if (*(skb->data + 3) == 0xFF) {
+		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+		    (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
+			return 0;
+		}
+	}
+	return 13;
+}
+
+static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
+	struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	int i, j, k, l, lc, good_cnt, ret_val = 0;
+	unsigned long time;
+
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), rx_ring->count - 1);
+
+	/*
+	 * Calculate the loop count based on the largest descriptor ring
+	 * The idea is to wrap the largest ring a number of times using 64
+	 * send/receive pairs during each loop
+	 */
+
+	if (rx_ring->count <= tx_ring->count)
+		lc = ((tx_ring->count / 64) * 2) + 1;
+	else
+		lc = ((rx_ring->count / 64) * 2) + 1;
+
+	k = l = 0;
+	for (j = 0; j <= lc; j++) {
+		for (i = 0; i < 64; i++) {
+			ixgbe_create_lbtest_frame(
+					tx_ring->tx_buffer_info[k].skb,
+					1024);
+			pci_dma_sync_single_for_device(pdev,
+				tx_ring->tx_buffer_info[k].dma,
+				tx_ring->tx_buffer_info[k].length,
+				PCI_DMA_TODEVICE);
+			if (unlikely(++k == tx_ring->count))
+				k = 0;
+		}
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), k);
+		msleep(200);
+		/* set the start time for the receive */
+		time = jiffies;
+		good_cnt = 0;
+		do {
+			/* receive the sent packets */
+			pci_dma_sync_single_for_cpu(pdev,
+					rx_ring->rx_buffer_info[l].dma,
+					IXGBE_RXBUFFER_2048,
+					PCI_DMA_FROMDEVICE);
+			ret_val = ixgbe_check_lbtest_frame(
+					rx_ring->rx_buffer_info[l].skb, 1024);
+			if (!ret_val)
+				good_cnt++;
+			if (++l == rx_ring->count)
+				l = 0;
+			/*
+			 * time + 20 msecs (200 msecs on 2.4) is more than
+			 * enough time to complete the receives, if it's
+			 * exceeded, break and error off
+			 */
+		} while (good_cnt < 64 && jiffies < (time + 20));
+		if (good_cnt != 64) {
+			/* ret_val is the same as mis-compare */
+			ret_val = 13;
+			break;
+		}
+		if (jiffies >= (time + 20)) {
+			/* Error code for time out error */
+			ret_val = 14;
+			break;
+		}
+	}
+
+	return ret_val;
+}
+
+static int ixgbe_loopback_test(struct ixgbe_adapter *adapter, u64 *data)
+{
+	*data = ixgbe_setup_desc_rings(adapter);
+	if (*data)
+		goto out;
+	*data = ixgbe_setup_loopback_test(adapter);
+	if (*data)
+		goto err_loopback;
+	*data = ixgbe_run_loopback_test(adapter);
+	ixgbe_loopback_cleanup(adapter);
+
+err_loopback:
+	ixgbe_free_desc_rings(adapter);
+out:
+	return *data;
+}
+
+static void ixgbe_diag_test(struct net_device *netdev,
+                            struct ethtool_test *eth_test, u64 *data)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	bool if_running = netif_running(netdev);
+
+	set_bit(__IXGBE_TESTING, &adapter->state);
+	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+		/* Offline tests */
+
+		DPRINTK(HW, INFO, "offline testing starting\n");
+
+		/* Link test performed before hardware reset so autoneg doesn't
+		 * interfere with test result */
+		if (ixgbe_link_test(adapter, &data[4]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		if (if_running)
+			/* indicate we're in test mode */
+			dev_close(netdev);
+		else
+			ixgbe_reset(adapter);
+
+		DPRINTK(HW, INFO, "register testing starting\n");
+		if (ixgbe_reg_test(adapter, &data[0]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		ixgbe_reset(adapter);
+		DPRINTK(HW, INFO, "eeprom testing starting\n");
+		if (ixgbe_eeprom_test(adapter, &data[1]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		ixgbe_reset(adapter);
+		DPRINTK(HW, INFO, "interrupt testing starting\n");
+		if (ixgbe_intr_test(adapter, &data[2]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		ixgbe_reset(adapter);
+		DPRINTK(HW, INFO, "loopback testing starting\n");
+		if (ixgbe_loopback_test(adapter, &data[3]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		ixgbe_reset(adapter);
+
+		clear_bit(__IXGBE_TESTING, &adapter->state);
+		if (if_running)
+			dev_open(netdev);
+	} else {
+		DPRINTK(HW, INFO, "online testing starting\n");
+		/* Online tests */
+		if (ixgbe_link_test(adapter, &data[4]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		/* Online tests aren't run; pass by default */
+		data[0] = 0;
+		data[1] = 0;
+		data[2] = 0;
+		data[3] = 0;
+
+		clear_bit(__IXGBE_TESTING, &adapter->state);
+	}
+	msleep_interruptible(4 * 1000);
+}
 
 static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter,
                                struct ethtool_wolinfo *wol)
@@ -955,7 +1830,6 @@
 		break;
 	default:
 		wol->supported = 0;
-		retval = 0;
 	}
 
 	return retval;
@@ -1074,6 +1948,7 @@
                               struct ethtool_coalesce *ec)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_q_vector *q_vector;
 	int i;
 
 	if (ec->tx_max_coalesced_frames_irq)
@@ -1101,25 +1976,58 @@
 		 * any other value means disable eitr, which is best
 		 * served by setting the interrupt rate very high
 		 */
-		adapter->eitr_param = IXGBE_MAX_INT_RATE;
+		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
+			adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE;
+		else
+			adapter->eitr_param = IXGBE_MAX_INT_RATE;
 		adapter->itr_setting = 0;
 	}
 
-	for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
-		struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
-		if (q_vector->txr_count && !q_vector->rxr_count)
-			/* tx vector gets half the rate */
-			q_vector->eitr = (adapter->eitr_param >> 1);
-		else
-			/* rx only or mixed */
-			q_vector->eitr = adapter->eitr_param;
-		ixgbe_write_eitr(adapter, i,
-		                 EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
+	/* MSI/MSIx Interrupt Mode */
+	if (adapter->flags &
+	    (IXGBE_FLAG_MSIX_ENABLED | IXGBE_FLAG_MSI_ENABLED)) {
+		int num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+		for (i = 0; i < num_vectors; i++) {
+			q_vector = adapter->q_vector[i];
+			if (q_vector->txr_count && !q_vector->rxr_count)
+				/* tx vector gets half the rate */
+				q_vector->eitr = (adapter->eitr_param >> 1);
+			else
+				/* rx only or mixed */
+				q_vector->eitr = adapter->eitr_param;
+			ixgbe_write_eitr(q_vector);
+		}
+	/* Legacy Interrupt Mode */
+	} else {
+		q_vector = adapter->q_vector[0];
+		q_vector->eitr = adapter->eitr_param;
+		ixgbe_write_eitr(q_vector);
 	}
 
 	return 0;
 }
 
+static int ixgbe_set_flags(struct net_device *netdev, u32 data)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+	ethtool_op_set_flags(netdev, data);
+
+	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
+		return 0;
+
+	/* if state changes we need to update adapter->flags and reset */
+	if ((!!(data & ETH_FLAG_LRO)) != 
+	    (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
+		adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
+		if (netif_running(netdev))
+			ixgbe_reinit_locked(adapter);
+		else
+			ixgbe_reset(adapter);
+	}
+	return 0;
+
+}
 
 static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_settings           = ixgbe_get_settings,
@@ -1147,6 +2055,7 @@
 	.set_msglevel           = ixgbe_set_msglevel,
 	.get_tso                = ethtool_op_get_tso,
 	.set_tso                = ixgbe_set_tso,
+	.self_test              = ixgbe_diag_test,
 	.get_strings            = ixgbe_get_strings,
 	.phys_id                = ixgbe_phys_id,
 	.get_sset_count         = ixgbe_get_sset_count,
@@ -1154,7 +2063,7 @@
 	.get_coalesce           = ixgbe_get_coalesce,
 	.set_coalesce           = ixgbe_set_coalesce,
 	.get_flags              = ethtool_op_get_flags,
-	.set_flags              = ethtool_op_set_flags,
+	.set_flags              = ixgbe_set_flags,
 };
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_fcoe.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_fcoe.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_fcoe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_fcoe.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,556 @@
+/*******************************************************************************
+
+  Intel 10 Gigabit PCI Express Linux driver
+  Copyright(c) 1999 - 2009 Intel Corporation.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Contact Information:
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+
+#include "ixgbe.h"
+#include <linux/if_ether.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_fcoe.h>
+#include <scsi/libfc.h>
+#include <scsi/libfcoe.h>
+
+/**
+ * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
+ * @rx_desc: advanced rx descriptor
+ *
+ * Returns : true if it is FCoE pkt
+ */
+static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc)
+{
+	u16 p;
+
+	p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info);
+	if (p & IXGBE_RXDADV_PKTTYPE_ETQF) {
+		p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK;
+		p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT;
+		return p == IXGBE_ETQF_FILTER_FCOE;
+	}
+	return false;
+}
+
+/**
+ * ixgbe_fcoe_clear_ddp - clear the given ddp context
+ * @ddp - ptr to the ixgbe_fcoe_ddp
+ *
+ * Returns : none
+ *
+ */
+static inline void ixgbe_fcoe_clear_ddp(struct ixgbe_fcoe_ddp *ddp)
+{
+	ddp->len = 0;
+	ddp->err = 0;
+	ddp->udl = NULL;
+	ddp->udp = 0UL;
+	ddp->sgl = NULL;
+	ddp->sgc = 0;
+}
+
+/**
+ * ixgbe_fcoe_ddp_put - free the ddp context for a given xid
+ * @netdev: the corresponding net_device
+ * @xid: the xid that corresponding ddp will be freed
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_done
+ * and it is expected to be called by ULD, i.e., FCP layer of libfc
+ * to release the corresponding ddp context when the I/O is done.
+ *
+ * Returns : data length already ddp-ed in bytes
+ */
+int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
+{
+	int len = 0;
+	struct ixgbe_fcoe *fcoe;
+	struct ixgbe_adapter *adapter;
+	struct ixgbe_fcoe_ddp *ddp;
+
+	if (!netdev)
+		goto out_ddp_put;
+
+	if (xid >= IXGBE_FCOE_DDP_MAX)
+		goto out_ddp_put;
+
+	adapter = netdev_priv(netdev);
+	fcoe = &adapter->fcoe;
+	ddp = &fcoe->ddp[xid];
+	if (!ddp->udl)
+		goto out_ddp_put;
+
+	len = ddp->len;
+	/* if there an error, force to invalidate ddp context */
+	if (ddp->err) {
+		spin_lock_bh(&fcoe->lock);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLT, 0);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLTRW,
+				(xid | IXGBE_FCFLTRW_WE));
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCBUFF, 0);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW,
+				(xid | IXGBE_FCDMARW_WE));
+		spin_unlock_bh(&fcoe->lock);
+	}
+	if (ddp->sgl)
+		pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc,
+			     DMA_FROM_DEVICE);
+	pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+	ixgbe_fcoe_clear_ddp(ddp);
+
+out_ddp_put:
+	return len;
+}
+
+/**
+ * ixgbe_fcoe_ddp_get - called to set up ddp context
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
+ * and is expected to be called from ULD, e.g., FCP layer of libfc
+ * to set up ddp for the corresponding xid of the given sglist for
+ * the corresponding I/O.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ */
+int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
+		       struct scatterlist *sgl, unsigned int sgc)
+{
+	struct ixgbe_adapter *adapter;
+	struct ixgbe_hw *hw;
+	struct ixgbe_fcoe *fcoe;
+	struct ixgbe_fcoe_ddp *ddp;
+	struct scatterlist *sg;
+	unsigned int i, j, dmacount;
+	unsigned int len;
+	static const unsigned int bufflen = 4096;
+	unsigned int firstoff = 0;
+	unsigned int lastsize;
+	unsigned int thisoff = 0;
+	unsigned int thislen = 0;
+	u32 fcbuff, fcdmarw, fcfltrw;
+	dma_addr_t addr;
+
+	if (!netdev || !sgl)
+		return 0;
+
+	adapter = netdev_priv(netdev);
+	if (xid >= IXGBE_FCOE_DDP_MAX) {
+		DPRINTK(DRV, WARNING, "xid=0x%x out-of-range\n", xid);
+		return 0;
+	}
+
+	fcoe = &adapter->fcoe;
+	if (!fcoe->pool) {
+		DPRINTK(DRV, WARNING, "xid=0x%x no ddp pool for fcoe\n", xid);
+		return 0;
+	}
+
+	ddp = &fcoe->ddp[xid];
+	if (ddp->sgl) {
+		DPRINTK(DRV, ERR, "xid 0x%x w/ non-null sgl=%p nents=%d\n",
+			xid, ddp->sgl, ddp->sgc);
+		return 0;
+	}
+	ixgbe_fcoe_clear_ddp(ddp);
+
+	/* setup dma from scsi command sgl */
+	dmacount = pci_map_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
+	if (dmacount == 0) {
+		DPRINTK(DRV, ERR, "xid 0x%x DMA map error\n", xid);
+		return 0;
+	}
+
+	/* alloc the udl from our ddp pool */
+	ddp->udl = pci_pool_alloc(fcoe->pool, GFP_KERNEL, &ddp->udp);
+	if (!ddp->udl) {
+		DPRINTK(DRV, ERR, "failed allocated ddp context\n");
+		goto out_noddp_unmap;
+	}
+	ddp->sgl = sgl;
+	ddp->sgc = sgc;
+
+	j = 0;
+	for_each_sg(sgl, sg, dmacount, i) {
+		addr = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+		while (len) {
+			/* get the offset of length of current buffer */
+			thisoff = addr & ((dma_addr_t)bufflen - 1);
+			thislen = min((bufflen - thisoff), len);
+			/*
+			 * all but the 1st buffer (j == 0)
+			 * must be aligned on bufflen
+			 */
+			if ((j != 0) && (thisoff))
+				goto out_noddp_free;
+			/*
+			 * all but the last buffer
+			 * ((i == (dmacount - 1)) && (thislen == len))
+			 * must end at bufflen
+			 */
+			if (((i != (dmacount - 1)) || (thislen != len))
+			    && ((thislen + thisoff) != bufflen))
+				goto out_noddp_free;
+
+			ddp->udl[j] = (u64)(addr - thisoff);
+			/* only the first buffer may have none-zero offset */
+			if (j == 0)
+				firstoff = thisoff;
+			len -= thislen;
+			addr += thislen;
+			j++;
+			/* max number of buffers allowed in one DDP context */
+			if (j > IXGBE_BUFFCNT_MAX) {
+				DPRINTK(DRV, ERR, "xid=%x:%d,%d,%d:addr=%llx "
+					"not enough descriptors\n",
+					xid, i, j, dmacount, (u64)addr);
+				goto out_noddp_free;
+			}
+		}
+	}
+	/* only the last buffer may have non-full bufflen */
+	lastsize = thisoff + thislen;
+
+	fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
+	fcbuff |= (j << IXGBE_FCBUFF_BUFFCNT_SHIFT);
+	fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
+	fcbuff |= (IXGBE_FCBUFF_VALID);
+
+	fcdmarw = xid;
+	fcdmarw |= IXGBE_FCDMARW_WE;
+	fcdmarw |= (lastsize << IXGBE_FCDMARW_LASTSIZE_SHIFT);
+
+	fcfltrw = xid;
+	fcfltrw |= IXGBE_FCFLTRW_WE;
+
+	/* program DMA context */
+	hw = &adapter->hw;
+	spin_lock_bh(&fcoe->lock);
+	IXGBE_WRITE_REG(hw, IXGBE_FCPTRL, ddp->udp & DMA_BIT_MASK(32));
+	IXGBE_WRITE_REG(hw, IXGBE_FCPTRH, (u64)ddp->udp >> 32);
+	IXGBE_WRITE_REG(hw, IXGBE_FCBUFF, fcbuff);
+	IXGBE_WRITE_REG(hw, IXGBE_FCDMARW, fcdmarw);
+	/* program filter context */
+	IXGBE_WRITE_REG(hw, IXGBE_FCPARAM, 0);
+	IXGBE_WRITE_REG(hw, IXGBE_FCFLT, IXGBE_FCFLT_VALID);
+	IXGBE_WRITE_REG(hw, IXGBE_FCFLTRW, fcfltrw);
+	spin_unlock_bh(&fcoe->lock);
+
+	return 1;
+
+out_noddp_free:
+	pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
+	ixgbe_fcoe_clear_ddp(ddp);
+
+out_noddp_unmap:
+	pci_unmap_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
+	return 0;
+}
+
+/**
+ * ixgbe_fcoe_ddp - check ddp status and mark it done
+ * @adapter: ixgbe adapter
+ * @rx_desc: advanced rx descriptor
+ * @skb: the skb holding the received data
+ *
+ * This checks ddp status.
+ *
+ * Returns : < 0 indicates an error or not a FCiE ddp, 0 indicates
+ * not passing the skb to ULD, > 0 indicates is the length of data
+ * being ddped.
+ */
+int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
+		   union ixgbe_adv_rx_desc *rx_desc,
+		   struct sk_buff *skb)
+{
+	u16 xid;
+	u32 sterr, fceofe, fcerr, fcstat;
+	int rc = -EINVAL;
+	struct ixgbe_fcoe *fcoe;
+	struct ixgbe_fcoe_ddp *ddp;
+	struct fc_frame_header *fh;
+
+	if (!ixgbe_rx_is_fcoe(rx_desc))
+		goto ddp_out;
+
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	sterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+	fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR);
+	fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE);
+	if (fcerr == IXGBE_FCERR_BADCRC)
+		skb->ip_summed = CHECKSUM_NONE;
+
+	skb_reset_network_header(skb);
+	skb_set_transport_header(skb, skb_network_offset(skb) +
+				 sizeof(struct fcoe_hdr));
+	fh = (struct fc_frame_header *)skb_transport_header(skb);
+	xid =  be16_to_cpu(fh->fh_ox_id);
+	if (xid >= IXGBE_FCOE_DDP_MAX)
+		goto ddp_out;
+
+	fcoe = &adapter->fcoe;
+	ddp = &fcoe->ddp[xid];
+	if (!ddp->udl)
+		goto ddp_out;
+
+	ddp->err = (fcerr | fceofe);
+	if (ddp->err)
+		goto ddp_out;
+
+	fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT);
+	if (fcstat) {
+		/* update length of DDPed data */
+		ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
+		/* unmap the sg list when FCP_RSP is received */
+		if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_FCPRSP) {
+			pci_unmap_sg(adapter->pdev, ddp->sgl,
+				     ddp->sgc, DMA_FROM_DEVICE);
+			ddp->sgl = NULL;
+			ddp->sgc = 0;
+		}
+		/* return 0 to bypass going to ULD for DDPed data */
+		if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_DDP)
+			rc = 0;
+		else if (ddp->len)
+			rc = ddp->len;
+	}
+
+ddp_out:
+	return rc;
+}
+
+/**
+ * ixgbe_fso - ixgbe FCoE Sequence Offload (FSO)
+ * @adapter: ixgbe adapter
+ * @tx_ring: tx desc ring
+ * @skb: associated skb
+ * @tx_flags: tx flags
+ * @hdr_len: hdr_len to be returned
+ *
+ * This sets up large send offload for FCoE
+ *
+ * Returns : 0 indicates no FSO, > 0 for FSO, < 0 for error
+ */
+int ixgbe_fso(struct ixgbe_adapter *adapter,
+              struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+              u32 tx_flags, u8 *hdr_len)
+{
+	u8 sof, eof;
+	u32 vlan_macip_lens;
+	u32 fcoe_sof_eof;
+	u32 type_tucmd;
+	u32 mss_l4len_idx;
+	int mss = 0;
+	unsigned int i;
+	struct ixgbe_tx_buffer *tx_buffer_info;
+	struct ixgbe_adv_tx_context_desc *context_desc;
+	struct fc_frame_header *fh;
+
+	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE)) {
+		DPRINTK(DRV, ERR, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
+			skb_shinfo(skb)->gso_type);
+		return -EINVAL;
+	}
+
+	/* resets the header to point fcoe/fc */
+	skb_set_network_header(skb, skb->mac_len);
+	skb_set_transport_header(skb, skb->mac_len +
+				 sizeof(struct fcoe_hdr));
+
+	/* sets up SOF and ORIS */
+	fcoe_sof_eof = 0;
+	sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
+	switch (sof) {
+	case FC_SOF_I2:
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+		break;
+	case FC_SOF_I3:
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIS;
+		break;
+	case FC_SOF_N2:
+		break;
+	case FC_SOF_N3:
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_SOF;
+		break;
+	default:
+		DPRINTK(DRV, WARNING, "unknown sof = 0x%x\n", sof);
+		return -EINVAL;
+	}
+
+	/* the first byte of the last dword is EOF */
+	skb_copy_bits(skb, skb->len - 4, &eof, 1);
+	/* sets up EOF and ORIE */
+	switch (eof) {
+	case FC_EOF_N:
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
+		break;
+	case FC_EOF_T:
+		/* lso needs ORIE */
+		if (skb_is_gso(skb)) {
+			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
+			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_ORIE;
+		} else {
+			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T;
+		}
+		break;
+	case FC_EOF_NI:
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI;
+		break;
+	case FC_EOF_A:
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A;
+		break;
+	default:
+		DPRINTK(DRV, WARNING, "unknown eof = 0x%x\n", eof);
+		return -EINVAL;
+	}
+
+	/* sets up PARINC indicating data offset */
+	fh = (struct fc_frame_header *)skb_transport_header(skb);
+	if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
+		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC;
+
+	/* hdr_len includes fc_hdr if FCoE lso is enabled */
+	*hdr_len = sizeof(struct fcoe_crc_eof);
+	if (skb_is_gso(skb))
+		*hdr_len += (skb_transport_offset(skb) +
+			     sizeof(struct fc_frame_header));
+	/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+	vlan_macip_lens = (skb_transport_offset(skb) +
+			  sizeof(struct fc_frame_header));
+	vlan_macip_lens |= ((skb_transport_offset(skb) - 4)
+			   << IXGBE_ADVTXD_MACLEN_SHIFT);
+	vlan_macip_lens |= (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
+
+	/* type_tycmd and mss: set TUCMD.FCoE to enable offload */
+	type_tucmd = IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT |
+		     IXGBE_ADVTXT_TUCMD_FCOE;
+	if (skb_is_gso(skb))
+		mss = skb_shinfo(skb)->gso_size;
+	/* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */
+	mss_l4len_idx = (mss << IXGBE_ADVTXD_MSS_SHIFT) |
+			(1 << IXGBE_ADVTXD_IDX_SHIFT);
+
+	/* write context desc */
+	i = tx_ring->next_to_use;
+	context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
+	context_desc->vlan_macip_lens	= cpu_to_le32(vlan_macip_lens);
+	context_desc->seqnum_seed	= cpu_to_le32(fcoe_sof_eof);
+	context_desc->type_tucmd_mlhl	= cpu_to_le32(type_tucmd);
+	context_desc->mss_l4len_idx	= cpu_to_le32(mss_l4len_idx);
+
+	tx_buffer_info = &tx_ring->tx_buffer_info[i];
+	tx_buffer_info->time_stamp = jiffies;
+	tx_buffer_info->next_to_watch = i;
+
+	i++;
+	if (i == tx_ring->count)
+		i = 0;
+	tx_ring->next_to_use = i;
+
+	return skb_is_gso(skb);
+}
+
+/**
+ * ixgbe_configure_fcoe - configures registers for fcoe at start
+ * @adapter: ptr to ixgbe adapter
+ *
+ * This sets up FCoE related registers
+ *
+ * Returns : none
+ */
+void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
+{
+	int i, fcoe_q, fcoe_i;
+	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
+	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
+
+	/* create the pool for ddp if not created yet */
+	if (!fcoe->pool) {
+		/* allocate ddp pool */
+		fcoe->pool = pci_pool_create("ixgbe_fcoe_ddp",
+					     adapter->pdev, IXGBE_FCPTR_MAX,
+					     IXGBE_FCPTR_ALIGN, PAGE_SIZE);
+		if (!fcoe->pool)
+			DPRINTK(DRV, ERR,
+				"failed to allocated FCoE DDP pool\n");
+
+		spin_lock_init(&fcoe->lock);
+	}
+
+	/* Enable L2 eth type filter for FCoE */
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE),
+			(ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN));
+	if (adapter->ring_feature[RING_F_FCOE].indices) {
+		/* Use multiple rx queues for FCoE by redirection table */
+		for (i = 0; i < IXGBE_FCRETA_SIZE; i++) {
+			fcoe_i = f->mask + i % f->indices;
+			fcoe_i &= IXGBE_FCRETA_ENTRY_MASK;
+			fcoe_q = adapter->rx_ring[fcoe_i].reg_idx;
+			IXGBE_WRITE_REG(hw, IXGBE_FCRETA(i), fcoe_q);
+		}
+		IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, IXGBE_FCRECTL_ENA);
+		IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), 0);
+	} else  {
+		/* Use single rx queue for FCoE */
+		fcoe_i = f->mask;
+		fcoe_q = adapter->rx_ring[fcoe_i].reg_idx;
+		IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, 0);
+		IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE),
+				IXGBE_ETQS_QUEUE_EN |
+				(fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL,
+			IXGBE_FCRXCTRL_FCOELLI |
+			IXGBE_FCRXCTRL_FCCRCBO |
+			(FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT));
+}
+
+/**
+ * ixgbe_cleanup_fcoe - release all fcoe ddp context resources
+ * @adapter : ixgbe adapter
+ *
+ * Cleans up outstanding ddp context resources
+ *
+ * Returns : none
+ */
+void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter)
+{
+	int i;
+	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
+
+	/* release ddp resource */
+	if (fcoe->pool) {
+		for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
+			ixgbe_fcoe_ddp_put(adapter->netdev, i);
+		pci_pool_destroy(fcoe->pool);
+		fcoe->pool = NULL;
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_fcoe.h linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_fcoe.h
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_fcoe.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_fcoe.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,67 @@
+/*******************************************************************************
+
+  Intel 10 Gigabit PCI Express Linux driver
+  Copyright(c) 1999 - 2009 Intel Corporation.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Contact Information:
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _IXGBE_FCOE_H
+#define _IXGBE_FCOE_H
+
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_fcoe.h>
+
+/* shift bits within STAT fo FCSTAT */
+#define IXGBE_RXDADV_FCSTAT_SHIFT	4
+
+/* ddp user buffer */
+#define IXGBE_BUFFCNT_MAX	256	/* 8 bits bufcnt */
+#define IXGBE_FCPTR_ALIGN	16
+#define IXGBE_FCPTR_MAX	(IXGBE_BUFFCNT_MAX * sizeof(dma_addr_t))
+#define IXGBE_FCBUFF_4KB	0x0
+#define IXGBE_FCBUFF_8KB	0x1
+#define IXGBE_FCBUFF_16KB	0x2
+#define IXGBE_FCBUFF_64KB	0x3
+#define IXGBE_FCBUFF_MAX	65536	/* 64KB max */
+#define IXGBE_FCBUFF_MIN	4096	/* 4KB min */
+#define IXGBE_FCOE_DDP_MAX	512	/* 9 bits xid */
+
+/* fcerr */
+#define IXGBE_FCERR_BADCRC       0x00100000
+
+struct ixgbe_fcoe_ddp {
+	int len;
+	u32 err;
+	unsigned int sgc;
+	struct scatterlist *sgl;
+	dma_addr_t udp;
+	u64 *udl;
+};
+
+struct ixgbe_fcoe {
+	spinlock_t lock;
+	struct pci_pool *pool;
+	struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
+};
+
+#endif /* _IXGBE_FCOE_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe.h linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe.h
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,6 +36,10 @@
 #include "ixgbe_type.h"
 #include "ixgbe_common.h"
 #include "ixgbe_dcb.h"
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#define IXGBE_FCOE
+#include "ixgbe_fcoe.h"
+#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
 #ifdef CONFIG_IXGBE_DCA
 #include <linux/dca.h>
 #endif
@@ -71,6 +75,8 @@
 #define IXGBE_RXBUFFER_128   128    /* Used for packet split */
 #define IXGBE_RXBUFFER_256   256    /* Used for packet split */
 #define IXGBE_RXBUFFER_2048  2048
+#define IXGBE_RXBUFFER_4096  4096
+#define IXGBE_RXBUFFER_8192  8192
 #define IXGBE_MAX_RXBUFFER   16384  /* largest size for a single descriptor */
 
 #define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_256
@@ -84,10 +90,14 @@
 #define IXGBE_TX_FLAGS_VLAN		(u32)(1 << 1)
 #define IXGBE_TX_FLAGS_TSO		(u32)(1 << 2)
 #define IXGBE_TX_FLAGS_IPV4		(u32)(1 << 3)
+#define IXGBE_TX_FLAGS_FCOE		(u32)(1 << 4)
+#define IXGBE_TX_FLAGS_FSO		(u32)(1 << 5)
 #define IXGBE_TX_FLAGS_VLAN_MASK	0xffff0000
 #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK   0x0000e000
 #define IXGBE_TX_FLAGS_VLAN_SHIFT	16
 
+#define IXGBE_MAX_RSC_INT_RATE          162760
+
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
 struct ixgbe_tx_buffer {
@@ -113,40 +123,45 @@
 
 struct ixgbe_ring {
 	void *desc;			/* descriptor ring memory */
-	dma_addr_t dma;			/* phys. address of descriptor ring */
-	unsigned int size;		/* length in bytes */
-	unsigned int count;		/* amount of descriptors */
-	unsigned int next_to_use;
-	unsigned int next_to_clean;
-
-	int queue_index; /* needed for multiqueue queue management */
 	union {
 		struct ixgbe_tx_buffer *tx_buffer_info;
 		struct ixgbe_rx_buffer *rx_buffer_info;
 	};
+	u8 atr_sample_rate;
+	u8 atr_count;
+	u16 count;			/* amount of descriptors */
+	u16 rx_buf_len;
+	u16 next_to_use;
+	u16 next_to_clean;
+
+	u8 queue_index; /* needed for multiqueue queue management */
 
+#define IXGBE_RING_RX_PS_ENABLED                (u8)(1)
+	u8 flags;			/* per ring feature flags */
 	u16 head;
 	u16 tail;
 
 	unsigned int total_bytes;
 	unsigned int total_packets;
 
-	u16 reg_idx; /* holds the special value that gets the hardware register
-		      * offset associated with this ring, which is different
-		      * for DCB and RSS modes */
-
 #ifdef CONFIG_IXGBE_DCA
 	/* cpu for tx queue */
 	int cpu;
 #endif
-	struct ixgbe_queue_stats stats;
-	u64 v_idx; /* maps directly to the index for this ring in the hardware
-	            * vector array, can also be used for finding the bit in EICR
-	            * and friends that represents the vector for this ring */
 
+	u16 work_limit;			/* max work per interrupt */
+	u16 reg_idx;			/* holds the special value that gets
+					 * the hardware register offset
+					 * associated with this ring, which is
+					 * different for DCB and RSS modes
+					 */
 
-	u16 work_limit;                /* max work per interrupt */
-	u16 rx_buf_len;
+	struct ixgbe_queue_stats stats;
+	unsigned long reinit_state;
+	u64 rsc_count;			/* stat for coalesced packets */
+
+	unsigned int size;		/* length in bytes */
+	dma_addr_t dma;			/* phys. address of descriptor ring */
 };
 
 enum ixgbe_ring_f_enum {
@@ -154,6 +169,10 @@
 	RING_F_DCB,
 	RING_F_VMDQ,
 	RING_F_RSS,
+	RING_F_FDIR,
+#ifdef IXGBE_FCOE
+	RING_F_FCOE,
+#endif /* IXGBE_FCOE */
 
 	RING_F_ARRAY_SIZE      /* must be last in enum set */
 };
@@ -161,6 +180,10 @@
 #define IXGBE_MAX_DCB_INDICES   8
 #define IXGBE_MAX_RSS_INDICES  16
 #define IXGBE_MAX_VMDQ_INDICES 16
+#define IXGBE_MAX_FDIR_INDICES 64
+#ifdef IXGBE_FCOE
+#define IXGBE_MAX_FCOE_INDICES  8
+#endif /* IXGBE_FCOE */
 struct ixgbe_ring_feature {
 	int indices;
 	int mask;
@@ -178,6 +201,9 @@
  */
 struct ixgbe_q_vector {
 	struct ixgbe_adapter *adapter;
+	unsigned int v_idx; /* index of q_vector within array, also used for
+	                     * finding the bit in EICR and friends that
+	                     * represents the vector for this ring */
 	struct napi_struct napi;
 	DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
 	DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
@@ -207,7 +233,15 @@
 #define IXGBE_TX_CTXTDESC_ADV(R, i)	    \
 	(&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i]))
 
+#define IXGBE_GET_DESC(R, i, type)	(&(((struct type *)((R).desc))[i]))
+#define IXGBE_TX_DESC(R, i)	IXGBE_GET_DESC(R, i, ixgbe_legacy_tx_desc)
+#define IXGBE_RX_DESC(R, i)	IXGBE_GET_DESC(R, i, ixgbe_legacy_rx_desc)
+
 #define IXGBE_MAX_JUMBO_FRAME_SIZE        16128
+#ifdef IXGBE_FCOE
+/* Use 3K as the baby jumbo frame size for FCoE */
+#define IXGBE_FCOE_JUMBO_FRAME_SIZE       3072
+#endif /* IXGBE_FCOE */
 
 #define OTHER_VECTOR 1
 #define NON_Q_VECTORS (OTHER_VECTOR)
@@ -229,11 +263,12 @@
 	struct vlan_group *vlgrp;
 	u16 bd_number;
 	struct work_struct reset_task;
-	struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
+	struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
 	char name[MAX_MSIX_COUNT][IFNAMSIZ + 9];
 	struct ixgbe_dcb_config dcb_cfg;
 	struct ixgbe_dcb_config temp_dcb_cfg;
 	u8 dcb_set_bitmap;
+	enum ixgbe_fc_mode last_lfc_mode;
 
 	/* Interrupt Throttle Rate */
 	u32 itr_setting;
@@ -294,7 +329,14 @@
 #define IXGBE_FLAG_IN_WATCHDOG_TASK             (u32)(1 << 23)
 #define IXGBE_FLAG_IN_SFP_LINK_TASK             (u32)(1 << 24)
 #define IXGBE_FLAG_IN_SFP_MOD_TASK              (u32)(1 << 25)
+#define IXGBE_FLAG_FDIR_HASH_CAPABLE            (u32)(1 << 26)
+#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE         (u32)(1 << 27)
+#define IXGBE_FLAG_FCOE_CAPABLE                 (u32)(1 << 28)
+#define IXGBE_FLAG_FCOE_ENABLED                 (u32)(1 << 29)
 
+	u32 flags2;
+#define IXGBE_FLAG2_RSC_CAPABLE                 (u32)(1)
+#define IXGBE_FLAG2_RSC_ENABLED                 (u32)(1 << 1)
 /* default to trying for four seconds */
 #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
 
@@ -303,6 +345,10 @@
 	struct pci_dev *pdev;
 	struct net_device_stats net_stats;
 
+	u32 test_icr;
+	struct ixgbe_ring test_tx_ring;
+	struct ixgbe_ring test_rx_ring;
+
 	/* structs defined in ixgbe_hw.h */
 	struct ixgbe_hw hw;
 	u16 msg_enable;
@@ -325,6 +371,14 @@
 	struct timer_list sfp_timer;
 	struct work_struct multispeed_fiber_task;
 	struct work_struct sfp_config_module_task;
+	u32 fdir_pballoc;
+	u32 atr_sample_rate;
+	spinlock_t fdir_perfect_lock;
+	struct work_struct fdir_reinit_task;
+#ifdef IXGBE_FCOE
+	struct ixgbe_fcoe fcoe;
+#endif /* IXGBE_FCOE */
+	u64 rsc_count;
 	u32 wol;
 	u16 eeprom_version;
 };
@@ -333,6 +387,7 @@
 	__IXGBE_TESTING,
 	__IXGBE_RESETTING,
 	__IXGBE_DOWN,
+	__IXGBE_FDIR_INIT_DONE,
 	__IXGBE_SFP_MODULE_NOT_FOUND
 };
 
@@ -363,10 +418,77 @@
 extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
 extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
 extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
-extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter);
 extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
-void ixgbe_napi_add_all(struct ixgbe_adapter *adapter);
-void ixgbe_napi_del_all(struct ixgbe_adapter *adapter);
-extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32);
+extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
+extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
+extern int ethtool_ioctl(struct ifreq *ifr);
+extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
+extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
+extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
+extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+                                                 struct ixgbe_atr_input *input,
+                                                 u8 queue);
+extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
+                                               struct ixgbe_atr_input *input,
+                                               u16 soft_id,
+                                               u8 queue);
+extern u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *input, u32 key);
+extern s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input,
+                                       u16 vlan_id);
+extern s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input,
+                                        u32 src_addr);
+extern s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input,
+                                        u32 dst_addr);
+extern s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
+                                        u32 src_addr_1, u32 src_addr_2,
+                                        u32 src_addr_3, u32 src_addr_4);
+extern s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
+                                        u32 dst_addr_1, u32 dst_addr_2,
+                                        u32 dst_addr_3, u32 dst_addr_4);
+extern s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input,
+                                        u16 src_port);
+extern s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input,
+                                        u16 dst_port);
+extern s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input,
+                                         u16 flex_byte);
+extern s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input,
+                                       u8 vm_pool);
+extern s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input,
+                                      u8 l4type);
+extern s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input,
+                                       u16 *vlan_id);
+extern s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input,
+                                        u32 *src_addr);
+extern s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input,
+                                        u32 *dst_addr);
+extern s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
+                                        u32 *src_addr_1, u32 *src_addr_2,
+                                        u32 *src_addr_3, u32 *src_addr_4);
+extern s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
+                                        u32 *dst_addr_1, u32 *dst_addr_2,
+                                        u32 *dst_addr_3, u32 *dst_addr_4);
+extern s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input,
+                                        u16 *src_port);
+extern s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input,
+                                        u16 *dst_port);
+extern s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input,
+                                         u16 *flex_byte);
+extern s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input,
+                                       u8 *vm_pool);
+extern s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input,
+                                      u8 *l4type);
+#ifdef IXGBE_FCOE
+extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
+extern int ixgbe_fso(struct ixgbe_adapter *adapter,
+                     struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+                     u32 tx_flags, u8 *hdr_len);
+extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
+extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
+                          union ixgbe_adv_rx_desc *rx_desc,
+                          struct sk_buff *skb);
+extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
+                              struct scatterlist *sgl, unsigned int sgc);
+extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid);
+#endif /* IXGBE_FCOE */
 
 #endif /* _IXGBE_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_main.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_main.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -34,11 +34,13 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/pkt_sched.h>
 #include <linux/ipv6.h>
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#include <scsi/fc/fc_fcoe.h>
 
 #include "ixgbe.h"
 #include "ixgbe_common.h"
@@ -47,7 +49,7 @@
 static const char ixgbe_driver_string[] =
                               "Intel(R) 10 Gigabit PCI Express Network Driver";
 
-#define DRV_VERSION "2.0.8-k2"
+#define DRV_VERSION "2.0.34-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
 
@@ -89,6 +91,8 @@
 	 board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4),
 	 board_82599 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM),
+	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP),
 	 board_82599 },
 
@@ -183,6 +187,22 @@
 	}
 }
 
+static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
+                                          u64 qmask)
+{
+	u32 mask;
+
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+		mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
+	} else {
+		mask = (qmask & 0xFFFFFFFF);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
+		mask = (qmask >> 32);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
+	}
+}
+
 static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
                                              struct ixgbe_tx_buffer
                                              *tx_buffer_info)
@@ -245,14 +265,13 @@
 
 /**
  * ixgbe_clean_tx_irq - Reclaim resources after transmit completes
- * @adapter: board private structure
+ * @q_vector: structure containing interrupt and ring information
  * @tx_ring: tx ring to clean
- *
- * returns true if transmit work is done
  **/
-static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
+static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
                                struct ixgbe_ring *tx_ring)
 {
+	struct ixgbe_adapter *adapter = q_vector->adapter;
 	struct net_device *netdev = adapter->netdev;
 	union ixgbe_adv_tx_desc *tx_desc, *eop_desc;
 	struct ixgbe_tx_buffer *tx_buffer_info;
@@ -275,12 +294,24 @@
 
 			if (cleaned && skb) {
 				unsigned int segs, bytecount;
+				unsigned int hlen = skb_headlen(skb);
 
 				/* gso_segs is currently only valid for tcp */
 				segs = skb_shinfo(skb)->gso_segs ?: 1;
+#ifdef IXGBE_FCOE
+				/* adjust for FCoE Sequence Offload */
+				if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
+				    && (skb->protocol == htons(ETH_P_FCOE)) &&
+				    skb_is_gso(skb)) {
+					hlen = skb_transport_offset(skb) +
+						sizeof(struct fc_frame_header) +
+						sizeof(struct fcoe_crc_eof);
+					segs = DIV_ROUND_UP(skb->len - hlen,
+						skb_shinfo(skb)->gso_size);
+				}
+#endif /* IXGBE_FCOE */
 				/* multiply data chunks by size of headers */
-				bytecount = ((segs - 1) * skb_headlen(skb)) +
-				            skb->len;
+				bytecount = ((segs - 1) * hlen) + skb->len;
 				total_packets += segs;
 				total_bytes += bytecount;
 			}
@@ -327,7 +358,7 @@
 
 	/* re-arm the interrupt */
 	if (count >= tx_ring->work_limit)
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx);
+		ixgbe_irq_rearm_queues(adapter, ((u64)1 << q_vector->v_idx));
 
 	tx_ring->total_bytes += total_bytes;
 	tx_ring->total_packets += total_packets;
@@ -398,6 +429,9 @@
 	if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
 		return;
 
+	/* always use CB2 mode, difference is masked in the CB driver */
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
+
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		adapter->tx_ring[i].cpu = -1;
 		ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]);
@@ -419,9 +453,6 @@
 		/* if we're already enabled, don't do it again */
 		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
 			break;
-		/* Always use CB2 mode, difference is masked
-		 * in the CB driver. */
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
 		if (dca_add_requester(dev) == 0) {
 			adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
 			ixgbe_setup_dca(adapter);
@@ -451,6 +482,7 @@
  **/
 static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
                               struct sk_buff *skb, u8 status,
+                              struct ixgbe_ring *ring,
                               union ixgbe_adv_rx_desc *rx_desc)
 {
 	struct ixgbe_adapter *adapter = q_vector->adapter;
@@ -458,24 +490,17 @@
 	bool is_vlan = (status & IXGBE_RXD_STAT_VP);
 	u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-	skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]);
-	if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
-		if (adapter->vlgrp && is_vlan && (tag != 0))
+	skb_record_rx_queue(skb, ring->queue_index);
+	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
+		if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
 			vlan_gro_receive(napi, adapter->vlgrp, tag, skb);
 		else
 			napi_gro_receive(napi, skb);
 	} else {
-		if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
-			if (adapter->vlgrp && is_vlan && (tag != 0))
-				vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
-			else
-				netif_receive_skb(skb);
-		} else {
-			if (adapter->vlgrp && is_vlan && (tag != 0))
-				vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
-			else
-				netif_rx(skb);
-		}
+		if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
+			vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
+		else
+			netif_rx(skb);
 	}
 }
 
@@ -486,8 +511,11 @@
  * @skb: skb currently being received and modified
  **/
 static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
-                                     u32 status_err, struct sk_buff *skb)
+				     union ixgbe_adv_rx_desc *rx_desc,
+				     struct sk_buff *skb)
 {
+	u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error);
+
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Rx csum disabled */
@@ -505,6 +533,16 @@
 		return;
 
 	if (status_err & IXGBE_RXDADV_ERR_TCPE) {
+		u16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
+
+		/*
+		 * 82599 errata, UDP frames with a 0 checksum can be marked as
+		 * checksum errors.
+		 */
+		if ((pkt_info & IXGBE_RXDADV_PKTTYPE_UDP) &&
+		    (adapter->hw.mac.type == ixgbe_mac_82599EB))
+			return;
+
 		adapter->hw_csum_rx_error++;
 		return;
 	}
@@ -539,7 +577,6 @@
 	union ixgbe_adv_rx_desc *rx_desc;
 	struct ixgbe_rx_buffer *bi;
 	unsigned int i;
-	unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN;
 
 	i = rx_ring->next_to_use;
 	bi = &rx_ring->rx_buffer_info[i];
@@ -548,7 +585,7 @@
 		rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
 
 		if (!bi->page_dma &&
-		    (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) {
+		    (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) {
 			if (!bi->page) {
 				bi->page = alloc_page(GFP_ATOMIC);
 				if (!bi->page) {
@@ -569,7 +606,9 @@
 
 		if (!bi->skb) {
 			struct sk_buff *skb;
-			skb = netdev_alloc_skb(adapter->netdev, bufsz);
+			skb = netdev_alloc_skb(adapter->netdev,
+			                       (rx_ring->rx_buf_len +
+			                        NET_IP_ALIGN));
 
 			if (!skb) {
 				adapter->alloc_rx_buff_failed++;
@@ -584,12 +623,13 @@
 			skb_reserve(skb, NET_IP_ALIGN);
 
 			bi->skb = skb;
-			bi->dma = pci_map_single(pdev, skb->data, bufsz,
+			bi->dma = pci_map_single(pdev, skb->data,
+			                         rx_ring->rx_buf_len,
 			                         PCI_DMA_FROMDEVICE);
 		}
 		/* Refresh the desc even if buffer_addrs didn't change because
 		 * each write-back erases this info. */
-		if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+		if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
 			rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
 			rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
 		} else {
@@ -622,6 +662,40 @@
 	return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
 }
 
+static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc)
+{
+	return (le32_to_cpu(rx_desc->wb.lower.lo_dword.data) &
+	        IXGBE_RXDADV_RSCCNT_MASK) >>
+	        IXGBE_RXDADV_RSCCNT_SHIFT;
+}
+
+/**
+ * ixgbe_transform_rsc_queue - change rsc queue into a full packet
+ * @skb: pointer to the last skb in the rsc queue
+ *
+ * This function changes a queue full of hw rsc buffers into a completed
+ * packet.  It uses the ->prev pointers to find the first packet and then
+ * turns it into the frag list owner.
+ **/
+static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb)
+{
+	unsigned int frag_list_size = 0;
+
+	while (skb->prev) {
+		struct sk_buff *prev = skb->prev;
+		frag_list_size += skb->len;
+		skb->prev = NULL;
+		skb = prev;
+	}
+
+	skb_shinfo(skb)->frag_list = skb->next;
+	skb->next = NULL;
+	skb->len += frag_list_size;
+	skb->data_len += frag_list_size;
+	skb->truesize += frag_list_size;
+	return skb;
+}
+
 static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                                struct ixgbe_ring *rx_ring,
                                int *work_done, int work_to_do)
@@ -631,12 +705,15 @@
 	union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
 	struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
 	struct sk_buff *skb;
-	unsigned int i;
+	unsigned int i, rsc_count = 0;
 	u32 len, staterr;
 	u16 hdr_info;
 	bool cleaned = false;
 	int cleaned_count = 0;
 	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
+#ifdef IXGBE_FCOE
+	int ddp_bytes = 0;
+#endif /* IXGBE_FCOE */
 
 	i = rx_ring->next_to_clean;
 	rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
@@ -649,7 +726,7 @@
 			break;
 		(*work_done)++;
 
-		if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+		if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
 			hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc));
 			len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
 			       IXGBE_RXDADV_HDRBUFLEN_SHIFT;
@@ -667,10 +744,11 @@
 		prefetch(skb->data - NET_IP_ALIGN);
 		rx_buffer_info->skb = NULL;
 
-		if (len && !skb_shinfo(skb)->nr_frags) {
+		if (rx_buffer_info->dma) {
 			pci_unmap_single(pdev, rx_buffer_info->dma,
 			                 rx_ring->rx_buf_len,
 			                 PCI_DMA_FROMDEVICE);
+			rx_buffer_info->dma = 0;
 			skb_put(skb, len);
 		}
 
@@ -697,20 +775,38 @@
 		i++;
 		if (i == rx_ring->count)
 			i = 0;
-		next_buffer = &rx_ring->rx_buffer_info[i];
 
 		next_rxd = IXGBE_RX_DESC_ADV(*rx_ring, i);
 		prefetch(next_rxd);
-
 		cleaned_count++;
+
+		if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
+			rsc_count = ixgbe_get_rsc_count(rx_desc);
+
+		if (rsc_count) {
+			u32 nextp = (staterr & IXGBE_RXDADV_NEXTP_MASK) >>
+				     IXGBE_RXDADV_NEXTP_SHIFT;
+			next_buffer = &rx_ring->rx_buffer_info[nextp];
+			rx_ring->rsc_count += (rsc_count - 1);
+		} else {
+			next_buffer = &rx_ring->rx_buffer_info[i];
+		}
+
 		if (staterr & IXGBE_RXD_STAT_EOP) {
+			if (skb->prev)
+				skb = ixgbe_transform_rsc_queue(skb);
 			rx_ring->stats.packets++;
 			rx_ring->stats.bytes += skb->len;
 		} else {
-			rx_buffer_info->skb = next_buffer->skb;
-			rx_buffer_info->dma = next_buffer->dma;
-			next_buffer->skb = skb;
-			next_buffer->dma = 0;
+			if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+				rx_buffer_info->skb = next_buffer->skb;
+				rx_buffer_info->dma = next_buffer->dma;
+				next_buffer->skb = skb;
+				next_buffer->dma = 0;
+			} else {
+				skb->next = next_buffer->skb;
+				skb->next->prev = skb;
+			}
 			adapter->non_eop_descs++;
 			goto next_desc;
 		}
@@ -720,14 +816,22 @@
 			goto next_desc;
 		}
 
-		ixgbe_rx_checksum(adapter, staterr, skb);
+		ixgbe_rx_checksum(adapter, rx_desc, skb);
 
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
 		total_rx_packets++;
 
 		skb->protocol = eth_type_trans(skb, adapter->netdev);
-		ixgbe_receive_skb(q_vector, skb, staterr, rx_desc);
+#ifdef IXGBE_FCOE
+		/* if ddp, not passing to ULD unless for FCP_RSP or error */
+		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+			ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb);
+			if (!ddp_bytes)
+				goto next_desc;
+		}
+#endif /* IXGBE_FCOE */
+		ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
 
 next_desc:
 		rx_desc->wb.upper.status_error = 0;
@@ -740,7 +844,7 @@
 
 		/* use prefetched values */
 		rx_desc = next_rxd;
-		rx_buffer_info = next_buffer;
+		rx_buffer_info = &rx_ring->rx_buffer_info[i];
 
 		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
 	}
@@ -751,6 +855,21 @@
 	if (cleaned_count)
 		ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
 
+#ifdef IXGBE_FCOE
+	/* include DDPed FCoE data */
+	if (ddp_bytes > 0) {
+		unsigned int mss;
+
+		mss = adapter->netdev->mtu - sizeof(struct fcoe_hdr) -
+			sizeof(struct fc_frame_header) -
+			sizeof(struct fcoe_crc_eof);
+		if (mss > 512)
+			mss &= ~511;
+		total_rx_bytes += ddp_bytes;
+		total_rx_packets += DIV_ROUND_UP(ddp_bytes, mss);
+	}
+#endif /* IXGBE_FCOE */
+
 	rx_ring->total_packets += total_rx_packets;
 	rx_ring->total_bytes += total_rx_bytes;
 	adapter->net_stats.rx_bytes += total_rx_bytes;
@@ -780,7 +899,7 @@
 	 * corresponding register.
 	 */
 	for (v_idx = 0; v_idx < q_vectors; v_idx++) {
-		q_vector = &adapter->q_vector[v_idx];
+		q_vector = adapter->q_vector[v_idx];
 		/* XXX for_each_bit(...) */
 		r_idx = find_first_bit(q_vector->rxr_idx,
 		                       adapter->num_rx_queues);
@@ -810,12 +929,7 @@
 			/* rx only */
 			q_vector->eitr = adapter->eitr_param;
 
-		/*
-		 * since this is initial set up don't need to call
-		 * ixgbe_write_eitr helper
-		 */
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx),
-		                EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
+		ixgbe_write_eitr(q_vector);
 	}
 
 	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
@@ -900,17 +1014,19 @@
 
 /**
  * ixgbe_write_eitr - write EITR register in hardware specific way
- * @adapter: pointer to adapter struct
- * @v_idx: vector index into q_vector array
- * @itr_reg: new value to be written in *register* format, not ints/s
+ * @q_vector: structure containing interrupt and ring information
  *
  * This function is made to be called by ethtool and by the driver
  * when it needs to update EITR registers at runtime.  Hardware
  * specific quirks/differences are taken care of here.
  */
-void ixgbe_write_eitr(struct ixgbe_adapter *adapter, int v_idx, u32 itr_reg)
+void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
 {
+	struct ixgbe_adapter *adapter = q_vector->adapter;
 	struct ixgbe_hw *hw = &adapter->hw;
+	int v_idx = q_vector->v_idx;
+	u32 itr_reg = EITR_INTS_PER_SEC_TO_REG(q_vector->eitr);
+
 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
 		/* must write high and low 16 bits to reset counter */
 		itr_reg |= (itr_reg << 16);
@@ -929,8 +1045,7 @@
 	struct ixgbe_adapter *adapter = q_vector->adapter;
 	u32 new_itr;
 	u8 current_itr, ret_itr;
-	int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) /
-	                       sizeof(struct ixgbe_q_vector);
+	int i, r_idx;
 	struct ixgbe_ring *rx_ring, *tx_ring;
 
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
@@ -980,14 +1095,13 @@
 	}
 
 	if (new_itr != q_vector->eitr) {
-		u32 itr_reg;
+		/* do an exponential smoothing */
+		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
 
 		/* save the algorithm value here, not the smoothed one */
 		q_vector->eitr = new_itr;
-		/* do an exponential smoothing */
-		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
-		itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
-		ixgbe_write_eitr(adapter, v_idx, itr_reg);
+
+		ixgbe_write_eitr(q_vector);
 	}
 
 	return;
@@ -1058,14 +1172,64 @@
 	if (hw->mac.type == ixgbe_mac_82598EB)
 		ixgbe_check_fan_failure(adapter, eicr);
 
-	if (hw->mac.type == ixgbe_mac_82599EB)
+	if (hw->mac.type == ixgbe_mac_82599EB) {
 		ixgbe_check_sfp_event(adapter, eicr);
+
+		/* Handle Flow Director Full threshold interrupt */
+		if (eicr & IXGBE_EICR_FLOW_DIR) {
+			int i;
+			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR);
+			/* Disable transmits before FDIR Re-initialization */
+			netif_tx_stop_all_queues(netdev);
+			for (i = 0; i < adapter->num_tx_queues; i++) {
+				struct ixgbe_ring *tx_ring =
+				                           &adapter->tx_ring[i];
+				if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE,
+				                       &tx_ring->reinit_state))
+					schedule_work(&adapter->fdir_reinit_task);
+			}
+		}
+	}
 	if (!test_bit(__IXGBE_DOWN, &adapter->state))
 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
 
 	return IRQ_HANDLED;
 }
 
+static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
+					   u64 qmask)
+{
+	u32 mask;
+
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+		mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+	} else {
+		mask = (qmask & 0xFFFFFFFF);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(0), mask);
+		mask = (qmask >> 32);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask);
+	}
+	/* skip the flush */
+}
+
+static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
+                                            u64 qmask)
+{
+	u32 mask;
+
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+		mask = (IXGBE_EIMS_RTX_QUEUE & qmask);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask);
+	} else {
+		mask = (qmask & 0xFFFFFFFF);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), mask);
+		mask = (qmask >> 32);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), mask);
+	}
+	/* skip the flush */
+}
+
 static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
 {
 	struct ixgbe_q_vector *q_vector = data;
@@ -1079,17 +1243,16 @@
 	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
 	for (i = 0; i < q_vector->txr_count; i++) {
 		tx_ring = &(adapter->tx_ring[r_idx]);
-#ifdef CONFIG_IXGBE_DCA
-		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
-			ixgbe_update_tx_dca(adapter, tx_ring);
-#endif
 		tx_ring->total_bytes = 0;
 		tx_ring->total_packets = 0;
-		ixgbe_clean_tx_irq(adapter, tx_ring);
 		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
 		                      r_idx + 1);
 	}
 
+	/* disable interrupts on this vector only */
+	ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx));
+	napi_schedule(&q_vector->napi);
+
 	return IRQ_HANDLED;
 }
 
@@ -1121,7 +1284,7 @@
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	rx_ring = &(adapter->rx_ring[r_idx]);
 	/* disable interrupts on this vector only */
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx);
+	ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx));
 	napi_schedule(&q_vector->napi);
 
 	return IRQ_HANDLED;
@@ -1129,8 +1292,36 @@
 
 static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
 {
-	ixgbe_msix_clean_rx(irq, data);
-	ixgbe_msix_clean_tx(irq, data);
+	struct ixgbe_q_vector *q_vector = data;
+	struct ixgbe_adapter  *adapter = q_vector->adapter;
+	struct ixgbe_ring  *ring;
+	int r_idx;
+	int i;
+
+	if (!q_vector->txr_count && !q_vector->rxr_count)
+		return IRQ_HANDLED;
+
+	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->txr_count; i++) {
+		ring = &(adapter->tx_ring[r_idx]);
+		ring->total_bytes = 0;
+		ring->total_packets = 0;
+		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+		                      r_idx + 1);
+	}
+
+	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
+	for (i = 0; i < q_vector->rxr_count; i++) {
+		ring = &(adapter->rx_ring[r_idx]);
+		ring->total_bytes = 0;
+		ring->total_packets = 0;
+		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
+		                      r_idx + 1);
+	}
+
+	/* disable interrupts on this vector only */
+	ixgbe_irq_disable_queues(adapter, ((u64)1 << q_vector->v_idx));
+	napi_schedule(&q_vector->napi);
 
 	return IRQ_HANDLED;
 }
@@ -1167,29 +1358,42 @@
 		if (adapter->itr_setting & 1)
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
-			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rx_ring->v_idx);
+			ixgbe_irq_enable_queues(adapter,
+			                        ((u64)1 << q_vector->v_idx));
 	}
 
 	return work_done;
 }
 
 /**
- * ixgbe_clean_rxonly_many - msix (aka one shot) rx clean routine
+ * ixgbe_clean_rxtx_many - msix (aka one shot) rx clean routine
  * @napi: napi struct with our devices info in it
  * @budget: amount of work driver is allowed to do this pass, in packets
  *
  * This function will clean more than one rx queue associated with a
  * q_vector.
  **/
-static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
+static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
 {
 	struct ixgbe_q_vector *q_vector =
 	                       container_of(napi, struct ixgbe_q_vector, napi);
 	struct ixgbe_adapter *adapter = q_vector->adapter;
-	struct ixgbe_ring *rx_ring = NULL;
+	struct ixgbe_ring *ring = NULL;
 	int work_done = 0, i;
 	long r_idx;
-	u16 enable_mask = 0;
+	bool tx_clean_complete = true;
+
+	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	for (i = 0; i < q_vector->txr_count; i++) {
+		ring = &(adapter->tx_ring[r_idx]);
+#ifdef CONFIG_IXGBE_DCA
+		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+			ixgbe_update_tx_dca(adapter, ring);
+#endif
+		tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
+		r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
+		                      r_idx + 1);
+	}
 
 	/* attempt to distribute budget to each queue fairly, but don't allow
 	 * the budget to go below 1 because we'll exit polling */
@@ -1197,47 +1401,87 @@
 	budget = max(budget, 1);
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
 	for (i = 0; i < q_vector->rxr_count; i++) {
-		rx_ring = &(adapter->rx_ring[r_idx]);
+		ring = &(adapter->rx_ring[r_idx]);
 #ifdef CONFIG_IXGBE_DCA
 		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
-			ixgbe_update_rx_dca(adapter, rx_ring);
+			ixgbe_update_rx_dca(adapter, ring);
 #endif
-		ixgbe_clean_rx_irq(q_vector, rx_ring, &work_done, budget);
-		enable_mask |= rx_ring->v_idx;
+		ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget);
 		r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
 		                      r_idx + 1);
 	}
 
 	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
-	rx_ring = &(adapter->rx_ring[r_idx]);
+	ring = &(adapter->rx_ring[r_idx]);
 	/* If all Rx work done, exit the polling mode */
 	if (work_done < budget) {
 		napi_complete(napi);
 		if (adapter->itr_setting & 1)
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
-			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, enable_mask);
+			ixgbe_irq_enable_queues(adapter,
+			                        ((u64)1 << q_vector->v_idx));
 		return 0;
 	}
 
 	return work_done;
 }
+
+/**
+ * ixgbe_clean_txonly - msix (aka one shot) tx clean routine
+ * @napi: napi struct with our devices info in it
+ * @budget: amount of work driver is allowed to do this pass, in packets
+ *
+ * This function is optimized for cleaning one queue only on a single
+ * q_vector!!!
+ **/
+static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
+{
+	struct ixgbe_q_vector *q_vector =
+	                       container_of(napi, struct ixgbe_q_vector, napi);
+	struct ixgbe_adapter *adapter = q_vector->adapter;
+	struct ixgbe_ring *tx_ring = NULL;
+	int work_done = 0;
+	long r_idx;
+
+	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
+	tx_ring = &(adapter->tx_ring[r_idx]);
+#ifdef CONFIG_IXGBE_DCA
+	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
+		ixgbe_update_tx_dca(adapter, tx_ring);
+#endif
+
+	if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
+		work_done = budget;
+
+	/* If all Rx work done, exit the polling mode */
+	if (work_done < budget) {
+		napi_complete(napi);
+		if (adapter->itr_setting & 1)
+			ixgbe_set_itr_msix(q_vector);
+		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+			ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
+	}
+
+	return work_done;
+}
+
 static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
                                      int r_idx)
 {
-	a->q_vector[v_idx].adapter = a;
-	set_bit(r_idx, a->q_vector[v_idx].rxr_idx);
-	a->q_vector[v_idx].rxr_count++;
-	a->rx_ring[r_idx].v_idx = 1 << v_idx;
+	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
+
+	set_bit(r_idx, q_vector->rxr_idx);
+	q_vector->rxr_count++;
 }
 
 static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
-                                     int r_idx)
+                                     int t_idx)
 {
-	a->q_vector[v_idx].adapter = a;
-	set_bit(r_idx, a->q_vector[v_idx].txr_idx);
-	a->q_vector[v_idx].txr_count++;
-	a->tx_ring[r_idx].v_idx = 1 << v_idx;
+	struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
+
+	set_bit(t_idx, q_vector->txr_idx);
+	q_vector->txr_count++;
 }
 
 /**
@@ -1333,7 +1577,7 @@
                          (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
                          &ixgbe_msix_clean_many)
 	for (vector = 0; vector < q_vectors; vector++) {
-		handler = SET_HANDLER(&adapter->q_vector[vector]);
+		handler = SET_HANDLER(adapter->q_vector[vector]);
 
 		if(handler == &ixgbe_msix_clean_rx) {
 			sprintf(adapter->name[vector], "%s-%s-%d",
@@ -1349,7 +1593,7 @@
 
 		err = request_irq(adapter->msix_entries[vector].vector,
 		                  handler, 0, adapter->name[vector],
-		                  &(adapter->q_vector[vector]));
+		                  adapter->q_vector[vector]);
 		if (err) {
 			DPRINTK(PROBE, ERR,
 			        "request_irq failed for MSIX interrupt "
@@ -1372,7 +1616,7 @@
 free_queue_irqs:
 	for (i = vector - 1; i >= 0; i--)
 		free_irq(adapter->msix_entries[--vector].vector,
-		         &(adapter->q_vector[i]));
+		         adapter->q_vector[i]);
 	adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
 	pci_disable_msix(adapter->pdev);
 	kfree(adapter->msix_entries);
@@ -1383,7 +1627,7 @@
 
 static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
 {
-	struct ixgbe_q_vector *q_vector = adapter->q_vector;
+	struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
 	u8 current_itr;
 	u32 new_itr = q_vector->eitr;
 	struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
@@ -1416,14 +1660,13 @@
 	}
 
 	if (new_itr != q_vector->eitr) {
-		u32 itr_reg;
+		/* do an exponential smoothing */
+		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
 
 		/* save the algorithm value here, not the smoothed one */
 		q_vector->eitr = new_itr;
-		/* do an exponential smoothing */
-		new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
-		itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
-		ixgbe_write_eitr(adapter, 0, itr_reg);
+
+		ixgbe_write_eitr(q_vector);
 	}
 
 	return;
@@ -1436,7 +1679,8 @@
 static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
 {
 	u32 mask;
-	mask = IXGBE_EIMS_ENABLE_MASK;
+
+	mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
 	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
 		mask |= IXGBE_EIMS_GPI_SDP1;
 	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
@@ -1444,16 +1688,12 @@
 		mask |= IXGBE_EIMS_GPI_SDP1;
 		mask |= IXGBE_EIMS_GPI_SDP2;
 	}
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+		mask |= IXGBE_EIMS_FLOW_DIR;
 
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-		/* enable the rest of the queue vectors */
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1),
-		                (IXGBE_EIMS_RTX_QUEUE << 16));
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2),
-		                ((IXGBE_EIMS_RTX_QUEUE << 16) |
-		                  IXGBE_EIMS_RTX_QUEUE));
-	}
+	ixgbe_irq_enable_queues(adapter, ~0);
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 }
 
@@ -1467,6 +1707,7 @@
 	struct net_device *netdev = data;
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
 	u32 eicr;
 
 	/*
@@ -1494,13 +1735,13 @@
 
 	ixgbe_check_fan_failure(adapter, eicr);
 
-	if (napi_schedule_prep(&adapter->q_vector[0].napi)) {
+	if (napi_schedule_prep(&(q_vector->napi))) {
 		adapter->tx_ring[0].total_packets = 0;
 		adapter->tx_ring[0].total_bytes = 0;
 		adapter->rx_ring[0].total_packets = 0;
 		adapter->rx_ring[0].total_bytes = 0;
 		/* would disable interrupts here but EIAM disabled it */
-		__napi_schedule(&adapter->q_vector[0].napi);
+		__napi_schedule(&(q_vector->napi));
 	}
 
 	return IRQ_HANDLED;
@@ -1511,7 +1752,7 @@
 	int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 
 	for (i = 0; i < q_vectors; i++) {
-		struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
+		struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
 		bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES);
 		bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES);
 		q_vector->rxr_count = 0;
@@ -1562,7 +1803,7 @@
 		i--;
 		for (; i >= 0; i--) {
 			free_irq(adapter->msix_entries[i].vector,
-			         &(adapter->q_vector[i]));
+			         adapter->q_vector[i]);
 		}
 
 		ixgbe_reset_q_vectors(adapter);
@@ -1577,10 +1818,12 @@
  **/
 static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
 {
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+	} else {
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(2), ~0);
 	}
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
@@ -1592,18 +1835,6 @@
 	}
 }
 
-static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter)
-{
-	u32 mask = IXGBE_EIMS_RTX_QUEUE;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(1), mask << 16);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS_EX(2),
-		                (mask << 16 | mask));
-	}
-	/* skip the flush */
-}
-
 /**
  * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts
  *
@@ -1667,55 +1898,73 @@
 
 #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
 
-static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
+static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
+                                   struct ixgbe_ring *rx_ring)
 {
-	struct ixgbe_ring *rx_ring;
 	u32 srrctl;
-	int queue0 = 0;
-	unsigned long mask;
+	int index;
+	struct ixgbe_ring_feature *feature = adapter->ring_feature;
 
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-		queue0 = index;
-	} else {
-		mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask;
-		queue0 = index & mask;
+	index = rx_ring->reg_idx;
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+		unsigned long mask;
+		mask = (unsigned long) feature[RING_F_RSS].mask;
 		index = index & mask;
 	}
-
-	rx_ring = &adapter->rx_ring[queue0];
-
 	srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(index));
 
 	srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
 	srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
 
-	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
-		u16 bufsz = IXGBE_RXBUFFER_2048;
-		/* grow the amount we can receive on large page machines */
-		if (bufsz < (PAGE_SIZE / 2))
-			bufsz = (PAGE_SIZE / 2);
-		/* cap the bufsz at our largest descriptor size */
-		bufsz = min((u16)IXGBE_MAX_RXBUFFER, bufsz);
+	srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
+		  IXGBE_SRRCTL_BSIZEHDR_MASK;
 
-		srrctl |= bufsz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+	if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+#if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER
+		srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+#else
+		srrctl |= (PAGE_SIZE / 2) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+#endif
 		srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
-		srrctl |= ((IXGBE_RX_HDR_SIZE <<
-		            IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
-		           IXGBE_SRRCTL_BSIZEHDR_MASK);
 	} else {
+		srrctl |= ALIGN(rx_ring->rx_buf_len, 1024) >>
+			  IXGBE_SRRCTL_BSIZEPKT_SHIFT;
 		srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
-
-		if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE)
-			srrctl |= IXGBE_RXBUFFER_2048 >>
-			          IXGBE_SRRCTL_BSIZEPKT_SHIFT;
-		else
-			srrctl |= rx_ring->rx_buf_len >>
-			          IXGBE_SRRCTL_BSIZEPKT_SHIFT;
 	}
 
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl);
 }
 
+static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
+{
+	u32 mrqc = 0;
+	int mask;
+
+	if (!(adapter->hw.mac.type == ixgbe_mac_82599EB))
+		return mrqc;
+
+	mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
+#ifdef CONFIG_IXGBE_DCB
+				 | IXGBE_FLAG_DCB_ENABLED
+#endif
+				);
+
+	switch (mask) {
+	case (IXGBE_FLAG_RSS_ENABLED):
+		mrqc = IXGBE_MRQC_RSSEN;
+		break;
+#ifdef CONFIG_IXGBE_DCB
+	case (IXGBE_FLAG_DCB_ENABLED):
+		mrqc = IXGBE_MRQC_RT8TCEN;
+		break;
+#endif /* CONFIG_IXGBE_DCB */
+	default:
+		break;
+	}
+
+	return mrqc;
+}
+
 /**
  * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
  * @adapter: board private structure
@@ -1726,6 +1975,7 @@
 {
 	u64 rdba;
 	struct ixgbe_hw *hw = &adapter->hw;
+	struct ixgbe_ring *rx_ring;
 	struct net_device *netdev = adapter->netdev;
 	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 	int i, j;
@@ -1736,6 +1986,7 @@
 	u32 fctrl, hlreg0;
 	u32 reta = 0, mrqc = 0;
 	u32 rdrxctl;
+	u32 rscctrl;
 	int rx_buf_len;
 
 	/* Decide whether to use packet split mode or not */
@@ -1749,11 +2000,13 @@
 			u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
 			              IXGBE_PSRTYPE_UDPHDR |
 			              IXGBE_PSRTYPE_IPV4HDR |
-			              IXGBE_PSRTYPE_IPV6HDR;
+			              IXGBE_PSRTYPE_IPV6HDR |
+			              IXGBE_PSRTYPE_L2HDR;
 			IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
 		}
 	} else {
-		if (netdev->mtu <= ETH_DATA_LEN)
+		if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
+		    (netdev->mtu <= ETH_DATA_LEN))
 			rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 		else
 			rx_buf_len = ALIGN(max_frame, 1024);
@@ -1770,6 +2023,10 @@
 		hlreg0 &= ~IXGBE_HLREG0_JUMBOEN;
 	else
 		hlreg0 |= IXGBE_HLREG0_JUMBOEN;
+#ifdef IXGBE_FCOE
+	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
+		hlreg0 |= IXGBE_HLREG0_JUMBOEN;
+#endif
 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
 
 	rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc);
@@ -1777,21 +2034,40 @@
 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
 
-	/* Setup the HW Rx Head and Tail Descriptor Pointers and
-	 * the Base and Length of the Rx Descriptor Ring */
+	/*
+	 * Setup the HW Rx Head and Tail Descriptor Pointers and
+	 * the Base and Length of the Rx Descriptor Ring
+	 */
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		rdba = adapter->rx_ring[i].dma;
-		j = adapter->rx_ring[i].reg_idx;
+		rx_ring = &adapter->rx_ring[i];
+		rdba = rx_ring->dma;
+		j = rx_ring->reg_idx;
 		IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32)));
 		IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
 		IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen);
 		IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
 		IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
-		adapter->rx_ring[i].head = IXGBE_RDH(j);
-		adapter->rx_ring[i].tail = IXGBE_RDT(j);
-		adapter->rx_ring[i].rx_buf_len = rx_buf_len;
+		rx_ring->head = IXGBE_RDH(j);
+		rx_ring->tail = IXGBE_RDT(j);
+		rx_ring->rx_buf_len = rx_buf_len;
 
-		ixgbe_configure_srrctl(adapter, j);
+		if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)
+			rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED;
+
+#ifdef IXGBE_FCOE
+		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+			struct ixgbe_ring_feature *f;
+			f = &adapter->ring_feature[RING_F_FCOE];
+			if ((i >= f->mask) && (i < f->mask + f->indices)) {
+				rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
+				if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE)
+					rx_ring->rx_buf_len =
+					        IXGBE_FCOE_JUMBO_FRAME_SIZE;
+			}
+		}
+
+#endif /* IXGBE_FCOE */
+		ixgbe_configure_srrctl(adapter, rx_ring);
 	}
 
 	if (hw->mac.type == ixgbe_mac_82598EB) {
@@ -1811,23 +2087,8 @@
 	}
 
 	/* Program MRQC for the distribution of queues */
-	if (hw->mac.type == ixgbe_mac_82599EB) {
-		int mask = adapter->flags & (
-				IXGBE_FLAG_RSS_ENABLED
-				| IXGBE_FLAG_DCB_ENABLED
-				);
+	mrqc = ixgbe_setup_mrqc(adapter);
 
-		switch (mask) {
-		case (IXGBE_FLAG_RSS_ENABLED):
-			mrqc = IXGBE_MRQC_RSSEN;
-			break;
-		case (IXGBE_FLAG_DCB_ENABLED):
-			mrqc = IXGBE_MRQC_RT8TCEN;
-			break;
-		default:
-			break;
-		}
-	}
 	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
 		/* Fill out redirection table */
 		for (i = 0, j = 0; i < 128; i++, j++) {
@@ -1875,8 +2136,46 @@
 	if (hw->mac.type == ixgbe_mac_82599EB) {
 		rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
 		rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
+		rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
 		IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
 	}
+
+	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
+		/* Enable 82599 HW-RSC */
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			rx_ring = &adapter->rx_ring[i];
+			j = rx_ring->reg_idx;
+			rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
+			rscctrl |= IXGBE_RSCCTL_RSCEN;
+			/*
+			 * we must limit the number of descriptors so that the
+			 * total size of max desc * buf_len is not greater
+			 * than 65535
+			 */
+			if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+#if (MAX_SKB_FRAGS > 16)
+				rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
+#elif (MAX_SKB_FRAGS > 8)
+				rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
+#elif (MAX_SKB_FRAGS > 4)
+				rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
+#else
+				rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
+#endif
+			} else {
+				if (rx_buf_len < IXGBE_RXBUFFER_4096)
+					rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
+				else if (rx_buf_len < IXGBE_RXBUFFER_8192)
+					rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
+				else
+					rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
+			}
+			IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
+		}
+		/* Disable RSC for ACK packets */
+		IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
+		   (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
+	}
 }
 
 static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
@@ -2015,11 +2314,7 @@
 	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
 
 	/* reprogram secondary unicast list */
-	addr_count = netdev->uc_count;
-	if (addr_count)
-		addr_list = netdev->uc_list->dmi_addr;
-	hw->mac.ops.update_uc_addr_list(hw, addr_list, addr_count,
-	                                  ixgbe_addr_list_itr);
+	hw->mac.ops.update_uc_addr_list(hw, &netdev->uc.list);
 
 	/* reprogram multicast list */
 	addr_count = netdev->mc_count;
@@ -2041,13 +2336,16 @@
 
 	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
 		struct napi_struct *napi;
-		q_vector = &adapter->q_vector[q_idx];
-		if (!q_vector->rxr_count)
-			continue;
+		q_vector = adapter->q_vector[q_idx];
 		napi = &q_vector->napi;
-		if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) &&
-		    (q_vector->rxr_count > 1))
-			napi->poll = &ixgbe_clean_rxonly_many;
+		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+			if (!q_vector->rxr_count || !q_vector->txr_count) {
+				if (q_vector->txr_count == 1)
+					napi->poll = &ixgbe_clean_txonly;
+				else if (q_vector->rxr_count == 1)
+					napi->poll = &ixgbe_clean_rxonly;
+			}
+		}
 
 		napi_enable(napi);
 	}
@@ -2064,9 +2362,7 @@
 		q_vectors = 1;
 
 	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
-		q_vector = &adapter->q_vector[q_idx];
-		if (!q_vector->rxr_count)
-			continue;
+		q_vector = adapter->q_vector[q_idx];
 		napi_disable(&q_vector->napi);
 	}
 }
@@ -2124,6 +2420,7 @@
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
+	struct ixgbe_hw *hw = &adapter->hw;
 	int i;
 
 	ixgbe_set_rx_mode(netdev);
@@ -2140,6 +2437,20 @@
 	netif_set_gso_max_size(netdev, 65536);
 #endif
 
+#ifdef IXGBE_FCOE
+	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
+		ixgbe_configure_fcoe(adapter);
+
+#endif /* IXGBE_FCOE */
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			adapter->tx_ring[i].atr_sample_rate =
+			                               adapter->atr_sample_rate;
+		ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
+	} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
+		ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc);
+	}
+
 	ixgbe_configure_tx(adapter);
 	ixgbe_configure_rx(adapter);
 	for (i = 0; i < adapter->num_rx_queues; i++)
@@ -2294,6 +2605,13 @@
 		IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
 	}
 
+#ifdef IXGBE_FCOE
+	/* adjust max frame to be able to do baby jumbo for FCoE */
+	if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
+	    (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE))
+		max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
+
+#endif /* IXGBE_FCOE */
 	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
 	if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
@@ -2357,17 +2675,35 @@
 	ixgbe_irq_enable(adapter);
 
 	/*
+	 * If this adapter has a fan, check to see if we had a failure
+	 * before we enabled the interrupt.
+	 */
+	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
+		u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		if (esdp & IXGBE_ESDP_SDP1)
+			DPRINTK(DRV, CRIT,
+				"Fan has stopped, replace the adapter\n");
+	}
+
+	/*
 	 * For hot-pluggable SFP+ devices, a new SFP+ module may have
-	 * arrived before interrupts were enabled.  We need to kick off
-	 * the SFP+ module setup first, then try to bring up link.
+	 * arrived before interrupts were enabled but after probe.  Such
+	 * devices wouldn't have their type identified yet. We need to
+	 * kick off the SFP+ module setup first, then try to bring up link.
 	 * If we're not hot-pluggable SFP+, we just need to configure link
 	 * and bring it up.
 	 */
-	err = hw->phy.ops.identify(hw);
-	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-		DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err);
-		ixgbe_down(adapter);
-		return err;
+	if (hw->phy.type == ixgbe_phy_unknown) {
+		err = hw->phy.ops.identify(hw);
+		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+			/*
+			 * Take the device down and schedule the sfp tasklet
+			 * which will unregister_netdev and log it.
+			 */
+			ixgbe_down(adapter);
+			schedule_work(&adapter->sfp_config_module_task);
+			return err;
+		}
 	}
 
 	if (ixgbe_is_sfp(hw)) {
@@ -2378,6 +2714,10 @@
 			DPRINTK(PROBE, ERR, "link_config FAILED %d\n", err);
 	}
 
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		set_bit(__IXGBE_FDIR_INIT_DONE,
+		        &(adapter->tx_ring[i].reinit_state));
+
 	/* enable transmits */
 	netif_tx_start_all_queues(netdev);
 
@@ -2404,20 +2744,37 @@
 	/* hardware has been reset, we need to reload some things */
 	ixgbe_configure(adapter);
 
-	ixgbe_napi_add_all(adapter);
-
 	return ixgbe_up_complete(adapter);
 }
 
 void ixgbe_reset(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	if (hw->mac.ops.init_hw(hw))
-		dev_err(&adapter->pdev->dev, "Hardware Error\n");
+	int err;
+
+	err = hw->mac.ops.init_hw(hw);
+	switch (err) {
+	case 0:
+	case IXGBE_ERR_SFP_NOT_PRESENT:
+		break;
+	case IXGBE_ERR_MASTER_REQUESTS_PENDING:
+		dev_err(&adapter->pdev->dev, "master disable timed out\n");
+		break;
+	case IXGBE_ERR_EEPROM_VERSION:
+		/* We are running on a pre-production device, log a warning */
+		dev_warn(&adapter->pdev->dev, "This device is a pre-production "
+		         "adapter/LOM.  Please be aware there may be issues "
+		         "associated with your hardware.  If you are "
+		         "experiencing problems please contact your Intel or "
+		         "hardware representative who provided you with this "
+		         "hardware.\n");
+		break;
+	default:
+		dev_err(&adapter->pdev->dev, "Hardware Error: %d\n", err);
+	}
 
 	/* reprogram the RAR[0] in case user changed it. */
 	hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
 }
 
 /**
@@ -2445,14 +2802,21 @@
 			rx_buffer_info->dma = 0;
 		}
 		if (rx_buffer_info->skb) {
-			dev_kfree_skb(rx_buffer_info->skb);
+			struct sk_buff *skb = rx_buffer_info->skb;
 			rx_buffer_info->skb = NULL;
+			do {
+				struct sk_buff *this = skb;
+				skb = skb->prev;
+				dev_kfree_skb(this);
+			} while (skb);
 		}
 		if (!rx_buffer_info->page)
 			continue;
-		pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2,
-		               PCI_DMA_FROMDEVICE);
-		rx_buffer_info->page_dma = 0;
+		if (rx_buffer_info->page_dma) {
+			pci_unmap_page(pdev, rx_buffer_info->page_dma,
+			               PAGE_SIZE / 2, PCI_DMA_FROMDEVICE);
+			rx_buffer_info->page_dma = 0;
+		}
 		put_page(rx_buffer_info->page);
 		rx_buffer_info->page = NULL;
 		rx_buffer_info->page_offset = 0;
@@ -2560,6 +2924,10 @@
 	del_timer_sync(&adapter->watchdog_timer);
 	cancel_work_sync(&adapter->watchdog_task);
 
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+		cancel_work_sync(&adapter->fdir_reinit_task);
+
 	/* disable transmits in the hardware now that interrupts are off */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		j = adapter->tx_ring[i].reg_idx;
@@ -2575,13 +2943,6 @@
 
 	netif_carrier_off(netdev);
 
-#ifdef CONFIG_IXGBE_DCA
-	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
-		adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
-		dca_remove_requester(&adapter->pdev->dev);
-	}
-
-#endif
 	if (!pci_channel_offline(adapter->pdev))
 		ixgbe_reset(adapter);
 	ixgbe_clean_all_tx_rings(adapter);
@@ -2589,13 +2950,7 @@
 
 #ifdef CONFIG_IXGBE_DCA
 	/* since we reset the hardware DCA settings were cleared */
-	if (dca_add_requester(&adapter->pdev->dev) == 0) {
-		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
-		/* always use CB2 mode, difference is masked
-		 * in the CB driver */
-		IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2);
-		ixgbe_setup_dca(adapter);
-	}
+	ixgbe_setup_dca(adapter);
 #endif
 }
 
@@ -2620,7 +2975,7 @@
 	}
 #endif
 
-	tx_clean_complete = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
+	tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring);
 	ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget);
 
 	if (!tx_clean_complete)
@@ -2632,7 +2987,7 @@
 		if (adapter->itr_setting & 1)
 			ixgbe_set_itr(adapter);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
-			ixgbe_irq_enable_queues(adapter);
+			ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
 	}
 	return work_done;
 }
@@ -2668,17 +3023,15 @@
 static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
 {
 	bool ret = false;
+	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_DCB];
 
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		adapter->ring_feature[RING_F_DCB].mask = 0x7 << 3;
-		adapter->num_rx_queues =
-		                      adapter->ring_feature[RING_F_DCB].indices;
-		adapter->num_tx_queues =
-		                      adapter->ring_feature[RING_F_DCB].indices;
-		ret = true;
-	} else {
-		ret = false;
-	}
+	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+		return ret;
+
+	f->mask = 0x7 << 3;
+	adapter->num_rx_queues = f->indices;
+	adapter->num_tx_queues = f->indices;
+	ret = true;
 
 	return ret;
 }
@@ -2695,13 +3048,12 @@
 static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter)
 {
 	bool ret = false;
+	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_RSS];
 
 	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
-		adapter->ring_feature[RING_F_RSS].mask = 0xF;
-		adapter->num_rx_queues =
-		                      adapter->ring_feature[RING_F_RSS].indices;
-		adapter->num_tx_queues =
-		                      adapter->ring_feature[RING_F_RSS].indices;
+		f->mask = 0xF;
+		adapter->num_rx_queues = f->indices;
+		adapter->num_tx_queues = f->indices;
 		ret = true;
 	} else {
 		ret = false;
@@ -2710,6 +3062,83 @@
 	return ret;
 }
 
+/**
+ * ixgbe_set_fdir_queues: Allocate queues for Flow Director
+ * @adapter: board private structure to initialize
+ *
+ * Flow Director is an advanced Rx filter, attempting to get Rx flows back
+ * to the original CPU that initiated the Tx session.  This runs in addition
+ * to RSS, so if a packet doesn't match an FDIR filter, we can still spread the
+ * Rx load across CPUs using RSS.
+ *
+ **/
+static bool inline ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
+{
+	bool ret = false;
+	struct ixgbe_ring_feature *f_fdir = &adapter->ring_feature[RING_F_FDIR];
+
+	f_fdir->indices = min((int)num_online_cpus(), f_fdir->indices);
+	f_fdir->mask = 0;
+
+	/* Flow Director must have RSS enabled */
+	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
+	    ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+	     (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)))) {
+		adapter->num_tx_queues = f_fdir->indices;
+		adapter->num_rx_queues = f_fdir->indices;
+		ret = true;
+	} else {
+		adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+	}
+	return ret;
+}
+
+#ifdef IXGBE_FCOE
+/**
+ * ixgbe_set_fcoe_queues: Allocate queues for Fiber Channel over Ethernet (FCoE)
+ * @adapter: board private structure to initialize
+ *
+ * FCoE RX FCRETA can use up to 8 rx queues for up to 8 different exchanges.
+ * The ring feature mask is not used as a mask for FCoE, as it can take any 8
+ * rx queues out of the max number of rx queues, instead, it is used as the
+ * index of the first rx queue used by FCoE.
+ *
+ **/
+static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
+{
+	bool ret = false;
+	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
+
+	f->indices = min((int)num_online_cpus(), f->indices);
+	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+#ifdef CONFIG_IXGBE_DCB
+		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+			DPRINTK(PROBE, INFO, "FCOE enabled with DCB \n");
+			ixgbe_set_dcb_queues(adapter);
+		}
+#endif
+		if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
+			DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n");
+			if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+			    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+				ixgbe_set_fdir_queues(adapter);
+			else
+				ixgbe_set_rss_queues(adapter);
+		}
+		/* adding FCoE rx rings to the end */
+		f->mask = adapter->num_rx_queues;
+		adapter->num_rx_queues += f->indices;
+		if (adapter->num_tx_queues == 0)
+			adapter->num_tx_queues = f->indices;
+
+		ret = true;
+	}
+
+	return ret;
+}
+
+#endif /* IXGBE_FCOE */
 /*
  * ixgbe_set_num_queues: Allocate queues for device, feature dependant
  * @adapter: board private structure to initialize
@@ -2723,11 +3152,19 @@
  **/
 static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
 {
+#ifdef IXGBE_FCOE
+	if (ixgbe_set_fcoe_queues(adapter))
+		goto done;
+
+#endif /* IXGBE_FCOE */
 #ifdef CONFIG_IXGBE_DCB
 	if (ixgbe_set_dcb_queues(adapter))
 		goto done;
 
 #endif
+	if (ixgbe_set_fdir_queues(adapter))
+		goto done;
+
 	if (ixgbe_set_rss_queues(adapter))
 		goto done;
 
@@ -2778,9 +3215,6 @@
 		adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
 		kfree(adapter->msix_entries);
 		adapter->msix_entries = NULL;
-		adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
-		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
-		ixgbe_set_num_queues(adapter);
 	} else {
 		adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */
 		/*
@@ -2902,6 +3336,69 @@
 #endif
 
 /**
+ * ixgbe_cache_ring_fdir - Descriptor ring to register mapping for Flow Director
+ * @adapter: board private structure to initialize
+ *
+ * Cache the descriptor ring offsets for Flow Director to the assigned rings.
+ *
+ **/
+static bool inline ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
+{
+	int i;
+	bool ret = false;
+
+	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED &&
+	    ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+	     (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) {
+		for (i = 0; i < adapter->num_rx_queues; i++)
+			adapter->rx_ring[i].reg_idx = i;
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			adapter->tx_ring[i].reg_idx = i;
+		ret = true;
+	}
+
+	return ret;
+}
+
+#ifdef IXGBE_FCOE
+/**
+ * ixgbe_cache_ring_fcoe - Descriptor ring to register mapping for the FCoE
+ * @adapter: board private structure to initialize
+ *
+ * Cache the descriptor ring offsets for FCoE mode to the assigned rings.
+ *
+ */
+static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
+{
+	int i, fcoe_i = 0;
+	bool ret = false;
+	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
+
+	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+#ifdef CONFIG_IXGBE_DCB
+		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+			ixgbe_cache_ring_dcb(adapter);
+			fcoe_i = adapter->rx_ring[0].reg_idx + 1;
+		}
+#endif /* CONFIG_IXGBE_DCB */
+		if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
+			if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+			    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+				ixgbe_cache_ring_fdir(adapter);
+			else
+				ixgbe_cache_ring_rss(adapter);
+
+			fcoe_i = f->mask;
+		}
+		for (i = 0; i < f->indices; i++, fcoe_i++)
+			adapter->rx_ring[f->mask + i].reg_idx = fcoe_i;
+		ret = true;
+	}
+	return ret;
+}
+
+#endif /* IXGBE_FCOE */
+/**
  * ixgbe_cache_ring_register - Descriptor ring to register mapping
  * @adapter: board private structure to initialize
  *
@@ -2918,11 +3415,19 @@
 	adapter->rx_ring[0].reg_idx = 0;
 	adapter->tx_ring[0].reg_idx = 0;
 
+#ifdef IXGBE_FCOE
+	if (ixgbe_cache_ring_fcoe(adapter))
+		return;
+
+#endif /* IXGBE_FCOE */
 #ifdef CONFIG_IXGBE_DCB
 	if (ixgbe_cache_ring_dcb(adapter))
 		return;
 
 #endif
+	if (ixgbe_cache_ring_fdir(adapter))
+		return;
+
 	if (ixgbe_cache_ring_rss(adapter))
 		return;
 }
@@ -3004,31 +3509,23 @@
 	 * mean we disable MSI-X capabilities of the adapter. */
 	adapter->msix_entries = kcalloc(v_budget,
 	                                sizeof(struct msix_entry), GFP_KERNEL);
-	if (!adapter->msix_entries) {
-		adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
-		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
-		ixgbe_set_num_queues(adapter);
-		kfree(adapter->tx_ring);
-		kfree(adapter->rx_ring);
-		err = ixgbe_alloc_queues(adapter);
-		if (err) {
-			DPRINTK(PROBE, ERR, "Unable to allocate memory "
-			        "for queues\n");
-			goto out;
-		}
-
-		goto try_msi;
-	}
+	if (adapter->msix_entries) {
+		for (vector = 0; vector < v_budget; vector++)
+			adapter->msix_entries[vector].entry = vector;
 
-	for (vector = 0; vector < v_budget; vector++)
-		adapter->msix_entries[vector].entry = vector;
+		ixgbe_acquire_msix_vectors(adapter, v_budget);
 
-	ixgbe_acquire_msix_vectors(adapter, v_budget);
+		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+			goto out;
+	}
 
-	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
-		goto out;
+	adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+	adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+	adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+	adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+	adapter->atr_sample_rate = 0;
+	ixgbe_set_num_queues(adapter);
 
-try_msi:
 	err = pci_enable_msi(adapter->pdev);
 	if (!err) {
 		adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
@@ -3043,6 +3540,79 @@
 	return err;
 }
 
+/**
+ * ixgbe_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one q_vector per queue interrupt.  If allocation fails we
+ * return -ENOMEM.
+ **/
+static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
+{
+	int q_idx, num_q_vectors;
+	struct ixgbe_q_vector *q_vector;
+	int napi_vectors;
+	int (*poll)(struct napi_struct *, int);
+
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+		napi_vectors = adapter->num_rx_queues;
+		poll = &ixgbe_clean_rxtx_many;
+	} else {
+		num_q_vectors = 1;
+		napi_vectors = 1;
+		poll = &ixgbe_poll;
+	}
+
+	for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+		q_vector = kzalloc(sizeof(struct ixgbe_q_vector), GFP_KERNEL);
+		if (!q_vector)
+			goto err_out;
+		q_vector->adapter = adapter;
+		q_vector->eitr = adapter->eitr_param;
+		q_vector->v_idx = q_idx;
+		netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
+		adapter->q_vector[q_idx] = q_vector;
+	}
+
+	return 0;
+
+err_out:
+	while (q_idx) {
+		q_idx--;
+		q_vector = adapter->q_vector[q_idx];
+		netif_napi_del(&q_vector->napi);
+		kfree(q_vector);
+		adapter->q_vector[q_idx] = NULL;
+	}
+	return -ENOMEM;
+}
+
+/**
+ * ixgbe_free_q_vectors - Free memory allocated for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function frees the memory allocated to the q_vectors.  In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter)
+{
+	int q_idx, num_q_vectors;
+
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+		num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+	else
+		num_q_vectors = 1;
+
+	for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+		struct ixgbe_q_vector *q_vector = adapter->q_vector[q_idx];
+		adapter->q_vector[q_idx] = NULL;
+		netif_napi_del(&q_vector->napi);
+		kfree(q_vector);
+	}
+}
+
 void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
 {
 	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
@@ -3074,18 +3644,25 @@
 	/* Number of supported queues */
 	ixgbe_set_num_queues(adapter);
 
-	err = ixgbe_alloc_queues(adapter);
-	if (err) {
-		DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
-		goto err_alloc_queues;
-	}
-
 	err = ixgbe_set_interrupt_capability(adapter);
 	if (err) {
 		DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n");
 		goto err_set_interrupt;
 	}
 
+	err = ixgbe_alloc_q_vectors(adapter);
+	if (err) {
+		DPRINTK(PROBE, ERR, "Unable to allocate memory for queue "
+		        "vectors\n");
+		goto err_alloc_q_vectors;
+	}
+
+	err = ixgbe_alloc_queues(adapter);
+	if (err) {
+		DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+		goto err_alloc_queues;
+	}
+
 	DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, "
 	        "Tx Queue count = %u\n",
 	        (adapter->num_rx_queues > 1) ? "Enabled" :
@@ -3095,11 +3672,30 @@
 
 	return 0;
 
+err_alloc_queues:
+	ixgbe_free_q_vectors(adapter);
+err_alloc_q_vectors:
+	ixgbe_reset_interrupt_capability(adapter);
 err_set_interrupt:
+	return err;
+}
+
+/**
+ * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings
+ * @adapter: board private structure to clear interrupt scheme on
+ *
+ * We go through and clear interrupt specific resources and reset the structure
+ * to pre-load conditions
+ **/
+void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
+{
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
-err_alloc_queues:
-	return err;
+	adapter->tx_ring = NULL;
+	adapter->rx_ring = NULL;
+
+	ixgbe_free_q_vectors(adapter);
+	ixgbe_reset_interrupt_capability(adapter);
 }
 
 /**
@@ -3131,14 +3727,15 @@
 	if ((hw->phy.type == ixgbe_phy_nl) &&
 	    (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
 		s32 ret = hw->phy.ops.identify_sfp(hw);
-		if (ret)
+		if (ret == IXGBE_ERR_SFP_NOT_PRESENT)
 			goto reschedule;
 		ret = hw->phy.ops.reset(hw);
 		if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-			DPRINTK(PROBE, ERR, "failed to initialize because an "
-			        "unsupported SFP+ module type was detected.\n"
-			        "Reload the driver after installing a "
-			        "supported module.\n");
+			dev_err(&adapter->pdev->dev, "failed to initialize "
+				"because an unsupported SFP+ module type "
+				"was detected.\n"
+				"Reload the driver after installing a "
+				"supported module.\n");
 			unregister_netdev(adapter->netdev);
 		} else {
 			DPRINTK(PROBE, INFO, "detected SFP+: %d\n",
@@ -3185,10 +3782,25 @@
 	adapter->ring_feature[RING_F_RSS].indices = rss;
 	adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
 	adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
-	if (hw->mac.type == ixgbe_mac_82598EB)
+	if (hw->mac.type == ixgbe_mac_82598EB) {
+		if (hw->device_id == IXGBE_DEV_ID_82598AT)
+			adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
 		adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598;
-	else if (hw->mac.type == ixgbe_mac_82599EB)
+	} else if (hw->mac.type == ixgbe_mac_82599EB) {
 		adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
+		adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
+		adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
+		adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		adapter->ring_feature[RING_F_FDIR].indices =
+		                                         IXGBE_MAX_FDIR_INDICES;
+		adapter->atr_sample_rate = 20;
+		adapter->fdir_pballoc = 0;
+#ifdef IXGBE_FCOE
+		adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
+		adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+		adapter->ring_feature[RING_F_FCOE].indices = 0;
+#endif /* IXGBE_FCOE */
+	}
 
 #ifdef CONFIG_IXGBE_DCB
 	/* Configure DCB traffic classes */
@@ -3203,6 +3815,7 @@
 	adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
 	adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
 	adapter->dcb_cfg.rx_pba_cfg = pba_equal;
+	adapter->dcb_cfg.pfc_mode_enable = false;
 	adapter->dcb_cfg.round_robin_enable = false;
 	adapter->dcb_set_bitmap = 0x00;
 	ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
@@ -3213,6 +3826,9 @@
 	/* default flow control settings */
 	hw->fc.requested_mode = ixgbe_fc_full;
 	hw->fc.current_mode = ixgbe_fc_full;	/* init for ethtool output */
+#ifdef CONFIG_DCB
+	adapter->last_lfc_mode = hw->fc.current_mode;
+#endif
 	hw->fc.high_water = IXGBE_DEFAULT_FCRTH;
 	hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
 	hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
@@ -3503,6 +4119,8 @@
 	if (test_bit(__IXGBE_TESTING, &adapter->state))
 		return -EBUSY;
 
+	netif_carrier_off(netdev);
+
 	/* allocate transmit descriptors */
 	err = ixgbe_setup_all_tx_resources(adapter);
 	if (err)
@@ -3515,8 +4133,6 @@
 
 	ixgbe_configure(adapter);
 
-	ixgbe_napi_add_all(adapter);
-
 	err = ixgbe_request_irq(adapter);
 	if (err)
 		goto err_req_irq;
@@ -3568,55 +4184,6 @@
 	return 0;
 }
 
-/**
- * ixgbe_napi_add_all - prep napi structs for use
- * @adapter: private struct
- *
- * helper function to napi_add each possible q_vector->napi
- */
-void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
-{
-	int q_idx, q_vectors;
-	struct net_device *netdev = adapter->netdev;
-	int (*poll)(struct napi_struct *, int);
-
-	/* check if we already have our netdev->napi_list populated */
-	if (&netdev->napi_list != netdev->napi_list.next)
-		return;
-
-	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
-		poll = &ixgbe_clean_rxonly;
-		/* Only enable as many vectors as we have rx queues. */
-		q_vectors = adapter->num_rx_queues;
-	} else {
-		poll = &ixgbe_poll;
-		/* only one q_vector for legacy modes */
-		q_vectors = 1;
-	}
-
-	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
-		struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx];
-		netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
-	}
-}
-
-void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
-{
-	int q_idx;
-	int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-
-	/* legacy and MSI only use one vector */
-	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
-		q_vectors = 1;
-
-	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
-		struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx];
-		if (!q_vector->rxr_count)
-			continue;
-		netif_napi_del(&q_vector->napi);
-	}
-}
-
 #ifdef CONFIG_PM
 static int ixgbe_resume(struct pci_dev *pdev)
 {
@@ -3626,7 +4193,8 @@
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
-	err = pci_enable_device(pdev);
+
+	err = pci_enable_device_mem(pdev);
 	if (err) {
 		printk(KERN_ERR "ixgbe: Cannot enable PCI device from "
 				"suspend\n");
@@ -3634,8 +4202,7 @@
 	}
 	pci_set_master(pdev);
 
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
+	pci_wake_from_d3(pdev, false);
 
 	err = ixgbe_init_interrupt_scheme(adapter);
 	if (err) {
@@ -3679,11 +4246,7 @@
 		ixgbe_free_all_tx_resources(adapter);
 		ixgbe_free_all_rx_resources(adapter);
 	}
-	ixgbe_reset_interrupt_capability(adapter);
-	ixgbe_napi_del_all(adapter);
-	INIT_LIST_HEAD(&netdev->napi_list);
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
+	ixgbe_clear_interrupt_scheme(adapter);
 
 #ifdef CONFIG_PM
 	retval = pci_save_state(pdev);
@@ -3711,13 +4274,10 @@
 		IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
 	}
 
-	if (wufc && hw->mac.type == ixgbe_mac_82599EB) {
-		pci_enable_wake(pdev, PCI_D3hot, 1);
-		pci_enable_wake(pdev, PCI_D3cold, 1);
-	} else {
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_enable_wake(pdev, PCI_D3cold, 0);
-	}
+	if (wufc && hw->mac.type == ixgbe_mac_82599EB)
+		pci_wake_from_d3(pdev, true);
+	else
+		pci_wake_from_d3(pdev, false);
 
 	*enable_wake = !!wufc;
 
@@ -3772,9 +4332,13 @@
 	u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
 
 	if (hw->mac.type == ixgbe_mac_82599EB) {
+		u64 rsc_count = 0;
 		for (i = 0; i < 16; i++)
 			adapter->hw_rx_no_dma_resources +=
 			                     IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+		for (i = 0; i < adapter->num_rx_queues; i++)
+			rsc_count += adapter->rx_ring[i].rsc_count;
+		adapter->rsc_count = rsc_count;
 	}
 
 	adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
@@ -3821,6 +4385,16 @@
 		IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */
 		adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
 		adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+		adapter->stats.fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
+		adapter->stats.fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+#ifdef IXGBE_FCOE
+		adapter->stats.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
+		adapter->stats.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
+		adapter->stats.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
+		adapter->stats.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
+		adapter->stats.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
+		adapter->stats.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
+#endif /* IXGBE_FCOE */
 	} else {
 		adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
 		adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
@@ -3888,64 +4462,43 @@
 {
 	struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
 	struct ixgbe_hw *hw = &adapter->hw;
+	u64 eics = 0;
+	int i;
 
-	/* Do the watchdog outside of interrupt context due to the lovely
-	 * delays that some of the newer hardware requires */
-	if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
-		u64 eics = 0;
-		int i;
+	/*
+	 *  Do the watchdog outside of interrupt context due to the lovely
+	 * delays that some of the newer hardware requires
+	 */
 
-		for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++)
-			eics |= (1 << i);
+	if (test_bit(__IXGBE_DOWN, &adapter->state))
+		goto watchdog_short_circuit;
 
-		/* Cause software interrupt to ensure rx rings are cleaned */
-		switch (hw->mac.type) {
-		case ixgbe_mac_82598EB:
-			if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
-				IXGBE_WRITE_REG(hw, IXGBE_EICS, (u32)eics);
-			} else {
-				/*
-				 * for legacy and MSI interrupts don't set any
-				 * bits that are enabled for EIAM, because this
-				 * operation would set *both* EIMS and EICS for
-				 * any bit in EIAM
-				 */
-				IXGBE_WRITE_REG(hw, IXGBE_EICS,
-				     (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
-			}
-			break;
-		case ixgbe_mac_82599EB:
-			if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
-				/*
-				 * EICS(0..15) first 0-15 q vectors
-				 * EICS[1] (16..31) q vectors 16-31
-				 * EICS[2] (0..31) q vectors 32-63
-				 */
-				IXGBE_WRITE_REG(hw, IXGBE_EICS,
-				                (u32)(eics & 0xFFFF));
-				IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(1),
-				                (u32)(eics & 0xFFFF0000));
-				IXGBE_WRITE_REG(hw, IXGBE_EICS_EX(2),
-				                (u32)(eics >> 32));
-			} else {
-				/*
-				 * for legacy and MSI interrupts don't set any
-				 * bits that are enabled for EIAM, because this
-				 * operation would set *both* EIMS and EICS for
-				 * any bit in EIAM
-				 */
-				IXGBE_WRITE_REG(hw, IXGBE_EICS,
-				     (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
-			}
-			break;
-		default:
-			break;
-		}
-		/* Reset the timer */
-		mod_timer(&adapter->watchdog_timer,
-		          round_jiffies(jiffies + 2 * HZ));
+	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+		/*
+		 * for legacy and MSI interrupts don't set any bits
+		 * that are enabled for EIAM, because this operation
+		 * would set *both* EIMS and EICS for any bit in EIAM
+		 */
+		IXGBE_WRITE_REG(hw, IXGBE_EICS,
+			(IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
+		goto watchdog_reschedule;
+	}
+
+	/* get one bit for every active tx/rx interrupt vector */
+	for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
+		struct ixgbe_q_vector *qv = adapter->q_vector[i];
+		if (qv->rxr_count || qv->txr_count)
+			eics |= ((u64)1 << i);
 	}
 
+	/* Cause software interrupt to ensure rx rings are cleaned */
+	ixgbe_irq_rearm_queues(adapter, eics);
+
+watchdog_reschedule:
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
+
+watchdog_short_circuit:
 	schedule_work(&adapter->watchdog_task);
 }
 
@@ -3962,7 +4515,8 @@
 	u32 autoneg;
 
 	adapter->flags |= IXGBE_FLAG_IN_SFP_LINK_TASK;
-	if (hw->mac.ops.get_link_capabilities)
+	autoneg = hw->phy.autoneg_advertised;
+	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
 		hw->mac.ops.get_link_capabilities(hw, &autoneg,
 		                                  &hw->mac.autoneg);
 	if (hw->mac.ops.setup_link_speed)
@@ -3984,10 +4538,17 @@
 	u32 err;
 
 	adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK;
+
+	/* Time for electrical oscillations to settle down */
+	msleep(100);
 	err = hw->phy.ops.identify_sfp(hw);
+
 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-		DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err);
-		ixgbe_down(adapter);
+		dev_err(&adapter->pdev->dev, "failed to initialize because "
+			"an unsupported SFP+ module type was detected.\n"
+			"Reload the driver after installing a supported "
+			"module.\n");
+		unregister_netdev(adapter->netdev);
 		return;
 	}
 	hw->mac.ops.setup_sfp(hw);
@@ -3999,6 +4560,30 @@
 }
 
 /**
+ * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table
+ * @work: pointer to work_struct containing our data
+ **/
+static void ixgbe_fdir_reinit_task(struct work_struct *work)
+{
+	struct ixgbe_adapter *adapter = container_of(work,
+	                                             struct ixgbe_adapter,
+	                                             fdir_reinit_task);
+	struct ixgbe_hw *hw = &adapter->hw;
+	int i;
+
+	if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			set_bit(__IXGBE_FDIR_INIT_DONE,
+			        &(adapter->tx_ring[i].reinit_state));
+	} else {
+		DPRINTK(PROBE, ERR, "failed to finish FDIR re-initialization, "
+		        "ignored adding FDIR ATR filters \n");
+	}
+	/* Done FDIR Re-initialization, enable transmits */
+	netif_tx_start_all_queues(adapter->netdev);
+}
+
+/**
  * ixgbe_watchdog_task - worker thread to bring link up
  * @work: pointer to work_struct containing our data
  **/
@@ -4011,16 +4596,32 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 link_speed = adapter->link_speed;
 	bool link_up = adapter->link_up;
+	int i;
+	struct ixgbe_ring *tx_ring;
+	int some_tx_pending = 0;
 
 	adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
 
 	if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
 		hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
+		if (link_up) {
+#ifdef CONFIG_DCB
+			if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+				for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+					hw->mac.ops.fc_enable(hw, i);
+			} else {
+				hw->mac.ops.fc_enable(hw, 0);
+			}
+#else
+			hw->mac.ops.fc_enable(hw, 0);
+#endif
+		}
+
 		if (link_up ||
 		    time_after(jiffies, (adapter->link_check_timeout +
 		                         IXGBE_TRY_LINK_TIMEOUT))) {
-			IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
 			adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
+			IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
 		}
 		adapter->link_up = link_up;
 		adapter->link_speed = link_speed;
@@ -4068,6 +4669,25 @@
 		}
 	}
 
+	if (!netif_carrier_ok(netdev)) {
+		for (i = 0; i < adapter->num_tx_queues; i++) {
+			tx_ring = &adapter->tx_ring[i];
+			if (tx_ring->next_to_use != tx_ring->next_to_clean) {
+				some_tx_pending = 1;
+				break;
+			}
+		}
+
+		if (some_tx_pending) {
+			/* We've lost link, so the controller stops DMA,
+			 * but we've got queued Tx work that's never going
+			 * to get done, so reset controller to flush Tx.
+			 * (Do the reset outside of interrupt context).
+			 */
+			 schedule_work(&adapter->reset_task);
+		}
+	}
+
 	ixgbe_update_stats(adapter);
 	adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK;
 }
@@ -4196,12 +4816,18 @@
 				if (ip_hdr(skb)->protocol == IPPROTO_TCP)
 					type_tucmd_mlhl |=
 					        IXGBE_ADVTXD_TUCMD_L4T_TCP;
+				else if (ip_hdr(skb)->protocol == IPPROTO_SCTP)
+					type_tucmd_mlhl |=
+					        IXGBE_ADVTXD_TUCMD_L4T_SCTP;
 				break;
 			case cpu_to_be16(ETH_P_IPV6):
 				/* XXX what about other V6 headers?? */
 				if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
 					type_tucmd_mlhl |=
 					        IXGBE_ADVTXD_TUCMD_L4T_TCP;
+				else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP)
+					type_tucmd_mlhl |=
+					        IXGBE_ADVTXD_TUCMD_L4T_SCTP;
 				break;
 			default:
 				if (unlikely(net_ratelimit())) {
@@ -4234,10 +4860,12 @@
 
 static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
                         struct ixgbe_ring *tx_ring,
-                        struct sk_buff *skb, unsigned int first)
+                        struct sk_buff *skb, u32 tx_flags,
+                        unsigned int first)
 {
 	struct ixgbe_tx_buffer *tx_buffer_info;
-	unsigned int len = skb_headlen(skb);
+	unsigned int len;
+	unsigned int total = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
 	unsigned int f;
@@ -4252,16 +4880,22 @@
 
 	map = skb_shinfo(skb)->dma_maps;
 
+	if (tx_flags & IXGBE_TX_FLAGS_FCOE)
+		/* excluding fcoe_crc_eof for FCoE */
+		total -= sizeof(struct fcoe_crc_eof);
+
+	len = min(skb_headlen(skb), total);
 	while (len) {
 		tx_buffer_info = &tx_ring->tx_buffer_info[i];
 		size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
 
 		tx_buffer_info->length = size;
-		tx_buffer_info->dma = map[0] + offset;
+		tx_buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
 		tx_buffer_info->time_stamp = jiffies;
 		tx_buffer_info->next_to_watch = i;
 
 		len -= size;
+		total -= size;
 		offset += size;
 		count++;
 
@@ -4276,7 +4910,7 @@
 		struct skb_frag_struct *frag;
 
 		frag = &skb_shinfo(skb)->frags[f];
-		len = frag->size;
+		len = min((unsigned int)frag->size, total);
 		offset = 0;
 
 		while (len) {
@@ -4288,14 +4922,17 @@
 			size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
 
 			tx_buffer_info->length = size;
-			tx_buffer_info->dma = map[f + 1] + offset;
+			tx_buffer_info->dma = map[f] + offset;
 			tx_buffer_info->time_stamp = jiffies;
 			tx_buffer_info->next_to_watch = i;
 
 			len -= size;
+			total -= size;
 			offset += size;
 			count++;
 		}
+		if (total == 0)
+			break;
 	}
 
 	tx_ring->tx_buffer_info[i].skb = skb;
@@ -4337,6 +4974,13 @@
 		olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
 		                 IXGBE_ADVTXD_POPTS_SHIFT;
 
+	if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
+		olinfo_status |= IXGBE_ADVTXD_CC;
+		olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
+		if (tx_flags & IXGBE_TX_FLAGS_FSO)
+			cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
+	}
+
 	olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT);
 
 	i = tx_ring->next_to_use;
@@ -4366,6 +5010,58 @@
 	writel(i, adapter->hw.hw_addr + tx_ring->tail);
 }
 
+static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
+	              int queue, u32 tx_flags)
+{
+	/* Right now, we support IPv4 only */
+	struct ixgbe_atr_input atr_input;
+	struct tcphdr *th;
+	struct udphdr *uh;
+	struct iphdr *iph = ip_hdr(skb);
+	struct ethhdr *eth = (struct ethhdr *)skb->data;
+	u16 vlan_id, src_port, dst_port, flex_bytes;
+	u32 src_ipv4_addr, dst_ipv4_addr;
+	u8 l4type = 0;
+
+	/* check if we're UDP or TCP */
+	if (iph->protocol == IPPROTO_TCP) {
+		th = tcp_hdr(skb);
+		src_port = th->source;
+		dst_port = th->dest;
+		l4type |= IXGBE_ATR_L4TYPE_TCP;
+		/* l4type IPv4 type is 0, no need to assign */
+	} else if(iph->protocol == IPPROTO_UDP) {
+		uh = udp_hdr(skb);
+		src_port = uh->source;
+		dst_port = uh->dest;
+		l4type |= IXGBE_ATR_L4TYPE_UDP;
+		/* l4type IPv4 type is 0, no need to assign */
+	} else {
+		/* Unsupported L4 header, just bail here */
+		return;
+	}
+
+	memset(&atr_input, 0, sizeof(struct ixgbe_atr_input));
+
+	vlan_id = (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK) >>
+	           IXGBE_TX_FLAGS_VLAN_SHIFT;
+	src_ipv4_addr = iph->saddr;
+	dst_ipv4_addr = iph->daddr;
+	flex_bytes = eth->h_proto;
+
+	ixgbe_atr_set_vlan_id_82599(&atr_input, vlan_id);
+	ixgbe_atr_set_src_port_82599(&atr_input, dst_port);
+	ixgbe_atr_set_dst_port_82599(&atr_input, src_port);
+	ixgbe_atr_set_flex_byte_82599(&atr_input, flex_bytes);
+	ixgbe_atr_set_l4type_82599(&atr_input, l4type);
+	/* src and dst are inverted, think how the receiver sees them */
+	ixgbe_atr_set_src_ipv4_82599(&atr_input, dst_ipv4_addr);
+	ixgbe_atr_set_dst_ipv4_82599(&atr_input, src_ipv4_addr);
+
+	/* This assumes the Rx queue and Tx queue are bound to the same CPU */
+	ixgbe_fdir_add_signature_filter_82599(&adapter->hw, &atr_input, queue);
+}
+
 static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
                                  struct ixgbe_ring *tx_ring, int size)
 {
@@ -4400,6 +5096,9 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
+		return smp_processor_id();
+
 	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
 		return 0;  /* All traffic should default to class 0 */
 
@@ -4417,9 +5116,6 @@
 	int count = 0;
 	unsigned int f;
 
-	r_idx = skb->queue_mapping;
-	tx_ring = &adapter->tx_ring[r_idx];
-
 	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
 		tx_flags |= vlan_tx_tag_get(skb);
 		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
@@ -4429,14 +5125,28 @@
 		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
 	} else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		tx_flags |= (skb->queue_mapping << 13);
-		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
-		tx_flags |= IXGBE_TX_FLAGS_VLAN;
+		if (skb->priority != TC_PRIO_CONTROL) {
+			tx_flags |= (skb->queue_mapping << 13);
+			tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
+			tx_flags |= IXGBE_TX_FLAGS_VLAN;
+		} else {
+			skb->queue_mapping =
+				adapter->ring_feature[RING_F_DCB].indices-1;
+		}
 	}
-	/* three things can cause us to need a context descriptor */
+
+	r_idx = skb->queue_mapping;
+	tx_ring = &adapter->tx_ring[r_idx];
+
+	if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
+	    (skb->protocol == htons(ETH_P_FCOE)))
+		tx_flags |= IXGBE_TX_FLAGS_FCOE;
+
+	/* four things can cause us to need a context descriptor */
 	if (skb_is_gso(skb) ||
 	    (skb->ip_summed == CHECKSUM_PARTIAL) ||
-	    (tx_flags & IXGBE_TX_FLAGS_VLAN))
+	    (tx_flags & IXGBE_TX_FLAGS_VLAN) ||
+	    (tx_flags & IXGBE_TX_FLAGS_FCOE))
 		count++;
 
 	count += TXD_USE_COUNT(skb_headlen(skb));
@@ -4448,27 +5158,49 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	if (skb->protocol == htons(ETH_P_IP))
-		tx_flags |= IXGBE_TX_FLAGS_IPV4;
 	first = tx_ring->next_to_use;
-	tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len);
-	if (tso < 0) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (tso)
-		tx_flags |= IXGBE_TX_FLAGS_TSO;
-	else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) &&
-	         (skb->ip_summed == CHECKSUM_PARTIAL))
-		tx_flags |= IXGBE_TX_FLAGS_CSUM;
+	if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
+#ifdef IXGBE_FCOE
+		/* setup tx offload for FCoE */
+		tso = ixgbe_fso(adapter, tx_ring, skb, tx_flags, &hdr_len);
+		if (tso < 0) {
+			dev_kfree_skb_any(skb);
+			return NETDEV_TX_OK;
+		}
+		if (tso)
+			tx_flags |= IXGBE_TX_FLAGS_FSO;
+#endif /* IXGBE_FCOE */
+	} else {
+		if (skb->protocol == htons(ETH_P_IP))
+			tx_flags |= IXGBE_TX_FLAGS_IPV4;
+		tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len);
+		if (tso < 0) {
+			dev_kfree_skb_any(skb);
+			return NETDEV_TX_OK;
+		}
 
-	count = ixgbe_tx_map(adapter, tx_ring, skb, first);
+		if (tso)
+			tx_flags |= IXGBE_TX_FLAGS_TSO;
+		else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) &&
+			 (skb->ip_summed == CHECKSUM_PARTIAL))
+			tx_flags |= IXGBE_TX_FLAGS_CSUM;
+	}
 
+	count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first);
 	if (count) {
+		/* add the ATR filter if ATR is on */
+		if (tx_ring->atr_sample_rate) {
+			++tx_ring->atr_count;
+			if ((tx_ring->atr_count >= tx_ring->atr_sample_rate) &&
+		             test_bit(__IXGBE_FDIR_INIT_DONE,
+                                      &tx_ring->reinit_state)) {
+				ixgbe_atr(adapter, skb, tx_ring->queue_index,
+				          tx_flags);
+				tx_ring->atr_count = 0;
+			}
+		}
 		ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
 		               hdr_len);
-		netdev->trans_start = jiffies;
 		ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED);
 
 	} else {
@@ -4519,6 +5251,82 @@
 	return 0;
 }
 
+static int
+ixgbe_mdio_read(struct net_device *netdev, int prtad, int devad, u16 addr)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
+	u16 value;
+	int rc;
+
+	if (prtad != hw->phy.mdio.prtad)
+		return -EINVAL;
+	rc = hw->phy.ops.read_reg(hw, addr, devad, &value);
+	if (!rc)
+		rc = value;
+	return rc;
+}
+
+static int ixgbe_mdio_write(struct net_device *netdev, int prtad, int devad,
+			    u16 addr, u16 value)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
+
+	if (prtad != hw->phy.mdio.prtad)
+		return -EINVAL;
+	return hw->phy.ops.write_reg(hw, addr, devad, value);
+}
+
+static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+	return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd);
+}
+
+/**
+ * ixgbe_add_sanmac_netdev - Add the SAN MAC address to the corresponding
+ * netdev->dev_addrs
+ * @netdev: network interface device structure
+ *
+ * Returns non-zero on failure
+ **/
+static int ixgbe_add_sanmac_netdev(struct net_device *dev)
+{
+	int err = 0;
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ixgbe_mac_info *mac = &adapter->hw.mac;
+
+	if (is_valid_ether_addr(mac->san_addr)) {
+		rtnl_lock();
+		err = dev_addr_add(dev, mac->san_addr, NETDEV_HW_ADDR_T_SAN);
+		rtnl_unlock();
+	}
+	return err;
+}
+
+/**
+ * ixgbe_del_sanmac_netdev - Removes the SAN MAC address to the corresponding
+ * netdev->dev_addrs
+ * @netdev: network interface device structure
+ *
+ * Returns non-zero on failure
+ **/
+static int ixgbe_del_sanmac_netdev(struct net_device *dev)
+{
+	int err = 0;
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ixgbe_mac_info *mac = &adapter->hw.mac;
+
+	if (is_valid_ether_addr(mac->san_addr)) {
+		rtnl_lock();
+		err = dev_addr_del(dev, mac->san_addr, NETDEV_HW_ADDR_T_SAN);
+		rtnl_unlock();
+	}
+	return err;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /*
  * Polling 'interrupt' - used by things like netconsole to send skbs
@@ -4528,12 +5336,19 @@
 static void ixgbe_netpoll(struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	int i;
 
-	disable_irq(adapter->pdev->irq);
 	adapter->flags |= IXGBE_FLAG_IN_NETPOLL;
-	ixgbe_intr(adapter->pdev->irq, netdev);
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+		for (i = 0; i < num_q_vectors; i++) {
+			struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
+			ixgbe_msix_clean_many(0, q_vector);
+		}
+	} else {
+		ixgbe_intr(adapter->pdev->irq, netdev);
+	}
 	adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL;
-	enable_irq(adapter->pdev->irq);
 }
 #endif
 
@@ -4552,9 +5367,14 @@
 	.ndo_vlan_rx_register	= ixgbe_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= ixgbe_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= ixgbe_vlan_rx_kill_vid,
+	.ndo_do_ioctl		= ixgbe_ioctl,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ixgbe_netpoll,
 #endif
+#ifdef IXGBE_FCOE
+	.ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get,
+	.ndo_fcoe_ddp_done = ixgbe_fcoe_ddp_put,
+#endif /* IXGBE_FCOE */
 };
 
 /**
@@ -4577,9 +5397,12 @@
 	const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
 	static int cards_found;
 	int i, err, pci_using_dac;
+#ifdef IXGBE_FCOE
+	u16 device_caps;
+#endif
 	u32 part_num, eec;
 
-	err = pci_enable_device(pdev);
+	err = pci_enable_device_mem(pdev);
 	if (err)
 		return err;
 
@@ -4599,9 +5422,11 @@
 		pci_using_dac = 0;
 	}
 
-	err = pci_request_regions(pdev, ixgbe_driver_name);
+	err = pci_request_selected_regions(pdev, pci_select_bars(pdev,
+	                                   IORESOURCE_MEM), ixgbe_driver_name);
 	if (err) {
-		dev_err(&pdev->dev, "pci_request_regions failed 0x%x\n", err);
+		dev_err(&pdev->dev,
+		        "pci_request_selected_regions failed 0x%x\n", err);
 		goto err_pci_reg;
 	}
 
@@ -4665,6 +5490,13 @@
 	/* PHY */
 	memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops));
 	hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+	/* ixgbe_identify_phy_generic will set prtad and mmds properly */
+	hw->phy.mdio.prtad = MDIO_PRTAD_NONE;
+	hw->phy.mdio.mmds = 0;
+	hw->phy.mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+	hw->phy.mdio.dev = netdev;
+	hw->phy.mdio.mdio_read = ixgbe_mdio_read;
+	hw->phy.mdio.mdio_write = ixgbe_mdio_write;
 
 	/* set up this timer and work struct before calling get_invariants
 	 * which might start the timer
@@ -4682,29 +5514,44 @@
 	INIT_WORK(&adapter->sfp_config_module_task,
 	          ixgbe_sfp_config_module_task);
 
-	err = ii->get_invariants(hw);
-	if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
-		/* start a kernel thread to watch for a module to arrive */
-		set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
-		mod_timer(&adapter->sfp_timer,
-		          round_jiffies(jiffies + (2 * HZ)));
-		err = 0;
-	} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-		DPRINTK(PROBE, ERR, "failed to load because an "
-		        "unsupported SFP+ module type was detected.\n");
-		goto err_hw_init;
-	} else if (err) {
-		goto err_hw_init;
-	}
+	ii->get_invariants(hw);
 
 	/* setup the private structure */
 	err = ixgbe_sw_init(adapter);
 	if (err)
 		goto err_sw_init;
 
+	/*
+	 * If there is a fan on this device and it has failed log the
+	 * failure.
+	 */
+	if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
+		u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		if (esdp & IXGBE_ESDP_SDP1)
+			DPRINTK(PROBE, CRIT,
+				"Fan has stopped, replace the adapter\n");
+	}
+
 	/* reset_hw fills in the perm_addr as well */
 	err = hw->mac.ops.reset_hw(hw);
-	if (err) {
+	if (err == IXGBE_ERR_SFP_NOT_PRESENT &&
+	    hw->mac.type == ixgbe_mac_82598EB) {
+		/*
+		 * Start a kernel thread to watch for a module to arrive.
+		 * Only do this for 82598, since 82599 will generate
+		 * interrupts on module arrival.
+		 */
+		set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
+		mod_timer(&adapter->sfp_timer,
+			  round_jiffies(jiffies + (2 * HZ)));
+		err = 0;
+	} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+		dev_err(&adapter->pdev->dev, "failed to initialize because "
+			"an unsupported SFP+ module type was detected.\n"
+			"Reload the driver after installing a supported "
+			"module.\n");
+		goto err_sw_init;
+	} else if (err) {
 		dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err);
 		goto err_sw_init;
 	}
@@ -4720,6 +5567,9 @@
 	netdev->features |= NETIF_F_TSO6;
 	netdev->features |= NETIF_F_GRO;
 
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+		netdev->features |= NETIF_F_SCTP_CSUM;
+
 	netdev->vlan_features |= NETIF_F_TSO;
 	netdev->vlan_features |= NETIF_F_TSO6;
 	netdev->vlan_features |= NETIF_F_IP_CSUM;
@@ -4732,9 +5582,21 @@
 	netdev->dcbnl_ops = &dcbnl_ops;
 #endif
 
+#ifdef IXGBE_FCOE
+	if (adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) {
+		if (hw->mac.ops.get_device_caps) {
+			hw->mac.ops.get_device_caps(hw, &device_caps);
+			if (device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)
+				adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE;
+		}
+	}
+#endif /* IXGBE_FCOE */
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
+		netdev->features |= NETIF_F_LRO;
+
 	/* make sure the EEPROM is good */
 	if (hw->eeprom.ops.validate_checksum(hw, NULL) < 0) {
 		dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");
@@ -4766,14 +5628,19 @@
 	case IXGBE_DEV_ID_82599_KX4:
 		adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
 		                IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+		/* Enable ACPI wakeup in GRC */
+		IXGBE_WRITE_REG(hw, IXGBE_GRC,
+		             (IXGBE_READ_REG(hw, IXGBE_GRC) & ~IXGBE_GRC_APME));
 		break;
 	default:
 		adapter->wol = 0;
 		break;
 	}
-	device_init_wakeup(&adapter->pdev->dev, true);
 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
+	/* pick up the PCI bus settings for reporting later */
+	hw->mac.ops.get_bus_info(hw);
+
 	/* print bus type/speed/width info */
 	dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n",
 	        ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s":
@@ -4805,24 +5672,37 @@
 	hw->eeprom.ops.read(hw, 0x29, &adapter->eeprom_version);
 
 	/* reset the hardware with the new settings */
-	hw->mac.ops.start_hw(hw);
-
-	netif_carrier_off(netdev);
+	err = hw->mac.ops.start_hw(hw);
 
+	if (err == IXGBE_ERR_EEPROM_VERSION) {
+		/* We are running on a pre-production device, log a warning */
+		dev_warn(&pdev->dev, "This device is a pre-production "
+		         "adapter/LOM.  Please be aware there may be issues "
+		         "associated with your hardware.  If you are "
+		         "experiencing problems please contact your Intel or "
+		         "hardware representative who provided you with this "
+		         "hardware.\n");
+	}
 	strcpy(netdev->name, "eth%d");
 	err = register_netdev(netdev);
 	if (err)
 		goto err_register;
 
+	/* carrier off reporting is important to ethtool even BEFORE open */
+	netif_carrier_off(netdev);
+
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+		INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task);
+
 #ifdef CONFIG_IXGBE_DCA
 	if (dca_add_requester(&pdev->dev) == 0) {
 		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
-		/* always use CB2 mode, difference is masked
-		 * in the CB driver */
-		IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2);
 		ixgbe_setup_dca(adapter);
 	}
 #endif
+	/* add san mac addr to netdev */
+	ixgbe_add_sanmac_netdev(netdev);
 
 	dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n");
 	cards_found++;
@@ -4830,9 +5710,8 @@
 
 err_register:
 	ixgbe_release_hw_control(adapter);
-err_hw_init:
+	ixgbe_clear_interrupt_scheme(adapter);
 err_sw_init:
-	ixgbe_reset_interrupt_capability(adapter);
 err_eeprom:
 	clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
 	del_timer_sync(&adapter->sfp_timer);
@@ -4843,7 +5722,8 @@
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
-	pci_release_regions(pdev);
+	pci_release_selected_regions(pdev, pci_select_bars(pdev,
+	                             IORESOURCE_MEM));
 err_pci_reg:
 err_dma:
 	pci_disable_device(pdev);
@@ -4877,6 +5757,9 @@
 	cancel_work_sync(&adapter->sfp_task);
 	cancel_work_sync(&adapter->multispeed_fiber_task);
 	cancel_work_sync(&adapter->sfp_config_module_task);
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
+	    adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
+		cancel_work_sync(&adapter->fdir_reinit_task);
 	flush_scheduled_work();
 
 #ifdef CONFIG_IXGBE_DCA
@@ -4887,19 +5770,27 @@
 	}
 
 #endif
+#ifdef IXGBE_FCOE
+	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
+		ixgbe_cleanup_fcoe(adapter);
+
+#endif /* IXGBE_FCOE */
+
+	/* remove the added san mac */
+	ixgbe_del_sanmac_netdev(netdev);
+
 	if (netdev->reg_state == NETREG_REGISTERED)
 		unregister_netdev(netdev);
 
-	ixgbe_reset_interrupt_capability(adapter);
+	ixgbe_clear_interrupt_scheme(adapter);
 
 	ixgbe_release_hw_control(adapter);
 
 	iounmap(adapter->hw.hw_addr);
-	pci_release_regions(pdev);
+	pci_release_selected_regions(pdev, pci_select_bars(pdev,
+	                             IORESOURCE_MEM));
 
 	DPRINTK(PROBE, INFO, "complete\n");
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
 
 	free_netdev(netdev);
 
@@ -4927,6 +5818,9 @@
 
 	netif_device_detach(netdev);
 
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
 	if (netif_running(netdev))
 		ixgbe_down(adapter);
 	pci_disable_device(pdev);
@@ -4948,7 +5842,7 @@
 	pci_ers_result_t result;
 	int err;
 
-	if (pci_enable_device(pdev)) {
+	if (pci_enable_device_mem(pdev)) {
 		DPRINTK(PROBE, ERR,
 		        "Cannot re-enable PCI device after reset.\n");
 		result = PCI_ERS_RESULT_DISCONNECT;
@@ -4956,8 +5850,7 @@
 		pci_set_master(pdev);
 		pci_restore_state(pdev);
 
-		pci_enable_wake(pdev, PCI_D3hot, 0);
-		pci_enable_wake(pdev, PCI_D3cold, 0);
+		pci_wake_from_d3(pdev, false);
 
 		ixgbe_reset(adapter);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_phy.c linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_phy.c
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,7 +44,6 @@
 static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data);
 static bool ixgbe_get_i2c_data(u32 *i2cctl);
 static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
-static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr);
 static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
 static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
 
@@ -61,8 +60,8 @@
 
 	if (hw->phy.type == ixgbe_phy_unknown) {
 		for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
-			if (ixgbe_validate_phy_addr(hw, phy_addr)) {
-				hw->phy.addr = phy_addr;
+			hw->phy.mdio.prtad = phy_addr;
+			if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) {
 				ixgbe_get_phy_id(hw);
 				hw->phy.type =
 				        ixgbe_get_phy_type_from_id(hw->phy.id);
@@ -70,6 +69,8 @@
 				break;
 			}
 		}
+		/* clear value if nothing found */
+		hw->phy.mdio.prtad = 0;
 	} else {
 		status = 0;
 	}
@@ -78,26 +79,6 @@
 }
 
 /**
- *  ixgbe_validate_phy_addr - Determines phy address is valid
- *  @hw: pointer to hardware structure
- *
- **/
-static bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr)
-{
-	u16 phy_id = 0;
-	bool valid = false;
-
-	hw->phy.addr = phy_addr;
-	hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
-	                     IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id);
-
-	if (phy_id != 0xFFFF && phy_id != 0x0)
-		valid = true;
-
-	return valid;
-}
-
-/**
  *  ixgbe_get_phy_id - Get the phy type
  *  @hw: pointer to hardware structure
  *
@@ -108,14 +89,12 @@
 	u16 phy_id_high = 0;
 	u16 phy_id_low = 0;
 
-	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
-	                              IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+	status = hw->phy.ops.read_reg(hw, MDIO_DEVID1, MDIO_MMD_PMAPMD,
 	                              &phy_id_high);
 
 	if (status == 0) {
 		hw->phy.id = (u32)(phy_id_high << 16);
-		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW,
-		                              IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+		status = hw->phy.ops.read_reg(hw, MDIO_DEVID2, MDIO_MMD_PMAPMD,
 		                              &phy_id_low);
 		hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK);
 		hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK);
@@ -160,9 +139,8 @@
 	 * Perform soft PHY reset to the PHY_XS.
 	 * This will cause a soft reset to the PHY
 	 */
-	return hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
-	                             IXGBE_MDIO_PHY_XS_DEV_TYPE,
-	                             IXGBE_MDIO_PHY_XS_RESET);
+	return hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS,
+				     MDIO_CTRL1_RESET);
 }
 
 /**
@@ -192,7 +170,7 @@
 		/* Setup and write the address cycle command */
 		command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
 		           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-		           (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+		           (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
 		           (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
 
 		IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -223,7 +201,8 @@
 			 */
 			command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
 			           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-			           (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+			           (hw->phy.mdio.prtad <<
+				    IXGBE_MSCA_PHY_ADDR_SHIFT) |
 			           (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND));
 
 			IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -292,7 +271,7 @@
 		/* Setup and write the address cycle command */
 		command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
 		           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-		           (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+		           (hw->phy.mdio.prtad << IXGBE_MSCA_PHY_ADDR_SHIFT) |
 		           (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND));
 
 		IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -323,7 +302,8 @@
 			 */
 			command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT)  |
 			           (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-			           (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
+			           (hw->phy.mdio.prtad <<
+				    IXGBE_MSCA_PHY_ADDR_SHIFT) |
 			           (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND));
 
 			IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
@@ -365,7 +345,7 @@
 	s32 status = IXGBE_NOT_IMPLEMENTED;
 	u32 time_out;
 	u32 max_time_out = 10;
-	u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+	u16 autoneg_reg;
 
 	/*
 	 * Set advertisement settings in PHY based on autoneg_advertised
@@ -373,36 +353,31 @@
 	 * tnx devices cannot be "forced" to a autoneg 10G and fail.  But can
 	 * for a 1G.
 	 */
-	hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
-	                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
+	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg);
 
 	if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL)
-		autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */
+		autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
 	else
-		autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */
+		autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
 
-	hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG,
-	                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
+	hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg);
 
 	/* Restart PHY autonegotiation and wait for completion */
-	hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
-	                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
+	hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, &autoneg_reg);
 
-	autoneg_reg |= IXGBE_MII_RESTART;
+	autoneg_reg |= MDIO_AN_CTRL1_RESTART;
 
-	hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
-	                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg);
+	hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, autoneg_reg);
 
 	/* Wait for autonegotiation to finish */
 	for (time_out = 0; time_out < max_time_out; time_out++) {
 		udelay(10);
 		/* Restart PHY autonegotiation and wait for completion */
-		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-		                              IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
 		                              &autoneg_reg);
 
-		autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE;
-		if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) {
+		autoneg_reg &= MDIO_AN_STAT1_COMPLETE;
+		if (autoneg_reg == MDIO_AN_STAT1_COMPLETE) {
 			status = 0;
 			break;
 		}
@@ -457,23 +432,21 @@
 	s32 ret_val = 0;
 	u32 i;
 
-	hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
-	                     IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
+	hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &phy_data);
 
 	/* reset the PHY and poll for completion */
-	hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
-	                      IXGBE_MDIO_PHY_XS_DEV_TYPE,
-	                      (phy_data | IXGBE_MDIO_PHY_XS_RESET));
+	hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS,
+	                      (phy_data | MDIO_CTRL1_RESET));
 
 	for (i = 0; i < 100; i++) {
-		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
-		                     IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
-		if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0)
+		hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS,
+		                     &phy_data);
+		if ((phy_data & MDIO_CTRL1_RESET) == 0)
 			break;
 		msleep(10);
 	}
 
-	if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) {
+	if ((phy_data & MDIO_CTRL1_RESET) != 0) {
 		hw_dbg(hw, "PHY reset did not complete.\n");
 		ret_val = IXGBE_ERR_PHY;
 		goto out;
@@ -509,7 +482,7 @@
 			for (i = 0; i < edata; i++) {
 				hw->eeprom.ops.read(hw, data_offset, &eword);
 				hw->phy.ops.write_reg(hw, phy_offset,
-				                      IXGBE_TWINAX_DEV, eword);
+				                      MDIO_MMD_PMAPMD, eword);
 				hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword,
 				       phy_offset);
 				data_offset++;
@@ -552,18 +525,30 @@
 {
 	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
 	u32 vendor_oui = 0;
+	enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
 	u8 identifier = 0;
 	u8 comp_codes_1g = 0;
 	u8 comp_codes_10g = 0;
 	u8 oui_bytes[3] = {0, 0, 0};
-	u8 transmission_media = 0;
+	u8 cable_tech = 0;
 	u16 enforce_sfp = 0;
 
+	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
+		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+		status = IXGBE_ERR_SFP_NOT_PRESENT;
+		goto out;
+	}
+
 	status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
 	                                     &identifier);
 
-	if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
+	if (status == IXGBE_ERR_SFP_NOT_PRESENT || status == IXGBE_ERR_I2C) {
+		status = IXGBE_ERR_SFP_NOT_PRESENT;
 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+		if (hw->phy.type != ixgbe_phy_nl) {
+			hw->phy.id = 0;
+			hw->phy.type = ixgbe_phy_unknown;
+		}
 		goto out;
 	}
 
@@ -572,8 +557,8 @@
 		                            &comp_codes_1g);
 		hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES,
 		                            &comp_codes_10g);
-		hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_TRANSMISSION_MEDIA,
-		                            &transmission_media);
+		hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_CABLE_TECHNOLOGY,
+		                            &cable_tech);
 
 		/* ID Module
 		 * =========
@@ -586,7 +571,7 @@
 		 * 6    SFP_SR/LR_CORE1 - 82599-specific
 		 */
 		if (hw->mac.type == ixgbe_mac_82598EB) {
-			if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
+			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 				hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
 			else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
 				hw->phy.sfp_type = ixgbe_sfp_type_sr;
@@ -595,7 +580,7 @@
 			else
 				hw->phy.sfp_type = ixgbe_sfp_type_unknown;
 		} else if (hw->mac.type == ixgbe_mac_82599EB) {
-			if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
+			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 				if (hw->bus.lan_id == 0)
 					hw->phy.sfp_type =
 					             ixgbe_sfp_type_da_cu_core0;
@@ -620,8 +605,19 @@
 				hw->phy.sfp_type = ixgbe_sfp_type_unknown;
 		}
 
+		if (hw->phy.sfp_type != stored_sfp_type)
+			hw->phy.sfp_setup_needed = true;
+
+		/* Determine if the SFP+ PHY is dual speed or not. */
+		hw->phy.multispeed_fiber = false;
+		if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
+		   (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
+		   ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
+		   (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
+			hw->phy.multispeed_fiber = true;
+
 		/* Determine PHY vendor */
-		if (hw->phy.type == ixgbe_phy_unknown) {
+		if (hw->phy.type != ixgbe_phy_nl) {
 			hw->phy.id = identifier;
 			hw->phy.ops.read_i2c_eeprom(hw,
 			                            IXGBE_SFF_VENDOR_OUI_BYTE0,
@@ -640,8 +636,7 @@
 
 			switch (vendor_oui) {
 			case IXGBE_SFF_VENDOR_OUI_TYCO:
-				if (transmission_media &
-				    IXGBE_SFF_TWIN_AX_CAPABLE)
+				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 					hw->phy.type = ixgbe_phy_tw_tyco;
 				break;
 			case IXGBE_SFF_VENDOR_OUI_FTL:
@@ -654,31 +649,42 @@
 				hw->phy.type = ixgbe_phy_sfp_intel;
 				break;
 			default:
-				if (transmission_media &
-				    IXGBE_SFF_TWIN_AX_CAPABLE)
+				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 					hw->phy.type = ixgbe_phy_tw_unknown;
 				else
 					hw->phy.type = ixgbe_phy_sfp_unknown;
 				break;
 			}
 		}
-		if (hw->mac.type == ixgbe_mac_82598EB ||
-		    (hw->phy.sfp_type != ixgbe_sfp_type_sr &&
-		     hw->phy.sfp_type != ixgbe_sfp_type_lr &&
-		     hw->phy.sfp_type != ixgbe_sfp_type_srlr_core0 &&
-		     hw->phy.sfp_type != ixgbe_sfp_type_srlr_core1)) {
+
+		/* All passive DA cables are supported */
+		if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
 			status = 0;
 			goto out;
 		}
 
-		hw->eeprom.ops.read(hw, IXGBE_PHY_ENFORCE_INTEL_SFP_OFFSET,
-		                    &enforce_sfp);
-		if (!(enforce_sfp & IXGBE_PHY_ALLOW_ANY_SFP)) {
+		/* 1G SFP modules are not supported */
+		if (comp_codes_10g == 0) {
+			hw->phy.type = ixgbe_phy_sfp_unsupported;
+			status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+			goto out;
+		}
+
+		/* Anything else 82598-based is supported */
+		if (hw->mac.type == ixgbe_mac_82598EB) {
+			status = 0;
+			goto out;
+		}
+
+		/* This is guaranteed to be 82599, no need to check for NULL */
+		hw->mac.ops.get_device_caps(hw, &enforce_sfp);
+		if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
 			/* Make sure we're a supported PHY type */
 			if (hw->phy.type == ixgbe_phy_sfp_intel) {
 				status = 0;
 			} else {
 				hw_dbg(hw, "SFP+ module not supported\n");
+				hw->phy.type = ixgbe_phy_sfp_unsupported;
 				status = IXGBE_ERR_SFP_NOT_SUPPORTED;
 			}
 		} else {
@@ -1279,7 +1285,7 @@
 		udelay(10);
 		status = hw->phy.ops.read_reg(hw,
 		                        IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
-		                        IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+					MDIO_MMD_VEND1,
 		                        &phy_data);
 		phy_link = phy_data &
 		           IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
@@ -1307,8 +1313,7 @@
 {
 	s32 status = 0;
 
-	status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
-	                              IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+	status = hw->phy.ops.read_reg(hw, TNX_FW_REV, MDIO_MMD_VEND1,
 	                              firmware_version);
 
 	return status;
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_phy.h linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_phy.h
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_phy.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_phy.h	2009-09-09 18:13:59.000000000 -0400
@@ -39,11 +39,12 @@
 #define IXGBE_SFF_VENDOR_OUI_BYTE2   0x27
 #define IXGBE_SFF_1GBE_COMP_CODES    0x6
 #define IXGBE_SFF_10GBE_COMP_CODES   0x3
-#define IXGBE_SFF_TRANSMISSION_MEDIA 0x9
+#define IXGBE_SFF_CABLE_TECHNOLOGY   0x8
 
 /* Bitmasks */
-#define IXGBE_SFF_TWIN_AX_CAPABLE            0x80
+#define IXGBE_SFF_DA_PASSIVE_CABLE           0x4
 #define IXGBE_SFF_1GBASESX_CAPABLE           0x1
+#define IXGBE_SFF_1GBASELX_CAPABLE           0x2
 #define IXGBE_SFF_10GBASESR_CAPABLE          0x10
 #define IXGBE_SFF_10GBASELR_CAPABLE          0x20
 #define IXGBE_I2C_EEPROM_READ_MASK           0x100
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_type.h linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_type.h
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/ixgbe_type.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/ixgbe_type.h	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,8 @@
 #define _IXGBE_TYPE_H_
 
 #include <linux/types.h>
+#include <linux/mdio.h>
+#include <linux/list.h>
 
 /* Vendor ID */
 #define IXGBE_INTEL_VENDOR_ID   0x8086
@@ -45,9 +47,9 @@
 #define IXGBE_DEV_ID_82598_DA_DUAL_PORT  0x10F1
 #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM      0x10E1
 #define IXGBE_DEV_ID_82598EB_XF_LR       0x10F4
-#define IXGBE_DEV_ID_82599               0x10D8
 #define IXGBE_DEV_ID_82599_KX4           0x10F7
 #define IXGBE_DEV_ID_82599_SFP           0x10FB
+#define IXGBE_DEV_ID_82599_XAUI_LOM      0x10FC
 
 /* General Registers */
 #define IXGBE_CTRL      0x00000
@@ -229,6 +231,34 @@
 #define IXGBE_RETA(_i)  (0x05C00 + ((_i) * 4))  /* 32 of these (0-31) */
 #define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4))  /* 10 of these (0-9) */
 
+/* Flow Director registers */
+#define IXGBE_FDIRCTRL  0x0EE00
+#define IXGBE_FDIRHKEY  0x0EE68
+#define IXGBE_FDIRSKEY  0x0EE6C
+#define IXGBE_FDIRDIP4M 0x0EE3C
+#define IXGBE_FDIRSIP4M 0x0EE40
+#define IXGBE_FDIRTCPM  0x0EE44
+#define IXGBE_FDIRUDPM  0x0EE48
+#define IXGBE_FDIRIP6M  0x0EE74
+#define IXGBE_FDIRM     0x0EE70
+
+/* Flow Director Stats registers */
+#define IXGBE_FDIRFREE  0x0EE38
+#define IXGBE_FDIRLEN   0x0EE4C
+#define IXGBE_FDIRUSTAT 0x0EE50
+#define IXGBE_FDIRFSTAT 0x0EE54
+#define IXGBE_FDIRMATCH 0x0EE58
+#define IXGBE_FDIRMISS  0x0EE5C
+
+/* Flow Director Programming registers */
+#define IXGBE_FDIRSIPv6(_i) (0x0EE0C + ((_i) * 4)) /* 3 of these (0-2) */
+#define IXGBE_FDIRIPSA      0x0EE18
+#define IXGBE_FDIRIPDA      0x0EE1C
+#define IXGBE_FDIRPORT      0x0EE20
+#define IXGBE_FDIRVLAN      0x0EE24
+#define IXGBE_FDIRHASH      0x0EE28
+#define IXGBE_FDIRCMD       0x0EE2C
+
 /* Transmit DMA registers */
 #define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of these (0-31)*/
 #define IXGBE_TDBAH(_i) (0x06004 + ((_i) * 0x40))
@@ -443,6 +473,21 @@
 
 #define IXGBE_SECTXCTRL_STORE_FORWARD_ENABLE    0x4
 
+/* HW RSC registers */
+#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \
+                          (0x0D02C + ((_i - 64) * 0x40)))
+#define IXGBE_RSCDBU      0x03028
+#define IXGBE_RSCCTL_RSCEN          0x01
+#define IXGBE_RSCCTL_MAXDESC_1      0x00
+#define IXGBE_RSCCTL_MAXDESC_4      0x04
+#define IXGBE_RSCCTL_MAXDESC_8      0x08
+#define IXGBE_RSCCTL_MAXDESC_16     0x0C
+#define IXGBE_RXDADV_RSCCNT_SHIFT     17
+#define IXGBE_GPIE_RSC_DELAY_SHIFT    11
+#define IXGBE_RXDADV_RSCCNT_MASK    0x001E0000
+#define IXGBE_RSCDBU_RSCACKDIS      0x00000080
+#define IXGBE_RDRXCTL_RSCFRSTSIZE   0x003E0000
+
 /* DCB registers */
 #define IXGBE_RTRPCS      0x02430
 #define IXGBE_RTTDCS      0x04900
@@ -462,6 +507,63 @@
 #define IXGBE_RTTDTECC_NO_BCN   0x00000100
 #define IXGBE_RTTBCNRC    0x04984
 
+/* FCoE registers */
+#define IXGBE_FCPTRL    0x02410 /* FC User Desc. PTR Low */
+#define IXGBE_FCPTRH    0x02414 /* FC USer Desc. PTR High */
+#define IXGBE_FCBUFF    0x02418 /* FC Buffer Control */
+#define IXGBE_FCDMARW   0x02420 /* FC Receive DMA RW */
+#define IXGBE_FCINVST0  0x03FC0 /* FC Invalid DMA Context Status Reg 0 */
+#define IXGBE_FCINVST(_i)       (IXGBE_FCINVST0 + ((_i) * 4))
+#define IXGBE_FCBUFF_VALID      (1 << 0)   /* DMA Context Valid */
+#define IXGBE_FCBUFF_BUFFSIZE   (3 << 3)   /* User Buffer Size */
+#define IXGBE_FCBUFF_WRCONTX    (1 << 7)   /* 0: Initiator, 1: Target */
+#define IXGBE_FCBUFF_BUFFCNT    0x0000ff00 /* Number of User Buffers */
+#define IXGBE_FCBUFF_OFFSET     0xffff0000 /* User Buffer Offset */
+#define IXGBE_FCBUFF_BUFFSIZE_SHIFT  3
+#define IXGBE_FCBUFF_BUFFCNT_SHIFT   8
+#define IXGBE_FCBUFF_OFFSET_SHIFT    16
+#define IXGBE_FCDMARW_WE        (1 << 14)   /* Write enable */
+#define IXGBE_FCDMARW_RE        (1 << 15)   /* Read enable */
+#define IXGBE_FCDMARW_FCOESEL   0x000001ff  /* FC X_ID: 11 bits */
+#define IXGBE_FCDMARW_LASTSIZE  0xffff0000  /* Last User Buffer Size */
+#define IXGBE_FCDMARW_LASTSIZE_SHIFT 16
+
+/* FCoE SOF/EOF */
+#define IXGBE_TEOFF     0x04A94 /* Tx FC EOF */
+#define IXGBE_TSOFF     0x04A98 /* Tx FC SOF */
+#define IXGBE_REOFF     0x05158 /* Rx FC EOF */
+#define IXGBE_RSOFF     0x051F8 /* Rx FC SOF */
+/* FCoE Filter Context Registers */
+#define IXGBE_FCFLT     0x05108 /* FC FLT Context */
+#define IXGBE_FCFLTRW   0x05110 /* FC Filter RW Control */
+#define IXGBE_FCPARAM   0x051d8 /* FC Offset Parameter */
+#define IXGBE_FCFLT_VALID       (1 << 0)   /* Filter Context Valid */
+#define IXGBE_FCFLT_FIRST       (1 << 1)   /* Filter First */
+#define IXGBE_FCFLT_SEQID       0x00ff0000 /* Sequence ID */
+#define IXGBE_FCFLT_SEQCNT      0xff000000 /* Sequence Count */
+#define IXGBE_FCFLTRW_RVALDT    (1 << 13)  /* Fast Re-Validation */
+#define IXGBE_FCFLTRW_WE        (1 << 14)  /* Write Enable */
+#define IXGBE_FCFLTRW_RE        (1 << 15)  /* Read Enable */
+/* FCoE Receive Control */
+#define IXGBE_FCRXCTRL  0x05100 /* FC Receive Control */
+#define IXGBE_FCRXCTRL_FCOELLI  (1 << 0)   /* Low latency interrupt */
+#define IXGBE_FCRXCTRL_SAVBAD   (1 << 1)   /* Save Bad Frames */
+#define IXGBE_FCRXCTRL_FRSTRDH  (1 << 2)   /* EN 1st Read Header */
+#define IXGBE_FCRXCTRL_LASTSEQH (1 << 3)   /* EN Last Header in Seq */
+#define IXGBE_FCRXCTRL_ALLH     (1 << 4)   /* EN All Headers */
+#define IXGBE_FCRXCTRL_FRSTSEQH (1 << 5)   /* EN 1st Seq. Header */
+#define IXGBE_FCRXCTRL_ICRC     (1 << 6)   /* Ignore Bad FC CRC */
+#define IXGBE_FCRXCTRL_FCCRCBO  (1 << 7)   /* FC CRC Byte Ordering */
+#define IXGBE_FCRXCTRL_FCOEVER  0x00000f00 /* FCoE Version: 4 bits */
+#define IXGBE_FCRXCTRL_FCOEVER_SHIFT 8
+/* FCoE Redirection */
+#define IXGBE_FCRECTL   0x0ED00 /* FC Redirection Control */
+#define IXGBE_FCRETA0   0x0ED10 /* FC Redirection Table 0 */
+#define IXGBE_FCRETA(_i)        (IXGBE_FCRETA0 + ((_i) * 4)) /* FCoE Redir */
+#define IXGBE_FCRECTL_ENA       0x1        /* FCoE Redir Table Enable */
+#define IXGBE_FCRETA_SIZE       8          /* Max entries in FCRETA */
+#define IXGBE_FCRETA_ENTRY_MASK 0x0000007f /* 7 bits for the queue index */
+
 /* Stats registers */
 #define IXGBE_CRCERRS   0x04000
 #define IXGBE_ILLERRC   0x04004
@@ -533,6 +635,13 @@
 #define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */
 #define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */
 #define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */
+#define IXGBE_FCCRC     0x05118 /* Count of Good Eth CRC w/ Bad FC CRC */
+#define IXGBE_FCOERPDC  0x0241C /* FCoE Rx Packets Dropped Count */
+#define IXGBE_FCLAST    0x02424 /* FCoE Last Error Count */
+#define IXGBE_FCOEPRC   0x02428 /* Number of FCoE Packets Received */
+#define IXGBE_FCOEDWRC  0x0242C /* Number of FCoE DWords Received */
+#define IXGBE_FCOEPTC   0x08784 /* Number of FCoE Packets Transmitted */
+#define IXGBE_FCOEDWTC  0x08788 /* Number of FCoE DWords Transmitted */
 
 /* Management */
 #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */
@@ -609,6 +718,12 @@
 #define IXGBE_ECC_STATUS_82599  0x110E0
 #define IXGBE_BAR_CTRL_82599    0x110F4
 
+/* PCI Express Control */
+#define IXGBE_GCR_CMPL_TMOUT_MASK       0x0000F000
+#define IXGBE_GCR_CMPL_TMOUT_10ms       0x00001000
+#define IXGBE_GCR_CMPL_TMOUT_RESEND     0x00010000
+#define IXGBE_GCR_CAP_VER2              0x00040000
+
 /* Time Sync Registers */
 #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */
 #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */
@@ -833,13 +948,7 @@
 /* Omer bit masks */
 #define IXGBE_CORECTL_WRITE_CMD         0x00010000
 
-/* Device Type definitions for new protocol MDIO commands */
-#define IXGBE_MDIO_PMA_PMD_DEV_TYPE               0x1
-#define IXGBE_MDIO_PCS_DEV_TYPE                   0x3
-#define IXGBE_MDIO_PHY_XS_DEV_TYPE                0x4
-#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE              0x7
-#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE     0x1E   /* Device 30 */
-#define IXGBE_TWINAX_DEV                          1
+/* MDIO definitions */
 
 #define IXGBE_MDIO_COMMAND_TIMEOUT     100 /* PHY Timeout for 1 GB mode */
 
@@ -850,31 +959,10 @@
 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED    0x0018
 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED     0x0010
 
-#define IXGBE_MDIO_AUTO_NEG_CONTROL    0x0 /* AUTO_NEG Control Reg */
-#define IXGBE_MDIO_AUTO_NEG_STATUS     0x1 /* AUTO_NEG Status Reg */
-#define IXGBE_MDIO_PHY_XS_CONTROL      0x0 /* PHY_XS Control Reg */
-#define IXGBE_MDIO_PHY_XS_RESET        0x8000 /* PHY_XS Reset */
-#define IXGBE_MDIO_PHY_ID_HIGH         0x2 /* PHY ID High Reg*/
-#define IXGBE_MDIO_PHY_ID_LOW          0x3 /* PHY ID Low Reg*/
-#define IXGBE_MDIO_PHY_SPEED_ABILITY   0x4 /* Speed Ability Reg */
-#define IXGBE_MDIO_PHY_SPEED_10G       0x0001 /* 10G capable */
-#define IXGBE_MDIO_PHY_SPEED_1G        0x0010 /* 1G capable */
-#define IXGBE_MDIO_PHY_EXT_ABILITY        0xB /* Ext Ability Reg */
-#define IXGBE_MDIO_PHY_10GBASET_ABILITY   0x0004 /* 10GBaseT capable */
-#define IXGBE_MDIO_PHY_1000BASET_ABILITY  0x0020 /* 1000BaseT capable */
-
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR     0xC30A /* PHY_XS SDA/SCL Addr Reg */
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA     0xC30B /* PHY_XS SDA/SCL Data Reg */
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT     0xC30C /* PHY_XS SDA/SCL Status Reg */
 
-/* MII clause 22/28 definitions */
-#define IXGBE_MDIO_PHY_LOW_POWER_MODE  0x0800
-
-#define IXGBE_MII_SPEED_SELECTION_REG  0x10
-#define IXGBE_MII_RESTART              0x200
-#define IXGBE_MII_AUTONEG_COMPLETE     0x20
-#define IXGBE_MII_AUTONEG_REG          0x0
-
 #define IXGBE_PHY_REVISION_MASK        0xFFFFFFF0
 #define IXGBE_MAX_PHY_ADDR             32
 
@@ -898,8 +986,6 @@
 #define IXGBE_CONTROL_NL         0x000F
 #define IXGBE_CONTROL_EOL_NL     0x0FFF
 #define IXGBE_CONTROL_SOL_NL     0x0000
-#define IXGBE_PHY_ENFORCE_INTEL_SFP_OFFSET 0x002C
-#define IXGBE_PHY_ALLOW_ANY_SFP            0x1
 
 /* General purpose Interrupt Enable */
 #define IXGBE_SDP0_GPIEN         0x00000001 /* SDP0 */
@@ -958,6 +1044,8 @@
 #define IXGBE_VT_CTL_DIS_DEFPL  0x20000000 /* disable default pool */
 #define IXGBE_VT_CTL_REPLEN     0x40000000 /* replication enabled */
 #define IXGBE_VT_CTL_VT_ENABLE  0x00000001  /* Enable VT Mode */
+#define IXGBE_VT_CTL_POOL_SHIFT 7
+#define IXGBE_VT_CTL_POOL_MASK  (0x3F << IXGBE_VT_CTL_POOL_SHIFT)
 
 /* VMOLR bitmasks */
 #define IXGBE_VMOLR_AUPE        0x01000000 /* accept untagged packets */
@@ -1148,6 +1236,7 @@
 
 /* Interrupt Vector Allocation Registers */
 #define IXGBE_IVAR_REG_NUM      25
+#define IXGBE_IVAR_REG_NUM_82599       64
 #define IXGBE_IVAR_TXRX_ENTRY   96
 #define IXGBE_IVAR_RX_ENTRY     64
 #define IXGBE_IVAR_RX_QUEUE(_i)    (0 + (_i))
@@ -1163,6 +1252,7 @@
 
 /* ETYPE Queue Filter/Select Bit Masks */
 #define IXGBE_MAX_ETQF_FILTERS  8
+#define IXGBE_ETQF_FCOE         0x08000000 /* bit 27 */
 #define IXGBE_ETQF_BCN          0x10000000 /* bit 28 */
 #define IXGBE_ETQF_1588         0x40000000 /* bit 30 */
 #define IXGBE_ETQF_FILTER_EN    0x80000000 /* bit 31 */
@@ -1185,6 +1275,7 @@
  */
 #define IXGBE_ETQF_FILTER_EAPOL          0
 #define IXGBE_ETQF_FILTER_BCN            1
+#define IXGBE_ETQF_FILTER_FCOE           2
 #define IXGBE_ETQF_FILTER_1588           3
 /* VLAN Control Bit Masks */
 #define IXGBE_VLNCTRL_VET       0x0000FFFF  /* bits 0-15 */
@@ -1208,8 +1299,10 @@
 #define IXGBE_STATUS_LAN_ID_1   0x00000004 /* LAN ID 1 */
 
 /* ESDP Bit Masks */
-#define IXGBE_ESDP_SDP0 0x00000001
-#define IXGBE_ESDP_SDP1 0x00000002
+#define IXGBE_ESDP_SDP0 0x00000001 /* SDP0 Data Value */
+#define IXGBE_ESDP_SDP1 0x00000002 /* SDP1 Data Value */
+#define IXGBE_ESDP_SDP2 0x00000004 /* SDP2 Data Value */
+#define IXGBE_ESDP_SDP3 0x00000008 /* SDP3 Data Value */
 #define IXGBE_ESDP_SDP4 0x00000010 /* SDP4 Data Value */
 #define IXGBE_ESDP_SDP5 0x00000020 /* SDP5 Data Value */
 #define IXGBE_ESDP_SDP6 0x00000040 /* SDP6 Data Value */
@@ -1309,8 +1402,6 @@
 #define IXGBE_LINK_UP_TIME      90 /* 9.0 Seconds */
 #define IXGBE_AUTO_NEG_TIME     45 /* 4.5 Seconds */
 
-#define FIBER_LINK_UP_LIMIT     50
-
 /* PCS1GLSTA Bit Masks */
 #define IXGBE_PCS1GLSTA_LINK_OK         1
 #define IXGBE_PCS1GLSTA_SYNK_OK         0x10
@@ -1382,6 +1473,8 @@
 #define IXGBE_FW_PTR            0x0F
 #define IXGBE_PBANUM0_PTR       0x15
 #define IXGBE_PBANUM1_PTR       0x16
+#define IXGBE_DEVICE_CAPS       0x2C
+#define IXGBE_SAN_MAC_ADDR_PTR  0x28
 #define IXGBE_PCIE_MSIX_82599_CAPS  0x72
 #define IXGBE_PCIE_MSIX_82598_CAPS  0x62
 
@@ -1425,8 +1518,16 @@
 #define IXGBE_EERD_ATTEMPTS 100000
 #endif
 
+#define IXGBE_SAN_MAC_ADDR_PORT0_OFFSET  0x0
+#define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET  0x3
+#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP  0x1
+#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS  0x2
+#define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR   0x4
+#define IXGBE_FW_PATCH_VERSION_4   0x7
+
 /* PCI Bus Info */
 #define IXGBE_PCI_LINK_STATUS     0xB2
+#define IXGBE_PCI_DEVICE_CONTROL2 0xC8
 #define IXGBE_PCI_LINK_WIDTH      0x3F0
 #define IXGBE_PCI_LINK_WIDTH_1    0x10
 #define IXGBE_PCI_LINK_WIDTH_2    0x20
@@ -1437,6 +1538,7 @@
 #define IXGBE_PCI_LINK_SPEED_5000 0x2
 #define IXGBE_PCI_HEADER_TYPE_REGISTER  0x0E
 #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80
+#define IXGBE_PCI_DEVICE_CONTROL2_16ms  0x0005
 
 /* Number of 100 microseconds we wait for PCI Express master disable */
 #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
@@ -1553,7 +1655,8 @@
 #define IXGBE_MTQC_RT_ENA       0x1 /* DCB Enable */
 #define IXGBE_MTQC_VT_ENA       0x2 /* VMDQ2 Enable */
 #define IXGBE_MTQC_64Q_1PB      0x0 /* 64 queues 1 pack buffer */
-#define IXGBE_MTQC_64VF         0x8 /* 2 TX Queues per pool w/64VF's */
+#define IXGBE_MTQC_32VF         0x8 /* 4 TX Queues per pool w/32VF's */
+#define IXGBE_MTQC_64VF         0x4 /* 2 TX Queues per pool w/64VF's */
 #define IXGBE_MTQC_8TC_8TQ      0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */
 
 /* Receive Descriptor bit definitions */
@@ -1585,6 +1688,11 @@
 #define IXGBE_RXD_ERR_IPE       0x80    /* IP Checksum Error */
 #define IXGBE_RXDADV_ERR_MASK           0xfff00000 /* RDESC.ERRORS mask */
 #define IXGBE_RXDADV_ERR_SHIFT          20         /* RDESC.ERRORS shift */
+#define IXGBE_RXDADV_ERR_FCEOFE         0x80000000 /* FCoEFe/IPE */
+#define IXGBE_RXDADV_ERR_FCERR          0x00700000 /* FCERR/FDIRERR */
+#define IXGBE_RXDADV_ERR_FDIR_LEN       0x00100000 /* FDIR Length error */
+#define IXGBE_RXDADV_ERR_FDIR_DROP      0x00200000 /* FDIR Drop error */
+#define IXGBE_RXDADV_ERR_FDIR_COLL      0x00400000 /* FDIR Collision error */
 #define IXGBE_RXDADV_ERR_HBO    0x00800000 /*Header Buffer Overflow */
 #define IXGBE_RXDADV_ERR_CE     0x01000000 /* CRC Error */
 #define IXGBE_RXDADV_ERR_LE     0x02000000 /* Length Error */
@@ -1604,12 +1712,19 @@
 #define IXGBE_RXDADV_STAT_FLM           IXGBE_RXD_STAT_FLM /* FDir Match */
 #define IXGBE_RXDADV_STAT_VP            IXGBE_RXD_STAT_VP  /* IEEE VLAN Pkt */
 #define IXGBE_RXDADV_STAT_MASK          0x000fffff /* Stat/NEXTP: bit 0-19 */
+#define IXGBE_RXDADV_STAT_FCEOFS        0x00000040 /* FCoE EOF/SOF Stat */
+#define IXGBE_RXDADV_STAT_FCSTAT        0x00000030 /* FCoE Pkt Stat */
+#define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000 /* 00: No Ctxt Match */
+#define IXGBE_RXDADV_STAT_FCSTAT_NODDP  0x00000010 /* 01: Ctxt w/o DDP */
+#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */
+#define IXGBE_RXDADV_STAT_FCSTAT_DDP    0x00000030 /* 11: Ctxt w/ DDP */
 
 /* PSRTYPE bit definitions */
 #define IXGBE_PSRTYPE_TCPHDR    0x00000010
 #define IXGBE_PSRTYPE_UDPHDR    0x00000020
 #define IXGBE_PSRTYPE_IPV4HDR   0x00000100
 #define IXGBE_PSRTYPE_IPV6HDR   0x00000200
+#define IXGBE_PSRTYPE_L2HDR     0x00001000
 
 /* SRRCTL bit definitions */
 #define IXGBE_SRRCTL_BSIZEPKT_SHIFT     10     /* so many KBs */
@@ -1710,6 +1825,82 @@
 
 #endif
 
+enum ixgbe_fdir_pballoc_type {
+	IXGBE_FDIR_PBALLOC_64K = 0,
+	IXGBE_FDIR_PBALLOC_128K,
+	IXGBE_FDIR_PBALLOC_256K,
+};
+#define IXGBE_FDIR_PBALLOC_SIZE_SHIFT           16
+
+/* Flow Director register values */
+#define IXGBE_FDIRCTRL_PBALLOC_64K              0x00000001
+#define IXGBE_FDIRCTRL_PBALLOC_128K             0x00000002
+#define IXGBE_FDIRCTRL_PBALLOC_256K             0x00000003
+#define IXGBE_FDIRCTRL_INIT_DONE                0x00000008
+#define IXGBE_FDIRCTRL_PERFECT_MATCH            0x00000010
+#define IXGBE_FDIRCTRL_REPORT_STATUS            0x00000020
+#define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS     0x00000080
+#define IXGBE_FDIRCTRL_DROP_Q_SHIFT             8
+#define IXGBE_FDIRCTRL_FLEX_SHIFT               16
+#define IXGBE_FDIRCTRL_SEARCHLIM                0x00800000
+#define IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT         24
+#define IXGBE_FDIRCTRL_FULL_THRESH_MASK         0xF0000000
+#define IXGBE_FDIRCTRL_FULL_THRESH_SHIFT        28
+
+#define IXGBE_FDIRTCPM_DPORTM_SHIFT             16
+#define IXGBE_FDIRUDPM_DPORTM_SHIFT             16
+#define IXGBE_FDIRIP6M_DIPM_SHIFT               16
+#define IXGBE_FDIRM_VLANID                      0x00000001
+#define IXGBE_FDIRM_VLANP                       0x00000002
+#define IXGBE_FDIRM_POOL                        0x00000004
+#define IXGBE_FDIRM_L3P                         0x00000008
+#define IXGBE_FDIRM_L4P                         0x00000010
+#define IXGBE_FDIRM_FLEX                        0x00000020
+#define IXGBE_FDIRM_DIPv6                       0x00000040
+
+#define IXGBE_FDIRFREE_FREE_MASK                0xFFFF
+#define IXGBE_FDIRFREE_FREE_SHIFT               0
+#define IXGBE_FDIRFREE_COLL_MASK                0x7FFF0000
+#define IXGBE_FDIRFREE_COLL_SHIFT               16
+#define IXGBE_FDIRLEN_MAXLEN_MASK               0x3F
+#define IXGBE_FDIRLEN_MAXLEN_SHIFT              0
+#define IXGBE_FDIRLEN_MAXHASH_MASK              0x7FFF0000
+#define IXGBE_FDIRLEN_MAXHASH_SHIFT             16
+#define IXGBE_FDIRUSTAT_ADD_MASK                0xFFFF
+#define IXGBE_FDIRUSTAT_ADD_SHIFT               0
+#define IXGBE_FDIRUSTAT_REMOVE_MASK             0xFFFF0000
+#define IXGBE_FDIRUSTAT_REMOVE_SHIFT            16
+#define IXGBE_FDIRFSTAT_FADD_MASK               0x00FF
+#define IXGBE_FDIRFSTAT_FADD_SHIFT              0
+#define IXGBE_FDIRFSTAT_FREMOVE_MASK            0xFF00
+#define IXGBE_FDIRFSTAT_FREMOVE_SHIFT           8
+#define IXGBE_FDIRPORT_DESTINATION_SHIFT        16
+#define IXGBE_FDIRVLAN_FLEX_SHIFT               16
+#define IXGBE_FDIRHASH_BUCKET_VALID_SHIFT       15
+#define IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT       16
+
+#define IXGBE_FDIRCMD_CMD_MASK                  0x00000003
+#define IXGBE_FDIRCMD_CMD_ADD_FLOW              0x00000001
+#define IXGBE_FDIRCMD_CMD_REMOVE_FLOW           0x00000002
+#define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT        0x00000003
+#define IXGBE_FDIRCMD_CMD_QUERY_REM_HASH        0x00000007
+#define IXGBE_FDIRCMD_FILTER_UPDATE             0x00000008
+#define IXGBE_FDIRCMD_IPv6DMATCH                0x00000010
+#define IXGBE_FDIRCMD_L4TYPE_UDP                0x00000020
+#define IXGBE_FDIRCMD_L4TYPE_TCP                0x00000040
+#define IXGBE_FDIRCMD_L4TYPE_SCTP               0x00000060
+#define IXGBE_FDIRCMD_IPV6                      0x00000080
+#define IXGBE_FDIRCMD_CLEARHT                   0x00000100
+#define IXGBE_FDIRCMD_DROP                      0x00000200
+#define IXGBE_FDIRCMD_INT                       0x00000400
+#define IXGBE_FDIRCMD_LAST                      0x00000800
+#define IXGBE_FDIRCMD_COLLISION                 0x00001000
+#define IXGBE_FDIRCMD_QUEUE_EN                  0x00008000
+#define IXGBE_FDIRCMD_RX_QUEUE_SHIFT            16
+#define IXGBE_FDIRCMD_VT_POOL_SHIFT             24
+#define IXGBE_FDIR_INIT_DONE_POLL               10
+#define IXGBE_FDIRCMD_CMD_POLL                  10
+
 /* Transmit Descriptor - Legacy */
 struct ixgbe_legacy_tx_desc {
 	u64 buffer_addr;       /* Address of the descriptor's data buffer */
@@ -1836,6 +2027,16 @@
 #define IXGBE_ADVTXD_POPTS_IPSEC      0x00000400 /* IPSec offload request */
 #define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
 #define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000/* ESP Encrypt Enable */
+#define IXGBE_ADVTXT_TUCMD_FCOE      0x00008000       /* FCoE Frame Type */
+#define IXGBE_ADVTXD_FCOEF_EOF_MASK  (0x3 << 10)      /* FC EOF index */
+#define IXGBE_ADVTXD_FCOEF_SOF       ((1 << 2) << 10) /* FC SOF index */
+#define IXGBE_ADVTXD_FCOEF_PARINC    ((1 << 3) << 10) /* Rel_Off in F_CTL */
+#define IXGBE_ADVTXD_FCOEF_ORIE      ((1 << 4) << 10) /* Orientation: End */
+#define IXGBE_ADVTXD_FCOEF_ORIS      ((1 << 5) << 10) /* Orientation: Start */
+#define IXGBE_ADVTXD_FCOEF_EOF_N     (0x0 << 10)      /* 00: EOFn */
+#define IXGBE_ADVTXD_FCOEF_EOF_T     (0x1 << 10)      /* 01: EOFt */
+#define IXGBE_ADVTXD_FCOEF_EOF_NI    (0x2 << 10)      /* 10: EOFni */
+#define IXGBE_ADVTXD_FCOEF_EOF_A     (0x3 << 10)      /* 11: EOFa */
 #define IXGBE_ADVTXD_L4LEN_SHIFT     8  /* Adv ctxt L4LEN shift */
 #define IXGBE_ADVTXD_MSS_SHIFT       16  /* Adv ctxt MSS shift */
 
@@ -1861,7 +2062,7 @@
 #define IXGBE_PHYSICAL_LAYER_UNKNOWN      0
 #define IXGBE_PHYSICAL_LAYER_10GBASE_T    0x0001
 #define IXGBE_PHYSICAL_LAYER_1000BASE_T   0x0002
-#define IXGBE_PHYSICAL_LAYER_100BASE_T    0x0004
+#define IXGBE_PHYSICAL_LAYER_100BASE_TX   0x0004
 #define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU  0x0008
 #define IXGBE_PHYSICAL_LAYER_10GBASE_LR   0x0010
 #define IXGBE_PHYSICAL_LAYER_10GBASE_LRM  0x0020
@@ -1870,6 +2071,47 @@
 #define IXGBE_PHYSICAL_LAYER_10GBASE_CX4  0x0100
 #define IXGBE_PHYSICAL_LAYER_1000BASE_KX  0x0200
 #define IXGBE_PHYSICAL_LAYER_1000BASE_BX  0x0400
+#define IXGBE_PHYSICAL_LAYER_10GBASE_KR   0x0800
+#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000
+
+/* Software ATR hash keys */
+#define IXGBE_ATR_BUCKET_HASH_KEY    0xE214AD3D
+#define IXGBE_ATR_SIGNATURE_HASH_KEY 0x14364D17
+
+/* Software ATR input stream offsets and masks */
+#define IXGBE_ATR_VLAN_OFFSET       0
+#define IXGBE_ATR_SRC_IPV6_OFFSET   2
+#define IXGBE_ATR_SRC_IPV4_OFFSET  14
+#define IXGBE_ATR_DST_IPV6_OFFSET  18
+#define IXGBE_ATR_DST_IPV4_OFFSET  30
+#define IXGBE_ATR_SRC_PORT_OFFSET  34
+#define IXGBE_ATR_DST_PORT_OFFSET  36
+#define IXGBE_ATR_FLEX_BYTE_OFFSET 38
+#define IXGBE_ATR_VM_POOL_OFFSET   40
+#define IXGBE_ATR_L4TYPE_OFFSET    41
+
+#define IXGBE_ATR_L4TYPE_MASK      0x3
+#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4
+#define IXGBE_ATR_L4TYPE_UDP       0x1
+#define IXGBE_ATR_L4TYPE_TCP       0x2
+#define IXGBE_ATR_L4TYPE_SCTP      0x3
+#define IXGBE_ATR_HASH_MASK     0x7fff
+
+/* Flow Director ATR input struct. */
+struct ixgbe_atr_input {
+	/* Byte layout in order, all values with MSB first:
+	 *
+	 * vlan_id    - 2 bytes
+	 * src_ip     - 16 bytes
+	 * dst_ip     - 16 bytes
+	 * src_port   - 2 bytes
+	 * dst_port   - 2 bytes
+	 * flex_bytes - 2 bytes
+	 * vm_pool    - 1 byte
+	 * l4type     - 1 byte
+	 */
+	u8 byte_stream[42];
+};
 
 enum ixgbe_eeprom_type {
 	ixgbe_eeprom_uninitialized = 0,
@@ -1897,6 +2139,7 @@
 	ixgbe_phy_sfp_ftl,
 	ixgbe_phy_sfp_unknown,
 	ixgbe_phy_sfp_intel,
+	ixgbe_phy_sfp_unsupported,
 	ixgbe_phy_generic
 };
 
@@ -2005,7 +2248,8 @@
 	u16 pause_time; /* Flow Control Pause timer */
 	bool send_xon; /* Flow control send XON */
 	bool strict_ieee; /* Strict IEEE mode */
-	bool disable_fc_autoneg; /* Turn off autoneg FC mode */
+	bool disable_fc_autoneg; /* Do not autonegotiate FC */
+	bool fc_was_autonegged; /* Is current_mode the result of autonegging? */
 	enum ixgbe_fc_mode current_mode; /* FC mode in effect */
 	enum ixgbe_fc_mode requested_mode; /* FC mode requested by caller */
 };
@@ -2075,6 +2319,12 @@
 	u64 fdirfstat_fremove;
 	u64 fdirmatch;
 	u64 fdirmiss;
+	u64 fccrc;
+	u64 fcoerpdc;
+	u64 fcoeprc;
+	u64 fcoeptc;
+	u64 fcoedwrc;
+	u64 fcoedwtc;
 };
 
 /* forward declaration */
@@ -2101,6 +2351,8 @@
 	enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
 	u32 (*get_supported_physical_layer)(struct ixgbe_hw *);
 	s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
+	s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *);
+	s32 (*get_device_caps)(struct ixgbe_hw *, u16 *);
 	s32 (*stop_adapter)(struct ixgbe_hw *);
 	s32 (*get_bus_info)(struct ixgbe_hw *);
 	void (*set_lan_id)(struct ixgbe_hw *);
@@ -2129,8 +2381,7 @@
 	s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32);
 	s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32);
 	s32 (*init_rx_addrs)(struct ixgbe_hw *);
-	s32 (*update_uc_addr_list)(struct ixgbe_hw *, u8 *, u32,
-	                           ixgbe_mc_addr_itr);
+	s32 (*update_uc_addr_list)(struct ixgbe_hw *, struct list_head *);
 	s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32,
 	                           ixgbe_mc_addr_itr);
 	s32 (*enable_mc)(struct ixgbe_hw *);
@@ -2140,12 +2391,13 @@
 	s32 (*init_uta_tables)(struct ixgbe_hw *);
 
 	/* Flow Control */
-	s32 (*setup_fc)(struct ixgbe_hw *, s32);
+	s32 (*fc_enable)(struct ixgbe_hw *, s32);
 };
 
 struct ixgbe_phy_operations {
 	s32 (*identify)(struct ixgbe_hw *);
 	s32 (*identify_sfp)(struct ixgbe_hw *);
+	s32 (*init)(struct ixgbe_hw *);
 	s32 (*reset)(struct ixgbe_hw *);
 	s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *);
 	s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16);
@@ -2173,6 +2425,7 @@
 	enum ixgbe_mac_type             type;
 	u8                              addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
 	u8                              perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
+	u8                              san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
 	s32                             mc_filter_type;
 	u32                             mcft_size;
 	u32                             vft_size;
@@ -2185,14 +2438,16 @@
 	bool                            orig_link_settings_stored;
 	bool                            autoneg;
 	bool                            autoneg_succeeded;
+	bool                            autotry_restart;
 };
 
 struct ixgbe_phy_info {
 	struct ixgbe_phy_operations     ops;
+	struct mdio_if_info		mdio;
 	enum ixgbe_phy_type             type;
-	u32                             addr;
 	u32                             id;
 	enum ixgbe_sfp_type             sfp_type;
+	bool                            sfp_setup_needed;
 	u32                             revision;
 	enum ixgbe_media_type           media_type;
 	bool                            reset_disable;
@@ -2249,6 +2504,8 @@
 #define IXGBE_ERR_SFP_NOT_SUPPORTED             -19
 #define IXGBE_ERR_SFP_NOT_PRESENT               -20
 #define IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT       -21
+#define IXGBE_ERR_FDIR_REINIT_FAILED            -23
+#define IXGBE_ERR_EEPROM_VERSION                -24
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
 
 #endif /* _IXGBE_TYPE_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixgbe/Makefile linux-libre-2.6.31-gnu/drivers/net/ixgbe/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/ixgbe/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixgbe/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -37,3 +37,5 @@
 
 ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
                               ixgbe_dcb_82599.o ixgbe_dcb_nl.o
+
+ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/ixp2000/ixpdev.c linux-libre-2.6.31-gnu/drivers/net/ixp2000/ixpdev.c
--- linux-libre-2.6.30-gnu/drivers/net/ixp2000/ixpdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ixp2000/ixpdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,6 +41,7 @@
 	struct ixpdev_priv *ip = netdev_priv(dev);
 	struct ixpdev_tx_desc *desc;
 	int entry;
+	unsigned long flags;
 
 	if (unlikely(skb->len > PAGE_SIZE)) {
 		/* @@@ Count drops.  */
@@ -63,11 +64,11 @@
 
 	dev->trans_start = jiffies;
 
-	local_irq_disable();
+	local_irq_save(flags);
 	ip->tx_queue_entries++;
 	if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
 		netif_stop_queue(dev);
-	local_irq_enable();
+	local_irq_restore(flags);
 
 	return 0;
 }
@@ -270,6 +271,18 @@
 	return 0;
 }
 
+static const struct net_device_ops ixpdev_netdev_ops = {
+	.ndo_open		= ixpdev_open,
+	.ndo_stop		= ixpdev_close,
+	.ndo_start_xmit		= ixpdev_xmit,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= ixpdev_poll_controller,
+#endif
+};
+
 struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
 {
 	struct net_device *dev;
@@ -279,12 +292,7 @@
 	if (dev == NULL)
 		return NULL;
 
-	dev->hard_start_xmit = ixpdev_xmit;
-	dev->open = ixpdev_open;
-	dev->stop = ixpdev_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = ixpdev_poll_controller;
-#endif
+	dev->netdev_ops = &ixpdev_netdev_ops;
 
 	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/jazzsonic.c linux-libre-2.6.31-gnu/drivers/net/jazzsonic.c
--- linux-libre-2.6.30-gnu/drivers/net/jazzsonic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/jazzsonic.c	2009-09-09 18:13:59.000000000 -0400
@@ -96,6 +96,18 @@
 	return err;
 }
 
+static const struct net_device_ops sonic_netdev_ops = {
+	.ndo_open		= jazzsonic_open,
+	.ndo_stop		= jazzsonic_close,
+	.ndo_start_xmit		= sonic_send_packet,
+	.ndo_get_stats		= sonic_get_stats,
+	.ndo_set_multicast_list	= sonic_multicast_list,
+	.ndo_tx_timeout		= sonic_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
 static int __init sonic_probe1(struct net_device *dev)
 {
 	static unsigned version_printed;
@@ -179,12 +191,7 @@
 	lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
 	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
 
-	dev->open = jazzsonic_open;
-	dev->stop = jazzsonic_close;
-	dev->hard_start_xmit = sonic_send_packet;
-	dev->get_stats = sonic_get_stats;
-	dev->set_multicast_list = &sonic_multicast_list;
-	dev->tx_timeout = sonic_tx_timeout;
+	dev->netdev_ops = &sonic_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	/*
@@ -222,6 +229,7 @@
 	lp = netdev_priv(dev);
 	lp->device = &pdev->dev;
 	SET_NETDEV_DEV(dev, &pdev->dev);
+	platform_set_drvdata(pdev, dev);
 
 	netdev_boot_setup_check(dev);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/jme.c linux-libre-2.6.31-gnu/drivers/net/jme.c
--- linux-libre-2.6.30-gnu/drivers/net/jme.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/jme.c	2009-09-09 18:13:59.000000000 -0400
@@ -1939,7 +1939,6 @@
 				TXCS_SELECT_QUEUE0 |
 				TXCS_QUEUE0S |
 				TXCS_ENABLE);
-	netdev->trans_start = jiffies;
 
 	tx_dbg(jme, "xmit: %d+%d@%lu\n", idx,
 			skb_shinfo(skb)->nr_frags + 2,
diff -druN linux-libre-2.6.30-gnu/drivers/net/Kconfig linux-libre-2.6.31-gnu/drivers/net/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,4 +1,3 @@
-
 #
 # Network device configuration
 #
@@ -26,15 +25,6 @@
 # that for each of the symbols.
 if NETDEVICES
 
-config COMPAT_NET_DEV_OPS
-       default y
-       bool "Enable older network device API compatibility"
-       ---help---
-          This option enables kernel compatibility with older network devices
-          that do not use net_device_ops interface.
-
-	  If unsure, say Y.
-
 config IFB
 	tristate "Intermediate Functional Block support"
 	depends on NET_CLS_ACT
@@ -526,15 +516,16 @@
 config SH_ETH
 	tristate "Renesas SuperH Ethernet support"
 	depends on SUPERH && \
-		(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7763 || \
-		 CPU_SUBTYPE_SH7619)
+		(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
+		 CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
+		 CPU_SUBTYPE_SH7724)
 	select CRC32
 	select MII
 	select MDIO_BITBANG
 	select PHYLIB
 	help
 	  Renesas SuperH Ethernet device driver.
-	  This driver support SH7710, SH7712, SH7763 and SH7619.
+	  This driver support SH7710, SH7712, SH7763, SH7619, and SH7724.
 
 config SUNLANCE
 	tristate "Sun LANCE support"
@@ -927,6 +918,16 @@
 	  To compile this driver as a module, choose M here. The module
 	  will be called netx-eth.
 
+config TI_DAVINCI_EMAC
+	tristate "TI DaVinci EMAC Support"
+	depends on ARM && ARCH_DAVINCI
+	select PHYLIB
+	help
+	  This driver supports TI's DaVinci Ethernet .
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called davinci_emac_driver.  This is recommended.
+
 config DM9000
 	tristate "DM9000 support"
 	depends on ARM || BLACKFIN || MIPS
@@ -1000,7 +1001,7 @@
 
 config SMSC911X
 	tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
-	depends on ARM || SUPERH
+	depends on ARM || SUPERH || BLACKFIN
 	select CRC32
 	select MII
 	select PHYLIB
@@ -1722,6 +1723,21 @@
 
 	  Please email feedback to <torben.mathiasen@compaq.com>.
 
+config KS8842
+	tristate "Micrel KSZ8842"
+	depends on HAS_IOMEM
+	help
+	  This platform driver is for Micrel KSZ8842 / KS8842
+	  2-port ethernet switch chip (managed, VLAN, QoS).
+
+config KS8851
+       tristate "Micrel KS8851 SPI"
+       depends on SPI
+       select MII
+	select CRC32
+       help
+         SPI driver for Micrel KS8851 SPI attached network chip.
+
 config VIA_RHINE
 	tristate "VIA Rhine support"
 	depends on NET_PCI && PCI
@@ -1858,8 +1874,8 @@
 	  the Motorola 68360 processor.
 
 config FEC
-	bool "FEC ethernet controller (of ColdFire CPUs)"
-	depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27
+	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
+	depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
 	  controller on some Motorola ColdFire and Freescale i.MX processors.
@@ -1880,7 +1896,7 @@
 	---help---
 	  This option enables support for the MPC5200's on-chip
 	  Fast Ethernet Controller
-	  If compiled as module, it will be called 'fec_mpc52xx.ko'.
+	  If compiled as module, it will be called fec_mpc52xx.
 
 config FEC_MPC52xx_MDIO
 	bool "MPC52xx FEC MDIO bus driver"
@@ -1892,7 +1908,7 @@
 	  (Motorola? industry standard).
 	  If your board uses an external PHY connected to FEC, enable this.
 	  If not sure, enable.
-	  If compiled as module, it will be called 'fec_mpc52xx_phy.ko'.
+	  If compiled as module, it will be called fec_mpc52xx_phy.
 
 config NE_H8300
 	tristate "NE2000 compatible support for H8/300"
@@ -2200,7 +2216,7 @@
        depends on SKGE && DEBUG_FS
        help
 	 This option adds the ability to dump driver state for debugging.
-	 The file debugfs/skge/ethX displays the state of the internal
+	 The file /sys/kernel/debug/skge/ethX displays the state of the internal
 	 transmit and receive rings.
 
 	 If unsure, say N.
@@ -2226,7 +2242,7 @@
        depends on SKY2 && DEBUG_FS
        help
 	 This option adds the ability to dump driver state for debugging.
-	 The file debugfs/sky2/ethX displays the state of the internal
+	 The file /sys/kernel/debug/sky2/ethX displays the state of the internal
 	 transmit and receive rings.
 
 	 If unsure, say N.
@@ -2264,6 +2280,18 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called bnx2.  This is recommended.
 
+config CNIC
+	tristate "Broadcom CNIC support"
+	depends on PCI
+	select BNX2
+	select UIO
+	help
+	  This driver supports offload features of Broadcom NetXtremeII
+	  gigabit Ethernet cards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called cnic.  This is recommended.
+
 config SPIDER_NET
 	tristate "Spider Gigabit Ethernet driver"
 	depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB)
@@ -2351,7 +2379,7 @@
 
 config MV643XX_ETH
 	tristate "Marvell Discovery (643XX) and Orion ethernet support"
-	depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION
+	depends on MV64X60 || PPC32 || PLAT_ORION
 	select INET_LRO
 	select PHYLIB
 	help
@@ -2362,6 +2390,14 @@
 	  Some boards that use the Discovery chipset are the Momenco
 	  Ocelot C and Jaguar ATX and Pegasos II.
 
+config XILINX_LL_TEMAC
+	tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
+	select PHYLIB
+	depends on PPC_DCR_NATIVE
+	help
+	  This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
+	  core used in Xilinx Spartan and Virtex FPGAs
+
 config QLA3XXX
 	tristate "QLogic QLA3XXX Network Driver Support"
 	depends on PCI
@@ -2417,6 +2453,17 @@
 	  To compile this driver as a module, choose M here. The module
 	  will be called jme.
 
+config S6GMAC
+	tristate "S6105 GMAC ethernet support"
+	depends on XTENSA_VARIANT_S6000
+	select PHYLIB
+	help
+	  This driver supports the on chip ethernet device on the
+	  S6105 xtensa processor.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called s6gmac.
+
 endif # NETDEV_1000
 
 #
@@ -2435,10 +2482,14 @@
 
 if NETDEV_10000
 
+config MDIO
+	tristate
+
 config CHELSIO_T1
         tristate "Chelsio 10Gb Ethernet support"
         depends on PCI
 	select CRC32
+	select MDIO
         help
           This driver supports Chelsio gigabit and 10-gigabit
           Ethernet cards. More information about adapter features and
@@ -2471,6 +2522,7 @@
 	tristate "Chelsio Communications T3 10Gb Ethernet support"
 	depends on CHELSIO_T3_DEPENDS
 	select FW_LOADER
+	select MDIO
 	help
 	  This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
 	  adapters.
@@ -2506,6 +2558,7 @@
 config IXGBE
 	tristate "Intel(R) 10GbE PCI Express adapters support"
 	depends on PCI && INET
+	select MDIO
 	---help---
 	  This driver supports Intel(R) 10GbE PCI Express family of
 	  adapters.  For more information on how to identify your adapter, go
@@ -2668,6 +2721,7 @@
 config BNX2X
 	tristate "Broadcom NetXtremeII 10Gb support"
 	depends on PCI
+	select FW_LOADER
 	select ZLIB_INFLATE
 	select LIBCRC32C
 	help
@@ -2704,6 +2758,8 @@
 
 source "drivers/atm/Kconfig"
 
+source "drivers/ieee802154/Kconfig"
+
 source "drivers/s390/net/Kconfig"
 
 config XEN_NETDEV_FRONTEND
diff -druN linux-libre-2.6.30-gnu/drivers/net/korina.c linux-libre-2.6.31-gnu/drivers/net/korina.c
--- linux-libre-2.6.30-gnu/drivers/net/korina.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/korina.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,6 +133,7 @@
 	int dma_halt_cnt;
 	int dma_run_cnt;
 	struct napi_struct napi;
+	struct timer_list media_check_timer;
 	struct mii_if_info mii_if;
 	struct net_device *dev;
 	int phy_addr;
@@ -664,6 +665,15 @@
 						&lp->eth_regs->ethmac2);
 }
 
+static void korina_poll_media(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct korina_private *lp = netdev_priv(dev);
+
+	korina_check_media(dev, 0);
+	mod_timer(&lp->media_check_timer, jiffies + HZ);
+}
+
 static void korina_set_carrier(struct mii_if_info *mii)
 {
 	if (mii->force_media) {
@@ -1034,6 +1044,7 @@
 		    dev->name, lp->und_irq);
 		goto err_free_ovr_irq;
 	}
+	mod_timer(&lp->media_check_timer, jiffies + 1);
 out:
 	return ret;
 
@@ -1053,6 +1064,8 @@
 	struct korina_private *lp = netdev_priv(dev);
 	u32 tmp;
 
+	del_timer(&lp->media_check_timer);
+
 	/* Disable interrupts */
 	disable_irq(lp->rx_irq);
 	disable_irq(lp->tx_irq);
@@ -1081,6 +1094,21 @@
 	return 0;
 }
 
+static const struct net_device_ops korina_netdev_ops = {
+	.ndo_open		= korina_open,
+	.ndo_stop		= korina_close,
+	.ndo_start_xmit		= korina_send_packet,
+	.ndo_set_multicast_list	= korina_multicast_list,
+	.ndo_tx_timeout		= korina_tx_timeout,
+	.ndo_do_ioctl		= korina_ioctl,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= korina_poll_controller,
+#endif
+};
+
 static int korina_probe(struct platform_device *pdev)
 {
 	struct korina_device *bif = platform_get_drvdata(pdev);
@@ -1149,17 +1177,9 @@
 	dev->irq = lp->rx_irq;
 	lp->dev = dev;
 
-	dev->open = korina_open;
-	dev->stop = korina_close;
-	dev->hard_start_xmit = korina_send_packet;
-	dev->set_multicast_list = &korina_multicast_list;
+	dev->netdev_ops = &korina_netdev_ops;
 	dev->ethtool_ops = &netdev_ethtool_ops;
-	dev->tx_timeout = korina_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->do_ioctl = &korina_ioctl;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = korina_poll_controller;
-#endif
 	netif_napi_add(dev, &lp->napi, korina_poll, 64);
 
 	lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05);
@@ -1176,6 +1196,7 @@
 			": cannot register net device %d\n", rc);
 		goto probe_err_register;
 	}
+	setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev);
 out:
 	return rc;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ks8842.c linux-libre-2.6.31-gnu/drivers/net/ks8842.c
--- linux-libre-2.6.30-gnu/drivers/net/ks8842.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ks8842.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,732 @@
+/*
+ * ks8842_main.c timberdale KS8842 ethernet driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * The Micrel KS8842 behind the timberdale FPGA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+
+#define DRV_NAME "ks8842"
+
+/* Timberdale specific Registers */
+#define REG_TIMB_RST	0x1c
+
+/* KS8842 registers */
+
+#define REG_SELECT_BANK 0x0e
+
+/* bank 0 registers */
+#define REG_QRFCR	0x04
+
+/* bank 2 registers */
+#define REG_MARL	0x00
+#define REG_MARM	0x02
+#define REG_MARH	0x04
+
+/* bank 3 registers */
+#define REG_GRR		0x06
+
+/* bank 16 registers */
+#define REG_TXCR	0x00
+#define REG_TXSR	0x02
+#define REG_RXCR	0x04
+#define REG_TXMIR	0x08
+#define REG_RXMIR	0x0A
+
+/* bank 17 registers */
+#define REG_TXQCR	0x00
+#define REG_RXQCR	0x02
+#define REG_TXFDPR	0x04
+#define REG_RXFDPR	0x06
+#define REG_QMU_DATA_LO 0x08
+#define REG_QMU_DATA_HI 0x0A
+
+/* bank 18 registers */
+#define REG_IER		0x00
+#define IRQ_LINK_CHANGE	0x8000
+#define IRQ_TX		0x4000
+#define IRQ_RX		0x2000
+#define IRQ_RX_OVERRUN	0x0800
+#define IRQ_TX_STOPPED	0x0200
+#define IRQ_RX_STOPPED	0x0100
+#define IRQ_RX_ERROR	0x0080
+#define ENABLED_IRQS	(IRQ_LINK_CHANGE | IRQ_TX | IRQ_RX | IRQ_RX_STOPPED | \
+		IRQ_TX_STOPPED | IRQ_RX_OVERRUN | IRQ_RX_ERROR)
+#define REG_ISR		0x02
+#define REG_RXSR	0x04
+#define RXSR_VALID	0x8000
+#define RXSR_BROADCAST	0x80
+#define RXSR_MULTICAST	0x40
+#define RXSR_UNICAST	0x20
+#define RXSR_FRAMETYPE	0x08
+#define RXSR_TOO_LONG	0x04
+#define RXSR_RUNT	0x02
+#define RXSR_CRC_ERROR	0x01
+#define RXSR_ERROR	(RXSR_TOO_LONG | RXSR_RUNT | RXSR_CRC_ERROR)
+
+/* bank 32 registers */
+#define REG_SW_ID_AND_ENABLE	0x00
+#define REG_SGCR1		0x02
+#define REG_SGCR2		0x04
+#define REG_SGCR3		0x06
+
+/* bank 39 registers */
+#define REG_MACAR1		0x00
+#define REG_MACAR2		0x02
+#define REG_MACAR3		0x04
+
+/* bank 45 registers */
+#define REG_P1MBCR		0x00
+#define REG_P1MBSR		0x02
+
+/* bank 46 registers */
+#define REG_P2MBCR		0x00
+#define REG_P2MBSR		0x02
+
+/* bank 48 registers */
+#define REG_P1CR2		0x02
+
+/* bank 49 registers */
+#define REG_P1CR4		0x02
+#define REG_P1SR		0x04
+
+struct ks8842_adapter {
+	void __iomem	*hw_addr;
+	int		irq;
+	struct tasklet_struct	tasklet;
+	spinlock_t	lock; /* spinlock to be interrupt safe */
+	struct platform_device *pdev;
+};
+
+static inline void ks8842_select_bank(struct ks8842_adapter *adapter, u16 bank)
+{
+	iowrite16(bank, adapter->hw_addr + REG_SELECT_BANK);
+}
+
+static inline void ks8842_write8(struct ks8842_adapter *adapter, u16 bank,
+	u8 value, int offset)
+{
+	ks8842_select_bank(adapter, bank);
+	iowrite8(value, adapter->hw_addr + offset);
+}
+
+static inline void ks8842_write16(struct ks8842_adapter *adapter, u16 bank,
+	u16 value, int offset)
+{
+	ks8842_select_bank(adapter, bank);
+	iowrite16(value, adapter->hw_addr + offset);
+}
+
+static inline void ks8842_enable_bits(struct ks8842_adapter *adapter, u16 bank,
+	u16 bits, int offset)
+{
+	u16 reg;
+	ks8842_select_bank(adapter, bank);
+	reg = ioread16(adapter->hw_addr + offset);
+	reg |= bits;
+	iowrite16(reg, adapter->hw_addr + offset);
+}
+
+static inline void ks8842_clear_bits(struct ks8842_adapter *adapter, u16 bank,
+	u16 bits, int offset)
+{
+	u16 reg;
+	ks8842_select_bank(adapter, bank);
+	reg = ioread16(adapter->hw_addr + offset);
+	reg &= ~bits;
+	iowrite16(reg, adapter->hw_addr + offset);
+}
+
+static inline void ks8842_write32(struct ks8842_adapter *adapter, u16 bank,
+	u32 value, int offset)
+{
+	ks8842_select_bank(adapter, bank);
+	iowrite32(value, adapter->hw_addr + offset);
+}
+
+static inline u8 ks8842_read8(struct ks8842_adapter *adapter, u16 bank,
+	int offset)
+{
+	ks8842_select_bank(adapter, bank);
+	return ioread8(adapter->hw_addr + offset);
+}
+
+static inline u16 ks8842_read16(struct ks8842_adapter *adapter, u16 bank,
+	int offset)
+{
+	ks8842_select_bank(adapter, bank);
+	return ioread16(adapter->hw_addr + offset);
+}
+
+static inline u32 ks8842_read32(struct ks8842_adapter *adapter, u16 bank,
+	int offset)
+{
+	ks8842_select_bank(adapter, bank);
+	return ioread32(adapter->hw_addr + offset);
+}
+
+static void ks8842_reset(struct ks8842_adapter *adapter)
+{
+	/* The KS8842 goes haywire when doing softare reset
+	 * a work around in the timberdale IP is implemented to
+	 * do a hardware reset instead
+	ks8842_write16(adapter, 3, 1, REG_GRR);
+	msleep(10);
+	iowrite16(0, adapter->hw_addr + REG_GRR);
+	*/
+	iowrite16(32, adapter->hw_addr + REG_SELECT_BANK);
+	iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST);
+	msleep(20);
+}
+
+static void ks8842_update_link_status(struct net_device *netdev,
+	struct ks8842_adapter *adapter)
+{
+	/* check the status of the link */
+	if (ks8842_read16(adapter, 45, REG_P1MBSR) & 0x4) {
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
+	} else {
+		netif_stop_queue(netdev);
+		netif_carrier_off(netdev);
+	}
+}
+
+static void ks8842_enable_tx(struct ks8842_adapter *adapter)
+{
+	ks8842_enable_bits(adapter, 16, 0x01, REG_TXCR);
+}
+
+static void ks8842_disable_tx(struct ks8842_adapter *adapter)
+{
+	ks8842_clear_bits(adapter, 16, 0x01, REG_TXCR);
+}
+
+static void ks8842_enable_rx(struct ks8842_adapter *adapter)
+{
+	ks8842_enable_bits(adapter, 16, 0x01, REG_RXCR);
+}
+
+static void ks8842_disable_rx(struct ks8842_adapter *adapter)
+{
+	ks8842_clear_bits(adapter, 16, 0x01, REG_RXCR);
+}
+
+static void ks8842_reset_hw(struct ks8842_adapter *adapter)
+{
+	/* reset the HW */
+	ks8842_reset(adapter);
+
+	/* Enable QMU Transmit flow control / transmit padding / Transmit CRC */
+	ks8842_write16(adapter, 16, 0x000E, REG_TXCR);
+
+	/* enable the receiver, uni + multi + broadcast + flow ctrl
+		+ crc strip */
+	ks8842_write16(adapter, 16, 0x8 | 0x20 | 0x40 | 0x80 | 0x400,
+		REG_RXCR);
+
+	/* TX frame pointer autoincrement */
+	ks8842_write16(adapter, 17, 0x4000, REG_TXFDPR);
+
+	/* RX frame pointer autoincrement */
+	ks8842_write16(adapter, 17, 0x4000, REG_RXFDPR);
+
+	/* RX 2 kb high watermark */
+	ks8842_write16(adapter, 0, 0x1000, REG_QRFCR);
+
+	/* aggresive back off in half duplex */
+	ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1);
+
+	/* enable no excessive collison drop */
+	ks8842_enable_bits(adapter, 32, 1 << 3, REG_SGCR2);
+
+	/* Enable port 1 force flow control / back pressure / transmit / recv */
+	ks8842_write16(adapter, 48, 0x1E07, REG_P1CR2);
+
+	/* restart port auto-negotiation */
+	ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4);
+	/* only advertise 10Mbps */
+	ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4);
+
+	/* Enable the transmitter */
+	ks8842_enable_tx(adapter);
+
+	/* Enable the receiver */
+	ks8842_enable_rx(adapter);
+
+	/* clear all interrupts */
+	ks8842_write16(adapter, 18, 0xffff, REG_ISR);
+
+	/* enable interrupts */
+	ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER);
+
+	/* enable the switch */
+	ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE);
+}
+
+static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest)
+{
+	int i;
+	u16 mac;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i);
+
+	/* make sure the switch port uses the same MAC as the QMU */
+	mac = ks8842_read16(adapter, 2, REG_MARL);
+	ks8842_write16(adapter, 39, mac, REG_MACAR1);
+	mac = ks8842_read16(adapter, 2, REG_MARM);
+	ks8842_write16(adapter, 39, mac, REG_MACAR2);
+	mac = ks8842_read16(adapter, 2, REG_MARH);
+	ks8842_write16(adapter, 39, mac, REG_MACAR3);
+}
+
+static inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter)
+{
+	return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff;
+}
+
+static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+	int len = skb->len;
+	u32 *ptr = (u32 *)skb->data;
+	u32 ctrl;
+
+	dev_dbg(&adapter->pdev->dev,
+		"%s: len %u head %p data %p tail %p end %p\n",
+		__func__, skb->len, skb->head, skb->data,
+		skb_tail_pointer(skb), skb_end_pointer(skb));
+
+	/* check FIFO buffer space, we need space for CRC and command bits */
+	if (ks8842_tx_fifo_space(adapter) < len + 8)
+		return NETDEV_TX_BUSY;
+
+	/* the control word, enable IRQ, port 1 and the length */
+	ctrl = 0x8000 | 0x100 | (len << 16);
+	ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO);
+
+	netdev->stats.tx_bytes += len;
+
+	/* copy buffer */
+	while (len > 0) {
+		iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO);
+		len -= sizeof(u32);
+		ptr++;
+	}
+
+	/* enqueue packet */
+	ks8842_write16(adapter, 17, 1, REG_TXQCR);
+
+	dev_kfree_skb(skb);
+
+	return NETDEV_TX_OK;
+}
+
+static void ks8842_rx_frame(struct net_device *netdev,
+	struct ks8842_adapter *adapter)
+{
+	u32 status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO);
+	int len = (status >> 16) & 0x7ff;
+
+	status &= 0xffff;
+
+	dev_dbg(&adapter->pdev->dev, "%s - rx_data: status: %x\n",
+		__func__, status);
+
+	/* check the status */
+	if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
+		struct sk_buff *skb = netdev_alloc_skb(netdev, len + 2);
+
+		dev_dbg(&adapter->pdev->dev, "%s, got package, len: %d\n",
+			__func__, len);
+		if (skb) {
+			u32 *data;
+
+			netdev->stats.rx_packets++;
+			netdev->stats.rx_bytes += len;
+			if (status & RXSR_MULTICAST)
+				netdev->stats.multicast++;
+
+			/* Align socket buffer in 4-byte boundary for
+				 better performance. */
+			skb_reserve(skb, 2);
+			data = (u32 *)skb_put(skb, len);
+
+			ks8842_select_bank(adapter, 17);
+			while (len > 0) {
+				*data++ = ioread32(adapter->hw_addr +
+					REG_QMU_DATA_LO);
+				len -= sizeof(u32);
+			}
+
+			skb->protocol = eth_type_trans(skb, netdev);
+			netif_rx(skb);
+		} else
+			netdev->stats.rx_dropped++;
+	} else {
+		dev_dbg(&adapter->pdev->dev, "RX error, status: %x\n", status);
+		netdev->stats.rx_errors++;
+		if (status & RXSR_TOO_LONG)
+			netdev->stats.rx_length_errors++;
+		if (status & RXSR_CRC_ERROR)
+			netdev->stats.rx_crc_errors++;
+		if (status & RXSR_RUNT)
+			netdev->stats.rx_frame_errors++;
+	}
+
+	/* set high watermark to 3K */
+	ks8842_clear_bits(adapter, 0, 1 << 12, REG_QRFCR);
+
+	/* release the frame */
+	ks8842_write16(adapter, 17, 0x01, REG_RXQCR);
+
+	/* set high watermark to 2K */
+	ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR);
+}
+
+void ks8842_handle_rx(struct net_device *netdev, struct ks8842_adapter *adapter)
+{
+	u16 rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
+	dev_dbg(&adapter->pdev->dev, "%s Entry - rx_data: %d\n",
+		__func__, rx_data);
+	while (rx_data) {
+		ks8842_rx_frame(netdev, adapter);
+		rx_data = ks8842_read16(adapter, 16, REG_RXMIR) & 0x1fff;
+	}
+}
+
+void ks8842_handle_tx(struct net_device *netdev, struct ks8842_adapter *adapter)
+{
+	u16 sr = ks8842_read16(adapter, 16, REG_TXSR);
+	dev_dbg(&adapter->pdev->dev, "%s - entry, sr: %x\n", __func__, sr);
+	netdev->stats.tx_packets++;
+	if (netif_queue_stopped(netdev))
+		netif_wake_queue(netdev);
+}
+
+void ks8842_handle_rx_overrun(struct net_device *netdev,
+	struct ks8842_adapter *adapter)
+{
+	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+	netdev->stats.rx_errors++;
+	netdev->stats.rx_fifo_errors++;
+}
+
+void ks8842_tasklet(unsigned long arg)
+{
+	struct net_device *netdev = (struct net_device *)arg;
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+	u16 isr;
+	unsigned long flags;
+	u16 entry_bank;
+
+	/* read current bank to be able to set it back */
+	spin_lock_irqsave(&adapter->lock, flags);
+	entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+
+	isr = ks8842_read16(adapter, 18, REG_ISR);
+	dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr);
+
+	/* Ack */
+	ks8842_write16(adapter, 18, isr, REG_ISR);
+
+	if (!netif_running(netdev))
+		return;
+
+	if (isr & IRQ_LINK_CHANGE)
+		ks8842_update_link_status(netdev, adapter);
+
+	if (isr & (IRQ_RX | IRQ_RX_ERROR))
+		ks8842_handle_rx(netdev, adapter);
+
+	if (isr & IRQ_TX)
+		ks8842_handle_tx(netdev, adapter);
+
+	if (isr & IRQ_RX_OVERRUN)
+		ks8842_handle_rx_overrun(netdev, adapter);
+
+	if (isr & IRQ_TX_STOPPED) {
+		ks8842_disable_tx(adapter);
+		ks8842_enable_tx(adapter);
+	}
+
+	if (isr & IRQ_RX_STOPPED) {
+		ks8842_disable_rx(adapter);
+		ks8842_enable_rx(adapter);
+	}
+
+	/* re-enable interrupts, put back the bank selection register */
+	spin_lock_irqsave(&adapter->lock, flags);
+	ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER);
+	iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+static irqreturn_t ks8842_irq(int irq, void *devid)
+{
+	struct ks8842_adapter *adapter = devid;
+	u16 isr;
+	u16 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK);
+	irqreturn_t ret = IRQ_NONE;
+
+	isr = ks8842_read16(adapter, 18, REG_ISR);
+	dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr);
+
+	if (isr) {
+		/* disable IRQ */
+		ks8842_write16(adapter, 18, 0x00, REG_IER);
+
+		/* schedule tasklet */
+		tasklet_schedule(&adapter->tasklet);
+
+		ret = IRQ_HANDLED;
+	}
+
+	iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK);
+
+	return ret;
+}
+
+
+/* Netdevice operations */
+
+static int ks8842_open(struct net_device *netdev)
+{
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+	int err;
+
+	dev_dbg(&adapter->pdev->dev, "%s - entry\n", __func__);
+
+	/* reset the HW */
+	ks8842_reset_hw(adapter);
+
+	ks8842_update_link_status(netdev, adapter);
+
+	err = request_irq(adapter->irq, ks8842_irq, IRQF_SHARED, DRV_NAME,
+		adapter);
+	if (err) {
+		printk(KERN_ERR "Failed to request IRQ: %d: %d\n",
+			adapter->irq, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int ks8842_close(struct net_device *netdev)
+{
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+
+	dev_dbg(&adapter->pdev->dev, "%s - entry\n", __func__);
+
+	/* free the irq */
+	free_irq(adapter->irq, adapter);
+
+	/* disable the switch */
+	ks8842_write16(adapter, 32, 0x0, REG_SW_ID_AND_ENABLE);
+
+	return 0;
+}
+
+static int ks8842_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	int ret;
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+
+	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+
+	ret = ks8842_tx_frame(skb, netdev);
+
+	if (ks8842_tx_fifo_space(adapter) <  netdev->mtu + 8)
+		netif_stop_queue(netdev);
+
+	return ret;
+}
+
+static int ks8842_set_mac(struct net_device *netdev, void *p)
+{
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	struct sockaddr *addr = p;
+	char *mac = (u8 *)addr->sa_data;
+	int i;
+
+	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, mac, netdev->addr_len);
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	for (i = 0; i < ETH_ALEN; i++) {
+		ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i);
+		ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1],
+			REG_MACAR1 + i);
+	}
+	spin_unlock_irqrestore(&adapter->lock, flags);
+	return 0;
+}
+
+static void ks8842_tx_timeout(struct net_device *netdev)
+{
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+
+	dev_dbg(&adapter->pdev->dev, "%s: entry\n", __func__);
+
+	spin_lock_irqsave(&adapter->lock, flags);
+	/* disable interrupts */
+	ks8842_write16(adapter, 18, 0, REG_IER);
+	ks8842_write16(adapter, 18, 0xFFFF, REG_ISR);
+	spin_unlock_irqrestore(&adapter->lock, flags);
+
+	ks8842_reset_hw(adapter);
+
+	ks8842_update_link_status(netdev, adapter);
+}
+
+static const struct net_device_ops ks8842_netdev_ops = {
+	.ndo_open		= ks8842_open,
+	.ndo_stop		= ks8842_close,
+	.ndo_start_xmit		= ks8842_xmit_frame,
+	.ndo_set_mac_address	= ks8842_set_mac,
+	.ndo_tx_timeout 	= ks8842_tx_timeout,
+	.ndo_validate_addr	= eth_validate_addr
+};
+
+static struct ethtool_ops ks8842_ethtool_ops = {
+	.get_link		= ethtool_op_get_link,
+};
+
+static int __devinit ks8842_probe(struct platform_device *pdev)
+{
+	int err = -ENOMEM;
+	struct resource *iomem;
+	struct net_device *netdev;
+	struct ks8842_adapter *adapter;
+	u16 id;
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME))
+		goto err_mem_region;
+
+	netdev = alloc_etherdev(sizeof(struct ks8842_adapter));
+	if (!netdev)
+		goto err_alloc_etherdev;
+
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	adapter = netdev_priv(netdev);
+	adapter->hw_addr = ioremap(iomem->start, resource_size(iomem));
+	if (!adapter->hw_addr)
+		goto err_ioremap;
+
+	adapter->irq = platform_get_irq(pdev, 0);
+	if (adapter->irq < 0) {
+		err = adapter->irq;
+		goto err_get_irq;
+	}
+
+	adapter->pdev = pdev;
+
+	tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev);
+	spin_lock_init(&adapter->lock);
+
+	netdev->netdev_ops = &ks8842_netdev_ops;
+	netdev->ethtool_ops = &ks8842_ethtool_ops;
+
+	ks8842_read_mac_addr(adapter, netdev->dev_addr);
+
+	id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE);
+
+	strcpy(netdev->name, "eth%d");
+	err = register_netdev(netdev);
+	if (err)
+		goto err_register;
+
+	platform_set_drvdata(pdev, netdev);
+
+	printk(KERN_INFO DRV_NAME
+		" Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n",
+		(id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7);
+
+	return 0;
+
+err_register:
+err_get_irq:
+	iounmap(adapter->hw_addr);
+err_ioremap:
+	free_netdev(netdev);
+err_alloc_etherdev:
+	release_mem_region(iomem->start, resource_size(iomem));
+err_mem_region:
+	return err;
+}
+
+static int __devexit ks8842_remove(struct platform_device *pdev)
+{
+	struct net_device *netdev = platform_get_drvdata(pdev);
+	struct ks8842_adapter *adapter = netdev_priv(netdev);
+	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	unregister_netdev(netdev);
+	tasklet_kill(&adapter->tasklet);
+	iounmap(adapter->hw_addr);
+	free_netdev(netdev);
+	release_mem_region(iomem->start, resource_size(iomem));
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+
+static struct platform_driver ks8842_platform_driver = {
+	.driver = {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ks8842_probe,
+	.remove		= ks8842_remove,
+};
+
+static int __init ks8842_init(void)
+{
+	return platform_driver_register(&ks8842_platform_driver);
+}
+
+static void __exit ks8842_exit(void)
+{
+	platform_driver_unregister(&ks8842_platform_driver);
+}
+
+module_init(ks8842_init);
+module_exit(ks8842_exit);
+
+MODULE_DESCRIPTION("Timberdale KS8842 ethernet driver");
+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ks8842");
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/ks8851.c linux-libre-2.6.31-gnu/drivers/net/ks8851.c
--- linux-libre-2.6.30-gnu/drivers/net/ks8851.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ks8851.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1322 @@
+/* drivers/net/ks8651.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *	http://www.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+ */
+
+#define DEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/cache.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+
+#include <linux/spi/spi.h>
+
+#include "ks8851.h"
+
+/**
+ * struct ks8851_rxctrl - KS8851 driver rx control
+ * @mchash: Multicast hash-table data.
+ * @rxcr1: KS_RXCR1 register setting
+ * @rxcr2: KS_RXCR2 register setting
+ *
+ * Representation of the settings needs to control the receive filtering
+ * such as the multicast hash-filter and the receive register settings. This
+ * is used to make the job of working out if the receive settings change and
+ * then issuing the new settings to the worker that will send the necessary
+ * commands.
+ */
+struct ks8851_rxctrl {
+	u16	mchash[4];
+	u16	rxcr1;
+	u16	rxcr2;
+};
+
+/**
+ * union ks8851_tx_hdr - tx header data
+ * @txb: The header as bytes
+ * @txw: The header as 16bit, little-endian words
+ *
+ * A dual representation of the tx header data to allow
+ * access to individual bytes, and to allow 16bit accesses
+ * with 16bit alignment.
+ */
+union ks8851_tx_hdr {
+	u8	txb[6];
+	__le16	txw[3];
+};
+
+/**
+ * struct ks8851_net - KS8851 driver private data
+ * @netdev: The network device we're bound to
+ * @spidev: The spi device we're bound to.
+ * @lock: Lock to ensure that the device is not accessed when busy.
+ * @statelock: Lock on this structure for tx list.
+ * @mii: The MII state information for the mii calls.
+ * @rxctrl: RX settings for @rxctrl_work.
+ * @tx_work: Work queue for tx packets
+ * @irq_work: Work queue for servicing interrupts
+ * @rxctrl_work: Work queue for updating RX mode and multicast lists
+ * @txq: Queue of packets for transmission.
+ * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1.
+ * @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2.
+ * @txh: Space for generating packet TX header in DMA-able data
+ * @rxd: Space for receiving SPI data, in DMA-able space.
+ * @txd: Space for transmitting SPI data, in DMA-able space.
+ * @msg_enable: The message flags controlling driver output (see ethtool).
+ * @fid: Incrementing frame id tag.
+ * @rc_ier: Cached copy of KS_IER.
+ * @rc_rxqcr: Cached copy of KS_RXQCR.
+ *
+ * The @lock ensures that the chip is protected when certain operations are
+ * in progress. When the read or write packet transfer is in progress, most
+ * of the chip registers are not ccessible until the transfer is finished and
+ * the DMA has been de-asserted.
+ *
+ * The @statelock is used to protect information in the structure which may
+ * need to be accessed via several sources, such as the network driver layer
+ * or one of the work queues.
+ *
+ * We align the buffers we may use for rx/tx to ensure that if the SPI driver
+ * wants to DMA map them, it will not have any problems with data the driver
+ * modifies.
+ */
+struct ks8851_net {
+	struct net_device	*netdev;
+	struct spi_device	*spidev;
+	struct mutex		lock;
+	spinlock_t		statelock;
+
+	union ks8851_tx_hdr	txh ____cacheline_aligned;
+	u8			rxd[8];
+	u8			txd[8];
+
+	u32			msg_enable ____cacheline_aligned;
+	u16			tx_space;
+	u8			fid;
+
+	u16			rc_ier;
+	u16			rc_rxqcr;
+
+	struct mii_if_info	mii;
+	struct ks8851_rxctrl	rxctrl;
+
+	struct work_struct	tx_work;
+	struct work_struct	irq_work;
+	struct work_struct	rxctrl_work;
+
+	struct sk_buff_head	txq;
+
+	struct spi_message	spi_msg1;
+	struct spi_message	spi_msg2;
+	struct spi_transfer	spi_xfer1;
+	struct spi_transfer	spi_xfer2[2];
+};
+
+static int msg_enable;
+
+#define ks_info(_ks, _msg...) dev_info(&(_ks)->spidev->dev, _msg)
+#define ks_warn(_ks, _msg...) dev_warn(&(_ks)->spidev->dev, _msg)
+#define ks_dbg(_ks, _msg...) dev_dbg(&(_ks)->spidev->dev, _msg)
+#define ks_err(_ks, _msg...) dev_err(&(_ks)->spidev->dev, _msg)
+
+/* shift for byte-enable data */
+#define BYTE_EN(_x)	((_x) << 2)
+
+/* turn register number and byte-enable mask into data for start of packet */
+#define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg)  << (8+2) | (_reg) >> 6)
+
+/* SPI register read/write calls.
+ *
+ * All these calls issue SPI transactions to access the chip's registers. They
+ * all require that the necessary lock is held to prevent accesses when the
+ * chip is busy transfering packet data (RX/TX FIFO accesses).
+ */
+
+/**
+ * ks8851_wrreg16 - write 16bit register value to chip
+ * @ks: The chip state
+ * @reg: The register address
+ * @val: The value to write
+ *
+ * Issue a write to put the value @val into the register specified in @reg.
+ */
+static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val)
+{
+	struct spi_transfer *xfer = &ks->spi_xfer1;
+	struct spi_message *msg = &ks->spi_msg1;
+	__le16 txb[2];
+	int ret;
+
+	txb[0] = cpu_to_le16(MK_OP(reg & 2 ? 0xC : 0x03, reg) | KS_SPIOP_WR);
+	txb[1] = cpu_to_le16(val);
+
+	xfer->tx_buf = txb;
+	xfer->rx_buf = NULL;
+	xfer->len = 4;
+
+	ret = spi_sync(ks->spidev, msg);
+	if (ret < 0)
+		ks_err(ks, "spi_sync() failed\n");
+}
+
+/**
+ * ks8851_rx_1msg - select whether to use one or two messages for spi read
+ * @ks: The device structure
+ *
+ * Return whether to generate a single message with a tx and rx buffer
+ * supplied to spi_sync(), or alternatively send the tx and rx buffers
+ * as separate messages.
+ *
+ * Depending on the hardware in use, a single message may be more efficient
+ * on interrupts or work done by the driver.
+ *
+ * This currently always returns true until we add some per-device data passed
+ * from the platform code to specify which mode is better.
+ */
+static inline bool ks8851_rx_1msg(struct ks8851_net *ks)
+{
+	return true;
+}
+
+/**
+ * ks8851_rdreg - issue read register command and return the data
+ * @ks: The device state
+ * @op: The register address and byte enables in message format.
+ * @rxb: The RX buffer to return the result into
+ * @rxl: The length of data expected.
+ *
+ * This is the low level read call that issues the necessary spi message(s)
+ * to read data from the register specified in @op.
+ */
+static void ks8851_rdreg(struct ks8851_net *ks, unsigned op,
+			 u8 *rxb, unsigned rxl)
+{
+	struct spi_transfer *xfer;
+	struct spi_message *msg;
+	__le16 *txb = (__le16 *)ks->txd;
+	u8 *trx = ks->rxd;
+	int ret;
+
+	txb[0] = cpu_to_le16(op | KS_SPIOP_RD);
+
+	if (ks8851_rx_1msg(ks)) {
+		msg = &ks->spi_msg1;
+		xfer = &ks->spi_xfer1;
+
+		xfer->tx_buf = txb;
+		xfer->rx_buf = trx;
+		xfer->len = rxl + 2;
+	} else {
+		msg = &ks->spi_msg2;
+		xfer = ks->spi_xfer2;
+
+		xfer->tx_buf = txb;
+		xfer->rx_buf = NULL;
+		xfer->len = 2;
+
+		xfer++;
+		xfer->tx_buf = NULL;
+		xfer->rx_buf = trx;
+		xfer->len = rxl;
+	}
+
+	ret = spi_sync(ks->spidev, msg);
+	if (ret < 0)
+		ks_err(ks, "read: spi_sync() failed\n");
+	else if (ks8851_rx_1msg(ks))
+		memcpy(rxb, trx + 2, rxl);
+	else
+		memcpy(rxb, trx, rxl);
+}
+
+/**
+ * ks8851_rdreg8 - read 8 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 8bit register from the chip, returning the result
+*/
+static unsigned ks8851_rdreg8(struct ks8851_net *ks, unsigned reg)
+{
+	u8 rxb[1];
+
+	ks8851_rdreg(ks, MK_OP(1 << (reg & 3), reg), rxb, 1);
+	return rxb[0];
+}
+
+/**
+ * ks8851_rdreg16 - read 16 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 16bit register from the chip, returning the result
+*/
+static unsigned ks8851_rdreg16(struct ks8851_net *ks, unsigned reg)
+{
+	__le16 rx = 0;
+
+	ks8851_rdreg(ks, MK_OP(reg & 2 ? 0xC : 0x3, reg), (u8 *)&rx, 2);
+	return le16_to_cpu(rx);
+}
+
+/**
+ * ks8851_rdreg32 - read 32 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 32bit register from the chip.
+ *
+ * Note, this read requires the address be aligned to 4 bytes.
+*/
+static unsigned ks8851_rdreg32(struct ks8851_net *ks, unsigned reg)
+{
+	__le32 rx = 0;
+
+	WARN_ON(reg & 3);
+
+	ks8851_rdreg(ks, MK_OP(0xf, reg), (u8 *)&rx, 4);
+	return le32_to_cpu(rx);
+}
+
+/**
+ * ks8851_soft_reset - issue one of the soft reset to the device
+ * @ks: The device state.
+ * @op: The bit(s) to set in the GRR
+ *
+ * Issue the relevant soft-reset command to the device's GRR register
+ * specified by @op.
+ *
+ * Note, the delays are in there as a caution to ensure that the reset
+ * has time to take effect and then complete. Since the datasheet does
+ * not currently specify the exact sequence, we have chosen something
+ * that seems to work with our device.
+ */
+static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op)
+{
+	ks8851_wrreg16(ks, KS_GRR, op);
+	mdelay(1);	/* wait a short time to effect reset */
+	ks8851_wrreg16(ks, KS_GRR, 0);
+	mdelay(1);	/* wait for condition to clear */
+}
+
+/**
+ * ks8851_write_mac_addr - write mac address to device registers
+ * @dev: The network device
+ *
+ * Update the KS8851 MAC address registers from the address in @dev.
+ *
+ * This call assumes that the chip is not running, so there is no need to
+ * shutdown the RXQ process whilst setting this.
+*/
+static int ks8851_write_mac_addr(struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	u16 *mcp = (u16 *)dev->dev_addr;
+
+	mutex_lock(&ks->lock);
+
+	ks8851_wrreg16(ks, KS_MARL, mcp[0]);
+	ks8851_wrreg16(ks, KS_MARM, mcp[1]);
+	ks8851_wrreg16(ks, KS_MARH, mcp[2]);
+
+	mutex_unlock(&ks->lock);
+
+	return 0;
+}
+
+/**
+ * ks8851_init_mac - initialise the mac address
+ * @ks: The device structure
+ *
+ * Get or create the initial mac address for the device and then set that
+ * into the station address register. Currently we assume that the device
+ * does not have a valid mac address in it, and so we use random_ether_addr()
+ * to create a new one.
+ *
+ * In future, the driver should check to see if the device has an EEPROM
+ * attached and whether that has a valid ethernet address in it.
+ */
+static void ks8851_init_mac(struct ks8851_net *ks)
+{
+	struct net_device *dev = ks->netdev;
+
+	random_ether_addr(dev->dev_addr);
+	ks8851_write_mac_addr(dev);
+}
+
+/**
+ * ks8851_irq - device interrupt handler
+ * @irq: Interrupt number passed from the IRQ hnalder.
+ * @pw: The private word passed to register_irq(), our struct ks8851_net.
+ *
+ * Disable the interrupt from happening again until we've processed the
+ * current status by scheduling ks8851_irq_work().
+ */
+static irqreturn_t ks8851_irq(int irq, void *pw)
+{
+	struct ks8851_net *ks = pw;
+
+	disable_irq_nosync(irq);
+	schedule_work(&ks->irq_work);
+	return IRQ_HANDLED;
+}
+
+/**
+ * ks8851_rdfifo - read data from the receive fifo
+ * @ks: The device state.
+ * @buff: The buffer address
+ * @len: The length of the data to read
+ *
+ * Issue an RXQ FIFO read command and read the @len ammount of data from
+ * the FIFO into the buffer specified by @buff.
+ */
+static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len)
+{
+	struct spi_transfer *xfer = ks->spi_xfer2;
+	struct spi_message *msg = &ks->spi_msg2;
+	u8 txb[1];
+	int ret;
+
+	if (netif_msg_rx_status(ks))
+		ks_dbg(ks, "%s: %d@%p\n", __func__, len, buff);
+
+	/* set the operation we're issuing */
+	txb[0] = KS_SPIOP_RXFIFO;
+
+	xfer->tx_buf = txb;
+	xfer->rx_buf = NULL;
+	xfer->len = 1;
+
+	xfer++;
+	xfer->rx_buf = buff;
+	xfer->tx_buf = NULL;
+	xfer->len = len;
+
+	ret = spi_sync(ks->spidev, msg);
+	if (ret < 0)
+		ks_err(ks, "%s: spi_sync() failed\n", __func__);
+}
+
+/**
+ * ks8851_dbg_dumpkkt - dump initial packet contents to debug
+ * @ks: The device state
+ * @rxpkt: The data for the received packet
+ *
+ * Dump the initial data from the packet to dev_dbg().
+*/
+static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
+{
+	ks_dbg(ks, "pkt %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",
+	       rxpkt[4], rxpkt[5], rxpkt[6], rxpkt[7],
+	       rxpkt[8], rxpkt[9], rxpkt[10], rxpkt[11],
+	       rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]);
+}
+
+/**
+ * ks8851_rx_pkts - receive packets from the host
+ * @ks: The device information.
+ *
+ * This is called from the IRQ work queue when the system detects that there
+ * are packets in the receive queue. Find out how many packets there are and
+ * read them from the FIFO.
+ */
+static void ks8851_rx_pkts(struct ks8851_net *ks)
+{
+	struct sk_buff *skb;
+	unsigned rxfc;
+	unsigned rxlen;
+	unsigned rxstat;
+	u32 rxh;
+	u8 *rxpkt;
+
+	rxfc = ks8851_rdreg8(ks, KS_RXFC);
+
+	if (netif_msg_rx_status(ks))
+		ks_dbg(ks, "%s: %d packets\n", __func__, rxfc);
+
+	/* Currently we're issuing a read per packet, but we could possibly
+	 * improve the code by issuing a single read, getting the receive
+	 * header, allocating the packet and then reading the packet data
+	 * out in one go.
+	 *
+	 * This form of operation would require us to hold the SPI bus'
+	 * chipselect low during the entie transaction to avoid any
+	 * reset to the data stream comming from the chip.
+	 */
+
+	for (; rxfc != 0; rxfc--) {
+		rxh = ks8851_rdreg32(ks, KS_RXFHSR);
+		rxstat = rxh & 0xffff;
+		rxlen = rxh >> 16;
+
+		if (netif_msg_rx_status(ks))
+			ks_dbg(ks, "rx: stat 0x%04x, len 0x%04x\n",
+				rxstat, rxlen);
+
+		/* the length of the packet includes the 32bit CRC */
+
+		/* set dma read address */
+		ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00);
+
+		/* start the packet dma process, and set auto-dequeue rx */
+		ks8851_wrreg16(ks, KS_RXQCR,
+			       ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE);
+
+		if (rxlen > 0) {
+			skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8);
+			if (!skb) {
+				/* todo - dump frame and move on */
+			}
+
+			/* two bytes to ensure ip is aligned, and four bytes
+			 * for the status header and 4 bytes of garbage */
+			skb_reserve(skb, 2 + 4 + 4);
+
+			rxpkt = skb_put(skb, rxlen - 4) - 8;
+
+			/* align the packet length to 4 bytes, and add 4 bytes
+			 * as we're getting the rx status header as well */
+			ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8);
+
+			if (netif_msg_pktdata(ks))
+				ks8851_dbg_dumpkkt(ks, rxpkt);
+
+			skb->protocol = eth_type_trans(skb, ks->netdev);
+			netif_rx(skb);
+
+			ks->netdev->stats.rx_packets++;
+			ks->netdev->stats.rx_bytes += rxlen - 4;
+		}
+
+		ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+	}
+}
+
+/**
+ * ks8851_irq_work - work queue handler for dealing with interrupt requests
+ * @work: The work structure that was scheduled by schedule_work()
+ *
+ * This is the handler invoked when the ks8851_irq() is called to find out
+ * what happened, as we cannot allow ourselves to sleep whilst waiting for
+ * anything other process has the chip's lock.
+ *
+ * Read the interrupt status, work out what needs to be done and then clear
+ * any of the interrupts that are not needed.
+ */
+static void ks8851_irq_work(struct work_struct *work)
+{
+	struct ks8851_net *ks = container_of(work, struct ks8851_net, irq_work);
+	unsigned status;
+	unsigned handled = 0;
+
+	mutex_lock(&ks->lock);
+
+	status = ks8851_rdreg16(ks, KS_ISR);
+
+	if (netif_msg_intr(ks))
+		dev_dbg(&ks->spidev->dev, "%s: status 0x%04x\n",
+			__func__, status);
+
+	if (status & IRQ_LCI) {
+		/* should do something about checking link status */
+		handled |= IRQ_LCI;
+	}
+
+	if (status & IRQ_LDI) {
+		u16 pmecr = ks8851_rdreg16(ks, KS_PMECR);
+		pmecr &= ~PMECR_WKEVT_MASK;
+		ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
+
+		handled |= IRQ_LDI;
+	}
+
+	if (status & IRQ_RXPSI)
+		handled |= IRQ_RXPSI;
+
+	if (status & IRQ_TXI) {
+		handled |= IRQ_TXI;
+
+		/* no lock here, tx queue should have been stopped */
+
+		/* update our idea of how much tx space is available to the
+		 * system */
+		ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
+
+		if (netif_msg_intr(ks))
+			ks_dbg(ks, "%s: txspace %d\n", __func__, ks->tx_space);
+	}
+
+	if (status & IRQ_RXI)
+		handled |= IRQ_RXI;
+
+	if (status & IRQ_SPIBEI) {
+		dev_err(&ks->spidev->dev, "%s: spi bus error\n", __func__);
+		handled |= IRQ_SPIBEI;
+	}
+
+	ks8851_wrreg16(ks, KS_ISR, handled);
+
+	if (status & IRQ_RXI) {
+		/* the datasheet says to disable the rx interrupt during
+		 * packet read-out, however we're masking the interrupt
+		 * from the device so do not bother masking just the RX
+		 * from the device. */
+
+		ks8851_rx_pkts(ks);
+	}
+
+	/* if something stopped the rx process, probably due to wanting
+	 * to change the rx settings, then do something about restarting
+	 * it. */
+	if (status & IRQ_RXPSI) {
+		struct ks8851_rxctrl *rxc = &ks->rxctrl;
+
+		/* update the multicast hash table */
+		ks8851_wrreg16(ks, KS_MAHTR0, rxc->mchash[0]);
+		ks8851_wrreg16(ks, KS_MAHTR1, rxc->mchash[1]);
+		ks8851_wrreg16(ks, KS_MAHTR2, rxc->mchash[2]);
+		ks8851_wrreg16(ks, KS_MAHTR3, rxc->mchash[3]);
+
+		ks8851_wrreg16(ks, KS_RXCR2, rxc->rxcr2);
+		ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1);
+	}
+
+	mutex_unlock(&ks->lock);
+
+	if (status & IRQ_TXI)
+		netif_wake_queue(ks->netdev);
+
+	enable_irq(ks->netdev->irq);
+}
+
+/**
+ * calc_txlen - calculate size of message to send packet
+ * @len: Lenght of data
+ *
+ * Returns the size of the TXFIFO message needed to send
+ * this packet.
+ */
+static inline unsigned calc_txlen(unsigned len)
+{
+	return ALIGN(len + 4, 4);
+}
+
+/**
+ * ks8851_wrpkt - write packet to TX FIFO
+ * @ks: The device state.
+ * @txp: The sk_buff to transmit.
+ * @irq: IRQ on completion of the packet.
+ *
+ * Send the @txp to the chip. This means creating the relevant packet header
+ * specifying the length of the packet and the other information the chip
+ * needs, such as IRQ on completion. Send the header and the packet data to
+ * the device.
+ */
+static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq)
+{
+	struct spi_transfer *xfer = ks->spi_xfer2;
+	struct spi_message *msg = &ks->spi_msg2;
+	unsigned fid = 0;
+	int ret;
+
+	if (netif_msg_tx_queued(ks))
+		dev_dbg(&ks->spidev->dev, "%s: skb %p, %d@%p, irq %d\n",
+			__func__, txp, txp->len, txp->data, irq);
+
+	fid = ks->fid++;
+	fid &= TXFR_TXFID_MASK;
+
+	if (irq)
+		fid |= TXFR_TXIC;	/* irq on completion */
+
+	/* start header at txb[1] to align txw entries */
+	ks->txh.txb[1] = KS_SPIOP_TXFIFO;
+	ks->txh.txw[1] = cpu_to_le16(fid);
+	ks->txh.txw[2] = cpu_to_le16(txp->len);
+
+	xfer->tx_buf = &ks->txh.txb[1];
+	xfer->rx_buf = NULL;
+	xfer->len = 5;
+
+	xfer++;
+	xfer->tx_buf = txp->data;
+	xfer->rx_buf = NULL;
+	xfer->len = ALIGN(txp->len, 4);
+
+	ret = spi_sync(ks->spidev, msg);
+	if (ret < 0)
+		ks_err(ks, "%s: spi_sync() failed\n", __func__);
+}
+
+/**
+ * ks8851_done_tx - update and then free skbuff after transmitting
+ * @ks: The device state
+ * @txb: The buffer transmitted
+ */
+static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb)
+{
+	struct net_device *dev = ks->netdev;
+
+	dev->stats.tx_bytes += txb->len;
+	dev->stats.tx_packets++;
+
+	dev_kfree_skb(txb);
+}
+
+/**
+ * ks8851_tx_work - process tx packet(s)
+ * @work: The work strucutre what was scheduled.
+ *
+ * This is called when a number of packets have been scheduled for
+ * transmission and need to be sent to the device.
+ */
+static void ks8851_tx_work(struct work_struct *work)
+{
+	struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work);
+	struct sk_buff *txb;
+	bool last = false;
+
+	mutex_lock(&ks->lock);
+
+	while (!last) {
+		txb = skb_dequeue(&ks->txq);
+		last = skb_queue_empty(&ks->txq);
+
+		ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
+		ks8851_wrpkt(ks, txb, last);
+		ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+		ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
+
+		ks8851_done_tx(ks, txb);
+	}
+
+	mutex_unlock(&ks->lock);
+}
+
+/**
+ * ks8851_set_powermode - set power mode of the device
+ * @ks: The device state
+ * @pwrmode: The power mode value to write to KS_PMECR.
+ *
+ * Change the power mode of the chip.
+ */
+static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode)
+{
+	unsigned pmecr;
+
+	if (netif_msg_hw(ks))
+		ks_dbg(ks, "setting power mode %d\n", pwrmode);
+
+	pmecr = ks8851_rdreg16(ks, KS_PMECR);
+	pmecr &= ~PMECR_PM_MASK;
+	pmecr |= pwrmode;
+
+	ks8851_wrreg16(ks, KS_PMECR, pmecr);
+}
+
+/**
+ * ks8851_net_open - open network device
+ * @dev: The network device being opened.
+ *
+ * Called when the network device is marked active, such as a user executing
+ * 'ifconfig up' on the device.
+ */
+static int ks8851_net_open(struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+
+	/* lock the card, even if we may not actually be doing anything
+	 * else at the moment */
+	mutex_lock(&ks->lock);
+
+	if (netif_msg_ifup(ks))
+		ks_dbg(ks, "opening %s\n", dev->name);
+
+	/* bring chip out of any power saving mode it was in */
+	ks8851_set_powermode(ks, PMECR_PM_NORMAL);
+
+	/* issue a soft reset to the RX/TX QMU to put it into a known
+	 * state. */
+	ks8851_soft_reset(ks, GRR_QMU);
+
+	/* setup transmission parameters */
+
+	ks8851_wrreg16(ks, KS_TXCR, (TXCR_TXE | /* enable transmit process */
+				     TXCR_TXPE | /* pad to min length */
+				     TXCR_TXCRC | /* add CRC */
+				     TXCR_TXFCE)); /* enable flow control */
+
+	/* auto-increment tx data, reset tx pointer */
+	ks8851_wrreg16(ks, KS_TXFDPR, TXFDPR_TXFPAI);
+
+	/* setup receiver control */
+
+	ks8851_wrreg16(ks, KS_RXCR1, (RXCR1_RXPAFMA | /*  from mac filter */
+				      RXCR1_RXFCE | /* enable flow control */
+				      RXCR1_RXBE | /* broadcast enable */
+				      RXCR1_RXUE | /* unicast enable */
+				      RXCR1_RXE)); /* enable rx block */
+
+	/* transfer entire frames out in one go */
+	ks8851_wrreg16(ks, KS_RXCR2, RXCR2_SRDBL_FRAME);
+
+	/* set receive counter timeouts */
+	ks8851_wrreg16(ks, KS_RXDTTR, 1000); /* 1ms after first frame to IRQ */
+	ks8851_wrreg16(ks, KS_RXDBCTR, 4096); /* >4Kbytes in buffer to IRQ */
+	ks8851_wrreg16(ks, KS_RXFCTR, 10);  /* 10 frames to IRQ */
+
+	ks->rc_rxqcr = (RXQCR_RXFCTE |  /* IRQ on frame count exceeded */
+			RXQCR_RXDBCTE | /* IRQ on byte count exceeded */
+			RXQCR_RXDTTE);  /* IRQ on time exceeded */
+
+	ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+
+	/* clear then enable interrupts */
+
+#define STD_IRQ (IRQ_LCI |	/* Link Change */	\
+		 IRQ_TXI |	/* TX done */		\
+		 IRQ_RXI |	/* RX done */		\
+		 IRQ_SPIBEI |	/* SPI bus error */	\
+		 IRQ_TXPSI |	/* TX process stop */	\
+		 IRQ_RXPSI)	/* RX process stop */
+
+	ks->rc_ier = STD_IRQ;
+	ks8851_wrreg16(ks, KS_ISR, STD_IRQ);
+	ks8851_wrreg16(ks, KS_IER, STD_IRQ);
+
+	netif_start_queue(ks->netdev);
+
+	if (netif_msg_ifup(ks))
+		ks_dbg(ks, "network device %s up\n", dev->name);
+
+	mutex_unlock(&ks->lock);
+	return 0;
+}
+
+/**
+ * ks8851_net_stop - close network device
+ * @dev: The device being closed.
+ *
+ * Called to close down a network device which has been active. Cancell any
+ * work, shutdown the RX and TX process and then place the chip into a low
+ * power state whilst it is not being used.
+ */
+static int ks8851_net_stop(struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+
+	if (netif_msg_ifdown(ks))
+		ks_info(ks, "%s: shutting down\n", dev->name);
+
+	netif_stop_queue(dev);
+
+	mutex_lock(&ks->lock);
+
+	/* stop any outstanding work */
+	flush_work(&ks->irq_work);
+	flush_work(&ks->tx_work);
+	flush_work(&ks->rxctrl_work);
+
+	/* turn off the IRQs and ack any outstanding */
+	ks8851_wrreg16(ks, KS_IER, 0x0000);
+	ks8851_wrreg16(ks, KS_ISR, 0xffff);
+
+	/* shutdown RX process */
+	ks8851_wrreg16(ks, KS_RXCR1, 0x0000);
+
+	/* shutdown TX process */
+	ks8851_wrreg16(ks, KS_TXCR, 0x0000);
+
+	/* set powermode to soft power down to save power */
+	ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
+
+	/* ensure any queued tx buffers are dumped */
+	while (!skb_queue_empty(&ks->txq)) {
+		struct sk_buff *txb = skb_dequeue(&ks->txq);
+
+		if (netif_msg_ifdown(ks))
+			ks_dbg(ks, "%s: freeing txb %p\n", __func__, txb);
+
+		dev_kfree_skb(txb);
+	}
+
+	mutex_unlock(&ks->lock);
+	return 0;
+}
+
+/**
+ * ks8851_start_xmit - transmit packet
+ * @skb: The buffer to transmit
+ * @dev: The device used to transmit the packet.
+ *
+ * Called by the network layer to transmit the @skb. Queue the packet for
+ * the device and schedule the necessary work to transmit the packet when
+ * it is free.
+ *
+ * We do this to firstly avoid sleeping with the network device locked,
+ * and secondly so we can round up more than one packet to transmit which
+ * means we can try and avoid generating too many transmit done interrupts.
+ */
+static int ks8851_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	unsigned needed = calc_txlen(skb->len);
+	int ret = NETDEV_TX_OK;
+
+	if (netif_msg_tx_queued(ks))
+		ks_dbg(ks, "%s: skb %p, %d@%p\n", __func__,
+		       skb, skb->len, skb->data);
+
+	spin_lock(&ks->statelock);
+
+	if (needed > ks->tx_space) {
+		netif_stop_queue(dev);
+		ret = NETDEV_TX_BUSY;
+	} else {
+		ks->tx_space -= needed;
+		skb_queue_tail(&ks->txq, skb);
+	}
+
+	spin_unlock(&ks->statelock);
+	schedule_work(&ks->tx_work);
+
+	return ret;
+}
+
+/**
+ * ks8851_rxctrl_work - work handler to change rx mode
+ * @work: The work structure this belongs to.
+ *
+ * Lock the device and issue the necessary changes to the receive mode from
+ * the network device layer. This is done so that we can do this without
+ * having to sleep whilst holding the network device lock.
+ *
+ * Since the recommendation from Micrel is that the RXQ is shutdown whilst the
+ * receive parameters are programmed, we issue a write to disable the RXQ and
+ * then wait for the interrupt handler to be triggered once the RXQ shutdown is
+ * complete. The interrupt handler then writes the new values into the chip.
+ */
+static void ks8851_rxctrl_work(struct work_struct *work)
+{
+	struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work);
+
+	mutex_lock(&ks->lock);
+
+	/* need to shutdown RXQ before modifying filter parameters */
+	ks8851_wrreg16(ks, KS_RXCR1, 0x00);
+
+	mutex_unlock(&ks->lock);
+}
+
+static void ks8851_set_rx_mode(struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	struct ks8851_rxctrl rxctrl;
+
+	memset(&rxctrl, 0, sizeof(rxctrl));
+
+	if (dev->flags & IFF_PROMISC) {
+		/* interface to receive everything */
+
+		rxctrl.rxcr1 = RXCR1_RXAE | RXCR1_RXINVF;
+	} else if (dev->flags & IFF_ALLMULTI) {
+		/* accept all multicast packets */
+
+		rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE |
+				RXCR1_RXPAFMA | RXCR1_RXMAFMA);
+	} else if (dev->flags & IFF_MULTICAST && dev->mc_count > 0) {
+		struct dev_mc_list *mcptr = dev->mc_list;
+		u32 crc;
+		int i;
+
+		/* accept some multicast */
+
+		for (i = dev->mc_count; i > 0; i--) {
+			crc = ether_crc(ETH_ALEN, mcptr->dmi_addr);
+			crc >>= (32 - 6);  /* get top six bits */
+
+			rxctrl.mchash[crc >> 4] |= (1 << (crc & 0xf));
+			mcptr = mcptr->next;
+		}
+
+		rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA;
+	} else {
+		/* just accept broadcast / unicast */
+		rxctrl.rxcr1 = RXCR1_RXPAFMA;
+	}
+
+	rxctrl.rxcr1 |= (RXCR1_RXUE | /* unicast enable */
+			 RXCR1_RXBE | /* broadcast enable */
+			 RXCR1_RXE | /* RX process enable */
+			 RXCR1_RXFCE); /* enable flow control */
+
+	rxctrl.rxcr2 |= RXCR2_SRDBL_FRAME;
+
+	/* schedule work to do the actual set of the data if needed */
+
+	spin_lock(&ks->statelock);
+
+	if (memcmp(&rxctrl, &ks->rxctrl, sizeof(rxctrl)) != 0) {
+		memcpy(&ks->rxctrl, &rxctrl, sizeof(ks->rxctrl));
+		schedule_work(&ks->rxctrl_work);
+	}
+
+	spin_unlock(&ks->statelock);
+}
+
+static int ks8851_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct sockaddr *sa = addr;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(sa->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
+	return ks8851_write_mac_addr(dev);
+}
+
+static int ks8851_net_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	return generic_mii_ioctl(&ks->mii, if_mii(req), cmd, NULL);
+}
+
+static const struct net_device_ops ks8851_netdev_ops = {
+	.ndo_open		= ks8851_net_open,
+	.ndo_stop		= ks8851_net_stop,
+	.ndo_do_ioctl		= ks8851_net_ioctl,
+	.ndo_start_xmit		= ks8851_start_xmit,
+	.ndo_set_mac_address	= ks8851_set_mac_address,
+	.ndo_set_rx_mode	= ks8851_set_rx_mode,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+/* ethtool support */
+
+static void ks8851_get_drvinfo(struct net_device *dev,
+			       struct ethtool_drvinfo *di)
+{
+	strlcpy(di->driver, "KS8851", sizeof(di->driver));
+	strlcpy(di->version, "1.00", sizeof(di->version));
+	strlcpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info));
+}
+
+static u32 ks8851_get_msglevel(struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	return ks->msg_enable;
+}
+
+static void ks8851_set_msglevel(struct net_device *dev, u32 to)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	ks->msg_enable = to;
+}
+
+static int ks8851_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	return mii_ethtool_gset(&ks->mii, cmd);
+}
+
+static int ks8851_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	return mii_ethtool_sset(&ks->mii, cmd);
+}
+
+static u32 ks8851_get_link(struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	return mii_link_ok(&ks->mii);
+}
+
+static int ks8851_nway_reset(struct net_device *dev)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	return mii_nway_restart(&ks->mii);
+}
+
+static const struct ethtool_ops ks8851_ethtool_ops = {
+	.get_drvinfo	= ks8851_get_drvinfo,
+	.get_msglevel	= ks8851_get_msglevel,
+	.set_msglevel	= ks8851_set_msglevel,
+	.get_settings	= ks8851_get_settings,
+	.set_settings	= ks8851_set_settings,
+	.get_link	= ks8851_get_link,
+	.nway_reset	= ks8851_nway_reset,
+};
+
+/* MII interface controls */
+
+/**
+ * ks8851_phy_reg - convert MII register into a KS8851 register
+ * @reg: MII register number.
+ *
+ * Return the KS8851 register number for the corresponding MII PHY register
+ * if possible. Return zero if the MII register has no direct mapping to the
+ * KS8851 register set.
+ */
+static int ks8851_phy_reg(int reg)
+{
+	switch (reg) {
+	case MII_BMCR:
+		return KS_P1MBCR;
+	case MII_BMSR:
+		return KS_P1MBSR;
+	case MII_PHYSID1:
+		return KS_PHY1ILR;
+	case MII_PHYSID2:
+		return KS_PHY1IHR;
+	case MII_ADVERTISE:
+		return KS_P1ANAR;
+	case MII_LPA:
+		return KS_P1ANLPR;
+	}
+
+	return 0x0;
+}
+
+/**
+ * ks8851_phy_read - MII interface PHY register read.
+ * @dev: The network device the PHY is on.
+ * @phy_addr: Address of PHY (ignored as we only have one)
+ * @reg: The register to read.
+ *
+ * This call reads data from the PHY register specified in @reg. Since the
+ * device does not support all the MII registers, the non-existant values
+ * are always returned as zero.
+ *
+ * We return zero for unsupported registers as the MII code does not check
+ * the value returned for any error status, and simply returns it to the
+ * caller. The mii-tool that the driver was tested with takes any -ve error
+ * as real PHY capabilities, thus displaying incorrect data to the user.
+ */
+static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	int ksreg;
+	int result;
+
+	ksreg = ks8851_phy_reg(reg);
+	if (!ksreg)
+		return 0x0;	/* no error return allowed, so use zero */
+
+	mutex_lock(&ks->lock);
+	result = ks8851_rdreg16(ks, ksreg);
+	mutex_unlock(&ks->lock);
+
+	return result;
+}
+
+static void ks8851_phy_write(struct net_device *dev,
+			     int phy, int reg, int value)
+{
+	struct ks8851_net *ks = netdev_priv(dev);
+	int ksreg;
+
+	ksreg = ks8851_phy_reg(reg);
+	if (ksreg) {
+		mutex_lock(&ks->lock);
+		ks8851_wrreg16(ks, ksreg, value);
+		mutex_unlock(&ks->lock);
+	}
+}
+
+/**
+ * ks8851_read_selftest - read the selftest memory info.
+ * @ks: The device state
+ *
+ * Read and check the TX/RX memory selftest information.
+ */
+static int ks8851_read_selftest(struct ks8851_net *ks)
+{
+	unsigned both_done = MBIR_TXMBF | MBIR_RXMBF;
+	int ret = 0;
+	unsigned rd;
+
+	rd = ks8851_rdreg16(ks, KS_MBIR);
+
+	if ((rd & both_done) != both_done) {
+		ks_warn(ks, "Memory selftest not finished\n");
+		return 0;
+	}
+
+	if (rd & MBIR_TXMBFA) {
+		ks_err(ks, "TX memory selftest fail\n");
+		ret |= 1;
+	}
+
+	if (rd & MBIR_RXMBFA) {
+		ks_err(ks, "RX memory selftest fail\n");
+		ret |= 2;
+	}
+
+	return 0;
+}
+
+/* driver bus management functions */
+
+static int __devinit ks8851_probe(struct spi_device *spi)
+{
+	struct net_device *ndev;
+	struct ks8851_net *ks;
+	int ret;
+
+	ndev = alloc_etherdev(sizeof(struct ks8851_net));
+	if (!ndev) {
+		dev_err(&spi->dev, "failed to alloc ethernet device\n");
+		return -ENOMEM;
+	}
+
+	spi->bits_per_word = 8;
+
+	ks = netdev_priv(ndev);
+
+	ks->netdev = ndev;
+	ks->spidev = spi;
+	ks->tx_space = 6144;
+
+	mutex_init(&ks->lock);
+	spin_lock_init(&ks->statelock);
+
+	INIT_WORK(&ks->tx_work, ks8851_tx_work);
+	INIT_WORK(&ks->irq_work, ks8851_irq_work);
+	INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work);
+
+	/* initialise pre-made spi transfer messages */
+
+	spi_message_init(&ks->spi_msg1);
+	spi_message_add_tail(&ks->spi_xfer1, &ks->spi_msg1);
+
+	spi_message_init(&ks->spi_msg2);
+	spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2);
+	spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2);
+
+	/* setup mii state */
+	ks->mii.dev		= ndev;
+	ks->mii.phy_id		= 1,
+	ks->mii.phy_id_mask	= 1;
+	ks->mii.reg_num_mask	= 0xf;
+	ks->mii.mdio_read	= ks8851_phy_read;
+	ks->mii.mdio_write	= ks8851_phy_write;
+
+	dev_info(&spi->dev, "message enable is %d\n", msg_enable);
+
+	/* set the default message enable */
+	ks->msg_enable = netif_msg_init(msg_enable, (NETIF_MSG_DRV |
+						     NETIF_MSG_PROBE |
+						     NETIF_MSG_LINK));
+
+	skb_queue_head_init(&ks->txq);
+
+	SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops);
+	SET_NETDEV_DEV(ndev, &spi->dev);
+
+	dev_set_drvdata(&spi->dev, ks);
+
+	ndev->if_port = IF_PORT_100BASET;
+	ndev->netdev_ops = &ks8851_netdev_ops;
+	ndev->irq = spi->irq;
+
+	/* simple check for a valid chip being connected to the bus */
+
+	if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
+		dev_err(&spi->dev, "failed to read device ID\n");
+		ret = -ENODEV;
+		goto err_id;
+	}
+
+	ks8851_read_selftest(ks);
+	ks8851_init_mac(ks);
+
+	ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW,
+			  ndev->name, ks);
+	if (ret < 0) {
+		dev_err(&spi->dev, "failed to get irq\n");
+		goto err_irq;
+	}
+
+	ret = register_netdev(ndev);
+	if (ret) {
+		dev_err(&spi->dev, "failed to register network device\n");
+		goto err_netdev;
+	}
+
+	dev_info(&spi->dev, "revision %d, MAC %pM, IRQ %d\n",
+		 CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
+		 ndev->dev_addr, ndev->irq);
+
+	return 0;
+
+
+err_netdev:
+	free_irq(ndev->irq, ndev);
+
+err_id:
+err_irq:
+	free_netdev(ndev);
+	return ret;
+}
+
+static int __devexit ks8851_remove(struct spi_device *spi)
+{
+	struct ks8851_net *priv = dev_get_drvdata(&spi->dev);
+
+	if (netif_msg_drv(priv))
+		dev_info(&spi->dev, "remove");
+
+	unregister_netdev(priv->netdev);
+	free_irq(spi->irq, priv);
+	free_netdev(priv->netdev);
+
+	return 0;
+}
+
+static struct spi_driver ks8851_driver = {
+	.driver = {
+		.name = "ks8851",
+		.owner = THIS_MODULE,
+	},
+	.probe = ks8851_probe,
+	.remove = __devexit_p(ks8851_remove),
+};
+
+static int __init ks8851_init(void)
+{
+	return spi_register_driver(&ks8851_driver);
+}
+
+static void __exit ks8851_exit(void)
+{
+	spi_unregister_driver(&ks8851_driver);
+}
+
+module_init(ks8851_init);
+module_exit(ks8851_exit);
+
+MODULE_DESCRIPTION("KS8851 Network driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
+
+module_param_named(message, msg_enable, int, 0);
+MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)");
diff -druN linux-libre-2.6.30-gnu/drivers/net/ks8851.h linux-libre-2.6.31-gnu/drivers/net/ks8851.h
--- linux-libre-2.6.30-gnu/drivers/net/ks8851.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ks8851.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,296 @@
+/* drivers/net/ks8851.h
+ *
+ * Copyright 2009 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * KS8851 register definitions
+ *
+ * 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.
+*/
+
+#define KS_CCR					0x08
+#define CCR_EEPROM				(1 << 9)
+#define CCR_SPI					(1 << 8)
+#define CCR_32PIN				(1 << 0)
+
+/* MAC address registers */
+#define KS_MARL					0x10
+#define KS_MARM					0x12
+#define KS_MARH					0x14
+
+#define KS_OBCR					0x20
+#define OBCR_ODS_16mA				(1 << 6)
+
+#define KS_EEPCR				0x22
+#define EEPCR_EESA				(1 << 4)
+#define EEPCR_EESB				(1 << 3)
+#define EEPCR_EEDO				(1 << 2)
+#define EEPCR_EESCK				(1 << 1)
+#define EEPCR_EECS				(1 << 0)
+
+#define KS_MBIR					0x24
+#define MBIR_TXMBF				(1 << 12)
+#define MBIR_TXMBFA				(1 << 11)
+#define MBIR_RXMBF				(1 << 4)
+#define MBIR_RXMBFA				(1 << 3)
+
+#define KS_GRR					0x26
+#define GRR_QMU					(1 << 1)
+#define GRR_GSR					(1 << 0)
+
+#define KS_WFCR					0x2A
+#define WFCR_MPRXE				(1 << 7)
+#define WFCR_WF3E				(1 << 3)
+#define WFCR_WF2E				(1 << 2)
+#define WFCR_WF1E				(1 << 1)
+#define WFCR_WF0E				(1 << 0)
+
+#define KS_WF0CRC0				0x30
+#define KS_WF0CRC1				0x32
+#define KS_WF0BM0				0x34
+#define KS_WF0BM1				0x36
+#define KS_WF0BM2				0x38
+#define KS_WF0BM3				0x3A
+
+#define KS_WF1CRC0				0x40
+#define KS_WF1CRC1				0x42
+#define KS_WF1BM0				0x44
+#define KS_WF1BM1				0x46
+#define KS_WF1BM2				0x48
+#define KS_WF1BM3				0x4A
+
+#define KS_WF2CRC0				0x50
+#define KS_WF2CRC1				0x52
+#define KS_WF2BM0				0x54
+#define KS_WF2BM1				0x56
+#define KS_WF2BM2				0x58
+#define KS_WF2BM3				0x5A
+
+#define KS_WF3CRC0				0x60
+#define KS_WF3CRC1				0x62
+#define KS_WF3BM0				0x64
+#define KS_WF3BM1				0x66
+#define KS_WF3BM2				0x68
+#define KS_WF3BM3				0x6A
+
+#define KS_TXCR					0x70
+#define TXCR_TCGICMP				(1 << 8)
+#define TXCR_TCGUDP				(1 << 7)
+#define TXCR_TCGTCP				(1 << 6)
+#define TXCR_TCGIP				(1 << 5)
+#define TXCR_FTXQ				(1 << 4)
+#define TXCR_TXFCE				(1 << 3)
+#define TXCR_TXPE				(1 << 2)
+#define TXCR_TXCRC				(1 << 1)
+#define TXCR_TXE				(1 << 0)
+
+#define KS_TXSR					0x72
+#define TXSR_TXLC				(1 << 13)
+#define TXSR_TXMC				(1 << 12)
+#define TXSR_TXFID_MASK				(0x3f << 0)
+#define TXSR_TXFID_SHIFT			(0)
+#define TXSR_TXFID_GET(_v)			(((_v) >> 0) & 0x3f)
+
+#define KS_RXCR1				0x74
+#define RXCR1_FRXQ				(1 << 15)
+#define RXCR1_RXUDPFCC				(1 << 14)
+#define RXCR1_RXTCPFCC				(1 << 13)
+#define RXCR1_RXIPFCC				(1 << 12)
+#define RXCR1_RXPAFMA				(1 << 11)
+#define RXCR1_RXFCE				(1 << 10)
+#define RXCR1_RXEFE				(1 << 9)
+#define RXCR1_RXMAFMA				(1 << 8)
+#define RXCR1_RXBE				(1 << 7)
+#define RXCR1_RXME				(1 << 6)
+#define RXCR1_RXUE				(1 << 5)
+#define RXCR1_RXAE				(1 << 4)
+#define RXCR1_RXINVF				(1 << 1)
+#define RXCR1_RXE				(1 << 0)
+
+#define KS_RXCR2				0x76
+#define RXCR2_SRDBL_MASK			(0x7 << 5)
+#define RXCR2_SRDBL_SHIFT			(5)
+#define RXCR2_SRDBL_4B				(0x0 << 5)
+#define RXCR2_SRDBL_8B				(0x1 << 5)
+#define RXCR2_SRDBL_16B				(0x2 << 5)
+#define RXCR2_SRDBL_32B				(0x3 << 5)
+#define RXCR2_SRDBL_FRAME			(0x4 << 5)
+#define RXCR2_IUFFP				(1 << 4)
+#define RXCR2_RXIUFCEZ				(1 << 3)
+#define RXCR2_UDPLFE				(1 << 2)
+#define RXCR2_RXICMPFCC				(1 << 1)
+#define RXCR2_RXSAF				(1 << 0)
+
+#define KS_TXMIR				0x78
+
+#define KS_RXFHSR				0x7C
+#define RXFSHR_RXFV				(1 << 15)
+#define RXFSHR_RXICMPFCS			(1 << 13)
+#define RXFSHR_RXIPFCS				(1 << 12)
+#define RXFSHR_RXTCPFCS				(1 << 11)
+#define RXFSHR_RXUDPFCS				(1 << 10)
+#define RXFSHR_RXBF				(1 << 7)
+#define RXFSHR_RXMF				(1 << 6)
+#define RXFSHR_RXUF				(1 << 5)
+#define RXFSHR_RXMR				(1 << 4)
+#define RXFSHR_RXFT				(1 << 3)
+#define RXFSHR_RXFTL				(1 << 2)
+#define RXFSHR_RXRF				(1 << 1)
+#define RXFSHR_RXCE				(1 << 0)
+
+#define KS_RXFHBCR				0x7E
+#define KS_TXQCR				0x80
+#define TXQCR_AETFE				(1 << 2)
+#define TXQCR_TXQMAM				(1 << 1)
+#define TXQCR_METFE				(1 << 0)
+
+#define KS_RXQCR				0x82
+#define RXQCR_RXDTTS				(1 << 12)
+#define RXQCR_RXDBCTS				(1 << 11)
+#define RXQCR_RXFCTS				(1 << 10)
+#define RXQCR_RXIPHTOE				(1 << 9)
+#define RXQCR_RXDTTE				(1 << 7)
+#define RXQCR_RXDBCTE				(1 << 6)
+#define RXQCR_RXFCTE				(1 << 5)
+#define RXQCR_ADRFE				(1 << 4)
+#define RXQCR_SDA				(1 << 3)
+#define RXQCR_RRXEF				(1 << 0)
+
+#define KS_TXFDPR				0x84
+#define TXFDPR_TXFPAI				(1 << 14)
+#define TXFDPR_TXFP_MASK			(0x7ff << 0)
+#define TXFDPR_TXFP_SHIFT			(0)
+
+#define KS_RXFDPR				0x86
+#define RXFDPR_RXFPAI				(1 << 14)
+
+#define KS_RXDTTR				0x8C
+#define KS_RXDBCTR				0x8E
+
+#define KS_IER					0x90
+#define KS_ISR					0x92
+#define IRQ_LCI					(1 << 15)
+#define IRQ_TXI					(1 << 14)
+#define IRQ_RXI					(1 << 13)
+#define IRQ_RXOI				(1 << 11)
+#define IRQ_TXPSI				(1 << 9)
+#define IRQ_RXPSI				(1 << 8)
+#define IRQ_TXSAI				(1 << 6)
+#define IRQ_RXWFDI				(1 << 5)
+#define IRQ_RXMPDI				(1 << 4)
+#define IRQ_LDI					(1 << 3)
+#define IRQ_EDI					(1 << 2)
+#define IRQ_SPIBEI				(1 << 1)
+#define IRQ_DEDI				(1 << 0)
+
+#define KS_RXFCTR				0x9C
+#define KS_RXFC					0x9D
+#define RXFCTR_RXFC_MASK			(0xff << 8)
+#define RXFCTR_RXFC_SHIFT			(8)
+#define RXFCTR_RXFC_GET(_v)			(((_v) >> 8) & 0xff)
+#define RXFCTR_RXFCT_MASK			(0xff << 0)
+#define RXFCTR_RXFCT_SHIFT			(0)
+
+#define KS_TXNTFSR				0x9E
+
+#define KS_MAHTR0				0xA0
+#define KS_MAHTR1				0xA2
+#define KS_MAHTR2				0xA4
+#define KS_MAHTR3				0xA6
+
+#define KS_FCLWR				0xB0
+#define KS_FCHWR				0xB2
+#define KS_FCOWR				0xB4
+
+#define KS_CIDER				0xC0
+#define CIDER_ID				0x8870
+#define CIDER_REV_MASK				(0x7 << 1)
+#define CIDER_REV_SHIFT				(1)
+#define CIDER_REV_GET(_v)			(((_v) >> 1) & 0x7)
+
+#define KS_CGCR					0xC6
+
+#define KS_IACR					0xC8
+#define IACR_RDEN				(1 << 12)
+#define IACR_TSEL_MASK				(0x3 << 10)
+#define IACR_TSEL_SHIFT				(10)
+#define IACR_TSEL_MIB				(0x3 << 10)
+#define IACR_ADDR_MASK				(0x1f << 0)
+#define IACR_ADDR_SHIFT				(0)
+
+#define KS_IADLR				0xD0
+#define KS_IAHDR				0xD2
+
+#define KS_PMECR				0xD4
+#define PMECR_PME_DELAY				(1 << 14)
+#define PMECR_PME_POL				(1 << 12)
+#define PMECR_WOL_WAKEUP			(1 << 11)
+#define PMECR_WOL_MAGICPKT			(1 << 10)
+#define PMECR_WOL_LINKUP			(1 << 9)
+#define PMECR_WOL_ENERGY			(1 << 8)
+#define PMECR_AUTO_WAKE_EN			(1 << 7)
+#define PMECR_WAKEUP_NORMAL			(1 << 6)
+#define PMECR_WKEVT_MASK			(0xf << 2)
+#define PMECR_WKEVT_SHIFT			(2)
+#define PMECR_WKEVT_GET(_v)			(((_v) >> 2) & 0xf)
+#define PMECR_WKEVT_ENERGY			(0x1 << 2)
+#define PMECR_WKEVT_LINK			(0x2 << 2)
+#define PMECR_WKEVT_MAGICPKT			(0x4 << 2)
+#define PMECR_WKEVT_FRAME			(0x8 << 2)
+#define PMECR_PM_MASK				(0x3 << 0)
+#define PMECR_PM_SHIFT				(0)
+#define PMECR_PM_NORMAL				(0x0 << 0)
+#define PMECR_PM_ENERGY				(0x1 << 0)
+#define PMECR_PM_SOFTDOWN			(0x2 << 0)
+#define PMECR_PM_POWERSAVE			(0x3 << 0)
+
+/* Standard MII PHY data */
+#define KS_P1MBCR				0xE4
+#define KS_P1MBSR				0xE6
+#define KS_PHY1ILR				0xE8
+#define KS_PHY1IHR				0xEA
+#define KS_P1ANAR				0xEC
+#define KS_P1ANLPR				0xEE
+
+#define KS_P1SCLMD				0xF4
+#define P1SCLMD_LEDOFF				(1 << 15)
+#define P1SCLMD_TXIDS				(1 << 14)
+#define P1SCLMD_RESTARTAN			(1 << 13)
+#define P1SCLMD_DISAUTOMDIX			(1 << 10)
+#define P1SCLMD_FORCEMDIX			(1 << 9)
+#define P1SCLMD_AUTONEGEN			(1 << 7)
+#define P1SCLMD_FORCE100			(1 << 6)
+#define P1SCLMD_FORCEFDX			(1 << 5)
+#define P1SCLMD_ADV_FLOW			(1 << 4)
+#define P1SCLMD_ADV_100BT_FDX			(1 << 3)
+#define P1SCLMD_ADV_100BT_HDX			(1 << 2)
+#define P1SCLMD_ADV_10BT_FDX			(1 << 1)
+#define P1SCLMD_ADV_10BT_HDX			(1 << 0)
+
+#define KS_P1CR					0xF6
+#define P1CR_HP_MDIX				(1 << 15)
+#define P1CR_REV_POL				(1 << 13)
+#define P1CR_OP_100M				(1 << 10)
+#define P1CR_OP_FDX				(1 << 9)
+#define P1CR_OP_MDI				(1 << 7)
+#define P1CR_AN_DONE				(1 << 6)
+#define P1CR_LINK_GOOD				(1 << 5)
+#define P1CR_PNTR_FLOW				(1 << 4)
+#define P1CR_PNTR_100BT_FDX			(1 << 3)
+#define P1CR_PNTR_100BT_HDX			(1 << 2)
+#define P1CR_PNTR_10BT_FDX			(1 << 1)
+#define P1CR_PNTR_10BT_HDX			(1 << 0)
+
+/* TX Frame control */
+
+#define TXFR_TXIC				(1 << 15)
+#define TXFR_TXFID_MASK				(0x3f << 0)
+#define TXFR_TXFID_SHIFT			(0)
+
+/* SPI frame opcodes */
+#define KS_SPIOP_RD				(0x00)
+#define KS_SPIOP_WR				(0x40)
+#define KS_SPIOP_RXFIFO				(0x80)
+#define KS_SPIOP_TXFIFO				(0xC0)
diff -druN linux-libre-2.6.30-gnu/drivers/net/lasi_82596.c linux-libre-2.6.31-gnu/drivers/net/lasi_82596.c
--- linux-libre-2.6.30-gnu/drivers/net/lasi_82596.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/lasi_82596.c	2009-09-09 18:13:59.000000000 -0400
@@ -161,12 +161,12 @@
 
 	if (!dev->irq) {
 		printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
-			__FILE__, dev->hpa.start);
+			__FILE__, (unsigned long)dev->hpa.start);
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
-			dev->irq);
+	printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n",
+			(unsigned long)dev->hpa.start, dev->irq);
 
 	netdevice = alloc_etherdev(sizeof(struct i596_private));
 	if (!netdevice)
diff -druN linux-libre-2.6.30-gnu/drivers/net/lib82596.c linux-libre-2.6.31-gnu/drivers/net/lib82596.c
--- linux-libre-2.6.30-gnu/drivers/net/lib82596.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/lib82596.c	2009-09-09 18:13:59.000000000 -0400
@@ -1036,6 +1036,19 @@
 	printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n",
 	       add, add + 6, add, add[12], add[13], str);
 }
+static const struct net_device_ops i596_netdev_ops = {
+	.ndo_open		= i596_open,
+	.ndo_stop		= i596_close,
+	.ndo_start_xmit		= i596_start_xmit,
+	.ndo_set_multicast_list	= set_multicast_list,
+	.ndo_tx_timeout		= i596_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= i596_poll_controller,
+#endif
+};
 
 static int __devinit i82596_probe(struct net_device *dev)
 {
@@ -1062,16 +1075,8 @@
 		return -ENOMEM;
 	}
 
-	/* The 82596-specific entries in the device structure. */
-	dev->open = i596_open;
-	dev->stop = i596_close;
-	dev->hard_start_xmit = i596_start_xmit;
-	dev->set_multicast_list = set_multicast_list;
-	dev->tx_timeout = i596_tx_timeout;
+	dev->netdev_ops = &i596_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = i596_poll_controller;
-#endif
 
 	memset(dma, 0, sizeof(struct i596_dma));
 	lp->dma = dma;
diff -druN linux-libre-2.6.30-gnu/drivers/net/lib8390.c linux-libre-2.6.31-gnu/drivers/net/lib8390.c
--- linux-libre-2.6.30-gnu/drivers/net/lib8390.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/lib8390.c	2009-09-09 18:13:59.000000000 -0400
@@ -370,7 +370,7 @@
 		spin_unlock(&ei_local->page_lock);
 		enable_irq_lockdep_irqrestore(dev->irq, &flags);
 		dev->stats.tx_errors++;
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	/*
diff -druN linux-libre-2.6.30-gnu/drivers/net/ll_temac.h linux-libre-2.6.31-gnu/drivers/net/ll_temac.h
--- linux-libre-2.6.30-gnu/drivers/net/ll_temac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ll_temac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,374 @@
+
+#ifndef XILINX_LL_TEMAC_H
+#define XILINX_LL_TEMAC_H
+
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
+
+/* packet size info */
+#define XTE_HDR_SIZE			14      /* size of Ethernet header */
+#define XTE_TRL_SIZE			4       /* size of Ethernet trailer (FCS) */
+#define XTE_JUMBO_MTU			9000
+#define XTE_MAX_JUMBO_FRAME_SIZE	(XTE_JUMBO_MTU + XTE_HDR_SIZE + XTE_TRL_SIZE)
+
+/*  Configuration options */
+
+/*  Accept all incoming packets.
+ *  This option defaults to disabled (cleared) */
+#define XTE_OPTION_PROMISC                      (1 << 0)
+/*  Jumbo frame support for Tx & Rx.
+ *  This option defaults to disabled (cleared) */
+#define XTE_OPTION_JUMBO                        (1 << 1)
+/*  VLAN Rx & Tx frame support.
+ *  This option defaults to disabled (cleared) */
+#define XTE_OPTION_VLAN                         (1 << 2)
+/*  Enable recognition of flow control frames on Rx
+ *  This option defaults to enabled (set) */
+#define XTE_OPTION_FLOW_CONTROL                 (1 << 4)
+/*  Strip FCS and PAD from incoming frames.
+ *  Note: PAD from VLAN frames is not stripped.
+ *  This option defaults to disabled (set) */
+#define XTE_OPTION_FCS_STRIP                    (1 << 5)
+/*  Generate FCS field and add PAD automatically for outgoing frames.
+ *  This option defaults to enabled (set) */
+#define XTE_OPTION_FCS_INSERT                   (1 << 6)
+/*  Enable Length/Type error checking for incoming frames. When this option is
+set, the MAC will filter frames that have a mismatched type/length field
+and if XTE_OPTION_REPORT_RXERR is set, the user is notified when these
+types of frames are encountered. When this option is cleared, the MAC will
+allow these types of frames to be received.
+This option defaults to enabled (set) */
+#define XTE_OPTION_LENTYPE_ERR                  (1 << 7)
+/*  Enable the transmitter.
+ *  This option defaults to enabled (set) */
+#define XTE_OPTION_TXEN                         (1 << 11)
+/*  Enable the receiver
+*   This option defaults to enabled (set) */
+#define XTE_OPTION_RXEN                         (1 << 12)
+
+/*  Default options set when device is initialized or reset */
+#define XTE_OPTION_DEFAULTS                     \
+	(XTE_OPTION_TXEN |                          \
+	 XTE_OPTION_FLOW_CONTROL |                  \
+	 XTE_OPTION_RXEN)
+
+/* XPS_LL_TEMAC SDMA registers definition */
+
+#define TX_NXTDESC_PTR      0x00            /* r */
+#define TX_CURBUF_ADDR      0x01            /* r */
+#define TX_CURBUF_LENGTH    0x02            /* r */
+#define TX_CURDESC_PTR      0x03            /* rw */
+#define TX_TAILDESC_PTR     0x04            /* rw */
+#define TX_CHNL_CTRL        0x05            /* rw */
+/*
+ 0:7      24:31       IRQTimeout
+ 8:15     16:23       IRQCount
+ 16:20    11:15       Reserved
+ 21       10          0
+ 22       9           UseIntOnEnd
+ 23       8           LdIRQCnt
+ 24       7           IRQEn
+ 25:28    3:6         Reserved
+ 29       2           IrqErrEn
+ 30       1           IrqDlyEn
+ 31       0           IrqCoalEn
+*/
+#define CHNL_CTRL_IRQ_IOE       (1 << 9)
+#define CHNL_CTRL_IRQ_EN        (1 << 7)
+#define CHNL_CTRL_IRQ_ERR_EN    (1 << 2)
+#define CHNL_CTRL_IRQ_DLY_EN    (1 << 1)
+#define CHNL_CTRL_IRQ_COAL_EN   (1 << 0)
+#define TX_IRQ_REG          0x06            /* rw */
+/*
+  0:7      24:31       DltTmrValue
+ 8:15     16:23       ClscCntrValue
+ 16:17    14:15       Reserved
+ 18:21    10:13       ClscCnt
+ 22:23    8:9         DlyCnt
+ 24:28    3::7        Reserved
+ 29       2           ErrIrq
+ 30       1           DlyIrq
+ 31       0           CoalIrq
+ */
+#define TX_CHNL_STS         0x07            /* r */
+/*
+   0:9      22:31   Reserved
+ 10       21      TailPErr
+ 11       20      CmpErr
+ 12       19      AddrErr
+ 13       18      NxtPErr
+ 14       17      CurPErr
+ 15       16      BsyWr
+ 16:23    8:15    Reserved
+ 24       7       Error
+ 25       6       IOE
+ 26       5       SOE
+ 27       4       Cmplt
+ 28       3       SOP
+ 29       2       EOP
+ 30       1       EngBusy
+ 31       0       Reserved
+*/
+
+#define RX_NXTDESC_PTR      0x08            /* r */
+#define RX_CURBUF_ADDR      0x09            /* r */
+#define RX_CURBUF_LENGTH    0x0a            /* r */
+#define RX_CURDESC_PTR      0x0b            /* rw */
+#define RX_TAILDESC_PTR     0x0c            /* rw */
+#define RX_CHNL_CTRL        0x0d            /* rw */
+/*
+ 0:7      24:31       IRQTimeout
+ 8:15     16:23       IRQCount
+ 16:20    11:15       Reserved
+ 21       10          0
+ 22       9           UseIntOnEnd
+ 23       8           LdIRQCnt
+ 24       7           IRQEn
+ 25:28    3:6         Reserved
+ 29       2           IrqErrEn
+ 30       1           IrqDlyEn
+ 31       0           IrqCoalEn
+ */
+#define RX_IRQ_REG          0x0e            /* rw */
+#define IRQ_COAL        (1 << 0)
+#define IRQ_DLY         (1 << 1)
+#define IRQ_ERR         (1 << 2)
+#define IRQ_DMAERR      (1 << 7)            /* this is not documented ??? */
+/*
+ 0:7      24:31       DltTmrValue
+ 8:15     16:23       ClscCntrValue
+ 16:17    14:15       Reserved
+ 18:21    10:13       ClscCnt
+ 22:23    8:9         DlyCnt
+ 24:28    3::7        Reserved
+*/
+#define RX_CHNL_STS         0x0f        /* r */
+#define CHNL_STS_ENGBUSY    (1 << 1)
+#define CHNL_STS_EOP        (1 << 2)
+#define CHNL_STS_SOP        (1 << 3)
+#define CHNL_STS_CMPLT      (1 << 4)
+#define CHNL_STS_SOE        (1 << 5)
+#define CHNL_STS_IOE        (1 << 6)
+#define CHNL_STS_ERR        (1 << 7)
+
+#define CHNL_STS_BSYWR      (1 << 16)
+#define CHNL_STS_CURPERR    (1 << 17)
+#define CHNL_STS_NXTPERR    (1 << 18)
+#define CHNL_STS_ADDRERR    (1 << 19)
+#define CHNL_STS_CMPERR     (1 << 20)
+#define CHNL_STS_TAILERR    (1 << 21)
+/*
+ 0:9      22:31   Reserved
+ 10       21      TailPErr
+ 11       20      CmpErr
+ 12       19      AddrErr
+ 13       18      NxtPErr
+ 14       17      CurPErr
+ 15       16      BsyWr
+ 16:23    8:15    Reserved
+ 24       7       Error
+ 25       6       IOE
+ 26       5       SOE
+ 27       4       Cmplt
+ 28       3       SOP
+ 29       2       EOP
+ 30       1       EngBusy
+ 31       0       Reserved
+*/
+
+#define DMA_CONTROL_REG             0x10            /* rw */
+#define DMA_CONTROL_RST                 (1 << 0)
+#define DMA_TAIL_ENABLE                 (1 << 2)
+
+/* XPS_LL_TEMAC direct registers definition */
+
+#define XTE_RAF0_OFFSET              0x00
+#define RAF0_RST                        (1 << 0)
+#define RAF0_MCSTREJ                    (1 << 1)
+#define RAF0_BCSTREJ                    (1 << 2)
+#define XTE_TPF0_OFFSET              0x04
+#define XTE_IFGP0_OFFSET             0x08
+#define XTE_ISR0_OFFSET              0x0c
+#define ISR0_HARDACSCMPLT               (1 << 0)
+#define ISR0_AUTONEG                    (1 << 1)
+#define ISR0_RXCMPLT                    (1 << 2)
+#define ISR0_RXREJ                      (1 << 3)
+#define ISR0_RXFIFOOVR                  (1 << 4)
+#define ISR0_TXCMPLT                    (1 << 5)
+#define ISR0_RXDCMLCK                   (1 << 6)
+
+#define XTE_IPR0_OFFSET              0x10
+#define XTE_IER0_OFFSET              0x14
+
+#define XTE_MSW0_OFFSET              0x20
+#define XTE_LSW0_OFFSET              0x24
+#define XTE_CTL0_OFFSET              0x28
+#define XTE_RDY0_OFFSET              0x2c
+
+#define XTE_RSE_MIIM_RR_MASK      0x0002
+#define XTE_RSE_MIIM_WR_MASK      0x0004
+#define XTE_RSE_CFG_RR_MASK       0x0020
+#define XTE_RSE_CFG_WR_MASK       0x0040
+#define XTE_RDY0_HARD_ACS_RDY_MASK  (0x10000)
+
+/* XPS_LL_TEMAC indirect registers offset definition */
+
+#define	XTE_RXC0_OFFSET			0x00000200 /* Rx configuration word 0 */
+#define	XTE_RXC1_OFFSET			0x00000240 /* Rx configuration word 1 */
+#define XTE_RXC1_RXRST_MASK		(1 << 31)  /* Receiver reset */
+#define XTE_RXC1_RXJMBO_MASK		(1 << 30)  /* Jumbo frame enable */
+#define XTE_RXC1_RXFCS_MASK		(1 << 29)  /* FCS not stripped */
+#define XTE_RXC1_RXEN_MASK		(1 << 28)  /* Receiver enable */
+#define XTE_RXC1_RXVLAN_MASK		(1 << 27)  /* VLAN enable */
+#define XTE_RXC1_RXHD_MASK		(1 << 26)  /* Half duplex */
+#define XTE_RXC1_RXLT_MASK		(1 << 25)  /* Length/type check disable */
+
+#define XTE_TXC_OFFSET			0x00000280 /*  Tx configuration */
+#define XTE_TXC_TXRST_MASK		(1 << 31)  /* Transmitter reset */
+#define XTE_TXC_TXJMBO_MASK		(1 << 30)  /* Jumbo frame enable */
+#define XTE_TXC_TXFCS_MASK		(1 << 29)  /* Generate FCS */
+#define XTE_TXC_TXEN_MASK		(1 << 28)  /* Transmitter enable */
+#define XTE_TXC_TXVLAN_MASK		(1 << 27)  /* VLAN enable */
+#define XTE_TXC_TXHD_MASK		(1 << 26)  /* Half duplex */
+
+#define XTE_FCC_OFFSET			0x000002C0 /* Flow control config */
+#define XTE_FCC_RXFLO_MASK		(1 << 29)  /* Rx flow control enable */
+#define XTE_FCC_TXFLO_MASK		(1 << 30)  /* Tx flow control enable */
+
+#define XTE_EMCFG_OFFSET		0x00000300 /* EMAC configuration */
+#define XTE_EMCFG_LINKSPD_MASK		0xC0000000 /* Link speed */
+#define XTE_EMCFG_HOSTEN_MASK		(1 << 26)  /* Host interface enable */
+#define XTE_EMCFG_LINKSPD_10		0x00000000 /* 10 Mbit LINKSPD_MASK */
+#define XTE_EMCFG_LINKSPD_100		(1 << 30)  /* 100 Mbit LINKSPD_MASK */
+#define XTE_EMCFG_LINKSPD_1000		(1 << 31)  /* 1000 Mbit LINKSPD_MASK */
+
+#define XTE_GMIC_OFFSET			0x00000320 /* RGMII/SGMII config */
+#define XTE_MC_OFFSET			0x00000340 /* MDIO configuration */
+#define XTE_UAW0_OFFSET			0x00000380 /* Unicast address word 0 */
+#define XTE_UAW1_OFFSET			0x00000384 /* Unicast address word 1 */
+
+#define XTE_MAW0_OFFSET			0x00000388 /* Multicast addr word 0 */
+#define XTE_MAW1_OFFSET			0x0000038C /* Multicast addr word 1 */
+#define XTE_AFM_OFFSET			0x00000390 /* Promiscuous mode */
+#define XTE_AFM_EPPRM_MASK		(1 << 31)  /* Promiscuous mode enable */
+
+/* Interrupt Request status */
+#define XTE_TIS_OFFSET			0x000003A0
+#define TIS_FRIS			(1 << 0)
+#define TIS_MRIS			(1 << 1)
+#define TIS_MWIS			(1 << 2)
+#define TIS_ARIS			(1 << 3)
+#define TIS_AWIS			(1 << 4)
+#define TIS_CRIS			(1 << 5)
+#define TIS_CWIS			(1 << 6)
+
+#define XTE_TIE_OFFSET			0x000003A4 /* Interrupt enable */
+
+/**  MII Mamagement Control register (MGTCR) */
+#define XTE_MGTDR_OFFSET		0x000003B0 /* MII data */
+#define XTE_MIIMAI_OFFSET		0x000003B4 /* MII control */
+
+#define CNTLREG_WRITE_ENABLE_MASK   0x8000
+#define CNTLREG_EMAC1SEL_MASK       0x0400
+#define CNTLREG_ADDRESSCODE_MASK    0x03ff
+
+/* CDMAC descriptor status bit definitions */
+
+#define STS_CTRL_APP0_ERR         (1 << 31)
+#define STS_CTRL_APP0_IRQONEND    (1 << 30)
+/* undoccumented */
+#define STS_CTRL_APP0_STOPONEND   (1 << 29)
+#define STS_CTRL_APP0_CMPLT       (1 << 28)
+#define STS_CTRL_APP0_SOP         (1 << 27)
+#define STS_CTRL_APP0_EOP         (1 << 26)
+#define STS_CTRL_APP0_ENGBUSY     (1 << 25)
+/* undocumented */
+#define STS_CTRL_APP0_ENGRST      (1 << 24)
+
+#define TX_CONTROL_CALC_CSUM_MASK   1
+
+#define XTE_ALIGN       32
+#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN)
+
+#define MULTICAST_CAM_TABLE_NUM 4
+
+/* TX/RX CURDESC_PTR points to first descriptor */
+/* TX/RX TAILDESC_PTR points to last descriptor in linked list */
+
+/**
+ * struct cdmac_bd - LocalLink buffer descriptor format
+ *
+ * app0 bits:
+ *	0    Error
+ *	1    IrqOnEnd    generate an interrupt at completion of DMA  op
+ *	2    reserved
+ *	3    completed   Current descriptor completed
+ *	4    SOP         TX - marks first desc/ RX marks first desct
+ *	5    EOP         TX marks last desc/RX marks last desc
+ *	6    EngBusy     DMA is processing
+ *	7    reserved
+ *	8:31 application specific
+ */
+struct cdmac_bd {
+	u32 next;	/* Physical address of next buffer descriptor */
+	u32 phys;
+	u32 len;
+	u32 app0;
+	u32 app1;	/* TX start << 16 | insert */
+	u32 app2;	/* TX csum */
+	u32 app3;
+	u32 app4;	/* skb for TX length for RX */
+};
+
+struct temac_local {
+	struct net_device *ndev;
+	struct device *dev;
+
+	/* Connection to PHY device */
+	struct phy_device *phy_dev;	/* Pointer to PHY device */
+	struct device_node *phy_node;
+
+	/* MDIO bus data */
+	struct mii_bus *mii_bus;	/* MII bus reference */
+	int mdio_irqs[PHY_MAX_ADDR];	/* IRQs table for MDIO bus */
+
+	/* IO registers and IRQs */
+	void __iomem *regs;
+	dcr_host_t sdma_dcrs;
+	int tx_irq;
+	int rx_irq;
+	int emac_num;
+
+	struct sk_buff **rx_skb;
+	spinlock_t rx_lock;
+	struct mutex indirect_mutex;
+	u32 options;			/* Current options word */
+	int last_link;
+
+	/* Buffer descriptors */
+	struct cdmac_bd *tx_bd_v;
+	dma_addr_t tx_bd_p;
+	struct cdmac_bd *rx_bd_v;
+	dma_addr_t rx_bd_p;
+	int tx_bd_ci;
+	int tx_bd_next;
+	int tx_bd_tail;
+	int rx_bd_ci;
+};
+
+/* xilinx_temac.c */
+u32 temac_ior(struct temac_local *lp, int offset);
+void temac_iow(struct temac_local *lp, int offset, u32 value);
+int temac_indirect_busywait(struct temac_local *lp);
+u32 temac_indirect_in32(struct temac_local *lp, int reg);
+void temac_indirect_out32(struct temac_local *lp, int reg, u32 value);
+
+
+/* xilinx_temac_mdio.c */
+int temac_mdio_setup(struct temac_local *lp, struct device_node *np);
+void temac_mdio_teardown(struct temac_local *lp);
+
+#endif /* XILINX_LL_TEMAC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ll_temac_main.c linux-libre-2.6.31-gnu/drivers/net/ll_temac_main.c
--- linux-libre-2.6.30-gnu/drivers/net/ll_temac_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ll_temac_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,969 @@
+/*
+ * Driver for Xilinx TEMAC Ethernet device
+ *
+ * Copyright (c) 2008 Nissin Systems Co., Ltd.,  Yoshio Kashiwagi
+ * Copyright (c) 2005-2008 DLA Systems,  David H. Lynch Jr. <dhlii@dlasys.net>
+ * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
+ *
+ * This is a driver for the Xilinx ll_temac ipcore which is often used
+ * in the Virtex and Spartan series of chips.
+ *
+ * Notes:
+ * - The ll_temac hardware uses indirect access for many of the TEMAC
+ *   registers, include the MDIO bus.  However, indirect access to MDIO
+ *   registers take considerably more clock cycles than to TEMAC registers.
+ *   MDIO accesses are long, so threads doing them should probably sleep
+ *   rather than busywait.  However, since only one indirect access can be
+ *   in progress at any given time, that means that *all* indirect accesses
+ *   could end up sleeping (to wait for an MDIO access to complete).
+ *   Fortunately none of the indirect accesses are on the 'hot' path for tx
+ *   or rx, so this should be okay.
+ *
+ * TODO:
+ * - Fix driver to work on more than just Virtex5.  Right now the driver
+ *   assumes that the locallink DMA registers are accessed via DCR
+ *   instructions.
+ * - Factor out locallink DMA code into separate driver
+ * - Fix multicast assignment.
+ * - Fix support for hardware checksumming.
+ * - Testing.  Lots and lots of testing.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/tcp.h>      /* needed for sizeof(tcphdr) */
+#include <linux/udp.h>      /* needed for sizeof(udphdr) */
+#include <linux/phy.h>
+#include <linux/in.h>
+#include <linux/io.h>
+#include <linux/ip.h>
+
+#include "ll_temac.h"
+
+#define TX_BD_NUM   64
+#define RX_BD_NUM   128
+
+/* ---------------------------------------------------------------------
+ * Low level register access functions
+ */
+
+u32 temac_ior(struct temac_local *lp, int offset)
+{
+	return in_be32((u32 *)(lp->regs + offset));
+}
+
+void temac_iow(struct temac_local *lp, int offset, u32 value)
+{
+	out_be32((u32 *) (lp->regs + offset), value);
+}
+
+int temac_indirect_busywait(struct temac_local *lp)
+{
+	long end = jiffies + 2;
+
+	while (!(temac_ior(lp, XTE_RDY0_OFFSET) & XTE_RDY0_HARD_ACS_RDY_MASK)) {
+		if (end - jiffies <= 0) {
+			WARN_ON(1);
+			return -ETIMEDOUT;
+		}
+		msleep(1);
+	}
+	return 0;
+}
+
+/**
+ * temac_indirect_in32
+ *
+ * lp->indirect_mutex must be held when calling this function
+ */
+u32 temac_indirect_in32(struct temac_local *lp, int reg)
+{
+	u32 val;
+
+	if (temac_indirect_busywait(lp))
+		return -ETIMEDOUT;
+	temac_iow(lp, XTE_CTL0_OFFSET, reg);
+	if (temac_indirect_busywait(lp))
+		return -ETIMEDOUT;
+	val = temac_ior(lp, XTE_LSW0_OFFSET);
+
+	return val;
+}
+
+/**
+ * temac_indirect_out32
+ *
+ * lp->indirect_mutex must be held when calling this function
+ */
+void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
+{
+	if (temac_indirect_busywait(lp))
+		return;
+	temac_iow(lp, XTE_LSW0_OFFSET, value);
+	temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
+}
+
+static u32 temac_dma_in32(struct temac_local *lp, int reg)
+{
+	return dcr_read(lp->sdma_dcrs, reg);
+}
+
+static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
+{
+	dcr_write(lp->sdma_dcrs, reg, value);
+}
+
+/**
+ * temac_dma_bd_init - Setup buffer descriptor rings
+ */
+static int temac_dma_bd_init(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct sk_buff *skb;
+	int i;
+
+	lp->rx_skb = kzalloc(sizeof(struct sk_buff)*RX_BD_NUM, GFP_KERNEL);
+	/* allocate the tx and rx ring buffer descriptors. */
+	/* returns a virtual addres and a physical address. */
+	lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+					 sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+					 &lp->tx_bd_p, GFP_KERNEL);
+	lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+					 sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+					 &lp->rx_bd_p, GFP_KERNEL);
+
+	memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
+	for (i = 0; i < TX_BD_NUM; i++) {
+		lp->tx_bd_v[i].next = lp->tx_bd_p +
+				sizeof(*lp->tx_bd_v) * ((i + 1) % TX_BD_NUM);
+	}
+
+	memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
+	for (i = 0; i < RX_BD_NUM; i++) {
+		lp->rx_bd_v[i].next = lp->rx_bd_p +
+				sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
+
+		skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE
+				+ XTE_ALIGN, GFP_ATOMIC);
+		if (skb == 0) {
+			dev_err(&ndev->dev, "alloc_skb error %d\n", i);
+			return -1;
+		}
+		lp->rx_skb[i] = skb;
+		skb_reserve(skb,  BUFFER_ALIGN(skb->data));
+		/* returns physical address of skb->data */
+		lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
+						     skb->data,
+						     XTE_MAX_JUMBO_FRAME_SIZE,
+						     DMA_FROM_DEVICE);
+		lp->rx_bd_v[i].len = XTE_MAX_JUMBO_FRAME_SIZE;
+		lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND;
+	}
+
+	temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 |
+					  CHNL_CTRL_IRQ_EN |
+					  CHNL_CTRL_IRQ_DLY_EN |
+					  CHNL_CTRL_IRQ_COAL_EN);
+	/* 0x10220483 */
+	/* 0x00100483 */
+	temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 |
+					  CHNL_CTRL_IRQ_EN |
+					  CHNL_CTRL_IRQ_DLY_EN |
+					  CHNL_CTRL_IRQ_COAL_EN |
+					  CHNL_CTRL_IRQ_IOE);
+	/* 0xff010283 */
+
+	temac_dma_out32(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
+	temac_dma_out32(lp, RX_TAILDESC_PTR,
+		       lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
+	temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p);
+
+	return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * net_device_ops
+ */
+
+static int temac_set_mac_address(struct net_device *ndev, void *address)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+
+	if (address)
+		memcpy(ndev->dev_addr, address, ETH_ALEN);
+
+	if (!is_valid_ether_addr(ndev->dev_addr))
+		random_ether_addr(ndev->dev_addr);
+
+	/* set up unicast MAC address filter set its mac address */
+	mutex_lock(&lp->indirect_mutex);
+	temac_indirect_out32(lp, XTE_UAW0_OFFSET,
+			     (ndev->dev_addr[0]) |
+			     (ndev->dev_addr[1] << 8) |
+			     (ndev->dev_addr[2] << 16) |
+			     (ndev->dev_addr[3] << 24));
+	/* There are reserved bits in EUAW1
+	 * so don't affect them Set MAC bits [47:32] in EUAW1 */
+	temac_indirect_out32(lp, XTE_UAW1_OFFSET,
+			     (ndev->dev_addr[4] & 0x000000ff) |
+			     (ndev->dev_addr[5] << 8));
+	mutex_unlock(&lp->indirect_mutex);
+
+	return 0;
+}
+
+static void temac_set_multicast_list(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	u32 multi_addr_msw, multi_addr_lsw, val;
+	int i;
+
+	mutex_lock(&lp->indirect_mutex);
+	if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC)
+			|| ndev->mc_count > MULTICAST_CAM_TABLE_NUM) {
+		/*
+		 *	We must make the kernel realise we had to move
+		 *	into promisc mode or we start all out war on
+		 *	the cable. If it was a promisc request the
+		 *	flag is already set. If not we assert it.
+		 */
+		ndev->flags |= IFF_PROMISC;
+		temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK);
+		dev_info(&ndev->dev, "Promiscuous mode enabled.\n");
+	} else if (ndev->mc_count) {
+		struct dev_mc_list *mclist = ndev->mc_list;
+		for (i = 0; mclist && i < ndev->mc_count; i++) {
+
+			if (i >= MULTICAST_CAM_TABLE_NUM)
+				break;
+			multi_addr_msw = ((mclist->dmi_addr[3] << 24) |
+					  (mclist->dmi_addr[2] << 16) |
+					  (mclist->dmi_addr[1] << 8) |
+					  (mclist->dmi_addr[0]));
+			temac_indirect_out32(lp, XTE_MAW0_OFFSET,
+					     multi_addr_msw);
+			multi_addr_lsw = ((mclist->dmi_addr[5] << 8) |
+					  (mclist->dmi_addr[4]) | (i << 16));
+			temac_indirect_out32(lp, XTE_MAW1_OFFSET,
+					     multi_addr_lsw);
+			mclist = mclist->next;
+		}
+	} else {
+		val = temac_indirect_in32(lp, XTE_AFM_OFFSET);
+		temac_indirect_out32(lp, XTE_AFM_OFFSET,
+				     val & ~XTE_AFM_EPPRM_MASK);
+		temac_indirect_out32(lp, XTE_MAW0_OFFSET, 0);
+		temac_indirect_out32(lp, XTE_MAW1_OFFSET, 0);
+		dev_info(&ndev->dev, "Promiscuous mode disabled.\n");
+	}
+	mutex_unlock(&lp->indirect_mutex);
+}
+
+struct temac_option {
+	int flg;
+	u32 opt;
+	u32 reg;
+	u32 m_or;
+	u32 m_and;
+} temac_options[] = {
+	/* Turn on jumbo packet support for both Rx and Tx */
+	{
+		.opt = XTE_OPTION_JUMBO,
+		.reg = XTE_TXC_OFFSET,
+		.m_or = XTE_TXC_TXJMBO_MASK,
+	},
+	{
+		.opt = XTE_OPTION_JUMBO,
+		.reg = XTE_RXC1_OFFSET,
+		.m_or =XTE_RXC1_RXJMBO_MASK,
+	},
+	/* Turn on VLAN packet support for both Rx and Tx */
+	{
+		.opt = XTE_OPTION_VLAN,
+		.reg = XTE_TXC_OFFSET,
+		.m_or =XTE_TXC_TXVLAN_MASK,
+	},
+	{
+		.opt = XTE_OPTION_VLAN,
+		.reg = XTE_RXC1_OFFSET,
+		.m_or =XTE_RXC1_RXVLAN_MASK,
+	},
+	/* Turn on FCS stripping on receive packets */
+	{
+		.opt = XTE_OPTION_FCS_STRIP,
+		.reg = XTE_RXC1_OFFSET,
+		.m_or =XTE_RXC1_RXFCS_MASK,
+	},
+	/* Turn on FCS insertion on transmit packets */
+	{
+		.opt = XTE_OPTION_FCS_INSERT,
+		.reg = XTE_TXC_OFFSET,
+		.m_or =XTE_TXC_TXFCS_MASK,
+	},
+	/* Turn on length/type field checking on receive packets */
+	{
+		.opt = XTE_OPTION_LENTYPE_ERR,
+		.reg = XTE_RXC1_OFFSET,
+		.m_or =XTE_RXC1_RXLT_MASK,
+	},
+	/* Turn on flow control */
+	{
+		.opt = XTE_OPTION_FLOW_CONTROL,
+		.reg = XTE_FCC_OFFSET,
+		.m_or =XTE_FCC_RXFLO_MASK,
+	},
+	/* Turn on flow control */
+	{
+		.opt = XTE_OPTION_FLOW_CONTROL,
+		.reg = XTE_FCC_OFFSET,
+		.m_or =XTE_FCC_TXFLO_MASK,
+	},
+	/* Turn on promiscuous frame filtering (all frames are received ) */
+	{
+		.opt = XTE_OPTION_PROMISC,
+		.reg = XTE_AFM_OFFSET,
+		.m_or =XTE_AFM_EPPRM_MASK,
+	},
+	/* Enable transmitter if not already enabled */
+	{
+		.opt = XTE_OPTION_TXEN,
+		.reg = XTE_TXC_OFFSET,
+		.m_or =XTE_TXC_TXEN_MASK,
+	},
+	/* Enable receiver? */
+	{
+		.opt = XTE_OPTION_RXEN,
+		.reg = XTE_RXC1_OFFSET,
+		.m_or =XTE_RXC1_RXEN_MASK,
+	},
+	{}
+};
+
+/**
+ * temac_setoptions
+ */
+static u32 temac_setoptions(struct net_device *ndev, u32 options)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct temac_option *tp = &temac_options[0];
+	int reg;
+
+	mutex_lock(&lp->indirect_mutex);
+	while (tp->opt) {
+		reg = temac_indirect_in32(lp, tp->reg) & ~tp->m_or;
+		if (options & tp->opt)
+			reg |= tp->m_or;
+		temac_indirect_out32(lp, tp->reg, reg);
+		tp++;
+	}
+	lp->options |= options;
+	mutex_unlock(&lp->indirect_mutex);
+
+	return (0);
+}
+
+/* Initilize temac */
+static void temac_device_reset(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	u32 timeout;
+	u32 val;
+
+	/* Perform a software reset */
+
+	/* 0x300 host enable bit ? */
+	/* reset PHY through control register ?:1 */
+
+	dev_dbg(&ndev->dev, "%s()\n", __func__);
+
+	mutex_lock(&lp->indirect_mutex);
+	/* Reset the receiver and wait for it to finish reset */
+	temac_indirect_out32(lp, XTE_RXC1_OFFSET, XTE_RXC1_RXRST_MASK);
+	timeout = 1000;
+	while (temac_indirect_in32(lp, XTE_RXC1_OFFSET) & XTE_RXC1_RXRST_MASK) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev,
+				"temac_device_reset RX reset timeout!!\n");
+			break;
+		}
+	}
+
+	/* Reset the transmitter and wait for it to finish reset */
+	temac_indirect_out32(lp, XTE_TXC_OFFSET, XTE_TXC_TXRST_MASK);
+	timeout = 1000;
+	while (temac_indirect_in32(lp, XTE_TXC_OFFSET) & XTE_TXC_TXRST_MASK) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev,
+				"temac_device_reset TX reset timeout!!\n");
+			break;
+		}
+	}
+
+	/* Disable the receiver */
+	val = temac_indirect_in32(lp, XTE_RXC1_OFFSET);
+	temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK);
+
+	/* Reset Local Link (DMA) */
+	temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
+	timeout = 1000;
+	while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev,
+				"temac_device_reset DMA reset timeout!!\n");
+			break;
+		}
+	}
+	temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
+
+	temac_dma_bd_init(ndev);
+
+	temac_indirect_out32(lp, XTE_RXC0_OFFSET, 0);
+	temac_indirect_out32(lp, XTE_RXC1_OFFSET, 0);
+	temac_indirect_out32(lp, XTE_TXC_OFFSET, 0);
+	temac_indirect_out32(lp, XTE_FCC_OFFSET, XTE_FCC_RXFLO_MASK);
+
+	mutex_unlock(&lp->indirect_mutex);
+
+	/* Sync default options with HW
+	 * but leave receiver and transmitter disabled.  */
+	temac_setoptions(ndev,
+			 lp->options & ~(XTE_OPTION_TXEN | XTE_OPTION_RXEN));
+
+	temac_set_mac_address(ndev, NULL);
+
+	/* Set address filter table */
+	temac_set_multicast_list(ndev);
+	if (temac_setoptions(ndev, lp->options))
+		dev_err(&ndev->dev, "Error setting TEMAC options\n");
+
+	/* Init Driver variable */
+	ndev->trans_start = 0;
+}
+
+void temac_adjust_link(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct phy_device *phy = lp->phy_dev;
+	u32 mii_speed;
+	int link_state;
+
+	/* hash together the state values to decide if something has changed */
+	link_state = phy->speed | (phy->duplex << 1) | phy->link;
+
+	mutex_lock(&lp->indirect_mutex);
+	if (lp->last_link != link_state) {
+		mii_speed = temac_indirect_in32(lp, XTE_EMCFG_OFFSET);
+		mii_speed &= ~XTE_EMCFG_LINKSPD_MASK;
+
+		switch (phy->speed) {
+		case SPEED_1000: mii_speed |= XTE_EMCFG_LINKSPD_1000; break;
+		case SPEED_100: mii_speed |= XTE_EMCFG_LINKSPD_100; break;
+		case SPEED_10: mii_speed |= XTE_EMCFG_LINKSPD_10; break;
+		}
+
+		/* Write new speed setting out to TEMAC */
+		temac_indirect_out32(lp, XTE_EMCFG_OFFSET, mii_speed);
+		lp->last_link = link_state;
+		phy_print_status(phy);
+	}
+	mutex_unlock(&lp->indirect_mutex);
+}
+
+static void temac_start_xmit_done(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct cdmac_bd *cur_p;
+	unsigned int stat = 0;
+
+	cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+	stat = cur_p->app0;
+
+	while (stat & STS_CTRL_APP0_CMPLT) {
+		dma_unmap_single(ndev->dev.parent, cur_p->phys, cur_p->len,
+				 DMA_TO_DEVICE);
+		if (cur_p->app4)
+			dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
+		cur_p->app0 = 0;
+
+		ndev->stats.tx_packets++;
+		ndev->stats.tx_bytes += cur_p->len;
+
+		lp->tx_bd_ci++;
+		if (lp->tx_bd_ci >= TX_BD_NUM)
+			lp->tx_bd_ci = 0;
+
+		cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+		stat = cur_p->app0;
+	}
+
+	netif_wake_queue(ndev);
+}
+
+static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct cdmac_bd *cur_p;
+	dma_addr_t start_p, tail_p;
+	int ii;
+	unsigned long num_frag;
+	skb_frag_t *frag;
+
+	num_frag = skb_shinfo(skb)->nr_frags;
+	frag = &skb_shinfo(skb)->frags[0];
+	start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
+	cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+
+	if (cur_p->app0 & STS_CTRL_APP0_CMPLT) {
+		if (!netif_queue_stopped(ndev)) {
+			netif_stop_queue(ndev);
+			return NETDEV_TX_BUSY;
+		}
+		return NETDEV_TX_BUSY;
+	}
+
+	cur_p->app0 = 0;
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		const struct iphdr *ip = ip_hdr(skb);
+		int length = 0, start = 0, insert = 0;
+
+		switch (ip->protocol) {
+		case IPPROTO_TCP:
+			start = sizeof(struct iphdr) + ETH_HLEN;
+			insert = sizeof(struct iphdr) + ETH_HLEN + 16;
+			length = ip->tot_len - sizeof(struct iphdr);
+			break;
+		case IPPROTO_UDP:
+			start = sizeof(struct iphdr) + ETH_HLEN;
+			insert = sizeof(struct iphdr) + ETH_HLEN + 6;
+			length = ip->tot_len - sizeof(struct iphdr);
+			break;
+		default:
+			break;
+		}
+		cur_p->app1 = ((start << 16) | insert);
+		cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr,
+						length, ip->protocol, 0);
+		skb->data[insert] = 0;
+		skb->data[insert + 1] = 0;
+	}
+	cur_p->app0 |= STS_CTRL_APP0_SOP;
+	cur_p->len = skb_headlen(skb);
+	cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len,
+				     DMA_TO_DEVICE);
+	cur_p->app4 = (unsigned long)skb;
+
+	for (ii = 0; ii < num_frag; ii++) {
+		lp->tx_bd_tail++;
+		if (lp->tx_bd_tail >= TX_BD_NUM)
+			lp->tx_bd_tail = 0;
+
+		cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+		cur_p->phys = dma_map_single(ndev->dev.parent,
+					     (void *)page_address(frag->page) +
+					          frag->page_offset,
+					     frag->size, DMA_TO_DEVICE);
+		cur_p->len = frag->size;
+		cur_p->app0 = 0;
+		frag++;
+	}
+	cur_p->app0 |= STS_CTRL_APP0_EOP;
+
+	tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
+	lp->tx_bd_tail++;
+	if (lp->tx_bd_tail >= TX_BD_NUM)
+		lp->tx_bd_tail = 0;
+
+	/* Kick off the transfer */
+	temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
+
+	return 0;
+}
+
+
+static void ll_temac_recv(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct sk_buff *skb, *new_skb;
+	unsigned int bdstat;
+	struct cdmac_bd *cur_p;
+	dma_addr_t tail_p;
+	int length;
+	unsigned long skb_vaddr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lp->rx_lock, flags);
+
+	tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
+	cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
+
+	bdstat = cur_p->app0;
+	while ((bdstat & STS_CTRL_APP0_CMPLT)) {
+
+		skb = lp->rx_skb[lp->rx_bd_ci];
+		length = cur_p->app4;
+
+		skb_vaddr = virt_to_bus(skb->data);
+		dma_unmap_single(ndev->dev.parent, skb_vaddr, length,
+				 DMA_FROM_DEVICE);
+
+		skb_put(skb, length);
+		skb->dev = ndev;
+		skb->protocol = eth_type_trans(skb, ndev);
+		skb->ip_summed = CHECKSUM_NONE;
+
+		netif_rx(skb);
+
+		ndev->stats.rx_packets++;
+		ndev->stats.rx_bytes += length;
+
+		new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN,
+				GFP_ATOMIC);
+		if (new_skb == 0) {
+			dev_err(&ndev->dev, "no memory for new sk_buff\n");
+			spin_unlock_irqrestore(&lp->rx_lock, flags);
+			return;
+		}
+
+		skb_reserve(new_skb, BUFFER_ALIGN(new_skb->data));
+
+		cur_p->app0 = STS_CTRL_APP0_IRQONEND;
+		cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
+					     XTE_MAX_JUMBO_FRAME_SIZE,
+					     DMA_FROM_DEVICE);
+		cur_p->len = XTE_MAX_JUMBO_FRAME_SIZE;
+		lp->rx_skb[lp->rx_bd_ci] = new_skb;
+
+		lp->rx_bd_ci++;
+		if (lp->rx_bd_ci >= RX_BD_NUM)
+			lp->rx_bd_ci = 0;
+
+		cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
+		bdstat = cur_p->app0;
+	}
+	temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p);
+
+	spin_unlock_irqrestore(&lp->rx_lock, flags);
+}
+
+static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
+{
+	struct net_device *ndev = _ndev;
+	struct temac_local *lp = netdev_priv(ndev);
+	unsigned int status;
+
+	status = temac_dma_in32(lp, TX_IRQ_REG);
+	temac_dma_out32(lp, TX_IRQ_REG, status);
+
+	if (status & (IRQ_COAL | IRQ_DLY))
+		temac_start_xmit_done(lp->ndev);
+	if (status & 0x080)
+		dev_err(&ndev->dev, "DMA error 0x%x\n", status);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
+{
+	struct net_device *ndev = _ndev;
+	struct temac_local *lp = netdev_priv(ndev);
+	unsigned int status;
+
+	/* Read and clear the status registers */
+	status = temac_dma_in32(lp, RX_IRQ_REG);
+	temac_dma_out32(lp, RX_IRQ_REG, status);
+
+	if (status & (IRQ_COAL | IRQ_DLY))
+		ll_temac_recv(lp->ndev);
+
+	return IRQ_HANDLED;
+}
+
+static int temac_open(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	int rc;
+
+	dev_dbg(&ndev->dev, "temac_open()\n");
+
+	if (lp->phy_node) {
+		lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
+					     temac_adjust_link, 0, 0);
+		if (!lp->phy_dev) {
+			dev_err(lp->dev, "of_phy_connect() failed\n");
+			return -ENODEV;
+		}
+
+		phy_start(lp->phy_dev);
+	}
+
+	rc = request_irq(lp->tx_irq, ll_temac_tx_irq, 0, ndev->name, ndev);
+	if (rc)
+		goto err_tx_irq;
+	rc = request_irq(lp->rx_irq, ll_temac_rx_irq, 0, ndev->name, ndev);
+	if (rc)
+		goto err_rx_irq;
+
+	temac_device_reset(ndev);
+	return 0;
+
+ err_rx_irq:
+	free_irq(lp->tx_irq, ndev);
+ err_tx_irq:
+	if (lp->phy_dev)
+		phy_disconnect(lp->phy_dev);
+	lp->phy_dev = NULL;
+	dev_err(lp->dev, "request_irq() failed\n");
+	return rc;
+}
+
+static int temac_stop(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+
+	dev_dbg(&ndev->dev, "temac_close()\n");
+
+	free_irq(lp->tx_irq, ndev);
+	free_irq(lp->rx_irq, ndev);
+
+	if (lp->phy_dev)
+		phy_disconnect(lp->phy_dev);
+	lp->phy_dev = NULL;
+
+	return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+temac_poll_controller(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+
+	disable_irq(lp->tx_irq);
+	disable_irq(lp->rx_irq);
+
+	ll_temac_rx_irq(lp->tx_irq, lp);
+	ll_temac_tx_irq(lp->rx_irq, lp);
+
+	enable_irq(lp->tx_irq);
+	enable_irq(lp->rx_irq);
+}
+#endif
+
+static const struct net_device_ops temac_netdev_ops = {
+	.ndo_open = temac_open,
+	.ndo_stop = temac_stop,
+	.ndo_start_xmit = temac_start_xmit,
+	.ndo_set_mac_address = temac_set_mac_address,
+	//.ndo_set_multicast_list = temac_set_multicast_list,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller = temac_poll_controller,
+#endif
+};
+
+/* ---------------------------------------------------------------------
+ * SYSFS device attributes
+ */
+static ssize_t temac_show_llink_regs(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct temac_local *lp = netdev_priv(ndev);
+	int i, len = 0;
+
+	for (i = 0; i < 0x11; i++)
+		len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i),
+			       (i % 8) == 7 ? "\n" : " ");
+	len += sprintf(buf + len, "\n");
+
+	return len;
+}
+
+static DEVICE_ATTR(llink_regs, 0440, temac_show_llink_regs, NULL);
+
+static struct attribute *temac_device_attrs[] = {
+	&dev_attr_llink_regs.attr,
+	NULL,
+};
+
+static const struct attribute_group temac_attr_group = {
+	.attrs = temac_device_attrs,
+};
+
+static int __init
+temac_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+	struct device_node *np;
+	struct temac_local *lp;
+	struct net_device *ndev;
+	const void *addr;
+	int size, rc = 0;
+	unsigned int dcrs;
+
+	/* Init network device structure */
+	ndev = alloc_etherdev(sizeof(*lp));
+	if (!ndev) {
+		dev_err(&op->dev, "could not allocate device.\n");
+		return -ENOMEM;
+	}
+	ether_setup(ndev);
+	dev_set_drvdata(&op->dev, ndev);
+	SET_NETDEV_DEV(ndev, &op->dev);
+	ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
+	ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+	ndev->netdev_ops = &temac_netdev_ops;
+#if 0
+	ndev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4. */
+	ndev->features |= NETIF_F_HW_CSUM; /* Can checksum all the packets. */
+	ndev->features |= NETIF_F_IPV6_CSUM; /* Can checksum IPV6 TCP/UDP */
+	ndev->features |= NETIF_F_HIGHDMA; /* Can DMA to high memory. */
+	ndev->features |= NETIF_F_HW_VLAN_TX; /* Transmit VLAN hw accel */
+	ndev->features |= NETIF_F_HW_VLAN_RX; /* Receive VLAN hw acceleration */
+	ndev->features |= NETIF_F_HW_VLAN_FILTER; /* Receive VLAN filtering */
+	ndev->features |= NETIF_F_VLAN_CHALLENGED; /* cannot handle VLAN pkts */
+	ndev->features |= NETIF_F_GSO; /* Enable software GSO. */
+	ndev->features |= NETIF_F_MULTI_QUEUE; /* Has multiple TX/RX queues */
+	ndev->features |= NETIF_F_LRO; /* large receive offload */
+#endif
+
+	/* setup temac private info structure */
+	lp = netdev_priv(ndev);
+	lp->ndev = ndev;
+	lp->dev = &op->dev;
+	lp->options = XTE_OPTION_DEFAULTS;
+	spin_lock_init(&lp->rx_lock);
+	mutex_init(&lp->indirect_mutex);
+
+	/* map device registers */
+	lp->regs = of_iomap(op->node, 0);
+	if (!lp->regs) {
+		dev_err(&op->dev, "could not map temac regs.\n");
+		goto nodev;
+	}
+
+	/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
+	np = of_parse_phandle(op->node, "llink-connected", 0);
+	if (!np) {
+		dev_err(&op->dev, "could not find DMA node\n");
+		goto nodev;
+	}
+
+	dcrs = dcr_resource_start(np, 0);
+	if (dcrs == 0) {
+		dev_err(&op->dev, "could not get DMA register address\n");
+		goto nodev;;
+	}
+	lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
+	dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
+
+	lp->rx_irq = irq_of_parse_and_map(np, 0);
+	lp->tx_irq = irq_of_parse_and_map(np, 1);
+	if (!lp->rx_irq || !lp->tx_irq) {
+		dev_err(&op->dev, "could not determine irqs\n");
+		rc = -ENOMEM;
+		goto nodev;
+	}
+
+	of_node_put(np); /* Finished with the DMA node; drop the reference */
+
+	/* Retrieve the MAC address */
+	addr = of_get_property(op->node, "local-mac-address", &size);
+	if ((!addr) || (size != 6)) {
+		dev_err(&op->dev, "could not find MAC address\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+	temac_set_mac_address(ndev, (void *)addr);
+
+	rc = temac_mdio_setup(lp, op->node);
+	if (rc)
+		dev_warn(&op->dev, "error registering MDIO bus\n");
+
+	lp->phy_node = of_parse_phandle(op->node, "phy-handle", 0);
+	if (lp->phy_node)
+		dev_dbg(lp->dev, "using PHY node %s (%p)\n", np->full_name, np);
+
+	/* Add the device attributes */
+	rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group);
+	if (rc) {
+		dev_err(lp->dev, "Error creating sysfs files\n");
+		goto nodev;
+	}
+
+	rc = register_netdev(lp->ndev);
+	if (rc) {
+		dev_err(lp->dev, "register_netdev() error (%i)\n", rc);
+		goto err_register_ndev;
+	}
+
+	return 0;
+
+ err_register_ndev:
+	sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
+ nodev:
+	free_netdev(ndev);
+	ndev = NULL;
+	return rc;
+}
+
+static int __devexit temac_of_remove(struct of_device *op)
+{
+	struct net_device *ndev = dev_get_drvdata(&op->dev);
+	struct temac_local *lp = netdev_priv(ndev);
+
+	temac_mdio_teardown(lp);
+	unregister_netdev(ndev);
+	sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
+	if (lp->phy_node)
+		of_node_put(lp->phy_node);
+	lp->phy_node = NULL;
+	dev_set_drvdata(&op->dev, NULL);
+	free_netdev(ndev);
+	return 0;
+}
+
+static struct of_device_id temac_of_match[] __devinitdata = {
+	{ .compatible = "xlnx,xps-ll-temac-1.01.b", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, temac_of_match);
+
+static struct of_platform_driver temac_of_driver = {
+	.match_table = temac_of_match,
+	.probe = temac_of_probe,
+	.remove = __devexit_p(temac_of_remove),
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "xilinx_temac",
+	},
+};
+
+static int __init temac_init(void)
+{
+	return of_register_platform_driver(&temac_of_driver);
+}
+module_init(temac_init);
+
+static void __exit temac_exit(void)
+{
+	of_unregister_platform_driver(&temac_of_driver);
+}
+module_exit(temac_exit);
+
+MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver");
+MODULE_AUTHOR("Yoshio Kashiwagi");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/net/ll_temac_mdio.c linux-libre-2.6.31-gnu/drivers/net/ll_temac_mdio.c
--- linux-libre-2.6.30-gnu/drivers/net/ll_temac_mdio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/ll_temac_mdio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * MDIO bus driver for the Xilinx TEMAC device
+ *
+ * Copyright (c) 2009 Secret Lab Technologies, Ltd.
+ */
+
+#include <linux/io.h>
+#include <linux/netdevice.h>
+#include <linux/mutex.h>
+#include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_mdio.h>
+
+#include "ll_temac.h"
+
+/* ---------------------------------------------------------------------
+ * MDIO Bus functions
+ */
+static int temac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+	struct temac_local *lp = bus->priv;
+	u32 rc;
+
+	/* Write the PHY address to the MIIM Access Initiator register.
+	 * When the transfer completes, the PHY register value will appear
+	 * in the LSW0 register */
+	mutex_lock(&lp->indirect_mutex);
+	temac_iow(lp, XTE_LSW0_OFFSET, (phy_id << 5) | reg);
+	rc = temac_indirect_in32(lp, XTE_MIIMAI_OFFSET);
+	mutex_unlock(&lp->indirect_mutex);
+
+	dev_dbg(lp->dev, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n",
+		phy_id, reg, rc);
+
+	return rc;
+}
+
+static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+{
+	struct temac_local *lp = bus->priv;
+
+	dev_dbg(lp->dev, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
+		phy_id, reg, val);
+
+	/* First write the desired value into the write data register
+	 * and then write the address into the access initiator register
+	 */
+	mutex_lock(&lp->indirect_mutex);
+	temac_indirect_out32(lp, XTE_MGTDR_OFFSET, val);
+	temac_indirect_out32(lp, XTE_MIIMAI_OFFSET, (phy_id << 5) | reg);
+	mutex_unlock(&lp->indirect_mutex);
+
+	return 0;
+}
+
+int temac_mdio_setup(struct temac_local *lp, struct device_node *np)
+{
+	struct mii_bus *bus;
+	const u32 *bus_hz;
+	int clk_div;
+	int rc, size;
+	struct resource res;
+
+	/* Calculate a reasonable divisor for the clock rate */
+	clk_div = 0x3f; /* worst-case default setting */
+	bus_hz = of_get_property(np, "clock-frequency", &size);
+	if (bus_hz && size >= sizeof(*bus_hz)) {
+		clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1;
+		if (clk_div < 1)
+			clk_div = 1;
+		if (clk_div > 0x3f)
+			clk_div = 0x3f;
+	}
+
+	/* Enable the MDIO bus by asserting the enable bit and writing
+	 * in the clock config */
+	mutex_lock(&lp->indirect_mutex);
+	temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div);
+	mutex_unlock(&lp->indirect_mutex);
+
+	bus = mdiobus_alloc();
+	if (!bus)
+		return -ENOMEM;
+
+	of_address_to_resource(np, 0, &res);
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
+		 (unsigned long long)res.start);
+	bus->priv = lp;
+	bus->name = "Xilinx TEMAC MDIO";
+	bus->read = temac_mdio_read;
+	bus->write = temac_mdio_write;
+	bus->parent = lp->dev;
+	bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
+
+	lp->mii_bus = bus;
+
+	rc = of_mdiobus_register(bus, np);
+	if (rc)
+		goto err_register;
+
+	mutex_lock(&lp->indirect_mutex);
+	dev_dbg(lp->dev, "MDIO bus registered;  MC:%x\n",
+		temac_indirect_in32(lp, XTE_MC_OFFSET));
+	mutex_unlock(&lp->indirect_mutex);
+	return 0;
+
+ err_register:
+	mdiobus_free(bus);
+	return rc;
+}
+
+void temac_mdio_teardown(struct temac_local *lp)
+{
+	mdiobus_unregister(lp->mii_bus);
+	kfree(lp->mii_bus->irq);
+	mdiobus_free(lp->mii_bus);
+	lp->mii_bus = NULL;
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/loopback.c linux-libre-2.6.31-gnu/drivers/net/loopback.c
--- linux-libre-2.6.30-gnu/drivers/net/loopback.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/loopback.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,7 @@
 struct pcpu_lstats {
 	unsigned long packets;
 	unsigned long bytes;
+	unsigned long drops;
 };
 
 /*
@@ -71,18 +72,22 @@
 static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct pcpu_lstats *pcpu_lstats, *lb_stats;
+	int len;
 
 	skb_orphan(skb);
 
-	skb->protocol = eth_type_trans(skb,dev);
+	skb->protocol = eth_type_trans(skb, dev);
 
 	/* it's OK to use per_cpu_ptr() because BHs are off */
 	pcpu_lstats = dev->ml_priv;
 	lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
-	lb_stats->bytes += skb->len;
-	lb_stats->packets++;
 
-	netif_rx(skb);
+	len = skb->len;
+	if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
+		lb_stats->bytes += len;
+		lb_stats->packets++;
+	} else
+		lb_stats->drops++;
 
 	return 0;
 }
@@ -93,6 +98,7 @@
 	struct net_device_stats *stats = &dev->stats;
 	unsigned long bytes = 0;
 	unsigned long packets = 0;
+	unsigned long drops = 0;
 	int i;
 
 	pcpu_lstats = dev->ml_priv;
@@ -102,11 +108,14 @@
 		lb_stats = per_cpu_ptr(pcpu_lstats, i);
 		bytes   += lb_stats->bytes;
 		packets += lb_stats->packets;
+		drops   += lb_stats->drops;
 	}
 	stats->rx_packets = packets;
 	stats->tx_packets = packets;
-	stats->rx_bytes = bytes;
-	stats->tx_bytes = bytes;
+	stats->rx_dropped = drops;
+	stats->rx_errors  = drops;
+	stats->rx_bytes   = bytes;
+	stats->tx_bytes   = bytes;
 	return stats;
 }
 
@@ -161,6 +170,7 @@
 	dev->tx_queue_len	= 0;
 	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
 	dev->flags		= IFF_LOOPBACK;
+	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
 	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST
 		| NETIF_F_TSO
 		| NETIF_F_NO_CSUM
diff -druN linux-libre-2.6.30-gnu/drivers/net/mac8390.c linux-libre-2.6.31-gnu/drivers/net/mac8390.c
--- linux-libre-2.6.30-gnu/drivers/net/mac8390.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mac8390.c	2009-09-09 18:13:59.000000000 -0400
@@ -620,19 +620,12 @@
 
 	/* Good, done, now spit out some messages */
 	printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
-		   dev->name, ndev->board->name, ndev->board->slot, cardname[type]);
-	printk(KERN_INFO "MAC ");
-	{
-		int i;
-		for (i = 0; i < 6; i++) {
-			printk("%2.2x", dev->dev_addr[i]);
-			if (i < 5)
-				printk(":");
-		}
-	}
-	printk(" IRQ %d, %d KB shared memory at %#lx,  %d-bit access.\n",
-		   dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4,
-		   dev->mem_start, access_bitmode?32:16);
+	       dev->name, ndev->board->name, ndev->board->slot, cardname[type]);
+	printk(KERN_INFO
+	       "MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n",
+	       dev->dev_addr, dev->irq,
+	       (unsigned int)(dev->mem_end - dev->mem_start) >> 10,
+	       dev->mem_start, access_bitmode ? 32 : 16);
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/mac89x0.c linux-libre-2.6.31-gnu/drivers/net/mac89x0.c
--- linux-libre-2.6.30-gnu/drivers/net/mac89x0.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mac89x0.c	2009-09-09 18:13:59.000000000 -0400
@@ -73,8 +73,6 @@
    or override something. */
 #include <linux/module.h>
 
-#define PRINTK(x) printk x
-
 /*
   Sources:
 
@@ -402,7 +400,7 @@
 		/* Gasp!  It hasn't.  But that shouldn't happen since
 		   we're waiting for TxOk, so return 1 and requeue this packet. */
 		local_irq_restore(flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Write the contents of the packet */
diff -druN linux-libre-2.6.30-gnu/drivers/net/macb.c linux-libre-2.6.31-gnu/drivers/net/macb.c
--- linux-libre-2.6.30-gnu/drivers/net/macb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/macb.c	2009-09-09 18:13:59.000000000 -0400
@@ -599,12 +599,28 @@
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void macb_poll_controller(struct net_device *dev)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	macb_interrupt(dev->irq, dev);
+	local_irq_restore(flags);
+}
+#endif
+
 static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct macb *bp = netdev_priv(dev);
 	dma_addr_t mapping;
 	unsigned int len, entry;
 	u32 ctrl;
+	unsigned long flags;
 
 #ifdef DEBUG
 	int i;
@@ -620,17 +636,17 @@
 #endif
 
 	len = skb->len;
-	spin_lock_irq(&bp->lock);
+	spin_lock_irqsave(&bp->lock, flags);
 
 	/* This is a hard error, log it. */
 	if (TX_BUFFS_AVAIL(bp) < 1) {
 		netif_stop_queue(dev);
-		spin_unlock_irq(&bp->lock);
+		spin_unlock_irqrestore(&bp->lock, flags);
 		dev_err(&bp->pdev->dev,
 			"BUG! Tx Ring full when queue awake!\n");
 		dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n",
 			bp->tx_head, bp->tx_tail);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	entry = bp->tx_head;
@@ -659,7 +675,7 @@
 	if (TX_BUFFS_AVAIL(bp) < 1)
 		netif_stop_queue(dev);
 
-	spin_unlock_irq(&bp->lock);
+	spin_unlock_irqrestore(&bp->lock, flags);
 
 	dev->trans_start = jiffies;
 
@@ -1094,6 +1110,9 @@
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= macb_poll_controller,
+#endif
 };
 
 static int __init macb_probe(struct platform_device *pdev)
diff -druN linux-libre-2.6.30-gnu/drivers/net/mace.c linux-libre-2.6.31-gnu/drivers/net/mace.c
--- linux-libre-2.6.30-gnu/drivers/net/mace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mace.c	2009-09-09 18:13:59.000000000 -0400
@@ -94,6 +94,16 @@
  */
 static unsigned char *dummy_buf;
 
+static const struct net_device_ops mace_netdev_ops = {
+	.ndo_open		= mace_open,
+	.ndo_stop		= mace_close,
+	.ndo_start_xmit		= mace_xmit_start,
+	.ndo_set_multicast_list	= mace_set_multicast,
+	.ndo_set_mac_address	= mace_set_address,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
 static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
 {
 	struct device_node *mace = macio_get_of_node(mdev);
@@ -207,11 +217,7 @@
 		}
 	}
 
-	dev->open = mace_open;
-	dev->stop = mace_close;
-	dev->hard_start_xmit = mace_xmit_start;
-	dev->set_multicast_list = mace_set_multicast;
-	dev->set_mac_address = mace_set_address;
+	dev->netdev_ops = &mace_netdev_ops;
 
 	/*
 	 * Most of what is below could be moved to mace_open()
@@ -541,7 +547,7 @@
 	netif_stop_queue(dev);
 	mp->tx_fullup = 1;
 	spin_unlock_irqrestore(&mp->lock, flags);
-	return 1;		/* can't take it at the moment */
+	return NETDEV_TX_BUSY;		/* can't take it at the moment */
     }
     spin_unlock_irqrestore(&mp->lock, flags);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/macmace.c linux-libre-2.6.31-gnu/drivers/net/macmace.c
--- linux-libre-2.6.30-gnu/drivers/net/macmace.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/macmace.c	2009-09-09 18:13:59.000000000 -0400
@@ -180,6 +180,17 @@
 	psc_write_word(PSC_ENETWR_CMD + PSC_SET1, 0x1100);
 }
 
+static const struct net_device_ops mace_netdev_ops = {
+	.ndo_open		= mace_open,
+	.ndo_stop		= mace_close,
+	.ndo_start_xmit		= mace_xmit_start,
+	.ndo_tx_timeout		= mace_tx_timeout,
+	.ndo_set_multicast_list	= mace_set_multicast,
+	.ndo_set_mac_address	= mace_set_address,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
 /*
  * Not really much of a probe. The hardware table tells us if this
  * model of Macintrash has a MACE (AV macintoshes)
@@ -240,13 +251,8 @@
 		return -ENODEV;
 	}
 
-	dev->open		= mace_open;
-	dev->stop		= mace_close;
-	dev->hard_start_xmit	= mace_xmit_start;
-	dev->tx_timeout		= mace_tx_timeout;
+	dev->netdev_ops		= &mace_netdev_ops;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-	dev->set_multicast_list	= mace_set_multicast;
-	dev->set_mac_address	= mace_set_address;
 
 	printk(KERN_INFO "%s: 68K MACE, hardware address %pM\n",
 	       dev->name, dev->dev_addr);
diff -druN linux-libre-2.6.30-gnu/drivers/net/macsonic.c linux-libre-2.6.31-gnu/drivers/net/macsonic.c
--- linux-libre-2.6.30-gnu/drivers/net/macsonic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/macsonic.c	2009-09-09 18:13:59.000000000 -0400
@@ -179,7 +179,7 @@
 	.ndo_set_mac_address	= eth_mac_addr,
 };
 
-static int __init macsonic_init(struct net_device *dev)
+static int __devinit macsonic_init(struct net_device *dev)
 {
 	struct sonic_local* lp = netdev_priv(dev);
 
@@ -223,7 +223,7 @@
 	return 0;
 }
 
-static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
 {
 	struct sonic_local *lp = netdev_priv(dev);
 	const int prom_addr = ONBOARD_SONIC_PROM_BASE;
@@ -288,7 +288,7 @@
 	} else return 0;
 }
 
-static int __init mac_onboard_sonic_probe(struct net_device *dev)
+static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
 {
 	/* Bwahahaha */
 	static int once_is_more_than_enough;
@@ -409,7 +409,7 @@
 	return macsonic_init(dev);
 }
 
-static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev,
+static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
 						unsigned long prom_addr,
 						int id)
 {
@@ -424,7 +424,7 @@
 	return 0;
 }
 
-static int __init macsonic_ident(struct nubus_dev *ndev)
+static int __devinit macsonic_ident(struct nubus_dev *ndev)
 {
 	if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
 	    ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
@@ -449,7 +449,7 @@
 	return -1;
 }
 
-static int __init mac_nubus_sonic_probe(struct net_device *dev)
+static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
 {
 	static int slots;
 	struct nubus_dev* ndev = NULL;
@@ -562,7 +562,7 @@
 	return macsonic_init(dev);
 }
 
-static int __init mac_sonic_probe(struct platform_device *pdev)
+static int __devinit mac_sonic_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
 	struct sonic_local *lp;
@@ -575,6 +575,7 @@
 	lp = netdev_priv(dev);
 	lp->device = &pdev->dev;
 	SET_NETDEV_DEV(dev, &pdev->dev);
+	platform_set_drvdata(pdev, dev);
 
 	/* This will catch fatal stuff like -ENOMEM as well as success */
 	err = mac_onboard_sonic_probe(dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/macvlan.c linux-libre-2.6.31-gnu/drivers/net/macvlan.c
--- linux-libre-2.6.30-gnu/drivers/net/macvlan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/macvlan.c	2009-09-09 18:13:59.000000000 -0400
@@ -232,7 +232,7 @@
 	if (macvlan_addr_busy(vlan->port, dev->dev_addr))
 		goto out;
 
-	err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN);
+	err = dev_unicast_add(lowerdev, dev->dev_addr);
 	if (err < 0)
 		goto out;
 	if (dev->flags & IFF_ALLMULTI) {
@@ -244,7 +244,7 @@
 	return 0;
 
 del_unicast:
-	dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN);
+	dev_unicast_delete(lowerdev, dev->dev_addr);
 out:
 	return err;
 }
@@ -258,7 +258,7 @@
 	if (dev->flags & IFF_ALLMULTI)
 		dev_set_allmulti(lowerdev, -1);
 
-	dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN);
+	dev_unicast_delete(lowerdev, dev->dev_addr);
 
 	macvlan_hash_del(vlan);
 	return 0;
@@ -282,10 +282,11 @@
 		if (macvlan_addr_busy(vlan->port, addr->sa_data))
 			return -EBUSY;
 
-		if ((err = dev_unicast_add(lowerdev, addr->sa_data, ETH_ALEN)))
+		err = dev_unicast_add(lowerdev, addr->sa_data);
+		if (err)
 			return err;
 
-		dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN);
+		dev_unicast_delete(lowerdev, dev->dev_addr);
 
 		macvlan_hash_change_addr(vlan, addr->sa_data);
 	}
@@ -358,6 +359,7 @@
 				  (lowerdev->state & MACVLAN_STATE_MASK);
 	dev->features 		= lowerdev->features & MACVLAN_FEATURES;
 	dev->iflink		= lowerdev->ifindex;
+	dev->hard_header_len	= lowerdev->hard_header_len;
 
 	macvlan_set_lockdep_class(dev);
 
@@ -374,36 +376,20 @@
 static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev)
 {
 	const struct macvlan_dev *vlan = netdev_priv(dev);
-	struct net_device *lowerdev = vlan->lowerdev;
-
-	if (lowerdev->ethtool_ops == NULL ||
-	    lowerdev->ethtool_ops->get_rx_csum == NULL)
-		return 0;
-	return lowerdev->ethtool_ops->get_rx_csum(lowerdev);
+	return dev_ethtool_get_rx_csum(vlan->lowerdev);
 }
 
 static int macvlan_ethtool_get_settings(struct net_device *dev,
 					struct ethtool_cmd *cmd)
 {
 	const struct macvlan_dev *vlan = netdev_priv(dev);
-	struct net_device *lowerdev = vlan->lowerdev;
-
-	if (!lowerdev->ethtool_ops ||
-	    !lowerdev->ethtool_ops->get_settings)
-		return -EOPNOTSUPP;
-
-	return lowerdev->ethtool_ops->get_settings(lowerdev, cmd);
+	return dev_ethtool_get_settings(vlan->lowerdev, cmd);
 }
 
 static u32 macvlan_ethtool_get_flags(struct net_device *dev)
 {
 	const struct macvlan_dev *vlan = netdev_priv(dev);
-	struct net_device *lowerdev = vlan->lowerdev;
-
-	if (!lowerdev->ethtool_ops ||
-	    !lowerdev->ethtool_ops->get_flags)
-		return 0;
-	return lowerdev->ethtool_ops->get_flags(lowerdev);
+	return dev_ethtool_get_flags(vlan->lowerdev);
 }
 
 static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -430,6 +416,7 @@
 {
 	ether_setup(dev);
 
+	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
 	dev->netdev_ops		= &macvlan_netdev_ops;
 	dev->destructor		= free_netdev;
 	dev->header_ops		= &macvlan_hard_header_ops,
diff -druN linux-libre-2.6.30-gnu/drivers/net/Makefile linux-libre-2.6.31-gnu/drivers/net/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -2,6 +2,8 @@
 # Makefile for the Linux network (ethercard) device drivers.
 #
 
+obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
+
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_E1000E) += e1000e/
 obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
@@ -73,6 +75,7 @@
 obj-$(CONFIG_FEALNX) += fealnx.o
 obj-$(CONFIG_TIGON3) += tg3.o
 obj-$(CONFIG_BNX2) += bnx2.o
+obj-$(CONFIG_CNIC) += cnic.o
 obj-$(CONFIG_BNX2X) += bnx2x.o
 bnx2x-objs := bnx2x_main.o bnx2x_link.o
 spidernet-y += spider_net.o spider_net_ethtool.o
@@ -84,6 +87,8 @@
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
 obj-$(CONFIG_SKFP) += skfp/
+obj-$(CONFIG_KS8842)	+= ks8842.o
+obj-$(CONFIG_KS8851)	+= ks8851.o
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
@@ -95,6 +100,7 @@
 #
 
 obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_MDIO) += mdio.o
 obj-$(CONFIG_PHYLIB) += phy/
 
 obj-$(CONFIG_SUNDANCE) += sundance.o
@@ -134,6 +140,8 @@
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
+obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
 obj-$(CONFIG_QLA3XXX) += qla3xxx.o
 obj-$(CONFIG_QLGE) += qlge/
 
@@ -238,6 +246,7 @@
 
 obj-$(CONFIG_DNET) += dnet.o
 obj-$(CONFIG_MACB) += macb.o
+obj-$(CONFIG_S6GMAC) += s6gmac.o
 
 obj-$(CONFIG_ARM) += arm/
 obj-$(CONFIG_DEV_APPLETALK) += appletalk/
diff -druN linux-libre-2.6.30-gnu/drivers/net/mdio.c linux-libre-2.6.31-gnu/drivers/net/mdio.c
--- linux-libre-2.6.30-gnu/drivers/net/mdio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/mdio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,435 @@
+/*
+ * mdio.c: Generic support for MDIO-compatible transceivers
+ * Copyright 2006-2009 Solarflare Communications Inc.
+ *
+ * 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, incorporated herein by reference.
+ */
+
+#include <linux/kernel.h>
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/ethtool.h>
+#include <linux/mdio.h>
+#include <linux/module.h>
+
+MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers");
+MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc.");
+MODULE_LICENSE("GPL");
+
+/**
+ * mdio45_probe - probe for an MDIO (clause 45) device
+ * @mdio: MDIO interface
+ * @prtad: Expected PHY address
+ *
+ * This sets @prtad and @mmds in the MDIO interface if successful.
+ * Returns 0 on success, negative on error.
+ */
+int mdio45_probe(struct mdio_if_info *mdio, int prtad)
+{
+	int mmd, stat2, devs1, devs2;
+
+	/* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY
+	 * XS or DTE XS; give up if none is present. */
+	for (mmd = 1; mmd <= 5; mmd++) {
+		/* Is this MMD present? */
+		stat2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_STAT2);
+		if (stat2 < 0 ||
+		    (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL)
+			continue;
+
+		/* It should tell us about all the other MMDs */
+		devs1 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS1);
+		devs2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS2);
+		if (devs1 < 0 || devs2 < 0)
+			continue;
+
+		mdio->prtad = prtad;
+		mdio->mmds = devs1 | (devs2 << 16);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(mdio45_probe);
+
+/**
+ * mdio_set_flag - set or clear flag in an MDIO register
+ * @mdio: MDIO interface
+ * @prtad: PHY address
+ * @devad: MMD address
+ * @addr: Register address
+ * @mask: Mask for flag (single bit set)
+ * @sense: New value of flag
+ *
+ * This debounces changes: it does not write the register if the flag
+ * already has the proper value.  Returns 0 on success, negative on error.
+ */
+int mdio_set_flag(const struct mdio_if_info *mdio,
+		  int prtad, int devad, u16 addr, int mask,
+		  bool sense)
+{
+	int old_val = mdio->mdio_read(mdio->dev, prtad, devad, addr);
+	int new_val;
+
+	if (old_val < 0)
+		return old_val;
+	if (sense)
+		new_val = old_val | mask;
+	else
+		new_val = old_val & ~mask;
+	if (old_val == new_val)
+		return 0;
+	return mdio->mdio_write(mdio->dev, prtad, devad, addr, new_val);
+}
+EXPORT_SYMBOL(mdio_set_flag);
+
+/**
+ * mdio_link_ok - is link status up/OK
+ * @mdio: MDIO interface
+ * @mmd_mask: Mask for MMDs to check
+ *
+ * Returns 1 if the PHY reports link status up/OK, 0 otherwise.
+ * @mmd_mask is normally @mdio->mmds, but if loopback is enabled
+ * the MMDs being bypassed should be excluded from the mask.
+ */
+int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmd_mask)
+{
+	int devad, reg;
+
+	if (!mmd_mask) {
+		/* Use absence of XGMII faults in lieu of link state */
+		reg = mdio->mdio_read(mdio->dev, mdio->prtad,
+				      MDIO_MMD_PHYXS, MDIO_STAT2);
+		return reg >= 0 && !(reg & MDIO_STAT2_RXFAULT);
+	}
+
+	for (devad = 0; mmd_mask; devad++) {
+		if (mmd_mask & (1 << devad)) {
+			mmd_mask &= ~(1 << devad);
+
+			/* Read twice because link state is latched and a
+			 * read moves the current state into the register */
+			mdio->mdio_read(mdio->dev, mdio->prtad,
+					devad, MDIO_STAT1);
+			reg = mdio->mdio_read(mdio->dev, mdio->prtad,
+					      devad, MDIO_STAT1);
+			if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
+				return false;
+		}
+	}
+
+	return true;
+}
+EXPORT_SYMBOL(mdio45_links_ok);
+
+/**
+ * mdio45_nway_restart - restart auto-negotiation for this interface
+ * @mdio: MDIO interface
+ *
+ * Returns 0 on success, negative on error.
+ */
+int mdio45_nway_restart(const struct mdio_if_info *mdio)
+{
+	if (!(mdio->mmds & MDIO_DEVS_AN))
+		return -EOPNOTSUPP;
+
+	mdio_set_flag(mdio, mdio->prtad, MDIO_MMD_AN, MDIO_CTRL1,
+		      MDIO_AN_CTRL1_RESTART, true);
+	return 0;
+}
+EXPORT_SYMBOL(mdio45_nway_restart);
+
+static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr)
+{
+	u32 result = 0;
+	int reg;
+
+	reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, addr);
+	if (reg & ADVERTISE_10HALF)
+		result |= ADVERTISED_10baseT_Half;
+	if (reg & ADVERTISE_10FULL)
+		result |= ADVERTISED_10baseT_Full;
+	if (reg & ADVERTISE_100HALF)
+		result |= ADVERTISED_100baseT_Half;
+	if (reg & ADVERTISE_100FULL)
+		result |= ADVERTISED_100baseT_Full;
+	return result;
+}
+
+/**
+ * mdio45_ethtool_gset_npage - get settings for ETHTOOL_GSET
+ * @mdio: MDIO interface
+ * @ecmd: Ethtool request structure
+ * @npage_adv: Modes currently advertised on next pages
+ * @npage_lpa: Modes advertised by link partner on next pages
+ *
+ * Since the CSRs for auto-negotiation using next pages are not fully
+ * standardised, this function does not attempt to decode them.  The
+ * caller must pass them in.
+ */
+void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
+			       struct ethtool_cmd *ecmd,
+			       u32 npage_adv, u32 npage_lpa)
+{
+	int reg;
+
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->phy_address = mdio->prtad;
+	ecmd->mdio_support =
+		mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22);
+
+	reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+			      MDIO_CTRL2);
+	switch (reg & MDIO_PMA_CTRL2_TYPE) {
+	case MDIO_PMA_CTRL2_10GBT:
+	case MDIO_PMA_CTRL2_1000BT:
+	case MDIO_PMA_CTRL2_100BTX:
+	case MDIO_PMA_CTRL2_10BT:
+		ecmd->port = PORT_TP;
+		ecmd->supported = SUPPORTED_TP;
+		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+				      MDIO_SPEED);
+		if (reg & MDIO_SPEED_10G)
+			ecmd->supported |= SUPPORTED_10000baseT_Full;
+		if (reg & MDIO_PMA_SPEED_1000)
+			ecmd->supported |= (SUPPORTED_1000baseT_Full |
+					    SUPPORTED_1000baseT_Half);
+		if (reg & MDIO_PMA_SPEED_100)
+			ecmd->supported |= (SUPPORTED_100baseT_Full |
+					    SUPPORTED_100baseT_Half);
+		if (reg & MDIO_PMA_SPEED_10)
+			ecmd->supported |= (SUPPORTED_10baseT_Full |
+					    SUPPORTED_10baseT_Half);
+		ecmd->advertising = ADVERTISED_TP;
+		break;
+
+	case MDIO_PMA_CTRL2_10GBCX4:
+		ecmd->port = PORT_OTHER;
+		ecmd->supported = 0;
+		ecmd->advertising = 0;
+		break;
+
+	case MDIO_PMA_CTRL2_10GBKX4:
+	case MDIO_PMA_CTRL2_10GBKR:
+	case MDIO_PMA_CTRL2_1000BKX:
+		ecmd->port = PORT_OTHER;
+		ecmd->supported = SUPPORTED_Backplane;
+		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+				      MDIO_PMA_EXTABLE);
+		if (reg & MDIO_PMA_EXTABLE_10GBKX4)
+			ecmd->supported |= SUPPORTED_10000baseKX4_Full;
+		if (reg & MDIO_PMA_EXTABLE_10GBKR)
+			ecmd->supported |= SUPPORTED_10000baseKR_Full;
+		if (reg & MDIO_PMA_EXTABLE_1000BKX)
+			ecmd->supported |= SUPPORTED_1000baseKX_Full;
+		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+				      MDIO_PMA_10GBR_FECABLE);
+		if (reg & MDIO_PMA_10GBR_FECABLE_ABLE)
+			ecmd->supported |= SUPPORTED_10000baseR_FEC;
+		ecmd->advertising = ADVERTISED_Backplane;
+		break;
+
+	/* All the other defined modes are flavours of optical */
+	default:
+		ecmd->port = PORT_FIBRE;
+		ecmd->supported = SUPPORTED_FIBRE;
+		ecmd->advertising = ADVERTISED_FIBRE;
+		break;
+	}
+
+	if (mdio->mmds & MDIO_DEVS_AN) {
+		ecmd->supported |= SUPPORTED_Autoneg;
+		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
+				      MDIO_CTRL1);
+		if (reg & MDIO_AN_CTRL1_ENABLE) {
+			ecmd->autoneg = AUTONEG_ENABLE;
+			ecmd->advertising |=
+				ADVERTISED_Autoneg |
+				mdio45_get_an(mdio, MDIO_AN_ADVERTISE) |
+				npage_adv;
+		} else {
+			ecmd->autoneg = AUTONEG_DISABLE;
+		}
+	} else {
+		ecmd->autoneg = AUTONEG_DISABLE;
+	}
+
+	if (ecmd->autoneg) {
+		u32 modes = 0;
+		int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad,
+					      MDIO_MMD_AN, MDIO_STAT1);
+
+		/* If AN is complete and successful, report best common
+		 * mode, otherwise report best advertised mode. */
+		if (an_stat & MDIO_AN_STAT1_COMPLETE) {
+			ecmd->lp_advertising =
+				mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa;
+			if (an_stat & MDIO_AN_STAT1_LPABLE)
+				ecmd->lp_advertising |= ADVERTISED_Autoneg;
+			modes = ecmd->advertising & ecmd->lp_advertising;
+		}
+		if ((modes & ~ADVERTISED_Autoneg) == 0)
+			modes = ecmd->advertising;
+
+		if (modes & (ADVERTISED_10000baseT_Full |
+			     ADVERTISED_10000baseKX4_Full |
+			     ADVERTISED_10000baseKR_Full)) {
+			ecmd->speed = SPEED_10000;
+			ecmd->duplex = DUPLEX_FULL;
+		} else if (modes & (ADVERTISED_1000baseT_Full |
+				    ADVERTISED_1000baseT_Half |
+				    ADVERTISED_1000baseKX_Full)) {
+			ecmd->speed = SPEED_1000;
+			ecmd->duplex = !(modes & ADVERTISED_1000baseT_Half);
+		} else if (modes & (ADVERTISED_100baseT_Full |
+				    ADVERTISED_100baseT_Half)) {
+			ecmd->speed = SPEED_100;
+			ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
+		} else {
+			ecmd->speed = SPEED_10;
+			ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
+		}
+	} else {
+		/* Report forced settings */
+		reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+				      MDIO_CTRL1);
+		ecmd->speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) *
+			       ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10));
+		ecmd->duplex = (reg & MDIO_CTRL1_FULLDPLX ||
+				ecmd->speed == SPEED_10000);
+	}
+
+	/* 10GBASE-T MDI/MDI-X */
+	if (ecmd->port == PORT_TP && ecmd->speed == SPEED_10000) {
+		switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD,
+					MDIO_PMA_10GBT_SWAPPOL)) {
+		case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
+			ecmd->eth_tp_mdix = ETH_TP_MDI;
+			break;
+		case 0:
+			ecmd->eth_tp_mdix = ETH_TP_MDI_X;
+			break;
+		default:
+			/* It's complicated... */
+			ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL(mdio45_ethtool_gset_npage);
+
+/**
+ * mdio45_ethtool_spauseparam_an - set auto-negotiated pause parameters
+ * @mdio: MDIO interface
+ * @ecmd: Ethtool request structure
+ *
+ * This function assumes that the PHY has an auto-negotiation MMD.  It
+ * will enable and disable advertising of flow control as appropriate.
+ */
+void mdio45_ethtool_spauseparam_an(const struct mdio_if_info *mdio,
+				   const struct ethtool_pauseparam *ecmd)
+{
+	int adv, old_adv;
+
+	WARN_ON(!(mdio->mmds & MDIO_DEVS_AN));
+
+	old_adv = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN,
+				  MDIO_AN_ADVERTISE);
+	adv = old_adv & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+	if (ecmd->autoneg)
+		adv |= mii_advertise_flowctrl(
+			(ecmd->rx_pause ? FLOW_CTRL_RX : 0) |
+			(ecmd->tx_pause ? FLOW_CTRL_TX : 0));
+	if (adv != old_adv) {
+		mdio->mdio_write(mdio->dev, mdio->prtad, MDIO_MMD_AN,
+				 MDIO_AN_ADVERTISE, adv);
+		mdio45_nway_restart(mdio);
+	}
+}
+EXPORT_SYMBOL(mdio45_ethtool_spauseparam_an);
+
+/**
+ * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs
+ * @mdio: MDIO interface
+ * @mii_data: MII ioctl data structure
+ * @cmd: MII ioctl command
+ *
+ * Returns 0 on success, negative on error.
+ */
+int mdio_mii_ioctl(const struct mdio_if_info *mdio,
+		   struct mii_ioctl_data *mii_data, int cmd)
+{
+	int prtad, devad;
+	u16 addr = mii_data->reg_num;
+
+	/* Validate/convert cmd to one of SIOC{G,S}MIIREG */
+	switch (cmd) {
+	case SIOCGMIIPHY:
+		if (mdio->prtad == MDIO_PRTAD_NONE)
+			return -EOPNOTSUPP;
+		mii_data->phy_id = mdio->prtad;
+		cmd = SIOCGMIIREG;
+		break;
+	case SIOCGMIIREG:
+		break;
+	case SIOCSMIIREG:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	/* Validate/convert phy_id */
+	if ((mdio->mode_support & MDIO_SUPPORTS_C45) &&
+	    mdio_phy_id_is_c45(mii_data->phy_id)) {
+		prtad = mdio_phy_id_prtad(mii_data->phy_id);
+		devad = mdio_phy_id_devad(mii_data->phy_id);
+	} else if ((mdio->mode_support & MDIO_SUPPORTS_C22) &&
+		   mii_data->phy_id < 0x20) {
+		prtad = mii_data->phy_id;
+		devad = MDIO_DEVAD_NONE;
+		addr &= 0x1f;
+	} else if ((mdio->mode_support & MDIO_EMULATE_C22) &&
+		   mdio->prtad != MDIO_PRTAD_NONE &&
+		   mii_data->phy_id == mdio->prtad) {
+		/* Remap commonly-used MII registers. */
+		prtad = mdio->prtad;
+		switch (addr) {
+		case MII_BMCR:
+		case MII_BMSR:
+		case MII_PHYSID1:
+		case MII_PHYSID2:
+			devad = __ffs(mdio->mmds);
+			break;
+		case MII_ADVERTISE:
+		case MII_LPA:
+			if (!(mdio->mmds & MDIO_DEVS_AN))
+				return -EINVAL;
+			devad = MDIO_MMD_AN;
+			if (addr == MII_ADVERTISE)
+				addr = MDIO_AN_ADVERTISE;
+			else
+				addr = MDIO_AN_LPA;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	if (cmd == SIOCGMIIREG) {
+		int rc = mdio->mdio_read(mdio->dev, prtad, devad, addr);
+		if (rc < 0)
+			return rc;
+		mii_data->val_out = rc;
+		return 0;
+	} else {
+		return mdio->mdio_write(mdio->dev, prtad, devad, addr,
+					mii_data->val_in);
+	}
+}
+EXPORT_SYMBOL(mdio_mii_ioctl);
diff -druN linux-libre-2.6.30-gnu/drivers/net/meth.c linux-libre-2.6.31-gnu/drivers/net/meth.c
--- linux-libre-2.6.30-gnu/drivers/net/meth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/meth.c	2009-09-09 18:13:59.000000000 -0400
@@ -770,9 +770,17 @@
 	}
 }
 
-/*
- * Return statistics to the caller
- */
+static const struct net_device_ops meth_netdev_ops = {
+	.ndo_open		= meth_open,
+	.ndo_stop		= meth_release,
+	.ndo_start_xmit		= meth_tx,
+	.ndo_do_ioctl		= meth_ioctl,
+	.ndo_tx_timeout		= meth_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
 /*
  * The init function.
  */
@@ -786,16 +794,10 @@
 	if (!dev)
 		return -ENOMEM;
 
-	dev->open            = meth_open;
-	dev->stop            = meth_release;
-	dev->hard_start_xmit = meth_tx;
-	dev->do_ioctl        = meth_ioctl;
-#ifdef HAVE_TX_TIMEOUT
-	dev->tx_timeout      = meth_tx_timeout;
-	dev->watchdog_timeo  = timeout;
-#endif
-	dev->irq	     = MACE_ETHERNET_IRQ;
-	dev->base_addr	     = (unsigned long)&mace->eth;
+	dev->netdev_ops		= &meth_netdev_ops;
+	dev->watchdog_timeo	= timeout;
+	dev->irq		= MACE_ETHERNET_IRQ;
+	dev->base_addr		= (unsigned long)&mace->eth;
 	memcpy(dev->dev_addr, o2meth_eaddr, 6);
 
 	priv = netdev_priv(dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/mii.c linux-libre-2.6.31-gnu/drivers/net/mii.c
--- linux-libre-2.6.30-gnu/drivers/net/mii.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mii.c	2009-09-09 18:13:59.000000000 -0400
@@ -31,7 +31,27 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
-#include <linux/mii.h>
+#include <linux/mdio.h>
+
+static u32 mii_get_an(struct mii_if_info *mii, u16 addr)
+{
+	u32 result = 0;
+	int advert;
+
+	advert = mii->mdio_read(mii->dev, mii->phy_id, addr);
+	if (advert & LPA_LPACK)
+		result |= ADVERTISED_Autoneg;
+	if (advert & ADVERTISE_10HALF)
+		result |= ADVERTISED_10baseT_Half;
+	if (advert & ADVERTISE_10FULL)
+		result |= ADVERTISED_10baseT_Full;
+	if (advert & ADVERTISE_100HALF)
+		result |= ADVERTISED_100baseT_Half;
+	if (advert & ADVERTISE_100FULL)
+		result |= ADVERTISED_100baseT_Full;
+
+	return result;
+}
 
 /**
  * mii_ethtool_gset - get settings that are specified in @ecmd
@@ -43,8 +63,8 @@
 int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
 {
 	struct net_device *dev = mii->dev;
-	u32 advert, bmcr, lpa, nego;
-	u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
+	u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0;
+	u32 nego;
 
 	ecmd->supported =
 	    (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
@@ -62,50 +82,51 @@
 
 	/* this isn't fully supported at higher layers */
 	ecmd->phy_address = mii->phy_id;
+	ecmd->mdio_support = MDIO_SUPPORTS_C22;
 
 	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
-	advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
-	if (mii->supports_gmii)
-		advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
-
-	if (advert & ADVERTISE_10HALF)
-		ecmd->advertising |= ADVERTISED_10baseT_Half;
-	if (advert & ADVERTISE_10FULL)
-		ecmd->advertising |= ADVERTISED_10baseT_Full;
-	if (advert & ADVERTISE_100HALF)
-		ecmd->advertising |= ADVERTISED_100baseT_Half;
-	if (advert & ADVERTISE_100FULL)
-		ecmd->advertising |= ADVERTISED_100baseT_Full;
-	if (advert2 & ADVERTISE_1000HALF)
-		ecmd->advertising |= ADVERTISED_1000baseT_Half;
-	if (advert2 & ADVERTISE_1000FULL)
-		ecmd->advertising |= ADVERTISED_1000baseT_Full;
 
 	bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
-	lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
+	bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR);
 	if (mii->supports_gmii) {
-		bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
-		lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
+ 		ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+		stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
 	}
 	if (bmcr & BMCR_ANENABLE) {
 		ecmd->advertising |= ADVERTISED_Autoneg;
 		ecmd->autoneg = AUTONEG_ENABLE;
 
-		nego = mii_nway_result(advert & lpa);
-		if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) &
-		    (lpa2 >> 2))
+		ecmd->advertising |= mii_get_an(mii, MII_ADVERTISE);
+		if (ctrl1000 & ADVERTISE_1000HALF)
+			ecmd->advertising |= ADVERTISED_1000baseT_Half;
+		if (ctrl1000 & ADVERTISE_1000FULL)
+			ecmd->advertising |= ADVERTISED_1000baseT_Full;
+
+		if (bmsr & BMSR_ANEGCOMPLETE) {
+			ecmd->lp_advertising = mii_get_an(mii, MII_LPA);
+			if (stat1000 & LPA_1000HALF)
+				ecmd->lp_advertising |=
+					ADVERTISED_1000baseT_Half;
+			if (stat1000 & LPA_1000FULL)
+				ecmd->lp_advertising |=
+					ADVERTISED_1000baseT_Full;
+		} else {
+			ecmd->lp_advertising = 0;
+		}
+
+		nego = ecmd->advertising & ecmd->lp_advertising;
+
+		if (nego & (ADVERTISED_1000baseT_Full |
+			    ADVERTISED_1000baseT_Half)) {
 			ecmd->speed = SPEED_1000;
-		else if (nego == LPA_100FULL || nego == LPA_100HALF)
+			ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full);
+		} else if (nego & (ADVERTISED_100baseT_Full |
+				   ADVERTISED_100baseT_Half)) {
 			ecmd->speed = SPEED_100;
-		else
-			ecmd->speed = SPEED_10;
-		if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
-		    nego == LPA_10FULL) {
-			ecmd->duplex = DUPLEX_FULL;
-			mii->full_duplex = 1;
+			ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full);
 		} else {
-			ecmd->duplex = DUPLEX_HALF;
-			mii->full_duplex = 0;
+			ecmd->speed = SPEED_10;
+			ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full);
 		}
 	} else {
 		ecmd->autoneg = AUTONEG_DISABLE;
@@ -116,6 +137,8 @@
 		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
 	}
 
+	mii->full_duplex = ecmd->duplex;
+
 	/* ignore maxtxpkt, maxrxpkt for now */
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/mipsnet.c linux-libre-2.6.31-gnu/drivers/net/mipsnet.c
--- linux-libre-2.6.30-gnu/drivers/net/mipsnet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mipsnet.c	2009-09-09 18:13:59.000000000 -0400
@@ -237,6 +237,16 @@
 {
 }
 
+static const struct net_device_ops mipsnet_netdev_ops = {
+	.ndo_open		= mipsnet_open,
+	.ndo_stop		= mipsnet_close,
+	.ndo_start_xmit		= mipsnet_xmit,
+	.ndo_set_multicast_list	= mipsnet_set_mclist,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
 static int __init mipsnet_probe(struct platform_device *dev)
 {
 	struct net_device *netdev;
@@ -250,10 +260,7 @@
 
 	platform_set_drvdata(dev, netdev);
 
-	netdev->open			= mipsnet_open;
-	netdev->stop			= mipsnet_close;
-	netdev->hard_start_xmit		= mipsnet_xmit;
-	netdev->set_multicast_list	= mipsnet_set_mclist;
+	netdev->netdev_ops = &mipsnet_netdev_ops;
 
 	/*
 	 * TODO: probe for these or load them from PARAM
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/cmd.c linux-libre-2.6.31-gnu/drivers/net/mlx4/cmd.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/cmd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/cmd.c	2009-09-09 18:13:59.000000000 -0400
@@ -80,7 +80,9 @@
 	/* Bad management packet (silently discarded): */
 	CMD_STAT_BAD_PKT	= 0x30,
 	/* More outstanding CQEs in CQ than new CQ size: */
-	CMD_STAT_BAD_SIZE	= 0x40
+	CMD_STAT_BAD_SIZE	= 0x40,
+	/* Multi Function device support required: */
+	CMD_STAT_MULTI_FUNC_REQ	= 0x50,
 };
 
 enum {
@@ -128,6 +130,7 @@
 		[CMD_STAT_LAM_NOT_PRE]	  = -EAGAIN,
 		[CMD_STAT_BAD_PKT]	  = -EINVAL,
 		[CMD_STAT_BAD_SIZE]	  = -ENOMEM,
+		[CMD_STAT_MULTI_FUNC_REQ] = -EACCES,
 	};
 
 	if (status >= ARRAY_SIZE(trans_table) ||
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/en_cq.c linux-libre-2.6.31-gnu/drivers/net/mlx4/en_cq.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/en_cq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/en_cq.c	2009-09-09 18:13:59.000000000 -0400
@@ -89,6 +89,9 @@
 	*cq->mcq.arm_db    = 0;
 	memset(cq->buf, 0, cq->buf_size);
 
+	if (!cq->is_tx)
+		cq->size = priv->rx_ring[cq->ring].actual_size;
+
 	err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar,
 			    cq->wqres.db.dma, &cq->mcq, cq->vector, cq->is_tx);
 	if (err)
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/en_ethtool.c linux-libre-2.6.31-gnu/drivers/net/mlx4/en_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/en_ethtool.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/en_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+
+#include "mlx4_en.h"
+#include "en_port.h"
+
+
+static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
+{
+	int i;
+
+	priv->port_stats.lro_aggregated = 0;
+	priv->port_stats.lro_flushed = 0;
+	priv->port_stats.lro_no_desc = 0;
+
+	for (i = 0; i < priv->rx_ring_num; i++) {
+		priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
+		priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
+		priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
+	}
+}
+
+static void
+mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+
+	sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id);
+	strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
+	sprintf(drvinfo->fw_version, "%d.%d.%d",
+		(u16) (mdev->dev->caps.fw_ver >> 32),
+		(u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),
+		(u16) (mdev->dev->caps.fw_ver & 0xffff));
+	strncpy(drvinfo->bus_info, pci_name(mdev->dev->pdev), 32);
+	drvinfo->n_stats = 0;
+	drvinfo->regdump_len = 0;
+	drvinfo->eedump_len = 0;
+}
+
+static u32 mlx4_en_get_tso(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_TSO) != 0;
+}
+
+static int mlx4_en_set_tso(struct net_device *dev, u32 data)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+
+	if (data) {
+		if (!priv->mdev->LSO_support)
+			return -EPERM;
+		dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
+	} else
+		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+	return 0;
+}
+
+static u32 mlx4_en_get_rx_csum(struct net_device *dev)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	return priv->rx_csum;
+}
+
+static int mlx4_en_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	priv->rx_csum = (data != 0);
+	return 0;
+}
+
+static const char main_strings[][ETH_GSTRING_LEN] = {
+	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
+	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+	"tx_heartbeat_errors", "tx_window_errors",
+
+	/* port statistics */
+	"lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets",
+	"queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
+	"rx_csum_good", "rx_csum_none", "tx_chksum_offload",
+
+	/* packet statistics */
+	"broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3",
+	"rx_prio_4", "rx_prio_5", "rx_prio_6", "rx_prio_7", "tx_prio_0",
+	"tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5",
+	"tx_prio_6", "tx_prio_7",
+};
+#define NUM_MAIN_STATS	21
+#define NUM_ALL_STATS	(NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
+
+static u32 mlx4_en_get_msglevel(struct net_device *dev)
+{
+	return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
+}
+
+static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
+{
+	((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable = val;
+}
+
+static void mlx4_en_get_wol(struct net_device *netdev,
+			    struct ethtool_wolinfo *wol)
+{
+	wol->supported = 0;
+	wol->wolopts = 0;
+
+	return;
+}
+
+static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+
+	if (sset != ETH_SS_STATS)
+		return -EOPNOTSUPP;
+
+	return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2;
+}
+
+static void mlx4_en_get_ethtool_stats(struct net_device *dev,
+		struct ethtool_stats *stats, uint64_t *data)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	int index = 0;
+	int i;
+
+	spin_lock_bh(&priv->stats_lock);
+
+	mlx4_en_update_lro_stats(priv);
+
+	for (i = 0; i < NUM_MAIN_STATS; i++)
+		data[index++] = ((unsigned long *) &priv->stats)[i];
+	for (i = 0; i < NUM_PORT_STATS; i++)
+		data[index++] = ((unsigned long *) &priv->port_stats)[i];
+	for (i = 0; i < priv->tx_ring_num; i++) {
+		data[index++] = priv->tx_ring[i].packets;
+		data[index++] = priv->tx_ring[i].bytes;
+	}
+	for (i = 0; i < priv->rx_ring_num; i++) {
+		data[index++] = priv->rx_ring[i].packets;
+		data[index++] = priv->rx_ring[i].bytes;
+	}
+	for (i = 0; i < NUM_PKT_STATS; i++)
+		data[index++] = ((unsigned long *) &priv->pkstats)[i];
+	spin_unlock_bh(&priv->stats_lock);
+
+}
+
+static void mlx4_en_get_strings(struct net_device *dev,
+				uint32_t stringset, uint8_t *data)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	int index = 0;
+	int i;
+
+	if (stringset != ETH_SS_STATS)
+		return;
+
+	/* Add main counters */
+	for (i = 0; i < NUM_MAIN_STATS; i++)
+		strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
+	for (i = 0; i < NUM_PORT_STATS; i++)
+		strcpy(data + (index++) * ETH_GSTRING_LEN,
+			main_strings[i + NUM_MAIN_STATS]);
+	for (i = 0; i < priv->tx_ring_num; i++) {
+		sprintf(data + (index++) * ETH_GSTRING_LEN,
+			"tx%d_packets", i);
+		sprintf(data + (index++) * ETH_GSTRING_LEN,
+			"tx%d_bytes", i);
+	}
+	for (i = 0; i < priv->rx_ring_num; i++) {
+		sprintf(data + (index++) * ETH_GSTRING_LEN,
+			"rx%d_packets", i);
+		sprintf(data + (index++) * ETH_GSTRING_LEN,
+			"rx%d_bytes", i);
+	}
+	for (i = 0; i < NUM_PKT_STATS; i++)
+		strcpy(data + (index++) * ETH_GSTRING_LEN,
+			main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
+}
+
+static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	cmd->autoneg = AUTONEG_DISABLE;
+	cmd->supported = SUPPORTED_10000baseT_Full;
+	cmd->advertising = ADVERTISED_1000baseT_Full;
+	if (netif_carrier_ok(dev)) {
+		cmd->speed = SPEED_10000;
+		cmd->duplex = DUPLEX_FULL;
+	} else {
+		cmd->speed = -1;
+		cmd->duplex = -1;
+	}
+	return 0;
+}
+
+static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	if ((cmd->autoneg == AUTONEG_ENABLE) ||
+	    (cmd->speed != SPEED_10000) || (cmd->duplex != DUPLEX_FULL))
+		return -EINVAL;
+
+	/* Nothing to change */
+	return 0;
+}
+
+static int mlx4_en_get_coalesce(struct net_device *dev,
+			      struct ethtool_coalesce *coal)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+
+	coal->tx_coalesce_usecs = 0;
+	coal->tx_max_coalesced_frames = 0;
+	coal->rx_coalesce_usecs = priv->rx_usecs;
+	coal->rx_max_coalesced_frames = priv->rx_frames;
+
+	coal->pkt_rate_low = priv->pkt_rate_low;
+	coal->rx_coalesce_usecs_low = priv->rx_usecs_low;
+	coal->pkt_rate_high = priv->pkt_rate_high;
+	coal->rx_coalesce_usecs_high = priv->rx_usecs_high;
+	coal->rate_sample_interval = priv->sample_interval;
+	coal->use_adaptive_rx_coalesce = priv->adaptive_rx_coal;
+	return 0;
+}
+
+static int mlx4_en_set_coalesce(struct net_device *dev,
+			      struct ethtool_coalesce *coal)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	int err, i;
+
+	priv->rx_frames = (coal->rx_max_coalesced_frames ==
+			   MLX4_EN_AUTO_CONF) ?
+				MLX4_EN_RX_COAL_TARGET :
+				coal->rx_max_coalesced_frames;
+	priv->rx_usecs = (coal->rx_coalesce_usecs ==
+			  MLX4_EN_AUTO_CONF) ?
+				MLX4_EN_RX_COAL_TIME :
+				coal->rx_coalesce_usecs;
+
+	/* Set adaptive coalescing params */
+	priv->pkt_rate_low = coal->pkt_rate_low;
+	priv->rx_usecs_low = coal->rx_coalesce_usecs_low;
+	priv->pkt_rate_high = coal->pkt_rate_high;
+	priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
+	priv->sample_interval = coal->rate_sample_interval;
+	priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
+	priv->last_moder_time = MLX4_EN_AUTO_CONF;
+	if (priv->adaptive_rx_coal)
+		return 0;
+
+	for (i = 0; i < priv->rx_ring_num; i++) {
+		priv->rx_cq[i].moder_cnt = priv->rx_frames;
+		priv->rx_cq[i].moder_time = priv->rx_usecs;
+		err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int mlx4_en_set_pauseparam(struct net_device *dev,
+				struct ethtool_pauseparam *pause)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+	int err;
+
+	priv->prof->tx_pause = pause->tx_pause != 0;
+	priv->prof->rx_pause = pause->rx_pause != 0;
+	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
+				    priv->rx_skb_size + ETH_FCS_LEN,
+				    priv->prof->tx_pause,
+				    priv->prof->tx_ppp,
+				    priv->prof->rx_pause,
+				    priv->prof->rx_ppp);
+	if (err)
+		en_err(priv, "Failed setting pause params\n");
+
+	return err;
+}
+
+static void mlx4_en_get_pauseparam(struct net_device *dev,
+				 struct ethtool_pauseparam *pause)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+
+	pause->tx_pause = priv->prof->tx_pause;
+	pause->rx_pause = priv->prof->rx_pause;
+}
+
+static int mlx4_en_set_ringparam(struct net_device *dev,
+				 struct ethtool_ringparam *param)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+	u32 rx_size, tx_size;
+	int port_up = 0;
+	int err = 0;
+
+	if (param->rx_jumbo_pending || param->rx_mini_pending)
+		return -EINVAL;
+
+	rx_size = roundup_pow_of_two(param->rx_pending);
+	rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
+	rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
+	tx_size = roundup_pow_of_two(param->tx_pending);
+	tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
+	tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
+
+	if (rx_size == priv->prof->rx_ring_size &&
+	    tx_size == priv->prof->tx_ring_size)
+		return 0;
+
+	mutex_lock(&mdev->state_lock);
+	if (priv->port_up) {
+		port_up = 1;
+		mlx4_en_stop_port(dev);
+	}
+
+	mlx4_en_free_resources(priv);
+
+	priv->prof->tx_ring_size = tx_size;
+	priv->prof->rx_ring_size = rx_size;
+
+	err = mlx4_en_alloc_resources(priv);
+	if (err) {
+		en_err(priv, "Failed reallocating port resources\n");
+		goto out;
+	}
+	if (port_up) {
+		err = mlx4_en_start_port(dev);
+		if (err)
+			en_err(priv, "Failed starting port\n");
+	}
+
+out:
+	mutex_unlock(&mdev->state_lock);
+	return err;
+}
+
+static void mlx4_en_get_ringparam(struct net_device *dev,
+				  struct ethtool_ringparam *param)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+
+	memset(param, 0, sizeof(*param));
+	param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
+	param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
+	param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size;
+	param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size;
+}
+
+const struct ethtool_ops mlx4_en_ethtool_ops = {
+	.get_drvinfo = mlx4_en_get_drvinfo,
+	.get_settings = mlx4_en_get_settings,
+	.set_settings = mlx4_en_set_settings,
+#ifdef NETIF_F_TSO
+	.get_tso = mlx4_en_get_tso,
+	.set_tso = mlx4_en_set_tso,
+#endif
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+	.get_link = ethtool_op_get_link,
+	.get_rx_csum = mlx4_en_get_rx_csum,
+	.set_rx_csum = mlx4_en_set_rx_csum,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_ipv6_csum,
+	.get_strings = mlx4_en_get_strings,
+	.get_sset_count = mlx4_en_get_sset_count,
+	.get_ethtool_stats = mlx4_en_get_ethtool_stats,
+	.get_wol = mlx4_en_get_wol,
+	.get_msglevel = mlx4_en_get_msglevel,
+	.set_msglevel = mlx4_en_set_msglevel,
+	.get_coalesce = mlx4_en_get_coalesce,
+	.set_coalesce = mlx4_en_set_coalesce,
+	.get_pauseparam = mlx4_en_get_pauseparam,
+	.set_pauseparam = mlx4_en_set_pauseparam,
+	.get_ringparam = mlx4_en_get_ringparam,
+	.set_ringparam = mlx4_en_set_ringparam,
+	.get_flags = ethtool_op_get_flags,
+	.set_flags = ethtool_op_set_flags,
+};
+
+
+
+
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/en_main.c linux-libre-2.6.31-gnu/drivers/net/mlx4/en_main.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/en_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/en_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,6 +51,55 @@
 	DRV_NAME ": Mellanox ConnectX HCA Ethernet driver v"
 	DRV_VERSION " (" DRV_RELDATE ")\n";
 
+#define MLX4_EN_PARM_INT(X, def_val, desc) \
+	static unsigned int X = def_val;\
+	module_param(X , uint, 0444); \
+	MODULE_PARM_DESC(X, desc);
+
+
+/*
+ * Device scope module parameters
+ */
+
+
+/* Use a XOR rathern than Toeplitz hash function for RSS */
+MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS");
+
+/* RSS hash type mask - default to <saddr, daddr, sport, dport> */
+MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask");
+
+/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
+MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
+		 "Number of LRO sessions per ring or disabled (0)");
+
+/* Priority pausing */
+MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
+			   " Per priority bit mask");
+MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]."
+			   " Per priority bit mask");
+
+static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
+{
+	struct mlx4_en_profile *params = &mdev->profile;
+	int i;
+
+	params->rss_xor = (rss_xor != 0);
+	params->rss_mask = rss_mask & 0x1f;
+	params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
+	for (i = 1; i <= MLX4_MAX_PORTS; i++) {
+		params->prof[i].rx_pause = 1;
+		params->prof[i].rx_ppp = pfcrx;
+		params->prof[i].tx_pause = 1;
+		params->prof[i].tx_ppp = pfctx;
+		params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
+		params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
+		params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
+			(!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
+	}
+
+	return 0;
+}
+
 static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr,
 			  enum mlx4_dev_event event, int port)
 {
@@ -194,28 +243,11 @@
 	/* Create a netdev for each port */
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
 		mlx4_info(mdev, "Activating port:%d\n", i);
-		if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) {
+		if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i]))
 			mdev->pndev[i] = NULL;
-			goto err_free_netdev;
-		}
 	}
 	return mdev;
 
-
-err_free_netdev:
-	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
-		if (mdev->pndev[i])
-			mlx4_en_destroy_netdev(mdev->pndev[i]);
-	}
-
-	mutex_lock(&mdev->state_lock);
-	mdev->device_up = false;
-	mutex_unlock(&mdev->state_lock);
-	flush_workqueue(mdev->workqueue);
-
-	/* Stop event queue before we drop down to release shared SW state */
-	destroy_workqueue(mdev->workqueue);
-
 err_mr:
 	mlx4_mr_free(dev, &mdev->mr);
 err_uar:
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/en_netdev.c linux-libre-2.6.31-gnu/drivers/net/mlx4/en_netdev.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/en_netdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/en_netdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,14 +51,14 @@
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err;
 
-	mlx4_dbg(HW, priv, "Registering VLAN group:%p\n", grp);
+	en_dbg(HW, priv, "Registering VLAN group:%p\n", grp);
 	priv->vlgrp = grp;
 
 	mutex_lock(&mdev->state_lock);
 	if (mdev->device_up && priv->port_up) {
 		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, grp);
 		if (err)
-			mlx4_err(mdev, "Failed configuring VLAN filter\n");
+			en_err(priv, "Failed configuring VLAN filter\n");
 	}
 	mutex_unlock(&mdev->state_lock);
 }
@@ -72,15 +72,15 @@
 	if (!priv->vlgrp)
 		return;
 
-	mlx4_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n",
-		 vid, vlan_group_get_device(priv->vlgrp, vid));
+	en_dbg(HW, priv, "adding VLAN:%d (vlgrp entry:%p)\n",
+	       vid, vlan_group_get_device(priv->vlgrp, vid));
 
 	/* Add VID to port VLAN filter */
 	mutex_lock(&mdev->state_lock);
 	if (mdev->device_up && priv->port_up) {
 		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
 		if (err)
-			mlx4_err(mdev, "Failed configuring VLAN filter\n");
+			en_err(priv, "Failed configuring VLAN filter\n");
 	}
 	mutex_unlock(&mdev->state_lock);
 }
@@ -94,9 +94,8 @@
 	if (!priv->vlgrp)
 		return;
 
-	mlx4_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp "
-		 "entry:%p)\n", vid, priv->vlgrp,
-		 vlan_group_get_device(priv->vlgrp, vid));
+	en_dbg(HW, priv, "Killing VID:%d (vlgrp:%p vlgrp entry:%p)\n",
+	       vid, priv->vlgrp, vlan_group_get_device(priv->vlgrp, vid));
 	vlan_group_set_device(priv->vlgrp, vid, NULL);
 
 	/* Remove VID from port VLAN filter */
@@ -104,7 +103,7 @@
 	if (mdev->device_up && priv->port_up) {
 		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
 		if (err)
-			mlx4_err(mdev, "Failed configuring VLAN filter\n");
+			en_err(priv, "Failed configuring VLAN filter\n");
 	}
 	mutex_unlock(&mdev->state_lock);
 }
@@ -150,9 +149,10 @@
 		err = mlx4_register_mac(mdev->dev, priv->port,
 					priv->mac, &priv->mac_index);
 		if (err)
-			mlx4_err(mdev, "Failed changing HW MAC address\n");
+			en_err(priv, "Failed changing HW MAC address\n");
 	} else
-		mlx4_dbg(HW, priv, "Port is down, exiting...\n");
+		en_dbg(HW, priv, "Port is down while "
+				 "registering mac, exiting...\n");
 
 	mutex_unlock(&mdev->state_lock);
 }
@@ -174,7 +174,6 @@
 static void mlx4_en_cache_mclist(struct net_device *dev)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
 	struct dev_mc_list *mclist;
 	struct dev_mc_list *tmp;
 	struct dev_mc_list *plist = NULL;
@@ -182,7 +181,7 @@
 	for (mclist = dev->mc_list; mclist; mclist = mclist->next) {
 		tmp = kmalloc(sizeof(struct dev_mc_list), GFP_ATOMIC);
 		if (!tmp) {
-			mlx4_err(mdev, "failed to allocate multicast list\n");
+			en_err(priv, "failed to allocate multicast list\n");
 			mlx4_en_clear_list(dev);
 			return;
 		}
@@ -219,13 +218,13 @@
 
 	mutex_lock(&mdev->state_lock);
 	if (!mdev->device_up) {
-		mlx4_dbg(HW, priv, "Card is not up, ignoring "
-				   "multicast change.\n");
+		en_dbg(HW, priv, "Card is not up, "
+				 "ignoring multicast change.\n");
 		goto out;
 	}
 	if (!priv->port_up) {
-		mlx4_dbg(HW, priv, "Port is down, ignoring "
-				   "multicast change.\n");
+		en_dbg(HW, priv, "Port is down, "
+				 "ignoring  multicast change.\n");
 		goto out;
 	}
 
@@ -236,29 +235,27 @@
 	if (dev->flags & IFF_PROMISC) {
 		if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) {
 			if (netif_msg_rx_status(priv))
-				mlx4_warn(mdev, "Port:%d entering promiscuous mode\n",
-					  priv->port);
+				en_warn(priv, "Entering promiscuous mode\n");
 			priv->flags |= MLX4_EN_FLAG_PROMISC;
 
 			/* Enable promiscouos mode */
 			err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
 						     priv->base_qpn, 1);
 			if (err)
-				mlx4_err(mdev, "Failed enabling "
-					 "promiscous mode\n");
+				en_err(priv, "Failed enabling "
+					     "promiscous mode\n");
 
 			/* Disable port multicast filter (unconditionally) */
 			err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
 						  0, MLX4_MCAST_DISABLE);
 			if (err)
-				mlx4_err(mdev, "Failed disabling "
-					 "multicast filter\n");
+				en_err(priv, "Failed disabling "
+					     "multicast filter\n");
 
 			/* Disable port VLAN filter */
 			err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
 			if (err)
-				mlx4_err(mdev, "Failed disabling "
-					 "VLAN filter\n");
+				en_err(priv, "Failed disabling VLAN filter\n");
 		}
 		goto out;
 	}
@@ -269,20 +266,19 @@
 
 	if (priv->flags & MLX4_EN_FLAG_PROMISC) {
 		if (netif_msg_rx_status(priv))
-			mlx4_warn(mdev, "Port:%d leaving promiscuous mode\n",
-				  priv->port);
+			en_warn(priv, "Leaving promiscuous mode\n");
 		priv->flags &= ~MLX4_EN_FLAG_PROMISC;
 
 		/* Disable promiscouos mode */
 		err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
 					     priv->base_qpn, 0);
 		if (err)
-			mlx4_err(mdev, "Failed disabling promiscous mode\n");
+			en_err(priv, "Failed disabling promiscous mode\n");
 
 		/* Enable port VLAN filter */
 		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
 		if (err)
-			mlx4_err(mdev, "Failed enabling VLAN filter\n");
+			en_err(priv, "Failed enabling VLAN filter\n");
 	}
 
 	/* Enable/disable the multicast filter according to IFF_ALLMULTI */
@@ -290,12 +286,12 @@
 		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
 					  0, MLX4_MCAST_DISABLE);
 		if (err)
-			mlx4_err(mdev, "Failed disabling multicast filter\n");
+			en_err(priv, "Failed disabling multicast filter\n");
 	} else {
 		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
 					  0, MLX4_MCAST_DISABLE);
 		if (err)
-			mlx4_err(mdev, "Failed disabling multicast filter\n");
+			en_err(priv, "Failed disabling multicast filter\n");
 
 		/* Flush mcast filter and init it with broadcast address */
 		mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
@@ -314,7 +310,7 @@
 		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
 					  0, MLX4_MCAST_ENABLE);
 		if (err)
-			mlx4_err(mdev, "Failed enabling multicast filter\n");
+			en_err(priv, "Failed enabling multicast filter\n");
 
 		mlx4_en_clear_list(dev);
 	}
@@ -346,10 +342,10 @@
 	struct mlx4_en_dev *mdev = priv->mdev;
 
 	if (netif_msg_timer(priv))
-		mlx4_warn(mdev, "Tx timeout called on port:%d\n", priv->port);
+		en_warn(priv, "Tx timeout called on port:%d\n", priv->port);
 
 	priv->port_stats.tx_timeout++;
-	mlx4_dbg(DRV, priv, "Scheduling watchdog\n");
+	en_dbg(DRV, priv, "Scheduling watchdog\n");
 	queue_work(mdev->workqueue, &priv->watchdog_task);
 }
 
@@ -371,15 +367,15 @@
 	int i;
 
 	/* If we haven't received a specific coalescing setting
-	 * (module param), we set the moderation paramters as follows:
+	 * (module param), we set the moderation parameters as follows:
 	 * - moder_cnt is set to the number of mtu sized packets to
 	 *   satisfy our coelsing target.
 	 * - moder_time is set to a fixed value.
 	 */
-	priv->rx_frames = MLX4_EN_RX_COAL_TARGET / priv->dev->mtu + 1;
+	priv->rx_frames = MLX4_EN_RX_COAL_TARGET;
 	priv->rx_usecs = MLX4_EN_RX_COAL_TIME;
-	mlx4_dbg(INTR, priv, "Default coalesing params for mtu:%d - "
-			     "rx_frames:%d rx_usecs:%d\n",
+	en_dbg(INTR, priv, "Default coalesing params for mtu:%d - "
+			   "rx_frames:%d rx_usecs:%d\n",
 		 priv->dev->mtu, priv->rx_frames, priv->rx_usecs);
 
 	/* Setup cq moderation params */
@@ -412,7 +408,6 @@
 static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
 {
 	unsigned long period = (unsigned long) (jiffies - priv->last_moder_jiffies);
-	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_en_cq *cq;
 	unsigned long packets;
 	unsigned long rate;
@@ -472,11 +467,11 @@
 		moder_time = priv->rx_usecs;
 	}
 
-	mlx4_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
-		 tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period);
+	en_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
+	       tx_pkt_diff * HZ / period, rx_pkt_diff * HZ / period);
 
-	mlx4_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu "
-		 "[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n",
+	en_dbg(INTR, priv, "Rx moder_time changed from:%d to %d period:%lu "
+	       "[jiff] packets:%lu avg_pkt_size:%lu rate:%lu [p/s])\n",
 		 priv->last_moder_time, moder_time, period, packets,
 		 avg_pkt_size, rate);
 
@@ -487,8 +482,7 @@
 			cq->moder_time = moder_time;
 			err = mlx4_en_set_cq_moder(priv, cq);
 			if (err) {
-				mlx4_err(mdev, "Failed modifying moderation for cq:%d "
-					 "on port:%d\n", i, priv->port);
+				en_err(priv, "Failed modifying moderation for cq:%d\n", i);
 				break;
 			}
 		}
@@ -511,8 +505,7 @@
 
 	err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0);
 	if (err)
-		mlx4_dbg(HW, priv, "Could not update stats for "
-				   "port:%d\n", priv->port);
+		en_dbg(HW, priv, "Could not update stats \n");
 
 	mutex_lock(&mdev->state_lock);
 	if (mdev->device_up) {
@@ -536,12 +529,10 @@
 	 * report to system log */
 	if (priv->last_link_state != linkstate) {
 		if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
-			if (netif_msg_link(priv))
-				mlx4_info(mdev, "Port %d - link down\n", priv->port);
+			en_dbg(LINK, priv, "Link Down\n");
 			netif_carrier_off(priv->dev);
 		} else {
-			if (netif_msg_link(priv))
-				mlx4_info(mdev, "Port %d - link up\n", priv->port);
+			en_dbg(LINK, priv, "Link Up\n");
 			netif_carrier_on(priv->dev);
 		}
 	}
@@ -556,58 +547,53 @@
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_en_cq *cq;
 	struct mlx4_en_tx_ring *tx_ring;
-	struct mlx4_en_rx_ring *rx_ring;
 	int rx_index = 0;
 	int tx_index = 0;
-	u16 stride;
 	int err = 0;
 	int i;
 	int j;
 
 	if (priv->port_up) {
-		mlx4_dbg(DRV, priv, "start port called while port already up\n");
+		en_dbg(DRV, priv, "start port called while port already up\n");
 		return 0;
 	}
 
 	/* Calculate Rx buf size */
 	dev->mtu = min(dev->mtu, priv->max_mtu);
 	mlx4_en_calc_rx_buf(dev);
-	mlx4_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_skb_size);
-	stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
-				    DS_SIZE * priv->num_frags);
+	en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_skb_size);
+
 	/* Configure rx cq's and rings */
+	err = mlx4_en_activate_rx_rings(priv);
+	if (err) {
+		en_err(priv, "Failed to activate RX rings\n");
+		return err;
+	}
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		cq = &priv->rx_cq[i];
-		rx_ring = &priv->rx_ring[i];
 
 		err = mlx4_en_activate_cq(priv, cq);
 		if (err) {
-			mlx4_err(mdev, "Failed activating Rx CQ\n");
+			en_err(priv, "Failed activating Rx CQ\n");
 			goto cq_err;
 		}
 		for (j = 0; j < cq->size; j++)
 			cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK;
 		err = mlx4_en_set_cq_moder(priv, cq);
 		if (err) {
-			mlx4_err(mdev, "Failed setting cq moderation parameters");
+			en_err(priv, "Failed setting cq moderation parameters");
 			mlx4_en_deactivate_cq(priv, cq);
 			goto cq_err;
 		}
 		mlx4_en_arm_cq(priv, cq);
-
+		priv->rx_ring[i].cqn = cq->mcq.cqn;
 		++rx_index;
 	}
 
-	err = mlx4_en_activate_rx_rings(priv);
-	if (err) {
-		mlx4_err(mdev, "Failed to activate RX rings\n");
-		goto cq_err;
-	}
-
 	err = mlx4_en_config_rss_steer(priv);
 	if (err) {
-		mlx4_err(mdev, "Failed configuring rss steering\n");
-		goto rx_err;
+		en_err(priv, "Failed configuring rss steering\n");
+		goto cq_err;
 	}
 
 	/* Configure tx cq's and rings */
@@ -616,16 +602,16 @@
 		cq = &priv->tx_cq[i];
 		err = mlx4_en_activate_cq(priv, cq);
 		if (err) {
-			mlx4_err(mdev, "Failed allocating Tx CQ\n");
+			en_err(priv, "Failed allocating Tx CQ\n");
 			goto tx_err;
 		}
 		err = mlx4_en_set_cq_moder(priv, cq);
 		if (err) {
-			mlx4_err(mdev, "Failed setting cq moderation parameters");
+			en_err(priv, "Failed setting cq moderation parameters");
 			mlx4_en_deactivate_cq(priv, cq);
 			goto tx_err;
 		}
-		mlx4_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
+		en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
 		cq->buf->wqe_index = cpu_to_be16(0xffff);
 
 		/* Configure ring */
@@ -633,7 +619,7 @@
 		err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
 					       priv->rx_ring[0].srq.srqn);
 		if (err) {
-			mlx4_err(mdev, "Failed allocating Tx ring\n");
+			en_err(priv, "Failed allocating Tx ring\n");
 			mlx4_en_deactivate_cq(priv, cq);
 			goto tx_err;
 		}
@@ -651,30 +637,30 @@
 				    priv->prof->rx_pause,
 				    priv->prof->rx_ppp);
 	if (err) {
-		mlx4_err(mdev, "Failed setting port general configurations"
-			       " for port %d, with error %d\n", priv->port, err);
+		en_err(priv, "Failed setting port general configurations "
+			     "for port %d, with error %d\n", priv->port, err);
 		goto tx_err;
 	}
 	/* Set default qp number */
 	err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0);
 	if (err) {
-		mlx4_err(mdev, "Failed setting default qp numbers\n");
+		en_err(priv, "Failed setting default qp numbers\n");
 		goto tx_err;
 	}
 	/* Set port mac number */
-	mlx4_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
+	en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
 	err = mlx4_register_mac(mdev->dev, priv->port,
 				priv->mac, &priv->mac_index);
 	if (err) {
-		mlx4_err(mdev, "Failed setting port mac\n");
+		en_err(priv, "Failed setting port mac\n");
 		goto tx_err;
 	}
 
 	/* Init port */
-	mlx4_dbg(HW, priv, "Initializing port\n");
+	en_dbg(HW, priv, "Initializing port\n");
 	err = mlx4_INIT_PORT(mdev->dev, priv->port);
 	if (err) {
-		mlx4_err(mdev, "Failed Initializing port\n");
+		en_err(priv, "Failed Initializing port\n");
 		goto mac_err;
 	}
 
@@ -682,7 +668,7 @@
 	queue_work(mdev->workqueue, &priv->mcast_task);
 
 	priv->port_up = true;
-	netif_start_queue(dev);
+	netif_tx_start_all_queues(dev);
 	return 0;
 
 mac_err:
@@ -694,12 +680,11 @@
 	}
 
 	mlx4_en_release_rss_steer(priv);
-rx_err:
-	for (i = 0; i < priv->rx_ring_num; i++)
-		mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]);
 cq_err:
 	while (rx_index--)
 		mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
+	for (i = 0; i < priv->rx_ring_num; i++)
+		mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]);
 
 	return err; /* need to close devices */
 }
@@ -712,18 +697,17 @@
 	int i;
 
 	if (!priv->port_up) {
-		mlx4_dbg(DRV, priv, "stop port (%d) called while port already down\n",
-			 priv->port);
+		en_dbg(DRV, priv, "stop port called while port already down\n");
 		return;
 	}
-	netif_stop_queue(dev);
 
 	/* Synchronize with tx routine */
 	netif_tx_lock_bh(dev);
-	priv->port_up = false;
+	netif_tx_stop_all_queues(dev);
 	netif_tx_unlock_bh(dev);
 
 	/* close port*/
+	priv->port_up = false;
 	mlx4_CLOSE_PORT(mdev->dev, priv->port);
 
 	/* Unregister Mac address for the port */
@@ -758,13 +742,13 @@
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct net_device *dev = priv->dev;
 
-	mlx4_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
+	en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
 
 	mutex_lock(&mdev->state_lock);
 	if (priv->port_up) {
 		mlx4_en_stop_port(dev);
 		if (mlx4_en_start_port(dev))
-			mlx4_err(mdev, "Failed restarting port %d\n", priv->port);
+			en_err(priv, "Failed restarting port %d\n", priv->port);
 	}
 	mutex_unlock(&mdev->state_lock);
 }
@@ -780,14 +764,14 @@
 	mutex_lock(&mdev->state_lock);
 
 	if (!mdev->device_up) {
-		mlx4_err(mdev, "Cannot open - device down/disabled\n");
+		en_err(priv, "Cannot open - device down/disabled\n");
 		err = -EBUSY;
 		goto out;
 	}
 
 	/* Reset HW statistics and performance counters */
 	if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
-		mlx4_dbg(HW, priv, "Failed dumping statistics\n");
+		en_dbg(HW, priv, "Failed dumping statistics\n");
 
 	memset(&priv->stats, 0, sizeof(priv->stats));
 	memset(&priv->pstats, 0, sizeof(priv->pstats));
@@ -804,7 +788,7 @@
 	mlx4_en_set_default_moderation(priv);
 	err = mlx4_en_start_port(dev);
 	if (err)
-		mlx4_err(mdev, "Failed starting port:%d\n", priv->port);
+		en_err(priv, "Failed starting port:%d\n", priv->port);
 
 out:
 	mutex_unlock(&mdev->state_lock);
@@ -817,8 +801,7 @@
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 
-	if (netif_msg_ifdown(priv))
-		mlx4_info(mdev, "Close called for port:%d\n", priv->port);
+	en_dbg(IFDOWN, priv, "Close port called\n");
 
 	mutex_lock(&mdev->state_lock);
 
@@ -850,7 +833,6 @@
 
 int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
 {
-	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_en_port_profile *prof = priv->prof;
 	int i;
 
@@ -879,7 +861,7 @@
 	return 0;
 
 err:
-	mlx4_err(mdev, "Failed to allocate NIC resources\n");
+	en_err(priv, "Failed to allocate NIC resources\n");
 	return -ENOMEM;
 }
 
@@ -889,7 +871,7 @@
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 
-	mlx4_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
+	en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
 
 	/* Unregister device - this will close the port if it was up */
 	if (priv->registered)
@@ -899,7 +881,6 @@
 		mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
 
 	cancel_delayed_work(&priv->stats_task);
-	cancel_delayed_work(&priv->refill_task);
 	/* flush any pending task for this netdev */
 	flush_workqueue(mdev->workqueue);
 
@@ -918,11 +899,11 @@
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err = 0;
 
-	mlx4_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n",
+	en_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n",
 		 dev->mtu, new_mtu);
 
 	if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
-		mlx4_err(mdev, "Bad MTU size:%d.\n", new_mtu);
+		en_err(priv, "Bad MTU size:%d.\n", new_mtu);
 		return -EPERM;
 	}
 	dev->mtu = new_mtu;
@@ -932,13 +913,13 @@
 		if (!mdev->device_up) {
 			/* NIC is probably restarting - let watchdog task reset
 			 * the port */
-			mlx4_dbg(DRV, priv, "Change MTU called with card down!?\n");
+			en_dbg(DRV, priv, "Change MTU called with card down!?\n");
 		} else {
 			mlx4_en_stop_port(dev);
 			mlx4_en_set_default_moderation(priv);
 			err = mlx4_en_start_port(dev);
 			if (err) {
-				mlx4_err(mdev, "Failed restarting port:%d\n",
+				en_err(priv, "Failed restarting port:%d\n",
 					 priv->port);
 				queue_work(mdev->workqueue, &priv->watchdog_task);
 			}
@@ -952,6 +933,7 @@
 	.ndo_open		= mlx4_en_open,
 	.ndo_stop		= mlx4_en_close,
 	.ndo_start_xmit		= mlx4_en_xmit,
+	.ndo_select_queue	= mlx4_en_select_queue,
 	.ndo_get_stats		= mlx4_en_get_stats,
 	.ndo_set_multicast_list	= mlx4_en_set_multicast,
 	.ndo_set_mac_address	= mlx4_en_set_mac,
@@ -974,7 +956,7 @@
 	int i;
 	int err;
 
-	dev = alloc_etherdev(sizeof(struct mlx4_en_priv));
+	dev = alloc_etherdev_mq(sizeof(struct mlx4_en_priv), prof->tx_ring_num);
 	if (dev == NULL) {
 		mlx4_err(mdev, "Net device allocation failed\n");
 		return -ENOMEM;
@@ -1003,7 +985,6 @@
 	spin_lock_init(&priv->stats_lock);
 	INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast);
 	INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac);
-	INIT_DELAYED_WORK(&priv->refill_task, mlx4_en_rx_refill);
 	INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
 	INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
 	INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
@@ -1012,7 +993,7 @@
 	priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
 	priv->mac = mdev->dev->caps.def_mac[priv->port];
 	if (ILLEGAL_MAC(priv->mac)) {
-		mlx4_err(mdev, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
+		en_err(priv, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
 			 priv->port, priv->mac);
 		err = -EINVAL;
 		goto out;
@@ -1031,19 +1012,17 @@
 	err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
 				MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
 	if (err) {
-		mlx4_err(mdev, "Failed to allocate page for rx qps\n");
+		en_err(priv, "Failed to allocate page for rx qps\n");
 		goto out;
 	}
 	priv->allocated = 1;
 
-	/* Populate Tx priority mappings */
-	mlx4_en_set_prio_map(priv, priv->tx_prio_map, prof->tx_ring_num);
-
 	/*
 	 * Initialize netdev entry points
 	 */
 	dev->netdev_ops = &mlx4_netdev_ops;
 	dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
+	dev->real_num_tx_queues = MLX4_EN_NUM_TX_RINGS;
 
 	SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
 
@@ -1057,7 +1036,9 @@
 	 * Set driver features
 	 */
 	dev->features |= NETIF_F_SG;
+	dev->vlan_features |= NETIF_F_SG;
 	dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	dev->features |= NETIF_F_HIGHDMA;
 	dev->features |= NETIF_F_HW_VLAN_TX |
 			 NETIF_F_HW_VLAN_RX |
@@ -1067,6 +1048,8 @@
 	if (mdev->LSO_support) {
 		dev->features |= NETIF_F_TSO;
 		dev->features |= NETIF_F_TSO6;
+		dev->vlan_features |= NETIF_F_TSO;
+		dev->vlan_features |= NETIF_F_TSO6;
 	}
 
 	mdev->pndev[port] = dev;
@@ -1074,9 +1057,13 @@
 	netif_carrier_off(dev);
 	err = register_netdev(dev);
 	if (err) {
-		mlx4_err(mdev, "Netdev registration failed\n");
+		en_err(priv, "Netdev registration failed for port %d\n", port);
 		goto out;
 	}
+
+	en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
+	en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
+
 	priv->registered = 1;
 	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/en_params.c linux-libre-2.6.31-gnu/drivers/net/mlx4/en_params.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/en_params.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/en_params.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,485 +0,0 @@
-/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/ethtool.h>
-#include <linux/netdevice.h>
-
-#include "mlx4_en.h"
-#include "en_port.h"
-
-#define MLX4_EN_PARM_INT(X, def_val, desc) \
-	static unsigned int X = def_val;\
-	module_param(X , uint, 0444); \
-	MODULE_PARM_DESC(X, desc);
-
-
-/*
- * Device scope module parameters
- */
-
-
-/* Use a XOR rathern than Toeplitz hash function for RSS */
-MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS");
-
-/* RSS hash type mask - default to <saddr, daddr, sport, dport> */
-MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask");
-
-/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
-MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
-		 "Number of LRO sessions per ring or disabled (0)");
-
-/* Priority pausing */
-MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
-			   " Per priority bit mask");
-MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]."
-			   " Per priority bit mask");
-
-int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
-{
-	struct mlx4_en_profile *params = &mdev->profile;
-	int i;
-
-	params->rss_xor = (rss_xor != 0);
-	params->rss_mask = rss_mask & 0x1f;
-	params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
-	for (i = 1; i <= MLX4_MAX_PORTS; i++) {
-		params->prof[i].rx_pause = 1;
-		params->prof[i].rx_ppp = pfcrx;
-		params->prof[i].tx_pause = 1;
-		params->prof[i].tx_ppp = pfctx;
-		params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
-		params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
-	}
-	if (pfcrx || pfctx) {
-		params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM;
-		params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM;
-	} else {
-		params->prof[1].tx_ring_num = 1;
-		params->prof[2].tx_ring_num = 1;
-	}
-
-	return 0;
-}
-
-
-/*
- * Ethtool support
- */
-
-static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
-{
-	int i;
-
-	priv->port_stats.lro_aggregated = 0;
-	priv->port_stats.lro_flushed = 0;
-	priv->port_stats.lro_no_desc = 0;
-
-	for (i = 0; i < priv->rx_ring_num; i++) {
-		priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
-		priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
-		priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
-	}
-}
-
-static void
-mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
-
-	sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id);
-	strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
-	sprintf(drvinfo->fw_version, "%d.%d.%d",
-		(u16) (mdev->dev->caps.fw_ver >> 32),
-		(u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),
-		(u16) (mdev->dev->caps.fw_ver & 0xffff));
-	strncpy(drvinfo->bus_info, pci_name(mdev->dev->pdev), 32);
-	drvinfo->n_stats = 0;
-	drvinfo->regdump_len = 0;
-	drvinfo->eedump_len = 0;
-}
-
-static u32 mlx4_en_get_tso(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_TSO) != 0;
-}
-
-static int mlx4_en_set_tso(struct net_device *dev, u32 data)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-
-	if (data) {
-		if (!priv->mdev->LSO_support)
-			return -EPERM;
-		dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-	} else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-	return 0;
-}
-
-static u32 mlx4_en_get_rx_csum(struct net_device *dev)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	return priv->rx_csum;
-}
-
-static int mlx4_en_set_rx_csum(struct net_device *dev, u32 data)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	priv->rx_csum = (data != 0);
-	return 0;
-}
-
-static const char main_strings[][ETH_GSTRING_LEN] = {
-	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
-	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
-	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
-	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
-	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
-	"tx_heartbeat_errors", "tx_window_errors",
-
-	/* port statistics */
-	"lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets",
-	"queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
-	"rx_csum_good", "rx_csum_none", "tx_chksum_offload",
-
-	/* packet statistics */
-	"broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3",
-	"rx_prio_4", "rx_prio_5", "rx_prio_6", "rx_prio_7", "tx_prio_0",
-	"tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5",
-	"tx_prio_6", "tx_prio_7",
-};
-#define NUM_MAIN_STATS	21
-#define NUM_ALL_STATS	(NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
-
-static u32 mlx4_en_get_msglevel(struct net_device *dev)
-{
-	return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
-}
-
-static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
-{
-	((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable = val;
-}
-
-static void mlx4_en_get_wol(struct net_device *netdev,
-			    struct ethtool_wolinfo *wol)
-{
-	wol->supported = 0;
-	wol->wolopts = 0;
-
-	return;
-}
-
-static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-
-	if (sset != ETH_SS_STATS)
-		return -EOPNOTSUPP;
-
-	return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2;
-}
-
-static void mlx4_en_get_ethtool_stats(struct net_device *dev,
-		struct ethtool_stats *stats, uint64_t *data)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	int index = 0;
-	int i;
-
-	spin_lock_bh(&priv->stats_lock);
-
-	mlx4_en_update_lro_stats(priv);
-
-	for (i = 0; i < NUM_MAIN_STATS; i++)
-		data[index++] = ((unsigned long *) &priv->stats)[i];
-	for (i = 0; i < NUM_PORT_STATS; i++)
-		data[index++] = ((unsigned long *) &priv->port_stats)[i];
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		data[index++] = priv->tx_ring[i].packets;
-		data[index++] = priv->tx_ring[i].bytes;
-	}
-	for (i = 0; i < priv->rx_ring_num; i++) {
-		data[index++] = priv->rx_ring[i].packets;
-		data[index++] = priv->rx_ring[i].bytes;
-	}
-	for (i = 0; i < NUM_PKT_STATS; i++)
-		data[index++] = ((unsigned long *) &priv->pkstats)[i];
-	spin_unlock_bh(&priv->stats_lock);
-
-}
-
-static void mlx4_en_get_strings(struct net_device *dev,
-				uint32_t stringset, uint8_t *data)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	int index = 0;
-	int i;
-
-	if (stringset != ETH_SS_STATS)
-		return;
-
-	/* Add main counters */
-	for (i = 0; i < NUM_MAIN_STATS; i++)
-		strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
-	for (i = 0; i < NUM_PORT_STATS; i++)
-		strcpy(data + (index++) * ETH_GSTRING_LEN,
-			main_strings[i + NUM_MAIN_STATS]);
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"tx%d_packets", i);
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"tx%d_bytes", i);
-	}
-	for (i = 0; i < priv->rx_ring_num; i++) {
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"rx%d_packets", i);
-		sprintf(data + (index++) * ETH_GSTRING_LEN,
-			"rx%d_bytes", i);
-	}
-	for (i = 0; i < NUM_PKT_STATS; i++)
-		strcpy(data + (index++) * ETH_GSTRING_LEN,
-			main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
-}
-
-static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	cmd->autoneg = AUTONEG_DISABLE;
-	cmd->supported = SUPPORTED_10000baseT_Full;
-	cmd->advertising = SUPPORTED_10000baseT_Full;
-	if (netif_carrier_ok(dev)) {
-		cmd->speed = SPEED_10000;
-		cmd->duplex = DUPLEX_FULL;
-	} else {
-		cmd->speed = -1;
-		cmd->duplex = -1;
-	}
-	return 0;
-}
-
-static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	if ((cmd->autoneg == AUTONEG_ENABLE) ||
-	    (cmd->speed != SPEED_10000) || (cmd->duplex != DUPLEX_FULL))
-		return -EINVAL;
-
-	/* Nothing to change */
-	return 0;
-}
-
-static int mlx4_en_get_coalesce(struct net_device *dev,
-			      struct ethtool_coalesce *coal)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-
-	coal->tx_coalesce_usecs = 0;
-	coal->tx_max_coalesced_frames = 0;
-	coal->rx_coalesce_usecs = priv->rx_usecs;
-	coal->rx_max_coalesced_frames = priv->rx_frames;
-
-	coal->pkt_rate_low = priv->pkt_rate_low;
-	coal->rx_coalesce_usecs_low = priv->rx_usecs_low;
-	coal->pkt_rate_high = priv->pkt_rate_high;
-	coal->rx_coalesce_usecs_high = priv->rx_usecs_high;
-	coal->rate_sample_interval = priv->sample_interval;
-	coal->use_adaptive_rx_coalesce = priv->adaptive_rx_coal;
-	return 0;
-}
-
-static int mlx4_en_set_coalesce(struct net_device *dev,
-			      struct ethtool_coalesce *coal)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	int err, i;
-
-	priv->rx_frames = (coal->rx_max_coalesced_frames ==
-			   MLX4_EN_AUTO_CONF) ?
-				MLX4_EN_RX_COAL_TARGET /
-				priv->dev->mtu + 1 :
-				coal->rx_max_coalesced_frames;
-	priv->rx_usecs = (coal->rx_coalesce_usecs ==
-			  MLX4_EN_AUTO_CONF) ?
-				MLX4_EN_RX_COAL_TIME :
-				coal->rx_coalesce_usecs;
-
-	/* Set adaptive coalescing params */
-	priv->pkt_rate_low = coal->pkt_rate_low;
-	priv->rx_usecs_low = coal->rx_coalesce_usecs_low;
-	priv->pkt_rate_high = coal->pkt_rate_high;
-	priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
-	priv->sample_interval = coal->rate_sample_interval;
-	priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
-	priv->last_moder_time = MLX4_EN_AUTO_CONF;
-	if (priv->adaptive_rx_coal)
-		return 0;
-
-	for (i = 0; i < priv->rx_ring_num; i++) {
-		priv->rx_cq[i].moder_cnt = priv->rx_frames;
-		priv->rx_cq[i].moder_time = priv->rx_usecs;
-		err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-static int mlx4_en_set_pauseparam(struct net_device *dev,
-				struct ethtool_pauseparam *pause)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
-	int err;
-
-	priv->prof->tx_pause = pause->tx_pause != 0;
-	priv->prof->rx_pause = pause->rx_pause != 0;
-	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
-				    priv->rx_skb_size + ETH_FCS_LEN,
-				    priv->prof->tx_pause,
-				    priv->prof->tx_ppp,
-				    priv->prof->rx_pause,
-				    priv->prof->rx_ppp);
-	if (err)
-		mlx4_err(mdev, "Failed setting pause params to\n");
-
-	return err;
-}
-
-static void mlx4_en_get_pauseparam(struct net_device *dev,
-				 struct ethtool_pauseparam *pause)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-
-	pause->tx_pause = priv->prof->tx_pause;
-	pause->rx_pause = priv->prof->rx_pause;
-}
-
-static int mlx4_en_set_ringparam(struct net_device *dev,
-				 struct ethtool_ringparam *param)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
-	u32 rx_size, tx_size;
-	int port_up = 0;
-	int err = 0;
-
-	if (param->rx_jumbo_pending || param->rx_mini_pending)
-		return -EINVAL;
-
-	rx_size = roundup_pow_of_two(param->rx_pending);
-	rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
-	rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
-	tx_size = roundup_pow_of_two(param->tx_pending);
-	tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
-	tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
-
-	if (rx_size == priv->prof->rx_ring_size &&
-	    tx_size == priv->prof->tx_ring_size)
-		return 0;
-
-	mutex_lock(&mdev->state_lock);
-	if (priv->port_up) {
-		port_up = 1;
-		mlx4_en_stop_port(dev);
-	}
-
-	mlx4_en_free_resources(priv);
-
-	priv->prof->tx_ring_size = tx_size;
-	priv->prof->rx_ring_size = rx_size;
-
-	err = mlx4_en_alloc_resources(priv);
-	if (err) {
-		mlx4_err(mdev, "Failed reallocating port resources\n");
-		goto out;
-	}
-	if (port_up) {
-		err = mlx4_en_start_port(dev);
-		if (err)
-			mlx4_err(mdev, "Failed starting port\n");
-	}
-
-out:
-	mutex_unlock(&mdev->state_lock);
-	return err;
-}
-
-static void mlx4_en_get_ringparam(struct net_device *dev,
-				  struct ethtool_ringparam *param)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
-
-	memset(param, 0, sizeof(*param));
-	param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
-	param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
-	param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size;
-	param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size;
-}
-
-const struct ethtool_ops mlx4_en_ethtool_ops = {
-	.get_drvinfo = mlx4_en_get_drvinfo,
-	.get_settings = mlx4_en_get_settings,
-	.set_settings = mlx4_en_set_settings,
-#ifdef NETIF_F_TSO
-	.get_tso = mlx4_en_get_tso,
-	.set_tso = mlx4_en_set_tso,
-#endif
-	.get_sg = ethtool_op_get_sg,
-	.set_sg = ethtool_op_set_sg,
-	.get_link = ethtool_op_get_link,
-	.get_rx_csum = mlx4_en_get_rx_csum,
-	.set_rx_csum = mlx4_en_set_rx_csum,
-	.get_tx_csum = ethtool_op_get_tx_csum,
-	.set_tx_csum = ethtool_op_set_tx_ipv6_csum,
-	.get_strings = mlx4_en_get_strings,
-	.get_sset_count = mlx4_en_get_sset_count,
-	.get_ethtool_stats = mlx4_en_get_ethtool_stats,
-	.get_wol = mlx4_en_get_wol,
-	.get_msglevel = mlx4_en_get_msglevel,
-	.set_msglevel = mlx4_en_set_msglevel,
-	.get_coalesce = mlx4_en_get_coalesce,
-	.set_coalesce = mlx4_en_set_coalesce,
-	.get_pauseparam = mlx4_en_get_pauseparam,
-	.set_pauseparam = mlx4_en_set_pauseparam,
-	.get_ringparam = mlx4_en_get_ringparam,
-	.set_ringparam = mlx4_en_set_ringparam,
-	.get_flags = ethtool_op_get_flags,
-	.set_flags = ethtool_op_set_flags,
-};
-
-
-
-
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/en_rx.c linux-libre-2.6.31-gnu/drivers/net/mlx4/en_rx.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/en_rx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/en_rx.c	2009-09-09 18:13:59.000000000 -0400
@@ -114,8 +114,8 @@
 			goto out;
 
 		page_alloc->offset = priv->frag_info[i].frag_align;
-		mlx4_dbg(DRV, priv, "Initialized allocator:%d with page:%p\n",
-			 i, page_alloc->page);
+		en_dbg(DRV, priv, "Initialized allocator:%d with page:%p\n",
+		       i, page_alloc->page);
 	}
 	return 0;
 
@@ -136,8 +136,8 @@
 
 	for (i = 0; i < priv->num_frags; i++) {
 		page_alloc = &ring->page_alloc[i];
-		mlx4_dbg(DRV, priv, "Freeing allocator:%d count:%d\n",
-			 i, page_count(page_alloc->page));
+		en_dbg(DRV, priv, "Freeing allocator:%d count:%d\n",
+		       i, page_count(page_alloc->page));
 
 		put_page(page_alloc->page);
 		page_alloc->page = NULL;
@@ -202,12 +202,34 @@
 	*ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
 }
 
-static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
+static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv,
+				 struct mlx4_en_rx_ring *ring,
+				 int index)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
+	struct skb_frag_struct *skb_frags;
+	struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride);
+	dma_addr_t dma;
+	int nr;
+
+	skb_frags = ring->rx_info + (index << priv->log_rx_info);
+	for (nr = 0; nr < priv->num_frags; nr++) {
+		en_dbg(DRV, priv, "Freeing fragment:%d\n", nr);
+		dma = be64_to_cpu(rx_desc->data[nr].addr);
+
+		en_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma);
+		pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size,
+				 PCI_DMA_FROMDEVICE);
+		put_page(skb_frags[nr].page);
+	}
+}
+
+static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
+{
 	struct mlx4_en_rx_ring *ring;
 	int ring_ind;
 	int buf_ind;
+	int new_size;
 
 	for (buf_ind = 0; buf_ind < priv->prof->rx_ring_size; buf_ind++) {
 		for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
@@ -216,121 +238,55 @@
 			if (mlx4_en_prepare_rx_desc(priv, ring,
 						    ring->actual_size)) {
 				if (ring->actual_size < MLX4_EN_MIN_RX_SIZE) {
-					mlx4_err(mdev, "Failed to allocate "
-						       "enough rx buffers\n");
+					en_err(priv, "Failed to allocate "
+						     "enough rx buffers\n");
 					return -ENOMEM;
 				} else {
-					if (netif_msg_rx_err(priv))
-						mlx4_warn(mdev,
-							  "Only %d buffers allocated\n",
-							  ring->actual_size);
-					goto out;
+					new_size = rounddown_pow_of_two(ring->actual_size);
+					en_warn(priv, "Only %d buffers allocated "
+						      "reducing ring size to %d",
+						ring->actual_size, new_size);
+					goto reduce_rings;
 				}
 			}
 			ring->actual_size++;
 			ring->prod++;
 		}
 	}
-out:
 	return 0;
-}
-
-static int mlx4_en_fill_rx_buf(struct net_device *dev,
-			       struct mlx4_en_rx_ring *ring)
-{
-	struct mlx4_en_priv *priv = netdev_priv(dev);
-	int num = 0;
-	int err;
 
-	while ((u32) (ring->prod - ring->cons) < ring->actual_size) {
-		err = mlx4_en_prepare_rx_desc(priv, ring, ring->prod &
-					      ring->size_mask);
-		if (err) {
-			if (netif_msg_rx_err(priv))
-				mlx4_warn(priv->mdev,
-					  "Failed preparing rx descriptor\n");
-			priv->port_stats.rx_alloc_failed++;
-			break;
+reduce_rings:
+	for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
+		ring = &priv->rx_ring[ring_ind];
+		while (ring->actual_size > new_size) {
+			ring->actual_size--;
+			ring->prod--;
+			mlx4_en_free_rx_desc(priv, ring, ring->actual_size);
 		}
-		++num;
-		++ring->prod;
+		ring->size_mask = ring->actual_size - 1;
 	}
-	if ((u32) (ring->prod - ring->cons) == ring->size)
-		ring->full = 1;
 
-	return num;
+	return 0;
 }
 
 static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
 				struct mlx4_en_rx_ring *ring)
 {
-	struct mlx4_en_dev *mdev = priv->mdev;
-	struct skb_frag_struct *skb_frags;
-	struct mlx4_en_rx_desc *rx_desc;
-	dma_addr_t dma;
 	int index;
-	int nr;
 
-	mlx4_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n",
-			ring->cons, ring->prod);
+	en_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n",
+	       ring->cons, ring->prod);
 
 	/* Unmap and free Rx buffers */
-	BUG_ON((u32) (ring->prod - ring->cons) > ring->size);
+	BUG_ON((u32) (ring->prod - ring->cons) > ring->actual_size);
 	while (ring->cons != ring->prod) {
 		index = ring->cons & ring->size_mask;
-		rx_desc = ring->buf + (index << ring->log_stride);
-		skb_frags = ring->rx_info + (index << priv->log_rx_info);
-		mlx4_dbg(DRV, priv, "Processing descriptor:%d\n", index);
-
-		for (nr = 0; nr < priv->num_frags; nr++) {
-			mlx4_dbg(DRV, priv, "Freeing fragment:%d\n", nr);
-			dma = be64_to_cpu(rx_desc->data[nr].addr);
-
-			mlx4_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma);
-			pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size,
-					 PCI_DMA_FROMDEVICE);
-			put_page(skb_frags[nr].page);
-		}
+		en_dbg(DRV, priv, "Processing descriptor:%d\n", index);
+		mlx4_en_free_rx_desc(priv, ring, index);
 		++ring->cons;
 	}
 }
 
-
-void mlx4_en_rx_refill(struct work_struct *work)
-{
-	struct delayed_work *delay = to_delayed_work(work);
-	struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
-						 refill_task);
-	struct mlx4_en_dev *mdev = priv->mdev;
-	struct net_device *dev = priv->dev;
-	struct mlx4_en_rx_ring *ring;
-	int need_refill = 0;
-	int i;
-
-	mutex_lock(&mdev->state_lock);
-	if (!mdev->device_up || !priv->port_up)
-		goto out;
-
-	/* We only get here if there are no receive buffers, so we can't race
-	 * with Rx interrupts while filling buffers */
-	for (i = 0; i < priv->rx_ring_num; i++) {
-		ring = &priv->rx_ring[i];
-		if (ring->need_refill) {
-			if (mlx4_en_fill_rx_buf(dev, ring)) {
-				ring->need_refill = 0;
-				mlx4_en_update_rx_prod_db(ring);
-			} else
-				need_refill = 1;
-		}
-	}
-	if (need_refill)
-		queue_delayed_work(mdev->workqueue, &priv->refill_task, HZ);
-
-out:
-	mutex_unlock(&mdev->state_lock);
-}
-
-
 int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
 			   struct mlx4_en_rx_ring *ring, u32 size, u16 stride)
 {
@@ -354,10 +310,10 @@
 					sizeof(struct skb_frag_struct));
 	ring->rx_info = vmalloc(tmp);
 	if (!ring->rx_info) {
-		mlx4_err(mdev, "Failed allocating rx_info ring\n");
+		en_err(priv, "Failed allocating rx_info ring\n");
 		return -ENOMEM;
 	}
-	mlx4_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n",
+	en_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n",
 		 ring->rx_info, tmp);
 
 	err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres,
@@ -367,7 +323,7 @@
 
 	err = mlx4_en_map_buffer(&ring->wqres.buf);
 	if (err) {
-		mlx4_err(mdev, "Failed to map RX buffer\n");
+		en_err(priv, "Failed to map RX buffer\n");
 		goto err_hwq;
 	}
 	ring->buf = ring->wqres.buf.direct.buf;
@@ -385,7 +341,7 @@
 				    sizeof(struct net_lro_desc),
 				    GFP_KERNEL);
 	if (!ring->lro.lro_arr) {
-		mlx4_err(mdev, "Failed to allocate lro array\n");
+		en_err(priv, "Failed to allocate lro array\n");
 		goto err_map;
 	}
 	ring->lro.get_frag_header = mlx4_en_get_frag_header;
@@ -436,13 +392,10 @@
 		/* Initialize page allocators */
 		err = mlx4_en_init_allocator(priv, ring);
 		if (err) {
-			mlx4_err(mdev, "Failed initializing ring allocator\n");
+			en_err(priv, "Failed initializing ring allocator\n");
 			ring_ind--;
 			goto err_allocator;
 		}
-
-		/* Fill Rx buffers */
-		ring->full = 0;
 	}
 	err = mlx4_en_fill_rx_buffers(priv);
 	if (err)
@@ -454,7 +407,7 @@
 		mlx4_en_update_rx_prod_db(ring);
 
 		/* Configure SRQ representing the ring */
-		ring->srq.max    = ring->size;
+		ring->srq.max    = ring->actual_size;
 		ring->srq.max_gs = max_gs;
 		ring->srq.wqe_shift = ilog2(ring->stride);
 
@@ -467,7 +420,7 @@
 		err = mlx4_srq_alloc(mdev->dev, mdev->priv_pdn, &ring->wqres.mtt,
 				     ring->wqres.db.dma, &ring->srq);
 		if (err){
-			mlx4_err(mdev, "Failed to allocate srq\n");
+			en_err(priv, "Failed to allocate srq\n");
 			ring_ind--;
 			goto err_srq;
 		}
@@ -553,8 +506,9 @@
 				 PCI_DMA_FROMDEVICE);
 	}
 	/* Adjust size of last fragment to match actual length */
-	skb_frags_rx[nr - 1].size = length -
-		priv->frag_info[nr - 1].frag_prefix_size;
+	if (nr > 0)
+		skb_frags_rx[nr - 1].size = length -
+			priv->frag_info[nr - 1].frag_prefix_size;
 	return nr;
 
 fail:
@@ -582,7 +536,7 @@
 
 	skb = dev_alloc_skb(SMALL_PACKET_SIZE + NET_IP_ALIGN);
 	if (!skb) {
-		mlx4_dbg(RX_ERR, priv, "Failed allocating skb\n");
+		en_dbg(RX_ERR, priv, "Failed allocating skb\n");
 		return NULL;
 	}
 	skb->dev = priv->dev;
@@ -630,38 +584,10 @@
 	return skb;
 }
 
-static void mlx4_en_copy_desc(struct mlx4_en_priv *priv,
-			      struct mlx4_en_rx_ring *ring,
-			      int from, int to, int num)
-{
-	struct skb_frag_struct *skb_frags_from;
-	struct skb_frag_struct *skb_frags_to;
-	struct mlx4_en_rx_desc *rx_desc_from;
-	struct mlx4_en_rx_desc *rx_desc_to;
-	int from_index, to_index;
-	int nr, i;
-
-	for (i = 0; i < num; i++) {
-		from_index = (from + i) & ring->size_mask;
-		to_index = (to + i) & ring->size_mask;
-		skb_frags_from = ring->rx_info + (from_index << priv->log_rx_info);
-		skb_frags_to = ring->rx_info + (to_index << priv->log_rx_info);
-		rx_desc_from = ring->buf + (from_index << ring->log_stride);
-		rx_desc_to = ring->buf + (to_index << ring->log_stride);
-
-		for (nr = 0; nr < priv->num_frags; nr++) {
-			skb_frags_to[nr].page = skb_frags_from[nr].page;
-			skb_frags_to[nr].page_offset = skb_frags_from[nr].page_offset;
-			rx_desc_to->data[nr].addr = rx_desc_from->data[nr].addr;
-		}
-	}
-}
-
 
 int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_cqe *cqe;
 	struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
 	struct skb_frag_struct *skb_frags;
@@ -698,14 +624,14 @@
 		/* Drop packet on bad receive or bad checksum */
 		if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
 						MLX4_CQE_OPCODE_ERROR)) {
-			mlx4_err(mdev, "CQE completed in error - vendor "
+			en_err(priv, "CQE completed in error - vendor "
 				  "syndrom:%d syndrom:%d\n",
 				  ((struct mlx4_err_cqe *) cqe)->vendor_err_syndrome,
 				  ((struct mlx4_err_cqe *) cqe)->syndrome);
 			goto next;
 		}
 		if (unlikely(cqe->badfcs_enc & MLX4_CQE_BAD_FCS)) {
-			mlx4_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n");
+			en_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n");
 			goto next;
 		}
 
@@ -805,11 +731,6 @@
 	wmb(); /* ensure HW sees CQ consumer before we post new buffers */
 	ring->cons = cq->mcq.cons_index;
 	ring->prod += polled; /* Polled descriptors were realocated in place */
-	if (unlikely(!ring->full)) {
-		mlx4_en_copy_desc(priv, ring, ring->cons - polled,
-				  ring->prod - polled, polled);
-		mlx4_en_fill_rx_buf(dev, ring);
-	}
 	mlx4_en_update_rx_prod_db(ring);
 	return polled;
 }
@@ -855,7 +776,7 @@
 	u16 res = MLX4_EN_ALLOC_SIZE % stride;
 	u16 offset = MLX4_EN_ALLOC_SIZE - stride - res + align;
 
-	mlx4_dbg(DRV, priv, "Calculated last offset for stride:%d align:%d "
+	en_dbg(DRV, priv, "Calculated last offset for stride:%d align:%d "
 			    "res:%d offset:%d\n", stride, align, res, offset);
 	return offset;
 }
@@ -900,10 +821,10 @@
 	priv->rx_skb_size = eff_mtu;
 	priv->log_rx_info = ROUNDUP_LOG2(i * sizeof(struct skb_frag_struct));
 
-	mlx4_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d "
+	en_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d "
 		  "num_frags:%d):\n", eff_mtu, priv->num_frags);
 	for (i = 0; i < priv->num_frags; i++) {
-		mlx4_dbg(DRV, priv, "  frag:%d - size:%d prefix:%d align:%d "
+		en_dbg(DRV, priv, "  frag:%d - size:%d prefix:%d align:%d "
 				"stride:%d last_offset:%d\n", i,
 				priv->frag_info[i].frag_size,
 				priv->frag_info[i].frag_prefix_size,
@@ -923,12 +844,12 @@
 	int i;
 
 	rss_map->size = roundup_pow_of_two(num_entries);
-	mlx4_dbg(DRV, priv, "Setting default RSS map of %d entires\n",
-		 rss_map->size);
+	en_dbg(DRV, priv, "Setting default RSS map of %d entires\n",
+	       rss_map->size);
 
 	for (i = 0; i < rss_map->size; i++) {
 		rss_map->map[i] = i % num_rings;
-		mlx4_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]);
+		en_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]);
 	}
 }
 
@@ -943,13 +864,13 @@
 
 	context = kmalloc(sizeof *context , GFP_KERNEL);
 	if (!context) {
-		mlx4_err(mdev, "Failed to allocate qp context\n");
+		en_err(priv, "Failed to allocate qp context\n");
 		return -ENOMEM;
 	}
 
 	err = mlx4_qp_alloc(mdev->dev, qpn, qp);
 	if (err) {
-		mlx4_err(mdev, "Failed to allocate qp #%d\n", qpn);
+		en_err(priv, "Failed to allocate qp #%x\n", qpn);
 		goto out;
 	}
 	qp->event = mlx4_en_sqp_event;
@@ -981,12 +902,11 @@
 	int err = 0;
 	int good_qps = 0;
 
-	mlx4_dbg(DRV, priv, "Configuring rss steering for port %u\n", priv->port);
+	en_dbg(DRV, priv, "Configuring rss steering\n");
 	err = mlx4_qp_reserve_range(mdev->dev, rss_map->size,
 				    rss_map->size, &rss_map->base_qpn);
 	if (err) {
-		mlx4_err(mdev, "Failed reserving %d qps for port %u\n",
-			 rss_map->size, priv->port);
+		en_err(priv, "Failed reserving %d qps\n", rss_map->size);
 		return err;
 	}
 
@@ -1006,13 +926,13 @@
 	/* Configure RSS indirection qp */
 	err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
 	if (err) {
-		mlx4_err(mdev, "Failed to reserve range for RSS "
-			       "indirection qp\n");
+		en_err(priv, "Failed to reserve range for RSS "
+			     "indirection qp\n");
 		goto rss_err;
 	}
 	err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
 	if (err) {
-		mlx4_err(mdev, "Failed to allocate RSS indirection QP\n");
+		en_err(priv, "Failed to allocate RSS indirection QP\n");
 		goto reserve_err;
 	}
 	rss_map->indir_qp.event = mlx4_en_sqp_event;
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/en_tx.c linux-libre-2.6.31-gnu/drivers/net/mlx4/en_tx.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/en_tx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/en_tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -68,15 +68,15 @@
 	tmp = size * sizeof(struct mlx4_en_tx_info);
 	ring->tx_info = vmalloc(tmp);
 	if (!ring->tx_info) {
-		mlx4_err(mdev, "Failed allocating tx_info ring\n");
+		en_err(priv, "Failed allocating tx_info ring\n");
 		return -ENOMEM;
 	}
-	mlx4_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n",
+	en_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n",
 		 ring->tx_info, tmp);
 
 	ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL);
 	if (!ring->bounce_buf) {
-		mlx4_err(mdev, "Failed allocating bounce buffer\n");
+		en_err(priv, "Failed allocating bounce buffer\n");
 		err = -ENOMEM;
 		goto err_tx;
 	}
@@ -85,31 +85,31 @@
 	err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size,
 				 2 * PAGE_SIZE);
 	if (err) {
-		mlx4_err(mdev, "Failed allocating hwq resources\n");
+		en_err(priv, "Failed allocating hwq resources\n");
 		goto err_bounce;
 	}
 
 	err = mlx4_en_map_buffer(&ring->wqres.buf);
 	if (err) {
-		mlx4_err(mdev, "Failed to map TX buffer\n");
+		en_err(priv, "Failed to map TX buffer\n");
 		goto err_hwq_res;
 	}
 
 	ring->buf = ring->wqres.buf.direct.buf;
 
-	mlx4_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d "
-		 "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size,
-		 ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map);
+	en_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d "
+	       "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size,
+	       ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map);
 
 	err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn);
 	if (err) {
-		mlx4_err(mdev, "Failed reserving qp for tx ring.\n");
+		en_err(priv, "Failed reserving qp for tx ring.\n");
 		goto err_map;
 	}
 
 	err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp);
 	if (err) {
-		mlx4_err(mdev, "Failed allocating qp %d\n", ring->qpn);
+		en_err(priv, "Failed allocating qp %d\n", ring->qpn);
 		goto err_reserve;
 	}
 	ring->qp.event = mlx4_en_sqp_event;
@@ -135,7 +135,7 @@
 			     struct mlx4_en_tx_ring *ring)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
-	mlx4_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
+	en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
 
 	mlx4_qp_remove(mdev->dev, &ring->qp);
 	mlx4_qp_free(mdev->dev, &ring->qp);
@@ -249,6 +249,7 @@
 				pci_unmap_page(mdev->pdev,
 					(dma_addr_t) be64_to_cpu(data->addr),
 					 frag->size, PCI_DMA_TODEVICE);
+				++data;
 			}
 		}
 		/* Stamp the freed descriptor */
@@ -274,12 +275,12 @@
 
 	/* Skip last polled descriptor */
 	ring->cons += ring->last_nr_txbb;
-	mlx4_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n",
+	en_dbg(DRV, priv, "Freeing Tx buf - cons:0x%x prod:0x%x\n",
 		 ring->cons, ring->prod);
 
 	if ((u32) (ring->prod - ring->cons) > ring->size) {
 		if (netif_msg_tx_err(priv))
-			mlx4_warn(priv->mdev, "Tx consumer passed producer!\n");
+			en_warn(priv, "Tx consumer passed producer!\n");
 		return 0;
 	}
 
@@ -292,39 +293,11 @@
 	}
 
 	if (cnt)
-		mlx4_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt);
+		en_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt);
 
 	return cnt;
 }
 
-void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num)
-{
-	int block = 8 / ring_num;
-	int extra = 8 - (block * ring_num);
-	int num = 0;
-	u16 ring = 1;
-	int prio;
-
-	if (ring_num == 1) {
-		for (prio = 0; prio < 8; prio++)
-			prio_map[prio] = 0;
-		return;
-	}
-
-	for (prio = 0; prio < 8; prio++) {
-		if (extra && (num == block + 1)) {
-			ring++;
-			num = 0;
-			extra--;
-		} else if (!extra && (num == block)) {
-			ring++;
-			num = 0;
-		}
-		prio_map[prio] = ring;
-		mlx4_dbg(DRV, priv, " prio:%d --> ring:%d\n", prio, ring);
-		num++;
-	}
-}
 
 static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
 {
@@ -386,18 +359,8 @@
 	if (unlikely(ring->blocked)) {
 		if ((u32) (ring->prod - ring->cons) <=
 		     ring->size - HEADROOM - MAX_DESC_TXBBS) {
-
-			/* TODO: support multiqueue netdevs. Currently, we block
-			 * when *any* ring is full. Note that:
-			 * - 2 Tx rings can unblock at the same time and call
-			 *   netif_wake_queue(), which is OK since this
-			 *   operation is idempotent.
-			 * - We might wake the queue just after another ring
-			 *   stopped it. This is no big deal because the next
-			 *   transmission on that ring would stop the queue.
-			 */
 			ring->blocked = 0;
-			netif_wake_queue(dev);
+			netif_tx_wake_queue(netdev_get_tx_queue(dev, cq->ring));
 			priv->port_stats.wake_queue++;
 		}
 	}
@@ -474,6 +437,7 @@
 {
 	struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind];
 	struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind];
+	unsigned long flags;
 
 	/* If we don't have a pending timer, set one up to catch our recent
 	   post in case the interface becomes idle */
@@ -482,9 +446,9 @@
 
 	/* Poll the CQ every mlx4_en_TX_MODER_POLL packets */
 	if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0)
-		if (spin_trylock_irq(&ring->comp_lock)) {
+		if (spin_trylock_irqsave(&ring->comp_lock, flags)) {
 			mlx4_en_process_tx_cq(priv->dev, cq);
-			spin_unlock_irq(&ring->comp_lock);
+			spin_unlock_irqrestore(&ring->comp_lock, flags);
 		}
 }
 
@@ -539,7 +503,6 @@
 			 int *lso_header_size)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_dev *mdev = priv->mdev;
 	int real_size;
 
 	if (skb_is_gso(skb)) {
@@ -553,17 +516,10 @@
 				real_size += DS_SIZE;
 			else {
 				if (netif_msg_tx_err(priv))
-					mlx4_warn(mdev, "Non-linear headers\n");
-				dev_kfree_skb_any(skb);
+					en_warn(priv, "Non-linear headers\n");
 				return 0;
 			}
 		}
-		if (unlikely(*lso_header_size > MAX_LSO_HDR_SIZE)) {
-			if (netif_msg_tx_err(priv))
-				mlx4_warn(mdev, "LSO header size too big\n");
-			dev_kfree_skb_any(skb);
-			return 0;
-		}
 	} else {
 		*lso_header_size = 0;
 		if (!is_inline(skb, NULL))
@@ -617,21 +573,20 @@
 	tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
 }
 
-static int get_vlan_info(struct mlx4_en_priv *priv, struct sk_buff *skb,
-			 u16 *vlan_tag)
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
-	int tx_ind;
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	u16 vlan_tag = 0;
 
-	/* Obtain VLAN information if present */
-	if (priv->vlgrp && vlan_tx_tag_present(skb)) {
-		*vlan_tag = vlan_tx_tag_get(skb);
-		/* Set the Tx ring to use according to vlan priority */
-		tx_ind = priv->tx_prio_map[*vlan_tag >> 13];
-	} else {
-		*vlan_tag = 0;
-		tx_ind = 0;
+	/* If we support per priority flow control and the packet contains
+	 * a vlan tag, send the packet to the TX ring assigned to that priority
+	 */
+	if (priv->prof->rx_ppp && priv->vlgrp && vlan_tx_tag_present(skb)) {
+		vlan_tag = vlan_tx_tag_get(skb);
+		return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13);
 	}
-	return tx_ind;
+
+	return skb_tx_hash(dev, skb);
 }
 
 int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -651,38 +606,34 @@
 	dma_addr_t dma;
 	u32 index;
 	__be32 op_own;
-	u16 vlan_tag;
+	u16 vlan_tag = 0;
 	int i;
 	int lso_header_size;
 	void *fragptr;
 
-	if (unlikely(!skb->len)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
 	real_size = get_real_size(skb, dev, &lso_header_size);
 	if (unlikely(!real_size))
-		return NETDEV_TX_OK;
+		goto tx_drop;
 
 	/* Allign descriptor to TXBB size */
 	desc_size = ALIGN(real_size, TXBB_SIZE);
 	nr_txbb = desc_size / TXBB_SIZE;
 	if (unlikely(nr_txbb > MAX_DESC_TXBBS)) {
 		if (netif_msg_tx_err(priv))
-			mlx4_warn(mdev, "Oversized header or SG list\n");
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
+			en_warn(priv, "Oversized header or SG list\n");
+		goto tx_drop;
 	}
 
-	tx_ind = get_vlan_info(priv, skb, &vlan_tag);
+	tx_ind = skb->queue_mapping;
 	ring = &priv->tx_ring[tx_ind];
+	if (priv->vlgrp && vlan_tx_tag_present(skb))
+		vlan_tag = vlan_tx_tag_get(skb);
 
 	/* Check available TXBBs And 2K spare for prefetch */
 	if (unlikely(((int)(ring->prod - ring->cons)) >
 		     ring->size - HEADROOM - MAX_DESC_TXBBS)) {
-		/* every full Tx ring stops queue.
-		 * TODO: implement multi-queue support (per-queue stop) */
-		netif_stop_queue(dev);
+		/* every full Tx ring stops queue */
+		netif_tx_stop_queue(netdev_get_tx_queue(dev, tx_ind));
 		ring->blocked = 1;
 		priv->port_stats.queue_stopped++;
 
@@ -692,14 +643,6 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	/* Now that we know what Tx ring to use */
-	if (unlikely(!priv->port_up)) {
-		if (netif_msg_tx_err(priv))
-			mlx4_warn(mdev, "xmit: port down!\n");
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
 	/* Track current inflight packets for performance analysis */
 	AVG_PERF_COUNTER(priv->pstats.inflight_avg,
 			 (u32) (ring->prod - ring->cons - 1));
@@ -819,11 +762,15 @@
 	/* Ring doorbell! */
 	wmb();
 	writel(ring->doorbell_qpn, mdev->uar_map + MLX4_SEND_DOORBELL);
-	dev->trans_start = jiffies;
 
 	/* Poll CQ here */
 	mlx4_en_xmit_poll(priv, tx_ind);
 
 	return 0;
+
+tx_drop:
+	dev_kfree_skb_any(skb);
+	priv->stats.tx_dropped++;
+	return NETDEV_TX_OK;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/eq.c linux-libre-2.6.31-gnu/drivers/net/mlx4/eq.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/eq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/eq.c	2009-09-09 18:13:59.000000000 -0400
@@ -497,8 +497,10 @@
 	if (eq_table->have_irq)
 		free_irq(dev->pdev->irq, dev);
 	for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
-		if (eq_table->eq[i].have_irq)
+		if (eq_table->eq[i].have_irq) {
 			free_irq(eq_table->eq[i].irq, eq_table->eq + i);
+			eq_table->eq[i].have_irq = 0;
+		}
 
 	kfree(eq_table->irq_names);
 }
@@ -623,8 +625,10 @@
 		err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE,
 				     (dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
 				     &priv->eq_table.eq[i]);
-		if (err)
+		if (err) {
+			--i;
 			goto err_out_unmap;
+		}
 	}
 
 	err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE,
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/main.c linux-libre-2.6.31-gnu/drivers/net/mlx4/main.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -100,6 +100,10 @@
 MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports "
 		  "(0/1, default 0)");
 
+static int log_mtts_per_seg = ilog2(MLX4_MTT_ENTRY_PER_SEG);
+module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
+MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-5)");
+
 int mlx4_check_port_params(struct mlx4_dev *dev,
 			   enum mlx4_port_type *port_type)
 {
@@ -203,12 +207,13 @@
 	dev->caps.max_cqes	     = dev_cap->max_cq_sz - 1;
 	dev->caps.reserved_cqs	     = dev_cap->reserved_cqs;
 	dev->caps.reserved_eqs	     = dev_cap->reserved_eqs;
+	dev->caps.mtts_per_seg	     = 1 << log_mtts_per_seg;
 	dev->caps.reserved_mtts	     = DIV_ROUND_UP(dev_cap->reserved_mtts,
-						    MLX4_MTT_ENTRY_PER_SEG);
+						    dev->caps.mtts_per_seg);
 	dev->caps.reserved_mrws	     = dev_cap->reserved_mrws;
 	dev->caps.reserved_uars	     = dev_cap->reserved_uars;
 	dev->caps.reserved_pds	     = dev_cap->reserved_pds;
-	dev->caps.mtt_entry_sz	     = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz;
+	dev->caps.mtt_entry_sz	     = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz;
 	dev->caps.max_msg_sz         = dev_cap->max_msg_sz;
 	dev->caps.page_size_cap	     = ~(u32) (dev_cap->min_page_sz - 1);
 	dev->caps.flags		     = dev_cap->flags;
@@ -724,7 +729,10 @@
 
 	err = mlx4_QUERY_FW(dev);
 	if (err) {
-		mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
+		if (err == -EACCES)
+			mlx4_info(dev, "non-primary physical function, skipping.\n");
+		else
+			mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
 		return err;
 	}
 
@@ -1280,6 +1288,7 @@
 	{ PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
 	{ PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
 	{ PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
+	{ PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
 	{ 0, }
 };
 
@@ -1304,6 +1313,11 @@
 		return -1;
 	}
 
+	if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 5)) {
+		printk(KERN_WARNING "mlx4_core: bad log_mtts_per_seg: %d\n", log_mtts_per_seg);
+		return -1;
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/Makefile linux-libre-2.6.31-gnu/drivers/net/mlx4/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -5,5 +5,5 @@
 
 obj-$(CONFIG_MLX4_EN)               += mlx4_en.o
 
-mlx4_en-y := 	en_main.o en_tx.o en_rx.o en_params.o en_port.o en_cq.o \
+mlx4_en-y := 	en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
 		en_resources.o en_netdev.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/mlx4_en.h linux-libre-2.6.31-gnu/drivers/net/mlx4/mlx4_en.h
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/mlx4_en.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/mlx4_en.h	2009-09-09 18:13:59.000000000 -0400
@@ -49,26 +49,42 @@
 #include "en_port.h"
 
 #define DRV_NAME	"mlx4_en"
-#define DRV_VERSION	"1.4.0"
-#define DRV_RELDATE	"Sep 2008"
+#define DRV_VERSION	"1.4.1.1"
+#define DRV_RELDATE	"June 2009"
 
 
 #define MLX4_EN_MSG_LEVEL	(NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
 
-#define mlx4_dbg(mlevel, priv, format, arg...)	\
-	if (NETIF_MSG_##mlevel & priv->msg_enable) \
-	printk(KERN_DEBUG "%s %s: " format , DRV_NAME ,\
-		(dev_name(&priv->mdev->pdev->dev)) , ## arg)
+#define en_print(level, priv, format, arg...)			\
+	{							\
+	if ((priv)->registered)					\
+		printk(level "%s: %s: " format, DRV_NAME,	\
+			(priv->dev)->name, ## arg);		\
+	else							\
+		printk(level "%s: %s: Port %d: " format,	\
+			DRV_NAME, dev_name(&priv->mdev->pdev->dev), \
+			(priv)->port, ## arg);			\
+	}
+
+#define en_dbg(mlevel, priv, format, arg...)			\
+	{							\
+	if (NETIF_MSG_##mlevel & priv->msg_enable)		\
+		en_print(KERN_DEBUG, priv, format, ## arg)	\
+	}
+#define en_warn(priv, format, arg...)				\
+	en_print(KERN_WARNING, priv, format, ## arg)
+#define en_err(priv, format, arg...)				\
+	en_print(KERN_ERR, priv, format, ## arg)
 
 #define mlx4_err(mdev, format, arg...) \
 	printk(KERN_ERR "%s %s: " format , DRV_NAME ,\
-		(dev_name(&mdev->pdev->dev)) , ## arg)
+		dev_name(&mdev->pdev->dev) , ## arg)
 #define mlx4_info(mdev, format, arg...) \
 	printk(KERN_INFO "%s %s: " format , DRV_NAME ,\
-		(dev_name(&mdev->pdev->dev)) , ## arg)
+		dev_name(&mdev->pdev->dev) , ## arg)
 #define mlx4_warn(mdev, format, arg...) \
 	printk(KERN_WARNING "%s %s: " format , DRV_NAME ,\
-		(dev_name(&mdev->pdev->dev)) , ## arg)
+		dev_name(&mdev->pdev->dev) , ## arg)
 
 /*
  * Device constants
@@ -83,7 +99,6 @@
 #define RSS_FACTOR		2
 #define TXBB_SIZE		64
 #define HEADROOM		(2048 / TXBB_SIZE + 1)
-#define MAX_LSO_HDR_SIZE	92
 #define STAMP_STRIDE		64
 #define STAMP_DWORDS		(STAMP_STRIDE / 4)
 #define STAMP_SHIFT		31
@@ -123,12 +138,14 @@
 #define MLX4_EN_MIN_RX_SIZE	(MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES)
 #define MLX4_EN_MIN_TX_SIZE	(4096 / TXBB_SIZE)
 
-#define MLX4_EN_TX_RING_NUM		9
-#define MLX4_EN_DEF_TX_RING_SIZE	1024
+#define MLX4_EN_SMALL_PKT_SIZE		64
+#define MLX4_EN_NUM_TX_RINGS		8
+#define MLX4_EN_NUM_PPP_RINGS		8
+#define MLX4_EN_DEF_TX_RING_SIZE	512
 #define MLX4_EN_DEF_RX_RING_SIZE  	1024
 
-/* Target number of bytes to coalesce with interrupt moderation */
-#define MLX4_EN_RX_COAL_TARGET	0x20000
+/* Target number of packets to coalesce with interrupt moderation */
+#define MLX4_EN_RX_COAL_TARGET	44
 #define MLX4_EN_RX_COAL_TIME	0x10
 
 #define MLX4_EN_TX_COAL_PKTS	5
@@ -278,8 +295,6 @@
 	u32 prod;
 	u32 cons;
 	u32 buf_size;
-	int need_refill;
-	int full;
 	void *buf;
 	void *rx_info;
 	unsigned long bytes;
@@ -462,7 +477,6 @@
 	int base_qpn;
 
 	struct mlx4_en_rss_map rss_map;
-	u16 tx_prio_map[8];
 	u32 flags;
 #define MLX4_EN_FLAG_PROMISC	0x1
 	u32 tx_ring_num;
@@ -478,7 +492,6 @@
 	struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
 	struct work_struct mcast_task;
 	struct work_struct mac_task;
-	struct delayed_work refill_task;
 	struct work_struct watchdog_task;
 	struct work_struct linkstate_task;
 	struct delayed_work stats_task;
@@ -500,8 +513,6 @@
 void mlx4_en_free_resources(struct mlx4_en_priv *priv);
 int mlx4_en_alloc_resources(struct mlx4_en_priv *priv);
 
-int mlx4_en_get_profile(struct mlx4_en_dev *mdev);
-
 int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
 		      int entries, int ring, enum cq_type mode);
 void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
@@ -512,6 +523,7 @@
 
 void mlx4_en_poll_tx_cq(unsigned long data);
 void mlx4_en_tx_irq(struct mlx4_cq *mcq);
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb);
 int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring,
@@ -546,11 +558,9 @@
 void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv,
 				 struct mlx4_en_rss_map *rss_map,
 				 int num_entries, int num_rings);
-void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num);
 int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
 void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
 int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
-void mlx4_en_rx_refill(struct work_struct *work);
 void mlx4_en_rx_irq(struct mlx4_cq *mcq);
 
 int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/mr.c linux-libre-2.6.31-gnu/drivers/net/mlx4/mr.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/mr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/mr.c	2009-09-09 18:13:59.000000000 -0400
@@ -209,7 +209,7 @@
 	} else
 		mtt->page_shift = page_shift;
 
-	for (mtt->order = 0, i = MLX4_MTT_ENTRY_PER_SEG; i < npages; i <<= 1)
+	for (mtt->order = 0, i = dev->caps.mtts_per_seg; i < npages; i <<= 1)
 		++mtt->order;
 
 	mtt->first_seg = mlx4_alloc_mtt_range(dev, mtt->order);
@@ -350,7 +350,7 @@
 		mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG |
 						   MLX4_MPT_PD_FLAG_RAE);
 		mpt_entry->mtt_sz    = cpu_to_be32((1 << mr->mtt.order) *
-						   MLX4_MTT_ENTRY_PER_SEG);
+						   dev->caps.mtts_per_seg);
 	} else {
 		mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
 	}
@@ -391,7 +391,7 @@
 	    (start_index + npages - 1) / (PAGE_SIZE / sizeof (u64)))
 		return -EINVAL;
 
-	if (start_index & (MLX4_MTT_ENTRY_PER_SEG - 1))
+	if (start_index & (dev->caps.mtts_per_seg - 1))
 		return -EINVAL;
 
 	mtts = mlx4_table_find(&priv->mr_table.mtt_table, mtt->first_seg +
@@ -399,10 +399,14 @@
 	if (!mtts)
 		return -ENOMEM;
 
+	dma_sync_single_for_cpu(&dev->pdev->dev, dma_handle,
+				npages * sizeof (u64), DMA_TO_DEVICE);
+
 	for (i = 0; i < npages; ++i)
 		mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT);
 
-	dma_sync_single(&dev->pdev->dev, dma_handle, npages * sizeof (u64), DMA_TO_DEVICE);
+	dma_sync_single_for_device(&dev->pdev->dev, dma_handle,
+				   npages * sizeof (u64), DMA_TO_DEVICE);
 
 	return 0;
 }
@@ -546,11 +550,14 @@
 	/* Make sure MPT status is visible before writing MTT entries */
 	wmb();
 
+	dma_sync_single_for_cpu(&dev->pdev->dev, fmr->dma_handle,
+				npages * sizeof(u64), DMA_TO_DEVICE);
+
 	for (i = 0; i < npages; ++i)
 		fmr->mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT);
 
-	dma_sync_single(&dev->pdev->dev, fmr->dma_handle,
-			npages * sizeof(u64), DMA_TO_DEVICE);
+	dma_sync_single_for_device(&dev->pdev->dev, fmr->dma_handle,
+				   npages * sizeof(u64), DMA_TO_DEVICE);
 
 	fmr->mpt->key    = cpu_to_be32(key);
 	fmr->mpt->lkey   = cpu_to_be32(key);
diff -druN linux-libre-2.6.30-gnu/drivers/net/mlx4/profile.c linux-libre-2.6.31-gnu/drivers/net/mlx4/profile.c
--- linux-libre-2.6.30-gnu/drivers/net/mlx4/profile.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mlx4/profile.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,7 +98,7 @@
 	profile[MLX4_RES_EQ].size     = dev_cap->eqc_entry_sz;
 	profile[MLX4_RES_DMPT].size   = dev_cap->dmpt_entry_sz;
 	profile[MLX4_RES_CMPT].size   = dev_cap->cmpt_entry_sz;
-	profile[MLX4_RES_MTT].size    = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz;
+	profile[MLX4_RES_MTT].size    = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz;
 	profile[MLX4_RES_MCG].size    = MLX4_MGM_ENTRY_SIZE;
 
 	profile[MLX4_RES_QP].num      = request->num_qp;
diff -druN linux-libre-2.6.30-gnu/drivers/net/mv643xx_eth.c linux-libre-2.6.31-gnu/drivers/net/mv643xx_eth.c
--- linux-libre-2.6.30-gnu/drivers/net/mv643xx_eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mv643xx_eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -55,6 +55,7 @@
 #include <linux/types.h>
 #include <linux/inet_lro.h>
 #include <asm/system.h>
+#include <linux/list.h>
 
 static char mv643xx_eth_driver_name[] = "mv643xx_eth";
 static char mv643xx_eth_driver_version[] = "1.4";
@@ -88,7 +89,24 @@
 #define MAC_ADDR_LOW			0x0014
 #define MAC_ADDR_HIGH			0x0018
 #define SDMA_CONFIG			0x001c
+#define  TX_BURST_SIZE_16_64BIT		0x01000000
+#define  TX_BURST_SIZE_4_64BIT		0x00800000
+#define  BLM_TX_NO_SWAP			0x00000020
+#define  BLM_RX_NO_SWAP			0x00000010
+#define  RX_BURST_SIZE_16_64BIT		0x00000008
+#define  RX_BURST_SIZE_4_64BIT		0x00000004
 #define PORT_SERIAL_CONTROL		0x003c
+#define  SET_MII_SPEED_TO_100		0x01000000
+#define  SET_GMII_SPEED_TO_1000		0x00800000
+#define  SET_FULL_DUPLEX_MODE		0x00200000
+#define  MAX_RX_PACKET_9700BYTE		0x000a0000
+#define  DISABLE_AUTO_NEG_SPEED_GMII	0x00002000
+#define  DO_NOT_FORCE_LINK_FAIL		0x00000400
+#define  SERIAL_PORT_CONTROL_RESERVED	0x00000200
+#define  DISABLE_AUTO_NEG_FOR_FLOW_CTRL	0x00000008
+#define  DISABLE_AUTO_NEG_FOR_DUPLEX	0x00000004
+#define  FORCE_LINK_PASS		0x00000002
+#define  SERIAL_PORT_ENABLE		0x00000001
 #define PORT_STATUS			0x0044
 #define  TX_FIFO_EMPTY			0x00000400
 #define  TX_IN_PROGRESS			0x00000080
@@ -106,7 +124,9 @@
 #define TX_BW_BURST			0x005c
 #define INT_CAUSE			0x0060
 #define  INT_TX_END			0x07f80000
+#define  INT_TX_END_0			0x00080000
 #define  INT_RX				0x000003fc
+#define  INT_RX_0			0x00000004
 #define  INT_EXT			0x00000002
 #define INT_CAUSE_EXT			0x0064
 #define  INT_EXT_LINK_PHY		0x00110000
@@ -135,15 +155,8 @@
 
 
 /*
- * SDMA configuration register.
+ * SDMA configuration register default value.
  */
-#define RX_BURST_SIZE_4_64BIT		(2 << 1)
-#define RX_BURST_SIZE_16_64BIT		(4 << 1)
-#define BLM_RX_NO_SWAP			(1 << 4)
-#define BLM_TX_NO_SWAP			(1 << 5)
-#define TX_BURST_SIZE_4_64BIT		(2 << 22)
-#define TX_BURST_SIZE_16_64BIT		(4 << 22)
-
 #if defined(__BIG_ENDIAN)
 #define PORT_SDMA_CONFIG_DEFAULT_VALUE		\
 		(RX_BURST_SIZE_4_64BIT	|	\
@@ -160,22 +173,11 @@
 
 
 /*
- * Port serial control register.
+ * Misc definitions.
  */
-#define SET_MII_SPEED_TO_100			(1 << 24)
-#define SET_GMII_SPEED_TO_1000			(1 << 23)
-#define SET_FULL_DUPLEX_MODE			(1 << 21)
-#define MAX_RX_PACKET_9700BYTE			(5 << 17)
-#define DISABLE_AUTO_NEG_SPEED_GMII		(1 << 13)
-#define DO_NOT_FORCE_LINK_FAIL			(1 << 10)
-#define SERIAL_PORT_CONTROL_RESERVED		(1 << 9)
-#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL		(1 << 3)
-#define DISABLE_AUTO_NEG_FOR_DUPLEX		(1 << 2)
-#define FORCE_LINK_PASS				(1 << 1)
-#define SERIAL_PORT_ENABLE			(1 << 0)
-
-#define DEFAULT_RX_QUEUE_SIZE		128
-#define DEFAULT_TX_QUEUE_SIZE		256
+#define DEFAULT_RX_QUEUE_SIZE	128
+#define DEFAULT_TX_QUEUE_SIZE	256
+#define SKB_DMA_REALIGN		((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES)
 
 
 /*
@@ -393,6 +395,7 @@
 	struct work_struct tx_timeout_task;
 
 	struct napi_struct napi;
+	u32 int_mask;
 	u8 oom;
 	u8 work_link;
 	u8 work_tx;
@@ -651,23 +654,20 @@
 	refilled = 0;
 	while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) {
 		struct sk_buff *skb;
-		int unaligned;
 		int rx;
 		struct rx_desc *rx_desc;
 
 		skb = __skb_dequeue(&mp->rx_recycle);
 		if (skb == NULL)
-			skb = dev_alloc_skb(mp->skb_size +
-					    dma_get_cache_alignment() - 1);
+			skb = dev_alloc_skb(mp->skb_size);
 
 		if (skb == NULL) {
 			mp->oom = 1;
 			goto oom;
 		}
 
-		unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1);
-		if (unaligned)
-			skb_reserve(skb, dma_get_cache_alignment() - unaligned);
+		if (SKB_DMA_REALIGN)
+			skb_reserve(skb, SKB_DMA_REALIGN);
 
 		refilled++;
 		rxq->rx_desc_count++;
@@ -969,8 +969,7 @@
 		if (skb != NULL) {
 			if (skb_queue_len(&mp->rx_recycle) <
 					mp->rx_ring_size &&
-			    skb_recycle_check(skb, mp->skb_size +
-					dma_get_cache_alignment() - 1))
+			    skb_recycle_check(skb, mp->skb_size))
 				__skb_queue_head(&mp->rx_recycle, skb);
 			else
 				dev_kfree_skb(skb);
@@ -1723,20 +1722,20 @@
 
 static u32 uc_addr_filter_mask(struct net_device *dev)
 {
-	struct dev_addr_list *uc_ptr;
+	struct netdev_hw_addr *ha;
 	u32 nibbles;
 
 	if (dev->flags & IFF_PROMISC)
 		return 0;
 
 	nibbles = 1 << (dev->dev_addr[5] & 0x0f);
-	for (uc_ptr = dev->uc_list; uc_ptr != NULL; uc_ptr = uc_ptr->next) {
-		if (memcmp(dev->dev_addr, uc_ptr->da_addr, 5))
+	list_for_each_entry(ha, &dev->uc.list, list) {
+		if (memcmp(dev->dev_addr, ha->addr, 5))
 			return 0;
-		if ((dev->dev_addr[5] ^ uc_ptr->da_addr[5]) & 0xf0)
+		if ((dev->dev_addr[5] ^ ha->addr[5]) & 0xf0)
 			return 0;
 
-		nibbles |= 1 << (uc_ptr->da_addr[5] & 0x0f);
+		nibbles |= 1 << (ha->addr[5] & 0x0f);
 	}
 
 	return nibbles;
@@ -1751,12 +1750,12 @@
 
 	uc_addr_set(mp, dev->dev_addr);
 
-	port_config = rdlp(mp, PORT_CONFIG);
+	port_config = rdlp(mp, PORT_CONFIG) & ~UNICAST_PROMISCUOUS_MODE;
+
 	nibbles = uc_addr_filter_mask(dev);
 	if (!nibbles) {
 		port_config |= UNICAST_PROMISCUOUS_MODE;
-		wrlp(mp, PORT_CONFIG, port_config);
-		return;
+		nibbles = 0xffff;
 	}
 
 	for (i = 0; i < 16; i += 4) {
@@ -1777,7 +1776,6 @@
 		wrl(mp, off, v);
 	}
 
-	port_config &= ~UNICAST_PROMISCUOUS_MODE;
 	wrlp(mp, PORT_CONFIG, port_config);
 }
 
@@ -1810,7 +1808,6 @@
 	if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
 		int port_num;
 		u32 accept;
-		int i;
 
 oom:
 		port_num = mp->port_num;
@@ -2067,15 +2064,16 @@
 	u32 int_cause;
 	u32 int_cause_ext;
 
-	int_cause = rdlp(mp, INT_CAUSE) & (INT_TX_END | INT_RX | INT_EXT);
+	int_cause = rdlp(mp, INT_CAUSE) & mp->int_mask;
 	if (int_cause == 0)
 		return 0;
 
 	int_cause_ext = 0;
-	if (int_cause & INT_EXT)
+	if (int_cause & INT_EXT) {
+		int_cause &= ~INT_EXT;
 		int_cause_ext = rdlp(mp, INT_CAUSE_EXT);
+	}
 
-	int_cause &= INT_TX_END | INT_RX;
 	if (int_cause) {
 		wrlp(mp, INT_CAUSE, ~int_cause);
 		mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) &
@@ -2182,6 +2180,7 @@
 		if (mp->work_link) {
 			mp->work_link = 0;
 			handle_link_event(mp);
+			work_done++;
 			continue;
 		}
 
@@ -2220,7 +2219,7 @@
 		if (mp->oom)
 			mod_timer(&mp->rx_oom, jiffies + (HZ / 10));
 		napi_complete(napi);
-		wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
+		wrlp(mp, INT_MASK, mp->int_mask);
 	}
 
 	return work_done;
@@ -2341,6 +2340,14 @@
 	 * size field are ignored by the hardware.
 	 */
 	mp->skb_size = (skb_size + 7) & ~7;
+
+	/*
+	 * If NET_SKB_PAD is smaller than a cache line,
+	 * netdev_alloc_skb() will cause skb->data to be misaligned
+	 * to a cache line boundary.  If this is the case, include
+	 * some extra space to allow re-aligning the data area.
+	 */
+	mp->skb_size += SKB_DMA_REALIGN;
 }
 
 static int mv643xx_eth_open(struct net_device *dev)
@@ -2366,6 +2373,8 @@
 
 	skb_queue_head_init(&mp->rx_recycle);
 
+	mp->int_mask = INT_EXT;
+
 	for (i = 0; i < mp->rxq_count; i++) {
 		err = rxq_init(mp, i);
 		if (err) {
@@ -2375,6 +2384,7 @@
 		}
 
 		rxq_refill(mp->rxq + i, INT_MAX);
+		mp->int_mask |= INT_RX_0 << i;
 	}
 
 	if (mp->oom) {
@@ -2389,12 +2399,13 @@
 				txq_deinit(mp->txq + i);
 			goto out_free;
 		}
+		mp->int_mask |= INT_TX_END_0 << i;
 	}
 
 	port_start(mp);
 
 	wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX);
-	wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
+	wrlp(mp, INT_MASK, mp->int_mask);
 
 	return 0;
 
@@ -2538,7 +2549,7 @@
 
 	mv643xx_eth_irq(dev->irq, dev);
 
-	wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
+	wrlp(mp, INT_MASK, mp->int_mask);
 }
 #endif
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/mvme147.c linux-libre-2.6.31-gnu/drivers/net/mvme147.c
--- linux-libre-2.6.30-gnu/drivers/net/mvme147.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/mvme147.c	2009-09-09 18:13:59.000000000 -0400
@@ -57,6 +57,17 @@
 typedef void (*writerdp_t)(void *, unsigned short);
 typedef unsigned short (*readrdp_t)(void *);
 
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open		= m147lance_open,
+	.ndo_stop		= m147lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_multicast_list	= lance_set_multicast,
+	.ndo_tx_timeout		= lance_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
 /* Initialise the one and only on-board 7990 */
 struct net_device * __init mvme147lance_probe(int unit)
 {
@@ -81,11 +92,7 @@
 
 	/* Fill the dev fields */
 	dev->base_addr = (unsigned long)MVME147_LANCE_BASE;
-	dev->open = &m147lance_open;
-	dev->stop = &m147lance_close;
-	dev->hard_start_xmit = &lance_start_xmit;
-	dev->set_multicast_list = &lance_set_multicast;
-	dev->tx_timeout = &lance_tx_timeout;
+	dev->netdev_ops = &lance_netdev_ops;
 	dev->dma = 0;
 
 	addr=(u_long *)ETHERNET_ADDRESS;
diff -druN linux-libre-2.6.30-gnu/drivers/net/myri10ge/myri10ge.c linux-libre-2.6.31-gnu/drivers/net/myri10ge/myri10ge.c
--- linux-libre-2.6.30-gnu/drivers/net/myri10ge/myri10ge.c	2012-03-22 19:15:07.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/myri10ge/myri10ge.c	2012-03-22 20:11:13.000000000 -0400
@@ -75,7 +75,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.4.4-1.401"
+#define MYRI10GE_VERSION_STR "1.5.0-1.418"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -255,6 +255,7 @@
 	u32 read_write_dma;
 	u32 link_changes;
 	u32 msg_enable;
+	unsigned int board_number;
 };
 
 static char *myri10ge_fw_unaligned = "/*(DEBLOBBED)*/";
@@ -266,6 +267,13 @@
 module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name");
 
+#define MYRI10GE_MAX_BOARDS 8
+static char *myri10ge_fw_names[MYRI10GE_MAX_BOARDS] =
+    {[0 ... (MYRI10GE_MAX_BOARDS - 1)] = NULL };
+module_param_array_named(myri10ge_fw_names, myri10ge_fw_names, charp, NULL,
+			 0444);
+MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image names per board");
+
 static int myri10ge_ecrc_enable = 1;
 module_param(myri10ge_ecrc_enable, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E");
@@ -319,10 +327,6 @@
 module_param(myri10ge_debug, int, 0);
 MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
 
-static int myri10ge_lro = 1;
-module_param(myri10ge_lro, int, S_IRUGO);
-MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload");
-
 static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS;
 module_param(myri10ge_lro_max_pkts, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_lro_max_pkts,
@@ -361,6 +365,8 @@
 	__raw_writel((__force __u32) val, (__force void __iomem *)p);
 }
 
+static struct net_device_stats *myri10ge_get_stats(struct net_device *dev);
+
 static int
 myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
 		  struct myri10ge_cmd *data, int atomic)
@@ -1290,7 +1296,7 @@
 		remainder -= MYRI10GE_ALLOC_SIZE;
 	}
 
-	if (mgp->csum_flag && myri10ge_lro) {
+	if (dev->features & NETIF_F_LRO) {
 		rx_frags[0].page_offset += MXGEFW_PAD;
 		rx_frags[0].size -= MXGEFW_PAD;
 		len -= MXGEFW_PAD;
@@ -1412,6 +1418,7 @@
 {
 	struct myri10ge_rx_done *rx_done = &ss->rx_done;
 	struct myri10ge_priv *mgp = ss->mgp;
+	struct net_device *netdev = mgp->dev;
 	unsigned long rx_bytes = 0;
 	unsigned long rx_packets = 0;
 	unsigned long rx_ok;
@@ -1445,7 +1452,7 @@
 	ss->stats.rx_packets += rx_packets;
 	ss->stats.rx_bytes += rx_bytes;
 
-	if (myri10ge_lro)
+	if (netdev->features & NETIF_F_LRO)
 		lro_flush_all(&rx_done->lro_mgr);
 
 	/* restock receive rings if needed */
@@ -1686,7 +1693,7 @@
 	ring->rx_mini_max_pending = mgp->ss[0].rx_small.mask + 1;
 	ring->rx_max_pending = mgp->ss[0].rx_big.mask + 1;
 	ring->rx_jumbo_max_pending = 0;
-	ring->tx_max_pending = mgp->ss[0].rx_small.mask + 1;
+	ring->tx_max_pending = mgp->ss[0].tx.mask + 1;
 	ring->rx_mini_pending = ring->rx_mini_max_pending;
 	ring->rx_pending = ring->rx_max_pending;
 	ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
@@ -1706,12 +1713,17 @@
 static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
 {
 	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	int err = 0;
 
 	if (csum_enabled)
 		mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
-	else
+	else {
+		u32 flags = ethtool_op_get_flags(netdev);
+		err = ethtool_op_set_flags(netdev, (flags & ~ETH_FLAG_LRO));
 		mgp->csum_flag = 0;
-	return 0;
+
+	}
+	return err;
 }
 
 static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
@@ -1803,6 +1815,8 @@
 	int slice;
 	int i;
 
+	/* force stats update */
+	(void)myri10ge_get_stats(netdev);
 	for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
 		data[i] = ((unsigned long *)&mgp->stats)[i];
 
@@ -1892,7 +1906,9 @@
 	.get_sset_count = myri10ge_get_sset_count,
 	.get_ethtool_stats = myri10ge_get_ethtool_stats,
 	.set_msglevel = myri10ge_set_msglevel,
-	.get_msglevel = myri10ge_get_msglevel
+	.get_msglevel = myri10ge_get_msglevel,
+	.get_flags = ethtool_op_get_flags,
+	.set_flags = ethtool_op_set_flags
 };
 
 static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
@@ -2671,7 +2687,7 @@
 		/* we are out of transmit resources */
 		tx->stop_queue++;
 		netif_tx_stop_queue(netdev_queue);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Setup checksum offloading, if needed */
@@ -2876,7 +2892,6 @@
 		tx->stop_queue++;
 		netif_tx_stop_queue(netdev_queue);
 	}
-	dev->trans_start = jiffies;
 	return 0;
 
 abort_linearize:
@@ -2969,6 +2984,7 @@
 	struct net_device_stats *stats = &mgp->stats;
 	int i;
 
+	spin_lock(&mgp->stats_lock);
 	memset(stats, 0, sizeof(*stats));
 	for (i = 0; i < mgp->num_slices; i++) {
 		slice_stats = &mgp->ss[i].stats;
@@ -2979,6 +2995,7 @@
 		stats->rx_dropped += slice_stats->rx_dropped;
 		stats->tx_dropped += slice_stats->tx_dropped;
 	}
+	spin_unlock(&mgp->stats_lock);
 	return stats;
 }
 
@@ -3246,6 +3263,8 @@
 
 static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
 {
+	int overridden = 0;
+
 	if (myri10ge_force_firmware == 0) {
 		int link_width, exp_cap;
 		u16 lnk;
@@ -3279,10 +3298,18 @@
 		}
 	}
 	if (myri10ge_fw_name != NULL) {
-		dev_info(&mgp->pdev->dev, "overriding firmware to %s\n",
-			 myri10ge_fw_name);
+		overridden = 1;
 		mgp->fw_name = myri10ge_fw_name;
 	}
+	if (mgp->board_number < MYRI10GE_MAX_BOARDS &&
+	    myri10ge_fw_names[mgp->board_number] != NULL &&
+	    strlen(myri10ge_fw_names[mgp->board_number])) {
+		mgp->fw_name = myri10ge_fw_names[mgp->board_number];
+		overridden = 1;
+	}
+	if (overridden)
+		dev_info(&mgp->pdev->dev, "overriding firmware to %s\n",
+			 mgp->fw_name);
 }
 
 #ifdef CONFIG_PM
@@ -3747,6 +3774,7 @@
 	int status = -ENXIO;
 	int dac_enabled;
 	unsigned hdr_offset, ss_offset;
+	static int board_number;
 
 	netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
 	if (netdev == NULL) {
@@ -3763,6 +3791,7 @@
 	mgp->pause = myri10ge_flow_control;
 	mgp->intr_coal_delay = myri10ge_intr_coal_delay;
 	mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT);
+	mgp->board_number = board_number;
 	init_waitqueue_head(&mgp->down_wq);
 
 	if (pci_enable_device(pdev)) {
@@ -3877,6 +3906,13 @@
 
 	if (dac_enabled)
 		netdev->features |= NETIF_F_HIGHDMA;
+	netdev->features |= NETIF_F_LRO;
+
+	netdev->vlan_features |= mgp->features;
+	if (mgp->fw_ver_tiny < 37)
+		netdev->vlan_features &= ~NETIF_F_TSO6;
+	if (mgp->fw_ver_tiny < 32)
+		netdev->vlan_features &= ~NETIF_F_TSO;
 
 	/* make sure we can get an irq, and that MSI can be
 	 * setup (if available).  Also ensure netdev->irq
@@ -3895,6 +3931,7 @@
 	setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
 		    (unsigned long)mgp);
 
+	spin_lock_init(&mgp->stats_lock);
 	SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
 	INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
 	status = register_netdev(netdev);
@@ -3912,6 +3949,7 @@
 			 netdev->irq, mgp->tx_boundary, mgp->fw_name,
 			 (mgp->wc_enabled ? "Enabled" : "Disabled"));
 
+	board_number++;
 	return 0;
 
 abort_with_state:
@@ -4001,6 +4039,8 @@
 	{0},
 };
 
+MODULE_DEVICE_TABLE(pci, myri10ge_pci_tbl);
+
 static struct pci_driver myri10ge_driver = {
 	.name = "myri10ge",
 	.probe = myri10ge_probe,
diff -druN linux-libre-2.6.30-gnu/drivers/net/myri_sbus.c linux-libre-2.6.31-gnu/drivers/net/myri_sbus.c
--- linux-libre-2.6.30-gnu/drivers/net/myri_sbus.c	2012-03-22 19:15:00.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/myri_sbus.c	2012-03-22 20:11:10.000000000 -0400
@@ -640,7 +640,7 @@
 
 	if (!TX_BUFFS_AVAIL(head, tail)) {
 		DTX(("no buffs available, returning 1\n"));
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	spin_lock_irqsave(&mp->irq_lock, flags);
diff -druN linux-libre-2.6.30-gnu/drivers/net/natsemi.c linux-libre-2.6.31-gnu/drivers/net/natsemi.c
--- linux-libre-2.6.30-gnu/drivers/net/natsemi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/natsemi.c	2009-09-09 18:13:59.000000000 -0400
@@ -130,8 +130,8 @@
 static const char version[] __devinitconst =
   KERN_INFO DRV_NAME " dp8381x driver, version "
       DRV_VERSION ", " DRV_RELDATE "\n"
-  KERN_INFO "  originally by Donald Becker <becker@scyld.com>\n"
-  KERN_INFO "  2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";
+  "  originally by Donald Becker <becker@scyld.com>\n"
+  "  2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver");
diff -druN linux-libre-2.6.30-gnu/drivers/net/ne2k-pci.c linux-libre-2.6.31-gnu/drivers/net/ne2k-pci.c
--- linux-libre-2.6.30-gnu/drivers/net/ne2k-pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ne2k-pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -374,7 +374,7 @@
 	dev->ethtool_ops = &ne2k_pci_ethtool_ops;
 	NS8390_init(dev, 0);
 
-	memcpy(dev->dev_addr, SA_prom, 6);
+	memcpy(dev->dev_addr, SA_prom, dev->addr_len);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	i = register_netdev(dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ne3210.c linux-libre-2.6.31-gnu/drivers/net/ne3210.c
--- linux-libre-2.6.30-gnu/drivers/net/ne3210.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ne3210.c	2009-09-09 18:13:59.000000000 -0400
@@ -104,7 +104,7 @@
 	}
 
 	SET_NETDEV_DEV(dev, device);
-	device->driver_data = dev;
+	dev_set_drvdata(device, dev);
 	ioaddr = edev->base_addr;
 
 	if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) {
@@ -225,7 +225,7 @@
 
 static int __devexit ne3210_eisa_remove (struct device *device)
 {
-	struct net_device  *dev    = device->driver_data;
+	struct net_device  *dev    = dev_get_drvdata(device);
 	unsigned long       ioaddr = to_eisa_device (device)->base_addr;
 
 	unregister_netdev (dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ne.c linux-libre-2.6.31-gnu/drivers/net/ne.c
--- linux-libre-2.6.30-gnu/drivers/net/ne.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ne.c	2009-09-09 18:13:59.000000000 -0400
@@ -321,7 +321,7 @@
 	}
 
 	if (ei_debug  &&  version_printed++ == 0)
-		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
+		printk(KERN_INFO "%s%s", version1, version2);
 
 	printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_ctx.c linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_ctx.c
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_ctx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_ctx.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,8 +41,7 @@
 
 	for (;;) {
 		/* Acquire PCIE HW semaphore5 */
-		netxen_nic_read_w0(adapter,
-			NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done);
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_LOCK));
 
 		if (done == 1)
 			break;
@@ -56,7 +55,7 @@
 	}
 
 #if 0
-	netxen_nic_write_w1(adapter,
+	NXWR32(adapter,
 		NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
 #endif
 	return 0;
@@ -65,11 +64,8 @@
 static int
 netxen_api_unlock(struct netxen_adapter *adapter)
 {
-	u32 val;
-
 	/* Release PCIE HW semaphore5 */
-	netxen_nic_read_w0(adapter,
-		NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
+	NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK));
 	return 0;
 }
 
@@ -86,7 +82,7 @@
 		if (++timeout > NX_OS_CRB_RETRY_COUNT)
 			return NX_CDRP_RSP_TIMEOUT;
 
-		netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp);
+		rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET);
 	} while (!NX_CDRP_IS_RSP(rsp));
 
 	return rsp;
@@ -106,16 +102,15 @@
 	if (netxen_api_lock(adapter))
 		return NX_RCODE_TIMEOUT;
 
-	netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature);
+	NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature);
 
-	netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1);
+	NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1);
 
-	netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2);
+	NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2);
 
-	netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3);
+	NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3);
 
-	netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
-			NX_CDRP_FORM_CMD(cmd));
+	NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd));
 
 	rsp = netxen_poll_rsp(adapter);
 
@@ -125,7 +120,7 @@
 
 		rcode = NX_RCODE_TIMEOUT;
 	} else if (rsp == NX_CDRP_RSP_FAIL) {
-		netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
+		rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET);
 
 		printk(KERN_ERR "%s: failed card response code:0x%x\n",
 				netxen_nic_driver_name, rcode);
@@ -328,6 +323,8 @@
 	int	err = 0;
 	u64	offset, phys_addr;
 	dma_addr_t	rq_phys_addr, rsp_phys_addr;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
 	rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
 	rq_addr = pci_alloc_consistent(adapter->pdev,
@@ -362,15 +359,13 @@
 
 	prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr);
 
-	offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx);
+	offset = recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx);
 	prq->cmd_cons_dma_addr = cpu_to_le64(offset);
 
 	prq_cds = &prq->cds_ring;
 
-	prq_cds->host_phys_addr =
-		cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
-
-	prq_cds->ring_size = cpu_to_le32(adapter->num_txd);
+	prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr);
+	prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
 
 	phys_addr = rq_phys_addr;
 	err = netxen_issue_cmd(adapter,
@@ -383,8 +378,7 @@
 
 	if (err == NX_RCODE_SUCCESS) {
 		temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
-		adapter->crb_addr_cmd_producer =
-			NETXEN_NIC_REG(temp - 0x200);
+		tx_ring->crb_cmd_producer = NETXEN_NIC_REG(temp - 0x200);
 #if 0
 		adapter->tx_state =
 			le32_to_cpu(prsp->host_ctx_state);
@@ -448,7 +442,19 @@
 			NETXEN_NIC_REG(0x120)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x138),
+		{
+			NETXEN_NIC_REG(0x138),
+			NETXEN_NIC_REG_2(0x000),
+			NETXEN_NIC_REG_2(0x004),
+			NETXEN_NIC_REG_2(0x008),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_0,
+			NETXEN_NIC_REG_2(0x044),
+			NETXEN_NIC_REG_2(0x048),
+			NETXEN_NIC_REG_2(0x04c),
+		},
 	},
 	/* Instance 1 */
 	{
@@ -461,7 +467,19 @@
 			NETXEN_NIC_REG(0x164)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x17c),
+		{
+			NETXEN_NIC_REG(0x17c),
+			NETXEN_NIC_REG_2(0x020),
+			NETXEN_NIC_REG_2(0x024),
+			NETXEN_NIC_REG_2(0x028),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_1,
+			NETXEN_NIC_REG_2(0x064),
+			NETXEN_NIC_REG_2(0x068),
+			NETXEN_NIC_REG_2(0x06c),
+		},
 	},
 	/* Instance 2 */
 	{
@@ -474,7 +492,19 @@
 			NETXEN_NIC_REG(0x208)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x220),
+		{
+			NETXEN_NIC_REG(0x220),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_2,
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
 	},
 	/* Instance 3 */
 	{
@@ -487,7 +517,19 @@
 			NETXEN_NIC_REG(0x24c)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x264),
+		{
+			NETXEN_NIC_REG(0x264),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_3,
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
 	},
 };
 
@@ -497,84 +539,91 @@
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
 	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
 	int ring;
-	int func_id = adapter->portnum;
-
-	adapter->ctx_desc->cmd_ring_addr =
-		cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
-	adapter->ctx_desc->cmd_ring_size =
-		cpu_to_le32(adapter->num_txd);
+	int port = adapter->portnum;
+	struct netxen_ring_ctx *hwctx;
+	u32 signature;
 
+	tx_ring = adapter->tx_ring;
 	recv_ctx = &adapter->recv_ctx;
+	hwctx = recv_ctx->hwctx;
+
+	hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr);
+	hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc);
+
 
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
 
-		adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+		hwctx->rcv_rings[ring].addr =
 			cpu_to_le64(rds_ring->phys_addr);
-		adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
+		hwctx->rcv_rings[ring].size =
 			cpu_to_le32(rds_ring->num_desc);
 	}
-	sds_ring = &recv_ctx->sds_rings[0];
-	adapter->ctx_desc->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr);
-	adapter->ctx_desc->sts_ring_size = cpu_to_le32(sds_ring->num_desc);
 
-	adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id),
-			lower32(adapter->ctx_desc_phys_addr));
-	adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id),
-			upper32(adapter->ctx_desc_phys_addr));
-	adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id),
-			NETXEN_CTX_SIGNATURE | func_id);
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+
+		if (ring == 0) {
+			hwctx->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr);
+			hwctx->sts_ring_size = cpu_to_le32(sds_ring->num_desc);
+		}
+		hwctx->sts_rings[ring].addr = cpu_to_le64(sds_ring->phys_addr);
+		hwctx->sts_rings[ring].size = cpu_to_le32(sds_ring->num_desc);
+		hwctx->sts_rings[ring].msi_index = cpu_to_le16(ring);
+	}
+	hwctx->sts_ring_count = cpu_to_le32(adapter->max_sds_rings);
+
+	signature = (adapter->max_sds_rings > 1) ?
+		NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE;
+
+	NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port),
+			lower32(recv_ctx->phys_addr));
+	NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port),
+			upper32(recv_ctx->phys_addr));
+	NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port),
+			signature | port);
 	return 0;
 }
 
-static uint32_t sw_int_mask[4] = {
-	CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
-	CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
-};
-
 int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
 {
-	struct netxen_hardware_context *hw = &adapter->ahw;
-	u32 state = 0;
 	void *addr;
 	int err = 0;
 	int ring;
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
 	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
 
 	struct pci_dev *pdev = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
+	int port = adapter->portnum;
 
-	err = netxen_receive_peg_ready(adapter);
-	if (err) {
-		printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
-				state);
-		return err;
-	}
+	recv_ctx = &adapter->recv_ctx;
+	tx_ring = adapter->tx_ring;
 
 	addr = pci_alloc_consistent(pdev,
 			sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
-			&adapter->ctx_desc_phys_addr);
-
+			&recv_ctx->phys_addr);
 	if (addr == NULL) {
 		dev_err(&pdev->dev, "failed to allocate hw context\n");
 		return -ENOMEM;
 	}
+
 	memset(addr, 0, sizeof(struct netxen_ring_ctx));
-	adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
-	adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
-	adapter->ctx_desc->cmd_consumer_offset =
-		cpu_to_le64(adapter->ctx_desc_phys_addr +
+	recv_ctx->hwctx = (struct netxen_ring_ctx *)addr;
+	recv_ctx->hwctx->ctx_id = cpu_to_le32(port);
+	recv_ctx->hwctx->cmd_consumer_offset =
+		cpu_to_le64(recv_ctx->phys_addr +
 			sizeof(struct netxen_ring_ctx));
-	adapter->cmd_consumer =
+	tx_ring->hw_consumer =
 		(__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));
 
 	/* cmd desc ring */
-	addr = pci_alloc_consistent(pdev,
-			TX_DESC_RINGSIZE(adapter),
-			&hw->cmd_desc_phys_addr);
+	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring),
+			&tx_ring->phys_addr);
 
 	if (addr == NULL) {
 		dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
@@ -582,9 +631,7 @@
 		return -ENOMEM;
 	}
 
-	hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
-
-	recv_ctx = &adapter->recv_ctx;
+	tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
 
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
@@ -602,8 +649,7 @@
 
 		if (adapter->fw_major < 4)
 			rds_ring->crb_rcv_producer =
-				recv_crb_registers[adapter->portnum].
-				crb_rcv_producer[ring];
+				recv_crb_registers[port].crb_rcv_producer[ring];
 	}
 
 	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
@@ -620,13 +666,16 @@
 			goto err_out_free;
 		}
 		sds_ring->desc_head = (struct status_desc *)addr;
+
+		sds_ring->crb_sts_consumer =
+			recv_crb_registers[port].crb_sts_consumer[ring];
+
+		sds_ring->crb_intr_mask =
+			recv_crb_registers[port].sw_int_mask[ring];
 	}
 
 
 	if (adapter->fw_major >= 4) {
-		adapter->intr_scheme = INTR_SCHEME_PERPORT;
-		adapter->msi_mode = MSI_MODE_MULTIFUNC;
-
 		err = nx_fw_cmd_create_rx_ctx(adapter);
 		if (err)
 			goto err_out_free;
@@ -634,23 +683,9 @@
 		if (err)
 			goto err_out_free;
 	} else {
-		sds_ring = &recv_ctx->sds_rings[0];
-		sds_ring->crb_sts_consumer =
-			recv_crb_registers[adapter->portnum].crb_sts_consumer;
-
-		adapter->intr_scheme = adapter->pci_read_normalize(adapter,
-				CRB_NIC_CAPABILITIES_FW);
-		adapter->msi_mode = adapter->pci_read_normalize(adapter,
-				CRB_NIC_MSI_MODE_FW);
-		recv_ctx->sds_rings[0].crb_intr_mask =
-				sw_int_mask[adapter->portnum];
-
 		err = netxen_init_old_ctx(adapter);
-		if (err) {
-			netxen_free_hw_resources(adapter);
-			return err;
-		}
-
+		if (err)
+			goto err_out_free;
 	}
 
 	return 0;
@@ -665,32 +700,43 @@
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
 	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
 	int ring;
 
+	int port = adapter->portnum;
+
 	if (adapter->fw_major >= 4) {
-		nx_fw_cmd_destroy_tx_ctx(adapter);
 		nx_fw_cmd_destroy_rx_ctx(adapter);
+		nx_fw_cmd_destroy_tx_ctx(adapter);
+	} else {
+		netxen_api_lock(adapter);
+		NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port),
+				NETXEN_CTX_D3_RESET | port);
+		netxen_api_unlock(adapter);
 	}
 
-	if (adapter->ctx_desc != NULL) {
+	/* Allow dma queues to drain after context reset */
+	msleep(20);
+
+	recv_ctx = &adapter->recv_ctx;
+
+	if (recv_ctx->hwctx != NULL) {
 		pci_free_consistent(adapter->pdev,
 				sizeof(struct netxen_ring_ctx) +
 				sizeof(uint32_t),
-				adapter->ctx_desc,
-				adapter->ctx_desc_phys_addr);
-		adapter->ctx_desc = NULL;
+				recv_ctx->hwctx,
+				recv_ctx->phys_addr);
+		recv_ctx->hwctx = NULL;
 	}
 
-	if (adapter->ahw.cmd_desc_head != NULL) {
+	tx_ring = adapter->tx_ring;
+	if (tx_ring->desc_head != NULL) {
 		pci_free_consistent(adapter->pdev,
-				sizeof(struct cmd_desc_type0) *
-				adapter->num_txd,
-				adapter->ahw.cmd_desc_head,
-				adapter->ahw.cmd_desc_phys_addr);
-		adapter->ahw.cmd_desc_head = NULL;
+				TX_DESC_RINGSIZE(tx_ring),
+				tx_ring->desc_head, tx_ring->phys_addr);
+		tx_ring->desc_head = NULL;
 	}
 
-	recv_ctx = &adapter->recv_ctx;
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_ethtool.c linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,7 +30,6 @@
 
 #include <linux/types.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <linux/netdevice.h>
@@ -53,13 +52,9 @@
 #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
 
 static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
-	{"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)},
 	{"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
-	{"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)},
 	{"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
-	{"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)},
-	{"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)},
-	{"polled", NETXEN_NIC_STAT(stats.polled)},
+	{"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},
 	{"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
 	{"csummed", NETXEN_NIC_STAT(stats.csummed)},
 	{"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)},
@@ -97,12 +92,9 @@
 	strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
 	strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
 	write_lock_irqsave(&adapter->adapter_lock, flags);
-	fw_major = adapter->pci_read_normalize(adapter,
-					NETXEN_FW_VERSION_MAJOR);
-	fw_minor = adapter->pci_read_normalize(adapter,
-					NETXEN_FW_VERSION_MINOR);
-	fw_build = adapter->pci_read_normalize(adapter,
-					NETXEN_FW_VERSION_SUB);
+	fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+	fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+	fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
 	write_unlock_irqrestore(&adapter->adapter_lock, flags);
 	sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
 
@@ -115,6 +107,7 @@
 netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
+	int check_sfp_module = 0;
 
 	/* read which mode */
 	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
@@ -139,7 +132,7 @@
 	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 		u32 val;
 
-		adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &val, 4);
+		val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
 		if (val == NETXEN_PORT_MODE_802_3_AP) {
 			ecmd->supported = SUPPORTED_1000baseT_Full;
 			ecmd->advertising = ADVERTISED_1000baseT_Full;
@@ -148,13 +141,19 @@
 			ecmd->advertising = ADVERTISED_10000baseT_Full;
 		}
 
+		if (netif_running(dev) && adapter->has_link_events) {
+			ecmd->speed = adapter->link_speed;
+			ecmd->autoneg = adapter->link_autoneg;
+			ecmd->duplex = adapter->link_duplex;
+			goto skip;
+		}
+
 		ecmd->port = PORT_TP;
 
 		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 			u16 pcifn = adapter->ahw.pci_func;
 
-			adapter->hw_read_wx(adapter,
-				P3_LINK_SPEED_REG(pcifn), &val, 4);
+			val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn));
 			ecmd->speed = P3_LINK_SPEED_MHZ *
 					P3_LINK_SPEED_VAL(pcifn, val);
 		} else
@@ -165,10 +164,11 @@
 	} else
 		return -EIO;
 
+skip:
 	ecmd->phy_address = adapter->physical_port;
 	ecmd->transceiver = XCVR_EXTERNAL;
 
-	switch ((netxen_brdtype_t)adapter->ahw.board_type) {
+	switch (adapter->ahw.board_type) {
 	case NETXEN_BRDTYPE_P2_SB35_4G:
 	case NETXEN_BRDTYPE_P2_SB31_2G:
 	case NETXEN_BRDTYPE_P3_REF_QG:
@@ -195,7 +195,7 @@
 	case NETXEN_BRDTYPE_P3_HMEZ:
 		ecmd->supported |= SUPPORTED_MII;
 		ecmd->advertising |= ADVERTISED_MII;
-		ecmd->port = PORT_FIBRE;
+		ecmd->port = PORT_MII;
 		ecmd->autoneg = AUTONEG_DISABLE;
 		break;
 	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
@@ -203,6 +203,8 @@
 	case NETXEN_BRDTYPE_P3_10G_SFP_QT:
 		ecmd->advertising |= ADVERTISED_TP;
 		ecmd->supported |= SUPPORTED_TP;
+		check_sfp_module = netif_running(dev) &&
+			adapter->has_link_events;
 	case NETXEN_BRDTYPE_P2_SB31_10G:
 	case NETXEN_BRDTYPE_P3_10G_XFP:
 		ecmd->supported |= SUPPORTED_FIBRE;
@@ -217,6 +219,8 @@
 			ecmd->advertising |=
 				(ADVERTISED_FIBRE | ADVERTISED_TP);
 			ecmd->port = PORT_FIBRE;
+			check_sfp_module = netif_running(dev) &&
+				adapter->has_link_events;
 		} else {
 			ecmd->autoneg = AUTONEG_ENABLE;
 			ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
@@ -227,10 +231,28 @@
 		break;
 	default:
 		printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
-		       (netxen_brdtype_t)adapter->ahw.board_type);
+				adapter->ahw.board_type);
 		return -EIO;
 	}
 
+	if (check_sfp_module) {
+		switch (adapter->module_type) {
+		case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
+		case LINKEVENT_MODULE_OPTICAL_SRLR:
+		case LINKEVENT_MODULE_OPTICAL_LRM:
+		case LINKEVENT_MODULE_OPTICAL_SFP_1G:
+			ecmd->port = PORT_FIBRE;
+			break;
+		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
+		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
+		case LINKEVENT_MODULE_TWINAX:
+			ecmd->port = PORT_TP;
+			break;
+		default:
+			ecmd->port = -1;
+		}
+	}
+
 	return 0;
 }
 
@@ -398,12 +420,11 @@
 	regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
 	    (adapter->pdev)->device;
 	/* which mode */
-	adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, &regs_buff[0], 4);
+	regs_buff[0] = NXRD32(adapter, NETXEN_NIU_MODE);
 	mode = regs_buff[0];
 
 	/* Common registers to all the modes */
-	adapter->hw_read_wx(adapter,
-			NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, &regs_buff[2], 4);
+	regs_buff[2] = NXRD32(adapter, NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER);
 	/* GB/XGB Mode */
 	mode = (mode / 2) - 1;
 	window = 0;
@@ -414,9 +435,8 @@
 				window = adapter->physical_port *
 					NETXEN_NIC_PORT_WINDOW;
 
-			adapter->hw_read_wx(adapter,
-				niu_registers[mode].reg[i - 3] + window,
-				&regs_buff[i], 4);
+			regs_buff[i] = NXRD32(adapter,
+				niu_registers[mode].reg[i - 3] + window);
 		}
 
 	}
@@ -440,7 +460,7 @@
 			return !val;
 		}
 	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
-		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
+		val = NXRD32(adapter, CRB_XG_STATE);
 		return (val == XG_LINK_UP) ? 0 : 1;
 	}
 	return -EIO;
@@ -504,10 +524,9 @@
 		if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 			return;
 		/* get flow control settings */
-		netxen_nic_read_w0(adapter,NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				&val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 		pause->rx_pause = netxen_gb_get_rx_flowctl(val);
-		netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 		switch (port) {
 			case 0:
 				pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
@@ -527,7 +546,7 @@
 		if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
 			return;
 		pause->rx_pause = 1;
-		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 		if (port == 0)
 			pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
 		else
@@ -550,18 +569,17 @@
 		if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 			return -EIO;
 		/* set flow control */
-		netxen_nic_read_w0(adapter,
-					NETXEN_NIU_GB_MAC_CONFIG_0(port), &val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 
 		if (pause->rx_pause)
 			netxen_gb_rx_flowctl(val);
 		else
 			netxen_gb_unset_rx_flowctl(val);
 
-		netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+		NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 				val);
 		/* set autoneg */
-		netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 		switch (port) {
 			case 0:
 				if (pause->tx_pause)
@@ -589,11 +607,11 @@
 					netxen_gb_set_gb3_mask(val);
 				break;
 		}
-		netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
+		NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
 	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 		if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
 			return -EIO;
-		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 		if (port == 0) {
 			if (pause->tx_pause)
 				netxen_xg_unset_xg0_mask(val);
@@ -605,7 +623,7 @@
 			else
 				netxen_xg_set_xg1_mask(val);
 		}
-		netxen_nic_write_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
+		NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
 	} else {
 		printk(KERN_ERR "%s: Unknown board type: %x\n",
 				netxen_nic_driver_name,
@@ -619,14 +637,14 @@
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	u32 data_read, data_written;
 
-	netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read);
+	data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
 	if ((data_read & 0xffff) != PHAN_VENDOR_ID)
 	return 1;
 
 	data_written = (u32)0xa5a5a5a5;
 
-	netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
-	data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST);
+	NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
+	data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
 	if (data_written != data_read)
 		return 1;
 
@@ -743,11 +761,11 @@
 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 		return;
 
-	wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV);
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 	if (wol_cfg & (1UL << adapter->portnum))
 		wol->supported |= WAKE_MAGIC;
 
-	wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG);
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 	if (wol_cfg & (1UL << adapter->portnum))
 		wol->wolopts |= WAKE_MAGIC;
 }
@@ -764,16 +782,16 @@
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EOPNOTSUPP;
 
-	wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV);
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 	if (!(wol_cfg & (1 << adapter->portnum)))
 		return -EOPNOTSUPP;
 
-	wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG);
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 	if (wol->wolopts & WAKE_MAGIC)
 		wol_cfg |= 1UL << adapter->portnum;
 	else
 		wol_cfg &= ~(1UL << adapter->portnum);
-	netxen_nic_reg_write(adapter, NETXEN_WOL_CONFIG, wol_cfg);
+	NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic.h linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic.h
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic.h	2012-03-22 20:11:13.000000000 -0400
@@ -34,10 +34,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -46,21 +42,16 @@
 #include <linux/in.h>
 #include <linux/tcp.h>
 #include <linux/skbuff.h>
+#include <linux/firmware.h>
 
 #include <linux/ethtool.h>
 #include <linux/mii.h>
-#include <linux/interrupt.h>
 #include <linux/timer.h>
 
-#include <linux/mm.h>
-#include <linux/mman.h>
 #include <linux/vmalloc.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
 
 #include "netxen_nic_hw.h"
 
@@ -69,7 +60,18 @@
 #define _NETXEN_NIC_LINUX_SUBVERSION 30
 #define NETXEN_NIC_LINUX_VERSIONID  "4.0.30"
 
-#define NETXEN_VERSION_CODE(a, b, c)	(((a) << 16) + ((b) << 8) + (c))
+#define NETXEN_VERSION_CODE(a, b, c)	(((a) << 24) + ((b) << 16) + (c))
+#define _major(v)	(((v) >> 24) & 0xff)
+#define _minor(v)	(((v) >> 16) & 0xff)
+#define _build(v)	((v) & 0xffff)
+
+/* version in image has weird encoding:
+ *  7:0  - major
+ * 15:8  - minor
+ * 31:16 - build (little endian)
+ */
+#define NETXEN_DECODE_VERSION(v) \
+	NETXEN_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16))
 
 #define NETXEN_NUM_FLASH_SECTORS (64)
 #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
@@ -84,10 +86,10 @@
 	(sizeof(struct netxen_rx_buffer) * rds_ring->num_desc)
 #define STATUS_DESC_RINGSIZE(sds_ring)	\
 	(sizeof(struct status_desc) * (sds_ring)->num_desc)
-#define TX_BUFF_RINGSIZE(adapter)	\
-	(sizeof(struct netxen_cmd_buffer) * adapter->num_txd)
-#define TX_DESC_RINGSIZE(adapter)	\
-	(sizeof(struct cmd_desc_type0) * adapter->num_txd)
+#define TX_BUFF_RINGSIZE(tx_ring)	\
+	(sizeof(struct netxen_cmd_buffer) * tx_ring->num_desc)
+#define TX_DESC_RINGSIZE(tx_ring)	\
+	(sizeof(struct cmd_desc_type0) * tx_ring->num_desc)
 
 #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
 
@@ -118,6 +120,7 @@
 #define NX_P3_A2		0x30
 #define NX_P3_B0		0x40
 #define NX_P3_B1		0x41
+#define NX_P3_B2		0x42
 
 #define NX_IS_REVISION_P2(REVISION)     (REVISION <= NX_P2_C1)
 #define NX_IS_REVISION_P3(REVISION)     (REVISION >= NX_P3_A0)
@@ -177,6 +180,7 @@
 #define	MAX_NUM_CARDS		4
 
 #define MAX_BUFFERS_PER_CMD	32
+#define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + 4)
 
 /*
  * Following are the states of the Phantom. Phantom will set them and
@@ -203,18 +207,11 @@
 #define MAX_RCV_DESCRIPTORS_10G		4096
 #define MAX_JUMBO_RCV_DESCRIPTORS	1024
 #define MAX_LRO_RCV_DESCRIPTORS		8
-#define MAX_RCVSTATUS_DESCRIPTORS	MAX_RCV_DESCRIPTORS
-#define MAX_JUMBO_RCV_DESC	MAX_JUMBO_RCV_DESCRIPTORS
-#define MAX_RCV_DESC		MAX_RCV_DESCRIPTORS
-#define MAX_RCVSTATUS_DESC	MAX_RCV_DESCRIPTORS
-#define MAX_EPG_DESCRIPTORS	(MAX_CMD_DESCRIPTORS * 8)
-#define NUM_RCV_DESC		(MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS + \
-				 MAX_LRO_RCV_DESCRIPTORS)
-#define MIN_TX_COUNT	4096
-#define MIN_RX_COUNT	4096
 #define NETXEN_CTX_SIGNATURE	0xdee0
+#define NETXEN_CTX_SIGNATURE_V2	0x0002dee0
+#define NETXEN_CTX_RESET	0xbad0
+#define NETXEN_CTX_D3_RESET	0xacc0
 #define NETXEN_RCV_PRODUCER(ringid)	(ringid)
-#define MAX_FRAME_SIZE	0x10000	/* 64K MAX size for LSO */
 
 #define PHAN_PEG_RCV_INITIALIZED	0xff01
 #define PHAN_PEG_RCV_START_INITIALIZE	0xff00
@@ -253,12 +250,19 @@
 #define netxen_set_msg_opcode(config_word, val)	\
 	((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28)
 
-struct netxen_rcv_context {
-	__le64 rcv_ring_addr;
-	__le32 rcv_ring_size;
+struct netxen_rcv_ring {
+	__le64 addr;
+	__le32 size;
 	__le32 rsrvd;
 };
 
+struct netxen_sts_ring {
+	__le64 addr;
+	__le32 size;
+	__le16 msi_index;
+	__le16 rsvd;
+} ;
+
 struct netxen_ring_ctx {
 
 	/* one command ring */
@@ -268,13 +272,18 @@
 	__le32 rsrvd;
 
 	/* three receive rings */
-	struct netxen_rcv_context rcv_ctx[3];
+	struct netxen_rcv_ring rcv_rings[NUM_RCV_DESC_RINGS];
 
-	/* one status ring */
 	__le64 sts_ring_addr;
 	__le32 sts_ring_size;
 
 	__le32 ctx_id;
+
+	__le64 rsrvd_2[3];
+	__le32 sts_ring_count;
+	__le32 rsrvd_3;
+	struct netxen_sts_ring sts_rings[NUM_STS_DESC_RINGS];
+
 } __attribute__ ((aligned(64)));
 
 /*
@@ -373,6 +382,7 @@
 /* opcode field in status_desc */
 #define NETXEN_NIC_RXPKT_DESC  0x04
 #define NETXEN_OLD_RXPKT_DESC  0x3f
+#define NETXEN_NIC_RESPONSE_DESC 0x05
 
 /* for status field in status_desc */
 #define STATUS_NEED_CKSUM	(1)
@@ -382,13 +392,11 @@
 #define STATUS_OWNER_HOST	(0x1ULL << 56)
 #define STATUS_OWNER_PHANTOM	(0x2ULL << 56)
 
-/* Note: sizeof(status_desc) should always be a mutliple of 2 */
-
-#define netxen_get_sts_desc_lro_cnt(status_desc)	\
-	((status_desc)->lro & 0x7F)
-#define netxen_get_sts_desc_lro_last_frag(status_desc)	\
-	(((status_desc)->lro & 0x80) >> 7)
-
+/* Status descriptor:
+   0-3 port, 4-7 status, 8-11 type, 12-27 total_length
+   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
+   53-55 desc_cnt, 56-57 owner, 58-63 opcode
+ */
 #define netxen_get_sts_port(sts_data)	\
 	((sts_data) & 0x0F)
 #define netxen_get_sts_status(sts_data)	\
@@ -403,41 +411,15 @@
 	(((sts_data) >> 44) & 0x0F)
 #define netxen_get_sts_pkt_offset(sts_data)	\
 	(((sts_data) >> 48) & 0x1F)
+#define netxen_get_sts_desc_cnt(sts_data)	\
+	(((sts_data) >> 53) & 0x7)
 #define netxen_get_sts_opcode(sts_data)	\
 	(((sts_data) >> 58) & 0x03F)
 
 struct status_desc {
-	/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
-	   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
-	   53-55 desc_cnt, 56-57 owner, 58-63 opcode
-	 */
-	__le64 status_desc_data;
-	union {
-		struct {
-			__le32 hash_value;
-			u8 hash_type;
-			u8 msg_type;
-			u8 unused;
-			union {
-				/* Bit pattern: 0-6 lro_count indicates frag
-				 * sequence, 7 last_frag indicates last frag
-				 */
-				u8 lro;
-
-				/* chained buffers */
-				u8 nr_frags;
-			};
-		};
-		struct {
-			__le16 frag_handles[4];
-		};
-	};
+	__le64 status_desc_data[2];
 } __attribute__ ((aligned(16)));
 
-enum {
-	NETXEN_RCV_PEG_0 = 0,
-	NETXEN_RCV_PEG_1
-};
 /* The version of the main data structure */
 #define	NETXEN_BDINFO_VERSION 1
 
@@ -447,85 +429,35 @@
 /* Max number of Gig ports on a Phantom board */
 #define NETXEN_MAX_PORTS 4
 
-typedef enum {
-	NETXEN_BRDTYPE_P1_BD = 0x0000,
-	NETXEN_BRDTYPE_P1_SB = 0x0001,
-	NETXEN_BRDTYPE_P1_SMAX = 0x0002,
-	NETXEN_BRDTYPE_P1_SOCK = 0x0003,
-
-	NETXEN_BRDTYPE_P2_SOCK_31 = 0x0008,
-	NETXEN_BRDTYPE_P2_SOCK_35 = 0x0009,
-	NETXEN_BRDTYPE_P2_SB35_4G = 0x000a,
-	NETXEN_BRDTYPE_P2_SB31_10G = 0x000b,
-	NETXEN_BRDTYPE_P2_SB31_2G = 0x000c,
-
-	NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
-	NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
-	NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f,
-
-	NETXEN_BRDTYPE_P3_REF_QG = 0x0021,
-	NETXEN_BRDTYPE_P3_HMEZ = 0x0022,
-	NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023,
-	NETXEN_BRDTYPE_P3_4_GB = 0x0024,
-	NETXEN_BRDTYPE_P3_IMEZ = 0x0025,
-	NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026,
-	NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027,
-	NETXEN_BRDTYPE_P3_XG_LOM = 0x0028,
-	NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029,
-	NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a,
-	NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b,
-	NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
-	NETXEN_BRDTYPE_P3_10G_XFP = 0x0032,
-	NETXEN_BRDTYPE_P3_10G_TP = 0x0080
-
-} netxen_brdtype_t;
-
-typedef enum {
-	NETXEN_BRDMFG_INVENTEC = 1
-} netxen_brdmfg;
+#define NETXEN_BRDTYPE_P1_BD		0x0000
+#define NETXEN_BRDTYPE_P1_SB		0x0001
+#define NETXEN_BRDTYPE_P1_SMAX		0x0002
+#define NETXEN_BRDTYPE_P1_SOCK		0x0003
 
-typedef enum {
-	MEM_ORG_128Mbx4 = 0x0,	/* DDR1 only */
-	MEM_ORG_128Mbx8 = 0x1,	/* DDR1 only */
-	MEM_ORG_128Mbx16 = 0x2,	/* DDR1 only */
-	MEM_ORG_256Mbx4 = 0x3,
-	MEM_ORG_256Mbx8 = 0x4,
-	MEM_ORG_256Mbx16 = 0x5,
-	MEM_ORG_512Mbx4 = 0x6,
-	MEM_ORG_512Mbx8 = 0x7,
-	MEM_ORG_512Mbx16 = 0x8,
-	MEM_ORG_1Gbx4 = 0x9,
-	MEM_ORG_1Gbx8 = 0xa,
-	MEM_ORG_1Gbx16 = 0xb,
-	MEM_ORG_2Gbx4 = 0xc,
-	MEM_ORG_2Gbx8 = 0xd,
-	MEM_ORG_2Gbx16 = 0xe,
-	MEM_ORG_128Mbx32 = 0x10002,	/* GDDR only */
-	MEM_ORG_256Mbx32 = 0x10005	/* GDDR only */
-} netxen_mn_mem_org_t;
+#define NETXEN_BRDTYPE_P2_SOCK_31	0x0008
+#define NETXEN_BRDTYPE_P2_SOCK_35	0x0009
+#define NETXEN_BRDTYPE_P2_SB35_4G	0x000a
+#define NETXEN_BRDTYPE_P2_SB31_10G	0x000b
+#define NETXEN_BRDTYPE_P2_SB31_2G	0x000c
 
-typedef enum {
-	MEM_ORG_512Kx36 = 0x0,
-	MEM_ORG_1Mx36 = 0x1,
-	MEM_ORG_2Mx36 = 0x2
-} netxen_sn_mem_org_t;
+#define NETXEN_BRDTYPE_P2_SB31_10G_IMEZ		0x000d
+#define NETXEN_BRDTYPE_P2_SB31_10G_HMEZ		0x000e
+#define NETXEN_BRDTYPE_P2_SB31_10G_CX4		0x000f
 
-typedef enum {
-	MEM_DEPTH_4MB = 0x1,
-	MEM_DEPTH_8MB = 0x2,
-	MEM_DEPTH_16MB = 0x3,
-	MEM_DEPTH_32MB = 0x4,
-	MEM_DEPTH_64MB = 0x5,
-	MEM_DEPTH_128MB = 0x6,
-	MEM_DEPTH_256MB = 0x7,
-	MEM_DEPTH_512MB = 0x8,
-	MEM_DEPTH_1GB = 0x9,
-	MEM_DEPTH_2GB = 0xa,
-	MEM_DEPTH_4GB = 0xb,
-	MEM_DEPTH_8GB = 0xc,
-	MEM_DEPTH_16GB = 0xd,
-	MEM_DEPTH_32GB = 0xe
-} netxen_mem_depth_t;
+#define NETXEN_BRDTYPE_P3_REF_QG	0x0021
+#define NETXEN_BRDTYPE_P3_HMEZ		0x0022
+#define NETXEN_BRDTYPE_P3_10G_CX4_LP	0x0023
+#define NETXEN_BRDTYPE_P3_4_GB		0x0024
+#define NETXEN_BRDTYPE_P3_IMEZ		0x0025
+#define NETXEN_BRDTYPE_P3_10G_SFP_PLUS	0x0026
+#define NETXEN_BRDTYPE_P3_10000_BASE_T	0x0027
+#define NETXEN_BRDTYPE_P3_XG_LOM	0x0028
+#define NETXEN_BRDTYPE_P3_4_GB_MM	0x0029
+#define NETXEN_BRDTYPE_P3_10G_SFP_CT	0x002a
+#define NETXEN_BRDTYPE_P3_10G_SFP_QT	0x002b
+#define NETXEN_BRDTYPE_P3_10G_CX4	0x0031
+#define NETXEN_BRDTYPE_P3_10G_XFP	0x0032
+#define NETXEN_BRDTYPE_P3_10G_TP	0x0080
 
 struct netxen_board_info {
 	u32 header_version;
@@ -676,17 +608,15 @@
 #define PRIMARY_IMAGE_BAD	0xffffffff
 
 /* Flash memory map */
-typedef enum {
-	NETXEN_CRBINIT_START = 0,	/* Crbinit section */
-	NETXEN_BRDCFG_START = 0x4000,	/* board config */
-	NETXEN_INITCODE_START = 0x6000,	/* pegtune code */
-	NETXEN_BOOTLD_START = 0x10000,	/* bootld */
-	NETXEN_IMAGE_START = 0x43000,	/* compressed image */
-	NETXEN_SECONDARY_START = 0x200000,	/* backup images */
-	NETXEN_PXE_START = 0x3E0000,	/* user defined region */
-	NETXEN_USER_START = 0x3E8000,	/* User defined region for new boards */
-	NETXEN_FIXED_START = 0x3F0000	/* backup of crbinit */
-} netxen_flash_map_t;
+#define NETXEN_CRBINIT_START	0	/* crbinit section */
+#define NETXEN_BRDCFG_START	0x4000	/* board config */
+#define NETXEN_INITCODE_START	0x6000	/* pegtune code */
+#define NETXEN_BOOTLD_START	0x10000	/* bootld */
+#define NETXEN_IMAGE_START	0x43000	/* compressed image */
+#define NETXEN_SECONDARY_START	0x200000	/* backup images */
+#define NETXEN_PXE_START	0x3E0000	/* PXE boot rom */
+#define NETXEN_USER_START	0x3E8000	/* Firmare info */
+#define NETXEN_FIXED_START	0x3F0000	/* backup of crbinit */
 
 #define NX_FW_VERSION_OFFSET	(NETXEN_USER_START+0x408)
 #define NX_FW_SIZE_OFFSET	(NETXEN_USER_START+0x40c)
@@ -696,6 +626,7 @@
 #define NX_P2_MN_ROMIMAGE	0
 #define NX_P3_CT_ROMIMAGE	1
 #define NX_P3_MN_ROMIMAGE	2
+#define NX_FLASH_ROMIMAGE	3
 
 #define NETXEN_USER_START_OLD NETXEN_PXE_START	/* for backward compatibility */
 
@@ -708,21 +639,8 @@
 #define NETXEN_FLASH_SECONDARY_SIZE 	(NETXEN_USER_START-NETXEN_SECONDARY_START)
 #define NETXEN_NUM_PRIMARY_SECTORS	(0x20)
 #define NETXEN_NUM_CONFIG_SECTORS 	(1)
-#define PFX "NetXen: "
 extern char netxen_nic_driver_name[];
 
-/* Note: Make sure to not call this before adapter->port is valid */
-#if !defined(NETXEN_DEBUG)
-#define DPRINTK(klevel, fmt, args...)	do { \
-	} while (0)
-#else
-#define DPRINTK(klevel, fmt, args...)	do { \
-	printk(KERN_##klevel PFX "%s: %s: " fmt, __func__,\
-		(adapter != NULL && adapter->netdev != NULL) ? \
-		adapter->netdev->name : NULL, \
-		## args); } while(0)
-#endif
-
 /* Number of status descriptors to handle per interrupt */
 #define MAX_STATUS_HANDLE	(64)
 
@@ -732,7 +650,7 @@
  */
 struct netxen_skb_frag {
 	u64 dma;
-	ulong length;
+	u64 length;
 };
 
 #define _netxen_set_bits(config_word, start, bits, val)	{\
@@ -793,34 +711,24 @@
 
 	u8 cut_through;
 	u8 revision_id;
+	u8 pci_func;
+	u8 linkup;
 	u16 port_type;
-	int board_type;
-	u32 linkup;
-	/* Address of cmd ring in Phantom */
-	struct cmd_desc_type0 *cmd_desc_head;
-	dma_addr_t cmd_desc_phys_addr;
-	struct netxen_adapter *adapter;
-	int pci_func;
+	u16 board_type;
 };
 
 #define MINIMUM_ETHERNET_FRAME_SIZE	64	/* With FCS */
 #define ETHERNET_FCS_SIZE		4
 
 struct netxen_adapter_stats {
-	u64  rcvdbadskb;
 	u64  xmitcalled;
-	u64  xmitedframes;
 	u64  xmitfinished;
-	u64  badskblen;
-	u64  nocmddescriptor;
-	u64  polled;
 	u64  rxdropped;
 	u64  txdropped;
 	u64  csummed;
 	u64  no_rcv;
 	u64  rxbytes;
 	u64  txbytes;
-	u64  ints;
 };
 
 /*
@@ -852,14 +760,27 @@
 	struct napi_struct napi;
 	struct list_head free_list[NUM_RCV_DESC_RINGS];
 
-	u16 clean_tx;
-	u16 post_rxd;
 	int irq;
 
 	dma_addr_t phys_addr;
 	char name[IFNAMSIZ+4];
 };
 
+struct nx_host_tx_ring {
+	u32 producer;
+	__le32 *hw_consumer;
+	u32 sw_consumer;
+	u32 crb_cmd_producer;
+	u32 crb_cmd_consumer;
+	u32 num_desc;
+
+	struct netdev_queue *txq;
+
+	struct netxen_cmd_buffer *cmd_buf_arr;
+	struct cmd_desc_type0 *desc_head;
+	dma_addr_t phys_addr;
+};
+
 /*
  * Receive context. There is one such structure per instance of the
  * receive processing. Any state information that is relevant to
@@ -871,8 +792,11 @@
 	u16 context_id;
 	u16 virt_port;
 
-	struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS];
-	struct nx_host_sds_ring sds_rings[NUM_STS_DESC_RINGS];
+	struct nx_host_rds_ring *rds_rings;
+	struct nx_host_sds_ring *sds_rings;
+
+	struct netxen_ring_ctx *hwctx;
+	dma_addr_t phys_addr;
 };
 
 /* New HW context creation */
@@ -1111,8 +1035,8 @@
 #define NETXEN_MAC_DEL	2
 
 typedef struct nx_mac_list_s {
-	struct nx_mac_list_s *next;
-	uint8_t mac_addr[MAX_ADDR_LEN];
+	struct list_head list;
+	uint8_t mac_addr[ETH_ALEN+2];
 } nx_mac_list_t;
 
 /*
@@ -1154,31 +1078,118 @@
 
 #define NX_MAC_EVENT		0x1
 
-enum {
-	NX_NIC_H2C_OPCODE_START = 0,
-	NX_NIC_H2C_OPCODE_CONFIG_RSS,
-	NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL,
-	NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE,
-	NX_NIC_H2C_OPCODE_CONFIG_LED,
-	NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS,
-	NX_NIC_H2C_OPCODE_CONFIG_L2_MAC,
-	NX_NIC_H2C_OPCODE_LRO_REQUEST,
-	NX_NIC_H2C_OPCODE_GET_SNMP_STATS,
-	NX_NIC_H2C_OPCODE_PROXY_START_REQUEST,
-	NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST,
-	NX_NIC_H2C_OPCODE_PROXY_SET_MTU,
-	NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE,
-	NX_H2P_OPCODE_GET_FINGER_PRINT_REQUEST,
-	NX_H2P_OPCODE_INSTALL_LICENSE_REQUEST,
-	NX_H2P_OPCODE_GET_LICENSE_CAPABILITY_REQUEST,
-	NX_NIC_H2C_OPCODE_GET_NET_STATS,
-	NX_NIC_H2C_OPCODE_LAST
-};
+/*
+ * Driver --> Firmware
+ */
+#define NX_NIC_H2C_OPCODE_START				0
+#define NX_NIC_H2C_OPCODE_CONFIG_RSS			1
+#define NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL		2
+#define NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE		3
+#define NX_NIC_H2C_OPCODE_CONFIG_LED			4
+#define NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS		5
+#define NX_NIC_H2C_OPCODE_CONFIG_L2_MAC			6
+#define NX_NIC_H2C_OPCODE_LRO_REQUEST			7
+#define NX_NIC_H2C_OPCODE_GET_SNMP_STATS		8
+#define NX_NIC_H2C_OPCODE_PROXY_START_REQUEST		9
+#define NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST		10
+#define NX_NIC_H2C_OPCODE_PROXY_SET_MTU			11
+#define NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE	12
+#define NX_NIC_H2C_OPCODE_GET_FINGER_PRINT_REQUEST	13
+#define NX_NIC_H2C_OPCODE_INSTALL_LICENSE_REQUEST	14
+#define NX_NIC_H2C_OPCODE_GET_LICENSE_CAPABILITY_REQUEST	15
+#define NX_NIC_H2C_OPCODE_GET_NET_STATS			16
+#define NX_NIC_H2C_OPCODE_PROXY_UPDATE_P2V		17
+#define NX_NIC_H2C_OPCODE_CONFIG_IPADDR			18
+#define NX_NIC_H2C_OPCODE_CONFIG_LOOPBACK		19
+#define NX_NIC_H2C_OPCODE_PROXY_STOP_DONE		20
+#define NX_NIC_H2C_OPCODE_GET_LINKEVENT			21
+#define NX_NIC_C2C_OPCODE				22
+#define NX_NIC_H2C_OPCODE_LAST				23
+
+/*
+ * Firmware --> Driver
+ */
+
+#define NX_NIC_C2H_OPCODE_START				128
+#define NX_NIC_C2H_OPCODE_CONFIG_RSS_RESPONSE		129
+#define NX_NIC_C2H_OPCODE_CONFIG_RSS_TBL_RESPONSE	130
+#define NX_NIC_C2H_OPCODE_CONFIG_MAC_RESPONSE		131
+#define NX_NIC_C2H_OPCODE_CONFIG_PROMISCUOUS_RESPONSE	132
+#define NX_NIC_C2H_OPCODE_CONFIG_L2_MAC_RESPONSE	133
+#define NX_NIC_C2H_OPCODE_LRO_DELETE_RESPONSE		134
+#define NX_NIC_C2H_OPCODE_LRO_ADD_FAILURE_RESPONSE	135
+#define NX_NIC_C2H_OPCODE_GET_SNMP_STATS		136
+#define NX_NIC_C2H_OPCODE_GET_FINGER_PRINT_REPLY	137
+#define NX_NIC_C2H_OPCODE_INSTALL_LICENSE_REPLY		138
+#define NX_NIC_C2H_OPCODE_GET_LICENSE_CAPABILITIES_REPLY 139
+#define NX_NIC_C2H_OPCODE_GET_NET_STATS_RESPONSE	140
+#define NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE	141
+#define NX_NIC_C2H_OPCODE_LAST				142
 
 #define VPORT_MISS_MODE_DROP		0 /* drop all unmatched */
 #define VPORT_MISS_MODE_ACCEPT_ALL	1 /* accept all packets */
 #define VPORT_MISS_MODE_ACCEPT_MULTI	2 /* accept unmatched multicast */
 
+#define NX_FW_CAPABILITY_LINK_NOTIFICATION	(1 << 5)
+#define NX_FW_CAPABILITY_SWITCHING		(1 << 6)
+
+/* module types */
+#define LINKEVENT_MODULE_NOT_PRESENT			1
+#define LINKEVENT_MODULE_OPTICAL_UNKNOWN		2
+#define LINKEVENT_MODULE_OPTICAL_SRLR			3
+#define LINKEVENT_MODULE_OPTICAL_LRM			4
+#define LINKEVENT_MODULE_OPTICAL_SFP_1G			5
+#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE	6
+#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN	7
+#define LINKEVENT_MODULE_TWINAX				8
+
+#define LINKSPEED_10GBPS	10000
+#define LINKSPEED_1GBPS		1000
+#define LINKSPEED_100MBPS	100
+#define LINKSPEED_10MBPS	10
+
+#define LINKSPEED_ENCODED_10MBPS	0
+#define LINKSPEED_ENCODED_100MBPS	1
+#define LINKSPEED_ENCODED_1GBPS		2
+
+#define LINKEVENT_AUTONEG_DISABLED	0
+#define LINKEVENT_AUTONEG_ENABLED	1
+
+#define LINKEVENT_HALF_DUPLEX		0
+#define LINKEVENT_FULL_DUPLEX		1
+
+#define LINKEVENT_LINKSPEED_MBPS	0
+#define LINKEVENT_LINKSPEED_ENCODED	1
+
+/* firmware response header:
+ *	63:58 - message type
+ *	57:56 - owner
+ *	55:53 - desc count
+ *	52:48 - reserved
+ *	47:40 - completion id
+ *	39:32 - opcode
+ *	31:16 - error code
+ *	15:00 - reserved
+ */
+#define netxen_get_nic_msgtype(msg_hdr)	\
+	((msg_hdr >> 58) & 0x3F)
+#define netxen_get_nic_msg_compid(msg_hdr)	\
+	((msg_hdr >> 40) & 0xFF)
+#define netxen_get_nic_msg_opcode(msg_hdr)	\
+	((msg_hdr >> 32) & 0xFF)
+#define netxen_get_nic_msg_errcode(msg_hdr)	\
+	((msg_hdr >> 16) & 0xFFFF)
+
+typedef struct {
+	union {
+		struct {
+			u64 hdr;
+			u64 body[7];
+		};
+		u64 words[8];
+	};
+} nx_fw_msg_t;
+
 typedef struct {
 	__le64 qhdr;
 	__le64 req_hdr;
@@ -1218,99 +1229,96 @@
 
 	struct net_device *netdev;
 	struct pci_dev *pdev;
-	int pci_using_dac;
-	struct net_device_stats net_stats;
-	int mtu;
-	int portnum;
-	u8 physical_port;
-	u16 tx_context_id;
-
-	uint8_t		mc_enabled;
-	uint8_t		max_mc_count;
-	nx_mac_list_t	*mac_list;
-
-	struct netxen_legacy_intr_set legacy_intr;
-
-	struct work_struct watchdog_task;
-	struct timer_list watchdog_timer;
-	struct work_struct  tx_timeout_task;
+	struct list_head mac_list;
 
 	u32 curr_window;
 	u32 crb_win;
 	rwlock_t adapter_lock;
 
-	u32 cmd_producer;
-	__le32 *cmd_consumer;
-	u32 last_cmd_consumer;
-	u32 crb_addr_cmd_producer;
-	u32 crb_addr_cmd_consumer;
 	spinlock_t tx_clean_lock;
 
-	u32 num_txd;
-	u32 num_rxd;
-	u32 num_jumbo_rxd;
-	u32 num_lro_rxd;
-
-	int max_rds_rings;
-	int max_sds_rings;
-
-	u32 flags;
-	u32 irq;
-	int driver_mismatch;
-	u32 temp;
+	u16 num_txd;
+	u16 num_rxd;
+	u16 num_jumbo_rxd;
+	u16 num_lro_rxd;
 
-	u32 fw_major;
-	u32 fw_version;
+	u8 max_rds_rings;
+	u8 max_sds_rings;
+	u8 driver_mismatch;
+	u8 msix_supported;
+	u8 rx_csum;
+	u8 pci_using_dac;
+	u8 portnum;
+	u8 physical_port;
 
-	int msix_supported;
-	struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+	u8 mc_enabled;
+	u8 max_mc_count;
+	u8 rss_supported;
+	u8 link_changed;
+	u32 resv3;
 
-	struct netxen_adapter_stats stats;
+	u8 has_link_events;
+	u8 fw_type;
+	u16 tx_context_id;
+	u16 mtu;
+	u16 is_up;
 
 	u16 link_speed;
 	u16 link_duplex;
-	u16 state;
 	u16 link_autoneg;
-	int rx_csum;
+	u16 module_type;
 
-	struct netxen_cmd_buffer *cmd_buf_arr;	/* Command buffers for xmit */
+	u32 capabilities;
+	u32 flags;
+	u32 irq;
+	u32 temp;
 
-	/*
-	 * Receive instances. These can be either one per port,
-	 * or one per peg, etc.
-	 */
-	struct netxen_recv_context recv_ctx;
+	u32 msi_tgt_status;
+	u32 resv4;
 
-	int is_up;
-	struct netxen_dummy_dma dummy_dma;
-	nx_nic_intr_coalesce_t coal;
+	struct netxen_adapter_stats stats;
+
+	struct netxen_recv_context recv_ctx;
+	struct nx_host_tx_ring *tx_ring;
 
-	/* Context interface shared between card and host */
-	struct netxen_ring_ctx *ctx_desc;
-	dma_addr_t ctx_desc_phys_addr;
-	int intr_scheme;
-	int msi_mode;
 	int (*enable_phy_interrupts) (struct netxen_adapter *);
 	int (*disable_phy_interrupts) (struct netxen_adapter *);
-	int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
+	int (*macaddr_set) (struct netxen_adapter *, u8 *);
 	int (*set_mtu) (struct netxen_adapter *, int);
 	int (*set_promisc) (struct netxen_adapter *, u32);
+	void (*set_multi) (struct net_device *);
 	int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
 	int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
 	int (*init_port) (struct netxen_adapter *, int);
 	int (*stop_port) (struct netxen_adapter *);
 
-	int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int);
-	int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int);
+	u32 (*hw_read_wx)(struct netxen_adapter *, ulong);
+	int (*hw_write_wx)(struct netxen_adapter *, ulong, u32);
 	int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int);
 	int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int);
 	int (*pci_write_immediate)(struct netxen_adapter *, u64, u32);
 	u32 (*pci_read_immediate)(struct netxen_adapter *, u64);
-	void (*pci_write_normalize)(struct netxen_adapter *, u64, u32);
-	u32 (*pci_read_normalize)(struct netxen_adapter *, u64);
 	unsigned long (*pci_set_window)(struct netxen_adapter *,
 			unsigned long long);
-};				/* netxen_adapter structure */
+
+	struct netxen_legacy_intr_set legacy_intr;
+
+	struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+
+	struct netxen_dummy_dma dummy_dma;
+
+	struct work_struct watchdog_task;
+	struct timer_list watchdog_timer;
+	struct work_struct  tx_timeout_task;
+
+	struct net_device_stats net_stats;
+
+	nx_nic_intr_coalesce_t coal;
+
+	u32 fw_major;
+	u32 fw_version;
+	const struct firmware *fw;
+};
 
 /*
  * NetXen dma watchdog control structure
@@ -1330,46 +1338,6 @@
 #define netxen_get_dma_watchdog_disabled(config_word) \
 	(((config_word) >> 1) & 0x1)
 
-/* Max number of xmit producer threads that can run simultaneously */
-#define	MAX_XMIT_PRODUCERS		16
-
-#define PCI_OFFSET_FIRST_RANGE(adapter, off)    \
-	((adapter)->ahw.pci_base0 + (off))
-#define PCI_OFFSET_SECOND_RANGE(adapter, off)   \
-	((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START)
-#define PCI_OFFSET_THIRD_RANGE(adapter, off)    \
-	((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START)
-
-static inline void __iomem *pci_base_offset(struct netxen_adapter *adapter,
-					    unsigned long off)
-{
-	if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) {
-		return (adapter->ahw.pci_base0 + off);
-	} else if ((off < SECOND_PAGE_GROUP_END) &&
-		   (off >= SECOND_PAGE_GROUP_START)) {
-		return (adapter->ahw.pci_base1 + off - SECOND_PAGE_GROUP_START);
-	} else if ((off < THIRD_PAGE_GROUP_END) &&
-		   (off >= THIRD_PAGE_GROUP_START)) {
-		return (adapter->ahw.pci_base2 + off - THIRD_PAGE_GROUP_START);
-	}
-	return NULL;
-}
-
-static inline void __iomem *pci_base(struct netxen_adapter *adapter,
-				     unsigned long off)
-{
-	if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) {
-		return adapter->ahw.pci_base0;
-	} else if ((off < SECOND_PAGE_GROUP_END) &&
-		   (off >= SECOND_PAGE_GROUP_START)) {
-		return adapter->ahw.pci_base1;
-	} else if ((off < THIRD_PAGE_GROUP_END) &&
-		   (off >= THIRD_PAGE_GROUP_START)) {
-		return adapter->ahw.pci_base2;
-	}
-	return NULL;
-}
-
 int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter);
@@ -1382,21 +1350,22 @@
 /* Functions available from netxen_nic_hw.c */
 int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
 int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
-int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
-void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value);
-void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value);
+
+int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
+int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
+
+#define NXRD32(adapter, off) \
+	(adapter->hw_read_wx(adapter, off))
+#define NXWR32(adapter, off, val) \
+	(adapter->hw_write_wx(adapter, off, val))
 
 int netxen_nic_get_board_info(struct netxen_adapter *adapter);
 void netxen_nic_get_firmware_info(struct netxen_adapter *adapter);
 int netxen_nic_wol_supported(struct netxen_adapter *adapter);
 
-int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+u32 netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off);
 int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+		ulong off, u32 data);
 int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size);
 int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
@@ -1412,16 +1381,13 @@
 void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter,
 		u32 wndw);
 
-int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+u32 netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off);
 int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+		ulong off, u32 data);
 int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size);
 int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size);
-void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
-				 unsigned long off, int data);
 int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
 		u64 off, u32 data);
 u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off);
@@ -1435,8 +1401,10 @@
 void netxen_free_adapter_offload(struct netxen_adapter *adapter);
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
-int netxen_receive_peg_ready(struct netxen_adapter *adapter);
 int netxen_load_firmware(struct netxen_adapter *adapter);
+int netxen_need_fw_reset(struct netxen_adapter *adapter);
+void netxen_reject_firmware(struct netxen_adapter *adapter);
+void netxen_release_firmware(struct netxen_adapter *adapter);
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
 
 int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
@@ -1475,6 +1443,8 @@
 int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
 int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
 int netxen_config_rss(struct netxen_adapter *adapter, int enable);
+int netxen_linkevent_request(struct netxen_adapter *adapter, int enable);
+void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup);
 
 int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu);
 int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
@@ -1483,7 +1453,7 @@
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
 
 void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
-		uint32_t crb_producer);
+		struct nx_host_tx_ring *tx_ring);
 
 /*
  * NetXen Board information
@@ -1491,7 +1461,7 @@
 
 #define NETXEN_MAX_SHORT_NAME 32
 struct netxen_brdinfo {
-	netxen_brdtype_t brdtype;	/* type of board */
+	int brdtype;	/* type of board */
 	long ports;		/* max no of physical ports */
 	char short_name[NETXEN_MAX_SHORT_NAME];
 };
@@ -1541,17 +1511,15 @@
 	u32 ctrl;
 
 	/* check if already inactive */
-	if (adapter->hw_read_wx(adapter,
-	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
-		printk(KERN_ERR "failed to read dma watchdog status\n");
+	ctrl = adapter->hw_read_wx(adapter,
+			NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
 
 	if (netxen_get_dma_watchdog_enabled(ctrl) == 0)
 		return 1;
 
 	/* Send the disable request */
 	netxen_set_dma_watchdog_disable_req(ctrl);
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+	NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
 
 	return 0;
 }
@@ -1561,9 +1529,8 @@
 {
 	u32 ctrl;
 
-	if (adapter->hw_read_wx(adapter,
-	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
-		printk(KERN_ERR "failed to read dma watchdog status\n");
+	ctrl = adapter->hw_read_wx(adapter,
+			NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
 
 	return (netxen_get_dma_watchdog_enabled(ctrl) == 0);
 }
@@ -1573,9 +1540,8 @@
 {
 	u32 ctrl;
 
-	if (adapter->hw_read_wx(adapter,
-		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
-		printk(KERN_ERR "failed to read dma watchdog status\n");
+	ctrl = adapter->hw_read_wx(adapter,
+			NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
 
 	if (netxen_get_dma_watchdog_enabled(ctrl))
 		return 1;
@@ -1583,13 +1549,20 @@
 	/* send the wakeup request */
 	netxen_set_dma_watchdog_enable_req(ctrl);
 
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+	NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
 
 	return 0;
 }
 
 
+static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring)
+{
+	smp_mb();
+	return find_diff_among(tx_ring->producer,
+			tx_ring->sw_consumer, tx_ring->num_desc);
+
+}
+
 int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
 int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
 extern void netxen_change_ringparam(struct netxen_adapter *adapter);
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_hdr.h linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_hdr.h
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_hdr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_hdr.h	2009-09-09 18:13:59.000000000 -0400
@@ -31,16 +31,8 @@
 #ifndef __NETXEN_NIC_HDR_H_
 #define __NETXEN_NIC_HDR_H_
 
-#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <asm/irq.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
 #include <linux/types.h>
-#include <asm/uaccess.h>
-#include <asm/string.h>		/* for memset */
 
 /*
  * The basic unit of access when reading/writing control registers.
@@ -363,6 +355,7 @@
 #define NETXEN_HW_CRB_HUB_AGT_ADR_LPC	\
 	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_LPC_CRB_AGT_ADR)
 
+#define NETXEN_SRE_MISC			(NETXEN_CRB_SRE + 0x0002c)
 #define NETXEN_SRE_INT_STATUS		(NETXEN_CRB_SRE + 0x00034)
 #define NETXEN_SRE_PBI_ACTIVE_STATUS	(NETXEN_CRB_SRE + 0x01014)
 #define NETXEN_SRE_L1RE_CTL		(NETXEN_CRB_SRE + 0x03000)
@@ -860,6 +853,7 @@
 #define NX_PEG_TUNE_CAPABILITY		(NETXEN_CAM_RAM(0x02c))
 
 #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL		(0x14)
+#define NETXEN_PEG_ALIVE_COUNTER	(NETXEN_CAM_RAM(0xb0))
 
 #define	ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
 #define ISR_LEGACY_INT_TRIGGERED(VAL)	(((VAL) & 0x300) == 0x200)
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_hw.c linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_hw.c
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_hw.c	2012-03-22 19:15:11.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,6 @@
 #include "netxen_nic_hw.h"
 #include "netxen_nic_phan_reg.h"
 
-#include <linux/firmware.h>
 #include <net/ip.h>
 
 #define MASK(n) ((1ULL<<(n))-1)
@@ -48,8 +47,49 @@
 #define CRB_HI(off)	((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
 #define CRB_INDIRECT_2M	(0x1e0000UL)
 
+#ifndef readq
+static inline u64 readq(void __iomem *addr)
+{
+	return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(u64 val, void __iomem *addr)
+{
+	writel(((u32) (val)), (addr));
+	writel(((u32) (val >> 32)), (addr + 4));
+}
+#endif
+
+#define ADDR_IN_RANGE(addr, low, high)	\
+	(((addr) < (high)) && ((addr) >= (low)))
+
+#define PCI_OFFSET_FIRST_RANGE(adapter, off)    \
+	((adapter)->ahw.pci_base0 + (off))
+#define PCI_OFFSET_SECOND_RANGE(adapter, off)   \
+	((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START)
+#define PCI_OFFSET_THIRD_RANGE(adapter, off)    \
+	((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START)
+
+static void __iomem *pci_base_offset(struct netxen_adapter *adapter,
+					    unsigned long off)
+{
+	if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END))
+		return PCI_OFFSET_FIRST_RANGE(adapter, off);
+
+	if (ADDR_IN_RANGE(off, SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_END))
+		return PCI_OFFSET_SECOND_RANGE(adapter, off);
+
+	if (ADDR_IN_RANGE(off, THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_END))
+		return PCI_OFFSET_THIRD_RANGE(adapter, off);
+
+	return NULL;
+}
+
 #define CRB_WIN_LOCK_TIMEOUT 100000000
-static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
+static crb_128M_2M_block_map_t
+crb_128M_2M_map[64] __cacheline_aligned_in_smp = {
     {{{0, 0,         0,         0} } },		/* 0: PCI */
     {{{1, 0x0100000, 0x0102000, 0x120000},	/* 1: PCIE */
 	  {1, 0x0110000, 0x0120000, 0x130000},
@@ -279,39 +319,8 @@
 
 /*  PCI Windowing for DDR regions.  */
 
-#define ADDR_IN_RANGE(addr, low, high)	\
-	(((addr) <= (high)) && ((addr) >= (low)))
-
 #define NETXEN_WINDOW_ONE 	0x2000000 /*CRB Window: bit 25 of CRB address */
 
-#define NETXEN_NIC_ZERO_PAUSE_ADDR     0ULL
-#define NETXEN_NIC_UNIT_PAUSE_ADDR     0x200ULL
-#define NETXEN_NIC_EPG_PAUSE_ADDR1     0x2200010000c28001ULL
-#define NETXEN_NIC_EPG_PAUSE_ADDR2     0x0100088866554433ULL
-
-#define NETXEN_NIC_WINDOW_MARGIN 0x100000
-
-int netxen_nic_set_mac(struct net_device *netdev, void *p)
-{
-	struct netxen_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-
-	/* For P3, MAC addr is not set in NIU */
-	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
-		if (adapter->macaddr_set)
-			adapter->macaddr_set(adapter, addr->sa_data);
-
-	return 0;
-}
-
 #define NETXEN_UNICAST_ADDR(port, index) \
 	(NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
 #define NETXEN_MCAST_ADDR(port, index) \
@@ -331,22 +340,20 @@
 	if (adapter->mc_enabled)
 		return 0;
 
-	adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);
 	val |= (1UL << (28+port));
-	adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
 
 	/* add broadcast addr to filter */
 	val = 0xffffff;
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_UNICAST_ADDR(port, 0)+4, val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);
 
 	/* add station addr to filter */
 	val = MAC_HI(addr);
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
 	val = MAC_LO(addr);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_UNICAST_ADDR(port, 1)+4, val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, val);
 
 	adapter->mc_enabled = 1;
 	return 0;
@@ -362,18 +369,17 @@
 	if (!adapter->mc_enabled)
 		return 0;
 
-	adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);
 	val &= ~(1UL << (28+port));
-	adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
 
 	val = MAC_HI(addr);
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
 	val = MAC_LO(addr);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_UNICAST_ADDR(port, 0)+4, val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);
 
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
 
 	adapter->mc_enabled = 0;
 	return 0;
@@ -389,10 +395,8 @@
 	lo = MAC_LO(addr);
 	hi = MAC_HI(addr);
 
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_MCAST_ADDR(port, index), hi);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_MCAST_ADDR(port, index)+4, lo);
+	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index), hi);
+	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index)+4, lo);
 
 	return 0;
 }
@@ -445,100 +449,59 @@
 		netxen_nic_set_mcast_addr(adapter, index, null_addr);
 }
 
-static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
-		u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
-{
-	nx_mac_list_t *cur, *prev;
-
-	/* if in del_list, move it to adapter->mac_list */
-	for (cur = *del_list, prev = NULL; cur;) {
-		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
-			if (prev == NULL)
-				*del_list = cur->next;
-			else
-				prev->next = cur->next;
-			cur->next = adapter->mac_list;
-			adapter->mac_list = cur;
-			return 0;
-		}
-		prev = cur;
-		cur = cur->next;
-	}
-
-	/* make sure to add each mac address only once */
-	for (cur = adapter->mac_list; cur; cur = cur->next) {
-		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
-			return 0;
-	}
-	/* not in del_list, create new entry and add to add_list */
-	cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
-	if (cur == NULL) {
-		printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
-				"not work properly from now.\n", __func__);
-		return -1;
-	}
-
-	memcpy(cur->mac_addr, addr, ETH_ALEN);
-	cur->next = *add_list;
-	*add_list = cur;
-	return 0;
-}
-
 static int
 netxen_send_cmd_descs(struct netxen_adapter *adapter,
-		struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
+		struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
 {
-	uint32_t i, producer;
+	u32 i, producer, consumer;
 	struct netxen_cmd_buffer *pbuf;
 	struct cmd_desc_type0 *cmd_desc;
-
-	if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
-		printk(KERN_WARNING "%s: Too many command descriptors in a "
-			      "request\n", __func__);
-		return -EINVAL;
-	}
+	struct nx_host_tx_ring *tx_ring;
 
 	i = 0;
 
-	netif_tx_lock_bh(adapter->netdev);
+	tx_ring = adapter->tx_ring;
+	__netif_tx_lock_bh(tx_ring->txq);
+
+	producer = tx_ring->producer;
+	consumer = tx_ring->sw_consumer;
+
+	if (nr_desc >= netxen_tx_avail(tx_ring)) {
+		netif_tx_stop_queue(tx_ring->txq);
+		__netif_tx_unlock_bh(tx_ring->txq);
+		return -EBUSY;
+	}
 
-	producer = adapter->cmd_producer;
 	do {
 		cmd_desc = &cmd_desc_arr[i];
 
-		pbuf = &adapter->cmd_buf_arr[producer];
+		pbuf = &tx_ring->cmd_buf_arr[producer];
 		pbuf->skb = NULL;
 		pbuf->frag_count = 0;
 
-		/* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
-		memcpy(&adapter->ahw.cmd_desc_head[producer],
+		memcpy(&tx_ring->desc_head[producer],
 			&cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
 
-		producer = get_next_index(producer,
-				adapter->num_txd);
+		producer = get_next_index(producer, tx_ring->num_desc);
 		i++;
 
-	} while (i != nr_elements);
-
-	adapter->cmd_producer = producer;
+	} while (i != nr_desc);
 
-	/* write producer index to start the xmit */
+	tx_ring->producer = producer;
 
-	netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+	netxen_nic_update_cmd_producer(adapter, tx_ring);
 
-	netif_tx_unlock_bh(adapter->netdev);
+	__netif_tx_unlock_bh(tx_ring->txq);
 
 	return 0;
 }
 
-static int nx_p3_sre_macaddr_change(struct net_device *dev,
-		u8 *addr, unsigned op)
+static int
+nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op)
 {
-	struct netxen_adapter *adapter = netdev_priv(dev);
 	nx_nic_req_t req;
 	nx_mac_req_t *mac_req;
 	u64 word;
-	int rv;
 
 	memset(&req, 0, sizeof(nx_nic_req_t));
 	req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
@@ -550,28 +513,51 @@
 	mac_req->op = op;
 	memcpy(mac_req->mac_addr, addr, 6);
 
-	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
-	if (rv != 0) {
-		printk(KERN_ERR "ERROR. Could not send mac update\n");
-		return rv;
+	return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+}
+
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+		u8 *addr, struct list_head *del_list)
+{
+	struct list_head *head;
+	nx_mac_list_t *cur;
+
+	/* look up if already exists */
+	list_for_each(head, del_list) {
+		cur = list_entry(head, nx_mac_list_t, list);
+
+		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+			list_move_tail(head, &adapter->mac_list);
+			return 0;
+		}
 	}
 
-	return 0;
+	cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC);
+	if (cur == NULL) {
+		printk(KERN_ERR "%s: failed to add mac address filter\n",
+				adapter->netdev->name);
+		return -ENOMEM;
+	}
+	memcpy(cur->mac_addr, addr, ETH_ALEN);
+	list_add_tail(&cur->list, &adapter->mac_list);
+	return nx_p3_sre_macaddr_change(adapter,
+				cur->mac_addr, NETXEN_MAC_ADD);
 }
 
 void netxen_p3_nic_set_multi(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
 	struct dev_mc_list *mc_ptr;
 	u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 	u32 mode = VPORT_MISS_MODE_DROP;
+	LIST_HEAD(del_list);
+	struct list_head *head;
+	nx_mac_list_t *cur;
 
-	del_list = adapter->mac_list;
-	adapter->mac_list = NULL;
+	list_splice_tail_init(&adapter->mac_list, &del_list);
 
-	nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
-	nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+	nx_p3_nic_add_mac(adapter, netdev->dev_addr, &del_list);
+	nx_p3_nic_add_mac(adapter, bcast_addr, &del_list);
 
 	if (netdev->flags & IFF_PROMISC) {
 		mode = VPORT_MISS_MODE_ACCEPT_ALL;
@@ -587,25 +573,20 @@
 	if (netdev->mc_count > 0) {
 		for (mc_ptr = netdev->mc_list; mc_ptr;
 		     mc_ptr = mc_ptr->next) {
-			nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
-					  &add_list, &del_list);
+			nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list);
 		}
 	}
 
 send_fw_cmd:
 	adapter->set_promisc(adapter, mode);
-	for (cur = del_list; cur;) {
-		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
-		next = cur->next;
+	head = &del_list;
+	while (!list_empty(head)) {
+		cur = list_entry(head->next, nx_mac_list_t, list);
+
+		nx_p3_sre_macaddr_change(adapter,
+				cur->mac_addr, NETXEN_MAC_DEL);
+		list_del(&cur->list);
 		kfree(cur);
-		cur = next;
-	}
-	for (cur = add_list; cur;) {
-		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
-		next = cur->next;
-		cur->next = adapter->mac_list;
-		adapter->mac_list = cur;
-		cur = next;
 	}
 }
 
@@ -630,17 +611,25 @@
 
 void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
 {
-	nx_mac_list_t *cur, *next;
-
-	cur = adapter->mac_list;
+	nx_mac_list_t *cur;
+	struct list_head *head = &adapter->mac_list;
 
-	while (cur) {
-		next = cur->next;
+	while (!list_empty(head)) {
+		cur = list_entry(head->next, nx_mac_list_t, list);
+		nx_p3_sre_macaddr_change(adapter,
+				cur->mac_addr, NETXEN_MAC_DEL);
+		list_del(&cur->list);
 		kfree(cur);
-		cur = next;
 	}
 }
 
+int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+{
+	/* assuming caller has already copied new addr to netdev */
+	netxen_p3_nic_set_multi(adapter->netdev);
+	return 0;
+}
+
 #define	NETXEN_CONFIG_INTR_COALESCE	3
 
 /*
@@ -717,6 +706,28 @@
 	return rv;
 }
 
+int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)
+{
+	nx_nic_req_t req;
+	u64 word;
+	int rv;
+
+	memset(&req, 0, sizeof(nx_nic_req_t));
+	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
+
+	word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
+	req.req_hdr = cpu_to_le64(word);
+	req.words[0] = cpu_to_le64(enable | (enable << 8));
+
+	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv != 0) {
+		printk(KERN_ERR "%s: could not configure link notification\n",
+				adapter->netdev->name);
+	}
+
+	return rv;
+}
+
 /*
  * netxen_nic_change_mtu - Change the Maximum Transfer Unit
  * @returns 0 on success, negative on failure
@@ -812,8 +823,8 @@
 	crbaddr = CRB_MAC_BLOCK_START +
 		(4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
 
-	adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4);
-	adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4);
+	mac_lo = NXRD32(adapter, crbaddr);
+	mac_hi = NXRD32(adapter, crbaddr+4);
 
 	if (pci_func & 1)
 		*mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));
@@ -831,8 +842,7 @@
 
 	while (!done) {
 		/* acquire semaphore3 from PCI HW block */
-		adapter->hw_read_wx(adapter,
-				NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_LOCK));
 		if (done == 1)
 			break;
 		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
@@ -840,8 +850,7 @@
 		timeout++;
 		udelay(1);
 	}
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
+	NXWR32(adapter, NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
 	return 0;
 }
 
@@ -849,8 +858,7 @@
 {
 	int val;
 
-	adapter->hw_read_wx(adapter,
-			NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4);
+	val = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK));
 }
 
 /*
@@ -907,17 +915,15 @@
  * In: 'off' is offset from base in 128M pci map
  */
 static int
-netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
-		ulong *off, int len)
+netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off)
 {
-	unsigned long end = *off + len;
 	crb_128M_2M_sub_block_map_t *m;
 
 
 	if (*off >= NETXEN_CRB_MAX)
 		return -1;
 
-	if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
+	if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) {
 		*off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
 			(ulong)adapter->ahw.pci_base0;
 		return 0;
@@ -927,14 +933,13 @@
 		return -1;
 
 	*off -= NETXEN_PCI_CRBSPACE;
-	end = *off + len;
 
 	/*
 	 * Try direct map
 	 */
 	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
 
-	if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
 		*off = *off + m->start_2M - m->start_128M +
 			(ulong)adapter->ahw.pci_base0;
 		return 0;
@@ -972,214 +977,11 @@
 		(ulong)adapter->ahw.pci_base0;
 }
 
-static int
-netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname,
-		const struct firmware *fw)
-{
-	u64 *ptr64;
-	u32 i, flashaddr, size;
-	struct pci_dev *pdev = adapter->pdev;
-
-	if (fw)
-		dev_info(&pdev->dev, "loading firmware from file %s\n", fwname);
-	else
-		dev_info(&pdev->dev, "loading firmware from flash\n");
-
-	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_CAS_RST, 1);
-
-	if (fw) {
-		__le64 data;
-
-		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;
-
-		ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
-		flashaddr = NETXEN_BOOTLD_START;
-
-		for (i = 0; i < size; i++) {
-			data = cpu_to_le64(ptr64[i]);
-			adapter->pci_mem_write(adapter, flashaddr, &data, 8);
-			flashaddr += 8;
-		}
-
-		size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
-		size = (__force u32)cpu_to_le32(size) / 8;
-
-		ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
-		flashaddr = NETXEN_IMAGE_START;
-
-		for (i = 0; i < size; i++) {
-			data = cpu_to_le64(ptr64[i]);
-
-			if (adapter->pci_mem_write(adapter,
-						flashaddr, &data, 8))
-				return -EIO;
-
-			flashaddr += 8;
-		}
-	} else {
-		u32 data;
-
-		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4;
-		flashaddr = NETXEN_BOOTLD_START;
-
-		for (i = 0; i < size; i++) {
-			if (netxen_rom_fast_read(adapter,
-					flashaddr, (int *)&data) != 0)
-				return -EIO;
-
-			if (adapter->pci_mem_write(adapter,
-						flashaddr, &data, 4))
-				return -EIO;
-
-			flashaddr += 4;
-		}
-	}
-	msleep(1);
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
-	else {
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_CAS_RST, 0);
-	}
-
-	return 0;
-}
-
-static int
-netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname,
-		const struct firmware *fw)
-{
-	__le32 val;
-	u32 major, minor, build, ver, min_ver, bios;
-	struct pci_dev *pdev = adapter->pdev;
-
-	if (fw->size < NX_FW_MIN_SIZE)
-		return -EINVAL;
-
-	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
-	if ((__force u32)val != NETXEN_BDINFO_MAGIC)
-		return -EINVAL;
-
-	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
-	major = (__force u32)val & 0xff;
-	minor = ((__force u32)val >> 8) & 0xff;
-	build = (__force u32)val >> 16;
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		min_ver = NETXEN_VERSION_CODE(4, 0, 216);
-	else
-		min_ver = NETXEN_VERSION_CODE(3, 4, 216);
-
-	ver = NETXEN_VERSION_CODE(major, minor, build);
-
-	if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
-		dev_err(&pdev->dev,
-				"%s: firmware version %d.%d.%d unsupported\n",
-				fwname, major, minor, build);
-		return -EINVAL;
-	}
-
-	val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
-	netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
-	if ((__force u32)val != bios) {
-		dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
-				fwname);
-		return -EINVAL;
-	}
-
-	/* check if flashed firmware is newer */
-	if (netxen_rom_fast_read(adapter,
-			NX_FW_VERSION_OFFSET, (int *)&val))
-		return -EIO;
-	major = (__force u32)val & 0xff;
-	minor = ((__force u32)val >> 8) & 0xff;
-	build = (__force u32)val >> 16;
-	if (NETXEN_VERSION_CODE(major, minor, build) > ver)
-		return -EINVAL;
-
-	netxen_nic_reg_write(adapter, NETXEN_CAM_RAM(0x1fc),
-			NETXEN_BDINFO_MAGIC);
-	return 0;
-}
-
-static char *fw_name[] = { "/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/" };
-
-int netxen_load_firmware(struct netxen_adapter *adapter)
-{
-	u32 capability, flashed_ver;
-	const struct firmware *fw;
-	int fw_type;
-	struct pci_dev *pdev = adapter->pdev;
-	int rc = 0;
-
-	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
-		fw_type = NX_P2_MN_ROMIMAGE;
-		goto request_fw;
-	} else {
-		fw_type = NX_P3_CT_ROMIMAGE;
-		goto request_fw;
-	}
-
-request_mn:
-	capability = 0;
-
-	netxen_rom_fast_read(adapter,
-			NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
-	if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
-		adapter->hw_read_wx(adapter,
-				NX_PEG_TUNE_CAPABILITY, &capability, 4);
-		if (capability & NX_PEG_TUNE_MN_PRESENT) {
-			fw_type = NX_P3_MN_ROMIMAGE;
-			goto request_fw;
-		}
-	}
-
-request_fw:
-	rc = reject_firmware(&fw, fw_name[fw_type], &pdev->dev);
-	if (rc != 0) {
-		if (fw_type == NX_P3_CT_ROMIMAGE) {
-			msleep(1);
-			goto request_mn;
-		}
-
-		fw = NULL;
-		goto load_fw;
-	}
-
-	rc = netxen_validate_firmware(adapter, fw_name[fw_type], fw);
-	if (rc != 0) {
-		release_firmware(fw);
-
-		if (fw_type == NX_P3_CT_ROMIMAGE) {
-			msleep(1);
-			goto request_mn;
-		}
-
-		fw = NULL;
-	}
-
-load_fw:
-	rc = netxen_do_load_firmware(adapter, fw_name[fw_type], fw);
-
-	if (fw)
-		release_firmware(fw);
-	return rc;
-}
-
 int
-netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data)
 {
 	void __iomem *addr;
 
-	BUG_ON(len != 4);
-
 	if (ADDR_IN_WINDOW1(off)) {
 		addr = NETXEN_CRB_NORMALIZE(adapter, off);
 	} else {		/* Window 0 */
@@ -1192,7 +994,7 @@
 		return 1;
 	}
 
-	writel(*(u32 *) data, addr);
+	writel(data, addr);
 
 	if (!ADDR_IN_WINDOW1(off))
 		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
@@ -1200,13 +1002,11 @@
 	return 0;
 }
 
-int
-netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+u32
+netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off)
 {
 	void __iomem *addr;
-
-	BUG_ON(len != 4);
+	u32 data;
 
 	if (ADDR_IN_WINDOW1(off)) {	/* Window 1 */
 		addr = NETXEN_CRB_NORMALIZE(adapter, off);
@@ -1220,24 +1020,21 @@
 		return 1;
 	}
 
-	*(u32 *)data = readl(addr);
+	data = readl(addr);
 
 	if (!ADDR_IN_WINDOW1(off))
 		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 
-	return 0;
+	return data;
 }
 
 int
-netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data)
 {
 	unsigned long flags = 0;
 	int rv;
 
-	BUG_ON(len != 4);
-
-	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
 
 	if (rv == -1) {
 		printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
@@ -1250,26 +1047,24 @@
 		write_lock_irqsave(&adapter->adapter_lock, flags);
 		crb_win_lock(adapter);
 		netxen_nic_pci_set_crbwindow_2M(adapter, &off);
-		writel(*(uint32_t *)data, (void __iomem *)off);
+		writel(data, (void __iomem *)off);
 		crb_win_unlock(adapter);
 		write_unlock_irqrestore(&adapter->adapter_lock, flags);
 	} else
-		writel(*(uint32_t *)data, (void __iomem *)off);
+		writel(data, (void __iomem *)off);
 
 
 	return 0;
 }
 
-int
-netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+u32
+netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off)
 {
 	unsigned long flags = 0;
 	int rv;
+	u32 data;
 
-	BUG_ON(len != 4);
-
-	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
 
 	if (rv == -1) {
 		printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
@@ -1282,47 +1077,13 @@
 		write_lock_irqsave(&adapter->adapter_lock, flags);
 		crb_win_lock(adapter);
 		netxen_nic_pci_set_crbwindow_2M(adapter, &off);
-		*(uint32_t *)data = readl((void __iomem *)off);
+		data = readl((void __iomem *)off);
 		crb_win_unlock(adapter);
 		write_unlock_irqrestore(&adapter->adapter_lock, flags);
 	} else
-		*(uint32_t *)data = readl((void __iomem *)off);
-
-	return 0;
-}
-
-void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
-{
-	adapter->hw_write_wx(adapter, off, &val, 4);
-}
-
-int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
-{
-	int val;
-	adapter->hw_read_wx(adapter, off, &val, 4);
-	return val;
-}
-
-/* Change the window to 0, write and change back to window 1. */
-void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
-{
-	adapter->hw_write_wx(adapter, index, &value, 4);
-}
-
-/* Change the window to 0, read and change back to window 1. */
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value)
-{
-	adapter->hw_read_wx(adapter, index, value, 4);
-}
-
-void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value)
-{
-	adapter->hw_write_wx(adapter, index, &value, 4);
-}
+		data = readl((void __iomem *)off);
 
-void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value)
-{
-	adapter->hw_read_wx(adapter, index, value, 4);
+	return data;
 }
 
 /*
@@ -1425,17 +1186,6 @@
 	return readl((void __iomem *)(pci_base_offset(adapter, off)));
 }
 
-void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
-		u64 off, u32 data)
-{
-	writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
-}
-
-u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off)
-{
-	return readl(NETXEN_CRB_NORMALIZE(adapter, off));
-}
-
 unsigned long
 netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
 		unsigned long long addr)
@@ -1447,12 +1197,10 @@
 		/* DDR network side */
 		window = MN_WIN(addr);
 		adapter->ahw.ddr_mn_window = window;
-		adapter->hw_write_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&window, 4);
-		adapter->hw_read_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&win_read, 4);
+		NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				window);
+		win_read = NXRD32(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE);
 		if ((win_read << 17) != window) {
 			printk(KERN_INFO "Written MNwin (0x%x) != "
 				"Read MNwin (0x%x)\n", window, win_read);
@@ -1467,12 +1215,10 @@
 
 		window = OCM_WIN(addr);
 		adapter->ahw.ddr_mn_window = window;
-		adapter->hw_write_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&window, 4);
-		adapter->hw_read_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&win_read, 4);
+		NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				window);
+		win_read = NXRD32(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE);
 		if ((win_read >> 7) != window) {
 			printk(KERN_INFO "%s: Written OCMwin (0x%x) != "
 					"Read OCMwin (0x%x)\n",
@@ -1485,12 +1231,10 @@
 		/* QDR network side */
 		window = MS_WIN(addr);
 		adapter->ahw.qdr_sn_window = window;
-		adapter->hw_write_wx(adapter,
-				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
-				&window, 4);
-		adapter->hw_read_wx(adapter,
-				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
-				&win_read, 4);
+		NXWR32(adapter, adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+				window);
+		win_read = NXRD32(adapter,
+				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE);
 		if (win_read != window) {
 			printk(KERN_INFO "%s: Written MSwin (0x%x) != "
 					"Read MSwin (0x%x)\n",
@@ -1936,27 +1680,20 @@
 
 	for (i = 0; i < loop; i++) {
 		temp = off8 + (i << 3);
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
 		temp = 0;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);
 		temp = word[i] & 0xffffffff;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);
 		temp = (word[i] >> 32) & 0xffffffff;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);
 		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp);
 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp);
 
 		for (j = 0; j < MAX_CTL_CHECK; j++) {
-			adapter->hw_read_wx(adapter,
-					mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+			temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL);
 			if ((temp & MIU_TA_CTL_BUSY) == 0)
 				break;
 		}
@@ -2013,21 +1750,16 @@
 
 	for (i = 0; i < loop; i++) {
 		temp = off8 + (i << 3);
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
 		temp = 0;
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
 		temp = MIU_TA_CTL_ENABLE;
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp);
 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp);
 
 		for (j = 0; j < MAX_CTL_CHECK; j++) {
-			adapter->hw_read_wx(adapter,
-					mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+			temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL);
 			if ((temp & MIU_TA_CTL_BUSY) == 0)
 				break;
 		}
@@ -2042,8 +1774,8 @@
 		start = off0[i] >> 2;
 		end   = (off0[i] + sz[i] - 1) >> 2;
 		for (k = start; k <= end; k++) {
-			adapter->hw_read_wx(adapter,
-				mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
+			temp = NXRD32(adapter,
+				mem_crb + MIU_TEST_AGT_RDDATA(k));
 			word[i] |= ((uint64_t)temp << (32 * k));
 		}
 	}
@@ -2086,29 +1818,14 @@
 int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
 		u64 off, u32 data)
 {
-	adapter->hw_write_wx(adapter, off, &data, 4);
+	NXWR32(adapter, off, data);
 
 	return 0;
 }
 
 u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off)
 {
-	u32 temp;
-	adapter->hw_read_wx(adapter, off, &temp, 4);
-	return temp;
-}
-
-void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
-		u64 off, u32 data)
-{
-	adapter->hw_write_wx(adapter, off, &data, 4);
-}
-
-u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off)
-{
-	u32 temp;
-	adapter->hw_read_wx(adapter, off, &temp, 4);
-	return temp;
+	return NXRD32(adapter, off);
 }
 
 int netxen_nic_get_board_info(struct netxen_adapter *adapter)
@@ -2142,13 +1859,12 @@
 	adapter->ahw.board_type = board_type;
 
 	if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
-		u32 gpio = netxen_nic_reg_read(adapter,
-				NETXEN_ROMUSB_GLB_PAD_GPIO_I);
+		u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I);
 		if ((gpio & 0x8000) == 0)
 			board_type = NETXEN_BRDTYPE_P3_10G_TP;
 	}
 
-	switch ((netxen_brdtype_t)board_type) {
+	switch (board_type) {
 	case NETXEN_BRDTYPE_P2_SB35_4G:
 		adapter->ahw.port_type = NETXEN_NIC_GBE;
 		break;
@@ -2195,8 +1911,7 @@
 int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu)
 {
 	new_mtu += MTU_FUDGE_FACTOR;
-	netxen_nic_write_w0(adapter,
-		NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
+	NXWR32(adapter, NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
 		new_mtu);
 	return 0;
 }
@@ -2205,21 +1920,12 @@
 {
 	new_mtu += MTU_FUDGE_FACTOR;
 	if (adapter->physical_port == 0)
-		netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE,
-				new_mtu);
+		NXWR32(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
 	else
-		netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE,
-				new_mtu);
+		NXWR32(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu);
 	return 0;
 }
 
-void
-netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
-		unsigned long off, int data)
-{
-	adapter->hw_write_wx(adapter, off, &data, 4);
-}
-
 void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
 {
 	__u32 status;
@@ -2234,8 +1940,7 @@
 	}
 
 	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
-		adapter->hw_read_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &port_mode, 4);
+		port_mode = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
 		if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
 			adapter->link_speed   = SPEED_1000;
 			adapter->link_duplex  = DUPLEX_FULL;
@@ -2312,9 +2017,9 @@
 		addr += sizeof(u32);
 	}
 
-	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4);
-	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4);
-	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4);
+	fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+	fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+	fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
 
 	adapter->fw_major = fw_major;
 	adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build);
@@ -2337,9 +2042,8 @@
 			fw_major, fw_minor, fw_build);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
-		adapter->hw_read_wx(adapter,
-				NETXEN_MIU_MN_CONTROL, &i, 4);
-		adapter->ahw.cut_through = (i & 0x4) ? 1 : 0;
+		i = NXRD32(adapter, NETXEN_SRE_MISC);
+		adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0;
 		dev_info(&pdev->dev, "firmware running in %s mode\n",
 		adapter->ahw.cut_through ? "cut-through" : "legacy");
 	}
@@ -2353,9 +2057,9 @@
 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
 		return 0;
 
-	wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV);
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
 	if (wol_cfg & (1UL << adapter->portnum)) {
-		wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG);
+		wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
 		if (wol_cfg & (1 << adapter->portnum))
 			return 1;
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_hw.h linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_hw.h
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_hw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_hw.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,35 +36,13 @@
 /* Hardware memory size of 128 meg */
 #define NETXEN_MEMADDR_MAX (128 * 1024 * 1024)
 
-#ifndef readq
-static inline u64 readq(void __iomem * addr)
-{
-	return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
-}
-#endif
-
-#ifndef writeq
-static inline void writeq(u64 val, void __iomem * addr)
-{
-	writel(((u32) (val)), (addr));
-	writel(((u32) (val >> 32)), (addr + 4));
-}
-#endif
-
 struct netxen_adapter;
 
 #define NETXEN_PCI_MAPSIZE_BYTES  (NETXEN_PCI_MAPSIZE << 20)
 
-struct netxen_port;
 void netxen_nic_set_link_parameters(struct netxen_adapter *adapter);
 
-typedef u8 netxen_ethernet_macaddr_t[6];
-
 /* Nibble or Byte mode for phy interface (GbE mode only) */
-typedef enum {
-	NETXEN_NIU_10_100_MB = 0,
-	NETXEN_NIU_1000_MB
-} netxen_niu_gbe_ifmode_t;
 
 #define _netxen_crb_get_bit(var, bit)  ((var >> bit) & 0x1)
 
@@ -222,30 +200,28 @@
 /*
  * PHY-Specific MII control/status registers.
  */
-typedef enum {
-	NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27
-} netxen_niu_phy_register_t;
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL		0
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS		1
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0		2
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1		3
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG		4
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART		5
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE	6
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT	7
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE	8
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL	9
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS	10
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS	15
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL		16
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS		17
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE		18
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS		19
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE	20
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT	21
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL		24
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE	25
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET	26
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE	27
 
 /*
  * PHY-Specific Status Register (reg 17).
@@ -417,14 +393,6 @@
 int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
 				       u32 mode);
 
-/* set the MAC address for a given MAC */
-int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
-			   netxen_ethernet_macaddr_t addr);
-
-/* XG version */
-int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
-			      netxen_ethernet_macaddr_t addr);
-
 /* Generic enable for GbE ports. Will detect the speed of the link. */
 int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_init.c linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_init.c
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_init.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_init.c	2012-03-22 20:11:16.000000000 -0400
@@ -108,42 +108,6 @@
 	crb_addr_transform(I2C0);
 }
 
-int netxen_init_firmware(struct netxen_adapter *adapter)
-{
-	u32 state = 0, loops = 0, err = 0;
-
-	/* Window 1 call */
-	state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
-
-	if (state == PHAN_INITIALIZE_ACK)
-		return 0;
-
-	while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
-		msleep(1);
-		/* Window 1 call */
-		state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
-
-		loops++;
-	}
-	if (loops >= 2000) {
-		printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
-		       state);
-		err = -EIO;
-		return err;
-	}
-	/* Window 1 call */
-	adapter->pci_write_normalize(adapter,
-			CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
-	adapter->pci_write_normalize(adapter,
-			CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
-	adapter->pci_write_normalize(adapter,
-			CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
-	adapter->pci_write_normalize(adapter,
-			CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
-
-	return err;
-}
-
 void netxen_release_rx_buffers(struct netxen_adapter *adapter)
 {
 	struct netxen_recv_context *recv_ctx;
@@ -173,9 +137,10 @@
 	struct netxen_cmd_buffer *cmd_buf;
 	struct netxen_skb_frag *buffrag;
 	int i, j;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 
-	cmd_buf = adapter->cmd_buf_arr;
-	for (i = 0; i < adapter->num_txd; i++) {
+	cmd_buf = tx_ring->cmd_buf_arr;
+	for (i = 0; i < tx_ring->num_desc; i++) {
 		buffrag = cmd_buf->frag_array;
 		if (buffrag->dma) {
 			pci_unmap_single(adapter->pdev, buffrag->dma,
@@ -203,20 +168,27 @@
 {
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
+	struct nx_host_tx_ring *tx_ring;
 	int ring;
 
 	recv_ctx = &adapter->recv_ctx;
+
+	if (recv_ctx->rds_rings == NULL)
+		goto skip_rds;
+
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
-		if (rds_ring->rx_buf_arr) {
-			vfree(rds_ring->rx_buf_arr);
-			rds_ring->rx_buf_arr = NULL;
-		}
+		vfree(rds_ring->rx_buf_arr);
+		rds_ring->rx_buf_arr = NULL;
 	}
+	kfree(recv_ctx->rds_rings);
 
-	if (adapter->cmd_buf_arr)
-		vfree(adapter->cmd_buf_arr);
-	return;
+skip_rds:
+	if (adapter->tx_ring == NULL)
+		return;
+
+	tx_ring = adapter->tx_ring;
+	vfree(tx_ring->cmd_buf_arr);
 }
 
 int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
@@ -224,23 +196,46 @@
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
 	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
 	struct netxen_rx_buffer *rx_buf;
-	int ring, i, num_rx_bufs;
+	int ring, i, size;
 
 	struct netxen_cmd_buffer *cmd_buf_arr;
 	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
 
-	cmd_buf_arr =
-		(struct netxen_cmd_buffer *)vmalloc(TX_BUFF_RINGSIZE(adapter));
+	size = sizeof(struct nx_host_tx_ring);
+	tx_ring = kzalloc(size, GFP_KERNEL);
+	if (tx_ring == NULL) {
+		dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n",
+		       netdev->name);
+		return -ENOMEM;
+	}
+	adapter->tx_ring = tx_ring;
+
+	tx_ring->num_desc = adapter->num_txd;
+	tx_ring->txq = netdev_get_tx_queue(netdev, 0);
+
+	cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
 	if (cmd_buf_arr == NULL) {
-		printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
+		dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
 		       netdev->name);
 		return -ENOMEM;
 	}
-	memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(adapter));
-	adapter->cmd_buf_arr = cmd_buf_arr;
+	memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
+	tx_ring->cmd_buf_arr = cmd_buf_arr;
 
 	recv_ctx = &adapter->recv_ctx;
+
+	size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring);
+	rds_ring = kzalloc(size, GFP_KERNEL);
+	if (rds_ring == NULL) {
+		dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
+		       netdev->name);
+		return -ENOMEM;
+	}
+	recv_ctx->rds_rings = rds_ring;
+
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
 		switch (ring) {
@@ -292,9 +287,8 @@
 		 * Now go through all of them, set reference handles
 		 * and put them in the queues.
 		 */
-		num_rx_bufs = rds_ring->num_desc;
 		rx_buf = rds_ring->rx_buf_arr;
-		for (i = 0; i < num_rx_bufs; i++) {
+		for (i = 0; i < rds_ring->num_desc; i++) {
 			list_add_tail(&rx_buf->list,
 					&rds_ring->free_list);
 			rx_buf->ref_handle = i;
@@ -307,8 +301,6 @@
 	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 		sds_ring = &recv_ctx->sds_rings[ring];
 		sds_ring->irq = adapter->msix_entries[ring].vector;
-		sds_ring->clean_tx = (ring == 0);
-		sds_ring->post_rxd = (ring == 0);
 		sds_ring->adapter = adapter;
 		sds_ring->num_desc = adapter->num_rxd;
 
@@ -325,13 +317,15 @@
 
 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
 {
+	adapter->macaddr_set = netxen_p2_nic_set_mac_addr;
+	adapter->set_multi = netxen_p2_nic_set_multi;
+
 	switch (adapter->ahw.port_type) {
 	case NETXEN_NIC_GBE:
 		adapter->enable_phy_interrupts =
 		    netxen_niu_gbe_enable_phy_interrupts;
 		adapter->disable_phy_interrupts =
 		    netxen_niu_gbe_disable_phy_interrupts;
-		adapter->macaddr_set = netxen_niu_macaddr_set;
 		adapter->set_mtu = netxen_nic_set_mtu_gb;
 		adapter->set_promisc = netxen_niu_set_promiscuous_mode;
 		adapter->phy_read = netxen_niu_gbe_phy_read;
@@ -345,7 +339,6 @@
 		    netxen_niu_xgbe_enable_phy_interrupts;
 		adapter->disable_phy_interrupts =
 		    netxen_niu_xgbe_disable_phy_interrupts;
-		adapter->macaddr_set = netxen_niu_xg_macaddr_set;
 		adapter->set_mtu = netxen_nic_set_mtu_xgb;
 		adapter->init_port = netxen_niu_xg_init_port;
 		adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
@@ -359,6 +352,8 @@
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 		adapter->set_mtu = nx_fw_cmd_set_mtu;
 		adapter->set_promisc = netxen_p3_nic_set_promisc;
+		adapter->macaddr_set = netxen_p3_nic_set_mac_addr;
+		adapter->set_multi = netxen_p3_nic_set_multi;
 	}
 }
 
@@ -400,8 +395,7 @@
 
 	while (!done) {
 		/* acquire semaphore2 from PCI HW block */
-		netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
-				   &done);
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK));
 		if (done == 1)
 			break;
 		if (timeout >= rom_lock_timeout)
@@ -418,7 +412,7 @@
 				cpu_relax();	/*This a nop instr on i386 */
 		}
 	}
-	netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
+	NXWR32(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
 	return 0;
 }
 
@@ -430,7 +424,7 @@
 	cond_resched();
 
 	while (done == 0) {
-		done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
+		done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS);
 		done &= 2;
 		timeout++;
 		if (timeout >= rom_max_timeout) {
@@ -443,30 +437,28 @@
 
 static void netxen_rom_unlock(struct netxen_adapter *adapter)
 {
-	u32 val;
-
 	/* release semaphore2 */
-	netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
+	NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK));
 
 }
 
 static int do_rom_fast_read(struct netxen_adapter *adapter,
 			    int addr, int *valp)
 {
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
 	if (netxen_wait_rom_done(adapter)) {
 		printk("Error waiting for rom done\n");
 		return -EIO;
 	}
 	/* reset abyte_cnt and dummy_byte_cnt */
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
 	udelay(10);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
 
-	*valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
+	*valp = NXRD32(adapter, NETXEN_ROMUSB_ROM_RDATA);
 	return 0;
 }
 
@@ -530,8 +522,7 @@
 
 	/* resetall */
 	rom_lock(adapter);
-	netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
-				    0xffffffff);
+	NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff);
 	netxen_rom_unlock(adapter);
 
 	if (verbose) {
@@ -655,7 +646,7 @@
 			}
 		}
 
-		adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
+		NXWR32(adapter, off, buf[i].data);
 
 		msleep(init_delay);
 	}
@@ -665,36 +656,303 @@
 
 	/* unreset_net_cache */
 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
-		adapter->hw_read_wx(adapter,
-				NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
-		netxen_crb_writelit_adapter(adapter,
-				NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
+		val = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET);
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
 	}
 
 	/* p2dn replyCount */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
 	/* disable_peg_cache 0 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
 	/* disable_peg_cache 1 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
 
 	/* peg_clr_all */
 
 	/* peg_clr 0 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
 	/* peg_clr 1 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
 	/* peg_clr 2 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
 	/* peg_clr 3 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
+	return 0;
+}
+
+int
+netxen_need_fw_reset(struct netxen_adapter *adapter)
+{
+	u32 count, old_count;
+	u32 val, version, major, minor, build;
+	int i, timeout;
+	u8 fw_type;
+
+	/* NX2031 firmware doesn't support heartbit */
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		return 1;
+
+	/* last attempt had failed */
+	if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
+		return 1;
+
+	old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+
+	for (i = 0; i < 10; i++) {
+
+		timeout = msleep_interruptible(200);
+		if (timeout) {
+			NXWR32(adapter, CRB_CMDPEG_STATE,
+					PHAN_INITIALIZE_FAILED);
+			return -EINTR;
+		}
+
+		count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+		if (count != old_count)
+			break;
+	}
+
+	/* firmware is dead */
+	if (count == old_count)
+		return 1;
+
+	/* check if we have got newer or different file firmware */
+	if (adapter->fw) {
+
+		const struct firmware *fw = adapter->fw;
+
+		val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+		version = NETXEN_DECODE_VERSION(val);
+
+		major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+		minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+		build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
+
+		if (version > NETXEN_VERSION_CODE(major, minor, build))
+			return 1;
+
+		if (version == NETXEN_VERSION_CODE(major, minor, build)) {
+
+			val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL);
+			fw_type = (val & 0x4) ?
+				NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE;
+
+			if (adapter->fw_type != fw_type)
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+static char *fw_name[] = {
+	"/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/", "/*(DEBLOBBED)*/", "flash",
+};
+
+int
+netxen_load_firmware(struct netxen_adapter *adapter)
+{
+	u64 *ptr64;
+	u32 i, flashaddr, size;
+	const struct firmware *fw = adapter->fw;
+	struct pci_dev *pdev = adapter->pdev;
+
+	dev_info(&pdev->dev, "loading firmware from %s\n",
+			fw_name[adapter->fw_type]);
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);
+
+	if (fw) {
+		__le64 data;
+
+		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;
+
+		ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
+		flashaddr = NETXEN_BOOTLD_START;
+
+		for (i = 0; i < size; i++) {
+			data = cpu_to_le64(ptr64[i]);
+			adapter->pci_mem_write(adapter, flashaddr, &data, 8);
+			flashaddr += 8;
+		}
+
+		size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
+		size = (__force u32)cpu_to_le32(size) / 8;
+
+		ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
+		flashaddr = NETXEN_IMAGE_START;
+
+		for (i = 0; i < size; i++) {
+			data = cpu_to_le64(ptr64[i]);
+
+			if (adapter->pci_mem_write(adapter,
+						flashaddr, &data, 8))
+				return -EIO;
+
+			flashaddr += 8;
+		}
+	} else {
+		u32 data;
+
+		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4;
+		flashaddr = NETXEN_BOOTLD_START;
+
+		for (i = 0; i < size; i++) {
+			if (netxen_rom_fast_read(adapter,
+					flashaddr, (int *)&data) != 0)
+				return -EIO;
+
+			if (adapter->pci_mem_write(adapter,
+						flashaddr, &data, 4))
+				return -EIO;
+
+			flashaddr += 4;
+		}
+	}
+	msleep(1);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
+	else {
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0);
+	}
+
 	return 0;
 }
 
+static int
+netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
+{
+	__le32 val;
+	u32 ver, min_ver, bios;
+	struct pci_dev *pdev = adapter->pdev;
+	const struct firmware *fw = adapter->fw;
+
+	if (fw->size < NX_FW_MIN_SIZE)
+		return -EINVAL;
+
+	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
+	if ((__force u32)val != NETXEN_BDINFO_MAGIC)
+		return -EINVAL;
+
+	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		min_ver = NETXEN_VERSION_CODE(4, 0, 216);
+	else
+		min_ver = NETXEN_VERSION_CODE(3, 4, 216);
+
+	ver = NETXEN_DECODE_VERSION(val);
+
+	if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+		dev_err(&pdev->dev,
+				"%s: firmware version %d.%d.%d unsupported\n",
+				fwname, _major(ver), _minor(ver), _build(ver));
+		return -EINVAL;
+	}
+
+	val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
+	netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
+	if ((__force u32)val != bios) {
+		dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
+				fwname);
+		return -EINVAL;
+	}
+
+	/* check if flashed firmware is newer */
+	if (netxen_rom_fast_read(adapter,
+			NX_FW_VERSION_OFFSET, (int *)&val))
+		return -EIO;
+	val = NETXEN_DECODE_VERSION(val);
+	if (val > ver) {
+		dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+				fwname);
+		return -EINVAL;
+	}
+
+	NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+	return 0;
+}
+
+void netxen_reject_firmware(struct netxen_adapter *adapter)
+{
+	u32 capability, flashed_ver;
+	u8 fw_type;
+	struct pci_dev *pdev = adapter->pdev;
+	int rc = 0;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+		fw_type = NX_P2_MN_ROMIMAGE;
+		goto request_fw;
+	} else {
+		fw_type = NX_P3_CT_ROMIMAGE;
+		goto request_fw;
+	}
+
+request_mn:
+	capability = 0;
+
+	netxen_rom_fast_read(adapter,
+			NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
+	flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
+
+	if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
+		capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
+		if (capability & NX_PEG_TUNE_MN_PRESENT) {
+			fw_type = NX_P3_MN_ROMIMAGE;
+			goto request_fw;
+		}
+	}
+
+	fw_type = NX_FLASH_ROMIMAGE;
+	adapter->fw = NULL;
+	goto done;
+
+request_fw:
+	rc = reject_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
+	if (rc != 0) {
+		if (fw_type == NX_P3_CT_ROMIMAGE) {
+			msleep(1);
+			goto request_mn;
+		}
+
+		fw_type = NX_FLASH_ROMIMAGE;
+		adapter->fw = NULL;
+		goto done;
+	}
+
+	rc = netxen_validate_firmware(adapter, fw_name[fw_type]);
+	if (rc != 0) {
+		release_firmware(adapter->fw);
+
+		if (fw_type == NX_P3_CT_ROMIMAGE) {
+			msleep(1);
+			goto request_mn;
+		}
+
+		fw_type = NX_FLASH_ROMIMAGE;
+		adapter->fw = NULL;
+		goto done;
+	}
+
+done:
+	adapter->fw_type = fw_type;
+}
+
+
+void
+netxen_release_firmware(struct netxen_adapter *adapter)
+{
+	if (adapter->fw)
+		release_firmware(adapter->fw);
+}
+
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
 {
 	uint64_t addr;
@@ -715,12 +973,12 @@
 	hi = (addr >> 32) & 0xffffffff;
 	lo = addr & 0xffffffff;
 
-	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
-	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
+	NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
+	NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 		uint32_t temp = 0;
-		adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
+		NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp);
 	}
 
 	return 0;
@@ -760,38 +1018,41 @@
 	u32 val = 0;
 	int retries = 60;
 
-	if (!pegtune_val) {
-		do {
-			val = adapter->pci_read_normalize(adapter,
-					CRB_CMDPEG_STATE);
+	if (pegtune_val)
+		return 0;
 
-			if (val == PHAN_INITIALIZE_COMPLETE ||
-				val == PHAN_INITIALIZE_ACK)
-				return 0;
+	do {
+		val = NXRD32(adapter, CRB_CMDPEG_STATE);
 
-			msleep(500);
+		switch (val) {
+		case PHAN_INITIALIZE_COMPLETE:
+		case PHAN_INITIALIZE_ACK:
+			return 0;
+		case PHAN_INITIALIZE_FAILED:
+			goto out_err;
+		default:
+			break;
+		}
 
-		} while (--retries);
+		msleep(500);
 
-		if (!retries) {
-			pegtune_val = adapter->pci_read_normalize(adapter,
-					NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
-			printk(KERN_WARNING "netxen_phantom_init: init failed, "
-					"pegtune_val=%x\n", pegtune_val);
-			return -1;
-		}
-	}
+	} while (--retries);
 
-	return 0;
+	NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+
+out_err:
+	dev_warn(&adapter->pdev->dev, "firmware init failed\n");
+	return -EIO;
 }
 
-int netxen_receive_peg_ready(struct netxen_adapter *adapter)
+static int
+netxen_receive_peg_ready(struct netxen_adapter *adapter)
 {
 	u32 val = 0;
 	int retries = 2000;
 
 	do {
-		val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);
+		val = NXRD32(adapter, CRB_RCVPEG_STATE);
 
 		if (val == PHAN_PEG_RCV_INITIALIZED)
 			return 0;
@@ -809,6 +1070,93 @@
 	return 0;
 }
 
+int netxen_init_firmware(struct netxen_adapter *adapter)
+{
+	int err;
+
+	err = netxen_receive_peg_ready(adapter);
+	if (err)
+		return err;
+
+	NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
+	NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
+	NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
+	NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+
+	if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) {
+		adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
+	}
+
+	return err;
+}
+
+static void
+netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg)
+{
+	u32 cable_OUI;
+	u16 cable_len;
+	u16 link_speed;
+	u8  link_status, module, duplex, autoneg;
+	struct net_device *netdev = adapter->netdev;
+
+	adapter->has_link_events = 1;
+
+	cable_OUI = msg->body[1] & 0xffffffff;
+	cable_len = (msg->body[1] >> 32) & 0xffff;
+	link_speed = (msg->body[1] >> 48) & 0xffff;
+
+	link_status = msg->body[2] & 0xff;
+	duplex = (msg->body[2] >> 16) & 0xff;
+	autoneg = (msg->body[2] >> 24) & 0xff;
+
+	module = (msg->body[2] >> 8) & 0xff;
+	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) {
+		printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n",
+				netdev->name, cable_OUI, cable_len);
+	} else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) {
+		printk(KERN_INFO "%s: unsupported cable length %d\n",
+				netdev->name, cable_len);
+	}
+
+	netxen_advert_link_change(adapter, link_status);
+
+	/* update link parameters */
+	if (duplex == LINKEVENT_FULL_DUPLEX)
+		adapter->link_duplex = DUPLEX_FULL;
+	else
+		adapter->link_duplex = DUPLEX_HALF;
+	adapter->module_type = module;
+	adapter->link_autoneg = autoneg;
+	adapter->link_speed = link_speed;
+}
+
+static void
+netxen_handle_fw_message(int desc_cnt, int index,
+		struct nx_host_sds_ring *sds_ring)
+{
+	nx_fw_msg_t msg;
+	struct status_desc *desc;
+	int i = 0, opcode;
+
+	while (desc_cnt > 0 && i < 8) {
+		desc = &sds_ring->desc_head[index];
+		msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
+		msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
+
+		index = get_next_index(index, sds_ring->num_desc);
+		desc_cnt--;
+	}
+
+	opcode = netxen_get_nic_msg_opcode(msg.body[0]);
+	switch (opcode) {
+	case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
+		netxen_handle_linkevent(sds_ring->adapter, &msg);
+		break;
+	default:
+		break;
+	}
+}
+
 static int
 netxen_alloc_rx_skb(struct netxen_adapter *adapter,
 		struct nx_host_rds_ring *rds_ring,
@@ -874,7 +1222,8 @@
 
 static struct netxen_rx_buffer *
 netxen_process_rcv(struct netxen_adapter *adapter,
-		int ring, int index, int length, int cksum, int pkt_offset)
+		int ring, int index, int length, int cksum, int pkt_offset,
+		struct nx_host_sds_ring *sds_ring)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
@@ -902,7 +1251,7 @@
 
 	skb->protocol = eth_type_trans(skb, netdev);
 
-	netif_receive_skb(skb);
+	napi_gro_receive(&sds_ring->napi, skb);
 
 	adapter->stats.no_rcv++;
 	adapter->stats.rxbytes += length;
@@ -927,35 +1276,53 @@
 
 	int count = 0;
 	u64 sts_data;
-	int opcode, ring, index, length, cksum, pkt_offset;
+	int opcode, ring, index, length, cksum, pkt_offset, desc_cnt;
 
 	while (count < max) {
 		desc = &sds_ring->desc_head[consumer];
-		sts_data = le64_to_cpu(desc->status_desc_data);
+		sts_data = le64_to_cpu(desc->status_desc_data[0]);
 
 		if (!(sts_data & STATUS_OWNER_HOST))
 			break;
 
+		desc_cnt = netxen_get_sts_desc_cnt(sts_data);
 		ring   = netxen_get_sts_type(sts_data);
+
 		if (ring > RCV_RING_JUMBO)
-			continue;
+			goto skip;
 
 		opcode = netxen_get_sts_opcode(sts_data);
 
+		switch (opcode) {
+		case NETXEN_NIC_RXPKT_DESC:
+		case NETXEN_OLD_RXPKT_DESC:
+			break;
+		case NETXEN_NIC_RESPONSE_DESC:
+			netxen_handle_fw_message(desc_cnt, consumer, sds_ring);
+		default:
+			goto skip;
+		}
+
+		WARN_ON(desc_cnt > 1);
+
 		index  = netxen_get_sts_refhandle(sts_data);
 		length = netxen_get_sts_totallength(sts_data);
 		cksum  = netxen_get_sts_status(sts_data);
 		pkt_offset = netxen_get_sts_pkt_offset(sts_data);
 
 		rxbuf = netxen_process_rcv(adapter, ring, index,
-				length, cksum, pkt_offset);
+				length, cksum, pkt_offset, sds_ring);
 
 		if (rxbuf)
 			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
 
-		desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM);
-
-		consumer = get_next_index(consumer, sds_ring->num_desc);
+skip:
+		for (; desc_cnt > 0; desc_cnt--) {
+			desc = &sds_ring->desc_head[consumer];
+			desc->status_desc_data[0] =
+				cpu_to_le64(STATUS_OWNER_PHANTOM);
+			consumer = get_next_index(consumer, sds_ring->num_desc);
+		}
 		count++;
 	}
 
@@ -980,8 +1347,7 @@
 
 	if (count) {
 		sds_ring->consumer = consumer;
-		adapter->pci_write_normalize(adapter,
-				sds_ring->crb_sts_consumer, consumer);
+		NXWR32(adapter, sds_ring->crb_sts_consumer, consumer);
 	}
 
 	return count;
@@ -990,23 +1356,23 @@
 /* Process Command status ring */
 int netxen_process_cmd_ring(struct netxen_adapter *adapter)
 {
-	u32 last_consumer, consumer;
+	u32 sw_consumer, hw_consumer;
 	int count = 0, i;
 	struct netxen_cmd_buffer *buffer;
 	struct pci_dev *pdev = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
 	struct netxen_skb_frag *frag;
 	int done = 0;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 
 	if (!spin_trylock(&adapter->tx_clean_lock))
 		return 1;
 
-	last_consumer = adapter->last_cmd_consumer;
-	barrier(); /* cmd_consumer can change underneath */
-	consumer = le32_to_cpu(*(adapter->cmd_consumer));
+	sw_consumer = tx_ring->sw_consumer;
+	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
 
-	while (last_consumer != consumer) {
-		buffer = &adapter->cmd_buf_arr[last_consumer];
+	while (sw_consumer != hw_consumer) {
+		buffer = &tx_ring->cmd_buf_arr[sw_consumer];
 		if (buffer->skb) {
 			frag = &buffer->frag_array[0];
 			pci_unmap_single(pdev, frag->dma, frag->length,
@@ -1024,20 +1390,21 @@
 			buffer->skb = NULL;
 		}
 
-		last_consumer = get_next_index(last_consumer,
-					       adapter->num_txd);
+		sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
 		if (++count >= MAX_STATUS_HANDLE)
 			break;
 	}
 
-	if (count) {
-		adapter->last_cmd_consumer = last_consumer;
+	if (count && netif_running(netdev)) {
+		tx_ring->sw_consumer = sw_consumer;
+
 		smp_mb();
-		if (netif_queue_stopped(netdev) && netif_running(netdev)) {
-			netif_tx_lock(netdev);
-			netif_wake_queue(netdev);
-			smp_mb();
-			netif_tx_unlock(netdev);
+
+		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
+			__netif_tx_lock(tx_ring->txq, smp_processor_id());
+			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+				netif_wake_queue(netdev);
+			__netif_tx_unlock(tx_ring->txq);
 		}
 	}
 	/*
@@ -1053,9 +1420,8 @@
 	 * There is still a possible race condition and the host could miss an
 	 * interrupt. The card has to take care of this.
 	 */
-	barrier(); /* cmd_consumer can change underneath */
-	consumer = le32_to_cpu(*(adapter->cmd_consumer));
-	done = (last_consumer == consumer);
+	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+	done = (sw_consumer == hw_consumer);
 	spin_unlock(&adapter->tx_clean_lock);
 
 	return (done);
@@ -1099,8 +1465,7 @@
 
 	if (count) {
 		rds_ring->producer = producer;
-		adapter->pci_write_normalize(adapter,
-				rds_ring->crb_rcv_producer,
+		NXWR32(adapter, rds_ring->crb_rcv_producer,
 				(producer-1) & (rds_ring->num_desc-1));
 
 		if (adapter->fw_major < 4) {
@@ -1160,10 +1525,8 @@
 
 	if (count) {
 		rds_ring->producer = producer;
-		adapter->pci_write_normalize(adapter,
-			rds_ring->crb_rcv_producer,
+		NXWR32(adapter, rds_ring->crb_rcv_producer,
 				(producer - 1) & (rds_ring->num_desc - 1));
-			wmb();
 	}
 	spin_unlock(&rds_ring->lock);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_main.c linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_main.c
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_main.c	2012-03-22 20:11:13.000000000 -0400
@@ -29,7 +29,7 @@
  */
 
 #include <linux/vmalloc.h>
-#include <linux/highmem.h>
+#include <linux/interrupt.h>
 #include "netxen_nic_hw.h"
 
 #include "netxen_nic.h"
@@ -94,10 +94,6 @@
 
 MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
 
-static struct workqueue_struct *netxen_workq;
-#define SCHEDULE_WORK(tp)	queue_work(netxen_workq, tp)
-#define FLUSH_SCHEDULED_WORK()	flush_workqueue(netxen_workq)
-
 static void netxen_watchdog(unsigned long);
 
 static uint32_t crb_cmd_producer[4] = {
@@ -107,10 +103,14 @@
 
 void
 netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
-		uint32_t crb_producer)
+		struct nx_host_tx_ring *tx_ring)
 {
-	adapter->pci_write_normalize(adapter,
-			adapter->crb_addr_cmd_producer, crb_producer);
+	NXWR32(adapter, tx_ring->crb_cmd_producer, tx_ring->producer);
+
+	if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) {
+		netif_stop_queue(adapter->netdev);
+		smp_mb();
+	}
 }
 
 static uint32_t crb_cmd_consumer[4] = {
@@ -120,10 +120,9 @@
 
 static inline void
 netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
-		u32 crb_consumer)
+		struct nx_host_tx_ring *tx_ring)
 {
-	adapter->pci_write_normalize(adapter,
-			adapter->crb_addr_cmd_consumer, crb_consumer);
+	NXWR32(adapter, tx_ring->crb_cmd_consumer, tx_ring->sw_consumer);
 }
 
 static uint32_t msi_tgt_status[8] = {
@@ -139,37 +138,71 @@
 {
 	struct netxen_adapter *adapter = sds_ring->adapter;
 
-	adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0);
+	NXWR32(adapter, sds_ring->crb_intr_mask, 0);
 }
 
 static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring)
 {
 	struct netxen_adapter *adapter = sds_ring->adapter;
 
-	adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1);
+	NXWR32(adapter, sds_ring->crb_intr_mask, 0x1);
 
 	if (!NETXEN_IS_MSI_FAMILY(adapter))
 		adapter->pci_write_immediate(adapter,
 				adapter->legacy_intr.tgt_mask_reg, 0xfbff);
 }
 
+static int
+netxen_alloc_sds_rings(struct netxen_recv_context *recv_ctx, int count)
+{
+	int size = sizeof(struct nx_host_sds_ring) * count;
+
+	recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
+
+	return (recv_ctx->sds_rings == NULL);
+}
+
 static void
+netxen_free_sds_rings(struct netxen_recv_context *recv_ctx)
+{
+	if (recv_ctx->sds_rings != NULL)
+		kfree(recv_ctx->sds_rings);
+
+	recv_ctx->sds_rings = NULL;
+}
+
+static int
 netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
 {
 	int ring;
 	struct nx_host_sds_ring *sds_ring;
 	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
-	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
-		adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2;
-	else
-		adapter->max_sds_rings = 1;
+	if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
+		return 1;
 
 	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 		sds_ring = &recv_ctx->sds_rings[ring];
 		netif_napi_add(netdev, &sds_ring->napi,
 				netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
 	}
+
+	return 0;
+}
+
+static void
+netxen_napi_del(struct netxen_adapter *adapter)
+{
+	int ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		netif_napi_del(&sds_ring->napi);
+	}
+
+	netxen_free_sds_rings(&adapter->recv_ctx);
 }
 
 static void
@@ -196,11 +229,12 @@
 	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 		sds_ring = &recv_ctx->sds_rings[ring];
 		netxen_nic_disable_int(sds_ring);
+		napi_synchronize(&sds_ring->napi);
 		napi_disable(&sds_ring->napi);
 	}
 }
 
-static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+static int nx_set_dma_mask(struct netxen_adapter *adapter)
 {
 	struct pci_dev *pdev = adapter->pdev;
 	uint64_t mask, cmask;
@@ -208,19 +242,17 @@
 	adapter->pci_using_dac = 0;
 
 	mask = DMA_BIT_MASK(32);
-	/*
-	 * Consistent DMA mask is set to 32 bit because it cannot be set to
-	 * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
-	 * come off this pool.
-	 */
 	cmask = DMA_BIT_MASK(32);
 
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 #ifndef CONFIG_IA64
-	if (revision_id >= NX_P3_B0)
-		mask = DMA_BIT_MASK(39);
-	else if (revision_id == NX_P2_C1)
 		mask = DMA_BIT_MASK(35);
 #endif
+	} else {
+		mask = DMA_BIT_MASK(39);
+		cmask = mask;
+	}
+
 	if (pci_set_dma_mask(pdev, mask) == 0 &&
 		pci_set_consistent_dma_mask(pdev, cmask) == 0) {
 		adapter->pci_using_dac = 1;
@@ -235,13 +267,13 @@
 nx_update_dma_mask(struct netxen_adapter *adapter)
 {
 	int change, shift, err;
-	uint64_t mask, old_mask;
+	uint64_t mask, old_mask, old_cmask;
 	struct pci_dev *pdev = adapter->pdev;
 
 	change = 0;
 
-	shift = netxen_nic_reg_read(adapter, CRB_DMA_SHIFT);
-	if (shift >= 32)
+	shift = NXRD32(adapter, CRB_DMA_SHIFT);
+	if (shift > 32)
 		return 0;
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9))
@@ -251,14 +283,29 @@
 
 	if (change) {
 		old_mask = pdev->dma_mask;
-		mask = (1ULL<<(32+shift)) - 1;
+		old_cmask = pdev->dev.coherent_dma_mask;
+
+		mask = DMA_BIT_MASK(32+shift);
 
 		err = pci_set_dma_mask(pdev, mask);
 		if (err)
-			return pci_set_dma_mask(pdev, old_mask);
+			goto err_out;
+
+		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+
+			err = pci_set_consistent_dma_mask(pdev, mask);
+			if (err)
+				goto err_out;
+		}
+		dev_info(&pdev->dev, "using %d-bit dma mask\n", 32+shift);
 	}
 
 	return 0;
+
+err_out:
+	pci_set_dma_mask(pdev, old_mask);
+	pci_set_consistent_dma_mask(pdev, old_cmask);
+	return err;
 }
 
 static void netxen_check_options(struct netxen_adapter *adapter)
@@ -268,10 +315,21 @@
 	else if (adapter->ahw.port_type == NETXEN_NIC_GBE)
 		adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G;
 
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+	adapter->msix_supported = 0;
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 		adapter->msix_supported = !!use_msi_x;
-	else
-		adapter->msix_supported = 0;
+		adapter->rss_supported = !!use_msi_x;
+	} else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) {
+		switch (adapter->ahw.board_type) {
+		case NETXEN_BRDTYPE_P2_SB31_10G:
+		case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+			adapter->msix_supported = !!use_msi_x;
+			adapter->rss_supported = !!use_msi_x;
+			break;
+		default:
+			break;
+		}
+	}
 
 	adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST;
 	adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS;
@@ -287,43 +345,34 @@
 
 	if (first_boot == 0x55555555) {
 		/* This is the first boot after power up */
-		adapter->pci_write_normalize(adapter,
-			NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+		NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
 
 		if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
 			return 0;
 
 		/* PCI bus master workaround */
-		adapter->hw_read_wx(adapter,
-			NETXEN_PCIE_REG(0x4), &first_boot, 4);
+		first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4));
 		if (!(first_boot & 0x4)) {
 			first_boot |= 0x4;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PCIE_REG(0x4), &first_boot, 4);
-			adapter->hw_read_wx(adapter,
-				NETXEN_PCIE_REG(0x4), &first_boot, 4);
+			NXWR32(adapter, NETXEN_PCIE_REG(0x4), first_boot);
+			first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4));
 		}
 
 		/* This is the first boot after power up */
-		adapter->hw_read_wx(adapter,
-			NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4);
+		first_boot = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET);
 		if (first_boot != 0x80000f) {
 			/* clear the register for future unloads/loads */
-			adapter->pci_write_normalize(adapter,
-					NETXEN_CAM_RAM(0x1fc), 0);
+			NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), 0);
 			return -EIO;
 		}
 
 		/* Start P2 boot loader */
-		val = adapter->pci_read_normalize(adapter,
-				NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1);
+		val = NXRD32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1);
 		timeout = 0;
 		do {
 			msleep(1);
-			val = adapter->pci_read_normalize(adapter,
-					NETXEN_CAM_RAM(0x1fc));
+			val = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc));
 
 			if (++timeout > 5000)
 				return -EIO;
@@ -342,24 +391,19 @@
 		(val == NETXEN_BRDTYPE_P3_XG_LOM)) {
 		if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
 			data = NETXEN_PORT_MODE_802_3_AP;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else if (port_mode == NETXEN_PORT_MODE_XG) {
 			data = NETXEN_PORT_MODE_XG;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) {
 			data = NETXEN_PORT_MODE_AUTO_NEG_1G;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) {
 			data = NETXEN_PORT_MODE_AUTO_NEG_XG;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else {
 			data = NETXEN_PORT_MODE_AUTO_NEG;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		}
 
 		if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) &&
@@ -368,8 +412,7 @@
 			(wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) {
 			wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG;
 		}
-		adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE,
-			&wol_port_mode, 4);
+		NXWR32(adapter, NETXEN_WOL_PORT_MODE, wol_port_mode);
 	}
 }
 
@@ -389,11 +432,11 @@
 	}
 }
 
-static void netxen_init_msix_entries(struct netxen_adapter *adapter)
+static void netxen_init_msix_entries(struct netxen_adapter *adapter, int count)
 {
 	int i;
 
-	for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++)
+	for (i = 0; i < count; i++)
 		adapter->msix_entries[i].entry = i;
 }
 
@@ -424,20 +467,38 @@
 
 	if (!is_valid_ether_addr(netdev->perm_addr))
 		dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr);
-	else
-		adapter->macaddr_set(adapter, netdev->dev_addr);
 
 	return 0;
 }
 
+int netxen_nic_set_mac(struct net_device *netdev, void *p)
+{
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EINVAL;
+
+	if (netif_running(netdev)) {
+		netif_device_detach(netdev);
+		netxen_napi_disable(adapter);
+	}
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	adapter->macaddr_set(adapter, addr->sa_data);
+
+	if (netif_running(netdev)) {
+		netif_device_attach(netdev);
+		netxen_napi_enable(adapter);
+	}
+	return 0;
+}
+
 static void netxen_set_multicast_list(struct net_device *dev)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
 
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		netxen_p3_nic_set_multi(dev);
-	else
-		netxen_p2_nic_set_multi(dev);
+	adapter->set_multi(dev);
 }
 
 static const struct net_device_ops netxen_netdev_ops = {
@@ -460,10 +521,17 @@
 {
 	struct netxen_legacy_intr_set *legacy_intrp;
 	struct pci_dev *pdev = adapter->pdev;
+	int err, num_msix;
+
+	if (adapter->rss_supported) {
+		num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
+			MSIX_ENTRIES_PER_ADAPTER : 2;
+	} else
+		num_msix = 1;
+
+	adapter->max_sds_rings = 1;
 
 	adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
-	adapter->intr_scheme = -1;
-	adapter->msi_mode = -1;
 
 	if (adapter->ahw.revision_id >= NX_P3_B0)
 		legacy_intrp = &legacy_intr[adapter->ahw.pci_func];
@@ -478,24 +546,36 @@
 
 	if (adapter->msix_supported) {
 
-		netxen_init_msix_entries(adapter);
-		if (pci_enable_msix(pdev, adapter->msix_entries,
-					MSIX_ENTRIES_PER_ADAPTER))
-			goto request_msi;
+		netxen_init_msix_entries(adapter, num_msix);
+		err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
+		if (err == 0) {
+			adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
+			netxen_set_msix_bit(pdev, 1);
 
-		adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
-		netxen_set_msix_bit(pdev, 1);
-		dev_info(&pdev->dev, "using msi-x interrupts\n");
+			if (adapter->rss_supported)
+				adapter->max_sds_rings = num_msix;
 
-	} else {
-request_msi:
-		if (use_msi && !pci_enable_msi(pdev)) {
-			adapter->flags |= NETXEN_NIC_MSI_ENABLED;
-			dev_info(&pdev->dev, "using msi interrupts\n");
-		} else
-			dev_info(&pdev->dev, "using legacy interrupts\n");
+			dev_info(&pdev->dev, "using msi-x interrupts\n");
+			return;
+		}
+
+		if (err > 0)
+			pci_disable_msix(pdev);
+
+		/* fall through for msi */
+	}
+
+	if (use_msi && !pci_enable_msi(pdev)) {
+		adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+		adapter->msi_tgt_status =
+			msi_tgt_status[adapter->ahw.pci_func];
+		dev_info(&pdev->dev, "using msi interrupts\n");
 		adapter->msix_entries[0].vector = pdev->irq;
+		return;
 	}
+
+	dev_info(&pdev->dev, "using legacy interrupts\n");
+	adapter->msix_entries[0].vector = pdev->irq;
 }
 
 static void
@@ -552,8 +632,6 @@
 	adapter->hw_read_wx = netxen_nic_hw_read_wx_128M;
 	adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M;
 	adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M;
-	adapter->pci_read_normalize = netxen_nic_pci_read_normalize_128M;
-	adapter->pci_write_normalize = netxen_nic_pci_write_normalize_128M;
 	adapter->pci_set_window = netxen_nic_pci_set_window_128M;
 	adapter->pci_mem_read = netxen_nic_pci_mem_read_128M;
 	adapter->pci_mem_write = netxen_nic_pci_mem_write_128M;
@@ -575,9 +653,6 @@
 		adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M;
 		adapter->pci_write_immediate =
 			netxen_nic_pci_write_immediate_2M;
-		adapter->pci_read_normalize = netxen_nic_pci_read_normalize_2M;
-		adapter->pci_write_normalize =
-			netxen_nic_pci_write_normalize_2M;
 		adapter->pci_set_window = netxen_nic_pci_set_window_2M;
 		adapter->pci_mem_read = netxen_nic_pci_mem_read_2M;
 		adapter->pci_mem_write = netxen_nic_pci_mem_write_2M;
@@ -643,25 +718,22 @@
 }
 
 static int
-netxen_start_firmware(struct netxen_adapter *adapter)
+netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
 {
 	int val, err, first_boot;
 	struct pci_dev *pdev = adapter->pdev;
 
 	int first_driver = 0;
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
-		if (adapter->ahw.pci_func == 0)
-			first_driver = 1;
-	} else {
-		if (adapter->portnum == 0)
-			first_driver = 1;
-	}
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		first_driver = (adapter->portnum == 0);
+	else
+		first_driver = (adapter->ahw.pci_func == 0);
 
 	if (!first_driver)
-		return 0;
+		goto wait_init;
 
-	first_boot = adapter->pci_read_normalize(adapter,
-			NETXEN_CAM_RAM(0x1fc));
+	first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc));
 
 	err = netxen_check_hw_init(adapter, first_boot);
 	if (err) {
@@ -669,14 +741,20 @@
 		return err;
 	}
 
+	if (request_fw)
+		netxen_reject_firmware(adapter);
+
+	err = netxen_need_fw_reset(adapter);
+	if (err <= 0)
+		return err;
+
 	if (first_boot != 0x55555555) {
-		adapter->pci_write_normalize(adapter,
-					CRB_CMDPEG_STATE, 0);
+		NXWR32(adapter, CRB_CMDPEG_STATE, 0);
 		netxen_pinit_from_rom(adapter, 0);
 		msleep(1);
 	}
 
-	netxen_nic_reg_write(adapter, CRB_DMA_SHIFT, 0x55555555);
+	NXWR32(adapter, CRB_DMA_SHIFT, 0x55555555);
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 		netxen_set_port_mode(adapter);
 
@@ -688,8 +766,7 @@
 		val = 0x7654;
 		if (adapter->ahw.port_type == NETXEN_NIC_XGBE)
 			val |= 0x0f000000;
-		netxen_crb_writelit_adapter(adapter,
-				NETXEN_MAC_ADDR_CNTL_REG, val);
+		NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
 
 	}
 
@@ -703,8 +780,9 @@
 	val = (_NETXEN_NIC_LINUX_MAJOR << 16)
 		| ((_NETXEN_NIC_LINUX_MINOR << 8))
 		| (_NETXEN_NIC_LINUX_SUBVERSION);
-	adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, val);
+	NXWR32(adapter, CRB_DRIVER_VERSION, val);
 
+wait_init:
 	/* Handshake with the card before we register the devices. */
 	err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
 	if (err) {
@@ -726,15 +804,6 @@
 	struct net_device *netdev = adapter->netdev;
 	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
-	if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
-		(adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
-		printk(KERN_ERR "%s: Firmware interrupt scheme is "
-				"incompatible with driver\n",
-				netdev->name);
-		adapter->driver_mismatch = 1;
-		return -EINVAL;
-	}
-
 	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
 		handler = netxen_msix_intr;
 	else if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
@@ -747,7 +816,7 @@
 
 	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
 		sds_ring = &recv_ctx->sds_rings[ring];
-		sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring);
+		sprintf(sds_ring->name, "%s[%d]", netdev->name, ring);
 		err = request_irq(sds_ring->irq, handler,
 				  flags, sds_ring->name, sds_ring);
 		if (err)
@@ -782,38 +851,47 @@
 				netxen_nic_driver_name, adapter->portnum);
 		return err;
 	}
-	adapter->macaddr_set(adapter, netdev->dev_addr);
-
-	netxen_nic_set_link_parameters(adapter);
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		adapter->macaddr_set(adapter, netdev->dev_addr);
 
-	netxen_set_multicast_list(netdev);
-	if (adapter->set_mtu)
-		adapter->set_mtu(adapter, netdev->mtu);
+	adapter->set_multi(netdev);
+	adapter->set_mtu(adapter, netdev->mtu);
 
 	adapter->ahw.linkup = 0;
-	mod_timer(&adapter->watchdog_timer, jiffies);
-
-	netxen_napi_enable(adapter);
 
 	if (adapter->max_sds_rings > 1)
 		netxen_config_rss(adapter, 1);
 
+	netxen_napi_enable(adapter);
+
+	if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
+		netxen_linkevent_request(adapter, 1);
+	else
+		netxen_nic_set_link_parameters(adapter);
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+
 	return 0;
 }
 
 static void
 netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
 {
+	spin_lock(&adapter->tx_clean_lock);
 	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-	netxen_napi_disable(adapter);
+	netif_tx_disable(netdev);
 
 	if (adapter->stop_port)
 		adapter->stop_port(adapter);
 
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		netxen_p3_free_mac_list(adapter);
+
+	netxen_napi_disable(adapter);
+
 	netxen_release_tx_buffers(adapter);
+	spin_unlock(&adapter->tx_clean_lock);
 
-	FLUSH_SCHEDULED_WORK();
 	del_timer_sync(&adapter->watchdog_timer);
 }
 
@@ -825,12 +903,15 @@
 	struct pci_dev *pdev = adapter->pdev;
 	int err, ring;
 	struct nx_host_rds_ring *rds_ring;
+	struct nx_host_tx_ring *tx_ring;
 
 	err = netxen_init_firmware(adapter);
-	if (err != 0) {
-		printk(KERN_ERR "Failed to init firmware\n");
-		return -EIO;
-	}
+	if (err)
+		return err;
+
+	err = netxen_napi_add(adapter, netdev);
+	if (err)
+		return err;
 
 	if (adapter->fw_major < 4)
 		adapter->max_rds_rings = 3;
@@ -854,13 +935,15 @@
 	}
 
 	if (adapter->fw_major < 4) {
-		adapter->crb_addr_cmd_producer =
-			crb_cmd_producer[adapter->portnum];
-		adapter->crb_addr_cmd_consumer =
-			crb_cmd_consumer[adapter->portnum];
+		tx_ring = adapter->tx_ring;
+		tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum];
+		tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum];
 
-		netxen_nic_update_cmd_producer(adapter, 0);
-		netxen_nic_update_cmd_consumer(adapter, 0);
+		tx_ring->producer = 0;
+		tx_ring->sw_consumer = 0;
+
+		netxen_nic_update_cmd_producer(adapter, tx_ring);
+		netxen_nic_update_cmd_consumer(adapter, tx_ring);
 	}
 
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
@@ -889,10 +972,10 @@
 static void
 netxen_nic_detach(struct netxen_adapter *adapter)
 {
-	netxen_nic_free_irq(adapter);
-
-	netxen_release_rx_buffers(adapter);
 	netxen_free_hw_resources(adapter);
+	netxen_release_rx_buffers(adapter);
+	netxen_nic_free_irq(adapter);
+	netxen_napi_del(adapter);
 	netxen_free_sw_resources(adapter);
 
 	adapter->is_up = 0;
@@ -951,12 +1034,13 @@
 	revision_id = pdev->revision;
 	adapter->ahw.revision_id = revision_id;
 
-	err = nx_set_dma_mask(adapter, revision_id);
+	err = nx_set_dma_mask(adapter);
 	if (err)
 		goto err_out_free_netdev;
 
 	rwlock_init(&adapter->adapter_lock);
 	spin_lock_init(&adapter->tx_clean_lock);
+	INIT_LIST_HEAD(&adapter->mac_list);
 
 	err = netxen_setup_pci_map(adapter);
 	if (err)
@@ -979,6 +1063,7 @@
 	SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
 
 	netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+	netdev->features |= (NETIF_F_GRO);
 	netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
 
 	if (NX_IS_REVISION_P3(revision_id)) {
@@ -1011,7 +1096,7 @@
 		break;
 	}
 
-	err = netxen_start_firmware(adapter);
+	err = netxen_start_firmware(adapter, 1);
 	if (err)
 		goto err_out_iounmap;
 
@@ -1024,8 +1109,7 @@
 	 */
 	adapter->physical_port = adapter->portnum;
 	if (adapter->fw_major < 4) {
-		i = adapter->pci_read_normalize(adapter,
-				CRB_V2P(adapter->portnum));
+		i = NXRD32(adapter, CRB_V2P(adapter->portnum));
 		if (i != 0x55555555)
 			adapter->physical_port = i;
 	}
@@ -1036,12 +1120,6 @@
 
 	netdev->irq = adapter->msix_entries[0].vector;
 
-	netxen_napi_add(adapter, netdev);
-
-	err = netxen_receive_peg_ready(adapter);
-	if (err)
-		goto err_out_disable_msi;
-
 	init_timer(&adapter->watchdog_timer);
 	adapter->watchdog_timer.function = &netxen_watchdog;
 	adapter->watchdog_timer.data = (unsigned long)adapter;
@@ -1111,11 +1189,11 @@
 
 	unregister_netdev(netdev);
 
+	cancel_work_sync(&adapter->watchdog_task);
+	cancel_work_sync(&adapter->tx_timeout_task);
+
 	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
 		netxen_nic_detach(adapter);
-
-		if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-			netxen_p3_free_mac_list(adapter);
 	}
 
 	if (adapter->portnum == 0)
@@ -1125,6 +1203,8 @@
 
 	netxen_cleanup_pci_map(adapter);
 
+	netxen_release_firmware(adapter);
+
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
@@ -1132,6 +1212,7 @@
 	free_netdev(netdev);
 }
 
+#ifdef CONFIG_PM
 static int
 netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
 {
@@ -1144,6 +1225,9 @@
 	if (netif_running(netdev))
 		netxen_nic_down(adapter, netdev);
 
+	cancel_work_sync(&adapter->watchdog_task);
+	cancel_work_sync(&adapter->tx_timeout_task);
+
 	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
 		netxen_nic_detach(adapter);
 
@@ -1176,7 +1260,7 @@
 
 	adapter->curr_window = 255;
 
-	err = netxen_start_firmware(adapter);
+	err = netxen_start_firmware(adapter, 0);
 	if (err) {
 		dev_err(&pdev->dev, "failed to start firmware\n");
 		return err;
@@ -1196,6 +1280,7 @@
 
 	return 0;
 }
+#endif
 
 static int netxen_nic_open(struct net_device *netdev)
 {
@@ -1315,7 +1400,7 @@
 netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	struct netxen_hardware_context *hw = &adapter->ahw;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 	unsigned int first_seg_len = skb->len - skb->data_len;
 	struct netxen_cmd_buffer *pbuf;
 	struct netxen_skb_frag *buffrag;
@@ -1324,30 +1409,26 @@
 	dma_addr_t temp_dma;
 	int i, k;
 
-	u32 producer, consumer;
+	u32 producer;
 	int frag_count, no_of_desc;
-	u32 num_txd = adapter->num_txd;
+	u32 num_txd = tx_ring->num_desc;
 	bool is_tso = false;
 
 	frag_count = skb_shinfo(skb)->nr_frags + 1;
 
-	/* There 4 fragments per descriptor */
+	/* 4 fragments per cmd des */
 	no_of_desc = (frag_count + 3) >> 2;
 
-	producer = adapter->cmd_producer;
-	smp_mb();
-	consumer = adapter->last_cmd_consumer;
-	if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) {
+	if (unlikely(no_of_desc + 2) > netxen_tx_avail(tx_ring)) {
 		netif_stop_queue(netdev);
-		smp_mb();
 		return NETDEV_TX_BUSY;
 	}
 
-	/* Copy the descriptors into the hardware    */
-	hwdesc = &hw->cmd_desc_head[producer];
+	producer = tx_ring->producer;
+
+	hwdesc = &tx_ring->desc_head[producer];
 	netxen_clear_cmddesc((u64 *)hwdesc);
-	/* Take skb->data itself */
-	pbuf = &adapter->cmd_buf_arr[producer];
+	pbuf = &tx_ring->cmd_buf_arr[producer];
 
 	is_tso = netxen_tso_check(netdev, hwdesc, skb);
 
@@ -1376,9 +1457,9 @@
 		if ((i & 0x3) == 0) {
 			k = 0;
 			producer = get_next_index(producer, num_txd);
-			hwdesc = &hw->cmd_desc_head[producer];
+			hwdesc = &tx_ring->desc_head[producer];
 			netxen_clear_cmddesc((u64 *)hwdesc);
-			pbuf = &adapter->cmd_buf_arr[producer];
+			pbuf = &tx_ring->cmd_buf_arr[producer];
 			pbuf->skb = NULL;
 		}
 		frag = &skb_shinfo(skb)->frags[i - 1];
@@ -1430,8 +1511,8 @@
 			more_hdr = 0;
 		}
 		/* copy the MAC/IP/TCP headers to the cmd descriptor list */
-		hwdesc = &hw->cmd_desc_head[producer];
-		pbuf = &adapter->cmd_buf_arr[producer];
+		hwdesc = &tx_ring->desc_head[producer];
+		pbuf = &tx_ring->cmd_buf_arr[producer];
 		pbuf->skb = NULL;
 
 		/* copy the first 64 bytes */
@@ -1440,8 +1521,8 @@
 		producer = get_next_index(producer, num_txd);
 
 		if (more_hdr) {
-			hwdesc = &hw->cmd_desc_head[producer];
-			pbuf = &adapter->cmd_buf_arr[producer];
+			hwdesc = &tx_ring->desc_head[producer];
+			pbuf = &tx_ring->cmd_buf_arr[producer];
 			pbuf->skb = NULL;
 			/* copy the next 64 bytes - should be enough except
 			 * for pathological case
@@ -1454,13 +1535,12 @@
 		}
 	}
 
-	adapter->cmd_producer = producer;
+	tx_ring->producer = producer;
 	adapter->stats.txbytes += skb->len;
 
-	netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+	netxen_nic_update_cmd_producer(adapter, tx_ring);
 
 	adapter->stats.xmitcalled++;
-	netdev->trans_start = jiffies;
 
 	return NETDEV_TX_OK;
 
@@ -1476,7 +1556,7 @@
 	uint32_t temp, temp_state, temp_val;
 	int rv = 0;
 
-	temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE);
+	temp = NXRD32(adapter, CRB_TEMP_STATE);
 
 	temp_state = nx_get_temp_state(temp);
 	temp_val = nx_get_temp_val(temp);
@@ -1485,10 +1565,7 @@
 		printk(KERN_ALERT
 		       "%s: Device temperature %d degrees C exceeds"
 		       " maximum allowed. Hardware has been shut down.\n",
-		       netxen_nic_driver_name, temp_val);
-
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
+		       netdev->name, temp_val);
 		rv = 1;
 	} else if (temp_state == NX_TEMP_WARN) {
 		if (adapter->temp == NX_TEMP_NORMAL) {
@@ -1496,13 +1573,13 @@
 			       "%s: Device temperature %d degrees C "
 			       "exceeds operating range."
 			       " Immediate action needed.\n",
-			       netxen_nic_driver_name, temp_val);
+			       netdev->name, temp_val);
 		}
 	} else {
 		if (adapter->temp == NX_TEMP_WARN) {
 			printk(KERN_INFO
 			       "%s: Device temperature is now %d degrees C"
-			       " in normal range.\n", netxen_nic_driver_name,
+			       " in normal range.\n", netdev->name,
 			       temp_val);
 		}
 	}
@@ -1510,26 +1587,9 @@
 	return rv;
 }
 
-static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup)
 {
 	struct net_device *netdev = adapter->netdev;
-	u32 val, port, linkup;
-
-	port = adapter->physical_port;
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
-		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3);
-		val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
-		linkup = (val == XG_LINK_UP_P3);
-	} else {
-		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
-		if (adapter->ahw.port_type == NETXEN_NIC_GBE)
-			linkup = (val >> port) & 1;
-		else {
-			val = (val >> port*8) & 0xff;
-			linkup = (val == XG_LINK_UP);
-		}
-	}
 
 	if (adapter->ahw.linkup && !linkup) {
 		printk(KERN_INFO "%s: %s NIC Link is down\n",
@@ -1539,8 +1599,7 @@
 			netif_carrier_off(netdev);
 			netif_stop_queue(netdev);
 		}
-
-		netxen_nic_set_link_parameters(adapter);
+		adapter->link_changed = !adapter->has_link_events;
 	} else if (!adapter->ahw.linkup && linkup) {
 		printk(KERN_INFO "%s: %s NIC Link is up\n",
 		       netxen_nic_driver_name, netdev->name);
@@ -1549,16 +1608,63 @@
 			netif_carrier_on(netdev);
 			netif_wake_queue(netdev);
 		}
+		adapter->link_changed = !adapter->has_link_events;
+	}
+}
 
-		netxen_nic_set_link_parameters(adapter);
+static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+	u32 val, port, linkup;
+
+	port = adapter->physical_port;
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		val = NXRD32(adapter, CRB_XG_STATE_P3);
+		val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+		linkup = (val == XG_LINK_UP_P3);
+	} else {
+		val = NXRD32(adapter, CRB_XG_STATE);
+		if (adapter->ahw.port_type == NETXEN_NIC_GBE)
+			linkup = (val >> port) & 1;
+		else {
+			val = (val >> port*8) & 0xff;
+			linkup = (val == XG_LINK_UP);
+		}
 	}
+
+	netxen_advert_link_change(adapter, linkup);
+}
+
+static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	netif_device_detach(netdev);
+	netxen_nic_down(adapter, netdev);
+	netxen_nic_detach(adapter);
 }
 
 static void netxen_watchdog(unsigned long v)
 {
 	struct netxen_adapter *adapter = (struct netxen_adapter *)v;
 
-	SCHEDULE_WORK(&adapter->watchdog_task);
+	if (netxen_nic_check_temp(adapter))
+		goto do_sched;
+
+	if (!adapter->has_link_events) {
+		netxen_nic_handle_phy_intr(adapter);
+
+		if (adapter->link_changed)
+			goto do_sched;
+	}
+
+	if (netif_running(adapter->netdev))
+		mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+
+	return;
+
+do_sched:
+	schedule_work(&adapter->watchdog_task);
 }
 
 void netxen_watchdog_task(struct work_struct *work)
@@ -1566,10 +1672,13 @@
 	struct netxen_adapter *adapter =
 		container_of(work, struct netxen_adapter, watchdog_task);
 
-	if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
+	if (adapter->temp == NX_TEMP_PANIC) {
+		netxen_nic_thermal_shutdown(adapter);
 		return;
+	}
 
-	netxen_nic_handle_phy_intr(adapter);
+	if (adapter->link_changed)
+		netxen_nic_set_link_parameters(adapter);
 
 	if (netif_running(adapter->netdev))
 		mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
@@ -1577,9 +1686,8 @@
 
 static void netxen_tx_timeout(struct net_device *netdev)
 {
-	struct netxen_adapter *adapter = (struct netxen_adapter *)
-						netdev_priv(netdev);
-	SCHEDULE_WORK(&adapter->tx_timeout_task);
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+	schedule_work(&adapter->tx_timeout_task);
 }
 
 static void netxen_tx_timeout_task(struct work_struct *work)
@@ -1587,6 +1695,9 @@
 	struct netxen_adapter *adapter =
 		container_of(work, struct netxen_adapter, tx_timeout_task);
 
+	if (!netif_running(adapter->netdev))
+		return;
+
 	printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
 	       netxen_nic_driver_name, adapter->netdev->name);
 
@@ -1598,10 +1709,6 @@
 	netif_wake_queue(adapter->netdev);
 }
 
-/*
- * netxen_nic_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- */
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -1609,22 +1716,11 @@
 
 	memset(stats, 0, sizeof(*stats));
 
-	/* total packets received   */
 	stats->rx_packets = adapter->stats.no_rcv;
-	/* total packets transmitted    */
-	stats->tx_packets = adapter->stats.xmitedframes +
-		adapter->stats.xmitfinished;
-	/* total bytes received     */
+	stats->tx_packets = adapter->stats.xmitfinished;
 	stats->rx_bytes = adapter->stats.rxbytes;
-	/* total bytes transmitted  */
 	stats->tx_bytes = adapter->stats.txbytes;
-	/* bad packets received     */
-	stats->rx_errors = adapter->stats.rcvdbadskb;
-	/* packet transmit problems */
-	stats->tx_errors = adapter->stats.nocmddescriptor;
-	/* no space in linux buffers    */
 	stats->rx_dropped = adapter->stats.rxdropped;
-	/* no space available in linux  */
 	stats->tx_dropped = adapter->stats.txdropped;
 
 	return stats;
@@ -1651,15 +1747,14 @@
 	} else {
 		unsigned long our_int = 0;
 
-		our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR);
+		our_int = NXRD32(adapter, CRB_INT_VECTOR);
 
 		/* not our interrupt */
 		if (!test_and_clear_bit((7 + adapter->portnum), &our_int))
 			return IRQ_NONE;
 
 		/* claim interrupt */
-		adapter->pci_write_normalize(adapter,
-				CRB_INT_VECTOR, (our_int & 0xffffffff));
+		NXWR32(adapter, CRB_INT_VECTOR, (our_int & 0xffffffff));
 	}
 
 	/* clear interrupt */
@@ -1685,7 +1780,7 @@
 
 	/* clear interrupt */
 	adapter->pci_write_immediate(adapter,
-			msi_tgt_status[adapter->ahw.pci_func], 0xffffffff);
+			adapter->msi_tgt_status, 0xffffffff);
 
 	napi_schedule(&sds_ring->napi);
 	return IRQ_HANDLED;
@@ -1715,7 +1810,8 @@
 
 	if ((work_done < budget) && tx_complete) {
 		napi_complete(&sds_ring->napi);
-		netxen_nic_enable_int(sds_ring);
+		if (netif_running(adapter->netdev))
+			netxen_nic_enable_int(sds_ring);
 	}
 
 	return work_done;
@@ -1736,8 +1832,10 @@
 	.id_table = netxen_pci_tbl,
 	.probe = netxen_nic_probe,
 	.remove = __devexit_p(netxen_nic_remove),
+#ifdef CONFIG_PM
 	.suspend = netxen_nic_suspend,
 	.resume = netxen_nic_resume
+#endif
 };
 
 /* Driver Registration on NetXen card    */
@@ -1746,9 +1844,6 @@
 {
 	printk(KERN_INFO "%s\n", netxen_nic_driver_string);
 
-	if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL)
-		return -ENOMEM;
-
 	return pci_register_driver(&netxen_driver);
 }
 
@@ -1757,7 +1852,6 @@
 static void __exit netxen_exit_module(void)
 {
 	pci_unregister_driver(&netxen_driver);
-	destroy_workqueue(netxen_workq);
 }
 
 module_exit(netxen_exit_module);
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_niu.c linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_niu.c
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_niu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_niu.c	2009-09-09 18:13:59.000000000 -0400
@@ -43,8 +43,7 @@
 	int done = 0, timeout = 0;
 
 	while (!done) {
-		done = netxen_nic_reg_read(adapter,
-				NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
 		if (done == 1)
 			break;
 		if (timeout >= phy_lock_timeout) {
@@ -59,8 +58,7 @@
 		}
 	}
 
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
+	NXWR32(adapter, NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
 	return 0;
 }
 
@@ -105,9 +103,7 @@
 	 * so it cannot be in reset
 	 */
 
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
-				  &mac_cfg0, 4))
-		return -EIO;
+	mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0));
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
 		__u32 temp;
 		temp = 0;
@@ -115,9 +111,7 @@
 		netxen_gb_rx_reset_pb(temp);
 		netxen_gb_tx_reset_mac(temp);
 		netxen_gb_rx_reset_mac(temp);
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &temp, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp))
 			return -EIO;
 		restore = 1;
 	}
@@ -125,43 +119,32 @@
 	address = 0;
 	netxen_gb_mii_mgmt_reg_addr(address, reg);
 	netxen_gb_mii_mgmt_phy_addr(address, phy);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
-				   &address, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address))
 		return -EIO;
 	command = 0;		/* turn off any prior activity */
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
-				   &command, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
 		return -EIO;
 	/* send read command */
 	netxen_gb_mii_mgmt_set_read_cycle(command);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
-				   &command, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
 		return -EIO;
 
 	status = 0;
 	do {
-		if (adapter->hw_read_wx(adapter,
-					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
-					  &status, 4))
-			return -EIO;
+		status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0));
 		timeout++;
 	} while ((netxen_get_gb_mii_mgmt_busy(status)
 		  || netxen_get_gb_mii_mgmt_notvalid(status))
 		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
 
 	if (timeout < NETXEN_NIU_PHY_WAITMAX) {
-		if (adapter->hw_read_wx(adapter,
-					  NETXEN_NIU_GB_MII_MGMT_STATUS(0),
-					  readval, 4))
-			return -EIO;
+		*readval = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(0));
 		result = 0;
 	} else
 		result = -1;
 
 	if (restore)
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &mac_cfg0, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0))
 			return -EIO;
 	phy_unlock(adapter);
 	return result;
@@ -197,9 +180,7 @@
 	 * cannot be in reset
 	 */
 
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
-				  &mac_cfg0, 4))
-		return -EIO;
+	mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0));
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
 		__u32 temp;
 		temp = 0;
@@ -208,35 +189,27 @@
 		netxen_gb_tx_reset_mac(temp);
 		netxen_gb_rx_reset_mac(temp);
 
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &temp, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp))
 			return -EIO;
 		restore = 1;
 	}
 
 	command = 0;		/* turn off any prior activity */
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
-				   &command, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
 		return -EIO;
 
 	address = 0;
 	netxen_gb_mii_mgmt_reg_addr(address, reg);
 	netxen_gb_mii_mgmt_phy_addr(address, phy);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
-				   &address, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address))
 		return -EIO;
 
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
-				   &val, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), val))
 		return -EIO;
 
 	status = 0;
 	do {
-		if (adapter->hw_read_wx(adapter,
-					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
-					  &status, 4))
-			return -EIO;
+		status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0));
 		timeout++;
 	} while ((netxen_get_gb_mii_mgmt_busy(status))
 		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
@@ -248,9 +221,7 @@
 
 	/* restore the state of port 0 MAC in case we tampered with it */
 	if (restore)
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &mac_cfg0, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0))
 			return -EIO;
 
 	return result;
@@ -258,7 +229,7 @@
 
 int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f);
+	NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x3f);
 	return 0;
 }
 
@@ -281,7 +252,7 @@
 
 int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f);
+	NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x7f);
 	return 0;
 }
 
@@ -315,36 +286,27 @@
 static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
 					int port, long enable)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x80000000);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x0000f0025);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
-				    0xf1ff);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
-	netxen_crb_writelit_adapter(adapter,
-				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+	NXWR32(adapter, NETXEN_NIU_MODE, 0x2);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf1ff);
+	NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
+	NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
+	NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+	NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
 
 	if (enable) {
 		/*
 		 * Do NOT enable flow control until a suitable solution for
 		 *  shutting down pause frames is found.
 		 */
-		netxen_crb_writelit_adapter(adapter,
-					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
-					    0x5);
+		NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5);
 	}
 
 	if (netxen_niu_gbe_enable_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+		printk(KERN_ERR "ERROR enabling PHY interrupts\n");
 	if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+		printk(KERN_ERR "ERROR clearing PHY interrupts\n");
 }
 
 /*
@@ -353,36 +315,27 @@
 static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
 					 int port, long enable)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x80000000);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x0000f0025);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
-				    0xf2ff);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
-	netxen_crb_writelit_adapter(adapter,
-				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+	NXWR32(adapter, NETXEN_NIU_MODE, 0x2);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf2ff);
+	NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
+	NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
+	NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+	NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
 
 	if (enable) {
 		/*
 		 * Do NOT enable flow control until a suitable solution for
 		 *  shutting down pause frames is found.
 		 */
-		netxen_crb_writelit_adapter(adapter,
-					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
-					    0x5);
+		NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5);
 	}
 
 	if (netxen_niu_gbe_enable_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+		printk(KERN_ERR "ERROR enabling PHY interrupts\n");
 	if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+		printk(KERN_ERR "ERROR clearing PHY interrupts\n");
 }
 
 int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
@@ -416,25 +369,20 @@
 			 * plugged in.
 			 */
 
-			netxen_crb_writelit_adapter(adapter,
-						    NETXEN_NIU_GB_MAC_CONFIG_0
-						    (port),
+			NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 						    NETXEN_GB_MAC_SOFT_RESET);
-			netxen_crb_writelit_adapter(adapter,
-						    NETXEN_NIU_GB_MAC_CONFIG_0
-						    (port),
-						    NETXEN_GB_MAC_RESET_PROT_BLK
-						    | NETXEN_GB_MAC_ENABLE_TX_RX
-						    |
-						    NETXEN_GB_MAC_PAUSED_FRMS);
+			NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+					    NETXEN_GB_MAC_RESET_PROT_BLK |
+					    NETXEN_GB_MAC_ENABLE_TX_RX |
+					    NETXEN_GB_MAC_PAUSED_FRMS);
 			if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-				printk(KERN_ERR PFX
+				printk(KERN_ERR
 				       "ERROR clearing PHY interrupts\n");
 			if (netxen_niu_gbe_enable_phy_interrupts(adapter))
-				printk(KERN_ERR PFX
+				printk(KERN_ERR
 				       "ERROR enabling PHY interrupts\n");
 			if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-				printk(KERN_ERR PFX
+				printk(KERN_ERR
 				       "ERROR clearing PHY interrupts\n");
 			result = -1;
 		}
@@ -447,88 +395,10 @@
 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
-		netxen_crb_writelit_adapter(adapter,
-			NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
-		netxen_crb_writelit_adapter(adapter,
-			NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
-	}
-
-	return 0;
-}
-
-/*
- * Return the current station MAC address.
- * Note that the passed-in value must already be in network byte order.
- */
-static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
-				  netxen_ethernet_macaddr_t * addr)
-{
-	u32 stationhigh;
-	u32 stationlow;
-	int phy = adapter->physical_port;
-	u8 val[8];
-
-	if (addr == NULL)
-		return -EINVAL;
-	if ((phy < 0) || (phy > 3))
-		return -EINVAL;
-
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
-				  &stationhigh, 4))
-		return -EIO;
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
-				  &stationlow, 4))
-		return -EIO;
-	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
-	((__le32 *)val)[0] = cpu_to_le32(stationlow);
-
-	memcpy(addr, val + 2, 6);
-
-	return 0;
-}
-
-/*
- * Set the station MAC address.
- * Note that the passed-in value must already be in network byte order.
- */
-int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
-			   netxen_ethernet_macaddr_t addr)
-{
-	u8 temp[4];
-	u32 val;
-	int phy = adapter->physical_port;
-	unsigned char mac_addr[6];
-	int i;
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		return 0;
-
-	for (i = 0; i < 10; i++) {
-		temp[0] = temp[1] = 0;
-		memcpy(temp + 2, addr, 2);
-		val = le32_to_cpu(*(__le32 *)temp);
-		if (adapter->hw_write_wx(adapter,
-				NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
-			return -EIO;
-
-		memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
-		val = le32_to_cpu(*(__le32 *)temp);
-		if (adapter->hw_write_wx(adapter,
-				NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
-			return -2;
-
-		netxen_niu_macaddr_get(adapter,
-				       (netxen_ethernet_macaddr_t *) mac_addr);
-		if (memcmp(mac_addr, addr, 6) == 0)
-			break;
+		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
+		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
 	}
 
-	if (i == 10) {
-		printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
-		       netxen_nic_driver_name, adapter->netdev->name);
-		printk(KERN_ERR "MAC address set: %pM.\n", addr);
-		printk(KERN_ERR "MAC address get: %pM.\n", mac_addr);
-	}
 	return 0;
 }
 
@@ -545,8 +415,7 @@
 		return -EINVAL;
 	mac_cfg0 = 0;
 	netxen_gb_soft_reset(mac_cfg0);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				   &mac_cfg0, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0))
 		return -EIO;
 	return 0;
 }
@@ -564,8 +433,8 @@
 		return -EINVAL;
 
 	mac_cfg = 0;
-	if (adapter->hw_write_wx(adapter,
-		NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
+	if (NXWR32(adapter,
+			NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg))
 		return -EIO;
 	return 0;
 }
@@ -581,9 +450,7 @@
 		return -EINVAL;
 
 	/* save previous contents */
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
-				  &reg, 4))
-		return -EIO;
+	reg = NXRD32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR);
 	if (mode == NETXEN_NIU_PROMISC_MODE) {
 		switch (port) {
 		case 0:
@@ -619,64 +486,8 @@
 			return -EIO;
 		}
 	}
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
-				   &reg, 4))
-		return -EIO;
-	return 0;
-}
-
-/*
- * Set the MAC address for an XG port
- * Note that the passed-in value must already be in network byte order.
- */
-int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
-			      netxen_ethernet_macaddr_t addr)
-{
-	int phy = adapter->physical_port;
-	u8 temp[4];
-	u32 val;
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		return 0;
-
-	if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS))
-		return -EIO;
-
-	temp[0] = temp[1] = 0;
-	switch (phy) {
-	case 0:
-	    memcpy(temp + 2, addr, 2);
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
-				&val, 4))
-		return -EIO;
-
-	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
-				&val, 4))
-		return -EIO;
-	    break;
-
-	case 1:
-	    memcpy(temp + 2, addr, 2);
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
-				&val, 4))
-		return -EIO;
-
-	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
-				&val, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg))
 		return -EIO;
-	    break;
-
-	default:
-	    printk(KERN_ERR "Unknown port %d\n", phy);
-	    break;
-	}
-
 	return 0;
 }
 
@@ -689,9 +500,7 @@
 	if (port > NETXEN_NIU_MAX_XG_PORTS)
 		return -EINVAL;
 
-	if (adapter->hw_read_wx(adapter,
-		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
-			return -EIO;
+	reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port));
 	if (mode == NETXEN_NIU_PROMISC_MODE)
 		reg = (reg | 0x2000UL);
 	else
@@ -702,8 +511,40 @@
 	else
 		reg = (reg & ~0x1000UL);
 
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
+	NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
+
+	return 0;
+}
+
+int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+{
+	u32 mac_hi, mac_lo;
+	u32 reg_hi, reg_lo;
+
+	u8 phy = adapter->physical_port;
+	u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ?
+		NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS;
+
+	if (phy >= phy_count)
+		return -EINVAL;
+
+	mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24);
+	mac_hi = addr[2] | ((u32)addr[3] << 8) |
+		((u32)addr[4] << 16) | ((u32)addr[5] << 24);
+
+	if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
+		reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy);
+		reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy);
+	} else {
+		reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy);
+		reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy);
+	}
+
+	/* write twice to flush */
+	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
+		return -EIO;
+	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
+		return -EIO;
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_phan_reg.h linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_phan_reg.h
--- linux-libre-2.6.30-gnu/drivers/net/netxen/netxen_nic_phan_reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netxen/netxen_nic_phan_reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -36,23 +36,25 @@
  */
 #define NIC_CRB_BASE               NETXEN_CAM_RAM(0x200)
 #define NETXEN_NIC_REG(X)             (NIC_CRB_BASE+(X))
+#define NIC_CRB_BASE_2             NETXEN_CAM_RAM(0x700)
+#define NETXEN_NIC_REG_2(X)         (NIC_CRB_BASE_2+(X))
 
 #define CRB_PHAN_CNTRL_LO_OFFSET    NETXEN_NIC_REG(0x00)
 #define CRB_PHAN_CNTRL_HI_OFFSET    NETXEN_NIC_REG(0x04)
 #define CRB_CMD_PRODUCER_OFFSET     NETXEN_NIC_REG(0x08)
 #define CRB_CMD_CONSUMER_OFFSET     NETXEN_NIC_REG(0x0c)
-#define CRB_PAUSE_ADDR_LO           NETXEN_NIC_REG(0x10)	/* C0 EPG BUG  */
+#define CRB_PAUSE_ADDR_LO           NETXEN_NIC_REG(0x10)
 #define CRB_PAUSE_ADDR_HI           NETXEN_NIC_REG(0x14)
 #define NX_CDRP_CRB_OFFSET          NETXEN_NIC_REG(0x18)
 #define NX_ARG1_CRB_OFFSET          NETXEN_NIC_REG(0x1c)
 #define NX_ARG2_CRB_OFFSET          NETXEN_NIC_REG(0x20)
 #define NX_ARG3_CRB_OFFSET          NETXEN_NIC_REG(0x24)
 #define NX_SIGN_CRB_OFFSET          NETXEN_NIC_REG(0x28)
-#define CRB_CMD_INTR_LOOP           NETXEN_NIC_REG(0x20)	/* 4 regs for perf */
+#define CRB_CMD_INTR_LOOP           NETXEN_NIC_REG(0x20)
 #define CRB_CMD_DMA_LOOP            NETXEN_NIC_REG(0x24)
 #define CRB_RCV_INTR_LOOP           NETXEN_NIC_REG(0x28)
 #define CRB_RCV_DMA_LOOP            NETXEN_NIC_REG(0x2c)
-#define CRB_ENABLE_TX_INTR          NETXEN_NIC_REG(0x30)	/* phantom init status */
+#define CRB_ENABLE_TX_INTR          NETXEN_NIC_REG(0x30)
 #define CRB_MMAP_ADDR_3             NETXEN_NIC_REG(0x34)
 #define CRB_CMDPEG_CMDRING          NETXEN_NIC_REG(0x38)
 #define CRB_HOST_DUMMY_BUF_ADDR_HI  NETXEN_NIC_REG(0x3c)
@@ -65,7 +67,7 @@
 #define CRB_MMAP_SIZE_1             NETXEN_NIC_REG(0x58)
 #define CRB_MMAP_SIZE_2             NETXEN_NIC_REG(0x5c)
 #define CRB_MMAP_SIZE_3             NETXEN_NIC_REG(0x60)
-#define CRB_GLOBAL_INT_COAL         NETXEN_NIC_REG(0x64)	/* interrupt coalescing */
+#define CRB_GLOBAL_INT_COAL         NETXEN_NIC_REG(0x64)
 #define CRB_INT_COAL_MODE           NETXEN_NIC_REG(0x68)
 #define CRB_MAX_RCV_BUFS            NETXEN_NIC_REG(0x6c)
 #define CRB_TX_INT_THRESHOLD        NETXEN_NIC_REG(0x70)
@@ -83,13 +85,13 @@
 #define CRB_AGENT_TX_TYPE           NETXEN_NIC_REG(0xa0)
 #define CRB_AGENT_TX_ADDR           NETXEN_NIC_REG(0xa4)
 #define CRB_AGENT_TX_MSS            NETXEN_NIC_REG(0xa8)
-#define CRB_TX_STATE                NETXEN_NIC_REG(0xac)	/* Debug -performance */
+#define CRB_TX_STATE                NETXEN_NIC_REG(0xac)
 #define CRB_TX_COUNT                NETXEN_NIC_REG(0xb0)
 #define CRB_RX_STATE                NETXEN_NIC_REG(0xb4)
 #define CRB_RX_PERF_DEBUG_1         NETXEN_NIC_REG(0xb8)
-#define CRB_RX_LRO_CONTROL          NETXEN_NIC_REG(0xbc)	/* LRO On/OFF */
+#define CRB_RX_LRO_CONTROL          NETXEN_NIC_REG(0xbc)
 #define CRB_RX_LRO_START_NUM        NETXEN_NIC_REG(0xc0)
-#define CRB_MPORT_MODE              NETXEN_NIC_REG(0xc4)	/* Multiport Mode */
+#define CRB_MPORT_MODE              NETXEN_NIC_REG(0xc4)
 #define CRB_CMD_RING_SIZE           NETXEN_NIC_REG(0xc8)
 #define CRB_DMA_SHIFT               NETXEN_NIC_REG(0xcc)
 #define CRB_INT_VECTOR              NETXEN_NIC_REG(0xd4)
@@ -109,8 +111,6 @@
 #define CRB_CMD_CONSUMER_OFFSET_1   NETXEN_NIC_REG(0x1b0)
 #define CRB_CMD_PRODUCER_OFFSET_2   NETXEN_NIC_REG(0x1b8)
 #define CRB_CMD_CONSUMER_OFFSET_2   NETXEN_NIC_REG(0x1bc)
-
-// 1c0 to 1cc used for signature reg
 #define CRB_CMD_PRODUCER_OFFSET_3   NETXEN_NIC_REG(0x1d0)
 #define CRB_CMD_CONSUMER_OFFSET_3   NETXEN_NIC_REG(0x1d4)
 #define CRB_TEMP_STATE              NETXEN_NIC_REG(0x1b4)
@@ -120,13 +120,13 @@
 #define CRB_V2P_2		    NETXEN_NIC_REG(0x298)
 #define CRB_V2P_3		    NETXEN_NIC_REG(0x29c)
 #define CRB_V2P(port)		    (CRB_V2P_0+((port)*4))
-#define CRB_DRIVER_VERSION	    NETXEN_NIC_REG(0x2a0)
-/* sw int status/mask registers */
+#define CRB_DRIVER_VERSION	   NETXEN_NIC_REG(0x2a0)
 #define CRB_SW_INT_MASK_0	   NETXEN_NIC_REG(0x1d8)
 #define CRB_SW_INT_MASK_1	   NETXEN_NIC_REG(0x1e0)
 #define CRB_SW_INT_MASK_2	   NETXEN_NIC_REG(0x1e4)
 #define CRB_SW_INT_MASK_3	   NETXEN_NIC_REG(0x1e8)
 
+#define CRB_FW_CAPABILITIES_1      NETXEN_CAM_RAM(0x128)
 #define CRB_MAC_BLOCK_START        NETXEN_CAM_RAM(0x1c0)
 
 /*
@@ -136,7 +136,7 @@
 #define CRB_NIC_CAPABILITIES_HOST	NETXEN_NIC_REG(0x1a8)
 #define CRB_NIC_CAPABILITIES_FW	  	NETXEN_NIC_REG(0x1dc)
 #define CRB_NIC_MSI_MODE_HOST		NETXEN_NIC_REG(0x270)
-#define CRB_NIC_MSI_MODE_FW	  		NETXEN_NIC_REG(0x274)
+#define CRB_NIC_MSI_MODE_FW	  	NETXEN_NIC_REG(0x274)
 
 #define INTR_SCHEME_PERPORT	      	0x1
 #define MSI_MODE_MULTIFUNC	      	0x1
@@ -162,7 +162,8 @@
 
 struct netxen_recv_crb {
 	u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
-	u32 crb_sts_consumer;
+	u32 crb_sts_consumer[NUM_STS_DESC_RINGS];
+	u32 sw_int_mask[NUM_STS_DESC_RINGS];
 };
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/net/netx-eth.c linux-libre-2.6.31-gnu/drivers/net/netx-eth.c
--- linux-libre-2.6.30-gnu/drivers/net/netx-eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/netx-eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -301,6 +301,17 @@
 	while (readl(NETX_MIIMU) & MIIMU_SNRDY);
 }
 
+static const struct net_device_ops netx_eth_netdev_ops = {
+	.ndo_open		= netx_eth_open,
+	.ndo_stop		= netx_eth_close,
+	.ndo_start_xmit		= netx_eth_hard_start_xmit,
+	.ndo_tx_timeout		= netx_eth_timeout,
+	.ndo_set_multicast_list	= netx_eth_set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
 static int netx_eth_enable(struct net_device *ndev)
 {
 	struct netx_eth_priv *priv = netdev_priv(ndev);
@@ -309,12 +320,8 @@
 
 	ether_setup(ndev);
 
-	ndev->open = netx_eth_open;
-	ndev->stop = netx_eth_close;
-	ndev->hard_start_xmit = netx_eth_hard_start_xmit;
-	ndev->tx_timeout = netx_eth_timeout;
+	ndev->netdev_ops = &netx_eth_netdev_ops;
 	ndev->watchdog_timeo = msecs_to_jiffies(5000);
-	ndev->set_multicast_list = netx_eth_set_multicast_list;
 
 	priv->msg_enable       = NETIF_MSG_LINK;
 	priv->mii.phy_id_mask  = 0x1f;
diff -druN linux-libre-2.6.30-gnu/drivers/net/ni65.c linux-libre-2.6.31-gnu/drivers/net/ni65.c
--- linux-libre-2.6.30-gnu/drivers/net/ni65.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ni65.c	2009-09-09 18:13:59.000000000 -0400
@@ -1165,7 +1165,7 @@
 
 	if (test_and_set_bit(0, (void*)&p->lock)) {
 		printk(KERN_ERR "%s: Queue was locked.\n", dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	{
diff -druN linux-libre-2.6.30-gnu/drivers/net/niu.c linux-libre-2.6.31-gnu/drivers/net/niu.c
--- linux-libre-2.6.30-gnu/drivers/net/niu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/niu.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/log2.h>
 #include <linux/jiffies.h>
 #include <linux/crc32.h>
+#include <linux/list.h>
 
 #include <linux/io.h>
 
@@ -1317,7 +1318,7 @@
 
 	err = mdio_read(np, np->phy_addr,
 			BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
-	if (err < 0)
+	if (err < 0 || err == 0xffff)
 		return err;
 	err |= BMCR_RESET;
 	err = mdio_write(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
@@ -2042,7 +2043,7 @@
 
 	err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
 			BCM8704_PMD_RCV_SIGDET);
-	if (err < 0)
+	if (err < 0 || err == 0xffff)
 		goto out;
 	if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
 		err = 0;
@@ -2083,8 +2084,6 @@
 
 out:
 	*link_up_p = link_up;
-	if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
-		err = 0;
 	return err;
 }
 
@@ -2220,10 +2219,17 @@
 		if (phy_present != phy_present_prev) {
 			/* state change */
 			if (phy_present) {
+				/* A NEM was just plugged in */
 				np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
 				if (np->phy_ops->xcvr_init)
 					err = np->phy_ops->xcvr_init(np);
 				if (err) {
+					err = mdio_read(np, np->phy_addr,
+						BCM8704_PHYXS_DEV_ADDR, MII_BMCR);
+					if (err == 0xffff) {
+						/* No mdio, back-to-back XAUI */
+						goto out;
+					}
 					/* debounce */
 					np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
 				}
@@ -2234,13 +2240,21 @@
 					np->dev->name);
 			}
 		}
-		if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
+out:
+		if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) {
 			err = link_status_10g_bcm8706(np, link_up_p);
+			if (err == 0xffff) {
+				/* No mdio, back-to-back XAUI: it is C10NEM */
+				*link_up_p = 1;
+				np->link_config.active_speed = SPEED_10000;
+				np->link_config.active_duplex = DUPLEX_FULL;
+			}
+		}
 	}
 
 	spin_unlock_irqrestore(&np->lock, flags);
 
-	return err;
+	return 0;
 }
 
 static int niu_link_status(struct niu *np, int *link_up_p)
@@ -2312,6 +2326,12 @@
 	.link_status		= link_status_10g_hotplug,
 };
 
+static const struct niu_phy_ops phy_ops_niu_10g_hotplug = {
+	.serdes_init		= serdes_init_niu_10g_fiber,
+	.xcvr_init		= xcvr_init_10g_bcm8706,
+	.link_status		= link_status_10g_hotplug,
+};
+
 static const struct niu_phy_ops phy_ops_10g_copper = {
 	.serdes_init		= serdes_init_10g,
 	.link_status		= link_status_10g, /* XXX */
@@ -2358,6 +2378,11 @@
 	.phy_addr_base	= 8,
 };
 
+static const struct niu_phy_template phy_template_niu_10g_hotplug = {
+	.ops		= &phy_ops_niu_10g_hotplug,
+	.phy_addr_base	= 8,
+};
+
 static const struct niu_phy_template phy_template_10g_copper = {
 	.ops		= &phy_ops_10g_copper,
 	.phy_addr_base	= 10,
@@ -2542,8 +2567,16 @@
 		case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
 			/* 10G Fiber */
 		default:
-			tp = &phy_template_niu_10g_fiber;
-			phy_addr_off += np->port;
+			if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+				tp = &phy_template_niu_10g_hotplug;
+				if (np->port == 0)
+					phy_addr_off = 8;
+				if (np->port == 1)
+					phy_addr_off = 12;
+			} else {
+				tp = &phy_template_niu_10g_fiber;
+				phy_addr_off += np->port;
+			}
 			break;
 		}
 	} else {
@@ -2630,11 +2663,11 @@
 		msleep(200);
 	}
 	err = niu_serdes_init(np);
-	if (err)
+	if (err && !(np->flags & NIU_FLAGS_HOTPLUG_PHY))
 		return err;
 	msleep(200);
 	err = niu_xcvr_init(np);
-	if (!err)
+	if (!err || (np->flags & NIU_FLAGS_HOTPLUG_PHY))
 		niu_link_status(np, &ignore);
 	return 0;
 }
@@ -6330,6 +6363,7 @@
 	struct niu *np = netdev_priv(dev);
 	int i, alt_cnt, err;
 	struct dev_addr_list *addr;
+	struct netdev_hw_addr *ha;
 	unsigned long flags;
 	u16 hash[16] = { 0, };
 
@@ -6342,7 +6376,7 @@
 	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 0))
 		np->flags |= NIU_FLAGS_MCAST;
 
-	alt_cnt = dev->uc_count;
+	alt_cnt = dev->uc.count;
 	if (alt_cnt > niu_num_alt_addr(np)) {
 		alt_cnt = 0;
 		np->flags |= NIU_FLAGS_PROMISC;
@@ -6351,9 +6385,8 @@
 	if (alt_cnt) {
 		int index = 0;
 
-		for (addr = dev->uc_list; addr; addr = addr->next) {
-			err = niu_set_alt_mac(np, index,
-					      addr->da_addr);
+		list_for_each_entry(ha, &dev->uc.list, list) {
+			err = niu_set_alt_mac(np, index, ha->addr);
 			if (err)
 				printk(KERN_WARNING PFX "%s: Error %d "
 				       "adding alt mac %d\n",
@@ -6745,8 +6778,6 @@
 			netif_tx_wake_queue(txq);
 	}
 
-	dev->trans_start = jiffies;
-
 out:
 	return NETDEV_TX_OK;
 
@@ -9346,6 +9377,11 @@
 	if (model)
 		strcpy(np->vpd.model, model);
 
+	if (of_find_property(dp, "hot-swappable-phy", &prop_len)) {
+		np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
+			NIU_FLAGS_HOTPLUG_PHY);
+	}
+
 	return 0;
 #else
 	return -EINVAL;
diff -druN linux-libre-2.6.30-gnu/drivers/net/niu.h linux-libre-2.6.31-gnu/drivers/net/niu.h
--- linux-libre-2.6.30-gnu/drivers/net/niu.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/niu.h	2009-09-09 18:13:59.000000000 -0400
@@ -3242,8 +3242,8 @@
 	struct niu_parent		*parent;
 
 	u32				flags;
-#define NIU_FLAGS_HOTPLUG_PHY_PRESENT	0x02000000 /* Removebale PHY detected*/
-#define NIU_FLAGS_HOTPLUG_PHY		0x01000000 /* Removebale PHY */
+#define NIU_FLAGS_HOTPLUG_PHY_PRESENT	0x02000000 /* Removeable PHY detected*/
+#define NIU_FLAGS_HOTPLUG_PHY		0x01000000 /* Removeable PHY */
 #define NIU_FLAGS_VPD_VALID		0x00800000 /* VPD has valid version */
 #define NIU_FLAGS_MSIX			0x00400000 /* MSI-X in use */
 #define NIU_FLAGS_MCAST			0x00200000 /* multicast filter enabled */
diff -druN linux-libre-2.6.30-gnu/drivers/net/ns83820.c linux-libre-2.6.31-gnu/drivers/net/ns83820.c
--- linux-libre-2.6.30-gnu/drivers/net/ns83820.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ns83820.c	2009-09-09 18:13:59.000000000 -0400
@@ -1097,7 +1097,7 @@
 	if (unlikely(dev->CFG_cache & CFG_LNKSTS)) {
 		netif_stop_queue(ndev);
 		if (unlikely(dev->CFG_cache & CFG_LNKSTS))
-			return 1;
+			return NETDEV_TX_BUSY;
 		netif_start_queue(ndev);
 	}
 
@@ -1115,7 +1115,7 @@
 			netif_start_queue(ndev);
 			goto again;
 		}
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	if (free_idx == dev->tx_intr_idx) {
@@ -1204,9 +1204,7 @@
 	if (stopped && (dev->tx_done_idx != tx_done_idx) && start_tx_okay(dev))
 		netif_start_queue(ndev);
 
-	/* set the transmit start time to catch transmit timeouts */
-	ndev->trans_start = jiffies;
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 static void ns83820_update_stats(struct ns83820 *dev)
@@ -1626,7 +1624,7 @@
 		);
 #endif
 
-	if (time_after(jiffies, ndev->trans_start + 1*HZ) &&
+	if (time_after(jiffies, dev_trans_start(ndev) + 1*HZ) &&
 	    dev->tx_done_idx != dev->tx_free_idx) {
 		printk(KERN_DEBUG "%s: ns83820_tx_watch: %u %u %d\n",
 			ndev->name,
diff -druN linux-libre-2.6.30-gnu/drivers/net/pasemi_mac.c linux-libre-2.6.31-gnu/drivers/net/pasemi_mac.c
--- linux-libre-2.6.30-gnu/drivers/net/pasemi_mac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pasemi_mac.c	2009-09-09 18:13:59.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/dmaengine.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/of_mdio.h>
 #include <linux/etherdevice.h>
 #include <asm/dma-mapping.h>
 #include <linux/in.h>
@@ -1086,34 +1087,17 @@
 	struct pasemi_mac *mac = netdev_priv(dev);
 	struct device_node *dn, *phy_dn;
 	struct phy_device *phydev;
-	unsigned int phy_id;
-	const phandle *ph;
-	const unsigned int *prop;
-	struct resource r;
-	int ret;
 
 	dn = pci_device_to_OF_node(mac->pdev);
-	ph = of_get_property(dn, "phy-handle", NULL);
-	if (!ph)
-		return -ENODEV;
-	phy_dn = of_find_node_by_phandle(*ph);
-
-	prop = of_get_property(phy_dn, "reg", NULL);
-	ret = of_address_to_resource(phy_dn->parent, 0, &r);
-	if (ret)
-		goto err;
-
-	phy_id = *prop;
-	snprintf(mac->phy_id, sizeof(mac->phy_id), "%x:%02x",
-		 (int)r.start, phy_id);
-
+	phy_dn = of_parse_phandle(dn, "phy-handle", 0);
 	of_node_put(phy_dn);
 
 	mac->link = 0;
 	mac->speed = 0;
 	mac->duplex = -1;
 
-	phydev = phy_connect(dev, mac->phy_id, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII);
+	phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0,
+				PHY_INTERFACE_MODE_SGMII);
 
 	if (IS_ERR(phydev)) {
 		printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
@@ -1123,10 +1107,6 @@
 	mac->phydev = phydev;
 
 	return 0;
-
-err:
-	of_node_put(phy_dn);
-	return -ENODEV;
 }
 
 
@@ -1735,12 +1715,25 @@
 	return ret;
 }
 
+static const struct net_device_ops pasemi_netdev_ops = {
+	.ndo_open		= pasemi_mac_open,
+	.ndo_stop		= pasemi_mac_close,
+	.ndo_start_xmit		= pasemi_mac_start_tx,
+	.ndo_set_multicast_list	= pasemi_mac_set_rx_mode,
+	.ndo_set_mac_address	= pasemi_mac_set_mac_addr,
+	.ndo_change_mtu		= pasemi_mac_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= pasemi_mac_netpoll,
+#endif
+};
+
 static int __devinit
 pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct net_device *dev;
 	struct pasemi_mac *mac;
-	int err;
+	int err, ret;
 
 	err = pci_enable_device(pdev);
 	if (err)
@@ -1798,12 +1791,13 @@
 	}
 	memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr));
 
-	mac->dma_if = mac_to_intf(mac);
-	if (mac->dma_if < 0) {
+	ret = mac_to_intf(mac);
+	if (ret < 0) {
 		dev_err(&mac->pdev->dev, "Can't map DMA interface\n");
 		err = -ENODEV;
 		goto out;
 	}
+	mac->dma_if = ret;
 
 	switch (pdev->device) {
 	case 0xa005:
@@ -1817,19 +1811,11 @@
 		goto out;
 	}
 
-	dev->open = pasemi_mac_open;
-	dev->stop = pasemi_mac_close;
-	dev->hard_start_xmit = pasemi_mac_start_tx;
-	dev->set_multicast_list = pasemi_mac_set_rx_mode;
-	dev->set_mac_address = pasemi_mac_set_mac_addr;
+	dev->netdev_ops = &pasemi_netdev_ops;
 	dev->mtu = PE_DEF_MTU;
 	/* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
 	mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = pasemi_mac_netpoll;
-#endif
 
-	dev->change_mtu = pasemi_mac_change_mtu;
 	dev->ethtool_ops = &pasemi_mac_ethtool_ops;
 
 	if (err)
diff -druN linux-libre-2.6.30-gnu/drivers/net/pasemi_mac.h linux-libre-2.6.31-gnu/drivers/net/pasemi_mac.h
--- linux-libre-2.6.30-gnu/drivers/net/pasemi_mac.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pasemi_mac.h	2009-09-09 18:13:59.000000000 -0400
@@ -100,7 +100,6 @@
 	int	duplex;
 
 	unsigned int	msg_enable;
-	char	phy_id[BUS_ID_SIZE];
 };
 
 /* Software status descriptor (ring_info) */
diff -druN linux-libre-2.6.30-gnu/drivers/net/pci-skeleton.c linux-libre-2.6.31-gnu/drivers/net/pci-skeleton.c
--- linux-libre-2.6.30-gnu/drivers/net/pci-skeleton.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pci-skeleton.c	2009-09-09 18:13:59.000000000 -0400
@@ -105,7 +105,7 @@
 
 static char version[] __devinitdata =
 KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n"
-KERN_INFO "  Support available from http://foo.com/bar/baz.html\n";
+"  Support available from http://foo.com/bar/baz.html\n";
 
 /* define to 1 to enable PIO instead of MMIO */
 #undef USE_IO_OPS
@@ -728,6 +728,17 @@
 	return rc;
 }
 
+static const struct net_device_ops netdrv_netdev_ops = {
+	.ndo_open		= netdrv_open,
+	.ndo_stop		= netdrv_close,
+	.ndo_start_xmit		= netdrv_start_xmit,
+	.ndo_set_multicast_list	= netdrv_set_rx_mode,
+	.ndo_do_ioctl		= netdrv_ioctl,
+	.ndo_tx_timeout		= netdrv_tx_timeout,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
 
 static int __devinit netdrv_init_one (struct pci_dev *pdev,
 				       const struct pci_device_id *ent)
@@ -769,13 +780,7 @@
 		((u16 *) (dev->dev_addr))[i] =
 		    le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
 
-	/* The Rtl8139-specific entries in the device structure. */
-	dev->open = netdrv_open;
-	dev->hard_start_xmit = netdrv_start_xmit;
-	dev->stop = netdrv_close;
-	dev->set_multicast_list = netdrv_set_rx_mode;
-	dev->do_ioctl = netdrv_ioctl;
-	dev->tx_timeout = netdrv_tx_timeout;
+	dev->netdev_ops = &netdrv_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	dev->irq = pdev->irq;
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/3c574_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/3c574_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/3c574_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/3c574_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -1195,7 +1195,7 @@
 
 static struct pcmcia_device_id tc574_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574),
-	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"),
+	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, tc574_ids);
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/3c589_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/3c589_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/3c589_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/3c589_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -156,6 +156,7 @@
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
 static void el3_tx_timeout(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static const struct ethtool_ops netdev_ethtool_ops;
 
@@ -488,8 +489,7 @@
     /* Switch to register set 1 for normal use. */
     EL3WINDOW(1);
 
-    /* Accept b-cast and phys addr only. */
-    outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
+    set_rx_mode(dev);
     outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
     outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
     outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -700,7 +700,7 @@
 		if (fifo_diag & 0x2000) {
 		    /* Rx underrun */
 		    tc589_wait_for_completion(dev, RxReset);
-		    set_multicast_list(dev);
+		    set_rx_mode(dev);
 		    outw(RxEnable, ioaddr + EL3_CMD);
 		}
 		outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
@@ -905,14 +905,11 @@
     return 0;
 }
 
-static void set_multicast_list(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
-    struct el3_private *lp = netdev_priv(dev);
-    struct pcmcia_device *link = lp->p_dev;
     unsigned int ioaddr = dev->base_addr;
     u16 opts = SetRxFilter | RxStation | RxBroadcast;
 
-    if (!pcmcia_dev_present(link)) return;
     if (dev->flags & IFF_PROMISC)
 	opts |= RxMulticast | RxProm;
     else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
@@ -920,6 +917,16 @@
     outw(opts, ioaddr + EL3_CMD);
 }
 
+static void set_multicast_list(struct net_device *dev)
+{
+	struct el3_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	set_rx_mode(dev);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
 static int el3_close(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
@@ -967,8 +974,8 @@
 	PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77),
 	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589),
 	PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202),
-	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"),
-	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"),
+	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "cis/3CXEM556.cis"),
+	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "cis/3CXEM556.cis"),
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, tc589_ids);
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/axnet_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/axnet_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/axnet_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/axnet_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -1130,7 +1130,7 @@
 		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 		spin_unlock_irqrestore(&ei_local->page_lock, flags);
 		dev->stats.tx_errors++;
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	/*
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/fmvj18x_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/fmvj18x_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/fmvj18x_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -877,7 +877,7 @@
 	if (length > ETH_FRAME_LEN) {
 	    printk(KERN_NOTICE "%s: Attempting to send a large packet"
 		   " (%d bytes).\n", dev->name, length);
-	    return 1;
+	    return NETDEV_TX_BUSY;
 	}
 
 	DEBUG(4, "%s: Transmitting a packet of length %lu.\n",
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/ibmtr_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/ibmtr_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/ibmtr_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/ibmtr_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -298,14 +298,11 @@
 
     strcpy(info->node.dev_name, dev->name);
 
-    printk(KERN_INFO "%s: port %#3lx, irq %d,",
-           dev->name, dev->base_addr, dev->irq);
-    printk (" mmio %#5lx,", (u_long)ti->mmio);
-    printk (" sram %#5lx,", (u_long)ti->sram_base << 12);
-    printk ("\n" KERN_INFO "  hwaddr=");
-    for (i = 0; i < TR_ALEN; i++)
-        printk("%02X", dev->dev_addr[i]);
-    printk("\n");
+    printk(KERN_INFO
+	   "%s: port %#3lx, irq %d,  mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
+           dev->name, dev->base_addr, dev->irq,
+	   (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
+	   dev->dev_addr);
     return 0;
 
 cs_failed:
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/nmclan_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/nmclan_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/nmclan_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/nmclan_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -1425,15 +1425,12 @@
   ladrf[byte] |= (1 << (hashcode & 7));
 
 #ifdef PCMCIA_DEBUG
-  if (pc_debug > 2) {
-    printk(KERN_DEBUG "    adr =");
-    for (i = 0; i < 6; i++)
-      printk(" %02X", adr[i]);
-    printk("\n" KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63]"
-	   " =", hashcode);
-    for (i = 0; i < 8; i++)
-      printk(" %02X", ladrf[i]);
-    printk("\n");
+  if (pc_debug > 2)
+    printk(KERN_DEBUG "    adr =%pM\n", adr);
+  printk(KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63] =", hashcode);
+  for (i = 0; i < 8; i++)
+    printk(KERN_CONT " %02X", ladrf[i]);
+  printk(KERN_CONT "\n");
   }
 #endif
 } /* BuildLAF */
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/pcnet_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/pcnet_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/pcnet_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/pcnet_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -1727,6 +1727,7 @@
 	PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
 	PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
 	PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
 	PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
 	PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
 	PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/smc91c92_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/smc91c92_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/smc91c92_cs.c	2012-03-22 19:15:58.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/smc91c92_cs.c	2012-03-22 20:11:52.000000000 -0400
@@ -1388,7 +1388,7 @@
 	dev->stats.tx_aborted_errors++;
 	printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n",
 	       dev->name);
-	return 1;
+	return NETDEV_TX_BUSY;
     }
     smc->saved_skb = skb;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcmcia/xirc2ps_cs.c linux-libre-2.6.31-gnu/drivers/net/pcmcia/xirc2ps_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/pcmcia/xirc2ps_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcmcia/xirc2ps_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -1399,7 +1399,7 @@
     DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n",
 	  dev->name, freespace, okay ? " (okay)":" (not enough)");
     if (!okay) { /* not enough space */
-	return 1;  /* upper layer may decide to requeue this packet */
+	return NETDEV_TX_BUSY;  /* upper layer may decide to requeue this packet */
     }
     /* send the packet */
     PutWord(XIRCREG_EDP, (u_short)pktlen);
diff -druN linux-libre-2.6.30-gnu/drivers/net/pcnet32.c linux-libre-2.6.31-gnu/drivers/net/pcnet32.c
--- linux-libre-2.6.30-gnu/drivers/net/pcnet32.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pcnet32.c	2009-09-09 18:13:59.000000000 -0400
@@ -485,7 +485,7 @@
 					   &new_ring_dma_addr);
 	if (new_tx_ring == NULL) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR
+			printk(KERN_ERR
 			       "%s: Consistent memory allocation failed.\n",
 			       dev->name);
 		return;
@@ -496,7 +496,7 @@
 				GFP_ATOMIC);
 	if (!new_dma_addr_list) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR
+			printk(KERN_ERR
 			       "%s: Memory allocation failed.\n", dev->name);
 		goto free_new_tx_ring;
 	}
@@ -505,7 +505,7 @@
 				GFP_ATOMIC);
 	if (!new_skb_list) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR
+			printk(KERN_ERR
 			       "%s: Memory allocation failed.\n", dev->name);
 		goto free_new_lists;
 	}
@@ -563,7 +563,7 @@
 					   &new_ring_dma_addr);
 	if (new_rx_ring == NULL) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR
+			printk(KERN_ERR
 			       "%s: Consistent memory allocation failed.\n",
 			       dev->name);
 		return;
@@ -574,7 +574,7 @@
 				GFP_ATOMIC);
 	if (!new_dma_addr_list) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR
+			printk(KERN_ERR
 			       "%s: Memory allocation failed.\n", dev->name);
 		goto free_new_rx_ring;
 	}
@@ -583,7 +583,7 @@
 				GFP_ATOMIC);
 	if (!new_skb_list) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR
+			printk(KERN_ERR
 			       "%s: Memory allocation failed.\n", dev->name);
 		goto free_new_lists;
 	}
@@ -1227,7 +1227,6 @@
 		dev->stats.rx_dropped++;
 		return;
 	}
-	skb->dev = dev;
 	if (!rx_in_place) {
 		skb_reserve(skb, NET_IP_ALIGN);
 		skb_put(skb, pkt_len);	/* Make room */
@@ -1406,7 +1405,7 @@
 
 		/* Set interrupt enable. */
 		lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN);
-		mmiowb();
+
 		spin_unlock_irqrestore(&lp->lock, flags);
 	}
 	return work_done;
@@ -1612,8 +1611,11 @@
 		if (pcnet32_dwio_read_csr(ioaddr, 0) == 4
 		    && pcnet32_dwio_check(ioaddr)) {
 			a = &pcnet32_dwio;
-		} else
+		} else {
+			if (pcnet32_debug & NETIF_MSG_PROBE)
+				printk(KERN_ERR PFX "No access methods\n");
 			goto err_release_region;
+		}
 	}
 
 	chip_version =
@@ -1720,7 +1722,9 @@
 		ret = -ENOMEM;
 		goto err_release_region;
 	}
-	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	if (pdev)
+		SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pcnet32_debug & NETIF_MSG_PROBE)
 		printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
@@ -1767,38 +1771,38 @@
 		/* Version 0x2623 and 0x2624 */
 		if (((chip_version + 1) & 0xfffe) == 0x2624) {
 			i = a->read_csr(ioaddr, 80) & 0x0C00;	/* Check tx_start_pt */
-			printk("\n" KERN_INFO "    tx_start_pt(0x%04x):", i);
+			printk(KERN_INFO "    tx_start_pt(0x%04x):", i);
 			switch (i >> 10) {
 			case 0:
-				printk("  20 bytes,");
+				printk(KERN_CONT "  20 bytes,");
 				break;
 			case 1:
-				printk("  64 bytes,");
+				printk(KERN_CONT "  64 bytes,");
 				break;
 			case 2:
-				printk(" 128 bytes,");
+				printk(KERN_CONT " 128 bytes,");
 				break;
 			case 3:
-				printk("~220 bytes,");
+				printk(KERN_CONT "~220 bytes,");
 				break;
 			}
 			i = a->read_bcr(ioaddr, 18);	/* Check Burst/Bus control */
-			printk(" BCR18(%x):", i & 0xffff);
+			printk(KERN_CONT " BCR18(%x):", i & 0xffff);
 			if (i & (1 << 5))
-				printk("BurstWrEn ");
+				printk(KERN_CONT "BurstWrEn ");
 			if (i & (1 << 6))
-				printk("BurstRdEn ");
+				printk(KERN_CONT "BurstRdEn ");
 			if (i & (1 << 7))
-				printk("DWordIO ");
+				printk(KERN_CONT "DWordIO ");
 			if (i & (1 << 11))
-				printk("NoUFlow ");
+				printk(KERN_CONT "NoUFlow ");
 			i = a->read_bcr(ioaddr, 25);
-			printk("\n" KERN_INFO "    SRAMSIZE=0x%04x,", i << 8);
+			printk(KERN_INFO "    SRAMSIZE=0x%04x,", i << 8);
 			i = a->read_bcr(ioaddr, 26);
-			printk(" SRAM_BND=0x%04x,", i << 8);
+			printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8);
 			i = a->read_bcr(ioaddr, 27);
 			if (i & (1 << 14))
-				printk("LowLatRx");
+				printk(KERN_CONT "LowLatRx");
 		}
 	}
 
@@ -1819,7 +1823,6 @@
 
 	spin_lock_init(&lp->lock);
 
-	SET_NETDEV_DEV(dev, &pdev->dev);
 	lp->name = chipname;
 	lp->shared_irq = shared;
 	lp->tx_ring_size = TX_RING_SIZE;	/* default tx ring size */
@@ -1836,7 +1839,7 @@
 	lp->chip_version = chip_version;
 	lp->msg_enable = pcnet32_debug;
 	if ((cards_found >= MAX_UNITS)
-	    || (options[cards_found] > sizeof(options_mapping)))
+	    || (options[cards_found] >= sizeof(options_mapping)))
 		lp->options = PCNET32_PORT_ASEL;
 	else
 		lp->options = options_mapping[options[cards_found]];
@@ -1853,12 +1856,6 @@
 	    ((cards_found >= MAX_UNITS) || full_duplex[cards_found]))
 		lp->options |= PCNET32_PORT_FD;
 
-	if (!a) {
-		if (pcnet32_debug & NETIF_MSG_PROBE)
-			printk(KERN_ERR PFX "No access methods\n");
-		ret = -ENODEV;
-		goto err_free_consistent;
-	}
 	lp->a = *a;
 
 	/* prior to register_netdev, dev->name is not yet correct */
@@ -1974,14 +1971,13 @@
 
 	return 0;
 
-      err_free_ring:
+err_free_ring:
 	pcnet32_free_ring(dev);
-      err_free_consistent:
 	pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
 			    lp->init_block, lp->init_dma_addr);
-      err_free_netdev:
+err_free_netdev:
 	free_netdev(dev);
-      err_release_region:
+err_release_region:
 	release_region(ioaddr, PCNET32_TOTAL_SIZE);
 	return ret;
 }
@@ -1997,7 +1993,7 @@
 					   &lp->tx_ring_dma_addr);
 	if (lp->tx_ring == NULL) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR PFX
+			printk(KERN_ERR PFX
 			       "%s: Consistent memory allocation failed.\n",
 			       name);
 		return -ENOMEM;
@@ -2009,7 +2005,7 @@
 					   &lp->rx_ring_dma_addr);
 	if (lp->rx_ring == NULL) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR PFX
+			printk(KERN_ERR PFX
 			       "%s: Consistent memory allocation failed.\n",
 			       name);
 		return -ENOMEM;
@@ -2019,7 +2015,7 @@
 				  GFP_ATOMIC);
 	if (!lp->tx_dma_addr) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR PFX
+			printk(KERN_ERR PFX
 			       "%s: Memory allocation failed.\n", name);
 		return -ENOMEM;
 	}
@@ -2028,7 +2024,7 @@
 				  GFP_ATOMIC);
 	if (!lp->rx_dma_addr) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR PFX
+			printk(KERN_ERR PFX
 			       "%s: Memory allocation failed.\n", name);
 		return -ENOMEM;
 	}
@@ -2037,7 +2033,7 @@
 				GFP_ATOMIC);
 	if (!lp->tx_skbuff) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR PFX
+			printk(KERN_ERR PFX
 			       "%s: Memory allocation failed.\n", name);
 		return -ENOMEM;
 	}
@@ -2046,7 +2042,7 @@
 				GFP_ATOMIC);
 	if (!lp->rx_skbuff) {
 		if (netif_msg_drv(lp))
-			printk("\n" KERN_ERR PFX
+			printk(KERN_ERR PFX
 			       "%s: Memory allocation failed.\n", name);
 		return -ENOMEM;
 	}
@@ -2090,6 +2086,7 @@
 static int pcnet32_open(struct net_device *dev)
 {
 	struct pcnet32_private *lp = netdev_priv(dev);
+	struct pci_dev *pdev = lp->pci_dev;
 	unsigned long ioaddr = dev->base_addr;
 	u16 val;
 	int i;
@@ -2150,9 +2147,9 @@
 	lp->a.write_csr(ioaddr, 124, val);
 
 	/* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */
-	if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT &&
-	    (lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
-	     lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
+	if (pdev && pdev->subsystem_vendor == PCI_VENDOR_ID_AT &&
+	    (pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
+	     pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
 		if (lp->options & PCNET32_PORT_ASEL) {
 			lp->options = PCNET32_PORT_FD | PCNET32_PORT_100;
 			if (netif_msg_link(lp))
@@ -2598,7 +2595,7 @@
 			val = lp->a.read_csr(ioaddr, CSR3);
 			val |= 0x5f00;
 			lp->a.write_csr(ioaddr, CSR3, val);
-			mmiowb();
+
 			__napi_schedule(&lp->napi);
 			break;
 		}
diff -druN linux-libre-2.6.30-gnu/drivers/net/phy/marvell.c linux-libre-2.6.31-gnu/drivers/net/phy/marvell.c
--- linux-libre-2.6.30-gnu/drivers/net/phy/marvell.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/phy/marvell.c	2009-09-09 18:13:59.000000000 -0400
@@ -243,6 +243,7 @@
 
 		temp &= ~(MII_M1111_HWCFG_MODE_MASK);
 		temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
+		temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
 
 		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
 		if (err < 0)
diff -druN linux-libre-2.6.30-gnu/drivers/net/phy/mdio_bus.c linux-libre-2.6.31-gnu/drivers/net/phy/mdio_bus.c
--- linux-libre-2.6.30-gnu/drivers/net/phy/mdio_bus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/phy/mdio_bus.c	2009-09-09 18:13:59.000000000 -0400
@@ -113,7 +113,6 @@
 		bus->reset(bus);
 
 	for (i = 0; i < PHY_MAX_ADDR; i++) {
-		bus->phy_map[i] = NULL;
 		if ((bus->phy_mask & (1 << i)) == 0) {
 			struct phy_device *phydev;
 
@@ -150,6 +149,7 @@
 	for (i = 0; i < PHY_MAX_ADDR; i++) {
 		if (bus->phy_map[i])
 			device_unregister(&bus->phy_map[i]->dev);
+		bus->phy_map[i] = NULL;
 	}
 }
 EXPORT_SYMBOL(mdiobus_unregister);
@@ -188,35 +188,12 @@
 	if (IS_ERR(phydev) || phydev == NULL)
 		return phydev;
 
-	/* There's a PHY at this address
-	 * We need to set:
-	 * 1) IRQ
-	 * 2) bus_id
-	 * 3) parent
-	 * 4) bus
-	 * 5) mii_bus
-	 * And, we need to register it */
-
-	phydev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
-
-	phydev->dev.parent = bus->parent;
-	phydev->dev.bus = &mdio_bus_type;
-	dev_set_name(&phydev->dev, PHY_ID_FMT, bus->id, addr);
-
-	phydev->bus = bus;
-
-	/* Run all of the fixups for this PHY */
-	phy_scan_fixups(phydev);
-
-	err = device_register(&phydev->dev);
+	err = phy_device_register(phydev);
 	if (err) {
-		printk(KERN_ERR "phy %d failed to register\n", addr);
 		phy_device_free(phydev);
-		phydev = NULL;
+		return NULL;
 	}
 
-	bus->phy_map[addr] = phydev;
-
 	return phydev;
 }
 EXPORT_SYMBOL(mdiobus_scan);
diff -druN linux-libre-2.6.30-gnu/drivers/net/phy/mdio-gpio.c linux-libre-2.6.31-gnu/drivers/net/phy/mdio-gpio.c
--- linux-libre-2.6.30-gnu/drivers/net/phy/mdio-gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/phy/mdio-gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -30,6 +30,7 @@
 
 #ifdef CONFIG_OF_GPIO
 #include <linux/of_gpio.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #endif
 
@@ -81,13 +82,12 @@
 	.get_mdio_data = mdio_get,
 };
 
-static int __devinit mdio_gpio_bus_init(struct device *dev,
+static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
 					struct mdio_gpio_platform_data *pdata,
 					int bus_id)
 {
 	struct mii_bus *new_bus;
 	struct mdio_gpio_info *bitbang;
-	int ret = -ENOMEM;
 	int i;
 
 	bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
@@ -104,8 +104,6 @@
 
 	new_bus->name = "GPIO Bitbanged MDIO",
 
-	ret = -ENODEV;
-
 	new_bus->phy_mask = pdata->phy_mask;
 	new_bus->irq = pdata->irqs;
 	new_bus->parent = dev;
@@ -129,15 +127,8 @@
 
 	dev_set_drvdata(dev, new_bus);
 
-	ret = mdiobus_register(new_bus);
-	if (ret)
-		goto out_free_all;
-
-	return 0;
+	return new_bus;
 
-out_free_all:
-	dev_set_drvdata(dev, NULL);
-	gpio_free(bitbang->mdio);
 out_free_mdc:
 	gpio_free(bitbang->mdc);
 out_free_bus:
@@ -145,30 +136,47 @@
 out_free_bitbang:
 	kfree(bitbang);
 out:
-	return ret;
+	return NULL;
 }
 
-static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+static void __devinit mdio_gpio_bus_deinit(struct device *dev)
 {
 	struct mii_bus *bus = dev_get_drvdata(dev);
 	struct mdio_gpio_info *bitbang = bus->priv;
 
-	mdiobus_unregister(bus);
-	free_mdio_bitbang(bus);
 	dev_set_drvdata(dev, NULL);
-	gpio_free(bitbang->mdc);
 	gpio_free(bitbang->mdio);
+	gpio_free(bitbang->mdc);
+	free_mdio_bitbang(bus);
 	kfree(bitbang);
 }
 
+static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+{
+	struct mii_bus *bus = dev_get_drvdata(dev);
+
+	mdiobus_unregister(bus);
+	mdio_gpio_bus_deinit(dev);
+}
+
 static int __devinit mdio_gpio_probe(struct platform_device *pdev)
 {
 	struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data;
+	struct mii_bus *new_bus;
+	int ret;
 
 	if (!pdata)
 		return -ENODEV;
 
-	return mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+	new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+	if (!new_bus)
+		return -ENODEV;
+
+	ret = mdiobus_register(new_bus);
+	if (ret)
+		mdio_gpio_bus_deinit(&pdev->dev);
+
+	return ret;
 }
 
 static int __devexit mdio_gpio_remove(struct platform_device *pdev)
@@ -179,29 +187,12 @@
 }
 
 #ifdef CONFIG_OF_GPIO
-static void __devinit add_phy(struct mdio_gpio_platform_data *pdata,
-			      struct device_node *np)
-{
-	const u32 *data;
-	int len, id, irq;
-
-	data = of_get_property(np, "reg", &len);
-	if (!data || len != 4)
-		return;
-
-	id = *data;
-	pdata->phy_mask &= ~(1 << id);
-
-	irq = of_irq_to_resource(np, 0, NULL);
-	if (irq)
-		pdata->irqs[id] = irq;
-}
 
 static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
                                         const struct of_device_id *match)
 {
-	struct device_node *np = NULL;
 	struct mdio_gpio_platform_data *pdata;
+	struct mii_bus *new_bus;
 	int ret;
 
 	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
@@ -215,14 +206,18 @@
 
 	ret = of_get_gpio(ofdev->node, 1);
 	if (ret < 0)
-                goto out_free;
+		goto out_free;
 	pdata->mdio = ret;
 
-	while ((np = of_get_next_child(ofdev->node, np)))
-		if (!strcmp(np->type, "ethernet-phy"))
-			add_phy(pdata, np);
+	new_bus = mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
+	if (!new_bus)
+		return -ENODEV;
 
-	return mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
+	ret = of_mdiobus_register(new_bus, ofdev->node);
+	if (ret)
+		mdio_gpio_bus_deinit(&ofdev->dev);
+
+	return ret;
 
 out_free:
 	kfree(pdata);
diff -druN linux-libre-2.6.30-gnu/drivers/net/phy/phy.c linux-libre-2.6.31-gnu/drivers/net/phy/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/phy/phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/phy/phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -928,13 +928,32 @@
 				 * Otherwise, it's 0, and we're
 				 * still waiting for AN */
 				if (err > 0) {
-					phydev->state = PHY_RUNNING;
+					err = phy_read_status(phydev);
+					if (err)
+						break;
+
+					if (phydev->link) {
+						phydev->state = PHY_RUNNING;
+						netif_carrier_on(phydev->attached_dev);
+					} else
+						phydev->state = PHY_NOLINK;
+					phydev->adjust_link(phydev->attached_dev);
 				} else {
 					phydev->state = PHY_AN;
 					phydev->link_timeout = PHY_AN_TIMEOUT;
 				}
-			} else
-				phydev->state = PHY_RUNNING;
+			} else {
+				err = phy_read_status(phydev);
+				if (err)
+					break;
+
+				if (phydev->link) {
+					phydev->state = PHY_RUNNING;
+					netif_carrier_on(phydev->attached_dev);
+				} else
+					phydev->state = PHY_NOLINK;
+				phydev->adjust_link(phydev->attached_dev);
+			}
 			break;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/phy/phy_device.c linux-libre-2.6.31-gnu/drivers/net/phy/phy_device.c
--- linux-libre-2.6.30-gnu/drivers/net/phy/phy_device.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/phy/phy_device.c	2009-09-09 18:13:59.000000000 -0400
@@ -39,20 +39,21 @@
 MODULE_AUTHOR("Andy Fleming");
 MODULE_LICENSE("GPL");
 
-static struct phy_driver genphy_driver;
-extern int mdio_bus_init(void);
-extern void mdio_bus_exit(void);
-
 void phy_device_free(struct phy_device *phydev)
 {
 	kfree(phydev);
 }
+EXPORT_SYMBOL(phy_device_free);
 
 static void phy_device_release(struct device *dev)
 {
 	phy_device_free(to_phy_device(dev));
 }
 
+static struct phy_driver genphy_driver;
+extern int mdio_bus_init(void);
+extern void mdio_bus_exit(void);
+
 static LIST_HEAD(phy_fixup_list);
 static DEFINE_MUTEX(phy_fixup_lock);
 
@@ -133,8 +134,10 @@
 
 			err = fixup->run(phydev);
 
-			if (err < 0)
+			if (err < 0) {
+				mutex_unlock(&phy_fixup_lock);
 				return err;
+			}
 		}
 	}
 	mutex_unlock(&phy_fixup_lock);
@@ -166,6 +169,10 @@
 	dev->addr = addr;
 	dev->phy_id = phy_id;
 	dev->bus = bus;
+	dev->dev.parent = bus->parent;
+	dev->dev.bus = &mdio_bus_type;
+	dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
+	dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
 
 	dev->state = PHY_DOWN;
 
@@ -235,6 +242,38 @@
 
 	return dev;
 }
+EXPORT_SYMBOL(get_phy_device);
+
+/**
+ * phy_device_register - Register the phy device on the MDIO bus
+ * @phydev: phy_device structure to be added to the MDIO bus
+ */
+int phy_device_register(struct phy_device *phydev)
+{
+	int err;
+
+	/* Don't register a phy if one is already registered at this
+	 * address */
+	if (phydev->bus->phy_map[phydev->addr])
+		return -EINVAL;
+	phydev->bus->phy_map[phydev->addr] = phydev;
+
+	/* Run all of the fixups for this PHY */
+	phy_scan_fixups(phydev);
+
+	err = device_register(&phydev->dev);
+	if (err) {
+		pr_err("phy %d failed to register\n", phydev->addr);
+		goto out;
+	}
+
+	return 0;
+
+ out:
+	phydev->bus->phy_map[phydev->addr] = NULL;
+	return err;
+}
+EXPORT_SYMBOL(phy_device_register);
 
 /**
  * phy_prepare_link - prepares the PHY layer to monitor link status
@@ -255,6 +294,33 @@
 }
 
 /**
+ * phy_connect_direct - connect an ethernet device to a specific phy_device
+ * @dev: the network device to connect
+ * @phydev: the pointer to the phy device
+ * @handler: callback function for state change notifications
+ * @flags: PHY device's dev_flags
+ * @interface: PHY device's interface
+ */
+int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
+		       void (*handler)(struct net_device *), u32 flags,
+		       phy_interface_t interface)
+{
+	int rc;
+
+	rc = phy_attach_direct(dev, phydev, flags, interface);
+	if (rc)
+		return rc;
+
+	phy_prepare_link(phydev, handler);
+	phy_start_machine(phydev, NULL);
+	if (phydev->irq > 0)
+		phy_start_interrupts(phydev);
+
+	return 0;
+}
+EXPORT_SYMBOL(phy_connect_direct);
+
+/**
  * phy_connect - connect an ethernet device to a PHY device
  * @dev: the network device to connect
  * @bus_id: the id string of the PHY device to connect
@@ -275,18 +341,21 @@
 		phy_interface_t interface)
 {
 	struct phy_device *phydev;
+	struct device *d;
+	int rc;
 
-	phydev = phy_attach(dev, bus_id, flags, interface);
-
-	if (IS_ERR(phydev))
-		return phydev;
-
-	phy_prepare_link(phydev, handler);
-
-	phy_start_machine(phydev, NULL);
+	/* Search the list of PHY devices on the mdio bus for the
+	 * PHY with the requested name */
+	d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id);
+	if (!d) {
+		pr_err("PHY %s not found\n", bus_id);
+		return ERR_PTR(-ENODEV);
+	}
+	phydev = to_phy_device(d);
 
-	if (phydev->irq > 0)
-		phy_start_interrupts(phydev);
+	rc = phy_connect_direct(dev, phydev, handler, flags, interface);
+	if (rc)
+		return ERR_PTR(rc);
 
 	return phydev;
 }
@@ -310,9 +379,9 @@
 EXPORT_SYMBOL(phy_disconnect);
 
 /**
- * phy_attach - attach a network device to a particular PHY device
+ * phy_attach_direct - attach a network device to a given PHY device pointer
  * @dev: network device to attach
- * @bus_id: PHY device to attach
+ * @phydev: Pointer to phy_device to attach
  * @flags: PHY device's dev_flags
  * @interface: PHY device's interface
  *
@@ -323,22 +392,10 @@
  *     the attaching device, and given a callback for link status
  *     change.  The phy_device is returned to the attaching driver.
  */
-struct phy_device *phy_attach(struct net_device *dev,
-		const char *bus_id, u32 flags, phy_interface_t interface)
+int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
+		      u32 flags, phy_interface_t interface)
 {
-	struct bus_type *bus = &mdio_bus_type;
-	struct phy_device *phydev;
-	struct device *d;
-
-	/* Search the list of PHY devices on the mdio bus for the
-	 * PHY with the requested name */
-	d = bus_find_device_by_name(bus, NULL, bus_id);
-	if (d) {
-		phydev = to_phy_device(d);
-	} else {
-		printk(KERN_ERR "%s not found\n", bus_id);
-		return ERR_PTR(-ENODEV);
-	}
+	struct device *d = &phydev->dev;
 
 	/* Assume that if there is no driver, that it doesn't
 	 * exist, and we should use the genphy driver. */
@@ -351,13 +408,12 @@
 			err = device_bind_driver(d);
 
 		if (err)
-			return ERR_PTR(err);
+			return err;
 	}
 
 	if (phydev->attached_dev) {
-		printk(KERN_ERR "%s: %s already attached\n",
-				dev->name, bus_id);
-		return ERR_PTR(-EBUSY);
+		dev_err(&dev->dev, "PHY already attached\n");
+		return -EBUSY;
 	}
 
 	phydev->attached_dev = dev;
@@ -375,14 +431,49 @@
 		err = phy_scan_fixups(phydev);
 
 		if (err < 0)
-			return ERR_PTR(err);
+			return err;
 
 		err = phydev->drv->config_init(phydev);
 
 		if (err < 0)
-			return ERR_PTR(err);
+			return err;
 	}
 
+	return 0;
+}
+EXPORT_SYMBOL(phy_attach_direct);
+
+/**
+ * phy_attach - attach a network device to a particular PHY device
+ * @dev: network device to attach
+ * @bus_id: Bus ID of PHY device to attach
+ * @flags: PHY device's dev_flags
+ * @interface: PHY device's interface
+ *
+ * Description: Same as phy_attach_direct() except that a PHY bus_id
+ *     string is passed instead of a pointer to a struct phy_device.
+ */
+struct phy_device *phy_attach(struct net_device *dev,
+		const char *bus_id, u32 flags, phy_interface_t interface)
+{
+	struct bus_type *bus = &mdio_bus_type;
+	struct phy_device *phydev;
+	struct device *d;
+	int rc;
+
+	/* Search the list of PHY devices on the mdio bus for the
+	 * PHY with the requested name */
+	d = bus_find_device_by_name(bus, NULL, bus_id);
+	if (!d) {
+		pr_err("PHY %s not found\n", bus_id);
+		return ERR_PTR(-ENODEV);
+	}
+	phydev = to_phy_device(d);
+
+	rc = phy_attach_direct(dev, phydev, flags, interface);
+	if (rc)
+		return ERR_PTR(rc);
+
 	return phydev;
 }
 EXPORT_SYMBOL(phy_attach);
diff -druN linux-libre-2.6.30-gnu/drivers/net/plip.c linux-libre-2.6.31-gnu/drivers/net/plip.c
--- linux-libre-2.6.30-gnu/drivers/net/plip.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/plip.c	2009-09-09 18:13:59.000000000 -0400
@@ -270,6 +270,9 @@
 	.ndo_stop		 = plip_close,
 	.ndo_start_xmit		 = plip_tx_packet,
 	.ndo_do_ioctl		 = plip_ioctl,
+	.ndo_change_mtu		 = eth_change_mtu,
+	.ndo_set_mac_address	 = eth_mac_addr,
+	.ndo_validate_addr	 = eth_validate_addr,
 };
 
 /* Entry point of PLIP driver.
@@ -955,12 +958,12 @@
 	struct plip_local *snd = &nl->snd_data;
 
 	if (netif_queue_stopped(dev))
-		return 1;
+		return NETDEV_TX_BUSY;
 
 	/* We may need to grab the bus */
 	if (!nl->port_owner) {
 		if (parport_claim(nl->pardev))
-			return 1;
+			return NETDEV_TX_BUSY;
 		nl->port_owner = 1;
 	}
 
@@ -969,7 +972,7 @@
 	if (skb->len > dev->mtu + dev->hard_header_len) {
 		printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len);
 		netif_start_queue (dev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	if (net_debug > 2)
diff -druN linux-libre-2.6.30-gnu/drivers/net/ppp_generic.c linux-libre-2.6.31-gnu/drivers/net/ppp_generic.c
--- linux-libre-2.6.30-gnu/drivers/net/ppp_generic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ppp_generic.c	2009-09-09 18:13:59.000000000 -0400
@@ -1054,6 +1054,7 @@
 	dev->type = ARPHRD_PPP;
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
 	dev->features |= NETIF_F_NETNS_LOCAL;
+	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 }
 
 /*
@@ -1383,7 +1384,7 @@
 
 	/* create a	fragment for each channel */
 	bits = B;
-	while (nfree > 0 &&	len	> 0) {
+	while (len	> 0) {
 		list = list->next;
 		if (list ==	&ppp->channels)	{
 			i =	0;
@@ -1430,29 +1431,31 @@
 		*otherwise divide it according to the speed
 		*of the channel we are going to transmit on
 		*/
-		if (pch->speed == 0) {
-			flen = totlen/nfree	;
-			if (nbigger > 0) {
-				flen++;
-				nbigger--;
-			}
-		} else {
-			flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
-				((totspeed*totfree)/pch->speed)) - hdrlen;
-			if (nbigger > 0) {
-				flen += ((totfree - nzero)*pch->speed)/totspeed;
-				nbigger -= ((totfree - nzero)*pch->speed)/
+		if (nfree > 0) {
+			if (pch->speed == 0) {
+				flen = totlen/nfree	;
+				if (nbigger > 0) {
+					flen++;
+					nbigger--;
+				}
+			} else {
+				flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
+					((totspeed*totfree)/pch->speed)) - hdrlen;
+				if (nbigger > 0) {
+					flen += ((totfree - nzero)*pch->speed)/totspeed;
+					nbigger -= ((totfree - nzero)*pch->speed)/
 							totspeed;
+				}
 			}
+			nfree--;
 		}
-		nfree--;
 
 		/*
 		 *check	if we are on the last channel or
 		 *we exceded the lenght	of the data	to
 		 *fragment
 		 */
-		if ((nfree == 0) || (flen > len))
+		if ((nfree <= 0) || (flen > len))
 			flen = len;
 		/*
 		 *it is not worth to tx on slow channels:
@@ -1466,7 +1469,7 @@
 			continue;
 		}
 
-		mtu	= pch->chan->mtu + 2 - hdrlen;
+		mtu	= pch->chan->mtu - hdrlen;
 		if (mtu	< 4)
 			mtu	= 4;
 		if (flen > mtu)
diff -druN linux-libre-2.6.30-gnu/drivers/net/pppoe.c linux-libre-2.6.31-gnu/drivers/net/pppoe.c
--- linux-libre-2.6.30-gnu/drivers/net/pppoe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pppoe.c	2009-09-09 18:13:59.000000000 -0400
@@ -1063,6 +1063,7 @@
 	else {
 		int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
 
+		po = NULL;
 		while (++hash < PPPOE_HASH_SIZE) {
 			po = pn->hash_table[hash];
 			if (po)
diff -druN linux-libre-2.6.30-gnu/drivers/net/pppol2tp.c linux-libre-2.6.31-gnu/drivers/net/pppol2tp.c
--- linux-libre-2.6.30-gnu/drivers/net/pppol2tp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/pppol2tp.c	2009-09-09 18:13:59.000000000 -0400
@@ -433,8 +433,7 @@
 		 *   to the inner packet either
 		 */
 		secpath_reset(skb);
-		dst_release(skb->dst);
-		skb->dst = NULL;
+		skb_dst_drop(skb);
 		nf_reset(skb);
 
 		po = pppox_sk(session_sock);
@@ -976,7 +975,7 @@
 	/* Calculate UDP checksum if configured to do so */
 	if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
 		skb->ip_summed = CHECKSUM_NONE;
-	else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) {
+	else if (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		csum = skb_checksum(skb, 0, udp_len, 0);
 		uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
@@ -1172,14 +1171,14 @@
 	nf_reset(skb);
 
 	/* Get routing info from the tunnel socket */
-	dst_release(skb->dst);
-	skb->dst = dst_clone(__sk_dst_get(sk_tun));
+	skb_dst_drop(skb);
+	skb_dst_set(skb, dst_clone(__sk_dst_get(sk_tun)));
 	pppol2tp_skb_set_owner_w(skb, sk_tun);
 
 	/* Calculate UDP checksum if configured to do so */
 	if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
 		skb->ip_summed = CHECKSUM_NONE;
-	else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) {
+	else if (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		csum = skb_checksum(skb, 0, udp_len, 0);
 		uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
@@ -1238,8 +1237,7 @@
 	struct pppol2tp_session *session;
 	struct sock *sk;
 
-	if (tunnel == NULL)
-		BUG();
+	BUG_ON(tunnel == NULL);
 
 	PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
 	       "%s: closing all sessions...\n", tunnel->name);
@@ -2682,6 +2680,7 @@
 static void __exit pppol2tp_exit(void)
 {
 	unregister_pppox_proto(PX_PROTO_OL2TP);
+	unregister_pernet_gen_device(pppol2tp_net_id, &pppol2tp_net_ops);
 	proto_unregister(&pppol2tp_sk_proto);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ps3_gelic_net.c linux-libre-2.6.31-gnu/drivers/net/ps3_gelic_net.c
--- linux-libre-2.6.30-gnu/drivers/net/ps3_gelic_net.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ps3_gelic_net.c	2009-09-09 18:13:59.000000000 -0400
@@ -214,9 +214,10 @@
  *
  * returns 0 on success, <0 on failure
  */
-static int gelic_card_init_chain(struct gelic_card *card,
-				 struct gelic_descr_chain *chain,
-				 struct gelic_descr *start_descr, int no)
+static int __devinit gelic_card_init_chain(struct gelic_card *card,
+					   struct gelic_descr_chain *chain,
+					   struct gelic_descr *start_descr,
+					   int no)
 {
 	int i;
 	struct gelic_descr *descr;
@@ -407,7 +408,7 @@
  *
  * returns 0 on success, < 0 on failure
  */
-static int gelic_card_alloc_rx_skbs(struct gelic_card *card)
+static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card)
 {
 	struct gelic_descr_chain *chain;
 	int ret;
@@ -1410,6 +1411,7 @@
 	.ndo_set_multicast_list = gelic_net_set_multi,
 	.ndo_change_mtu = gelic_net_change_mtu,
 	.ndo_tx_timeout = gelic_net_tx_timeout,
+	.ndo_set_mac_address = eth_mac_addr,
 	.ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = gelic_net_poll_controller,
@@ -1422,8 +1424,8 @@
  *
  * fills out function pointers in the net_device structure
  */
-static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
-					 struct napi_struct *napi)
+static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
+						   struct napi_struct *napi)
 {
 	netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
 	/* NAPI */
@@ -1443,7 +1445,8 @@
  * gelic_ether_setup_netdev initializes the net_device structure
  * and register it.
  **/
-int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
+int __devinit gelic_net_setup_netdev(struct net_device *netdev,
+				     struct gelic_card *card)
 {
 	int status;
 	u64 v1, v2;
@@ -1491,7 +1494,7 @@
  * the card and net_device structures are linked to each other
  */
 #define GELIC_ALIGN (32)
-static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev)
+static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev)
 {
 	struct gelic_card *card;
 	struct gelic_port *port;
@@ -1542,7 +1545,7 @@
 	return card;
 }
 
-static void gelic_card_get_vlan_info(struct gelic_card *card)
+static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
 {
 	u64 v1, v2;
 	int status;
@@ -1616,7 +1619,7 @@
 /**
  * ps3_gelic_driver_probe - add a device to the control of this driver
  */
-static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
+static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
 {
 	struct gelic_card *card;
 	struct net_device *netdev;
@@ -1648,7 +1651,7 @@
 		result = -ENOMEM;
 		goto fail_alloc_card;
 	}
-	ps3_system_bus_set_driver_data(dev, card);
+	ps3_system_bus_set_drvdata(dev, card);
 	card->dev = dev;
 
 	/* get internal vlan info */
@@ -1749,7 +1752,7 @@
 					       bus_id(card),
 					       0, 0);
 fail_status_indicator:
-	ps3_system_bus_set_driver_data(dev, NULL);
+	ps3_system_bus_set_drvdata(dev, NULL);
 	kfree(netdev_card(netdev)->unalign);
 	free_netdev(netdev);
 fail_alloc_card:
@@ -1766,7 +1769,7 @@
 
 static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev)
 {
-	struct gelic_card *card = ps3_system_bus_get_driver_data(dev);
+	struct gelic_card *card = ps3_system_bus_get_drvdata(dev);
 	struct net_device *netdev0;
 	pr_debug("%s: called\n", __func__);
 
@@ -1803,7 +1806,7 @@
 	kfree(netdev_card(netdev0)->unalign);
 	free_netdev(netdev0);
 
-	ps3_system_bus_set_driver_data(dev, NULL);
+	ps3_system_bus_set_drvdata(dev, NULL);
 
 	ps3_dma_region_free(dev->d_region);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ps3_gelic_wireless.c linux-libre-2.6.31-gnu/drivers/net/ps3_gelic_wireless.c
--- linux-libre-2.6.30-gnu/drivers/net/ps3_gelic_wireless.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ps3_gelic_wireless.c	2009-09-09 18:13:59.000000000 -0400
@@ -2442,7 +2442,7 @@
 #endif
 };
 
-static struct net_device *gelic_wl_alloc(struct gelic_card *card)
+static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card)
 {
 	struct net_device *netdev;
 	struct gelic_port *port;
@@ -2707,6 +2707,7 @@
 	.ndo_set_multicast_list = gelic_net_set_multi,
 	.ndo_change_mtu = gelic_net_change_mtu,
 	.ndo_tx_timeout = gelic_net_tx_timeout,
+	.ndo_set_mac_address = eth_mac_addr,
 	.ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = gelic_net_poll_controller,
@@ -2722,7 +2723,7 @@
 	.set_rx_csum	= gelic_net_set_rx_csum,
 };
 
-static void gelic_wl_setup_netdev_ops(struct net_device *netdev)
+static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
 {
 	struct gelic_wl_info *wl;
 	wl = port_wl(netdev_priv(netdev));
@@ -2738,7 +2739,7 @@
 /*
  * driver probe/remove
  */
-int gelic_wl_driver_probe(struct gelic_card *card)
+int __devinit gelic_wl_driver_probe(struct gelic_card *card)
 {
 	int ret;
 	struct net_device *netdev;
diff -druN linux-libre-2.6.30-gnu/drivers/net/qla3xxx.c linux-libre-2.6.31-gnu/drivers/net/qla3xxx.c
--- linux-libre-2.6.30-gnu/drivers/net/qla3xxx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/qla3xxx.c	2009-09-09 18:13:59.000000000 -0400
@@ -2617,7 +2617,6 @@
 			    &port_regs->CommonRegs.reqQProducerIndex,
 			    qdev->req_producer_index);
 
-	ndev->trans_start = jiffies;
 	if (netif_msg_tx_queued(qdev))
 		printk(KERN_DEBUG PFX "%s: tx queued, slot %d, len %d\n",
 		       ndev->name, qdev->req_producer_index, skb->len);
@@ -3143,6 +3142,7 @@
 						(void __iomem *)port_regs;
 	u32 delay = 10;
 	int status = 0;
+	unsigned long hw_flags = 0;
 
 	if(ql_mii_setup(qdev))
 		return -1;
@@ -3151,7 +3151,8 @@
 	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
 			    (ISP_SERIAL_PORT_IF_WE |
 			     (ISP_SERIAL_PORT_IF_WE << 16)));
-
+	/* Give the PHY time to come out of reset. */
+	mdelay(100);
 	qdev->port_link_state = LS_DOWN;
 	netif_carrier_off(qdev->ndev);
 
@@ -3351,7 +3352,9 @@
 		value = ql_read_page0_reg(qdev, &port_regs->portStatus);
 		if (value & PORT_STATUS_IC)
 			break;
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 		msleep(500);
+		spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 	} while (--delay);
 
 	if (delay == 0) {
@@ -3838,7 +3841,9 @@
 						      16) | ISP_CONTROL_RI));
 			}
 
+			spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 			ssleep(1);
+			spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 		} while (--max_wait_time);
 		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/qlge/qlge_ethtool.c linux-libre-2.6.31-gnu/drivers/net/qlge/qlge_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/qlge/qlge_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/qlge/qlge_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -59,7 +59,7 @@
 			cqicb->pkt_delay =
 			    cpu_to_le16(qdev->tx_max_coalesced_frames);
 			cqicb->flags = FLAGS_LI;
-			status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
+			status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb),
 						CFG_LCQ, rx_ring->cq_id);
 			if (status) {
 				QPRINTK(qdev, IFUP, ERR,
@@ -82,7 +82,7 @@
 			cqicb->pkt_delay =
 			    cpu_to_le16(qdev->rx_max_coalesced_frames);
 			cqicb->flags = FLAGS_LI;
-			status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
+			status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb),
 						CFG_LCQ, rx_ring->cq_id);
 			if (status) {
 				QPRINTK(qdev, IFUP, ERR,
@@ -293,7 +293,10 @@
 	struct ql_adapter *qdev = netdev_priv(ndev);
 	strncpy(drvinfo->driver, qlge_driver_name, 32);
 	strncpy(drvinfo->version, qlge_driver_version, 32);
-	strncpy(drvinfo->fw_version, "N/A", 32);
+	snprintf(drvinfo->fw_version, 32, "v%d.%d.%d",
+		 (qdev->fw_rev_id & 0x00ff0000) >> 16,
+		 (qdev->fw_rev_id & 0x0000ff00) >> 8,
+		 (qdev->fw_rev_id & 0x000000ff));
 	strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32);
 	drvinfo->n_stats = 0;
 	drvinfo->testinfo_len = 0;
@@ -401,6 +404,7 @@
 	.get_rx_csum = ql_get_rx_csum,
 	.set_rx_csum = ql_set_rx_csum,
 	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,
 	.get_sg = ethtool_op_get_sg,
 	.set_sg = ethtool_op_set_sg,
 	.get_tso = ethtool_op_get_tso,
diff -druN linux-libre-2.6.30-gnu/drivers/net/qlge/qlge.h linux-libre-2.6.31-gnu/drivers/net/qlge/qlge.h
--- linux-libre-2.6.30-gnu/drivers/net/qlge/qlge.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/qlge/qlge.h	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,8 @@
 			   "%s: " fmt, __func__, ##args);  \
        } while (0)
 
+#define WQ_ADDR_ALIGN	0x3	/* 4 byte alignment */
+
 #define QLGE_VENDOR_ID    0x1077
 #define QLGE_DEVICE_ID_8012	0x8012
 #define QLGE_DEVICE_ID_8000	0x8000
@@ -39,7 +41,18 @@
 
 #define NUM_SMALL_BUFFERS   512
 #define NUM_LARGE_BUFFERS   512
+#define DB_PAGE_SIZE 4096
 
+/* Calculate the number of (4k) pages required to
+ * contain a buffer queue of the given length.
+ */
+#define MAX_DB_PAGES_PER_BQ(x) \
+		(((x * sizeof(u64)) / DB_PAGE_SIZE) + \
+		(((x * sizeof(u64)) % DB_PAGE_SIZE) ? 1 : 0))
+
+#define RX_RING_SHADOW_SPACE	(sizeof(u64) + \
+		MAX_DB_PAGES_PER_BQ(NUM_SMALL_BUFFERS) * sizeof(u64) + \
+		MAX_DB_PAGES_PER_BQ(NUM_LARGE_BUFFERS) * sizeof(u64))
 #define SMALL_BUFFER_SIZE 256
 #define LARGE_BUFFER_SIZE	PAGE_SIZE
 #define MAX_SPLIT_SIZE 1023
@@ -50,7 +63,7 @@
 #define MAX_INTER_FRAME_WAIT 10	/* 10 usec max interframe-wait for coalescing */
 #define DFLT_INTER_FRAME_WAIT (MAX_INTER_FRAME_WAIT/2)
 #define UDELAY_COUNT 3
-#define UDELAY_DELAY 10
+#define UDELAY_DELAY 100
 
 
 #define TX_DESC_PER_IOCB 8
@@ -63,7 +76,16 @@
 #define TX_DESC_PER_OAL 0
 #endif
 
-#define DB_PAGE_SIZE 4096
+/* MPI test register definitions. This register
+ * is used for determining alternate NIC function's
+ * PCI->func number.
+ */
+enum {
+	MPI_TEST_FUNC_PORT_CFG = 0x1002,
+	MPI_TEST_NIC1_FUNC_SHIFT = 1,
+	MPI_TEST_NIC2_FUNC_SHIFT = 5,
+	MPI_TEST_NIC_FUNC_MASK = 0x00000007,
+};
 
 /*
  * Processor Address Register (PROC_ADDR) bit definitions.
@@ -1430,7 +1452,10 @@
 
 	/* Hardware information */
 	u32 chip_rev_id;
+	u32 fw_rev_id;
 	u32 func;		/* PCI function for this adapter */
+	u32 alt_func;		/* PCI function for alternate adapter */
+	u32 port;		/* Port number this adapter */
 
 	spinlock_t adapter_lock;
 	spinlock_t hw_lock;
@@ -1580,6 +1605,10 @@
 void ql_mpi_port_cfg_work(struct work_struct *work);
 int ql_mb_get_fw_state(struct ql_adapter *qdev);
 int ql_cam_route_initialize(struct ql_adapter *qdev);
+int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
+int ql_mb_about_fw(struct ql_adapter *qdev);
+void ql_link_on(struct ql_adapter *qdev);
+void ql_link_off(struct ql_adapter *qdev);
 
 #if 1
 #define QL_ALL_DUMP
diff -druN linux-libre-2.6.30-gnu/drivers/net/qlge/qlge_main.c linux-libre-2.6.31-gnu/drivers/net/qlge/qlge_main.c
--- linux-libre-2.6.30-gnu/drivers/net/qlge/qlge_main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/qlge/qlge_main.c	2009-09-09 18:13:59.000000000 -0400
@@ -214,6 +214,10 @@
 		return -ENOMEM;
 	}
 
+	status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
+	if (status)
+		return status;
+
 	status = ql_wait_cfg(qdev, bit);
 	if (status) {
 		QPRINTK(qdev, IFUP, ERR,
@@ -221,12 +225,8 @@
 		goto exit;
 	}
 
-	status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
-	if (status)
-		goto exit;
 	ql_write32(qdev, ICB_L, (u32) map);
 	ql_write32(qdev, ICB_H, (u32) (map >> 32));
-	ql_sem_unlock(qdev, SEM_ICB_MASK);	/* does flush too */
 
 	mask = CFG_Q_MASK | (bit << 16);
 	value = bit | (q_id << CFG_Q_SHIFT);
@@ -237,6 +237,7 @@
 	 */
 	status = ql_wait_cfg(qdev, bit);
 exit:
+	ql_sem_unlock(qdev, SEM_ICB_MASK);	/* does flush too */
 	pci_unmap_single(qdev->pdev, map, size, direction);
 	return status;
 }
@@ -412,6 +413,57 @@
 	return status;
 }
 
+/* Set or clear MAC address in hardware. We sometimes
+ * have to clear it to prevent wrong frame routing
+ * especially in a bonding environment.
+ */
+static int ql_set_mac_addr(struct ql_adapter *qdev, int set)
+{
+	int status;
+	char zero_mac_addr[ETH_ALEN];
+	char *addr;
+
+	if (set) {
+		addr = &qdev->ndev->dev_addr[0];
+		QPRINTK(qdev, IFUP, DEBUG,
+			"Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+			addr[0], addr[1], addr[2], addr[3],
+			addr[4], addr[5]);
+	} else {
+		memset(zero_mac_addr, 0, ETH_ALEN);
+		addr = &zero_mac_addr[0];
+		QPRINTK(qdev, IFUP, DEBUG,
+				"Clearing MAC address on %s\n",
+				qdev->ndev->name);
+	}
+	status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+	if (status)
+		return status;
+	status = ql_set_mac_addr_reg(qdev, (u8 *) addr,
+			MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
+	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+	if (status)
+		QPRINTK(qdev, IFUP, ERR, "Failed to init mac "
+			"address.\n");
+	return status;
+}
+
+void ql_link_on(struct ql_adapter *qdev)
+{
+	QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n",
+				 qdev->ndev->name);
+	netif_carrier_on(qdev->ndev);
+	ql_set_mac_addr(qdev, 1);
+}
+
+void ql_link_off(struct ql_adapter *qdev)
+{
+	QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n",
+				 qdev->ndev->name);
+	netif_carrier_off(qdev->ndev);
+	ql_set_mac_addr(qdev, 0);
+}
+
 /* Get a specific frame routing value from the CAM.
  * Used for debug and reg dump.
  */
@@ -675,11 +727,12 @@
 	int status;
 	__le32 *p = (__le32 *)&qdev->flash;
 	u32 offset;
+	u8 mac_addr[6];
 
 	/* Get flash offset for function and adjust
 	 * for dword access.
 	 */
-	if (!qdev->func)
+	if (!qdev->port)
 		offset = FUNC0_FLASH_OFFSET / sizeof(u32);
 	else
 		offset = FUNC1_FLASH_OFFSET / sizeof(u32);
@@ -705,14 +758,26 @@
 		goto exit;
 	}
 
-	if (!is_valid_ether_addr(qdev->flash.flash_params_8000.mac_addr)) {
+	/* Extract either manufacturer or BOFM modified
+	 * MAC address.
+	 */
+	if (qdev->flash.flash_params_8000.data_type1 == 2)
+		memcpy(mac_addr,
+			qdev->flash.flash_params_8000.mac_addr1,
+			qdev->ndev->addr_len);
+	else
+		memcpy(mac_addr,
+			qdev->flash.flash_params_8000.mac_addr,
+			qdev->ndev->addr_len);
+
+	if (!is_valid_ether_addr(mac_addr)) {
 		QPRINTK(qdev, IFUP, ERR, "Invalid MAC address.\n");
 		status = -EINVAL;
 		goto exit;
 	}
 
 	memcpy(qdev->ndev->dev_addr,
-		qdev->flash.flash_params_8000.mac_addr,
+		mac_addr,
 		qdev->ndev->addr_len);
 
 exit:
@@ -731,7 +796,7 @@
 	/* Second function's parameters follow the first
 	 * function's.
 	 */
-	if (qdev->func)
+	if (qdev->port)
 		offset = size;
 
 	if (ql_sem_spinlock(qdev, SEM_FLASH_MASK))
@@ -837,6 +902,13 @@
 static int ql_8000_port_initialize(struct ql_adapter *qdev)
 {
 	int status;
+	/*
+	 * Get MPI firmware version for driver banner
+	 * and ethool info.
+	 */
+	status = ql_mb_about_fw(qdev);
+	if (status)
+		goto exit;
 	status = ql_mb_get_fw_state(qdev);
 	if (status)
 		goto exit;
@@ -1518,6 +1590,22 @@
 		return;
 	}
 
+	/* Frame error, so drop the packet. */
+	if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+		QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n",
+					ib_mac_rsp->flags2);
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
+	/* The max framesize filter on this chip is set higher than
+	 * MTU since FCoE uses 2k frames.
+	 */
+	if (skb->len > ndev->mtu + ETH_HLEN) {
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
 	prefetch(skb->data);
 	skb->dev = ndev;
 	if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) {
@@ -1540,7 +1628,6 @@
 	 * csum or frame errors.
 	 */
 	if (qdev->rx_csum &&
-		!(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) &&
 		!(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) {
 		/* TCP frame. */
 		if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) {
@@ -1593,7 +1680,7 @@
 	tx_ring = &qdev->tx_ring[mac_rsp->txq_idx];
 	tx_ring_desc = &tx_ring->q[mac_rsp->tid];
 	ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt);
-	qdev->stats.tx_bytes += tx_ring_desc->map_cnt;
+	qdev->stats.tx_bytes += (tx_ring_desc->skb)->len;
 	qdev->stats.tx_packets++;
 	dev_kfree_skb(tx_ring_desc->skb);
 	tx_ring_desc->skb = NULL;
@@ -1625,13 +1712,13 @@
 /* Fire up a handler to reset the MPI processor. */
 void ql_queue_fw_error(struct ql_adapter *qdev)
 {
-	netif_carrier_off(qdev->ndev);
+	ql_link_off(qdev);
 	queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0);
 }
 
 void ql_queue_asic_error(struct ql_adapter *qdev)
 {
-	netif_carrier_off(qdev->ndev);
+	ql_link_off(qdev);
 	ql_disable_interrupts(qdev);
 	/* Clear adapter up bit to signal the recovery
 	 * process that it shouldn't kill the reset worker
@@ -2069,7 +2156,7 @@
 	}
 	tx_ring_desc = &tx_ring->q[tx_ring->prod_idx];
 	mac_iocb_ptr = tx_ring_desc->queue_entry;
-	memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr));
+	memset((void *)mac_iocb_ptr, 0, sizeof(*mac_iocb_ptr));
 
 	mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB;
 	mac_iocb_ptr->tid = tx_ring_desc->index;
@@ -2108,7 +2195,6 @@
 	wmb();
 
 	ql_write_db_reg(tx_ring->prod_idx, tx_ring->prod_idx_db_reg);
-	ndev->trans_start = jiffies;
 	QPRINTK(qdev, TX_QUEUED, DEBUG, "tx queued, slot %d, len %d\n",
 		tx_ring->prod_idx, skb->len);
 
@@ -2203,7 +2289,7 @@
 				 &tx_ring->wq_base_dma);
 
 	if ((tx_ring->wq_base == NULL)
-	    || tx_ring->wq_base_dma & (tx_ring->wq_size - 1)) {
+		|| tx_ring->wq_base_dma & WQ_ADDR_ALIGN) {
 		QPRINTK(qdev, IFUP, ERR, "tx_ring alloc failed.\n");
 		return -ENOMEM;
 	}
@@ -2518,14 +2604,16 @@
 {
 	struct cqicb *cqicb = &rx_ring->cqicb;
 	void *shadow_reg = qdev->rx_ring_shadow_reg_area +
-	    (rx_ring->cq_id * sizeof(u64) * 4);
+		(rx_ring->cq_id * RX_RING_SHADOW_SPACE);
 	u64 shadow_reg_dma = qdev->rx_ring_shadow_reg_dma +
-	    (rx_ring->cq_id * sizeof(u64) * 4);
+		(rx_ring->cq_id * RX_RING_SHADOW_SPACE);
 	void __iomem *doorbell_area =
 	    qdev->doorbell_area + (DB_PAGE_SIZE * (128 + rx_ring->cq_id));
 	int err = 0;
 	u16 bq_len;
 	u64 tmp;
+	__le64 *base_indirect_ptr;
+	int page_entries;
 
 	/* Set up the shadow registers for this ring. */
 	rx_ring->prod_idx_sh_reg = shadow_reg;
@@ -2534,8 +2622,8 @@
 	shadow_reg_dma += sizeof(u64);
 	rx_ring->lbq_base_indirect = shadow_reg;
 	rx_ring->lbq_base_indirect_dma = shadow_reg_dma;
-	shadow_reg += sizeof(u64);
-	shadow_reg_dma += sizeof(u64);
+	shadow_reg += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len));
+	shadow_reg_dma += (sizeof(u64) * MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len));
 	rx_ring->sbq_base_indirect = shadow_reg;
 	rx_ring->sbq_base_indirect_dma = shadow_reg_dma;
 
@@ -2572,7 +2660,14 @@
 	if (rx_ring->lbq_len) {
 		cqicb->flags |= FLAGS_LL;	/* Load lbq values */
 		tmp = (u64)rx_ring->lbq_base_dma;;
-		*((__le64 *) rx_ring->lbq_base_indirect) = cpu_to_le64(tmp);
+		base_indirect_ptr = (__le64 *) rx_ring->lbq_base_indirect;
+		page_entries = 0;
+		do {
+			*base_indirect_ptr = cpu_to_le64(tmp);
+			tmp += DB_PAGE_SIZE;
+			base_indirect_ptr++;
+			page_entries++;
+		} while (page_entries < MAX_DB_PAGES_PER_BQ(rx_ring->lbq_len));
 		cqicb->lbq_addr =
 		    cpu_to_le64(rx_ring->lbq_base_indirect_dma);
 		bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 :
@@ -2589,7 +2684,14 @@
 	if (rx_ring->sbq_len) {
 		cqicb->flags |= FLAGS_LS;	/* Load sbq values */
 		tmp = (u64)rx_ring->sbq_base_dma;;
-		*((__le64 *) rx_ring->sbq_base_indirect) = cpu_to_le64(tmp);
+		base_indirect_ptr = (__le64 *) rx_ring->sbq_base_indirect;
+		page_entries = 0;
+		do {
+			*base_indirect_ptr = cpu_to_le64(tmp);
+			tmp += DB_PAGE_SIZE;
+			base_indirect_ptr++;
+			page_entries++;
+		} while (page_entries < MAX_DB_PAGES_PER_BQ(rx_ring->sbq_len));
 		cqicb->sbq_addr =
 		    cpu_to_le64(rx_ring->sbq_base_indirect_dma);
 		cqicb->sbq_buf_size =
@@ -2693,7 +2795,7 @@
 
 	ql_init_tx_ring(qdev, tx_ring);
 
-	err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ,
+	err = ql_write_cfg(qdev, wqicb, sizeof(*wqicb), CFG_LRQ,
 			   (u16) tx_ring->wq_id);
 	if (err) {
 		QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n");
@@ -2958,7 +3060,7 @@
 	int i;
 	u8 *hash_id = (u8 *) ricb->hash_cq_id;
 
-	memset((void *)ricb, 0, sizeof(ricb));
+	memset((void *)ricb, 0, sizeof(*ricb));
 
 	ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K;
 	ricb->flags =
@@ -2980,7 +3082,7 @@
 
 	QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n");
 
-	status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0);
+	status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0);
 	if (status) {
 		QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n");
 		return status;
@@ -2989,25 +3091,40 @@
 	return status;
 }
 
-/* Initialize the frame-to-queue routing. */
-static int ql_route_initialize(struct ql_adapter *qdev)
+static int ql_clear_routing_entries(struct ql_adapter *qdev)
 {
-	int status = 0;
-	int i;
+	int i, status = 0;
 
 	status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
 	if (status)
 		return status;
-
 	/* Clear all the entries in the routing table. */
 	for (i = 0; i < 16; i++) {
 		status = ql_set_routing_reg(qdev, i, 0, 0);
 		if (status) {
 			QPRINTK(qdev, IFUP, ERR,
-				"Failed to init routing register for CAM packets.\n");
-			goto exit;
+				"Failed to init routing register for CAM "
+				"packets.\n");
+			break;
 		}
 	}
+	ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
+	return status;
+}
+
+/* Initialize the frame-to-queue routing. */
+static int ql_route_initialize(struct ql_adapter *qdev)
+{
+	int status = 0;
+
+	status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
+	if (status)
+		return status;
+
+	/* Clear all the entries in the routing table. */
+	status = ql_clear_routing_entries(qdev);
+	if (status)
+		goto exit;
 
 	status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1);
 	if (status) {
@@ -3046,14 +3163,15 @@
 
 int ql_cam_route_initialize(struct ql_adapter *qdev)
 {
-	int status;
+	int status, set;
 
-	status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
-	if (status)
-		return status;
-	status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr,
-			     MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
-	ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+	/* If check if the link is up and use to
+	 * determine if we are setting or clearing
+	 * the MAC address in the CAM.
+	 */
+	set = ql_read32(qdev, STS);
+	set &= qdev->port_link_up;
+	status = ql_set_mac_addr(qdev, set);
 	if (status) {
 		QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n");
 		return status;
@@ -3160,9 +3278,17 @@
 {
 	u32 value;
 	int status = 0;
-	unsigned long end_jiffies = jiffies +
-		max((unsigned long)1, usecs_to_jiffies(30));
+	unsigned long end_jiffies;
+
+	/* Clear all the entries in the routing table. */
+	status = ql_clear_routing_entries(qdev);
+	if (status) {
+		QPRINTK(qdev, IFUP, ERR, "Failed to clear routing bits.\n");
+		return status;
+	}
 
+	end_jiffies = jiffies +
+		max((unsigned long)1, usecs_to_jiffies(30));
 	ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR);
 
 	do {
@@ -3174,7 +3300,7 @@
 
 	if (value & RST_FO_FR) {
 		QPRINTK(qdev, IFDOWN, ERR,
-			"ETIMEOUT!!! errored out of resetting the chip!\n");
+			"ETIMEDOUT!!! errored out of resetting the chip!\n");
 		status = -ETIMEDOUT;
 	}
 
@@ -3186,9 +3312,10 @@
 	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
 
 	QPRINTK(qdev, PROBE, INFO,
-		"Function #%d, NIC Roll %d, NIC Rev = %d, "
+		"Function #%d, Port %d, NIC Roll %d, NIC Rev = %d, "
 		"XG Roll = %d, XG Rev = %d.\n",
 		qdev->func,
+		qdev->port,
 		qdev->chip_rev_id & 0x0000000f,
 		qdev->chip_rev_id >> 4 & 0x0000000f,
 		qdev->chip_rev_id >> 8 & 0x0000000f,
@@ -3201,7 +3328,7 @@
 	int i, status = 0;
 	struct rx_ring *rx_ring;
 
-	netif_carrier_off(qdev->ndev);
+	ql_link_off(qdev);
 
 	/* Don't kill the reset worker thread if we
 	 * are in the process of recovery.
@@ -3264,13 +3391,16 @@
 	err = ql_adapter_initialize(qdev);
 	if (err) {
 		QPRINTK(qdev, IFUP, INFO, "Unable to initialize adapter.\n");
-		spin_unlock(&qdev->hw_lock);
 		goto err_init;
 	}
 	set_bit(QL_ADAPTER_UP, &qdev->flags);
 	ql_alloc_rx_buffers(qdev);
-	if ((ql_read32(qdev, STS) & qdev->port_init))
-		netif_carrier_on(qdev->ndev);
+	/* If the port is initialized and the
+	 * link is up the turn on the carrier.
+	 */
+	if ((ql_read32(qdev, STS) & qdev->port_init) &&
+			(ql_read32(qdev, STS) & qdev->port_link_up))
+		ql_link_on(qdev);
 	ql_enable_interrupts(qdev);
 	ql_enable_all_completion_interrupts(qdev);
 	netif_tx_start_all_queues(qdev->ndev);
@@ -3296,11 +3426,6 @@
 		return -ENOMEM;
 	}
 	status = ql_request_irq(qdev);
-	if (status)
-		goto err_irq;
-	return status;
-err_irq:
-	ql_free_mem_resources(qdev);
 	return status;
 }
 
@@ -3361,11 +3486,10 @@
 	 * completion handler rx_rings.
 	 */
 	qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1;
-	netif_set_gso_max_size(qdev->ndev, 65536);
 
 	for (i = 0; i < qdev->tx_ring_count; i++) {
 		tx_ring = &qdev->tx_ring[i];
-		memset((void *)tx_ring, 0, sizeof(tx_ring));
+		memset((void *)tx_ring, 0, sizeof(*tx_ring));
 		tx_ring->qdev = qdev;
 		tx_ring->wq_id = i;
 		tx_ring->wq_len = qdev->tx_ring_size;
@@ -3381,7 +3505,7 @@
 
 	for (i = 0; i < qdev->rx_ring_count; i++) {
 		rx_ring = &qdev->rx_ring[i];
-		memset((void *)rx_ring, 0, sizeof(rx_ring));
+		memset((void *)rx_ring, 0, sizeof(*rx_ring));
 		rx_ring->qdev = qdev;
 		rx_ring->cq_id = i;
 		rx_ring->cpu = i % cpu_cnt;	/* CPU to run handler on. */
@@ -3644,12 +3768,53 @@
 	.port_initialize	= ql_8000_port_initialize,
 };
 
+/* Find the pcie function number for the other NIC
+ * on this chip.  Since both NIC functions share a
+ * common firmware we have the lowest enabled function
+ * do any common work.  Examples would be resetting
+ * after a fatal firmware error, or doing a firmware
+ * coredump.
+ */
+static int ql_get_alt_pcie_func(struct ql_adapter *qdev)
+{
+	int status = 0;
+	u32 temp;
+	u32 nic_func1, nic_func2;
+
+	status = ql_read_mpi_reg(qdev, MPI_TEST_FUNC_PORT_CFG,
+			&temp);
+	if (status)
+		return status;
 
-static void ql_get_board_info(struct ql_adapter *qdev)
+	nic_func1 = ((temp >> MPI_TEST_NIC1_FUNC_SHIFT) &
+			MPI_TEST_NIC_FUNC_MASK);
+	nic_func2 = ((temp >> MPI_TEST_NIC2_FUNC_SHIFT) &
+			MPI_TEST_NIC_FUNC_MASK);
+
+	if (qdev->func == nic_func1)
+		qdev->alt_func = nic_func2;
+	else if (qdev->func == nic_func2)
+		qdev->alt_func = nic_func1;
+	else
+		status = -EIO;
+
+	return status;
+}
+
+static int ql_get_board_info(struct ql_adapter *qdev)
 {
+	int status;
 	qdev->func =
 	    (ql_read32(qdev, STS) & STS_FUNC_ID_MASK) >> STS_FUNC_ID_SHIFT;
-	if (qdev->func) {
+	if (qdev->func > 3)
+		return -EIO;
+
+	status = ql_get_alt_pcie_func(qdev);
+	if (status)
+		return status;
+
+	qdev->port = (qdev->func < qdev->alt_func) ? 0 : 1;
+	if (qdev->port) {
 		qdev->xg_sem_mask = SEM_XGMAC1_MASK;
 		qdev->port_link_up = STS_PL1;
 		qdev->port_init = STS_PI1;
@@ -3668,6 +3833,7 @@
 		qdev->nic_ops = &qla8012_nic_ops;
 	else if (qdev->device_id == QLGE_DEVICE_ID_8000)
 		qdev->nic_ops = &qla8000_nic_ops;
+	return status;
 }
 
 static void ql_release_all(struct pci_dev *pdev)
@@ -3698,7 +3864,7 @@
 	int pos, err = 0;
 	u16 val16;
 
-	memset((void *)qdev, 0, sizeof(qdev));
+	memset((void *)qdev, 0, sizeof(*qdev));
 	err = pci_enable_device(pdev);
 	if (err) {
 		dev_err(&pdev->dev, "PCI device enable failed.\n");
@@ -3762,7 +3928,12 @@
 
 	qdev->ndev = ndev;
 	qdev->pdev = pdev;
-	ql_get_board_info(qdev);
+	err = ql_get_board_info(qdev);
+	if (err) {
+		dev_err(&pdev->dev, "Register access failed.\n");
+		err = -EIO;
+		goto err_out;
+	}
 	qdev->msg_enable = netif_msg_init(debug, default_msg);
 	spin_lock_init(&qdev->hw_lock);
 	spin_lock_init(&qdev->stats_lock);
@@ -3880,7 +4051,7 @@
 		pci_disable_device(pdev);
 		return err;
 	}
-	netif_carrier_off(ndev);
+	ql_link_off(qdev);
 	ql_display_dev_info(ndev);
 	cards_found++;
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/qlge/qlge_mpi.c linux-libre-2.6.31-gnu/drivers/net/qlge/qlge_mpi.c
--- linux-libre-2.6.30-gnu/drivers/net/qlge/qlge_mpi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/qlge/qlge_mpi.c	2009-09-09 18:13:59.000000000 -0400
@@ -90,14 +90,14 @@
  */
 static int ql_wait_mbx_cmd_cmplt(struct ql_adapter *qdev)
 {
-	int count = 50;	/* TODO: arbitrary for now. */
+	int count = 100;
 	u32 value;
 
 	do {
 		value = ql_read32(qdev, STS);
 		if (value & STS_PI)
 			return 0;
-		udelay(UDELAY_DELAY); /* 10us */
+		mdelay(UDELAY_DELAY); /* 100ms */
 	} while (--count);
 	return -ETIMEDOUT;
 }
@@ -141,7 +141,7 @@
 /* We are being asked by firmware to accept
  * a change to the port.  This is only
  * a change to max frame sizes (Tx/Rx), pause
- * paramters, or loopback mode. We wake up a worker
+ * parameters, or loopback mode. We wake up a worker
  * to handler processing this since a mailbox command
  * will need to be sent to ACK the request.
  */
@@ -238,7 +238,7 @@
 				&qdev->mpi_port_cfg_work, 0);
 	}
 
-	netif_carrier_on(qdev->ndev);
+	ql_link_on(qdev);
 }
 
 static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
@@ -251,7 +251,7 @@
 	if (status)
 		QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n");
 
-	netif_carrier_off(qdev->ndev);
+	ql_link_off(qdev);
 }
 
 static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp)
@@ -371,7 +371,7 @@
 	/* We are being asked by firmware to accept
 	 * a change to the port.  This is only
 	 * a change to max frame sizes (Tx/Rx), pause
-	 * paramters, or loopback mode.
+	 * parameters, or loopback mode.
 	 */
 	case AEN_IDC_REQ:
 		status = ql_idc_req_aen(qdev);
@@ -380,7 +380,7 @@
 	/* Process and inbound IDC event.
 	 * This will happen when we're trying to
 	 * change tx/rx max frame size, change pause
-	 * paramters or loopback mode.
+	 * parameters or loopback mode.
 	 */
 	case AEN_IDC_CMPLT:
 	case AEN_IDC_EXT:
@@ -453,6 +453,13 @@
 	}
 end:
 	ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
+	/* Restore the original mailbox count to
+	 * what the caller asked for.  This can get
+	 * changed when a mailbox command is waiting
+	 * for a response and an AEN arrives and
+	 * is handled.
+	 * */
+	mbcp->out_count = orig_count;
 	return status;
 }
 
@@ -540,6 +547,40 @@
 	return status;
 }
 
+
+/* Get MPI firmware version. This will be used for
+ * driver banner and for ethtool info.
+ * Returns zero on success.
+ */
+int ql_mb_about_fw(struct ql_adapter *qdev)
+{
+	struct mbox_params mbc;
+	struct mbox_params *mbcp = &mbc;
+	int status = 0;
+
+	memset(mbcp, 0, sizeof(struct mbox_params));
+
+	mbcp->in_count = 1;
+	mbcp->out_count = 3;
+
+	mbcp->mbox_in[0] = MB_CMD_ABOUT_FW;
+
+	status = ql_mailbox_command(qdev, mbcp);
+	if (status)
+		return status;
+
+	if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) {
+		QPRINTK(qdev, DRV, ERR,
+			"Failed about firmware command\n");
+		status = -EIO;
+	}
+
+	/* Store the firmware version */
+	qdev->fw_rev_id = mbcp->mbox_out[1];
+
+	return status;
+}
+
 /* Get functional state for MPI firmware.
  * Returns zero on success.
  */
@@ -754,7 +795,6 @@
 {
 	struct ql_adapter *qdev =
 	    container_of(work, struct ql_adapter, mpi_port_cfg_work.work);
-	struct net_device *ndev = qdev->ndev;
 	int status;
 
 	status = ql_mb_get_port_cfg(qdev);
@@ -764,9 +804,7 @@
 		goto err;
 	}
 
-	if (ndev->mtu <= 2500)
-		goto end;
-	else if (qdev->link_config & CFG_JUMBO_FRAME_SIZE &&
+	if (qdev->link_config & CFG_JUMBO_FRAME_SIZE &&
 			qdev->max_frame_size ==
 			CFG_DEFAULT_MAX_FRAME_SIZE)
 		goto end;
@@ -811,7 +849,7 @@
 	case MB_CMD_PORT_RESET:
 	case MB_CMD_SET_PORT_CFG:
 	case MB_CMD_STOP_FW:
-		netif_carrier_off(qdev->ndev);
+		ql_link_off(qdev);
 		/* Signal the resulting link up AEN
 		 * that the frame routing and mac addr
 		 * needs to be set.
@@ -831,13 +869,19 @@
 	    container_of(work, struct ql_adapter, mpi_work.work);
 	struct mbox_params mbc;
 	struct mbox_params *mbcp = &mbc;
+	int err = 0;
 
 	mutex_lock(&qdev->mpi_mutex);
 
 	while (ql_read32(qdev, STS) & STS_PI) {
 		memset(mbcp, 0, sizeof(struct mbox_params));
 		mbcp->out_count = 1;
-		ql_mpi_handler(qdev, mbcp);
+		/* Don't continue if an async event
+		 * did not complete properly.
+		 */
+		err = ql_mpi_handler(qdev, mbcp);
+		if (err)
+			break;
 	}
 
 	mutex_unlock(&qdev->mpi_mutex);
diff -druN linux-libre-2.6.30-gnu/drivers/net/r6040.c linux-libre-2.6.31-gnu/drivers/net/r6040.c
--- linux-libre-2.6.30-gnu/drivers/net/r6040.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/r6040.c	2009-09-09 18:13:59.000000000 -0400
@@ -49,8 +49,8 @@
 #include <asm/processor.h>
 
 #define DRV_NAME	"r6040"
-#define DRV_VERSION	"0.22"
-#define DRV_RELDATE	"25Mar2009"
+#define DRV_VERSION	"0.24"
+#define DRV_RELDATE	"08Jul2009"
 
 /* PHY CHIP Address */
 #define PHY1_ADDR	1	/* For MAC1 */
@@ -401,6 +401,9 @@
 	 * we may got called by r6040_tx_timeout which has left
 	 * some unsent tx buffers */
 	iowrite16(0x01, ioaddr + MTPR);
+
+	/* Check media */
+	mii_check_media(&lp->mii_if, 1, 1);
 }
 
 static void r6040_tx_timeout(struct net_device *dev)
@@ -528,6 +531,8 @@
 			phy_dat = 0x0000;
 	}
 
+	mii_check_media(&lp->mii_if, 0, 1);
+
 	return phy_dat;
 };
 
@@ -699,8 +704,11 @@
 	/* Read MISR status and clear */
 	status = ioread16(ioaddr + MISR);
 
-	if (status == 0x0000 || status == 0xffff)
+	if (status == 0x0000 || status == 0xffff) {
+		/* Restore RDC MAC interrupt */
+		iowrite16(misr, ioaddr + MIER);
 		return IRQ_NONE;
+	}
 
 	/* RX interrupt request */
 	if (status & RX_INTS) {
@@ -742,6 +750,14 @@
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 	int ret;
+	u16 val;
+
+	/* Check presence of a second PHY */
+	val = r6040_phy_read(ioaddr, lp->phy_addr, 2);
+	if (val == 0xFFFF) {
+		printk(KERN_ERR DRV_NAME " no second PHY attached\n");
+		return -EIO;
+	}
 
 	/* Initialise and alloc RX/TX buffers */
 	r6040_init_txbufs(dev);
@@ -802,7 +818,6 @@
 		lp->phy_mode = phy_mode;
 		lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode;
 		iowrite16(lp->mcr0, ioaddr);
-		printk(KERN_INFO "Link Change %x \n", ioread16(ioaddr));
 	}
 
 	/* Timer active again */
diff -druN linux-libre-2.6.30-gnu/drivers/net/r8169.c linux-libre-2.6.31-gnu/drivers/net/r8169.c
--- linux-libre-2.6.30-gnu/drivers/net/r8169.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/r8169.c	2009-09-09 18:13:59.000000000 -0400
@@ -51,9 +51,6 @@
 #define TX_BUFFS_AVAIL(tp) \
 	(tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
 
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static const int max_interrupt_work = 20;
-
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
    The RTL chips use a 64 element hash table based on the Ethernet CRC. */
 static const int multicast_filter_limit = 32;
@@ -93,6 +90,7 @@
 #define RTL_R32(reg)		((unsigned long) readl (ioaddr + (reg)))
 
 enum mac_version {
+	RTL_GIGA_MAC_NONE   = 0x00,
 	RTL_GIGA_MAC_VER_01 = 0x01, // 8169
 	RTL_GIGA_MAC_VER_02 = 0x02, // 8169S
 	RTL_GIGA_MAC_VER_03 = 0x03, // 8110S
@@ -478,7 +476,6 @@
 	u16 intr_event;
 	u16 napi_event;
 	u16 intr_mask;
-	int phy_auto_nego_reg;
 	int phy_1000_ctrl_reg;
 #ifdef CONFIG_R8169_VLAN
 	struct vlan_group *vlgrp;
@@ -843,76 +840,81 @@
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
-	int auto_nego, giga_ctrl;
-
-	auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
-	auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
-		       ADVERTISE_100HALF | ADVERTISE_100FULL);
-	giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
-	giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+	int giga_ctrl, bmcr;
 
 	if (autoneg == AUTONEG_ENABLE) {
+		int auto_nego;
+
+		auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
 		auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
 			      ADVERTISE_100HALF | ADVERTISE_100FULL);
-		giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
-	} else {
-		if (speed == SPEED_10)
-			auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL;
-		else if (speed == SPEED_100)
-			auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL;
-		else if (speed == SPEED_1000)
-			giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
-
-		if (duplex == DUPLEX_HALF)
-			auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL);
-
-		if (duplex == DUPLEX_FULL)
-			auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF);
+		auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 
-		/* This tweak comes straight from Realtek's driver. */
-		if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) &&
-		    ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
-		     (tp->mac_version == RTL_GIGA_MAC_VER_16))) {
-			auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
-		}
-	}
+		giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
+		giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
 
-	/* The 8100e/8101e/8102e do Fast Ethernet only. */
-	if ((tp->mac_version == RTL_GIGA_MAC_VER_07) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_08) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_09) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_10) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
-		if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
-		    netif_msg_link(tp)) {
+		/* The 8100e/8101e/8102e do Fast Ethernet only. */
+		if ((tp->mac_version != RTL_GIGA_MAC_VER_07) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_08) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_09) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_10) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_13) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_14) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_15) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_16)) {
+			giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
+		} else if (netif_msg_link(tp)) {
 			printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",
 			       dev->name);
 		}
-		giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
-	}
 
-	auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+		bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
+
+		if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
+		    (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
+		    (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
+			/*
+			 * Wake up the PHY.
+			 * Vendor specific (0x1f) and reserved (0x0e) MII
+			 * registers.
+			 */
+			mdio_write(ioaddr, 0x1f, 0x0000);
+			mdio_write(ioaddr, 0x0e, 0x0000);
+		}
+
+		mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
+		mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
+	} else {
+		giga_ctrl = 0;
+
+		if (speed == SPEED_10)
+			bmcr = 0;
+		else if (speed == SPEED_100)
+			bmcr = BMCR_SPEED100;
+		else
+			return -EINVAL;
+
+		if (duplex == DUPLEX_FULL)
+			bmcr |= BMCR_FULLDPLX;
 
-	if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
-	    (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
-		/*
-		 * Wake up the PHY.
-		 * Vendor specific (0x1f) and reserved (0x0e) MII registers.
-		 */
 		mdio_write(ioaddr, 0x1f, 0x0000);
-		mdio_write(ioaddr, 0x0e, 0x0000);
 	}
 
-	tp->phy_auto_nego_reg = auto_nego;
 	tp->phy_1000_ctrl_reg = giga_ctrl;
 
-	mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
-	mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
-	mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+	mdio_write(ioaddr, MII_BMCR, bmcr);
+
+	if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
+	    (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
+		if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
+			mdio_write(ioaddr, 0x17, 0x2138);
+			mdio_write(ioaddr, 0x0e, 0x0260);
+		} else {
+			mdio_write(ioaddr, 0x17, 0x2108);
+			mdio_write(ioaddr, 0x0e, 0x0000);
+		}
+	}
+
 	return 0;
 }
 
@@ -1295,7 +1297,8 @@
 		{ 0xfc800000, 0x00800000,	RTL_GIGA_MAC_VER_02 },
 		{ 0xfc800000, 0x00000000,	RTL_GIGA_MAC_VER_01 },
 
-		{ 0x00000000, 0x00000000,	RTL_GIGA_MAC_VER_01 }	/* Catch-all */
+		/* Catch-all */
+		{ 0x00000000, 0x00000000,	RTL_GIGA_MAC_NONE   }
 	}, *p = mac_info;
 	u32 reg;
 
@@ -1303,12 +1306,6 @@
 	while ((reg & p->mask) != p->val)
 		p++;
 	tp->mac_version = p->mac_version;
-
-	if (p->mask == 0x00000000) {
-		struct pci_dev *pdev = tp->pci_dev;
-
-		dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg);
-	}
 }
 
 static void rtl8169_print_mac_version(struct rtl8169_private *tp)
@@ -1884,6 +1881,7 @@
 	u16 intr_event;
 	u16 napi_event;
 	unsigned features;
+	u8 default_ver;
 } rtl_cfg_infos [] = {
 	[RTL_CFG_0] = {
 		.hw_start	= rtl_hw_start_8169,
@@ -1892,7 +1890,8 @@
 		.intr_event	= SYSErr | LinkChg | RxOverflow |
 				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
 		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
-		.features	= RTL_FEATURE_GMII
+		.features	= RTL_FEATURE_GMII,
+		.default_ver	= RTL_GIGA_MAC_VER_01,
 	},
 	[RTL_CFG_1] = {
 		.hw_start	= rtl_hw_start_8168,
@@ -1901,7 +1900,8 @@
 		.intr_event	= SYSErr | LinkChg | RxOverflow |
 				  TxErr | TxOK | RxOK | RxErr,
 		.napi_event	= TxErr | TxOK | RxOK | RxOverflow,
-		.features	= RTL_FEATURE_GMII | RTL_FEATURE_MSI
+		.features	= RTL_FEATURE_GMII | RTL_FEATURE_MSI,
+		.default_ver	= RTL_GIGA_MAC_VER_11,
 	},
 	[RTL_CFG_2] = {
 		.hw_start	= rtl_hw_start_8101,
@@ -1910,7 +1910,8 @@
 		.intr_event	= SYSErr | LinkChg | RxOverflow | PCSTimeout |
 				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
 		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
-		.features	= RTL_FEATURE_MSI
+		.features	= RTL_FEATURE_MSI,
+		.default_ver	= RTL_GIGA_MAC_VER_13,
 	}
 };
 
@@ -2059,8 +2060,6 @@
 		}
 	}
 
-	pci_set_master(pdev);
-
 	/* ioremap MMIO region */
 	ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
 	if (!ioaddr) {
@@ -2088,9 +2087,20 @@
 
 	RTL_W16(IntrStatus, 0xffff);
 
+	pci_set_master(pdev);
+
 	/* Identify chip attached to board */
 	rtl8169_get_mac_version(tp, ioaddr);
 
+	/* Use appropriate default if unknown */
+	if (tp->mac_version == RTL_GIGA_MAC_NONE) {
+		if (netif_msg_probe(tp)) {
+			dev_notice(&pdev->dev,
+				   "unknown MAC, using family default\n");
+		}
+		tp->mac_version = cfg->default_ver;
+	}
+
 	rtl8169_print_mac_version(tp);
 
 	for (i = 0; i < ARRAY_SIZE(rtl_chip_info); i++) {
@@ -2098,13 +2108,9 @@
 			break;
 	}
 	if (i == ARRAY_SIZE(rtl_chip_info)) {
-		/* Unknown chip: assume array element #0, original RTL-8169 */
-		if (netif_msg_probe(tp)) {
-			dev_printk(KERN_DEBUG, &pdev->dev,
-				"unknown chip version, assuming %s\n",
-				rtl_chip_info[0].name);
-		}
-		i = 0;
+		dev_err(&pdev->dev,
+			"driver bug, MAC version not found in rtl_chip_info\n");
+		goto err_out_msi_5;
 	}
 	tp->chipset = i;
 
@@ -3269,8 +3275,6 @@
 	status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
 	txd->opts1 = cpu_to_le32(status);
 
-	dev->trans_start = jiffies;
-
 	tp->cur_tx += frags + 1;
 
 	smp_wmb();
@@ -3371,7 +3375,7 @@
 		rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
 
 		if (status & LastFrag) {
-			dev_kfree_skb_irq(tx_skb->skb);
+			dev_kfree_skb(tx_skb->skb);
 			tx_skb->skb = NULL;
 		}
 		dirty_tx++;
@@ -3802,45 +3806,32 @@
 	return &dev->stats;
 }
 
-#ifdef CONFIG_PM
-
-static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
+static void rtl8169_net_suspend(struct net_device *dev)
 {
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = netdev_priv(dev);
-	void __iomem *ioaddr = tp->mmio_addr;
-
 	if (!netif_running(dev))
-		goto out_pci_suspend;
+		return;
 
 	netif_device_detach(dev);
 	netif_stop_queue(dev);
+}
 
-	spin_lock_irq(&tp->lock);
-
-	rtl8169_asic_down(ioaddr);
-
-	rtl8169_rx_missed(dev, ioaddr);
+#ifdef CONFIG_PM
 
-	spin_unlock_irq(&tp->lock);
+static int rtl8169_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct net_device *dev = pci_get_drvdata(pdev);
 
-out_pci_suspend:
-	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state),
-		(tp->features & RTL_FEATURE_WOL) ? 1 : 0);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	rtl8169_net_suspend(dev);
 
 	return 0;
 }
 
-static int rtl8169_resume(struct pci_dev *pdev)
+static int rtl8169_resume(struct device *device)
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct net_device *dev = pci_get_drvdata(pdev);
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_enable_wake(pdev, PCI_D0, 0);
-
 	if (!netif_running(dev))
 		goto out;
 
@@ -3851,23 +3842,59 @@
 	return 0;
 }
 
+static struct dev_pm_ops rtl8169_pm_ops = {
+	.suspend = rtl8169_suspend,
+	.resume = rtl8169_resume,
+	.freeze = rtl8169_suspend,
+	.thaw = rtl8169_resume,
+	.poweroff = rtl8169_suspend,
+	.restore = rtl8169_resume,
+};
+
+#define RTL8169_PM_OPS	(&rtl8169_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define RTL8169_PM_OPS	NULL
+
+#endif /* !CONFIG_PM */
+
 static void rtl_shutdown(struct pci_dev *pdev)
 {
-	rtl8169_suspend(pdev, PMSG_SUSPEND);
-}
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
 
-#endif /* CONFIG_PM */
+	rtl8169_net_suspend(dev);
+
+	spin_lock_irq(&tp->lock);
+
+	rtl8169_asic_down(ioaddr);
+
+	spin_unlock_irq(&tp->lock);
+
+	if (system_state == SYSTEM_POWER_OFF) {
+		/* WoL fails with some 8168 when the receiver is disabled. */
+		if (tp->features & RTL_FEATURE_WOL) {
+			pci_clear_master(pdev);
+
+			RTL_W8(ChipCmd, CmdRxEnb);
+			/* PCI commit */
+			RTL_R8(ChipCmd);
+		}
+
+		pci_wake_from_d3(pdev, true);
+		pci_set_power_state(pdev, PCI_D3hot);
+	}
+}
 
 static struct pci_driver rtl8169_pci_driver = {
 	.name		= MODULENAME,
 	.id_table	= rtl8169_pci_tbl,
 	.probe		= rtl8169_init_one,
 	.remove		= __devexit_p(rtl8169_remove_one),
-#ifdef CONFIG_PM
-	.suspend	= rtl8169_suspend,
-	.resume		= rtl8169_resume,
 	.shutdown	= rtl_shutdown,
-#endif
+	.driver.pm	= RTL8169_PM_OPS,
 };
 
 static int __init rtl8169_init_module(void)
diff -druN linux-libre-2.6.30-gnu/drivers/net/rionet.c linux-libre-2.6.31-gnu/drivers/net/rionet.c
--- linux-libre-2.6.30-gnu/drivers/net/rionet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/rionet.c	2009-09-09 18:13:59.000000000 -0400
@@ -428,6 +428,15 @@
 	.get_link = ethtool_op_get_link,
 };
 
+static const struct net_device_ops rionet_netdev_ops = {
+	.ndo_open		= rionet_open,
+	.ndo_stop		= rionet_close,
+	.ndo_start_xmit		= rionet_start_xmit,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
 static int rionet_setup_netdev(struct rio_mport *mport)
 {
 	int rc = 0;
@@ -466,10 +475,7 @@
 	ndev->dev_addr[4] = device_id >> 8;
 	ndev->dev_addr[5] = device_id & 0xff;
 
-	/* Fill in the driver function table */
-	ndev->open = &rionet_open;
-	ndev->hard_start_xmit = &rionet_start_xmit;
-	ndev->stop = &rionet_close;
+	ndev->netdev_ops = &rionet_netdev_ops;
 	ndev->mtu = RIO_MAX_MSG_SIZE - 14;
 	ndev->features = NETIF_F_LLTX;
 	SET_ETHTOOL_OPS(ndev, &rionet_ethtool_ops);
diff -druN linux-libre-2.6.30-gnu/drivers/net/rrunner.c linux-libre-2.6.31-gnu/drivers/net/rrunner.c
--- linux-libre-2.6.30-gnu/drivers/net/rrunner.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/rrunner.c	2009-09-09 18:13:59.000000000 -0400
@@ -1425,7 +1425,7 @@
 		if (!(new_skb = dev_alloc_skb(len + 8))) {
 			dev_kfree_skb(skb);
 			netif_wake_queue(dev);
-			return -EBUSY;
+			return NETDEV_TX_OK;
 		}
 		skb_reserve(new_skb, 8);
 		skb_put(new_skb, len);
diff -druN linux-libre-2.6.30-gnu/drivers/net/s2io.c linux-libre-2.6.31-gnu/drivers/net/s2io.c
--- linux-libre-2.6.30-gnu/drivers/net/s2io.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/s2io.c	2009-09-09 18:13:59.000000000 -0400
@@ -63,6 +63,7 @@
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/mdio.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -1763,7 +1764,7 @@
 		 * by then we return error.
 		 */
 		time = 0;
-		while (TRUE) {
+		while (true) {
 			val64 = readq(&bar0->rti_command_mem);
 			if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD))
 				break;
@@ -2136,7 +2137,7 @@
 
 	herc = (sp->device_type == XFRAME_II_DEVICE);
 
-	if (flag == FALSE) {
+	if (flag == false) {
 		if ((!herc && (sp->pdev->revision >= 4)) || herc) {
 			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
 				ret = 1;
@@ -3328,9 +3329,9 @@
 	struct stat_block *stat_info = sp->mac_control.stats_info;
 
 	/* Check the communication with the MDIO slave */
-	addr = 0x0000;
+	addr = MDIO_CTRL1;
 	val64 = 0x0;
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
 	if((val64 == 0xFFFF) || (val64 == 0x0000))
 	{
 		DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - "
@@ -3338,24 +3339,24 @@
 		return;
 	}
 
-	/* Check for the expecte value of 2040 at PMA address 0x0000 */
-	if(val64 != 0x2040)
+	/* Check for the expected value of control reg 1 */
+	if(val64 != MDIO_CTRL1_SPEED10G)
 	{
 		DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - ");
-		DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n",
-			  (unsigned long long)val64);
+		DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x%x\n",
+			  (unsigned long long)val64, MDIO_CTRL1_SPEED10G);
 		return;
 	}
 
 	/* Loading the DOM register to MDIO register */
 	addr = 0xA100;
-	s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev);
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	s2io_mdio_write(MDIO_MMD_PMAPMD, addr, val16, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
 
 	/* Reading the Alarm flags */
 	addr = 0xA070;
 	val64 = 0x0;
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
 
 	flag = CHECKBIT(val64, 0x7);
 	type = 1;
@@ -3387,7 +3388,7 @@
 	/* Reading the Warning flags */
 	addr = 0xA074;
 	val64 = 0x0;
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
 
 	if(CHECKBIT(val64, 0x7))
 		stat_info->xpak_stat.warn_transceiver_temp_high++;
@@ -3586,7 +3587,7 @@
 		writeq(val64, &bar0->pcc_err_reg);
 	}
 
-	sp->device_enabled_once = FALSE;
+	sp->device_enabled_once = false;
 }
 
 /**
@@ -4298,7 +4299,6 @@
 		s2io_stop_tx_queue(sp, fifo->fifo_no);
 	}
 	mac_control->stats_info->sw_stat.mem_allocated += skb->truesize;
-	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
 
 	if (sp->config.intr_type == MSI_X)
@@ -5572,10 +5572,10 @@
 
 	val64 = readq(&bar0->rmac_pause_cfg);
 	if (val64 & RMAC_PAUSE_GEN_ENABLE)
-		ep->tx_pause = TRUE;
+		ep->tx_pause = true;
 	if (val64 & RMAC_PAUSE_RX_ENABLE)
-		ep->rx_pause = TRUE;
-	ep->autoneg = FALSE;
+		ep->rx_pause = true;
+	ep->autoneg = false;
 }
 
 /**
@@ -6806,7 +6806,7 @@
 					val64 |= ADAPTER_LED_ON;
 					writeq(val64, &bar0->adapter_control);
 				}
-				nic->device_enabled_once = TRUE;
+				nic->device_enabled_once = true;
 			} else {
 				DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
 				DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
@@ -7754,7 +7754,7 @@
 	struct s2io_nic *sp;
 	struct net_device *dev;
 	int i, j, ret;
-	int dma_flag = FALSE;
+	int dma_flag = false;
 	u32 mac_up, mac_down;
 	u64 val64 = 0, tmp64 = 0;
 	struct XENA_dev_config __iomem *bar0 = NULL;
@@ -7777,7 +7777,7 @@
 
 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
 		DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n");
-		dma_flag = TRUE;
+		dma_flag = true;
 		if (pci_set_consistent_dma_mask
 		    (pdev, DMA_BIT_MASK(64))) {
 			DBG_PRINT(ERR_DBG,
@@ -7818,7 +7818,7 @@
 	sp->dev = dev;
 	sp->pdev = pdev;
 	sp->high_dma_flag = dma_flag;
-	sp->device_enabled_once = FALSE;
+	sp->device_enabled_once = false;
 	if (rx_ring_mode == 1)
 		sp->rxd_mode = RXD_MODE_1;
 	if (rx_ring_mode == 2)
@@ -7964,7 +7964,7 @@
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 
 	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-	if (sp->high_dma_flag == TRUE)
+	if (sp->high_dma_flag == true)
 		dev->features |= NETIF_F_HIGHDMA;
 	dev->features |= NETIF_F_TSO;
 	dev->features |= NETIF_F_TSO6;
diff -druN linux-libre-2.6.30-gnu/drivers/net/s2io.h linux-libre-2.6.31-gnu/drivers/net/s2io.h
--- linux-libre-2.6.30-gnu/drivers/net/s2io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/s2io.h	2009-09-09 18:13:59.000000000 -0400
@@ -18,15 +18,6 @@
 #define vBIT(val, loc, sz)	(((u64)val) << (64-loc-sz))
 #define INV(d)  ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff)
 
-#ifndef BOOL
-#define BOOL    int
-#endif
-
-#ifndef TRUE
-#define TRUE    1
-#define FALSE   0
-#endif
-
 #undef SUCCESS
 #define SUCCESS 0
 #define FAILURE -1
diff -druN linux-libre-2.6.30-gnu/drivers/net/s2io-regs.h linux-libre-2.6.31-gnu/drivers/net/s2io-regs.h
--- linux-libre-2.6.30-gnu/drivers/net/s2io-regs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/s2io-regs.h	2009-09-09 18:13:59.000000000 -0400
@@ -271,11 +271,6 @@
 	u64 mdio_control;
 #define MDIO_MMD_INDX_ADDR(val)		vBIT(val, 0, 16)
 #define MDIO_MMD_DEV_ADDR(val)		vBIT(val, 19, 5)
-#define MDIO_MMD_PMA_DEV_ADDR		0x1
-#define MDIO_MMD_PMD_DEV_ADDR		0x1
-#define MDIO_MMD_WIS_DEV_ADDR		0x2
-#define MDIO_MMD_PCS_DEV_ADDR		0x3
-#define MDIO_MMD_PHYXS_DEV_ADDR		0x4
 #define MDIO_MMS_PRT_ADDR(val)		vBIT(val, 27, 5)
 #define MDIO_CTRL_START_TRANS(val)	vBIT(val, 56, 4)
 #define MDIO_OP(val)			vBIT(val, 60, 2)
diff -druN linux-libre-2.6.30-gnu/drivers/net/s6gmac.c linux-libre-2.6.31-gnu/drivers/net/s6gmac.c
--- linux-libre-2.6.30-gnu/drivers/net/s6gmac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/s6gmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1073 @@
+/*
+ * Ethernet driver for S6105 on chip network device
+ * (c)2008 emlix GmbH http://www.emlix.com
+ * Authors:	Oskar Schirmer <os@emlix.com>
+ *		Daniel Gloeckner <dg@emlix.com>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if.h>
+#include <linux/stddef.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <variant/hardware.h>
+#include <variant/dmac.h>
+
+#define DRV_NAME "s6gmac"
+#define DRV_PRMT DRV_NAME ": "
+
+
+/* register declarations */
+
+#define S6_GMAC_MACCONF1	0x000
+#define S6_GMAC_MACCONF1_TXENA		0
+#define S6_GMAC_MACCONF1_SYNCTX		1
+#define S6_GMAC_MACCONF1_RXENA		2
+#define S6_GMAC_MACCONF1_SYNCRX		3
+#define S6_GMAC_MACCONF1_TXFLOWCTRL	4
+#define S6_GMAC_MACCONF1_RXFLOWCTRL	5
+#define S6_GMAC_MACCONF1_LOOPBACK	8
+#define S6_GMAC_MACCONF1_RESTXFUNC	16
+#define S6_GMAC_MACCONF1_RESRXFUNC	17
+#define S6_GMAC_MACCONF1_RESTXMACCTRL	18
+#define S6_GMAC_MACCONF1_RESRXMACCTRL	19
+#define S6_GMAC_MACCONF1_SIMULRES	30
+#define S6_GMAC_MACCONF1_SOFTRES	31
+#define S6_GMAC_MACCONF2	0x004
+#define S6_GMAC_MACCONF2_FULL		0
+#define S6_GMAC_MACCONF2_CRCENA		1
+#define S6_GMAC_MACCONF2_PADCRCENA	2
+#define S6_GMAC_MACCONF2_LENGTHFCHK	4
+#define S6_GMAC_MACCONF2_HUGEFRAMENA	5
+#define S6_GMAC_MACCONF2_IFMODE		8
+#define S6_GMAC_MACCONF2_IFMODE_NIBBLE		1
+#define S6_GMAC_MACCONF2_IFMODE_BYTE		2
+#define S6_GMAC_MACCONF2_IFMODE_MASK		3
+#define S6_GMAC_MACCONF2_PREAMBLELEN	12
+#define S6_GMAC_MACCONF2_PREAMBLELEN_MASK	0x0F
+#define S6_GMAC_MACIPGIFG	0x008
+#define S6_GMAC_MACIPGIFG_B2BINTERPGAP	0
+#define S6_GMAC_MACIPGIFG_B2BINTERPGAP_MASK	0x7F
+#define S6_GMAC_MACIPGIFG_MINIFGENFORCE	8
+#define S6_GMAC_MACIPGIFG_B2BINTERPGAP2	16
+#define S6_GMAC_MACIPGIFG_B2BINTERPGAP1	24
+#define S6_GMAC_MACHALFDUPLEX	0x00C
+#define S6_GMAC_MACHALFDUPLEX_COLLISWIN	0
+#define S6_GMAC_MACHALFDUPLEX_COLLISWIN_MASK	0x3F
+#define S6_GMAC_MACHALFDUPLEX_RETXMAX	12
+#define S6_GMAC_MACHALFDUPLEX_RETXMAX_MASK	0x0F
+#define S6_GMAC_MACHALFDUPLEX_EXCESSDEF	16
+#define S6_GMAC_MACHALFDUPLEX_NOBACKOFF	17
+#define S6_GMAC_MACHALFDUPLEX_BPNOBCKOF	18
+#define S6_GMAC_MACHALFDUPLEX_ALTBEBENA	19
+#define S6_GMAC_MACHALFDUPLEX_ALTBEBTRN	20
+#define S6_GMAC_MACHALFDUPLEX_ALTBEBTR_MASK	0x0F
+#define S6_GMAC_MACMAXFRAMELEN	0x010
+#define S6_GMAC_MACMIICONF	0x020
+#define S6_GMAC_MACMIICONF_CSEL		0
+#define S6_GMAC_MACMIICONF_CSEL_DIV10		0
+#define S6_GMAC_MACMIICONF_CSEL_DIV12		1
+#define S6_GMAC_MACMIICONF_CSEL_DIV14		2
+#define S6_GMAC_MACMIICONF_CSEL_DIV18		3
+#define S6_GMAC_MACMIICONF_CSEL_DIV24		4
+#define S6_GMAC_MACMIICONF_CSEL_DIV34		5
+#define S6_GMAC_MACMIICONF_CSEL_DIV68		6
+#define S6_GMAC_MACMIICONF_CSEL_DIV168		7
+#define S6_GMAC_MACMIICONF_CSEL_MASK		7
+#define S6_GMAC_MACMIICONF_PREAMBLESUPR	4
+#define S6_GMAC_MACMIICONF_SCANAUTOINCR	5
+#define S6_GMAC_MACMIICMD	0x024
+#define S6_GMAC_MACMIICMD_READ		0
+#define S6_GMAC_MACMIICMD_SCAN		1
+#define S6_GMAC_MACMIIADDR	0x028
+#define S6_GMAC_MACMIIADDR_REG		0
+#define S6_GMAC_MACMIIADDR_REG_MASK		0x1F
+#define S6_GMAC_MACMIIADDR_PHY		8
+#define S6_GMAC_MACMIIADDR_PHY_MASK		0x1F
+#define S6_GMAC_MACMIICTRL	0x02C
+#define S6_GMAC_MACMIISTAT	0x030
+#define S6_GMAC_MACMIIINDI	0x034
+#define S6_GMAC_MACMIIINDI_BUSY		0
+#define S6_GMAC_MACMIIINDI_SCAN		1
+#define S6_GMAC_MACMIIINDI_INVAL	2
+#define S6_GMAC_MACINTERFSTAT	0x03C
+#define S6_GMAC_MACINTERFSTAT_LINKFAIL	3
+#define S6_GMAC_MACINTERFSTAT_EXCESSDEF	9
+#define S6_GMAC_MACSTATADDR1	0x040
+#define S6_GMAC_MACSTATADDR2	0x044
+
+#define S6_GMAC_FIFOCONF0	0x048
+#define S6_GMAC_FIFOCONF0_HSTRSTWT	0
+#define S6_GMAC_FIFOCONF0_HSTRSTSR	1
+#define S6_GMAC_FIFOCONF0_HSTRSTFR	2
+#define S6_GMAC_FIFOCONF0_HSTRSTST	3
+#define S6_GMAC_FIFOCONF0_HSTRSTFT	4
+#define S6_GMAC_FIFOCONF0_WTMENREQ	8
+#define S6_GMAC_FIFOCONF0_SRFENREQ	9
+#define S6_GMAC_FIFOCONF0_FRFENREQ	10
+#define S6_GMAC_FIFOCONF0_STFENREQ	11
+#define S6_GMAC_FIFOCONF0_FTFENREQ	12
+#define S6_GMAC_FIFOCONF0_WTMENRPLY	16
+#define S6_GMAC_FIFOCONF0_SRFENRPLY	17
+#define S6_GMAC_FIFOCONF0_FRFENRPLY	18
+#define S6_GMAC_FIFOCONF0_STFENRPLY	19
+#define S6_GMAC_FIFOCONF0_FTFENRPLY	20
+#define S6_GMAC_FIFOCONF1	0x04C
+#define S6_GMAC_FIFOCONF2	0x050
+#define S6_GMAC_FIFOCONF2_CFGLWM	0
+#define S6_GMAC_FIFOCONF2_CFGHWM	16
+#define S6_GMAC_FIFOCONF3	0x054
+#define S6_GMAC_FIFOCONF3_CFGFTTH	0
+#define S6_GMAC_FIFOCONF3_CFGHWMFT	16
+#define S6_GMAC_FIFOCONF4	0x058
+#define S6_GMAC_FIFOCONF_RSV_PREVDROP	0
+#define S6_GMAC_FIFOCONF_RSV_RUNT	1
+#define S6_GMAC_FIFOCONF_RSV_FALSECAR	2
+#define S6_GMAC_FIFOCONF_RSV_CODEERR	3
+#define S6_GMAC_FIFOCONF_RSV_CRCERR	4
+#define S6_GMAC_FIFOCONF_RSV_LENGTHERR	5
+#define S6_GMAC_FIFOCONF_RSV_LENRANGE	6
+#define S6_GMAC_FIFOCONF_RSV_OK		7
+#define S6_GMAC_FIFOCONF_RSV_MULTICAST	8
+#define S6_GMAC_FIFOCONF_RSV_BROADCAST	9
+#define S6_GMAC_FIFOCONF_RSV_DRIBBLE	10
+#define S6_GMAC_FIFOCONF_RSV_CTRLFRAME	11
+#define S6_GMAC_FIFOCONF_RSV_PAUSECTRL	12
+#define S6_GMAC_FIFOCONF_RSV_UNOPCODE	13
+#define S6_GMAC_FIFOCONF_RSV_VLANTAG	14
+#define S6_GMAC_FIFOCONF_RSV_LONGEVENT	15
+#define S6_GMAC_FIFOCONF_RSV_TRUNCATED	16
+#define S6_GMAC_FIFOCONF_RSV_MASK		0x3FFFF
+#define S6_GMAC_FIFOCONF5	0x05C
+#define S6_GMAC_FIFOCONF5_DROPLT64	18
+#define S6_GMAC_FIFOCONF5_CFGBYTM	19
+#define S6_GMAC_FIFOCONF5_RXDROPSIZE	20
+#define S6_GMAC_FIFOCONF5_RXDROPSIZE_MASK	0xF
+
+#define S6_GMAC_STAT_REGS	0x080
+#define S6_GMAC_STAT_SIZE_MIN		12
+#define S6_GMAC_STATTR64	0x080
+#define S6_GMAC_STATTR64_SIZE		18
+#define S6_GMAC_STATTR127	0x084
+#define S6_GMAC_STATTR127_SIZE		18
+#define S6_GMAC_STATTR255	0x088
+#define S6_GMAC_STATTR255_SIZE		18
+#define S6_GMAC_STATTR511	0x08C
+#define S6_GMAC_STATTR511_SIZE		18
+#define S6_GMAC_STATTR1K	0x090
+#define S6_GMAC_STATTR1K_SIZE		18
+#define S6_GMAC_STATTRMAX	0x094
+#define S6_GMAC_STATTRMAX_SIZE		18
+#define S6_GMAC_STATTRMGV	0x098
+#define S6_GMAC_STATTRMGV_SIZE		18
+#define S6_GMAC_STATRBYT	0x09C
+#define S6_GMAC_STATRBYT_SIZE		24
+#define S6_GMAC_STATRPKT	0x0A0
+#define S6_GMAC_STATRPKT_SIZE		18
+#define S6_GMAC_STATRFCS	0x0A4
+#define S6_GMAC_STATRFCS_SIZE		12
+#define S6_GMAC_STATRMCA	0x0A8
+#define S6_GMAC_STATRMCA_SIZE		18
+#define S6_GMAC_STATRBCA	0x0AC
+#define S6_GMAC_STATRBCA_SIZE		22
+#define S6_GMAC_STATRXCF	0x0B0
+#define S6_GMAC_STATRXCF_SIZE		18
+#define S6_GMAC_STATRXPF	0x0B4
+#define S6_GMAC_STATRXPF_SIZE		12
+#define S6_GMAC_STATRXUO	0x0B8
+#define S6_GMAC_STATRXUO_SIZE		12
+#define S6_GMAC_STATRALN	0x0BC
+#define S6_GMAC_STATRALN_SIZE		12
+#define S6_GMAC_STATRFLR	0x0C0
+#define S6_GMAC_STATRFLR_SIZE		16
+#define S6_GMAC_STATRCDE	0x0C4
+#define S6_GMAC_STATRCDE_SIZE		12
+#define S6_GMAC_STATRCSE	0x0C8
+#define S6_GMAC_STATRCSE_SIZE		12
+#define S6_GMAC_STATRUND	0x0CC
+#define S6_GMAC_STATRUND_SIZE		12
+#define S6_GMAC_STATROVR	0x0D0
+#define S6_GMAC_STATROVR_SIZE		12
+#define S6_GMAC_STATRFRG	0x0D4
+#define S6_GMAC_STATRFRG_SIZE		12
+#define S6_GMAC_STATRJBR	0x0D8
+#define S6_GMAC_STATRJBR_SIZE		12
+#define S6_GMAC_STATRDRP	0x0DC
+#define S6_GMAC_STATRDRP_SIZE		12
+#define S6_GMAC_STATTBYT	0x0E0
+#define S6_GMAC_STATTBYT_SIZE		24
+#define S6_GMAC_STATTPKT	0x0E4
+#define S6_GMAC_STATTPKT_SIZE		18
+#define S6_GMAC_STATTMCA	0x0E8
+#define S6_GMAC_STATTMCA_SIZE		18
+#define S6_GMAC_STATTBCA	0x0EC
+#define S6_GMAC_STATTBCA_SIZE		18
+#define S6_GMAC_STATTXPF	0x0F0
+#define S6_GMAC_STATTXPF_SIZE		12
+#define S6_GMAC_STATTDFR	0x0F4
+#define S6_GMAC_STATTDFR_SIZE		12
+#define S6_GMAC_STATTEDF	0x0F8
+#define S6_GMAC_STATTEDF_SIZE		12
+#define S6_GMAC_STATTSCL	0x0FC
+#define S6_GMAC_STATTSCL_SIZE		12
+#define S6_GMAC_STATTMCL	0x100
+#define S6_GMAC_STATTMCL_SIZE		12
+#define S6_GMAC_STATTLCL	0x104
+#define S6_GMAC_STATTLCL_SIZE		12
+#define S6_GMAC_STATTXCL	0x108
+#define S6_GMAC_STATTXCL_SIZE		12
+#define S6_GMAC_STATTNCL	0x10C
+#define S6_GMAC_STATTNCL_SIZE		13
+#define S6_GMAC_STATTPFH	0x110
+#define S6_GMAC_STATTPFH_SIZE		12
+#define S6_GMAC_STATTDRP	0x114
+#define S6_GMAC_STATTDRP_SIZE		12
+#define S6_GMAC_STATTJBR	0x118
+#define S6_GMAC_STATTJBR_SIZE		12
+#define S6_GMAC_STATTFCS	0x11C
+#define S6_GMAC_STATTFCS_SIZE		12
+#define S6_GMAC_STATTXCF	0x120
+#define S6_GMAC_STATTXCF_SIZE		12
+#define S6_GMAC_STATTOVR	0x124
+#define S6_GMAC_STATTOVR_SIZE		12
+#define S6_GMAC_STATTUND	0x128
+#define S6_GMAC_STATTUND_SIZE		12
+#define S6_GMAC_STATTFRG	0x12C
+#define S6_GMAC_STATTFRG_SIZE		12
+#define S6_GMAC_STATCARRY(n)	(0x130 + 4*(n))
+#define S6_GMAC_STATCARRYMSK(n)	(0x138 + 4*(n))
+#define S6_GMAC_STATCARRY1_RDRP		0
+#define S6_GMAC_STATCARRY1_RJBR		1
+#define S6_GMAC_STATCARRY1_RFRG		2
+#define S6_GMAC_STATCARRY1_ROVR		3
+#define S6_GMAC_STATCARRY1_RUND		4
+#define S6_GMAC_STATCARRY1_RCSE		5
+#define S6_GMAC_STATCARRY1_RCDE		6
+#define S6_GMAC_STATCARRY1_RFLR		7
+#define S6_GMAC_STATCARRY1_RALN		8
+#define S6_GMAC_STATCARRY1_RXUO		9
+#define S6_GMAC_STATCARRY1_RXPF		10
+#define S6_GMAC_STATCARRY1_RXCF		11
+#define S6_GMAC_STATCARRY1_RBCA		12
+#define S6_GMAC_STATCARRY1_RMCA		13
+#define S6_GMAC_STATCARRY1_RFCS		14
+#define S6_GMAC_STATCARRY1_RPKT		15
+#define S6_GMAC_STATCARRY1_RBYT		16
+#define S6_GMAC_STATCARRY1_TRMGV	25
+#define S6_GMAC_STATCARRY1_TRMAX	26
+#define S6_GMAC_STATCARRY1_TR1K		27
+#define S6_GMAC_STATCARRY1_TR511	28
+#define S6_GMAC_STATCARRY1_TR255	29
+#define S6_GMAC_STATCARRY1_TR127	30
+#define S6_GMAC_STATCARRY1_TR64		31
+#define S6_GMAC_STATCARRY2_TDRP		0
+#define S6_GMAC_STATCARRY2_TPFH		1
+#define S6_GMAC_STATCARRY2_TNCL		2
+#define S6_GMAC_STATCARRY2_TXCL		3
+#define S6_GMAC_STATCARRY2_TLCL		4
+#define S6_GMAC_STATCARRY2_TMCL		5
+#define S6_GMAC_STATCARRY2_TSCL		6
+#define S6_GMAC_STATCARRY2_TEDF		7
+#define S6_GMAC_STATCARRY2_TDFR		8
+#define S6_GMAC_STATCARRY2_TXPF		9
+#define S6_GMAC_STATCARRY2_TBCA		10
+#define S6_GMAC_STATCARRY2_TMCA		11
+#define S6_GMAC_STATCARRY2_TPKT		12
+#define S6_GMAC_STATCARRY2_TBYT		13
+#define S6_GMAC_STATCARRY2_TFRG		14
+#define S6_GMAC_STATCARRY2_TUND		15
+#define S6_GMAC_STATCARRY2_TOVR		16
+#define S6_GMAC_STATCARRY2_TXCF		17
+#define S6_GMAC_STATCARRY2_TFCS		18
+#define S6_GMAC_STATCARRY2_TJBR		19
+
+#define S6_GMAC_HOST_PBLKCTRL	0x140
+#define S6_GMAC_HOST_PBLKCTRL_TXENA	0
+#define S6_GMAC_HOST_PBLKCTRL_RXENA	1
+#define S6_GMAC_HOST_PBLKCTRL_TXSRES	2
+#define S6_GMAC_HOST_PBLKCTRL_RXSRES	3
+#define S6_GMAC_HOST_PBLKCTRL_TXBSIZ	8
+#define S6_GMAC_HOST_PBLKCTRL_RXBSIZ	12
+#define S6_GMAC_HOST_PBLKCTRL_SIZ_16		4
+#define S6_GMAC_HOST_PBLKCTRL_SIZ_32		5
+#define S6_GMAC_HOST_PBLKCTRL_SIZ_64		6
+#define S6_GMAC_HOST_PBLKCTRL_SIZ_128		7
+#define S6_GMAC_HOST_PBLKCTRL_SIZ_MASK		0xF
+#define S6_GMAC_HOST_PBLKCTRL_STATENA	16
+#define S6_GMAC_HOST_PBLKCTRL_STATAUTOZ	17
+#define S6_GMAC_HOST_PBLKCTRL_STATCLEAR	18
+#define S6_GMAC_HOST_PBLKCTRL_RGMII	19
+#define S6_GMAC_HOST_INTMASK	0x144
+#define S6_GMAC_HOST_INTSTAT	0x148
+#define S6_GMAC_HOST_INT_TXBURSTOVER	3
+#define S6_GMAC_HOST_INT_TXPREWOVER	4
+#define S6_GMAC_HOST_INT_RXBURSTUNDER	5
+#define S6_GMAC_HOST_INT_RXPOSTRFULL	6
+#define S6_GMAC_HOST_INT_RXPOSTRUNDER	7
+#define S6_GMAC_HOST_RXFIFOHWM	0x14C
+#define S6_GMAC_HOST_CTRLFRAMXP	0x150
+#define S6_GMAC_HOST_DSTADDRLO(n) (0x160 + 8*(n))
+#define S6_GMAC_HOST_DSTADDRHI(n) (0x164 + 8*(n))
+#define S6_GMAC_HOST_DSTMASKLO(n) (0x180 + 8*(n))
+#define S6_GMAC_HOST_DSTMASKHI(n) (0x184 + 8*(n))
+
+#define S6_GMAC_BURST_PREWR	0x1B0
+#define S6_GMAC_BURST_PREWR_LEN		0
+#define S6_GMAC_BURST_PREWR_LEN_MASK		((1 << 20) - 1)
+#define S6_GMAC_BURST_PREWR_CFE		20
+#define S6_GMAC_BURST_PREWR_PPE		21
+#define S6_GMAC_BURST_PREWR_FCS		22
+#define S6_GMAC_BURST_PREWR_PAD		23
+#define S6_GMAC_BURST_POSTRD	0x1D0
+#define S6_GMAC_BURST_POSTRD_LEN	0
+#define S6_GMAC_BURST_POSTRD_LEN_MASK		((1 << 20) - 1)
+#define S6_GMAC_BURST_POSTRD_DROP	20
+
+
+/* data handling */
+
+#define S6_NUM_TX_SKB	8	/* must be larger than TX fifo size */
+#define S6_NUM_RX_SKB	16
+#define S6_MAX_FRLEN	1536
+
+struct s6gmac {
+	u32 reg;
+	u32 tx_dma;
+	u32 rx_dma;
+	u32 io;
+	u8 tx_chan;
+	u8 rx_chan;
+	spinlock_t lock;
+	u8 tx_skb_i, tx_skb_o;
+	u8 rx_skb_i, rx_skb_o;
+	struct sk_buff *tx_skb[S6_NUM_TX_SKB];
+	struct sk_buff *rx_skb[S6_NUM_RX_SKB];
+	unsigned long carry[sizeof(struct net_device_stats) / sizeof(long)];
+	unsigned long stats[sizeof(struct net_device_stats) / sizeof(long)];
+	struct phy_device *phydev;
+	struct {
+		struct mii_bus *bus;
+		int irq[PHY_MAX_ADDR];
+	} mii;
+	struct {
+		unsigned int mbit;
+		u8 giga;
+		u8 isup;
+		u8 full;
+	} link;
+};
+
+static void s6gmac_rx_fillfifo(struct s6gmac *pd)
+{
+	struct sk_buff *skb;
+	while ((((u8)(pd->rx_skb_i - pd->rx_skb_o)) < S6_NUM_RX_SKB)
+			&& (!s6dmac_fifo_full(pd->rx_dma, pd->rx_chan))
+			&& (skb = dev_alloc_skb(S6_MAX_FRLEN + 2))) {
+		pd->rx_skb[(pd->rx_skb_i++) % S6_NUM_RX_SKB] = skb;
+		s6dmac_put_fifo_cache(pd->rx_dma, pd->rx_chan,
+			pd->io, (u32)skb->data, S6_MAX_FRLEN);
+	}
+}
+
+static void s6gmac_rx_interrupt(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	u32 pfx;
+	struct sk_buff *skb;
+	while (((u8)(pd->rx_skb_i - pd->rx_skb_o)) >
+			s6dmac_pending_count(pd->rx_dma, pd->rx_chan)) {
+		skb = pd->rx_skb[(pd->rx_skb_o++) % S6_NUM_RX_SKB];
+		pfx = readl(pd->reg + S6_GMAC_BURST_POSTRD);
+		if (pfx & (1 << S6_GMAC_BURST_POSTRD_DROP)) {
+			dev_kfree_skb_irq(skb);
+		} else {
+			skb_put(skb, (pfx >> S6_GMAC_BURST_POSTRD_LEN)
+				& S6_GMAC_BURST_POSTRD_LEN_MASK);
+			skb->dev = dev;
+			skb->protocol = eth_type_trans(skb, dev);
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			netif_rx(skb);
+		}
+	}
+}
+
+static void s6gmac_tx_interrupt(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	while (((u8)(pd->tx_skb_i - pd->tx_skb_o)) >
+			s6dmac_pending_count(pd->tx_dma, pd->tx_chan)) {
+		dev_kfree_skb_irq(pd->tx_skb[(pd->tx_skb_o++) % S6_NUM_TX_SKB]);
+	}
+	if (!s6dmac_fifo_full(pd->tx_dma, pd->tx_chan))
+		netif_wake_queue(dev);
+}
+
+struct s6gmac_statinf {
+	unsigned reg_size : 4; /* 0: unused */
+	unsigned reg_off : 6;
+	unsigned net_index : 6;
+};
+
+#define S6_STATS_B (8 * sizeof(u32))
+#define S6_STATS_C(b, r, f) [b] = { \
+	BUILD_BUG_ON_ZERO(r##_SIZE < S6_GMAC_STAT_SIZE_MIN) + \
+	BUILD_BUG_ON_ZERO((r##_SIZE - (S6_GMAC_STAT_SIZE_MIN - 1)) \
+			>= (1<<4)) + \
+	r##_SIZE - (S6_GMAC_STAT_SIZE_MIN - 1), \
+	BUILD_BUG_ON_ZERO(((unsigned)((r - S6_GMAC_STAT_REGS) / sizeof(u32))) \
+			>= ((1<<6)-1)) + \
+	(r - S6_GMAC_STAT_REGS) / sizeof(u32), \
+	BUILD_BUG_ON_ZERO((offsetof(struct net_device_stats, f)) \
+			% sizeof(unsigned long)) + \
+	BUILD_BUG_ON_ZERO((((unsigned)(offsetof(struct net_device_stats, f)) \
+			/ sizeof(unsigned long)) >= (1<<6))) + \
+	BUILD_BUG_ON_ZERO((sizeof(((struct net_device_stats *)0)->f) \
+			!= sizeof(unsigned long))) + \
+	(offsetof(struct net_device_stats, f)) / sizeof(unsigned long)},
+
+static const struct s6gmac_statinf statinf[2][S6_STATS_B] = { {
+	S6_STATS_C(S6_GMAC_STATCARRY1_RBYT, S6_GMAC_STATRBYT, rx_bytes)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RPKT, S6_GMAC_STATRPKT, rx_packets)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RFCS, S6_GMAC_STATRFCS, rx_crc_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RMCA, S6_GMAC_STATRMCA, multicast)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RALN, S6_GMAC_STATRALN, rx_frame_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RFLR, S6_GMAC_STATRFLR, rx_length_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RCDE, S6_GMAC_STATRCDE, rx_missed_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RUND, S6_GMAC_STATRUND, rx_length_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_ROVR, S6_GMAC_STATROVR, rx_length_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RFRG, S6_GMAC_STATRFRG, rx_crc_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RJBR, S6_GMAC_STATRJBR, rx_crc_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY1_RDRP, S6_GMAC_STATRDRP, rx_dropped)
+}, {
+	S6_STATS_C(S6_GMAC_STATCARRY2_TBYT, S6_GMAC_STATTBYT, tx_bytes)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TPKT, S6_GMAC_STATTPKT, tx_packets)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TEDF, S6_GMAC_STATTEDF, tx_aborted_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TXCL, S6_GMAC_STATTXCL, tx_aborted_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TNCL, S6_GMAC_STATTNCL, collisions)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TDRP, S6_GMAC_STATTDRP, tx_dropped)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TJBR, S6_GMAC_STATTJBR, tx_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TFCS, S6_GMAC_STATTFCS, tx_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TOVR, S6_GMAC_STATTOVR, tx_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TUND, S6_GMAC_STATTUND, tx_errors)
+	S6_STATS_C(S6_GMAC_STATCARRY2_TFRG, S6_GMAC_STATTFRG, tx_errors)
+} };
+
+static void s6gmac_stats_collect(struct s6gmac *pd,
+		const struct s6gmac_statinf *inf)
+{
+	int b;
+	for (b = 0; b < S6_STATS_B; b++) {
+		if (inf[b].reg_size) {
+			pd->stats[inf[b].net_index] +=
+				readl(pd->reg + S6_GMAC_STAT_REGS
+					+ sizeof(u32) * inf[b].reg_off);
+		}
+	}
+}
+
+static void s6gmac_stats_carry(struct s6gmac *pd,
+		const struct s6gmac_statinf *inf, u32 mask)
+{
+	int b;
+	while (mask) {
+		b = fls(mask) - 1;
+		mask &= ~(1 << b);
+		pd->carry[inf[b].net_index] += (1 << inf[b].reg_size);
+	}
+}
+
+static inline u32 s6gmac_stats_pending(struct s6gmac *pd, int carry)
+{
+	int r = readl(pd->reg + S6_GMAC_STATCARRY(carry)) &
+		~readl(pd->reg + S6_GMAC_STATCARRYMSK(carry));
+	return r;
+}
+
+static inline void s6gmac_stats_interrupt(struct s6gmac *pd, int carry)
+{
+	u32 mask;
+	mask = s6gmac_stats_pending(pd, carry);
+	if (mask) {
+		writel(mask, pd->reg + S6_GMAC_STATCARRY(carry));
+		s6gmac_stats_carry(pd, &statinf[carry][0], mask);
+	}
+}
+
+static irqreturn_t s6gmac_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct s6gmac *pd = netdev_priv(dev);
+	if (!dev)
+		return IRQ_NONE;
+	spin_lock(&pd->lock);
+	if (s6dmac_termcnt_irq(pd->rx_dma, pd->rx_chan))
+		s6gmac_rx_interrupt(dev);
+	s6gmac_rx_fillfifo(pd);
+	if (s6dmac_termcnt_irq(pd->tx_dma, pd->tx_chan))
+		s6gmac_tx_interrupt(dev);
+	s6gmac_stats_interrupt(pd, 0);
+	s6gmac_stats_interrupt(pd, 1);
+	spin_unlock(&pd->lock);
+	return IRQ_HANDLED;
+}
+
+static inline void s6gmac_set_dstaddr(struct s6gmac *pd, int n,
+	u32 addrlo, u32 addrhi, u32 masklo, u32 maskhi)
+{
+	writel(addrlo, pd->reg + S6_GMAC_HOST_DSTADDRLO(n));
+	writel(addrhi, pd->reg + S6_GMAC_HOST_DSTADDRHI(n));
+	writel(masklo, pd->reg + S6_GMAC_HOST_DSTMASKLO(n));
+	writel(maskhi, pd->reg + S6_GMAC_HOST_DSTMASKHI(n));
+}
+
+static inline void s6gmac_stop_device(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	writel(0, pd->reg + S6_GMAC_MACCONF1);
+}
+
+static inline void s6gmac_init_device(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	int is_rgmii = !!(pd->phydev->supported
+		& (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half));
+#if 0
+	writel(1 << S6_GMAC_MACCONF1_SYNCTX |
+		1 << S6_GMAC_MACCONF1_SYNCRX |
+		1 << S6_GMAC_MACCONF1_TXFLOWCTRL |
+		1 << S6_GMAC_MACCONF1_RXFLOWCTRL |
+		1 << S6_GMAC_MACCONF1_RESTXFUNC |
+		1 << S6_GMAC_MACCONF1_RESRXFUNC |
+		1 << S6_GMAC_MACCONF1_RESTXMACCTRL |
+		1 << S6_GMAC_MACCONF1_RESRXMACCTRL,
+		pd->reg + S6_GMAC_MACCONF1);
+#endif
+	writel(1 << S6_GMAC_MACCONF1_SOFTRES, pd->reg + S6_GMAC_MACCONF1);
+	udelay(1000);
+	writel(1 << S6_GMAC_MACCONF1_TXENA | 1 << S6_GMAC_MACCONF1_RXENA,
+		pd->reg + S6_GMAC_MACCONF1);
+	writel(1 << S6_GMAC_HOST_PBLKCTRL_TXSRES |
+		1 << S6_GMAC_HOST_PBLKCTRL_RXSRES,
+		pd->reg + S6_GMAC_HOST_PBLKCTRL);
+	writel(S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_TXBSIZ |
+		S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_RXBSIZ |
+		1 << S6_GMAC_HOST_PBLKCTRL_STATENA |
+		1 << S6_GMAC_HOST_PBLKCTRL_STATCLEAR |
+		is_rgmii << S6_GMAC_HOST_PBLKCTRL_RGMII,
+		pd->reg + S6_GMAC_HOST_PBLKCTRL);
+	writel(1 << S6_GMAC_MACCONF1_TXENA |
+		1 << S6_GMAC_MACCONF1_RXENA |
+		(dev->flags & IFF_LOOPBACK ? 1 : 0)
+			<< S6_GMAC_MACCONF1_LOOPBACK,
+		pd->reg + S6_GMAC_MACCONF1);
+	writel(dev->mtu && (dev->mtu < (S6_MAX_FRLEN - ETH_HLEN-ETH_FCS_LEN)) ?
+			dev->mtu+ETH_HLEN+ETH_FCS_LEN : S6_MAX_FRLEN,
+		pd->reg + S6_GMAC_MACMAXFRAMELEN);
+	writel((pd->link.full ? 1 : 0) << S6_GMAC_MACCONF2_FULL |
+		1 << S6_GMAC_MACCONF2_PADCRCENA |
+		1 << S6_GMAC_MACCONF2_LENGTHFCHK |
+		(pd->link.giga ?
+			S6_GMAC_MACCONF2_IFMODE_BYTE :
+			S6_GMAC_MACCONF2_IFMODE_NIBBLE)
+			<< S6_GMAC_MACCONF2_IFMODE |
+		7 << S6_GMAC_MACCONF2_PREAMBLELEN,
+		pd->reg + S6_GMAC_MACCONF2);
+	writel(0, pd->reg + S6_GMAC_MACSTATADDR1);
+	writel(0, pd->reg + S6_GMAC_MACSTATADDR2);
+	writel(1 << S6_GMAC_FIFOCONF0_WTMENREQ |
+		1 << S6_GMAC_FIFOCONF0_SRFENREQ |
+		1 << S6_GMAC_FIFOCONF0_FRFENREQ |
+		1 << S6_GMAC_FIFOCONF0_STFENREQ |
+		1 << S6_GMAC_FIFOCONF0_FTFENREQ,
+		pd->reg + S6_GMAC_FIFOCONF0);
+	writel(128 << S6_GMAC_FIFOCONF3_CFGFTTH |
+		128 << S6_GMAC_FIFOCONF3_CFGHWMFT,
+		pd->reg + S6_GMAC_FIFOCONF3);
+	writel((S6_GMAC_FIFOCONF_RSV_MASK & ~(
+			1 << S6_GMAC_FIFOCONF_RSV_RUNT |
+			1 << S6_GMAC_FIFOCONF_RSV_CRCERR |
+			1 << S6_GMAC_FIFOCONF_RSV_OK |
+			1 << S6_GMAC_FIFOCONF_RSV_DRIBBLE |
+			1 << S6_GMAC_FIFOCONF_RSV_CTRLFRAME |
+			1 << S6_GMAC_FIFOCONF_RSV_PAUSECTRL |
+			1 << S6_GMAC_FIFOCONF_RSV_UNOPCODE |
+			1 << S6_GMAC_FIFOCONF_RSV_TRUNCATED)) |
+		1 << S6_GMAC_FIFOCONF5_DROPLT64 |
+		pd->link.giga << S6_GMAC_FIFOCONF5_CFGBYTM |
+		1 << S6_GMAC_FIFOCONF5_RXDROPSIZE,
+		pd->reg + S6_GMAC_FIFOCONF5);
+	writel(1 << S6_GMAC_FIFOCONF_RSV_RUNT |
+		1 << S6_GMAC_FIFOCONF_RSV_CRCERR |
+		1 << S6_GMAC_FIFOCONF_RSV_DRIBBLE |
+		1 << S6_GMAC_FIFOCONF_RSV_CTRLFRAME |
+		1 << S6_GMAC_FIFOCONF_RSV_PAUSECTRL |
+		1 << S6_GMAC_FIFOCONF_RSV_UNOPCODE |
+		1 << S6_GMAC_FIFOCONF_RSV_TRUNCATED,
+		pd->reg + S6_GMAC_FIFOCONF4);
+	s6gmac_set_dstaddr(pd, 0,
+		0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0x0000FFFF);
+	s6gmac_set_dstaddr(pd, 1,
+		dev->dev_addr[5] |
+		dev->dev_addr[4] << 8 |
+		dev->dev_addr[3] << 16 |
+		dev->dev_addr[2] << 24,
+		dev->dev_addr[1] |
+		dev->dev_addr[0] << 8,
+		0xFFFFFFFF, 0x0000FFFF);
+	s6gmac_set_dstaddr(pd, 2,
+		0x00000000, 0x00000100, 0x00000000, 0x00000100);
+	s6gmac_set_dstaddr(pd, 3,
+		0x00000000, 0x00000000, 0x00000000, 0x00000000);
+	writel(1 << S6_GMAC_HOST_PBLKCTRL_TXENA |
+		1 << S6_GMAC_HOST_PBLKCTRL_RXENA |
+		S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_TXBSIZ |
+		S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_RXBSIZ |
+		1 << S6_GMAC_HOST_PBLKCTRL_STATENA |
+		1 << S6_GMAC_HOST_PBLKCTRL_STATCLEAR |
+		is_rgmii << S6_GMAC_HOST_PBLKCTRL_RGMII,
+		pd->reg + S6_GMAC_HOST_PBLKCTRL);
+}
+
+static void s6mii_enable(struct s6gmac *pd)
+{
+	writel(readl(pd->reg + S6_GMAC_MACCONF1) &
+		~(1 << S6_GMAC_MACCONF1_SOFTRES),
+		pd->reg + S6_GMAC_MACCONF1);
+	writel((readl(pd->reg + S6_GMAC_MACMIICONF)
+		& ~(S6_GMAC_MACMIICONF_CSEL_MASK << S6_GMAC_MACMIICONF_CSEL))
+		| (S6_GMAC_MACMIICONF_CSEL_DIV168 << S6_GMAC_MACMIICONF_CSEL),
+		pd->reg + S6_GMAC_MACMIICONF);
+}
+
+static int s6mii_busy(struct s6gmac *pd, int tmo)
+{
+	while (readl(pd->reg + S6_GMAC_MACMIIINDI)) {
+		if (--tmo == 0)
+			return -ETIME;
+		udelay(64);
+	}
+	return 0;
+}
+
+static int s6mii_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+	struct s6gmac *pd = bus->priv;
+	s6mii_enable(pd);
+	if (s6mii_busy(pd, 256))
+		return -ETIME;
+	writel(phy_addr << S6_GMAC_MACMIIADDR_PHY |
+		regnum << S6_GMAC_MACMIIADDR_REG,
+		pd->reg + S6_GMAC_MACMIIADDR);
+	writel(1 << S6_GMAC_MACMIICMD_READ, pd->reg + S6_GMAC_MACMIICMD);
+	writel(0, pd->reg + S6_GMAC_MACMIICMD);
+	if (s6mii_busy(pd, 256))
+		return -ETIME;
+	return (u16)readl(pd->reg + S6_GMAC_MACMIISTAT);
+}
+
+static int s6mii_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value)
+{
+	struct s6gmac *pd = bus->priv;
+	s6mii_enable(pd);
+	if (s6mii_busy(pd, 256))
+		return -ETIME;
+	writel(phy_addr << S6_GMAC_MACMIIADDR_PHY |
+		regnum << S6_GMAC_MACMIIADDR_REG,
+		pd->reg + S6_GMAC_MACMIIADDR);
+	writel(value, pd->reg + S6_GMAC_MACMIICTRL);
+	if (s6mii_busy(pd, 256))
+		return -ETIME;
+	return 0;
+}
+
+static int s6mii_reset(struct mii_bus *bus)
+{
+	struct s6gmac *pd = bus->priv;
+	s6mii_enable(pd);
+	if (s6mii_busy(pd, PHY_INIT_TIMEOUT))
+		return -ETIME;
+	return 0;
+}
+
+static void s6gmac_set_rgmii_txclock(struct s6gmac *pd)
+{
+	u32 pllsel = readl(S6_REG_GREG1 + S6_GREG1_PLLSEL);
+	pllsel &= ~(S6_GREG1_PLLSEL_GMAC_MASK << S6_GREG1_PLLSEL_GMAC);
+	switch (pd->link.mbit) {
+	case 10:
+		pllsel |= S6_GREG1_PLLSEL_GMAC_2500KHZ << S6_GREG1_PLLSEL_GMAC;
+		break;
+	case 100:
+		pllsel |= S6_GREG1_PLLSEL_GMAC_25MHZ << S6_GREG1_PLLSEL_GMAC;
+		break;
+	case 1000:
+		pllsel |= S6_GREG1_PLLSEL_GMAC_125MHZ << S6_GREG1_PLLSEL_GMAC;
+		break;
+	default:
+		return;
+	}
+	writel(pllsel, S6_REG_GREG1 + S6_GREG1_PLLSEL);
+}
+
+static inline void s6gmac_linkisup(struct net_device *dev, int isup)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	struct phy_device *phydev = pd->phydev;
+
+	pd->link.full = phydev->duplex;
+	pd->link.giga = (phydev->speed == 1000);
+	if (pd->link.mbit != phydev->speed) {
+		pd->link.mbit = phydev->speed;
+		s6gmac_set_rgmii_txclock(pd);
+	}
+	pd->link.isup = isup;
+	if (isup)
+		netif_carrier_on(dev);
+	phy_print_status(phydev);
+}
+
+static void s6gmac_adjust_link(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	struct phy_device *phydev = pd->phydev;
+	if (pd->link.isup &&
+			(!phydev->link ||
+			(pd->link.mbit != phydev->speed) ||
+			(pd->link.full != phydev->duplex))) {
+		pd->link.isup = 0;
+		netif_tx_disable(dev);
+		if (!phydev->link) {
+			netif_carrier_off(dev);
+			phy_print_status(phydev);
+		}
+	}
+	if (!pd->link.isup && phydev->link) {
+		if (pd->link.full != phydev->duplex) {
+			u32 maccfg = readl(pd->reg + S6_GMAC_MACCONF2);
+			if (phydev->duplex)
+				maccfg |= 1 << S6_GMAC_MACCONF2_FULL;
+			else
+				maccfg &= ~(1 << S6_GMAC_MACCONF2_FULL);
+			writel(maccfg, pd->reg + S6_GMAC_MACCONF2);
+		}
+
+		if (pd->link.giga != (phydev->speed == 1000)) {
+			u32 fifocfg = readl(pd->reg + S6_GMAC_FIFOCONF5);
+			u32 maccfg = readl(pd->reg + S6_GMAC_MACCONF2);
+			maccfg &= ~(S6_GMAC_MACCONF2_IFMODE_MASK
+				     << S6_GMAC_MACCONF2_IFMODE);
+			if (phydev->speed == 1000) {
+				fifocfg |= 1 << S6_GMAC_FIFOCONF5_CFGBYTM;
+				maccfg |= S6_GMAC_MACCONF2_IFMODE_BYTE
+					   << S6_GMAC_MACCONF2_IFMODE;
+			} else {
+				fifocfg &= ~(1 << S6_GMAC_FIFOCONF5_CFGBYTM);
+				maccfg |= S6_GMAC_MACCONF2_IFMODE_NIBBLE
+					   << S6_GMAC_MACCONF2_IFMODE;
+			}
+			writel(fifocfg, pd->reg + S6_GMAC_FIFOCONF5);
+			writel(maccfg, pd->reg + S6_GMAC_MACCONF2);
+		}
+
+		if (!s6dmac_fifo_full(pd->tx_dma, pd->tx_chan))
+			netif_wake_queue(dev);
+		s6gmac_linkisup(dev, 1);
+	}
+}
+
+static inline int s6gmac_phy_start(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	int i = 0;
+	struct phy_device *p = NULL;
+	while ((i < PHY_MAX_ADDR) && (!(p = pd->mii.bus->phy_map[i])))
+		i++;
+	p = phy_connect(dev, dev_name(&p->dev), &s6gmac_adjust_link, 0,
+			PHY_INTERFACE_MODE_RGMII);
+	if (IS_ERR(p)) {
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(p);
+	}
+	p->supported &= PHY_GBIT_FEATURES;
+	p->advertising = p->supported;
+	pd->phydev = p;
+	return 0;
+}
+
+static inline void s6gmac_init_stats(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	u32 mask;
+	mask =	1 << S6_GMAC_STATCARRY1_RDRP |
+		1 << S6_GMAC_STATCARRY1_RJBR |
+		1 << S6_GMAC_STATCARRY1_RFRG |
+		1 << S6_GMAC_STATCARRY1_ROVR |
+		1 << S6_GMAC_STATCARRY1_RUND |
+		1 << S6_GMAC_STATCARRY1_RCDE |
+		1 << S6_GMAC_STATCARRY1_RFLR |
+		1 << S6_GMAC_STATCARRY1_RALN |
+		1 << S6_GMAC_STATCARRY1_RMCA |
+		1 << S6_GMAC_STATCARRY1_RFCS |
+		1 << S6_GMAC_STATCARRY1_RPKT |
+		1 << S6_GMAC_STATCARRY1_RBYT;
+	writel(mask, pd->reg + S6_GMAC_STATCARRY(0));
+	writel(~mask, pd->reg + S6_GMAC_STATCARRYMSK(0));
+	mask =	1 << S6_GMAC_STATCARRY2_TDRP |
+		1 << S6_GMAC_STATCARRY2_TNCL |
+		1 << S6_GMAC_STATCARRY2_TXCL |
+		1 << S6_GMAC_STATCARRY2_TEDF |
+		1 << S6_GMAC_STATCARRY2_TPKT |
+		1 << S6_GMAC_STATCARRY2_TBYT |
+		1 << S6_GMAC_STATCARRY2_TFRG |
+		1 << S6_GMAC_STATCARRY2_TUND |
+		1 << S6_GMAC_STATCARRY2_TOVR |
+		1 << S6_GMAC_STATCARRY2_TFCS |
+		1 << S6_GMAC_STATCARRY2_TJBR;
+	writel(mask, pd->reg + S6_GMAC_STATCARRY(1));
+	writel(~mask, pd->reg + S6_GMAC_STATCARRYMSK(1));
+}
+
+static inline void s6gmac_init_dmac(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	s6dmac_disable_chan(pd->tx_dma, pd->tx_chan);
+	s6dmac_disable_chan(pd->rx_dma, pd->rx_chan);
+	s6dmac_disable_error_irqs(pd->tx_dma, 1 << S6_HIFDMA_GMACTX);
+	s6dmac_disable_error_irqs(pd->rx_dma, 1 << S6_HIFDMA_GMACRX);
+}
+
+static int s6gmac_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	unsigned long flags;
+	spin_lock_irqsave(&pd->lock, flags);
+	dev->trans_start = jiffies;
+	writel(skb->len << S6_GMAC_BURST_PREWR_LEN |
+		0 << S6_GMAC_BURST_PREWR_CFE |
+		1 << S6_GMAC_BURST_PREWR_PPE |
+		1 << S6_GMAC_BURST_PREWR_FCS |
+		((skb->len < ETH_ZLEN) ? 1 : 0) << S6_GMAC_BURST_PREWR_PAD,
+		pd->reg + S6_GMAC_BURST_PREWR);
+	s6dmac_put_fifo_cache(pd->tx_dma, pd->tx_chan,
+		(u32)skb->data, pd->io, skb->len);
+	if (s6dmac_fifo_full(pd->tx_dma, pd->tx_chan))
+		netif_stop_queue(dev);
+	if (((u8)(pd->tx_skb_i - pd->tx_skb_o)) >= S6_NUM_TX_SKB) {
+		printk(KERN_ERR "GMAC BUG: skb tx ring overflow [%x, %x]\n",
+			pd->tx_skb_o, pd->tx_skb_i);
+		BUG();
+	}
+	pd->tx_skb[(pd->tx_skb_i++) % S6_NUM_TX_SKB] = skb;
+	spin_unlock_irqrestore(&pd->lock, flags);
+	return 0;
+}
+
+static void s6gmac_tx_timeout(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	unsigned long flags;
+	spin_lock_irqsave(&pd->lock, flags);
+	s6gmac_tx_interrupt(dev);
+	spin_unlock_irqrestore(&pd->lock, flags);
+}
+
+static int s6gmac_open(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	unsigned long flags;
+	phy_read_status(pd->phydev);
+	spin_lock_irqsave(&pd->lock, flags);
+	pd->link.mbit = 0;
+	s6gmac_linkisup(dev, pd->phydev->link);
+	s6gmac_init_device(dev);
+	s6gmac_init_stats(dev);
+	s6gmac_init_dmac(dev);
+	s6gmac_rx_fillfifo(pd);
+	s6dmac_enable_chan(pd->rx_dma, pd->rx_chan,
+		2, 1, 0, 1, 0, 0, 0, 7, -1, 2, 0, 1);
+	s6dmac_enable_chan(pd->tx_dma, pd->tx_chan,
+		2, 0, 1, 0, 0, 0, 0, 7, -1, 2, 0, 1);
+	writel(0 << S6_GMAC_HOST_INT_TXBURSTOVER |
+		0 << S6_GMAC_HOST_INT_TXPREWOVER |
+		0 << S6_GMAC_HOST_INT_RXBURSTUNDER |
+		0 << S6_GMAC_HOST_INT_RXPOSTRFULL |
+		0 << S6_GMAC_HOST_INT_RXPOSTRUNDER,
+		pd->reg + S6_GMAC_HOST_INTMASK);
+	spin_unlock_irqrestore(&pd->lock, flags);
+	phy_start(pd->phydev);
+	netif_start_queue(dev);
+	return 0;
+}
+
+static int s6gmac_stop(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	unsigned long flags;
+	netif_stop_queue(dev);
+	phy_stop(pd->phydev);
+	spin_lock_irqsave(&pd->lock, flags);
+	s6gmac_init_dmac(dev);
+	s6gmac_stop_device(dev);
+	while (pd->tx_skb_i != pd->tx_skb_o)
+		dev_kfree_skb(pd->tx_skb[(pd->tx_skb_o++) % S6_NUM_TX_SKB]);
+	while (pd->rx_skb_i != pd->rx_skb_o)
+		dev_kfree_skb(pd->rx_skb[(pd->rx_skb_o++) % S6_NUM_RX_SKB]);
+	spin_unlock_irqrestore(&pd->lock, flags);
+	return 0;
+}
+
+static struct net_device_stats *s6gmac_stats(struct net_device *dev)
+{
+	struct s6gmac *pd = netdev_priv(dev);
+	struct net_device_stats *st = (struct net_device_stats *)&pd->stats;
+	int i;
+	do {
+		unsigned long flags;
+		spin_lock_irqsave(&pd->lock, flags);
+		for (i = 0; i < sizeof(pd->stats) / sizeof(unsigned long); i++)
+			pd->stats[i] =
+				pd->carry[i] << (S6_GMAC_STAT_SIZE_MIN - 1);
+		s6gmac_stats_collect(pd, &statinf[0][0]);
+		s6gmac_stats_collect(pd, &statinf[1][0]);
+		i = s6gmac_stats_pending(pd, 0) |
+			s6gmac_stats_pending(pd, 1);
+		spin_unlock_irqrestore(&pd->lock, flags);
+	} while (i);
+	st->rx_errors = st->rx_crc_errors +
+			st->rx_frame_errors +
+			st->rx_length_errors +
+			st->rx_missed_errors;
+	st->tx_errors += st->tx_aborted_errors;
+	return st;
+}
+
+static int __devinit s6gmac_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct s6gmac *pd;
+	int res;
+	unsigned long i;
+	struct mii_bus *mb;
+	dev = alloc_etherdev(sizeof(*pd));
+	if (!dev) {
+		printk(KERN_ERR DRV_PRMT "etherdev alloc failed, aborting.\n");
+		return -ENOMEM;
+	}
+	dev->open = s6gmac_open;
+	dev->stop = s6gmac_stop;
+	dev->hard_start_xmit = s6gmac_tx;
+	dev->tx_timeout = s6gmac_tx_timeout;
+	dev->watchdog_timeo = HZ;
+	dev->get_stats = s6gmac_stats;
+	dev->irq = platform_get_irq(pdev, 0);
+	pd = netdev_priv(dev);
+	memset(pd, 0, sizeof(*pd));
+	spin_lock_init(&pd->lock);
+	pd->reg = platform_get_resource(pdev, IORESOURCE_MEM, 0)->start;
+	i = platform_get_resource(pdev, IORESOURCE_DMA, 0)->start;
+	pd->tx_dma = DMA_MASK_DMAC(i);
+	pd->tx_chan = DMA_INDEX_CHNL(i);
+	i = platform_get_resource(pdev, IORESOURCE_DMA, 1)->start;
+	pd->rx_dma = DMA_MASK_DMAC(i);
+	pd->rx_chan = DMA_INDEX_CHNL(i);
+	pd->io = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+	res = request_irq(dev->irq, &s6gmac_interrupt, 0, dev->name, dev);
+	if (res) {
+		printk(KERN_ERR DRV_PRMT "irq request failed: %d\n", dev->irq);
+		goto errirq;
+	}
+	res = register_netdev(dev);
+	if (res) {
+		printk(KERN_ERR DRV_PRMT "error registering device %s\n",
+			dev->name);
+		goto errdev;
+	}
+	mb = mdiobus_alloc();
+	if (!mb) {
+		printk(KERN_ERR DRV_PRMT "error allocating mii bus\n");
+		goto errmii;
+	}
+	mb->name = "s6gmac_mii";
+	mb->read = s6mii_read;
+	mb->write = s6mii_write;
+	mb->reset = s6mii_reset;
+	mb->priv = pd;
+	snprintf(mb->id, MII_BUS_ID_SIZE, "0");
+	mb->phy_mask = ~(1 << 0);
+	mb->irq = &pd->mii.irq[0];
+	for (i = 0; i < PHY_MAX_ADDR; i++) {
+		int n = platform_get_irq(pdev, i + 1);
+		if (n < 0)
+			n = PHY_POLL;
+		pd->mii.irq[i] = n;
+	}
+	mdiobus_register(mb);
+	pd->mii.bus = mb;
+	res = s6gmac_phy_start(dev);
+	if (res)
+		return res;
+	platform_set_drvdata(pdev, dev);
+	return 0;
+errmii:
+	unregister_netdev(dev);
+errdev:
+	free_irq(dev->irq, dev);
+errirq:
+	free_netdev(dev);
+	return res;
+}
+
+static int __devexit s6gmac_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	if (dev) {
+		struct s6gmac *pd = netdev_priv(dev);
+		mdiobus_unregister(pd->mii.bus);
+		unregister_netdev(dev);
+		free_irq(dev->irq, dev);
+		free_netdev(dev);
+		platform_set_drvdata(pdev, NULL);
+	}
+	return 0;
+}
+
+static struct platform_driver s6gmac_driver = {
+	.probe = s6gmac_probe,
+	.remove = __devexit_p(s6gmac_remove),
+	.driver = {
+		.name = "s6gmac",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init s6gmac_init(void)
+{
+	printk(KERN_INFO DRV_PRMT "S6 GMAC ethernet driver\n");
+	return platform_driver_register(&s6gmac_driver);
+}
+
+
+static void __exit s6gmac_exit(void)
+{
+	platform_driver_unregister(&s6gmac_driver);
+}
+
+module_init(s6gmac_init);
+module_exit(s6gmac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("S6105 on chip Ethernet driver");
+MODULE_AUTHOR("Oskar Schirmer <os@emlix.com>");
diff -druN linux-libre-2.6.30-gnu/drivers/net/sb1250-mac.c linux-libre-2.6.31-gnu/drivers/net/sb1250-mac.c
--- linux-libre-2.6.30-gnu/drivers/net/sb1250-mac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sb1250-mac.c	2009-09-09 18:13:59.000000000 -0400
@@ -2084,7 +2084,7 @@
 		netif_stop_queue(dev);
 		spin_unlock_irqrestore(&sc->sbm_lock, flags);
 
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	dev->trans_start = jiffies;
@@ -2271,6 +2271,21 @@
 	return 0;
 }
 
+static const struct net_device_ops sbmac_netdev_ops = {
+	.ndo_open		= sbmac_open,
+	.ndo_stop		= sbmac_close,
+	.ndo_start_xmit		= sbmac_start_tx,
+	.ndo_set_multicast_list	= sbmac_set_rx_mode,
+	.ndo_tx_timeout		= sbmac_tx_timeout,
+	.ndo_do_ioctl		= sbmac_mii_ioctl,
+	.ndo_change_mtu		= sb1250_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= sbmac_netpoll,
+#endif
+};
+
 /**********************************************************************
  *  SBMAC_INIT(dev)
  *
@@ -2285,7 +2300,7 @@
 
 static int sbmac_init(struct platform_device *pldev, long long base)
 {
-	struct net_device *dev = pldev->dev.driver_data;
+	struct net_device *dev = dev_get_drvdata(&pldev->dev);
 	int idx = pldev->id;
 	struct sbmac_softc *sc = netdev_priv(dev);
 	unsigned char *eaddr;
@@ -2327,21 +2342,11 @@
 
 	spin_lock_init(&(sc->sbm_lock));
 
-	dev->open               = sbmac_open;
-	dev->hard_start_xmit    = sbmac_start_tx;
-	dev->stop               = sbmac_close;
-	dev->set_multicast_list = sbmac_set_rx_mode;
-	dev->do_ioctl           = sbmac_mii_ioctl;
-	dev->tx_timeout         = sbmac_tx_timeout;
-	dev->watchdog_timeo     = TX_TIMEOUT;
+	dev->netdev_ops = &sbmac_netdev_ops;
+	dev->watchdog_timeo = TX_TIMEOUT;
 
 	netif_napi_add(dev, &sc->napi, sbmac_poll, 16);
 
-	dev->change_mtu         = sb1250_change_mtu;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = sbmac_netpoll;
-#endif
-
 	dev->irq		= UNIT_INT(idx);
 
 	/* This is needed for PASS2 for Rx H/W checksum feature */
@@ -2726,7 +2731,7 @@
 		goto out_unmap;
 	}
 
-	pldev->dev.driver_data = dev;
+	dev_set_drvdata(&pldev->dev, dev);
 	SET_NETDEV_DEV(dev, &pldev->dev);
 
 	sc = netdev_priv(dev);
@@ -2751,7 +2756,7 @@
 
 static int __exit sbmac_remove(struct platform_device *pldev)
 {
-	struct net_device *dev = pldev->dev.driver_data;
+	struct net_device *dev = dev_get_drvdata(&pldev->dev);
 	struct sbmac_softc *sc = netdev_priv(dev);
 
 	unregister_netdev(dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/sc92031.c linux-libre-2.6.31-gnu/drivers/net/sc92031.c
--- linux-libre-2.6.30-gnu/drivers/net/sc92031.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sc92031.c	2009-09-09 18:13:59.000000000 -0400
@@ -1593,6 +1593,7 @@
 static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) },
+	{ PCI_DEVICE(0x1088, 0x2031) },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table);
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/boards.c linux-libre-2.6.31-gnu/drivers/net/sfc/boards.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/boards.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/boards.c	2009-09-09 18:13:59.000000000 -0400
@@ -172,7 +172,6 @@
 static struct i2c_board_info sfe4002_hwmon_info = {
 	I2C_BOARD_INFO("lm87", 0x2e),
 	.platform_data	= &sfe4002_lm87_channel,
-	.irq		= -1,
 };
 
 /****************************************************************************/
@@ -247,7 +246,6 @@
 static struct i2c_board_info sfn4112f_hwmon_info = {
 	I2C_BOARD_INFO("lm87", 0x2e),
 	.platform_data	= &sfn4112f_lm87_channel,
-	.irq		= -1,
 };
 
 #define SFN4112F_ACT_LED	0
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/efx.c linux-libre-2.6.31-gnu/drivers/net/sfc/efx.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/efx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/efx.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,16 +50,6 @@
  *************************************************************************/
 
 /*
- * Enable large receive offload (LRO) aka soft segment reassembly (SSR)
- *
- * This sets the default for new devices.  It can be controlled later
- * using ethtool.
- */
-static int lro = true;
-module_param(lro, int, 0644);
-MODULE_PARM_DESC(lro, "Large receive offload acceleration");
-
-/*
  * Use separate channels for TX and RX events
  *
  * Set this to 1 to use separate channels for TX and RX. It allows us
@@ -894,9 +884,9 @@
 	int count;
 	int cpu;
 
-	if (!alloc_cpumask_var(&core_mask, GFP_KERNEL)) {
+	if (unlikely(!alloc_cpumask_var(&core_mask, GFP_KERNEL))) {
 		printk(KERN_WARNING
-		       "efx.c: allocation failure, irq balancing hobbled\n");
+		       "sfc: RSS disabled due to allocation failure\n");
 		return 1;
 	}
 
@@ -1300,10 +1290,16 @@
 static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
+	struct mii_ioctl_data *data = if_mii(ifr);
 
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
-	return generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL);
+	/* Convert phy_id from older PRTAD/DEVAD format */
+	if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) &&
+	    (data->phy_id & 0xfc00) == 0x0400)
+		data->phy_id ^= MDIO_PHY_ID_C45 | 0x0400;
+
+	return mdio_mii_ioctl(&efx->mdio, data, cmd);
 }
 
 /**************************************************************************
@@ -1945,7 +1941,7 @@
 	mutex_init(&efx->mac_lock);
 	efx->mac_op = &efx_dummy_mac_operations;
 	efx->phy_op = &efx_dummy_phy_operations;
-	efx->mii.dev = net_dev;
+	efx->mdio.dev = net_dev;
 	INIT_WORK(&efx->phy_work, efx_phy_work);
 	INIT_WORK(&efx->mac_work, efx_mac_work);
 	atomic_set(&efx->netif_stop_count, 1);
@@ -2161,9 +2157,8 @@
 	if (!net_dev)
 		return -ENOMEM;
 	net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG |
-			      NETIF_F_HIGHDMA | NETIF_F_TSO);
-	if (lro)
-		net_dev->features |= NETIF_F_GRO;
+			      NETIF_F_HIGHDMA | NETIF_F_TSO |
+			      NETIF_F_GRO);
 	/* Mask for features that also apply to VLAN devices */
 	net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG |
 				   NETIF_F_HIGHDMA | NETIF_F_TSO);
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/ethtool.c linux-libre-2.6.31-gnu/drivers/net/sfc/ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -10,6 +10,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
+#include <linux/mdio.h>
 #include <linux/rtnetlink.h>
 #include "net_driver.h"
 #include "workarounds.h"
@@ -345,8 +346,8 @@
 	unsigned int n = 0, i;
 	enum efx_loopback_mode mode;
 
-	efx_fill_test(n++, strings, data, &tests->mii,
-		      "core", 0, "mii", NULL);
+	efx_fill_test(n++, strings, data, &tests->mdio,
+		      "core", 0, "mdio", NULL);
 	efx_fill_test(n++, strings, data, &tests->nvram,
 		      "core", 0, "nvram", NULL);
 	efx_fill_test(n++, strings, data, &tests->interrupt,
@@ -529,14 +530,7 @@
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 
-	if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) {
-		mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
-				       MDIO_MMDREG_CTRL1,
-				       __ffs(BMCR_ANRESTART), true);
-		return 0;
-	}
-
-	return -EOPNOTSUPP;
+	return mdio45_nway_restart(&efx->mdio);
 }
 
 static u32 efx_ethtool_get_link(struct net_device *net_dev)
@@ -689,7 +683,7 @@
 		return -EINVAL;
 	}
 
-	if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) &&
+	if (!(efx->phy_op->mmds & MDIO_DEVS_AN) &&
 	    (wanted_fc & EFX_FC_AUTO)) {
 		EFX_LOG(efx, "PHY does not support flow control "
 			"autonegotiation\n");
@@ -717,7 +711,8 @@
 	mutex_lock(&efx->mac_lock);
 
 	efx->wanted_fc = wanted_fc;
-	mdio_clause45_set_pause(efx);
+	if (efx->phy_op->mmds & MDIO_DEVS_AN)
+		mdio45_ethtool_spauseparam_an(&efx->mdio, pause);
 	__efx_reconfigure_port(efx);
 
 	mutex_unlock(&efx->mac_lock);
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/falcon.c linux-libre-2.6.31-gnu/drivers/net/sfc/falcon.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/falcon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/falcon.c	2009-09-09 18:13:59.000000000 -0400
@@ -2063,26 +2063,6 @@
  **************************************************************************
  */
 
-/* Use the top bit of the MII PHY id to indicate the PHY type
- * (1G/10G), with the remaining bits as the actual PHY id.
- *
- * This allows us to avoid leaking information from the mii_if_info
- * structure into other data structures.
- */
-#define FALCON_PHY_ID_ID_WIDTH  EFX_WIDTH(MD_PRT_DEV_ADR)
-#define FALCON_PHY_ID_ID_MASK   ((1 << FALCON_PHY_ID_ID_WIDTH) - 1)
-#define FALCON_PHY_ID_WIDTH     (FALCON_PHY_ID_ID_WIDTH + 1)
-#define FALCON_PHY_ID_MASK      ((1 << FALCON_PHY_ID_WIDTH) - 1)
-#define FALCON_PHY_ID_10G       (1 << (FALCON_PHY_ID_WIDTH - 1))
-
-
-/* Packing the clause 45 port and device fields into a single value */
-#define MD_PRT_ADR_COMP_LBN   (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN)
-#define MD_PRT_ADR_COMP_WIDTH  MD_PRT_ADR_WIDTH
-#define MD_DEV_ADR_COMP_LBN    0
-#define MD_DEV_ADR_COMP_WIDTH  MD_DEV_ADR_WIDTH
-
-
 /* Wait for GMII access to complete */
 static int falcon_gmii_wait(struct efx_nic *efx)
 {
@@ -2108,49 +2088,29 @@
 	return -ETIMEDOUT;
 }
 
-/* Writes a GMII register of a PHY connected to Falcon using MDIO. */
-static void falcon_mdio_write(struct net_device *net_dev, int phy_id,
-			      int addr, int value)
+/* Write an MDIO register of a PHY connected to Falcon. */
+static int falcon_mdio_write(struct net_device *net_dev,
+			     int prtad, int devad, u16 addr, u16 value)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK;
 	efx_oword_t reg;
+	int rc;
 
-	/* The 'generic' prt/dev packing in mdio_10g.h is conveniently
-	 * chosen so that the only current user, Falcon, can take the
-	 * packed value and use them directly.
-	 * Fail to build if this assumption is broken.
-	 */
-	BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G);
-	BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH);
-	BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN);
-	BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN);
-
-	if (phy_id2 == PHY_ADDR_INVALID)
-		return;
-
-	/* See falcon_mdio_read for an explanation. */
-	if (!(phy_id & FALCON_PHY_ID_10G)) {
-		int mmd = ffs(efx->phy_op->mmds) - 1;
-		EFX_TRACE(efx, "Fixing erroneous clause22 write\n");
-		phy_id2 = mdio_clause45_pack(phy_id2, mmd)
-			& FALCON_PHY_ID_ID_MASK;
-	}
-
-	EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id,
-		    addr, value);
+	EFX_REGDUMP(efx, "writing MDIO %d register %d.%d with 0x%04x\n",
+		    prtad, devad, addr, value);
 
 	spin_lock_bh(&efx->phy_lock);
 
-	/* Check MII not currently being accessed */
-	if (falcon_gmii_wait(efx) != 0)
+	/* Check MDIO not currently being accessed */
+	rc = falcon_gmii_wait(efx);
+	if (rc)
 		goto out;
 
 	/* Write the address/ID register */
 	EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
 	falcon_write(efx, &reg, MD_PHY_ADR_REG_KER);
 
-	EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2);
+	EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad);
 	falcon_write(efx, &reg, MD_ID_REG_KER);
 
 	/* Write data */
@@ -2163,7 +2123,8 @@
 	falcon_write(efx, &reg, MD_CS_REG_KER);
 
 	/* Wait for data to be written */
-	if (falcon_gmii_wait(efx) != 0) {
+	rc = falcon_gmii_wait(efx);
+	if (rc) {
 		/* Abort the write operation */
 		EFX_POPULATE_OWORD_2(reg,
 				     MD_WRC, 0,
@@ -2174,45 +2135,28 @@
 
  out:
 	spin_unlock_bh(&efx->phy_lock);
+	return rc;
 }
 
-/* Reads a GMII register from a PHY connected to Falcon.  If no value
- * could be read, -1 will be returned. */
-static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr)
+/* Read an MDIO register of a PHY connected to Falcon. */
+static int falcon_mdio_read(struct net_device *net_dev,
+			    int prtad, int devad, u16 addr)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK;
 	efx_oword_t reg;
-	int value = -1;
-
-	if (phy_addr == PHY_ADDR_INVALID)
-		return -1;
-
-	/* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G)
-	 * but the generic Linux code does not make any distinction or have
-	 * any state for this.
-	 * We spot the case where someone tried to talk 22 to a 45 PHY and
-	 * redirect the request to the lowest numbered MMD as a clause45
-	 * request. This is enough to allow simple queries like id and link
-	 * state to succeed. TODO: We may need to do more in future.
-	 */
-	if (!(phy_id & FALCON_PHY_ID_10G)) {
-		int mmd = ffs(efx->phy_op->mmds) - 1;
-		EFX_TRACE(efx, "Fixing erroneous clause22 read\n");
-		phy_addr = mdio_clause45_pack(phy_addr, mmd)
-			& FALCON_PHY_ID_ID_MASK;
-	}
+	int rc;
 
 	spin_lock_bh(&efx->phy_lock);
 
-	/* Check MII not currently being accessed */
-	if (falcon_gmii_wait(efx) != 0)
+	/* Check MDIO not currently being accessed */
+	rc = falcon_gmii_wait(efx);
+	if (rc)
 		goto out;
 
 	EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
 	falcon_write(efx, &reg, MD_PHY_ADR_REG_KER);
 
-	EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr);
+	EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad);
 	falcon_write(efx, &reg, MD_ID_REG_KER);
 
 	/* Request data to be read */
@@ -2220,12 +2164,12 @@
 	falcon_write(efx, &reg, MD_CS_REG_KER);
 
 	/* Wait for data to become available */
-	value = falcon_gmii_wait(efx);
-	if (value == 0) {
+	rc = falcon_gmii_wait(efx);
+	if (rc == 0) {
 		falcon_read(efx, &reg, MD_RXD_REG_KER);
-		value = EFX_OWORD_FIELD(reg, MD_RXD);
-		EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n",
-			    phy_id, addr, value);
+		rc = EFX_OWORD_FIELD(reg, MD_RXD);
+		EFX_REGDUMP(efx, "read from MDIO %d register %d.%d, got %04x\n",
+			    prtad, devad, addr, rc);
 	} else {
 		/* Abort the read operation */
 		EFX_POPULATE_OWORD_2(reg,
@@ -2233,22 +2177,13 @@
 				     MD_GC, 1);
 		falcon_write(efx, &reg, MD_CS_REG_KER);
 
-		EFX_LOG(efx, "read from GMII 0x%x register %02x, got "
-			"error %d\n", phy_id, addr, value);
+		EFX_LOG(efx, "read from MDIO %d register %d.%d, got error %d\n",
+			prtad, devad, addr, rc);
 	}
 
  out:
 	spin_unlock_bh(&efx->phy_lock);
-
-	return value;
-}
-
-static void falcon_init_mdio(struct mii_if_info *gmii)
-{
-	gmii->mdio_read = falcon_mdio_read;
-	gmii->mdio_write = falcon_mdio_write;
-	gmii->phy_id_mask = FALCON_PHY_ID_MASK;
-	gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_PHY_ADR)) - 1);
+	return rc;
 }
 
 static int falcon_probe_phy(struct efx_nic *efx)
@@ -2342,9 +2277,11 @@
 	if (rc)
 		return rc;
 
-	/* Set up GMII structure for PHY */
-	efx->mii.supports_gmii = true;
-	falcon_init_mdio(&efx->mii);
+	/* Set up MDIO structure for PHY */
+	efx->mdio.mmds = efx->phy_op->mmds;
+	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+	efx->mdio.mdio_read = falcon_mdio_read;
+	efx->mdio.mdio_write = falcon_mdio_write;
 
 	/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
 	if (falcon_rev(efx) >= FALCON_REV_B0)
@@ -2761,7 +2698,7 @@
 	if (rc == -EINVAL) {
 		EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n");
 		efx->phy_type = PHY_TYPE_NONE;
-		efx->mii.phy_id = PHY_ADDR_INVALID;
+		efx->mdio.prtad = MDIO_PRTAD_NONE;
 		board_rev = 0;
 		rc = 0;
 	} else if (rc) {
@@ -2771,7 +2708,7 @@
 		struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3;
 
 		efx->phy_type = v2->port0_phy_type;
-		efx->mii.phy_id = v2->port0_phy_addr;
+		efx->mdio.prtad = v2->port0_phy_addr;
 		board_rev = le16_to_cpu(v2->board_revision);
 
 		if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
@@ -2793,7 +2730,7 @@
 	/* Read the MAC addresses */
 	memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
 
-	EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id);
+	EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad);
 
 	efx_set_board_info(efx, board_rev);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/falcon_hwdefs.h linux-libre-2.6.31-gnu/drivers/net/sfc/falcon_hwdefs.h
--- linux-libre-2.6.30-gnu/drivers/net/sfc/falcon_hwdefs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/falcon_hwdefs.h	2009-09-09 18:13:59.000000000 -0400
@@ -456,9 +456,6 @@
 #define MD_PRT_ADR_WIDTH 5
 #define MD_DEV_ADR_LBN 6
 #define MD_DEV_ADR_WIDTH 5
-/* Used for writing both at once */
-#define MD_PRT_DEV_ADR_LBN 6
-#define MD_PRT_DEV_ADR_WIDTH 10
 
 /* PHY management status & mask register (DWORD read only) */
 #define MD_STAT_REG_KER 0xc50
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/falcon_xmac.c linux-libre-2.6.31-gnu/drivers/net/sfc/falcon_xmac.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/falcon_xmac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/falcon_xmac.c	2009-09-09 18:13:59.000000000 -0400
@@ -133,7 +133,7 @@
 	/* If the link is up, then check the phy side of the xaui link */
 	if (efx->link_up && link_ok)
 		if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS))
-			link_ok = mdio_clause45_phyxgxs_lane_sync(efx);
+			link_ok = efx_mdio_phyxgxs_lane_sync(efx);
 
 	return link_ok;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/Kconfig linux-libre-2.6.31-gnu/drivers/net/sfc/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/sfc/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 config SFC
 	tristate "Solarflare Solarstorm SFC4000 support"
 	depends on PCI && INET
-	select MII
+	select MDIO
 	select CRC32
 	select I2C
 	select I2C_ALGOBIT
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/mdio_10g.c linux-libre-2.6.31-gnu/drivers/net/sfc/mdio_10g.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/mdio_10g.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/mdio_10g.c	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 #include "boards.h"
 #include "workarounds.h"
 
-unsigned mdio_id_oui(u32 id)
+unsigned efx_mdio_id_oui(u32 id)
 {
 	unsigned oui = 0;
 	int i;
@@ -32,52 +32,45 @@
 	return oui;
 }
 
-int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd,
+int efx_mdio_reset_mmd(struct efx_nic *port, int mmd,
 			    int spins, int spintime)
 {
 	u32 ctrl;
-	int phy_id = port->mii.phy_id;
 
 	/* Catch callers passing values in the wrong units (or just silly) */
 	EFX_BUG_ON_PARANOID(spins * spintime >= 5000);
 
-	mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1,
-			    (1 << MDIO_MMDREG_CTRL1_RESET_LBN));
+	efx_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET);
 	/* Wait for the reset bit to clear. */
 	do {
 		msleep(spintime);
-		ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1);
+		ctrl = efx_mdio_read(port, mmd, MDIO_CTRL1);
 		spins--;
 
-	} while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)));
+	} while (spins && (ctrl & MDIO_CTRL1_RESET));
 
 	return spins ? spins : -ETIMEDOUT;
 }
 
-static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd,
-				   int fault_fatal)
+static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal)
 {
 	int status;
-	int phy_id = efx->mii.phy_id;
 
 	if (LOOPBACK_INTERNAL(efx))
 		return 0;
 
 	if (mmd != MDIO_MMD_AN) {
 		/* Read MMD STATUS2 to check it is responding. */
-		status = mdio_clause45_read(efx, phy_id, mmd,
-					    MDIO_MMDREG_STAT2);
-		if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
-		     ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) !=
-		    MDIO_MMDREG_STAT2_PRESENT_VAL) {
+		status = efx_mdio_read(efx, mmd, MDIO_STAT2);
+		if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) {
 			EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd);
 			return -EIO;
 		}
 	}
 
 	/* Read MMD STATUS 1 to check for fault. */
-	status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1);
-	if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) {
+	status = efx_mdio_read(efx, mmd, MDIO_STAT1);
+	if (status & MDIO_STAT1_FAULT) {
 		if (fault_fatal) {
 			EFX_ERR(efx, "PHY MMD %d reporting fatal"
 				" fault: status %x\n", mmd, status);
@@ -94,8 +87,7 @@
 #define MDIO45_RESET_TIME	1000 /* ms */
 #define MDIO45_RESET_ITERS	100
 
-int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
-				  unsigned int mmd_mask)
+int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
 {
 	const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS;
 	int tries = MDIO45_RESET_ITERS;
@@ -109,16 +101,13 @@
 		in_reset = 0;
 		while (mask) {
 			if (mask & 1) {
-				stat = mdio_clause45_read(efx,
-							  efx->mii.phy_id,
-							  mmd,
-							  MDIO_MMDREG_CTRL1);
+				stat = efx_mdio_read(efx, mmd, MDIO_CTRL1);
 				if (stat < 0) {
 					EFX_ERR(efx, "failed to read status of"
 						" MMD %d\n", mmd);
 					return -EIO;
 				}
-				if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))
+				if (stat & MDIO_CTRL1_RESET)
 					in_reset |= (1 << mmd);
 			}
 			mask = mask >> 1;
@@ -137,28 +126,26 @@
 	return rc;
 }
 
-int mdio_clause45_check_mmds(struct efx_nic *efx,
-			     unsigned int mmd_mask, unsigned int fatal_mask)
+int efx_mdio_check_mmds(struct efx_nic *efx,
+			unsigned int mmd_mask, unsigned int fatal_mask)
 {
-	int mmd = 0, probe_mmd, devs0, devs1;
+	int mmd = 0, probe_mmd, devs1, devs2;
 	u32 devices;
 
 	/* Historically we have probed the PHYXS to find out what devices are
 	 * present,but that doesn't work so well if the PHYXS isn't expected
 	 * to exist, if so just find the first item in the list supplied. */
-	probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS :
+	probe_mmd = (mmd_mask & MDIO_DEVS_PHYXS) ? MDIO_MMD_PHYXS :
 	    __ffs(mmd_mask);
 
 	/* Check all the expected MMDs are present */
-	devs0 = mdio_clause45_read(efx, efx->mii.phy_id,
-				   probe_mmd, MDIO_MMDREG_DEVS0);
-	devs1 = mdio_clause45_read(efx, efx->mii.phy_id,
-				   probe_mmd, MDIO_MMDREG_DEVS1);
-	if (devs0 < 0 || devs1 < 0) {
+	devs1 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS1);
+	devs2 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS2);
+	if (devs1 < 0 || devs2 < 0) {
 		EFX_ERR(efx, "failed to read devices present\n");
 		return -EIO;
 	}
-	devices = devs0 | (devs1 << 16);
+	devices = devs1 | (devs2 << 16);
 	if ((devices & mmd_mask) != mmd_mask) {
 		EFX_ERR(efx, "required MMDs not present: got %x, "
 			"wanted %x\n", devices, mmd_mask);
@@ -170,7 +157,7 @@
 	while (mmd_mask) {
 		if (mmd_mask & 1) {
 			int fault_fatal = fatal_mask & 1;
-			if (mdio_clause45_check_mmd(efx, mmd, fault_fatal))
+			if (efx_mdio_check_mmd(efx, mmd, fault_fatal))
 				return -EIO;
 		}
 		mmd_mask = mmd_mask >> 1;
@@ -181,13 +168,8 @@
 	return 0;
 }
 
-bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
+bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
 {
-	int phy_id = efx->mii.phy_id;
-	u32 reg;
-	bool ok = true;
-	int mmd = 0;
-
 	/* If the port is in loopback, then we should only consider a subset
 	 * of mmd's */
 	if (LOOPBACK_INTERNAL(efx))
@@ -197,241 +179,75 @@
 	else if (efx_phy_mode_disabled(efx->phy_mode))
 		return false;
 	else if (efx->loopback_mode == LOOPBACK_PHYXS)
-		mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
-			      MDIO_MMDREG_DEVS_PCS |
-			      MDIO_MMDREG_DEVS_PMAPMD |
-			      MDIO_MMDREG_DEVS_AN);
+		mmd_mask &= ~(MDIO_DEVS_PHYXS |
+			      MDIO_DEVS_PCS |
+			      MDIO_DEVS_PMAPMD |
+			      MDIO_DEVS_AN);
 	else if (efx->loopback_mode == LOOPBACK_PCS)
-		mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
-			      MDIO_MMDREG_DEVS_PMAPMD |
-			      MDIO_MMDREG_DEVS_AN);
+		mmd_mask &= ~(MDIO_DEVS_PCS |
+			      MDIO_DEVS_PMAPMD |
+			      MDIO_DEVS_AN);
 	else if (efx->loopback_mode == LOOPBACK_PMAPMD)
-		mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD |
-			      MDIO_MMDREG_DEVS_AN);
-
-	if (!mmd_mask) {
-		/* Use presence of XGMII faults in leui of link state */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
-					 MDIO_PHYXS_STATUS2);
-		return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
-	}
+		mmd_mask &= ~(MDIO_DEVS_PMAPMD |
+			      MDIO_DEVS_AN);
 
-	while (mmd_mask) {
-		if (mmd_mask & 1) {
-			/* Double reads because link state is latched, and a
-			 * read moves the current state into the register */
-			reg = mdio_clause45_read(efx, phy_id,
-						 mmd, MDIO_MMDREG_STAT1);
-			reg = mdio_clause45_read(efx, phy_id,
-						 mmd, MDIO_MMDREG_STAT1);
-			ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
-		}
-		mmd_mask = (mmd_mask >> 1);
-		mmd++;
-	}
-	return ok;
+	return mdio45_links_ok(&efx->mdio, mmd_mask);
 }
 
-void mdio_clause45_transmit_disable(struct efx_nic *efx)
+void efx_mdio_transmit_disable(struct efx_nic *efx)
 {
-	mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-			       MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN,
-			       efx->phy_mode & PHY_MODE_TX_DISABLED);
+	efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
+			  MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL,
+			  efx->phy_mode & PHY_MODE_TX_DISABLED);
 }
 
-void mdio_clause45_phy_reconfigure(struct efx_nic *efx)
+void efx_mdio_phy_reconfigure(struct efx_nic *efx)
 {
-	int phy_id = efx->mii.phy_id;
-
-	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD,
-			       MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN,
-			       efx->loopback_mode == LOOPBACK_PMAPMD);
-	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS,
-			       MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN,
-			       efx->loopback_mode == LOOPBACK_PCS);
-	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS,
-			       MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN,
-			       efx->loopback_mode == LOOPBACK_NETWORK);
+	efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD,
+			  MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK,
+			  efx->loopback_mode == LOOPBACK_PMAPMD);
+	efx_mdio_set_flag(efx, MDIO_MMD_PCS,
+			  MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK,
+			  efx->loopback_mode == LOOPBACK_PCS);
+	efx_mdio_set_flag(efx, MDIO_MMD_PHYXS,
+			  MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK,
+			  efx->loopback_mode == LOOPBACK_NETWORK);
 }
 
-static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx,
-					 int lpower, int mmd)
+static void efx_mdio_set_mmd_lpower(struct efx_nic *efx,
+				    int lpower, int mmd)
 {
-	int phy = efx->mii.phy_id;
-	int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1);
+	int stat = efx_mdio_read(efx, mmd, MDIO_STAT1);
 
 	EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n",
 		  mmd, lpower);
 
-	if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) {
-		mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1,
-				       MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower);
+	if (stat & MDIO_STAT1_LPOWERABLE) {
+		efx_mdio_set_flag(efx, mmd, MDIO_CTRL1,
+				  MDIO_CTRL1_LPOWER, lpower);
 	}
 }
 
-void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
-				   int low_power, unsigned int mmd_mask)
+void efx_mdio_set_mmds_lpower(struct efx_nic *efx,
+			      int low_power, unsigned int mmd_mask)
 {
 	int mmd = 0;
-	mmd_mask &= ~MDIO_MMDREG_DEVS_AN;
+	mmd_mask &= ~MDIO_DEVS_AN;
 	while (mmd_mask) {
 		if (mmd_mask & 1)
-			mdio_clause45_set_mmd_lpower(efx, low_power, mmd);
+			efx_mdio_set_mmd_lpower(efx, low_power, mmd);
 		mmd_mask = (mmd_mask >> 1);
 		mmd++;
 	}
 }
 
-static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr)
-{
-	int phy_id = efx->mii.phy_id;
-	u32 result = 0;
-	int reg;
-
-	reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr);
-	if (reg & ADVERTISE_10HALF)
-		result |= ADVERTISED_10baseT_Half;
-	if (reg & ADVERTISE_10FULL)
-		result |= ADVERTISED_10baseT_Full;
-	if (reg & ADVERTISE_100HALF)
-		result |= ADVERTISED_100baseT_Half;
-	if (reg & ADVERTISE_100FULL)
-		result |= ADVERTISED_100baseT_Full;
-	return result;
-}
-
-/**
- * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
- * @efx:		Efx NIC
- * @ecmd: 		Buffer for settings
- *
- * On return the 'port', 'speed', 'supported' and 'advertising' fields of
- * ecmd have been filled out.
- */
-void mdio_clause45_get_settings(struct efx_nic *efx,
-				struct ethtool_cmd *ecmd)
-{
-	mdio_clause45_get_settings_ext(efx, ecmd, 0, 0);
-}
-
 /**
- * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO.
- * @efx:		Efx NIC
- * @ecmd: 		Buffer for settings
- * @xnp:		Advertised Extended Next Page state
- * @xnp_lpa:		Link Partner's advertised XNP state
- *
- * On return the 'port', 'speed', 'supported' and 'advertising' fields of
- * ecmd have been filled out.
- */
-void mdio_clause45_get_settings_ext(struct efx_nic *efx,
-				    struct ethtool_cmd *ecmd,
-				    u32 npage_adv, u32 npage_lpa)
-{
-	int phy_id = efx->mii.phy_id;
-	int reg;
-
-	ecmd->transceiver = XCVR_INTERNAL;
-	ecmd->phy_address = phy_id;
-
-	reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-				 MDIO_MMDREG_CTRL2);
-	switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) {
-	case MDIO_PMAPMD_CTRL2_10G_BT:
-	case MDIO_PMAPMD_CTRL2_1G_BT:
-	case MDIO_PMAPMD_CTRL2_100_BT:
-	case MDIO_PMAPMD_CTRL2_10_BT:
-		ecmd->port = PORT_TP;
-		ecmd->supported = SUPPORTED_TP;
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-					 MDIO_MMDREG_SPEED);
-		if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN))
-			ecmd->supported |= SUPPORTED_10000baseT_Full;
-		if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN))
-			ecmd->supported |= (SUPPORTED_1000baseT_Full |
-					    SUPPORTED_1000baseT_Half);
-		if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN))
-			ecmd->supported |= (SUPPORTED_100baseT_Full |
-					    SUPPORTED_100baseT_Half);
-		if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN))
-			ecmd->supported |= (SUPPORTED_10baseT_Full |
-					    SUPPORTED_10baseT_Half);
-		ecmd->advertising = ADVERTISED_TP;
-		break;
-
-	/* We represent CX4 as fibre in the absence of anything better */
-	case MDIO_PMAPMD_CTRL2_10G_CX4:
-	/* All the other defined modes are flavours of optical */
-	default:
-		ecmd->port = PORT_FIBRE;
-		ecmd->supported = SUPPORTED_FIBRE;
-		ecmd->advertising = ADVERTISED_FIBRE;
-		break;
-	}
-
-	if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) {
-		ecmd->supported |= SUPPORTED_Autoneg;
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-					 MDIO_MMDREG_CTRL1);
-		if (reg & BMCR_ANENABLE) {
-			ecmd->autoneg = AUTONEG_ENABLE;
-			ecmd->advertising |=
-				ADVERTISED_Autoneg |
-				mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) |
-				npage_adv;
-		} else
-			ecmd->autoneg = AUTONEG_DISABLE;
-	} else
-		ecmd->autoneg = AUTONEG_DISABLE;
-
-	if (ecmd->autoneg) {
-		/* If AN is complete, report best common mode,
-		 * otherwise report best advertised mode. */
-		u32 modes = 0;
-		if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-				       MDIO_MMDREG_STAT1) &
-		    (1 << MDIO_AN_STATUS_AN_DONE_LBN))
-			modes = (ecmd->advertising &
-				 (mdio_clause45_get_an(efx, MDIO_AN_LPA) |
-				  npage_lpa));
-		if (modes == 0)
-			modes = ecmd->advertising;
-
-		if (modes & ADVERTISED_10000baseT_Full) {
-			ecmd->speed = SPEED_10000;
-			ecmd->duplex = DUPLEX_FULL;
-		} else if (modes & (ADVERTISED_1000baseT_Full |
-				    ADVERTISED_1000baseT_Half)) {
-			ecmd->speed = SPEED_1000;
-			ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full);
-		} else if (modes & (ADVERTISED_100baseT_Full |
-				    ADVERTISED_100baseT_Half)) {
-			ecmd->speed = SPEED_100;
-			ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
-		} else {
-			ecmd->speed = SPEED_10;
-			ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
-		}
-	} else {
-		/* Report forced settings */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-					 MDIO_MMDREG_CTRL1);
-		ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) *
-			       ((reg & BMCR_SPEED100) ? 100 : 10));
-		ecmd->duplex = (reg & BMCR_FULLDPLX ||
-				ecmd->speed == SPEED_10000);
-	}
-}
-
-/**
- * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO.
+ * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO.
  * @efx:		Efx NIC
  * @ecmd: 		New settings
  */
-int mdio_clause45_set_settings(struct efx_nic *efx,
-			       struct ethtool_cmd *ecmd)
+int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
-	int phy_id = efx->mii.phy_id;
 	struct ethtool_cmd prev;
 	u32 required;
 	int reg;
@@ -488,95 +304,48 @@
 		else if (ecmd->advertising & (ADVERTISED_1000baseT_Half |
 					      ADVERTISED_1000baseT_Full))
 			reg |= ADVERTISE_NPAGE;
-		reg |= efx_fc_advertise(efx->wanted_fc);
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
-				    MDIO_AN_ADVERTISE, reg);
+		reg |= mii_advertise_flowctrl(efx->wanted_fc);
+		efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
 
 		/* Set up the (extended) next page if necessary */
 		if (efx->phy_op->set_npage_adv)
 			efx->phy_op->set_npage_adv(efx, ecmd->advertising);
 
 		/* Enable and restart AN */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-					 MDIO_MMDREG_CTRL1);
-		reg |= BMCR_ANENABLE;
+		reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
+		reg |= MDIO_AN_CTRL1_ENABLE;
 		if (!(EFX_WORKAROUND_15195(efx) &&
 		      LOOPBACK_MASK(efx) & efx->phy_op->loopbacks))
-			reg |= BMCR_ANRESTART;
+			reg |= MDIO_AN_CTRL1_RESTART;
 		if (xnp)
-			reg |= 1 << MDIO_AN_CTRL_XNP_LBN;
+			reg |= MDIO_AN_CTRL1_XNP;
 		else
-			reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN);
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
-				    MDIO_MMDREG_CTRL1, reg);
+			reg &= ~MDIO_AN_CTRL1_XNP;
+		efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
 	} else {
 		/* Disable AN */
-		mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
-				       MDIO_MMDREG_CTRL1,
-				       __ffs(BMCR_ANENABLE), false);
+		efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_CTRL1,
+				  MDIO_AN_CTRL1_ENABLE, false);
 
 		/* Set the basic control bits */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-					 MDIO_MMDREG_CTRL1);
-		reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX |
-			 0x003c);
+		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1);
+		reg &= ~(MDIO_CTRL1_SPEEDSEL | MDIO_CTRL1_FULLDPLX);
 		if (ecmd->speed == SPEED_100)
-			reg |= BMCR_SPEED100;
+			reg |= MDIO_PMA_CTRL1_SPEED100;
 		if (ecmd->duplex)
-			reg |= BMCR_FULLDPLX;
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-				    MDIO_MMDREG_CTRL1, reg);
+			reg |= MDIO_CTRL1_FULLDPLX;
+		efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, reg);
 	}
 
 	return 0;
 }
 
-void mdio_clause45_set_pause(struct efx_nic *efx)
-{
-	int phy_id = efx->mii.phy_id;
-	int reg;
-
-	if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) {
-		/* Set pause capability advertising */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-					 MDIO_AN_ADVERTISE);
-		reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
-		reg |= efx_fc_advertise(efx->wanted_fc);
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
-				    MDIO_AN_ADVERTISE, reg);
-
-		/* Restart auto-negotiation */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-					 MDIO_MMDREG_CTRL1);
-		if (reg & BMCR_ANENABLE) {
-			reg |= BMCR_ANRESTART;
-			mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
-					    MDIO_MMDREG_CTRL1, reg);
-		}
-	}
-}
-
-enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx)
+enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx)
 {
-	int phy_id = efx->mii.phy_id;
 	int lpa;
 
-	if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)))
+	if (!(efx->phy_op->mmds & MDIO_DEVS_AN))
 		return efx->wanted_fc;
-	lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA);
+	lpa = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA);
 	return efx_fc_resolve(efx->wanted_fc, lpa);
 }
-
-void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev,
-			    u16 addr, int bit, bool sense)
-{
-	int old_val = mdio_clause45_read(efx, prt, dev, addr);
-	int new_val;
-
-	if (sense)
-		new_val = old_val | (1 << bit);
-	else
-		new_val = old_val & ~(1 << bit);
-	if (old_val != new_val)
-		mdio_clause45_write(efx, prt, dev, addr, new_val);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/mdio_10g.h linux-libre-2.6.31-gnu/drivers/net/sfc/mdio_10g.h
--- linux-libre-2.6.30-gnu/drivers/net/sfc/mdio_10g.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/mdio_10g.h	2009-09-09 18:13:59.000000000 -0400
@@ -10,247 +10,53 @@
 #ifndef EFX_MDIO_10G_H
 #define EFX_MDIO_10G_H
 
+#include <linux/mdio.h>
+
 /*
- * Definitions needed for doing 10G MDIO as specified in clause 45
- * MDIO, which do not appear in Linux yet. Also some helper functions.
+ * Helper functions for doing 10G MDIO as specified in IEEE 802.3 clause 45.
  */
 
 #include "efx.h"
 #include "boards.h"
 
-/* Numbering of the MDIO Manageable Devices (MMDs) */
-/* Physical Medium Attachment/ Physical Medium Dependent sublayer */
-#define MDIO_MMD_PMAPMD	(1)
-/* WAN Interface Sublayer */
-#define MDIO_MMD_WIS	(2)
-/* Physical Coding Sublayer */
-#define MDIO_MMD_PCS	(3)
-/* PHY Extender Sublayer */
-#define MDIO_MMD_PHYXS	(4)
-/* Extender Sublayer */
-#define MDIO_MMD_DTEXS	(5)
-/* Transmission convergence */
-#define MDIO_MMD_TC	(6)
-/* Auto negotiation */
-#define MDIO_MMD_AN	(7)
-/* Clause 22 extension */
-#define MDIO_MMD_C22EXT	29
-
-/* Generic register locations */
-#define MDIO_MMDREG_CTRL1	(0)
-#define MDIO_MMDREG_STAT1	(1)
-#define MDIO_MMDREG_IDHI	(2)
-#define MDIO_MMDREG_IDLOW	(3)
-#define MDIO_MMDREG_SPEED	(4)
-#define MDIO_MMDREG_DEVS0	(5)
-#define MDIO_MMDREG_DEVS1	(6)
-#define MDIO_MMDREG_CTRL2	(7)
-#define MDIO_MMDREG_STAT2	(8)
-#define MDIO_MMDREG_TXDIS	(9)
-
-/* Bits in MMDREG_CTRL1 */
-/* Reset */
-#define MDIO_MMDREG_CTRL1_RESET_LBN	(15)
-#define MDIO_MMDREG_CTRL1_RESET_WIDTH	(1)
-/* Loopback */
-/* Loopback bit for WIS, PCS, PHYSX and DTEXS */
-#define MDIO_MMDREG_CTRL1_LBACK_LBN	(14)
-#define MDIO_MMDREG_CTRL1_LBACK_WIDTH	(1)
-/* Low power */
-#define MDIO_MMDREG_CTRL1_LPOWER_LBN	(11)
-#define MDIO_MMDREG_CTRL1_LPOWER_WIDTH	(1)
-
-/* Bits in MMDREG_STAT1 */
-#define MDIO_MMDREG_STAT1_FAULT_LBN	(7)
-#define MDIO_MMDREG_STAT1_FAULT_WIDTH	(1)
-/* Link state */
-#define MDIO_MMDREG_STAT1_LINK_LBN	(2)
-#define MDIO_MMDREG_STAT1_LINK_WIDTH	(1)
-/* Low power ability */
-#define MDIO_MMDREG_STAT1_LPABLE_LBN	(1)
-#define MDIO_MMDREG_STAT1_LPABLE_WIDTH	(1)
-
-/* Bits in combined ID regs */
-static inline unsigned mdio_id_rev(u32 id) { return id & 0xf; }
-static inline unsigned mdio_id_model(u32 id) { return (id >> 4) & 0x3f; }
-extern unsigned mdio_id_oui(u32 id);
-
-/* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out
- * so the 'bit present' bit number of an MMD is the number of
- * that MMD */
-#define DEV_PRESENT_BIT(_b) (1 << _b)
-
-#define MDIO_MMDREG_DEVS_PHYXS	DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
-#define MDIO_MMDREG_DEVS_PCS	DEV_PRESENT_BIT(MDIO_MMD_PCS)
-#define MDIO_MMDREG_DEVS_PMAPMD	DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
-#define MDIO_MMDREG_DEVS_AN	DEV_PRESENT_BIT(MDIO_MMD_AN)
-#define MDIO_MMDREG_DEVS_C22EXT	DEV_PRESENT_BIT(MDIO_MMD_C22EXT)
-
-/* Bits in MMDREG_SPEED */
-#define MDIO_MMDREG_SPEED_10G_LBN	0
-#define MDIO_MMDREG_SPEED_10G_WIDTH	1
-#define MDIO_MMDREG_SPEED_1000M_LBN	4
-#define MDIO_MMDREG_SPEED_1000M_WIDTH	1
-#define MDIO_MMDREG_SPEED_100M_LBN	5
-#define MDIO_MMDREG_SPEED_100M_WIDTH	1
-#define MDIO_MMDREG_SPEED_10M_LBN	6
-#define MDIO_MMDREG_SPEED_10M_WIDTH	1
-
-/* Bits in MMDREG_STAT2 */
-#define MDIO_MMDREG_STAT2_PRESENT_VAL	(2)
-#define MDIO_MMDREG_STAT2_PRESENT_LBN	(14)
-#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2)
-
-/* Bits in MMDREG_TXDIS */
-#define MDIO_MMDREG_TXDIS_GLOBAL_LBN    (0)
-#define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH  (1)
-
-/* MMD-specific bits, ordered by MMD, then register */
-#define MDIO_PMAPMD_CTRL1_LBACK_LBN	(0)
-#define MDIO_PMAPMD_CTRL1_LBACK_WIDTH	(1)
-
-/* PMA type (4 bits) */
-#define MDIO_PMAPMD_CTRL2_10G_CX4	(0x0)
-#define MDIO_PMAPMD_CTRL2_10G_EW	(0x1)
-#define MDIO_PMAPMD_CTRL2_10G_LW	(0x2)
-#define MDIO_PMAPMD_CTRL2_10G_SW	(0x3)
-#define MDIO_PMAPMD_CTRL2_10G_LX4	(0x4)
-#define MDIO_PMAPMD_CTRL2_10G_ER	(0x5)
-#define MDIO_PMAPMD_CTRL2_10G_LR	(0x6)
-#define MDIO_PMAPMD_CTRL2_10G_SR	(0x7)
-/* Reserved */
-#define MDIO_PMAPMD_CTRL2_10G_BT	(0x9)
-/* Reserved */
-/* Reserved */
-#define MDIO_PMAPMD_CTRL2_1G_BT		(0xc)
-/* Reserved */
-#define MDIO_PMAPMD_CTRL2_100_BT	(0xe)
-#define MDIO_PMAPMD_CTRL2_10_BT		(0xf)
-#define MDIO_PMAPMD_CTRL2_TYPE_MASK	(0xf)
-
-/* PMA 10GBT registers */
-#define MDIO_PMAPMD_10GBT_TXPWR		(131)
-#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0)
-#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1)
-
-/* PHY XGXS Status 2 */
-#define MDIO_PHYXS_STATUS2              (8)
-#define MDIO_PHYXS_STATUS2_RX_FAULT_LBN 10
-
-/* PHY XGXS lane state */
-#define MDIO_PHYXS_LANE_STATE		(0x18)
-#define MDIO_PHYXS_LANE_ALIGNED_LBN	(12)
-
-/* AN registers */
-#define MDIO_AN_CTRL_XNP_LBN		13
-#define MDIO_AN_STATUS			(1)
-#define MDIO_AN_STATUS_XNP_LBN		(7)
-#define MDIO_AN_STATUS_PAGE_LBN		(6)
-#define MDIO_AN_STATUS_AN_DONE_LBN	(5)
-#define MDIO_AN_STATUS_LP_AN_CAP_LBN	(0)
-
-#define MDIO_AN_ADVERTISE		16
-#define MDIO_AN_ADVERTISE_XNP_LBN	12
-#define MDIO_AN_LPA			19
-#define MDIO_AN_XNP			22
-#define MDIO_AN_LPA_XNP			25
-
-#define MDIO_AN_10GBT_CTRL		32
-#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN	12
-#define MDIO_AN_10GBT_STATUS		(33)
-#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
-#define MDIO_AN_10GBT_STATUS_MS_LBN     (14) /* MASTER/SLAVE config */
-#define MDIO_AN_10GBT_STATUS_LOC_OK_LBN (13) /* Local OK */
-#define MDIO_AN_10GBT_STATUS_REM_OK_LBN (12) /* Remote OK */
-#define MDIO_AN_10GBT_STATUS_LP_10G_LBN (11) /* Link partner is 10GBT capable */
-#define MDIO_AN_10GBT_STATUS_LP_LTA_LBN (10) /* LP loop timing ability */
-#define MDIO_AN_10GBT_STATUS_LP_TRR_LBN (9)  /* LP Training Reset Request */
-
-
-/* Packing of the prt and dev arguments of clause 45 style MDIO into a
- * single int so they can be passed into the mdio_read/write functions
- * that currently exist. Note that as Falcon is the only current user,
- * the packed form is chosen to match what Falcon needs to write into
- * a register. This is checked at compile-time so do not change it. If
- * your target chip needs things layed out differently you will need
- * to unpack the arguments in your chip-specific mdio functions.
- */
- /* These are defined by the standard. */
-#define MDIO45_PRT_ID_WIDTH  (5)
-#define MDIO45_DEV_ID_WIDTH  (5)
-
-/* The prt ID is just packed in immediately to the left of the dev ID */
-#define MDIO45_PRT_DEV_WIDTH (MDIO45_PRT_ID_WIDTH + MDIO45_DEV_ID_WIDTH)
-
-#define MDIO45_PRT_ID_MASK   ((1 << MDIO45_PRT_DEV_WIDTH) - 1)
-/* This is the prt + dev extended by 1 bit to hold the 'is clause 45' flag. */
-#define MDIO45_XPRT_ID_WIDTH   (MDIO45_PRT_DEV_WIDTH + 1)
-#define MDIO45_XPRT_ID_MASK   ((1 << MDIO45_XPRT_ID_WIDTH) - 1)
-#define MDIO45_XPRT_ID_IS10G   (1 << (MDIO45_XPRT_ID_WIDTH - 1))
-
-
-#define MDIO45_PRT_ID_COMP_LBN   MDIO45_DEV_ID_WIDTH
-#define MDIO45_PRT_ID_COMP_WIDTH  MDIO45_PRT_ID_WIDTH
-#define MDIO45_DEV_ID_COMP_LBN    0
-#define MDIO45_DEV_ID_COMP_WIDTH  MDIO45_DEV_ID_WIDTH
-
-/* Compose port and device into a phy_id */
-static inline int mdio_clause45_pack(u8 prt, u8 dev)
-{
-	efx_dword_t phy_id;
-	EFX_POPULATE_DWORD_2(phy_id, MDIO45_PRT_ID_COMP, prt,
-			     MDIO45_DEV_ID_COMP, dev);
-	return MDIO45_XPRT_ID_IS10G | EFX_DWORD_VAL(phy_id);
-}
-
-static inline void mdio_clause45_unpack(u32 val, u8 *prt, u8 *dev)
-{
-	efx_dword_t phy_id;
-	EFX_POPULATE_DWORD_1(phy_id, EFX_DWORD_0, val);
-	*prt = EFX_DWORD_FIELD(phy_id, MDIO45_PRT_ID_COMP);
-	*dev = EFX_DWORD_FIELD(phy_id, MDIO45_DEV_ID_COMP);
-}
+static inline unsigned efx_mdio_id_rev(u32 id) { return id & 0xf; }
+static inline unsigned efx_mdio_id_model(u32 id) { return (id >> 4) & 0x3f; }
+extern unsigned efx_mdio_id_oui(u32 id);
 
-static inline int mdio_clause45_read(struct efx_nic *efx,
-				     u8 prt, u8 dev, u16 addr)
+static inline int efx_mdio_read(struct efx_nic *efx, int devad, int addr)
 {
-	return efx->mii.mdio_read(efx->net_dev,
-				  mdio_clause45_pack(prt, dev), addr);
+	return efx->mdio.mdio_read(efx->net_dev, efx->mdio.prtad, devad, addr);
 }
 
-static inline void mdio_clause45_write(struct efx_nic *efx,
-				       u8 prt, u8 dev, u16 addr, int value)
+static inline void
+efx_mdio_write(struct efx_nic *efx, int devad, int addr, int value)
 {
-	efx->mii.mdio_write(efx->net_dev,
-			    mdio_clause45_pack(prt, dev), addr, value);
+	efx->mdio.mdio_write(efx->net_dev, efx->mdio.prtad, devad, addr, value);
 }
 
-
-static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd)
+static inline u32 efx_mdio_read_id(struct efx_nic *efx, int mmd)
 {
-	int phy_id = efx->mii.phy_id;
-	u16 id_low = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDLOW);
-	u16 id_hi = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDHI);
+	u16 id_low = efx_mdio_read(efx, mmd, MDIO_DEVID2);
+	u16 id_hi = efx_mdio_read(efx, mmd, MDIO_DEVID1);
 	return (id_hi << 16) | (id_low);
 }
 
-static inline bool mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx)
+static inline bool efx_mdio_phyxgxs_lane_sync(struct efx_nic *efx)
 {
 	int i, lane_status;
 	bool sync;
 
 	for (i = 0; i < 2; ++i)
-		lane_status = mdio_clause45_read(efx, efx->mii.phy_id,
-						 MDIO_MMD_PHYXS,
-						 MDIO_PHYXS_LANE_STATE);
+		lane_status = efx_mdio_read(efx, MDIO_MMD_PHYXS,
+					    MDIO_PHYXS_LNSTAT);
 
-	sync = !!(lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN));
+	sync = !!(lane_status & MDIO_PHYXS_LNSTAT_ALIGN);
 	if (!sync)
 		EFX_LOG(efx, "XGXS lane status: %x\n", lane_status);
 	return sync;
 }
 
-extern const char *mdio_clause45_mmd_name(int mmd);
+extern const char *efx_mdio_mmd_name(int mmd);
 
 /*
  * Reset a specific MMD and wait for reset to clear.
@@ -258,54 +64,44 @@
  *
  * This function will sleep
  */
-extern int mdio_clause45_reset_mmd(struct efx_nic *efx, int mmd,
-				   int spins, int spintime);
+extern int efx_mdio_reset_mmd(struct efx_nic *efx, int mmd,
+			      int spins, int spintime);
 
-/* As mdio_clause45_check_mmd but for multiple MMDs */
-int mdio_clause45_check_mmds(struct efx_nic *efx,
-			     unsigned int mmd_mask, unsigned int fatal_mask);
+/* As efx_mdio_check_mmd but for multiple MMDs */
+int efx_mdio_check_mmds(struct efx_nic *efx,
+			unsigned int mmd_mask, unsigned int fatal_mask);
 
 /* Check the link status of specified mmds in bit mask */
-extern bool mdio_clause45_links_ok(struct efx_nic *efx,
-				   unsigned int mmd_mask);
+extern bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask);
 
 /* Generic transmit disable support though PMAPMD */
-extern void mdio_clause45_transmit_disable(struct efx_nic *efx);
+extern void efx_mdio_transmit_disable(struct efx_nic *efx);
 
 /* Generic part of reconfigure: set/clear loopback bits */
-extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx);
+extern void efx_mdio_phy_reconfigure(struct efx_nic *efx);
 
 /* Set the power state of the specified MMDs */
-extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
-					  int low_power, unsigned int mmd_mask);
-
-/* Read (some of) the PHY settings over MDIO */
-extern void mdio_clause45_get_settings(struct efx_nic *efx,
-				       struct ethtool_cmd *ecmd);
-
-/* Read (some of) the PHY settings over MDIO */
-extern void
-mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd,
-			       u32 xnp, u32 xnp_lpa);
+extern void efx_mdio_set_mmds_lpower(struct efx_nic *efx,
+				     int low_power, unsigned int mmd_mask);
 
 /* Set (some of) the PHY settings over MDIO */
-extern int mdio_clause45_set_settings(struct efx_nic *efx,
-				      struct ethtool_cmd *ecmd);
-
-/* Set pause parameters to be advertised through AN (if available) */
-extern void mdio_clause45_set_pause(struct efx_nic *efx);
+extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
 
 /* Get pause parameters from AN if available (otherwise return
  * requested pause parameters)
  */
-enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx);
+enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx);
 
 /* Wait for specified MMDs to exit reset within a timeout */
-extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
-					 unsigned int mmd_mask);
+extern int efx_mdio_wait_reset_mmds(struct efx_nic *efx,
+				    unsigned int mmd_mask);
 
 /* Set or clear flag, debouncing */
-extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev,
-				   u16 addr, int bit, bool sense);
+static inline void
+efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr,
+		  int mask, bool state)
+{
+	mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state);
+}
 
 #endif /* EFX_MDIO_10G_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/net_driver.h linux-libre-2.6.31-gnu/drivers/net/sfc/net_driver.h
--- linux-libre-2.6.30-gnu/drivers/net/sfc/net_driver.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/net_driver.h	2009-09-09 18:13:59.000000000 -0400
@@ -19,7 +19,7 @@
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/timer.h>
-#include <linux/mii.h>
+#include <linux/mdio.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/device.h>
@@ -458,8 +458,6 @@
 	PHY_TYPE_MAX	/* Insert any new items before this */
 };
 
-#define PHY_ADDR_INVALID 0xff
-
 #define EFX_IS10G(efx) ((efx)->link_speed == 10000)
 
 enum nic_state {
@@ -497,8 +495,8 @@
 
 /* Pseudo bit-mask flow control field */
 enum efx_fc_type {
-	EFX_FC_RX = 1,
-	EFX_FC_TX = 2,
+	EFX_FC_RX = FLOW_CTRL_RX,
+	EFX_FC_TX = FLOW_CTRL_TX,
 	EFX_FC_AUTO = 4,
 };
 
@@ -508,33 +506,15 @@
 	EFX_XMAC = 2,
 };
 
-static inline unsigned int efx_fc_advertise(enum efx_fc_type wanted_fc)
-{
-	unsigned int adv = 0;
-	if (wanted_fc & EFX_FC_RX)
-		adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-	if (wanted_fc & EFX_FC_TX)
-		adv ^= ADVERTISE_PAUSE_ASYM;
-	return adv;
-}
-
 static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc,
 					      unsigned int lpa)
 {
-	unsigned int adv = efx_fc_advertise(wanted_fc);
+	BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX));
 
 	if (!(wanted_fc & EFX_FC_AUTO))
 		return wanted_fc;
 
-	if (adv & lpa & ADVERTISE_PAUSE_CAP)
-		return EFX_FC_RX | EFX_FC_TX;
-	if (adv & lpa & ADVERTISE_PAUSE_ASYM) {
-		if (adv & ADVERTISE_PAUSE_CAP)
-			return EFX_FC_RX;
-		if (lpa & ADVERTISE_PAUSE_CAP)
-			return EFX_FC_TX;
-	}
-	return 0;
+	return mii_resolve_flowctrl_fdx(mii_advertise_flowctrl(wanted_fc), lpa);
 }
 
 /**
@@ -758,7 +738,7 @@
  * @phy_lock: PHY access lock
  * @phy_op: PHY interface
  * @phy_data: PHY private data (including PHY-specific stats)
- * @mii: PHY interface
+ * @mdio: PHY MDIO interface
  * @phy_mode: PHY operating mode. Serialised by @mac_lock.
  * @mac_up: MAC link state
  * @link_up: Link status
@@ -845,7 +825,7 @@
 	struct work_struct phy_work;
 	struct efx_phy_operations *phy_op;
 	void *phy_data;
-	struct mii_if_info mii;
+	struct mdio_if_info mdio;
 	enum efx_phy_mode phy_mode;
 
 	bool mac_up;
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/rx.c linux-libre-2.6.31-gnu/drivers/net/sfc/rx.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/rx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/rx.c	2009-09-09 18:13:59.000000000 -0400
@@ -450,17 +450,27 @@
 
 	/* Pass the skb/page into the LRO engine */
 	if (rx_buf->page) {
-		struct napi_gro_fraginfo info;
+		struct sk_buff *skb = napi_get_frags(napi);
 
-		info.frags[0].page = rx_buf->page;
-		info.frags[0].page_offset = efx_rx_buf_offset(rx_buf);
-		info.frags[0].size = rx_buf->len;
-		info.nr_frags = 1;
-		info.ip_summed = CHECKSUM_UNNECESSARY;
-		info.len = rx_buf->len;
+		if (!skb) {
+			put_page(rx_buf->page);
+			goto out;
+		}
 
-		napi_gro_frags(napi, &info);
+		skb_shinfo(skb)->frags[0].page = rx_buf->page;
+		skb_shinfo(skb)->frags[0].page_offset =
+			efx_rx_buf_offset(rx_buf);
+		skb_shinfo(skb)->frags[0].size = rx_buf->len;
+		skb_shinfo(skb)->nr_frags = 1;
 
+		skb->len = rx_buf->len;
+		skb->data_len = rx_buf->len;
+		skb->truesize += rx_buf->len;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		napi_gro_frags(napi);
+
+out:
 		EFX_BUG_ON_PARANOID(rx_buf->skb);
 		rx_buf->page = NULL;
 	} else {
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/selftest.c linux-libre-2.6.31-gnu/drivers/net/sfc/selftest.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/selftest.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/selftest.c	2009-09-09 18:13:59.000000000 -0400
@@ -80,39 +80,38 @@
  *
  **************************************************************************/
 
-static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests)
+static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests)
 {
 	int rc = 0;
+	int devad = __ffs(efx->mdio.mmds);
 	u16 physid1, physid2;
-	struct mii_if_info *mii = &efx->mii;
-	struct net_device *net_dev = efx->net_dev;
 
 	if (efx->phy_type == PHY_TYPE_NONE)
 		return 0;
 
 	mutex_lock(&efx->mac_lock);
-	tests->mii = -1;
+	tests->mdio = -1;
 
-	physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1);
-	physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2);
+	physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1);
+	physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2);
 
 	if ((physid1 == 0x0000) || (physid1 == 0xffff) ||
 	    (physid2 == 0x0000) || (physid2 == 0xffff)) {
-		EFX_ERR(efx, "no MII PHY present with ID %d\n",
-			mii->phy_id);
+		EFX_ERR(efx, "no MDIO PHY present with ID %d\n",
+			efx->mdio.prtad);
 		rc = -EINVAL;
 		goto out;
 	}
 
 	if (EFX_IS10G(efx)) {
-		rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0);
+		rc = efx_mdio_check_mmds(efx, efx->phy_op->mmds, 0);
 		if (rc)
 			goto out;
 	}
 
 out:
 	mutex_unlock(&efx->mac_lock);
-	tests->mii = rc ? -1 : 1;
+	tests->mdio = rc ? -1 : 1;
 	return rc;
 }
 
@@ -439,6 +438,7 @@
 			kfree_skb(skb);
 			return -EPIPE;
 		}
+		efx->net_dev->trans_start = jiffies;
 	}
 
 	return 0;
@@ -673,7 +673,7 @@
 	/* Online (i.e. non-disruptive) testing
 	 * This checks interrupt generation, event delivery and PHY presence. */
 
-	rc = efx_test_mii(efx, tests);
+	rc = efx_test_mdio(efx, tests);
 	if (rc && !rc_test)
 		rc_test = rc;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/selftest.h linux-libre-2.6.31-gnu/drivers/net/sfc/selftest.h
--- linux-libre-2.6.30-gnu/drivers/net/sfc/selftest.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/selftest.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,7 +32,7 @@
  */
 struct efx_self_tests {
 	/* online tests */
-	int mii;
+	int mdio;
 	int nvram;
 	int interrupt;
 	int eventq_dma[EFX_MAX_CHANNELS];
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/sfe4001.c linux-libre-2.6.31-gnu/drivers/net/sfc/sfe4001.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/sfe4001.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/sfe4001.c	2009-09-09 18:13:59.000000000 -0400
@@ -296,7 +296,6 @@
 
 static struct i2c_board_info sfe4001_hwmon_info = {
 	I2C_BOARD_INFO("max6647", 0x4e),
-	.irq		= -1,
 };
 
 /* This board uses an I2C expander to provider power to the PHY, which needs to
@@ -389,12 +388,10 @@
 
 static struct i2c_board_info sfn4111t_a0_hwmon_info = {
 	I2C_BOARD_INFO("max6647", 0x4e),
-	.irq		= -1,
 };
 
 static struct i2c_board_info sfn4111t_r5_hwmon_info = {
 	I2C_BOARD_INFO("max6646", 0x4d),
-	.irq		= -1,
 };
 
 int sfn4111t_init(struct efx_nic *efx)
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/tenxpress.c linux-libre-2.6.31-gnu/drivers/net/sfc/tenxpress.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/tenxpress.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/tenxpress.c	2009-09-09 18:13:59.000000000 -0400
@@ -23,10 +23,10 @@
  * clause 22 extension MMD, but since it doesn't have all the generic
  * MMD registers it is pointless to include it here.
  */
-#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PMAPMD	| \
-				 MDIO_MMDREG_DEVS_PCS		| \
-				 MDIO_MMDREG_DEVS_PHYXS		| \
-				 MDIO_MMDREG_DEVS_AN)
+#define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD	| \
+				 MDIO_DEVS_PCS		| \
+				 MDIO_DEVS_PHYXS	| \
+				 MDIO_DEVS_AN)
 
 #define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) |	\
 			   (1 << LOOPBACK_PCS) |	\
@@ -44,18 +44,6 @@
  */
 #define MAX_BAD_LP_TRIES	(5)
 
-/* LASI Control */
-#define PMA_PMD_LASI_CTRL	36866
-#define PMA_PMD_LASI_STATUS	36869
-#define PMA_PMD_LS_ALARM_LBN	0
-#define PMA_PMD_LS_ALARM_WIDTH	1
-#define PMA_PMD_TX_ALARM_LBN	1
-#define PMA_PMD_TX_ALARM_WIDTH	1
-#define PMA_PMD_RX_ALARM_LBN	2
-#define PMA_PMD_RX_ALARM_WIDTH	1
-#define PMA_PMD_AN_ALARM_LBN	3
-#define PMA_PMD_AN_ALARM_WIDTH	1
-
 /* Extended control register */
 #define PMA_PMD_XCONTROL_REG	49152
 #define PMA_PMD_EXT_GMII_EN_LBN	1
@@ -75,6 +63,7 @@
 
 /* extended status register */
 #define PMA_PMD_XSTATUS_REG	49153
+#define PMA_PMD_XSTAT_MDIX_LBN	14
 #define PMA_PMD_XSTAT_FLP_LBN   (12)
 
 /* LED control register */
@@ -153,10 +142,6 @@
 #define LOOPBACK_NEAR_LBN   (8)
 #define LOOPBACK_NEAR_WIDTH (1)
 
-#define PCS_10GBASET_STAT1       32
-#define PCS_10GBASET_BLKLK_LBN   0
-#define PCS_10GBASET_BLKLK_WIDTH 1
-
 /* Boot status register */
 #define PCS_BOOT_STATUS_REG		53248
 #define PCS_BOOT_FATAL_ERROR_LBN	0
@@ -206,10 +191,8 @@
 	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
 	int reg;
 
-	reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-				 MDIO_PMAPMD_10GBT_TXPWR);
-	return sprintf(buf, "%d\n",
-		       !!(reg & (1 << MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN)));
+	reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR);
+	return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT));
 }
 
 static ssize_t set_phy_short_reach(struct device *dev,
@@ -219,10 +202,9 @@
 	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
 
 	rtnl_lock();
-	mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-			       MDIO_PMAPMD_10GBT_TXPWR,
-			       MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN,
-			       count != 0 && *buf != '0');
+	efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
+			  MDIO_PMA_10GBT_TXPWR_SHORT,
+			  count != 0 && *buf != '0');
 	efx_reconfigure_port(efx);
 	rtnl_unlock();
 
@@ -238,9 +220,8 @@
 	int boot_stat;
 
 	for (;;) {
-		boot_stat = mdio_clause45_read(efx, efx->mii.phy_id,
-					       MDIO_MMD_PCS,
-					       PCS_BOOT_STATUS_REG);
+		boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS,
+					  PCS_BOOT_STATUS_REG);
 		if (boot_stat >= 0) {
 			EFX_LOG(efx, "PHY boot status = %#x\n", boot_stat);
 			switch (boot_stat &
@@ -286,38 +267,32 @@
 
 static int tenxpress_init(struct efx_nic *efx)
 {
-	int phy_id = efx->mii.phy_id;
 	int reg;
 
 	if (efx->phy_type == PHY_TYPE_SFX7101) {
 		/* Enable 312.5 MHz clock */
-		mdio_clause45_write(efx, phy_id,
-				    MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
-				    1 << CLK312_EN_LBN);
+		efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
+			       1 << CLK312_EN_LBN);
 	} else {
 		/* Enable 312.5 MHz clock and GMII */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-					 PMA_PMD_XCONTROL_REG);
+		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
 		reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
 			(1 << PMA_PMD_EXT_CLK_OUT_LBN) |
 			(1 << PMA_PMD_EXT_CLK312_LBN) |
 			(1 << PMA_PMD_EXT_ROBUST_LBN));
 
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-				    PMA_PMD_XCONTROL_REG, reg);
-		mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
-				       GPHY_XCONTROL_REG, GPHY_ISOLATE_LBN,
-				       false);
+		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
+		efx_mdio_set_flag(efx, MDIO_MMD_C22EXT,
+			      GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN,
+			      false);
 	}
 
 	/* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
 	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD,
-				       PMA_PMD_LED_CTRL_REG,
-				       PMA_PMA_LED_ACTIVITY_LBN,
-				       true);
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-				    PMA_PMD_LED_OVERR_REG, PMA_PMD_LED_DEFAULT);
+		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
+				  1 << PMA_PMA_LED_ACTIVITY_LBN, true);
+		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
+			       PMA_PMD_LED_DEFAULT);
 	}
 
 	return 0;
@@ -337,22 +312,19 @@
 	if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
 		if (efx->phy_type == PHY_TYPE_SFT9001A) {
 			int reg;
-			reg = mdio_clause45_read(efx, efx->mii.phy_id,
-						 MDIO_MMD_PMAPMD,
-						 PMA_PMD_XCONTROL_REG);
+			reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
+					    PMA_PMD_XCONTROL_REG);
 			reg |= (1 << PMA_PMD_EXT_SSR_LBN);
-			mdio_clause45_write(efx, efx->mii.phy_id,
-					    MDIO_MMD_PMAPMD,
-					    PMA_PMD_XCONTROL_REG, reg);
+			efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+				       PMA_PMD_XCONTROL_REG, reg);
 			mdelay(200);
 		}
 
-		rc = mdio_clause45_wait_reset_mmds(efx,
-						   TENXPRESS_REQUIRED_DEVS);
+		rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
 		if (rc < 0)
 			goto fail;
 
-		rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
+		rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
 		if (rc < 0)
 			goto fail;
 	}
@@ -360,7 +332,6 @@
 	rc = tenxpress_init(efx);
 	if (rc < 0)
 		goto fail;
-	mdio_clause45_set_pause(efx);
 
 	if (efx->phy_type == PHY_TYPE_SFT9001B) {
 		rc = device_create_file(&efx->pci_dev->dev,
@@ -395,17 +366,14 @@
 	efx_stats_disable(efx);
 
 	/* Initiate reset */
-	reg = mdio_clause45_read(efx, efx->mii.phy_id,
-				 MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
+	reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
 	reg |= (1 << PMA_PMD_EXT_SSR_LBN);
-	mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-			    PMA_PMD_XCONTROL_REG, reg);
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
 
 	mdelay(200);
 
 	/* Wait for the blocks to come out of reset */
-	rc = mdio_clause45_wait_reset_mmds(efx,
-					   TENXPRESS_REQUIRED_DEVS);
+	rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
 	if (rc < 0)
 		goto out;
 
@@ -424,7 +392,6 @@
 static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
 {
 	struct tenxpress_phy_data *pd = efx->phy_data;
-	int phy_id = efx->mii.phy_id;
 	bool bad_lp;
 	int reg;
 
@@ -432,11 +399,10 @@
 		bad_lp = false;
 	} else {
 		/* Check that AN has started but not completed. */
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-					 MDIO_AN_STATUS);
-		if (!(reg & (1 << MDIO_AN_STATUS_LP_AN_CAP_LBN)))
+		reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1);
+		if (!(reg & MDIO_AN_STAT1_LPABLE))
 			return; /* LP status is unknown */
-		bad_lp = !(reg & (1 << MDIO_AN_STATUS_AN_DONE_LBN));
+		bad_lp = !(reg & MDIO_AN_STAT1_COMPLETE);
 		if (bad_lp)
 			pd->bad_lp_tries++;
 	}
@@ -448,8 +414,8 @@
 	/* Use the RX (red) LED as an error indicator once we've seen AN
 	 * failure several times in a row, and also log a message. */
 	if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-					 PMA_PMD_LED_OVERR_REG);
+		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
+				    PMA_PMD_LED_OVERR_REG);
 		reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN);
 		if (!bad_lp) {
 			reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN;
@@ -460,23 +426,22 @@
 				" supports 10GBASE-T ONLY, so no link can"
 				" be established\n");
 		}
-		mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-				    PMA_PMD_LED_OVERR_REG, reg);
+		efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+			       PMA_PMD_LED_OVERR_REG, reg);
 		pd->bad_lp_tries = bad_lp;
 	}
 }
 
 static bool sfx7101_link_ok(struct efx_nic *efx)
 {
-	return mdio_clause45_links_ok(efx,
-				      MDIO_MMDREG_DEVS_PMAPMD |
-				      MDIO_MMDREG_DEVS_PCS |
-				      MDIO_MMDREG_DEVS_PHYXS);
+	return efx_mdio_links_ok(efx,
+				 MDIO_DEVS_PMAPMD |
+				 MDIO_DEVS_PCS |
+				 MDIO_DEVS_PHYXS);
 }
 
 static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
-	int phy_id = efx->mii.phy_id;
 	u32 reg;
 
 	if (efx_phy_mode_disabled(efx->phy_mode))
@@ -484,50 +449,43 @@
 	else if (efx->loopback_mode == LOOPBACK_GPHY)
 		return true;
 	else if (efx->loopback_mode)
-		return mdio_clause45_links_ok(efx,
-					      MDIO_MMDREG_DEVS_PMAPMD |
-					      MDIO_MMDREG_DEVS_PHYXS);
+		return efx_mdio_links_ok(efx,
+					 MDIO_DEVS_PMAPMD |
+					 MDIO_DEVS_PHYXS);
 
 	/* We must use the same definition of link state as LASI,
 	 * otherwise we can miss a link state transition
 	 */
 	if (ecmd->speed == 10000) {
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
-					 PCS_10GBASET_STAT1);
-		return reg & (1 << PCS_10GBASET_BLKLK_LBN);
+		reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
+		return reg & MDIO_PCS_10GBRT_STAT1_BLKLK;
 	} else {
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
-					 C22EXT_STATUS_REG);
+		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG);
 		return reg & (1 << C22EXT_STATUS_LINK_LBN);
 	}
 }
 
 static void tenxpress_ext_loopback(struct efx_nic *efx)
 {
-	int phy_id = efx->mii.phy_id;
-
-	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS,
-			       PHYXS_TEST1, LOOPBACK_NEAR_LBN,
-			       efx->loopback_mode == LOOPBACK_PHYXS);
+	efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1,
+			  1 << LOOPBACK_NEAR_LBN,
+			  efx->loopback_mode == LOOPBACK_PHYXS);
 	if (efx->phy_type != PHY_TYPE_SFX7101)
-		mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
-				       GPHY_XCONTROL_REG,
-				       GPHY_LOOPBACK_NEAR_LBN,
-				       efx->loopback_mode == LOOPBACK_GPHY);
+		efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG,
+				  1 << GPHY_LOOPBACK_NEAR_LBN,
+				  efx->loopback_mode == LOOPBACK_GPHY);
 }
 
 static void tenxpress_low_power(struct efx_nic *efx)
 {
-	int phy_id = efx->mii.phy_id;
-
 	if (efx->phy_type == PHY_TYPE_SFX7101)
-		mdio_clause45_set_mmds_lpower(
+		efx_mdio_set_mmds_lpower(
 			efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
 			TENXPRESS_REQUIRED_DEVS);
 	else
-		mdio_clause45_set_flag(
-			efx, phy_id, MDIO_MMD_PMAPMD,
-			PMA_PMD_XCONTROL_REG, PMA_PMD_EXT_LPOWER_LBN,
+		efx_mdio_set_flag(
+			efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG,
+			1 << PMA_PMD_EXT_LPOWER_LBN,
 			!!(efx->phy_mode & PHY_MODE_LOW_POWER));
 }
 
@@ -568,8 +526,8 @@
 		WARN_ON(rc);
 	}
 
-	mdio_clause45_transmit_disable(efx);
-	mdio_clause45_phy_reconfigure(efx);
+	efx_mdio_transmit_disable(efx);
+	efx_mdio_phy_reconfigure(efx);
 	tenxpress_ext_loopback(efx);
 
 	phy_data->loopback_mode = efx->loopback_mode;
@@ -585,7 +543,7 @@
 		efx->link_fd = ecmd.duplex == DUPLEX_FULL;
 		efx->link_up = sft9001_link_ok(efx, &ecmd);
 	}
-	efx->link_fc = mdio_clause45_get_pause(efx);
+	efx->link_fc = efx_mdio_get_pause(efx);
 }
 
 /* Poll PHY for interrupt */
@@ -599,7 +557,7 @@
 		if (link_ok != efx->link_up) {
 			change = true;
 		} else {
-			unsigned int link_fc = mdio_clause45_get_pause(efx);
+			unsigned int link_fc = efx_mdio_get_pause(efx);
 			if (link_fc != efx->link_fc)
 				change = true;
 		}
@@ -609,10 +567,9 @@
 		if (link_ok != efx->link_up)
 			change = true;
 	} else {
-		u32 status = mdio_clause45_read(efx, efx->mii.phy_id,
-						MDIO_MMD_PMAPMD,
-						PMA_PMD_LASI_STATUS);
-		if (status & (1 << PMA_PMD_LS_ALARM_LBN))
+		int status = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
+					   MDIO_PMA_LASI_STAT);
+		if (status & MDIO_PMA_LASI_LSALARM)
 			change = true;
 	}
 
@@ -634,8 +591,7 @@
 	if (efx->phy_type == PHY_TYPE_SFX7101) {
 		/* Power down the LNPGA */
 		reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
-		mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-				    PMA_PMD_XCONTROL_REG, reg);
+		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
 
 		/* Waiting here ensures that the board fini, which can turn
 		 * off the power to the PHY, won't get run until the LNPGA
@@ -661,8 +617,7 @@
 	else
 		reg = PMA_PMD_LED_DEFAULT;
 
-	mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-			    PMA_PMD_LED_OVERR_REG, reg);
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
 }
 
 static const char *const sfx7101_test_names[] = {
@@ -698,7 +653,6 @@
 static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
 {
 	struct ethtool_cmd ecmd;
-	int phy_id = efx->mii.phy_id;
 	int rc = 0, rc2, i, ctrl_reg, res_reg;
 
 	if (flags & ETH_TEST_FL_OFFLINE)
@@ -717,11 +671,10 @@
 		 * must reset the PHY to resume normal service. */
 		ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN);
 	}
-	mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-			    PMA_PMD_CDIAG_CTRL_REG, ctrl_reg);
+	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG,
+		       ctrl_reg);
 	i = 0;
-	while (mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-				  PMA_PMD_CDIAG_CTRL_REG) &
+	while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) &
 	       (1 << CDIAG_CTRL_IN_PROG_LBN)) {
 		if (++i == 50) {
 			rc = -ETIMEDOUT;
@@ -729,15 +682,13 @@
 		}
 		msleep(100);
 	}
-	res_reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-				     PMA_PMD_CDIAG_RES_REG);
+	res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG);
 	for (i = 0; i < 4; i++) {
 		int pair_res =
 			(res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
 			& ((1 << CDIAG_RES_WIDTH) - 1);
-		int len_reg = mdio_clause45_read(efx, efx->mii.phy_id,
-						 MDIO_MMD_PMAPMD,
-						 PMA_PMD_CDIAG_LEN_REG + i);
+		int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
+					    PMA_PMD_CDIAG_LEN_REG + i);
 		if (pair_res == CDIAG_RES_OK)
 			results[1 + i] = 1;
 		else if (pair_res == CDIAG_RES_INVALID)
@@ -769,36 +720,39 @@
 static void
 tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
-	int phy_id = efx->mii.phy_id;
 	u32 adv = 0, lpa = 0;
 	int reg;
 
 	if (efx->phy_type != PHY_TYPE_SFX7101) {
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
-					 C22EXT_MSTSLV_CTRL);
+		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL);
 		if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
 			adv |= ADVERTISED_1000baseT_Full;
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
-					 C22EXT_MSTSLV_STATUS);
+		reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS);
 		if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
 			lpa |= ADVERTISED_1000baseT_Half;
 		if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
 			lpa |= ADVERTISED_1000baseT_Full;
 	}
-	reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-				 MDIO_AN_10GBT_CTRL);
-	if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN))
+	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
+	if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
 		adv |= ADVERTISED_10000baseT_Full;
-	reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
-				 MDIO_AN_10GBT_STATUS);
-	if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
+	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
+	if (reg & MDIO_AN_10GBT_STAT_LP10G)
 		lpa |= ADVERTISED_10000baseT_Full;
 
-	mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa);
+	mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);
 
-	if (efx->phy_type != PHY_TYPE_SFX7101)
+	if (efx->phy_type != PHY_TYPE_SFX7101) {
 		ecmd->supported |= (SUPPORTED_100baseT_Full |
 				    SUPPORTED_1000baseT_Full);
+		if (ecmd->speed != SPEED_10000) {
+			ecmd->eth_tp_mdix =
+				(efx_mdio_read(efx, MDIO_MMD_PMAPMD,
+					       PMA_PMD_XSTATUS_REG) &
+				 (1 << PMA_PMD_XSTAT_MDIX_LBN))
+				? ETH_TP_MDI_X : ETH_TP_MDI;
+		}
+	}
 
 	/* In loopback, the PHY automatically brings up the correct interface,
 	 * but doesn't advertise the correct speed. So override it */
@@ -813,29 +767,24 @@
 	if (!ecmd->autoneg)
 		return -EINVAL;
 
-	return mdio_clause45_set_settings(efx, ecmd);
+	return efx_mdio_set_settings(efx, ecmd);
 }
 
 static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
 {
-	mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
-			       MDIO_AN_10GBT_CTRL,
-			       MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
-			       advertising & ADVERTISED_10000baseT_Full);
+	efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+			  MDIO_AN_10GBT_CTRL_ADV10G,
+			  advertising & ADVERTISED_10000baseT_Full);
 }
 
 static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
 {
-	int phy_id = efx->mii.phy_id;
-
-	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
-			       C22EXT_MSTSLV_CTRL,
-			       C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
-			       advertising & ADVERTISED_1000baseT_Full);
-	mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
-			       MDIO_AN_10GBT_CTRL,
-			       MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
-			       advertising & ADVERTISED_10000baseT_Full);
+	efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL,
+			  1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
+			  advertising & ADVERTISED_1000baseT_Full);
+	efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+			  MDIO_AN_10GBT_CTRL_ADV10G,
+			  advertising & ADVERTISED_10000baseT_Full);
 }
 
 struct efx_phy_operations falcon_sfx7101_phy_ops = {
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/tx.c linux-libre-2.6.31-gnu/drivers/net/sfc/tx.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/tx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -360,13 +360,6 @@
 
 	/* Map fragments for DMA and add to TX queue */
 	rc = efx_enqueue_skb(tx_queue, skb);
-	if (unlikely(rc != NETDEV_TX_OK))
-		goto out;
-
-	/* Update last TX timer */
-	efx->net_dev->trans_start = jiffies;
-
- out:
 	return rc;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/xenpack.h linux-libre-2.6.31-gnu/drivers/net/sfc/xenpack.h
--- linux-libre-2.6.30-gnu/drivers/net/sfc/xenpack.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/xenpack.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/****************************************************************************
- * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006 Solarflare Communications Inc.
- *
- * 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, incorporated herein by reference.
- */
-
-#ifndef EFX_XENPACK_H
-#define EFX_XENPACK_H
-
-/* Exported functions from Xenpack standard PHY control */
-
-#include "mdio_10g.h"
-
-/****************************************************************************/
-/* XENPACK MDIO register extensions */
-#define MDIO_XP_LASI_RX_CTRL	(0x9000)
-#define MDIO_XP_LASI_TX_CTRL	(0x9001)
-#define MDIO_XP_LASI_CTRL	(0x9002)
-#define MDIO_XP_LASI_RX_STAT	(0x9003)
-#define MDIO_XP_LASI_TX_STAT	(0x9004)
-#define MDIO_XP_LASI_STAT	(0x9005)
-
-/* Control/Status bits */
-#define XP_LASI_LS_ALARM	(1 << 0)
-#define XP_LASI_TX_ALARM	(1 << 1)
-#define XP_LASI_RX_ALARM	(1 << 2)
-/* These two are Quake vendor extensions to the standard XENPACK defines */
-#define XP_LASI_LS_INTB		(1 << 3)
-#define XP_LASI_TEST		(1 << 7)
-
-/* Enable LASI interrupts for PHY */
-static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx)
-{
-	int reg;
-	int phy_id = efx->mii.phy_id;
-	/* Read to clear LASI status register */
-	reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
-				 MDIO_XP_LASI_STAT);
-
-	mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
-			    MDIO_XP_LASI_CTRL, XP_LASI_LS_ALARM);
-}
-
-/* Read the LASI interrupt status to clear the interrupt. */
-static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx)
-{
-	/* Read to clear link status alarm */
-	return mdio_clause45_read(efx, efx->mii.phy_id,
-				  MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT);
-}
-
-/* Turn off LASI interrupts */
-static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx)
-{
-	mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-			    MDIO_XP_LASI_CTRL, 0);
-}
-
-#endif /* EFX_XENPACK_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/sfc/xfp_phy.c linux-libre-2.6.31-gnu/drivers/net/sfc/xfp_phy.c
--- linux-libre-2.6.30-gnu/drivers/net/sfc/xfp_phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sfc/xfp_phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -15,13 +15,12 @@
 #include <linux/delay.h>
 #include "efx.h"
 #include "mdio_10g.h"
-#include "xenpack.h"
 #include "phy.h"
 #include "falcon.h"
 
-#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS |	\
-			   MDIO_MMDREG_DEVS_PMAPMD |	\
-			   MDIO_MMDREG_DEVS_PHYXS)
+#define XFP_REQUIRED_DEVS (MDIO_DEVS_PCS |	\
+			   MDIO_DEVS_PMAPMD |	\
+			   MDIO_DEVS_PHYXS)
 
 #define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) |		\
 		       (1 << LOOPBACK_PMAPMD) |		\
@@ -49,8 +48,7 @@
 void xfp_set_led(struct efx_nic *p, int led, int mode)
 {
 	int addr = MDIO_QUAKE_LED0_REG + led;
-	mdio_clause45_write(p, p->mii.phy_id, MDIO_MMD_PMAPMD, addr,
-			    mode);
+	efx_mdio_write(p, MDIO_MMD_PMAPMD, addr, mode);
 }
 
 struct xfp_phy_data {
@@ -63,14 +61,12 @@
 static int qt2025c_wait_reset(struct efx_nic *efx)
 {
 	unsigned long timeout = jiffies + 10 * HZ;
-	int phy_id = efx->mii.phy_id;
 	int reg, old_counter = 0;
 
 	/* Wait for firmware heartbeat to start */
 	for (;;) {
 		int counter;
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
-					 PCS_FW_HEARTBEAT_REG);
+		reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG);
 		if (reg < 0)
 			return reg;
 		counter = ((reg >> PCS_FW_HEARTB_LBN) &
@@ -86,8 +82,7 @@
 
 	/* Wait for firmware status to look good */
 	for (;;) {
-		reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
-					 PCS_UC8051_STATUS_REG);
+		reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
 		if (reg < 0)
 			return reg;
 		if ((reg &
@@ -109,9 +104,9 @@
 {
 	int rc;
 
-	rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PHYXS,
-				     XFP_MAX_RESET_TIME / XFP_RESET_WAIT,
-				     XFP_RESET_WAIT);
+	rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
+				XFP_MAX_RESET_TIME / XFP_RESET_WAIT,
+				XFP_RESET_WAIT);
 	if (rc < 0)
 		goto fail;
 
@@ -126,8 +121,7 @@
 
 	/* Check that all the MMDs we expect are present and responding. We
 	 * expect faults on some if the link is down, but not on the PHY XS */
-	rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS,
-				      MDIO_MMDREG_DEVS_PHYXS);
+	rc = efx_mdio_check_mmds(efx, XFP_REQUIRED_DEVS, MDIO_DEVS_PHYXS);
 	if (rc < 0)
 		goto fail;
 
@@ -143,7 +137,7 @@
 static int xfp_phy_init(struct efx_nic *efx)
 {
 	struct xfp_phy_data *phy_data;
-	u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS);
+	u32 devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
 	int rc;
 
 	phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL);
@@ -152,8 +146,8 @@
 	efx->phy_data = phy_data;
 
 	EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n",
-		 devid, mdio_id_oui(devid), mdio_id_model(devid),
-		 mdio_id_rev(devid));
+		 devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
+		 efx_mdio_id_rev(devid));
 
 	phy_data->phy_mode = efx->phy_mode;
 
@@ -174,12 +168,13 @@
 
 static void xfp_phy_clear_interrupt(struct efx_nic *efx)
 {
-	xenpack_clear_lasi_irqs(efx);
+	/* Read to clear link status alarm */
+	efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT);
 }
 
 static int xfp_link_ok(struct efx_nic *efx)
 {
-	return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS);
+	return efx_mdio_links_ok(efx, XFP_REQUIRED_DEVS);
 }
 
 static void xfp_phy_poll(struct efx_nic *efx)
@@ -200,9 +195,9 @@
 		 * or optical transceivers, varying somewhat between
 		 * firmware versions.  Only 'static mode' appears to
 		 * cover everything. */
-		mdio_clause45_set_flag(
-			efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
-			PMA_PMD_FTX_CTRL2_REG, PMA_PMD_FTX_STATIC_LBN,
+		mdio_set_flag(
+			&efx->mdio, efx->mdio.prtad, MDIO_MMD_PMAPMD,
+			PMA_PMD_FTX_CTRL2_REG, 1 << PMA_PMD_FTX_STATIC_LBN,
 			efx->phy_mode & PHY_MODE_TX_DISABLED ||
 			efx->phy_mode & PHY_MODE_LOW_POWER ||
 			efx->loopback_mode == LOOPBACK_PCS ||
@@ -213,10 +208,10 @@
 		    (phy_data->phy_mode & PHY_MODE_TX_DISABLED))
 			xfp_reset_phy(efx);
 
-		mdio_clause45_transmit_disable(efx);
+		efx_mdio_transmit_disable(efx);
 	}
 
-	mdio_clause45_phy_reconfigure(efx);
+	efx_mdio_phy_reconfigure(efx);
 
 	phy_data->phy_mode = efx->phy_mode;
 	efx->link_up = xfp_link_ok(efx);
@@ -225,6 +220,10 @@
 	efx->link_fc = efx->wanted_fc;
 }
 
+static void xfp_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+	mdio45_ethtool_gset(&efx->mdio, ecmd);
+}
 
 static void xfp_phy_fini(struct efx_nic *efx)
 {
@@ -243,8 +242,8 @@
 	.poll            = xfp_phy_poll,
 	.fini            = xfp_phy_fini,
 	.clear_interrupt = xfp_phy_clear_interrupt,
-	.get_settings    = mdio_clause45_get_settings,
-	.set_settings	 = mdio_clause45_set_settings,
+	.get_settings    = xfp_phy_get_settings,
+	.set_settings	 = efx_mdio_set_settings,
 	.mmds            = XFP_REQUIRED_DEVS,
 	.loopbacks       = XFP_LOOPBACKS,
 };
diff -druN linux-libre-2.6.30-gnu/drivers/net/sgiseeq.c linux-libre-2.6.31-gnu/drivers/net/sgiseeq.c
--- linux-libre-2.6.30-gnu/drivers/net/sgiseeq.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sgiseeq.c	2009-09-09 18:13:59.000000000 -0400
@@ -709,6 +709,17 @@
 	dma_sync_desc_dev(dev, &buf[i]);
 }
 
+static const struct net_device_ops sgiseeq_netdev_ops = {
+	.ndo_open		= sgiseeq_open,
+	.ndo_stop		= sgiseeq_close,
+	.ndo_start_xmit		= sgiseeq_start_xmit,
+	.ndo_tx_timeout		= timeout,
+	.ndo_set_multicast_list	= sgiseeq_set_multicast,
+	.ndo_set_mac_address	= sgiseeq_set_mac_address,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
 static int __init sgiseeq_probe(struct platform_device *pdev)
 {
 	struct sgiseeq_platform_data *pd = pdev->dev.platform_data;
@@ -775,13 +786,8 @@
 			      SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT |
 			      SEEQ_CTRL_ENCARR;
 
-	dev->open		= sgiseeq_open;
-	dev->stop		= sgiseeq_close;
-	dev->hard_start_xmit	= sgiseeq_start_xmit;
-	dev->tx_timeout		= timeout;
+	dev->netdev_ops		= &sgiseeq_netdev_ops;
 	dev->watchdog_timeo	= (200 * HZ) / 1000;
-	dev->set_multicast_list	= sgiseeq_set_multicast;
-	dev->set_mac_address	= sgiseeq_set_mac_address;
 	dev->irq		= irq;
 
 	if (register_netdev(dev)) {
diff -druN linux-libre-2.6.30-gnu/drivers/net/sh_eth.c linux-libre-2.6.31-gnu/drivers/net/sh_eth.c
--- linux-libre-2.6.30-gnu/drivers/net/sh_eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sh_eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
  *  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- *  Copyright (C) 2008 Renesas Solutions Corp.
+ *  Copyright (C) 2008-2009 Renesas Solutions Corp.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -33,6 +33,226 @@
 
 #include "sh_eth.h"
 
+/* There is CPU dependent code */
+#if defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define SH_ETH_RESET_DEFAULT	1
+static void sh_eth_set_duplex(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+
+	if (mdp->duplex) /* Full */
+		ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+	else		/* Half */
+		ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+}
+
+static void sh_eth_set_rate(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+
+	switch (mdp->speed) {
+	case 10: /* 10BASE */
+		ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR);
+		break;
+	case 100:/* 100BASE */
+		ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR);
+		break;
+	default:
+		break;
+	}
+}
+
+/* SH7724 */
+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+	.set_duplex	= sh_eth_set_duplex,
+	.set_rate	= sh_eth_set_rate,
+
+	.ecsr_value	= ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
+	.ecsipr_value	= ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
+	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x01ff009f,
+
+	.tx_check	= EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
+	.eesr_err_check	= EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
+			  EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
+	.tx_error_check	= EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.hw_swap	= 1,
+};
+
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
+#define SH_ETH_HAS_TSU	1
+static void sh_eth_chip_reset(struct net_device *ndev)
+{
+	/* reset device */
+	ctrl_outl(ARSTR_ARSTR, ARSTR);
+	mdelay(1);
+}
+
+static void sh_eth_reset(struct net_device *ndev)
+{
+	u32 ioaddr = ndev->base_addr;
+	int cnt = 100;
+
+	ctrl_outl(EDSR_ENALL, ioaddr + EDSR);
+	ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	while (cnt > 0) {
+		if (!(ctrl_inl(ioaddr + EDMR) & 0x3))
+			break;
+		mdelay(1);
+		cnt--;
+	}
+	if (cnt < 0)
+		printk(KERN_ERR "Device reset fail\n");
+
+	/* Table Init */
+	ctrl_outl(0x0, ioaddr + TDLAR);
+	ctrl_outl(0x0, ioaddr + TDFAR);
+	ctrl_outl(0x0, ioaddr + TDFXR);
+	ctrl_outl(0x0, ioaddr + TDFFR);
+	ctrl_outl(0x0, ioaddr + RDLAR);
+	ctrl_outl(0x0, ioaddr + RDFAR);
+	ctrl_outl(0x0, ioaddr + RDFXR);
+	ctrl_outl(0x0, ioaddr + RDFFR);
+}
+
+static void sh_eth_set_duplex(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+
+	if (mdp->duplex) /* Full */
+		ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+	else		/* Half */
+		ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+}
+
+static void sh_eth_set_rate(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+
+	switch (mdp->speed) {
+	case 10: /* 10BASE */
+		ctrl_outl(GECMR_10, ioaddr + GECMR);
+		break;
+	case 100:/* 100BASE */
+		ctrl_outl(GECMR_100, ioaddr + GECMR);
+		break;
+	case 1000: /* 1000BASE */
+		ctrl_outl(GECMR_1000, ioaddr + GECMR);
+		break;
+	default:
+		break;
+	}
+}
+
+/* sh7763 */
+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+	.chip_reset	= sh_eth_chip_reset,
+	.set_duplex	= sh_eth_set_duplex,
+	.set_rate	= sh_eth_set_rate,
+
+	.ecsr_value	= ECSR_ICD | ECSR_MPD,
+	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
+	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+
+	.tx_check	= EESR_TC1 | EESR_FTC,
+	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
+			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
+			  EESR_ECI,
+	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
+			  EESR_TFE,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.bculr		= 1,
+	.hw_swap	= 1,
+	.rpadir		= 1,
+	.no_trimd	= 1,
+	.no_ade		= 1,
+};
+
+#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+#define SH_ETH_RESET_DEFAULT	1
+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.hw_swap	= 1,
+};
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
+#define SH_ETH_RESET_DEFAULT	1
+#define SH_ETH_HAS_TSU	1
+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+};
+#endif
+
+static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
+{
+	if (!cd->ecsr_value)
+		cd->ecsr_value = DEFAULT_ECSR_INIT;
+
+	if (!cd->ecsipr_value)
+		cd->ecsipr_value = DEFAULT_ECSIPR_INIT;
+
+	if (!cd->fcftr_value)
+		cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \
+				  DEFAULT_FIFO_F_D_RFD;
+
+	if (!cd->fdr_value)
+		cd->fdr_value = DEFAULT_FDR_INIT;
+
+	if (!cd->rmcr_value)
+		cd->rmcr_value = DEFAULT_RMCR_VALUE;
+
+	if (!cd->tx_check)
+		cd->tx_check = DEFAULT_TX_CHECK;
+
+	if (!cd->eesr_err_check)
+		cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK;
+
+	if (!cd->tx_error_check)
+		cd->tx_error_check = DEFAULT_TX_ERROR_CHECK;
+}
+
+#if defined(SH_ETH_RESET_DEFAULT)
+/* Chip Reset */
+static void sh_eth_reset(struct net_device *ndev)
+{
+	u32 ioaddr = ndev->base_addr;
+
+	ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	mdelay(3);
+	ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
+}
+#endif
+
+#if defined(CONFIG_CPU_SH4)
+static void sh_eth_set_receive_align(struct sk_buff *skb)
+{
+	int reserve;
+
+	reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1));
+	if (reserve)
+		skb_reserve(skb, reserve);
+}
+#else
+static void sh_eth_set_receive_align(struct sk_buff *skb)
+{
+	skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN);
+}
+#endif
+
+
 /* CPU <-> EDMAC endian convert */
 static inline __u32 cpu_to_edmac(struct sh_eth_private *mdp, u32 x)
 {
@@ -165,41 +385,6 @@
 	.get_mdio_data = sh_get_mdio,
 };
 
-/* Chip Reset */
-static void sh_eth_reset(struct net_device *ndev)
-{
-	u32 ioaddr = ndev->base_addr;
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	int cnt = 100;
-
-	ctrl_outl(EDSR_ENALL, ioaddr + EDSR);
-	ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
-	while (cnt > 0) {
-		if (!(ctrl_inl(ioaddr + EDMR) & 0x3))
-			break;
-		mdelay(1);
-		cnt--;
-	}
-	if (cnt < 0)
-		printk(KERN_ERR "Device reset fail\n");
-
-	/* Table Init */
-	ctrl_outl(0x0, ioaddr + TDLAR);
-	ctrl_outl(0x0, ioaddr + TDFAR);
-	ctrl_outl(0x0, ioaddr + TDFXR);
-	ctrl_outl(0x0, ioaddr + TDFFR);
-	ctrl_outl(0x0, ioaddr + RDLAR);
-	ctrl_outl(0x0, ioaddr + RDFAR);
-	ctrl_outl(0x0, ioaddr + RDFXR);
-	ctrl_outl(0x0, ioaddr + RDFFR);
-#else
-	ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
-	mdelay(3);
-	ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
-#endif
-}
-
 /* free skb and descriptor buffer */
 static void sh_eth_ring_free(struct net_device *ndev)
 {
@@ -228,7 +413,7 @@
 /* format skb and descriptor buffer */
 static void sh_eth_ring_format(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr, reserve = 0;
+	u32 ioaddr = ndev->base_addr;
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
@@ -250,37 +435,27 @@
 		mdp->rx_skbuff[i] = skb;
 		if (skb == NULL)
 			break;
+		dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz,
+				DMA_FROM_DEVICE);
 		skb->dev = ndev; /* Mark as being used by this device. */
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-		reserve = SH7763_SKB_ALIGN
-			- ((uint32_t)skb->data & (SH7763_SKB_ALIGN-1));
-		if (reserve)
-			skb_reserve(skb, reserve);
-#else
-		skb_reserve(skb, RX_OFFSET);
-#endif
+		sh_eth_set_receive_align(skb);
+
 		/* RX descriptor */
 		rxdesc = &mdp->rx_ring[i];
-		rxdesc->addr = (u32)skb->data & ~0x3UL;
+		rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
 		rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
 
 		/* The size of the buffer is 16 byte boundary. */
-		rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
+		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
 		/* Rx descriptor address set */
 		if (i == 0) {
-			ctrl_outl((u32)rxdesc, ioaddr + RDLAR);
+			ctrl_outl(mdp->rx_desc_dma, ioaddr + RDLAR);
 #if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			ctrl_outl((u32)rxdesc, ioaddr + RDFAR);
+			ctrl_outl(mdp->rx_desc_dma, ioaddr + RDFAR);
 #endif
 		}
 	}
 
-	/* Rx descriptor address set */
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	ctrl_outl((u32)rxdesc, ioaddr + RDFXR);
-	ctrl_outl(0x1, ioaddr + RDFFR);
-#endif
-
 	mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
 
 	/* Mark the last entry as wrapping the ring. */
@@ -296,19 +471,13 @@
 		txdesc->buffer_length = 0;
 		if (i == 0) {
 			/* Tx descriptor address set */
-			ctrl_outl((u32)txdesc, ioaddr + TDLAR);
+			ctrl_outl(mdp->tx_desc_dma, ioaddr + TDLAR);
 #if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			ctrl_outl((u32)txdesc, ioaddr + TDFAR);
+			ctrl_outl(mdp->tx_desc_dma, ioaddr + TDFAR);
 #endif
 		}
 	}
 
-	/* Tx descriptor address set */
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	ctrl_outl((u32)txdesc, ioaddr + TDFXR);
-	ctrl_outl(0x1, ioaddr + TDFFR);
-#endif
-
 	txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
 }
 
@@ -331,7 +500,7 @@
 	mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
 				GFP_KERNEL);
 	if (!mdp->rx_skbuff) {
-		printk(KERN_ERR "%s: Cannot allocate Rx skb\n", ndev->name);
+		dev_err(&ndev->dev, "Cannot allocate Rx skb\n");
 		ret = -ENOMEM;
 		return ret;
 	}
@@ -339,7 +508,7 @@
 	mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE,
 				GFP_KERNEL);
 	if (!mdp->tx_skbuff) {
-		printk(KERN_ERR "%s: Cannot allocate Tx skb\n", ndev->name);
+		dev_err(&ndev->dev, "Cannot allocate Tx skb\n");
 		ret = -ENOMEM;
 		goto skb_ring_free;
 	}
@@ -350,8 +519,8 @@
 			GFP_KERNEL);
 
 	if (!mdp->rx_ring) {
-		printk(KERN_ERR "%s: Cannot allocate Rx Ring (size %d bytes)\n",
-			ndev->name, rx_ringsize);
+		dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n",
+			rx_ringsize);
 		ret = -ENOMEM;
 		goto desc_ring_free;
 	}
@@ -363,8 +532,8 @@
 	mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
 			GFP_KERNEL);
 	if (!mdp->tx_ring) {
-		printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
-			ndev->name, tx_ringsize);
+		dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n",
+			tx_ringsize);
 		ret = -ENOMEM;
 		goto desc_ring_free;
 	}
@@ -394,44 +563,43 @@
 
 	/* Descriptor format */
 	sh_eth_ring_format(ndev);
-	ctrl_outl(RPADIR_INIT, ioaddr + RPADIR);
+	if (mdp->cd->rpadir)
+		ctrl_outl(mdp->cd->rpadir_value, ioaddr + RPADIR);
 
 	/* all sh_eth int mask */
 	ctrl_outl(0, ioaddr + EESIPR);
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	ctrl_outl(EDMR_EL, ioaddr + EDMR);
-#else
-	ctrl_outl(0, ioaddr + EDMR);	/* Endian change */
+#if defined(__LITTLE_ENDIAN__)
+	if (mdp->cd->hw_swap)
+		ctrl_outl(EDMR_EL, ioaddr + EDMR);
+	else
 #endif
+		ctrl_outl(0, ioaddr + EDMR);
 
 	/* FIFO size set */
-	ctrl_outl((FIFO_SIZE_T | FIFO_SIZE_R), ioaddr + FDR);
+	ctrl_outl(mdp->cd->fdr_value, ioaddr + FDR);
 	ctrl_outl(0, ioaddr + TFTR);
 
 	/* Frame recv control */
-	ctrl_outl(0, ioaddr + RMCR);
+	ctrl_outl(mdp->cd->rmcr_value, ioaddr + RMCR);
 
 	rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
 	tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
 	ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER);
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	/* Burst sycle set */
-	ctrl_outl(0x800, ioaddr + BCULR);
-#endif
+	if (mdp->cd->bculr)
+		ctrl_outl(0x800, ioaddr + BCULR);	/* Burst sycle set */
 
-	ctrl_outl((FIFO_F_D_RFF | FIFO_F_D_RFD), ioaddr + FCFTR);
+	ctrl_outl(mdp->cd->fcftr_value, ioaddr + FCFTR);
 
-#if !defined(CONFIG_CPU_SUBTYPE_SH7763)
-	ctrl_outl(0, ioaddr + TRIMD);
-#endif
+	if (!mdp->cd->no_trimd)
+		ctrl_outl(0, ioaddr + TRIMD);
 
 	/* Recv frame limit set register */
 	ctrl_outl(RFLR_VALUE, ioaddr + RFLR);
 
 	ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR);
-	ctrl_outl((DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff), ioaddr + EESIPR);
+	ctrl_outl(mdp->cd->eesipr_value, ioaddr + EESIPR);
 
 	/* PAUSE Prohibition */
 	val = (ctrl_inl(ioaddr + ECMR) & ECMR_DM) |
@@ -439,24 +607,25 @@
 
 	ctrl_outl(val, ioaddr + ECMR);
 
+	if (mdp->cd->set_rate)
+		mdp->cd->set_rate(ndev);
+
 	/* E-MAC Status Register clear */
-	ctrl_outl(ECSR_INIT, ioaddr + ECSR);
+	ctrl_outl(mdp->cd->ecsr_value, ioaddr + ECSR);
 
 	/* E-MAC Interrupt Enable register */
-	ctrl_outl(ECSIPR_INIT, ioaddr + ECSIPR);
+	ctrl_outl(mdp->cd->ecsipr_value, ioaddr + ECSIPR);
 
 	/* Set MAC address */
 	update_mac_address(ndev);
 
 	/* mask reset */
-#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7763)
-	ctrl_outl(APR_AP, ioaddr + APR);
-	ctrl_outl(MPR_MP, ioaddr + MPR);
-	ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7710)
-	ctrl_outl(BCFR_UNLIMITED, ioaddr + BCFR);
-#endif
+	if (mdp->cd->apr)
+		ctrl_outl(APR_AP, ioaddr + APR);
+	if (mdp->cd->mpr)
+		ctrl_outl(MPR_MP, ioaddr + MPR);
+	if (mdp->cd->tpauser)
+		ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
 
 	/* Setting the Rx mode will start the Rx process. */
 	ctrl_outl(EDRRR_R, ioaddr + EDRRR);
@@ -505,7 +674,7 @@
 	int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
 	struct sk_buff *skb;
 	u16 pkt_len = 0;
-	u32 desc_status, reserve = 0;
+	u32 desc_status;
 
 	rxdesc = &mdp->rx_ring[entry];
 	while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
@@ -534,7 +703,10 @@
 			if (desc_status & RD_RFS10)
 				mdp->stats.rx_over_errors++;
 		} else {
-			swaps((char *)(rxdesc->addr & ~0x3), pkt_len + 2);
+			if (!mdp->cd->hw_swap)
+				sh_eth_soft_swap(
+					phys_to_virt(ALIGN(rxdesc->addr, 4)),
+					pkt_len + 2);
 			skb = mdp->rx_skbuff[entry];
 			mdp->rx_skbuff[entry] = NULL;
 			skb_put(skb, pkt_len);
@@ -545,6 +717,7 @@
 		}
 		rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
 		entry = (++mdp->cur_rx) % RX_RING_SIZE;
+		rxdesc = &mdp->rx_ring[entry];
 	}
 
 	/* Refill the Rx ring buffers. */
@@ -552,24 +725,20 @@
 		entry = mdp->dirty_rx % RX_RING_SIZE;
 		rxdesc = &mdp->rx_ring[entry];
 		/* The size of the buffer is 16 byte boundary. */
-		rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
+		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
 
 		if (mdp->rx_skbuff[entry] == NULL) {
 			skb = dev_alloc_skb(mdp->rx_buf_sz);
 			mdp->rx_skbuff[entry] = skb;
 			if (skb == NULL)
 				break;	/* Better luck next round. */
+			dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz,
+					DMA_FROM_DEVICE);
 			skb->dev = ndev;
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			reserve = SH7763_SKB_ALIGN
-				- ((uint32_t)skb->data & (SH7763_SKB_ALIGN-1));
-			if (reserve)
-				skb_reserve(skb, reserve);
-#else
-			skb_reserve(skb, RX_OFFSET);
-#endif
+			sh_eth_set_receive_align(skb);
+
 			skb->ip_summed = CHECKSUM_NONE;
-			rxdesc->addr = (u32)skb->data & ~0x3UL;
+			rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
 		}
 		if (entry >= RX_RING_SIZE - 1)
 			rxdesc->status |=
@@ -593,6 +762,8 @@
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	u32 ioaddr = ndev->base_addr;
 	u32 felic_stat;
+	u32 link_stat;
+	u32 mask;
 
 	if (intr_status & EESR_ECI) {
 		felic_stat = ctrl_inl(ioaddr + ECSR);
@@ -601,7 +772,14 @@
 			mdp->stats.tx_carrier_errors++;
 		if (felic_stat & ECSR_LCHNG) {
 			/* Link Changed */
-			u32 link_stat = (ctrl_inl(ioaddr + PSR));
+			if (mdp->cd->no_psr) {
+				if (mdp->link == PHY_DOWN)
+					link_stat = 0;
+				else
+					link_stat = PHY_ST_LINK;
+			} else {
+				link_stat = (ctrl_inl(ioaddr + PSR));
+			}
 			if (!(link_stat & PHY_ST_LINK)) {
 				/* Link Down : disable tx and rx */
 				ctrl_outl(ctrl_inl(ioaddr + ECMR) &
@@ -633,17 +811,15 @@
 		if (intr_status & EESR_RFRMER) {
 			/* Receive Frame Overflow int */
 			mdp->stats.rx_frame_errors++;
-			printk(KERN_ERR "Receive Frame Overflow\n");
+			dev_err(&ndev->dev, "Receive Frame Overflow\n");
 		}
 	}
-#if !defined(CONFIG_CPU_SUBTYPE_SH7763)
-	if (intr_status & EESR_ADE) {
-		if (intr_status & EESR_TDE) {
-			if (intr_status & EESR_TFE)
-				mdp->stats.tx_fifo_errors++;
-		}
+
+	if (!mdp->cd->no_ade) {
+		if (intr_status & EESR_ADE && intr_status & EESR_TDE &&
+		    intr_status & EESR_TFE)
+			mdp->stats.tx_fifo_errors++;
 	}
-#endif
 
 	if (intr_status & EESR_RDE) {
 		/* Receive Descriptor Empty int */
@@ -651,24 +827,24 @@
 
 		if (ctrl_inl(ioaddr + EDRRR) ^ EDRRR_R)
 			ctrl_outl(EDRRR_R, ioaddr + EDRRR);
-		printk(KERN_ERR "Receive Descriptor Empty\n");
+		dev_err(&ndev->dev, "Receive Descriptor Empty\n");
 	}
 	if (intr_status & EESR_RFE) {
 		/* Receive FIFO Overflow int */
 		mdp->stats.rx_fifo_errors++;
-		printk(KERN_ERR "Receive FIFO Overflow\n");
+		dev_err(&ndev->dev, "Receive FIFO Overflow\n");
 	}
-	if (intr_status & (EESR_TWB | EESR_TABT |
-#if !defined(CONFIG_CPU_SUBTYPE_SH7763)
-			EESR_ADE |
-#endif
-			EESR_TDE | EESR_TFE)) {
+
+	mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
+	if (mdp->cd->no_ade)
+		mask &= ~EESR_ADE;
+	if (intr_status & mask) {
 		/* Tx error */
 		u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR);
 		/* dmesg */
-		printk(KERN_ERR "%s:TX error. status=%8.8x cur_tx=%8.8x ",
-				ndev->name, intr_status, mdp->cur_tx);
-		printk(KERN_ERR "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
+		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
+				intr_status, mdp->cur_tx);
+		dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
 				mdp->dirty_tx, (u32) ndev->state, edtrr);
 		/* dirty buffer free */
 		sh_eth_txfree(ndev);
@@ -687,9 +863,9 @@
 {
 	struct net_device *ndev = netdev;
 	struct sh_eth_private *mdp = netdev_priv(ndev);
+	struct sh_eth_cpu_data *cd = mdp->cd;
 	irqreturn_t ret = IRQ_NONE;
-	u32 ioaddr, boguscnt = RX_RING_SIZE;
-	u32 intr_status = 0;
+	u32 ioaddr, intr_status = 0;
 
 	ioaddr = ndev->base_addr;
 	spin_lock(&mdp->lock);
@@ -699,7 +875,7 @@
 	/* Clear interrupt */
 	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
 			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
-			TX_CHECK | EESR_ERR_CHECK)) {
+			cd->tx_check | cd->eesr_err_check)) {
 		ctrl_outl(intr_status, ioaddr + EESR);
 		ret = IRQ_HANDLED;
 	} else
@@ -716,20 +892,14 @@
 	}
 
 	/* Tx Check */
-	if (intr_status & TX_CHECK) {
+	if (intr_status & cd->tx_check) {
 		sh_eth_txfree(ndev);
 		netif_wake_queue(ndev);
 	}
 
-	if (intr_status & EESR_ERR_CHECK)
+	if (intr_status & cd->eesr_err_check)
 		sh_eth_error(ndev, intr_status);
 
-	if (--boguscnt < 0) {
-		printk(KERN_WARNING
-		       "%s: Too much work at interrupt, status=0x%4.4x.\n",
-		       ndev->name, intr_status);
-	}
-
 other_irq:
 	spin_unlock(&mdp->lock);
 
@@ -756,32 +926,15 @@
 		if (phydev->duplex != mdp->duplex) {
 			new_state = 1;
 			mdp->duplex = phydev->duplex;
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			if (mdp->duplex) { /*  FULL */
-				ctrl_outl(ctrl_inl(ioaddr + ECMR) | ECMR_DM,
-						ioaddr + ECMR);
-			} else {	/* Half */
-				ctrl_outl(ctrl_inl(ioaddr + ECMR) & ~ECMR_DM,
-						ioaddr + ECMR);
-			}
-#endif
+			if (mdp->cd->set_duplex)
+				mdp->cd->set_duplex(ndev);
 		}
 
 		if (phydev->speed != mdp->speed) {
 			new_state = 1;
 			mdp->speed = phydev->speed;
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			switch (mdp->speed) {
-			case 10: /* 10BASE */
-				ctrl_outl(GECMR_10, ioaddr + GECMR); break;
-			case 100:/* 100BASE */
-				ctrl_outl(GECMR_100, ioaddr + GECMR); break;
-			case 1000: /* 1000BASE */
-				ctrl_outl(GECMR_1000, ioaddr + GECMR); break;
-			default:
-				break;
-			}
-#endif
+			if (mdp->cd->set_rate)
+				mdp->cd->set_rate(ndev);
 		}
 		if (mdp->link == PHY_DOWN) {
 			ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF)
@@ -804,7 +957,7 @@
 static int sh_eth_phy_init(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	char phy_id[BUS_ID_SIZE];
+	char phy_id[MII_BUS_ID_SIZE + 3];
 	struct phy_device *phydev = NULL;
 
 	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
@@ -821,8 +974,9 @@
 		dev_err(&ndev->dev, "phy_connect failed\n");
 		return PTR_ERR(phydev);
 	}
+
 	dev_info(&ndev->dev, "attached phy %i to driver %s\n",
-	phydev->addr, phydev->drv->name);
+		phydev->addr, phydev->drv->name);
 
 	mdp->phydev = phydev;
 
@@ -860,7 +1014,7 @@
 #endif
 				ndev->name, ndev);
 	if (ret) {
-		printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME);
+		dev_err(&ndev->dev, "Can not assign IRQ number\n");
 		return ret;
 	}
 
@@ -947,7 +1101,7 @@
 		if (!sh_eth_txfree(ndev)) {
 			netif_stop_queue(ndev);
 			spin_unlock_irqrestore(&mdp->lock, flags);
-			return 1;
+			return NETDEV_TX_BUSY;
 		}
 	}
 	spin_unlock_irqrestore(&mdp->lock, flags);
@@ -955,9 +1109,11 @@
 	entry = mdp->cur_tx % TX_RING_SIZE;
 	mdp->tx_skbuff[entry] = skb;
 	txdesc = &mdp->tx_ring[entry];
-	txdesc->addr = (u32)(skb->data);
+	txdesc->addr = virt_to_phys(skb->data);
 	/* soft swap. */
-	swaps((char *)(txdesc->addr & ~0x3), skb->len + 2);
+	if (!mdp->cd->hw_swap)
+		sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
+				 skb->len + 2);
 	/* write back */
 	__flush_purge_region(skb->data, skb->len);
 	if (skb->len < ETHERSMALL)
@@ -1059,7 +1215,7 @@
 	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
 }
 
-
+#if defined(SH_ETH_HAS_TSU)
 /* Multicast reception directions set */
 static void sh_eth_set_multicast_list(struct net_device *ndev)
 {
@@ -1104,6 +1260,7 @@
 	ctrl_outl(0, ioaddr + TSU_POST3);	/* Disable CAM entry [16-23] */
 	ctrl_outl(0, ioaddr + TSU_POST4);	/* Disable CAM entry [24-31] */
 }
+#endif /* SH_ETH_HAS_TSU */
 
 /* MDIO bus release function */
 static int sh_mdio_release(struct net_device *ndev)
@@ -1193,7 +1350,9 @@
 	.ndo_stop		= sh_eth_close,
 	.ndo_start_xmit		= sh_eth_start_xmit,
 	.ndo_get_stats		= sh_eth_get_stats,
+#if defined(SH_ETH_HAS_TSU)
 	.ndo_set_multicast_list	= sh_eth_set_multicast_list,
+#endif
 	.ndo_tx_timeout		= sh_eth_tx_timeout,
 	.ndo_do_ioctl		= sh_eth_do_ioctl,
 	.ndo_validate_addr	= eth_validate_addr,
@@ -1219,7 +1378,7 @@
 
 	ndev = alloc_etherdev(sizeof(struct sh_eth_private));
 	if (!ndev) {
-		printk(KERN_ERR "%s: could not allocate device.\n", CARDNAME);
+		dev_err(&pdev->dev, "Could not allocate device.\n");
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -1252,6 +1411,10 @@
 	/* EDMAC endian */
 	mdp->edmac_endian = pd->edmac_endian;
 
+	/* set cpu data */
+	mdp->cd = &sh_eth_my_cpu_data;
+	sh_eth_set_default_cpu_data(mdp->cd);
+
 	/* set function */
 	ndev->netdev_ops = &sh_eth_netdev_ops;
 	ndev->watchdog_timeo = TX_TIMEOUT;
@@ -1264,13 +1427,10 @@
 
 	/* First device only init */
 	if (!devno) {
-#if defined(ARSTR)
-		/* reset device */
-		ctrl_outl(ARSTR_ARSTR, ARSTR);
-		mdelay(1);
-#endif
+		if (mdp->cd->chip_reset)
+			mdp->cd->chip_reset(ndev);
 
-#if defined(SH_TSU_ADDR)
+#if defined(SH_ETH_HAS_TSU)
 		/* TSU init (Init only)*/
 		sh_eth_tsu_init(SH_TSU_ADDR);
 #endif
@@ -1287,8 +1447,8 @@
 		goto out_unregister;
 
 	/* pritnt device infomation */
-	printk(KERN_INFO "%s: %s at 0x%x, ",
-	       ndev->name, CARDNAME, (u32) ndev->base_addr);
+	pr_info("Base address at 0x%x, ",
+	       (u32)ndev->base_addr);
 
 	for (i = 0; i < 5; i++)
 		printk("%02X:", ndev->dev_addr[i]);
diff -druN linux-libre-2.6.30-gnu/drivers/net/sh_eth.h linux-libre-2.6.31-gnu/drivers/net/sh_eth.h
--- linux-libre-2.6.30-gnu/drivers/net/sh_eth.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sh_eth.h	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
  *  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- *  Copyright (C) 2008 Renesas Solutions Corp.
+ *  Copyright (C) 2008-2009 Renesas Solutions Corp.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -39,12 +39,12 @@
 #define ETHERSMALL		60
 #define PKT_BUF_SZ		1538
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
+#if defined(CONFIG_CPU_SUBTYPE_SH7763)
+/* This CPU register maps is very difference by other SH4 CPU */
 
-#define SH7763_SKB_ALIGN 32
 /* Chip Base Address */
 # define SH_TSU_ADDR	0xFEE01800
-# define ARSTR			SH_TSU_ADDR
+# define ARSTR		SH_TSU_ADDR
 
 /* Chip Registers */
 /* E-DMAC */
@@ -143,8 +143,60 @@
 # define FWNLCR1         0xB0
 # define FWALCR1         0x40
 
-#else /* CONFIG_CPU_SUBTYPE_SH7763 */
-# define RX_OFFSET 2	/* skb offset */
+#elif defined(CONFIG_CPU_SH4)	/* #if defined(CONFIG_CPU_SUBTYPE_SH7763) */
+/* EtherC */
+#define ECMR		0x100
+#define RFLR		0x108
+#define ECSR		0x110
+#define ECSIPR		0x118
+#define PIR		0x120
+#define PSR		0x128
+#define RDMLR		0x140
+#define IPGR		0x150
+#define APR		0x154
+#define MPR		0x158
+#define TPAUSER		0x164
+#define RFCF		0x160
+#define TPAUSECR	0x168
+#define BCFRR		0x16c
+#define MAHR		0x1c0
+#define MALR		0x1c8
+#define TROCR		0x1d0
+#define CDCR		0x1d4
+#define LCCR		0x1d8
+#define CNDCR		0x1dc
+#define CEFCR		0x1e4
+#define FRECR		0x1e8
+#define TSFRCR		0x1ec
+#define TLFRCR		0x1f0
+#define RFCR		0x1f4
+#define MAFCR		0x1f8
+#define RTRATE		0x1fc
+
+/* E-DMAC */
+#define EDMR		0x000
+#define EDTRR		0x008
+#define EDRRR		0x010
+#define TDLAR		0x018
+#define RDLAR		0x020
+#define EESR		0x028
+#define EESIPR		0x030
+#define TRSCER		0x038
+#define RMFCR		0x040
+#define TFTR		0x048
+#define FDR		0x050
+#define RMCR		0x058
+#define TFUCR		0x064
+#define RFOCR		0x068
+#define FCFTR		0x070
+#define RPADIR		0x078
+#define TRIMD		0x07c
+#define RBWAR		0x0c8
+#define RDFAR		0x0cc
+#define TBRAR		0x0d4
+#define TDFAR		0x0d8
+#else /* #elif defined(CONFIG_CPU_SH4) */
+/* This section is SH3 or SH2 */
 #ifndef CONFIG_CPU_SUBTYPE_SH7619
 /* Chip base address */
 # define SH_TSU_ADDR  0xA7000804
@@ -243,6 +295,30 @@
 
 #endif /* CONFIG_CPU_SUBTYPE_SH7763 */
 
+/* There are avoid compile error... */
+#if !defined(BCULR)
+#define BCULR	0x0fc
+#endif
+#if !defined(TRIMD)
+#define TRIMD	0x0fc
+#endif
+#if !defined(APR)
+#define APR	0x0fc
+#endif
+#if !defined(MPR)
+#define MPR	0x0fc
+#endif
+#if !defined(TPAUSER)
+#define TPAUSER	0x0fc
+#endif
+
+/* Driver's parameters */
+#if defined(CONFIG_CPU_SH4)
+#define SH4_SKB_RX_ALIGN	32
+#else
+#define SH2_SH3_SKB_RX_ALIGN	2
+#endif
+
 /*
  * Register's bits
  */
@@ -261,11 +337,10 @@
 
 /* EDMR */
 enum DMAC_M_BIT {
+	EDMR_EL = 0x40, /* Litte endian */
 	EDMR_DL1 = 0x20, EDMR_DL0 = 0x10,
 #ifdef CONFIG_CPU_SUBTYPE_SH7763
-	EDMR_SRST	= 0x03,
-	EMDR_DESC_R	= 0x30, /* Descriptor reserve size */
-	EDMR_EL		= 0x40, /* Litte endian */
+	EDMR_SRST = 0x03,
 #else /* CONFIG_CPU_SUBTYPE_SH7763 */
 	EDMR_SRST = 0x01,
 #endif
@@ -307,47 +382,43 @@
 
 /* EESR */
 enum EESR_BIT {
-#ifndef CONFIG_CPU_SUBTYPE_SH7763
-	EESR_TWB  = 0x40000000,
-#else
-	EESR_TWB  = 0xC0000000,
-	EESR_TC1  = 0x20000000,
-	EESR_TUC  = 0x10000000,
-	EESR_ROC  = 0x80000000,
-#endif
-	EESR_TABT = 0x04000000,
-	EESR_RABT = 0x02000000, EESR_RFRMER = 0x01000000,
-#ifndef CONFIG_CPU_SUBTYPE_SH7763
-	EESR_ADE  = 0x00800000,
-#endif
-	EESR_ECI  = 0x00400000,
-	EESR_FTC  = 0x00200000, EESR_TDE  = 0x00100000,
-	EESR_TFE  = 0x00080000, EESR_FRC  = 0x00040000,
-	EESR_RDE  = 0x00020000, EESR_RFE  = 0x00010000,
-#ifndef CONFIG_CPU_SUBTYPE_SH7763
-	EESR_CND  = 0x00000800,
-#endif
-	EESR_DLC  = 0x00000400,
-	EESR_CD   = 0x00000200, EESR_RTO  = 0x00000100,
-	EESR_RMAF = 0x00000080, EESR_CEEF = 0x00000040,
-	EESR_CELF = 0x00000020, EESR_RRF  = 0x00000010,
-	EESR_RTLF = 0x00000008, EESR_RTSF = 0x00000004,
-	EESR_PRE  = 0x00000002, EESR_CERF = 0x00000001,
+	EESR_TWB1	= 0x80000000,
+	EESR_TWB	= 0x40000000,	/* same as TWB0 */
+	EESR_TC1	= 0x20000000,
+	EESR_TUC	= 0x10000000,
+	EESR_ROC	= 0x08000000,
+	EESR_TABT	= 0x04000000,
+	EESR_RABT	= 0x02000000,
+	EESR_RFRMER	= 0x01000000,	/* same as RFCOF */
+	EESR_ADE	= 0x00800000,
+	EESR_ECI	= 0x00400000,
+	EESR_FTC	= 0x00200000,	/* same as TC or TC0 */
+	EESR_TDE	= 0x00100000,
+	EESR_TFE	= 0x00080000,	/* same as TFUF */
+	EESR_FRC	= 0x00040000,	/* same as FR */
+	EESR_RDE	= 0x00020000,
+	EESR_RFE	= 0x00010000,
+	EESR_CND	= 0x00000800,
+	EESR_DLC	= 0x00000400,
+	EESR_CD		= 0x00000200,
+	EESR_RTO	= 0x00000100,
+	EESR_RMAF	= 0x00000080,
+	EESR_CEEF	= 0x00000040,
+	EESR_CELF	= 0x00000020,
+	EESR_RRF	= 0x00000010,
+	EESR_RTLF	= 0x00000008,
+	EESR_RTSF	= 0x00000004,
+	EESR_PRE	= 0x00000002,
+	EESR_CERF	= 0x00000001,
 };
 
-
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-# define TX_CHECK (EESR_TC1 | EESR_FTC)
-# define EESR_ERR_CHECK	(EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \
-		| EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI)
-# define TX_ERROR_CEHCK (EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE)
-
-#else
-# define TX_CHECK (EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO)
-# define EESR_ERR_CHECK	(EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \
-		| EESR_RFRMER | EESR_ADE | EESR_TFE | EESR_TDE | EESR_ECI)
-# define TX_ERROR_CEHCK (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE)
-#endif
+#define DEFAULT_TX_CHECK	(EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | \
+				 EESR_RTO)
+#define DEFAULT_EESR_ERR_CHECK	(EESR_TWB | EESR_TABT | EESR_RABT | \
+				 EESR_RDE | EESR_RFRMER | EESR_ADE | \
+				 EESR_TFE | EESR_TDE | EESR_ECI)
+#define DEFAULT_TX_ERROR_CHECK	(EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | \
+				 EESR_TFE)
 
 /* EESIPR */
 enum DMAC_IM_BIT {
@@ -386,12 +457,8 @@
 	FCFTR_RFF0 = 0x00010000, FCFTR_RFD2 = 0x00000004,
 	FCFTR_RFD1 = 0x00000002, FCFTR_RFD0 = 0x00000001,
 };
-#define FIFO_F_D_RFF	(FCFTR_RFF2|FCFTR_RFF1|FCFTR_RFF0)
-#ifndef CONFIG_CPU_SUBTYPE_SH7619
-#define FIFO_F_D_RFD	(FCFTR_RFD2|FCFTR_RFD1|FCFTR_RFD0)
-#else
-#define FIFO_F_D_RFD	(FCFTR_RFD0)
-#endif
+#define DEFAULT_FIFO_F_D_RFF	(FCFTR_RFF2 | FCFTR_RFF1 | FCFTR_RFF0)
+#define DEFAULT_FIFO_F_D_RFD	(FCFTR_RFD2 | FCFTR_RFD1 | FCFTR_RFD0)
 
 /* Transfer descriptor bit */
 enum TD_STS_BIT {
@@ -404,60 +471,38 @@
 #define TD_TFP	(TD_TFP1|TD_TFP0)
 
 /* RMCR */
-enum RECV_RST_BIT { RMCR_RST = 0x01, };
+#define DEFAULT_RMCR_VALUE	0x00000000
+
 /* ECMR */
 enum FELIC_MODE_BIT {
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
 	ECMR_TRCCM = 0x04000000, ECMR_RCSC = 0x00800000,
 	ECMR_DPAD = 0x00200000, ECMR_RZPF = 0x00100000,
-#endif
 	ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000,
 	ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000,
 	ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020,
-	ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004, ECMR_DM = 0x00000002,
-	ECMR_PRM = 0x00000001,
+	ECMR_RTM = 0x00000010, ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004,
+	ECMR_DM = 0x00000002, ECMR_PRM = 0x00000001,
 };
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-#define ECMR_CHG_DM	(ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF |\
-			ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT)
-#elif CONFIG_CPU_SUBTYPE_SH7619
-#define ECMR_CHG_DM	(ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF)
-#else
-#define ECMR_CHG_DM	(ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT)
-#endif
-
 /* ECSR */
 enum ECSR_STATUS_BIT {
-#ifndef CONFIG_CPU_SUBTYPE_SH7763
 	ECSR_BRCRX = 0x20, ECSR_PSRTO = 0x10,
-#endif
 	ECSR_LCHNG = 0x04,
 	ECSR_MPD = 0x02, ECSR_ICD = 0x01,
 };
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-# define ECSR_INIT (ECSR_ICD | ECSIPR_MPDIP)
-#else
-# define ECSR_INIT (ECSR_BRCRX | ECSR_PSRTO | \
-			ECSR_LCHNG | ECSR_ICD | ECSIPR_MPDIP)
-#endif
+#define DEFAULT_ECSR_INIT	(ECSR_BRCRX | ECSR_PSRTO | ECSR_LCHNG | \
+				 ECSR_ICD | ECSIPR_MPDIP)
 
 /* ECSIPR */
 enum ECSIPR_STATUS_MASK_BIT {
-#ifndef CONFIG_CPU_SUBTYPE_SH7763
 	ECSIPR_BRCRXIP = 0x20, ECSIPR_PSRTOIP = 0x10,
-#endif
 	ECSIPR_LCHNGIP = 0x04,
 	ECSIPR_MPDIP = 0x02, ECSIPR_ICDIP = 0x01,
 };
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-# define ECSIPR_INIT (ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP)
-#else
-# define ECSIPR_INIT (ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | \
-				ECSIPR_ICDIP | ECSIPR_MPDIP)
-#endif
+#define DEFAULT_ECSIPR_INIT	(ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | \
+				 ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP)
 
 /* APR */
 enum APR_BIT {
@@ -483,23 +528,12 @@
 	RPADIR_PADR = 0x0003f,
 };
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-# define RPADIR_INIT (0x00)
-#else
-# define RPADIR_INIT (RPADIR_PADS1)
-#endif
-
 /* RFLR */
 #define RFLR_VALUE 0x1000
 
 /* FDR */
-enum FIFO_SIZE_BIT {
-#ifndef CONFIG_CPU_SUBTYPE_SH7619
-	FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
-#else
-	FIFO_SIZE_T = 0x00000100, FIFO_SIZE_R = 0x00000001,
-#endif
-};
+#define DEFAULT_FDR_INIT	0x00000707
+
 enum phy_offsets {
 	PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3,
 	PHY_ANA = 4, PHY_ANL = 5, PHY_ANE = 6,
@@ -633,7 +667,43 @@
 	u32 pad0;		/* padding data */
 } __attribute__((aligned(2), packed));
 
+/* This structure is used by each CPU dependency handling. */
+struct sh_eth_cpu_data {
+	/* optional functions */
+	void (*chip_reset)(struct net_device *ndev);
+	void (*set_duplex)(struct net_device *ndev);
+	void (*set_rate)(struct net_device *ndev);
+
+	/* mandatory initialize value */
+	unsigned long eesipr_value;
+
+	/* optional initialize value */
+	unsigned long ecsr_value;
+	unsigned long ecsipr_value;
+	unsigned long fdr_value;
+	unsigned long fcftr_value;
+	unsigned long rpadir_value;
+	unsigned long rmcr_value;
+
+	/* interrupt checking mask */
+	unsigned long tx_check;
+	unsigned long eesr_err_check;
+	unsigned long tx_error_check;
+
+	/* hardware features */
+	unsigned no_psr:1;		/* EtherC DO NOT have PSR */
+	unsigned apr:1;			/* EtherC have APR */
+	unsigned mpr:1;			/* EtherC have MPR */
+	unsigned tpauser:1;		/* EtherC have TPAUSER */
+	unsigned bculr:1;		/* EtherC have BCULR */
+	unsigned hw_swap:1;		/* E-DMAC have DE bit in EDMR */
+	unsigned rpadir:1;		/* E-DMAC have RPADIR */
+	unsigned no_trimd:1;		/* E-DMAC DO NOT have TRIMD */
+	unsigned no_ade:1;	/* E-DMAC DO NOT have ADE bit in EESR */
+};
+
 struct sh_eth_private {
+	struct sh_eth_cpu_data *cd;
 	dma_addr_t rx_desc_dma;
 	dma_addr_t tx_desc_dma;
 	struct sh_eth_rxdesc *rx_ring;
@@ -661,11 +731,7 @@
 	struct net_device_stats tsu_stats;	/* TSU forward status */
 };
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-/* SH7763 has endian control register */
-#define swaps(x, y)
-#else
-static void swaps(char *src, int len)
+static inline void sh_eth_soft_swap(char *src, int len)
 {
 #ifdef __LITTLE_ENDIAN__
 	u32 *p = (u32 *)src;
@@ -676,5 +742,5 @@
 		*p = swab32(*p);
 #endif
 }
-#endif /* CONFIG_CPU_SUBTYPE_SH7763 */
-#endif
+
+#endif	/* #ifndef __SH_ETH_H__ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/sis190.c linux-libre-2.6.31-gnu/drivers/net/sis190.c
--- linux-libre-2.6.30-gnu/drivers/net/sis190.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sis190.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,7 @@
 #define PHY_ID_ANY		0x1f
 #define MII_REG_ANY		0x1f
 
-#define DRV_VERSION		"1.2"
+#define DRV_VERSION		"1.3"
 #define DRV_NAME		"sis190"
 #define SIS190_DRIVER_NAME	DRV_NAME " Gigabit Ethernet driver " DRV_VERSION
 #define PFX DRV_NAME ": "
@@ -317,6 +317,7 @@
         unsigned int type;
 	u32 feature;
 } mii_chip_table[] = {
+	{ "Atheros PHY",          { 0x004d, 0xd010 }, LAN, 0 },
 	{ "Atheros PHY AR8012",   { 0x004d, 0xd020 }, LAN, 0 },
 	{ "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
 	{ "Broadcom PHY AC131",   { 0x0143, 0xbc70 }, LAN, 0 },
@@ -347,7 +348,7 @@
 	u32 msg_enable;
 } debug = { -1 };
 
-MODULE_DESCRIPTION("SiS sis190 Gigabit Ethernet driver");
+MODULE_DESCRIPTION("SiS sis190/191 Gigabit Ethernet driver");
 module_param(rx_copybreak, int, 0);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param_named(debug, debug.msg_enable, int, 0);
@@ -539,8 +540,8 @@
 	if (!skb)
 		goto out;
 
-	pci_dma_sync_single_for_device(tp->pci_dev, addr, pkt_size,
-				       PCI_DMA_FROMDEVICE);
+	pci_dma_sync_single_for_cpu(tp->pci_dev, addr, tp->rx_buf_sz,
+				PCI_DMA_FROMDEVICE);
 	skb_reserve(skb, 2);
 	skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
 	*sk_buff = skb;
@@ -942,9 +943,9 @@
 			u32 ctl;
 			const char *msg;
 		} reg31[] = {
-			{ LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000,
+			{ LPA_1000FULL, 0x07000c00 | 0x00001000,
 				"1000 Mbps Full Duplex" },
-			{ LPA_1000XHALF | LPA_SLCT, 0x07000c00,
+			{ LPA_1000HALF, 0x07000c00,
 				"1000 Mbps Half Duplex" },
 			{ LPA_100FULL, 0x04000800 | 0x00001000,
 				"100 Mbps Full Duplex" },
@@ -955,22 +956,35 @@
 			{ LPA_10HALF, 0x04000400,
 				"10 Mbps Half Duplex" },
 			{ 0, 0x04000400, "unknown" }
- 		}, *p;
-		u16 adv;
+		}, *p = NULL;
+		u16 adv, autoexp, gigadv, gigrec;
 
 		val = mdio_read(ioaddr, phy_id, 0x1f);
 		net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val);
 
 		val = mdio_read(ioaddr, phy_id, MII_LPA);
 		adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
-		net_link(tp, KERN_INFO "%s: mii lpa = %04x adv = %04x.\n",
-			 dev->name, val, adv);
+		autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION);
+		net_link(tp, KERN_INFO "%s: mii lpa=%04x adv=%04x exp=%04x.\n",
+			 dev->name, val, adv, autoexp);
 
-		val &= adv;
+		if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) {
+			/* check for gigabit speed */
+			gigadv = mdio_read(ioaddr, phy_id, MII_CTRL1000);
+			gigrec = mdio_read(ioaddr, phy_id, MII_STAT1000);
+			val = (gigadv & (gigrec >> 2));
+			if (val & ADVERTISE_1000FULL)
+				p = reg31;
+			else if (val & ADVERTISE_1000HALF)
+				p = reg31 + 1;
+		}
+		if (!p) {
+			val &= adv;
 
-		for (p = reg31; p->val; p++) {
-			if ((val & p->val) == p->val)
-				break;
+			for (p = reg31; p->val; p++) {
+				if ((val & p->val) == p->val)
+					break;
+			}
 		}
 
 		p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
@@ -1204,8 +1218,6 @@
 
 	SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
 
-	dev->trans_start = jiffies;
-
 	dirty_tx = tp->dirty_tx;
 	if ((tp->cur_tx - NUM_TX_DESC) == dirty_tx) {
 		netif_stop_queue(dev);
@@ -1269,7 +1281,7 @@
 		else if (phy_lan)
 			phy_default = phy_lan;
 		else
-			phy_default = list_entry(&tp->first_phy,
+			phy_default = list_first_entry(&tp->first_phy,
 						 struct sis190_phy, list);
 	}
 
@@ -1315,12 +1327,15 @@
 			((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
 				LAN : HOME) : p->type;
 		tp->features |= p->feature;
-	} else
+		net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n",
+			pci_name(tp->pci_dev), p->name, phy_id);
+	} else {
 		phy->type = UNKNOWN;
-
-	net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n",
-		  pci_name(tp->pci_dev),
-		  (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id);
+		net_probe(tp, KERN_INFO
+			"%s: unknown PHY 0x%x:0x%x transceiver at address %d\n",
+			pci_name(tp->pci_dev),
+			phy->id[0], (phy->id[1] & 0xfff0), phy_id);
+	}
 }
 
 static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
diff -druN linux-libre-2.6.30-gnu/drivers/net/sis900.c linux-libre-2.6.31-gnu/drivers/net/sis900.c
--- linux-libre-2.6.30-gnu/drivers/net/sis900.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sis900.c	2009-09-09 18:13:59.000000000 -0400
@@ -1584,7 +1584,7 @@
 	/* Don't transmit data before the complete of auto-negotiation */
 	if(!sis_priv->autong_complete){
 		netif_stop_queue(net_dev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	spin_lock_irqsave(&sis_priv->lock, flags);
diff -druN linux-libre-2.6.30-gnu/drivers/net/skfp/h/smt.h linux-libre-2.6.31-gnu/drivers/net/skfp/h/smt.h
--- linux-libre-2.6.30-gnu/drivers/net/skfp/h/smt.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/skfp/h/smt.h	2009-09-09 18:13:59.000000000 -0400
@@ -413,7 +413,7 @@
 #define SMT_RDF_SUCCESS	0x00000003	/* success (PMF) */
 #define SMT_RDF_BADSET	0x00000004	/* bad set count (PMF) */
 #define SMT_RDF_ILLEGAL 0x00000005	/* read only (PMF) */
-#define SMT_RDF_NOPARAM	0x6		/* paramter not supported (PMF) */
+#define SMT_RDF_NOPARAM	0x6		/* parameter not supported (PMF) */
 #define SMT_RDF_RANGE	0x8		/* out of range */
 #define SMT_RDF_AUTHOR	0x9		/* not autohorized */
 #define SMT_RDF_LENGTH	0x0a		/* length error */
diff -druN linux-libre-2.6.30-gnu/drivers/net/skfp/skfddi.c linux-libre-2.6.31-gnu/drivers/net/skfp/skfddi.c
--- linux-libre-2.6.30-gnu/drivers/net/skfp/skfddi.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/skfp/skfddi.c	2009-09-09 18:13:59.000000000 -0400
@@ -159,12 +159,6 @@
 
 static int num_boards;	/* total number of adapters configured */
 
-#ifdef DRIVERDEBUG
-#define PRINTK(s, args...) printk(s, ## args)
-#else
-#define PRINTK(s, args...)
-#endif				// DRIVERDEBUG
-
 static const struct net_device_ops skfp_netdev_ops = {
 	.ndo_open		= skfp_open,
 	.ndo_stop		= skfp_close,
@@ -213,7 +207,7 @@
 	void __iomem *mem;
 	int err;
 
-	PRINTK(KERN_INFO "entering skfp_init_one\n");
+	pr_debug(KERN_INFO "entering skfp_init_one\n");
 
 	if (num_boards == 0) 
 		printk("%s\n", boot_msg);
@@ -389,7 +383,7 @@
 	skfddi_priv *bp = &smc->os;
 	int err = -EIO;
 
-	PRINTK(KERN_INFO "entering skfp_driver_init\n");
+	pr_debug(KERN_INFO "entering skfp_driver_init\n");
 
 	// set the io address in private structures
 	bp->base_addr = dev->base_addr;
@@ -409,7 +403,7 @@
 
 	// Determine the required size of the 'shared' memory area.
 	bp->SharedMemSize = mac_drv_check_space();
-	PRINTK(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize);
+	pr_debug(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize);
 	if (bp->SharedMemSize > 0) {
 		bp->SharedMemSize += 16;	// for descriptor alignment
 
@@ -433,13 +427,13 @@
 
 	card_stop(smc);		// Reset adapter.
 
-	PRINTK(KERN_INFO "mac_drv_init()..\n");
+	pr_debug(KERN_INFO "mac_drv_init()..\n");
 	if (mac_drv_init(smc) != 0) {
-		PRINTK(KERN_INFO "mac_drv_init() failed.\n");
+		pr_debug(KERN_INFO "mac_drv_init() failed.\n");
 		goto fail;
 	}
 	read_address(smc, NULL);
-	PRINTK(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n",
+	pr_debug(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n",
 	       smc->hw.fddi_canon_addr.a[0],
 	       smc->hw.fddi_canon_addr.a[1],
 	       smc->hw.fddi_canon_addr.a[2],
@@ -495,7 +489,7 @@
 	struct s_smc *smc = netdev_priv(dev);
 	int err;
 
-	PRINTK(KERN_INFO "entering skfp_open\n");
+	pr_debug(KERN_INFO "entering skfp_open\n");
 	/* Register IRQ - support shared interrupts by passing device ptr */
 	err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
 			  dev->name, dev);
@@ -868,12 +862,12 @@
 	/* Enable promiscuous mode, if necessary */
 	if (dev->flags & IFF_PROMISC) {
 		mac_drv_rx_mode(smc, RX_ENABLE_PROMISC);
-		PRINTK(KERN_INFO "PROMISCUOUS MODE ENABLED\n");
+		pr_debug(KERN_INFO "PROMISCUOUS MODE ENABLED\n");
 	}
 	/* Else, update multicast address table */
 	else {
 		mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
-		PRINTK(KERN_INFO "PROMISCUOUS MODE DISABLED\n");
+		pr_debug(KERN_INFO "PROMISCUOUS MODE DISABLED\n");
 
 		// Reset all MC addresses
 		mac_clear_multicast(smc);
@@ -881,7 +875,7 @@
 
 		if (dev->flags & IFF_ALLMULTI) {
 			mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
-			PRINTK(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+			pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
 		} else if (dev->mc_count > 0) {
 			if (dev->mc_count <= FPMAX_MULTICAST) {
 				/* use exact filtering */
@@ -894,12 +888,12 @@
 							  (struct fddi_addr *)dmi->dmi_addr, 
 							  1);
 
-					PRINTK(KERN_INFO "ENABLE MC ADDRESS:");
-					PRINTK(" %02x %02x %02x ",
+					pr_debug(KERN_INFO "ENABLE MC ADDRESS:");
+					pr_debug(" %02x %02x %02x ",
 					       dmi->dmi_addr[0],
 					       dmi->dmi_addr[1],
 					       dmi->dmi_addr[2]);
-					PRINTK("%02x %02x %02x\n",
+					pr_debug("%02x %02x %02x\n",
 					       dmi->dmi_addr[3],
 					       dmi->dmi_addr[4],
 					       dmi->dmi_addr[5]);
@@ -909,11 +903,11 @@
 			} else {	// more MC addresses than HW supports
 
 				mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
-				PRINTK(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+				pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
 			}
 		} else {	// no MC addresses
 
-			PRINTK(KERN_INFO "DISABLE ALL MC ADDRESSES\n");
+			pr_debug(KERN_INFO "DISABLE ALL MC ADDRESSES\n");
 		}
 
 		/* Update adapter filters */
@@ -1067,7 +1061,7 @@
 	struct s_smc *smc = netdev_priv(dev);
 	skfddi_priv *bp = &smc->os;
 
-	PRINTK(KERN_INFO "skfp_send_pkt\n");
+	pr_debug(KERN_INFO "skfp_send_pkt\n");
 
 	/*
 	 * Verify that incoming transmit request is OK
@@ -1088,7 +1082,7 @@
 	if (bp->QueueSkb == 0) {	// return with tbusy set: queue full
 
 		netif_stop_queue(dev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	bp->QueueSkb--;
 	skb_queue_tail(&bp->SendSkbQueue, skb);
@@ -1137,13 +1131,13 @@
 
 	int frame_status;	// HWM tx frame status.
 
-	PRINTK(KERN_INFO "send queued packets\n");
+	pr_debug(KERN_INFO "send queued packets\n");
 	for (;;) {
 		// send first buffer from queue
 		skb = skb_dequeue(&bp->SendSkbQueue);
 
 		if (!skb) {
-			PRINTK(KERN_INFO "queue empty\n");
+			pr_debug(KERN_INFO "queue empty\n");
 			return;
 		}		// queue empty !
 
@@ -1174,11 +1168,11 @@
 
 			if ((frame_status & RING_DOWN) != 0) {
 				// Ring is down.
-				PRINTK("Tx attempt while ring down.\n");
+				pr_debug("Tx attempt while ring down.\n");
 			} else if ((frame_status & OUT_OF_TXD) != 0) {
-				PRINTK("%s: out of TXDs.\n", bp->dev->name);
+				pr_debug("%s: out of TXDs.\n", bp->dev->name);
 			} else {
-				PRINTK("%s: out of transmit resources",
+				pr_debug("%s: out of transmit resources",
 					bp->dev->name);
 			}
 
@@ -1255,7 +1249,7 @@
 static void ResetAdapter(struct s_smc *smc)
 {
 
-	PRINTK(KERN_INFO "[fddi: ResetAdapter]\n");
+	pr_debug(KERN_INFO "[fddi: ResetAdapter]\n");
 
 	// Stop the adapter.
 
@@ -1301,7 +1295,7 @@
 {
 	skfddi_priv *bp = &smc->os;
 
-	PRINTK(KERN_INFO "[llc_restart_tx]\n");
+	pr_debug(KERN_INFO "[llc_restart_tx]\n");
 
 	// Try to send queued packets
 	spin_unlock(&bp->DriverLock);
@@ -1331,7 +1325,7 @@
 {
 	void *virt;
 
-	PRINTK(KERN_INFO "mac_drv_get_space (%d bytes), ", size);
+	pr_debug(KERN_INFO "mac_drv_get_space (%d bytes), ", size);
 	virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);
 
 	if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {
@@ -1340,9 +1334,9 @@
 	}
 	smc->os.SharedMemHeap += size;	// Move heap pointer.
 
-	PRINTK(KERN_INFO "mac_drv_get_space end\n");
-	PRINTK(KERN_INFO "virt addr: %lx\n", (ulong) virt);
-	PRINTK(KERN_INFO "bus  addr: %lx\n", (ulong)
+	pr_debug(KERN_INFO "mac_drv_get_space end\n");
+	pr_debug(KERN_INFO "virt addr: %lx\n", (ulong) virt);
+	pr_debug(KERN_INFO "bus  addr: %lx\n", (ulong)
 	       (smc->os.SharedMemDMA +
 		((char *) virt - (char *)smc->os.SharedMemAddr)));
 	return (virt);
@@ -1372,7 +1366,7 @@
 
 	char *virt;
 
-	PRINTK(KERN_INFO "mac_drv_get_desc_mem\n");
+	pr_debug(KERN_INFO "mac_drv_get_desc_mem\n");
 
 	// Descriptor memory must be aligned on 16-byte boundary.
 
@@ -1381,8 +1375,8 @@
 	size = (u_int) (16 - (((unsigned long) virt) & 15UL));
 	size = size % 16;
 
-	PRINTK("Allocate %u bytes alignment gap ", size);
-	PRINTK("for descriptor memory.\n");
+	pr_debug("Allocate %u bytes alignment gap ", size);
+	pr_debug("for descriptor memory.\n");
 
 	if (!mac_drv_get_space(smc, size)) {
 		printk("fddi: Unable to align descriptor memory.\n");
@@ -1516,11 +1510,11 @@
 {
 	struct sk_buff *skb;
 
-	PRINTK(KERN_INFO "entering mac_drv_tx_complete\n");
+	pr_debug(KERN_INFO "entering mac_drv_tx_complete\n");
 	// Check if this TxD points to a skb
 
 	if (!(skb = txd->txd_os.skb)) {
-		PRINTK("TXD with no skb assigned.\n");
+		pr_debug("TXD with no skb assigned.\n");
 		return;
 	}
 	txd->txd_os.skb = NULL;
@@ -1536,7 +1530,7 @@
 	// free the skb
 	dev_kfree_skb_irq(skb);
 
-	PRINTK(KERN_INFO "leaving mac_drv_tx_complete\n");
+	pr_debug(KERN_INFO "leaving mac_drv_tx_complete\n");
 }				// mac_drv_tx_complete
 
 
@@ -1603,7 +1597,7 @@
 	unsigned short ri;
 	u_int RifLength;
 
-	PRINTK(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len);
+	pr_debug(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len);
 	if (frag_count != 1) {	// This is not allowed to happen.
 
 		printk("fddi: Multi-fragment receive!\n");
@@ -1612,7 +1606,7 @@
 	}
 	skb = rxd->rxd_os.skb;
 	if (!skb) {
-		PRINTK(KERN_INFO "No skb in rxd\n");
+		pr_debug(KERN_INFO "No skb in rxd\n");
 		smc->os.MacStat.gen.rx_errors++;
 		goto RequeueRxd;
 	}
@@ -1642,7 +1636,7 @@
 	else {
 		int n;
 // goos: RIF removal has still to be tested
-		PRINTK(KERN_INFO "RIF found\n");
+		pr_debug(KERN_INFO "RIF found\n");
 		// Get RIF length from Routing Control (RC) field.
 		cp = virt + FDDI_MAC_HDR_LEN;	// Point behind MAC header.
 
@@ -1687,7 +1681,7 @@
 	return;
 
       RequeueRxd:
-	PRINTK(KERN_INFO "Rx: re-queue RXD.\n");
+	pr_debug(KERN_INFO "Rx: re-queue RXD.\n");
 	mac_drv_requeue_rxd(smc, rxd, frag_count);
 	smc->os.MacStat.gen.rx_errors++;	// Count receive packets
 						// not indicated.
@@ -1736,7 +1730,7 @@
 		skb = src_rxd->rxd_os.skb;
 		if (skb == NULL) {	// this should not happen
 
-			PRINTK("Requeue with no skb in rxd!\n");
+			pr_debug("Requeue with no skb in rxd!\n");
 			skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
 			if (skb) {
 				// we got a skb
@@ -1751,7 +1745,7 @@
 				rxd->rxd_os.dma_addr = b_addr;
 			} else {
 				// no skb available, use local buffer
-				PRINTK("Queueing invalid buffer!\n");
+				pr_debug("Queueing invalid buffer!\n");
 				rxd->rxd_os.skb = NULL;
 				v_addr = smc->os.LocalRxBuffer;
 				b_addr = smc->os.LocalRxBufferDMA;
@@ -1798,7 +1792,7 @@
 	struct sk_buff *skb;
 	volatile struct s_smt_fp_rxd *rxd;
 
-	PRINTK(KERN_INFO "entering mac_drv_fill_rxd\n");
+	pr_debug(KERN_INFO "entering mac_drv_fill_rxd\n");
 
 	// Walk through the list of free receive buffers, passing receive
 	// buffers to the HWM as long as RXDs are available.
@@ -1806,7 +1800,7 @@
 	MaxFrameSize = smc->os.MaxFrameSize;
 	// Check if there is any RXD left.
 	while (HWM_GET_RX_FREE(smc) > 0) {
-		PRINTK(KERN_INFO ".\n");
+		pr_debug(KERN_INFO ".\n");
 
 		rxd = HWM_GET_CURR_RXD(smc);
 		skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
@@ -1826,7 +1820,7 @@
 			// keep the receiver running in hope of better times.
 			// Multiple descriptors may point to this local buffer,
 			// so data in it must be considered invalid.
-			PRINTK("Queueing invalid buffer!\n");
+			pr_debug("Queueing invalid buffer!\n");
 			v_addr = smc->os.LocalRxBuffer;
 			b_addr = smc->os.LocalRxBufferDMA;
 		}
@@ -1837,7 +1831,7 @@
 		hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
 			    FIRST_FRAG | LAST_FRAG);
 	}
-	PRINTK(KERN_INFO "leaving mac_drv_fill_rxd\n");
+	pr_debug(KERN_INFO "leaving mac_drv_fill_rxd\n");
 }				// mac_drv_fill_rxd
 
 
@@ -1863,7 +1857,7 @@
 
 	struct sk_buff *skb;
 
-	PRINTK("entering mac_drv_clear_rxd\n");
+	pr_debug("entering mac_drv_clear_rxd\n");
 
 	if (frag_count != 1)	// This is not allowed to happen.
 
@@ -1919,19 +1913,19 @@
 {
 	struct sk_buff *skb;
 
-	PRINTK("entering mac_drv_rx_init(len=%d)\n", len);
+	pr_debug("entering mac_drv_rx_init(len=%d)\n", len);
 
 	// "Received" a SMT or NSA frame of the local SMT.
 
 	if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) {
-		PRINTK("fddi: Discard invalid local SMT frame\n");
-		PRINTK("  len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
+		pr_debug("fddi: Discard invalid local SMT frame\n");
+		pr_debug("  len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
 		       len, la_len, (unsigned long) look_ahead);
 		return (0);
 	}
 	skb = alloc_skb(len + 3, GFP_ATOMIC);
 	if (!skb) {
-		PRINTK("fddi: Local SMT: skb memory exhausted.\n");
+		pr_debug("fddi: Local SMT: skb memory exhausted.\n");
 		return (0);
 	}
 	skb_reserve(skb, 3);
@@ -1981,40 +1975,40 @@
  ************************/
 void ring_status_indication(struct s_smc *smc, u_long status)
 {
-	PRINTK("ring_status_indication( ");
+	pr_debug("ring_status_indication( ");
 	if (status & RS_RES15)
-		PRINTK("RS_RES15 ");
+		pr_debug("RS_RES15 ");
 	if (status & RS_HARDERROR)
-		PRINTK("RS_HARDERROR ");
+		pr_debug("RS_HARDERROR ");
 	if (status & RS_SOFTERROR)
-		PRINTK("RS_SOFTERROR ");
+		pr_debug("RS_SOFTERROR ");
 	if (status & RS_BEACON)
-		PRINTK("RS_BEACON ");
+		pr_debug("RS_BEACON ");
 	if (status & RS_PATHTEST)
-		PRINTK("RS_PATHTEST ");
+		pr_debug("RS_PATHTEST ");
 	if (status & RS_SELFTEST)
-		PRINTK("RS_SELFTEST ");
+		pr_debug("RS_SELFTEST ");
 	if (status & RS_RES9)
-		PRINTK("RS_RES9 ");
+		pr_debug("RS_RES9 ");
 	if (status & RS_DISCONNECT)
-		PRINTK("RS_DISCONNECT ");
+		pr_debug("RS_DISCONNECT ");
 	if (status & RS_RES7)
-		PRINTK("RS_RES7 ");
+		pr_debug("RS_RES7 ");
 	if (status & RS_DUPADDR)
-		PRINTK("RS_DUPADDR ");
+		pr_debug("RS_DUPADDR ");
 	if (status & RS_NORINGOP)
-		PRINTK("RS_NORINGOP ");
+		pr_debug("RS_NORINGOP ");
 	if (status & RS_VERSION)
-		PRINTK("RS_VERSION ");
+		pr_debug("RS_VERSION ");
 	if (status & RS_STUCKBYPASSS)
-		PRINTK("RS_STUCKBYPASSS ");
+		pr_debug("RS_STUCKBYPASSS ");
 	if (status & RS_EVENT)
-		PRINTK("RS_EVENT ");
+		pr_debug("RS_EVENT ");
 	if (status & RS_RINGOPCHANGE)
-		PRINTK("RS_RINGOPCHANGE ");
+		pr_debug("RS_RINGOPCHANGE ");
 	if (status & RS_RES0)
-		PRINTK("RS_RES0 ");
-	PRINTK("]\n");
+		pr_debug("RS_RES0 ");
+	pr_debug("]\n");
 }				// ring_status_indication
 
 
@@ -2057,17 +2051,17 @@
 {
 //      BOOLEAN RingIsUp ;
 
-	PRINTK(KERN_INFO "smt_stat_counter\n");
+	pr_debug(KERN_INFO "smt_stat_counter\n");
 	switch (stat) {
 	case 0:
-		PRINTK(KERN_INFO "Ring operational change.\n");
+		pr_debug(KERN_INFO "Ring operational change.\n");
 		break;
 	case 1:
-		PRINTK(KERN_INFO "Receive fifo overflow.\n");
+		pr_debug(KERN_INFO "Receive fifo overflow.\n");
 		smc->os.MacStat.gen.rx_errors++;
 		break;
 	default:
-		PRINTK(KERN_INFO "Unknown status (%d).\n", stat);
+		pr_debug(KERN_INFO "Unknown status (%d).\n", stat);
 		break;
 	}
 }				// smt_stat_counter
@@ -2123,10 +2117,10 @@
 		s = "SC11_C_WRAP_S";
 		break;
 	default:
-		PRINTK(KERN_INFO "cfm_state_change: unknown %d\n", c_state);
+		pr_debug(KERN_INFO "cfm_state_change: unknown %d\n", c_state);
 		return;
 	}
-	PRINTK(KERN_INFO "cfm_state_change: %s\n", s);
+	pr_debug(KERN_INFO "cfm_state_change: %s\n", s);
 #endif				// DRIVERDEBUG
 }				// cfm_state_change
 
@@ -2181,7 +2175,7 @@
 		s = "unknown";
 		break;
 	}
-	PRINTK(KERN_INFO "ecm_state_change: %s\n", s);
+	pr_debug(KERN_INFO "ecm_state_change: %s\n", s);
 #endif				//DRIVERDEBUG
 }				// ecm_state_change
 
@@ -2236,7 +2230,7 @@
 		s = "unknown";
 		break;
 	}
-	PRINTK(KERN_INFO "[rmt_state_change: %s]\n", s);
+	pr_debug(KERN_INFO "[rmt_state_change: %s]\n", s);
 #endif				// DRIVERDEBUG
 }				// rmt_state_change
 
@@ -2256,7 +2250,7 @@
  ************************/
 void drv_reset_indication(struct s_smc *smc)
 {
-	PRINTK(KERN_INFO "entering drv_reset_indication\n");
+	pr_debug(KERN_INFO "entering drv_reset_indication\n");
 
 	smc->os.ResetRequested = TRUE;	// Set flag.
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/skge.c linux-libre-2.6.31-gnu/drivers/net/skge.c
--- linux-libre-2.6.30-gnu/drivers/net/skge.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/skge.c	2009-09-09 18:13:59.000000000 -0400
@@ -2837,8 +2837,6 @@
 		netif_stop_queue(dev);
 	}
 
-	dev->trans_start = jiffies;
-
 	return NETDEV_TX_OK;
 }
 
@@ -3856,8 +3854,10 @@
 	skge->speed = -1;
 	skge->advertising = skge_supported_modes(hw);
 
-	if (device_may_wakeup(&hw->pdev->dev))
+	if (device_can_wakeup(&hw->pdev->dev)) {
 		skge->wol = wol_supported(hw) & WAKE_MAGIC;
+		device_set_wakeup_enable(&hw->pdev->dev, skge->wol);
+	}
 
 	hw->dev[port] = dev;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/sky2.c linux-libre-2.6.31-gnu/drivers/net/sky2.c
--- linux-libre-2.6.30-gnu/drivers/net/sky2.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sky2.c	2009-09-09 18:13:59.000000000 -0400
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.22"
+#define DRV_VERSION		"1.23"
 #define PFX			DRV_NAME " "
 
 /*
@@ -65,9 +65,9 @@
 #define RX_DEF_PENDING		RX_MAX_PENDING
 
 #define TX_RING_SIZE		512
-#define TX_DEF_PENDING		(TX_RING_SIZE - 1)
-#define TX_MIN_PENDING		64
+#define TX_DEF_PENDING		128
 #define MAX_SKB_TX_LE		(4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS)
+#define TX_MIN_PENDING		(MAX_SKB_TX_LE+1)
 
 #define STATUS_RING_SIZE	2048	/* 2 ports * (TX + 2*RX) */
 #define STATUS_LE_BYTES		(STATUS_RING_SIZE*sizeof(struct sky2_status_le))
@@ -1169,6 +1169,7 @@
 			re->skb = NULL;
 		}
 	}
+	skb_queue_purge(&sky2->rx_recycle);
 }
 
 /* Basic MII support */
@@ -1245,6 +1246,12 @@
 }
 #endif
 
+/* Amount of required worst case padding in rx buffer */
+static inline unsigned sky2_rx_pad(const struct sky2_hw *hw)
+{
+	return (hw->flags & SKY2_HW_RAM_BUFFER) ? 8 : 2;
+}
+
 /*
  * Allocate an skb for receiving. If the MTU is large enough
  * make the skb non-linear with a fragment list of pages.
@@ -1254,6 +1261,13 @@
 	struct sk_buff *skb;
 	int i;
 
+	skb = __skb_dequeue(&sky2->rx_recycle);
+	if (!skb)
+		skb = netdev_alloc_skb(sky2->netdev, sky2->rx_data_size
+				       + sky2_rx_pad(sky2->hw));
+	if (!skb)
+		goto nomem;
+
 	if (sky2->hw->flags & SKY2_HW_RAM_BUFFER) {
 		unsigned char *start;
 		/*
@@ -1262,18 +1276,10 @@
 		 * The buffer returned from netdev_alloc_skb is
 		 * aligned except if slab debugging is enabled.
 		 */
-		skb = netdev_alloc_skb(sky2->netdev, sky2->rx_data_size + 8);
-		if (!skb)
-			goto nomem;
 		start = PTR_ALIGN(skb->data, 8);
 		skb_reserve(skb, start - skb->data);
-	} else {
-		skb = netdev_alloc_skb(sky2->netdev,
-				       sky2->rx_data_size + NET_IP_ALIGN);
-		if (!skb)
-			goto nomem;
+	} else
 		skb_reserve(skb, NET_IP_ALIGN);
-	}
 
 	for (i = 0; i < sky2->rx_nfrags; i++) {
 		struct page *page = alloc_page(GFP_ATOMIC);
@@ -1350,6 +1356,8 @@
 
 	sky2->rx_data_size = size;
 
+	skb_queue_head_init(&sky2->rx_recycle);
+
 	/* Fill Rx ring */
 	for (i = 0; i < sky2->rx_pending; i++) {
 		re = sky2->rx_ring + i;
@@ -1480,6 +1488,8 @@
 	sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
 #endif
 
+	sky2->restarting = 0;
+
 	err = sky2_rx_start(sky2);
 	if (err)
 		goto err_out;
@@ -1488,9 +1498,13 @@
 	imask = sky2_read32(hw, B0_IMSK);
 	imask |= portirq_msk[port];
 	sky2_write32(hw, B0_IMSK, imask);
+	sky2_read32(hw, B0_IMSK);
 
 	sky2_set_multicast(dev);
 
+	/* wake queue incase we are restarting */
+	netif_wake_queue(dev);
+
 	if (netif_msg_ifup(sky2))
 		printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
 	return 0;
@@ -1524,6 +1538,8 @@
 /* Number of list elements available for next tx */
 static inline int tx_avail(const struct sky2_port *sky2)
 {
+	if (unlikely(sky2->restarting))
+		return 0;
 	return sky2->tx_pending - tx_dist(sky2->tx_cons, sky2->tx_prod);
 }
 
@@ -1690,7 +1706,6 @@
 
 	sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod);
 
-	dev->trans_start = jiffies;
 	return NETDEV_TX_OK;
 
 mapping_unwind:
@@ -1757,14 +1772,22 @@
 		}
 
 		if (le->ctrl & EOP) {
+			struct sk_buff *skb = re->skb;
+
 			if (unlikely(netif_msg_tx_done(sky2)))
 				printk(KERN_DEBUG "%s: tx done %u\n",
 				       dev->name, idx);
 
 			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += re->skb->len;
+			dev->stats.tx_bytes += skb->len;
+
+			if (skb_queue_len(&sky2->rx_recycle) < sky2->rx_pending
+			    && skb_recycle_check(skb, sky2->rx_data_size
+						 + sky2_rx_pad(sky2->hw)))
+				__skb_queue_head(&sky2->rx_recycle, skb);
+			else
+				dev_kfree_skb_any(skb);
 
-			dev_kfree_skb_any(re->skb);
 			sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE);
 		}
 	}
@@ -1802,14 +1825,12 @@
 	if (netif_msg_ifdown(sky2))
 		printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
-	/* Disable port IRQ */
-	imask = sky2_read32(hw, B0_IMSK);
-	imask &= ~portirq_msk[port];
-	sky2_write32(hw, B0_IMSK, imask);
-
-	synchronize_irq(hw->pdev->irq);
+	/* explicitly shut off tx incase we're restarting */
+	sky2->restarting = 1;
+	netif_tx_disable(dev);
 
-	sky2_gmac_reset(hw, port);
+	/* Force flow control off */
+	sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
 
 	/* Stop transmitter */
 	sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP);
@@ -1822,9 +1843,6 @@
 	ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
 	gma_write16(hw, port, GM_GP_CTRL, ctrl);
 
-	/* Make sure no packets are pending */
-	napi_synchronize(&hw->napi);
-
 	sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
 
 	/* Workaround shared GMAC reset */
@@ -1850,11 +1868,26 @@
 
 	sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
 
-	sky2_rx_stop(sky2);
-
 	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
 	sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
 
+	/* Force any delayed status interrrupt and NAPI */
+	sky2_write32(hw, STAT_LEV_TIMER_CNT, 0);
+	sky2_write32(hw, STAT_TX_TIMER_CNT, 0);
+	sky2_write32(hw, STAT_ISR_TIMER_CNT, 0);
+	sky2_read8(hw, STAT_ISR_TIMER_CTRL);
+
+	sky2_rx_stop(sky2);
+
+	/* Disable port IRQ */
+	imask = sky2_read32(hw, B0_IMSK);
+	imask &= ~portirq_msk[port];
+	sky2_write32(hw, B0_IMSK, imask);
+	sky2_read32(hw, B0_IMSK);
+
+	synchronize_irq(hw->pdev->irq);
+	napi_synchronize(&hw->napi);
+
 	sky2_phy_power_down(hw, port);
 
 	/* turn off LED's */
@@ -2337,18 +2370,52 @@
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 
-	if (netif_running(dev)) {
+	if (likely(netif_running(dev) && !sky2->restarting)) {
 		netif_tx_lock(dev);
 		sky2_tx_complete(sky2, last);
 		netif_tx_unlock(dev);
 	}
 }
 
+static inline void sky2_skb_rx(const struct sky2_port *sky2,
+			       u32 status, struct sk_buff *skb)
+{
+#ifdef SKY2_VLAN_TAG_USED
+	u16 vlan_tag = be16_to_cpu(sky2->rx_tag);
+	if (sky2->vlgrp && (status & GMR_FS_VLAN)) {
+		if (skb->ip_summed == CHECKSUM_NONE)
+			vlan_hwaccel_receive_skb(skb, sky2->vlgrp, vlan_tag);
+		else
+			vlan_gro_receive(&sky2->hw->napi, sky2->vlgrp,
+					 vlan_tag, skb);
+		return;
+	}
+#endif
+	if (skb->ip_summed == CHECKSUM_NONE)
+		netif_receive_skb(skb);
+	else
+		napi_gro_receive(&sky2->hw->napi, skb);
+}
+
+static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port,
+				unsigned packets, unsigned bytes)
+{
+	if (packets) {
+		struct net_device *dev = hw->dev[port];
+
+		dev->stats.rx_packets += packets;
+		dev->stats.rx_bytes += bytes;
+		dev->last_rx = jiffies;
+		sky2_rx_update(netdev_priv(dev), rxqaddr[port]);
+	}
+}
+
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
 {
 	int work_done = 0;
-	unsigned rx[2] = { 0, 0 };
+	unsigned int total_bytes[2] = { 0 };
+	unsigned int total_packets[2] = { 0 };
 
 	rmb();
 	do {
@@ -2375,7 +2442,8 @@
 		le->opcode = 0;
 		switch (opcode & ~HW_OWNER) {
 		case OP_RXSTAT:
-			++rx[port];
+			total_packets[port]++;
+			total_bytes[port] += length;
 			skb = sky2_receive(dev, length, status);
 			if (unlikely(!skb)) {
 				dev->stats.rx_dropped++;
@@ -2393,18 +2461,8 @@
 			}
 
 			skb->protocol = eth_type_trans(skb, dev);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += skb->len;
-			dev->last_rx = jiffies;
 
-#ifdef SKY2_VLAN_TAG_USED
-			if (sky2->vlgrp && (status & GMR_FS_VLAN)) {
-				vlan_hwaccel_receive_skb(skb,
-							 sky2->vlgrp,
-							 be16_to_cpu(sky2->rx_tag));
-			} else
-#endif
-				netif_receive_skb(skb);
+			sky2_skb_rx(sky2, status, skb);
 
 			/* Stop after net poll weight */
 			if (++work_done >= to_do)
@@ -2441,7 +2499,7 @@
 			if (likely(status >> 16 == (status & 0xffff))) {
 				skb = sky2->rx_ring[sky2->rx_next].skb;
 				skb->ip_summed = CHECKSUM_COMPLETE;
-				skb->csum = status & 0xffff;
+				skb->csum = le16_to_cpu(status);
 			} else {
 				printk(KERN_NOTICE PFX "%s: hardware receive "
 				       "checksum problem (status = %#x)\n",
@@ -2474,11 +2532,8 @@
 	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
 
 exit_loop:
-	if (rx[0])
-		sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
-
-	if (rx[1])
-		sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
+	sky2_rx_done(hw, 0, total_packets[0], total_bytes[0]);
+	sky2_rx_done(hw, 1, total_packets[1], total_bytes[1]);
 
 	return work_done;
 }
@@ -4239,6 +4294,7 @@
 	spin_lock_init(&sky2->phy_lock);
 	sky2->tx_pending = TX_DEF_PENDING;
 	sky2->rx_pending = RX_DEF_PENDING;
+	sky2->restarting = 0;
 
 	hw->dev[port] = dev;
 
@@ -4365,6 +4421,22 @@
 		goto err_out;
 	}
 
+	/* Get configuration information
+	 * Note: only regular PCI config access once to test for HW issues
+	 *       other PCI access through shared memory for speed and to
+	 *	 avoid MMCONFIG problems.
+	 */
+	err = pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
+	if (err) {
+		dev_err(&pdev->dev, "PCI read config failed\n");
+		goto err_out;
+	}
+
+	if (~reg == 0) {
+		dev_err(&pdev->dev, "PCI configuration read error\n");
+		goto err_out;
+	}
+
 	err = pci_request_regions(pdev, DRV_NAME);
 	if (err) {
 		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
@@ -4390,21 +4462,6 @@
 		}
 	}
 
-	/* Get configuration information
-	 * Note: only regular PCI config access once to test for HW issues
-	 *       other PCI access through shared memory for speed and to
-	 *	 avoid MMCONFIG problems.
-	 */
-	err = pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
-	if (err) {
-		dev_err(&pdev->dev, "PCI read config failed\n");
-		goto err_out_free_regions;
-	}
-
-	/* size of available VPD, only impact sysfs */
-	err = pci_vpd_truncate(pdev, 1ul << (((reg & PCI_VPD_ROM_SZ) >> 14) + 8));
-	if (err)
-		dev_warn(&pdev->dev, "Can't set VPD size\n");
 
 #ifdef __BIG_ENDIAN
 	/* The sk98lin vendor driver uses hardware byte swapping but
diff -druN linux-libre-2.6.30-gnu/drivers/net/sky2.h linux-libre-2.6.31-gnu/drivers/net/sky2.h
--- linux-libre-2.6.30-gnu/drivers/net/sky2.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sky2.h	2009-09-09 18:13:59.000000000 -0400
@@ -2028,6 +2028,7 @@
 	u16		     rx_pending;
 	u16		     rx_data_size;
 	u16		     rx_nfrags;
+	struct sk_buff_head  rx_recycle;
 
 #ifdef SKY2_VLAN_TAG_USED
 	u16		     rx_tag;
@@ -2050,6 +2051,7 @@
 	u8		     duplex;	/* DUPLEX_HALF, DUPLEX_FULL */
 	u8		     rx_csum;
 	u8		     wol;
+	u8		     restarting;
  	enum flow_control    flow_mode;
  	enum flow_control    flow_status;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/smc911x.c linux-libre-2.6.31-gnu/drivers/net/smc911x.c
--- linux-libre-2.6.30-gnu/drivers/net/smc911x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/smc911x.c	2009-09-09 18:13:59.000000000 -0400
@@ -1774,6 +1774,20 @@
 	return probe_irq_off(cookie);
 }
 
+static const struct net_device_ops smc911x_netdev_ops = {
+	.ndo_open		= smc911x_open,
+	.ndo_stop		= smc911x_close,
+	.ndo_start_xmit		= smc911x_hard_start_xmit,
+	.ndo_tx_timeout		= smc911x_timeout,
+	.ndo_set_multicast_list	= smc911x_set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= smc911x_poll_controller,
+#endif
+};
+
 /*
  * Function: smc911x_probe(unsigned long ioaddr)
  *
@@ -1940,16 +1954,9 @@
 	/* Fill in the fields of the device structure with ethernet values. */
 	ether_setup(dev);
 
-	dev->open = smc911x_open;
-	dev->stop = smc911x_close;
-	dev->hard_start_xmit = smc911x_hard_start_xmit;
-	dev->tx_timeout = smc911x_timeout;
+	dev->netdev_ops = &smc911x_netdev_ops;
 	dev->watchdog_timeo = msecs_to_jiffies(watchdog);
-	dev->set_multicast_list = smc911x_set_multicast_list;
 	dev->ethtool_ops = &smc911x_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = smc911x_poll_controller;
-#endif
 
 	INIT_WORK(&lp->phy_configure, smc911x_phy_configure);
 	lp->mii.phy_id_mask = 0x1f;
diff -druN linux-libre-2.6.30-gnu/drivers/net/smc9194.c linux-libre-2.6.31-gnu/drivers/net/smc9194.c
--- linux-libre-2.6.30-gnu/drivers/net/smc9194.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/smc9194.c	2009-09-09 18:13:59.000000000 -0400
@@ -503,7 +503,7 @@
 		/* THIS SHOULD NEVER HAPPEN. */
 		dev->stats.tx_aborted_errors++;
 		printk(CARDNAME": Bad Craziness - sent packet while busy.\n" );
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	lp->saved_skb = skb;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/smc91x.c linux-libre-2.6.31-gnu/drivers/net/smc91x.c
--- linux-libre-2.6.30-gnu/drivers/net/smc91x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/smc91x.c	2009-09-09 18:13:59.000000000 -0400
@@ -196,21 +196,23 @@
 /* this enables an interrupt in the interrupt mask register */
 #define SMC_ENABLE_INT(lp, x) do {					\
 	unsigned char mask;						\
-	spin_lock_irq(&lp->lock);					\
+	unsigned long smc_enable_flags;					\
+	spin_lock_irqsave(&lp->lock, smc_enable_flags);			\
 	mask = SMC_GET_INT_MASK(lp);					\
 	mask |= (x);							\
 	SMC_SET_INT_MASK(lp, mask);					\
-	spin_unlock_irq(&lp->lock);					\
+	spin_unlock_irqrestore(&lp->lock, smc_enable_flags);		\
 } while (0)
 
 /* this disables an interrupt from the interrupt mask register */
 #define SMC_DISABLE_INT(lp, x) do {					\
 	unsigned char mask;						\
-	spin_lock_irq(&lp->lock);					\
+	unsigned long smc_disable_flags;				\
+	spin_lock_irqsave(&lp->lock, smc_disable_flags);		\
 	mask = SMC_GET_INT_MASK(lp);					\
 	mask &= ~(x);							\
 	SMC_SET_INT_MASK(lp, mask);					\
-	spin_unlock_irq(&lp->lock);					\
+	spin_unlock_irqrestore(&lp->lock, smc_disable_flags);		\
 } while (0)
 
 /*
@@ -520,21 +522,21 @@
  * any other concurrent access and C would always interrupt B. But life
  * isn't that easy in a SMP world...
  */
-#define smc_special_trylock(lock)					\
+#define smc_special_trylock(lock, flags)				\
 ({									\
 	int __ret;							\
-	local_irq_disable();						\
+	local_irq_save(flags);						\
 	__ret = spin_trylock(lock);					\
 	if (!__ret)							\
-		local_irq_enable();					\
+		local_irq_restore(flags);				\
 	__ret;								\
 })
-#define smc_special_lock(lock)		spin_lock_irq(lock)
-#define smc_special_unlock(lock)	spin_unlock_irq(lock)
+#define smc_special_lock(lock, flags)		spin_lock_irqsave(lock, flags)
+#define smc_special_unlock(lock, flags) 	spin_unlock_irqrestore(lock, flags)
 #else
-#define smc_special_trylock(lock)	(1)
-#define smc_special_lock(lock)		do { } while (0)
-#define smc_special_unlock(lock)	do { } while (0)
+#define smc_special_trylock(lock, flags)	(1)
+#define smc_special_lock(lock, flags)   	do { } while (0)
+#define smc_special_unlock(lock, flags)	do { } while (0)
 #endif
 
 /*
@@ -548,10 +550,11 @@
 	struct sk_buff *skb;
 	unsigned int packet_no, len;
 	unsigned char *buf;
+	unsigned long flags;
 
 	DBG(3, "%s: %s\n", dev->name, __func__);
 
-	if (!smc_special_trylock(&lp->lock)) {
+	if (!smc_special_trylock(&lp->lock, flags)) {
 		netif_stop_queue(dev);
 		tasklet_schedule(&lp->tx_task);
 		return;
@@ -559,7 +562,7 @@
 
 	skb = lp->pending_tx_skb;
 	if (unlikely(!skb)) {
-		smc_special_unlock(&lp->lock);
+		smc_special_unlock(&lp->lock, flags);
 		return;
 	}
 	lp->pending_tx_skb = NULL;
@@ -569,7 +572,7 @@
 		printk("%s: Memory allocation failed.\n", dev->name);
 		dev->stats.tx_errors++;
 		dev->stats.tx_fifo_errors++;
-		smc_special_unlock(&lp->lock);
+		smc_special_unlock(&lp->lock, flags);
 		goto done;
 	}
 
@@ -608,7 +611,7 @@
 
 	/* queue the packet for TX */
 	SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
-	smc_special_unlock(&lp->lock);
+	smc_special_unlock(&lp->lock, flags);
 
 	dev->trans_start = jiffies;
 	dev->stats.tx_packets++;
@@ -633,6 +636,7 @@
 	struct smc_local *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 	unsigned int numPages, poll_count, status;
+	unsigned long flags;
 
 	DBG(3, "%s: %s\n", dev->name, __func__);
 
@@ -658,7 +662,7 @@
 		return 0;
 	}
 
-	smc_special_lock(&lp->lock);
+	smc_special_lock(&lp->lock, flags);
 
 	/* now, try to allocate the memory */
 	SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
@@ -676,7 +680,7 @@
 		}
    	} while (--poll_count);
 
-	smc_special_unlock(&lp->lock);
+	smc_special_unlock(&lp->lock, flags);
 
 	lp->pending_tx_skb = skb;
    	if (!poll_count) {
@@ -1774,6 +1778,7 @@
 	.ndo_start_xmit		= smc_hard_start_xmit,
 	.ndo_tx_timeout		= smc_timeout,
 	.ndo_set_multicast_list	= smc_set_multicast_list,
+	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address 	= eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druN linux-libre-2.6.30-gnu/drivers/net/smc91x.h linux-libre-2.6.31-gnu/drivers/net/smc91x.h
--- linux-libre-2.6.30-gnu/drivers/net/smc91x.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/smc91x.h	2009-09-09 18:13:59.000000000 -0400
@@ -45,7 +45,8 @@
     defined(CONFIG_MACH_ZYLONITE) ||\
     defined(CONFIG_MACH_LITTLETON) ||\
     defined(CONFIG_MACH_ZYLONITE2) ||\
-    defined(CONFIG_ARCH_VIPER)
+    defined(CONFIG_ARCH_VIPER) ||\
+    defined(CONFIG_MACH_STARGATE2)
 
 #include <asm/mach-types.h>
 
@@ -73,7 +74,7 @@
 /* We actually can't write halfwords properly if not word aligned */
 static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 {
-	if (machine_is_mainstone() && reg & 2) {
+	if ((machine_is_mainstone() || machine_is_stargate2()) && reg & 2) {
 		unsigned int v = val << 16;
 		v |= readl(ioaddr + (reg & ~2)) & 0xffff;
 		writel(v, ioaddr + (reg & ~2));
@@ -185,7 +186,8 @@
 #define SMC_outsb(a, r, p, l)	writesb((a) + (r), p, (l))
 #define SMC_IRQ_FLAGS		(-1)	/* from resource */
 
-#elif	defined(CONFIG_MACH_LOGICPD_PXA270)
+#elif	defined(CONFIG_MACH_LOGICPD_PXA270) \
+	|| defined(CONFIG_MACH_NOMADIK_8815NHK)
 
 #define SMC_CAN_USE_8BIT	0
 #define SMC_CAN_USE_16BIT	1
diff -druN linux-libre-2.6.30-gnu/drivers/net/smc-mca.c linux-libre-2.6.31-gnu/drivers/net/smc-mca.c
--- linux-libre-2.6.30-gnu/drivers/net/smc-mca.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/smc-mca.c	2009-09-09 18:13:59.000000000 -0400
@@ -370,7 +370,7 @@
 
 	outb(reg4, ioaddr + 4);
 
-	gen_dev->driver_data = dev;
+	dev_set_drvdata(gen_dev, dev);
 
 	/* The 8390 isn't at the base address, so fake the offset
 	 */
@@ -531,7 +531,7 @@
 static int ultramca_remove(struct device *gen_dev)
 {
 	struct mca_device *mca_dev = to_mca_device(gen_dev);
-	struct net_device *dev = (struct net_device *)gen_dev->driver_data;
+	struct net_device *dev = dev_get_drvdata(gen_dev);
 
 	if (dev) {
 		/* NB: ultra_close_card() does free_irq */
diff -druN linux-libre-2.6.30-gnu/drivers/net/smsc911x.c linux-libre-2.6.31-gnu/drivers/net/smsc911x.c
--- linux-libre-2.6.30-gnu/drivers/net/smsc911x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/smsc911x.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,6 +47,7 @@
 #include <linux/bitops.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/swab.h>
 #include <linux/phy.h>
 #include <linux/smsc911x.h>
 #include "smsc911x.h"
@@ -175,6 +176,12 @@
 smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
 		      unsigned int wordcount)
 {
+	if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
+		while (wordcount--)
+			smsc911x_reg_write(pdata, TX_DATA_FIFO, swab32(*buf++));
+		return;
+	}
+
 	if (pdata->config.flags & SMSC911X_USE_32BIT) {
 		writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
 		return;
@@ -194,6 +201,12 @@
 smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
 		     unsigned int wordcount)
 {
+	if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
+		while (wordcount--)
+			*buf++ = swab32(smsc911x_reg_read(pdata, RX_DATA_FIFO));
+		return;
+	}
+
 	if (pdata->config.flags & SMSC911X_USE_32BIT) {
 		readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
 		return;
@@ -1766,6 +1779,7 @@
 	.ndo_get_stats		= smsc911x_get_stats,
 	.ndo_set_multicast_list	= smsc911x_set_multicast_list,
 	.ndo_do_ioctl		= smsc911x_do_ioctl,
+	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address 	= smsc911x_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1925,7 +1939,7 @@
 	if (!res)
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	release_mem_region(res->start, res->end - res->start);
+	release_mem_region(res->start, resource_size(res));
 
 	iounmap(pdata->ioaddr);
 
@@ -1963,7 +1977,7 @@
 		retval = -ENODEV;
 		goto out_0;
 	}
-	res_size = res->end - res->start;
+	res_size = resource_size(res);
 
 	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!irq_res) {
@@ -2091,17 +2105,63 @@
 out_free_netdev_2:
 	free_netdev(dev);
 out_release_io_1:
-	release_mem_region(res->start, res->end - res->start);
+	release_mem_region(res->start, resource_size(res));
 out_0:
 	return retval;
 }
 
+#ifdef CONFIG_PM
+/* This implementation assumes the devices remains powered on its VDDVARIO
+ * pins during suspend. */
+
+static int smsc911x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct smsc911x_data *pdata = netdev_priv(dev);
+
+	/* enable wake on LAN, energy detection and the external PME
+	 * signal. */
+	smsc911x_reg_write(pdata, PMT_CTRL,
+		PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ |
+		PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_);
+
+	return 0;
+}
+
+static int smsc911x_resume(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct smsc911x_data *pdata = netdev_priv(dev);
+	unsigned int to = 100;
+
+	/* Note 3.11 from the datasheet:
+	 * 	"When the LAN9220 is in a power saving state, a write of any
+	 * 	 data to the BYTE_TEST register will wake-up the device."
+	 */
+	smsc911x_reg_write(pdata, BYTE_TEST, 0);
+
+	/* poll the READY bit in PMT_CTRL. Any other access to the device is
+	 * forbidden while this bit isn't set. Try for 100ms and return -EIO
+	 * if it failed. */
+	while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+		udelay(1000);
+
+	return (to == 0) ? -EIO : 0;
+}
+
+#else
+#define smsc911x_suspend	NULL
+#define smsc911x_resume		NULL
+#endif
+
 static struct platform_driver smsc911x_driver = {
 	.probe = smsc911x_drv_probe,
-	.remove = smsc911x_drv_remove,
+	.remove = __devexit_p(smsc911x_drv_remove),
 	.driver = {
 		.name = SMSC_CHIPNAME,
 	},
+	.suspend = smsc911x_suspend,
+	.resume = smsc911x_resume,
 };
 
 /* Entry point for loading the module */
diff -druN linux-libre-2.6.30-gnu/drivers/net/sonic.c linux-libre-2.6.31-gnu/drivers/net/sonic.c
--- linux-libre-2.6.30-gnu/drivers/net/sonic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sonic.c	2009-09-09 18:13:59.000000000 -0400
@@ -223,7 +223,7 @@
 	if (!laddr) {
 		printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
 		dev_kfree_skb(skb);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0);       /* clear status */
diff -druN linux-libre-2.6.30-gnu/drivers/net/starfire.c linux-libre-2.6.31-gnu/drivers/net/starfire.c
--- linux-libre-2.6.30-gnu/drivers/net/starfire.c	2012-03-22 19:14:23.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/starfire.c	2012-03-22 20:10:33.000000000 -0400
@@ -180,7 +180,7 @@
 /* These identify the driver base version and may not be removed. */
 static const char version[] __devinitconst =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
-KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
+" (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
@@ -1235,7 +1235,7 @@
 	 */
 	if ((np->cur_tx - np->dirty_tx) + skb_num_frags(skb) * 2 > TX_RING_SIZE) {
 		netif_stop_queue(dev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
diff -druN linux-libre-2.6.30-gnu/drivers/net/sun3_82586.c linux-libre-2.6.31-gnu/drivers/net/sun3_82586.c
--- linux-libre-2.6.30-gnu/drivers/net/sun3_82586.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sun3_82586.c	2009-09-09 18:13:59.000000000 -0400
@@ -1023,7 +1023,7 @@
 #if(NUM_XMIT_BUFFS > 1)
 	if(test_and_set_bit(0,(void *) &p->lock)) {
 		printk("%s: Queue was locked\n",dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	else
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/sun3lance.c linux-libre-2.6.31-gnu/drivers/net/sun3lance.c
--- linux-libre-2.6.30-gnu/drivers/net/sun3lance.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sun3lance.c	2009-09-09 18:13:59.000000000 -0400
@@ -294,6 +294,16 @@
 	return ERR_PTR(err);
 }
 
+static const struct net_device_ops lance_netdev_ops = {
+	.ndo_open		= lance_open,
+	.ndo_stop		= lance_close,
+	.ndo_start_xmit		= lance_start_xmit,
+	.ndo_set_multicast_list	= set_multicast_list,
+	.ndo_set_mac_address	= NULL,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
 static int __init lance_probe( struct net_device *dev)
 {
 	unsigned long ioaddr;
@@ -397,12 +407,7 @@
 	if (did_version++ == 0)
 		printk( version );
 
-	/* The LANCE-specific entries in the device structure. */
-	dev->open = &lance_open;
-	dev->hard_start_xmit = &lance_start_xmit;
-	dev->stop = &lance_close;
-	dev->set_multicast_list = &set_multicast_list;
-	dev->set_mac_address = NULL;
+	dev->netdev_ops = &lance_netdev_ops;
 //	KLUDGE -- REMOVE ME
 	set_bit(__LINK_STATE_PRESENT, &dev->state);
 
@@ -521,7 +526,7 @@
 	if (netif_queue_stopped(dev)) {
 		int tickssofar = jiffies - dev->trans_start;
 		if (tickssofar < 20)
-			return( 1 );
+			return NETDEV_TX_BUSY;
 
 		DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
 					  dev->name, DREG ));
@@ -572,7 +577,7 @@
 	if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {
 		printk( "%s: tx queue lock!.\n", dev->name);
 		/* don't clear dev->tbusy flag. */
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	AREG = CSR0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/sundance.c linux-libre-2.6.31-gnu/drivers/net/sundance.c
--- linux-libre-2.6.30-gnu/drivers/net/sundance.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sundance.c	2009-09-09 18:13:59.000000000 -0400
@@ -369,7 +369,6 @@
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
         dma_addr_t tx_ring_dma;
         dma_addr_t rx_ring_dma;
-	struct net_device_stats stats;
 	struct timer_list timer;		/* Media monitoring timer. */
 	/* Frequently used values: keep some adjacent for cache effect. */
 	spinlock_t lock;
@@ -975,7 +974,7 @@
 	dev->if_port = 0;
 
 	dev->trans_start = jiffies;
-	np->stats.tx_errors++;
+	dev->stats.tx_errors++;
 	if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
 		netif_wake_queue(dev);
 	}
@@ -1123,7 +1122,7 @@
 			else
 				dev_kfree_skb (skb);
 			np->tx_skbuff[i] = NULL;
-			np->stats.tx_dropped++;
+			dev->stats.tx_dropped++;
 		}
 	}
 	np->cur_tx = np->dirty_tx = 0;
@@ -1181,15 +1180,15 @@
 					if (netif_msg_tx_err(np))
 						printk("%s: Transmit error status %4.4x.\n",
 							   dev->name, tx_status);
-					np->stats.tx_errors++;
+					dev->stats.tx_errors++;
 					if (tx_status & 0x10)
-						np->stats.tx_fifo_errors++;
+						dev->stats.tx_fifo_errors++;
 					if (tx_status & 0x08)
-						np->stats.collisions++;
+						dev->stats.collisions++;
 					if (tx_status & 0x04)
-						np->stats.tx_fifo_errors++;
+						dev->stats.tx_fifo_errors++;
 					if (tx_status & 0x02)
-						np->stats.tx_window_errors++;
+						dev->stats.tx_window_errors++;
 
 					/*
 					** This reset has been verified on
@@ -1313,11 +1312,15 @@
 			if (netif_msg_rx_err(np))
 				printk(KERN_DEBUG "  netdev_rx() Rx error was %8.8x.\n",
 					   frame_status);
-			np->stats.rx_errors++;
-			if (frame_status & 0x00100000) np->stats.rx_length_errors++;
-			if (frame_status & 0x00010000) np->stats.rx_fifo_errors++;
-			if (frame_status & 0x00060000) np->stats.rx_frame_errors++;
-			if (frame_status & 0x00080000) np->stats.rx_crc_errors++;
+			dev->stats.rx_errors++;
+			if (frame_status & 0x00100000)
+				dev->stats.rx_length_errors++;
+			if (frame_status & 0x00010000)
+				dev->stats.rx_fifo_errors++;
+			if (frame_status & 0x00060000)
+				dev->stats.rx_frame_errors++;
+			if (frame_status & 0x00080000)
+				dev->stats.rx_crc_errors++;
 			if (frame_status & 0x00100000) {
 				printk(KERN_WARNING "%s: Oversized Ethernet frame,"
 					   " status %8.8x.\n",
@@ -1485,22 +1488,22 @@
 	   the vulnerability window is very small and statistics are
 	   non-critical. */
 	/* The chip only need report frame silently dropped. */
-	np->stats.rx_missed_errors	+= ioread8(ioaddr + RxMissed);
-	np->stats.tx_packets += ioread16(ioaddr + TxFramesOK);
-	np->stats.rx_packets += ioread16(ioaddr + RxFramesOK);
-	np->stats.collisions += ioread8(ioaddr + StatsLateColl);
-	np->stats.collisions += ioread8(ioaddr + StatsMultiColl);
-	np->stats.collisions += ioread8(ioaddr + StatsOneColl);
-	np->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError);
+	dev->stats.rx_missed_errors	+= ioread8(ioaddr + RxMissed);
+	dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK);
+	dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK);
+	dev->stats.collisions += ioread8(ioaddr + StatsLateColl);
+	dev->stats.collisions += ioread8(ioaddr + StatsMultiColl);
+	dev->stats.collisions += ioread8(ioaddr + StatsOneColl);
+	dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError);
 	ioread8(ioaddr + StatsTxDefer);
 	for (i = StatsTxDefer; i <= StatsMcastRx; i++)
 		ioread8(ioaddr + i);
-	np->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow);
-	np->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16;
-	np->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow);
-	np->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16;
+	dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow);
+	dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16;
+	dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow);
+	dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16;
 
-	return &np->stats;
+	return &dev->stats;
 }
 
 static void set_rx_mode(struct net_device *dev)
@@ -1695,13 +1698,13 @@
 
 #ifdef __i386__
 	if (netif_msg_hw(np)) {
-		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
+		printk(KERN_DEBUG "  Tx ring at %8.8x:\n",
 			   (int)(np->tx_ring_dma));
 		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" #%d desc. %4.4x %8.8x %8.8x.\n",
+			printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n",
 				   i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr,
 				   np->tx_ring[i].frag[0].length);
-		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
+		printk(KERN_DEBUG "  Rx ring %8.8x:\n",
 			   (int)(np->rx_ring_dma));
 		for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) {
 			printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
diff -druN linux-libre-2.6.30-gnu/drivers/net/sunhme.c linux-libre-2.6.31-gnu/drivers/net/sunhme.c
--- linux-libre-2.6.30-gnu/drivers/net/sunhme.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sunhme.c	2009-09-09 18:13:59.000000000 -0400
@@ -2275,7 +2275,7 @@
 		spin_unlock_irq(&hp->happy_lock);
 		printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	entry = hp->tx_new;
diff -druN linux-libre-2.6.30-gnu/drivers/net/sunvnet.c linux-libre-2.6.31-gnu/drivers/net/sunvnet.c
--- linux-libre-2.6.30-gnu/drivers/net/sunvnet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/sunvnet.c	2009-09-09 18:13:59.000000000 -0400
@@ -1016,7 +1016,9 @@
 	.ndo_open		= vnet_open,
 	.ndo_stop		= vnet_close,
 	.ndo_set_multicast_list	= vnet_set_rx_mode,
+	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= vnet_set_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= vnet_tx_timeout,
 	.ndo_change_mtu		= vnet_change_mtu,
 	.ndo_start_xmit		= vnet_start_xmit,
diff -druN linux-libre-2.6.30-gnu/drivers/net/tc35815.c linux-libre-2.6.31-gnu/drivers/net/tc35815.c
--- linux-libre-2.6.30-gnu/drivers/net/tc35815.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tc35815.c	2009-09-09 18:13:59.000000000 -0400
@@ -688,14 +688,11 @@
 
 	if (status_change && netif_msg_link(lp)) {
 		phy_print_status(phydev);
-#ifdef DEBUG
-		printk(KERN_DEBUG
-		       "%s: MII BMCR %04x BMSR %04x LPA %04x\n",
-		       dev->name,
-		       phy_read(phydev, MII_BMCR),
-		       phy_read(phydev, MII_BMSR),
-		       phy_read(phydev, MII_LPA));
-#endif
+		pr_debug("%s: MII BMCR %04x BMSR %04x LPA %04x\n",
+			 dev->name,
+			 phy_read(phydev, MII_BMCR),
+			 phy_read(phydev, MII_BMSR),
+			 phy_read(phydev, MII_LPA));
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/tehuti.c linux-libre-2.6.31-gnu/drivers/net/tehuti.c
--- linux-libre-2.6.30-gnu/drivers/net/tehuti.c	2012-03-22 19:15:29.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tehuti.c	2012-03-22 20:11:29.000000000 -0400
@@ -948,8 +948,7 @@
 
 static void bdx_rxdb_destroy(struct rxdb *db)
 {
-	if (db)
-		vfree(db);
+	vfree(db);
 }
 
 static struct rxdb *bdx_rxdb_create(int nelem)
@@ -1482,10 +1481,8 @@
 {
 	BDX_ASSERT(d == NULL);
 
-	if (d->start) {
-		vfree(d->start);
-		d->start = NULL;
-	}
+	vfree(d->start);
+	d->start = NULL;
 }
 
 /*************************************************************************
@@ -1718,8 +1715,9 @@
 	WRITE_REG(priv, f->m.reg_WPTR, f->m.wptr & TXF_WPTR_WR_PTR);
 
 #endif
-	ndev->trans_start = jiffies;
-
+#ifdef BDX_LLTX
+	ndev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
+#endif
 	priv->net_stats.tx_packets++;
 	priv->net_stats.tx_bytes += skb->len;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/tg3.c linux-libre-2.6.31-gnu/drivers/net/tg3.c
--- linux-libre-2.6.30-gnu/drivers/net/tg3.c	2012-03-22 19:15:39.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tg3.c	2012-03-22 20:11:37.000000000 -0400
@@ -61,8 +61,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.98"
-#define DRV_MODULE_RELDATE	"February 25, 2009"
+#define DRV_MODULE_VERSION	"3.99"
+#define DRV_MODULE_RELDATE	"April 20, 2009"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -1941,7 +1941,8 @@
 				     GRC_LCLCTRL_GPIO_OUTPUT0 |
 				     GRC_LCLCTRL_GPIO_OUTPUT1),
 				    100);
-		} else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) {
+		} else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+			   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
 			/* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
 			u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
 					     GRC_LCLCTRL_GPIO_OE1 |
@@ -2446,8 +2447,6 @@
 		}
 	}
 
-	__tg3_set_mac_addr(tp, 0);
-
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 		u32 val;
 
@@ -4647,6 +4646,7 @@
 			 * so we must read it before checking for more work.
 			 */
 			tp->last_tag = sblk->status_tag;
+			tp->last_irq_tag = tp->last_tag;
 			rmb();
 		} else
 			sblk->status &= ~SD_STATUS_UPDATED;
@@ -4802,7 +4802,7 @@
 	 * Reading the PCI State register will confirm whether the
 	 * interrupt is ours and will flush the status block.
 	 */
-	if (unlikely(sblk->status_tag == tp->last_tag)) {
+	if (unlikely(sblk->status_tag == tp->last_irq_tag)) {
 		if ((tp->tg3_flags & TG3_FLAG_CHIP_RESETTING) ||
 		    (tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
 			handled = 0;
@@ -4822,18 +4822,22 @@
 	 * excessive spurious interrupts can be worse in some cases.
 	 */
 	tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+
+	/*
+	 * In a shared interrupt configuration, sometimes other devices'
+	 * interrupts will scream.  We record the current status tag here
+	 * so that the above check can report that the screaming interrupts
+	 * are unhandled.  Eventually they will be silenced.
+	 */
+	tp->last_irq_tag = sblk->status_tag;
+
 	if (tg3_irq_sync(tp))
 		goto out;
-	if (napi_schedule_prep(&tp->napi)) {
-		prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
-		/* Update last_tag to mark that this status has been
-		 * seen. Because interrupt may be shared, we may be
-		 * racing with tg3_poll(), so only update last_tag
-		 * if tg3_poll() is not scheduled.
-		 */
-		tp->last_tag = sblk->status_tag;
-		__napi_schedule(&tp->napi);
-	}
+
+	prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+
+	napi_schedule(&tp->napi);
+
 out:
 	return IRQ_RETVAL(handled);
 }
@@ -5008,7 +5012,7 @@
 		/* New SKB is guaranteed to be linear. */
 		entry = *start;
 		ret = skb_dma_map(&tp->pdev->dev, new_skb, DMA_TO_DEVICE);
-		new_addr = skb_shinfo(new_skb)->dma_maps[0];
+		new_addr = skb_shinfo(new_skb)->dma_head;
 
 		/* Make sure new skb does not cross any 4G boundaries.
 		 * Drop the packet if it does.
@@ -5142,7 +5146,7 @@
 
 	sp = skb_shinfo(skb);
 
-	mapping = sp->dma_maps[0];
+	mapping = sp->dma_head;
 
 	tp->tx_buffers[entry].skb = skb;
 
@@ -5160,7 +5164,7 @@
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
 			len = frag->size;
-			mapping = sp->dma_maps[i + 1];
+			mapping = sp->dma_maps[i];
 			tp->tx_buffers[entry].skb = NULL;
 
 			tg3_set_txd(tp, entry, mapping, len,
@@ -5181,9 +5185,7 @@
 	}
 
 out_unlock:
-    	mmiowb();
-
-	dev->trans_start = jiffies;
+	mmiowb();
 
 	return NETDEV_TX_OK;
 }
@@ -5320,7 +5322,7 @@
 
 	sp = skb_shinfo(skb);
 
-	mapping = sp->dma_maps[0];
+	mapping = sp->dma_head;
 
 	tp->tx_buffers[entry].skb = skb;
 
@@ -5345,7 +5347,7 @@
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
 			len = frag->size;
-			mapping = sp->dma_maps[i + 1];
+			mapping = sp->dma_maps[i];
 
 			tp->tx_buffers[entry].skb = NULL;
 
@@ -5394,9 +5396,7 @@
 	}
 
 out_unlock:
-    	mmiowb();
-
-	dev->trans_start = jiffies;
+	mmiowb();
 
 	return NETDEV_TX_OK;
 }
@@ -6147,6 +6147,7 @@
 		tp->hw_status->status_tag = 0;
 	}
 	tp->last_tag = 0;
+	tp->last_irq_tag = 0;
 	smp_mb();
 	synchronize_irq(tp->pdev->irq);
 
@@ -6341,6 +6342,8 @@
 	tg3_abort_hw(tp, silent);
 	err = tg3_chip_reset(tp);
 
+	__tg3_set_mac_addr(tp, 0);
+
 	tg3_write_sig_legacy(tp, kind);
 	tg3_write_sig_post_reset(tp, kind);
 
@@ -6702,6 +6705,13 @@
 		tw32(TG3_CPMU_HST_ACC, val);
 	}
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+		val = tr32(PCIE_PWR_MGMT_THRESH) & ~PCIE_PWR_MGMT_L1_THRESH_MSK;
+		val |= PCIE_PWR_MGMT_EXT_ASPM_TMR_EN |
+		       PCIE_PWR_MGMT_L1_THRESH_4MS;
+		tw32(PCIE_PWR_MGMT_THRESH, val);
+	}
+
 	/* This works around an issue with Athlon chipsets on
 	 * B3 tigon3 silicon.  This bit has no effect on any
 	 * other revision.  But do not set this on PCI Express
@@ -7129,7 +7139,6 @@
 	udelay(100);
 
 	tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
-	tp->last_tag = 0;
 
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
 		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
@@ -8530,6 +8539,9 @@
 	u32 i, offset, len, b_offset, b_count;
 	__be32 val;
 
+	if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM)
+		return -EINVAL;
+
 	if (tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
@@ -8595,7 +8607,8 @@
 	if (tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
-	if (eeprom->magic != TG3_EEPROM_MAGIC)
+	if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
+	    eeprom->magic != TG3_EEPROM_MAGIC)
 		return -EINVAL;
 
 	offset = eeprom->offset;
@@ -9192,6 +9205,9 @@
 	__be32 *buf;
 	int i, j, k, err = 0, size;
 
+	if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM)
+		return 0;
+
 	if (tg3_nvram_read(tp, 0, &magic) != 0)
 		return -EIO;
 
@@ -10174,7 +10190,8 @@
 {
 	u32 val;
 
-	if (tg3_nvram_read(tp, 0, &val) != 0)
+	if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
+	    tg3_nvram_read(tp, 0, &val) != 0)
 		return;
 
 	/* Selfboot format */
@@ -10556,6 +10573,7 @@
 		}
 		break;
 	default:
+		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM;
 		return;
 	}
 
@@ -11356,7 +11374,8 @@
 	unsigned int i;
 	u32 magic;
 
-	if (tg3_nvram_read(tp, 0x0, &magic))
+	if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
+	    tg3_nvram_read(tp, 0x0, &magic))
 		goto out_not_found;
 
 	if (magic == TG3_EEPROM_MAGIC) {
@@ -11448,6 +11467,15 @@
 out_not_found:
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
 		strcpy(tp->board_part_number, "BCM95906");
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
+		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780)
+		strcpy(tp->board_part_number, "BCM57780");
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
+		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760)
+		strcpy(tp->board_part_number, "BCM57760");
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
+		 tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790)
+		strcpy(tp->board_part_number, "BCM57790");
 	else
 		strcpy(tp->board_part_number, "none");
 }
@@ -11658,6 +11686,14 @@
 {
 	u32 val;
 
+	if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) {
+		tp->fw_ver[0] = 's';
+		tp->fw_ver[1] = 'b';
+		tp->fw_ver[2] = '\0';
+
+		return;
+	}
+
 	if (tg3_nvram_read(tp, 0, &val))
 		return;
 
@@ -11943,7 +11979,8 @@
 				tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
 			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
 			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
-			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+			    tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 ||
+			    tp->pci_chip_rev_id == CHIPREV_ID_57780_A1)
 				tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG;
 		}
 	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
@@ -12135,7 +12172,8 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 		tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
 
-	if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) {
+	if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
+	    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
 		/* Turn off the debug UART. */
 		tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
 		if (tp->tg3_flags2 & TG3_FLG2_IS_NIC)
@@ -12445,7 +12483,8 @@
 	}
 	if (!addr_ok) {
 		/* Next, try NVRAM. */
-		if (!tg3_nvram_read_be32(tp, mac_offset + 0, &hi) &&
+		if (!(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) &&
+		    !tg3_nvram_read_be32(tp, mac_offset + 0, &hi) &&
 		    !tg3_nvram_read_be32(tp, mac_offset + 4, &lo)) {
 			memcpy(&dev->dev_addr[0], ((char *)&hi) + 2, 2);
 			memcpy(&dev->dev_addr[2], (char *)&lo, sizeof(lo));
diff -druN linux-libre-2.6.30-gnu/drivers/net/tg3.h linux-libre-2.6.31-gnu/drivers/net/tg3.h
--- linux-libre-2.6.30-gnu/drivers/net/tg3.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tg3.h	2009-09-09 18:13:59.000000000 -0400
@@ -95,6 +95,8 @@
 #define  CHIPREV_ID_5752_A1		 0x6001
 #define  CHIPREV_ID_5714_A2		 0x9002
 #define  CHIPREV_ID_5906_A1		 0xc001
+#define  CHIPREV_ID_57780_A0		 0x57780000
+#define  CHIPREV_ID_57780_A1		 0x57780001
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -1697,6 +1699,8 @@
 
 #define PCIE_PWR_MGMT_THRESH		0x00007d28
 #define PCIE_PWR_MGMT_L1_THRESH_MSK	 0x0000ff00
+#define PCIE_PWR_MGMT_L1_THRESH_4MS	 0x0000ff00
+#define PCIE_PWR_MGMT_EXT_ASPM_TMR_EN	 0x01000000
 
 
 /* OTP bit definitions */
@@ -2501,6 +2505,7 @@
 	struct tg3_hw_status		*hw_status;
 	dma_addr_t			status_mapping;
 	u32				last_tag;
+	u32				last_irq_tag;
 
 	u32				msg_enable;
 
@@ -2635,6 +2640,7 @@
 #define TG3_FLG3_CLKREQ_BUG		0x00000800
 #define TG3_FLG3_PHY_ENABLE_APD		0x00001000
 #define TG3_FLG3_5755_PLUS		0x00002000
+#define TG3_FLG3_NO_NVRAM		0x00004000
 
 	struct timer_list		timer;
 	u16				timer_counter;
diff -druN linux-libre-2.6.30-gnu/drivers/net/tlan.c linux-libre-2.6.31-gnu/drivers/net/tlan.c
--- linux-libre-2.6.30-gnu/drivers/net/tlan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tlan.c	2009-09-09 18:13:59.000000000 -0400
@@ -1111,7 +1111,7 @@
 			  dev->name, priv->txHead, priv->txTail );
 		netif_stop_queue(dev);
 		priv->txBusyCount++;
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	tail_list->forward = 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/tokenring/3c359.c linux-libre-2.6.31-gnu/drivers/net/tokenring/3c359.c
--- linux-libre-2.6.30-gnu/drivers/net/tokenring/3c359.c	2012-03-22 19:16:01.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tokenring/3c359.c	2012-03-22 20:11:55.000000000 -0400
@@ -79,7 +79,7 @@
 MODULE_DESCRIPTION("3Com 3C359 Velocity XL Token Ring Adapter Driver \n") ;
 /*(DEBLOBBED)*/
 
-/* Module paramters */
+/* Module parameters */
 
 /* Ring Speed 0,4,16 
  * 0 = Autosense   
@@ -1243,7 +1243,7 @@
 		return 0;
 	} else {
 		spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ; 
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/tokenring/ibmtr.c linux-libre-2.6.31-gnu/drivers/net/tokenring/ibmtr.c
--- linux-libre-2.6.30-gnu/drivers/net/tokenring/ibmtr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tokenring/ibmtr.c	2009-09-09 18:13:59.000000000 -0400
@@ -1912,7 +1912,7 @@
 
 	find_turbo_adapters(io);
 
-	for (i = 0; io[i] && (i < IBMTR_MAX_ADAPTERS); i++) {
+	for (i = 0; i < IBMTR_MAX_ADAPTERS && io[i]; i++) {
 		struct net_device *dev;
 		irq[i] = 0;
 		mem[i] = 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/tokenring/lanstreamer.c linux-libre-2.6.31-gnu/drivers/net/tokenring/lanstreamer.c
--- linux-libre-2.6.30-gnu/drivers/net/tokenring/lanstreamer.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tokenring/lanstreamer.c	2009-09-09 18:13:59.000000000 -0400
@@ -169,7 +169,7 @@
 	"Monitor Contention failer for RPL", "FDX Protocol Error"
 };
 
-/* Module paramters */
+/* Module parameters */
 
 /* Ring Speed 0,4,16
  * 0 = Autosense         
@@ -1187,7 +1187,7 @@
 	} else {
 	        netif_stop_queue(dev);
 	        spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/tokenring/olympic.c linux-libre-2.6.31-gnu/drivers/net/tokenring/olympic.c
--- linux-libre-2.6.30-gnu/drivers/net/tokenring/olympic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tokenring/olympic.c	2009-09-09 18:13:59.000000000 -0400
@@ -132,7 +132,7 @@
 				   "Reserved", "Reserved", "No Monitor Detected for RPL", 
 				   "Monitor Contention failer for RPL", "FDX Protocol Error"};
 
-/* Module paramters */
+/* Module parameters */
 
 MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ; 
 MODULE_DESCRIPTION("Olympic PCI/Cardbus Chipset Driver") ; 
@@ -1055,7 +1055,7 @@
 		return 0;
 	} else {
 		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	} 
 
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/tokenring/smctr.c linux-libre-2.6.31-gnu/drivers/net/tokenring/smctr.c
--- linux-libre-2.6.30-gnu/drivers/net/tokenring/smctr.c	2012-03-22 19:16:08.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tokenring/smctr.c	2012-03-22 20:12:00.000000000 -0400
@@ -4601,7 +4601,7 @@
         netif_stop_queue(dev);
 
         if(tp->QueueSkb == 0)
-                return (1);     /* Return with tbusy set: queue full */
+                return NETDEV_TX_BUSY;     /* Return with tbusy set: queue full */
 
         tp->QueueSkb--;
         skb_queue_tail(&tp->SendSkbQueue, skb);
diff -druN linux-libre-2.6.30-gnu/drivers/net/tokenring/tms380tr.c linux-libre-2.6.31-gnu/drivers/net/tokenring/tms380tr.c
--- linux-libre-2.6.30-gnu/drivers/net/tokenring/tms380tr.c	2012-03-22 19:16:12.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tokenring/tms380tr.c	2012-03-22 20:12:03.000000000 -0400
@@ -633,7 +633,7 @@
 		if (tms380tr_debug > 0)
 			printk(KERN_DEBUG "%s: No free TPL\n", dev->name);
 		spin_unlock_irqrestore(&tp->lock, flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	dmabuf = 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/tsi108_eth.c linux-libre-2.6.31-gnu/drivers/net/tsi108_eth.c
--- linux-libre-2.6.30-gnu/drivers/net/tsi108_eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tsi108_eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -1132,7 +1132,9 @@
 	}
 
 	if (!is_valid_ether_addr(dev->dev_addr)) {
-		printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2);
+		printk(KERN_ERR
+		       "%s: Invalid MAC address. word1: %08x, word2: %08x\n",
+		       dev->name, word1, word2);
 		return -EINVAL;
 	}
 
@@ -1201,8 +1203,8 @@
 				__set_bit(hash, &data->mc_hash[0]);
 			} else {
 				printk(KERN_ERR
-				       "%s: got multicast address of length %d "
-				       "instead of 6.\n", dev->name,
+		"%s: got multicast address of length %d instead of 6.\n",
+				       dev->name,
 				       mc->dmi_addrlen);
 			}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/tulip/de2104x.c linux-libre-2.6.31-gnu/drivers/net/tulip/de2104x.c
--- linux-libre-2.6.30-gnu/drivers/net/tulip/de2104x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tulip/de2104x.c	2009-09-09 18:13:59.000000000 -0400
@@ -82,6 +82,13 @@
 				 NETIF_MSG_RX_ERR	| \
 				 NETIF_MSG_TX_ERR)
 
+/* Descriptor skip length in 32 bit longwords. */
+#ifndef CONFIG_DE2104X_DSL
+#define DSL			0
+#else
+#define DSL			CONFIG_DE2104X_DSL
+#endif
+
 #define DE_RX_RING_SIZE		64
 #define DE_TX_RING_SIZE		64
 #define DE_RING_BYTES		\
@@ -153,6 +160,7 @@
 	CmdReset		= (1 << 0),
 	CacheAlign16		= 0x00008000,
 	BurstLen4		= 0x00000400,
+	DescSkipLen		= (DSL << 2),
 
 	/* Rx/TxPoll bits */
 	NormalTxPoll		= (1 << 0),
@@ -246,7 +254,7 @@
  * Set the programmable burst length to 4 longwords for all:
  * DMA errors result without these values. Cache align 16 long.
  */
-static const u32 de_bus_mode = CacheAlign16 | BurstLen4;
+static const u32 de_bus_mode = CacheAlign16 | BurstLen4 | DescSkipLen;
 
 struct de_srom_media_block {
 	u8			opts;
@@ -266,6 +274,9 @@
 	__le32			opts2;
 	__le32			addr1;
 	__le32			addr2;
+#if DSL
+	__le32			skip[DSL];
+#endif
 };
 
 struct media_info {
@@ -601,7 +612,7 @@
 	if (tx_free == 0) {
 		netif_stop_queue(dev);
 		spin_unlock_irq(&de->lock);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	tx_free--;
 
@@ -933,9 +944,10 @@
 		macmode &= ~FullDuplex;
 
 	if (netif_msg_link(de)) {
-		printk(KERN_INFO "%s: set link %s\n"
-		       KERN_INFO "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
-		       KERN_INFO "%s:    set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
+		printk(KERN_INFO
+		       "%s: set link %s\n"
+		       "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
+		       "%s:    set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
 		       de->dev->name, media_name[media],
 		       de->dev->name, dr32(MacMode), dr32(SIAStatus),
 		       dr32(CSR13), dr32(CSR14), dr32(CSR15),
diff -druN linux-libre-2.6.30-gnu/drivers/net/tulip/de4x5.c linux-libre-2.6.31-gnu/drivers/net/tulip/de4x5.c
--- linux-libre-2.6.30-gnu/drivers/net/tulip/de4x5.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tulip/de4x5.c	2009-09-09 18:13:59.000000000 -0400
@@ -1099,7 +1099,7 @@
     struct pci_dev *pdev = NULL;
     int i, status=0;
 
-    gendev->driver_data = dev;
+    dev_set_drvdata(gendev, dev);
 
     /* Ensure we're not sleeping */
     if (lp->bus == EISA) {
@@ -1461,12 +1461,12 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    int status = 0;
+    int status = NETDEV_TX_OK;
     u_long flags = 0;
 
     netif_stop_queue(dev);
     if (!lp->tx_enable) {                   /* Cannot send for now */
-	return -1;
+	return NETDEV_TX_LOCKED;
     }
 
     /*
@@ -1480,7 +1480,7 @@
 
     /* Test if cache is already locked - requeue skb if so */
     if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt)
-	return -1;
+	return NETDEV_TX_LOCKED;
 
     /* Transmit descriptor ring full or stale skb */
     if (netif_queue_stopped(dev) || (u_long) lp->tx_skb[lp->tx_new] > 1) {
@@ -2094,7 +2094,7 @@
 	struct net_device *dev;
 	u_long iobase;
 
-	dev = device->driver_data;
+	dev = dev_get_drvdata(device);
 	iobase = dev->base_addr;
 
 	unregister_netdev (dev);
@@ -2338,7 +2338,7 @@
 	struct net_device *dev;
 	u_long iobase;
 
-	dev = pdev->dev.driver_data;
+	dev = dev_get_drvdata(&pdev->dev);
 	iobase = dev->base_addr;
 
 	unregister_netdev (dev);
@@ -5059,7 +5059,7 @@
 	if ((id == 0) || (id == 65535)) continue;  /* Valid ID? */
 	for (j=0; j<limit; j++) {                  /* Search PHY table */
 	    if (id != phy_info[j].id) continue;    /* ID match? */
-	    for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
+	    for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++);
 	    if (k < DE4X5_MAX_PHY) {
 		memcpy((char *)&lp->phy[k],
 		       (char *)&phy_info[j], sizeof(struct phy_table));
@@ -5072,7 +5072,7 @@
 	    break;
 	}
 	if ((j == limit) && (i < DE4X5_MAX_MII)) {
-	    for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
+	    for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++);
 	    lp->phy[k].addr = i;
 	    lp->phy[k].id = id;
 	    lp->phy[k].spd.reg = GENERIC_REG;      /* ANLPA register         */
@@ -5091,7 +5091,7 @@
   purgatory:
     lp->active = 0;
     if (lp->phy[0].id) {                           /* Reset the PHY devices */
-	for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++) { /*For each PHY*/
+	for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++) { /*For each PHY*/
 	    mii_wr(MII_CR_RST, MII_CR, lp->phy[k].addr, DE4X5_MII);
 	    while (mii_rd(MII_CR, lp->phy[k].addr, DE4X5_MII) & MII_CR_RST);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/tulip/dmfe.c linux-libre-2.6.31-gnu/drivers/net/tulip/dmfe.c
--- linux-libre-2.6.30-gnu/drivers/net/tulip/dmfe.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tulip/dmfe.c	2009-09-09 18:13:59.000000000 -0400
@@ -686,7 +686,7 @@
 		spin_unlock_irqrestore(&db->lock, flags);
 		printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n",
 		       db->tx_queue_cnt);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Disable NIC interrupt */
diff -druN linux-libre-2.6.30-gnu/drivers/net/tulip/Kconfig linux-libre-2.6.31-gnu/drivers/net/tulip/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/tulip/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tulip/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -27,6 +27,18 @@
 	  To compile this driver as a module, choose M here. The module will
 	  be called de2104x.
 
+config DE2104X_DSL
+	int "Descriptor Skip Length in 32 bit longwords"
+	depends on DE2104X
+	range 0 31
+	default 0
+	help
+	  Setting this value allows to align ring buffer descriptors into their
+	  own cache lines. Value of 4 corresponds to the typical 32 byte line
+	  (the descriptor is 16 bytes). This is necessary on systems that lack
+	  cache coherence, an example is PowerMac 5500. Otherwise 0 is safe.
+	  Default is 0, and range is 0 to 31.
+
 config TULIP
 	tristate "DECchip Tulip (dc2114x) PCI support"
 	depends on PCI
diff -druN linux-libre-2.6.30-gnu/drivers/net/tulip/tulip_core.c linux-libre-2.6.31-gnu/drivers/net/tulip/tulip_core.c
--- linux-libre-2.6.30-gnu/drivers/net/tulip/tulip_core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tulip/tulip_core.c	2009-09-09 18:13:59.000000000 -0400
@@ -570,16 +570,18 @@
 				   (unsigned int)tp->rx_ring[i].buffer2,
 				   buf[0], buf[1], buf[2]);
 			for (j = 0; buf[j] != 0xee && j < 1600; j++)
-				if (j < 100) printk(" %2.2x", buf[j]);
-			printk(" j=%d.\n", j);
+				if (j < 100)
+					printk(KERN_CONT " %2.2x", buf[j]);
+			printk(KERN_CONT " j=%d.\n", j);
 		}
 		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)tp->rx_ring);
 		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
-		printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
+			printk(KERN_CONT " %8.8x",
+			       (unsigned int)tp->rx_ring[i].status);
+		printk(KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
 		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
-		printk("\n");
+			printk(KERN_CONT " %8.8x", (unsigned int)tp->tx_ring[i].status);
+		printk(KERN_CONT "\n");
 	}
 #endif
 
@@ -650,8 +652,9 @@
 	int entry;
 	u32 flag;
 	dma_addr_t mapping;
+	unsigned long flags;
 
-	spin_lock_irq(&tp->lock);
+	spin_lock_irqsave(&tp->lock, flags);
 
 	/* Calculate the next Tx descriptor entry. */
 	entry = tp->cur_tx % TX_RING_SIZE;
@@ -686,7 +689,7 @@
 	/* Trigger an immediate transmit demand. */
 	iowrite32(0, tp->base_addr + CSR1);
 
-	spin_unlock_irq(&tp->lock);
+	spin_unlock_irqrestore(&tp->lock, flags);
 
 	dev->trans_start = jiffies;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/tulip/uli526x.c linux-libre-2.6.31-gnu/drivers/net/tulip/uli526x.c
--- linux-libre-2.6.30-gnu/drivers/net/tulip/uli526x.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tulip/uli526x.c	2009-09-09 18:13:59.000000000 -0400
@@ -591,7 +591,7 @@
 	if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
 		spin_unlock_irqrestore(&db->lock, flags);
 		printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_packet_cnt);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	/* Disable NIC interrupt */
diff -druN linux-libre-2.6.30-gnu/drivers/net/tulip/winbond-840.c linux-libre-2.6.31-gnu/drivers/net/tulip/winbond-840.c
--- linux-libre-2.6.30-gnu/drivers/net/tulip/winbond-840.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tulip/winbond-840.c	2009-09-09 18:13:59.000000000 -0400
@@ -142,7 +142,7 @@
 static const char version[] __initconst =
 	KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) "
 	DRV_RELDATE "  Donald Becker <becker@scyld.com>\n"
-	KERN_INFO "  http://www.scyld.com/network/drivers.html\n";
+	"  http://www.scyld.com/network/drivers.html\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver");
@@ -939,7 +939,7 @@
 		printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
 		for (i = 0; i < RX_RING_SIZE; i++)
 			printk(" %8.8x", (unsigned int)np->rx_ring[i].status);
-		printk("\n"KERN_DEBUG"  Tx ring %p: ", np->tx_ring);
+		printk(KERN_DEBUG"  Tx ring %p: ", np->tx_ring);
 		for (i = 0; i < TX_RING_SIZE; i++)
 			printk(" %8.8x", np->tx_ring[i].status);
 		printk("\n");
@@ -1520,7 +1520,7 @@
 			printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n",
 				   i, np->tx_ring[i].length,
 				   np->tx_ring[i].status, np->tx_ring[i].buffer1);
-		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
+		printk(KERN_DEBUG "  Rx ring %8.8x:\n",
 			   (int)np->rx_ring);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
@@ -1601,8 +1601,7 @@
 
 		/* no more hardware accesses behind this line. */
 
-		BUG_ON(np->csr6);
-		if (ioread32(ioaddr + IntrEnable)) BUG();
+		BUG_ON(np->csr6 || ioread32(ioaddr + IntrEnable));
 
 		/* pci_power_off(pdev, -1); */
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/tun.c linux-libre-2.6.31-gnu/drivers/net/tun.c
--- linux-libre-2.6.30-gnu/drivers/net/tun.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/tun.c	2009-09-09 18:13:59.000000000 -0400
@@ -486,12 +486,14 @@
 {
 	struct tun_file *tfile = file->private_data;
 	struct tun_struct *tun = __tun_get(tfile);
-	struct sock *sk = tun->sk;
+	struct sock *sk;
 	unsigned int mask = 0;
 
 	if (!tun)
 		return POLLERR;
 
+	sk = tun->sk;
+
 	DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
 
 	poll_wait(file, &tun->socket.wait, wait);
@@ -540,31 +542,38 @@
 
 /* Get packet from user space buffer */
 static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
-				       struct iovec *iv, size_t count,
+				       const struct iovec *iv, size_t count,
 				       int noblock)
 {
 	struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
 	struct sk_buff *skb;
 	size_t len = count, align = 0;
 	struct virtio_net_hdr gso = { 0 };
+	int offset = 0;
 
 	if (!(tun->flags & TUN_NO_PI)) {
 		if ((len -= sizeof(pi)) > count)
 			return -EINVAL;
 
-		if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
+		if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi)))
 			return -EFAULT;
+		offset += sizeof(pi);
 	}
 
 	if (tun->flags & TUN_VNET_HDR) {
 		if ((len -= sizeof(gso)) > count)
 			return -EINVAL;
 
-		if (memcpy_fromiovec((void *)&gso, iv, sizeof(gso)))
+		if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso)))
 			return -EFAULT;
 
+		if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
+		    gso.csum_start + gso.csum_offset + 2 > gso.hdr_len)
+			gso.hdr_len = gso.csum_start + gso.csum_offset + 2;
+
 		if (gso.hdr_len > len)
 			return -EINVAL;
+		offset += sizeof(gso);
 	}
 
 	if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
@@ -581,7 +590,7 @@
 		return PTR_ERR(skb);
 	}
 
-	if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) {
+	if (skb_copy_datagram_from_iovec(skb, 0, iv, offset, len)) {
 		tun->dev->stats.rx_dropped++;
 		kfree_skb(skb);
 		return -EFAULT;
@@ -673,7 +682,7 @@
 
 	DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count);
 
-	result = tun_get_user(tun, (struct iovec *)iv, iov_length(iv, count),
+	result = tun_get_user(tun, iv, iov_length(iv, count),
 			      file->f_flags & O_NONBLOCK);
 
 	tun_put(tun);
@@ -683,7 +692,7 @@
 /* Put packet to the user space buffer */
 static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
 				       struct sk_buff *skb,
-				       struct iovec *iv, int len)
+				       const struct iovec *iv, int len)
 {
 	struct tun_pi pi = { 0, skb->protocol };
 	ssize_t total = 0;
@@ -697,7 +706,7 @@
 			pi.flags |= TUN_PKT_STRIP;
 		}
 
-		if (memcpy_toiovec(iv, (void *) &pi, sizeof(pi)))
+		if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi)))
 			return -EFAULT;
 		total += sizeof(pi);
 	}
@@ -730,14 +739,15 @@
 			gso.csum_offset = skb->csum_offset;
 		} /* else everything is zero */
 
-		if (unlikely(memcpy_toiovec(iv, (void *)&gso, sizeof(gso))))
+		if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
+					       sizeof(gso))))
 			return -EFAULT;
 		total += sizeof(gso);
 	}
 
 	len = min_t(int, skb->len, len);
 
-	skb_copy_datagram_iovec(skb, 0, iv, len);
+	skb_copy_datagram_const_iovec(skb, 0, iv, total, len);
 	total += len;
 
 	tun->dev->stats.tx_packets++;
@@ -792,7 +802,7 @@
 		}
 		netif_wake_queue(tun->dev);
 
-		ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
+		ret = tun_put_user(tun, skb, iv, len);
 		kfree_skb(skb);
 		break;
 	}
@@ -840,12 +850,12 @@
 	if (!sock_writeable(sk))
 		return;
 
-	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-		wake_up_interruptible_sync(sk->sk_sleep);
-
 	if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags))
 		return;
 
+	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+		wake_up_interruptible_sync(sk->sk_sleep);
+
 	tun = container_of(sk, struct tun_sock, sk)->tun;
 	kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
 }
@@ -861,6 +871,52 @@
 	.obj_size	= sizeof(struct tun_sock),
 };
 
+static int tun_flags(struct tun_struct *tun)
+{
+	int flags = 0;
+
+	if (tun->flags & TUN_TUN_DEV)
+		flags |= IFF_TUN;
+	else
+		flags |= IFF_TAP;
+
+	if (tun->flags & TUN_NO_PI)
+		flags |= IFF_NO_PI;
+
+	if (tun->flags & TUN_ONE_QUEUE)
+		flags |= IFF_ONE_QUEUE;
+
+	if (tun->flags & TUN_VNET_HDR)
+		flags |= IFF_VNET_HDR;
+
+	return flags;
+}
+
+static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct tun_struct *tun = netdev_priv(to_net_dev(dev));
+	return sprintf(buf, "0x%x\n", tun_flags(tun));
+}
+
+static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct tun_struct *tun = netdev_priv(to_net_dev(dev));
+	return sprintf(buf, "%d\n", tun->owner);
+}
+
+static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct tun_struct *tun = netdev_priv(to_net_dev(dev));
+	return sprintf(buf, "%d\n", tun->group);
+}
+
+static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL);
+static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL);
+static DEVICE_ATTR(group, 0444, tun_show_group, NULL);
+
 static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 {
 	struct sock *sk;
@@ -870,6 +926,8 @@
 
 	dev = __dev_get_by_name(net, ifr->ifr_name);
 	if (dev) {
+		if (ifr->ifr_flags & IFF_TUN_EXCL)
+			return -EBUSY;
 		if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
 			tun = netdev_priv(dev);
 		else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops)
@@ -944,6 +1002,11 @@
 		if (err < 0)
 			goto err_free_sk;
 
+		if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
+		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
+		    device_create_file(&tun->dev->dev, &dev_attr_group))
+			printk(KERN_ERR "Failed to create tun sysfs files\n");
+
 		sk->sk_destruct = tun_sock_destruct;
 
 		err = tun_attach(tun, file);
@@ -985,34 +1048,15 @@
 	return err;
 }
 
-static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
+static int tun_get_iff(struct net *net, struct tun_struct *tun,
+		       struct ifreq *ifr)
 {
-	struct tun_struct *tun = tun_get(file);
-
-	if (!tun)
-		return -EBADFD;
-
 	DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
 
 	strcpy(ifr->ifr_name, tun->dev->name);
 
-	ifr->ifr_flags = 0;
-
-	if (ifr->ifr_flags & TUN_TUN_DEV)
-		ifr->ifr_flags |= IFF_TUN;
-	else
-		ifr->ifr_flags |= IFF_TAP;
-
-	if (tun->flags & TUN_NO_PI)
-		ifr->ifr_flags |= IFF_NO_PI;
-
-	if (tun->flags & TUN_ONE_QUEUE)
-		ifr->ifr_flags |= IFF_ONE_QUEUE;
-
-	if (tun->flags & TUN_VNET_HDR)
-		ifr->ifr_flags |= IFF_VNET_HDR;
+	ifr->ifr_flags = tun_flags(tun);
 
-	tun_put(tun);
 	return 0;
 }
 
@@ -1056,8 +1100,8 @@
 	return 0;
 }
 
-static int tun_chr_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg)
+static long tun_chr_ioctl(struct file *file, unsigned int cmd,
+			  unsigned long arg)
 {
 	struct tun_file *tfile = file->private_data;
 	struct tun_struct *tun;
@@ -1079,34 +1123,32 @@
 				(unsigned int __user*)argp);
 	}
 
+	rtnl_lock();
+
 	tun = __tun_get(tfile);
 	if (cmd == TUNSETIFF && !tun) {
-		int err;
-
 		ifr.ifr_name[IFNAMSIZ-1] = '\0';
 
-		rtnl_lock();
-		err = tun_set_iff(tfile->net, file, &ifr);
-		rtnl_unlock();
+		ret = tun_set_iff(tfile->net, file, &ifr);
 
-		if (err)
-			return err;
+		if (ret)
+			goto unlock;
 
 		if (copy_to_user(argp, &ifr, sizeof(ifr)))
-			return -EFAULT;
-		return 0;
+			ret = -EFAULT;
+		goto unlock;
 	}
 
-
+	ret = -EBADFD;
 	if (!tun)
-		return -EBADFD;
+		goto unlock;
 
 	DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
 
 	ret = 0;
 	switch (cmd) {
 	case TUNGETIFF:
-		ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr);
+		ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
 		if (ret)
 			break;
 
@@ -1152,7 +1194,6 @@
 
 	case TUNSETLINK:
 		/* Only allow setting the type when the interface is down */
-		rtnl_lock();
 		if (tun->dev->flags & IFF_UP) {
 			DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
 				tun->dev->name);
@@ -1162,7 +1203,6 @@
 			DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
 			ret = 0;
 		}
-		rtnl_unlock();
 		break;
 
 #ifdef TUN_DEBUG
@@ -1171,9 +1211,7 @@
 		break;
 #endif
 	case TUNSETOFFLOAD:
-		rtnl_lock();
 		ret = set_offload(tun->dev, arg);
-		rtnl_unlock();
 		break;
 
 	case TUNSETTXFILTER:
@@ -1181,9 +1219,7 @@
 		ret = -EINVAL;
 		if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
 			break;
-		rtnl_lock();
 		ret = update_filter(&tun->txflt, (void __user *)arg);
-		rtnl_unlock();
 		break;
 
 	case SIOCGIFHWADDR:
@@ -1199,9 +1235,7 @@
 		DBG(KERN_DEBUG "%s: set hw address: %pM\n",
 			tun->dev->name, ifr.ifr_hwaddr.sa_data);
 
-		rtnl_lock();
 		ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
-		rtnl_unlock();
 		break;
 
 	case TUNGETSNDBUF:
@@ -1224,7 +1258,10 @@
 		break;
 	};
 
-	tun_put(tun);
+unlock:
+	rtnl_unlock();
+	if (tun)
+		tun_put(tun);
 	return ret;
 }
 
@@ -1275,20 +1312,23 @@
 static int tun_chr_close(struct inode *inode, struct file *file)
 {
 	struct tun_file *tfile = file->private_data;
-	struct tun_struct *tun = __tun_get(tfile);
-
+	struct tun_struct *tun;
 
+	tun = __tun_get(tfile);
 	if (tun) {
-		DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name);
+		struct net_device *dev = tun->dev;
+
+		DBG(KERN_INFO "%s: tun_chr_close\n", dev->name);
 
-		rtnl_lock();
 		__tun_detach(tun);
 
 		/* If desireable, unregister the netdevice. */
-		if (!(tun->flags & TUN_PERSIST))
-			unregister_netdevice(tun->dev);
-
-		rtnl_unlock();
+		if (!(tun->flags & TUN_PERSIST)) {
+			rtnl_lock();
+			if (dev->reg_state == NETREG_REGISTERED)
+				unregister_netdevice(dev);
+			rtnl_unlock();
+		}
 	}
 
 	tun = tfile->tun;
@@ -1309,7 +1349,7 @@
 	.write = do_sync_write,
 	.aio_write = tun_chr_aio_write,
 	.poll	= tun_chr_poll,
-	.ioctl	= tun_chr_ioctl,
+	.unlocked_ioctl = tun_chr_ioctl,
 	.open	= tun_chr_open,
 	.release = tun_chr_close,
 	.fasync = tun_chr_fasync
@@ -1318,6 +1358,7 @@
 static struct miscdevice tun_miscdev = {
 	.minor = TUN_MINOR,
 	.name = "tun",
+	.devnode = "net/tun",
 	.fops = &tun_fops,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/ucc_geth.c linux-libre-2.6.31-gnu/drivers/net/ucc_geth.c
--- linux-libre-2.6.30-gnu/drivers/net/ucc_geth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ucc_geth.c	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved.
  *
  * Author: Shlomi Gridish <gridish@freescale.com>
  *	   Li Yang <leoli@freescale.com>
@@ -27,6 +27,7 @@
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/workqueue.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
 #include <asm/uaccess.h>
@@ -270,7 +271,7 @@
 				  u8 num_entries,
 				  u32 thread_size,
 				  u32 thread_alignment,
-				  enum qe_risc_allocation risc,
+				  unsigned int risc,
 				  int skip_page_for_first_entry)
 {
 	u32 init_enet_offset;
@@ -307,7 +308,7 @@
 static int return_init_enet_entries(struct ucc_geth_private *ugeth,
 				    u32 *p_start,
 				    u8 num_entries,
-				    enum qe_risc_allocation risc,
+				    unsigned int risc,
 				    int skip_page_for_first_entry)
 {
 	u32 init_enet_offset;
@@ -342,7 +343,7 @@
 				  u32 __iomem *p_start,
 				  u8 num_entries,
 				  u32 thread_size,
-				  enum qe_risc_allocation risc,
+				  unsigned int risc,
 				  int skip_page_for_first_entry)
 {
 	u32 init_enet_offset;
@@ -1409,6 +1410,9 @@
 	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
 		upsmr |= UCC_GETH_UPSMR_TBIM;
 	}
+	if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII))
+		upsmr |= UCC_GETH_UPSMR_SGMM;
+
 	out_be32(&uf_regs->upsmr, upsmr);
 
 	/* Disable autonegotiation in tbi mode, because by default it
@@ -1530,6 +1534,49 @@
 	spin_unlock_irqrestore(&ugeth->lock, flags);
 }
 
+/* Initialize TBI PHY interface for communicating with the
+ * SERDES lynx PHY on the chip.  We communicate with this PHY
+ * through the MDIO bus on each controller, treating it as a
+ * "normal" PHY at the address found in the UTBIPA register.  We assume
+ * that the UTBIPA register is valid.  Either the MDIO bus code will set
+ * it to a value that doesn't conflict with other PHYs on the bus, or the
+ * value doesn't matter, as there are no other PHYs on the bus.
+ */
+static void uec_configure_serdes(struct net_device *dev)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct ucc_geth_info *ug_info = ugeth->ug_info;
+	struct phy_device *tbiphy;
+
+	if (!ug_info->tbi_node) {
+		dev_warn(&dev->dev, "SGMII mode requires that the device "
+			"tree specify a tbi-handle\n");
+		return;
+	}
+
+	tbiphy = of_phy_find_device(ug_info->tbi_node);
+	if (!tbiphy) {
+		dev_err(&dev->dev, "error: Could not get TBI device\n");
+		return;
+	}
+
+	/*
+	 * If the link is already up, we must already be ok, and don't need to
+	 * configure and reset the TBI<->SerDes link.  Maybe U-Boot configured
+	 * everything for us?  Resetting it takes the link down and requires
+	 * several seconds for it to come back.
+	 */
+	if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS)
+		return;
+
+	/* Single clk mode, mii mode off(for serdes communication) */
+	phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
+
+	phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
+
+	phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
+}
+
 /* Configure the PHY for dev.
  * returns 0 if success.  -1 if failure
  */
@@ -1543,14 +1590,19 @@
 	priv->oldspeed = 0;
 	priv->oldduplex = -1;
 
-	phydev = phy_connect(dev, ug_info->phy_bus_id, &adjust_link, 0,
-			     priv->phy_interface);
-
-	if (IS_ERR(phydev)) {
-		printk("%s: Could not attach to PHY\n", dev->name);
-		return PTR_ERR(phydev);
+	phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,
+				priv->phy_interface);
+	if (!phydev)
+		phydev = of_phy_connect_fixed_link(dev, &adjust_link,
+						   priv->phy_interface);
+	if (!phydev) {
+		dev_err(&dev->dev, "Could not attach to PHY\n");
+		return -ENODEV;
 	}
 
+	if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
+		uec_configure_serdes(dev);
+
 	phydev->supported &= (ADVERTISED_10baseT_Half |
 				 ADVERTISED_10baseT_Full |
 				 ADVERTISED_100baseT_Half |
@@ -2135,6 +2187,14 @@
 		return -ENOMEM;
 	}
 
+	/* read the number of risc engines, update the riscTx and riscRx
+	 * if there are 4 riscs in QE
+	 */
+	if (qe_get_num_of_risc() == 4) {
+		ug_info->riscTx = QE_RISC_ALLOCATION_FOUR_RISCS;
+		ug_info->riscRx = QE_RISC_ALLOCATION_FOUR_RISCS;
+	}
+
 	ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs));
 	if (!ugeth->ug_regs) {
 		if (netif_msg_probe(ugeth))
@@ -3051,10 +3111,11 @@
 	u8 __iomem *bd;			/* BD pointer */
 	u32 bd_status;
 	u8 txQ = 0;
+	unsigned long flags;
 
 	ugeth_vdbg("%s: IN", __func__);
 
-	spin_lock_irq(&ugeth->lock);
+	spin_lock_irqsave(&ugeth->lock, flags);
 
 	dev->stats.tx_bytes += skb->len;
 
@@ -3111,7 +3172,7 @@
 	uccf = ugeth->uccf;
 	out_be16(uccf->p_utodr, UCC_FAST_TOD);
 #endif
-	spin_unlock_irq(&ugeth->lock);
+	spin_unlock_irqrestore(&ugeth->lock, flags);
 
 	return 0;
 }
@@ -3217,7 +3278,7 @@
 		dev->stats.tx_packets++;
 
 		/* Free the sk buffer associated with this TxBD */
-		dev_kfree_skb_irq(ugeth->
+		dev_kfree_skb(ugeth->
 				  tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]);
 		ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
 		ugeth->skb_dirtytx[txQ] =
@@ -3251,9 +3312,15 @@
 	for (i = 0; i < ug_info->numQueuesRx; i++)
 		howmany += ucc_geth_rx(ugeth, i, budget - howmany);
 
+	/* Tx event processing */
+	spin_lock(&ugeth->lock);
+	for (i = 0; i < ug_info->numQueuesTx; i++)
+		ucc_geth_tx(ugeth->ndev, i);
+	spin_unlock(&ugeth->lock);
+
 	if (howmany < budget) {
 		napi_complete(napi);
-		setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS);
+		setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS | UCCE_TX_EVENTS);
 	}
 
 	return howmany;
@@ -3267,8 +3334,6 @@
 	struct ucc_geth_info *ug_info;
 	register u32 ucce;
 	register u32 uccm;
-	register u32 tx_mask;
-	u8 i;
 
 	ugeth_vdbg("%s: IN", __func__);
 
@@ -3282,27 +3347,14 @@
 	out_be32(uccf->p_ucce, ucce);
 
 	/* check for receive events that require processing */
-	if (ucce & UCCE_RX_EVENTS) {
+	if (ucce & (UCCE_RX_EVENTS | UCCE_TX_EVENTS)) {
 		if (napi_schedule_prep(&ugeth->napi)) {
-			uccm &= ~UCCE_RX_EVENTS;
+			uccm &= ~(UCCE_RX_EVENTS | UCCE_TX_EVENTS);
 			out_be32(uccf->p_uccm, uccm);
 			__napi_schedule(&ugeth->napi);
 		}
 	}
 
-	/* Tx event processing */
-	if (ucce & UCCE_TX_EVENTS) {
-		spin_lock(&ugeth->lock);
-		tx_mask = UCC_GETH_UCCE_TXB0;
-		for (i = 0; i < ug_info->numQueuesTx; i++) {
-			if (ucce & tx_mask)
-				ucc_geth_tx(dev, i);
-			ucce &= ~tx_mask;
-			tx_mask <<= 1;
-		}
-		spin_unlock(&ugeth->lock);
-	}
-
 	/* Errors and other events */
 	if (ucce & UCCE_OTHER) {
 		if (ucce & UCC_GETH_UCCE_BSY)
@@ -3331,6 +3383,37 @@
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
 
+static int ucc_geth_set_mac_addr(struct net_device *dev, void *p)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	/*
+	 * If device is not running, we will set mac addr register
+	 * when opening the device.
+	 */
+	if (!netif_running(dev))
+		return 0;
+
+	spin_lock_irq(&ugeth->lock);
+	init_mac_station_addr_regs(dev->dev_addr[0],
+				   dev->dev_addr[1],
+				   dev->dev_addr[2],
+				   dev->dev_addr[3],
+				   dev->dev_addr[4],
+				   dev->dev_addr[5],
+				   &ugeth->ug_regs->macstnaddr1,
+				   &ugeth->ug_regs->macstnaddr2);
+	spin_unlock_irq(&ugeth->lock);
+
+	return 0;
+}
+
 /* Called when something needs to use the ethernet device */
 /* Returns 0 for success. */
 static int ucc_geth_open(struct net_device *dev)
@@ -3498,6 +3581,8 @@
 		return PHY_INTERFACE_MODE_RGMII_RXID;
 	if (strcasecmp(phy_connection_type, "rtbi") == 0)
 		return PHY_INTERFACE_MODE_RTBI;
+	if (strcasecmp(phy_connection_type, "sgmii") == 0)
+		return PHY_INTERFACE_MODE_SGMII;
 
 	return PHY_INTERFACE_MODE_MII;
 }
@@ -3507,7 +3592,7 @@
 	.ndo_stop		= ucc_geth_close,
 	.ndo_start_xmit		= ucc_geth_start_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_set_mac_address	= ucc_geth_set_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_multicast_list	= ucc_geth_set_multi,
 	.ndo_tx_timeout		= ucc_geth_timeout,
@@ -3520,15 +3605,11 @@
 {
 	struct device *device = &ofdev->dev;
 	struct device_node *np = ofdev->node;
-	struct device_node *mdio;
 	struct net_device *dev = NULL;
 	struct ucc_geth_private *ugeth = NULL;
 	struct ucc_geth_info *ug_info;
 	struct resource res;
-	struct device_node *phy;
 	int err, ucc_num, max_speed = 0;
-	const phandle *ph;
-	const u32 *fixed_link;
 	const unsigned int *prop;
 	const char *sprop;
 	const void *mac_addr;
@@ -3544,6 +3625,7 @@
 		PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII,
 		PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
 		PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
+		PHY_INTERFACE_MODE_SGMII,
 	};
 
 	ugeth_vdbg("%s: IN", __func__);
@@ -3625,48 +3707,17 @@
 
 	ug_info->uf_info.regs = res.start;
 	ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
-	fixed_link = of_get_property(np, "fixed-link", NULL);
-	if (fixed_link) {
-		snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id),
-			 PHY_ID_FMT, "0", fixed_link[0]);
-		phy = NULL;
-	} else {
-		char bus_name[MII_BUS_ID_SIZE];
-
-		ph = of_get_property(np, "phy-handle", NULL);
-		phy = of_find_node_by_phandle(*ph);
-
-		if (phy == NULL)
-			return -ENODEV;
-
-		/* set the PHY address */
-		prop = of_get_property(phy, "reg", NULL);
-		if (prop == NULL)
-			return -1;
-
-		/* Set the bus id */
-		mdio = of_get_parent(phy);
 
-		if (mdio == NULL)
-			return -ENODEV;
-
-		err = of_address_to_resource(mdio, 0, &res);
+	ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
 
-		if (err) {
-			of_node_put(mdio);
-			return err;
-		}
-		fsl_pq_mdio_bus_name(bus_name, mdio);
-		of_node_put(mdio);
-		snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id),
-			"%s:%02x", bus_name, *prop);
-	}
+	/* Find the TBI PHY node.  If it's not there, we don't support SGMII */
+	ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
 
 	/* get the phy interface type, or default to MII */
 	prop = of_get_property(np, "phy-connection-type", NULL);
 	if (!prop) {
 		/* handle interface property present in old trees */
-		prop = of_get_property(phy, "interface", NULL);
+		prop = of_get_property(ug_info->phy_node, "interface", NULL);
 		if (prop != NULL) {
 			phy_interface = enet_to_phy_interface[*prop];
 			max_speed = enet_to_speed[*prop];
@@ -3686,6 +3737,7 @@
 		case PHY_INTERFACE_MODE_RGMII_TXID:
 		case PHY_INTERFACE_MODE_TBI:
 		case PHY_INTERFACE_MODE_RTBI:
+		case PHY_INTERFACE_MODE_SGMII:
 			max_speed = SPEED_1000;
 			break;
 		default:
@@ -3702,7 +3754,15 @@
 		ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT;
 		ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT;
 		ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4;
-		ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
+
+		/* If QE's snum number is 46 which means we need to support
+		 * 4 UECs at 1000Base-T simultaneously, we need to allocate
+		 * more Threads to Rx.
+		 */
+		if (qe_get_num_of_snums() == 46)
+			ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6;
+		else
+			ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
 	}
 
 	if (netif_msg_probe(&debug))
@@ -3735,7 +3795,7 @@
 	dev->netdev_ops = &ucc_geth_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work);
-	netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT);
+	netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, 64);
 	dev->mtu = 1500;
 
 	ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT);
diff -druN linux-libre-2.6.30-gnu/drivers/net/ucc_geth_ethtool.c linux-libre-2.6.31-gnu/drivers/net/ucc_geth_ethtool.c
--- linux-libre-2.6.30-gnu/drivers/net/ucc_geth_ethtool.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ucc_geth_ethtool.c	2009-09-09 18:13:59.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Limitation:
  * Can only get/set setttings of the first queue.
- * Need to re-open the interface manually after changing some paramters.
+ * Need to re-open the interface manually after changing some parameters.
  *
  * 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
diff -druN linux-libre-2.6.30-gnu/drivers/net/ucc_geth.h linux-libre-2.6.31-gnu/drivers/net/ucc_geth.h
--- linux-libre-2.6.30-gnu/drivers/net/ucc_geth.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/ucc_geth.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ * Copyright (C) Freescale Semicondutor, Inc. 2006-2009. All rights reserved.
  *
  * Author: Shlomi Gridish <gridish@freescale.com>
  *
@@ -193,6 +193,31 @@
 #define	ENET_TBI_MII_JD		0x10	/* Jitter diagnostics */
 #define	ENET_TBI_MII_TBICON	0x11	/* TBI control */
 
+/* TBI MDIO register bit fields*/
+#define TBISR_LSTATUS          0x0004
+#define TBICON_CLK_SELECT       0x0020
+#define TBIANA_ASYMMETRIC_PAUSE 0x0100
+#define TBIANA_SYMMETRIC_PAUSE  0x0080
+#define TBIANA_HALF_DUPLEX      0x0040
+#define TBIANA_FULL_DUPLEX      0x0020
+#define TBICR_PHY_RESET         0x8000
+#define TBICR_ANEG_ENABLE       0x1000
+#define TBICR_RESTART_ANEG      0x0200
+#define TBICR_FULL_DUPLEX       0x0100
+#define TBICR_SPEED1_SET        0x0040
+
+#define TBIANA_SETTINGS ( \
+		TBIANA_ASYMMETRIC_PAUSE \
+		| TBIANA_SYMMETRIC_PAUSE \
+		| TBIANA_FULL_DUPLEX \
+		)
+#define TBICR_SETTINGS ( \
+		TBICR_PHY_RESET \
+		| TBICR_ANEG_ENABLE \
+		| TBICR_FULL_DUPLEX \
+		| TBICR_SPEED1_SET \
+		)
+
 /* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
 #define MACCFG1_FLOW_RX                         0x00000020	/* Flow Control
 								   Rx */
@@ -852,7 +877,6 @@
 /* Driver definitions */
 #define TX_BD_RING_LEN                          0x10
 #define RX_BD_RING_LEN                          0x10
-#define UCC_GETH_DEV_WEIGHT                     TX_BD_RING_LEN
 
 #define TX_RING_MOD_MASK(size)                  (size-1)
 #define RX_RING_MOD_MASK(size)                  (size-1)
@@ -1100,7 +1124,8 @@
 	u32 eventRegMask;
 	u16 pausePeriod;
 	u16 extensionField;
-	char phy_bus_id[BUS_ID_SIZE];
+	struct device_node *phy_node;
+	struct device_node *tbi_node;
 	u8 weightfactor[NUM_TX_QUEUES];
 	u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
 	u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
@@ -1120,8 +1145,8 @@
 	enum ucc_geth_maccfg2_pad_and_crc_mode padAndCrc;
 	enum ucc_geth_num_of_threads numThreadsTx;
 	enum ucc_geth_num_of_threads numThreadsRx;
-	enum qe_risc_allocation riscTx;
-	enum qe_risc_allocation riscRx;
+	unsigned int riscTx;
+	unsigned int riscRx;
 };
 
 /* structure representing UCC GETH */
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/cdc_eem.c linux-libre-2.6.31-gnu/drivers/net/usb/cdc_eem.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/cdc_eem.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/cdc_eem.c	2009-09-09 18:13:59.000000000 -0400
@@ -311,7 +311,7 @@
 			 *	bmCRC = 0	: CRC = 0xDEADBEEF
 			 */
 			if (header & BIT(14))
-				crc2 = ~crc32_le(~0, skb2->data, len);
+				crc2 = ~crc32_le(~0, skb2->data, skb2->len);
 			else
 				crc2 = 0xdeadbeef;
 
@@ -319,7 +319,7 @@
 				return crc == crc2;
 
 			if (unlikely(crc != crc2)) {
-				dev->stats.rx_errors++;
+				dev->net->stats.rx_errors++;
 				dev_kfree_skb_any(skb2);
 			} else
 				usbnet_skb_return(dev, skb2);
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/cdc_ether.c linux-libre-2.6.31-gnu/drivers/net/usb/cdc_ether.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/cdc_ether.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/cdc_ether.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/ctype.h>
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
 #include <linux/mii.h>
@@ -389,36 +388,6 @@
 	}
 }
 
-static u8 nibble(unsigned char c)
-{
-	if (likely(isdigit(c)))
-		return c - '0';
-	c = toupper(c);
-	if (likely(isxdigit(c)))
-		return 10 + c - 'A';
-	return 0;
-}
-
-static inline int
-get_ethernet_addr(struct usbnet *dev, struct usb_cdc_ether_desc *e)
-{
-	int 		tmp, i;
-	unsigned char	buf [13];
-
-	tmp = usb_string(dev->udev, e->iMACAddress, buf, sizeof buf);
-	if (tmp != 12) {
-		dev_dbg(&dev->udev->dev,
-			"bad MAC string %d fetch, %d\n", e->iMACAddress, tmp);
-		if (tmp >= 0)
-			tmp = -EINVAL;
-		return tmp;
-	}
-	for (i = tmp = 0; i < 6; i++, tmp += 2)
-		dev->net->dev_addr [i] =
-			(nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]);
-	return 0;
-}
-
 static int cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int				status;
@@ -428,7 +397,7 @@
 	if (status < 0)
 		return status;
 
-	status = get_ethernet_addr(dev, info->ether);
+	status = usbnet_get_ethernet_addr(dev, info->ether->iMACAddress);
 	if (status < 0) {
 		usb_set_intfdata(info->data, NULL);
 		usb_driver_release_interface(driver_of(intf), info->data);
@@ -564,6 +533,31 @@
 	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Ericsson F3507g ver. 2 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1902, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Ericsson F3607gw */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1904, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Ericsson F3307 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Toshiba F3507g */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Dell F3507g */
+	USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8147, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
 },
 	{ },		// END
 };
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/cdc-phonet.c linux-libre-2.6.31-gnu/drivers/net/usb/cdc-phonet.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/cdc-phonet.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/usb/cdc-phonet.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,461 @@
+/*
+ * phonet.c -- USB CDC Phonet host driver
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * Author: Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_phonet.h>
+
+#define PN_MEDIA_USB	0x1B
+
+static const unsigned rxq_size = 17;
+
+struct usbpn_dev {
+	struct net_device	*dev;
+
+	struct usb_interface	*intf, *data_intf;
+	struct usb_device	*usb;
+	unsigned int		tx_pipe, rx_pipe;
+	u8 active_setting;
+	u8 disconnected;
+
+	unsigned		tx_queue;
+	spinlock_t		tx_lock;
+
+	spinlock_t		rx_lock;
+	struct sk_buff		*rx_skb;
+	struct urb		*urbs[0];
+};
+
+static void tx_complete(struct urb *req);
+static void rx_complete(struct urb *req);
+
+/*
+ * Network device callbacks
+ */
+static int usbpn_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct usbpn_dev *pnd = netdev_priv(dev);
+	struct urb *req = NULL;
+	unsigned long flags;
+	int err;
+
+	if (skb->protocol != htons(ETH_P_PHONET))
+		goto drop;
+
+	req = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!req)
+		goto drop;
+	usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len,
+				tx_complete, skb);
+	req->transfer_flags = URB_ZERO_PACKET;
+	err = usb_submit_urb(req, GFP_ATOMIC);
+	if (err) {
+		usb_free_urb(req);
+		goto drop;
+	}
+
+	spin_lock_irqsave(&pnd->tx_lock, flags);
+	pnd->tx_queue++;
+	if (pnd->tx_queue >= dev->tx_queue_len)
+		netif_stop_queue(dev);
+	spin_unlock_irqrestore(&pnd->tx_lock, flags);
+	return 0;
+
+drop:
+	dev_kfree_skb(skb);
+	dev->stats.tx_dropped++;
+	return 0;
+}
+
+static void tx_complete(struct urb *req)
+{
+	struct sk_buff *skb = req->context;
+	struct net_device *dev = skb->dev;
+	struct usbpn_dev *pnd = netdev_priv(dev);
+
+	switch (req->status) {
+	case 0:
+		dev->stats.tx_bytes += skb->len;
+		break;
+
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		dev->stats.tx_aborted_errors++;
+	default:
+		dev->stats.tx_errors++;
+		dev_dbg(&dev->dev, "TX error (%d)\n", req->status);
+	}
+	dev->stats.tx_packets++;
+
+	spin_lock(&pnd->tx_lock);
+	pnd->tx_queue--;
+	netif_wake_queue(dev);
+	spin_unlock(&pnd->tx_lock);
+
+	dev_kfree_skb_any(skb);
+	usb_free_urb(req);
+}
+
+static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags)
+{
+	struct net_device *dev = pnd->dev;
+	struct page *page;
+	int err;
+
+	page = __netdev_alloc_page(dev, gfp_flags);
+	if (!page)
+		return -ENOMEM;
+
+	usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page),
+				PAGE_SIZE, rx_complete, dev);
+	req->transfer_flags = 0;
+	err = usb_submit_urb(req, gfp_flags);
+	if (unlikely(err)) {
+		dev_dbg(&dev->dev, "RX submit error (%d)\n", err);
+		netdev_free_page(dev, page);
+	}
+	return err;
+}
+
+static void rx_complete(struct urb *req)
+{
+	struct net_device *dev = req->context;
+	struct usbpn_dev *pnd = netdev_priv(dev);
+	struct page *page = virt_to_page(req->transfer_buffer);
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	switch (req->status) {
+	case 0:
+		spin_lock_irqsave(&pnd->rx_lock, flags);
+		skb = pnd->rx_skb;
+		if (!skb) {
+			skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
+			if (likely(skb)) {
+				/* Can't use pskb_pull() on page in IRQ */
+				memcpy(skb_put(skb, 1), page_address(page), 1);
+				skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+						page, 1, req->actual_length);
+				page = NULL;
+			}
+		} else {
+			skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+					page, 0, req->actual_length);
+			page = NULL;
+		}
+		if (req->actual_length < PAGE_SIZE)
+			pnd->rx_skb = NULL; /* Last fragment */
+		else
+			skb = NULL;
+		spin_unlock_irqrestore(&pnd->rx_lock, flags);
+		if (skb) {
+			skb->protocol = htons(ETH_P_PHONET);
+			skb_reset_mac_header(skb);
+			__skb_pull(skb, 1);
+			skb->dev = dev;
+			dev->stats.rx_packets++;
+			dev->stats.rx_bytes += skb->len;
+
+			netif_rx(skb);
+		}
+		goto resubmit;
+
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		req = NULL;
+		break;
+
+	case -EOVERFLOW:
+		dev->stats.rx_over_errors++;
+		dev_dbg(&dev->dev, "RX overflow\n");
+		break;
+
+	case -EILSEQ:
+		dev->stats.rx_crc_errors++;
+		break;
+	}
+
+	dev->stats.rx_errors++;
+resubmit:
+	if (page)
+		netdev_free_page(dev, page);
+	if (req)
+		rx_submit(pnd, req, GFP_ATOMIC);
+}
+
+static int usbpn_close(struct net_device *dev);
+
+static int usbpn_open(struct net_device *dev)
+{
+	struct usbpn_dev *pnd = netdev_priv(dev);
+	int err;
+	unsigned i;
+	unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
+
+	err = usb_set_interface(pnd->usb, num, pnd->active_setting);
+	if (err)
+		return err;
+
+	for (i = 0; i < rxq_size; i++) {
+		struct urb *req = usb_alloc_urb(0, GFP_KERNEL);
+
+		if (!req || rx_submit(pnd, req, GFP_KERNEL)) {
+			usbpn_close(dev);
+			return -ENOMEM;
+		}
+		pnd->urbs[i] = req;
+	}
+
+	netif_wake_queue(dev);
+	return 0;
+}
+
+static int usbpn_close(struct net_device *dev)
+{
+	struct usbpn_dev *pnd = netdev_priv(dev);
+	unsigned i;
+	unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
+
+	netif_stop_queue(dev);
+
+	for (i = 0; i < rxq_size; i++) {
+		struct urb *req = pnd->urbs[i];
+
+		if (!req)
+			continue;
+		usb_kill_urb(req);
+		usb_free_urb(req);
+		pnd->urbs[i] = NULL;
+	}
+
+	return usb_set_interface(pnd->usb, num, !pnd->active_setting);
+}
+
+static int usbpn_set_mtu(struct net_device *dev, int new_mtu)
+{
+	if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+static const struct net_device_ops usbpn_ops = {
+	.ndo_open	= usbpn_open,
+	.ndo_stop	= usbpn_close,
+	.ndo_start_xmit = usbpn_xmit,
+	.ndo_change_mtu = usbpn_set_mtu,
+};
+
+static void usbpn_setup(struct net_device *dev)
+{
+	dev->features		= 0;
+	dev->netdev_ops		= &usbpn_ops,
+	dev->header_ops		= &phonet_header_ops;
+	dev->type		= ARPHRD_PHONET;
+	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
+	dev->mtu		= PHONET_MAX_MTU;
+	dev->hard_header_len	= 1;
+	dev->dev_addr[0]	= PN_MEDIA_USB;
+	dev->addr_len		= 1;
+	dev->tx_queue_len	= 3;
+
+	dev->destructor		= free_netdev;
+}
+
+/*
+ * USB driver callbacks
+ */
+static struct usb_device_id usbpn_ids[] = {
+	{
+		.match_flags = USB_DEVICE_ID_MATCH_VENDOR
+			| USB_DEVICE_ID_MATCH_INT_CLASS
+			| USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+		.idVendor = 0x0421, /* Nokia */
+		.bInterfaceClass = USB_CLASS_COMM,
+		.bInterfaceSubClass = 0xFE,
+	},
+	{ },
+};
+
+MODULE_DEVICE_TABLE(usb, usbpn_ids);
+
+static struct usb_driver usbpn_driver;
+
+int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	static const char ifname[] = "usbpn%d";
+	const struct usb_cdc_union_desc *union_header = NULL;
+	const struct usb_cdc_header_desc *phonet_header = NULL;
+	const struct usb_host_interface *data_desc;
+	struct usb_interface *data_intf;
+	struct usb_device *usbdev = interface_to_usbdev(intf);
+	struct net_device *dev;
+	struct usbpn_dev *pnd;
+	u8 *data;
+	int len, err;
+
+	data = intf->altsetting->extra;
+	len = intf->altsetting->extralen;
+	while (len >= 3) {
+		u8 dlen = data[0];
+		if (dlen < 3)
+			return -EINVAL;
+
+		/* bDescriptorType */
+		if (data[1] == USB_DT_CS_INTERFACE) {
+			/* bDescriptorSubType */
+			switch (data[2]) {
+			case USB_CDC_UNION_TYPE:
+				if (union_header || dlen < 5)
+					break;
+				union_header =
+					(struct usb_cdc_union_desc *)data;
+				break;
+			case 0xAB:
+				if (phonet_header || dlen < 5)
+					break;
+				phonet_header =
+					(struct usb_cdc_header_desc *)data;
+				break;
+			}
+		}
+		data += dlen;
+		len -= dlen;
+	}
+
+	if (!union_header || !phonet_header)
+		return -EINVAL;
+
+	data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
+	if (data_intf == NULL)
+		return -ENODEV;
+	/* Data interface has one inactive and one active setting */
+	if (data_intf->num_altsetting != 2)
+		return -EINVAL;
+	if (data_intf->altsetting[0].desc.bNumEndpoints == 0
+	 && data_intf->altsetting[1].desc.bNumEndpoints == 2)
+		data_desc = data_intf->altsetting + 1;
+	else
+	if (data_intf->altsetting[0].desc.bNumEndpoints == 2
+	 && data_intf->altsetting[1].desc.bNumEndpoints == 0)
+		data_desc = data_intf->altsetting;
+	else
+		return -EINVAL;
+
+	dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size,
+				ifname, usbpn_setup);
+	if (!dev)
+		return -ENOMEM;
+
+	pnd = netdev_priv(dev);
+	SET_NETDEV_DEV(dev, &intf->dev);
+	netif_stop_queue(dev);
+
+	pnd->dev = dev;
+	pnd->usb = usb_get_dev(usbdev);
+	pnd->intf = intf;
+	pnd->data_intf = data_intf;
+	spin_lock_init(&pnd->tx_lock);
+	spin_lock_init(&pnd->rx_lock);
+	/* Endpoints */
+	if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) {
+		pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
+			data_desc->endpoint[0].desc.bEndpointAddress);
+		pnd->tx_pipe = usb_sndbulkpipe(usbdev,
+			data_desc->endpoint[1].desc.bEndpointAddress);
+	} else {
+		pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
+			data_desc->endpoint[1].desc.bEndpointAddress);
+		pnd->tx_pipe = usb_sndbulkpipe(usbdev,
+			data_desc->endpoint[0].desc.bEndpointAddress);
+	}
+	pnd->active_setting = data_desc - data_intf->altsetting;
+
+	err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd);
+	if (err)
+		goto out;
+
+	/* Force inactive mode until the network device is brought UP */
+	usb_set_interface(usbdev, union_header->bSlaveInterface0,
+				!pnd->active_setting);
+	usb_set_intfdata(intf, pnd);
+
+	err = register_netdev(dev);
+	if (err) {
+		usb_driver_release_interface(&usbpn_driver, data_intf);
+		goto out;
+	}
+
+	dev_dbg(&dev->dev, "USB CDC Phonet device found\n");
+	return 0;
+
+out:
+	usb_set_intfdata(intf, NULL);
+	free_netdev(dev);
+	return err;
+}
+
+static void usbpn_disconnect(struct usb_interface *intf)
+{
+	struct usbpn_dev *pnd = usb_get_intfdata(intf);
+	struct usb_device *usb = pnd->usb;
+
+	if (pnd->disconnected)
+		return;
+
+	pnd->disconnected = 1;
+	usb_driver_release_interface(&usbpn_driver,
+			(pnd->intf == intf) ? pnd->data_intf : pnd->intf);
+	unregister_netdev(pnd->dev);
+	usb_put_dev(usb);
+}
+
+static struct usb_driver usbpn_driver = {
+	.name =		"cdc_phonet",
+	.probe =	usbpn_probe,
+	.disconnect =	usbpn_disconnect,
+	.id_table =	usbpn_ids,
+};
+
+static int __init usbpn_init(void)
+{
+	return usb_register(&usbpn_driver);
+}
+
+static void __exit usbpn_exit(void)
+{
+	usb_deregister(&usbpn_driver);
+}
+
+module_init(usbpn_init);
+module_exit(usbpn_exit);
+
+MODULE_AUTHOR("Remi Denis-Courmont");
+MODULE_DESCRIPTION("USB CDC Phonet host interface");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/cdc_subset.c linux-libre-2.6.31-gnu/drivers/net/usb/cdc_subset.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/cdc_subset.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/cdc_subset.c	2009-09-09 18:13:59.000000000 -0400
@@ -307,9 +307,10 @@
 	USB_DEVICE (0x1286, 0x8001),    // "blob" bootloader
 	.driver_info =  (unsigned long) &blob_info,
 }, {
-	// Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config
-	// e.g. Gumstix, current OpenZaurus, ...
-	USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
+	// Linux Ethernet/RNDIS gadget, mostly on PXA, second config
+	// e.g. Gumstix, current OpenZaurus, ... or anything else
+	// that just enables this gadget option.
+	USB_DEVICE (0x0525, 0xa4a2),
 	.driver_info =	(unsigned long) &linuxdev_info,
 },
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/dm9601.c linux-libre-2.6.31-gnu/drivers/net/usb/dm9601.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/dm9601.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/dm9601.c	2009-09-09 18:13:59.000000000 -0400
@@ -497,10 +497,10 @@
 	int len;
 
 	/* format:
-	   b0: rx status
-	   b1: packet length (incl crc) low
-	   b2: packet length (incl crc) high
-	   b3..n-4: packet data
+	   b1: rx status
+	   b2: packet length (incl crc) low
+	   b3: packet length (incl crc) high
+	   b4..n-4: packet data
 	   bn-3..bn: ethernet crc
 	 */
 
@@ -513,11 +513,11 @@
 	len = (skb->data[1] | (skb->data[2] << 8)) - 4;
 
 	if (unlikely(status & 0xbf)) {
-		if (status & 0x01) dev->stats.rx_fifo_errors++;
-		if (status & 0x02) dev->stats.rx_crc_errors++;
-		if (status & 0x04) dev->stats.rx_frame_errors++;
-		if (status & 0x20) dev->stats.rx_missed_errors++;
-		if (status & 0x90) dev->stats.rx_length_errors++;
+		if (status & 0x01) dev->net->stats.rx_fifo_errors++;
+		if (status & 0x02) dev->net->stats.rx_crc_errors++;
+		if (status & 0x04) dev->net->stats.rx_frame_errors++;
+		if (status & 0x20) dev->net->stats.rx_missed_errors++;
+		if (status & 0x90) dev->net->stats.rx_length_errors++;
 		return 0;
 	}
 
@@ -533,8 +533,8 @@
 	int len;
 
 	/* format:
-	   b0: packet length low
-	   b1: packet length high
+	   b1: packet length low
+	   b2: packet length high
 	   b3..n: packet data
 	*/
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/hso.c linux-libre-2.6.31-gnu/drivers/net/usb/hso.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/hso.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/hso.c	2009-09-09 18:13:59.000000000 -0400
@@ -482,7 +482,7 @@
 				       struct device_attribute *attr,
 				       char *buf)
 {
-	struct hso_device *hso_dev = dev->driver_data;
+	struct hso_device *hso_dev = dev_get_drvdata(dev);
 	char *port_name;
 
 	if (!hso_dev)
@@ -816,7 +816,7 @@
 	}
 	dev_kfree_skb(skb);
 	/* we're done */
-	return result;
+	return NETDEV_TX_OK;
 }
 
 static void hso_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
@@ -899,15 +899,14 @@
 					continue;
 				}
 				/* Allocate an sk_buff */
-				odev->skb_rx_buf = dev_alloc_skb(frame_len);
+				odev->skb_rx_buf = netdev_alloc_skb(odev->net,
+								    frame_len);
 				if (!odev->skb_rx_buf) {
 					/* We got no receive buffer. */
 					D1("could not allocate memory");
 					odev->rx_parse_state = WAIT_SYNC;
 					return;
 				}
-				/* Here's where it came from */
-				odev->skb_rx_buf->dev = odev->net;
 
 				/* Copy what we got so far. make room for iphdr
 				 * after tail. */
@@ -2313,7 +2312,7 @@
 	serial->parent->dev = tty_register_device(tty_drv, minor,
 					&serial->parent->interface->dev);
 	dev = serial->parent->dev;
-	dev->driver_data = serial->parent;
+	dev_set_drvdata(dev, serial->parent);
 	i = device_create_file(dev, &dev_attr_hsotype);
 
 	/* fill in specific data for later use */
@@ -2481,10 +2480,10 @@
 	return 0;
 }
 
-static int hso_radio_toggle(void *data, enum rfkill_state state)
+static int hso_rfkill_set_block(void *data, bool blocked)
 {
 	struct hso_device *hso_dev = data;
-	int enabled = (state == RFKILL_STATE_ON);
+	int enabled = !blocked;
 	int rv;
 
 	mutex_lock(&hso_dev->mutex);
@@ -2498,6 +2497,10 @@
 	return rv;
 }
 
+static const struct rfkill_ops hso_rfkill_ops = {
+	.set_block = hso_rfkill_set_block,
+};
+
 /* Creates and sets up everything for rfkill */
 static void hso_create_rfkill(struct hso_device *hso_dev,
 			     struct usb_interface *interface)
@@ -2506,29 +2509,25 @@
 	struct device *dev = &hso_net->net->dev;
 	char *rfkn;
 
-	hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev,
-				 RFKILL_TYPE_WWAN);
-	if (!hso_net->rfkill) {
-		dev_err(dev, "%s - Out of memory\n", __func__);
-		return;
-	}
 	rfkn = kzalloc(20, GFP_KERNEL);
-	if (!rfkn) {
-		rfkill_free(hso_net->rfkill);
-		hso_net->rfkill = NULL;
+	if (!rfkn)
 		dev_err(dev, "%s - Out of memory\n", __func__);
-		return;
-	}
+
 	snprintf(rfkn, 20, "hso-%d",
 		 interface->altsetting->desc.bInterfaceNumber);
-	hso_net->rfkill->name = rfkn;
-	hso_net->rfkill->state = RFKILL_STATE_ON;
-	hso_net->rfkill->data = hso_dev;
-	hso_net->rfkill->toggle_radio = hso_radio_toggle;
+
+	hso_net->rfkill = rfkill_alloc(rfkn,
+				       &interface_to_usbdev(interface)->dev,
+				       RFKILL_TYPE_WWAN,
+				       &hso_rfkill_ops, hso_dev);
+	if (!hso_net->rfkill) {
+		dev_err(dev, "%s - Out of memory\n", __func__);
+		kfree(rfkn);
+		return;
+	}
 	if (rfkill_register(hso_net->rfkill) < 0) {
+		rfkill_destroy(hso_net->rfkill);
 		kfree(rfkn);
-		hso_net->rfkill->name = NULL;
-		rfkill_free(hso_net->rfkill);
 		hso_net->rfkill = NULL;
 		dev_err(dev, "%s - Failed to register rfkill\n", __func__);
 		return;
@@ -3165,8 +3164,10 @@
 			hso_stop_net_device(network_table[i]);
 			cancel_work_sync(&network_table[i]->async_put_intf);
 			cancel_work_sync(&network_table[i]->async_get_intf);
-			if (rfk)
+			if (rfk) {
 				rfkill_unregister(rfk);
+				rfkill_destroy(rfk);
+			}
 			hso_free_net_device(network_table[i]);
 		}
 	}
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/int51x1.c linux-libre-2.6.31-gnu/drivers/net/usb/int51x1.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/int51x1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/usb/int51x1.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2009 Peter Holik
+ *
+ * Intellon usb PLC (Powerline Communications) usb net driver
+ *
+ * http://www.tandel.be/downloads/INT51X1_Datasheet.pdf
+ *
+ * Based on the work of Jan 'RedBully' Seiffert
+ */
+
+/*
+ * 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/ctype.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/usbnet.h>
+
+#define INT51X1_VENDOR_ID	0x09e1
+#define INT51X1_PRODUCT_ID	0x5121
+
+#define INT51X1_HEADER_SIZE	2	/* 2 byte header */
+
+#define PACKET_TYPE_PROMISCUOUS		(1 << 0)
+#define PACKET_TYPE_ALL_MULTICAST	(1 << 1) /* no filter */
+#define PACKET_TYPE_DIRECTED		(1 << 2)
+#define PACKET_TYPE_BROADCAST		(1 << 3)
+#define PACKET_TYPE_MULTICAST		(1 << 4) /* filtered */
+
+#define SET_ETHERNET_PACKET_FILTER	0x43
+
+static int int51x1_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	int len;
+
+	if (!(pskb_may_pull(skb, INT51X1_HEADER_SIZE))) {
+		deverr(dev, "unexpected tiny rx frame");
+		return 0;
+	}
+
+	len = le16_to_cpu(*(__le16 *)&skb->data[skb->len - 2]);
+
+	skb_trim(skb, len);
+
+	return 1;
+}
+
+static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev,
+		struct sk_buff *skb, gfp_t flags)
+{
+	int pack_len = skb->len;
+	int pack_with_header_len = pack_len + INT51X1_HEADER_SIZE;
+	int headroom = skb_headroom(skb);
+	int tailroom = skb_tailroom(skb);
+	int need_tail = 0;
+	__le16 *len;
+
+	/* if packet and our header is smaler than 64 pad to 64 (+ ZLP) */
+	if ((pack_with_header_len) < dev->maxpacket)
+		need_tail = dev->maxpacket - pack_with_header_len + 1;
+	/*
+	 * usbnet would send a ZLP if packetlength mod urbsize == 0 for us,
+	 * but we need to know ourself, because this would add to the length
+	 * we send down to the device...
+	 */
+	else if (!(pack_with_header_len % dev->maxpacket))
+		need_tail = 1;
+
+	if (!skb_cloned(skb) &&
+			(headroom + tailroom >= need_tail + INT51X1_HEADER_SIZE)) {
+		if (headroom < INT51X1_HEADER_SIZE || tailroom < need_tail) {
+			skb->data = memmove(skb->head + INT51X1_HEADER_SIZE,
+					skb->data, skb->len);
+			skb_set_tail_pointer(skb, skb->len);
+		}
+	} else {
+		struct sk_buff *skb2;
+
+		skb2 = skb_copy_expand(skb,
+				INT51X1_HEADER_SIZE,
+				need_tail,
+				flags);
+		dev_kfree_skb_any(skb);
+		if (!skb2)
+			return NULL;
+		skb = skb2;
+	}
+
+	pack_len += need_tail;
+	pack_len &= 0x07ff;
+
+	len = (__le16 *) __skb_push(skb, INT51X1_HEADER_SIZE);
+	*len = cpu_to_le16(pack_len);
+
+	if(need_tail)
+		memset(__skb_put(skb, need_tail), 0, need_tail);
+
+	return skb;
+}
+
+static void int51x1_async_cmd_callback(struct urb *urb)
+{
+	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+	int status = urb->status;
+
+	if (status < 0)
+		dev_warn(&urb->dev->dev, "async callback failed with %d\n", status);
+
+	kfree(req);
+	usb_free_urb(urb);
+}
+
+static void int51x1_set_multicast(struct net_device *netdev)
+{
+	struct usb_ctrlrequest *req;
+	int status;
+	struct urb *urb;
+	struct usbnet *dev = netdev_priv(netdev);
+	u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
+
+	if (netdev->flags & IFF_PROMISC) {
+		/* do not expect to see traffic of other PLCs */
+		filter |= PACKET_TYPE_PROMISCUOUS;
+		devinfo(dev, "promiscuous mode enabled");
+	} else if (netdev->mc_count ||
+		  (netdev->flags & IFF_ALLMULTI)) {
+		filter |= PACKET_TYPE_ALL_MULTICAST;
+		devdbg(dev, "receive all multicast enabled");
+	} else {
+		/* ~PROMISCUOUS, ~MULTICAST */
+		devdbg(dev, "receive own packets only");
+	}
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		devwarn(dev, "Error allocating URB");
+		return;
+	}
+
+	req = kmalloc(sizeof(*req), GFP_ATOMIC);
+	if (!req) {
+		devwarn(dev, "Error allocating control msg");
+		goto out;
+	}
+
+	req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+	req->bRequest = SET_ETHERNET_PACKET_FILTER;
+	req->wValue = cpu_to_le16(filter);
+	req->wIndex = 0;
+	req->wLength = 0;
+
+	usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
+		(void *)req, NULL, 0,
+		int51x1_async_cmd_callback,
+		(void *)req);
+
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status < 0) {
+		devwarn(dev, "Error submitting control msg, sts=%d", status);
+		goto out1;
+	}
+	return;
+out1:
+	kfree(req);
+out:
+	usb_free_urb(urb);
+}
+
+static const struct net_device_ops int51x1_netdev_ops = {
+	.ndo_open		= usbnet_open,
+	.ndo_stop		= usbnet_stop,
+	.ndo_start_xmit		= usbnet_start_xmit,
+	.ndo_tx_timeout		= usbnet_tx_timeout,
+	.ndo_change_mtu		= usbnet_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_multicast_list	= int51x1_set_multicast,
+};
+
+static int int51x1_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int status = usbnet_get_ethernet_addr(dev, 3);
+
+	if (status)
+		return status;
+
+	dev->net->hard_header_len += INT51X1_HEADER_SIZE;
+	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+	dev->net->netdev_ops = &int51x1_netdev_ops;
+
+	return usbnet_get_endpoints(dev, intf);
+}
+
+static const struct driver_info int51x1_info = {
+	.description = "Intellon usb powerline adapter",
+	.bind        = int51x1_bind,
+	.rx_fixup    = int51x1_rx_fixup,
+	.tx_fixup    = int51x1_tx_fixup,
+	.in          = 1,
+	.out         = 2,
+	.flags       = FLAG_ETHER,
+};
+
+static const struct usb_device_id products[] = {
+	{
+	USB_DEVICE(INT51X1_VENDOR_ID, INT51X1_PRODUCT_ID),
+		.driver_info = (unsigned long) &int51x1_info,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver int51x1_driver = {
+	.name       = "int51x1",
+	.id_table   = products,
+	.probe      = usbnet_probe,
+	.disconnect = usbnet_disconnect,
+	.suspend    = usbnet_suspend,
+	.resume     = usbnet_resume,
+};
+
+static int __init int51x1_init(void)
+{
+	return usb_register(&int51x1_driver);
+}
+module_init(int51x1_init);
+
+static void __exit int51x1_exit(void)
+{
+	usb_deregister(&int51x1_driver);
+}
+module_exit(int51x1_exit);
+
+MODULE_AUTHOR("Peter Holik");
+MODULE_DESCRIPTION("Intellon usb powerline adapter");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/kaweth.c linux-libre-2.6.31-gnu/drivers/net/usb/kaweth.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/kaweth.c	2012-03-22 19:16:15.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/kaweth.c	2012-03-22 20:12:06.000000000 -0400
@@ -31,7 +31,6 @@
  ****************************************************************/
 
 /* TODO:
- * Fix in_interrupt() problem
  * Develop test procedures for USB net interfaces
  * Run test procedures
  * Fix bugs from previous two steps
@@ -603,14 +602,30 @@
 
 	struct sk_buff *skb;
 
-	if(unlikely(status == -ECONNRESET || status == -ESHUTDOWN))
-	/* we are killed - set a flag and wake the disconnect handler */
-	{
+	if (unlikely(status == -EPIPE)) {
+		kaweth->stats.rx_errors++;
 		kaweth->end = 1;
 		wake_up(&kaweth->term_wait);
+		dbg("Status was -EPIPE.");
 		return;
 	}
-
+	if (unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) {
+		/* we are killed - set a flag and wake the disconnect handler */
+		kaweth->end = 1;
+		wake_up(&kaweth->term_wait);
+		dbg("Status was -ECONNRESET or -ESHUTDOWN.");
+		return;
+	}
+	if (unlikely(status == -EPROTO || status == -ETIME ||
+		     status == -EILSEQ)) {
+		kaweth->stats.rx_errors++;
+		dbg("Status was -EPROTO, -ETIME, or -EILSEQ.");
+		return;
+	}
+	if (unlikely(status == -EOVERFLOW)) {
+		kaweth->stats.rx_errors++;
+		dbg("Status was -EOVERFLOW.");
+	}
 	spin_lock(&kaweth->device_lock);
 	if (IS_BLOCKED(kaweth->status)) {
 		spin_unlock(&kaweth->device_lock);
@@ -880,13 +895,16 @@
  ****************************************************************/
 static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
 {
+	int result;
 	__u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
+
 	kaweth->packet_filter_bitmap = 0;
 	if (packet_filter_bitmap == 0)
 		return;
 
-	{
-	int result;
+	if (in_interrupt())
+		return;
+
 	result = kaweth_control(kaweth,
 				usb_sndctrlpipe(kaweth->dev, 0),
 				KAWETH_COMMAND_SET_PACKET_FILTER,
@@ -903,7 +921,6 @@
 	else {
 		dbg("Set Rx mode to %d", packet_filter_bitmap);
 	}
-	}
 }
 
 /****************************************************************
@@ -979,6 +996,9 @@
 	.ndo_tx_timeout =		kaweth_tx_timeout,
 	.ndo_set_multicast_list =	kaweth_set_rx_mode,
 	.ndo_get_stats =		kaweth_netdev_stats,
+	.ndo_change_mtu =		eth_change_mtu,
+	.ndo_set_mac_address =		eth_mac_addr,
+	.ndo_validate_addr =		eth_validate_addr,
 };
 
 static int kaweth_probe(
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/Kconfig linux-libre-2.6.31-gnu/drivers/net/usb/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/usb/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -169,10 +169,12 @@
 	  The Linux-USB CDC Ethernet Gadget driver is an open implementation.
  	  This driver should work with at least the following devices:
 
+	    * Dell Wireless 5530 HSPA
  	    * Ericsson PipeRider (all variants)
+	    * Ericsson Mobile Broadband Module (all variants)
  	    * Motorola (DM100 and SB4100)
  	    * Broadcom Cable Modem (reference design)
- 	    * Toshiba PCX1100U
+	    * Toshiba (PCX1100U and F3507g)
 	    * ...
 
 	  This driver creates an interface named "ethX", where X depends on
@@ -359,4 +361,20 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called hso.
 
+config USB_NET_INT51X1
+	tristate "Intellon PLC based usb adapter"
+	depends on USB_USBNET
+	help
+	  Choose this option if you're using a 14Mb USB-based PLC
+	  (Powerline Communications) solution with an Intellon
+	  INT51x1/INT5200 chip, like the "devolo dLan duo".
+
+config USB_CDC_PHONET
+	tristate "CDC Phonet support"
+	depends on PHONET
+	help
+	  Choose this option to support the Phonet interface to a Nokia
+	  cellular modem, as found on most Nokia handsets with the
+	  "PC suite" USB profile.
+
 endmenu
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/Makefile linux-libre-2.6.31-gnu/drivers/net/usb/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/usb/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -20,4 +20,6 @@
 obj-$(CONFIG_USB_NET_ZAURUS)	+= zaurus.o
 obj-$(CONFIG_USB_NET_MCS7830)	+= mcs7830.o
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
+obj-$(CONFIG_USB_NET_INT51X1)	+= int51x1.o
+obj-$(CONFIG_USB_CDC_PHONET)	+= cdc-phonet.o
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/net1080.c linux-libre-2.6.31-gnu/drivers/net/usb/net1080.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/net1080.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/net1080.c	2009-09-09 18:13:59.000000000 -0400
@@ -433,7 +433,7 @@
 		dbg("rx framesize %d range %d..%d mtu %d", skb->len,
 			net->hard_header_len, dev->hard_mtu, net->mtu);
 #endif
-		dev->stats.rx_frame_errors++;
+		dev->net->stats.rx_frame_errors++;
 		nc_ensure_sync(dev);
 		return 0;
 	}
@@ -442,12 +442,12 @@
 	hdr_len = le16_to_cpup(&header->hdr_len);
 	packet_len = le16_to_cpup(&header->packet_len);
 	if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) {
-		dev->stats.rx_frame_errors++;
+		dev->net->stats.rx_frame_errors++;
 		dbg("packet too big, %d", packet_len);
 		nc_ensure_sync(dev);
 		return 0;
 	} else if (hdr_len < MIN_HEADER) {
-		dev->stats.rx_frame_errors++;
+		dev->net->stats.rx_frame_errors++;
 		dbg("header too short, %d", hdr_len);
 		nc_ensure_sync(dev);
 		return 0;
@@ -465,21 +465,21 @@
 
 	if ((packet_len & 0x01) == 0) {
 		if (skb->data [packet_len] != PAD_BYTE) {
-			dev->stats.rx_frame_errors++;
+			dev->net->stats.rx_frame_errors++;
 			dbg("bad pad");
 			return 0;
 		}
 		skb_trim(skb, skb->len - 1);
 	}
 	if (skb->len != packet_len) {
-		dev->stats.rx_frame_errors++;
+		dev->net->stats.rx_frame_errors++;
 		dbg("bad packet len %d (expected %d)",
 			skb->len, packet_len);
 		nc_ensure_sync(dev);
 		return 0;
 	}
 	if (header->packet_id != get_unaligned(&trailer->packet_id)) {
-		dev->stats.rx_fifo_errors++;
+		dev->net->stats.rx_fifo_errors++;
 		dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
 			le16_to_cpu(header->packet_id),
 			le16_to_cpu(trailer->packet_id));
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/pegasus.c linux-libre-2.6.31-gnu/drivers/net/usb/pegasus.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/pegasus.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/pegasus.c	2009-09-09 18:13:59.000000000 -0400
@@ -297,7 +297,7 @@
 
 	pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
 	pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
-	pegasus->dr.wValue = 0;
+	pegasus->dr.wValue = cpu_to_le16(0);
 	pegasus->dr.wIndex = cpu_to_le16(EthCtrl0);
 	pegasus->dr.wLength = cpu_to_le16(3);
 	pegasus->ctrl_urb->transfer_buffer_length = 3;
@@ -446,11 +446,12 @@
 	int i;
 	__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
 	int ret;
+	__le16 le_data = cpu_to_le16(data);
 
 	set_registers(pegasus, EpromOffset, 4, d);
 	enable_eprom_write(pegasus);
 	set_register(pegasus, EpromOffset, index);
-	set_registers(pegasus, EpromData, 2, &data);
+	set_registers(pegasus, EpromData, 2, &le_data);
 	set_register(pegasus, EpromCtrl, EPROM_WRITE);
 
 	for (i = 0; i < REG_TIMEOUT; i++) {
@@ -923,29 +924,32 @@
 
 static inline void disable_net_traffic(pegasus_t * pegasus)
 {
-	int tmp = 0;
+	__le16 tmp = cpu_to_le16(0);
 
-	set_registers(pegasus, EthCtrl0, 2, &tmp);
+	set_registers(pegasus, EthCtrl0, sizeof(tmp), &tmp);
 }
 
 static inline void get_interrupt_interval(pegasus_t * pegasus)
 {
-	__u8 data[2];
+	u16 data;
+	u8 interval;
 
-	read_eprom_word(pegasus, 4, (__u16 *) data);
+	read_eprom_word(pegasus, 4, &data);
+	interval = data >> 8;
 	if (pegasus->usb->speed != USB_SPEED_HIGH) {
-		if (data[1] < 0x80) {
+		if (interval < 0x80) {
 			if (netif_msg_timer(pegasus))
 				dev_info(&pegasus->intf->dev, "intr interval "
 					"changed from %ums to %ums\n",
-					data[1], 0x80);
-			data[1] = 0x80;
+					interval, 0x80);
+			interval = 0x80;
+			data = (data & 0x00FF) | ((u16)interval << 8);
 #ifdef PEGASUS_WRITE_EEPROM
-			write_eprom_word(pegasus, 4, *(__u16 *) data);
+			write_eprom_word(pegasus, 4, data);
 #endif
 		}
 	}
-	pegasus->intr_interval = data[1];
+	pegasus->intr_interval = interval;
 }
 
 static void set_carrier(struct net_device *net)
@@ -1299,7 +1303,8 @@
 	/* Special quirk to keep the driver from handling the Belkin Bluetooth
 	 * dongle which happens to have the same ID.
 	 */
-	if ((udd->idVendor == VENDOR_BELKIN && udd->idProduct == 0x0121) &&
+	if ((udd->idVendor == cpu_to_le16(VENDOR_BELKIN)) &&
+	    (udd->idProduct == cpu_to_le16(0x0121)) &&
 	    (udd->bDeviceClass == USB_CLASS_WIRELESS_CONTROLLER) &&
 	    (udd->bDeviceProtocol == 1))
 		return 1;
@@ -1488,6 +1493,9 @@
 	.ndo_set_multicast_list =	pegasus_set_multicast,
 	.ndo_get_stats =		pegasus_netdev_stats,
 	.ndo_tx_timeout =		pegasus_tx_timeout,
+	.ndo_change_mtu =		eth_change_mtu,
+	.ndo_set_mac_address =		eth_mac_addr,
+	.ndo_validate_addr =		eth_validate_addr,
 };
 
 static struct usb_driver pegasus_driver = {
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/pegasus.h linux-libre-2.6.31-gnu/drivers/net/usb/pegasus.h
--- linux-libre-2.6.30-gnu/drivers/net/usb/pegasus.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/pegasus.h	2009-09-09 18:13:59.000000000 -0400
@@ -250,6 +250,8 @@
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "IO DATA USB ETX-US2", VENDOR_IODATA, 0x092a,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
 		DEFAULT_GPIO_RESET)
 PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/rndis_host.c linux-libre-2.6.31-gnu/drivers/net/usb/rndis_host.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/rndis_host.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/rndis_host.c	2009-09-09 18:13:59.000000000 -0400
@@ -487,7 +487,7 @@
 		if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET
 				|| skb->len < msg_len
 				|| (data_offset + data_len + 8) > msg_len)) {
-			dev->stats.rx_frame_errors++;
+			dev->net->stats.rx_frame_errors++;
 			devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d",
 				le32_to_cpu(hdr->msg_type),
 				msg_len, data_offset, data_len, skb->len);
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/rtl8150.c linux-libre-2.6.31-gnu/drivers/net/usb/rtl8150.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/rtl8150.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/rtl8150.c	2009-09-09 18:13:59.000000000 -0400
@@ -221,7 +221,8 @@
 	case -ENOENT:
 		break;
 	default:
-		dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status);
+		if (printk_ratelimit())
+			dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status);
 	}
 	dev = urb->context;
 	clear_bit(RX_REG_SET, &dev->flags);
@@ -442,10 +443,12 @@
 	case -ENOENT:
 		return;	/* the urb is in unlink state */
 	case -ETIME:
-		dev_warn(&urb->dev->dev, "may be reset is needed?..\n");
+		if (printk_ratelimit())
+			dev_warn(&urb->dev->dev, "may be reset is needed?..\n");
 		goto goon;
 	default:
-		dev_warn(&urb->dev->dev, "Rx status %d\n", status);
+		if (printk_ratelimit())
+			dev_warn(&urb->dev->dev, "Rx status %d\n", status);
 		goto goon;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/smsc95xx.c linux-libre-2.6.31-gnu/drivers/net/usb/smsc95xx.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/smsc95xx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/smsc95xx.c	2009-09-09 18:13:59.000000000 -0400
@@ -1108,18 +1108,18 @@
 		if (unlikely(header & RX_STS_ES_)) {
 			if (netif_msg_rx_err(dev))
 				devdbg(dev, "Error header=0x%08x", header);
-			dev->stats.rx_errors++;
-			dev->stats.rx_dropped++;
+			dev->net->stats.rx_errors++;
+			dev->net->stats.rx_dropped++;
 
 			if (header & RX_STS_CRC_) {
-				dev->stats.rx_crc_errors++;
+				dev->net->stats.rx_crc_errors++;
 			} else {
 				if (header & (RX_STS_TL_ | RX_STS_RF_))
-					dev->stats.rx_frame_errors++;
+					dev->net->stats.rx_frame_errors++;
 
 				if ((header & RX_STS_LE_) &&
 					(!(header & RX_STS_FT_)))
-					dev->stats.rx_length_errors++;
+					dev->net->stats.rx_length_errors++;
 			}
 		} else {
 			/* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
@@ -1134,7 +1134,7 @@
 			if (skb->len == size) {
 				if (pdata->use_rx_csum)
 					smsc95xx_rx_csum_offload(skb);
-
+				skb_trim(skb, skb->len - 4); /* remove fcs */
 				skb->truesize = size + sizeof(struct sk_buff);
 
 				return 1;
@@ -1152,7 +1152,7 @@
 
 			if (pdata->use_rx_csum)
 				smsc95xx_rx_csum_offload(ax_skb);
-
+			skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
 			ax_skb->truesize = size + sizeof(struct sk_buff);
 
 			usbnet_skb_return(dev, ax_skb);
diff -druN linux-libre-2.6.30-gnu/drivers/net/usb/usbnet.c linux-libre-2.6.31-gnu/drivers/net/usb/usbnet.c
--- linux-libre-2.6.30-gnu/drivers/net/usb/usbnet.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/usb/usbnet.c	2009-09-09 18:13:59.000000000 -0400
@@ -37,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/ctype.h>
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
 #include <linux/mii.h>
@@ -156,6 +157,36 @@
 }
 EXPORT_SYMBOL_GPL(usbnet_get_endpoints);
 
+static u8 nibble(unsigned char c)
+{
+	if (likely(isdigit(c)))
+		return c - '0';
+	c = toupper(c);
+	if (likely(isxdigit(c)))
+		return 10 + c - 'A';
+	return 0;
+}
+
+int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress)
+{
+	int 		tmp, i;
+	unsigned char	buf [13];
+
+	tmp = usb_string(dev->udev, iMACAddress, buf, sizeof buf);
+	if (tmp != 12) {
+		dev_dbg(&dev->udev->dev,
+			"bad MAC string %d fetch, %d\n", iMACAddress, tmp);
+		if (tmp >= 0)
+			tmp = -EINVAL;
+		return tmp;
+	}
+	for (i = tmp = 0; i < 6; i++, tmp += 2)
+		dev->net->dev_addr [i] =
+			(nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr);
+
 static void intr_complete (struct urb *urb);
 
 static int init_status (struct usbnet *dev, struct usb_interface *intf)
@@ -203,8 +234,8 @@
 	int	status;
 
 	skb->protocol = eth_type_trans (skb, dev->net);
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += skb->len;
+	dev->net->stats.rx_packets++;
+	dev->net->stats.rx_bytes += skb->len;
 
 	if (netif_msg_rx_status (dev))
 		devdbg (dev, "< rx, len %zu, type 0x%x",
@@ -366,7 +397,7 @@
 		if (netif_msg_rx_err (dev))
 			devdbg (dev, "drop");
 error:
-		dev->stats.rx_errors++;
+		dev->net->stats.rx_errors++;
 		skb_queue_tail (&dev->done, skb);
 	}
 }
@@ -389,8 +420,8 @@
 	case 0:
 		if (skb->len < dev->net->hard_header_len) {
 			entry->state = rx_cleanup;
-			dev->stats.rx_errors++;
-			dev->stats.rx_length_errors++;
+			dev->net->stats.rx_errors++;
+			dev->net->stats.rx_length_errors++;
 			if (netif_msg_rx_err (dev))
 				devdbg (dev, "rx length %d", skb->len);
 		}
@@ -398,11 +429,11 @@
 
 	/* stalls need manual reset. this is rare ... except that
 	 * when going through USB 2.0 TTs, unplug appears this way.
-	 * we avoid the highspeed version of the ETIMEOUT/EILSEQ
+	 * we avoid the highspeed version of the ETIMEDOUT/EILSEQ
 	 * storm, recovering as needed.
 	 */
 	case -EPIPE:
-		dev->stats.rx_errors++;
+		dev->net->stats.rx_errors++;
 		usbnet_defer_kevent (dev, EVENT_RX_HALT);
 		// FALLTHROUGH
 
@@ -420,7 +451,7 @@
 	case -EPROTO:
 	case -ETIME:
 	case -EILSEQ:
-		dev->stats.rx_errors++;
+		dev->net->stats.rx_errors++;
 		if (!timer_pending (&dev->delay)) {
 			mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
 			if (netif_msg_link (dev))
@@ -434,12 +465,12 @@
 
 	/* data overrun ... flush fifo? */
 	case -EOVERFLOW:
-		dev->stats.rx_over_errors++;
+		dev->net->stats.rx_over_errors++;
 		// FALLTHROUGH
 
 	default:
 		entry->state = rx_cleanup;
-		dev->stats.rx_errors++;
+		dev->net->stats.rx_errors++;
 		if (netif_msg_rx_err (dev))
 			devdbg (dev, "rx status %d", urb_status);
 		break;
@@ -552,8 +583,8 @@
 
 	if (netif_msg_ifdown (dev))
 		devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
-			dev->stats.rx_packets, dev->stats.tx_packets,
-			dev->stats.rx_errors, dev->stats.tx_errors
+			net->stats.rx_packets, net->stats.tx_packets,
+			net->stats.rx_errors, net->stats.tx_errors
 			);
 
 	// ensure there are no more active urbs
@@ -860,10 +891,10 @@
 	struct usbnet		*dev = entry->dev;
 
 	if (urb->status == 0) {
-		dev->stats.tx_packets++;
-		dev->stats.tx_bytes += entry->length;
+		dev->net->stats.tx_packets++;
+		dev->net->stats.tx_bytes += entry->length;
 	} else {
-		dev->stats.tx_errors++;
+		dev->net->stats.tx_errors++;
 
 		switch (urb->status) {
 		case -EPIPE:
@@ -989,7 +1020,7 @@
 			devdbg (dev, "drop, code %d", retval);
 drop:
 		retval = NET_XMIT_SUCCESS;
-		dev->stats.tx_dropped++;
+		dev->net->stats.tx_dropped++;
 		if (skb)
 			dev_kfree_skb_any (skb);
 		usb_free_urb (urb);
@@ -1185,12 +1216,6 @@
 #endif
 
 	net->netdev_ops = &usbnet_netdev_ops;
-#ifdef CONFIG_COMPAT_NET_DEV_OPS
-	net->hard_start_xmit = usbnet_start_xmit;
-	net->open = usbnet_open;
-	net->stop = usbnet_stop;
-	net->tx_timeout = usbnet_tx_timeout;
-#endif
 	net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
 	net->ethtool_ops = &usbnet_ethtool_ops;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/veth.c linux-libre-2.6.31-gnu/drivers/net/veth.c
--- linux-libre-2.6.30-gnu/drivers/net/veth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/veth.c	2009-09-09 18:13:59.000000000 -0400
@@ -176,8 +176,6 @@
 	if (dev->features & NETIF_F_NO_CSUM)
 		skb->ip_summed = rcv_priv->ip_summed;
 
-	dst_release(skb->dst);
-	skb->dst = NULL;
 	skb->mark = 0;
 	secpath_reset(skb);
 	nf_reset(skb);
@@ -210,11 +208,14 @@
 
 static struct net_device_stats *veth_get_stats(struct net_device *dev)
 {
-	struct veth_priv *priv = netdev_priv(dev);
-	struct net_device_stats *dev_stats = &dev->stats;
-	unsigned int cpu;
+	struct veth_priv *priv;
+	struct net_device_stats *dev_stats;
+	int cpu;
 	struct veth_net_stats *stats;
 
+	priv = netdev_priv(dev);
+	dev_stats = &dev->stats;
+
 	dev_stats->rx_packets = 0;
 	dev_stats->tx_packets = 0;
 	dev_stats->rx_bytes = 0;
@@ -222,17 +223,16 @@
 	dev_stats->tx_dropped = 0;
 	dev_stats->rx_dropped = 0;
 
-	if (priv->stats)
-		for_each_online_cpu(cpu) {
-			stats = per_cpu_ptr(priv->stats, cpu);
+	for_each_online_cpu(cpu) {
+		stats = per_cpu_ptr(priv->stats, cpu);
 
-			dev_stats->rx_packets += stats->rx_packets;
-			dev_stats->tx_packets += stats->tx_packets;
-			dev_stats->rx_bytes += stats->rx_bytes;
-			dev_stats->tx_bytes += stats->tx_bytes;
-			dev_stats->tx_dropped += stats->tx_dropped;
-			dev_stats->rx_dropped += stats->rx_dropped;
-		}
+		dev_stats->rx_packets += stats->rx_packets;
+		dev_stats->tx_packets += stats->tx_packets;
+		dev_stats->rx_bytes += stats->rx_bytes;
+		dev_stats->tx_bytes += stats->tx_bytes;
+		dev_stats->tx_dropped += stats->tx_dropped;
+		dev_stats->rx_dropped += stats->rx_dropped;
+	}
 
 	return dev_stats;
 }
@@ -259,8 +259,6 @@
 	netif_carrier_off(dev);
 	netif_carrier_off(priv->peer);
 
-	free_percpu(priv->stats);
-	priv->stats = NULL;
 	return 0;
 }
 
@@ -291,6 +289,15 @@
 	return 0;
 }
 
+static void veth_dev_free(struct net_device *dev)
+{
+	struct veth_priv *priv;
+
+	priv = netdev_priv(dev);
+	free_percpu(priv->stats);
+	free_netdev(dev);
+}
+
 static const struct net_device_ops veth_netdev_ops = {
 	.ndo_init            = veth_dev_init,
 	.ndo_open            = veth_open,
@@ -308,7 +315,7 @@
 	dev->netdev_ops = &veth_netdev_ops;
 	dev->ethtool_ops = &veth_ethtool_ops;
 	dev->features |= NETIF_F_LLTX;
-	dev->destructor = free_netdev;
+	dev->destructor = veth_dev_free;
 }
 
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/net/via-rhine.c linux-libre-2.6.31-gnu/drivers/net/via-rhine.c
--- linux-libre-2.6.30-gnu/drivers/net/via-rhine.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/via-rhine.c	2009-09-09 18:13:59.000000000 -0400
@@ -388,7 +388,6 @@
 	long pioaddr;
 	struct net_device *dev;
 	struct napi_struct napi;
-	struct net_device_stats stats;
 	spinlock_t lock;
 
 	/* Frequently used values: keep some adjacent for cache effect. */
@@ -622,6 +621,7 @@
 	.ndo_start_xmit		 = rhine_start_tx,
 	.ndo_get_stats		 = rhine_get_stats,
 	.ndo_set_multicast_list	 = rhine_set_rx_mode,
+	.ndo_change_mtu		 = eth_change_mtu,
 	.ndo_validate_addr	 = eth_validate_addr,
 	.ndo_set_mac_address 	 = eth_mac_addr,
 	.ndo_do_ioctl		 = netdev_ioctl,
@@ -1209,7 +1209,7 @@
 	enable_irq(rp->pdev->irq);
 
 	dev->trans_start = jiffies;
-	rp->stats.tx_errors++;
+	dev->stats.tx_errors++;
 	netif_wake_queue(dev);
 }
 
@@ -1218,6 +1218,7 @@
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 	unsigned entry;
+	unsigned long flags;
 
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
@@ -1237,7 +1238,7 @@
 			/* packet too long, drop it */
 			dev_kfree_skb(skb);
 			rp->tx_skbuff[entry] = NULL;
-			rp->stats.tx_dropped++;
+			dev->stats.tx_dropped++;
 			return 0;
 		}
 
@@ -1261,7 +1262,7 @@
 		cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
 	/* lock eth irq */
-	spin_lock_irq(&rp->lock);
+	spin_lock_irqsave(&rp->lock, flags);
 	wmb();
 	rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
 	wmb();
@@ -1280,7 +1281,7 @@
 
 	dev->trans_start = jiffies;
 
-	spin_unlock_irq(&rp->lock);
+	spin_unlock_irqrestore(&rp->lock, flags);
 
 	if (debug > 4) {
 		printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
@@ -1378,29 +1379,33 @@
 				printk(KERN_DEBUG "%s: Transmit error, "
 				       "Tx status %8.8x.\n",
 				       dev->name, txstatus);
-			rp->stats.tx_errors++;
-			if (txstatus & 0x0400) rp->stats.tx_carrier_errors++;
-			if (txstatus & 0x0200) rp->stats.tx_window_errors++;
-			if (txstatus & 0x0100) rp->stats.tx_aborted_errors++;
-			if (txstatus & 0x0080) rp->stats.tx_heartbeat_errors++;
+			dev->stats.tx_errors++;
+			if (txstatus & 0x0400)
+				dev->stats.tx_carrier_errors++;
+			if (txstatus & 0x0200)
+				dev->stats.tx_window_errors++;
+			if (txstatus & 0x0100)
+				dev->stats.tx_aborted_errors++;
+			if (txstatus & 0x0080)
+				dev->stats.tx_heartbeat_errors++;
 			if (((rp->quirks & rqRhineI) && txstatus & 0x0002) ||
 			    (txstatus & 0x0800) || (txstatus & 0x1000)) {
-				rp->stats.tx_fifo_errors++;
+				dev->stats.tx_fifo_errors++;
 				rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
 				break; /* Keep the skb - we try again */
 			}
 			/* Transmitter restarted in 'abnormal' handler. */
 		} else {
 			if (rp->quirks & rqRhineI)
-				rp->stats.collisions += (txstatus >> 3) & 0x0F;
+				dev->stats.collisions += (txstatus >> 3) & 0x0F;
 			else
-				rp->stats.collisions += txstatus & 0x0F;
+				dev->stats.collisions += txstatus & 0x0F;
 			if (debug > 6)
 				printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n",
 				       (txstatus >> 3) & 0xF,
 				       txstatus & 0xF);
-			rp->stats.tx_bytes += rp->tx_skbuff[entry]->len;
-			rp->stats.tx_packets++;
+			dev->stats.tx_bytes += rp->tx_skbuff[entry]->len;
+			dev->stats.tx_packets++;
 		}
 		/* Free the original skb. */
 		if (rp->tx_skbuff_dma[entry]) {
@@ -1455,21 +1460,24 @@
 				printk(KERN_WARNING "%s: Oversized Ethernet "
 				       "frame %p vs %p.\n", dev->name,
 				       rp->rx_head_desc, &rp->rx_ring[entry]);
-				rp->stats.rx_length_errors++;
+				dev->stats.rx_length_errors++;
 			} else if (desc_status & RxErr) {
 				/* There was a error. */
 				if (debug > 2)
 					printk(KERN_DEBUG "rhine_rx() Rx "
 					       "error was %8.8x.\n",
 					       desc_status);
-				rp->stats.rx_errors++;
-				if (desc_status & 0x0030) rp->stats.rx_length_errors++;
-				if (desc_status & 0x0048) rp->stats.rx_fifo_errors++;
-				if (desc_status & 0x0004) rp->stats.rx_frame_errors++;
+				dev->stats.rx_errors++;
+				if (desc_status & 0x0030)
+					dev->stats.rx_length_errors++;
+				if (desc_status & 0x0048)
+					dev->stats.rx_fifo_errors++;
+				if (desc_status & 0x0004)
+					dev->stats.rx_frame_errors++;
 				if (desc_status & 0x0002) {
 					/* this can also be updated outside the interrupt handler */
 					spin_lock(&rp->lock);
-					rp->stats.rx_crc_errors++;
+					dev->stats.rx_crc_errors++;
 					spin_unlock(&rp->lock);
 				}
 			}
@@ -1513,8 +1521,8 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_receive_skb(skb);
-			rp->stats.rx_bytes += pkt_len;
-			rp->stats.rx_packets++;
+			dev->stats.rx_bytes += pkt_len;
+			dev->stats.rx_packets++;
 		}
 		entry = (++rp->cur_rx) % RX_RING_SIZE;
 		rp->rx_head_desc = &rp->rx_ring[entry];
@@ -1599,8 +1607,8 @@
 	if (intr_status & IntrLinkChange)
 		rhine_check_media(dev, 0);
 	if (intr_status & IntrStatsMax) {
-		rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
-		rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
+		dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
+		dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
 		clear_tally_counters(ioaddr);
 	}
 	if (intr_status & IntrTxAborted) {
@@ -1654,12 +1662,12 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&rp->lock, flags);
-	rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
-	rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
+	dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
+	dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
 	clear_tally_counters(ioaddr);
 	spin_unlock_irqrestore(&rp->lock, flags);
 
-	return &rp->stats;
+	return &dev->stats;
 }
 
 static void rhine_set_rx_mode(struct net_device *dev)
diff -druN linux-libre-2.6.30-gnu/drivers/net/via-velocity.c linux-libre-2.6.31-gnu/drivers/net/via-velocity.c
--- linux-libre-2.6.30-gnu/drivers/net/via-velocity.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/via-velocity.c	2009-09-09 18:13:59.000000000 -0400
@@ -989,8 +989,10 @@
 	if (ret < 0)
 		goto err_iounmap;
 
-	if (velocity_get_link(dev))
+	if (!velocity_get_link(dev)) {
 		netif_carrier_off(dev);
+		vptr->mii_status |= VELOCITY_LINK_FAIL;
+	}
 
 	velocity_print_info(vptr);
 	pci_set_drvdata(pdev, dev);
@@ -1385,7 +1387,7 @@
 
 static int velocity_rx_srv(struct velocity_info *vptr, int status)
 {
-	struct net_device_stats *stats = &vptr->stats;
+	struct net_device_stats *stats = &vptr->dev->stats;
 	int rd_curr = vptr->rx.curr;
 	int works = 0;
 
@@ -1519,7 +1521,7 @@
 static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 {
 	void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
-	struct net_device_stats *stats = &vptr->stats;
+	struct net_device_stats *stats = &vptr->dev->stats;
 	struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
 	struct rx_desc *rd = &(vptr->rx.ring[idx]);
 	int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
@@ -1532,7 +1534,7 @@
 	}
 
 	if (rd->rdesc0.RSR & RSR_MAR)
-		vptr->stats.multicast++;
+		stats->multicast++;
 
 	skb = rd_info->skb;
 
@@ -1634,7 +1636,7 @@
 	int idx;
 	int works = 0;
 	struct velocity_td_info *tdinfo;
-	struct net_device_stats *stats = &vptr->stats;
+	struct net_device_stats *stats = &vptr->dev->stats;
 
 	for (qnum = 0; qnum < vptr->tx.numq; qnum++) {
 		for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0;
@@ -1776,7 +1778,7 @@
 			 *	 mode
 			 */
 			if (vptr->rev_id < REV_ID_VT3216_A0) {
-				if (vptr->mii_status | VELOCITY_DUPLEX_FULL)
+				if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
 					BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
 				else
 					BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
@@ -1845,7 +1847,7 @@
 	 */
 	if (tdinfo->skb_dma) {
 
-		pktlen = (skb->len > ETH_ZLEN ? : ETH_ZLEN);
+		pktlen = max_t(unsigned int, skb->len, ETH_ZLEN);
 		for (i = 0; i < tdinfo->nskb_dma; i++) {
 #ifdef VELOCITY_ZERO_COPY_SUPPORT
 			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE);
@@ -2324,22 +2326,22 @@
 
 	/* If the hardware is down, don't touch MII */
 	if(!netif_running(dev))
-		return &vptr->stats;
+		return &dev->stats;
 
 	spin_lock_irq(&vptr->lock);
 	velocity_update_hw_mibs(vptr);
 	spin_unlock_irq(&vptr->lock);
 
-	vptr->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts];
-	vptr->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts];
-	vptr->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors];
+	dev->stats.rx_packets = vptr->mib_counter[HW_MIB_ifRxAllPkts];
+	dev->stats.rx_errors = vptr->mib_counter[HW_MIB_ifRxErrorPkts];
+	dev->stats.rx_length_errors = vptr->mib_counter[HW_MIB_ifInRangeLengthErrors];
 
 //  unsigned long   rx_dropped;     /* no space in linux buffers    */
-	vptr->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions];
+	dev->stats.collisions = vptr->mib_counter[HW_MIB_ifTxEtherCollisions];
 	/* detailed rx_errors: */
 //  unsigned long   rx_length_errors;
 //  unsigned long   rx_over_errors;     /* receiver ring buff overflow  */
-	vptr->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE];
+	dev->stats.rx_crc_errors = vptr->mib_counter[HW_MIB_ifRxPktCRCE];
 //  unsigned long   rx_frame_errors;    /* recv'd frame alignment error */
 //  unsigned long   rx_fifo_errors;     /* recv'r fifo overrun      */
 //  unsigned long   rx_missed_errors;   /* receiver missed packet   */
@@ -2347,7 +2349,7 @@
 	/* detailed tx_errors */
 //  unsigned long   tx_fifo_errors;
 
-	return &vptr->stats;
+	return &dev->stats;
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/via-velocity.h linux-libre-2.6.31-gnu/drivers/net/via-velocity.h
--- linux-libre-2.6.30-gnu/drivers/net/via-velocity.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/via-velocity.h	2009-09-09 18:13:59.000000000 -0400
@@ -1503,7 +1503,6 @@
 
 	struct pci_dev *pdev;
 	struct net_device *dev;
-	struct net_device_stats stats;
 
 	struct vlan_group    *vlgrp;
 	u8 ip_addr[4];
diff -druN linux-libre-2.6.30-gnu/drivers/net/virtio_net.c linux-libre-2.6.31-gnu/drivers/net/virtio_net.c
--- linux-libre-2.6.30-gnu/drivers/net/virtio_net.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/virtio_net.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,6 +70,9 @@
 	struct sk_buff_head recv;
 	struct sk_buff_head send;
 
+	/* Work struct for refilling if we run low on memory. */
+	struct delayed_work refill;
+
 	/* Chain pages by the private ptr. */
 	struct page *pages;
 };
@@ -273,20 +276,24 @@
 	dev_kfree_skb(skb);
 }
 
-static void try_fill_recv_maxbufs(struct virtnet_info *vi)
+static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp)
 {
 	struct sk_buff *skb;
 	struct scatterlist sg[2+MAX_SKB_FRAGS];
 	int num, err, i;
+	bool oom = false;
 
 	sg_init_table(sg, 2+MAX_SKB_FRAGS);
 	for (;;) {
 		struct virtio_net_hdr *hdr;
 
-		skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
-		if (unlikely(!skb))
+		skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN);
+		if (unlikely(!skb)) {
+			oom = true;
 			break;
+		}
 
+		skb_reserve(skb, NET_IP_ALIGN);
 		skb_put(skb, MAX_PACKET_LEN);
 
 		hdr = skb_vnet_hdr(skb);
@@ -295,7 +302,7 @@
 		if (vi->big_packets) {
 			for (i = 0; i < MAX_SKB_FRAGS; i++) {
 				skb_frag_t *f = &skb_shinfo(skb)->frags[i];
-				f->page = get_a_page(vi, GFP_ATOMIC);
+				f->page = get_a_page(vi, gfp);
 				if (!f->page)
 					break;
 
@@ -324,31 +331,35 @@
 	if (unlikely(vi->num > vi->max))
 		vi->max = vi->num;
 	vi->rvq->vq_ops->kick(vi->rvq);
+	return !oom;
 }
 
-static void try_fill_recv(struct virtnet_info *vi)
+/* Returns false if we couldn't fill entirely (OOM). */
+static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
 {
 	struct sk_buff *skb;
 	struct scatterlist sg[1];
 	int err;
+	bool oom = false;
 
-	if (!vi->mergeable_rx_bufs) {
-		try_fill_recv_maxbufs(vi);
-		return;
-	}
+	if (!vi->mergeable_rx_bufs)
+		return try_fill_recv_maxbufs(vi, gfp);
 
 	for (;;) {
 		skb_frag_t *f;
 
 		skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN);
-		if (unlikely(!skb))
+		if (unlikely(!skb)) {
+			oom = true;
 			break;
+		}
 
 		skb_reserve(skb, NET_IP_ALIGN);
 
 		f = &skb_shinfo(skb)->frags[0];
-		f->page = get_a_page(vi, GFP_ATOMIC);
+		f->page = get_a_page(vi, gfp);
 		if (!f->page) {
+			oom = true;
 			kfree_skb(skb);
 			break;
 		}
@@ -372,6 +383,7 @@
 	if (unlikely(vi->num > vi->max))
 		vi->max = vi->num;
 	vi->rvq->vq_ops->kick(vi->rvq);
+	return !oom;
 }
 
 static void skb_recv_done(struct virtqueue *rvq)
@@ -384,6 +396,23 @@
 	}
 }
 
+static void refill_work(struct work_struct *work)
+{
+	struct virtnet_info *vi;
+	bool still_empty;
+
+	vi = container_of(work, struct virtnet_info, refill.work);
+	napi_disable(&vi->napi);
+	try_fill_recv(vi, GFP_KERNEL);
+	still_empty = (vi->num == 0);
+	napi_enable(&vi->napi);
+
+	/* In theory, this can happen: if we don't get any buffers in
+	 * we will *never* try to fill again. */
+	if (still_empty)
+		schedule_delayed_work(&vi->refill, HZ/2);
+}
+
 static int virtnet_poll(struct napi_struct *napi, int budget)
 {
 	struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
@@ -399,10 +428,10 @@
 		received++;
 	}
 
-	/* FIXME: If we oom and completely run out of inbufs, we need
-	 * to start a timer trying to fill more. */
-	if (vi->num < vi->max / 2)
-		try_fill_recv(vi);
+	if (vi->num < vi->max / 2) {
+		if (!try_fill_recv(vi, GFP_ATOMIC))
+			schedule_delayed_work(&vi->refill, 0);
+	}
 
 	/* Out of packets? */
 	if (received < budget) {
@@ -470,7 +499,7 @@
 	}
 
 	if (skb_is_gso(skb)) {
-		hdr->hdr_len = skb_transport_header(skb) - skb->data;
+		hdr->hdr_len = skb_headlen(skb);
 		hdr->gso_size = skb_shinfo(skb)->gso_size;
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
 			hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
@@ -622,12 +651,9 @@
 	unsigned int tmp;
 	int i;
 
-	if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
-		BUG();  /* Caller should know better */
-		return false;
-	}
-
-	BUG_ON(out + in > VIRTNET_SEND_COMMAND_SG_MAX);
+	/* Caller should know better */
+	BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ||
+		(out + in > VIRTNET_SEND_COMMAND_SG_MAX));
 
 	out++; /* Add header */
 	in++; /* Add return status */
@@ -642,8 +668,7 @@
 		sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
 	sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
 
-	if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0)
-		BUG();
+	BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi));
 
 	vi->cvq->vq_ops->kick(vi->cvq);
 
@@ -684,6 +709,7 @@
 	u8 promisc, allmulti;
 	struct virtio_net_ctrl_mac *mac_data;
 	struct dev_addr_list *addr;
+	struct netdev_hw_addr *ha;
 	void *buf;
 	int i;
 
@@ -711,7 +737,7 @@
 			 allmulti ? "en" : "dis");
 
 	/* MAC filter - use one buffer for both lists */
-	mac_data = buf = kzalloc(((dev->uc_count + dev->mc_count) * ETH_ALEN) +
+	mac_data = buf = kzalloc(((dev->uc.count + dev->mc_count) * ETH_ALEN) +
 				 (2 * sizeof(mac_data->entries)), GFP_ATOMIC);
 	if (!buf) {
 		dev_warn(&dev->dev, "No memory for MAC address buffer\n");
@@ -721,16 +747,16 @@
 	sg_init_table(sg, 2);
 
 	/* Store the unicast list and count in the front of the buffer */
-	mac_data->entries = dev->uc_count;
-	addr = dev->uc_list;
-	for (i = 0; i < dev->uc_count; i++, addr = addr->next)
-		memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN);
+	mac_data->entries = dev->uc.count;
+	i = 0;
+	list_for_each_entry(ha, &dev->uc.list, list)
+		memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN);
 
 	sg_set_buf(&sg[0], mac_data,
-		   sizeof(mac_data->entries) + (dev->uc_count * ETH_ALEN));
+		   sizeof(mac_data->entries) + (dev->uc.count * ETH_ALEN));
 
 	/* multicast list and count fill the end */
-	mac_data = (void *)&mac_data->macs[dev->uc_count][0];
+	mac_data = (void *)&mac_data->macs[dev->uc.count][0];
 
 	mac_data->entries = dev->mc_count;
 	addr = dev->mc_list;
@@ -845,6 +871,10 @@
 	int err;
 	struct net_device *dev;
 	struct virtnet_info *vi;
+	struct virtqueue *vqs[3];
+	vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done, NULL};
+	const char *names[] = { "input", "output", "control" };
+	int nvqs;
 
 	/* Allocate ourselves a network device with room for our info */
 	dev = alloc_etherdev(sizeof(struct virtnet_info));
@@ -891,6 +921,7 @@
 	vi->vdev = vdev;
 	vdev->priv = vi;
 	vi->pages = NULL;
+	INIT_DELAYED_WORK(&vi->refill, refill_work);
 
 	/* If they give us a callback when all buffers are done, we don't need
 	 * the timer. */
@@ -905,25 +936,19 @@
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
 		vi->mergeable_rx_bufs = true;
 
-	/* We expect two virtqueues, receive then send. */
-	vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
-	if (IS_ERR(vi->rvq)) {
-		err = PTR_ERR(vi->rvq);
+	/* We expect two virtqueues, receive then send,
+	 * and optionally control. */
+	nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
+
+	err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names);
+	if (err)
 		goto free;
-	}
 
-	vi->svq = vdev->config->find_vq(vdev, 1, skb_xmit_done);
-	if (IS_ERR(vi->svq)) {
-		err = PTR_ERR(vi->svq);
-		goto free_recv;
-	}
+	vi->rvq = vqs[0];
+	vi->svq = vqs[1];
 
 	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
-		vi->cvq = vdev->config->find_vq(vdev, 2, NULL);
-		if (IS_ERR(vi->cvq)) {
-			err = PTR_ERR(vi->svq);
-			goto free_send;
-		}
+		vi->cvq = vqs[2];
 
 		if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
 			dev->features |= NETIF_F_HW_VLAN_FILTER;
@@ -941,11 +966,11 @@
 	err = register_netdev(dev);
 	if (err) {
 		pr_debug("virtio_net: registering device failed\n");
-		goto free_ctrl;
+		goto free_vqs;
 	}
 
 	/* Last of all, set up some receive buffers. */
-	try_fill_recv(vi);
+	try_fill_recv(vi, GFP_KERNEL);
 
 	/* If we didn't even get one input buffer, we're useless. */
 	if (vi->num == 0) {
@@ -962,13 +987,9 @@
 
 unregister:
 	unregister_netdev(dev);
-free_ctrl:
-	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
-		vdev->config->del_vq(vi->cvq);
-free_send:
-	vdev->config->del_vq(vi->svq);
-free_recv:
-	vdev->config->del_vq(vi->rvq);
+	cancel_delayed_work_sync(&vi->refill);
+free_vqs:
+	vdev->config->del_vqs(vdev);
 free:
 	free_netdev(dev);
 	return err;
@@ -994,11 +1015,10 @@
 
 	BUG_ON(vi->num != 0);
 
-	vdev->config->del_vq(vi->svq);
-	vdev->config->del_vq(vi->rvq);
-	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
-		vdev->config->del_vq(vi->cvq);
 	unregister_netdev(vi->dev);
+	cancel_delayed_work_sync(&vi->refill);
+
+	vdev->config->del_vqs(vi->vdev);
 
 	while (vi->pages)
 		__free_pages(get_a_page(vi, GFP_KERNEL), 0);
diff -druN linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-config.c linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-config.c
--- linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-config.c	2009-09-09 18:13:59.000000000 -0400
@@ -454,7 +454,7 @@
 	return VXGE_HW_OK;
 }
 
-static enum vxge_hw_status
+enum vxge_hw_status
 __vxge_hw_device_is_privilaged(struct __vxge_hw_device *hldev)
 {
 	if ((hldev->host_type == VXGE_HW_NO_MR_NO_SR_NORMAL_FUNCTION ||
@@ -676,10 +676,12 @@
 {
 	enum vxge_hw_status status = VXGE_HW_OK;
 
-	/* Validate the pci-e link width and speed */
-	status = __vxge_hw_verify_pci_e_info(hldev);
-	if (status != VXGE_HW_OK)
-		goto exit;
+	if (VXGE_HW_OK == __vxge_hw_device_is_privilaged(hldev)) {
+		/* Validate the pci-e link width and speed */
+		status = __vxge_hw_verify_pci_e_info(hldev);
+		if (status != VXGE_HW_OK)
+			goto exit;
+	}
 
 	vxge_hw_wrr_rebalance(hldev);
 exit:
@@ -1884,17 +1886,13 @@
 				mempool->memblock_size, dma_object);
 	}
 
-	if (mempool->items_arr)
-		vfree(mempool->items_arr);
+	vfree(mempool->items_arr);
 
-	if (mempool->memblocks_dma_arr)
-		vfree(mempool->memblocks_dma_arr);
+	vfree(mempool->memblocks_dma_arr);
 
-	if (mempool->memblocks_priv_arr)
-		vfree(mempool->memblocks_priv_arr);
+	vfree(mempool->memblocks_priv_arr);
 
-	if (mempool->memblocks_arr)
-		vfree(mempool->memblocks_arr);
+	vfree(mempool->memblocks_arr);
 
 	vfree(mempool);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-main.c linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-main.c
--- linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-main.c	2009-09-09 18:13:59.000000000 -0400
@@ -677,7 +677,7 @@
 	return VXGE_HW_OK;
 }
 
-/* select a vpath to trasmit the packet */
+/* select a vpath to transmit the packet */
 static u32 vxge_get_vpath_no(struct vxgedev *vdev, struct sk_buff *skb,
 	int *do_lock)
 {
@@ -992,7 +992,9 @@
 					VXGE_HW_FIFO_TXD_TX_CKO_UDP_EN);
 
 	vxge_hw_fifo_txdl_post(fifo_hw, dtr);
-	dev->trans_start = jiffies;
+#ifdef NETIF_F_LLTX
+	dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
+#endif
 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
 
 	VXGE_COMPLETE_VPATH_TX(fifo);
@@ -4201,6 +4203,16 @@
 		max_vpath_supported++;
 	}
 
+	/* Enable SRIOV mode, if firmware has SRIOV support and if it is a PF */
+	if ((VXGE_HW_FUNCTION_MODE_SRIOV ==
+		ll_config.device_hw_info.function_mode) &&
+		(max_config_dev > 1) && (pdev->is_physfn)) {
+			ret = pci_enable_sriov(pdev, max_config_dev - 1);
+			if (ret)
+				vxge_debug_ll_config(VXGE_ERR,
+					"Failed to enable SRIOV: %d \n", ret);
+	}
+
 	/*
 	 * Configure vpaths and get driver configured number of vpaths
 	 * which is less than or equal to the maximum vpaths per function.
@@ -4364,6 +4376,7 @@
 
 	vxge_device_unregister(hldev);
 _exit5:
+	pci_disable_sriov(pdev);
 	vxge_hw_device_terminate(hldev);
 _exit4:
 	iounmap(attr.bar1);
@@ -4427,6 +4440,8 @@
 	iounmap(vdev->bar0);
 	iounmap(vdev->bar1);
 
+	pci_disable_sriov(pdev);
+
 	/* we are safe to free it now */
 	free_netdev(dev);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-traffic.c linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-traffic.c
--- linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-traffic.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-traffic.c	2009-09-09 18:13:59.000000000 -0400
@@ -1923,7 +1923,7 @@
 	if (vpath == NULL) {
 		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
 			alarm_event);
-		goto out;
+		goto out2;
 	}
 
 	hldev = vpath->hldev;
@@ -2161,7 +2161,7 @@
 	}
 out:
 	hldev->stats.sw_dev_err_stats.vpath_alarms++;
-
+out2:
 	if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) ||
 		(alarm_event == VXGE_HW_EVENT_UNKNOWN))
 		return VXGE_HW_OK;
diff -druN linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-version.h linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-version.h
--- linux-libre-2.6.30-gnu/drivers/net/vxge/vxge-version.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/vxge/vxge-version.h	2009-09-09 18:13:59.000000000 -0400
@@ -17,7 +17,7 @@
 
 #define VXGE_VERSION_MAJOR	"2"
 #define VXGE_VERSION_MINOR	"0"
-#define VXGE_VERSION_FIX	"1"
-#define VXGE_VERSION_BUILD	"17129"
+#define VXGE_VERSION_FIX	"4"
+#define VXGE_VERSION_BUILD	"17795"
 #define VXGE_VERSION_FOR	"k"
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/cycx_x25.c linux-libre-2.6.31-gnu/drivers/net/wan/cycx_x25.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/cycx_x25.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/cycx_x25.c	2009-09-09 18:13:59.000000000 -0400
@@ -615,7 +615,7 @@
 		case WAN_DISCONNECTED:
 			if (cycx_x25_chan_connect(dev)) {
 				netif_stop_queue(dev);
-				return -EBUSY;
+				return NETDEV_TX_BUSY;
 			}
 			/* fall thru */
 		case WAN_CONNECTED:
@@ -624,7 +624,7 @@
 			netif_stop_queue(dev);
 
 			if (cycx_x25_chan_send(dev, skb))
-				return -EBUSY;
+				return NETDEV_TX_BUSY;
 
 			break;
 		default:
@@ -656,7 +656,7 @@
 		if (cycx_x25_chan_send(dev, skb)) {
 			/* prepare for future retransmissions */
 			skb_push(skb, 1);
-			return -EBUSY;
+			return NETDEV_TX_BUSY;
 		}
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/dlci.c linux-libre-2.6.31-gnu/drivers/net/wan/dlci.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/dlci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/dlci.c	2009-09-09 18:13:59.000000000 -0400
@@ -205,15 +205,15 @@
 	{
 		case DLCI_RET_OK:
 			dev->stats.tx_packets++;
-			ret = 0;
+			ret = NETDEV_TX_OK;
 			break;
 			case DLCI_RET_ERR:
 			dev->stats.tx_errors++;
-			ret = 0;
+			ret = NETDEV_TX_OK;
 			break;
 			case DLCI_RET_DROP:
 			dev->stats.tx_dropped++;
-			ret = 1;
+			ret = NETDEV_TX_BUSY;
 			break;
 	}
 	/* Alan Cox recommends always returning 0, and always freeing the packet */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/hd64570.c linux-libre-2.6.31-gnu/drivers/net/wan/hd64570.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/hd64570.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/hd64570.c	2009-09-09 18:13:59.000000000 -0400
@@ -584,8 +584,9 @@
 	       sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in");
 	for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++)
 		printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+	printk(KERN_CONT "\n");
 
-	printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
+	printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
 	       "last=%u %sactive",
 	       sca_inw(get_dmac_tx(port) + CDAL, card),
 	       sca_inw(get_dmac_tx(port) + EDAL, card),
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/hd64572.c linux-libre-2.6.31-gnu/drivers/net/wan/hd64572.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/hd64572.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/hd64572.c	2009-09-09 18:13:59.000000000 -0400
@@ -529,8 +529,9 @@
 	       sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
 	for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
 		printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+	printk(KERN_CONT "\n");
 
-	printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
+	printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
 	       "last=%u %sactive",
 	       sca_inl(get_dmac_tx(port) + CDAL, card),
 	       sca_inl(get_dmac_tx(port) + EDAL, card),
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/hdlc_fr.c linux-libre-2.6.31-gnu/drivers/net/wan/hdlc_fr.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/hdlc_fr.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/hdlc_fr.c	2009-09-09 18:13:59.000000000 -0400
@@ -1054,6 +1054,7 @@
 	dev->flags = IFF_POINTOPOINT;
 	dev->hard_header_len = 10;
 	dev->addr_len = 2;
+	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 }
 
 static const struct net_device_ops pvc_ops = {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/ixp4xx_hss.c linux-libre-2.6.31-gnu/drivers/net/wan/ixp4xx_hss.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/ixp4xx_hss.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/ixp4xx_hss.c	2009-09-09 18:13:59.000000000 -0400
@@ -579,7 +579,8 @@
 	debug_desc(phys, desc);
 	BUG_ON(phys & 0x1F);
 	qmgr_put_entry(queue, phys);
-	BUG_ON(qmgr_stat_overflow(queue));
+	/* Don't check for queue overflow here, we've allocated sufficient
+	   length and queues >= 32 don't support this check anyway. */
 }
 
 
@@ -731,8 +732,8 @@
 		dma_unmap_single(&dev->dev, desc->data,
 				 RX_SIZE, DMA_FROM_DEVICE);
 #else
-		dma_sync_single(&dev->dev, desc->data,
-				RX_SIZE, DMA_FROM_DEVICE);
+		dma_sync_single_for_cpu(&dev->dev, desc->data,
+					RX_SIZE, DMA_FROM_DEVICE);
 		memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n],
 			      ALIGN(desc->pkt_len, 4) / 4);
 #endif
@@ -789,10 +790,10 @@
 		free_buffer_irq(port->tx_buff_tab[n_desc]);
 		port->tx_buff_tab[n_desc] = NULL;
 
-		start = qmgr_stat_empty(port->plat->txreadyq);
+		start = qmgr_stat_below_low_watermark(port->plat->txreadyq);
 		queue_put_desc(port->plat->txreadyq,
 			       tx_desc_phys(port, n_desc), desc);
-		if (start) {
+		if (start) { /* TX-ready queue was empty */
 #if DEBUG_TX
 			printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit"
 			       " ready\n", dev->name);
@@ -867,13 +868,13 @@
 	queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc);
 	dev->trans_start = jiffies;
 
-	if (qmgr_stat_empty(txreadyq)) {
+	if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */
 #if DEBUG_TX
 		printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name);
 #endif
 		netif_stop_queue(dev);
 		/* we could miss TX ready interrupt */
-		if (!qmgr_stat_empty(txreadyq)) {
+		if (!qmgr_stat_below_low_watermark(txreadyq)) {
 #if DEBUG_TX
 			printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n",
 			       dev->name);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/lapbether.c linux-libre-2.6.31-gnu/drivers/net/wan/lapbether.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/lapbether.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/lapbether.c	2009-09-09 18:13:59.000000000 -0400
@@ -149,46 +149,40 @@
  */
 static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	int err = -ENODEV;
+	int err;
 
 	/*
 	 * Just to be *really* sure not to send anything if the interface
 	 * is down, the ethernet device may have gone.
 	 */
-	if (!netif_running(dev)) {
+	if (!netif_running(dev))
 		goto drop;
-	}
 
 	switch (skb->data[0]) {
 	case 0x00:
-		err = 0;
 		break;
 	case 0x01:
 		if ((err = lapb_connect_request(dev)) != LAPB_OK)
 			printk(KERN_ERR "lapbeth: lapb_connect_request "
 			       "error: %d\n", err);
-		goto drop_ok;
+		goto drop;
 	case 0x02:
 		if ((err = lapb_disconnect_request(dev)) != LAPB_OK)
 			printk(KERN_ERR "lapbeth: lapb_disconnect_request "
 			       "err: %d\n", err);
 		/* Fall thru */
 	default:
-		goto drop_ok;
+		goto drop;
 	}
 
 	skb_pull(skb, 1);
 
 	if ((err = lapb_data_request(dev, skb)) != LAPB_OK) {
 		printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
-		err = -ENOMEM;
 		goto drop;
 	}
-	err = 0;
 out:
-	return err;
-drop_ok:
-	err = 0;
+	return NETDEV_TX_OK;
 drop:
 	kfree_skb(skb);
 	goto out;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/pc300_drv.c linux-libre-2.6.31-gnu/drivers/net/wan/pc300_drv.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/pc300_drv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/pc300_drv.c	2009-09-09 18:13:59.000000000 -0400
@@ -225,6 +225,7 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/spinlock.h>
 #include <linux/if.h>
 #include <net/arp.h>
@@ -3246,6 +3247,16 @@
 		rcsvers, rcsdate, __DATE__, __TIME__);
 }				/* show_version */
 
+static const struct net_device_ops cpc_netdev_ops = {
+	.ndo_open		= cpc_open,
+	.ndo_stop		= cpc_close,
+	.ndo_tx_timeout		= cpc_tx_timeout,
+	.ndo_set_mac_address	= NULL,
+	.ndo_change_mtu		= cpc_change_mtu,
+	.ndo_do_ioctl		= cpc_ioctl,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
 static void cpc_init_card(pc300_t * card)
 {
 	int i, devcount = 0;
@@ -3357,18 +3368,11 @@
 		dev->mem_start = card->hw.ramphys;
 		dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1;
 		dev->irq = card->hw.irq;
-		dev->init = NULL;
 		dev->tx_queue_len = PC300_TX_QUEUE_LEN;
 		dev->mtu = PC300_DEF_MTU;
 
-		dev->open = cpc_open;
-		dev->stop = cpc_close;
-		dev->tx_timeout = cpc_tx_timeout;
+		dev->netdev_ops = &cpc_netdev_ops;
 		dev->watchdog_timeo = PC300_TX_TIMEOUT;
-		dev->set_multicast_list = NULL;
-		dev->set_mac_address = NULL;
-		dev->change_mtu = cpc_change_mtu;
-		dev->do_ioctl = cpc_ioctl;
 
 		if (register_hdlc_device(dev) == 0) {
 			printk("%s: Cyclades-PC300/", dev->name);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/sbni.c linux-libre-2.6.31-gnu/drivers/net/wan/sbni.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/sbni.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/sbni.c	2009-09-09 18:13:59.000000000 -0400
@@ -326,11 +326,9 @@
 		}
 
 		if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
-			printk( KERN_WARNING "  WARNING: The PCI BIOS assigned "
-				"this PCI card to IRQ %d, which is unlikely "
-				"to work!.\n"
-				KERN_WARNING " You should use the PCI BIOS "
-				"setup to assign a valid IRQ line.\n",
+			printk( KERN_WARNING
+	"  WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
+	" You should use the PCI BIOS setup to assign a valid IRQ line.\n",
 				pci_irq_line );
 
 		/* avoiding re-enable dual adapters */
@@ -469,7 +467,7 @@
 		}
 	}
 
-	return  1;
+	return NETDEV_TX_BUSY;
 }
 
 #else	/* CONFIG_SBNI_MULTILINE */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wan/wanxl.c linux-libre-2.6.31-gnu/drivers/net/wan/wanxl.c
--- linux-libre-2.6.30-gnu/drivers/net/wan/wanxl.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wan/wanxl.c	2009-09-09 18:13:59.000000000 -0400
@@ -283,7 +283,7 @@
 #endif
 		netif_stop_queue(dev);
 		spin_unlock_irq(&port->lock);
-		return 1;       /* request packet to be queued */
+		return NETDEV_TX_BUSY;       /* request packet to be queued */
 	}
 
 #ifdef DEBUG_PKT
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/control.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/control.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/control.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/control.c	2009-09-09 18:13:59.000000000 -0400
@@ -292,8 +292,6 @@
 
 	d_fnstart(3, dev, "(i2400m %p ss %p [%u])\n", i2400m, ss, i2400m_state);
 
-	if (unlikely(i2400m->ready == 0))	/* act if up */
-		goto out;
 	if (i2400m->state != i2400m_state) {
 		i2400m->state = i2400m_state;
 		wake_up_all(&i2400m->state_wq);
@@ -341,7 +339,6 @@
 		i2400m->bus_reset(i2400m, I2400M_RT_WARM);
 		break;
 	};
-out:
 	d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n",
 		i2400m, ss, i2400m_state);
 }
@@ -372,8 +369,6 @@
 
 	d_fnstart(3, dev, "(i2400m %p ms %p [%u])\n", i2400m, ms, status);
 
-	if (unlikely(i2400m->ready == 0))	/* act if up */
-		goto out;
 	switch (status) {
 	case I2400M_MEDIA_STATUS_LINK_UP:
 		netif_carrier_on(net_dev);
@@ -393,14 +388,59 @@
 		dev_err(dev, "HW BUG? unknown media status %u\n",
 			status);
 	};
-out:
 	d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n",
 		i2400m, ms, status);
 }
 
 
 /*
- * Parse a 'state report' and extract carrier on/off information
+ * Process a TLV from a 'state report'
+ *
+ * @i2400m: device descriptor
+ * @tlv: pointer to the TLV header; it has been already validated for
+ *     consistent size.
+ * @tag: for error messages
+ *
+ * Act on the TLVs from a 'state report'.
+ */
+static
+void i2400m_report_state_parse_tlv(struct i2400m *i2400m,
+				   const struct i2400m_tlv_hdr *tlv,
+				   const char *tag)
+{
+	struct device *dev = i2400m_dev(i2400m);
+	const struct i2400m_tlv_media_status *ms;
+	const struct i2400m_tlv_system_state *ss;
+	const struct i2400m_tlv_rf_switches_status *rfss;
+
+	if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE, sizeof(*ss))) {
+		ss = container_of(tlv, typeof(*ss), hdr);
+		d_printf(2, dev, "%s: system state TLV "
+			 "found (0x%04x), state 0x%08x\n",
+			 tag, I2400M_TLV_SYSTEM_STATE,
+			 le32_to_cpu(ss->state));
+		i2400m_report_tlv_system_state(i2400m, ss);
+	}
+	if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS, sizeof(*rfss))) {
+		rfss = container_of(tlv, typeof(*rfss), hdr);
+		d_printf(2, dev, "%s: RF status TLV "
+			 "found (0x%04x), sw 0x%02x hw 0x%02x\n",
+			 tag, I2400M_TLV_RF_STATUS,
+			 le32_to_cpu(rfss->sw_rf_switch),
+			 le32_to_cpu(rfss->hw_rf_switch));
+		i2400m_report_tlv_rf_switches_status(i2400m, rfss);
+	}
+	if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS, sizeof(*ms))) {
+		ms = container_of(tlv, typeof(*ms), hdr);
+		d_printf(2, dev, "%s: Media Status TLV: %u\n",
+			 tag, le32_to_cpu(ms->media_status));
+		i2400m_report_tlv_media_status(i2400m, ms);
+	}
+}
+
+
+/*
+ * Parse a 'state report' and extract information
  *
  * @i2400m: device descriptor
  * @l3l4_hdr: pointer to message; it has been already validated for
@@ -409,13 +449,7 @@
  *        declaration is assumed to be congruent with @size (as in
  *        sizeof(*l3l4_hdr) + l3l4_hdr->length == size)
  *
- * Extract from the report state the system state TLV and infer from
- * there if we have a carrier or not. Update our local state and tell
- * netdev.
- *
- * When setting the carrier, it's fine to set OFF twice (for example),
- * as netif_carrier_off() will not generate two OFF events (just on
- * the transitions).
+ * Walk over the TLVs in a report state and act on them.
  */
 static
 void i2400m_report_state_hook(struct i2400m *i2400m,
@@ -424,9 +458,6 @@
 {
 	struct device *dev = i2400m_dev(i2400m);
 	const struct i2400m_tlv_hdr *tlv;
-	const struct i2400m_tlv_system_state *ss;
-	const struct i2400m_tlv_rf_switches_status *rfss;
-	const struct i2400m_tlv_media_status *ms;
 	size_t tlv_size = le16_to_cpu(l3l4_hdr->length);
 
 	d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n",
@@ -434,34 +465,8 @@
 	tlv = NULL;
 
 	while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl,
-					     tlv_size, tlv))) {
-		if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE,
-					  sizeof(*ss))) {
-			ss = container_of(tlv, typeof(*ss), hdr);
-			d_printf(2, dev, "%s: system state TLV "
-				 "found (0x%04x), state 0x%08x\n",
-				 tag, I2400M_TLV_SYSTEM_STATE,
-				 le32_to_cpu(ss->state));
-			i2400m_report_tlv_system_state(i2400m, ss);
-		}
-		if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS,
-					  sizeof(*rfss))) {
-			rfss = container_of(tlv, typeof(*rfss), hdr);
-			d_printf(2, dev, "%s: RF status TLV "
-				 "found (0x%04x), sw 0x%02x hw 0x%02x\n",
-				 tag, I2400M_TLV_RF_STATUS,
-				 le32_to_cpu(rfss->sw_rf_switch),
-				 le32_to_cpu(rfss->hw_rf_switch));
-			i2400m_report_tlv_rf_switches_status(i2400m, rfss);
-		}
-		if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS,
-					  sizeof(*ms))) {
-			ms = container_of(tlv, typeof(*ms), hdr);
-			d_printf(2, dev, "%s: Media Status TLV: %u\n",
-				 tag, le32_to_cpu(ms->media_status));
-			i2400m_report_tlv_media_status(i2400m, ms);
-		}
-	}
+					     tlv_size, tlv)))
+		i2400m_report_state_parse_tlv(i2400m, tlv, tag);
 	d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n",
 		i2400m, l3l4_hdr, size, tag);
 }
@@ -500,8 +505,15 @@
 	 * it. */
 	case I2400M_MT_REPORT_POWERSAVE_READY:	/* zzzzz */
 		if (l3l4_hdr->status == cpu_to_le16(I2400M_MS_DONE_OK)) {
-			d_printf(1, dev, "ready for powersave, requesting\n");
-			i2400m_cmd_enter_powersave(i2400m);
+			if (i2400m_power_save_disabled)
+				d_printf(1, dev, "ready for powersave, "
+					 "not requesting (disabled by module "
+					 "parameter)\n");
+			else {
+				d_printf(1, dev, "ready for powersave, "
+					 "requesting\n");
+				i2400m_cmd_enter_powersave(i2400m);
+			}
 		}
 		break;
 	};
@@ -683,8 +695,9 @@
 	d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n",
 		  i2400m, buf, buf_len);
 
+	rmb();		/* Make sure we see what i2400m_dev_reset_handle() */
 	if (i2400m->boot_mode)
-		return ERR_PTR(-ENODEV);
+		return ERR_PTR(-EL3RST);
 
 	msg_l3l4_hdr = buf;
 	/* Check msg & payload consistency */
@@ -721,6 +734,8 @@
 		ack_timeout = HZ;
 	};
 
+	if (unlikely(i2400m->trace_msg_from_user))
+		wimax_msg(&i2400m->wimax_dev, "echo", buf, buf_len, GFP_KERNEL);
 	/* The RX path in rx.c will put any response for this message
 	 * in i2400m->ack_skb and wake us up. If we cancel the wait,
 	 * we need to change the value of i2400m->ack_skb to something
@@ -755,6 +770,9 @@
 	ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len);
 
 	/* Check the ack and deliver it if it is ok */
+	if (unlikely(i2400m->trace_msg_from_user))
+		wimax_msg(&i2400m->wimax_dev, "echo",
+			  ack_l3l4_hdr, ack_len, GFP_KERNEL);
 	result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len);
 	if (result < 0) {
 		dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n",
@@ -1379,16 +1397,16 @@
  *
  * @i2400m: device descriptor
  *
- * Gracefully stops the device, moving it to the lowest power
- * consumption state possible.
+ * Release resources acquired during the running of the device; in
+ * theory, should also tell the device to go to sleep, switch off the
+ * radio, all that, but at this point, in most cases (driver
+ * disconnection, reset handling) we can't even talk to the device.
  */
 void i2400m_dev_shutdown(struct i2400m *i2400m)
 {
-	int result = -ENODEV;
 	struct device *dev = i2400m_dev(i2400m);
 
 	d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
-	result = i2400m->bus_reset(i2400m, I2400M_RT_WARM);
-	d_fnend(3, dev, "(i2400m %p) = void [%d]\n", i2400m, result);
+	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
 	return;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/driver.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/driver.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/driver.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/driver.c	2009-09-09 18:13:59.000000000 -0400
@@ -62,6 +62,7 @@
  *   unregister_netdev()
  */
 #include "i2400m.h"
+#include <linux/etherdevice.h>
 #include <linux/wimax/i2400m.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -81,6 +82,14 @@
 MODULE_PARM_DESC(rx_reorder_disabled,
 		 "If true, RX reordering will be disabled.");
 
+int i2400m_power_save_disabled;	/* 0 (power saving enabled) by default */
+module_param_named(power_save_disabled, i2400m_power_save_disabled, int, 0644);
+MODULE_PARM_DESC(power_save_disabled,
+		 "If true, the driver will not tell the device to enter "
+		 "power saving mode when it reports it is ready for it. "
+		 "False by default (so the device is told to do power "
+		 "saving).");
+
 /**
  * i2400m_queue_work - schedule work on a i2400m's queue
  *
@@ -171,7 +180,6 @@
 	int result;
 	struct i2400m_work *iw;
 
-	BUG_ON(i2400m->work_queue == NULL);
 	result = -ENOMEM;
 	iw = kzalloc(sizeof(*iw), gfp_flags);
 	if (iw == NULL)
@@ -234,9 +242,6 @@
 	result = PTR_ERR(ack_skb);
 	if (IS_ERR(ack_skb))
 		goto error_msg_to_dev;
-	if (unlikely(i2400m->trace_msg_from_user))
-		wimax_msg(&i2400m->wimax_dev, "trace",
-			  msg_buf, msg_len, GFP_KERNEL);
 	result = wimax_msg_send(&i2400m->wimax_dev, ack_skb);
 error_msg_to_dev:
 	d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu "
@@ -379,6 +384,11 @@
  * Uploads firmware and brings up all the resources needed to be able
  * to communicate with the device.
  *
+ * The workqueue has to be setup early, at least before RX handling
+ * (it's only real user for now) so it can process reports as they
+ * arrive. We also want to destroy it if we retry, to make sure it is
+ * flushed...easier like this.
+ *
  * TX needs to be setup before the bus-specific code (otherwise on
  * shutdown, the bus-tx code could try to access it).
  */
@@ -389,7 +399,7 @@
 	struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
 	struct net_device *net_dev = wimax_dev->net_dev;
 	struct device *dev = i2400m_dev(i2400m);
-	int times = 3;
+	int times = i2400m->bus_bm_retries;
 
 	d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
 retry:
@@ -404,15 +414,15 @@
 	result = i2400m_rx_setup(i2400m);
 	if (result < 0)
 		goto error_rx_setup;
-	result = i2400m->bus_dev_start(i2400m);
-	if (result < 0)
-		goto error_bus_dev_start;
 	i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name);
 	if (i2400m->work_queue == NULL) {
 		result = -ENOMEM;
 		dev_err(dev, "cannot create workqueue\n");
 		goto error_create_workqueue;
 	}
+	result = i2400m->bus_dev_start(i2400m);
+	if (result < 0)
+		goto error_bus_dev_start;
 	result = i2400m_firmware_check(i2400m);	/* fw versions ok? */
 	if (result < 0)
 		goto error_fw_check;
@@ -434,17 +444,17 @@
 error_dev_initialize:
 error_check_mac_addr:
 error_fw_check:
-	destroy_workqueue(i2400m->work_queue);
-error_create_workqueue:
 	i2400m->bus_dev_stop(i2400m);
 error_bus_dev_start:
+	destroy_workqueue(i2400m->work_queue);
+error_create_workqueue:
 	i2400m_rx_release(i2400m);
 error_rx_setup:
 	i2400m_tx_release(i2400m);
 error_tx_setup:
 error_bootstrap:
-	if (result == -ERESTARTSYS && times-- > 0) {
-		flags = I2400M_BRI_SOFT;
+	if (result == -EL3RST && times-- > 0) {
+		flags = I2400M_BRI_SOFT|I2400M_BRI_MAC_REINIT;
 		goto retry;
 	}
 	d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
@@ -473,7 +483,9 @@
  *
  * Returns: 0 if ok, < 0 errno code on error.
  *
- * Releases all the resources allocated to communicate with the device.
+ * Releases all the resources allocated to communicate with the
+ * device. Note we cannot destroy the workqueue earlier as until RX is
+ * fully destroyed, it could still try to schedule jobs.
  */
 static
 void __i2400m_dev_stop(struct i2400m *i2400m)
@@ -485,8 +497,8 @@
 	wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
 	i2400m_dev_shutdown(i2400m);
 	i2400m->ready = 0;
-	destroy_workqueue(i2400m->work_queue);
 	i2400m->bus_dev_stop(i2400m);
+	destroy_workqueue(i2400m->work_queue);
 	i2400m_rx_release(i2400m);
 	i2400m_tx_release(i2400m);
 	wimax_state_change(wimax_dev, WIMAX_ST_DOWN);
@@ -548,7 +560,7 @@
 		 * i2400m_dev_stop() [we are shutting down anyway, so
 		 * ignore it] or we are resetting somewhere else. */
 		dev_err(dev, "device rebooted\n");
-		i2400m_msg_to_dev_cancel_wait(i2400m, -ERESTARTSYS);
+		i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST);
 		complete(&i2400m->msg_completion);
 		goto out;
 	}
@@ -598,6 +610,8 @@
  */
 int i2400m_dev_reset_handle(struct i2400m *i2400m)
 {
+	i2400m->boot_mode = 1;
+	wmb();		/* Make sure i2400m_msg_to_dev() sees boot_mode */
 	return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle,
 				    GFP_ATOMIC);
 }
@@ -650,6 +664,7 @@
 	result = i2400m_read_mac_addr(i2400m);
 	if (result < 0)
 		goto error_read_mac_addr;
+	random_ether_addr(i2400m->src_mac_addr);
 
 	result = register_netdev(net_dev);	/* Okey dokey, bring it up */
 	if (result < 0) {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/fw.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/fw.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/fw.c	2012-03-22 19:19:51.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/fw.c	2012-03-22 20:14:54.000000000 -0400
@@ -397,7 +397,7 @@
 				 unsigned int direct, unsigned int do_csum)
 {
 	int ret;
-	size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_PAD);
+	size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_ALIGN);
 	struct device *dev = i2400m_dev(i2400m);
 	struct {
 		struct i2400m_bootrom_header cmd;
@@ -532,14 +532,14 @@
 	cmd = (void *) bcf + offset;
 	if (i2400m->sboot == 0) {
 		struct i2400m_bootrom_header jump_ack;
-		d_printf(3, dev, "unsecure boot, jumping to 0x%08x\n",
+		d_printf(1, dev, "unsecure boot, jumping to 0x%08x\n",
 			le32_to_cpu(cmd->target_addr));
 		i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP);
 		cmd->data_size = 0;
 		ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
 				    &jump_ack, sizeof(jump_ack), 0);
 	} else {
-		d_printf(3, dev, "secure boot, jumping to 0x%08x\n",
+		d_printf(1, dev, "secure boot, jumping to 0x%08x\n",
 			 le32_to_cpu(cmd->target_addr));
 		cmd_buf = i2400m->bm_cmd_buf;
 		memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd));
@@ -696,8 +696,7 @@
 	return result;
 
 error_timeout:
-	dev_err(dev, "Timed out waiting for reboot ack, resetting\n");
-	i2400m->bus_reset(i2400m, I2400M_RT_BUS);
+	dev_err(dev, "Timed out waiting for reboot ack\n");
 	result = -ETIMEDOUT;
 	goto exit_timeout;
 }
@@ -770,40 +769,21 @@
 static
 int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
 {
-#define POKE(a, d) {					\
-	.address = cpu_to_le32(a),		\
-	.data = cpu_to_le32(d)		\
-}
-	static const struct {
-		__le32 address;
-		__le32 data;
-	} i2400m_pokes[] = {
-		POKE(0x081A58, 0xA7810230),
-		POKE(0x080040, 0x00000000),
-		POKE(0x080048, 0x00000082),
-		POKE(0x08004C, 0x0000081F),
-		POKE(0x080054, 0x00000085),
-		POKE(0x080058, 0x00000180),
-		POKE(0x08005C, 0x00000018),
-		POKE(0x080060, 0x00000010),
-		POKE(0x080574, 0x00000001),
-		POKE(0x080550, 0x00000005),
-		POKE(0xAE0000, 0x00000000),
-	};
-#undef POKE
-	unsigned i;
-	int ret;
+	unsigned i = 0;
+	int ret = 0;
 	struct device *dev = i2400m_dev(i2400m);
-
-	dev_warn(dev, "WARNING!!! non-signed boot UNTESTED PATH!\n");
-
 	d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
-	for (i = 0; i < ARRAY_SIZE(i2400m_pokes); i++) {
-		ret = i2400m_download_chunk(i2400m, &i2400m_pokes[i].data,
-					    sizeof(i2400m_pokes[i].data),
-					    i2400m_pokes[i].address, 1, 1);
-		if (ret < 0)
-			break;
+	if (i2400m->bus_bm_pokes_table) {
+		while (i2400m->bus_bm_pokes_table[i].address) {
+			ret = i2400m_download_chunk(
+				i2400m,
+				&i2400m->bus_bm_pokes_table[i].data,
+				sizeof(i2400m->bus_bm_pokes_table[i].data),
+				i2400m->bus_bm_pokes_table[i].address, 1, 1);
+			if (ret < 0)
+				break;
+			i++;
+		}
 	}
 	d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
 	return ret;
@@ -980,11 +960,12 @@
 {
 	int ret = 0;
 	struct device *dev = i2400m_dev(i2400m);
-	int count = I2400M_BOOT_RETRIES;
+	int count = i2400m->bus_bm_retries;
 
 	d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n",
 		  i2400m, bcf, bcf_size);
 	i2400m->boot_mode = 1;
+	wmb();		/* Make sure other readers see it */
 hw_reboot:
 	if (count-- == 0) {
 		ret = -ERESTARTSYS;
@@ -1033,6 +1014,7 @@
 	d_printf(2, dev, "fw %s successfully uploaded\n",
 		 i2400m->fw_name);
 	i2400m->boot_mode = 0;
+	wmb();		/* Make sure i2400m_msg_to_dev() sees boot_mode */
 error_dnload_finalize:
 error_dnload_bcf:
 error_dnload_init:
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/i2400m.h linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/i2400m.h
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/i2400m.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/i2400m.h	2009-09-09 18:13:59.000000000 -0400
@@ -150,11 +150,33 @@
 enum {
 	/* Firmware uploading */
 	I2400M_BOOT_RETRIES = 3,
+	I3200_BOOT_RETRIES = 3,
 	/* Size of the Boot Mode Command buffer */
 	I2400M_BM_CMD_BUF_SIZE = 16 * 1024,
 	I2400M_BM_ACK_BUF_SIZE = 256,
 };
 
+/**
+ * struct i2400m_poke_table - Hardware poke table for the Intel 2400m
+ *
+ * This structure will be used to create a device specific poke table
+ * to put the device in a consistant state at boot time.
+ *
+ * @address: The device address to poke
+ *
+ * @data: The data value to poke to the device address
+ *
+ */
+struct i2400m_poke_table{
+	__le32 address;
+	__le32 data;
+};
+
+#define I2400M_FW_POKE(a, d) {		\
+	.address = cpu_to_le32(a),	\
+	.data = cpu_to_le32(d)		\
+}
+
 
 /**
  * i2400m_reset_type - methods to reset a device
@@ -224,6 +246,17 @@
  *     process, so it cannot rely on common infrastructure being laid
  *     out.
  *
+ * @bus_bm_retries: [fill] How many times shall a firmware upload /
+ *     device initialization be retried? Different models of the same
+ *     device might need different values, hence it is set by the
+ *     bus-specific driver. Note this value is used in two places,
+ *     i2400m_fw_dnload() and __i2400m_dev_start(); they won't become
+ *     multiplicative (__i2400m_dev_start() calling N times
+ *     i2400m_fw_dnload() and this trying N times to download the
+ *     firmware), as if __i2400m_dev_start() only retries if the
+ *     firmware crashed while initializing the device (not in a
+ *     general case).
+ *
  * @bus_bm_cmd_send: [fill] Function called to send a boot-mode
  *     command. Flags are defined in 'enum i2400m_bm_cmd_flags'. This
  *     is synchronous and has to return 0 if ok or < 0 errno code in
@@ -252,6 +285,12 @@
  *     address provided in boot mode is kind of broken and needs to
  *     be re-read later on.
  *
+ * @bus_bm_pokes_table: [fill/optional] A table of device addresses
+ *     and values that will be poked at device init time to move the
+ *     device to the correct state for the type of boot/firmware being
+ *     used.  This table MUST be terminated with (0x000000,
+ *     0x00000000) or bad things will happen.
+ *
  *
  * @wimax_dev: WiMAX generic device for linkage into the kernel WiMAX
  *     stack. Due to the way a net_device is allocated, we need to
@@ -323,6 +362,10 @@
  *     delivered. Then the driver can release them to the host. See
  *     drivers/net/i2400m/rx.c for details.
  *
+ * @src_mac_addr: MAC address used to make ethernet packets be coming
+ *     from. This is generated at i2400m_setup() time and used during
+ *     the life cycle of the instance. See i2400m_fake_eth_header().
+ *
  * @init_mutex: Mutex used for serializing the device bringup
  *     sequence; this way if the device reboots in the middle, we
  *     don't try to do a bringup again while we are tearing down the
@@ -389,12 +432,14 @@
 	unsigned ready:1;		/* all probing steps done */
 	unsigned rx_reorder:1;		/* RX reorder is enabled */
 	u8 trace_msg_from_user;		/* echo rx msgs to 'trace' pipe */
-					/* typed u8 so debugfs/u8 can tweak */
+					/* typed u8 so /sys/kernel/debug/u8 can tweak */
 	enum i2400m_system_state state;
 	wait_queue_head_t state_wq;	/* Woken up when on state updates */
 
 	size_t bus_tx_block_size;
 	size_t bus_pl_size_max;
+	unsigned bus_bm_retries;
+
 	int (*bus_dev_start)(struct i2400m *);
 	void (*bus_dev_stop)(struct i2400m *);
 	void (*bus_tx_kick)(struct i2400m *);
@@ -406,6 +451,7 @@
 				       struct i2400m_bootrom_header *, size_t);
 	const char **bus_fw_names;
 	unsigned bus_bm_mac_addr_impaired:1;
+	const struct i2400m_poke_table *bus_bm_pokes_table;
 
 	spinlock_t tx_lock;		/* protect TX state */
 	void *tx_buf;
@@ -421,6 +467,7 @@
 	unsigned rx_pl_num, rx_pl_max, rx_pl_min,
 		rx_num, rx_size_acc, rx_size_min, rx_size_max;
 	struct i2400m_roq *rx_roq;	/* not under rx_lock! */
+	u8 src_mac_addr[ETH_HLEN];
 
 	struct mutex msg_mutex;		/* serialize command execution */
 	struct completion msg_completion;
@@ -704,6 +751,7 @@
 	cpu_to_le32(I2400M_SBOOT_BARKER)
 };
 
+extern int i2400m_power_save_disabled;
 
 /*
  * Utility functions
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/i2400m-sdio.h linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/i2400m-sdio.h
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/i2400m-sdio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/i2400m-sdio.h	2009-09-09 18:13:59.000000000 -0400
@@ -78,6 +78,8 @@
 	/* The number of ticks to wait for the device to signal that
 	 * it is ready */
 	I2400MS_INIT_SLEEP_INTERVAL = 10,
+	/* How long to wait for the device to settle after reset */
+	I2400MS_SETTLE_TIME = 40,
 };
 
 
@@ -105,6 +107,10 @@
 	char tx_wq_name[32];
 
 	struct dentry *debugfs_dentry;
+
+	wait_queue_head_t bm_wfa_wq;
+	int bm_wait_result;
+	size_t bm_ack_size;
 };
 
 
@@ -129,4 +135,7 @@
 extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *,
 					   struct i2400m_bootrom_header *,
 					   size_t);
+extern void i2400ms_bus_bm_release(struct i2400m *);
+extern int i2400ms_bus_bm_setup(struct i2400m *);
+
 #endif /* #ifndef __I2400M_SDIO_H__ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/netdev.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/netdev.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/netdev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/netdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -404,10 +404,12 @@
 void i2400m_rx_fake_eth_header(struct net_device *net_dev,
 			       void *_eth_hdr, __be16 protocol)
 {
+	struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
 	struct ethhdr *eth_hdr = _eth_hdr;
 
 	memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest));
-	memset(eth_hdr->h_source, 0, sizeof(eth_hdr->h_dest));
+	memcpy(eth_hdr->h_source, i2400m->src_mac_addr,
+	       sizeof(eth_hdr->h_source));
 	eth_hdr->h_proto = protocol;
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/op-rfkill.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/op-rfkill.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/op-rfkill.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/op-rfkill.c	2009-09-09 18:13:59.000000000 -0400
@@ -54,8 +54,10 @@
 		/* state == WIMAX_RF_ON */
 		return i2400m->state != I2400M_SS_RF_OFF
 			&& i2400m->state != I2400M_SS_RF_SHUTDOWN;
-	else
+	else {
 		BUG();
+		return -EINVAL;	/* shut gcc warnings on certain arches */
+	}
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/rx.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/rx.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/rx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/rx.c	2009-09-09 18:13:59.000000000 -0400
@@ -177,7 +177,8 @@
 	struct i2400m_work *iw =
 		container_of(ws, struct i2400m_work, ws);
 	struct i2400m_report_hook_args *args = (void *) iw->pl;
-	i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size);
+	if (iw->i2400m->ready)
+		i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size);
 	kfree_skb(args->skb_rx);
 	i2400m_put(iw->i2400m);
 	kfree(iw);
@@ -309,6 +310,9 @@
 		skb_get(skb_rx);
 		i2400m_queue_work(i2400m, i2400m_report_hook_work,
 				  GFP_KERNEL, &args, sizeof(args));
+		if (unlikely(i2400m->trace_msg_from_user))
+			wimax_msg(&i2400m->wimax_dev, "echo",
+				  l3l4_hdr, size, GFP_KERNEL);
 		result = wimax_msg(&i2400m->wimax_dev, NULL, l3l4_hdr, size,
 				   GFP_KERNEL);
 		if (result < 0)
@@ -1144,7 +1148,7 @@
 	num_pls = le16_to_cpu(msg_hdr->num_pls);
 	pl_itr = sizeof(*msg_hdr) +	/* Check payload descriptor(s) */
 		num_pls * sizeof(msg_hdr->pld[0]);
-	pl_itr = ALIGN(pl_itr, I2400M_PL_PAD);
+	pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN);
 	if (pl_itr > skb->len) {	/* got all the payload descriptors? */
 		dev_err(dev, "RX: HW BUG? message too short (%u bytes) for "
 			"%u payload descriptors (%zu each, total %zu)\n",
@@ -1162,7 +1166,7 @@
 		single_last = num_pls == 1 || i == num_pls - 1;
 		i2400m_rx_payload(i2400m, skb, single_last, &msg_hdr->pld[i],
 				  skb->data + pl_itr);
-		pl_itr += ALIGN(pl_size, I2400M_PL_PAD);
+		pl_itr += ALIGN(pl_size, I2400M_PL_ALIGN);
 		cond_resched();		/* Don't monopolize */
 	}
 	kfree_skb(skb);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/sdio.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/sdio.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/sdio.c	2012-03-22 19:19:53.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/sdio.c	2012-03-22 20:14:56.000000000 -0400
@@ -78,6 +78,14 @@
 };
 
 
+static const struct i2400m_poke_table i2400ms_pokes[] = {
+	I2400M_FW_POKE(0x6BE260, 0x00000088),
+	I2400M_FW_POKE(0x080550, 0x00000005),
+	I2400M_FW_POKE(0xAE0000, 0x00000000),
+	I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad
+					       * things will happen */
+};
+
 /*
  * Enable the SDIO function
  *
@@ -148,19 +156,14 @@
 
 	d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
 	msleep(200);
-	result = i2400ms_rx_setup(i2400ms);
-	if (result < 0)
-		goto error_rx_setup;
 	result = i2400ms_tx_setup(i2400ms);
 	if (result < 0)
 		goto error_tx_setup;
 	d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
 	return result;
 
-	i2400ms_tx_release(i2400ms);
 error_tx_setup:
-	i2400ms_rx_release(i2400ms);
-error_rx_setup:
+	i2400ms_tx_release(i2400ms);
 	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
 	return result;
 }
@@ -174,7 +177,6 @@
 	struct device *dev = &func->dev;
 
 	d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
-	i2400ms_rx_release(i2400ms);
 	i2400ms_tx_release(i2400ms);
 	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
 }
@@ -255,7 +257,7 @@
 static
 int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
 {
-	int result;
+	int result = 0;
 	struct i2400ms *i2400ms =
 		container_of(i2400m, struct i2400ms, i2400m);
 	struct device *dev = i2400m_dev(i2400m);
@@ -280,8 +282,25 @@
 					       sizeof(i2400m_COLD_BOOT_BARKER));
 	else if (rt == I2400M_RT_BUS) {
 do_bus_reset:
-		dev_err(dev, "FIXME: SDIO bus reset not implemented\n");
-		result = rt == I2400M_RT_WARM ? -ENODEV : -ENOSYS;
+		/* call netif_tx_disable() before sending IOE disable,
+		 * so that all the tx from network layer are stopped
+		 * while IOE is being reset. Make sure it is called
+		 * only after register_netdev() was issued.
+		 */
+		if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED)
+			netif_tx_disable(i2400m->wimax_dev.net_dev);
+
+		i2400ms_rx_release(i2400ms);
+		sdio_claim_host(i2400ms->func);
+		sdio_disable_func(i2400ms->func);
+		sdio_release_host(i2400ms->func);
+
+		/* Wait for the device to settle */
+		msleep(40);
+
+		result = i2400ms_enable_function(i2400ms->func);
+		if (result >= 0)
+			i2400ms_rx_setup(i2400ms);
 	} else
 		BUG();
 	if (result < 0 && rt != I2400M_RT_BUS) {
@@ -404,24 +423,32 @@
 	i2400m->bus_dev_stop = i2400ms_bus_dev_stop;
 	i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
 	i2400m->bus_reset = i2400ms_bus_reset;
+	/* The iwmc3200-wimax sometimes requires the driver to try
+	 * hard when we paint it into a corner. */
+	i2400m->bus_bm_retries = I3200_BOOT_RETRIES;
 	i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
 	i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
 	i2400m->bus_fw_names = i2400ms_bus_fw_names;
 	i2400m->bus_bm_mac_addr_impaired = 1;
-
-	result = i2400ms_enable_function(i2400ms->func);
-	if (result < 0) {
-		dev_err(dev, "Cannot enable SDIO function: %d\n", result);
-		goto error_func_enable;
-	}
+	i2400m->bus_bm_pokes_table = &i2400ms_pokes[0];
 
 	sdio_claim_host(func);
 	result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
+	sdio_release_host(func);
 	if (result < 0) {
 		dev_err(dev, "Failed to set block size: %d\n", result);
 		goto error_set_blk_size;
 	}
-	sdio_release_host(func);
+
+	result = i2400ms_enable_function(i2400ms->func);
+	if (result < 0) {
+		dev_err(dev, "Cannot enable SDIO function: %d\n", result);
+		goto error_func_enable;
+	}
+
+	result = i2400ms_rx_setup(i2400ms);
+	if (result < 0)
+		goto error_rx_setup;
 
 	result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
 	if (result < 0) {
@@ -440,12 +467,14 @@
 error_debugfs_add:
 	i2400m_release(i2400m);
 error_setup:
-	sdio_set_drvdata(func, NULL);
+	i2400ms_rx_release(i2400ms);
+error_rx_setup:
 	sdio_claim_host(func);
-error_set_blk_size:
 	sdio_disable_func(func);
 	sdio_release_host(func);
 error_func_enable:
+error_set_blk_size:
+	sdio_set_drvdata(func, NULL);
 	free_netdev(net_dev);
 error_alloc_netdev:
 	return result;
@@ -462,6 +491,7 @@
 
 	d_fnstart(3, dev, "SDIO func %p\n", func);
 	debugfs_remove_recursive(i2400ms->debugfs_dentry);
+	i2400ms_rx_release(i2400ms);
 	i2400m_release(i2400m);
 	sdio_set_drvdata(func, NULL);
 	sdio_claim_host(func);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/sdio-fw.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/sdio-fw.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/sdio-fw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/sdio-fw.c	2009-09-09 18:13:59.000000000 -0400
@@ -46,17 +46,24 @@
  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  *  - SDIO rehash for changes in the bus-driver model
  *
+ * Dirk Brandewie <dirk.j.brandewie@intel.com>
+ *  - Make it IRQ based, not polling
+ *
  * THE PROCEDURE
  *
  * See fw.c for the generic description of this procedure.
  *
  * This file implements only the SDIO specifics. It boils down to how
  * to send a command and waiting for an acknowledgement from the
- * device. We do polled reads.
+ * device.
+ *
+ * All this code is sequential -- all i2400ms_bus_bm_*() functions are
+ * executed in the same thread, except i2400ms_bm_irq() [on its own by
+ * the SDIO driver]. This makes it possible to avoid locking.
  *
  * COMMAND EXECUTION
  *
- * THe generic firmware upload code will call i2400m_bus_bm_cmd_send()
+ * The generic firmware upload code will call i2400m_bus_bm_cmd_send()
  * to send commands.
  *
  * The SDIO devices expects things in 256 byte blocks, so it will pad
@@ -64,12 +71,15 @@
  *
  * ACK RECEPTION
  *
- * This works in polling mode -- the fw loader says when to wait for
- * data and for that it calls i2400ms_bus_bm_wait_for_ack().
+ * This works in IRQ mode -- the fw loader says when to wait for data
+ * and for that it calls i2400ms_bus_bm_wait_for_ack().
  *
- * This will poll the device for data until it is received. We need to
- * receive at least as much bytes as where asked for (although it'll
- * always be a multiple of 256 bytes).
+ * This checks if there is any data available (RX size > 0); if not,
+ * waits for the IRQ handler to notify about it. Once there is data,
+ * it is read and passed to the caller. Doing it this way we don't
+ * need much coordination/locking, and it makes it much more difficult
+ * for an interrupt to be lost and the wait_for_ack() function getting
+ * stuck even when data is pending.
  */
 #include <linux/mmc/sdio_func.h>
 #include "i2400m-sdio.h"
@@ -78,6 +88,7 @@
 #define D_SUBMODULE fw
 #include "sdio-debug-levels.h"
 
+
 /*
  * Send a boot-mode command to the SDIO function
  *
@@ -139,7 +150,7 @@
 
 
 /*
- * Read an ack from the device's boot-mode (polling)
+ * Read an ack from the device's boot-mode
  *
  * @i2400m:
  * @_ack: pointer to where to store the read data
@@ -150,75 +161,49 @@
  * The ACK for a BM command is always at least sizeof(*ack) bytes, so
  * check for that. We don't need to check for device reboots
  *
- * NOTE: We do an artificial timeout of 1 sec over the SDIO timeout;
- *     this way we have control over it...there is no way that I know
- *     of setting an SDIO transaction timeout.
  */
 ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m,
 				    struct i2400m_bootrom_header *ack,
 				    size_t ack_size)
 {
-	int result;
-	ssize_t rx_size;
-	u64 timeout;
+	ssize_t result;
 	struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
 	struct sdio_func *func = i2400ms->func;
 	struct device *dev = &func->dev;
+	int size;
 
 	BUG_ON(sizeof(*ack) > ack_size);
 
 	d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n",
 		  i2400m, ack, ack_size);
 
-	timeout = get_jiffies_64() + 2 * HZ;
-	sdio_claim_host(func);
-	while (1) {
-		if (time_after64(get_jiffies_64(), timeout)) {
-			rx_size = -ETIMEDOUT;
-			dev_err(dev, "timeout waiting for ack data\n");
-			goto error_timedout;
-		}
+	spin_lock(&i2400m->rx_lock);
+	i2400ms->bm_ack_size = -EINPROGRESS;
+	spin_unlock(&i2400m->rx_lock);
 
-		/* Find the RX size, check if it fits or not -- it if
-		 * doesn't fit, fail, as we have no way to dispose of
-		 * the extra data. */
-		rx_size = __i2400ms_rx_get_size(i2400ms);
-		if (rx_size < 0)
-			goto error_rx_get_size;
-		result = -ENOSPC;		/* Check it fits */
-		if (rx_size < sizeof(*ack)) {
-			rx_size = -EIO;
-			dev_err(dev, "HW BUG? received is too small (%zu vs "
-				"%zu needed)\n", sizeof(*ack), rx_size);
-			goto error_too_small;
-		}
-		if (rx_size > I2400M_BM_ACK_BUF_SIZE) {
-			dev_err(dev, "SW BUG? BM_ACK_BUF is too small (%u vs "
-				"%zu needed)\n", I2400M_BM_ACK_BUF_SIZE,
-				rx_size);
-			goto error_too_small;
-		}
+	result = wait_event_timeout(i2400ms->bm_wfa_wq,
+				    i2400ms->bm_ack_size != -EINPROGRESS,
+				    2 * HZ);
+	if (result == 0) {
+		result = -ETIMEDOUT;
+		dev_err(dev, "BM: error waiting for an ack\n");
+		goto error_timeout;
+	}
 
-		/* Read it */
-		result = sdio_memcpy_fromio(func, i2400m->bm_ack_buf,
-					    I2400MS_DATA_ADDR, rx_size);
-		if (result == -ETIMEDOUT || result == -ETIME)
-			continue;
-		if (result < 0) {
-			dev_err(dev, "BM SDIO receive (%zu B) failed: %d\n",
-				rx_size, result);
-			goto error_read;
-		} else
-			break;
+	spin_lock(&i2400m->rx_lock);
+	result = i2400ms->bm_ack_size;
+	BUG_ON(result == -EINPROGRESS);
+	if (result < 0)        /* so we exit when rx_release() is called */
+		dev_err(dev, "BM: %s failed: %zd\n", __func__, result);
+	else {
+		size = min(ack_size, i2400ms->bm_ack_size);
+		memcpy(ack, i2400m->bm_ack_buf, size);
 	}
-	rx_size = min((ssize_t)ack_size, rx_size);
-	memcpy(ack, i2400m->bm_ack_buf, rx_size);
-error_read:
-error_too_small:
-error_rx_get_size:
-error_timedout:
-	sdio_release_host(func);
-	d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %ld\n",
-		i2400m, ack, ack_size, (long) rx_size);
-	return rx_size;
+	i2400ms->bm_ack_size = -EINPROGRESS;
+	spin_unlock(&i2400m->rx_lock);
+
+error_timeout:
+	d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n",
+		i2400m, ack, ack_size, result);
+	return result;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/sdio-rx.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/sdio-rx.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/sdio-rx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/sdio-rx.c	2009-09-09 18:13:59.000000000 -0400
@@ -69,6 +69,13 @@
 #define D_SUBMODULE rx
 #include "sdio-debug-levels.h"
 
+static const __le32 i2400m_ACK_BARKER[4] = {
+	__constant_cpu_to_le32(I2400M_ACK_BARKER),
+	__constant_cpu_to_le32(I2400M_ACK_BARKER),
+	__constant_cpu_to_le32(I2400M_ACK_BARKER),
+	__constant_cpu_to_le32(I2400M_ACK_BARKER)
+};
+
 
 /*
  * Read and return the amount of bytes available for RX
@@ -131,25 +138,35 @@
 		ret = rx_size;
 		goto error_get_size;
 	}
+
 	ret = -ENOMEM;
 	skb = alloc_skb(rx_size, GFP_ATOMIC);
 	if (NULL == skb) {
 		dev_err(dev, "RX: unable to alloc skb\n");
 		goto error_alloc_skb;
 	}
-
 	ret = sdio_memcpy_fromio(func, skb->data,
 				 I2400MS_DATA_ADDR, rx_size);
 	if (ret < 0) {
 		dev_err(dev, "RX: SDIO data read failed: %d\n", ret);
 		goto error_memcpy_fromio;
 	}
-	/* Check if device has reset */
-	if (!memcmp(skb->data, i2400m_NBOOT_BARKER,
-		    sizeof(i2400m_NBOOT_BARKER))
-	    || !memcmp(skb->data, i2400m_SBOOT_BARKER,
-		       sizeof(i2400m_SBOOT_BARKER))) {
+
+	rmb();	/* make sure we get boot_mode from dev_reset_handle */
+	if (i2400m->boot_mode == 1) {
+		spin_lock(&i2400m->rx_lock);
+		i2400ms->bm_ack_size = rx_size;
+		spin_unlock(&i2400m->rx_lock);
+		memcpy(i2400m->bm_ack_buf, skb->data, rx_size);
+		wake_up(&i2400ms->bm_wfa_wq);
+		dev_err(dev, "RX: SDIO boot mode message\n");
+		kfree_skb(skb);
+	} else if (unlikely(!memcmp(skb->data, i2400m_NBOOT_BARKER,
+				    sizeof(i2400m_NBOOT_BARKER))
+			    || !memcmp(skb->data, i2400m_SBOOT_BARKER,
+				       sizeof(i2400m_SBOOT_BARKER)))) {
 		ret = i2400m_dev_reset_handle(i2400m);
+		dev_err(dev, "RX: SDIO reboot barker\n");
 		kfree_skb(skb);
 	} else {
 		skb_put(skb, rx_size);
@@ -179,7 +196,6 @@
 {
 	int ret;
 	struct i2400ms *i2400ms = sdio_get_drvdata(func);
-	struct i2400m *i2400m = &i2400ms->i2400m;
 	struct device *dev = &func->dev;
 	int val;
 
@@ -194,10 +210,7 @@
 		goto error_no_irq;
 	}
 	sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
-	if (WARN_ON(i2400m->boot_mode != 0))
-		dev_err(dev, "RX: SW BUG? boot mode and IRQ is up?\n");
-	else
-		i2400ms_rx(i2400ms);
+	i2400ms_rx(i2400ms);
 error_no_irq:
 	d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
 	return;
@@ -214,8 +227,15 @@
 	int result;
 	struct sdio_func *func = i2400ms->func;
 	struct device *dev = &func->dev;
+	struct i2400m *i2400m = &i2400ms->i2400m;
 
 	d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
+
+	init_waitqueue_head(&i2400ms->bm_wfa_wq);
+	spin_lock(&i2400m->rx_lock);
+	i2400ms->bm_wait_result = -EINPROGRESS;
+	spin_unlock(&i2400m->rx_lock);
+
 	sdio_claim_host(func);
 	result = sdio_claim_irq(func, i2400ms_irq);
 	if (result < 0) {
@@ -245,8 +265,13 @@
 	int result;
 	struct sdio_func *func = i2400ms->func;
 	struct device *dev = &func->dev;
+	struct i2400m *i2400m = &i2400ms->i2400m;
 
 	d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
+	spin_lock(&i2400m->rx_lock);
+	i2400ms->bm_ack_size = -EINTR;
+	spin_unlock(&i2400m->rx_lock);
+	wake_up_all(&i2400ms->bm_wfa_wq);
 	sdio_claim_host(func);
 	sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result);
 	sdio_release_irq(func);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/tx.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/tx.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/tx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -278,6 +278,48 @@
 #define TAIL_FULL ((void *)~(unsigned long)NULL)
 
 /*
+ * Calculate how much tail room is available
+ *
+ * Note the trick here. This path is ONLY caleed for Case A (see
+ * i2400m_tx_fifo_push() below), where we have:
+ *
+ *       Case A
+ * N  ___________
+ *   | tail room |
+ *   |           |
+ *   |<-  IN   ->|
+ *   |           |
+ *   |   data    |
+ *   |           |
+ *   |<-  OUT  ->|
+ *   |           |
+ *   | head room |
+ * 0  -----------
+ *
+ * When calculating the tail_room, tx_in might get to be zero if
+ * i2400m->tx_in is right at the end of the buffer (really full
+ * buffer) if there is no head room. In this case, tail_room would be
+ * I2400M_TX_BUF_SIZE, although it is actually zero. Hence the final
+ * mod (%) operation. However, when doing this kind of optimization,
+ * i2400m->tx_in being zero would fail, so we treat is an a special
+ * case.
+ */
+static inline
+size_t __i2400m_tx_tail_room(struct i2400m *i2400m)
+{
+	size_t tail_room;
+	size_t tx_in;
+
+	if (unlikely(i2400m->tx_in) == 0)
+		return I2400M_TX_BUF_SIZE;
+	tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE;
+	tail_room = I2400M_TX_BUF_SIZE - tx_in;
+	tail_room %= I2400M_TX_BUF_SIZE;
+	return tail_room;
+}
+
+
+/*
  * Allocate @size bytes in the TX fifo, return a pointer to it
  *
  * @i2400m: device descriptor
@@ -338,7 +380,7 @@
 		return NULL;
 	}
 	/* Is there space at the tail? */
-	tail_room = I2400M_TX_BUF_SIZE - i2400m->tx_in % I2400M_TX_BUF_SIZE;
+	tail_room = __i2400m_tx_tail_room(i2400m);
 	if (tail_room < needed_size) {
 		if (i2400m->tx_out % I2400M_TX_BUF_SIZE
 		    < i2400m->tx_in % I2400M_TX_BUF_SIZE) {
@@ -367,17 +409,29 @@
  * (I2400M_PL_PAD for the payloads, I2400M_TX_PLD_SIZE for the
  * header).
  *
+ * Tail room can get to be zero if a message was opened when there was
+ * space only for a header. _tx_close() will mark it as to-skip (as it
+ * will have no payloads) and there will be no more space to flush, so
+ * nothing has to be done here. This is probably cheaper than ensuring
+ * in _tx_new() that there is some space for payloads...as we could
+ * always possibly hit the same problem if the payload wouldn't fit.
+ *
  * Note:
  *
  *     Assumes i2400m->tx_lock is taken, and we use that as a barrier
+ *
+ *     This path is only taken for Case A FIFO situations [see
+ *     i2400m_tx_fifo_push()]
  */
 static
 void i2400m_tx_skip_tail(struct i2400m *i2400m)
 {
 	struct device *dev = i2400m_dev(i2400m);
 	size_t tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE;
-	size_t tail_room = I2400M_TX_BUF_SIZE - tx_in;
+	size_t tail_room = __i2400m_tx_tail_room(i2400m);
 	struct i2400m_msg_hdr *msg = i2400m->tx_buf + tx_in;
+	if (unlikely(tail_room == 0))
+		return;
 	BUG_ON(tail_room < sizeof(*msg));
 	msg->size = tail_room | I2400M_TX_SKIP;
 	d_printf(2, dev, "skip tail: skipping %zu bytes @%zu\n",
@@ -474,10 +528,18 @@
 	struct i2400m_msg_hdr *tx_msg_moved;
 	size_t aligned_size, padding, hdr_size;
 	void *pad_buf;
+	unsigned num_pls;
 
 	if (tx_msg->size & I2400M_TX_SKIP)	/* a skipper? nothing to do */
 		goto out;
-
+	num_pls = le16_to_cpu(tx_msg->num_pls);
+	/* We can get this situation when a new message was started
+	 * and there was no space to add payloads before hitting the
+	 tail (and taking padding into consideration). */
+	if (num_pls == 0) {
+		tx_msg->size |= I2400M_TX_SKIP;
+		goto out;
+	}
 	/* Relocate the message header
 	 *
 	 * Find the current header size, align it to 16 and if we need
@@ -491,7 +553,7 @@
 	 */
 	hdr_size = sizeof(*tx_msg)
 		+ le16_to_cpu(tx_msg->num_pls) * sizeof(tx_msg->pld[0]);
-	hdr_size = ALIGN(hdr_size, I2400M_PL_PAD);
+	hdr_size = ALIGN(hdr_size, I2400M_PL_ALIGN);
 	tx_msg->offset = I2400M_TX_PLD_SIZE - hdr_size;
 	tx_msg_moved = (void *) tx_msg + tx_msg->offset;
 	memmove(tx_msg_moved, tx_msg, hdr_size);
@@ -574,7 +636,7 @@
 
 	d_fnstart(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u)\n",
 		  i2400m, buf, buf_len, pl_type);
-	padded_len = ALIGN(buf_len, I2400M_PL_PAD);
+	padded_len = ALIGN(buf_len, I2400M_PL_ALIGN);
 	d_printf(5, dev, "padded_len %zd buf_len %zd\n", padded_len, buf_len);
 	/* If there is no current TX message, create one; if the
 	 * current one is out of payload slots or we have a singleton,
@@ -591,6 +653,8 @@
 		i2400m_tx_close(i2400m);
 		i2400m_tx_new(i2400m);
 	}
+	if (i2400m->tx_msg == NULL)
+		goto error_tx_new;
 	if (i2400m->tx_msg->size + padded_len > I2400M_TX_BUF_SIZE / 2) {
 		d_printf(2, dev, "TX: message too big, going new\n");
 		i2400m_tx_close(i2400m);
@@ -773,7 +837,6 @@
 	n = i2400m->tx_out / I2400M_TX_BUF_SIZE;
 	i2400m->tx_out %= I2400M_TX_BUF_SIZE;
 	i2400m->tx_in -= n * I2400M_TX_BUF_SIZE;
-	netif_start_queue(i2400m->wimax_dev.net_dev);
 	spin_unlock_irqrestore(&i2400m->tx_lock, flags);
 	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/usb.c linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wimax/i2400m/usb.c	2012-03-22 19:19:56.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wimax/i2400m/usb.c	2012-03-22 20:14:58.000000000 -0400
@@ -254,8 +254,10 @@
 			dev_err(dev, "USB reset failed (%d), giving up!\n",
 				result);
 		}
-	} else
+	} else {
+		result = -EINVAL;	/* shut gcc up in certain arches */
 		BUG();
+	}
 	if (result < 0
 	    && result != -EINVAL	/* device is gone */
 	    && rt != I2400M_RT_BUS) {
@@ -399,6 +401,7 @@
 	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
 	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
 	i2400m->bus_reset = i2400mu_bus_reset;
+	i2400m->bus_bm_retries = I2400M_BOOT_RETRIES;
 	i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
 	i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
 	i2400m->bus_fw_names = i2400mu_bus_fw_names;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/adm8211.c linux-libre-2.6.31-gnu/drivers/net/wireless/adm8211.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/adm8211.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/adm8211.c	2009-09-09 18:13:59.000000000 -0400
@@ -1311,18 +1311,20 @@
 	return 0;
 }
 
-static int adm8211_config_interface(struct ieee80211_hw *dev,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_if_conf *conf)
+static void adm8211_bss_info_changed(struct ieee80211_hw *dev,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *conf,
+				     u32 changes)
 {
 	struct adm8211_priv *priv = dev->priv;
 
+	if (!(changes & BSS_CHANGED_BSSID))
+		return;
+
 	if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
 		adm8211_set_bssid(dev, conf->bssid);
 		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
 	}
-
-	return 0;
 }
 
 static void adm8211_configure_filter(struct ieee80211_hw *dev,
@@ -1753,7 +1755,7 @@
 	.add_interface		= adm8211_add_interface,
 	.remove_interface	= adm8211_remove_interface,
 	.config			= adm8211_config,
-	.config_interface	= adm8211_config_interface,
+	.bss_info_changed	= adm8211_bss_info_changed,
 	.configure_filter	= adm8211_configure_filter,
 	.get_stats		= adm8211_get_stats,
 	.get_tx_stats		= adm8211_get_tx_stats,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/airo.c linux-libre-2.6.31-gnu/drivers/net/wireless/airo.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/airo.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/airo.c	2009-09-09 18:13:59.000000000 -0400
@@ -1935,7 +1935,7 @@
 		netif_stop_queue (dev);
 		if (npacks > MAXTXQ) {
 			dev->stats.tx_fifo_errors++;
-			return 1;
+			return NETDEV_TX_BUSY;
 		}
 		skb_queue_tail (&ai->txq, skb);
 		return 0;
@@ -2139,7 +2139,7 @@
 
 		if (i == MAX_FIDS / 2) {
 			dev->stats.tx_fifo_errors++;
-			return 1;
+			return NETDEV_TX_BUSY;
 		}
 	}
 	/* check min length*/
@@ -2193,7 +2193,8 @@
 	if (test_bit(FLAG_MPI, &priv->flags)) {
 		/* Not implemented yet for MPI350 */
 		netif_stop_queue(dev);
-		return -ENETDOWN;
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
 	}
 
 	if ( skb == NULL ) {
@@ -2210,7 +2211,7 @@
 
 		if (i == MAX_FIDS) {
 			dev->stats.tx_fifo_errors++;
-			return 1;
+			return NETDEV_TX_BUSY;
 		}
 	}
 	/* check min length*/
@@ -5917,20 +5918,19 @@
 	readSsidRid(local, &SSID_rid);
 
 	/* Check if we asked for `any' */
-	if(dwrq->flags == 0) {
+	if (dwrq->flags == 0) {
 		/* Just send an empty SSID list */
 		memset(&SSID_rid, 0, sizeof(SSID_rid));
 	} else {
-		int	index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+		unsigned index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
 		/* Check the size of the string */
-		if(dwrq->length > IW_ESSID_MAX_SIZE) {
+		if (dwrq->length > IW_ESSID_MAX_SIZE)
 			return -E2BIG ;
-		}
+
 		/* Check if index is valid */
-		if((index < 0) || (index >= 4)) {
+		if (index >= ARRAY_SIZE(SSID_rid.ssids))
 			return -EINVAL;
-		}
 
 		/* Set the SSID */
 		memset(SSID_rid.ssids[index].ssid, 0,
@@ -6818,7 +6818,7 @@
 		return -EINVAL;
 	}
 	clear_bit (FLAG_RADIO_OFF, &local->flags);
-	for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
+	for (i = 0; i < 8 && cap_rid.txPowerLevels[i]; i++)
 		if (v == cap_rid.txPowerLevels[i]) {
 			readConfigRid(local, 1);
 			local->config.txPower = v;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/ar9170.h linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/ar9170.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/ar9170.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/ar9170.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,209 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * Driver specific definitions
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef __AR9170_H
-#define __AR9170_H
-
-#include <linux/completion.h>
-#include <linux/spinlock.h>
-#include <net/wireless.h>
-#include <net/mac80211.h>
-#ifdef CONFIG_AR9170_LEDS
-#include <linux/leds.h>
-#endif /* CONFIG_AR9170_LEDS */
-#include "eeprom.h"
-#include "hw.h"
-
-#define PAYLOAD_MAX	(AR9170_MAX_CMD_LEN/4 - 1)
-
-enum ar9170_bw {
-	AR9170_BW_20,
-	AR9170_BW_40_BELOW,
-	AR9170_BW_40_ABOVE,
-
-	__AR9170_NUM_BW,
-};
-
-enum ar9170_rf_init_mode {
-	AR9170_RFI_NONE,
-	AR9170_RFI_WARM,
-	AR9170_RFI_COLD,
-};
-
-#define AR9170_MAX_RX_BUFFER_SIZE		8192
-
-#ifdef CONFIG_AR9170_LEDS
-struct ar9170;
-
-struct ar9170_led {
-	struct ar9170 *ar;
-	struct led_classdev l;
-	char name[32];
-	unsigned int toggled;
-	bool registered;
-};
-
-#endif /* CONFIG_AR9170_LEDS */
-
-enum ar9170_device_state {
-	AR9170_UNKNOWN_STATE,
-	AR9170_STOPPED,
-	AR9170_IDLE,
-	AR9170_STARTED,
-	AR9170_ASSOCIATED,
-};
-
-struct ar9170 {
-	struct ieee80211_hw *hw;
-	struct mutex mutex;
-	enum ar9170_device_state state;
-
-	int (*open)(struct ar9170 *);
-	void (*stop)(struct ar9170 *);
-	int (*tx)(struct ar9170 *, struct sk_buff *, bool, unsigned int);
-	int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 ,
-			void *, u32 , void *);
-	void (*callback_cmd)(struct ar9170 *, u32 , void *);
-
-	/* interface mode settings */
-	struct ieee80211_vif *vif;
-	u8 mac_addr[ETH_ALEN];
-	u8 bssid[ETH_ALEN];
-
-	/* beaconing */
-	struct sk_buff *beacon;
-	struct work_struct beacon_work;
-
-	/* cryptographic engine */
-	u64 usedkeys;
-	bool rx_software_decryption;
-	bool disable_offload;
-
-	/* filter settings */
-	struct work_struct filter_config_work;
-	u64 cur_mc_hash, want_mc_hash;
-	u32 cur_filter, want_filter;
-	unsigned int filter_changed;
-	bool sniffer_enabled;
-
-	/* PHY */
-	struct ieee80211_channel *channel;
-	int noise[4];
-
-	/* power calibration data */
-	u8 power_5G_leg[4];
-	u8 power_2G_cck[4];
-	u8 power_2G_ofdm[4];
-	u8 power_5G_ht20[8];
-	u8 power_5G_ht40[8];
-	u8 power_2G_ht20[8];
-	u8 power_2G_ht40[8];
-
-#ifdef CONFIG_AR9170_LEDS
-	struct delayed_work led_work;
-	struct ar9170_led leds[AR9170_NUM_LEDS];
-#endif /* CONFIG_AR9170_LEDS */
-
-	/* qos queue settings */
-	spinlock_t tx_stats_lock;
-	struct ieee80211_tx_queue_stats tx_stats[5];
-	struct ieee80211_tx_queue_params edcf[5];
-
-	spinlock_t cmdlock;
-	__le32 cmdbuf[PAYLOAD_MAX + 1];
-
-	/* MAC statistics */
-	struct ieee80211_low_level_stats stats;
-
-	/* EEPROM */
-	struct ar9170_eeprom eeprom;
-
-	/* global tx status for unregistered Stations. */
-	struct sk_buff_head global_tx_status;
-	struct sk_buff_head global_tx_status_waste;
-	struct delayed_work tx_status_janitor;
-};
-
-struct ar9170_sta_info {
-	struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
-};
-
-#define IS_STARTED(a)		(a->state >= AR9170_STARTED)
-#define IS_ACCEPTING_CMD(a)	(a->state >= AR9170_IDLE)
-
-#define AR9170_FILTER_CHANGED_PROMISC		BIT(0)
-#define AR9170_FILTER_CHANGED_MULTICAST		BIT(1)
-#define AR9170_FILTER_CHANGED_FRAMEFILTER	BIT(2)
-
-/* exported interface */
-void *ar9170_alloc(size_t priv_size);
-int ar9170_register(struct ar9170 *ar, struct device *pdev);
-void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb);
-void ar9170_unregister(struct ar9170 *ar);
-void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
-			     bool update_statistics, u16 tx_status);
-
-/* MAC */
-int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-int ar9170_init_mac(struct ar9170 *ar);
-int ar9170_set_qos(struct ar9170 *ar);
-int ar9170_update_multicast(struct ar9170 *ar);
-int ar9170_update_frame_filter(struct ar9170 *ar);
-int ar9170_set_operating_mode(struct ar9170 *ar);
-int ar9170_set_beacon_timers(struct ar9170 *ar);
-int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry);
-int ar9170_update_beacon(struct ar9170 *ar);
-void ar9170_new_beacon(struct work_struct *work);
-int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype,
-		      u8 keyidx, u8 *keydata, int keylen);
-int ar9170_disable_key(struct ar9170 *ar, u8 id);
-
-/* LEDs */
-#ifdef CONFIG_AR9170_LEDS
-int ar9170_register_leds(struct ar9170 *ar);
-void ar9170_unregister_leds(struct ar9170 *ar);
-#endif /* CONFIG_AR9170_LEDS */
-int ar9170_init_leds(struct ar9170 *ar);
-int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state);
-
-/* PHY / RF */
-int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band);
-int ar9170_init_rf(struct ar9170 *ar);
-int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
-		       enum ar9170_rf_init_mode rfi, enum ar9170_bw bw);
-
-#endif /* __AR9170_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/cmd.c linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/cmd.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/cmd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/cmd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,129 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * Basic HW register/memory/command access functions
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ar9170.h"
-#include "cmd.h"
-
-int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len)
-{
-	int err;
-
-	if (unlikely(!IS_ACCEPTING_CMD(ar)))
-		return 0;
-
-	err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL);
-	if (err)
-		printk(KERN_DEBUG "%s: writing memory failed\n",
-		       wiphy_name(ar->hw->wiphy));
-	return err;
-}
-
-int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
-{
-	__le32 buf[2] = {
-		cpu_to_le32(reg),
-		cpu_to_le32(val),
-	};
-	int err;
-
-	if (unlikely(!IS_ACCEPTING_CMD(ar)))
-		return 0;
-
-	err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf),
-			   (u8 *) buf, 0, NULL);
-	if (err)
-		printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n",
-		       wiphy_name(ar->hw->wiphy), reg, val);
-	return err;
-}
-
-static int ar9170_read_mreg(struct ar9170 *ar, int nregs,
-			    const u32 *regs, u32 *out)
-{
-	int i, err;
-	__le32 *offs, *res;
-
-	if (unlikely(!IS_ACCEPTING_CMD(ar)))
-		return 0;
-
-	/* abuse "out" for the register offsets, must be same length */
-	offs = (__le32 *)out;
-	for (i = 0; i < nregs; i++)
-		offs[i] = cpu_to_le32(regs[i]);
-
-	/* also use the same buffer for the input */
-	res = (__le32 *)out;
-
-	err = ar->exec_cmd(ar, AR9170_CMD_RREG,
-			   4 * nregs, (u8 *)offs,
-			   4 * nregs, (u8 *)res);
-	if (err)
-		return err;
-
-	/* convert result to cpu endian */
-	for (i = 0; i < nregs; i++)
-		out[i] = le32_to_cpu(res[i]);
-
-	return 0;
-}
-
-int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val)
-{
-	return ar9170_read_mreg(ar, 1, &reg, val);
-}
-
-int ar9170_echo_test(struct ar9170 *ar, u32 v)
-{
-	__le32 echobuf = cpu_to_le32(v);
-	__le32 echores;
-	int err;
-
-	if (unlikely(!IS_ACCEPTING_CMD(ar)))
-		return -ENODEV;
-
-	err = ar->exec_cmd(ar, AR9170_CMD_ECHO,
-			   4, (u8 *)&echobuf,
-			   4, (u8 *)&echores);
-	if (err)
-		return err;
-
-	if (echobuf != echores)
-		return -EINVAL;
-
-	return 0;
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/cmd.h linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/cmd.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/cmd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/cmd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * Basic HW register/memory/command access functions
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef __CMD_H
-#define __CMD_H
-
-#include "ar9170.h"
-
-/* basic HW access */
-int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len);
-int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
-int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val);
-int ar9170_echo_test(struct ar9170 *ar, u32 v);
-
-/*
- * Macros to facilitate writing multiple registers in a single
- * write-combining USB command. Note that when the first group
- * fails the whole thing will fail without any others attempted,
- * but you won't know which write in the group failed.
- */
-#define ar9170_regwrite_begin(ar)					\
-do {									\
-	int __nreg = 0, __err = 0;					\
-	struct ar9170 *__ar = ar;
-
-#define ar9170_regwrite(r, v) do {					\
-	__ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r);			\
-	__ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v);			\
-	__nreg++;							\
-	if ((__nreg >= PAYLOAD_MAX/2)) {				\
-		if (IS_ACCEPTING_CMD(__ar))				\
-			__err = ar->exec_cmd(__ar, AR9170_CMD_WREG,	\
-					     8 * __nreg,		\
-					     (u8 *) &__ar->cmdbuf[1],	\
-					     0, NULL);			\
-		__nreg = 0;						\
-		if (__err)						\
-			goto __regwrite_out;				\
-	}								\
-} while (0)
-
-#define ar9170_regwrite_finish()					\
-__regwrite_out :							\
-	if (__nreg) {							\
-		if (IS_ACCEPTING_CMD(__ar))				\
-			__err = ar->exec_cmd(__ar, AR9170_CMD_WREG,	\
-					     8 * __nreg, 		\
-					     (u8 *) &__ar->cmdbuf[1],	\
-					     0, NULL);			\
-		__nreg = 0;						\
-	}
-
-#define ar9170_regwrite_result()					\
-	__err;								\
-} while (0);
-
-#endif /* __CMD_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/eeprom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/eeprom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * EEPROM layout
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef __AR9170_EEPROM_H
-#define __AR9170_EEPROM_H
-
-#define AR5416_MAX_CHAINS		2
-#define AR5416_MODAL_SPURS		5
-
-struct ar9170_eeprom_modal {
-	__le32	antCtrlChain[AR5416_MAX_CHAINS];
-	__le32	antCtrlCommon;
-	s8	antennaGainCh[AR5416_MAX_CHAINS];
-	u8	switchSettling;
-	u8	txRxAttenCh[AR5416_MAX_CHAINS];
-	u8	rxTxMarginCh[AR5416_MAX_CHAINS];
-	s8	adcDesiredSize;
-	s8	pgaDesiredSize;
-	u8	xlnaGainCh[AR5416_MAX_CHAINS];
-	u8	txEndToXpaOff;
-	u8	txEndToRxOn;
-	u8	txFrameToXpaOn;
-	u8	thresh62;
-	s8	noiseFloorThreshCh[AR5416_MAX_CHAINS];
-	u8	xpdGain;
-	u8	xpd;
-	s8	iqCalICh[AR5416_MAX_CHAINS];
-	s8	iqCalQCh[AR5416_MAX_CHAINS];
-	u8	pdGainOverlap;
-	u8	ob;
-	u8	db;
-	u8	xpaBiasLvl;
-	u8	pwrDecreaseFor2Chain;
-	u8	pwrDecreaseFor3Chain;
-	u8	txFrameToDataStart;
-	u8	txFrameToPaOn;
-	u8	ht40PowerIncForPdadc;
-	u8	bswAtten[AR5416_MAX_CHAINS];
-	u8	bswMargin[AR5416_MAX_CHAINS];
-	u8	swSettleHt40;
-	u8	reserved[22];
-	struct spur_channel {
-		__le16 spurChan;
-		u8	spurRangeLow;
-		u8	spurRangeHigh;
-	} __packed spur_channels[AR5416_MODAL_SPURS];
-} __packed;
-
-#define AR5416_NUM_PD_GAINS		4
-#define AR5416_PD_GAIN_ICEPTS		5
-
-struct ar9170_calibration_data_per_freq {
-	u8	pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
-	u8	vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
-} __packed;
-
-#define AR5416_NUM_5G_CAL_PIERS		8
-#define AR5416_NUM_2G_CAL_PIERS		4
-
-#define AR5416_NUM_5G_TARGET_PWRS	8
-#define AR5416_NUM_2G_CCK_TARGET_PWRS	3
-#define AR5416_NUM_2G_OFDM_TARGET_PWRS	4
-#define AR5416_MAX_NUM_TGT_PWRS		8
-
-struct ar9170_calibration_target_power_legacy {
-	u8	freq;
-	u8	power[4];
-} __packed;
-
-struct ar9170_calibration_target_power_ht {
-	u8	freq;
-	u8	power[8];
-} __packed;
-
-#define AR5416_NUM_CTLS			24
-
-struct ar9170_calctl_edges {
-	u8	channel;
-#define AR9170_CALCTL_EDGE_FLAGS	0xC0
-	u8	power_flags;
-} __packed;
-
-#define AR5416_NUM_BAND_EDGES		8
-
-struct ar9170_calctl_data {
-	struct ar9170_calctl_edges
-		control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
-} __packed;
-
-
-struct ar9170_eeprom {
-	__le16	length;
-	__le16	checksum;
-	__le16	version;
-	u8	operating_flags;
-#define AR9170_OPFLAG_5GHZ 		1
-#define AR9170_OPFLAG_2GHZ 		2
-	u8	misc;
-	__le16	reg_domain[2];
-	u8	mac_address[6];
-	u8	rx_mask;
-	u8	tx_mask;
-	__le16	rf_silent;
-	__le16	bluetooth_options;
-	__le16	device_capabilities;
-	__le32	build_number;
-	u8	deviceType;
-	u8	reserved[33];
-
-	u8	customer_data[64];
-
-	struct ar9170_eeprom_modal
-		modal_header[2];
-
-	u8	cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS];
-	u8	cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS];
-
-	struct ar9170_calibration_data_per_freq
-		cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS],
-		cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
-
-	/* power calibration data */
-	struct ar9170_calibration_target_power_legacy
-		cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS];
-	struct ar9170_calibration_target_power_ht
-		cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS],
-		cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS];
-
-	struct ar9170_calibration_target_power_legacy
-		cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS],
-		cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS];
-	struct ar9170_calibration_target_power_ht
-		cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS],
-		cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS];
-
-	/* conformance testing limits */
-	u8	ctl_index[AR5416_NUM_CTLS];
-	struct ar9170_calctl_data
-		ctl_data[AR5416_NUM_CTLS];
-
-	u8	pad;
-	__le16	subsystem_id;
-} __packed;
-
-#endif /* __AR9170_EEPROM_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/hw.h linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/hw.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/hw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,417 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * Hardware-specific definitions
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef __AR9170_HW_H
-#define __AR9170_HW_H
-
-#define AR9170_MAX_CMD_LEN	64
-
-enum ar9170_cmd {
-	AR9170_CMD_RREG		= 0x00,
-	AR9170_CMD_WREG		= 0x01,
-	AR9170_CMD_RMEM		= 0x02,
-	AR9170_CMD_WMEM		= 0x03,
-	AR9170_CMD_BITAND	= 0x04,
-	AR9170_CMD_BITOR	= 0x05,
-	AR9170_CMD_EKEY		= 0x28,
-	AR9170_CMD_DKEY		= 0x29,
-	AR9170_CMD_FREQUENCY	= 0x30,
-	AR9170_CMD_RF_INIT	= 0x31,
-	AR9170_CMD_SYNTH	= 0x32,
-	AR9170_CMD_FREQ_START	= 0x33,
-	AR9170_CMD_ECHO		= 0x80,
-	AR9170_CMD_TALLY	= 0x81,
-	AR9170_CMD_TALLY_APD	= 0x82,
-	AR9170_CMD_CONFIG	= 0x83,
-	AR9170_CMD_RESET	= 0x90,
-	AR9170_CMD_DKRESET	= 0x91,
-	AR9170_CMD_DKTX_STATUS	= 0x92,
-	AR9170_CMD_FDC		= 0xA0,
-	AR9170_CMD_WREEPROM	= 0xB0,
-	AR9170_CMD_WFLASH	= 0xB0,
-	AR9170_CMD_FLASH_ERASE	= 0xB1,
-	AR9170_CMD_FLASH_PROG	= 0xB2,
-	AR9170_CMD_FLASH_CHKSUM	= 0xB3,
-	AR9170_CMD_FLASH_READ	= 0xB4,
-	AR9170_CMD_FW_DL_INIT	= 0xB5,
-	AR9170_CMD_MEM_WREEPROM	= 0xBB,
-};
-
-/* endpoints */
-#define AR9170_EP_TX				1
-#define AR9170_EP_RX				2
-#define AR9170_EP_IRQ				3
-#define AR9170_EP_CMD				4
-
-#define AR9170_EEPROM_START			0x1600
-
-#define AR9170_GPIO_REG_BASE			0x1d0100
-#define AR9170_GPIO_REG_PORT_TYPE		AR9170_GPIO_REG_BASE
-#define AR9170_GPIO_REG_DATA			(AR9170_GPIO_REG_BASE + 4)
-#define AR9170_NUM_LEDS				2
-
-
-#define AR9170_USB_REG_BASE			0x1e1000
-#define AR9170_USB_REG_DMA_CTL			(AR9170_USB_REG_BASE + 0x108)
-#define		AR9170_DMA_CTL_ENABLE_TO_DEVICE		0x1
-#define		AR9170_DMA_CTL_ENABLE_FROM_DEVICE	0x2
-#define		AR9170_DMA_CTL_HIGH_SPEED		0x4
-#define		AR9170_DMA_CTL_PACKET_MODE		0x8
-
-#define AR9170_USB_REG_MAX_AGG_UPLOAD		(AR9170_USB_REG_BASE + 0x110)
-#define AR9170_USB_REG_UPLOAD_TIME_CTL		(AR9170_USB_REG_BASE + 0x114)
-
-
-
-#define AR9170_MAC_REG_BASE			0x1c3000
-
-#define AR9170_MAC_REG_TSF_L			(AR9170_MAC_REG_BASE + 0x514)
-#define AR9170_MAC_REG_TSF_H			(AR9170_MAC_REG_BASE + 0x518)
-
-#define AR9170_MAC_REG_ATIM_WINDOW		(AR9170_MAC_REG_BASE + 0x51C)
-#define AR9170_MAC_REG_BCN_PERIOD		(AR9170_MAC_REG_BASE + 0x520)
-#define AR9170_MAC_REG_PRETBTT			(AR9170_MAC_REG_BASE + 0x524)
-
-#define AR9170_MAC_REG_MAC_ADDR_L		(AR9170_MAC_REG_BASE + 0x610)
-#define AR9170_MAC_REG_MAC_ADDR_H		(AR9170_MAC_REG_BASE + 0x614)
-#define AR9170_MAC_REG_BSSID_L			(AR9170_MAC_REG_BASE + 0x618)
-#define AR9170_MAC_REG_BSSID_H			(AR9170_MAC_REG_BASE + 0x61c)
-
-#define AR9170_MAC_REG_GROUP_HASH_TBL_L		(AR9170_MAC_REG_BASE + 0x624)
-#define AR9170_MAC_REG_GROUP_HASH_TBL_H		(AR9170_MAC_REG_BASE + 0x628)
-
-#define AR9170_MAC_REG_RX_TIMEOUT		(AR9170_MAC_REG_BASE + 0x62C)
-
-#define AR9170_MAC_REG_BASIC_RATE		(AR9170_MAC_REG_BASE + 0x630)
-#define AR9170_MAC_REG_MANDATORY_RATE		(AR9170_MAC_REG_BASE + 0x634)
-#define AR9170_MAC_REG_RTS_CTS_RATE		(AR9170_MAC_REG_BASE + 0x638)
-#define AR9170_MAC_REG_BACKOFF_PROTECT		(AR9170_MAC_REG_BASE + 0x63c)
-#define AR9170_MAC_REG_RX_THRESHOLD		(AR9170_MAC_REG_BASE + 0x640)
-#define AR9170_MAC_REG_RX_PE_DELAY		(AR9170_MAC_REG_BASE + 0x64C)
-
-#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK		(AR9170_MAC_REG_BASE + 0x658)
-#define AR9170_MAC_REG_SNIFFER			(AR9170_MAC_REG_BASE + 0x674)
-#define		AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC	BIT(0)
-#define		AR9170_MAC_REG_SNIFFER_DEFAULTS		0x02000000
-#define AR9170_MAC_REG_ENCRYPTION		(AR9170_MAC_REG_BASE + 0x678)
-#define		AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE	BIT(3)
-#define		AR9170_MAC_REG_ENCRYPTION_DEFAULTS	0x70
-
-#define AR9170_MAC_REG_MISC_680			(AR9170_MAC_REG_BASE + 0x680)
-#define AR9170_MAC_REG_TX_UNDERRUN		(AR9170_MAC_REG_BASE + 0x688)
-
-#define AR9170_MAC_REG_FRAMETYPE_FILTER		(AR9170_MAC_REG_BASE + 0x68c)
-#define		AR9170_MAC_REG_FTF_ASSOC_REQ		BIT(0)
-#define		AR9170_MAC_REG_FTF_ASSOC_RESP		BIT(1)
-#define		AR9170_MAC_REG_FTF_REASSOC_REQ		BIT(2)
-#define		AR9170_MAC_REG_FTF_REASSOC_RESP		BIT(3)
-#define		AR9170_MAC_REG_FTF_PRB_REQ		BIT(4)
-#define		AR9170_MAC_REG_FTF_PRB_RESP		BIT(5)
-#define		AR9170_MAC_REG_FTF_BIT6			BIT(6)
-#define		AR9170_MAC_REG_FTF_BIT7			BIT(7)
-#define		AR9170_MAC_REG_FTF_BEACON		BIT(8)
-#define		AR9170_MAC_REG_FTF_ATIM			BIT(9)
-#define		AR9170_MAC_REG_FTF_DEASSOC		BIT(10)
-#define		AR9170_MAC_REG_FTF_AUTH			BIT(11)
-#define		AR9170_MAC_REG_FTF_DEAUTH		BIT(12)
-#define		AR9170_MAC_REG_FTF_BIT13		BIT(13)
-#define		AR9170_MAC_REG_FTF_BIT14		BIT(14)
-#define		AR9170_MAC_REG_FTF_BIT15		BIT(15)
-#define		AR9170_MAC_REG_FTF_BAR			BIT(24)
-#define		AR9170_MAC_REG_FTF_BIT25		BIT(25)
-#define		AR9170_MAC_REG_FTF_PSPOLL		BIT(26)
-#define		AR9170_MAC_REG_FTF_RTS			BIT(27)
-#define		AR9170_MAC_REG_FTF_CTS			BIT(28)
-#define		AR9170_MAC_REG_FTF_ACK			BIT(29)
-#define		AR9170_MAC_REG_FTF_CFE			BIT(30)
-#define		AR9170_MAC_REG_FTF_CFE_ACK		BIT(31)
-#define		AR9170_MAC_REG_FTF_DEFAULTS		0x0500ffff
-#define		AR9170_MAC_REG_FTF_MONITOR		0xfd00ffff
-
-#define AR9170_MAC_REG_RX_TOTAL			(AR9170_MAC_REG_BASE + 0x6A0)
-#define AR9170_MAC_REG_RX_CRC32			(AR9170_MAC_REG_BASE + 0x6A4)
-#define AR9170_MAC_REG_RX_CRC16			(AR9170_MAC_REG_BASE + 0x6A8)
-#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI	(AR9170_MAC_REG_BASE + 0x6AC)
-#define AR9170_MAC_REG_RX_OVERRUN		(AR9170_MAC_REG_BASE + 0x6B0)
-#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL	(AR9170_MAC_REG_BASE + 0x6BC)
-#define AR9170_MAC_REG_TX_RETRY			(AR9170_MAC_REG_BASE + 0x6CC)
-#define AR9170_MAC_REG_TX_TOTAL			(AR9170_MAC_REG_BASE + 0x6F4)
-
-
-#define AR9170_MAC_REG_ACK_EXTENSION		(AR9170_MAC_REG_BASE + 0x690)
-#define AR9170_MAC_REG_EIFS_AND_SIFS		(AR9170_MAC_REG_BASE + 0x698)
-
-#define AR9170_MAC_REG_SLOT_TIME		(AR9170_MAC_REG_BASE + 0x6F0)
-
-#define AR9170_MAC_REG_POWERMANAGEMENT		(AR9170_MAC_REG_BASE + 0x700)
-#define		AR9170_MAC_REG_POWERMGT_IBSS		0xe0
-#define		AR9170_MAC_REG_POWERMGT_AP		0xa1
-#define		AR9170_MAC_REG_POWERMGT_STA		0x2
-#define		AR9170_MAC_REG_POWERMGT_AP_WDS		0x3
-#define		AR9170_MAC_REG_POWERMGT_DEFAULTS	(0xf << 24)
-
-#define AR9170_MAC_REG_ROLL_CALL_TBL_L		(AR9170_MAC_REG_BASE + 0x704)
-#define AR9170_MAC_REG_ROLL_CALL_TBL_H		(AR9170_MAC_REG_BASE + 0x708)
-
-#define AR9170_MAC_REG_AC0_CW			(AR9170_MAC_REG_BASE + 0xB00)
-#define AR9170_MAC_REG_AC1_CW			(AR9170_MAC_REG_BASE + 0xB04)
-#define AR9170_MAC_REG_AC2_CW			(AR9170_MAC_REG_BASE + 0xB08)
-#define AR9170_MAC_REG_AC3_CW			(AR9170_MAC_REG_BASE + 0xB0C)
-#define AR9170_MAC_REG_AC4_CW			(AR9170_MAC_REG_BASE + 0xB10)
-#define AR9170_MAC_REG_AC1_AC0_AIFS		(AR9170_MAC_REG_BASE + 0xB14)
-#define AR9170_MAC_REG_AC3_AC2_AIFS		(AR9170_MAC_REG_BASE + 0xB18)
-
-#define AR9170_MAC_REG_RETRY_MAX		(AR9170_MAC_REG_BASE + 0xB28)
-
-#define AR9170_MAC_REG_FCS_SELECT		(AR9170_MAC_REG_BASE + 0xBB0)
-#define		AR9170_MAC_FCS_SWFCS		0x1
-#define		AR9170_MAC_FCS_FIFO_PROT	0x4
-
-
-#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND	(AR9170_MAC_REG_BASE + 0xB30)
-
-#define AR9170_MAC_REG_AC1_AC0_TXOP		(AR9170_MAC_REG_BASE + 0xB44)
-#define AR9170_MAC_REG_AC3_AC2_TXOP		(AR9170_MAC_REG_BASE + 0xB48)
-
-#define AR9170_MAC_REG_ACK_TABLE		(AR9170_MAC_REG_BASE + 0xC00)
-#define AR9170_MAC_REG_AMPDU_RX_THRESH		(AR9170_MAC_REG_BASE + 0xC50)
-
-#define AR9170_MAC_REG_TXRX_MPI			(AR9170_MAC_REG_BASE + 0xD7C)
-#define		AR9170_MAC_TXRX_MPI_TX_MPI_MASK	0x0000000f
-#define		AR9170_MAC_TXRX_MPI_TX_TO_MASK	0x0000fff0
-#define		AR9170_MAC_TXRX_MPI_RX_MPI_MASK	0x000f0000
-#define		AR9170_MAC_TXRX_MPI_RX_TO_MASK	0xfff00000
-
-#define AR9170_MAC_REG_BCN_ADDR			(AR9170_MAC_REG_BASE + 0xD84)
-#define AR9170_MAC_REG_BCN_LENGTH		(AR9170_MAC_REG_BASE + 0xD88)
-#define AR9170_MAC_REG_BCN_PLCP			(AR9170_MAC_REG_BASE + 0xD90)
-#define AR9170_MAC_REG_BCN_CTRL			(AR9170_MAC_REG_BASE + 0xD94)
-#define AR9170_MAC_REG_BCN_HT1			(AR9170_MAC_REG_BASE + 0xDA0)
-#define AR9170_MAC_REG_BCN_HT2			(AR9170_MAC_REG_BASE + 0xDA4)
-
-
-#define AR9170_PWR_REG_BASE			0x1D4000
-
-#define AR9170_PWR_REG_CLOCK_SEL		(AR9170_PWR_REG_BASE + 0x008)
-#define		AR9170_PWR_CLK_AHB_40MHZ	0
-#define		AR9170_PWR_CLK_AHB_20_22MHZ	1
-#define		AR9170_PWR_CLK_AHB_40_44MHZ	2
-#define		AR9170_PWR_CLK_AHB_80_88MHZ	3
-#define		AR9170_PWR_CLK_DAC_160_INV_DLY	0x70
-
-
-/* put beacon here in memory */
-#define AR9170_BEACON_BUFFER_ADDRESS		0x117900
-
-
-struct ar9170_tx_control {
-	__le16 length;
-	__le16 mac_control;
-	__le32 phy_control;
-	u8 frame_data[0];
-} __packed;
-
-/* these are either-or */
-#define AR9170_TX_MAC_PROT_RTS			0x0001
-#define AR9170_TX_MAC_PROT_CTS			0x0002
-
-#define AR9170_TX_MAC_NO_ACK			0x0004
-/* if unset, MAC will only do SIFS space before frame */
-#define AR9170_TX_MAC_BACKOFF			0x0008
-#define AR9170_TX_MAC_BURST			0x0010
-#define AR9170_TX_MAC_AGGR			0x0020
-
-/* encryption is a two-bit field */
-#define AR9170_TX_MAC_ENCR_NONE			0x0000
-#define AR9170_TX_MAC_ENCR_RC4			0x0040
-#define AR9170_TX_MAC_ENCR_CENC			0x0080
-#define AR9170_TX_MAC_ENCR_AES			0x00c0
-
-#define AR9170_TX_MAC_MMIC			0x0100
-#define AR9170_TX_MAC_HW_DURATION		0x0200
-#define AR9170_TX_MAC_QOS_SHIFT			10
-#define AR9170_TX_MAC_QOS_MASK			(3 << AR9170_TX_MAC_QOS_SHIFT)
-#define AR9170_TX_MAC_AGGR_QOS_BIT1		0x0400
-#define AR9170_TX_MAC_AGGR_QOS_BIT2		0x0800
-#define AR9170_TX_MAC_DISABLE_TXOP		0x1000
-#define AR9170_TX_MAC_TXOP_RIFS			0x2000
-#define AR9170_TX_MAC_IMM_AMPDU			0x4000
-#define AR9170_TX_MAC_RATE_PROBE		0x8000
-
-/* either-or */
-#define AR9170_TX_PHY_MOD_CCK			0x00000000
-#define AR9170_TX_PHY_MOD_OFDM			0x00000001
-#define AR9170_TX_PHY_MOD_HT			0x00000002
-
-/* depends on modulation */
-#define AR9170_TX_PHY_SHORT_PREAMBLE		0x00000004
-#define AR9170_TX_PHY_GREENFIELD		0x00000004
-
-#define AR9170_TX_PHY_BW_SHIFT			3
-#define AR9170_TX_PHY_BW_MASK			(3 << AR9170_TX_PHY_BW_SHIFT)
-#define AR9170_TX_PHY_BW_20MHZ			0
-#define AR9170_TX_PHY_BW_40MHZ			2
-#define AR9170_TX_PHY_BW_40MHZ_DUP		3
-
-#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT	6
-#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK	(7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT)
-
-#define AR9170_TX_PHY_TX_PWR_SHIFT		9
-#define AR9170_TX_PHY_TX_PWR_MASK		(0x3f << AR9170_TX_PHY_TX_PWR_SHIFT)
-
-/* not part of the hw-spec */
-#define AR9170_TX_PHY_QOS_SHIFT			25
-#define AR9170_TX_PHY_QOS_MASK			(3 << AR9170_TX_PHY_QOS_SHIFT)
-
-#define AR9170_TX_PHY_TXCHAIN_SHIFT		15
-#define AR9170_TX_PHY_TXCHAIN_MASK		(7 << AR9170_TX_PHY_TXCHAIN_SHIFT)
-#define AR9170_TX_PHY_TXCHAIN_1			1
-/* use for cck, ofdm 6/9/12/18/24 and HT if capable */
-#define AR9170_TX_PHY_TXCHAIN_2			5
-
-#define AR9170_TX_PHY_MCS_SHIFT			18
-#define AR9170_TX_PHY_MCS_MASK			(0x7f << AR9170_TX_PHY_MCS_SHIFT)
-
-#define AR9170_TX_PHY_SHORT_GI			0x80000000
-
-struct ar9170_rx_head {
-	u8 plcp[12];
-} __packed;
-
-struct ar9170_rx_tail {
-	union {
-		struct {
-			u8 rssi_ant0, rssi_ant1, rssi_ant2,
-			   rssi_ant0x, rssi_ant1x, rssi_ant2x,
-			   rssi_combined;
-		} __packed;
-		u8 rssi[7];
-	} __packed;
-
-	u8 evm_stream0[6], evm_stream1[6];
-	u8 phy_err;
-	u8 SAidx, DAidx;
-	u8 error;
-	u8 status;
-} __packed;
-
-#define AR9170_ENC_ALG_NONE			0x0
-#define AR9170_ENC_ALG_WEP64			0x1
-#define AR9170_ENC_ALG_TKIP			0x2
-#define AR9170_ENC_ALG_AESCCMP			0x4
-#define AR9170_ENC_ALG_WEP128			0x5
-#define AR9170_ENC_ALG_WEP256			0x6
-#define AR9170_ENC_ALG_CENC			0x7
-
-#define AR9170_RX_ENC_SOFTWARE			0x8
-
-static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t)
-{
-	return (t->SAidx & 0xc0) >> 4 |
-	       (t->DAidx & 0xc0) >> 6;
-}
-
-#define AR9170_RX_STATUS_MODULATION_MASK	0x03
-#define AR9170_RX_STATUS_MODULATION_CCK		0x00
-#define AR9170_RX_STATUS_MODULATION_OFDM	0x01
-#define AR9170_RX_STATUS_MODULATION_HT		0x02
-#define AR9170_RX_STATUS_MODULATION_DUPOFDM	0x03
-
-/* depends on modulation */
-#define AR9170_RX_STATUS_SHORT_PREAMBLE		0x08
-#define AR9170_RX_STATUS_GREENFIELD		0x08
-
-#define AR9170_RX_STATUS_MPDU_MASK		0x30
-#define AR9170_RX_STATUS_MPDU_SINGLE		0x00
-#define AR9170_RX_STATUS_MPDU_FIRST		0x10
-#define AR9170_RX_STATUS_MPDU_MIDDLE		0x20
-#define AR9170_RX_STATUS_MPDU_LAST		0x30
-
-
-#define AR9170_RX_ERROR_RXTO			0x01
-#define AR9170_RX_ERROR_OVERRUN			0x02
-#define AR9170_RX_ERROR_DECRYPT			0x04
-#define AR9170_RX_ERROR_FCS			0x08
-#define AR9170_RX_ERROR_WRONG_RA		0x10
-#define AR9170_RX_ERROR_PLCP			0x20
-#define AR9170_RX_ERROR_MMIC			0x40
-
-struct ar9170_cmd_tx_status {
-	__le16 unkn;
-	u8 dst[ETH_ALEN];
-	__le32 rate;
-	__le16 status;
-} __packed;
-
-#define AR9170_TX_STATUS_COMPLETE		0x00
-#define AR9170_TX_STATUS_RETRY			0x01
-#define AR9170_TX_STATUS_FAILED			0x02
-
-struct ar9170_cmd_ba_failed_count {
-	__le16 failed;
-	__le16 rate;
-} __packed;
-
-struct ar9170_cmd_response {
-	u8 flag;
-	u8 type;
-
-	union {
-		struct ar9170_cmd_tx_status		tx_status;
-		struct ar9170_cmd_ba_failed_count	ba_fail_cnt;
-		u8 data[0];
-	};
-} __packed;
-
-/* QoS */
-
-/* mac80211 queue to HW/FW map */
-static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 };
-
-/* HW/FW queue to mac80211 map */
-static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 };
-
-enum ar9170_txq {
-	AR9170_TXQ_BE,
-	AR9170_TXQ_BK,
-	AR9170_TXQ_VI,
-	AR9170_TXQ_VO,
-
-	__AR9170_NUM_TXQ,
-};
-
-#endif /* __AR9170_HW_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-config AR9170_USB
-	tristate "Atheros AR9170 802.11n USB support"
-	depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
-	select FW_LOADER
-	help
-	  This is a driver for the Atheros "otus" 802.11n USB devices.
-
-	  These devices require additional firmware (2 files).
-	  For now, these files can be downloaded from here:
-	  http://wireless.kernel.org/en/users/Drivers/ar9170
-
-	  If you choose to build a module, it'll be called ar9170usb.
-
-config AR9170_LEDS
-	bool
-	depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB)
-	default y
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/led.c linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/led.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/led.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/led.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,171 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * LED handling
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ar9170.h"
-#include "cmd.h"
-
-int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state)
-{
-	return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state);
-}
-
-int ar9170_init_leds(struct ar9170 *ar)
-{
-	int err;
-
-	/* disable LEDs */
-	/* GPIO [0/1 mode: output, 2/3: input] */
-	err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
-	if (err)
-		goto out;
-
-	/* GPIO 0/1 value: off */
-	err = ar9170_set_leds_state(ar, 0);
-
-out:
-	return err;
-}
-
-#ifdef CONFIG_AR9170_LEDS
-static void ar9170_update_leds(struct work_struct *work)
-{
-	struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
-	int i, tmp, blink_delay = 1000;
-	u32 led_val = 0;
-	bool rerun = false;
-
-	if (unlikely(!IS_ACCEPTING_CMD(ar)))
-		return ;
-
-	mutex_lock(&ar->mutex);
-	for (i = 0; i < AR9170_NUM_LEDS; i++)
-		if (ar->leds[i].toggled) {
-			led_val |= 1 << i;
-
-			tmp = 70 + 200 / (ar->leds[i].toggled);
-			if (tmp < blink_delay)
-				blink_delay = tmp;
-
-			if (ar->leds[i].toggled > 1)
-				ar->leds[i].toggled = 0;
-
-			rerun = true;
-		}
-
-	ar9170_set_leds_state(ar, led_val);
-	mutex_unlock(&ar->mutex);
-
-	if (rerun)
-		queue_delayed_work(ar->hw->workqueue, &ar->led_work,
-				   msecs_to_jiffies(blink_delay));
-}
-
-static void ar9170_led_brightness_set(struct led_classdev *led,
-				      enum led_brightness brightness)
-{
-	struct ar9170_led *arl = container_of(led, struct ar9170_led, l);
-	struct ar9170 *ar = arl->ar;
-
-	arl->toggled++;
-
-	if (likely(IS_ACCEPTING_CMD(ar) && brightness))
-		queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
-}
-
-static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
-			       char *trigger)
-{
-	int err;
-
-	snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
-		 "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
-
-	ar->leds[i].ar = ar;
-	ar->leds[i].l.name = ar->leds[i].name;
-	ar->leds[i].l.brightness_set = ar9170_led_brightness_set;
-	ar->leds[i].l.brightness = 0;
-	ar->leds[i].l.default_trigger = trigger;
-
-	err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
-				    &ar->leds[i].l);
-	if (err)
-		printk(KERN_ERR "%s: failed to register %s LED (%d).\n",
-		       wiphy_name(ar->hw->wiphy), ar->leds[i].name, err);
-	else
-		ar->leds[i].registered = true;
-
-	return err;
-}
-
-void ar9170_unregister_leds(struct ar9170 *ar)
-{
-	int i;
-
-	cancel_delayed_work_sync(&ar->led_work);
-
-	for (i = 0; i < AR9170_NUM_LEDS; i++)
-		if (ar->leds[i].registered) {
-			led_classdev_unregister(&ar->leds[i].l);
-			ar->leds[i].registered = false;
-		}
-}
-
-int ar9170_register_leds(struct ar9170 *ar)
-{
-	int err;
-
-	INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds);
-
-	err = ar9170_register_led(ar, 0, "tx",
-				  ieee80211_get_tx_led_name(ar->hw));
-	if (err)
-		goto fail;
-
-	err = ar9170_register_led(ar, 1, "assoc",
-				 ieee80211_get_assoc_led_name(ar->hw));
-	if (err)
-		goto fail;
-
-	return 0;
-
-fail:
-	ar9170_unregister_leds(ar);
-	return err;
-}
-
-#endif /* CONFIG_AR9170_LEDS */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/mac.c linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/mac.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/mac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/mac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,452 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * MAC programming
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include "ar9170.h"
-#include "cmd.h"
-
-int ar9170_set_qos(struct ar9170 *ar)
-{
-	ar9170_regwrite_begin(ar);
-
-	ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min |
-			(ar->edcf[0].cw_max << 16));
-	ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min |
-			(ar->edcf[1].cw_max << 16));
-	ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min |
-			(ar->edcf[2].cw_max << 16));
-	ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min |
-			(ar->edcf[3].cw_max << 16));
-	ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min |
-			(ar->edcf[4].cw_max << 16));
-
-	ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS,
-			((ar->edcf[0].aifs * 9 + 10)) |
-			((ar->edcf[1].aifs * 9 + 10) << 12) |
-			((ar->edcf[2].aifs * 9 + 10) << 24));
-	ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS,
-			((ar->edcf[2].aifs * 9 + 10) >> 8) |
-			((ar->edcf[3].aifs * 9 + 10) << 4) |
-			((ar->edcf[4].aifs * 9 + 10) << 16));
-
-	ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP,
-			ar->edcf[0].txop | ar->edcf[1].txop << 16);
-	ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP,
-			ar->edcf[1].txop | ar->edcf[3].txop << 16);
-
-	ar9170_regwrite_finish();
-
-	return ar9170_regwrite_result();
-}
-
-int ar9170_init_mac(struct ar9170 *ar)
-{
-	ar9170_regwrite_begin(ar);
-
-	ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40);
-
-	ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0);
-
-	/* enable MMIC */
-	ar9170_regwrite(AR9170_MAC_REG_SNIFFER,
-			AR9170_MAC_REG_SNIFFER_DEFAULTS);
-
-	ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80);
-
-	ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70);
-	ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000);
-	ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10);
-
-	/* CF-END mode */
-	ar9170_regwrite(0x1c3b2c, 0x19000000);
-
-	/* NAV protects ACK only (in TXOP) */
-	ar9170_regwrite(0x1c3b38, 0x201);
-
-	/* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */
-	/* OTUS set AM to 0x1 */
-	ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170);
-
-	ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
-
-	/* AGG test code*/
-	/* Aggregation MAX number and timeout */
-	ar9170_regwrite(0x1c3b9c, 0x10000a);
-
-	ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
-			AR9170_MAC_REG_FTF_DEFAULTS);
-
-	/* Enable deaggregator, response in sniffer mode */
-	ar9170_regwrite(0x1c3c40, 0x1 | 1<<30);
-
-	/* rate sets */
-	ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f);
-	ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f);
-	ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
-
-	/* MIMO response control */
-	ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28  otus-AM */
-
-	/* switch MAC to OTUS interface */
-	ar9170_regwrite(0x1c3600, 0x3);
-
-	ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff);
-
-	/* set PHY register read timeout (??) */
-	ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008);
-
-	/* Disable Rx TimeOut, workaround for BB. */
-	ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0);
-
-	/* Set CPU clock frequency to 88/80MHz */
-	ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL,
-			AR9170_PWR_CLK_AHB_80_88MHZ |
-			AR9170_PWR_CLK_DAC_160_INV_DLY);
-
-	/* Set WLAN DMA interrupt mode: generate int per packet */
-	ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011);
-
-	ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT,
-			AR9170_MAC_FCS_FIFO_PROT);
-
-	/* Disables the CF_END frame, undocumented register */
-	ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND,
-			0x141E0F48);
-
-	ar9170_regwrite_finish();
-
-	return ar9170_regwrite_result();
-}
-
-static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac)
-{
-	static const u8 zero[ETH_ALEN] = { 0 };
-
-	if (!mac)
-		mac = zero;
-
-	ar9170_regwrite_begin(ar);
-
-	ar9170_regwrite(reg,
-			(mac[3] << 24) | (mac[2] << 16) |
-			(mac[1] << 8) | mac[0]);
-
-	ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]);
-
-	ar9170_regwrite_finish();
-
-	return ar9170_regwrite_result();
-}
-
-int ar9170_update_multicast(struct ar9170 *ar)
-{
-	int err;
-
-	ar9170_regwrite_begin(ar);
-	ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H,
-		ar->want_mc_hash >> 32);
-	ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L,
-		ar->want_mc_hash);
-
-	ar9170_regwrite_finish();
-	err = ar9170_regwrite_result();
-
-	if (err)
-		return err;
-
-	ar->cur_mc_hash = ar->want_mc_hash;
-
-	return 0;
-}
-
-int ar9170_update_frame_filter(struct ar9170 *ar)
-{
-	int err;
-
-	err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER,
-			       ar->want_filter);
-
-	if (err)
-		return err;
-
-	ar->cur_filter = ar->want_filter;
-
-	return 0;
-}
-
-static int ar9170_set_promiscouous(struct ar9170 *ar)
-{
-	u32 encr_mode, sniffer;
-	int err;
-
-	err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer);
-	if (err)
-		return err;
-
-	err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode);
-	if (err)
-		return err;
-
-	if (ar->sniffer_enabled) {
-		sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC;
-
-		/*
-		 * Rx decryption works in place.
-		 *
-		 * If we don't disable it, the hardware will render all
-		 * encrypted frames which are encrypted with an unknown
-		 * key useless.
-		 */
-
-		encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
-		ar->sniffer_enabled = true;
-	} else {
-		sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC;
-
-		if (ar->rx_software_decryption)
-			encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
-		else
-			encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
-	}
-
-	ar9170_regwrite_begin(ar);
-	ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode);
-	ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer);
-	ar9170_regwrite_finish();
-
-	return ar9170_regwrite_result();
-}
-
-int ar9170_set_operating_mode(struct ar9170 *ar)
-{
-	u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS;
-	u8 *mac_addr, *bssid;
-	int err;
-
-	if (ar->vif) {
-		mac_addr = ar->mac_addr;
-		bssid = ar->bssid;
-
-		switch (ar->vif->type) {
-		case NL80211_IFTYPE_MESH_POINT:
-		case NL80211_IFTYPE_ADHOC:
-			pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS;
-			break;
-/*		case NL80211_IFTYPE_AP:
-			pm_mode |= AR9170_MAC_REG_POWERMGT_AP;
-			break;*/
-		case NL80211_IFTYPE_WDS:
-			pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS;
-			break;
-		case NL80211_IFTYPE_MONITOR:
-			ar->sniffer_enabled = true;
-			ar->rx_software_decryption = true;
-			break;
-		default:
-			pm_mode |= AR9170_MAC_REG_POWERMGT_STA;
-			break;
-		}
-	} else {
-		mac_addr = NULL;
-		bssid = NULL;
-	}
-
-	err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr);
-	if (err)
-		return err;
-
-	err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid);
-	if (err)
-		return err;
-
-	err = ar9170_set_promiscouous(ar);
-	if (err)
-		return err;
-
-	ar9170_regwrite_begin(ar);
-
-	ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode);
-	ar9170_regwrite_finish();
-
-	return ar9170_regwrite_result();
-}
-
-int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry)
-{
-	u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111);
-
-	return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp);
-}
-
-int ar9170_set_beacon_timers(struct ar9170 *ar)
-{
-	u32 v = 0;
-	u32 pretbtt = 0;
-
-	v |= ar->hw->conf.beacon_int;
-
-	if (ar->vif) {
-		switch (ar->vif->type) {
-		case NL80211_IFTYPE_MESH_POINT:
-		case NL80211_IFTYPE_ADHOC:
-			v |= BIT(25);
-			break;
-		case NL80211_IFTYPE_AP:
-			v |= BIT(24);
-			pretbtt = (ar->hw->conf.beacon_int - 6) << 16;
-			break;
-		default:
-			break;
-		}
-
-		v |= ar->vif->bss_conf.dtim_period << 16;
-	}
-
-	ar9170_regwrite_begin(ar);
-
-	ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
-	ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
-	ar9170_regwrite_finish();
-	return ar9170_regwrite_result();
-}
-
-int ar9170_update_beacon(struct ar9170 *ar)
-{
-	struct sk_buff *skb;
-	__le32 *data, *old = NULL;
-	u32 word;
-	int i;
-
-	skb = ieee80211_beacon_get(ar->hw, ar->vif);
-	if (!skb)
-		return -ENOMEM;
-
-	data = (__le32 *)skb->data;
-	if (ar->beacon)
-		old = (__le32 *)ar->beacon->data;
-
-	ar9170_regwrite_begin(ar);
-	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
-		/*
-		 * XXX: This accesses beyond skb data for up
-		 *	to the last 3 bytes!!
-		 */
-
-		if (old && (data[i] == old[i]))
-			continue;
-
-		word = le32_to_cpu(data[i]);
-		ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word);
-	}
-
-	/* XXX: use skb->cb info */
-	if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
-		ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
-				((skb->len + 4) << (3+16)) + 0x0400);
-	else
-		ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
-				((skb->len + 4) << (3+16)) + 0x0400);
-
-	ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4);
-	ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS);
-	ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1);
-
-	ar9170_regwrite_finish();
-
-	dev_kfree_skb(ar->beacon);
-	ar->beacon = skb;
-
-	return ar9170_regwrite_result();
-}
-
-void ar9170_new_beacon(struct work_struct *work)
-{
-	struct ar9170 *ar = container_of(work, struct ar9170,
-					 beacon_work);
-	struct sk_buff *skb;
-
-	if (unlikely(!IS_STARTED(ar)))
-		return ;
-
-	mutex_lock(&ar->mutex);
-
-	if (!ar->vif)
-		goto out;
-
-	ar9170_update_beacon(ar);
-
-	rcu_read_lock();
-	while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif)))
-		ar9170_op_tx(ar->hw, skb);
-
-	rcu_read_unlock();
-
- out:
-	mutex_unlock(&ar->mutex);
-}
-
-int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype,
-		      u8 keyidx, u8 *keydata, int keylen)
-{
-	__le32 vals[7];
-	static const u8 bcast[ETH_ALEN] =
-		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-	u8 dummy;
-
-	mac = mac ? : bcast;
-
-	vals[0] = cpu_to_le32((keyidx << 16) + id);
-	vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype);
-	vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 |
-			      mac[3] << 8 | mac[2]);
-	memset(&vals[3], 0, 16);
-	if (keydata)
-		memcpy(&vals[3], keydata, keylen);
-
-	return ar->exec_cmd(ar, AR9170_CMD_EKEY,
-			    sizeof(vals), (u8 *)vals,
-			    1, &dummy);
-}
-
-int ar9170_disable_key(struct ar9170 *ar, u8 id)
-{
-	__le32 val = cpu_to_le32(id);
-	u8 dummy;
-
-	return ar->exec_cmd(ar, AR9170_CMD_EKEY,
-			    sizeof(val), (u8 *)&val,
-			    1, &dummy);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1671 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * mac80211 interaction code
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, Christian Lamparter <chunkeey@web.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.
- *
- * 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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/etherdevice.h>
-#include <net/mac80211.h>
-#include "ar9170.h"
-#include "hw.h"
-#include "cmd.h"
-
-static int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-#define RATE(_bitrate, _hw_rate, _txpidx, _flags) {	\
-	.bitrate	= (_bitrate),			\
-	.flags		= (_flags),			\
-	.hw_value	= (_hw_rate) | (_txpidx) << 4,	\
-}
-
-static struct ieee80211_rate __ar9170_ratetable[] = {
-	RATE(10, 0, 0, 0),
-	RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(60, 0xb, 0, 0),
-	RATE(90, 0xf, 0, 0),
-	RATE(120, 0xa, 0, 0),
-	RATE(180, 0xe, 0, 0),
-	RATE(240, 0x9, 0, 0),
-	RATE(360, 0xd, 1, 0),
-	RATE(480, 0x8, 2, 0),
-	RATE(540, 0xc, 3, 0),
-};
-#undef RATE
-
-#define ar9170_g_ratetable	(__ar9170_ratetable + 0)
-#define ar9170_g_ratetable_size	12
-#define ar9170_a_ratetable	(__ar9170_ratetable + 4)
-#define ar9170_a_ratetable_size	8
-
-/*
- * NB: The hw_value is used as an index into the ar9170_phy_freq_params
- *     array in phy.c so that we don't have to do frequency lookups!
- */
-#define CHAN(_freq, _idx) {		\
-	.center_freq	= (_freq),	\
-	.hw_value	= (_idx),	\
-	.max_power	= 18, /* XXX */	\
-}
-
-static struct ieee80211_channel ar9170_2ghz_chantable[] = {
-	CHAN(2412,  0),
-	CHAN(2417,  1),
-	CHAN(2422,  2),
-	CHAN(2427,  3),
-	CHAN(2432,  4),
-	CHAN(2437,  5),
-	CHAN(2442,  6),
-	CHAN(2447,  7),
-	CHAN(2452,  8),
-	CHAN(2457,  9),
-	CHAN(2462, 10),
-	CHAN(2467, 11),
-	CHAN(2472, 12),
-	CHAN(2484, 13),
-};
-
-static struct ieee80211_channel ar9170_5ghz_chantable[] = {
-	CHAN(4920, 14),
-	CHAN(4940, 15),
-	CHAN(4960, 16),
-	CHAN(4980, 17),
-	CHAN(5040, 18),
-	CHAN(5060, 19),
-	CHAN(5080, 20),
-	CHAN(5180, 21),
-	CHAN(5200, 22),
-	CHAN(5220, 23),
-	CHAN(5240, 24),
-	CHAN(5260, 25),
-	CHAN(5280, 26),
-	CHAN(5300, 27),
-	CHAN(5320, 28),
-	CHAN(5500, 29),
-	CHAN(5520, 30),
-	CHAN(5540, 31),
-	CHAN(5560, 32),
-	CHAN(5580, 33),
-	CHAN(5600, 34),
-	CHAN(5620, 35),
-	CHAN(5640, 36),
-	CHAN(5660, 37),
-	CHAN(5680, 38),
-	CHAN(5700, 39),
-	CHAN(5745, 40),
-	CHAN(5765, 41),
-	CHAN(5785, 42),
-	CHAN(5805, 43),
-	CHAN(5825, 44),
-	CHAN(5170, 45),
-	CHAN(5190, 46),
-	CHAN(5210, 47),
-	CHAN(5230, 48),
-};
-#undef CHAN
-
-static struct ieee80211_supported_band ar9170_band_2GHz = {
-	.channels	= ar9170_2ghz_chantable,
-	.n_channels	= ARRAY_SIZE(ar9170_2ghz_chantable),
-	.bitrates	= ar9170_g_ratetable,
-	.n_bitrates	= ar9170_g_ratetable_size,
-};
-
-#ifdef AR9170_QUEUE_DEBUG
-/*
- * In case some wants works with AR9170's crazy tx_status queueing techniques.
- * He might need this rather useful probing function.
- *
- * NOTE: caller must hold the queue's spinlock!
- */
-
-static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
-{
-	struct ar9170_tx_control *txc = (void *) skb->data;
-	struct ieee80211_hdr *hdr = (void *)txc->frame_data;
-
-	printk(KERN_DEBUG "%s: => FRAME [skb:%p, queue:%d, DA:[%pM] "
-			  "mac_control:%04x, phy_control:%08x]\n",
-	       wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
-	       ieee80211_get_DA(hdr), le16_to_cpu(txc->mac_control),
-	       le32_to_cpu(txc->phy_control));
-}
-
-static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar,
-						struct sk_buff_head *queue)
-{
-	struct sk_buff *skb;
-	int i = 0;
-
-	printk(KERN_DEBUG "---[ cut here ]---\n");
-	printk(KERN_DEBUG "%s: %d entries in tx_status queue.\n",
-	       wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
-
-	skb_queue_walk(queue, skb) {
-		struct ar9170_tx_control *txc = (void *) skb->data;
-		struct ieee80211_hdr *hdr = (void *)txc->frame_data;
-
-		printk(KERN_DEBUG "index:%d => \n", i);
-		ar9170_print_txheader(ar, skb);
-	}
-	printk(KERN_DEBUG "---[ end ]---\n");
-}
-#endif /* AR9170_QUEUE_DEBUG */
-
-static struct ieee80211_supported_band ar9170_band_5GHz = {
-	.channels	= ar9170_5ghz_chantable,
-	.n_channels	= ARRAY_SIZE(ar9170_5ghz_chantable),
-	.bitrates	= ar9170_a_ratetable,
-	.n_bitrates	= ar9170_a_ratetable_size,
-};
-
-void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
-			     bool valid_status, u16 tx_status)
-{
-	struct ieee80211_tx_info *txinfo;
-	unsigned int retries = 0, queue = skb_get_queue_mapping(skb);
-	unsigned long flags;
-
-	spin_lock_irqsave(&ar->tx_stats_lock, flags);
-	ar->tx_stats[queue].len--;
-	if (ieee80211_queue_stopped(ar->hw, queue))
-		ieee80211_wake_queue(ar->hw, queue);
-	spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
-
-	txinfo = IEEE80211_SKB_CB(skb);
-	ieee80211_tx_info_clear_status(txinfo);
-
-	switch (tx_status) {
-	case AR9170_TX_STATUS_RETRY:
-		retries = 2;
-	case AR9170_TX_STATUS_COMPLETE:
-		txinfo->flags |= IEEE80211_TX_STAT_ACK;
-		break;
-
-	case AR9170_TX_STATUS_FAILED:
-		retries = ar->hw->conf.long_frame_max_tx_count;
-		break;
-
-	default:
-		printk(KERN_ERR "%s: invalid tx_status response (%x).\n",
-		       wiphy_name(ar->hw->wiphy), tx_status);
-		break;
-	}
-
-	if (valid_status)
-		txinfo->status.rates[0].count = retries + 1;
-
-	skb_pull(skb, sizeof(struct ar9170_tx_control));
-	ieee80211_tx_status_irqsafe(ar->hw, skb);
-}
-
-static struct sk_buff *ar9170_find_skb_in_queue(struct ar9170 *ar,
-						const u8 *mac,
-						const u32 queue,
-						struct sk_buff_head *q)
-{
-	unsigned long flags;
-	struct sk_buff *skb;
-
-	spin_lock_irqsave(&q->lock, flags);
-	skb_queue_walk(q, skb) {
-		struct ar9170_tx_control *txc = (void *) skb->data;
-		struct ieee80211_hdr *hdr = (void *) txc->frame_data;
-		u32 txc_queue = (le32_to_cpu(txc->phy_control) &
-				AR9170_TX_PHY_QOS_MASK) >>
-				AR9170_TX_PHY_QOS_SHIFT;
-
-		if  ((queue != txc_queue) ||
-		     (compare_ether_addr(ieee80211_get_DA(hdr), mac)))
-			continue;
-
-		__skb_unlink(skb, q);
-		spin_unlock_irqrestore(&q->lock, flags);
-		return skb;
-	}
-	spin_unlock_irqrestore(&q->lock, flags);
-	return NULL;
-}
-
-static struct sk_buff *ar9170_find_queued_skb(struct ar9170 *ar, const u8 *mac,
-					      const u32 queue)
-{
-	struct ieee80211_sta *sta;
-	struct sk_buff *skb;
-
-	/*
-	 * Unfortunately, the firmware does not tell to which (queued) frame
-	 * this transmission status report belongs to.
-	 *
-	 * So we have to make risky guesses - with the scarce information
-	 * the firmware provided (-> destination MAC, and phy_control) -
-	 * and hope that we picked the right one...
-	 */
-	rcu_read_lock();
-	sta = ieee80211_find_sta(ar->hw, mac);
-
-	if (likely(sta)) {
-		struct ar9170_sta_info *sta_priv = (void *) sta->drv_priv;
-		skb = skb_dequeue(&sta_priv->tx_status[queue]);
-		rcu_read_unlock();
-		if (likely(skb))
-			return skb;
-	} else
-		rcu_read_unlock();
-
-	/* scan the waste queue for candidates */
-	skb = ar9170_find_skb_in_queue(ar, mac, queue,
-				       &ar->global_tx_status_waste);
-	if (!skb) {
-		/* so it still _must_ be in the global list. */
-		skb = ar9170_find_skb_in_queue(ar, mac, queue,
-					       &ar->global_tx_status);
-	}
-
-#ifdef AR9170_QUEUE_DEBUG
-	if (unlikely((!skb) && net_ratelimit())) {
-		printk(KERN_ERR "%s: ESS:[%pM] does not have any "
-				"outstanding frames in this queue (%d).\n",
-				wiphy_name(ar->hw->wiphy), mac, queue);
-	}
-#endif /* AR9170_QUEUE_DEBUG */
-	return skb;
-}
-
-/*
- * This worker tries to keep the global tx_status queue empty.
- * So we can guarantee that incoming tx_status reports for
- * unregistered stations are always synced with the actual
- * frame - which we think - belongs to.
- */
-
-static void ar9170_tx_status_janitor(struct work_struct *work)
-{
-	struct ar9170 *ar = container_of(work, struct ar9170,
-					 tx_status_janitor.work);
-	struct sk_buff *skb;
-
-	if (unlikely(!IS_STARTED(ar)))
-		return ;
-
-	mutex_lock(&ar->mutex);
-	/* recycle the garbage back to mac80211... one by one. */
-	while ((skb = skb_dequeue(&ar->global_tx_status_waste))) {
-#ifdef AR9170_QUEUE_DEBUG
-		printk(KERN_DEBUG "%s: dispose queued frame =>\n",
-		       wiphy_name(ar->hw->wiphy));
-		ar9170_print_txheader(ar, skb);
-#endif /* AR9170_QUEUE_DEBUG */
-		ar9170_handle_tx_status(ar, skb, false,
-					AR9170_TX_STATUS_FAILED);
-	}
-
-	while ((skb = skb_dequeue(&ar->global_tx_status))) {
-#ifdef AR9170_QUEUE_DEBUG
-		printk(KERN_DEBUG "%s: moving frame into waste queue =>\n",
-		       wiphy_name(ar->hw->wiphy));
-
-		ar9170_print_txheader(ar, skb);
-#endif /* AR9170_QUEUE_DEBUG */
-		skb_queue_tail(&ar->global_tx_status_waste, skb);
-	}
-
-	/* recall the janitor in 100ms - if there's garbage in the can. */
-	if (skb_queue_len(&ar->global_tx_status_waste) > 0)
-		queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor,
-				   msecs_to_jiffies(100));
-
-	mutex_unlock(&ar->mutex);
-}
-
-static void ar9170_handle_command_response(struct ar9170 *ar,
-					   void *buf, u32 len)
-{
-	struct ar9170_cmd_response *cmd = (void *) buf;
-
-	if ((cmd->type & 0xc0) != 0xc0) {
-		ar->callback_cmd(ar, len, buf);
-		return;
-	}
-
-	/* hardware event handlers */
-	switch (cmd->type) {
-	case 0xc1: {
-		/*
-		 * TX status notification:
-		 * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1
-		 *
-		 * XX always 81
-		 * YY always 00
-		 * M1-M6 is the MAC address
-		 * R1-R4 is the transmit rate
-		 * S1-S2 is the transmit status
-		 */
-
-		struct sk_buff *skb;
-		u32 queue = (le32_to_cpu(cmd->tx_status.rate) &
-			    AR9170_TX_PHY_QOS_MASK) >> AR9170_TX_PHY_QOS_SHIFT;
-
-		skb = ar9170_find_queued_skb(ar, cmd->tx_status.dst, queue);
-		if (unlikely(!skb))
-			return ;
-
-		ar9170_handle_tx_status(ar, skb, true,
-					le16_to_cpu(cmd->tx_status.status));
-		break;
-		}
-
-	case 0xc0:
-		/*
-		 * pre-TBTT event
-		 */
-		if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
-			queue_work(ar->hw->workqueue, &ar->beacon_work);
-		break;
-
-	case 0xc2:
-		/*
-		 * (IBSS) beacon send notification
-		 * bytes: 04 c2 XX YY B4 B3 B2 B1
-		 *
-		 * XX always 80
-		 * YY always 00
-		 * B1-B4 "should" be the number of send out beacons.
-		 */
-		break;
-
-	case 0xc3:
-		/* End of Atim Window */
-		break;
-
-	case 0xc4:
-	case 0xc5:
-		/* BlockACK events */
-		break;
-
-	case 0xc6:
-		/* Watchdog Interrupt */
-		break;
-
-	case 0xc9:
-		/* retransmission issue / SIFS/EIFS collision ?! */
-		break;
-
-	default:
-		printk(KERN_INFO "received unhandled event %x\n", cmd->type);
-		print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
-		break;
-	}
-}
-
-/*
- * If the frame alignment is right (or the kernel has
- * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
- * is only a single MPDU in the USB frame, then we can
- * submit to mac80211 the SKB directly. However, since
- * there may be multiple packets in one SKB in stream
- * mode, and we need to observe the proper ordering,
- * this is non-trivial.
- */
-static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
-{
-	struct sk_buff *skb;
-	struct ar9170_rx_head *head = (void *)buf;
-	struct ar9170_rx_tail *tail;
-	struct ieee80211_rx_status status;
-	int mpdu_len, i;
-	u8 error, antennas = 0, decrypt;
-	__le16 fc;
-	int reserved;
-
-	if (unlikely(!IS_STARTED(ar)))
-		return ;
-
-	/* Received MPDU */
-	mpdu_len = len;
-	mpdu_len -= sizeof(struct ar9170_rx_head);
-	mpdu_len -= sizeof(struct ar9170_rx_tail);
-	BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
-	BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24);
-
-	if (mpdu_len <= FCS_LEN)
-		return;
-
-	tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len);
-
-	for (i = 0; i < 3; i++)
-		if (tail->rssi[i] != 0x80)
-			antennas |= BIT(i);
-
-	/* post-process RSSI */
-	for (i = 0; i < 7; i++)
-		if (tail->rssi[i] & 0x80)
-			tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f;
-
-	memset(&status, 0, sizeof(status));
-
-	status.band = ar->channel->band;
-	status.freq = ar->channel->center_freq;
-	status.signal = ar->noise[0] + tail->rssi_combined;
-	status.noise = ar->noise[0];
-	status.antenna = antennas;
-
-	switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) {
-	case AR9170_RX_STATUS_MODULATION_CCK:
-		if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
-			status.flag |= RX_FLAG_SHORTPRE;
-		switch (head->plcp[0]) {
-		case 0x0a:
-			status.rate_idx = 0;
-			break;
-		case 0x14:
-			status.rate_idx = 1;
-			break;
-		case 0x37:
-			status.rate_idx = 2;
-			break;
-		case 0x6e:
-			status.rate_idx = 3;
-			break;
-		default:
-			if ((!ar->sniffer_enabled) && (net_ratelimit()))
-				printk(KERN_ERR "%s: invalid plcp cck rate "
-				       "(%x).\n", wiphy_name(ar->hw->wiphy),
-				       head->plcp[0]);
-			return;
-		}
-		break;
-	case AR9170_RX_STATUS_MODULATION_OFDM:
-		switch (head->plcp[0] & 0xF) {
-		case 0xB:
-			status.rate_idx = 0;
-			break;
-		case 0xF:
-			status.rate_idx = 1;
-			break;
-		case 0xA:
-			status.rate_idx = 2;
-			break;
-		case 0xE:
-			status.rate_idx = 3;
-			break;
-		case 0x9:
-			status.rate_idx = 4;
-			break;
-		case 0xD:
-			status.rate_idx = 5;
-			break;
-		case 0x8:
-			status.rate_idx = 6;
-			break;
-		case 0xC:
-			status.rate_idx = 7;
-			break;
-		default:
-			if ((!ar->sniffer_enabled) && (net_ratelimit()))
-				printk(KERN_ERR "%s: invalid plcp ofdm rate "
-				       "(%x).\n", wiphy_name(ar->hw->wiphy),
-				       head->plcp[0]);
-			return;
-		}
-		if (status.band == IEEE80211_BAND_2GHZ)
-			status.rate_idx += 4;
-		break;
-	case AR9170_RX_STATUS_MODULATION_HT:
-	case AR9170_RX_STATUS_MODULATION_DUPOFDM:
-		/* XXX */
-
-		if (net_ratelimit())
-			printk(KERN_ERR "%s: invalid modulation\n",
-			       wiphy_name(ar->hw->wiphy));
-		return;
-	}
-
-	error = tail->error;
-
-	if (error & AR9170_RX_ERROR_MMIC) {
-		status.flag |= RX_FLAG_MMIC_ERROR;
-		error &= ~AR9170_RX_ERROR_MMIC;
-	}
-
-	if (error & AR9170_RX_ERROR_PLCP) {
-		status.flag |= RX_FLAG_FAILED_PLCP_CRC;
-		error &= ~AR9170_RX_ERROR_PLCP;
-	}
-
-	if (error & AR9170_RX_ERROR_FCS) {
-		status.flag |= RX_FLAG_FAILED_FCS_CRC;
-		error &= ~AR9170_RX_ERROR_FCS;
-	}
-
-	decrypt = ar9170_get_decrypt_type(tail);
-	if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
-	    decrypt != AR9170_ENC_ALG_NONE)
-		status.flag |= RX_FLAG_DECRYPTED;
-
-	/* ignore wrong RA errors */
-	error &= ~AR9170_RX_ERROR_WRONG_RA;
-
-	if (error & AR9170_RX_ERROR_DECRYPT) {
-		error &= ~AR9170_RX_ERROR_DECRYPT;
-
-		/*
-		 * Rx decryption is done in place,
-		 * the original data is lost anyway.
-		 */
-		return ;
-	}
-
-	/* drop any other error frames */
-	if ((error) && (net_ratelimit())) {
-		printk(KERN_DEBUG "%s: errors: %#x\n",
-		       wiphy_name(ar->hw->wiphy), error);
-		return;
-	}
-
-	buf += sizeof(struct ar9170_rx_head);
-	fc = *(__le16 *)buf;
-
-	if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc))
-		reserved = 32 + 2;
-	else
-		reserved = 32;
-
-	skb = dev_alloc_skb(mpdu_len + reserved);
-	if (!skb)
-		return;
-
-	skb_reserve(skb, reserved);
-	memcpy(skb_put(skb, mpdu_len), buf, mpdu_len);
-	ieee80211_rx_irqsafe(ar->hw, skb, &status);
-}
-
-void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
-{
-	unsigned int i, tlen, resplen;
-	u8 *tbuf, *respbuf;
-
-	tbuf = skb->data;
-	tlen = skb->len;
-
-	while (tlen >= 4) {
-		int clen = tbuf[1] << 8 | tbuf[0];
-		int wlen = (clen + 3) & ~3;
-
-		/*
-		 * parse stream (if any)
-		 */
-		if (tbuf[2] != 0 || tbuf[3] != 0x4e) {
-			printk(KERN_ERR "%s: missing tag!\n",
-			       wiphy_name(ar->hw->wiphy));
-			return ;
-		}
-		if (wlen > tlen - 4) {
-			printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n",
-			       wiphy_name(ar->hw->wiphy), clen, wlen, tlen);
-			print_hex_dump(KERN_DEBUG, "data: ",
-				       DUMP_PREFIX_OFFSET,
-				       16, 1, tbuf, tlen, true);
-			return ;
-		}
-		resplen = clen;
-		respbuf = tbuf + 4;
-		tbuf += wlen + 4;
-		tlen -= wlen + 4;
-
-		i = 0;
-
-		/* weird thing, but this is the same in the original driver */
-		while (resplen > 2 && i < 12 &&
-		       respbuf[0] == 0xff && respbuf[1] == 0xff) {
-			i += 2;
-			resplen -= 2;
-			respbuf += 2;
-		}
-
-		if (resplen < 4)
-			continue;
-
-		/* found the 6 * 0xffff marker? */
-		if (i == 12)
-			ar9170_handle_command_response(ar, respbuf, resplen);
-		else
-			ar9170_handle_mpdu(ar, respbuf, resplen);
-	}
-
-	if (tlen)
-		printk(KERN_ERR "%s: buffer remains!\n",
-		       wiphy_name(ar->hw->wiphy));
-}
-
-#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop)		\
-do {									\
-	queue.aifs = ai_fs;						\
-	queue.cw_min = cwmin;						\
-	queue.cw_max = cwmax;						\
-	queue.txop = _txop;						\
-} while (0)
-
-static int ar9170_op_start(struct ieee80211_hw *hw)
-{
-	struct ar9170 *ar = hw->priv;
-	int err, i;
-
-	mutex_lock(&ar->mutex);
-
-	/* reinitialize queues statistics */
-	memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
-	for (i = 0; i < ARRAY_SIZE(ar->tx_stats); i++)
-		ar->tx_stats[i].limit = 8;
-
-	/* reset QoS defaults */
-	AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023,  0); /* BEST EFFORT*/
-	AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023,  0); /* BACKGROUND */
-	AR9170_FILL_QUEUE(ar->edcf[2], 2, 7,    15, 94); /* VIDEO */
-	AR9170_FILL_QUEUE(ar->edcf[3], 2, 3,     7, 47); /* VOICE */
-	AR9170_FILL_QUEUE(ar->edcf[4], 2, 3,     7,  0); /* SPECIAL */
-
-	err = ar->open(ar);
-	if (err)
-		goto out;
-
-	err = ar9170_init_mac(ar);
-	if (err)
-		goto out;
-
-	err = ar9170_set_qos(ar);
-	if (err)
-		goto out;
-
-	err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ);
-	if (err)
-		goto out;
-
-	err = ar9170_init_rf(ar);
-	if (err)
-		goto out;
-
-	/* start DMA */
-	err = ar9170_write_reg(ar, 0x1c3d30, 0x100);
-	if (err)
-		goto out;
-
-	ar->state = AR9170_STARTED;
-
-out:
-	mutex_unlock(&ar->mutex);
-	return err;
-}
-
-static void ar9170_op_stop(struct ieee80211_hw *hw)
-{
-	struct ar9170 *ar = hw->priv;
-
-	if (IS_STARTED(ar))
-		ar->state = AR9170_IDLE;
-
-	mutex_lock(&ar->mutex);
-
-	cancel_delayed_work_sync(&ar->tx_status_janitor);
-	cancel_work_sync(&ar->filter_config_work);
-	cancel_work_sync(&ar->beacon_work);
-	skb_queue_purge(&ar->global_tx_status_waste);
-	skb_queue_purge(&ar->global_tx_status);
-
-	if (IS_ACCEPTING_CMD(ar)) {
-		ar9170_set_leds_state(ar, 0);
-
-		/* stop DMA */
-		ar9170_write_reg(ar, 0x1c3d30, 0);
-		ar->stop(ar);
-	}
-
-	mutex_unlock(&ar->mutex);
-}
-
-int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct ar9170 *ar = hw->priv;
-	struct ieee80211_hdr *hdr;
-	struct ar9170_tx_control *txc;
-	struct ieee80211_tx_info *info;
-	struct ieee80211_rate *rate = NULL;
-	struct ieee80211_tx_rate *txrate;
-	unsigned int queue = skb_get_queue_mapping(skb);
-	unsigned long flags = 0;
-	struct ar9170_sta_info *sta_info = NULL;
-	u32 power, chains;
-	u16 keytype = 0;
-	u16 len, icv = 0;
-	int err;
-	bool tx_status;
-
-	if (unlikely(!IS_STARTED(ar)))
-		goto err_free;
-
-	hdr = (void *)skb->data;
-	info = IEEE80211_SKB_CB(skb);
-	len = skb->len;
-
-	spin_lock_irqsave(&ar->tx_stats_lock, flags);
-	if (ar->tx_stats[queue].limit < ar->tx_stats[queue].len) {
-		spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
-		return NETDEV_TX_OK;
-	}
-
-	ar->tx_stats[queue].len++;
-	ar->tx_stats[queue].count++;
-	if (ar->tx_stats[queue].limit == ar->tx_stats[queue].len)
-		ieee80211_stop_queue(hw, queue);
-
-	spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
-
-	txc = (void *)skb_push(skb, sizeof(*txc));
-
-	tx_status = (((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) != 0) ||
-		    ((info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) != 0));
-
-	if (info->control.hw_key) {
-		icv = info->control.hw_key->icv_len;
-
-		switch (info->control.hw_key->alg) {
-		case ALG_WEP:
-			keytype = AR9170_TX_MAC_ENCR_RC4;
-			break;
-		case ALG_TKIP:
-			keytype = AR9170_TX_MAC_ENCR_RC4;
-			break;
-		case ALG_CCMP:
-			keytype = AR9170_TX_MAC_ENCR_AES;
-			break;
-		default:
-			WARN_ON(1);
-			goto err_dequeue;
-		}
-	}
-
-	/* Length */
-	txc->length = cpu_to_le16(len + icv + 4);
-
-	txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
-				       AR9170_TX_MAC_BACKOFF);
-	txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] <<
-					AR9170_TX_MAC_QOS_SHIFT);
-	txc->mac_control |= cpu_to_le16(keytype);
-	txc->phy_control = cpu_to_le32(0);
-
-	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
-		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
-
-	if (info->flags & IEEE80211_TX_CTL_AMPDU)
-		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
-
-	txrate = &info->control.rates[0];
-
-	if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
-		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
-	else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
-		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
-
-	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
-		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
-
-	if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
-
-	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ);
-	/* this works because 40 MHz is 2 and dup is 3 */
-	if (txrate->flags & IEEE80211_TX_RC_DUP_DATA)
-		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP);
-
-	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
-		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
-
-	if (txrate->flags & IEEE80211_TX_RC_MCS) {
-		u32 r = txrate->idx;
-		u8 *txpower;
-
-		r <<= AR9170_TX_PHY_MCS_SHIFT;
-		if (WARN_ON(r & ~AR9170_TX_PHY_MCS_MASK))
-			goto err_dequeue;
-		txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK);
-		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
-
-		if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
-			if (info->band == IEEE80211_BAND_5GHZ)
-				txpower = ar->power_5G_ht40;
-			else
-				txpower = ar->power_2G_ht40;
-		} else {
-			if (info->band == IEEE80211_BAND_5GHZ)
-				txpower = ar->power_5G_ht20;
-			else
-				txpower = ar->power_2G_ht20;
-		}
-
-		power = txpower[(txrate->idx) & 7];
-	} else {
-		u8 *txpower;
-		u32 mod;
-		u32 phyrate;
-		u8 idx = txrate->idx;
-
-		if (info->band != IEEE80211_BAND_2GHZ) {
-			idx += 4;
-			txpower = ar->power_5G_leg;
-			mod = AR9170_TX_PHY_MOD_OFDM;
-		} else {
-			if (idx < 4) {
-				txpower = ar->power_2G_cck;
-				mod = AR9170_TX_PHY_MOD_CCK;
-			} else {
-				mod = AR9170_TX_PHY_MOD_OFDM;
-				txpower = ar->power_2G_ofdm;
-			}
-		}
-
-		rate = &__ar9170_ratetable[idx];
-
-		phyrate = rate->hw_value & 0xF;
-		power = txpower[(rate->hw_value & 0x30) >> 4];
-		phyrate <<= AR9170_TX_PHY_MCS_SHIFT;
-
-		txc->phy_control |= cpu_to_le32(mod);
-		txc->phy_control |= cpu_to_le32(phyrate);
-	}
-
-	power <<= AR9170_TX_PHY_TX_PWR_SHIFT;
-	power &= AR9170_TX_PHY_TX_PWR_MASK;
-	txc->phy_control |= cpu_to_le32(power);
-
-	/* set TX chains */
-	if (ar->eeprom.tx_mask == 1) {
-		chains = AR9170_TX_PHY_TXCHAIN_1;
-	} else {
-		chains = AR9170_TX_PHY_TXCHAIN_2;
-
-		/* >= 36M legacy OFDM - use only one chain */
-		if (rate && rate->bitrate >= 360)
-			chains = AR9170_TX_PHY_TXCHAIN_1;
-	}
-	txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
-
-	if (tx_status) {
-		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
-		/*
-		 * WARNING:
-		 * Putting the QoS queue bits into an unexplored territory is
-		 * certainly not elegant.
-		 *
-		 * In my defense: This idea provides a reasonable way to
-		 * smuggle valuable information to the tx_status callback.
-		 * Also, the idea behind this bit-abuse came straight from
-		 * the original driver code.
-		 */
-
-		txc->phy_control |=
-			cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
-
-		if (info->control.sta) {
-			sta_info = (void *) info->control.sta->drv_priv;
-			skb_queue_tail(&sta_info->tx_status[queue], skb);
-		} else {
-			skb_queue_tail(&ar->global_tx_status, skb);
-
-			queue_delayed_work(ar->hw->workqueue,
-					   &ar->tx_status_janitor,
-					   msecs_to_jiffies(100));
-		}
-	}
-
-	err = ar->tx(ar, skb, tx_status, 0);
-	if (unlikely(tx_status && err)) {
-		if (info->control.sta)
-			skb_unlink(skb, &sta_info->tx_status[queue]);
-		else
-			skb_unlink(skb, &ar->global_tx_status);
-	}
-
-	return NETDEV_TX_OK;
-
-err_dequeue:
-	spin_lock_irqsave(&ar->tx_stats_lock, flags);
-	ar->tx_stats[queue].len--;
-	ar->tx_stats[queue].count--;
-	spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
-
-err_free:
-	dev_kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-static int ar9170_op_add_interface(struct ieee80211_hw *hw,
-				   struct ieee80211_if_init_conf *conf)
-{
-	struct ar9170 *ar = hw->priv;
-	int err = 0;
-
-	mutex_lock(&ar->mutex);
-
-	if (ar->vif) {
-		err = -EBUSY;
-		goto unlock;
-	}
-
-	ar->vif = conf->vif;
-	memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN);
-
-	if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
-		ar->rx_software_decryption = true;
-		ar->disable_offload = true;
-	}
-
-	ar->cur_filter = 0;
-	ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS;
-	err = ar9170_update_frame_filter(ar);
-	if (err)
-		goto unlock;
-
-	err = ar9170_set_operating_mode(ar);
-
-unlock:
-	mutex_unlock(&ar->mutex);
-	return err;
-}
-
-static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
-				       struct ieee80211_if_init_conf *conf)
-{
-	struct ar9170 *ar = hw->priv;
-
-	mutex_lock(&ar->mutex);
-	ar->vif = NULL;
-	ar->want_filter = 0;
-	ar9170_update_frame_filter(ar);
-	ar9170_set_beacon_timers(ar);
-	dev_kfree_skb(ar->beacon);
-	ar->beacon = NULL;
-	ar->sniffer_enabled = false;
-	ar->rx_software_decryption = false;
-	ar9170_set_operating_mode(ar);
-	mutex_unlock(&ar->mutex);
-}
-
-static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct ar9170 *ar = hw->priv;
-	int err = 0;
-
-	mutex_lock(&ar->mutex);
-
-	if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
-		/* TODO */
-		err = 0;
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
-		/* TODO */
-		err = 0;
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_PS) {
-		/* TODO */
-		err = 0;
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-		/* TODO */
-		err = 0;
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
-		/*
-		 * is it long_frame_max_tx_count or short_frame_max_tx_count?
-		 */
-
-		err = ar9170_set_hwretry_limit(ar,
-			ar->hw->conf.long_frame_max_tx_count);
-		if (err)
-			goto out;
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) {
-		err = ar9170_set_beacon_timers(ar);
-		if (err)
-			goto out;
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		err = ar9170_set_channel(ar, hw->conf.channel,
-					 AR9170_RFI_NONE, AR9170_BW_20);
-		if (err)
-			goto out;
-		/* adjust slot time for 5 GHz */
-		if (hw->conf.channel->band == IEEE80211_BAND_5GHZ)
-			err = ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME,
-					       9 << 10);
-	}
-
-out:
-	mutex_unlock(&ar->mutex);
-	return err;
-}
-
-static int ar9170_op_config_interface(struct ieee80211_hw *hw,
-				      struct ieee80211_vif *vif,
-				      struct ieee80211_if_conf *conf)
-{
-	struct ar9170 *ar = hw->priv;
-	int err = 0;
-
-	mutex_lock(&ar->mutex);
-
-	if (conf->changed & IEEE80211_IFCC_BSSID) {
-		memcpy(ar->bssid, conf->bssid, ETH_ALEN);
-		err = ar9170_set_operating_mode(ar);
-	}
-
-	if (conf->changed & IEEE80211_IFCC_BEACON) {
-		err = ar9170_update_beacon(ar);
-
-		if (err)
-			goto out;
-		err = ar9170_set_beacon_timers(ar);
-	}
-
-out:
-	mutex_unlock(&ar->mutex);
-	return err;
-}
-
-static void ar9170_set_filters(struct work_struct *work)
-{
-	struct ar9170 *ar = container_of(work, struct ar9170,
-					 filter_config_work);
-	int err;
-
-	mutex_lock(&ar->mutex);
-	if (unlikely(!IS_STARTED(ar)))
-		goto unlock;
-
-	if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) {
-		err = ar9170_set_operating_mode(ar);
-		if (err)
-			goto unlock;
-	}
-
-	if (ar->filter_changed & AR9170_FILTER_CHANGED_MULTICAST) {
-		err = ar9170_update_multicast(ar);
-		if (err)
-			goto unlock;
-	}
-
-	if (ar->filter_changed & AR9170_FILTER_CHANGED_FRAMEFILTER)
-		err = ar9170_update_frame_filter(ar);
-
-unlock:
-	mutex_unlock(&ar->mutex);
-}
-
-static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
-				       unsigned int changed_flags,
-				       unsigned int *new_flags,
-				       int mc_count, struct dev_mc_list *mclist)
-{
-	struct ar9170 *ar = hw->priv;
-
-	/* mask supported flags */
-	*new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
-		      FIF_PROMISC_IN_BSS;
-
-	/*
-	 * We can support more by setting the sniffer bit and
-	 * then checking the error flags, later.
-	 */
-
-	if (changed_flags & FIF_ALLMULTI) {
-		if (*new_flags & FIF_ALLMULTI) {
-			ar->want_mc_hash = ~0ULL;
-		} else {
-			u64 mchash;
-			int i;
-
-			/* always get broadcast frames */
-			mchash = 1ULL << (0xff>>2);
-
-			for (i = 0; i < mc_count; i++) {
-				if (WARN_ON(!mclist))
-					break;
-				mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
-				mclist = mclist->next;
-			}
-		ar->want_mc_hash = mchash;
-		}
-		ar->filter_changed |= AR9170_FILTER_CHANGED_MULTICAST;
-	}
-
-	if (changed_flags & FIF_CONTROL) {
-		u32 filter = AR9170_MAC_REG_FTF_PSPOLL |
-			     AR9170_MAC_REG_FTF_RTS |
-			     AR9170_MAC_REG_FTF_CTS |
-			     AR9170_MAC_REG_FTF_ACK |
-			     AR9170_MAC_REG_FTF_CFE |
-			     AR9170_MAC_REG_FTF_CFE_ACK;
-
-		if (*new_flags & FIF_CONTROL)
-			ar->want_filter = ar->cur_filter | filter;
-		else
-			ar->want_filter = ar->cur_filter & ~filter;
-
-		ar->filter_changed |= AR9170_FILTER_CHANGED_FRAMEFILTER;
-	}
-
-	if (changed_flags & FIF_PROMISC_IN_BSS) {
-		ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
-		ar->filter_changed |= AR9170_FILTER_CHANGED_PROMISC;
-	}
-
-	if (likely(IS_STARTED(ar)))
-		queue_work(ar->hw->workqueue, &ar->filter_config_work);
-}
-
-static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif,
-				       struct ieee80211_bss_conf *bss_conf,
-				       u32 changed)
-{
-	struct ar9170 *ar = hw->priv;
-	int err = 0;
-
-	mutex_lock(&ar->mutex);
-
-	ar9170_regwrite_begin(ar);
-
-	if (changed & BSS_CHANGED_ASSOC) {
-		ar->state = bss_conf->assoc ? AR9170_ASSOCIATED : ar->state;
-
-#ifndef CONFIG_AR9170_LEDS
-		/* enable assoc LED. */
-		err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0);
-#endif /* CONFIG_AR9170_LEDS */
-	}
-
-	if (changed & BSS_CHANGED_HT) {
-		/* TODO */
-		err = 0;
-	}
-
-	if (changed & BSS_CHANGED_ERP_SLOT) {
-		u32 slottime = 20;
-
-		if (bss_conf->use_short_slot)
-			slottime = 9;
-
-		ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, slottime << 10);
-	}
-
-	if (changed & BSS_CHANGED_BASIC_RATES) {
-		u32 cck, ofdm;
-
-		if (hw->conf.channel->band == IEEE80211_BAND_5GHZ) {
-			ofdm = bss_conf->basic_rates;
-			cck = 0;
-		} else {
-			/* four cck rates */
-			cck = bss_conf->basic_rates & 0xf;
-			ofdm = bss_conf->basic_rates >> 4;
-		}
-		ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE,
-				ofdm << 8 | cck);
-	}
-
-	ar9170_regwrite_finish();
-	err = ar9170_regwrite_result();
-	mutex_unlock(&ar->mutex);
-}
-
-static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
-{
-	struct ar9170 *ar = hw->priv;
-	int err;
-	u32 tsf_low;
-	u32 tsf_high;
-	u64 tsf;
-
-	mutex_lock(&ar->mutex);
-	err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low);
-	if (!err)
-		err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high);
-	mutex_unlock(&ar->mutex);
-
-	if (WARN_ON(err))
-		return 0;
-
-	tsf = tsf_high;
-	tsf = (tsf << 32) | tsf_low;
-	return tsf;
-}
-
-static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-			  struct ieee80211_key_conf *key)
-{
-	struct ar9170 *ar = hw->priv;
-	int err = 0, i;
-	u8 ktype;
-
-	if ((!ar->vif) || (ar->disable_offload))
-		return -EOPNOTSUPP;
-
-	switch (key->alg) {
-	case ALG_WEP:
-		if (key->keylen == LEN_WEP40)
-			ktype = AR9170_ENC_ALG_WEP64;
-		else
-			ktype = AR9170_ENC_ALG_WEP128;
-		break;
-	case ALG_TKIP:
-		ktype = AR9170_ENC_ALG_TKIP;
-		break;
-	case ALG_CCMP:
-		ktype = AR9170_ENC_ALG_AESCCMP;
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	mutex_lock(&ar->mutex);
-	if (cmd == SET_KEY) {
-		if (unlikely(!IS_STARTED(ar))) {
-			err = -EOPNOTSUPP;
-			goto out;
-		}
-
-		/* group keys need all-zeroes address */
-		if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
-			sta = NULL;
-
-		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
-			for (i = 0; i < 64; i++)
-				if (!(ar->usedkeys & BIT(i)))
-					break;
-			if (i == 64) {
-				ar->rx_software_decryption = true;
-				ar9170_set_operating_mode(ar);
-				err = -ENOSPC;
-				goto out;
-			}
-		} else {
-			i = 64 + key->keyidx;
-		}
-
-		key->hw_key_idx = i;
-
-		err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0,
-					key->key, min_t(u8, 16, key->keylen));
-		if (err)
-			goto out;
-
-		if (key->alg == ALG_TKIP) {
-			err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL,
-						ktype, 1, key->key + 16, 16);
-			if (err)
-				goto out;
-
-			/*
-			 * hardware is not capable generating the MMIC
-			 * for fragmented frames!
-			 */
-			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-		}
-
-		if (i < 64)
-			ar->usedkeys |= BIT(i);
-
-		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-	} else {
-		if (unlikely(!IS_STARTED(ar))) {
-			/* The device is gone... together with the key ;-) */
-			err = 0;
-			goto out;
-		}
-
-		err = ar9170_disable_key(ar, key->hw_key_idx);
-		if (err)
-			goto out;
-
-		if (key->hw_key_idx < 64) {
-			ar->usedkeys &= ~BIT(key->hw_key_idx);
-		} else {
-			err = ar9170_upload_key(ar, key->hw_key_idx, NULL,
-						AR9170_ENC_ALG_NONE, 0,
-						NULL, 0);
-			if (err)
-				goto out;
-
-			if (key->alg == ALG_TKIP) {
-				err = ar9170_upload_key(ar, key->hw_key_idx,
-							NULL,
-							AR9170_ENC_ALG_NONE, 1,
-							NULL, 0);
-				if (err)
-					goto out;
-			}
-
-		}
-	}
-
-	ar9170_regwrite_begin(ar);
-	ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys);
-	ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32);
-	ar9170_regwrite_finish();
-	err = ar9170_regwrite_result();
-
-out:
-	mutex_unlock(&ar->mutex);
-
-	return err;
-}
-
-static void ar9170_sta_notify(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      enum sta_notify_cmd cmd,
-			      struct ieee80211_sta *sta)
-{
-	struct ar9170 *ar = hw->priv;
-	struct ar9170_sta_info *info = (void *) sta->drv_priv;
-	struct sk_buff *skb;
-	unsigned int i;
-
-	switch (cmd) {
-	case STA_NOTIFY_ADD:
-		for (i = 0; i < ar->hw->queues; i++)
-			skb_queue_head_init(&info->tx_status[i]);
-		break;
-
-	case STA_NOTIFY_REMOVE:
-
-		/*
-		 * transfer all outstanding frames that need a tx_status
-		 * reports to the global tx_status queue
-		 */
-
-		for (i = 0; i < ar->hw->queues; i++) {
-			while ((skb = skb_dequeue(&info->tx_status[i]))) {
-#ifdef AR9170_QUEUE_DEBUG
-				printk(KERN_DEBUG "%s: queueing frame in "
-					  "global tx_status queue =>\n",
-				       wiphy_name(ar->hw->wiphy));
-
-				ar9170_print_txheader(ar, skb);
-#endif /* AR9170_QUEUE_DEBUG */
-				skb_queue_tail(&ar->global_tx_status, skb);
-			}
-		}
-		queue_delayed_work(ar->hw->workqueue, &ar->tx_status_janitor,
-				   msecs_to_jiffies(100));
-		break;
-
-	default:
-		break;
-	}
-}
-
-static int ar9170_get_stats(struct ieee80211_hw *hw,
-			    struct ieee80211_low_level_stats *stats)
-{
-	struct ar9170 *ar = hw->priv;
-	u32 val;
-	int err;
-
-	mutex_lock(&ar->mutex);
-	err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val);
-	ar->stats.dot11ACKFailureCount += val;
-
-	memcpy(stats, &ar->stats, sizeof(*stats));
-	mutex_unlock(&ar->mutex);
-
-	return 0;
-}
-
-static int ar9170_get_tx_stats(struct ieee80211_hw *hw,
-			       struct ieee80211_tx_queue_stats *tx_stats)
-{
-	struct ar9170 *ar = hw->priv;
-
-	spin_lock_bh(&ar->tx_stats_lock);
-	memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues);
-	spin_unlock_bh(&ar->tx_stats_lock);
-
-	return 0;
-}
-
-static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			  const struct ieee80211_tx_queue_params *param)
-{
-	struct ar9170 *ar = hw->priv;
-	int ret;
-
-	mutex_lock(&ar->mutex);
-	if ((param) && !(queue > ar->hw->queues)) {
-		memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
-		       param, sizeof(*param));
-
-		ret = ar9170_set_qos(ar);
-	} else
-		ret = -EINVAL;
-
-	mutex_unlock(&ar->mutex);
-	return ret;
-}
-
-static const struct ieee80211_ops ar9170_ops = {
-	.start			= ar9170_op_start,
-	.stop			= ar9170_op_stop,
-	.tx			= ar9170_op_tx,
-	.add_interface		= ar9170_op_add_interface,
-	.remove_interface	= ar9170_op_remove_interface,
-	.config			= ar9170_op_config,
-	.config_interface	= ar9170_op_config_interface,
-	.configure_filter	= ar9170_op_configure_filter,
-	.conf_tx		= ar9170_conf_tx,
-	.bss_info_changed	= ar9170_op_bss_info_changed,
-	.get_tsf		= ar9170_op_get_tsf,
-	.set_key		= ar9170_set_key,
-	.sta_notify		= ar9170_sta_notify,
-	.get_stats		= ar9170_get_stats,
-	.get_tx_stats		= ar9170_get_tx_stats,
-};
-
-void *ar9170_alloc(size_t priv_size)
-{
-	struct ieee80211_hw *hw;
-	struct ar9170 *ar;
-	int i;
-
-	hw = ieee80211_alloc_hw(priv_size, &ar9170_ops);
-	if (!hw)
-		return ERR_PTR(-ENOMEM);
-
-	ar = hw->priv;
-	ar->hw = hw;
-
-	mutex_init(&ar->mutex);
-	spin_lock_init(&ar->cmdlock);
-	spin_lock_init(&ar->tx_stats_lock);
-	skb_queue_head_init(&ar->global_tx_status);
-	skb_queue_head_init(&ar->global_tx_status_waste);
-	INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
-	INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
-	INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor);
-
-	/* all hw supports 2.4 GHz, so set channel to 1 by default */
-	ar->channel = &ar9170_2ghz_chantable[0];
-
-	/* first part of wiphy init */
-	ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-					 BIT(NL80211_IFTYPE_WDS) |
-					 BIT(NL80211_IFTYPE_ADHOC);
-	ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
-			 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-			 IEEE80211_HW_SIGNAL_DBM |
-			 IEEE80211_HW_NOISE_DBM;
-
-	ar->hw->queues = __AR9170_NUM_TXQ;
-	ar->hw->extra_tx_headroom = 8;
-	ar->hw->sta_data_size = sizeof(struct ar9170_sta_info);
-
-	ar->hw->max_rates = 1;
-	ar->hw->max_rate_tries = 3;
-
-	for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
-		ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
-
-	return ar;
-}
-
-static int ar9170_read_eeprom(struct ar9170 *ar)
-{
-#define RW	8	/* number of words to read at once */
-#define RB	(sizeof(u32) * RW)
-	DECLARE_MAC_BUF(mbuf);
-	u8 *eeprom = (void *)&ar->eeprom;
-	u8 *addr = ar->eeprom.mac_address;
-	__le32 offsets[RW];
-	int i, j, err, bands = 0;
-
-	BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
-
-	BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4);
-#ifndef __CHECKER__
-	/* don't want to handle trailing remains */
-	BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
-#endif
-
-	for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
-		for (j = 0; j < RW; j++)
-			offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
-						 RB * i + 4 * j);
-
-		err = ar->exec_cmd(ar, AR9170_CMD_RREG,
-				   RB, (u8 *) &offsets,
-				   RB, eeprom + RB * i);
-		if (err)
-			return err;
-	}
-
-#undef RW
-#undef RB
-
-	if (ar->eeprom.length == cpu_to_le16(0xFFFF))
-		return -ENODATA;
-
-	if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
-		ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz;
-		bands++;
-	}
-	if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
-		ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz;
-		bands++;
-	}
-	/*
-	 * I measured this, a bandswitch takes roughly
-	 * 135 ms and a frequency switch about 80.
-	 *
-	 * FIXME: measure these values again once EEPROM settings
-	 *	  are used, that will influence them!
-	 */
-	if (bands == 2)
-		ar->hw->channel_change_time = 135 * 1000;
-	else
-		ar->hw->channel_change_time = 80 * 1000;
-
-	/* second part of wiphy init */
-	SET_IEEE80211_PERM_ADDR(ar->hw, addr);
-
-	return bands ? 0 : -EINVAL;
-}
-
-int ar9170_register(struct ar9170 *ar, struct device *pdev)
-{
-	int err;
-
-	/* try to read EEPROM, init MAC addr */
-	err = ar9170_read_eeprom(ar);
-	if (err)
-		goto err_out;
-
-	err = ieee80211_register_hw(ar->hw);
-	if (err)
-		goto err_out;
-
-	err = ar9170_init_leds(ar);
-	if (err)
-		goto err_unreg;
-
-#ifdef CONFIG_AR9170_LEDS
-	err = ar9170_register_leds(ar);
-	if (err)
-		goto err_unreg;
-#endif /* CONFIG_AR9170_LEDS */
-
-	dev_info(pdev, "Atheros AR9170 is registered as '%s'\n",
-		 wiphy_name(ar->hw->wiphy));
-
-	return err;
-
-err_unreg:
-	ieee80211_unregister_hw(ar->hw);
-
-err_out:
-	return err;
-}
-
-void ar9170_unregister(struct ar9170 *ar)
-{
-#ifdef CONFIG_AR9170_LEDS
-	ar9170_unregister_leds(ar);
-#endif /* CONFIG_AR9170_LEDS */
-
-	ieee80211_unregister_hw(ar->hw);
-	mutex_destroy(&ar->mutex);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o
-
-obj-$(CONFIG_AR9170_USB) += ar9170usb.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/phy.c linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/phy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1240 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * PHY and RF code
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/bitrev.h>
-#include "ar9170.h"
-#include "cmd.h"
-
-static int ar9170_init_power_cal(struct ar9170 *ar)
-{
-	ar9170_regwrite_begin(ar);
-
-	ar9170_regwrite(0x1bc000 + 0x993c, 0x7f);
-	ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f);
-	ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f);
-
-	ar9170_regwrite_finish();
-	return ar9170_regwrite_result();
-}
-
-struct ar9170_phy_init {
-	u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20;
-};
-
-static struct ar9170_phy_init ar5416_phy_init[] = {
-	{ 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
-	{ 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, },
-	{ 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, },
-	{ 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, },
-	{ 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, },
-	{ 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, },
-	{ 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, },
-	{ 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
-	{ 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, },
-	{ 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
-	{ 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
-	{ 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
-	{ 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, },
-	{ 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, },
-	{ 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, },
-	{ 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, },
-	{ 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, },
-	{ 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, },
-	{ 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, },
-	{ 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, },
-	{ 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, },
-	{ 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, },
-	{ 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, },
-	{ 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, },
-	{ 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, },
-	{ 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, },
-	{ 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, },
-	{ 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, },
-	{ 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, },
-	{ 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
-	{ 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
-	{ 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, },
-	{ 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, },
-	{ 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, },
-	{ 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, },
-	{ 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, },
-	{ 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, },
-	{ 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
-	{ 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, },
-	{ 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, },
-	{ 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
-	{ 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
-	{ 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, },
-	{ 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, },
-	{ 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, },
-	{ 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, },
-	{ 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, },
-	{ 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, },
-	{ 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, },
-	{ 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, },
-	{ 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, },
-	{ 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, },
-	{ 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, },
-	{ 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, },
-	{ 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, },
-	{ 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, },
-	{ 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, },
-	{ 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, },
-	{ 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, },
-	{ 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, },
-	{ 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, },
-	{ 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, },
-	{ 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, },
-	{ 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, },
-	{ 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, },
-	{ 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
-	{ 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, },
-	{ 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, },
-	{ 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, },
-	{ 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, },
-	{ 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, },
-	{ 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, },
-	{ 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, },
-	{ 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, },
-	{ 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, },
-	{ 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, },
-	{ 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, },
-	{ 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, },
-	{ 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, },
-	{ 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, },
-	{ 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, },
-	{ 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, },
-	{ 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, },
-	{ 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, },
-	{ 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, },
-	{ 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, },
-	{ 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, },
-	{ 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, },
-	{ 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, },
-	{ 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, },
-	{ 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, },
-	{ 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, },
-	{ 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, },
-	{ 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, },
-	{ 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, },
-	{ 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
-	{ 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
-	{ 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, },
-	{ 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, },
-	{ 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
-	{ 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, },
-	{ 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, },
-	{ 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, },
-	{ 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, },
-	{ 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, },
-	{ 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, },
-	{ 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, },
-	{ 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
-	{ 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, },
-	{ 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, },
-	{ 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, },
-	{ 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, },
-	{ 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, },
-	{ 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, },
-	{ 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, },
-	{ 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
-	{ 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, },
-	{ 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, },
-	{ 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, },
-	{ 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, },
-	{ 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, },
-	{ 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, },
-	{ 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, },
-	{ 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, },
-	{ 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, },
-	{ 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
-	{ 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, },
-	{ 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, },
-	{ 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, },
-	{ 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, },
-	{ 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, },
-	{ 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, },
-	{ 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, },
-	{ 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, },
-	{ 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, },
-	{ 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, },
-	{ 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
-	{ 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
-	{ 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
-	{ 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, },
-	{ 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, },
-	{ 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, },
-	{ 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
-	{ 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, },
-	{ 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, },
-	{ 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, },
-	{ 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, },
-	{ 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, },
-	{ 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, },
-	{ 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, },
-	{ 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, },
-	{ 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, },
-	{ 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, },
-	{ 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, },
-	{ 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, },
-	{ 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
-	{ 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
-	{ 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, },
-	{ 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, },
-	{ 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, },
-	{ 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, },
-	{ 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
-	{ 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, },
-	{ 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
-	{ 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, },
-	{ 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, },
-	{ 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, },
-	{ 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, },
-	{ 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, },
-	{ 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, },
-	{ 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, },
-	{ 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, },
-	{ 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, },
-	{ 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, },
-	{ 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, },
-	{ 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, },
-	{ 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
-	{ 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
-	{ 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
-	{ 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, },
-	{ 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, },
-	{ 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, },
-	{ 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
-	{ 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, },
-	{ 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
-	{ 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
-	{ 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
-	{ 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
-	{ 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, },
-	{ 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
-	{ 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
-	{ 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
-	{ 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
-	{ 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
-	{ 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
-	{ 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
-	{ 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
-	{ 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
-	{ 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
-/*	{ 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */
-	{ 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, },
-	{ 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, },
-	{ 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, },
-	{ 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, },
-	{ 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, },
-	{ 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, },
-	{ 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, },
-	{ 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, },
-	{ 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, },
-	{ 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, },
-	{ 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, },
-	{ 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, },
-	{ 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, },
-	{ 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, },
-	{ 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, },
-	{ 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
-};
-
-int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
-{
-	int i, err;
-	u32 val;
-	bool is_2ghz = band == IEEE80211_BAND_2GHZ;
-	bool is_40mhz = false; /* XXX: for now */
-
-	ar9170_regwrite_begin(ar);
-
-	for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
-		if (is_40mhz) {
-			if (is_2ghz)
-				val = ar5416_phy_init[i]._2ghz_40;
-			else
-				val = ar5416_phy_init[i]._5ghz_40;
-		} else {
-			if (is_2ghz)
-				val = ar5416_phy_init[i]._2ghz_20;
-			else
-				val = ar5416_phy_init[i]._5ghz_20;
-		}
-
-		ar9170_regwrite(ar5416_phy_init[i].reg, val);
-	}
-
-	ar9170_regwrite_finish();
-	err = ar9170_regwrite_result();
-	if (err)
-		return err;
-
-	/* XXX: use EEPROM data here! */
-
-	err = ar9170_init_power_cal(ar);
-	if (err)
-		return err;
-
-	/* XXX: remove magic! */
-	if (is_2ghz)
-		err = ar9170_write_reg(ar, 0x1d4014, 0x5163);
-	else
-		err = ar9170_write_reg(ar, 0x1d4014, 0x5143);
-
-	return err;
-}
-
-struct ar9170_rf_init {
-	u32 reg, _5ghz, _2ghz;
-};
-
-static struct ar9170_rf_init ar9170_rf_init[] = {
-     /* bank 0 */
-     { 0x1c58b0,  0x1e5795e5,  0x1e5795e5},
-     { 0x1c58e0,  0x02008020,  0x02008020},
-     /* bank 1 */
-     { 0x1c58b0,  0x02108421,  0x02108421},
-     { 0x1c58ec,  0x00000008,  0x00000008},
-     /* bank 2 */
-     { 0x1c58b0,  0x0e73ff17,  0x0e73ff17},
-     { 0x1c58e0,  0x00000420,  0x00000420},
-     /* bank 3 */
-     { 0x1c58f0,  0x01400018,  0x01c00018},
-     /* bank 4 */
-     { 0x1c58b0,  0x000001a1,  0x000001a1},
-     { 0x1c58e8,  0x00000001,  0x00000001},
-     /* bank 5 */
-     { 0x1c58b0,  0x00000013,  0x00000013},
-     { 0x1c58e4,  0x00000002,  0x00000002},
-     /* bank 6 */
-     { 0x1c58b0,  0x00000000,  0x00000000},
-     { 0x1c58b0,  0x00000000,  0x00000000},
-     { 0x1c58b0,  0x00000000,  0x00000000},
-     { 0x1c58b0,  0x00000000,  0x00000000},
-     { 0x1c58b0,  0x00000000,  0x00000000},
-     { 0x1c58b0,  0x00004000,  0x00004000},
-     { 0x1c58b0,  0x00006c00,  0x00006c00},
-     { 0x1c58b0,  0x00002c00,  0x00002c00},
-     { 0x1c58b0,  0x00004800,  0x00004800},
-     { 0x1c58b0,  0x00004000,  0x00004000},
-     { 0x1c58b0,  0x00006000,  0x00006000},
-     { 0x1c58b0,  0x00001000,  0x00001000},
-     { 0x1c58b0,  0x00004000,  0x00004000},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00087c00,  0x00087c00},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00005400,  0x00005400},
-     { 0x1c58b0,  0x00000c00,  0x00000c00},
-     { 0x1c58b0,  0x00001800,  0x00001800},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00006c00,  0x00006c00},
-     { 0x1c58b0,  0x00006c00,  0x00006c00},
-     { 0x1c58b0,  0x00007c00,  0x00007c00},
-     { 0x1c58b0,  0x00002c00,  0x00002c00},
-     { 0x1c58b0,  0x00003c00,  0x00003c00},
-     { 0x1c58b0,  0x00003800,  0x00003800},
-     { 0x1c58b0,  0x00001c00,  0x00001c00},
-     { 0x1c58b0,  0x00000800,  0x00000800},
-     { 0x1c58b0,  0x00000408,  0x00000408},
-     { 0x1c58b0,  0x00004c15,  0x00004c15},
-     { 0x1c58b0,  0x00004188,  0x00004188},
-     { 0x1c58b0,  0x0000201e,  0x0000201e},
-     { 0x1c58b0,  0x00010408,  0x00010408},
-     { 0x1c58b0,  0x00000801,  0x00000801},
-     { 0x1c58b0,  0x00000c08,  0x00000c08},
-     { 0x1c58b0,  0x0000181e,  0x0000181e},
-     { 0x1c58b0,  0x00001016,  0x00001016},
-     { 0x1c58b0,  0x00002800,  0x00002800},
-     { 0x1c58b0,  0x00004010,  0x00004010},
-     { 0x1c58b0,  0x0000081c,  0x0000081c},
-     { 0x1c58b0,  0x00000115,  0x00000115},
-     { 0x1c58b0,  0x00000015,  0x00000015},
-     { 0x1c58b0,  0x00000066,  0x00000066},
-     { 0x1c58b0,  0x0000001c,  0x0000001c},
-     { 0x1c58b0,  0x00000000,  0x00000000},
-     { 0x1c58b0,  0x00000004,  0x00000004},
-     { 0x1c58b0,  0x00000015,  0x00000015},
-     { 0x1c58b0,  0x0000001f,  0x0000001f},
-     { 0x1c58e0,  0x00000000,  0x00000400},
-     /* bank 7 */
-     { 0x1c58b0,  0x000000a0,  0x000000a0},
-     { 0x1c58b0,  0x00000000,  0x00000000},
-     { 0x1c58b0,  0x00000040,  0x00000040},
-     { 0x1c58f0,  0x0000001c,  0x0000001c},
-};
-
-static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz)
-{
-	int err, i;
-
-	ar9170_regwrite_begin(ar);
-
-	for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++)
-		ar9170_regwrite(ar9170_rf_init[i].reg,
-				band5ghz ? ar9170_rf_init[i]._5ghz
-					 : ar9170_rf_init[i]._2ghz);
-
-	ar9170_regwrite_finish();
-	err = ar9170_regwrite_result();
-	if (err)
-		printk(KERN_ERR "%s: rf init failed\n",
-		       wiphy_name(ar->hw->wiphy));
-	return err;
-}
-
-static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz,
-				    u32 freq, enum ar9170_bw bw)
-{
-	int err;
-	u32 d0, d1, td0, td1, fd0, fd1;
-	u8 chansel;
-	u8 refsel0 = 1, refsel1 = 0;
-	u8 lf_synth = 0;
-
-	switch (bw) {
-	case AR9170_BW_40_ABOVE:
-		freq += 10;
-		break;
-	case AR9170_BW_40_BELOW:
-		freq -= 10;
-		break;
-	case AR9170_BW_20:
-		break;
-	case __AR9170_NUM_BW:
-		BUG();
-	}
-
-	if (band5ghz) {
-		if (freq % 10) {
-			chansel = (freq - 4800) / 5;
-		} else {
-			chansel = ((freq - 4800) / 10) * 2;
-			refsel0 = 0;
-			refsel1 = 1;
-		}
-		chansel = byte_rev_table[chansel];
-	} else {
-		if (freq == 2484) {
-			chansel = 10 + (freq - 2274) / 5;
-			lf_synth = 1;
-		} else
-			chansel = 16 + (freq - 2272) / 5;
-		chansel *= 4;
-		chansel = byte_rev_table[chansel];
-	}
-
-	d1 =	chansel;
-	d0 =	0x21 |
-		refsel0 << 3 |
-		refsel1 << 2 |
-		lf_synth << 1;
-	td0 =	d0 & 0x1f;
-	td1 =	d1 & 0x1f;
-	fd0 =	td1 << 5 | td0;
-
-	td0 =	(d0 >> 5) & 0x7;
-	td1 =	(d1 >> 5) & 0x7;
-	fd1 =	td1 << 5 | td0;
-
-	ar9170_regwrite_begin(ar);
-
-	ar9170_regwrite(0x1c58b0, fd0);
-	ar9170_regwrite(0x1c58e8, fd1);
-
-	ar9170_regwrite_finish();
-	err = ar9170_regwrite_result();
-	if (err)
-		return err;
-
-	msleep(10);
-
-	return 0;
-}
-
-struct ar9170_phy_freq_params {
-	u8 coeff_exp;
-	u16 coeff_man;
-	u8 coeff_exp_shgi;
-	u16 coeff_man_shgi;
-};
-
-struct ar9170_phy_freq_entry {
-	u16 freq;
-	struct ar9170_phy_freq_params params[__AR9170_NUM_BW];
-};
-
-/* NB: must be in sync with channel tables in main! */
-static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = {
-/*
- *	freq,
- *		20MHz,
- *		40MHz (below),
- *		40Mhz (above),
- */
-	{ 2412, {
-		{ 3, 21737, 3, 19563, },
-		{ 3, 21827, 3, 19644, },
-		{ 3, 21647, 3, 19482, },
-	} },
-	{ 2417, {
-		{ 3, 21692, 3, 19523, },
-		{ 3, 21782, 3, 19604, },
-		{ 3, 21602, 3, 19442, },
-	} },
-	{ 2422, {
-		{ 3, 21647, 3, 19482, },
-		{ 3, 21737, 3, 19563, },
-		{ 3, 21558, 3, 19402, },
-	} },
-	{ 2427, {
-		{ 3, 21602, 3, 19442, },
-		{ 3, 21692, 3, 19523, },
-		{ 3, 21514, 3, 19362, },
-	} },
-	{ 2432, {
-		{ 3, 21558, 3, 19402, },
-		{ 3, 21647, 3, 19482, },
-		{ 3, 21470, 3, 19323, },
-	} },
-	{ 2437, {
-		{ 3, 21514, 3, 19362, },
-		{ 3, 21602, 3, 19442, },
-		{ 3, 21426, 3, 19283, },
-	} },
-	{ 2442, {
-		{ 3, 21470, 3, 19323, },
-		{ 3, 21558, 3, 19402, },
-		{ 3, 21382, 3, 19244, },
-	} },
-	{ 2447, {
-		{ 3, 21426, 3, 19283, },
-		{ 3, 21514, 3, 19362, },
-		{ 3, 21339, 3, 19205, },
-	} },
-	{ 2452, {
-		{ 3, 21382, 3, 19244, },
-		{ 3, 21470, 3, 19323, },
-		{ 3, 21295, 3, 19166, },
-	} },
-	{ 2457, {
-		{ 3, 21339, 3, 19205, },
-		{ 3, 21426, 3, 19283, },
-		{ 3, 21252, 3, 19127, },
-	} },
-	{ 2462, {
-		{ 3, 21295, 3, 19166, },
-		{ 3, 21382, 3, 19244, },
-		{ 3, 21209, 3, 19088, },
-	} },
-	{ 2467, {
-		{ 3, 21252, 3, 19127, },
-		{ 3, 21339, 3, 19205, },
-		{ 3, 21166, 3, 19050, },
-	} },
-	{ 2472, {
-		{ 3, 21209, 3, 19088, },
-		{ 3, 21295, 3, 19166, },
-		{ 3, 21124, 3, 19011, },
-	} },
-	{ 2484, {
-		{ 3, 21107, 3, 18996, },
-		{ 3, 21192, 3, 19073, },
-		{ 3, 21022, 3, 18920, },
-	} },
-	{ 4920, {
-		{ 4, 21313, 4, 19181, },
-		{ 4, 21356, 4, 19220, },
-		{ 4, 21269, 4, 19142, },
-	} },
-	{ 4940, {
-		{ 4, 21226, 4, 19104, },
-		{ 4, 21269, 4, 19142, },
-		{ 4, 21183, 4, 19065, },
-	} },
-	{ 4960, {
-		{ 4, 21141, 4, 19027, },
-		{ 4, 21183, 4, 19065, },
-		{ 4, 21098, 4, 18988, },
-	} },
-	{ 4980, {
-		{ 4, 21056, 4, 18950, },
-		{ 4, 21098, 4, 18988, },
-		{ 4, 21014, 4, 18912, },
-	} },
-	{ 5040, {
-		{ 4, 20805, 4, 18725, },
-		{ 4, 20846, 4, 18762, },
-		{ 4, 20764, 4, 18687, },
-	} },
-	{ 5060, {
-		{ 4, 20723, 4, 18651, },
-		{ 4, 20764, 4, 18687, },
-		{ 4, 20682, 4, 18614, },
-	} },
-	{ 5080, {
-		{ 4, 20641, 4, 18577, },
-		{ 4, 20682, 4, 18614, },
-		{ 4, 20601, 4, 18541, },
-	} },
-	{ 5180, {
-		{ 4, 20243, 4, 18219, },
-		{ 4, 20282, 4, 18254, },
-		{ 4, 20204, 4, 18183, },
-	} },
-	{ 5200, {
-		{ 4, 20165, 4, 18148, },
-		{ 4, 20204, 4, 18183, },
-		{ 4, 20126, 4, 18114, },
-	} },
-	{ 5220, {
-		{ 4, 20088, 4, 18079, },
-		{ 4, 20126, 4, 18114, },
-		{ 4, 20049, 4, 18044, },
-	} },
-	{ 5240, {
-		{ 4, 20011, 4, 18010, },
-		{ 4, 20049, 4, 18044, },
-		{ 4, 19973, 4, 17976, },
-	} },
-	{ 5260, {
-		{ 4, 19935, 4, 17941, },
-		{ 4, 19973, 4, 17976, },
-		{ 4, 19897, 4, 17907, },
-	} },
-	{ 5280, {
-		{ 4, 19859, 4, 17873, },
-		{ 4, 19897, 4, 17907, },
-		{ 4, 19822, 4, 17840, },
-	} },
-	{ 5300, {
-		{ 4, 19784, 4, 17806, },
-		{ 4, 19822, 4, 17840, },
-		{ 4, 19747, 4, 17772, },
-	} },
-	{ 5320, {
-		{ 4, 19710, 4, 17739, },
-		{ 4, 19747, 4, 17772, },
-		{ 4, 19673, 4, 17706, },
-	} },
-	{ 5500, {
-		{ 4, 19065, 4, 17159, },
-		{ 4, 19100, 4, 17190, },
-		{ 4, 19030, 4, 17127, },
-	} },
-	{ 5520, {
-		{ 4, 18996, 4, 17096, },
-		{ 4, 19030, 4, 17127, },
-		{ 4, 18962, 4, 17065, },
-	} },
-	{ 5540, {
-		{ 4, 18927, 4, 17035, },
-		{ 4, 18962, 4, 17065, },
-		{ 4, 18893, 4, 17004, },
-	} },
-	{ 5560, {
-		{ 4, 18859, 4, 16973, },
-		{ 4, 18893, 4, 17004, },
-		{ 4, 18825, 4, 16943, },
-	} },
-	{ 5580, {
-		{ 4, 18792, 4, 16913, },
-		{ 4, 18825, 4, 16943, },
-		{ 4, 18758, 4, 16882, },
-	} },
-	{ 5600, {
-		{ 4, 18725, 4, 16852, },
-		{ 4, 18758, 4, 16882, },
-		{ 4, 18691, 4, 16822, },
-	} },
-	{ 5620, {
-		{ 4, 18658, 4, 16792, },
-		{ 4, 18691, 4, 16822, },
-		{ 4, 18625, 4, 16762, },
-	} },
-	{ 5640, {
-		{ 4, 18592, 4, 16733, },
-		{ 4, 18625, 4, 16762, },
-		{ 4, 18559, 4, 16703, },
-	} },
-	{ 5660, {
-		{ 4, 18526, 4, 16673, },
-		{ 4, 18559, 4, 16703, },
-		{ 4, 18493, 4, 16644, },
-	} },
-	{ 5680, {
-		{ 4, 18461, 4, 16615, },
-		{ 4, 18493, 4, 16644, },
-		{ 4, 18428, 4, 16586, },
-	} },
-	{ 5700, {
-		{ 4, 18396, 4, 16556, },
-		{ 4, 18428, 4, 16586, },
-		{ 4, 18364, 4, 16527, },
-	} },
-	{ 5745, {
-		{ 4, 18252, 4, 16427, },
-		{ 4, 18284, 4, 16455, },
-		{ 4, 18220, 4, 16398, },
-	} },
-	{ 5765, {
-		{ 4, 18189, 5, 32740, },
-		{ 4, 18220, 4, 16398, },
-		{ 4, 18157, 5, 32683, },
-	} },
-	{ 5785, {
-		{ 4, 18126, 5, 32626, },
-		{ 4, 18157, 5, 32683, },
-		{ 4, 18094, 5, 32570, },
-	} },
-	{ 5805, {
-		{ 4, 18063, 5, 32514, },
-		{ 4, 18094, 5, 32570, },
-		{ 4, 18032, 5, 32458, },
-	} },
-	{ 5825, {
-		{ 4, 18001, 5, 32402, },
-		{ 4, 18032, 5, 32458, },
-		{ 4, 17970, 5, 32347, },
-	} },
-	{ 5170, {
-		{ 4, 20282, 4, 18254, },
-		{ 4, 20321, 4, 18289, },
-		{ 4, 20243, 4, 18219, },
-	} },
-	{ 5190, {
-		{ 4, 20204, 4, 18183, },
-		{ 4, 20243, 4, 18219, },
-		{ 4, 20165, 4, 18148, },
-	} },
-	{ 5210, {
-		{ 4, 20126, 4, 18114, },
-		{ 4, 20165, 4, 18148, },
-		{ 4, 20088, 4, 18079, },
-	} },
-	{ 5230, {
-		{ 4, 20049, 4, 18044, },
-		{ 4, 20088, 4, 18079, },
-		{ 4, 20011, 4, 18010, },
-	} },
-};
-
-static const struct ar9170_phy_freq_params *
-ar9170_get_hw_dyn_params(struct ieee80211_channel *channel,
-			 enum ar9170_bw bw)
-{
-	unsigned int chanidx = 0;
-	u16 freq = 2412;
-
-	if (channel) {
-		chanidx = channel->hw_value;
-		freq = channel->center_freq;
-	}
-
-	BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params));
-
-	BUILD_BUG_ON(__AR9170_NUM_BW != 3);
-
-	WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq);
-
-	return &ar9170_phy_freq_params[chanidx].params[bw];
-}
-
-
-int ar9170_init_rf(struct ar9170 *ar)
-{
-	const struct ar9170_phy_freq_params *freqpar;
-	__le32 cmd[7];
-	int err;
-
-	err = ar9170_init_rf_banks_0_7(ar, false);
-	if (err)
-		return err;
-
-	err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20);
-	if (err)
-		return err;
-
-	freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20);
-
-	cmd[0] = cpu_to_le32(2412 * 1000);
-	cmd[1] = cpu_to_le32(0);
-	cmd[2] = cpu_to_le32(1);
-	cmd[3] = cpu_to_le32(freqpar->coeff_exp);
-	cmd[4] = cpu_to_le32(freqpar->coeff_man);
-	cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi);
-	cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi);
-
-	/* RF_INIT echoes the command back to us */
-	err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT,
-			   sizeof(cmd), (u8 *)cmd,
-			   sizeof(cmd), (u8 *)cmd);
-	if (err)
-		return err;
-
-	msleep(1000);
-
-	return ar9170_echo_test(ar, 0xaabbccdd);
-}
-
-static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f)
-{
-	int idx = nfreqs - 2;
-
-	while (idx >= 0) {
-		if (f >= freqs[idx])
-			return idx;
-		idx--;
-	}
-
-	return 0;
-}
-
-static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
-{
-	/* nothing to interpolate, it's horizontal */
-	if (y2 == y1)
-		return y1;
-
-	/* check if we hit one of the edges */
-	if (x == x1)
-		return y1;
-	if (x == x2)
-		return y2;
-
-	/* x1 == x2 is bad, hopefully == x */
-	if (x2 == x1)
-		return y1;
-
-	return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1));
-}
-
-static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
-{
-#define SHIFT		8
-	s32 y;
-
-	y = ar9170_interpolate_s32(x << SHIFT,
-				   x1 << SHIFT, y1 << SHIFT,
-				   x2 << SHIFT, y2 << SHIFT);
-
-	/*
-	 * XXX: unwrap this expression
-	 *	Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
-	 *	Can we rely on the compiler to optimise away the div?
-	 */
-	return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
-#undef SHIFT
-}
-
-static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
-{
-	struct ar9170_calibration_target_power_legacy *ctpl;
-	struct ar9170_calibration_target_power_ht *ctph;
-	u8 *ctpres;
-	int ntargets;
-	int idx, i, n;
-	u8 ackpower, ackchains, f;
-	u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS];
-
-	if (freq < 3000)
-		f = freq - 2300;
-	else
-		f = (freq - 4800)/5;
-
-	/*
-	 * cycle through the various modes
-	 *
-	 * legacy modes first: 5G, 2G CCK, 2G OFDM
-	 */
-	for (i = 0; i < 3; i++) {
-		switch (i) {
-		case 0: /* 5 GHz legacy */
-			ctpl = &ar->eeprom.cal_tgt_pwr_5G[0];
-			ntargets = AR5416_NUM_5G_TARGET_PWRS;
-			ctpres = ar->power_5G_leg;
-			break;
-		case 1: /* 2.4 GHz CCK */
-			ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0];
-			ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS;
-			ctpres = ar->power_2G_cck;
-			break;
-		case 2: /* 2.4 GHz OFDM */
-			ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0];
-			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
-			ctpres = ar->power_2G_ofdm;
-			break;
-		default:
-			BUG();
-		}
-
-		for (n = 0; n < ntargets; n++) {
-			if (ctpl[n].freq == 0xff)
-				break;
-			pwr_freqs[n] = ctpl[n].freq;
-		}
-		ntargets = n;
-		idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f);
-		for (n = 0; n < 4; n++)
-			ctpres[n] = ar9170_interpolate_u8(
-					f,
-					ctpl[idx + 0].freq,
-					ctpl[idx + 0].power[n],
-					ctpl[idx + 1].freq,
-					ctpl[idx + 1].power[n]);
-	}
-
-	/*
-	 * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40
-	 */
-	for (i = 0; i < 4; i++) {
-		switch (i) {
-		case 0: /* 5 GHz HT 20 */
-			ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0];
-			ntargets = AR5416_NUM_5G_TARGET_PWRS;
-			ctpres = ar->power_5G_ht20;
-			break;
-		case 1: /* 5 GHz HT 40 */
-			ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0];
-			ntargets = AR5416_NUM_5G_TARGET_PWRS;
-			ctpres = ar->power_5G_ht40;
-			break;
-		case 2: /* 2.4 GHz HT 20 */
-			ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0];
-			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
-			ctpres = ar->power_2G_ht20;
-			break;
-		case 3: /* 2.4 GHz HT 40 */
-			ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0];
-			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
-			ctpres = ar->power_2G_ht40;
-			break;
-		default:
-			BUG();
-		}
-
-		for (n = 0; n < ntargets; n++) {
-			if (ctph[n].freq == 0xff)
-				break;
-			pwr_freqs[n] = ctph[n].freq;
-		}
-		ntargets = n;
-		idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f);
-		for (n = 0; n < 8; n++)
-			ctpres[n] = ar9170_interpolate_u8(
-					f,
-					ctph[idx + 0].freq,
-					ctph[idx + 0].power[n],
-					ctph[idx + 1].freq,
-					ctph[idx + 1].power[n]);
-	}
-
-	/* set ACK/CTS TX power */
-	ar9170_regwrite_begin(ar);
-
-	if (ar->eeprom.tx_mask != 1)
-		ackchains = AR9170_TX_PHY_TXCHAIN_2;
-	else
-		ackchains = AR9170_TX_PHY_TXCHAIN_1;
-
-	if (freq < 3000)
-		ackpower = ar->power_2G_ofdm[0] & 0x3f;
-	else
-		ackpower = ar->power_5G_leg[0] & 0x3f;
-
-	ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26);
-	ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 |
-				  ackpower << 21 | ackchains << 27);
-
-	ar9170_regwrite_finish();
-	return ar9170_regwrite_result();
-}
-
-static int ar9170_calc_noise_dbm(u32 raw_noise)
-{
-	if (raw_noise & 0x100)
-		return ~((raw_noise & 0x0ff) >> 1);
-	else
-		return (raw_noise & 0xff) >> 1;
-}
-
-int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
-		       enum ar9170_rf_init_mode rfi, enum ar9170_bw bw)
-{
-	const struct ar9170_phy_freq_params *freqpar;
-	u32 cmd, tmp, offs;
-	__le32 vals[8];
-	int i, err;
-	bool bandswitch;
-
-	/* clear BB heavy clip enable */
-	err = ar9170_write_reg(ar, 0x1c59e0, 0x200);
-	if (err)
-		return err;
-
-	/* may be NULL at first setup */
-	if (ar->channel)
-		bandswitch = ar->channel->band != channel->band;
-	else
-		bandswitch = true;
-
-	/* HW workaround */
-	if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
-	    channel->center_freq <= 2417)
-		bandswitch = true;
-
-	err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL);
-	if (err)
-		return err;
-
-	if (rfi != AR9170_RFI_NONE || bandswitch) {
-		u32 val = 0x400;
-
-		if (rfi == AR9170_RFI_COLD)
-			val = 0x800;
-
-		/* warm/cold reset BB/ADDA */
-		err = ar9170_write_reg(ar, 0x1d4004, val);
-		if (err)
-			return err;
-
-		err = ar9170_write_reg(ar, 0x1d4004, 0x0);
-		if (err)
-			return err;
-
-		err = ar9170_init_phy(ar, channel->band);
-		if (err)
-			return err;
-
-		err = ar9170_init_rf_banks_0_7(ar,
-			channel->band == IEEE80211_BAND_5GHZ);
-		if (err)
-			return err;
-
-		cmd = AR9170_CMD_RF_INIT;
-	} else {
-		cmd = AR9170_CMD_FREQUENCY;
-	}
-
-	err = ar9170_init_rf_bank4_pwr(ar,
-		channel->band == IEEE80211_BAND_5GHZ,
-		channel->center_freq, bw);
-	if (err)
-		return err;
-
-	switch (bw) {
-	case AR9170_BW_20:
-		tmp = 0x240;
-		offs = 0;
-		break;
-	case AR9170_BW_40_BELOW:
-		tmp = 0x2c4;
-		offs = 3;
-		break;
-	case AR9170_BW_40_ABOVE:
-		tmp = 0x2d4;
-		offs = 1;
-		break;
-	default:
-		BUG();
-		return -ENOSYS;
-	}
-
-	if (0 /* 2 streams capable */)
-		tmp |= 0x100;
-
-	err = ar9170_write_reg(ar, 0x1c5804, tmp);
-	if (err)
-		return err;
-
-	err = ar9170_set_power_cal(ar, channel->center_freq, bw);
-	if (err)
-		return err;
-
-	freqpar = ar9170_get_hw_dyn_params(channel, bw);
-
-	vals[0] = cpu_to_le32(channel->center_freq * 1000);
-	vals[1] = cpu_to_le32(bw == AR9170_BW_20 ? 0 : 1);
-	vals[2] = cpu_to_le32(offs << 2 | 1);
-	vals[3] = cpu_to_le32(freqpar->coeff_exp);
-	vals[4] = cpu_to_le32(freqpar->coeff_man);
-	vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi);
-	vals[6] = cpu_to_le32(freqpar->coeff_man_shgi);
-	vals[7] = cpu_to_le32(1000);
-
-	err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals,
-			   sizeof(vals), (u8 *)vals);
-	if (err)
-		return err;
-
-	for (i = 0; i < 2; i++) {
-		ar->noise[i] = ar9170_calc_noise_dbm(
-				(le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff);
-
-		ar->noise[i + 2] = ar9170_calc_noise_dbm(
-				    (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff);
-	}
-
-	ar->channel = channel;
-	return 0;
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/usb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/usb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,822 +0,0 @@
-/*
- * Atheros AR9170 driver
- *
- * USB - frontend
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, Christian Lamparter <chunkeey@web.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.
- *
- * 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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <net/mac80211.h>
-#include "ar9170.h"
-#include "cmd.h"
-#include "hw.h"
-#include "usb.h"
-
-MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
-MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
-MODULE_FIRMWARE("ar9170-1.fw");
-MODULE_FIRMWARE("ar9170-2.fw");
-
-static struct usb_device_id ar9170_usb_ids[] = {
-	/* Atheros 9170 */
-	{ USB_DEVICE(0x0cf3, 0x9170) },
-	/* Atheros TG121N */
-	{ USB_DEVICE(0x0cf3, 0x1001) },
-	/* Cace Airpcap NX */
-	{ USB_DEVICE(0xcace, 0x0300) },
-	/* D-Link DWA 160A */
-	{ USB_DEVICE(0x07d1, 0x3c10) },
-	/* Netgear WNDA3100 */
-	{ USB_DEVICE(0x0846, 0x9010) },
-	/* Netgear WN111 v2 */
-	{ USB_DEVICE(0x0846, 0x9001) },
-	/* Zydas ZD1221 */
-	{ USB_DEVICE(0x0ace, 0x1221) },
-	/* ZyXEL NWD271N */
-	{ USB_DEVICE(0x0586, 0x3417) },
-	/* Z-Com UB81 BG */
-	{ USB_DEVICE(0x0cde, 0x0023) },
-	/* Z-Com UB82 ABG */
-	{ USB_DEVICE(0x0cde, 0x0026) },
-	/* Arcadyan WN7512 */
-	{ USB_DEVICE(0x083a, 0xf522) },
-	/* Planex GWUS300 */
-	{ USB_DEVICE(0x2019, 0x5304) },
-	/* IO-Data WNGDNUS2 */
-	{ USB_DEVICE(0x04bb, 0x093f) },
-
-	/* terminate */
-	{}
-};
-MODULE_DEVICE_TABLE(usb, ar9170_usb_ids);
-
-static void ar9170_usb_tx_urb_complete_free(struct urb *urb)
-{
-	struct sk_buff *skb = urb->context;
-	struct ar9170_usb *aru = (struct ar9170_usb *)
-	      usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
-
-	if (!aru) {
-		dev_kfree_skb_irq(skb);
-		return ;
-	}
-
-	ar9170_handle_tx_status(&aru->common, skb, false,
-				AR9170_TX_STATUS_COMPLETE);
-}
-
-static void ar9170_usb_tx_urb_complete(struct urb *urb)
-{
-}
-
-static void ar9170_usb_irq_completed(struct urb *urb)
-{
-	struct ar9170_usb *aru = urb->context;
-
-	switch (urb->status) {
-	/* everything is fine */
-	case 0:
-		break;
-
-	/* disconnect */
-	case -ENOENT:
-	case -ECONNRESET:
-	case -ENODEV:
-	case -ESHUTDOWN:
-		goto free;
-
-	default:
-		goto resubmit;
-	}
-
-	print_hex_dump_bytes("ar9170 irq: ", DUMP_PREFIX_OFFSET,
-			     urb->transfer_buffer, urb->actual_length);
-
-resubmit:
-	usb_anchor_urb(urb, &aru->rx_submitted);
-	if (usb_submit_urb(urb, GFP_ATOMIC)) {
-		usb_unanchor_urb(urb);
-		goto free;
-	}
-
-	return;
-
-free:
-	usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
-}
-
-static void ar9170_usb_rx_completed(struct urb *urb)
-{
-	struct sk_buff *skb = urb->context;
-	struct ar9170_usb *aru = (struct ar9170_usb *)
-		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
-	int err;
-
-	if (!aru)
-		goto free;
-
-	switch (urb->status) {
-	/* everything is fine */
-	case 0:
-		break;
-
-	/* disconnect */
-	case -ENOENT:
-	case -ECONNRESET:
-	case -ENODEV:
-	case -ESHUTDOWN:
-		goto free;
-
-	default:
-		goto resubmit;
-	}
-
-	skb_put(skb, urb->actual_length);
-	ar9170_rx(&aru->common, skb);
-
-resubmit:
-	skb_reset_tail_pointer(skb);
-	skb_trim(skb, 0);
-
-	usb_anchor_urb(urb, &aru->rx_submitted);
-	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (err) {
-		usb_unanchor_urb(urb);
-		dev_kfree_skb_irq(skb);
-	}
-
-	return ;
-
-free:
-	dev_kfree_skb_irq(skb);
-	return;
-}
-
-static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru,
-				  struct urb *urb, gfp_t gfp)
-{
-	struct sk_buff *skb;
-
-	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp);
-	if (!skb)
-		return -ENOMEM;
-
-	/* reserve some space for mac80211's radiotap */
-	skb_reserve(skb, 32);
-
-	usb_fill_bulk_urb(urb, aru->udev,
-			  usb_rcvbulkpipe(aru->udev, AR9170_EP_RX),
-			  skb->data, min(skb_tailroom(skb),
-			  AR9170_MAX_RX_BUFFER_SIZE),
-			  ar9170_usb_rx_completed, skb);
-
-	return 0;
-}
-
-static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
-{
-	struct urb *urb = NULL;
-	void *ibuf;
-	int err = -ENOMEM;
-
-	/* initialize interrupt endpoint */
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		goto out;
-
-	ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
-	if (!ibuf)
-		goto out;
-
-	usb_fill_int_urb(urb, aru->udev,
-			 usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf,
-			 64, ar9170_usb_irq_completed, aru, 1);
-	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	usb_anchor_urb(urb, &aru->rx_submitted);
-	err = usb_submit_urb(urb, GFP_KERNEL);
-	if (err) {
-		usb_unanchor_urb(urb);
-		usb_buffer_free(aru->udev, 64, urb->transfer_buffer,
-				urb->transfer_dma);
-	}
-
-out:
-	usb_free_urb(urb);
-	return err;
-}
-
-static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru)
-{
-	struct urb *urb;
-	int i;
-	int err = -EINVAL;
-
-	for (i = 0; i < AR9170_NUM_RX_URBS; i++) {
-		err = -ENOMEM;
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb)
-			goto err_out;
-
-		err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL);
-		if (err) {
-			usb_free_urb(urb);
-			goto err_out;
-		}
-
-		usb_anchor_urb(urb, &aru->rx_submitted);
-		err = usb_submit_urb(urb, GFP_KERNEL);
-		if (err) {
-			usb_unanchor_urb(urb);
-			dev_kfree_skb_any((void *) urb->transfer_buffer);
-			usb_free_urb(urb);
-			goto err_out;
-		}
-		usb_free_urb(urb);
-	}
-
-	/* the device now waiting for a firmware. */
-	aru->common.state = AR9170_IDLE;
-	return 0;
-
-err_out:
-
-	usb_kill_anchored_urbs(&aru->rx_submitted);
-	return err;
-}
-
-static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru)
-{
-	int ret;
-
-	aru->common.state = AR9170_UNKNOWN_STATE;
-
-	usb_unlink_anchored_urbs(&aru->tx_submitted);
-
-	/* give the LED OFF command and the deauth frame a chance to air. */
-	ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
-					    msecs_to_jiffies(100));
-	if (ret == 0)
-		dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
-	usb_poison_anchored_urbs(&aru->tx_submitted);
-
-	usb_poison_anchored_urbs(&aru->rx_submitted);
-}
-
-static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd,
-			       unsigned int plen, void *payload,
-			       unsigned int outlen, void *out)
-{
-	struct ar9170_usb *aru = (void *) ar;
-	struct urb *urb = NULL;
-	unsigned long flags;
-	int err = -ENOMEM;
-
-	if (unlikely(!IS_ACCEPTING_CMD(ar)))
-		return -EPERM;
-
-	if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4))
-		return -EINVAL;
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (unlikely(!urb))
-		goto err_free;
-
-	ar->cmdbuf[0] = cpu_to_le32(plen);
-	ar->cmdbuf[0] |= cpu_to_le32(cmd << 8);
-	/* writing multiple regs fills this buffer already */
-	if (plen && payload != (u8 *)(&ar->cmdbuf[1]))
-		memcpy(&ar->cmdbuf[1], payload, plen);
-
-	spin_lock_irqsave(&aru->common.cmdlock, flags);
-	aru->readbuf = (u8 *)out;
-	aru->readlen = outlen;
-	spin_unlock_irqrestore(&aru->common.cmdlock, flags);
-
-	usb_fill_int_urb(urb, aru->udev,
-			 usb_sndbulkpipe(aru->udev, AR9170_EP_CMD),
-			 aru->common.cmdbuf, plen + 4,
-			 ar9170_usb_tx_urb_complete, NULL, 1);
-
-	usb_anchor_urb(urb, &aru->tx_submitted);
-	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (err) {
-		usb_unanchor_urb(urb);
-		usb_free_urb(urb);
-		goto err_unbuf;
-	}
-	usb_free_urb(urb);
-
-	err = wait_for_completion_timeout(&aru->cmd_wait, HZ);
-	if (err == 0) {
-		err = -ETIMEDOUT;
-		goto err_unbuf;
-	}
-
-	if (outlen >= 0 && aru->readlen != outlen) {
-		err = -EMSGSIZE;
-		goto err_unbuf;
-	}
-
-	return 0;
-
-err_unbuf:
-	/* Maybe the device was removed in the second we were waiting? */
-	if (IS_STARTED(ar)) {
-		dev_err(&aru->udev->dev, "no command feedback "
-					 "received (%d).\n", err);
-
-		/* provide some maybe useful debug information */
-		print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE,
-				     aru->common.cmdbuf, plen + 4);
-		dump_stack();
-	}
-
-	/* invalidate to avoid completing the next prematurely */
-	spin_lock_irqsave(&aru->common.cmdlock, flags);
-	aru->readbuf = NULL;
-	aru->readlen = 0;
-	spin_unlock_irqrestore(&aru->common.cmdlock, flags);
-
-err_free:
-
-	return err;
-}
-
-static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb,
-			 bool txstatus_needed, unsigned int extra_len)
-{
-	struct ar9170_usb *aru = (struct ar9170_usb *) ar;
-	struct urb *urb;
-	int err;
-
-	if (unlikely(!IS_STARTED(ar))) {
-		/* Seriously, what were you drink... err... thinking!? */
-		return -EPERM;
-	}
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (unlikely(!urb))
-		return -ENOMEM;
-
-	usb_fill_bulk_urb(urb, aru->udev,
-			  usb_sndbulkpipe(aru->udev, AR9170_EP_TX),
-			  skb->data, skb->len + extra_len, (txstatus_needed ?
-			  ar9170_usb_tx_urb_complete :
-			  ar9170_usb_tx_urb_complete_free), skb);
-	urb->transfer_flags |= URB_ZERO_PACKET;
-
-	usb_anchor_urb(urb, &aru->tx_submitted);
-	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (unlikely(err))
-		usb_unanchor_urb(urb);
-
-	usb_free_urb(urb);
-	return err;
-}
-
-static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer)
-{
-	struct ar9170_usb *aru = (void *) ar;
-	unsigned long flags;
-	u32 in, out;
-
-	if (!buffer)
-		return ;
-
-	in = le32_to_cpup((__le32 *)buffer);
-	out = le32_to_cpu(ar->cmdbuf[0]);
-
-	/* mask off length byte */
-	out &= ~0xFF;
-
-	if (aru->readlen >= 0) {
-		/* add expected length */
-		out |= aru->readlen;
-	} else {
-		/* add obtained length */
-		out |= in & 0xFF;
-	}
-
-	/*
-	 * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response
-	 * length and we cannot predict the correct length in advance.
-	 * So we only check if we provided enough space for the data.
-	 */
-	if (unlikely(out < in)) {
-		dev_warn(&aru->udev->dev, "received invalid command response "
-					  "got %d bytes, instead of %d bytes "
-					  "and the resp length is %d bytes\n",
-			 in, out, len);
-		print_hex_dump_bytes("ar9170 invalid resp: ",
-				     DUMP_PREFIX_OFFSET, buffer, len);
-		/*
-		 * Do not complete, then the command times out,
-		 * and we get a stack trace from there.
-		 */
-		return ;
-	}
-
-	spin_lock_irqsave(&aru->common.cmdlock, flags);
-	if (aru->readbuf && len > 0) {
-		memcpy(aru->readbuf, buffer + 4, len - 4);
-		aru->readbuf = NULL;
-	}
-	complete(&aru->cmd_wait);
-	spin_unlock_irqrestore(&aru->common.cmdlock, flags);
-}
-
-static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data,
-			     size_t len, u32 addr, bool complete)
-{
-	int transfer, err;
-	u8 *buf = kmalloc(4096, GFP_KERNEL);
-
-	if (!buf)
-		return -ENOMEM;
-
-	while (len) {
-		transfer = min_t(int, len, 4096);
-		memcpy(buf, data, transfer);
-
-		err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0),
-				      0x30 /* FW DL */, 0x40 | USB_DIR_OUT,
-				      addr >> 8, 0, buf, transfer, 1000);
-
-		if (err < 0) {
-			kfree(buf);
-			return err;
-		}
-
-		len -= transfer;
-		data += transfer;
-		addr += transfer;
-	}
-	kfree(buf);
-
-	if (complete) {
-		err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0),
-				      0x31 /* FW DL COMPLETE */,
-				      0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000);
-	}
-
-	return 0;
-}
-
-static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
-{
-	int err = 0;
-
-	err = request_firmware(&aru->init_values, "ar9170-1.fw",
-			       &aru->udev->dev);
-	if (err) {
-		dev_err(&aru->udev->dev, "file with init values not found.\n");
-		return err;
-	}
-
-	err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
-	if (err) {
-		release_firmware(aru->init_values);
-		dev_err(&aru->udev->dev, "firmware file not found.\n");
-		return err;
-	}
-
-	return err;
-}
-
-static int ar9170_usb_reset(struct ar9170_usb *aru)
-{
-	int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING);
-
-	if (lock) {
-		ret = usb_lock_device_for_reset(aru->udev, aru->intf);
-		if (ret < 0) {
-			dev_err(&aru->udev->dev, "unable to lock device "
-				"for reset (%d).\n", ret);
-			return ret;
-		}
-	}
-
-	ret = usb_reset_device(aru->udev);
-	if (lock)
-		usb_unlock_device(aru->udev);
-
-	/* let it rest - for a second - */
-	msleep(1000);
-
-	return ret;
-}
-
-static int ar9170_usb_upload_firmware(struct ar9170_usb *aru)
-{
-	int err;
-
-	/* First, upload initial values to device RAM */
-	err = ar9170_usb_upload(aru, aru->init_values->data,
-				aru->init_values->size, 0x102800, false);
-	if (err) {
-		dev_err(&aru->udev->dev, "firmware part 1 "
-			"upload failed (%d).\n", err);
-		return err;
-	}
-
-	/* Then, upload the firmware itself and start it */
-	return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size,
-				0x200000, true);
-}
-
-static int ar9170_usb_init_transport(struct ar9170_usb *aru)
-{
-	struct ar9170 *ar = (void *) &aru->common;
-	int err;
-
-	ar9170_regwrite_begin(ar);
-
-	/* Set USB Rx stream mode MAX packet number to 2 */
-	ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4);
-
-	/* Set USB Rx stream mode timeout to 10us */
-	ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80);
-
-	ar9170_regwrite_finish();
-
-	err = ar9170_regwrite_result();
-	if (err)
-		dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err);
-
-	return err;
-}
-
-static void ar9170_usb_stop(struct ar9170 *ar)
-{
-	struct ar9170_usb *aru = (void *) ar;
-	int ret;
-
-	if (IS_ACCEPTING_CMD(ar))
-		aru->common.state = AR9170_STOPPED;
-
-	/* lets wait a while until the tx - queues are dried out */
-	ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
-					    msecs_to_jiffies(1000));
-	if (ret == 0)
-		dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
-
-	usb_poison_anchored_urbs(&aru->tx_submitted);
-
-	/*
-	 * Note:
-	 * So far we freed all tx urbs, but we won't dare to touch any rx urbs.
-	 * Else we would end up with a unresponsive device...
-	 */
-}
-
-static int ar9170_usb_open(struct ar9170 *ar)
-{
-	struct ar9170_usb *aru = (void *) ar;
-	int err;
-
-	usb_unpoison_anchored_urbs(&aru->tx_submitted);
-	err = ar9170_usb_init_transport(aru);
-	if (err) {
-		usb_poison_anchored_urbs(&aru->tx_submitted);
-		return err;
-	}
-
-	aru->common.state = AR9170_IDLE;
-	return 0;
-}
-
-static int ar9170_usb_init_device(struct ar9170_usb *aru)
-{
-	int err;
-
-	err = ar9170_usb_alloc_rx_irq_urb(aru);
-	if (err)
-		goto err_out;
-
-	err = ar9170_usb_alloc_rx_bulk_urbs(aru);
-	if (err)
-		goto err_unrx;
-
-	err = ar9170_usb_upload_firmware(aru);
-	if (err) {
-		err = ar9170_echo_test(&aru->common, 0x60d43110);
-		if (err) {
-			/* force user invention, by disabling the device */
-			err = usb_driver_set_configuration(aru->udev, -1);
-			dev_err(&aru->udev->dev, "device is in a bad state. "
-						 "please reconnect it!\n");
-			goto err_unrx;
-		}
-	}
-
-	return 0;
-
-err_unrx:
-	ar9170_usb_cancel_urbs(aru);
-
-err_out:
-	return err;
-}
-
-static int ar9170_usb_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
-{
-	struct ar9170_usb *aru;
-	struct ar9170 *ar;
-	struct usb_device *udev;
-	int err;
-
-	aru = ar9170_alloc(sizeof(*aru));
-	if (IS_ERR(aru)) {
-		err = PTR_ERR(aru);
-		goto out;
-	}
-
-	udev = interface_to_usbdev(intf);
-	usb_get_dev(udev);
-	aru->udev = udev;
-	aru->intf = intf;
-	ar = &aru->common;
-
-	usb_set_intfdata(intf, aru);
-	SET_IEEE80211_DEV(ar->hw, &udev->dev);
-
-	init_usb_anchor(&aru->rx_submitted);
-	init_usb_anchor(&aru->tx_submitted);
-	init_completion(&aru->cmd_wait);
-
-	aru->common.stop = ar9170_usb_stop;
-	aru->common.open = ar9170_usb_open;
-	aru->common.tx = ar9170_usb_tx;
-	aru->common.exec_cmd = ar9170_usb_exec_cmd;
-	aru->common.callback_cmd = ar9170_usb_callback_cmd;
-
-	err = ar9170_usb_reset(aru);
-	if (err)
-		goto err_freehw;
-
-	err = ar9170_usb_request_firmware(aru);
-	if (err)
-		goto err_freehw;
-
-	err = ar9170_usb_init_device(aru);
-	if (err)
-		goto err_freefw;
-
-	err = ar9170_usb_open(ar);
-	if (err)
-		goto err_unrx;
-
-	err = ar9170_register(ar, &udev->dev);
-
-	ar9170_usb_stop(ar);
-	if (err)
-		goto err_unrx;
-
-	return 0;
-
-err_unrx:
-	ar9170_usb_cancel_urbs(aru);
-
-err_freefw:
-	release_firmware(aru->init_values);
-	release_firmware(aru->firmware);
-
-err_freehw:
-	usb_set_intfdata(intf, NULL);
-	usb_put_dev(udev);
-	ieee80211_free_hw(ar->hw);
-out:
-	return err;
-}
-
-static void ar9170_usb_disconnect(struct usb_interface *intf)
-{
-	struct ar9170_usb *aru = usb_get_intfdata(intf);
-
-	if (!aru)
-		return;
-
-	aru->common.state = AR9170_IDLE;
-	ar9170_unregister(&aru->common);
-	ar9170_usb_cancel_urbs(aru);
-
-	release_firmware(aru->init_values);
-	release_firmware(aru->firmware);
-
-	usb_put_dev(aru->udev);
-	usb_set_intfdata(intf, NULL);
-	ieee80211_free_hw(aru->common.hw);
-}
-
-#ifdef CONFIG_PM
-static int ar9170_suspend(struct usb_interface *intf,
-			  pm_message_t  message)
-{
-	struct ar9170_usb *aru = usb_get_intfdata(intf);
-
-	if (!aru)
-		return -ENODEV;
-
-	aru->common.state = AR9170_IDLE;
-	ar9170_usb_cancel_urbs(aru);
-
-	return 0;
-}
-
-static int ar9170_resume(struct usb_interface *intf)
-{
-	struct ar9170_usb *aru = usb_get_intfdata(intf);
-	int err;
-
-	if (!aru)
-		return -ENODEV;
-
-	usb_unpoison_anchored_urbs(&aru->rx_submitted);
-	usb_unpoison_anchored_urbs(&aru->tx_submitted);
-
-	/*
-	 * FIXME: firmware upload will fail on resume.
-	 * but this is better than a hang!
-	 */
-
-	err = ar9170_usb_init_device(aru);
-	if (err)
-		goto err_unrx;
-
-	err = ar9170_usb_open(&aru->common);
-	if (err)
-		goto err_unrx;
-
-	return 0;
-
-err_unrx:
-	aru->common.state = AR9170_IDLE;
-	ar9170_usb_cancel_urbs(aru);
-
-	return err;
-}
-#endif /* CONFIG_PM */
-
-static struct usb_driver ar9170_driver = {
-	.name = "ar9170usb",
-	.probe = ar9170_usb_probe,
-	.disconnect = ar9170_usb_disconnect,
-	.id_table = ar9170_usb_ids,
-	.soft_unbind = 1,
-#ifdef CONFIG_PM
-	.suspend = ar9170_suspend,
-	.resume = ar9170_resume,
-#endif /* CONFIG_PM */
-};
-
-static int __init ar9170_init(void)
-{
-	return usb_register(&ar9170_driver);
-}
-
-static void __exit ar9170_exit(void)
-{
-	usb_deregister(&ar9170_driver);
-}
-
-module_init(ar9170_init);
-module_exit(ar9170_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/usb.h linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/usb.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ar9170/usb.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ar9170/usb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-/*
- * Atheros AR9170 USB driver
- *
- * Driver specific definitions
- *
- * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2009, Christian Lamparter <chunkeey@web.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.
- *
- * 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; see the file COPYING.  If not, see
- * http://www.gnu.org/licenses/.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *    Copyright (c) 2007-2008 Atheros Communications, Inc.
- *
- *    Permission to use, copy, modify, and/or distribute this software for any
- *    purpose with or without fee is hereby granted, provided that the above
- *    copyright notice and this permission notice appear in all copies.
- *
- *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef __USB_H
-#define __USB_H
-
-#include <linux/usb.h>
-#include <linux/completion.h>
-#include <linux/spinlock.h>
-#include <linux/leds.h>
-#include <net/wireless.h>
-#include <net/mac80211.h>
-#include <linux/firmware.h>
-#include "eeprom.h"
-#include "hw.h"
-#include "ar9170.h"
-
-#define AR9170_NUM_RX_URBS			16
-
-struct firmware;
-
-struct ar9170_usb {
-	struct ar9170 common;
-	struct usb_device *udev;
-	struct usb_interface *intf;
-
-	struct usb_anchor rx_submitted;
-	struct usb_anchor tx_submitted;
-
-	spinlock_t cmdlock;
-	struct completion cmd_wait;
-	int readlen;
-	u8 *readbuf;
-
-	const struct firmware *init_values;
-	const struct firmware *firmware;
-};
-
-#endif /* __USB_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/arlan-main.c linux-libre-2.6.31-gnu/drivers/net/wireless/arlan-main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/arlan-main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/arlan-main.c	2009-09-09 18:13:59.000000000 -0400
@@ -1199,7 +1199,7 @@
 	arlan_process_interrupt(dev);
 	netif_stop_queue (dev);
 	ARLAN_DEBUG_EXIT("arlan_tx");
-	return 1;
+	return NETDEV_TX_BUSY;
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/at76c50x-usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/at76c50x-usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/at76c50x-usb.c	2012-03-22 19:16:24.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/at76c50x-usb.c	2012-03-22 20:12:13.000000000 -0400
@@ -1965,13 +1965,18 @@
 	return 0;
 }
 
-static int at76_config_interface(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 struct ieee80211_if_conf *conf)
+static void at76_bss_info_changed(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  struct ieee80211_bss_conf *conf,
+				  u32 changed)
 {
 	struct at76_priv *priv = hw->priv;
 
 	at76_dbg(DBG_MAC80211, "%s():", __func__);
+
+	if (!(changed & BSS_CHANGED_BSSID))
+		return;
+
 	at76_dbg_dump(DBG_MAC80211, conf->bssid, ETH_ALEN, "bssid:");
 
 	mutex_lock(&priv->mtx);
@@ -1983,8 +1988,6 @@
 		at76_join(priv);
 
 	mutex_unlock(&priv->mtx);
-
-	return 0;
 }
 
 /* must be atomic */
@@ -2076,7 +2079,7 @@
 	.add_interface = at76_add_interface,
 	.remove_interface = at76_remove_interface,
 	.config = at76_config,
-	.config_interface = at76_config_interface,
+	.bss_info_changed = at76_bss_info_changed,
 	.configure_filter = at76_configure_filter,
 	.start = at76_mac80211_start,
 	.stop = at76_mac80211_stop,
@@ -2250,6 +2253,7 @@
 
 	/* mac80211 initialisation */
 	priv->hw->wiphy->max_scan_ssids = 1;
+	priv->hw->wiphy->max_scan_ie_len = 0;
 	priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 	priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band;
 	priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
@@ -2311,8 +2315,7 @@
 
 	del_timer_sync(&ledtrig_tx_timer);
 
-	if (priv->rx_skb)
-		kfree_skb(priv->rx_skb);
+	kfree_skb(priv->rx_skb);
 
 	usb_put_dev(priv->udev);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/ar9170.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/ar9170.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/ar9170.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/ar9170.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,257 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * Driver specific definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __AR9170_H
+#define __AR9170_H
+
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#ifdef CONFIG_AR9170_LEDS
+#include <linux/leds.h>
+#endif /* CONFIG_AR9170_LEDS */
+#include "eeprom.h"
+#include "hw.h"
+
+#include "../regd.h"
+
+#define PAYLOAD_MAX	(AR9170_MAX_CMD_LEN/4 - 1)
+
+enum ar9170_bw {
+	AR9170_BW_20,
+	AR9170_BW_40_BELOW,
+	AR9170_BW_40_ABOVE,
+
+	__AR9170_NUM_BW,
+};
+
+static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type)
+{
+	switch (type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		return AR9170_BW_20;
+	case NL80211_CHAN_HT40MINUS:
+		return AR9170_BW_40_BELOW;
+	case NL80211_CHAN_HT40PLUS:
+		return AR9170_BW_40_ABOVE;
+	default:
+		BUG();
+	}
+}
+
+enum ar9170_rf_init_mode {
+	AR9170_RFI_NONE,
+	AR9170_RFI_WARM,
+	AR9170_RFI_COLD,
+};
+
+#define AR9170_MAX_RX_BUFFER_SIZE		8192
+
+#ifdef CONFIG_AR9170_LEDS
+struct ar9170;
+
+struct ar9170_led {
+	struct ar9170 *ar;
+	struct led_classdev l;
+	char name[32];
+	unsigned int toggled;
+	bool last_state;
+	bool registered;
+};
+
+#endif /* CONFIG_AR9170_LEDS */
+
+enum ar9170_device_state {
+	AR9170_UNKNOWN_STATE,
+	AR9170_STOPPED,
+	AR9170_IDLE,
+	AR9170_STARTED,
+};
+
+struct ar9170_rxstream_mpdu_merge {
+	struct ar9170_rx_head plcp;
+	bool has_plcp;
+};
+
+#define AR9170_QUEUE_TIMEOUT		64
+#define AR9170_TX_TIMEOUT		8
+#define AR9170_JANITOR_DELAY		128
+#define AR9170_TX_INVALID_RATE		0xffffffff
+
+struct ar9170 {
+	struct ieee80211_hw *hw;
+	struct mutex mutex;
+	enum ar9170_device_state state;
+	unsigned long bad_hw_nagger;
+
+	int (*open)(struct ar9170 *);
+	void (*stop)(struct ar9170 *);
+	int (*tx)(struct ar9170 *, struct sk_buff *);
+	int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 ,
+			void *, u32 , void *);
+	void (*callback_cmd)(struct ar9170 *, u32 , void *);
+	int (*flush)(struct ar9170 *);
+
+	/* interface mode settings */
+	struct ieee80211_vif *vif;
+	u8 mac_addr[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
+
+	/* beaconing */
+	struct sk_buff *beacon;
+	struct work_struct beacon_work;
+
+	/* cryptographic engine */
+	u64 usedkeys;
+	bool rx_software_decryption;
+	bool disable_offload;
+
+	/* filter settings */
+	struct work_struct filter_config_work;
+	u64 cur_mc_hash, want_mc_hash;
+	u32 cur_filter, want_filter;
+	unsigned long filter_changed;
+	unsigned int filter_state;
+	bool sniffer_enabled;
+
+	/* PHY */
+	struct ieee80211_channel *channel;
+	int noise[4];
+
+	/* power calibration data */
+	u8 power_5G_leg[4];
+	u8 power_2G_cck[4];
+	u8 power_2G_ofdm[4];
+	u8 power_5G_ht20[8];
+	u8 power_5G_ht40[8];
+	u8 power_2G_ht20[8];
+	u8 power_2G_ht40[8];
+
+#ifdef CONFIG_AR9170_LEDS
+	struct delayed_work led_work;
+	struct ar9170_led leds[AR9170_NUM_LEDS];
+#endif /* CONFIG_AR9170_LEDS */
+
+	/* qos queue settings */
+	spinlock_t tx_stats_lock;
+	struct ieee80211_tx_queue_stats tx_stats[5];
+	struct ieee80211_tx_queue_params edcf[5];
+
+	spinlock_t cmdlock;
+	__le32 cmdbuf[PAYLOAD_MAX + 1];
+
+	/* MAC statistics */
+	struct ieee80211_low_level_stats stats;
+
+	/* EEPROM */
+	struct ar9170_eeprom eeprom;
+	struct ath_regulatory regulatory;
+
+	/* tx queues - as seen by hw - */
+	struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
+	struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
+	struct delayed_work tx_janitor;
+
+	/* rxstream mpdu merge */
+	struct ar9170_rxstream_mpdu_merge rx_mpdu;
+	struct sk_buff *rx_failover;
+	int rx_failover_missing;
+};
+
+struct ar9170_sta_info {
+};
+
+#define AR9170_TX_FLAG_WAIT_FOR_ACK	BIT(0)
+#define AR9170_TX_FLAG_NO_ACK		BIT(1)
+#define AR9170_TX_FLAG_BLOCK_ACK	BIT(2)
+
+struct ar9170_tx_info {
+	unsigned long timeout;
+	unsigned int flags;
+};
+
+#define IS_STARTED(a)		(((struct ar9170 *)a)->state >= AR9170_STARTED)
+#define IS_ACCEPTING_CMD(a)	(((struct ar9170 *)a)->state >= AR9170_IDLE)
+
+#define AR9170_FILTER_CHANGED_MODE		BIT(0)
+#define AR9170_FILTER_CHANGED_MULTICAST		BIT(1)
+#define AR9170_FILTER_CHANGED_FRAMEFILTER	BIT(2)
+
+/* exported interface */
+void *ar9170_alloc(size_t priv_size);
+int ar9170_register(struct ar9170 *ar, struct device *pdev);
+void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb);
+void ar9170_unregister(struct ar9170 *ar);
+void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb);
+void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
+int ar9170_nag_limiter(struct ar9170 *ar);
+
+/* MAC */
+int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+int ar9170_init_mac(struct ar9170 *ar);
+int ar9170_set_qos(struct ar9170 *ar);
+int ar9170_update_multicast(struct ar9170 *ar);
+int ar9170_update_frame_filter(struct ar9170 *ar);
+int ar9170_set_operating_mode(struct ar9170 *ar);
+int ar9170_set_beacon_timers(struct ar9170 *ar);
+int ar9170_set_dyn_sifs_ack(struct ar9170 *ar);
+int ar9170_set_slot_time(struct ar9170 *ar);
+int ar9170_set_basic_rates(struct ar9170 *ar);
+int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry);
+int ar9170_update_beacon(struct ar9170 *ar);
+void ar9170_new_beacon(struct work_struct *work);
+int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype,
+		      u8 keyidx, u8 *keydata, int keylen);
+int ar9170_disable_key(struct ar9170 *ar, u8 id);
+
+/* LEDs */
+#ifdef CONFIG_AR9170_LEDS
+int ar9170_register_leds(struct ar9170 *ar);
+void ar9170_unregister_leds(struct ar9170 *ar);
+#endif /* CONFIG_AR9170_LEDS */
+int ar9170_init_leds(struct ar9170 *ar);
+int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state);
+
+/* PHY / RF */
+int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band);
+int ar9170_init_rf(struct ar9170 *ar);
+int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
+		       enum ar9170_rf_init_mode rfi, enum ar9170_bw bw);
+
+#endif /* __AR9170_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/cmd.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/cmd.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/cmd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/cmd.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,129 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * Basic HW register/memory/command access functions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ar9170.h"
+#include "cmd.h"
+
+int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len)
+{
+	int err;
+
+	if (unlikely(!IS_ACCEPTING_CMD(ar)))
+		return 0;
+
+	err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL);
+	if (err)
+		printk(KERN_DEBUG "%s: writing memory failed\n",
+		       wiphy_name(ar->hw->wiphy));
+	return err;
+}
+
+int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
+{
+	__le32 buf[2] = {
+		cpu_to_le32(reg),
+		cpu_to_le32(val),
+	};
+	int err;
+
+	if (unlikely(!IS_ACCEPTING_CMD(ar)))
+		return 0;
+
+	err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf),
+			   (u8 *) buf, 0, NULL);
+	if (err)
+		printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n",
+		       wiphy_name(ar->hw->wiphy), reg, val);
+	return err;
+}
+
+static int ar9170_read_mreg(struct ar9170 *ar, int nregs,
+			    const u32 *regs, u32 *out)
+{
+	int i, err;
+	__le32 *offs, *res;
+
+	if (unlikely(!IS_ACCEPTING_CMD(ar)))
+		return 0;
+
+	/* abuse "out" for the register offsets, must be same length */
+	offs = (__le32 *)out;
+	for (i = 0; i < nregs; i++)
+		offs[i] = cpu_to_le32(regs[i]);
+
+	/* also use the same buffer for the input */
+	res = (__le32 *)out;
+
+	err = ar->exec_cmd(ar, AR9170_CMD_RREG,
+			   4 * nregs, (u8 *)offs,
+			   4 * nregs, (u8 *)res);
+	if (err)
+		return err;
+
+	/* convert result to cpu endian */
+	for (i = 0; i < nregs; i++)
+		out[i] = le32_to_cpu(res[i]);
+
+	return 0;
+}
+
+int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val)
+{
+	return ar9170_read_mreg(ar, 1, &reg, val);
+}
+
+int ar9170_echo_test(struct ar9170 *ar, u32 v)
+{
+	__le32 echobuf = cpu_to_le32(v);
+	__le32 echores;
+	int err;
+
+	if (unlikely(!IS_ACCEPTING_CMD(ar)))
+		return -ENODEV;
+
+	err = ar->exec_cmd(ar, AR9170_CMD_ECHO,
+			   4, (u8 *)&echobuf,
+			   4, (u8 *)&echores);
+	if (err)
+		return err;
+
+	if (echobuf != echores)
+		return -EINVAL;
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/cmd.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/cmd.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/cmd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/cmd.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,91 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * Basic HW register/memory/command access functions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CMD_H
+#define __CMD_H
+
+#include "ar9170.h"
+
+/* basic HW access */
+int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len);
+int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
+int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val);
+int ar9170_echo_test(struct ar9170 *ar, u32 v);
+
+/*
+ * Macros to facilitate writing multiple registers in a single
+ * write-combining USB command. Note that when the first group
+ * fails the whole thing will fail without any others attempted,
+ * but you won't know which write in the group failed.
+ */
+#define ar9170_regwrite_begin(ar)					\
+do {									\
+	int __nreg = 0, __err = 0;					\
+	struct ar9170 *__ar = ar;
+
+#define ar9170_regwrite(r, v) do {					\
+	__ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r);			\
+	__ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v);			\
+	__nreg++;							\
+	if ((__nreg >= PAYLOAD_MAX/2)) {				\
+		if (IS_ACCEPTING_CMD(__ar))				\
+			__err = ar->exec_cmd(__ar, AR9170_CMD_WREG,	\
+					     8 * __nreg,		\
+					     (u8 *) &__ar->cmdbuf[1],	\
+					     0, NULL);			\
+		__nreg = 0;						\
+		if (__err)						\
+			goto __regwrite_out;				\
+	}								\
+} while (0)
+
+#define ar9170_regwrite_finish()					\
+__regwrite_out :							\
+	if (__nreg) {							\
+		if (IS_ACCEPTING_CMD(__ar))				\
+			__err = ar->exec_cmd(__ar, AR9170_CMD_WREG,	\
+					     8 * __nreg, 		\
+					     (u8 *) &__ar->cmdbuf[1],	\
+					     0, NULL);			\
+		__nreg = 0;						\
+	}
+
+#define ar9170_regwrite_result()					\
+	__err;								\
+} while (0);
+
+#endif /* __CMD_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/eeprom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/eeprom.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,179 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * EEPROM layout
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __AR9170_EEPROM_H
+#define __AR9170_EEPROM_H
+
+#define AR5416_MAX_CHAINS		2
+#define AR5416_MODAL_SPURS		5
+
+struct ar9170_eeprom_modal {
+	__le32	antCtrlChain[AR5416_MAX_CHAINS];
+	__le32	antCtrlCommon;
+	s8	antennaGainCh[AR5416_MAX_CHAINS];
+	u8	switchSettling;
+	u8	txRxAttenCh[AR5416_MAX_CHAINS];
+	u8	rxTxMarginCh[AR5416_MAX_CHAINS];
+	s8	adcDesiredSize;
+	s8	pgaDesiredSize;
+	u8	xlnaGainCh[AR5416_MAX_CHAINS];
+	u8	txEndToXpaOff;
+	u8	txEndToRxOn;
+	u8	txFrameToXpaOn;
+	u8	thresh62;
+	s8	noiseFloorThreshCh[AR5416_MAX_CHAINS];
+	u8	xpdGain;
+	u8	xpd;
+	s8	iqCalICh[AR5416_MAX_CHAINS];
+	s8	iqCalQCh[AR5416_MAX_CHAINS];
+	u8	pdGainOverlap;
+	u8	ob;
+	u8	db;
+	u8	xpaBiasLvl;
+	u8	pwrDecreaseFor2Chain;
+	u8	pwrDecreaseFor3Chain;
+	u8	txFrameToDataStart;
+	u8	txFrameToPaOn;
+	u8	ht40PowerIncForPdadc;
+	u8	bswAtten[AR5416_MAX_CHAINS];
+	u8	bswMargin[AR5416_MAX_CHAINS];
+	u8	swSettleHt40;
+	u8	reserved[22];
+	struct spur_channel {
+		__le16 spurChan;
+		u8	spurRangeLow;
+		u8	spurRangeHigh;
+	} __packed spur_channels[AR5416_MODAL_SPURS];
+} __packed;
+
+#define AR5416_NUM_PD_GAINS		4
+#define AR5416_PD_GAIN_ICEPTS		5
+
+struct ar9170_calibration_data_per_freq {
+	u8	pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+	u8	vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed;
+
+#define AR5416_NUM_5G_CAL_PIERS		8
+#define AR5416_NUM_2G_CAL_PIERS		4
+
+#define AR5416_NUM_5G_TARGET_PWRS	8
+#define AR5416_NUM_2G_CCK_TARGET_PWRS	3
+#define AR5416_NUM_2G_OFDM_TARGET_PWRS	4
+#define AR5416_MAX_NUM_TGT_PWRS		8
+
+struct ar9170_calibration_target_power_legacy {
+	u8	freq;
+	u8	power[4];
+} __packed;
+
+struct ar9170_calibration_target_power_ht {
+	u8	freq;
+	u8	power[8];
+} __packed;
+
+#define AR5416_NUM_CTLS			24
+
+struct ar9170_calctl_edges {
+	u8	channel;
+#define AR9170_CALCTL_EDGE_FLAGS	0xC0
+	u8	power_flags;
+} __packed;
+
+#define AR5416_NUM_BAND_EDGES		8
+
+struct ar9170_calctl_data {
+	struct ar9170_calctl_edges
+		control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __packed;
+
+
+struct ar9170_eeprom {
+	__le16	length;
+	__le16	checksum;
+	__le16	version;
+	u8	operating_flags;
+#define AR9170_OPFLAG_5GHZ 		1
+#define AR9170_OPFLAG_2GHZ 		2
+	u8	misc;
+	__le16	reg_domain[2];
+	u8	mac_address[6];
+	u8	rx_mask;
+	u8	tx_mask;
+	__le16	rf_silent;
+	__le16	bluetooth_options;
+	__le16	device_capabilities;
+	__le32	build_number;
+	u8	deviceType;
+	u8	reserved[33];
+
+	u8	customer_data[64];
+
+	struct ar9170_eeprom_modal
+		modal_header[2];
+
+	u8	cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS];
+	u8	cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS];
+
+	struct ar9170_calibration_data_per_freq
+		cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS],
+		cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+
+	/* power calibration data */
+	struct ar9170_calibration_target_power_legacy
+		cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS];
+	struct ar9170_calibration_target_power_ht
+		cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS],
+		cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS];
+
+	struct ar9170_calibration_target_power_legacy
+		cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS],
+		cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS];
+	struct ar9170_calibration_target_power_ht
+		cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS],
+		cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS];
+
+	/* conformance testing limits */
+	u8	ctl_index[AR5416_NUM_CTLS];
+	struct ar9170_calctl_data
+		ctl_data[AR5416_NUM_CTLS];
+
+	u8	pad;
+	__le16	subsystem_id;
+} __packed;
+
+#endif /* __AR9170_EEPROM_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/hw.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/hw.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/hw.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,426 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * Hardware-specific definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __AR9170_HW_H
+#define __AR9170_HW_H
+
+#define AR9170_MAX_CMD_LEN	64
+
+enum ar9170_cmd {
+	AR9170_CMD_RREG		= 0x00,
+	AR9170_CMD_WREG		= 0x01,
+	AR9170_CMD_RMEM		= 0x02,
+	AR9170_CMD_WMEM		= 0x03,
+	AR9170_CMD_BITAND	= 0x04,
+	AR9170_CMD_BITOR	= 0x05,
+	AR9170_CMD_EKEY		= 0x28,
+	AR9170_CMD_DKEY		= 0x29,
+	AR9170_CMD_FREQUENCY	= 0x30,
+	AR9170_CMD_RF_INIT	= 0x31,
+	AR9170_CMD_SYNTH	= 0x32,
+	AR9170_CMD_FREQ_START	= 0x33,
+	AR9170_CMD_ECHO		= 0x80,
+	AR9170_CMD_TALLY	= 0x81,
+	AR9170_CMD_TALLY_APD	= 0x82,
+	AR9170_CMD_CONFIG	= 0x83,
+	AR9170_CMD_RESET	= 0x90,
+	AR9170_CMD_DKRESET	= 0x91,
+	AR9170_CMD_DKTX_STATUS	= 0x92,
+	AR9170_CMD_FDC		= 0xA0,
+	AR9170_CMD_WREEPROM	= 0xB0,
+	AR9170_CMD_WFLASH	= 0xB0,
+	AR9170_CMD_FLASH_ERASE	= 0xB1,
+	AR9170_CMD_FLASH_PROG	= 0xB2,
+	AR9170_CMD_FLASH_CHKSUM	= 0xB3,
+	AR9170_CMD_FLASH_READ	= 0xB4,
+	AR9170_CMD_FW_DL_INIT	= 0xB5,
+	AR9170_CMD_MEM_WREEPROM	= 0xBB,
+};
+
+/* endpoints */
+#define AR9170_EP_TX				1
+#define AR9170_EP_RX				2
+#define AR9170_EP_IRQ				3
+#define AR9170_EP_CMD				4
+
+#define AR9170_EEPROM_START			0x1600
+
+#define AR9170_GPIO_REG_BASE			0x1d0100
+#define AR9170_GPIO_REG_PORT_TYPE		AR9170_GPIO_REG_BASE
+#define AR9170_GPIO_REG_DATA			(AR9170_GPIO_REG_BASE + 4)
+#define AR9170_NUM_LEDS				2
+
+
+#define AR9170_USB_REG_BASE			0x1e1000
+#define AR9170_USB_REG_DMA_CTL			(AR9170_USB_REG_BASE + 0x108)
+#define		AR9170_DMA_CTL_ENABLE_TO_DEVICE		0x1
+#define		AR9170_DMA_CTL_ENABLE_FROM_DEVICE	0x2
+#define		AR9170_DMA_CTL_HIGH_SPEED		0x4
+#define		AR9170_DMA_CTL_PACKET_MODE		0x8
+
+#define AR9170_USB_REG_MAX_AGG_UPLOAD		(AR9170_USB_REG_BASE + 0x110)
+#define AR9170_USB_REG_UPLOAD_TIME_CTL		(AR9170_USB_REG_BASE + 0x114)
+
+
+
+#define AR9170_MAC_REG_BASE			0x1c3000
+
+#define AR9170_MAC_REG_TSF_L			(AR9170_MAC_REG_BASE + 0x514)
+#define AR9170_MAC_REG_TSF_H			(AR9170_MAC_REG_BASE + 0x518)
+
+#define AR9170_MAC_REG_ATIM_WINDOW		(AR9170_MAC_REG_BASE + 0x51C)
+#define AR9170_MAC_REG_BCN_PERIOD		(AR9170_MAC_REG_BASE + 0x520)
+#define AR9170_MAC_REG_PRETBTT			(AR9170_MAC_REG_BASE + 0x524)
+
+#define AR9170_MAC_REG_MAC_ADDR_L		(AR9170_MAC_REG_BASE + 0x610)
+#define AR9170_MAC_REG_MAC_ADDR_H		(AR9170_MAC_REG_BASE + 0x614)
+#define AR9170_MAC_REG_BSSID_L			(AR9170_MAC_REG_BASE + 0x618)
+#define AR9170_MAC_REG_BSSID_H			(AR9170_MAC_REG_BASE + 0x61c)
+
+#define AR9170_MAC_REG_GROUP_HASH_TBL_L		(AR9170_MAC_REG_BASE + 0x624)
+#define AR9170_MAC_REG_GROUP_HASH_TBL_H		(AR9170_MAC_REG_BASE + 0x628)
+
+#define AR9170_MAC_REG_RX_TIMEOUT		(AR9170_MAC_REG_BASE + 0x62C)
+
+#define AR9170_MAC_REG_BASIC_RATE		(AR9170_MAC_REG_BASE + 0x630)
+#define AR9170_MAC_REG_MANDATORY_RATE		(AR9170_MAC_REG_BASE + 0x634)
+#define AR9170_MAC_REG_RTS_CTS_RATE		(AR9170_MAC_REG_BASE + 0x638)
+#define AR9170_MAC_REG_BACKOFF_PROTECT		(AR9170_MAC_REG_BASE + 0x63c)
+#define AR9170_MAC_REG_RX_THRESHOLD		(AR9170_MAC_REG_BASE + 0x640)
+#define AR9170_MAC_REG_RX_PE_DELAY		(AR9170_MAC_REG_BASE + 0x64C)
+
+#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK		(AR9170_MAC_REG_BASE + 0x658)
+#define AR9170_MAC_REG_SNIFFER			(AR9170_MAC_REG_BASE + 0x674)
+#define		AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC	BIT(0)
+#define		AR9170_MAC_REG_SNIFFER_DEFAULTS		0x02000000
+#define AR9170_MAC_REG_ENCRYPTION		(AR9170_MAC_REG_BASE + 0x678)
+#define		AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE	BIT(3)
+#define		AR9170_MAC_REG_ENCRYPTION_DEFAULTS	0x70
+
+#define AR9170_MAC_REG_MISC_680			(AR9170_MAC_REG_BASE + 0x680)
+#define AR9170_MAC_REG_TX_UNDERRUN		(AR9170_MAC_REG_BASE + 0x688)
+
+#define AR9170_MAC_REG_FRAMETYPE_FILTER		(AR9170_MAC_REG_BASE + 0x68c)
+#define		AR9170_MAC_REG_FTF_ASSOC_REQ		BIT(0)
+#define		AR9170_MAC_REG_FTF_ASSOC_RESP		BIT(1)
+#define		AR9170_MAC_REG_FTF_REASSOC_REQ		BIT(2)
+#define		AR9170_MAC_REG_FTF_REASSOC_RESP		BIT(3)
+#define		AR9170_MAC_REG_FTF_PRB_REQ		BIT(4)
+#define		AR9170_MAC_REG_FTF_PRB_RESP		BIT(5)
+#define		AR9170_MAC_REG_FTF_BIT6			BIT(6)
+#define		AR9170_MAC_REG_FTF_BIT7			BIT(7)
+#define		AR9170_MAC_REG_FTF_BEACON		BIT(8)
+#define		AR9170_MAC_REG_FTF_ATIM			BIT(9)
+#define		AR9170_MAC_REG_FTF_DEASSOC		BIT(10)
+#define		AR9170_MAC_REG_FTF_AUTH			BIT(11)
+#define		AR9170_MAC_REG_FTF_DEAUTH		BIT(12)
+#define		AR9170_MAC_REG_FTF_BIT13		BIT(13)
+#define		AR9170_MAC_REG_FTF_BIT14		BIT(14)
+#define		AR9170_MAC_REG_FTF_BIT15		BIT(15)
+#define		AR9170_MAC_REG_FTF_BAR			BIT(24)
+#define		AR9170_MAC_REG_FTF_BIT25		BIT(25)
+#define		AR9170_MAC_REG_FTF_PSPOLL		BIT(26)
+#define		AR9170_MAC_REG_FTF_RTS			BIT(27)
+#define		AR9170_MAC_REG_FTF_CTS			BIT(28)
+#define		AR9170_MAC_REG_FTF_ACK			BIT(29)
+#define		AR9170_MAC_REG_FTF_CFE			BIT(30)
+#define		AR9170_MAC_REG_FTF_CFE_ACK		BIT(31)
+#define		AR9170_MAC_REG_FTF_DEFAULTS		0x0500ffff
+#define		AR9170_MAC_REG_FTF_MONITOR		0xfd00ffff
+
+#define AR9170_MAC_REG_RX_TOTAL			(AR9170_MAC_REG_BASE + 0x6A0)
+#define AR9170_MAC_REG_RX_CRC32			(AR9170_MAC_REG_BASE + 0x6A4)
+#define AR9170_MAC_REG_RX_CRC16			(AR9170_MAC_REG_BASE + 0x6A8)
+#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI	(AR9170_MAC_REG_BASE + 0x6AC)
+#define AR9170_MAC_REG_RX_OVERRUN		(AR9170_MAC_REG_BASE + 0x6B0)
+#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL	(AR9170_MAC_REG_BASE + 0x6BC)
+#define AR9170_MAC_REG_TX_RETRY			(AR9170_MAC_REG_BASE + 0x6CC)
+#define AR9170_MAC_REG_TX_TOTAL			(AR9170_MAC_REG_BASE + 0x6F4)
+
+
+#define AR9170_MAC_REG_ACK_EXTENSION		(AR9170_MAC_REG_BASE + 0x690)
+#define AR9170_MAC_REG_EIFS_AND_SIFS		(AR9170_MAC_REG_BASE + 0x698)
+
+#define AR9170_MAC_REG_SLOT_TIME		(AR9170_MAC_REG_BASE + 0x6F0)
+
+#define AR9170_MAC_REG_POWERMANAGEMENT		(AR9170_MAC_REG_BASE + 0x700)
+#define		AR9170_MAC_REG_POWERMGT_IBSS		0xe0
+#define		AR9170_MAC_REG_POWERMGT_AP		0xa1
+#define		AR9170_MAC_REG_POWERMGT_STA		0x2
+#define		AR9170_MAC_REG_POWERMGT_AP_WDS		0x3
+#define		AR9170_MAC_REG_POWERMGT_DEFAULTS	(0xf << 24)
+
+#define AR9170_MAC_REG_ROLL_CALL_TBL_L		(AR9170_MAC_REG_BASE + 0x704)
+#define AR9170_MAC_REG_ROLL_CALL_TBL_H		(AR9170_MAC_REG_BASE + 0x708)
+
+#define AR9170_MAC_REG_AC0_CW			(AR9170_MAC_REG_BASE + 0xB00)
+#define AR9170_MAC_REG_AC1_CW			(AR9170_MAC_REG_BASE + 0xB04)
+#define AR9170_MAC_REG_AC2_CW			(AR9170_MAC_REG_BASE + 0xB08)
+#define AR9170_MAC_REG_AC3_CW			(AR9170_MAC_REG_BASE + 0xB0C)
+#define AR9170_MAC_REG_AC4_CW			(AR9170_MAC_REG_BASE + 0xB10)
+#define AR9170_MAC_REG_AC1_AC0_AIFS		(AR9170_MAC_REG_BASE + 0xB14)
+#define AR9170_MAC_REG_AC3_AC2_AIFS		(AR9170_MAC_REG_BASE + 0xB18)
+
+#define AR9170_MAC_REG_RETRY_MAX		(AR9170_MAC_REG_BASE + 0xB28)
+
+#define AR9170_MAC_REG_FCS_SELECT		(AR9170_MAC_REG_BASE + 0xBB0)
+#define		AR9170_MAC_FCS_SWFCS		0x1
+#define		AR9170_MAC_FCS_FIFO_PROT	0x4
+
+
+#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND	(AR9170_MAC_REG_BASE + 0xB30)
+
+#define AR9170_MAC_REG_AC1_AC0_TXOP		(AR9170_MAC_REG_BASE + 0xB44)
+#define AR9170_MAC_REG_AC3_AC2_TXOP		(AR9170_MAC_REG_BASE + 0xB48)
+
+#define AR9170_MAC_REG_AMPDU_FACTOR		(AR9170_MAC_REG_BASE + 0xB9C)
+#define AR9170_MAC_REG_AMPDU_DENSITY		(AR9170_MAC_REG_BASE + 0xBA0)
+
+#define AR9170_MAC_REG_ACK_TABLE		(AR9170_MAC_REG_BASE + 0xC00)
+#define AR9170_MAC_REG_AMPDU_RX_THRESH		(AR9170_MAC_REG_BASE + 0xC50)
+
+#define AR9170_MAC_REG_TXRX_MPI			(AR9170_MAC_REG_BASE + 0xD7C)
+#define		AR9170_MAC_TXRX_MPI_TX_MPI_MASK	0x0000000f
+#define		AR9170_MAC_TXRX_MPI_TX_TO_MASK	0x0000fff0
+#define		AR9170_MAC_TXRX_MPI_RX_MPI_MASK	0x000f0000
+#define		AR9170_MAC_TXRX_MPI_RX_TO_MASK	0xfff00000
+
+#define AR9170_MAC_REG_BCN_ADDR			(AR9170_MAC_REG_BASE + 0xD84)
+#define AR9170_MAC_REG_BCN_LENGTH		(AR9170_MAC_REG_BASE + 0xD88)
+#define AR9170_MAC_REG_BCN_PLCP			(AR9170_MAC_REG_BASE + 0xD90)
+#define AR9170_MAC_REG_BCN_CTRL			(AR9170_MAC_REG_BASE + 0xD94)
+#define AR9170_MAC_REG_BCN_HT1			(AR9170_MAC_REG_BASE + 0xDA0)
+#define AR9170_MAC_REG_BCN_HT2			(AR9170_MAC_REG_BASE + 0xDA4)
+
+
+#define AR9170_PWR_REG_BASE			0x1D4000
+
+#define AR9170_PWR_REG_CLOCK_SEL		(AR9170_PWR_REG_BASE + 0x008)
+#define		AR9170_PWR_CLK_AHB_40MHZ	0
+#define		AR9170_PWR_CLK_AHB_20_22MHZ	1
+#define		AR9170_PWR_CLK_AHB_40_44MHZ	2
+#define		AR9170_PWR_CLK_AHB_80_88MHZ	3
+#define		AR9170_PWR_CLK_DAC_160_INV_DLY	0x70
+
+
+/* put beacon here in memory */
+#define AR9170_BEACON_BUFFER_ADDRESS		0x117900
+
+
+struct ar9170_tx_control {
+	__le16 length;
+	__le16 mac_control;
+	__le32 phy_control;
+	u8 frame_data[0];
+} __packed;
+
+/* these are either-or */
+#define AR9170_TX_MAC_PROT_RTS			0x0001
+#define AR9170_TX_MAC_PROT_CTS			0x0002
+
+#define AR9170_TX_MAC_NO_ACK			0x0004
+/* if unset, MAC will only do SIFS space before frame */
+#define AR9170_TX_MAC_BACKOFF			0x0008
+#define AR9170_TX_MAC_BURST			0x0010
+#define AR9170_TX_MAC_AGGR			0x0020
+
+/* encryption is a two-bit field */
+#define AR9170_TX_MAC_ENCR_NONE			0x0000
+#define AR9170_TX_MAC_ENCR_RC4			0x0040
+#define AR9170_TX_MAC_ENCR_CENC			0x0080
+#define AR9170_TX_MAC_ENCR_AES			0x00c0
+
+#define AR9170_TX_MAC_MMIC			0x0100
+#define AR9170_TX_MAC_HW_DURATION		0x0200
+#define AR9170_TX_MAC_QOS_SHIFT			10
+#define AR9170_TX_MAC_QOS_MASK			(3 << AR9170_TX_MAC_QOS_SHIFT)
+#define AR9170_TX_MAC_AGGR_QOS_BIT1		0x0400
+#define AR9170_TX_MAC_AGGR_QOS_BIT2		0x0800
+#define AR9170_TX_MAC_DISABLE_TXOP		0x1000
+#define AR9170_TX_MAC_TXOP_RIFS			0x2000
+#define AR9170_TX_MAC_IMM_AMPDU			0x4000
+#define AR9170_TX_MAC_RATE_PROBE		0x8000
+
+/* either-or */
+#define AR9170_TX_PHY_MOD_CCK			0x00000000
+#define AR9170_TX_PHY_MOD_OFDM			0x00000001
+#define AR9170_TX_PHY_MOD_HT			0x00000002
+
+/* depends on modulation */
+#define AR9170_TX_PHY_SHORT_PREAMBLE		0x00000004
+#define AR9170_TX_PHY_GREENFIELD		0x00000004
+
+#define AR9170_TX_PHY_BW_SHIFT			3
+#define AR9170_TX_PHY_BW_MASK			(3 << AR9170_TX_PHY_BW_SHIFT)
+#define AR9170_TX_PHY_BW_20MHZ			0
+#define AR9170_TX_PHY_BW_40MHZ			2
+#define AR9170_TX_PHY_BW_40MHZ_DUP		3
+
+#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT	6
+#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK	(7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT)
+
+#define AR9170_TX_PHY_TX_PWR_SHIFT		9
+#define AR9170_TX_PHY_TX_PWR_MASK		(0x3f << AR9170_TX_PHY_TX_PWR_SHIFT)
+
+/* not part of the hw-spec */
+#define AR9170_TX_PHY_QOS_SHIFT			25
+#define AR9170_TX_PHY_QOS_MASK			(3 << AR9170_TX_PHY_QOS_SHIFT)
+
+#define AR9170_TX_PHY_TXCHAIN_SHIFT		15
+#define AR9170_TX_PHY_TXCHAIN_MASK		(7 << AR9170_TX_PHY_TXCHAIN_SHIFT)
+#define AR9170_TX_PHY_TXCHAIN_1			1
+/* use for cck, ofdm 6/9/12/18/24 and HT if capable */
+#define AR9170_TX_PHY_TXCHAIN_2			5
+
+#define AR9170_TX_PHY_MCS_SHIFT			18
+#define AR9170_TX_PHY_MCS_MASK			(0x7f << AR9170_TX_PHY_MCS_SHIFT)
+
+#define AR9170_TX_PHY_SHORT_GI			0x80000000
+
+struct ar9170_rx_head {
+	u8 plcp[12];
+} __packed;
+
+struct ar9170_rx_phystatus {
+	union {
+		struct {
+			u8 rssi_ant0, rssi_ant1, rssi_ant2,
+			   rssi_ant0x, rssi_ant1x, rssi_ant2x,
+			   rssi_combined;
+		} __packed;
+		u8 rssi[7];
+	} __packed;
+
+	u8 evm_stream0[6], evm_stream1[6];
+	u8 phy_err;
+} __packed;
+
+struct ar9170_rx_macstatus {
+	u8 SAidx, DAidx;
+	u8 error;
+	u8 status;
+} __packed;
+
+#define AR9170_ENC_ALG_NONE			0x0
+#define AR9170_ENC_ALG_WEP64			0x1
+#define AR9170_ENC_ALG_TKIP			0x2
+#define AR9170_ENC_ALG_AESCCMP			0x4
+#define AR9170_ENC_ALG_WEP128			0x5
+#define AR9170_ENC_ALG_WEP256			0x6
+#define AR9170_ENC_ALG_CENC			0x7
+
+#define AR9170_RX_ENC_SOFTWARE			0x8
+
+static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
+{
+	return (t->SAidx & 0xc0) >> 4 |
+	       (t->DAidx & 0xc0) >> 6;
+}
+
+#define AR9170_RX_STATUS_MODULATION_MASK	0x03
+#define AR9170_RX_STATUS_MODULATION_CCK		0x00
+#define AR9170_RX_STATUS_MODULATION_OFDM	0x01
+#define AR9170_RX_STATUS_MODULATION_HT		0x02
+#define AR9170_RX_STATUS_MODULATION_DUPOFDM	0x03
+
+/* depends on modulation */
+#define AR9170_RX_STATUS_SHORT_PREAMBLE		0x08
+#define AR9170_RX_STATUS_GREENFIELD		0x08
+
+#define AR9170_RX_STATUS_MPDU_MASK		0x30
+#define AR9170_RX_STATUS_MPDU_SINGLE		0x00
+#define AR9170_RX_STATUS_MPDU_FIRST		0x20
+#define AR9170_RX_STATUS_MPDU_MIDDLE		0x30
+#define AR9170_RX_STATUS_MPDU_LAST		0x10
+
+#define AR9170_RX_ERROR_RXTO			0x01
+#define AR9170_RX_ERROR_OVERRUN			0x02
+#define AR9170_RX_ERROR_DECRYPT			0x04
+#define AR9170_RX_ERROR_FCS			0x08
+#define AR9170_RX_ERROR_WRONG_RA		0x10
+#define AR9170_RX_ERROR_PLCP			0x20
+#define AR9170_RX_ERROR_MMIC			0x40
+#define AR9170_RX_ERROR_FATAL			0x80
+
+struct ar9170_cmd_tx_status {
+	u8 dst[ETH_ALEN];
+	__le32 rate;
+	__le16 status;
+} __packed;
+
+#define AR9170_TX_STATUS_COMPLETE		0x00
+#define AR9170_TX_STATUS_RETRY			0x01
+#define AR9170_TX_STATUS_FAILED			0x02
+
+struct ar9170_cmd_ba_failed_count {
+	__le16 failed;
+	__le16 rate;
+} __packed;
+
+struct ar9170_cmd_response {
+	u8 flag;
+	u8 type;
+	__le16 padding;
+
+	union {
+		struct ar9170_cmd_tx_status		tx_status;
+		struct ar9170_cmd_ba_failed_count	ba_fail_cnt;
+		u8 data[0];
+	};
+} __packed;
+
+/* QoS */
+
+/* mac80211 queue to HW/FW map */
+static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 };
+
+/* HW/FW queue to mac80211 map */
+static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 };
+
+enum ar9170_txq {
+	AR9170_TXQ_BE,
+	AR9170_TXQ_BK,
+	AR9170_TXQ_VI,
+	AR9170_TXQ_VO,
+
+	__AR9170_NUM_TXQ,
+};
+
+#define AR9170_TXQ_DEPTH	32
+#define AR9170_TX_MAX_PENDING	128
+
+#endif /* __AR9170_HW_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+config AR9170_USB
+	tristate "Atheros AR9170 802.11n USB support"
+	depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
+	select FW_LOADER
+	select ATH_COMMON
+	help
+	  This is a driver for the Atheros "otus" 802.11n USB devices.
+
+	  These devices require additional firmware (2 files).
+	  For now, these files can be downloaded from here:
+	  http://wireless.kernel.org/en/users/Drivers/ar9170
+
+	  If you choose to build a module, it'll be called ar9170usb.
+
+config AR9170_LEDS
+	bool
+	depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB)
+	default y
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/led.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/led.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/led.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/led.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,178 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * LED handling
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ar9170.h"
+#include "cmd.h"
+
+int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state)
+{
+	return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state);
+}
+
+int ar9170_init_leds(struct ar9170 *ar)
+{
+	int err;
+
+	/* disable LEDs */
+	/* GPIO [0/1 mode: output, 2/3: input] */
+	err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
+	if (err)
+		goto out;
+
+	/* GPIO 0/1 value: off */
+	err = ar9170_set_leds_state(ar, 0);
+
+out:
+	return err;
+}
+
+#ifdef CONFIG_AR9170_LEDS
+static void ar9170_update_leds(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
+	int i, tmp, blink_delay = 1000;
+	u32 led_val = 0;
+	bool rerun = false;
+
+	if (unlikely(!IS_ACCEPTING_CMD(ar)))
+		return ;
+
+	mutex_lock(&ar->mutex);
+	for (i = 0; i < AR9170_NUM_LEDS; i++)
+		if (ar->leds[i].registered && ar->leds[i].toggled) {
+			led_val |= 1 << i;
+
+			tmp = 70 + 200 / (ar->leds[i].toggled);
+			if (tmp < blink_delay)
+				blink_delay = tmp;
+
+			if (ar->leds[i].toggled > 1)
+				ar->leds[i].toggled = 0;
+
+			rerun = true;
+		}
+
+	ar9170_set_leds_state(ar, led_val);
+	mutex_unlock(&ar->mutex);
+
+	if (rerun)
+		queue_delayed_work(ar->hw->workqueue, &ar->led_work,
+				   msecs_to_jiffies(blink_delay));
+}
+
+static void ar9170_led_brightness_set(struct led_classdev *led,
+				      enum led_brightness brightness)
+{
+	struct ar9170_led *arl = container_of(led, struct ar9170_led, l);
+	struct ar9170 *ar = arl->ar;
+
+	if (unlikely(!arl->registered))
+		return ;
+
+	if (arl->last_state != !!brightness) {
+		arl->toggled++;
+		arl->last_state = !!brightness;
+	}
+
+	if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
+		queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
+}
+
+static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
+			       char *trigger)
+{
+	int err;
+
+	snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
+		 "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
+
+	ar->leds[i].ar = ar;
+	ar->leds[i].l.name = ar->leds[i].name;
+	ar->leds[i].l.brightness_set = ar9170_led_brightness_set;
+	ar->leds[i].l.brightness = 0;
+	ar->leds[i].l.default_trigger = trigger;
+
+	err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
+				    &ar->leds[i].l);
+	if (err)
+		printk(KERN_ERR "%s: failed to register %s LED (%d).\n",
+		       wiphy_name(ar->hw->wiphy), ar->leds[i].name, err);
+	else
+		ar->leds[i].registered = true;
+
+	return err;
+}
+
+void ar9170_unregister_leds(struct ar9170 *ar)
+{
+	int i;
+
+	for (i = 0; i < AR9170_NUM_LEDS; i++)
+		if (ar->leds[i].registered) {
+			led_classdev_unregister(&ar->leds[i].l);
+			ar->leds[i].registered = false;
+			ar->leds[i].toggled = 0;
+		}
+
+	cancel_delayed_work_sync(&ar->led_work);
+}
+
+int ar9170_register_leds(struct ar9170 *ar)
+{
+	int err;
+
+	INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds);
+
+	err = ar9170_register_led(ar, 0, "tx",
+				  ieee80211_get_tx_led_name(ar->hw));
+	if (err)
+		goto fail;
+
+	err = ar9170_register_led(ar, 1, "assoc",
+				 ieee80211_get_assoc_led_name(ar->hw));
+	if (err)
+		goto fail;
+
+	return 0;
+
+fail:
+	ar9170_unregister_leds(ar);
+	return err;
+}
+
+#endif /* CONFIG_AR9170_LEDS */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/mac.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/mac.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/mac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/mac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,524 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * MAC programming
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "ar9170.h"
+#include "cmd.h"
+
+int ar9170_set_dyn_sifs_ack(struct ar9170 *ar)
+{
+	u32 val;
+
+	if (conf_is_ht40(&ar->hw->conf))
+		val = 0x010a;
+	else {
+		if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+			val = 0x105;
+		else
+			val = 0x104;
+	}
+
+	return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val);
+}
+
+int ar9170_set_slot_time(struct ar9170 *ar)
+{
+	u32 slottime = 20;
+
+	if (!ar->vif)
+		return 0;
+
+	if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
+	    ar->vif->bss_conf.use_short_slot)
+		slottime = 9;
+
+	return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10);
+}
+
+int ar9170_set_basic_rates(struct ar9170 *ar)
+{
+	u8 cck, ofdm;
+
+	if (!ar->vif)
+		return 0;
+
+	ofdm = ar->vif->bss_conf.basic_rates >> 4;
+
+	/* FIXME: is still necessary? */
+	if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+		cck = 0;
+	else
+		cck = ar->vif->bss_conf.basic_rates & 0xf;
+
+	return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE,
+				ofdm << 8 | cck);
+}
+
+int ar9170_set_qos(struct ar9170 *ar)
+{
+	ar9170_regwrite_begin(ar);
+
+	ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min |
+			(ar->edcf[0].cw_max << 16));
+	ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min |
+			(ar->edcf[1].cw_max << 16));
+	ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min |
+			(ar->edcf[2].cw_max << 16));
+	ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min |
+			(ar->edcf[3].cw_max << 16));
+	ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min |
+			(ar->edcf[4].cw_max << 16));
+
+	ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS,
+			((ar->edcf[0].aifs * 9 + 10)) |
+			((ar->edcf[1].aifs * 9 + 10) << 12) |
+			((ar->edcf[2].aifs * 9 + 10) << 24));
+	ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS,
+			((ar->edcf[2].aifs * 9 + 10) >> 8) |
+			((ar->edcf[3].aifs * 9 + 10) << 4) |
+			((ar->edcf[4].aifs * 9 + 10) << 16));
+
+	ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP,
+			ar->edcf[0].txop | ar->edcf[1].txop << 16);
+	ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP,
+			ar->edcf[1].txop | ar->edcf[3].txop << 16);
+
+	ar9170_regwrite_finish();
+
+	return ar9170_regwrite_result();
+}
+
+static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity)
+{
+	u32 val;
+
+	/* don't allow AMPDU density > 8us */
+	if (mpdudensity > 6)
+		return -EINVAL;
+
+	/* Watch out! Otus uses slightly different density values. */
+	val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0);
+
+	ar9170_regwrite_begin(ar);
+	ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val);
+	ar9170_regwrite_finish();
+
+	return ar9170_regwrite_result();
+}
+
+int ar9170_init_mac(struct ar9170 *ar)
+{
+	ar9170_regwrite_begin(ar);
+
+	ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40);
+
+	ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0);
+
+	/* enable MMIC */
+	ar9170_regwrite(AR9170_MAC_REG_SNIFFER,
+			AR9170_MAC_REG_SNIFFER_DEFAULTS);
+
+	ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80);
+
+	ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70);
+	ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000);
+	ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10);
+
+	/* CF-END mode */
+	ar9170_regwrite(0x1c3b2c, 0x19000000);
+
+	/* NAV protects ACK only (in TXOP) */
+	ar9170_regwrite(0x1c3b38, 0x201);
+
+	/* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */
+	/* OTUS set AM to 0x1 */
+	ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170);
+
+	ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
+
+	/* AGG test code*/
+	/* Aggregation MAX number and timeout */
+	ar9170_regwrite(0x1c3b9c, 0x10000a);
+
+	ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
+			AR9170_MAC_REG_FTF_DEFAULTS);
+
+	/* Enable deaggregator, response in sniffer mode */
+	ar9170_regwrite(0x1c3c40, 0x1 | 1<<30);
+
+	/* rate sets */
+	ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f);
+	ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f);
+	ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
+
+	/* MIMO response control */
+	ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28  otus-AM */
+
+	/* switch MAC to OTUS interface */
+	ar9170_regwrite(0x1c3600, 0x3);
+
+	ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff);
+
+	/* set PHY register read timeout (??) */
+	ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008);
+
+	/* Disable Rx TimeOut, workaround for BB. */
+	ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0);
+
+	/* Set CPU clock frequency to 88/80MHz */
+	ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL,
+			AR9170_PWR_CLK_AHB_80_88MHZ |
+			AR9170_PWR_CLK_DAC_160_INV_DLY);
+
+	/* Set WLAN DMA interrupt mode: generate int per packet */
+	ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011);
+
+	ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT,
+			AR9170_MAC_FCS_FIFO_PROT);
+
+	/* Disables the CF_END frame, undocumented register */
+	ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND,
+			0x141E0F48);
+
+	ar9170_regwrite_finish();
+
+	return ar9170_regwrite_result();
+}
+
+static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac)
+{
+	static const u8 zero[ETH_ALEN] = { 0 };
+
+	if (!mac)
+		mac = zero;
+
+	ar9170_regwrite_begin(ar);
+
+	ar9170_regwrite(reg,
+			(mac[3] << 24) | (mac[2] << 16) |
+			(mac[1] << 8) | mac[0]);
+
+	ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]);
+
+	ar9170_regwrite_finish();
+
+	return ar9170_regwrite_result();
+}
+
+int ar9170_update_multicast(struct ar9170 *ar)
+{
+	int err;
+
+	ar9170_regwrite_begin(ar);
+	ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H,
+		ar->want_mc_hash >> 32);
+	ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L,
+		ar->want_mc_hash);
+
+	ar9170_regwrite_finish();
+	err = ar9170_regwrite_result();
+
+	if (err)
+		return err;
+
+	ar->cur_mc_hash = ar->want_mc_hash;
+
+	return 0;
+}
+
+int ar9170_update_frame_filter(struct ar9170 *ar)
+{
+	int err;
+
+	err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER,
+			       ar->want_filter);
+
+	if (err)
+		return err;
+
+	ar->cur_filter = ar->want_filter;
+
+	return 0;
+}
+
+static int ar9170_set_promiscouous(struct ar9170 *ar)
+{
+	u32 encr_mode, sniffer;
+	int err;
+
+	err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer);
+	if (err)
+		return err;
+
+	err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode);
+	if (err)
+		return err;
+
+	if (ar->sniffer_enabled) {
+		sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC;
+
+		/*
+		 * Rx decryption works in place.
+		 *
+		 * If we don't disable it, the hardware will render all
+		 * encrypted frames which are encrypted with an unknown
+		 * key useless.
+		 */
+
+		encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
+		ar->sniffer_enabled = true;
+	} else {
+		sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC;
+
+		if (ar->rx_software_decryption)
+			encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
+		else
+			encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE;
+	}
+
+	ar9170_regwrite_begin(ar);
+	ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode);
+	ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer);
+	ar9170_regwrite_finish();
+
+	return ar9170_regwrite_result();
+}
+
+int ar9170_set_operating_mode(struct ar9170 *ar)
+{
+	u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS;
+	u8 *mac_addr, *bssid;
+	int err;
+
+	if (ar->vif) {
+		mac_addr = ar->mac_addr;
+		bssid = ar->bssid;
+
+		switch (ar->vif->type) {
+		case NL80211_IFTYPE_MESH_POINT:
+		case NL80211_IFTYPE_ADHOC:
+			pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS;
+			break;
+		case NL80211_IFTYPE_AP:
+			pm_mode |= AR9170_MAC_REG_POWERMGT_AP;
+			break;
+		case NL80211_IFTYPE_WDS:
+			pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS;
+			break;
+		case NL80211_IFTYPE_MONITOR:
+			ar->sniffer_enabled = true;
+			ar->rx_software_decryption = true;
+			break;
+		default:
+			pm_mode |= AR9170_MAC_REG_POWERMGT_STA;
+			break;
+		}
+	} else {
+		mac_addr = NULL;
+		bssid = NULL;
+	}
+
+	err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr);
+	if (err)
+		return err;
+
+	err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid);
+	if (err)
+		return err;
+
+	err = ar9170_set_promiscouous(ar);
+	if (err)
+		return err;
+
+	/* set AMPDU density to 8us. */
+	err = ar9170_set_ampdu_density(ar, 6);
+	if (err)
+		return err;
+
+	ar9170_regwrite_begin(ar);
+
+	ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode);
+	ar9170_regwrite_finish();
+
+	return ar9170_regwrite_result();
+}
+
+int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry)
+{
+	u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111);
+
+	return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp);
+}
+
+int ar9170_set_beacon_timers(struct ar9170 *ar)
+{
+	u32 v = 0;
+	u32 pretbtt = 0;
+
+	if (ar->vif) {
+		v |= ar->vif->bss_conf.beacon_int;
+
+		switch (ar->vif->type) {
+		case NL80211_IFTYPE_MESH_POINT:
+		case NL80211_IFTYPE_ADHOC:
+			v |= BIT(25);
+			break;
+		case NL80211_IFTYPE_AP:
+			v |= BIT(24);
+			pretbtt = (ar->vif->bss_conf.beacon_int - 6) << 16;
+			break;
+		default:
+			break;
+		}
+
+		v |= ar->vif->bss_conf.dtim_period << 16;
+	}
+
+	ar9170_regwrite_begin(ar);
+
+	ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
+	ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
+	ar9170_regwrite_finish();
+	return ar9170_regwrite_result();
+}
+
+int ar9170_update_beacon(struct ar9170 *ar)
+{
+	struct sk_buff *skb;
+	__le32 *data, *old = NULL;
+	u32 word;
+	int i;
+
+	skb = ieee80211_beacon_get(ar->hw, ar->vif);
+	if (!skb)
+		return -ENOMEM;
+
+	data = (__le32 *)skb->data;
+	if (ar->beacon)
+		old = (__le32 *)ar->beacon->data;
+
+	ar9170_regwrite_begin(ar);
+	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
+		/*
+		 * XXX: This accesses beyond skb data for up
+		 *	to the last 3 bytes!!
+		 */
+
+		if (old && (data[i] == old[i]))
+			continue;
+
+		word = le32_to_cpu(data[i]);
+		ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word);
+	}
+
+	/* XXX: use skb->cb info */
+	if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+		ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
+				((skb->len + 4) << (3 + 16)) + 0x0400);
+	else
+		ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP,
+				((skb->len + 4) << 16) + 0x001b);
+
+	ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4);
+	ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS);
+	ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1);
+
+	ar9170_regwrite_finish();
+
+	dev_kfree_skb(ar->beacon);
+	ar->beacon = skb;
+
+	return ar9170_regwrite_result();
+}
+
+void ar9170_new_beacon(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170,
+					 beacon_work);
+	struct sk_buff *skb;
+
+	if (unlikely(!IS_STARTED(ar)))
+		return ;
+
+	mutex_lock(&ar->mutex);
+
+	if (!ar->vif)
+		goto out;
+
+	ar9170_update_beacon(ar);
+
+	rcu_read_lock();
+	while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif)))
+		ar9170_op_tx(ar->hw, skb);
+
+	rcu_read_unlock();
+
+ out:
+	mutex_unlock(&ar->mutex);
+}
+
+int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype,
+		      u8 keyidx, u8 *keydata, int keylen)
+{
+	__le32 vals[7];
+	static const u8 bcast[ETH_ALEN] =
+		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+	u8 dummy;
+
+	mac = mac ? : bcast;
+
+	vals[0] = cpu_to_le32((keyidx << 16) + id);
+	vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype);
+	vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 |
+			      mac[3] << 8 | mac[2]);
+	memset(&vals[3], 0, 16);
+	if (keydata)
+		memcpy(&vals[3], keydata, keylen);
+
+	return ar->exec_cmd(ar, AR9170_CMD_EKEY,
+			    sizeof(vals), (u8 *)vals,
+			    1, &dummy);
+}
+
+int ar9170_disable_key(struct ar9170 *ar, u8 id)
+{
+	__le32 val = cpu_to_le32(id);
+	u8 dummy;
+
+	return ar->exec_cmd(ar, AR9170_CMD_EKEY,
+			    sizeof(val), (u8 *)&val,
+			    1, &dummy);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2211 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * mac80211 interaction code
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, Christian Lamparter <chunkeey@web.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.
+ *
+ * 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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+#include "ar9170.h"
+#include "hw.h"
+#include "cmd.h"
+
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+#define RATE(_bitrate, _hw_rate, _txpidx, _flags) {	\
+	.bitrate	= (_bitrate),			\
+	.flags		= (_flags),			\
+	.hw_value	= (_hw_rate) | (_txpidx) << 4,	\
+}
+
+static struct ieee80211_rate __ar9170_ratetable[] = {
+	RATE(10, 0, 0, 0),
+	RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(60, 0xb, 0, 0),
+	RATE(90, 0xf, 0, 0),
+	RATE(120, 0xa, 0, 0),
+	RATE(180, 0xe, 0, 0),
+	RATE(240, 0x9, 0, 0),
+	RATE(360, 0xd, 1, 0),
+	RATE(480, 0x8, 2, 0),
+	RATE(540, 0xc, 3, 0),
+};
+#undef RATE
+
+#define ar9170_g_ratetable	(__ar9170_ratetable + 0)
+#define ar9170_g_ratetable_size	12
+#define ar9170_a_ratetable	(__ar9170_ratetable + 4)
+#define ar9170_a_ratetable_size	8
+
+/*
+ * NB: The hw_value is used as an index into the ar9170_phy_freq_params
+ *     array in phy.c so that we don't have to do frequency lookups!
+ */
+#define CHAN(_freq, _idx) {		\
+	.center_freq	= (_freq),	\
+	.hw_value	= (_idx),	\
+	.max_power	= 18, /* XXX */	\
+}
+
+static struct ieee80211_channel ar9170_2ghz_chantable[] = {
+	CHAN(2412,  0),
+	CHAN(2417,  1),
+	CHAN(2422,  2),
+	CHAN(2427,  3),
+	CHAN(2432,  4),
+	CHAN(2437,  5),
+	CHAN(2442,  6),
+	CHAN(2447,  7),
+	CHAN(2452,  8),
+	CHAN(2457,  9),
+	CHAN(2462, 10),
+	CHAN(2467, 11),
+	CHAN(2472, 12),
+	CHAN(2484, 13),
+};
+
+static struct ieee80211_channel ar9170_5ghz_chantable[] = {
+	CHAN(4920, 14),
+	CHAN(4940, 15),
+	CHAN(4960, 16),
+	CHAN(4980, 17),
+	CHAN(5040, 18),
+	CHAN(5060, 19),
+	CHAN(5080, 20),
+	CHAN(5180, 21),
+	CHAN(5200, 22),
+	CHAN(5220, 23),
+	CHAN(5240, 24),
+	CHAN(5260, 25),
+	CHAN(5280, 26),
+	CHAN(5300, 27),
+	CHAN(5320, 28),
+	CHAN(5500, 29),
+	CHAN(5520, 30),
+	CHAN(5540, 31),
+	CHAN(5560, 32),
+	CHAN(5580, 33),
+	CHAN(5600, 34),
+	CHAN(5620, 35),
+	CHAN(5640, 36),
+	CHAN(5660, 37),
+	CHAN(5680, 38),
+	CHAN(5700, 39),
+	CHAN(5745, 40),
+	CHAN(5765, 41),
+	CHAN(5785, 42),
+	CHAN(5805, 43),
+	CHAN(5825, 44),
+	CHAN(5170, 45),
+	CHAN(5190, 46),
+	CHAN(5210, 47),
+	CHAN(5230, 48),
+};
+#undef CHAN
+
+#define AR9170_HT_CAP							\
+{									\
+	.ht_supported	= true,						\
+	.cap		= IEEE80211_HT_CAP_MAX_AMSDU |			\
+			  IEEE80211_HT_CAP_SUP_WIDTH_20_40 |		\
+			  IEEE80211_HT_CAP_SGI_40 |			\
+			  IEEE80211_HT_CAP_DSSSCCK40 |			\
+			  IEEE80211_HT_CAP_SM_PS,			\
+	.ampdu_factor	= 3,						\
+	.ampdu_density	= 6,						\
+	.mcs		= {						\
+		.rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, },	\
+	},								\
+}
+
+static struct ieee80211_supported_band ar9170_band_2GHz = {
+	.channels	= ar9170_2ghz_chantable,
+	.n_channels	= ARRAY_SIZE(ar9170_2ghz_chantable),
+	.bitrates	= ar9170_g_ratetable,
+	.n_bitrates	= ar9170_g_ratetable_size,
+	.ht_cap		= AR9170_HT_CAP,
+};
+
+static struct ieee80211_supported_band ar9170_band_5GHz = {
+	.channels	= ar9170_5ghz_chantable,
+	.n_channels	= ARRAY_SIZE(ar9170_5ghz_chantable),
+	.bitrates	= ar9170_a_ratetable,
+	.n_bitrates	= ar9170_a_ratetable_size,
+	.ht_cap		= AR9170_HT_CAP,
+};
+
+static void ar9170_tx(struct ar9170 *ar);
+
+#ifdef AR9170_QUEUE_DEBUG
+static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ar9170_tx_control *txc = (void *) skb->data;
+	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+	struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
+	struct ieee80211_hdr *hdr = (void *) txc->frame_data;
+
+	printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x "
+			  "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
+	       wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
+	       ieee80211_get_DA(hdr), arinfo->flags,
+	       le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
+	       jiffies_to_msecs(arinfo->timeout - jiffies));
+}
+
+static void __ar9170_dump_txqueue(struct ar9170 *ar,
+				struct sk_buff_head *queue)
+{
+	struct sk_buff *skb;
+	int i = 0;
+
+	printk(KERN_DEBUG "---[ cut here ]---\n");
+	printk(KERN_DEBUG "%s: %d entries in queue.\n",
+	       wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
+
+	skb_queue_walk(queue, skb) {
+		printk(KERN_DEBUG "index:%d => \n", i++);
+		ar9170_print_txheader(ar, skb);
+	}
+	if (i != skb_queue_len(queue))
+		printk(KERN_DEBUG "WARNING: queue frame counter "
+		       "mismatch %d != %d\n", skb_queue_len(queue), i);
+	printk(KERN_DEBUG "---[ end ]---\n");
+}
+
+static void ar9170_dump_txqueue(struct ar9170 *ar,
+				struct sk_buff_head *queue)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&queue->lock, flags);
+	__ar9170_dump_txqueue(ar, queue);
+	spin_unlock_irqrestore(&queue->lock, flags);
+}
+
+static void __ar9170_dump_txstats(struct ar9170 *ar)
+{
+	int i;
+
+	printk(KERN_DEBUG "%s: QoS queue stats\n",
+	       wiphy_name(ar->hw->wiphy));
+
+	for (i = 0; i < __AR9170_NUM_TXQ; i++)
+		printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d\n",
+		       wiphy_name(ar->hw->wiphy), i, ar->tx_stats[i].limit,
+		       ar->tx_stats[i].len, skb_queue_len(&ar->tx_status[i]));
+}
+
+static void ar9170_dump_txstats(struct ar9170 *ar)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ar->tx_stats_lock, flags);
+	__ar9170_dump_txstats(ar);
+	spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+}
+#endif /* AR9170_QUEUE_DEBUG */
+
+/* caller must guarantee exclusive access for _bin_ queue. */
+static void ar9170_recycle_expired(struct ar9170 *ar,
+				   struct sk_buff_head *queue,
+				   struct sk_buff_head *bin)
+{
+	struct sk_buff *skb, *old = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&queue->lock, flags);
+	while ((skb = skb_peek(queue))) {
+		struct ieee80211_tx_info *txinfo;
+		struct ar9170_tx_info *arinfo;
+
+		txinfo = IEEE80211_SKB_CB(skb);
+		arinfo = (void *) txinfo->rate_driver_data;
+
+		if (time_is_before_jiffies(arinfo->timeout)) {
+#ifdef AR9170_QUEUE_DEBUG
+			printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
+			       "recycle \n", wiphy_name(ar->hw->wiphy),
+			       jiffies, arinfo->timeout);
+			ar9170_print_txheader(ar, skb);
+#endif /* AR9170_QUEUE_DEBUG */
+			__skb_unlink(skb, queue);
+			__skb_queue_tail(bin, skb);
+		} else {
+			break;
+		}
+
+		if (unlikely(old == skb)) {
+			/* bail out - queue is shot. */
+
+			WARN_ON(1);
+			break;
+		}
+		old = skb;
+	}
+	spin_unlock_irqrestore(&queue->lock, flags);
+}
+
+static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
+				    u16 tx_status)
+{
+	struct ieee80211_tx_info *txinfo;
+	unsigned int retries = 0;
+
+	txinfo = IEEE80211_SKB_CB(skb);
+	ieee80211_tx_info_clear_status(txinfo);
+
+	switch (tx_status) {
+	case AR9170_TX_STATUS_RETRY:
+		retries = 2;
+	case AR9170_TX_STATUS_COMPLETE:
+		txinfo->flags |= IEEE80211_TX_STAT_ACK;
+		break;
+
+	case AR9170_TX_STATUS_FAILED:
+		retries = ar->hw->conf.long_frame_max_tx_count;
+		break;
+
+	default:
+		printk(KERN_ERR "%s: invalid tx_status response (%x).\n",
+		       wiphy_name(ar->hw->wiphy), tx_status);
+		break;
+	}
+
+	txinfo->status.rates[0].count = retries + 1;
+	skb_pull(skb, sizeof(struct ar9170_tx_control));
+	ieee80211_tx_status_irqsafe(ar->hw, skb);
+}
+
+void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data;
+	unsigned int queue = skb_get_queue_mapping(skb);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ar->tx_stats_lock, flags);
+	ar->tx_stats[queue].len--;
+
+	if (skb_queue_empty(&ar->tx_pending[queue])) {
+#ifdef AR9170_QUEUE_STOP_DEBUG
+		printk(KERN_DEBUG "%s: wake queue %d\n",
+		       wiphy_name(ar->hw->wiphy), queue);
+		__ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_STOP_DEBUG */
+		ieee80211_wake_queue(ar->hw, queue);
+	}
+	spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+
+	if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) {
+		dev_kfree_skb_any(skb);
+	} else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) {
+		arinfo->timeout = jiffies +
+				  msecs_to_jiffies(AR9170_TX_TIMEOUT);
+
+		skb_queue_tail(&ar->tx_status[queue], skb);
+	} else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) {
+		ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED);
+	} else {
+#ifdef AR9170_QUEUE_DEBUG
+		printk(KERN_DEBUG "%s: unsupported frame flags!\n",
+		       wiphy_name(ar->hw->wiphy));
+		ar9170_print_txheader(ar, skb);
+#endif /* AR9170_QUEUE_DEBUG */
+		dev_kfree_skb_any(skb);
+	}
+
+	if (!ar->tx_stats[queue].len &&
+	    !skb_queue_empty(&ar->tx_pending[queue])) {
+		ar9170_tx(ar);
+	}
+}
+
+static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
+					     const u8 *mac,
+					     struct sk_buff_head *queue,
+					     const u32 rate)
+{
+	unsigned long flags;
+	struct sk_buff *skb;
+
+	/*
+	 * Unfortunately, the firmware does not tell to which (queued) frame
+	 * this transmission status report belongs to.
+	 *
+	 * So we have to make risky guesses - with the scarce information
+	 * the firmware provided (-> destination MAC, and phy_control) -
+	 * and hope that we picked the right one...
+	 */
+
+	spin_lock_irqsave(&queue->lock, flags);
+	skb_queue_walk(queue, skb) {
+		struct ar9170_tx_control *txc = (void *) skb->data;
+		struct ieee80211_hdr *hdr = (void *) txc->frame_data;
+		u32 r;
+
+		if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) {
+#ifdef AR9170_QUEUE_DEBUG
+			printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n",
+			       wiphy_name(ar->hw->wiphy), mac,
+			       ieee80211_get_DA(hdr));
+			ar9170_print_txheader(ar, skb);
+#endif /* AR9170_QUEUE_DEBUG */
+			continue;
+		}
+
+		r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >>
+		    AR9170_TX_PHY_MCS_SHIFT;
+
+		if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) {
+#ifdef AR9170_QUEUE_DEBUG
+			printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n",
+			       wiphy_name(ar->hw->wiphy), rate, r);
+			ar9170_print_txheader(ar, skb);
+#endif /* AR9170_QUEUE_DEBUG */
+			continue;
+		}
+
+		__skb_unlink(skb, queue);
+		spin_unlock_irqrestore(&queue->lock, flags);
+		return skb;
+	}
+
+#ifdef AR9170_QUEUE_DEBUG
+	printk(KERN_ERR "%s: ESS:[%pM] does not have any "
+			"outstanding frames in queue.\n",
+			wiphy_name(ar->hw->wiphy), mac);
+	__ar9170_dump_txqueue(ar, queue);
+#endif /* AR9170_QUEUE_DEBUG */
+	spin_unlock_irqrestore(&queue->lock, flags);
+
+	return NULL;
+}
+
+/*
+ * This worker tries to keeps an maintain tx_status queues.
+ * So we can guarantee that incoming tx_status reports are
+ * actually for a pending frame.
+ */
+
+static void ar9170_tx_janitor(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170,
+					 tx_janitor.work);
+	struct sk_buff_head waste;
+	unsigned int i;
+	bool resched = false;
+
+	if (unlikely(!IS_STARTED(ar)))
+		return ;
+
+	skb_queue_head_init(&waste);
+
+	for (i = 0; i < __AR9170_NUM_TXQ; i++) {
+#ifdef AR9170_QUEUE_DEBUG
+		printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n",
+		       wiphy_name(ar->hw->wiphy), i);
+		ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
+		ar9170_dump_txqueue(ar, &ar->tx_status[i]);
+#endif /* AR9170_QUEUE_DEBUG */
+
+		ar9170_recycle_expired(ar, &ar->tx_status[i], &waste);
+		ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste);
+		skb_queue_purge(&waste);
+
+		if (!skb_queue_empty(&ar->tx_status[i]) ||
+		    !skb_queue_empty(&ar->tx_pending[i]))
+			resched = true;
+	}
+
+	if (resched)
+		queue_delayed_work(ar->hw->workqueue,
+				   &ar->tx_janitor,
+				   msecs_to_jiffies(AR9170_JANITOR_DELAY));
+}
+
+void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
+{
+	struct ar9170_cmd_response *cmd = (void *) buf;
+
+	if ((cmd->type & 0xc0) != 0xc0) {
+		ar->callback_cmd(ar, len, buf);
+		return;
+	}
+
+	/* hardware event handlers */
+	switch (cmd->type) {
+	case 0xc1: {
+		/*
+		 * TX status notification:
+		 * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1
+		 *
+		 * XX always 81
+		 * YY always 00
+		 * M1-M6 is the MAC address
+		 * R1-R4 is the transmit rate
+		 * S1-S2 is the transmit status
+		 */
+
+		struct sk_buff *skb;
+		u32 phy = le32_to_cpu(cmd->tx_status.rate);
+		u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >>
+			AR9170_TX_PHY_QOS_SHIFT;
+#ifdef AR9170_QUEUE_DEBUG
+		printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n",
+		       wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q);
+#endif /* AR9170_QUEUE_DEBUG */
+
+		skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst,
+					    &ar->tx_status[q],
+					    AR9170_TX_INVALID_RATE);
+		if (unlikely(!skb))
+			return ;
+
+		ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status));
+		break;
+		}
+
+	case 0xc0:
+		/*
+		 * pre-TBTT event
+		 */
+		if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
+			queue_work(ar->hw->workqueue, &ar->beacon_work);
+		break;
+
+	case 0xc2:
+		/*
+		 * (IBSS) beacon send notification
+		 * bytes: 04 c2 XX YY B4 B3 B2 B1
+		 *
+		 * XX always 80
+		 * YY always 00
+		 * B1-B4 "should" be the number of send out beacons.
+		 */
+		break;
+
+	case 0xc3:
+		/* End of Atim Window */
+		break;
+
+	case 0xc4:
+	case 0xc5:
+		/* BlockACK events */
+		break;
+
+	case 0xc6:
+		/* Watchdog Interrupt */
+		break;
+
+	case 0xc9:
+		/* retransmission issue / SIFS/EIFS collision ?! */
+		break;
+
+	/* firmware debug */
+	case 0xca:
+		printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4);
+		break;
+	case 0xcb:
+		len -= 4;
+
+		switch (len) {
+		case 1:
+			printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n",
+				*((char *)buf + 4));
+			break;
+		case 2:
+			printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n",
+				le16_to_cpup((__le16 *)((char *)buf + 4)));
+			break;
+		case 4:
+			printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n",
+				le32_to_cpup((__le32 *)((char *)buf + 4)));
+			break;
+		case 8:
+			printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n",
+				(unsigned long)le64_to_cpup(
+						(__le64 *)((char *)buf + 4)));
+			break;
+		}
+		break;
+	case 0xcc:
+		print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE,
+				     (char *)buf + 4, len - 4);
+		break;
+
+	default:
+		printk(KERN_INFO "received unhandled event %x\n", cmd->type);
+		print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
+		break;
+	}
+}
+
+static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar)
+{
+	memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head));
+	ar->rx_mpdu.has_plcp = false;
+}
+
+int ar9170_nag_limiter(struct ar9170 *ar)
+{
+	bool print_message;
+
+	/*
+	 * we expect all sorts of errors in promiscuous mode.
+	 * don't bother with it, it's OK!
+	 */
+	if (ar->sniffer_enabled)
+		return false;
+
+	/*
+	 * only go for frequent errors! The hardware tends to
+	 * do some stupid thing once in a while under load, in
+	 * noisy environments or just for fun!
+	 */
+	if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit())
+		print_message = true;
+	else
+		print_message = false;
+
+	/* reset threshold for "once in a while" */
+	ar->bad_hw_nagger = jiffies + HZ / 4;
+	return print_message;
+}
+
+static int ar9170_rx_mac_status(struct ar9170 *ar,
+				struct ar9170_rx_head *head,
+				struct ar9170_rx_macstatus *mac,
+				struct ieee80211_rx_status *status)
+{
+	u8 error, decrypt;
+
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4);
+
+	error = mac->error;
+	if (error & AR9170_RX_ERROR_MMIC) {
+		status->flag |= RX_FLAG_MMIC_ERROR;
+		error &= ~AR9170_RX_ERROR_MMIC;
+	}
+
+	if (error & AR9170_RX_ERROR_PLCP) {
+		status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+		error &= ~AR9170_RX_ERROR_PLCP;
+
+		if (!(ar->filter_state & FIF_PLCPFAIL))
+			return -EINVAL;
+	}
+
+	if (error & AR9170_RX_ERROR_FCS) {
+		status->flag |= RX_FLAG_FAILED_FCS_CRC;
+		error &= ~AR9170_RX_ERROR_FCS;
+
+		if (!(ar->filter_state & FIF_FCSFAIL))
+			return -EINVAL;
+	}
+
+	decrypt = ar9170_get_decrypt_type(mac);
+	if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
+	    decrypt != AR9170_ENC_ALG_NONE)
+		status->flag |= RX_FLAG_DECRYPTED;
+
+	/* ignore wrong RA errors */
+	error &= ~AR9170_RX_ERROR_WRONG_RA;
+
+	if (error & AR9170_RX_ERROR_DECRYPT) {
+		error &= ~AR9170_RX_ERROR_DECRYPT;
+		/*
+		 * Rx decryption is done in place,
+		 * the original data is lost anyway.
+		 */
+
+		return -EINVAL;
+	}
+
+	/* drop any other error frames */
+	if (unlikely(error)) {
+		/* TODO: update netdevice's RX dropped/errors statistics */
+
+		if (ar9170_nag_limiter(ar))
+			printk(KERN_DEBUG "%s: received frame with "
+			       "suspicious error code (%#x).\n",
+			       wiphy_name(ar->hw->wiphy), error);
+
+		return -EINVAL;
+	}
+
+	status->band = ar->channel->band;
+	status->freq = ar->channel->center_freq;
+
+	switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) {
+	case AR9170_RX_STATUS_MODULATION_CCK:
+		if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
+			status->flag |= RX_FLAG_SHORTPRE;
+		switch (head->plcp[0]) {
+		case 0x0a:
+			status->rate_idx = 0;
+			break;
+		case 0x14:
+			status->rate_idx = 1;
+			break;
+		case 0x37:
+			status->rate_idx = 2;
+			break;
+		case 0x6e:
+			status->rate_idx = 3;
+			break;
+		default:
+			if (ar9170_nag_limiter(ar))
+				printk(KERN_ERR "%s: invalid plcp cck rate "
+				       "(%x).\n", wiphy_name(ar->hw->wiphy),
+				       head->plcp[0]);
+			return -EINVAL;
+		}
+		break;
+
+	case AR9170_RX_STATUS_MODULATION_OFDM:
+		switch (head->plcp[0] & 0xf) {
+		case 0xb:
+			status->rate_idx = 0;
+			break;
+		case 0xf:
+			status->rate_idx = 1;
+			break;
+		case 0xa:
+			status->rate_idx = 2;
+			break;
+		case 0xe:
+			status->rate_idx = 3;
+			break;
+		case 0x9:
+			status->rate_idx = 4;
+			break;
+		case 0xd:
+			status->rate_idx = 5;
+			break;
+		case 0x8:
+			status->rate_idx = 6;
+			break;
+		case 0xc:
+			status->rate_idx = 7;
+			break;
+		default:
+			if (ar9170_nag_limiter(ar))
+				printk(KERN_ERR "%s: invalid plcp ofdm rate "
+				       "(%x).\n", wiphy_name(ar->hw->wiphy),
+				       head->plcp[0]);
+			return -EINVAL;
+		}
+		if (status->band == IEEE80211_BAND_2GHZ)
+			status->rate_idx += 4;
+		break;
+
+	case AR9170_RX_STATUS_MODULATION_HT:
+		if (head->plcp[3] & 0x80)
+			status->flag |= RX_FLAG_40MHZ;
+		if (head->plcp[6] & 0x80)
+			status->flag |= RX_FLAG_SHORT_GI;
+
+		status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f);
+		status->flag |= RX_FLAG_HT;
+		break;
+
+	case AR9170_RX_STATUS_MODULATION_DUPOFDM:
+		/* XXX */
+		if (ar9170_nag_limiter(ar))
+			printk(KERN_ERR "%s: invalid modulation\n",
+			       wiphy_name(ar->hw->wiphy));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void ar9170_rx_phy_status(struct ar9170 *ar,
+				 struct ar9170_rx_phystatus *phy,
+				 struct ieee80211_rx_status *status)
+{
+	int i;
+
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20);
+
+	for (i = 0; i < 3; i++)
+		if (phy->rssi[i] != 0x80)
+			status->antenna |= BIT(i);
+
+	/* post-process RSSI */
+	for (i = 0; i < 7; i++)
+		if (phy->rssi[i] & 0x80)
+			phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f;
+
+	/* TODO: we could do something with phy_errors */
+	status->signal = ar->noise[0] + phy->rssi_combined;
+	status->noise = ar->noise[0];
+}
+
+static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len)
+{
+	struct sk_buff *skb;
+	int reserved = 0;
+	struct ieee80211_hdr *hdr = (void *) buf;
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		reserved += NET_IP_ALIGN;
+
+		if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+			reserved += NET_IP_ALIGN;
+	}
+
+	if (ieee80211_has_a4(hdr->frame_control))
+		reserved += NET_IP_ALIGN;
+
+	reserved = 32 + (reserved & NET_IP_ALIGN);
+
+	skb = dev_alloc_skb(len + reserved);
+	if (likely(skb)) {
+		skb_reserve(skb, reserved);
+		memcpy(skb_put(skb, len), buf, len);
+	}
+
+	return skb;
+}
+
+/*
+ * If the frame alignment is right (or the kernel has
+ * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
+ * is only a single MPDU in the USB frame, then we could
+ * submit to mac80211 the SKB directly. However, since
+ * there may be multiple packets in one SKB in stream
+ * mode, and we need to observe the proper ordering,
+ * this is non-trivial.
+ */
+
+static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+{
+	struct ar9170_rx_head *head;
+	struct ar9170_rx_macstatus *mac;
+	struct ar9170_rx_phystatus *phy = NULL;
+	struct ieee80211_rx_status status;
+	struct sk_buff *skb;
+	int mpdu_len;
+
+	if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac))))
+		return ;
+
+	/* Received MPDU */
+	mpdu_len = len - sizeof(*mac);
+
+	mac = (void *)(buf + mpdu_len);
+	if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) {
+		/* this frame is too damaged and can't be used - drop it */
+
+		return ;
+	}
+
+	switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) {
+	case AR9170_RX_STATUS_MPDU_FIRST:
+		/* first mpdu packet has the plcp header */
+		if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
+			head = (void *) buf;
+			memcpy(&ar->rx_mpdu.plcp, (void *) buf,
+			       sizeof(struct ar9170_rx_head));
+
+			mpdu_len -= sizeof(struct ar9170_rx_head);
+			buf += sizeof(struct ar9170_rx_head);
+			ar->rx_mpdu.has_plcp = true;
+		} else {
+			if (ar9170_nag_limiter(ar))
+				printk(KERN_ERR "%s: plcp info is clipped.\n",
+				       wiphy_name(ar->hw->wiphy));
+			return ;
+		}
+		break;
+
+	case AR9170_RX_STATUS_MPDU_LAST:
+		/* last mpdu has a extra tail with phy status information */
+
+		if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
+			mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+			phy = (void *)(buf + mpdu_len);
+		} else {
+			if (ar9170_nag_limiter(ar))
+				printk(KERN_ERR "%s: frame tail is clipped.\n",
+				       wiphy_name(ar->hw->wiphy));
+			return ;
+		}
+
+	case AR9170_RX_STATUS_MPDU_MIDDLE:
+		/* middle mpdus are just data */
+		if (unlikely(!ar->rx_mpdu.has_plcp)) {
+			if (!ar9170_nag_limiter(ar))
+				return ;
+
+			printk(KERN_ERR "%s: rx stream did not start "
+					"with a first_mpdu frame tag.\n",
+			       wiphy_name(ar->hw->wiphy));
+
+			return ;
+		}
+
+		head = &ar->rx_mpdu.plcp;
+		break;
+
+	case AR9170_RX_STATUS_MPDU_SINGLE:
+		/* single mpdu - has plcp (head) and phy status (tail) */
+		head = (void *) buf;
+
+		mpdu_len -= sizeof(struct ar9170_rx_head);
+		mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+
+		buf += sizeof(struct ar9170_rx_head);
+		phy = (void *)(buf + mpdu_len);
+		break;
+
+	default:
+		BUG_ON(1);
+		break;
+	}
+
+	if (unlikely(mpdu_len < FCS_LEN))
+		return ;
+
+	memset(&status, 0, sizeof(status));
+	if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status)))
+		return ;
+
+	if (phy)
+		ar9170_rx_phy_status(ar, phy, &status);
+
+	skb = ar9170_rx_copy_data(buf, mpdu_len);
+	if (likely(skb))
+		ieee80211_rx_irqsafe(ar->hw, skb, &status);
+}
+
+void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
+{
+	unsigned int i, tlen, resplen, wlen = 0, clen = 0;
+	u8 *tbuf, *respbuf;
+
+	tbuf = skb->data;
+	tlen = skb->len;
+
+	while (tlen >= 4) {
+		clen = tbuf[1] << 8 | tbuf[0];
+		wlen = ALIGN(clen, 4);
+
+		/* check if this is stream has a valid tag.*/
+		if (tbuf[2] != 0 || tbuf[3] != 0x4e) {
+			/*
+			 * TODO: handle the highly unlikely event that the
+			 * corrupted stream has the TAG at the right position.
+			 */
+
+			/* check if the frame can be repaired. */
+			if (!ar->rx_failover_missing) {
+				/* this is no "short read". */
+				if (ar9170_nag_limiter(ar)) {
+					printk(KERN_ERR "%s: missing tag!\n",
+					       wiphy_name(ar->hw->wiphy));
+					goto err_telluser;
+				} else
+					goto err_silent;
+			}
+
+			if (ar->rx_failover_missing > tlen) {
+				if (ar9170_nag_limiter(ar)) {
+					printk(KERN_ERR "%s: possible multi "
+					       "stream corruption!\n",
+					       wiphy_name(ar->hw->wiphy));
+					goto err_telluser;
+				} else
+					goto err_silent;
+			}
+
+			memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+			ar->rx_failover_missing -= tlen;
+
+			if (ar->rx_failover_missing <= 0) {
+				/*
+				 * nested ar9170_rx call!
+				 * termination is guranteed, even when the
+				 * combined frame also have a element with
+				 * a bad tag.
+				 */
+
+				ar->rx_failover_missing = 0;
+				ar9170_rx(ar, ar->rx_failover);
+
+				skb_reset_tail_pointer(ar->rx_failover);
+				skb_trim(ar->rx_failover, 0);
+			}
+
+			return ;
+		}
+
+		/* check if stream is clipped */
+		if (wlen > tlen - 4) {
+			if (ar->rx_failover_missing) {
+				/* TODO: handle double stream corruption. */
+				if (ar9170_nag_limiter(ar)) {
+					printk(KERN_ERR "%s: double rx stream "
+					       "corruption!\n",
+						wiphy_name(ar->hw->wiphy));
+					goto err_telluser;
+				} else
+					goto err_silent;
+			}
+
+			/*
+			 * save incomplete data set.
+			 * the firmware will resend the missing bits when
+			 * the rx - descriptor comes round again.
+			 */
+
+			memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+			ar->rx_failover_missing = clen - tlen;
+			return ;
+		}
+		resplen = clen;
+		respbuf = tbuf + 4;
+		tbuf += wlen + 4;
+		tlen -= wlen + 4;
+
+		i = 0;
+
+		/* weird thing, but this is the same in the original driver */
+		while (resplen > 2 && i < 12 &&
+		       respbuf[0] == 0xff && respbuf[1] == 0xff) {
+			i += 2;
+			resplen -= 2;
+			respbuf += 2;
+		}
+
+		if (resplen < 4)
+			continue;
+
+		/* found the 6 * 0xffff marker? */
+		if (i == 12)
+			ar9170_handle_command_response(ar, respbuf, resplen);
+		else
+			ar9170_handle_mpdu(ar, respbuf, clen);
+	}
+
+	if (tlen) {
+		if (net_ratelimit())
+			printk(KERN_ERR "%s: %d bytes of unprocessed "
+					"data left in rx stream!\n",
+			       wiphy_name(ar->hw->wiphy), tlen);
+
+		goto err_telluser;
+	}
+
+	return ;
+
+err_telluser:
+	printk(KERN_ERR "%s: damaged RX stream data [want:%d, "
+			"data:%d, rx:%d, pending:%d ]\n",
+	       wiphy_name(ar->hw->wiphy), clen, wlen, tlen,
+	       ar->rx_failover_missing);
+
+	if (ar->rx_failover_missing)
+		print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
+				     ar->rx_failover->data,
+				     ar->rx_failover->len);
+
+	print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
+			     skb->data, skb->len);
+
+	printk(KERN_ERR "%s: please check your hardware and cables, if "
+			"you see this message frequently.\n",
+	       wiphy_name(ar->hw->wiphy));
+
+err_silent:
+	if (ar->rx_failover_missing) {
+		skb_reset_tail_pointer(ar->rx_failover);
+		skb_trim(ar->rx_failover, 0);
+		ar->rx_failover_missing = 0;
+	}
+}
+
+#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop)		\
+do {									\
+	queue.aifs = ai_fs;						\
+	queue.cw_min = cwmin;						\
+	queue.cw_max = cwmax;						\
+	queue.txop = _txop;						\
+} while (0)
+
+static int ar9170_op_start(struct ieee80211_hw *hw)
+{
+	struct ar9170 *ar = hw->priv;
+	int err, i;
+
+	mutex_lock(&ar->mutex);
+
+	ar->filter_changed = 0;
+
+	/* reinitialize queues statistics */
+	memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
+	for (i = 0; i < __AR9170_NUM_TXQ; i++)
+		ar->tx_stats[i].limit = AR9170_TXQ_DEPTH;
+
+	/* reset QoS defaults */
+	AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023,  0); /* BEST EFFORT*/
+	AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023,  0); /* BACKGROUND */
+	AR9170_FILL_QUEUE(ar->edcf[2], 2, 7,    15, 94); /* VIDEO */
+	AR9170_FILL_QUEUE(ar->edcf[3], 2, 3,     7, 47); /* VOICE */
+	AR9170_FILL_QUEUE(ar->edcf[4], 2, 3,     7,  0); /* SPECIAL */
+
+	ar->bad_hw_nagger = jiffies;
+
+	err = ar->open(ar);
+	if (err)
+		goto out;
+
+	err = ar9170_init_mac(ar);
+	if (err)
+		goto out;
+
+	err = ar9170_set_qos(ar);
+	if (err)
+		goto out;
+
+	err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ);
+	if (err)
+		goto out;
+
+	err = ar9170_init_rf(ar);
+	if (err)
+		goto out;
+
+	/* start DMA */
+	err = ar9170_write_reg(ar, 0x1c3d30, 0x100);
+	if (err)
+		goto out;
+
+	ar->state = AR9170_STARTED;
+
+out:
+	mutex_unlock(&ar->mutex);
+	return err;
+}
+
+static void ar9170_op_stop(struct ieee80211_hw *hw)
+{
+	struct ar9170 *ar = hw->priv;
+	unsigned int i;
+
+	if (IS_STARTED(ar))
+		ar->state = AR9170_IDLE;
+
+	flush_workqueue(ar->hw->workqueue);
+
+	cancel_delayed_work_sync(&ar->tx_janitor);
+	cancel_work_sync(&ar->filter_config_work);
+	cancel_work_sync(&ar->beacon_work);
+	mutex_lock(&ar->mutex);
+
+	if (IS_ACCEPTING_CMD(ar)) {
+		ar9170_set_leds_state(ar, 0);
+
+		/* stop DMA */
+		ar9170_write_reg(ar, 0x1c3d30, 0);
+		ar->stop(ar);
+	}
+
+	for (i = 0; i < __AR9170_NUM_TXQ; i++) {
+		skb_queue_purge(&ar->tx_pending[i]);
+		skb_queue_purge(&ar->tx_status[i]);
+	}
+	mutex_unlock(&ar->mutex);
+}
+
+static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+	struct ar9170_tx_control *txc;
+	struct ieee80211_tx_info *info;
+	struct ieee80211_tx_rate *txrate;
+	struct ar9170_tx_info *arinfo;
+	unsigned int queue = skb_get_queue_mapping(skb);
+	u16 keytype = 0;
+	u16 len, icv = 0;
+
+	BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
+
+	hdr = (void *)skb->data;
+	info = IEEE80211_SKB_CB(skb);
+	len = skb->len;
+
+	txc = (void *)skb_push(skb, sizeof(*txc));
+
+	if (info->control.hw_key) {
+		icv = info->control.hw_key->icv_len;
+
+		switch (info->control.hw_key->alg) {
+		case ALG_WEP:
+			keytype = AR9170_TX_MAC_ENCR_RC4;
+			break;
+		case ALG_TKIP:
+			keytype = AR9170_TX_MAC_ENCR_RC4;
+			break;
+		case ALG_CCMP:
+			keytype = AR9170_TX_MAC_ENCR_AES;
+			break;
+		default:
+			WARN_ON(1);
+			goto err_out;
+		}
+	}
+
+	/* Length */
+	txc->length = cpu_to_le16(len + icv + 4);
+
+	txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
+				       AR9170_TX_MAC_BACKOFF);
+	txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] <<
+					AR9170_TX_MAC_QOS_SHIFT);
+	txc->mac_control |= cpu_to_le16(keytype);
+	txc->phy_control = cpu_to_le32(0);
+
+	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
+
+	txrate = &info->control.rates[0];
+	if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
+	else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
+		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
+
+	arinfo = (void *)info->rate_driver_data;
+	arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT);
+
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+	     (is_valid_ether_addr(ieee80211_get_DA(hdr)))) {
+		if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+			if (unlikely(!info->control.sta))
+				goto err_out;
+
+			txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
+			arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK;
+			goto out;
+		}
+
+		txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
+		/*
+		 * WARNING:
+		 * Putting the QoS queue bits into an unexplored territory is
+		 * certainly not elegant.
+		 *
+		 * In my defense: This idea provides a reasonable way to
+		 * smuggle valuable information to the tx_status callback.
+		 * Also, the idea behind this bit-abuse came straight from
+		 * the original driver code.
+		 */
+
+		txc->phy_control |=
+			cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
+		arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK;
+	} else {
+		arinfo->flags = AR9170_TX_FLAG_NO_ACK;
+	}
+
+out:
+	return 0;
+
+err_out:
+	skb_pull(skb, sizeof(*txc));
+	return -EINVAL;
+}
+
+static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ar9170_tx_control *txc;
+	struct ieee80211_tx_info *info;
+	struct ieee80211_rate *rate = NULL;
+	struct ieee80211_tx_rate *txrate;
+	u32 power, chains;
+
+	txc = (void *) skb->data;
+	info = IEEE80211_SKB_CB(skb);
+	txrate = &info->control.rates[0];
+
+	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
+
+	if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
+
+	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ);
+	/* this works because 40 MHz is 2 and dup is 3 */
+	if (txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP);
+
+	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
+
+	if (txrate->flags & IEEE80211_TX_RC_MCS) {
+		u32 r = txrate->idx;
+		u8 *txpower;
+
+		/* heavy clip control */
+		txc->phy_control |= cpu_to_le32((r & 0x7) << 7);
+
+		r <<= AR9170_TX_PHY_MCS_SHIFT;
+		BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK);
+
+		txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK);
+		txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
+
+		if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+			if (info->band == IEEE80211_BAND_5GHZ)
+				txpower = ar->power_5G_ht40;
+			else
+				txpower = ar->power_2G_ht40;
+		} else {
+			if (info->band == IEEE80211_BAND_5GHZ)
+				txpower = ar->power_5G_ht20;
+			else
+				txpower = ar->power_2G_ht20;
+		}
+
+		power = txpower[(txrate->idx) & 7];
+	} else {
+		u8 *txpower;
+		u32 mod;
+		u32 phyrate;
+		u8 idx = txrate->idx;
+
+		if (info->band != IEEE80211_BAND_2GHZ) {
+			idx += 4;
+			txpower = ar->power_5G_leg;
+			mod = AR9170_TX_PHY_MOD_OFDM;
+		} else {
+			if (idx < 4) {
+				txpower = ar->power_2G_cck;
+				mod = AR9170_TX_PHY_MOD_CCK;
+			} else {
+				mod = AR9170_TX_PHY_MOD_OFDM;
+				txpower = ar->power_2G_ofdm;
+			}
+		}
+
+		rate = &__ar9170_ratetable[idx];
+
+		phyrate = rate->hw_value & 0xF;
+		power = txpower[(rate->hw_value & 0x30) >> 4];
+		phyrate <<= AR9170_TX_PHY_MCS_SHIFT;
+
+		txc->phy_control |= cpu_to_le32(mod);
+		txc->phy_control |= cpu_to_le32(phyrate);
+	}
+
+	power <<= AR9170_TX_PHY_TX_PWR_SHIFT;
+	power &= AR9170_TX_PHY_TX_PWR_MASK;
+	txc->phy_control |= cpu_to_le32(power);
+
+	/* set TX chains */
+	if (ar->eeprom.tx_mask == 1) {
+		chains = AR9170_TX_PHY_TXCHAIN_1;
+	} else {
+		chains = AR9170_TX_PHY_TXCHAIN_2;
+
+		/* >= 36M legacy OFDM - use only one chain */
+		if (rate && rate->bitrate >= 360)
+			chains = AR9170_TX_PHY_TXCHAIN_1;
+	}
+	txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
+}
+
+static void ar9170_tx(struct ar9170 *ar)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+	struct ieee80211_tx_info *info;
+	struct ar9170_tx_info *arinfo;
+	unsigned int i, frames, frames_failed, remaining_space;
+	int err;
+	bool schedule_garbagecollector = false;
+
+	BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
+
+	if (unlikely(!IS_STARTED(ar)))
+		return ;
+
+	remaining_space = AR9170_TX_MAX_PENDING;
+
+	for (i = 0; i < __AR9170_NUM_TXQ; i++) {
+		spin_lock_irqsave(&ar->tx_stats_lock, flags);
+		if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
+#ifdef AR9170_QUEUE_DEBUG
+			printk(KERN_DEBUG "%s: queue %d full\n",
+			       wiphy_name(ar->hw->wiphy), i);
+
+			__ar9170_dump_txstats(ar);
+			printk(KERN_DEBUG "stuck frames: ===> \n");
+			ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
+			ar9170_dump_txqueue(ar, &ar->tx_status[i]);
+#endif /* AR9170_QUEUE_DEBUG */
+			ieee80211_stop_queue(ar->hw, i);
+			spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+			continue;
+		}
+
+		frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len,
+			     skb_queue_len(&ar->tx_pending[i]));
+
+		if (remaining_space < frames) {
+#ifdef AR9170_QUEUE_DEBUG
+			printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
+			       "remaining slots:%d, needed:%d\n",
+			       wiphy_name(ar->hw->wiphy), i, remaining_space,
+			       frames);
+
+			ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_DEBUG */
+			frames = remaining_space;
+		}
+
+		ar->tx_stats[i].len += frames;
+		ar->tx_stats[i].count += frames;
+		spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+
+		if (!frames)
+			continue;
+
+		frames_failed = 0;
+		while (frames) {
+			skb = skb_dequeue(&ar->tx_pending[i]);
+			if (unlikely(!skb)) {
+				frames_failed += frames;
+				frames = 0;
+				break;
+			}
+
+			info = IEEE80211_SKB_CB(skb);
+			arinfo = (void *) info->rate_driver_data;
+
+			/* TODO: cancel stuck frames */
+			arinfo->timeout = jiffies +
+					  msecs_to_jiffies(AR9170_TX_TIMEOUT);
+
+#ifdef AR9170_QUEUE_DEBUG
+			printk(KERN_DEBUG "%s: send frame q:%d =>\n",
+			       wiphy_name(ar->hw->wiphy), i);
+			ar9170_print_txheader(ar, skb);
+#endif /* AR9170_QUEUE_DEBUG */
+
+			err = ar->tx(ar, skb);
+			if (unlikely(err)) {
+				frames_failed++;
+				dev_kfree_skb_any(skb);
+			} else {
+				remaining_space--;
+				schedule_garbagecollector = true;
+			}
+
+			frames--;
+		}
+
+#ifdef AR9170_QUEUE_DEBUG
+		printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n",
+		       wiphy_name(ar->hw->wiphy), i);
+
+		printk(KERN_DEBUG "%s: unprocessed pending frames left:\n",
+		       wiphy_name(ar->hw->wiphy));
+		ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
+#endif /* AR9170_QUEUE_DEBUG */
+
+		if (unlikely(frames_failed)) {
+#ifdef AR9170_QUEUE_DEBUG
+			printk(KERN_DEBUG "%s: frames failed =>\n",
+			       wiphy_name(ar->hw->wiphy), frames_failed);
+#endif /* AR9170_QUEUE_DEBUG */
+
+			spin_lock_irqsave(&ar->tx_stats_lock, flags);
+			ar->tx_stats[i].len -= frames_failed;
+			ar->tx_stats[i].count -= frames_failed;
+			ieee80211_wake_queue(ar->hw, i);
+			spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+		}
+	}
+
+	if (schedule_garbagecollector)
+		queue_delayed_work(ar->hw->workqueue,
+				   &ar->tx_janitor,
+				   msecs_to_jiffies(AR9170_JANITOR_DELAY));
+}
+
+int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ar9170 *ar = hw->priv;
+	struct ieee80211_tx_info *info;
+
+	if (unlikely(!IS_STARTED(ar)))
+		goto err_free;
+
+	if (unlikely(ar9170_tx_prepare(ar, skb)))
+		goto err_free;
+
+	info = IEEE80211_SKB_CB(skb);
+	if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+		/* drop frame, we do not allow TX A-MPDU aggregation yet. */
+		goto err_free;
+	} else {
+		unsigned int queue = skb_get_queue_mapping(skb);
+
+		ar9170_tx_prepare_phy(ar, skb);
+		skb_queue_tail(&ar->tx_pending[queue], skb);
+	}
+
+	ar9170_tx(ar);
+	return NETDEV_TX_OK;
+
+err_free:
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static int ar9170_op_add_interface(struct ieee80211_hw *hw,
+				   struct ieee80211_if_init_conf *conf)
+{
+	struct ar9170 *ar = hw->priv;
+	int err = 0;
+
+	mutex_lock(&ar->mutex);
+
+	if (ar->vif) {
+		err = -EBUSY;
+		goto unlock;
+	}
+
+	ar->vif = conf->vif;
+	memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN);
+
+	if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
+		ar->rx_software_decryption = true;
+		ar->disable_offload = true;
+	}
+
+	ar->cur_filter = 0;
+	ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS;
+	err = ar9170_update_frame_filter(ar);
+	if (err)
+		goto unlock;
+
+	err = ar9170_set_operating_mode(ar);
+
+unlock:
+	mutex_unlock(&ar->mutex);
+	return err;
+}
+
+static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
+				       struct ieee80211_if_init_conf *conf)
+{
+	struct ar9170 *ar = hw->priv;
+
+	mutex_lock(&ar->mutex);
+	ar->vif = NULL;
+	ar->want_filter = 0;
+	ar9170_update_frame_filter(ar);
+	ar9170_set_beacon_timers(ar);
+	dev_kfree_skb(ar->beacon);
+	ar->beacon = NULL;
+	ar->sniffer_enabled = false;
+	ar->rx_software_decryption = false;
+	ar9170_set_operating_mode(ar);
+	mutex_unlock(&ar->mutex);
+}
+
+static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ar9170 *ar = hw->priv;
+	int err = 0;
+
+	mutex_lock(&ar->mutex);
+
+	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
+		/* TODO */
+		err = 0;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_PS) {
+		/* TODO */
+		err = 0;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		/* TODO */
+		err = 0;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
+		/*
+		 * is it long_frame_max_tx_count or short_frame_max_tx_count?
+		 */
+
+		err = ar9170_set_hwretry_limit(ar,
+			ar->hw->conf.long_frame_max_tx_count);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		err = ar9170_set_beacon_timers(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+
+		/* adjust slot time for 5 GHz */
+		err = ar9170_set_slot_time(ar);
+		if (err)
+			goto out;
+
+		err = ar9170_set_dyn_sifs_ack(ar);
+		if (err)
+			goto out;
+
+		err = ar9170_set_channel(ar, hw->conf.channel,
+				AR9170_RFI_NONE,
+				nl80211_to_ar9170(hw->conf.channel_type));
+		if (err)
+			goto out;
+	}
+
+out:
+	mutex_unlock(&ar->mutex);
+	return err;
+}
+
+static void ar9170_set_filters(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170,
+					 filter_config_work);
+	int err;
+
+	if (unlikely(!IS_STARTED(ar)))
+		return ;
+
+	mutex_lock(&ar->mutex);
+	if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE,
+			       &ar->filter_changed)) {
+		err = ar9170_set_operating_mode(ar);
+		if (err)
+			goto unlock;
+	}
+
+	if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST,
+			       &ar->filter_changed)) {
+		err = ar9170_update_multicast(ar);
+		if (err)
+			goto unlock;
+	}
+
+	if (test_and_clear_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
+			       &ar->filter_changed)) {
+		err = ar9170_update_frame_filter(ar);
+		if (err)
+			goto unlock;
+	}
+
+unlock:
+	mutex_unlock(&ar->mutex);
+}
+
+static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
+				       unsigned int changed_flags,
+				       unsigned int *new_flags,
+				       int mc_count, struct dev_mc_list *mclist)
+{
+	struct ar9170 *ar = hw->priv;
+
+	/* mask supported flags */
+	*new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
+		      FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL;
+	ar->filter_state = *new_flags;
+	/*
+	 * We can support more by setting the sniffer bit and
+	 * then checking the error flags, later.
+	 */
+
+	if (changed_flags & FIF_ALLMULTI) {
+		if (*new_flags & FIF_ALLMULTI) {
+			ar->want_mc_hash = ~0ULL;
+		} else {
+			u64 mchash;
+			int i;
+
+			/* always get broadcast frames */
+			mchash = 1ULL << (0xff >> 2);
+
+			for (i = 0; i < mc_count; i++) {
+				if (WARN_ON(!mclist))
+					break;
+				mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
+				mclist = mclist->next;
+			}
+		ar->want_mc_hash = mchash;
+		}
+		set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed);
+	}
+
+	if (changed_flags & FIF_CONTROL) {
+		u32 filter = AR9170_MAC_REG_FTF_PSPOLL |
+			     AR9170_MAC_REG_FTF_RTS |
+			     AR9170_MAC_REG_FTF_CTS |
+			     AR9170_MAC_REG_FTF_ACK |
+			     AR9170_MAC_REG_FTF_CFE |
+			     AR9170_MAC_REG_FTF_CFE_ACK;
+
+		if (*new_flags & FIF_CONTROL)
+			ar->want_filter = ar->cur_filter | filter;
+		else
+			ar->want_filter = ar->cur_filter & ~filter;
+
+		set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER,
+			&ar->filter_changed);
+	}
+
+	if (changed_flags & FIF_PROMISC_IN_BSS) {
+		ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
+		set_bit(AR9170_FILTER_CHANGED_MODE,
+			&ar->filter_changed);
+	}
+
+	if (likely(IS_STARTED(ar)))
+		queue_work(ar->hw->workqueue, &ar->filter_config_work);
+}
+
+static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_bss_conf *bss_conf,
+				       u32 changed)
+{
+	struct ar9170 *ar = hw->priv;
+	int err = 0;
+
+	mutex_lock(&ar->mutex);
+
+	if (changed & BSS_CHANGED_BSSID) {
+		memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN);
+		err = ar9170_set_operating_mode(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) {
+		err = ar9170_update_beacon(ar);
+		if (err)
+			goto out;
+
+		err = ar9170_set_beacon_timers(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_ASSOC) {
+#ifndef CONFIG_AR9170_LEDS
+		/* enable assoc LED. */
+		err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0);
+#endif /* CONFIG_AR9170_LEDS */
+	}
+
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		err = ar9170_set_beacon_timers(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_HT) {
+		/* TODO */
+		err = 0;
+	}
+
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		err = ar9170_set_slot_time(ar);
+		if (err)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_BASIC_RATES) {
+		err = ar9170_set_basic_rates(ar);
+		if (err)
+			goto out;
+	}
+
+out:
+	mutex_unlock(&ar->mutex);
+}
+
+static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
+{
+	struct ar9170 *ar = hw->priv;
+	int err;
+	u32 tsf_low;
+	u32 tsf_high;
+	u64 tsf;
+
+	mutex_lock(&ar->mutex);
+	err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low);
+	if (!err)
+		err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high);
+	mutex_unlock(&ar->mutex);
+
+	if (WARN_ON(err))
+		return 0;
+
+	tsf = tsf_high;
+	tsf = (tsf << 32) | tsf_low;
+	return tsf;
+}
+
+static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+			  struct ieee80211_key_conf *key)
+{
+	struct ar9170 *ar = hw->priv;
+	int err = 0, i;
+	u8 ktype;
+
+	if ((!ar->vif) || (ar->disable_offload))
+		return -EOPNOTSUPP;
+
+	switch (key->alg) {
+	case ALG_WEP:
+		if (key->keylen == WLAN_KEY_LEN_WEP40)
+			ktype = AR9170_ENC_ALG_WEP64;
+		else
+			ktype = AR9170_ENC_ALG_WEP128;
+		break;
+	case ALG_TKIP:
+		ktype = AR9170_ENC_ALG_TKIP;
+		break;
+	case ALG_CCMP:
+		ktype = AR9170_ENC_ALG_AESCCMP;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	mutex_lock(&ar->mutex);
+	if (cmd == SET_KEY) {
+		if (unlikely(!IS_STARTED(ar))) {
+			err = -EOPNOTSUPP;
+			goto out;
+		}
+
+		/* group keys need all-zeroes address */
+		if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+			sta = NULL;
+
+		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
+			for (i = 0; i < 64; i++)
+				if (!(ar->usedkeys & BIT(i)))
+					break;
+			if (i == 64) {
+				ar->rx_software_decryption = true;
+				ar9170_set_operating_mode(ar);
+				err = -ENOSPC;
+				goto out;
+			}
+		} else {
+			i = 64 + key->keyidx;
+		}
+
+		key->hw_key_idx = i;
+
+		err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0,
+					key->key, min_t(u8, 16, key->keylen));
+		if (err)
+			goto out;
+
+		if (key->alg == ALG_TKIP) {
+			err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL,
+						ktype, 1, key->key + 16, 16);
+			if (err)
+				goto out;
+
+			/*
+			 * hardware is not capable generating the MMIC
+			 * for fragmented frames!
+			 */
+			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+		}
+
+		if (i < 64)
+			ar->usedkeys |= BIT(i);
+
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+	} else {
+		if (unlikely(!IS_STARTED(ar))) {
+			/* The device is gone... together with the key ;-) */
+			err = 0;
+			goto out;
+		}
+
+		err = ar9170_disable_key(ar, key->hw_key_idx);
+		if (err)
+			goto out;
+
+		if (key->hw_key_idx < 64) {
+			ar->usedkeys &= ~BIT(key->hw_key_idx);
+		} else {
+			err = ar9170_upload_key(ar, key->hw_key_idx, NULL,
+						AR9170_ENC_ALG_NONE, 0,
+						NULL, 0);
+			if (err)
+				goto out;
+
+			if (key->alg == ALG_TKIP) {
+				err = ar9170_upload_key(ar, key->hw_key_idx,
+							NULL,
+							AR9170_ENC_ALG_NONE, 1,
+							NULL, 0);
+				if (err)
+					goto out;
+			}
+
+		}
+	}
+
+	ar9170_regwrite_begin(ar);
+	ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys);
+	ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32);
+	ar9170_regwrite_finish();
+	err = ar9170_regwrite_result();
+
+out:
+	mutex_unlock(&ar->mutex);
+
+	return err;
+}
+
+static void ar9170_sta_notify(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif,
+			      enum sta_notify_cmd cmd,
+			      struct ieee80211_sta *sta)
+{
+}
+
+static int ar9170_get_stats(struct ieee80211_hw *hw,
+			    struct ieee80211_low_level_stats *stats)
+{
+	struct ar9170 *ar = hw->priv;
+	u32 val;
+	int err;
+
+	mutex_lock(&ar->mutex);
+	err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val);
+	ar->stats.dot11ACKFailureCount += val;
+
+	memcpy(stats, &ar->stats, sizeof(*stats));
+	mutex_unlock(&ar->mutex);
+
+	return 0;
+}
+
+static int ar9170_get_tx_stats(struct ieee80211_hw *hw,
+			       struct ieee80211_tx_queue_stats *tx_stats)
+{
+	struct ar9170 *ar = hw->priv;
+
+	spin_lock_bh(&ar->tx_stats_lock);
+	memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues);
+	spin_unlock_bh(&ar->tx_stats_lock);
+
+	return 0;
+}
+
+static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			  const struct ieee80211_tx_queue_params *param)
+{
+	struct ar9170 *ar = hw->priv;
+	int ret;
+
+	mutex_lock(&ar->mutex);
+	if (queue < __AR9170_NUM_TXQ) {
+		memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
+		       param, sizeof(*param));
+
+		ret = ar9170_set_qos(ar);
+	} else {
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&ar->mutex);
+	return ret;
+}
+
+static int ar9170_ampdu_action(struct ieee80211_hw *hw,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+{
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/*
+		 * Something goes wrong -- RX locks up
+		 * after a while of receiving aggregated
+		 * frames -- not enabling for now.
+		 */
+		return -EOPNOTSUPP;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static const struct ieee80211_ops ar9170_ops = {
+	.start			= ar9170_op_start,
+	.stop			= ar9170_op_stop,
+	.tx			= ar9170_op_tx,
+	.add_interface		= ar9170_op_add_interface,
+	.remove_interface	= ar9170_op_remove_interface,
+	.config			= ar9170_op_config,
+	.configure_filter	= ar9170_op_configure_filter,
+	.conf_tx		= ar9170_conf_tx,
+	.bss_info_changed	= ar9170_op_bss_info_changed,
+	.get_tsf		= ar9170_op_get_tsf,
+	.set_key		= ar9170_set_key,
+	.sta_notify		= ar9170_sta_notify,
+	.get_stats		= ar9170_get_stats,
+	.get_tx_stats		= ar9170_get_tx_stats,
+	.ampdu_action		= ar9170_ampdu_action,
+};
+
+void *ar9170_alloc(size_t priv_size)
+{
+	struct ieee80211_hw *hw;
+	struct ar9170 *ar;
+	struct sk_buff *skb;
+	int i;
+
+	/*
+	 * this buffer is used for rx stream reconstruction.
+	 * Under heavy load this device (or the transport layer?)
+	 * tends to split the streams into seperate rx descriptors.
+	 */
+
+	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
+	if (!skb)
+		goto err_nomem;
+
+	hw = ieee80211_alloc_hw(priv_size, &ar9170_ops);
+	if (!hw)
+		goto err_nomem;
+
+	ar = hw->priv;
+	ar->hw = hw;
+	ar->rx_failover = skb;
+
+	mutex_init(&ar->mutex);
+	spin_lock_init(&ar->cmdlock);
+	spin_lock_init(&ar->tx_stats_lock);
+	for (i = 0; i < __AR9170_NUM_TXQ; i++) {
+		skb_queue_head_init(&ar->tx_status[i]);
+		skb_queue_head_init(&ar->tx_pending[i]);
+	}
+	ar9170_rx_reset_rx_mpdu(ar);
+	INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
+	INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
+	INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
+
+	/* all hw supports 2.4 GHz, so set channel to 1 by default */
+	ar->channel = &ar9170_2ghz_chantable[0];
+
+	/* first part of wiphy init */
+	ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+					 BIT(NL80211_IFTYPE_WDS) |
+					 BIT(NL80211_IFTYPE_ADHOC);
+	ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
+			 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+			 IEEE80211_HW_SIGNAL_DBM |
+			 IEEE80211_HW_NOISE_DBM;
+
+	ar->hw->queues = __AR9170_NUM_TXQ;
+	ar->hw->extra_tx_headroom = 8;
+	ar->hw->sta_data_size = sizeof(struct ar9170_sta_info);
+
+	ar->hw->max_rates = 1;
+	ar->hw->max_rate_tries = 3;
+
+	for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
+		ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
+
+	return ar;
+
+err_nomem:
+	kfree_skb(skb);
+	return ERR_PTR(-ENOMEM);
+}
+
+static int ar9170_read_eeprom(struct ar9170 *ar)
+{
+#define RW	8	/* number of words to read at once */
+#define RB	(sizeof(u32) * RW)
+	DECLARE_MAC_BUF(mbuf);
+	u8 *eeprom = (void *)&ar->eeprom;
+	u8 *addr = ar->eeprom.mac_address;
+	__le32 offsets[RW];
+	int i, j, err, bands = 0;
+
+	BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
+
+	BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4);
+#ifndef __CHECKER__
+	/* don't want to handle trailing remains */
+	BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
+#endif
+
+	for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
+		for (j = 0; j < RW; j++)
+			offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
+						 RB * i + 4 * j);
+
+		err = ar->exec_cmd(ar, AR9170_CMD_RREG,
+				   RB, (u8 *) &offsets,
+				   RB, eeprom + RB * i);
+		if (err)
+			return err;
+	}
+
+#undef RW
+#undef RB
+
+	if (ar->eeprom.length == cpu_to_le16(0xFFFF))
+		return -ENODATA;
+
+	if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
+		ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz;
+		bands++;
+	}
+	if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
+		ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz;
+		bands++;
+	}
+	/*
+	 * I measured this, a bandswitch takes roughly
+	 * 135 ms and a frequency switch about 80.
+	 *
+	 * FIXME: measure these values again once EEPROM settings
+	 *	  are used, that will influence them!
+	 */
+	if (bands == 2)
+		ar->hw->channel_change_time = 135 * 1000;
+	else
+		ar->hw->channel_change_time = 80 * 1000;
+
+	ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
+	ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
+
+	/* second part of wiphy init */
+	SET_IEEE80211_PERM_ADDR(ar->hw, addr);
+
+	return bands ? 0 : -EINVAL;
+}
+
+static int ar9170_reg_notifier(struct wiphy *wiphy,
+			struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ar9170 *ar = hw->priv;
+
+	return ath_reg_notifier_apply(wiphy, request, &ar->regulatory);
+}
+
+int ar9170_register(struct ar9170 *ar, struct device *pdev)
+{
+	int err;
+
+	/* try to read EEPROM, init MAC addr */
+	err = ar9170_read_eeprom(ar);
+	if (err)
+		goto err_out;
+
+	err = ath_regd_init(&ar->regulatory, ar->hw->wiphy,
+			    ar9170_reg_notifier);
+	if (err)
+		goto err_out;
+
+	err = ieee80211_register_hw(ar->hw);
+	if (err)
+		goto err_out;
+
+	if (!ath_is_world_regd(&ar->regulatory))
+		regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2);
+
+	err = ar9170_init_leds(ar);
+	if (err)
+		goto err_unreg;
+
+#ifdef CONFIG_AR9170_LEDS
+	err = ar9170_register_leds(ar);
+	if (err)
+		goto err_unreg;
+#endif /* CONFIG_AR9170_LEDS */
+
+	dev_info(pdev, "Atheros AR9170 is registered as '%s'\n",
+		 wiphy_name(ar->hw->wiphy));
+
+	return err;
+
+err_unreg:
+	ieee80211_unregister_hw(ar->hw);
+
+err_out:
+	return err;
+}
+
+void ar9170_unregister(struct ar9170 *ar)
+{
+#ifdef CONFIG_AR9170_LEDS
+	ar9170_unregister_leds(ar);
+#endif /* CONFIG_AR9170_LEDS */
+
+	kfree_skb(ar->rx_failover);
+	ieee80211_unregister_hw(ar->hw);
+	mutex_destroy(&ar->mutex);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3 @@
+ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o
+
+obj-$(CONFIG_AR9170_USB) += ar9170usb.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/phy.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1240 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * PHY and RF code
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/bitrev.h>
+#include "ar9170.h"
+#include "cmd.h"
+
+static int ar9170_init_power_cal(struct ar9170 *ar)
+{
+	ar9170_regwrite_begin(ar);
+
+	ar9170_regwrite(0x1bc000 + 0x993c, 0x7f);
+	ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f);
+	ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f);
+
+	ar9170_regwrite_finish();
+	return ar9170_regwrite_result();
+}
+
+struct ar9170_phy_init {
+	u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20;
+};
+
+static struct ar9170_phy_init ar5416_phy_init[] = {
+	{ 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, },
+	{ 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, },
+	{ 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, },
+	{ 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, },
+	{ 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, },
+	{ 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, },
+	{ 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
+	{ 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, },
+	{ 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
+	{ 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
+	{ 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, },
+	{ 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, },
+	{ 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, },
+	{ 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, },
+	{ 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, },
+	{ 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, },
+	{ 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, },
+	{ 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, },
+	{ 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, },
+	{ 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, },
+	{ 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, },
+	{ 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, },
+	{ 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, },
+	{ 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, },
+	{ 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, },
+	{ 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, },
+	{ 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, },
+	{ 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
+	{ 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, },
+	{ 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, },
+	{ 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, },
+	{ 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, },
+	{ 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, },
+	{ 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, },
+	{ 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+	{ 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, },
+	{ 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, },
+	{ 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, },
+	{ 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, },
+	{ 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, },
+	{ 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, },
+	{ 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, },
+	{ 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, },
+	{ 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, },
+	{ 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, },
+	{ 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, },
+	{ 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, },
+	{ 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, },
+	{ 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, },
+	{ 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, },
+	{ 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, },
+	{ 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, },
+	{ 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, },
+	{ 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, },
+	{ 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, },
+	{ 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, },
+	{ 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, },
+	{ 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, },
+	{ 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, },
+	{ 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, },
+	{ 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
+	{ 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, },
+	{ 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, },
+	{ 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, },
+	{ 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, },
+	{ 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, },
+	{ 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, },
+	{ 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, },
+	{ 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, },
+	{ 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, },
+	{ 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, },
+	{ 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, },
+	{ 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, },
+	{ 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, },
+	{ 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, },
+	{ 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, },
+	{ 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, },
+	{ 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, },
+	{ 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, },
+	{ 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, },
+	{ 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, },
+	{ 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, },
+	{ 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, },
+	{ 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, },
+	{ 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, },
+	{ 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, },
+	{ 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, },
+	{ 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, },
+	{ 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, },
+	{ 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, },
+	{ 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+	{ 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, },
+	{ 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, },
+	{ 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
+	{ 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, },
+	{ 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, },
+	{ 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, },
+	{ 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, },
+	{ 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, },
+	{ 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, },
+	{ 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, },
+	{ 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
+	{ 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, },
+	{ 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, },
+	{ 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, },
+	{ 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, },
+	{ 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, },
+	{ 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, },
+	{ 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, },
+	{ 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
+	{ 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, },
+	{ 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, },
+	{ 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, },
+	{ 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, },
+	{ 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, },
+	{ 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, },
+	{ 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, },
+	{ 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, },
+	{ 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, },
+	{ 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
+	{ 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, },
+	{ 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, },
+	{ 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, },
+	{ 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, },
+	{ 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, },
+	{ 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, },
+	{ 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, },
+	{ 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, },
+	{ 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, },
+	{ 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, },
+	{ 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+	{ 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
+	{ 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
+	{ 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, },
+	{ 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, },
+	{ 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, },
+	{ 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+	{ 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, },
+	{ 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, },
+	{ 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, },
+	{ 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, },
+	{ 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, },
+	{ 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, },
+	{ 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, },
+	{ 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, },
+	{ 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, },
+	{ 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, },
+	{ 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, },
+	{ 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, },
+	{ 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+	{ 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
+	{ 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, },
+	{ 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, },
+	{ 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, },
+	{ 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, },
+	{ 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+	{ 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, },
+	{ 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+	{ 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, },
+	{ 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, },
+	{ 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, },
+	{ 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, },
+	{ 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, },
+	{ 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, },
+	{ 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, },
+	{ 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, },
+	{ 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, },
+	{ 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, },
+	{ 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, },
+	{ 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, },
+	{ 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+	{ 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+	{ 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+	{ 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, },
+	{ 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, },
+	{ 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, },
+	{ 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+	{ 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, },
+	{ 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+	{ 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+	{ 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+	{ 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+	{ 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, },
+	{ 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
+	{ 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
+	{ 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+	{ 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+	{ 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+	{ 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
+	{ 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
+	{ 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+	{ 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+	{ 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+/*	{ 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */
+	{ 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, },
+	{ 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, },
+	{ 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, },
+	{ 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, },
+	{ 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, },
+	{ 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, },
+	{ 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, },
+	{ 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, },
+	{ 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, },
+	{ 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, },
+	{ 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, },
+	{ 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, },
+	{ 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, },
+	{ 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, },
+	{ 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, },
+	{ 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
+};
+
+int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
+{
+	int i, err;
+	u32 val;
+	bool is_2ghz = band == IEEE80211_BAND_2GHZ;
+	bool is_40mhz = conf_is_ht40(&ar->hw->conf);
+
+	ar9170_regwrite_begin(ar);
+
+	for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
+		if (is_40mhz) {
+			if (is_2ghz)
+				val = ar5416_phy_init[i]._2ghz_40;
+			else
+				val = ar5416_phy_init[i]._5ghz_40;
+		} else {
+			if (is_2ghz)
+				val = ar5416_phy_init[i]._2ghz_20;
+			else
+				val = ar5416_phy_init[i]._5ghz_20;
+		}
+
+		ar9170_regwrite(ar5416_phy_init[i].reg, val);
+	}
+
+	ar9170_regwrite_finish();
+	err = ar9170_regwrite_result();
+	if (err)
+		return err;
+
+	/* XXX: use EEPROM data here! */
+
+	err = ar9170_init_power_cal(ar);
+	if (err)
+		return err;
+
+	/* XXX: remove magic! */
+	if (is_2ghz)
+		err = ar9170_write_reg(ar, 0x1d4014, 0x5163);
+	else
+		err = ar9170_write_reg(ar, 0x1d4014, 0x5143);
+
+	return err;
+}
+
+struct ar9170_rf_init {
+	u32 reg, _5ghz, _2ghz;
+};
+
+static struct ar9170_rf_init ar9170_rf_init[] = {
+     /* bank 0 */
+     { 0x1c58b0,  0x1e5795e5,  0x1e5795e5},
+     { 0x1c58e0,  0x02008020,  0x02008020},
+     /* bank 1 */
+     { 0x1c58b0,  0x02108421,  0x02108421},
+     { 0x1c58ec,  0x00000008,  0x00000008},
+     /* bank 2 */
+     { 0x1c58b0,  0x0e73ff17,  0x0e73ff17},
+     { 0x1c58e0,  0x00000420,  0x00000420},
+     /* bank 3 */
+     { 0x1c58f0,  0x01400018,  0x01c00018},
+     /* bank 4 */
+     { 0x1c58b0,  0x000001a1,  0x000001a1},
+     { 0x1c58e8,  0x00000001,  0x00000001},
+     /* bank 5 */
+     { 0x1c58b0,  0x00000013,  0x00000013},
+     { 0x1c58e4,  0x00000002,  0x00000002},
+     /* bank 6 */
+     { 0x1c58b0,  0x00000000,  0x00000000},
+     { 0x1c58b0,  0x00000000,  0x00000000},
+     { 0x1c58b0,  0x00000000,  0x00000000},
+     { 0x1c58b0,  0x00000000,  0x00000000},
+     { 0x1c58b0,  0x00000000,  0x00000000},
+     { 0x1c58b0,  0x00004000,  0x00004000},
+     { 0x1c58b0,  0x00006c00,  0x00006c00},
+     { 0x1c58b0,  0x00002c00,  0x00002c00},
+     { 0x1c58b0,  0x00004800,  0x00004800},
+     { 0x1c58b0,  0x00004000,  0x00004000},
+     { 0x1c58b0,  0x00006000,  0x00006000},
+     { 0x1c58b0,  0x00001000,  0x00001000},
+     { 0x1c58b0,  0x00004000,  0x00004000},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00087c00,  0x00087c00},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00005400,  0x00005400},
+     { 0x1c58b0,  0x00000c00,  0x00000c00},
+     { 0x1c58b0,  0x00001800,  0x00001800},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00006c00,  0x00006c00},
+     { 0x1c58b0,  0x00006c00,  0x00006c00},
+     { 0x1c58b0,  0x00007c00,  0x00007c00},
+     { 0x1c58b0,  0x00002c00,  0x00002c00},
+     { 0x1c58b0,  0x00003c00,  0x00003c00},
+     { 0x1c58b0,  0x00003800,  0x00003800},
+     { 0x1c58b0,  0x00001c00,  0x00001c00},
+     { 0x1c58b0,  0x00000800,  0x00000800},
+     { 0x1c58b0,  0x00000408,  0x00000408},
+     { 0x1c58b0,  0x00004c15,  0x00004c15},
+     { 0x1c58b0,  0x00004188,  0x00004188},
+     { 0x1c58b0,  0x0000201e,  0x0000201e},
+     { 0x1c58b0,  0x00010408,  0x00010408},
+     { 0x1c58b0,  0x00000801,  0x00000801},
+     { 0x1c58b0,  0x00000c08,  0x00000c08},
+     { 0x1c58b0,  0x0000181e,  0x0000181e},
+     { 0x1c58b0,  0x00001016,  0x00001016},
+     { 0x1c58b0,  0x00002800,  0x00002800},
+     { 0x1c58b0,  0x00004010,  0x00004010},
+     { 0x1c58b0,  0x0000081c,  0x0000081c},
+     { 0x1c58b0,  0x00000115,  0x00000115},
+     { 0x1c58b0,  0x00000015,  0x00000015},
+     { 0x1c58b0,  0x00000066,  0x00000066},
+     { 0x1c58b0,  0x0000001c,  0x0000001c},
+     { 0x1c58b0,  0x00000000,  0x00000000},
+     { 0x1c58b0,  0x00000004,  0x00000004},
+     { 0x1c58b0,  0x00000015,  0x00000015},
+     { 0x1c58b0,  0x0000001f,  0x0000001f},
+     { 0x1c58e0,  0x00000000,  0x00000400},
+     /* bank 7 */
+     { 0x1c58b0,  0x000000a0,  0x000000a0},
+     { 0x1c58b0,  0x00000000,  0x00000000},
+     { 0x1c58b0,  0x00000040,  0x00000040},
+     { 0x1c58f0,  0x0000001c,  0x0000001c},
+};
+
+static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz)
+{
+	int err, i;
+
+	ar9170_regwrite_begin(ar);
+
+	for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++)
+		ar9170_regwrite(ar9170_rf_init[i].reg,
+				band5ghz ? ar9170_rf_init[i]._5ghz
+					 : ar9170_rf_init[i]._2ghz);
+
+	ar9170_regwrite_finish();
+	err = ar9170_regwrite_result();
+	if (err)
+		printk(KERN_ERR "%s: rf init failed\n",
+		       wiphy_name(ar->hw->wiphy));
+	return err;
+}
+
+static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz,
+				    u32 freq, enum ar9170_bw bw)
+{
+	int err;
+	u32 d0, d1, td0, td1, fd0, fd1;
+	u8 chansel;
+	u8 refsel0 = 1, refsel1 = 0;
+	u8 lf_synth = 0;
+
+	switch (bw) {
+	case AR9170_BW_40_ABOVE:
+		freq += 10;
+		break;
+	case AR9170_BW_40_BELOW:
+		freq -= 10;
+		break;
+	case AR9170_BW_20:
+		break;
+	case __AR9170_NUM_BW:
+		BUG();
+	}
+
+	if (band5ghz) {
+		if (freq % 10) {
+			chansel = (freq - 4800) / 5;
+		} else {
+			chansel = ((freq - 4800) / 10) * 2;
+			refsel0 = 0;
+			refsel1 = 1;
+		}
+		chansel = byte_rev_table[chansel];
+	} else {
+		if (freq == 2484) {
+			chansel = 10 + (freq - 2274) / 5;
+			lf_synth = 1;
+		} else
+			chansel = 16 + (freq - 2272) / 5;
+		chansel *= 4;
+		chansel = byte_rev_table[chansel];
+	}
+
+	d1 =	chansel;
+	d0 =	0x21 |
+		refsel0 << 3 |
+		refsel1 << 2 |
+		lf_synth << 1;
+	td0 =	d0 & 0x1f;
+	td1 =	d1 & 0x1f;
+	fd0 =	td1 << 5 | td0;
+
+	td0 =	(d0 >> 5) & 0x7;
+	td1 =	(d1 >> 5) & 0x7;
+	fd1 =	td1 << 5 | td0;
+
+	ar9170_regwrite_begin(ar);
+
+	ar9170_regwrite(0x1c58b0, fd0);
+	ar9170_regwrite(0x1c58e8, fd1);
+
+	ar9170_regwrite_finish();
+	err = ar9170_regwrite_result();
+	if (err)
+		return err;
+
+	msleep(10);
+
+	return 0;
+}
+
+struct ar9170_phy_freq_params {
+	u8 coeff_exp;
+	u16 coeff_man;
+	u8 coeff_exp_shgi;
+	u16 coeff_man_shgi;
+};
+
+struct ar9170_phy_freq_entry {
+	u16 freq;
+	struct ar9170_phy_freq_params params[__AR9170_NUM_BW];
+};
+
+/* NB: must be in sync with channel tables in main! */
+static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = {
+/*
+ *	freq,
+ *		20MHz,
+ *		40MHz (below),
+ *		40Mhz (above),
+ */
+	{ 2412, {
+		{ 3, 21737, 3, 19563, },
+		{ 3, 21827, 3, 19644, },
+		{ 3, 21647, 3, 19482, },
+	} },
+	{ 2417, {
+		{ 3, 21692, 3, 19523, },
+		{ 3, 21782, 3, 19604, },
+		{ 3, 21602, 3, 19442, },
+	} },
+	{ 2422, {
+		{ 3, 21647, 3, 19482, },
+		{ 3, 21737, 3, 19563, },
+		{ 3, 21558, 3, 19402, },
+	} },
+	{ 2427, {
+		{ 3, 21602, 3, 19442, },
+		{ 3, 21692, 3, 19523, },
+		{ 3, 21514, 3, 19362, },
+	} },
+	{ 2432, {
+		{ 3, 21558, 3, 19402, },
+		{ 3, 21647, 3, 19482, },
+		{ 3, 21470, 3, 19323, },
+	} },
+	{ 2437, {
+		{ 3, 21514, 3, 19362, },
+		{ 3, 21602, 3, 19442, },
+		{ 3, 21426, 3, 19283, },
+	} },
+	{ 2442, {
+		{ 3, 21470, 3, 19323, },
+		{ 3, 21558, 3, 19402, },
+		{ 3, 21382, 3, 19244, },
+	} },
+	{ 2447, {
+		{ 3, 21426, 3, 19283, },
+		{ 3, 21514, 3, 19362, },
+		{ 3, 21339, 3, 19205, },
+	} },
+	{ 2452, {
+		{ 3, 21382, 3, 19244, },
+		{ 3, 21470, 3, 19323, },
+		{ 3, 21295, 3, 19166, },
+	} },
+	{ 2457, {
+		{ 3, 21339, 3, 19205, },
+		{ 3, 21426, 3, 19283, },
+		{ 3, 21252, 3, 19127, },
+	} },
+	{ 2462, {
+		{ 3, 21295, 3, 19166, },
+		{ 3, 21382, 3, 19244, },
+		{ 3, 21209, 3, 19088, },
+	} },
+	{ 2467, {
+		{ 3, 21252, 3, 19127, },
+		{ 3, 21339, 3, 19205, },
+		{ 3, 21166, 3, 19050, },
+	} },
+	{ 2472, {
+		{ 3, 21209, 3, 19088, },
+		{ 3, 21295, 3, 19166, },
+		{ 3, 21124, 3, 19011, },
+	} },
+	{ 2484, {
+		{ 3, 21107, 3, 18996, },
+		{ 3, 21192, 3, 19073, },
+		{ 3, 21022, 3, 18920, },
+	} },
+	{ 4920, {
+		{ 4, 21313, 4, 19181, },
+		{ 4, 21356, 4, 19220, },
+		{ 4, 21269, 4, 19142, },
+	} },
+	{ 4940, {
+		{ 4, 21226, 4, 19104, },
+		{ 4, 21269, 4, 19142, },
+		{ 4, 21183, 4, 19065, },
+	} },
+	{ 4960, {
+		{ 4, 21141, 4, 19027, },
+		{ 4, 21183, 4, 19065, },
+		{ 4, 21098, 4, 18988, },
+	} },
+	{ 4980, {
+		{ 4, 21056, 4, 18950, },
+		{ 4, 21098, 4, 18988, },
+		{ 4, 21014, 4, 18912, },
+	} },
+	{ 5040, {
+		{ 4, 20805, 4, 18725, },
+		{ 4, 20846, 4, 18762, },
+		{ 4, 20764, 4, 18687, },
+	} },
+	{ 5060, {
+		{ 4, 20723, 4, 18651, },
+		{ 4, 20764, 4, 18687, },
+		{ 4, 20682, 4, 18614, },
+	} },
+	{ 5080, {
+		{ 4, 20641, 4, 18577, },
+		{ 4, 20682, 4, 18614, },
+		{ 4, 20601, 4, 18541, },
+	} },
+	{ 5180, {
+		{ 4, 20243, 4, 18219, },
+		{ 4, 20282, 4, 18254, },
+		{ 4, 20204, 4, 18183, },
+	} },
+	{ 5200, {
+		{ 4, 20165, 4, 18148, },
+		{ 4, 20204, 4, 18183, },
+		{ 4, 20126, 4, 18114, },
+	} },
+	{ 5220, {
+		{ 4, 20088, 4, 18079, },
+		{ 4, 20126, 4, 18114, },
+		{ 4, 20049, 4, 18044, },
+	} },
+	{ 5240, {
+		{ 4, 20011, 4, 18010, },
+		{ 4, 20049, 4, 18044, },
+		{ 4, 19973, 4, 17976, },
+	} },
+	{ 5260, {
+		{ 4, 19935, 4, 17941, },
+		{ 4, 19973, 4, 17976, },
+		{ 4, 19897, 4, 17907, },
+	} },
+	{ 5280, {
+		{ 4, 19859, 4, 17873, },
+		{ 4, 19897, 4, 17907, },
+		{ 4, 19822, 4, 17840, },
+	} },
+	{ 5300, {
+		{ 4, 19784, 4, 17806, },
+		{ 4, 19822, 4, 17840, },
+		{ 4, 19747, 4, 17772, },
+	} },
+	{ 5320, {
+		{ 4, 19710, 4, 17739, },
+		{ 4, 19747, 4, 17772, },
+		{ 4, 19673, 4, 17706, },
+	} },
+	{ 5500, {
+		{ 4, 19065, 4, 17159, },
+		{ 4, 19100, 4, 17190, },
+		{ 4, 19030, 4, 17127, },
+	} },
+	{ 5520, {
+		{ 4, 18996, 4, 17096, },
+		{ 4, 19030, 4, 17127, },
+		{ 4, 18962, 4, 17065, },
+	} },
+	{ 5540, {
+		{ 4, 18927, 4, 17035, },
+		{ 4, 18962, 4, 17065, },
+		{ 4, 18893, 4, 17004, },
+	} },
+	{ 5560, {
+		{ 4, 18859, 4, 16973, },
+		{ 4, 18893, 4, 17004, },
+		{ 4, 18825, 4, 16943, },
+	} },
+	{ 5580, {
+		{ 4, 18792, 4, 16913, },
+		{ 4, 18825, 4, 16943, },
+		{ 4, 18758, 4, 16882, },
+	} },
+	{ 5600, {
+		{ 4, 18725, 4, 16852, },
+		{ 4, 18758, 4, 16882, },
+		{ 4, 18691, 4, 16822, },
+	} },
+	{ 5620, {
+		{ 4, 18658, 4, 16792, },
+		{ 4, 18691, 4, 16822, },
+		{ 4, 18625, 4, 16762, },
+	} },
+	{ 5640, {
+		{ 4, 18592, 4, 16733, },
+		{ 4, 18625, 4, 16762, },
+		{ 4, 18559, 4, 16703, },
+	} },
+	{ 5660, {
+		{ 4, 18526, 4, 16673, },
+		{ 4, 18559, 4, 16703, },
+		{ 4, 18493, 4, 16644, },
+	} },
+	{ 5680, {
+		{ 4, 18461, 4, 16615, },
+		{ 4, 18493, 4, 16644, },
+		{ 4, 18428, 4, 16586, },
+	} },
+	{ 5700, {
+		{ 4, 18396, 4, 16556, },
+		{ 4, 18428, 4, 16586, },
+		{ 4, 18364, 4, 16527, },
+	} },
+	{ 5745, {
+		{ 4, 18252, 4, 16427, },
+		{ 4, 18284, 4, 16455, },
+		{ 4, 18220, 4, 16398, },
+	} },
+	{ 5765, {
+		{ 4, 18189, 5, 32740, },
+		{ 4, 18220, 4, 16398, },
+		{ 4, 18157, 5, 32683, },
+	} },
+	{ 5785, {
+		{ 4, 18126, 5, 32626, },
+		{ 4, 18157, 5, 32683, },
+		{ 4, 18094, 5, 32570, },
+	} },
+	{ 5805, {
+		{ 4, 18063, 5, 32514, },
+		{ 4, 18094, 5, 32570, },
+		{ 4, 18032, 5, 32458, },
+	} },
+	{ 5825, {
+		{ 4, 18001, 5, 32402, },
+		{ 4, 18032, 5, 32458, },
+		{ 4, 17970, 5, 32347, },
+	} },
+	{ 5170, {
+		{ 4, 20282, 4, 18254, },
+		{ 4, 20321, 4, 18289, },
+		{ 4, 20243, 4, 18219, },
+	} },
+	{ 5190, {
+		{ 4, 20204, 4, 18183, },
+		{ 4, 20243, 4, 18219, },
+		{ 4, 20165, 4, 18148, },
+	} },
+	{ 5210, {
+		{ 4, 20126, 4, 18114, },
+		{ 4, 20165, 4, 18148, },
+		{ 4, 20088, 4, 18079, },
+	} },
+	{ 5230, {
+		{ 4, 20049, 4, 18044, },
+		{ 4, 20088, 4, 18079, },
+		{ 4, 20011, 4, 18010, },
+	} },
+};
+
+static const struct ar9170_phy_freq_params *
+ar9170_get_hw_dyn_params(struct ieee80211_channel *channel,
+			 enum ar9170_bw bw)
+{
+	unsigned int chanidx = 0;
+	u16 freq = 2412;
+
+	if (channel) {
+		chanidx = channel->hw_value;
+		freq = channel->center_freq;
+	}
+
+	BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params));
+
+	BUILD_BUG_ON(__AR9170_NUM_BW != 3);
+
+	WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq);
+
+	return &ar9170_phy_freq_params[chanidx].params[bw];
+}
+
+
+int ar9170_init_rf(struct ar9170 *ar)
+{
+	const struct ar9170_phy_freq_params *freqpar;
+	__le32 cmd[7];
+	int err;
+
+	err = ar9170_init_rf_banks_0_7(ar, false);
+	if (err)
+		return err;
+
+	err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20);
+	if (err)
+		return err;
+
+	freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20);
+
+	cmd[0] = cpu_to_le32(2412 * 1000);
+	cmd[1] = cpu_to_le32(0);
+	cmd[2] = cpu_to_le32(1);
+	cmd[3] = cpu_to_le32(freqpar->coeff_exp);
+	cmd[4] = cpu_to_le32(freqpar->coeff_man);
+	cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi);
+	cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi);
+
+	/* RF_INIT echoes the command back to us */
+	err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT,
+			   sizeof(cmd), (u8 *)cmd,
+			   sizeof(cmd), (u8 *)cmd);
+	if (err)
+		return err;
+
+	msleep(1000);
+
+	return ar9170_echo_test(ar, 0xaabbccdd);
+}
+
+static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f)
+{
+	int idx = nfreqs - 2;
+
+	while (idx >= 0) {
+		if (f >= freqs[idx])
+			return idx;
+		idx--;
+	}
+
+	return 0;
+}
+
+static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+{
+	/* nothing to interpolate, it's horizontal */
+	if (y2 == y1)
+		return y1;
+
+	/* check if we hit one of the edges */
+	if (x == x1)
+		return y1;
+	if (x == x2)
+		return y2;
+
+	/* x1 == x2 is bad, hopefully == x */
+	if (x2 == x1)
+		return y1;
+
+	return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1));
+}
+
+static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
+{
+#define SHIFT		8
+	s32 y;
+
+	y = ar9170_interpolate_s32(x << SHIFT,
+				   x1 << SHIFT, y1 << SHIFT,
+				   x2 << SHIFT, y2 << SHIFT);
+
+	/*
+	 * XXX: unwrap this expression
+	 *	Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
+	 *	Can we rely on the compiler to optimise away the div?
+	 */
+	return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
+#undef SHIFT
+}
+
+static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
+{
+	struct ar9170_calibration_target_power_legacy *ctpl;
+	struct ar9170_calibration_target_power_ht *ctph;
+	u8 *ctpres;
+	int ntargets;
+	int idx, i, n;
+	u8 ackpower, ackchains, f;
+	u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS];
+
+	if (freq < 3000)
+		f = freq - 2300;
+	else
+		f = (freq - 4800)/5;
+
+	/*
+	 * cycle through the various modes
+	 *
+	 * legacy modes first: 5G, 2G CCK, 2G OFDM
+	 */
+	for (i = 0; i < 3; i++) {
+		switch (i) {
+		case 0: /* 5 GHz legacy */
+			ctpl = &ar->eeprom.cal_tgt_pwr_5G[0];
+			ntargets = AR5416_NUM_5G_TARGET_PWRS;
+			ctpres = ar->power_5G_leg;
+			break;
+		case 1: /* 2.4 GHz CCK */
+			ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0];
+			ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS;
+			ctpres = ar->power_2G_cck;
+			break;
+		case 2: /* 2.4 GHz OFDM */
+			ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0];
+			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+			ctpres = ar->power_2G_ofdm;
+			break;
+		default:
+			BUG();
+		}
+
+		for (n = 0; n < ntargets; n++) {
+			if (ctpl[n].freq == 0xff)
+				break;
+			pwr_freqs[n] = ctpl[n].freq;
+		}
+		ntargets = n;
+		idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f);
+		for (n = 0; n < 4; n++)
+			ctpres[n] = ar9170_interpolate_u8(
+					f,
+					ctpl[idx + 0].freq,
+					ctpl[idx + 0].power[n],
+					ctpl[idx + 1].freq,
+					ctpl[idx + 1].power[n]);
+	}
+
+	/*
+	 * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40
+	 */
+	for (i = 0; i < 4; i++) {
+		switch (i) {
+		case 0: /* 5 GHz HT 20 */
+			ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0];
+			ntargets = AR5416_NUM_5G_TARGET_PWRS;
+			ctpres = ar->power_5G_ht20;
+			break;
+		case 1: /* 5 GHz HT 40 */
+			ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0];
+			ntargets = AR5416_NUM_5G_TARGET_PWRS;
+			ctpres = ar->power_5G_ht40;
+			break;
+		case 2: /* 2.4 GHz HT 20 */
+			ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0];
+			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+			ctpres = ar->power_2G_ht20;
+			break;
+		case 3: /* 2.4 GHz HT 40 */
+			ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0];
+			ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+			ctpres = ar->power_2G_ht40;
+			break;
+		default:
+			BUG();
+		}
+
+		for (n = 0; n < ntargets; n++) {
+			if (ctph[n].freq == 0xff)
+				break;
+			pwr_freqs[n] = ctph[n].freq;
+		}
+		ntargets = n;
+		idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f);
+		for (n = 0; n < 8; n++)
+			ctpres[n] = ar9170_interpolate_u8(
+					f,
+					ctph[idx + 0].freq,
+					ctph[idx + 0].power[n],
+					ctph[idx + 1].freq,
+					ctph[idx + 1].power[n]);
+	}
+
+	/* set ACK/CTS TX power */
+	ar9170_regwrite_begin(ar);
+
+	if (ar->eeprom.tx_mask != 1)
+		ackchains = AR9170_TX_PHY_TXCHAIN_2;
+	else
+		ackchains = AR9170_TX_PHY_TXCHAIN_1;
+
+	if (freq < 3000)
+		ackpower = ar->power_2G_ofdm[0] & 0x3f;
+	else
+		ackpower = ar->power_5G_leg[0] & 0x3f;
+
+	ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26);
+	ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 |
+				  ackpower << 21 | ackchains << 27);
+
+	ar9170_regwrite_finish();
+	return ar9170_regwrite_result();
+}
+
+static int ar9170_calc_noise_dbm(u32 raw_noise)
+{
+	if (raw_noise & 0x100)
+		return ~((raw_noise & 0x0ff) >> 1);
+	else
+		return (raw_noise & 0xff) >> 1;
+}
+
+int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
+		       enum ar9170_rf_init_mode rfi, enum ar9170_bw bw)
+{
+	const struct ar9170_phy_freq_params *freqpar;
+	u32 cmd, tmp, offs;
+	__le32 vals[8];
+	int i, err;
+	bool bandswitch;
+
+	/* clear BB heavy clip enable */
+	err = ar9170_write_reg(ar, 0x1c59e0, 0x200);
+	if (err)
+		return err;
+
+	/* may be NULL at first setup */
+	if (ar->channel)
+		bandswitch = ar->channel->band != channel->band;
+	else
+		bandswitch = true;
+
+	/* HW workaround */
+	if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
+	    channel->center_freq <= 2417)
+		bandswitch = true;
+
+	err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL);
+	if (err)
+		return err;
+
+	if (rfi != AR9170_RFI_NONE || bandswitch) {
+		u32 val = 0x400;
+
+		if (rfi == AR9170_RFI_COLD)
+			val = 0x800;
+
+		/* warm/cold reset BB/ADDA */
+		err = ar9170_write_reg(ar, 0x1d4004, val);
+		if (err)
+			return err;
+
+		err = ar9170_write_reg(ar, 0x1d4004, 0x0);
+		if (err)
+			return err;
+
+		err = ar9170_init_phy(ar, channel->band);
+		if (err)
+			return err;
+
+		err = ar9170_init_rf_banks_0_7(ar,
+			channel->band == IEEE80211_BAND_5GHZ);
+		if (err)
+			return err;
+
+		cmd = AR9170_CMD_RF_INIT;
+	} else {
+		cmd = AR9170_CMD_FREQUENCY;
+	}
+
+	err = ar9170_init_rf_bank4_pwr(ar,
+		channel->band == IEEE80211_BAND_5GHZ,
+		channel->center_freq, bw);
+	if (err)
+		return err;
+
+	switch (bw) {
+	case AR9170_BW_20:
+		tmp = 0x240;
+		offs = 0;
+		break;
+	case AR9170_BW_40_BELOW:
+		tmp = 0x2c4;
+		offs = 3;
+		break;
+	case AR9170_BW_40_ABOVE:
+		tmp = 0x2d4;
+		offs = 1;
+		break;
+	default:
+		BUG();
+		return -ENOSYS;
+	}
+
+	if (ar->eeprom.tx_mask != 1)
+		tmp |= 0x100;
+
+	err = ar9170_write_reg(ar, 0x1c5804, tmp);
+	if (err)
+		return err;
+
+	err = ar9170_set_power_cal(ar, channel->center_freq, bw);
+	if (err)
+		return err;
+
+	freqpar = ar9170_get_hw_dyn_params(channel, bw);
+
+	vals[0] = cpu_to_le32(channel->center_freq * 1000);
+	vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf));
+	vals[2] = cpu_to_le32(offs << 2 | 1);
+	vals[3] = cpu_to_le32(freqpar->coeff_exp);
+	vals[4] = cpu_to_le32(freqpar->coeff_man);
+	vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi);
+	vals[6] = cpu_to_le32(freqpar->coeff_man_shgi);
+	vals[7] = cpu_to_le32(1000);
+
+	err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals,
+			   sizeof(vals), (u8 *)vals);
+	if (err)
+		return err;
+
+	for (i = 0; i < 2; i++) {
+		ar->noise[i] = ar9170_calc_noise_dbm(
+				(le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff);
+
+		ar->noise[i + 2] = ar9170_calc_noise_dbm(
+				    (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff);
+	}
+
+	ar->channel = channel;
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/usb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/usb.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,933 @@
+/*
+ * Atheros AR9170 driver
+ *
+ * USB - frontend
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, Christian Lamparter <chunkeey@web.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.
+ *
+ * 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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+#include "ar9170.h"
+#include "cmd.h"
+#include "hw.h"
+#include "usb.h"
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
+MODULE_FIRMWARE("ar9170.fw");
+MODULE_FIRMWARE("ar9170-1.fw");
+MODULE_FIRMWARE("ar9170-2.fw");
+
+enum ar9170_requirements {
+	AR9170_REQ_FW1_ONLY = 1,
+};
+
+static struct usb_device_id ar9170_usb_ids[] = {
+	/* Atheros 9170 */
+	{ USB_DEVICE(0x0cf3, 0x9170) },
+	/* Atheros TG121N */
+	{ USB_DEVICE(0x0cf3, 0x1001) },
+	/* Cace Airpcap NX */
+	{ USB_DEVICE(0xcace, 0x0300) },
+	/* D-Link DWA 160A */
+	{ USB_DEVICE(0x07d1, 0x3c10) },
+	/* Netgear WNDA3100 */
+	{ USB_DEVICE(0x0846, 0x9010) },
+	/* Netgear WN111 v2 */
+	{ USB_DEVICE(0x0846, 0x9001) },
+	/* Zydas ZD1221 */
+	{ USB_DEVICE(0x0ace, 0x1221) },
+	/* ZyXEL NWD271N */
+	{ USB_DEVICE(0x0586, 0x3417) },
+	/* Z-Com UB81 BG */
+	{ USB_DEVICE(0x0cde, 0x0023) },
+	/* Z-Com UB82 ABG */
+	{ USB_DEVICE(0x0cde, 0x0026) },
+	/* Arcadyan WN7512 */
+	{ USB_DEVICE(0x083a, 0xf522) },
+	/* Planex GWUS300 */
+	{ USB_DEVICE(0x2019, 0x5304) },
+	/* IO-Data WNGDNUS2 */
+	{ USB_DEVICE(0x04bb, 0x093f) },
+	/* AVM FRITZ!WLAN USB Stick N */
+	{ USB_DEVICE(0x057C, 0x8401) },
+	/* AVM FRITZ!WLAN USB Stick N 2.4 */
+	{ USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY },
+
+	/* terminate */
+	{}
+};
+MODULE_DEVICE_TABLE(usb, ar9170_usb_ids);
+
+static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
+{
+	struct urb *urb;
+	unsigned long flags;
+	int err;
+
+	if (unlikely(!IS_STARTED(&aru->common)))
+		return ;
+
+	spin_lock_irqsave(&aru->tx_urb_lock, flags);
+	if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) {
+		spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
+		return ;
+	}
+	aru->tx_submitted_urbs++;
+
+	urb = usb_get_from_anchor(&aru->tx_pending);
+	if (!urb) {
+		aru->tx_submitted_urbs--;
+		spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
+
+		return ;
+	}
+	spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
+
+	aru->tx_pending_urbs--;
+	usb_anchor_urb(urb, &aru->tx_submitted);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		if (ar9170_nag_limiter(&aru->common))
+			dev_err(&aru->udev->dev, "submit_urb failed (%d).\n",
+				err);
+
+		usb_unanchor_urb(urb);
+		aru->tx_submitted_urbs--;
+		ar9170_tx_callback(&aru->common, urb->context);
+	}
+
+	usb_free_urb(urb);
+}
+
+static void ar9170_usb_tx_urb_complete_frame(struct urb *urb)
+{
+	struct sk_buff *skb = urb->context;
+	struct ar9170_usb *aru = (struct ar9170_usb *)
+	      usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+
+	if (unlikely(!aru)) {
+		dev_kfree_skb_irq(skb);
+		return ;
+	}
+
+	aru->tx_submitted_urbs--;
+
+	ar9170_tx_callback(&aru->common, skb);
+
+	ar9170_usb_submit_urb(aru);
+}
+
+static void ar9170_usb_tx_urb_complete(struct urb *urb)
+{
+}
+
+static void ar9170_usb_irq_completed(struct urb *urb)
+{
+	struct ar9170_usb *aru = urb->context;
+
+	switch (urb->status) {
+	/* everything is fine */
+	case 0:
+		break;
+
+	/* disconnect */
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		goto free;
+
+	default:
+		goto resubmit;
+	}
+
+	ar9170_handle_command_response(&aru->common, urb->transfer_buffer,
+				       urb->actual_length);
+
+resubmit:
+	usb_anchor_urb(urb, &aru->rx_submitted);
+	if (usb_submit_urb(urb, GFP_ATOMIC)) {
+		usb_unanchor_urb(urb);
+		goto free;
+	}
+
+	return;
+
+free:
+	usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma);
+}
+
+static void ar9170_usb_rx_completed(struct urb *urb)
+{
+	struct sk_buff *skb = urb->context;
+	struct ar9170_usb *aru = (struct ar9170_usb *)
+		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+	int err;
+
+	if (!aru)
+		goto free;
+
+	switch (urb->status) {
+	/* everything is fine */
+	case 0:
+		break;
+
+	/* disconnect */
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		goto free;
+
+	default:
+		goto resubmit;
+	}
+
+	skb_put(skb, urb->actual_length);
+	ar9170_rx(&aru->common, skb);
+
+resubmit:
+	skb_reset_tail_pointer(skb);
+	skb_trim(skb, 0);
+
+	usb_anchor_urb(urb, &aru->rx_submitted);
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		usb_unanchor_urb(urb);
+		goto free;
+	}
+
+	return ;
+
+free:
+	dev_kfree_skb_irq(skb);
+}
+
+static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru,
+				  struct urb *urb, gfp_t gfp)
+{
+	struct sk_buff *skb;
+
+	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp);
+	if (!skb)
+		return -ENOMEM;
+
+	/* reserve some space for mac80211's radiotap */
+	skb_reserve(skb, 32);
+
+	usb_fill_bulk_urb(urb, aru->udev,
+			  usb_rcvbulkpipe(aru->udev, AR9170_EP_RX),
+			  skb->data, min(skb_tailroom(skb),
+			  AR9170_MAX_RX_BUFFER_SIZE),
+			  ar9170_usb_rx_completed, skb);
+
+	return 0;
+}
+
+static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru)
+{
+	struct urb *urb = NULL;
+	void *ibuf;
+	int err = -ENOMEM;
+
+	/* initialize interrupt endpoint */
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		goto out;
+
+	ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma);
+	if (!ibuf)
+		goto out;
+
+	usb_fill_int_urb(urb, aru->udev,
+			 usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf,
+			 64, ar9170_usb_irq_completed, aru, 1);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	usb_anchor_urb(urb, &aru->rx_submitted);
+	err = usb_submit_urb(urb, GFP_KERNEL);
+	if (err) {
+		usb_unanchor_urb(urb);
+		usb_buffer_free(aru->udev, 64, urb->transfer_buffer,
+				urb->transfer_dma);
+	}
+
+out:
+	usb_free_urb(urb);
+	return err;
+}
+
+static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru)
+{
+	struct urb *urb;
+	int i;
+	int err = -EINVAL;
+
+	for (i = 0; i < AR9170_NUM_RX_URBS; i++) {
+		err = -ENOMEM;
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb)
+			goto err_out;
+
+		err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL);
+		if (err) {
+			usb_free_urb(urb);
+			goto err_out;
+		}
+
+		usb_anchor_urb(urb, &aru->rx_submitted);
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err) {
+			usb_unanchor_urb(urb);
+			dev_kfree_skb_any((void *) urb->transfer_buffer);
+			usb_free_urb(urb);
+			goto err_out;
+		}
+		usb_free_urb(urb);
+	}
+
+	/* the device now waiting for a firmware. */
+	aru->common.state = AR9170_IDLE;
+	return 0;
+
+err_out:
+
+	usb_kill_anchored_urbs(&aru->rx_submitted);
+	return err;
+}
+
+static int ar9170_usb_flush(struct ar9170 *ar)
+{
+	struct ar9170_usb *aru = (void *) ar;
+	struct urb *urb;
+	int ret, err = 0;
+
+	if (IS_STARTED(ar))
+		aru->common.state = AR9170_IDLE;
+
+	usb_wait_anchor_empty_timeout(&aru->tx_pending,
+					    msecs_to_jiffies(800));
+	while ((urb = usb_get_from_anchor(&aru->tx_pending))) {
+		ar9170_tx_callback(&aru->common, (void *) urb->context);
+		usb_free_urb(urb);
+	}
+
+	/* lets wait a while until the tx - queues are dried out */
+	ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted,
+					    msecs_to_jiffies(100));
+	if (ret == 0)
+		err = -ETIMEDOUT;
+
+	usb_kill_anchored_urbs(&aru->tx_submitted);
+
+	if (IS_ACCEPTING_CMD(ar))
+		aru->common.state = AR9170_STARTED;
+
+	return err;
+}
+
+static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru)
+{
+	int err;
+
+	aru->common.state = AR9170_UNKNOWN_STATE;
+
+	err = ar9170_usb_flush(&aru->common);
+	if (err)
+		dev_err(&aru->udev->dev, "stuck tx urbs!\n");
+
+	usb_poison_anchored_urbs(&aru->tx_submitted);
+	usb_poison_anchored_urbs(&aru->rx_submitted);
+}
+
+static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd,
+			       unsigned int plen, void *payload,
+			       unsigned int outlen, void *out)
+{
+	struct ar9170_usb *aru = (void *) ar;
+	struct urb *urb = NULL;
+	unsigned long flags;
+	int err = -ENOMEM;
+
+	if (unlikely(!IS_ACCEPTING_CMD(ar)))
+		return -EPERM;
+
+	if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4))
+		return -EINVAL;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (unlikely(!urb))
+		goto err_free;
+
+	ar->cmdbuf[0] = cpu_to_le32(plen);
+	ar->cmdbuf[0] |= cpu_to_le32(cmd << 8);
+	/* writing multiple regs fills this buffer already */
+	if (plen && payload != (u8 *)(&ar->cmdbuf[1]))
+		memcpy(&ar->cmdbuf[1], payload, plen);
+
+	spin_lock_irqsave(&aru->common.cmdlock, flags);
+	aru->readbuf = (u8 *)out;
+	aru->readlen = outlen;
+	spin_unlock_irqrestore(&aru->common.cmdlock, flags);
+
+	usb_fill_int_urb(urb, aru->udev,
+			 usb_sndbulkpipe(aru->udev, AR9170_EP_CMD),
+			 aru->common.cmdbuf, plen + 4,
+			 ar9170_usb_tx_urb_complete, NULL, 1);
+
+	usb_anchor_urb(urb, &aru->tx_submitted);
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		usb_unanchor_urb(urb);
+		usb_free_urb(urb);
+		goto err_unbuf;
+	}
+	usb_free_urb(urb);
+
+	err = wait_for_completion_timeout(&aru->cmd_wait, HZ);
+	if (err == 0) {
+		err = -ETIMEDOUT;
+		goto err_unbuf;
+	}
+
+	if (aru->readlen != outlen) {
+		err = -EMSGSIZE;
+		goto err_unbuf;
+	}
+
+	return 0;
+
+err_unbuf:
+	/* Maybe the device was removed in the second we were waiting? */
+	if (IS_STARTED(ar)) {
+		dev_err(&aru->udev->dev, "no command feedback "
+					 "received (%d).\n", err);
+
+		/* provide some maybe useful debug information */
+		print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE,
+				     aru->common.cmdbuf, plen + 4);
+		dump_stack();
+	}
+
+	/* invalidate to avoid completing the next prematurely */
+	spin_lock_irqsave(&aru->common.cmdlock, flags);
+	aru->readbuf = NULL;
+	aru->readlen = 0;
+	spin_unlock_irqrestore(&aru->common.cmdlock, flags);
+
+err_free:
+
+	return err;
+}
+
+static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb)
+{
+	struct ar9170_usb *aru = (struct ar9170_usb *) ar;
+	struct urb *urb;
+
+	if (unlikely(!IS_STARTED(ar))) {
+		/* Seriously, what were you drink... err... thinking!? */
+		return -EPERM;
+	}
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (unlikely(!urb))
+		return -ENOMEM;
+
+	usb_fill_bulk_urb(urb, aru->udev,
+			  usb_sndbulkpipe(aru->udev, AR9170_EP_TX),
+			  skb->data, skb->len,
+			  ar9170_usb_tx_urb_complete_frame, skb);
+	urb->transfer_flags |= URB_ZERO_PACKET;
+
+	usb_anchor_urb(urb, &aru->tx_pending);
+	aru->tx_pending_urbs++;
+
+	usb_free_urb(urb);
+
+	ar9170_usb_submit_urb(aru);
+	return 0;
+}
+
+static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer)
+{
+	struct ar9170_usb *aru = (void *) ar;
+	unsigned long flags;
+	u32 in, out;
+
+	if (unlikely(!buffer))
+		return ;
+
+	in = le32_to_cpup((__le32 *)buffer);
+	out = le32_to_cpu(ar->cmdbuf[0]);
+
+	/* mask off length byte */
+	out &= ~0xFF;
+
+	if (aru->readlen >= 0) {
+		/* add expected length */
+		out |= aru->readlen;
+	} else {
+		/* add obtained length */
+		out |= in & 0xFF;
+	}
+
+	/*
+	 * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response
+	 * length and we cannot predict the correct length in advance.
+	 * So we only check if we provided enough space for the data.
+	 */
+	if (unlikely(out < in)) {
+		dev_warn(&aru->udev->dev, "received invalid command response "
+					  "got %d bytes, instead of %d bytes "
+					  "and the resp length is %d bytes\n",
+			 in, out, len);
+		print_hex_dump_bytes("ar9170 invalid resp: ",
+				     DUMP_PREFIX_OFFSET, buffer, len);
+		/*
+		 * Do not complete, then the command times out,
+		 * and we get a stack trace from there.
+		 */
+		return ;
+	}
+
+	spin_lock_irqsave(&aru->common.cmdlock, flags);
+	if (aru->readbuf && len > 0) {
+		memcpy(aru->readbuf, buffer + 4, len - 4);
+		aru->readbuf = NULL;
+	}
+	complete(&aru->cmd_wait);
+	spin_unlock_irqrestore(&aru->common.cmdlock, flags);
+}
+
+static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data,
+			     size_t len, u32 addr, bool complete)
+{
+	int transfer, err;
+	u8 *buf = kmalloc(4096, GFP_KERNEL);
+
+	if (!buf)
+		return -ENOMEM;
+
+	while (len) {
+		transfer = min_t(int, len, 4096);
+		memcpy(buf, data, transfer);
+
+		err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0),
+				      0x30 /* FW DL */, 0x40 | USB_DIR_OUT,
+				      addr >> 8, 0, buf, transfer, 1000);
+
+		if (err < 0) {
+			kfree(buf);
+			return err;
+		}
+
+		len -= transfer;
+		data += transfer;
+		addr += transfer;
+	}
+	kfree(buf);
+
+	if (complete) {
+		err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0),
+				      0x31 /* FW DL COMPLETE */,
+				      0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000);
+	}
+
+	return 0;
+}
+
+static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
+{
+	int err = 0;
+
+	err = request_firmware(&aru->firmware, "ar9170.fw",
+			       &aru->udev->dev);
+	if (!err) {
+		aru->init_values = NULL;
+		return 0;
+	}
+
+	if (aru->req_one_stage_fw) {
+		dev_err(&aru->udev->dev, "ar9170.fw firmware file "
+			"not found and is required for this device\n");
+		return -EINVAL;
+	}
+
+	dev_err(&aru->udev->dev, "ar9170.fw firmware file "
+		"not found, trying old firmware...\n");
+
+	err = request_firmware(&aru->init_values, "ar9170-1.fw",
+			       &aru->udev->dev);
+	if (err) {
+		dev_err(&aru->udev->dev, "file with init values not found.\n");
+		return err;
+	}
+
+	err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
+	if (err) {
+		release_firmware(aru->init_values);
+		dev_err(&aru->udev->dev, "firmware file not found.\n");
+		return err;
+	}
+
+	return err;
+}
+
+static int ar9170_usb_reset(struct ar9170_usb *aru)
+{
+	int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING);
+
+	if (lock) {
+		ret = usb_lock_device_for_reset(aru->udev, aru->intf);
+		if (ret < 0) {
+			dev_err(&aru->udev->dev, "unable to lock device "
+				"for reset (%d).\n", ret);
+			return ret;
+		}
+	}
+
+	ret = usb_reset_device(aru->udev);
+	if (lock)
+		usb_unlock_device(aru->udev);
+
+	/* let it rest - for a second - */
+	msleep(1000);
+
+	return ret;
+}
+
+static int ar9170_usb_upload_firmware(struct ar9170_usb *aru)
+{
+	int err;
+
+	if (!aru->init_values)
+		goto upload_fw_start;
+
+	/* First, upload initial values to device RAM */
+	err = ar9170_usb_upload(aru, aru->init_values->data,
+				aru->init_values->size, 0x102800, false);
+	if (err) {
+		dev_err(&aru->udev->dev, "firmware part 1 "
+			"upload failed (%d).\n", err);
+		return err;
+	}
+
+upload_fw_start:
+
+	/* Then, upload the firmware itself and start it */
+	return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size,
+				0x200000, true);
+}
+
+static int ar9170_usb_init_transport(struct ar9170_usb *aru)
+{
+	struct ar9170 *ar = (void *) &aru->common;
+	int err;
+
+	ar9170_regwrite_begin(ar);
+
+	/* Set USB Rx stream mode MAX packet number to 2 */
+	ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4);
+
+	/* Set USB Rx stream mode timeout to 10us */
+	ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80);
+
+	ar9170_regwrite_finish();
+
+	err = ar9170_regwrite_result();
+	if (err)
+		dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err);
+
+	return err;
+}
+
+static void ar9170_usb_stop(struct ar9170 *ar)
+{
+	struct ar9170_usb *aru = (void *) ar;
+	int ret;
+
+	if (IS_ACCEPTING_CMD(ar))
+		aru->common.state = AR9170_STOPPED;
+
+	ret = ar9170_usb_flush(ar);
+	if (ret)
+		dev_err(&aru->udev->dev, "kill pending tx urbs.\n");
+
+	usb_poison_anchored_urbs(&aru->tx_submitted);
+
+	/*
+	 * Note:
+	 * So far we freed all tx urbs, but we won't dare to touch any rx urbs.
+	 * Else we would end up with a unresponsive device...
+	 */
+}
+
+static int ar9170_usb_open(struct ar9170 *ar)
+{
+	struct ar9170_usb *aru = (void *) ar;
+	int err;
+
+	usb_unpoison_anchored_urbs(&aru->tx_submitted);
+	err = ar9170_usb_init_transport(aru);
+	if (err) {
+		usb_poison_anchored_urbs(&aru->tx_submitted);
+		return err;
+	}
+
+	aru->common.state = AR9170_IDLE;
+	return 0;
+}
+
+static int ar9170_usb_init_device(struct ar9170_usb *aru)
+{
+	int err;
+
+	err = ar9170_usb_alloc_rx_irq_urb(aru);
+	if (err)
+		goto err_out;
+
+	err = ar9170_usb_alloc_rx_bulk_urbs(aru);
+	if (err)
+		goto err_unrx;
+
+	err = ar9170_usb_upload_firmware(aru);
+	if (err) {
+		err = ar9170_echo_test(&aru->common, 0x60d43110);
+		if (err) {
+			/* force user invention, by disabling the device */
+			err = usb_driver_set_configuration(aru->udev, -1);
+			dev_err(&aru->udev->dev, "device is in a bad state. "
+						 "please reconnect it!\n");
+			goto err_unrx;
+		}
+	}
+
+	return 0;
+
+err_unrx:
+	ar9170_usb_cancel_urbs(aru);
+
+err_out:
+	return err;
+}
+
+static bool ar9170_requires_one_stage(const struct usb_device_id *id)
+{
+	if (!id->driver_info)
+		return false;
+	if (id->driver_info == AR9170_REQ_FW1_ONLY)
+		return true;
+	return false;
+}
+
+static int ar9170_usb_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	struct ar9170_usb *aru;
+	struct ar9170 *ar;
+	struct usb_device *udev;
+	int err;
+
+	aru = ar9170_alloc(sizeof(*aru));
+	if (IS_ERR(aru)) {
+		err = PTR_ERR(aru);
+		goto out;
+	}
+
+	udev = interface_to_usbdev(intf);
+	usb_get_dev(udev);
+	aru->udev = udev;
+	aru->intf = intf;
+	ar = &aru->common;
+
+	aru->req_one_stage_fw = ar9170_requires_one_stage(id);
+
+	usb_set_intfdata(intf, aru);
+	SET_IEEE80211_DEV(ar->hw, &udev->dev);
+
+	init_usb_anchor(&aru->rx_submitted);
+	init_usb_anchor(&aru->tx_pending);
+	init_usb_anchor(&aru->tx_submitted);
+	init_completion(&aru->cmd_wait);
+	spin_lock_init(&aru->tx_urb_lock);
+
+	aru->tx_pending_urbs = 0;
+	aru->tx_submitted_urbs = 0;
+
+	aru->common.stop = ar9170_usb_stop;
+	aru->common.flush = ar9170_usb_flush;
+	aru->common.open = ar9170_usb_open;
+	aru->common.tx = ar9170_usb_tx;
+	aru->common.exec_cmd = ar9170_usb_exec_cmd;
+	aru->common.callback_cmd = ar9170_usb_callback_cmd;
+
+#ifdef CONFIG_PM
+	udev->reset_resume = 1;
+#endif /* CONFIG_PM */
+	err = ar9170_usb_reset(aru);
+	if (err)
+		goto err_freehw;
+
+	err = ar9170_usb_request_firmware(aru);
+	if (err)
+		goto err_freehw;
+
+	err = ar9170_usb_init_device(aru);
+	if (err)
+		goto err_freefw;
+
+	err = ar9170_usb_open(ar);
+	if (err)
+		goto err_unrx;
+
+	err = ar9170_register(ar, &udev->dev);
+
+	ar9170_usb_stop(ar);
+	if (err)
+		goto err_unrx;
+
+	return 0;
+
+err_unrx:
+	ar9170_usb_cancel_urbs(aru);
+
+err_freefw:
+	release_firmware(aru->init_values);
+	release_firmware(aru->firmware);
+
+err_freehw:
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(udev);
+	ieee80211_free_hw(ar->hw);
+out:
+	return err;
+}
+
+static void ar9170_usb_disconnect(struct usb_interface *intf)
+{
+	struct ar9170_usb *aru = usb_get_intfdata(intf);
+
+	if (!aru)
+		return;
+
+	aru->common.state = AR9170_IDLE;
+	ar9170_unregister(&aru->common);
+	ar9170_usb_cancel_urbs(aru);
+
+	release_firmware(aru->init_values);
+	release_firmware(aru->firmware);
+
+	usb_put_dev(aru->udev);
+	usb_set_intfdata(intf, NULL);
+	ieee80211_free_hw(aru->common.hw);
+}
+
+#ifdef CONFIG_PM
+static int ar9170_suspend(struct usb_interface *intf,
+			  pm_message_t  message)
+{
+	struct ar9170_usb *aru = usb_get_intfdata(intf);
+
+	if (!aru)
+		return -ENODEV;
+
+	aru->common.state = AR9170_IDLE;
+	ar9170_usb_cancel_urbs(aru);
+
+	return 0;
+}
+
+static int ar9170_resume(struct usb_interface *intf)
+{
+	struct ar9170_usb *aru = usb_get_intfdata(intf);
+	int err;
+
+	if (!aru)
+		return -ENODEV;
+
+	usb_unpoison_anchored_urbs(&aru->rx_submitted);
+	usb_unpoison_anchored_urbs(&aru->tx_submitted);
+
+	err = ar9170_usb_init_device(aru);
+	if (err)
+		goto err_unrx;
+
+	err = ar9170_usb_open(&aru->common);
+	if (err)
+		goto err_unrx;
+
+	return 0;
+
+err_unrx:
+	aru->common.state = AR9170_IDLE;
+	ar9170_usb_cancel_urbs(aru);
+
+	return err;
+}
+#endif /* CONFIG_PM */
+
+static struct usb_driver ar9170_driver = {
+	.name = "ar9170usb",
+	.probe = ar9170_usb_probe,
+	.disconnect = ar9170_usb_disconnect,
+	.id_table = ar9170_usb_ids,
+	.soft_unbind = 1,
+#ifdef CONFIG_PM
+	.suspend = ar9170_suspend,
+	.resume = ar9170_resume,
+	.reset_resume = ar9170_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init ar9170_init(void)
+{
+	return usb_register(&ar9170_driver);
+}
+
+static void __exit ar9170_exit(void)
+{
+	usb_deregister(&ar9170_driver);
+}
+
+module_init(ar9170_init);
+module_exit(ar9170_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/usb.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/usb.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ar9170/usb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ar9170/usb.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,81 @@
+/*
+ * Atheros AR9170 USB driver
+ *
+ * Driver specific definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, Christian Lamparter <chunkeey@web.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.
+ *
+ * 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; see the file COPYING.  If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *    Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ *    Permission to use, copy, modify, and/or distribute this software for any
+ *    purpose with or without fee is hereby granted, provided that the above
+ *    copyright notice and this permission notice appear in all copies.
+ *
+ *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __USB_H
+#define __USB_H
+
+#include <linux/usb.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <linux/firmware.h>
+#include "eeprom.h"
+#include "hw.h"
+#include "ar9170.h"
+
+#define AR9170_NUM_RX_URBS			16
+#define AR9170_NUM_TX_URBS			8
+
+struct firmware;
+
+struct ar9170_usb {
+	struct ar9170 common;
+	struct usb_device *udev;
+	struct usb_interface *intf;
+
+	struct usb_anchor rx_submitted;
+	struct usb_anchor tx_pending;
+	struct usb_anchor tx_submitted;
+
+	bool req_one_stage_fw;
+
+	spinlock_t tx_urb_lock;
+	unsigned int tx_submitted_urbs;
+	unsigned int tx_pending_urbs;
+
+	struct completion cmd_wait;
+	int readlen;
+	u8 *readbuf;
+
+	const struct firmware *init_values;
+	const struct firmware *firmware;
+};
+
+#endif /* __USB_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/ath5k.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/ath5k.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/ath5k.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/ath5k.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1379 @@
+/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ATH5K_H
+#define _ATH5K_H
+
+/* TODO: Clean up channel debuging -doesn't work anyway- and start
+ * working on reg. control code using all available eeprom information
+ * -rev. engineering needed- */
+#define CHAN_DEBUG	0
+
+#include <linux/io.h>
+#include <linux/types.h>
+#include <net/mac80211.h>
+
+#include "../regd.h"
+
+/* RX/TX descriptor hw structs
+ * TODO: Driver part should only see sw structs */
+#include "desc.h"
+
+/* EEPROM structs/offsets
+ * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
+ * and clean up common bits, then introduce set/get functions in eeprom.c */
+#include "eeprom.h"
+
+/* PCI IDs */
+#define PCI_DEVICE_ID_ATHEROS_AR5210 		0x0007 /* AR5210 */
+#define PCI_DEVICE_ID_ATHEROS_AR5311 		0x0011 /* AR5311 */
+#define PCI_DEVICE_ID_ATHEROS_AR5211 		0x0012 /* AR5211 */
+#define PCI_DEVICE_ID_ATHEROS_AR5212 		0x0013 /* AR5212 */
+#define PCI_DEVICE_ID_3COM_3CRDAG675 		0x0013 /* 3CRDAG675 (Atheros AR5212) */
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175 		0x0013 /* 3CRPAG175 (Atheros AR5212) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 	0x0207 /* AR5210 (Early) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM	0x1014 /* AR5212 (IBM MiniPCI) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 	0x1107 /* AR5210 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 	0x1113 /* AR5212 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 	0x1112 /* AR5211 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 	0xf013 /* AR5212 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 	0xff12 /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 	0xf11b /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 	0x0052 /* AR5312 WMAC (AP31) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 	0x0057 /* AR5312 WMAC (AP30-040) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 	0x0058 /* AR5312 WMAC (AP43-030) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 	0x0014 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 	0x0015 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 	0x0016 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 	0x0017 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 	0x0018 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 	0x0019 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR2413 		0x001a /* AR2413 (Griffin-lite) */
+#define PCI_DEVICE_ID_ATHEROS_AR5413 		0x001b /* AR5413 (Eagle) */
+#define PCI_DEVICE_ID_ATHEROS_AR5424 		0x001c /* AR5424 (Condor PCI-E) */
+#define PCI_DEVICE_ID_ATHEROS_AR5416 		0x0023 /* AR5416 */
+#define PCI_DEVICE_ID_ATHEROS_AR5418 		0x0024 /* AR5418 */
+
+/****************************\
+  GENERIC DRIVER DEFINITIONS
+\****************************/
+
+#define ATH5K_PRINTF(fmt, ...)   printk("%s: " fmt, __func__, ##__VA_ARGS__)
+
+#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
+	printk(_level "ath5k %s: " _fmt, \
+		((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \
+		##__VA_ARGS__)
+
+#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \
+	if (net_ratelimit()) \
+		ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \
+	} while (0)
+
+#define ATH5K_INFO(_sc, _fmt, ...) \
+	ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__)
+
+#define ATH5K_WARN(_sc, _fmt, ...) \
+	ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__)
+
+#define ATH5K_ERR(_sc, _fmt, ...) \
+	ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__)
+
+/*
+ * AR5K REGISTER ACCESS
+ */
+
+/* Some macros to read/write fields */
+
+/* First shift, then mask */
+#define AR5K_REG_SM(_val, _flags)					\
+	(((_val) << _flags##_S) & (_flags))
+
+/* First mask, then shift */
+#define AR5K_REG_MS(_val, _flags)					\
+	(((_val) & (_flags)) >> _flags##_S)
+
+/* Some registers can hold multiple values of interest. For this
+ * reason when we want to write to these registers we must first
+ * retrieve the values which we do not want to clear (lets call this
+ * old_data) and then set the register with this and our new_value:
+ * ( old_data | new_value) */
+#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val)			\
+	ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
+	    (((_val) << _flags##_S) & (_flags)), _reg)
+
+#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask)			\
+	ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) &		\
+			(_mask)) | (_flags), _reg)
+
+#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags)				\
+	ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
+
+#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags)			\
+	ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
+
+/* Access to PHY registers */
+#define AR5K_PHY_READ(ah, _reg)					\
+	ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
+
+#define AR5K_PHY_WRITE(ah, _reg, _val)					\
+	ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
+
+/* Access QCU registers per queue */
+#define AR5K_REG_READ_Q(ah, _reg, _queue)				\
+	(ath5k_hw_reg_read(ah, _reg) & (1 << _queue))			\
+
+#define AR5K_REG_WRITE_Q(ah, _reg, _queue)				\
+	ath5k_hw_reg_write(ah, (1 << _queue), _reg)
+
+#define AR5K_Q_ENABLE_BITS(_reg, _queue) do {				\
+	_reg |= 1 << _queue;						\
+} while (0)
+
+#define AR5K_Q_DISABLE_BITS(_reg, _queue) do {				\
+	_reg &= ~(1 << _queue);						\
+} while (0)
+
+/* Used while writing initvals */
+#define AR5K_REG_WAIT(_i) do {						\
+	if (_i % 64)							\
+		udelay(1);						\
+} while (0)
+
+/* Register dumps are done per operation mode */
+#define AR5K_INI_RFGAIN_5GHZ		0
+#define AR5K_INI_RFGAIN_2GHZ		1
+
+/* TODO: Clean this up */
+#define AR5K_INI_VAL_11A		0
+#define AR5K_INI_VAL_11A_TURBO		1
+#define AR5K_INI_VAL_11B		2
+#define AR5K_INI_VAL_11G		3
+#define AR5K_INI_VAL_11G_TURBO		4
+#define AR5K_INI_VAL_XR			0
+#define AR5K_INI_VAL_MAX		5
+
+/* Used for BSSID etc manipulation */
+#define AR5K_LOW_ID(_a)(				\
+(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24	\
+)
+
+#define AR5K_HIGH_ID(_a)	((_a)[4] | (_a)[5] << 8)
+
+/*
+ * Some tuneable values (these should be changeable by the user)
+ * TODO: Make use of them and add more options OR use debug/configfs
+ */
+#define AR5K_TUNE_DMA_BEACON_RESP		2
+#define AR5K_TUNE_SW_BEACON_RESP		10
+#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF	0
+#define AR5K_TUNE_RADAR_ALERT			false
+#define AR5K_TUNE_MIN_TX_FIFO_THRES		1
+#define AR5K_TUNE_MAX_TX_FIFO_THRES		((IEEE80211_MAX_LEN / 64) + 1)
+#define AR5K_TUNE_REGISTER_TIMEOUT		20000
+/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
+ * be the max value. */
+#define AR5K_TUNE_RSSI_THRES			129
+/* This must be set when setting the RSSI threshold otherwise it can
+ * prevent a reset. If AR5K_RSSI_THR is read after writing to it
+ * the BMISS_THRES will be seen as 0, seems harware doesn't keep
+ * track of it. Max value depends on harware. For AR5210 this is just 7.
+ * For AR5211+ this seems to be up to 255. */
+#define AR5K_TUNE_BMISS_THRES			7
+#define AR5K_TUNE_REGISTER_DWELL_TIME		20000
+#define AR5K_TUNE_BEACON_INTERVAL		100
+#define AR5K_TUNE_AIFS				2
+#define AR5K_TUNE_AIFS_11B			2
+#define AR5K_TUNE_AIFS_XR			0
+#define AR5K_TUNE_CWMIN				15
+#define AR5K_TUNE_CWMIN_11B			31
+#define AR5K_TUNE_CWMIN_XR			3
+#define AR5K_TUNE_CWMAX				1023
+#define AR5K_TUNE_CWMAX_11B			1023
+#define AR5K_TUNE_CWMAX_XR			7
+#define AR5K_TUNE_NOISE_FLOOR			-72
+#define AR5K_TUNE_MAX_TXPOWER			63
+#define AR5K_TUNE_DEFAULT_TXPOWER		25
+#define AR5K_TUNE_TPC_TXPOWER			false
+#define AR5K_TUNE_HWTXTRIES			4
+
+#define AR5K_INIT_CARR_SENSE_EN			1
+
+/*Swap RX/TX Descriptor for big endian archs*/
+#if defined(__BIG_ENDIAN)
+#define AR5K_INIT_CFG	(		\
+	AR5K_CFG_SWTD | AR5K_CFG_SWRD	\
+)
+#else
+#define AR5K_INIT_CFG	0x00000000
+#endif
+
+/* Initial values */
+#define	AR5K_INIT_CYCRSSI_THR1			2
+#define AR5K_INIT_TX_LATENCY			502
+#define AR5K_INIT_USEC				39
+#define AR5K_INIT_USEC_TURBO			79
+#define AR5K_INIT_USEC_32			31
+#define AR5K_INIT_SLOT_TIME			396
+#define AR5K_INIT_SLOT_TIME_TURBO		480
+#define AR5K_INIT_ACK_CTS_TIMEOUT		1024
+#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO		0x08000800
+#define AR5K_INIT_PROG_IFS			920
+#define AR5K_INIT_PROG_IFS_TURBO		960
+#define AR5K_INIT_EIFS				3440
+#define AR5K_INIT_EIFS_TURBO			6880
+#define AR5K_INIT_SIFS				560
+#define AR5K_INIT_SIFS_TURBO			480
+#define AR5K_INIT_SH_RETRY			10
+#define AR5K_INIT_LG_RETRY			AR5K_INIT_SH_RETRY
+#define AR5K_INIT_SSH_RETRY			32
+#define AR5K_INIT_SLG_RETRY			AR5K_INIT_SSH_RETRY
+#define AR5K_INIT_TX_RETRY			10
+
+#define AR5K_INIT_TRANSMIT_LATENCY		(			\
+	(AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) |	\
+	(AR5K_INIT_USEC)						\
+)
+#define AR5K_INIT_TRANSMIT_LATENCY_TURBO	(			\
+	(AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) |	\
+	(AR5K_INIT_USEC_TURBO)						\
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL		(			\
+	(AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) |	\
+	(AR5K_INIT_PROG_IFS)						\
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO	(			\
+	(AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
+	(AR5K_INIT_PROG_IFS_TURBO)					\
+)
+
+/* token to use for aifs, cwmin, cwmax in MadWiFi */
+#define	AR5K_TXQ_USEDEFAULT	((u32) -1)
+
+/* GENERIC CHIPSET DEFINITIONS */
+
+/* MAC Chips */
+enum ath5k_version {
+	AR5K_AR5210	= 0,
+	AR5K_AR5211	= 1,
+	AR5K_AR5212	= 2,
+};
+
+/* PHY Chips */
+enum ath5k_radio {
+	AR5K_RF5110	= 0,
+	AR5K_RF5111	= 1,
+	AR5K_RF5112	= 2,
+	AR5K_RF2413	= 3,
+	AR5K_RF5413	= 4,
+	AR5K_RF2316	= 5,
+	AR5K_RF2317	= 6,
+	AR5K_RF2425	= 7,
+};
+
+/*
+ * Common silicon revision/version values
+ */
+
+enum ath5k_srev_type {
+	AR5K_VERSION_MAC,
+	AR5K_VERSION_RAD,
+};
+
+struct ath5k_srev_name {
+	const char		*sr_name;
+	enum ath5k_srev_type	sr_type;
+	u_int			sr_val;
+};
+
+#define AR5K_SREV_UNKNOWN	0xffff
+
+#define AR5K_SREV_AR5210	0x00 /* Crete */
+#define AR5K_SREV_AR5311	0x10 /* Maui 1 */
+#define AR5K_SREV_AR5311A	0x20 /* Maui 2 */
+#define AR5K_SREV_AR5311B	0x30 /* Spirit */
+#define AR5K_SREV_AR5211	0x40 /* Oahu */
+#define AR5K_SREV_AR5212	0x50 /* Venice */
+#define AR5K_SREV_AR5213	0x55 /* ??? */
+#define AR5K_SREV_AR5213A	0x59 /* Hainan */
+#define AR5K_SREV_AR2413	0x78 /* Griffin lite */
+#define AR5K_SREV_AR2414	0x70 /* Griffin */
+#define AR5K_SREV_AR5424	0x90 /* Condor */
+#define AR5K_SREV_AR5413	0xa4 /* Eagle lite */
+#define AR5K_SREV_AR5414	0xa0 /* Eagle */
+#define AR5K_SREV_AR2415	0xb0 /* Talon */
+#define AR5K_SREV_AR5416	0xc0 /* PCI-E */
+#define AR5K_SREV_AR5418	0xca /* PCI-E */
+#define AR5K_SREV_AR2425	0xe0 /* Swan */
+#define AR5K_SREV_AR2417	0xf0 /* Nala */
+
+#define AR5K_SREV_RAD_5110	0x00
+#define AR5K_SREV_RAD_5111	0x10
+#define AR5K_SREV_RAD_5111A	0x15
+#define AR5K_SREV_RAD_2111	0x20
+#define AR5K_SREV_RAD_5112	0x30
+#define AR5K_SREV_RAD_5112A	0x35
+#define	AR5K_SREV_RAD_5112B	0x36
+#define AR5K_SREV_RAD_2112	0x40
+#define AR5K_SREV_RAD_2112A	0x45
+#define	AR5K_SREV_RAD_2112B	0x46
+#define AR5K_SREV_RAD_2413	0x50
+#define AR5K_SREV_RAD_5413	0x60
+#define AR5K_SREV_RAD_2316	0x70 /* Cobra SoC */
+#define AR5K_SREV_RAD_2317	0x80
+#define AR5K_SREV_RAD_5424	0xa0 /* Mostly same as 5413 */
+#define AR5K_SREV_RAD_2425	0xa2
+#define AR5K_SREV_RAD_5133	0xc0
+
+#define AR5K_SREV_PHY_5211	0x30
+#define AR5K_SREV_PHY_5212	0x41
+#define	AR5K_SREV_PHY_5212A	0x42
+#define AR5K_SREV_PHY_5212B	0x43
+#define AR5K_SREV_PHY_2413	0x45
+#define AR5K_SREV_PHY_5413	0x61
+#define AR5K_SREV_PHY_2425	0x70
+
+/* IEEE defs */
+#define IEEE80211_MAX_LEN       2500
+
+/* TODO add support to mac80211 for vendor-specific rates and modes */
+
+/*
+ * Some of this information is based on Documentation from:
+ *
+ * http://madwifi.org/wiki/ChipsetFeatures/SuperAG
+ *
+ * Modulation for Atheros' eXtended Range - range enhancing extension that is
+ * supposed to double the distance an Atheros client device can keep a
+ * connection with an Atheros access point. This is achieved by increasing
+ * the receiver sensitivity up to, -105dBm, which is about 20dB above what
+ * the 802.11 specifications demand. In addition, new (proprietary) data rates
+ * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
+ *
+ * Please note that can you either use XR or TURBO but you cannot use both,
+ * they are exclusive.
+ *
+ */
+#define MODULATION_XR 		0x00000200
+/*
+ * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
+ * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
+ * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
+ * channels. To use this feature your Access Point must also suport it.
+ * There is also a distinction between "static" and "dynamic" turbo modes:
+ *
+ * - Static: is the dumb version: devices set to this mode stick to it until
+ *     the mode is turned off.
+ * - Dynamic: is the intelligent version, the network decides itself if it
+ *     is ok to use turbo. As soon as traffic is detected on adjacent channels
+ *     (which would get used in turbo mode), or when a non-turbo station joins
+ *     the network, turbo mode won't be used until the situation changes again.
+ *     Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which
+ *     monitors the used radio band in order to decide whether turbo mode may
+ *     be used or not.
+ *
+ * This article claims Super G sticks to bonding of channels 5 and 6 for
+ * USA:
+ *
+ * http://www.pcworld.com/article/id,113428-page,1/article.html
+ *
+ * The channel bonding seems to be driver specific though. In addition to
+ * deciding what channels will be used, these "Turbo" modes are accomplished
+ * by also enabling the following features:
+ *
+ * - Bursting: allows multiple frames to be sent at once, rather than pausing
+ *     after each frame. Bursting is a standards-compliant feature that can be
+ *     used with any Access Point.
+ * - Fast frames: increases the amount of information that can be sent per
+ *     frame, also resulting in a reduction of transmission overhead. It is a
+ *     proprietary feature that needs to be supported by the Access Point.
+ * - Compression: data frames are compressed in real time using a Lempel Ziv
+ *     algorithm. This is done transparently. Once this feature is enabled,
+ *     compression and decompression takes place inside the chipset, without
+ *     putting additional load on the host CPU.
+ *
+ */
+#define MODULATION_TURBO	0x00000080
+
+enum ath5k_driver_mode {
+	AR5K_MODE_11A		=	0,
+	AR5K_MODE_11A_TURBO	=	1,
+	AR5K_MODE_11B		=	2,
+	AR5K_MODE_11G		=	3,
+	AR5K_MODE_11G_TURBO	=	4,
+	AR5K_MODE_XR		=	0,
+	AR5K_MODE_MAX		=	5
+};
+
+enum ath5k_ant_mode {
+	AR5K_ANTMODE_DEFAULT	= 0,	/* default antenna setup */
+	AR5K_ANTMODE_FIXED_A	= 1,	/* only antenna A is present */
+	AR5K_ANTMODE_FIXED_B	= 2,	/* only antenna B is present */
+	AR5K_ANTMODE_SINGLE_AP	= 3,	/* sta locked on a single ap */
+	AR5K_ANTMODE_SECTOR_AP	= 4,	/* AP with tx antenna set on tx desc */
+	AR5K_ANTMODE_SECTOR_STA	= 5,	/* STA with tx antenna set on tx desc */
+	AR5K_ANTMODE_DEBUG	= 6,	/* Debug mode -A -> Rx, B-> Tx- */
+	AR5K_ANTMODE_MAX,
+};
+
+
+/****************\
+  TX DEFINITIONS
+\****************/
+
+/*
+ * TX Status descriptor
+ */
+struct ath5k_tx_status {
+	u16	ts_seqnum;
+	u16	ts_tstamp;
+	u8	ts_status;
+	u8	ts_rate[4];
+	u8	ts_retry[4];
+	u8	ts_final_idx;
+	s8	ts_rssi;
+	u8	ts_shortretry;
+	u8	ts_longretry;
+	u8	ts_virtcol;
+	u8	ts_antenna;
+};
+
+#define AR5K_TXSTAT_ALTRATE	0x80
+#define AR5K_TXERR_XRETRY	0x01
+#define AR5K_TXERR_FILT		0x02
+#define AR5K_TXERR_FIFO		0x04
+
+/**
+ * enum ath5k_tx_queue - Queue types used to classify tx queues.
+ * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue
+ * @AR5K_TX_QUEUE_DATA: A normal data queue
+ * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue
+ * @AR5K_TX_QUEUE_BEACON: The beacon queue
+ * @AR5K_TX_QUEUE_CAB: The after-beacon queue
+ * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue
+ */
+enum ath5k_tx_queue {
+	AR5K_TX_QUEUE_INACTIVE = 0,
+	AR5K_TX_QUEUE_DATA,
+	AR5K_TX_QUEUE_XR_DATA,
+	AR5K_TX_QUEUE_BEACON,
+	AR5K_TX_QUEUE_CAB,
+	AR5K_TX_QUEUE_UAPSD,
+};
+
+#define	AR5K_NUM_TX_QUEUES		10
+#define	AR5K_NUM_TX_QUEUES_NOQCU	2
+
+/*
+ * Queue syb-types to classify normal data queues.
+ * These are the 4 Access Categories as defined in
+ * WME spec. 0 is the lowest priority and 4 is the
+ * highest. Normal data that hasn't been classified
+ * goes to the Best Effort AC.
+ */
+enum ath5k_tx_queue_subtype {
+	AR5K_WME_AC_BK = 0,	/*Background traffic*/
+	AR5K_WME_AC_BE, 	/*Best-effort (normal) traffic)*/
+	AR5K_WME_AC_VI, 	/*Video traffic*/
+	AR5K_WME_AC_VO, 	/*Voice traffic*/
+};
+
+/*
+ * Queue ID numbers as returned by the hw functions, each number
+ * represents a hw queue. If hw does not support hw queues
+ * (eg 5210) all data goes in one queue. These match
+ * d80211 definitions (net80211/MadWiFi don't use them).
+ */
+enum ath5k_tx_queue_id {
+	AR5K_TX_QUEUE_ID_NOQCU_DATA	= 0,
+	AR5K_TX_QUEUE_ID_NOQCU_BEACON	= 1,
+	AR5K_TX_QUEUE_ID_DATA_MIN	= 0, /*IEEE80211_TX_QUEUE_DATA0*/
+	AR5K_TX_QUEUE_ID_DATA_MAX	= 4, /*IEEE80211_TX_QUEUE_DATA4*/
+	AR5K_TX_QUEUE_ID_DATA_SVP	= 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
+	AR5K_TX_QUEUE_ID_CAB		= 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
+	AR5K_TX_QUEUE_ID_BEACON		= 7, /*IEEE80211_TX_QUEUE_BEACON*/
+	AR5K_TX_QUEUE_ID_UAPSD		= 8,
+	AR5K_TX_QUEUE_ID_XR_DATA	= 9,
+};
+
+/*
+ * Flags to set hw queue's parameters...
+ */
+#define AR5K_TXQ_FLAG_TXOKINT_ENABLE		0x0001	/* Enable TXOK interrupt */
+#define AR5K_TXQ_FLAG_TXERRINT_ENABLE		0x0002	/* Enable TXERR interrupt */
+#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE		0x0004	/* Enable TXEOL interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE		0x0008	/* Enable TXDESC interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXURNINT_ENABLE		0x0010	/* Enable TXURN interrupt */
+#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE		0x0020	/* Enable CBRORN interrupt */
+#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE		0x0040	/* Enable CBRURN interrupt */
+#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE		0x0080	/* Enable QTRIG interrupt */
+#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE		0x0100	/* Enable TXNOFRM interrupt */
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE		0x0200	/* Disable random post-backoff */
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE	0x0300	/* Enable ready time expiry policy (?)*/
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE	0x0800	/* Enable backoff while bursting */
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS		0x1000	/* Disable backoff while bursting */
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE	0x2000	/* Enable hw compression -not implemented-*/
+
+/*
+ * A struct to hold tx queue's parameters
+ */
+struct ath5k_txq_info {
+	enum ath5k_tx_queue tqi_type;
+	enum ath5k_tx_queue_subtype tqi_subtype;
+	u16	tqi_flags;	/* Tx queue flags (see above) */
+	u32	tqi_aifs;	/* Arbitrated Interframe Space */
+	s32	tqi_cw_min;	/* Minimum Contention Window */
+	s32	tqi_cw_max;	/* Maximum Contention Window */
+	u32	tqi_cbr_period; /* Constant bit rate period */
+	u32	tqi_cbr_overflow_limit;
+	u32	tqi_burst_time;
+	u32	tqi_ready_time; /* Not used */
+};
+
+/*
+ * Transmit packet types.
+ * used on tx control descriptor
+ * TODO: Use them inside base.c corectly
+ */
+enum ath5k_pkt_type {
+	AR5K_PKT_TYPE_NORMAL		= 0,
+	AR5K_PKT_TYPE_ATIM		= 1,
+	AR5K_PKT_TYPE_PSPOLL		= 2,
+	AR5K_PKT_TYPE_BEACON		= 3,
+	AR5K_PKT_TYPE_PROBE_RESP	= 4,
+	AR5K_PKT_TYPE_PIFS		= 5,
+};
+
+/*
+ * TX power and TPC settings
+ */
+#define AR5K_TXPOWER_OFDM(_r, _v)	(			\
+	((0 & 1) << ((_v) + 6)) |				\
+	(((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v))	\
+)
+
+#define AR5K_TXPOWER_CCK(_r, _v)	(			\
+	(ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v)	\
+)
+
+/*
+ * DMA size definitions (2^n+2)
+ */
+enum ath5k_dmasize {
+	AR5K_DMASIZE_4B	= 0,
+	AR5K_DMASIZE_8B,
+	AR5K_DMASIZE_16B,
+	AR5K_DMASIZE_32B,
+	AR5K_DMASIZE_64B,
+	AR5K_DMASIZE_128B,
+	AR5K_DMASIZE_256B,
+	AR5K_DMASIZE_512B
+};
+
+
+/****************\
+  RX DEFINITIONS
+\****************/
+
+/*
+ * RX Status descriptor
+ */
+struct ath5k_rx_status {
+	u16	rs_datalen;
+	u16	rs_tstamp;
+	u8	rs_status;
+	u8	rs_phyerr;
+	s8	rs_rssi;
+	u8	rs_keyix;
+	u8	rs_rate;
+	u8	rs_antenna;
+	u8	rs_more;
+};
+
+#define AR5K_RXERR_CRC		0x01
+#define AR5K_RXERR_PHY		0x02
+#define AR5K_RXERR_FIFO		0x04
+#define AR5K_RXERR_DECRYPT	0x08
+#define AR5K_RXERR_MIC		0x10
+#define AR5K_RXKEYIX_INVALID	((u8) - 1)
+#define AR5K_TXKEYIX_INVALID	((u32) - 1)
+
+
+/**************************\
+ BEACON TIMERS DEFINITIONS
+\**************************/
+
+#define AR5K_BEACON_PERIOD	0x0000ffff
+#define AR5K_BEACON_ENA		0x00800000 /*enable beacon xmit*/
+#define AR5K_BEACON_RESET_TSF	0x01000000 /*force a TSF reset*/
+
+#if 0
+/**
+ * struct ath5k_beacon_state - Per-station beacon timer state.
+ * @bs_interval: in TU's, can also include the above flags
+ * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a
+ * 	Point Coordination Function capable AP
+ */
+struct ath5k_beacon_state {
+	u32	bs_next_beacon;
+	u32	bs_next_dtim;
+	u32	bs_interval;
+	u8	bs_dtim_period;
+	u8	bs_cfp_period;
+	u16	bs_cfp_max_duration;
+	u16	bs_cfp_du_remain;
+	u16	bs_tim_offset;
+	u16	bs_sleep_duration;
+	u16	bs_bmiss_threshold;
+	u32  	bs_cfp_next;
+};
+#endif
+
+
+/*
+ * TSF to TU conversion:
+ *
+ * TSF is a 64bit value in usec (microseconds).
+ * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of
+ * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024).
+ */
+#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
+
+
+/*******************************\
+  GAIN OPTIMIZATION DEFINITIONS
+\*******************************/
+
+enum ath5k_rfgain {
+	AR5K_RFGAIN_INACTIVE = 0,
+	AR5K_RFGAIN_ACTIVE,
+	AR5K_RFGAIN_READ_REQUESTED,
+	AR5K_RFGAIN_NEED_CHANGE,
+};
+
+struct ath5k_gain {
+	u8			g_step_idx;
+	u8			g_current;
+	u8			g_target;
+	u8			g_low;
+	u8			g_high;
+	u8			g_f_corr;
+	u8			g_state;
+};
+
+/********************\
+  COMMON DEFINITIONS
+\********************/
+
+#define AR5K_SLOT_TIME_9	396
+#define AR5K_SLOT_TIME_20	880
+#define AR5K_SLOT_TIME_MAX	0xffff
+
+/* channel_flags */
+#define	CHANNEL_CW_INT	0x0008	/* Contention Window interference detected */
+#define	CHANNEL_TURBO	0x0010	/* Turbo Channel */
+#define	CHANNEL_CCK	0x0020	/* CCK channel */
+#define	CHANNEL_OFDM	0x0040	/* OFDM channel */
+#define	CHANNEL_2GHZ	0x0080	/* 2GHz channel. */
+#define	CHANNEL_5GHZ	0x0100	/* 5GHz channel */
+#define	CHANNEL_PASSIVE	0x0200	/* Only passive scan allowed */
+#define	CHANNEL_DYN	0x0400	/* Dynamic CCK-OFDM channel (for g operation) */
+#define	CHANNEL_XR	0x0800	/* XR channel */
+
+#define	CHANNEL_A	(CHANNEL_5GHZ|CHANNEL_OFDM)
+#define	CHANNEL_B	(CHANNEL_2GHZ|CHANNEL_CCK)
+#define	CHANNEL_G	(CHANNEL_2GHZ|CHANNEL_OFDM)
+#define	CHANNEL_T	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define	CHANNEL_TG	(CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define	CHANNEL_108A	CHANNEL_T
+#define	CHANNEL_108G	CHANNEL_TG
+#define	CHANNEL_X	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
+
+#define	CHANNEL_ALL 	(CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
+		CHANNEL_TURBO)
+
+#define	CHANNEL_ALL_NOTURBO 	(CHANNEL_ALL & ~CHANNEL_TURBO)
+#define CHANNEL_MODES		CHANNEL_ALL
+
+/*
+ * Used internaly for reset_tx_queue).
+ * Also see struct struct ieee80211_channel.
+ */
+#define IS_CHAN_XR(_c)	((_c.hw_value & CHANNEL_XR) != 0)
+#define IS_CHAN_B(_c)	((_c.hw_value & CHANNEL_B) != 0)
+
+/*
+ * The following structure is used to map 2GHz channels to
+ * 5GHz Atheros channels.
+ * TODO: Clean up
+ */
+struct ath5k_athchan_2ghz {
+	u32	a2_flags;
+	u16	a2_athchan;
+};
+
+
+/******************\
+  RATE DEFINITIONS
+\******************/
+
+/**
+ * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
+ *
+ * The rate code is used to get the RX rate or set the TX rate on the
+ * hardware descriptors. It is also used for internal modulation control
+ * and settings.
+ *
+ * This is the hardware rate map we are aware of:
+ *
+ * rate_code   0x01    0x02    0x03    0x04    0x05    0x06    0x07    0x08
+ * rate_kbps   3000    1000    ?       ?       ?       2000    500     48000
+ *
+ * rate_code   0x09    0x0A    0x0B    0x0C    0x0D    0x0E    0x0F    0x10
+ * rate_kbps   24000   12000   6000    54000   36000   18000   9000    ?
+ *
+ * rate_code   17      18      19      20      21      22      23      24
+ * rate_kbps   ?       ?       ?       ?       ?       ?       ?       11000
+ *
+ * rate_code   25      26      27      28      29      30      31      32
+ * rate_kbps   5500    2000    1000    11000S  5500S   2000S   ?       ?
+ *
+ * "S" indicates CCK rates with short preamble.
+ *
+ * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
+ * lowest 4 bits, so they are the same as below with a 0xF mask.
+ * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
+ * We handle this in ath5k_setup_bands().
+ */
+#define AR5K_MAX_RATES 32
+
+/* B */
+#define ATH5K_RATE_CODE_1M	0x1B
+#define ATH5K_RATE_CODE_2M	0x1A
+#define ATH5K_RATE_CODE_5_5M	0x19
+#define ATH5K_RATE_CODE_11M	0x18
+/* A and G */
+#define ATH5K_RATE_CODE_6M	0x0B
+#define ATH5K_RATE_CODE_9M	0x0F
+#define ATH5K_RATE_CODE_12M	0x0A
+#define ATH5K_RATE_CODE_18M	0x0E
+#define ATH5K_RATE_CODE_24M	0x09
+#define ATH5K_RATE_CODE_36M	0x0D
+#define ATH5K_RATE_CODE_48M	0x08
+#define ATH5K_RATE_CODE_54M	0x0C
+/* XR */
+#define ATH5K_RATE_CODE_XR_500K	0x07
+#define ATH5K_RATE_CODE_XR_1M	0x02
+#define ATH5K_RATE_CODE_XR_2M	0x06
+#define ATH5K_RATE_CODE_XR_3M	0x01
+
+/* adding this flag to rate_code enables short preamble */
+#define AR5K_SET_SHORT_PREAMBLE 0x04
+
+/*
+ * Crypto definitions
+ */
+
+#define AR5K_KEYCACHE_SIZE	8
+
+/***********************\
+ HW RELATED DEFINITIONS
+\***********************/
+
+/*
+ * Misc definitions
+ */
+#define	AR5K_RSSI_EP_MULTIPLIER	(1<<7)
+
+#define AR5K_ASSERT_ENTRY(_e, _s) do {		\
+	if (_e >= _s)				\
+		return (false);			\
+} while (0)
+
+/*
+ * Hardware interrupt abstraction
+ */
+
+/**
+ * enum ath5k_int - Hardware interrupt masks helpers
+ *
+ * @AR5K_INT_RX: mask to identify received frame interrupts, of type
+ * 	AR5K_ISR_RXOK or AR5K_ISR_RXERR
+ * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
+ * @AR5K_INT_RXNOFRM: No frame received (?)
+ * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
+ * 	Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
+ * 	LinkPtr is NULL. For more details, refer to:
+ * 	http://www.freepatentsonline.com/20030225739.html
+ * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
+ * 	Note that Rx overrun is not always fatal, on some chips we can continue
+ * 	operation without reseting the card, that's why int_fatal is not
+ * 	common for all chips.
+ * @AR5K_INT_TX: mask to identify received frame interrupts, of type
+ * 	AR5K_ISR_TXOK or AR5K_ISR_TXERR
+ * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
+ * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
+ * 	We currently do increments on interrupt by
+ * 	(AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
+ * @AR5K_INT_MIB: Indicates the Management Information Base counters should be
+ * 	checked. We should do this with ath5k_hw_update_mib_counters() but
+ * 	it seems we should also then do some noise immunity work.
+ * @AR5K_INT_RXPHY: RX PHY Error
+ * @AR5K_INT_RXKCM: RX Key cache miss
+ * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
+ * 	beacon that must be handled in software. The alternative is if you
+ * 	have VEOL support, in that case you let the hardware deal with things.
+ * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
+ * 	beacons from the AP have associated with, we should probably try to
+ * 	reassociate. When in IBSS mode this might mean we have not received
+ * 	any beacons from any local stations. Note that every station in an
+ * 	IBSS schedules to send beacons at the Target Beacon Transmission Time
+ * 	(TBTT) with a random backoff.
+ * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
+ * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
+ * 	until properly handled
+ * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
+ * 	errors. These types of errors we can enable seem to be of type
+ * 	AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
+ * @AR5K_INT_GLOBAL: Used to clear and set the IER
+ * @AR5K_INT_NOCARD: signals the card has been removed
+ * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
+ * 	bit value
+ *
+ * These are mapped to take advantage of some common bits
+ * between the MACs, to be able to set intr properties
+ * easier. Some of them are not used yet inside hw.c. Most map
+ * to the respective hw interrupt value as they are common amogst different
+ * MACs.
+ */
+enum ath5k_int {
+	AR5K_INT_RXOK	= 0x00000001,
+	AR5K_INT_RXDESC	= 0x00000002,
+	AR5K_INT_RXERR	= 0x00000004,
+	AR5K_INT_RXNOFRM = 0x00000008,
+	AR5K_INT_RXEOL	= 0x00000010,
+	AR5K_INT_RXORN	= 0x00000020,
+	AR5K_INT_TXOK	= 0x00000040,
+	AR5K_INT_TXDESC	= 0x00000080,
+	AR5K_INT_TXERR	= 0x00000100,
+	AR5K_INT_TXNOFRM = 0x00000200,
+	AR5K_INT_TXEOL	= 0x00000400,
+	AR5K_INT_TXURN	= 0x00000800,
+	AR5K_INT_MIB	= 0x00001000,
+	AR5K_INT_SWI	= 0x00002000,
+	AR5K_INT_RXPHY	= 0x00004000,
+	AR5K_INT_RXKCM	= 0x00008000,
+	AR5K_INT_SWBA	= 0x00010000,
+	AR5K_INT_BRSSI	= 0x00020000,
+	AR5K_INT_BMISS	= 0x00040000,
+	AR5K_INT_FATAL	= 0x00080000, /* Non common */
+	AR5K_INT_BNR	= 0x00100000, /* Non common */
+	AR5K_INT_TIM	= 0x00200000, /* Non common */
+	AR5K_INT_DTIM	= 0x00400000, /* Non common */
+	AR5K_INT_DTIM_SYNC =	0x00800000, /* Non common */
+	AR5K_INT_GPIO	=	0x01000000,
+	AR5K_INT_BCN_TIMEOUT =	0x02000000, /* Non common */
+	AR5K_INT_CAB_TIMEOUT =	0x04000000, /* Non common */
+	AR5K_INT_RX_DOPPLER =	0x08000000, /* Non common */
+	AR5K_INT_QCBRORN =	0x10000000, /* Non common */
+	AR5K_INT_QCBRURN =	0x20000000, /* Non common */
+	AR5K_INT_QTRIG	=	0x40000000, /* Non common */
+	AR5K_INT_GLOBAL =	0x80000000,
+
+	AR5K_INT_COMMON  = AR5K_INT_RXOK
+		| AR5K_INT_RXDESC
+		| AR5K_INT_RXERR
+		| AR5K_INT_RXNOFRM
+		| AR5K_INT_RXEOL
+		| AR5K_INT_RXORN
+		| AR5K_INT_TXOK
+		| AR5K_INT_TXDESC
+		| AR5K_INT_TXERR
+		| AR5K_INT_TXNOFRM
+		| AR5K_INT_TXEOL
+		| AR5K_INT_TXURN
+		| AR5K_INT_MIB
+		| AR5K_INT_SWI
+		| AR5K_INT_RXPHY
+		| AR5K_INT_RXKCM
+		| AR5K_INT_SWBA
+		| AR5K_INT_BRSSI
+		| AR5K_INT_BMISS
+		| AR5K_INT_GPIO
+		| AR5K_INT_GLOBAL,
+
+	AR5K_INT_NOCARD	= 0xffffffff
+};
+
+/*
+ * Power management
+ */
+enum ath5k_power_mode {
+	AR5K_PM_UNDEFINED = 0,
+	AR5K_PM_AUTO,
+	AR5K_PM_AWAKE,
+	AR5K_PM_FULL_SLEEP,
+	AR5K_PM_NETWORK_SLEEP,
+};
+
+/*
+ * These match net80211 definitions (not used in
+ * mac80211).
+ * TODO: Clean this up
+ */
+#define AR5K_LED_INIT	0 /*IEEE80211_S_INIT*/
+#define AR5K_LED_SCAN	1 /*IEEE80211_S_SCAN*/
+#define AR5K_LED_AUTH	2 /*IEEE80211_S_AUTH*/
+#define AR5K_LED_ASSOC	3 /*IEEE80211_S_ASSOC*/
+#define AR5K_LED_RUN	4 /*IEEE80211_S_RUN*/
+
+/* GPIO-controlled software LED */
+#define AR5K_SOFTLED_PIN	0
+#define AR5K_SOFTLED_ON		0
+#define AR5K_SOFTLED_OFF	1
+
+/*
+ * Chipset capabilities -see ath5k_hw_get_capability-
+ * get_capability function is not yet fully implemented
+ * in ath5k so most of these don't work yet...
+ * TODO: Implement these & merge with _TUNE_ stuff above
+ */
+enum ath5k_capability_type {
+	AR5K_CAP_REG_DMN		= 0,	/* Used to get current reg. domain id */
+	AR5K_CAP_TKIP_MIC		= 2,	/* Can handle TKIP MIC in hardware */
+	AR5K_CAP_TKIP_SPLIT		= 3,	/* TKIP uses split keys */
+	AR5K_CAP_PHYCOUNTERS		= 4,	/* PHY error counters */
+	AR5K_CAP_DIVERSITY		= 5,	/* Supports fast diversity */
+	AR5K_CAP_NUM_TXQUEUES		= 6,	/* Used to get max number of hw txqueues */
+	AR5K_CAP_VEOL			= 7,	/* Supports virtual EOL */
+	AR5K_CAP_COMPRESSION		= 8,	/* Supports compression */
+	AR5K_CAP_BURST			= 9,	/* Supports packet bursting */
+	AR5K_CAP_FASTFRAME		= 10,	/* Supports fast frames */
+	AR5K_CAP_TXPOW			= 11,	/* Used to get global tx power limit */
+	AR5K_CAP_TPC			= 12,	/* Can do per-packet tx power control (needed for 802.11a) */
+	AR5K_CAP_BSSIDMASK		= 13,	/* Supports bssid mask */
+	AR5K_CAP_MCAST_KEYSRCH		= 14,	/* Supports multicast key search */
+	AR5K_CAP_TSF_ADJUST		= 15,	/* Supports beacon tsf adjust */
+	AR5K_CAP_XR			= 16,	/* Supports XR mode */
+	AR5K_CAP_WME_TKIPMIC 		= 17,	/* Supports TKIP MIC when using WMM */
+	AR5K_CAP_CHAN_HALFRATE 		= 18,	/* Supports half rate channels */
+	AR5K_CAP_CHAN_QUARTERRATE 	= 19,	/* Supports quarter rate channels */
+	AR5K_CAP_RFSILENT		= 20,	/* Supports RFsilent */
+};
+
+
+/* XXX: we *may* move cap_range stuff to struct wiphy */
+struct ath5k_capabilities {
+	/*
+	 * Supported PHY modes
+	 * (ie. CHANNEL_A, CHANNEL_B, ...)
+	 */
+	DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
+
+	/*
+	 * Frequency range (without regulation restrictions)
+	 */
+	struct {
+		u16	range_2ghz_min;
+		u16	range_2ghz_max;
+		u16	range_5ghz_min;
+		u16	range_5ghz_max;
+	} cap_range;
+
+	/*
+	 * Values stored in the EEPROM (some of them...)
+	 */
+	struct ath5k_eeprom_info	cap_eeprom;
+
+	/*
+	 * Queue information
+	 */
+	struct {
+		u8	q_tx_num;
+	} cap_queues;
+};
+
+
+/***************************************\
+  HARDWARE ABSTRACTION LAYER STRUCTURE
+\***************************************/
+
+/*
+ * Misc defines
+ */
+
+#define AR5K_MAX_GPIO		10
+#define AR5K_MAX_RF_BANKS	8
+
+/* TODO: Clean up and merge with ath5k_softc */
+struct ath5k_hw {
+	u32			ah_magic;
+
+	struct ath5k_softc	*ah_sc;
+	void __iomem		*ah_iobase;
+
+	enum ath5k_int		ah_imr;
+
+	enum nl80211_iftype	ah_op_mode;
+	enum ath5k_power_mode	ah_power_mode;
+	struct ieee80211_channel ah_current_channel;
+	bool			ah_turbo;
+	bool			ah_calibration;
+	bool			ah_running;
+	bool			ah_single_chip;
+	bool			ah_combined_mic;
+
+	u32			ah_mac_srev;
+	u16			ah_mac_version;
+	u16			ah_mac_revision;
+	u16			ah_phy_revision;
+	u16			ah_radio_5ghz_revision;
+	u16			ah_radio_2ghz_revision;
+
+	enum ath5k_version	ah_version;
+	enum ath5k_radio	ah_radio;
+	u32			ah_phy;
+
+	bool			ah_5ghz;
+	bool			ah_2ghz;
+
+#define ah_modes		ah_capabilities.cap_mode
+#define ah_ee_version		ah_capabilities.cap_eeprom.ee_version
+
+	u32			ah_atim_window;
+	u32			ah_aifs;
+	u32			ah_cw_min;
+	u32			ah_cw_max;
+	bool			ah_software_retry;
+	u32			ah_limit_tx_retries;
+
+	/* Antenna Control */
+	u32			ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+	u8			ah_ant_mode;
+	u8			ah_tx_ant;
+	u8			ah_def_ant;
+
+	u8			ah_sta_id[ETH_ALEN];
+
+	/* Current BSSID we are trying to assoc to / create.
+	 * This is passed by mac80211 on config_interface() and cached here for
+	 * use in resets */
+	u8			ah_bssid[ETH_ALEN];
+	u8			ah_bssid_mask[ETH_ALEN];
+
+	u32			ah_gpio[AR5K_MAX_GPIO];
+	int			ah_gpio_npins;
+
+	struct ath_regulatory	ah_regulatory;
+	struct ath5k_capabilities ah_capabilities;
+
+	struct ath5k_txq_info	ah_txq[AR5K_NUM_TX_QUEUES];
+	u32			ah_txq_status;
+	u32			ah_txq_imr_txok;
+	u32			ah_txq_imr_txerr;
+	u32			ah_txq_imr_txurn;
+	u32			ah_txq_imr_txdesc;
+	u32			ah_txq_imr_txeol;
+	u32			ah_txq_imr_cbrorn;
+	u32			ah_txq_imr_cbrurn;
+	u32			ah_txq_imr_qtrig;
+	u32			ah_txq_imr_nofrm;
+	u32			ah_txq_isr;
+	u32			*ah_rf_banks;
+	size_t			ah_rf_banks_size;
+	size_t			ah_rf_regs_count;
+	struct ath5k_gain	ah_gain;
+	u8			ah_offset[AR5K_MAX_RF_BANKS];
+
+
+	struct {
+		/* Temporary tables used for interpolation */
+		u8		tmpL[AR5K_EEPROM_N_PD_GAINS]
+					[AR5K_EEPROM_POWER_TABLE_SIZE];
+		u8		tmpR[AR5K_EEPROM_N_PD_GAINS]
+					[AR5K_EEPROM_POWER_TABLE_SIZE];
+		u8		txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2];
+		u16		txp_rates_power_table[AR5K_MAX_RATES];
+		u8		txp_min_idx;
+		bool		txp_tpc;
+		/* Values in 0.25dB units */
+		s16		txp_min_pwr;
+		s16		txp_max_pwr;
+		/* Values in 0.5dB units */
+		s16		txp_offset;
+		s16		txp_ofdm;
+		s16		txp_cck_ofdm_gainf_delta;
+		/* Value in dB units */
+		s16		txp_cck_ofdm_pwr_delta;
+	} ah_txpower;
+
+	struct {
+		bool		r_enabled;
+		int		r_last_alert;
+		struct ieee80211_channel r_last_channel;
+	} ah_radar;
+
+	/* noise floor from last periodic calibration */
+	s32			ah_noise_floor;
+
+	/*
+	 * Function pointers
+	 */
+	int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc,
+				u32 size, unsigned int flags);
+	int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+		unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+		unsigned int, unsigned int, unsigned int, unsigned int,
+		unsigned int, unsigned int, unsigned int);
+	int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+		unsigned int, unsigned int, unsigned int, unsigned int,
+		unsigned int, unsigned int);
+	int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+		struct ath5k_tx_status *);
+	int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+		struct ath5k_rx_status *);
+};
+
+/*
+ * Prototypes
+ */
+
+/* Attach/Detach Functions */
+extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version);
+extern void ath5k_hw_detach(struct ath5k_hw *ah);
+
+/* LED functions */
+extern int ath5k_init_leds(struct ath5k_softc *sc);
+extern void ath5k_led_enable(struct ath5k_softc *sc);
+extern void ath5k_led_off(struct ath5k_softc *sc);
+extern void ath5k_unregister_leds(struct ath5k_softc *sc);
+
+/* Reset Functions */
+extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
+extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
+/* Power management functions */
+extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
+
+/* DMA Related Functions */
+extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
+extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
+extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
+extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
+				u32 phys_addr);
+extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
+/* Interrupt handling */
+extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
+extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
+extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum
+ath5k_int new_mask);
+extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
+
+/* EEPROM access functions */
+extern int ath5k_eeprom_init(struct ath5k_hw *ah);
+extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
+extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
+
+/* Protocol Control Unit Functions */
+extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
+/* BSSID Functions */
+extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
+extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
+extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
+/* Receive start/stop functions */
+extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
+extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
+/* RX Filter functions */
+extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
+extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
+extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
+extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
+/* Beacon control functions */
+extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
+extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
+extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
+extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
+extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
+#if 0
+extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state);
+extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
+extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
+#endif
+/* ACK bit rate */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
+/* ACK/CTS Timeouts */
+extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
+extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
+/* Key table (WEP) functions */
+extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
+extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
+extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac);
+extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
+
+/* Queue Control Unit, DFS Control Unit Functions */
+extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
+				const struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
+				enum ath5k_tx_queue queue_type,
+				struct ath5k_txq_info *queue_info);
+extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
+extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
+extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah);
+extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+
+/* Hardware Descriptor Functions */
+extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
+
+/* GPIO Functions */
+extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
+extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
+extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
+extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+
+/* rfkill Functions */
+extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
+extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
+
+/* Misc functions */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
+extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
+extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
+
+/* Initial register settings functions */
+extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
+
+/* Initialize RF */
+extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
+				struct ieee80211_channel *channel,
+				unsigned int mode);
+extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
+extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
+extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
+/* PHY/RF channel functions */
+extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
+extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
+/* PHY calibration */
+extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
+extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
+/* Spur mitigation */
+bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+				struct ieee80211_channel *channel);
+void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
+				struct ieee80211_channel *channel);
+/* Misc PHY functions */
+extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
+/* Antenna control */
+extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode);
+extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant);
+extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
+/* TX power setup */
+extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower);
+extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
+
+/*
+ * Functions used internaly
+ */
+
+/*
+ * Translate usec to hw clock units
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
+{
+	return turbo ? (usec * 80) : (usec * 40);
+}
+
+/*
+ * Translate hw clock units to usec
+ * TODO: Half/quarter rate
+ */
+static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
+{
+	return turbo ? (clock / 80) : (clock / 40);
+}
+
+/*
+ * Read from a register
+ */
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
+{
+	return ioread32(ah->ah_iobase + reg);
+}
+
+/*
+ * Write to a register
+ */
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
+{
+	iowrite32(val, ah->ah_iobase + reg);
+}
+
+#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY)
+/*
+ * Check if a register write has been completed
+ */
+static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag,
+		u32 val, bool is_set)
+{
+	int i;
+	u32 data;
+
+	for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+		data = ath5k_hw_reg_read(ah, reg);
+		if (is_set && (data & flag))
+			break;
+		else if ((data & flag) == val)
+			break;
+		udelay(15);
+	}
+
+	return (i <= 0) ? -EAGAIN : 0;
+}
+#endif
+
+static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
+{
+	u32 retval = 0, bit, i;
+
+	for (i = 0; i < bits; i++) {
+		bit = (val >> i) & 1;
+		retval = (retval << 1) | bit;
+	}
+
+	return retval;
+}
+
+static inline int ath5k_pad_size(int hdrlen)
+{
+	return (hdrlen < 24) ? 0 : hdrlen & 3;
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/attach.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/attach.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/attach.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/attach.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*************************************\
+* Attach/Detach Functions and helpers *
+\*************************************/
+
+#include <linux/pci.h>
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/**
+ * ath5k_hw_post - Power On Self Test helper function
+ *
+ * @ah: The &struct ath5k_hw
+ */
+static int ath5k_hw_post(struct ath5k_hw *ah)
+{
+
+	static const u32 static_pattern[4] = {
+		0x55555555,	0xaaaaaaaa,
+		0x66666666,	0x99999999
+	};
+	static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) };
+	int i, c;
+	u16 cur_reg;
+	u32 var_pattern;
+	u32 init_val;
+	u32 cur_val;
+
+	for (c = 0; c < 2; c++) {
+
+		cur_reg = regs[c];
+
+		/* Save previous value */
+		init_val = ath5k_hw_reg_read(ah, cur_reg);
+
+		for (i = 0; i < 256; i++) {
+			var_pattern = i << 16 | i;
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+			cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+			if (cur_val != var_pattern) {
+				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+				return -EAGAIN;
+			}
+
+			/* Found on ndiswrapper dumps */
+			var_pattern = 0x0039080f;
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+		}
+
+		for (i = 0; i < 4; i++) {
+			var_pattern = static_pattern[i];
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+			cur_val = ath5k_hw_reg_read(ah, cur_reg);
+
+			if (cur_val != var_pattern) {
+				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
+				return -EAGAIN;
+			}
+
+			/* Found on ndiswrapper dumps */
+			var_pattern = 0x003b080f;
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
+		}
+
+		/* Restore previous value */
+		ath5k_hw_reg_write(ah, init_val, cur_reg);
+
+	}
+
+	return 0;
+
+}
+
+/**
+ * ath5k_hw_attach - Check if hw is supported and init the needed structs
+ *
+ * @sc: The &struct ath5k_softc we got from the driver's attach function
+ * @mac_version: The mac version id (check out ath5k.h) based on pci id
+ *
+ * Check if the device is supported, perform a POST and initialize the needed
+ * structs. Returns -ENOMEM if we don't have memory for the needed structs,
+ * -ENODEV if the device is not supported or prints an error msg if something
+ * else went wrong.
+ */
+struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+{
+	struct ath5k_hw *ah;
+	struct pci_dev *pdev = sc->pdev;
+	int ret;
+	u32 srev;
+
+	/*If we passed the test malloc a ath5k_hw struct*/
+	ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
+	if (ah == NULL) {
+		ret = -ENOMEM;
+		ATH5K_ERR(sc, "out of memory\n");
+		goto err;
+	}
+
+	ah->ah_sc = sc;
+	ah->ah_iobase = sc->iobase;
+
+	/*
+	 * HW information
+	 */
+	ah->ah_op_mode = NL80211_IFTYPE_STATION;
+	ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
+	ah->ah_turbo = false;
+	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+	ah->ah_imr = 0;
+	ah->ah_atim_window = 0;
+	ah->ah_aifs = AR5K_TUNE_AIFS;
+	ah->ah_cw_min = AR5K_TUNE_CWMIN;
+	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
+	ah->ah_software_retry = false;
+
+	/*
+	 * Set the mac version based on the pci id
+	 */
+	ah->ah_version = mac_version;
+
+	/*Fill the ath5k_hw struct with the needed functions*/
+	ret = ath5k_hw_init_desc_functions(ah);
+	if (ret)
+		goto err_free;
+
+	/* Bring device out of sleep and reset it's units */
+	ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
+	if (ret)
+		goto err_free;
+
+	/* Get MAC, PHY and RADIO revisions */
+	srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+	ah->ah_mac_srev = srev;
+	ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+	ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+	ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
+			0xffffffff;
+	ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
+			CHANNEL_5GHZ);
+	ah->ah_phy = AR5K_PHY(0);
+
+	/* Try to identify radio chip based on it's srev */
+	switch (ah->ah_radio_5ghz_revision & 0xf0) {
+	case AR5K_SREV_RAD_5111:
+		ah->ah_radio = AR5K_RF5111;
+		ah->ah_single_chip = false;
+		ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+							CHANNEL_2GHZ);
+		break;
+	case AR5K_SREV_RAD_5112:
+	case AR5K_SREV_RAD_2112:
+		ah->ah_radio = AR5K_RF5112;
+		ah->ah_single_chip = false;
+		ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+							CHANNEL_2GHZ);
+		break;
+	case AR5K_SREV_RAD_2413:
+		ah->ah_radio = AR5K_RF2413;
+		ah->ah_single_chip = true;
+		break;
+	case AR5K_SREV_RAD_5413:
+		ah->ah_radio = AR5K_RF5413;
+		ah->ah_single_chip = true;
+		break;
+	case AR5K_SREV_RAD_2316:
+		ah->ah_radio = AR5K_RF2316;
+		ah->ah_single_chip = true;
+		break;
+	case AR5K_SREV_RAD_2317:
+		ah->ah_radio = AR5K_RF2317;
+		ah->ah_single_chip = true;
+		break;
+	case AR5K_SREV_RAD_5424:
+		if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
+		ah->ah_mac_version == AR5K_SREV_AR2417){
+			ah->ah_radio = AR5K_RF2425;
+			ah->ah_single_chip = true;
+		} else {
+			ah->ah_radio = AR5K_RF5413;
+			ah->ah_single_chip = true;
+		}
+		break;
+	default:
+		/* Identify radio based on mac/phy srev */
+		if (ah->ah_version == AR5K_AR5210) {
+			ah->ah_radio = AR5K_RF5110;
+			ah->ah_single_chip = false;
+		} else if (ah->ah_version == AR5K_AR5211) {
+			ah->ah_radio = AR5K_RF5111;
+			ah->ah_single_chip = false;
+			ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+								CHANNEL_2GHZ);
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
+		ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
+		ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
+			ah->ah_radio = AR5K_RF2425;
+			ah->ah_single_chip = true;
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
+		} else if (srev == AR5K_SREV_AR5213A &&
+		ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
+			ah->ah_radio = AR5K_RF5112;
+			ah->ah_single_chip = false;
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
+			ah->ah_radio = AR5K_RF2316;
+			ah->ah_single_chip = true;
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
+		ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
+			ah->ah_radio = AR5K_RF5413;
+			ah->ah_single_chip = true;
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
+		ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
+			ah->ah_radio = AR5K_RF2413;
+			ah->ah_single_chip = true;
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
+		} else {
+			ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
+			ret = -ENODEV;
+			goto err_free;
+		}
+	}
+
+
+	/* Return on unsuported chips (unsupported eeprom etc) */
+	if ((srev >= AR5K_SREV_AR5416) &&
+	(srev < AR5K_SREV_AR2425)) {
+		ATH5K_ERR(sc, "Device not yet supported.\n");
+		ret = -ENODEV;
+		goto err_free;
+	}
+
+	/*
+	 * Write PCI-E power save settings
+	 */
+	if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
+		ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
+		ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
+		/* Shut off RX when elecidle is asserted */
+		ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
+		ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
+		/* TODO: EEPROM work */
+		ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
+		/* Shut off PLL and CLKREQ active in L1 */
+		ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
+		/* Preserce other settings */
+		ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
+		ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
+		ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
+		/* Reset SERDES to load new settings */
+		ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
+		mdelay(1);
+	}
+
+	/*
+	 * POST
+	 */
+	ret = ath5k_hw_post(ah);
+	if (ret)
+		goto err_free;
+
+	/* Enable pci core retry fix on Hainan (5213A) and later chips */
+	if (srev >= AR5K_SREV_AR5213A)
+		ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
+
+	/*
+	 * Get card capabilities, calibration values etc
+	 * TODO: EEPROM work
+	 */
+	ret = ath5k_eeprom_init(ah);
+	if (ret) {
+		ATH5K_ERR(sc, "unable to init EEPROM\n");
+		goto err_free;
+	}
+
+	/* Get misc capabilities */
+	ret = ath5k_hw_set_capabilities(ah);
+	if (ret) {
+		ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
+			sc->pdev->device);
+		goto err_free;
+	}
+
+	if (srev >= AR5K_SREV_AR2414) {
+		ah->ah_combined_mic = true;
+		AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
+			AR5K_MISC_MODE_COMBINED_MIC);
+	}
+
+	/* MAC address is cleared until add_interface */
+	ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){});
+
+	/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
+	memset(ah->ah_bssid, 0xff, ETH_ALEN);
+	ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+	ath5k_hw_set_opmode(ah);
+
+	ath5k_hw_rfgain_opt_init(ah);
+
+	return ah;
+err_free:
+	kfree(ah);
+err:
+	return ERR_PTR(ret);
+}
+
+/**
+ * ath5k_hw_detach - Free the ath5k_hw struct
+ *
+ * @ah: The &struct ath5k_hw
+ */
+void ath5k_hw_detach(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	__set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
+
+	if (ah->ah_rf_banks != NULL)
+		kfree(ah->ah_rf_banks);
+
+	ath5k_eeprom_detach(ah);
+
+	/* assume interrupts are down */
+	kfree(ah);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/base.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/base.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/base.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/base.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3184 @@
+/*-
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+#include <linux/if.h>
+#include <linux/io.h>
+#include <linux/netdevice.h>
+#include <linux/cache.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/uaccess.h>
+
+#include <net/ieee80211_radiotap.h>
+
+#include <asm/unaligned.h>
+
+#include "base.h"
+#include "reg.h"
+#include "debug.h"
+
+static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+static int modparam_all_channels;
+module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
+MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
+
+
+/******************\
+* Internal defines *
+\******************/
+
+/* Module info */
+MODULE_AUTHOR("Jiri Slaby");
+MODULE_AUTHOR("Nick Kossifidis");
+MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
+MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
+
+
+/* Known PCI ids */
+static const struct pci_device_id ath5k_pci_id_table[] = {
+	{ PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */
+	{ PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */
+	{ PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/
+	{ PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */
+	{ PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */
+	{ PCI_VDEVICE(3COM_2,  0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */
+	{ PCI_VDEVICE(3COM,    0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */
+	{ PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */
+	{ PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+	{ PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
+	{ PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
+	{ PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */
+	{ PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
+
+/* Known SREVs */
+static const struct ath5k_srev_name srev_names[] = {
+	{ "5210",	AR5K_VERSION_MAC,	AR5K_SREV_AR5210 },
+	{ "5311",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311 },
+	{ "5311A",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311A },
+	{ "5311B",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311B },
+	{ "5211",	AR5K_VERSION_MAC,	AR5K_SREV_AR5211 },
+	{ "5212",	AR5K_VERSION_MAC,	AR5K_SREV_AR5212 },
+	{ "5213",	AR5K_VERSION_MAC,	AR5K_SREV_AR5213 },
+	{ "5213A",	AR5K_VERSION_MAC,	AR5K_SREV_AR5213A },
+	{ "2413",	AR5K_VERSION_MAC,	AR5K_SREV_AR2413 },
+	{ "2414",	AR5K_VERSION_MAC,	AR5K_SREV_AR2414 },
+	{ "5424",	AR5K_VERSION_MAC,	AR5K_SREV_AR5424 },
+	{ "5413",	AR5K_VERSION_MAC,	AR5K_SREV_AR5413 },
+	{ "5414",	AR5K_VERSION_MAC,	AR5K_SREV_AR5414 },
+	{ "2415",	AR5K_VERSION_MAC,	AR5K_SREV_AR2415 },
+	{ "5416",	AR5K_VERSION_MAC,	AR5K_SREV_AR5416 },
+	{ "5418",	AR5K_VERSION_MAC,	AR5K_SREV_AR5418 },
+	{ "2425",	AR5K_VERSION_MAC,	AR5K_SREV_AR2425 },
+	{ "2417",	AR5K_VERSION_MAC,	AR5K_SREV_AR2417 },
+	{ "xxxxx",	AR5K_VERSION_MAC,	AR5K_SREV_UNKNOWN },
+	{ "5110",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5110 },
+	{ "5111",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5111 },
+	{ "5111A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5111A },
+	{ "2111",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2111 },
+	{ "5112",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5112 },
+	{ "5112A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5112A },
+	{ "5112B",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5112B },
+	{ "2112",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112 },
+	{ "2112A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112A },
+	{ "2112B",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112B },
+	{ "2413",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2413 },
+	{ "5413",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5413 },
+	{ "2316",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2316 },
+	{ "2317",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2317 },
+	{ "5424",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5424 },
+	{ "5133",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5133 },
+	{ "xxxxx",	AR5K_VERSION_RAD,	AR5K_SREV_UNKNOWN },
+};
+
+static const struct ieee80211_rate ath5k_rates[] = {
+	{ .bitrate = 10,
+	  .hw_value = ATH5K_RATE_CODE_1M, },
+	{ .bitrate = 20,
+	  .hw_value = ATH5K_RATE_CODE_2M,
+	  .hw_value_short = ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 55,
+	  .hw_value = ATH5K_RATE_CODE_5_5M,
+	  .hw_value_short = ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 110,
+	  .hw_value = ATH5K_RATE_CODE_11M,
+	  .hw_value_short = ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE,
+	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 60,
+	  .hw_value = ATH5K_RATE_CODE_6M,
+	  .flags = 0 },
+	{ .bitrate = 90,
+	  .hw_value = ATH5K_RATE_CODE_9M,
+	  .flags = 0 },
+	{ .bitrate = 120,
+	  .hw_value = ATH5K_RATE_CODE_12M,
+	  .flags = 0 },
+	{ .bitrate = 180,
+	  .hw_value = ATH5K_RATE_CODE_18M,
+	  .flags = 0 },
+	{ .bitrate = 240,
+	  .hw_value = ATH5K_RATE_CODE_24M,
+	  .flags = 0 },
+	{ .bitrate = 360,
+	  .hw_value = ATH5K_RATE_CODE_36M,
+	  .flags = 0 },
+	{ .bitrate = 480,
+	  .hw_value = ATH5K_RATE_CODE_48M,
+	  .flags = 0 },
+	{ .bitrate = 540,
+	  .hw_value = ATH5K_RATE_CODE_54M,
+	  .flags = 0 },
+	/* XR missing */
+};
+
+/*
+ * Prototypes - PCI stack related functions
+ */
+static int __devinit	ath5k_pci_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id);
+static void __devexit	ath5k_pci_remove(struct pci_dev *pdev);
+#ifdef CONFIG_PM
+static int		ath5k_pci_suspend(struct pci_dev *pdev,
+					pm_message_t state);
+static int		ath5k_pci_resume(struct pci_dev *pdev);
+#else
+#define ath5k_pci_suspend NULL
+#define ath5k_pci_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_driver ath5k_pci_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= ath5k_pci_id_table,
+	.probe		= ath5k_pci_probe,
+	.remove		= __devexit_p(ath5k_pci_remove),
+	.suspend	= ath5k_pci_suspend,
+	.resume		= ath5k_pci_resume,
+};
+
+
+
+/*
+ * Prototypes - MAC 802.11 stack related functions
+ */
+static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
+static int ath5k_reset_wake(struct ath5k_softc *sc);
+static int ath5k_start(struct ieee80211_hw *hw);
+static void ath5k_stop(struct ieee80211_hw *hw);
+static int ath5k_add_interface(struct ieee80211_hw *hw,
+		struct ieee80211_if_init_conf *conf);
+static void ath5k_remove_interface(struct ieee80211_hw *hw,
+		struct ieee80211_if_init_conf *conf);
+static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
+static void ath5k_configure_filter(struct ieee80211_hw *hw,
+		unsigned int changed_flags,
+		unsigned int *new_flags,
+		int mc_count, struct dev_mc_list *mclist);
+static int ath5k_set_key(struct ieee80211_hw *hw,
+		enum set_key_cmd cmd,
+		struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		struct ieee80211_key_conf *key);
+static int ath5k_get_stats(struct ieee80211_hw *hw,
+		struct ieee80211_low_level_stats *stats);
+static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
+		struct ieee80211_tx_queue_stats *stats);
+static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
+static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
+static void ath5k_reset_tsf(struct ieee80211_hw *hw);
+static int ath5k_beacon_update(struct ieee80211_hw *hw,
+		struct ieee80211_vif *vif);
+static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
+		struct ieee80211_vif *vif,
+		struct ieee80211_bss_conf *bss_conf,
+		u32 changes);
+
+static const struct ieee80211_ops ath5k_hw_ops = {
+	.tx 		= ath5k_tx,
+	.start 		= ath5k_start,
+	.stop 		= ath5k_stop,
+	.add_interface 	= ath5k_add_interface,
+	.remove_interface = ath5k_remove_interface,
+	.config 	= ath5k_config,
+	.configure_filter = ath5k_configure_filter,
+	.set_key 	= ath5k_set_key,
+	.get_stats 	= ath5k_get_stats,
+	.conf_tx 	= NULL,
+	.get_tx_stats 	= ath5k_get_tx_stats,
+	.get_tsf 	= ath5k_get_tsf,
+	.set_tsf 	= ath5k_set_tsf,
+	.reset_tsf 	= ath5k_reset_tsf,
+	.bss_info_changed = ath5k_bss_info_changed,
+};
+
+/*
+ * Prototypes - Internal functions
+ */
+/* Attach detach */
+static int 	ath5k_attach(struct pci_dev *pdev,
+			struct ieee80211_hw *hw);
+static void 	ath5k_detach(struct pci_dev *pdev,
+			struct ieee80211_hw *hw);
+/* Channel/mode setup */
+static inline short ath5k_ieee2mhz(short chan);
+static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
+				struct ieee80211_channel *channels,
+				unsigned int mode,
+				unsigned int max);
+static int 	ath5k_setup_bands(struct ieee80211_hw *hw);
+static int 	ath5k_chan_set(struct ath5k_softc *sc,
+				struct ieee80211_channel *chan);
+static void	ath5k_setcurmode(struct ath5k_softc *sc,
+				unsigned int mode);
+static void	ath5k_mode_setup(struct ath5k_softc *sc);
+
+/* Descriptor setup */
+static int	ath5k_desc_alloc(struct ath5k_softc *sc,
+				struct pci_dev *pdev);
+static void	ath5k_desc_free(struct ath5k_softc *sc,
+				struct pci_dev *pdev);
+/* Buffers setup */
+static int 	ath5k_rxbuf_setup(struct ath5k_softc *sc,
+				struct ath5k_buf *bf);
+static int 	ath5k_txbuf_setup(struct ath5k_softc *sc,
+				struct ath5k_buf *bf);
+static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
+				struct ath5k_buf *bf)
+{
+	BUG_ON(!bf);
+	if (!bf->skb)
+		return;
+	pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
+			PCI_DMA_TODEVICE);
+	dev_kfree_skb_any(bf->skb);
+	bf->skb = NULL;
+}
+
+static inline void ath5k_rxbuf_free(struct ath5k_softc *sc,
+				struct ath5k_buf *bf)
+{
+	BUG_ON(!bf);
+	if (!bf->skb)
+		return;
+	pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
+			PCI_DMA_FROMDEVICE);
+	dev_kfree_skb_any(bf->skb);
+	bf->skb = NULL;
+}
+
+
+/* Queues setup */
+static struct 	ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc,
+				int qtype, int subtype);
+static int 	ath5k_beaconq_setup(struct ath5k_hw *ah);
+static int 	ath5k_beaconq_config(struct ath5k_softc *sc);
+static void 	ath5k_txq_drainq(struct ath5k_softc *sc,
+				struct ath5k_txq *txq);
+static void 	ath5k_txq_cleanup(struct ath5k_softc *sc);
+static void 	ath5k_txq_release(struct ath5k_softc *sc);
+/* Rx handling */
+static int 	ath5k_rx_start(struct ath5k_softc *sc);
+static void 	ath5k_rx_stop(struct ath5k_softc *sc);
+static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
+					struct ath5k_desc *ds,
+					struct sk_buff *skb,
+					struct ath5k_rx_status *rs);
+static void 	ath5k_tasklet_rx(unsigned long data);
+/* Tx handling */
+static void 	ath5k_tx_processq(struct ath5k_softc *sc,
+				struct ath5k_txq *txq);
+static void 	ath5k_tasklet_tx(unsigned long data);
+/* Beacon handling */
+static int 	ath5k_beacon_setup(struct ath5k_softc *sc,
+					struct ath5k_buf *bf);
+static void 	ath5k_beacon_send(struct ath5k_softc *sc);
+static void 	ath5k_beacon_config(struct ath5k_softc *sc);
+static void	ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
+static void	ath5k_tasklet_beacon(unsigned long data);
+
+static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
+{
+	u64 tsf = ath5k_hw_get_tsf64(ah);
+
+	if ((tsf & 0x7fff) < rstamp)
+		tsf -= 0x8000;
+
+	return (tsf & ~0x7fff) | rstamp;
+}
+
+/* Interrupt handling */
+static int 	ath5k_init(struct ath5k_softc *sc);
+static int 	ath5k_stop_locked(struct ath5k_softc *sc);
+static int 	ath5k_stop_hw(struct ath5k_softc *sc);
+static irqreturn_t ath5k_intr(int irq, void *dev_id);
+static void 	ath5k_tasklet_reset(unsigned long data);
+
+static void 	ath5k_calibrate(unsigned long data);
+
+/*
+ * Module init/exit functions
+ */
+static int __init
+init_ath5k_pci(void)
+{
+	int ret;
+
+	ath5k_debug_init();
+
+	ret = pci_register_driver(&ath5k_pci_driver);
+	if (ret) {
+		printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit
+exit_ath5k_pci(void)
+{
+	pci_unregister_driver(&ath5k_pci_driver);
+
+	ath5k_debug_finish();
+}
+
+module_init(init_ath5k_pci);
+module_exit(exit_ath5k_pci);
+
+
+/********************\
+* PCI Initialization *
+\********************/
+
+static const char *
+ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
+{
+	const char *name = "xxxxx";
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
+		if (srev_names[i].sr_type != type)
+			continue;
+
+		if ((val & 0xf0) == srev_names[i].sr_val)
+			name = srev_names[i].sr_name;
+
+		if ((val & 0xff) == srev_names[i].sr_val) {
+			name = srev_names[i].sr_name;
+			break;
+		}
+	}
+
+	return name;
+}
+
+static int __devinit
+ath5k_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *id)
+{
+	void __iomem *mem;
+	struct ath5k_softc *sc;
+	struct ieee80211_hw *hw;
+	int ret;
+	u8 csz;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "can't enable device\n");
+		goto err;
+	}
+
+	/* XXX 32-bit addressing only */
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "32-bit DMA not available\n");
+		goto err_dis;
+	}
+
+	/*
+	 * Cache line size is used to size and align various
+	 * structures used to communicate with the hardware.
+	 */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+	if (csz == 0) {
+		/*
+		 * Linux 2.4.18 (at least) writes the cache line size
+		 * register as a 16-bit wide register which is wrong.
+		 * We must have this setup properly for rx buffer
+		 * DMA to work so force a reasonable value here if it
+		 * comes up zero.
+		 */
+		csz = L1_CACHE_BYTES / sizeof(u32);
+		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+	}
+	/*
+	 * The default setting of latency timer yields poor results,
+	 * set it to the value used by other systems.  It may be worth
+	 * tweaking this setting more.
+	 */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+	/* Enable bus mastering */
+	pci_set_master(pdev);
+
+	/*
+	 * Disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_write_config_byte(pdev, 0x41, 0);
+
+	ret = pci_request_region(pdev, 0, "ath5k");
+	if (ret) {
+		dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
+		goto err_dis;
+	}
+
+	mem = pci_iomap(pdev, 0, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+		ret = -EIO;
+		goto err_reg;
+	}
+
+	/*
+	 * Allocate hw (mac80211 main struct)
+	 * and hw->priv (driver private data)
+	 */
+	hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+	if (hw == NULL) {
+		dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
+		ret = -ENOMEM;
+		goto err_map;
+	}
+
+	dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
+
+	/* Initialize driver private data */
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+		    IEEE80211_HW_SIGNAL_DBM |
+		    IEEE80211_HW_NOISE_DBM;
+
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_ADHOC) |
+		BIT(NL80211_IFTYPE_MESH_POINT);
+
+	hw->extra_tx_headroom = 2;
+	hw->channel_change_time = 5000;
+	sc = hw->priv;
+	sc->hw = hw;
+	sc->pdev = pdev;
+
+	ath5k_debug_init_device(sc);
+
+	/*
+	 * Mark the device as detached to avoid processing
+	 * interrupts until setup is complete.
+	 */
+	__set_bit(ATH_STAT_INVALID, sc->status);
+
+	sc->iobase = mem; /* So we can unmap it on detach */
+	sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
+	sc->opmode = NL80211_IFTYPE_STATION;
+	sc->bintval = 1000;
+	mutex_init(&sc->lock);
+	spin_lock_init(&sc->rxbuflock);
+	spin_lock_init(&sc->txbuflock);
+	spin_lock_init(&sc->block);
+
+	/* Set private data */
+	pci_set_drvdata(pdev, hw);
+
+	/* Setup interrupt handler */
+	ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+	if (ret) {
+		ATH5K_ERR(sc, "request_irq failed\n");
+		goto err_free;
+	}
+
+	/* Initialize device */
+	sc->ah = ath5k_hw_attach(sc, id->driver_data);
+	if (IS_ERR(sc->ah)) {
+		ret = PTR_ERR(sc->ah);
+		goto err_irq;
+	}
+
+	/* set up multi-rate retry capabilities */
+	if (sc->ah->ah_version == AR5K_AR5212) {
+		hw->max_rates = 4;
+		hw->max_rate_tries = 11;
+	}
+
+	/* Finish private driver data initialization */
+	ret = ath5k_attach(pdev, hw);
+	if (ret)
+		goto err_ah;
+
+	ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+			ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
+					sc->ah->ah_mac_srev,
+					sc->ah->ah_phy_revision);
+
+	if (!sc->ah->ah_single_chip) {
+		/* Single chip radio (!RF5111) */
+		if (sc->ah->ah_radio_5ghz_revision &&
+			!sc->ah->ah_radio_2ghz_revision) {
+			/* No 5GHz support -> report 2GHz radio */
+			if (!test_bit(AR5K_MODE_11A,
+				sc->ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			/* No 2GHz support (5110 and some
+			 * 5Ghz only cards) -> report 5Ghz radio */
+			} else if (!test_bit(AR5K_MODE_11B,
+				sc->ah->ah_capabilities.cap_mode)) {
+				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			/* Multiband radio */
+			} else {
+				ATH5K_INFO(sc, "RF%s multiband radio found"
+					" (0x%x)\n",
+					ath5k_chip_name(AR5K_VERSION_RAD,
+						sc->ah->ah_radio_5ghz_revision),
+						sc->ah->ah_radio_5ghz_revision);
+			}
+		}
+		/* Multi chip radio (RF5111 - RF2111) ->
+		 * report both 2GHz/5GHz radios */
+		else if (sc->ah->ah_radio_5ghz_revision &&
+				sc->ah->ah_radio_2ghz_revision){
+			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+				ath5k_chip_name(AR5K_VERSION_RAD,
+					sc->ah->ah_radio_5ghz_revision),
+					sc->ah->ah_radio_5ghz_revision);
+			ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+				ath5k_chip_name(AR5K_VERSION_RAD,
+					sc->ah->ah_radio_2ghz_revision),
+					sc->ah->ah_radio_2ghz_revision);
+		}
+	}
+
+
+	/* ready to process interrupts */
+	__clear_bit(ATH_STAT_INVALID, sc->status);
+
+	return 0;
+err_ah:
+	ath5k_hw_detach(sc->ah);
+err_irq:
+	free_irq(pdev->irq, sc);
+err_free:
+	ieee80211_free_hw(hw);
+err_map:
+	pci_iounmap(pdev, mem);
+err_reg:
+	pci_release_region(pdev, 0);
+err_dis:
+	pci_disable_device(pdev);
+err:
+	return ret;
+}
+
+static void __devexit
+ath5k_pci_remove(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct ath5k_softc *sc = hw->priv;
+
+	ath5k_debug_finish_device(sc);
+	ath5k_detach(pdev, hw);
+	ath5k_hw_detach(sc->ah);
+	free_irq(pdev->irq, sc);
+	pci_iounmap(pdev, sc->iobase);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
+	ieee80211_free_hw(hw);
+}
+
+#ifdef CONFIG_PM
+static int
+ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct ath5k_softc *sc = hw->priv;
+
+	ath5k_led_off(sc);
+
+	free_irq(pdev->irq, sc);
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int
+ath5k_pci_resume(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct ath5k_softc *sc = hw->priv;
+	int err;
+
+	pci_restore_state(pdev);
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	/*
+	 * Suspend/Resume resets the PCI configuration space, so we have to
+	 * re-disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state
+	 */
+	pci_write_config_byte(pdev, 0x41, 0);
+
+	err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+	if (err) {
+		ATH5K_ERR(sc, "request_irq failed\n");
+		goto err_no_irq;
+	}
+
+	ath5k_led_enable(sc);
+	return 0;
+
+err_no_irq:
+	pci_disable_device(pdev);
+	return err;
+}
+#endif /* CONFIG_PM */
+
+
+/***********************\
+* Driver Initialization *
+\***********************/
+
+static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ath5k_softc *sc = hw->priv;
+	struct ath_regulatory *reg = &sc->ah->ah_regulatory;
+
+	return ath_reg_notifier_apply(wiphy, request, reg);
+}
+
+static int
+ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	u8 mac[ETH_ALEN] = {};
+	int ret;
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
+
+	/*
+	 * Check if the MAC has multi-rate retry support.
+	 * We do this by trying to setup a fake extended
+	 * descriptor.  MAC's that don't have support will
+	 * return false w/o doing anything.  MAC's that do
+	 * support it will return true w/o doing anything.
+	 */
+	ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
+	if (ret < 0)
+		goto err;
+	if (ret > 0)
+		__set_bit(ATH_STAT_MRRETRY, sc->status);
+
+	/*
+	 * Collect the channel list.  The 802.11 layer
+	 * is resposible for filtering this list based
+	 * on settings like the phy mode and regulatory
+	 * domain restrictions.
+	 */
+	ret = ath5k_setup_bands(hw);
+	if (ret) {
+		ATH5K_ERR(sc, "can't get channels\n");
+		goto err;
+	}
+
+	/* NB: setup here so ath5k_rate_update is happy */
+	if (test_bit(AR5K_MODE_11A, ah->ah_modes))
+		ath5k_setcurmode(sc, AR5K_MODE_11A);
+	else
+		ath5k_setcurmode(sc, AR5K_MODE_11B);
+
+	/*
+	 * Allocate tx+rx descriptors and populate the lists.
+	 */
+	ret = ath5k_desc_alloc(sc, pdev);
+	if (ret) {
+		ATH5K_ERR(sc, "can't allocate descriptors\n");
+		goto err;
+	}
+
+	/*
+	 * Allocate hardware transmit queues: one queue for
+	 * beacon frames and one data queue for each QoS
+	 * priority.  Note that hw functions handle reseting
+	 * these queues at the needed time.
+	 */
+	ret = ath5k_beaconq_setup(ah);
+	if (ret < 0) {
+		ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
+		goto err_desc;
+	}
+	sc->bhalq = ret;
+
+	sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+	if (IS_ERR(sc->txq)) {
+		ATH5K_ERR(sc, "can't setup xmit queue\n");
+		ret = PTR_ERR(sc->txq);
+		goto err_bhal;
+	}
+
+	tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
+	tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
+	tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
+	tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
+	setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
+
+	ret = ath5k_eeprom_read_mac(ah, mac);
+	if (ret) {
+		ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
+			sc->pdev->device);
+		goto err_queues;
+	}
+
+	SET_IEEE80211_PERM_ADDR(hw, mac);
+	/* All MAC address bits matter for ACKs */
+	memset(sc->bssidmask, 0xff, ETH_ALEN);
+	ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+
+	ah->ah_regulatory.current_rd =
+		ah->ah_capabilities.cap_eeprom.ee_regdomain;
+	ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier);
+	if (ret) {
+		ATH5K_ERR(sc, "can't initialize regulatory system\n");
+		goto err_queues;
+	}
+
+	ret = ieee80211_register_hw(hw);
+	if (ret) {
+		ATH5K_ERR(sc, "can't register ieee80211 hw\n");
+		goto err_queues;
+	}
+
+	if (!ath_is_world_regd(&sc->ah->ah_regulatory))
+		regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2);
+
+	ath5k_init_leds(sc);
+
+	return 0;
+err_queues:
+	ath5k_txq_release(sc);
+err_bhal:
+	ath5k_hw_release_tx_queue(ah, sc->bhalq);
+err_desc:
+	ath5k_desc_free(sc, pdev);
+err:
+	return ret;
+}
+
+static void
+ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	/*
+	 * NB: the order of these is important:
+	 * o call the 802.11 layer before detaching ath5k_hw to
+	 *   insure callbacks into the driver to delete global
+	 *   key cache entries can be handled
+	 * o reclaim the tx queue data structures after calling
+	 *   the 802.11 layer as we'll get called back to reclaim
+	 *   node state and potentially want to use them
+	 * o to cleanup the tx queues the hal is called, so detach
+	 *   it last
+	 * XXX: ??? detach ath5k_hw ???
+	 * Other than that, it's straightforward...
+	 */
+	ieee80211_unregister_hw(hw);
+	ath5k_desc_free(sc, pdev);
+	ath5k_txq_release(sc);
+	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
+	ath5k_unregister_leds(sc);
+
+	/*
+	 * NB: can't reclaim these until after ieee80211_ifdetach
+	 * returns because we'll get called back to reclaim node
+	 * state and potentially want to use them.
+	 */
+}
+
+
+
+
+/********************\
+* Channel/mode setup *
+\********************/
+
+/*
+ * Convert IEEE channel number to MHz frequency.
+ */
+static inline short
+ath5k_ieee2mhz(short chan)
+{
+	if (chan <= 14 || chan >= 27)
+		return ieee80211chan2mhz(chan);
+	else
+		return 2212 + chan * 20;
+}
+
+/*
+ * Returns true for the channel numbers used without all_channels modparam.
+ */
+static bool ath5k_is_standard_channel(short chan)
+{
+	return ((chan <= 14) ||
+		/* UNII 1,2 */
+		((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
+		/* midband */
+		((chan & 3) == 0 && chan >= 100 && chan <= 140) ||
+		/* UNII-3 */
+		((chan & 3) == 1 && chan >= 149 && chan <= 165));
+}
+
+static unsigned int
+ath5k_copy_channels(struct ath5k_hw *ah,
+		struct ieee80211_channel *channels,
+		unsigned int mode,
+		unsigned int max)
+{
+	unsigned int i, count, size, chfreq, freq, ch;
+
+	if (!test_bit(mode, ah->ah_modes))
+		return 0;
+
+	switch (mode) {
+	case AR5K_MODE_11A:
+	case AR5K_MODE_11A_TURBO:
+		/* 1..220, but 2GHz frequencies are filtered by check_channel */
+		size = 220 ;
+		chfreq = CHANNEL_5GHZ;
+		break;
+	case AR5K_MODE_11B:
+	case AR5K_MODE_11G:
+	case AR5K_MODE_11G_TURBO:
+		size = 26;
+		chfreq = CHANNEL_2GHZ;
+		break;
+	default:
+		ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
+		return 0;
+	}
+
+	for (i = 0, count = 0; i < size && max > 0; i++) {
+		ch = i + 1 ;
+		freq = ath5k_ieee2mhz(ch);
+
+		/* Check if channel is supported by the chipset */
+		if (!ath5k_channel_ok(ah, freq, chfreq))
+			continue;
+
+		if (!modparam_all_channels && !ath5k_is_standard_channel(ch))
+			continue;
+
+		/* Write channel info and increment counter */
+		channels[count].center_freq = freq;
+		channels[count].band = (chfreq == CHANNEL_2GHZ) ?
+			IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+		switch (mode) {
+		case AR5K_MODE_11A:
+		case AR5K_MODE_11G:
+			channels[count].hw_value = chfreq | CHANNEL_OFDM;
+			break;
+		case AR5K_MODE_11A_TURBO:
+		case AR5K_MODE_11G_TURBO:
+			channels[count].hw_value = chfreq |
+				CHANNEL_OFDM | CHANNEL_TURBO;
+			break;
+		case AR5K_MODE_11B:
+			channels[count].hw_value = CHANNEL_B;
+		}
+
+		count++;
+		max--;
+	}
+
+	return count;
+}
+
+static void
+ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
+{
+	u8 i;
+
+	for (i = 0; i < AR5K_MAX_RATES; i++)
+		sc->rate_idx[b->band][i] = -1;
+
+	for (i = 0; i < b->n_bitrates; i++) {
+		sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
+		if (b->bitrates[i].hw_value_short)
+			sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
+	}
+}
+
+static int
+ath5k_setup_bands(struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ieee80211_supported_band *sband;
+	int max_c, count_c = 0;
+	int i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
+	max_c = ARRAY_SIZE(sc->channels);
+
+	/* 2GHz band */
+	sband = &sc->sbands[IEEE80211_BAND_2GHZ];
+	sband->band = IEEE80211_BAND_2GHZ;
+	sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0];
+
+	if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
+		/* G mode */
+		memcpy(sband->bitrates, &ath5k_rates[0],
+		       sizeof(struct ieee80211_rate) * 12);
+		sband->n_bitrates = 12;
+
+		sband->channels = sc->channels;
+		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+					AR5K_MODE_11G, max_c);
+
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
+		count_c = sband->n_channels;
+		max_c -= count_c;
+	} else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) {
+		/* B mode */
+		memcpy(sband->bitrates, &ath5k_rates[0],
+		       sizeof(struct ieee80211_rate) * 4);
+		sband->n_bitrates = 4;
+
+		/* 5211 only supports B rates and uses 4bit rate codes
+		 * (e.g normally we have 0x1B for 1M, but on 5211 we have 0x0B)
+		 * fix them up here:
+		 */
+		if (ah->ah_version == AR5K_AR5211) {
+			for (i = 0; i < 4; i++) {
+				sband->bitrates[i].hw_value =
+					sband->bitrates[i].hw_value & 0xF;
+				sband->bitrates[i].hw_value_short =
+					sband->bitrates[i].hw_value_short & 0xF;
+			}
+		}
+
+		sband->channels = sc->channels;
+		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+					AR5K_MODE_11B, max_c);
+
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
+		count_c = sband->n_channels;
+		max_c -= count_c;
+	}
+	ath5k_setup_rate_idx(sc, sband);
+
+	/* 5GHz band, A mode */
+	if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
+		sband = &sc->sbands[IEEE80211_BAND_5GHZ];
+		sband->band = IEEE80211_BAND_5GHZ;
+		sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0];
+
+		memcpy(sband->bitrates, &ath5k_rates[4],
+		       sizeof(struct ieee80211_rate) * 8);
+		sband->n_bitrates = 8;
+
+		sband->channels = &sc->channels[count_c];
+		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+					AR5K_MODE_11A, max_c);
+
+		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
+	}
+	ath5k_setup_rate_idx(sc, sband);
+
+	ath5k_debug_dump_bands(sc);
+
+	return 0;
+}
+
+/*
+ * Set/change channels.  If the channel is really being changed,
+ * it's done by reseting the chip.  To accomplish this we must
+ * first cleanup any pending DMA, then restart stuff after a la
+ * ath5k_init.
+ *
+ * Called with sc->lock.
+ */
+static int
+ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+{
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
+		sc->curchan->center_freq, chan->center_freq);
+
+	if (chan->center_freq != sc->curchan->center_freq ||
+		chan->hw_value != sc->curchan->hw_value) {
+
+		/*
+		 * To switch channels clear any pending DMA operations;
+		 * wait long enough for the RX fifo to drain, reset the
+		 * hardware at the new frequency, and then re-enable
+		 * the relevant bits of the h/w.
+		 */
+		return ath5k_reset(sc, chan);
+	}
+
+	return 0;
+}
+
+static void
+ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+{
+	sc->curmode = mode;
+
+	if (mode == AR5K_MODE_11A) {
+		sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
+	} else {
+		sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
+	}
+}
+
+static void
+ath5k_mode_setup(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	u32 rfilt;
+
+	/* configure rx filter */
+	rfilt = sc->filter_flags;
+	ath5k_hw_set_rx_filter(ah, rfilt);
+
+	if (ath5k_hw_hasbssidmask(ah))
+		ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
+
+	/* configure operational mode */
+	ath5k_hw_set_opmode(ah);
+
+	ath5k_hw_set_mcast_filter(ah, 0, 0);
+	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+}
+
+static inline int
+ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
+{
+	int rix;
+
+	/* return base rate on errors */
+	if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES,
+			"hw_rix out of bounds: %x\n", hw_rix))
+		return 0;
+
+	rix = sc->rate_idx[sc->curband->band][hw_rix];
+	if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
+		rix = 0;
+
+	return rix;
+}
+
+/***************\
+* Buffers setup *
+\***************/
+
+static
+struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
+{
+	struct sk_buff *skb;
+	unsigned int off;
+
+	/*
+	 * Allocate buffer with headroom_needed space for the
+	 * fake physical layer header at the start.
+	 */
+	skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
+
+	if (!skb) {
+		ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
+				sc->rxbufsize + sc->cachelsz - 1);
+		return NULL;
+	}
+	/*
+	 * Cache-line-align.  This is important (for the
+	 * 5210 at least) as not doing so causes bogus data
+	 * in rx'd frames.
+	 */
+	off = ((unsigned long)skb->data) % sc->cachelsz;
+	if (off != 0)
+		skb_reserve(skb, sc->cachelsz - off);
+
+	*skb_addr = pci_map_single(sc->pdev,
+		skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
+	if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
+		ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
+		dev_kfree_skb(skb);
+		return NULL;
+	}
+	return skb;
+}
+
+static int
+ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+	struct ath5k_hw *ah = sc->ah;
+	struct sk_buff *skb = bf->skb;
+	struct ath5k_desc *ds;
+
+	if (!skb) {
+		skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
+		if (!skb)
+			return -ENOMEM;
+		bf->skb = skb;
+	}
+
+	/*
+	 * Setup descriptors.  For receive we always terminate
+	 * the descriptor list with a self-linked entry so we'll
+	 * not get overrun under high load (as can happen with a
+	 * 5212 when ANI processing enables PHY error frames).
+	 *
+	 * To insure the last descriptor is self-linked we create
+	 * each descriptor as self-linked and add it to the end.  As
+	 * each additional descriptor is added the previous self-linked
+	 * entry is ``fixed'' naturally.  This should be safe even
+	 * if DMA is happening.  When processing RX interrupts we
+	 * never remove/process the last, self-linked, entry on the
+	 * descriptor list.  This insures the hardware always has
+	 * someplace to write a new frame.
+	 */
+	ds = bf->desc;
+	ds->ds_link = bf->daddr;	/* link to self */
+	ds->ds_data = bf->skbaddr;
+	ah->ah_setup_rx_desc(ah, ds,
+		skb_tailroom(skb),	/* buffer size */
+		0);
+
+	if (sc->rxlink != NULL)
+		*sc->rxlink = bf->daddr;
+	sc->rxlink = &ds->ds_link;
+	return 0;
+}
+
+static int
+ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_txq *txq = sc->txq;
+	struct ath5k_desc *ds = bf->desc;
+	struct sk_buff *skb = bf->skb;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
+	struct ieee80211_rate *rate;
+	unsigned int mrr_rate[3], mrr_tries[3];
+	int i, ret;
+	u16 hw_rate;
+	u16 cts_rate = 0;
+	u16 duration = 0;
+	u8 rc_flags;
+
+	flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
+
+	/* XXX endianness */
+	bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
+			PCI_DMA_TODEVICE);
+
+	rate = ieee80211_get_tx_rate(sc->hw, info);
+
+	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+		flags |= AR5K_TXDESC_NOACK;
+
+	rc_flags = info->control.rates[0].flags;
+	hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
+		rate->hw_value_short : rate->hw_value;
+
+	pktlen = skb->len;
+
+	/* FIXME: If we are in g mode and rate is a CCK rate
+	 * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
+	 * from tx power (value is in dB units already) */
+	if (info->control.hw_key) {
+		keyidx = info->control.hw_key->hw_key_idx;
+		pktlen += info->control.hw_key->icv_len;
+	}
+	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+		flags |= AR5K_TXDESC_RTSENA;
+		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
+		duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
+			sc->vif, pktlen, info));
+	}
+	if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+		flags |= AR5K_TXDESC_CTSENA;
+		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
+		duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
+			sc->vif, pktlen, info));
+	}
+	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
+		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
+		(sc->power_level * 2),
+		hw_rate,
+		info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
+		cts_rate, duration);
+	if (ret)
+		goto err_unmap;
+
+	memset(mrr_rate, 0, sizeof(mrr_rate));
+	memset(mrr_tries, 0, sizeof(mrr_tries));
+	for (i = 0; i < 3; i++) {
+		rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
+		if (!rate)
+			break;
+
+		mrr_rate[i] = rate->hw_value;
+		mrr_tries[i] = info->control.rates[i + 1].count;
+	}
+
+	ah->ah_setup_mrr_tx_desc(ah, ds,
+		mrr_rate[0], mrr_tries[0],
+		mrr_rate[1], mrr_tries[1],
+		mrr_rate[2], mrr_tries[2]);
+
+	ds->ds_link = 0;
+	ds->ds_data = bf->skbaddr;
+
+	spin_lock_bh(&txq->lock);
+	list_add_tail(&bf->list, &txq->q);
+	sc->tx_stats[txq->qnum].len++;
+	if (txq->link == NULL) /* is this first packet? */
+		ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
+	else /* no, so only link it */
+		*txq->link = bf->daddr;
+
+	txq->link = &ds->ds_link;
+	ath5k_hw_start_tx_dma(ah, txq->qnum);
+	mmiowb();
+	spin_unlock_bh(&txq->lock);
+
+	return 0;
+err_unmap:
+	pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+	return ret;
+}
+
+/*******************\
+* Descriptors setup *
+\*******************/
+
+static int
+ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
+{
+	struct ath5k_desc *ds;
+	struct ath5k_buf *bf;
+	dma_addr_t da;
+	unsigned int i;
+	int ret;
+
+	/* allocate descriptors */
+	sc->desc_len = sizeof(struct ath5k_desc) *
+			(ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
+	sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
+	if (sc->desc == NULL) {
+		ATH5K_ERR(sc, "can't allocate descriptors\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	ds = sc->desc;
+	da = sc->desc_daddr;
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
+		ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
+
+	bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
+			sizeof(struct ath5k_buf), GFP_KERNEL);
+	if (bf == NULL) {
+		ATH5K_ERR(sc, "can't allocate bufptr\n");
+		ret = -ENOMEM;
+		goto err_free;
+	}
+	sc->bufptr = bf;
+
+	INIT_LIST_HEAD(&sc->rxbuf);
+	for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+		bf->desc = ds;
+		bf->daddr = da;
+		list_add_tail(&bf->list, &sc->rxbuf);
+	}
+
+	INIT_LIST_HEAD(&sc->txbuf);
+	sc->txbuf_len = ATH_TXBUF;
+	for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
+			da += sizeof(*ds)) {
+		bf->desc = ds;
+		bf->daddr = da;
+		list_add_tail(&bf->list, &sc->txbuf);
+	}
+
+	/* beacon buffer */
+	bf->desc = ds;
+	bf->daddr = da;
+	sc->bbuf = bf;
+
+	return 0;
+err_free:
+	pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+err:
+	sc->desc = NULL;
+	return ret;
+}
+
+static void
+ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
+{
+	struct ath5k_buf *bf;
+
+	ath5k_txbuf_free(sc, sc->bbuf);
+	list_for_each_entry(bf, &sc->txbuf, list)
+		ath5k_txbuf_free(sc, bf);
+	list_for_each_entry(bf, &sc->rxbuf, list)
+		ath5k_rxbuf_free(sc, bf);
+
+	/* Free memory associated with all descriptors */
+	pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+
+	kfree(sc->bufptr);
+	sc->bufptr = NULL;
+}
+
+
+
+
+
+/**************\
+* Queues setup *
+\**************/
+
+static struct ath5k_txq *
+ath5k_txq_setup(struct ath5k_softc *sc,
+		int qtype, int subtype)
+{
+	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_txq *txq;
+	struct ath5k_txq_info qi = {
+		.tqi_subtype = subtype,
+		.tqi_aifs = AR5K_TXQ_USEDEFAULT,
+		.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
+		.tqi_cw_max = AR5K_TXQ_USEDEFAULT
+	};
+	int qnum;
+
+	/*
+	 * Enable interrupts only for EOL and DESC conditions.
+	 * We mark tx descriptors to receive a DESC interrupt
+	 * when a tx queue gets deep; otherwise waiting for the
+	 * EOL to reap descriptors.  Note that this is done to
+	 * reduce interrupt load and this only defers reaping
+	 * descriptors, never transmitting frames.  Aside from
+	 * reducing interrupts this also permits more concurrency.
+	 * The only potential downside is if the tx queue backs
+	 * up in which case the top half of the kernel may backup
+	 * due to a lack of tx descriptors.
+	 */
+	qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
+				AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
+	qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
+	if (qnum < 0) {
+		/*
+		 * NB: don't print a message, this happens
+		 * normally on parts with too few tx queues
+		 */
+		return ERR_PTR(qnum);
+	}
+	if (qnum >= ARRAY_SIZE(sc->txqs)) {
+		ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
+			qnum, ARRAY_SIZE(sc->txqs));
+		ath5k_hw_release_tx_queue(ah, qnum);
+		return ERR_PTR(-EINVAL);
+	}
+	txq = &sc->txqs[qnum];
+	if (!txq->setup) {
+		txq->qnum = qnum;
+		txq->link = NULL;
+		INIT_LIST_HEAD(&txq->q);
+		spin_lock_init(&txq->lock);
+		txq->setup = true;
+	}
+	return &sc->txqs[qnum];
+}
+
+static int
+ath5k_beaconq_setup(struct ath5k_hw *ah)
+{
+	struct ath5k_txq_info qi = {
+		.tqi_aifs = AR5K_TXQ_USEDEFAULT,
+		.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
+		.tqi_cw_max = AR5K_TXQ_USEDEFAULT,
+		/* NB: for dynamic turbo, don't enable any other interrupts */
+		.tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
+	};
+
+	return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi);
+}
+
+static int
+ath5k_beaconq_config(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_txq_info qi;
+	int ret;
+
+	ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
+	if (ret)
+		return ret;
+	if (sc->opmode == NL80211_IFTYPE_AP ||
+		sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+		/*
+		 * Always burst out beacon and CAB traffic
+		 * (aifs = cwmin = cwmax = 0)
+		 */
+		qi.tqi_aifs = 0;
+		qi.tqi_cw_min = 0;
+		qi.tqi_cw_max = 0;
+	} else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+		/*
+		 * Adhoc mode; backoff between 0 and (2 * cw_min).
+		 */
+		qi.tqi_aifs = 0;
+		qi.tqi_cw_min = 0;
+		qi.tqi_cw_max = 2 * ah->ah_cw_min;
+	}
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+		"beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
+		qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
+
+	ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi);
+	if (ret) {
+		ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
+			"hardware queue!\n", __func__);
+		return ret;
+	}
+
+	return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */;
+}
+
+static void
+ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+	struct ath5k_buf *bf, *bf0;
+
+	/*
+	 * NB: this assumes output has been stopped and
+	 *     we do not need to block ath5k_tx_tasklet
+	 */
+	spin_lock_bh(&txq->lock);
+	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+		ath5k_debug_printtxbuf(sc, bf);
+
+		ath5k_txbuf_free(sc, bf);
+
+		spin_lock_bh(&sc->txbuflock);
+		sc->tx_stats[txq->qnum].len--;
+		list_move_tail(&bf->list, &sc->txbuf);
+		sc->txbuf_len++;
+		spin_unlock_bh(&sc->txbuflock);
+	}
+	txq->link = NULL;
+	spin_unlock_bh(&txq->lock);
+}
+
+/*
+ * Drain the transmit queues and reclaim resources.
+ */
+static void
+ath5k_txq_cleanup(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	unsigned int i;
+
+	/* XXX return value */
+	if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) {
+		/* don't touch the hardware if marked invalid */
+		ath5k_hw_stop_tx_dma(ah, sc->bhalq);
+		ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
+			ath5k_hw_get_txdp(ah, sc->bhalq));
+		for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
+			if (sc->txqs[i].setup) {
+				ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
+				ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
+					"link %p\n",
+					sc->txqs[i].qnum,
+					ath5k_hw_get_txdp(ah,
+							sc->txqs[i].qnum),
+					sc->txqs[i].link);
+			}
+	}
+	ieee80211_wake_queues(sc->hw); /* XXX move to callers */
+
+	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
+		if (sc->txqs[i].setup)
+			ath5k_txq_drainq(sc, &sc->txqs[i]);
+}
+
+static void
+ath5k_txq_release(struct ath5k_softc *sc)
+{
+	struct ath5k_txq *txq = sc->txqs;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
+		if (txq->setup) {
+			ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
+			txq->setup = false;
+		}
+}
+
+
+
+
+/*************\
+* RX Handling *
+\*************/
+
+/*
+ * Enable the receive h/w following a reset.
+ */
+static int
+ath5k_rx_start(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_buf *bf;
+	int ret;
+
+	sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz);
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
+		sc->cachelsz, sc->rxbufsize);
+
+	spin_lock_bh(&sc->rxbuflock);
+	sc->rxlink = NULL;
+	list_for_each_entry(bf, &sc->rxbuf, list) {
+		ret = ath5k_rxbuf_setup(sc, bf);
+		if (ret != 0) {
+			spin_unlock_bh(&sc->rxbuflock);
+			goto err;
+		}
+	}
+	bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+	ath5k_hw_set_rxdp(ah, bf->daddr);
+	spin_unlock_bh(&sc->rxbuflock);
+
+	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
+	ath5k_mode_setup(sc);		/* set filters, etc. */
+	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
+
+	return 0;
+err:
+	return ret;
+}
+
+/*
+ * Disable the receive h/w in preparation for a reset.
+ */
+static void
+ath5k_rx_stop(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+
+	ath5k_hw_stop_rx_pcu(ah);	/* disable PCU */
+	ath5k_hw_set_rx_filter(ah, 0);	/* clear recv filter */
+	ath5k_hw_stop_rx_dma(ah);	/* disable DMA engine */
+
+	ath5k_debug_printrxbuffs(sc, ah);
+
+	sc->rxlink = NULL;		/* just in case */
+}
+
+static unsigned int
+ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
+		struct sk_buff *skb, struct ath5k_rx_status *rs)
+{
+	struct ieee80211_hdr *hdr = (void *)skb->data;
+	unsigned int keyix, hlen;
+
+	if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
+			rs->rs_keyix != AR5K_RXKEYIX_INVALID)
+		return RX_FLAG_DECRYPTED;
+
+	/* Apparently when a default key is used to decrypt the packet
+	   the hw does not set the index used to decrypt.  In such cases
+	   get the index from the packet. */
+	hlen = ieee80211_hdrlen(hdr->frame_control);
+	if (ieee80211_has_protected(hdr->frame_control) &&
+	    !(rs->rs_status & AR5K_RXERR_DECRYPT) &&
+	    skb->len >= hlen + 4) {
+		keyix = skb->data[hlen + 3] >> 6;
+
+		if (test_bit(keyix, sc->keymap))
+			return RX_FLAG_DECRYPTED;
+	}
+
+	return 0;
+}
+
+
+static void
+ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
+		     struct ieee80211_rx_status *rxs)
+{
+	u64 tsf, bc_tstamp;
+	u32 hw_tu;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+
+	if (ieee80211_is_beacon(mgmt->frame_control) &&
+	    le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
+	    memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
+		/*
+		 * Received an IBSS beacon with the same BSSID. Hardware *must*
+		 * have updated the local TSF. We have to work around various
+		 * hardware bugs, though...
+		 */
+		tsf = ath5k_hw_get_tsf64(sc->ah);
+		bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+		hw_tu = TSF_TO_TU(tsf);
+
+		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
+			(unsigned long long)bc_tstamp,
+			(unsigned long long)rxs->mactime,
+			(unsigned long long)(rxs->mactime - bc_tstamp),
+			(unsigned long long)tsf);
+
+		/*
+		 * Sometimes the HW will give us a wrong tstamp in the rx
+		 * status, causing the timestamp extension to go wrong.
+		 * (This seems to happen especially with beacon frames bigger
+		 * than 78 byte (incl. FCS))
+		 * But we know that the receive timestamp must be later than the
+		 * timestamp of the beacon since HW must have synced to that.
+		 *
+		 * NOTE: here we assume mactime to be after the frame was
+		 * received, not like mac80211 which defines it at the start.
+		 */
+		if (bc_tstamp > rxs->mactime) {
+			ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+				"fixing mactime from %llx to %llx\n",
+				(unsigned long long)rxs->mactime,
+				(unsigned long long)tsf);
+			rxs->mactime = tsf;
+		}
+
+		/*
+		 * Local TSF might have moved higher than our beacon timers,
+		 * in that case we have to update them to continue sending
+		 * beacons. This also takes care of synchronizing beacon sending
+		 * times with other stations.
+		 */
+		if (hw_tu >= sc->nexttbtt)
+			ath5k_beacon_update_timers(sc, bc_tstamp);
+	}
+}
+
+static void
+ath5k_tasklet_rx(unsigned long data)
+{
+	struct ieee80211_rx_status rxs = {};
+	struct ath5k_rx_status rs = {};
+	struct sk_buff *skb, *next_skb;
+	dma_addr_t next_skb_addr;
+	struct ath5k_softc *sc = (void *)data;
+	struct ath5k_buf *bf;
+	struct ath5k_desc *ds;
+	int ret;
+	int hdrlen;
+	int padsize;
+
+	spin_lock(&sc->rxbuflock);
+	if (list_empty(&sc->rxbuf)) {
+		ATH5K_WARN(sc, "empty rx buf pool\n");
+		goto unlock;
+	}
+	do {
+		rxs.flag = 0;
+
+		bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+		BUG_ON(bf->skb == NULL);
+		skb = bf->skb;
+		ds = bf->desc;
+
+		/* bail if HW is still using self-linked descriptor */
+		if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr)
+			break;
+
+		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+		if (unlikely(ret == -EINPROGRESS))
+			break;
+		else if (unlikely(ret)) {
+			ATH5K_ERR(sc, "error in processing rx descriptor\n");
+			spin_unlock(&sc->rxbuflock);
+			return;
+		}
+
+		if (unlikely(rs.rs_more)) {
+			ATH5K_WARN(sc, "unsupported jumbo\n");
+			goto next;
+		}
+
+		if (unlikely(rs.rs_status)) {
+			if (rs.rs_status & AR5K_RXERR_PHY)
+				goto next;
+			if (rs.rs_status & AR5K_RXERR_DECRYPT) {
+				/*
+				 * Decrypt error.  If the error occurred
+				 * because there was no hardware key, then
+				 * let the frame through so the upper layers
+				 * can process it.  This is necessary for 5210
+				 * parts which have no way to setup a ``clear''
+				 * key cache entry.
+				 *
+				 * XXX do key cache faulting
+				 */
+				if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
+				    !(rs.rs_status & AR5K_RXERR_CRC))
+					goto accept;
+			}
+			if (rs.rs_status & AR5K_RXERR_MIC) {
+				rxs.flag |= RX_FLAG_MMIC_ERROR;
+				goto accept;
+			}
+
+			/* let crypto-error packets fall through in MNTR */
+			if ((rs.rs_status &
+				~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
+					sc->opmode != NL80211_IFTYPE_MONITOR)
+				goto next;
+		}
+accept:
+		next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
+
+		/*
+		 * If we can't replace bf->skb with a new skb under memory
+		 * pressure, just skip this packet
+		 */
+		if (!next_skb)
+			goto next;
+
+		pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
+				PCI_DMA_FROMDEVICE);
+		skb_put(skb, rs.rs_datalen);
+
+		/* The MAC header is padded to have 32-bit boundary if the
+		 * packet payload is non-zero. The general calculation for
+		 * padsize would take into account odd header lengths:
+		 * padsize = (4 - hdrlen % 4) % 4; However, since only
+		 * even-length headers are used, padding can only be 0 or 2
+		 * bytes and we can optimize this a bit. In addition, we must
+		 * not try to remove padding from short control frames that do
+		 * not have payload. */
+		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+		padsize = ath5k_pad_size(hdrlen);
+		if (padsize) {
+			memmove(skb->data + padsize, skb->data, hdrlen);
+			skb_pull(skb, padsize);
+		}
+
+		/*
+		 * always extend the mac timestamp, since this information is
+		 * also needed for proper IBSS merging.
+		 *
+		 * XXX: it might be too late to do it here, since rs_tstamp is
+		 * 15bit only. that means TSF extension has to be done within
+		 * 32768usec (about 32ms). it might be necessary to move this to
+		 * the interrupt handler, like it is done in madwifi.
+		 *
+		 * Unfortunately we don't know when the hardware takes the rx
+		 * timestamp (beginning of phy frame, data frame, end of rx?).
+		 * The only thing we know is that it is hardware specific...
+		 * On AR5213 it seems the rx timestamp is at the end of the
+		 * frame, but i'm not sure.
+		 *
+		 * NOTE: mac80211 defines mactime at the beginning of the first
+		 * data symbol. Since we don't have any time references it's
+		 * impossible to comply to that. This affects IBSS merge only
+		 * right now, so it's not too bad...
+		 */
+		rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
+		rxs.flag |= RX_FLAG_TSFT;
+
+		rxs.freq = sc->curchan->center_freq;
+		rxs.band = sc->curband->band;
+
+		rxs.noise = sc->ah->ah_noise_floor;
+		rxs.signal = rxs.noise + rs.rs_rssi;
+
+		/* An rssi of 35 indicates you should be able use
+		 * 54 Mbps reliably. A more elaborate scheme can be used
+		 * here but it requires a map of SNR/throughput for each
+		 * possible mode used */
+		rxs.qual = rs.rs_rssi * 100 / 35;
+
+		/* rssi can be more than 35 though, anything above that
+		 * should be considered at 100% */
+		if (rxs.qual > 100)
+			rxs.qual = 100;
+
+		rxs.antenna = rs.rs_antenna;
+		rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
+		rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
+
+		if (rxs.rate_idx >= 0 && rs.rs_rate ==
+		    sc->curband->bitrates[rxs.rate_idx].hw_value_short)
+			rxs.flag |= RX_FLAG_SHORTPRE;
+
+		ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
+
+		/* check beacons in IBSS mode */
+		if (sc->opmode == NL80211_IFTYPE_ADHOC)
+			ath5k_check_ibss_tsf(sc, skb, &rxs);
+
+		__ieee80211_rx(sc->hw, skb, &rxs);
+
+		bf->skb = next_skb;
+		bf->skbaddr = next_skb_addr;
+next:
+		list_move_tail(&bf->list, &sc->rxbuf);
+	} while (ath5k_rxbuf_setup(sc, bf) == 0);
+unlock:
+	spin_unlock(&sc->rxbuflock);
+}
+
+
+
+
+/*************\
+* TX Handling *
+\*************/
+
+static void
+ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+	struct ath5k_tx_status ts = {};
+	struct ath5k_buf *bf, *bf0;
+	struct ath5k_desc *ds;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
+	int i, ret;
+
+	spin_lock(&txq->lock);
+	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+		ds = bf->desc;
+
+		ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+		if (unlikely(ret == -EINPROGRESS))
+			break;
+		else if (unlikely(ret)) {
+			ATH5K_ERR(sc, "error %d while processing queue %u\n",
+				ret, txq->qnum);
+			break;
+		}
+
+		skb = bf->skb;
+		info = IEEE80211_SKB_CB(skb);
+		bf->skb = NULL;
+
+		pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
+				PCI_DMA_TODEVICE);
+
+		ieee80211_tx_info_clear_status(info);
+		for (i = 0; i < 4; i++) {
+			struct ieee80211_tx_rate *r =
+				&info->status.rates[i];
+
+			if (ts.ts_rate[i]) {
+				r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
+				r->count = ts.ts_retry[i];
+			} else {
+				r->idx = -1;
+				r->count = 0;
+			}
+		}
+
+		/* count the successful attempt as well */
+		info->status.rates[ts.ts_final_idx].count++;
+
+		if (unlikely(ts.ts_status)) {
+			sc->ll_stats.dot11ACKFailureCount++;
+			if (ts.ts_status & AR5K_TXERR_FILT)
+				info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+		} else {
+			info->flags |= IEEE80211_TX_STAT_ACK;
+			info->status.ack_signal = ts.ts_rssi;
+		}
+
+		ieee80211_tx_status(sc->hw, skb);
+		sc->tx_stats[txq->qnum].count++;
+
+		spin_lock(&sc->txbuflock);
+		sc->tx_stats[txq->qnum].len--;
+		list_move_tail(&bf->list, &sc->txbuf);
+		sc->txbuf_len++;
+		spin_unlock(&sc->txbuflock);
+	}
+	if (likely(list_empty(&txq->q)))
+		txq->link = NULL;
+	spin_unlock(&txq->lock);
+	if (sc->txbuf_len > ATH_TXBUF / 5)
+		ieee80211_wake_queues(sc->hw);
+}
+
+static void
+ath5k_tasklet_tx(unsigned long data)
+{
+	struct ath5k_softc *sc = (void *)data;
+
+	ath5k_tx_processq(sc, sc->txq);
+}
+
+
+/*****************\
+* Beacon handling *
+\*****************/
+
+/*
+ * Setup the beacon frame for transmit.
+ */
+static int
+ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+	struct sk_buff *skb = bf->skb;
+	struct	ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ath5k_hw *ah = sc->ah;
+	struct ath5k_desc *ds;
+	int ret = 0;
+	u8 antenna;
+	u32 flags;
+
+	bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
+			PCI_DMA_TODEVICE);
+	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
+			"skbaddr %llx\n", skb, skb->data, skb->len,
+			(unsigned long long)bf->skbaddr);
+	if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) {
+		ATH5K_ERR(sc, "beacon DMA mapping failed\n");
+		return -EIO;
+	}
+
+	ds = bf->desc;
+	antenna = ah->ah_tx_ant;
+
+	flags = AR5K_TXDESC_NOACK;
+	if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
+		ds->ds_link = bf->daddr;	/* self-linked */
+		flags |= AR5K_TXDESC_VEOL;
+	} else
+		ds->ds_link = 0;
+
+	/*
+	 * If we use multiple antennas on AP and use
+	 * the Sectored AP scenario, switch antenna every
+	 * 4 beacons to make sure everybody hears our AP.
+	 * When a client tries to associate, hw will keep
+	 * track of the tx antenna to be used for this client
+	 * automaticaly, based on ACKed packets.
+	 *
+	 * Note: AP still listens and transmits RTS on the
+	 * default antenna which is supposed to be an omni.
+	 *
+	 * Note2: On sectored scenarios it's possible to have
+	 * multiple antennas (1omni -the default- and 14 sectors)
+	 * so if we choose to actually support this mode we need
+	 * to allow user to set how many antennas we have and tweak
+	 * the code below to send beacons on all of them.
+	 */
+	if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP)
+		antenna = sc->bsent & 4 ? 2 : 1;
+
+
+	/* FIXME: If we are in g mode and rate is a CCK rate
+	 * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
+	 * from tx power (value is in dB units already) */
+	ds->ds_data = bf->skbaddr;
+	ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
+			ieee80211_get_hdrlen_from_skb(skb),
+			AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
+			ieee80211_get_tx_rate(sc->hw, info)->hw_value,
+			1, AR5K_TXKEYIX_INVALID,
+			antenna, flags, 0, 0);
+	if (ret)
+		goto err_unmap;
+
+	return 0;
+err_unmap:
+	pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+	return ret;
+}
+
+static void ath5k_beacon_disable(struct ath5k_softc *sc)
+{
+	sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
+	ath5k_hw_set_imr(sc->ah, sc->imask);
+	ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
+}
+
+/*
+ * Transmit a beacon frame at SWBA.  Dynamic updates to the
+ * frame contents are done as needed and the slot time is
+ * also adjusted based on current state.
+ *
+ * This is called from software irq context (beacontq or restq
+ * tasklets) or user context from ath5k_beacon_config.
+ */
+static void
+ath5k_beacon_send(struct ath5k_softc *sc)
+{
+	struct ath5k_buf *bf = sc->bbuf;
+	struct ath5k_hw *ah = sc->ah;
+
+	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
+
+	if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
+			sc->opmode == NL80211_IFTYPE_MONITOR)) {
+		ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
+		return;
+	}
+	/*
+	 * Check if the previous beacon has gone out.  If
+	 * not don't don't try to post another, skip this
+	 * period and wait for the next.  Missed beacons
+	 * indicate a problem and should not occur.  If we
+	 * miss too many consecutive beacons reset the device.
+	 */
+	if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
+		sc->bmisscount++;
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+			"missed %u consecutive beacons\n", sc->bmisscount);
+		if (sc->bmisscount > 10) {	/* NB: 10 is a guess */
+			ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+				"stuck beacon time (%u missed)\n",
+				sc->bmisscount);
+			tasklet_schedule(&sc->restq);
+		}
+		return;
+	}
+	if (unlikely(sc->bmisscount != 0)) {
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+			"resume beacon xmit after %u misses\n",
+			sc->bmisscount);
+		sc->bmisscount = 0;
+	}
+
+	/*
+	 * Stop any current dma and put the new frame on the queue.
+	 * This should never fail since we check above that no frames
+	 * are still pending on the queue.
+	 */
+	if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
+		ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq);
+		/* NB: hw still stops DMA, so proceed */
+	}
+
+	/* refresh the beacon for AP mode */
+	if (sc->opmode == NL80211_IFTYPE_AP)
+		ath5k_beacon_update(sc->hw, sc->vif);
+
+	ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
+	ath5k_hw_start_tx_dma(ah, sc->bhalq);
+	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
+		sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
+
+	sc->bsent++;
+}
+
+
+/**
+ * ath5k_beacon_update_timers - update beacon timers
+ *
+ * @sc: struct ath5k_softc pointer we are operating on
+ * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
+ *          beacon timer update based on the current HW TSF.
+ *
+ * Calculate the next target beacon transmit time (TBTT) based on the timestamp
+ * of a received beacon or the current local hardware TSF and write it to the
+ * beacon timer registers.
+ *
+ * This is called in a variety of situations, e.g. when a beacon is received,
+ * when a TSF update has been detected, but also when an new IBSS is created or
+ * when we otherwise know we have to update the timers, but we keep it in this
+ * function to have it all together in one place.
+ */
+static void
+ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
+{
+	struct ath5k_hw *ah = sc->ah;
+	u32 nexttbtt, intval, hw_tu, bc_tu;
+	u64 hw_tsf;
+
+	intval = sc->bintval & AR5K_BEACON_PERIOD;
+	if (WARN_ON(!intval))
+		return;
+
+	/* beacon TSF converted to TU */
+	bc_tu = TSF_TO_TU(bc_tsf);
+
+	/* current TSF converted to TU */
+	hw_tsf = ath5k_hw_get_tsf64(ah);
+	hw_tu = TSF_TO_TU(hw_tsf);
+
+#define FUDGE 3
+	/* we use FUDGE to make sure the next TBTT is ahead of the current TU */
+	if (bc_tsf == -1) {
+		/*
+		 * no beacons received, called internally.
+		 * just need to refresh timers based on HW TSF.
+		 */
+		nexttbtt = roundup(hw_tu + FUDGE, intval);
+	} else if (bc_tsf == 0) {
+		/*
+		 * no beacon received, probably called by ath5k_reset_tsf().
+		 * reset TSF to start with 0.
+		 */
+		nexttbtt = intval;
+		intval |= AR5K_BEACON_RESET_TSF;
+	} else if (bc_tsf > hw_tsf) {
+		/*
+		 * beacon received, SW merge happend but HW TSF not yet updated.
+		 * not possible to reconfigure timers yet, but next time we
+		 * receive a beacon with the same BSSID, the hardware will
+		 * automatically update the TSF and then we need to reconfigure
+		 * the timers.
+		 */
+		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			"need to wait for HW TSF sync\n");
+		return;
+	} else {
+		/*
+		 * most important case for beacon synchronization between STA.
+		 *
+		 * beacon received and HW TSF has been already updated by HW.
+		 * update next TBTT based on the TSF of the beacon, but make
+		 * sure it is ahead of our local TSF timer.
+		 */
+		nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval);
+	}
+#undef FUDGE
+
+	sc->nexttbtt = nexttbtt;
+
+	intval |= AR5K_BEACON_ENA;
+	ath5k_hw_init_beacon(ah, nexttbtt, intval);
+
+	/*
+	 * debugging output last in order to preserve the time critical aspect
+	 * of this function
+	 */
+	if (bc_tsf == -1)
+		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			"reconfigured timers based on HW TSF\n");
+	else if (bc_tsf == 0)
+		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			"reset HW TSF and timers\n");
+	else
+		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			"updated timers based on beacon TSF\n");
+
+	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			  "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
+			  (unsigned long long) bc_tsf,
+			  (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt);
+	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
+		intval & AR5K_BEACON_PERIOD,
+		intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
+		intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
+}
+
+
+/**
+ * ath5k_beacon_config - Configure the beacon queues and interrupts
+ *
+ * @sc: struct ath5k_softc pointer we are operating on
+ *
+ * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
+ * interrupts to detect TSF updates only.
+ */
+static void
+ath5k_beacon_config(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	unsigned long flags;
+
+	ath5k_hw_set_imr(ah, 0);
+	sc->bmisscount = 0;
+	sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
+
+	if (sc->opmode == NL80211_IFTYPE_ADHOC ||
+			sc->opmode == NL80211_IFTYPE_MESH_POINT ||
+			sc->opmode == NL80211_IFTYPE_AP) {
+		/*
+		 * In IBSS mode we use a self-linked tx descriptor and let the
+		 * hardware send the beacons automatically. We have to load it
+		 * only once here.
+		 * We use the SWBA interrupt only to keep track of the beacon
+		 * timers in order to detect automatic TSF updates.
+		 */
+		ath5k_beaconq_config(sc);
+
+		sc->imask |= AR5K_INT_SWBA;
+
+		if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+			if (ath5k_hw_hasveol(ah)) {
+				spin_lock_irqsave(&sc->block, flags);
+				ath5k_beacon_send(sc);
+				spin_unlock_irqrestore(&sc->block, flags);
+			}
+		} else
+			ath5k_beacon_update_timers(sc, -1);
+	}
+
+	ath5k_hw_set_imr(ah, sc->imask);
+}
+
+static void ath5k_tasklet_beacon(unsigned long data)
+{
+	struct ath5k_softc *sc = (struct ath5k_softc *) data;
+
+	/*
+	 * Software beacon alert--time to send a beacon.
+	 *
+	 * In IBSS mode we use this interrupt just to
+	 * keep track of the next TBTT (target beacon
+	 * transmission time) in order to detect wether
+	 * automatic TSF updates happened.
+	 */
+	if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+		/* XXX: only if VEOL suppported */
+		u64 tsf = ath5k_hw_get_tsf64(sc->ah);
+		sc->nexttbtt += sc->bintval;
+		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+				"SWBA nexttbtt: %x hw_tu: %x "
+				"TSF: %llx\n",
+				sc->nexttbtt,
+				TSF_TO_TU(tsf),
+				(unsigned long long) tsf);
+	} else {
+		spin_lock(&sc->block);
+		ath5k_beacon_send(sc);
+		spin_unlock(&sc->block);
+	}
+}
+
+
+/********************\
+* Interrupt handling *
+\********************/
+
+static int
+ath5k_init(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+	int ret, i;
+
+	mutex_lock(&sc->lock);
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
+
+	/*
+	 * Stop anything previously setup.  This is safe
+	 * no matter this is the first time through or not.
+	 */
+	ath5k_stop_locked(sc);
+
+	/*
+	 * The basic interface to setting the hardware in a good
+	 * state is ``reset''.  On return the hardware is known to
+	 * be powered up and with interrupts disabled.  This must
+	 * be followed by initialization of the appropriate bits
+	 * and then setup of the interrupt mask.
+	 */
+	sc->curchan = sc->hw->conf.channel;
+	sc->curband = &sc->sbands[sc->curchan->band];
+	sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+		AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
+		AR5K_INT_FATAL | AR5K_INT_GLOBAL;
+	ret = ath5k_reset(sc, NULL);
+	if (ret)
+		goto done;
+
+	ath5k_rfkill_hw_start(ah);
+
+	/*
+	 * Reset the key cache since some parts do not reset the
+	 * contents on initial power up or resume from suspend.
+	 */
+	for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
+		ath5k_hw_reset_key(ah, i);
+
+	/* Set ack to be sent at low bit-rates */
+	ath5k_hw_set_ack_bitrate_high(ah, false);
+
+	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
+			msecs_to_jiffies(ath5k_calinterval * 1000)));
+
+	ret = 0;
+done:
+	mmiowb();
+	mutex_unlock(&sc->lock);
+	return ret;
+}
+
+static int
+ath5k_stop_locked(struct ath5k_softc *sc)
+{
+	struct ath5k_hw *ah = sc->ah;
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
+			test_bit(ATH_STAT_INVALID, sc->status));
+
+	/*
+	 * Shutdown the hardware and driver:
+	 *    stop output from above
+	 *    disable interrupts
+	 *    turn off timers
+	 *    turn off the radio
+	 *    clear transmit machinery
+	 *    clear receive machinery
+	 *    drain and release tx queues
+	 *    reclaim beacon resources
+	 *    power down hardware
+	 *
+	 * Note that some of this work is not possible if the
+	 * hardware is gone (invalid).
+	 */
+	ieee80211_stop_queues(sc->hw);
+
+	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+		ath5k_led_off(sc);
+		ath5k_hw_set_imr(ah, 0);
+		synchronize_irq(sc->pdev->irq);
+	}
+	ath5k_txq_cleanup(sc);
+	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+		ath5k_rx_stop(sc);
+		ath5k_hw_phy_disable(ah);
+	} else
+		sc->rxlink = NULL;
+
+	return 0;
+}
+
+/*
+ * Stop the device, grabbing the top-level lock to protect
+ * against concurrent entry through ath5k_init (which can happen
+ * if another thread does a system call and the thread doing the
+ * stop is preempted).
+ */
+static int
+ath5k_stop_hw(struct ath5k_softc *sc)
+{
+	int ret;
+
+	mutex_lock(&sc->lock);
+	ret = ath5k_stop_locked(sc);
+	if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
+		/*
+		 * Set the chip in full sleep mode.  Note that we are
+		 * careful to do this only when bringing the interface
+		 * completely to a stop.  When the chip is in this state
+		 * it must be carefully woken up or references to
+		 * registers in the PCI clock domain may freeze the bus
+		 * (and system).  This varies by chip and is mostly an
+		 * issue with newer parts that go to sleep more quickly.
+		 */
+		if (sc->ah->ah_mac_srev >= 0x78) {
+			/*
+			 * XXX
+			 * don't put newer MAC revisions > 7.8 to sleep because
+			 * of the above mentioned problems
+			 */
+			ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
+				"not putting device to sleep\n");
+		} else {
+			ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+				"putting device to full sleep\n");
+			ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
+		}
+	}
+	ath5k_txbuf_free(sc, sc->bbuf);
+
+	mmiowb();
+	mutex_unlock(&sc->lock);
+
+	del_timer_sync(&sc->calib_tim);
+	tasklet_kill(&sc->rxtq);
+	tasklet_kill(&sc->txtq);
+	tasklet_kill(&sc->restq);
+	tasklet_kill(&sc->beacontq);
+
+	ath5k_rfkill_hw_stop(sc->ah);
+
+	return ret;
+}
+
+static irqreturn_t
+ath5k_intr(int irq, void *dev_id)
+{
+	struct ath5k_softc *sc = dev_id;
+	struct ath5k_hw *ah = sc->ah;
+	enum ath5k_int status;
+	unsigned int counter = 1000;
+
+	if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
+				!ath5k_hw_is_intr_pending(ah)))
+		return IRQ_NONE;
+
+	do {
+		ath5k_hw_get_isr(ah, &status);		/* NB: clears IRQ too */
+		ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
+				status, sc->imask);
+		if (unlikely(status & AR5K_INT_FATAL)) {
+			/*
+			 * Fatal errors are unrecoverable.
+			 * Typically these are caused by DMA errors.
+			 */
+			tasklet_schedule(&sc->restq);
+		} else if (unlikely(status & AR5K_INT_RXORN)) {
+			tasklet_schedule(&sc->restq);
+		} else {
+			if (status & AR5K_INT_SWBA) {
+				tasklet_hi_schedule(&sc->beacontq);
+			}
+			if (status & AR5K_INT_RXEOL) {
+				/*
+				* NB: the hardware should re-read the link when
+				*     RXE bit is written, but it doesn't work at
+				*     least on older hardware revs.
+				*/
+				sc->rxlink = NULL;
+			}
+			if (status & AR5K_INT_TXURN) {
+				/* bump tx trigger level */
+				ath5k_hw_update_tx_triglevel(ah, true);
+			}
+			if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
+				tasklet_schedule(&sc->rxtq);
+			if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
+					| AR5K_INT_TXERR | AR5K_INT_TXEOL))
+				tasklet_schedule(&sc->txtq);
+			if (status & AR5K_INT_BMISS) {
+				/* TODO */
+			}
+			if (status & AR5K_INT_MIB) {
+				/*
+				 * These stats are also used for ANI i think
+				 * so how about updating them more often ?
+				 */
+				ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+			}
+			if (status & AR5K_INT_GPIO)
+				tasklet_schedule(&sc->rf_kill.toggleq);
+
+		}
+	} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
+
+	if (unlikely(!counter))
+		ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
+
+	return IRQ_HANDLED;
+}
+
+static void
+ath5k_tasklet_reset(unsigned long data)
+{
+	struct ath5k_softc *sc = (void *)data;
+
+	ath5k_reset_wake(sc);
+}
+
+/*
+ * Periodically recalibrate the PHY to account
+ * for temperature/environment changes.
+ */
+static void
+ath5k_calibrate(unsigned long data)
+{
+	struct ath5k_softc *sc = (void *)data;
+	struct ath5k_hw *ah = sc->ah;
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
+		ieee80211_frequency_to_channel(sc->curchan->center_freq),
+		sc->curchan->hw_value);
+
+	if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
+		/*
+		 * Rfgain is out of bounds, reset the chip
+		 * to load new gain values.
+		 */
+		ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
+		ath5k_reset_wake(sc);
+	}
+	if (ath5k_hw_phy_calibrate(ah, sc->curchan))
+		ATH5K_ERR(sc, "calibration of channel %u failed\n",
+			ieee80211_frequency_to_channel(
+				sc->curchan->center_freq));
+
+	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
+			msecs_to_jiffies(ath5k_calinterval * 1000)));
+}
+
+
+/********************\
+* Mac80211 functions *
+\********************/
+
+static int
+ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_buf *bf;
+	unsigned long flags;
+	int hdrlen;
+	int padsize;
+
+	ath5k_debug_dump_skb(sc, skb, "TX  ", 1);
+
+	if (sc->opmode == NL80211_IFTYPE_MONITOR)
+		ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
+
+	/*
+	 * the hardware expects the header padded to 4 byte boundaries
+	 * if this is not the case we add the padding after the header
+	 */
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	padsize = ath5k_pad_size(hdrlen);
+	if (padsize) {
+
+		if (skb_headroom(skb) < padsize) {
+			ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
+				  " headroom to pad %d\n", hdrlen, padsize);
+			goto drop_packet;
+		}
+		skb_push(skb, padsize);
+		memmove(skb->data, skb->data+padsize, hdrlen);
+	}
+
+	spin_lock_irqsave(&sc->txbuflock, flags);
+	if (list_empty(&sc->txbuf)) {
+		ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
+		spin_unlock_irqrestore(&sc->txbuflock, flags);
+		ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
+		goto drop_packet;
+	}
+	bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
+	list_del(&bf->list);
+	sc->txbuf_len--;
+	if (list_empty(&sc->txbuf))
+		ieee80211_stop_queues(hw);
+	spin_unlock_irqrestore(&sc->txbuflock, flags);
+
+	bf->skb = skb;
+
+	if (ath5k_txbuf_setup(sc, bf)) {
+		bf->skb = NULL;
+		spin_lock_irqsave(&sc->txbuflock, flags);
+		list_add_tail(&bf->list, &sc->txbuf);
+		sc->txbuf_len++;
+		spin_unlock_irqrestore(&sc->txbuflock, flags);
+		goto drop_packet;
+	}
+	return NETDEV_TX_OK;
+
+drop_packet:
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+/*
+ * Reset the hardware.  If chan is not NULL, then also pause rx/tx
+ * and change to the given channel.
+ */
+static int
+ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+{
+	struct ath5k_hw *ah = sc->ah;
+	int ret;
+
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+
+	if (chan) {
+		ath5k_hw_set_imr(ah, 0);
+		ath5k_txq_cleanup(sc);
+		ath5k_rx_stop(sc);
+
+		sc->curchan = chan;
+		sc->curband = &sc->sbands[chan->band];
+	}
+	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
+	if (ret) {
+		ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
+		goto err;
+	}
+
+	ret = ath5k_rx_start(sc);
+	if (ret) {
+		ATH5K_ERR(sc, "can't start recv logic\n");
+		goto err;
+	}
+
+	/*
+	 * Change channels and update the h/w rate map if we're switching;
+	 * e.g. 11a to 11b/g.
+	 *
+	 * We may be doing a reset in response to an ioctl that changes the
+	 * channel so update any state that might change as a result.
+	 *
+	 * XXX needed?
+	 */
+/*	ath5k_chan_change(sc, c); */
+
+	ath5k_beacon_config(sc);
+	/* intrs are enabled by ath5k_beacon_config */
+
+	return 0;
+err:
+	return ret;
+}
+
+static int
+ath5k_reset_wake(struct ath5k_softc *sc)
+{
+	int ret;
+
+	ret = ath5k_reset(sc, sc->curchan);
+	if (!ret)
+		ieee80211_wake_queues(sc->hw);
+
+	return ret;
+}
+
+static int ath5k_start(struct ieee80211_hw *hw)
+{
+	return ath5k_init(hw->priv);
+}
+
+static void ath5k_stop(struct ieee80211_hw *hw)
+{
+	ath5k_stop_hw(hw->priv);
+}
+
+static int ath5k_add_interface(struct ieee80211_hw *hw,
+		struct ieee80211_if_init_conf *conf)
+{
+	struct ath5k_softc *sc = hw->priv;
+	int ret;
+
+	mutex_lock(&sc->lock);
+	if (sc->vif) {
+		ret = 0;
+		goto end;
+	}
+
+	sc->vif = conf->vif;
+
+	switch (conf->type) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+	case NL80211_IFTYPE_MONITOR:
+		sc->opmode = conf->type;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		goto end;
+	}
+
+	ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
+
+	ret = 0;
+end:
+	mutex_unlock(&sc->lock);
+	return ret;
+}
+
+static void
+ath5k_remove_interface(struct ieee80211_hw *hw,
+			struct ieee80211_if_init_conf *conf)
+{
+	struct ath5k_softc *sc = hw->priv;
+	u8 mac[ETH_ALEN] = {};
+
+	mutex_lock(&sc->lock);
+	if (sc->vif != conf->vif)
+		goto end;
+
+	ath5k_hw_set_lladdr(sc->ah, mac);
+	ath5k_beacon_disable(sc);
+	sc->vif = NULL;
+end:
+	mutex_unlock(&sc->lock);
+}
+
+/*
+ * TODO: Phy disable/diversity etc
+ */
+static int
+ath5k_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ieee80211_conf *conf = &hw->conf;
+	int ret = 0;
+
+	mutex_lock(&sc->lock);
+
+	ret = ath5k_chan_set(sc, conf->channel);
+	if (ret < 0)
+		goto unlock;
+
+	if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
+	(sc->power_level != conf->power_level)) {
+		sc->power_level = conf->power_level;
+
+		/* Half dB steps */
+		ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
+	}
+
+	/* TODO:
+	 * 1) Move this on config_interface and handle each case
+	 * separately eg. when we have only one STA vif, use
+	 * AR5K_ANTMODE_SINGLE_AP
+	 *
+	 * 2) Allow the user to change antenna mode eg. when only
+	 * one antenna is present
+	 *
+	 * 3) Allow the user to set default/tx antenna when possible
+	 *
+	 * 4) Default mode should handle 90% of the cases, together
+	 * with fixed a/b and single AP modes we should be able to
+	 * handle 99%. Sectored modes are extreme cases and i still
+	 * haven't found a usage for them. If we decide to support them,
+	 * then we must allow the user to set how many tx antennas we
+	 * have available
+	 */
+	ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
+
+unlock:
+	mutex_unlock(&sc->lock);
+	return ret;
+}
+
+#define SUPPORTED_FIF_FLAGS \
+	FIF_PROMISC_IN_BSS |  FIF_ALLMULTI | FIF_FCSFAIL | \
+	FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
+	FIF_BCN_PRBRESP_PROMISC
+/*
+ * o always accept unicast, broadcast, and multicast traffic
+ * o multicast traffic for all BSSIDs will be enabled if mac80211
+ *   says it should be
+ * o maintain current state of phy ofdm or phy cck error reception.
+ *   If the hardware detects any of these type of errors then
+ *   ath5k_hw_get_rx_filter() will pass to us the respective
+ *   hardware filters to be able to receive these type of frames.
+ * o probe request frames are accepted only when operating in
+ *   hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ *   - when operating in adhoc mode so the 802.11 layer creates
+ *     node table entries for peers,
+ *   - when operating in station mode for collecting rssi data when
+ *     the station is otherwise quiet, or
+ *   - when scanning
+ */
+static void ath5k_configure_filter(struct ieee80211_hw *hw,
+		unsigned int changed_flags,
+		unsigned int *new_flags,
+		int mc_count, struct dev_mc_list *mclist)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	u32 mfilt[2], val, rfilt;
+	u8 pos;
+	int i;
+
+	mfilt[0] = 0;
+	mfilt[1] = 0;
+
+	/* Only deal with supported flags */
+	changed_flags &= SUPPORTED_FIF_FLAGS;
+	*new_flags &= SUPPORTED_FIF_FLAGS;
+
+	/* If HW detects any phy or radar errors, leave those filters on.
+	 * Also, always enable Unicast, Broadcasts and Multicast
+	 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
+	rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
+		(AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
+		AR5K_RX_FILTER_MCAST);
+
+	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
+		if (*new_flags & FIF_PROMISC_IN_BSS) {
+			rfilt |= AR5K_RX_FILTER_PROM;
+			__set_bit(ATH_STAT_PROMISC, sc->status);
+		} else {
+			__clear_bit(ATH_STAT_PROMISC, sc->status);
+		}
+	}
+
+	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
+	if (*new_flags & FIF_ALLMULTI) {
+		mfilt[0] =  ~0;
+		mfilt[1] =  ~0;
+	} else {
+		for (i = 0; i < mc_count; i++) {
+			if (!mclist)
+				break;
+			/* calculate XOR of eight 6-bit values */
+			val = get_unaligned_le32(mclist->dmi_addr + 0);
+			pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+			val = get_unaligned_le32(mclist->dmi_addr + 3);
+			pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+			pos &= 0x3f;
+			mfilt[pos / 32] |= (1 << (pos % 32));
+			/* XXX: we might be able to just do this instead,
+			* but not sure, needs testing, if we do use this we'd
+			* neet to inform below to not reset the mcast */
+			/* ath5k_hw_set_mcast_filterindex(ah,
+			 *      mclist->dmi_addr[5]); */
+			mclist = mclist->next;
+		}
+	}
+
+	/* This is the best we can do */
+	if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
+		rfilt |= AR5K_RX_FILTER_PHYERR;
+
+	/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
+	* and probes for any BSSID, this needs testing */
+	if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
+		rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ;
+
+	/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
+	 * set we should only pass on control frames for this
+	 * station. This needs testing. I believe right now this
+	 * enables *all* control frames, which is OK.. but
+	 * but we should see if we can improve on granularity */
+	if (*new_flags & FIF_CONTROL)
+		rfilt |= AR5K_RX_FILTER_CONTROL;
+
+	/* Additional settings per mode -- this is per ath5k */
+
+	/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
+
+	if (sc->opmode == NL80211_IFTYPE_MONITOR)
+		rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
+			AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
+	if (sc->opmode != NL80211_IFTYPE_STATION)
+		rfilt |= AR5K_RX_FILTER_PROBEREQ;
+	if (sc->opmode != NL80211_IFTYPE_AP &&
+		sc->opmode != NL80211_IFTYPE_MESH_POINT &&
+		test_bit(ATH_STAT_PROMISC, sc->status))
+		rfilt |= AR5K_RX_FILTER_PROM;
+	if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) ||
+		sc->opmode == NL80211_IFTYPE_ADHOC ||
+		sc->opmode == NL80211_IFTYPE_AP)
+		rfilt |= AR5K_RX_FILTER_BEACON;
+	if (sc->opmode == NL80211_IFTYPE_MESH_POINT)
+		rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
+			AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
+
+	/* Set filters */
+	ath5k_hw_set_rx_filter(ah, rfilt);
+
+	/* Set multicast bits */
+	ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
+	/* Set the cached hw filter flags, this will alter actually
+	 * be set in HW */
+	sc->filter_flags = rfilt;
+}
+
+static int
+ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+	      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+	      struct ieee80211_key_conf *key)
+{
+	struct ath5k_softc *sc = hw->priv;
+	int ret = 0;
+
+	if (modparam_nohwcrypt)
+		return -EOPNOTSUPP;
+
+	if (sc->opmode == NL80211_IFTYPE_AP)
+		return -EOPNOTSUPP;
+
+	switch (key->alg) {
+	case ALG_WEP:
+	case ALG_TKIP:
+		break;
+	case ALG_CCMP:
+		return -EOPNOTSUPP;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	mutex_lock(&sc->lock);
+
+	switch (cmd) {
+	case SET_KEY:
+		ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
+				       sta ? sta->addr : NULL);
+		if (ret) {
+			ATH5K_ERR(sc, "can't set the key\n");
+			goto unlock;
+		}
+		__set_bit(key->keyidx, sc->keymap);
+		key->hw_key_idx = key->keyidx;
+		key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
+			       IEEE80211_KEY_FLAG_GENERATE_MMIC);
+		break;
+	case DISABLE_KEY:
+		ath5k_hw_reset_key(sc->ah, key->keyidx);
+		__clear_bit(key->keyidx, sc->keymap);
+		break;
+	default:
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+unlock:
+	mmiowb();
+	mutex_unlock(&sc->lock);
+	return ret;
+}
+
+static int
+ath5k_get_stats(struct ieee80211_hw *hw,
+		struct ieee80211_low_level_stats *stats)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+
+	/* Force update */
+	ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+
+	memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
+
+	return 0;
+}
+
+static int
+ath5k_get_tx_stats(struct ieee80211_hw *hw,
+		struct ieee80211_tx_queue_stats *stats)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats));
+
+	return 0;
+}
+
+static u64
+ath5k_get_tsf(struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	return ath5k_hw_get_tsf64(sc->ah);
+}
+
+static void
+ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	ath5k_hw_set_tsf64(sc->ah, tsf);
+}
+
+static void
+ath5k_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	/*
+	 * in IBSS mode we need to update the beacon timers too.
+	 * this will also reset the TSF if we call it with 0
+	 */
+	if (sc->opmode == NL80211_IFTYPE_ADHOC)
+		ath5k_beacon_update_timers(sc, 0);
+	else
+		ath5k_hw_reset_tsf(sc->ah);
+}
+
+/*
+ * Updates the beacon that is sent by ath5k_beacon_send.  For adhoc,
+ * this is called only once at config_bss time, for AP we do it every
+ * SWBA interrupt so that the TIM will reflect buffered frames.
+ *
+ * Called with the beacon lock.
+ */
+static int
+ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	int ret;
+	struct ath5k_softc *sc = hw->priv;
+	struct sk_buff *skb;
+
+	if (WARN_ON(!vif)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	skb = ieee80211_beacon_get(hw, vif);
+
+	if (!skb) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ath5k_debug_dump_skb(sc, skb, "BC  ", 1);
+
+	ath5k_txbuf_free(sc, sc->bbuf);
+	sc->bbuf->skb = skb;
+	ret = ath5k_beacon_setup(sc, sc->bbuf);
+	if (ret)
+		sc->bbuf->skb = NULL;
+out:
+	return ret;
+}
+
+/*
+ *  Update the beacon and reconfigure the beacon queues.
+ */
+static void
+ath5k_beacon_reconfig(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	int ret;
+	unsigned long flags;
+	struct ath5k_softc *sc = hw->priv;
+
+	spin_lock_irqsave(&sc->block, flags);
+	ret = ath5k_beacon_update(hw, vif);
+	spin_unlock_irqrestore(&sc->block, flags);
+	if (ret == 0) {
+		ath5k_beacon_config(sc);
+		mmiowb();
+	}
+}
+
+static void
+set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	u32 rfilt;
+	rfilt = ath5k_hw_get_rx_filter(ah);
+	if (enable)
+		rfilt |= AR5K_RX_FILTER_BEACON;
+	else
+		rfilt &= ~AR5K_RX_FILTER_BEACON;
+	ath5k_hw_set_rx_filter(ah, rfilt);
+	sc->filter_flags = rfilt;
+}
+
+static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *bss_conf,
+				    u32 changes)
+{
+	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+
+	mutex_lock(&sc->lock);
+	if (WARN_ON(sc->vif != vif))
+		goto unlock;
+
+	if (changes & BSS_CHANGED_BSSID) {
+		/* Cache for later use during resets */
+		memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN);
+		/* XXX: assoc id is set to 0 for now, mac80211 doesn't have
+		 * a clean way of letting us retrieve this yet. */
+		ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+		mmiowb();
+	}
+
+	if (changes & BSS_CHANGED_BEACON_INT)
+		sc->bintval = bss_conf->beacon_int;
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		sc->assoc = bss_conf->assoc;
+		if (sc->opmode == NL80211_IFTYPE_STATION)
+			set_beacon_filter(hw, sc->assoc);
+	}
+
+	if (changes & BSS_CHANGED_BEACON &&
+	    (vif->type == NL80211_IFTYPE_ADHOC ||
+	     vif->type == NL80211_IFTYPE_MESH_POINT ||
+	     vif->type == NL80211_IFTYPE_AP)) {
+		ath5k_beacon_reconfig(hw, vif);
+	}
+
+ unlock:
+	mutex_unlock(&sc->lock);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/base.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/base.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/base.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/base.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ */
+
+/*
+ * Defintions for the Atheros Wireless LAN controller driver.
+ */
+#ifndef _DEV_ATH_ATHVAR_H
+#define _DEV_ATH_ATHVAR_H
+
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/wireless.h>
+#include <linux/if_ether.h>
+#include <linux/leds.h>
+#include <linux/rfkill.h>
+
+#include "ath5k.h"
+#include "debug.h"
+
+#define	ATH_RXBUF	40		/* number of RX buffers */
+#define	ATH_TXBUF	200		/* number of TX buffers */
+#define ATH_BCBUF	1		/* number of beacon buffers */
+
+struct ath5k_buf {
+	struct list_head	list;
+	struct ath5k_desc	*desc;	/* virtual addr of desc */
+	dma_addr_t		daddr;	/* physical addr of desc */
+	struct sk_buff		*skb;	/* skbuff for buf */
+	dma_addr_t		skbaddr;/* physical addr of skb data */
+};
+
+/*
+ * Data transmit queue state.  One of these exists for each
+ * hardware transmit queue.  Packets sent to us from above
+ * are assigned to queues based on their priority.  Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+struct ath5k_txq {
+	unsigned int		qnum;	/* hardware q number */
+	u32			*link;	/* link ptr in last TX desc */
+	struct list_head	q;	/* transmit queue */
+	spinlock_t		lock;	/* lock on q and link */
+	bool			setup;
+};
+
+#define ATH5K_LED_MAX_NAME_LEN 31
+
+/*
+ * State for LED triggers
+ */
+struct ath5k_led
+{
+	char name[ATH5K_LED_MAX_NAME_LEN + 1];	/* name of the LED in sysfs */
+	struct ath5k_softc *sc;			/* driver state */
+	struct led_classdev led_dev;		/* led classdev */
+};
+
+/* Rfkill */
+struct ath5k_rfkill {
+	/* GPIO PIN for rfkill */
+	u16 gpio;
+	/* polarity of rfkill GPIO PIN */
+	bool polarity;
+	/* RFKILL toggle tasklet */
+	struct tasklet_struct toggleq;
+};
+
+#if CHAN_DEBUG
+#define ATH_CHAN_MAX	(26+26+26+200+200)
+#else
+#define ATH_CHAN_MAX	(14+14+14+252+20)
+#endif
+
+/* Software Carrier, keeps track of the driver state
+ * associated with an instance of a device */
+struct ath5k_softc {
+	struct pci_dev		*pdev;		/* for dma mapping */
+	void __iomem		*iobase;	/* address of the device */
+	struct mutex		lock;		/* dev-level lock */
+	/* FIXME: how many does it really need? */
+	struct ieee80211_tx_queue_stats tx_stats[16];
+	struct ieee80211_low_level_stats ll_stats;
+	struct ieee80211_hw	*hw;		/* IEEE 802.11 common */
+	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+	struct ieee80211_channel channels[ATH_CHAN_MAX];
+	struct ieee80211_rate	rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+	s8			rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
+	enum nl80211_iftype	opmode;
+	struct ath5k_hw		*ah;		/* Atheros HW */
+
+	struct ieee80211_supported_band		*curband;
+
+#ifdef CONFIG_ATH5K_DEBUG
+	struct ath5k_dbg_info	debug;		/* debug info */
+#endif /* CONFIG_ATH5K_DEBUG */
+
+	struct ath5k_buf	*bufptr;	/* allocated buffer ptr */
+	struct ath5k_desc	*desc;		/* TX/RX descriptors */
+	dma_addr_t		desc_daddr;	/* DMA (physical) address */
+	size_t			desc_len;	/* size of TX/RX descriptors */
+	u16			cachelsz;	/* cache line size */
+
+	DECLARE_BITMAP(status, 5);
+#define ATH_STAT_INVALID	0		/* disable hardware accesses */
+#define ATH_STAT_MRRETRY	1		/* multi-rate retry support */
+#define ATH_STAT_PROMISC	2
+#define ATH_STAT_LEDSOFT	3		/* enable LED gpio status */
+#define ATH_STAT_STARTED	4		/* opened & irqs enabled */
+
+	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
+	unsigned int		curmode;	/* current phy mode */
+	struct ieee80211_channel *curchan;	/* current h/w channel */
+
+	struct ieee80211_vif *vif;
+
+	enum ath5k_int		imask;		/* interrupt mask copy */
+
+	DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */
+
+	u8			bssidmask[ETH_ALEN];
+
+	unsigned int		led_pin,	/* GPIO pin for driving LED */
+				led_on;		/* pin setting for LED on */
+
+	struct tasklet_struct	restq;		/* reset tasklet */
+
+	unsigned int		rxbufsize;	/* rx size based on mtu */
+	struct list_head	rxbuf;		/* receive buffer */
+	spinlock_t		rxbuflock;
+	u32			*rxlink;	/* link ptr in last RX desc */
+	struct tasklet_struct	rxtq;		/* rx intr tasklet */
+	struct ath5k_led	rx_led;		/* rx led */
+
+	struct list_head	txbuf;		/* transmit buffer */
+	spinlock_t		txbuflock;
+	unsigned int		txbuf_len;	/* buf count in txbuf list */
+	struct ath5k_txq	txqs[2];	/* beacon and tx */
+
+	struct ath5k_txq	*txq;		/* beacon and tx*/
+	struct tasklet_struct	txtq;		/* tx intr tasklet */
+	struct ath5k_led	tx_led;		/* tx led */
+
+	struct ath5k_rfkill	rf_kill;
+
+	spinlock_t		block;		/* protects beacon */
+	struct tasklet_struct	beacontq;	/* beacon intr tasklet */
+	struct ath5k_buf	*bbuf;		/* beacon buffer */
+	unsigned int		bhalq,		/* SW q for outgoing beacons */
+				bmisscount,	/* missed beacon transmits */
+				bintval,	/* beacon interval in TU */
+				bsent;
+	unsigned int		nexttbtt;	/* next beacon time in TU */
+
+	struct timer_list	calib_tim;	/* calibration timer */
+	int 			power_level;	/* Requested tx power in dbm */
+	bool			assoc;		/* assocate state */
+};
+
+#define ath5k_hw_hasbssidmask(_ah) \
+	(ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
+#define ath5k_hw_hasveol(_ah) \
+	(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/caps.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/caps.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/caps.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/caps.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/**************\
+* Capabilities *
+\**************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Fill the capabilities struct
+ * TODO: Merge this with EEPROM code when we are done with it
+ */
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
+{
+	u16 ee_header;
+
+	ATH5K_TRACE(ah->ah_sc);
+	/* Capabilities stored in the EEPROM */
+	ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
+
+	if (ah->ah_version == AR5K_AR5210) {
+		/*
+		 * Set radio capabilities
+		 * (The AR5110 only supports the middle 5GHz band)
+		 */
+		ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
+		ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
+		ah->ah_capabilities.cap_range.range_2ghz_min = 0;
+		ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+
+		/* Set supported modes */
+		__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
+		__set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
+	} else {
+		/*
+		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
+		 * XXX and from 2312 to 2732GHz. There are problems with the
+		 * XXX current ieee80211 implementation because the IEEE
+		 * XXX channel mapping does not support negative channel
+		 * XXX numbers (2312MHz is channel -19). Of course, this
+		 * XXX doesn't matter because these channels are out of range
+		 * XXX but some regulation domains like MKK (Japan) will
+		 * XXX support frequencies somewhere around 4.8GHz.
+		 */
+
+		/*
+		 * Set radio capabilities
+		 */
+
+		if (AR5K_EEPROM_HDR_11A(ee_header)) {
+			/* 4920 */
+			ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
+			ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+
+			/* Set supported modes */
+			__set_bit(AR5K_MODE_11A,
+					ah->ah_capabilities.cap_mode);
+			__set_bit(AR5K_MODE_11A_TURBO,
+					ah->ah_capabilities.cap_mode);
+			if (ah->ah_version == AR5K_AR5212)
+				__set_bit(AR5K_MODE_11G_TURBO,
+						ah->ah_capabilities.cap_mode);
+		}
+
+		/* Enable  802.11b if a 2GHz capable radio (2111/5112) is
+		 * connected */
+		if (AR5K_EEPROM_HDR_11B(ee_header) ||
+		    (AR5K_EEPROM_HDR_11G(ee_header) &&
+		     ah->ah_version != AR5K_AR5211)) {
+			/* 2312 */
+			ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
+			ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+
+			if (AR5K_EEPROM_HDR_11B(ee_header))
+				__set_bit(AR5K_MODE_11B,
+						ah->ah_capabilities.cap_mode);
+
+			if (AR5K_EEPROM_HDR_11G(ee_header) &&
+			    ah->ah_version != AR5K_AR5211)
+				__set_bit(AR5K_MODE_11G,
+						ah->ah_capabilities.cap_mode);
+		}
+	}
+
+	/* GPIO */
+	ah->ah_gpio_npins = AR5K_NUM_GPIO;
+
+	/* Set number of supported TX queues */
+	if (ah->ah_version == AR5K_AR5210)
+		ah->ah_capabilities.cap_queues.q_tx_num =
+			AR5K_NUM_TX_QUEUES_NOQCU;
+	else
+		ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
+
+	return 0;
+}
+
+/* Main function used by the driver part to check caps */
+int ath5k_hw_get_capability(struct ath5k_hw *ah,
+		enum ath5k_capability_type cap_type,
+		u32 capability, u32 *result)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	switch (cap_type) {
+	case AR5K_CAP_NUM_TXQUEUES:
+		if (result) {
+			if (ah->ah_version == AR5K_AR5210)
+				*result = AR5K_NUM_TX_QUEUES_NOQCU;
+			else
+				*result = AR5K_NUM_TX_QUEUES;
+			goto yes;
+		}
+	case AR5K_CAP_VEOL:
+		goto yes;
+	case AR5K_CAP_COMPRESSION:
+		if (ah->ah_version == AR5K_AR5212)
+			goto yes;
+		else
+			goto no;
+	case AR5K_CAP_BURST:
+		goto yes;
+	case AR5K_CAP_TPC:
+		goto yes;
+	case AR5K_CAP_BSSIDMASK:
+		if (ah->ah_version == AR5K_AR5212)
+			goto yes;
+		else
+			goto no;
+	case AR5K_CAP_XR:
+		if (ah->ah_version == AR5K_AR5212)
+			goto yes;
+		else
+			goto no;
+	default:
+		goto no;
+	}
+
+no:
+	return -EINVAL;
+yes:
+	return 0;
+}
+
+/*
+ * TODO: Following functions should be part of a new function
+ * set_capability
+ */
+
+int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
+		u16 assoc_id)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	if (ah->ah_version == AR5K_AR5210) {
+		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
+		return 0;
+	}
+
+	return -EIO;
+}
+
+int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	if (ah->ah_version == AR5K_AR5210) {
+		AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
+			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
+		return 0;
+	}
+
+	return -EIO;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/debug.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/debug.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com>
+ *
+ *  This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include "base.h"
+#include "debug.h"
+
+static unsigned int ath5k_debug;
+module_param_named(debug, ath5k_debug, uint, 0);
+
+
+#ifdef CONFIG_ATH5K_DEBUG
+
+#include <linux/seq_file.h>
+#include "reg.h"
+
+static struct dentry *ath5k_global_debugfs;
+
+static int ath5k_debugfs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+
+/* debugfs: registers */
+
+struct reg {
+	const char *name;
+	int addr;
+};
+
+#define REG_STRUCT_INIT(r) { #r, r }
+
+/* just a few random registers, might want to add more */
+static const struct reg regs[] = {
+	REG_STRUCT_INIT(AR5K_CR),
+	REG_STRUCT_INIT(AR5K_RXDP),
+	REG_STRUCT_INIT(AR5K_CFG),
+	REG_STRUCT_INIT(AR5K_IER),
+	REG_STRUCT_INIT(AR5K_BCR),
+	REG_STRUCT_INIT(AR5K_RTSD0),
+	REG_STRUCT_INIT(AR5K_RTSD1),
+	REG_STRUCT_INIT(AR5K_TXCFG),
+	REG_STRUCT_INIT(AR5K_RXCFG),
+	REG_STRUCT_INIT(AR5K_RXJLA),
+	REG_STRUCT_INIT(AR5K_MIBC),
+	REG_STRUCT_INIT(AR5K_TOPS),
+	REG_STRUCT_INIT(AR5K_RXNOFRM),
+	REG_STRUCT_INIT(AR5K_TXNOFRM),
+	REG_STRUCT_INIT(AR5K_RPGTO),
+	REG_STRUCT_INIT(AR5K_RFCNT),
+	REG_STRUCT_INIT(AR5K_MISC),
+	REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
+	REG_STRUCT_INIT(AR5K_ISR),
+	REG_STRUCT_INIT(AR5K_PISR),
+	REG_STRUCT_INIT(AR5K_SISR0),
+	REG_STRUCT_INIT(AR5K_SISR1),
+	REG_STRUCT_INIT(AR5K_SISR2),
+	REG_STRUCT_INIT(AR5K_SISR3),
+	REG_STRUCT_INIT(AR5K_SISR4),
+	REG_STRUCT_INIT(AR5K_IMR),
+	REG_STRUCT_INIT(AR5K_PIMR),
+	REG_STRUCT_INIT(AR5K_SIMR0),
+	REG_STRUCT_INIT(AR5K_SIMR1),
+	REG_STRUCT_INIT(AR5K_SIMR2),
+	REG_STRUCT_INIT(AR5K_SIMR3),
+	REG_STRUCT_INIT(AR5K_SIMR4),
+	REG_STRUCT_INIT(AR5K_DCM_ADDR),
+	REG_STRUCT_INIT(AR5K_DCCFG),
+	REG_STRUCT_INIT(AR5K_CCFG),
+	REG_STRUCT_INIT(AR5K_CPC0),
+	REG_STRUCT_INIT(AR5K_CPC1),
+	REG_STRUCT_INIT(AR5K_CPC2),
+	REG_STRUCT_INIT(AR5K_CPC3),
+	REG_STRUCT_INIT(AR5K_CPCOVF),
+	REG_STRUCT_INIT(AR5K_RESET_CTL),
+	REG_STRUCT_INIT(AR5K_SLEEP_CTL),
+	REG_STRUCT_INIT(AR5K_INTPEND),
+	REG_STRUCT_INIT(AR5K_SFR),
+	REG_STRUCT_INIT(AR5K_PCICFG),
+	REG_STRUCT_INIT(AR5K_GPIOCR),
+	REG_STRUCT_INIT(AR5K_GPIODO),
+	REG_STRUCT_INIT(AR5K_SREV),
+};
+
+static void *reg_start(struct seq_file *seq, loff_t *pos)
+{
+	return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
+}
+
+static void reg_stop(struct seq_file *seq, void *p)
+{
+	/* nothing to do */
+}
+
+static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
+{
+	++*pos;
+	return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
+}
+
+static int reg_show(struct seq_file *seq, void *p)
+{
+	struct ath5k_softc *sc = seq->private;
+	struct reg *r = p;
+	seq_printf(seq, "%-25s0x%08x\n", r->name,
+		ath5k_hw_reg_read(sc->ah, r->addr));
+	return 0;
+}
+
+static const struct seq_operations register_seq_ops = {
+	.start = reg_start,
+	.next  = reg_next,
+	.stop  = reg_stop,
+	.show  = reg_show
+};
+
+static int open_file_registers(struct inode *inode, struct file *file)
+{
+	struct seq_file *s;
+	int res;
+	res = seq_open(file, &register_seq_ops);
+	if (res == 0) {
+		s = file->private_data;
+		s->private = inode->i_private;
+	}
+	return res;
+}
+
+static const struct file_operations fops_registers = {
+	.open = open_file_registers,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+	.owner = THIS_MODULE,
+};
+
+
+/* debugfs: beacons */
+
+static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = sc->ah;
+	char buf[500];
+	unsigned int len = 0;
+	unsigned int v;
+	u64 tsf;
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
+		"AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
+		(v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
+
+	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
+		"AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
+
+	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
+		"AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
+	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+		"AR5K_TIMER0 (TBTT)", v, v);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
+	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+		"AR5K_TIMER1 (DMA)", v, v >> 3);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
+	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+		"AR5K_TIMER2 (SWBA)", v, v >> 3);
+
+	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
+	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+		"AR5K_TIMER3 (ATIM)", v, v);
+
+	tsf = ath5k_hw_get_tsf64(sc->ah);
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"TSF\t\t0x%016llx\tTU: %08x\n",
+		(unsigned long long)tsf, TSF_TO_TU(tsf));
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_beacon(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	struct ath5k_hw *ah = sc->ah;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	if (strncmp(buf, "disable", 7) == 0) {
+		AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
+		printk(KERN_INFO "debugfs disable beacons\n");
+	} else if (strncmp(buf, "enable", 6) == 0) {
+		AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
+		printk(KERN_INFO "debugfs enable beacons\n");
+	}
+	return count;
+}
+
+static const struct file_operations fops_beacon = {
+	.read = read_file_beacon,
+	.write = write_file_beacon,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
+};
+
+
+/* debugfs: reset */
+
+static ssize_t write_file_reset(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	tasklet_schedule(&sc->restq);
+	return count;
+}
+
+static const struct file_operations fops_reset = {
+	.write = write_file_reset,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
+};
+
+
+/* debugfs: debug level */
+
+static const struct {
+	enum ath5k_debug_level level;
+	const char *name;
+	const char *desc;
+} dbg_info[] = {
+	{ ATH5K_DEBUG_RESET,	"reset",	"reset and initialization" },
+	{ ATH5K_DEBUG_INTR,	"intr",		"interrupt handling" },
+	{ ATH5K_DEBUG_MODE,	"mode",		"mode init/setup" },
+	{ ATH5K_DEBUG_XMIT,	"xmit",		"basic xmit operation" },
+	{ ATH5K_DEBUG_BEACON,	"beacon",	"beacon handling" },
+	{ ATH5K_DEBUG_CALIBRATE, "calib",	"periodic calibration" },
+	{ ATH5K_DEBUG_TXPOWER,	"txpower",	"transmit power setting" },
+	{ ATH5K_DEBUG_LED,	"led",		"LED management" },
+	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
+	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
+	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
+	{ ATH5K_DEBUG_TRACE,	"trace",	"trace function calls" },
+	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
+};
+
+static ssize_t read_file_debug(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	char buf[700];
+	unsigned int len = 0;
+	unsigned int i;
+
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
+
+	for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
+		len += snprintf(buf+len, sizeof(buf)-len,
+			"%10s %c 0x%08x - %s\n", dbg_info[i].name,
+			sc->debug.level & dbg_info[i].level ? '+' : ' ',
+			dbg_info[i].level, dbg_info[i].desc);
+	}
+	len += snprintf(buf+len, sizeof(buf)-len,
+		"%10s %c 0x%08x - %s\n", dbg_info[i].name,
+		sc->debug.level == dbg_info[i].level ? '+' : ' ',
+		dbg_info[i].level, dbg_info[i].desc);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_debug(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_softc *sc = file->private_data;
+	unsigned int i;
+	char buf[20];
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
+		if (strncmp(buf, dbg_info[i].name,
+					strlen(dbg_info[i].name)) == 0) {
+			sc->debug.level ^= dbg_info[i].level; /* toggle bit */
+			break;
+		}
+	}
+	return count;
+}
+
+static const struct file_operations fops_debug = {
+	.read = read_file_debug,
+	.write = write_file_debug,
+	.open = ath5k_debugfs_open,
+	.owner = THIS_MODULE,
+};
+
+
+/* init */
+
+void
+ath5k_debug_init(void)
+{
+	ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
+}
+
+void
+ath5k_debug_init_device(struct ath5k_softc *sc)
+{
+	sc->debug.level = ath5k_debug;
+
+	sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
+				ath5k_global_debugfs);
+
+	sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO,
+				sc->debug.debugfs_phydir, sc, &fops_debug);
+
+	sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
+				sc->debug.debugfs_phydir, sc, &fops_registers);
+
+	sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
+				sc->debug.debugfs_phydir, sc, &fops_beacon);
+
+	sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
+				sc->debug.debugfs_phydir, sc, &fops_reset);
+}
+
+void
+ath5k_debug_finish(void)
+{
+	debugfs_remove(ath5k_global_debugfs);
+}
+
+void
+ath5k_debug_finish_device(struct ath5k_softc *sc)
+{
+	debugfs_remove(sc->debug.debugfs_debug);
+	debugfs_remove(sc->debug.debugfs_registers);
+	debugfs_remove(sc->debug.debugfs_beacon);
+	debugfs_remove(sc->debug.debugfs_reset);
+	debugfs_remove(sc->debug.debugfs_phydir);
+}
+
+
+/* functions used in other places */
+
+void
+ath5k_debug_dump_bands(struct ath5k_softc *sc)
+{
+	unsigned int b, i;
+
+	if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
+		return;
+
+	BUG_ON(!sc->sbands);
+
+	for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
+		struct ieee80211_supported_band *band = &sc->sbands[b];
+		char bname[6];
+		switch (band->band) {
+		case IEEE80211_BAND_2GHZ:
+			strcpy(bname, "2 GHz");
+			break;
+		case IEEE80211_BAND_5GHZ:
+			strcpy(bname, "5 GHz");
+			break;
+		default:
+			printk(KERN_DEBUG "Band not supported: %d\n",
+				band->band);
+			return;
+		}
+		printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
+				band->n_channels, band->n_bitrates);
+		printk(KERN_DEBUG " channels:\n");
+		for (i = 0; i < band->n_channels; i++)
+			printk(KERN_DEBUG "  %3d %d %.4x %.4x\n",
+					ieee80211_frequency_to_channel(
+						band->channels[i].center_freq),
+					band->channels[i].center_freq,
+					band->channels[i].hw_value,
+					band->channels[i].flags);
+		printk(KERN_DEBUG " rates:\n");
+		for (i = 0; i < band->n_bitrates; i++)
+			printk(KERN_DEBUG "  %4d %.4x %.4x %.4x\n",
+					band->bitrates[i].bitrate,
+					band->bitrates[i].hw_value,
+					band->bitrates[i].flags,
+					band->bitrates[i].hw_value_short);
+	}
+}
+
+static inline void
+ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
+		       struct ath5k_rx_status *rs)
+{
+	struct ath5k_desc *ds = bf->desc;
+	struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
+
+	printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
+		ds, (unsigned long long)bf->daddr,
+		ds->ds_link, ds->ds_data,
+		rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
+		rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
+		!done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
+}
+
+void
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+{
+	struct ath5k_desc *ds;
+	struct ath5k_buf *bf;
+	struct ath5k_rx_status rs = {};
+	int status;
+
+	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+		return;
+
+	printk(KERN_DEBUG "rx queue %x, link %p\n",
+		ath5k_hw_get_rxdp(ah), sc->rxlink);
+
+	spin_lock_bh(&sc->rxbuflock);
+	list_for_each_entry(bf, &sc->rxbuf, list) {
+		ds = bf->desc;
+		status = ah->ah_proc_rx_desc(ah, ds, &rs);
+		if (!status)
+			ath5k_debug_printrxbuf(bf, status == 0, &rs);
+	}
+	spin_unlock_bh(&sc->rxbuflock);
+}
+
+void
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
+			struct sk_buff *skb, const char *prefix, int tx)
+{
+	char buf[16];
+
+	if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) ||
+		     (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX)))))
+		return;
+
+	snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix);
+
+	print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data,
+		min(200U, skb->len));
+
+	printk(KERN_DEBUG "\n");
+}
+
+void
+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+	struct ath5k_desc *ds = bf->desc;
+	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
+	struct ath5k_tx_status ts = {};
+	int done;
+
+	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+		return;
+
+	done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
+
+	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
+		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
+		ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
+		td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
+		td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
+		done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
+}
+
+#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/debug.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/debug.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/debug.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/debug.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
+ *
+ *  This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#ifndef _ATH5K_DEBUG_H
+#define _ATH5K_DEBUG_H
+
+struct ath5k_softc;
+struct ath5k_hw;
+struct sk_buff;
+struct ath5k_buf;
+
+struct ath5k_dbg_info {
+	unsigned int		level;		/* debug level */
+	/* debugfs entries */
+	struct dentry		*debugfs_phydir;
+	struct dentry		*debugfs_debug;
+	struct dentry		*debugfs_registers;
+	struct dentry		*debugfs_beacon;
+	struct dentry		*debugfs_reset;
+};
+
+/**
+ * enum ath5k_debug_level - ath5k debug level
+ *
+ * @ATH5K_DEBUG_RESET: reset processing
+ * @ATH5K_DEBUG_INTR: interrupt handling
+ * @ATH5K_DEBUG_MODE: mode init/setup
+ * @ATH5K_DEBUG_XMIT: basic xmit operation
+ * @ATH5K_DEBUG_BEACON: beacon handling
+ * @ATH5K_DEBUG_CALIBRATE: periodic calibration
+ * @ATH5K_DEBUG_TXPOWER: transmit power setting
+ * @ATH5K_DEBUG_LED: led management
+ * @ATH5K_DEBUG_DUMP_RX: print received skb content
+ * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
+ * @ATH5K_DEBUG_DUMPBANDS: dump bands
+ * @ATH5K_DEBUG_TRACE: trace function calls
+ * @ATH5K_DEBUG_ANY: show at any debug level
+ *
+ * The debug level is used to control the amount and type of debugging output
+ * we want to see. The debug level is given in calls to ATH5K_DBG to specify
+ * where the message should appear, and the user can control the debugging
+ * messages he wants to see, either by the module parameter 'debug' on module
+ * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can
+ * be combined together by bitwise OR.
+ */
+enum ath5k_debug_level {
+	ATH5K_DEBUG_RESET	= 0x00000001,
+	ATH5K_DEBUG_INTR	= 0x00000002,
+	ATH5K_DEBUG_MODE	= 0x00000004,
+	ATH5K_DEBUG_XMIT	= 0x00000008,
+	ATH5K_DEBUG_BEACON	= 0x00000010,
+	ATH5K_DEBUG_CALIBRATE	= 0x00000020,
+	ATH5K_DEBUG_TXPOWER	= 0x00000040,
+	ATH5K_DEBUG_LED		= 0x00000080,
+	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
+	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
+	ATH5K_DEBUG_DUMPBANDS	= 0x00000400,
+	ATH5K_DEBUG_TRACE	= 0x00001000,
+	ATH5K_DEBUG_ANY		= 0xffffffff
+};
+
+#ifdef CONFIG_ATH5K_DEBUG
+
+#define ATH5K_TRACE(_sc) do { \
+	if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
+		printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \
+	} while (0)
+
+#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \
+	if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \
+		ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
+			__func__, __LINE__, ##__VA_ARGS__); \
+	} while (0)
+
+#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \
+	if (unlikely((_sc)->debug.level & (_m))) \
+		ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
+			__func__, __LINE__, ##__VA_ARGS__); \
+	} while (0)
+
+void
+ath5k_debug_init(void);
+
+void
+ath5k_debug_init_device(struct ath5k_softc *sc);
+
+void
+ath5k_debug_finish(void);
+
+void
+ath5k_debug_finish_device(struct ath5k_softc *sc);
+
+void
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+
+void
+ath5k_debug_dump_bands(struct ath5k_softc *sc);
+
+void
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
+			struct sk_buff *skb, const char *prefix, int tx);
+
+void
+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
+
+#else /* no debugging */
+
+#include <linux/compiler.h>
+
+#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
+
+static inline void __attribute__ ((format (printf, 3, 4)))
+ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
+
+static inline void __attribute__ ((format (printf, 3, 4)))
+ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
+{}
+
+static inline void
+ath5k_debug_init(void) {}
+
+static inline void
+ath5k_debug_init_device(struct ath5k_softc *sc) {}
+
+static inline void
+ath5k_debug_finish(void) {}
+
+static inline void
+ath5k_debug_finish_device(struct ath5k_softc *sc) {}
+
+static inline void
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+
+static inline void
+ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
+
+static inline void
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
+			struct sk_buff *skb, const char *prefix, int tx) {}
+
+static inline void
+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
+
+#endif /* ifdef CONFIG_ATH5K_DEBUG */
+
+#endif /* ifndef _ATH5K_DEBUG_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/desc.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/desc.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/desc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/desc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,696 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/******************************\
+ Hardware Descriptor Functions
+\******************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * TX Descriptors
+ */
+
+/*
+ * Initialize the 2-word tx control descriptor on 5210/5211
+ */
+static int
+ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+	unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
+	unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
+	unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
+	unsigned int rtscts_rate, unsigned int rtscts_duration)
+{
+	u32 frame_type;
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
+	unsigned int frame_len;
+
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+
+	/*
+	 * Validate input
+	 * - Zero retries don't make sense.
+	 * - A zero rate will put the HW into a mode where it continously sends
+	 *   noise on the channel, so it is important to avoid this.
+	 */
+	if (unlikely(tx_tries0 == 0)) {
+		ATH5K_ERR(ah->ah_sc, "zero retries\n");
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	if (unlikely(tx_rate0 == 0)) {
+		ATH5K_ERR(ah->ah_sc, "zero rate\n");
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/* Clear descriptor */
+	memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
+
+	/* Setup control descriptor */
+
+	/* Verify and set frame length */
+
+	/* remove padding we might have added before */
+	frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
+
+	if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
+		return -EINVAL;
+
+	tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+
+	/* Verify and set buffer length */
+
+	/* NB: beacon's BufLen must be a multiple of 4 bytes */
+	if (type == AR5K_PKT_TYPE_BEACON)
+		pkt_len = roundup(pkt_len, 4);
+
+	if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
+		return -EINVAL;
+
+	tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+
+	/*
+	 * Verify and set header length
+	 * XXX: I only found that on 5210 code, does it work on 5211 ?
+	 */
+	if (ah->ah_version == AR5K_AR5210) {
+		if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
+			return -EINVAL;
+		tx_ctl->tx_control_0 |=
+			AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
+	}
+
+	/*Diferences between 5210-5211*/
+	if (ah->ah_version == AR5K_AR5210) {
+		switch (type) {
+		case AR5K_PKT_TYPE_BEACON:
+		case AR5K_PKT_TYPE_PROBE_RESP:
+			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
+		case AR5K_PKT_TYPE_PIFS:
+			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
+		default:
+			frame_type = type /*<< 2 ?*/;
+		}
+
+		tx_ctl->tx_control_0 |=
+		AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
+		AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+
+	} else {
+		tx_ctl->tx_control_0 |=
+			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
+			AR5K_REG_SM(antenna_mode,
+				AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
+		tx_ctl->tx_control_1 |=
+			AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
+	}
+#define _TX_FLAGS(_c, _flag)					\
+	if (flags & AR5K_TXDESC_##_flag) {			\
+		tx_ctl->tx_control_##_c |=			\
+			AR5K_2W_TX_DESC_CTL##_c##_##_flag;	\
+	}
+
+	_TX_FLAGS(0, CLRDMASK);
+	_TX_FLAGS(0, VEOL);
+	_TX_FLAGS(0, INTREQ);
+	_TX_FLAGS(0, RTSENA);
+	_TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+	/*
+	 * WEP crap
+	 */
+	if (key_index != AR5K_TXKEYIX_INVALID) {
+		tx_ctl->tx_control_0 |=
+			AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+		tx_ctl->tx_control_1 |=
+			AR5K_REG_SM(key_index,
+			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+	}
+
+	/*
+	 * RTS/CTS Duration [5210 ?]
+	 */
+	if ((ah->ah_version == AR5K_AR5210) &&
+			(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
+		tx_ctl->tx_control_1 |= rtscts_duration &
+				AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
+
+	return 0;
+}
+
+/*
+ * Initialize the 4-word tx control descriptor on 5212
+ */
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+	struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
+	enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
+	unsigned int tx_tries0, unsigned int key_index,
+	unsigned int antenna_mode, unsigned int flags,
+	unsigned int rtscts_rate,
+	unsigned int rtscts_duration)
+{
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
+	unsigned int frame_len;
+
+	ATH5K_TRACE(ah->ah_sc);
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+	/*
+	 * Validate input
+	 * - Zero retries don't make sense.
+	 * - A zero rate will put the HW into a mode where it continously sends
+	 *   noise on the channel, so it is important to avoid this.
+	 */
+	if (unlikely(tx_tries0 == 0)) {
+		ATH5K_ERR(ah->ah_sc, "zero retries\n");
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	if (unlikely(tx_rate0 == 0)) {
+		ATH5K_ERR(ah->ah_sc, "zero rate\n");
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	tx_power += ah->ah_txpower.txp_offset;
+	if (tx_power > AR5K_TUNE_MAX_TXPOWER)
+		tx_power = AR5K_TUNE_MAX_TXPOWER;
+
+	/* Clear descriptor */
+	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
+
+	/* Setup control descriptor */
+
+	/* Verify and set frame length */
+
+	/* remove padding we might have added before */
+	frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
+
+	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+		return -EINVAL;
+
+	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+
+	/* Verify and set buffer length */
+
+	/* NB: beacon's BufLen must be a multiple of 4 bytes */
+	if (type == AR5K_PKT_TYPE_BEACON)
+		pkt_len = roundup(pkt_len, 4);
+
+	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+		return -EINVAL;
+
+	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+
+	tx_ctl->tx_control_0 |=
+		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+	tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
+					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+#define _TX_FLAGS(_c, _flag)					\
+	if (flags & AR5K_TXDESC_##_flag) {			\
+		tx_ctl->tx_control_##_c |=			\
+			AR5K_4W_TX_DESC_CTL##_c##_##_flag;	\
+	}
+
+	_TX_FLAGS(0, CLRDMASK);
+	_TX_FLAGS(0, VEOL);
+	_TX_FLAGS(0, INTREQ);
+	_TX_FLAGS(0, RTSENA);
+	_TX_FLAGS(0, CTSENA);
+	_TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+	/*
+	 * WEP crap
+	 */
+	if (key_index != AR5K_TXKEYIX_INVALID) {
+		tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+		tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
+				AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+	}
+
+	/*
+	 * RTS/CTS
+	 */
+	if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
+		if ((flags & AR5K_TXDESC_RTSENA) &&
+				(flags & AR5K_TXDESC_CTSENA))
+			return -EINVAL;
+		tx_ctl->tx_control_2 |= rtscts_duration &
+				AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+	}
+
+	return 0;
+}
+
+/*
+ * Initialize a 4-word multi rate retry tx control descriptor on 5212
+ */
+static int
+ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
+	u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
+{
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
+
+	/*
+	 * Rates can be 0 as long as the retry count is 0 too.
+	 * A zero rate and nonzero retry count will put the HW into a mode where
+	 * it continously sends noise on the channel, so it is important to
+	 * avoid this.
+	 */
+	if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
+		     (tx_rate2 == 0 && tx_tries2 != 0) ||
+		     (tx_rate3 == 0 && tx_tries3 != 0))) {
+		ATH5K_ERR(ah->ah_sc, "zero rate\n");
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	if (ah->ah_version == AR5K_AR5212) {
+		tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+#define _XTX_TRIES(_n)							\
+	if (tx_tries##_n) {						\
+		tx_ctl->tx_control_2 |=					\
+		    AR5K_REG_SM(tx_tries##_n,				\
+		    AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n);		\
+		tx_ctl->tx_control_3 |=					\
+		    AR5K_REG_SM(tx_rate##_n,				\
+		    AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n);		\
+	}
+
+		_XTX_TRIES(1);
+		_XTX_TRIES(2);
+		_XTX_TRIES(3);
+
+#undef _XTX_TRIES
+
+		return 1;
+	}
+
+	return 0;
+}
+
+/* no mrr support for cards older than 5212 */
+static int
+ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc,
+	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
+	u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
+{
+	return 0;
+}
+
+/*
+ * Proccess the tx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
+	struct ath5k_hw_tx_status *tx_status;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+	tx_status = &desc->ud.ds_tx5210.tx_stat;
+
+	/* No frame has been send or error */
+	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+		return -EINPROGRESS;
+
+	/*
+	 * Get descriptor status
+	 */
+	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+	/*TODO: ts->ts_virtcol + test*/
+	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+		AR5K_DESC_TX_STATUS1_SEQ_NUM);
+	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+	ts->ts_antenna = 1;
+	ts->ts_status = 0;
+	ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
+		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+	ts->ts_retry[0] = ts->ts_longretry;
+	ts->ts_final_idx = 0;
+
+	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+		if (tx_status->tx_status_0 &
+				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+			ts->ts_status |= AR5K_TXERR_XRETRY;
+
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+			ts->ts_status |= AR5K_TXERR_FIFO;
+
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+			ts->ts_status |= AR5K_TXERR_FILT;
+	}
+
+	return 0;
+}
+
+/*
+ * Proccess a tx status descriptor on 5212
+ */
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+{
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
+	struct ath5k_hw_tx_status *tx_status;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+	tx_status = &desc->ud.ds_tx5212.tx_stat;
+
+	/* No frame has been send or error */
+	if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
+		return -EINPROGRESS;
+
+	/*
+	 * Get descriptor status
+	 */
+	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+		AR5K_DESC_TX_STATUS1_SEQ_NUM);
+	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+	ts->ts_antenna = (tx_status->tx_status_1 &
+		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
+	ts->ts_status = 0;
+
+	ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
+			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
+
+	/* The longretry counter has the number of un-acked retries
+	 * for the final rate. To get the total number of retries
+	 * we have to add the retry counters for the other rates
+	 * as well
+	 */
+	ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
+	switch (ts->ts_final_idx) {
+	case 3:
+		ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
+			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
+
+		ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
+			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+		ts->ts_longretry += ts->ts_retry[2];
+		/* fall through */
+	case 2:
+		ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
+			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
+
+		ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
+			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+		ts->ts_longretry += ts->ts_retry[1];
+		/* fall through */
+	case 1:
+		ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
+			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
+
+		ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
+			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+		ts->ts_longretry += ts->ts_retry[0];
+		/* fall through */
+	case 0:
+		ts->ts_rate[0] = tx_ctl->tx_control_3 &
+			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+		break;
+	}
+
+	/* TX error */
+	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+		if (tx_status->tx_status_0 &
+				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+			ts->ts_status |= AR5K_TXERR_XRETRY;
+
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+			ts->ts_status |= AR5K_TXERR_FIFO;
+
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+			ts->ts_status |= AR5K_TXERR_FILT;
+	}
+
+	return 0;
+}
+
+/*
+ * RX Descriptors
+ */
+
+/*
+ * Initialize an rx control descriptor
+ */
+static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+			u32 size, unsigned int flags)
+{
+	struct ath5k_hw_rx_ctl *rx_ctl;
+
+	ATH5K_TRACE(ah->ah_sc);
+	rx_ctl = &desc->ud.ds_rx.rx_ctl;
+
+	/*
+	 * Clear the descriptor
+	 * If we don't clean the status descriptor,
+	 * while scanning we get too many results,
+	 * most of them virtual, after some secs
+	 * of scanning system hangs. M.F.
+	*/
+	memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
+
+	/* Setup descriptor */
+	rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+	if (unlikely(rx_ctl->rx_control_1 != size))
+		return -EINVAL;
+
+	if (flags & AR5K_RXDESC_INTREQ)
+		rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+
+	return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
+		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+	struct ath5k_hw_rx_status *rx_status;
+
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+	/* No frame received / not ready */
+	if (unlikely(!(rx_status->rx_status_1 &
+	AR5K_5210_RX_DESC_STATUS1_DONE)))
+		return -EINPROGRESS;
+
+	/*
+	 * Frame receive status
+	 */
+	rs->rs_datalen = rx_status->rx_status_0 &
+		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
+	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
+	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+	rs->rs_more = !!(rx_status->rx_status_0 &
+		AR5K_5210_RX_DESC_STATUS0_MORE);
+	/* TODO: this timestamp is 13 bit, later on we assume 15 bit */
+	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+	rs->rs_status = 0;
+	rs->rs_phyerr = 0;
+
+	/*
+	 * Key table status
+	 */
+	if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
+		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+			AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
+	else
+		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+	/*
+	 * Receive/descriptor errors
+	 */
+	if (!(rx_status->rx_status_1 &
+	AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+		if (rx_status->rx_status_1 &
+				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
+			rs->rs_status |= AR5K_RXERR_CRC;
+
+		if (rx_status->rx_status_1 &
+				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
+			rs->rs_status |= AR5K_RXERR_FIFO;
+
+		if (rx_status->rx_status_1 &
+				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
+			rs->rs_status |= AR5K_RXERR_PHY;
+			rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
+				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
+		}
+
+		if (rx_status->rx_status_1 &
+				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+			rs->rs_status |= AR5K_RXERR_DECRYPT;
+	}
+
+	return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5212
+ */
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
+		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+{
+	struct ath5k_hw_rx_status *rx_status;
+	struct ath5k_hw_rx_error *rx_err;
+
+	ATH5K_TRACE(ah->ah_sc);
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+	/* Overlay on error */
+	rx_err = &desc->ud.ds_rx.u.rx_err;
+
+	/* No frame received / not ready */
+	if (unlikely(!(rx_status->rx_status_1 &
+	AR5K_5212_RX_DESC_STATUS1_DONE)))
+		return -EINPROGRESS;
+
+	/*
+	 * Frame receive status
+	 */
+	rs->rs_datalen = rx_status->rx_status_0 &
+		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
+	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
+	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+	rs->rs_more = !!(rx_status->rx_status_0 &
+		AR5K_5212_RX_DESC_STATUS0_MORE);
+	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+	rs->rs_status = 0;
+	rs->rs_phyerr = 0;
+
+	/*
+	 * Key table status
+	 */
+	if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
+		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+				AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
+	else
+		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+	/*
+	 * Receive/descriptor errors
+	 */
+	if (!(rx_status->rx_status_1 &
+	AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
+			rs->rs_status |= AR5K_RXERR_CRC;
+
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
+			rs->rs_status |= AR5K_RXERR_PHY;
+			rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
+					   AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+		}
+
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+			rs->rs_status |= AR5K_RXERR_DECRYPT;
+
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
+			rs->rs_status |= AR5K_RXERR_MIC;
+	}
+
+	return 0;
+}
+
+/*
+ * Init function pointers inside ath5k_hw struct
+ */
+int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
+{
+
+	if (ah->ah_version != AR5K_AR5210 &&
+		ah->ah_version != AR5K_AR5211 &&
+		ah->ah_version != AR5K_AR5212)
+			return -ENOTSUPP;
+
+	/* XXX: What is this magic value and where is it used ? */
+	if (ah->ah_version == AR5K_AR5212)
+		ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
+	else if (ah->ah_version == AR5K_AR5211)
+		ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
+
+	if (ah->ah_version == AR5K_AR5212) {
+		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+		ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
+		ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
+		ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
+	} else {
+		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
+		ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
+		ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr;
+		ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
+	}
+
+	if (ah->ah_version == AR5K_AR5212)
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
+	else if (ah->ah_version <= AR5K_AR5211)
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/desc.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/desc.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/desc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/desc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Internal RX/TX descriptor structures
+ * (rX: reserved fields possibily used by future versions of the ar5k chipset)
+ */
+
+/*
+ * common hardware RX control descriptor
+ */
+struct ath5k_hw_rx_ctl {
+	u32	rx_control_0; /* RX control word 0 */
+	u32	rx_control_1; /* RX control word 1 */
+} __packed;
+
+/* RX control word 0 field/sflags */
+#define AR5K_DESC_RX_CTL0			0x00000000
+
+/* RX control word 1 fields/flags */
+#define AR5K_DESC_RX_CTL1_BUF_LEN		0x00000fff
+#define AR5K_DESC_RX_CTL1_INTREQ		0x00002000
+
+/*
+ * common hardware RX status descriptor
+ * 5210/11 and 5212 differ only in the flags defined below
+ */
+struct ath5k_hw_rx_status {
+	u32	rx_status_0; /* RX status word 0 */
+	u32	rx_status_1; /* RX status word 1 */
+} __packed;
+
+/* 5210/5211 */
+/* RX status word 0 fields/flags */
+#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+#define AR5K_5210_RX_DESC_STATUS0_MORE			0x00001000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S	15
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x07f80000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
+
+/* RX status word 1 fields/flags */
+#define AR5K_5210_RX_DESC_STATUS1_DONE			0x00000001
+#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
+#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS	0x10000000
+
+/* 5212 */
+/* RX status word 0 fields/flags */
+#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+#define AR5K_5212_RX_DESC_STATUS0_MORE			0x00001000
+#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S	15
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x0ff00000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
+
+/* RX status word 1 fields/flags */
+#define AR5K_5212_RX_DESC_STATUS1_DONE			0x00000001
+#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
+#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR		0x00000010
+#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR		0x00000020
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S		9
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
+#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS	0x80000000
+
+/*
+ * common hardware RX error descriptor
+ */
+struct ath5k_hw_rx_error {
+	u32	rx_error_0; /* RX status word 0 */
+	u32	rx_error_1; /* RX status word 1 */
+} __packed;
+
+/* RX error word 0 fields/flags */
+#define AR5K_RX_DESC_ERROR0			0x00000000
+
+/* RX error word 1 fields/flags */
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE	0x0000ff00
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S	8
+
+/* PHY Error codes */
+#define AR5K_DESC_RX_PHY_ERROR_NONE		0x00
+#define AR5K_DESC_RX_PHY_ERROR_TIMING		0x20
+#define AR5K_DESC_RX_PHY_ERROR_PARITY		0x40
+#define AR5K_DESC_RX_PHY_ERROR_RATE		0x60
+#define AR5K_DESC_RX_PHY_ERROR_LENGTH		0x80
+#define AR5K_DESC_RX_PHY_ERROR_64QAM		0xa0
+#define AR5K_DESC_RX_PHY_ERROR_SERVICE		0xc0
+#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR	0xe0
+
+/*
+ * 5210/5211 hardware 2-word TX control descriptor
+ */
+struct ath5k_hw_2w_tx_ctl {
+	u32	tx_control_0; /* TX control word 0 */
+	u32	tx_control_1; /* TX control word 1 */
+} __packed;
+
+/* TX control word 0 fields/flags */
+#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN		0x0003f000 /*[5210 ?]*/
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S	12
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE		0x003c0000
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S	18
+#define AR5K_2W_TX_DESC_CTL0_RTSENA		0x00400000
+#define AR5K_2W_TX_DESC_CTL0_CLRDMASK		0x01000000
+#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET	0x00800000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_VEOL		0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE		0x1c000000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S	26
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210	0x02000000
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211	0x1e000000
+
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT			\
+		(ah->ah_version == AR5K_AR5210 ?		\
+		AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 :	\
+		AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
+
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S	25
+#define AR5K_2W_TX_DESC_CTL0_INTREQ		0x20000000
+#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID	0x40000000
+
+/* TX control word 1 fields/flags */
+#define AR5K_2W_TX_DESC_CTL1_BUF_LEN		0x00000fff
+#define AR5K_2W_TX_DESC_CTL1_MORE		0x00001000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210	0x0007e000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211	0x000fe000
+
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX				\
+			(ah->ah_version == AR5K_AR5210 ?		\
+			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 :	\
+			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
+
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S	13
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE		0x00700000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S	20
+#define AR5K_2W_TX_DESC_CTL1_NOACK		0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION	0xfff80000 /*[5210 ?]*/
+
+/* Frame types */
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL   0x00
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM     0x04
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL   0x08
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS     0x10
+
+/*
+ * 5212 hardware 4-word TX control descriptor
+ */
+struct ath5k_hw_4w_tx_ctl {
+	u32	tx_control_0; /* TX control word 0 */
+
+#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER		0x003f0000
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S	16
+#define AR5K_4W_TX_DESC_CTL0_RTSENA		0x00400000
+#define AR5K_4W_TX_DESC_CTL0_VEOL		0x00800000
+#define AR5K_4W_TX_DESC_CTL0_CLRDMASK		0x01000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT	0x1e000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S	25
+#define AR5K_4W_TX_DESC_CTL0_INTREQ		0x20000000
+#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID	0x40000000
+#define AR5K_4W_TX_DESC_CTL0_CTSENA		0x80000000
+
+	u32	tx_control_1; /* TX control word 1 */
+
+#define AR5K_4W_TX_DESC_CTL1_BUF_LEN		0x00000fff
+#define AR5K_4W_TX_DESC_CTL1_MORE		0x00001000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX	0x000fe000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S	13
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE		0x00f00000
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S	20
+#define AR5K_4W_TX_DESC_CTL1_NOACK		0x01000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC		0x06000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S	25
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN	0x18000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S	27
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN	0x60000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S	29
+
+	u32	tx_control_2; /* TX control word 2 */
+
+#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION		0x00007fff
+#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE	0x00008000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0		0x000f0000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S		16
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1		0x00f00000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S		20
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2		0x0f000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S		24
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3		0xf0000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S		28
+
+	u32	tx_control_3; /* TX control word 3 */
+
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0		0x0000001f
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1		0x000003e0
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S	5
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2		0x00007c00
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S	10
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3		0x000f8000
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S	15
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE	0x01f00000
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S	20
+} __packed;
+
+/*
+ * Common TX status descriptor
+ */
+struct ath5k_hw_tx_status {
+	u32	tx_status_0; /* TX status word 0 */
+	u32	tx_status_1; /* TX status word 1 */
+} __packed;
+
+/* TX status word 0 fields/flags */
+#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK	0x00000001
+#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES	0x00000002
+#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN	0x00000004
+#define AR5K_DESC_TX_STATUS0_FILTERED		0x00000008
+/*???
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT	0x000000f0
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S	4
+*/
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT	0x000000f0
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S	4
+/*???
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT	0x00000f00
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S	8
+*/
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT	0x00000f00
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S	8
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT	0x0000f000
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S	12
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP	0xffff0000
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S	16
+
+/* TX status word 1 fields/flags */
+#define AR5K_DESC_TX_STATUS1_DONE		0x00000001
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM		0x00001ffe
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S		1
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH	0x001fe000
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S	13
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX	0x00600000
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S	21
+#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS	0x00800000
+#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA	0x01000000
+
+/*
+ * 5210/5211 hardware TX descriptor
+ */
+struct ath5k_hw_5210_tx_desc {
+	struct ath5k_hw_2w_tx_ctl	tx_ctl;
+	struct ath5k_hw_tx_status	tx_stat;
+} __packed;
+
+/*
+ * 5212 hardware TX descriptor
+ */
+struct ath5k_hw_5212_tx_desc {
+	struct ath5k_hw_4w_tx_ctl	tx_ctl;
+	struct ath5k_hw_tx_status	tx_stat;
+} __packed;
+
+/*
+ * common hardware RX descriptor
+ */
+struct ath5k_hw_all_rx_desc {
+	struct ath5k_hw_rx_ctl			rx_ctl;
+	union {
+		struct ath5k_hw_rx_status	rx_stat;
+		struct ath5k_hw_rx_error	rx_err;
+	} u;
+} __packed;
+
+/*
+ * Atheros hardware descriptor
+ * This is read and written to by the hardware
+ */
+struct ath5k_desc {
+	u32	ds_link;	/* physical address of the next descriptor */
+	u32	ds_data;	/* physical address of data buffer (skb) */
+
+	union {
+		struct ath5k_hw_5210_tx_desc	ds_tx5210;
+		struct ath5k_hw_5212_tx_desc	ds_tx5212;
+		struct ath5k_hw_all_rx_desc	ds_rx;
+	} ud;
+} __packed;
+
+#define AR5K_RXDESC_INTREQ	0x0020
+
+#define AR5K_TXDESC_CLRDMASK	0x0001
+#define AR5K_TXDESC_NOACK	0x0002	/*[5211+]*/
+#define AR5K_TXDESC_RTSENA	0x0004
+#define AR5K_TXDESC_CTSENA	0x0008
+#define AR5K_TXDESC_INTREQ	0x0010
+#define AR5K_TXDESC_VEOL	0x0020	/*[5211+]*/
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/dma.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/dma.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,703 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*************************************\
+* DMA and interrupt masking functions *
+\*************************************/
+
+/*
+ * dma.c - DMA and interrupt masking functions
+ *
+ * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
+ * handle queue setup for 5210 chipset (rest are handled on qcu.c).
+ * Also we setup interrupt mask register (IMR) and read the various iterrupt
+ * status registers (ISR).
+ *
+ * TODO: Handle SISR on 5211+ and introduce a function to return the queue
+ * number that resulted the interrupt.
+ */
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*********\
+* Receive *
+\*********/
+
+/**
+ * ath5k_hw_start_rx_dma - Start DMA receive
+ *
+ * @ah:	The &struct ath5k_hw
+ */
+void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
+	ath5k_hw_reg_read(ah, AR5K_CR);
+}
+
+/**
+ * ath5k_hw_stop_rx_dma - Stop DMA receive
+ *
+ * @ah:	The &struct ath5k_hw
+ */
+int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
+{
+	unsigned int i;
+
+	ATH5K_TRACE(ah->ah_sc);
+	ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
+
+	/*
+	 * It may take some time to disable the DMA receive unit
+	 */
+	for (i = 1000; i > 0 &&
+			(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
+			i--)
+		udelay(10);
+
+	return i ? 0 : -EBUSY;
+}
+
+/**
+ * ath5k_hw_get_rxdp - Get RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ */
+u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
+{
+	return ath5k_hw_reg_read(ah, AR5K_RXDP);
+}
+
+/**
+ * ath5k_hw_set_rxdp - Set RX Descriptor's address
+ *
+ * @ah: The &struct ath5k_hw
+ * @phys_addr: RX descriptor address
+ *
+ * XXX: Should we check if rx is enabled before setting rxdp ?
+ */
+void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
+}
+
+
+/**********\
+* Transmit *
+\**********/
+
+/**
+ * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Start DMA transmit for a specific queue and since 5210 doesn't have
+ * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
+ * queue for normal data and one queue for beacons). For queue setup
+ * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
+ * of range or if queue is already disabled.
+ *
+ * NOTE: Must be called after setting up tx control descriptor for that
+ * queue (see below).
+ */
+int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+	u32 tx_queue;
+
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	/* Return if queue is declared inactive */
+	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+		return -EIO;
+
+	if (ah->ah_version == AR5K_AR5210) {
+		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+		/*
+		 * Set the queue by type on 5210
+		 */
+		switch (ah->ah_txq[queue].tqi_type) {
+		case AR5K_TX_QUEUE_DATA:
+			tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
+			break;
+		case AR5K_TX_QUEUE_BEACON:
+			tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
+			ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
+					AR5K_BSR);
+			break;
+		case AR5K_TX_QUEUE_CAB:
+			tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
+			ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
+				AR5K_BCR_BDMAE, AR5K_BSR);
+			break;
+		default:
+			return -EINVAL;
+		}
+		/* Start queue */
+		ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+		ath5k_hw_reg_read(ah, AR5K_CR);
+	} else {
+		/* Return if queue is disabled */
+		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
+			return -EIO;
+
+		/* Start queue */
+		AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
+	}
+
+	return 0;
+}
+
+/**
+ * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Stop DMA transmit on a specific hw queue and drain queue so we don't
+ * have any pending frames. Returns -EBUSY if we still have pending frames,
+ * -EINVAL if queue number is out of range.
+ *
+ */
+int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+	unsigned int i = 40;
+	u32 tx_queue, pending;
+
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	/* Return if queue is declared inactive */
+	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+		return -EIO;
+
+	if (ah->ah_version == AR5K_AR5210) {
+		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+		/*
+		 * Set by queue type
+		 */
+		switch (ah->ah_txq[queue].tqi_type) {
+		case AR5K_TX_QUEUE_DATA:
+			tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
+			break;
+		case AR5K_TX_QUEUE_BEACON:
+		case AR5K_TX_QUEUE_CAB:
+			/* XXX Fix me... */
+			tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
+			ath5k_hw_reg_write(ah, 0, AR5K_BSR);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		/* Stop queue */
+		ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+		ath5k_hw_reg_read(ah, AR5K_CR);
+	} else {
+		/*
+		 * Schedule TX disable and wait until queue is empty
+		 */
+		AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
+
+		/*Check for pending frames*/
+		do {
+			pending = ath5k_hw_reg_read(ah,
+				AR5K_QUEUE_STATUS(queue)) &
+				AR5K_QCU_STS_FRMPENDCNT;
+			udelay(100);
+		} while (--i && pending);
+
+		/* For 2413+ order PCU to drop packets using
+		 * QUIET mechanism */
+		if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
+		pending){
+			/* Set periodicity and duration */
+			ath5k_hw_reg_write(ah,
+				AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
+				AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
+				AR5K_QUIET_CTL2);
+
+			/* Enable quiet period for current TSF */
+			ath5k_hw_reg_write(ah,
+				AR5K_QUIET_CTL1_QT_EN |
+				AR5K_REG_SM(ath5k_hw_reg_read(ah,
+						AR5K_TSF_L32_5211) >> 10,
+						AR5K_QUIET_CTL1_NEXT_QT_TSF),
+				AR5K_QUIET_CTL1);
+
+			/* Force channel idle high */
+			AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+
+			/* Wait a while and disable mechanism */
+			udelay(200);
+			AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
+						AR5K_QUIET_CTL1_QT_EN);
+
+			/* Re-check for pending frames */
+			i = 40;
+			do {
+				pending = ath5k_hw_reg_read(ah,
+					AR5K_QUEUE_STATUS(queue)) &
+					AR5K_QCU_STS_FRMPENDCNT;
+				udelay(100);
+			} while (--i && pending);
+
+			AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
+					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+		}
+
+		/* Clear register */
+		ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
+		if (pending)
+			return -EBUSY;
+	}
+
+	/* TODO: Check for success on 5210 else return error */
+	return 0;
+}
+
+/**
+ * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Get TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and use tx queue type since we only have 2 queues.
+ * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just read the corresponding TXDP register.
+ *
+ * XXX: Is TXDP read and clear ?
+ */
+u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
+{
+	u16 tx_reg;
+
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	/*
+	 * Get the transmit queue descriptor pointer from the selected queue
+	 */
+	/*5210 doesn't have QCU*/
+	if (ah->ah_version == AR5K_AR5210) {
+		switch (ah->ah_txq[queue].tqi_type) {
+		case AR5K_TX_QUEUE_DATA:
+			tx_reg = AR5K_NOQCU_TXDP0;
+			break;
+		case AR5K_TX_QUEUE_BEACON:
+		case AR5K_TX_QUEUE_CAB:
+			tx_reg = AR5K_NOQCU_TXDP1;
+			break;
+		default:
+			return 0xffffffff;
+		}
+	} else {
+		tx_reg = AR5K_QUEUE_TXDP(queue);
+	}
+
+	return ath5k_hw_reg_read(ah, tx_reg);
+}
+
+/**
+ * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
+ *
+ * @ah: The &struct ath5k_hw
+ * @queue: The hw queue number
+ *
+ * Set TX descriptor's address for a specific queue. For 5210 we ignore
+ * the queue number and we use tx queue type since we only have 2 queues
+ * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
+ * For newer chips with QCU/DCU we just set the corresponding TXDP register.
+ * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
+ * active.
+ */
+int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
+{
+	u16 tx_reg;
+
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	/*
+	 * Set the transmit queue descriptor pointer register by type
+	 * on 5210
+	 */
+	if (ah->ah_version == AR5K_AR5210) {
+		switch (ah->ah_txq[queue].tqi_type) {
+		case AR5K_TX_QUEUE_DATA:
+			tx_reg = AR5K_NOQCU_TXDP0;
+			break;
+		case AR5K_TX_QUEUE_BEACON:
+		case AR5K_TX_QUEUE_CAB:
+			tx_reg = AR5K_NOQCU_TXDP1;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		/*
+		 * Set the transmit queue descriptor pointer for
+		 * the selected queue on QCU for 5211+
+		 * (this won't work if the queue is still active)
+		 */
+		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+			return -EIO;
+
+		tx_reg = AR5K_QUEUE_TXDP(queue);
+	}
+
+	/* Set descriptor pointer */
+	ath5k_hw_reg_write(ah, phys_addr, tx_reg);
+
+	return 0;
+}
+
+/**
+ * ath5k_hw_update_tx_triglevel - Update tx trigger level
+ *
+ * @ah: The &struct ath5k_hw
+ * @increase: Flag to force increase of trigger level
+ *
+ * This function increases/decreases the tx trigger level for the tx fifo
+ * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
+ * the buffer and transmits it's data. Lowering this results sending small
+ * frames more quickly but can lead to tx underruns, raising it a lot can
+ * result other problems (i think bmiss is related). Right now we start with
+ * the lowest possible (64Bytes) and if we get tx underrun we increase it using
+ * the increase flag. Returns -EIO if we have have reached maximum/minimum.
+ *
+ * XXX: Link this with tx DMA size ?
+ * XXX: Use it to save interrupts ?
+ * TODO: Needs testing, i think it's related to bmiss...
+ */
+int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
+{
+	u32 trigger_level, imr;
+	int ret = -EIO;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/*
+	 * Disable interrupts by setting the mask
+	 */
+	imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
+
+	trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
+			AR5K_TXCFG_TXFULL);
+
+	if (!increase) {
+		if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+			goto done;
+	} else
+		trigger_level +=
+			((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
+
+	/*
+	 * Update trigger level on success
+	 */
+	if (ah->ah_version == AR5K_AR5210)
+		ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
+	else
+		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+				AR5K_TXCFG_TXFULL, trigger_level);
+
+	ret = 0;
+
+done:
+	/*
+	 * Restore interrupt mask
+	 */
+	ath5k_hw_set_imr(ah, imr);
+
+	return ret;
+}
+
+/*******************\
+* Interrupt masking *
+\*******************/
+
+/**
+ * ath5k_hw_is_intr_pending - Check if we have pending interrupts
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Check if we have pending interrupts to process. Returns 1 if we
+ * have pending interrupts and 0 if we haven't.
+ */
+bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
+}
+
+/**
+ * ath5k_hw_get_isr - Get interrupt status
+ *
+ * @ah: The @struct ath5k_hw
+ * @interrupt_mask: Driver's interrupt mask used to filter out
+ * interrupts in sw.
+ *
+ * This function is used inside our interrupt handler to determine the reason
+ * for the interrupt by reading Primary Interrupt Status Register. Returns an
+ * abstract interrupt status mask which is mostly ISR with some uncommon bits
+ * being mapped on some standard non hw-specific positions
+ * (check out &ath5k_int).
+ *
+ * NOTE: We use read-and-clear register, so after this function is called ISR
+ * is zeroed.
+ */
+int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
+{
+	u32 data;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/*
+	 * Read interrupt status from the Interrupt Status register
+	 * on 5210
+	 */
+	if (ah->ah_version == AR5K_AR5210) {
+		data = ath5k_hw_reg_read(ah, AR5K_ISR);
+		if (unlikely(data == AR5K_INT_NOCARD)) {
+			*interrupt_mask = data;
+			return -ENODEV;
+		}
+	} else {
+		/*
+		 * Read interrupt status from Interrupt
+		 * Status Register shadow copy (Read And Clear)
+		 *
+		 * Note: PISR/SISR Not available on 5210
+		 */
+		data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
+		if (unlikely(data == AR5K_INT_NOCARD)) {
+			*interrupt_mask = data;
+			return -ENODEV;
+		}
+	}
+
+	/*
+	 * Get abstract interrupt mask (driver-compatible)
+	 */
+	*interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
+
+	if (ah->ah_version != AR5K_AR5210) {
+		u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
+
+		/*HIU = Host Interface Unit (PCI etc)*/
+		if (unlikely(data & (AR5K_ISR_HIUERR)))
+			*interrupt_mask |= AR5K_INT_FATAL;
+
+		/*Beacon Not Ready*/
+		if (unlikely(data & (AR5K_ISR_BNR)))
+			*interrupt_mask |= AR5K_INT_BNR;
+
+		if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
+					AR5K_SISR2_DPERR |
+					AR5K_SISR2_MCABT)))
+			*interrupt_mask |= AR5K_INT_FATAL;
+
+		if (data & AR5K_ISR_TIM)
+			*interrupt_mask |= AR5K_INT_TIM;
+
+		if (data & AR5K_ISR_BCNMISC) {
+			if (sisr2 & AR5K_SISR2_TIM)
+				*interrupt_mask |= AR5K_INT_TIM;
+			if (sisr2 & AR5K_SISR2_DTIM)
+				*interrupt_mask |= AR5K_INT_DTIM;
+			if (sisr2 & AR5K_SISR2_DTIM_SYNC)
+				*interrupt_mask |= AR5K_INT_DTIM_SYNC;
+			if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
+				*interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
+			if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
+				*interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
+		}
+
+		if (data & AR5K_ISR_RXDOPPLER)
+			*interrupt_mask |= AR5K_INT_RX_DOPPLER;
+		if (data & AR5K_ISR_QCBRORN) {
+			*interrupt_mask |= AR5K_INT_QCBRORN;
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+					AR5K_SISR3_QCBRORN);
+		}
+		if (data & AR5K_ISR_QCBRURN) {
+			*interrupt_mask |= AR5K_INT_QCBRURN;
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+					AR5K_SISR3_QCBRURN);
+		}
+		if (data & AR5K_ISR_QTRIG) {
+			*interrupt_mask |= AR5K_INT_QTRIG;
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
+					AR5K_SISR4_QTRIG);
+		}
+
+		if (data & AR5K_ISR_TXOK)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+					AR5K_SISR0_QCU_TXOK);
+
+		if (data & AR5K_ISR_TXDESC)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+					AR5K_SISR0_QCU_TXDESC);
+
+		if (data & AR5K_ISR_TXERR)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+					AR5K_SISR1_QCU_TXERR);
+
+		if (data & AR5K_ISR_TXEOL)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+					AR5K_SISR1_QCU_TXEOL);
+
+		if (data & AR5K_ISR_TXURN)
+			ah->ah_txq_isr |= AR5K_REG_MS(
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
+					AR5K_SISR2_QCU_TXURN);
+	} else {
+		if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
+				| AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
+			*interrupt_mask |= AR5K_INT_FATAL;
+
+		/*
+		 * XXX: BMISS interrupts may occur after association.
+		 * I found this on 5210 code but it needs testing. If this is
+		 * true we should disable them before assoc and re-enable them
+		 * after a successful assoc + some jiffies.
+			interrupt_mask &= ~AR5K_INT_BMISS;
+		 */
+	}
+
+	/*
+	 * In case we didn't handle anything,
+	 * print the register value.
+	 */
+	if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
+		ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
+
+	return 0;
+}
+
+/**
+ * ath5k_hw_set_imr - Set interrupt mask
+ *
+ * @ah: The &struct ath5k_hw
+ * @new_mask: The new interrupt mask to be set
+ *
+ * Set the interrupt mask in hw to save interrupts. We do that by mapping
+ * ath5k_int bits to hw-specific bits to remove abstraction and writing
+ * Interrupt Mask Register.
+ */
+enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
+{
+	enum ath5k_int old_mask, int_mask;
+
+	old_mask = ah->ah_imr;
+
+	/*
+	 * Disable card interrupts to prevent any race conditions
+	 * (they will be re-enabled afterwards if AR5K_INT GLOBAL
+	 * is set again on the new mask).
+	 */
+	if (old_mask & AR5K_INT_GLOBAL) {
+		ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
+		ath5k_hw_reg_read(ah, AR5K_IER);
+	}
+
+	/*
+	 * Add additional, chipset-dependent interrupt mask flags
+	 * and write them to the IMR (interrupt mask register).
+	 */
+	int_mask = new_mask & AR5K_INT_COMMON;
+
+	if (ah->ah_version != AR5K_AR5210) {
+		/* Preserve per queue TXURN interrupt mask */
+		u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
+				& AR5K_SIMR2_QCU_TXURN;
+
+		if (new_mask & AR5K_INT_FATAL) {
+			int_mask |= AR5K_IMR_HIUERR;
+			simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
+				| AR5K_SIMR2_DPERR);
+		}
+
+		/*Beacon Not Ready*/
+		if (new_mask & AR5K_INT_BNR)
+			int_mask |= AR5K_INT_BNR;
+
+		if (new_mask & AR5K_INT_TIM)
+			int_mask |= AR5K_IMR_TIM;
+
+		if (new_mask & AR5K_INT_TIM)
+			simr2 |= AR5K_SISR2_TIM;
+		if (new_mask & AR5K_INT_DTIM)
+			simr2 |= AR5K_SISR2_DTIM;
+		if (new_mask & AR5K_INT_DTIM_SYNC)
+			simr2 |= AR5K_SISR2_DTIM_SYNC;
+		if (new_mask & AR5K_INT_BCN_TIMEOUT)
+			simr2 |= AR5K_SISR2_BCN_TIMEOUT;
+		if (new_mask & AR5K_INT_CAB_TIMEOUT)
+			simr2 |= AR5K_SISR2_CAB_TIMEOUT;
+
+		if (new_mask & AR5K_INT_RX_DOPPLER)
+			int_mask |= AR5K_IMR_RXDOPPLER;
+
+		/* Note: Per queue interrupt masks
+		 * are set via reset_tx_queue (qcu.c) */
+		ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+		ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
+
+	} else {
+		if (new_mask & AR5K_INT_FATAL)
+			int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
+				| AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
+
+		ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
+	}
+
+	/* If RXNOFRM interrupt is masked disable it
+	 * by setting AR5K_RXNOFRM to zero */
+	if (!(new_mask & AR5K_INT_RXNOFRM))
+		ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
+
+	/* Store new interrupt mask */
+	ah->ah_imr = new_mask;
+
+	/* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
+	if (new_mask & AR5K_INT_GLOBAL) {
+		ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
+		ath5k_hw_reg_read(ah, AR5K_IER);
+	}
+
+	return old_mask;
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/eeprom.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/eeprom.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/eeprom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/eeprom.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1802 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*************************************\
+* EEPROM access functions and helpers *
+\*************************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Read from eeprom
+ */
+static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
+{
+	u32 status, timeout;
+
+	ATH5K_TRACE(ah->ah_sc);
+	/*
+	 * Initialize EEPROM access
+	 */
+	if (ah->ah_version == AR5K_AR5210) {
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+		(void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
+	} else {
+		ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+		AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+				AR5K_EEPROM_CMD_READ);
+	}
+
+	for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+		status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+		if (status & AR5K_EEPROM_STAT_RDDONE) {
+			if (status & AR5K_EEPROM_STAT_RDERR)
+				return -EIO;
+			*data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
+					0xffff);
+			return 0;
+		}
+		udelay(15);
+	}
+
+	return -ETIMEDOUT;
+}
+
+/*
+ * Translate binary channel representation in EEPROM to frequency
+ */
+static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
+                                 unsigned int mode)
+{
+	u16 val;
+
+	if (bin == AR5K_EEPROM_CHANNEL_DIS)
+		return bin;
+
+	if (mode == AR5K_EEPROM_MODE_11A) {
+		if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
+			val = (5 * bin) + 4800;
+		else
+			val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
+				(bin * 10) + 5100;
+	} else {
+		if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
+			val = bin + 2300;
+		else
+			val = bin + 2400;
+	}
+
+	return val;
+}
+
+/*
+ * Initialize eeprom & capabilities structs
+ */
+static int
+ath5k_eeprom_init_header(struct ath5k_hw *ah)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	int ret;
+	u16 val;
+
+	/*
+	 * Read values from EEPROM and store them in the capability structure
+	 */
+	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
+	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
+	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
+	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
+	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+
+	/* Return if we have an old EEPROM */
+	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
+		return 0;
+
+#ifdef notyet
+	/*
+	 * Validate the checksum of the EEPROM date. There are some
+	 * devices with invalid EEPROMs.
+	 */
+	for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
+		AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
+		cksum ^= val;
+	}
+	if (cksum != AR5K_EEPROM_INFO_CKSUM) {
+		ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
+		return -EIO;
+	}
+#endif
+
+	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
+	    ee_ant_gain);
+
+	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+		AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
+		AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+
+		/* XXX: Don't know which versions include these two */
+		AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
+
+		if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
+			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
+
+		if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
+			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
+			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
+			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
+		}
+	}
+
+	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
+		AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
+		ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
+		ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+
+		AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
+		ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
+		ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+	}
+
+	AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val);
+
+	if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val)
+		ee->ee_is_hb63 = true;
+	else
+		ee->ee_is_hb63 = false;
+
+	AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val);
+	ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL);
+	ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? true : false;
+
+	return 0;
+}
+
+
+/*
+ * Read antenna infos from eeprom
+ */
+static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
+		unsigned int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 o = *offset;
+	u16 val;
+	int ret, i = 0;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_switch_settling[mode]	= (val >> 8) & 0x7f;
+	ee->ee_atn_tx_rx[mode]		= (val >> 2) & 0x3f;
+	ee->ee_ant_control[mode][i]	= (val << 4) & 0x3f;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_ant_control[mode][i++]	|= (val >> 12) & 0xf;
+	ee->ee_ant_control[mode][i++]	= (val >> 6) & 0x3f;
+	ee->ee_ant_control[mode][i++]	= val & 0x3f;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_ant_control[mode][i++]	= (val >> 10) & 0x3f;
+	ee->ee_ant_control[mode][i++]	= (val >> 4) & 0x3f;
+	ee->ee_ant_control[mode][i]	= (val << 2) & 0x3f;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_ant_control[mode][i++]	|= (val >> 14) & 0x3;
+	ee->ee_ant_control[mode][i++]	= (val >> 8) & 0x3f;
+	ee->ee_ant_control[mode][i++]	= (val >> 2) & 0x3f;
+	ee->ee_ant_control[mode][i]	= (val << 4) & 0x3f;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_ant_control[mode][i++]	|= (val >> 12) & 0xf;
+	ee->ee_ant_control[mode][i++]	= (val >> 6) & 0x3f;
+	ee->ee_ant_control[mode][i++]	= val & 0x3f;
+
+	/* Get antenna switch tables */
+	ah->ah_ant_ctl[mode][AR5K_ANT_CTL] =
+	    (ee->ee_ant_control[mode][0] << 4);
+	ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] =
+	     ee->ee_ant_control[mode][1] 	|
+	    (ee->ee_ant_control[mode][2] << 6) 	|
+	    (ee->ee_ant_control[mode][3] << 12) |
+	    (ee->ee_ant_control[mode][4] << 18) |
+	    (ee->ee_ant_control[mode][5] << 24);
+	ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] =
+	     ee->ee_ant_control[mode][6] 	|
+	    (ee->ee_ant_control[mode][7] << 6) 	|
+	    (ee->ee_ant_control[mode][8] << 12) |
+	    (ee->ee_ant_control[mode][9] << 18) |
+	    (ee->ee_ant_control[mode][10] << 24);
+
+	/* return new offset */
+	*offset = o;
+
+	return 0;
+}
+
+/*
+ * Read supported modes and some mode-specific calibration data
+ * from eeprom
+ */
+static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
+		unsigned int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 o = *offset;
+	u16 val;
+	int ret;
+
+	ee->ee_n_piers[mode] = 0;
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_adc_desired_size[mode]	= (s8)((val >> 8) & 0xff);
+	switch(mode) {
+	case AR5K_EEPROM_MODE_11A:
+		ee->ee_ob[mode][3]	= (val >> 5) & 0x7;
+		ee->ee_db[mode][3]	= (val >> 2) & 0x7;
+		ee->ee_ob[mode][2]	= (val << 1) & 0x7;
+
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_ob[mode][2]	|= (val >> 15) & 0x1;
+		ee->ee_db[mode][2]	= (val >> 12) & 0x7;
+		ee->ee_ob[mode][1]	= (val >> 9) & 0x7;
+		ee->ee_db[mode][1]	= (val >> 6) & 0x7;
+		ee->ee_ob[mode][0]	= (val >> 3) & 0x7;
+		ee->ee_db[mode][0]	= val & 0x7;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+	case AR5K_EEPROM_MODE_11B:
+		ee->ee_ob[mode][1]	= (val >> 4) & 0x7;
+		ee->ee_db[mode][1]	= val & 0x7;
+		break;
+	}
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_tx_end2xlna_enable[mode]	= (val >> 8) & 0xff;
+	ee->ee_thr_62[mode]		= val & 0xff;
+
+	if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+		ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_tx_end2xpa_disable[mode]	= (val >> 8) & 0xff;
+	ee->ee_tx_frm2xpa_enable[mode]	= val & 0xff;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_pga_desired_size[mode]	= (val >> 8) & 0xff;
+
+	if ((val & 0xff) & 0x80)
+		ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
+	else
+		ee->ee_noise_floor_thr[mode] = val & 0xff;
+
+	if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+		ee->ee_noise_floor_thr[mode] =
+		    mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
+
+	AR5K_EEPROM_READ(o++, val);
+	ee->ee_xlna_gain[mode]		= (val >> 5) & 0xff;
+	ee->ee_x_gain[mode]		= (val >> 1) & 0xf;
+	ee->ee_xpd[mode]		= val & 0x1;
+
+	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
+		ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
+
+	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
+
+		if (mode == AR5K_EEPROM_MODE_11A)
+			ee->ee_xr_power[mode] = val & 0x3f;
+		else {
+			ee->ee_ob[mode][0] = val & 0x7;
+			ee->ee_db[mode][0] = (val >> 3) & 0x7;
+		}
+	}
+
+	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
+		ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
+		ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
+	} else {
+		ee->ee_i_gain[mode] = (val >> 13) & 0x7;
+
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_i_gain[mode] |= (val << 3) & 0x38;
+
+		if (mode == AR5K_EEPROM_MODE_11G) {
+			ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
+			if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6)
+				ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+		}
+	}
+
+	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
+			mode == AR5K_EEPROM_MODE_11A) {
+		ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+		ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+	}
+
+	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
+		goto done;
+
+	/* Note: >= v5 have bg freq piers on another location
+	 * so these freq piers are ignored for >= v5 (should be 0xff
+	 * anyway) */
+	switch(mode) {
+	case AR5K_EEPROM_MODE_11A:
+		if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
+			break;
+
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_margin_tx_rx[mode] = val & 0x3f;
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		AR5K_EEPROM_READ(o++, val);
+
+		ee->ee_pwr_cal_b[0].freq =
+			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+		if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+			ee->ee_n_piers[mode]++;
+
+		ee->ee_pwr_cal_b[1].freq =
+			ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+		if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+			ee->ee_n_piers[mode]++;
+
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_pwr_cal_b[2].freq =
+			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+		if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+			ee->ee_n_piers[mode]++;
+
+		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+			ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		AR5K_EEPROM_READ(o++, val);
+
+		ee->ee_pwr_cal_g[0].freq =
+			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+		if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+			ee->ee_n_piers[mode]++;
+
+		ee->ee_pwr_cal_g[1].freq =
+			ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+		if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+			ee->ee_n_piers[mode]++;
+
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_turbo_max_power[mode] = val & 0x7f;
+		ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_pwr_cal_g[2].freq =
+			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+		if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+			ee->ee_n_piers[mode]++;
+
+		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+			ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+		ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+
+		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+			AR5K_EEPROM_READ(o++, val);
+			ee->ee_cck_ofdm_gain_delta = val & 0xff;
+		}
+		break;
+	}
+
+done:
+	/* return new offset */
+	*offset = o;
+
+	return 0;
+}
+
+/*
+ * Read turbo mode information on newer EEPROM versions
+ */
+static int
+ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
+			      u32 *offset, unsigned int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 o = *offset;
+	u16 val;
+	int ret;
+
+	if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
+		return 0;
+
+	switch (mode){
+	case AR5K_EEPROM_MODE_11A:
+		ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
+
+		ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7;
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3;
+		ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f;
+
+		ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f;
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
+		ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
+
+		if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
+			ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f;
+
+		ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7;
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1;
+		ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f;
+
+		ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f;
+		AR5K_EEPROM_READ(o++, val);
+		ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5;
+		ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff;
+		break;
+	}
+
+	/* return new offset */
+	*offset = o;
+
+	return 0;
+}
+
+/* Read mode-specific data (except power calibration data) */
+static int
+ath5k_eeprom_init_modes(struct ath5k_hw *ah)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 mode_offset[3];
+	unsigned int mode;
+	u32 offset;
+	int ret;
+
+	/*
+	 * Get values for all modes
+	 */
+	mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
+	mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
+	mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
+
+	ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] =
+		AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+
+	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
+		offset = mode_offset[mode];
+
+		ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+		if (ret)
+			return ret;
+
+		ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+		if (ret)
+			return ret;
+
+		ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
+		if (ret)
+			return ret;
+	}
+
+	/* override for older eeprom versions for better performance */
+	if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) {
+		ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15;
+		ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28;
+		ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28;
+	}
+
+	return 0;
+}
+
+/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
+ * frequency mask) */
+static inline int
+ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
+			struct ath5k_chan_pcal_info *pc, unsigned int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	int o = *offset;
+	int i = 0;
+	u8 freq1, freq2;
+	int ret;
+	u16 val;
+
+	ee->ee_n_piers[mode] = 0;
+	while(i < max) {
+		AR5K_EEPROM_READ(o++, val);
+
+		freq1 = val & 0xff;
+		if (!freq1)
+			break;
+
+		pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+				freq1, mode);
+		ee->ee_n_piers[mode]++;
+
+		freq2 = (val >> 8) & 0xff;
+		if (!freq2)
+			break;
+
+		pc[i++].freq = ath5k_eeprom_bin2freq(ee,
+				freq2, mode);
+		ee->ee_n_piers[mode]++;
+	}
+
+	/* return new offset */
+	*offset = o;
+
+	return 0;
+}
+
+/* Read frequency piers for 802.11a */
+static int
+ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
+	int i, ret;
+	u16 val;
+	u8 mask;
+
+	if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+		ath5k_eeprom_read_freq_list(ah, &offset,
+			AR5K_EEPROM_N_5GHZ_CHAN, pcal,
+			AR5K_EEPROM_MODE_11A);
+	} else {
+		mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
+
+		AR5K_EEPROM_READ(offset++, val);
+		pcal[0].freq  = (val >> 9) & mask;
+		pcal[1].freq  = (val >> 2) & mask;
+		pcal[2].freq  = (val << 5) & mask;
+
+		AR5K_EEPROM_READ(offset++, val);
+		pcal[2].freq |= (val >> 11) & 0x1f;
+		pcal[3].freq  = (val >> 4) & mask;
+		pcal[4].freq  = (val << 3) & mask;
+
+		AR5K_EEPROM_READ(offset++, val);
+		pcal[4].freq |= (val >> 13) & 0x7;
+		pcal[5].freq  = (val >> 6) & mask;
+		pcal[6].freq  = (val << 1) & mask;
+
+		AR5K_EEPROM_READ(offset++, val);
+		pcal[6].freq |= (val >> 15) & 0x1;
+		pcal[7].freq  = (val >> 8) & mask;
+		pcal[8].freq  = (val >> 1) & mask;
+		pcal[9].freq  = (val << 6) & mask;
+
+		AR5K_EEPROM_READ(offset++, val);
+		pcal[9].freq |= (val >> 10) & 0x3f;
+
+		/* Fixed number of piers */
+		ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
+
+		for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
+			pcal[i].freq = ath5k_eeprom_bin2freq(ee,
+				pcal[i].freq, AR5K_EEPROM_MODE_11A);
+		}
+	}
+
+	return 0;
+}
+
+/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
+static inline int
+ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info *pcal;
+
+	switch(mode) {
+	case AR5K_EEPROM_MODE_11B:
+		pcal = ee->ee_pwr_cal_b;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		pcal = ee->ee_pwr_cal_g;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ath5k_eeprom_read_freq_list(ah, &offset,
+		AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
+		mode);
+
+	return 0;
+}
+
+/*
+ * Read power calibration for RF5111 chips
+ *
+ * For RF5111 we have an XPD -eXternal Power Detector- curve
+ * for each calibrated channel. Each curve has 0,5dB Power steps
+ * on x axis and PCDAC steps (offsets) on y axis and looks like an
+ * exponential function. To recreate the curve we read 11 points
+ * here and interpolate later.
+ */
+
+/* Used to match PCDAC steps with power values on RF5111 chips
+ * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
+ * steps that match with the power values we read from eeprom. On
+ * older eeprom versions (< 3.2) these steps are equaly spaced at
+ * 10% of the pcdac curve -until the curve reaches it's maximum-
+ * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
+ * these 11 steps are spaced in a different way. This function returns
+ * the pcdac steps based on eeprom version and curve min/max so that we
+ * can have pcdac/pwr points.
+ */
+static inline void
+ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
+{
+	static const u16 intercepts3[] =
+		{ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
+	static const u16 intercepts3_2[] =
+		{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+	const u16 *ip;
+	int i;
+
+	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
+		ip = intercepts3_2;
+	else
+		ip = intercepts3;
+
+	for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
+		vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
+}
+
+/* Convert RF5111 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
+				struct ath5k_chan_pcal_info *chinfo)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info_rf5111 *pcinfo;
+	struct ath5k_pdgain_info *pd;
+	u8 pier, point, idx;
+	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+
+	/* Fill raw data for each calibration pier */
+	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+		pcinfo = &chinfo[pier].rf5111_info;
+
+		/* Allocate pd_curves for this cal pier */
+		chinfo[pier].pd_curves =
+			kcalloc(AR5K_EEPROM_N_PD_CURVES,
+				sizeof(struct ath5k_pdgain_info),
+				GFP_KERNEL);
+
+		if (!chinfo[pier].pd_curves)
+			return -ENOMEM;
+
+		/* Only one curve for RF5111
+		 * find out which one and place
+		 * in in pd_curves.
+		 * Note: ee_x_gain is reversed here */
+		for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
+
+			if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) {
+				pdgain_idx[0] = idx;
+				break;
+			}
+		}
+
+		ee->ee_pd_gains[mode] = 1;
+
+		pd = &chinfo[pier].pd_curves[idx];
+
+		pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111;
+
+		/* Allocate pd points for this curve */
+		pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
+					sizeof(u8), GFP_KERNEL);
+		if (!pd->pd_step)
+			return -ENOMEM;
+
+		pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
+					sizeof(s16), GFP_KERNEL);
+		if (!pd->pd_pwr)
+			return -ENOMEM;
+
+		/* Fill raw dataset
+		 * (convert power to 0.25dB units
+		 * for RF5112 combatibility) */
+		for (point = 0; point < pd->pd_points; point++) {
+
+			/* Absolute values */
+			pd->pd_pwr[point] = 2 * pcinfo->pwr[point];
+
+			/* Already sorted */
+			pd->pd_step[point] = pcinfo->pcdac[point];
+		}
+
+		/* Set min/max pwr */
+		chinfo[pier].min_pwr = pd->pd_pwr[0];
+		chinfo[pier].max_pwr = pd->pd_pwr[10];
+
+	}
+
+	return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info *pcal;
+	int offset, ret;
+	int i;
+	u16 val;
+
+	offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+	switch(mode) {
+	case AR5K_EEPROM_MODE_11A:
+		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+			return 0;
+
+		ret = ath5k_eeprom_init_11a_pcal_freq(ah,
+			offset + AR5K_EEPROM_GROUP1_OFFSET);
+		if (ret < 0)
+			return ret;
+
+		offset += AR5K_EEPROM_GROUP2_OFFSET;
+		pcal = ee->ee_pwr_cal_a;
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		if (!AR5K_EEPROM_HDR_11B(ee->ee_header) &&
+		    !AR5K_EEPROM_HDR_11G(ee->ee_header))
+			return 0;
+
+		pcal = ee->ee_pwr_cal_b;
+		offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+		/* fixed piers */
+		pcal[0].freq = 2412;
+		pcal[1].freq = 2447;
+		pcal[2].freq = 2484;
+		ee->ee_n_piers[mode] = 3;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+			return 0;
+
+		pcal = ee->ee_pwr_cal_g;
+		offset += AR5K_EEPROM_GROUP4_OFFSET;
+
+		/* fixed piers */
+		pcal[0].freq = 2312;
+		pcal[1].freq = 2412;
+		pcal[2].freq = 2484;
+		ee->ee_n_piers[mode] = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+		struct ath5k_chan_pcal_info_rf5111 *cdata =
+			&pcal[i].rf5111_info;
+
+		AR5K_EEPROM_READ(offset++, val);
+		cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M);
+		cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M);
+		cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M);
+
+		AR5K_EEPROM_READ(offset++, val);
+		cdata->pwr[0] |= ((val >> 14) & 0x3);
+		cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+		cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+		cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M);
+
+		AR5K_EEPROM_READ(offset++, val);
+		cdata->pwr[3] |= ((val >> 12) & 0xf);
+		cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M);
+		cdata->pwr[5] = (val  & AR5K_EEPROM_POWER_M);
+
+		AR5K_EEPROM_READ(offset++, val);
+		cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M);
+		cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M);
+		cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M);
+
+		AR5K_EEPROM_READ(offset++, val);
+		cdata->pwr[8] |= ((val >> 14) & 0x3);
+		cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+		cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+
+		ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
+			cdata->pcdac_max, cdata->pcdac);
+	}
+
+	return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
+}
+
+
+/*
+ * Read power calibration for RF5112 chips
+ *
+ * For RF5112 we have 4 XPD -eXternal Power Detector- curves
+ * for each calibrated channel on 0, -6, -12 and -18dbm but we only
+ * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
+ * power steps on x axis and PCDAC steps on y axis and looks like a
+ * linear function. To recreate the curve and pass the power values
+ * on hw, we read 4 points for xpd 0 (lower gain -> max power)
+ * and 3 points for xpd 3 (higher gain -> lower power) here and
+ * interpolate later.
+ *
+ * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
+ */
+
+/* Convert RF5112 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
+				struct ath5k_chan_pcal_info *chinfo)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info_rf5112 *pcinfo;
+	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+	unsigned int pier, pdg, point;
+
+	/* Fill raw data for each calibration pier */
+	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+		pcinfo = &chinfo[pier].rf5112_info;
+
+		/* Allocate pd_curves for this cal pier */
+		chinfo[pier].pd_curves =
+				kcalloc(AR5K_EEPROM_N_PD_CURVES,
+					sizeof(struct ath5k_pdgain_info),
+					GFP_KERNEL);
+
+		if (!chinfo[pier].pd_curves)
+			return -ENOMEM;
+
+		/* Fill pd_curves */
+		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+
+			u8 idx = pdgain_idx[pdg];
+			struct ath5k_pdgain_info *pd =
+					&chinfo[pier].pd_curves[idx];
+
+			/* Lowest gain curve (max power) */
+			if (pdg == 0) {
+				/* One more point for better accuracy */
+				pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS;
+
+				/* Allocate pd points for this curve */
+				pd->pd_step = kcalloc(pd->pd_points,
+						sizeof(u8), GFP_KERNEL);
+
+				if (!pd->pd_step)
+					return -ENOMEM;
+
+				pd->pd_pwr = kcalloc(pd->pd_points,
+						sizeof(s16), GFP_KERNEL);
+
+				if (!pd->pd_pwr)
+					return -ENOMEM;
+
+
+				/* Fill raw dataset
+				 * (all power levels are in 0.25dB units) */
+				pd->pd_step[0] = pcinfo->pcdac_x0[0];
+				pd->pd_pwr[0] = pcinfo->pwr_x0[0];
+
+				for (point = 1; point < pd->pd_points;
+				point++) {
+					/* Absolute values */
+					pd->pd_pwr[point] =
+						pcinfo->pwr_x0[point];
+
+					/* Deltas */
+					pd->pd_step[point] =
+						pd->pd_step[point - 1] +
+						pcinfo->pcdac_x0[point];
+				}
+
+				/* Set min power for this frequency */
+				chinfo[pier].min_pwr = pd->pd_pwr[0];
+
+			/* Highest gain curve (min power) */
+			} else if (pdg == 1) {
+
+				pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS;
+
+				/* Allocate pd points for this curve */
+				pd->pd_step = kcalloc(pd->pd_points,
+						sizeof(u8), GFP_KERNEL);
+
+				if (!pd->pd_step)
+					return -ENOMEM;
+
+				pd->pd_pwr = kcalloc(pd->pd_points,
+						sizeof(s16), GFP_KERNEL);
+
+				if (!pd->pd_pwr)
+					return -ENOMEM;
+
+				/* Fill raw dataset
+				 * (all power levels are in 0.25dB units) */
+				for (point = 0; point < pd->pd_points;
+				point++) {
+					/* Absolute values */
+					pd->pd_pwr[point] =
+						pcinfo->pwr_x3[point];
+
+					/* Fixed points */
+					pd->pd_step[point] =
+						pcinfo->pcdac_x3[point];
+				}
+
+				/* Since we have a higher gain curve
+				 * override min power */
+				chinfo[pier].min_pwr = pd->pd_pwr[0];
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
+	struct ath5k_chan_pcal_info *gen_chan_info;
+	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+	u32 offset;
+	u8 i, c;
+	u16 val;
+	int ret;
+	u8 pd_gains = 0;
+
+	/* Count how many curves we have and
+	 * identify them (which one of the 4
+	 * available curves we have on each count).
+	 * Curves are stored from lower (x0) to
+	 * higher (x3) gain */
+	for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) {
+		/* ee_x_gain[mode] is x gain mask */
+		if ((ee->ee_x_gain[mode] >> i) & 0x1)
+			pdgain_idx[pd_gains++] = i;
+	}
+	ee->ee_pd_gains[mode] = pd_gains;
+
+	if (pd_gains == 0 || pd_gains > 2)
+		return -EINVAL;
+
+	switch (mode) {
+	case AR5K_EEPROM_MODE_11A:
+		/*
+		 * Read 5GHz EEPROM channels
+		 */
+		offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+		ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+
+		offset += AR5K_EEPROM_GROUP2_OFFSET;
+		gen_chan_info = ee->ee_pwr_cal_a;
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+		if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+			offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+		/* NB: frequency piers parsed during mode init */
+		gen_chan_info = ee->ee_pwr_cal_b;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+		if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+			offset += AR5K_EEPROM_GROUP4_OFFSET;
+		else if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+			offset += AR5K_EEPROM_GROUP2_OFFSET;
+
+		/* NB: frequency piers parsed during mode init */
+		gen_chan_info = ee->ee_pwr_cal_g;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+		chan_pcal_info = &gen_chan_info[i].rf5112_info;
+
+		/* Power values in quarter dB
+		 * for the lower xpd gain curve
+		 * (0 dBm -> higher output power) */
+		for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
+			AR5K_EEPROM_READ(offset++, val);
+			chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff);
+			chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff);
+		}
+
+		/* PCDAC steps
+		 * corresponding to the above power
+		 * measurements */
+		AR5K_EEPROM_READ(offset++, val);
+		chan_pcal_info->pcdac_x0[1] = (val & 0x1f);
+		chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
+		chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
+
+		/* Power values in quarter dB
+		 * for the higher xpd gain curve
+		 * (18 dBm -> lower output power) */
+		AR5K_EEPROM_READ(offset++, val);
+		chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff);
+		chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff);
+
+		AR5K_EEPROM_READ(offset++, val);
+		chan_pcal_info->pwr_x3[2] = (val & 0xff);
+
+		/* PCDAC steps
+		 * corresponding to the above power
+		 * measurements (fixed) */
+		chan_pcal_info->pcdac_x3[0] = 20;
+		chan_pcal_info->pcdac_x3[1] = 35;
+		chan_pcal_info->pcdac_x3[2] = 63;
+
+		if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
+			chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f);
+
+			/* Last xpd0 power level is also channel maximum */
+			gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
+		} else {
+			chan_pcal_info->pcdac_x0[0] = 1;
+			gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff);
+		}
+
+	}
+
+	return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
+}
+
+
+/*
+ * Read power calibration for RF2413 chips
+ *
+ * For RF2413 we have a Power to PDDAC table (Power Detector)
+ * instead of a PCDAC and 4 pd gain curves for each calibrated channel.
+ * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y
+ * axis and looks like an exponential function like the RF5111 curve.
+ *
+ * To recreate the curves we read here the points and interpolate
+ * later. Note that in most cases only 2 (higher and lower) curves are
+ * used (like RF5112) but vendors have the oportunity to include all
+ * 4 curves on eeprom. The final curve (higher power) has an extra
+ * point for better accuracy like RF5112.
+ */
+
+/* For RF2413 power calibration data doesn't start on a fixed location and
+ * if a mode is not supported, it's section is missing -not zeroed-.
+ * So we need to calculate the starting offset for each section by using
+ * these two functions */
+
+/* Return the size of each section based on the mode and the number of pd
+ * gains available (maximum 4). */
+static inline unsigned int
+ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
+{
+	static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
+	unsigned int sz;
+
+	sz = pdgains_size[ee->ee_pd_gains[mode] - 1];
+	sz *= ee->ee_n_piers[mode];
+
+	return sz;
+}
+
+/* Return the starting offset for a section based on the modes supported
+ * and each section's size. */
+static unsigned int
+ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
+{
+	u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
+
+	switch(mode) {
+	case AR5K_EEPROM_MODE_11G:
+		if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+			offset += ath5k_pdgains_size_2413(ee,
+					AR5K_EEPROM_MODE_11B) +
+					AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+		/* fall through */
+	case AR5K_EEPROM_MODE_11B:
+		if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+			offset += ath5k_pdgains_size_2413(ee,
+					AR5K_EEPROM_MODE_11A) +
+					AR5K_EEPROM_N_5GHZ_CHAN / 2;
+		/* fall through */
+	case AR5K_EEPROM_MODE_11A:
+		break;
+	default:
+		break;
+	}
+
+	return offset;
+}
+
+/* Convert RF2413 specific data to generic raw data
+ * used by interpolation code */
+static int
+ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
+				struct ath5k_chan_pcal_info *chinfo)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+	unsigned int pier, pdg, point;
+
+	/* Fill raw data for each calibration pier */
+	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+
+		pcinfo = &chinfo[pier].rf2413_info;
+
+		/* Allocate pd_curves for this cal pier */
+		chinfo[pier].pd_curves =
+				kcalloc(AR5K_EEPROM_N_PD_CURVES,
+					sizeof(struct ath5k_pdgain_info),
+					GFP_KERNEL);
+
+		if (!chinfo[pier].pd_curves)
+			return -ENOMEM;
+
+		/* Fill pd_curves */
+		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+
+			u8 idx = pdgain_idx[pdg];
+			struct ath5k_pdgain_info *pd =
+					&chinfo[pier].pd_curves[idx];
+
+			/* One more point for the highest power
+			 * curve (lowest gain) */
+			if (pdg == ee->ee_pd_gains[mode] - 1)
+				pd->pd_points = AR5K_EEPROM_N_PD_POINTS;
+			else
+				pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1;
+
+			/* Allocate pd points for this curve */
+			pd->pd_step = kcalloc(pd->pd_points,
+					sizeof(u8), GFP_KERNEL);
+
+			if (!pd->pd_step)
+				return -ENOMEM;
+
+			pd->pd_pwr = kcalloc(pd->pd_points,
+					sizeof(s16), GFP_KERNEL);
+
+			if (!pd->pd_pwr)
+				return -ENOMEM;
+
+			/* Fill raw dataset
+			 * convert all pwr levels to
+			 * quarter dB for RF5112 combatibility */
+			pd->pd_step[0] = pcinfo->pddac_i[pdg];
+			pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
+
+			for (point = 1; point < pd->pd_points; point++) {
+
+				pd->pd_pwr[point] = pd->pd_pwr[point - 1] +
+					2 * pcinfo->pwr[pdg][point - 1];
+
+				pd->pd_step[point] = pd->pd_step[point - 1] +
+						pcinfo->pddac[pdg][point - 1];
+
+			}
+
+			/* Highest gain curve -> min power */
+			if (pdg == 0)
+				chinfo[pier].min_pwr = pd->pd_pwr[0];
+
+			/* Lowest gain curve -> max power */
+			if (pdg == ee->ee_pd_gains[mode] - 1)
+				chinfo[pier].max_pwr =
+					pd->pd_pwr[pd->pd_points - 1];
+		}
+	}
+
+	return 0;
+}
+
+/* Parse EEPROM data */
+static int
+ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info_rf2413 *pcinfo;
+	struct ath5k_chan_pcal_info *chinfo;
+	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
+	u32 offset;
+	int idx, i, ret;
+	u16 val;
+	u8 pd_gains = 0;
+
+	/* Count how many curves we have and
+	 * identify them (which one of the 4
+	 * available curves we have on each count).
+	 * Curves are stored from higher to
+	 * lower gain so we go backwards */
+	for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
+		/* ee_x_gain[mode] is x gain mask */
+		if ((ee->ee_x_gain[mode] >> idx) & 0x1)
+			pdgain_idx[pd_gains++] = idx;
+
+	}
+	ee->ee_pd_gains[mode] = pd_gains;
+
+	if (pd_gains == 0)
+		return -EINVAL;
+
+	offset = ath5k_cal_data_offset_2413(ee, mode);
+	switch (mode) {
+	case AR5K_EEPROM_MODE_11A:
+		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+			return 0;
+
+		ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+		offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
+		chinfo = ee->ee_pwr_cal_a;
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+			return 0;
+
+		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+		chinfo = ee->ee_pwr_cal_b;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+			return 0;
+
+		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+		chinfo = ee->ee_pwr_cal_g;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+		pcinfo = &chinfo[i].rf2413_info;
+
+		/*
+		 * Read pwr_i, pddac_i and the first
+		 * 2 pd points (pwr, pddac)
+		 */
+		AR5K_EEPROM_READ(offset++, val);
+		pcinfo->pwr_i[0] = val & 0x1f;
+		pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
+		pcinfo->pwr[0][0] = (val >> 12) & 0xf;
+
+		AR5K_EEPROM_READ(offset++, val);
+		pcinfo->pddac[0][0] = val & 0x3f;
+		pcinfo->pwr[0][1] = (val >> 6) & 0xf;
+		pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
+
+		AR5K_EEPROM_READ(offset++, val);
+		pcinfo->pwr[0][2] = val & 0xf;
+		pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
+
+		pcinfo->pwr[0][3] = 0;
+		pcinfo->pddac[0][3] = 0;
+
+		if (pd_gains > 1) {
+			/*
+			 * Pd gain 0 is not the last pd gain
+			 * so it only has 2 pd points.
+			 * Continue wih pd gain 1.
+			 */
+			pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
+
+			pcinfo->pddac_i[1] = (val >> 15) & 0x1;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
+
+			pcinfo->pwr[1][0] = (val >> 6) & 0xf;
+			pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
+
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pwr[1][1] = val & 0xf;
+			pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
+			pcinfo->pwr[1][2] = (val >> 10) & 0xf;
+
+			pcinfo->pddac[1][2] = (val >> 14) & 0x3;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pddac[1][2] |= (val & 0xF) << 2;
+
+			pcinfo->pwr[1][3] = 0;
+			pcinfo->pddac[1][3] = 0;
+		} else if (pd_gains == 1) {
+			/*
+			 * Pd gain 0 is the last one so
+			 * read the extra point.
+			 */
+			pcinfo->pwr[0][3] = (val >> 10) & 0xf;
+
+			pcinfo->pddac[0][3] = (val >> 14) & 0x3;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pddac[0][3] |= (val & 0xF) << 2;
+		}
+
+		/*
+		 * Proceed with the other pd_gains
+		 * as above.
+		 */
+		if (pd_gains > 2) {
+			pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
+			pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
+
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pwr[2][0] = (val >> 0) & 0xf;
+			pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
+			pcinfo->pwr[2][1] = (val >> 10) & 0xf;
+
+			pcinfo->pddac[2][1] = (val >> 14) & 0x3;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pddac[2][1] |= (val & 0xF) << 2;
+
+			pcinfo->pwr[2][2] = (val >> 4) & 0xf;
+			pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
+
+			pcinfo->pwr[2][3] = 0;
+			pcinfo->pddac[2][3] = 0;
+		} else if (pd_gains == 2) {
+			pcinfo->pwr[1][3] = (val >> 4) & 0xf;
+			pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
+		}
+
+		if (pd_gains > 3) {
+			pcinfo->pwr_i[3] = (val >> 14) & 0x3;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
+
+			pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
+			pcinfo->pwr[3][0] = (val >> 10) & 0xf;
+			pcinfo->pddac[3][0] = (val >> 14) & 0x3;
+
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pddac[3][0] |= (val & 0xF) << 2;
+			pcinfo->pwr[3][1] = (val >> 4) & 0xf;
+			pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
+
+			pcinfo->pwr[3][2] = (val >> 14) & 0x3;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
+
+			pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
+			pcinfo->pwr[3][3] = (val >> 8) & 0xf;
+
+			pcinfo->pddac[3][3] = (val >> 12) & 0xF;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
+		} else if (pd_gains == 3) {
+			pcinfo->pwr[2][3] = (val >> 14) & 0x3;
+			AR5K_EEPROM_READ(offset++, val);
+			pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
+
+			pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
+		}
+	}
+
+	return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
+}
+
+
+/*
+ * Read per rate target power (this is the maximum tx power
+ * supported by the card). This info is used when setting
+ * tx power, no matter the channel.
+ *
+ * This also works for v5 EEPROMs.
+ */
+static int
+ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_rate_pcal_info *rate_pcal_info;
+	u8 *rate_target_pwr_num;
+	u32 offset;
+	u16 val;
+	int ret, i;
+
+	offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
+	rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
+	switch (mode) {
+	case AR5K_EEPROM_MODE_11A:
+		offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
+		rate_pcal_info = ee->ee_rate_tpwr_a;
+		ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
+		rate_pcal_info = ee->ee_rate_tpwr_b;
+		ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
+		rate_pcal_info = ee->ee_rate_tpwr_g;
+		ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Different freq mask for older eeproms (<= v3.2) */
+	if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) {
+		for (i = 0; i < (*rate_target_pwr_num); i++) {
+			AR5K_EEPROM_READ(offset++, val);
+			rate_pcal_info[i].freq =
+			    ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
+
+			rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
+			rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
+
+			AR5K_EEPROM_READ(offset++, val);
+
+			if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+			    val == 0) {
+				(*rate_target_pwr_num) = i;
+				break;
+			}
+
+			rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
+			rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
+			rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
+		}
+	} else {
+		for (i = 0; i < (*rate_target_pwr_num); i++) {
+			AR5K_EEPROM_READ(offset++, val);
+			rate_pcal_info[i].freq =
+			    ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+
+			rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
+			rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
+
+			AR5K_EEPROM_READ(offset++, val);
+
+			if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+			    val == 0) {
+				(*rate_target_pwr_num) = i;
+				break;
+			}
+
+			rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
+			rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
+			rate_pcal_info[i].target_power_54 = (val & 0x3f);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Read per channel calibration info from EEPROM
+ *
+ * This info is used to calibrate the baseband power table. Imagine
+ * that for each channel there is a power curve that's hw specific
+ * (depends on amplifier etc) and we try to "correct" this curve using
+ * offests we pass on to phy chip (baseband -> before amplifier) so that
+ * it can use accurate power values when setting tx power (takes amplifier's
+ * performance on each channel into account).
+ *
+ * EEPROM provides us with the offsets for some pre-calibrated channels
+ * and we have to interpolate to create the full table for these channels and
+ * also the table for any channel.
+ */
+static int
+ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	int (*read_pcal)(struct ath5k_hw *hw, int mode);
+	int mode;
+	int err;
+
+	if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) &&
+			(AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1))
+		read_pcal = ath5k_eeprom_read_pcal_info_5112;
+	else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) &&
+			(AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2))
+		read_pcal = ath5k_eeprom_read_pcal_info_2413;
+	else
+		read_pcal = ath5k_eeprom_read_pcal_info_5111;
+
+
+	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G;
+	mode++) {
+		err = read_pcal(ah, mode);
+		if (err)
+			return err;
+
+		err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info *chinfo;
+	u8 pier, pdg;
+
+	switch (mode) {
+	case AR5K_EEPROM_MODE_11A:
+		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+			return 0;
+		chinfo = ee->ee_pwr_cal_a;
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+			return 0;
+		chinfo = ee->ee_pwr_cal_b;
+		break;
+	case AR5K_EEPROM_MODE_11G:
+		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+			return 0;
+		chinfo = ee->ee_pwr_cal_g;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
+		if (!chinfo[pier].pd_curves)
+			continue;
+
+		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
+			struct ath5k_pdgain_info *pd =
+					&chinfo[pier].pd_curves[pdg];
+
+			if (pd != NULL) {
+				kfree(pd->pd_step);
+				kfree(pd->pd_pwr);
+			}
+		}
+
+		kfree(chinfo[pier].pd_curves);
+	}
+
+	return 0;
+}
+
+void
+ath5k_eeprom_detach(struct ath5k_hw *ah)
+{
+	u8 mode;
+
+	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
+		ath5k_eeprom_free_pcal_info(ah, mode);
+}
+
+/* Read conformance test limits used for regulatory control */
+static int
+ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_edge_power *rep;
+	unsigned int fmask, pmask;
+	unsigned int ctl_mode;
+	int ret, i, j;
+	u32 offset;
+	u16 val;
+
+	pmask = AR5K_EEPROM_POWER_M;
+	fmask = AR5K_EEPROM_FREQ_M(ee->ee_version);
+	offset = AR5K_EEPROM_CTL(ee->ee_version);
+	ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version);
+	for (i = 0; i < ee->ee_ctls; i += 2) {
+		AR5K_EEPROM_READ(offset++, val);
+		ee->ee_ctl[i] = (val >> 8) & 0xff;
+		ee->ee_ctl[i + 1] = val & 0xff;
+	}
+
+	offset = AR5K_EEPROM_GROUP8_OFFSET;
+	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
+		offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) -
+			AR5K_EEPROM_GROUP5_OFFSET;
+	else
+		offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
+
+	rep = ee->ee_ctl_pwr;
+	for(i = 0; i < ee->ee_ctls; i++) {
+		switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
+		case AR5K_CTL_11A:
+		case AR5K_CTL_TURBO:
+			ctl_mode = AR5K_EEPROM_MODE_11A;
+			break;
+		default:
+			ctl_mode = AR5K_EEPROM_MODE_11G;
+			break;
+		}
+		if (ee->ee_ctl[i] == 0) {
+			if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3)
+				offset += 8;
+			else
+				offset += 7;
+			rep += AR5K_EEPROM_N_EDGES;
+			continue;
+		}
+		if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+			for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+				AR5K_EEPROM_READ(offset++, val);
+				rep[j].freq = (val >> 8) & fmask;
+				rep[j + 1].freq = val & fmask;
+			}
+			for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+				AR5K_EEPROM_READ(offset++, val);
+				rep[j].edge = (val >> 8) & pmask;
+				rep[j].flag = (val >> 14) & 1;
+				rep[j + 1].edge = val & pmask;
+				rep[j + 1].flag = (val >> 6) & 1;
+			}
+		} else {
+			AR5K_EEPROM_READ(offset++, val);
+			rep[0].freq = (val >> 9) & fmask;
+			rep[1].freq = (val >> 2) & fmask;
+			rep[2].freq = (val << 5) & fmask;
+
+			AR5K_EEPROM_READ(offset++, val);
+			rep[2].freq |= (val >> 11) & 0x1f;
+			rep[3].freq = (val >> 4) & fmask;
+			rep[4].freq = (val << 3) & fmask;
+
+			AR5K_EEPROM_READ(offset++, val);
+			rep[4].freq |= (val >> 13) & 0x7;
+			rep[5].freq = (val >> 6) & fmask;
+			rep[6].freq = (val << 1) & fmask;
+
+			AR5K_EEPROM_READ(offset++, val);
+			rep[6].freq |= (val >> 15) & 0x1;
+			rep[7].freq = (val >> 8) & fmask;
+
+			rep[0].edge = (val >> 2) & pmask;
+			rep[1].edge = (val << 4) & pmask;
+
+			AR5K_EEPROM_READ(offset++, val);
+			rep[1].edge |= (val >> 12) & 0xf;
+			rep[2].edge = (val >> 6) & pmask;
+			rep[3].edge = val & pmask;
+
+			AR5K_EEPROM_READ(offset++, val);
+			rep[4].edge = (val >> 10) & pmask;
+			rep[5].edge = (val >> 4) & pmask;
+			rep[6].edge = (val << 2) & pmask;
+
+			AR5K_EEPROM_READ(offset++, val);
+			rep[6].edge |= (val >> 14) & 0x3;
+			rep[7].edge = (val >> 8) & pmask;
+		}
+		for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) {
+			rep[j].freq = ath5k_eeprom_bin2freq(ee,
+				rep[j].freq, ctl_mode);
+		}
+		rep += AR5K_EEPROM_N_EDGES;
+	}
+
+	return 0;
+}
+
+static int
+ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 offset;
+	u16 val;
+	int ret = 0, i;
+
+	offset = AR5K_EEPROM_CTL(ee->ee_version) +
+				AR5K_EEPROM_N_CTLS(ee->ee_version);
+
+	if (ee->ee_version < AR5K_EEPROM_VERSION_5_3) {
+		/* No spur info for 5GHz */
+		ee->ee_spur_chans[0][0] = AR5K_EEPROM_NO_SPUR;
+		/* 2 channels for 2GHz (2464/2420) */
+		ee->ee_spur_chans[0][1] = AR5K_EEPROM_5413_SPUR_CHAN_1;
+		ee->ee_spur_chans[1][1] = AR5K_EEPROM_5413_SPUR_CHAN_2;
+		ee->ee_spur_chans[2][1] = AR5K_EEPROM_NO_SPUR;
+	} else if (ee->ee_version >= AR5K_EEPROM_VERSION_5_3) {
+		for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) {
+			AR5K_EEPROM_READ(offset, val);
+			ee->ee_spur_chans[i][0] = val;
+			AR5K_EEPROM_READ(offset + AR5K_EEPROM_N_SPUR_CHANS,
+									val);
+			ee->ee_spur_chans[i][1] = val;
+			offset++;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Initialize eeprom data structure
+ */
+int
+ath5k_eeprom_init(struct ath5k_hw *ah)
+{
+	int err;
+
+	err = ath5k_eeprom_init_header(ah);
+	if (err < 0)
+		return err;
+
+	err = ath5k_eeprom_init_modes(ah);
+	if (err < 0)
+		return err;
+
+	err = ath5k_eeprom_read_pcal_info(ah);
+	if (err < 0)
+		return err;
+
+	err = ath5k_eeprom_read_ctl_info(ah);
+	if (err < 0)
+		return err;
+
+	err = ath5k_eeprom_read_spur_chans(ah);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+/*
+ * Read the MAC address from eeprom
+ */
+int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+	u8 mac_d[ETH_ALEN] = {};
+	u32 total, offset;
+	u16 data;
+	int octet, ret;
+
+	ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
+	if (ret)
+		return ret;
+
+	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+		ret = ath5k_hw_eeprom_read(ah, offset, &data);
+		if (ret)
+			return ret;
+
+		total += data;
+		mac_d[octet + 1] = data & 0xff;
+		mac_d[octet] = data >> 8;
+		octet += 2;
+	}
+
+	if (!total || total == 3 * 0xffff)
+		return -EINVAL;
+
+	memcpy(mac, mac_d, ETH_ALEN);
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/eeprom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/eeprom.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
+ */
+#define AR5K_EEPROM_MAGIC		0x003d	/* EEPROM Magic number */
+#define AR5K_EEPROM_MAGIC_VALUE		0x5aa5	/* Default - found on EEPROM */
+#define AR5K_EEPROM_MAGIC_5212		0x0000145c /* 5212 */
+#define AR5K_EEPROM_MAGIC_5211		0x0000145b /* 5211 */
+#define AR5K_EEPROM_MAGIC_5210		0x0000145a /* 5210 */
+
+#define	AR5K_EEPROM_IS_HB63		0x000b	/* Talon detect */
+
+#define AR5K_EEPROM_RFKILL		0x0f
+#define AR5K_EEPROM_RFKILL_GPIO_SEL	0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S	2
+#define AR5K_EEPROM_RFKILL_POLARITY	0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S	1
+
+#define AR5K_EEPROM_REG_DOMAIN		0x00bf	/* EEPROM regdom */
+#define AR5K_EEPROM_CHECKSUM		0x00c0	/* EEPROM checksum */
+#define AR5K_EEPROM_INFO_BASE		0x00c0	/* EEPROM header */
+#define AR5K_EEPROM_INFO_MAX		(0x400 - AR5K_EEPROM_INFO_BASE)
+#define AR5K_EEPROM_INFO_CKSUM		0xffff
+#define AR5K_EEPROM_INFO(_n)		(AR5K_EEPROM_INFO_BASE + (_n))
+
+#define AR5K_EEPROM_VERSION		AR5K_EEPROM_INFO(1)	/* EEPROM Version */
+#define AR5K_EEPROM_VERSION_3_0		0x3000	/* No idea what's going on before this version */
+#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_2		0x3002	/* different frequency representation (eeprom_bin2freq) */
+#define AR5K_EEPROM_VERSION_3_3		0x3003	/* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_3_4		0x3004	/* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_4_0		0x4000	/* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_1		0x4001	/* has ee_margin_tx_rx (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_2		0x4002	/* has ee_cck_ofdm_gain_delta (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_3		0x4003	/* power calibration changes */
+#define AR5K_EEPROM_VERSION_4_4		0x4004
+#define AR5K_EEPROM_VERSION_4_5		0x4005
+#define AR5K_EEPROM_VERSION_4_6		0x4006	/* has ee_scaled_cck_delta */
+#define AR5K_EEPROM_VERSION_4_7		0x3007	/* 4007 ? */
+#define AR5K_EEPROM_VERSION_4_9		0x4009	/* EAR futureproofing */
+#define AR5K_EEPROM_VERSION_5_0		0x5000	/* Has 2413 PDADC calibration etc */
+#define AR5K_EEPROM_VERSION_5_1		0x5001	/* Has capability values */
+#define AR5K_EEPROM_VERSION_5_3		0x5003	/* Has spur mitigation tables */
+
+#define AR5K_EEPROM_MODE_11A		0
+#define AR5K_EEPROM_MODE_11B		1
+#define AR5K_EEPROM_MODE_11G		2
+
+#define AR5K_EEPROM_HDR			AR5K_EEPROM_INFO(2)	/* Header that contains the device caps */
+#define AR5K_EEPROM_HDR_11A(_v)		(((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
+#define AR5K_EEPROM_HDR_11B(_v)		(((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
+#define AR5K_EEPROM_HDR_11G(_v)		(((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2Ghz (?) */
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v)	(((_v) >> 4) & 0x7f)	/* Max turbo power for a/XR mode (eeprom_init) */
+#define AR5K_EEPROM_HDR_DEVICE(_v)	(((_v) >> 11) & 0x7)
+#define AR5K_EEPROM_HDR_RFKILL(_v)	(((_v) >> 14) & 0x1)	/* Device has RFKill support */
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5Ghz */
+
+/* Newer EEPROMs are using a different offset */
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
+	(((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
+
+#define AR5K_EEPROM_ANT_GAIN(_v)	AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v)	((s8)(((_v) >> 8) & 0xff))
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v)	((s8)((_v) & 0xff))
+
+/* Misc values available since EEPROM 4.0 */
+#define AR5K_EEPROM_MISC0		AR5K_EEPROM_INFO(4)
+#define AR5K_EEPROM_EARSTART(_v)	((_v) & 0xfff)
+#define AR5K_EEPROM_HDR_XR2_DIS(_v)	(((_v) >> 12) & 0x1)
+#define AR5K_EEPROM_HDR_XR5_DIS(_v)	(((_v) >> 13) & 0x1)
+#define AR5K_EEPROM_EEMAP(_v)		(((_v) >> 14) & 0x3)
+
+#define AR5K_EEPROM_MISC1			AR5K_EEPROM_INFO(5)
+#define AR5K_EEPROM_TARGET_PWRSTART(_v)		((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)		(((_v) >> 14) & 0x1)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v)	(((_v) >> 15) & 0x1)
+
+#define AR5K_EEPROM_MISC2			AR5K_EEPROM_INFO(6)
+#define AR5K_EEPROM_EEP_FILE_VERSION(_v)	(((_v) >> 8) & 0xff)
+#define AR5K_EEPROM_EAR_FILE_VERSION(_v)	((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC3		AR5K_EEPROM_INFO(7)
+#define AR5K_EEPROM_ART_BUILD_NUM(_v)	(((_v) >> 10) & 0x3f)
+#define AR5K_EEPROM_EAR_FILE_ID(_v)	((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC4		AR5K_EEPROM_INFO(8)
+#define AR5K_EEPROM_CAL_DATA_START(_v)	(((_v) >> 4) & 0xfff)
+#define AR5K_EEPROM_MASK_R0(_v)		(((_v) >> 2) & 0x3)
+#define AR5K_EEPROM_MASK_R1(_v)		((_v) & 0x3)
+
+#define AR5K_EEPROM_MISC5		AR5K_EEPROM_INFO(9)
+#define AR5K_EEPROM_COMP_DIS(_v)	((_v) & 0x1)
+#define AR5K_EEPROM_AES_DIS(_v)		(((_v) >> 1) & 0x1)
+#define AR5K_EEPROM_FF_DIS(_v)		(((_v) >> 2) & 0x1)
+#define AR5K_EEPROM_BURST_DIS(_v)	(((_v) >> 3) & 0x1)
+#define AR5K_EEPROM_MAX_QCU(_v)		(((_v) >> 4) & 0xf)
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v)	(((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_KEY_CACHE_SIZE(_v)	(((_v) >> 12) & 0xf)
+
+#define AR5K_EEPROM_MISC6		AR5K_EEPROM_INFO(10)
+#define AR5K_EEPROM_TX_CHAIN_DIS	((_v) & 0x8)
+#define AR5K_EEPROM_RX_CHAIN_DIS	(((_v) >> 3) & 0x8)
+#define AR5K_EEPROM_FCC_MID_EN		(((_v) >> 6) & 0x1)
+#define AR5K_EEPROM_JAP_U1EVEN_EN	(((_v) >> 7) & 0x1)
+#define AR5K_EEPROM_JAP_U2_EN		(((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_JAP_U1ODD_EN	(((_v) >> 9) & 0x1)
+#define AR5K_EEPROM_JAP_11A_NEW_EN	(((_v) >> 10) & 0x1)
+
+/* calibration settings */
+#define AR5K_EEPROM_MODES_11A(_v)	AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
+#define AR5K_EEPROM_MODES_11B(_v)	AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
+#define AR5K_EEPROM_MODES_11G(_v)	AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
+#define AR5K_EEPROM_CTL(_v)		AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128)	/* Conformance test limits */
+#define AR5K_EEPROM_GROUPS_START(_v)	AR5K_EEPROM_OFF(_v, 0x0100, 0x0150)	/* Start of Groups */
+#define AR5K_EEPROM_GROUP1_OFFSET	0x0
+#define AR5K_EEPROM_GROUP2_OFFSET	0x5
+#define AR5K_EEPROM_GROUP3_OFFSET	0x37
+#define AR5K_EEPROM_GROUP4_OFFSET	0x46
+#define AR5K_EEPROM_GROUP5_OFFSET	0x55
+#define AR5K_EEPROM_GROUP6_OFFSET	0x65
+#define AR5K_EEPROM_GROUP7_OFFSET	0x69
+#define AR5K_EEPROM_GROUP8_OFFSET	0x6f
+
+#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+								AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+								AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+								AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
+
+/* [3.1 - 3.3] */
+#define AR5K_EEPROM_OBDB0_2GHZ		0x00ec
+#define AR5K_EEPROM_OBDB1_2GHZ		0x00ed
+
+#define AR5K_EEPROM_PROTECT		0x003f	/* EEPROM protect status */
+#define AR5K_EEPROM_PROTECT_RD_0_31	0x0001	/* Read protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_WR_0_31	0x0002	/* Write protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_RD_32_63	0x0004	/* 0x20 - 0x3f */
+#define AR5K_EEPROM_PROTECT_WR_32_63	0x0008
+#define AR5K_EEPROM_PROTECT_RD_64_127	0x0010	/* 0x40 - 0x7f */
+#define AR5K_EEPROM_PROTECT_WR_64_127	0x0020
+#define AR5K_EEPROM_PROTECT_RD_128_191	0x0040	/* 0x80 - 0xbf (regdom) */
+#define AR5K_EEPROM_PROTECT_WR_128_191	0x0080
+#define AR5K_EEPROM_PROTECT_RD_192_207	0x0100	/* 0xc0 - 0xcf */
+#define AR5K_EEPROM_PROTECT_WR_192_207	0x0200
+#define AR5K_EEPROM_PROTECT_RD_208_223	0x0400	/* 0xd0 - 0xdf */
+#define AR5K_EEPROM_PROTECT_WR_208_223	0x0800
+#define AR5K_EEPROM_PROTECT_RD_224_239	0x1000	/* 0xe0 - 0xef */
+#define AR5K_EEPROM_PROTECT_WR_224_239	0x2000
+#define AR5K_EEPROM_PROTECT_RD_240_255	0x4000	/* 0xf0 - 0xff */
+#define AR5K_EEPROM_PROTECT_WR_240_255	0x8000
+
+/* Some EEPROM defines */
+#define AR5K_EEPROM_EEP_SCALE		100
+#define AR5K_EEPROM_EEP_DELTA		10
+#define AR5K_EEPROM_N_MODES		3
+#define AR5K_EEPROM_N_5GHZ_CHAN		10
+#define AR5K_EEPROM_N_2GHZ_CHAN		3
+#define AR5K_EEPROM_N_2GHZ_CHAN_2413	4
+#define	AR5K_EEPROM_N_2GHZ_CHAN_MAX	4
+#define AR5K_EEPROM_MAX_CHAN		10
+#define AR5K_EEPROM_N_PWR_POINTS_5111	11
+#define AR5K_EEPROM_N_PCDAC		11
+#define AR5K_EEPROM_N_PHASE_CAL		5
+#define AR5K_EEPROM_N_TEST_FREQ		8
+#define AR5K_EEPROM_N_EDGES		8
+#define AR5K_EEPROM_N_INTERCEPTS	11
+#define AR5K_EEPROM_FREQ_M(_v)		AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
+#define AR5K_EEPROM_PCDAC_M		0x3f
+#define AR5K_EEPROM_PCDAC_START		1
+#define AR5K_EEPROM_PCDAC_STOP		63
+#define AR5K_EEPROM_PCDAC_STEP		1
+#define AR5K_EEPROM_NON_EDGE_M		0x40
+#define AR5K_EEPROM_CHANNEL_POWER	8
+#define AR5K_EEPROM_N_OBDB		4
+#define AR5K_EEPROM_OBDB_DIS		0xffff
+#define AR5K_EEPROM_CHANNEL_DIS		0xff
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x)	(((_x) * 2) / 10)
+#define AR5K_EEPROM_N_CTLS(_v)		AR5K_EEPROM_OFF(_v, 16, 32)
+#define AR5K_EEPROM_MAX_CTLS		32
+#define AR5K_EEPROM_N_PD_CURVES		4
+#define AR5K_EEPROM_N_XPD0_POINTS	4
+#define AR5K_EEPROM_N_XPD3_POINTS	3
+#define AR5K_EEPROM_N_PD_GAINS		4
+#define AR5K_EEPROM_N_PD_POINTS		5
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ	35
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ	55
+#define AR5K_EEPROM_POWER_M		0x3f
+#define AR5K_EEPROM_POWER_MIN		0
+#define AR5K_EEPROM_POWER_MAX		3150
+#define AR5K_EEPROM_POWER_STEP		50
+#define AR5K_EEPROM_POWER_TABLE_SIZE	64
+#define AR5K_EEPROM_N_POWER_LOC_11B	4
+#define AR5K_EEPROM_N_POWER_LOC_11G	6
+#define AR5K_EEPROM_I_GAIN		10
+#define AR5K_EEPROM_CCK_OFDM_DELTA	15
+#define AR5K_EEPROM_N_IQ_CAL		2
+/* 5GHz/2GHz */
+enum ath5k_eeprom_freq_bands{
+	AR5K_EEPROM_BAND_5GHZ = 0,
+	AR5K_EEPROM_BAND_2GHZ = 1,
+	AR5K_EEPROM_N_FREQ_BANDS,
+};
+/* Spur chans per freq band */
+#define	AR5K_EEPROM_N_SPUR_CHANS	5
+/* fbin value for chan 2464 x2 */
+#define	AR5K_EEPROM_5413_SPUR_CHAN_1	1640
+/* fbin value for chan 2420 x2 */
+#define	AR5K_EEPROM_5413_SPUR_CHAN_2	1200
+#define	AR5K_EEPROM_SPUR_CHAN_MASK	0x3FFF
+#define	AR5K_EEPROM_NO_SPUR		0x8000
+#define	AR5K_SPUR_CHAN_WIDTH			87
+#define	AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz	3125
+#define	AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz	6250
+
+#define AR5K_EEPROM_READ(_o, _v) do {			\
+	ret = ath5k_hw_eeprom_read(ah, (_o), &(_v));	\
+	if (ret)					\
+		return ret;				\
+} while (0)
+
+#define AR5K_EEPROM_READ_HDR(_o, _v)					\
+	AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v);	\
+
+enum ath5k_ant_table {
+	AR5K_ANT_CTL		= 0,	/* Idle switch table settings */
+	AR5K_ANT_SWTABLE_A	= 1,	/* Switch table for antenna A */
+	AR5K_ANT_SWTABLE_B	= 2,	/* Switch table for antenna B */
+	AR5K_ANT_MAX,
+};
+
+enum ath5k_ctl_mode {
+	AR5K_CTL_11A = 0,
+	AR5K_CTL_11B = 1,
+	AR5K_CTL_11G = 2,
+	AR5K_CTL_TURBO = 3,
+	AR5K_CTL_TURBOG = 4,
+	AR5K_CTL_2GHT20 = 5,
+	AR5K_CTL_5GHT20 = 6,
+	AR5K_CTL_2GHT40 = 7,
+	AR5K_CTL_5GHT40 = 8,
+	AR5K_CTL_MODE_M = 15,
+};
+
+/* Default CTL ids for the 3 main reg domains.
+ * Atheros only uses these by default but vendors
+ * can have up to 32 different CTLs for different
+ * scenarios. Note that theese values are ORed with
+ * the mode id (above) so we can have up to 24 CTL
+ * datasets out of these 3 main regdomains. That leaves
+ * 8 ids that can be used by vendors and since 0x20 is
+ * missing from HAL sources i guess this is the set of
+ * custom CTLs vendors can use. */
+#define	AR5K_CTL_FCC	0x10
+#define	AR5K_CTL_CUSTOM	0x20
+#define	AR5K_CTL_ETSI	0x30
+#define	AR5K_CTL_MKK	0x40
+
+/* Indicates a CTL with only mode set and
+ * no reg domain mapping, such CTLs are used
+ * for world roaming domains or simply when
+ * a reg domain is not set */
+#define	AR5K_CTL_NO_REGDOMAIN	0xf0
+
+/* Indicates an empty (invalid) CTL */
+#define AR5K_CTL_NO_CTL		0xff
+
+/* Per channel calibration data, used for power table setup */
+struct ath5k_chan_pcal_info_rf5111 {
+	/* Power levels in half dbm units
+	 * for one power curve. */
+	u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
+	/* PCDAC table steps
+	 * for the above values */
+	u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
+	/* Starting PCDAC step */
+	u8 pcdac_min;
+	/* Final PCDAC step */
+	u8 pcdac_max;
+};
+
+struct ath5k_chan_pcal_info_rf5112 {
+	/* Power levels in quarter dBm units
+	 * for lower (0) and higher (3)
+	 * level curves in 0.25dB units */
+	s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
+	s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
+	/* PCDAC table steps
+	 * for the above values */
+	u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
+	u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
+};
+
+struct ath5k_chan_pcal_info_rf2413 {
+	/* Starting pwr/pddac values */
+	s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
+	u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
+	/* (pwr,pddac) points
+	 * power levels in 0.5dB units */
+	s8 pwr[AR5K_EEPROM_N_PD_GAINS]
+		[AR5K_EEPROM_N_PD_POINTS];
+	u8 pddac[AR5K_EEPROM_N_PD_GAINS]
+		[AR5K_EEPROM_N_PD_POINTS];
+};
+
+enum ath5k_powertable_type {
+	AR5K_PWRTABLE_PWR_TO_PCDAC = 0,
+	AR5K_PWRTABLE_LINEAR_PCDAC = 1,
+	AR5K_PWRTABLE_PWR_TO_PDADC = 2,
+};
+
+struct ath5k_pdgain_info {
+	u8 pd_points;
+	u8 *pd_step;
+	/* Power values are in
+	 * 0.25dB units */
+	s16 *pd_pwr;
+};
+
+struct ath5k_chan_pcal_info {
+	/* Frequency */
+	u16	freq;
+	/* Tx power boundaries */
+	s16	max_pwr;
+	s16	min_pwr;
+	union {
+		struct ath5k_chan_pcal_info_rf5111 rf5111_info;
+		struct ath5k_chan_pcal_info_rf5112 rf5112_info;
+		struct ath5k_chan_pcal_info_rf2413 rf2413_info;
+	};
+	/* Raw values used by phy code
+	 * Curves are stored in order from lower
+	 * gain to higher gain (max txpower -> min txpower) */
+	struct ath5k_pdgain_info *pd_curves;
+};
+
+/* Per rate calibration data for each mode,
+ * used for rate power table setup.
+ * Note: Values in 0.5dB units */
+struct ath5k_rate_pcal_info {
+	u16	freq; /* Frequency */
+	/* Power level for 6-24Mbit/s rates or
+	 * 1Mb rate */
+	u16	target_power_6to24;
+	/* Power level for 36Mbit rate or
+	 * 2Mb rate */
+	u16	target_power_36;
+	/* Power level for 48Mbit rate or
+	 * 5.5Mbit rate */
+	u16	target_power_48;
+	/* Power level for 54Mbit rate or
+	 * 11Mbit rate */
+	u16	target_power_54;
+};
+
+/* Power edges for conformance test limits */
+struct ath5k_edge_power {
+	u16 freq;
+	u16 edge; /* in half dBm */
+	bool flag;
+};
+
+/* EEPROM calibration data */
+struct ath5k_eeprom_info {
+
+	/* Header information */
+	u16	ee_magic;
+	u16	ee_protect;
+	u16	ee_regdomain;
+	u16	ee_version;
+	u16	ee_header;
+	u16	ee_ant_gain;
+	u8	ee_rfkill_pin;
+	bool	ee_rfkill_pol;
+	bool	ee_is_hb63;
+	u16	ee_misc0;
+	u16	ee_misc1;
+	u16	ee_misc2;
+	u16	ee_misc3;
+	u16	ee_misc4;
+	u16	ee_misc5;
+	u16	ee_misc6;
+	u16	ee_cck_ofdm_gain_delta;
+	u16	ee_cck_ofdm_power_delta;
+	u16	ee_scaled_cck_delta;
+
+	/* RF Calibration settings (reset, rfregs) */
+	u16	ee_i_cal[AR5K_EEPROM_N_MODES];
+	u16	ee_q_cal[AR5K_EEPROM_N_MODES];
+	u16	ee_fixed_bias[AR5K_EEPROM_N_MODES];
+	u16	ee_turbo_max_power[AR5K_EEPROM_N_MODES];
+	u16	ee_xr_power[AR5K_EEPROM_N_MODES];
+	u16	ee_switch_settling[AR5K_EEPROM_N_MODES];
+	u16	ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
+	u16	ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
+	u16	ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+	u16	ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+	u16	ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
+	u16	ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
+	u16	ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
+	u16	ee_thr_62[AR5K_EEPROM_N_MODES];
+	u16	ee_xlna_gain[AR5K_EEPROM_N_MODES];
+	u16	ee_xpd[AR5K_EEPROM_N_MODES];
+	u16	ee_x_gain[AR5K_EEPROM_N_MODES];
+	u16	ee_i_gain[AR5K_EEPROM_N_MODES];
+	u16	ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
+	u16	ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
+	u16	ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
+	u16	ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
+
+	/* Power calibration data */
+	u16	ee_false_detect[AR5K_EEPROM_N_MODES];
+
+	/* Number of pd gain curves per mode */
+	u8	ee_pd_gains[AR5K_EEPROM_N_MODES];
+	/* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */
+	u8	ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS];
+
+	u8	ee_n_piers[AR5K_EEPROM_N_MODES];
+	struct ath5k_chan_pcal_info	ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
+	struct ath5k_chan_pcal_info	ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+	struct ath5k_chan_pcal_info	ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+
+	/* Per rate target power levels */
+	u8	ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
+	struct ath5k_rate_pcal_info	ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
+	struct ath5k_rate_pcal_info	ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+	struct ath5k_rate_pcal_info	ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
+
+	/* Conformance test limits (Unused) */
+	u8	ee_ctls;
+	u8	ee_ctl[AR5K_EEPROM_MAX_CTLS];
+	struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
+
+	/* Noise Floor Calibration settings */
+	s16	ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
+	s8	ee_adc_desired_size[AR5K_EEPROM_N_MODES];
+	s8	ee_pga_desired_size[AR5K_EEPROM_N_MODES];
+	s8	ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
+	s8	ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
+	s8	ee_pd_gain_overlap;
+
+	/* Spur mitigation data (fbin values for spur channels) */
+	u16	ee_spur_chans[AR5K_EEPROM_N_SPUR_CHANS][AR5K_EEPROM_N_FREQ_BANDS];
+
+	/* Antenna raw switch tables */
+	u32	ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+};
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/gpio.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/gpio.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/gpio.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/****************\
+  GPIO Functions
+\****************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Set led state
+ */
+void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
+{
+	u32 led;
+	/*5210 has different led mode handling*/
+	u32 led_5210;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/*Reset led status*/
+	if (ah->ah_version != AR5K_AR5210)
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+			AR5K_PCICFG_LEDMODE |  AR5K_PCICFG_LED);
+	else
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
+
+	/*
+	 * Some blinking values, define at your wish
+	 */
+	switch (state) {
+	case AR5K_LED_SCAN:
+	case AR5K_LED_AUTH:
+		led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
+		led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
+		break;
+
+	case AR5K_LED_INIT:
+		led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
+		led_5210 = AR5K_PCICFG_LED_PEND;
+		break;
+
+	case AR5K_LED_ASSOC:
+	case AR5K_LED_RUN:
+		led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
+		led_5210 = AR5K_PCICFG_LED_ASSOC;
+		break;
+
+	default:
+		led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
+		led_5210 = AR5K_PCICFG_LED_PEND;
+		break;
+	}
+
+	/*Write new status to the register*/
+	if (ah->ah_version != AR5K_AR5210)
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
+	else
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
+}
+
+/*
+ * Set GPIO inputs
+ */
+int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (gpio >= AR5K_NUM_GPIO)
+		return -EINVAL;
+
+	ath5k_hw_reg_write(ah,
+		(ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+		| AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
+
+	return 0;
+}
+
+/*
+ * Set GPIO outputs
+ */
+int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (gpio >= AR5K_NUM_GPIO)
+		return -EINVAL;
+
+	ath5k_hw_reg_write(ah,
+		(ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
+		| AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
+
+	return 0;
+}
+
+/*
+ * Get GPIO state
+ */
+u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (gpio >= AR5K_NUM_GPIO)
+		return 0xffffffff;
+
+	/* GPIO input magic */
+	return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
+		0x1;
+}
+
+/*
+ * Set GPIO state
+ */
+int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
+{
+	u32 data;
+	ATH5K_TRACE(ah->ah_sc);
+
+	if (gpio >= AR5K_NUM_GPIO)
+		return -EINVAL;
+
+	/* GPIO output magic */
+	data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+	data &= ~(1 << gpio);
+	data |= (val & 1) << gpio;
+
+	ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
+
+	return 0;
+}
+
+/*
+ * Initialize the GPIO interrupt (RFKill switch)
+ */
+void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
+		u32 interrupt_level)
+{
+	u32 data;
+
+	ATH5K_TRACE(ah->ah_sc);
+	if (gpio >= AR5K_NUM_GPIO)
+		return;
+
+	/*
+	 * Set the GPIO interrupt
+	 */
+	data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
+		~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
+		AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
+		(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
+
+	ath5k_hw_reg_write(ah, interrupt_level ? data :
+		(data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
+
+	ah->ah_imr |= AR5K_IMR_GPIO;
+
+	/* Enable GPIO interrupts */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/initvals.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/initvals.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/initvals.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/initvals.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1555 @@
+/*
+ * Initial register settings functions
+ *
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Mode-independent initial register writes
+ */
+
+struct ath5k_ini {
+	u16	ini_register;
+	u32	ini_value;
+
+	enum {
+		AR5K_INI_WRITE = 0,	/* Default */
+		AR5K_INI_READ = 1,	/* Cleared on read */
+	} ini_mode;
+};
+
+/*
+ * Mode specific initial register values
+ */
+
+struct ath5k_ini_mode {
+	u16	mode_register;
+	u32	mode_value[5];
+};
+
+/* Initial register settings for AR5210 */
+static const struct ath5k_ini ar5210_ini[] = {
+	/* PCU and MAC registers */
+	{ AR5K_NOQCU_TXDP0,	0 },
+	{ AR5K_NOQCU_TXDP1,	0 },
+	{ AR5K_RXDP,		0 },
+	{ AR5K_CR,		0 },
+	{ AR5K_ISR,		0, AR5K_INI_READ },
+	{ AR5K_IMR,		0 },
+	{ AR5K_IER,		AR5K_IER_DISABLE },
+	{ AR5K_BSR,		0, AR5K_INI_READ },
+	{ AR5K_TXCFG,		AR5K_DMASIZE_128B },
+	{ AR5K_RXCFG,		AR5K_DMASIZE_128B },
+	{ AR5K_CFG,		AR5K_INIT_CFG },
+	{ AR5K_TOPS,		8 },
+	{ AR5K_RXNOFRM,		8 },
+	{ AR5K_RPGTO,		0 },
+	{ AR5K_TXNOFRM,		0 },
+	{ AR5K_SFR,		0 },
+	{ AR5K_MIBC,		0 },
+	{ AR5K_MISC,		0 },
+	{ AR5K_RX_FILTER_5210,	0 },
+	{ AR5K_MCAST_FILTER0_5210, 0 },
+	{ AR5K_MCAST_FILTER1_5210, 0 },
+	{ AR5K_TX_MASK0,	0 },
+	{ AR5K_TX_MASK1,	0 },
+	{ AR5K_CLR_TMASK,	0 },
+	{ AR5K_TRIG_LVL,	AR5K_TUNE_MIN_TX_FIFO_THRES },
+	{ AR5K_DIAG_SW_5210,	0 },
+	{ AR5K_RSSI_THR,	AR5K_TUNE_RSSI_THRES },
+	{ AR5K_TSF_L32_5210,	0 },
+	{ AR5K_TIMER0_5210,	0 },
+	{ AR5K_TIMER1_5210,	0xffffffff },
+	{ AR5K_TIMER2_5210,	0xffffffff },
+	{ AR5K_TIMER3_5210,	1 },
+	{ AR5K_CFP_DUR_5210,	0 },
+	{ AR5K_CFP_PERIOD_5210,	0 },
+	/* PHY registers */
+	{ AR5K_PHY(0),	0x00000047 },
+	{ AR5K_PHY_AGC,	0x00000000 },
+	{ AR5K_PHY(3),	0x09848ea6 },
+	{ AR5K_PHY(4),	0x3d32e000 },
+	{ AR5K_PHY(5),	0x0000076b },
+	{ AR5K_PHY_ACT,	AR5K_PHY_ACT_DISABLE },
+	{ AR5K_PHY(8),	0x02020200 },
+	{ AR5K_PHY(9),	0x00000e0e },
+	{ AR5K_PHY(10),	0x0a020201 },
+	{ AR5K_PHY(11),	0x00036ffc },
+	{ AR5K_PHY(12),	0x00000000 },
+	{ AR5K_PHY(13),	0x00000e0e },
+	{ AR5K_PHY(14),	0x00000007 },
+	{ AR5K_PHY(15),	0x00020100 },
+	{ AR5K_PHY(16),	0x89630000 },
+	{ AR5K_PHY(17),	0x1372169c },
+	{ AR5K_PHY(18),	0x0018b633 },
+	{ AR5K_PHY(19),	0x1284613c },
+	{ AR5K_PHY(20),	0x0de8b8e0 },
+	{ AR5K_PHY(21),	0x00074859 },
+	{ AR5K_PHY(22),	0x7e80beba },
+	{ AR5K_PHY(23),	0x313a665e },
+	{ AR5K_PHY_AGCCTL, 0x00001d08 },
+	{ AR5K_PHY(25),	0x0001ce00 },
+	{ AR5K_PHY(26),	0x409a4190 },
+	{ AR5K_PHY(28),	0x0000000f },
+	{ AR5K_PHY(29),	0x00000080 },
+	{ AR5K_PHY(30),	0x00000004 },
+	{ AR5K_PHY(31),	0x00000018 }, 	/* 0x987c */
+	{ AR5K_PHY(64),	0x00000000 }, 	/* 0x9900 */
+	{ AR5K_PHY(65),	0x00000000 },
+	{ AR5K_PHY(66),	0x00000000 },
+	{ AR5K_PHY(67),	0x00800000 },
+	{ AR5K_PHY(68),	0x00000003 },
+	/* BB gain table (64bytes) */
+	{ AR5K_BB_GAIN(0), 0x00000000 },
+	{ AR5K_BB_GAIN(1), 0x00000020 },
+	{ AR5K_BB_GAIN(2), 0x00000010 },
+	{ AR5K_BB_GAIN(3), 0x00000030 },
+	{ AR5K_BB_GAIN(4), 0x00000008 },
+	{ AR5K_BB_GAIN(5), 0x00000028 },
+	{ AR5K_BB_GAIN(6), 0x00000028 },
+	{ AR5K_BB_GAIN(7), 0x00000004 },
+	{ AR5K_BB_GAIN(8), 0x00000024 },
+	{ AR5K_BB_GAIN(9), 0x00000014 },
+	{ AR5K_BB_GAIN(10), 0x00000034 },
+	{ AR5K_BB_GAIN(11), 0x0000000c },
+	{ AR5K_BB_GAIN(12), 0x0000002c },
+	{ AR5K_BB_GAIN(13), 0x00000002 },
+	{ AR5K_BB_GAIN(14), 0x00000022 },
+	{ AR5K_BB_GAIN(15), 0x00000012 },
+	{ AR5K_BB_GAIN(16), 0x00000032 },
+	{ AR5K_BB_GAIN(17), 0x0000000a },
+	{ AR5K_BB_GAIN(18), 0x0000002a },
+	{ AR5K_BB_GAIN(19), 0x00000001 },
+	{ AR5K_BB_GAIN(20), 0x00000021 },
+	{ AR5K_BB_GAIN(21), 0x00000011 },
+	{ AR5K_BB_GAIN(22), 0x00000031 },
+	{ AR5K_BB_GAIN(23), 0x00000009 },
+	{ AR5K_BB_GAIN(24), 0x00000029 },
+	{ AR5K_BB_GAIN(25), 0x00000005 },
+	{ AR5K_BB_GAIN(26), 0x00000025 },
+	{ AR5K_BB_GAIN(27), 0x00000015 },
+	{ AR5K_BB_GAIN(28), 0x00000035 },
+	{ AR5K_BB_GAIN(29), 0x0000000d },
+	{ AR5K_BB_GAIN(30), 0x0000002d },
+	{ AR5K_BB_GAIN(31), 0x00000003 },
+	{ AR5K_BB_GAIN(32), 0x00000023 },
+	{ AR5K_BB_GAIN(33), 0x00000013 },
+	{ AR5K_BB_GAIN(34), 0x00000033 },
+	{ AR5K_BB_GAIN(35), 0x0000000b },
+	{ AR5K_BB_GAIN(36), 0x0000002b },
+	{ AR5K_BB_GAIN(37), 0x00000007 },
+	{ AR5K_BB_GAIN(38), 0x00000027 },
+	{ AR5K_BB_GAIN(39), 0x00000017 },
+	{ AR5K_BB_GAIN(40), 0x00000037 },
+	{ AR5K_BB_GAIN(41), 0x0000000f },
+	{ AR5K_BB_GAIN(42), 0x0000002f },
+	{ AR5K_BB_GAIN(43), 0x0000002f },
+	{ AR5K_BB_GAIN(44), 0x0000002f },
+	{ AR5K_BB_GAIN(45), 0x0000002f },
+	{ AR5K_BB_GAIN(46), 0x0000002f },
+	{ AR5K_BB_GAIN(47), 0x0000002f },
+	{ AR5K_BB_GAIN(48), 0x0000002f },
+	{ AR5K_BB_GAIN(49), 0x0000002f },
+	{ AR5K_BB_GAIN(50), 0x0000002f },
+	{ AR5K_BB_GAIN(51), 0x0000002f },
+	{ AR5K_BB_GAIN(52), 0x0000002f },
+	{ AR5K_BB_GAIN(53), 0x0000002f },
+	{ AR5K_BB_GAIN(54), 0x0000002f },
+	{ AR5K_BB_GAIN(55), 0x0000002f },
+	{ AR5K_BB_GAIN(56), 0x0000002f },
+	{ AR5K_BB_GAIN(57), 0x0000002f },
+	{ AR5K_BB_GAIN(58), 0x0000002f },
+	{ AR5K_BB_GAIN(59), 0x0000002f },
+	{ AR5K_BB_GAIN(60), 0x0000002f },
+	{ AR5K_BB_GAIN(61), 0x0000002f },
+	{ AR5K_BB_GAIN(62), 0x0000002f },
+	{ AR5K_BB_GAIN(63), 0x0000002f },
+	/* 5110 RF gain table (64btes) */
+	{ AR5K_RF_GAIN(0), 0x0000001d },
+	{ AR5K_RF_GAIN(1), 0x0000005d },
+	{ AR5K_RF_GAIN(2), 0x0000009d },
+	{ AR5K_RF_GAIN(3), 0x000000dd },
+	{ AR5K_RF_GAIN(4), 0x0000011d },
+	{ AR5K_RF_GAIN(5), 0x00000021 },
+	{ AR5K_RF_GAIN(6), 0x00000061 },
+	{ AR5K_RF_GAIN(7), 0x000000a1 },
+	{ AR5K_RF_GAIN(8), 0x000000e1 },
+	{ AR5K_RF_GAIN(9), 0x00000031 },
+	{ AR5K_RF_GAIN(10), 0x00000071 },
+	{ AR5K_RF_GAIN(11), 0x000000b1 },
+	{ AR5K_RF_GAIN(12), 0x0000001c },
+	{ AR5K_RF_GAIN(13), 0x0000005c },
+	{ AR5K_RF_GAIN(14), 0x00000029 },
+	{ AR5K_RF_GAIN(15), 0x00000069 },
+	{ AR5K_RF_GAIN(16), 0x000000a9 },
+	{ AR5K_RF_GAIN(17), 0x00000020 },
+	{ AR5K_RF_GAIN(18), 0x00000019 },
+	{ AR5K_RF_GAIN(19), 0x00000059 },
+	{ AR5K_RF_GAIN(20), 0x00000099 },
+	{ AR5K_RF_GAIN(21), 0x00000030 },
+	{ AR5K_RF_GAIN(22), 0x00000005 },
+	{ AR5K_RF_GAIN(23), 0x00000025 },
+	{ AR5K_RF_GAIN(24), 0x00000065 },
+	{ AR5K_RF_GAIN(25), 0x000000a5 },
+	{ AR5K_RF_GAIN(26), 0x00000028 },
+	{ AR5K_RF_GAIN(27), 0x00000068 },
+	{ AR5K_RF_GAIN(28), 0x0000001f },
+	{ AR5K_RF_GAIN(29), 0x0000001e },
+	{ AR5K_RF_GAIN(30), 0x00000018 },
+	{ AR5K_RF_GAIN(31), 0x00000058 },
+	{ AR5K_RF_GAIN(32), 0x00000098 },
+	{ AR5K_RF_GAIN(33), 0x00000003 },
+	{ AR5K_RF_GAIN(34), 0x00000004 },
+	{ AR5K_RF_GAIN(35), 0x00000044 },
+	{ AR5K_RF_GAIN(36), 0x00000084 },
+	{ AR5K_RF_GAIN(37), 0x00000013 },
+	{ AR5K_RF_GAIN(38), 0x00000012 },
+	{ AR5K_RF_GAIN(39), 0x00000052 },
+	{ AR5K_RF_GAIN(40), 0x00000092 },
+	{ AR5K_RF_GAIN(41), 0x000000d2 },
+	{ AR5K_RF_GAIN(42), 0x0000002b },
+	{ AR5K_RF_GAIN(43), 0x0000002a },
+	{ AR5K_RF_GAIN(44), 0x0000006a },
+	{ AR5K_RF_GAIN(45), 0x000000aa },
+	{ AR5K_RF_GAIN(46), 0x0000001b },
+	{ AR5K_RF_GAIN(47), 0x0000001a },
+	{ AR5K_RF_GAIN(48), 0x0000005a },
+	{ AR5K_RF_GAIN(49), 0x0000009a },
+	{ AR5K_RF_GAIN(50), 0x000000da },
+	{ AR5K_RF_GAIN(51), 0x00000006 },
+	{ AR5K_RF_GAIN(52), 0x00000006 },
+	{ AR5K_RF_GAIN(53), 0x00000006 },
+	{ AR5K_RF_GAIN(54), 0x00000006 },
+	{ AR5K_RF_GAIN(55), 0x00000006 },
+	{ AR5K_RF_GAIN(56), 0x00000006 },
+	{ AR5K_RF_GAIN(57), 0x00000006 },
+	{ AR5K_RF_GAIN(58), 0x00000006 },
+	{ AR5K_RF_GAIN(59), 0x00000006 },
+	{ AR5K_RF_GAIN(60), 0x00000006 },
+	{ AR5K_RF_GAIN(61), 0x00000006 },
+	{ AR5K_RF_GAIN(62), 0x00000006 },
+	{ AR5K_RF_GAIN(63), 0x00000006 },
+	/* PHY activation */
+	{ AR5K_PHY(53), 0x00000020 },
+	{ AR5K_PHY(51), 0x00000004 },
+	{ AR5K_PHY(50), 0x00060106 },
+	{ AR5K_PHY(39), 0x0000006d },
+	{ AR5K_PHY(48), 0x00000000 },
+	{ AR5K_PHY(52), 0x00000014 },
+	{ AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE },
+};
+
+/* Initial register settings for AR5211 */
+static const struct ath5k_ini ar5211_ini[] = {
+	{ AR5K_RXDP,		0x00000000 },
+	{ AR5K_RTSD0,		0x84849c9c },
+	{ AR5K_RTSD1,		0x7c7c7c7c },
+	{ AR5K_RXCFG,		0x00000005 },
+	{ AR5K_MIBC,		0x00000000 },
+	{ AR5K_TOPS,		0x00000008 },
+	{ AR5K_RXNOFRM,		0x00000008 },
+	{ AR5K_TXNOFRM,		0x00000010 },
+	{ AR5K_RPGTO,		0x00000000 },
+	{ AR5K_RFCNT,		0x0000001f },
+	{ AR5K_QUEUE_TXDP(0),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(1),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(2),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(3),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(4),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(5),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(6),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(7),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(8),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(9),	0x00000000 },
+	{ AR5K_DCU_FP,		0x00000000 },
+	{ AR5K_STA_ID1,		0x00000000 },
+	{ AR5K_BSS_ID0,		0x00000000 },
+	{ AR5K_BSS_ID1,		0x00000000 },
+	{ AR5K_RSSI_THR,	0x00000000 },
+	{ AR5K_CFP_PERIOD_5211,	0x00000000 },
+	{ AR5K_TIMER0_5211,	0x00000030 },
+	{ AR5K_TIMER1_5211,	0x0007ffff },
+	{ AR5K_TIMER2_5211,	0x01ffffff },
+	{ AR5K_TIMER3_5211,	0x00000031 },
+	{ AR5K_CFP_DUR_5211,	0x00000000 },
+	{ AR5K_RX_FILTER_5211,	0x00000000 },
+	{ AR5K_MCAST_FILTER0_5211, 0x00000000 },
+	{ AR5K_MCAST_FILTER1_5211, 0x00000002 },
+	{ AR5K_DIAG_SW_5211,	0x00000000 },
+	{ AR5K_ADDAC_TEST,	0x00000000 },
+	{ AR5K_DEFAULT_ANTENNA,	0x00000000 },
+	/* PHY registers */
+	{ AR5K_PHY_AGC,	0x00000000 },
+	{ AR5K_PHY(3),	0x2d849093 },
+	{ AR5K_PHY(4),	0x7d32e000 },
+	{ AR5K_PHY(5),	0x00000f6b },
+	{ AR5K_PHY_ACT,	0x00000000 },
+	{ AR5K_PHY(11),	0x00026ffe },
+	{ AR5K_PHY(12),	0x00000000 },
+	{ AR5K_PHY(15),	0x00020100 },
+	{ AR5K_PHY(16),	0x206a017a },
+	{ AR5K_PHY(19),	0x1284613c },
+	{ AR5K_PHY(21),	0x00000859 },
+	{ AR5K_PHY(26),	0x409a4190 },	/* 0x9868 */
+	{ AR5K_PHY(27),	0x050cb081 },
+	{ AR5K_PHY(28),	0x0000000f },
+	{ AR5K_PHY(29),	0x00000080 },
+	{ AR5K_PHY(30),	0x0000000c },
+	{ AR5K_PHY(64),	0x00000000 },
+	{ AR5K_PHY(65),	0x00000000 },
+	{ AR5K_PHY(66),	0x00000000 },
+	{ AR5K_PHY(67),	0x00800000 },
+	{ AR5K_PHY(68),	0x00000001 },
+	{ AR5K_PHY(71),	0x0000092a },
+	{ AR5K_PHY_IQ,	0x00000000 },
+	{ AR5K_PHY(73),	0x00058a05 },
+	{ AR5K_PHY(74),	0x00000001 },
+	{ AR5K_PHY(75),	0x00000000 },
+	{ AR5K_PHY_PAPD_PROBE, 0x00000000 },
+	{ AR5K_PHY(77),	0x00000000 },	/* 0x9934 */
+	{ AR5K_PHY(78),	0x00000000 },	/* 0x9938 */
+	{ AR5K_PHY(79),	0x0000003f },	/* 0x993c */
+	{ AR5K_PHY(80),	0x00000004 },
+	{ AR5K_PHY(82),	0x00000000 },
+	{ AR5K_PHY(83),	0x00000000 },
+	{ AR5K_PHY(84),	0x00000000 },
+	{ AR5K_PHY_RADAR, 0x5d50f14c },
+	{ AR5K_PHY(86),	0x00000018 },
+	{ AR5K_PHY(87),	0x004b6a8e },
+	/* Initial Power table (32bytes)
+	 * common on all cards/modes.
+	 * Note: Table is rewritten during
+	 * txpower setup later using calibration
+	 * data etc. so next write is non-common */
+	{ AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff },
+	{ AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff },
+	{ AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff },
+	{ AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff },
+	{ AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff },
+	{ AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff },
+	{ AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff },
+	{ AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff },
+	{ AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff },
+	{ AR5K_PHY_CCKTXCTL, 0x00000000 },
+	{ AR5K_PHY(642), 0x503e4646 },
+	{ AR5K_PHY_GAIN_2GHZ, 0x6480416c },
+	{ AR5K_PHY(644), 0x0199a003 },
+	{ AR5K_PHY(645), 0x044cd610 },
+	{ AR5K_PHY(646), 0x13800040 },
+	{ AR5K_PHY(647), 0x1be00060 },
+	{ AR5K_PHY(648), 0x0c53800a },
+	{ AR5K_PHY(649), 0x0014df3b },
+	{ AR5K_PHY(650), 0x000001b5 },
+	{ AR5K_PHY(651), 0x00000020 },
+};
+
+/* Initial mode-specific settings for AR5211
+ * 5211 supports OFDM-only g (draft g) but we
+ * need to test it !
+ */
+static const struct ath5k_ini_mode ar5211_ini_mode[] = {
+	{ AR5K_TXCFG,
+	/*	  a	    aTurbo	  b	  g (OFDM)    */
+	   { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+	{ AR5K_DCU_GBL_IFS_SLOT,
+	   { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } },
+	{ AR5K_DCU_GBL_IFS_SIFS,
+	   { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } },
+	{ AR5K_DCU_GBL_IFS_EIFS,
+	   { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } },
+	{ AR5K_DCU_GBL_IFS_MISC,
+	   { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } },
+	{ AR5K_TIME_OUT,
+	   { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } },
+	{ AR5K_USEC_5211,
+	   { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } },
+	{ AR5K_PHY_TURBO,
+	   { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } },
+	{ AR5K_PHY(8),
+	   { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } },
+	{ AR5K_PHY(9),
+	   { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } },
+	{ AR5K_PHY(10),
+	   { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } },
+	{ AR5K_PHY(13),
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	{ AR5K_PHY(14),
+	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } },
+	{ AR5K_PHY(17),
+	   { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } },
+	{ AR5K_PHY(18),
+	   { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
+	{ AR5K_PHY(20),
+	   { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
+	{ AR5K_PHY_SIG,
+	   { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
+	{ AR5K_PHY_AGCCOARSE,
+	   { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
+	{ AR5K_PHY_AGCCTL,
+	   { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
+	{ AR5K_PHY_NF,
+	   { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+	{ AR5K_PHY_RX_DELAY,
+	   { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } },
+	{ AR5K_PHY(70),
+	   { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } },
+	{ AR5K_PHY_FRAME_CTL_5211,
+	   { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
+	{ AR5K_PHY_PCDAC_TXPOWER_BASE,
+	   { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
+	{ AR5K_RF_BUFFER_CONTROL_4,
+	   { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } },
+};
+
+/* Initial register settings for AR5212 */
+static const struct ath5k_ini ar5212_ini_common_start[] = {
+	{ AR5K_RXDP,		0x00000000 },
+	{ AR5K_RXCFG,		0x00000005 },
+	{ AR5K_MIBC,		0x00000000 },
+	{ AR5K_TOPS,		0x00000008 },
+	{ AR5K_RXNOFRM,		0x00000008 },
+	{ AR5K_TXNOFRM,		0x00000010 },
+	{ AR5K_RPGTO,		0x00000000 },
+	{ AR5K_RFCNT,		0x0000001f },
+	{ AR5K_QUEUE_TXDP(0),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(1),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(2),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(3),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(4),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(5),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(6),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(7),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(8),	0x00000000 },
+	{ AR5K_QUEUE_TXDP(9),	0x00000000 },
+	{ AR5K_DCU_FP,		0x00000000 },
+	{ AR5K_DCU_TXP,		0x00000000 },
+	/* Tx filter table 0 (32 entries) */
+	{ AR5K_DCU_TX_FILTER_0(0),  0x00000000 }, /* DCU 0 */
+	{ AR5K_DCU_TX_FILTER_0(1),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(2),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(3),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(4),  0x00000000 }, /* DCU 1 */
+	{ AR5K_DCU_TX_FILTER_0(5),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(6),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(7),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(8),  0x00000000 }, /* DCU 2 */
+	{ AR5K_DCU_TX_FILTER_0(9),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(10), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(11), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(12), 0x00000000 }, /* DCU 3 */
+	{ AR5K_DCU_TX_FILTER_0(13), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(14), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(15), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(16), 0x00000000 }, /* DCU 4 */
+	{ AR5K_DCU_TX_FILTER_0(17), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(18), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(19), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(20), 0x00000000 }, /* DCU 5 */
+	{ AR5K_DCU_TX_FILTER_0(21), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(22), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(23), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(24), 0x00000000 }, /* DCU 6 */
+	{ AR5K_DCU_TX_FILTER_0(25), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(26), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(27), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(28), 0x00000000 }, /* DCU 7 */
+	{ AR5K_DCU_TX_FILTER_0(29), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(30), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_0(31), 0x00000000 },
+	/* Tx filter table 1 (16 entries) */
+	{ AR5K_DCU_TX_FILTER_1(0),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(1),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(2),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(3),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(4),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(5),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(6),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(7),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(8),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(9),  0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(10), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(11), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(12), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(13), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(14), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_1(15), 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
+	{ AR5K_DCU_TX_FILTER_SET, 0x00000000 },
+	{ AR5K_STA_ID1,		0x00000000 },
+	{ AR5K_BSS_ID0,		0x00000000 },
+	{ AR5K_BSS_ID1,		0x00000000 },
+	{ AR5K_BEACON_5211,	0x00000000 },
+	{ AR5K_CFP_PERIOD_5211, 0x00000000 },
+	{ AR5K_TIMER0_5211,	0x00000030 },
+	{ AR5K_TIMER1_5211,	0x0007ffff },
+	{ AR5K_TIMER2_5211,	0x01ffffff },
+	{ AR5K_TIMER3_5211,	0x00000031 },
+	{ AR5K_CFP_DUR_5211,	0x00000000 },
+	{ AR5K_RX_FILTER_5211,	0x00000000 },
+	{ AR5K_DIAG_SW_5211,	0x00000000 },
+	{ AR5K_ADDAC_TEST,	0x00000000 },
+	{ AR5K_DEFAULT_ANTENNA,	0x00000000 },
+	{ AR5K_FRAME_CTL_QOSM, 	0x000fc78f },
+	{ AR5K_XRMODE,		0x2a82301a },
+	{ AR5K_XRDELAY,		0x05dc01e0 },
+	{ AR5K_XRTIMEOUT,	0x1f402710 },
+	{ AR5K_XRCHIRP,		0x01f40000 },
+	{ AR5K_XRSTOMP,		0x00001e1c },
+	{ AR5K_SLEEP0,		0x0002aaaa },
+	{ AR5K_SLEEP1,		0x02005555 },
+	{ AR5K_SLEEP2,		0x00000000 },
+	{ AR5K_BSS_IDM0,	0xffffffff },
+	{ AR5K_BSS_IDM1,	0x0000ffff },
+	{ AR5K_TXPC,		0x00000000 },
+	{ AR5K_PROFCNT_TX,	0x00000000 },
+	{ AR5K_PROFCNT_RX,	0x00000000 },
+	{ AR5K_PROFCNT_RXCLR,	0x00000000 },
+	{ AR5K_PROFCNT_CYCLE,	0x00000000 },
+	{ AR5K_QUIET_CTL1,	0x00000088 },
+	/* Initial rate duration table (32 entries )*/
+	{ AR5K_RATE_DUR(0),	0x00000000 },
+	{ AR5K_RATE_DUR(1),	0x0000008c },
+	{ AR5K_RATE_DUR(2),	0x000000e4 },
+	{ AR5K_RATE_DUR(3),	0x000002d5 },
+	{ AR5K_RATE_DUR(4),	0x00000000 },
+	{ AR5K_RATE_DUR(5),	0x00000000 },
+	{ AR5K_RATE_DUR(6),	0x000000a0 },
+	{ AR5K_RATE_DUR(7),	0x000001c9 },
+	{ AR5K_RATE_DUR(8),	0x0000002c },
+	{ AR5K_RATE_DUR(9),	0x0000002c },
+	{ AR5K_RATE_DUR(10),	0x00000030 },
+	{ AR5K_RATE_DUR(11),	0x0000003c },
+	{ AR5K_RATE_DUR(12),	0x0000002c },
+	{ AR5K_RATE_DUR(13),	0x0000002c },
+	{ AR5K_RATE_DUR(14),	0x00000030 },
+	{ AR5K_RATE_DUR(15),	0x0000003c },
+	{ AR5K_RATE_DUR(16),	0x00000000 },
+	{ AR5K_RATE_DUR(17),	0x00000000 },
+	{ AR5K_RATE_DUR(18),	0x00000000 },
+	{ AR5K_RATE_DUR(19),	0x00000000 },
+	{ AR5K_RATE_DUR(20),	0x00000000 },
+	{ AR5K_RATE_DUR(21),	0x00000000 },
+	{ AR5K_RATE_DUR(22),	0x00000000 },
+	{ AR5K_RATE_DUR(23),	0x00000000 },
+	{ AR5K_RATE_DUR(24),	0x000000d5 },
+	{ AR5K_RATE_DUR(25),	0x000000df },
+	{ AR5K_RATE_DUR(26),	0x00000102 },
+	{ AR5K_RATE_DUR(27),	0x0000013a },
+	{ AR5K_RATE_DUR(28),	0x00000075 },
+	{ AR5K_RATE_DUR(29),	0x0000007f },
+	{ AR5K_RATE_DUR(30),	0x000000a2 },
+	{ AR5K_RATE_DUR(31),	0x00000000 },
+	{ AR5K_QUIET_CTL2,	0x00010002 },
+	{ AR5K_TSF_PARM,	0x00000001 },
+	{ AR5K_QOS_NOACK,	0x000000c0 },
+	{ AR5K_PHY_ERR_FIL,	0x00000000 },
+	{ AR5K_XRLAT_TX,	0x00000168 },
+	{ AR5K_ACKSIFS,		0x00000000 },
+	/* Rate -> db table
+	 * notice ...03<-02<-01<-00 ! */
+	{ AR5K_RATE2DB(0),	0x03020100 },
+	{ AR5K_RATE2DB(1),	0x07060504 },
+	{ AR5K_RATE2DB(2),	0x0b0a0908 },
+	{ AR5K_RATE2DB(3),	0x0f0e0d0c },
+	{ AR5K_RATE2DB(4),	0x13121110 },
+	{ AR5K_RATE2DB(5),	0x17161514 },
+	{ AR5K_RATE2DB(6),	0x1b1a1918 },
+	{ AR5K_RATE2DB(7),	0x1f1e1d1c },
+	/* Db -> Rate table */
+	{ AR5K_DB2RATE(0),	0x03020100 },
+	{ AR5K_DB2RATE(1),	0x07060504 },
+	{ AR5K_DB2RATE(2),	0x0b0a0908 },
+	{ AR5K_DB2RATE(3),	0x0f0e0d0c },
+	{ AR5K_DB2RATE(4),	0x13121110 },
+	{ AR5K_DB2RATE(5),	0x17161514 },
+	{ AR5K_DB2RATE(6),	0x1b1a1918 },
+	{ AR5K_DB2RATE(7),	0x1f1e1d1c },
+	/* PHY registers (Common settings
+	 * for all chips/modes) */
+	{ AR5K_PHY(3),		0xad848e19 },
+	{ AR5K_PHY(4),		0x7d28e000 },
+	{ AR5K_PHY_TIMING_3,	0x9c0a9f6b },
+	{ AR5K_PHY_ACT,		0x00000000 },
+	{ AR5K_PHY(16),		0x206a017a },
+	{ AR5K_PHY(21),		0x00000859 },
+	{ AR5K_PHY_BIN_MASK_1,	0x00000000 },
+	{ AR5K_PHY_BIN_MASK_2,	0x00000000 },
+	{ AR5K_PHY_BIN_MASK_3,	0x00000000 },
+	{ AR5K_PHY_BIN_MASK_CTL, 0x00800000 },
+	{ AR5K_PHY_ANT_CTL,	0x00000001 },
+	/*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */
+	{ AR5K_PHY_MAX_RX_LEN,	0x00000c80 },
+	{ AR5K_PHY_IQ,		0x05100000 },
+	{ AR5K_PHY_WARM_RESET,	0x00000001 },
+	{ AR5K_PHY_CTL,		0x00000004 },
+	{ AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 },
+	{ AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d },
+	{ AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f },
+	{ AR5K_PHY(82),		0x9280b212 },
+	{ AR5K_PHY_RADAR,	0x5d50e188 },
+	/*{ AR5K_PHY(86), 0x000000ff },*/
+	{ AR5K_PHY(87),		0x004b6a8e },
+	{ AR5K_PHY_NFTHRES,	0x000003ce },
+	{ AR5K_PHY_RESTART,	0x192fb515 },
+	{ AR5K_PHY(94),		0x00000001 },
+	{ AR5K_PHY_RFBUS_REQ,	0x00000000 },
+	/*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */
+	/*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */
+	{ AR5K_PHY(644),	0x00806333 },
+	{ AR5K_PHY(645),	0x00106c10 },
+	{ AR5K_PHY(646),	0x009c4060 },
+	/* { AR5K_PHY(647), 0x1483800a }, */
+	/* { AR5K_PHY(648), 0x01831061 }, */ /* Old value */
+	{ AR5K_PHY(648),	0x018830c6 },
+	{ AR5K_PHY(649),	0x00000400 },
+	/*{ AR5K_PHY(650), 0x000001b5 },*/
+	{ AR5K_PHY(651),	0x00000000 },
+	{ AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
+	{ AR5K_PHY_TXPOWER_RATE4, 0x20202020 },
+	/*{ AR5K_PHY(655), 0x13c889af },*/
+	{ AR5K_PHY(656),	0x38490a20 },
+	{ AR5K_PHY(657),	0x00007bb6 },
+	{ AR5K_PHY(658),	0x0fff3ffc },
+};
+
+/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
+static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
+	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
+	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+	{ AR5K_DCU_GBL_IFS_SIFS,
+	   { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
+	{ AR5K_DCU_GBL_IFS_SLOT,
+	   { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
+	{ AR5K_DCU_GBL_IFS_EIFS,
+	   { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
+	{ AR5K_DCU_GBL_IFS_MISC,
+	   { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
+	{ AR5K_TIME_OUT,
+	   { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
+	{ AR5K_PHY_TURBO,
+	   { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
+	{ AR5K_PHY(8),
+	   { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
+	{ AR5K_PHY_RF_CTL2,
+	   { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
+	{ AR5K_PHY_SETTLING,
+	   { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
+	{ AR5K_PHY_AGCCTL,
+	   { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
+	{ AR5K_PHY_NF,
+	   { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+	{ AR5K_PHY_WEAK_OFDM_HIGH_THR,
+	   { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
+	{ AR5K_PHY(70),
+	   { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
+	{ AR5K_PHY_OFDM_SELFCORR,
+	   { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
+	{ 0xa230,
+	   { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
+	{ AR5K_TXCFG,
+	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
+	   { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+	{ AR5K_USEC_5211,
+	   { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
+	{ AR5K_PHY_RF_CTL3,
+	   { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
+	{ AR5K_PHY_RF_CTL4,
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	{ AR5K_PHY_PA_CTL,
+	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+	{ AR5K_PHY_GAIN,
+	   { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
+	{ AR5K_PHY_DESIRED_SIZE,
+	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+	{ AR5K_PHY_SIG,
+	   { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
+	{ AR5K_PHY_AGCCOARSE,
+	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
+	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
+	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
+	{ AR5K_PHY_RX_DELAY,
+	   { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
+	{ AR5K_PHY_FRAME_CTL_5211,
+	   { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
+	{ AR5K_PHY_GAIN_2GHZ,
+	   { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
+	{ AR5K_PHY_CCK_RX_CTL_4,
+	   { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf5111_ini_common_end[] = {
+	{ AR5K_DCU_FP,		0x00000000 },
+	{ AR5K_PHY_AGC, 	0x00000000 },
+	{ AR5K_PHY_ADC_CTL, 	0x00022ffe },
+	{ 0x983c, 		0x00020100 },
+	{ AR5K_PHY_GAIN_OFFSET,	0x1284613c },
+	{ AR5K_PHY_PAPD_PROBE,	0x00004883 },
+	{ 0x9940,		0x00000004 },
+	{ 0x9958,		0x000000ff },
+	{ 0x9974,		0x00000000 },
+	{ AR5K_PHY_SPENDING,	0x00000018 },
+	{ AR5K_PHY_CCKTXCTL,	0x00000000 },
+	{ AR5K_PHY_CCK_CROSSCORR, 0xd03e6788 },
+	{ AR5K_PHY_DAG_CCK_CTL,	0x000001b5 },
+	{ 0xa23c,		0x13c889af },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
+	{ AR5K_TXCFG,
+	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
+	   { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+	{ AR5K_USEC_5211,
+	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+	{ AR5K_PHY_RF_CTL3,
+	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+	{ AR5K_PHY_RF_CTL4,
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	{ AR5K_PHY_PA_CTL,
+	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+	{ AR5K_PHY_GAIN,
+	   { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
+	{ AR5K_PHY_DESIRED_SIZE,
+	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+	{ AR5K_PHY_SIG,
+	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
+	{ AR5K_PHY_AGCCOARSE,
+	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
+	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
+	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	{ AR5K_PHY_RX_DELAY,
+	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	{ AR5K_PHY_FRAME_CTL_5211,
+	   { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
+	{ AR5K_PHY_CCKTXCTL,
+	   { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
+	{ AR5K_PHY_CCK_CROSSCORR,
+	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	{ AR5K_PHY_GAIN_2GHZ,
+	   { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
+	{ AR5K_PHY_CCK_RX_CTL_4,
+	   { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf5112_ini_common_end[] = {
+	{ AR5K_DCU_FP,		0x00000000 },
+	{ AR5K_PHY_AGC,		0x00000000 },
+	{ AR5K_PHY_ADC_CTL,	0x00022ffe },
+	{ 0x983c,		0x00020100 },
+	{ AR5K_PHY_GAIN_OFFSET,	0x1284613c },
+	{ AR5K_PHY_PAPD_PROBE,	0x00004882 },
+	{ 0x9940,		0x00000004 },
+	{ 0x9958,		0x000000ff },
+	{ 0x9974,		0x00000000 },
+	{ AR5K_PHY_DAG_CCK_CTL,	0x000001b5 },
+	{ 0xa23c,		0x13c889af },
+};
+
+/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
+static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
+	{ AR5K_TXCFG,
+	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
+	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+	{ AR5K_USEC_5211,
+	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+	{ AR5K_PHY_RF_CTL3,
+	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+	{ AR5K_PHY_RF_CTL4,
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	{ AR5K_PHY_PA_CTL,
+	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+	{ AR5K_PHY_GAIN,
+	   { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
+	{ AR5K_PHY_DESIRED_SIZE,
+	   { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+	{ AR5K_PHY_SIG,
+	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+	{ AR5K_PHY_AGCCOARSE,
+	   { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
+	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	{ AR5K_PHY_RX_DELAY,
+	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	{ AR5K_PHY_FRAME_CTL_5211,
+	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+	{ AR5K_PHY_CCKTXCTL,
+	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ AR5K_PHY_CCK_CROSSCORR,
+	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	{ AR5K_PHY_GAIN_2GHZ,
+	   { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
+	{ AR5K_PHY_CCK_RX_CTL_4,
+	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+	{ 0xa300,
+	   { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
+	{ 0xa304,
+	   { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
+	{ 0xa308,
+	   { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
+	{ 0xa30c,
+	   { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
+	{ 0xa310,
+	   { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
+	{ 0xa314,
+	   { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
+	{ 0xa318,
+	   { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
+	{ 0xa31c,
+	   { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
+	{ 0xa320,
+	   { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
+	{ 0xa324,
+	   { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
+	{ 0xa328,
+	   { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
+	{ 0xa32c,
+	   { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
+	{ 0xa330,
+	   { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
+	{ 0xa334,
+	   { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
+};
+
+static const struct ath5k_ini rf5413_ini_common_end[] = {
+	{ AR5K_DCU_FP,		0x000003e0 },
+	{ AR5K_5414_CBCFG,	0x00000010 },
+	{ AR5K_SEQ_MASK,	0x0000000f },
+	{ 0x809c,		0x00000000 },
+	{ 0x80a0,		0x00000000 },
+	{ AR5K_MIC_QOS_CTL,	0x00000000 },
+	{ AR5K_MIC_QOS_SEL,	0x00000000 },
+	{ AR5K_MISC_MODE,	0x00000000 },
+	{ AR5K_OFDM_FIL_CNT,	0x00000000 },
+	{ AR5K_CCK_FIL_CNT,	0x00000000 },
+	{ AR5K_PHYERR_CNT1,	0x00000000 },
+	{ AR5K_PHYERR_CNT1_MASK, 0x00000000 },
+	{ AR5K_PHYERR_CNT2,	0x00000000 },
+	{ AR5K_PHYERR_CNT2_MASK, 0x00000000 },
+	{ AR5K_TSF_THRES,	0x00000000 },
+	{ 0x8140,		0x800003f9 },
+	{ 0x8144,		0x00000000 },
+	{ AR5K_PHY_AGC,		0x00000000 },
+	{ AR5K_PHY_ADC_CTL,	0x0000a000 },
+	{ 0x983c,		0x00200400 },
+	{ AR5K_PHY_GAIN_OFFSET, 0x1284233c },
+	{ AR5K_PHY_SCR,		0x0000001f },
+	{ AR5K_PHY_SLMT,	0x00000080 },
+	{ AR5K_PHY_SCAL,	0x0000000e },
+	{ 0x9958,		0x00081fff },
+	{ AR5K_PHY_TIMING_7,	0x00000000 },
+	{ AR5K_PHY_TIMING_8,	0x02800000 },
+	{ AR5K_PHY_TIMING_11,	0x00000000 },
+	{ AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
+	{ 0x99e4,		0xaaaaaaaa },
+	{ 0x99e8,		0x3c466478 },
+	{ 0x99ec,		0x000000aa },
+	{ AR5K_PHY_SCLOCK,	0x0000000c },
+	{ AR5K_PHY_SDELAY,	0x000000ff },
+	{ AR5K_PHY_SPENDING,	0x00000014 },
+	{ AR5K_PHY_DAG_CCK_CTL, 0x000009b5 },
+	{ 0xa23c,		0x93c889af },
+	{ AR5K_PHY_FAST_ADC,	0x00000001 },
+	{ 0xa250,		0x0000a000 },
+	{ AR5K_PHY_BLUETOOTH,	0x00000000 },
+	{ AR5K_PHY_TPC_RG1,	0x0cc75380 },
+	{ 0xa25c,		0x0f0f0f01 },
+	{ 0xa260,		0x5f690f01 },
+	{ 0xa264,		0x00418a11 },
+	{ 0xa268,		0x00000000 },
+	{ AR5K_PHY_TPC_RG5,	0x0c30c16a },
+	{ 0xa270, 0x00820820 },
+	{ 0xa274, 0x081b7caa },
+	{ 0xa278, 0x1ce739ce },
+	{ 0xa27c, 0x051701ce },
+	{ 0xa338, 0x00000000 },
+	{ 0xa33c, 0x00000000 },
+	{ 0xa340, 0x00000000 },
+	{ 0xa344, 0x00000000 },
+	{ 0xa348, 0x3fffffff },
+	{ 0xa34c, 0x3fffffff },
+	{ 0xa350, 0x3fffffff },
+	{ 0xa354, 0x0003ffff },
+	{ 0xa358, 0x79a8aa1f },
+	{ 0xa35c, 0x066c420f },
+	{ 0xa360, 0x0f282207 },
+	{ 0xa364, 0x17601685 },
+	{ 0xa368, 0x1f801104 },
+	{ 0xa36c, 0x37a00c03 },
+	{ 0xa370, 0x3fc40883 },
+	{ 0xa374, 0x57c00803 },
+	{ 0xa378, 0x5fd80682 },
+	{ 0xa37c, 0x7fe00482 },
+	{ 0xa380, 0x7f3c7bba },
+	{ 0xa384, 0xf3307ff0 },
+};
+
+/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
+/* XXX: a mode ? */
+static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
+	{ AR5K_TXCFG,
+	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
+	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+	{ AR5K_USEC_5211,
+	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+	{ AR5K_PHY_RF_CTL3,
+	   { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } },
+	{ AR5K_PHY_RF_CTL4,
+	   { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } },
+	{ AR5K_PHY_PA_CTL,
+	   { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } },
+	{ AR5K_PHY_GAIN,
+	   { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
+	{ AR5K_PHY_DESIRED_SIZE,
+	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } },
+	{ AR5K_PHY_SIG,
+	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } },
+	{ AR5K_PHY_AGCCOARSE,
+	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } },
+	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
+	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	{ AR5K_PHY_RX_DELAY,
+	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	{ AR5K_PHY_FRAME_CTL_5211,
+	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+	{ AR5K_PHY_CCKTXCTL,
+	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ AR5K_PHY_CCK_CROSSCORR,
+	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	{ AR5K_PHY_GAIN_2GHZ,
+	   { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } },
+	{ AR5K_PHY_CCK_RX_CTL_4,
+	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+};
+
+static const struct ath5k_ini rf2413_ini_common_end[] = {
+	{ AR5K_DCU_FP,		0x000003e0 },
+	{ AR5K_SEQ_MASK,	0x0000000f },
+	{ AR5K_MIC_QOS_CTL,	0x00000000 },
+	{ AR5K_MIC_QOS_SEL,	0x00000000 },
+	{ AR5K_MISC_MODE,	0x00000000 },
+	{ AR5K_OFDM_FIL_CNT,	0x00000000 },
+	{ AR5K_CCK_FIL_CNT,	0x00000000 },
+	{ AR5K_PHYERR_CNT1,	0x00000000 },
+	{ AR5K_PHYERR_CNT1_MASK, 0x00000000 },
+	{ AR5K_PHYERR_CNT2,	0x00000000 },
+	{ AR5K_PHYERR_CNT2_MASK, 0x00000000 },
+	{ AR5K_TSF_THRES,	0x00000000 },
+	{ 0x8140,		0x800000a8 },
+	{ 0x8144,		0x00000000 },
+	{ AR5K_PHY_AGC,		0x00000000 },
+	{ AR5K_PHY_ADC_CTL,	0x0000a000 },
+	{ 0x983c,		0x00200400 },
+	{ AR5K_PHY_GAIN_OFFSET,	0x1284233c },
+	{ AR5K_PHY_SCR,		0x0000001f },
+	{ AR5K_PHY_SLMT,	0x00000080 },
+	{ AR5K_PHY_SCAL,	0x0000000e },
+	{ 0x9958,		0x000000ff },
+	{ AR5K_PHY_TIMING_7,	0x00000000 },
+	{ AR5K_PHY_TIMING_8,	0x02800000 },
+	{ AR5K_PHY_TIMING_11,	0x00000000 },
+	{ AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
+	{ 0x99e4,		0xaaaaaaaa },
+	{ 0x99e8,		0x3c466478 },
+	{ 0x99ec,		0x000000aa },
+	{ AR5K_PHY_SCLOCK,	0x0000000c },
+	{ AR5K_PHY_SDELAY,	0x000000ff },
+	{ AR5K_PHY_SPENDING,	0x00000014 },
+	{ AR5K_PHY_DAG_CCK_CTL,	0x000009b5 },
+	{ 0xa23c,		0x93c889af },
+	{ AR5K_PHY_FAST_ADC,	0x00000001 },
+	{ 0xa250,		0x0000a000 },
+	{ AR5K_PHY_BLUETOOTH,	0x00000000 },
+	{ AR5K_PHY_TPC_RG1,	0x0cc75380 },
+	{ 0xa25c,		0x0f0f0f01 },
+	{ 0xa260,		0x5f690f01 },
+	{ 0xa264,		0x00418a11 },
+	{ 0xa268,		0x00000000 },
+	{ AR5K_PHY_TPC_RG5,	0x0c30c16a },
+	{ 0xa270, 0x00820820 },
+	{ 0xa274, 0x001b7caa },
+	{ 0xa278, 0x1ce739ce },
+	{ 0xa27c, 0x051701ce },
+	{ 0xa300, 0x18010000 },
+	{ 0xa304, 0x30032602 },
+	{ 0xa308, 0x48073e06 },
+	{ 0xa30c, 0x560b4c0a },
+	{ 0xa310, 0x641a600f },
+	{ 0xa314, 0x784f6e1b },
+	{ 0xa318, 0x868f7c5a },
+	{ 0xa31c, 0x8ecf865b },
+	{ 0xa320, 0x9d4f970f },
+	{ 0xa324, 0xa5cfa18f },
+	{ 0xa328, 0xb55faf1f },
+	{ 0xa32c, 0xbddfb99f },
+	{ 0xa330, 0xcd7fc73f },
+	{ 0xa334, 0xd5ffd1bf },
+	{ 0xa338, 0x00000000 },
+	{ 0xa33c, 0x00000000 },
+	{ 0xa340, 0x00000000 },
+	{ 0xa344, 0x00000000 },
+	{ 0xa348, 0x3fffffff },
+	{ 0xa34c, 0x3fffffff },
+	{ 0xa350, 0x3fffffff },
+	{ 0xa354, 0x0003ffff },
+	{ 0xa358, 0x79a8aa1f },
+	{ 0xa35c, 0x066c420f },
+	{ 0xa360, 0x0f282207 },
+	{ 0xa364, 0x17601685 },
+	{ 0xa368, 0x1f801104 },
+	{ 0xa36c, 0x37a00c03 },
+	{ 0xa370, 0x3fc40883 },
+	{ 0xa374, 0x57c00803 },
+	{ 0xa378, 0x5fd80682 },
+	{ 0xa37c, 0x7fe00482 },
+	{ 0xa380, 0x7f3c7bba },
+	{ 0xa384, 0xf3307ff0 },
+};
+
+/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
+/* XXX: a mode ? */
+static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
+	{ AR5K_TXCFG,
+	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
+	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+	{ AR5K_USEC_5211,
+	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+	{ AR5K_PHY_TURBO,
+	   { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } },
+	{ AR5K_PHY_RF_CTL3,
+	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+	{ AR5K_PHY_RF_CTL4,
+	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+	{ AR5K_PHY_PA_CTL,
+	   { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } },
+	{ AR5K_PHY_SETTLING,
+	   { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } },
+	{ AR5K_PHY_GAIN,
+	   { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } },
+	{ AR5K_PHY_DESIRED_SIZE,
+	   { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+	{ AR5K_PHY_SIG,
+	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+	{ AR5K_PHY_AGCCOARSE,
+	   { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
+	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+	{ AR5K_PHY_RX_DELAY,
+	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+	{ AR5K_PHY_FRAME_CTL_5211,
+	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+	{ AR5K_PHY_CCKTXCTL,
+	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ AR5K_PHY_CCK_CROSSCORR,
+	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+	{ AR5K_PHY_GAIN_2GHZ,
+	   { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } },
+	{ AR5K_PHY_CCK_RX_CTL_4,
+	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+	{ 0xa324,
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	{ 0xa328,
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	{ 0xa32c,
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	{ 0xa330,
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+	{ 0xa334,
+	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+};
+
+static const struct ath5k_ini rf2425_ini_common_end[] = {
+	{ AR5K_DCU_FP,		0x000003e0 },
+	{ AR5K_SEQ_MASK,	0x0000000f },
+	{ 0x809c,		0x00000000 },
+	{ 0x80a0,		0x00000000 },
+	{ AR5K_MIC_QOS_CTL,	0x00000000 },
+	{ AR5K_MIC_QOS_SEL,	0x00000000 },
+	{ AR5K_MISC_MODE,	0x00000000 },
+	{ AR5K_OFDM_FIL_CNT,	0x00000000 },
+	{ AR5K_CCK_FIL_CNT,	0x00000000 },
+	{ AR5K_PHYERR_CNT1,	0x00000000 },
+	{ AR5K_PHYERR_CNT1_MASK, 0x00000000 },
+	{ AR5K_PHYERR_CNT2,	0x00000000 },
+	{ AR5K_PHYERR_CNT2_MASK, 0x00000000 },
+	{ AR5K_TSF_THRES,	0x00000000 },
+	{ 0x8140,		0x800003f9 },
+	{ 0x8144,		0x00000000 },
+	{ AR5K_PHY_AGC,		0x00000000 },
+	{ AR5K_PHY_ADC_CTL,	0x0000a000 },
+	{ 0x983c,		0x00200400 },
+	{ AR5K_PHY_GAIN_OFFSET, 0x1284233c },
+	{ AR5K_PHY_SCR,		0x0000001f },
+	{ AR5K_PHY_SLMT,	0x00000080 },
+	{ AR5K_PHY_SCAL,	0x0000000e },
+	{ 0x9958,		0x00081fff },
+	{ AR5K_PHY_TIMING_7,	0x00000000 },
+	{ AR5K_PHY_TIMING_8,	0x02800000 },
+	{ AR5K_PHY_TIMING_11,	0x00000000 },
+	{ 0x99dc,		0xfebadbe8 },
+	{ AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
+	{ 0x99e4,		0xaaaaaaaa },
+	{ 0x99e8,		0x3c466478 },
+	{ 0x99ec,		0x000000aa },
+	{ AR5K_PHY_SCLOCK,	0x0000000c },
+	{ AR5K_PHY_SDELAY,	0x000000ff },
+	{ AR5K_PHY_SPENDING,	0x00000014 },
+	{ AR5K_PHY_DAG_CCK_CTL,	0x000009b5 },
+	{ AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
+	{ AR5K_PHY_TXPOWER_RATE4, 0x20202020 },
+	{ 0xa23c,		0x93c889af },
+	{ AR5K_PHY_FAST_ADC,	0x00000001 },
+	{ 0xa250,		0x0000a000 },
+	{ AR5K_PHY_BLUETOOTH,	0x00000000 },
+	{ AR5K_PHY_TPC_RG1,	0x0cc75380 },
+	{ 0xa25c,		0x0f0f0f01 },
+	{ 0xa260,		0x5f690f01 },
+	{ 0xa264,		0x00418a11 },
+	{ 0xa268,		0x00000000 },
+	{ AR5K_PHY_TPC_RG5,	0x0c30c166 },
+	{ 0xa270, 0x00820820 },
+	{ 0xa274, 0x081a3caa },
+	{ 0xa278, 0x1ce739ce },
+	{ 0xa27c, 0x051701ce },
+	{ 0xa300, 0x16010000 },
+	{ 0xa304, 0x2c032402 },
+	{ 0xa308, 0x48433e42 },
+	{ 0xa30c, 0x5a0f500b },
+	{ 0xa310, 0x6c4b624a },
+	{ 0xa314, 0x7e8b748a },
+	{ 0xa318, 0x96cf8ccb },
+	{ 0xa31c, 0xa34f9d0f },
+	{ 0xa320, 0xa7cfa58f },
+	{ 0xa348, 0x3fffffff },
+	{ 0xa34c, 0x3fffffff },
+	{ 0xa350, 0x3fffffff },
+	{ 0xa354, 0x0003ffff },
+	{ 0xa358, 0x79a8aa1f },
+	{ 0xa35c, 0x066c420f },
+	{ 0xa360, 0x0f282207 },
+	{ 0xa364, 0x17601685 },
+	{ 0xa368, 0x1f801104 },
+	{ 0xa36c, 0x37a00c03 },
+	{ 0xa370, 0x3fc40883 },
+	{ 0xa374, 0x57c00803 },
+	{ 0xa378, 0x5fd80682 },
+	{ 0xa37c, 0x7fe00482 },
+	{ 0xa380, 0x7f3c7bba },
+	{ 0xa384, 0xf3307ff0 },
+};
+
+/*
+ * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
+ * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
+ */
+
+/* RF5111 Initial BaseBand Gain settings */
+static const struct ath5k_ini rf5111_ini_bbgain[] = {
+	{ AR5K_BB_GAIN(0), 0x00000000 },
+	{ AR5K_BB_GAIN(1), 0x00000020 },
+	{ AR5K_BB_GAIN(2), 0x00000010 },
+	{ AR5K_BB_GAIN(3), 0x00000030 },
+	{ AR5K_BB_GAIN(4), 0x00000008 },
+	{ AR5K_BB_GAIN(5), 0x00000028 },
+	{ AR5K_BB_GAIN(6), 0x00000004 },
+	{ AR5K_BB_GAIN(7), 0x00000024 },
+	{ AR5K_BB_GAIN(8), 0x00000014 },
+	{ AR5K_BB_GAIN(9), 0x00000034 },
+	{ AR5K_BB_GAIN(10), 0x0000000c },
+	{ AR5K_BB_GAIN(11), 0x0000002c },
+	{ AR5K_BB_GAIN(12), 0x00000002 },
+	{ AR5K_BB_GAIN(13), 0x00000022 },
+	{ AR5K_BB_GAIN(14), 0x00000012 },
+	{ AR5K_BB_GAIN(15), 0x00000032 },
+	{ AR5K_BB_GAIN(16), 0x0000000a },
+	{ AR5K_BB_GAIN(17), 0x0000002a },
+	{ AR5K_BB_GAIN(18), 0x00000006 },
+	{ AR5K_BB_GAIN(19), 0x00000026 },
+	{ AR5K_BB_GAIN(20), 0x00000016 },
+	{ AR5K_BB_GAIN(21), 0x00000036 },
+	{ AR5K_BB_GAIN(22), 0x0000000e },
+	{ AR5K_BB_GAIN(23), 0x0000002e },
+	{ AR5K_BB_GAIN(24), 0x00000001 },
+	{ AR5K_BB_GAIN(25), 0x00000021 },
+	{ AR5K_BB_GAIN(26), 0x00000011 },
+	{ AR5K_BB_GAIN(27), 0x00000031 },
+	{ AR5K_BB_GAIN(28), 0x00000009 },
+	{ AR5K_BB_GAIN(29), 0x00000029 },
+	{ AR5K_BB_GAIN(30), 0x00000005 },
+	{ AR5K_BB_GAIN(31), 0x00000025 },
+	{ AR5K_BB_GAIN(32), 0x00000015 },
+	{ AR5K_BB_GAIN(33), 0x00000035 },
+	{ AR5K_BB_GAIN(34), 0x0000000d },
+	{ AR5K_BB_GAIN(35), 0x0000002d },
+	{ AR5K_BB_GAIN(36), 0x00000003 },
+	{ AR5K_BB_GAIN(37), 0x00000023 },
+	{ AR5K_BB_GAIN(38), 0x00000013 },
+	{ AR5K_BB_GAIN(39), 0x00000033 },
+	{ AR5K_BB_GAIN(40), 0x0000000b },
+	{ AR5K_BB_GAIN(41), 0x0000002b },
+	{ AR5K_BB_GAIN(42), 0x0000002b },
+	{ AR5K_BB_GAIN(43), 0x0000002b },
+	{ AR5K_BB_GAIN(44), 0x0000002b },
+	{ AR5K_BB_GAIN(45), 0x0000002b },
+	{ AR5K_BB_GAIN(46), 0x0000002b },
+	{ AR5K_BB_GAIN(47), 0x0000002b },
+	{ AR5K_BB_GAIN(48), 0x0000002b },
+	{ AR5K_BB_GAIN(49), 0x0000002b },
+	{ AR5K_BB_GAIN(50), 0x0000002b },
+	{ AR5K_BB_GAIN(51), 0x0000002b },
+	{ AR5K_BB_GAIN(52), 0x0000002b },
+	{ AR5K_BB_GAIN(53), 0x0000002b },
+	{ AR5K_BB_GAIN(54), 0x0000002b },
+	{ AR5K_BB_GAIN(55), 0x0000002b },
+	{ AR5K_BB_GAIN(56), 0x0000002b },
+	{ AR5K_BB_GAIN(57), 0x0000002b },
+	{ AR5K_BB_GAIN(58), 0x0000002b },
+	{ AR5K_BB_GAIN(59), 0x0000002b },
+	{ AR5K_BB_GAIN(60), 0x0000002b },
+	{ AR5K_BB_GAIN(61), 0x0000002b },
+	{ AR5K_BB_GAIN(62), 0x00000002 },
+	{ AR5K_BB_GAIN(63), 0x00000016 },
+};
+
+/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */
+static const struct ath5k_ini rf5112_ini_bbgain[] = {
+	{ AR5K_BB_GAIN(0), 0x00000000 },
+	{ AR5K_BB_GAIN(1), 0x00000001 },
+	{ AR5K_BB_GAIN(2), 0x00000002 },
+	{ AR5K_BB_GAIN(3), 0x00000003 },
+	{ AR5K_BB_GAIN(4), 0x00000004 },
+	{ AR5K_BB_GAIN(5), 0x00000005 },
+	{ AR5K_BB_GAIN(6), 0x00000008 },
+	{ AR5K_BB_GAIN(7), 0x00000009 },
+	{ AR5K_BB_GAIN(8), 0x0000000a },
+	{ AR5K_BB_GAIN(9), 0x0000000b },
+	{ AR5K_BB_GAIN(10), 0x0000000c },
+	{ AR5K_BB_GAIN(11), 0x0000000d },
+	{ AR5K_BB_GAIN(12), 0x00000010 },
+	{ AR5K_BB_GAIN(13), 0x00000011 },
+	{ AR5K_BB_GAIN(14), 0x00000012 },
+	{ AR5K_BB_GAIN(15), 0x00000013 },
+	{ AR5K_BB_GAIN(16), 0x00000014 },
+	{ AR5K_BB_GAIN(17), 0x00000015 },
+	{ AR5K_BB_GAIN(18), 0x00000018 },
+	{ AR5K_BB_GAIN(19), 0x00000019 },
+	{ AR5K_BB_GAIN(20), 0x0000001a },
+	{ AR5K_BB_GAIN(21), 0x0000001b },
+	{ AR5K_BB_GAIN(22), 0x0000001c },
+	{ AR5K_BB_GAIN(23), 0x0000001d },
+	{ AR5K_BB_GAIN(24), 0x00000020 },
+	{ AR5K_BB_GAIN(25), 0x00000021 },
+	{ AR5K_BB_GAIN(26), 0x00000022 },
+	{ AR5K_BB_GAIN(27), 0x00000023 },
+	{ AR5K_BB_GAIN(28), 0x00000024 },
+	{ AR5K_BB_GAIN(29), 0x00000025 },
+	{ AR5K_BB_GAIN(30), 0x00000028 },
+	{ AR5K_BB_GAIN(31), 0x00000029 },
+	{ AR5K_BB_GAIN(32), 0x0000002a },
+	{ AR5K_BB_GAIN(33), 0x0000002b },
+	{ AR5K_BB_GAIN(34), 0x0000002c },
+	{ AR5K_BB_GAIN(35), 0x0000002d },
+	{ AR5K_BB_GAIN(36), 0x00000030 },
+	{ AR5K_BB_GAIN(37), 0x00000031 },
+	{ AR5K_BB_GAIN(38), 0x00000032 },
+	{ AR5K_BB_GAIN(39), 0x00000033 },
+	{ AR5K_BB_GAIN(40), 0x00000034 },
+	{ AR5K_BB_GAIN(41), 0x00000035 },
+	{ AR5K_BB_GAIN(42), 0x00000035 },
+	{ AR5K_BB_GAIN(43), 0x00000035 },
+	{ AR5K_BB_GAIN(44), 0x00000035 },
+	{ AR5K_BB_GAIN(45), 0x00000035 },
+	{ AR5K_BB_GAIN(46), 0x00000035 },
+	{ AR5K_BB_GAIN(47), 0x00000035 },
+	{ AR5K_BB_GAIN(48), 0x00000035 },
+	{ AR5K_BB_GAIN(49), 0x00000035 },
+	{ AR5K_BB_GAIN(50), 0x00000035 },
+	{ AR5K_BB_GAIN(51), 0x00000035 },
+	{ AR5K_BB_GAIN(52), 0x00000035 },
+	{ AR5K_BB_GAIN(53), 0x00000035 },
+	{ AR5K_BB_GAIN(54), 0x00000035 },
+	{ AR5K_BB_GAIN(55), 0x00000035 },
+	{ AR5K_BB_GAIN(56), 0x00000035 },
+	{ AR5K_BB_GAIN(57), 0x00000035 },
+	{ AR5K_BB_GAIN(58), 0x00000035 },
+	{ AR5K_BB_GAIN(59), 0x00000035 },
+	{ AR5K_BB_GAIN(60), 0x00000035 },
+	{ AR5K_BB_GAIN(61), 0x00000035 },
+	{ AR5K_BB_GAIN(62), 0x00000010 },
+	{ AR5K_BB_GAIN(63), 0x0000001a },
+};
+
+
+/*
+ * Write initial register dump
+ */
+static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
+		const struct ath5k_ini *ini_regs, bool change_channel)
+{
+	unsigned int i;
+
+	/* Write initial registers */
+	for (i = 0; i < size; i++) {
+		/* On channel change there is
+		 * no need to mess with PCU */
+		if (change_channel &&
+				ini_regs[i].ini_register >= AR5K_PCU_MIN &&
+				ini_regs[i].ini_register <= AR5K_PCU_MAX)
+			continue;
+
+		switch (ini_regs[i].ini_mode) {
+		case AR5K_INI_READ:
+			/* Cleared on read */
+			ath5k_hw_reg_read(ah, ini_regs[i].ini_register);
+			break;
+		case AR5K_INI_WRITE:
+		default:
+			AR5K_REG_WAIT(i);
+			ath5k_hw_reg_write(ah, ini_regs[i].ini_value,
+					ini_regs[i].ini_register);
+		}
+	}
+}
+
+static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
+		unsigned int size, const struct ath5k_ini_mode *ini_mode,
+		u8 mode)
+{
+	unsigned int i;
+
+	for (i = 0; i < size; i++) {
+		AR5K_REG_WAIT(i);
+		ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode],
+			(u32)ini_mode[i].mode_register);
+	}
+
+}
+
+int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
+{
+	/*
+	 * Write initial register settings
+	 */
+
+	/* For AR5212 and combatible */
+	if (ah->ah_version == AR5K_AR5212) {
+
+		/* First set of mode-specific settings */
+		ath5k_hw_ini_mode_registers(ah,
+			ARRAY_SIZE(ar5212_ini_mode_start),
+			ar5212_ini_mode_start, mode);
+
+		/*
+		 * Write initial settings common for all modes
+		 */
+		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start),
+				ar5212_ini_common_start, change_channel);
+
+		/* Second set of mode-specific settings */
+		switch (ah->ah_radio) {
+		case AR5K_RF5111:
+
+			ath5k_hw_ini_mode_registers(ah,
+					ARRAY_SIZE(rf5111_ini_mode_end),
+					rf5111_ini_mode_end, mode);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5111_ini_common_end),
+					rf5111_ini_common_end, change_channel);
+
+			/* Baseband gain table */
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5111_ini_bbgain),
+					rf5111_ini_bbgain, change_channel);
+
+			break;
+		case AR5K_RF5112:
+
+			ath5k_hw_ini_mode_registers(ah,
+					ARRAY_SIZE(rf5112_ini_mode_end),
+					rf5112_ini_mode_end, mode);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5112_ini_common_end),
+					rf5112_ini_common_end, change_channel);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5112_ini_bbgain),
+					rf5112_ini_bbgain, change_channel);
+
+			break;
+		case AR5K_RF5413:
+
+			ath5k_hw_ini_mode_registers(ah,
+					ARRAY_SIZE(rf5413_ini_mode_end),
+					rf5413_ini_mode_end, mode);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5413_ini_common_end),
+					rf5413_ini_common_end, change_channel);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5112_ini_bbgain),
+					rf5112_ini_bbgain, change_channel);
+
+			break;
+		case AR5K_RF2316:
+		case AR5K_RF2413:
+
+			ath5k_hw_ini_mode_registers(ah,
+					ARRAY_SIZE(rf2413_ini_mode_end),
+					rf2413_ini_mode_end, mode);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf2413_ini_common_end),
+					rf2413_ini_common_end, change_channel);
+
+			/* Override settings from rf2413_ini_common_end */
+			if (ah->ah_radio == AR5K_RF2316) {
+				ath5k_hw_reg_write(ah, 0x00004000,
+							AR5K_PHY_AGC);
+				ath5k_hw_reg_write(ah, 0x081b7caa,
+							0xa274);
+			}
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5112_ini_bbgain),
+					rf5112_ini_bbgain, change_channel);
+			break;
+		case AR5K_RF2317:
+		case AR5K_RF2425:
+
+			ath5k_hw_ini_mode_registers(ah,
+					ARRAY_SIZE(rf2425_ini_mode_end),
+					rf2425_ini_mode_end, mode);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf2425_ini_common_end),
+					rf2425_ini_common_end, change_channel);
+
+			ath5k_hw_ini_registers(ah,
+					ARRAY_SIZE(rf5112_ini_bbgain),
+					rf5112_ini_bbgain, change_channel);
+			break;
+		default:
+			return -EINVAL;
+
+		}
+
+	/* For AR5211 */
+	} else if (ah->ah_version == AR5K_AR5211) {
+
+		/* AR5K_MODE_11B */
+		if (mode > 2) {
+			ATH5K_ERR(ah->ah_sc,
+				"unsupported channel mode: %d\n", mode);
+			return -EINVAL;
+		}
+
+		/* Mode-specific settings */
+		ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode),
+				ar5211_ini_mode, mode);
+
+		/*
+		 * Write initial settings common for all modes
+		 */
+		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
+				ar5211_ini, change_channel);
+
+		/* AR5211 only comes with 5111 */
+
+		/* Baseband gain table */
+		ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
+				rf5111_ini_bbgain, change_channel);
+	/* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
+	} else if (ah->ah_version == AR5K_AR5210) {
+		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
+				ar5210_ini, change_channel);
+	}
+
+	return 0;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,40 @@
+config ATH5K
+	tristate "Atheros 5xxx wireless cards support"
+	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+	select ATH_COMMON
+	select MAC80211_LEDS
+	select LEDS_CLASS
+	select NEW_LEDS
+	---help---
+	  This module adds support for wireless adapters based on
+	  Atheros 5xxx chipset.
+
+	  Currently the following chip versions are supported:
+
+	  MAC: AR5211 AR5212
+	  PHY: RF5111/2111 RF5112/2112 RF5413/2413
+
+	  This driver uses the kernel's mac80211 subsystem.
+
+	  If you choose to build a module, it'll be called ath5k. Say M if
+	  unsure.
+
+config ATH5K_DEBUG
+	bool "Atheros 5xxx debugging"
+	depends on ATH5K
+	---help---
+	  Atheros 5xxx debugging messages.
+
+	  Say Y, if and you will get debug options for ath5k.
+	  To use this, you need to mount debugfs:
+
+	  mount -t debugfs debug /sys/kernel/debug
+
+	  You will get access to files under:
+	  /sys/kernel/debug/ath5k/phy0/
+
+	  To enable debug, pass the debug level to the debug module
+	  parameter. For example:
+
+	  modprobe ath5k debug=0x00000400
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/led.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/led.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/led.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/led.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2009 Bob Copeland <me@bobcopeland.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ */
+
+#include <linux/pci.h>
+#include "ath5k.h"
+#include "base.h"
+
+#define ATH_SDEVICE(subv,subd) \
+	.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
+	.subvendor = (subv), .subdevice = (subd)
+
+#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity))
+#define ATH_PIN(data) ((data) >> 8)
+#define ATH_POLARITY(data) ((data) & 0xff)
+
+/* Devices we match on for LED config info (typically laptops) */
+static const struct pci_device_id ath5k_led_devices[] = {
+	/* AR5211 */
+	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
+	/* HP Compaq nc6xx, nc4000, nx6000 */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) },
+	/* Acer Aspire One A150 (maximlevitsky@gmail.com) */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) },
+	/* Acer Ferrari 5000 (russ.dill@gmail.com) */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) },
+	/* E-machines E510 (tuliom@gmail.com) */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) },
+	/* Acer Extensa 5620z (nekoreeve@gmail.com) */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) },
+	/* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) },
+	/* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) },
+	/* IBM-specific AR5212 (all others) */
+	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
+	{ }
+};
+
+void ath5k_led_enable(struct ath5k_softc *sc)
+{
+	if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
+		ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
+		ath5k_led_off(sc);
+	}
+}
+
+static void ath5k_led_on(struct ath5k_softc *sc)
+{
+	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+		return;
+	ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
+}
+
+void ath5k_led_off(struct ath5k_softc *sc)
+{
+	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+		return;
+	ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
+}
+
+static void
+ath5k_led_brightness_set(struct led_classdev *led_dev,
+	enum led_brightness brightness)
+{
+	struct ath5k_led *led = container_of(led_dev, struct ath5k_led,
+		led_dev);
+
+	if (brightness == LED_OFF)
+		ath5k_led_off(led->sc);
+	else
+		ath5k_led_on(led->sc);
+}
+
+static int
+ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
+		   const char *name, char *trigger)
+{
+	int err;
+
+	led->sc = sc;
+	strncpy(led->name, name, sizeof(led->name));
+	led->led_dev.name = led->name;
+	led->led_dev.default_trigger = trigger;
+	led->led_dev.brightness_set = ath5k_led_brightness_set;
+
+	err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
+	if (err) {
+		ATH5K_WARN(sc, "could not register LED %s\n", name);
+		led->sc = NULL;
+	}
+	return err;
+}
+
+static void
+ath5k_unregister_led(struct ath5k_led *led)
+{
+	if (!led->sc)
+		return;
+	led_classdev_unregister(&led->led_dev);
+	ath5k_led_off(led->sc);
+	led->sc = NULL;
+}
+
+void ath5k_unregister_leds(struct ath5k_softc *sc)
+{
+	ath5k_unregister_led(&sc->rx_led);
+	ath5k_unregister_led(&sc->tx_led);
+}
+
+int ath5k_init_leds(struct ath5k_softc *sc)
+{
+	int ret = 0;
+	struct ieee80211_hw *hw = sc->hw;
+	struct pci_dev *pdev = sc->pdev;
+	char name[ATH5K_LED_MAX_NAME_LEN + 1];
+	const struct pci_device_id *match;
+
+	match = pci_match_id(&ath5k_led_devices[0], pdev);
+	if (match) {
+		__set_bit(ATH_STAT_LEDSOFT, sc->status);
+		sc->led_pin = ATH_PIN(match->driver_data);
+		sc->led_on = ATH_POLARITY(match->driver_data);
+	}
+
+	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
+		goto out;
+
+	ath5k_led_enable(sc);
+
+	snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
+	ret = ath5k_register_led(sc, &sc->rx_led, name,
+		ieee80211_get_rx_led_name(hw));
+	if (ret)
+		goto out;
+
+	snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
+	ret = ath5k_register_led(sc, &sc->tx_led, name,
+		ieee80211_get_tx_led_name(hw));
+out:
+	return ret;
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,16 @@
+ath5k-y				+= caps.o
+ath5k-y				+= initvals.o
+ath5k-y				+= eeprom.o
+ath5k-y				+= gpio.o
+ath5k-y				+= desc.o
+ath5k-y				+= dma.o
+ath5k-y				+= qcu.o
+ath5k-y				+= pcu.o
+ath5k-y				+= phy.o
+ath5k-y				+= reset.o
+ath5k-y				+= attach.o
+ath5k-y				+= base.o
+ath5k-y				+= led.o
+ath5k-y				+= rfkill.o
+ath5k-$(CONFIG_ATH5K_DEBUG)	+= debug.o
+obj-$(CONFIG_ATH5K)		+= ath5k.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/pcu.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/pcu.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/pcu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/pcu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Matthew W. S. Bell  <mentor@madwifi.org>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*********************************\
+* Protocol Control Unit Functions *
+\*********************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*******************\
+* Generic functions *
+\*******************/
+
+/**
+ * ath5k_hw_set_opmode - Set PCU operating mode
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Initialize PCU for the various operating modes (AP/STA etc)
+ *
+ * NOTE: ah->ah_op_mode must be set before calling this.
+ */
+int ath5k_hw_set_opmode(struct ath5k_hw *ah)
+{
+	u32 pcu_reg, beacon_reg, low_id, high_id;
+
+
+	/* Preserve rest settings */
+	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+	pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
+			| AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
+			(AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+
+	beacon_reg = 0;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	switch (ah->ah_op_mode) {
+	case NL80211_IFTYPE_ADHOC:
+		pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
+		beacon_reg |= AR5K_BCR_ADHOC;
+		if (ah->ah_version == AR5K_AR5210)
+			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+		else
+			AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+		break;
+
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_MESH_POINT:
+		pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
+		beacon_reg |= AR5K_BCR_AP;
+		if (ah->ah_version == AR5K_AR5210)
+			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+		else
+			AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+		break;
+
+	case NL80211_IFTYPE_STATION:
+		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
+				AR5K_STA_ID1_PWR_SV : 0);
+	case NL80211_IFTYPE_MONITOR:
+		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+			| (ah->ah_version == AR5K_AR5210 ?
+				AR5K_STA_ID1_NO_PSPOLL : 0);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Set PCU registers
+	 */
+	low_id = AR5K_LOW_ID(ah->ah_sta_id);
+	high_id = AR5K_HIGH_ID(ah->ah_sta_id);
+	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+	/*
+	 * Set Beacon Control Register on 5210
+	 */
+	if (ah->ah_version == AR5K_AR5210)
+		ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+
+	return 0;
+}
+
+/**
+ * ath5k_hw_update - Update mib counters (mac layer statistics)
+ *
+ * @ah: The &struct ath5k_hw
+ * @stats: The &struct ieee80211_low_level_stats we use to track
+ * statistics on the driver
+ *
+ * Reads MIB counters from PCU and updates sw statistics. Must be
+ * called after a MIB interrupt.
+ */
+void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
+		struct ieee80211_low_level_stats  *stats)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	/* Read-And-Clear */
+	stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
+	stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
+	stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
+	stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
+
+	/* XXX: Should we use this to track beacon count ?
+	 * -we read it anyway to clear the register */
+	ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
+
+	/* Reset profile count registers on 5212*/
+	if (ah->ah_version == AR5K_AR5212) {
+		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
+		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
+		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
+		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
+	}
+
+	/* TODO: Handle ANI stats */
+}
+
+/**
+ * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
+ *
+ * @ah: The &struct ath5k_hw
+ * @high: Flag to determine if we want to use high transmition rate
+ * for ACKs or not
+ *
+ * If high flag is set, we tell hw to use a set of control rates based on
+ * the current transmition rate (check out control_rates array inside reset.c).
+ * If not hw just uses the lowest rate available for the current modulation
+ * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
+ */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
+{
+	if (ah->ah_version != AR5K_AR5212)
+		return;
+	else {
+		u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
+		if (high)
+			AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+		else
+			AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+	}
+}
+
+
+/******************\
+* ACK/CTS Timeouts *
+\******************/
+
+/**
+ * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+			AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
+			ah->ah_turbo) <= timeout)
+		return -EINVAL;
+
+	AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
+		ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+	return 0;
+}
+
+/**
+ * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+			AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
+}
+
+/**
+ * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
+ *
+ * @ah: The &struct ath5k_hw
+ * @timeout: Timeout in usec
+ */
+int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
+			ah->ah_turbo) <= timeout)
+		return -EINVAL;
+
+	AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
+			ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+	return 0;
+}
+
+
+/****************\
+* BSSID handling *
+\****************/
+
+/**
+ * ath5k_hw_get_lladdr - Get station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Initialize ah->ah_sta_id using the mac address provided
+ * (just a memcpy).
+ *
+ * TODO: Remove it once we merge ath5k_softc and ath5k_hw
+ */
+void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	memcpy(mac, ah->ah_sta_id, ETH_ALEN);
+}
+
+/**
+ * ath5k_hw_set_lladdr - Set station id
+ *
+ * @ah: The &struct ath5k_hw
+ * @mac: The card's mac address
+ *
+ * Set station id on hw using the provided mac address
+ */
+int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
+{
+	u32 low_id, high_id;
+	u32 pcu_reg;
+
+	ATH5K_TRACE(ah->ah_sc);
+	/* Set new station ID */
+	memcpy(ah->ah_sta_id, mac, ETH_ALEN);
+
+	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+
+	low_id = AR5K_LOW_ID(mac);
+	high_id = AR5K_HIGH_ID(mac);
+
+	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+	return 0;
+}
+
+/**
+ * ath5k_hw_set_associd - Set BSSID for association
+ *
+ * @ah: The &struct ath5k_hw
+ * @bssid: BSSID
+ * @assoc_id: Assoc id
+ *
+ * Sets the BSSID which trigers the "SME Join" operation
+ */
+void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
+{
+	u32 low_id, high_id;
+	u16 tim_offset = 0;
+
+	/*
+	 * Set simple BSSID mask on 5212
+	 */
+	if (ah->ah_version == AR5K_AR5212) {
+		ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
+							AR5K_BSS_IDM0);
+		ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
+							AR5K_BSS_IDM1);
+	}
+
+	/*
+	 * Set BSSID which triggers the "SME Join" operation
+	 */
+	low_id = AR5K_LOW_ID(bssid);
+	high_id = AR5K_HIGH_ID(bssid);
+	ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
+	ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
+				AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
+
+	if (assoc_id == 0) {
+		ath5k_hw_disable_pspoll(ah);
+		return;
+	}
+
+	AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
+			tim_offset ? tim_offset + 4 : 0);
+
+	ath5k_hw_enable_pspoll(ah, NULL, 0);
+}
+
+/**
+ * ath5k_hw_set_bssid_mask - filter out bssids we listen
+ *
+ * @ah: the &struct ath5k_hw
+ * @mask: the bssid_mask, a u8 array of size ETH_ALEN
+ *
+ * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
+ * which bits of the interface's MAC address should be looked at when trying
+ * to decide which packets to ACK. In station mode and AP mode with a single
+ * BSS every bit matters since we lock to only one BSS. In AP mode with
+ * multiple BSSes (virtual interfaces) not every bit matters because hw must
+ * accept frames for all BSSes and so we tweak some bits of our mac address
+ * in order to have multiple BSSes.
+ *
+ * NOTE: This is a simple filter and does *not* filter out all
+ * relevant frames. Some frames that are not for us might get ACKed from us
+ * by PCU because they just match the mask.
+ *
+ * When handling multiple BSSes you can get the BSSID mask by computing the
+ * set of  ~ ( MAC XOR BSSID ) for all bssids we handle.
+ *
+ * When you do this you are essentially computing the common bits of all your
+ * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
+ * the MAC address to obtain the relevant bits and compare the result with
+ * (frame's BSSID & mask) to see if they match.
+ */
+/*
+ * Simple example: on your card you have have two BSSes you have created with
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
+ *
+ *                  \
+ * MAC:                0001 |
+ * BSSID-01:   0100 | --> Belongs to us
+ * BSSID-02:   1001 |
+ *                  /
+ * -------------------
+ * BSSID-03:   0110  | --> External
+ * -------------------
+ *
+ * Our bssid_mask would then be:
+ *
+ *             On loop iteration for BSSID-01:
+ *             ~(0001 ^ 0100)  -> ~(0101)
+ *                             ->   1010
+ *             bssid_mask      =    1010
+ *
+ *             On loop iteration for BSSID-02:
+ *             bssid_mask &= ~(0001   ^   1001)
+ *             bssid_mask =   (1010)  & ~(0001 ^ 1001)
+ *             bssid_mask =   (1010)  & ~(1001)
+ *             bssid_mask =   (1010)  &  (0110)
+ *             bssid_mask =   0010
+ *
+ * A bssid_mask of 0010 means "only pay attention to the second least
+ * significant bit". This is because its the only bit common
+ * amongst the MAC and all BSSIDs we support. To findout what the real
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
+ * or our MAC address (we assume the hardware uses the MAC address).
+ *
+ * Now, suppose there's an incoming frame for BSSID-03:
+ *
+ * IFRAME-01:  0110
+ *
+ * An easy eye-inspeciton of this already should tell you that this frame
+ * will not pass our check. This is beacuse the bssid_mask tells the
+ * hardware to only look at the second least significant bit and the
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
+ * as 1, which does not match 0.
+ *
+ * So with IFRAME-01 we *assume* the hardware will do:
+ *
+ *     allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ *  --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
+ *  --> allow = (0010) == 0000 ? 1 : 0;
+ *  --> allow = 0
+ *
+ *  Lets now test a frame that should work:
+ *
+ * IFRAME-02:  0001 (we should allow)
+ *
+ *     allow = (0001 & 1010) == 1010
+ *
+ *     allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ *  --> allow = (0001 & 0010) ==  (0010 & 0001) ? 1 :0;
+ *  --> allow = (0010) == (0010)
+ *  --> allow = 1
+ *
+ * Other examples:
+ *
+ * IFRAME-03:  0100 --> allowed
+ * IFRAME-04:  1001 --> allowed
+ * IFRAME-05:  1101 --> allowed but its not for us!!!
+ *
+ */
+int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
+{
+	u32 low_id, high_id;
+	ATH5K_TRACE(ah->ah_sc);
+
+	/* Cache bssid mask so that we can restore it
+	 * on reset */
+	memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
+	if (ah->ah_version == AR5K_AR5212) {
+		low_id = AR5K_LOW_ID(mask);
+		high_id = AR5K_HIGH_ID(mask);
+
+		ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
+		ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
+
+		return 0;
+	}
+
+	return -EIO;
+}
+
+
+/************\
+* RX Control *
+\************/
+
+/**
+ * ath5k_hw_start_rx_pcu - Start RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Starts RX engine on PCU so that hw can process RXed frames
+ * (ACK etc).
+ *
+ * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
+ * TODO: Init ANI here
+ */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * at5k_hw_stop_rx_pcu - Stop RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stops RX engine on PCU
+ *
+ * TODO: Detach ANI here
+ */
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/*
+ * Set multicast filter
+ */
+void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	/* Set the multicat filter */
+	ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
+	ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
+}
+
+/*
+ * Set multicast filter by index
+ */
+int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
+{
+
+	ATH5K_TRACE(ah->ah_sc);
+	if (index >= 64)
+		return -EINVAL;
+	else if (index >= 32)
+		AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
+				(1 << (index - 32)));
+	else
+		AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
+
+	return 0;
+}
+
+/*
+ * Clear Multicast filter by index
+ */
+int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
+{
+
+	ATH5K_TRACE(ah->ah_sc);
+	if (index >= 64)
+		return -EINVAL;
+	else if (index >= 32)
+		AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
+				(1 << (index - 32)));
+	else
+		AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
+
+	return 0;
+}
+
+/**
+ * ath5k_hw_get_rx_filter - Get current rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns the RX filter by reading rx filter and
+ * phy error filter registers. RX filter is used
+ * to set the allowed frame types that PCU will accept
+ * and pass to the driver. For a list of frame types
+ * check out reg.h.
+ */
+u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
+{
+	u32 data, filter = 0;
+
+	ATH5K_TRACE(ah->ah_sc);
+	filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
+
+	/*Radar detection for 5212*/
+	if (ah->ah_version == AR5K_AR5212) {
+		data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
+
+		if (data & AR5K_PHY_ERR_FIL_RADAR)
+			filter |= AR5K_RX_FILTER_RADARERR;
+		if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
+			filter |= AR5K_RX_FILTER_PHYERR;
+	}
+
+	return filter;
+}
+
+/**
+ * ath5k_hw_set_rx_filter - Set rx filter
+ *
+ * @ah: The &struct ath5k_hw
+ * @filter: RX filter mask (see reg.h)
+ *
+ * Sets RX filter register and also handles PHY error filter
+ * register on 5212 and newer chips so that we have proper PHY
+ * error reporting.
+ */
+void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
+{
+	u32 data = 0;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/* Set PHY error filter register on 5212*/
+	if (ah->ah_version == AR5K_AR5212) {
+		if (filter & AR5K_RX_FILTER_RADARERR)
+			data |= AR5K_PHY_ERR_FIL_RADAR;
+		if (filter & AR5K_RX_FILTER_PHYERR)
+			data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
+	}
+
+	/*
+	 * The AR5210 uses promiscous mode to detect radar activity
+	 */
+	if (ah->ah_version == AR5K_AR5210 &&
+			(filter & AR5K_RX_FILTER_RADARERR)) {
+		filter &= ~AR5K_RX_FILTER_RADARERR;
+		filter |= AR5K_RX_FILTER_PROM;
+	}
+
+	/*Zero length DMA (phy error reporting) */
+	if (data)
+		AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+	else
+		AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+
+	/*Write RX Filter register*/
+	ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
+
+	/*Write PHY error filter register on 5212*/
+	if (ah->ah_version == AR5K_AR5212)
+		ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
+
+}
+
+
+/****************\
+* Beacon control *
+\****************/
+
+/**
+ * ath5k_hw_get_tsf32 - Get a 32bit TSF
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns lower 32 bits of current TSF
+ */
+u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
+}
+
+/**
+ * ath5k_hw_get_tsf64 - Get the full 64bit TSF
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Returns the current TSF
+ */
+u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
+{
+	u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+	ATH5K_TRACE(ah->ah_sc);
+
+	return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
+}
+
+/**
+ * ath5k_hw_set_tsf64 - Set a new 64bit TSF
+ *
+ * @ah: The &struct ath5k_hw
+ * @tsf64: The new 64bit TSF
+ *
+ * Sets the new TSF
+ */
+void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
+	ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
+}
+
+/**
+ * ath5k_hw_reset_tsf - Force a TSF reset
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Forces a TSF reset on PCU
+ */
+void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
+{
+	u32 val;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF;
+
+	/*
+	 * Each write to the RESET_TSF bit toggles a hardware internal
+	 * signal to reset TSF, but if left high it will cause a TSF reset
+	 * on the next chip reset as well.  Thus we always write the value
+	 * twice to clear the signal.
+	 */
+	ath5k_hw_reg_write(ah, val, AR5K_BEACON);
+	ath5k_hw_reg_write(ah, val, AR5K_BEACON);
+}
+
+/*
+ * Initialize beacon timers
+ */
+void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
+{
+	u32 timer1, timer2, timer3;
+
+	ATH5K_TRACE(ah->ah_sc);
+	/*
+	 * Set the additional timers by mode
+	 */
+	switch (ah->ah_op_mode) {
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_STATION:
+		/* In STA mode timer1 is used as next wakeup
+		 * timer and timer2 as next CFP duration start
+		 * timer. Both in 1/8TUs. */
+		/* TODO: PCF handling */
+		if (ah->ah_version == AR5K_AR5210) {
+			timer1 = 0xffffffff;
+			timer2 = 0xffffffff;
+		} else {
+			timer1 = 0x0000ffff;
+			timer2 = 0x0007ffff;
+		}
+		/* Mark associated AP as PCF incapable for now */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
+	default:
+		/* On non-STA modes timer1 is used as next DMA
+		 * beacon alert (DBA) timer and timer2 as next
+		 * software beacon alert. Both in 1/8TUs. */
+		timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
+		timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
+		break;
+	}
+
+	/* Timer3 marks the end of our ATIM window
+	 * a zero length window is not allowed because
+	 * we 'll get no beacons */
+	timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
+
+	/*
+	 * Set the beacon register and enable all timers.
+	 */
+	/* When in AP or Mesh Point mode zero timer0 to start TSF */
+	if (ah->ah_op_mode == NL80211_IFTYPE_AP ||
+	    ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT)
+		ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
+
+	ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
+	ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
+	ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
+	ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
+
+	/* Force a TSF reset if requested and enable beacons */
+	if (interval & AR5K_BEACON_RESET_TSF)
+		ath5k_hw_reset_tsf(ah);
+
+	ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
+					AR5K_BEACON_ENABLE),
+						AR5K_BEACON);
+
+	/* Flush any pending BMISS interrupts on ISR by
+	 * performing a clear-on-write operation on PISR
+	 * register for the BMISS bit (writing a bit on
+	 * ISR togles a reset for that bit and leaves
+	 * the rest bits intact) */
+	if (ah->ah_version == AR5K_AR5210)
+		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
+	else
+		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
+
+	/* TODO: Set enchanced sleep registers on AR5212
+	 * based on vif->bss_conf params, until then
+	 * disable power save reporting.*/
+	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
+
+}
+
+#if 0
+/*
+ * Set beacon timers
+ */
+int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
+		const struct ath5k_beacon_state *state)
+{
+	u32 cfp_period, next_cfp, dtim, interval, next_beacon;
+
+	/*
+	 * TODO: should be changed through *state
+	 * review struct ath5k_beacon_state struct
+	 *
+	 * XXX: These are used for cfp period bellow, are they
+	 * ok ? Is it O.K. for tsf here to be 0 or should we use
+	 * get_tsf ?
+	 */
+	u32 dtim_count = 0; /* XXX */
+	u32 cfp_count = 0; /* XXX */
+	u32 tsf = 0; /* XXX */
+
+	ATH5K_TRACE(ah->ah_sc);
+	/* Return on an invalid beacon state */
+	if (state->bs_interval < 1)
+		return -EINVAL;
+
+	interval = state->bs_interval;
+	dtim = state->bs_dtim_period;
+
+	/*
+	 * PCF support?
+	 */
+	if (state->bs_cfp_period > 0) {
+		/*
+		 * Enable PCF mode and set the CFP
+		 * (Contention Free Period) and timer registers
+		 */
+		cfp_period = state->bs_cfp_period * state->bs_dtim_period *
+			state->bs_interval;
+		next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
+			state->bs_interval;
+
+		AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
+				AR5K_STA_ID1_DEFAULT_ANTENNA |
+				AR5K_STA_ID1_PCF);
+		ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
+		ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
+				AR5K_CFP_DUR);
+		ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
+						next_cfp)) << 3, AR5K_TIMER2);
+	} else {
+		/* Disable PCF mode */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+				AR5K_STA_ID1_DEFAULT_ANTENNA |
+				AR5K_STA_ID1_PCF);
+	}
+
+	/*
+	 * Enable the beacon timer register
+	 */
+	ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
+
+	/*
+	 * Start the beacon timers
+	 */
+	ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &
+		~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
+		AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
+		AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
+		AR5K_BEACON_PERIOD), AR5K_BEACON);
+
+	/*
+	 * Write new beacon miss threshold, if it appears to be valid
+	 * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
+	 * and return if its not in range. We can test this by reading value and
+	 * setting value to a largest value and seeing which values register.
+	 */
+
+	AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
+			state->bs_bmiss_threshold);
+
+	/*
+	 * Set sleep control register
+	 * XXX: Didn't find this in 5210 code but since this register
+	 * exists also in ar5k's 5210 headers i leave it as common code.
+	 */
+	AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
+			(state->bs_sleep_duration - 3) << 3);
+
+	/*
+	 * Set enhanced sleep registers on 5212
+	 */
+	if (ah->ah_version == AR5K_AR5212) {
+		if (state->bs_sleep_duration > state->bs_interval &&
+				roundup(state->bs_sleep_duration, interval) ==
+				state->bs_sleep_duration)
+			interval = state->bs_sleep_duration;
+
+		if (state->bs_sleep_duration > dtim && (dtim == 0 ||
+				roundup(state->bs_sleep_duration, dtim) ==
+				state->bs_sleep_duration))
+			dtim = state->bs_sleep_duration;
+
+		if (interval > dtim)
+			return -EINVAL;
+
+		next_beacon = interval == dtim ? state->bs_next_dtim :
+			state->bs_next_beacon;
+
+		ath5k_hw_reg_write(ah,
+			AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
+			AR5K_SLEEP0_NEXT_DTIM) |
+			AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
+			AR5K_SLEEP0_ENH_SLEEP_EN |
+			AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
+
+		ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
+			AR5K_SLEEP1_NEXT_TIM) |
+			AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
+
+		ath5k_hw_reg_write(ah,
+			AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
+			AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
+	}
+
+	return 0;
+}
+
+/*
+ * Reset beacon timers
+ */
+void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	/*
+	 * Disable beacon timer
+	 */
+	ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
+
+	/*
+	 * Disable some beacon register values
+	 */
+	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+			AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
+	ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
+}
+
+/*
+ * Wait for beacon queue to finish
+ */
+int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
+{
+	unsigned int i;
+	int ret;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/* 5210 doesn't have QCU*/
+	if (ah->ah_version == AR5K_AR5210) {
+		/*
+		 * Wait for beaconn queue to finish by checking
+		 * Control Register and Beacon Status Register.
+		 */
+		for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
+			if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
+					||
+			    !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
+				break;
+			udelay(10);
+		}
+
+		/* Timeout... */
+		if (i <= 0) {
+			/*
+			 * Re-schedule the beacon queue
+			 */
+			ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
+			ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
+					AR5K_BCR);
+
+			return -EIO;
+		}
+		ret = 0;
+	} else {
+	/*5211/5212*/
+		ret = ath5k_hw_register_timeout(ah,
+			AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
+			AR5K_QCU_STS_FRMPENDCNT, 0, false);
+
+		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
+			return -EIO;
+	}
+
+	return ret;
+}
+#endif
+
+
+/*********************\
+* Key table functions *
+\*********************/
+
+/*
+ * Reset a key entry on the table
+ */
+int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+{
+	unsigned int i, type;
+	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
+
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+	type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
+
+	for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
+		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+
+	/* Reset associated MIC entry if TKIP
+	 * is enabled located at offset (entry + 64) */
+	if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+		AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
+		for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
+			ath5k_hw_reg_write(ah, 0,
+				AR5K_KEYTABLE_OFF(micentry, i));
+	}
+
+	/*
+	 * Set NULL encryption on AR5212+
+	 *
+	 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
+	 *       AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
+	 *
+	 * Note2: Windows driver (ndiswrapper) sets this to
+	 *        0x00000714 instead of 0x00000007
+	 */
+	if (ah->ah_version >= AR5K_AR5211) {
+		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+				AR5K_KEYTABLE_TYPE(entry));
+
+		if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+			ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+				AR5K_KEYTABLE_TYPE(micentry));
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Check if a table entry is valid
+ */
+int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+	/* Check the validation flag at the end of the entry */
+	return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
+		AR5K_KEYTABLE_VALID;
+}
+
+static
+int ath5k_keycache_type(const struct ieee80211_key_conf *key)
+{
+	switch (key->alg) {
+	case ALG_TKIP:
+		return AR5K_KEYTABLE_TYPE_TKIP;
+	case ALG_CCMP:
+		return AR5K_KEYTABLE_TYPE_CCM;
+	case ALG_WEP:
+		if (key->keylen == WLAN_KEY_LEN_WEP40)
+			return AR5K_KEYTABLE_TYPE_40;
+		else if (key->keylen == WLAN_KEY_LEN_WEP104)
+			return AR5K_KEYTABLE_TYPE_104;
+		return -EINVAL;
+	default:
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+/*
+ * Set a key entry on the table
+ */
+int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
+		const struct ieee80211_key_conf *key, const u8 *mac)
+{
+	unsigned int i;
+	int keylen;
+	__le32 key_v[5] = {};
+	__le32 key0 = 0, key1 = 0;
+	__le32 *rxmic, *txmic;
+	int keytype;
+	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
+	bool is_tkip;
+	const u8 *key_ptr;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	is_tkip = (key->alg == ALG_TKIP);
+
+	/*
+	 * key->keylen comes in from mac80211 in bytes.
+	 * TKIP is 128 bit + 128 bit mic
+	 */
+	keylen = (is_tkip) ? (128 / 8) : key->keylen;
+
+	if (entry > AR5K_KEYTABLE_SIZE ||
+		(is_tkip && micentry > AR5K_KEYTABLE_SIZE))
+		return -EOPNOTSUPP;
+
+	if (unlikely(keylen > 16))
+		return -EOPNOTSUPP;
+
+	keytype = ath5k_keycache_type(key);
+	if (keytype < 0)
+		return keytype;
+
+	/*
+	 * each key block is 6 bytes wide, written as pairs of
+	 * alternating 32 and 16 bit le values.
+	 */
+	key_ptr = key->key;
+	for (i = 0; keylen >= 6; keylen -= 6) {
+		memcpy(&key_v[i], key_ptr, 6);
+		i += 2;
+		key_ptr += 6;
+	}
+	if (keylen)
+		memcpy(&key_v[i], key_ptr, keylen);
+
+	/* intentionally corrupt key until mic is installed */
+	if (is_tkip) {
+		key0 = key_v[0] = ~key_v[0];
+		key1 = key_v[1] = ~key_v[1];
+	}
+
+	for (i = 0; i < ARRAY_SIZE(key_v); i++)
+		ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
+				AR5K_KEYTABLE_OFF(entry, i));
+
+	ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
+
+	if (is_tkip) {
+		/* Install rx/tx MIC */
+		rxmic = (__le32 *) &key->key[16];
+		txmic = (__le32 *) &key->key[24];
+
+		if (ah->ah_combined_mic) {
+			key_v[0] = rxmic[0];
+			key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16);
+			key_v[2] = rxmic[1];
+			key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff);
+			key_v[4] = txmic[1];
+		} else {
+			key_v[0] = rxmic[0];
+			key_v[1] = 0;
+			key_v[2] = rxmic[1];
+			key_v[3] = 0;
+			key_v[4] = 0;
+		}
+		for (i = 0; i < ARRAY_SIZE(key_v); i++)
+			ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
+				AR5K_KEYTABLE_OFF(micentry, i));
+
+		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+			AR5K_KEYTABLE_TYPE(micentry));
+		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
+		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
+
+		/* restore first 2 words of key */
+		ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
+			AR5K_KEYTABLE_OFF(entry, 0));
+		ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
+			AR5K_KEYTABLE_OFF(entry, 1));
+	}
+
+	return ath5k_hw_set_key_lladdr(ah, entry, mac);
+}
+
+int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
+{
+	u32 low_id, high_id;
+
+	ATH5K_TRACE(ah->ah_sc);
+	 /* Invalid entry (key table overflow) */
+	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+	/* MAC may be NULL if it's a broadcast key. In this case no need to
+	 * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
+	if (!mac) {
+		low_id = 0xffffffff;
+		high_id = 0xffff | AR5K_KEYTABLE_VALID;
+	} else {
+		low_id = AR5K_LOW_ID(mac);
+		high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
+	}
+
+	ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
+	ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/phy.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3044 @@
+/*
+ * PHY functions
+ *
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#define _ATH5K_PHY
+
+#include <linux/delay.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+#include "rfbuffer.h"
+#include "rfgain.h"
+
+/*
+ * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
+ */
+static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
+					const struct ath5k_rf_reg *rf_regs,
+					u32 val, u8 reg_id, bool set)
+{
+	const struct ath5k_rf_reg *rfreg = NULL;
+	u8 offset, bank, num_bits, col, position;
+	u16 entry;
+	u32 mask, data, last_bit, bits_shifted, first_bit;
+	u32 *rfb;
+	s32 bits_left;
+	int i;
+
+	data = 0;
+	rfb = ah->ah_rf_banks;
+
+	for (i = 0; i < ah->ah_rf_regs_count; i++) {
+		if (rf_regs[i].index == reg_id) {
+			rfreg = &rf_regs[i];
+			break;
+		}
+	}
+
+	if (rfb == NULL || rfreg == NULL) {
+		ATH5K_PRINTF("Rf register not found!\n");
+		/* should not happen */
+		return 0;
+	}
+
+	bank = rfreg->bank;
+	num_bits = rfreg->field.len;
+	first_bit = rfreg->field.pos;
+	col = rfreg->field.col;
+
+	/* first_bit is an offset from bank's
+	 * start. Since we have all banks on
+	 * the same array, we use this offset
+	 * to mark each bank's start */
+	offset = ah->ah_offset[bank];
+
+	/* Boundary check */
+	if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) {
+		ATH5K_PRINTF("invalid values at offset %u\n", offset);
+		return 0;
+	}
+
+	entry = ((first_bit - 1) / 8) + offset;
+	position = (first_bit - 1) % 8;
+
+	if (set)
+		data = ath5k_hw_bitswap(val, num_bits);
+
+	for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
+	position = 0, entry++) {
+
+		last_bit = (position + bits_left > 8) ? 8 :
+					position + bits_left;
+
+		mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) <<
+								(col * 8);
+
+		if (set) {
+			rfb[entry] &= ~mask;
+			rfb[entry] |= ((data << position) << (col * 8)) & mask;
+			data >>= (8 - position);
+		} else {
+			data |= (((rfb[entry] & mask) >> (col * 8)) >> position)
+				<< bits_shifted;
+			bits_shifted += last_bit - position;
+		}
+
+		bits_left -= 8 - position;
+	}
+
+	data = set ? 1 : ath5k_hw_bitswap(data, num_bits);
+
+	return data;
+}
+
+/**********************\
+* RF Gain optimization *
+\**********************/
+
+/*
+ * This code is used to optimize rf gain on different environments
+ * (temprature mostly) based on feedback from a power detector.
+ *
+ * It's only used on RF5111 and RF5112, later RF chips seem to have
+ * auto adjustment on hw -notice they have a much smaller BANK 7 and
+ * no gain optimization ladder-.
+ *
+ * For more infos check out this patent doc
+ * http://www.freepatentsonline.com/7400691.html
+ *
+ * This paper describes power drops as seen on the receiver due to
+ * probe packets
+ * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues
+ * %20of%20Power%20Control.pdf
+ *
+ * And this is the MadWiFi bug entry related to the above
+ * http://madwifi-project.org/ticket/1659
+ * with various measurements and diagrams
+ *
+ * TODO: Deal with power drops due to probes by setting an apropriate
+ * tx power on the probe packets ! Make this part of the calibration process.
+ */
+
+/* Initialize ah_gain durring attach */
+int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
+{
+	/* Initialize the gain optimization values */
+	switch (ah->ah_radio) {
+	case AR5K_RF5111:
+		ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
+		ah->ah_gain.g_low = 20;
+		ah->ah_gain.g_high = 35;
+		ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+		break;
+	case AR5K_RF5112:
+		ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
+		ah->ah_gain.g_low = 20;
+		ah->ah_gain.g_high = 85;
+		ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Schedule a gain probe check on the next transmited packet.
+ * That means our next packet is going to be sent with lower
+ * tx power and a Peak to Average Power Detector (PAPD) will try
+ * to measure the gain.
+ *
+ * XXX:  How about forcing a tx packet (bypassing PCU arbitrator etc)
+ * just after we enable the probe so that we don't mess with
+ * standard traffic ? Maybe it's time to use sw interrupts and
+ * a probe tasklet !!!
+ */
+static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
+{
+
+	/* Skip if gain calibration is inactive or
+	 * we already handle a probe request */
+	if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE)
+		return;
+
+	/* Send the packet with 2dB below max power as
+	 * patent doc suggest */
+	ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_ofdm - 4,
+			AR5K_PHY_PAPD_PROBE_TXPOWER) |
+			AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
+
+	ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED;
+
+}
+
+/* Calculate gain_F measurement correction
+ * based on the current step for RF5112 rev. 2 */
+static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
+{
+	u32 mix, step;
+	u32 *rf;
+	const struct ath5k_gain_opt *go;
+	const struct ath5k_gain_opt_step *g_step;
+	const struct ath5k_rf_reg *rf_regs;
+
+	/* Only RF5112 Rev. 2 supports it */
+	if ((ah->ah_radio != AR5K_RF5112) ||
+	(ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A))
+		return 0;
+
+	go = &rfgain_opt_5112;
+	rf_regs = rf_regs_5112a;
+	ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
+
+	g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+	if (ah->ah_rf_banks == NULL)
+		return 0;
+
+	rf = ah->ah_rf_banks;
+	ah->ah_gain.g_f_corr = 0;
+
+	/* No VGA (Variable Gain Amplifier) override, skip */
+	if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1)
+		return 0;
+
+	/* Mix gain stepping */
+	step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false);
+
+	/* Mix gain override */
+	mix = g_step->gos_param[0];
+
+	switch (mix) {
+	case 3:
+		ah->ah_gain.g_f_corr = step * 2;
+		break;
+	case 2:
+		ah->ah_gain.g_f_corr = (step - 5) * 2;
+		break;
+	case 1:
+		ah->ah_gain.g_f_corr = step;
+		break;
+	default:
+		ah->ah_gain.g_f_corr = 0;
+		break;
+	}
+
+	return ah->ah_gain.g_f_corr;
+}
+
+/* Check if current gain_F measurement is in the range of our
+ * power detector windows. If we get a measurement outside range
+ * we know it's not accurate (detectors can't measure anything outside
+ * their detection window) so we must ignore it */
+static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
+{
+	const struct ath5k_rf_reg *rf_regs;
+	u32 step, mix_ovr, level[4];
+	u32 *rf;
+
+	if (ah->ah_rf_banks == NULL)
+		return false;
+
+	rf = ah->ah_rf_banks;
+
+	if (ah->ah_radio == AR5K_RF5111) {
+
+		rf_regs = rf_regs_5111;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
+
+		step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP,
+			false);
+
+		level[0] = 0;
+		level[1] = (step == 63) ? 50 : step + 4;
+		level[2] = (step != 63) ? 64 : level[0];
+		level[3] = level[2] + 50 ;
+
+		ah->ah_gain.g_high = level[3] -
+			(step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
+		ah->ah_gain.g_low = level[0] +
+			(step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
+	} else {
+
+		rf_regs = rf_regs_5112;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
+
+		mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR,
+			false);
+
+		level[0] = level[2] = 0;
+
+		if (mix_ovr == 1) {
+			level[1] = level[3] = 83;
+		} else {
+			level[1] = level[3] = 107;
+			ah->ah_gain.g_high = 55;
+		}
+	}
+
+	return (ah->ah_gain.g_current >= level[0] &&
+			ah->ah_gain.g_current <= level[1]) ||
+		(ah->ah_gain.g_current >= level[2] &&
+			ah->ah_gain.g_current <= level[3]);
+}
+
+/* Perform gain_F adjustment by choosing the right set
+ * of parameters from rf gain optimization ladder */
+static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
+{
+	const struct ath5k_gain_opt *go;
+	const struct ath5k_gain_opt_step *g_step;
+	int ret = 0;
+
+	switch (ah->ah_radio) {
+	case AR5K_RF5111:
+		go = &rfgain_opt_5111;
+		break;
+	case AR5K_RF5112:
+		go = &rfgain_opt_5112;
+		break;
+	default:
+		return 0;
+	}
+
+	g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+	if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
+
+		/* Reached maximum */
+		if (ah->ah_gain.g_step_idx == 0)
+			return -1;
+
+		for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+				ah->ah_gain.g_target >=  ah->ah_gain.g_high &&
+				ah->ah_gain.g_step_idx > 0;
+				g_step = &go->go_step[ah->ah_gain.g_step_idx])
+			ah->ah_gain.g_target -= 2 *
+			    (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
+			    g_step->gos_gain);
+
+		ret = 1;
+		goto done;
+	}
+
+	if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
+
+		/* Reached minimum */
+		if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
+			return -2;
+
+		for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+				ah->ah_gain.g_target <= ah->ah_gain.g_low &&
+				ah->ah_gain.g_step_idx < go->go_steps_count-1;
+				g_step = &go->go_step[ah->ah_gain.g_step_idx])
+			ah->ah_gain.g_target -= 2 *
+			    (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
+			    g_step->gos_gain);
+
+		ret = 2;
+		goto done;
+	}
+
+done:
+	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+		"ret %d, gain step %u, current gain %u, target gain %u\n",
+		ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
+		ah->ah_gain.g_target);
+
+	return ret;
+}
+
+/* Main callback for thermal rf gain calibration engine
+ * Check for a new gain reading and schedule an adjustment
+ * if needed.
+ *
+ * TODO: Use sw interrupt to schedule reset if gain_F needs
+ * adjustment */
+enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
+{
+	u32 data, type;
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	if (ah->ah_rf_banks == NULL ||
+	ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
+		return AR5K_RFGAIN_INACTIVE;
+
+	/* No check requested, either engine is inactive
+	 * or an adjustment is already requested */
+	if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED)
+		goto done;
+
+	/* Read the PAPD (Peak to Average Power Detector)
+	 * register */
+	data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
+
+	/* No probe is scheduled, read gain_F measurement */
+	if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
+		ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
+		type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
+
+		/* If tx packet is CCK correct the gain_F measurement
+		 * by cck ofdm gain delta */
+		if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) {
+			if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
+				ah->ah_gain.g_current +=
+					ee->ee_cck_ofdm_gain_delta;
+			else
+				ah->ah_gain.g_current +=
+					AR5K_GAIN_CCK_PROBE_CORR;
+		}
+
+		/* Further correct gain_F measurement for
+		 * RF5112A radios */
+		if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
+			ath5k_hw_rf_gainf_corr(ah);
+			ah->ah_gain.g_current =
+				ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
+				(ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
+				0;
+		}
+
+		/* Check if measurement is ok and if we need
+		 * to adjust gain, schedule a gain adjustment,
+		 * else switch back to the acive state */
+		if (ath5k_hw_rf_check_gainf_readback(ah) &&
+		AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
+		ath5k_hw_rf_gainf_adjust(ah)) {
+			ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE;
+		} else {
+			ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+		}
+	}
+
+done:
+	return ah->ah_gain.g_state;
+}
+
+/* Write initial rf gain table to set the RF sensitivity
+ * this one works on all RF chips and has nothing to do
+ * with gain_F calibration */
+int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
+{
+	const struct ath5k_ini_rfgain *ath5k_rfg;
+	unsigned int i, size;
+
+	switch (ah->ah_radio) {
+	case AR5K_RF5111:
+		ath5k_rfg = rfgain_5111;
+		size = ARRAY_SIZE(rfgain_5111);
+		break;
+	case AR5K_RF5112:
+		ath5k_rfg = rfgain_5112;
+		size = ARRAY_SIZE(rfgain_5112);
+		break;
+	case AR5K_RF2413:
+		ath5k_rfg = rfgain_2413;
+		size = ARRAY_SIZE(rfgain_2413);
+		break;
+	case AR5K_RF2316:
+		ath5k_rfg = rfgain_2316;
+		size = ARRAY_SIZE(rfgain_2316);
+		break;
+	case AR5K_RF5413:
+		ath5k_rfg = rfgain_5413;
+		size = ARRAY_SIZE(rfgain_5413);
+		break;
+	case AR5K_RF2317:
+	case AR5K_RF2425:
+		ath5k_rfg = rfgain_2425;
+		size = ARRAY_SIZE(rfgain_2425);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (freq) {
+	case AR5K_INI_RFGAIN_2GHZ:
+	case AR5K_INI_RFGAIN_5GHZ:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (i = 0; i < size; i++) {
+		AR5K_REG_WAIT(i);
+		ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
+			(u32)ath5k_rfg[i].rfg_register);
+	}
+
+	return 0;
+}
+
+
+
+/********************\
+* RF Registers setup *
+\********************/
+
+
+/*
+ * Setup RF registers by writing rf buffer on hw
+ */
+int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+		unsigned int mode)
+{
+	const struct ath5k_rf_reg *rf_regs;
+	const struct ath5k_ini_rfbuffer *ini_rfb;
+	const struct ath5k_gain_opt *go = NULL;
+	const struct ath5k_gain_opt_step *g_step;
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u8 ee_mode = 0;
+	u32 *rfb;
+	int i, obdb = -1, bank = -1;
+
+	switch (ah->ah_radio) {
+	case AR5K_RF5111:
+		rf_regs = rf_regs_5111;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
+		ini_rfb = rfb_5111;
+		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111);
+		go = &rfgain_opt_5111;
+		break;
+	case AR5K_RF5112:
+		if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
+			rf_regs = rf_regs_5112a;
+			ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
+			ini_rfb = rfb_5112a;
+			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a);
+		} else {
+			rf_regs = rf_regs_5112;
+			ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
+			ini_rfb = rfb_5112;
+			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112);
+		}
+		go = &rfgain_opt_5112;
+		break;
+	case AR5K_RF2413:
+		rf_regs = rf_regs_2413;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413);
+		ini_rfb = rfb_2413;
+		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413);
+		break;
+	case AR5K_RF2316:
+		rf_regs = rf_regs_2316;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316);
+		ini_rfb = rfb_2316;
+		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316);
+		break;
+	case AR5K_RF5413:
+		rf_regs = rf_regs_5413;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413);
+		ini_rfb = rfb_5413;
+		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413);
+		break;
+	case AR5K_RF2317:
+		rf_regs = rf_regs_2425;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
+		ini_rfb = rfb_2317;
+		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317);
+		break;
+	case AR5K_RF2425:
+		rf_regs = rf_regs_2425;
+		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
+		if (ah->ah_mac_srev < AR5K_SREV_AR2417) {
+			ini_rfb = rfb_2425;
+			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425);
+		} else {
+			ini_rfb = rfb_2417;
+			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* If it's the first time we set rf buffer, allocate
+	 * ah->ah_rf_banks based on ah->ah_rf_banks_size
+	 * we set above */
+	if (ah->ah_rf_banks == NULL) {
+		ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
+								GFP_KERNEL);
+		if (ah->ah_rf_banks == NULL) {
+			ATH5K_ERR(ah->ah_sc, "out of memory\n");
+			return -ENOMEM;
+		}
+	}
+
+	/* Copy values to modify them */
+	rfb = ah->ah_rf_banks;
+
+	for (i = 0; i < ah->ah_rf_banks_size; i++) {
+		if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
+			ATH5K_ERR(ah->ah_sc, "invalid bank\n");
+			return -EINVAL;
+		}
+
+		/* Bank changed, write down the offset */
+		if (bank != ini_rfb[i].rfb_bank) {
+			bank = ini_rfb[i].rfb_bank;
+			ah->ah_offset[bank] = i;
+		}
+
+		rfb[i] = ini_rfb[i].rfb_mode_data[mode];
+	}
+
+	/* Set Output and Driver bias current (OB/DB) */
+	if (channel->hw_value & CHANNEL_2GHZ) {
+
+		if (channel->hw_value & CHANNEL_CCK)
+			ee_mode = AR5K_EEPROM_MODE_11B;
+		else
+			ee_mode = AR5K_EEPROM_MODE_11G;
+
+		/* For RF511X/RF211X combination we
+		 * use b_OB and b_DB parameters stored
+		 * in eeprom on ee->ee_ob[ee_mode][0]
+		 *
+		 * For all other chips we use OB/DB for 2Ghz
+		 * stored in the b/g modal section just like
+		 * 802.11a on ee->ee_ob[ee_mode][1] */
+		if ((ah->ah_radio == AR5K_RF5111) ||
+		(ah->ah_radio == AR5K_RF5112))
+			obdb = 0;
+		else
+			obdb = 1;
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
+						AR5K_RF_OB_2GHZ, true);
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
+						AR5K_RF_DB_2GHZ, true);
+
+	/* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
+	} else if ((channel->hw_value & CHANNEL_5GHZ) ||
+			(ah->ah_radio == AR5K_RF5111)) {
+
+		/* For 11a, Turbo and XR we need to choose
+		 * OB/DB based on frequency range */
+		ee_mode = AR5K_EEPROM_MODE_11A;
+		obdb =	 channel->center_freq >= 5725 ? 3 :
+			(channel->center_freq >= 5500 ? 2 :
+			(channel->center_freq >= 5260 ? 1 :
+			 (channel->center_freq > 4000 ? 0 : -1)));
+
+		if (obdb < 0)
+			return -EINVAL;
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
+						AR5K_RF_OB_5GHZ, true);
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
+						AR5K_RF_DB_5GHZ, true);
+	}
+
+	g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+	/* Bank Modifications (chip-specific) */
+	if (ah->ah_radio == AR5K_RF5111) {
+
+		/* Set gain_F settings according to current step */
+		if (channel->hw_value & CHANNEL_OFDM) {
+
+			AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
+					AR5K_PHY_FRAME_CTL_TX_CLIP,
+					g_step->gos_param[0]);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
+							AR5K_RF_PWD_90, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
+							AR5K_RF_PWD_84, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
+						AR5K_RF_RFGAIN_SEL, true);
+
+			/* We programmed gain_F parameters, switch back
+			 * to active state */
+			ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+
+		}
+
+		/* Bank 6/7 setup */
+
+		ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode],
+						AR5K_RF_PWD_XPD, true);
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode],
+						AR5K_RF_XPD_GAIN, true);
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
+						AR5K_RF_GAIN_I, true);
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
+						AR5K_RF_PLO_SEL, true);
+
+		/* TODO: Half/quarter channel support */
+	}
+
+	if (ah->ah_radio == AR5K_RF5112) {
+
+		/* Set gain_F settings according to current step */
+		if (channel->hw_value & CHANNEL_OFDM) {
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
+						AR5K_RF_MIXGAIN_OVR, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
+						AR5K_RF_PWD_138, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
+						AR5K_RF_PWD_137, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
+						AR5K_RF_PWD_136, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4],
+						AR5K_RF_PWD_132, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5],
+						AR5K_RF_PWD_131, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6],
+						AR5K_RF_PWD_130, true);
+
+			/* We programmed gain_F parameters, switch back
+			 * to active state */
+			ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
+		}
+
+		/* Bank 6/7 setup */
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
+						AR5K_RF_XPD_SEL, true);
+
+		if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
+			/* Rev. 1 supports only one xpd */
+			ath5k_hw_rfb_op(ah, rf_regs,
+						ee->ee_x_gain[ee_mode],
+						AR5K_RF_XPD_GAIN, true);
+
+		} else {
+			/* TODO: Set high and low gain bits */
+			ath5k_hw_rfb_op(ah, rf_regs,
+						ee->ee_x_gain[ee_mode],
+						AR5K_RF_PD_GAIN_LO, true);
+			ath5k_hw_rfb_op(ah, rf_regs,
+						ee->ee_x_gain[ee_mode],
+						AR5K_RF_PD_GAIN_HI, true);
+
+			/* Lower synth voltage on Rev 2 */
+			ath5k_hw_rfb_op(ah, rf_regs, 2,
+					AR5K_RF_HIGH_VC_CP, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, 2,
+					AR5K_RF_MID_VC_CP, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, 2,
+					AR5K_RF_LOW_VC_CP, true);
+
+			ath5k_hw_rfb_op(ah, rf_regs, 2,
+					AR5K_RF_PUSH_UP, true);
+
+			/* Decrease power consumption on 5213+ BaseBand */
+			if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+				ath5k_hw_rfb_op(ah, rf_regs, 1,
+						AR5K_RF_PAD2GND, true);
+
+				ath5k_hw_rfb_op(ah, rf_regs, 1,
+						AR5K_RF_XB2_LVL, true);
+
+				ath5k_hw_rfb_op(ah, rf_regs, 1,
+						AR5K_RF_XB5_LVL, true);
+
+				ath5k_hw_rfb_op(ah, rf_regs, 1,
+						AR5K_RF_PWD_167, true);
+
+				ath5k_hw_rfb_op(ah, rf_regs, 1,
+						AR5K_RF_PWD_166, true);
+			}
+		}
+
+		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
+						AR5K_RF_GAIN_I, true);
+
+		/* TODO: Half/quarter channel support */
+
+	}
+
+	if (ah->ah_radio == AR5K_RF5413 &&
+	channel->hw_value & CHANNEL_2GHZ) {
+
+		ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
+									true);
+
+		/* Set optimum value for early revisions (on pci-e chips) */
+		if (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
+		ah->ah_mac_srev < AR5K_SREV_AR5413)
+			ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3),
+						AR5K_RF_PWD_ICLOBUF_2G, true);
+
+	}
+
+	/* Write RF banks on hw */
+	for (i = 0; i < ah->ah_rf_banks_size; i++) {
+		AR5K_REG_WAIT(i);
+		ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register);
+	}
+
+	return 0;
+}
+
+
+/**************************\
+  PHY/RF channel functions
+\**************************/
+
+/*
+ * Check if a channel is supported
+ */
+bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+{
+	/* Check if the channel is in our supported range */
+	if (flags & CHANNEL_2GHZ) {
+		if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
+		    (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
+			return true;
+	} else if (flags & CHANNEL_5GHZ)
+		if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
+		    (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
+			return true;
+
+	return false;
+}
+
+/*
+ * Convertion needed for RF5110
+ */
+static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
+{
+	u32 athchan;
+
+	/*
+	 * Convert IEEE channel/MHz to an internal channel value used
+	 * by the AR5210 chipset. This has not been verified with
+	 * newer chipsets like the AR5212A who have a completely
+	 * different RF/PHY part.
+	 */
+	athchan = (ath5k_hw_bitswap(
+			(ieee80211_frequency_to_channel(
+				channel->center_freq) - 24) / 2, 5)
+				<< 1) | (1 << 6) | 0x1;
+	return athchan;
+}
+
+/*
+ * Set channel on RF5110
+ */
+static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
+{
+	u32 data;
+
+	/*
+	 * Set the channel and wait
+	 */
+	data = ath5k_hw_rf5110_chan2athchan(channel);
+	ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
+	ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
+	mdelay(1);
+
+	return 0;
+}
+
+/*
+ * Convertion needed for 5111
+ */
+static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
+		struct ath5k_athchan_2ghz *athchan)
+{
+	int channel;
+
+	/* Cast this value to catch negative channel numbers (>= -19) */
+	channel = (int)ieee;
+
+	/*
+	 * Map 2GHz IEEE channel to 5GHz Atheros channel
+	 */
+	if (channel <= 13) {
+		athchan->a2_athchan = 115 + channel;
+		athchan->a2_flags = 0x46;
+	} else if (channel == 14) {
+		athchan->a2_athchan = 124;
+		athchan->a2_flags = 0x44;
+	} else if (channel >= 15 && channel <= 26) {
+		athchan->a2_athchan = ((channel - 14) * 4) + 132;
+		athchan->a2_flags = 0x46;
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Set channel on 5111
+ */
+static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
+{
+	struct ath5k_athchan_2ghz ath5k_channel_2ghz;
+	unsigned int ath5k_channel =
+		ieee80211_frequency_to_channel(channel->center_freq);
+	u32 data0, data1, clock;
+	int ret;
+
+	/*
+	 * Set the channel on the RF5111 radio
+	 */
+	data0 = data1 = 0;
+
+	if (channel->hw_value & CHANNEL_2GHZ) {
+		/* Map 2GHz channel to 5GHz Atheros channel ID */
+		ret = ath5k_hw_rf5111_chan2athchan(
+			ieee80211_frequency_to_channel(channel->center_freq),
+			&ath5k_channel_2ghz);
+		if (ret)
+			return ret;
+
+		ath5k_channel = ath5k_channel_2ghz.a2_athchan;
+		data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
+		    << 5) | (1 << 4);
+	}
+
+	if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
+		clock = 1;
+		data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
+			(clock << 1) | (1 << 10) | 1;
+	} else {
+		clock = 0;
+		data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
+			<< 2) | (clock << 1) | (1 << 10) | 1;
+	}
+
+	ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
+			AR5K_RF_BUFFER);
+	ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
+			AR5K_RF_BUFFER_CONTROL_3);
+
+	return 0;
+}
+
+/*
+ * Set channel on 5112 and newer
+ */
+static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
+{
+	u32 data, data0, data1, data2;
+	u16 c;
+
+	data = data0 = data1 = data2 = 0;
+	c = channel->center_freq;
+
+	if (c < 4800) {
+		if (!((c - 2224) % 5)) {
+			data0 = ((2 * (c - 704)) - 3040) / 10;
+			data1 = 1;
+		} else if (!((c - 2192) % 5)) {
+			data0 = ((2 * (c - 672)) - 3040) / 10;
+			data1 = 0;
+		} else
+			return -EINVAL;
+
+		data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
+	} else if ((c - (c % 5)) != 2 || c > 5435) {
+		if (!(c % 20) && c >= 5120) {
+			data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
+			data2 = ath5k_hw_bitswap(3, 2);
+		} else if (!(c % 10)) {
+			data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
+			data2 = ath5k_hw_bitswap(2, 2);
+		} else if (!(c % 5)) {
+			data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
+			data2 = ath5k_hw_bitswap(1, 2);
+		} else
+			return -EINVAL;
+	} else {
+		data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+		data2 = ath5k_hw_bitswap(0, 2);
+	}
+
+	data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
+
+	ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
+	ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
+
+	return 0;
+}
+
+/*
+ * Set the channel on the RF2425
+ */
+static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
+{
+	u32 data, data0, data2;
+	u16 c;
+
+	data = data0 = data2 = 0;
+	c = channel->center_freq;
+
+	if (c < 4800) {
+		data0 = ath5k_hw_bitswap((c - 2272), 8);
+		data2 = 0;
+	/* ? 5GHz ? */
+	} else if ((c - (c % 5)) != 2 || c > 5435) {
+		if (!(c % 20) && c < 5120)
+			data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
+		else if (!(c % 10))
+			data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
+		else if (!(c % 5))
+			data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
+		else
+			return -EINVAL;
+		data2 = ath5k_hw_bitswap(1, 2);
+	} else {
+		data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+		data2 = ath5k_hw_bitswap(0, 2);
+	}
+
+	data = (data0 << 4) | data2 << 2 | 0x1001;
+
+	ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
+	ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
+
+	return 0;
+}
+
+/*
+ * Set a channel on the radio chip
+ */
+int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+{
+	int ret;
+	/*
+	 * Check bounds supported by the PHY (we don't care about regultory
+	 * restrictions at this point). Note: hw_value already has the band
+	 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
+	 * of the band by that */
+	if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
+		ATH5K_ERR(ah->ah_sc,
+			"channel frequency (%u MHz) out of supported "
+			"band range\n",
+			channel->center_freq);
+			return -EINVAL;
+	}
+
+	/*
+	 * Set the channel and wait
+	 */
+	switch (ah->ah_radio) {
+	case AR5K_RF5110:
+		ret = ath5k_hw_rf5110_channel(ah, channel);
+		break;
+	case AR5K_RF5111:
+		ret = ath5k_hw_rf5111_channel(ah, channel);
+		break;
+	case AR5K_RF2425:
+		ret = ath5k_hw_rf2425_channel(ah, channel);
+		break;
+	default:
+		ret = ath5k_hw_rf5112_channel(ah, channel);
+		break;
+	}
+
+	if (ret)
+		return ret;
+
+	/* Set JAPAN setting for channel 14 */
+	if (channel->center_freq == 2484) {
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
+				AR5K_PHY_CCKTXCTL_JAPAN);
+	} else {
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
+				AR5K_PHY_CCKTXCTL_WORLD);
+	}
+
+	ah->ah_current_channel.center_freq = channel->center_freq;
+	ah->ah_current_channel.hw_value = channel->hw_value;
+	ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
+
+	return 0;
+}
+
+/*****************\
+  PHY calibration
+\*****************/
+
+/**
+ * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
+ *
+ * @ah: struct ath5k_hw pointer we are operating on
+ * @freq: the channel frequency, just used for error logging
+ *
+ * This function performs a noise floor calibration of the PHY and waits for
+ * it to complete. Then the noise floor value is compared to some maximum
+ * noise floor we consider valid.
+ *
+ * Note that this is different from what the madwifi HAL does: it reads the
+ * noise floor and afterwards initiates the calibration. Since the noise floor
+ * calibration can take some time to finish, depending on the current channel
+ * use, that avoids the occasional timeout warnings we are seeing now.
+ *
+ * See the following link for an Atheros patent on noise floor calibration:
+ * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
+ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
+ *
+ * XXX: Since during noise floor calibration antennas are detached according to
+ * the patent, we should stop tx queues here.
+ */
+int
+ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
+{
+	int ret;
+	unsigned int i;
+	s32 noise_floor;
+
+	/*
+	 * Enable noise floor calibration
+	 */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+				AR5K_PHY_AGCCTL_NF);
+
+	ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+			AR5K_PHY_AGCCTL_NF, 0, false);
+	if (ret) {
+		ATH5K_ERR(ah->ah_sc,
+			"noise floor calibration timeout (%uMHz)\n", freq);
+		return -EAGAIN;
+	}
+
+	/* Wait until the noise floor is calibrated and read the value */
+	for (i = 20; i > 0; i--) {
+		mdelay(1);
+		noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
+		noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
+		if (noise_floor & AR5K_PHY_NF_ACTIVE) {
+			noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
+
+			if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
+				break;
+		}
+	}
+
+	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+		"noise floor %d\n", noise_floor);
+
+	if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
+		ATH5K_ERR(ah->ah_sc,
+			"noise floor calibration failed (%uMHz)\n", freq);
+		return -EAGAIN;
+	}
+
+	ah->ah_noise_floor = noise_floor;
+
+	return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5110
+ * -Fix BPSK/QAM Constellation (I/Q correction)
+ * -Calculate Noise Floor
+ */
+static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
+{
+	u32 phy_sig, phy_agc, phy_sat, beacon;
+	int ret;
+
+	/*
+	 * Disable beacons and RX/TX queues, wait
+	 */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
+		AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+	beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
+	ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
+
+	mdelay(2);
+
+	/*
+	 * Set the channel (with AGC turned off)
+	 */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+	udelay(10);
+	ret = ath5k_hw_channel(ah, channel);
+
+	/*
+	 * Activate PHY and wait
+	 */
+	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+	mdelay(1);
+
+	AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * Calibrate the radio chip
+	 */
+
+	/* Remember normal state */
+	phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
+	phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
+	phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
+
+	/* Update radio registers */
+	ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
+		AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
+
+	ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
+			AR5K_PHY_AGCCOARSE_LO)) |
+		AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
+		AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
+
+	ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
+			AR5K_PHY_ADCSAT_THR)) |
+		AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
+		AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
+
+	udelay(20);
+
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+	udelay(10);
+	ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
+	AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+	mdelay(1);
+
+	/*
+	 * Enable calibration and wait until completion
+	 */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
+
+	ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+			AR5K_PHY_AGCCTL_CAL, 0, false);
+
+	/* Reset to normal state */
+	ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
+	ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
+	ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
+
+	if (ret) {
+		ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+				channel->center_freq);
+		return ret;
+	}
+
+	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+	/*
+	 * Re-enable RX/TX and beacons
+	 */
+	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
+		AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+	ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
+
+	return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5111/5112 and newer chips
+ */
+static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
+{
+	u32 i_pwr, q_pwr;
+	s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
+	int i;
+	ATH5K_TRACE(ah->ah_sc);
+
+	if (!ah->ah_calibration ||
+		ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
+		goto done;
+
+	/* Calibration has finished, get the results and re-run */
+	for (i = 0; i <= 10; i++) {
+		iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
+		i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
+		q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
+	}
+
+	i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
+	q_coffd = q_pwr >> 7;
+
+	/* No correction */
+	if (i_coffd == 0 || q_coffd == 0)
+		goto done;
+
+	i_coff = ((-iq_corr) / i_coffd) & 0x3f;
+
+	/* Boundary check */
+	if (i_coff > 31)
+		i_coff = 31;
+	if (i_coff < -32)
+		i_coff = -32;
+
+	q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
+
+	/* Boundary check */
+	if (q_coff > 15)
+		q_coff = 15;
+	if (q_coff < -16)
+		q_coff = -16;
+
+	/* Commit new I/Q value */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
+		((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
+
+	/* Re-enable calibration -if we don't we'll commit
+	 * the same values again and again */
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+			AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
+
+done:
+
+	/* TODO: Separate noise floor calibration from I/Q calibration
+	 * since noise floor calibration interrupts rx path while I/Q
+	 * calibration doesn't. We don't need to run noise floor calibration
+	 * as often as I/Q calibration.*/
+	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+	/* Initiate a gain_F calibration */
+	ath5k_hw_request_rfgain_probe(ah);
+
+	return 0;
+}
+
+/*
+ * Perform a PHY calibration
+ */
+int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel)
+{
+	int ret;
+
+	if (ah->ah_radio == AR5K_RF5110)
+		ret = ath5k_hw_rf5110_calibrate(ah, channel);
+	else
+		ret = ath5k_hw_rf511x_calibrate(ah, channel);
+
+	return ret;
+}
+
+/***************************\
+* Spur mitigation functions *
+\***************************/
+
+bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+				struct ieee80211_channel *channel)
+{
+	u8 refclk_freq;
+
+	if ((ah->ah_radio == AR5K_RF5112) ||
+	(ah->ah_radio == AR5K_RF5413) ||
+	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+		refclk_freq = 40;
+	else
+		refclk_freq = 32;
+
+	if ((channel->center_freq % refclk_freq != 0) &&
+	((channel->center_freq % refclk_freq < 10) ||
+	(channel->center_freq % refclk_freq > 22)))
+		return true;
+	else
+		return false;
+}
+
+void
+ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
+				struct ieee80211_channel *channel)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 mag_mask[4] = {0, 0, 0, 0};
+	u32 pilot_mask[2] = {0, 0};
+	/* Note: fbin values are scaled up by 2 */
+	u16 spur_chan_fbin, chan_fbin, symbol_width, spur_detection_window;
+	s32 spur_delta_phase, spur_freq_sigma_delta;
+	s32 spur_offset, num_symbols_x16;
+	u8 num_symbol_offsets, i, freq_band;
+
+	/* Convert current frequency to fbin value (the same way channels
+	 * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale
+	 * up by 2 so we can compare it later */
+	if (channel->hw_value & CHANNEL_2GHZ) {
+		chan_fbin = (channel->center_freq - 2300) * 10;
+		freq_band = AR5K_EEPROM_BAND_2GHZ;
+	} else {
+		chan_fbin = (channel->center_freq - 4900) * 10;
+		freq_band = AR5K_EEPROM_BAND_5GHZ;
+	}
+
+	/* Check if any spur_chan_fbin from EEPROM is
+	 * within our current channel's spur detection range */
+	spur_chan_fbin = AR5K_EEPROM_NO_SPUR;
+	spur_detection_window = AR5K_SPUR_CHAN_WIDTH;
+	/* XXX: Half/Quarter channels ?*/
+	if (channel->hw_value & CHANNEL_TURBO)
+		spur_detection_window *= 2;
+
+	for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) {
+		spur_chan_fbin = ee->ee_spur_chans[i][freq_band];
+
+		/* Note: mask cleans AR5K_EEPROM_NO_SPUR flag
+		 * so it's zero if we got nothing from EEPROM */
+		if (spur_chan_fbin == AR5K_EEPROM_NO_SPUR) {
+			spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK;
+			break;
+		}
+
+		if ((chan_fbin - spur_detection_window <=
+		(spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK)) &&
+		(chan_fbin + spur_detection_window >=
+		(spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK))) {
+			spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK;
+			break;
+		}
+	}
+
+	/* We need to enable spur filter for this channel */
+	if (spur_chan_fbin) {
+		spur_offset = spur_chan_fbin - chan_fbin;
+		/*
+		 * Calculate deltas:
+		 * spur_freq_sigma_delta -> spur_offset / sample_freq << 21
+		 * spur_delta_phase -> spur_offset / chip_freq << 11
+		 * Note: Both values have 100KHz resolution
+		 */
+		/* XXX: Half/Quarter rate channels ? */
+		switch (channel->hw_value) {
+		case CHANNEL_A:
+			/* Both sample_freq and chip_freq are 40MHz */
+			spur_delta_phase = (spur_offset << 17) / 25;
+			spur_freq_sigma_delta = (spur_delta_phase >> 10);
+			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
+			break;
+		case CHANNEL_G:
+			/* sample_freq -> 40MHz chip_freq -> 44MHz
+			 * (for b compatibility) */
+			spur_freq_sigma_delta = (spur_offset << 8) / 55;
+			spur_delta_phase = (spur_offset << 17) / 25;
+			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
+			break;
+		case CHANNEL_T:
+		case CHANNEL_TG:
+			/* Both sample_freq and chip_freq are 80MHz */
+			spur_delta_phase = (spur_offset << 16) / 25;
+			spur_freq_sigma_delta = (spur_delta_phase >> 10);
+			symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz;
+			break;
+		default:
+			return;
+		}
+
+		/* Calculate pilot and magnitude masks */
+
+		/* Scale up spur_offset by 1000 to switch to 100HZ resolution
+		 * and divide by symbol_width to find how many symbols we have
+		 * Note: number of symbols is scaled up by 16 */
+		num_symbols_x16 = ((spur_offset * 1000) << 4) / symbol_width;
+
+		/* Spur is on a symbol if num_symbols_x16 % 16 is zero */
+		if (!(num_symbols_x16 & 0xF))
+			/* _X_ */
+			num_symbol_offsets = 3;
+		else
+			/* _xx_ */
+			num_symbol_offsets = 4;
+
+		for (i = 0; i < num_symbol_offsets; i++) {
+
+			/* Calculate pilot mask */
+			s32 curr_sym_off =
+				(num_symbols_x16 / 16) + i + 25;
+
+			/* Pilot magnitude mask seems to be a way to
+			 * declare the boundaries for our detection
+			 * window or something, it's 2 for the middle
+			 * value(s) where the symbol is expected to be
+			 * and 1 on the boundary values */
+			u8 plt_mag_map =
+				(i == 0 || i == (num_symbol_offsets - 1))
+								? 1 : 2;
+
+			if (curr_sym_off >= 0 && curr_sym_off <= 32) {
+				if (curr_sym_off <= 25)
+					pilot_mask[0] |= 1 << curr_sym_off;
+				else if (curr_sym_off >= 27)
+					pilot_mask[0] |= 1 << (curr_sym_off - 1);
+			} else if (curr_sym_off >= 33 && curr_sym_off <= 52)
+				pilot_mask[1] |= 1 << (curr_sym_off - 33);
+
+			/* Calculate magnitude mask (for viterbi decoder) */
+			if (curr_sym_off >= -1 && curr_sym_off <= 14)
+				mag_mask[0] |=
+					plt_mag_map << (curr_sym_off + 1) * 2;
+			else if (curr_sym_off >= 15 && curr_sym_off <= 30)
+				mag_mask[1] |=
+					plt_mag_map << (curr_sym_off - 15) * 2;
+			else if (curr_sym_off >= 31 && curr_sym_off <= 46)
+				mag_mask[2] |=
+					plt_mag_map << (curr_sym_off - 31) * 2;
+			else if (curr_sym_off >= 46 && curr_sym_off <= 53)
+				mag_mask[3] |=
+					plt_mag_map << (curr_sym_off - 47) * 2;
+
+		}
+
+		/* Write settings on hw to enable spur filter */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
+					AR5K_PHY_BIN_MASK_CTL_RATE, 0xff);
+		/* XXX: Self correlator also ? */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+					AR5K_PHY_IQ_PILOT_MASK_EN |
+					AR5K_PHY_IQ_CHAN_MASK_EN |
+					AR5K_PHY_IQ_SPUR_FILT_EN);
+
+		/* Set delta phase and freq sigma delta */
+		ath5k_hw_reg_write(ah,
+				AR5K_REG_SM(spur_delta_phase,
+					AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE) |
+				AR5K_REG_SM(spur_freq_sigma_delta,
+				AR5K_PHY_TIMING_11_SPUR_FREQ_SD) |
+				AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC,
+				AR5K_PHY_TIMING_11);
+
+		/* Write pilot masks */
+		ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_7);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8,
+					AR5K_PHY_TIMING_8_PILOT_MASK_2,
+					pilot_mask[1]);
+
+		ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_9);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10,
+					AR5K_PHY_TIMING_10_PILOT_MASK_2,
+					pilot_mask[1]);
+
+		/* Write magnitude masks */
+		ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK_1);
+		ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK_2);
+		ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK_3);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
+					AR5K_PHY_BIN_MASK_CTL_MASK_4,
+					mag_mask[3]);
+
+		ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK2_1);
+		ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK2_2);
+		ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK2_3);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4,
+					AR5K_PHY_BIN_MASK2_4_MASK_4,
+					mag_mask[3]);
+
+	} else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) &
+	AR5K_PHY_IQ_SPUR_FILT_EN) {
+		/* Clean up spur mitigation settings and disable fliter */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
+					AR5K_PHY_BIN_MASK_CTL_RATE, 0);
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ,
+					AR5K_PHY_IQ_PILOT_MASK_EN |
+					AR5K_PHY_IQ_CHAN_MASK_EN |
+					AR5K_PHY_IQ_SPUR_FILT_EN);
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_11);
+
+		/* Clear pilot masks */
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_7);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8,
+					AR5K_PHY_TIMING_8_PILOT_MASK_2,
+					0);
+
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_9);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10,
+					AR5K_PHY_TIMING_10_PILOT_MASK_2,
+					0);
+
+		/* Clear magnitude masks */
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_1);
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_2);
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_3);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
+					AR5K_PHY_BIN_MASK_CTL_MASK_4,
+					0);
+
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_1);
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_2);
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_3);
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4,
+					AR5K_PHY_BIN_MASK2_4_MASK_4,
+					0);
+	}
+}
+
+/********************\
+  Misc PHY functions
+\********************/
+
+int ath5k_hw_phy_disable(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	/*Just a try M.F.*/
+	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+
+	return 0;
+}
+
+/*
+ * Get the PHY Chip revision
+ */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+{
+	unsigned int i;
+	u32 srev;
+	u16 ret;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/*
+	 * Set the radio chip access register
+	 */
+	switch (chan) {
+	case CHANNEL_2GHZ:
+		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
+		break;
+	case CHANNEL_5GHZ:
+		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+		break;
+	default:
+		return 0;
+	}
+
+	mdelay(2);
+
+	/* ...wait until PHY is ready and read the selected radio revision */
+	ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
+
+	for (i = 0; i < 8; i++)
+		ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
+
+	if (ah->ah_version == AR5K_AR5210) {
+		srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+		ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
+	} else {
+		srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
+		ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
+				((srev & 0x0f) << 4), 8);
+	}
+
+	/* Reset to the 5GHz mode */
+	ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+	return ret;
+}
+
+/*****************\
+* Antenna control *
+\*****************/
+
+void /*TODO:Boundary check*/
+ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	if (ah->ah_version != AR5K_AR5210)
+		ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA);
+}
+
+unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+
+	if (ah->ah_version != AR5K_AR5210)
+		return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7;
+
+	return false; /*XXX: What do we return for 5210 ?*/
+}
+
+/*
+ * Enable/disable fast rx antenna diversity
+ */
+static void
+ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
+{
+	switch (ee_mode) {
+	case AR5K_EEPROM_MODE_11G:
+		/* XXX: This is set to
+		 * disabled on initvals !!! */
+	case AR5K_EEPROM_MODE_11A:
+		if (enable)
+			AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL,
+					AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
+		else
+			AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+					AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
+		break;
+	case AR5K_EEPROM_MODE_11B:
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+					AR5K_PHY_AGCCTL_OFDM_DIV_DIS);
+		break;
+	default:
+		return;
+	}
+
+	if (enable) {
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
+				AR5K_PHY_RESTART_DIV_GC, 0xc);
+
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
+					AR5K_PHY_FAST_ANT_DIV_EN);
+	} else {
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
+				AR5K_PHY_RESTART_DIV_GC, 0x8);
+
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
+					AR5K_PHY_FAST_ANT_DIV_EN);
+	}
+}
+
+/*
+ * Set antenna operating mode
+ */
+void
+ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
+{
+	struct ieee80211_channel *channel = &ah->ah_current_channel;
+	bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div;
+	bool use_def_for_sg;
+	u8 def_ant, tx_ant, ee_mode;
+	u32 sta_id1 = 0;
+
+	def_ant = ah->ah_def_ant;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	switch (channel->hw_value & CHANNEL_MODES) {
+	case CHANNEL_A:
+	case CHANNEL_T:
+	case CHANNEL_XR:
+		ee_mode = AR5K_EEPROM_MODE_11A;
+		break;
+	case CHANNEL_G:
+	case CHANNEL_TG:
+		ee_mode = AR5K_EEPROM_MODE_11G;
+		break;
+	case CHANNEL_B:
+		ee_mode = AR5K_EEPROM_MODE_11B;
+		break;
+	default:
+		ATH5K_ERR(ah->ah_sc,
+			"invalid channel: %d\n", channel->center_freq);
+		return;
+	}
+
+	switch (ant_mode) {
+	case AR5K_ANTMODE_DEFAULT:
+		tx_ant = 0;
+		use_def_for_tx = false;
+		update_def_on_tx = false;
+		use_def_for_rts = false;
+		use_def_for_sg = false;
+		fast_div = true;
+		break;
+	case AR5K_ANTMODE_FIXED_A:
+		def_ant = 1;
+		tx_ant = 0;
+		use_def_for_tx = true;
+		update_def_on_tx = false;
+		use_def_for_rts = true;
+		use_def_for_sg = true;
+		fast_div = false;
+		break;
+	case AR5K_ANTMODE_FIXED_B:
+		def_ant = 2;
+		tx_ant = 0;
+		use_def_for_tx = true;
+		update_def_on_tx = false;
+		use_def_for_rts = true;
+		use_def_for_sg = true;
+		fast_div = false;
+		break;
+	case AR5K_ANTMODE_SINGLE_AP:
+		def_ant = 1;	/* updated on tx */
+		tx_ant = 0;
+		use_def_for_tx = true;
+		update_def_on_tx = true;
+		use_def_for_rts = true;
+		use_def_for_sg = true;
+		fast_div = true;
+		break;
+	case AR5K_ANTMODE_SECTOR_AP:
+		tx_ant = 1;	/* variable */
+		use_def_for_tx = false;
+		update_def_on_tx = false;
+		use_def_for_rts = true;
+		use_def_for_sg = false;
+		fast_div = false;
+		break;
+	case AR5K_ANTMODE_SECTOR_STA:
+		tx_ant = 1;	/* variable */
+		use_def_for_tx = true;
+		update_def_on_tx = false;
+		use_def_for_rts = true;
+		use_def_for_sg = false;
+		fast_div = true;
+		break;
+	case AR5K_ANTMODE_DEBUG:
+		def_ant = 1;
+		tx_ant = 2;
+		use_def_for_tx = false;
+		update_def_on_tx = false;
+		use_def_for_rts = false;
+		use_def_for_sg = false;
+		fast_div = false;
+		break;
+	default:
+		return;
+	}
+
+	ah->ah_tx_ant = tx_ant;
+	ah->ah_ant_mode = ant_mode;
+
+	sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0;
+	sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0;
+	sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0;
+	sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0;
+
+	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS);
+
+	if (sta_id1)
+		AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1);
+
+	/* Note: set diversity before default antenna
+	 * because it won't work correctly */
+	ath5k_hw_set_fast_div(ah, ee_mode, fast_div);
+	ath5k_hw_set_def_antenna(ah, def_ant);
+}
+
+
+/****************\
+* TX power setup *
+\****************/
+
+/*
+ * Helper functions
+ */
+
+/*
+ * Do linear interpolation between two given (x, y) points
+ */
+static s16
+ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
+					s16 y_left, s16 y_right)
+{
+	s16 ratio, result;
+
+	/* Avoid divide by zero and skip interpolation
+	 * if we have the same point */
+	if ((x_left == x_right) || (y_left == y_right))
+		return y_left;
+
+	/*
+	 * Since we use ints and not fps, we need to scale up in
+	 * order to get a sane ratio value (or else we 'll eg. get
+	 * always 1 instead of 1.25, 1.75 etc). We scale up by 100
+	 * to have some accuracy both for 0.5 and 0.25 steps.
+	 */
+	ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
+
+	/* Now scale down to be in range */
+	result = y_left + (ratio * (target - x_left) / 100);
+
+	return result;
+}
+
+/*
+ * Find vertical boundary (min pwr) for the linear PCDAC curve.
+ *
+ * Since we have the top of the curve and we draw the line below
+ * until we reach 1 (1 pcdac step) we need to know which point
+ * (x value) that is so that we don't go below y axis and have negative
+ * pcdac values when creating the curve, or fill the table with zeroes.
+ */
+static s16
+ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
+				const s16 *pwrL, const s16 *pwrR)
+{
+	s8 tmp;
+	s16 min_pwrL, min_pwrR;
+	s16 pwr_i;
+
+	if (WARN_ON(stepL[0] == stepL[1] || stepR[0] == stepR[1]))
+		return 0;
+
+	if (pwrL[0] == pwrL[1])
+		min_pwrL = pwrL[0];
+	else {
+		pwr_i = pwrL[0];
+		do {
+			pwr_i--;
+			tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+							pwrL[0], pwrL[1],
+							stepL[0], stepL[1]);
+		} while (tmp > 1);
+
+		min_pwrL = pwr_i;
+	}
+
+	if (pwrR[0] == pwrR[1])
+		min_pwrR = pwrR[0];
+	else {
+		pwr_i = pwrR[0];
+		do {
+			pwr_i--;
+			tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+							pwrR[0], pwrR[1],
+							stepR[0], stepR[1]);
+		} while (tmp > 1);
+
+		min_pwrR = pwr_i;
+	}
+
+	/* Keep the right boundary so that it works for both curves */
+	return max(min_pwrL, min_pwrR);
+}
+
+/*
+ * Interpolate (pwr,vpd) points to create a Power to PDADC or a
+ * Power to PCDAC curve.
+ *
+ * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC
+ * steps (offsets) on y axis. Power can go up to 31.5dB and max
+ * PCDAC/PDADC step for each curve is 64 but we can write more than
+ * one curves on hw so we can go up to 128 (which is the max step we
+ * can write on the final table).
+ *
+ * We write y values (PCDAC/PDADC steps) on hw.
+ */
+static void
+ath5k_create_power_curve(s16 pmin, s16 pmax,
+			const s16 *pwr, const u8 *vpd,
+			u8 num_points,
+			u8 *vpd_table, u8 type)
+{
+	u8 idx[2] = { 0, 1 };
+	s16 pwr_i = 2*pmin;
+	int i;
+
+	if (num_points < 2)
+		return;
+
+	/* We want the whole line, so adjust boundaries
+	 * to cover the entire power range. Note that
+	 * power values are already 0.25dB so no need
+	 * to multiply pwr_i by 2 */
+	if (type == AR5K_PWRTABLE_LINEAR_PCDAC) {
+		pwr_i = pmin;
+		pmin = 0;
+		pmax = 63;
+	}
+
+	/* Find surrounding turning points (TPs)
+	 * and interpolate between them */
+	for (i = 0; (i <= (u16) (pmax - pmin)) &&
+	(i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
+
+		/* We passed the right TP, move to the next set of TPs
+		 * if we pass the last TP, extrapolate above using the last
+		 * two TPs for ratio */
+		if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) {
+			idx[0]++;
+			idx[1]++;
+		}
+
+		vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i,
+						pwr[idx[0]], pwr[idx[1]],
+						vpd[idx[0]], vpd[idx[1]]);
+
+		/* Increase by 0.5dB
+		 * (0.25 dB units) */
+		pwr_i += 2;
+	}
+}
+
+/*
+ * Get the surrounding per-channel power calibration piers
+ * for a given frequency so that we can interpolate between
+ * them and come up with an apropriate dataset for our current
+ * channel.
+ */
+static void
+ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
+			struct ieee80211_channel *channel,
+			struct ath5k_chan_pcal_info **pcinfo_l,
+			struct ath5k_chan_pcal_info **pcinfo_r)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_chan_pcal_info *pcinfo;
+	u8 idx_l, idx_r;
+	u8 mode, max, i;
+	u32 target = channel->center_freq;
+
+	idx_l = 0;
+	idx_r = 0;
+
+	if (!(channel->hw_value & CHANNEL_OFDM)) {
+		pcinfo = ee->ee_pwr_cal_b;
+		mode = AR5K_EEPROM_MODE_11B;
+	} else if (channel->hw_value & CHANNEL_2GHZ) {
+		pcinfo = ee->ee_pwr_cal_g;
+		mode = AR5K_EEPROM_MODE_11G;
+	} else {
+		pcinfo = ee->ee_pwr_cal_a;
+		mode = AR5K_EEPROM_MODE_11A;
+	}
+	max = ee->ee_n_piers[mode] - 1;
+
+	/* Frequency is below our calibrated
+	 * range. Use the lowest power curve
+	 * we have */
+	if (target < pcinfo[0].freq) {
+		idx_l = idx_r = 0;
+		goto done;
+	}
+
+	/* Frequency is above our calibrated
+	 * range. Use the highest power curve
+	 * we have */
+	if (target > pcinfo[max].freq) {
+		idx_l = idx_r = max;
+		goto done;
+	}
+
+	/* Frequency is inside our calibrated
+	 * channel range. Pick the surrounding
+	 * calibration piers so that we can
+	 * interpolate */
+	for (i = 0; i <= max; i++) {
+
+		/* Frequency matches one of our calibration
+		 * piers, no need to interpolate, just use
+		 * that calibration pier */
+		if (pcinfo[i].freq == target) {
+			idx_l = idx_r = i;
+			goto done;
+		}
+
+		/* We found a calibration pier that's above
+		 * frequency, use this pier and the previous
+		 * one to interpolate */
+		if (target < pcinfo[i].freq) {
+			idx_r = i;
+			idx_l = idx_r - 1;
+			goto done;
+		}
+	}
+
+done:
+	*pcinfo_l = &pcinfo[idx_l];
+	*pcinfo_r = &pcinfo[idx_r];
+
+	return;
+}
+
+/*
+ * Get the surrounding per-rate power calibration data
+ * for a given frequency and interpolate between power
+ * values to set max target power supported by hw for
+ * each rate.
+ */
+static void
+ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
+			struct ieee80211_channel *channel,
+			struct ath5k_rate_pcal_info *rates)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_rate_pcal_info *rpinfo;
+	u8 idx_l, idx_r;
+	u8 mode, max, i;
+	u32 target = channel->center_freq;
+
+	idx_l = 0;
+	idx_r = 0;
+
+	if (!(channel->hw_value & CHANNEL_OFDM)) {
+		rpinfo = ee->ee_rate_tpwr_b;
+		mode = AR5K_EEPROM_MODE_11B;
+	} else if (channel->hw_value & CHANNEL_2GHZ) {
+		rpinfo = ee->ee_rate_tpwr_g;
+		mode = AR5K_EEPROM_MODE_11G;
+	} else {
+		rpinfo = ee->ee_rate_tpwr_a;
+		mode = AR5K_EEPROM_MODE_11A;
+	}
+	max = ee->ee_rate_target_pwr_num[mode] - 1;
+
+	/* Get the surrounding calibration
+	 * piers - same as above */
+	if (target < rpinfo[0].freq) {
+		idx_l = idx_r = 0;
+		goto done;
+	}
+
+	if (target > rpinfo[max].freq) {
+		idx_l = idx_r = max;
+		goto done;
+	}
+
+	for (i = 0; i <= max; i++) {
+
+		if (rpinfo[i].freq == target) {
+			idx_l = idx_r = i;
+			goto done;
+		}
+
+		if (target < rpinfo[i].freq) {
+			idx_r = i;
+			idx_l = idx_r - 1;
+			goto done;
+		}
+	}
+
+done:
+	/* Now interpolate power value, based on the frequency */
+	rates->freq = target;
+
+	rates->target_power_6to24 =
+		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+					rpinfo[idx_r].freq,
+					rpinfo[idx_l].target_power_6to24,
+					rpinfo[idx_r].target_power_6to24);
+
+	rates->target_power_36 =
+		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+					rpinfo[idx_r].freq,
+					rpinfo[idx_l].target_power_36,
+					rpinfo[idx_r].target_power_36);
+
+	rates->target_power_48 =
+		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+					rpinfo[idx_r].freq,
+					rpinfo[idx_l].target_power_48,
+					rpinfo[idx_r].target_power_48);
+
+	rates->target_power_54 =
+		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
+					rpinfo[idx_r].freq,
+					rpinfo[idx_l].target_power_54,
+					rpinfo[idx_r].target_power_54);
+}
+
+/*
+ * Get the max edge power for this channel if
+ * we have such data from EEPROM's Conformance Test
+ * Limits (CTL), and limit max power if needed.
+ */
+static void
+ath5k_get_max_ctl_power(struct ath5k_hw *ah,
+			struct ieee80211_channel *channel)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
+	u8 *ctl_val = ee->ee_ctl;
+	s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4;
+	s16 edge_pwr = 0;
+	u8 rep_idx;
+	u8 i, ctl_mode;
+	u8 ctl_idx = 0xFF;
+	u32 target = channel->center_freq;
+
+	ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band);
+
+	switch (channel->hw_value & CHANNEL_MODES) {
+	case CHANNEL_A:
+		ctl_mode |= AR5K_CTL_11A;
+		break;
+	case CHANNEL_G:
+		ctl_mode |= AR5K_CTL_11G;
+		break;
+	case CHANNEL_B:
+		ctl_mode |= AR5K_CTL_11B;
+		break;
+	case CHANNEL_T:
+		ctl_mode |= AR5K_CTL_TURBO;
+		break;
+	case CHANNEL_TG:
+		ctl_mode |= AR5K_CTL_TURBOG;
+		break;
+	case CHANNEL_XR:
+		/* Fall through */
+	default:
+		return;
+	}
+
+	for (i = 0; i < ee->ee_ctls; i++) {
+		if (ctl_val[i] == ctl_mode) {
+			ctl_idx = i;
+			break;
+		}
+	}
+
+	/* If we have a CTL dataset available grab it and find the
+	 * edge power for our frequency */
+	if (ctl_idx == 0xFF)
+		return;
+
+	/* Edge powers are sorted by frequency from lower
+	 * to higher. Each CTL corresponds to 8 edge power
+	 * measurements. */
+	rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES;
+
+	/* Don't do boundaries check because we
+	 * might have more that one bands defined
+	 * for this mode */
+
+	/* Get the edge power that's closer to our
+	 * frequency */
+	for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) {
+		rep_idx += i;
+		if (target <= rep[rep_idx].freq)
+			edge_pwr = (s16) rep[rep_idx].edge;
+	}
+
+	if (edge_pwr)
+		ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
+}
+
+
+/*
+ * Power to PCDAC table functions
+ */
+
+/*
+ * Fill Power to PCDAC table on RF5111
+ *
+ * No further processing is needed for RF5111, the only thing we have to
+ * do is fill the values below and above calibration range since eeprom data
+ * may not cover the entire PCDAC table.
+ */
+static void
+ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
+							s16 *table_max)
+{
+	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
+	u8	*pcdac_tmp = ah->ah_txpower.tmpL[0];
+	u8	pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
+	s16	min_pwr, max_pwr;
+
+	/* Get table boundaries */
+	min_pwr = table_min[0];
+	pcdac_0 = pcdac_tmp[0];
+
+	max_pwr = table_max[0];
+	pcdac_n = pcdac_tmp[table_max[0] - table_min[0]];
+
+	/* Extrapolate below minimum using pcdac_0 */
+	pcdac_i = 0;
+	for (i = 0; i < min_pwr; i++)
+		pcdac_out[pcdac_i++] = pcdac_0;
+
+	/* Copy values from pcdac_tmp */
+	pwr_idx = min_pwr;
+	for (i = 0 ; pwr_idx <= max_pwr &&
+	pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
+		pcdac_out[pcdac_i++] = pcdac_tmp[i];
+		pwr_idx++;
+	}
+
+	/* Extrapolate above maximum */
+	while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE)
+		pcdac_out[pcdac_i++] = pcdac_n;
+
+}
+
+/*
+ * Combine available XPD Curves and fill Linear Power to PCDAC table
+ * on RF5112
+ *
+ * RFX112 can have up to 2 curves (one for low txpower range and one for
+ * higher txpower range). We need to put them both on pcdac_out and place
+ * them in the correct location. In case we only have one curve available
+ * just fit it on pcdac_out (it's supposed to cover the entire range of
+ * available pwr levels since it's always the higher power curve). Extrapolate
+ * below and above final table if needed.
+ */
+static void
+ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
+						s16 *table_max, u8 pdcurves)
+{
+	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
+	u8	*pcdac_low_pwr;
+	u8	*pcdac_high_pwr;
+	u8	*pcdac_tmp;
+	u8	pwr;
+	s16	max_pwr_idx;
+	s16	min_pwr_idx;
+	s16	mid_pwr_idx = 0;
+	/* Edge flag turs on the 7nth bit on the PCDAC
+	 * to delcare the higher power curve (force values
+	 * to be greater than 64). If we only have one curve
+	 * we don't need to set this, if we have 2 curves and
+	 * fill the table backwards this can also be used to
+	 * switch from higher power curve to lower power curve */
+	u8	edge_flag;
+	int	i;
+
+	/* When we have only one curve available
+	 * that's the higher power curve. If we have
+	 * two curves the first is the high power curve
+	 * and the next is the low power curve. */
+	if (pdcurves > 1) {
+		pcdac_low_pwr = ah->ah_txpower.tmpL[1];
+		pcdac_high_pwr = ah->ah_txpower.tmpL[0];
+		mid_pwr_idx = table_max[1] - table_min[1] - 1;
+		max_pwr_idx = (table_max[0] - table_min[0]) / 2;
+
+		/* If table size goes beyond 31.5dB, keep the
+		 * upper 31.5dB range when setting tx power.
+		 * Note: 126 = 31.5 dB in quarter dB steps */
+		if (table_max[0] - table_min[1] > 126)
+			min_pwr_idx = table_max[0] - 126;
+		else
+			min_pwr_idx = table_min[1];
+
+		/* Since we fill table backwards
+		 * start from high power curve */
+		pcdac_tmp = pcdac_high_pwr;
+
+		edge_flag = 0x40;
+#if 0
+		/* If both min and max power limits are in lower
+		 * power curve's range, only use the low power curve.
+		 * TODO: min/max levels are related to target
+		 * power values requested from driver/user
+		 * XXX: Is this really needed ? */
+		if (min_pwr < table_max[1] &&
+		max_pwr < table_max[1]) {
+			edge_flag = 0;
+			pcdac_tmp = pcdac_low_pwr;
+			max_pwr_idx = (table_max[1] - table_min[1])/2;
+		}
+#endif
+	} else {
+		pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */
+		pcdac_high_pwr = ah->ah_txpower.tmpL[0];
+		min_pwr_idx = table_min[0];
+		max_pwr_idx = (table_max[0] - table_min[0]) / 2;
+		pcdac_tmp = pcdac_high_pwr;
+		edge_flag = 0;
+	}
+
+	/* This is used when setting tx power*/
+	ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
+
+	/* Fill Power to PCDAC table backwards */
+	pwr = max_pwr_idx;
+	for (i = 63; i >= 0; i--) {
+		/* Entering lower power range, reset
+		 * edge flag and set pcdac_tmp to lower
+		 * power curve.*/
+		if (edge_flag == 0x40 &&
+		(2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
+			edge_flag = 0x00;
+			pcdac_tmp = pcdac_low_pwr;
+			pwr = mid_pwr_idx/2;
+		}
+
+		/* Don't go below 1, extrapolate below if we have
+		 * already swithced to the lower power curve -or
+		 * we only have one curve and edge_flag is zero
+		 * anyway */
+		if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
+			while (i >= 0) {
+				pcdac_out[i] = pcdac_out[i + 1];
+				i--;
+			}
+			break;
+		}
+
+		pcdac_out[i] = pcdac_tmp[pwr] | edge_flag;
+
+		/* Extrapolate above if pcdac is greater than
+		 * 126 -this can happen because we OR pcdac_out
+		 * value with edge_flag on high power curve */
+		if (pcdac_out[i] > 126)
+			pcdac_out[i] = 126;
+
+		/* Decrease by a 0.5dB step */
+		pwr--;
+	}
+}
+
+/* Write PCDAC values on hw */
+static void
+ath5k_setup_pcdac_table(struct ath5k_hw *ah)
+{
+	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
+	int	i;
+
+	/*
+	 * Write TX power values
+	 */
+	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
+		ath5k_hw_reg_write(ah,
+			(((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
+			(((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
+			AR5K_PHY_PCDAC_TXPOWER(i));
+	}
+}
+
+
+/*
+ * Power to PDADC table functions
+ */
+
+/*
+ * Set the gain boundaries and create final Power to PDADC table
+ *
+ * We can have up to 4 pd curves, we need to do a simmilar process
+ * as we do for RF5112. This time we don't have an edge_flag but we
+ * set the gain boundaries on a separate register.
+ */
+static void
+ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
+			s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
+{
+	u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS];
+	u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
+	u8 *pdadc_tmp;
+	s16 pdadc_0;
+	u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size;
+	u8 pd_gain_overlap;
+
+	/* Note: Register value is initialized on initvals
+	 * there is no feedback from hw.
+	 * XXX: What about pd_gain_overlap from EEPROM ? */
+	pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) &
+		AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP;
+
+	/* Create final PDADC table */
+	for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) {
+		pdadc_tmp = ah->ah_txpower.tmpL[pdg];
+
+		if (pdg == pdcurves - 1)
+			/* 2 dB boundary stretch for last
+			 * (higher power) curve */
+			gain_boundaries[pdg] = pwr_max[pdg] + 4;
+		else
+			/* Set gain boundary in the middle
+			 * between this curve and the next one */
+			gain_boundaries[pdg] =
+				(pwr_max[pdg] + pwr_min[pdg + 1]) / 2;
+
+		/* Sanity check in case our 2 db stretch got out of
+		 * range. */
+		if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER)
+			gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER;
+
+		/* For the first curve (lower power)
+		 * start from 0 dB */
+		if (pdg == 0)
+			pdadc_0 = 0;
+		else
+			/* For the other curves use the gain overlap */
+			pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) -
+							pd_gain_overlap;
+
+		/* Force each power step to be at least 0.5 dB */
+		if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1)
+			pwr_step = pdadc_tmp[1] - pdadc_tmp[0];
+		else
+			pwr_step = 1;
+
+		/* If pdadc_0 is negative, we need to extrapolate
+		 * below this pdgain by a number of pwr_steps */
+		while ((pdadc_0 < 0) && (pdadc_i < 128)) {
+			s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step;
+			pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp;
+			pdadc_0++;
+		}
+
+		/* Set last pwr level, using gain boundaries */
+		pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg];
+		/* Limit it to be inside pwr range */
+		table_size = pwr_max[pdg] - pwr_min[pdg];
+		max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
+
+		/* Fill pdadc_out table */
+		while (pdadc_0 < max_idx)
+			pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
+
+		/* Need to extrapolate above this pdgain? */
+		if (pdadc_n <= max_idx)
+			continue;
+
+		/* Force each power step to be at least 0.5 dB */
+		if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1)
+			pwr_step = pdadc_tmp[table_size - 1] -
+						pdadc_tmp[table_size - 2];
+		else
+			pwr_step = 1;
+
+		/* Extrapolate above */
+		while ((pdadc_0 < (s16) pdadc_n) &&
+		(pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) {
+			s16 tmp = pdadc_tmp[table_size - 1] +
+					(pdadc_0 - max_idx) * pwr_step;
+			pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp;
+			pdadc_0++;
+		}
+	}
+
+	while (pdg < AR5K_EEPROM_N_PD_GAINS) {
+		gain_boundaries[pdg] = gain_boundaries[pdg - 1];
+		pdg++;
+	}
+
+	while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) {
+		pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1];
+		pdadc_i++;
+	}
+
+	/* Set gain boundaries */
+	ath5k_hw_reg_write(ah,
+		AR5K_REG_SM(pd_gain_overlap,
+			AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) |
+		AR5K_REG_SM(gain_boundaries[0],
+			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) |
+		AR5K_REG_SM(gain_boundaries[1],
+			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) |
+		AR5K_REG_SM(gain_boundaries[2],
+			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) |
+		AR5K_REG_SM(gain_boundaries[3],
+			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4),
+		AR5K_PHY_TPC_RG5);
+
+	/* Used for setting rate power table */
+	ah->ah_txpower.txp_min_idx = pwr_min[0];
+
+}
+
+/* Write PDADC values on hw */
+static void
+ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah,
+			u8 pdcurves, u8 *pdg_to_idx)
+{
+	u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
+	u32 reg;
+	u8 i;
+
+	/* Select the right pdgain curves */
+
+	/* Clear current settings */
+	reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1);
+	reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 |
+		AR5K_PHY_TPC_RG1_PDGAIN_2 |
+		AR5K_PHY_TPC_RG1_PDGAIN_3 |
+		AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
+
+	/*
+	 * Use pd_gains curve from eeprom
+	 *
+	 * This overrides the default setting from initvals
+	 * in case some vendors (e.g. Zcomax) don't use the default
+	 * curves. If we don't honor their settings we 'll get a
+	 * 5dB (1 * gain overlap ?) drop.
+	 */
+	reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
+
+	switch (pdcurves) {
+	case 3:
+		reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
+		/* Fall through */
+	case 2:
+		reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
+		/* Fall through */
+	case 1:
+		reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
+		break;
+	}
+	ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1);
+
+	/*
+	 * Write TX power values
+	 */
+	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
+		ath5k_hw_reg_write(ah,
+			((pdadc_out[4*i + 0] & 0xff) << 0) |
+			((pdadc_out[4*i + 1] & 0xff) << 8) |
+			((pdadc_out[4*i + 2] & 0xff) << 16) |
+			((pdadc_out[4*i + 3] & 0xff) << 24),
+			AR5K_PHY_PDADC_TXPOWER(i));
+	}
+}
+
+
+/*
+ * Common code for PCDAC/PDADC tables
+ */
+
+/*
+ * This is the main function that uses all of the above
+ * to set PCDAC/PDADC table on hw for the current channel.
+ * This table is used for tx power calibration on the basband,
+ * without it we get weird tx power levels and in some cases
+ * distorted spectral mask
+ */
+static int
+ath5k_setup_channel_powertable(struct ath5k_hw *ah,
+			struct ieee80211_channel *channel,
+			u8 ee_mode, u8 type)
+{
+	struct ath5k_pdgain_info *pdg_L, *pdg_R;
+	struct ath5k_chan_pcal_info *pcinfo_L;
+	struct ath5k_chan_pcal_info *pcinfo_R;
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
+	s16 table_min[AR5K_EEPROM_N_PD_GAINS];
+	s16 table_max[AR5K_EEPROM_N_PD_GAINS];
+	u8 *tmpL;
+	u8 *tmpR;
+	u32 target = channel->center_freq;
+	int pdg, i;
+
+	/* Get surounding freq piers for this channel */
+	ath5k_get_chan_pcal_surrounding_piers(ah, channel,
+						&pcinfo_L,
+						&pcinfo_R);
+
+	/* Loop over pd gain curves on
+	 * surounding freq piers by index */
+	for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
+
+		/* Fill curves in reverse order
+		 * from lower power (max gain)
+		 * to higher power. Use curve -> idx
+		 * backmaping we did on eeprom init */
+		u8 idx = pdg_curve_to_idx[pdg];
+
+		/* Grab the needed curves by index */
+		pdg_L = &pcinfo_L->pd_curves[idx];
+		pdg_R = &pcinfo_R->pd_curves[idx];
+
+		/* Initialize the temp tables */
+		tmpL = ah->ah_txpower.tmpL[pdg];
+		tmpR = ah->ah_txpower.tmpR[pdg];
+
+		/* Set curve's x boundaries and create
+		 * curves so that they cover the same
+		 * range (if we don't do that one table
+		 * will have values on some range and the
+		 * other one won't have any so interpolation
+		 * will fail) */
+		table_min[pdg] = min(pdg_L->pd_pwr[0],
+					pdg_R->pd_pwr[0]) / 2;
+
+		table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
+				pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2;
+
+		/* Now create the curves on surrounding channels
+		 * and interpolate if needed to get the final
+		 * curve for this gain on this channel */
+		switch (type) {
+		case AR5K_PWRTABLE_LINEAR_PCDAC:
+			/* Override min/max so that we don't loose
+			 * accuracy (don't divide by 2) */
+			table_min[pdg] = min(pdg_L->pd_pwr[0],
+						pdg_R->pd_pwr[0]);
+
+			table_max[pdg] =
+				max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
+					pdg_R->pd_pwr[pdg_R->pd_points - 1]);
+
+			/* Override minimum so that we don't get
+			 * out of bounds while extrapolating
+			 * below. Don't do this when we have 2
+			 * curves and we are on the high power curve
+			 * because table_min is ok in this case */
+			if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) {
+
+				table_min[pdg] =
+					ath5k_get_linear_pcdac_min(pdg_L->pd_step,
+								pdg_R->pd_step,
+								pdg_L->pd_pwr,
+								pdg_R->pd_pwr);
+
+				/* Don't go too low because we will
+				 * miss the upper part of the curve.
+				 * Note: 126 = 31.5dB (max power supported)
+				 * in 0.25dB units */
+				if (table_max[pdg] - table_min[pdg] > 126)
+					table_min[pdg] = table_max[pdg] - 126;
+			}
+
+			/* Fall through */
+		case AR5K_PWRTABLE_PWR_TO_PCDAC:
+		case AR5K_PWRTABLE_PWR_TO_PDADC:
+
+			ath5k_create_power_curve(table_min[pdg],
+						table_max[pdg],
+						pdg_L->pd_pwr,
+						pdg_L->pd_step,
+						pdg_L->pd_points, tmpL, type);
+
+			/* We are in a calibration
+			 * pier, no need to interpolate
+			 * between freq piers */
+			if (pcinfo_L == pcinfo_R)
+				continue;
+
+			ath5k_create_power_curve(table_min[pdg],
+						table_max[pdg],
+						pdg_R->pd_pwr,
+						pdg_R->pd_step,
+						pdg_R->pd_points, tmpR, type);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		/* Interpolate between curves
+		 * of surounding freq piers to
+		 * get the final curve for this
+		 * pd gain. Re-use tmpL for interpolation
+		 * output */
+		for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) &&
+		(i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
+			tmpL[i] = (u8) ath5k_get_interpolated_value(target,
+							(s16) pcinfo_L->freq,
+							(s16) pcinfo_R->freq,
+							(s16) tmpL[i],
+							(s16) tmpR[i]);
+		}
+	}
+
+	/* Now we have a set of curves for this
+	 * channel on tmpL (x range is table_max - table_min
+	 * and y values are tmpL[pdg][]) sorted in the same
+	 * order as EEPROM (because we've used the backmaping).
+	 * So for RF5112 it's from higher power to lower power
+	 * and for RF2413 it's from lower power to higher power.
+	 * For RF5111 we only have one curve. */
+
+	/* Fill min and max power levels for this
+	 * channel by interpolating the values on
+	 * surounding channels to complete the dataset */
+	ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
+					(s16) pcinfo_L->freq,
+					(s16) pcinfo_R->freq,
+					pcinfo_L->min_pwr, pcinfo_R->min_pwr);
+
+	ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target,
+					(s16) pcinfo_L->freq,
+					(s16) pcinfo_R->freq,
+					pcinfo_L->max_pwr, pcinfo_R->max_pwr);
+
+	/* We are ready to go, fill PCDAC/PDADC
+	 * table and write settings on hardware */
+	switch (type) {
+	case AR5K_PWRTABLE_LINEAR_PCDAC:
+		/* For RF5112 we can have one or two curves
+		 * and each curve covers a certain power lvl
+		 * range so we need to do some more processing */
+		ath5k_combine_linear_pcdac_curves(ah, table_min, table_max,
+						ee->ee_pd_gains[ee_mode]);
+
+		/* Set txp.offset so that we can
+		 * match max power value with max
+		 * table index */
+		ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
+
+		/* Write settings on hw */
+		ath5k_setup_pcdac_table(ah);
+		break;
+	case AR5K_PWRTABLE_PWR_TO_PCDAC:
+		/* We are done for RF5111 since it has only
+		 * one curve, just fit the curve on the table */
+		ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max);
+
+		/* No rate powertable adjustment for RF5111 */
+		ah->ah_txpower.txp_min_idx = 0;
+		ah->ah_txpower.txp_offset = 0;
+
+		/* Write settings on hw */
+		ath5k_setup_pcdac_table(ah);
+		break;
+	case AR5K_PWRTABLE_PWR_TO_PDADC:
+		/* Set PDADC boundaries and fill
+		 * final PDADC table */
+		ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
+						ee->ee_pd_gains[ee_mode]);
+
+		/* Write settings on hw */
+		ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
+
+		/* Set txp.offset, note that table_min
+		 * can be negative */
+		ah->ah_txpower.txp_offset = table_min[0];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Per-rate tx power setting
+ *
+ * This is the code that sets the desired tx power (below
+ * maximum) on hw for each rate (we also have TPC that sets
+ * power per packet). We do that by providing an index on the
+ * PCDAC/PDADC table we set up.
+ */
+
+/*
+ * Set rate power table
+ *
+ * For now we only limit txpower based on maximum tx power
+ * supported by hw (what's inside rate_info). We need to limit
+ * this even more, based on regulatory domain etc.
+ *
+ * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps)
+ * and is indexed as follows:
+ * rates[0] - rates[7] -> OFDM rates
+ * rates[8] - rates[14] -> CCK rates
+ * rates[15] -> XR rates (they all have the same power)
+ */
+static void
+ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
+			struct ath5k_rate_pcal_info *rate_info,
+			u8 ee_mode)
+{
+	unsigned int i;
+	u16 *rates;
+
+	/* max_pwr is power level we got from driver/user in 0.5dB
+	 * units, switch to 0.25dB units so we can compare */
+	max_pwr *= 2;
+	max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2;
+
+	/* apply rate limits */
+	rates = ah->ah_txpower.txp_rates_power_table;
+
+	/* OFDM rates 6 to 24Mb/s */
+	for (i = 0; i < 5; i++)
+		rates[i] = min(max_pwr, rate_info->target_power_6to24);
+
+	/* Rest OFDM rates */
+	rates[5] = min(rates[0], rate_info->target_power_36);
+	rates[6] = min(rates[0], rate_info->target_power_48);
+	rates[7] = min(rates[0], rate_info->target_power_54);
+
+	/* CCK rates */
+	/* 1L */
+	rates[8] = min(rates[0], rate_info->target_power_6to24);
+	/* 2L */
+	rates[9] = min(rates[0], rate_info->target_power_36);
+	/* 2S */
+	rates[10] = min(rates[0], rate_info->target_power_36);
+	/* 5L */
+	rates[11] = min(rates[0], rate_info->target_power_48);
+	/* 5S */
+	rates[12] = min(rates[0], rate_info->target_power_48);
+	/* 11L */
+	rates[13] = min(rates[0], rate_info->target_power_54);
+	/* 11S */
+	rates[14] = min(rates[0], rate_info->target_power_54);
+
+	/* XR rates */
+	rates[15] = min(rates[0], rate_info->target_power_6to24);
+
+	/* CCK rates have different peak to average ratio
+	 * so we have to tweak their power so that gainf
+	 * correction works ok. For this we use OFDM to
+	 * CCK delta from eeprom */
+	if ((ee_mode == AR5K_EEPROM_MODE_11G) &&
+	(ah->ah_phy_revision < AR5K_SREV_PHY_5212A))
+		for (i = 8; i <= 15; i++)
+			rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
+
+	/* Now that we have all rates setup use table offset to
+	 * match the power range set by user with the power indices
+	 * on PCDAC/PDADC table */
+	for (i = 0; i < 16; i++) {
+		rates[i] += ah->ah_txpower.txp_offset;
+		/* Don't get out of bounds */
+		if (rates[i] > 63)
+			rates[i] = 63;
+	}
+
+	/* Min/max in 0.25dB units */
+	ah->ah_txpower.txp_min_pwr = 2 * rates[7];
+	ah->ah_txpower.txp_max_pwr = 2 * rates[0];
+	ah->ah_txpower.txp_ofdm = rates[7];
+}
+
+
+/*
+ * Set transmition power
+ */
+int
+ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+		u8 ee_mode, u8 txpower)
+{
+	struct ath5k_rate_pcal_info rate_info;
+	u8 type;
+	int ret;
+
+	ATH5K_TRACE(ah->ah_sc);
+	if (txpower > AR5K_TUNE_MAX_TXPOWER) {
+		ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
+		return -EINVAL;
+	}
+	if (txpower == 0)
+		txpower = AR5K_TUNE_DEFAULT_TXPOWER;
+
+	/* Reset TX power values */
+	memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
+	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+	ah->ah_txpower.txp_min_pwr = 0;
+	ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
+
+	/* Initialize TX power table */
+	switch (ah->ah_radio) {
+	case AR5K_RF5111:
+		type = AR5K_PWRTABLE_PWR_TO_PCDAC;
+		break;
+	case AR5K_RF5112:
+		type = AR5K_PWRTABLE_LINEAR_PCDAC;
+		break;
+	case AR5K_RF2413:
+	case AR5K_RF5413:
+	case AR5K_RF2316:
+	case AR5K_RF2317:
+	case AR5K_RF2425:
+		type = AR5K_PWRTABLE_PWR_TO_PDADC;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* FIXME: Only on channel/mode change */
+	ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
+	if (ret)
+		return ret;
+
+	/* Limit max power if we have a CTL available */
+	ath5k_get_max_ctl_power(ah, channel);
+
+	/* FIXME: Tx power limit for this regdomain
+	 * XXX: Mac80211/CRDA will do that anyway ? */
+
+	/* FIXME: Antenna reduction stuff */
+
+	/* FIXME: Limit power on turbo modes */
+
+	/* FIXME: TPC scale reduction */
+
+	/* Get surounding channels for per-rate power table
+	 * calibration */
+	ath5k_get_rate_pcal_data(ah, channel, &rate_info);
+
+	/* Setup rate power table */
+	ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode);
+
+	/* Write rate power table on hw */
+	ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
+		AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
+		AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
+
+	ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
+		AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
+		AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
+
+	ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
+		AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
+		AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
+
+	ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
+		AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
+		AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
+
+	/* FIXME: TPC support */
+	if (ah->ah_txpower.txp_tpc) {
+		ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
+			AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+
+		ath5k_hw_reg_write(ah,
+			AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) |
+			AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) |
+			AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
+			AR5K_TPC);
+	} else {
+		ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
+			AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+	}
+
+	return 0;
+}
+
+int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
+{
+	/*Just a try M.F.*/
+	struct ieee80211_channel *channel = &ah->ah_current_channel;
+	u8 ee_mode;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	switch (channel->hw_value & CHANNEL_MODES) {
+	case CHANNEL_A:
+	case CHANNEL_T:
+	case CHANNEL_XR:
+		ee_mode = AR5K_EEPROM_MODE_11A;
+		break;
+	case CHANNEL_G:
+	case CHANNEL_TG:
+		ee_mode = AR5K_EEPROM_MODE_11G;
+		break;
+	case CHANNEL_B:
+		ee_mode = AR5K_EEPROM_MODE_11B;
+		break;
+	default:
+		ATH5K_ERR(ah->ah_sc,
+			"invalid channel: %d\n", channel->center_freq);
+		return -EINVAL;
+	}
+
+	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
+		"changing txpower to %d\n", txpower);
+
+	return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
+}
+
+#undef _ATH5K_PHY
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/qcu.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/qcu.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/qcu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/qcu.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/********************************************\
+Queue Control Unit, DFS Control Unit Functions
+\********************************************/
+
+#include "ath5k.h"
+#include "reg.h"
+#include "debug.h"
+#include "base.h"
+
+/*
+ * Get properties for a transmit queue
+ */
+int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
+		struct ath5k_txq_info *queue_info)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
+	return 0;
+}
+
+/*
+ * Set properties for a transmit queue
+ */
+int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
+				const struct ath5k_txq_info *queue_info)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+		return -EIO;
+
+	memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
+
+	/*XXX: Is this supported on 5210 ?*/
+	if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
+			((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
+			(queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
+			queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
+		ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+
+	return 0;
+}
+
+/*
+ * Initialize a transmit queue
+ */
+int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
+		struct ath5k_txq_info *queue_info)
+{
+	unsigned int queue;
+	int ret;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/*
+	 * Get queue by type
+	 */
+	/*5210 only has 2 queues*/
+	if (ah->ah_version == AR5K_AR5210) {
+		switch (queue_type) {
+		case AR5K_TX_QUEUE_DATA:
+			queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
+			break;
+		case AR5K_TX_QUEUE_BEACON:
+		case AR5K_TX_QUEUE_CAB:
+			queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		switch (queue_type) {
+		case AR5K_TX_QUEUE_DATA:
+			for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
+				ah->ah_txq[queue].tqi_type !=
+				AR5K_TX_QUEUE_INACTIVE; queue++) {
+
+				if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
+					return -EINVAL;
+			}
+			break;
+		case AR5K_TX_QUEUE_UAPSD:
+			queue = AR5K_TX_QUEUE_ID_UAPSD;
+			break;
+		case AR5K_TX_QUEUE_BEACON:
+			queue = AR5K_TX_QUEUE_ID_BEACON;
+			break;
+		case AR5K_TX_QUEUE_CAB:
+			queue = AR5K_TX_QUEUE_ID_CAB;
+			break;
+		case AR5K_TX_QUEUE_XR_DATA:
+			if (ah->ah_version != AR5K_AR5212)
+				ATH5K_ERR(ah->ah_sc,
+					"XR data queues only supported in"
+					" 5212!\n");
+			queue = AR5K_TX_QUEUE_ID_XR_DATA;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Setup internal queue structure
+	 */
+	memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
+	ah->ah_txq[queue].tqi_type = queue_type;
+
+	if (queue_info != NULL) {
+		queue_info->tqi_type = queue_type;
+		ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * We use ah_txq_status to hold a temp value for
+	 * the Secondary interrupt mask registers on 5211+
+	 * check out ath5k_hw_reset_tx_queue
+	 */
+	AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
+
+	return queue;
+}
+
+/*
+ * Get number of pending frames
+ * for a specific queue [5211+]
+ */
+u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
+{
+	u32 pending;
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	/* Return if queue is declared inactive */
+	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+		return false;
+
+	/* XXX: How about AR5K_CFG_TXCNT ? */
+	if (ah->ah_version == AR5K_AR5210)
+		return false;
+
+	pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
+	pending &= AR5K_QCU_STS_FRMPENDCNT;
+
+	/* It's possible to have no frames pending even if TXE
+	 * is set. To indicate that q has not stopped return
+	 * true */
+	if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+		return true;
+
+	return pending;
+}
+
+/*
+ * Set a transmit queue inactive
+ */
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
+		return;
+
+	/* This queue will be skipped in further operations */
+	ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
+	/*For SIMR setup*/
+	AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
+}
+
+/*
+ * Set DFS properties for a transmit queue on DCU
+ */
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+	u32 cw_min, cw_max, retry_lg, retry_sh;
+	struct ath5k_txq_info *tq = &ah->ah_txq[queue];
+
+	ATH5K_TRACE(ah->ah_sc);
+	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+	tq = &ah->ah_txq[queue];
+
+	if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
+		return 0;
+
+	if (ah->ah_version == AR5K_AR5210) {
+		/* Only handle data queues, others will be ignored */
+		if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
+			return 0;
+
+		/* Set Slot time */
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+			AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
+			AR5K_SLOT_TIME);
+		/* Set ACK_CTS timeout */
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+			AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
+			AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
+		/* Set Transmit Latency */
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+			AR5K_INIT_TRANSMIT_LATENCY_TURBO :
+			AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
+
+		/* Set IFS0 */
+		if (ah->ah_turbo) {
+			 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
+				(ah->ah_aifs + tq->tqi_aifs) *
+				AR5K_INIT_SLOT_TIME_TURBO) <<
+				AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
+				AR5K_IFS0);
+		} else {
+			ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
+				(ah->ah_aifs + tq->tqi_aifs) *
+				AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+				AR5K_INIT_SIFS, AR5K_IFS0);
+		}
+
+		/* Set IFS1 */
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+			AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
+			AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
+		/* Set AR5K_PHY_SETTLING */
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+			| 0x38 :
+			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
+			| 0x1C,
+			AR5K_PHY_SETTLING);
+		/* Set Frame Control Register */
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
+			(AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
+			AR5K_PHY_TURBO_SHORT | 0x2020) :
+			(AR5K_PHY_FRAME_CTL_INI | 0x1020),
+			AR5K_PHY_FRAME_CTL_5210);
+	}
+
+	/*
+	 * Calculate cwmin/max by channel mode
+	 */
+	cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
+	cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
+	ah->ah_aifs = AR5K_TUNE_AIFS;
+	/*XR is only supported on 5212*/
+	if (IS_CHAN_XR(ah->ah_current_channel) &&
+			ah->ah_version == AR5K_AR5212) {
+		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
+		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
+		ah->ah_aifs = AR5K_TUNE_AIFS_XR;
+	/*B mode is not supported on 5210*/
+	} else if (IS_CHAN_B(ah->ah_current_channel) &&
+			ah->ah_version != AR5K_AR5210) {
+		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
+		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
+		ah->ah_aifs = AR5K_TUNE_AIFS_11B;
+	}
+
+	cw_min = 1;
+	while (cw_min < ah->ah_cw_min)
+		cw_min = (cw_min << 1) | 1;
+
+	cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
+		((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
+	cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
+		((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
+
+	/*
+	 * Calculate and set retry limits
+	 */
+	if (ah->ah_software_retry) {
+		/* XXX Need to test this */
+		retry_lg = ah->ah_limit_tx_retries;
+		retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
+			AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
+	} else {
+		retry_lg = AR5K_INIT_LG_RETRY;
+		retry_sh = AR5K_INIT_SH_RETRY;
+	}
+
+	/*No QCU/DCU [5210]*/
+	if (ah->ah_version == AR5K_AR5210) {
+		ath5k_hw_reg_write(ah,
+			(cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+			| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+				AR5K_NODCU_RETRY_LMT_SLG_RETRY)
+			| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+				AR5K_NODCU_RETRY_LMT_SSH_RETRY)
+			| AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
+			| AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
+			AR5K_NODCU_RETRY_LMT);
+	} else {
+		/*QCU/DCU [5211+]*/
+		ath5k_hw_reg_write(ah,
+			AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+				AR5K_DCU_RETRY_LMT_SLG_RETRY) |
+			AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+				AR5K_DCU_RETRY_LMT_SSH_RETRY) |
+			AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
+			AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
+			AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
+
+	/*===Rest is also for QCU/DCU only [5211+]===*/
+
+		/*
+		 * Set initial content window (cw_min/cw_max)
+		 * and arbitrated interframe space (aifs)...
+		 */
+		ath5k_hw_reg_write(ah,
+			AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+			AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+			AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
+				AR5K_DCU_LCL_IFS_AIFS),
+			AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+		/*
+		 * Set misc registers
+		 */
+		/* Enable DCU early termination for this queue */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_DCU_EARLY);
+
+		/* Enable DCU to wait for next fragment from QCU */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+					AR5K_DCU_MISC_FRAG_WAIT);
+
+		/* On Maui and Spirit use the global seqnum on DCU */
+		if (ah->ah_mac_version < AR5K_SREV_AR5211)
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+						AR5K_DCU_MISC_SEQNUM_CTL);
+
+		if (tq->tqi_cbr_period) {
+			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+				AR5K_QCU_CBRCFG_INTVAL) |
+				AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+				AR5K_QCU_CBRCFG_ORN_THRES),
+				AR5K_QUEUE_CBRCFG(queue));
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+				AR5K_QCU_MISC_FRSHED_CBR);
+			if (tq->tqi_cbr_overflow_limit)
+				AR5K_REG_ENABLE_BITS(ah,
+					AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_CBR_THRES_ENABLE);
+		}
+
+		if (tq->tqi_ready_time &&
+		(tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
+			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+				AR5K_QCU_RDYTIMECFG_INTVAL) |
+				AR5K_QCU_RDYTIMECFG_ENABLE,
+				AR5K_QUEUE_RDYTIMECFG(queue));
+
+		if (tq->tqi_burst_time) {
+			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+				AR5K_DCU_CHAN_TIME_DUR) |
+				AR5K_DCU_CHAN_TIME_ENABLE,
+				AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+
+			if (tq->tqi_flags
+			& AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+				AR5K_REG_ENABLE_BITS(ah,
+					AR5K_QUEUE_MISC(queue),
+					AR5K_QCU_MISC_RDY_VEOL_POLICY);
+		}
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+				AR5K_QUEUE_DFS_MISC(queue));
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+				AR5K_QUEUE_DFS_MISC(queue));
+
+		/*
+		 * Set registers by queue type
+		 */
+		switch (tq->tqi_type) {
+		case AR5K_TX_QUEUE_BEACON:
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+				AR5K_QCU_MISC_FRSHED_DBA_GT |
+				AR5K_QCU_MISC_CBREXP_BCN_DIS |
+				AR5K_QCU_MISC_BCN_ENABLE);
+
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+				(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+				AR5K_DCU_MISC_ARBLOCK_CTL_S) |
+				AR5K_DCU_MISC_ARBLOCK_IGNORE |
+				AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
+				AR5K_DCU_MISC_BCN_ENABLE);
+			break;
+
+		case AR5K_TX_QUEUE_CAB:
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+				AR5K_QCU_MISC_FRSHED_BCN_SENT_GT |
+				AR5K_QCU_MISC_CBREXP_DIS |
+				AR5K_QCU_MISC_RDY_VEOL_POLICY |
+				AR5K_QCU_MISC_CBREXP_BCN_DIS);
+
+			ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
+				(AR5K_TUNE_SW_BEACON_RESP -
+				AR5K_TUNE_DMA_BEACON_RESP) -
+				AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
+				AR5K_QCU_RDYTIMECFG_ENABLE,
+				AR5K_QUEUE_RDYTIMECFG(queue));
+
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+				(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+				AR5K_DCU_MISC_ARBLOCK_CTL_S));
+			break;
+
+		case AR5K_TX_QUEUE_UAPSD:
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+				AR5K_QCU_MISC_CBREXP_DIS);
+			break;
+
+		case AR5K_TX_QUEUE_DATA:
+		default:
+			break;
+		}
+
+		/* TODO: Handle frame compression */
+
+		/*
+		 * Enable interrupts for this tx queue
+		 * in the secondary interrupt mask registers
+		 */
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
+
+		/* Update secondary interrupt mask registers */
+
+		/* Filter out inactive queues */
+		ah->ah_txq_imr_txok &= ah->ah_txq_status;
+		ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+		ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+		ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+		ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+		ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+		ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+		ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+		ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
+
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+			AR5K_SIMR0_QCU_TXOK) |
+			AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+			AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+			AR5K_SIMR1_QCU_TXERR) |
+			AR5K_REG_SM(ah->ah_txq_imr_txeol,
+			AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
+		/* Update simr2 but don't overwrite rest simr2 settings */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+		AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+			AR5K_REG_SM(ah->ah_txq_imr_txurn,
+			AR5K_SIMR2_QCU_TXURN));
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+			AR5K_SIMR3_QCBRORN) |
+			AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+			AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+			AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+		/* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+			AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+		/* No queue has TXNOFRM enabled, disable the interrupt
+		 * by setting AR5K_TXNOFRM to zero */
+		if (ah->ah_txq_imr_nofrm == 0)
+			ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+
+		/* Set QCU mask for this DCU to save power */
+		AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
+	}
+
+	return 0;
+}
+
+/*
+ * Get slot time from DCU
+ */
+unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (ah->ah_version == AR5K_AR5210)
+		return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
+				AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
+	else
+		return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
+}
+
+/*
+ * Set slot time on DCU
+ */
+int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+{
+	ATH5K_TRACE(ah->ah_sc);
+	if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
+		return -EINVAL;
+
+	if (ah->ah_version == AR5K_AR5210)
+		ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
+				ah->ah_turbo), AR5K_SLOT_TIME);
+	else
+		ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/reg.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/reg.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2596 @@
+/*
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2007-2008 Michael Taylor <mike.taylor@apprion.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k
+ * maintained by Reyk Floeter
+ *
+ * I tried to document those registers by looking at ar5k code, some
+ * 802.11 (802.11e mostly) papers and by reading various public available
+ * Atheros presentations and papers like these:
+ *
+ * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf
+ *        http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
+ *
+ * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
+ *
+ * This file also contains register values found on a memory dump of
+ * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal
+ * released by Atheros and on various debug messages found on the net.
+ */
+
+
+
+/*====MAC DMA REGISTERS====*/
+
+/*
+ * AR5210-Specific TXDP registers
+ * 5210 has only 2 transmit queues so no DCU/QCU, just
+ * 2 transmit descriptor pointers...
+ */
+#define AR5K_NOQCU_TXDP0	0x0000		/* Queue 0 - data */
+#define AR5K_NOQCU_TXDP1	0x0004		/* Queue 1 - beacons */
+
+/*
+ * Mac Control Register
+ */
+#define	AR5K_CR		0x0008			/* Register Address */
+#define AR5K_CR_TXE0	0x00000001	/* TX Enable for queue 0 on 5210 */
+#define AR5K_CR_TXE1	0x00000002	/* TX Enable for queue 1 on 5210 */
+#define	AR5K_CR_RXE	0x00000004	/* RX Enable */
+#define AR5K_CR_TXD0	0x00000008	/* TX Disable for queue 0 on 5210 */
+#define AR5K_CR_TXD1	0x00000010	/* TX Disable for queue 1 on 5210 */
+#define	AR5K_CR_RXD	0x00000020	/* RX Disable */
+#define	AR5K_CR_SWI	0x00000040	/* Software Interrupt */
+
+/*
+ * RX Descriptor Pointer register
+ */
+#define	AR5K_RXDP	0x000c
+
+/*
+ * Configuration and status register
+ */
+#define	AR5K_CFG		0x0014			/* Register Address */
+#define	AR5K_CFG_SWTD		0x00000001	/* Byte-swap TX descriptor (for big endian archs) */
+#define	AR5K_CFG_SWTB		0x00000002	/* Byte-swap TX buffer */
+#define	AR5K_CFG_SWRD		0x00000004	/* Byte-swap RX descriptor */
+#define	AR5K_CFG_SWRB		0x00000008	/* Byte-swap RX buffer */
+#define	AR5K_CFG_SWRG		0x00000010	/* Byte-swap Register access */
+#define AR5K_CFG_IBSS		0x00000020 	/* 0-BSS, 1-IBSS [5211+] */
+#define AR5K_CFG_PHY_OK		0x00000100	/* [5211+] */
+#define AR5K_CFG_EEBS		0x00000200	/* EEPROM is busy */
+#define	AR5K_CFG_CLKGD		0x00000400	/* Clock gated (Disable dynamic clock) */
+#define AR5K_CFG_TXCNT		0x00007800	/* Tx frame count (?) [5210] */
+#define AR5K_CFG_TXCNT_S	11
+#define AR5K_CFG_TXFSTAT	0x00008000	/* Tx frame status (?) [5210] */
+#define AR5K_CFG_TXFSTRT	0x00010000	/* [5210] */
+#define	AR5K_CFG_PCI_THRES	0x00060000	/* PCI Master req q threshold [5211+] */
+#define	AR5K_CFG_PCI_THRES_S	17
+
+/*
+ * Interrupt enable register
+ */
+#define AR5K_IER		0x0024		/* Register Address */
+#define AR5K_IER_DISABLE	0x00000000	/* Disable card interrupts */
+#define AR5K_IER_ENABLE		0x00000001	/* Enable card interrupts */
+
+
+/*
+ * 0x0028 is Beacon Control Register on 5210
+ * and first RTS duration register on 5211
+ */
+
+/*
+ * Beacon control register [5210]
+ */
+#define AR5K_BCR		0x0028		/* Register Address */
+#define AR5K_BCR_AP		0x00000000	/* AP mode */
+#define AR5K_BCR_ADHOC		0x00000001	/* Ad-Hoc mode */
+#define AR5K_BCR_BDMAE		0x00000002	/* DMA enable */
+#define AR5K_BCR_TQ1FV		0x00000004	/* Use Queue1 for CAB traffic */
+#define AR5K_BCR_TQ1V		0x00000008	/* Use Queue1 for Beacon traffic */
+#define AR5K_BCR_BCGET		0x00000010
+
+/*
+ * First RTS duration register [5211]
+ */
+#define AR5K_RTSD0		0x0028		/* Register Address */
+#define	AR5K_RTSD0_6		0x000000ff	/* 6Mb RTS duration mask (?) */
+#define	AR5K_RTSD0_6_S		0		/* 6Mb RTS duration shift (?) */
+#define	AR5K_RTSD0_9		0x0000ff00	/* 9Mb*/
+#define	AR5K_RTSD0_9_S		8
+#define	AR5K_RTSD0_12		0x00ff0000	/* 12Mb*/
+#define	AR5K_RTSD0_12_S		16
+#define	AR5K_RTSD0_18		0xff000000	/* 16Mb*/
+#define	AR5K_RTSD0_18_S		24
+
+
+/*
+ * 0x002c is Beacon Status Register on 5210
+ * and second RTS duration register on 5211
+ */
+
+/*
+ * Beacon status register [5210]
+ *
+ * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR
+ * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning
+ * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR).
+ * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i
+ * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what
+ * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
+ */
+#define AR5K_BSR		0x002c			/* Register Address */
+#define AR5K_BSR_BDLYSW		0x00000001	/* SW Beacon delay (?) */
+#define AR5K_BSR_BDLYDMA	0x00000002	/* DMA Beacon delay (?) */
+#define AR5K_BSR_TXQ1F		0x00000004	/* Beacon queue (1) finished */
+#define AR5K_BSR_ATIMDLY	0x00000008	/* ATIM delay (?) */
+#define AR5K_BSR_SNPADHOC	0x00000100	/* Ad-hoc mode set (?) */
+#define AR5K_BSR_SNPBDMAE	0x00000200	/* Beacon DMA enabled (?) */
+#define AR5K_BSR_SNPTQ1FV	0x00000400	/* Queue1 is used for CAB traffic (?) */
+#define AR5K_BSR_SNPTQ1V	0x00000800	/* Queue1 is used for Beacon traffic (?) */
+#define AR5K_BSR_SNAPSHOTSVALID	0x00001000	/* BCR snapshots are valid (?) */
+#define AR5K_BSR_SWBA_CNT	0x00ff0000
+
+/*
+ * Second RTS duration register [5211]
+ */
+#define AR5K_RTSD1		0x002c			/* Register Address */
+#define	AR5K_RTSD1_24		0x000000ff	/* 24Mb */
+#define	AR5K_RTSD1_24_S		0
+#define	AR5K_RTSD1_36		0x0000ff00	/* 36Mb */
+#define	AR5K_RTSD1_36_S		8
+#define	AR5K_RTSD1_48		0x00ff0000	/* 48Mb */
+#define	AR5K_RTSD1_48_S		16
+#define	AR5K_RTSD1_54		0xff000000	/* 54Mb */
+#define	AR5K_RTSD1_54_S		24
+
+
+/*
+ * Transmit configuration register
+ */
+#define AR5K_TXCFG			0x0030			/* Register Address */
+#define AR5K_TXCFG_SDMAMR		0x00000007	/* DMA size (read) */
+#define AR5K_TXCFG_SDMAMR_S		0
+#define AR5K_TXCFG_B_MODE		0x00000008	/* Set b mode for 5111 (enable 2111) */
+#define AR5K_TXCFG_TXFSTP		0x00000008	/* TX DMA full Stop [5210] */
+#define AR5K_TXCFG_TXFULL		0x000003f0	/* TX Triger level mask */
+#define AR5K_TXCFG_TXFULL_S		4
+#define AR5K_TXCFG_TXFULL_0B		0x00000000
+#define AR5K_TXCFG_TXFULL_64B		0x00000010
+#define AR5K_TXCFG_TXFULL_128B		0x00000020
+#define AR5K_TXCFG_TXFULL_192B		0x00000030
+#define AR5K_TXCFG_TXFULL_256B		0x00000040
+#define AR5K_TXCFG_TXCONT_EN		0x00000080
+#define AR5K_TXCFG_DMASIZE		0x00000100	/* Flag for passing DMA size [5210] */
+#define AR5K_TXCFG_JUMBO_DESC_EN	0x00000400	/* Enable jumbo tx descriptors [5211+] */
+#define AR5K_TXCFG_ADHOC_BCN_ATIM	0x00000800	/* Adhoc Beacon ATIM Policy */
+#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS	0x00001000	/* Disable ATIM window defer [5211+] */
+#define AR5K_TXCFG_RTSRND		0x00001000	/* [5211+] */
+#define AR5K_TXCFG_FRMPAD_DIS		0x00002000	/* [5211+] */
+#define AR5K_TXCFG_RDY_CBR_DIS		0x00004000	/* Ready time CBR disable [5211+] */
+#define AR5K_TXCFG_JUMBO_FRM_MODE	0x00008000	/* Jumbo frame mode [5211+] */
+#define	AR5K_TXCFG_DCU_DBL_BUF_DIS	0x00008000	/* Disable double buffering on DCU */
+#define AR5K_TXCFG_DCU_CACHING_DIS	0x00010000	/* Disable DCU caching */
+
+/*
+ * Receive configuration register
+ */
+#define AR5K_RXCFG		0x0034			/* Register Address */
+#define AR5K_RXCFG_SDMAMW	0x00000007	/* DMA size (write) */
+#define AR5K_RXCFG_SDMAMW_S	0
+#define AR5K_RXCFG_ZLFDMA	0x00000008	/* Enable Zero-length frame DMA */
+#define	AR5K_RXCFG_DEF_ANTENNA	0x00000010	/* Default antenna (?) */
+#define AR5K_RXCFG_JUMBO_RXE	0x00000020	/* Enable jumbo rx descriptors [5211+] */
+#define AR5K_RXCFG_JUMBO_WRAP	0x00000040	/* Wrap jumbo frames [5211+] */
+#define AR5K_RXCFG_SLE_ENTRY	0x00000080	/* Sleep entry policy */
+
+/*
+ * Receive jumbo descriptor last address register
+ * Only found in 5211 (?)
+ */
+#define AR5K_RXJLA		0x0038
+
+/*
+ * MIB control register
+ */
+#define AR5K_MIBC		0x0040			/* Register Address */
+#define AR5K_MIBC_COW		0x00000001	/* Warn test indicator */
+#define AR5K_MIBC_FMC		0x00000002	/* Freeze MIB Counters  */
+#define AR5K_MIBC_CMC		0x00000004	/* Clean MIB Counters  */
+#define AR5K_MIBC_MCS		0x00000008	/* MIB counter strobe */
+
+/*
+ * Timeout prescale register
+ */
+#define AR5K_TOPS		0x0044
+#define	AR5K_TOPS_M		0x0000ffff
+
+/*
+ * Receive timeout register (no frame received)
+ */
+#define AR5K_RXNOFRM		0x0048
+#define	AR5K_RXNOFRM_M		0x000003ff
+
+/*
+ * Transmit timeout register (no frame sent)
+ */
+#define AR5K_TXNOFRM		0x004c
+#define	AR5K_TXNOFRM_M		0x000003ff
+#define	AR5K_TXNOFRM_QCU	0x000ffc00
+#define	AR5K_TXNOFRM_QCU_S	10
+
+/*
+ * Receive frame gap timeout register
+ */
+#define AR5K_RPGTO		0x0050
+#define AR5K_RPGTO_M		0x000003ff
+
+/*
+ * Receive frame count limit register
+ */
+#define AR5K_RFCNT		0x0054
+#define AR5K_RFCNT_M		0x0000001f	/* [5211+] (?) */
+#define AR5K_RFCNT_RFCL		0x0000000f	/* [5210] */
+
+/*
+ * Misc settings register
+ * (reserved0-3)
+ */
+#define AR5K_MISC		0x0058			/* Register Address */
+#define	AR5K_MISC_DMA_OBS_M	0x000001e0
+#define	AR5K_MISC_DMA_OBS_S	5
+#define	AR5K_MISC_MISC_OBS_M	0x00000e00
+#define	AR5K_MISC_MISC_OBS_S	9
+#define	AR5K_MISC_MAC_OBS_LSB_M	0x00007000
+#define	AR5K_MISC_MAC_OBS_LSB_S	12
+#define	AR5K_MISC_MAC_OBS_MSB_M	0x00038000
+#define	AR5K_MISC_MAC_OBS_MSB_S	15
+#define AR5K_MISC_LED_DECAY	0x001c0000	/* [5210] */
+#define AR5K_MISC_LED_BLINK	0x00e00000	/* [5210] */
+
+/*
+ * QCU/DCU clock gating register (5311)
+ * (reserved4-5)
+ */
+#define	AR5K_QCUDCU_CLKGT	0x005c			/* Register Address (?) */
+#define	AR5K_QCUDCU_CLKGT_QCU	0x0000ffff	/* Mask for QCU clock */
+#define	AR5K_QCUDCU_CLKGT_DCU	0x07ff0000	/* Mask for DCU clock */
+
+/*
+ * Interrupt Status Registers
+ *
+ * For 5210 there is only one status register but for
+ * 5211/5212 we have one primary and 4 secondary registers.
+ * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
+ * Most of these bits are common for all chipsets.
+ */
+#define AR5K_ISR		0x001c			/* Register Address [5210] */
+#define AR5K_PISR		0x0080			/* Register Address [5211+] */
+#define AR5K_ISR_RXOK		0x00000001	/* Frame successfuly recieved */
+#define AR5K_ISR_RXDESC		0x00000002	/* RX descriptor request */
+#define AR5K_ISR_RXERR		0x00000004	/* Receive error */
+#define AR5K_ISR_RXNOFRM	0x00000008	/* No frame received (receive timeout) */
+#define AR5K_ISR_RXEOL		0x00000010	/* Empty RX descriptor */
+#define AR5K_ISR_RXORN		0x00000020	/* Receive FIFO overrun */
+#define AR5K_ISR_TXOK		0x00000040	/* Frame successfuly transmited */
+#define AR5K_ISR_TXDESC		0x00000080	/* TX descriptor request */
+#define AR5K_ISR_TXERR		0x00000100	/* Transmit error */
+#define AR5K_ISR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout) */
+#define AR5K_ISR_TXEOL		0x00000400	/* Empty TX descriptor */
+#define AR5K_ISR_TXURN		0x00000800	/* Transmit FIFO underrun */
+#define AR5K_ISR_MIB		0x00001000	/* Update MIB counters */
+#define AR5K_ISR_SWI		0x00002000	/* Software interrupt */
+#define AR5K_ISR_RXPHY		0x00004000	/* PHY error */
+#define AR5K_ISR_RXKCM		0x00008000	/* RX Key cache miss */
+#define AR5K_ISR_SWBA		0x00010000	/* Software beacon alert */
+#define AR5K_ISR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */
+#define AR5K_ISR_BMISS		0x00040000	/* Beacon missed */
+#define AR5K_ISR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */
+#define AR5K_ISR_BNR		0x00100000 	/* Beacon not ready [5211+] */
+#define AR5K_ISR_MCABT		0x00100000	/* Master Cycle Abort [5210] */
+#define AR5K_ISR_RXCHIRP	0x00200000	/* CHIRP Received [5212+] */
+#define AR5K_ISR_SSERR		0x00200000	/* Signaled System Error [5210] */
+#define AR5K_ISR_DPERR		0x00400000	/* Det par Error (?) [5210] */
+#define AR5K_ISR_RXDOPPLER	0x00400000	/* Doppler chirp received [5212+] */
+#define AR5K_ISR_TIM		0x00800000	/* [5211+] */
+#define AR5K_ISR_BCNMISC	0x00800000	/* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+						CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
+#define AR5K_ISR_GPIO		0x01000000	/* GPIO (rf kill) */
+#define AR5K_ISR_QCBRORN	0x02000000	/* QCU CBR overrun [5211+] */
+#define AR5K_ISR_QCBRURN	0x04000000	/* QCU CBR underrun [5211+] */
+#define AR5K_ISR_QTRIG		0x08000000	/* QCU scheduling trigger [5211+] */
+
+/*
+ * Secondary status registers [5211+] (0 - 4)
+ *
+ * These give the status for each QCU, only QCUs 0-9 are
+ * represented.
+ */
+#define AR5K_SISR0		0x0084			/* Register Address [5211+] */
+#define AR5K_SISR0_QCU_TXOK	0x000003ff	/* Mask for QCU_TXOK */
+#define AR5K_SISR0_QCU_TXOK_S	0
+#define AR5K_SISR0_QCU_TXDESC	0x03ff0000	/* Mask for QCU_TXDESC */
+#define AR5K_SISR0_QCU_TXDESC_S	16
+
+#define AR5K_SISR1		0x0088			/* Register Address [5211+] */
+#define AR5K_SISR1_QCU_TXERR	0x000003ff	/* Mask for QCU_TXERR */
+#define AR5K_SISR1_QCU_TXERR_S	0
+#define AR5K_SISR1_QCU_TXEOL	0x03ff0000	/* Mask for QCU_TXEOL */
+#define AR5K_SISR1_QCU_TXEOL_S	16
+
+#define AR5K_SISR2		0x008c			/* Register Address [5211+] */
+#define AR5K_SISR2_QCU_TXURN	0x000003ff	/* Mask for QCU_TXURN */
+#define	AR5K_SISR2_QCU_TXURN_S	0
+#define	AR5K_SISR2_MCABT	0x00100000	/* Master Cycle Abort */
+#define	AR5K_SISR2_SSERR	0x00200000	/* Signaled System Error */
+#define	AR5K_SISR2_DPERR	0x00400000	/* Bus parity error */
+#define	AR5K_SISR2_TIM		0x01000000	/* [5212+] */
+#define	AR5K_SISR2_CAB_END	0x02000000	/* [5212+] */
+#define	AR5K_SISR2_DTIM_SYNC	0x04000000	/* DTIM sync lost [5212+] */
+#define	AR5K_SISR2_BCN_TIMEOUT	0x08000000	/* Beacon Timeout [5212+] */
+#define	AR5K_SISR2_CAB_TIMEOUT	0x10000000	/* CAB Timeout [5212+] */
+#define	AR5K_SISR2_DTIM		0x20000000	/* [5212+] */
+#define	AR5K_SISR2_TSFOOR	0x80000000	/* TSF OOR (?) */
+
+#define AR5K_SISR3		0x0090			/* Register Address [5211+] */
+#define AR5K_SISR3_QCBRORN	0x000003ff	/* Mask for QCBRORN */
+#define AR5K_SISR3_QCBRORN_S	0
+#define AR5K_SISR3_QCBRURN	0x03ff0000	/* Mask for QCBRURN */
+#define AR5K_SISR3_QCBRURN_S	16
+
+#define AR5K_SISR4		0x0094			/* Register Address [5211+] */
+#define AR5K_SISR4_QTRIG	0x000003ff	/* Mask for QTRIG */
+#define AR5K_SISR4_QTRIG_S	0
+
+/*
+ * Shadow read-and-clear interrupt status registers [5211+]
+ */
+#define AR5K_RAC_PISR		0x00c0		/* Read and clear PISR */
+#define AR5K_RAC_SISR0		0x00c4		/* Read and clear SISR0 */
+#define AR5K_RAC_SISR1		0x00c8		/* Read and clear SISR1 */
+#define AR5K_RAC_SISR2		0x00cc		/* Read and clear SISR2 */
+#define AR5K_RAC_SISR3		0x00d0		/* Read and clear SISR3 */
+#define AR5K_RAC_SISR4		0x00d4		/* Read and clear SISR4 */
+
+/*
+ * Interrupt Mask Registers
+ *
+ * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
+ * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match.
+ */
+#define	AR5K_IMR		0x0020			/* Register Address [5210] */
+#define AR5K_PIMR		0x00a0			/* Register Address [5211+] */
+#define AR5K_IMR_RXOK		0x00000001	/* Frame successfuly recieved*/
+#define AR5K_IMR_RXDESC		0x00000002	/* RX descriptor request*/
+#define AR5K_IMR_RXERR		0x00000004	/* Receive error*/
+#define AR5K_IMR_RXNOFRM	0x00000008	/* No frame received (receive timeout)*/
+#define AR5K_IMR_RXEOL		0x00000010	/* Empty RX descriptor*/
+#define AR5K_IMR_RXORN		0x00000020	/* Receive FIFO overrun*/
+#define AR5K_IMR_TXOK		0x00000040	/* Frame successfuly transmited*/
+#define AR5K_IMR_TXDESC		0x00000080	/* TX descriptor request*/
+#define AR5K_IMR_TXERR		0x00000100	/* Transmit error*/
+#define AR5K_IMR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout)*/
+#define AR5K_IMR_TXEOL		0x00000400	/* Empty TX descriptor*/
+#define AR5K_IMR_TXURN		0x00000800	/* Transmit FIFO underrun*/
+#define AR5K_IMR_MIB		0x00001000	/* Update MIB counters*/
+#define AR5K_IMR_SWI		0x00002000	/* Software interrupt */
+#define AR5K_IMR_RXPHY		0x00004000	/* PHY error*/
+#define AR5K_IMR_RXKCM		0x00008000	/* RX Key cache miss */
+#define AR5K_IMR_SWBA		0x00010000	/* Software beacon alert*/
+#define AR5K_IMR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */
+#define AR5K_IMR_BMISS		0x00040000	/* Beacon missed*/
+#define AR5K_IMR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */
+#define AR5K_IMR_BNR		0x00100000 	/* Beacon not ready [5211+] */
+#define AR5K_IMR_MCABT		0x00100000	/* Master Cycle Abort [5210] */
+#define AR5K_IMR_RXCHIRP	0x00200000	/* CHIRP Received [5212+]*/
+#define AR5K_IMR_SSERR		0x00200000	/* Signaled System Error [5210] */
+#define AR5K_IMR_DPERR		0x00400000	/* Det par Error (?) [5210] */
+#define AR5K_IMR_RXDOPPLER	0x00400000	/* Doppler chirp received [5212+] */
+#define AR5K_IMR_TIM		0x00800000	/* [5211+] */
+#define AR5K_IMR_BCNMISC	0x00800000	/* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
+						CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
+#define AR5K_IMR_GPIO		0x01000000	/* GPIO (rf kill)*/
+#define AR5K_IMR_QCBRORN	0x02000000	/* QCU CBR overrun (?) [5211+] */
+#define AR5K_IMR_QCBRURN	0x04000000	/* QCU CBR underrun (?) [5211+] */
+#define AR5K_IMR_QTRIG		0x08000000	/* QCU scheduling trigger [5211+] */
+
+/*
+ * Secondary interrupt mask registers [5211+] (0 - 4)
+ */
+#define AR5K_SIMR0		0x00a4			/* Register Address [5211+] */
+#define AR5K_SIMR0_QCU_TXOK	0x000003ff	/* Mask for QCU_TXOK */
+#define AR5K_SIMR0_QCU_TXOK_S	0
+#define AR5K_SIMR0_QCU_TXDESC	0x03ff0000	/* Mask for QCU_TXDESC */
+#define AR5K_SIMR0_QCU_TXDESC_S	16
+
+#define AR5K_SIMR1		0x00a8			/* Register Address [5211+] */
+#define AR5K_SIMR1_QCU_TXERR	0x000003ff	/* Mask for QCU_TXERR */
+#define AR5K_SIMR1_QCU_TXERR_S	0
+#define AR5K_SIMR1_QCU_TXEOL	0x03ff0000	/* Mask for QCU_TXEOL */
+#define AR5K_SIMR1_QCU_TXEOL_S	16
+
+#define AR5K_SIMR2		0x00ac			/* Register Address [5211+] */
+#define AR5K_SIMR2_QCU_TXURN	0x000003ff	/* Mask for QCU_TXURN */
+#define AR5K_SIMR2_QCU_TXURN_S	0
+#define	AR5K_SIMR2_MCABT	0x00100000	/* Master Cycle Abort */
+#define	AR5K_SIMR2_SSERR	0x00200000	/* Signaled System Error */
+#define	AR5K_SIMR2_DPERR	0x00400000	/* Bus parity error */
+#define	AR5K_SIMR2_TIM		0x01000000	/* [5212+] */
+#define	AR5K_SIMR2_CAB_END	0x02000000	/* [5212+] */
+#define	AR5K_SIMR2_DTIM_SYNC	0x04000000	/* DTIM Sync lost [5212+] */
+#define	AR5K_SIMR2_BCN_TIMEOUT	0x08000000	/* Beacon Timeout [5212+] */
+#define	AR5K_SIMR2_CAB_TIMEOUT	0x10000000	/* CAB Timeout [5212+] */
+#define	AR5K_SIMR2_DTIM		0x20000000	/* [5212+] */
+#define	AR5K_SIMR2_TSFOOR	0x80000000	/* TSF OOR (?) */
+
+#define AR5K_SIMR3		0x00b0			/* Register Address [5211+] */
+#define AR5K_SIMR3_QCBRORN	0x000003ff	/* Mask for QCBRORN */
+#define AR5K_SIMR3_QCBRORN_S	0
+#define AR5K_SIMR3_QCBRURN	0x03ff0000	/* Mask for QCBRURN */
+#define AR5K_SIMR3_QCBRURN_S	16
+
+#define AR5K_SIMR4		0x00b4			/* Register Address [5211+] */
+#define AR5K_SIMR4_QTRIG	0x000003ff	/* Mask for QTRIG */
+#define AR5K_SIMR4_QTRIG_S	0
+
+/*
+ * DMA Debug registers 0-7
+ * 0xe0 - 0xfc
+ */
+
+/*
+ * Decompression mask registers [5212+]
+ */
+#define AR5K_DCM_ADDR		0x0400		/*Decompression mask address (index) */
+#define AR5K_DCM_DATA		0x0404		/*Decompression mask data */
+
+/*
+ * Wake On Wireless pattern control register [5212+]
+ */
+#define	AR5K_WOW_PCFG			0x0410			/* Register Address */
+#define	AR5K_WOW_PCFG_PAT_MATCH_EN	0x00000001	/* Pattern match enable */
+#define	AR5K_WOW_PCFG_LONG_FRAME_POL	0x00000002	/* Long frame policy */
+#define	AR5K_WOW_PCFG_WOBMISS		0x00000004	/* Wake on bea(con) miss (?) */
+#define	AR5K_WOW_PCFG_PAT_0_EN		0x00000100	/* Enable pattern 0 */
+#define	AR5K_WOW_PCFG_PAT_1_EN		0x00000200	/* Enable pattern 1 */
+#define	AR5K_WOW_PCFG_PAT_2_EN		0x00000400	/* Enable pattern 2 */
+#define	AR5K_WOW_PCFG_PAT_3_EN		0x00000800	/* Enable pattern 3 */
+#define	AR5K_WOW_PCFG_PAT_4_EN		0x00001000	/* Enable pattern 4 */
+#define	AR5K_WOW_PCFG_PAT_5_EN		0x00002000	/* Enable pattern 5 */
+
+/*
+ * Wake On Wireless pattern index register (?) [5212+]
+ */
+#define	AR5K_WOW_PAT_IDX	0x0414
+
+/*
+ * Wake On Wireless pattern data register [5212+]
+ */
+#define	AR5K_WOW_PAT_DATA	0x0418			/* Register Address */
+#define	AR5K_WOW_PAT_DATA_0_3_V	0x00000001	/* Pattern 0, 3 value */
+#define	AR5K_WOW_PAT_DATA_1_4_V	0x00000100	/* Pattern 1, 4 value */
+#define	AR5K_WOW_PAT_DATA_2_5_V	0x00010000	/* Pattern 2, 5 value */
+#define	AR5K_WOW_PAT_DATA_0_3_M	0x01000000	/* Pattern 0, 3 mask */
+#define	AR5K_WOW_PAT_DATA_1_4_M	0x04000000	/* Pattern 1, 4 mask */
+#define	AR5K_WOW_PAT_DATA_2_5_M	0x10000000	/* Pattern 2, 5 mask */
+
+/*
+ * Decompression configuration registers [5212+]
+ */
+#define AR5K_DCCFG		0x0420			/* Register Address */
+#define AR5K_DCCFG_GLOBAL_EN	0x00000001	/* Enable decompression on all queues */
+#define AR5K_DCCFG_BYPASS_EN	0x00000002	/* Bypass decompression */
+#define AR5K_DCCFG_BCAST_EN	0x00000004	/* Enable decompression for bcast frames */
+#define AR5K_DCCFG_MCAST_EN	0x00000008	/* Enable decompression for mcast frames */
+
+/*
+ * Compression configuration registers [5212+]
+ */
+#define AR5K_CCFG		0x0600			/* Register Address */
+#define	AR5K_CCFG_WINDOW_SIZE	0x00000007	/* Compression window size */
+#define	AR5K_CCFG_CPC_EN	0x00000008	/* Enable performance counters */
+
+#define AR5K_CCFG_CCU		0x0604			/* Register Address */
+#define AR5K_CCFG_CCU_CUP_EN	0x00000001	/* CCU Catchup enable */
+#define AR5K_CCFG_CCU_CREDIT	0x00000002	/* CCU Credit (field) */
+#define AR5K_CCFG_CCU_CD_THRES	0x00000080	/* CCU Cyc(lic?) debt threshold (field) */
+#define AR5K_CCFG_CCU_CUP_LCNT	0x00010000	/* CCU Catchup lit(?) count */
+#define	AR5K_CCFG_CCU_INIT	0x00100200	/* Initial value during reset */
+
+/*
+ * Compression performance counter registers [5212+]
+ */
+#define AR5K_CPC0		0x0610		/* Compression performance counter 0 */
+#define AR5K_CPC1		0x0614		/* Compression performance counter 1*/
+#define AR5K_CPC2		0x0618		/* Compression performance counter 2 */
+#define AR5K_CPC3		0x061c		/* Compression performance counter 3 */
+#define AR5K_CPCOVF		0x0620		/* Compression performance overflow */
+
+
+/*
+ * Queue control unit (QCU) registers [5211+]
+ *
+ * Card has 12 TX Queues but i see that only 0-9 are used (?)
+ * both in binary HAL (see ah.h) and ar5k. Each queue has it's own
+ * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate)
+ * configuration register (0x08c0 - 0x08ec), a ready time configuration
+ * register (0x0900 - 0x092c), a misc configuration register (0x09c0 -
+ * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some
+ * global registers, QCU transmit enable/disable and "one shot arm (?)"
+ * set/clear, which contain status for all queues (we shift by 1 for each
+ * queue). To access these registers easily we define some macros here
+ * that are used inside HAL. For more infos check out *_tx_queue functs.
+ */
+
+/*
+ * Generic QCU Register access macros
+ */
+#define	AR5K_QUEUE_REG(_r, _q)		(((_q) << 2) + _r)
+#define AR5K_QCU_GLOBAL_READ(_r, _q)	(AR5K_REG_READ(_r) & (1 << _q))
+#define AR5K_QCU_GLOBAL_WRITE(_r, _q)	AR5K_REG_WRITE(_r, (1 << _q))
+
+/*
+ * QCU Transmit descriptor pointer registers
+ */
+#define AR5K_QCU_TXDP_BASE	0x0800		/* Register Address - Queue0 TXDP */
+#define AR5K_QUEUE_TXDP(_q)	AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q)
+
+/*
+ * QCU Transmit enable register
+ */
+#define AR5K_QCU_TXE		0x0840
+#define AR5K_ENABLE_QUEUE(_q)	AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q)
+#define AR5K_QUEUE_ENABLED(_q)	AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q)
+
+/*
+ * QCU Transmit disable register
+ */
+#define AR5K_QCU_TXD		0x0880
+#define AR5K_DISABLE_QUEUE(_q)	AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q)
+#define AR5K_QUEUE_DISABLED(_q)	AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q)
+
+/*
+ * QCU Constant Bit Rate configuration registers
+ */
+#define	AR5K_QCU_CBRCFG_BASE		0x08c0	/* Register Address - Queue0 CBRCFG */
+#define	AR5K_QCU_CBRCFG_INTVAL		0x00ffffff	/* CBR Interval mask */
+#define AR5K_QCU_CBRCFG_INTVAL_S	0
+#define	AR5K_QCU_CBRCFG_ORN_THRES	0xff000000	/* CBR overrun threshold mask */
+#define AR5K_QCU_CBRCFG_ORN_THRES_S	24
+#define	AR5K_QUEUE_CBRCFG(_q)		AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q)
+
+/*
+ * QCU Ready time configuration registers
+ */
+#define	AR5K_QCU_RDYTIMECFG_BASE	0x0900	/* Register Address - Queue0 RDYTIMECFG */
+#define	AR5K_QCU_RDYTIMECFG_INTVAL	0x00ffffff	/* Ready time interval mask */
+#define AR5K_QCU_RDYTIMECFG_INTVAL_S	0
+#define	AR5K_QCU_RDYTIMECFG_ENABLE	0x01000000	/* Ready time enable mask */
+#define AR5K_QUEUE_RDYTIMECFG(_q)	AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q)
+
+/*
+ * QCU one shot arm set registers
+ */
+#define	AR5K_QCU_ONESHOTARM_SET		0x0940	/* Register Address -QCU "one shot arm set (?)" */
+#define	AR5K_QCU_ONESHOTARM_SET_M	0x0000ffff
+
+/*
+ * QCU one shot arm clear registers
+ */
+#define	AR5K_QCU_ONESHOTARM_CLEAR	0x0980	/* Register Address -QCU "one shot arm clear (?)" */
+#define	AR5K_QCU_ONESHOTARM_CLEAR_M	0x0000ffff
+
+/*
+ * QCU misc registers
+ */
+#define AR5K_QCU_MISC_BASE		0x09c0			/* Register Address -Queue0 MISC */
+#define	AR5K_QCU_MISC_FRSHED_M		0x0000000f	/* Frame sheduling mask */
+#define	AR5K_QCU_MISC_FRSHED_ASAP		0	/* ASAP */
+#define	AR5K_QCU_MISC_FRSHED_CBR		1	/* Constant Bit Rate */
+#define	AR5K_QCU_MISC_FRSHED_DBA_GT		2	/* DMA Beacon alert gated */
+#define	AR5K_QCU_MISC_FRSHED_TIM_GT		3	/* TIMT gated */
+#define	AR5K_QCU_MISC_FRSHED_BCN_SENT_GT	4	/* Beacon sent gated */
+#define	AR5K_QCU_MISC_ONESHOT_ENABLE	0x00000010	/* Oneshot enable */
+#define	AR5K_QCU_MISC_CBREXP_DIS	0x00000020	/* Disable CBR expired counter (normal queue) */
+#define	AR5K_QCU_MISC_CBREXP_BCN_DIS	0x00000040	/* Disable CBR expired counter (beacon queue) */
+#define	AR5K_QCU_MISC_BCN_ENABLE	0x00000080	/* Enable Beacon use */
+#define	AR5K_QCU_MISC_CBR_THRES_ENABLE	0x00000100	/* CBR expired threshold enabled */
+#define	AR5K_QCU_MISC_RDY_VEOL_POLICY	0x00000200	/* TXE reset when RDYTIME expired or VEOL */
+#define	AR5K_QCU_MISC_CBR_RESET_CNT	0x00000400	/* CBR threshold (counter) reset */
+#define	AR5K_QCU_MISC_DCU_EARLY		0x00000800	/* DCU early termination */
+#define AR5K_QCU_MISC_DCU_CMP_EN	0x00001000	/* Enable frame compression */
+#define AR5K_QUEUE_MISC(_q)		AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q)
+
+
+/*
+ * QCU status registers
+ */
+#define AR5K_QCU_STS_BASE	0x0a00			/* Register Address - Queue0 STS */
+#define	AR5K_QCU_STS_FRMPENDCNT	0x00000003	/* Frames pending counter */
+#define	AR5K_QCU_STS_CBREXPCNT	0x0000ff00	/* CBR expired counter */
+#define	AR5K_QUEUE_STATUS(_q)	AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q)
+
+/*
+ * QCU ready time shutdown register
+ */
+#define AR5K_QCU_RDYTIMESHDN	0x0a40
+#define AR5K_QCU_RDYTIMESHDN_M	0x000003ff
+
+/*
+ * QCU compression buffer base registers [5212+]
+ */
+#define AR5K_QCU_CBB_SELECT	0x0b00
+#define AR5K_QCU_CBB_ADDR	0x0b04
+#define AR5K_QCU_CBB_ADDR_S	9
+
+/*
+ * QCU compression buffer configuration register [5212+]
+ * (buffer size)
+ */
+#define AR5K_QCU_CBCFG		0x0b08
+
+
+
+/*
+ * Distributed Coordination Function (DCF) control unit (DCU)
+ * registers [5211+]
+ *
+ * These registers control the various characteristics of each queue
+ * for 802.11e (WME) combatibility so they go together with
+ * QCU registers in pairs. For each queue we have a QCU mask register,
+ * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
+ * a retry limit register (0x1080 - 0x10ac), a channel time register
+ * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
+ * a sequence number register (0x1140 - 0x116c). It seems that "global"
+ * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
+ * We use the same macros here for easier register access.
+ *
+ */
+
+/*
+ * DCU QCU mask registers
+ */
+#define AR5K_DCU_QCUMASK_BASE	0x1000		/* Register Address -Queue0 DCU_QCUMASK */
+#define AR5K_DCU_QCUMASK_M	0x000003ff
+#define AR5K_QUEUE_QCUMASK(_q)	AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q)
+
+/*
+ * DCU local Inter Frame Space settings register
+ */
+#define AR5K_DCU_LCL_IFS_BASE		0x1040			/* Register Address -Queue0 DCU_LCL_IFS */
+#define	AR5K_DCU_LCL_IFS_CW_MIN	        0x000003ff	/* Minimum Contention Window */
+#define	AR5K_DCU_LCL_IFS_CW_MIN_S	0
+#define	AR5K_DCU_LCL_IFS_CW_MAX	        0x000ffc00	/* Maximum Contention Window */
+#define	AR5K_DCU_LCL_IFS_CW_MAX_S	10
+#define	AR5K_DCU_LCL_IFS_AIFS		0x0ff00000	/* Arbitrated Interframe Space */
+#define	AR5K_DCU_LCL_IFS_AIFS_S		20
+#define	AR5K_DCU_LCL_IFS_AIFS_MAX	0xfc		/* Anything above that can cause DCU to hang */
+#define	AR5K_QUEUE_DFS_LOCAL_IFS(_q)	AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
+
+/*
+ * DCU retry limit registers
+ */
+#define AR5K_DCU_RETRY_LMT_BASE		0x1080			/* Register Address -Queue0 DCU_RETRY_LMT */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY	0x0000000f	/* Short retry limit mask */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY_S	0
+#define AR5K_DCU_RETRY_LMT_LG_RETRY	0x000000f0	/* Long retry limit mask */
+#define AR5K_DCU_RETRY_LMT_LG_RETRY_S	4
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY	0x00003f00	/* Station short retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S	8
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY	0x000fc000	/* Station long retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S	14
+#define	AR5K_QUEUE_DFS_RETRY_LIMIT(_q)	AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
+
+/*
+ * DCU channel time registers
+ */
+#define AR5K_DCU_CHAN_TIME_BASE		0x10c0			/* Register Address -Queue0 DCU_CHAN_TIME */
+#define	AR5K_DCU_CHAN_TIME_DUR		0x000fffff	/* Channel time duration */
+#define	AR5K_DCU_CHAN_TIME_DUR_S	0
+#define	AR5K_DCU_CHAN_TIME_ENABLE	0x00100000	/* Enable channel time */
+#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q)	AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q)
+
+/*
+ * DCU misc registers [5211+]
+ *
+ * Note: Arbiter lockout control controls the
+ * behaviour on low priority queues when we have multiple queues
+ * with pending frames. Intra-frame lockout means we wait until
+ * the queue's current frame transmits (with post frame backoff and bursting)
+ * before we transmit anything else and global lockout means we
+ * wait for the whole queue to finish before higher priority queues
+ * can transmit (this is used on beacon and CAB queues).
+ * No lockout means there is no special handling.
+ */
+#define AR5K_DCU_MISC_BASE		0x1100			/* Register Address -Queue0 DCU_MISC */
+#define	AR5K_DCU_MISC_BACKOFF		0x0000003f	/* Mask for backoff threshold */
+#define	AR5K_DCU_MISC_ETS_RTS_POL	0x00000040	/* End of transmission series
+							station RTS/data failure count
+							reset policy (?) */
+#define AR5K_DCU_MISC_ETS_CW_POL	0x00000080	/* End of transmission series
+							CW reset policy */
+#define	AR5K_DCU_MISC_FRAG_WAIT		0x00000100	/* Wait for next fragment */
+#define AR5K_DCU_MISC_BACKOFF_FRAG	0x00000200	/* Enable backoff while bursting */
+#define	AR5K_DCU_MISC_HCFPOLL_ENABLE	0x00000800	/* CF - Poll enable */
+#define	AR5K_DCU_MISC_BACKOFF_PERSIST	0x00001000	/* Persistent backoff */
+#define	AR5K_DCU_MISC_FRMPRFTCH_ENABLE	0x00002000	/* Enable frame pre-fetch */
+#define	AR5K_DCU_MISC_VIRTCOL		0x0000c000	/* Mask for Virtual Collision (?) */
+#define	AR5K_DCU_MISC_VIRTCOL_NORMAL	0
+#define	AR5K_DCU_MISC_VIRTCOL_IGNORE	1
+#define	AR5K_DCU_MISC_BCN_ENABLE	0x00010000	/* Enable Beacon use */
+#define	AR5K_DCU_MISC_ARBLOCK_CTL	0x00060000	/* Arbiter lockout control mask */
+#define	AR5K_DCU_MISC_ARBLOCK_CTL_S	17
+#define	AR5K_DCU_MISC_ARBLOCK_CTL_NONE		0	/* No arbiter lockout */
+#define	AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM	1	/* Intra-frame lockout */
+#define	AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL	2	/* Global lockout */
+#define	AR5K_DCU_MISC_ARBLOCK_IGNORE	0x00080000	/* Ignore Arbiter lockout */
+#define	AR5K_DCU_MISC_SEQ_NUM_INCR_DIS	0x00100000	/* Disable sequence number increment */
+#define	AR5K_DCU_MISC_POST_FR_BKOFF_DIS	0x00200000	/* Disable post-frame backoff */
+#define	AR5K_DCU_MISC_VIRT_COLL_POLICY	0x00400000	/* Virtual Collision cw policy */
+#define	AR5K_DCU_MISC_BLOWN_IFS_POLICY	0x00800000	/* Blown IFS policy (?) */
+#define	AR5K_DCU_MISC_SEQNUM_CTL	0x01000000	/* Sequence number control (?) */
+#define AR5K_QUEUE_DFS_MISC(_q)		AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q)
+
+/*
+ * DCU frame sequence number registers
+ */
+#define AR5K_DCU_SEQNUM_BASE		0x1140
+#define	AR5K_DCU_SEQNUM_M		0x00000fff
+#define	AR5K_QUEUE_DCU_SEQNUM(_q)	AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
+
+/*
+ * DCU global IFS SIFS register
+ */
+#define AR5K_DCU_GBL_IFS_SIFS	0x1030
+#define AR5K_DCU_GBL_IFS_SIFS_M	0x0000ffff
+
+/*
+ * DCU global IFS slot interval register
+ */
+#define AR5K_DCU_GBL_IFS_SLOT	0x1070
+#define AR5K_DCU_GBL_IFS_SLOT_M	0x0000ffff
+
+/*
+ * DCU global IFS EIFS register
+ */
+#define AR5K_DCU_GBL_IFS_EIFS	0x10b0
+#define AR5K_DCU_GBL_IFS_EIFS_M	0x0000ffff
+
+/*
+ * DCU global IFS misc register
+ *
+ * LFSR stands for Linear Feedback Shift Register
+ * and it's used for generating pseudo-random
+ * number sequences.
+ *
+ * (If i understand corectly, random numbers are
+ * used for idle sensing -multiplied with cwmin/max etc-)
+ */
+#define AR5K_DCU_GBL_IFS_MISC			0x10f0			/* Register Address */
+#define	AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE	0x00000007	/* LFSR Slice Select */
+#define	AR5K_DCU_GBL_IFS_MISC_TURBO_MODE	0x00000008	/* Turbo mode */
+#define	AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC	0x000003f0	/* SIFS Duration mask */
+#define	AR5K_DCU_GBL_IFS_MISC_USEC_DUR		0x000ffc00	/* USEC Duration mask */
+#define	AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S	10
+#define	AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY	0x00300000	/* DCU Arbiter delay mask */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST	0x00400000	/* SIFS cnt reset policy (?) */
+#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST	0x00800000	/* AIFS cnt reset policy (?) */
+#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS	0x01000000	/* Disable random LFSR slice */
+
+/*
+ * DCU frame prefetch control register
+ */
+#define AR5K_DCU_FP			0x1230			/* Register Address */
+#define AR5K_DCU_FP_NOBURST_DCU_EN	0x00000001	/* Enable non-burst prefetch on DCU (?) */
+#define AR5K_DCU_FP_NOBURST_EN		0x00000010	/* Enable non-burst prefetch (?) */
+#define AR5K_DCU_FP_BURST_DCU_EN	0x00000020	/* Enable burst prefetch on DCU (?) */
+
+/*
+ * DCU transmit pause control/status register
+ */
+#define AR5K_DCU_TXP		0x1270			/* Register Address */
+#define	AR5K_DCU_TXP_M		0x000003ff	/* Tx pause mask */
+#define	AR5K_DCU_TXP_STATUS	0x00010000	/* Tx pause status */
+
+/*
+ * DCU transmit filter table 0 (32 entries)
+ * each entry contains a 32bit slice of the
+ * 128bit tx filter for each DCU (4 slices per DCU)
+ */
+#define AR5K_DCU_TX_FILTER_0_BASE	0x1038
+#define	AR5K_DCU_TX_FILTER_0(_n)	(AR5K_DCU_TX_FILTER_0_BASE + (_n * 64))
+
+/*
+ * DCU transmit filter table 1 (16 entries)
+ */
+#define AR5K_DCU_TX_FILTER_1_BASE	0x103c
+#define	AR5K_DCU_TX_FILTER_1(_n)	(AR5K_DCU_TX_FILTER_1_BASE + (_n * 64))
+
+/*
+ * DCU clear transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_CLR	0x143c
+
+/*
+ * DCU set transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_SET	0x147c
+
+/*
+ * Reset control register
+ */
+#define AR5K_RESET_CTL		0x4000			/* Register Address */
+#define AR5K_RESET_CTL_PCU	0x00000001	/* Protocol Control Unit reset */
+#define AR5K_RESET_CTL_DMA	0x00000002	/* DMA (Rx/Tx) reset [5210] */
+#define	AR5K_RESET_CTL_BASEBAND	0x00000002	/* Baseband reset [5211+] */
+#define AR5K_RESET_CTL_MAC	0x00000004	/* MAC reset (PCU+Baseband ?) [5210] */
+#define AR5K_RESET_CTL_PHY	0x00000008	/* PHY reset [5210] */
+#define AR5K_RESET_CTL_PCI	0x00000010	/* PCI Core reset (interrupts etc) */
+
+/*
+ * Sleep control register
+ */
+#define AR5K_SLEEP_CTL			0x4004			/* Register Address */
+#define AR5K_SLEEP_CTL_SLDUR		0x0000ffff	/* Sleep duration mask */
+#define AR5K_SLEEP_CTL_SLDUR_S		0
+#define AR5K_SLEEP_CTL_SLE		0x00030000	/* Sleep enable mask */
+#define AR5K_SLEEP_CTL_SLE_S		16
+#define AR5K_SLEEP_CTL_SLE_WAKE		0x00000000	/* Force chip awake */
+#define AR5K_SLEEP_CTL_SLE_SLP		0x00010000	/* Force chip sleep */
+#define AR5K_SLEEP_CTL_SLE_ALLOW	0x00020000	/* Normal sleep policy */
+#define AR5K_SLEEP_CTL_SLE_UNITS	0x00000008	/* [5211+] */
+#define AR5K_SLEEP_CTL_DUR_TIM_POL	0x00040000	/* Sleep duration timing policy */
+#define AR5K_SLEEP_CTL_DUR_WRITE_POL	0x00080000	/* Sleep duration write policy */
+#define AR5K_SLEEP_CTL_SLE_POL		0x00100000	/* Sleep policy mode */
+
+/*
+ * Interrupt pending register
+ */
+#define AR5K_INTPEND	0x4008
+#define AR5K_INTPEND_M	0x00000001
+
+/*
+ * Sleep force register
+ */
+#define AR5K_SFR	0x400c
+#define AR5K_SFR_EN	0x00000001
+
+/*
+ * PCI configuration register
+ * TODO: Fix LED stuff
+ */
+#define AR5K_PCICFG			0x4010			/* Register Address */
+#define AR5K_PCICFG_EEAE		0x00000001	/* Eeprom access enable [5210] */
+#define AR5K_PCICFG_SLEEP_CLOCK_EN	0x00000002	/* Enable sleep clock */
+#define AR5K_PCICFG_CLKRUNEN		0x00000004	/* CLKRUN enable [5211+] */
+#define AR5K_PCICFG_EESIZE		0x00000018	/* Mask for EEPROM size [5211+] */
+#define AR5K_PCICFG_EESIZE_S		3
+#define AR5K_PCICFG_EESIZE_4K		0		/* 4K */
+#define AR5K_PCICFG_EESIZE_8K		1		/* 8K */
+#define AR5K_PCICFG_EESIZE_16K		2		/* 16K */
+#define AR5K_PCICFG_EESIZE_FAIL		3		/* Failed to get size [5211+] */
+#define AR5K_PCICFG_LED			0x00000060	/* Led status [5211+] */
+#define AR5K_PCICFG_LED_NONE		0x00000000	/* Default [5211+] */
+#define AR5K_PCICFG_LED_PEND		0x00000020	/* Scan / Auth pending */
+#define AR5K_PCICFG_LED_ASSOC		0x00000040	/* Associated */
+#define	AR5K_PCICFG_BUS_SEL		0x00000380	/* Mask for "bus select" [5211+] (?) */
+#define AR5K_PCICFG_CBEFIX_DIS		0x00000400	/* Disable CBE fix */
+#define AR5K_PCICFG_SL_INTEN		0x00000800	/* Enable interrupts when asleep */
+#define AR5K_PCICFG_LED_BCTL		0x00001000	/* Led blink (?) [5210] */
+#define AR5K_PCICFG_RETRY_FIX		0x00001000	/* Enable pci core retry fix */
+#define AR5K_PCICFG_SL_INPEN		0x00002000	/* Sleep even whith pending interrupts*/
+#define AR5K_PCICFG_SPWR_DN		0x00010000	/* Mask for power status */
+#define AR5K_PCICFG_LEDMODE		0x000e0000	/* Ledmode [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROP	0x00000000	/* Blink on standard traffic [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROM	0x00020000	/* Default mode (blink on any traffic) [5211+] */
+#define AR5K_PCICFG_LEDMODE_PWR		0x00040000	/* Some other blinking mode  (?) [5211+] */
+#define AR5K_PCICFG_LEDMODE_RAND	0x00060000	/* Random blinking (?) [5211+] */
+#define AR5K_PCICFG_LEDBLINK		0x00700000	/* Led blink rate */
+#define AR5K_PCICFG_LEDBLINK_S		20
+#define AR5K_PCICFG_LEDSLOW		0x00800000	/* Slowest led blink rate [5211+] */
+#define AR5K_PCICFG_LEDSTATE				\
+	(AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE |	\
+	AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
+#define	AR5K_PCICFG_SLEEP_CLOCK_RATE	0x03000000	/* Sleep clock rate */
+#define	AR5K_PCICFG_SLEEP_CLOCK_RATE_S	24
+
+/*
+ * "General Purpose Input/Output" (GPIO) control register
+ *
+ * I'm not sure about this but after looking at the code
+ * for all chipsets here is what i got.
+ *
+ * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits)
+ * Mode 0 -> always input
+ * Mode 1 -> output when GPIODO for this GPIO is set to 0
+ * Mode 2 -> output when GPIODO for this GPIO is set to 1
+ * Mode 3 -> always output
+ *
+ * For more infos check out get_gpio/set_gpio and
+ * set_gpio_input/set_gpio_output functs.
+ * For more infos on gpio interrupt check out set_gpio_intr.
+ */
+#define AR5K_NUM_GPIO	6
+
+#define AR5K_GPIOCR		0x4014				/* Register Address */
+#define AR5K_GPIOCR_INT_ENA	0x00008000		/* Enable GPIO interrupt */
+#define AR5K_GPIOCR_INT_SELL	0x00000000		/* Generate interrupt when pin is low */
+#define AR5K_GPIOCR_INT_SELH	0x00010000		/* Generate interrupt when pin is high */
+#define AR5K_GPIOCR_IN(n)	(0 << ((n) * 2))	/* Mode 0 for pin n */
+#define AR5K_GPIOCR_OUT0(n)	(1 << ((n) * 2))	/* Mode 1 for pin n */
+#define AR5K_GPIOCR_OUT1(n)	(2 << ((n) * 2))	/* Mode 2 for pin n */
+#define AR5K_GPIOCR_OUT(n)	(3 << ((n) * 2))	/* Mode 3 for pin n */
+#define AR5K_GPIOCR_INT_SEL(n)	((n) << 12)		/* Interrupt for GPIO pin n */
+
+/*
+ * "General Purpose Input/Output" (GPIO) data output register
+ */
+#define AR5K_GPIODO	0x4018
+
+/*
+ * "General Purpose Input/Output" (GPIO) data input register
+ */
+#define AR5K_GPIODI	0x401c
+#define AR5K_GPIODI_M	0x0000002f
+
+/*
+ * Silicon revision register
+ */
+#define AR5K_SREV		0x4020			/* Register Address */
+#define AR5K_SREV_REV		0x0000000f	/* Mask for revision */
+#define AR5K_SREV_REV_S		0
+#define AR5K_SREV_VER		0x000000ff	/* Mask for version */
+#define AR5K_SREV_VER_S		4
+
+/*
+ * TXE write posting register
+ */
+#define	AR5K_TXEPOST	0x4028
+
+/*
+ * QCU sleep mask
+ */
+#define	AR5K_QCU_SLEEP_MASK	0x402c
+
+/* 0x4068 is compression buffer configuration
+ * register on 5414 and pm configuration register
+ * on 5424 and newer pci-e chips. */
+
+/*
+ * Compression buffer configuration
+ * register (enable/disable) [5414]
+ */
+#define AR5K_5414_CBCFG		0x4068
+#define AR5K_5414_CBCFG_BUF_DIS	0x10	/* Disable buffer */
+
+/*
+ * PCI-E Power managment configuration
+ * and status register [5424+]
+ */
+#define	AR5K_PCIE_PM_CTL		0x4068			/* Register address */
+/* Only 5424 */
+#define	AR5K_PCIE_PM_CTL_L1_WHEN_D2	0x00000001	/* enable PCIe core enter L1
+							when d2_sleep_en is asserted */
+#define	AR5K_PCIE_PM_CTL_L0_L0S_CLEAR	0x00000002	/* Clear L0 and L0S counters */
+#define	AR5K_PCIE_PM_CTL_L0_L0S_EN	0x00000004	/* Start L0 nd L0S counters */
+#define	AR5K_PCIE_PM_CTL_LDRESET_EN	0x00000008	/* Enable reset when link goes
+							down */
+/* Wake On Wireless */
+#define	AR5K_PCIE_PM_CTL_PME_EN		0x00000010	/* PME Enable */
+#define	AR5K_PCIE_PM_CTL_AUX_PWR_DET	0x00000020	/* Aux power detect */
+#define	AR5K_PCIE_PM_CTL_PME_CLEAR	0x00000040	/* Clear PME */
+#define	AR5K_PCIE_PM_CTL_PSM_D0		0x00000080
+#define	AR5K_PCIE_PM_CTL_PSM_D1		0x00000100
+#define	AR5K_PCIE_PM_CTL_PSM_D2		0x00000200
+#define	AR5K_PCIE_PM_CTL_PSM_D3		0x00000400
+
+/*
+ * PCI-E Workaround enable register
+ */
+#define	AR5K_PCIE_WAEN	0x407c
+
+/*
+ * PCI-E Serializer/Desirializer
+ * registers
+ */
+#define	AR5K_PCIE_SERDES	0x4080
+#define	AR5K_PCIE_SERDES_RESET	0x4084
+
+/*====EEPROM REGISTERS====*/
+
+/*
+ * EEPROM access registers
+ *
+ * Here we got a difference between 5210/5211-12
+ * read data register for 5210 is at 0x6800 and
+ * status register is at 0x6c00. There is also
+ * no eeprom command register on 5210 and the
+ * offsets are different.
+ *
+ * To read eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ *        read AR5K_EEPROM_BASE +(4 * offset)
+ *        check the eeprom status register
+ *        and read eeprom data register.
+ *
+ * 5211 - write offset to AR5K_EEPROM_BASE
+ * 5212   write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD
+ *        check the eeprom status register
+ *        and read eeprom data register.
+ *
+ * To write eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ *        write data to AR5K_EEPROM_BASE +(4 * offset)
+ *        check the eeprom status register
+ * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD
+ * 5212   write offset to AR5K_EEPROM_BASE
+ *        write data to data register
+ *	  write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD
+ *        check the eeprom status register
+ *
+ * For more infos check eeprom_* functs and the ar5k.c
+ * file posted in madwifi-devel mailing list.
+ * http://sourceforge.net/mailarchive/message.php?msg_id=8966525
+ *
+ */
+#define AR5K_EEPROM_BASE	0x6000
+
+/*
+ * EEPROM data register
+ */
+#define AR5K_EEPROM_DATA_5211	0x6004
+#define AR5K_EEPROM_DATA_5210	0x6800
+#define	AR5K_EEPROM_DATA	(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
+
+/*
+ * EEPROM command register
+ */
+#define AR5K_EEPROM_CMD		0x6008			/* Register Addres */
+#define AR5K_EEPROM_CMD_READ	0x00000001	/* EEPROM read */
+#define AR5K_EEPROM_CMD_WRITE	0x00000002	/* EEPROM write */
+#define AR5K_EEPROM_CMD_RESET	0x00000004	/* EEPROM reset */
+
+/*
+ * EEPROM status register
+ */
+#define AR5K_EEPROM_STAT_5210	0x6c00			/* Register Address [5210] */
+#define AR5K_EEPROM_STAT_5211	0x600c			/* Register Address [5211+] */
+#define	AR5K_EEPROM_STATUS	(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
+#define AR5K_EEPROM_STAT_RDERR	0x00000001	/* EEPROM read failed */
+#define AR5K_EEPROM_STAT_RDDONE	0x00000002	/* EEPROM read successful */
+#define AR5K_EEPROM_STAT_WRERR	0x00000004	/* EEPROM write failed */
+#define AR5K_EEPROM_STAT_WRDONE	0x00000008	/* EEPROM write successful */
+
+/*
+ * EEPROM config register
+ */
+#define AR5K_EEPROM_CFG			0x6010			/* Register Addres */
+#define AR5K_EEPROM_CFG_SIZE		0x00000003		/* Size determination override */
+#define AR5K_EEPROM_CFG_SIZE_AUTO	0
+#define AR5K_EEPROM_CFG_SIZE_4KBIT	1
+#define AR5K_EEPROM_CFG_SIZE_8KBIT	2
+#define AR5K_EEPROM_CFG_SIZE_16KBIT	3
+#define AR5K_EEPROM_CFG_WR_WAIT_DIS	0x00000004	/* Disable write wait */
+#define AR5K_EEPROM_CFG_CLK_RATE	0x00000018	/* Clock rate */
+#define AR5K_EEPROM_CFG_CLK_RATE_S		3
+#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ	0
+#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ	1
+#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ	2
+#define AR5K_EEPROM_CFG_PROT_KEY	0x00ffff00      /* Protection key */
+#define AR5K_EEPROM_CFG_PROT_KEY_S	8
+#define AR5K_EEPROM_CFG_LIND_EN		0x01000000	/* Enable length indicator (?) */
+
+
+/*
+ * TODO: Wake On Wireless registers
+ * Range 0x7000 - 0x7ce0
+ */
+
+/*
+ * Protocol Control Unit (PCU) registers
+ */
+/*
+ * Used for checking initial register writes
+ * during channel reset (see reset func)
+ */
+#define AR5K_PCU_MIN	0x8000
+#define AR5K_PCU_MAX	0x8fff
+
+/*
+ * First station id register (Lower 32 bits of MAC address)
+ */
+#define AR5K_STA_ID0		0x8000
+#define	AR5K_STA_ID0_ARRD_L32	0xffffffff
+
+/*
+ * Second station id register (Upper 16 bits of MAC address + PCU settings)
+ */
+#define AR5K_STA_ID1			0x8004			/* Register Address */
+#define	AR5K_STA_ID1_ADDR_U16		0x0000ffff	/* Upper 16 bits of MAC addres */
+#define AR5K_STA_ID1_AP			0x00010000	/* Set AP mode */
+#define AR5K_STA_ID1_ADHOC		0x00020000	/* Set Ad-Hoc mode */
+#define AR5K_STA_ID1_PWR_SV		0x00040000	/* Power save reporting */
+#define AR5K_STA_ID1_NO_KEYSRCH		0x00080000	/* No key search */
+#define AR5K_STA_ID1_NO_PSPOLL		0x00100000	/* No power save polling [5210] */
+#define AR5K_STA_ID1_PCF_5211		0x00100000	/* Enable PCF on [5211+] */
+#define AR5K_STA_ID1_PCF_5210		0x00200000	/* Enable PCF on [5210]*/
+#define	AR5K_STA_ID1_PCF		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211)
+#define AR5K_STA_ID1_DEFAULT_ANTENNA	0x00200000	/* Use default antenna */
+#define AR5K_STA_ID1_DESC_ANTENNA	0x00400000	/* Update antenna from descriptor */
+#define AR5K_STA_ID1_RTS_DEF_ANTENNA	0x00800000	/* Use default antenna for RTS */
+#define AR5K_STA_ID1_ACKCTS_6MB		0x01000000	/* Use 6Mbit/s for ACK/CTS */
+#define AR5K_STA_ID1_BASE_RATE_11B	0x02000000	/* Use 11b base rate for ACK/CTS [5211+] */
+#define AR5K_STA_ID1_SELFGEN_DEF_ANT	0x04000000	/* Use def. antenna for self generated frames */
+#define AR5K_STA_ID1_CRYPT_MIC_EN	0x08000000	/* Enable MIC */
+#define AR5K_STA_ID1_KEYSRCH_MODE	0x10000000	/* Look up key when key id != 0 */
+#define AR5K_STA_ID1_PRESERVE_SEQ_NUM	0x20000000	/* Preserve sequence number */
+#define AR5K_STA_ID1_CBCIV_ENDIAN	0x40000000	/* ??? */
+#define AR5K_STA_ID1_KEYSRCH_MCAST	0x80000000	/* Do key cache search for mcast frames */
+
+#define	AR5K_STA_ID1_ANTENNA_SETTINGS	(AR5K_STA_ID1_DEFAULT_ANTENNA | \
+					AR5K_STA_ID1_DESC_ANTENNA | \
+					AR5K_STA_ID1_RTS_DEF_ANTENNA | \
+					AR5K_STA_ID1_SELFGEN_DEF_ANT)
+
+/*
+ * First BSSID register (MAC address, lower 32bits)
+ */
+#define AR5K_BSS_ID0	0x8008
+
+/*
+ * Second BSSID register (MAC address in upper 16 bits)
+ *
+ * AID: Association ID
+ */
+#define AR5K_BSS_ID1		0x800c
+#define AR5K_BSS_ID1_AID	0xffff0000
+#define AR5K_BSS_ID1_AID_S	16
+
+/*
+ * Backoff slot time register
+ */
+#define AR5K_SLOT_TIME	0x8010
+
+/*
+ * ACK/CTS timeout register
+ */
+#define AR5K_TIME_OUT		0x8014			/* Register Address */
+#define AR5K_TIME_OUT_ACK	0x00001fff	/* ACK timeout mask */
+#define AR5K_TIME_OUT_ACK_S	0
+#define AR5K_TIME_OUT_CTS	0x1fff0000	/* CTS timeout mask */
+#define AR5K_TIME_OUT_CTS_S	16
+
+/*
+ * RSSI threshold register
+ */
+#define AR5K_RSSI_THR			0x8018		/* Register Address */
+#define AR5K_RSSI_THR_M			0x000000ff	/* Mask for RSSI threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5210	0x00000700	/* Mask for Beacon Missed threshold [5210] */
+#define AR5K_RSSI_THR_BMISS_5210_S	8
+#define AR5K_RSSI_THR_BMISS_5211	0x0000ff00	/* Mask for Beacon Missed threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5211_S	8
+#define	AR5K_RSSI_THR_BMISS		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211)
+#define	AR5K_RSSI_THR_BMISS_S		8
+
+/*
+ * 5210 has more PCU registers because there is no QCU/DCU
+ * so queue parameters are set here, this way a lot common
+ * registers have different address for 5210. To make things
+ * easier we define a macro based on ah->ah_version for common
+ * registers with different addresses and common flags.
+ */
+
+/*
+ * Retry limit register
+ *
+ * Retry limit register for 5210 (no QCU/DCU so it's done in PCU)
+ */
+#define AR5K_NODCU_RETRY_LMT		0x801c			/* Register Address */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY	0x0000000f	/* Short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S	0
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY	0x000000f0	/* Long retry mask */
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S	4
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY	0x00003f00	/* Station short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S	8
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY	0x000fc000	/* Station long retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S	14
+#define AR5K_NODCU_RETRY_LMT_CW_MIN	0x3ff00000	/* Minimum contention window mask */
+#define AR5K_NODCU_RETRY_LMT_CW_MIN_S	20
+
+/*
+ * Transmit latency register
+ */
+#define AR5K_USEC_5210			0x8020			/* Register Address [5210] */
+#define AR5K_USEC_5211			0x801c			/* Register Address [5211+] */
+#define AR5K_USEC			(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_USEC_5210 : AR5K_USEC_5211)
+#define AR5K_USEC_1			0x0000007f	/* clock cycles for 1us */
+#define AR5K_USEC_1_S			0
+#define AR5K_USEC_32			0x00003f80	/* clock cycles for 1us while on 32Mhz clock */
+#define AR5K_USEC_32_S			7
+#define AR5K_USEC_TX_LATENCY_5211	0x007fc000
+#define AR5K_USEC_TX_LATENCY_5211_S	14
+#define AR5K_USEC_RX_LATENCY_5211	0x1f800000
+#define AR5K_USEC_RX_LATENCY_5211_S	23
+#define AR5K_USEC_TX_LATENCY_5210	0x000fc000	/* also for 5311 */
+#define AR5K_USEC_TX_LATENCY_5210_S	14
+#define AR5K_USEC_RX_LATENCY_5210	0x03f00000	/* also for 5311 */
+#define AR5K_USEC_RX_LATENCY_5210_S	20
+
+/*
+ * PCU beacon control register
+ */
+#define AR5K_BEACON_5210	0x8024			/*Register Address [5210] */
+#define AR5K_BEACON_5211	0x8020			/*Register Address [5211+] */
+#define AR5K_BEACON		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_BEACON_5210 : AR5K_BEACON_5211)
+#define AR5K_BEACON_PERIOD	0x0000ffff	/* Mask for beacon period */
+#define AR5K_BEACON_PERIOD_S	0
+#define AR5K_BEACON_TIM		0x007f0000	/* Mask for TIM offset */
+#define AR5K_BEACON_TIM_S	16
+#define AR5K_BEACON_ENABLE	0x00800000	/* Enable beacons */
+#define AR5K_BEACON_RESET_TSF	0x01000000	/* Force TSF reset */
+
+/*
+ * CFP period register
+ */
+#define AR5K_CFP_PERIOD_5210	0x8028
+#define AR5K_CFP_PERIOD_5211	0x8024
+#define AR5K_CFP_PERIOD		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211)
+
+/*
+ * Next beacon time register
+ */
+#define AR5K_TIMER0_5210	0x802c
+#define AR5K_TIMER0_5211	0x8028
+#define AR5K_TIMER0		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
+
+/*
+ * Next DMA beacon alert register
+ */
+#define AR5K_TIMER1_5210	0x8030
+#define AR5K_TIMER1_5211	0x802c
+#define AR5K_TIMER1		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
+
+/*
+ * Next software beacon alert register
+ */
+#define AR5K_TIMER2_5210	0x8034
+#define AR5K_TIMER2_5211	0x8030
+#define AR5K_TIMER2		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
+
+/*
+ * Next ATIM window time register
+ */
+#define AR5K_TIMER3_5210	0x8038
+#define AR5K_TIMER3_5211	0x8034
+#define AR5K_TIMER3		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
+
+
+/*
+ * 5210 First inter frame spacing register (IFS)
+ */
+#define AR5K_IFS0		0x8040
+#define AR5K_IFS0_SIFS		0x000007ff
+#define AR5K_IFS0_SIFS_S	0
+#define AR5K_IFS0_DIFS		0x007ff800
+#define AR5K_IFS0_DIFS_S	11
+
+/*
+ * 5210 Second inter frame spacing register (IFS)
+ */
+#define AR5K_IFS1		0x8044
+#define AR5K_IFS1_PIFS		0x00000fff
+#define AR5K_IFS1_PIFS_S	0
+#define AR5K_IFS1_EIFS		0x03fff000
+#define AR5K_IFS1_EIFS_S	12
+#define AR5K_IFS1_CS_EN		0x04000000
+
+
+/*
+ * CFP duration register
+ */
+#define AR5K_CFP_DUR_5210	0x8048
+#define AR5K_CFP_DUR_5211	0x8038
+#define AR5K_CFP_DUR		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211)
+
+/*
+ * Receive filter register
+ */
+#define AR5K_RX_FILTER_5210	0x804c			/* Register Address [5210] */
+#define AR5K_RX_FILTER_5211	0x803c			/* Register Address [5211+] */
+#define AR5K_RX_FILTER		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
+#define	AR5K_RX_FILTER_UCAST 	0x00000001	/* Don't filter unicast frames */
+#define	AR5K_RX_FILTER_MCAST 	0x00000002	/* Don't filter multicast frames */
+#define	AR5K_RX_FILTER_BCAST 	0x00000004	/* Don't filter broadcast frames */
+#define	AR5K_RX_FILTER_CONTROL 	0x00000008	/* Don't filter control frames */
+#define	AR5K_RX_FILTER_BEACON 	0x00000010	/* Don't filter beacon frames */
+#define	AR5K_RX_FILTER_PROM 	0x00000020	/* Set promiscuous mode */
+#define	AR5K_RX_FILTER_XRPOLL 	0x00000040	/* Don't filter XR poll frame [5212+] */
+#define	AR5K_RX_FILTER_PROBEREQ 0x00000080	/* Don't filter probe requests [5212+] */
+#define	AR5K_RX_FILTER_PHYERR_5212	0x00000100	/* Don't filter phy errors [5212+] */
+#define	AR5K_RX_FILTER_RADARERR_5212 	0x00000200	/* Don't filter phy radar errors [5212+] */
+#define AR5K_RX_FILTER_PHYERR_5211	0x00000040	/* [5211] */
+#define AR5K_RX_FILTER_RADARERR_5211	0x00000080	/* [5211] */
+#define AR5K_RX_FILTER_PHYERR  \
+	((ah->ah_version == AR5K_AR5211 ? \
+	AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212))
+#define        AR5K_RX_FILTER_RADARERR \
+	((ah->ah_version == AR5K_AR5211 ? \
+	AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212))
+
+/*
+ * Multicast filter register (lower 32 bits)
+ */
+#define AR5K_MCAST_FILTER0_5210	0x8050
+#define AR5K_MCAST_FILTER0_5211	0x8040
+#define AR5K_MCAST_FILTER0	(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211)
+
+/*
+ * Multicast filter register (higher 16 bits)
+ */
+#define AR5K_MCAST_FILTER1_5210	0x8054
+#define AR5K_MCAST_FILTER1_5211	0x8044
+#define AR5K_MCAST_FILTER1	(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211)
+
+
+/*
+ * Transmit mask register (lower 32 bits) [5210]
+ */
+#define AR5K_TX_MASK0	0x8058
+
+/*
+ * Transmit mask register (higher 16 bits) [5210]
+ */
+#define AR5K_TX_MASK1	0x805c
+
+/*
+ * Clear transmit mask [5210]
+ */
+#define AR5K_CLR_TMASK	0x8060
+
+/*
+ * Trigger level register (before transmission) [5210]
+ */
+#define AR5K_TRIG_LVL	0x8064
+
+
+/*
+ * PCU control register
+ *
+ * Only DIS_RX is used in the code, the rest i guess are
+ * for tweaking/diagnostics.
+ */
+#define AR5K_DIAG_SW_5210		0x8068			/* Register Address [5210] */
+#define AR5K_DIAG_SW_5211		0x8048			/* Register Address [5211+] */
+#define AR5K_DIAG_SW			(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211)
+#define AR5K_DIAG_SW_DIS_WEP_ACK	0x00000001	/* Disable ACKs if WEP key is invalid */
+#define AR5K_DIAG_SW_DIS_ACK		0x00000002	/* Disable ACKs */
+#define AR5K_DIAG_SW_DIS_CTS		0x00000004	/* Disable CTSs */
+#define AR5K_DIAG_SW_DIS_ENC		0x00000008	/* Disable encryption */
+#define AR5K_DIAG_SW_DIS_DEC		0x00000010	/* Disable decryption */
+#define AR5K_DIAG_SW_DIS_TX		0x00000020	/* Disable transmit [5210] */
+#define AR5K_DIAG_SW_DIS_RX_5210	0x00000040	/* Disable recieve */
+#define AR5K_DIAG_SW_DIS_RX_5211	0x00000020
+#define	AR5K_DIAG_SW_DIS_RX		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
+#define AR5K_DIAG_SW_LOOP_BACK_5210	0x00000080	/* Loopback (i guess it goes with DIS_TX) [5210] */
+#define AR5K_DIAG_SW_LOOP_BACK_5211	0x00000040
+#define AR5K_DIAG_SW_LOOP_BACK		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
+#define AR5K_DIAG_SW_CORR_FCS_5210	0x00000100	/* Corrupted FCS */
+#define AR5K_DIAG_SW_CORR_FCS_5211	0x00000080
+#define AR5K_DIAG_SW_CORR_FCS		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
+#define AR5K_DIAG_SW_CHAN_INFO_5210	0x00000200	/* Dump channel info */
+#define AR5K_DIAG_SW_CHAN_INFO_5211	0x00000100
+#define AR5K_DIAG_SW_CHAN_INFO		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210	0x00000400	/* Enable fixed scrambler seed */
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211	0x00000200
+#define AR5K_DIAG_SW_EN_SCRAM_SEED	(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
+#define AR5K_DIAG_SW_ECO_ENABLE		0x00000400	/* [5211+] */
+#define AR5K_DIAG_SW_SCVRAM_SEED	0x0003f800	/* [5210] */
+#define AR5K_DIAG_SW_SCRAM_SEED_M	0x0001fc00	/* Scrambler seed mask */
+#define AR5K_DIAG_SW_SCRAM_SEED_S	10
+#define AR5K_DIAG_SW_DIS_SEQ_INC	0x00040000	/* Disable seqnum increment (?)[5210] */
+#define AR5K_DIAG_SW_FRAME_NV0_5210	0x00080000
+#define AR5K_DIAG_SW_FRAME_NV0_5211	0x00020000	/* Accept frames of non-zero protocol number */
+#define	AR5K_DIAG_SW_FRAME_NV0		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
+#define AR5K_DIAG_SW_OBSPT_M		0x000c0000	/* Observation point select (?) */
+#define AR5K_DIAG_SW_OBSPT_S		18
+#define AR5K_DIAG_SW_RX_CLEAR_HIGH	0x0010000	/* Force RX Clear high */
+#define AR5K_DIAG_SW_IGNORE_CARR_SENSE	0x0020000	/* Ignore virtual carrier sense */
+#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH	0x0040000	/* Force channel idle high */
+#define AR5K_DIAG_SW_PHEAR_ME		0x0080000	/* ??? */
+
+/*
+ * TSF (clock) register (lower 32 bits)
+ */
+#define AR5K_TSF_L32_5210	0x806c
+#define AR5K_TSF_L32_5211	0x804c
+#define	AR5K_TSF_L32		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
+
+/*
+ * TSF (clock) register (higher 32 bits)
+ */
+#define AR5K_TSF_U32_5210	0x8070
+#define AR5K_TSF_U32_5211	0x8050
+#define	AR5K_TSF_U32		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
+
+/*
+ * Last beacon timestamp register (Read Only)
+ */
+#define AR5K_LAST_TSTP	0x8080
+
+/*
+ * ADDAC test register [5211+]
+ */
+#define AR5K_ADDAC_TEST			0x8054			/* Register Address */
+#define AR5K_ADDAC_TEST_TXCONT 		0x00000001	/* Test continuous tx */
+#define AR5K_ADDAC_TEST_TST_MODE	0x00000002	/* Test mode */
+#define AR5K_ADDAC_TEST_LOOP_EN		0x00000004	/* Enable loop */
+#define AR5K_ADDAC_TEST_LOOP_LEN	0x00000008	/* Loop length (field) */
+#define AR5K_ADDAC_TEST_USE_U8		0x00004000	/* Use upper 8 bits */
+#define AR5K_ADDAC_TEST_MSB		0x00008000	/* State of MSB */
+#define AR5K_ADDAC_TEST_TRIG_SEL	0x00010000	/* Trigger select */
+#define AR5K_ADDAC_TEST_TRIG_PTY	0x00020000	/* Trigger polarity */
+#define AR5K_ADDAC_TEST_RXCONT		0x00040000	/* Continuous capture */
+#define AR5K_ADDAC_TEST_CAPTURE		0x00080000	/* Begin capture */
+#define AR5K_ADDAC_TEST_TST_ARM		0x00100000	/* ARM rx buffer for capture */
+
+/*
+ * Default antenna register [5211+]
+ */
+#define AR5K_DEFAULT_ANTENNA	0x8058
+
+/*
+ * Frame control QoS mask register (?) [5211+]
+ * (FC_QOS_MASK)
+ */
+#define AR5K_FRAME_CTL_QOSM	0x805c
+
+/*
+ * Seq mask register (?) [5211+]
+ */
+#define AR5K_SEQ_MASK	0x8060
+
+/*
+ * Retry count register [5210]
+ */
+#define AR5K_RETRY_CNT		0x8084			/* Register Address [5210] */
+#define AR5K_RETRY_CNT_SSH	0x0000003f	/* Station short retry count (?) */
+#define AR5K_RETRY_CNT_SLG	0x00000fc0	/* Station long retry count (?) */
+
+/*
+ * Back-off status register [5210]
+ */
+#define AR5K_BACKOFF		0x8088			/* Register Address [5210] */
+#define AR5K_BACKOFF_CW		0x000003ff	/* Backoff Contention Window (?) */
+#define AR5K_BACKOFF_CNT	0x03ff0000	/* Backoff count (?) */
+
+
+
+/*
+ * NAV register (current)
+ */
+#define AR5K_NAV_5210		0x808c
+#define AR5K_NAV_5211		0x8084
+#define	AR5K_NAV		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_NAV_5210 : AR5K_NAV_5211)
+
+/*
+ * RTS success register
+ */
+#define AR5K_RTS_OK_5210	0x8090
+#define AR5K_RTS_OK_5211	0x8088
+#define	AR5K_RTS_OK		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
+
+/*
+ * RTS failure register
+ */
+#define AR5K_RTS_FAIL_5210	0x8094
+#define AR5K_RTS_FAIL_5211	0x808c
+#define	AR5K_RTS_FAIL		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
+
+/*
+ * ACK failure register
+ */
+#define AR5K_ACK_FAIL_5210	0x8098
+#define AR5K_ACK_FAIL_5211	0x8090
+#define	AR5K_ACK_FAIL		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
+
+/*
+ * FCS failure register
+ */
+#define AR5K_FCS_FAIL_5210	0x809c
+#define AR5K_FCS_FAIL_5211	0x8094
+#define	AR5K_FCS_FAIL		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211)
+
+/*
+ * Beacon count register
+ */
+#define AR5K_BEACON_CNT_5210	0x80a0
+#define AR5K_BEACON_CNT_5211	0x8098
+#define	AR5K_BEACON_CNT		(ah->ah_version == AR5K_AR5210 ? \
+				AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211)
+
+
+/*===5212 Specific PCU registers===*/
+
+/*
+ * Transmit power control register
+ */
+#define AR5K_TPC			0x80e8
+#define AR5K_TPC_ACK			0x0000003f	/* ack frames */
+#define AR5K_TPC_ACK_S			0
+#define AR5K_TPC_CTS			0x00003f00	/* cts frames */
+#define AR5K_TPC_CTS_S			8
+#define AR5K_TPC_CHIRP			0x003f0000	/* chirp frames */
+#define AR5K_TPC_CHIRP_S		16
+#define AR5K_TPC_DOPPLER		0x0f000000	/* doppler chirp span */
+#define AR5K_TPC_DOPPLER_S		24
+
+/*
+ * XR (eXtended Range) mode register
+ */
+#define AR5K_XRMODE			0x80c0			/* Register Address */
+#define	AR5K_XRMODE_POLL_TYPE_M		0x0000003f	/* Mask for Poll type (?) */
+#define	AR5K_XRMODE_POLL_TYPE_S		0
+#define	AR5K_XRMODE_POLL_SUBTYPE_M	0x0000003c	/* Mask for Poll subtype (?) */
+#define	AR5K_XRMODE_POLL_SUBTYPE_S	2
+#define	AR5K_XRMODE_POLL_WAIT_ALL	0x00000080	/* Wait for poll */
+#define	AR5K_XRMODE_SIFS_DELAY		0x000fff00	/* Mask for SIFS delay */
+#define	AR5K_XRMODE_FRAME_HOLD_M	0xfff00000	/* Mask for frame hold (?) */
+#define	AR5K_XRMODE_FRAME_HOLD_S	20
+
+/*
+ * XR delay register
+ */
+#define AR5K_XRDELAY			0x80c4			/* Register Address */
+#define AR5K_XRDELAY_SLOT_DELAY_M	0x0000ffff	/* Mask for slot delay */
+#define AR5K_XRDELAY_SLOT_DELAY_S	0
+#define AR5K_XRDELAY_CHIRP_DELAY_M	0xffff0000	/* Mask for CHIRP data delay */
+#define AR5K_XRDELAY_CHIRP_DELAY_S	16
+
+/*
+ * XR timeout register
+ */
+#define AR5K_XRTIMEOUT			0x80c8			/* Register Address */
+#define AR5K_XRTIMEOUT_CHIRP_M		0x0000ffff	/* Mask for CHIRP timeout */
+#define AR5K_XRTIMEOUT_CHIRP_S		0
+#define AR5K_XRTIMEOUT_POLL_M		0xffff0000	/* Mask for Poll timeout */
+#define AR5K_XRTIMEOUT_POLL_S		16
+
+/*
+ * XR chirp register
+ */
+#define AR5K_XRCHIRP			0x80cc			/* Register Address */
+#define AR5K_XRCHIRP_SEND		0x00000001	/* Send CHIRP */
+#define AR5K_XRCHIRP_GAP		0xffff0000	/* Mask for CHIRP gap (?) */
+
+/*
+ * XR stomp register
+ */
+#define AR5K_XRSTOMP			0x80d0			/* Register Address */
+#define AR5K_XRSTOMP_TX			0x00000001	/* Stomp Tx (?) */
+#define AR5K_XRSTOMP_RX			0x00000002	/* Stomp Rx (?) */
+#define AR5K_XRSTOMP_TX_RSSI		0x00000004	/* Stomp Tx RSSI (?) */
+#define AR5K_XRSTOMP_TX_BSSID		0x00000008	/* Stomp Tx BSSID (?) */
+#define AR5K_XRSTOMP_DATA		0x00000010	/* Stomp data (?)*/
+#define AR5K_XRSTOMP_RSSI_THRES		0x0000ff00	/* Mask for XR RSSI threshold */
+
+/*
+ * First enhanced sleep register
+ */
+#define AR5K_SLEEP0			0x80d4			/* Register Address */
+#define AR5K_SLEEP0_NEXT_DTIM		0x0007ffff	/* Mask for next DTIM (?) */
+#define AR5K_SLEEP0_NEXT_DTIM_S		0
+#define AR5K_SLEEP0_ASSUME_DTIM		0x00080000	/* Assume DTIM */
+#define AR5K_SLEEP0_ENH_SLEEP_EN	0x00100000	/* Enable enchanced sleep control */
+#define AR5K_SLEEP0_CABTO		0xff000000	/* Mask for CAB Time Out */
+#define AR5K_SLEEP0_CABTO_S		24
+
+/*
+ * Second enhanced sleep register
+ */
+#define AR5K_SLEEP1			0x80d8			/* Register Address */
+#define AR5K_SLEEP1_NEXT_TIM		0x0007ffff	/* Mask for next TIM (?) */
+#define AR5K_SLEEP1_NEXT_TIM_S		0
+#define AR5K_SLEEP1_BEACON_TO		0xff000000	/* Mask for Beacon Time Out */
+#define AR5K_SLEEP1_BEACON_TO_S		24
+
+/*
+ * Third enhanced sleep register
+ */
+#define AR5K_SLEEP2			0x80dc			/* Register Address */
+#define AR5K_SLEEP2_TIM_PER		0x0000ffff	/* Mask for TIM period (?) */
+#define AR5K_SLEEP2_TIM_PER_S		0
+#define AR5K_SLEEP2_DTIM_PER		0xffff0000	/* Mask for DTIM period (?) */
+#define AR5K_SLEEP2_DTIM_PER_S		16
+
+/*
+ * BSSID mask registers
+ */
+#define AR5K_BSS_IDM0			0x80e0	/* Upper bits */
+#define AR5K_BSS_IDM1			0x80e4	/* Lower bits */
+
+/*
+ * TX power control (TPC) register
+ *
+ * XXX: PCDAC steps (0.5dbm) or DBM ?
+ *
+ */
+#define AR5K_TXPC			0x80e8			/* Register Address */
+#define AR5K_TXPC_ACK_M			0x0000003f	/* ACK tx power */
+#define AR5K_TXPC_ACK_S			0
+#define AR5K_TXPC_CTS_M			0x00003f00	/* CTS tx power */
+#define AR5K_TXPC_CTS_S			8
+#define AR5K_TXPC_CHIRP_M		0x003f0000	/* CHIRP tx power */
+#define AR5K_TXPC_CHIRP_S		16
+#define AR5K_TXPC_DOPPLER		0x0f000000	/* Doppler chirp span (?) */
+#define AR5K_TXPC_DOPPLER_S		24
+
+/*
+ * Profile count registers
+ */
+#define AR5K_PROFCNT_TX			0x80ec	/* Tx count */
+#define AR5K_PROFCNT_RX			0x80f0	/* Rx count */
+#define AR5K_PROFCNT_RXCLR		0x80f4	/* Clear Rx count */
+#define AR5K_PROFCNT_CYCLE		0x80f8	/* Cycle count (?) */
+
+/*
+ * Quiet period control registers
+ */
+#define AR5K_QUIET_CTL1			0x80fc			/* Register Address */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF	0x0000ffff	/* Next quiet period TSF (TU) */
+#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S	0
+#define AR5K_QUIET_CTL1_QT_EN		0x00010000	/* Enable quiet period */
+#define AR5K_QUIET_CTL1_ACK_CTS_EN	0x00020000	/* Send ACK/CTS during quiet period */
+
+#define AR5K_QUIET_CTL2			0x8100			/* Register Address */
+#define AR5K_QUIET_CTL2_QT_PER		0x0000ffff	/* Mask for quiet period periodicity */
+#define AR5K_QUIET_CTL2_QT_PER_S	0
+#define AR5K_QUIET_CTL2_QT_DUR		0xffff0000	/* Mask for quiet period duration */
+#define AR5K_QUIET_CTL2_QT_DUR_S	16
+
+/*
+ * TSF parameter register
+ */
+#define AR5K_TSF_PARM			0x8104			/* Register Address */
+#define AR5K_TSF_PARM_INC		0x000000ff	/* Mask for TSF increment */
+#define AR5K_TSF_PARM_INC_S		0
+
+/*
+ * QoS NOACK policy
+ */
+#define AR5K_QOS_NOACK			0x8108			/* Register Address */
+#define AR5K_QOS_NOACK_2BIT_VALUES	0x0000000f	/* ??? */
+#define AR5K_QOS_NOACK_2BIT_VALUES_S	0
+#define AR5K_QOS_NOACK_BIT_OFFSET	0x00000070	/* ??? */
+#define AR5K_QOS_NOACK_BIT_OFFSET_S	4
+#define AR5K_QOS_NOACK_BYTE_OFFSET	0x00000180	/* ??? */
+#define AR5K_QOS_NOACK_BYTE_OFFSET_S	7
+
+/*
+ * PHY error filter register
+ */
+#define AR5K_PHY_ERR_FIL		0x810c
+#define AR5K_PHY_ERR_FIL_RADAR		0x00000020	/* Radar signal */
+#define AR5K_PHY_ERR_FIL_OFDM		0x00020000	/* OFDM false detect (ANI) */
+#define AR5K_PHY_ERR_FIL_CCK		0x02000000	/* CCK false detect (ANI) */
+
+/*
+ * XR latency register
+ */
+#define AR5K_XRLAT_TX		0x8110
+
+/*
+ * ACK SIFS register
+ */
+#define AR5K_ACKSIFS		0x8114			/* Register Address */
+#define AR5K_ACKSIFS_INC	0x00000000	/* ACK SIFS Increment (field) */
+
+/*
+ * MIC QoS control register (?)
+ */
+#define	AR5K_MIC_QOS_CTL		0x8118			/* Register Address */
+#define	AR5K_MIC_QOS_CTL_OFF(_n)	(1 << (_n * 2))
+#define	AR5K_MIC_QOS_CTL_MQ_EN		0x00010000	/* Enable MIC QoS */
+
+/*
+ * MIC QoS select register (?)
+ */
+#define	AR5K_MIC_QOS_SEL		0x811c
+#define	AR5K_MIC_QOS_SEL_OFF(_n)	(1 << (_n * 4))
+
+/*
+ * Misc mode control register (?)
+ */
+#define	AR5K_MISC_MODE			0x8120			/* Register Address */
+#define	AR5K_MISC_MODE_FBSSID_MATCH	0x00000001	/* Force BSSID match */
+#define	AR5K_MISC_MODE_ACKSIFS_MEM	0x00000002	/* ACK SIFS memory (?) */
+#define	AR5K_MISC_MODE_COMBINED_MIC	0x00000004	/* use rx/tx MIC key */
+/* more bits */
+
+/*
+ * OFDM Filter counter
+ */
+#define	AR5K_OFDM_FIL_CNT		0x8124
+
+/*
+ * CCK Filter counter
+ */
+#define	AR5K_CCK_FIL_CNT		0x8128
+
+/*
+ * PHY Error Counters (?)
+ */
+#define	AR5K_PHYERR_CNT1		0x812c
+#define	AR5K_PHYERR_CNT1_MASK		0x8130
+
+#define	AR5K_PHYERR_CNT2		0x8134
+#define	AR5K_PHYERR_CNT2_MASK		0x8138
+
+/*
+ * TSF Threshold register (?)
+ */
+#define	AR5K_TSF_THRES			0x813c
+
+/*
+ * TODO: Wake On Wireless registers
+ * Range: 0x8147 - 0x818c
+ */
+
+/*
+ * Rate -> ACK SIFS mapping table (32 entries)
+ */
+#define	AR5K_RATE_ACKSIFS_BASE		0x8680			/* Register Address */
+#define	AR5K_RATE_ACKSIFS(_n)		(AR5K_RATE_ACKSIFS_BSE + ((_n) << 2))
+#define	AR5K_RATE_ACKSIFS_NORMAL	0x00000001	/* Normal SIFS (field) */
+#define	AR5K_RATE_ACKSIFS_TURBO		0x00000400	/* Turbo SIFS (field) */
+
+/*
+ * Rate -> duration mapping table (32 entries)
+ */
+#define AR5K_RATE_DUR_BASE		0x8700
+#define AR5K_RATE_DUR(_n)		(AR5K_RATE_DUR_BASE + ((_n) << 2))
+
+/*
+ * Rate -> db mapping table
+ * (8 entries, each one has 4 8bit fields)
+ */
+#define AR5K_RATE2DB_BASE		0x87c0
+#define AR5K_RATE2DB(_n)		(AR5K_RATE2DB_BASE + ((_n) << 2))
+
+/*
+ * db -> Rate mapping table
+ * (8 entries, each one has 4 8bit fields)
+ */
+#define AR5K_DB2RATE_BASE		0x87e0
+#define AR5K_DB2RATE(_n)		(AR5K_DB2RATE_BASE + ((_n) << 2))
+
+/*===5212 end===*/
+
+/*
+ * Key table (WEP) register
+ */
+#define AR5K_KEYTABLE_0_5210		0x9000
+#define AR5K_KEYTABLE_0_5211		0x8800
+#define AR5K_KEYTABLE_5210(_n)		(AR5K_KEYTABLE_0_5210 + ((_n) << 5))
+#define AR5K_KEYTABLE_5211(_n)		(AR5K_KEYTABLE_0_5211 + ((_n) << 5))
+#define	AR5K_KEYTABLE(_n)		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
+#define AR5K_KEYTABLE_OFF(_n, x)	(AR5K_KEYTABLE(_n) + (x << 2))
+#define AR5K_KEYTABLE_TYPE(_n)		AR5K_KEYTABLE_OFF(_n, 5)
+#define AR5K_KEYTABLE_TYPE_40		0x00000000
+#define AR5K_KEYTABLE_TYPE_104		0x00000001
+#define AR5K_KEYTABLE_TYPE_128		0x00000003
+#define AR5K_KEYTABLE_TYPE_TKIP		0x00000004	/* [5212+] */
+#define AR5K_KEYTABLE_TYPE_AES		0x00000005	/* [5211+] */
+#define AR5K_KEYTABLE_TYPE_CCM		0x00000006	/* [5212+] */
+#define AR5K_KEYTABLE_TYPE_NULL		0x00000007	/* [5211+] */
+#define AR5K_KEYTABLE_ANTENNA		0x00000008	/* [5212+] */
+#define AR5K_KEYTABLE_MAC0(_n)		AR5K_KEYTABLE_OFF(_n, 6)
+#define AR5K_KEYTABLE_MAC1(_n)		AR5K_KEYTABLE_OFF(_n, 7)
+#define AR5K_KEYTABLE_VALID		0x00008000
+
+/* If key type is TKIP and MIC is enabled
+ * MIC key goes in offset entry + 64 */
+#define	AR5K_KEYTABLE_MIC_OFFSET	64
+
+/* WEP 40-bit	= 40-bit  entered key + 24 bit IV = 64-bit
+ * WEP 104-bit	= 104-bit entered key + 24-bit IV = 128-bit
+ * WEP 128-bit	= 128-bit entered key + 24 bit IV = 152-bit
+ *
+ * Some vendors have introduced bigger WEP keys to address
+ * security vulnerabilities in WEP. This includes:
+ *
+ * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
+ *
+ * We can expand this if we find ar5k Atheros cards with a larger
+ * key table size.
+ */
+#define AR5K_KEYTABLE_SIZE_5210		64
+#define AR5K_KEYTABLE_SIZE_5211		128
+#define	AR5K_KEYTABLE_SIZE		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
+
+
+/*===PHY REGISTERS===*/
+
+/*
+ * PHY registers start
+ */
+#define	AR5K_PHY_BASE			0x9800
+#define	AR5K_PHY(_n)			(AR5K_PHY_BASE + ((_n) << 2))
+
+/*
+ * TST_2 (Misc config parameters)
+ */
+#define	AR5K_PHY_TST2			0x9800			/* Register Address */
+#define AR5K_PHY_TST2_TRIG_SEL		0x00000007	/* Trigger select (?)*/
+#define AR5K_PHY_TST2_TRIG		0x00000010	/* Trigger (?) */
+#define AR5K_PHY_TST2_CBUS_MODE		0x00000060	/* Cardbus mode (?) */
+#define AR5K_PHY_TST2_CLK32		0x00000400	/* CLK_OUT is CLK32 (32Khz external) */
+#define AR5K_PHY_TST2_CHANCOR_DUMP_EN	0x00000800	/* Enable Chancor dump (?) */
+#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP	0x00001000	/* Even Chancor dump (?) */
+#define AR5K_PHY_TST2_RFSILENT_EN	0x00002000	/* Enable RFSILENT */
+#define AR5K_PHY_TST2_ALT_RFDATA	0x00004000	/* Alternate RFDATA (5-2GHz switch ?) */
+#define AR5K_PHY_TST2_MINI_OBS_EN	0x00008000	/* Enable mini OBS (?) */
+#define AR5K_PHY_TST2_RX2_IS_RX5_INV	0x00010000	/* 2GHz rx path is the 5GHz path inverted (?) */
+#define AR5K_PHY_TST2_SLOW_CLK160	0x00020000	/* Slow CLK160 (?) */
+#define AR5K_PHY_TST2_AGC_OBS_SEL_3	0x00040000	/* AGC OBS Select 3 (?) */
+#define AR5K_PHY_TST2_BBB_OBS_SEL	0x00080000	/* BB OBS Select (field ?) */
+#define AR5K_PHY_TST2_ADC_OBS_SEL	0x00800000	/* ADC OBS Select (field ?) */
+#define AR5K_PHY_TST2_RX_CLR_SEL	0x08000000	/* RX Clear Select (?) */
+#define AR5K_PHY_TST2_FORCE_AGC_CLR	0x10000000	/* Force AGC clear (?) */
+#define AR5K_PHY_SHIFT_2GHZ		0x00004007	/* Used to access 2GHz radios */
+#define AR5K_PHY_SHIFT_5GHZ		0x00000007	/* Used to access 5GHz radios (default) */
+
+/*
+ * PHY frame control register [5110] /turbo mode register [5111+]
+ *
+ * There is another frame control register for [5111+]
+ * at address 0x9944 (see below) but the 2 first flags
+ * are common here between 5110 frame control register
+ * and [5111+] turbo mode register, so this also works as
+ * a "turbo mode register" for 5110. We treat this one as
+ * a frame control register for 5110 below.
+ */
+#define	AR5K_PHY_TURBO			0x9804			/* Register Address */
+#define	AR5K_PHY_TURBO_MODE		0x00000001	/* Enable turbo mode */
+#define	AR5K_PHY_TURBO_SHORT		0x00000002	/* Set short symbols to turbo mode */
+#define	AR5K_PHY_TURBO_MIMO		0x00000004	/* Set turbo for mimo mimo */
+
+/*
+ * PHY agility command register
+ * (aka TST_1)
+ */
+#define	AR5K_PHY_AGC			0x9808			/* Register Address */
+#define	AR5K_PHY_TST1			0x9808
+#define	AR5K_PHY_AGC_DISABLE		0x08000000	/* Disable AGC to A2 (?)*/
+#define	AR5K_PHY_TST1_TXHOLD		0x00003800	/* Set tx hold (?) */
+#define	AR5K_PHY_TST1_TXSRC_SRC		0x00000002	/* Used with bit 7 (?) */
+#define	AR5K_PHY_TST1_TXSRC_SRC_S	1
+#define	AR5K_PHY_TST1_TXSRC_ALT		0x00000080	/* Set input to tsdac (?) */
+#define	AR5K_PHY_TST1_TXSRC_ALT_S	7
+
+
+/*
+ * PHY timing register 3 [5112+]
+ */
+#define	AR5K_PHY_TIMING_3		0x9814
+#define	AR5K_PHY_TIMING_3_DSC_MAN	0xfffe0000
+#define	AR5K_PHY_TIMING_3_DSC_MAN_S	17
+#define	AR5K_PHY_TIMING_3_DSC_EXP	0x0001e000
+#define	AR5K_PHY_TIMING_3_DSC_EXP_S	13
+
+/*
+ * PHY chip revision register
+ */
+#define	AR5K_PHY_CHIP_ID		0x9818
+
+/*
+ * PHY activation register
+ */
+#define	AR5K_PHY_ACT			0x981c			/* Register Address */
+#define	AR5K_PHY_ACT_ENABLE		0x00000001	/* Activate PHY */
+#define	AR5K_PHY_ACT_DISABLE		0x00000002	/* Deactivate PHY */
+
+/*
+ * PHY RF control registers
+ */
+#define AR5K_PHY_RF_CTL2		0x9824			/* Register Address */
+#define	AR5K_PHY_RF_CTL2_TXF2TXD_START	0x0000000f	/* TX frame to TX data start */
+#define	AR5K_PHY_RF_CTL2_TXF2TXD_START_S	0
+
+#define AR5K_PHY_RF_CTL3		0x9828			/* Register Address */
+#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON	0x0000ff00	/* TX end to XLNA on */
+#define	AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S	8
+
+#define	AR5K_PHY_ADC_CTL			0x982c
+#define	AR5K_PHY_ADC_CTL_INBUFGAIN_OFF		0x00000003
+#define	AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S	0
+#define	AR5K_PHY_ADC_CTL_PWD_DAC_OFF		0x00002000
+#define	AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF	0x00004000
+#define	AR5K_PHY_ADC_CTL_PWD_ADC_OFF		0x00008000
+#define	AR5K_PHY_ADC_CTL_INBUFGAIN_ON		0x00030000
+#define	AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S		16
+
+#define AR5K_PHY_RF_CTL4		0x9834			/* Register Address */
+#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON	0x00000001	/* TX frame to XPA A on (field) */
+#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON	0x00000100	/* TX frame to XPA B on (field) */
+#define	AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF	0x00010000	/* TX end to XPA A off (field) */
+#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF	0x01000000	/* TX end to XPA B off (field) */
+
+/*
+ * Pre-Amplifier control register
+ * (XPA -> external pre-amplifier)
+ */
+#define	AR5K_PHY_PA_CTL			0x9838			/* Register Address */
+#define	AR5K_PHY_PA_CTL_XPA_A_HI	0x00000001	/* XPA A high (?) */
+#define	AR5K_PHY_PA_CTL_XPA_B_HI	0x00000002	/* XPA B high (?) */
+#define	AR5K_PHY_PA_CTL_XPA_A_EN	0x00000004	/* Enable XPA A */
+#define	AR5K_PHY_PA_CTL_XPA_B_EN	0x00000008	/* Enable XPA B */
+
+/*
+ * PHY settling register
+ */
+#define AR5K_PHY_SETTLING		0x9844			/* Register Address */
+#define	AR5K_PHY_SETTLING_AGC		0x0000007f	/* AGC settling time */
+#define	AR5K_PHY_SETTLING_AGC_S		0
+#define	AR5K_PHY_SETTLING_SWITCH	0x00003f80	/* Switch settlig time */
+#define	AR5K_PHY_SETTLING_SWITCH_S	7
+
+/*
+ * PHY Gain registers
+ */
+#define AR5K_PHY_GAIN			0x9848			/* Register Address */
+#define	AR5K_PHY_GAIN_TXRX_ATTEN	0x0003f000	/* TX-RX Attenuation */
+#define	AR5K_PHY_GAIN_TXRX_ATTEN_S	12
+#define	AR5K_PHY_GAIN_TXRX_RF_MAX	0x007c0000
+#define	AR5K_PHY_GAIN_TXRX_RF_MAX_S	18
+
+#define	AR5K_PHY_GAIN_OFFSET		0x984c			/* Register Address */
+#define	AR5K_PHY_GAIN_OFFSET_RXTX_FLAG	0x00020000	/* RX-TX flag (?) */
+
+/*
+ * Desired ADC/PGA size register
+ * (for more infos read ANI patent)
+ */
+#define AR5K_PHY_DESIRED_SIZE		0x9850			/* Register Address */
+#define	AR5K_PHY_DESIRED_SIZE_ADC	0x000000ff	/* ADC desired size */
+#define	AR5K_PHY_DESIRED_SIZE_ADC_S	0
+#define	AR5K_PHY_DESIRED_SIZE_PGA	0x0000ff00	/* PGA desired size */
+#define	AR5K_PHY_DESIRED_SIZE_PGA_S	8
+#define	AR5K_PHY_DESIRED_SIZE_TOT	0x0ff00000	/* Total desired size */
+#define	AR5K_PHY_DESIRED_SIZE_TOT_S	20
+
+/*
+ * PHY signal register
+ * (for more infos read ANI patent)
+ */
+#define	AR5K_PHY_SIG			0x9858			/* Register Address */
+#define	AR5K_PHY_SIG_FIRSTEP		0x0003f000	/* FIRSTEP */
+#define	AR5K_PHY_SIG_FIRSTEP_S		12
+#define	AR5K_PHY_SIG_FIRPWR		0x03fc0000	/* FIPWR */
+#define	AR5K_PHY_SIG_FIRPWR_S		18
+
+/*
+ * PHY coarse agility control register
+ * (for more infos read ANI patent)
+ */
+#define	AR5K_PHY_AGCCOARSE		0x985c			/* Register Address */
+#define	AR5K_PHY_AGCCOARSE_LO		0x00007f80	/* AGC Coarse low */
+#define	AR5K_PHY_AGCCOARSE_LO_S		7
+#define	AR5K_PHY_AGCCOARSE_HI		0x003f8000	/* AGC Coarse high */
+#define	AR5K_PHY_AGCCOARSE_HI_S		15
+
+/*
+ * PHY agility control register
+ */
+#define	AR5K_PHY_AGCCTL			0x9860			/* Register address */
+#define	AR5K_PHY_AGCCTL_CAL		0x00000001	/* Enable PHY calibration */
+#define	AR5K_PHY_AGCCTL_NF		0x00000002	/* Enable Noise Floor calibration */
+#define	AR5K_PHY_AGCCTL_OFDM_DIV_DIS	0x00000008	/* Disable antenna diversity on OFDM modes */
+#define	AR5K_PHY_AGCCTL_NF_EN		0x00008000	/* Enable nf calibration to happen (?) */
+#define	AR5K_PHY_AGCTL_FLTR_CAL		0x00010000	/* Allow filter calibration (?) */
+#define	AR5K_PHY_AGCCTL_NF_NOUPDATE	0x00020000	/* Don't update nf automaticaly */
+
+/*
+ * PHY noise floor status register
+ */
+#define AR5K_PHY_NF			0x9864			/* Register address */
+#define AR5K_PHY_NF_M			0x000001ff	/* Noise floor mask */
+#define AR5K_PHY_NF_ACTIVE		0x00000100	/* Noise floor calibration still active */
+#define AR5K_PHY_NF_RVAL(_n)		(((_n) >> 19) & AR5K_PHY_NF_M)
+#define AR5K_PHY_NF_AVAL(_n)		(-((_n) ^ AR5K_PHY_NF_M) + 1)
+#define AR5K_PHY_NF_SVAL(_n)		(((_n) & AR5K_PHY_NF_M) | (1 << 9))
+#define	AR5K_PHY_NF_THRESH62		0x0007f000	/* Thresh62 -check ANI patent- (field) */
+#define	AR5K_PHY_NF_THRESH62_S		12
+#define	AR5K_PHY_NF_MINCCA_PWR		0x0ff80000	/* ??? */
+#define	AR5K_PHY_NF_MINCCA_PWR_S	19
+
+/*
+ * PHY ADC saturation register [5110]
+ */
+#define	AR5K_PHY_ADCSAT			0x9868
+#define	AR5K_PHY_ADCSAT_ICNT		0x0001f800
+#define	AR5K_PHY_ADCSAT_ICNT_S		11
+#define	AR5K_PHY_ADCSAT_THR		0x000007e0
+#define	AR5K_PHY_ADCSAT_THR_S		5
+
+/*
+ * PHY Weak ofdm signal detection threshold registers (ANI) [5212+]
+ */
+
+/* High thresholds */
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR		0x9868
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT	0x0000001f
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S	0
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1		0x00fe0000
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S	17
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2		0x7f000000
+#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S	24
+
+/* Low thresholds */
+#define AR5K_PHY_WEAK_OFDM_LOW_THR 		0x986c
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN	0x00000001
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT	0x00003f00
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S	8
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1		0x001fc000
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S		14
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2		0x0fe00000
+#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S		21
+
+
+/*
+ * PHY sleep registers [5112+]
+ */
+#define AR5K_PHY_SCR			0x9870
+
+#define AR5K_PHY_SLMT			0x9874
+#define AR5K_PHY_SLMT_32MHZ		0x0000007f
+
+#define AR5K_PHY_SCAL			0x9878
+#define AR5K_PHY_SCAL_32MHZ		0x0000000e
+#define	AR5K_PHY_SCAL_32MHZ_2417	0x0000000a
+#define	AR5K_PHY_SCAL_32MHZ_HB63	0x00000032
+
+/*
+ * PHY PLL (Phase Locked Loop) control register
+ */
+#define	AR5K_PHY_PLL			0x987c
+#define	AR5K_PHY_PLL_20MHZ		0x00000013	/* For half rate (?) */
+/* 40MHz -> 5GHz band */
+#define	AR5K_PHY_PLL_40MHZ_5211		0x00000018
+#define	AR5K_PHY_PLL_40MHZ_5212		0x000000aa
+#define	AR5K_PHY_PLL_40MHZ_5413		0x00000004
+#define	AR5K_PHY_PLL_40MHZ		(ah->ah_version == AR5K_AR5211 ? \
+					AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
+/* 44MHz -> 2.4GHz band */
+#define	AR5K_PHY_PLL_44MHZ_5211		0x00000019
+#define	AR5K_PHY_PLL_44MHZ_5212		0x000000ab
+#define	AR5K_PHY_PLL_44MHZ		(ah->ah_version == AR5K_AR5211 ? \
+					AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
+
+#define AR5K_PHY_PLL_RF5111		0x00000000
+#define AR5K_PHY_PLL_RF5112		0x00000040
+#define	AR5K_PHY_PLL_HALF_RATE		0x00000100
+#define	AR5K_PHY_PLL_QUARTER_RATE	0x00000200
+
+/*
+ * RF Buffer register
+ *
+ * It's obvious from the code that 0x989c is the buffer register but
+ * for the other special registers that we write to after sending each
+ * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
+ * for now. It's interesting that they are also used for some other operations.
+ */
+
+#define AR5K_RF_BUFFER			0x989c
+#define AR5K_RF_BUFFER_CONTROL_0	0x98c0	/* Channel on 5110 */
+#define AR5K_RF_BUFFER_CONTROL_1	0x98c4	/* Bank 7 on 5112 */
+#define AR5K_RF_BUFFER_CONTROL_2	0x98cc	/* Bank 7 on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_3	0x98d0	/* Bank 2 on 5112 */
+						/* Channel set on 5111 */
+						/* Used to read radio revision*/
+
+#define AR5K_RF_BUFFER_CONTROL_4	0x98d4  /* RF Stage register on 5110 */
+						/* Bank 0,1,2,6 on 5111 */
+						/* Bank 1 on 5112 */
+						/* Used during activation on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_5	0x98d8	/* Bank 3 on 5111 */
+						/* Used during activation on 5111 */
+						/* Channel on 5112 */
+						/* Bank 6 on 5112 */
+
+#define AR5K_RF_BUFFER_CONTROL_6	0x98dc	/* Bank 3 on 5112 */
+
+/*
+ * PHY RF stage register [5210]
+ */
+#define AR5K_PHY_RFSTG			0x98d4
+#define AR5K_PHY_RFSTG_DISABLE		0x00000021
+
+/*
+ * BIN masks (?)
+ */
+#define	AR5K_PHY_BIN_MASK_1	0x9900
+#define	AR5K_PHY_BIN_MASK_2	0x9904
+#define	AR5K_PHY_BIN_MASK_3	0x9908
+
+#define	AR5K_PHY_BIN_MASK_CTL		0x990c
+#define	AR5K_PHY_BIN_MASK_CTL_MASK_4	0x00003fff
+#define	AR5K_PHY_BIN_MASK_CTL_MASK_4_S	0
+#define	AR5K_PHY_BIN_MASK_CTL_RATE	0xff000000
+#define	AR5K_PHY_BIN_MASK_CTL_RATE_S	24
+
+/*
+ * PHY Antenna control register
+ */
+#define AR5K_PHY_ANT_CTL		0x9910			/* Register Address */
+#define	AR5K_PHY_ANT_CTL_TXRX_EN	0x00000001	/* Enable TX/RX (?) */
+#define	AR5K_PHY_ANT_CTL_SECTORED_ANT	0x00000004	/* Sectored Antenna */
+#define	AR5K_PHY_ANT_CTL_HITUNE5	0x00000008	/* Hitune5 (?) */
+#define	AR5K_PHY_ANT_CTL_SWTABLE_IDLE	0x000003f0	/* Switch table idle (?) */
+#define	AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S	4
+
+/*
+ * PHY receiver delay register [5111+]
+ */
+#define	AR5K_PHY_RX_DELAY		0x9914			/* Register Address */
+#define	AR5K_PHY_RX_DELAY_M		0x00003fff	/* Mask for RX activate to receive delay (/100ns) */
+
+/*
+ * PHY max rx length register (?) [5111]
+ */
+#define	AR5K_PHY_MAX_RX_LEN		0x991c
+
+/*
+ * PHY timing register 4
+ * I(nphase)/Q(adrature) calibration register [5111+]
+ */
+#define	AR5K_PHY_IQ			0x9920			/* Register Address */
+#define	AR5K_PHY_IQ_CORR_Q_Q_COFF	0x0000001f	/* Mask for q correction info */
+#define	AR5K_PHY_IQ_CORR_Q_I_COFF	0x000007e0	/* Mask for i correction info */
+#define	AR5K_PHY_IQ_CORR_Q_I_COFF_S	5
+#define	AR5K_PHY_IQ_CORR_ENABLE		0x00000800	/* Enable i/q correction */
+#define	AR5K_PHY_IQ_CAL_NUM_LOG_MAX	0x0000f000	/* Mask for max number of samples in log scale */
+#define	AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S	12
+#define	AR5K_PHY_IQ_RUN			0x00010000	/* Run i/q calibration */
+#define	AR5K_PHY_IQ_USE_PT_DF		0x00020000	/* Use pilot track df (?) */
+#define	AR5K_PHY_IQ_EARLY_TRIG_THR	0x00200000	/* Early trigger threshold (?) (field) */
+#define	AR5K_PHY_IQ_PILOT_MASK_EN	0x10000000	/* Enable pilot mask (?) */
+#define	AR5K_PHY_IQ_CHAN_MASK_EN	0x20000000	/* Enable channel mask (?) */
+#define	AR5K_PHY_IQ_SPUR_FILT_EN	0x40000000	/* Enable spur filter */
+#define	AR5K_PHY_IQ_SPUR_RSSI_EN	0x80000000	/* Enable spur rssi */
+
+/*
+ * PHY timing register 5
+ * OFDM Self-correlator Cyclic RSSI threshold params
+ * (Check out bb_cycpwr_thr1 on ANI patent)
+ */
+#define	AR5K_PHY_OFDM_SELFCORR			0x9924			/* Register Address */
+#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN	0x00000001	/* Enable cyclic RSSI thr 1 */
+#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1	0x000000fe	/* Mask for Cyclic RSSI threshold 1 */
+#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S	1
+#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3	0x00000100	/* Cyclic RSSI threshold 3 (field) (?) */
+#define	AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN	0x00008000	/* Enable 1A RSSI threshold (?) */
+#define	AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR	0x00010000	/* 1A RSSI threshold (field) (?) */
+#define	AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI	0x00800000	/* Long sc threshold hi rssi (?) */
+
+/*
+ * PHY-only warm reset register
+ */
+#define	AR5K_PHY_WARM_RESET		0x9928
+
+/*
+ * PHY-only control register
+ */
+#define AR5K_PHY_CTL			0x992c			/* Register Address */
+#define	AR5K_PHY_CTL_RX_DRAIN_RATE	0x00000001	/* RX drain rate (?) */
+#define	AR5K_PHY_CTL_LATE_TX_SIG_SYM	0x00000002	/* Late tx signal symbol (?) */
+#define	AR5K_PHY_CTL_GEN_SCRAMBLER	0x00000004	/* Generate scrambler */
+#define	AR5K_PHY_CTL_TX_ANT_SEL		0x00000008	/* TX antenna select */
+#define	AR5K_PHY_CTL_TX_ANT_STATIC	0x00000010	/* Static TX antenna */
+#define	AR5K_PHY_CTL_RX_ANT_SEL		0x00000020	/* RX antenna select */
+#define	AR5K_PHY_CTL_RX_ANT_STATIC	0x00000040	/* Static RX antenna */
+#define	AR5K_PHY_CTL_LOW_FREQ_SLE_EN	0x00000080	/* Enable low freq sleep */
+
+/*
+ * PHY PAPD probe register [5111+]
+ */
+#define	AR5K_PHY_PAPD_PROBE		0x9930
+#define	AR5K_PHY_PAPD_PROBE_SH_HI_PAR	0x00000001
+#define	AR5K_PHY_PAPD_PROBE_PCDAC_BIAS	0x00000002
+#define	AR5K_PHY_PAPD_PROBE_COMP_GAIN	0x00000040
+#define	AR5K_PHY_PAPD_PROBE_TXPOWER	0x00007e00
+#define	AR5K_PHY_PAPD_PROBE_TXPOWER_S	9
+#define	AR5K_PHY_PAPD_PROBE_TX_NEXT	0x00008000
+#define	AR5K_PHY_PAPD_PROBE_PREDIST_EN	0x00010000
+#define	AR5K_PHY_PAPD_PROBE_TYPE	0x01800000	/* [5112+] */
+#define	AR5K_PHY_PAPD_PROBE_TYPE_S	23
+#define	AR5K_PHY_PAPD_PROBE_TYPE_OFDM	0
+#define	AR5K_PHY_PAPD_PROBE_TYPE_XR	1
+#define	AR5K_PHY_PAPD_PROBE_TYPE_CCK	2
+#define	AR5K_PHY_PAPD_PROBE_GAINF	0xfe000000
+#define	AR5K_PHY_PAPD_PROBE_GAINF_S	25
+#define	AR5K_PHY_PAPD_PROBE_INI_5111	0x00004883	/* [5212+] */
+#define	AR5K_PHY_PAPD_PROBE_INI_5112	0x00004882	/* [5212+] */
+
+/*
+ * PHY TX rate power registers [5112+]
+ */
+#define	AR5K_PHY_TXPOWER_RATE1			0x9934
+#define	AR5K_PHY_TXPOWER_RATE2			0x9938
+#define	AR5K_PHY_TXPOWER_RATE_MAX		0x993c
+#define	AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE	0x00000040
+#define	AR5K_PHY_TXPOWER_RATE3			0xa234
+#define	AR5K_PHY_TXPOWER_RATE4			0xa238
+
+/*
+ * PHY frame control register [5111+]
+ */
+#define	AR5K_PHY_FRAME_CTL_5210		0x9804
+#define	AR5K_PHY_FRAME_CTL_5211		0x9944
+#define	AR5K_PHY_FRAME_CTL		(ah->ah_version == AR5K_AR5210 ? \
+					AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
+/*---[5111+]---*/
+#define	AR5K_PHY_FRAME_CTL_TX_CLIP	0x00000038	/* Mask for tx clip (?) */
+#define	AR5K_PHY_FRAME_CTL_TX_CLIP_S	3
+#define	AR5K_PHY_FRAME_CTL_PREP_CHINFO	0x00010000	/* Prepend chan info */
+#define	AR5K_PHY_FRAME_CTL_EMU		0x80000000
+#define	AR5K_PHY_FRAME_CTL_EMU_S	31
+/*---[5110/5111]---*/
+#define	AR5K_PHY_FRAME_CTL_TIMING_ERR	0x01000000	/* PHY timing error */
+#define	AR5K_PHY_FRAME_CTL_PARITY_ERR	0x02000000	/* Parity error */
+#define	AR5K_PHY_FRAME_CTL_ILLRATE_ERR	0x04000000	/* Illegal rate */
+#define	AR5K_PHY_FRAME_CTL_ILLLEN_ERR	0x08000000	/* Illegal length */
+#define	AR5K_PHY_FRAME_CTL_SERVICE_ERR	0x20000000
+#define	AR5K_PHY_FRAME_CTL_TXURN_ERR	0x40000000	/* TX underrun */
+#define AR5K_PHY_FRAME_CTL_INI		AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
+			AR5K_PHY_FRAME_CTL_TXURN_ERR | \
+			AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
+			AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
+			AR5K_PHY_FRAME_CTL_PARITY_ERR | \
+			AR5K_PHY_FRAME_CTL_TIMING_ERR
+
+/*
+ * PHY Tx Power adjustment register [5212A+]
+ */
+#define	AR5K_PHY_TX_PWR_ADJ			0x994c
+#define	AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA	0x00000fc0
+#define	AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S	6
+#define	AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX	0x00fc0000
+#define	AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S	18
+
+/*
+ * PHY radar detection register [5111+]
+ */
+#define	AR5K_PHY_RADAR			0x9954
+#define	AR5K_PHY_RADAR_ENABLE		0x00000001
+#define	AR5K_PHY_RADAR_DISABLE		0x00000000
+#define AR5K_PHY_RADAR_INBANDTHR    	0x0000003e	/* Inband threshold
+							5-bits, units unknown {0..31}
+							(? MHz ?) */
+#define AR5K_PHY_RADAR_INBANDTHR_S	1
+
+#define AR5K_PHY_RADAR_PRSSI_THR    	0x00000fc0	/* Pulse RSSI/SNR threshold
+							6-bits, dBm range {0..63}
+							in dBm units. */
+#define AR5K_PHY_RADAR_PRSSI_THR_S	6
+
+#define AR5K_PHY_RADAR_PHEIGHT_THR   	0x0003f000	/* Pulse height threshold
+							6-bits, dBm range {0..63}
+							in dBm units. */
+#define AR5K_PHY_RADAR_PHEIGHT_THR_S	12
+
+#define AR5K_PHY_RADAR_RSSI_THR    	0x00fc0000	/* Radar RSSI/SNR threshold.
+							6-bits, dBm range {0..63}
+							in dBm units. */
+#define AR5K_PHY_RADAR_RSSI_THR_S	18
+
+#define AR5K_PHY_RADAR_FIRPWR_THR	0x7f000000	/* Finite Impulse Response
+							filter power out threshold.
+							7-bits, standard power range
+							{0..127} in 1/2 dBm units. */
+#define AR5K_PHY_RADAR_FIRPWR_THRS	24
+
+/*
+ * PHY antenna switch table registers
+ */
+#define AR5K_PHY_ANT_SWITCH_TABLE_0	0x9960
+#define AR5K_PHY_ANT_SWITCH_TABLE_1	0x9964
+
+/*
+ * PHY Noise floor threshold
+ */
+#define AR5K_PHY_NFTHRES		0x9968
+
+/*
+ * Sigma Delta register (?) [5213]
+ */
+#define AR5K_PHY_SIGMA_DELTA		0x996C
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL	0x00000003
+#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S	0
+#define AR5K_PHY_SIGMA_DELTA_FILT2	0x000000f8
+#define AR5K_PHY_SIGMA_DELTA_FILT2_S	3
+#define AR5K_PHY_SIGMA_DELTA_FILT1	0x00001f00
+#define AR5K_PHY_SIGMA_DELTA_FILT1_S	8
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP	0x01ffe000
+#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S	13
+
+/*
+ * RF restart register [5112+] (?)
+ */
+#define AR5K_PHY_RESTART		0x9970		/* restart */
+#define AR5K_PHY_RESTART_DIV_GC		0x001c0000	/* Fast diversity gc_limit (?) */
+#define AR5K_PHY_RESTART_DIV_GC_S	18
+
+/*
+ * RF Bus access request register (for synth-oly channel switching)
+ */
+#define AR5K_PHY_RFBUS_REQ		0x997C
+#define AR5K_PHY_RFBUS_REQ_REQUEST	0x00000001
+
+/*
+ * Spur mitigation masks (?)
+ */
+#define AR5K_PHY_TIMING_7		0x9980
+#define AR5K_PHY_TIMING_8		0x9984
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2		0x000fffff
+#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S	0
+
+#define AR5K_PHY_BIN_MASK2_1		0x9988
+#define AR5K_PHY_BIN_MASK2_2		0x998c
+#define AR5K_PHY_BIN_MASK2_3		0x9990
+
+#define AR5K_PHY_BIN_MASK2_4		0x9994
+#define AR5K_PHY_BIN_MASK2_4_MASK_4	0x00003fff
+#define AR5K_PHY_BIN_MASK2_4_MASK_4_S	0
+
+#define AR5K_PHY_TIMING_9			0x9998
+#define AR5K_PHY_TIMING_10			0x999c
+#define AR5K_PHY_TIMING_10_PILOT_MASK_2		0x000fffff
+#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S	0
+
+/*
+ * Spur mitigation control
+ */
+#define AR5K_PHY_TIMING_11			0x99a0		/* Register address */
+#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE	0x000fffff	/* Spur delta phase */
+#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S	0
+#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD		0x3ff00000	/* Freq sigma delta */
+#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S	20
+#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC	0x40000000	/* Spur filter in AGC detector */
+#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR	0x80000000	/* Spur filter in OFDM self correlator */
+
+/*
+ * Gain tables
+ */
+#define	AR5K_BB_GAIN_BASE		0x9b00	/* BaseBand Amplifier Gain table base address */
+#define AR5K_BB_GAIN(_n)		(AR5K_BB_GAIN_BASE + ((_n) << 2))
+#define	AR5K_RF_GAIN_BASE		0x9a00	/* RF Amplrifier Gain table base address */
+#define AR5K_RF_GAIN(_n)		(AR5K_RF_GAIN_BASE + ((_n) << 2))
+
+/*
+ * PHY timing IQ calibration result register [5111+]
+ */
+#define	AR5K_PHY_IQRES_CAL_PWR_I	0x9c10	/* I (Inphase) power value */
+#define	AR5K_PHY_IQRES_CAL_PWR_Q	0x9c14	/* Q (Quadrature) power value */
+#define	AR5K_PHY_IQRES_CAL_CORR		0x9c18	/* I/Q Correlation */
+
+/*
+ * PHY current RSSI register [5111+]
+ */
+#define	AR5K_PHY_CURRENT_RSSI	0x9c1c
+
+/*
+ * PHY RF Bus grant register
+ */
+#define	AR5K_PHY_RFBUS_GRANT	0x9c20
+#define	AR5K_PHY_RFBUS_GRANT_OK	0x00000001
+
+/*
+ * PHY ADC test register
+ */
+#define	AR5K_PHY_ADC_TEST	0x9c24
+#define	AR5K_PHY_ADC_TEST_I	0x00000001
+#define	AR5K_PHY_ADC_TEST_Q	0x00000200
+
+/*
+ * PHY DAC test register
+ */
+#define	AR5K_PHY_DAC_TEST	0x9c28
+#define	AR5K_PHY_DAC_TEST_I	0x00000001
+#define	AR5K_PHY_DAC_TEST_Q	0x00000200
+
+/*
+ * PHY PTAT register (?)
+ */
+#define	AR5K_PHY_PTAT		0x9c2c
+
+/*
+ * PHY Illegal TX rate register [5112+]
+ */
+#define	AR5K_PHY_BAD_TX_RATE	0x9c30
+
+/*
+ * PHY SPUR Power register [5112+]
+ */
+#define	AR5K_PHY_SPUR_PWR	0x9c34			/* Register Address */
+#define	AR5K_PHY_SPUR_PWR_I	0x00000001	/* SPUR Power estimate for I (field) */
+#define	AR5K_PHY_SPUR_PWR_Q	0x00000100	/* SPUR Power estimate for Q (field) */
+#define	AR5K_PHY_SPUR_PWR_FILT	0x00010000	/* Power with SPUR removed (field) */
+
+/*
+ * PHY Channel status register [5112+] (?)
+ */
+#define	AR5K_PHY_CHAN_STATUS		0x9c38
+#define	AR5K_PHY_CHAN_STATUS_BT_ACT	0x00000001
+#define	AR5K_PHY_CHAN_STATUS_RX_CLR_RAW	0x00000002
+#define	AR5K_PHY_CHAN_STATUS_RX_CLR_MAC	0x00000004
+#define	AR5K_PHY_CHAN_STATUS_RX_CLR_PAP	0x00000008
+
+/*
+ * Heavy clip enable register
+ */
+#define	AR5K_PHY_HEAVY_CLIP_ENABLE	0x99e0
+
+/*
+ * PHY clock sleep registers [5112+]
+ */
+#define AR5K_PHY_SCLOCK			0x99f0
+#define AR5K_PHY_SCLOCK_32MHZ		0x0000000c
+#define AR5K_PHY_SDELAY			0x99f4
+#define AR5K_PHY_SDELAY_32MHZ		0x000000ff
+#define AR5K_PHY_SPENDING		0x99f8
+
+
+/*
+ * PHY PAPD I (power?) table (?)
+ * (92! entries)
+ */
+#define	AR5K_PHY_PAPD_I_BASE	0xa000
+#define	AR5K_PHY_PAPD_I(_n)	(AR5K_PHY_PAPD_I_BASE + ((_n) << 2))
+
+/*
+ * PHY PCDAC TX power table
+ */
+#define	AR5K_PHY_PCDAC_TXPOWER_BASE	0xa180
+#define	AR5K_PHY_PCDAC_TXPOWER(_n)	(AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2))
+
+/*
+ * PHY mode register [5111+]
+ */
+#define	AR5K_PHY_MODE			0x0a200			/* Register Address */
+#define	AR5K_PHY_MODE_MOD		0x00000001	/* PHY Modulation bit */
+#define AR5K_PHY_MODE_MOD_OFDM		0
+#define AR5K_PHY_MODE_MOD_CCK		1
+#define AR5K_PHY_MODE_FREQ		0x00000002	/* Freq mode bit */
+#define	AR5K_PHY_MODE_FREQ_5GHZ		0
+#define	AR5K_PHY_MODE_FREQ_2GHZ		2
+#define AR5K_PHY_MODE_MOD_DYN		0x00000004	/* Enable Dynamic OFDM/CCK mode [5112+] */
+#define AR5K_PHY_MODE_RAD		0x00000008	/* [5212+] */
+#define AR5K_PHY_MODE_RAD_RF5111	0
+#define AR5K_PHY_MODE_RAD_RF5112	8
+#define AR5K_PHY_MODE_XR		0x00000010	/* Enable XR mode [5112+] */
+#define	AR5K_PHY_MODE_HALF_RATE		0x00000020	/* Enable Half rate (test) */
+#define	AR5K_PHY_MODE_QUARTER_RATE	0x00000040	/* Enable Quarter rat (test) */
+
+/*
+ * PHY CCK transmit control register [5111+ (?)]
+ */
+#define AR5K_PHY_CCKTXCTL		0xa204
+#define AR5K_PHY_CCKTXCTL_WORLD		0x00000000
+#define AR5K_PHY_CCKTXCTL_JAPAN		0x00000010
+#define	AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS	0x00000001
+#define	AR5K_PHY_CCKTXCTK_DAC_SCALE	0x00000004
+
+/*
+ * PHY CCK Cross-correlator Barker RSSI threshold register [5212+]
+ */
+#define AR5K_PHY_CCK_CROSSCORR			0xa208
+#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR	0x0000003f
+#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S	0
+
+/* Same address is used for antenna diversity activation */
+#define	AR5K_PHY_FAST_ANT_DIV		0xa208
+#define	AR5K_PHY_FAST_ANT_DIV_EN	0x00002000
+
+/*
+ * PHY 2GHz gain register [5111+]
+ */
+#define	AR5K_PHY_GAIN_2GHZ			0xa20c
+#define	AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX		0x00fc0000
+#define	AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S	18
+#define	AR5K_PHY_GAIN_2GHZ_INI_5111		0x6480416c
+
+#define	AR5K_PHY_CCK_RX_CTL_4			0xa21c
+#define	AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT	0x01f80000
+#define	AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S	19
+
+#define	AR5K_PHY_DAG_CCK_CTL			0xa228
+#define	AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR	0x00000200
+#define	AR5K_PHY_DAG_CCK_CTL_RSSI_THR		0x0001fc00
+#define	AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S		10
+
+#define	AR5K_PHY_FAST_ADC	0xa24c
+
+#define	AR5K_PHY_BLUETOOTH	0xa254
+
+/*
+ * Transmit Power Control register
+ * [2413+]
+ */
+#define	AR5K_PHY_TPC_RG1		0xa258
+#define	AR5K_PHY_TPC_RG1_NUM_PD_GAIN	0x0000c000
+#define	AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S	14
+#define AR5K_PHY_TPC_RG1_PDGAIN_1	0x00030000
+#define AR5K_PHY_TPC_RG1_PDGAIN_1_S	16
+#define AR5K_PHY_TPC_RG1_PDGAIN_2	0x000c0000
+#define AR5K_PHY_TPC_RG1_PDGAIN_2_S	18
+#define AR5K_PHY_TPC_RG1_PDGAIN_3	0x00300000
+#define AR5K_PHY_TPC_RG1_PDGAIN_3_S	20
+
+#define	AR5K_PHY_TPC_RG5			0xa26C
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP	0x0000000F
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S	0
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1	0x000003F0
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S	4
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2	0x0000FC00
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S	10
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3	0x003F0000
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S	16
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4	0x0FC00000
+#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S	22
+
+/*
+ * PHY PDADC Tx power table
+ */
+#define AR5K_PHY_PDADC_TXPOWER_BASE	0xa280
+#define	AR5K_PHY_PDADC_TXPOWER(_n)	(AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2))
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/reset.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/reset.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/reset.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/reset.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1323 @@
+/*
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#define _ATH5K_RESET
+
+/*****************************\
+  Reset functions and helpers
+\*****************************/
+
+#include <linux/pci.h> 		/* To determine if a card is pci-e */
+#include <linux/log2.h>
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+#include "debug.h"
+
+/**
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ *
+ * @ah: the &struct ath5k_hw
+ * @channel: the currently set channel upon reset
+ *
+ * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
+ * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
+ *
+ * Since delta slope is floating point we split it on its exponent and
+ * mantissa and provide these values on hw.
+ *
+ * For more infos i think this patent is related
+ * http://www.freepatentsonline.com/7184495.html
+ */
+static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+	struct ieee80211_channel *channel)
+{
+	/* Get exponent and mantissa and set it */
+	u32 coef_scaled, coef_exp, coef_man,
+		ds_coef_exp, ds_coef_man, clock;
+
+	BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
+		!(channel->hw_value & CHANNEL_OFDM));
+
+	/* Get coefficient
+	 * ALGO: coef = (5 * clock * carrier_freq) / 2)
+	 * we scale coef by shifting clock value by 24 for
+	 * better precision since we use integers */
+	/* TODO: Half/quarter rate */
+	clock =  ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
+
+	coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
+
+	/* Get exponent
+	 * ALGO: coef_exp = 14 - highest set bit position */
+	coef_exp = ilog2(coef_scaled);
+
+	/* Doesn't make sense if it's zero*/
+	if (!coef_scaled || !coef_exp)
+		return -EINVAL;
+
+	/* Note: we've shifted coef_scaled by 24 */
+	coef_exp = 14 - (coef_exp - 24);
+
+
+	/* Get mantissa (significant digits)
+	 * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
+	coef_man = coef_scaled +
+		(1 << (24 - coef_exp - 1));
+
+	/* Calculate delta slope coefficient exponent
+	 * and mantissa (remove scaling) and set them on hw */
+	ds_coef_man = coef_man >> (24 - coef_exp);
+	ds_coef_exp = coef_exp - 16;
+
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+		AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+		AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+
+	return 0;
+}
+
+
+/*
+ * index into rates for control rates, we can set it up like this because
+ * this is only used for AR5212 and we know it supports G mode
+ */
+static const unsigned int control_rates[] =
+	{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
+
+/**
+ * ath5k_hw_write_rate_duration - fill rate code to duration table
+ *
+ * @ah: the &struct ath5k_hw
+ * @mode: one of enum ath5k_driver_mode
+ *
+ * Write the rate code to duration table upon hw reset. This is a helper for
+ * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
+ * the hardware, based on current mode, for each rate. The rates which are
+ * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
+ * different rate code so we write their value twice (one for long preample
+ * and one for short).
+ *
+ * Note: Band doesn't matter here, if we set the values for OFDM it works
+ * on both a and g modes. So all we have to do is set values for all g rates
+ * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
+ * quarter rate mode, we need to use another set of bitrates (that's why we
+ * need the mode parameter) but we don't handle these proprietary modes yet.
+ */
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+       unsigned int mode)
+{
+	struct ath5k_softc *sc = ah->ah_sc;
+	struct ieee80211_rate *rate;
+	unsigned int i;
+
+	/* Write rate duration table */
+	for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
+		u32 reg;
+		u16 tx_time;
+
+		rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
+
+		/* Set ACK timeout */
+		reg = AR5K_RATE_DUR(rate->hw_value);
+
+		/* An ACK frame consists of 10 bytes. If you add the FCS,
+		 * which ieee80211_generic_frame_duration() adds,
+		 * its 14 bytes. Note we use the control rate and not the
+		 * actual rate for this rate. See mac80211 tx.c
+		 * ieee80211_duration() for a brief description of
+		 * what rate we should choose to TX ACKs. */
+		tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
+							sc->vif, 10, rate));
+
+		ath5k_hw_reg_write(ah, tx_time, reg);
+
+		if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
+			continue;
+
+		/*
+		 * We're not distinguishing short preamble here,
+		 * This is true, all we'll get is a longer value here
+		 * which is not necessarilly bad. We could use
+		 * export ieee80211_frame_duration() but that needs to be
+		 * fixed first to be properly used by mac802111 drivers:
+		 *
+		 *  - remove erp stuff and let the routine figure ofdm
+		 *    erp rates
+		 *  - remove passing argument ieee80211_local as
+		 *    drivers don't have access to it
+		 *  - move drivers using ieee80211_generic_frame_duration()
+		 *    to this
+		 */
+		ath5k_hw_reg_write(ah, tx_time,
+			reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+	}
+}
+
+/*
+ * Reset chipset
+ */
+static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
+{
+	int ret;
+	u32 mask = val ? val : ~0U;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/* Read-and-clear RX Descriptor Pointer*/
+	ath5k_hw_reg_read(ah, AR5K_RXDP);
+
+	/*
+	 * Reset the device and wait until success
+	 */
+	ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
+
+	/* Wait at least 128 PCI clocks */
+	udelay(15);
+
+	if (ah->ah_version == AR5K_AR5210) {
+		val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+			| AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+		mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
+			| AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
+	} else {
+		val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+		mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+	}
+
+	ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
+
+	/*
+	 * Reset configuration register (for hw byte-swap). Note that this
+	 * is only set for big endian. We do the necessary magic in
+	 * AR5K_INIT_CFG.
+	 */
+	if ((val & AR5K_RESET_CTL_PCU) == 0)
+		ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
+
+	return ret;
+}
+
+/*
+ * Sleep control
+ */
+int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+		bool set_chip, u16 sleep_duration)
+{
+	unsigned int i;
+	u32 staid, data;
+
+	ATH5K_TRACE(ah->ah_sc);
+	staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+
+	switch (mode) {
+	case AR5K_PM_AUTO:
+		staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
+		/* fallthrough */
+	case AR5K_PM_NETWORK_SLEEP:
+		if (set_chip)
+			ath5k_hw_reg_write(ah,
+				AR5K_SLEEP_CTL_SLE_ALLOW |
+				sleep_duration,
+				AR5K_SLEEP_CTL);
+
+		staid |= AR5K_STA_ID1_PWR_SV;
+		break;
+
+	case AR5K_PM_FULL_SLEEP:
+		if (set_chip)
+			ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
+				AR5K_SLEEP_CTL);
+
+		staid |= AR5K_STA_ID1_PWR_SV;
+		break;
+
+	case AR5K_PM_AWAKE:
+
+		staid &= ~AR5K_STA_ID1_PWR_SV;
+
+		if (!set_chip)
+			goto commit;
+
+		/* Preserve sleep duration */
+		data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
+		if (data & 0xffc00000)
+			data = 0;
+		else
+			data = data & 0xfffcffff;
+
+		ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+		udelay(15);
+
+		for (i = 50; i > 0; i--) {
+			/* Check if the chip did wake up */
+			if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+					AR5K_PCICFG_SPWR_DN) == 0)
+				break;
+
+			/* Wait a bit and retry */
+			udelay(200);
+			ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+		}
+
+		/* Fail if the chip didn't wake up */
+		if (i <= 0)
+			return -EIO;
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+commit:
+	ah->ah_power_mode = mode;
+	ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
+
+	return 0;
+}
+
+/*
+ * Bring up MAC + PHY Chips and program PLL
+ * TODO: Half/Quarter rate support
+ */
+int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+{
+	struct pci_dev *pdev = ah->ah_sc->pdev;
+	u32 turbo, mode, clock, bus_flags;
+	int ret;
+
+	turbo = 0;
+	mode = 0;
+	clock = 0;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	/* Wakeup the device */
+	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+	if (ret) {
+		ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+		return ret;
+	}
+
+	if (ah->ah_version != AR5K_AR5210) {
+		/*
+		 * Get channel mode flags
+		 */
+
+		if (ah->ah_radio >= AR5K_RF5112) {
+			mode = AR5K_PHY_MODE_RAD_RF5112;
+			clock = AR5K_PHY_PLL_RF5112;
+		} else {
+			mode = AR5K_PHY_MODE_RAD_RF5111;	/*Zero*/
+			clock = AR5K_PHY_PLL_RF5111;		/*Zero*/
+		}
+
+		if (flags & CHANNEL_2GHZ) {
+			mode |= AR5K_PHY_MODE_FREQ_2GHZ;
+			clock |= AR5K_PHY_PLL_44MHZ;
+
+			if (flags & CHANNEL_CCK) {
+				mode |= AR5K_PHY_MODE_MOD_CCK;
+			} else if (flags & CHANNEL_OFDM) {
+				/* XXX Dynamic OFDM/CCK is not supported by the
+				 * AR5211 so we set MOD_OFDM for plain g (no
+				 * CCK headers) operation. We need to test
+				 * this, 5211 might support ofdm-only g after
+				 * all, there are also initial register values
+				 * in the code for g mode (see initvals.c). */
+				if (ah->ah_version == AR5K_AR5211)
+					mode |= AR5K_PHY_MODE_MOD_OFDM;
+				else
+					mode |= AR5K_PHY_MODE_MOD_DYN;
+			} else {
+				ATH5K_ERR(ah->ah_sc,
+					"invalid radio modulation mode\n");
+				return -EINVAL;
+			}
+		} else if (flags & CHANNEL_5GHZ) {
+			mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+
+			if (ah->ah_radio == AR5K_RF5413)
+				clock = AR5K_PHY_PLL_40MHZ_5413;
+			else
+				clock |= AR5K_PHY_PLL_40MHZ;
+
+			if (flags & CHANNEL_OFDM)
+				mode |= AR5K_PHY_MODE_MOD_OFDM;
+			else {
+				ATH5K_ERR(ah->ah_sc,
+					"invalid radio modulation mode\n");
+				return -EINVAL;
+			}
+		} else {
+			ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
+			return -EINVAL;
+		}
+
+		if (flags & CHANNEL_TURBO)
+			turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
+	} else { /* Reset the device */
+
+		/* ...enable Atheros turbo mode if requested */
+		if (flags & CHANNEL_TURBO)
+			ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
+					AR5K_PHY_TURBO);
+	}
+
+	/* reseting PCI on PCI-E cards results card to hang
+	 * and always return 0xffff... so we ingore that flag
+	 * for PCI-E cards */
+	bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+	/* Reset chipset */
+	if (ah->ah_version == AR5K_AR5210) {
+		ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+			AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+			AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+			mdelay(2);
+	} else {
+		ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+			AR5K_RESET_CTL_BASEBAND | bus_flags);
+	}
+	if (ret) {
+		ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+		return -EIO;
+	}
+
+	/* ...wakeup again!*/
+	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+	if (ret) {
+		ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+		return ret;
+	}
+
+	/* ...final warm reset */
+	if (ath5k_hw_nic_reset(ah, 0)) {
+		ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+		return -EIO;
+	}
+
+	if (ah->ah_version != AR5K_AR5210) {
+
+		/* ...update PLL if needed */
+		if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
+			ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
+			udelay(300);
+		}
+
+		/* ...set the PHY operating mode */
+		ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
+		ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
+	}
+
+	return 0;
+}
+
+/*
+ * If there is an external 32KHz crystal available, use it
+ * as ref. clock instead of 32/40MHz clock and baseband clocks
+ * to save power during sleep or restore normal 32/40MHz
+ * operation.
+ *
+ * XXX: When operating on 32KHz certain PHY registers (27 - 31,
+ * 	123 - 127) require delay on access.
+ */
+static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	u32 scal, spending, usec32;
+
+	/* Only set 32KHz settings if we have an external
+	 * 32KHz crystal present */
+	if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
+	AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
+	enable) {
+
+		/* 1 usec/cycle */
+		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
+		/* Set up tsf increment on each cycle */
+		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
+
+		/* Set baseband sleep control registers
+		 * and sleep control rate */
+		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+
+		if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413) ||
+		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+			spending = 0x14;
+		else
+			spending = 0x18;
+		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+		if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413) ||
+		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+			ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
+			ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
+			ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
+			ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
+			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
+		} else {
+			ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
+			ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
+			ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
+			ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
+			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
+		}
+
+		/* Enable sleep clock operation */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+	} else {
+
+		/* Disable sleep clock operation and
+		 * restore default parameters */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+		AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
+
+		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+		ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
+
+		if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+			scal = AR5K_PHY_SCAL_32MHZ_2417;
+		else if (ee->ee_is_hb63)
+			scal = AR5K_PHY_SCAL_32MHZ_HB63;
+		else
+			scal = AR5K_PHY_SCAL_32MHZ;
+		ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+
+		ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+		ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+
+		if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413) ||
+		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+			spending = 0x14;
+		else
+			spending = 0x18;
+		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+		if ((ah->ah_radio == AR5K_RF5112) ||
+		(ah->ah_radio == AR5K_RF5413))
+			usec32 = 39;
+		else
+			usec32 = 31;
+		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
+
+		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
+	}
+	return;
+}
+
+/* TODO: Half/Quarter rate */
+static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
+				struct ieee80211_channel *channel)
+{
+	if (ah->ah_version == AR5K_AR5212 &&
+	    ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+
+		/* Setup ADC control */
+		ath5k_hw_reg_write(ah,
+				(AR5K_REG_SM(2,
+				AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
+				AR5K_REG_SM(2,
+				AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
+				AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
+				AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
+				AR5K_PHY_ADC_CTL);
+
+
+
+		/* Disable barker RSSI threshold */
+		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+				AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
+
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
+			AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
+
+		/* Set the mute mask */
+		ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
+	}
+
+	/* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
+	if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
+
+	/* Enable DCU double buffering */
+	if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
+		AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+				AR5K_TXCFG_DCU_DBL_BUF_DIS);
+
+	/* Set DAC/ADC delays */
+	if (ah->ah_version == AR5K_AR5212) {
+		u32 scal;
+		struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+		if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+			scal = AR5K_PHY_SCAL_32MHZ_2417;
+		else if (ee->ee_is_hb63)
+			scal = AR5K_PHY_SCAL_32MHZ_HB63;
+		else
+			scal = AR5K_PHY_SCAL_32MHZ;
+		ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+	}
+
+	/* Set fast ADC */
+	if ((ah->ah_radio == AR5K_RF5413) ||
+	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+		u32 fast_adc = true;
+
+		if (channel->center_freq == 2462 ||
+		channel->center_freq == 2467)
+			fast_adc = 0;
+
+		/* Only update if needed */
+		if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
+				ath5k_hw_reg_write(ah, fast_adc,
+						AR5K_PHY_FAST_ADC);
+	}
+
+	/* Fix for first revision of the RF5112 RF chipset */
+	if (ah->ah_radio == AR5K_RF5112 &&
+			ah->ah_radio_5ghz_revision <
+			AR5K_SREV_RAD_5112A) {
+		u32 data;
+		ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+				AR5K_PHY_CCKTXCTL);
+		if (channel->hw_value & CHANNEL_5GHZ)
+			data = 0xffb81020;
+		else
+			data = 0xffb80d20;
+		ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
+	}
+
+	if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+		u32 usec_reg;
+		/* 5311 has different tx/rx latency masks
+		 * from 5211, since we deal 5311 the same
+		 * as 5211 when setting initvals, shift
+		 * values here to their proper locations */
+		usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
+		ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
+				AR5K_USEC_32 |
+				AR5K_USEC_TX_LATENCY_5211 |
+				AR5K_REG_SM(29,
+				AR5K_USEC_RX_LATENCY_5210)),
+				AR5K_USEC_5211);
+		/* Clear QCU/DCU clock gating register */
+		ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
+		/* Set DAC/ADC delays */
+		ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
+		/* Enable PCU FIFO corruption ECO */
+		AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
+					AR5K_DIAG_SW_ECO_ENABLE);
+	}
+}
+
+static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
+		struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
+{
+	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+	s16 cck_ofdm_pwr_delta;
+
+	/* Adjust power delta for channel 14 */
+	if (channel->center_freq == 2484)
+		cck_ofdm_pwr_delta =
+			((ee->ee_cck_ofdm_power_delta -
+			ee->ee_scaled_cck_delta) * 2) / 10;
+	else
+		cck_ofdm_pwr_delta =
+			(ee->ee_cck_ofdm_power_delta * 2) / 10;
+
+	/* Set CCK to OFDM power delta on tx power
+	 * adjustment register */
+	if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
+		if (channel->hw_value == CHANNEL_G)
+			ath5k_hw_reg_write(ah,
+			AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
+				AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
+			AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
+				AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
+				AR5K_PHY_TX_PWR_ADJ);
+		else
+			ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
+	} else {
+		/* For older revs we scale power on sw during tx power
+		 * setup */
+		ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
+		ah->ah_txpower.txp_cck_ofdm_gainf_delta =
+						ee->ee_cck_ofdm_gain_delta;
+	}
+
+	/* Set antenna idle switch table */
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
+			AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
+			(ah->ah_ant_ctl[ee_mode][0] |
+			AR5K_PHY_ANT_CTL_TXRX_EN));
+
+	/* Set antenna switch tables */
+	ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]],
+		AR5K_PHY_ANT_SWITCH_TABLE_0);
+	ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]],
+		AR5K_PHY_ANT_SWITCH_TABLE_1);
+
+	/* Noise floor threshold */
+	ath5k_hw_reg_write(ah,
+		AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
+		AR5K_PHY_NFTHRES);
+
+	if ((channel->hw_value & CHANNEL_TURBO) &&
+	(ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
+		/* Switch settling time (Turbo) */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+				AR5K_PHY_SETTLING_SWITCH,
+				ee->ee_switch_settling_turbo[ee_mode]);
+
+		/* Tx/Rx attenuation (Turbo) */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+				AR5K_PHY_GAIN_TXRX_ATTEN,
+				ee->ee_atn_tx_rx_turbo[ee_mode]);
+
+		/* ADC/PGA desired size (Turbo) */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+				AR5K_PHY_DESIRED_SIZE_ADC,
+				ee->ee_adc_desired_size_turbo[ee_mode]);
+
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+				AR5K_PHY_DESIRED_SIZE_PGA,
+				ee->ee_pga_desired_size_turbo[ee_mode]);
+
+		/* Tx/Rx margin (Turbo) */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+				AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+				ee->ee_margin_tx_rx_turbo[ee_mode]);
+
+	} else {
+		/* Switch settling time */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+				AR5K_PHY_SETTLING_SWITCH,
+				ee->ee_switch_settling[ee_mode]);
+
+		/* Tx/Rx attenuation */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
+				AR5K_PHY_GAIN_TXRX_ATTEN,
+				ee->ee_atn_tx_rx[ee_mode]);
+
+		/* ADC/PGA desired size */
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+				AR5K_PHY_DESIRED_SIZE_ADC,
+				ee->ee_adc_desired_size[ee_mode]);
+
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
+				AR5K_PHY_DESIRED_SIZE_PGA,
+				ee->ee_pga_desired_size[ee_mode]);
+
+		/* Tx/Rx margin */
+		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+			AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+				AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+				ee->ee_margin_tx_rx[ee_mode]);
+	}
+
+	/* XPA delays */
+	ath5k_hw_reg_write(ah,
+		(ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+		(ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+		(ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+		(ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
+
+	/* XLNA delay */
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
+			AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
+			ee->ee_tx_end2xlna_enable[ee_mode]);
+
+	/* Thresh64 (ANI) */
+	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
+			AR5K_PHY_NF_THRESH62,
+			ee->ee_thr_62[ee_mode]);
+
+
+	/* False detect backoff for channels
+	 * that have spur noise. Write the new
+	 * cyclic power RSSI threshold. */
+	if (ath5k_hw_chan_has_spur_noise(ah, channel))
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+				AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+				AR5K_INIT_CYCRSSI_THR1 +
+				ee->ee_false_detect[ee_mode]);
+	else
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
+				AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
+				AR5K_INIT_CYCRSSI_THR1);
+
+	/* I/Q correction
+	 * TODO: Per channel i/q infos ? */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+		AR5K_PHY_IQ_CORR_ENABLE |
+		(ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
+		ee->ee_q_cal[ee_mode]);
+
+	/* Heavy clipping -disable for now */
+	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
+		ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
+
+	return;
+}
+
+/*
+ * Main reset function
+ */
+int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+	struct ieee80211_channel *channel, bool change_channel)
+{
+	u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
+	u32 phy_tst1;
+	u8 mode, freq, ee_mode, ant[2];
+	int i, ret;
+
+	ATH5K_TRACE(ah->ah_sc);
+
+	s_ant = 0;
+	ee_mode = 0;
+	staid1_flags = 0;
+	tsf_up = 0;
+	tsf_lo = 0;
+	freq = 0;
+	mode = 0;
+
+	/*
+	 * Save some registers before a reset
+	 */
+	/*DCU/Antenna selection not available on 5210*/
+	if (ah->ah_version != AR5K_AR5210) {
+
+		switch (channel->hw_value & CHANNEL_MODES) {
+		case CHANNEL_A:
+			mode = AR5K_MODE_11A;
+			freq = AR5K_INI_RFGAIN_5GHZ;
+			ee_mode = AR5K_EEPROM_MODE_11A;
+			break;
+		case CHANNEL_G:
+			mode = AR5K_MODE_11G;
+			freq = AR5K_INI_RFGAIN_2GHZ;
+			ee_mode = AR5K_EEPROM_MODE_11G;
+			break;
+		case CHANNEL_B:
+			mode = AR5K_MODE_11B;
+			freq = AR5K_INI_RFGAIN_2GHZ;
+			ee_mode = AR5K_EEPROM_MODE_11B;
+			break;
+		case CHANNEL_T:
+			mode = AR5K_MODE_11A_TURBO;
+			freq = AR5K_INI_RFGAIN_5GHZ;
+			ee_mode = AR5K_EEPROM_MODE_11A;
+			break;
+		case CHANNEL_TG:
+			if (ah->ah_version == AR5K_AR5211) {
+				ATH5K_ERR(ah->ah_sc,
+					"TurboG mode not available on 5211");
+				return -EINVAL;
+			}
+			mode = AR5K_MODE_11G_TURBO;
+			freq = AR5K_INI_RFGAIN_2GHZ;
+			ee_mode = AR5K_EEPROM_MODE_11G;
+			break;
+		case CHANNEL_XR:
+			if (ah->ah_version == AR5K_AR5211) {
+				ATH5K_ERR(ah->ah_sc,
+					"XR mode not available on 5211");
+				return -EINVAL;
+			}
+			mode = AR5K_MODE_XR;
+			freq = AR5K_INI_RFGAIN_5GHZ;
+			ee_mode = AR5K_EEPROM_MODE_11A;
+			break;
+		default:
+			ATH5K_ERR(ah->ah_sc,
+				"invalid channel: %d\n", channel->center_freq);
+			return -EINVAL;
+		}
+
+		if (change_channel) {
+			/*
+			 * Save frame sequence count
+			 * For revs. after Oahu, only save
+			 * seq num for DCU 0 (Global seq num)
+			 */
+			if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+
+				for (i = 0; i < 10; i++)
+					s_seq[i] = ath5k_hw_reg_read(ah,
+						AR5K_QUEUE_DCU_SEQNUM(i));
+
+			} else {
+				s_seq[0] = ath5k_hw_reg_read(ah,
+						AR5K_QUEUE_DCU_SEQNUM(0));
+			}
+
+			/* TSF accelerates on AR5211 durring reset
+			 * As a workaround save it here and restore
+			 * it later so that it's back in time after
+			 * reset. This way it'll get re-synced on the
+			 * next beacon without breaking ad-hoc.
+			 *
+			 * On AR5212 TSF is almost preserved across a
+			 * reset so it stays back in time anyway and
+			 * we don't have to save/restore it.
+			 *
+			 * XXX: Since this breaks power saving we have
+			 * to disable power saving until we receive the
+			 * next beacon, so we can resync beacon timers */
+			if (ah->ah_version == AR5K_AR5211) {
+				tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+				tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
+			}
+		}
+
+		/* Save default antenna */
+		s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+		if (ah->ah_version == AR5K_AR5212) {
+			/* Restore normal 32/40MHz clock operation
+			 * to avoid register access delay on certain
+			 * PHY registers */
+			ath5k_hw_set_sleep_clock(ah, false);
+
+			/* Since we are going to write rf buffer
+			 * check if we have any pending gain_F
+			 * optimization settings */
+			if (change_channel && ah->ah_rf_banks != NULL)
+				ath5k_hw_gainf_calibrate(ah);
+		}
+	}
+
+	/*GPIOs*/
+	s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+					AR5K_PCICFG_LEDSTATE;
+	s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+	s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+	/* AR5K_STA_ID1 flags, only preserve antenna
+	 * settings and ack/cts rate mode */
+	staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
+			(AR5K_STA_ID1_DEFAULT_ANTENNA |
+			AR5K_STA_ID1_DESC_ANTENNA |
+			AR5K_STA_ID1_RTS_DEF_ANTENNA |
+			AR5K_STA_ID1_ACKCTS_6MB |
+			AR5K_STA_ID1_BASE_RATE_11B |
+			AR5K_STA_ID1_SELFGEN_DEF_ANT);
+
+	/* Wakeup the device */
+	ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+	if (ret)
+		return ret;
+
+	/*
+	 * Initialize operating mode
+	 */
+	ah->ah_op_mode = op_mode;
+
+	/* PHY access enable */
+	if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
+		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+	else
+		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
+							AR5K_PHY(0));
+
+	/* Write initial settings */
+	ret = ath5k_hw_write_initvals(ah, mode, change_channel);
+	if (ret)
+		return ret;
+
+	/*
+	 * 5211/5212 Specific
+	 */
+	if (ah->ah_version != AR5K_AR5210) {
+
+		/*
+		 * Write initial RF gain settings
+		 * This should work for both 5111/5112
+		 */
+		ret = ath5k_hw_rfgain_init(ah, freq);
+		if (ret)
+			return ret;
+
+		mdelay(1);
+
+		/*
+		 * Tweak initval settings for revised
+		 * chipsets and add some more config
+		 * bits
+		 */
+		ath5k_hw_tweak_initval_settings(ah, channel);
+
+		/*
+		 * Set TX power
+		 */
+		ret = ath5k_hw_txpower(ah, channel, ee_mode,
+					ah->ah_txpower.txp_max_pwr / 2);
+		if (ret)
+			return ret;
+
+		/* Write rate duration table only on AR5212 and if
+		 * virtual interface has already been brought up
+		 * XXX: rethink this after new mode changes to
+		 * mac80211 are integrated */
+		if (ah->ah_version == AR5K_AR5212 &&
+			ah->ah_sc->vif != NULL)
+			ath5k_hw_write_rate_duration(ah, mode);
+
+		/*
+		 * Write RF buffer
+		 */
+		ret = ath5k_hw_rfregs_init(ah, channel, mode);
+		if (ret)
+			return ret;
+
+
+		/* Write OFDM timings on 5212*/
+		if (ah->ah_version == AR5K_AR5212 &&
+			channel->hw_value & CHANNEL_OFDM) {
+			struct ath5k_eeprom_info *ee =
+					&ah->ah_capabilities.cap_eeprom;
+
+			ret = ath5k_hw_write_ofdm_timings(ah, channel);
+			if (ret)
+				return ret;
+
+			/* Note: According to docs we can have a newer
+			 * EEPROM on old hardware, so we need to verify
+			 * that our hardware is new enough to have spur
+			 * mitigation registers (delta phase etc) */
+			if (ah->ah_mac_srev >= AR5K_SREV_AR5424 ||
+			(ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
+			ee->ee_version >= AR5K_EEPROM_VERSION_5_3))
+				ath5k_hw_set_spur_mitigation_filter(ah,
+								channel);
+		}
+
+		/*Enable/disable 802.11b mode on 5111
+		(enable 2111 frequency converter + CCK)*/
+		if (ah->ah_radio == AR5K_RF5111) {
+			if (mode == AR5K_MODE_11B)
+				AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+				    AR5K_TXCFG_B_MODE);
+			else
+				AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+				    AR5K_TXCFG_B_MODE);
+		}
+
+		/*
+		 * In case a fixed antenna was set as default
+		 * use the same switch table twice.
+		 */
+		if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A)
+				ant[0] = ant[1] = AR5K_ANT_SWTABLE_A;
+		else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B)
+				ant[0] = ant[1] = AR5K_ANT_SWTABLE_B;
+		else {
+			ant[0] = AR5K_ANT_SWTABLE_A;
+			ant[1] = AR5K_ANT_SWTABLE_B;
+		}
+
+		/* Commit values from EEPROM */
+		ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);
+
+	} else {
+		/*
+		 * For 5210 we do all initialization using
+		 * initvals, so we don't have to modify
+		 * any settings (5210 also only supports
+		 * a/aturbo modes)
+		 */
+		mdelay(1);
+		/* Disable phy and wait */
+		ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+		mdelay(1);
+	}
+
+	/*
+	 * Restore saved values
+	 */
+
+	/*DCU/Antenna selection not available on 5210*/
+	if (ah->ah_version != AR5K_AR5210) {
+
+		if (change_channel) {
+			if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+				for (i = 0; i < 10; i++)
+					ath5k_hw_reg_write(ah, s_seq[i],
+						AR5K_QUEUE_DCU_SEQNUM(i));
+			} else {
+				ath5k_hw_reg_write(ah, s_seq[0],
+					AR5K_QUEUE_DCU_SEQNUM(0));
+			}
+
+
+			if (ah->ah_version == AR5K_AR5211) {
+				ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
+				ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
+			}
+		}
+
+		ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
+	}
+
+	/* Ledstate */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
+
+	/* Gpio settings */
+	ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
+	ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
+
+	/* Restore sta_id flags and preserve our mac address*/
+	ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
+						AR5K_STA_ID0);
+	ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
+						AR5K_STA_ID1);
+
+
+	/*
+	 * Configure PCU
+	 */
+
+	/* Restore bssid and bssid mask */
+	/* XXX: add ah->aid once mac80211 gives this to us */
+	ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+
+	/* Set PCU config */
+	ath5k_hw_set_opmode(ah);
+
+	/* Clear any pending interrupts
+	 * PISR/SISR Not available on 5210 */
+	if (ah->ah_version != AR5K_AR5210)
+		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
+
+	/* Set RSSI/BRSSI thresholds
+	 *
+	 * Note: If we decide to set this value
+	 * dynamicaly, have in mind that when AR5K_RSSI_THR
+	 * register is read it might return 0x40 if we haven't
+	 * wrote anything to it plus BMISS RSSI threshold is zeroed.
+	 * So doing a save/restore procedure here isn't the right
+	 * choice. Instead store it on ath5k_hw */
+	ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
+				AR5K_TUNE_BMISS_THRES <<
+				AR5K_RSSI_THR_BMISS_S),
+				AR5K_RSSI_THR);
+
+	/* MIC QoS support */
+	if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
+		ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
+		ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
+	}
+
+	/* QoS NOACK Policy */
+	if (ah->ah_version == AR5K_AR5212) {
+		ath5k_hw_reg_write(ah,
+			AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
+			AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET)  |
+			AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
+			AR5K_QOS_NOACK);
+	}
+
+
+	/*
+	 * Configure PHY
+	 */
+
+	/* Set channel on PHY */
+	ret = ath5k_hw_channel(ah, channel);
+	if (ret)
+		return ret;
+
+	/*
+	 * Enable the PHY and wait until completion
+	 * This includes BaseBand and Synthesizer
+	 * activation.
+	 */
+	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+
+	/*
+	 * On 5211+ read activation -> rx delay
+	 * and use it.
+	 *
+	 * TODO: Half/quarter rate support
+	 */
+	if (ah->ah_version != AR5K_AR5210) {
+		u32 delay;
+		delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+			AR5K_PHY_RX_DELAY_M;
+		delay = (channel->hw_value & CHANNEL_CCK) ?
+			((delay << 2) / 22) : (delay / 10);
+
+		udelay(100 + (2 * delay));
+	} else {
+		mdelay(1);
+	}
+
+	/*
+	 * Perform ADC test to see if baseband is ready
+	 * Set tx hold and check adc test register
+	 */
+	phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
+	ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
+	for (i = 0; i <= 20; i++) {
+		if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
+			break;
+		udelay(200);
+	}
+	ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
+
+	/*
+	 * Start automatic gain control calibration
+	 *
+	 * During AGC calibration RX path is re-routed to
+	 * a power detector so we don't receive anything.
+	 *
+	 * This method is used to calibrate some static offsets
+	 * used together with on-the fly I/Q calibration (the
+	 * one performed via ath5k_hw_phy_calibrate), that doesn't
+	 * interrupt rx path.
+	 *
+	 * While rx path is re-routed to the power detector we also
+	 * start a noise floor calibration, to measure the
+	 * card's noise floor (the noise we measure when we are not
+	 * transmiting or receiving anything).
+	 *
+	 * If we are in a noisy environment AGC calibration may time
+	 * out and/or noise floor calibration might timeout.
+	 */
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+				AR5K_PHY_AGCCTL_CAL);
+
+	/* At the same time start I/Q calibration for QAM constellation
+	 * -no need for CCK- */
+	ah->ah_calibration = false;
+	if (!(mode == AR5K_MODE_11B)) {
+		ah->ah_calibration = true;
+		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+				AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+				AR5K_PHY_IQ_RUN);
+	}
+
+	/* Wait for gain calibration to finish (we check for I/Q calibration
+	 * during ath5k_phy_calibrate) */
+	if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+			AR5K_PHY_AGCCTL_CAL, 0, false)) {
+		ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
+			channel->center_freq);
+	}
+
+	/*
+	 * If we run NF calibration before AGC, it always times out.
+	 * Binary HAL starts NF and AGC calibration at the same time
+	 * and only waits for AGC to finish. Also if AGC or NF cal.
+	 * times out, reset doesn't fail on binary HAL. I believe
+	 * that's wrong because since rx path is routed to a detector,
+	 * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
+	 * enables noise floor calibration after offset calibration and if noise
+	 * floor calibration fails, reset fails. I believe that's
+	 * a better approach, we just need to find a polling interval
+	 * that suits best, even if reset continues we need to make
+	 * sure that rx path is ready.
+	 */
+	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+	/* Restore antenna mode */
+	ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
+
+	/*
+	 * Configure QCUs/DCUs
+	 */
+
+	/* TODO: HW Compression support for data queues */
+	/* TODO: Burst prefetch for data queues */
+
+	/*
+	 * Reset queues and start beacon timers at the end of the reset routine
+	 * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
+	 * Note: If we want we can assign multiple qcus on one dcu.
+	 */
+	for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
+		ret = ath5k_hw_reset_tx_queue(ah, i);
+		if (ret) {
+			ATH5K_ERR(ah->ah_sc,
+				"failed to reset TX queue #%d\n", i);
+			return ret;
+		}
+	}
+
+
+	/*
+	 * Configure DMA/Interrupts
+	 */
+
+	/*
+	 * Set Rx/Tx DMA Configuration
+	 *
+	 * Set standard DMA size (128). Note that
+	 * a DMA size of 512 causes rx overruns and tx errors
+	 * on pci-e cards (tested on 5424 but since rx overruns
+	 * also occur on 5416/5418 with madwifi we set 128
+	 * for all PCI-E cards to be safe).
+	 *
+	 * XXX: need to check 5210 for this
+	 * TODO: Check out tx triger level, it's always 64 on dumps but I
+	 * guess we can tweak it and see how it goes ;-)
+	 */
+	if (ah->ah_version != AR5K_AR5210) {
+		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+			AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+			AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+	}
+
+	/* Pre-enable interrupts on 5211/5212*/
+	if (ah->ah_version != AR5K_AR5210)
+		ath5k_hw_set_imr(ah, ah->ah_imr);
+
+	/* Enable 32KHz clock function for AR5212+ chips
+	 * Set clocks to 32KHz operation and use an
+	 * external 32KHz crystal when sleeping if one
+	 * exists */
+	if (ah->ah_version == AR5K_AR5212)
+			ath5k_hw_set_sleep_clock(ah, true);
+
+	/*
+	 * Disable beacons and reset the register
+	 */
+	AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
+			AR5K_BEACON_RESET_TSF);
+
+	return 0;
+}
+
+#undef _ATH5K_RESET
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/rfbuffer.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/rfbuffer.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/rfbuffer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/rfbuffer.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1181 @@
+/*
+ * RF Buffer handling functions
+ *
+ * Copyright (c) 2009 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+
+/*
+ * There are some special registers on the RF chip
+ * that control various operation settings related mostly to
+ * the analog parts (channel, gain adjustment etc).
+ *
+ * We don't write on those registers directly but
+ * we send a data packet on the chip, using a special register,
+ * that holds all the settings we need. After we 've sent the
+ * data packet, we write on another special register to notify hw
+ * to apply the settings. This is done so that control registers
+ * can be dynamicaly programmed during operation and the settings
+ * are applied faster on the hw.
+ *
+ * We call each data packet an "RF Bank" and all the data we write
+ * (all RF Banks) "RF Buffer". This file holds initial RF Buffer
+ * data for the different RF chips, and various info to match RF
+ * Buffer offsets with specific RF registers so that we can access
+ * them. We tweak these settings on rfregs_init function.
+ *
+ * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer
+ * registers and control registers):
+ *
+ * http://www.google.com/patents?id=qNURAAAAEBAJ
+ */
+
+
+/*
+ * Struct to hold default mode specific RF
+ * register values (RF Banks)
+ */
+struct ath5k_ini_rfbuffer {
+	u8	rfb_bank;		/* RF Bank number */
+	u16	rfb_ctrl_register;	/* RF Buffer control register */
+	u32	rfb_mode_data[5];	/* RF Buffer data for each mode */
+};
+
+/*
+ * Struct to hold RF Buffer field
+ * infos used to access certain RF
+ * analog registers
+ */
+struct ath5k_rfb_field {
+	u8	len;	/* Field length */
+	u16	pos;	/* Offset on the raw packet */
+	u8	col;	/* Column -used for shifting */
+};
+
+/*
+ * RF analog register definition
+ */
+struct ath5k_rf_reg {
+	u8			bank;	/* RF Buffer Bank number */
+	u8			index;	/* Register's index on rf_regs_idx */
+	struct ath5k_rfb_field	field;	/* RF Buffer field for this register */
+};
+
+/* Map RF registers to indexes
+ * We do this to handle common bits and make our
+ * life easier by using an index for each register
+ * instead of a full rfb_field */
+enum ath5k_rf_regs_idx {
+	/* BANK 6 */
+	AR5K_RF_OB_2GHZ = 0,
+	AR5K_RF_OB_5GHZ,
+	AR5K_RF_DB_2GHZ,
+	AR5K_RF_DB_5GHZ,
+	AR5K_RF_FIXED_BIAS_A,
+	AR5K_RF_FIXED_BIAS_B,
+	AR5K_RF_PWD_XPD,
+	AR5K_RF_XPD_SEL,
+	AR5K_RF_XPD_GAIN,
+	AR5K_RF_PD_GAIN_LO,
+	AR5K_RF_PD_GAIN_HI,
+	AR5K_RF_HIGH_VC_CP,
+	AR5K_RF_MID_VC_CP,
+	AR5K_RF_LOW_VC_CP,
+	AR5K_RF_PUSH_UP,
+	AR5K_RF_PAD2GND,
+	AR5K_RF_XB2_LVL,
+	AR5K_RF_XB5_LVL,
+	AR5K_RF_PWD_ICLOBUF_2G,
+	AR5K_RF_PWD_84,
+	AR5K_RF_PWD_90,
+	AR5K_RF_PWD_130,
+	AR5K_RF_PWD_131,
+	AR5K_RF_PWD_132,
+	AR5K_RF_PWD_136,
+	AR5K_RF_PWD_137,
+	AR5K_RF_PWD_138,
+	AR5K_RF_PWD_166,
+	AR5K_RF_PWD_167,
+	AR5K_RF_DERBY_CHAN_SEL_MODE,
+	/* BANK 7 */
+	AR5K_RF_GAIN_I,
+	AR5K_RF_PLO_SEL,
+	AR5K_RF_RFGAIN_SEL,
+	AR5K_RF_RFGAIN_STEP,
+	AR5K_RF_WAIT_S,
+	AR5K_RF_WAIT_I,
+	AR5K_RF_MAX_TIME,
+	AR5K_RF_MIXVGA_OVR,
+	AR5K_RF_MIXGAIN_OVR,
+	AR5K_RF_MIXGAIN_STEP,
+	AR5K_RF_PD_DELAY_A,
+	AR5K_RF_PD_DELAY_B,
+	AR5K_RF_PD_DELAY_XR,
+	AR5K_RF_PD_PERIOD_A,
+	AR5K_RF_PD_PERIOD_B,
+	AR5K_RF_PD_PERIOD_XR,
+};
+
+
+/*******************\
+* RF5111 (Sombrero) *
+\*******************/
+
+/* BANK 6				len  pos col */
+#define	AR5K_RF5111_OB_2GHZ		{ 3, 119, 0 }
+#define	AR5K_RF5111_DB_2GHZ		{ 3, 122, 0 }
+
+#define	AR5K_RF5111_OB_5GHZ		{ 3, 104, 0 }
+#define	AR5K_RF5111_DB_5GHZ		{ 3, 107, 0 }
+
+#define	AR5K_RF5111_PWD_XPD		{ 1, 95,  0 }
+#define	AR5K_RF5111_XPD_GAIN		{ 4, 96,  0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5111_PWD(_n)		{ 1, (135 - _n), 3 }
+
+/* BANK 7				len  pos col */
+#define	AR5K_RF5111_GAIN_I		{ 6, 29,  0 }
+#define	AR5K_RF5111_PLO_SEL		{ 1, 4,   0 }
+#define	AR5K_RF5111_RFGAIN_SEL		{ 1, 36,  0 }
+#define AR5K_RF5111_RFGAIN_STEP		{ 6, 37,  0 }
+/* Only on AR5212 BaseBand and up */
+#define	AR5K_RF5111_WAIT_S		{ 5, 19,  0 }
+#define	AR5K_RF5111_WAIT_I		{ 5, 24,  0 }
+#define	AR5K_RF5111_MAX_TIME		{ 2, 49,  0 }
+
+static const struct ath5k_rf_reg rf_regs_5111[] = {
+	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5111_OB_2GHZ},
+	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5111_DB_2GHZ},
+	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5111_OB_5GHZ},
+	{6, AR5K_RF_DB_5GHZ,		AR5K_RF5111_DB_5GHZ},
+	{6, AR5K_RF_PWD_XPD,		AR5K_RF5111_PWD_XPD},
+	{6, AR5K_RF_XPD_GAIN,		AR5K_RF5111_XPD_GAIN},
+	{6, AR5K_RF_PWD_84,		AR5K_RF5111_PWD(84)},
+	{6, AR5K_RF_PWD_90,		AR5K_RF5111_PWD(90)},
+	{7, AR5K_RF_GAIN_I,		AR5K_RF5111_GAIN_I},
+	{7, AR5K_RF_PLO_SEL,		AR5K_RF5111_PLO_SEL},
+	{7, AR5K_RF_RFGAIN_SEL,		AR5K_RF5111_RFGAIN_SEL},
+	{7, AR5K_RF_RFGAIN_STEP,	AR5K_RF5111_RFGAIN_STEP},
+	{7, AR5K_RF_WAIT_S,		AR5K_RF5111_WAIT_S},
+	{7, AR5K_RF_WAIT_I,		AR5K_RF5111_WAIT_I},
+	{7, AR5K_RF_MAX_TIME,		AR5K_RF5111_MAX_TIME}
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5111[] = {
+	{ 0, 0x989c,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 0, 0x989c,
+	    { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
+	{ 0, 0x989c,
+	    { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
+	{ 0, 0x98d4,
+	    { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
+	{ 1, 0x98d4,
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d4,
+	    { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
+	{ 3, 0x98d8,
+	    { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c,
+	    { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
+	{ 6, 0x989c,
+	    { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
+	{ 6, 0x989c,
+	    { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
+	{ 6, 0x989c,
+	    { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
+	{ 6, 0x989c,
+	    { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
+	{ 6, 0x98d4,
+	    { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
+	{ 7, 0x989c,
+	    { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
+	{ 7, 0x989c,
+	    { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
+	{ 7, 0x989c,
+	    { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+	{ 7, 0x989c,
+	    { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
+	{ 7, 0x989c,
+	    { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
+	{ 7, 0x989c,
+	    { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
+	{ 7, 0x989c,
+	    { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
+	{ 7, 0x98cc,
+	    { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***********************\
+* RF5112/RF2112 (Derby) *
+\***********************/
+
+/* BANK 7 (Common)			len  pos col */
+#define	AR5K_RF5112X_GAIN_I		{ 6, 14,  0 }
+#define	AR5K_RF5112X_MIXVGA_OVR		{ 1, 36,  0 }
+#define	AR5K_RF5112X_MIXGAIN_OVR	{ 2, 37,  0 }
+#define AR5K_RF5112X_MIXGAIN_STEP	{ 4, 32,  0 }
+#define	AR5K_RF5112X_PD_DELAY_A		{ 4, 58,  0 }
+#define	AR5K_RF5112X_PD_DELAY_B		{ 4, 62,  0 }
+#define	AR5K_RF5112X_PD_DELAY_XR	{ 4, 66,  0 }
+#define	AR5K_RF5112X_PD_PERIOD_A	{ 4, 70,  0 }
+#define	AR5K_RF5112X_PD_PERIOD_B	{ 4, 74,  0 }
+#define	AR5K_RF5112X_PD_PERIOD_XR	{ 4, 78,  0 }
+
+/* RFX112 (Derby 1) */
+
+/* BANK 6 				len  pos col */
+#define	AR5K_RF5112_OB_2GHZ		{ 3, 269, 0 }
+#define	AR5K_RF5112_DB_2GHZ		{ 3, 272, 0 }
+
+#define	AR5K_RF5112_OB_5GHZ		{ 3, 261, 0 }
+#define	AR5K_RF5112_DB_5GHZ		{ 3, 264, 0 }
+
+#define	AR5K_RF5112_FIXED_BIAS_A	{ 1, 260, 0 }
+#define	AR5K_RF5112_FIXED_BIAS_B	{ 1, 259, 0 }
+
+#define	AR5K_RF5112_XPD_SEL		{ 1, 284, 0 }
+#define	AR5K_RF5112_XPD_GAIN		{ 2, 252, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5112_PWD(_n)		{ 1, (302 - _n), 3 }
+
+static const struct ath5k_rf_reg rf_regs_5112[] = {
+	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5112_OB_2GHZ},
+	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5112_DB_2GHZ},
+	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5112_OB_5GHZ},
+	{6, AR5K_RF_DB_5GHZ,		AR5K_RF5112_DB_5GHZ},
+	{6, AR5K_RF_FIXED_BIAS_A,	AR5K_RF5112_FIXED_BIAS_A},
+	{6, AR5K_RF_FIXED_BIAS_B,	AR5K_RF5112_FIXED_BIAS_B},
+	{6, AR5K_RF_XPD_SEL,		AR5K_RF5112_XPD_SEL},
+	{6, AR5K_RF_XPD_GAIN,		AR5K_RF5112_XPD_GAIN},
+	{6, AR5K_RF_PWD_130,		AR5K_RF5112_PWD(130)},
+	{6, AR5K_RF_PWD_131,		AR5K_RF5112_PWD(131)},
+	{6, AR5K_RF_PWD_132,		AR5K_RF5112_PWD(132)},
+	{6, AR5K_RF_PWD_136,		AR5K_RF5112_PWD(136)},
+	{6, AR5K_RF_PWD_137,		AR5K_RF5112_PWD(137)},
+	{6, AR5K_RF_PWD_138,		AR5K_RF5112_PWD(138)},
+	{7, AR5K_RF_GAIN_I,		AR5K_RF5112X_GAIN_I},
+	{7, AR5K_RF_MIXVGA_OVR,		AR5K_RF5112X_MIXVGA_OVR},
+	{7, AR5K_RF_MIXGAIN_OVR,	AR5K_RF5112X_MIXGAIN_OVR},
+	{7, AR5K_RF_MIXGAIN_STEP,	AR5K_RF5112X_MIXGAIN_STEP},
+	{7, AR5K_RF_PD_DELAY_A,		AR5K_RF5112X_PD_DELAY_A},
+	{7, AR5K_RF_PD_DELAY_B,		AR5K_RF5112X_PD_DELAY_B},
+	{7, AR5K_RF_PD_DELAY_XR,	AR5K_RF5112X_PD_DELAY_XR},
+	{7, AR5K_RF_PD_PERIOD_A,	AR5K_RF5112X_PD_PERIOD_A},
+	{7, AR5K_RF_PD_PERIOD_B,	AR5K_RF5112X_PD_PERIOD_B},
+	{7, AR5K_RF_PD_PERIOD_XR,	AR5K_RF5112X_PD_PERIOD_XR},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5112[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+	{ 3, 0x98dc,
+	    { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
+	{ 6, 0x989c,
+	    { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
+	{ 6, 0x989c,
+	    { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
+	{ 6, 0x989c,
+	    { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
+	{ 6, 0x989c,
+	    { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
+	{ 6, 0x989c,
+	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+	{ 6, 0x989c,
+	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+	{ 6, 0x989c,
+	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+	{ 6, 0x989c,
+	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c,
+	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c,
+	    { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
+	{ 6, 0x989c,
+	    { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
+	{ 6, 0x989c,
+	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+	{ 6, 0x989c,
+	    { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+	{ 6, 0x989c,
+	    { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
+	{ 6, 0x989c,
+	    { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
+	{ 6, 0x989c,
+	    { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+	{ 6, 0x989c,
+	    { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
+	{ 6, 0x989c,
+	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+	{ 6, 0x989c,
+	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+	{ 6, 0x989c,
+	    { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
+	{ 6, 0x989c,
+	    { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
+	{ 6, 0x989c,
+	    { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+	{ 6, 0x989c,
+	    { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
+	{ 6, 0x989c,
+	    { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
+	{ 6, 0x989c,
+	    { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
+	{ 6, 0x989c,
+	    { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
+	{ 6, 0x989c,
+	    { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
+	{ 6, 0x989c,
+	    { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
+	{ 6, 0x989c,
+	    { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
+	{ 6, 0x989c,
+	    { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
+	{ 6, 0x989c,
+	    { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
+	{ 6, 0x989c,
+	    { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
+	{ 6, 0x98d0,
+	    { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
+	{ 7, 0x989c,
+	    { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+	{ 7, 0x989c,
+	    { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+	{ 7, 0x989c,
+	    { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
+	{ 7, 0x989c,
+	    { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+	{ 7, 0x989c,
+	    { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
+	{ 7, 0x989c,
+	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+	{ 7, 0x989c,
+	    { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+	{ 7, 0x989c,
+	    { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
+	{ 7, 0x989c,
+	    { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
+	{ 7, 0x989c,
+	    { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+	{ 7, 0x989c,
+	    { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+	{ 7, 0x989c,
+	    { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+	{ 7, 0x98c4,
+	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+/* RFX112A (Derby 2) */
+
+/* BANK 6				len  pos col */
+#define	AR5K_RF5112A_OB_2GHZ		{ 3, 287, 0 }
+#define	AR5K_RF5112A_DB_2GHZ		{ 3, 290, 0 }
+
+#define	AR5K_RF5112A_OB_5GHZ		{ 3, 279, 0 }
+#define	AR5K_RF5112A_DB_5GHZ		{ 3, 282, 0 }
+
+#define	AR5K_RF5112A_FIXED_BIAS_A	{ 1, 278, 0 }
+#define	AR5K_RF5112A_FIXED_BIAS_B	{ 1, 277, 0 }
+
+#define	AR5K_RF5112A_XPD_SEL		{ 1, 302, 0 }
+#define	AR5K_RF5112A_PDGAINLO		{ 2, 270, 0 }
+#define	AR5K_RF5112A_PDGAINHI		{ 2, 257, 0 }
+
+/* Access to PWD registers */
+#define AR5K_RF5112A_PWD(_n)		{ 1, (306 - _n), 3 }
+
+/* Voltage regulators */
+#define	AR5K_RF5112A_HIGH_VC_CP		{ 2, 90,  2 }
+#define	AR5K_RF5112A_MID_VC_CP		{ 2, 92,  2 }
+#define	AR5K_RF5112A_LOW_VC_CP		{ 2, 94,  2 }
+#define	AR5K_RF5112A_PUSH_UP		{ 1, 254,  2 }
+
+/* Power consumption */
+#define	AR5K_RF5112A_PAD2GND		{ 1, 281, 1 }
+#define	AR5K_RF5112A_XB2_LVL		{ 2, 1,	  3 }
+#define	AR5K_RF5112A_XB5_LVL		{ 2, 3,	  3 }
+
+static const struct ath5k_rf_reg rf_regs_5112a[] = {
+	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5112A_OB_2GHZ},
+	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5112A_DB_2GHZ},
+	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5112A_OB_5GHZ},
+	{6, AR5K_RF_DB_5GHZ,		AR5K_RF5112A_DB_5GHZ},
+	{6, AR5K_RF_FIXED_BIAS_A,	AR5K_RF5112A_FIXED_BIAS_A},
+	{6, AR5K_RF_FIXED_BIAS_B,	AR5K_RF5112A_FIXED_BIAS_B},
+	{6, AR5K_RF_XPD_SEL,		AR5K_RF5112A_XPD_SEL},
+	{6, AR5K_RF_PD_GAIN_LO,		AR5K_RF5112A_PDGAINLO},
+	{6, AR5K_RF_PD_GAIN_HI,		AR5K_RF5112A_PDGAINHI},
+	{6, AR5K_RF_PWD_130,		AR5K_RF5112A_PWD(130)},
+	{6, AR5K_RF_PWD_131,		AR5K_RF5112A_PWD(131)},
+	{6, AR5K_RF_PWD_132,		AR5K_RF5112A_PWD(132)},
+	{6, AR5K_RF_PWD_136,		AR5K_RF5112A_PWD(136)},
+	{6, AR5K_RF_PWD_137,		AR5K_RF5112A_PWD(137)},
+	{6, AR5K_RF_PWD_138,		AR5K_RF5112A_PWD(138)},
+	{6, AR5K_RF_PWD_166,		AR5K_RF5112A_PWD(166)},
+	{6, AR5K_RF_PWD_167,		AR5K_RF5112A_PWD(167)},
+	{6, AR5K_RF_HIGH_VC_CP,		AR5K_RF5112A_HIGH_VC_CP},
+	{6, AR5K_RF_MID_VC_CP,		AR5K_RF5112A_MID_VC_CP},
+	{6, AR5K_RF_LOW_VC_CP,		AR5K_RF5112A_LOW_VC_CP},
+	{6, AR5K_RF_PUSH_UP,		AR5K_RF5112A_PUSH_UP},
+	{6, AR5K_RF_PAD2GND,		AR5K_RF5112A_PAD2GND},
+	{6, AR5K_RF_XB2_LVL,		AR5K_RF5112A_XB2_LVL},
+	{6, AR5K_RF_XB5_LVL,		AR5K_RF5112A_XB5_LVL},
+	{7, AR5K_RF_GAIN_I,		AR5K_RF5112X_GAIN_I},
+	{7, AR5K_RF_MIXVGA_OVR,		AR5K_RF5112X_MIXVGA_OVR},
+	{7, AR5K_RF_MIXGAIN_OVR,	AR5K_RF5112X_MIXGAIN_OVR},
+	{7, AR5K_RF_MIXGAIN_STEP,	AR5K_RF5112X_MIXGAIN_STEP},
+	{7, AR5K_RF_PD_DELAY_A,		AR5K_RF5112X_PD_DELAY_A},
+	{7, AR5K_RF_PD_DELAY_B,		AR5K_RF5112X_PD_DELAY_B},
+	{7, AR5K_RF_PD_DELAY_XR,	AR5K_RF5112X_PD_DELAY_XR},
+	{7, AR5K_RF_PD_PERIOD_A,	AR5K_RF5112X_PD_PERIOD_A},
+	{7, AR5K_RF_PD_PERIOD_B,	AR5K_RF5112X_PD_PERIOD_B},
+	{7, AR5K_RF_PD_PERIOD_XR,	AR5K_RF5112X_PD_PERIOD_XR},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+	{ 3, 0x98dc,
+	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c,
+	    { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
+	{ 6, 0x989c,
+	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c,
+	    { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
+	{ 6, 0x989c,
+	    { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
+	{ 6, 0x989c,
+	    { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
+	{ 6, 0x989c,
+	    { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
+	{ 6, 0x989c,
+	    { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
+	{ 6, 0x989c,
+	    { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } },
+	{ 6, 0x989c,
+	    { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
+	{ 6, 0x989c,
+	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c,
+	    { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
+	{ 6, 0x989c,
+	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+	{ 6, 0x989c,
+	    { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } },
+	{ 6, 0x989c,
+	    { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+	{ 6, 0x989c,
+	    { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
+	{ 6, 0x989c,
+	    { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
+	{ 6, 0x989c,
+	    { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
+	{ 6, 0x989c,
+	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c,
+	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+	{ 6, 0x989c,
+	    { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
+	{ 6, 0x989c,
+	    { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
+	{ 6, 0x989c,
+	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+	{ 6, 0x989c,
+	    { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
+	{ 6, 0x989c,
+	    { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
+	{ 6, 0x989c,
+	    { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } },
+	{ 6, 0x989c,
+	    { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } },
+	{ 6, 0x989c,
+	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
+	{ 6, 0x989c,
+	    { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
+	{ 6, 0x989c,
+	    { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
+	{ 6, 0x989c,
+	    { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
+	{ 6, 0x989c,
+	    { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
+	{ 6, 0x98d8,
+	    { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
+	{ 7, 0x989c,
+	    { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+	{ 7, 0x989c,
+	    { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+	{ 7, 0x989c,
+	    { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
+	{ 7, 0x989c,
+	    { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+	{ 7, 0x989c,
+	    { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
+	{ 7, 0x989c,
+	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+	{ 7, 0x989c,
+	    { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+	{ 7, 0x989c,
+	    { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
+	{ 7, 0x989c,
+	    { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
+	{ 7, 0x989c,
+	    { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+	{ 7, 0x989c,
+	    { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+	{ 7, 0x989c,
+	    { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+	{ 7, 0x98c4,
+	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+
+
+/******************\
+* RF2413 (Griffin) *
+\******************/
+
+/* BANK 6 				len  pos col */
+#define	AR5K_RF2413_OB_2GHZ		{ 3, 168, 0 }
+#define	AR5K_RF2413_DB_2GHZ		{ 3, 165, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2413[] = {
+	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2413_OB_2GHZ},
+	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2413_DB_2GHZ},
+};
+
+/* Default mode specific settings
+ * XXX: a/aTurbo ???
+ */
+static const struct ath5k_ini_rfbuffer rfb_2413[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+	{ 3, 0x98dc,
+	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c,
+	    { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } },
+	{ 6, 0x989c,
+	    { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } },
+	{ 6, 0x989c,
+	    { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } },
+	{ 6, 0x989c,
+	    { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } },
+	{ 6, 0x989c,
+	    { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } },
+	{ 6, 0x989c,
+	    { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } },
+	{ 6, 0x989c,
+	    { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
+	{ 6, 0x989c,
+	    { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } },
+	{ 6, 0x989c,
+	    { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } },
+	{ 6, 0x989c,
+	    { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } },
+	{ 6, 0x989c,
+	    { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } },
+	{ 6, 0x989c,
+	    { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } },
+	{ 6, 0x989c,
+	    { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } },
+	{ 6, 0x98d8,
+	    { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } },
+	{ 7, 0x989c,
+	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c,
+	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc,
+	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***************************\
+* RF2315/RF2316 (Cobra SoC) *
+\***************************/
+
+/* BANK 6				len  pos col */
+#define	AR5K_RF2316_OB_2GHZ		{ 3, 178, 0 }
+#define	AR5K_RF2316_DB_2GHZ		{ 3, 175, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2316[] = {
+	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2316_OB_2GHZ},
+	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2316_DB_2GHZ},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_2316[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+	{ 3, 0x98dc,
+	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } },
+	{ 6, 0x989c,
+	    { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
+	{ 6, 0x989c,
+	    { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } },
+	{ 6, 0x989c,
+	    { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } },
+	{ 6, 0x989c,
+	    { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } },
+	{ 6, 0x989c,
+	    { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } },
+	{ 6, 0x989c,
+	    { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
+	{ 6, 0x989c,
+	    { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
+	{ 6, 0x989c,
+	    { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } },
+	{ 6, 0x989c,
+	    { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } },
+	{ 6, 0x989c,
+	    { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } },
+	{ 6, 0x989c,
+	    { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } },
+	{ 6, 0x989c,
+	    { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } },
+	{ 6, 0x989c,
+	    { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } },
+	{ 6, 0x989c,
+	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+	{ 6, 0x989c,
+	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+	{ 6, 0x989c,
+	    { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } },
+	{ 6, 0x989c,
+	    { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } },
+	{ 6, 0x98c0,
+	    { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
+	{ 7, 0x989c,
+	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c,
+	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc,
+	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/******************************\
+* RF5413/RF5424 (Eagle/Condor) *
+\******************************/
+
+/* BANK 6				len  pos col */
+#define	AR5K_RF5413_OB_2GHZ		{ 3, 241, 0 }
+#define	AR5K_RF5413_DB_2GHZ		{ 3, 238, 0 }
+
+#define	AR5K_RF5413_OB_5GHZ		{ 3, 247, 0 }
+#define	AR5K_RF5413_DB_5GHZ		{ 3, 244, 0 }
+
+#define	AR5K_RF5413_PWD_ICLOBUF2G	{ 3, 131, 3 }
+#define	AR5K_RF5413_DERBY_CHAN_SEL_MODE	{ 1, 291, 2 }
+
+static const struct ath5k_rf_reg rf_regs_5413[] = {
+	{6, AR5K_RF_OB_2GHZ,		 AR5K_RF5413_OB_2GHZ},
+	{6, AR5K_RF_DB_2GHZ,		 AR5K_RF5413_DB_2GHZ},
+	{6, AR5K_RF_OB_5GHZ,		 AR5K_RF5413_OB_5GHZ},
+	{6, AR5K_RF_DB_5GHZ,		 AR5K_RF5413_DB_5GHZ},
+	{6, AR5K_RF_PWD_ICLOBUF_2G,	 AR5K_RF5413_PWD_ICLOBUF2G},
+	{6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE},
+};
+
+/* Default mode specific settings */
+static const struct ath5k_ini_rfbuffer rfb_5413[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+	{ 3, 0x98dc,
+	    { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
+	{ 6, 0x989c,
+	    { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
+	{ 6, 0x989c,
+	    { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
+	{ 6, 0x989c,
+	    { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
+	{ 6, 0x989c,
+	    { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+	{ 6, 0x989c,
+	    { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+	{ 6, 0x989c,
+	    { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
+	{ 6, 0x989c,
+	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c,
+	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c,
+	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c,
+	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+	{ 6, 0x989c,
+	    { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
+	{ 6, 0x989c,
+	    { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
+	{ 6, 0x989c,
+	    { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
+	{ 6, 0x989c,
+	    { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
+	{ 6, 0x989c,
+	    { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
+	{ 6, 0x989c,
+	    { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
+	{ 6, 0x989c,
+	    { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
+	{ 6, 0x989c,
+	    { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
+	{ 6, 0x989c,
+	    { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+	{ 6, 0x989c,
+	    { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
+	{ 6, 0x989c,
+	    { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
+	{ 6, 0x989c,
+	    { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
+	{ 6, 0x989c,
+	    { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
+	{ 6, 0x989c,
+	    { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } },
+	{ 6, 0x989c,
+	    { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
+	{ 6, 0x989c,
+	    { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } },
+	{ 6, 0x98c8,
+	    { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
+	{ 7, 0x989c,
+	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c,
+	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc,
+	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+
+/***************************\
+* RF2425/RF2417 (Swan/Nala) *
+* AR2317 (Spider SoC)       *
+\***************************/
+
+/* BANK 6				len  pos col */
+#define	AR5K_RF2425_OB_2GHZ		{ 3, 193, 0 }
+#define	AR5K_RF2425_DB_2GHZ		{ 3, 190, 0 }
+
+static const struct ath5k_rf_reg rf_regs_2425[] = {
+	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2425_OB_2GHZ},
+	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2425_DB_2GHZ},
+};
+
+/* Default mode specific settings
+ * XXX: a/aTurbo ?
+ */
+static const struct ath5k_ini_rfbuffer rfb_2425[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
+	{ 3, 0x98dc,
+	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c,
+	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+	{ 6, 0x989c,
+	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+	{ 6, 0x989c,
+	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c,
+	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+	{ 6, 0x989c,
+	    { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
+	{ 6, 0x989c,
+	    { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
+	{ 6, 0x989c,
+	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+	{ 6, 0x989c,
+	    { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
+	{ 6, 0x989c,
+	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+	{ 6, 0x989c,
+	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+	{ 6, 0x989c,
+	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+	{ 6, 0x989c,
+	    { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
+	{ 6, 0x98c4,
+	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+	{ 7, 0x989c,
+	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c,
+	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc,
+	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+/*
+ * TODO: Handle the few differences with swan during
+ * bank modification and get rid of this
+ */
+static const struct ath5k_ini_rfbuffer rfb_2317[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
+	{ 3, 0x98dc,
+	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c,
+	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+	{ 6, 0x989c,
+	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+	{ 6, 0x989c,
+	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c,
+	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+	{ 6, 0x989c,
+	    { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
+	{ 6, 0x989c,
+	    { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } },
+	{ 6, 0x989c,
+	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+	{ 6, 0x989c,
+	    { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
+	{ 6, 0x989c,
+	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+	{ 6, 0x989c,
+	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+	{ 6, 0x989c,
+	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+	{ 6, 0x989c,
+	    { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } },
+	{ 6, 0x98c4,
+	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+	{ 7, 0x989c,
+	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c,
+	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc,
+	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+/*
+ * TODO: Handle the few differences with swan during
+ * bank modification and get rid of this
+ * XXX: a/aTurbo ?
+ */
+static const struct ath5k_ini_rfbuffer rfb_2417[] = {
+	{ 1, 0x98d4,
+	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
+	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+	{ 2, 0x98d0,
+	    { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
+	{ 3, 0x98dc,
+	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+	{ 6, 0x989c,
+	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
+	{ 6, 0x989c,
+	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
+	{ 6, 0x989c,
+	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+	{ 6, 0x989c,
+	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
+	{ 6, 0x989c,
+	    { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } },
+	{ 6, 0x989c,
+	    { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
+	{ 6, 0x989c,
+	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
+	{ 6, 0x989c,
+	    { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } },
+	{ 6, 0x989c,
+	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
+	{ 6, 0x989c,
+	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
+	{ 6, 0x989c,
+	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+	{ 6, 0x989c,
+	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
+	{ 6, 0x989c,
+	    { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
+	{ 6, 0x98c4,
+	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+	{ 7, 0x989c,
+	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+	{ 7, 0x989c,
+	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+	{ 7, 0x98cc,
+	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/rfgain.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/rfgain.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/rfgain.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/rfgain.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,516 @@
+/*
+ * RF Gain optimization
+ *
+ * Copyright (c) 2004-2009 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Mode-specific RF Gain table (64bytes) for RF5111/5112
+ * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
+ * RF Gain values are included in AR5K_AR5210_INI)
+ */
+struct ath5k_ini_rfgain {
+	u16	rfg_register;	/* RF Gain register address */
+	u32	rfg_value[2];	/* [freq (see below)] */
+};
+
+/* Initial RF Gain settings for RF5111 */
+static const struct ath5k_ini_rfgain rfgain_5111[] = {
+	/*			      5Ghz	2Ghz	*/
+	{ AR5K_RF_GAIN(0),	{ 0x000001a9, 0x00000000 } },
+	{ AR5K_RF_GAIN(1),	{ 0x000001e9, 0x00000040 } },
+	{ AR5K_RF_GAIN(2),	{ 0x00000029, 0x00000080 } },
+	{ AR5K_RF_GAIN(3),	{ 0x00000069, 0x00000150 } },
+	{ AR5K_RF_GAIN(4),	{ 0x00000199, 0x00000190 } },
+	{ AR5K_RF_GAIN(5),	{ 0x000001d9, 0x000001d0 } },
+	{ AR5K_RF_GAIN(6),	{ 0x00000019, 0x00000010 } },
+	{ AR5K_RF_GAIN(7),	{ 0x00000059, 0x00000044 } },
+	{ AR5K_RF_GAIN(8),	{ 0x00000099, 0x00000084 } },
+	{ AR5K_RF_GAIN(9),	{ 0x000001a5, 0x00000148 } },
+	{ AR5K_RF_GAIN(10),	{ 0x000001e5, 0x00000188 } },
+	{ AR5K_RF_GAIN(11),	{ 0x00000025, 0x000001c8 } },
+	{ AR5K_RF_GAIN(12),	{ 0x000001c8, 0x00000014 } },
+	{ AR5K_RF_GAIN(13),	{ 0x00000008, 0x00000042 } },
+	{ AR5K_RF_GAIN(14),	{ 0x00000048, 0x00000082 } },
+	{ AR5K_RF_GAIN(15),	{ 0x00000088, 0x00000178 } },
+	{ AR5K_RF_GAIN(16),	{ 0x00000198, 0x000001b8 } },
+	{ AR5K_RF_GAIN(17),	{ 0x000001d8, 0x000001f8 } },
+	{ AR5K_RF_GAIN(18),	{ 0x00000018, 0x00000012 } },
+	{ AR5K_RF_GAIN(19),	{ 0x00000058, 0x00000052 } },
+	{ AR5K_RF_GAIN(20),	{ 0x00000098, 0x00000092 } },
+	{ AR5K_RF_GAIN(21),	{ 0x000001a4, 0x0000017c } },
+	{ AR5K_RF_GAIN(22),	{ 0x000001e4, 0x000001bc } },
+	{ AR5K_RF_GAIN(23),	{ 0x00000024, 0x000001fc } },
+	{ AR5K_RF_GAIN(24),	{ 0x00000064, 0x0000000a } },
+	{ AR5K_RF_GAIN(25),	{ 0x000000a4, 0x0000004a } },
+	{ AR5K_RF_GAIN(26),	{ 0x000000e4, 0x0000008a } },
+	{ AR5K_RF_GAIN(27),	{ 0x0000010a, 0x0000015a } },
+	{ AR5K_RF_GAIN(28),	{ 0x0000014a, 0x0000019a } },
+	{ AR5K_RF_GAIN(29),	{ 0x0000018a, 0x000001da } },
+	{ AR5K_RF_GAIN(30),	{ 0x000001ca, 0x0000000e } },
+	{ AR5K_RF_GAIN(31),	{ 0x0000000a, 0x0000004e } },
+	{ AR5K_RF_GAIN(32),	{ 0x0000004a, 0x0000008e } },
+	{ AR5K_RF_GAIN(33),	{ 0x0000008a, 0x0000015e } },
+	{ AR5K_RF_GAIN(34),	{ 0x000001ba, 0x0000019e } },
+	{ AR5K_RF_GAIN(35),	{ 0x000001fa, 0x000001de } },
+	{ AR5K_RF_GAIN(36),	{ 0x0000003a, 0x00000009 } },
+	{ AR5K_RF_GAIN(37),	{ 0x0000007a, 0x00000049 } },
+	{ AR5K_RF_GAIN(38),	{ 0x00000186, 0x00000089 } },
+	{ AR5K_RF_GAIN(39),	{ 0x000001c6, 0x00000179 } },
+	{ AR5K_RF_GAIN(40),	{ 0x00000006, 0x000001b9 } },
+	{ AR5K_RF_GAIN(41),	{ 0x00000046, 0x000001f9 } },
+	{ AR5K_RF_GAIN(42),	{ 0x00000086, 0x00000039 } },
+	{ AR5K_RF_GAIN(43),	{ 0x000000c6, 0x00000079 } },
+	{ AR5K_RF_GAIN(44),	{ 0x000000c6, 0x000000b9 } },
+	{ AR5K_RF_GAIN(45),	{ 0x000000c6, 0x000001bd } },
+	{ AR5K_RF_GAIN(46),	{ 0x000000c6, 0x000001fd } },
+	{ AR5K_RF_GAIN(47),	{ 0x000000c6, 0x0000003d } },
+	{ AR5K_RF_GAIN(48),	{ 0x000000c6, 0x0000007d } },
+	{ AR5K_RF_GAIN(49),	{ 0x000000c6, 0x000000bd } },
+	{ AR5K_RF_GAIN(50),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(51),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(52),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(53),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(54),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(55),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(56),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(57),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(58),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(59),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(60),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(61),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(62),	{ 0x000000c6, 0x000000fd } },
+	{ AR5K_RF_GAIN(63),	{ 0x000000c6, 0x000000fd } },
+};
+
+/* Initial RF Gain settings for RF5112 */
+static const struct ath5k_ini_rfgain rfgain_5112[] = {
+	/*			      5Ghz	2Ghz	*/
+	{ AR5K_RF_GAIN(0),	{ 0x00000007, 0x00000007 } },
+	{ AR5K_RF_GAIN(1),	{ 0x00000047, 0x00000047 } },
+	{ AR5K_RF_GAIN(2),	{ 0x00000087, 0x00000087 } },
+	{ AR5K_RF_GAIN(3),	{ 0x000001a0, 0x000001a0 } },
+	{ AR5K_RF_GAIN(4),	{ 0x000001e0, 0x000001e0 } },
+	{ AR5K_RF_GAIN(5),	{ 0x00000020, 0x00000020 } },
+	{ AR5K_RF_GAIN(6),	{ 0x00000060, 0x00000060 } },
+	{ AR5K_RF_GAIN(7),	{ 0x000001a1, 0x000001a1 } },
+	{ AR5K_RF_GAIN(8),	{ 0x000001e1, 0x000001e1 } },
+	{ AR5K_RF_GAIN(9),	{ 0x00000021, 0x00000021 } },
+	{ AR5K_RF_GAIN(10),	{ 0x00000061, 0x00000061 } },
+	{ AR5K_RF_GAIN(11),	{ 0x00000162, 0x00000162 } },
+	{ AR5K_RF_GAIN(12),	{ 0x000001a2, 0x000001a2 } },
+	{ AR5K_RF_GAIN(13),	{ 0x000001e2, 0x000001e2 } },
+	{ AR5K_RF_GAIN(14),	{ 0x00000022, 0x00000022 } },
+	{ AR5K_RF_GAIN(15),	{ 0x00000062, 0x00000062 } },
+	{ AR5K_RF_GAIN(16),	{ 0x00000163, 0x00000163 } },
+	{ AR5K_RF_GAIN(17),	{ 0x000001a3, 0x000001a3 } },
+	{ AR5K_RF_GAIN(18),	{ 0x000001e3, 0x000001e3 } },
+	{ AR5K_RF_GAIN(19),	{ 0x00000023, 0x00000023 } },
+	{ AR5K_RF_GAIN(20),	{ 0x00000063, 0x00000063 } },
+	{ AR5K_RF_GAIN(21),	{ 0x00000184, 0x00000184 } },
+	{ AR5K_RF_GAIN(22),	{ 0x000001c4, 0x000001c4 } },
+	{ AR5K_RF_GAIN(23),	{ 0x00000004, 0x00000004 } },
+	{ AR5K_RF_GAIN(24),	{ 0x000001ea, 0x0000000b } },
+	{ AR5K_RF_GAIN(25),	{ 0x0000002a, 0x0000004b } },
+	{ AR5K_RF_GAIN(26),	{ 0x0000006a, 0x0000008b } },
+	{ AR5K_RF_GAIN(27),	{ 0x000000aa, 0x000001ac } },
+	{ AR5K_RF_GAIN(28),	{ 0x000001ab, 0x000001ec } },
+	{ AR5K_RF_GAIN(29),	{ 0x000001eb, 0x0000002c } },
+	{ AR5K_RF_GAIN(30),	{ 0x0000002b, 0x00000012 } },
+	{ AR5K_RF_GAIN(31),	{ 0x0000006b, 0x00000052 } },
+	{ AR5K_RF_GAIN(32),	{ 0x000000ab, 0x00000092 } },
+	{ AR5K_RF_GAIN(33),	{ 0x000001ac, 0x00000193 } },
+	{ AR5K_RF_GAIN(34),	{ 0x000001ec, 0x000001d3 } },
+	{ AR5K_RF_GAIN(35),	{ 0x0000002c, 0x00000013 } },
+	{ AR5K_RF_GAIN(36),	{ 0x0000003a, 0x00000053 } },
+	{ AR5K_RF_GAIN(37),	{ 0x0000007a, 0x00000093 } },
+	{ AR5K_RF_GAIN(38),	{ 0x000000ba, 0x00000194 } },
+	{ AR5K_RF_GAIN(39),	{ 0x000001bb, 0x000001d4 } },
+	{ AR5K_RF_GAIN(40),	{ 0x000001fb, 0x00000014 } },
+	{ AR5K_RF_GAIN(41),	{ 0x0000003b, 0x0000003a } },
+	{ AR5K_RF_GAIN(42),	{ 0x0000007b, 0x0000007a } },
+	{ AR5K_RF_GAIN(43),	{ 0x000000bb, 0x000000ba } },
+	{ AR5K_RF_GAIN(44),	{ 0x000001bc, 0x000001bb } },
+	{ AR5K_RF_GAIN(45),	{ 0x000001fc, 0x000001fb } },
+	{ AR5K_RF_GAIN(46),	{ 0x0000003c, 0x0000003b } },
+	{ AR5K_RF_GAIN(47),	{ 0x0000007c, 0x0000007b } },
+	{ AR5K_RF_GAIN(48),	{ 0x000000bc, 0x000000bb } },
+	{ AR5K_RF_GAIN(49),	{ 0x000000fc, 0x000001bc } },
+	{ AR5K_RF_GAIN(50),	{ 0x000000fc, 0x000001fc } },
+	{ AR5K_RF_GAIN(51),	{ 0x000000fc, 0x0000003c } },
+	{ AR5K_RF_GAIN(52),	{ 0x000000fc, 0x0000007c } },
+	{ AR5K_RF_GAIN(53),	{ 0x000000fc, 0x000000bc } },
+	{ AR5K_RF_GAIN(54),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(55),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(56),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(57),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(58),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(59),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(60),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(61),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(62),	{ 0x000000fc, 0x000000fc } },
+	{ AR5K_RF_GAIN(63),	{ 0x000000fc, 0x000000fc } },
+};
+
+/* Initial RF Gain settings for RF2413 */
+static const struct ath5k_ini_rfgain rfgain_2413[] = {
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
+	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
+	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
+	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x00000181 } },
+	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000001c1 } },
+	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x00000001 } },
+	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000041 } },
+	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000081 } },
+	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000168 } },
+	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x000001a8 } },
+	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x000001e8 } },
+	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x00000028 } },
+	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000068 } },
+	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000189 } },
+	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000001c9 } },
+	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x00000009 } },
+	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x00000049 } },
+	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000089 } },
+	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x00000190 } },
+	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x000001d0 } },
+	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x00000010 } },
+	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x00000050 } },
+	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000090 } },
+	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x00000191 } },
+	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000001d1 } },
+	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x00000011 } },
+	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x00000051 } },
+	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x00000091 } },
+	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x00000178 } },
+	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x000001b8 } },
+	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x000001f8 } },
+	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x00000038 } },
+	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x00000078 } },
+	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x00000199 } },
+	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x000001d9 } },
+	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x00000019 } },
+	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x00000059 } },
+	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x00000099 } },
+	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000d9 } },
+	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f9 } },
+};
+
+/* Initial RF Gain settings for AR2316 */
+static const struct ath5k_ini_rfgain rfgain_2316[] = {
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
+	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
+	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
+	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x000000c0 } },
+	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000000e0 } },
+	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x000000e0 } },
+	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000128 } },
+	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000128 } },
+	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000128 } },
+	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x00000168 } },
+	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x000001a8 } },
+	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x000001e8 } },
+	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000028 } },
+	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000068 } },
+	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000000a8 } },
+	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x000000e8 } },
+	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x000000e8 } },
+	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000130 } },
+	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x00000130 } },
+	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x00000170 } },
+	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x000001b0 } },
+	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x000001f0 } },
+	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000030 } },
+	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x00000070 } },
+	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000000b0 } },
+	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f0 } },
+	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f0 } },
+};
+
+
+/* Initial RF Gain settings for RF5413 */
+static const struct ath5k_ini_rfgain rfgain_5413[] = {
+	/*			      5Ghz	2Ghz	*/
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
+	{ AR5K_RF_GAIN(1),	{ 0x00000040, 0x00000040 } },
+	{ AR5K_RF_GAIN(2),	{ 0x00000080, 0x00000080 } },
+	{ AR5K_RF_GAIN(3),	{ 0x000001a1, 0x00000161 } },
+	{ AR5K_RF_GAIN(4),	{ 0x000001e1, 0x000001a1 } },
+	{ AR5K_RF_GAIN(5),	{ 0x00000021, 0x000001e1 } },
+	{ AR5K_RF_GAIN(6),	{ 0x00000061, 0x00000021 } },
+	{ AR5K_RF_GAIN(7),	{ 0x00000188, 0x00000061 } },
+	{ AR5K_RF_GAIN(8),	{ 0x000001c8, 0x00000188 } },
+	{ AR5K_RF_GAIN(9),	{ 0x00000008, 0x000001c8 } },
+	{ AR5K_RF_GAIN(10),	{ 0x00000048, 0x00000008 } },
+	{ AR5K_RF_GAIN(11),	{ 0x00000088, 0x00000048 } },
+	{ AR5K_RF_GAIN(12),	{ 0x000001a9, 0x00000088 } },
+	{ AR5K_RF_GAIN(13),	{ 0x000001e9, 0x00000169 } },
+	{ AR5K_RF_GAIN(14),	{ 0x00000029, 0x000001a9 } },
+	{ AR5K_RF_GAIN(15),	{ 0x00000069, 0x000001e9 } },
+	{ AR5K_RF_GAIN(16),	{ 0x000001d0, 0x00000029 } },
+	{ AR5K_RF_GAIN(17),	{ 0x00000010, 0x00000069 } },
+	{ AR5K_RF_GAIN(18),	{ 0x00000050, 0x00000190 } },
+	{ AR5K_RF_GAIN(19),	{ 0x00000090, 0x000001d0 } },
+	{ AR5K_RF_GAIN(20),	{ 0x000001b1, 0x00000010 } },
+	{ AR5K_RF_GAIN(21),	{ 0x000001f1, 0x00000050 } },
+	{ AR5K_RF_GAIN(22),	{ 0x00000031, 0x00000090 } },
+	{ AR5K_RF_GAIN(23),	{ 0x00000071, 0x00000171 } },
+	{ AR5K_RF_GAIN(24),	{ 0x000001b8, 0x000001b1 } },
+	{ AR5K_RF_GAIN(25),	{ 0x000001f8, 0x000001f1 } },
+	{ AR5K_RF_GAIN(26),	{ 0x00000038, 0x00000031 } },
+	{ AR5K_RF_GAIN(27),	{ 0x00000078, 0x00000071 } },
+	{ AR5K_RF_GAIN(28),	{ 0x00000199, 0x00000198 } },
+	{ AR5K_RF_GAIN(29),	{ 0x000001d9, 0x000001d8 } },
+	{ AR5K_RF_GAIN(30),	{ 0x00000019, 0x00000018 } },
+	{ AR5K_RF_GAIN(31),	{ 0x00000059, 0x00000058 } },
+	{ AR5K_RF_GAIN(32),	{ 0x00000099, 0x00000098 } },
+	{ AR5K_RF_GAIN(33),	{ 0x000000d9, 0x00000179 } },
+	{ AR5K_RF_GAIN(34),	{ 0x000000f9, 0x000001b9 } },
+	{ AR5K_RF_GAIN(35),	{ 0x000000f9, 0x000001f9 } },
+	{ AR5K_RF_GAIN(36),	{ 0x000000f9, 0x00000039 } },
+	{ AR5K_RF_GAIN(37),	{ 0x000000f9, 0x00000079 } },
+	{ AR5K_RF_GAIN(38),	{ 0x000000f9, 0x000000b9 } },
+	{ AR5K_RF_GAIN(39),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(40),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(41),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(42),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(43),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(44),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(45),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(46),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(47),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(48),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(49),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(50),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(51),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(52),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(53),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(54),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(55),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(56),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(57),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(58),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(59),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(60),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(61),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(62),	{ 0x000000f9, 0x000000f9 } },
+	{ AR5K_RF_GAIN(63),	{ 0x000000f9, 0x000000f9 } },
+};
+
+
+/* Initial RF Gain settings for RF2425 */
+static const struct ath5k_ini_rfgain rfgain_2425[] = {
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
+	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
+	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
+	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x00000181 } },
+	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000001c1 } },
+	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x00000001 } },
+	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000041 } },
+	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000081 } },
+	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000188 } },
+	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x000001c8 } },
+	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x00000008 } },
+	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x00000048 } },
+	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000088 } },
+	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000189 } },
+	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000001c9 } },
+	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x00000009 } },
+	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x00000049 } },
+	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000089 } },
+	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x000001b0 } },
+	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x000001f0 } },
+	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x00000030 } },
+	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x00000070 } },
+	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000171 } },
+	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x000001b1 } },
+	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000001f1 } },
+	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x00000031 } },
+	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x00000071 } },
+	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x000001b8 } },
+	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x000001f8 } },
+	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x00000038 } },
+	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x00000078 } },
+	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x000000b8 } },
+	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x000001b9 } },
+	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x000001f9 } },
+	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x00000039 } },
+	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x00000079 } },
+	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x000000b9 } },
+	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f9 } },
+	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f9 } },
+};
+
+#define AR5K_GAIN_CRN_FIX_BITS_5111		4
+#define AR5K_GAIN_CRN_FIX_BITS_5112		7
+#define AR5K_GAIN_CRN_MAX_FIX_BITS		AR5K_GAIN_CRN_FIX_BITS_5112
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN		15
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN		20
+#define AR5K_GAIN_CCK_PROBE_CORR		5
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA		15
+#define AR5K_GAIN_STEP_COUNT			10
+
+/* Check if our current measurement is inside our
+ * current variable attenuation window */
+#define AR5K_GAIN_CHECK_ADJUST(_g) 		\
+	((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
+
+struct ath5k_gain_opt_step {
+	s8				gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
+	s8				gos_gain;
+};
+
+struct ath5k_gain_opt {
+	u8				go_default;
+	u8				go_steps_count;
+	const struct ath5k_gain_opt_step	go_step[AR5K_GAIN_STEP_COUNT];
+};
+
+/*
+ * Parameters on gos_param:
+ * 1) Tx clip PHY register
+ * 2) PWD 90 RF register
+ * 3) PWD 84 RF register
+ * 4) RFGainSel RF register
+ */
+static const struct ath5k_gain_opt rfgain_opt_5111 = {
+	4,
+	9,
+	{
+		{ { 4, 1, 1, 1 }, 6 },
+		{ { 4, 0, 1, 1 }, 4 },
+		{ { 3, 1, 1, 1 }, 3 },
+		{ { 4, 0, 0, 1 }, 1 },
+		{ { 4, 1, 1, 0 }, 0 },
+		{ { 4, 0, 1, 0 }, -2 },
+		{ { 3, 1, 1, 0 }, -3 },
+		{ { 4, 0, 0, 0 }, -4 },
+		{ { 2, 1, 1, 0 }, -6 }
+	}
+};
+
+/*
+ * Parameters on gos_param:
+ * 1) Mixgain ovr RF register
+ * 2) PWD 138 RF register
+ * 3) PWD 137 RF register
+ * 4) PWD 136 RF register
+ * 5) PWD 132 RF register
+ * 6) PWD 131 RF register
+ * 7) PWD 130 RF register
+ */
+static const struct ath5k_gain_opt rfgain_opt_5112 = {
+	1,
+	8,
+	{
+		{ { 3, 0, 0, 0, 0, 0, 0 }, 6 },
+		{ { 2, 0, 0, 0, 0, 0, 0 }, 0 },
+		{ { 1, 0, 0, 0, 0, 0, 0 }, -3 },
+		{ { 0, 0, 0, 0, 0, 0, 0 }, -6 },
+		{ { 0, 1, 1, 0, 0, 0, 0 }, -8 },
+		{ { 0, 1, 1, 0, 1, 1, 0 }, -10 },
+		{ { 0, 1, 0, 1, 1, 1, 0 }, -13 },
+		{ { 0, 1, 0, 1, 1, 0, 1 }, -16 },
+	}
+};
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/rfkill.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/rfkill.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath5k/rfkill.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath5k/rfkill.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,121 @@
+/*
+ * RFKILL support for ath5k
+ *
+ * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include "base.h"
+
+
+static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+{
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n",
+		sc->rf_kill.gpio, sc->rf_kill.polarity);
+	ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+	ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
+}
+
+
+static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
+{
+	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n",
+		sc->rf_kill.gpio, sc->rf_kill.polarity);
+	ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+	ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
+}
+
+static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable)
+{
+	struct ath5k_hw *ah = sc->ah;
+	u32 curval;
+
+	ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
+	curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
+	ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+					!!curval : !curval);
+}
+
+static bool
+ath5k_is_rfkill_set(struct ath5k_softc *sc)
+{
+	/* configuring GPIO for input for some reason disables rfkill */
+	/*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
+	return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
+							sc->rf_kill.polarity;
+}
+
+static void
+ath5k_tasklet_rfkill_toggle(unsigned long data)
+{
+	struct ath5k_softc *sc = (void *)data;
+	bool blocked;
+
+	blocked = ath5k_is_rfkill_set(sc);
+	wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked);
+}
+
+
+void
+ath5k_rfkill_hw_start(struct ath5k_hw *ah)
+{
+	struct ath5k_softc *sc = ah->ah_sc;
+
+	/* read rfkill GPIO configuration from EEPROM header */
+	sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
+	sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
+
+	tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
+		(unsigned long)sc);
+
+	ath5k_rfkill_disable(sc);
+
+	/* enable interrupt for rfkill switch */
+	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
+		ath5k_rfkill_set_intr(sc, true);
+}
+
+
+void
+ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
+{
+	struct ath5k_softc *sc = ah->ah_sc;
+
+	/* disable interrupt for rfkill switch */
+	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
+		ath5k_rfkill_set_intr(sc, false);
+
+	tasklet_kill(&sc->rf_kill.toggleq);
+
+	/* enable RFKILL when stopping HW so Wifi LED is turned off */
+	ath5k_rfkill_enable(sc);
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ahb.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ahb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ahb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ahb.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
+#include "ath9k.h"
+
+/* return bus cachesize in 4B word units */
+static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz)
+{
+	*csz = L1_CACHE_BYTES >> 2;
+}
+
+static void ath_ahb_cleanup(struct ath_softc *sc)
+{
+	iounmap(sc->mem);
+}
+
+static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
+{
+	struct ath_softc *sc = ah->ah_sc;
+	struct platform_device *pdev = to_platform_device(sc->dev);
+	struct ath9k_platform_data *pdata;
+
+	pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
+	if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"%s: flash read failed, offset %08x is out of range\n",
+				__func__, off);
+		return false;
+	}
+
+	*data = pdata->eeprom_data[off];
+	return true;
+}
+
+static struct ath_bus_ops ath_ahb_bus_ops  = {
+	.read_cachesize = ath_ahb_read_cachesize,
+	.cleanup = ath_ahb_cleanup,
+
+	.eeprom_read = ath_ahb_eeprom_read,
+};
+
+static int ath_ahb_probe(struct platform_device *pdev)
+{
+	void __iomem *mem;
+	struct ath_wiphy *aphy;
+	struct ath_softc *sc;
+	struct ieee80211_hw *hw;
+	struct resource *res;
+	int irq;
+	int ret = 0;
+	struct ath_hw *ah;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "no platform data specified\n");
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no memory resource found\n");
+		ret = -ENXIO;
+		goto err_out;
+	}
+
+	mem = ioremap_nocache(res->start, res->end - res->start + 1);
+	if (mem == NULL) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no IRQ resource found\n");
+		ret = -ENXIO;
+		goto err_iounmap;
+	}
+
+	irq = res->start;
+
+	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
+				sizeof(struct ath_softc), &ath9k_ops);
+	if (hw == NULL) {
+		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
+		ret = -ENOMEM;
+		goto err_iounmap;
+	}
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+	platform_set_drvdata(pdev, hw);
+
+	aphy = hw->priv;
+	sc = (struct ath_softc *) (aphy + 1);
+	aphy->sc = sc;
+	aphy->hw = hw;
+	sc->pri_wiphy = aphy;
+	sc->hw = hw;
+	sc->dev = &pdev->dev;
+	sc->mem = mem;
+	sc->bus_ops = &ath_ahb_bus_ops;
+	sc->irq = irq;
+
+	ret = ath_attach(AR5416_AR9100_DEVID, sc);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
+		ret = -ENODEV;
+		goto err_free_hw;
+	}
+
+	ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
+	if (ret) {
+		dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret);
+		ret = -EIO;
+		goto err_detach;
+	}
+
+	ah = sc->sc_ah;
+	printk(KERN_INFO
+	       "%s: Atheros AR%s MAC/BB Rev:%x, "
+	       "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n",
+	       wiphy_name(hw->wiphy),
+	       ath_mac_bb_name(ah->hw_version.macVersion),
+	       ah->hw_version.macRev,
+	       ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
+	       ah->hw_version.phyRev,
+	       (unsigned long)mem, irq);
+
+	return 0;
+
+ err_detach:
+	ath_detach(sc);
+ err_free_hw:
+	ieee80211_free_hw(hw);
+	platform_set_drvdata(pdev, NULL);
+ err_iounmap:
+	iounmap(mem);
+ err_out:
+	return ret;
+}
+
+static int ath_ahb_remove(struct platform_device *pdev)
+{
+	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+
+	if (hw) {
+		struct ath_wiphy *aphy = hw->priv;
+		struct ath_softc *sc = aphy->sc;
+
+		ath_cleanup(sc);
+		platform_set_drvdata(pdev, NULL);
+	}
+
+	return 0;
+}
+
+static struct platform_driver ath_ahb_driver = {
+	.probe      = ath_ahb_probe,
+	.remove     = ath_ahb_remove,
+	.driver		= {
+		.name	= "ath9k",
+		.owner	= THIS_MODULE,
+	},
+};
+
+int ath_ahb_init(void)
+{
+	return platform_driver_register(&ath_ahb_driver);
+}
+
+void ath_ahb_exit(void)
+{
+	platform_driver_unregister(&ath_ahb_driver);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ani.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ani.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ani.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ani.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,834 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
+					struct ath9k_channel *chan)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
+		if (ah->ani[i].c &&
+		    ah->ani[i].c->channel == chan->channel)
+			return i;
+		if (ah->ani[i].c == NULL) {
+			ah->ani[i].c = chan;
+			return i;
+		}
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"No more channel states left. Using channel 0\n");
+
+	return 0;
+}
+
+static bool ath9k_hw_ani_control(struct ath_hw *ah,
+				 enum ath9k_ani_cmd cmd, int param)
+{
+	struct ar5416AniState *aniState = ah->curani;
+
+	switch (cmd & ah->ani_function) {
+	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
+		u32 level = param;
+
+		if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"level out of range (%u > %u)\n",
+				level,
+				(unsigned)ARRAY_SIZE(ah->totalSizeDesired));
+			return false;
+		}
+
+		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+			      AR_PHY_DESIRED_SZ_TOT_DES,
+			      ah->totalSizeDesired[level]);
+		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+			      AR_PHY_AGC_CTL1_COARSE_LOW,
+			      ah->coarse_low[level]);
+		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+			      AR_PHY_AGC_CTL1_COARSE_HIGH,
+			      ah->coarse_high[level]);
+		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+			      AR_PHY_FIND_SIG_FIRPWR,
+			      ah->firpwr[level]);
+
+		if (level > aniState->noiseImmunityLevel)
+			ah->stats.ast_ani_niup++;
+		else if (level < aniState->noiseImmunityLevel)
+			ah->stats.ast_ani_nidown++;
+		aniState->noiseImmunityLevel = level;
+		break;
+	}
+	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+		const int m1ThreshLow[] = { 127, 50 };
+		const int m2ThreshLow[] = { 127, 40 };
+		const int m1Thresh[] = { 127, 0x4d };
+		const int m2Thresh[] = { 127, 0x40 };
+		const int m2CountThr[] = { 31, 16 };
+		const int m2CountThrLow[] = { 63, 48 };
+		u32 on = param ? 1 : 0;
+
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+			      m1ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+			      m2ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+			      AR_PHY_SFCORR_M1_THRESH,
+			      m1Thresh[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+			      AR_PHY_SFCORR_M2_THRESH,
+			      m2Thresh[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+			      AR_PHY_SFCORR_M2COUNT_THR,
+			      m2CountThr[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+			      m2CountThrLow[on]);
+
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+			      m1ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+			      m2ThreshLow[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M1_THRESH,
+			      m1Thresh[on]);
+		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+			      AR_PHY_SFCORR_EXT_M2_THRESH,
+			      m2Thresh[on]);
+
+		if (on)
+			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+		else
+			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+		if (!on != aniState->ofdmWeakSigDetectOff) {
+			if (on)
+				ah->stats.ast_ani_ofdmon++;
+			else
+				ah->stats.ast_ani_ofdmoff++;
+			aniState->ofdmWeakSigDetectOff = !on;
+		}
+		break;
+	}
+	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
+		const int weakSigThrCck[] = { 8, 6 };
+		u32 high = param ? 1 : 0;
+
+		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+			      AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
+			      weakSigThrCck[high]);
+		if (high != aniState->cckWeakSigThreshold) {
+			if (high)
+				ah->stats.ast_ani_cckhigh++;
+			else
+				ah->stats.ast_ani_ccklow++;
+			aniState->cckWeakSigThreshold = high;
+		}
+		break;
+	}
+	case ATH9K_ANI_FIRSTEP_LEVEL:{
+		const int firstep[] = { 0, 4, 8 };
+		u32 level = param;
+
+		if (level >= ARRAY_SIZE(firstep)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"level out of range (%u > %u)\n",
+				level,
+				(unsigned) ARRAY_SIZE(firstep));
+			return false;
+		}
+		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+			      AR_PHY_FIND_SIG_FIRSTEP,
+			      firstep[level]);
+		if (level > aniState->firstepLevel)
+			ah->stats.ast_ani_stepup++;
+		else if (level < aniState->firstepLevel)
+			ah->stats.ast_ani_stepdown++;
+		aniState->firstepLevel = level;
+		break;
+	}
+	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+		const int cycpwrThr1[] =
+			{ 2, 4, 6, 8, 10, 12, 14, 16 };
+		u32 level = param;
+
+		if (level >= ARRAY_SIZE(cycpwrThr1)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"level out of range (%u > %u)\n",
+				level,
+				(unsigned)
+				ARRAY_SIZE(cycpwrThr1));
+			return false;
+		}
+		REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+			      AR_PHY_TIMING5_CYCPWR_THR1,
+			      cycpwrThr1[level]);
+		if (level > aniState->spurImmunityLevel)
+			ah->stats.ast_ani_spurup++;
+		else if (level < aniState->spurImmunityLevel)
+			ah->stats.ast_ani_spurdown++;
+		aniState->spurImmunityLevel = level;
+		break;
+	}
+	case ATH9K_ANI_PRESENT:
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"invalid cmd %u\n", cmd);
+		return false;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n");
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
+		"ofdmWeakSigDetectOff=%d\n",
+		aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
+		!aniState->ofdmWeakSigDetectOff);
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"cckWeakSigThreshold=%d, "
+		"firstepLevel=%d, listenTime=%d\n",
+		aniState->cckWeakSigThreshold, aniState->firstepLevel,
+		aniState->listenTime);
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
+		aniState->cycleCount, aniState->ofdmPhyErrCount,
+		aniState->cckPhyErrCount);
+
+	return true;
+}
+
+static void ath9k_hw_update_mibstats(struct ath_hw *ah,
+				     struct ath9k_mib_stats *stats)
+{
+	stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+	stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+	stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+	stats->rts_good += REG_READ(ah, AR_RTS_OK);
+	stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+}
+
+static void ath9k_ani_restart(struct ath_hw *ah)
+{
+	struct ar5416AniState *aniState;
+
+	if (!DO_ANI(ah))
+		return;
+
+	aniState = ah->curani;
+
+	aniState->listenTime = 0;
+	if (ah->has_hw_phycounters) {
+		if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
+			aniState->ofdmPhyErrBase = 0;
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"OFDM Trigger is too high for hw counters\n");
+		} else {
+			aniState->ofdmPhyErrBase =
+				AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+		}
+		if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
+			aniState->cckPhyErrBase = 0;
+			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+				"CCK Trigger is too high for hw counters\n");
+		} else {
+			aniState->cckPhyErrBase =
+				AR_PHY_COUNTMAX - aniState->cckTrigHigh;
+		}
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"Writing ofdmbase=%u   cckbase=%u\n",
+			aniState->ofdmPhyErrBase,
+			aniState->cckPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+		ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+	}
+	aniState->ofdmPhyErrCount = 0;
+	aniState->cckPhyErrCount = 0;
+}
+
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+	struct ar5416AniState *aniState;
+	int32_t rssi;
+
+	if (!DO_ANI(ah))
+		return;
+
+	aniState = ah->curani;
+
+	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+					 aniState->noiseImmunityLevel + 1)) {
+			return;
+		}
+	}
+
+	if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+					 aniState->spurImmunityLevel + 1)) {
+			return;
+		}
+	}
+
+	if (ah->opmode == NL80211_IFTYPE_AP) {
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+		}
+		return;
+	}
+	rssi = BEACON_RSSI(ah);
+	if (rssi > aniState->rssiThrHigh) {
+		if (!aniState->ofdmWeakSigDetectOff) {
+			if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+					 false)) {
+				ath9k_hw_ani_control(ah,
+					ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+				return;
+			}
+		}
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+			return;
+		}
+	} else if (rssi > aniState->rssiThrLow) {
+		if (aniState->ofdmWeakSigDetectOff)
+			ath9k_hw_ani_control(ah,
+				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     true);
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+		return;
+	} else {
+		if (conf->channel->band == IEEE80211_BAND_2GHZ) {
+			if (!aniState->ofdmWeakSigDetectOff)
+				ath9k_hw_ani_control(ah,
+				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     false);
+			if (aniState->firstepLevel > 0)
+				ath9k_hw_ani_control(ah,
+					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
+			return;
+		}
+	}
+}
+
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+	struct ar5416AniState *aniState;
+	int32_t rssi;
+
+	if (!DO_ANI(ah))
+		return;
+
+	aniState = ah->curani;
+	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+					 aniState->noiseImmunityLevel + 1)) {
+			return;
+		}
+	}
+	if (ah->opmode == NL80211_IFTYPE_AP) {
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+		}
+		return;
+	}
+	rssi = BEACON_RSSI(ah);
+	if (rssi > aniState->rssiThrLow) {
+		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+					     aniState->firstepLevel + 1);
+	} else {
+		if (conf->channel->band == IEEE80211_BAND_2GHZ) {
+			if (aniState->firstepLevel > 0)
+				ath9k_hw_ani_control(ah,
+					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
+		}
+	}
+}
+
+static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
+{
+	struct ar5416AniState *aniState;
+	int32_t rssi;
+
+	aniState = ah->curani;
+
+	if (ah->opmode == NL80211_IFTYPE_AP) {
+		if (aniState->firstepLevel > 0) {
+			if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+						 aniState->firstepLevel - 1))
+				return;
+		}
+	} else {
+		rssi = BEACON_RSSI(ah);
+		if (rssi > aniState->rssiThrHigh) {
+			/* XXX: Handle me */
+		} else if (rssi > aniState->rssiThrLow) {
+			if (aniState->ofdmWeakSigDetectOff) {
+				if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+					 true) == true)
+					return;
+			}
+			if (aniState->firstepLevel > 0) {
+				if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_FIRSTEP_LEVEL,
+					 aniState->firstepLevel - 1) == true)
+					return;
+			}
+		} else {
+			if (aniState->firstepLevel > 0) {
+				if (ath9k_hw_ani_control(ah,
+					 ATH9K_ANI_FIRSTEP_LEVEL,
+					 aniState->firstepLevel - 1) == true)
+					return;
+			}
+		}
+	}
+
+	if (aniState->spurImmunityLevel > 0) {
+		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+					 aniState->spurImmunityLevel - 1))
+			return;
+	}
+
+	if (aniState->noiseImmunityLevel > 0) {
+		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+				     aniState->noiseImmunityLevel - 1);
+		return;
+	}
+}
+
+static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
+{
+	struct ar5416AniState *aniState;
+	u32 txFrameCount, rxFrameCount, cycleCount;
+	int32_t listenTime;
+
+	txFrameCount = REG_READ(ah, AR_TFCNT);
+	rxFrameCount = REG_READ(ah, AR_RFCNT);
+	cycleCount = REG_READ(ah, AR_CCCNT);
+
+	aniState = ah->curani;
+	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+
+		listenTime = 0;
+		ah->stats.ast_ani_lzero++;
+	} else {
+		int32_t ccdelta = cycleCount - aniState->cycleCount;
+		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
+		int32_t tfdelta = txFrameCount - aniState->txFrameCount;
+		listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
+	}
+	aniState->cycleCount = cycleCount;
+	aniState->txFrameCount = txFrameCount;
+	aniState->rxFrameCount = rxFrameCount;
+
+	return listenTime;
+}
+
+void ath9k_ani_reset(struct ath_hw *ah)
+{
+	struct ar5416AniState *aniState;
+	struct ath9k_channel *chan = ah->curchan;
+	int index;
+
+	if (!DO_ANI(ah))
+		return;
+
+	index = ath9k_hw_get_ani_channel_idx(ah, chan);
+	aniState = &ah->ani[index];
+	ah->curani = aniState;
+
+	if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
+	    && ah->opmode != NL80211_IFTYPE_ADHOC) {
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"Reset ANI state opmode %u\n", ah->opmode);
+		ah->stats.ast_ani_reset++;
+
+		if (ah->opmode == NL80211_IFTYPE_AP) {
+			/*
+			 * ath9k_hw_ani_control() will only process items set on
+			 * ah->ani_function
+			 */
+			if (IS_CHAN_2GHZ(chan))
+				ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
+						    ATH9K_ANI_FIRSTEP_LEVEL);
+			else
+				ah->ani_function = 0;
+		}
+
+		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     !ATH9K_ANI_USE_OFDM_WEAK_SIG);
+		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+				     ATH9K_ANI_CCK_WEAK_SIG_THR);
+
+		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+				     ATH9K_RX_FILTER_PHYERR);
+
+		if (ah->opmode == NL80211_IFTYPE_AP) {
+			ah->curani->ofdmTrigHigh =
+				ah->config.ofdm_trig_high;
+			ah->curani->ofdmTrigLow =
+				ah->config.ofdm_trig_low;
+			ah->curani->cckTrigHigh =
+				ah->config.cck_trig_high;
+			ah->curani->cckTrigLow =
+				ah->config.cck_trig_low;
+		}
+		ath9k_ani_restart(ah);
+		return;
+	}
+
+	if (aniState->noiseImmunityLevel != 0)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+				     aniState->noiseImmunityLevel);
+	if (aniState->spurImmunityLevel != 0)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+				     aniState->spurImmunityLevel);
+	if (aniState->ofdmWeakSigDetectOff)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+				     !aniState->ofdmWeakSigDetectOff);
+	if (aniState->cckWeakSigThreshold)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+				     aniState->cckWeakSigThreshold);
+	if (aniState->firstepLevel != 0)
+		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+				     aniState->firstepLevel);
+	if (ah->has_hw_phycounters) {
+		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+				     ~ATH9K_RX_FILTER_PHYERR);
+		ath9k_ani_restart(ah);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+	} else {
+		ath9k_ani_restart(ah);
+		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+				     ATH9K_RX_FILTER_PHYERR);
+	}
+}
+
+void ath9k_hw_ani_monitor(struct ath_hw *ah,
+			  const struct ath9k_node_stats *stats,
+			  struct ath9k_channel *chan)
+{
+	struct ar5416AniState *aniState;
+	int32_t listenTime;
+
+	if (!DO_ANI(ah))
+		return;
+
+	aniState = ah->curani;
+	ah->stats.ast_nodestats = *stats;
+
+	listenTime = ath9k_hw_ani_get_listen_time(ah);
+	if (listenTime < 0) {
+		ah->stats.ast_ani_lneg++;
+		ath9k_ani_restart(ah);
+		return;
+	}
+
+	aniState->listenTime += listenTime;
+
+	if (ah->has_hw_phycounters) {
+		u32 phyCnt1, phyCnt2;
+		u32 ofdmPhyErrCnt, cckPhyErrCnt;
+
+		ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
+		phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+		phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+		if (phyCnt1 < aniState->ofdmPhyErrBase ||
+		    phyCnt2 < aniState->cckPhyErrBase) {
+			if (phyCnt1 < aniState->ofdmPhyErrBase) {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+					"phyCnt1 0x%x, resetting "
+					"counter value to 0x%x\n",
+					phyCnt1, aniState->ofdmPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_1,
+					  aniState->ofdmPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_MASK_1,
+					  AR_PHY_ERR_OFDM_TIMING);
+			}
+			if (phyCnt2 < aniState->cckPhyErrBase) {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+					"phyCnt2 0x%x, resetting "
+					"counter value to 0x%x\n",
+					phyCnt2, aniState->cckPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_2,
+					  aniState->cckPhyErrBase);
+				REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+					  AR_PHY_ERR_CCK_TIMING);
+			}
+			return;
+		}
+
+		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+		ah->stats.ast_ani_ofdmerrs +=
+			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+		ah->stats.ast_ani_cckerrs +=
+			cckPhyErrCnt - aniState->cckPhyErrCount;
+		aniState->cckPhyErrCount = cckPhyErrCnt;
+	}
+
+	if (aniState->listenTime > 5 * ah->aniperiod) {
+		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+		    aniState->ofdmTrigLow / 1000 &&
+		    aniState->cckPhyErrCount <= aniState->listenTime *
+		    aniState->cckTrigLow / 1000)
+			ath9k_hw_ani_lower_immunity(ah);
+		ath9k_ani_restart(ah);
+	} else if (aniState->listenTime > ah->aniperiod) {
+		if (aniState->ofdmPhyErrCount > aniState->listenTime *
+		    aniState->ofdmTrigHigh / 1000) {
+			ath9k_hw_ani_ofdm_err_trigger(ah);
+			ath9k_ani_restart(ah);
+		} else if (aniState->cckPhyErrCount >
+			   aniState->listenTime * aniState->cckTrigHigh /
+			   1000) {
+			ath9k_hw_ani_cck_err_trigger(ah);
+			ath9k_ani_restart(ah);
+		}
+	}
+}
+
+bool ath9k_hw_phycounters(struct ath_hw *ah)
+{
+	return ah->has_hw_phycounters ? true : false;
+}
+
+void ath9k_enable_mib_counters(struct ath_hw *ah)
+{
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
+
+	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+
+	REG_WRITE(ah, AR_FILT_OFDM, 0);
+	REG_WRITE(ah, AR_FILT_CCK, 0);
+	REG_WRITE(ah, AR_MIBC,
+		  ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
+		  & 0x0f);
+	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+}
+
+/* Freeze the MIB counters, get the stats and then clear them */
+void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
+{
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
+	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
+	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+	REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
+	REG_WRITE(ah, AR_FILT_OFDM, 0);
+	REG_WRITE(ah, AR_FILT_CCK, 0);
+}
+
+u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
+				  u32 *rxc_pcnt,
+				  u32 *rxf_pcnt,
+				  u32 *txf_pcnt)
+{
+	static u32 cycles, rx_clear, rx_frame, tx_frame;
+	u32 good = 1;
+
+	u32 rc = REG_READ(ah, AR_RCCNT);
+	u32 rf = REG_READ(ah, AR_RFCNT);
+	u32 tf = REG_READ(ah, AR_TFCNT);
+	u32 cc = REG_READ(ah, AR_CCCNT);
+
+	if (cycles == 0 || cycles > cc) {
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"cycle counter wrap. ExtBusy = 0\n");
+		good = 0;
+	} else {
+		u32 cc_d = cc - cycles;
+		u32 rc_d = rc - rx_clear;
+		u32 rf_d = rf - rx_frame;
+		u32 tf_d = tf - tx_frame;
+
+		if (cc_d != 0) {
+			*rxc_pcnt = rc_d * 100 / cc_d;
+			*rxf_pcnt = rf_d * 100 / cc_d;
+			*txf_pcnt = tf_d * 100 / cc_d;
+		} else {
+			good = 0;
+		}
+	}
+
+	cycles = cc;
+	rx_frame = rf;
+	rx_clear = rc;
+	tx_frame = tf;
+
+	return good;
+}
+
+/*
+ * Process a MIB interrupt.  We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void ath9k_hw_procmibevent(struct ath_hw *ah,
+			   const struct ath9k_node_stats *stats)
+{
+	u32 phyCnt1, phyCnt2;
+
+	/* Reset these counters regardless */
+	REG_WRITE(ah, AR_FILT_OFDM, 0);
+	REG_WRITE(ah, AR_FILT_CCK, 0);
+	if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
+		REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+
+	/* Clear the mib counters and save them in the stats */
+	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+	ah->stats.ast_nodestats = *stats;
+
+	if (!DO_ANI(ah))
+		return;
+
+	/* NB: these are not reset-on-read */
+	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+		struct ar5416AniState *aniState = ah->curani;
+		u32 ofdmPhyErrCnt, cckPhyErrCnt;
+
+		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
+		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+		ah->stats.ast_ani_ofdmerrs +=
+			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+		ah->stats.ast_ani_cckerrs +=
+			cckPhyErrCnt - aniState->cckPhyErrCount;
+		aniState->cckPhyErrCount = cckPhyErrCnt;
+
+		/*
+		 * NB: figure out which counter triggered.  If both
+		 * trigger we'll only deal with one as the processing
+		 * clobbers the error counter so the trigger threshold
+		 * check will never be true.
+		 */
+		if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
+			ath9k_hw_ani_ofdm_err_trigger(ah);
+		if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
+			ath9k_hw_ani_cck_err_trigger(ah);
+		/* NB: always restart to insure the h/w counters are reset */
+		ath9k_ani_restart(ah);
+	}
+}
+
+void ath9k_hw_ani_setup(struct ath_hw *ah)
+{
+	int i;
+
+	const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+	const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+	const int coarseLow[] = { -64, -64, -64, -64, -70 };
+	const int firpwr[] = { -78, -78, -78, -78, -80 };
+
+	for (i = 0; i < 5; i++) {
+		ah->totalSizeDesired[i] = totalSizeDesired[i];
+		ah->coarse_high[i] = coarseHigh[i];
+		ah->coarse_low[i] = coarseLow[i];
+		ah->firpwr[i] = firpwr[i];
+	}
+}
+
+void ath9k_hw_ani_attach(struct ath_hw *ah)
+{
+	int i;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
+
+	ah->has_hw_phycounters = 1;
+
+	memset(ah->ani, 0, sizeof(ah->ani));
+	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
+		ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
+		ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
+		ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
+		ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
+		ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+		ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+		ah->ani[i].ofdmWeakSigDetectOff =
+			!ATH9K_ANI_USE_OFDM_WEAK_SIG;
+		ah->ani[i].cckWeakSigThreshold =
+			ATH9K_ANI_CCK_WEAK_SIG_THR;
+		ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+		ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+		if (ah->has_hw_phycounters) {
+			ah->ani[i].ofdmPhyErrBase =
+				AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
+			ah->ani[i].cckPhyErrBase =
+				AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
+		}
+	}
+	if (ah->has_hw_phycounters) {
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"Setting OfdmErrBase = 0x%08x\n",
+			ah->ani[0].ofdmPhyErrBase);
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
+			ah->ani[0].cckPhyErrBase);
+
+		REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
+		REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
+		ath9k_enable_mib_counters(ah);
+	}
+	ah->aniperiod = ATH9K_ANI_PERIOD;
+	if (ah->config.enable_ani)
+		ah->proc_phyerr |= HAL_PROCESS_ANI;
+}
+
+void ath9k_hw_ani_detach(struct ath_hw *ah)
+{
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
+
+	if (ah->has_hw_phycounters) {
+		ath9k_hw_disable_mib_counters(ah);
+		REG_WRITE(ah, AR_PHY_ERR_1, 0);
+		REG_WRITE(ah, AR_PHY_ERR_2, 0);
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ani.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ani.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ani.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ani.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ANI_H
+#define ANI_H
+
+#define HAL_PROCESS_ANI           0x00000001
+#define ATH9K_RSSI_EP_MULTIPLIER  (1<<7)
+
+#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
+
+#define HAL_EP_RND(x, mul)						\
+	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+#define BEACON_RSSI(ahp)					\
+	HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi,	\
+		   ATH9K_RSSI_EP_MULTIPLIER)
+
+#define ATH9K_ANI_OFDM_TRIG_HIGH          500
+#define ATH9K_ANI_OFDM_TRIG_LOW           200
+#define ATH9K_ANI_CCK_TRIG_HIGH           200
+#define ATH9K_ANI_CCK_TRIG_LOW            100
+#define ATH9K_ANI_NOISE_IMMUNE_LVL        4
+#define ATH9K_ANI_USE_OFDM_WEAK_SIG       true
+#define ATH9K_ANI_CCK_WEAK_SIG_THR        false
+#define ATH9K_ANI_SPUR_IMMUNE_LVL         7
+#define ATH9K_ANI_FIRSTEP_LVL             0
+#define ATH9K_ANI_RSSI_THR_HIGH           40
+#define ATH9K_ANI_RSSI_THR_LOW            7
+#define ATH9K_ANI_PERIOD                  100
+
+#define HAL_NOISE_IMMUNE_MAX              4
+#define HAL_SPUR_IMMUNE_MAX               7
+#define HAL_FIRST_STEP_MAX                2
+
+enum ath9k_ani_cmd {
+	ATH9K_ANI_PRESENT = 0x1,
+	ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
+	ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4,
+	ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8,
+	ATH9K_ANI_FIRSTEP_LEVEL = 0x10,
+	ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
+	ATH9K_ANI_MODE = 0x40,
+	ATH9K_ANI_PHYERR_RESET = 0x80,
+	ATH9K_ANI_ALL = 0xff
+};
+
+struct ath9k_mib_stats {
+	u32 ackrcv_bad;
+	u32 rts_bad;
+	u32 rts_good;
+	u32 fcs_bad;
+	u32 beacons;
+};
+
+struct ath9k_node_stats {
+	u32 ns_avgbrssi;
+	u32 ns_avgrssi;
+	u32 ns_avgtxrssi;
+	u32 ns_avgtxrate;
+};
+
+struct ar5416AniState {
+	struct ath9k_channel *c;
+	u8 noiseImmunityLevel;
+	u8 spurImmunityLevel;
+	u8 firstepLevel;
+	u8 ofdmWeakSigDetectOff;
+	u8 cckWeakSigThreshold;
+	u32 listenTime;
+	u32 ofdmTrigHigh;
+	u32 ofdmTrigLow;
+	int32_t cckTrigHigh;
+	int32_t cckTrigLow;
+	int32_t rssiThrLow;
+	int32_t rssiThrHigh;
+	u32 noiseFloor;
+	u32 txFrameCount;
+	u32 rxFrameCount;
+	u32 cycleCount;
+	u32 ofdmPhyErrCount;
+	u32 cckPhyErrCount;
+	u32 ofdmPhyErrBase;
+	u32 cckPhyErrBase;
+	int16_t pktRssi[2];
+	int16_t ofdmErrRssi[2];
+	int16_t cckErrRssi[2];
+};
+
+struct ar5416Stats {
+	u32 ast_ani_niup;
+	u32 ast_ani_nidown;
+	u32 ast_ani_spurup;
+	u32 ast_ani_spurdown;
+	u32 ast_ani_ofdmon;
+	u32 ast_ani_ofdmoff;
+	u32 ast_ani_cckhigh;
+	u32 ast_ani_ccklow;
+	u32 ast_ani_stepup;
+	u32 ast_ani_stepdown;
+	u32 ast_ani_ofdmerrs;
+	u32 ast_ani_cckerrs;
+	u32 ast_ani_reset;
+	u32 ast_ani_lzero;
+	u32 ast_ani_lneg;
+	struct ath9k_mib_stats ast_mibstats;
+	struct ath9k_node_stats ast_nodestats;
+};
+#define ah_mibStats stats.ast_mibstats
+
+void ath9k_ani_reset(struct ath_hw *ah);
+void ath9k_hw_ani_monitor(struct ath_hw *ah,
+			  const struct ath9k_node_stats *stats,
+			  struct ath9k_channel *chan);
+bool ath9k_hw_phycounters(struct ath_hw *ah);
+void ath9k_enable_mib_counters(struct ath_hw *ah);
+void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
+u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
+				  u32 *rxf_pcnt, u32 *txf_pcnt);
+void ath9k_hw_procmibevent(struct ath_hw *ah,
+			   const struct ath9k_node_stats *stats);
+void ath9k_hw_ani_setup(struct ath_hw *ah);
+void ath9k_hw_ani_attach(struct ath_hw *ah);
+void ath9k_hw_ani_detach(struct ath_hw *ah);
+
+#endif /* ANI_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ath9k.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ath9k.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/ath9k.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/ath9k.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,697 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH9K_H
+#define ATH9K_H
+
+#include <linux/etherdevice.h>
+#include <linux/device.h>
+#include <net/mac80211.h>
+#include <linux/leds.h>
+
+#include "hw.h"
+#include "rc.h"
+#include "debug.h"
+
+struct ath_node;
+
+/* Macro to expand scalars to 64-bit objects */
+
+#define	ito64(x) (sizeof(x) == 8) ?			\
+	(((unsigned long long int)(x)) & (0xff)) :	\
+	(sizeof(x) == 16) ?				\
+	(((unsigned long long int)(x)) & 0xffff) :	\
+	((sizeof(x) == 32) ?				\
+	 (((unsigned long long int)(x)) & 0xffffffff) : \
+	 (unsigned long long int)(x))
+
+/* increment with wrap-around */
+#define INCR(_l, _sz)   do {			\
+		(_l)++;				\
+		(_l) &= ((_sz) - 1);		\
+	} while (0)
+
+/* decrement with wrap-around */
+#define DECR(_l,  _sz)  do {			\
+		(_l)--;				\
+		(_l) &= ((_sz) - 1);		\
+	} while (0)
+
+#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define ASSERT(exp) BUG_ON(!(exp))
+
+#define TSF_TO_TU(_h,_l) \
+	((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
+
+#define	ATH_TXQ_SETUP(sc, i)        ((sc)->tx.txqsetup & (1<<i))
+
+static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+struct ath_config {
+	u32 ath_aggr_prot;
+	u16 txpowlimit;
+	u8 cabqReadytime;
+};
+
+/*************************/
+/* Descriptor Management */
+/*************************/
+
+#define ATH_TXBUF_RESET(_bf) do {				\
+		(_bf)->bf_stale = false;			\
+		(_bf)->bf_lastbf = NULL;			\
+		(_bf)->bf_next = NULL;				\
+		memset(&((_bf)->bf_state), 0,			\
+		       sizeof(struct ath_buf_state));		\
+	} while (0)
+
+#define ATH_RXBUF_RESET(_bf) do {		\
+		(_bf)->bf_stale = false;	\
+	} while (0)
+
+/**
+ * enum buffer_type - Buffer type flags
+ *
+ * @BUF_HT: Send this buffer using HT capabilities
+ * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
+ * @BUF_AGGR: Indicates whether the buffer can be aggregated
+ *	(used in aggregation scheduling)
+ * @BUF_RETRY: Indicates whether the buffer is retried
+ * @BUF_XRETRY: To denote excessive retries of the buffer
+ */
+enum buffer_type {
+	BUF_HT			= BIT(1),
+	BUF_AMPDU		= BIT(2),
+	BUF_AGGR		= BIT(3),
+	BUF_RETRY		= BIT(4),
+	BUF_XRETRY		= BIT(5),
+};
+
+struct ath_buf_state {
+	int bfs_nframes;
+	u16 bfs_al;
+	u16 bfs_frmlen;
+	int bfs_seqno;
+	int bfs_tidno;
+	int bfs_retries;
+	u8 bf_type;
+	u32 bfs_keyix;
+	enum ath9k_key_type bfs_keytype;
+};
+
+#define bf_nframes      	bf_state.bfs_nframes
+#define bf_al           	bf_state.bfs_al
+#define bf_frmlen       	bf_state.bfs_frmlen
+#define bf_retries      	bf_state.bfs_retries
+#define bf_seqno        	bf_state.bfs_seqno
+#define bf_tidno        	bf_state.bfs_tidno
+#define bf_keyix                bf_state.bfs_keyix
+#define bf_keytype      	bf_state.bfs_keytype
+#define bf_isht(bf)		(bf->bf_state.bf_type & BUF_HT)
+#define bf_isampdu(bf)		(bf->bf_state.bf_type & BUF_AMPDU)
+#define bf_isaggr(bf)		(bf->bf_state.bf_type & BUF_AGGR)
+#define bf_isretried(bf)	(bf->bf_state.bf_type & BUF_RETRY)
+#define bf_isxretried(bf)	(bf->bf_state.bf_type & BUF_XRETRY)
+
+struct ath_buf {
+	struct list_head list;
+	struct ath_buf *bf_lastbf;	/* last buf of this unit (a frame or
+					   an aggregate) */
+	struct ath_buf *bf_next;	/* next subframe in the aggregate */
+	struct sk_buff *bf_mpdu;	/* enclosing frame structure */
+	struct ath_desc *bf_desc;	/* virtual addr of desc */
+	dma_addr_t bf_daddr;		/* physical addr of desc */
+	dma_addr_t bf_buf_addr;		/* physical addr of data buffer */
+	bool bf_stale;
+	u16 bf_flags;
+	struct ath_buf_state bf_state;
+	dma_addr_t bf_dmacontext;
+};
+
+struct ath_descdma {
+	struct ath_desc *dd_desc;
+	dma_addr_t dd_desc_paddr;
+	u32 dd_desc_len;
+	struct ath_buf *dd_bufptr;
+};
+
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+		      struct list_head *head, const char *name,
+		      int nbuf, int ndesc);
+void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
+			 struct list_head *head);
+
+/***********/
+/* RX / TX */
+/***********/
+
+#define ATH_MAX_ANTENNA         3
+#define ATH_RXBUF               512
+#define WME_NUM_TID             16
+#define ATH_TXBUF               512
+#define ATH_TXMAXTRY            13
+#define ATH_11N_TXMAXTRY        10
+#define ATH_MGT_TXMAXTRY        4
+#define WME_BA_BMP_SIZE         64
+#define WME_MAX_BA              WME_BA_BMP_SIZE
+#define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
+
+#define TID_TO_WME_AC(_tid)				\
+	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
+	 (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK :	\
+	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
+	 WME_AC_VO)
+
+#define WME_AC_BE   0
+#define WME_AC_BK   1
+#define WME_AC_VI   2
+#define WME_AC_VO   3
+#define WME_NUM_AC  4
+
+#define ADDBA_EXCHANGE_ATTEMPTS    10
+#define ATH_AGGR_DELIM_SZ          4
+#define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
+/* number of delimiters for encryption padding */
+#define ATH_AGGR_ENCRYPTDELIM      10
+/* minimum h/w qdepth to be sustained to maximize aggregation */
+#define ATH_AGGR_MIN_QDEPTH        2
+#define ATH_AMPDU_SUBFRAME_DEFAULT 32
+#define ATH_AMPDU_LIMIT_MAX        (64 * 1024 - 1)
+#define ATH_AMPDU_LIMIT_DEFAULT    ATH_AMPDU_LIMIT_MAX
+
+#define IEEE80211_SEQ_SEQ_SHIFT    4
+#define IEEE80211_SEQ_MAX          4096
+#define IEEE80211_MIN_AMPDU_BUF    0x8
+#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
+#define IEEE80211_WEP_IVLEN        3
+#define IEEE80211_WEP_KIDLEN       1
+#define IEEE80211_WEP_CRCLEN       4
+#define IEEE80211_MAX_MPDU_LEN     (3840 + FCS_LEN +		\
+				    (IEEE80211_WEP_IVLEN +	\
+				     IEEE80211_WEP_KIDLEN +	\
+				     IEEE80211_WEP_CRCLEN))
+
+/* return whether a bit at index _n in bitmap _bm is set
+ * _sz is the size of the bitmap  */
+#define ATH_BA_ISSET(_bm, _n)  (((_n) < (WME_BA_BMP_SIZE)) &&		\
+				((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
+
+/* return block-ack bitmap index given sequence and starting sequence */
+#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
+
+/* returns delimiter padding required given the packet length */
+#define ATH_AGGR_GET_NDELIM(_len)					\
+	(((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?           \
+	  (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
+
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+	((((_seqno) - (_start)) & 4095) < (_bawsz))
+
+#define ATH_DS_BA_SEQ(_ds)         ((_ds)->ds_us.tx.ts_seqnum)
+#define ATH_DS_BA_BITMAP(_ds)      (&(_ds)->ds_us.tx.ba_low)
+#define ATH_DS_TX_BA(_ds)          ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
+#define ATH_AN_2_TID(_an, _tidno)  (&(_an)->tid[(_tidno)])
+
+enum ATH_AGGR_STATUS {
+	ATH_AGGR_DONE,
+	ATH_AGGR_BAW_CLOSED,
+	ATH_AGGR_LIMITED,
+};
+
+struct ath_txq {
+	u32 axq_qnum;
+	u32 *axq_link;
+	struct list_head axq_q;
+	spinlock_t axq_lock;
+	u32 axq_depth;
+	u8 axq_aggr_depth;
+	u32 axq_totalqueued;
+	bool stopped;
+	struct ath_buf *axq_linkbuf;
+
+	/* first desc of the last descriptor that contains CTS */
+	struct ath_desc *axq_lastdsWithCTS;
+
+	/* final desc of the gating desc that determines whether
+	   lastdsWithCTS has been DMA'ed or not */
+	struct ath_desc *axq_gatingds;
+
+	struct list_head axq_acq;
+};
+
+#define AGGR_CLEANUP         BIT(1)
+#define AGGR_ADDBA_COMPLETE  BIT(2)
+#define AGGR_ADDBA_PROGRESS  BIT(3)
+
+struct ath_atx_tid {
+	struct list_head list;
+	struct list_head buf_q;
+	struct ath_node *an;
+	struct ath_atx_ac *ac;
+	struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
+	u16 seq_start;
+	u16 seq_next;
+	u16 baw_size;
+	int tidno;
+	int baw_head;	/* first un-acked tx buffer */
+	int baw_tail;	/* next unused tx buffer slot */
+	int sched;
+	int paused;
+	u8 state;
+	int addba_exchangeattempts;
+};
+
+struct ath_atx_ac {
+	int sched;
+	int qnum;
+	struct list_head list;
+	struct list_head tid_q;
+};
+
+struct ath_tx_control {
+	struct ath_txq *txq;
+	int if_id;
+	enum ath9k_internal_frame_type frame_type;
+};
+
+#define ATH_TX_ERROR        0x01
+#define ATH_TX_XRETRY       0x02
+#define ATH_TX_BAR          0x04
+
+struct ath_node {
+	struct ath_softc *an_sc;
+	struct ath_atx_tid tid[WME_NUM_TID];
+	struct ath_atx_ac ac[WME_NUM_AC];
+	u16 maxampdu;
+	u8 mpdudensity;
+};
+
+struct ath_tx {
+	u16 seq_no;
+	u32 txqsetup;
+	int hwq_map[ATH9K_WME_AC_VO+1];
+	spinlock_t txbuflock;
+	struct list_head txbuf;
+	struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
+	struct ath_descdma txdma;
+};
+
+struct ath_rx {
+	u8 defant;
+	u8 rxotherant;
+	u32 *rxlink;
+	int bufsize;
+	unsigned int rxfilter;
+	spinlock_t rxflushlock;
+	spinlock_t rxbuflock;
+	struct list_head rxbuf;
+	struct ath_descdma rxdma;
+};
+
+int ath_startrecv(struct ath_softc *sc);
+bool ath_stoprecv(struct ath_softc *sc);
+void ath_flushrecv(struct ath_softc *sc);
+u32 ath_calcrxfilter(struct ath_softc *sc);
+int ath_rx_init(struct ath_softc *sc, int nbufs);
+void ath_rx_cleanup(struct ath_softc *sc);
+int ath_rx_tasklet(struct ath_softc *sc, int flush);
+struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
+void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
+int ath_tx_setup(struct ath_softc *sc, int haltype);
+void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
+void ath_draintxq(struct ath_softc *sc,
+		     struct ath_txq *txq, bool retry_tx);
+void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
+void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
+int ath_tx_init(struct ath_softc *sc, int nbufs);
+void ath_tx_cleanup(struct ath_softc *sc);
+struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
+int ath_txq_update(struct ath_softc *sc, int qnum,
+		   struct ath9k_tx_queue_info *q);
+int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
+		 struct ath_tx_control *txctl);
+void ath_tx_tasklet(struct ath_softc *sc);
+void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
+bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+		      u16 tid, u16 *ssn);
+int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+
+/********/
+/* VIFs */
+/********/
+
+struct ath_vif {
+	int av_bslot;
+	__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
+	enum nl80211_iftype av_opmode;
+	struct ath_buf *av_bcbuf;
+	struct ath_tx_control av_btxctl;
+	u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */
+};
+
+/*******************/
+/* Beacon Handling */
+/*******************/
+
+/*
+ * Regardless of the number of beacons we stagger, (i.e. regardless of the
+ * number of BSSIDs) if a given beacon does not go out even after waiting this
+ * number of beacon intervals, the game's up.
+ */
+#define BSTUCK_THRESH           	(9 * ATH_BCBUF)
+#define	ATH_BCBUF               	4
+#define ATH_DEFAULT_BINTVAL     	100 /* TU */
+#define ATH_DEFAULT_BMISS_LIMIT 	10
+#define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
+
+struct ath_beacon_config {
+	u16 beacon_interval;
+	u16 listen_interval;
+	u16 dtim_period;
+	u16 bmiss_timeout;
+	u8 dtim_count;
+};
+
+struct ath_beacon {
+	enum {
+		OK,		/* no change needed */
+		UPDATE,		/* update pending */
+		COMMIT		/* beacon sent, commit change */
+	} updateslot;		/* slot time update fsm */
+
+	u32 beaconq;
+	u32 bmisscnt;
+	u32 ast_be_xmit;
+	u64 bc_tstamp;
+	struct ieee80211_vif *bslot[ATH_BCBUF];
+	struct ath_wiphy *bslot_aphy[ATH_BCBUF];
+	int slottime;
+	int slotupdate;
+	struct ath9k_tx_queue_info beacon_qi;
+	struct ath_descdma bdma;
+	struct ath_txq *cabq;
+	struct list_head bbuf;
+};
+
+void ath_beacon_tasklet(unsigned long data);
+void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
+int ath_beaconq_setup(struct ath_hw *ah);
+int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
+void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
+
+/*******/
+/* ANI */
+/*******/
+
+#define ATH_STA_SHORT_CALINTERVAL 1000    /* 1 second */
+#define ATH_AP_SHORT_CALINTERVAL  100     /* 100 ms */
+#define ATH_ANI_POLLINTERVAL      100     /* 100 ms */
+#define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
+#define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
+
+struct ath_ani {
+	bool caldone;
+	int16_t noise_floor;
+	unsigned int longcal_timer;
+	unsigned int shortcal_timer;
+	unsigned int resetcal_timer;
+	unsigned int checkani_timer;
+	struct timer_list timer;
+};
+
+/********************/
+/*   LED Control    */
+/********************/
+
+#define ATH_LED_PIN	1
+#define ATH_LED_ON_DURATION_IDLE	350	/* in msecs */
+#define ATH_LED_OFF_DURATION_IDLE	250	/* in msecs */
+
+enum ath_led_type {
+	ATH_LED_RADIO,
+	ATH_LED_ASSOC,
+	ATH_LED_TX,
+	ATH_LED_RX
+};
+
+struct ath_led {
+	struct ath_softc *sc;
+	struct led_classdev led_cdev;
+	enum ath_led_type led_type;
+	char name[32];
+	bool registered;
+};
+
+/********************/
+/* Main driver core */
+/********************/
+
+/*
+ * Default cache line size, in bytes.
+ * Used when PCI device not fully initialized by bootrom/BIOS
+*/
+#define DEFAULT_CACHELINE       32
+#define	ATH_DEFAULT_NOISE_FLOOR -95
+#define ATH_REGCLASSIDS_MAX     10
+#define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
+#define ATH_MAX_SW_RETRIES      10
+#define ATH_CHAN_MAX            255
+#define IEEE80211_WEP_NKID      4       /* number of key ids */
+
+/*
+ * The key cache is used for h/w cipher state and also for
+ * tracking station state such as the current tx antenna.
+ * We also setup a mapping table between key cache slot indices
+ * and station state to short-circuit node lookups on rx.
+ * Different parts have different size key caches.  We handle
+ * up to ATH_KEYMAX entries (could dynamically allocate state).
+ */
+#define	ATH_KEYMAX	        128     /* max key cache size we handle */
+
+#define ATH_TXPOWER_MAX         100     /* .5 dBm units */
+#define ATH_RSSI_DUMMY_MARKER   0x127
+#define ATH_RATE_DUMMY_MARKER   0
+
+#define SC_OP_INVALID           BIT(0)
+#define SC_OP_BEACONS           BIT(1)
+#define SC_OP_RXAGGR            BIT(2)
+#define SC_OP_TXAGGR            BIT(3)
+#define SC_OP_FULL_RESET        BIT(4)
+#define SC_OP_PREAMBLE_SHORT    BIT(5)
+#define SC_OP_PROTECT_ENABLE    BIT(6)
+#define SC_OP_RXFLUSH           BIT(7)
+#define SC_OP_LED_ASSOCIATED    BIT(8)
+#define SC_OP_WAIT_FOR_BEACON   BIT(12)
+#define SC_OP_LED_ON            BIT(13)
+#define SC_OP_SCANNING          BIT(14)
+#define SC_OP_TSF_RESET         BIT(15)
+#define SC_OP_WAIT_FOR_CAB      BIT(16)
+#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17)
+#define SC_OP_WAIT_FOR_TX_ACK   BIT(18)
+#define SC_OP_BEACON_SYNC       BIT(19)
+
+struct ath_bus_ops {
+	void		(*read_cachesize)(struct ath_softc *sc, int *csz);
+	void		(*cleanup)(struct ath_softc *sc);
+	bool		(*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data);
+};
+
+struct ath_wiphy;
+
+struct ath_softc {
+	struct ieee80211_hw *hw;
+	struct device *dev;
+
+	spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
+	struct ath_wiphy *pri_wiphy;
+	struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
+				       * have NULL entries */
+	int num_sec_wiphy; /* number of sec_wiphy pointers in the array */
+	int chan_idx;
+	int chan_is_ht;
+	struct ath_wiphy *next_wiphy;
+	struct work_struct chan_work;
+	int wiphy_select_failures;
+	unsigned long wiphy_select_first_fail;
+	struct delayed_work wiphy_work;
+	unsigned long wiphy_scheduler_int;
+	int wiphy_scheduler_index;
+
+	struct tasklet_struct intr_tq;
+	struct tasklet_struct bcon_tasklet;
+	struct ath_hw *sc_ah;
+	void __iomem *mem;
+	int irq;
+	spinlock_t sc_resetlock;
+	spinlock_t sc_serial_rw;
+	struct mutex mutex;
+
+	u8 curbssid[ETH_ALEN];
+	u8 bssidmask[ETH_ALEN];
+	u32 intrstatus;
+	u32 sc_flags; /* SC_OP_* */
+	u16 curtxpow;
+	u16 curaid;
+	u16 cachelsz;
+	u8 nbcnvifs;
+	u16 nvifs;
+	u8 tx_chainmask;
+	u8 rx_chainmask;
+	u32 keymax;
+	DECLARE_BITMAP(keymap, ATH_KEYMAX);
+	u8 splitmic;
+	atomic_t ps_usecount;
+	enum ath9k_int imask;
+	enum ath9k_ht_extprotspacing ht_extprotspacing;
+	enum ath9k_ht_macmode tx_chan_width;
+
+	struct ath_config config;
+	struct ath_rx rx;
+	struct ath_tx tx;
+	struct ath_beacon beacon;
+	struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
+	const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
+	const struct ath_rate_table *cur_rate_table;
+	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+
+	struct ath_led radio_led;
+	struct ath_led assoc_led;
+	struct ath_led tx_led;
+	struct ath_led rx_led;
+	struct delayed_work ath_led_blink_work;
+	int led_on_duration;
+	int led_off_duration;
+	int led_on_cnt;
+	int led_off_cnt;
+
+	int beacon_interval;
+
+	struct ath_ani ani;
+	struct ath9k_node_stats nodestats;
+#ifdef CONFIG_ATH9K_DEBUG
+	struct ath9k_debug debug;
+#endif
+	struct ath_bus_ops *bus_ops;
+	struct ath_beacon_config cur_beacon_conf;
+};
+
+struct ath_wiphy {
+	struct ath_softc *sc; /* shared for all virtual wiphys */
+	struct ieee80211_hw *hw;
+	enum ath_wiphy_state {
+		ATH_WIPHY_INACTIVE,
+		ATH_WIPHY_ACTIVE,
+		ATH_WIPHY_PAUSING,
+		ATH_WIPHY_PAUSED,
+		ATH_WIPHY_SCAN,
+	} state;
+	int chan_idx;
+	int chan_is_ht;
+};
+
+int ath_reset(struct ath_softc *sc, bool retry_tx);
+int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
+int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
+int ath_cabq_update(struct ath_softc *);
+
+static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
+{
+	sc->bus_ops->read_cachesize(sc, csz);
+}
+
+static inline void ath_bus_cleanup(struct ath_softc *sc)
+{
+	sc->bus_ops->cleanup(sc);
+}
+
+extern struct ieee80211_ops ath9k_ops;
+
+irqreturn_t ath_isr(int irq, void *dev);
+void ath_cleanup(struct ath_softc *sc);
+int ath_attach(u16 devid, struct ath_softc *sc);
+void ath_detach(struct ath_softc *sc);
+const char *ath_mac_bb_name(u32 mac_bb_version);
+const char *ath_rf_name(u16 rf_version);
+void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
+void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
+			   struct ath9k_channel *ichan);
+void ath_update_chainmask(struct ath_softc *sc, int is_ht);
+int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+		    struct ath9k_channel *hchan);
+void ath_radio_enable(struct ath_softc *sc);
+void ath_radio_disable(struct ath_softc *sc);
+
+#ifdef CONFIG_PCI
+int ath_pci_init(void);
+void ath_pci_exit(void);
+#else
+static inline int ath_pci_init(void) { return 0; };
+static inline void ath_pci_exit(void) {};
+#endif
+
+#ifdef CONFIG_ATHEROS_AR71XX
+int ath_ahb_init(void);
+void ath_ahb_exit(void);
+#else
+static inline int ath_ahb_init(void) { return 0; };
+static inline void ath_ahb_exit(void) {};
+#endif
+
+static inline void ath9k_ps_wakeup(struct ath_softc *sc)
+{
+	if (atomic_inc_return(&sc->ps_usecount) == 1)
+		if (sc->sc_ah->power_mode !=  ATH9K_PM_AWAKE) {
+			sc->sc_ah->restore_mode = sc->sc_ah->power_mode;
+			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+		}
+}
+
+static inline void ath9k_ps_restore(struct ath_softc *sc)
+{
+	if (atomic_dec_and_test(&sc->ps_usecount))
+		if ((sc->hw->conf.flags & IEEE80211_CONF_PS) &&
+		    !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+				      SC_OP_WAIT_FOR_CAB |
+				      SC_OP_WAIT_FOR_PSPOLL_DATA |
+				      SC_OP_WAIT_FOR_TX_ACK)))
+			ath9k_hw_setpower(sc->sc_ah,
+					  sc->sc_ah->restore_mode);
+}
+
+
+void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
+int ath9k_wiphy_add(struct ath_softc *sc);
+int ath9k_wiphy_del(struct ath_wiphy *aphy);
+void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
+int ath9k_wiphy_pause(struct ath_wiphy *aphy);
+int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
+int ath9k_wiphy_select(struct ath_wiphy *aphy);
+void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int);
+void ath9k_wiphy_chan_work(struct work_struct *work);
+bool ath9k_wiphy_started(struct ath_softc *sc);
+void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
+				  struct ath_wiphy *selected);
+bool ath9k_wiphy_scanning(struct ath_softc *sc);
+void ath9k_wiphy_work(struct work_struct *work);
+
+void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val);
+unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset);
+
+#endif /* ATH9K_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/beacon.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/beacon.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/beacon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/beacon.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+#define FUDGE 2
+
+/*
+ *  This function will modify certain transmit queue properties depending on
+ *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
+ *  settings and channel width min/max
+*/
+static int ath_beaconq_config(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_tx_queue_info qi;
+
+	ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
+	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
+		/* Always burst out beacon and CAB traffic. */
+		qi.tqi_aifs = 1;
+		qi.tqi_cwmin = 0;
+		qi.tqi_cwmax = 0;
+	} else {
+		/* Adhoc mode; important thing is to use 2x cwmin. */
+		qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs;
+		qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin;
+		qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax;
+	}
+
+	if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to update h/w beacon queue parameters\n");
+		return 0;
+	} else {
+		ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
+		return 1;
+	}
+}
+
+/*
+ *  Associates the beacon frame buffer with a transmit descriptor.  Will set
+ *  up all required antenna switch parameters, rate codes, and channel flags.
+ *  Beacons are always sent out at the lowest rate, and are not retried.
+*/
+static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
+			     struct ath_buf *bf)
+{
+	struct sk_buff *skb = bf->bf_mpdu;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_desc *ds;
+	struct ath9k_11n_rate_series series[4];
+	const struct ath_rate_table *rt;
+	int flags, antenna, ctsrate = 0, ctsduration = 0;
+	u8 rate;
+
+	ds = bf->bf_desc;
+	flags = ATH9K_TXDESC_NOACK;
+
+	if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
+	     (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
+	    (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
+		ds->ds_link = bf->bf_daddr; /* self-linked */
+		flags |= ATH9K_TXDESC_VEOL;
+		/* Let hardware handle antenna switching. */
+		antenna = 0;
+	} else {
+		ds->ds_link = 0;
+		/*
+		 * Switch antenna every beacon.
+		 * Should only switch every beacon period, not for every SWBA
+		 * XXX assumes two antennae
+		 */
+		antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
+	}
+
+	ds->ds_data = bf->bf_buf_addr;
+
+	rt = sc->cur_rate_table;
+	rate = rt->info[0].ratecode;
+	if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+		rate |= rt->info[0].short_preamble;
+
+	ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
+			       ATH9K_PKT_TYPE_BEACON,
+			       MAX_RATE_POWER,
+			       ATH9K_TXKEYIX_INVALID,
+			       ATH9K_KEY_TYPE_CLEAR,
+			       flags);
+
+	/* NB: beacon's BufLen must be a multiple of 4 bytes */
+	ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
+			    true, true, ds);
+
+	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+	series[0].Tries = 1;
+	series[0].Rate = rate;
+	series[0].ChSel = sc->tx_chainmask;
+	series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
+	ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
+				     series, 4, 0);
+}
+
+static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
+					   struct ieee80211_vif *vif)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_buf *bf;
+	struct ath_vif *avp;
+	struct sk_buff *skb;
+	struct ath_txq *cabq;
+	struct ieee80211_tx_info *info;
+	int cabq_depth;
+
+	if (aphy->state != ATH_WIPHY_ACTIVE)
+		return NULL;
+
+	avp = (void *)vif->drv_priv;
+	cabq = sc->beacon.cabq;
+
+	if (avp->av_bcbuf == NULL)
+		return NULL;
+
+	/* Release the old beacon first */
+
+	bf = avp->av_bcbuf;
+	skb = bf->bf_mpdu;
+	if (skb) {
+		dma_unmap_single(sc->dev, bf->bf_dmacontext,
+				 skb->len, DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);
+	}
+
+	/* Get a new beacon from mac80211 */
+
+	skb = ieee80211_beacon_get(hw, vif);
+	bf->bf_mpdu = skb;
+	if (skb == NULL)
+		return NULL;
+	((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
+		avp->tsf_adjust;
+
+	info = IEEE80211_SKB_CB(skb);
+	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		/*
+		 * TODO: make sure the seq# gets assigned properly (vs. other
+		 * TX frames)
+		 */
+		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+		sc->tx.seq_no += 0x10;
+		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+	}
+
+	bf->bf_buf_addr = bf->bf_dmacontext =
+		dma_map_single(sc->dev, skb->data,
+			       skb->len, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
+		dev_kfree_skb_any(skb);
+		bf->bf_mpdu = NULL;
+		DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n");
+		return NULL;
+	}
+
+	skb = ieee80211_get_buffered_bc(hw, vif);
+
+	/*
+	 * if the CABQ traffic from previous DTIM is pending and the current
+	 *  beacon is also a DTIM.
+	 *  1) if there is only one vif let the cab traffic continue.
+	 *  2) if there are more than one vif and we are using staggered
+	 *     beacons, then drain the cabq by dropping all the frames in
+	 *     the cabq so that the current vifs cab traffic can be scheduled.
+	 */
+	spin_lock_bh(&cabq->axq_lock);
+	cabq_depth = cabq->axq_depth;
+	spin_unlock_bh(&cabq->axq_lock);
+
+	if (skb && cabq_depth) {
+		if (sc->nvifs > 1) {
+			DPRINTF(sc, ATH_DBG_BEACON,
+				"Flushing previous cabq traffic\n");
+			ath_draintxq(sc, cabq, false);
+		}
+	}
+
+	ath_beacon_setup(sc, avp, bf);
+
+	while (skb) {
+		ath_tx_cabq(hw, skb);
+		skb = ieee80211_get_buffered_bc(hw, vif);
+	}
+
+	return bf;
+}
+
+/*
+ * Startup beacon transmission for adhoc mode when they are sent entirely
+ * by the hardware using the self-linked descriptor + veol trick.
+*/
+static void ath_beacon_start_adhoc(struct ath_softc *sc,
+				   struct ieee80211_vif *vif)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_buf *bf;
+	struct ath_vif *avp;
+	struct sk_buff *skb;
+
+	avp = (void *)vif->drv_priv;
+
+	if (avp->av_bcbuf == NULL)
+		return;
+
+	bf = avp->av_bcbuf;
+	skb = bf->bf_mpdu;
+
+	ath_beacon_setup(sc, avp, bf);
+
+	/* NB: caller is known to have already stopped tx dma */
+	ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
+	ath9k_hw_txstart(ah, sc->beacon.beaconq);
+	DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
+		sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
+}
+
+int ath_beaconq_setup(struct ath_hw *ah)
+{
+	struct ath9k_tx_queue_info qi;
+
+	memset(&qi, 0, sizeof(qi));
+	qi.tqi_aifs = 1;
+	qi.tqi_cwmin = 0;
+	qi.tqi_cwmax = 0;
+	/* NB: don't enable any interrupts */
+	return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
+}
+
+int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = aphy->sc;
+	struct ath_vif *avp;
+	struct ath_buf *bf;
+	struct sk_buff *skb;
+	__le64 tstamp;
+
+	avp = (void *)vif->drv_priv;
+
+	/* Allocate a beacon descriptor if we haven't done so. */
+	if (!avp->av_bcbuf) {
+		/* Allocate beacon state for hostap/ibss.  We know
+		 * a buffer is available. */
+		avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
+						 struct ath_buf, list);
+		list_del(&avp->av_bcbuf->list);
+
+		if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
+		    !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
+			int slot;
+			/*
+			 * Assign the vif to a beacon xmit slot. As
+			 * above, this cannot fail to find one.
+			 */
+			avp->av_bslot = 0;
+			for (slot = 0; slot < ATH_BCBUF; slot++)
+				if (sc->beacon.bslot[slot] == NULL) {
+					/*
+					 * XXX hack, space out slots to better
+					 * deal with misses
+					 */
+					if (slot+1 < ATH_BCBUF &&
+					    sc->beacon.bslot[slot+1] == NULL) {
+						avp->av_bslot = slot+1;
+						break;
+					}
+					avp->av_bslot = slot;
+					/* NB: keep looking for a double slot */
+				}
+			BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
+			sc->beacon.bslot[avp->av_bslot] = vif;
+			sc->beacon.bslot_aphy[avp->av_bslot] = aphy;
+			sc->nbcnvifs++;
+		}
+	}
+
+	/* release the previous beacon frame, if it already exists. */
+	bf = avp->av_bcbuf;
+	if (bf->bf_mpdu != NULL) {
+		skb = bf->bf_mpdu;
+		dma_unmap_single(sc->dev, bf->bf_dmacontext,
+				 skb->len, DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);
+		bf->bf_mpdu = NULL;
+	}
+
+	/* NB: the beacon data buffer must be 32-bit aligned. */
+	skb = ieee80211_beacon_get(sc->hw, vif);
+	if (skb == NULL) {
+		DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n");
+		return -ENOMEM;
+	}
+
+	tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+	sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
+	/* Calculate a TSF adjustment factor required for staggered beacons. */
+	if (avp->av_bslot > 0) {
+		u64 tsfadjust;
+		int intval;
+
+		intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+
+		/*
+		 * Calculate the TSF offset for this beacon slot, i.e., the
+		 * number of usecs that need to be added to the timestamp field
+		 * in Beacon and Probe Response frames. Beacon slot 0 is
+		 * processed at the correct offset, so it does not require TSF
+		 * adjustment. Other slots are adjusted to get the timestamp
+		 * close to the TBTT for the BSS.
+		 */
+		tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
+		avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
+
+		DPRINTF(sc, ATH_DBG_BEACON,
+			"stagger beacons, bslot %d intval %u tsfadjust %llu\n",
+			avp->av_bslot, intval, (unsigned long long)tsfadjust);
+
+		((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
+			avp->tsf_adjust;
+	} else
+		avp->tsf_adjust = cpu_to_le64(0);
+
+	bf->bf_mpdu = skb;
+	bf->bf_buf_addr = bf->bf_dmacontext =
+		dma_map_single(sc->dev, skb->data,
+			       skb->len, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
+		dev_kfree_skb_any(skb);
+		bf->bf_mpdu = NULL;
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"dma_mapping_error on beacon alloc\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
+{
+	if (avp->av_bcbuf != NULL) {
+		struct ath_buf *bf;
+
+		if (avp->av_bslot != -1) {
+			sc->beacon.bslot[avp->av_bslot] = NULL;
+			sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
+			sc->nbcnvifs--;
+		}
+
+		bf = avp->av_bcbuf;
+		if (bf->bf_mpdu != NULL) {
+			struct sk_buff *skb = bf->bf_mpdu;
+			dma_unmap_single(sc->dev, bf->bf_dmacontext,
+					 skb->len, DMA_TO_DEVICE);
+			dev_kfree_skb_any(skb);
+			bf->bf_mpdu = NULL;
+		}
+		list_add_tail(&bf->list, &sc->beacon.bbuf);
+
+		avp->av_bcbuf = NULL;
+	}
+}
+
+void ath_beacon_tasklet(unsigned long data)
+{
+	struct ath_softc *sc = (struct ath_softc *)data;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_buf *bf = NULL;
+	struct ieee80211_vif *vif;
+	struct ath_wiphy *aphy;
+	int slot;
+	u32 bfaddr, bc = 0, tsftu;
+	u64 tsf;
+	u16 intval;
+
+	/*
+	 * Check if the previous beacon has gone out.  If
+	 * not don't try to post another, skip this period
+	 * and wait for the next.  Missed beacons indicate
+	 * a problem and should not occur.  If we miss too
+	 * many consecutive beacons reset the device.
+	 */
+	if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
+		sc->beacon.bmisscnt++;
+
+		if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
+			DPRINTF(sc, ATH_DBG_BEACON,
+				"missed %u consecutive beacons\n",
+				sc->beacon.bmisscnt);
+		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
+			DPRINTF(sc, ATH_DBG_BEACON,
+				"beacon is officially stuck\n");
+			sc->sc_flags |= SC_OP_TSF_RESET;
+			ath_reset(sc, false);
+		}
+
+		return;
+	}
+
+	if (sc->beacon.bmisscnt != 0) {
+		DPRINTF(sc, ATH_DBG_BEACON,
+			"resume beacon xmit after %u misses\n",
+			sc->beacon.bmisscnt);
+		sc->beacon.bmisscnt = 0;
+	}
+
+	/*
+	 * Generate beacon frames. we are sending frames
+	 * staggered so calculate the slot for this frame based
+	 * on the tsf to safeguard against missing an swba.
+	 */
+
+	intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+
+	tsf = ath9k_hw_gettsf64(ah);
+	tsftu = TSF_TO_TU(tsf>>32, tsf);
+	slot = ((tsftu % intval) * ATH_BCBUF) / intval;
+	/*
+	 * Reverse the slot order to get slot 0 on the TBTT offset that does
+	 * not require TSF adjustment and other slots adding
+	 * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
+	 * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
+	 * and slot 0 is at correct offset to TBTT.
+	 */
+	slot = ATH_BCBUF - slot - 1;
+	vif = sc->beacon.bslot[slot];
+	aphy = sc->beacon.bslot_aphy[slot];
+
+	DPRINTF(sc, ATH_DBG_BEACON,
+		"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
+		slot, tsf, tsftu, intval, vif);
+
+	bfaddr = 0;
+	if (vif) {
+		bf = ath_beacon_generate(aphy->hw, vif);
+		if (bf != NULL) {
+			bfaddr = bf->bf_daddr;
+			bc = 1;
+		}
+	}
+
+	/*
+	 * Handle slot time change when a non-ERP station joins/leaves
+	 * an 11g network.  The 802.11 layer notifies us via callback,
+	 * we mark updateslot, then wait one beacon before effecting
+	 * the change.  This gives associated stations at least one
+	 * beacon interval to note the state change.
+	 *
+	 * NB: The slot time change state machine is clocked according
+	 *     to whether we are bursting or staggering beacons.  We
+	 *     recognize the request to update and record the current
+	 *     slot then don't transition until that slot is reached
+	 *     again.  If we miss a beacon for that slot then we'll be
+	 *     slow to transition but we'll be sure at least one beacon
+	 *     interval has passed.  When bursting slot is always left
+	 *     set to ATH_BCBUF so this check is a noop.
+	 */
+	if (sc->beacon.updateslot == UPDATE) {
+		sc->beacon.updateslot = COMMIT; /* commit next beacon */
+		sc->beacon.slotupdate = slot;
+	} else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
+		ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime);
+		sc->beacon.updateslot = OK;
+	}
+	if (bfaddr != 0) {
+		/*
+		 * Stop any current dma and put the new frame(s) on the queue.
+		 * This should never fail since we check above that no frames
+		 * are still pending on the queue.
+		 */
+		if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"beacon queue %u did not stop?\n", sc->beacon.beaconq);
+		}
+
+		/* NB: cabq traffic should already be queued and primed */
+		ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
+		ath9k_hw_txstart(ah, sc->beacon.beaconq);
+
+		sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
+	}
+}
+
+/*
+ * For multi-bss ap support beacons are either staggered evenly over N slots or
+ * burst together.  For the former arrange for the SWBA to be delivered for each
+ * slot. Slots that are not occupied will generate nothing.
+ */
+static void ath_beacon_config_ap(struct ath_softc *sc,
+				 struct ath_beacon_config *conf)
+{
+	u32 nexttbtt, intval;
+
+	/* Configure the timers only when the TSF has to be reset */
+
+	if (!(sc->sc_flags & SC_OP_TSF_RESET))
+		return;
+
+	/* NB: the beacon interval is kept internally in TU's */
+	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
+	intval /= ATH_BCBUF;    /* for staggered beacons */
+	nexttbtt = intval;
+	intval |= ATH9K_BEACON_RESET_TSF;
+
+	/*
+	 * In AP mode we enable the beacon timers and SWBA interrupts to
+	 * prepare beacon frames.
+	 */
+	intval |= ATH9K_BEACON_ENA;
+	sc->imask |= ATH9K_INT_SWBA;
+	ath_beaconq_config(sc);
+
+	/* Set the computed AP beacon timers */
+
+	ath9k_hw_set_interrupts(sc->sc_ah, 0);
+	ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
+	sc->beacon.bmisscnt = 0;
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
+
+	/* Clear the reset TSF flag, so that subsequent beacon updation
+	   will not reset the HW TSF. */
+
+	sc->sc_flags &= ~SC_OP_TSF_RESET;
+}
+
+/*
+ * This sets up the beacon timers according to the timestamp of the last
+ * received beacon and the current TSF, configures PCF and DTIM
+ * handling, programs the sleep registers so the hardware will wakeup in
+ * time to receive beacons, and configures the beacon miss handling so
+ * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
+ * we've associated with.
+ */
+static void ath_beacon_config_sta(struct ath_softc *sc,
+				  struct ath_beacon_config *conf)
+{
+	struct ath9k_beacon_state bs;
+	int dtimperiod, dtimcount, sleepduration;
+	int cfpperiod, cfpcount;
+	u32 nexttbtt = 0, intval, tsftu;
+	u64 tsf;
+	int num_beacons, offset, dtim_dec_count, cfp_dec_count;
+
+	memset(&bs, 0, sizeof(bs));
+	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
+
+	/*
+	 * Setup dtim and cfp parameters according to
+	 * last beacon we received (which may be none).
+	 */
+	dtimperiod = conf->dtim_period;
+	if (dtimperiod <= 0)		/* NB: 0 if not known */
+		dtimperiod = 1;
+	dtimcount = conf->dtim_count;
+	if (dtimcount >= dtimperiod)	/* NB: sanity check */
+		dtimcount = 0;
+	cfpperiod = 1;			/* NB: no PCF support yet */
+	cfpcount = 0;
+
+	sleepduration = conf->listen_interval * intval;
+	if (sleepduration <= 0)
+		sleepduration = intval;
+
+	/*
+	 * Pull nexttbtt forward to reflect the current
+	 * TSF and calculate dtim+cfp state for the result.
+	 */
+	tsf = ath9k_hw_gettsf64(sc->sc_ah);
+	tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+
+	num_beacons = tsftu / intval + 1;
+	offset = tsftu % intval;
+	nexttbtt = tsftu - offset;
+	if (offset)
+		nexttbtt += intval;
+
+	/* DTIM Beacon every dtimperiod Beacon */
+	dtim_dec_count = num_beacons % dtimperiod;
+	/* CFP every cfpperiod DTIM Beacon */
+	cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
+	if (dtim_dec_count)
+		cfp_dec_count++;
+
+	dtimcount -= dtim_dec_count;
+	if (dtimcount < 0)
+		dtimcount += dtimperiod;
+
+	cfpcount -= cfp_dec_count;
+	if (cfpcount < 0)
+		cfpcount += cfpperiod;
+
+	bs.bs_intval = intval;
+	bs.bs_nexttbtt = nexttbtt;
+	bs.bs_dtimperiod = dtimperiod*intval;
+	bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
+	bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
+	bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
+	bs.bs_cfpmaxduration = 0;
+
+	/*
+	 * Calculate the number of consecutive beacons to miss* before taking
+	 * a BMISS interrupt. The configuration is specified in TU so we only
+	 * need calculate based	on the beacon interval.  Note that we clamp the
+	 * result to at most 15 beacons.
+	 */
+	if (sleepduration > intval) {
+		bs.bs_bmissthreshold = conf->listen_interval *
+			ATH_DEFAULT_BMISS_LIMIT / 2;
+	} else {
+		bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval);
+		if (bs.bs_bmissthreshold > 15)
+			bs.bs_bmissthreshold = 15;
+		else if (bs.bs_bmissthreshold <= 0)
+			bs.bs_bmissthreshold = 1;
+	}
+
+	/*
+	 * Calculate sleep duration. The configuration is given in ms.
+	 * We ensure a multiple of the beacon period is used. Also, if the sleep
+	 * duration is greater than the DTIM period then it makes senses
+	 * to make it a multiple of that.
+	 *
+	 * XXX fixed at 100ms
+	 */
+
+	bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
+	if (bs.bs_sleepduration > bs.bs_dtimperiod)
+		bs.bs_sleepduration = bs.bs_dtimperiod;
+
+	/* TSF out of range threshold fixed at 1 second */
+	bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
+
+	DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+	DPRINTF(sc, ATH_DBG_BEACON,
+		"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+		bs.bs_bmissthreshold, bs.bs_sleepduration,
+		bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
+
+	/* Set the computed STA beacon timers */
+
+	ath9k_hw_set_interrupts(sc->sc_ah, 0);
+	ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs);
+	sc->imask |= ATH9K_INT_BMISS;
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
+}
+
+static void ath_beacon_config_adhoc(struct ath_softc *sc,
+				    struct ath_beacon_config *conf,
+				    struct ieee80211_vif *vif)
+{
+	u64 tsf;
+	u32 tsftu, intval, nexttbtt;
+
+	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
+
+	/*
+	 * It looks like mac80211 may end up using beacon interval of zero in
+	 * some cases (at least for mesh point). Avoid getting into an
+	 * infinite loop by using a bit safer value instead..
+	 */
+	if (intval == 0)
+		intval = 100;
+
+	/* Pull nexttbtt forward to reflect the current TSF */
+
+	nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
+	if (nexttbtt == 0)
+                nexttbtt = intval;
+        else if (intval)
+                nexttbtt = roundup(nexttbtt, intval);
+
+	tsf = ath9k_hw_gettsf64(sc->sc_ah);
+	tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE;
+	do {
+		nexttbtt += intval;
+	} while (nexttbtt < tsftu);
+
+	DPRINTF(sc, ATH_DBG_BEACON,
+		"IBSS nexttbtt %u intval %u (%u)\n",
+		nexttbtt, intval, conf->beacon_interval);
+
+	/*
+	 * In IBSS mode enable the beacon timers but only enable SWBA interrupts
+	 * if we need to manually prepare beacon frames.  Otherwise we use a
+	 * self-linked tx descriptor and let the hardware deal with things.
+	 */
+	intval |= ATH9K_BEACON_ENA;
+	if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
+		sc->imask |= ATH9K_INT_SWBA;
+
+	ath_beaconq_config(sc);
+
+	/* Set the computed ADHOC beacon timers */
+
+	ath9k_hw_set_interrupts(sc->sc_ah, 0);
+	ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
+	sc->beacon.bmisscnt = 0;
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
+
+	/* FIXME: Handle properly when vif is NULL */
+	if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
+		ath_beacon_start_adhoc(sc, vif);
+}
+
+void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
+{
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+	enum nl80211_iftype iftype;
+
+	/* Setup the beacon configuration parameters */
+
+	if (vif) {
+		struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+		iftype = vif->type;
+
+		cur_conf->beacon_interval = bss_conf->beacon_int;
+		cur_conf->dtim_period = bss_conf->dtim_period;
+		cur_conf->listen_interval = 1;
+		cur_conf->dtim_count = 1;
+		cur_conf->bmiss_timeout =
+			ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
+	} else {
+		iftype = sc->sc_ah->opmode;
+	}
+
+
+	switch (iftype) {
+	case NL80211_IFTYPE_AP:
+		ath_beacon_config_ap(sc, cur_conf);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+		ath_beacon_config_adhoc(sc, cur_conf, vif);
+		break;
+	case NL80211_IFTYPE_STATION:
+		ath_beacon_config_sta(sc, cur_conf);
+		break;
+	default:
+		DPRINTF(sc, ATH_DBG_CONFIG,
+			"Unsupported beaconing mode\n");
+		return;
+	}
+
+	sc->sc_flags |= SC_OP_BEACONS;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/calib.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/calib.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/calib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/calib.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+/* We can tune this as we go by monitoring really low values */
+#define ATH9K_NF_TOO_LOW	-60
+
+/* AR5416 may return very high value (like -31 dBm), in those cases the nf
+ * is incorrect and we should use the static NF value. Later we can try to
+ * find out why they are reporting these values */
+
+static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
+{
+	if (nf > ATH9K_NF_TOO_LOW) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"noise floor value detected (%d) is "
+			"lower than what we think is a "
+			"reasonable value (%d)\n",
+			nf, ATH9K_NF_TOO_LOW);
+		return false;
+	}
+	return true;
+}
+
+static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
+{
+	int16_t nfval;
+	int16_t sort[ATH9K_NF_CAL_HIST_MAX];
+	int i, j;
+
+	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
+		sort[i] = nfCalBuffer[i];
+
+	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
+		for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
+			if (sort[j] > sort[j - 1]) {
+				nfval = sort[j];
+				sort[j] = sort[j - 1];
+				sort[j - 1] = nfval;
+			}
+		}
+	}
+	nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
+
+	return nfval;
+}
+
+static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
+					      int16_t *nfarray)
+{
+	int i;
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
+			h[i].currIndex = 0;
+
+		if (h[i].invalidNFcount > 0) {
+			if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
+			    nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
+				h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
+			} else {
+				h[i].invalidNFcount--;
+				h[i].privNF = nfarray[i];
+			}
+		} else {
+			h[i].privNF =
+				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
+		}
+	}
+	return;
+}
+
+static void ath9k_hw_do_getnf(struct ath_hw *ah,
+			      int16_t nfarray[NUM_NF_READINGS])
+{
+	int16_t nf;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
+	else
+		nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+
+	if (nf & 0x100)
+		nf = 0 - ((nf ^ 0x1ff) + 1);
+	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+		"NF calibrated [ctl] [chain 0] is %d\n", nf);
+	nfarray[0] = nf;
+
+	if (!AR_SREV_9285(ah)) {
+		if (AR_SREV_9280_10_OR_LATER(ah))
+			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+					AR9280_PHY_CH1_MINCCA_PWR);
+		else
+			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+					AR_PHY_CH1_MINCCA_PWR);
+
+		if (nf & 0x100)
+			nf = 0 - ((nf ^ 0x1ff) + 1);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"NF calibrated [ctl] [chain 1] is %d\n", nf);
+		nfarray[1] = nf;
+
+		if (!AR_SREV_9280(ah)) {
+			nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
+					AR_PHY_CH2_MINCCA_PWR);
+			if (nf & 0x100)
+				nf = 0 - ((nf ^ 0x1ff) + 1);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"NF calibrated [ctl] [chain 2] is %d\n", nf);
+			nfarray[2] = nf;
+		}
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+			AR9280_PHY_EXT_MINCCA_PWR);
+	else
+		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+			AR_PHY_EXT_MINCCA_PWR);
+
+	if (nf & 0x100)
+		nf = 0 - ((nf ^ 0x1ff) + 1);
+	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+		"NF calibrated [ext] [chain 0] is %d\n", nf);
+	nfarray[3] = nf;
+
+	if (!AR_SREV_9285(ah)) {
+		if (AR_SREV_9280_10_OR_LATER(ah))
+			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+					AR9280_PHY_CH1_EXT_MINCCA_PWR);
+		else
+			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+					AR_PHY_CH1_EXT_MINCCA_PWR);
+
+		if (nf & 0x100)
+			nf = 0 - ((nf ^ 0x1ff) + 1);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"NF calibrated [ext] [chain 1] is %d\n", nf);
+		nfarray[4] = nf;
+
+		if (!AR_SREV_9280(ah)) {
+			nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
+					AR_PHY_CH2_EXT_MINCCA_PWR);
+			if (nf & 0x100)
+				nf = 0 - ((nf ^ 0x1ff) + 1);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"NF calibrated [ext] [chain 2] is %d\n", nf);
+			nfarray[5] = nf;
+		}
+	}
+}
+
+static bool getNoiseFloorThresh(struct ath_hw *ah,
+				enum ieee80211_band band,
+				int16_t *nft)
+{
+	switch (band) {
+	case IEEE80211_BAND_5GHZ:
+		*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
+		break;
+	case IEEE80211_BAND_2GHZ:
+		*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
+		break;
+	default:
+		BUG_ON(1);
+		return false;
+	}
+
+	return true;
+}
+
+static void ath9k_hw_setup_calibration(struct ath_hw *ah,
+				       struct ath9k_cal_list *currCal)
+{
+	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
+		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+		      currCal->calData->calCountMax);
+
+	switch (currCal->calData->calType) {
+	case IQ_MISMATCH_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"starting IQ Mismatch Calibration\n");
+		break;
+	case ADC_GAIN_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"starting ADC Gain Calibration\n");
+		break;
+	case ADC_DC_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"starting ADC DC Calibration\n");
+		break;
+	case ADC_DC_INIT_CAL:
+		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"starting Init ADC DC Calibration\n");
+		break;
+	}
+
+	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+		    AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+static void ath9k_hw_reset_calibration(struct ath_hw *ah,
+				       struct ath9k_cal_list *currCal)
+{
+	int i;
+
+	ath9k_hw_setup_calibration(ah, currCal);
+
+	currCal->calState = CAL_RUNNING;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ah->meas0.sign[i] = 0;
+		ah->meas1.sign[i] = 0;
+		ah->meas2.sign[i] = 0;
+		ah->meas3.sign[i] = 0;
+	}
+
+	ah->cal_samples = 0;
+}
+
+static bool ath9k_hw_per_calibration(struct ath_hw *ah,
+				     struct ath9k_channel *ichan,
+				     u8 rxchainmask,
+				     struct ath9k_cal_list *currCal)
+{
+	bool iscaldone = false;
+
+	if (currCal->calState == CAL_RUNNING) {
+		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+		      AR_PHY_TIMING_CTRL4_DO_CAL)) {
+
+			currCal->calData->calCollect(ah);
+			ah->cal_samples++;
+
+			if (ah->cal_samples >= currCal->calData->calNumSamples) {
+				int i, numChains = 0;
+				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+					if (rxchainmask & (1 << i))
+						numChains++;
+				}
+
+				currCal->calData->calPostProc(ah, numChains);
+				ichan->CalValid |= currCal->calData->calType;
+				currCal->calState = CAL_DONE;
+				iscaldone = true;
+			} else {
+				ath9k_hw_setup_calibration(ah, currCal);
+			}
+		}
+	} else if (!(ichan->CalValid & currCal->calData->calType)) {
+		ath9k_hw_reset_calibration(ah, currCal);
+	}
+
+	return iscaldone;
+}
+
+/* Assumes you are talking about the currently configured channel */
+static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
+				     enum ath9k_cal_types calType)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+
+	switch (calType & ah->supp_cals) {
+	case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
+		return true;
+	case ADC_GAIN_CAL:
+	case ADC_DC_CAL:
+		if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
+		      conf_is_ht20(conf)))
+			return true;
+		break;
+	}
+	return false;
+}
+
+static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
+{
+	int i;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ah->totalPowerMeasI[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+		ah->totalPowerMeasQ[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+		ah->totalIqCorrMeas[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+			ah->cal_samples, i, ah->totalPowerMeasI[i],
+			ah->totalPowerMeasQ[i],
+			ah->totalIqCorrMeas[i]);
+	}
+}
+
+static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
+{
+	int i;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ah->totalAdcIOddPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+		ah->totalAdcIEvenPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+		ah->totalAdcQOddPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+		ah->totalAdcQEvenPhase[i] +=
+			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+			"oddq=0x%08x; evenq=0x%08x;\n",
+			ah->cal_samples, i,
+			ah->totalAdcIOddPhase[i],
+			ah->totalAdcIEvenPhase[i],
+			ah->totalAdcQOddPhase[i],
+			ah->totalAdcQEvenPhase[i]);
+	}
+}
+
+static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
+{
+	int i;
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		ah->totalAdcDcOffsetIOddPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+		ah->totalAdcDcOffsetIEvenPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+		ah->totalAdcDcOffsetQOddPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+		ah->totalAdcDcOffsetQEvenPhase[i] +=
+			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+			"oddq=0x%08x; evenq=0x%08x;\n",
+			ah->cal_samples, i,
+			ah->totalAdcDcOffsetIOddPhase[i],
+			ah->totalAdcDcOffsetIEvenPhase[i],
+			ah->totalAdcDcOffsetQOddPhase[i],
+			ah->totalAdcDcOffsetQEvenPhase[i]);
+	}
+}
+
+static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
+{
+	u32 powerMeasQ, powerMeasI, iqCorrMeas;
+	u32 qCoffDenom, iCoffDenom;
+	int32_t qCoff, iCoff;
+	int iqCorrNeg, i;
+
+	for (i = 0; i < numChains; i++) {
+		powerMeasI = ah->totalPowerMeasI[i];
+		powerMeasQ = ah->totalPowerMeasQ[i];
+		iqCorrMeas = ah->totalIqCorrMeas[i];
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Starting IQ Cal and Correction for Chain %d\n",
+			i);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Orignal: Chn %diq_corr_meas = 0x%08x\n",
+			i, ah->totalIqCorrMeas[i]);
+
+		iqCorrNeg = 0;
+
+		if (iqCorrMeas > 0x80000000) {
+			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+			iqCorrNeg = 1;
+		}
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
+			iqCorrNeg);
+
+		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+		qCoffDenom = powerMeasQ / 64;
+
+		if (powerMeasQ != 0) {
+			iCoff = iqCorrMeas / iCoffDenom;
+			qCoff = powerMeasI / qCoffDenom - 64;
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d iCoff = 0x%08x\n", i, iCoff);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d qCoff = 0x%08x\n", i, qCoff);
+
+			iCoff = iCoff & 0x3f;
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
+			if (iqCorrNeg == 0x0)
+				iCoff = 0x40 - iCoff;
+
+			if (qCoff > 15)
+				qCoff = 15;
+			else if (qCoff <= -16)
+				qCoff = 16;
+
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
+				i, iCoff, qCoff);
+
+			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+				      iCoff);
+			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+				      qCoff);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"IQ Cal and Correction done for Chain %d\n",
+				i);
+		}
+	}
+
+	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
+
+static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
+{
+	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
+	u32 qGainMismatch, iGainMismatch, val, i;
+
+	for (i = 0; i < numChains; i++) {
+		iOddMeasOffset = ah->totalAdcIOddPhase[i];
+		iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
+		qOddMeasOffset = ah->totalAdcQOddPhase[i];
+		qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Starting ADC Gain Cal for Chain %d\n", i);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
+			iOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_i = 0x%08x\n", i,
+			iEvenMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
+			qOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_q = 0x%08x\n", i,
+			qEvenMeasOffset);
+
+		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+			iGainMismatch =
+				((iEvenMeasOffset * 32) /
+				 iOddMeasOffset) & 0x3f;
+			qGainMismatch =
+				((qOddMeasOffset * 32) /
+				 qEvenMeasOffset) & 0x3f;
+
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d gain_mismatch_i = 0x%08x\n", i,
+				iGainMismatch);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"Chn %d gain_mismatch_q = 0x%08x\n", i,
+				qGainMismatch);
+
+			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+			val &= 0xfffff000;
+			val |= (qGainMismatch) | (iGainMismatch << 6);
+			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"ADC Gain Cal done for Chain %d\n", i);
+		}
+	}
+
+	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
+
+static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
+{
+	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
+	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
+	const struct ath9k_percal_data *calData =
+		ah->cal_list_curr->calData;
+	u32 numSamples =
+		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+
+	for (i = 0; i < numChains; i++) {
+		iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
+		iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
+		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
+		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Starting ADC DC Offset Cal for Chain %d\n", i);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_i = %d\n", i,
+			iOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_i = %d\n", i,
+			iEvenMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_odd_q = %d\n", i,
+			qOddMeasOffset);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d pwr_meas_even_q = %d\n", i,
+			qEvenMeasOffset);
+
+		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+			       numSamples) & 0x1ff;
+		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+			       numSamples) & 0x1ff;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
+			iDcMismatch);
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
+			qDcMismatch);
+
+		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+		val &= 0xc0000fff;
+		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"ADC DC Offset Cal done for Chain %d\n", i);
+	}
+
+	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
+
+/* This is done for the currently configured channel */
+bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+	struct ath9k_cal_list *currCal = ah->cal_list_curr;
+
+	if (!ah->curchan)
+		return true;
+
+	if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
+		return true;
+
+	if (currCal == NULL)
+		return true;
+
+	if (currCal->calState != CAL_DONE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"Calibration state incorrect, %d\n",
+			currCal->calState);
+		return true;
+	}
+
+	if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
+		return true;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+		"Resetting Cal %d state for channel %u\n",
+		currCal->calData->calType, conf->channel->center_freq);
+
+	ah->curchan->CalValid &= ~currCal->calData->calType;
+	currCal->calState = CAL_WAITING;
+
+	return false;
+}
+
+void ath9k_hw_start_nfcal(struct ath_hw *ah)
+{
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_ENABLE_NF);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	struct ath9k_nfcal_hist *h;
+	int i, j;
+	int32_t val;
+	const u32 ar5416_cca_regs[6] = {
+		AR_PHY_CCA,
+		AR_PHY_CH1_CCA,
+		AR_PHY_CH2_CCA,
+		AR_PHY_EXT_CCA,
+		AR_PHY_CH1_EXT_CCA,
+		AR_PHY_CH2_EXT_CCA
+	};
+	u8 chainmask;
+
+	if (AR_SREV_9285(ah))
+		chainmask = 0x9;
+	else if (AR_SREV_9280(ah))
+		chainmask = 0x1B;
+	else
+		chainmask = 0x3F;
+
+	h = ah->nfCalHist;
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		if (chainmask & (1 << i)) {
+			val = REG_READ(ah, ar5416_cca_regs[i]);
+			val &= 0xFFFFFE00;
+			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
+			REG_WRITE(ah, ar5416_cca_regs[i], val);
+		}
+	}
+
+	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_ENABLE_NF);
+	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+	for (j = 0; j < 1000; j++) {
+		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+		     AR_PHY_AGC_CONTROL_NF) == 0)
+			break;
+		udelay(10);
+	}
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		if (chainmask & (1 << i)) {
+			val = REG_READ(ah, ar5416_cca_regs[i]);
+			val &= 0xFFFFFE00;
+			val |= (((u32) (-50) << 1) & 0x1ff);
+			REG_WRITE(ah, ar5416_cca_regs[i], val);
+		}
+	}
+}
+
+int16_t ath9k_hw_getnf(struct ath_hw *ah,
+		       struct ath9k_channel *chan)
+{
+	int16_t nf, nfThresh;
+	int16_t nfarray[NUM_NF_READINGS] = { 0 };
+	struct ath9k_nfcal_hist *h;
+	struct ieee80211_channel *c = chan->chan;
+
+	chan->channelFlags &= (~CHANNEL_CW_INT);
+	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+			"NF did not complete in calibration window\n");
+		nf = 0;
+		chan->rawNoiseFloor = nf;
+		return chan->rawNoiseFloor;
+	} else {
+		ath9k_hw_do_getnf(ah, nfarray);
+		nf = nfarray[0];
+		if (getNoiseFloorThresh(ah, c->band, &nfThresh)
+		    && nf > nfThresh) {
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"noise floor failed detected; "
+				"detected %d, threshold %d\n",
+				nf, nfThresh);
+			chan->channelFlags |= CHANNEL_CW_INT;
+		}
+	}
+
+	h = ah->nfCalHist;
+
+	ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
+	chan->rawNoiseFloor = h[0].privNF;
+
+	return chan->rawNoiseFloor;
+}
+
+void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
+{
+	int i, j;
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		ah->nfCalHist[i].currIndex = 0;
+		ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
+		ah->nfCalHist[i].invalidNFcount =
+			AR_PHY_CCA_FILTERWINDOW_LENGTH;
+		for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
+			ah->nfCalHist[i].nfCalBuffer[j] =
+				AR_PHY_CCA_MAX_GOOD_VALUE;
+		}
+	}
+}
+
+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	s16 nf;
+
+	if (chan->rawNoiseFloor == 0)
+		nf = -96;
+	else
+		nf = chan->rawNoiseFloor;
+
+	if (!ath9k_hw_nf_in_range(ah, nf))
+		nf = ATH_DEFAULT_NOISE_FLOOR;
+
+	return nf;
+}
+
+static void ath9k_olc_temp_compensation(struct ath_hw *ah)
+{
+	u32 rddata, i;
+	int delta, currPDADC, regval;
+
+	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
+
+	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
+
+	if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
+		delta = (currPDADC - ah->initPDADC + 4) / 8;
+	else
+		delta = (currPDADC - ah->initPDADC + 5) / 10;
+
+	if (delta != ah->PDADCdelta) {
+		ah->PDADCdelta = delta;
+		for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
+			regval = ah->originalGain[i] - delta;
+			if (regval < 0)
+				regval = 0;
+
+			REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
+					AR_PHY_TX_GAIN, regval);
+		}
+	}
+}
+
+static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
+{
+
+	u32 regVal;
+	int i, offset, offs_6_1, offs_0;
+	u32 ccomp_org, reg_field;
+	u32 regList[][2] = {
+		{ 0x786c, 0 },
+		{ 0x7854, 0 },
+		{ 0x7820, 0 },
+		{ 0x7824, 0 },
+		{ 0x7868, 0 },
+		{ 0x783c, 0 },
+		{ 0x7838, 0 },
+	};
+
+	if (AR_SREV_9285_11(ah)) {
+		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
+		udelay(10);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(regList); i++)
+		regList[i][1] = REG_READ(ah, regList[i][0]);
+
+	regVal = REG_READ(ah, 0x7834);
+	regVal &= (~(0x1));
+	REG_WRITE(ah, 0x7834, regVal);
+	regVal = REG_READ(ah, 0x9808);
+	regVal |= (0x1 << 27);
+	REG_WRITE(ah, 0x9808, regVal);
+
+	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
+
+	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+	udelay(30);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
+
+	for (i = 6; i > 0; i--) {
+		regVal = REG_READ(ah, 0x7834);
+		regVal |= (1 << (19 + i));
+		REG_WRITE(ah, 0x7834, regVal);
+		udelay(1);
+		regVal = REG_READ(ah, 0x7834);
+		regVal &= (~(0x1 << (19 + i)));
+		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
+		regVal |= (reg_field << (19 + i));
+		REG_WRITE(ah, 0x7834, regVal);
+	}
+
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
+	udelay(1);
+	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
+	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
+	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
+
+	offset = (offs_6_1<<1) | offs_0;
+	offset = offset - 0;
+	offs_6_1 = offset>>1;
+	offs_0 = offset & 1;
+
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
+
+	regVal = REG_READ(ah, 0x7834);
+	regVal |= 0x1;
+	REG_WRITE(ah, 0x7834, regVal);
+	regVal = REG_READ(ah, 0x9808);
+	regVal &= (~(0x1 << 27));
+	REG_WRITE(ah, 0x9808, regVal);
+
+	for (i = 0; i < ARRAY_SIZE(regList); i++)
+		REG_WRITE(ah, regList[i][0], regList[i][1]);
+
+	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
+
+	if (AR_SREV_9285_11(ah))
+		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+}
+
+bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
+			u8 rxchainmask, bool longcal)
+{
+	bool iscaldone = true;
+	struct ath9k_cal_list *currCal = ah->cal_list_curr;
+
+	if (currCal &&
+	    (currCal->calState == CAL_RUNNING ||
+	     currCal->calState == CAL_WAITING)) {
+		iscaldone = ath9k_hw_per_calibration(ah, chan,
+						     rxchainmask, currCal);
+		if (iscaldone) {
+			ah->cal_list_curr = currCal = currCal->calNext;
+
+			if (currCal->calState == CAL_WAITING) {
+				iscaldone = false;
+				ath9k_hw_reset_calibration(ah, currCal);
+			}
+		}
+	}
+
+	if (longcal) {
+		if (AR_SREV_9285_11_OR_LATER(ah))
+			ath9k_hw_9285_pa_cal(ah);
+
+		if (OLC_FOR_AR9280_20_LATER)
+			ath9k_olc_temp_compensation(ah);
+		ath9k_hw_getnf(ah, chan);
+		ath9k_hw_loadnf(ah, ah->curchan);
+		ath9k_hw_start_nfcal(ah);
+	}
+
+	return iscaldone;
+}
+
+static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+	if (IS_CHAN_HT20(chan)) {
+		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+			    AR_PHY_AGC_CONTROL_FLTR_CAL);
+		REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset "
+				"calibration failed to complete in "
+				"1ms; noisy ??\n");
+			return false;
+		}
+		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+	}
+	REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+	REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
+			  0, AH_WAIT_TIMEOUT)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration "
+				"failed to complete in 1ms; noisy ??\n");
+		return false;
+	}
+
+	REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+	REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+
+	return true;
+}
+
+bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	if (AR_SREV_9285_12_OR_LATER(ah)) {
+		if (!ar9285_clc(ah, chan))
+			return false;
+	} else {
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+		}
+
+		/* Calibrate the AGC */
+		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+			  REG_READ(ah, AR_PHY_AGC_CONTROL) |
+			  AR_PHY_AGC_CONTROL_CAL);
+
+		/* Poll for offset calibration complete */
+		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
+				   0, AH_WAIT_TIMEOUT)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"offset calibration failed to complete in 1ms; "
+				"noisy environment?\n");
+			return false;
+		}
+
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+		}
+	}
+
+	/* Do PA Calibration */
+	if (AR_SREV_9285_11_OR_LATER(ah))
+		ath9k_hw_9285_pa_cal(ah);
+
+	/* Do NF Calibration after DC offset and other calibrations */
+	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+		  REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
+
+	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+
+	/* Enable IQ, ADC Gain and ADC DC offset CALs */
+	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
+		if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
+			INIT_CAL(&ah->adcgain_caldata);
+			INSERT_CAL(ah, &ah->adcgain_caldata);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"enabling ADC Gain Calibration.\n");
+		}
+		if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
+			INIT_CAL(&ah->adcdc_caldata);
+			INSERT_CAL(ah, &ah->adcdc_caldata);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"enabling ADC DC Calibration.\n");
+		}
+		if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
+			INIT_CAL(&ah->iq_caldata);
+			INSERT_CAL(ah, &ah->iq_caldata);
+			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+				"enabling IQ Calibration.\n");
+		}
+
+		ah->cal_list_curr = ah->cal_list;
+
+		if (ah->cal_list_curr)
+			ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
+	}
+
+	chan->CalValid = 0;
+
+	return true;
+}
+
+const struct ath9k_percal_data iq_cal_multi_sample = {
+	IQ_MISMATCH_CAL,
+	MAX_CAL_SAMPLES,
+	PER_MIN_LOG_COUNT,
+	ath9k_hw_iqcal_collect,
+	ath9k_hw_iqcalibrate
+};
+const struct ath9k_percal_data iq_cal_single_sample = {
+	IQ_MISMATCH_CAL,
+	MIN_CAL_SAMPLES,
+	PER_MAX_LOG_COUNT,
+	ath9k_hw_iqcal_collect,
+	ath9k_hw_iqcalibrate
+};
+const struct ath9k_percal_data adc_gain_cal_multi_sample = {
+	ADC_GAIN_CAL,
+	MAX_CAL_SAMPLES,
+	PER_MIN_LOG_COUNT,
+	ath9k_hw_adc_gaincal_collect,
+	ath9k_hw_adc_gaincal_calibrate
+};
+const struct ath9k_percal_data adc_gain_cal_single_sample = {
+	ADC_GAIN_CAL,
+	MIN_CAL_SAMPLES,
+	PER_MAX_LOG_COUNT,
+	ath9k_hw_adc_gaincal_collect,
+	ath9k_hw_adc_gaincal_calibrate
+};
+const struct ath9k_percal_data adc_dc_cal_multi_sample = {
+	ADC_DC_CAL,
+	MAX_CAL_SAMPLES,
+	PER_MIN_LOG_COUNT,
+	ath9k_hw_adc_dccal_collect,
+	ath9k_hw_adc_dccal_calibrate
+};
+const struct ath9k_percal_data adc_dc_cal_single_sample = {
+	ADC_DC_CAL,
+	MIN_CAL_SAMPLES,
+	PER_MAX_LOG_COUNT,
+	ath9k_hw_adc_dccal_collect,
+	ath9k_hw_adc_dccal_calibrate
+};
+const struct ath9k_percal_data adc_init_dc_cal = {
+	ADC_DC_INIT_CAL,
+	MIN_CAL_SAMPLES,
+	INIT_LOG_COUNT,
+	ath9k_hw_adc_dccal_collect,
+	ath9k_hw_adc_dccal_calibrate
+};
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/calib.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/calib.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/calib.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/calib.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef CALIB_H
+#define CALIB_H
+
+extern const struct ath9k_percal_data iq_cal_multi_sample;
+extern const struct ath9k_percal_data iq_cal_single_sample;
+extern const struct ath9k_percal_data adc_gain_cal_multi_sample;
+extern const struct ath9k_percal_data adc_gain_cal_single_sample;
+extern const struct ath9k_percal_data adc_dc_cal_multi_sample;
+extern const struct ath9k_percal_data adc_dc_cal_single_sample;
+extern const struct ath9k_percal_data adc_init_dc_cal;
+
+#define AR_PHY_CCA_MAX_GOOD_VALUE      		-85
+#define AR_PHY_CCA_MAX_HIGH_VALUE      		-62
+#define AR_PHY_CCA_MIN_BAD_VALUE       		-140
+#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT     3
+#define AR_PHY_CCA_FILTERWINDOW_LENGTH          5
+
+#define NUM_NF_READINGS       6
+#define ATH9K_NF_CAL_HIST_MAX 5
+
+struct ar5416IniArray {
+	u32 *ia_array;
+	u32 ia_rows;
+	u32 ia_columns;
+};
+
+#define INIT_INI_ARRAY(iniarray, array, rows, columns) do {	\
+		(iniarray)->ia_array = (u32 *)(array);		\
+		(iniarray)->ia_rows = (rows);			\
+		(iniarray)->ia_columns = (columns);		\
+	} while (0)
+
+#define INI_RA(iniarray, row, column) \
+	(((iniarray)->ia_array)[(row) *	((iniarray)->ia_columns) + (column)])
+
+#define INIT_CAL(_perCal) do {				\
+		(_perCal)->calState = CAL_WAITING;	\
+		(_perCal)->calNext = NULL;		\
+	} while (0)
+
+#define INSERT_CAL(_ahp, _perCal)					\
+	do {								\
+		if ((_ahp)->cal_list_last == NULL) {			\
+			(_ahp)->cal_list =				\
+				(_ahp)->cal_list_last = (_perCal);	\
+			((_ahp)->cal_list_last)->calNext = (_perCal); \
+		} else {						\
+			((_ahp)->cal_list_last)->calNext = (_perCal); \
+			(_ahp)->cal_list_last = (_perCal);		\
+			(_perCal)->calNext = (_ahp)->cal_list;	\
+		}							\
+	} while (0)
+
+enum ath9k_cal_types {
+	ADC_DC_INIT_CAL = 0x1,
+	ADC_GAIN_CAL = 0x2,
+	ADC_DC_CAL = 0x4,
+	IQ_MISMATCH_CAL = 0x8
+};
+
+enum ath9k_cal_state {
+	CAL_INACTIVE,
+	CAL_WAITING,
+	CAL_RUNNING,
+	CAL_DONE
+};
+
+#define MIN_CAL_SAMPLES     1
+#define MAX_CAL_SAMPLES    64
+#define INIT_LOG_COUNT      5
+#define PER_MIN_LOG_COUNT   2
+#define PER_MAX_LOG_COUNT  10
+
+struct ath9k_percal_data {
+	enum ath9k_cal_types calType;
+	u32 calNumSamples;
+	u32 calCountMax;
+	void (*calCollect) (struct ath_hw *);
+	void (*calPostProc) (struct ath_hw *, u8);
+};
+
+struct ath9k_cal_list {
+	const struct ath9k_percal_data *calData;
+	enum ath9k_cal_state calState;
+	struct ath9k_cal_list *calNext;
+};
+
+struct ath9k_nfcal_hist {
+	int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX];
+	u8 currIndex;
+	int16_t privNF;
+	u8 invalidNFcount;
+};
+
+bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
+void ath9k_hw_start_nfcal(struct ath_hw *ah);
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
+int16_t ath9k_hw_getnf(struct ath_hw *ah,
+		       struct ath9k_channel *chan);
+void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
+bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
+			u8 rxchainmask, bool longcal);
+bool ath9k_hw_init_cal(struct ath_hw *ah,
+		       struct ath9k_channel *chan);
+
+#endif /* CALIB_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/debug.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/debug.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/debug.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+
+#include "ath9k.h"
+
+static unsigned int ath9k_debug = DBG_DEFAULT;
+module_param_named(debug, ath9k_debug, uint, 0);
+
+static struct dentry *ath9k_debugfs_root;
+
+void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...)
+{
+	if (!sc)
+		return;
+
+	if (sc->debug.debug_mask & dbg_mask) {
+		va_list args;
+
+		va_start(args, fmt);
+		printk(KERN_DEBUG "ath9k: ");
+		vprintk(fmt, args);
+		va_end(args);
+	}
+}
+
+static int ath9k_debugfs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t read_file_debug(struct file *file, char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	char buf[32];
+	unsigned int len;
+
+	len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.debug_mask);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	unsigned long mask;
+	char buf[32];
+	ssize_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EINVAL;
+
+	buf[len] = '\0';
+	if (strict_strtoul(buf, 0, &mask))
+		return -EINVAL;
+
+	sc->debug.debug_mask = mask;
+	return count;
+}
+
+static const struct file_operations fops_debug = {
+	.read = read_file_debug,
+	.write = write_file_debug,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE
+};
+
+static ssize_t read_file_dma(struct file *file, char __user *user_buf,
+			     size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath_hw *ah = sc->sc_ah;
+	char buf[1024];
+	unsigned int len = 0;
+	u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
+	int i, qcuOffset = 0, dcuOffset = 0;
+	u32 *qcuBase = &val[0], *dcuBase = &val[4];
+
+	REG_WRITE(ah, AR_MACMISC,
+		  ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+		   (AR_MACMISC_MISC_OBS_BUS_1 <<
+		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"Raw DMA Debug values:\n");
+
+	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
+		if (i % 4 == 0)
+			len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+		val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
+		len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
+				i, val[i]);
+	}
+
+	len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+
+	for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
+		if (i == 8) {
+			qcuOffset = 0;
+			qcuBase++;
+		}
+
+		if (i == 6) {
+			dcuOffset = 0;
+			dcuBase++;
+		}
+
+		len += snprintf(buf + len, sizeof(buf) - len,
+			"%2d          %2x      %1x     %2x           %2x\n",
+			i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+			(*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+			val[2] & (0x7 << (i * 3)) >> (i * 3),
+			(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+	}
+
+	len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
+		(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"qcu_complete state: %2x    dcu_complete state:     %2x\n",
+		(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"dcu_arb state:      %2x    dcu_fp state:           %2x\n",
+		(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
+		(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
+		(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
+		(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
+
+	len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
+			REG_READ(ah, AR_OBS_BUS_1));
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_dma = {
+	.read = read_file_dma,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE
+};
+
+
+void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
+{
+	if (status)
+		sc->debug.stats.istats.total++;
+	if (status & ATH9K_INT_RX)
+		sc->debug.stats.istats.rxok++;
+	if (status & ATH9K_INT_RXEOL)
+		sc->debug.stats.istats.rxeol++;
+	if (status & ATH9K_INT_RXORN)
+		sc->debug.stats.istats.rxorn++;
+	if (status & ATH9K_INT_TX)
+		sc->debug.stats.istats.txok++;
+	if (status & ATH9K_INT_TXURN)
+		sc->debug.stats.istats.txurn++;
+	if (status & ATH9K_INT_MIB)
+		sc->debug.stats.istats.mib++;
+	if (status & ATH9K_INT_RXPHY)
+		sc->debug.stats.istats.rxphyerr++;
+	if (status & ATH9K_INT_RXKCM)
+		sc->debug.stats.istats.rx_keycache_miss++;
+	if (status & ATH9K_INT_SWBA)
+		sc->debug.stats.istats.swba++;
+	if (status & ATH9K_INT_BMISS)
+		sc->debug.stats.istats.bmiss++;
+	if (status & ATH9K_INT_BNR)
+		sc->debug.stats.istats.bnr++;
+	if (status & ATH9K_INT_CST)
+		sc->debug.stats.istats.cst++;
+	if (status & ATH9K_INT_GTT)
+		sc->debug.stats.istats.gtt++;
+	if (status & ATH9K_INT_TIM)
+		sc->debug.stats.istats.tim++;
+	if (status & ATH9K_INT_CABEND)
+		sc->debug.stats.istats.cabend++;
+	if (status & ATH9K_INT_DTIMSYNC)
+		sc->debug.stats.istats.dtimsync++;
+	if (status & ATH9K_INT_DTIM)
+		sc->debug.stats.istats.dtim++;
+}
+
+static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	char buf[512];
+	unsigned int len = 0;
+
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "TIM", sc->debug.stats.istats.tim);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim);
+	len += snprintf(buf + len, sizeof(buf) - len,
+		"%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_interrupt = {
+	.read = read_file_interrupt,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE
+};
+
+void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
+{
+	struct ath_tx_info_priv *tx_info_priv = NULL;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_tx_rate *rates = tx_info->status.rates;
+	int final_ts_idx, idx;
+	struct ath_rc_stats *stats;
+
+	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+	final_ts_idx = tx_info_priv->tx.ts_rateindex;
+	idx = rates[final_ts_idx].idx;
+	stats = &sc->debug.stats.rcstats[idx];
+	stats->success++;
+}
+
+void ath_debug_stat_retries(struct ath_softc *sc, int rix,
+			    int xretries, int retries, u8 per)
+{
+	struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
+
+	stats->xretries += xretries;
+	stats->retries += retries;
+	stats->per = per;
+}
+
+static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	char *buf;
+	unsigned int len = 0, max;
+	int i = 0;
+	ssize_t retval;
+
+	if (sc->cur_rate_table == NULL)
+		return 0;
+
+	max = 80 + sc->cur_rate_table->rate_cnt * 64;
+	buf = kmalloc(max + 1, GFP_KERNEL);
+	if (buf == NULL)
+		return 0;
+	buf[max] = 0;
+
+	len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success",
+		       "Retries", "XRetries", "PER");
+
+	for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
+		u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
+		struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
+
+		len += snprintf(buf + len, max - len,
+			"%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000,
+			(ratekbps % 1000) / 100, stats->success,
+			stats->retries, stats->xretries,
+			stats->per);
+	}
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+	return retval;
+}
+
+static const struct file_operations fops_rcstat = {
+	.read = read_file_rcstat,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE
+};
+
+static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
+{
+	switch (state) {
+	case ATH_WIPHY_INACTIVE:
+		return "INACTIVE";
+	case ATH_WIPHY_ACTIVE:
+		return "ACTIVE";
+	case ATH_WIPHY_PAUSING:
+		return "PAUSING";
+	case ATH_WIPHY_PAUSED:
+		return "PAUSED";
+	case ATH_WIPHY_SCAN:
+		return "SCAN";
+	}
+	return "?";
+}
+
+static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
+			       size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	char buf[512];
+	unsigned int len = 0;
+	int i;
+	u8 addr[ETH_ALEN];
+
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"primary: %s (%s chan=%d ht=%d)\n",
+			wiphy_name(sc->pri_wiphy->hw->wiphy),
+			ath_wiphy_state_str(sc->pri_wiphy->state),
+			sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		struct ath_wiphy *aphy = sc->sec_wiphy[i];
+		if (aphy == NULL)
+			continue;
+		len += snprintf(buf + len, sizeof(buf) - len,
+				"secondary: %s (%s chan=%d ht=%d)\n",
+				wiphy_name(aphy->hw->wiphy),
+				ath_wiphy_state_str(aphy->state),
+				aphy->chan_idx, aphy->chan_is_ht);
+	}
+
+	put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr);
+	put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"addr: %pM\n", addr);
+	put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr);
+	put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
+	len += snprintf(buf + len, sizeof(buf) - len,
+			"addrmask: %pM\n", addr);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name)
+{
+	int i;
+	if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0)
+		return sc->pri_wiphy;
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		struct ath_wiphy *aphy = sc->sec_wiphy[i];
+		if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0)
+			return aphy;
+	}
+	return NULL;
+}
+
+static int del_wiphy(struct ath_softc *sc, const char *name)
+{
+	struct ath_wiphy *aphy = get_wiphy(sc, name);
+	if (!aphy)
+		return -ENOENT;
+	return ath9k_wiphy_del(aphy);
+}
+
+static int pause_wiphy(struct ath_softc *sc, const char *name)
+{
+	struct ath_wiphy *aphy = get_wiphy(sc, name);
+	if (!aphy)
+		return -ENOENT;
+	return ath9k_wiphy_pause(aphy);
+}
+
+static int unpause_wiphy(struct ath_softc *sc, const char *name)
+{
+	struct ath_wiphy *aphy = get_wiphy(sc, name);
+	if (!aphy)
+		return -ENOENT;
+	return ath9k_wiphy_unpause(aphy);
+}
+
+static int select_wiphy(struct ath_softc *sc, const char *name)
+{
+	struct ath_wiphy *aphy = get_wiphy(sc, name);
+	if (!aphy)
+		return -ENOENT;
+	return ath9k_wiphy_select(aphy);
+}
+
+static int schedule_wiphy(struct ath_softc *sc, const char *msec)
+{
+	ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0));
+	return 0;
+}
+
+static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	char buf[50];
+	size_t len;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+	buf[len] = '\0';
+	if (len > 0 && buf[len - 1] == '\n')
+		buf[len - 1] = '\0';
+
+	if (strncmp(buf, "add", 3) == 0) {
+		int res = ath9k_wiphy_add(sc);
+		if (res < 0)
+			return res;
+	} else if (strncmp(buf, "del=", 4) == 0) {
+		int res = del_wiphy(sc, buf + 4);
+		if (res < 0)
+			return res;
+	} else if (strncmp(buf, "pause=", 6) == 0) {
+		int res = pause_wiphy(sc, buf + 6);
+		if (res < 0)
+			return res;
+	} else if (strncmp(buf, "unpause=", 8) == 0) {
+		int res = unpause_wiphy(sc, buf + 8);
+		if (res < 0)
+			return res;
+	} else if (strncmp(buf, "select=", 7) == 0) {
+		int res = select_wiphy(sc, buf + 7);
+		if (res < 0)
+			return res;
+	} else if (strncmp(buf, "schedule=", 9) == 0) {
+		int res = schedule_wiphy(sc, buf + 9);
+		if (res < 0)
+			return res;
+	} else
+		return -EOPNOTSUPP;
+
+	return count;
+}
+
+static const struct file_operations fops_wiphy = {
+	.read = read_file_wiphy,
+	.write = write_file_wiphy,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE
+};
+
+
+int ath9k_init_debug(struct ath_softc *sc)
+{
+	sc->debug.debug_mask = ath9k_debug;
+
+	if (!ath9k_debugfs_root)
+		return -ENOENT;
+
+	sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
+						      ath9k_debugfs_root);
+	if (!sc->debug.debugfs_phy)
+		goto err;
+
+	sc->debug.debugfs_debug = debugfs_create_file("debug",
+		S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
+	if (!sc->debug.debugfs_debug)
+		goto err;
+
+	sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
+				       sc->debug.debugfs_phy, sc, &fops_dma);
+	if (!sc->debug.debugfs_dma)
+		goto err;
+
+	sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
+						     S_IRUGO,
+						     sc->debug.debugfs_phy,
+						     sc, &fops_interrupt);
+	if (!sc->debug.debugfs_interrupt)
+		goto err;
+
+	sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
+						  S_IRUGO,
+						  sc->debug.debugfs_phy,
+						  sc, &fops_rcstat);
+	if (!sc->debug.debugfs_rcstat)
+		goto err;
+
+	sc->debug.debugfs_wiphy = debugfs_create_file(
+		"wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc,
+		&fops_wiphy);
+	if (!sc->debug.debugfs_wiphy)
+		goto err;
+
+	return 0;
+err:
+	ath9k_exit_debug(sc);
+	return -ENOMEM;
+}
+
+void ath9k_exit_debug(struct ath_softc *sc)
+{
+	debugfs_remove(sc->debug.debugfs_wiphy);
+	debugfs_remove(sc->debug.debugfs_rcstat);
+	debugfs_remove(sc->debug.debugfs_interrupt);
+	debugfs_remove(sc->debug.debugfs_dma);
+	debugfs_remove(sc->debug.debugfs_debug);
+	debugfs_remove(sc->debug.debugfs_phy);
+}
+
+int ath9k_debug_create_root(void)
+{
+	ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (!ath9k_debugfs_root)
+		return -ENOENT;
+
+	return 0;
+}
+
+void ath9k_debug_remove_root(void)
+{
+	debugfs_remove(ath9k_debugfs_root);
+	ath9k_debugfs_root = NULL;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/debug.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/debug.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/debug.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/debug.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+enum ATH_DEBUG {
+	ATH_DBG_RESET		= 0x00000001,
+	ATH_DBG_QUEUE		= 0x00000002,
+	ATH_DBG_EEPROM		= 0x00000004,
+	ATH_DBG_CALIBRATE	= 0x00000008,
+	ATH_DBG_INTERRUPT	= 0x00000010,
+	ATH_DBG_REGULATORY	= 0x00000020,
+	ATH_DBG_ANI		= 0x00000040,
+	ATH_DBG_XMIT		= 0x00000080,
+	ATH_DBG_BEACON		= 0x00000100,
+	ATH_DBG_CONFIG		= 0x00000200,
+	ATH_DBG_FATAL		= 0x00000400,
+	ATH_DBG_PS		= 0x00000800,
+	ATH_DBG_ANY		= 0xffffffff
+};
+
+#define DBG_DEFAULT (ATH_DBG_FATAL)
+
+#ifdef CONFIG_ATH9K_DEBUG
+
+/**
+ * struct ath_interrupt_stats - Contains statistics about interrupts
+ * @total: Total no. of interrupts generated so far
+ * @rxok: RX with no errors
+ * @rxeol: RX with no more RXDESC available
+ * @rxorn: RX FIFO overrun
+ * @txok: TX completed at the requested rate
+ * @txurn: TX FIFO underrun
+ * @mib: MIB regs reaching its threshold
+ * @rxphyerr: RX with phy errors
+ * @rx_keycache_miss: RX with key cache misses
+ * @swba: Software Beacon Alert
+ * @bmiss: Beacon Miss
+ * @bnr: Beacon Not Ready
+ * @cst: Carrier Sense TImeout
+ * @gtt: Global TX Timeout
+ * @tim: RX beacon TIM occurrence
+ * @cabend: RX End of CAB traffic
+ * @dtimsync: DTIM sync lossage
+ * @dtim: RX Beacon with DTIM
+ */
+struct ath_interrupt_stats {
+	u32 total;
+	u32 rxok;
+	u32 rxeol;
+	u32 rxorn;
+	u32 txok;
+	u32 txeol;
+	u32 txurn;
+	u32 mib;
+	u32 rxphyerr;
+	u32 rx_keycache_miss;
+	u32 swba;
+	u32 bmiss;
+	u32 bnr;
+	u32 cst;
+	u32 gtt;
+	u32 tim;
+	u32 cabend;
+	u32 dtimsync;
+	u32 dtim;
+};
+
+struct ath_rc_stats {
+	u32 success;
+	u32 retries;
+	u32 xretries;
+	u8 per;
+};
+
+struct ath_stats {
+	struct ath_interrupt_stats istats;
+	struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+};
+
+struct ath9k_debug {
+	int debug_mask;
+	struct dentry *debugfs_phy;
+	struct dentry *debugfs_debug;
+	struct dentry *debugfs_dma;
+	struct dentry *debugfs_interrupt;
+	struct dentry *debugfs_rcstat;
+	struct dentry *debugfs_wiphy;
+	struct ath_stats stats;
+};
+
+void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...);
+int ath9k_init_debug(struct ath_softc *sc);
+void ath9k_exit_debug(struct ath_softc *sc);
+int ath9k_debug_create_root(void);
+void ath9k_debug_remove_root(void);
+void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
+void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
+void ath_debug_stat_retries(struct ath_softc *sc, int rix,
+			    int xretries, int retries, u8 per);
+
+#else
+
+static inline void DPRINTF(struct ath_softc *sc, int dbg_mask,
+			   const char *fmt, ...)
+{
+}
+
+static inline int ath9k_init_debug(struct ath_softc *sc)
+{
+	return 0;
+}
+
+static inline void ath9k_exit_debug(struct ath_softc *sc)
+{
+}
+
+static inline int ath9k_debug_create_root(void)
+{
+	return 0;
+}
+
+static inline void ath9k_debug_remove_root(void)
+{
+}
+
+static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
+					    enum ath9k_int status)
+{
+}
+
+static inline void ath_debug_stat_rc(struct ath_softc *sc,
+				     struct sk_buff *skb)
+{
+}
+
+static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
+					  int xretries, int retries, u8 per)
+{
+}
+
+#endif /* CONFIG_ATH9K_DEBUG */
+
+#endif /* DEBUG_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/eeprom.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/eeprom.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/eeprom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/eeprom.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2786 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah,
+				      u32 reg, u32 mask,
+				      u32 shift, u32 val)
+{
+	u32 regVal;
+
+	regVal = REG_READ(ah, reg) & ~mask;
+	regVal |= (val << shift) & mask;
+
+	REG_WRITE(ah, reg, regVal);
+
+	if (ah->config.analog_shiftreg)
+		udelay(100);
+
+	return;
+}
+
+static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
+{
+
+	if (fbin == AR5416_BCHAN_UNUSED)
+		return fbin;
+
+	return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+static inline int16_t ath9k_hw_interpolate(u16 target,
+					   u16 srcLeft, u16 srcRight,
+					   int16_t targetLeft,
+					   int16_t targetRight)
+{
+	int16_t rv;
+
+	if (srcRight == srcLeft) {
+		rv = targetLeft;
+	} else {
+		rv = (int16_t) (((target - srcLeft) * targetRight +
+				 (srcRight - target) * targetLeft) /
+				(srcRight - srcLeft));
+	}
+	return rv;
+}
+
+static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
+						  u16 listSize, u16 *indexL,
+						  u16 *indexR)
+{
+	u16 i;
+
+	if (target <= pList[0]) {
+		*indexL = *indexR = 0;
+		return true;
+	}
+	if (target >= pList[listSize - 1]) {
+		*indexL = *indexR = (u16) (listSize - 1);
+		return true;
+	}
+
+	for (i = 0; i < listSize - 1; i++) {
+		if (pList[i] == target) {
+			*indexL = *indexR = i;
+			return true;
+		}
+		if (target < pList[i + 1]) {
+			*indexL = i;
+			*indexR = (u16) (i + 1);
+			return false;
+		}
+	}
+	return false;
+}
+
+static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
+{
+	struct ath_softc *sc = ah->ah_sc;
+
+	return sc->bus_ops->eeprom_read(ah, off, data);
+}
+
+static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+					   u8 *pVpdList, u16 numIntercepts,
+					   u8 *pRetVpdList)
+{
+	u16 i, k;
+	u8 currPwr = pwrMin;
+	u16 idxL = 0, idxR = 0;
+
+	for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+		ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
+					       numIntercepts, &(idxL),
+					       &(idxR));
+		if (idxR < 1)
+			idxR = 1;
+		if (idxL == numIntercepts - 1)
+			idxL = (u16) (numIntercepts - 2);
+		if (pPwrList[idxL] == pPwrList[idxR])
+			k = pVpdList[idxL];
+		else
+			k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
+				   (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
+				  (pPwrList[idxR] - pPwrList[idxL]));
+		pRetVpdList[i] = (u8) k;
+		currPwr += 2;
+	}
+
+	return true;
+}
+
+static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
+				      struct ath9k_channel *chan,
+				      struct cal_target_power_leg *powInfo,
+				      u16 numChannels,
+				      struct cal_target_power_leg *pNewPower,
+				      u16 numRates, bool isExtTarget)
+{
+	struct chan_centers centers;
+	u16 clo, chi;
+	int i;
+	int matchIndex = -1, lowIndex = -1;
+	u16 freq;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
+
+	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
+				       IS_CHAN_2GHZ(chan))) {
+		matchIndex = 0;
+	} else {
+		for (i = 0; (i < numChannels) &&
+			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						       IS_CHAN_2GHZ(chan))) {
+				matchIndex = i;
+				break;
+			} else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						      IS_CHAN_2GHZ(chan))) &&
+				   (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+						      IS_CHAN_2GHZ(chan)))) {
+				lowIndex = i - 1;
+				break;
+			}
+		}
+		if ((matchIndex == -1) && (lowIndex == -1))
+			matchIndex = i - 1;
+	}
+
+	if (matchIndex != -1) {
+		*pNewPower = powInfo[matchIndex];
+	} else {
+		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+					 IS_CHAN_2GHZ(chan));
+		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+					 IS_CHAN_2GHZ(chan));
+
+		for (i = 0; i < numRates; i++) {
+			pNewPower->tPow2x[i] =
+				(u8)ath9k_hw_interpolate(freq, clo, chi,
+						powInfo[lowIndex].tPow2x[i],
+						powInfo[lowIndex + 1].tPow2x[i]);
+		}
+	}
+}
+
+static void ath9k_get_txgain_index(struct ath_hw *ah,
+		struct ath9k_channel *chan,
+		struct calDataPerFreqOpLoop *rawDatasetOpLoop,
+		u8 *calChans,  u16 availPiers, u8 *pwr, u8 *pcdacIdx)
+{
+	u8 pcdac, i = 0;
+	u16 idxL = 0, idxR = 0, numPiers;
+	bool match;
+	struct chan_centers centers;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	for (numPiers = 0; numPiers < availPiers; numPiers++)
+		if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
+			break;
+
+	match = ath9k_hw_get_lower_upper_index(
+			(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
+			calChans, numPiers, &idxL, &idxR);
+	if (match) {
+		pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
+		*pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
+	} else {
+		pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
+		*pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
+				rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+	}
+
+	while (pcdac > ah->originalGain[i] &&
+			i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
+		i++;
+
+	*pcdacIdx = i;
+	return;
+}
+
+static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
+				u32 initTxGain,
+				int txPower,
+				u8 *pPDADCValues)
+{
+	u32 i;
+	u32 offset;
+
+	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
+			AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
+			AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+
+	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
+			AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
+
+	offset = txPower;
+	for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
+		if (i < offset)
+			pPDADCValues[i] = 0x0;
+		else
+			pPDADCValues[i] = 0xFF;
+}
+
+
+
+
+static void ath9k_hw_get_target_powers(struct ath_hw *ah,
+				       struct ath9k_channel *chan,
+				       struct cal_target_power_ht *powInfo,
+				       u16 numChannels,
+				       struct cal_target_power_ht *pNewPower,
+				       u16 numRates, bool isHt40Target)
+{
+	struct chan_centers centers;
+	u16 clo, chi;
+	int i;
+	int matchIndex = -1, lowIndex = -1;
+	u16 freq;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+		matchIndex = 0;
+	} else {
+		for (i = 0; (i < numChannels) &&
+			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						       IS_CHAN_2GHZ(chan))) {
+				matchIndex = i;
+				break;
+			} else
+				if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+						       IS_CHAN_2GHZ(chan))) &&
+				    (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+						       IS_CHAN_2GHZ(chan)))) {
+					lowIndex = i - 1;
+					break;
+				}
+		}
+		if ((matchIndex == -1) && (lowIndex == -1))
+			matchIndex = i - 1;
+	}
+
+	if (matchIndex != -1) {
+		*pNewPower = powInfo[matchIndex];
+	} else {
+		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+					 IS_CHAN_2GHZ(chan));
+		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+					 IS_CHAN_2GHZ(chan));
+
+		for (i = 0; i < numRates; i++) {
+			pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
+						clo, chi,
+						powInfo[lowIndex].tPow2x[i],
+						powInfo[lowIndex + 1].tPow2x[i]);
+		}
+	}
+}
+
+static u16 ath9k_hw_get_max_edge_power(u16 freq,
+				       struct cal_ctl_edges *pRdEdgesPower,
+				       bool is2GHz, int num_band_edges)
+{
+	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	int i;
+
+	for (i = 0; (i < num_band_edges) &&
+		     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+		if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
+			twiceMaxEdgePower = pRdEdgesPower[i].tPower;
+			break;
+		} else if ((i > 0) &&
+			   (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
+						      is2GHz))) {
+			if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
+					       is2GHz) < freq &&
+			    pRdEdgesPower[i - 1].flag) {
+				twiceMaxEdgePower =
+					pRdEdgesPower[i - 1].tPower;
+			}
+			break;
+		}
+	}
+
+	return twiceMaxEdgePower;
+}
+
+/****************************************/
+/* EEPROM Operations for 4K sized cards */
+/****************************************/
+
+static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
+{
+	return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
+{
+	return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
+}
+
+static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+	int addr, eep_start_loc = 0;
+
+	eep_start_loc = 64;
+
+	if (!ath9k_hw_use_flash(ah)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
+	}
+
+	for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
+		if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			       "Unable to read eeprom region \n");
+			return false;
+		}
+		eep_data++;
+	}
+
+	return true;
+#undef SIZE_EEPROM_4K
+}
+
+static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
+{
+#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+	struct ar5416_eeprom_4k *eep =
+		(struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
+	u16 *eepdata, temp, magic, magic2;
+	u32 sum = 0, el;
+	bool need_swap = false;
+	int i, addr;
+
+
+	if (!ath9k_hw_use_flash(ah)) {
+		if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
+					 &magic)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Reading Magic # failed\n");
+			return false;
+		}
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"Read Magic = 0x%04X\n", magic);
+
+		if (magic != AR5416_EEPROM_MAGIC) {
+			magic2 = swab16(magic);
+
+			if (magic2 == AR5416_EEPROM_MAGIC) {
+				need_swap = true;
+				eepdata = (u16 *) (&ah->eeprom);
+
+				for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
+					temp = swab16(*eepdata);
+					*eepdata = temp;
+					eepdata++;
+				}
+			} else {
+				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+					"Invalid EEPROM Magic. "
+					"endianness mismatch.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
+		need_swap ? "True" : "False");
+
+	if (need_swap)
+		el = swab16(ah->eeprom.map4k.baseEepHeader.length);
+	else
+		el = ah->eeprom.map4k.baseEepHeader.length;
+
+	if (el > sizeof(struct ar5416_eeprom_4k))
+		el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
+	else
+		el = el / sizeof(u16);
+
+	eepdata = (u16 *)(&ah->eeprom);
+
+	for (i = 0; i < el; i++)
+		sum ^= *eepdata++;
+
+	if (need_swap) {
+		u32 integer;
+		u16 word;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"EEPROM Endianness is not native.. Changing\n");
+
+		word = swab16(eep->baseEepHeader.length);
+		eep->baseEepHeader.length = word;
+
+		word = swab16(eep->baseEepHeader.checksum);
+		eep->baseEepHeader.checksum = word;
+
+		word = swab16(eep->baseEepHeader.version);
+		eep->baseEepHeader.version = word;
+
+		word = swab16(eep->baseEepHeader.regDmn[0]);
+		eep->baseEepHeader.regDmn[0] = word;
+
+		word = swab16(eep->baseEepHeader.regDmn[1]);
+		eep->baseEepHeader.regDmn[1] = word;
+
+		word = swab16(eep->baseEepHeader.rfSilent);
+		eep->baseEepHeader.rfSilent = word;
+
+		word = swab16(eep->baseEepHeader.blueToothOptions);
+		eep->baseEepHeader.blueToothOptions = word;
+
+		word = swab16(eep->baseEepHeader.deviceCap);
+		eep->baseEepHeader.deviceCap = word;
+
+		integer = swab32(eep->modalHeader.antCtrlCommon);
+		eep->modalHeader.antCtrlCommon = integer;
+
+		for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+			integer = swab32(eep->modalHeader.antCtrlChain[i]);
+			eep->modalHeader.antCtrlChain[i] = integer;
+		}
+
+		for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+			word = swab16(eep->modalHeader.spurChans[i].spurChan);
+			eep->modalHeader.spurChans[i].spurChan = word;
+		}
+	}
+
+	if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+	    ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+			sum, ah->eep_ops->get_eeprom_ver(ah));
+		return -EINVAL;
+	}
+
+	return 0;
+#undef EEPROM_4K_SIZE
+}
+
+static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
+				  enum eeprom_param param)
+{
+	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+	struct modal_eep_4k_header *pModal = &eep->modalHeader;
+	struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+
+	switch (param) {
+	case EEP_NFTHRESH_2:
+		return pModal->noiseFloorThreshCh[0];
+	case AR_EEPROM_MAC(0):
+		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+	case AR_EEPROM_MAC(1):
+		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+	case AR_EEPROM_MAC(2):
+		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+	case EEP_REG_0:
+		return pBase->regDmn[0];
+	case EEP_REG_1:
+		return pBase->regDmn[1];
+	case EEP_OP_CAP:
+		return pBase->deviceCap;
+	case EEP_OP_MODE:
+		return pBase->opCapFlags;
+	case EEP_RF_SILENT:
+		return pBase->rfSilent;
+	case EEP_OB_2:
+		return pModal->ob_01;
+	case EEP_DB_2:
+		return pModal->db1_01;
+	case EEP_MINOR_REV:
+		return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+	case EEP_TX_MASK:
+		return pBase->txMask;
+	case EEP_RX_MASK:
+		return pBase->rxMask;
+	case EEP_FRAC_N_5G:
+		return 0;
+	default:
+		return 0;
+	}
+}
+
+static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
+				struct ath9k_channel *chan,
+				struct cal_data_per_freq_4k *pRawDataSet,
+				u8 *bChans, u16 availPiers,
+				u16 tPdGainOverlap, int16_t *pMinCalPower,
+				u16 *pPdGainBoundaries, u8 *pPDADCValues,
+				u16 numXpdGains)
+{
+#define TMP_VAL_VPD_TABLE \
+	((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
+	int i, j, k;
+	int16_t ss;
+	u16 idxL = 0, idxR = 0, numPiers;
+	static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+	u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+	u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+	int16_t vpdStep;
+	int16_t tmpVal;
+	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+	bool match;
+	int16_t minDelta = 0;
+	struct chan_centers centers;
+#define PD_GAIN_BOUNDARY_DEFAULT 58;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	for (numPiers = 0; numPiers < availPiers; numPiers++) {
+		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+			break;
+	}
+
+	match = ath9k_hw_get_lower_upper_index(
+					(u8)FREQ2FBIN(centers.synth_center,
+					IS_CHAN_2GHZ(chan)), bChans, numPiers,
+					&idxL, &idxR);
+
+	if (match) {
+		for (i = 0; i < numXpdGains; i++) {
+			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+					pRawDataSet[idxL].pwrPdg[i],
+					pRawDataSet[idxL].vpdPdg[i],
+					AR5416_EEP4K_PD_GAIN_ICEPTS,
+					vpdTableI[i]);
+		}
+	} else {
+		for (i = 0; i < numXpdGains; i++) {
+			pVpdL = pRawDataSet[idxL].vpdPdg[i];
+			pPwrL = pRawDataSet[idxL].pwrPdg[i];
+			pVpdR = pRawDataSet[idxR].vpdPdg[i];
+			pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+			maxPwrT4[i] =
+				min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
+				    pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
+
+
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrL, pVpdL,
+						AR5416_EEP4K_PD_GAIN_ICEPTS,
+						vpdTableL[i]);
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrR, pVpdR,
+						AR5416_EEP4K_PD_GAIN_ICEPTS,
+						vpdTableR[i]);
+
+			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+				vpdTableI[i][j] =
+					(u8)(ath9k_hw_interpolate((u16)
+					     FREQ2FBIN(centers.
+						       synth_center,
+						       IS_CHAN_2GHZ
+						       (chan)),
+					     bChans[idxL], bChans[idxR],
+					     vpdTableL[i][j], vpdTableR[i][j]));
+			}
+		}
+	}
+
+	*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+	k = 0;
+
+	for (i = 0; i < numXpdGains; i++) {
+		if (i == (numXpdGains - 1))
+			pPdGainBoundaries[i] =
+				(u16)(maxPwrT4[i] / 2);
+		else
+			pPdGainBoundaries[i] =
+				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+		pPdGainBoundaries[i] =
+			min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+		if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+			minDelta = pPdGainBoundaries[0] - 23;
+			pPdGainBoundaries[0] = 23;
+		} else {
+			minDelta = 0;
+		}
+
+		if (i == 0) {
+			if (AR_SREV_9280_10_OR_LATER(ah))
+				ss = (int16_t)(0 - (minPwrT4[i] / 2));
+			else
+				ss = 0;
+		} else {
+			ss = (int16_t)((pPdGainBoundaries[i - 1] -
+					(minPwrT4[i] / 2)) -
+				       tPdGainOverlap + 1 + minDelta);
+		}
+		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+			ss++;
+		}
+
+		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+				(minPwrT4[i] / 2));
+		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+			tgtIndex : sizeCurrVpdTable;
+
+		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
+			pPDADCValues[k++] = vpdTableI[i][ss++];
+
+		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+				    vpdTableI[i][sizeCurrVpdTable - 2]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		if (tgtIndex >= maxIndex) {
+			while ((ss <= tgtIndex) &&
+			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+				tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
+				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+							 255 : tmpVal);
+				ss++;
+			}
+		}
+	}
+
+	while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
+		pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
+		i++;
+	}
+
+	while (k < AR5416_NUM_PDADC_VALUES) {
+		pPDADCValues[k] = pPDADCValues[k - 1];
+		k++;
+	}
+
+	return;
+#undef TMP_VAL_VPD_TABLE
+}
+
+static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
+				  struct ath9k_channel *chan,
+				  int16_t *pTxPowerIndexOffset)
+{
+	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+	struct cal_data_per_freq_4k *pRawDataset;
+	u8 *pCalBChans = NULL;
+	u16 pdGainOverlap_t2;
+	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+	u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
+	u16 numPiers, i, j;
+	int16_t tMinCalPower;
+	u16 numXpdGain, xpdMask;
+	u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
+	u32 reg32, regOffset, regChainOffset;
+
+	xpdMask = pEepData->modalHeader.xpdGain;
+
+	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_2) {
+		pdGainOverlap_t2 =
+			pEepData->modalHeader.pdGainOverlap;
+	} else {
+		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+	}
+
+	pCalBChans = pEepData->calFreqPier2G;
+	numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
+
+	numXpdGain = 0;
+
+	for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
+		if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
+			if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
+				break;
+			xpdGainValues[numXpdGain] =
+				(u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
+			numXpdGain++;
+		}
+	}
+
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+		      (numXpdGain - 1) & 0x3);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+		      xpdGainValues[0]);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+		      xpdGainValues[1]);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
+
+	for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+		if (AR_SREV_5416_20_OR_LATER(ah) &&
+		    (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+		    (i != 0)) {
+			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+		} else
+			regChainOffset = i * 0x1000;
+
+		if (pEepData->baseEepHeader.txMask & (1 << i)) {
+			pRawDataset = pEepData->calPierData2G[i];
+
+			ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
+					    pRawDataset, pCalBChans,
+					    numPiers, pdGainOverlap_t2,
+					    &tMinCalPower, gainBoundaries,
+					    pdadcValues, numXpdGain);
+
+			if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+				REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+					  SM(pdGainOverlap_t2,
+					     AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+					  | SM(gainBoundaries[0],
+					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+					  | SM(gainBoundaries[1],
+					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+					  | SM(gainBoundaries[2],
+					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+					  | SM(gainBoundaries[3],
+				       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+			}
+
+			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+			for (j = 0; j < 32; j++) {
+				reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+					((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+					((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+					((pdadcValues[4 * j + 3] & 0xFF) << 24);
+				REG_WRITE(ah, regOffset, reg32);
+
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"PDADC (%d,%4x): %4.4x %8.8x\n",
+					i, regChainOffset, regOffset,
+					reg32);
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"PDADC: Chain %d | "
+					"PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d |\n",
+					i, 4 * j, pdadcValues[4 * j],
+					4 * j + 1, pdadcValues[4 * j + 1],
+					4 * j + 2, pdadcValues[4 * j + 2],
+					4 * j + 3,
+					pdadcValues[4 * j + 3]);
+
+				regOffset += 4;
+			}
+		}
+	}
+
+	*pTxPowerIndexOffset = 0;
+}
+
+static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
+						 struct ath9k_channel *chan,
+						 int16_t *ratesArray,
+						 u16 cfgCtl,
+						 u16 AntennaReduction,
+						 u16 twiceMaxRegulatoryPower,
+						 u16 powerLimit)
+{
+	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	static const u16 tpScaleReductionTable[5] =
+		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+	int i;
+	int16_t twiceLargestAntenna;
+	struct cal_ctl_data_4k *rep;
+	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+		0, { 0, 0, 0, 0}
+	};
+	struct cal_target_power_leg targetPowerOfdmExt = {
+		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+		0, { 0, 0, 0, 0 }
+	};
+	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+		0, {0, 0, 0, 0}
+	};
+	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+	u16 ctlModesFor11g[] =
+		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+		  CTL_2GHT40
+		};
+	u16 numCtlModes, *pCtlMode, ctlMode, freq;
+	struct chan_centers centers;
+	int tx_chainmask;
+	u16 twiceMinEdgePower;
+
+	tx_chainmask = ah->txchainmask;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
+
+	twiceLargestAntenna = (int16_t)min(AntennaReduction -
+					   twiceLargestAntenna, 0);
+
+	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+	if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
+		maxRegAllowedPower -=
+			(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+	}
+
+	scaledPower = min(powerLimit, maxRegAllowedPower);
+	scaledPower = max((u16)0, scaledPower);
+
+	numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+	pCtlMode = ctlModesFor11g;
+
+	ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPowerCck,
+			AR5416_NUM_2G_CCK_TARGET_POWERS,
+			&targetPowerCck, 4, false);
+	ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPower2G,
+			AR5416_NUM_2G_20_TARGET_POWERS,
+			&targetPowerOfdm, 4, false);
+	ath9k_hw_get_target_powers(ah, chan,
+			pEepData->calTargetPower2GHT20,
+			AR5416_NUM_2G_20_TARGET_POWERS,
+			&targetPowerHt20, 8, false);
+
+	if (IS_CHAN_HT40(chan)) {
+		numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+		ath9k_hw_get_target_powers(ah, chan,
+				pEepData->calTargetPower2GHT40,
+				AR5416_NUM_2G_40_TARGET_POWERS,
+				&targetPowerHt40, 8, true);
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPowerCck,
+				AR5416_NUM_2G_CCK_TARGET_POWERS,
+				&targetPowerCckExt, 4, true);
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPower2G,
+				AR5416_NUM_2G_20_TARGET_POWERS,
+				&targetPowerOfdmExt, 4, true);
+	}
+
+	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+			(pCtlMode[ctlMode] == CTL_2GHT40);
+		if (isHt40CtlMode)
+			freq = centers.synth_center;
+		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+			freq = centers.ext_center;
+		else
+			freq = centers.ctl_center;
+
+		if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
+		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
+			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+			"EXT_ADDITIVE %d\n",
+			ctlMode, numCtlModes, isHt40CtlMode,
+			(pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+		for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
+				pEepData->ctlIndex[i]; i++) {
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+				"chan %d\n",
+				i, cfgCtl, pCtlMode[ctlMode],
+				pEepData->ctlIndex[i], chan->channel);
+
+			if ((((cfgCtl & ~CTL_MODE_M) |
+			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+			     pEepData->ctlIndex[i]) ||
+			    (((cfgCtl & ~CTL_MODE_M) |
+			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+			     ((pEepData->ctlIndex[i] & CTL_MODE_M) |
+			      SD_NO_CTL))) {
+				rep = &(pEepData->ctlData[i]);
+
+				twiceMinEdgePower =
+					ath9k_hw_get_max_edge_power(freq,
+				rep->ctlEdges[ar5416_get_ntxchains
+						(tx_chainmask) - 1],
+				IS_CHAN_2GHZ(chan),
+				AR5416_EEP4K_NUM_BAND_EDGES);
+
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"    MATCH-EE_IDX %d: ch %d is2 %d "
+					"2xMinEdge %d chainmask %d chains %d\n",
+					i, freq, IS_CHAN_2GHZ(chan),
+					twiceMinEdgePower, tx_chainmask,
+					ar5416_get_ntxchains
+					(tx_chainmask));
+				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+					twiceMaxEdgePower =
+						min(twiceMaxEdgePower,
+						    twiceMinEdgePower);
+				} else {
+					twiceMaxEdgePower = twiceMinEdgePower;
+					break;
+				}
+			}
+		}
+
+		minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"    SEL-Min ctlMode %d pCtlMode %d "
+			"2xMaxEdge %d sP %d minCtlPwr %d\n",
+			ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+			scaledPower, minCtlPower);
+
+		switch (pCtlMode[ctlMode]) {
+		case CTL_11B:
+			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
+					i++) {
+				targetPowerCck.tPow2x[i] =
+					min((u16)targetPowerCck.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_11G:
+			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
+					i++) {
+				targetPowerOfdm.tPow2x[i] =
+					min((u16)targetPowerOfdm.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_2GHT20:
+			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
+					i++) {
+				targetPowerHt20.tPow2x[i] =
+					min((u16)targetPowerHt20.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_11B_EXT:
+			targetPowerCckExt.tPow2x[0] = min((u16)
+					targetPowerCckExt.tPow2x[0],
+					minCtlPower);
+			break;
+		case CTL_11G_EXT:
+			targetPowerOfdmExt.tPow2x[0] = min((u16)
+					targetPowerOfdmExt.tPow2x[0],
+					minCtlPower);
+			break;
+		case CTL_2GHT40:
+			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
+					i++) {
+				targetPowerHt40.tPow2x[i] =
+					min((u16)targetPowerHt40.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+		ratesArray[rate18mb] = ratesArray[rate24mb] =
+		targetPowerOfdm.tPow2x[0];
+	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+	ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+	ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+	ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+	ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+
+	if (IS_CHAN_HT40(chan)) {
+		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+			ratesArray[rateHt40_0 + i] =
+				targetPowerHt40.tPow2x[i];
+		}
+		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+		ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+	}
+}
+
+static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
+				   struct ath9k_channel *chan,
+				   u16 cfgCtl,
+				   u8 twiceAntennaReduction,
+				   u8 twiceMaxRegulatoryPower,
+				   u8 powerLimit)
+{
+	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+	struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
+	int16_t ratesArray[Ar5416RateSize];
+	int16_t txPowerIndexOffset = 0;
+	u8 ht40PowerIncForPdadc = 2;
+	int i;
+
+	memset(ratesArray, 0, sizeof(ratesArray));
+
+	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_2) {
+		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+	}
+
+	ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+					       &ratesArray[0], cfgCtl,
+					       twiceAntennaReduction,
+					       twiceMaxRegulatoryPower,
+					       powerLimit);
+
+	ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
+		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+			ratesArray[i] = AR5416_MAX_RATE_POWER;
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		for (i = 0; i < Ar5416RateSize; i++)
+			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
+		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
+		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+	if (IS_CHAN_2GHZ(chan)) {
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+			  ATH9K_POW_SM(ratesArray[rate2s], 24)
+			  | ATH9K_POW_SM(ratesArray[rate2l], 16)
+			  | ATH9K_POW_SM(ratesArray[rateXr], 8)
+			  | ATH9K_POW_SM(ratesArray[rate1l], 0));
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+			  ATH9K_POW_SM(ratesArray[rate11s], 24)
+			  | ATH9K_POW_SM(ratesArray[rate11l], 16)
+			  | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+			  | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+	if (IS_CHAN_HT40(chan)) {
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
+				       ht40PowerIncForPdadc, 24)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+					 ht40PowerIncForPdadc, 16)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+					 ht40PowerIncForPdadc, 8)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+					 ht40PowerIncForPdadc, 0));
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
+				       ht40PowerIncForPdadc, 24)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+					 ht40PowerIncForPdadc, 16)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+					 ht40PowerIncForPdadc, 8)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+					 ht40PowerIncForPdadc, 0));
+
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+			  ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+			  | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+	}
+
+	i = rate6mb;
+
+	if (IS_CHAN_HT40(chan))
+		i = rateHt40_0;
+	else if (IS_CHAN_HT20(chan))
+		i = rateHt20_0;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ah->regulatory.max_power_level =
+			ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+	else
+		ah->regulatory.max_power_level = ratesArray[i];
+
+}
+
+static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
+				  struct ath9k_channel *chan)
+{
+	struct modal_eep_4k_header *pModal;
+	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+	u8 biaslevel;
+
+	if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+		return;
+
+	if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+		return;
+
+	pModal = &eep->modalHeader;
+
+	if (pModal->xpaBiasLvl != 0xff) {
+		biaslevel = pModal->xpaBiasLvl;
+		INI_RA(&ah->iniAddac, 7, 1) =
+		  (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
+	}
+}
+
+static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
+				 struct modal_eep_4k_header *pModal,
+				 struct ar5416_eeprom_4k *eep,
+				 u8 txRxAttenLocal, int regChainOffset)
+{
+	REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+		  pModal->antCtrlChain[0]);
+
+	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+		  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+		   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+		     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+		  SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+		  SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_3) {
+		txRxAttenLocal = pModal->txRxAttenCh[0];
+
+		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
+		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+			      pModal->xatten2Margin[0]);
+		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
+	}
+
+	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+
+	if (AR_SREV_9285_11(ah))
+		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
+}
+
+static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
+					 struct ath9k_channel *chan)
+{
+	struct modal_eep_4k_header *pModal;
+	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+	u8 txRxAttenLocal;
+	u8 ob[5], db1[5], db2[5];
+	u8 ant_div_control1, ant_div_control2;
+	u32 regVal;
+
+	pModal = &eep->modalHeader;
+	txRxAttenLocal = 23;
+
+	REG_WRITE(ah, AR_PHY_SWITCH_COM,
+		  ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+
+	/* Single chain for 4K EEPROM*/
+	ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0);
+
+	/* Initialize Ant Diversity settings from EEPROM */
+	if (pModal->version == 3) {
+		ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
+		ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
+		regVal = REG_READ(ah, 0x99ac);
+		regVal &= (~(0x7f000000));
+		regVal |= ((ant_div_control1 & 0x1) << 24);
+		regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
+		regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
+		regVal |= ((ant_div_control2 & 0x3) << 25);
+		regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
+		REG_WRITE(ah, 0x99ac, regVal);
+		regVal = REG_READ(ah, 0x99ac);
+		regVal = REG_READ(ah, 0xa208);
+		regVal &= (~(0x1 << 13));
+		regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
+		REG_WRITE(ah, 0xa208, regVal);
+		regVal = REG_READ(ah, 0xa208);
+	}
+
+	if (pModal->version >= 2) {
+		ob[0] = (pModal->ob_01 & 0xf);
+		ob[1] = (pModal->ob_01 >> 4) & 0xf;
+		ob[2] = (pModal->ob_234 & 0xf);
+		ob[3] = ((pModal->ob_234 >> 4) & 0xf);
+		ob[4] = ((pModal->ob_234 >> 8) & 0xf);
+
+		db1[0] = (pModal->db1_01 & 0xf);
+		db1[1] = ((pModal->db1_01 >> 4) & 0xf);
+		db1[2] = (pModal->db1_234 & 0xf);
+		db1[3] = ((pModal->db1_234 >> 4) & 0xf);
+		db1[4] = ((pModal->db1_234 >> 8) & 0xf);
+
+		db2[0] = (pModal->db2_01 & 0xf);
+		db2[1] = ((pModal->db2_01 >> 4) & 0xf);
+		db2[2] = (pModal->db2_234 & 0xf);
+		db2[3] = ((pModal->db2_234 >> 4) & 0xf);
+		db2[4] = ((pModal->db2_234 >> 8) & 0xf);
+
+	} else if (pModal->version == 1) {
+		ob[0] = (pModal->ob_01 & 0xf);
+		ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
+		db1[0] = (pModal->db1_01 & 0xf);
+		db1[1] = db1[2] = db1[3] =
+			db1[4] = ((pModal->db1_01 >> 4) & 0xf);
+		db2[0] = (pModal->db2_01 & 0xf);
+		db2[1] = db2[2] = db2[3] =
+			db2[4] = ((pModal->db2_01 >> 4) & 0xf);
+	} else {
+		int i;
+		for (i = 0; i < 5; i++) {
+			ob[i] = pModal->ob_01;
+			db1[i] = pModal->db1_01;
+			db2[i] = pModal->db1_01;
+		}
+	}
+
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
+
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+			AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+			AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+			AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
+
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+			AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+			AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+			AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+			AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
+	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+			AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
+
+
+	if (AR_SREV_9285_11(ah))
+		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+		      pModal->switchSettling);
+	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+		      pModal->adcDesiredSize);
+
+	REG_WRITE(ah, AR_PHY_RF_CTL4,
+		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
+		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
+		  SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)  |
+		  SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+		      pModal->txEndToRxOn);
+	REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+		      pModal->thresh62);
+	REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+		      pModal->thresh62);
+
+	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+						AR5416_EEP_MINOR_VER_2) {
+		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
+			      pModal->txFrameToDataStart);
+		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+			      pModal->txFrameToPaOn);
+	}
+
+	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+						AR5416_EEP_MINOR_VER_3) {
+		if (IS_CHAN_HT40(chan))
+			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+				      AR_PHY_SETTLING_SWITCH,
+				      pModal->swSettleHt40);
+	}
+}
+
+static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
+					      struct ath9k_channel *chan)
+{
+	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+	struct modal_eep_4k_header *pModal = &eep->modalHeader;
+
+	return pModal->antCtrlCommon & 0xFFFF;
+}
+
+static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
+					 enum ieee80211_band freq_band)
+{
+	return 1;
+}
+
+static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+{
+#define EEP_MAP4K_SPURCHAN \
+	(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
+
+	u16 spur_val = AR_NO_SPUR;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"Getting spur idx %d is2Ghz. %d val %x\n",
+		i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+	switch (ah->config.spurmode) {
+	case SPUR_DISABLE:
+		break;
+	case SPUR_ENABLE_IOCTL:
+		spur_val = ah->config.spurchans[i][is2GHz];
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"Getting spur val from new loc. %d\n", spur_val);
+		break;
+	case SPUR_ENABLE_EEPROM:
+		spur_val = EEP_MAP4K_SPURCHAN;
+		break;
+	}
+
+	return spur_val;
+
+#undef EEP_MAP4K_SPURCHAN
+}
+
+static struct eeprom_ops eep_4k_ops = {
+	.check_eeprom		= ath9k_hw_4k_check_eeprom,
+	.get_eeprom		= ath9k_hw_4k_get_eeprom,
+	.fill_eeprom		= ath9k_hw_4k_fill_eeprom,
+	.get_eeprom_ver		= ath9k_hw_4k_get_eeprom_ver,
+	.get_eeprom_rev		= ath9k_hw_4k_get_eeprom_rev,
+	.get_num_ant_config	= ath9k_hw_4k_get_num_ant_config,
+	.get_eeprom_antenna_cfg	= ath9k_hw_4k_get_eeprom_antenna_cfg,
+	.set_board_values	= ath9k_hw_4k_set_board_values,
+	.set_addac		= ath9k_hw_4k_set_addac,
+	.set_txpower		= ath9k_hw_4k_set_txpower,
+	.get_spur_channel	= ath9k_hw_4k_get_spur_channel
+};
+
+/************************************************/
+/* EEPROM Operations for non-4K (Default) cards */
+/************************************************/
+
+static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
+{
+	return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
+}
+
+static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
+{
+	return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
+}
+
+static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
+	u16 *eep_data = (u16 *)&ah->eeprom.def;
+	int addr, ar5416_eep_start_loc = 0x100;
+
+	for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
+		if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
+					 eep_data)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Unable to read eeprom region\n");
+			return false;
+		}
+		eep_data++;
+	}
+	return true;
+#undef SIZE_EEPROM_DEF
+}
+
+static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
+{
+	struct ar5416_eeprom_def *eep =
+		(struct ar5416_eeprom_def *) &ah->eeprom.def;
+	u16 *eepdata, temp, magic, magic2;
+	u32 sum = 0, el;
+	bool need_swap = false;
+	int i, addr, size;
+
+	if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
+		return false;
+	}
+
+	if (!ath9k_hw_use_flash(ah)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"Read Magic = 0x%04X\n", magic);
+
+		if (magic != AR5416_EEPROM_MAGIC) {
+			magic2 = swab16(magic);
+
+			if (magic2 == AR5416_EEPROM_MAGIC) {
+				size = sizeof(struct ar5416_eeprom_def);
+				need_swap = true;
+				eepdata = (u16 *) (&ah->eeprom);
+
+				for (addr = 0; addr < size / sizeof(u16); addr++) {
+					temp = swab16(*eepdata);
+					*eepdata = temp;
+					eepdata++;
+				}
+			} else {
+				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+					"Invalid EEPROM Magic. "
+					"Endianness mismatch.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
+		need_swap ? "True" : "False");
+
+	if (need_swap)
+		el = swab16(ah->eeprom.def.baseEepHeader.length);
+	else
+		el = ah->eeprom.def.baseEepHeader.length;
+
+	if (el > sizeof(struct ar5416_eeprom_def))
+		el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
+	else
+		el = el / sizeof(u16);
+
+	eepdata = (u16 *)(&ah->eeprom);
+
+	for (i = 0; i < el; i++)
+		sum ^= *eepdata++;
+
+	if (need_swap) {
+		u32 integer, j;
+		u16 word;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"EEPROM Endianness is not native.. Changing.\n");
+
+		word = swab16(eep->baseEepHeader.length);
+		eep->baseEepHeader.length = word;
+
+		word = swab16(eep->baseEepHeader.checksum);
+		eep->baseEepHeader.checksum = word;
+
+		word = swab16(eep->baseEepHeader.version);
+		eep->baseEepHeader.version = word;
+
+		word = swab16(eep->baseEepHeader.regDmn[0]);
+		eep->baseEepHeader.regDmn[0] = word;
+
+		word = swab16(eep->baseEepHeader.regDmn[1]);
+		eep->baseEepHeader.regDmn[1] = word;
+
+		word = swab16(eep->baseEepHeader.rfSilent);
+		eep->baseEepHeader.rfSilent = word;
+
+		word = swab16(eep->baseEepHeader.blueToothOptions);
+		eep->baseEepHeader.blueToothOptions = word;
+
+		word = swab16(eep->baseEepHeader.deviceCap);
+		eep->baseEepHeader.deviceCap = word;
+
+		for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
+			struct modal_eep_header *pModal =
+				&eep->modalHeader[j];
+			integer = swab32(pModal->antCtrlCommon);
+			pModal->antCtrlCommon = integer;
+
+			for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+				integer = swab32(pModal->antCtrlChain[i]);
+				pModal->antCtrlChain[i] = integer;
+			}
+
+			for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+				word = swab16(pModal->spurChans[i].spurChan);
+				pModal->spurChans[i].spurChan = word;
+			}
+		}
+	}
+
+	if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
+	    ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+			sum, ah->eep_ops->get_eeprom_ver(ah));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
+				   enum eeprom_param param)
+{
+	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+	struct modal_eep_header *pModal = eep->modalHeader;
+	struct base_eep_header *pBase = &eep->baseEepHeader;
+
+	switch (param) {
+	case EEP_NFTHRESH_5:
+		return pModal[0].noiseFloorThreshCh[0];
+	case EEP_NFTHRESH_2:
+		return pModal[1].noiseFloorThreshCh[0];
+	case AR_EEPROM_MAC(0):
+		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+	case AR_EEPROM_MAC(1):
+		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+	case AR_EEPROM_MAC(2):
+		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+	case EEP_REG_0:
+		return pBase->regDmn[0];
+	case EEP_REG_1:
+		return pBase->regDmn[1];
+	case EEP_OP_CAP:
+		return pBase->deviceCap;
+	case EEP_OP_MODE:
+		return pBase->opCapFlags;
+	case EEP_RF_SILENT:
+		return pBase->rfSilent;
+	case EEP_OB_5:
+		return pModal[0].ob;
+	case EEP_DB_5:
+		return pModal[0].db;
+	case EEP_OB_2:
+		return pModal[1].ob;
+	case EEP_DB_2:
+		return pModal[1].db;
+	case EEP_MINOR_REV:
+		return AR5416_VER_MASK;
+	case EEP_TX_MASK:
+		return pBase->txMask;
+	case EEP_RX_MASK:
+		return pBase->rxMask;
+	case EEP_RXGAIN_TYPE:
+		return pBase->rxGainType;
+	case EEP_TXGAIN_TYPE:
+		return pBase->txGainType;
+	case EEP_OL_PWRCTRL:
+		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+			return pBase->openLoopPwrCntl ? true : false;
+		else
+			return false;
+	case EEP_RC_CHAIN_MASK:
+		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+			return pBase->rcChainMask;
+		else
+			return 0;
+	case EEP_DAC_HPWR_5G:
+		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
+			return pBase->dacHiPwrMode_5G;
+		else
+			return 0;
+	case EEP_FRAC_N_5G:
+		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
+			return pBase->frac_n_5g;
+		else
+			return 0;
+	default:
+		return 0;
+	}
+}
+
+static void ath9k_hw_def_set_gain(struct ath_hw *ah,
+				  struct modal_eep_header *pModal,
+				  struct ar5416_eeprom_def *eep,
+				  u8 txRxAttenLocal, int regChainOffset, int i)
+{
+	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+		txRxAttenLocal = pModal->txRxAttenCh[i];
+
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+			      pModal->bswMargin[i]);
+			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+			      pModal->bswAtten[i]);
+			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+			      pModal->xatten2Margin[i]);
+			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			      AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+			      pModal->xatten2Db[i]);
+		} else {
+			REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+			   ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+			  | SM(pModal-> bswMargin[i],
+			       AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+			REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+			   ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+			  | SM(pModal->bswAtten[i],
+			       AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+		}
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		REG_RMW_FIELD(ah,
+		      AR_PHY_RXGAIN + regChainOffset,
+		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+		REG_RMW_FIELD(ah,
+		      AR_PHY_RXGAIN + regChainOffset,
+		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
+	} else {
+		REG_WRITE(ah,
+			  AR_PHY_RXGAIN + regChainOffset,
+			  (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
+			   ~AR_PHY_RXGAIN_TXRX_ATTEN)
+			  | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
+		REG_WRITE(ah,
+			  AR_PHY_GAIN_2GHZ + regChainOffset,
+			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+			   ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+			  SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+	}
+}
+
+static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
+					  struct ath9k_channel *chan)
+{
+	struct modal_eep_header *pModal;
+	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+	int i, regChainOffset;
+	u8 txRxAttenLocal;
+
+	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+	txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
+
+	REG_WRITE(ah, AR_PHY_SWITCH_COM,
+		  ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		if (AR_SREV_9280(ah)) {
+			if (i >= 2)
+				break;
+		}
+
+		if (AR_SREV_5416_20_OR_LATER(ah) &&
+		    (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
+			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+		else
+			regChainOffset = i * 0x1000;
+
+		REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+			  pModal->antCtrlChain[i]);
+
+		REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+			  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+			   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+			  SM(pModal->iqCalICh[i],
+			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+			  SM(pModal->iqCalQCh[i],
+			     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+		if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
+			ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
+					      regChainOffset, i);
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		if (IS_CHAN_2GHZ(chan)) {
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+						  AR_AN_RF2G1_CH0_OB,
+						  AR_AN_RF2G1_CH0_OB_S,
+						  pModal->ob);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+						  AR_AN_RF2G1_CH0_DB,
+						  AR_AN_RF2G1_CH0_DB_S,
+						  pModal->db);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+						  AR_AN_RF2G1_CH1_OB,
+						  AR_AN_RF2G1_CH1_OB_S,
+						  pModal->ob_ch1);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+						  AR_AN_RF2G1_CH1_DB,
+						  AR_AN_RF2G1_CH1_DB_S,
+						  pModal->db_ch1);
+		} else {
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+						  AR_AN_RF5G1_CH0_OB5,
+						  AR_AN_RF5G1_CH0_OB5_S,
+						  pModal->ob);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+						  AR_AN_RF5G1_CH0_DB5,
+						  AR_AN_RF5G1_CH0_DB5_S,
+						  pModal->db);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+						  AR_AN_RF5G1_CH1_OB5,
+						  AR_AN_RF5G1_CH1_OB5_S,
+						  pModal->ob_ch1);
+			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+						  AR_AN_RF5G1_CH1_DB5,
+						  AR_AN_RF5G1_CH1_DB5_S,
+						  pModal->db_ch1);
+		}
+		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+					  AR_AN_TOP2_XPABIAS_LVL,
+					  AR_AN_TOP2_XPABIAS_LVL_S,
+					  pModal->xpaBiasLvl);
+		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+					  AR_AN_TOP2_LOCALBIAS,
+					  AR_AN_TOP2_LOCALBIAS_S,
+					  pModal->local_bias);
+		REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
+			      pModal->force_xpaon);
+	}
+
+	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+		      pModal->switchSettling);
+	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+		      pModal->adcDesiredSize);
+
+	if (!AR_SREV_9280_10_OR_LATER(ah))
+		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+			      AR_PHY_DESIRED_SZ_PGA,
+			      pModal->pgaDesiredSize);
+
+	REG_WRITE(ah, AR_PHY_RF_CTL4,
+		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+		  | SM(pModal->txEndToXpaOff,
+		       AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+		  | SM(pModal->txFrameToXpaOn,
+		       AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+		  | SM(pModal->txFrameToXpaOn,
+		       AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+		      pModal->txEndToRxOn);
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+			      pModal->thresh62);
+		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+			      AR_PHY_EXT_CCA0_THRESH62,
+			      pModal->thresh62);
+	} else {
+		REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+			      pModal->thresh62);
+		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+			      AR_PHY_EXT_CCA_THRESH62,
+			      pModal->thresh62);
+	}
+
+	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
+		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+			      AR_PHY_TX_END_DATA_START,
+			      pModal->txFrameToDataStart);
+		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+			      pModal->txFrameToPaOn);
+	}
+
+	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+		if (IS_CHAN_HT40(chan))
+			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+				      AR_PHY_SETTLING_SWITCH,
+				      pModal->swSettleHt40);
+	}
+
+	if (AR_SREV_9280_20_OR_LATER(ah) &&
+	    AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
+		REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
+			      AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
+			      pModal->miscBits);
+
+
+	if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
+		if (IS_CHAN_2GHZ(chan))
+			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+					eep->baseEepHeader.dacLpMode);
+		else if (eep->baseEepHeader.dacHiPwrMode_5G)
+			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
+		else
+			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
+				      eep->baseEepHeader.dacLpMode);
+
+		REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
+			      pModal->miscBits >> 2);
+
+		REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
+			      AR_PHY_TX_DESIRED_SCALE_CCK,
+			      eep->baseEepHeader.desiredScaleCCK);
+	}
+}
+
+static void ath9k_hw_def_set_addac(struct ath_hw *ah,
+				   struct ath9k_channel *chan)
+{
+#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
+	struct modal_eep_header *pModal;
+	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+	u8 biaslevel;
+
+	if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
+		return;
+
+	if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
+		return;
+
+	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+	if (pModal->xpaBiasLvl != 0xff) {
+		biaslevel = pModal->xpaBiasLvl;
+	} else {
+		u16 resetFreqBin, freqBin, freqCount = 0;
+		struct chan_centers centers;
+
+		ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+		resetFreqBin = FREQ2FBIN(centers.synth_center,
+					 IS_CHAN_2GHZ(chan));
+		freqBin = XPA_LVL_FREQ(0) & 0xff;
+		biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
+
+		freqCount++;
+
+		while (freqCount < 3) {
+			if (XPA_LVL_FREQ(freqCount) == 0x0)
+				break;
+
+			freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
+			if (resetFreqBin >= freqBin)
+				biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
+			else
+				break;
+			freqCount++;
+		}
+	}
+
+	if (IS_CHAN_2GHZ(chan)) {
+		INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
+					7, 1) & (~0x18)) | biaslevel << 3;
+	} else {
+		INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
+					6, 1) & (~0xc0)) | biaslevel << 6;
+	}
+#undef XPA_LVL_FREQ
+}
+
+static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
+				struct ath9k_channel *chan,
+				struct cal_data_per_freq *pRawDataSet,
+				u8 *bChans, u16 availPiers,
+				u16 tPdGainOverlap, int16_t *pMinCalPower,
+				u16 *pPdGainBoundaries, u8 *pPDADCValues,
+				u16 numXpdGains)
+{
+	int i, j, k;
+	int16_t ss;
+	u16 idxL = 0, idxR = 0, numPiers;
+	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
+		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+	u8 minPwrT4[AR5416_NUM_PD_GAINS];
+	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
+	int16_t vpdStep;
+	int16_t tmpVal;
+	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+	bool match;
+	int16_t minDelta = 0;
+	struct chan_centers centers;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	for (numPiers = 0; numPiers < availPiers; numPiers++) {
+		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+			break;
+	}
+
+	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
+							     IS_CHAN_2GHZ(chan)),
+					       bChans, numPiers, &idxL, &idxR);
+
+	if (match) {
+		for (i = 0; i < numXpdGains; i++) {
+			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+					pRawDataSet[idxL].pwrPdg[i],
+					pRawDataSet[idxL].vpdPdg[i],
+					AR5416_PD_GAIN_ICEPTS,
+					vpdTableI[i]);
+		}
+	} else {
+		for (i = 0; i < numXpdGains; i++) {
+			pVpdL = pRawDataSet[idxL].vpdPdg[i];
+			pPwrL = pRawDataSet[idxL].pwrPdg[i];
+			pVpdR = pRawDataSet[idxR].vpdPdg[i];
+			pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+			maxPwrT4[i] =
+				min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
+				    pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
+
+
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrL, pVpdL,
+						AR5416_PD_GAIN_ICEPTS,
+						vpdTableL[i]);
+			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+						pPwrR, pVpdR,
+						AR5416_PD_GAIN_ICEPTS,
+						vpdTableR[i]);
+
+			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+				vpdTableI[i][j] =
+					(u8)(ath9k_hw_interpolate((u16)
+					     FREQ2FBIN(centers.
+						       synth_center,
+						       IS_CHAN_2GHZ
+						       (chan)),
+					     bChans[idxL], bChans[idxR],
+					     vpdTableL[i][j], vpdTableR[i][j]));
+			}
+		}
+	}
+
+	*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+	k = 0;
+
+	for (i = 0; i < numXpdGains; i++) {
+		if (i == (numXpdGains - 1))
+			pPdGainBoundaries[i] =
+				(u16)(maxPwrT4[i] / 2);
+		else
+			pPdGainBoundaries[i] =
+				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+		pPdGainBoundaries[i] =
+			min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+		if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
+			minDelta = pPdGainBoundaries[0] - 23;
+			pPdGainBoundaries[0] = 23;
+		} else {
+			minDelta = 0;
+		}
+
+		if (i == 0) {
+			if (AR_SREV_9280_10_OR_LATER(ah))
+				ss = (int16_t)(0 - (minPwrT4[i] / 2));
+			else
+				ss = 0;
+		} else {
+			ss = (int16_t)((pPdGainBoundaries[i - 1] -
+					(minPwrT4[i] / 2)) -
+				       tPdGainOverlap + 1 + minDelta);
+		}
+		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+			ss++;
+		}
+
+		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+				(minPwrT4[i] / 2));
+		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+			tgtIndex : sizeCurrVpdTable;
+
+		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+			pPDADCValues[k++] = vpdTableI[i][ss++];
+		}
+
+		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+				    vpdTableI[i][sizeCurrVpdTable - 2]);
+		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+		if (tgtIndex > maxIndex) {
+			while ((ss <= tgtIndex) &&
+			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+						    (ss - maxIndex + 1) * vpdStep));
+				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+							 255 : tmpVal);
+				ss++;
+			}
+		}
+	}
+
+	while (i < AR5416_PD_GAINS_IN_MASK) {
+		pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
+		i++;
+	}
+
+	while (k < AR5416_NUM_PDADC_VALUES) {
+		pPDADCValues[k] = pPDADCValues[k - 1];
+		k++;
+	}
+
+	return;
+}
+
+static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
+				  struct ath9k_channel *chan,
+				  int16_t *pTxPowerIndexOffset)
+{
+#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
+#define SM_PDGAIN_B(x, y) \
+		SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
+
+	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+	struct cal_data_per_freq *pRawDataset;
+	u8 *pCalBChans = NULL;
+	u16 pdGainOverlap_t2;
+	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+	u16 numPiers, i, j;
+	int16_t tMinCalPower;
+	u16 numXpdGain, xpdMask;
+	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
+	u32 reg32, regOffset, regChainOffset;
+	int16_t modalIdx;
+
+	modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+	xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
+
+	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_2) {
+		pdGainOverlap_t2 =
+			pEepData->modalHeader[modalIdx].pdGainOverlap;
+	} else {
+		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+	}
+
+	if (IS_CHAN_2GHZ(chan)) {
+		pCalBChans = pEepData->calFreqPier2G;
+		numPiers = AR5416_NUM_2G_CAL_PIERS;
+	} else {
+		pCalBChans = pEepData->calFreqPier5G;
+		numPiers = AR5416_NUM_5G_CAL_PIERS;
+	}
+
+	if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
+		pRawDataset = pEepData->calPierData2G[0];
+		ah->initPDADC = ((struct calDataPerFreqOpLoop *)
+				 pRawDataset)->vpdPdg[0][0];
+	}
+
+	numXpdGain = 0;
+
+	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+			if (numXpdGain >= AR5416_NUM_PD_GAINS)
+				break;
+			xpdGainValues[numXpdGain] =
+				(u16)(AR5416_PD_GAINS_IN_MASK - i);
+			numXpdGain++;
+		}
+	}
+
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+		      (numXpdGain - 1) & 0x3);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+		      xpdGainValues[0]);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+		      xpdGainValues[1]);
+	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+		      xpdGainValues[2]);
+
+	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+		if (AR_SREV_5416_20_OR_LATER(ah) &&
+		    (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
+		    (i != 0)) {
+			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+		} else
+			regChainOffset = i * 0x1000;
+
+		if (pEepData->baseEepHeader.txMask & (1 << i)) {
+			if (IS_CHAN_2GHZ(chan))
+				pRawDataset = pEepData->calPierData2G[i];
+			else
+				pRawDataset = pEepData->calPierData5G[i];
+
+
+			if (OLC_FOR_AR9280_20_LATER) {
+				u8 pcdacIdx;
+				u8 txPower;
+
+				ath9k_get_txgain_index(ah, chan,
+				(struct calDataPerFreqOpLoop *)pRawDataset,
+				pCalBChans, numPiers, &txPower, &pcdacIdx);
+				ath9k_olc_get_pdadcs(ah, pcdacIdx,
+						     txPower/2, pdadcValues);
+			} else {
+				ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
+							chan, pRawDataset,
+							pCalBChans, numPiers,
+							pdGainOverlap_t2,
+							&tMinCalPower,
+							gainBoundaries,
+							pdadcValues,
+							numXpdGain);
+			}
+
+			if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
+				if (OLC_FOR_AR9280_20_LATER) {
+					REG_WRITE(ah,
+						AR_PHY_TPCRG5 + regChainOffset,
+						SM(0x6,
+						AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
+						SM_PD_GAIN(1) | SM_PD_GAIN(2) |
+						SM_PD_GAIN(3) | SM_PD_GAIN(4));
+				} else {
+					REG_WRITE(ah,
+						AR_PHY_TPCRG5 + regChainOffset,
+						SM(pdGainOverlap_t2,
+						AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
+						SM_PDGAIN_B(0, 1) |
+						SM_PDGAIN_B(1, 2) |
+						SM_PDGAIN_B(2, 3) |
+						SM_PDGAIN_B(3, 4));
+				}
+			}
+
+			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+			for (j = 0; j < 32; j++) {
+				reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+					((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+					((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+					((pdadcValues[4 * j + 3] & 0xFF) << 24);
+				REG_WRITE(ah, regOffset, reg32);
+
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"PDADC (%d,%4x): %4.4x %8.8x\n",
+					i, regChainOffset, regOffset,
+					reg32);
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"PDADC: Chain %d | PDADC %3d "
+					"Value %3d | PDADC %3d Value %3d | "
+					"PDADC %3d Value %3d | PDADC %3d "
+					"Value %3d |\n",
+					i, 4 * j, pdadcValues[4 * j],
+					4 * j + 1, pdadcValues[4 * j + 1],
+					4 * j + 2, pdadcValues[4 * j + 2],
+					4 * j + 3,
+					pdadcValues[4 * j + 3]);
+
+				regOffset += 4;
+			}
+		}
+	}
+
+	*pTxPowerIndexOffset = 0;
+#undef SM_PD_GAIN
+#undef SM_PDGAIN_B
+}
+
+static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
+						  struct ath9k_channel *chan,
+						  int16_t *ratesArray,
+						  u16 cfgCtl,
+						  u16 AntennaReduction,
+						  u16 twiceMaxRegulatoryPower,
+						  u16 powerLimit)
+{
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10 /* 10*log10(3)*2 */
+
+	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+	static const u16 tpScaleReductionTable[5] =
+		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+	int i;
+	int16_t twiceLargestAntenna;
+	struct cal_ctl_data *rep;
+	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+		0, { 0, 0, 0, 0}
+	};
+	struct cal_target_power_leg targetPowerOfdmExt = {
+		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+		0, { 0, 0, 0, 0 }
+	};
+	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+		0, {0, 0, 0, 0}
+	};
+	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+	u16 ctlModesFor11a[] =
+		{ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
+	u16 ctlModesFor11g[] =
+		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+		  CTL_2GHT40
+		};
+	u16 numCtlModes, *pCtlMode, ctlMode, freq;
+	struct chan_centers centers;
+	int tx_chainmask;
+	u16 twiceMinEdgePower;
+
+	tx_chainmask = ah->txchainmask;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	twiceLargestAntenna = max(
+		pEepData->modalHeader
+			[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+		pEepData->modalHeader
+			[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+	twiceLargestAntenna = max((u8)twiceLargestAntenna,
+				  pEepData->modalHeader
+				  [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+
+	twiceLargestAntenna = (int16_t)min(AntennaReduction -
+					   twiceLargestAntenna, 0);
+
+	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+	if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
+		maxRegAllowedPower -=
+			(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+	}
+
+	scaledPower = min(powerLimit, maxRegAllowedPower);
+
+	switch (ar5416_get_ntxchains(tx_chainmask)) {
+	case 1:
+		break;
+	case 2:
+		scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+		break;
+	case 3:
+		scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+		break;
+	}
+
+	scaledPower = max((u16)0, scaledPower);
+
+	if (IS_CHAN_2GHZ(chan)) {
+		numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
+			SUB_NUM_CTL_MODES_AT_2G_40;
+		pCtlMode = ctlModesFor11g;
+
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPowerCck,
+			AR5416_NUM_2G_CCK_TARGET_POWERS,
+			&targetPowerCck, 4, false);
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPower2G,
+			AR5416_NUM_2G_20_TARGET_POWERS,
+			&targetPowerOfdm, 4, false);
+		ath9k_hw_get_target_powers(ah, chan,
+			pEepData->calTargetPower2GHT20,
+			AR5416_NUM_2G_20_TARGET_POWERS,
+			&targetPowerHt20, 8, false);
+
+		if (IS_CHAN_HT40(chan)) {
+			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+			ath9k_hw_get_target_powers(ah, chan,
+				pEepData->calTargetPower2GHT40,
+				AR5416_NUM_2G_40_TARGET_POWERS,
+				&targetPowerHt40, 8, true);
+			ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPowerCck,
+				AR5416_NUM_2G_CCK_TARGET_POWERS,
+				&targetPowerCckExt, 4, true);
+			ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPower2G,
+				AR5416_NUM_2G_20_TARGET_POWERS,
+				&targetPowerOfdmExt, 4, true);
+		}
+	} else {
+		numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+			SUB_NUM_CTL_MODES_AT_5G_40;
+		pCtlMode = ctlModesFor11a;
+
+		ath9k_hw_get_legacy_target_powers(ah, chan,
+			pEepData->calTargetPower5G,
+			AR5416_NUM_5G_20_TARGET_POWERS,
+			&targetPowerOfdm, 4, false);
+		ath9k_hw_get_target_powers(ah, chan,
+			pEepData->calTargetPower5GHT20,
+			AR5416_NUM_5G_20_TARGET_POWERS,
+			&targetPowerHt20, 8, false);
+
+		if (IS_CHAN_HT40(chan)) {
+			numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+			ath9k_hw_get_target_powers(ah, chan,
+				pEepData->calTargetPower5GHT40,
+				AR5416_NUM_5G_40_TARGET_POWERS,
+				&targetPowerHt40, 8, true);
+			ath9k_hw_get_legacy_target_powers(ah, chan,
+				pEepData->calTargetPower5G,
+				AR5416_NUM_5G_20_TARGET_POWERS,
+				&targetPowerOfdmExt, 4, true);
+		}
+	}
+
+	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+			(pCtlMode[ctlMode] == CTL_2GHT40);
+		if (isHt40CtlMode)
+			freq = centers.synth_center;
+		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+			freq = centers.ext_center;
+		else
+			freq = centers.ctl_center;
+
+		if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
+		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
+			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+			"EXT_ADDITIVE %d\n",
+			ctlMode, numCtlModes, isHt40CtlMode,
+			(pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+		for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+				"chan %d\n",
+				i, cfgCtl, pCtlMode[ctlMode],
+				pEepData->ctlIndex[i], chan->channel);
+
+			if ((((cfgCtl & ~CTL_MODE_M) |
+			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+			     pEepData->ctlIndex[i]) ||
+			    (((cfgCtl & ~CTL_MODE_M) |
+			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+			     ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+				rep = &(pEepData->ctlData[i]);
+
+				twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+				rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
+				IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
+
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"    MATCH-EE_IDX %d: ch %d is2 %d "
+					"2xMinEdge %d chainmask %d chains %d\n",
+					i, freq, IS_CHAN_2GHZ(chan),
+					twiceMinEdgePower, tx_chainmask,
+					ar5416_get_ntxchains
+					(tx_chainmask));
+				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+					twiceMaxEdgePower = min(twiceMaxEdgePower,
+								twiceMinEdgePower);
+				} else {
+					twiceMaxEdgePower = twiceMinEdgePower;
+					break;
+				}
+			}
+		}
+
+		minCtlPower = min(twiceMaxEdgePower, scaledPower);
+
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"    SEL-Min ctlMode %d pCtlMode %d "
+			"2xMaxEdge %d sP %d minCtlPwr %d\n",
+			ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+			scaledPower, minCtlPower);
+
+		switch (pCtlMode[ctlMode]) {
+		case CTL_11B:
+			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+				targetPowerCck.tPow2x[i] =
+					min((u16)targetPowerCck.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_11A:
+		case CTL_11G:
+			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+				targetPowerOfdm.tPow2x[i] =
+					min((u16)targetPowerOfdm.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_5GHT20:
+		case CTL_2GHT20:
+			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+				targetPowerHt20.tPow2x[i] =
+					min((u16)targetPowerHt20.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		case CTL_11B_EXT:
+			targetPowerCckExt.tPow2x[0] = min((u16)
+					targetPowerCckExt.tPow2x[0],
+					minCtlPower);
+			break;
+		case CTL_11A_EXT:
+		case CTL_11G_EXT:
+			targetPowerOfdmExt.tPow2x[0] = min((u16)
+					targetPowerOfdmExt.tPow2x[0],
+					minCtlPower);
+			break;
+		case CTL_5GHT40:
+		case CTL_2GHT40:
+			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+				targetPowerHt40.tPow2x[i] =
+					min((u16)targetPowerHt40.tPow2x[i],
+					    minCtlPower);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+		ratesArray[rate18mb] = ratesArray[rate24mb] =
+		targetPowerOfdm.tPow2x[0];
+	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+	if (IS_CHAN_2GHZ(chan)) {
+		ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+		ratesArray[rate2s] = ratesArray[rate2l] =
+			targetPowerCck.tPow2x[1];
+		ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+			targetPowerCck.tPow2x[2];
+		;
+		ratesArray[rate11s] = ratesArray[rate11l] =
+			targetPowerCck.tPow2x[3];
+		;
+	}
+	if (IS_CHAN_HT40(chan)) {
+		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+			ratesArray[rateHt40_0 + i] =
+				targetPowerHt40.tPow2x[i];
+		}
+		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+		if (IS_CHAN_2GHZ(chan)) {
+			ratesArray[rateExtCck] =
+				targetPowerCckExt.tPow2x[0];
+		}
+	}
+}
+
+static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
+				    struct ath9k_channel *chan,
+				    u16 cfgCtl,
+				    u8 twiceAntennaReduction,
+				    u8 twiceMaxRegulatoryPower,
+				    u8 powerLimit)
+{
+#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+	struct modal_eep_header *pModal =
+		&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
+	int16_t ratesArray[Ar5416RateSize];
+	int16_t txPowerIndexOffset = 0;
+	u8 ht40PowerIncForPdadc = 2;
+	int i, cck_ofdm_delta = 0;
+
+	memset(ratesArray, 0, sizeof(ratesArray));
+
+	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+	    AR5416_EEP_MINOR_VER_2) {
+		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+	}
+
+	ath9k_hw_set_def_power_per_rate_table(ah, chan,
+					       &ratesArray[0], cfgCtl,
+					       twiceAntennaReduction,
+					       twiceMaxRegulatoryPower,
+					       powerLimit);
+
+	ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
+
+	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
+		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+			ratesArray[i] = AR5416_MAX_RATE_POWER;
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		for (i = 0; i < Ar5416RateSize; i++)
+			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
+		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
+		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+	if (IS_CHAN_2GHZ(chan)) {
+		if (OLC_FOR_AR9280_20_LATER) {
+			cck_ofdm_delta = 2;
+			REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+				ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
+				| ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
+				| ATH9K_POW_SM(ratesArray[rateXr], 8)
+				| ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
+			REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+				ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
+				| ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
+				| ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
+				| ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
+		} else {
+			REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+				ATH9K_POW_SM(ratesArray[rate2s], 24)
+				| ATH9K_POW_SM(ratesArray[rate2l], 16)
+				| ATH9K_POW_SM(ratesArray[rateXr], 8)
+				| ATH9K_POW_SM(ratesArray[rate1l], 0));
+			REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+				ATH9K_POW_SM(ratesArray[rate11s], 24)
+				| ATH9K_POW_SM(ratesArray[rate11l], 16)
+				| ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+				| ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+		}
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+	if (IS_CHAN_HT40(chan)) {
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
+				       ht40PowerIncForPdadc, 24)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+					 ht40PowerIncForPdadc, 16)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+					 ht40PowerIncForPdadc, 8)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+					 ht40PowerIncForPdadc, 0));
+		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
+				       ht40PowerIncForPdadc, 24)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+					 ht40PowerIncForPdadc, 16)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+					 ht40PowerIncForPdadc, 8)
+			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+					 ht40PowerIncForPdadc, 0));
+		if (OLC_FOR_AR9280_20_LATER) {
+			REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+				ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+				| ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
+				| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+				| ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
+		} else {
+			REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+				ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+				| ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+				| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+				| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+		}
+	}
+
+	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+	i = rate6mb;
+
+	if (IS_CHAN_HT40(chan))
+		i = rateHt40_0;
+	else if (IS_CHAN_HT20(chan))
+		i = rateHt20_0;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ah->regulatory.max_power_level =
+			ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+	else
+		ah->regulatory.max_power_level = ratesArray[i];
+
+	switch(ar5416_get_ntxchains(ah->txchainmask)) {
+	case 1:
+		break;
+	case 2:
+		ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+		break;
+	case 3:
+		ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+			"Invalid chainmask configuration\n");
+		break;
+	}
+}
+
+static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
+					  enum ieee80211_band freq_band)
+{
+	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+	struct modal_eep_header *pModal =
+		&(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
+	struct base_eep_header *pBase = &eep->baseEepHeader;
+	u8 num_ant_config;
+
+	num_ant_config = 1;
+
+	if (pBase->version >= 0x0E0D)
+		if (pModal->useAnt1)
+			num_ant_config += 1;
+
+	return num_ant_config;
+}
+
+static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
+					       struct ath9k_channel *chan)
+{
+	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+	struct modal_eep_header *pModal =
+		&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+	return pModal->antCtrlCommon & 0xFFFF;
+}
+
+static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+{
+#define EEP_DEF_SPURCHAN \
+	(ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+
+	u16 spur_val = AR_NO_SPUR;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+		"Getting spur idx %d is2Ghz. %d val %x\n",
+		i, is2GHz, ah->config.spurchans[i][is2GHz]);
+
+	switch (ah->config.spurmode) {
+	case SPUR_DISABLE:
+		break;
+	case SPUR_ENABLE_IOCTL:
+		spur_val = ah->config.spurchans[i][is2GHz];
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+			"Getting spur val from new loc. %d\n", spur_val);
+		break;
+	case SPUR_ENABLE_EEPROM:
+		spur_val = EEP_DEF_SPURCHAN;
+		break;
+	}
+
+	return spur_val;
+
+#undef EEP_DEF_SPURCHAN
+}
+
+static struct eeprom_ops eep_def_ops = {
+	.check_eeprom		= ath9k_hw_def_check_eeprom,
+	.get_eeprom		= ath9k_hw_def_get_eeprom,
+	.fill_eeprom		= ath9k_hw_def_fill_eeprom,
+	.get_eeprom_ver		= ath9k_hw_def_get_eeprom_ver,
+	.get_eeprom_rev		= ath9k_hw_def_get_eeprom_rev,
+	.get_num_ant_config	= ath9k_hw_def_get_num_ant_config,
+	.get_eeprom_antenna_cfg	= ath9k_hw_def_get_eeprom_antenna_cfg,
+	.set_board_values	= ath9k_hw_def_set_board_values,
+	.set_addac		= ath9k_hw_def_set_addac,
+	.set_txpower		= ath9k_hw_def_set_txpower,
+	.get_spur_channel	= ath9k_hw_def_get_spur_channel
+};
+
+int ath9k_hw_eeprom_attach(struct ath_hw *ah)
+{
+	int status;
+
+	if (AR_SREV_9285(ah)) {
+		ah->eep_map = EEP_MAP_4KBITS;
+		ah->eep_ops = &eep_4k_ops;
+	} else {
+		ah->eep_map = EEP_MAP_DEFAULT;
+		ah->eep_ops = &eep_def_ops;
+	}
+
+	if (!ah->eep_ops->fill_eeprom(ah))
+		return -EIO;
+
+	status = ah->eep_ops->check_eeprom(ah);
+
+	return status;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/eeprom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/eeprom.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef EEPROM_H
+#define EEPROM_H
+
+#include <net/cfg80211.h>
+
+#define AH_USE_EEPROM   0x1
+
+#ifdef __BIG_ENDIAN
+#define AR5416_EEPROM_MAGIC 0x5aa5
+#else
+#define AR5416_EEPROM_MAGIC 0xa55a
+#endif
+
+#define CTRY_DEBUG   0x1ff
+#define	CTRY_DEFAULT 0
+
+#define AR_EEPROM_EEPCAP_COMPRESS_DIS   0x0001
+#define AR_EEPROM_EEPCAP_AES_DIS        0x0002
+#define AR_EEPROM_EEPCAP_FASTFRAME_DIS  0x0004
+#define AR_EEPROM_EEPCAP_BURST_DIS      0x0008
+#define AR_EEPROM_EEPCAP_MAXQCU         0x01F0
+#define AR_EEPROM_EEPCAP_MAXQCU_S       4
+#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN  0x0200
+#define AR_EEPROM_EEPCAP_KC_ENTRIES     0xF000
+#define AR_EEPROM_EEPCAP_KC_ENTRIES_S   12
+
+#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND   0x0040
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN    0x0080
+#define AR_EEPROM_EEREGCAP_EN_KK_U2         0x0100
+#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND    0x0200
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD     0x0400
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A    0x0800
+
+#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0  0x4000
+#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000
+
+#define AR5416_EEPROM_MAGIC_OFFSET  0x0
+#define AR5416_EEPROM_S             2
+#define AR5416_EEPROM_OFFSET        0x2000
+#define AR5416_EEPROM_MAX           0xae0
+
+#define AR5416_EEPROM_START_ADDR \
+	(AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
+
+#define SD_NO_CTL               0xE0
+#define NO_CTL                  0xff
+#define CTL_MODE_M              7
+#define CTL_11A                 0
+#define CTL_11B                 1
+#define CTL_11G                 2
+#define CTL_2GHT20              5
+#define CTL_5GHT20              6
+#define CTL_2GHT40              7
+#define CTL_5GHT40              8
+
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2
+#define SUB_NUM_CTL_MODES_AT_2G_40 3
+
+#define INCREASE_MAXPOW_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+#define INCREASE_MAXPOW_BY_THREE_CHAIN   10 /* 10*log10(3)*2 */
+
+/*
+ * For AR9285 and later chipsets, the following bits are not being programmed
+ * in EEPROM and so need to be enabled always.
+ *
+ * Bit 0: en_fcc_mid
+ * Bit 1: en_jap_mid
+ * Bit 2: en_fcc_dfs_ht40
+ * Bit 3: en_jap_ht40
+ * Bit 4: en_jap_dfs_ht40
+ */
+#define AR9285_RDEXT_DEFAULT    0x1F
+
+#define AR_EEPROM_MAC(i)	(0x1d+(i))
+#define ATH9K_POW_SM(_r, _s)	(((_r) & 0x3f) << (_s))
+#define FREQ2FBIN(x, y)		((y) ? ((x) - 2300) : (((x) - 4800) / 5))
+#define ath9k_hw_use_flash(_ah)	(!(_ah->ah_flags & AH_USE_EEPROM))
+
+#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
+#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
+				 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+
+#define AR_EEPROM_RFSILENT_GPIO_SEL     0x001c
+#define AR_EEPROM_RFSILENT_GPIO_SEL_S   2
+#define AR_EEPROM_RFSILENT_POLARITY     0x0002
+#define AR_EEPROM_RFSILENT_POLARITY_S   1
+
+#define EEP_RFSILENT_ENABLED        0x0001
+#define EEP_RFSILENT_ENABLED_S      0
+#define EEP_RFSILENT_POLARITY       0x0002
+#define EEP_RFSILENT_POLARITY_S     1
+#define EEP_RFSILENT_GPIO_SEL       0x001c
+#define EEP_RFSILENT_GPIO_SEL_S     2
+
+#define AR5416_OPFLAGS_11A           0x01
+#define AR5416_OPFLAGS_11G           0x02
+#define AR5416_OPFLAGS_N_5G_HT40     0x04
+#define AR5416_OPFLAGS_N_2G_HT40     0x08
+#define AR5416_OPFLAGS_N_5G_HT20     0x10
+#define AR5416_OPFLAGS_N_2G_HT20     0x20
+
+#define AR5416_EEP_NO_BACK_VER       0x1
+#define AR5416_EEP_VER               0xE
+#define AR5416_EEP_VER_MINOR_MASK    0x0FFF
+#define AR5416_EEP_MINOR_VER_2       0x2
+#define AR5416_EEP_MINOR_VER_3       0x3
+#define AR5416_EEP_MINOR_VER_7       0x7
+#define AR5416_EEP_MINOR_VER_9       0x9
+#define AR5416_EEP_MINOR_VER_16      0x10
+#define AR5416_EEP_MINOR_VER_17      0x11
+#define AR5416_EEP_MINOR_VER_19      0x13
+#define AR5416_EEP_MINOR_VER_20      0x14
+#define AR5416_EEP_MINOR_VER_22      0x16
+
+#define AR5416_NUM_5G_CAL_PIERS         8
+#define AR5416_NUM_2G_CAL_PIERS         4
+#define AR5416_NUM_5G_20_TARGET_POWERS  8
+#define AR5416_NUM_5G_40_TARGET_POWERS  8
+#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_NUM_2G_20_TARGET_POWERS  4
+#define AR5416_NUM_2G_40_TARGET_POWERS  4
+#define AR5416_NUM_CTLS                 24
+#define AR5416_NUM_BAND_EDGES           8
+#define AR5416_NUM_PD_GAINS             4
+#define AR5416_PD_GAINS_IN_MASK         4
+#define AR5416_PD_GAIN_ICEPTS           5
+#define AR5416_EEPROM_MODAL_SPURS       5
+#define AR5416_MAX_RATE_POWER           63
+#define AR5416_NUM_PDADC_VALUES         128
+#define AR5416_BCHAN_UNUSED             0xFF
+#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
+#define AR5416_MAX_CHAINS               3
+#define AR5416_PWR_TABLE_OFFSET         -5
+
+/* Rx gain type values */
+#define AR5416_EEP_RXGAIN_23DB_BACKOFF     0
+#define AR5416_EEP_RXGAIN_13DB_BACKOFF     1
+#define AR5416_EEP_RXGAIN_ORIG             2
+
+/* Tx gain type values */
+#define AR5416_EEP_TXGAIN_ORIGINAL         0
+#define AR5416_EEP_TXGAIN_HIGH_POWER       1
+
+#define AR5416_EEP4K_START_LOC                64
+#define AR5416_EEP4K_NUM_2G_CAL_PIERS         3
+#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS  3
+#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS  3
+#define AR5416_EEP4K_NUM_CTLS                 12
+#define AR5416_EEP4K_NUM_BAND_EDGES           4
+#define AR5416_EEP4K_NUM_PD_GAINS             2
+#define AR5416_EEP4K_PD_GAINS_IN_MASK         4
+#define AR5416_EEP4K_PD_GAIN_ICEPTS           5
+#define AR5416_EEP4K_MAX_CHAINS               1
+
+#define AR9280_TX_GAIN_TABLE_SIZE 22
+
+enum eeprom_param {
+	EEP_NFTHRESH_5,
+	EEP_NFTHRESH_2,
+	EEP_MAC_MSW,
+	EEP_MAC_MID,
+	EEP_MAC_LSW,
+	EEP_REG_0,
+	EEP_REG_1,
+	EEP_OP_CAP,
+	EEP_OP_MODE,
+	EEP_RF_SILENT,
+	EEP_OB_5,
+	EEP_DB_5,
+	EEP_OB_2,
+	EEP_DB_2,
+	EEP_MINOR_REV,
+	EEP_TX_MASK,
+	EEP_RX_MASK,
+	EEP_RXGAIN_TYPE,
+	EEP_TXGAIN_TYPE,
+	EEP_OL_PWRCTRL,
+	EEP_RC_CHAIN_MASK,
+	EEP_DAC_HPWR_5G,
+	EEP_FRAC_N_5G
+};
+
+enum ar5416_rates {
+	rate6mb, rate9mb, rate12mb, rate18mb,
+	rate24mb, rate36mb, rate48mb, rate54mb,
+	rate1l, rate2l, rate2s, rate5_5l,
+	rate5_5s, rate11l, rate11s, rateXr,
+	rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
+	rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
+	rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
+	rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
+	rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
+	Ar5416RateSize
+};
+
+enum ath9k_hal_freq_band {
+	ATH9K_HAL_FREQ_BAND_5GHZ = 0,
+	ATH9K_HAL_FREQ_BAND_2GHZ = 1
+};
+
+struct base_eep_header {
+	u16 length;
+	u16 checksum;
+	u16 version;
+	u8 opCapFlags;
+	u8 eepMisc;
+	u16 regDmn[2];
+	u8 macAddr[6];
+	u8 rxMask;
+	u8 txMask;
+	u16 rfSilent;
+	u16 blueToothOptions;
+	u16 deviceCap;
+	u32 binBuildNumber;
+	u8 deviceType;
+	u8 pwdclkind;
+	u8 futureBase_1[2];
+	u8 rxGainType;
+	u8 dacHiPwrMode_5G;
+	u8 openLoopPwrCntl;
+	u8 dacLpMode;
+	u8 txGainType;
+	u8 rcChainMask;
+	u8 desiredScaleCCK;
+	u8 power_table_offset;
+	u8 frac_n_5g;
+	u8 futureBase_3[21];
+} __packed;
+
+struct base_eep_header_4k {
+	u16 length;
+	u16 checksum;
+	u16 version;
+	u8 opCapFlags;
+	u8 eepMisc;
+	u16 regDmn[2];
+	u8 macAddr[6];
+	u8 rxMask;
+	u8 txMask;
+	u16 rfSilent;
+	u16 blueToothOptions;
+	u16 deviceCap;
+	u32 binBuildNumber;
+	u8 deviceType;
+	u8 txGainType;
+} __packed;
+
+
+struct spur_chan {
+	u16 spurChan;
+	u8 spurRangeLow;
+	u8 spurRangeHigh;
+} __packed;
+
+struct modal_eep_header {
+	u32 antCtrlChain[AR5416_MAX_CHAINS];
+	u32 antCtrlCommon;
+	u8 antennaGainCh[AR5416_MAX_CHAINS];
+	u8 switchSettling;
+	u8 txRxAttenCh[AR5416_MAX_CHAINS];
+	u8 rxTxMarginCh[AR5416_MAX_CHAINS];
+	u8 adcDesiredSize;
+	u8 pgaDesiredSize;
+	u8 xlnaGainCh[AR5416_MAX_CHAINS];
+	u8 txEndToXpaOff;
+	u8 txEndToRxOn;
+	u8 txFrameToXpaOn;
+	u8 thresh62;
+	u8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
+	u8 xpdGain;
+	u8 xpd;
+	u8 iqCalICh[AR5416_MAX_CHAINS];
+	u8 iqCalQCh[AR5416_MAX_CHAINS];
+	u8 pdGainOverlap;
+	u8 ob;
+	u8 db;
+	u8 xpaBiasLvl;
+	u8 pwrDecreaseFor2Chain;
+	u8 pwrDecreaseFor3Chain;
+	u8 txFrameToDataStart;
+	u8 txFrameToPaOn;
+	u8 ht40PowerIncForPdadc;
+	u8 bswAtten[AR5416_MAX_CHAINS];
+	u8 bswMargin[AR5416_MAX_CHAINS];
+	u8 swSettleHt40;
+	u8 xatten2Db[AR5416_MAX_CHAINS];
+	u8 xatten2Margin[AR5416_MAX_CHAINS];
+	u8 ob_ch1;
+	u8 db_ch1;
+	u8 useAnt1:1,
+	    force_xpaon:1,
+	    local_bias:1,
+	    femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
+	u8 miscBits;
+	u16 xpaBiasLvlFreq[3];
+	u8 futureModal[6];
+
+	struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
+} __packed;
+
+struct calDataPerFreqOpLoop {
+	u8 pwrPdg[2][5];
+	u8 vpdPdg[2][5];
+	u8 pcdac[2][5];
+	u8 empty[2][5];
+} __packed;
+
+struct modal_eep_4k_header {
+	u32  antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
+	u32  antCtrlCommon;
+	u8   antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
+	u8   switchSettling;
+	u8   txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
+	u8   rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
+	u8   adcDesiredSize;
+	u8   pgaDesiredSize;
+	u8   xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
+	u8   txEndToXpaOff;
+	u8   txEndToRxOn;
+	u8   txFrameToXpaOn;
+	u8   thresh62;
+	u8   noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
+	u8   xpdGain;
+	u8   xpd;
+	u8   iqCalICh[AR5416_EEP4K_MAX_CHAINS];
+	u8   iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
+	u8   pdGainOverlap;
+	u8   ob_01;
+	u8   db1_01;
+	u8   xpaBiasLvl;
+	u8   txFrameToDataStart;
+	u8   txFrameToPaOn;
+	u8   ht40PowerIncForPdadc;
+	u8   bswAtten[AR5416_EEP4K_MAX_CHAINS];
+	u8   bswMargin[AR5416_EEP4K_MAX_CHAINS];
+	u8   swSettleHt40;
+	u8   xatten2Db[AR5416_EEP4K_MAX_CHAINS];
+	u8   xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
+	u8   db2_01;
+	u8   version;
+	u16  ob_234;
+	u16  db1_234;
+	u16  db2_234;
+	u8   futureModal[4];
+
+	struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
+} __packed;
+
+
+struct cal_data_per_freq {
+	u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+	u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed;
+
+struct cal_data_per_freq_4k {
+	u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
+	u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
+} __packed;
+
+struct cal_target_power_leg {
+	u8 bChannel;
+	u8 tPow2x[4];
+} __packed;
+
+struct cal_target_power_ht {
+	u8 bChannel;
+	u8 tPow2x[8];
+} __packed;
+
+
+#ifdef __BIG_ENDIAN_BITFIELD
+struct cal_ctl_edges {
+	u8 bChannel;
+	u8 flag:2, tPower:6;
+} __packed;
+#else
+struct cal_ctl_edges {
+	u8 bChannel;
+	u8 tPower:6, flag:2;
+} __packed;
+#endif
+
+struct cal_ctl_data {
+	struct cal_ctl_edges
+	ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __packed;
+
+struct cal_ctl_data_4k {
+	struct cal_ctl_edges
+	ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
+} __packed;
+
+struct ar5416_eeprom_def {
+	struct base_eep_header baseEepHeader;
+	u8 custData[64];
+	struct modal_eep_header modalHeader[2];
+	u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
+	u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
+	struct cal_data_per_freq
+	 calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
+	struct cal_data_per_freq
+	 calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+	struct cal_target_power_leg
+	 calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
+	struct cal_target_power_ht
+	 calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
+	struct cal_target_power_ht
+	 calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
+	struct cal_target_power_leg
+	 calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
+	struct cal_target_power_leg
+	 calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
+	struct cal_target_power_ht
+	 calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
+	struct cal_target_power_ht
+	 calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
+	u8 ctlIndex[AR5416_NUM_CTLS];
+	struct cal_ctl_data ctlData[AR5416_NUM_CTLS];
+	u8 padding;
+} __packed;
+
+struct ar5416_eeprom_4k {
+	struct base_eep_header_4k baseEepHeader;
+	u8 custData[20];
+	struct modal_eep_4k_header modalHeader;
+	u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
+	struct cal_data_per_freq_4k
+	calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
+	struct cal_target_power_leg
+	calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
+	struct cal_target_power_leg
+	calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+	struct cal_target_power_ht
+	calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+	struct cal_target_power_ht
+	calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
+	u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
+	struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
+	u8 padding;
+} __packed;
+
+enum reg_ext_bitmap {
+	REG_EXT_JAPAN_MIDBAND = 1,
+	REG_EXT_FCC_DFS_HT40 = 2,
+	REG_EXT_JAPAN_NONDFS_HT40 = 3,
+	REG_EXT_JAPAN_DFS_HT40 = 4
+};
+
+struct ath9k_country_entry {
+	u16 countryCode;
+	u16 regDmnEnum;
+	u16 regDmn5G;
+	u16 regDmn2G;
+	u8 isMultidomain;
+	u8 iso[3];
+};
+
+enum ath9k_eep_map {
+	EEP_MAP_DEFAULT = 0x0,
+	EEP_MAP_4KBITS,
+	EEP_MAP_MAX
+};
+
+struct eeprom_ops {
+	int (*check_eeprom)(struct ath_hw *hw);
+	u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
+	bool (*fill_eeprom)(struct ath_hw *hw);
+	int (*get_eeprom_ver)(struct ath_hw *hw);
+	int (*get_eeprom_rev)(struct ath_hw *hw);
+	u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band);
+	u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
+				      struct ath9k_channel *chan);
+	void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
+	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
+	void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
+			   u16 cfgCtl, u8 twiceAntennaReduction,
+			   u8 twiceMaxRegulatoryPower, u8 powerLimit);
+	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
+};
+
+#define ar5416_get_ntxchains(_txchainmask)			\
+	(((_txchainmask >> 2) & 1) +                            \
+	 ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
+
+int ath9k_hw_eeprom_attach(struct ath_hw *ah);
+
+#endif /* EEPROM_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/hw.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/hw.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/hw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,3870 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/io.h>
+#include <asm/unaligned.h>
+
+#include "ath9k.h"
+#include "initvals.h"
+
+static int btcoex_enable;
+module_param(btcoex_enable, bool, 0);
+MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support");
+
+#define ATH9K_CLOCK_RATE_CCK		22
+#define ATH9K_CLOCK_RATE_5GHZ_OFDM	40
+#define ATH9K_CLOCK_RATE_2GHZ_OFDM	44
+
+static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
+static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
+			      enum ath9k_ht_macmode macmode);
+static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
+			      struct ar5416_eeprom_def *pEepData,
+			      u32 reg, u32 value);
+static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
+static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
+
+/********************/
+/* Helper Functions */
+/********************/
+
+static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+
+	if (!ah->curchan) /* should really check for CCK instead */
+		return clks / ATH9K_CLOCK_RATE_CCK;
+	if (conf->channel->band == IEEE80211_BAND_2GHZ)
+		return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
+
+	return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
+}
+
+static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+
+	if (conf_is_ht40(conf))
+		return ath9k_hw_mac_usec(ah, clks) / 2;
+	else
+		return ath9k_hw_mac_usec(ah, clks);
+}
+
+static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+
+	if (!ah->curchan) /* should really check for CCK instead */
+		return usecs *ATH9K_CLOCK_RATE_CCK;
+	if (conf->channel->band == IEEE80211_BAND_2GHZ)
+		return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
+	return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM;
+}
+
+static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
+{
+	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
+
+	if (conf_is_ht40(conf))
+		return ath9k_hw_mac_clks(ah, usecs) * 2;
+	else
+		return ath9k_hw_mac_clks(ah, usecs);
+}
+
+/*
+ * Read and write, they both share the same lock. We do this to serialize
+ * reads and writes on Atheros 802.11n PCI devices only. This is required
+ * as the FIFO on these devices can only accept sanely 2 requests. After
+ * that the device goes bananas. Serializing the reads/writes prevents this
+ * from happening.
+ */
+
+void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val)
+{
+	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
+		unsigned long flags;
+		spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
+		iowrite32(val, ah->ah_sc->mem + reg_offset);
+		spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
+	} else
+		iowrite32(val, ah->ah_sc->mem + reg_offset);
+}
+
+unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset)
+{
+	u32 val;
+	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
+		unsigned long flags;
+		spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
+		val = ioread32(ah->ah_sc->mem + reg_offset);
+		spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
+	} else
+		val = ioread32(ah->ah_sc->mem + reg_offset);
+	return val;
+}
+
+bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
+{
+	int i;
+
+	BUG_ON(timeout < AH_TIME_QUANTUM);
+
+	for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
+		if ((REG_READ(ah, reg) & mask) == val)
+			return true;
+
+		udelay(AH_TIME_QUANTUM);
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+		"timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+		timeout, reg, REG_READ(ah, reg), mask, val);
+
+	return false;
+}
+
+u32 ath9k_hw_reverse_bits(u32 val, u32 n)
+{
+	u32 retval;
+	int i;
+
+	for (i = 0, retval = 0; i < n; i++) {
+		retval = (retval << 1) | (val & 1);
+		val >>= 1;
+	}
+	return retval;
+}
+
+bool ath9k_get_channel_edges(struct ath_hw *ah,
+			     u16 flags, u16 *low,
+			     u16 *high)
+{
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+	if (flags & CHANNEL_5GHZ) {
+		*low = pCap->low_5ghz_chan;
+		*high = pCap->high_5ghz_chan;
+		return true;
+	}
+	if ((flags & CHANNEL_2GHZ)) {
+		*low = pCap->low_2ghz_chan;
+		*high = pCap->high_2ghz_chan;
+		return true;
+	}
+	return false;
+}
+
+u16 ath9k_hw_computetxtime(struct ath_hw *ah,
+			   const struct ath_rate_table *rates,
+			   u32 frameLen, u16 rateix,
+			   bool shortPreamble)
+{
+	u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
+	u32 kbps;
+
+	kbps = rates->info[rateix].ratekbps;
+
+	if (kbps == 0)
+		return 0;
+
+	switch (rates->info[rateix].phy) {
+	case WLAN_RC_PHY_CCK:
+		phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
+		if (shortPreamble && rates->info[rateix].short_preamble)
+			phyTime >>= 1;
+		numBits = frameLen << 3;
+		txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
+		break;
+	case WLAN_RC_PHY_OFDM:
+		if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) {
+			bitsPerSymbol =	(kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
+			numBits = OFDM_PLCP_BITS + (frameLen << 3);
+			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+			txTime = OFDM_SIFS_TIME_QUARTER
+				+ OFDM_PREAMBLE_TIME_QUARTER
+				+ (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
+		} else if (ah->curchan &&
+			   IS_CHAN_HALF_RATE(ah->curchan)) {
+			bitsPerSymbol =	(kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
+			numBits = OFDM_PLCP_BITS + (frameLen << 3);
+			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+			txTime = OFDM_SIFS_TIME_HALF +
+				OFDM_PREAMBLE_TIME_HALF
+				+ (numSymbols * OFDM_SYMBOL_TIME_HALF);
+		} else {
+			bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
+			numBits = OFDM_PLCP_BITS + (frameLen << 3);
+			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+			txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
+				+ (numSymbols * OFDM_SYMBOL_TIME);
+		}
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Unknown phy %u (rate ix %u)\n",
+			rates->info[rateix].phy, rateix);
+		txTime = 0;
+		break;
+	}
+
+	return txTime;
+}
+
+void ath9k_hw_get_channel_centers(struct ath_hw *ah,
+				  struct ath9k_channel *chan,
+				  struct chan_centers *centers)
+{
+	int8_t extoff;
+
+	if (!IS_CHAN_HT40(chan)) {
+		centers->ctl_center = centers->ext_center =
+			centers->synth_center = chan->channel;
+		return;
+	}
+
+	if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+	    (chan->chanmode == CHANNEL_G_HT40PLUS)) {
+		centers->synth_center =
+			chan->channel + HT40_CHANNEL_CENTER_SHIFT;
+		extoff = 1;
+	} else {
+		centers->synth_center =
+			chan->channel - HT40_CHANNEL_CENTER_SHIFT;
+		extoff = -1;
+	}
+
+	centers->ctl_center =
+		centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
+	centers->ext_center =
+		centers->synth_center + (extoff *
+			 ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ?
+			  HT40_CHANNEL_CENTER_SHIFT : 15));
+}
+
+/******************/
+/* Chip Revisions */
+/******************/
+
+static void ath9k_hw_read_revisions(struct ath_hw *ah)
+{
+	u32 val;
+
+	val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+
+	if (val == 0xFF) {
+		val = REG_READ(ah, AR_SREV);
+		ah->hw_version.macVersion =
+			(val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+		ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+		ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+	} else {
+		if (!AR_SREV_9100(ah))
+			ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
+
+		ah->hw_version.macRev = val & AR_SREV_REVISION;
+
+		if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)
+			ah->is_pciexpress = true;
+	}
+}
+
+static int ath9k_hw_get_radiorev(struct ath_hw *ah)
+{
+	u32 val;
+	int i;
+
+	REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
+
+	for (i = 0; i < 8; i++)
+		REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
+	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
+	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
+
+	return ath9k_hw_reverse_bits(val, 8);
+}
+
+/************************************/
+/* HW Attach, Detach, Init Routines */
+/************************************/
+
+static void ath9k_hw_disablepcie(struct ath_hw *ah)
+{
+	if (AR_SREV_9100(ah))
+		return;
+
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+	REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
+
+	REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+}
+
+static bool ath9k_hw_chip_test(struct ath_hw *ah)
+{
+	u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
+	u32 regHold[2];
+	u32 patternData[4] = { 0x55555555,
+			       0xaaaaaaaa,
+			       0x66666666,
+			       0x99999999 };
+	int i, j;
+
+	for (i = 0; i < 2; i++) {
+		u32 addr = regAddr[i];
+		u32 wrData, rdData;
+
+		regHold[i] = REG_READ(ah, addr);
+		for (j = 0; j < 0x100; j++) {
+			wrData = (j << 16) | j;
+			REG_WRITE(ah, addr, wrData);
+			rdData = REG_READ(ah, addr);
+			if (rdData != wrData) {
+				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+					"address test failed "
+					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+					addr, wrData, rdData);
+				return false;
+			}
+		}
+		for (j = 0; j < 4; j++) {
+			wrData = patternData[j];
+			REG_WRITE(ah, addr, wrData);
+			rdData = REG_READ(ah, addr);
+			if (wrData != rdData) {
+				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+					"address test failed "
+					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+					addr, wrData, rdData);
+				return false;
+			}
+		}
+		REG_WRITE(ah, regAddr[i], regHold[i]);
+	}
+	udelay(100);
+
+	return true;
+}
+
+static const char *ath9k_hw_devname(u16 devid)
+{
+	switch (devid) {
+	case AR5416_DEVID_PCI:
+		return "Atheros 5416";
+	case AR5416_DEVID_PCIE:
+		return "Atheros 5418";
+	case AR9160_DEVID_PCI:
+		return "Atheros 9160";
+	case AR5416_AR9100_DEVID:
+		return "Atheros 9100";
+	case AR9280_DEVID_PCI:
+	case AR9280_DEVID_PCIE:
+		return "Atheros 9280";
+	case AR9285_DEVID_PCIE:
+		return "Atheros 9285";
+	}
+
+	return NULL;
+}
+
+static void ath9k_hw_set_defaults(struct ath_hw *ah)
+{
+	int i;
+
+	ah->config.dma_beacon_response_time = 2;
+	ah->config.sw_beacon_response_time = 10;
+	ah->config.additional_swba_backoff = 0;
+	ah->config.ack_6mb = 0x0;
+	ah->config.cwm_ignore_extcca = 0;
+	ah->config.pcie_powersave_enable = 0;
+	ah->config.pcie_clock_req = 0;
+	ah->config.pcie_waen = 0;
+	ah->config.analog_shiftreg = 1;
+	ah->config.ht_enable = 1;
+	ah->config.ofdm_trig_low = 200;
+	ah->config.ofdm_trig_high = 500;
+	ah->config.cck_trig_high = 200;
+	ah->config.cck_trig_low = 100;
+	ah->config.enable_ani = 1;
+	ah->config.diversity_control = 0;
+	ah->config.antenna_switch_swap = 0;
+
+	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+		ah->config.spurchans[i][0] = AR_NO_SPUR;
+		ah->config.spurchans[i][1] = AR_NO_SPUR;
+	}
+
+	ah->config.intr_mitigation = true;
+
+	/*
+	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
+	 * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
+	 * This means we use it for all AR5416 devices, and the few
+	 * minor PCI AR9280 devices out there.
+	 *
+	 * Serialization is required because these devices do not handle
+	 * well the case of two concurrent reads/writes due to the latency
+	 * involved. During one read/write another read/write can be issued
+	 * on another CPU while the previous read/write may still be working
+	 * on our hardware, if we hit this case the hardware poops in a loop.
+	 * We prevent this by serializing reads and writes.
+	 *
+	 * This issue is not present on PCI-Express devices or pre-AR5416
+	 * devices (legacy, 802.11abg).
+	 */
+	if (num_possible_cpus() > 1)
+		ah->config.serialize_regmode = SER_REG_MODE_AUTO;
+}
+
+static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
+					int *status)
+{
+	struct ath_hw *ah;
+
+	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
+	if (ah == NULL) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Cannot allocate memory for state block\n");
+		*status = -ENOMEM;
+		return NULL;
+	}
+
+	ah->ah_sc = sc;
+	ah->hw_version.magic = AR5416_MAGIC;
+	ah->regulatory.country_code = CTRY_DEFAULT;
+	ah->hw_version.devid = devid;
+	ah->hw_version.subvendorid = 0;
+
+	ah->ah_flags = 0;
+	if ((devid == AR5416_AR9100_DEVID))
+		ah->hw_version.macVersion = AR_SREV_VERSION_9100;
+	if (!AR_SREV_9100(ah))
+		ah->ah_flags = AH_USE_EEPROM;
+
+	ah->regulatory.power_limit = MAX_RATE_POWER;
+	ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
+	ah->atim_window = 0;
+	ah->diversity_control = ah->config.diversity_control;
+	ah->antenna_switch_swap =
+		ah->config.antenna_switch_swap;
+	ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
+	ah->beacon_interval = 100;
+	ah->enable_32kHz_clock = DONT_USE_32KHZ;
+	ah->slottime = (u32) -1;
+	ah->acktimeout = (u32) -1;
+	ah->ctstimeout = (u32) -1;
+	ah->globaltxtimeout = (u32) -1;
+
+	ah->gbeacon_rate = 0;
+
+	return ah;
+}
+
+static int ath9k_hw_rfattach(struct ath_hw *ah)
+{
+	bool rfStatus = false;
+	int ecode = 0;
+
+	rfStatus = ath9k_hw_init_rf(ah, &ecode);
+	if (!rfStatus) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"RF setup failed, status: %u\n", ecode);
+		return ecode;
+	}
+
+	return 0;
+}
+
+static int ath9k_hw_rf_claim(struct ath_hw *ah)
+{
+	u32 val;
+
+	REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+	val = ath9k_hw_get_radiorev(ah);
+	switch (val & AR_RADIO_SREV_MAJOR) {
+	case 0:
+		val = AR_RAD5133_SREV_MAJOR;
+		break;
+	case AR_RAD5133_SREV_MAJOR:
+	case AR_RAD5122_SREV_MAJOR:
+	case AR_RAD2133_SREV_MAJOR:
+	case AR_RAD2122_SREV_MAJOR:
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Radio Chip Rev 0x%02X not supported\n",
+			val & AR_RADIO_SREV_MAJOR);
+		return -EOPNOTSUPP;
+	}
+
+	ah->hw_version.analog5GhzRev = val;
+
+	return 0;
+}
+
+static int ath9k_hw_init_macaddr(struct ath_hw *ah)
+{
+	u32 sum;
+	int i;
+	u16 eeval;
+
+	sum = 0;
+	for (i = 0; i < 3; i++) {
+		eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i));
+		sum += eeval;
+		ah->macaddr[2 * i] = eeval >> 8;
+		ah->macaddr[2 * i + 1] = eeval & 0xff;
+	}
+	if (sum == 0 || sum == 0xffff * 3)
+		return -EADDRNOTAVAIL;
+
+	return 0;
+}
+
+static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah)
+{
+	u32 rxgain_type;
+
+	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
+		rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
+
+		if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+			ar9280Modes_backoff_13db_rxgain_9280_2,
+			ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
+		else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+			ar9280Modes_backoff_23db_rxgain_9280_2,
+			ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
+		else
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+			ar9280Modes_original_rxgain_9280_2,
+			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+	} else {
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+			ar9280Modes_original_rxgain_9280_2,
+			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+	}
+}
+
+static void ath9k_hw_init_txgain_ini(struct ath_hw *ah)
+{
+	u32 txgain_type;
+
+	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
+		txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
+
+		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+			ar9280Modes_high_power_tx_gain_9280_2,
+			ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
+		else
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+			ar9280Modes_original_tx_gain_9280_2,
+			ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+	} else {
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+		ar9280Modes_original_tx_gain_9280_2,
+		ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+	}
+}
+
+static int ath9k_hw_post_attach(struct ath_hw *ah)
+{
+	int ecode;
+
+	if (!ath9k_hw_chip_test(ah))
+		return -ENODEV;
+
+	ecode = ath9k_hw_rf_claim(ah);
+	if (ecode != 0)
+		return ecode;
+
+	ecode = ath9k_hw_eeprom_attach(ah);
+	if (ecode != 0)
+		return ecode;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n",
+		ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah));
+
+	ecode = ath9k_hw_rfattach(ah);
+	if (ecode != 0)
+		return ecode;
+
+	if (!AR_SREV_9100(ah)) {
+		ath9k_hw_ani_setup(ah);
+		ath9k_hw_ani_attach(ah);
+	}
+
+	return 0;
+}
+
+static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
+					 int *status)
+{
+	struct ath_hw *ah;
+	int ecode;
+	u32 i, j;
+
+	ah = ath9k_hw_newstate(devid, sc, status);
+	if (ah == NULL)
+		return NULL;
+
+	ath9k_hw_set_defaults(ah);
+
+	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
+		DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
+		ecode = -EIO;
+		goto bad;
+	}
+
+	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
+		DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
+		ecode = -EIO;
+		goto bad;
+	}
+
+	if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
+		if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
+		    (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
+			ah->config.serialize_regmode =
+				SER_REG_MODE_ON;
+		} else {
+			ah->config.serialize_regmode =
+				SER_REG_MODE_OFF;
+		}
+	}
+
+	DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
+		ah->config.serialize_regmode);
+
+	if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) &&
+	    (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
+	    (ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
+	    (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Mac Chip Rev 0x%02x.%x is not supported by "
+			"this driver\n", ah->hw_version.macVersion,
+			ah->hw_version.macRev);
+		ecode = -EOPNOTSUPP;
+		goto bad;
+	}
+
+	if (AR_SREV_9100(ah)) {
+		ah->iq_caldata.calData = &iq_cal_multi_sample;
+		ah->supp_cals = IQ_MISMATCH_CAL;
+		ah->is_pciexpress = false;
+	}
+	ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
+
+	if (AR_SREV_9160_10_OR_LATER(ah)) {
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			ah->iq_caldata.calData = &iq_cal_single_sample;
+			ah->adcgain_caldata.calData =
+				&adc_gain_cal_single_sample;
+			ah->adcdc_caldata.calData =
+				&adc_dc_cal_single_sample;
+			ah->adcdc_calinitdata.calData =
+				&adc_init_dc_cal;
+		} else {
+			ah->iq_caldata.calData = &iq_cal_multi_sample;
+			ah->adcgain_caldata.calData =
+				&adc_gain_cal_multi_sample;
+			ah->adcdc_caldata.calData =
+				&adc_dc_cal_multi_sample;
+			ah->adcdc_calinitdata.calData =
+				&adc_init_dc_cal;
+		}
+		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+	}
+
+	ah->ani_function = ATH9K_ANI_ALL;
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+
+	if (AR_SREV_9285_12_OR_LATER(ah)) {
+
+		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
+			       ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
+		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
+			       ARRAY_SIZE(ar9285Common_9285_1_2), 2);
+
+		if (ah->config.pcie_clock_req) {
+			INIT_INI_ARRAY(&ah->iniPcieSerdes,
+			ar9285PciePhy_clkreq_off_L1_9285_1_2,
+			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
+		} else {
+			INIT_INI_ARRAY(&ah->iniPcieSerdes,
+			ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
+			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
+				  2);
+		}
+	} else if (AR_SREV_9285_10_OR_LATER(ah)) {
+		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285,
+			       ARRAY_SIZE(ar9285Modes_9285), 6);
+		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285,
+			       ARRAY_SIZE(ar9285Common_9285), 2);
+
+		if (ah->config.pcie_clock_req) {
+			INIT_INI_ARRAY(&ah->iniPcieSerdes,
+			ar9285PciePhy_clkreq_off_L1_9285,
+			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
+		} else {
+			INIT_INI_ARRAY(&ah->iniPcieSerdes,
+			ar9285PciePhy_clkreq_always_on_L1_9285,
+			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
+		}
+	} else if (AR_SREV_9280_20_OR_LATER(ah)) {
+		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
+			       ARRAY_SIZE(ar9280Modes_9280_2), 6);
+		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
+			       ARRAY_SIZE(ar9280Common_9280_2), 2);
+
+		if (ah->config.pcie_clock_req) {
+			INIT_INI_ARRAY(&ah->iniPcieSerdes,
+			       ar9280PciePhy_clkreq_off_L1_9280,
+			       ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2);
+		} else {
+			INIT_INI_ARRAY(&ah->iniPcieSerdes,
+			       ar9280PciePhy_clkreq_always_on_L1_9280,
+			       ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
+		}
+		INIT_INI_ARRAY(&ah->iniModesAdditional,
+			       ar9280Modes_fast_clock_9280_2,
+			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
+	} else if (AR_SREV_9280_10_OR_LATER(ah)) {
+		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280,
+			       ARRAY_SIZE(ar9280Modes_9280), 6);
+		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280,
+			       ARRAY_SIZE(ar9280Common_9280), 2);
+	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
+		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
+			       ARRAY_SIZE(ar5416Modes_9160), 6);
+		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
+			       ARRAY_SIZE(ar5416Common_9160), 2);
+		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
+			       ARRAY_SIZE(ar5416Bank0_9160), 2);
+		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
+			       ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
+		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
+			       ARRAY_SIZE(ar5416Bank1_9160), 2);
+		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
+			       ARRAY_SIZE(ar5416Bank2_9160), 2);
+		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
+			       ARRAY_SIZE(ar5416Bank3_9160), 3);
+		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
+			       ARRAY_SIZE(ar5416Bank6_9160), 3);
+		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
+			       ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
+		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
+			       ARRAY_SIZE(ar5416Bank7_9160), 2);
+		if (AR_SREV_9160_11(ah)) {
+			INIT_INI_ARRAY(&ah->iniAddac,
+				       ar5416Addac_91601_1,
+				       ARRAY_SIZE(ar5416Addac_91601_1), 2);
+		} else {
+			INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
+				       ARRAY_SIZE(ar5416Addac_9160), 2);
+		}
+	} else if (AR_SREV_9100_OR_LATER(ah)) {
+		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
+			       ARRAY_SIZE(ar5416Modes_9100), 6);
+		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
+			       ARRAY_SIZE(ar5416Common_9100), 2);
+		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
+			       ARRAY_SIZE(ar5416Bank0_9100), 2);
+		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
+			       ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
+		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
+			       ARRAY_SIZE(ar5416Bank1_9100), 2);
+		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
+			       ARRAY_SIZE(ar5416Bank2_9100), 2);
+		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
+			       ARRAY_SIZE(ar5416Bank3_9100), 3);
+		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
+			       ARRAY_SIZE(ar5416Bank6_9100), 3);
+		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
+			       ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
+		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
+			       ARRAY_SIZE(ar5416Bank7_9100), 2);
+		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
+			       ARRAY_SIZE(ar5416Addac_9100), 2);
+	} else {
+		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
+			       ARRAY_SIZE(ar5416Modes), 6);
+		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
+			       ARRAY_SIZE(ar5416Common), 2);
+		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
+			       ARRAY_SIZE(ar5416Bank0), 2);
+		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
+			       ARRAY_SIZE(ar5416BB_RfGain), 3);
+		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
+			       ARRAY_SIZE(ar5416Bank1), 2);
+		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
+			       ARRAY_SIZE(ar5416Bank2), 2);
+		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
+			       ARRAY_SIZE(ar5416Bank3), 3);
+		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
+			       ARRAY_SIZE(ar5416Bank6), 3);
+		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
+			       ARRAY_SIZE(ar5416Bank6TPC), 3);
+		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
+			       ARRAY_SIZE(ar5416Bank7), 2);
+		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
+			       ARRAY_SIZE(ar5416Addac), 2);
+	}
+
+	if (ah->is_pciexpress)
+		ath9k_hw_configpcipowersave(ah, 0);
+	else
+		ath9k_hw_disablepcie(ah);
+
+	ecode = ath9k_hw_post_attach(ah);
+	if (ecode != 0)
+		goto bad;
+
+	if (AR_SREV_9285_12_OR_LATER(ah)) {
+		u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
+
+		/* txgain table */
+		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+			ar9285Modes_high_power_tx_gain_9285_1_2,
+			ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6);
+		} else {
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+			ar9285Modes_original_tx_gain_9285_1_2,
+			ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6);
+		}
+
+	}
+
+	/* rxgain table */
+	if (AR_SREV_9280_20(ah))
+		ath9k_hw_init_rxgain_ini(ah);
+
+	/* txgain table */
+	if (AR_SREV_9280_20(ah))
+		ath9k_hw_init_txgain_ini(ah);
+
+	ath9k_hw_fill_cap_info(ah);
+
+	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
+	    test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
+
+		/* EEPROM Fixup */
+		for (i = 0; i < ah->iniModes.ia_rows; i++) {
+			u32 reg = INI_RA(&ah->iniModes, i, 0);
+
+			for (j = 1; j < ah->iniModes.ia_columns; j++) {
+				u32 val = INI_RA(&ah->iniModes, i, j);
+
+				INI_RA(&ah->iniModes, i, j) =
+					ath9k_hw_ini_fixup(ah,
+							   &ah->eeprom.def,
+							   reg, val);
+			}
+		}
+	}
+
+	ecode = ath9k_hw_init_macaddr(ah);
+	if (ecode != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Failed to initialize MAC address\n");
+		goto bad;
+	}
+
+	if (AR_SREV_9285(ah))
+		ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
+	else
+		ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
+
+	ath9k_init_nfcal_hist_buffer(ah);
+
+	return ah;
+bad:
+	if (ah)
+		ath9k_hw_detach(ah);
+	if (status)
+		*status = ecode;
+
+	return NULL;
+}
+
+static void ath9k_hw_init_bb(struct ath_hw *ah,
+			     struct ath9k_channel *chan)
+{
+	u32 synthDelay;
+
+	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+	if (IS_CHAN_B(chan))
+		synthDelay = (4 * synthDelay) / 22;
+	else
+		synthDelay /= 10;
+
+	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+	udelay(synthDelay + BASE_ACTIVATE_DELAY);
+}
+
+static void ath9k_hw_init_qos(struct ath_hw *ah)
+{
+	REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
+	REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
+
+	REG_WRITE(ah, AR_QOS_NO_ACK,
+		  SM(2, AR_QOS_NO_ACK_TWO_BIT) |
+		  SM(5, AR_QOS_NO_ACK_BIT_OFF) |
+		  SM(0, AR_QOS_NO_ACK_BYTE_OFF));
+
+	REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
+	REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
+	REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
+	REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
+	REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
+}
+
+static void ath9k_hw_init_pll(struct ath_hw *ah,
+			      struct ath9k_channel *chan)
+{
+	u32 pll;
+
+	if (AR_SREV_9100(ah)) {
+		if (chan && IS_CHAN_5GHZ(chan))
+			pll = 0x1450;
+		else
+			pll = 0x1458;
+	} else {
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+			if (chan && IS_CHAN_HALF_RATE(chan))
+				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+			else if (chan && IS_CHAN_QUARTER_RATE(chan))
+				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+			if (chan && IS_CHAN_5GHZ(chan)) {
+				pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
+
+
+				if (AR_SREV_9280_20(ah)) {
+					if (((chan->channel % 20) == 0)
+					    || ((chan->channel % 10) == 0))
+						pll = 0x2850;
+					else
+						pll = 0x142c;
+				}
+			} else {
+				pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
+			}
+
+		} else if (AR_SREV_9160_10_OR_LATER(ah)) {
+
+			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
+
+			if (chan && IS_CHAN_HALF_RATE(chan))
+				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+			else if (chan && IS_CHAN_QUARTER_RATE(chan))
+				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
+
+			if (chan && IS_CHAN_5GHZ(chan))
+				pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
+			else
+				pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
+		} else {
+			pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+
+			if (chan && IS_CHAN_HALF_RATE(chan))
+				pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+			else if (chan && IS_CHAN_QUARTER_RATE(chan))
+				pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
+
+			if (chan && IS_CHAN_5GHZ(chan))
+				pll |= SM(0xa, AR_RTC_PLL_DIV);
+			else
+				pll |= SM(0xb, AR_RTC_PLL_DIV);
+		}
+	}
+	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+
+	udelay(RTC_PLL_SETTLE_DELAY);
+
+	REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+}
+
+static void ath9k_hw_init_chain_masks(struct ath_hw *ah)
+{
+	int rx_chainmask, tx_chainmask;
+
+	rx_chainmask = ah->rxchainmask;
+	tx_chainmask = ah->txchainmask;
+
+	switch (rx_chainmask) {
+	case 0x5:
+		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+			    AR_PHY_SWAP_ALT_CHAIN);
+	case 0x3:
+		if (((ah)->hw_version.macVersion <= AR_SREV_VERSION_9160)) {
+			REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
+			REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
+			break;
+		}
+	case 0x1:
+	case 0x2:
+	case 0x7:
+		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+		break;
+	default:
+		break;
+	}
+
+	REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
+	if (tx_chainmask == 0x5) {
+		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+			    AR_PHY_SWAP_ALT_CHAIN);
+	}
+	if (AR_SREV_9100(ah))
+		REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
+			  REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
+}
+
+static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
+					  enum nl80211_iftype opmode)
+{
+	ah->mask_reg = AR_IMR_TXERR |
+		AR_IMR_TXURN |
+		AR_IMR_RXERR |
+		AR_IMR_RXORN |
+		AR_IMR_BCNMISC;
+
+	if (ah->config.intr_mitigation)
+		ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+	else
+		ah->mask_reg |= AR_IMR_RXOK;
+
+	ah->mask_reg |= AR_IMR_TXOK;
+
+	if (opmode == NL80211_IFTYPE_AP)
+		ah->mask_reg |= AR_IMR_MIB;
+
+	REG_WRITE(ah, AR_IMR, ah->mask_reg);
+	REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
+
+	if (!AR_SREV_9100(ah)) {
+		REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
+		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+		REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
+	}
+}
+
+static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
+{
+	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us);
+		ah->acktimeout = (u32) -1;
+		return false;
+	} else {
+		REG_RMW_FIELD(ah, AR_TIME_OUT,
+			      AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
+		ah->acktimeout = us;
+		return true;
+	}
+}
+
+static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
+{
+	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us);
+		ah->ctstimeout = (u32) -1;
+		return false;
+	} else {
+		REG_RMW_FIELD(ah, AR_TIME_OUT,
+			      AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
+		ah->ctstimeout = us;
+		return true;
+	}
+}
+
+static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
+{
+	if (tu > 0xFFFF) {
+		DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
+			"bad global tx timeout %u\n", tu);
+		ah->globaltxtimeout = (u32) -1;
+		return false;
+	} else {
+		REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+		ah->globaltxtimeout = tu;
+		return true;
+	}
+}
+
+static void ath9k_hw_init_user_settings(struct ath_hw *ah)
+{
+	DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
+		ah->misc_mode);
+
+	if (ah->misc_mode != 0)
+		REG_WRITE(ah, AR_PCU_MISC,
+			  REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
+	if (ah->slottime != (u32) -1)
+		ath9k_hw_setslottime(ah, ah->slottime);
+	if (ah->acktimeout != (u32) -1)
+		ath9k_hw_set_ack_timeout(ah, ah->acktimeout);
+	if (ah->ctstimeout != (u32) -1)
+		ath9k_hw_set_cts_timeout(ah, ah->ctstimeout);
+	if (ah->globaltxtimeout != (u32) -1)
+		ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
+}
+
+const char *ath9k_hw_probe(u16 vendorid, u16 devid)
+{
+	return vendorid == ATHEROS_VENDOR_ID ?
+		ath9k_hw_devname(devid) : NULL;
+}
+
+void ath9k_hw_detach(struct ath_hw *ah)
+{
+	if (!AR_SREV_9100(ah))
+		ath9k_hw_ani_detach(ah);
+
+	ath9k_hw_rfdetach(ah);
+	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+	kfree(ah);
+}
+
+struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
+{
+	struct ath_hw *ah = NULL;
+
+	switch (devid) {
+	case AR5416_DEVID_PCI:
+	case AR5416_DEVID_PCIE:
+	case AR5416_AR9100_DEVID:
+	case AR9160_DEVID_PCI:
+	case AR9280_DEVID_PCI:
+	case AR9280_DEVID_PCIE:
+	case AR9285_DEVID_PCIE:
+		ah = ath9k_hw_do_attach(devid, sc, error);
+		break;
+	default:
+		*error = -ENXIO;
+		break;
+	}
+
+	return ah;
+}
+
+/*******/
+/* INI */
+/*******/
+
+static void ath9k_hw_override_ini(struct ath_hw *ah,
+				  struct ath9k_channel *chan)
+{
+	/*
+	 * Set the RX_ABORT and RX_DIS and clear if off only after
+	 * RXE is set for MAC. This prevents frames with corrupted
+	 * descriptor status.
+	 */
+	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+
+	if (!AR_SREV_5416_20_OR_LATER(ah) ||
+	    AR_SREV_9280_10_OR_LATER(ah))
+		return;
+
+	REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+}
+
+static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
+			      struct ar5416_eeprom_def *pEepData,
+			      u32 reg, u32 value)
+{
+	struct base_eep_header *pBase = &(pEepData->baseEepHeader);
+
+	switch (ah->hw_version.devid) {
+	case AR9280_DEVID_PCI:
+		if (reg == 0x7894) {
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+				"ini VAL: %x  EEPROM: %x\n", value,
+				(pBase->version & 0xff));
+
+			if ((pBase->version & 0xff) > 0x0a) {
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"PWDCLKIND: %d\n",
+					pBase->pwdclkind);
+				value &= ~AR_AN_TOP2_PWDCLKIND;
+				value |= AR_AN_TOP2_PWDCLKIND &
+					(pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
+			} else {
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+					"PWDCLKIND Earlier Rev\n");
+			}
+
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+				"final ini VAL: %x\n", value);
+		}
+		break;
+	}
+
+	return value;
+}
+
+static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
+			      struct ar5416_eeprom_def *pEepData,
+			      u32 reg, u32 value)
+{
+	if (ah->eep_map == EEP_MAP_4KBITS)
+		return value;
+	else
+		return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
+}
+
+static void ath9k_olc_init(struct ath_hw *ah)
+{
+	u32 i;
+
+	for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
+		ah->originalGain[i] =
+			MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
+					AR_PHY_TX_GAIN);
+	ah->PDADCdelta = 0;
+}
+
+static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
+			      struct ath9k_channel *chan)
+{
+	u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
+
+	if (IS_CHAN_B(chan))
+		ctl |= CTL_11B;
+	else if (IS_CHAN_G(chan))
+		ctl |= CTL_11G;
+	else
+		ctl |= CTL_11A;
+
+	return ctl;
+}
+
+static int ath9k_hw_process_ini(struct ath_hw *ah,
+				struct ath9k_channel *chan,
+				enum ath9k_ht_macmode macmode)
+{
+	int i, regWrites = 0;
+	struct ieee80211_channel *channel = chan->chan;
+	u32 modesIndex, freqIndex;
+
+	switch (chan->chanmode) {
+	case CHANNEL_A:
+	case CHANNEL_A_HT20:
+		modesIndex = 1;
+		freqIndex = 1;
+		break;
+	case CHANNEL_A_HT40PLUS:
+	case CHANNEL_A_HT40MINUS:
+		modesIndex = 2;
+		freqIndex = 1;
+		break;
+	case CHANNEL_G:
+	case CHANNEL_G_HT20:
+	case CHANNEL_B:
+		modesIndex = 4;
+		freqIndex = 2;
+		break;
+	case CHANNEL_G_HT40PLUS:
+	case CHANNEL_G_HT40MINUS:
+		modesIndex = 3;
+		freqIndex = 2;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	REG_WRITE(ah, AR_PHY(0), 0x00000007);
+	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+	ah->eep_ops->set_addac(ah, chan);
+
+	if (AR_SREV_5416_22_OR_LATER(ah)) {
+		REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
+	} else {
+		struct ar5416IniArray temp;
+		u32 addacSize =
+			sizeof(u32) * ah->iniAddac.ia_rows *
+			ah->iniAddac.ia_columns;
+
+		memcpy(ah->addac5416_21,
+		       ah->iniAddac.ia_array, addacSize);
+
+		(ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
+
+		temp.ia_array = ah->addac5416_21;
+		temp.ia_columns = ah->iniAddac.ia_columns;
+		temp.ia_rows = ah->iniAddac.ia_rows;
+		REG_WRITE_ARRAY(&temp, 1, regWrites);
+	}
+
+	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+	for (i = 0; i < ah->iniModes.ia_rows; i++) {
+		u32 reg = INI_RA(&ah->iniModes, i, 0);
+		u32 val = INI_RA(&ah->iniModes, i, modesIndex);
+
+		REG_WRITE(ah, reg, val);
+
+		if (reg >= 0x7800 && reg < 0x78a0
+		    && ah->config.analog_shiftreg) {
+			udelay(100);
+		}
+
+		DO_DELAY(regWrites);
+	}
+
+	if (AR_SREV_9280(ah))
+		REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
+
+	if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah))
+		REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+	for (i = 0; i < ah->iniCommon.ia_rows; i++) {
+		u32 reg = INI_RA(&ah->iniCommon, i, 0);
+		u32 val = INI_RA(&ah->iniCommon, i, 1);
+
+		REG_WRITE(ah, reg, val);
+
+		if (reg >= 0x7800 && reg < 0x78a0
+		    && ah->config.analog_shiftreg) {
+			udelay(100);
+		}
+
+		DO_DELAY(regWrites);
+	}
+
+	ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
+
+	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
+		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
+				regWrites);
+	}
+
+	ath9k_hw_override_ini(ah, chan);
+	ath9k_hw_set_regs(ah, chan, macmode);
+	ath9k_hw_init_chain_masks(ah);
+
+	if (OLC_FOR_AR9280_20_LATER)
+		ath9k_olc_init(ah);
+
+	ah->eep_ops->set_txpower(ah, chan,
+				 ath9k_regd_get_ctl(&ah->regulatory, chan),
+				 channel->max_antenna_gain * 2,
+				 channel->max_power * 2,
+				 min((u32) MAX_RATE_POWER,
+				 (u32) ah->regulatory.power_limit));
+
+	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"ar5416SetRfRegs failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/****************************************/
+/* Reset and Channel Switching Routines */
+/****************************************/
+
+static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	u32 rfMode = 0;
+
+	if (chan == NULL)
+		return;
+
+	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+
+	if (!AR_SREV_9280_10_OR_LATER(ah))
+		rfMode |= (IS_CHAN_5GHZ(chan)) ?
+			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
+
+	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
+		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+
+	REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
+
+static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
+{
+	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
+
+static inline void ath9k_hw_set_dma(struct ath_hw *ah)
+{
+	u32 regval;
+
+	regval = REG_READ(ah, AR_AHB_MODE);
+	REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+
+	regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
+	REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
+
+	REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+
+	regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
+	REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
+
+	REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
+
+	if (AR_SREV_9285(ah)) {
+		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+			  AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
+	} else {
+		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+			  AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+	}
+}
+
+static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
+{
+	u32 val;
+
+	val = REG_READ(ah, AR_STA_ID1);
+	val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
+	switch (opmode) {
+	case NL80211_IFTYPE_AP:
+		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
+			  | AR_STA_ID1_KSRCH_MODE);
+		REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
+			  | AR_STA_ID1_KSRCH_MODE);
+		REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+		break;
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_MONITOR:
+		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+		break;
+	}
+}
+
+static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah,
+						 u32 coef_scaled,
+						 u32 *coef_mantissa,
+						 u32 *coef_exponent)
+{
+	u32 coef_exp, coef_man;
+
+	for (coef_exp = 31; coef_exp > 0; coef_exp--)
+		if ((coef_scaled >> coef_exp) & 0x1)
+			break;
+
+	coef_exp = 14 - (coef_exp - COEF_SCALE_S);
+
+	coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
+
+	*coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
+	*coef_exponent = coef_exp - 16;
+}
+
+static void ath9k_hw_set_delta_slope(struct ath_hw *ah,
+				     struct ath9k_channel *chan)
+{
+	u32 coef_scaled, ds_coef_exp, ds_coef_man;
+	u32 clockMhzScaled = 0x64000000;
+	struct chan_centers centers;
+
+	if (IS_CHAN_HALF_RATE(chan))
+		clockMhzScaled = clockMhzScaled >> 1;
+	else if (IS_CHAN_QUARTER_RATE(chan))
+		clockMhzScaled = clockMhzScaled >> 2;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	coef_scaled = clockMhzScaled / centers.synth_center;
+
+	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+				      &ds_coef_exp);
+
+	REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+		      AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
+	REG_RMW_FIELD(ah, AR_PHY_TIMING3,
+		      AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
+
+	coef_scaled = (9 * coef_scaled) / 10;
+
+	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
+				      &ds_coef_exp);
+
+	REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+		      AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
+	REG_RMW_FIELD(ah, AR_PHY_HALFGI,
+		      AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
+}
+
+static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
+{
+	u32 rst_flags;
+	u32 tmpReg;
+
+	if (AR_SREV_9100(ah)) {
+		u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK);
+		val &= ~AR_RTC_DERIVED_CLK_PERIOD;
+		val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD);
+		REG_WRITE(ah, AR_RTC_DERIVED_CLK, val);
+		(void)REG_READ(ah, AR_RTC_DERIVED_CLK);
+	}
+
+	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+		  AR_RTC_FORCE_WAKE_ON_INT);
+
+	if (AR_SREV_9100(ah)) {
+		rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
+			AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
+	} else {
+		tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+		if (tmpReg &
+		    (AR_INTR_SYNC_LOCAL_TIMEOUT |
+		     AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+		} else {
+			REG_WRITE(ah, AR_RC, AR_RC_AHB);
+		}
+
+		rst_flags = AR_RTC_RC_MAC_WARM;
+		if (type == ATH9K_RESET_COLD)
+			rst_flags |= AR_RTC_RC_MAC_COLD;
+	}
+
+	REG_WRITE(ah, AR_RTC_RC, rst_flags);
+	udelay(50);
+
+	REG_WRITE(ah, AR_RTC_RC, 0);
+	if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+			"RTC stuck in MAC reset\n");
+		return false;
+	}
+
+	if (!AR_SREV_9100(ah))
+		REG_WRITE(ah, AR_RC, 0);
+
+	ath9k_hw_init_pll(ah, NULL);
+
+	if (AR_SREV_9100(ah))
+		udelay(50);
+
+	return true;
+}
+
+static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
+{
+	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+		  AR_RTC_FORCE_WAKE_ON_INT);
+
+	REG_WRITE(ah, AR_RTC_RESET, 0);
+	udelay(2);
+	REG_WRITE(ah, AR_RTC_RESET, 1);
+
+	if (!ath9k_hw_wait(ah,
+			   AR_RTC_STATUS,
+			   AR_RTC_STATUS_M,
+			   AR_RTC_STATUS_ON,
+			   AH_WAIT_TIMEOUT)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n");
+		return false;
+	}
+
+	ath9k_hw_read_revisions(ah);
+
+	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
+}
+
+static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
+{
+	REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+		  AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+	switch (type) {
+	case ATH9K_RESET_POWER_ON:
+		return ath9k_hw_set_reset_power_on(ah);
+	case ATH9K_RESET_WARM:
+	case ATH9K_RESET_COLD:
+		return ath9k_hw_set_reset(ah, type);
+	default:
+		return false;
+	}
+}
+
+static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
+			      enum ath9k_ht_macmode macmode)
+{
+	u32 phymode;
+	u32 enableDacFifo = 0;
+
+	if (AR_SREV_9285_10_OR_LATER(ah))
+		enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
+					 AR_PHY_FC_ENABLE_DAC_FIFO);
+
+	phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
+		| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
+
+	if (IS_CHAN_HT40(chan)) {
+		phymode |= AR_PHY_FC_DYN2040_EN;
+
+		if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+		    (chan->chanmode == CHANNEL_G_HT40PLUS))
+			phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+
+		if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
+			phymode |= AR_PHY_FC_DYN2040_EXT_CH;
+	}
+	REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+	ath9k_hw_set11nmac2040(ah, macmode);
+
+	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+static bool ath9k_hw_chip_reset(struct ath_hw *ah,
+				struct ath9k_channel *chan)
+{
+	if (OLC_FOR_AR9280_20_LATER) {
+		if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
+			return false;
+	} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+		return false;
+
+	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+		return false;
+
+	ah->chip_fullsleep = false;
+	ath9k_hw_init_pll(ah, chan);
+	ath9k_hw_set_rfmode(ah, chan);
+
+	return true;
+}
+
+static bool ath9k_hw_channel_change(struct ath_hw *ah,
+				    struct ath9k_channel *chan,
+				    enum ath9k_ht_macmode macmode)
+{
+	struct ieee80211_channel *channel = chan->chan;
+	u32 synthDelay, qnum;
+
+	for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
+		if (ath9k_hw_numtxpending(ah, qnum)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+				"Transmit frames pending on queue %d\n", qnum);
+			return false;
+		}
+	}
+
+	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+	if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+			   AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Could not kill baseband RX\n");
+		return false;
+	}
+
+	ath9k_hw_set_regs(ah, chan, macmode);
+
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		ath9k_hw_ar9280_set_channel(ah, chan);
+	} else {
+		if (!(ath9k_hw_set_channel(ah, chan))) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Failed to set channel\n");
+			return false;
+		}
+	}
+
+	ah->eep_ops->set_txpower(ah, chan,
+			     ath9k_regd_get_ctl(&ah->regulatory, chan),
+			     channel->max_antenna_gain * 2,
+			     channel->max_power * 2,
+			     min((u32) MAX_RATE_POWER,
+			     (u32) ah->regulatory.power_limit));
+
+	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+	if (IS_CHAN_B(chan))
+		synthDelay = (4 * synthDelay) / 22;
+	else
+		synthDelay /= 10;
+
+	udelay(synthDelay + BASE_ACTIVATE_DELAY);
+
+	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+
+	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+		ath9k_hw_set_delta_slope(ah, chan);
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ath9k_hw_9280_spur_mitigate(ah, chan);
+	else
+		ath9k_hw_spur_mitigate(ah, chan);
+
+	if (!chan->oneTimeCalsDone)
+		chan->oneTimeCalsDone = true;
+
+	return true;
+}
+
+static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	int bb_spur = AR_NO_SPUR;
+	int freq;
+	int bin, cur_bin;
+	int bb_spur_off, spur_subchannel_sd;
+	int spur_freq_sd;
+	int spur_delta_phase;
+	int denominator;
+	int upper, lower, cur_vit_mask;
+	int tmp, newVal;
+	int i;
+	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+	};
+	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+	};
+	int inc[4] = { 0, 100, 0, 0 };
+	struct chan_centers centers;
+
+	int8_t mask_m[123];
+	int8_t mask_p[123];
+	int8_t mask_amt;
+	int tmp_mask;
+	int cur_bb_spur;
+	bool is2GHz = IS_CHAN_2GHZ(chan);
+
+	memset(&mask_m, 0, sizeof(int8_t) * 123);
+	memset(&mask_p, 0, sizeof(int8_t) * 123);
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	freq = centers.synth_center;
+
+	ah->config.spurmode = SPUR_ENABLE_EEPROM;
+	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+
+		if (is2GHz)
+			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
+		else
+			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
+
+		if (AR_NO_SPUR == cur_bb_spur)
+			break;
+		cur_bb_spur = cur_bb_spur - freq;
+
+		if (IS_CHAN_HT40(chan)) {
+			if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
+			    (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
+				bb_spur = cur_bb_spur;
+				break;
+			}
+		} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
+			   (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
+			bb_spur = cur_bb_spur;
+			break;
+		}
+	}
+
+	if (AR_NO_SPUR == bb_spur) {
+		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+		return;
+	} else {
+		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
+			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+	}
+
+	bin = bb_spur * 320;
+
+	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+
+	newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+			AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+			AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+			AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
+
+	newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+		  AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+		  AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+		  AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+		  SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+	REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
+
+	if (IS_CHAN_HT40(chan)) {
+		if (bb_spur < 0) {
+			spur_subchannel_sd = 1;
+			bb_spur_off = bb_spur + 10;
+		} else {
+			spur_subchannel_sd = 0;
+			bb_spur_off = bb_spur - 10;
+		}
+	} else {
+		spur_subchannel_sd = 0;
+		bb_spur_off = bb_spur;
+	}
+
+	if (IS_CHAN_HT40(chan))
+		spur_delta_phase =
+			((bb_spur * 262144) /
+			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+	else
+		spur_delta_phase =
+			((bb_spur * 524288) /
+			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+	denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
+	spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
+
+	newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+		  SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+		  SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+	REG_WRITE(ah, AR_PHY_TIMING11, newVal);
+
+	newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
+	REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
+
+	cur_bin = -6000;
+	upper = bin + 100;
+	lower = bin - 100;
+
+	for (i = 0; i < 4; i++) {
+		int pilot_mask = 0;
+		int chan_mask = 0;
+		int bp = 0;
+		for (bp = 0; bp < 30; bp++) {
+			if ((cur_bin > lower) && (cur_bin < upper)) {
+				pilot_mask = pilot_mask | 0x1 << bp;
+				chan_mask = chan_mask | 0x1 << bp;
+			}
+			cur_bin += 100;
+		}
+		cur_bin += inc[i];
+		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+		REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+	}
+
+	cur_vit_mask = 6100;
+	upper = bin + 120;
+	lower = bin - 120;
+
+	for (i = 0; i < 123; i++) {
+		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+			/* workaround for gcc bug #37014 */
+			volatile int tmp_v = abs(cur_vit_mask - bin);
+
+			if (tmp_v < 75)
+				mask_amt = 1;
+			else
+				mask_amt = 0;
+			if (cur_vit_mask < 0)
+				mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+			else
+				mask_p[cur_vit_mask / 100] = mask_amt;
+		}
+		cur_vit_mask -= 100;
+	}
+
+	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+		| (mask_m[48] << 26) | (mask_m[49] << 24)
+		| (mask_m[50] << 22) | (mask_m[51] << 20)
+		| (mask_m[52] << 18) | (mask_m[53] << 16)
+		| (mask_m[54] << 14) | (mask_m[55] << 12)
+		| (mask_m[56] << 10) | (mask_m[57] << 8)
+		| (mask_m[58] << 6) | (mask_m[59] << 4)
+		| (mask_m[60] << 2) | (mask_m[61] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+	tmp_mask = (mask_m[31] << 28)
+		| (mask_m[32] << 26) | (mask_m[33] << 24)
+		| (mask_m[34] << 22) | (mask_m[35] << 20)
+		| (mask_m[36] << 18) | (mask_m[37] << 16)
+		| (mask_m[48] << 14) | (mask_m[39] << 12)
+		| (mask_m[40] << 10) | (mask_m[41] << 8)
+		| (mask_m[42] << 6) | (mask_m[43] << 4)
+		| (mask_m[44] << 2) | (mask_m[45] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+		| (mask_m[18] << 26) | (mask_m[18] << 24)
+		| (mask_m[20] << 22) | (mask_m[20] << 20)
+		| (mask_m[22] << 18) | (mask_m[22] << 16)
+		| (mask_m[24] << 14) | (mask_m[24] << 12)
+		| (mask_m[25] << 10) | (mask_m[26] << 8)
+		| (mask_m[27] << 6) | (mask_m[28] << 4)
+		| (mask_m[29] << 2) | (mask_m[30] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
+		| (mask_m[2] << 26) | (mask_m[3] << 24)
+		| (mask_m[4] << 22) | (mask_m[5] << 20)
+		| (mask_m[6] << 18) | (mask_m[7] << 16)
+		| (mask_m[8] << 14) | (mask_m[9] << 12)
+		| (mask_m[10] << 10) | (mask_m[11] << 8)
+		| (mask_m[12] << 6) | (mask_m[13] << 4)
+		| (mask_m[14] << 2) | (mask_m[15] << 0);
+	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+	tmp_mask = (mask_p[15] << 28)
+		| (mask_p[14] << 26) | (mask_p[13] << 24)
+		| (mask_p[12] << 22) | (mask_p[11] << 20)
+		| (mask_p[10] << 18) | (mask_p[9] << 16)
+		| (mask_p[8] << 14) | (mask_p[7] << 12)
+		| (mask_p[6] << 10) | (mask_p[5] << 8)
+		| (mask_p[4] << 6) | (mask_p[3] << 4)
+		| (mask_p[2] << 2) | (mask_p[1] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+	tmp_mask = (mask_p[30] << 28)
+		| (mask_p[29] << 26) | (mask_p[28] << 24)
+		| (mask_p[27] << 22) | (mask_p[26] << 20)
+		| (mask_p[25] << 18) | (mask_p[24] << 16)
+		| (mask_p[23] << 14) | (mask_p[22] << 12)
+		| (mask_p[21] << 10) | (mask_p[20] << 8)
+		| (mask_p[19] << 6) | (mask_p[18] << 4)
+		| (mask_p[17] << 2) | (mask_p[16] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+	tmp_mask = (mask_p[45] << 28)
+		| (mask_p[44] << 26) | (mask_p[43] << 24)
+		| (mask_p[42] << 22) | (mask_p[41] << 20)
+		| (mask_p[40] << 18) | (mask_p[39] << 16)
+		| (mask_p[38] << 14) | (mask_p[37] << 12)
+		| (mask_p[36] << 10) | (mask_p[35] << 8)
+		| (mask_p[34] << 6) | (mask_p[33] << 4)
+		| (mask_p[32] << 2) | (mask_p[31] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+		| (mask_p[59] << 26) | (mask_p[58] << 24)
+		| (mask_p[57] << 22) | (mask_p[56] << 20)
+		| (mask_p[55] << 18) | (mask_p[54] << 16)
+		| (mask_p[53] << 14) | (mask_p[52] << 12)
+		| (mask_p[51] << 10) | (mask_p[50] << 8)
+		| (mask_p[49] << 6) | (mask_p[48] << 4)
+		| (mask_p[47] << 2) | (mask_p[46] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	int bb_spur = AR_NO_SPUR;
+	int bin, cur_bin;
+	int spur_freq_sd;
+	int spur_delta_phase;
+	int denominator;
+	int upper, lower, cur_vit_mask;
+	int tmp, new;
+	int i;
+	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+	};
+	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+	};
+	int inc[4] = { 0, 100, 0, 0 };
+
+	int8_t mask_m[123];
+	int8_t mask_p[123];
+	int8_t mask_amt;
+	int tmp_mask;
+	int cur_bb_spur;
+	bool is2GHz = IS_CHAN_2GHZ(chan);
+
+	memset(&mask_m, 0, sizeof(int8_t) * 123);
+	memset(&mask_p, 0, sizeof(int8_t) * 123);
+
+	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+		if (AR_NO_SPUR == cur_bb_spur)
+			break;
+		cur_bb_spur = cur_bb_spur - (chan->channel * 10);
+		if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+			bb_spur = cur_bb_spur;
+			break;
+		}
+	}
+
+	if (AR_NO_SPUR == bb_spur)
+		return;
+
+	bin = bb_spur * 32;
+
+	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
+	new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+		     AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+		     AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+		     AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
+
+	new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+	       AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+	       AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+	       AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+	       SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+	REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+
+	spur_delta_phase = ((bb_spur * 524288) / 100) &
+		AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+	denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
+	spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+	new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+	       SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+	       SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+	REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+	cur_bin = -6000;
+	upper = bin + 100;
+	lower = bin - 100;
+
+	for (i = 0; i < 4; i++) {
+		int pilot_mask = 0;
+		int chan_mask = 0;
+		int bp = 0;
+		for (bp = 0; bp < 30; bp++) {
+			if ((cur_bin > lower) && (cur_bin < upper)) {
+				pilot_mask = pilot_mask | 0x1 << bp;
+				chan_mask = chan_mask | 0x1 << bp;
+			}
+			cur_bin += 100;
+		}
+		cur_bin += inc[i];
+		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+		REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+	}
+
+	cur_vit_mask = 6100;
+	upper = bin + 120;
+	lower = bin - 120;
+
+	for (i = 0; i < 123; i++) {
+		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+
+			/* workaround for gcc bug #37014 */
+			volatile int tmp_v = abs(cur_vit_mask - bin);
+
+			if (tmp_v < 75)
+				mask_amt = 1;
+			else
+				mask_amt = 0;
+			if (cur_vit_mask < 0)
+				mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+			else
+				mask_p[cur_vit_mask / 100] = mask_amt;
+		}
+		cur_vit_mask -= 100;
+	}
+
+	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+		| (mask_m[48] << 26) | (mask_m[49] << 24)
+		| (mask_m[50] << 22) | (mask_m[51] << 20)
+		| (mask_m[52] << 18) | (mask_m[53] << 16)
+		| (mask_m[54] << 14) | (mask_m[55] << 12)
+		| (mask_m[56] << 10) | (mask_m[57] << 8)
+		| (mask_m[58] << 6) | (mask_m[59] << 4)
+		| (mask_m[60] << 2) | (mask_m[61] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+	tmp_mask = (mask_m[31] << 28)
+		| (mask_m[32] << 26) | (mask_m[33] << 24)
+		| (mask_m[34] << 22) | (mask_m[35] << 20)
+		| (mask_m[36] << 18) | (mask_m[37] << 16)
+		| (mask_m[48] << 14) | (mask_m[39] << 12)
+		| (mask_m[40] << 10) | (mask_m[41] << 8)
+		| (mask_m[42] << 6) | (mask_m[43] << 4)
+		| (mask_m[44] << 2) | (mask_m[45] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+		| (mask_m[18] << 26) | (mask_m[18] << 24)
+		| (mask_m[20] << 22) | (mask_m[20] << 20)
+		| (mask_m[22] << 18) | (mask_m[22] << 16)
+		| (mask_m[24] << 14) | (mask_m[24] << 12)
+		| (mask_m[25] << 10) | (mask_m[26] << 8)
+		| (mask_m[27] << 6) | (mask_m[28] << 4)
+		| (mask_m[29] << 2) | (mask_m[30] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
+		| (mask_m[2] << 26) | (mask_m[3] << 24)
+		| (mask_m[4] << 22) | (mask_m[5] << 20)
+		| (mask_m[6] << 18) | (mask_m[7] << 16)
+		| (mask_m[8] << 14) | (mask_m[9] << 12)
+		| (mask_m[10] << 10) | (mask_m[11] << 8)
+		| (mask_m[12] << 6) | (mask_m[13] << 4)
+		| (mask_m[14] << 2) | (mask_m[15] << 0);
+	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+	tmp_mask = (mask_p[15] << 28)
+		| (mask_p[14] << 26) | (mask_p[13] << 24)
+		| (mask_p[12] << 22) | (mask_p[11] << 20)
+		| (mask_p[10] << 18) | (mask_p[9] << 16)
+		| (mask_p[8] << 14) | (mask_p[7] << 12)
+		| (mask_p[6] << 10) | (mask_p[5] << 8)
+		| (mask_p[4] << 6) | (mask_p[3] << 4)
+		| (mask_p[2] << 2) | (mask_p[1] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+	tmp_mask = (mask_p[30] << 28)
+		| (mask_p[29] << 26) | (mask_p[28] << 24)
+		| (mask_p[27] << 22) | (mask_p[26] << 20)
+		| (mask_p[25] << 18) | (mask_p[24] << 16)
+		| (mask_p[23] << 14) | (mask_p[22] << 12)
+		| (mask_p[21] << 10) | (mask_p[20] << 8)
+		| (mask_p[19] << 6) | (mask_p[18] << 4)
+		| (mask_p[17] << 2) | (mask_p[16] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+	tmp_mask = (mask_p[45] << 28)
+		| (mask_p[44] << 26) | (mask_p[43] << 24)
+		| (mask_p[42] << 22) | (mask_p[41] << 20)
+		| (mask_p[40] << 18) | (mask_p[39] << 16)
+		| (mask_p[38] << 14) | (mask_p[37] << 12)
+		| (mask_p[36] << 10) | (mask_p[35] << 8)
+		| (mask_p[34] << 6) | (mask_p[33] << 4)
+		| (mask_p[32] << 2) | (mask_p[31] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+		| (mask_p[59] << 26) | (mask_p[58] << 24)
+		| (mask_p[57] << 22) | (mask_p[56] << 20)
+		| (mask_p[55] << 18) | (mask_p[54] << 16)
+		| (mask_p[53] << 14) | (mask_p[52] << 12)
+		| (mask_p[51] << 10) | (mask_p[50] << 8)
+		| (mask_p[49] << 6) | (mask_p[48] << 4)
+		| (mask_p[47] << 2) | (mask_p[46] << 0);
+	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+static void ath9k_enable_rfkill(struct ath_hw *ah)
+{
+	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
+
+	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
+		    AR_GPIO_INPUT_MUX2_RFSILENT);
+
+	ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
+	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
+}
+
+int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+		    bool bChannelChange)
+{
+	u32 saveLedState;
+	struct ath_softc *sc = ah->ah_sc;
+	struct ath9k_channel *curchan = ah->curchan;
+	u32 saveDefAntenna;
+	u32 macStaId1;
+	int i, rx_chainmask, r;
+
+	ah->extprotspacing = sc->ht_extprotspacing;
+	ah->txchainmask = sc->tx_chainmask;
+	ah->rxchainmask = sc->rx_chainmask;
+
+	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+		return -EIO;
+
+	if (curchan)
+		ath9k_hw_getnf(ah, curchan);
+
+	if (bChannelChange &&
+	    (ah->chip_fullsleep != true) &&
+	    (ah->curchan != NULL) &&
+	    (chan->channel != ah->curchan->channel) &&
+	    ((chan->channelFlags & CHANNEL_ALL) ==
+	     (ah->curchan->channelFlags & CHANNEL_ALL)) &&
+	    (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
+				   !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) {
+
+		if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
+			ath9k_hw_loadnf(ah, ah->curchan);
+			ath9k_hw_start_nfcal(ah);
+			return 0;
+		}
+	}
+
+	saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
+	if (saveDefAntenna == 0)
+		saveDefAntenna = 1;
+
+	macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
+
+	saveLedState = REG_READ(ah, AR_CFG_LED) &
+		(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
+		 AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
+
+	ath9k_hw_mark_phy_inactive(ah);
+
+	if (!ath9k_hw_chip_reset(ah, chan)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n");
+		return -EINVAL;
+	}
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
+
+	r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width);
+	if (r)
+		return r;
+
+	/* Setup MFP options for CCMP */
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
+		/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
+		 * frames when constructing CCMP AAD. */
+		REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
+			      0xc7ff);
+		ah->sw_mgmt_crypto = false;
+	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
+		/* Disable hardware crypto for management frames */
+		REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
+			    AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
+		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+			    AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
+		ah->sw_mgmt_crypto = true;
+	} else
+		ah->sw_mgmt_crypto = true;
+
+	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+		ath9k_hw_set_delta_slope(ah, chan);
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ath9k_hw_9280_spur_mitigate(ah, chan);
+	else
+		ath9k_hw_spur_mitigate(ah, chan);
+
+	ah->eep_ops->set_board_values(ah, chan);
+
+	ath9k_hw_decrease_chain_power(ah, chan);
+
+	REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr));
+	REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4)
+		  | macStaId1
+		  | AR_STA_ID1_RTS_USE_DEF
+		  | (ah->config.
+		     ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
+		  | ah->sta_id1_defaults);
+	ath9k_hw_set_operating_mode(ah, ah->opmode);
+
+	REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask));
+	REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4));
+
+	REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+
+	REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid));
+	REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) |
+		  ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
+
+	REG_WRITE(ah, AR_ISR, ~0);
+
+	REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		ath9k_hw_ar9280_set_channel(ah, chan);
+	else
+		if (!(ath9k_hw_set_channel(ah, chan)))
+			return -EIO;
+
+	for (i = 0; i < AR_NUM_DCU; i++)
+		REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+	ah->intr_txqs = 0;
+	for (i = 0; i < ah->caps.total_queues; i++)
+		ath9k_hw_resettxqueue(ah, i);
+
+	ath9k_hw_init_interrupt_masks(ah, ah->opmode);
+	ath9k_hw_init_qos(ah);
+
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+		ath9k_enable_rfkill(ah);
+
+	ath9k_hw_init_user_settings(ah);
+
+	REG_WRITE(ah, AR_STA_ID1,
+		  REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
+
+	ath9k_hw_set_dma(ah);
+
+	REG_WRITE(ah, AR_OBS, 8);
+
+	if (ah->config.intr_mitigation) {
+		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
+		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
+	}
+
+	ath9k_hw_init_bb(ah, chan);
+
+	if (!ath9k_hw_init_cal(ah, chan))
+		return -EIO;;
+
+	rx_chainmask = ah->rxchainmask;
+	if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
+		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+	}
+
+	REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
+
+	if (AR_SREV_9100(ah)) {
+		u32 mask;
+		mask = REG_READ(ah, AR_CFG);
+		if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+				"CFG Byte Swap Set 0x%x\n", mask);
+		} else {
+			mask =
+				INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
+			REG_WRITE(ah, AR_CFG, mask);
+			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+				"Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
+		}
+	} else {
+#ifdef __BIG_ENDIAN
+		REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+#endif
+	}
+
+	return 0;
+}
+
+/************************/
+/* Key Cache Management */
+/************************/
+
+bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
+{
+	u32 keyType;
+
+	if (entry >= ah->caps.keycache_size) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"keychache entry %u out of range\n", entry);
+		return false;
+	}
+
+	keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+
+	REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+
+	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
+		u16 micentry = entry + 64;
+
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
+	}
+
+	if (ah->curchan == NULL)
+		return true;
+
+	return true;
+}
+
+bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
+{
+	u32 macHi, macLo;
+
+	if (entry >= ah->caps.keycache_size) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"keychache entry %u out of range\n", entry);
+		return false;
+	}
+
+	if (mac != NULL) {
+		macHi = (mac[5] << 8) | mac[4];
+		macLo = (mac[3] << 24) |
+			(mac[2] << 16) |
+			(mac[1] << 8) |
+			mac[0];
+		macLo >>= 1;
+		macLo |= (macHi & 1) << 31;
+		macHi >>= 1;
+	} else {
+		macLo = macHi = 0;
+	}
+	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
+
+	return true;
+}
+
+bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
+				 const struct ath9k_keyval *k,
+				 const u8 *mac)
+{
+	const struct ath9k_hw_capabilities *pCap = &ah->caps;
+	u32 key0, key1, key2, key3, key4;
+	u32 keyType;
+
+	if (entry >= pCap->keycache_size) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"keycache entry %u out of range\n", entry);
+		return false;
+	}
+
+	switch (k->kv_type) {
+	case ATH9K_CIPHER_AES_OCB:
+		keyType = AR_KEYTABLE_TYPE_AES;
+		break;
+	case ATH9K_CIPHER_AES_CCM:
+		if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+				"AES-CCM not supported by mac rev 0x%x\n",
+				ah->hw_version.macRev);
+			return false;
+		}
+		keyType = AR_KEYTABLE_TYPE_CCM;
+		break;
+	case ATH9K_CIPHER_TKIP:
+		keyType = AR_KEYTABLE_TYPE_TKIP;
+		if (ATH9K_IS_MIC_ENABLED(ah)
+		    && entry + 64 >= pCap->keycache_size) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+				"entry %u inappropriate for TKIP\n", entry);
+			return false;
+		}
+		break;
+	case ATH9K_CIPHER_WEP:
+		if (k->kv_len < WLAN_KEY_LEN_WEP40) {
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+				"WEP key length %u too small\n", k->kv_len);
+			return false;
+		}
+		if (k->kv_len <= WLAN_KEY_LEN_WEP40)
+			keyType = AR_KEYTABLE_TYPE_40;
+		else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
+			keyType = AR_KEYTABLE_TYPE_104;
+		else
+			keyType = AR_KEYTABLE_TYPE_128;
+		break;
+	case ATH9K_CIPHER_CLR:
+		keyType = AR_KEYTABLE_TYPE_CLR;
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"cipher %u not supported\n", k->kv_type);
+		return false;
+	}
+
+	key0 = get_unaligned_le32(k->kv_val + 0);
+	key1 = get_unaligned_le16(k->kv_val + 4);
+	key2 = get_unaligned_le32(k->kv_val + 6);
+	key3 = get_unaligned_le16(k->kv_val + 10);
+	key4 = get_unaligned_le32(k->kv_val + 12);
+	if (k->kv_len <= WLAN_KEY_LEN_WEP104)
+		key4 &= 0xff;
+
+	/*
+	 * Note: Key cache registers access special memory area that requires
+	 * two 32-bit writes to actually update the values in the internal
+	 * memory. Consequently, the exact order and pairs used here must be
+	 * maintained.
+	 */
+
+	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
+		u16 micentry = entry + 64;
+
+		/*
+		 * Write inverted key[47:0] first to avoid Michael MIC errors
+		 * on frames that could be sent or received at the same time.
+		 * The correct key will be written in the end once everything
+		 * else is ready.
+		 */
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
+
+		/* Write key[95:48] */
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+
+		/* Write key[127:96] and key type */
+		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+		/* Write MAC address for the entry */
+		(void) ath9k_hw_keysetmac(ah, entry, mac);
+
+		if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
+			/*
+			 * TKIP uses two key cache entries:
+			 * Michael MIC TX/RX keys in the same key cache entry
+			 * (idx = main index + 64):
+			 * key0 [31:0] = RX key [31:0]
+			 * key1 [15:0] = TX key [31:16]
+			 * key1 [31:16] = reserved
+			 * key2 [31:0] = RX key [63:32]
+			 * key3 [15:0] = TX key [15:0]
+			 * key3 [31:16] = reserved
+			 * key4 [31:0] = TX key [63:32]
+			 */
+			u32 mic0, mic1, mic2, mic3, mic4;
+
+			mic0 = get_unaligned_le32(k->kv_mic + 0);
+			mic2 = get_unaligned_le32(k->kv_mic + 4);
+			mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
+			mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
+			mic4 = get_unaligned_le32(k->kv_txmic + 4);
+
+			/* Write RX[31:0] and TX[31:16] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
+
+			/* Write RX[63:32] and TX[15:0] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
+
+			/* Write TX[63:32] and keyType(reserved) */
+			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+
+		} else {
+			/*
+			 * TKIP uses four key cache entries (two for group
+			 * keys):
+			 * Michael MIC TX/RX keys are in different key cache
+			 * entries (idx = main index + 64 for TX and
+			 * main index + 32 + 96 for RX):
+			 * key0 [31:0] = TX/RX MIC key [31:0]
+			 * key1 [31:0] = reserved
+			 * key2 [31:0] = TX/RX MIC key [63:32]
+			 * key3 [31:0] = reserved
+			 * key4 [31:0] = reserved
+			 *
+			 * Upper layer code will call this function separately
+			 * for TX and RX keys when these registers offsets are
+			 * used.
+			 */
+			u32 mic0, mic2;
+
+			mic0 = get_unaligned_le32(k->kv_mic + 0);
+			mic2 = get_unaligned_le32(k->kv_mic + 4);
+
+			/* Write MIC key[31:0] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+
+			/* Write MIC key[63:32] */
+			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
+			/* Write TX[63:32] and keyType(reserved) */
+			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+		}
+
+		/* MAC address registers are reserved for the MIC entry */
+		REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
+		REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
+
+		/*
+		 * Write the correct (un-inverted) key[47:0] last to enable
+		 * TKIP now that all other registers are set with correct
+		 * values.
+		 */
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+	} else {
+		/* Write key[47:0] */
+		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+
+		/* Write key[95:48] */
+		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+
+		/* Write key[127:96] and key type */
+		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+		/* Write MAC address for the entry */
+		(void) ath9k_hw_keysetmac(ah, entry, mac);
+	}
+
+	return true;
+}
+
+bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry)
+{
+	if (entry < ah->caps.keycache_size) {
+		u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
+		if (val & AR_KEYTABLE_VALID)
+			return true;
+	}
+	return false;
+}
+
+/******************************/
+/* Power Management (Chipset) */
+/******************************/
+
+static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
+{
+	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+	if (setChip) {
+		REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+			    AR_RTC_FORCE_WAKE_EN);
+		if (!AR_SREV_9100(ah))
+			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+
+		REG_CLR_BIT(ah, (AR_RTC_RESET),
+			    AR_RTC_RESET_EN);
+	}
+}
+
+static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
+{
+	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+	if (setChip) {
+		struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+			REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+				  AR_RTC_FORCE_WAKE_ON_INT);
+		} else {
+			REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+				    AR_RTC_FORCE_WAKE_EN);
+		}
+	}
+}
+
+static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
+{
+	u32 val;
+	int i;
+
+	if (setChip) {
+		if ((REG_READ(ah, AR_RTC_STATUS) &
+		     AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+			if (ath9k_hw_set_reset_reg(ah,
+					   ATH9K_RESET_POWER_ON) != true) {
+				return false;
+			}
+		}
+		if (AR_SREV_9100(ah))
+			REG_SET_BIT(ah, AR_RTC_RESET,
+				    AR_RTC_RESET_EN);
+
+		REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+			    AR_RTC_FORCE_WAKE_EN);
+		udelay(50);
+
+		for (i = POWER_UP_TIME / 50; i > 0; i--) {
+			val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+			if (val == AR_RTC_STATUS_ON)
+				break;
+			udelay(50);
+			REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+				    AR_RTC_FORCE_WAKE_EN);
+		}
+		if (i == 0) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Failed to wakeup in %uus\n", POWER_UP_TIME / 20);
+			return false;
+		}
+	}
+
+	REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+	return true;
+}
+
+bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
+{
+	int status = true, setChip = true;
+	static const char *modes[] = {
+		"AWAKE",
+		"FULL-SLEEP",
+		"NETWORK SLEEP",
+		"UNDEFINED"
+	};
+
+	DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n",
+		modes[ah->power_mode], modes[mode]);
+
+	switch (mode) {
+	case ATH9K_PM_AWAKE:
+		status = ath9k_hw_set_power_awake(ah, setChip);
+		break;
+	case ATH9K_PM_FULL_SLEEP:
+		ath9k_set_power_sleep(ah, setChip);
+		ah->chip_fullsleep = true;
+		break;
+	case ATH9K_PM_NETWORK_SLEEP:
+		ath9k_set_power_network_sleep(ah, setChip);
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Unknown power mode %u\n", mode);
+		return false;
+	}
+	ah->power_mode = mode;
+
+	return status;
+}
+
+/*
+ * Helper for ASPM support.
+ *
+ * Disable PLL when in L0s as well as receiver clock when in L1.
+ * This power saving option must be enabled through the SerDes.
+ *
+ * Programming the SerDes must go through the same 288 bit serial shift
+ * register as the other analog registers.  Hence the 9 writes.
+ */
+void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
+{
+	u8 i;
+
+	if (ah->is_pciexpress != true)
+		return;
+
+	/* Do not touch SerDes registers */
+	if (ah->config.pcie_powersave_enable == 2)
+		return;
+
+	/* Nothing to do on restore for 11N */
+	if (restore)
+		return;
+
+	if (AR_SREV_9280_20_OR_LATER(ah)) {
+		/*
+		 * AR9280 2.0 or later chips use SerDes values from the
+		 * initvals.h initialized depending on chipset during
+		 * ath9k_hw_do_attach()
+		 */
+		for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
+			REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
+				  INI_RA(&ah->iniPcieSerdes, i, 1));
+		}
+	} else if (AR_SREV_9280(ah) &&
+		   (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+		/* RX shut off when elecidle is asserted */
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
+
+		/* Shut off CLKREQ active in L1 */
+		if (ah->config.pcie_clock_req)
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
+		else
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
+
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
+
+		/* Load the new settings */
+		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+
+	} else {
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+		/* RX shut off when elecidle is asserted */
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+
+		/*
+		 * Ignore ah->ah_config.pcie_clock_req setting for
+		 * pre-AR9280 11n
+		 */
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+		REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+
+		/* Load the new settings */
+		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+	}
+
+	udelay(1000);
+
+	/* set bit 19 to allow forcing of pcie core into L1 state */
+	REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+	/* Several PCIe massages to ensure proper behaviour */
+	if (ah->config.pcie_waen) {
+		REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
+	} else {
+		if (AR_SREV_9285(ah))
+			REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
+		/*
+		 * On AR9280 chips bit 22 of 0x4004 needs to be set to
+		 * otherwise card may disappear.
+		 */
+		else if (AR_SREV_9280(ah))
+			REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
+		else
+			REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
+	}
+}
+
+/**********************/
+/* Interrupt Handling */
+/**********************/
+
+bool ath9k_hw_intrpend(struct ath_hw *ah)
+{
+	u32 host_isr;
+
+	if (AR_SREV_9100(ah))
+		return true;
+
+	host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
+	if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
+		return true;
+
+	host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+	if ((host_isr & AR_INTR_SYNC_DEFAULT)
+	    && (host_isr != AR_INTR_SPURIOUS))
+		return true;
+
+	return false;
+}
+
+bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
+{
+	u32 isr = 0;
+	u32 mask2 = 0;
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	u32 sync_cause = 0;
+	bool fatal_int = false;
+
+	if (!AR_SREV_9100(ah)) {
+		if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
+			if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
+			    == AR_RTC_STATUS_ON) {
+				isr = REG_READ(ah, AR_ISR);
+			}
+		}
+
+		sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
+			AR_INTR_SYNC_DEFAULT;
+
+		*masked = 0;
+
+		if (!isr && !sync_cause)
+			return false;
+	} else {
+		*masked = 0;
+		isr = REG_READ(ah, AR_ISR);
+	}
+
+	if (isr) {
+		if (isr & AR_ISR_BCNMISC) {
+			u32 isr2;
+			isr2 = REG_READ(ah, AR_ISR_S2);
+			if (isr2 & AR_ISR_S2_TIM)
+				mask2 |= ATH9K_INT_TIM;
+			if (isr2 & AR_ISR_S2_DTIM)
+				mask2 |= ATH9K_INT_DTIM;
+			if (isr2 & AR_ISR_S2_DTIMSYNC)
+				mask2 |= ATH9K_INT_DTIMSYNC;
+			if (isr2 & (AR_ISR_S2_CABEND))
+				mask2 |= ATH9K_INT_CABEND;
+			if (isr2 & AR_ISR_S2_GTT)
+				mask2 |= ATH9K_INT_GTT;
+			if (isr2 & AR_ISR_S2_CST)
+				mask2 |= ATH9K_INT_CST;
+			if (isr2 & AR_ISR_S2_TSFOOR)
+				mask2 |= ATH9K_INT_TSFOOR;
+		}
+
+		isr = REG_READ(ah, AR_ISR_RAC);
+		if (isr == 0xffffffff) {
+			*masked = 0;
+			return false;
+		}
+
+		*masked = isr & ATH9K_INT_COMMON;
+
+		if (ah->config.intr_mitigation) {
+			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+				*masked |= ATH9K_INT_RX;
+		}
+
+		if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+			*masked |= ATH9K_INT_RX;
+		if (isr &
+		    (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
+		     AR_ISR_TXEOL)) {
+			u32 s0_s, s1_s;
+
+			*masked |= ATH9K_INT_TX;
+
+			s0_s = REG_READ(ah, AR_ISR_S0_S);
+			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
+			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
+
+			s1_s = REG_READ(ah, AR_ISR_S1_S);
+			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
+			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
+		}
+
+		if (isr & AR_ISR_RXORN) {
+			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
+				"receive FIFO overrun interrupt\n");
+		}
+
+		if (!AR_SREV_9100(ah)) {
+			if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+				u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
+				if (isr5 & AR_ISR_S5_TIM_TIMER)
+					*masked |= ATH9K_INT_TIM_TIMER;
+			}
+		}
+
+		*masked |= mask2;
+	}
+
+	if (AR_SREV_9100(ah))
+		return true;
+
+	if (sync_cause) {
+		fatal_int =
+			(sync_cause &
+			 (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
+			? true : false;
+
+		if (fatal_int) {
+			if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+					"received PCI FATAL interrupt\n");
+			}
+			if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
+				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+					"received PCI PERR interrupt\n");
+			}
+			*masked |= ATH9K_INT_FATAL;
+		}
+		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
+				"AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
+			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
+			REG_WRITE(ah, AR_RC, 0);
+			*masked |= ATH9K_INT_FATAL;
+		}
+		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
+			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
+				"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
+		}
+
+		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
+	}
+
+	return true;
+}
+
+enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah)
+{
+	return ah->mask_reg;
+}
+
+enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
+{
+	u32 omask = ah->mask_reg;
+	u32 mask, mask2;
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
+
+	if (omask & ATH9K_INT_GLOBAL) {
+		DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n");
+		REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+		(void) REG_READ(ah, AR_IER);
+		if (!AR_SREV_9100(ah)) {
+			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+			(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+			(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+		}
+	}
+
+	mask = ints & ATH9K_INT_COMMON;
+	mask2 = 0;
+
+	if (ints & ATH9K_INT_TX) {
+		if (ah->txok_interrupt_mask)
+			mask |= AR_IMR_TXOK;
+		if (ah->txdesc_interrupt_mask)
+			mask |= AR_IMR_TXDESC;
+		if (ah->txerr_interrupt_mask)
+			mask |= AR_IMR_TXERR;
+		if (ah->txeol_interrupt_mask)
+			mask |= AR_IMR_TXEOL;
+	}
+	if (ints & ATH9K_INT_RX) {
+		mask |= AR_IMR_RXERR;
+		if (ah->config.intr_mitigation)
+			mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
+		else
+			mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
+		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+			mask |= AR_IMR_GENTMR;
+	}
+
+	if (ints & (ATH9K_INT_BMISC)) {
+		mask |= AR_IMR_BCNMISC;
+		if (ints & ATH9K_INT_TIM)
+			mask2 |= AR_IMR_S2_TIM;
+		if (ints & ATH9K_INT_DTIM)
+			mask2 |= AR_IMR_S2_DTIM;
+		if (ints & ATH9K_INT_DTIMSYNC)
+			mask2 |= AR_IMR_S2_DTIMSYNC;
+		if (ints & ATH9K_INT_CABEND)
+			mask2 |= AR_IMR_S2_CABEND;
+		if (ints & ATH9K_INT_TSFOOR)
+			mask2 |= AR_IMR_S2_TSFOOR;
+	}
+
+	if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
+		mask |= AR_IMR_BCNMISC;
+		if (ints & ATH9K_INT_GTT)
+			mask2 |= AR_IMR_S2_GTT;
+		if (ints & ATH9K_INT_CST)
+			mask2 |= AR_IMR_S2_CST;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
+	REG_WRITE(ah, AR_IMR, mask);
+	mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
+					   AR_IMR_S2_DTIM |
+					   AR_IMR_S2_DTIMSYNC |
+					   AR_IMR_S2_CABEND |
+					   AR_IMR_S2_CABTO |
+					   AR_IMR_S2_TSFOOR |
+					   AR_IMR_S2_GTT | AR_IMR_S2_CST);
+	REG_WRITE(ah, AR_IMR_S2, mask | mask2);
+	ah->mask_reg = ints;
+
+	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+		if (ints & ATH9K_INT_TIM_TIMER)
+			REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+		else
+			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+	}
+
+	if (ints & ATH9K_INT_GLOBAL) {
+		DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n");
+		REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+		if (!AR_SREV_9100(ah)) {
+			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
+				  AR_INTR_MAC_IRQ);
+			REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+
+			REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
+				  AR_INTR_SYNC_DEFAULT);
+			REG_WRITE(ah, AR_INTR_SYNC_MASK,
+				  AR_INTR_SYNC_DEFAULT);
+		}
+		DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+			 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+	}
+
+	return omask;
+}
+
+/*******************/
+/* Beacon Handling */
+/*******************/
+
+void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
+{
+	int flags = 0;
+
+	ah->beacon_interval = beacon_period;
+
+	switch (ah->opmode) {
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_MONITOR:
+		REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
+		REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
+		REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
+		flags |= AR_TBTT_TIMER_EN;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+		REG_SET_BIT(ah, AR_TXCFG,
+			    AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
+		REG_WRITE(ah, AR_NEXT_NDP_TIMER,
+			  TU_TO_USEC(next_beacon +
+				     (ah->atim_window ? ah->
+				      atim_window : 1)));
+		flags |= AR_NDP_TIMER_EN;
+	case NL80211_IFTYPE_AP:
+		REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
+		REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
+			  TU_TO_USEC(next_beacon -
+				     ah->config.
+				     dma_beacon_response_time));
+		REG_WRITE(ah, AR_NEXT_SWBA,
+			  TU_TO_USEC(next_beacon -
+				     ah->config.
+				     sw_beacon_response_time));
+		flags |=
+			AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_BEACON,
+			"%s: unsupported opmode: %d\n",
+			__func__, ah->opmode);
+		return;
+		break;
+	}
+
+	REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period));
+	REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period));
+	REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
+	REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
+
+	beacon_period &= ~ATH9K_BEACON_ENA;
+	if (beacon_period & ATH9K_BEACON_RESET_TSF) {
+		beacon_period &= ~ATH9K_BEACON_RESET_TSF;
+		ath9k_hw_reset_tsf(ah);
+	}
+
+	REG_SET_BIT(ah, AR_TIMER_MODE, flags);
+}
+
+void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
+				    const struct ath9k_beacon_state *bs)
+{
+	u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+	REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
+
+	REG_WRITE(ah, AR_BEACON_PERIOD,
+		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+	REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
+		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
+
+	REG_RMW_FIELD(ah, AR_RSSI_THR,
+		      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
+
+	beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
+
+	if (bs->bs_sleepduration > beaconintval)
+		beaconintval = bs->bs_sleepduration;
+
+	dtimperiod = bs->bs_dtimperiod;
+	if (bs->bs_sleepduration > dtimperiod)
+		dtimperiod = bs->bs_sleepduration;
+
+	if (beaconintval == dtimperiod)
+		nextTbtt = bs->bs_nextdtim;
+	else
+		nextTbtt = bs->bs_nexttbtt;
+
+	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim);
+	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt);
+	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
+	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
+
+	REG_WRITE(ah, AR_NEXT_DTIM,
+		  TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
+	REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
+
+	REG_WRITE(ah, AR_SLEEP1,
+		  SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
+		  | AR_SLEEP1_ASSUME_DTIM);
+
+	if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)
+		beacontimeout = (BEACON_TIMEOUT_VAL << 3);
+	else
+		beacontimeout = MIN_BEACON_TIMEOUT_VAL;
+
+	REG_WRITE(ah, AR_SLEEP2,
+		  SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
+
+	REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
+	REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
+
+	REG_SET_BIT(ah, AR_TIMER_MODE,
+		    AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
+		    AR_DTIM_TIMER_EN);
+
+	/* TSF Out of Range Threshold */
+	REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
+}
+
+/*******************/
+/* HW Capabilities */
+/*******************/
+
+void ath9k_hw_fill_cap_info(struct ath_hw *ah)
+{
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	u16 capField = 0, eeval;
+
+	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
+	ah->regulatory.current_rd = eeval;
+
+	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
+	if (AR_SREV_9285_10_OR_LATER(ah))
+		eeval |= AR9285_RDEXT_DEFAULT;
+	ah->regulatory.current_rd_ext = eeval;
+
+	capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP);
+
+	if (ah->opmode != NL80211_IFTYPE_AP &&
+	    ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+		if (ah->regulatory.current_rd == 0x64 ||
+		    ah->regulatory.current_rd == 0x65)
+			ah->regulatory.current_rd += 5;
+		else if (ah->regulatory.current_rd == 0x41)
+			ah->regulatory.current_rd = 0x43;
+		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
+			"regdomain mapped to 0x%x\n", ah->regulatory.current_rd);
+	}
+
+	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
+	bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
+
+	if (eeval & AR5416_OPFLAGS_11A) {
+		set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
+		if (ah->config.ht_enable) {
+			if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
+				set_bit(ATH9K_MODE_11NA_HT20,
+					pCap->wireless_modes);
+			if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
+				set_bit(ATH9K_MODE_11NA_HT40PLUS,
+					pCap->wireless_modes);
+				set_bit(ATH9K_MODE_11NA_HT40MINUS,
+					pCap->wireless_modes);
+			}
+		}
+	}
+
+	if (eeval & AR5416_OPFLAGS_11G) {
+		set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
+		set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
+		if (ah->config.ht_enable) {
+			if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
+				set_bit(ATH9K_MODE_11NG_HT20,
+					pCap->wireless_modes);
+			if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
+				set_bit(ATH9K_MODE_11NG_HT40PLUS,
+					pCap->wireless_modes);
+				set_bit(ATH9K_MODE_11NG_HT40MINUS,
+					pCap->wireless_modes);
+			}
+		}
+	}
+
+	pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
+	if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
+	    !(eeval & AR5416_OPFLAGS_11A))
+		pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
+	else
+		pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
+
+	if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
+		ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+
+	pCap->low_2ghz_chan = 2312;
+	pCap->high_2ghz_chan = 2732;
+
+	pCap->low_5ghz_chan = 4920;
+	pCap->high_5ghz_chan = 6100;
+
+	pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
+
+	pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
+	pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
+
+	if (ah->config.ht_enable)
+		pCap->hw_caps |= ATH9K_HW_CAP_HT;
+	else
+		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
+
+	pCap->hw_caps |= ATH9K_HW_CAP_GTT;
+	pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
+	pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
+	pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
+
+	if (capField & AR_EEPROM_EEPCAP_MAXQCU)
+		pCap->total_queues =
+			MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
+	else
+		pCap->total_queues = ATH9K_NUM_TX_QUEUES;
+
+	if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
+		pCap->keycache_size =
+			1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
+	else
+		pCap->keycache_size = AR_KEYTABLE_SIZE;
+
+	pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
+	pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
+
+	if (AR_SREV_9285_10_OR_LATER(ah))
+		pCap->num_gpio_pins = AR9285_NUM_GPIO;
+	else if (AR_SREV_9280_10_OR_LATER(ah))
+		pCap->num_gpio_pins = AR928X_NUM_GPIO;
+	else
+		pCap->num_gpio_pins = AR_NUM_GPIO;
+
+	if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
+		pCap->hw_caps |= ATH9K_HW_CAP_CST;
+		pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
+	} else {
+		pCap->rts_aggr_limit = (8 * 1024);
+	}
+
+	pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+	ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
+	if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
+		ah->rfkill_gpio =
+			MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL);
+		ah->rfkill_polarity =
+			MS(ah->rfsilent, EEP_RFSILENT_POLARITY);
+
+		pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
+	}
+#endif
+
+	if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) ||
+	    (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
+	    (ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
+	    (ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
+	    (ah->hw_version.macVersion == AR_SREV_VERSION_9280) ||
+	    (ah->hw_version.macVersion == AR_SREV_VERSION_9285))
+		pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+	else
+		pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
+
+	if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
+		pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
+	else
+		pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
+
+	if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
+		pCap->reg_cap =
+			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
+			AR_EEPROM_EEREGCAP_EN_KK_U2 |
+			AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
+	} else {
+		pCap->reg_cap =
+			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
+	}
+
+	pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
+
+	pCap->num_antcfg_5ghz =
+		ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ);
+	pCap->num_antcfg_2ghz =
+		ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
+
+	if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) {
+		pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX;
+		ah->btactive_gpio = 6;
+		ah->wlanactive_gpio = 5;
+	}
+}
+
+bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 *result)
+{
+	switch (type) {
+	case ATH9K_CAP_CIPHER:
+		switch (capability) {
+		case ATH9K_CIPHER_AES_CCM:
+		case ATH9K_CIPHER_AES_OCB:
+		case ATH9K_CIPHER_TKIP:
+		case ATH9K_CIPHER_WEP:
+		case ATH9K_CIPHER_MIC:
+		case ATH9K_CIPHER_CLR:
+			return true;
+		default:
+			return false;
+		}
+	case ATH9K_CAP_TKIP_MIC:
+		switch (capability) {
+		case 0:
+			return true;
+		case 1:
+			return (ah->sta_id1_defaults &
+				AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
+			false;
+		}
+	case ATH9K_CAP_TKIP_SPLIT:
+		return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ?
+			false : true;
+	case ATH9K_CAP_DIVERSITY:
+		return (REG_READ(ah, AR_PHY_CCK_DETECT) &
+			AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
+			true : false;
+	case ATH9K_CAP_MCAST_KEYSRCH:
+		switch (capability) {
+		case 0:
+			return true;
+		case 1:
+			if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
+				return false;
+			} else {
+				return (ah->sta_id1_defaults &
+					AR_STA_ID1_MCAST_KSRCH) ? true :
+					false;
+			}
+		}
+		return false;
+	case ATH9K_CAP_TXPOW:
+		switch (capability) {
+		case 0:
+			return 0;
+		case 1:
+			*result = ah->regulatory.power_limit;
+			return 0;
+		case 2:
+			*result = ah->regulatory.max_power_level;
+			return 0;
+		case 3:
+			*result = ah->regulatory.tp_scale;
+			return 0;
+		}
+		return false;
+	case ATH9K_CAP_DS:
+		return (AR_SREV_9280_20_OR_LATER(ah) &&
+			(ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1))
+			? false : true;
+	default:
+		return false;
+	}
+}
+
+bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 setting, int *status)
+{
+	u32 v;
+
+	switch (type) {
+	case ATH9K_CAP_TKIP_MIC:
+		if (setting)
+			ah->sta_id1_defaults |=
+				AR_STA_ID1_CRPT_MIC_ENABLE;
+		else
+			ah->sta_id1_defaults &=
+				~AR_STA_ID1_CRPT_MIC_ENABLE;
+		return true;
+	case ATH9K_CAP_DIVERSITY:
+		v = REG_READ(ah, AR_PHY_CCK_DETECT);
+		if (setting)
+			v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+		else
+			v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+		REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+		return true;
+	case ATH9K_CAP_MCAST_KEYSRCH:
+		if (setting)
+			ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH;
+		else
+			ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH;
+		return true;
+	default:
+		return false;
+	}
+}
+
+/****************************/
+/* GPIO / RFKILL / Antennae */
+/****************************/
+
+static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
+					 u32 gpio, u32 type)
+{
+	int addr;
+	u32 gpio_shift, tmp;
+
+	if (gpio > 11)
+		addr = AR_GPIO_OUTPUT_MUX3;
+	else if (gpio > 5)
+		addr = AR_GPIO_OUTPUT_MUX2;
+	else
+		addr = AR_GPIO_OUTPUT_MUX1;
+
+	gpio_shift = (gpio % 6) * 5;
+
+	if (AR_SREV_9280_20_OR_LATER(ah)
+	    || (addr != AR_GPIO_OUTPUT_MUX1)) {
+		REG_RMW(ah, addr, (type << gpio_shift),
+			(0x1f << gpio_shift));
+	} else {
+		tmp = REG_READ(ah, addr);
+		tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
+		tmp &= ~(0x1f << gpio_shift);
+		tmp |= (type << gpio_shift);
+		REG_WRITE(ah, addr, tmp);
+	}
+}
+
+void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
+{
+	u32 gpio_shift;
+
+	ASSERT(gpio < ah->caps.num_gpio_pins);
+
+	gpio_shift = gpio << 1;
+
+	REG_RMW(ah,
+		AR_GPIO_OE_OUT,
+		(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+		(AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
+{
+#define MS_REG_READ(x, y) \
+	(MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
+
+	if (gpio >= ah->caps.num_gpio_pins)
+		return 0xffffffff;
+
+	if (AR_SREV_9285_10_OR_LATER(ah))
+		return MS_REG_READ(AR9285, gpio) != 0;
+	else if (AR_SREV_9280_10_OR_LATER(ah))
+		return MS_REG_READ(AR928X, gpio) != 0;
+	else
+		return MS_REG_READ(AR, gpio) != 0;
+}
+
+void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
+			 u32 ah_signal_type)
+{
+	u32 gpio_shift;
+
+	ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+
+	gpio_shift = 2 * gpio;
+
+	REG_RMW(ah,
+		AR_GPIO_OE_OUT,
+		(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
+		(AR_GPIO_OE_OUT_DRV << gpio_shift));
+}
+
+void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
+{
+	REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
+		AR_GPIO_BIT(gpio));
+}
+
+u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
+{
+	return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
+}
+
+void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
+{
+	REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+}
+
+bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
+			       enum ath9k_ant_setting settings,
+			       struct ath9k_channel *chan,
+			       u8 *tx_chainmask,
+			       u8 *rx_chainmask,
+			       u8 *antenna_cfgd)
+{
+	static u8 tx_chainmask_cfg, rx_chainmask_cfg;
+
+	if (AR_SREV_9280(ah)) {
+		if (!tx_chainmask_cfg) {
+
+			tx_chainmask_cfg = *tx_chainmask;
+			rx_chainmask_cfg = *rx_chainmask;
+		}
+
+		switch (settings) {
+		case ATH9K_ANT_FIXED_A:
+			*tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+			*rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+			*antenna_cfgd = true;
+			break;
+		case ATH9K_ANT_FIXED_B:
+			if (ah->caps.tx_chainmask >
+			    ATH9K_ANTENNA1_CHAINMASK) {
+				*tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+			}
+			*rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+			*antenna_cfgd = true;
+			break;
+		case ATH9K_ANT_VARIABLE:
+			*tx_chainmask = tx_chainmask_cfg;
+			*rx_chainmask = rx_chainmask_cfg;
+			*antenna_cfgd = true;
+			break;
+		default:
+			break;
+		}
+	} else {
+		ah->diversity_control = settings;
+	}
+
+	return true;
+}
+
+/*********************/
+/* General Operation */
+/*********************/
+
+u32 ath9k_hw_getrxfilter(struct ath_hw *ah)
+{
+	u32 bits = REG_READ(ah, AR_RX_FILTER);
+	u32 phybits = REG_READ(ah, AR_PHY_ERR);
+
+	if (phybits & AR_PHY_ERR_RADAR)
+		bits |= ATH9K_RX_FILTER_PHYRADAR;
+	if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
+		bits |= ATH9K_RX_FILTER_PHYERR;
+
+	return bits;
+}
+
+void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
+{
+	u32 phybits;
+
+	REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
+	phybits = 0;
+	if (bits & ATH9K_RX_FILTER_PHYRADAR)
+		phybits |= AR_PHY_ERR_RADAR;
+	if (bits & ATH9K_RX_FILTER_PHYERR)
+		phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
+	REG_WRITE(ah, AR_PHY_ERR, phybits);
+
+	if (phybits)
+		REG_WRITE(ah, AR_RXCFG,
+			  REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
+	else
+		REG_WRITE(ah, AR_RXCFG,
+			  REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
+}
+
+bool ath9k_hw_phy_disable(struct ath_hw *ah)
+{
+	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
+}
+
+bool ath9k_hw_disable(struct ath_hw *ah)
+{
+	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+		return false;
+
+	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
+}
+
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
+{
+	struct ath9k_channel *chan = ah->curchan;
+	struct ieee80211_channel *channel = chan->chan;
+
+	ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
+
+	ah->eep_ops->set_txpower(ah, chan,
+				 ath9k_regd_get_ctl(&ah->regulatory, chan),
+				 channel->max_antenna_gain * 2,
+				 channel->max_power * 2,
+				 min((u32) MAX_RATE_POWER,
+				 (u32) ah->regulatory.power_limit));
+}
+
+void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac)
+{
+	memcpy(ah->macaddr, mac, ETH_ALEN);
+}
+
+void ath9k_hw_setopmode(struct ath_hw *ah)
+{
+	ath9k_hw_set_operating_mode(ah, ah->opmode);
+}
+
+void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1)
+{
+	REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+	REG_WRITE(ah, AR_MCAST_FIL1, filter1);
+}
+
+void ath9k_hw_setbssidmask(struct ath_softc *sc)
+{
+	REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask));
+	REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4));
+}
+
+void ath9k_hw_write_associd(struct ath_softc *sc)
+{
+	REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid));
+	REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) |
+		  ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
+}
+
+u64 ath9k_hw_gettsf64(struct ath_hw *ah)
+{
+	u64 tsf;
+
+	tsf = REG_READ(ah, AR_TSF_U32);
+	tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
+
+	return tsf;
+}
+
+void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64)
+{
+	REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
+	REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
+}
+
+void ath9k_hw_reset_tsf(struct ath_hw *ah)
+{
+	int count;
+
+	count = 0;
+	while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
+		count++;
+		if (count > 10) {
+			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+				"AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
+			break;
+		}
+		udelay(10);
+	}
+	REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
+}
+
+bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
+{
+	if (setting)
+		ah->misc_mode |= AR_PCU_TX_ADD_TSF;
+	else
+		ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
+
+	return true;
+}
+
+bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
+{
+	if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us);
+		ah->slottime = (u32) -1;
+		return false;
+	} else {
+		REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
+		ah->slottime = us;
+		return true;
+	}
+}
+
+void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode)
+{
+	u32 macmode;
+
+	if (mode == ATH9K_HT_MACMODE_2040 &&
+	    !ah->config.cwm_ignore_extcca)
+		macmode = AR_2040_JOINED_RX_CLEAR;
+	else
+		macmode = 0;
+
+	REG_WRITE(ah, AR_2040_MODE, macmode);
+}
+
+/***************************/
+/*  Bluetooth Coexistence  */
+/***************************/
+
+void ath9k_hw_btcoex_enable(struct ath_hw *ah)
+{
+	/* connect bt_active to baseband */
+	REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+			(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
+			 AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
+
+	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+			AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
+
+	/* Set input mux for bt_active to gpio pin */
+	REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+			AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+			ah->btactive_gpio);
+
+	/* Configure the desired gpio port for input */
+	ath9k_hw_cfg_gpio_input(ah, ah->btactive_gpio);
+
+	/* Configure the desired GPIO port for TX_FRAME output */
+	ath9k_hw_cfg_output(ah, ah->wlanactive_gpio,
+			    AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/hw.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/hw.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/hw.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HW_H
+#define HW_H
+
+#include <linux/if_ether.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "mac.h"
+#include "ani.h"
+#include "eeprom.h"
+#include "calib.h"
+#include "reg.h"
+#include "phy.h"
+
+#include "../regd.h"
+
+#define ATHEROS_VENDOR_ID	0x168c
+#define AR5416_DEVID_PCI	0x0023
+#define AR5416_DEVID_PCIE	0x0024
+#define AR9160_DEVID_PCI	0x0027
+#define AR9280_DEVID_PCI	0x0029
+#define AR9280_DEVID_PCIE	0x002a
+#define AR9285_DEVID_PCIE	0x002b
+#define AR5416_AR9100_DEVID	0x000b
+#define	AR_SUBVENDOR_ID_NOG	0x0e11
+#define AR_SUBVENDOR_ID_NEW_A	0x7065
+#define AR5416_MAGIC		0x19641014
+
+/* Register read/write primitives */
+#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
+#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
+
+#define SM(_v, _f)  (((_v) << _f##_S) & _f)
+#define MS(_v, _f)  (((_v) & _f) >> _f##_S)
+#define REG_RMW(_a, _r, _set, _clr)    \
+	REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set))
+#define REG_RMW_FIELD(_a, _r, _f, _v) \
+	REG_WRITE(_a, _r, \
+	(REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f))
+#define REG_SET_BIT(_a, _r, _f) \
+	REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
+#define REG_CLR_BIT(_a, _r, _f) \
+	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
+
+#define DO_DELAY(x) do {			\
+		if ((++(x) % 64) == 0)          \
+			udelay(1);		\
+	} while (0)
+
+#define REG_WRITE_ARRAY(iniarray, column, regWr) do {                   \
+		int r;							\
+		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\
+			REG_WRITE(ah, INI_RA((iniarray), (r), 0),	\
+				  INI_RA((iniarray), r, (column)));	\
+			DO_DELAY(regWr);				\
+		}							\
+	} while (0)
+
+#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     2
+#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME           3
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    5
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      6
+
+#define AR_GPIOD_MASK               0x00001FFF
+#define AR_GPIO_BIT(_gpio)          (1 << (_gpio))
+
+#define BASE_ACTIVATE_DELAY         100
+#define RTC_PLL_SETTLE_DELAY        1000
+#define COEF_SCALE_S                24
+#define HT40_CHANNEL_CENTER_SHIFT   10
+
+#define ATH9K_ANTENNA0_CHAINMASK    0x1
+#define ATH9K_ANTENNA1_CHAINMASK    0x2
+
+#define ATH9K_NUM_DMA_DEBUG_REGS    8
+#define ATH9K_NUM_QUEUES            10
+
+#define MAX_RATE_POWER              63
+#define AH_WAIT_TIMEOUT             100000 /* (us) */
+#define AH_TIME_QUANTUM             10
+#define AR_KEYTABLE_SIZE            128
+#define POWER_UP_TIME               200000
+#define SPUR_RSSI_THRESH            40
+
+#define CAB_TIMEOUT_VAL             10
+#define BEACON_TIMEOUT_VAL          10
+#define MIN_BEACON_TIMEOUT_VAL      1
+#define SLEEP_SLOP                  3
+
+#define INIT_CONFIG_STATUS          0x00000000
+#define INIT_RSSI_THR               0x00000700
+#define INIT_BCON_CNTRL_REG         0x00000000
+
+#define TU_TO_USEC(_tu)             ((_tu) << 10)
+
+enum wireless_mode {
+	ATH9K_MODE_11A = 0,
+	ATH9K_MODE_11B = 2,
+	ATH9K_MODE_11G = 3,
+	ATH9K_MODE_11NA_HT20 = 6,
+	ATH9K_MODE_11NG_HT20 = 7,
+	ATH9K_MODE_11NA_HT40PLUS = 8,
+	ATH9K_MODE_11NA_HT40MINUS = 9,
+	ATH9K_MODE_11NG_HT40PLUS = 10,
+	ATH9K_MODE_11NG_HT40MINUS = 11,
+	ATH9K_MODE_MAX
+};
+
+enum ath9k_hw_caps {
+	ATH9K_HW_CAP_MIC_AESCCM                 = BIT(0),
+	ATH9K_HW_CAP_MIC_CKIP                   = BIT(1),
+	ATH9K_HW_CAP_MIC_TKIP                   = BIT(2),
+	ATH9K_HW_CAP_CIPHER_AESCCM              = BIT(3),
+	ATH9K_HW_CAP_CIPHER_CKIP                = BIT(4),
+	ATH9K_HW_CAP_CIPHER_TKIP                = BIT(5),
+	ATH9K_HW_CAP_VEOL                       = BIT(6),
+	ATH9K_HW_CAP_BSSIDMASK                  = BIT(7),
+	ATH9K_HW_CAP_MCAST_KEYSEARCH            = BIT(8),
+	ATH9K_HW_CAP_HT                         = BIT(9),
+	ATH9K_HW_CAP_GTT                        = BIT(10),
+	ATH9K_HW_CAP_FASTCC                     = BIT(11),
+	ATH9K_HW_CAP_RFSILENT                   = BIT(12),
+	ATH9K_HW_CAP_CST                        = BIT(13),
+	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(14),
+	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(15),
+	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(16),
+	ATH9K_HW_CAP_BT_COEX			= BIT(17)
+};
+
+enum ath9k_capability_type {
+	ATH9K_CAP_CIPHER = 0,
+	ATH9K_CAP_TKIP_MIC,
+	ATH9K_CAP_TKIP_SPLIT,
+	ATH9K_CAP_DIVERSITY,
+	ATH9K_CAP_TXPOW,
+	ATH9K_CAP_MCAST_KEYSRCH,
+	ATH9K_CAP_DS
+};
+
+struct ath9k_hw_capabilities {
+	u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
+	DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
+	u16 total_queues;
+	u16 keycache_size;
+	u16 low_5ghz_chan, high_5ghz_chan;
+	u16 low_2ghz_chan, high_2ghz_chan;
+	u16 rts_aggr_limit;
+	u8 tx_chainmask;
+	u8 rx_chainmask;
+	u16 tx_triglevel_max;
+	u16 reg_cap;
+	u8 num_gpio_pins;
+	u8 num_antcfg_2ghz;
+	u8 num_antcfg_5ghz;
+};
+
+struct ath9k_ops_config {
+	int dma_beacon_response_time;
+	int sw_beacon_response_time;
+	int additional_swba_backoff;
+	int ack_6mb;
+	int cwm_ignore_extcca;
+	u8 pcie_powersave_enable;
+	u8 pcie_clock_req;
+	u32 pcie_waen;
+	u8 analog_shiftreg;
+	u8 ht_enable;
+	u32 ofdm_trig_low;
+	u32 ofdm_trig_high;
+	u32 cck_trig_high;
+	u32 cck_trig_low;
+	u32 enable_ani;
+	u16 diversity_control;
+	u16 antenna_switch_swap;
+	int serialize_regmode;
+	bool intr_mitigation;
+#define SPUR_DISABLE        	0
+#define SPUR_ENABLE_IOCTL   	1
+#define SPUR_ENABLE_EEPROM  	2
+#define AR_EEPROM_MODAL_SPURS   5
+#define AR_SPUR_5413_1      	1640
+#define AR_SPUR_5413_2      	1200
+#define AR_NO_SPUR      	0x8000
+#define AR_BASE_FREQ_2GHZ   	2300
+#define AR_BASE_FREQ_5GHZ   	4900
+#define AR_SPUR_FEEQ_BOUND_HT40 19
+#define AR_SPUR_FEEQ_BOUND_HT20 10
+	int spurmode;
+	u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
+};
+
+enum ath9k_int {
+	ATH9K_INT_RX = 0x00000001,
+	ATH9K_INT_RXDESC = 0x00000002,
+	ATH9K_INT_RXNOFRM = 0x00000008,
+	ATH9K_INT_RXEOL = 0x00000010,
+	ATH9K_INT_RXORN = 0x00000020,
+	ATH9K_INT_TX = 0x00000040,
+	ATH9K_INT_TXDESC = 0x00000080,
+	ATH9K_INT_TIM_TIMER = 0x00000100,
+	ATH9K_INT_TXURN = 0x00000800,
+	ATH9K_INT_MIB = 0x00001000,
+	ATH9K_INT_RXPHY = 0x00004000,
+	ATH9K_INT_RXKCM = 0x00008000,
+	ATH9K_INT_SWBA = 0x00010000,
+	ATH9K_INT_BMISS = 0x00040000,
+	ATH9K_INT_BNR = 0x00100000,
+	ATH9K_INT_TIM = 0x00200000,
+	ATH9K_INT_DTIM = 0x00400000,
+	ATH9K_INT_DTIMSYNC = 0x00800000,
+	ATH9K_INT_GPIO = 0x01000000,
+	ATH9K_INT_CABEND = 0x02000000,
+	ATH9K_INT_TSFOOR = 0x04000000,
+	ATH9K_INT_CST = 0x10000000,
+	ATH9K_INT_GTT = 0x20000000,
+	ATH9K_INT_FATAL = 0x40000000,
+	ATH9K_INT_GLOBAL = 0x80000000,
+	ATH9K_INT_BMISC = ATH9K_INT_TIM |
+		ATH9K_INT_DTIM |
+		ATH9K_INT_DTIMSYNC |
+		ATH9K_INT_TSFOOR |
+		ATH9K_INT_CABEND,
+	ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
+		ATH9K_INT_RXDESC |
+		ATH9K_INT_RXEOL |
+		ATH9K_INT_RXORN |
+		ATH9K_INT_TXURN |
+		ATH9K_INT_TXDESC |
+		ATH9K_INT_MIB |
+		ATH9K_INT_RXPHY |
+		ATH9K_INT_RXKCM |
+		ATH9K_INT_SWBA |
+		ATH9K_INT_BMISS |
+		ATH9K_INT_GPIO,
+	ATH9K_INT_NOCARD = 0xffffffff
+};
+
+#define CHANNEL_CW_INT    0x00002
+#define CHANNEL_CCK       0x00020
+#define CHANNEL_OFDM      0x00040
+#define CHANNEL_2GHZ      0x00080
+#define CHANNEL_5GHZ      0x00100
+#define CHANNEL_PASSIVE   0x00200
+#define CHANNEL_DYN       0x00400
+#define CHANNEL_HALF      0x04000
+#define CHANNEL_QUARTER   0x08000
+#define CHANNEL_HT20      0x10000
+#define CHANNEL_HT40PLUS  0x20000
+#define CHANNEL_HT40MINUS 0x40000
+
+#define CHANNEL_A           (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B           (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_G           (CHANNEL_2GHZ|CHANNEL_OFDM)
+#define CHANNEL_G_HT20      (CHANNEL_2GHZ|CHANNEL_HT20)
+#define CHANNEL_A_HT20      (CHANNEL_5GHZ|CHANNEL_HT20)
+#define CHANNEL_G_HT40PLUS  (CHANNEL_2GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_A_HT40PLUS  (CHANNEL_5GHZ|CHANNEL_HT40PLUS)
+#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS)
+#define CHANNEL_ALL				\
+	(CHANNEL_OFDM|				\
+	 CHANNEL_CCK|				\
+	 CHANNEL_2GHZ |				\
+	 CHANNEL_5GHZ |				\
+	 CHANNEL_HT20 |				\
+	 CHANNEL_HT40PLUS |			\
+	 CHANNEL_HT40MINUS)
+
+struct ath9k_channel {
+	struct ieee80211_channel *chan;
+	u16 channel;
+	u32 channelFlags;
+	u32 chanmode;
+	int32_t CalValid;
+	bool oneTimeCalsDone;
+	int8_t iCoff;
+	int8_t qCoff;
+	int16_t rawNoiseFloor;
+};
+
+#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
+       (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
+       (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
+       (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
+#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
+#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
+#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
+#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
+#define IS_CHAN_A_5MHZ_SPACED(_c)			\
+	((((_c)->channelFlags & CHANNEL_5GHZ) != 0) &&	\
+	 (((_c)->channel % 20) != 0) &&			\
+	 (((_c)->channel % 10) != 0))
+
+/* These macros check chanmode and not channelFlags */
+#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
+#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) ||	\
+			  ((_c)->chanmode == CHANNEL_G_HT20))
+#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) ||	\
+			  ((_c)->chanmode == CHANNEL_A_HT40MINUS) ||	\
+			  ((_c)->chanmode == CHANNEL_G_HT40PLUS) ||	\
+			  ((_c)->chanmode == CHANNEL_G_HT40MINUS))
+#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
+
+enum ath9k_power_mode {
+	ATH9K_PM_AWAKE = 0,
+	ATH9K_PM_FULL_SLEEP,
+	ATH9K_PM_NETWORK_SLEEP,
+	ATH9K_PM_UNDEFINED
+};
+
+enum ath9k_ant_setting {
+	ATH9K_ANT_VARIABLE = 0,
+	ATH9K_ANT_FIXED_A,
+	ATH9K_ANT_FIXED_B
+};
+
+enum ath9k_tp_scale {
+	ATH9K_TP_SCALE_MAX = 0,
+	ATH9K_TP_SCALE_50,
+	ATH9K_TP_SCALE_25,
+	ATH9K_TP_SCALE_12,
+	ATH9K_TP_SCALE_MIN
+};
+
+enum ser_reg_mode {
+	SER_REG_MODE_OFF = 0,
+	SER_REG_MODE_ON = 1,
+	SER_REG_MODE_AUTO = 2,
+};
+
+struct ath9k_beacon_state {
+	u32 bs_nexttbtt;
+	u32 bs_nextdtim;
+	u32 bs_intval;
+#define ATH9K_BEACON_PERIOD       0x0000ffff
+#define ATH9K_BEACON_ENA          0x00800000
+#define ATH9K_BEACON_RESET_TSF    0x01000000
+#define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */
+	u32 bs_dtimperiod;
+	u16 bs_cfpperiod;
+	u16 bs_cfpmaxduration;
+	u32 bs_cfpnext;
+	u16 bs_timoffset;
+	u16 bs_bmissthreshold;
+	u32 bs_sleepduration;
+	u32 bs_tsfoor_threshold;
+};
+
+struct chan_centers {
+	u16 synth_center;
+	u16 ctl_center;
+	u16 ext_center;
+};
+
+enum {
+	ATH9K_RESET_POWER_ON,
+	ATH9K_RESET_WARM,
+	ATH9K_RESET_COLD,
+};
+
+struct ath9k_hw_version {
+	u32 magic;
+	u16 devid;
+	u16 subvendorid;
+	u32 macVersion;
+	u16 macRev;
+	u16 phyRev;
+	u16 analog5GhzRev;
+	u16 analog2GhzRev;
+};
+
+struct ath_hw {
+	struct ath_softc *ah_sc;
+	struct ath9k_hw_version hw_version;
+	struct ath9k_ops_config config;
+	struct ath9k_hw_capabilities caps;
+	struct ath_regulatory regulatory;
+	struct ath9k_channel channels[38];
+	struct ath9k_channel *curchan;
+
+	union {
+		struct ar5416_eeprom_def def;
+		struct ar5416_eeprom_4k map4k;
+	} eeprom;
+	const struct eeprom_ops *eep_ops;
+	enum ath9k_eep_map eep_map;
+
+	bool sw_mgmt_crypto;
+	bool is_pciexpress;
+	u8 macaddr[ETH_ALEN];
+	u16 tx_trig_level;
+	u16 rfsilent;
+	u32 rfkill_gpio;
+	u32 rfkill_polarity;
+	u32 btactive_gpio;
+	u32 wlanactive_gpio;
+	u32 ah_flags;
+
+	enum nl80211_iftype opmode;
+	enum ath9k_power_mode power_mode;
+	enum ath9k_power_mode restore_mode;
+
+	struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
+	struct ar5416Stats stats;
+	struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+
+	int16_t curchan_rad_index;
+	u32 mask_reg;
+	u32 txok_interrupt_mask;
+	u32 txerr_interrupt_mask;
+	u32 txdesc_interrupt_mask;
+	u32 txeol_interrupt_mask;
+	u32 txurn_interrupt_mask;
+	bool chip_fullsleep;
+	u32 atim_window;
+	u16 antenna_switch_swap;
+	enum ath9k_ant_setting diversity_control;
+
+	/* Calibration */
+	enum ath9k_cal_types supp_cals;
+	struct ath9k_cal_list iq_caldata;
+	struct ath9k_cal_list adcgain_caldata;
+	struct ath9k_cal_list adcdc_calinitdata;
+	struct ath9k_cal_list adcdc_caldata;
+	struct ath9k_cal_list *cal_list;
+	struct ath9k_cal_list *cal_list_last;
+	struct ath9k_cal_list *cal_list_curr;
+#define totalPowerMeasI meas0.unsign
+#define totalPowerMeasQ meas1.unsign
+#define totalIqCorrMeas meas2.sign
+#define totalAdcIOddPhase  meas0.unsign
+#define totalAdcIEvenPhase meas1.unsign
+#define totalAdcQOddPhase  meas2.unsign
+#define totalAdcQEvenPhase meas3.unsign
+#define totalAdcDcOffsetIOddPhase  meas0.sign
+#define totalAdcDcOffsetIEvenPhase meas1.sign
+#define totalAdcDcOffsetQOddPhase  meas2.sign
+#define totalAdcDcOffsetQEvenPhase meas3.sign
+	union {
+		u32 unsign[AR5416_MAX_CHAINS];
+		int32_t sign[AR5416_MAX_CHAINS];
+	} meas0;
+	union {
+		u32 unsign[AR5416_MAX_CHAINS];
+		int32_t sign[AR5416_MAX_CHAINS];
+	} meas1;
+	union {
+		u32 unsign[AR5416_MAX_CHAINS];
+		int32_t sign[AR5416_MAX_CHAINS];
+	} meas2;
+	union {
+		u32 unsign[AR5416_MAX_CHAINS];
+		int32_t sign[AR5416_MAX_CHAINS];
+	} meas3;
+	u16 cal_samples;
+
+	u32 sta_id1_defaults;
+	u32 misc_mode;
+	enum {
+		AUTO_32KHZ,
+		USE_32KHZ,
+		DONT_USE_32KHZ,
+	} enable_32kHz_clock;
+
+	/* RF */
+	u32 *analogBank0Data;
+	u32 *analogBank1Data;
+	u32 *analogBank2Data;
+	u32 *analogBank3Data;
+	u32 *analogBank6Data;
+	u32 *analogBank6TPCData;
+	u32 *analogBank7Data;
+	u32 *addac5416_21;
+	u32 *bank6Temp;
+
+	int16_t txpower_indexoffset;
+	u32 beacon_interval;
+	u32 slottime;
+	u32 acktimeout;
+	u32 ctstimeout;
+	u32 globaltxtimeout;
+	u8 gbeacon_rate;
+
+	/* ANI */
+	u32 proc_phyerr;
+	bool has_hw_phycounters;
+	u32 aniperiod;
+	struct ar5416AniState *curani;
+	struct ar5416AniState ani[255];
+	int totalSizeDesired[5];
+	int coarse_high[5];
+	int coarse_low[5];
+	int firpwr[5];
+	enum ath9k_ani_cmd ani_function;
+
+	u32 intr_txqs;
+	enum ath9k_ht_extprotspacing extprotspacing;
+	u8 txchainmask;
+	u8 rxchainmask;
+
+	u32 originalGain[22];
+	int initPDADC;
+	int PDADCdelta;
+
+	struct ar5416IniArray iniModes;
+	struct ar5416IniArray iniCommon;
+	struct ar5416IniArray iniBank0;
+	struct ar5416IniArray iniBB_RfGain;
+	struct ar5416IniArray iniBank1;
+	struct ar5416IniArray iniBank2;
+	struct ar5416IniArray iniBank3;
+	struct ar5416IniArray iniBank6;
+	struct ar5416IniArray iniBank6TPC;
+	struct ar5416IniArray iniBank7;
+	struct ar5416IniArray iniAddac;
+	struct ar5416IniArray iniPcieSerdes;
+	struct ar5416IniArray iniModesAdditional;
+	struct ar5416IniArray iniModesRxGain;
+	struct ar5416IniArray iniModesTxGain;
+};
+
+/* Attach, Detach, Reset */
+const char *ath9k_hw_probe(u16 vendorid, u16 devid);
+void ath9k_hw_detach(struct ath_hw *ah);
+struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error);
+void ath9k_hw_rfdetach(struct ath_hw *ah);
+int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+		   bool bChannelChange);
+void ath9k_hw_fill_cap_info(struct ath_hw *ah);
+bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 *result);
+bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
+			    u32 capability, u32 setting, int *status);
+
+/* Key Cache Management */
+bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
+bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac);
+bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
+				 const struct ath9k_keyval *k,
+				 const u8 *mac);
+bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry);
+
+/* GPIO / RFKILL / Antennae */
+void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
+u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
+void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
+			 u32 ah_signal_type);
+void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
+u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
+void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
+bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
+			       enum ath9k_ant_setting settings,
+			       struct ath9k_channel *chan,
+			       u8 *tx_chainmask, u8 *rx_chainmask,
+			       u8 *antenna_cfgd);
+
+/* General Operation */
+bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
+u32 ath9k_hw_reverse_bits(u32 val, u32 n);
+bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high);
+u16 ath9k_hw_computetxtime(struct ath_hw *ah,
+			   const struct ath_rate_table *rates,
+			   u32 frameLen, u16 rateix, bool shortPreamble);
+void ath9k_hw_get_channel_centers(struct ath_hw *ah,
+				  struct ath9k_channel *chan,
+				  struct chan_centers *centers);
+u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
+void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
+bool ath9k_hw_phy_disable(struct ath_hw *ah);
+bool ath9k_hw_disable(struct ath_hw *ah);
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
+void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac);
+void ath9k_hw_setopmode(struct ath_hw *ah);
+void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
+void ath9k_hw_setbssidmask(struct ath_softc *sc);
+void ath9k_hw_write_associd(struct ath_softc *sc);
+u64 ath9k_hw_gettsf64(struct ath_hw *ah);
+void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
+void ath9k_hw_reset_tsf(struct ath_hw *ah);
+bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
+bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
+void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode);
+void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
+void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
+				    const struct ath9k_beacon_state *bs);
+bool ath9k_hw_setpower(struct ath_hw *ah,
+		       enum ath9k_power_mode mode);
+void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore);
+
+/* Interrupt Handling */
+bool ath9k_hw_intrpend(struct ath_hw *ah);
+bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked);
+enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah);
+enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
+
+void ath9k_hw_btcoex_enable(struct ath_hw *ah);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/initvals.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/initvals.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/initvals.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/initvals.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,4848 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+static const u32 ar5416Modes[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
+    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
+    { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 },
+    { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b },
+    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
+    { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+    { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+    { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
+    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
+    { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
+    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
+    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
+    { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
+    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
+    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
+    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
+    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
+    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
+    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const u32 ar5416Common[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00007010, 0x00000000 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0xffffffff },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00070000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a002e },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x05100000 },
+    { 0x0000a920, 0x05100000 },
+    { 0x0000b920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280b212 },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5d50e188 },
+    { 0x00009958, 0x00081fff },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x0000c968, 0x000003ce },
+    { 0x00009970, 0x190fb515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x001fff00 },
+    { 0x000099ac, 0x00000000 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000200 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x000000aa },
+    { 0x000099fc, 0x00001042 },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009b9c, 0x00000033 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+    { 0x0000a210, 0x40806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x00000bb5 },
+    { 0x0000a22c, 0x00000011 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000c26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x051701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa1f },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x08000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+};
+
+static const u32 ar5416Bank0[][2] = {
+    { 0x000098b0, 0x1e5795e5 },
+    { 0x000098e0, 0x02008020 },
+};
+
+static const u32 ar5416BB_RfGain[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000141 },
+    { 0x00009a10, 0x000001e1, 0x00000181 },
+    { 0x00009a14, 0x00000021, 0x000001c1 },
+    { 0x00009a18, 0x00000061, 0x00000001 },
+    { 0x00009a1c, 0x00000168, 0x00000041 },
+    { 0x00009a20, 0x000001a8, 0x000001a8 },
+    { 0x00009a24, 0x000001e8, 0x000001e8 },
+    { 0x00009a28, 0x00000028, 0x00000028 },
+    { 0x00009a2c, 0x00000068, 0x00000068 },
+    { 0x00009a30, 0x00000189, 0x000000a8 },
+    { 0x00009a34, 0x000001c9, 0x00000169 },
+    { 0x00009a38, 0x00000009, 0x000001a9 },
+    { 0x00009a3c, 0x00000049, 0x000001e9 },
+    { 0x00009a40, 0x00000089, 0x00000029 },
+    { 0x00009a44, 0x00000170, 0x00000069 },
+    { 0x00009a48, 0x000001b0, 0x00000190 },
+    { 0x00009a4c, 0x000001f0, 0x000001d0 },
+    { 0x00009a50, 0x00000030, 0x00000010 },
+    { 0x00009a54, 0x00000070, 0x00000050 },
+    { 0x00009a58, 0x00000191, 0x00000090 },
+    { 0x00009a5c, 0x000001d1, 0x00000151 },
+    { 0x00009a60, 0x00000011, 0x00000191 },
+    { 0x00009a64, 0x00000051, 0x000001d1 },
+    { 0x00009a68, 0x00000091, 0x00000011 },
+    { 0x00009a6c, 0x000001b8, 0x00000051 },
+    { 0x00009a70, 0x000001f8, 0x00000198 },
+    { 0x00009a74, 0x00000038, 0x000001d8 },
+    { 0x00009a78, 0x00000078, 0x00000018 },
+    { 0x00009a7c, 0x00000199, 0x00000058 },
+    { 0x00009a80, 0x000001d9, 0x00000098 },
+    { 0x00009a84, 0x00000019, 0x00000159 },
+    { 0x00009a88, 0x00000059, 0x00000199 },
+    { 0x00009a8c, 0x00000099, 0x000001d9 },
+    { 0x00009a90, 0x000000d9, 0x00000019 },
+    { 0x00009a94, 0x000000f9, 0x00000059 },
+    { 0x00009a98, 0x000000f9, 0x00000099 },
+    { 0x00009a9c, 0x000000f9, 0x000000d9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const u32 ar5416Bank1[][2] = {
+    { 0x000098b0, 0x02108421 },
+    { 0x000098ec, 0x00000008 },
+};
+
+static const u32 ar5416Bank2[][2] = {
+    { 0x000098b0, 0x0e73ff17 },
+    { 0x000098e0, 0x00000420 },
+};
+
+static const u32 ar5416Bank3[][3] = {
+    { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+static const u32 ar5416Bank6[][3] = {
+
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x004210a2, 0x004210a2 },
+    { 0x0000989c, 0x0014008f, 0x0014008f },
+    { 0x0000989c, 0x00c40003, 0x00c40003 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000f1, 0x000000f1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const u32 ar5416Bank6TPC[][3] = {
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x00423022, 0x00423022 },
+    { 0x0000989c, 0x201400df, 0x201400df },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000e1, 0x000000e1 },
+    { 0x0000989c, 0x00007081, 0x00007081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const u32 ar5416Bank7[][2] = {
+    { 0x0000989c, 0x00000500 },
+    { 0x0000989c, 0x00000800 },
+    { 0x000098cc, 0x0000000e },
+};
+
+static const u32 ar5416Addac[][2] = {
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000003 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x0000000c },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000030 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000060 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000058 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x000098cc,  0x00000000 },
+};
+
+static const u32 ar5416Modes_9100[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
+    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d },
+    { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 },
+    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
+    { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e },
+    { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff },
+#ifdef TB243
+    { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
+    { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 },
+#else
+    { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
+    { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
+    { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
+    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
+#endif
+    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 },
+    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
+    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
+    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
+    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
+    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
+    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
+    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
+    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
+    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const u32 ar5416Common_9100[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00020010, 0x00000003 },
+    { 0x00020038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00004000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0x00000000 },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00000000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a01ae },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x05100000 },
+    { 0x0000a920, 0x05100000 },
+    { 0x0000b920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280b212 },
+    { 0x0000994c, 0x00020028 },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x0000c968, 0x000003ce },
+    { 0x00009970, 0x190fb515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x006f0000 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000200 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099fc, 0x00001042 },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009b9c, 0x00000033 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+    { 0x0000a210, 0x40806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x001a0bb5 },
+    { 0x0000a22c, 0x00000000 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889ae },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000a000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000001 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000c26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x050701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79a8aa33 },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+};
+
+static const u32 ar5416Bank0_9100[][2] = {
+    { 0x000098b0, 0x1e5795e5 },
+    { 0x000098e0, 0x02008020 },
+};
+
+static const u32 ar5416BB_RfGain_9100[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000141 },
+    { 0x00009a10, 0x000001e1, 0x00000181 },
+    { 0x00009a14, 0x00000021, 0x000001c1 },
+    { 0x00009a18, 0x00000061, 0x00000001 },
+    { 0x00009a1c, 0x00000168, 0x00000041 },
+    { 0x00009a20, 0x000001a8, 0x000001a8 },
+    { 0x00009a24, 0x000001e8, 0x000001e8 },
+    { 0x00009a28, 0x00000028, 0x00000028 },
+    { 0x00009a2c, 0x00000068, 0x00000068 },
+    { 0x00009a30, 0x00000189, 0x000000a8 },
+    { 0x00009a34, 0x000001c9, 0x00000169 },
+    { 0x00009a38, 0x00000009, 0x000001a9 },
+    { 0x00009a3c, 0x00000049, 0x000001e9 },
+    { 0x00009a40, 0x00000089, 0x00000029 },
+    { 0x00009a44, 0x00000170, 0x00000069 },
+    { 0x00009a48, 0x000001b0, 0x00000190 },
+    { 0x00009a4c, 0x000001f0, 0x000001d0 },
+    { 0x00009a50, 0x00000030, 0x00000010 },
+    { 0x00009a54, 0x00000070, 0x00000050 },
+    { 0x00009a58, 0x00000191, 0x00000090 },
+    { 0x00009a5c, 0x000001d1, 0x00000151 },
+    { 0x00009a60, 0x00000011, 0x00000191 },
+    { 0x00009a64, 0x00000051, 0x000001d1 },
+    { 0x00009a68, 0x00000091, 0x00000011 },
+    { 0x00009a6c, 0x000001b8, 0x00000051 },
+    { 0x00009a70, 0x000001f8, 0x00000198 },
+    { 0x00009a74, 0x00000038, 0x000001d8 },
+    { 0x00009a78, 0x00000078, 0x00000018 },
+    { 0x00009a7c, 0x00000199, 0x00000058 },
+    { 0x00009a80, 0x000001d9, 0x00000098 },
+    { 0x00009a84, 0x00000019, 0x00000159 },
+    { 0x00009a88, 0x00000059, 0x00000199 },
+    { 0x00009a8c, 0x00000099, 0x000001d9 },
+    { 0x00009a90, 0x000000d9, 0x00000019 },
+    { 0x00009a94, 0x000000f9, 0x00000059 },
+    { 0x00009a98, 0x000000f9, 0x00000099 },
+    { 0x00009a9c, 0x000000f9, 0x000000d9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const u32 ar5416Bank1_9100[][2] = {
+    { 0x000098b0, 0x02108421},
+    { 0x000098ec, 0x00000008},
+};
+
+static const u32 ar5416Bank2_9100[][2] = {
+    { 0x000098b0, 0x0e73ff17},
+    { 0x000098e0, 0x00000420},
+};
+
+static const u32 ar5416Bank3_9100[][3] = {
+    { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+static const u32 ar5416Bank6_9100[][3] = {
+
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x004210a2, 0x004210a2 },
+    { 0x0000989c, 0x0014000f, 0x0014000f },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x000180d6, 0x000180d6 },
+    { 0x0000989c, 0x0000c0aa, 0x0000c0aa },
+    { 0x0000989c, 0x000000b1, 0x000000b1 },
+    { 0x0000989c, 0x00002000, 0x00002000 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+
+static const u32 ar5416Bank6TPC_9100[][3] = {
+
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x00423022, 0x00423022 },
+    { 0x0000989c, 0x2014008f, 0x2014008f },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000e1, 0x000000e1 },
+    { 0x0000989c, 0x00007080, 0x00007080 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const u32 ar5416Bank7_9100[][2] = {
+    { 0x0000989c, 0x00000500 },
+    { 0x0000989c, 0x00000800 },
+    { 0x000098cc, 0x0000000e },
+};
+
+static const u32 ar5416Addac_9100[][2] = {
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000010 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x000000c0 },
+    {0x0000989c, 0x00000015 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x0000989c, 0x00000000 },
+    {0x000098cc, 0x00000000 },
+};
+
+static const u32 ar5416Modes_9160[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
+    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
+    { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
+    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
+    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
+    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
+    { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
+    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
+    { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
+    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 },
+    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
+    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
+    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
+    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
+    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
+    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
+    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
+    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
+    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
+    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
+    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
+    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
+    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
+    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static const u32 ar5416Common_9160[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00007010, 0x00000020 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0xffffffff },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00ff0000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xad848e19 },
+    { 0x00009810, 0x7d14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a01ae },
+    { 0x0000984c, 0x1284233c },
+    { 0x00009854, 0x00000859 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x05100000 },
+    { 0x0000a920, 0x05100000 },
+    { 0x0000b920, 0x05100000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280b212 },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5f3ca3de },
+    { 0x00009958, 0x2108ecff },
+    { 0x00009940, 0x00750604 },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x00009970, 0x190fb515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x006f0000 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000200 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099fc, 0x00001042 },
+    { 0x00009b00, 0x00000000 },
+    { 0x00009b04, 0x00000001 },
+    { 0x00009b08, 0x00000002 },
+    { 0x00009b0c, 0x00000003 },
+    { 0x00009b10, 0x00000004 },
+    { 0x00009b14, 0x00000005 },
+    { 0x00009b18, 0x00000008 },
+    { 0x00009b1c, 0x00000009 },
+    { 0x00009b20, 0x0000000a },
+    { 0x00009b24, 0x0000000b },
+    { 0x00009b28, 0x0000000c },
+    { 0x00009b2c, 0x0000000d },
+    { 0x00009b30, 0x00000010 },
+    { 0x00009b34, 0x00000011 },
+    { 0x00009b38, 0x00000012 },
+    { 0x00009b3c, 0x00000013 },
+    { 0x00009b40, 0x00000014 },
+    { 0x00009b44, 0x00000015 },
+    { 0x00009b48, 0x00000018 },
+    { 0x00009b4c, 0x00000019 },
+    { 0x00009b50, 0x0000001a },
+    { 0x00009b54, 0x0000001b },
+    { 0x00009b58, 0x0000001c },
+    { 0x00009b5c, 0x0000001d },
+    { 0x00009b60, 0x00000020 },
+    { 0x00009b64, 0x00000021 },
+    { 0x00009b68, 0x00000022 },
+    { 0x00009b6c, 0x00000023 },
+    { 0x00009b70, 0x00000024 },
+    { 0x00009b74, 0x00000025 },
+    { 0x00009b78, 0x00000028 },
+    { 0x00009b7c, 0x00000029 },
+    { 0x00009b80, 0x0000002a },
+    { 0x00009b84, 0x0000002b },
+    { 0x00009b88, 0x0000002c },
+    { 0x00009b8c, 0x0000002d },
+    { 0x00009b90, 0x00000030 },
+    { 0x00009b94, 0x00000031 },
+    { 0x00009b98, 0x00000032 },
+    { 0x00009b9c, 0x00000033 },
+    { 0x00009ba0, 0x00000034 },
+    { 0x00009ba4, 0x00000035 },
+    { 0x00009ba8, 0x00000035 },
+    { 0x00009bac, 0x00000035 },
+    { 0x00009bb0, 0x00000035 },
+    { 0x00009bb4, 0x00000035 },
+    { 0x00009bb8, 0x00000035 },
+    { 0x00009bbc, 0x00000035 },
+    { 0x00009bc0, 0x00000035 },
+    { 0x00009bc4, 0x00000035 },
+    { 0x00009bc8, 0x00000035 },
+    { 0x00009bcc, 0x00000035 },
+    { 0x00009bd0, 0x00000035 },
+    { 0x00009bd4, 0x00000035 },
+    { 0x00009bd8, 0x00000035 },
+    { 0x00009bdc, 0x00000035 },
+    { 0x00009be0, 0x00000035 },
+    { 0x00009be4, 0x00000035 },
+    { 0x00009be8, 0x00000035 },
+    { 0x00009bec, 0x00000035 },
+    { 0x00009bf0, 0x00000035 },
+    { 0x00009bf4, 0x00000035 },
+    { 0x00009bf8, 0x00000010 },
+    { 0x00009bfc, 0x0000001a },
+    { 0x0000a210, 0x40806333 },
+    { 0x0000a214, 0x00106c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x018830c6 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x001a0bb5 },
+    { 0x0000a22c, 0x00000000 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x0000e000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cc75380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000001 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000c26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x050701ce },
+    { 0x0000a338, 0x00000000 },
+    { 0x0000a33c, 0x00000000 },
+    { 0x0000a340, 0x00000000 },
+    { 0x0000a344, 0x00000000 },
+    { 0x0000a348, 0x3fffffff },
+    { 0x0000a34c, 0x3fffffff },
+    { 0x0000a350, 0x3fffffff },
+    { 0x0000a354, 0x0003ffff },
+    { 0x0000a358, 0x79bfaa03 },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+};
+
+static const u32 ar5416Bank0_9160[][2] = {
+    { 0x000098b0, 0x1e5795e5 },
+    { 0x000098e0, 0x02008020 },
+};
+
+static const u32 ar5416BB_RfGain_9160[][3] = {
+    { 0x00009a00, 0x00000000, 0x00000000 },
+    { 0x00009a04, 0x00000040, 0x00000040 },
+    { 0x00009a08, 0x00000080, 0x00000080 },
+    { 0x00009a0c, 0x000001a1, 0x00000141 },
+    { 0x00009a10, 0x000001e1, 0x00000181 },
+    { 0x00009a14, 0x00000021, 0x000001c1 },
+    { 0x00009a18, 0x00000061, 0x00000001 },
+    { 0x00009a1c, 0x00000168, 0x00000041 },
+    { 0x00009a20, 0x000001a8, 0x000001a8 },
+    { 0x00009a24, 0x000001e8, 0x000001e8 },
+    { 0x00009a28, 0x00000028, 0x00000028 },
+    { 0x00009a2c, 0x00000068, 0x00000068 },
+    { 0x00009a30, 0x00000189, 0x000000a8 },
+    { 0x00009a34, 0x000001c9, 0x00000169 },
+    { 0x00009a38, 0x00000009, 0x000001a9 },
+    { 0x00009a3c, 0x00000049, 0x000001e9 },
+    { 0x00009a40, 0x00000089, 0x00000029 },
+    { 0x00009a44, 0x00000170, 0x00000069 },
+    { 0x00009a48, 0x000001b0, 0x00000190 },
+    { 0x00009a4c, 0x000001f0, 0x000001d0 },
+    { 0x00009a50, 0x00000030, 0x00000010 },
+    { 0x00009a54, 0x00000070, 0x00000050 },
+    { 0x00009a58, 0x00000191, 0x00000090 },
+    { 0x00009a5c, 0x000001d1, 0x00000151 },
+    { 0x00009a60, 0x00000011, 0x00000191 },
+    { 0x00009a64, 0x00000051, 0x000001d1 },
+    { 0x00009a68, 0x00000091, 0x00000011 },
+    { 0x00009a6c, 0x000001b8, 0x00000051 },
+    { 0x00009a70, 0x000001f8, 0x00000198 },
+    { 0x00009a74, 0x00000038, 0x000001d8 },
+    { 0x00009a78, 0x00000078, 0x00000018 },
+    { 0x00009a7c, 0x00000199, 0x00000058 },
+    { 0x00009a80, 0x000001d9, 0x00000098 },
+    { 0x00009a84, 0x00000019, 0x00000159 },
+    { 0x00009a88, 0x00000059, 0x00000199 },
+    { 0x00009a8c, 0x00000099, 0x000001d9 },
+    { 0x00009a90, 0x000000d9, 0x00000019 },
+    { 0x00009a94, 0x000000f9, 0x00000059 },
+    { 0x00009a98, 0x000000f9, 0x00000099 },
+    { 0x00009a9c, 0x000000f9, 0x000000d9 },
+    { 0x00009aa0, 0x000000f9, 0x000000f9 },
+    { 0x00009aa4, 0x000000f9, 0x000000f9 },
+    { 0x00009aa8, 0x000000f9, 0x000000f9 },
+    { 0x00009aac, 0x000000f9, 0x000000f9 },
+    { 0x00009ab0, 0x000000f9, 0x000000f9 },
+    { 0x00009ab4, 0x000000f9, 0x000000f9 },
+    { 0x00009ab8, 0x000000f9, 0x000000f9 },
+    { 0x00009abc, 0x000000f9, 0x000000f9 },
+    { 0x00009ac0, 0x000000f9, 0x000000f9 },
+    { 0x00009ac4, 0x000000f9, 0x000000f9 },
+    { 0x00009ac8, 0x000000f9, 0x000000f9 },
+    { 0x00009acc, 0x000000f9, 0x000000f9 },
+    { 0x00009ad0, 0x000000f9, 0x000000f9 },
+    { 0x00009ad4, 0x000000f9, 0x000000f9 },
+    { 0x00009ad8, 0x000000f9, 0x000000f9 },
+    { 0x00009adc, 0x000000f9, 0x000000f9 },
+    { 0x00009ae0, 0x000000f9, 0x000000f9 },
+    { 0x00009ae4, 0x000000f9, 0x000000f9 },
+    { 0x00009ae8, 0x000000f9, 0x000000f9 },
+    { 0x00009aec, 0x000000f9, 0x000000f9 },
+    { 0x00009af0, 0x000000f9, 0x000000f9 },
+    { 0x00009af4, 0x000000f9, 0x000000f9 },
+    { 0x00009af8, 0x000000f9, 0x000000f9 },
+    { 0x00009afc, 0x000000f9, 0x000000f9 },
+};
+
+static const u32 ar5416Bank1_9160[][2] = {
+    { 0x000098b0, 0x02108421 },
+    { 0x000098ec, 0x00000008 },
+};
+
+static const u32 ar5416Bank2_9160[][2] = {
+    { 0x000098b0, 0x0e73ff17 },
+    { 0x000098e0, 0x00000420 },
+};
+
+static const u32 ar5416Bank3_9160[][3] = {
+    { 0x000098f0, 0x01400018, 0x01c00018 },
+};
+
+static const u32 ar5416Bank6_9160[][3] = {
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x004210a2, 0x004210a2 },
+    { 0x0000989c, 0x0014008f, 0x0014008f },
+    { 0x0000989c, 0x00c40003, 0x00c40003 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000f1, 0x000000f1 },
+    { 0x0000989c, 0x00002081, 0x00002081 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const u32 ar5416Bank6TPC_9160[][3] = {
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00000000, 0x00000000 },
+    { 0x0000989c, 0x00e00000, 0x00e00000 },
+    { 0x0000989c, 0x005e0000, 0x005e0000 },
+    { 0x0000989c, 0x00120000, 0x00120000 },
+    { 0x0000989c, 0x00620000, 0x00620000 },
+    { 0x0000989c, 0x00020000, 0x00020000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
+    { 0x0000989c, 0x005f0000, 0x005f0000 },
+    { 0x0000989c, 0x00870000, 0x00870000 },
+    { 0x0000989c, 0x00f90000, 0x00f90000 },
+    { 0x0000989c, 0x007b0000, 0x007b0000 },
+    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
+    { 0x0000989c, 0x00f50000, 0x00f50000 },
+    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
+    { 0x0000989c, 0x00110000, 0x00110000 },
+    { 0x0000989c, 0x006100a8, 0x006100a8 },
+    { 0x0000989c, 0x00423022, 0x00423022 },
+    { 0x0000989c, 0x2014008f, 0x2014008f },
+    { 0x0000989c, 0x00c40002, 0x00c40002 },
+    { 0x0000989c, 0x003000f2, 0x003000f2 },
+    { 0x0000989c, 0x00440016, 0x00440016 },
+    { 0x0000989c, 0x00410040, 0x00410040 },
+    { 0x0000989c, 0x0001805e, 0x0001805e },
+    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
+    { 0x0000989c, 0x000000e1, 0x000000e1 },
+    { 0x0000989c, 0x00007080, 0x00007080 },
+    { 0x0000989c, 0x000000d4, 0x000000d4 },
+    { 0x000098d0, 0x0000000f, 0x0010000f },
+};
+
+static const u32 ar5416Bank7_9160[][2] = {
+    { 0x0000989c, 0x00000500 },
+    { 0x0000989c, 0x00000800 },
+    { 0x000098cc, 0x0000000e },
+};
+
+static u32 ar5416Addac_9160[][2] = {
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000018 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000019 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000003 },
+    {0x0000989c,  0x00000008 },
+    {0x0000989c,  0x00000000 },
+    {0x000098cc,  0x00000000 },
+};
+
+static u32 ar5416Addac_91601_1[][2] = {
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000018 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x000000c0 },
+    {0x0000989c,  0x00000019 },
+    {0x0000989c,  0x00000004 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x0000989c,  0x00000000 },
+    {0x000098cc,  0x00000000 },
+};
+
+/* XXX 9280 1 */
+static const u32 ar9280Modes_9280[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 },
+    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
+    { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
+    { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
+    { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
+    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+    { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 },
+    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 },
+    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+    { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 },
+    { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+    { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+    { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
+    { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a },
+    { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 },
+    { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 },
+    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 },
+    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 },
+    { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c },
+    { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 },
+    { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 },
+    { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 },
+    { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac },
+    { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 },
+    { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 },
+    { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 },
+    { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 },
+    { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 },
+    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 },
+    { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 },
+    { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 },
+    { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac },
+    { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 },
+    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 },
+    { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 },
+    { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 },
+    { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 },
+    { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad },
+    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
+    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
+    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
+    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
+    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
+    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
+    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
+    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
+    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
+    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
+    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
+    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
+    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
+    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
+    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
+    { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
+    { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
+    { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
+    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
+    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
+    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
+    { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
+    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
+    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
+    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
+    { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
+    { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
+    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
+    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
+    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
+    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
+    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
+    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
+    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
+    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
+    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
+    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
+    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
+    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
+    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
+    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
+    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
+    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
+    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
+    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
+    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
+    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
+    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
+    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
+    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
+    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
+    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
+    { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 },
+    { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
+    { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
+    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
+    { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
+    { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
+    { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
+    { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
+    { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
+    { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
+    { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
+    { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
+    { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
+    { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
+    { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
+    { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
+    { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
+    { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
+    { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
+    { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
+    { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
+    { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
+    { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
+    { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
+    { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c },
+    { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 },
+    { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 },
+    { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 },
+};
+
+static const u32 ar9280Common_9280[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00004024, 0x0000001f },
+    { 0x00007010, 0x00000033 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x00008070, 0x00000000 },
+    { 0x000080c0, 0x2a82301a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0x00000000 },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c4, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x00008300, 0x00000000 },
+    { 0x00008304, 0x00000000 },
+    { 0x00008308, 0x00000000 },
+    { 0x0000830c, 0x00000000 },
+    { 0x00008310, 0x00000000 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008318, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00000000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00008344, 0x00000000 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xaf268e30 },
+    { 0x00009810, 0xfd14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x00009840, 0x206a01ae },
+    { 0x0000984c, 0x0040233c },
+    { 0x0000a84c, 0x0040233c },
+    { 0x00009854, 0x00000044 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x04900000 },
+    { 0x0000a920, 0x04900000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280c00a },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0xe250a51e },
+    { 0x00009958, 0x3388ffff },
+    { 0x00009940, 0x00781204 },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x0000c968, 0x000003ce },
+    { 0x00009970, 0x190fb514 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x006f00c4 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099b4, 0x00000820 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099fc, 0x00001042 },
+    { 0x0000a210, 0x4080a333 },
+    { 0x0000a214, 0x40206c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x01834061 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x000003b5 },
+    { 0x0000a22c, 0x23277200 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c889af },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000001 },
+    { 0x0000a250, 0x001da000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cdbd380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000a27c, 0x050701ce },
+    { 0x0000a358, 0x7999aa0f },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+    { 0x0000a3e4, 0x00000000 },
+    { 0x0000a3e8, 0x18c43433 },
+    { 0x0000a3ec, 0x00f38081 },
+    { 0x00007800, 0x00040000 },
+    { 0x00007804, 0xdb005012 },
+    { 0x00007808, 0x04924914 },
+    { 0x0000780c, 0x21084210 },
+    { 0x00007810, 0x6d801300 },
+    { 0x00007814, 0x0019beff },
+    { 0x00007818, 0x07e40000 },
+    { 0x0000781c, 0x00492000 },
+    { 0x00007820, 0x92492480 },
+    { 0x00007824, 0x00040000 },
+    { 0x00007828, 0xdb005012 },
+    { 0x0000782c, 0x04924914 },
+    { 0x00007830, 0x21084210 },
+    { 0x00007834, 0x6d801300 },
+    { 0x00007838, 0x0019beff },
+    { 0x0000783c, 0x07e40000 },
+    { 0x00007840, 0x00492000 },
+    { 0x00007844, 0x92492480 },
+    { 0x00007848, 0x00120000 },
+    { 0x00007850, 0x54214514 },
+    { 0x00007858, 0x92592692 },
+    { 0x00007860, 0x52802000 },
+    { 0x00007864, 0x0a8e370e },
+    { 0x00007868, 0xc0102850 },
+    { 0x0000786c, 0x812d4000 },
+    { 0x00007874, 0x001b6db0 },
+    { 0x00007878, 0x00376b63 },
+    { 0x0000787c, 0x06db6db6 },
+    { 0x00007880, 0x006d8000 },
+    { 0x00007884, 0xffeffffe },
+    { 0x00007888, 0xffeffffe },
+    { 0x00007890, 0x00060aeb },
+    { 0x00007894, 0x5a108000 },
+    { 0x00007898, 0x2a850160 },
+};
+
+/* XXX 9280 2 */
+static const u32 ar9280Modes_9280_2[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+    { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
+    { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a },
+    { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
+    { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
+    { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e },
+    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
+    { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+    { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 },
+    { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+    { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+    { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
+    { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c },
+    { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 },
+    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
+    { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
+    { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 },
+    { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+    { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
+};
+
+static const u32 ar9280Common_9280_2[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020015 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00004024, 0x0000001f },
+    { 0x00004060, 0x00000000 },
+    { 0x00004064, 0x00000000 },
+    { 0x00007010, 0x00000033 },
+    { 0x00007034, 0x00000002 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x40000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x00008070, 0x00000000 },
+    { 0x000080c0, 0x2a80001a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0xffffffff },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c0, 0x00000000 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008264, 0xa8a00010 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x0000829c, 0x00000000 },
+    { 0x00008300, 0x00000040 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000007 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00ff0000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x000107ff },
+    { 0x00008344, 0x00581043 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xafa68e30 },
+    { 0x00009810, 0xfd14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x0040233c },
+    { 0x0000a84c, 0x0040233c },
+    { 0x00009854, 0x00000044 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x00009910, 0x01002310 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x04900000 },
+    { 0x0000a920, 0x04900000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009948, 0x9280c00a },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5f3ca3de },
+    { 0x00009958, 0x2108ecff },
+    { 0x00009940, 0x14750604 },
+    { 0x0000c95c, 0x004b6a8e },
+    { 0x0000c968, 0x000003ce },
+    { 0x00009970, 0x190fb515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x006f0000 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099b4, 0x00000820 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099f0, 0x00000000 },
+    { 0x000099fc, 0x00001042 },
+    { 0x0000a208, 0x803e4788 },
+    { 0x0000a210, 0x4080a333 },
+    { 0x0000a214, 0x40206c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x01834061 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x000003b5 },
+    { 0x0000a22c, 0x233f7180 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a23c, 0x13c88000 },
+    { 0x0000a240, 0x38490a20 },
+    { 0x0000a244, 0x00007bb6 },
+    { 0x0000a248, 0x0fff3ffc },
+    { 0x0000a24c, 0x00000000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0cdbd380 },
+    { 0x0000a25c, 0x0f0f0f01 },
+    { 0x0000a260, 0xdfa91f01 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0ebae9c6 },
+    { 0x0000b26c, 0x0ebae9c6 },
+    { 0x0000d270, 0x00820820 },
+    { 0x0000a278, 0x1ce739ce },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3c8, 0x00000246 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce },
+    { 0x0000a3e4, 0x00000000 },
+    { 0x0000a3e8, 0x18c43433 },
+    { 0x0000a3ec, 0x00f70081 },
+    { 0x00007800, 0x00040000 },
+    { 0x00007804, 0xdb005012 },
+    { 0x00007808, 0x04924914 },
+    { 0x0000780c, 0x21084210 },
+    { 0x00007810, 0x6d801300 },
+    { 0x00007818, 0x07e41000 },
+    { 0x00007824, 0x00040000 },
+    { 0x00007828, 0xdb005012 },
+    { 0x0000782c, 0x04924914 },
+    { 0x00007830, 0x21084210 },
+    { 0x00007834, 0x6d801300 },
+    { 0x0000783c, 0x07e40000 },
+    { 0x00007848, 0x00100000 },
+    { 0x0000784c, 0x773f0567 },
+    { 0x00007850, 0x54214514 },
+    { 0x00007854, 0x12035828 },
+    { 0x00007858, 0x9259269a },
+    { 0x00007860, 0x52802000 },
+    { 0x00007864, 0x0a8e370e },
+    { 0x00007868, 0xc0102850 },
+    { 0x0000786c, 0x812d4000 },
+    { 0x00007870, 0x807ec400 },
+    { 0x00007874, 0x001b6db0 },
+    { 0x00007878, 0x00376b63 },
+    { 0x0000787c, 0x06db6db6 },
+    { 0x00007880, 0x006d8000 },
+    { 0x00007884, 0xffeffffe },
+    { 0x00007888, 0xffeffffe },
+    { 0x0000788c, 0x00010000 },
+    { 0x00007890, 0x02060aeb },
+    { 0x00007898, 0x2a850160 },
+};
+
+static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
+    { 0x00001030, 0x00000268, 0x000004d0 },
+    { 0x00001070, 0x0000018c, 0x00000318 },
+    { 0x000010b0, 0x00000fd0, 0x00001fa0 },
+    { 0x00008014, 0x044c044c, 0x08980898 },
+    { 0x0000801c, 0x148ec02b, 0x148ec057 },
+    { 0x00008318, 0x000044c0, 0x00008980 },
+    { 0x00009820, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000f0f, 0x00000f0f },
+    { 0x00009828, 0x0b020001, 0x0b020001 },
+    { 0x00009834, 0x00000f0f, 0x00000f0f },
+    { 0x00009844, 0x03721821, 0x03721821 },
+    { 0x00009914, 0x00000898, 0x00001130 },
+    { 0x00009918, 0x0000000b, 0x00000016 },
+};
+
+static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
+    { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+    { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+    { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+    { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+    { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+    { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+    { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+    { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+    { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+    { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+    { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+    { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+    { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+    { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+    { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+    { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+    { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+    { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+    { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+    { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 },
+    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 },
+    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 },
+    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 },
+    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 },
+    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d },
+    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 },
+    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 },
+    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 },
+    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 },
+    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a },
+    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e },
+    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 },
+    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 },
+    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 },
+    { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 },
+    { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b },
+    { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f },
+    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 },
+    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 },
+    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 },
+    { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 },
+    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b },
+    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f },
+    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 },
+    { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 },
+    { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 },
+    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 },
+    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b },
+    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f },
+    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 },
+    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 },
+    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+    { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
+    { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
+};
+
+static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
+    { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+    { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+    { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+    { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+    { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+    { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+    { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+    { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+    { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+    { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+    { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+    { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+    { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+    { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+    { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+    { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+    { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+    { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+    { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+    { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
+    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
+    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
+    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
+    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
+    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
+    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
+    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
+    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
+    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
+    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
+    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
+    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
+    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
+    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
+    { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
+    { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
+    { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
+    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
+    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
+    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
+    { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
+    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
+    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
+    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
+    { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
+    { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
+    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
+    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
+    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
+    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
+    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
+    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
+    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
+    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
+    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
+    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
+    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
+    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
+    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
+    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
+    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
+    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
+    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
+    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
+    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
+    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
+    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
+    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
+    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
+    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
+    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+    { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
+    { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
+};
+
+static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
+    { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+    { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+    { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+    { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+    { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+    { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+    { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+    { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+    { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+    { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+    { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+    { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+    { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+    { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+    { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+    { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+    { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+    { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+    { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+    { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
+    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
+    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
+    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
+    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
+    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
+    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
+    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
+    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
+    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
+    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 },
+    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 },
+    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 },
+    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 },
+    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 },
+    { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c },
+    { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 },
+    { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 },
+    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 },
+    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 },
+    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 },
+    { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d },
+    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 },
+    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 },
+    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 },
+    { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 },
+    { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a },
+    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e },
+    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 },
+    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 },
+    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 },
+    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 },
+    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b },
+    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f },
+    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 },
+    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 },
+    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 },
+    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 },
+    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b },
+    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f },
+    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 },
+    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 },
+    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+    { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
+    { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
+};
+
+static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
+    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 },
+    { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 },
+    { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 },
+    { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 },
+    { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 },
+    { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a },
+    { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 },
+    { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
+    { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 },
+    { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 },
+    { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 },
+    { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 },
+    { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 },
+    { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 },
+    { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c },
+    { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a },
+    { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 },
+    { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 },
+    { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 },
+    { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 },
+    { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 },
+    { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
+    { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
+    { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
+    { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
+    { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
+    { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
+    { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
+    { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
+};
+
+static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
+    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
+    { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
+    { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
+    { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
+    { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
+    { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
+    { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
+    { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
+    { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
+    { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
+    { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
+    { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
+    { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
+    { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
+    { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
+    { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
+    { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
+    { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
+    { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
+    { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
+    { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
+    { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
+    { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
+    { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
+    { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
+    { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
+    { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
+    { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
+    { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
+};
+
+static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01dcffc },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
+
+static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01dcffd },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
+
+/* AR9285 */
+static const u_int32_t ar9285Modes_9285[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+    { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 },
+    { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 },
+    { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
+    { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e },
+    { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
+    { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
+    { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 },
+    { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c },
+    { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
+    { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
+    { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
+    { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
+    { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
+    { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
+    { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
+    { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+    { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 },
+    { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
+    { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
+    { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
+    { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
+    { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
+    { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
+    { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
+    { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
+    { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
+    { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 },
+    { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 },
+    { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 },
+    { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
+    { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
+    { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 },
+    { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
+    { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
+    { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 },
+    { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 },
+    { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+    { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+    { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+    { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+    { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+    { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+    { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 },
+    { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
+    { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
+    { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 },
+    { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 },
+    { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 },
+    { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 },
+    { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 },
+    { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 },
+    { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 },
+    { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+    { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
+    { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 },
+    { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 },
+    { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 },
+    { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 },
+    { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
+    { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
+    { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 },
+    { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 },
+    { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 },
+    { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 },
+    { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
+    { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
+    { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 },
+    { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 },
+    { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 },
+    { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 },
+    { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 },
+    { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 },
+    { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
+    { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
+    { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 },
+    { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
+    { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
+    { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
+    { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 },
+    { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
+    { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
+    { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 },
+    { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 },
+    { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
+    { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
+    { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 },
+    { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
+    { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
+    { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
+    { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
+    { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
+    { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
+    { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
+    { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 },
+    { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
+    { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 },
+    { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 },
+    { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+    { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 },
+    { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 },
+    { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
+    { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
+    { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
+    { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
+    { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
+    { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
+    { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
+    { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+    { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+    { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
+    { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
+    { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
+    { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
+    { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
+    { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
+    { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
+    { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
+    { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
+    { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 },
+    { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 },
+    { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 },
+    { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
+    { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
+    { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
+    { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
+    { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 },
+    { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 },
+    { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 },
+    { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 },
+    { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 },
+    { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 },
+    { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 },
+    { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 },
+    { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 },
+    { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 },
+    { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 },
+    { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 },
+    { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 },
+    { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 },
+    { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 },
+    { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 },
+    { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 },
+    { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 },
+    { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+    { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+    { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
+    { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 },
+    { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
+    { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
+    { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 },
+    { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 },
+    { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 },
+    { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 },
+    { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
+    { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
+    { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 },
+    { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 },
+    { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 },
+    { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 },
+    { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 },
+    { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 },
+    { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 },
+    { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 },
+    { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
+    { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
+    { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
+    { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
+    { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
+    { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 },
+    { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 },
+    { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
+    { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
+    { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
+    { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
+    { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 },
+    { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
+    { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 },
+    { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
+    { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
+    { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 },
+    { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
+    { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
+    { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
+    { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
+    { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
+    { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
+    { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
+    { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+    { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
+    { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 },
+    { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 },
+    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
+    { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 },
+    { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 },
+    { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 },
+    { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 },
+    { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 },
+    { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 },
+    { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 },
+    { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 },
+    { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 },
+    { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 },
+    { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 },
+    { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 },
+    { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+};
+
+static const u_int32_t ar9285Common_9285[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020045 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00004024, 0x0000001f },
+    { 0x00004060, 0x00000000 },
+    { 0x00004064, 0x00000000 },
+    { 0x00007010, 0x00000031 },
+    { 0x00007034, 0x00000002 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x00000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x00008070, 0x00000000 },
+    { 0x000080c0, 0x2a80001a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04800 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0x00000000 },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c0, 0x00000000 },
+    { 0x000081d0, 0x00003210 },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008264, 0xa8a00010 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x0000829c, 0x00000000 },
+    { 0x00008300, 0x00000040 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000001 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00000000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x00010380 },
+    { 0x00008344, 0x00581043 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xafe68e30 },
+    { 0x00009810, 0xfd14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x0040233c },
+    { 0x00009854, 0x00000044 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x00009910, 0x01002310 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x04900000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009940, 0x14750604 },
+    { 0x00009948, 0x9280c00a },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5f3ca3de },
+    { 0x00009958, 0x2108ecff },
+    { 0x00009968, 0x000003ce },
+    { 0x00009970, 0x1927b515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x2def0a00 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099b4, 0x00000820 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099f0, 0x00000000 },
+    { 0x0000a208, 0x803e6788 },
+    { 0x0000a210, 0x4080a333 },
+    { 0x0000a214, 0x00206c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x01834061 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x000003b5 },
+    { 0x0000a22c, 0x00000000 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a244, 0x00000000 },
+    { 0x0000a248, 0xfffffffc },
+    { 0x0000a24c, 0x00000000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0ccb5380 },
+    { 0x0000a25c, 0x15151501 },
+    { 0x0000a260, 0xdfa90f01 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0ebae9e6 },
+    { 0x0000d270, 0x0d820820 },
+    { 0x0000a278, 0x39ce739c },
+    { 0x0000a27c, 0x050e039c },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a394, 0x39ce739c },
+    { 0x0000a398, 0x0000039c },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3dc, 0x39ce739c },
+    { 0x0000a3e0, 0x0000039c },
+    { 0x0000a3e4, 0x00000000 },
+    { 0x0000a3e8, 0x18c43433 },
+    { 0x0000a3ec, 0x00f70081 },
+    { 0x00007800, 0x00140000 },
+    { 0x00007804, 0x0e4548d8 },
+    { 0x00007808, 0x54214514 },
+    { 0x0000780c, 0x02025820 },
+    { 0x00007810, 0x71c0d388 },
+    { 0x00007814, 0x924934a8 },
+    { 0x0000781c, 0x00000000 },
+    { 0x00007820, 0x00000c04 },
+    { 0x00007824, 0x00d86fff },
+    { 0x00007828, 0x26d2491b },
+    { 0x0000782c, 0x6e36d97b },
+    { 0x00007830, 0xedb6d96c },
+    { 0x00007834, 0x71400086 },
+    { 0x00007838, 0xfac68800 },
+    { 0x0000783c, 0x0001fffe },
+    { 0x00007840, 0xffeb1a20 },
+    { 0x00007844, 0x000c0db6 },
+    { 0x00007848, 0x6db61b6f },
+    { 0x0000784c, 0x6d9b66db },
+    { 0x00007850, 0x6d8c6dba },
+    { 0x00007854, 0x00040000 },
+    { 0x00007858, 0xdb003012 },
+    { 0x0000785c, 0x04924914 },
+    { 0x00007860, 0x21084210 },
+    { 0x00007864, 0xf7d7ffde },
+    { 0x00007868, 0xc2034080 },
+    { 0x0000786c, 0x48609eb4 },
+    { 0x00007870, 0x10142c00 },
+};
+
+static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01dcffd },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
+
+static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01dcffc },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
+
+/* AR9285 v1_2 PCI Register Writes.  Created: 03/04/09 */
+static const u_int32_t ar9285Modes_9285_1_2[][6] = {
+    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+    { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+    { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
+    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+    { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
+    { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 },
+    { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
+    { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
+    { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },
+    { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
+    { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+    { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+    { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
+    { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 },
+    { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c },
+    { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+    { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 },
+    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
+    { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
+    { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
+    { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
+    { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
+    { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
+    { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
+    { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
+    { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
+    { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
+    { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
+    { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
+    { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
+    { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
+    { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
+    { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
+    { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
+    { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
+    { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
+    { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
+    { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
+    { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
+    { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
+    { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
+    { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
+    { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
+    { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
+    { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
+    { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+    { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+    { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+    { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+    { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+    { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+    { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
+    { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
+    { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
+    { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
+    { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
+    { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
+    { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
+    { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
+    { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
+    { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
+    { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
+    { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
+    { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
+    { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
+    { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
+    { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
+    { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
+    { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
+    { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
+    { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
+    { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
+    { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
+    { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
+    { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
+    { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
+    { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
+    { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
+    { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
+    { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
+    { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
+    { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
+    { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
+    { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
+    { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
+    { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
+    { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
+    { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
+    { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
+    { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
+    { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
+    { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
+    { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
+    { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
+    { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
+    { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
+    { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
+    { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
+    { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
+    { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
+    { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
+    { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
+    { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
+    { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
+    { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
+    { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
+    { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
+    { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
+    { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
+    { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
+    { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
+    { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
+    { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
+    { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
+    { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
+    { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
+    { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
+    { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
+    { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
+    { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
+    { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
+    { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
+    { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
+    { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
+    { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
+    { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
+    { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
+    { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
+    { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
+    { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
+    { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
+    { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
+    { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+    { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+    { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+    { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+    { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+    { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+    { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
+    { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
+    { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
+    { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
+    { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
+    { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
+    { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
+    { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
+    { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
+    { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
+    { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
+    { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
+    { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
+    { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
+    { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
+    { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
+    { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
+    { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
+    { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
+    { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
+    { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
+    { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
+    { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
+    { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
+    { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
+    { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
+    { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
+    { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
+    { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
+    { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
+    { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
+    { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
+    { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
+    { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
+    { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
+    { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
+    { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
+    { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
+    { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
+    { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
+    { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
+    { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
+    { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
+    { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
+    { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
+    { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
+    { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
+    { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
+    { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
+    { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
+    { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
+    { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
+    { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
+    { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
+    { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
+    { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
+    { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
+    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+    { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
+    { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+};
+
+static const u_int32_t ar9285Common_9285_1_2[][2] = {
+    { 0x0000000c, 0x00000000 },
+    { 0x00000030, 0x00020045 },
+    { 0x00000034, 0x00000005 },
+    { 0x00000040, 0x00000000 },
+    { 0x00000044, 0x00000008 },
+    { 0x00000048, 0x00000008 },
+    { 0x0000004c, 0x00000010 },
+    { 0x00000050, 0x00000000 },
+    { 0x00000054, 0x0000001f },
+    { 0x00000800, 0x00000000 },
+    { 0x00000804, 0x00000000 },
+    { 0x00000808, 0x00000000 },
+    { 0x0000080c, 0x00000000 },
+    { 0x00000810, 0x00000000 },
+    { 0x00000814, 0x00000000 },
+    { 0x00000818, 0x00000000 },
+    { 0x0000081c, 0x00000000 },
+    { 0x00000820, 0x00000000 },
+    { 0x00000824, 0x00000000 },
+    { 0x00001040, 0x002ffc0f },
+    { 0x00001044, 0x002ffc0f },
+    { 0x00001048, 0x002ffc0f },
+    { 0x0000104c, 0x002ffc0f },
+    { 0x00001050, 0x002ffc0f },
+    { 0x00001054, 0x002ffc0f },
+    { 0x00001058, 0x002ffc0f },
+    { 0x0000105c, 0x002ffc0f },
+    { 0x00001060, 0x002ffc0f },
+    { 0x00001064, 0x002ffc0f },
+    { 0x00001230, 0x00000000 },
+    { 0x00001270, 0x00000000 },
+    { 0x00001038, 0x00000000 },
+    { 0x00001078, 0x00000000 },
+    { 0x000010b8, 0x00000000 },
+    { 0x000010f8, 0x00000000 },
+    { 0x00001138, 0x00000000 },
+    { 0x00001178, 0x00000000 },
+    { 0x000011b8, 0x00000000 },
+    { 0x000011f8, 0x00000000 },
+    { 0x00001238, 0x00000000 },
+    { 0x00001278, 0x00000000 },
+    { 0x000012b8, 0x00000000 },
+    { 0x000012f8, 0x00000000 },
+    { 0x00001338, 0x00000000 },
+    { 0x00001378, 0x00000000 },
+    { 0x000013b8, 0x00000000 },
+    { 0x000013f8, 0x00000000 },
+    { 0x00001438, 0x00000000 },
+    { 0x00001478, 0x00000000 },
+    { 0x000014b8, 0x00000000 },
+    { 0x000014f8, 0x00000000 },
+    { 0x00001538, 0x00000000 },
+    { 0x00001578, 0x00000000 },
+    { 0x000015b8, 0x00000000 },
+    { 0x000015f8, 0x00000000 },
+    { 0x00001638, 0x00000000 },
+    { 0x00001678, 0x00000000 },
+    { 0x000016b8, 0x00000000 },
+    { 0x000016f8, 0x00000000 },
+    { 0x00001738, 0x00000000 },
+    { 0x00001778, 0x00000000 },
+    { 0x000017b8, 0x00000000 },
+    { 0x000017f8, 0x00000000 },
+    { 0x0000103c, 0x00000000 },
+    { 0x0000107c, 0x00000000 },
+    { 0x000010bc, 0x00000000 },
+    { 0x000010fc, 0x00000000 },
+    { 0x0000113c, 0x00000000 },
+    { 0x0000117c, 0x00000000 },
+    { 0x000011bc, 0x00000000 },
+    { 0x000011fc, 0x00000000 },
+    { 0x0000123c, 0x00000000 },
+    { 0x0000127c, 0x00000000 },
+    { 0x000012bc, 0x00000000 },
+    { 0x000012fc, 0x00000000 },
+    { 0x0000133c, 0x00000000 },
+    { 0x0000137c, 0x00000000 },
+    { 0x000013bc, 0x00000000 },
+    { 0x000013fc, 0x00000000 },
+    { 0x0000143c, 0x00000000 },
+    { 0x0000147c, 0x00000000 },
+    { 0x00004030, 0x00000002 },
+    { 0x0000403c, 0x00000002 },
+    { 0x00004024, 0x0000001f },
+    { 0x00004060, 0x00000000 },
+    { 0x00004064, 0x00000000 },
+    { 0x00007010, 0x00000031 },
+    { 0x00007034, 0x00000002 },
+    { 0x00007038, 0x000004c2 },
+    { 0x00008004, 0x00000000 },
+    { 0x00008008, 0x00000000 },
+    { 0x0000800c, 0x00000000 },
+    { 0x00008018, 0x00000700 },
+    { 0x00008020, 0x00000000 },
+    { 0x00008038, 0x00000000 },
+    { 0x0000803c, 0x00000000 },
+    { 0x00008048, 0x00000000 },
+    { 0x00008054, 0x00000000 },
+    { 0x00008058, 0x00000000 },
+    { 0x0000805c, 0x000fc78f },
+    { 0x00008060, 0x0000000f },
+    { 0x00008064, 0x00000000 },
+    { 0x00008070, 0x00000000 },
+    { 0x000080c0, 0x2a80001a },
+    { 0x000080c4, 0x05dc01e0 },
+    { 0x000080c8, 0x1f402710 },
+    { 0x000080cc, 0x01f40000 },
+    { 0x000080d0, 0x00001e00 },
+    { 0x000080d4, 0x00000000 },
+    { 0x000080d8, 0x00400000 },
+    { 0x000080e0, 0xffffffff },
+    { 0x000080e4, 0x0000ffff },
+    { 0x000080e8, 0x003f3f3f },
+    { 0x000080ec, 0x00000000 },
+    { 0x000080f0, 0x00000000 },
+    { 0x000080f4, 0x00000000 },
+    { 0x000080f8, 0x00000000 },
+    { 0x000080fc, 0x00020000 },
+    { 0x00008100, 0x00020000 },
+    { 0x00008104, 0x00000001 },
+    { 0x00008108, 0x00000052 },
+    { 0x0000810c, 0x00000000 },
+    { 0x00008110, 0x00000168 },
+    { 0x00008118, 0x000100aa },
+    { 0x0000811c, 0x00003210 },
+    { 0x00008120, 0x08f04810 },
+    { 0x00008124, 0x00000000 },
+    { 0x00008128, 0x00000000 },
+    { 0x0000812c, 0x00000000 },
+    { 0x00008130, 0x00000000 },
+    { 0x00008134, 0x00000000 },
+    { 0x00008138, 0x00000000 },
+    { 0x0000813c, 0x00000000 },
+    { 0x00008144, 0xffffffff },
+    { 0x00008168, 0x00000000 },
+    { 0x0000816c, 0x00000000 },
+    { 0x00008170, 0x32143320 },
+    { 0x00008174, 0xfaa4fa50 },
+    { 0x00008178, 0x00000100 },
+    { 0x0000817c, 0x00000000 },
+    { 0x000081c0, 0x00000000 },
+    { 0x000081d0, 0x0000320a },
+    { 0x000081ec, 0x00000000 },
+    { 0x000081f0, 0x00000000 },
+    { 0x000081f4, 0x00000000 },
+    { 0x000081f8, 0x00000000 },
+    { 0x000081fc, 0x00000000 },
+    { 0x00008200, 0x00000000 },
+    { 0x00008204, 0x00000000 },
+    { 0x00008208, 0x00000000 },
+    { 0x0000820c, 0x00000000 },
+    { 0x00008210, 0x00000000 },
+    { 0x00008214, 0x00000000 },
+    { 0x00008218, 0x00000000 },
+    { 0x0000821c, 0x00000000 },
+    { 0x00008220, 0x00000000 },
+    { 0x00008224, 0x00000000 },
+    { 0x00008228, 0x00000000 },
+    { 0x0000822c, 0x00000000 },
+    { 0x00008230, 0x00000000 },
+    { 0x00008234, 0x00000000 },
+    { 0x00008238, 0x00000000 },
+    { 0x0000823c, 0x00000000 },
+    { 0x00008240, 0x00100000 },
+    { 0x00008244, 0x0010f400 },
+    { 0x00008248, 0x00000100 },
+    { 0x0000824c, 0x0001e800 },
+    { 0x00008250, 0x00000000 },
+    { 0x00008254, 0x00000000 },
+    { 0x00008258, 0x00000000 },
+    { 0x0000825c, 0x400000ff },
+    { 0x00008260, 0x00080922 },
+    { 0x00008264, 0xa8a00010 },
+    { 0x00008270, 0x00000000 },
+    { 0x00008274, 0x40000000 },
+    { 0x00008278, 0x003e4180 },
+    { 0x0000827c, 0x00000000 },
+    { 0x00008284, 0x0000002c },
+    { 0x00008288, 0x0000002c },
+    { 0x0000828c, 0x00000000 },
+    { 0x00008294, 0x00000000 },
+    { 0x00008298, 0x00000000 },
+    { 0x0000829c, 0x00000000 },
+    { 0x00008300, 0x00000040 },
+    { 0x00008314, 0x00000000 },
+    { 0x00008328, 0x00000000 },
+    { 0x0000832c, 0x00000001 },
+    { 0x00008330, 0x00000302 },
+    { 0x00008334, 0x00000e00 },
+    { 0x00008338, 0x00ff0000 },
+    { 0x0000833c, 0x00000000 },
+    { 0x00008340, 0x00010380 },
+    { 0x00008344, 0x00581043 },
+    { 0x00009808, 0x00000000 },
+    { 0x0000980c, 0xafe68e30 },
+    { 0x00009810, 0xfd14e000 },
+    { 0x00009814, 0x9c0a9f6b },
+    { 0x0000981c, 0x00000000 },
+    { 0x0000982c, 0x0000a000 },
+    { 0x00009830, 0x00000000 },
+    { 0x0000983c, 0x00200400 },
+    { 0x0000984c, 0x0040233c },
+    { 0x00009854, 0x00000044 },
+    { 0x00009900, 0x00000000 },
+    { 0x00009904, 0x00000000 },
+    { 0x00009908, 0x00000000 },
+    { 0x0000990c, 0x00000000 },
+    { 0x00009910, 0x01002310 },
+    { 0x0000991c, 0x10000fff },
+    { 0x00009920, 0x04900000 },
+    { 0x00009928, 0x00000001 },
+    { 0x0000992c, 0x00000004 },
+    { 0x00009934, 0x1e1f2022 },
+    { 0x00009938, 0x0a0b0c0d },
+    { 0x0000993c, 0x00000000 },
+    { 0x00009940, 0x14750604 },
+    { 0x00009948, 0x9280c00a },
+    { 0x0000994c, 0x00020028 },
+    { 0x00009954, 0x5f3ca3de },
+    { 0x00009958, 0x2108ecff },
+    { 0x00009968, 0x000003ce },
+    { 0x00009970, 0x192bb515 },
+    { 0x00009974, 0x00000000 },
+    { 0x00009978, 0x00000001 },
+    { 0x0000997c, 0x00000000 },
+    { 0x00009980, 0x00000000 },
+    { 0x00009984, 0x00000000 },
+    { 0x00009988, 0x00000000 },
+    { 0x0000998c, 0x00000000 },
+    { 0x00009990, 0x00000000 },
+    { 0x00009994, 0x00000000 },
+    { 0x00009998, 0x00000000 },
+    { 0x0000999c, 0x00000000 },
+    { 0x000099a0, 0x00000000 },
+    { 0x000099a4, 0x00000001 },
+    { 0x000099a8, 0x201fff00 },
+    { 0x000099ac, 0x2def0400 },
+    { 0x000099b0, 0x03051000 },
+    { 0x000099b4, 0x00000820 },
+    { 0x000099dc, 0x00000000 },
+    { 0x000099e0, 0x00000000 },
+    { 0x000099e4, 0xaaaaaaaa },
+    { 0x000099e8, 0x3c466478 },
+    { 0x000099ec, 0x0cc80caa },
+    { 0x000099f0, 0x00000000 },
+    { 0x0000a208, 0x803e68c8 },
+    { 0x0000a210, 0x4080a333 },
+    { 0x0000a214, 0x00206c10 },
+    { 0x0000a218, 0x009c4060 },
+    { 0x0000a220, 0x01834061 },
+    { 0x0000a224, 0x00000400 },
+    { 0x0000a228, 0x000003b5 },
+    { 0x0000a22c, 0x00000000 },
+    { 0x0000a234, 0x20202020 },
+    { 0x0000a238, 0x20202020 },
+    { 0x0000a244, 0x00000000 },
+    { 0x0000a248, 0xfffffffc },
+    { 0x0000a24c, 0x00000000 },
+    { 0x0000a254, 0x00000000 },
+    { 0x0000a258, 0x0ccb5380 },
+    { 0x0000a25c, 0x15151501 },
+    { 0x0000a260, 0xdfa90f01 },
+    { 0x0000a268, 0x00000000 },
+    { 0x0000a26c, 0x0ebae9e6 },
+    { 0x0000d270, 0x0d820820 },
+    { 0x0000d35c, 0x07ffffef },
+    { 0x0000d360, 0x0fffffe7 },
+    { 0x0000d364, 0x17ffffe5 },
+    { 0x0000d368, 0x1fffffe4 },
+    { 0x0000d36c, 0x37ffffe3 },
+    { 0x0000d370, 0x3fffffe3 },
+    { 0x0000d374, 0x57ffffe3 },
+    { 0x0000d378, 0x5fffffe2 },
+    { 0x0000d37c, 0x7fffffe2 },
+    { 0x0000d380, 0x7f3c7bba },
+    { 0x0000d384, 0xf3307ff0 },
+    { 0x0000a388, 0x0c000000 },
+    { 0x0000a38c, 0x20202020 },
+    { 0x0000a390, 0x20202020 },
+    { 0x0000a39c, 0x00000001 },
+    { 0x0000a3a0, 0x00000000 },
+    { 0x0000a3a4, 0x00000000 },
+    { 0x0000a3a8, 0x00000000 },
+    { 0x0000a3ac, 0x00000000 },
+    { 0x0000a3b0, 0x00000000 },
+    { 0x0000a3b4, 0x00000000 },
+    { 0x0000a3b8, 0x00000000 },
+    { 0x0000a3bc, 0x00000000 },
+    { 0x0000a3c0, 0x00000000 },
+    { 0x0000a3c4, 0x00000000 },
+    { 0x0000a3cc, 0x20202020 },
+    { 0x0000a3d0, 0x20202020 },
+    { 0x0000a3d4, 0x20202020 },
+    { 0x0000a3e4, 0x00000000 },
+    { 0x0000a3e8, 0x18c43433 },
+    { 0x0000a3ec, 0x00f70081 },
+    { 0x00007800, 0x00140000 },
+    { 0x00007804, 0x0e4548d8 },
+    { 0x00007808, 0x54214514 },
+    { 0x0000780c, 0x02025820 },
+    { 0x00007810, 0x71c0d388 },
+    { 0x00007814, 0x924934a8 },
+    { 0x0000781c, 0x00000000 },
+    { 0x00007824, 0x00d86fff },
+    { 0x00007828, 0x26d2491b },
+    { 0x0000782c, 0x6e36d97b },
+    { 0x00007830, 0xedb6d96e },
+    { 0x00007834, 0x71400087 },
+    { 0x0000783c, 0x0001fffe },
+    { 0x00007840, 0xffeb1a20 },
+    { 0x00007844, 0x000c0db6 },
+    { 0x00007848, 0x6db61b6f },
+    { 0x0000784c, 0x6d9b66db },
+    { 0x00007850, 0x6d8c6dba },
+    { 0x00007854, 0x00040000 },
+    { 0x00007858, 0xdb003012 },
+    { 0x0000785c, 0x04924914 },
+    { 0x00007860, 0x21084210 },
+    { 0x00007864, 0xf7d7ffde },
+    { 0x00007868, 0xc2034080 },
+    { 0x00007870, 0x10142c00 },
+};
+
+static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
+    /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */
+    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 },
+    { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
+    { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 },
+    { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 },
+    { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 },
+    { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 },
+    { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 },
+    { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 },
+    { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 },
+    { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 },
+    { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
+    { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
+    { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 },
+    { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe },
+    { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 },
+    { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
+    { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
+    { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
+    { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
+    { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
+    { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
+    { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
+};
+
+static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = {
+    /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */
+    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+    { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },
+    { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 },
+    { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 },
+    { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 },
+    { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 },
+    { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 },
+    { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 },
+    { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 },
+    { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 },
+    { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 },
+    { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 },
+    { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 },
+    { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 },
+    { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
+    { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
+    { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+    { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 },
+    { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 },
+    { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 },
+    { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
+    { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
+    { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c },
+    { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
+    { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
+    { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
+    { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
+};
+
+static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01dcffd },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
+
+static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
+    {0x00004040,  0x9248fd00 },
+    {0x00004040,  0x24924924 },
+    {0x00004040,  0xa8000019 },
+    {0x00004040,  0x13160820 },
+    {0x00004040,  0xe5980560 },
+    {0x00004040,  0xc01dcffc },
+    {0x00004040,  0x1aaabe41 },
+    {0x00004040,  0xbe105554 },
+    {0x00004040,  0x00043007 },
+    {0x00004044,  0x00000000 },
+};
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,23 @@
+config ATH9K
+	tristate "Atheros 802.11n wireless cards support"
+	depends on PCI && MAC80211 && WLAN_80211
+	select ATH_COMMON
+	select MAC80211_LEDS
+	select LEDS_CLASS
+	select NEW_LEDS
+	---help---
+	  This module adds support for wireless adapters based on
+	  Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
+
+	  If you choose to build a module, it'll be called ath9k.
+
+config ATH9K_DEBUG
+	bool "Atheros ath9k debugging"
+	depends on ATH9K
+	---help---
+	  Say Y, if you need ath9k to display debug messages.
+	  Pass the debug mask as a module parameter:
+
+	  modprobe ath9k debug=0x00002000
+
+	  Look in ath9k/core.h for possible debug masks
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/mac.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/mac.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/mac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/mac.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,976 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
+					struct ath9k_tx_queue_info *qi)
+{
+	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
+		"tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
+		ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
+		ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
+		ah->txurn_interrupt_mask);
+
+	REG_WRITE(ah, AR_IMR_S0,
+		  SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
+		  | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
+	REG_WRITE(ah, AR_IMR_S1,
+		  SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
+		  | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
+	REG_RMW_FIELD(ah, AR_IMR_S2,
+		      AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask);
+}
+
+u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
+{
+	return REG_READ(ah, AR_QTXDP(q));
+}
+
+bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
+{
+	REG_WRITE(ah, AR_QTXDP(q), txdp);
+
+	return true;
+}
+
+bool ath9k_hw_txstart(struct ath_hw *ah, u32 q)
+{
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
+
+	REG_WRITE(ah, AR_Q_TXE, 1 << q);
+
+	return true;
+}
+
+u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
+{
+	u32 npend;
+
+	npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
+	if (npend == 0) {
+
+		if (REG_READ(ah, AR_Q_TXE) & (1 << q))
+			npend = 1;
+	}
+
+	return npend;
+}
+
+bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
+{
+	u32 txcfg, curLevel, newLevel;
+	enum ath9k_int omask;
+
+	if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD)
+		return false;
+
+	omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
+
+	txcfg = REG_READ(ah, AR_TXCFG);
+	curLevel = MS(txcfg, AR_FTRIG);
+	newLevel = curLevel;
+	if (bIncTrigLevel) {
+		if (curLevel < MAX_TX_FIFO_THRESHOLD)
+			newLevel++;
+	} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
+		newLevel--;
+	if (newLevel != curLevel)
+		REG_WRITE(ah, AR_TXCFG,
+			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+
+	ath9k_hw_set_interrupts(ah, omask);
+
+	ah->tx_trig_level = newLevel;
+
+	return newLevel != curLevel;
+}
+
+bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
+{
+#define ATH9K_TX_STOP_DMA_TIMEOUT	4000    /* usec */
+#define ATH9K_TIME_QUANTUM		100     /* usec */
+
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	struct ath9k_tx_queue_info *qi;
+	u32 tsfLow, j, wait;
+	u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
+			"invalid queue: %u\n", q);
+		return false;
+	}
+
+	qi = &ah->txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
+			"inactive queue: %u\n", q);
+		return false;
+	}
+
+	REG_WRITE(ah, AR_Q_TXD, 1 << q);
+
+	for (wait = wait_time; wait != 0; wait--) {
+		if (ath9k_hw_numtxpending(ah, q) == 0)
+			break;
+		udelay(ATH9K_TIME_QUANTUM);
+	}
+
+	if (ath9k_hw_numtxpending(ah, q)) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+			"%s: Num of pending TX Frames %d on Q %d\n",
+			__func__, ath9k_hw_numtxpending(ah, q), q);
+
+		for (j = 0; j < 2; j++) {
+			tsfLow = REG_READ(ah, AR_TSF_L32);
+			REG_WRITE(ah, AR_QUIET2,
+				  SM(10, AR_QUIET2_QUIET_DUR));
+			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
+			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
+			REG_SET_BIT(ah, AR_TIMER_MODE,
+				       AR_QUIET_TIMER_EN);
+
+			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
+				break;
+
+			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+				"TSF has moved while trying to set "
+				"quiet time TSF: 0x%08x\n", tsfLow);
+		}
+
+		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+
+		udelay(200);
+		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+
+		wait = wait_time;
+		while (ath9k_hw_numtxpending(ah, q)) {
+			if ((--wait) == 0) {
+				DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+					"Failed to stop TX DMA in 100 "
+					"msec after killing last frame\n");
+				break;
+			}
+			udelay(ATH9K_TIME_QUANTUM);
+		}
+
+		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+	}
+
+	REG_WRITE(ah, AR_Q_TXD, 0);
+	return wait != 0;
+
+#undef ATH9K_TX_STOP_DMA_TIMEOUT
+#undef ATH9K_TIME_QUANTUM
+}
+
+bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
+			 u32 segLen, bool firstSeg,
+			 bool lastSeg, const struct ath_desc *ds0)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	if (firstSeg) {
+		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+	} else if (lastSeg) {
+		ads->ds_ctl0 = 0;
+		ads->ds_ctl1 = segLen;
+		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+	} else {
+		ads->ds_ctl0 = 0;
+		ads->ds_ctl1 = segLen | AR_TxMore;
+		ads->ds_ctl2 = 0;
+		ads->ds_ctl3 = 0;
+	}
+	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+	return true;
+}
+
+void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+}
+
+int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	if ((ads->ds_txstatus9 & AR_TxDone) == 0)
+		return -EINPROGRESS;
+
+	ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
+	ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
+	ds->ds_txstat.ts_status = 0;
+	ds->ds_txstat.ts_flags = 0;
+
+	if (ads->ds_txstatus1 & AR_ExcessiveRetries)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
+	if (ads->ds_txstatus1 & AR_Filtered)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
+	if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
+		ath9k_hw_updatetxtriglevel(ah, true);
+	}
+	if (ads->ds_txstatus9 & AR_TxOpExceeded)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
+	if (ads->ds_txstatus1 & AR_TxTimerExpired)
+		ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+
+	if (ads->ds_txstatus1 & AR_DescCfgErr)
+		ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+	if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
+		ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+		ath9k_hw_updatetxtriglevel(ah, true);
+	}
+	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
+		ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+		ath9k_hw_updatetxtriglevel(ah, true);
+	}
+	if (ads->ds_txstatus0 & AR_TxBaStatus) {
+		ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
+		ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
+		ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
+	}
+
+	ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
+	switch (ds->ds_txstat.ts_rateindex) {
+	case 0:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
+		break;
+	case 1:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
+		break;
+	case 2:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
+		break;
+	case 3:
+		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
+		break;
+	}
+
+	ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
+	ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
+	ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
+	ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
+	ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
+	ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
+	ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
+	ds->ds_txstat.evm0 = ads->AR_TxEVM0;
+	ds->ds_txstat.evm1 = ads->AR_TxEVM1;
+	ds->ds_txstat.evm2 = ads->AR_TxEVM2;
+	ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
+	ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
+	ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
+	ds->ds_txstat.ts_antenna = 0;
+
+	return 0;
+}
+
+void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
+			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
+			    u32 keyIx, enum ath9k_key_type keyType, u32 flags)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	txPower += ah->txpower_indexoffset;
+	if (txPower > 63)
+		txPower = 63;
+
+	ads->ds_ctl0 = (pktLen & AR_FrameLen)
+		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+		| SM(txPower, AR_XmitPower)
+		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
+
+	ads->ds_ctl1 =
+		(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
+		| SM(type, AR_FrameType)
+		| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+		| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+		| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+	ads->ds_ctl6 = SM(keyType, AR_EncrType);
+
+	if (AR_SREV_9285(ah)) {
+		ads->ds_ctl8 = 0;
+		ads->ds_ctl9 = 0;
+		ads->ds_ctl10 = 0;
+		ads->ds_ctl11 = 0;
+	}
+}
+
+void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
+				  struct ath_desc *lastds,
+				  u32 durUpdateEn, u32 rtsctsRate,
+				  u32 rtsctsDuration,
+				  struct ath9k_11n_rate_series series[],
+				  u32 nseries, u32 flags)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+	struct ar5416_desc *last_ads = AR5416DESC(lastds);
+	u32 ds_ctl0;
+
+	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+		ds_ctl0 = ads->ds_ctl0;
+
+		if (flags & ATH9K_TXDESC_RTSENA) {
+			ds_ctl0 &= ~AR_CTSEnable;
+			ds_ctl0 |= AR_RTSEnable;
+		} else {
+			ds_ctl0 &= ~AR_RTSEnable;
+			ds_ctl0 |= AR_CTSEnable;
+		}
+
+		ads->ds_ctl0 = ds_ctl0;
+	} else {
+		ads->ds_ctl0 =
+			(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
+	}
+
+	ads->ds_ctl2 = set11nTries(series, 0)
+		| set11nTries(series, 1)
+		| set11nTries(series, 2)
+		| set11nTries(series, 3)
+		| (durUpdateEn ? AR_DurUpdateEna : 0)
+		| SM(0, AR_BurstDur);
+
+	ads->ds_ctl3 = set11nRate(series, 0)
+		| set11nRate(series, 1)
+		| set11nRate(series, 2)
+		| set11nRate(series, 3);
+
+	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
+		| set11nPktDurRTSCTS(series, 1);
+
+	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
+		| set11nPktDurRTSCTS(series, 3);
+
+	ads->ds_ctl7 = set11nRateFlags(series, 0)
+		| set11nRateFlags(series, 1)
+		| set11nRateFlags(series, 2)
+		| set11nRateFlags(series, 3)
+		| SM(rtsctsRate, AR_RTSCTSRate);
+	last_ads->ds_ctl2 = ads->ds_ctl2;
+	last_ads->ds_ctl3 = ads->ds_ctl3;
+}
+
+void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
+				u32 aggrLen)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+	ads->ds_ctl6 &= ~AR_AggrLen;
+	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+}
+
+void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
+				 u32 numDelims)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+	unsigned int ctl6;
+
+	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+
+	ctl6 = ads->ds_ctl6;
+	ctl6 &= ~AR_PadDelim;
+	ctl6 |= SM(numDelims, AR_PadDelim);
+	ads->ds_ctl6 = ctl6;
+}
+
+void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl1 |= AR_IsAggr;
+	ads->ds_ctl1 &= ~AR_MoreAggr;
+	ads->ds_ctl6 &= ~AR_PadDelim;
+}
+
+void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+}
+
+void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
+				   u32 burstDuration)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	ads->ds_ctl2 &= ~AR_BurstDur;
+	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
+}
+
+void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
+				     u32 vmf)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+
+	if (vmf)
+		ads->ds_ctl0 |= AR_VirtMoreFrag;
+	else
+		ads->ds_ctl0 &= ~AR_VirtMoreFrag;
+}
+
+void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
+{
+	*txqs &= ah->intr_txqs;
+	ah->intr_txqs &= ~(*txqs);
+}
+
+bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
+			    const struct ath9k_tx_queue_info *qinfo)
+{
+	u32 cw;
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	struct ath9k_tx_queue_info *qi;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
+			"invalid queue: %u\n", q);
+		return false;
+	}
+
+	qi = &ah->txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
+			"inactive queue: %u\n", q);
+		return false;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
+
+	qi->tqi_ver = qinfo->tqi_ver;
+	qi->tqi_subtype = qinfo->tqi_subtype;
+	qi->tqi_qflags = qinfo->tqi_qflags;
+	qi->tqi_priority = qinfo->tqi_priority;
+	if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
+		qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
+	else
+		qi->tqi_aifs = INIT_AIFS;
+	if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
+		cw = min(qinfo->tqi_cwmin, 1024U);
+		qi->tqi_cwmin = 1;
+		while (qi->tqi_cwmin < cw)
+			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
+	} else
+		qi->tqi_cwmin = qinfo->tqi_cwmin;
+	if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
+		cw = min(qinfo->tqi_cwmax, 1024U);
+		qi->tqi_cwmax = 1;
+		while (qi->tqi_cwmax < cw)
+			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
+	} else
+		qi->tqi_cwmax = INIT_CWMAX;
+
+	if (qinfo->tqi_shretry != 0)
+		qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
+	else
+		qi->tqi_shretry = INIT_SH_RETRY;
+	if (qinfo->tqi_lgretry != 0)
+		qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
+	else
+		qi->tqi_lgretry = INIT_LG_RETRY;
+	qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
+	qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
+	qi->tqi_burstTime = qinfo->tqi_burstTime;
+	qi->tqi_readyTime = qinfo->tqi_readyTime;
+
+	switch (qinfo->tqi_subtype) {
+	case ATH9K_WME_UPSD:
+		if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
+			qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
+			    struct ath9k_tx_queue_info *qinfo)
+{
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	struct ath9k_tx_queue_info *qi;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
+			"invalid queue: %u\n", q);
+		return false;
+	}
+
+	qi = &ah->txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
+			"inactive queue: %u\n", q);
+		return false;
+	}
+
+	qinfo->tqi_qflags = qi->tqi_qflags;
+	qinfo->tqi_ver = qi->tqi_ver;
+	qinfo->tqi_subtype = qi->tqi_subtype;
+	qinfo->tqi_qflags = qi->tqi_qflags;
+	qinfo->tqi_priority = qi->tqi_priority;
+	qinfo->tqi_aifs = qi->tqi_aifs;
+	qinfo->tqi_cwmin = qi->tqi_cwmin;
+	qinfo->tqi_cwmax = qi->tqi_cwmax;
+	qinfo->tqi_shretry = qi->tqi_shretry;
+	qinfo->tqi_lgretry = qi->tqi_lgretry;
+	qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
+	qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
+	qinfo->tqi_burstTime = qi->tqi_burstTime;
+	qinfo->tqi_readyTime = qi->tqi_readyTime;
+
+	return true;
+}
+
+int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
+			  const struct ath9k_tx_queue_info *qinfo)
+{
+	struct ath9k_tx_queue_info *qi;
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	int q;
+
+	switch (type) {
+	case ATH9K_TX_QUEUE_BEACON:
+		q = pCap->total_queues - 1;
+		break;
+	case ATH9K_TX_QUEUE_CAB:
+		q = pCap->total_queues - 2;
+		break;
+	case ATH9K_TX_QUEUE_PSPOLL:
+		q = 1;
+		break;
+	case ATH9K_TX_QUEUE_UAPSD:
+		q = pCap->total_queues - 3;
+		break;
+	case ATH9K_TX_QUEUE_DATA:
+		for (q = 0; q < pCap->total_queues; q++)
+			if (ah->txq[q].tqi_type ==
+			    ATH9K_TX_QUEUE_INACTIVE)
+				break;
+		if (q == pCap->total_queues) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"No available TX queue\n");
+			return -1;
+		}
+		break;
+	default:
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n",
+			type);
+		return -1;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
+
+	qi = &ah->txq[q];
+	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"TX queue: %u already active\n", q);
+		return -1;
+	}
+	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
+	qi->tqi_type = type;
+	if (qinfo == NULL) {
+		qi->tqi_qflags =
+			TXQ_FLAG_TXOKINT_ENABLE
+			| TXQ_FLAG_TXERRINT_ENABLE
+			| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
+		qi->tqi_aifs = INIT_AIFS;
+		qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+		qi->tqi_cwmax = INIT_CWMAX;
+		qi->tqi_shretry = INIT_SH_RETRY;
+		qi->tqi_lgretry = INIT_LG_RETRY;
+		qi->tqi_physCompBuf = 0;
+	} else {
+		qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+		(void) ath9k_hw_set_txq_props(ah, q, qinfo);
+	}
+
+	return q;
+}
+
+bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
+{
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	struct ath9k_tx_queue_info *qi;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
+			"invalid queue: %u\n", q);
+		return false;
+	}
+	qi = &ah->txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
+			"inactive queue: %u\n", q);
+		return false;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
+
+	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
+	ah->txok_interrupt_mask &= ~(1 << q);
+	ah->txerr_interrupt_mask &= ~(1 << q);
+	ah->txdesc_interrupt_mask &= ~(1 << q);
+	ah->txeol_interrupt_mask &= ~(1 << q);
+	ah->txurn_interrupt_mask &= ~(1 << q);
+	ath9k_hw_set_txq_interrupts(ah, qi);
+
+	return true;
+}
+
+bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
+{
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	struct ath9k_channel *chan = ah->curchan;
+	struct ath9k_tx_queue_info *qi;
+	u32 cwMin, chanCwMin, value;
+
+	if (q >= pCap->total_queues) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
+			"invalid queue: %u\n", q);
+		return false;
+	}
+
+	qi = &ah->txq[q];
+	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
+			"inactive queue: %u\n", q);
+		return true;
+	}
+
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
+
+	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
+		if (chan && IS_CHAN_B(chan))
+			chanCwMin = INIT_CWMIN_11B;
+		else
+			chanCwMin = INIT_CWMIN;
+
+		for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
+	} else
+		cwMin = qi->tqi_cwmin;
+
+	REG_WRITE(ah, AR_DLCL_IFS(q),
+		  SM(cwMin, AR_D_LCL_IFS_CWMIN) |
+		  SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
+		  SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+	REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+		  SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
+		  SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
+		  SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
+
+	REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
+	REG_WRITE(ah, AR_DMISC(q),
+		  AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
+
+	if (qi->tqi_cbrPeriod) {
+		REG_WRITE(ah, AR_QCBRCFG(q),
+			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
+			  SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
+		REG_WRITE(ah, AR_QMISC(q),
+			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
+			  (qi->tqi_cbrOverflowLimit ?
+			   AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
+	}
+	if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
+		REG_WRITE(ah, AR_QRDYTIMECFG(q),
+			  SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
+			  AR_Q_RDYTIMECFG_EN);
+	}
+
+	REG_WRITE(ah, AR_DCHNTIME(q),
+		  SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
+		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+
+	if (qi->tqi_burstTime
+	    && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
+		REG_WRITE(ah, AR_QMISC(q),
+			  REG_READ(ah, AR_QMISC(q)) |
+			  AR_Q_MISC_RDYTIME_EXP_POLICY);
+
+	}
+
+	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
+		REG_WRITE(ah, AR_DMISC(q),
+			  REG_READ(ah, AR_DMISC(q)) |
+			  AR_D_MISC_POST_FR_BKOFF_DIS);
+	}
+	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
+		REG_WRITE(ah, AR_DMISC(q),
+			  REG_READ(ah, AR_DMISC(q)) |
+			  AR_D_MISC_FRAG_BKOFF_EN);
+	}
+	switch (qi->tqi_type) {
+	case ATH9K_TX_QUEUE_BEACON:
+		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+			  | AR_Q_MISC_FSP_DBA_GATED
+			  | AR_Q_MISC_BEACON_USE
+			  | AR_Q_MISC_CBR_INCR_DIS1);
+
+		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
+			  | AR_D_MISC_BEACON_USE
+			  | AR_D_MISC_POST_FR_BKOFF_DIS);
+		break;
+	case ATH9K_TX_QUEUE_CAB:
+		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+			  | AR_Q_MISC_FSP_DBA_GATED
+			  | AR_Q_MISC_CBR_INCR_DIS1
+			  | AR_Q_MISC_CBR_INCR_DIS0);
+		value = (qi->tqi_readyTime -
+			 (ah->config.sw_beacon_response_time -
+			  ah->config.dma_beacon_response_time) -
+			 ah->config.additional_swba_backoff) * 1024;
+		REG_WRITE(ah, AR_QRDYTIMECFG(q),
+			  value | AR_Q_RDYTIMECFG_EN);
+		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
+		break;
+	case ATH9K_TX_QUEUE_PSPOLL:
+		REG_WRITE(ah, AR_QMISC(q),
+			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
+		break;
+	case ATH9K_TX_QUEUE_UAPSD:
+		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+			  AR_D_MISC_POST_FR_BKOFF_DIS);
+		break;
+	default:
+		break;
+	}
+
+	if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
+		REG_WRITE(ah, AR_DMISC(q),
+			  REG_READ(ah, AR_DMISC(q)) |
+			  SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+			     AR_D_MISC_ARB_LOCKOUT_CNTRL) |
+			  AR_D_MISC_POST_FR_BKOFF_DIS);
+	}
+
+	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
+		ah->txok_interrupt_mask |= 1 << q;
+	else
+		ah->txok_interrupt_mask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
+		ah->txerr_interrupt_mask |= 1 << q;
+	else
+		ah->txerr_interrupt_mask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
+		ah->txdesc_interrupt_mask |= 1 << q;
+	else
+		ah->txdesc_interrupt_mask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
+		ah->txeol_interrupt_mask |= 1 << q;
+	else
+		ah->txeol_interrupt_mask &= ~(1 << q);
+	if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
+		ah->txurn_interrupt_mask |= 1 << q;
+	else
+		ah->txurn_interrupt_mask &= ~(1 << q);
+	ath9k_hw_set_txq_interrupts(ah, qi);
+
+	return true;
+}
+
+int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
+			u32 pa, struct ath_desc *nds, u64 tsf)
+{
+	struct ar5416_desc ads;
+	struct ar5416_desc *adsp = AR5416DESC(ds);
+	u32 phyerr;
+
+	if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
+		return -EINPROGRESS;
+
+	ads.u.rx = adsp->u.rx;
+
+	ds->ds_rxstat.rs_status = 0;
+	ds->ds_rxstat.rs_flags = 0;
+
+	ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
+	ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
+
+	ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+	ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
+	ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
+	ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
+	ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
+	ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
+	ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
+	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+		ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
+	else
+		ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+	ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
+	ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+	ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+	ds->ds_rxstat.rs_moreaggr =
+		(ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+	ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
+	ds->ds_rxstat.rs_flags =
+		(ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
+	ds->ds_rxstat.rs_flags |=
+		(ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+	if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
+		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
+		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+	if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
+		ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+		if (ads.ds_rxstatus8 & AR_CRCErr)
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
+		else if (ads.ds_rxstatus8 & AR_PHYErr) {
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
+			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
+			ds->ds_rxstat.rs_phyerr = phyerr;
+		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
+		else if (ads.ds_rxstatus8 & AR_MichaelErr)
+			ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
+	}
+
+	return 0;
+}
+
+bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+			  u32 size, u32 flags)
+{
+	struct ar5416_desc *ads = AR5416DESC(ds);
+	struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+	ads->ds_ctl1 = size & AR_BufLen;
+	if (flags & ATH9K_RXDESC_INTREQ)
+		ads->ds_ctl1 |= AR_RxIntrReq;
+
+	ads->ds_rxstatus8 &= ~AR_RxDone;
+	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+		memset(&(ads->u), 0, sizeof(ads->u));
+
+	return true;
+}
+
+bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
+{
+	u32 reg;
+
+	if (set) {
+		REG_SET_BIT(ah, AR_DIAG_SW,
+			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+		if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
+				   0, AH_WAIT_TIMEOUT)) {
+			REG_CLR_BIT(ah, AR_DIAG_SW,
+				    (AR_DIAG_RX_DIS |
+				     AR_DIAG_RX_ABORT));
+
+			reg = REG_READ(ah, AR_OBS_BUS_1);
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"RX failed to go idle in 10 ms RXSM=0x%x\n", reg);
+
+			return false;
+		}
+	} else {
+		REG_CLR_BIT(ah, AR_DIAG_SW,
+			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+	}
+
+	return true;
+}
+
+void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
+{
+	REG_WRITE(ah, AR_RXDP, rxdp);
+}
+
+void ath9k_hw_rxena(struct ath_hw *ah)
+{
+	REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+void ath9k_hw_startpcureceive(struct ath_hw *ah)
+{
+	ath9k_enable_mib_counters(ah);
+
+	ath9k_ani_reset(ah);
+
+	REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+}
+
+void ath9k_hw_stoppcurecv(struct ath_hw *ah)
+{
+	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
+
+	ath9k_hw_disable_mib_counters(ah);
+}
+
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
+{
+#define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
+#define AH_RX_TIME_QUANTUM     100     /* usec */
+
+	int i;
+
+	REG_WRITE(ah, AR_CR, AR_CR_RXD);
+
+	/* Wait for rx enable bit to go low */
+	for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
+		if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
+			break;
+		udelay(AH_TIME_QUANTUM);
+	}
+
+	if (i == 0) {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"DMA failed to stop in %d ms "
+			"AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+			AH_RX_STOP_DMA_TIMEOUT / 1000,
+			REG_READ(ah, AR_CR),
+			REG_READ(ah, AR_DIAG_SW));
+		return false;
+	} else {
+		return true;
+	}
+
+#undef AH_RX_TIME_QUANTUM
+#undef AH_RX_STOP_DMA_TIMEOUT
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/mac.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/mac.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/mac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/mac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MAC_H
+#define MAC_H
+
+#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ?		\
+				MS(ads->ds_rxstatus0, AR_RxRate) :	\
+				(ads->ds_rxstatus3 >> 2) & 0xFF)
+
+#define set11nTries(_series, _index) \
+	(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
+
+#define set11nRate(_series, _index) \
+	(SM((_series)[_index].Rate, AR_XmitRate##_index))
+
+#define set11nPktDurRTSCTS(_series, _index)				\
+	(SM((_series)[_index].PktDuration, AR_PacketDur##_index) |	\
+	 ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS   ?	\
+	  AR_RTSCTSQual##_index : 0))
+
+#define set11nRateFlags(_series, _index)				\
+	(((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ?		\
+	  AR_2040_##_index : 0)						\
+	 |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ?	\
+	   AR_GI##_index : 0)						\
+	 |SM((_series)[_index].ChSel, AR_ChainSel##_index))
+
+#define CCK_SIFS_TIME        10
+#define CCK_PREAMBLE_BITS   144
+#define CCK_PLCP_BITS        48
+
+#define OFDM_SIFS_TIME        16
+#define OFDM_PREAMBLE_TIME    20
+#define OFDM_PLCP_BITS        22
+#define OFDM_SYMBOL_TIME      4
+
+#define OFDM_SIFS_TIME_HALF     32
+#define OFDM_PREAMBLE_TIME_HALF 40
+#define OFDM_PLCP_BITS_HALF     22
+#define OFDM_SYMBOL_TIME_HALF   8
+
+#define OFDM_SIFS_TIME_QUARTER      64
+#define OFDM_PREAMBLE_TIME_QUARTER  80
+#define OFDM_PLCP_BITS_QUARTER      22
+#define OFDM_SYMBOL_TIME_QUARTER    16
+
+#define INIT_AIFS       2
+#define INIT_CWMIN      15
+#define INIT_CWMIN_11B  31
+#define INIT_CWMAX      1023
+#define INIT_SH_RETRY   10
+#define INIT_LG_RETRY   10
+#define INIT_SSH_RETRY  32
+#define INIT_SLG_RETRY  32
+
+#define ATH9K_SLOT_TIME_6 6
+#define ATH9K_SLOT_TIME_9 9
+#define ATH9K_SLOT_TIME_20 20
+
+#define ATH9K_TXERR_XRETRY         0x01
+#define ATH9K_TXERR_FILT           0x02
+#define ATH9K_TXERR_FIFO           0x04
+#define ATH9K_TXERR_XTXOP          0x08
+#define ATH9K_TXERR_TIMER_EXPIRED  0x10
+
+#define ATH9K_TX_BA                0x01
+#define ATH9K_TX_PWRMGMT           0x02
+#define ATH9K_TX_DESC_CFG_ERR      0x04
+#define ATH9K_TX_DATA_UNDERRUN     0x08
+#define ATH9K_TX_DELIM_UNDERRUN    0x10
+#define ATH9K_TX_SW_ABORTED        0x40
+#define ATH9K_TX_SW_FILTERED       0x80
+
+#define MIN_TX_FIFO_THRESHOLD   0x1
+#define MAX_TX_FIFO_THRESHOLD   ((4096 / 64) - 1)
+#define INIT_TX_FIFO_THRESHOLD  MIN_TX_FIFO_THRESHOLD
+
+struct ath_tx_status {
+	u32 ts_tstamp;
+	u16 ts_seqnum;
+	u8 ts_status;
+	u8 ts_ratecode;
+	u8 ts_rateindex;
+	int8_t ts_rssi;
+	u8 ts_shortretry;
+	u8 ts_longretry;
+	u8 ts_virtcol;
+	u8 ts_antenna;
+	u8 ts_flags;
+	int8_t ts_rssi_ctl0;
+	int8_t ts_rssi_ctl1;
+	int8_t ts_rssi_ctl2;
+	int8_t ts_rssi_ext0;
+	int8_t ts_rssi_ext1;
+	int8_t ts_rssi_ext2;
+	u8 pad[3];
+	u32 ba_low;
+	u32 ba_high;
+	u32 evm0;
+	u32 evm1;
+	u32 evm2;
+};
+
+struct ath_rx_status {
+	u32 rs_tstamp;
+	u16 rs_datalen;
+	u8 rs_status;
+	u8 rs_phyerr;
+	int8_t rs_rssi;
+	u8 rs_keyix;
+	u8 rs_rate;
+	u8 rs_antenna;
+	u8 rs_more;
+	int8_t rs_rssi_ctl0;
+	int8_t rs_rssi_ctl1;
+	int8_t rs_rssi_ctl2;
+	int8_t rs_rssi_ext0;
+	int8_t rs_rssi_ext1;
+	int8_t rs_rssi_ext2;
+	u8 rs_isaggr;
+	u8 rs_moreaggr;
+	u8 rs_num_delims;
+	u8 rs_flags;
+	u32 evm0;
+	u32 evm1;
+	u32 evm2;
+};
+
+#define ATH9K_RXERR_CRC           0x01
+#define ATH9K_RXERR_PHY           0x02
+#define ATH9K_RXERR_FIFO          0x04
+#define ATH9K_RXERR_DECRYPT       0x08
+#define ATH9K_RXERR_MIC           0x10
+
+#define ATH9K_RX_MORE             0x01
+#define ATH9K_RX_MORE_AGGR        0x02
+#define ATH9K_RX_GI               0x04
+#define ATH9K_RX_2040             0x08
+#define ATH9K_RX_DELIM_CRC_PRE    0x10
+#define ATH9K_RX_DELIM_CRC_POST   0x20
+#define ATH9K_RX_DECRYPT_BUSY     0x40
+
+#define ATH9K_RXKEYIX_INVALID	((u8)-1)
+#define ATH9K_TXKEYIX_INVALID	((u32)-1)
+
+struct ath_desc {
+	u32 ds_link;
+	u32 ds_data;
+	u32 ds_ctl0;
+	u32 ds_ctl1;
+	u32 ds_hw[20];
+	union {
+		struct ath_tx_status tx;
+		struct ath_rx_status rx;
+		void *stats;
+	} ds_us;
+	void *ds_vdata;
+} __packed;
+
+#define	ds_txstat	ds_us.tx
+#define	ds_rxstat	ds_us.rx
+#define ds_stat		ds_us.stats
+
+#define ATH9K_TXDESC_CLRDMASK		0x0001
+#define ATH9K_TXDESC_NOACK		0x0002
+#define ATH9K_TXDESC_RTSENA		0x0004
+#define ATH9K_TXDESC_CTSENA		0x0008
+/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
+ * the descriptor its marked on.  We take a tx interrupt to reap
+ * descriptors when the h/w hits an EOL condition or
+ * when the descriptor is specifically marked to generate
+ * an interrupt with this flag. Descriptors should be
+ * marked periodically to insure timely replenishing of the
+ * supply needed for sending frames. Defering interrupts
+ * reduces system load and potentially allows more concurrent
+ * work to be done but if done to aggressively can cause
+ * senders to backup. When the hardware queue is left too
+ * large rate control information may also be too out of
+ * date. An Alternative for this is TX interrupt mitigation
+ * but this needs more testing. */
+#define ATH9K_TXDESC_INTREQ		0x0010
+#define ATH9K_TXDESC_VEOL		0x0020
+#define ATH9K_TXDESC_EXT_ONLY		0x0040
+#define ATH9K_TXDESC_EXT_AND_CTL	0x0080
+#define ATH9K_TXDESC_VMF		0x0100
+#define ATH9K_TXDESC_FRAG_IS_ON 	0x0200
+#define ATH9K_TXDESC_CAB		0x0400
+
+#define ATH9K_RXDESC_INTREQ		0x0020
+
+struct ar5416_desc {
+	u32 ds_link;
+	u32 ds_data;
+	u32 ds_ctl0;
+	u32 ds_ctl1;
+	union {
+		struct {
+			u32 ctl2;
+			u32 ctl3;
+			u32 ctl4;
+			u32 ctl5;
+			u32 ctl6;
+			u32 ctl7;
+			u32 ctl8;
+			u32 ctl9;
+			u32 ctl10;
+			u32 ctl11;
+			u32 status0;
+			u32 status1;
+			u32 status2;
+			u32 status3;
+			u32 status4;
+			u32 status5;
+			u32 status6;
+			u32 status7;
+			u32 status8;
+			u32 status9;
+		} tx;
+		struct {
+			u32 status0;
+			u32 status1;
+			u32 status2;
+			u32 status3;
+			u32 status4;
+			u32 status5;
+			u32 status6;
+			u32 status7;
+			u32 status8;
+		} rx;
+	} u;
+} __packed;
+
+#define AR5416DESC(_ds)         ((struct ar5416_desc *)(_ds))
+#define AR5416DESC_CONST(_ds)   ((const struct ar5416_desc *)(_ds))
+
+#define ds_ctl2     u.tx.ctl2
+#define ds_ctl3     u.tx.ctl3
+#define ds_ctl4     u.tx.ctl4
+#define ds_ctl5     u.tx.ctl5
+#define ds_ctl6     u.tx.ctl6
+#define ds_ctl7     u.tx.ctl7
+#define ds_ctl8     u.tx.ctl8
+#define ds_ctl9     u.tx.ctl9
+#define ds_ctl10    u.tx.ctl10
+#define ds_ctl11    u.tx.ctl11
+
+#define ds_txstatus0    u.tx.status0
+#define ds_txstatus1    u.tx.status1
+#define ds_txstatus2    u.tx.status2
+#define ds_txstatus3    u.tx.status3
+#define ds_txstatus4    u.tx.status4
+#define ds_txstatus5    u.tx.status5
+#define ds_txstatus6    u.tx.status6
+#define ds_txstatus7    u.tx.status7
+#define ds_txstatus8    u.tx.status8
+#define ds_txstatus9    u.tx.status9
+
+#define ds_rxstatus0    u.rx.status0
+#define ds_rxstatus1    u.rx.status1
+#define ds_rxstatus2    u.rx.status2
+#define ds_rxstatus3    u.rx.status3
+#define ds_rxstatus4    u.rx.status4
+#define ds_rxstatus5    u.rx.status5
+#define ds_rxstatus6    u.rx.status6
+#define ds_rxstatus7    u.rx.status7
+#define ds_rxstatus8    u.rx.status8
+
+#define AR_FrameLen         0x00000fff
+#define AR_VirtMoreFrag     0x00001000
+#define AR_TxCtlRsvd00      0x0000e000
+#define AR_XmitPower        0x003f0000
+#define AR_XmitPower_S      16
+#define AR_RTSEnable        0x00400000
+#define AR_VEOL             0x00800000
+#define AR_ClrDestMask      0x01000000
+#define AR_TxCtlRsvd01      0x1e000000
+#define AR_TxIntrReq        0x20000000
+#define AR_DestIdxValid     0x40000000
+#define AR_CTSEnable        0x80000000
+
+#define AR_BufLen           0x00000fff
+#define AR_TxMore           0x00001000
+#define AR_DestIdx          0x000fe000
+#define AR_DestIdx_S        13
+#define AR_FrameType        0x00f00000
+#define AR_FrameType_S      20
+#define AR_NoAck            0x01000000
+#define AR_InsertTS         0x02000000
+#define AR_CorruptFCS       0x04000000
+#define AR_ExtOnly          0x08000000
+#define AR_ExtAndCtl        0x10000000
+#define AR_MoreAggr         0x20000000
+#define AR_IsAggr           0x40000000
+
+#define AR_BurstDur         0x00007fff
+#define AR_BurstDur_S       0
+#define AR_DurUpdateEna     0x00008000
+#define AR_XmitDataTries0   0x000f0000
+#define AR_XmitDataTries0_S 16
+#define AR_XmitDataTries1   0x00f00000
+#define AR_XmitDataTries1_S 20
+#define AR_XmitDataTries2   0x0f000000
+#define AR_XmitDataTries2_S 24
+#define AR_XmitDataTries3   0xf0000000
+#define AR_XmitDataTries3_S 28
+
+#define AR_XmitRate0        0x000000ff
+#define AR_XmitRate0_S      0
+#define AR_XmitRate1        0x0000ff00
+#define AR_XmitRate1_S      8
+#define AR_XmitRate2        0x00ff0000
+#define AR_XmitRate2_S      16
+#define AR_XmitRate3        0xff000000
+#define AR_XmitRate3_S      24
+
+#define AR_PacketDur0       0x00007fff
+#define AR_PacketDur0_S     0
+#define AR_RTSCTSQual0      0x00008000
+#define AR_PacketDur1       0x7fff0000
+#define AR_PacketDur1_S     16
+#define AR_RTSCTSQual1      0x80000000
+
+#define AR_PacketDur2       0x00007fff
+#define AR_PacketDur2_S     0
+#define AR_RTSCTSQual2      0x00008000
+#define AR_PacketDur3       0x7fff0000
+#define AR_PacketDur3_S     16
+#define AR_RTSCTSQual3      0x80000000
+
+#define AR_AggrLen          0x0000ffff
+#define AR_AggrLen_S        0
+#define AR_TxCtlRsvd60      0x00030000
+#define AR_PadDelim         0x03fc0000
+#define AR_PadDelim_S       18
+#define AR_EncrType         0x0c000000
+#define AR_EncrType_S       26
+#define AR_TxCtlRsvd61      0xf0000000
+
+#define AR_2040_0           0x00000001
+#define AR_GI0              0x00000002
+#define AR_ChainSel0        0x0000001c
+#define AR_ChainSel0_S      2
+#define AR_2040_1           0x00000020
+#define AR_GI1              0x00000040
+#define AR_ChainSel1        0x00000380
+#define AR_ChainSel1_S      7
+#define AR_2040_2           0x00000400
+#define AR_GI2              0x00000800
+#define AR_ChainSel2        0x00007000
+#define AR_ChainSel2_S      12
+#define AR_2040_3           0x00008000
+#define AR_GI3              0x00010000
+#define AR_ChainSel3        0x000e0000
+#define AR_ChainSel3_S      17
+#define AR_RTSCTSRate       0x0ff00000
+#define AR_RTSCTSRate_S     20
+#define AR_TxCtlRsvd70      0xf0000000
+
+#define AR_TxRSSIAnt00      0x000000ff
+#define AR_TxRSSIAnt00_S    0
+#define AR_TxRSSIAnt01      0x0000ff00
+#define AR_TxRSSIAnt01_S    8
+#define AR_TxRSSIAnt02      0x00ff0000
+#define AR_TxRSSIAnt02_S    16
+#define AR_TxStatusRsvd00   0x3f000000
+#define AR_TxBaStatus       0x40000000
+#define AR_TxStatusRsvd01   0x80000000
+
+#define AR_FrmXmitOK            0x00000001
+#define AR_ExcessiveRetries     0x00000002
+#define AR_FIFOUnderrun         0x00000004
+#define AR_Filtered             0x00000008
+#define AR_RTSFailCnt           0x000000f0
+#define AR_RTSFailCnt_S         4
+#define AR_DataFailCnt          0x00000f00
+#define AR_DataFailCnt_S        8
+#define AR_VirtRetryCnt         0x0000f000
+#define AR_VirtRetryCnt_S       12
+#define AR_TxDelimUnderrun      0x00010000
+#define AR_TxDataUnderrun       0x00020000
+#define AR_DescCfgErr           0x00040000
+#define AR_TxTimerExpired       0x00080000
+#define AR_TxStatusRsvd10       0xfff00000
+
+#define AR_SendTimestamp    ds_txstatus2
+#define AR_BaBitmapLow      ds_txstatus3
+#define AR_BaBitmapHigh     ds_txstatus4
+
+#define AR_TxRSSIAnt10      0x000000ff
+#define AR_TxRSSIAnt10_S    0
+#define AR_TxRSSIAnt11      0x0000ff00
+#define AR_TxRSSIAnt11_S    8
+#define AR_TxRSSIAnt12      0x00ff0000
+#define AR_TxRSSIAnt12_S    16
+#define AR_TxRSSICombined   0xff000000
+#define AR_TxRSSICombined_S 24
+
+#define AR_TxEVM0           ds_txstatus5
+#define AR_TxEVM1           ds_txstatus6
+#define AR_TxEVM2           ds_txstatus7
+
+#define AR_TxDone           0x00000001
+#define AR_SeqNum           0x00001ffe
+#define AR_SeqNum_S         1
+#define AR_TxStatusRsvd80   0x0001e000
+#define AR_TxOpExceeded     0x00020000
+#define AR_TxStatusRsvd81   0x001c0000
+#define AR_FinalTxIdx       0x00600000
+#define AR_FinalTxIdx_S     21
+#define AR_TxStatusRsvd82   0x01800000
+#define AR_PowerMgmt        0x02000000
+#define AR_TxStatusRsvd83   0xfc000000
+
+#define AR_RxCTLRsvd00  0xffffffff
+
+#define AR_BufLen       0x00000fff
+#define AR_RxCtlRsvd00  0x00001000
+#define AR_RxIntrReq    0x00002000
+#define AR_RxCtlRsvd01  0xffffc000
+
+#define AR_RxRSSIAnt00      0x000000ff
+#define AR_RxRSSIAnt00_S    0
+#define AR_RxRSSIAnt01      0x0000ff00
+#define AR_RxRSSIAnt01_S    8
+#define AR_RxRSSIAnt02      0x00ff0000
+#define AR_RxRSSIAnt02_S    16
+#define AR_RxRate           0xff000000
+#define AR_RxRate_S         24
+#define AR_RxStatusRsvd00   0xff000000
+
+#define AR_DataLen          0x00000fff
+#define AR_RxMore           0x00001000
+#define AR_NumDelim         0x003fc000
+#define AR_NumDelim_S       14
+#define AR_RxStatusRsvd10   0xff800000
+
+#define AR_RcvTimestamp     ds_rxstatus2
+
+#define AR_GI               0x00000001
+#define AR_2040             0x00000002
+#define AR_Parallel40       0x00000004
+#define AR_Parallel40_S     2
+#define AR_RxStatusRsvd30   0x000000f8
+#define AR_RxAntenna	    0xffffff00
+#define AR_RxAntenna_S	    8
+
+#define AR_RxRSSIAnt10            0x000000ff
+#define AR_RxRSSIAnt10_S          0
+#define AR_RxRSSIAnt11            0x0000ff00
+#define AR_RxRSSIAnt11_S          8
+#define AR_RxRSSIAnt12            0x00ff0000
+#define AR_RxRSSIAnt12_S          16
+#define AR_RxRSSICombined         0xff000000
+#define AR_RxRSSICombined_S       24
+
+#define AR_RxEVM0           ds_rxstatus4
+#define AR_RxEVM1           ds_rxstatus5
+#define AR_RxEVM2           ds_rxstatus6
+
+#define AR_RxDone           0x00000001
+#define AR_RxFrameOK        0x00000002
+#define AR_CRCErr           0x00000004
+#define AR_DecryptCRCErr    0x00000008
+#define AR_PHYErr           0x00000010
+#define AR_MichaelErr       0x00000020
+#define AR_PreDelimCRCErr   0x00000040
+#define AR_RxStatusRsvd70   0x00000080
+#define AR_RxKeyIdxValid    0x00000100
+#define AR_KeyIdx           0x0000fe00
+#define AR_KeyIdx_S         9
+#define AR_PHYErrCode       0x0000ff00
+#define AR_PHYErrCode_S     8
+#define AR_RxMoreAggr       0x00010000
+#define AR_RxAggr           0x00020000
+#define AR_PostDelimCRCErr  0x00040000
+#define AR_RxStatusRsvd71   0x3ff80000
+#define AR_DecryptBusyErr   0x40000000
+#define AR_KeyMiss          0x80000000
+
+enum ath9k_tx_queue {
+	ATH9K_TX_QUEUE_INACTIVE = 0,
+	ATH9K_TX_QUEUE_DATA,
+	ATH9K_TX_QUEUE_BEACON,
+	ATH9K_TX_QUEUE_CAB,
+	ATH9K_TX_QUEUE_UAPSD,
+	ATH9K_TX_QUEUE_PSPOLL
+};
+
+#define	ATH9K_NUM_TX_QUEUES 10
+
+enum ath9k_tx_queue_subtype {
+	ATH9K_WME_AC_BK = 0,
+	ATH9K_WME_AC_BE,
+	ATH9K_WME_AC_VI,
+	ATH9K_WME_AC_VO,
+	ATH9K_WME_UPSD
+};
+
+enum ath9k_tx_queue_flags {
+	TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
+	TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
+	TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
+	TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
+	TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
+	TXQ_FLAG_BACKOFF_DISABLE = 0x0010,
+	TXQ_FLAG_COMPRESSION_ENABLE = 0x0020,
+	TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040,
+	TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080,
+};
+
+#define ATH9K_TXQ_USEDEFAULT ((u32) -1)
+#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
+
+#define ATH9K_DECOMP_MASK_SIZE     128
+#define ATH9K_READY_TIME_LO_BOUND  50
+#define ATH9K_READY_TIME_HI_BOUND  96
+
+enum ath9k_pkt_type {
+	ATH9K_PKT_TYPE_NORMAL = 0,
+	ATH9K_PKT_TYPE_ATIM,
+	ATH9K_PKT_TYPE_PSPOLL,
+	ATH9K_PKT_TYPE_BEACON,
+	ATH9K_PKT_TYPE_PROBE_RESP,
+	ATH9K_PKT_TYPE_CHIRP,
+	ATH9K_PKT_TYPE_GRP_POLL,
+};
+
+struct ath9k_tx_queue_info {
+	u32 tqi_ver;
+	enum ath9k_tx_queue tqi_type;
+	enum ath9k_tx_queue_subtype tqi_subtype;
+	enum ath9k_tx_queue_flags tqi_qflags;
+	u32 tqi_priority;
+	u32 tqi_aifs;
+	u32 tqi_cwmin;
+	u32 tqi_cwmax;
+	u16 tqi_shretry;
+	u16 tqi_lgretry;
+	u32 tqi_cbrPeriod;
+	u32 tqi_cbrOverflowLimit;
+	u32 tqi_burstTime;
+	u32 tqi_readyTime;
+	u32 tqi_physCompBuf;
+	u32 tqi_intFlags;
+};
+
+enum ath9k_rx_filter {
+	ATH9K_RX_FILTER_UCAST = 0x00000001,
+	ATH9K_RX_FILTER_MCAST = 0x00000002,
+	ATH9K_RX_FILTER_BCAST = 0x00000004,
+	ATH9K_RX_FILTER_CONTROL = 0x00000008,
+	ATH9K_RX_FILTER_BEACON = 0x00000010,
+	ATH9K_RX_FILTER_PROM = 0x00000020,
+	ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
+	ATH9K_RX_FILTER_PHYERR = 0x00000100,
+	ATH9K_RX_FILTER_MYBEACON = 0x00000200,
+	ATH9K_RX_FILTER_PSPOLL = 0x00004000,
+	ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
+	ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
+};
+
+#define ATH9K_RATESERIES_RTS_CTS  0x0001
+#define ATH9K_RATESERIES_2040     0x0002
+#define ATH9K_RATESERIES_HALFGI   0x0004
+
+struct ath9k_11n_rate_series {
+	u32 Tries;
+	u32 Rate;
+	u32 PktDuration;
+	u32 ChSel;
+	u32 RateFlags;
+};
+
+struct ath9k_keyval {
+	u8 kv_type;
+	u8 kv_pad;
+	u16 kv_len;
+	u8 kv_val[16]; /* TK */
+	u8 kv_mic[8]; /* Michael MIC key */
+	u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
+			 * supports both MIC keys in the same key cache entry;
+			 * in that case, kv_mic is the RX key) */
+};
+
+enum ath9k_key_type {
+	ATH9K_KEY_TYPE_CLEAR,
+	ATH9K_KEY_TYPE_WEP,
+	ATH9K_KEY_TYPE_AES,
+	ATH9K_KEY_TYPE_TKIP,
+};
+
+enum ath9k_cipher {
+	ATH9K_CIPHER_WEP = 0,
+	ATH9K_CIPHER_AES_OCB = 1,
+	ATH9K_CIPHER_AES_CCM = 2,
+	ATH9K_CIPHER_CKIP = 3,
+	ATH9K_CIPHER_TKIP = 4,
+	ATH9K_CIPHER_CLR = 5,
+	ATH9K_CIPHER_MIC = 127
+};
+
+enum ath9k_ht_macmode {
+	ATH9K_HT_MACMODE_20 = 0,
+	ATH9K_HT_MACMODE_2040 = 1,
+};
+
+enum ath9k_ht_extprotspacing {
+	ATH9K_HT_EXTPROTSPACING_20 = 0,
+	ATH9K_HT_EXTPROTSPACING_25 = 1,
+};
+
+struct ath_hw;
+struct ath9k_channel;
+struct ath_rate_table;
+
+u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
+bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
+bool ath9k_hw_txstart(struct ath_hw *ah, u32 q);
+u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
+bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
+bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
+bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
+			 u32 segLen, bool firstSeg,
+			 bool lastSeg, const struct ath_desc *ds0);
+void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
+int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
+			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
+			    u32 keyIx, enum ath9k_key_type keyType, u32 flags);
+void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
+				  struct ath_desc *lastds,
+				  u32 durUpdateEn, u32 rtsctsRate,
+				  u32 rtsctsDuration,
+				  struct ath9k_11n_rate_series series[],
+				  u32 nseries, u32 flags);
+void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
+				u32 aggrLen);
+void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
+				 u32 numDelims);
+void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds);
+void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
+				   u32 burstDuration);
+void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
+				     u32 vmf);
+void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
+bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
+			    const struct ath9k_tx_queue_info *qinfo);
+bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
+			    struct ath9k_tx_queue_info *qinfo);
+int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
+			  const struct ath9k_tx_queue_info *qinfo);
+bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
+bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
+int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
+			u32 pa, struct ath_desc *nds, u64 tsf);
+bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
+			  u32 size, u32 flags);
+bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
+void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
+void ath9k_hw_rxena(struct ath_hw *ah);
+void ath9k_hw_startpcureceive(struct ath_hw *ah);
+void ath9k_hw_stoppcurecv(struct ath_hw *ah);
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
+
+#endif /* MAC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2837 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include "ath9k.h"
+
+#define ATH_PCI_VERSION "0.1"
+
+static char *dev_info = "ath9k";
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
+MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+
+/* We use the hw_value as an index into our private channel structure */
+
+#define CHAN2G(_freq, _idx)  { \
+	.center_freq = (_freq), \
+	.hw_value = (_idx), \
+	.max_power = 20, \
+}
+
+#define CHAN5G(_freq, _idx) { \
+	.band = IEEE80211_BAND_5GHZ, \
+	.center_freq = (_freq), \
+	.hw_value = (_idx), \
+	.max_power = 20, \
+}
+
+/* Some 2 GHz radios are actually tunable on 2312-2732
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static struct ieee80211_channel ath9k_2ghz_chantable[] = {
+	CHAN2G(2412, 0), /* Channel 1 */
+	CHAN2G(2417, 1), /* Channel 2 */
+	CHAN2G(2422, 2), /* Channel 3 */
+	CHAN2G(2427, 3), /* Channel 4 */
+	CHAN2G(2432, 4), /* Channel 5 */
+	CHAN2G(2437, 5), /* Channel 6 */
+	CHAN2G(2442, 6), /* Channel 7 */
+	CHAN2G(2447, 7), /* Channel 8 */
+	CHAN2G(2452, 8), /* Channel 9 */
+	CHAN2G(2457, 9), /* Channel 10 */
+	CHAN2G(2462, 10), /* Channel 11 */
+	CHAN2G(2467, 11), /* Channel 12 */
+	CHAN2G(2472, 12), /* Channel 13 */
+	CHAN2G(2484, 13), /* Channel 14 */
+};
+
+/* Some 5 GHz radios are actually tunable on XXXX-YYYY
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+static struct ieee80211_channel ath9k_5ghz_chantable[] = {
+	/* _We_ call this UNII 1 */
+	CHAN5G(5180, 14), /* Channel 36 */
+	CHAN5G(5200, 15), /* Channel 40 */
+	CHAN5G(5220, 16), /* Channel 44 */
+	CHAN5G(5240, 17), /* Channel 48 */
+	/* _We_ call this UNII 2 */
+	CHAN5G(5260, 18), /* Channel 52 */
+	CHAN5G(5280, 19), /* Channel 56 */
+	CHAN5G(5300, 20), /* Channel 60 */
+	CHAN5G(5320, 21), /* Channel 64 */
+	/* _We_ call this "Middle band" */
+	CHAN5G(5500, 22), /* Channel 100 */
+	CHAN5G(5520, 23), /* Channel 104 */
+	CHAN5G(5540, 24), /* Channel 108 */
+	CHAN5G(5560, 25), /* Channel 112 */
+	CHAN5G(5580, 26), /* Channel 116 */
+	CHAN5G(5600, 27), /* Channel 120 */
+	CHAN5G(5620, 28), /* Channel 124 */
+	CHAN5G(5640, 29), /* Channel 128 */
+	CHAN5G(5660, 30), /* Channel 132 */
+	CHAN5G(5680, 31), /* Channel 136 */
+	CHAN5G(5700, 32), /* Channel 140 */
+	/* _We_ call this UNII 3 */
+	CHAN5G(5745, 33), /* Channel 149 */
+	CHAN5G(5765, 34), /* Channel 153 */
+	CHAN5G(5785, 35), /* Channel 157 */
+	CHAN5G(5805, 36), /* Channel 161 */
+	CHAN5G(5825, 37), /* Channel 165 */
+};
+
+static void ath_cache_conf_rate(struct ath_softc *sc,
+				struct ieee80211_conf *conf)
+{
+	switch (conf->channel->band) {
+	case IEEE80211_BAND_2GHZ:
+		if (conf_is_ht20(conf))
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
+		else if (conf_is_ht40_minus(conf))
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
+		else if (conf_is_ht40_plus(conf))
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
+		else
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11G];
+		break;
+	case IEEE80211_BAND_5GHZ:
+		if (conf_is_ht20(conf))
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
+		else if (conf_is_ht40_minus(conf))
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
+		else if (conf_is_ht40_plus(conf))
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
+		else
+			sc->cur_rate_table =
+			  sc->hw_rate_table[ATH9K_MODE_11A];
+		break;
+	default:
+		BUG_ON(1);
+		break;
+	}
+}
+
+static void ath_update_txpow(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	u32 txpow;
+
+	if (sc->curtxpow != sc->config.txpowlimit) {
+		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
+		/* read back in case value is clamped */
+		ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
+		sc->curtxpow = txpow;
+	}
+}
+
+static u8 parse_mpdudensity(u8 mpdudensity)
+{
+	/*
+	 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
+	 *   0 for no restriction
+	 *   1 for 1/4 us
+	 *   2 for 1/2 us
+	 *   3 for 1 us
+	 *   4 for 2 us
+	 *   5 for 4 us
+	 *   6 for 8 us
+	 *   7 for 16 us
+	 */
+	switch (mpdudensity) {
+	case 0:
+		return 0;
+	case 1:
+	case 2:
+	case 3:
+		/* Our lower layer calculations limit our precision to
+		   1 microsecond */
+		return 1;
+	case 4:
+		return 2;
+	case 5:
+		return 4;
+	case 6:
+		return 8;
+	case 7:
+		return 16;
+	default:
+		return 0;
+	}
+}
+
+static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
+{
+	const struct ath_rate_table *rate_table = NULL;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_rate *rate;
+	int i, maxrates;
+
+	switch (band) {
+	case IEEE80211_BAND_2GHZ:
+		rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
+		break;
+	case IEEE80211_BAND_5GHZ:
+		rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
+		break;
+	default:
+		break;
+	}
+
+	if (rate_table == NULL)
+		return;
+
+	sband = &sc->sbands[band];
+	rate = sc->rates[band];
+
+	if (rate_table->rate_cnt > ATH_RATE_MAX)
+		maxrates = ATH_RATE_MAX;
+	else
+		maxrates = rate_table->rate_cnt;
+
+	for (i = 0; i < maxrates; i++) {
+		rate[i].bitrate = rate_table->info[i].ratekbps / 100;
+		rate[i].hw_value = rate_table->info[i].ratecode;
+		if (rate_table->info[i].short_preamble) {
+			rate[i].hw_value_short = rate_table->info[i].ratecode |
+				rate_table->info[i].short_preamble;
+			rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE;
+		}
+		sband->n_bitrates++;
+
+		DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n",
+			rate[i].bitrate / 10, rate[i].hw_value);
+	}
+}
+
+static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc,
+						struct ieee80211_hw *hw)
+{
+	struct ieee80211_channel *curchan = hw->conf.channel;
+	struct ath9k_channel *channel;
+	u8 chan_idx;
+
+	chan_idx = curchan->hw_value;
+	channel = &sc->sc_ah->channels[chan_idx];
+	ath9k_update_ichannel(sc, hw, channel);
+	return channel;
+}
+
+/*
+ * Set/change channels.  If the channel is really being changed, it's done
+ * by reseting the chip.  To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+		    struct ath9k_channel *hchan)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	bool fastcc = true, stopped;
+	struct ieee80211_channel *channel = hw->conf.channel;
+	int r;
+
+	if (sc->sc_flags & SC_OP_INVALID)
+		return -EIO;
+
+	ath9k_ps_wakeup(sc);
+
+	/*
+	 * This is only performed if the channel settings have
+	 * actually changed.
+	 *
+	 * To switch channels clear any pending DMA operations;
+	 * wait long enough for the RX fifo to drain, reset the
+	 * hardware at the new frequency, and then re-enable
+	 * the relevant bits of the h/w.
+	 */
+	ath9k_hw_set_interrupts(ah, 0);
+	ath_drain_all_txq(sc, false);
+	stopped = ath_stoprecv(sc);
+
+	/* XXX: do not flush receive queue here. We don't want
+	 * to flush data frames already in queue because of
+	 * changing channel. */
+
+	if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
+		fastcc = false;
+
+	DPRINTF(sc, ATH_DBG_CONFIG,
+		"(%u MHz) -> (%u MHz), chanwidth: %d\n",
+		sc->sc_ah->curchan->channel,
+		channel->center_freq, sc->tx_chan_width);
+
+	spin_lock_bh(&sc->sc_resetlock);
+
+	r = ath9k_hw_reset(ah, hchan, fastcc);
+	if (r) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to reset channel (%u Mhz) "
+			"reset status %d\n",
+			channel->center_freq, r);
+		spin_unlock_bh(&sc->sc_resetlock);
+		goto ps_restore;
+	}
+	spin_unlock_bh(&sc->sc_resetlock);
+
+	sc->sc_flags &= ~SC_OP_FULL_RESET;
+
+	if (ath_startrecv(sc) != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to restart recv logic\n");
+		r = -EIO;
+		goto ps_restore;
+	}
+
+	ath_cache_conf_rate(sc, &hw->conf);
+	ath_update_txpow(sc);
+	ath9k_hw_set_interrupts(ah, sc->imask);
+
+ ps_restore:
+	ath9k_ps_restore(sc);
+	return r;
+}
+
+/*
+ *  This routine performs the periodic noise floor calibration function
+ *  that is used to adjust and optimize the chip performance.  This
+ *  takes environmental changes (location, temperature) into account.
+ *  When the task is complete, it reschedules itself depending on the
+ *  appropriate interval that was calculated.
+ */
+static void ath_ani_calibrate(unsigned long data)
+{
+	struct ath_softc *sc = (struct ath_softc *)data;
+	struct ath_hw *ah = sc->sc_ah;
+	bool longcal = false;
+	bool shortcal = false;
+	bool aniflag = false;
+	unsigned int timestamp = jiffies_to_msecs(jiffies);
+	u32 cal_interval, short_cal_interval;
+
+	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
+		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
+
+	/*
+	* don't calibrate when we're scanning.
+	* we are most likely not on our home channel.
+	*/
+	if (sc->sc_flags & SC_OP_SCANNING)
+		goto set_timer;
+
+	/* Only calibrate if awake */
+	if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
+		goto set_timer;
+
+	ath9k_ps_wakeup(sc);
+
+	/* Long calibration runs independently of short calibration. */
+	if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
+		longcal = true;
+		DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
+		sc->ani.longcal_timer = timestamp;
+	}
+
+	/* Short calibration applies only while caldone is false */
+	if (!sc->ani.caldone) {
+		if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) {
+			shortcal = true;
+			DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies);
+			sc->ani.shortcal_timer = timestamp;
+			sc->ani.resetcal_timer = timestamp;
+		}
+	} else {
+		if ((timestamp - sc->ani.resetcal_timer) >=
+		    ATH_RESTART_CALINTERVAL) {
+			sc->ani.caldone = ath9k_hw_reset_calvalid(ah);
+			if (sc->ani.caldone)
+				sc->ani.resetcal_timer = timestamp;
+		}
+	}
+
+	/* Verify whether we must check ANI */
+	if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
+		aniflag = true;
+		sc->ani.checkani_timer = timestamp;
+	}
+
+	/* Skip all processing if there's nothing to do. */
+	if (longcal || shortcal || aniflag) {
+		/* Call ANI routine if necessary */
+		if (aniflag)
+			ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan);
+
+		/* Perform calibration if necessary */
+		if (longcal || shortcal) {
+			sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan,
+						     sc->rx_chainmask, longcal);
+
+			if (longcal)
+				sc->ani.noise_floor = ath9k_hw_getchan_noise(ah,
+								     ah->curchan);
+
+			DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n",
+				ah->curchan->channel, ah->curchan->channelFlags,
+				sc->ani.noise_floor);
+		}
+	}
+
+	ath9k_ps_restore(sc);
+
+set_timer:
+	/*
+	* Set timer interval based on previous results.
+	* The interval must be the shortest necessary to satisfy ANI,
+	* short calibration and long calibration.
+	*/
+	cal_interval = ATH_LONG_CALINTERVAL;
+	if (sc->sc_ah->config.enable_ani)
+		cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
+	if (!sc->ani.caldone)
+		cal_interval = min(cal_interval, (u32)short_cal_interval);
+
+	mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
+}
+
+static void ath_start_ani(struct ath_softc *sc)
+{
+	unsigned long timestamp = jiffies_to_msecs(jiffies);
+
+	sc->ani.longcal_timer = timestamp;
+	sc->ani.shortcal_timer = timestamp;
+	sc->ani.checkani_timer = timestamp;
+
+	mod_timer(&sc->ani.timer,
+		  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
+}
+
+/*
+ * Update tx/rx chainmask. For legacy association,
+ * hard code chainmask to 1x1, for 11n association, use
+ * the chainmask configuration, for bt coexistence, use
+ * the chainmask configuration even in legacy mode.
+ */
+void ath_update_chainmask(struct ath_softc *sc, int is_ht)
+{
+	if (is_ht ||
+	    (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
+		sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
+		sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
+	} else {
+		sc->tx_chainmask = 1;
+		sc->rx_chainmask = 1;
+	}
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n",
+		sc->tx_chainmask, sc->rx_chainmask);
+}
+
+static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
+{
+	struct ath_node *an;
+
+	an = (struct ath_node *)sta->drv_priv;
+
+	if (sc->sc_flags & SC_OP_TXAGGR) {
+		ath_tx_node_init(sc, an);
+		an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+				     sta->ht_cap.ampdu_factor);
+		an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+	}
+}
+
+static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
+{
+	struct ath_node *an = (struct ath_node *)sta->drv_priv;
+
+	if (sc->sc_flags & SC_OP_TXAGGR)
+		ath_tx_node_cleanup(sc, an);
+}
+
+static void ath9k_tasklet(unsigned long data)
+{
+	struct ath_softc *sc = (struct ath_softc *)data;
+	u32 status = sc->intrstatus;
+
+	ath9k_ps_wakeup(sc);
+
+	if (status & ATH9K_INT_FATAL) {
+		ath_reset(sc, false);
+		ath9k_ps_restore(sc);
+		return;
+	}
+
+	if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
+		spin_lock_bh(&sc->rx.rxflushlock);
+		ath_rx_tasklet(sc, 0);
+		spin_unlock_bh(&sc->rx.rxflushlock);
+	}
+
+	if (status & ATH9K_INT_TX)
+		ath_tx_tasklet(sc);
+
+	if ((status & ATH9K_INT_TSFOOR) &&
+	    (sc->hw->conf.flags & IEEE80211_CONF_PS)) {
+		/*
+		 * TSF sync does not look correct; remain awake to sync with
+		 * the next Beacon.
+		 */
+		DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n");
+		sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC;
+	}
+
+	/* re-enable hardware interrupt */
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
+	ath9k_ps_restore(sc);
+}
+
+irqreturn_t ath_isr(int irq, void *dev)
+{
+#define SCHED_INTR (				\
+		ATH9K_INT_FATAL |		\
+		ATH9K_INT_RXORN |		\
+		ATH9K_INT_RXEOL |		\
+		ATH9K_INT_RX |			\
+		ATH9K_INT_TX |			\
+		ATH9K_INT_BMISS |		\
+		ATH9K_INT_CST |			\
+		ATH9K_INT_TSFOOR)
+
+	struct ath_softc *sc = dev;
+	struct ath_hw *ah = sc->sc_ah;
+	enum ath9k_int status;
+	bool sched = false;
+
+	/*
+	 * The hardware is not ready/present, don't
+	 * touch anything. Note this can happen early
+	 * on if the IRQ is shared.
+	 */
+	if (sc->sc_flags & SC_OP_INVALID)
+		return IRQ_NONE;
+
+
+	/* shared irq, not for us */
+
+	if (!ath9k_hw_intrpend(ah))
+		return IRQ_NONE;
+
+	/*
+	 * Figure out the reason(s) for the interrupt.  Note
+	 * that the hal returns a pseudo-ISR that may include
+	 * bits we haven't explicitly enabled so we mask the
+	 * value to insure we only process bits we requested.
+	 */
+	ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
+	status &= sc->imask;	/* discard unasked-for bits */
+
+	/*
+	 * If there are no status bits set, then this interrupt was not
+	 * for me (should have been caught above).
+	 */
+	if (!status)
+		return IRQ_NONE;
+
+	/* Cache the status */
+	sc->intrstatus = status;
+
+	if (status & SCHED_INTR)
+		sched = true;
+
+	/*
+	 * If a FATAL or RXORN interrupt is received, we have to reset the
+	 * chip immediately.
+	 */
+	if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN))
+		goto chip_reset;
+
+	if (status & ATH9K_INT_SWBA)
+		tasklet_schedule(&sc->bcon_tasklet);
+
+	if (status & ATH9K_INT_TXURN)
+		ath9k_hw_updatetxtriglevel(ah, true);
+
+	if (status & ATH9K_INT_MIB) {
+		/*
+		 * Disable interrupts until we service the MIB
+		 * interrupt; otherwise it will continue to
+		 * fire.
+		 */
+		ath9k_hw_set_interrupts(ah, 0);
+		/*
+		 * Let the hal handle the event. We assume
+		 * it will clear whatever condition caused
+		 * the interrupt.
+		 */
+		ath9k_hw_procmibevent(ah, &sc->nodestats);
+		ath9k_hw_set_interrupts(ah, sc->imask);
+	}
+
+	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+		if (status & ATH9K_INT_TIM_TIMER) {
+			/* Clear RxAbort bit so that we can
+			 * receive frames */
+			ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
+			ath9k_hw_setrxabort(sc->sc_ah, 0);
+			sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
+		}
+
+chip_reset:
+
+	ath_debug_stat_interrupt(sc, status);
+
+	if (sched) {
+		/* turn off every interrupt except SWBA */
+		ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA));
+		tasklet_schedule(&sc->intr_tq);
+	}
+
+	return IRQ_HANDLED;
+
+#undef SCHED_INTR
+}
+
+static u32 ath_get_extchanmode(struct ath_softc *sc,
+			       struct ieee80211_channel *chan,
+			       enum nl80211_channel_type channel_type)
+{
+	u32 chanmode = 0;
+
+	switch (chan->band) {
+	case IEEE80211_BAND_2GHZ:
+		switch(channel_type) {
+		case NL80211_CHAN_NO_HT:
+		case NL80211_CHAN_HT20:
+			chanmode = CHANNEL_G_HT20;
+			break;
+		case NL80211_CHAN_HT40PLUS:
+			chanmode = CHANNEL_G_HT40PLUS;
+			break;
+		case NL80211_CHAN_HT40MINUS:
+			chanmode = CHANNEL_G_HT40MINUS;
+			break;
+		}
+		break;
+	case IEEE80211_BAND_5GHZ:
+		switch(channel_type) {
+		case NL80211_CHAN_NO_HT:
+		case NL80211_CHAN_HT20:
+			chanmode = CHANNEL_A_HT20;
+			break;
+		case NL80211_CHAN_HT40PLUS:
+			chanmode = CHANNEL_A_HT40PLUS;
+			break;
+		case NL80211_CHAN_HT40MINUS:
+			chanmode = CHANNEL_A_HT40MINUS;
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return chanmode;
+}
+
+static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
+			   struct ath9k_keyval *hk, const u8 *addr,
+			   bool authenticator)
+{
+	const u8 *key_rxmic;
+	const u8 *key_txmic;
+
+	key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
+	key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
+
+	if (addr == NULL) {
+		/*
+		 * Group key installation - only two key cache entries are used
+		 * regardless of splitmic capability since group key is only
+		 * used either for TX or RX.
+		 */
+		if (authenticator) {
+			memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
+			memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
+		} else {
+			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
+		}
+		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
+	}
+	if (!sc->splitmic) {
+		/* TX and RX keys share the same key cache entry. */
+		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
+		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
+	}
+
+	/* Separate key cache entries for TX and RX */
+
+	/* TX key goes at first index, RX key at +32. */
+	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
+	if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) {
+		/* TX MIC entry failed. No need to proceed further */
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Setting TX MIC Key Failed\n");
+		return 0;
+	}
+
+	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+	/* XXX delete tx key on failure? */
+	return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr);
+}
+
+static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
+{
+	int i;
+
+	for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
+		if (test_bit(i, sc->keymap) ||
+		    test_bit(i + 64, sc->keymap))
+			continue; /* At least one part of TKIP key allocated */
+		if (sc->splitmic &&
+		    (test_bit(i + 32, sc->keymap) ||
+		     test_bit(i + 64 + 32, sc->keymap)))
+			continue; /* At least one part of TKIP key allocated */
+
+		/* Found a free slot for a TKIP key */
+		return i;
+	}
+	return -1;
+}
+
+static int ath_reserve_key_cache_slot(struct ath_softc *sc)
+{
+	int i;
+
+	/* First, try to find slots that would not be available for TKIP. */
+	if (sc->splitmic) {
+		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) {
+			if (!test_bit(i, sc->keymap) &&
+			    (test_bit(i + 32, sc->keymap) ||
+			     test_bit(i + 64, sc->keymap) ||
+			     test_bit(i + 64 + 32, sc->keymap)))
+				return i;
+			if (!test_bit(i + 32, sc->keymap) &&
+			    (test_bit(i, sc->keymap) ||
+			     test_bit(i + 64, sc->keymap) ||
+			     test_bit(i + 64 + 32, sc->keymap)))
+				return i + 32;
+			if (!test_bit(i + 64, sc->keymap) &&
+			    (test_bit(i , sc->keymap) ||
+			     test_bit(i + 32, sc->keymap) ||
+			     test_bit(i + 64 + 32, sc->keymap)))
+				return i + 64;
+			if (!test_bit(i + 64 + 32, sc->keymap) &&
+			    (test_bit(i, sc->keymap) ||
+			     test_bit(i + 32, sc->keymap) ||
+			     test_bit(i + 64, sc->keymap)))
+				return i + 64 + 32;
+		}
+	} else {
+		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
+			if (!test_bit(i, sc->keymap) &&
+			    test_bit(i + 64, sc->keymap))
+				return i;
+			if (test_bit(i, sc->keymap) &&
+			    !test_bit(i + 64, sc->keymap))
+				return i + 64;
+		}
+	}
+
+	/* No partially used TKIP slots, pick any available slot */
+	for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) {
+		/* Do not allow slots that could be needed for TKIP group keys
+		 * to be used. This limitation could be removed if we know that
+		 * TKIP will not be used. */
+		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
+			continue;
+		if (sc->splitmic) {
+			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
+				continue;
+			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
+				continue;
+		}
+
+		if (!test_bit(i, sc->keymap))
+			return i; /* Found a free slot for a key */
+	}
+
+	/* No free slot found */
+	return -1;
+}
+
+static int ath_key_config(struct ath_softc *sc,
+			  struct ieee80211_vif *vif,
+			  struct ieee80211_sta *sta,
+			  struct ieee80211_key_conf *key)
+{
+	struct ath9k_keyval hk;
+	const u8 *mac = NULL;
+	int ret = 0;
+	int idx;
+
+	memset(&hk, 0, sizeof(hk));
+
+	switch (key->alg) {
+	case ALG_WEP:
+		hk.kv_type = ATH9K_CIPHER_WEP;
+		break;
+	case ALG_TKIP:
+		hk.kv_type = ATH9K_CIPHER_TKIP;
+		break;
+	case ALG_CCMP:
+		hk.kv_type = ATH9K_CIPHER_AES_CCM;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	hk.kv_len = key->keylen;
+	memcpy(hk.kv_val, key->key, key->keylen);
+
+	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+		/* For now, use the default keys for broadcast keys. This may
+		 * need to change with virtual interfaces. */
+		idx = key->keyidx;
+	} else if (key->keyidx) {
+		if (WARN_ON(!sta))
+			return -EOPNOTSUPP;
+		mac = sta->addr;
+
+		if (vif->type != NL80211_IFTYPE_AP) {
+			/* Only keyidx 0 should be used with unicast key, but
+			 * allow this for client mode for now. */
+			idx = key->keyidx;
+		} else
+			return -EIO;
+	} else {
+		if (WARN_ON(!sta))
+			return -EOPNOTSUPP;
+		mac = sta->addr;
+
+		if (key->alg == ALG_TKIP)
+			idx = ath_reserve_key_cache_slot_tkip(sc);
+		else
+			idx = ath_reserve_key_cache_slot(sc);
+		if (idx < 0)
+			return -ENOSPC; /* no free key cache entries */
+	}
+
+	if (key->alg == ALG_TKIP)
+		ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac,
+				      vif->type == NL80211_IFTYPE_AP);
+	else
+		ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac);
+
+	if (!ret)
+		return -EIO;
+
+	set_bit(idx, sc->keymap);
+	if (key->alg == ALG_TKIP) {
+		set_bit(idx + 64, sc->keymap);
+		if (sc->splitmic) {
+			set_bit(idx + 32, sc->keymap);
+			set_bit(idx + 64 + 32, sc->keymap);
+		}
+	}
+
+	return idx;
+}
+
+static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
+{
+	ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx);
+	if (key->hw_key_idx < IEEE80211_WEP_NKID)
+		return;
+
+	clear_bit(key->hw_key_idx, sc->keymap);
+	if (key->alg != ALG_TKIP)
+		return;
+
+	clear_bit(key->hw_key_idx + 64, sc->keymap);
+	if (sc->splitmic) {
+		clear_bit(key->hw_key_idx + 32, sc->keymap);
+		clear_bit(key->hw_key_idx + 64 + 32, sc->keymap);
+	}
+}
+
+static void setup_ht_cap(struct ath_softc *sc,
+			 struct ieee80211_sta_ht_cap *ht_info)
+{
+#define	ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3	/* 2 ^ 16 */
+#define	ATH9K_HT_CAP_MPDUDENSITY_8 0x6		/* 8 usec */
+
+	ht_info->ht_supported = true;
+	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+		       IEEE80211_HT_CAP_SM_PS |
+		       IEEE80211_HT_CAP_SGI_40 |
+		       IEEE80211_HT_CAP_DSSSCCK40;
+
+	ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
+	ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
+
+	/* set up supported mcs set */
+	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+
+	switch(sc->rx_chainmask) {
+	case 1:
+		ht_info->mcs.rx_mask[0] = 0xff;
+		break;
+	case 3:
+	case 5:
+	case 7:
+	default:
+		ht_info->mcs.rx_mask[0] = 0xff;
+		ht_info->mcs.rx_mask[1] = 0xff;
+		break;
+	}
+
+	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+}
+
+static void ath9k_bss_assoc_info(struct ath_softc *sc,
+				 struct ieee80211_vif *vif,
+				 struct ieee80211_bss_conf *bss_conf)
+{
+	struct ath_vif *avp = (void *)vif->drv_priv;
+
+	if (bss_conf->assoc) {
+		DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
+			bss_conf->aid, sc->curbssid);
+
+		/* New association, store aid */
+		if (avp->av_opmode == NL80211_IFTYPE_STATION) {
+			sc->curaid = bss_conf->aid;
+			ath9k_hw_write_associd(sc);
+
+			/*
+			 * Request a re-configuration of Beacon related timers
+			 * on the receipt of the first Beacon frame (i.e.,
+			 * after time sync with the AP).
+			 */
+			sc->sc_flags |= SC_OP_BEACON_SYNC;
+		}
+
+		/* Configure the beacon */
+		ath_beacon_config(sc, vif);
+
+		/* Reset rssi stats */
+		sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
+		sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
+		sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
+		sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
+
+		ath_start_ani(sc);
+	} else {
+		DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
+		sc->curaid = 0;
+	}
+}
+
+/********************************/
+/*	 LED functions		*/
+/********************************/
+
+static void ath_led_blink_work(struct work_struct *work)
+{
+	struct ath_softc *sc = container_of(work, struct ath_softc,
+					    ath_led_blink_work.work);
+
+	if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
+		return;
+
+	if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
+	    (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
+		ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
+	else
+		ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
+				  (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
+
+	queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work,
+			   (sc->sc_flags & SC_OP_LED_ON) ?
+			   msecs_to_jiffies(sc->led_off_duration) :
+			   msecs_to_jiffies(sc->led_on_duration));
+
+	sc->led_on_duration = sc->led_on_cnt ?
+			max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
+			ATH_LED_ON_DURATION_IDLE;
+	sc->led_off_duration = sc->led_off_cnt ?
+			max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
+			ATH_LED_OFF_DURATION_IDLE;
+	sc->led_on_cnt = sc->led_off_cnt = 0;
+	if (sc->sc_flags & SC_OP_LED_ON)
+		sc->sc_flags &= ~SC_OP_LED_ON;
+	else
+		sc->sc_flags |= SC_OP_LED_ON;
+}
+
+static void ath_led_brightness(struct led_classdev *led_cdev,
+			       enum led_brightness brightness)
+{
+	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
+	struct ath_softc *sc = led->sc;
+
+	switch (brightness) {
+	case LED_OFF:
+		if (led->led_type == ATH_LED_ASSOC ||
+		    led->led_type == ATH_LED_RADIO) {
+			ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
+				(led->led_type == ATH_LED_RADIO));
+			sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
+			if (led->led_type == ATH_LED_RADIO)
+				sc->sc_flags &= ~SC_OP_LED_ON;
+		} else {
+			sc->led_off_cnt++;
+		}
+		break;
+	case LED_FULL:
+		if (led->led_type == ATH_LED_ASSOC) {
+			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
+			queue_delayed_work(sc->hw->workqueue,
+					   &sc->ath_led_blink_work, 0);
+		} else if (led->led_type == ATH_LED_RADIO) {
+			ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
+			sc->sc_flags |= SC_OP_LED_ON;
+		} else {
+			sc->led_on_cnt++;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
+			    char *trigger)
+{
+	int ret;
+
+	led->sc = sc;
+	led->led_cdev.name = led->name;
+	led->led_cdev.default_trigger = trigger;
+	led->led_cdev.brightness_set = ath_led_brightness;
+
+	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
+	if (ret)
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Failed to register led:%s", led->name);
+	else
+		led->registered = 1;
+	return ret;
+}
+
+static void ath_unregister_led(struct ath_led *led)
+{
+	if (led->registered) {
+		led_classdev_unregister(&led->led_cdev);
+		led->registered = 0;
+	}
+}
+
+static void ath_deinit_leds(struct ath_softc *sc)
+{
+	cancel_delayed_work_sync(&sc->ath_led_blink_work);
+	ath_unregister_led(&sc->assoc_led);
+	sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
+	ath_unregister_led(&sc->tx_led);
+	ath_unregister_led(&sc->rx_led);
+	ath_unregister_led(&sc->radio_led);
+	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+}
+
+static void ath_init_leds(struct ath_softc *sc)
+{
+	char *trigger;
+	int ret;
+
+	/* Configure gpio 1 for output */
+	ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
+			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+	/* LED off, active low */
+	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+	INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
+
+	trigger = ieee80211_get_radio_led_name(sc->hw);
+	snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
+		"ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
+	ret = ath_register_led(sc, &sc->radio_led, trigger);
+	sc->radio_led.led_type = ATH_LED_RADIO;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_assoc_led_name(sc->hw);
+	snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
+		"ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
+	ret = ath_register_led(sc, &sc->assoc_led, trigger);
+	sc->assoc_led.led_type = ATH_LED_ASSOC;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_tx_led_name(sc->hw);
+	snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
+		"ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
+	ret = ath_register_led(sc, &sc->tx_led, trigger);
+	sc->tx_led.led_type = ATH_LED_TX;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_rx_led_name(sc->hw);
+	snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
+		"ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
+	ret = ath_register_led(sc, &sc->rx_led, trigger);
+	sc->rx_led.led_type = ATH_LED_RX;
+	if (ret)
+		goto fail;
+
+	return;
+
+fail:
+	ath_deinit_leds(sc);
+}
+
+void ath_radio_enable(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ieee80211_channel *channel = sc->hw->conf.channel;
+	int r;
+
+	ath9k_ps_wakeup(sc);
+	ath9k_hw_configpcipowersave(ah, 0);
+
+	if (!ah->curchan)
+		ah->curchan = ath_get_curchannel(sc, sc->hw);
+
+	spin_lock_bh(&sc->sc_resetlock);
+	r = ath9k_hw_reset(ah, ah->curchan, false);
+	if (r) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to reset channel %u (%uMhz) ",
+			"reset status %d\n",
+			channel->center_freq, r);
+	}
+	spin_unlock_bh(&sc->sc_resetlock);
+
+	ath_update_txpow(sc);
+	if (ath_startrecv(sc) != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to restart recv logic\n");
+		return;
+	}
+
+	if (sc->sc_flags & SC_OP_BEACONS)
+		ath_beacon_config(sc, NULL);	/* restart beacons */
+
+	/* Re-Enable  interrupts */
+	ath9k_hw_set_interrupts(ah, sc->imask);
+
+	/* Enable LED */
+	ath9k_hw_cfg_output(ah, ATH_LED_PIN,
+			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+	ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
+
+	ieee80211_wake_queues(sc->hw);
+	ath9k_ps_restore(sc);
+}
+
+void ath_radio_disable(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ieee80211_channel *channel = sc->hw->conf.channel;
+	int r;
+
+	ath9k_ps_wakeup(sc);
+	ieee80211_stop_queues(sc->hw);
+
+	/* Disable LED */
+	ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1);
+	ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN);
+
+	/* Disable interrupts */
+	ath9k_hw_set_interrupts(ah, 0);
+
+	ath_drain_all_txq(sc, false);	/* clear pending tx frames */
+	ath_stoprecv(sc);		/* turn off frame recv */
+	ath_flushrecv(sc);		/* flush recv queue */
+
+	if (!ah->curchan)
+		ah->curchan = ath_get_curchannel(sc, sc->hw);
+
+	spin_lock_bh(&sc->sc_resetlock);
+	r = ath9k_hw_reset(ah, ah->curchan, false);
+	if (r) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to reset channel %u (%uMhz) "
+			"reset status %d\n",
+			channel->center_freq, r);
+	}
+	spin_unlock_bh(&sc->sc_resetlock);
+
+	ath9k_hw_phy_disable(ah);
+	ath9k_hw_configpcipowersave(ah, 1);
+	ath9k_ps_restore(sc);
+	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+}
+
+/*******************/
+/*	Rfkill	   */
+/*******************/
+
+static bool ath_is_rfkill_set(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+
+	return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
+				  ah->rfkill_polarity;
+}
+
+static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	bool blocked = !!ath_is_rfkill_set(sc);
+
+	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
+
+	if (blocked)
+		ath_radio_disable(sc);
+	else
+		ath_radio_enable(sc);
+}
+
+static void ath_start_rfkill_poll(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+		wiphy_rfkill_start_polling(sc->hw->wiphy);
+}
+
+void ath_cleanup(struct ath_softc *sc)
+{
+	ath_detach(sc);
+	free_irq(sc->irq, sc);
+	ath_bus_cleanup(sc);
+	kfree(sc->sec_wiphy);
+	ieee80211_free_hw(sc->hw);
+}
+
+void ath_detach(struct ath_softc *sc)
+{
+	struct ieee80211_hw *hw = sc->hw;
+	int i = 0;
+
+	ath9k_ps_wakeup(sc);
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
+
+	ath_deinit_leds(sc);
+	cancel_work_sync(&sc->chan_work);
+	cancel_delayed_work_sync(&sc->wiphy_work);
+
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		struct ath_wiphy *aphy = sc->sec_wiphy[i];
+		if (aphy == NULL)
+			continue;
+		sc->sec_wiphy[i] = NULL;
+		ieee80211_unregister_hw(aphy->hw);
+		ieee80211_free_hw(aphy->hw);
+	}
+	ieee80211_unregister_hw(hw);
+	ath_rx_cleanup(sc);
+	ath_tx_cleanup(sc);
+
+	tasklet_kill(&sc->intr_tq);
+	tasklet_kill(&sc->bcon_tasklet);
+
+	if (!(sc->sc_flags & SC_OP_INVALID))
+		ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+
+	/* cleanup tx queues */
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+		if (ATH_TXQ_SETUP(sc, i))
+			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+	ath9k_hw_detach(sc->sc_ah);
+	ath9k_exit_debug(sc);
+	ath9k_ps_restore(sc);
+}
+
+static int ath9k_reg_notifier(struct wiphy *wiphy,
+			      struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_regulatory *reg = &sc->sc_ah->regulatory;
+
+	return ath_reg_notifier_apply(wiphy, request, reg);
+}
+
+static int ath_init(u16 devid, struct ath_softc *sc)
+{
+	struct ath_hw *ah = NULL;
+	int status;
+	int error = 0, i;
+	int csz = 0;
+
+	/* XXX: hardware will not be ready until ath_open() being called */
+	sc->sc_flags |= SC_OP_INVALID;
+
+	if (ath9k_init_debug(sc) < 0)
+		printk(KERN_ERR "Unable to create debugfs files\n");
+
+	spin_lock_init(&sc->wiphy_lock);
+	spin_lock_init(&sc->sc_resetlock);
+	spin_lock_init(&sc->sc_serial_rw);
+	mutex_init(&sc->mutex);
+	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
+	tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
+		     (unsigned long)sc);
+
+	/*
+	 * Cache line size is used to size and align various
+	 * structures used to communicate with the hardware.
+	 */
+	ath_read_cachesize(sc, &csz);
+	/* XXX assert csz is non-zero */
+	sc->cachelsz = csz << 2;	/* convert to bytes */
+
+	ah = ath9k_hw_attach(devid, sc, &status);
+	if (ah == NULL) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to attach hardware; HAL status %d\n", status);
+		error = -ENXIO;
+		goto bad;
+	}
+	sc->sc_ah = ah;
+
+	/* Get the hardware key cache size. */
+	sc->keymax = ah->caps.keycache_size;
+	if (sc->keymax > ATH_KEYMAX) {
+		DPRINTF(sc, ATH_DBG_ANY,
+			"Warning, using only %u entries in %u key cache\n",
+			ATH_KEYMAX, sc->keymax);
+		sc->keymax = ATH_KEYMAX;
+	}
+
+	/*
+	 * Reset the key cache since some parts do not
+	 * reset the contents on initial power up.
+	 */
+	for (i = 0; i < sc->keymax; i++)
+		ath9k_hw_keyreset(ah, (u16) i);
+
+	if (error)
+		goto bad;
+
+	/* default to MONITOR mode */
+	sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
+
+	/* Setup rate tables */
+
+	ath_rate_attach(sc);
+	ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
+	ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
+
+	/*
+	 * Allocate hardware transmit queues: one queue for
+	 * beacon frames and one data queue for each QoS
+	 * priority.  Note that the hal handles reseting
+	 * these queues at the needed time.
+	 */
+	sc->beacon.beaconq = ath_beaconq_setup(ah);
+	if (sc->beacon.beaconq == -1) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to setup a beacon xmit queue\n");
+		error = -EIO;
+		goto bad2;
+	}
+	sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
+	if (sc->beacon.cabq == NULL) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to setup CAB xmit queue\n");
+		error = -EIO;
+		goto bad2;
+	}
+
+	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
+	ath_cabq_update(sc);
+
+	for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
+		sc->tx.hwq_map[i] = -1;
+
+	/* Setup data queues */
+	/* NB: ensure BK queue is the lowest priority h/w queue */
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to setup xmit queue for BK traffic\n");
+		error = -EIO;
+		goto bad2;
+	}
+
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to setup xmit queue for BE traffic\n");
+		error = -EIO;
+		goto bad2;
+	}
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to setup xmit queue for VI traffic\n");
+		error = -EIO;
+		goto bad2;
+	}
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to setup xmit queue for VO traffic\n");
+		error = -EIO;
+		goto bad2;
+	}
+
+	/* Initializes the noise floor to a reasonable default value.
+	 * Later on this will be updated during ANI processing. */
+
+	sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
+	setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc);
+
+	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+				   ATH9K_CIPHER_TKIP, NULL)) {
+		/*
+		 * Whether we should enable h/w TKIP MIC.
+		 * XXX: if we don't support WME TKIP MIC, then we wouldn't
+		 * report WMM capable, so it's always safe to turn on
+		 * TKIP MIC in this case.
+		 */
+		ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
+				       0, 1, NULL);
+	}
+
+	/*
+	 * Check whether the separate key cache entries
+	 * are required to handle both tx+rx MIC keys.
+	 * With split mic keys the number of stations is limited
+	 * to 27 otherwise 59.
+	 */
+	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+				   ATH9K_CIPHER_TKIP, NULL)
+	    && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+				      ATH9K_CIPHER_MIC, NULL)
+	    && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
+				      0, NULL))
+		sc->splitmic = 1;
+
+	/* turn on mcast key search if possible */
+	if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
+		(void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
+					     1, NULL);
+
+	sc->config.txpowlimit = ATH_TXPOWER_MAX;
+
+	/* 11n Capabilities */
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+		sc->sc_flags |= SC_OP_TXAGGR;
+		sc->sc_flags |= SC_OP_RXAGGR;
+	}
+
+	sc->tx_chainmask = ah->caps.tx_chainmask;
+	sc->rx_chainmask = ah->caps.rx_chainmask;
+
+	ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
+	sc->rx.defant = ath9k_hw_getdefantenna(ah);
+
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
+		memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
+
+	sc->beacon.slottime = ATH9K_SLOT_TIME_9;	/* default to short slot time */
+
+	/* initialize beacon slots */
+	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
+		sc->beacon.bslot[i] = NULL;
+		sc->beacon.bslot_aphy[i] = NULL;
+	}
+
+	/* setup channels and rates */
+
+	sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
+	sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
+		sc->rates[IEEE80211_BAND_2GHZ];
+	sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+	sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
+		ARRAY_SIZE(ath9k_2ghz_chantable);
+
+	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
+		sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
+		sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
+			sc->rates[IEEE80211_BAND_5GHZ];
+		sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+		sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
+			ARRAY_SIZE(ath9k_5ghz_chantable);
+	}
+
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)
+		ath9k_hw_btcoex_enable(sc->sc_ah);
+
+	return 0;
+bad2:
+	/* cleanup tx queues */
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+		if (ATH_TXQ_SETUP(sc, i))
+			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+bad:
+	if (ah)
+		ath9k_hw_detach(ah);
+	ath9k_exit_debug(sc);
+
+	return error;
+}
+
+void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+{
+	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+		IEEE80211_HW_SIGNAL_DBM |
+		IEEE80211_HW_AMPDU_AGGREGATION |
+		IEEE80211_HW_SUPPORTS_PS |
+		IEEE80211_HW_PS_NULLFUNC_STACK |
+		IEEE80211_HW_SPECTRUM_MGMT;
+
+	if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
+		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
+
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_ADHOC) |
+		BIT(NL80211_IFTYPE_MESH_POINT);
+
+	hw->queues = 4;
+	hw->max_rates = 4;
+	hw->channel_change_time = 5000;
+	hw->max_listen_interval = 10;
+	hw->max_rate_tries = ATH_11N_TXMAXTRY;
+	hw->sta_data_size = sizeof(struct ath_node);
+	hw->vif_data_size = sizeof(struct ath_vif);
+
+	hw->rate_control_algorithm = "ath9k_rate_control";
+
+	hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+		&sc->sbands[IEEE80211_BAND_2GHZ];
+	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
+		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			&sc->sbands[IEEE80211_BAND_5GHZ];
+}
+
+int ath_attach(u16 devid, struct ath_softc *sc)
+{
+	struct ieee80211_hw *hw = sc->hw;
+	int error = 0, i;
+	struct ath_regulatory *reg;
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
+
+	error = ath_init(devid, sc);
+	if (error != 0)
+		return error;
+
+	/* get mac address from hardware and set in mac80211 */
+
+	SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
+
+	ath_set_hw_capab(sc, hw);
+
+	error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
+			      ath9k_reg_notifier);
+	if (error)
+		return error;
+
+	reg = &sc->sc_ah->regulatory;
+
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+		setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+		if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
+			setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+	}
+
+	/* initialize tx/rx engine */
+	error = ath_tx_init(sc, ATH_TXBUF);
+	if (error != 0)
+		goto error_attach;
+
+	error = ath_rx_init(sc, ATH_RXBUF);
+	if (error != 0)
+		goto error_attach;
+
+	INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
+	INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
+	sc->wiphy_scheduler_int = msecs_to_jiffies(500);
+
+	error = ieee80211_register_hw(hw);
+
+	if (!ath_is_world_regd(reg)) {
+		error = regulatory_hint(hw->wiphy, reg->alpha2);
+		if (error)
+			goto error_attach;
+	}
+
+	/* Initialize LED control */
+	ath_init_leds(sc);
+
+	ath_start_rfkill_poll(sc);
+
+	return 0;
+
+error_attach:
+	/* cleanup tx queues */
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+		if (ATH_TXQ_SETUP(sc, i))
+			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+	ath9k_hw_detach(sc->sc_ah);
+	ath9k_exit_debug(sc);
+
+	return error;
+}
+
+int ath_reset(struct ath_softc *sc, bool retry_tx)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ieee80211_hw *hw = sc->hw;
+	int r;
+
+	ath9k_hw_set_interrupts(ah, 0);
+	ath_drain_all_txq(sc, retry_tx);
+	ath_stoprecv(sc);
+	ath_flushrecv(sc);
+
+	spin_lock_bh(&sc->sc_resetlock);
+	r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
+	if (r)
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to reset hardware; reset status %d\n", r);
+	spin_unlock_bh(&sc->sc_resetlock);
+
+	if (ath_startrecv(sc) != 0)
+		DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
+
+	/*
+	 * We may be doing a reset in response to a request
+	 * that changes the channel so update any state that
+	 * might change as a result.
+	 */
+	ath_cache_conf_rate(sc, &hw->conf);
+
+	ath_update_txpow(sc);
+
+	if (sc->sc_flags & SC_OP_BEACONS)
+		ath_beacon_config(sc, NULL);	/* restart beacons */
+
+	ath9k_hw_set_interrupts(ah, sc->imask);
+
+	if (retry_tx) {
+		int i;
+		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+			if (ATH_TXQ_SETUP(sc, i)) {
+				spin_lock_bh(&sc->tx.txq[i].axq_lock);
+				ath_txq_schedule(sc, &sc->tx.txq[i]);
+				spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+			}
+		}
+	}
+
+	return r;
+}
+
+/*
+ *  This function will allocate both the DMA descriptor structure, and the
+ *  buffers it contains.  These are used to contain the descriptors used
+ *  by the system.
+*/
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+		      struct list_head *head, const char *name,
+		      int nbuf, int ndesc)
+{
+#define	DS2PHYS(_dd, _ds)						\
+	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
+	struct ath_desc *ds;
+	struct ath_buf *bf;
+	int i, bsize, error;
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
+		name, nbuf, ndesc);
+
+	INIT_LIST_HEAD(head);
+	/* ath_desc must be a multiple of DWORDs */
+	if ((sizeof(struct ath_desc) % 4) != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n");
+		ASSERT((sizeof(struct ath_desc) % 4) == 0);
+		error = -ENOMEM;
+		goto fail;
+	}
+
+	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
+
+	/*
+	 * Need additional DMA memory because we can't use
+	 * descriptors that cross the 4K page boundary. Assume
+	 * one skipped descriptor per 4K page.
+	 */
+	if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+		u32 ndesc_skipped =
+			ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
+		u32 dma_len;
+
+		while (ndesc_skipped) {
+			dma_len = ndesc_skipped * sizeof(struct ath_desc);
+			dd->dd_desc_len += dma_len;
+
+			ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
+		};
+	}
+
+	/* allocate descriptors */
+	dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
+					 &dd->dd_desc_paddr, GFP_KERNEL);
+	if (dd->dd_desc == NULL) {
+		error = -ENOMEM;
+		goto fail;
+	}
+	ds = dd->dd_desc;
+	DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
+		name, ds, (u32) dd->dd_desc_len,
+		ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
+
+	/* allocate buffers */
+	bsize = sizeof(struct ath_buf) * nbuf;
+	bf = kzalloc(bsize, GFP_KERNEL);
+	if (bf == NULL) {
+		error = -ENOMEM;
+		goto fail2;
+	}
+	dd->dd_bufptr = bf;
+
+	for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
+		bf->bf_desc = ds;
+		bf->bf_daddr = DS2PHYS(dd, ds);
+
+		if (!(sc->sc_ah->caps.hw_caps &
+		      ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+			/*
+			 * Skip descriptor addresses which can cause 4KB
+			 * boundary crossing (addr + length) with a 32 dword
+			 * descriptor fetch.
+			 */
+			while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
+				ASSERT((caddr_t) bf->bf_desc <
+				       ((caddr_t) dd->dd_desc +
+					dd->dd_desc_len));
+
+				ds += ndesc;
+				bf->bf_desc = ds;
+				bf->bf_daddr = DS2PHYS(dd, ds);
+			}
+		}
+		list_add_tail(&bf->list, head);
+	}
+	return 0;
+fail2:
+	dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+			  dd->dd_desc_paddr);
+fail:
+	memset(dd, 0, sizeof(*dd));
+	return error;
+#undef ATH_DESC_4KB_BOUND_CHECK
+#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
+#undef DS2PHYS
+}
+
+void ath_descdma_cleanup(struct ath_softc *sc,
+			 struct ath_descdma *dd,
+			 struct list_head *head)
+{
+	dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
+			  dd->dd_desc_paddr);
+
+	INIT_LIST_HEAD(head);
+	kfree(dd->dd_bufptr);
+	memset(dd, 0, sizeof(*dd));
+}
+
+int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
+{
+	int qnum;
+
+	switch (queue) {
+	case 0:
+		qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO];
+		break;
+	case 1:
+		qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI];
+		break;
+	case 2:
+		qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
+		break;
+	case 3:
+		qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK];
+		break;
+	default:
+		qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
+		break;
+	}
+
+	return qnum;
+}
+
+int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
+{
+	int qnum;
+
+	switch (queue) {
+	case ATH9K_WME_AC_VO:
+		qnum = 0;
+		break;
+	case ATH9K_WME_AC_VI:
+		qnum = 1;
+		break;
+	case ATH9K_WME_AC_BE:
+		qnum = 2;
+		break;
+	case ATH9K_WME_AC_BK:
+		qnum = 3;
+		break;
+	default:
+		qnum = -1;
+		break;
+	}
+
+	return qnum;
+}
+
+/* XXX: Remove me once we don't depend on ath9k_channel for all
+ * this redundant data */
+void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
+			   struct ath9k_channel *ichan)
+{
+	struct ieee80211_channel *chan = hw->conf.channel;
+	struct ieee80211_conf *conf = &hw->conf;
+
+	ichan->channel = chan->center_freq;
+	ichan->chan = chan;
+
+	if (chan->band == IEEE80211_BAND_2GHZ) {
+		ichan->chanmode = CHANNEL_G;
+		ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
+	} else {
+		ichan->chanmode = CHANNEL_A;
+		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
+	}
+
+	sc->tx_chan_width = ATH9K_HT_MACMODE_20;
+
+	if (conf_is_ht(conf)) {
+		if (conf_is_ht40(conf))
+			sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
+
+		ichan->chanmode = ath_get_extchanmode(sc, chan,
+					    conf->channel_type);
+	}
+}
+
+/**********************/
+/* mac80211 callbacks */
+/**********************/
+
+static int ath9k_start(struct ieee80211_hw *hw)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ieee80211_channel *curchan = hw->conf.channel;
+	struct ath9k_channel *init_channel;
+	int r;
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with "
+		"initial channel: %d MHz\n", curchan->center_freq);
+
+	mutex_lock(&sc->mutex);
+
+	if (ath9k_wiphy_started(sc)) {
+		if (sc->chan_idx == curchan->hw_value) {
+			/*
+			 * Already on the operational channel, the new wiphy
+			 * can be marked active.
+			 */
+			aphy->state = ATH_WIPHY_ACTIVE;
+			ieee80211_wake_queues(hw);
+		} else {
+			/*
+			 * Another wiphy is on another channel, start the new
+			 * wiphy in paused state.
+			 */
+			aphy->state = ATH_WIPHY_PAUSED;
+			ieee80211_stop_queues(hw);
+		}
+		mutex_unlock(&sc->mutex);
+		return 0;
+	}
+	aphy->state = ATH_WIPHY_ACTIVE;
+
+	/* setup initial channel */
+
+	sc->chan_idx = curchan->hw_value;
+
+	init_channel = ath_get_curchannel(sc, hw);
+
+	/* Reset SERDES registers */
+	ath9k_hw_configpcipowersave(sc->sc_ah, 0);
+
+	/*
+	 * The basic interface to setting the hardware in a good
+	 * state is ``reset''.  On return the hardware is known to
+	 * be powered up and with interrupts disabled.  This must
+	 * be followed by initialization of the appropriate bits
+	 * and then setup of the interrupt mask.
+	 */
+	spin_lock_bh(&sc->sc_resetlock);
+	r = ath9k_hw_reset(sc->sc_ah, init_channel, false);
+	if (r) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to reset hardware; reset status %d "
+			"(freq %u MHz)\n", r,
+			curchan->center_freq);
+		spin_unlock_bh(&sc->sc_resetlock);
+		goto mutex_unlock;
+	}
+	spin_unlock_bh(&sc->sc_resetlock);
+
+	/*
+	 * This is needed only to setup initial state
+	 * but it's best done after a reset.
+	 */
+	ath_update_txpow(sc);
+
+	/*
+	 * Setup the hardware after reset:
+	 * The receive engine is set going.
+	 * Frame transmit is handled entirely
+	 * in the frame output path; there's nothing to do
+	 * here except setup the interrupt mask.
+	 */
+	if (ath_startrecv(sc) != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
+		r = -EIO;
+		goto mutex_unlock;
+	}
+
+	/* Setup our intr mask. */
+	sc->imask = ATH9K_INT_RX | ATH9K_INT_TX
+		| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
+		| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
+
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
+		sc->imask |= ATH9K_INT_GTT;
+
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+		sc->imask |= ATH9K_INT_CST;
+
+	ath_cache_conf_rate(sc, &hw->conf);
+
+	sc->sc_flags &= ~SC_OP_INVALID;
+
+	/* Disable BMISS interrupt when we're not associated */
+	sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
+
+	ieee80211_wake_queues(hw);
+
+mutex_unlock:
+	mutex_unlock(&sc->mutex);
+
+	return r;
+}
+
+static int ath9k_tx(struct ieee80211_hw *hw,
+		    struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_tx_control txctl;
+	int hdrlen, padsize;
+
+	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
+		printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state "
+		       "%d\n", wiphy_name(hw->wiphy), aphy->state);
+		goto exit;
+	}
+
+	if (sc->hw->conf.flags & IEEE80211_CONF_PS) {
+		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+		/*
+		 * mac80211 does not set PM field for normal data frames, so we
+		 * need to update that based on the current PS mode.
+		 */
+		if (ieee80211_is_data(hdr->frame_control) &&
+		    !ieee80211_is_nullfunc(hdr->frame_control) &&
+		    !ieee80211_has_pm(hdr->frame_control)) {
+			DPRINTF(sc, ATH_DBG_PS, "Add PM=1 for a TX frame "
+				"while in PS mode\n");
+			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+		}
+	}
+
+	if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
+		/*
+		 * We are using PS-Poll and mac80211 can request TX while in
+		 * power save mode. Need to wake up hardware for the TX to be
+		 * completed and if needed, also for RX of buffered frames.
+		 */
+		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+		ath9k_ps_wakeup(sc);
+		ath9k_hw_setrxabort(sc->sc_ah, 0);
+		if (ieee80211_is_pspoll(hdr->frame_control)) {
+			DPRINTF(sc, ATH_DBG_PS, "Sending PS-Poll to pick a "
+				"buffered frame\n");
+			sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA;
+		} else {
+			DPRINTF(sc, ATH_DBG_PS, "Wake up to complete TX\n");
+			sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK;
+		}
+		/*
+		 * The actual restore operation will happen only after
+		 * the sc_flags bit is cleared. We are just dropping
+		 * the ps_usecount here.
+		 */
+		ath9k_ps_restore(sc);
+	}
+
+	memset(&txctl, 0, sizeof(struct ath_tx_control));
+
+	/*
+	 * As a temporary workaround, assign seq# here; this will likely need
+	 * to be cleaned up to work better with Beacon transmission and virtual
+	 * BSSes.
+	 */
+	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+			sc->tx.seq_no += 0x10;
+		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+	}
+
+	/* Add the padding after the header if this is not already done */
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	if (hdrlen & 3) {
+		padsize = hdrlen % 4;
+		if (skb_headroom(skb) < padsize)
+			return -1;
+		skb_push(skb, padsize);
+		memmove(skb->data, skb->data + padsize, hdrlen);
+	}
+
+	/* Check if a tx queue is available */
+
+	txctl.txq = ath_test_get_txq(sc, skb);
+	if (!txctl.txq)
+		goto exit;
+
+	DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
+
+	if (ath_tx_start(hw, skb, &txctl) != 0) {
+		DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n");
+		goto exit;
+	}
+
+	return 0;
+exit:
+	dev_kfree_skb_any(skb);
+	return 0;
+}
+
+static void ath9k_stop(struct ieee80211_hw *hw)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	aphy->state = ATH_WIPHY_INACTIVE;
+
+	if (sc->sc_flags & SC_OP_INVALID) {
+		DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
+		return;
+	}
+
+	mutex_lock(&sc->mutex);
+
+	ieee80211_stop_queues(hw);
+
+	if (ath9k_wiphy_started(sc)) {
+		mutex_unlock(&sc->mutex);
+		return; /* another wiphy still in use */
+	}
+
+	/* make sure h/w will not generate any interrupt
+	 * before setting the invalid flag. */
+	ath9k_hw_set_interrupts(sc->sc_ah, 0);
+
+	if (!(sc->sc_flags & SC_OP_INVALID)) {
+		ath_drain_all_txq(sc, false);
+		ath_stoprecv(sc);
+		ath9k_hw_phy_disable(sc->sc_ah);
+	} else
+		sc->rx.rxlink = NULL;
+
+	wiphy_rfkill_stop_polling(sc->hw->wiphy);
+
+	/* disable HAL and put h/w to sleep */
+	ath9k_hw_disable(sc->sc_ah);
+	ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+
+	sc->sc_flags |= SC_OP_INVALID;
+
+	mutex_unlock(&sc->mutex);
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n");
+}
+
+static int ath9k_add_interface(struct ieee80211_hw *hw,
+			       struct ieee80211_if_init_conf *conf)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_vif *avp = (void *)conf->vif->drv_priv;
+	enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
+	int ret = 0;
+
+	mutex_lock(&sc->mutex);
+
+	if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) &&
+	    sc->nvifs > 0) {
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	switch (conf->type) {
+	case NL80211_IFTYPE_STATION:
+		ic_opmode = NL80211_IFTYPE_STATION;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_MESH_POINT:
+		if (sc->nbcnvifs >= ATH_BCBUF) {
+			ret = -ENOBUFS;
+			goto out;
+		}
+		ic_opmode = conf->type;
+		break;
+	default:
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Interface type %d not yet supported\n", conf->type);
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode);
+
+	/* Set the VIF opmode */
+	avp->av_opmode = ic_opmode;
+	avp->av_bslot = -1;
+
+	sc->nvifs++;
+
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
+		ath9k_set_bssid_mask(hw);
+
+	if (sc->nvifs > 1)
+		goto out; /* skip global settings for secondary vif */
+
+	if (ic_opmode == NL80211_IFTYPE_AP) {
+		ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
+		sc->sc_flags |= SC_OP_TSF_RESET;
+	}
+
+	/* Set the device opmode */
+	sc->sc_ah->opmode = ic_opmode;
+
+	/*
+	 * Enable MIB interrupts when there are hardware phy counters.
+	 * Note we only do this (at the moment) for station mode.
+	 */
+	if ((conf->type == NL80211_IFTYPE_STATION) ||
+	    (conf->type == NL80211_IFTYPE_ADHOC) ||
+	    (conf->type == NL80211_IFTYPE_MESH_POINT)) {
+		if (ath9k_hw_phycounters(sc->sc_ah))
+			sc->imask |= ATH9K_INT_MIB;
+		sc->imask |= ATH9K_INT_TSFOOR;
+	}
+
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
+
+	if (conf->type == NL80211_IFTYPE_AP)
+		ath_start_ani(sc);
+
+out:
+	mutex_unlock(&sc->mutex);
+	return ret;
+}
+
+static void ath9k_remove_interface(struct ieee80211_hw *hw,
+				   struct ieee80211_if_init_conf *conf)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_vif *avp = (void *)conf->vif->drv_priv;
+	int i;
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n");
+
+	mutex_lock(&sc->mutex);
+
+	/* Stop ANI */
+	del_timer_sync(&sc->ani.timer);
+
+	/* Reclaim beacon resources */
+	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
+	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
+	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
+		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+		ath_beacon_return(sc, avp);
+	}
+
+	sc->sc_flags &= ~SC_OP_BEACONS;
+
+	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
+		if (sc->beacon.bslot[i] == conf->vif) {
+			printk(KERN_DEBUG "%s: vif had allocated beacon "
+			       "slot\n", __func__);
+			sc->beacon.bslot[i] = NULL;
+			sc->beacon.bslot_aphy[i] = NULL;
+		}
+	}
+
+	sc->nvifs--;
+
+	mutex_unlock(&sc->mutex);
+}
+
+static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ath_hw *ah = sc->sc_ah;
+
+	mutex_lock(&sc->mutex);
+
+	if (changed & IEEE80211_CONF_CHANGE_PS) {
+		if (conf->flags & IEEE80211_CONF_PS) {
+			if (!(ah->caps.hw_caps &
+			      ATH9K_HW_CAP_AUTOSLEEP)) {
+				if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
+					sc->imask |= ATH9K_INT_TIM_TIMER;
+					ath9k_hw_set_interrupts(sc->sc_ah,
+							sc->imask);
+				}
+				ath9k_hw_setrxabort(sc->sc_ah, 1);
+			}
+			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
+		} else {
+			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+			if (!(ah->caps.hw_caps &
+			      ATH9K_HW_CAP_AUTOSLEEP)) {
+				ath9k_hw_setrxabort(sc->sc_ah, 0);
+				sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON |
+						  SC_OP_WAIT_FOR_CAB |
+						  SC_OP_WAIT_FOR_PSPOLL_DATA |
+						  SC_OP_WAIT_FOR_TX_ACK);
+				if (sc->imask & ATH9K_INT_TIM_TIMER) {
+					sc->imask &= ~ATH9K_INT_TIM_TIMER;
+					ath9k_hw_set_interrupts(sc->sc_ah,
+							sc->imask);
+				}
+			}
+		}
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		struct ieee80211_channel *curchan = hw->conf.channel;
+		int pos = curchan->hw_value;
+
+		aphy->chan_idx = pos;
+		aphy->chan_is_ht = conf_is_ht(conf);
+
+		if (aphy->state == ATH_WIPHY_SCAN ||
+		    aphy->state == ATH_WIPHY_ACTIVE)
+			ath9k_wiphy_pause_all_forced(sc, aphy);
+		else {
+			/*
+			 * Do not change operational channel based on a paused
+			 * wiphy changes.
+			 */
+			goto skip_chan_change;
+		}
+
+		DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
+			curchan->center_freq);
+
+		/* XXX: remove me eventualy */
+		ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
+
+		ath_update_chainmask(sc, conf_is_ht(conf));
+
+		if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
+			DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n");
+			mutex_unlock(&sc->mutex);
+			return -EINVAL;
+		}
+	}
+
+skip_chan_change:
+	if (changed & IEEE80211_CONF_CHANGE_POWER)
+		sc->config.txpowlimit = 2 * conf->power_level;
+
+	mutex_unlock(&sc->mutex);
+
+	return 0;
+}
+
+#define SUPPORTED_FILTERS			\
+	(FIF_PROMISC_IN_BSS |			\
+	FIF_ALLMULTI |				\
+	FIF_CONTROL |				\
+	FIF_OTHER_BSS |				\
+	FIF_BCN_PRBRESP_PROMISC |		\
+	FIF_FCSFAIL)
+
+/* FIXME: sc->sc_full_reset ? */
+static void ath9k_configure_filter(struct ieee80211_hw *hw,
+				   unsigned int changed_flags,
+				   unsigned int *total_flags,
+				   int mc_count,
+				   struct dev_mc_list *mclist)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	u32 rfilt;
+
+	changed_flags &= SUPPORTED_FILTERS;
+	*total_flags &= SUPPORTED_FILTERS;
+
+	sc->rx.rxfilter = *total_flags;
+	ath9k_ps_wakeup(sc);
+	rfilt = ath_calcrxfilter(sc);
+	ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
+	ath9k_ps_restore(sc);
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter);
+}
+
+static void ath9k_sta_notify(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     enum sta_notify_cmd cmd,
+			     struct ieee80211_sta *sta)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	switch (cmd) {
+	case STA_NOTIFY_ADD:
+		ath_node_attach(sc, sta);
+		break;
+	case STA_NOTIFY_REMOVE:
+		ath_node_detach(sc, sta);
+		break;
+	default:
+		break;
+	}
+}
+
+static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			 const struct ieee80211_tx_queue_params *params)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath9k_tx_queue_info qi;
+	int ret = 0, qnum;
+
+	if (queue >= WME_NUM_AC)
+		return 0;
+
+	mutex_lock(&sc->mutex);
+
+	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
+
+	qi.tqi_aifs = params->aifs;
+	qi.tqi_cwmin = params->cw_min;
+	qi.tqi_cwmax = params->cw_max;
+	qi.tqi_burstTime = params->txop;
+	qnum = ath_get_hal_qnum(queue, sc);
+
+	DPRINTF(sc, ATH_DBG_CONFIG,
+		"Configure tx [queue/halq] [%d/%d],  "
+		"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
+		queue, qnum, params->aifs, params->cw_min,
+		params->cw_max, params->txop);
+
+	ret = ath_txq_update(sc, qnum, &qi);
+	if (ret)
+		DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n");
+
+	mutex_unlock(&sc->mutex);
+
+	return ret;
+}
+
+static int ath9k_set_key(struct ieee80211_hw *hw,
+			 enum set_key_cmd cmd,
+			 struct ieee80211_vif *vif,
+			 struct ieee80211_sta *sta,
+			 struct ieee80211_key_conf *key)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	int ret = 0;
+
+	if (modparam_nohwcrypt)
+		return -ENOSPC;
+
+	mutex_lock(&sc->mutex);
+	ath9k_ps_wakeup(sc);
+	DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n");
+
+	switch (cmd) {
+	case SET_KEY:
+		ret = ath_key_config(sc, vif, sta, key);
+		if (ret >= 0) {
+			key->hw_key_idx = ret;
+			/* push IV and Michael MIC generation to stack */
+			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+			if (key->alg == ALG_TKIP)
+				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+			if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
+				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
+			ret = 0;
+		}
+		break;
+	case DISABLE_KEY:
+		ath_key_delete(sc, key);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	ath9k_ps_restore(sc);
+	mutex_unlock(&sc->mutex);
+
+	return ret;
+}
+
+static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif,
+				   struct ieee80211_bss_conf *bss_conf,
+				   u32 changed)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_vif *avp = (void *)vif->drv_priv;
+	u32 rfilt = 0;
+	int error, i;
+
+	mutex_lock(&sc->mutex);
+
+	/*
+	 * TODO: Need to decide which hw opmode to use for
+	 *       multi-interface cases
+	 * XXX: This belongs into add_interface!
+	 */
+	if (vif->type == NL80211_IFTYPE_AP &&
+	    ah->opmode != NL80211_IFTYPE_AP) {
+		ah->opmode = NL80211_IFTYPE_STATION;
+		ath9k_hw_setopmode(ah);
+		memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN);
+		sc->curaid = 0;
+		ath9k_hw_write_associd(sc);
+		/* Request full reset to get hw opmode changed properly */
+		sc->sc_flags |= SC_OP_FULL_RESET;
+	}
+
+	if ((changed & BSS_CHANGED_BSSID) &&
+	    !is_zero_ether_addr(bss_conf->bssid)) {
+		switch (vif->type) {
+		case NL80211_IFTYPE_STATION:
+		case NL80211_IFTYPE_ADHOC:
+		case NL80211_IFTYPE_MESH_POINT:
+			/* Set BSSID */
+			memcpy(sc->curbssid, bss_conf->bssid, ETH_ALEN);
+			memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN);
+			sc->curaid = 0;
+			ath9k_hw_write_associd(sc);
+
+			/* Set aggregation protection mode parameters */
+			sc->config.ath_aggr_prot = 0;
+
+			DPRINTF(sc, ATH_DBG_CONFIG,
+				"RX filter 0x%x bssid %pM aid 0x%x\n",
+				rfilt, sc->curbssid, sc->curaid);
+
+			/* need to reconfigure the beacon */
+			sc->sc_flags &= ~SC_OP_BEACONS ;
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	if ((vif->type == NL80211_IFTYPE_ADHOC) ||
+	    (vif->type == NL80211_IFTYPE_AP) ||
+	    (vif->type == NL80211_IFTYPE_MESH_POINT)) {
+		if ((changed & BSS_CHANGED_BEACON) ||
+		    (changed & BSS_CHANGED_BEACON_ENABLED &&
+		     bss_conf->enable_beacon)) {
+			/*
+			 * Allocate and setup the beacon frame.
+			 *
+			 * Stop any previous beacon DMA.  This may be
+			 * necessary, for example, when an ibss merge
+			 * causes reconfiguration; we may be called
+			 * with beacon transmission active.
+			 */
+			ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+
+			error = ath_beacon_alloc(aphy, vif);
+			if (!error)
+				ath_beacon_config(sc, vif);
+		}
+	}
+
+	/* Check for WLAN_CAPABILITY_PRIVACY ? */
+	if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
+		for (i = 0; i < IEEE80211_WEP_NKID; i++)
+			if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
+				ath9k_hw_keysetmac(sc->sc_ah,
+						   (u16)i,
+						   sc->curbssid);
+	}
+
+	/* Only legacy IBSS for now */
+	if (vif->type == NL80211_IFTYPE_ADHOC)
+		ath_update_chainmask(sc, 0);
+
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
+			bss_conf->use_short_preamble);
+		if (bss_conf->use_short_preamble)
+			sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
+		else
+			sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
+	}
+
+	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+		DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
+			bss_conf->use_cts_prot);
+		if (bss_conf->use_cts_prot &&
+		    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
+			sc->sc_flags |= SC_OP_PROTECT_ENABLE;
+		else
+			sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
+	}
+
+	if (changed & BSS_CHANGED_ASSOC) {
+		DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+			bss_conf->assoc);
+		ath9k_bss_assoc_info(sc, vif, bss_conf);
+	}
+
+	/*
+	 * The HW TSF has to be reset when the beacon interval changes.
+	 * We set the flag here, and ath_beacon_config_ap() would take this
+	 * into account when it gets called through the subsequent
+	 * config_interface() call - with IFCC_BEACON in the changed field.
+	 */
+
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		sc->sc_flags |= SC_OP_TSF_RESET;
+		sc->beacon_interval = bss_conf->beacon_int;
+	}
+
+	mutex_unlock(&sc->mutex);
+}
+
+static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
+{
+	u64 tsf;
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	mutex_lock(&sc->mutex);
+	tsf = ath9k_hw_gettsf64(sc->sc_ah);
+	mutex_unlock(&sc->mutex);
+
+	return tsf;
+}
+
+static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	mutex_lock(&sc->mutex);
+	ath9k_hw_settsf64(sc->sc_ah, tsf);
+	mutex_unlock(&sc->mutex);
+}
+
+static void ath9k_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	mutex_lock(&sc->mutex);
+	ath9k_hw_reset_tsf(sc->sc_ah);
+	mutex_unlock(&sc->mutex);
+}
+
+static int ath9k_ampdu_action(struct ieee80211_hw *hw,
+			      enum ieee80211_ampdu_mlme_action action,
+			      struct ieee80211_sta *sta,
+			      u16 tid, u16 *ssn)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	int ret = 0;
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		if (!(sc->sc_flags & SC_OP_RXAGGR))
+			ret = -ENOTSUPP;
+		break;
+	case IEEE80211_AMPDU_RX_STOP:
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
+		if (ret < 0)
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"Unable to start TX aggregation\n");
+		else
+			ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_STOP:
+		ret = ath_tx_aggr_stop(sc, sta, tid);
+		if (ret < 0)
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"Unable to stop TX aggregation\n");
+
+		ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		ath_tx_aggr_resume(sc, sta, tid);
+		break;
+	default:
+		DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n");
+	}
+
+	return ret;
+}
+
+static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	if (ath9k_wiphy_scanning(sc)) {
+		printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the "
+		       "same time\n");
+		/*
+		 * Do not allow the concurrent scanning state for now. This
+		 * could be improved with scanning control moved into ath9k.
+		 */
+		return;
+	}
+
+	aphy->state = ATH_WIPHY_SCAN;
+	ath9k_wiphy_pause_all_forced(sc, aphy);
+
+	mutex_lock(&sc->mutex);
+	sc->sc_flags |= SC_OP_SCANNING;
+	mutex_unlock(&sc->mutex);
+}
+
+static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	mutex_lock(&sc->mutex);
+	aphy->state = ATH_WIPHY_ACTIVE;
+	sc->sc_flags &= ~SC_OP_SCANNING;
+	sc->sc_flags |= SC_OP_FULL_RESET;
+	mutex_unlock(&sc->mutex);
+}
+
+struct ieee80211_ops ath9k_ops = {
+	.tx 		    = ath9k_tx,
+	.start 		    = ath9k_start,
+	.stop 		    = ath9k_stop,
+	.add_interface 	    = ath9k_add_interface,
+	.remove_interface   = ath9k_remove_interface,
+	.config 	    = ath9k_config,
+	.configure_filter   = ath9k_configure_filter,
+	.sta_notify         = ath9k_sta_notify,
+	.conf_tx 	    = ath9k_conf_tx,
+	.bss_info_changed   = ath9k_bss_info_changed,
+	.set_key            = ath9k_set_key,
+	.get_tsf 	    = ath9k_get_tsf,
+	.set_tsf 	    = ath9k_set_tsf,
+	.reset_tsf 	    = ath9k_reset_tsf,
+	.ampdu_action       = ath9k_ampdu_action,
+	.sw_scan_start      = ath9k_sw_scan_start,
+	.sw_scan_complete   = ath9k_sw_scan_complete,
+	.rfkill_poll        = ath9k_rfkill_poll_state,
+};
+
+static struct {
+	u32 version;
+	const char * name;
+} ath_mac_bb_names[] = {
+	{ AR_SREV_VERSION_5416_PCI,	"5416" },
+	{ AR_SREV_VERSION_5416_PCIE,	"5418" },
+	{ AR_SREV_VERSION_9100,		"9100" },
+	{ AR_SREV_VERSION_9160,		"9160" },
+	{ AR_SREV_VERSION_9280,		"9280" },
+	{ AR_SREV_VERSION_9285,		"9285" }
+};
+
+static struct {
+	u16 version;
+	const char * name;
+} ath_rf_names[] = {
+	{ 0,				"5133" },
+	{ AR_RAD5133_SREV_MAJOR,	"5133" },
+	{ AR_RAD5122_SREV_MAJOR,	"5122" },
+	{ AR_RAD2133_SREV_MAJOR,	"2133" },
+	{ AR_RAD2122_SREV_MAJOR,	"2122" }
+};
+
+/*
+ * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
+ */
+const char *
+ath_mac_bb_name(u32 mac_bb_version)
+{
+	int i;
+
+	for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
+		if (ath_mac_bb_names[i].version == mac_bb_version) {
+			return ath_mac_bb_names[i].name;
+		}
+	}
+
+	return "????";
+}
+
+/*
+ * Return the RF name. "????" is returned if the RF is unknown.
+ */
+const char *
+ath_rf_name(u16 rf_version)
+{
+	int i;
+
+	for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
+		if (ath_rf_names[i].version == rf_version) {
+			return ath_rf_names[i].name;
+		}
+	}
+
+	return "????";
+}
+
+static int __init ath9k_init(void)
+{
+	int error;
+
+	/* Register rate control algorithm */
+	error = ath_rate_control_register();
+	if (error != 0) {
+		printk(KERN_ERR
+			"ath9k: Unable to register rate control "
+			"algorithm: %d\n",
+			error);
+		goto err_out;
+	}
+
+	error = ath9k_debug_create_root();
+	if (error) {
+		printk(KERN_ERR
+			"ath9k: Unable to create debugfs root: %d\n",
+			error);
+		goto err_rate_unregister;
+	}
+
+	error = ath_pci_init();
+	if (error < 0) {
+		printk(KERN_ERR
+			"ath9k: No PCI devices found, driver not installed.\n");
+		error = -ENODEV;
+		goto err_remove_root;
+	}
+
+	error = ath_ahb_init();
+	if (error < 0) {
+		error = -ENODEV;
+		goto err_pci_exit;
+	}
+
+	return 0;
+
+ err_pci_exit:
+	ath_pci_exit();
+
+ err_remove_root:
+	ath9k_debug_remove_root();
+ err_rate_unregister:
+	ath_rate_control_unregister();
+ err_out:
+	return error;
+}
+module_init(ath9k_init);
+
+static void __exit ath9k_exit(void)
+{
+	ath_ahb_exit();
+	ath_pci_exit();
+	ath9k_debug_remove_root();
+	ath_rate_control_unregister();
+	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
+}
+module_exit(ath9k_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,18 @@
+ath9k-y +=	hw.o \
+		eeprom.o \
+		mac.o \
+		calib.o \
+		ani.o \
+		phy.o \
+		beacon.o \
+		main.o \
+		recv.o \
+		xmit.o \
+		virtual.o \
+		rc.o
+
+ath9k-$(CONFIG_PCI) += pci.o
+ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
+ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o
+
+obj-$(CONFIG_ATH9K) += ath9k.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/pci.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/pci.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/pci.h>
+#include "ath9k.h"
+
+static struct pci_device_id ath_pci_id_table[] __devinitdata = {
+	{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI   */
+	{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
+	{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
+	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
+	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+	{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
+	{ 0 }
+};
+
+/* return bus cachesize in 4B word units */
+static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
+{
+	u8 u8tmp;
+
+	pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE,
+			     (u8 *)&u8tmp);
+	*csz = (int)u8tmp;
+
+	/*
+	 * This check was put in to avoid "unplesant" consequences if
+	 * the bootrom has not fully initialized all PCI devices.
+	 * Sometimes the cache line size register is not set
+	 */
+
+	if (*csz == 0)
+		*csz = DEFAULT_CACHELINE >> 2;   /* Use the default size */
+}
+
+static void ath_pci_cleanup(struct ath_softc *sc)
+{
+	struct pci_dev *pdev = to_pci_dev(sc->dev);
+
+	pci_iounmap(pdev, sc->mem);
+	pci_disable_device(pdev);
+	pci_release_region(pdev, 0);
+}
+
+static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
+{
+	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+
+	if (!ath9k_hw_wait(ah,
+			   AR_EEPROM_STATUS_DATA,
+			   AR_EEPROM_STATUS_DATA_BUSY |
+			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
+			   AH_WAIT_TIMEOUT)) {
+		return false;
+	}
+
+	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
+		   AR_EEPROM_STATUS_DATA_VAL);
+
+	return true;
+}
+
+static struct ath_bus_ops ath_pci_bus_ops = {
+	.read_cachesize = ath_pci_read_cachesize,
+	.cleanup = ath_pci_cleanup,
+	.eeprom_read = ath_pci_eeprom_read,
+};
+
+static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	void __iomem *mem;
+	struct ath_wiphy *aphy;
+	struct ath_softc *sc;
+	struct ieee80211_hw *hw;
+	u8 csz;
+	u32 val;
+	int ret = 0;
+	struct ath_hw *ah;
+
+	if (pci_enable_device(pdev))
+		return -EIO;
+
+	ret =  pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+
+	if (ret) {
+		printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
+		goto bad;
+	}
+
+	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+
+	if (ret) {
+		printk(KERN_ERR "ath9k: 32-bit DMA consistent "
+			"DMA enable failed\n");
+		goto bad;
+	}
+
+	/*
+	 * Cache line size is used to size and align various
+	 * structures used to communicate with the hardware.
+	 */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+	if (csz == 0) {
+		/*
+		 * Linux 2.4.18 (at least) writes the cache line size
+		 * register as a 16-bit wide register which is wrong.
+		 * We must have this setup properly for rx buffer
+		 * DMA to work so force a reasonable value here if it
+		 * comes up zero.
+		 */
+		csz = L1_CACHE_BYTES / sizeof(u32);
+		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+	}
+	/*
+	 * The default setting of latency timer yields poor results,
+	 * set it to the value used by other systems. It may be worth
+	 * tweaking this setting more.
+	 */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+	pci_set_master(pdev);
+
+	/*
+	 * Disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_read_config_dword(pdev, 0x40, &val);
+	if ((val & 0x0000ff00) != 0)
+		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+	ret = pci_request_region(pdev, 0, "ath9k");
+	if (ret) {
+		dev_err(&pdev->dev, "PCI memory region reserve error\n");
+		ret = -ENODEV;
+		goto bad;
+	}
+
+	mem = pci_iomap(pdev, 0, 0);
+	if (!mem) {
+		printk(KERN_ERR "PCI memory map error\n") ;
+		ret = -EIO;
+		goto bad1;
+	}
+
+	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
+				sizeof(struct ath_softc), &ath9k_ops);
+	if (hw == NULL) {
+		printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n");
+		goto bad2;
+	}
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+	pci_set_drvdata(pdev, hw);
+
+	aphy = hw->priv;
+	sc = (struct ath_softc *) (aphy + 1);
+	aphy->sc = sc;
+	aphy->hw = hw;
+	sc->pri_wiphy = aphy;
+	sc->hw = hw;
+	sc->dev = &pdev->dev;
+	sc->mem = mem;
+	sc->bus_ops = &ath_pci_bus_ops;
+
+	if (ath_attach(id->device, sc) != 0) {
+		ret = -ENODEV;
+		goto bad3;
+	}
+
+	/* setup interrupt service routine */
+
+	if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) {
+		printk(KERN_ERR "%s: request_irq failed\n",
+			wiphy_name(hw->wiphy));
+		ret = -EIO;
+		goto bad4;
+	}
+
+	sc->irq = pdev->irq;
+
+	ah = sc->sc_ah;
+	printk(KERN_INFO
+	       "%s: Atheros AR%s MAC/BB Rev:%x "
+	       "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n",
+	       wiphy_name(hw->wiphy),
+	       ath_mac_bb_name(ah->hw_version.macVersion),
+	       ah->hw_version.macRev,
+	       ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
+	       ah->hw_version.phyRev,
+	       (unsigned long)mem, pdev->irq);
+
+	return 0;
+bad4:
+	ath_detach(sc);
+bad3:
+	ieee80211_free_hw(hw);
+bad2:
+	pci_iounmap(pdev, mem);
+bad1:
+	pci_release_region(pdev, 0);
+bad:
+	pci_disable_device(pdev);
+	return ret;
+}
+
+static void ath_pci_remove(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	ath_cleanup(sc);
+}
+
+#ifdef CONFIG_PM
+
+static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+
+	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int ath_pci_resume(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	u32 val;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+	pci_restore_state(pdev);
+	/*
+	 * Suspend/Resume resets the PCI configuration space, so we have to
+	 * re-disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state
+	 */
+	pci_read_config_dword(pdev, 0x40, &val);
+	if ((val & 0x0000ff00) != 0)
+		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+	/* Enable LED */
+	ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
+			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
+
+static struct pci_driver ath_pci_driver = {
+	.name       = "ath9k",
+	.id_table   = ath_pci_id_table,
+	.probe      = ath_pci_probe,
+	.remove     = ath_pci_remove,
+#ifdef CONFIG_PM
+	.suspend    = ath_pci_suspend,
+	.resume     = ath_pci_resume,
+#endif /* CONFIG_PM */
+};
+
+int ath_pci_init(void)
+{
+	return pci_register_driver(&ath_pci_driver);
+}
+
+void ath_pci_exit(void)
+{
+	pci_unregister_driver(&ath_pci_driver);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/phy.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/phy.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+void
+ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex,
+		    int regWrites)
+{
+	REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
+}
+
+bool
+ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	u32 channelSel = 0;
+	u32 bModeSynth = 0;
+	u32 aModeRefSel = 0;
+	u32 reg32 = 0;
+	u16 freq;
+	struct chan_centers centers;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	freq = centers.synth_center;
+
+	if (freq < 4800) {
+		u32 txctl;
+
+		if (((freq - 2192) % 5) == 0) {
+			channelSel = ((freq - 672) * 2 - 3040) / 10;
+			bModeSynth = 0;
+		} else if (((freq - 2224) % 5) == 0) {
+			channelSel = ((freq - 704) * 2 - 3040) / 10;
+			bModeSynth = 1;
+		} else {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Invalid channel %u MHz\n", freq);
+			return false;
+		}
+
+		channelSel = (channelSel << 2) & 0xff;
+		channelSel = ath9k_hw_reverse_bits(channelSel, 8);
+
+		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+		if (freq == 2484) {
+
+			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+				  txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+		} else {
+			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+				  txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+		}
+
+	} else if ((freq % 20) == 0 && freq >= 5120) {
+		channelSel =
+		    ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
+		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+	} else if ((freq % 10) == 0) {
+		channelSel =
+		    ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
+		if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
+			aModeRefSel = ath9k_hw_reverse_bits(2, 2);
+		else
+			aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+	} else if ((freq % 5) == 0) {
+		channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
+		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+	} else {
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Invalid channel %u MHz\n", freq);
+		return false;
+	}
+
+	reg32 =
+	    (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
+	    (1 << 5) | 0x1;
+
+	REG_WRITE(ah, AR_PHY(0x37), reg32);
+
+	ah->curchan = chan;
+	ah->curchan_rad_index = -1;
+
+	return true;
+}
+
+void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
+				 struct ath9k_channel *chan)
+{
+	u16 bMode, fracMode, aModeRefSel = 0;
+	u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
+	struct chan_centers centers;
+	u32 refDivA = 24;
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+	freq = centers.synth_center;
+
+	reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
+	reg32 &= 0xc0000000;
+
+	if (freq < 4800) {
+		u32 txctl;
+
+		bMode = 1;
+		fracMode = 1;
+		aModeRefSel = 0;
+		channelSel = (freq * 0x10000) / 15;
+
+		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+		if (freq == 2484) {
+
+			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+				  txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+		} else {
+			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+				  txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+		}
+	} else {
+		bMode = 0;
+		fracMode = 0;
+
+		switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
+		case 0:
+			if ((freq % 20) == 0) {
+				aModeRefSel = 3;
+			} else if ((freq % 10) == 0) {
+				aModeRefSel = 2;
+			}
+			if (aModeRefSel)
+				break;
+		case 1:
+		default:
+			aModeRefSel = 0;
+			fracMode = 1;
+			refDivA = 1;
+			channelSel = (freq * 0x8000) / 15;
+
+			REG_RMW_FIELD(ah, AR_AN_SYNTH9,
+				      AR_AN_SYNTH9_REFDIVA, refDivA);
+
+		}
+
+		if (!fracMode) {
+			ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
+			channelSel = ndiv & 0x1ff;
+			channelFrac = (ndiv & 0xfffffe00) * 2;
+			channelSel = (channelSel << 17) | channelFrac;
+		}
+	}
+
+	reg32 = reg32 |
+	    (bMode << 29) |
+	    (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
+
+	REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
+
+	ah->curchan = chan;
+	ah->curchan_rad_index = -1;
+}
+
+static void
+ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
+			   u32 numBits, u32 firstBit,
+			   u32 column)
+{
+	u32 tmp32, mask, arrayEntry, lastBit;
+	int32_t bitPosition, bitsLeft;
+
+	tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
+	arrayEntry = (firstBit - 1) / 8;
+	bitPosition = (firstBit - 1) % 8;
+	bitsLeft = numBits;
+	while (bitsLeft > 0) {
+		lastBit = (bitPosition + bitsLeft > 8) ?
+		    8 : bitPosition + bitsLeft;
+		mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
+		    (column * 8);
+		rfBuf[arrayEntry] &= ~mask;
+		rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
+				      (column * 8)) & mask;
+		bitsLeft -= 8 - bitPosition;
+		tmp32 = tmp32 >> (8 - bitPosition);
+		bitPosition = 0;
+		arrayEntry++;
+	}
+}
+
+bool
+ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
+		     u16 modesIndex)
+{
+	u32 eepMinorRev;
+	u32 ob5GHz = 0, db5GHz = 0;
+	u32 ob2GHz = 0, db2GHz = 0;
+	int regWrites = 0;
+
+	if (AR_SREV_9280_10_OR_LATER(ah))
+		return true;
+
+	eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
+
+	RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1);
+
+	RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1);
+
+	RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1);
+
+	RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3,
+		      modesIndex);
+	{
+		int i;
+		for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
+			ah->analogBank6Data[i] =
+			    INI_RA(&ah->iniBank6TPC, i, modesIndex);
+		}
+	}
+
+	if (eepMinorRev >= 2) {
+		if (IS_CHAN_2GHZ(chan)) {
+			ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);
+			db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2);
+			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
+						   ob2GHz, 3, 197, 0);
+			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
+						   db2GHz, 3, 194, 0);
+		} else {
+			ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5);
+			db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5);
+			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
+						   ob5GHz, 3, 203, 0);
+			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
+						   db5GHz, 3, 200, 0);
+		}
+	}
+
+	RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1);
+
+	REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
+			   regWrites);
+	REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
+			   regWrites);
+	REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
+			   regWrites);
+	REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
+			   regWrites);
+	REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
+			   regWrites);
+	REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
+			   regWrites);
+
+	return true;
+}
+
+void
+ath9k_hw_rfdetach(struct ath_hw *ah)
+{
+	if (ah->analogBank0Data != NULL) {
+		kfree(ah->analogBank0Data);
+		ah->analogBank0Data = NULL;
+	}
+	if (ah->analogBank1Data != NULL) {
+		kfree(ah->analogBank1Data);
+		ah->analogBank1Data = NULL;
+	}
+	if (ah->analogBank2Data != NULL) {
+		kfree(ah->analogBank2Data);
+		ah->analogBank2Data = NULL;
+	}
+	if (ah->analogBank3Data != NULL) {
+		kfree(ah->analogBank3Data);
+		ah->analogBank3Data = NULL;
+	}
+	if (ah->analogBank6Data != NULL) {
+		kfree(ah->analogBank6Data);
+		ah->analogBank6Data = NULL;
+	}
+	if (ah->analogBank6TPCData != NULL) {
+		kfree(ah->analogBank6TPCData);
+		ah->analogBank6TPCData = NULL;
+	}
+	if (ah->analogBank7Data != NULL) {
+		kfree(ah->analogBank7Data);
+		ah->analogBank7Data = NULL;
+	}
+	if (ah->addac5416_21 != NULL) {
+		kfree(ah->addac5416_21);
+		ah->addac5416_21 = NULL;
+	}
+	if (ah->bank6Temp != NULL) {
+		kfree(ah->bank6Temp);
+		ah->bank6Temp = NULL;
+	}
+}
+
+bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
+{
+	if (!AR_SREV_9280_10_OR_LATER(ah)) {
+		ah->analogBank0Data =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank0.ia_rows), GFP_KERNEL);
+		ah->analogBank1Data =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank1.ia_rows), GFP_KERNEL);
+		ah->analogBank2Data =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank2.ia_rows), GFP_KERNEL);
+		ah->analogBank3Data =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank3.ia_rows), GFP_KERNEL);
+		ah->analogBank6Data =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank6.ia_rows), GFP_KERNEL);
+		ah->analogBank6TPCData =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank6TPC.ia_rows), GFP_KERNEL);
+		ah->analogBank7Data =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank7.ia_rows), GFP_KERNEL);
+
+		if (ah->analogBank0Data == NULL
+		    || ah->analogBank1Data == NULL
+		    || ah->analogBank2Data == NULL
+		    || ah->analogBank3Data == NULL
+		    || ah->analogBank6Data == NULL
+		    || ah->analogBank6TPCData == NULL
+		    || ah->analogBank7Data == NULL) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Cannot allocate RF banks\n");
+			*status = -ENOMEM;
+			return false;
+		}
+
+		ah->addac5416_21 =
+		    kzalloc((sizeof(u32) *
+			     ah->iniAddac.ia_rows *
+			     ah->iniAddac.ia_columns), GFP_KERNEL);
+		if (ah->addac5416_21 == NULL) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Cannot allocate addac5416_21\n");
+			*status = -ENOMEM;
+			return false;
+		}
+
+		ah->bank6Temp =
+		    kzalloc((sizeof(u32) *
+			     ah->iniBank6.ia_rows), GFP_KERNEL);
+		if (ah->bank6Temp == NULL) {
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Cannot allocate bank6Temp\n");
+			*status = -ENOMEM;
+			return false;
+		}
+	}
+
+	return true;
+}
+
+void
+ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	int i, regWrites = 0;
+	u32 bank6SelMask;
+	u32 *bank6Temp = ah->bank6Temp;
+
+	switch (ah->diversity_control) {
+	case ATH9K_ANT_FIXED_A:
+		bank6SelMask =
+		    (ah->
+		     antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 :
+		    REDUCE_CHAIN_1;
+		break;
+	case ATH9K_ANT_FIXED_B:
+		bank6SelMask =
+		    (ah->
+		     antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 :
+		    REDUCE_CHAIN_0;
+		break;
+	case ATH9K_ANT_VARIABLE:
+		return;
+		break;
+	default:
+		return;
+		break;
+	}
+
+	for (i = 0; i < ah->iniBank6.ia_rows; i++)
+		bank6Temp[i] = ah->analogBank6Data[i];
+
+	REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask);
+
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0);
+	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0);
+
+	REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites);
+
+	REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053);
+#ifdef ALTER_SWITCH
+	REG_WRITE(ah, PHY_SWITCH_CHAIN_0,
+		  (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38)
+		  | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38));
+#endif
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/phy.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/phy.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/phy.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef PHY_H
+#define PHY_H
+
+void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
+				 struct ath9k_channel
+				 *chan);
+bool ath9k_hw_set_channel(struct ath_hw *ah,
+			  struct ath9k_channel *chan);
+void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex,
+			 u32 freqIndex, int regWrites);
+bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
+			  struct ath9k_channel *chan,
+			  u16 modesIndex);
+void ath9k_hw_decrease_chain_power(struct ath_hw *ah,
+				   struct ath9k_channel *chan);
+bool ath9k_hw_init_rf(struct ath_hw *ah,
+		      int *status);
+
+#define AR_PHY_BASE     0x9800
+#define AR_PHY(_n)      (AR_PHY_BASE + ((_n)<<2))
+
+#define AR_PHY_TEST             0x9800
+#define PHY_AGC_CLR             0x10000000
+#define RFSILENT_BB             0x00002000
+
+#define AR_PHY_TURBO                0x9804
+#define AR_PHY_FC_TURBO_MODE        0x00000001
+#define AR_PHY_FC_TURBO_SHORT       0x00000002
+#define AR_PHY_FC_DYN2040_EN        0x00000004
+#define AR_PHY_FC_DYN2040_PRI_ONLY  0x00000008
+#define AR_PHY_FC_DYN2040_PRI_CH    0x00000010
+#define AR_PHY_FC_DYN2040_EXT_CH    0x00000020
+#define AR_PHY_FC_HT_EN             0x00000040
+#define AR_PHY_FC_SHORT_GI_40       0x00000080
+#define AR_PHY_FC_WALSH             0x00000100
+#define AR_PHY_FC_SINGLE_HT_LTF1    0x00000200
+#define AR_PHY_FC_ENABLE_DAC_FIFO   0x00000800
+
+#define AR_PHY_TEST2 		    0x9808
+
+#define AR_PHY_TIMING2           0x9810
+#define AR_PHY_TIMING3           0x9814
+#define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000
+#define AR_PHY_TIMING3_DSC_MAN_S 17
+#define AR_PHY_TIMING3_DSC_EXP   0x0001E000
+#define AR_PHY_TIMING3_DSC_EXP_S 13
+
+#define AR_PHY_CHIP_ID            0x9818
+#define AR_PHY_CHIP_ID_REV_0      0x80
+#define AR_PHY_CHIP_ID_REV_1      0x81
+#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
+
+#define AR_PHY_ACTIVE       0x981C
+#define AR_PHY_ACTIVE_EN    0x00000001
+#define AR_PHY_ACTIVE_DIS   0x00000000
+
+#define AR_PHY_RF_CTL2             0x9824
+#define AR_PHY_TX_END_DATA_START   0x000000FF
+#define AR_PHY_TX_END_DATA_START_S 0
+#define AR_PHY_TX_END_PA_ON        0x0000FF00
+#define AR_PHY_TX_END_PA_ON_S      8
+
+#define AR_PHY_RF_CTL3                  0x9828
+#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S     16
+
+#define AR_PHY_ADC_CTL                  0x982C
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN    0x00000003
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S  0
+#define AR_PHY_ADC_CTL_OFF_PWDDAC       0x00002000
+#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP   0x00004000
+#define AR_PHY_ADC_CTL_OFF_PWDADC       0x00008000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN     0x00030000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S   16
+
+#define AR_PHY_ADC_SERIAL_CTL       0x9830
+#define AR_PHY_SEL_INTERNAL_ADDAC   0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO   0x00000001
+
+#define AR_PHY_RF_CTL4                    0x9834
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF    0xFF000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S  24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF    0x00FF0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S  16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON      0x0000FF00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S    8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON      0x000000FF
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S    0
+
+#define AR_PHY_TSTDAC_CONST               0x983c
+
+#define AR_PHY_SETTLING          0x9844
+#define AR_PHY_SETTLING_SWITCH   0x00003F80
+#define AR_PHY_SETTLING_SWITCH_S 7
+
+#define AR_PHY_RXGAIN                   0x9848
+#define AR_PHY_RXGAIN_TXRX_ATTEN        0x0003F000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S      12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX       0x007C0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S     18
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN    0x00003F80
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S  7
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN   0x001FC000
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
+
+#define AR_PHY_DESIRED_SZ           0x9850
+#define AR_PHY_DESIRED_SZ_ADC       0x000000FF
+#define AR_PHY_DESIRED_SZ_ADC_S     0
+#define AR_PHY_DESIRED_SZ_PGA       0x0000FF00
+#define AR_PHY_DESIRED_SZ_PGA_S     8
+#define AR_PHY_DESIRED_SZ_TOT_DES   0x0FF00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+
+#define AR_PHY_FIND_SIG           0x9858
+#define AR_PHY_FIND_SIG_FIRSTEP   0x0003F000
+#define AR_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR_PHY_FIND_SIG_FIRPWR    0x03FC0000
+#define AR_PHY_FIND_SIG_FIRPWR_S  18
+
+#define AR_PHY_AGC_CTL1                  0x985C
+#define AR_PHY_AGC_CTL1_COARSE_LOW       0x00007F80
+#define AR_PHY_AGC_CTL1_COARSE_LOW_S     7
+#define AR_PHY_AGC_CTL1_COARSE_HIGH      0x003F8000
+#define AR_PHY_AGC_CTL1_COARSE_HIGH_S    15
+
+#define AR_PHY_AGC_CONTROL               0x9860
+#define AR_PHY_AGC_CONTROL_CAL           0x00000001
+#define AR_PHY_AGC_CONTROL_NF            0x00000002
+#define AR_PHY_AGC_CONTROL_ENABLE_NF     0x00008000
+#define AR_PHY_AGC_CONTROL_FLTR_CAL      0x00010000
+#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF  0x00020000
+
+#define AR_PHY_CCA                  0x9864
+#define AR_PHY_MINCCA_PWR           0x0FF80000
+#define AR_PHY_MINCCA_PWR_S         19
+#define AR_PHY_CCA_THRESH62         0x0007F000
+#define AR_PHY_CCA_THRESH62_S       12
+#define AR9280_PHY_MINCCA_PWR       0x1FF00000
+#define AR9280_PHY_MINCCA_PWR_S     20
+#define AR9280_PHY_CCA_THRESH62     0x000FF000
+#define AR9280_PHY_CCA_THRESH62_S   12
+
+#define AR_PHY_SFCORR_LOW                    0x986C
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW  0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW    0x00003F00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S  8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW      0x001FC000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S    14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW      0x0FE00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S    21
+
+#define AR_PHY_SFCORR                0x9868
+#define AR_PHY_SFCORR_M2COUNT_THR    0x0000001F
+#define AR_PHY_SFCORR_M2COUNT_THR_S  0
+#define AR_PHY_SFCORR_M1_THRESH      0x00FE0000
+#define AR_PHY_SFCORR_M1_THRESH_S    17
+#define AR_PHY_SFCORR_M2_THRESH      0x7F000000
+#define AR_PHY_SFCORR_M2_THRESH_S    24
+
+#define AR_PHY_SLEEP_CTR_CONTROL    0x9870
+#define AR_PHY_SLEEP_CTR_LIMIT      0x9874
+#define AR_PHY_SYNTH_CONTROL        0x9874
+#define AR_PHY_SLEEP_SCAL           0x9878
+
+#define AR_PHY_PLL_CTL          0x987c
+#define AR_PHY_PLL_CTL_40       0xaa
+#define AR_PHY_PLL_CTL_40_5413  0x04
+#define AR_PHY_PLL_CTL_44       0xab
+#define AR_PHY_PLL_CTL_44_2133  0xeb
+#define AR_PHY_PLL_CTL_40_2133  0xea
+
+#define AR_PHY_RX_DELAY           0x9914
+#define AR_PHY_SEARCH_START_DELAY 0x9918
+#define AR_PHY_RX_DELAY_DELAY     0x00003FFF
+
+#define AR_PHY_TIMING_CTRL4(_i)     (0x9920 + ((_i) << 12))
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE   0x800
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S   12
+#define AR_PHY_TIMING_CTRL4_DO_CAL    0x10000
+
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI	0x80000000
+#define	AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER	0x40000000
+#define	AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK	0x20000000
+#define	AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK	0x10000000
+
+#define AR_PHY_TIMING5               0x9924
+#define AR_PHY_TIMING5_CYCPWR_THR1   0x000000FE
+#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
+
+#define AR_PHY_POWER_TX_RATE1               0x9934
+#define AR_PHY_POWER_TX_RATE2               0x9938
+#define AR_PHY_POWER_TX_RATE_MAX            0x993c
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+
+#define AR_PHY_FRAME_CTL            0x9944
+#define AR_PHY_FRAME_CTL_TX_CLIP    0x00000038
+#define AR_PHY_FRAME_CTL_TX_CLIP_S  3
+
+#define AR_PHY_TXPWRADJ                   0x994C
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA    0x00000FC0
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S  6
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX   0x00FC0000
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
+
+#define AR_PHY_RADAR_EXT      0x9940
+#define AR_PHY_RADAR_EXT_ENA  0x00004000
+
+#define AR_PHY_RADAR_0          0x9954
+#define AR_PHY_RADAR_0_ENA      0x00000001
+#define AR_PHY_RADAR_0_FFT_ENA  0x80000000
+#define AR_PHY_RADAR_0_INBAND   0x0000003e
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI    0x00000FC0
+#define AR_PHY_RADAR_0_PRSSI_S  6
+#define AR_PHY_RADAR_0_HEIGHT   0x0003F000
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI    0x00FC0000
+#define AR_PHY_RADAR_0_RRSSI_S  18
+#define AR_PHY_RADAR_0_FIRPWR   0x7F000000
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+
+#define AR_PHY_RADAR_1                  0x9958
+#define AR_PHY_RADAR_1_RELPWR_ENA       0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128       0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH    0x003F0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S  16
+#define AR_PHY_RADAR_1_BLOCK_CHECK      0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI        0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK    0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH   0x00001F00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN           0x000000FF
+#define AR_PHY_RADAR_1_MAXLEN_S         0
+
+#define AR_PHY_SWITCH_CHAIN_0     0x9960
+#define AR_PHY_SWITCH_COM         0x9964
+
+#define AR_PHY_SIGMA_DELTA            0x996C
+#define AR_PHY_SIGMA_DELTA_ADC_SEL    0x00000003
+#define AR_PHY_SIGMA_DELTA_ADC_SEL_S  0
+#define AR_PHY_SIGMA_DELTA_FILT2      0x000000F8
+#define AR_PHY_SIGMA_DELTA_FILT2_S    3
+#define AR_PHY_SIGMA_DELTA_FILT1      0x00001F00
+#define AR_PHY_SIGMA_DELTA_FILT1_S    8
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP   0x01FFE000
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+#define AR_PHY_RESTART          0x9970
+#define AR_PHY_RESTART_DIV_GC   0x001C0000
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+#define AR_PHY_RFBUS_REQ        0x997C
+#define AR_PHY_RFBUS_REQ_EN     0x00000001
+
+#define	AR_PHY_TIMING7		        0x9980
+#define	AR_PHY_TIMING8		        0x9984
+#define	AR_PHY_TIMING8_PILOT_MASK_2	0x000FFFFF
+#define	AR_PHY_TIMING8_PILOT_MASK_2_S	0
+
+#define	AR_PHY_BIN_MASK2_1	0x9988
+#define	AR_PHY_BIN_MASK2_2	0x998c
+#define	AR_PHY_BIN_MASK2_3	0x9990
+#define	AR_PHY_BIN_MASK2_4	0x9994
+
+#define	AR_PHY_BIN_MASK_1	0x9900
+#define	AR_PHY_BIN_MASK_2	0x9904
+#define	AR_PHY_BIN_MASK_3	0x9908
+
+#define	AR_PHY_MASK_CTL		0x990c
+
+#define	AR_PHY_BIN_MASK2_4_MASK_4	0x00003FFF
+#define	AR_PHY_BIN_MASK2_4_MASK_4_S	0
+
+#define	AR_PHY_TIMING9		        0x9998
+#define	AR_PHY_TIMING10		        0x999c
+#define	AR_PHY_TIMING10_PILOT_MASK_2	0x000FFFFF
+#define	AR_PHY_TIMING10_PILOT_MASK_2_S	0
+
+#define	AR_PHY_TIMING11			        0x99a0
+#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE	0x000FFFFF
+#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE_S	0
+#define	AR_PHY_TIMING11_SPUR_FREQ_SD		0x3FF00000
+#define	AR_PHY_TIMING11_SPUR_FREQ_SD_S		20
+#define AR_PHY_TIMING11_USE_SPUR_IN_AGC		0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR	0x80000000
+
+#define AR_PHY_RX_CHAINMASK     0x99a4
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
+#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+#define AR_PHY_MULTICHAIN_GAIN_CTL  0x99ac
+
+#define AR_PHY_EXT_CCA0             0x99b8
+#define AR_PHY_EXT_CCA0_THRESH62    0x000000FF
+#define AR_PHY_EXT_CCA0_THRESH62_S  0
+
+#define AR_PHY_EXT_CCA                  0x99bc
+#define AR_PHY_EXT_CCA_CYCPWR_THR1      0x0000FE00
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_S    9
+#define AR_PHY_EXT_CCA_THRESH62         0x007F0000
+#define AR_PHY_EXT_CCA_THRESH62_S       16
+#define AR_PHY_EXT_MINCCA_PWR           0xFF800000
+#define AR_PHY_EXT_MINCCA_PWR_S         23
+#define AR9280_PHY_EXT_MINCCA_PWR       0x01FF0000
+#define AR9280_PHY_EXT_MINCCA_PWR_S     16
+
+#define AR_PHY_SFCORR_EXT                 0x99c0
+#define AR_PHY_SFCORR_EXT_M1_THRESH       0x0000007F
+#define AR_PHY_SFCORR_EXT_M1_THRESH_S     0
+#define AR_PHY_SFCORR_EXT_M2_THRESH       0x00003F80
+#define AR_PHY_SFCORR_EXT_M2_THRESH_S     7
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW   0x001FC000
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW   0x0FE00000
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S   28
+
+#define AR_PHY_HALFGI           0x99D0
+#define AR_PHY_HALFGI_DSC_MAN   0x0007FFF0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+#define AR_PHY_HALFGI_DSC_EXP   0x0000000F
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR_PHY_CHAN_INFO_MEMORY               0x99DC
+#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK  0x0001
+
+#define AR_PHY_HEAVY_CLIP_ENABLE         0x99E0
+
+#define AR_PHY_M_SLEEP      0x99f0
+#define AR_PHY_REFCLKDLY    0x99f4
+#define AR_PHY_REFCLKPD     0x99f8
+
+#define AR_PHY_CALMODE      0x99f0
+
+#define AR_PHY_CALMODE_IQ           0x00000000
+#define AR_PHY_CALMODE_ADC_GAIN     0x00000001
+#define AR_PHY_CALMODE_ADC_DC_PER   0x00000002
+#define AR_PHY_CALMODE_ADC_DC_INIT  0x00000003
+
+#define AR_PHY_CAL_MEAS_0(_i)     (0x9c10 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_1(_i)     (0x9c14 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_2(_i)     (0x9c18 + ((_i) << 12))
+#define AR_PHY_CAL_MEAS_3(_i)     (0x9c1c + ((_i) << 12))
+
+#define AR_PHY_CURRENT_RSSI 0x9c1c
+#define AR9280_PHY_CURRENT_RSSI 0x9c3c
+
+#define AR_PHY_RFBUS_GRANT       0x9C20
+#define AR_PHY_RFBUS_GRANT_EN    0x00000001
+
+#define AR_PHY_CHAN_INFO_GAIN_DIFF             0x9CF4
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
+#define AR_PHY_CHAN_INFO_GAIN          0x9CFC
+
+#define AR_PHY_MODE         0xA200
+#define AR_PHY_MODE_AR2133  0x08
+#define AR_PHY_MODE_AR5111  0x00
+#define AR_PHY_MODE_AR5112  0x08
+#define AR_PHY_MODE_DYNAMIC 0x04
+#define AR_PHY_MODE_RF2GHZ  0x02
+#define AR_PHY_MODE_RF5GHZ  0x00
+#define AR_PHY_MODE_CCK     0x01
+#define AR_PHY_MODE_OFDM    0x00
+#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
+
+#define AR_PHY_CCK_TX_CTRL       0xA204
+#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK         0x0000000C
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S       2
+
+#define AR_PHY_CCK_DETECT                           0xA208
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0
+/* [12:6] settling time for antenna switch */
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S         6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV    0x2000
+
+#define AR_PHY_GAIN_2GHZ                0xA20C
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN    0x00FC0000
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S  18
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN     0x00003C00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S   10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN      0x0000001F
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S    0
+
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN     0x003E0000
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S   17
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN     0x0001F000
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S   12
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB         0x00000FC0
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S       6
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB         0x0000003F
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S       0
+
+#define AR_PHY_CCK_RXCTRL4  0xA21C
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT   0x01F80000
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
+
+#define AR_PHY_DAG_CTRLCCK  0xA228
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR     0x0001FC00
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10
+
+#define AR_PHY_FORCE_CLKEN_CCK              0xA22C
+#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX      0x00000040
+
+#define AR_PHY_POWER_TX_RATE3   0xA234
+#define AR_PHY_POWER_TX_RATE4   0xA238
+
+#define AR_PHY_SCRM_SEQ_XR       0xA23C
+#define AR_PHY_HEADER_DETECT_XR  0xA240
+#define AR_PHY_CHIRP_DETECTED_XR 0xA244
+#define AR_PHY_BLUETOOTH         0xA254
+
+#define AR_PHY_TPCRG1   0xA258
+#define AR_PHY_TPCRG1_NUM_PD_GAIN   0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+
+#define AR_PHY_TPCRG1_PD_GAIN_1    0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S  16
+#define AR_PHY_TPCRG1_PD_GAIN_2    0x000C0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S  18
+#define AR_PHY_TPCRG1_PD_GAIN_3    0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S  20
+
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE   0x00400000
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
+
+#define AR_PHY_TX_PWRCTRL4       0xa264
+#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID     0x00000001
+#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S   0
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT       0x000001FE
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S     1
+
+#define AR_PHY_TX_PWRCTRL6_0     0xa270
+#define AR_PHY_TX_PWRCTRL6_1     0xb270
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE     0x03000000
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S   24
+
+#define AR_PHY_TX_PWRCTRL7       0xa274
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19
+
+#define AR_PHY_TX_PWRCTRL9       0xa27C
+#define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00
+#define AR_PHY_TX_DESIRED_SCALE_CCK_S      10
+
+#define AR_PHY_TX_GAIN_TBL1      0xa300
+#define AR_PHY_TX_GAIN                     0x0007F000
+#define AR_PHY_TX_GAIN_S                   12
+
+#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
+#define AR_PHY_MASK2_M_31_45     0xa3a4
+#define AR_PHY_MASK2_M_16_30     0xa3a8
+#define AR_PHY_MASK2_M_00_15     0xa3ac
+#define AR_PHY_MASK2_P_15_01     0xa3b8
+#define AR_PHY_MASK2_P_30_16     0xa3bc
+#define AR_PHY_MASK2_P_45_31     0xa3c0
+#define AR_PHY_MASK2_P_61_45     0xa3c4
+#define AR_PHY_SPUR_REG          0x994c
+
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL       (0xFF << 18)
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S     18
+
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM      0x20000
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT     (0xFF << 9)
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S   9
+#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH     0x7F
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S   0
+
+#define AR_PHY_PILOT_MASK_01_30   0xa3b0
+#define AR_PHY_PILOT_MASK_31_60   0xa3b4
+
+#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
+#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
+
+#define AR_PHY_ANALOG_SWAP      0xa268
+#define AR_PHY_SWAP_ALT_CHAIN   0x00000040
+
+#define AR_PHY_TPCRG5   0xA26C
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP       0x0000000F
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S     0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1    0x000003F0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S  4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2    0x0000FC00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S  10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003F0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0FC00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22
+
+/* Carrier leak calibration control, do it after AGC calibration */
+#define AR_PHY_CL_CAL_CTL       0xA358
+#define AR_PHY_CL_CAL_ENABLE    0x00000002
+#define AR_PHY_PARALLEL_CAL_ENABLE    0x00000001
+
+#define AR_PHY_POWER_TX_RATE5   0xA38C
+#define AR_PHY_POWER_TX_RATE6   0xA390
+
+#define AR_PHY_CAL_CHAINMASK    0xA39C
+
+#define AR_PHY_POWER_TX_SUB     0xA3C8
+#define AR_PHY_POWER_TX_RATE7   0xA3CC
+#define AR_PHY_POWER_TX_RATE8   0xA3D0
+#define AR_PHY_POWER_TX_RATE9   0xA3D4
+
+#define AR_PHY_XPA_CFG  	0xA3D8
+#define AR_PHY_FORCE_XPA_CFG	0x000000001
+#define AR_PHY_FORCE_XPA_CFG_S	0
+
+#define AR_PHY_CH1_CCA          0xa864
+#define AR_PHY_CH1_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH1_MINCCA_PWR_S 19
+#define AR9280_PHY_CH1_MINCCA_PWR   0x1FF00000
+#define AR9280_PHY_CH1_MINCCA_PWR_S 20
+
+#define AR_PHY_CH2_CCA          0xb864
+#define AR_PHY_CH2_MINCCA_PWR   0x0FF80000
+#define AR_PHY_CH2_MINCCA_PWR_S 19
+
+#define AR_PHY_CH1_EXT_CCA          0xa9bc
+#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000
+#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
+
+#define AR_PHY_CH2_EXT_CCA          0xb9bc
+#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
+#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
+
+#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do {               \
+		int r;							\
+		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\
+			REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
+			DO_DELAY(regWr);				\
+		}							\
+	} while (0)
+
+#define ATH9K_IS_MIC_ENABLED(ah)					\
+	((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
+
+#define ANTSWAP_AB 0x0001
+#define REDUCE_CHAIN_0 0x00000050
+#define REDUCE_CHAIN_1 0x00000051
+
+#define RF_BANK_SETUP(_bank, _iniarray, _col) do {			\
+		int i;							\
+		for (i = 0; i < (_iniarray)->ia_rows; i++)		\
+			(_bank)[i] = INI_RA((_iniarray), i, _col);;	\
+	} while (0)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/rc.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/rc.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/rc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/rc.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1756 @@
+/*
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * Copyright (c) 2004-2009 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static const struct ath_rate_table ar5416_11na_ratetable = {
+	42,
+	{
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+			5400, 0x0b, 0x00, 12,
+			0, 2, 1, 0, 0, 0, 0, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+			7800,  0x0f, 0x00, 18,
+			0, 3, 1, 1, 1, 1, 1, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+			10000, 0x0a, 0x00, 24,
+			2, 4, 2, 2, 2, 2, 2, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+			13900, 0x0e, 0x00, 36,
+			2, 6,  2, 3, 3, 3, 3, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+			17300, 0x09, 0x00, 48,
+			4, 10, 3, 4, 4, 4, 4, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+			23000, 0x0d, 0x00, 72,
+			4, 14, 3, 5, 5, 5, 5, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+			27400, 0x08, 0x00, 96,
+			4, 20, 3, 6, 6, 6, 6, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+			29300, 0x0c, 0x00, 108,
+			4, 23, 3, 7, 7, 7, 7, 0 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
+			6400, 0x80, 0x00, 0,
+			0, 2, 3, 8, 24, 8, 24, 3216 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
+			12700, 0x81, 0x00, 1,
+			2, 4, 3, 9, 25, 9, 25, 6434 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
+			18800, 0x82, 0x00, 2,
+			2, 6, 3, 10, 26, 10, 26, 9650 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
+			25000, 0x83, 0x00, 3,
+			4, 10, 3, 11, 27, 11, 27, 12868 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
+			36700, 0x84, 0x00, 4,
+			4, 14, 3, 12, 28, 12, 28, 19304 },
+		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
+			48100, 0x85, 0x00, 5,
+			4, 20, 3, 13, 29, 13, 29, 25740 },
+		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
+			53500, 0x86, 0x00, 6,
+			4, 23, 3, 14, 30, 14, 30,  28956 },
+		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
+			59000, 0x87, 0x00, 7,
+			4, 25, 3, 15, 31, 15, 32, 32180 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
+			12700, 0x88, 0x00,
+			8, 0, 2, 3, 16, 33, 16, 33, 6430 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
+			24800, 0x89, 0x00, 9,
+			2, 4, 3, 17, 34, 17, 34, 12860 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
+			36600, 0x8a, 0x00, 10,
+			2, 6, 3, 18, 35, 18, 35, 19300 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
+			48100, 0x8b, 0x00, 11,
+			4, 10, 3, 19, 36, 19, 36, 25736 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
+			69500, 0x8c, 0x00, 12,
+			4, 14, 3, 20, 37, 20, 37, 38600 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
+			89500, 0x8d, 0x00, 13,
+			4, 20, 3, 21, 38, 21, 38, 51472 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
+			98900, 0x8e, 0x00, 14,
+			4, 23, 3, 22, 39, 22, 39, 57890 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
+			108300, 0x8f, 0x00, 15,
+			4, 25, 3, 23, 40, 23, 41, 64320 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
+			13200, 0x80, 0x00, 0,
+			0, 2, 3, 8, 24, 24, 24, 6684 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
+			25900, 0x81, 0x00, 1,
+			2, 4, 3, 9, 25, 25, 25, 13368 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
+			38600, 0x82, 0x00, 2,
+			2, 6, 3, 10, 26, 26, 26, 20052 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
+			49800, 0x83, 0x00, 3,
+			4, 10, 3, 11, 27, 27, 27, 26738 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
+			72200, 0x84, 0x00, 4,
+			4, 14, 3, 12, 28, 28, 28, 40104 },
+		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
+			92900, 0x85, 0x00, 5,
+			4, 20, 3, 13, 29, 29, 29, 53476 },
+		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
+			102700, 0x86, 0x00, 6,
+			4, 23, 3, 14, 30, 30, 30, 60156 },
+		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
+			112000, 0x87, 0x00, 7,
+			4, 25, 3, 15, 31, 32, 32, 66840 },
+		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
+			122000, 0x87, 0x00, 7,
+			4, 25, 3, 15, 31, 32, 32, 74200 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
+			25800, 0x88, 0x00, 8,
+			0, 2, 3, 16, 33, 33, 33, 13360 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
+			49800, 0x89, 0x00, 9,
+			2, 4, 3, 17, 34, 34, 34, 26720 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
+			71900, 0x8a, 0x00, 10,
+			2, 6, 3, 18, 35, 35, 35, 40080 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
+			92500, 0x8b, 0x00, 11,
+			4, 10, 3, 19, 36, 36, 36, 53440 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
+			130300, 0x8c, 0x00, 12,
+			4, 14, 3, 20, 37, 37, 37, 80160 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
+			162800, 0x8d, 0x00, 13,
+			4, 20, 3, 21, 38, 38, 38, 106880 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
+			178200, 0x8e, 0x00, 14,
+			4, 23, 3, 22, 39, 39, 39, 120240 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
+			192100, 0x8f, 0x00, 15,
+			4, 25, 3, 23, 40, 41, 41, 133600 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
+			207000, 0x8f, 0x00, 15,
+			4, 25, 3, 23, 40, 41, 41, 148400 },
+	},
+	50,  /* probe interval */
+	50,  /* rssi reduce interval */
+	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
+};
+
+/* 4ms frame limit not used for NG mode.  The values filled
+ * for HT are the 64K max aggregate limit */
+
+static const struct ath_rate_table ar5416_11ng_ratetable = {
+	46,
+	{
+		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+			900, 0x1b, 0x00, 2,
+			0, 0, 1, 0, 0, 0, 0, 0 },
+		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+			1900, 0x1a, 0x04, 4,
+			1, 1, 1, 1, 1, 1, 1, 0 },
+		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+			4900, 0x19, 0x04, 11,
+			2, 2, 2, 2, 2, 2, 2, 0 },
+		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+			8100, 0x18, 0x04, 22,
+			3, 3, 2, 3, 3, 3, 3, 0 },
+		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+			5400, 0x0b, 0x00, 12,
+			4, 2, 1, 4, 4, 4, 4, 0 },
+		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+			7800, 0x0f, 0x00, 18,
+			4, 3, 1, 5, 5, 5, 5, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+			10100, 0x0a, 0x00, 24,
+			6, 4, 1, 6, 6, 6, 6, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+			14100,  0x0e, 0x00, 36,
+			6, 6, 2, 7, 7, 7, 7, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+			17700, 0x09, 0x00, 48,
+			8, 10, 3, 8, 8, 8, 8, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+			23700, 0x0d, 0x00, 72,
+			8, 14, 3, 9, 9, 9, 9, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+			27400, 0x08, 0x00, 96,
+			8, 20, 3, 10, 10, 10, 10, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+			30900, 0x0c, 0x00, 108,
+			8, 23, 3, 11, 11, 11, 11, 0 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
+			6400, 0x80, 0x00, 0,
+			4, 2, 3, 12, 28, 12, 28, 3216 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
+			12700, 0x81, 0x00, 1,
+			6, 4, 3, 13, 29, 13, 29, 6434 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
+			18800, 0x82, 0x00, 2,
+			6, 6, 3, 14, 30, 14, 30, 9650 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
+			25000, 0x83, 0x00, 3,
+			8, 10, 3, 15, 31, 15, 31, 12868 },
+		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
+			36700, 0x84, 0x00, 4,
+			8, 14, 3, 16, 32, 16, 32, 19304 },
+		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
+			48100, 0x85, 0x00, 5,
+			8, 20, 3, 17, 33, 17, 33, 25740 },
+		{ INVALID,  VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
+			53500, 0x86, 0x00, 6,
+			8, 23, 3, 18, 34, 18, 34, 28956 },
+		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
+			59000, 0x87, 0x00, 7,
+			8, 25, 3, 19, 35, 19, 36, 32180 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
+			12700, 0x88, 0x00, 8,
+			4, 2, 3, 20, 37, 20, 37, 6430 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
+			24800, 0x89, 0x00, 9,
+			6, 4, 3, 21, 38, 21, 38, 12860 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
+			36600, 0x8a, 0x00, 10,
+			6, 6, 3, 22, 39, 22, 39, 19300 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
+			48100, 0x8b, 0x00, 11,
+			8, 10, 3, 23, 40, 23, 40, 25736 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
+			69500, 0x8c, 0x00, 12,
+			8, 14, 3, 24, 41, 24, 41, 38600 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
+			89500, 0x8d, 0x00, 13,
+			8, 20, 3, 25, 42, 25, 42, 51472 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
+			98900, 0x8e, 0x00, 14,
+			8, 23, 3, 26, 43, 26, 44, 57890 },
+		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
+			108300, 0x8f, 0x00, 15,
+			8, 25, 3, 27, 44, 27, 45, 64320 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
+			13200, 0x80, 0x00, 0,
+			8, 2, 3, 12, 28, 28, 28, 6684 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
+			25900, 0x81, 0x00, 1,
+			8, 4, 3, 13, 29, 29, 29, 13368 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
+			38600, 0x82, 0x00, 2,
+			8, 6, 3, 14, 30, 30, 30, 20052 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
+			49800, 0x83, 0x00, 3,
+			8, 10, 3, 15, 31, 31, 31, 26738 },
+		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
+			72200, 0x84, 0x00, 4,
+			8, 14, 3, 16, 32, 32, 32, 40104 },
+		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
+			92900, 0x85, 0x00, 5,
+			8, 20, 3, 17, 33, 33, 33, 53476 },
+		{ INVALID,  VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
+			102700, 0x86, 0x00, 6,
+			8, 23, 3, 18, 34, 34, 34, 60156 },
+		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
+			112000, 0x87, 0x00, 7,
+			8, 23, 3, 19, 35, 36, 36, 66840 },
+		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
+			122000, 0x87, 0x00, 7,
+			8, 25, 3, 19, 35, 36, 36, 74200 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
+			25800, 0x88, 0x00, 8,
+			8, 2, 3, 20, 37, 37, 37, 13360 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
+			49800, 0x89, 0x00, 9,
+			8, 4, 3, 21, 38, 38, 38, 26720 },
+		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
+			71900, 0x8a, 0x00, 10,
+			8, 6, 3, 22, 39, 39, 39, 40080 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
+			92500, 0x8b, 0x00, 11,
+			8, 10, 3, 23, 40, 40, 40, 53440 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
+			130300, 0x8c, 0x00, 12,
+			8, 14, 3, 24, 41, 41, 41, 80160 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
+			162800, 0x8d, 0x00, 13,
+			8, 20, 3, 25, 42, 42, 42, 106880 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
+			178200, 0x8e, 0x00, 14,
+			8, 23, 3, 26, 43, 43, 43, 120240 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
+			192100, 0x8f, 0x00, 15,
+			8, 23, 3, 27, 44, 45, 45, 133600 },
+		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
+			207000, 0x8f, 0x00, 15,
+			8, 25, 3, 27, 44, 45, 45, 148400 },
+		},
+	50,  /* probe interval */
+	50,  /* rssi reduce interval */
+	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
+};
+
+static const struct ath_rate_table ar5416_11a_ratetable = {
+	8,
+	{
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+			5400, 0x0b, 0x00, (0x80|12),
+			0, 2, 1, 0, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+			7800, 0x0f, 0x00, 18,
+			0, 3, 1, 1, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+			10000, 0x0a, 0x00, (0x80|24),
+			2, 4, 2, 2, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+			13900, 0x0e, 0x00, 36,
+			2, 6, 2, 3, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+			17300, 0x09, 0x00, (0x80|48),
+			4, 10, 3, 4, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+			23000, 0x0d, 0x00, 72,
+			4, 14, 3, 5, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+			27400, 0x08, 0x00, 96,
+			4, 19, 3, 6, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+			29300, 0x0c, 0x00, 108,
+			4, 23, 3, 7, 0 },
+	},
+	50,  /* probe interval */
+	50,  /* rssi reduce interval */
+	0,   /* Phy rates allowed initially */
+};
+
+static const struct ath_rate_table ar5416_11g_ratetable = {
+	12,
+	{
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+			900, 0x1b, 0x00, 2,
+			0, 0, 1, 0, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+			1900, 0x1a, 0x04, 4,
+			1, 1, 1, 1, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+			4900, 0x19, 0x04, 11,
+			2, 2, 2, 2, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+			8100, 0x18, 0x04, 22,
+			3, 3, 2, 3, 0 },
+		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+			5400, 0x0b, 0x00, 12,
+			4, 2, 1, 4, 0 },
+		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+			7800, 0x0f, 0x00, 18,
+			4, 3, 1, 5, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+			10000, 0x0a, 0x00, 24,
+			6, 4, 1, 6, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+			13900, 0x0e, 0x00, 36,
+			6, 6, 2, 7, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+			17300, 0x09, 0x00, 48,
+			8, 10, 3, 8, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+			23000, 0x0d, 0x00, 72,
+			8, 14, 3, 9, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+			27400, 0x08, 0x00, 96,
+			8, 19, 3, 10, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+			29300, 0x0c, 0x00, 108,
+			8, 23, 3, 11, 0 },
+	},
+	50,  /* probe interval */
+	50,  /* rssi reduce interval */
+	0,   /* Phy rates allowed initially */
+};
+
+static const struct ath_rate_table ar5416_11b_ratetable = {
+	4,
+	{
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+			900, 0x1b,  0x00, (0x80|2),
+			0, 0, 1, 0, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+			1800, 0x1a, 0x04, (0x80|4),
+			1, 1, 1, 1, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+			4300, 0x19, 0x04, (0x80|11),
+			1, 2, 2, 2, 0 },
+		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+			7100, 0x18, 0x04, (0x80|22),
+			1, 4, 100, 3, 0 },
+	},
+	100, /* probe interval */
+	100, /* rssi reduce interval */
+	0,   /* Phy rates allowed initially */
+};
+
+static inline int8_t median(int8_t a, int8_t b, int8_t c)
+{
+	if (a >= b) {
+		if (b >= c)
+			return b;
+		else if (a > c)
+			return c;
+		else
+			return a;
+	} else {
+		if (a >= c)
+			return a;
+		else if (b >= c)
+			return c;
+		else
+			return b;
+	}
+}
+
+static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
+				   struct ath_rate_priv *ath_rc_priv)
+{
+	u8 i, j, idx, idx_next;
+
+	for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
+		for (j = 0; j <= i-1; j++) {
+			idx = ath_rc_priv->valid_rate_index[j];
+			idx_next = ath_rc_priv->valid_rate_index[j+1];
+
+			if (rate_table->info[idx].ratekbps >
+				rate_table->info[idx_next].ratekbps) {
+				ath_rc_priv->valid_rate_index[j] = idx_next;
+				ath_rc_priv->valid_rate_index[j+1] = idx;
+			}
+		}
+	}
+}
+
+static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
+{
+	u8 i;
+
+	for (i = 0; i < ath_rc_priv->rate_table_size; i++)
+		ath_rc_priv->valid_rate_index[i] = 0;
+}
+
+static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
+					   u8 index, int valid_tx_rate)
+{
+	ASSERT(index <= ath_rc_priv->rate_table_size);
+	ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
+}
+
+static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv,
+					u8 index)
+{
+	ASSERT(index <= ath_rc_priv->rate_table_size);
+	return ath_rc_priv->valid_rate_index[index];
+}
+
+static inline
+int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
+				struct ath_rate_priv *ath_rc_priv,
+				u8 cur_valid_txrate,
+				u8 *next_idx)
+{
+	u8 i;
+
+	for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
+		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
+			*next_idx = ath_rc_priv->valid_rate_index[i+1];
+			return 1;
+		}
+	}
+
+	/* No more valid rates */
+	*next_idx = 0;
+
+	return 0;
+}
+
+/* Return true only for single stream */
+
+static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
+{
+	if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
+		return 0;
+	if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
+		return 0;
+	if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
+		return 0;
+	if (!ignore_cw && WLAN_RC_PHY_HT(phy))
+		if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
+			return 0;
+		if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
+			return 0;
+	return 1;
+}
+
+static inline int
+ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table,
+				 struct ath_rate_priv *ath_rc_priv,
+				 u8 cur_valid_txrate, u8 *next_idx)
+{
+	int8_t i;
+
+	for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
+		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
+			*next_idx = ath_rc_priv->valid_rate_index[i-1];
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
+				 const struct ath_rate_table *rate_table,
+				 u32 capflag)
+{
+	u8 i, hi = 0;
+	u32 valid;
+
+	for (i = 0; i < rate_table->rate_cnt; i++) {
+		valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
+			 rate_table->info[i].valid_single_stream :
+			 rate_table->info[i].valid);
+		if (valid == 1) {
+			u32 phy = rate_table->info[i].phy;
+			u8 valid_rate_count = 0;
+
+			if (!ath_rc_valid_phyrate(phy, capflag, 0))
+				continue;
+
+			valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
+
+			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
+			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+			ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
+			hi = A_MAX(hi, i);
+		}
+	}
+
+	return hi;
+}
+
+static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
+				const struct ath_rate_table *rate_table,
+				struct ath_rateset *rateset,
+				u32 capflag)
+{
+	u8 i, j, hi = 0;
+
+	/* Use intersection of working rates and valid rates */
+	for (i = 0; i < rateset->rs_nrates; i++) {
+		for (j = 0; j < rate_table->rate_cnt; j++) {
+			u32 phy = rate_table->info[j].phy;
+			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
+				     rate_table->info[j].valid_single_stream :
+				     rate_table->info[j].valid);
+			u8 rate = rateset->rs_rates[i];
+			u8 dot11rate = rate_table->info[j].dot11rate;
+
+			/* We allow a rate only if its valid and the
+			 * capflag matches one of the validity
+			 * (VALID/VALID_20/VALID_40) flags */
+
+			if (((rate & 0x7F) == (dot11rate & 0x7F)) &&
+			    ((valid & WLAN_RC_CAP_MODE(capflag)) ==
+			     WLAN_RC_CAP_MODE(capflag)) &&
+			    !WLAN_RC_PHY_HT(phy)) {
+				u8 valid_rate_count = 0;
+
+				if (!ath_rc_valid_phyrate(phy, capflag, 0))
+					continue;
+
+				valid_rate_count =
+					ath_rc_priv->valid_phy_ratecnt[phy];
+
+				ath_rc_priv->valid_phy_rateidx[phy]
+					[valid_rate_count] = j;
+				ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+				ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
+				hi = A_MAX(hi, j);
+			}
+		}
+	}
+
+	return hi;
+}
+
+static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
+				  const struct ath_rate_table *rate_table,
+				  u8 *mcs_set, u32 capflag)
+{
+	struct ath_rateset *rateset = (struct ath_rateset *)mcs_set;
+
+	u8 i, j, hi = 0;
+
+	/* Use intersection of working rates and valid rates */
+	for (i = 0; i < rateset->rs_nrates; i++) {
+		for (j = 0; j < rate_table->rate_cnt; j++) {
+			u32 phy = rate_table->info[j].phy;
+			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
+				     rate_table->info[j].valid_single_stream :
+				     rate_table->info[j].valid);
+			u8 rate = rateset->rs_rates[i];
+			u8 dot11rate = rate_table->info[j].dot11rate;
+
+			if (((rate & 0x7F) != (dot11rate & 0x7F)) ||
+			    !WLAN_RC_PHY_HT(phy) ||
+			    !WLAN_RC_PHY_HT_VALID(valid, capflag))
+				continue;
+
+			if (!ath_rc_valid_phyrate(phy, capflag, 0))
+				continue;
+
+			ath_rc_priv->valid_phy_rateidx[phy]
+				[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
+			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+			ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
+			hi = A_MAX(hi, j);
+		}
+	}
+
+	return hi;
+}
+
+static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
+			     struct ath_rate_priv *ath_rc_priv,
+			     const struct ath_rate_table *rate_table,
+			     int *is_probing)
+{
+	u32 dt, best_thruput, this_thruput, now_msec;
+	u8 rate, next_rate, best_rate, maxindex, minindex;
+	int8_t  rssi_last, rssi_reduce = 0, index = 0;
+
+	*is_probing = 0;
+
+	rssi_last = median(ath_rc_priv->rssi_last,
+			   ath_rc_priv->rssi_last_prev,
+			   ath_rc_priv->rssi_last_prev2);
+
+	/*
+	 * Age (reduce) last ack rssi based on how old it is.
+	 * The bizarre numbers are so the delta is 160msec,
+	 * meaning we divide by 16.
+	 *   0msec   <= dt <= 25msec:   don't derate
+	 *   25msec  <= dt <= 185msec:  derate linearly from 0 to 10dB
+	 *   185msec <= dt:             derate by 10dB
+	 */
+
+	now_msec = jiffies_to_msecs(jiffies);
+	dt = now_msec - ath_rc_priv->rssi_time;
+
+	if (dt >= 185)
+		rssi_reduce = 10;
+	else if (dt >= 25)
+		rssi_reduce = (u8)((dt - 25) >> 4);
+
+	/* Now reduce rssi_last by rssi_reduce */
+	if (rssi_last < rssi_reduce)
+		rssi_last = 0;
+	else
+		rssi_last -= rssi_reduce;
+
+	/*
+	 * Now look up the rate in the rssi table and return it.
+	 * If no rates match then we return 0 (lowest rate)
+	 */
+
+	best_thruput = 0;
+	maxindex = ath_rc_priv->max_valid_rate-1;
+
+	minindex = 0;
+	best_rate = minindex;
+
+	/*
+	 * Try the higher rate first. It will reduce memory moving time
+	 * if we have very good channel characteristics.
+	 */
+	for (index = maxindex; index >= minindex ; index--) {
+		u8 per_thres;
+
+		rate = ath_rc_priv->valid_rate_index[index];
+		if (rate > ath_rc_priv->rate_max_phy)
+			continue;
+
+		/*
+		 * For TCP the average collision rate is around 11%,
+		 * so we ignore PERs less than this.  This is to
+		 * prevent the rate we are currently using (whose
+		 * PER might be in the 10-15 range because of TCP
+		 * collisions) looking worse than the next lower
+		 * rate whose PER has decayed close to 0.  If we
+		 * used to next lower rate, its PER would grow to
+		 * 10-15 and we would be worse off then staying
+		 * at the current rate.
+		 */
+		per_thres = ath_rc_priv->state[rate].per;
+		if (per_thres < 12)
+			per_thres = 12;
+
+		this_thruput = rate_table->info[rate].user_ratekbps *
+			(100 - per_thres);
+
+		if (best_thruput <= this_thruput) {
+			best_thruput = this_thruput;
+			best_rate    = rate;
+		}
+	}
+
+	rate = best_rate;
+	ath_rc_priv->rssi_last_lookup = rssi_last;
+
+	/*
+	 * Must check the actual rate (ratekbps) to account for
+	 * non-monoticity of 11g's rate table
+	 */
+
+	if (rate >= ath_rc_priv->rate_max_phy) {
+		rate = ath_rc_priv->rate_max_phy;
+
+		/* Probe the next allowed phy state */
+		if (ath_rc_get_nextvalid_txrate(rate_table,
+					ath_rc_priv, rate, &next_rate) &&
+		    (now_msec - ath_rc_priv->probe_time >
+		     rate_table->probe_interval) &&
+		    (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
+			rate = next_rate;
+			ath_rc_priv->probe_rate = rate;
+			ath_rc_priv->probe_time = now_msec;
+			ath_rc_priv->hw_maxretry_pktcnt = 0;
+			*is_probing = 1;
+		}
+	}
+
+	if (rate > (ath_rc_priv->rate_table_size - 1))
+		rate = ath_rc_priv->rate_table_size - 1;
+
+	ASSERT((rate_table->info[rate].valid &&
+		(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) ||
+	       (rate_table->info[rate].valid_single_stream &&
+		!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)));
+
+	return rate;
+}
+
+static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
+				   struct ieee80211_tx_rate *rate,
+				   struct ieee80211_tx_rate_control *txrc,
+				   u8 tries, u8 rix, int rtsctsenable)
+{
+	rate->count = tries;
+	rate->idx = rix;
+
+	if (txrc->short_preamble)
+		rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
+	if (txrc->rts || rtsctsenable)
+		rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+	if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
+		rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+	if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
+		rate->flags |= IEEE80211_TX_RC_SHORT_GI;
+	if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
+		rate->flags |= IEEE80211_TX_RC_MCS;
+}
+
+static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
+				   const struct ath_rate_table *rate_table,
+				   struct ieee80211_tx_info *tx_info)
+{
+	struct ieee80211_tx_rate *rates = tx_info->control.rates;
+	int i = 0, rix = 0, cix, enable_g_protection = 0;
+
+	/* get the cix for the lowest valid rix */
+	for (i = 3; i >= 0; i--) {
+		if (rates[i].count && (rates[i].idx >= 0)) {
+			rix = rates[i].idx;
+			break;
+		}
+	}
+	cix = rate_table->info[rix].ctrl_rate;
+
+	/* All protection frames are transmited at 2Mb/s for 802.11g,
+	 * otherwise we transmit them at 1Mb/s */
+	if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ &&
+	    !conf_is_ht(&sc->hw->conf))
+		enable_g_protection = 1;
+
+	/*
+	 * If 802.11g protection is enabled, determine whether to use RTS/CTS or
+	 * just CTS.  Note that this is only done for OFDM/HT unicast frames.
+	 */
+	if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) &&
+	    !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+	    (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
+	     WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
+		rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
+		cix = rate_table->info[enable_g_protection].ctrl_rate;
+	}
+
+	tx_info->control.rts_cts_rate_idx = cix;
+}
+
+static u8 ath_rc_rate_getidx(struct ath_softc *sc,
+			     struct ath_rate_priv *ath_rc_priv,
+			     const struct ath_rate_table *rate_table,
+			     u8 rix, u16 stepdown,
+			     u16 min_rate)
+{
+	u32 j;
+	u8 nextindex = 0;
+
+	if (min_rate) {
+		for (j = RATE_TABLE_SIZE; j > 0; j--) {
+			if (ath_rc_get_nextlowervalid_txrate(rate_table,
+						ath_rc_priv, rix, &nextindex))
+				rix = nextindex;
+			else
+				break;
+		}
+	} else {
+		for (j = stepdown; j > 0; j--) {
+			if (ath_rc_get_nextlowervalid_txrate(rate_table,
+						ath_rc_priv, rix, &nextindex))
+				rix = nextindex;
+			else
+				break;
+		}
+	}
+	return rix;
+}
+
+static void ath_rc_ratefind(struct ath_softc *sc,
+			    struct ath_rate_priv *ath_rc_priv,
+			    struct ieee80211_tx_rate_control *txrc)
+{
+	const struct ath_rate_table *rate_table;
+	struct sk_buff *skb = txrc->skb;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_tx_rate *rates = tx_info->control.rates;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	__le16 fc = hdr->frame_control;
+	u8 try_per_rate = 0, i = 0, rix, nrix;
+	int is_probe = 0;
+
+	rate_table = sc->cur_rate_table;
+	rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe);
+	nrix = rix;
+
+	if (is_probe) {
+		/* set one try for probe rates. For the
+		 * probes don't enable rts */
+		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
+				       1, nrix, 0);
+
+		try_per_rate = (ATH_11N_TXMAXTRY/4);
+		/* Get the next tried/allowed rate. No RTS for the next series
+		 * after the probe rate
+		 */
+		nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
+					  rate_table, nrix, 1, 0);
+		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
+				       try_per_rate, nrix, 0);
+
+		tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+	} else {
+		try_per_rate = (ATH_11N_TXMAXTRY/4);
+		/* Set the choosen rate. No RTS for first series entry. */
+		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
+				       try_per_rate, nrix, 0);
+	}
+
+	/* Fill in the other rates for multirate retry */
+	for ( ; i < 4; i++) {
+		u8 try_num;
+		u8 min_rate;
+
+		try_num = ((i + 1) == 4) ?
+			ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ;
+		min_rate = (((i + 1) == 4) && 0);
+
+		nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
+					  rate_table, nrix, 1, min_rate);
+		/* All other rates in the series have RTS enabled */
+		ath_rc_rate_set_series(rate_table, &rates[i], txrc,
+				       try_num, nrix, 1);
+	}
+
+	/*
+	 * NB:Change rate series to enable aggregation when operating
+	 * at lower MCS rates. When first rate in series is MCS2
+	 * in HT40 @ 2.4GHz, series should look like:
+	 *
+	 * {MCS2, MCS1, MCS0, MCS0}.
+	 *
+	 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
+	 * look like:
+	 *
+	 * {MCS3, MCS2, MCS1, MCS1}
+	 *
+	 * So, set fourth rate in series to be same as third one for
+	 * above conditions.
+	 */
+	if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
+	    (conf_is_ht(&sc->hw->conf))) {
+		u8 dot11rate = rate_table->info[rix].dot11rate;
+		u8 phy = rate_table->info[rix].phy;
+		if (i == 4 &&
+		    ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
+		     (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
+			rates[3].idx = rates[2].idx;
+			rates[3].flags = rates[2].flags;
+		}
+	}
+
+	/*
+	 * Force hardware to use computed duration for next
+	 * fragment by disabling multi-rate retry, which
+	 * updates duration based on the multi-rate duration table.
+	 *
+	 * FIXME: Fix duration
+	 */
+	if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+	    (ieee80211_has_morefrags(fc) ||
+	     (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) {
+		rates[1].count = rates[2].count = rates[3].count = 0;
+		rates[1].idx = rates[2].idx = rates[3].idx = 0;
+		rates[0].count = ATH_TXMAXTRY;
+	}
+
+	/* Setup RTS/CTS */
+	ath_rc_rate_set_rtscts(sc, rate_table, tx_info);
+}
+
+static bool ath_rc_update_per(struct ath_softc *sc,
+			      const struct ath_rate_table *rate_table,
+			      struct ath_rate_priv *ath_rc_priv,
+			      struct ath_tx_info_priv *tx_info_priv,
+			      int tx_rate, int xretries, int retries,
+			      u32 now_msec)
+{
+	bool state_change = false;
+	int count;
+	u8 last_per;
+	static u32 nretry_to_per_lookup[10] = {
+		100 * 0 / 1,
+		100 * 1 / 4,
+		100 * 1 / 2,
+		100 * 3 / 4,
+		100 * 4 / 5,
+		100 * 5 / 6,
+		100 * 6 / 7,
+		100 * 7 / 8,
+		100 * 8 / 9,
+		100 * 9 / 10
+	};
+
+	last_per = ath_rc_priv->state[tx_rate].per;
+
+	if (xretries) {
+		if (xretries == 1) {
+			ath_rc_priv->state[tx_rate].per += 30;
+			if (ath_rc_priv->state[tx_rate].per > 100)
+				ath_rc_priv->state[tx_rate].per = 100;
+		} else {
+			/* xretries == 2 */
+			count = ARRAY_SIZE(nretry_to_per_lookup);
+			if (retries >= count)
+				retries = count - 1;
+
+			/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
+			ath_rc_priv->state[tx_rate].per =
+				(u8)(last_per - (last_per >> 3) + (100 >> 3));
+		}
+
+		/* xretries == 1 or 2 */
+
+		if (ath_rc_priv->probe_rate == tx_rate)
+			ath_rc_priv->probe_rate = 0;
+
+	} else { /* xretries == 0 */
+		count = ARRAY_SIZE(nretry_to_per_lookup);
+		if (retries >= count)
+			retries = count - 1;
+
+		if (tx_info_priv->n_bad_frames) {
+			/* new_PER = 7/8*old_PER + 1/8*(currentPER)
+			 * Assuming that n_frames is not 0.  The current PER
+			 * from the retries is 100 * retries / (retries+1),
+			 * since the first retries attempts failed, and the
+			 * next one worked.  For the one that worked,
+			 * n_bad_frames subframes out of n_frames wored,
+			 * so the PER for that part is
+			 * 100 * n_bad_frames / n_frames, and it contributes
+			 * 100 * n_bad_frames / (n_frames * (retries+1)) to
+			 * the above PER.  The expression below is a
+			 * simplified version of the sum of these two terms.
+			 */
+			if (tx_info_priv->n_frames > 0) {
+				int n_frames, n_bad_frames;
+				u8 cur_per, new_per;
+
+				n_bad_frames = retries * tx_info_priv->n_frames +
+					tx_info_priv->n_bad_frames;
+				n_frames = tx_info_priv->n_frames * (retries + 1);
+				cur_per = (100 * n_bad_frames / n_frames) >> 3;
+				new_per = (u8)(last_per - (last_per >> 3) + cur_per);
+				ath_rc_priv->state[tx_rate].per = new_per;
+			}
+		} else {
+			ath_rc_priv->state[tx_rate].per =
+				(u8)(last_per - (last_per >> 3) +
+				     (nretry_to_per_lookup[retries] >> 3));
+		}
+
+		ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
+		ath_rc_priv->rssi_last_prev  = ath_rc_priv->rssi_last;
+		ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi;
+		ath_rc_priv->rssi_time = now_msec;
+
+		/*
+		 * If we got at most one retry then increase the max rate if
+		 * this was a probe.  Otherwise, ignore the probe.
+		 */
+		if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
+			if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
+				tx_info_priv->n_frames) {
+				/*
+				 * Since we probed with just a single attempt,
+				 * any retries means the probe failed.  Also,
+				 * if the attempt worked, but more than half
+				 * the subframes were bad then also consider
+				 * the probe a failure.
+				 */
+				ath_rc_priv->probe_rate = 0;
+			} else {
+				u8 probe_rate = 0;
+
+				ath_rc_priv->rate_max_phy =
+					ath_rc_priv->probe_rate;
+				probe_rate = ath_rc_priv->probe_rate;
+
+				if (ath_rc_priv->state[probe_rate].per > 30)
+					ath_rc_priv->state[probe_rate].per = 20;
+
+				ath_rc_priv->probe_rate = 0;
+
+				/*
+				 * Since this probe succeeded, we allow the next
+				 * probe twice as soon.  This allows the maxRate
+				 * to move up faster if the probes are
+				 * succesful.
+				 */
+				ath_rc_priv->probe_time =
+					now_msec - rate_table->probe_interval / 2;
+			}
+		}
+
+		if (retries > 0) {
+			/*
+			 * Don't update anything.  We don't know if
+			 * this was because of collisions or poor signal.
+			 *
+			 * Later: if rssi_ack is close to
+			 * ath_rc_priv->state[txRate].rssi_thres and we see lots
+			 * of retries, then we could increase
+			 * ath_rc_priv->state[txRate].rssi_thres.
+			 */
+			ath_rc_priv->hw_maxretry_pktcnt = 0;
+		} else {
+			int32_t rssi_ackAvg;
+			int8_t rssi_thres;
+			int8_t rssi_ack_vmin;
+
+			/*
+			 * It worked with no retries. First ignore bogus (small)
+			 * rssi_ack values.
+			 */
+			if (tx_rate == ath_rc_priv->rate_max_phy &&
+			    ath_rc_priv->hw_maxretry_pktcnt < 255) {
+				ath_rc_priv->hw_maxretry_pktcnt++;
+			}
+
+			if (tx_info_priv->tx.ts_rssi <
+			    rate_table->info[tx_rate].rssi_ack_validmin)
+				goto exit;
+
+			/* Average the rssi */
+			if (tx_rate != ath_rc_priv->rssi_sum_rate) {
+				ath_rc_priv->rssi_sum_rate = tx_rate;
+				ath_rc_priv->rssi_sum =
+					ath_rc_priv->rssi_sum_cnt = 0;
+			}
+
+			ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
+			ath_rc_priv->rssi_sum_cnt++;
+
+			if (ath_rc_priv->rssi_sum_cnt < 4)
+				goto exit;
+
+			rssi_ackAvg =
+				(ath_rc_priv->rssi_sum + 2) / 4;
+			rssi_thres =
+				ath_rc_priv->state[tx_rate].rssi_thres;
+			rssi_ack_vmin =
+				rate_table->info[tx_rate].rssi_ack_validmin;
+
+			ath_rc_priv->rssi_sum =
+				ath_rc_priv->rssi_sum_cnt = 0;
+
+			/* Now reduce the current rssi threshold */
+			if ((rssi_ackAvg < rssi_thres + 2) &&
+			    (rssi_thres > rssi_ack_vmin)) {
+				ath_rc_priv->state[tx_rate].rssi_thres--;
+			}
+
+			state_change = true;
+		}
+	}
+exit:
+	return state_change;
+}
+
+/* Update PER, RSSI and whatever else that the code thinks it is doing.
+   If you can make sense of all this, you really need to go out more. */
+
+static void ath_rc_update_ht(struct ath_softc *sc,
+			     struct ath_rate_priv *ath_rc_priv,
+			     struct ath_tx_info_priv *tx_info_priv,
+			     int tx_rate, int xretries, int retries)
+{
+#define CHK_RSSI(rate)					\
+	((ath_rc_priv->state[(rate)].rssi_thres +	\
+	  rate_table->info[(rate)].rssi_ack_deltamin) > \
+	 ath_rc_priv->state[(rate)+1].rssi_thres)
+
+	u32 now_msec = jiffies_to_msecs(jiffies);
+	int rate;
+	u8 last_per;
+	bool state_change = false;
+	const struct ath_rate_table *rate_table = sc->cur_rate_table;
+	int size = ath_rc_priv->rate_table_size;
+
+	if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
+		return;
+
+	/* To compensate for some imbalance between ctrl and ext. channel */
+
+	if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
+		tx_info_priv->tx.ts_rssi =
+			tx_info_priv->tx.ts_rssi < 3 ? 0 :
+			tx_info_priv->tx.ts_rssi - 3;
+
+	last_per = ath_rc_priv->state[tx_rate].per;
+
+	/* Update PER first */
+	state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
+					 tx_info_priv, tx_rate, xretries,
+					 retries, now_msec);
+
+	/*
+	 * If this rate looks bad (high PER) then stop using it for
+	 * a while (except if we are probing).
+	 */
+	if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
+	    rate_table->info[tx_rate].ratekbps <=
+	    rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
+		ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
+				 (u8)tx_rate, &ath_rc_priv->rate_max_phy);
+
+		/* Don't probe for a little while. */
+		ath_rc_priv->probe_time = now_msec;
+	}
+
+	if (state_change) {
+		/*
+		 * Make sure the rates above this have higher rssi thresholds.
+		 * (Note:  Monotonicity is kept within the OFDM rates and
+		 *         within the CCK rates. However, no adjustment is
+		 *         made to keep the rssi thresholds monotonically
+		 *         increasing between the CCK and OFDM rates.)
+		 */
+		for (rate = tx_rate; rate < size - 1; rate++) {
+			if (rate_table->info[rate+1].phy !=
+			    rate_table->info[tx_rate].phy)
+				break;
+
+			if (CHK_RSSI(rate)) {
+				ath_rc_priv->state[rate+1].rssi_thres =
+					ath_rc_priv->state[rate].rssi_thres +
+					rate_table->info[rate].rssi_ack_deltamin;
+			}
+		}
+
+		/* Make sure the rates below this have lower rssi thresholds. */
+		for (rate = tx_rate - 1; rate >= 0; rate--) {
+			if (rate_table->info[rate].phy !=
+			    rate_table->info[tx_rate].phy)
+				break;
+
+			if (CHK_RSSI(rate)) {
+				if (ath_rc_priv->state[rate+1].rssi_thres <
+				    rate_table->info[rate].rssi_ack_deltamin)
+					ath_rc_priv->state[rate].rssi_thres = 0;
+				else {
+					ath_rc_priv->state[rate].rssi_thres =
+					ath_rc_priv->state[rate+1].rssi_thres -
+					rate_table->info[rate].rssi_ack_deltamin;
+				}
+
+				if (ath_rc_priv->state[rate].rssi_thres <
+				    rate_table->info[rate].rssi_ack_validmin) {
+					ath_rc_priv->state[rate].rssi_thres =
+					rate_table->info[rate].rssi_ack_validmin;
+				}
+			}
+		}
+	}
+
+	/* Make sure the rates below this have lower PER */
+	/* Monotonicity is kept only for rates below the current rate. */
+	if (ath_rc_priv->state[tx_rate].per < last_per) {
+		for (rate = tx_rate - 1; rate >= 0; rate--) {
+			if (rate_table->info[rate].phy !=
+			    rate_table->info[tx_rate].phy)
+				break;
+
+			if (ath_rc_priv->state[rate].per >
+			    ath_rc_priv->state[rate+1].per) {
+				ath_rc_priv->state[rate].per =
+					ath_rc_priv->state[rate+1].per;
+			}
+		}
+	}
+
+	/* Maintain monotonicity for rates above the current rate */
+	for (rate = tx_rate; rate < size - 1; rate++) {
+		if (ath_rc_priv->state[rate+1].per <
+		    ath_rc_priv->state[rate].per)
+			ath_rc_priv->state[rate+1].per =
+				ath_rc_priv->state[rate].per;
+	}
+
+	/* Every so often, we reduce the thresholds and
+	 * PER (different for CCK and OFDM). */
+	if (now_msec - ath_rc_priv->rssi_down_time >=
+	    rate_table->rssi_reduce_interval) {
+
+		for (rate = 0; rate < size; rate++) {
+			if (ath_rc_priv->state[rate].rssi_thres >
+			    rate_table->info[rate].rssi_ack_validmin)
+				ath_rc_priv->state[rate].rssi_thres -= 1;
+		}
+		ath_rc_priv->rssi_down_time = now_msec;
+	}
+
+	/* Every so often, we reduce the thresholds
+	 * and PER (different for CCK and OFDM). */
+	if (now_msec - ath_rc_priv->per_down_time >=
+	    rate_table->rssi_reduce_interval) {
+		for (rate = 0; rate < size; rate++) {
+			ath_rc_priv->state[rate].per =
+				7 * ath_rc_priv->state[rate].per / 8;
+		}
+
+		ath_rc_priv->per_down_time = now_msec;
+	}
+
+	ath_debug_stat_retries(sc, tx_rate, xretries, retries,
+			       ath_rc_priv->state[tx_rate].per);
+
+#undef CHK_RSSI
+}
+
+static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
+				struct ieee80211_tx_rate *rate)
+{
+	int rix;
+
+	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+	    (rate->flags & IEEE80211_TX_RC_SHORT_GI))
+		rix = rate_table->info[rate->idx].ht_index;
+	else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+		rix = rate_table->info[rate->idx].sgi_index;
+	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		rix = rate_table->info[rate->idx].cw40index;
+	else
+		rix = rate_table->info[rate->idx].base_index;
+
+	return rix;
+}
+
+static void ath_rc_tx_status(struct ath_softc *sc,
+			     struct ath_rate_priv *ath_rc_priv,
+			     struct ieee80211_tx_info *tx_info,
+			     int final_ts_idx, int xretries, int long_retry)
+{
+	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+	const struct ath_rate_table *rate_table;
+	struct ieee80211_tx_rate *rates = tx_info->status.rates;
+	u8 flags;
+	u32 i = 0, rix;
+
+	rate_table = sc->cur_rate_table;
+
+	/*
+	 * If the first rate is not the final index, there
+	 * are intermediate rate failures to be processed.
+	 */
+	if (final_ts_idx != 0) {
+		/* Process intermediate rates that failed.*/
+		for (i = 0; i < final_ts_idx ; i++) {
+			if (rates[i].count != 0 && (rates[i].idx >= 0)) {
+				flags = rates[i].flags;
+
+				/* If HT40 and we have switched mode from
+				 * 40 to 20 => don't update */
+
+				if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+				    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
+					return;
+
+				rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+				ath_rc_update_ht(sc, ath_rc_priv,
+						tx_info_priv, rix,
+						xretries ? 1 : 2,
+						rates[i].count);
+			}
+		}
+	} else {
+		/*
+		 * Handle the special case of MIMO PS burst, where the second
+		 * aggregate is sent out with only one rate and one try.
+		 * Treating it as an excessive retry penalizes the rate
+		 * inordinately.
+		 */
+		if (rates[0].count == 1 && xretries == 1)
+			xretries = 2;
+	}
+
+	flags = rates[i].flags;
+
+	/* If HT40 and we have switched mode from 40 to 20 => don't update */
+	if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+	    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
+		return;
+
+	rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+	ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
+			 xretries, long_retry);
+}
+
+static const
+struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
+					     enum ieee80211_band band,
+					     bool is_ht,
+					     bool is_cw_40)
+{
+	int mode = 0;
+
+	switch(band) {
+	case IEEE80211_BAND_2GHZ:
+		mode = ATH9K_MODE_11G;
+		if (is_ht)
+			mode = ATH9K_MODE_11NG_HT20;
+		if (is_cw_40)
+			mode = ATH9K_MODE_11NG_HT40PLUS;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		mode = ATH9K_MODE_11A;
+		if (is_ht)
+			mode = ATH9K_MODE_11NA_HT20;
+		if (is_cw_40)
+			mode = ATH9K_MODE_11NA_HT40PLUS;
+		break;
+	default:
+		DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n");
+		return NULL;
+	}
+
+	BUG_ON(mode >= ATH9K_MODE_MAX);
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode);
+	return sc->hw_rate_table[mode];
+}
+
+static void ath_rc_init(struct ath_softc *sc,
+			struct ath_rate_priv *ath_rc_priv,
+			struct ieee80211_supported_band *sband,
+			struct ieee80211_sta *sta,
+			const struct ath_rate_table *rate_table)
+{
+	struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
+	u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
+	u8 i, j, k, hi = 0, hthi = 0;
+
+	if (!rate_table) {
+		DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
+		return;
+	}
+
+	/* Initial rate table size. Will change depending
+	 * on the working rate set */
+	ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
+
+	/* Initialize thresholds according to the global rate table */
+	for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
+		ath_rc_priv->state[i].rssi_thres =
+			rate_table->info[i].rssi_ack_validmin;
+		ath_rc_priv->state[i].per = 0;
+	}
+
+	/* Determine the valid rates */
+	ath_rc_init_valid_txmask(ath_rc_priv);
+
+	for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
+		for (j = 0; j < MAX_TX_RATE_PHY; j++)
+			ath_rc_priv->valid_phy_rateidx[i][j] = 0;
+		ath_rc_priv->valid_phy_ratecnt[i] = 0;
+	}
+
+	if (!rateset->rs_nrates) {
+		/* No working rate, just initialize valid rates */
+		hi = ath_rc_init_validrates(ath_rc_priv, rate_table,
+					    ath_rc_priv->ht_cap);
+	} else {
+		/* Use intersection of working rates and valid rates */
+		hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table,
+					   rateset, ath_rc_priv->ht_cap);
+		if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
+			hthi = ath_rc_setvalid_htrates(ath_rc_priv,
+						       rate_table,
+						       ht_mcs,
+						       ath_rc_priv->ht_cap);
+		}
+		hi = A_MAX(hi, hthi);
+	}
+
+	ath_rc_priv->rate_table_size = hi + 1;
+	ath_rc_priv->rate_max_phy = 0;
+	ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
+
+	for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
+		for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
+			ath_rc_priv->valid_rate_index[k++] =
+				ath_rc_priv->valid_phy_rateidx[i][j];
+		}
+
+		if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1)
+		    || !ath_rc_priv->valid_phy_ratecnt[i])
+			continue;
+
+		ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
+	}
+	ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
+	ASSERT(k <= RATE_TABLE_SIZE);
+
+	ath_rc_priv->max_valid_rate = k;
+	ath_rc_sort_validrates(rate_table, ath_rc_priv);
+	ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
+	sc->cur_rate_table = rate_table;
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n",
+		ath_rc_priv->ht_cap);
+}
+
+static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
+			       bool is_cw40, bool is_sgi40)
+{
+	u8 caps = 0;
+
+	if (sta->ht_cap.ht_supported) {
+		caps = WLAN_RC_HT_FLAG;
+		if (sc->sc_ah->caps.tx_chainmask != 1 &&
+		    ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) {
+			if (sta->ht_cap.mcs.rx_mask[1])
+				caps |= WLAN_RC_DS_FLAG;
+		}
+		if (is_cw40)
+			caps |= WLAN_RC_40_FLAG;
+		if (is_sgi40)
+			caps |= WLAN_RC_SGI_FLAG;
+	}
+
+	return caps;
+}
+
+/***********************************/
+/* mac80211 Rate Control callbacks */
+/***********************************/
+
+static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
+			  struct ieee80211_sta *sta, void *priv_sta,
+			  struct sk_buff *skb)
+{
+	struct ath_softc *sc = priv;
+	struct ath_rate_priv *ath_rc_priv = priv_sta;
+	struct ath_tx_info_priv *tx_info_priv = NULL;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr;
+	int final_ts_idx, tx_status = 0, is_underrun = 0;
+	__le16 fc;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+	final_ts_idx = tx_info_priv->tx.ts_rateindex;
+
+	if (!priv_sta || !ieee80211_is_data(fc) ||
+	    !tx_info_priv->update_rc)
+		goto exit;
+
+	if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
+		goto exit;
+
+	/*
+	 * If underrun error is seen assume it as an excessive retry only
+	 * if prefetch trigger level have reached the max (0x3f for 5416)
+	 * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
+	 * times. This affects how ratectrl updates PER for the failed rate.
+	 */
+	if (tx_info_priv->tx.ts_flags &
+	    (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
+	    ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) {
+		tx_status = 1;
+		is_underrun = 1;
+	}
+
+	if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
+	    (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
+		tx_status = 1;
+
+	ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
+			 (is_underrun) ? ATH_11N_TXMAXTRY :
+			 tx_info_priv->tx.ts_longretry);
+
+	/* Check if aggregation has to be enabled for this tid */
+	if (conf_is_ht(&sc->hw->conf) &&
+	    !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
+		if (ieee80211_is_data_qos(fc)) {
+			u8 *qc, tid;
+			struct ath_node *an;
+
+			qc = ieee80211_get_qos_ctl(hdr);
+			tid = qc[0] & 0xf;
+			an = (struct ath_node *)sta->drv_priv;
+
+			if(ath_tx_aggr_check(sc, an, tid))
+				ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid);
+		}
+	}
+
+	ath_debug_stat_rc(sc, skb);
+exit:
+	kfree(tx_info_priv);
+}
+
+static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+			 struct ieee80211_tx_rate_control *txrc)
+{
+	struct ieee80211_supported_band *sband = txrc->sband;
+	struct sk_buff *skb = txrc->skb;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ath_softc *sc = priv;
+	struct ath_rate_priv *ath_rc_priv = priv_sta;
+	__le16 fc = hdr->frame_control;
+
+	/* lowest rate for management and NO_ACK frames */
+	if (!ieee80211_is_data(fc) ||
+	    tx_info->flags & IEEE80211_TX_CTL_NO_ACK || !sta) {
+		tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
+		tx_info->control.rates[0].count =
+			(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ?
+				1 : ATH_MGT_TXMAXTRY;
+		return;
+	}
+
+	/* Find tx rate for unicast frames */
+	ath_rc_ratefind(sc, ath_rc_priv, txrc);
+}
+
+static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
+                          struct ieee80211_sta *sta, void *priv_sta)
+{
+	struct ath_softc *sc = priv;
+	struct ath_rate_priv *ath_rc_priv = priv_sta;
+	const struct ath_rate_table *rate_table = NULL;
+	bool is_cw40, is_sgi40;
+	int i, j = 0;
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if (sta->supp_rates[sband->band] & BIT(i)) {
+			ath_rc_priv->neg_rates.rs_rates[j]
+				= (sband->bitrates[i].bitrate * 2) / 10;
+			j++;
+		}
+	}
+	ath_rc_priv->neg_rates.rs_nrates = j;
+
+	if (sta->ht_cap.ht_supported) {
+		for (i = 0, j = 0; i < 77; i++) {
+			if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
+				ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
+			if (j == ATH_RATE_MAX)
+				break;
+		}
+		ath_rc_priv->neg_ht_rates.rs_nrates = j;
+	}
+
+	is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
+
+	/* Choose rate table first */
+
+	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
+	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
+	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
+		rate_table = ath_choose_rate_table(sc, sband->band,
+						   sta->ht_cap.ht_supported,
+						   is_cw40);
+	} else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
+		/* cur_rate_table would be set on init through config() */
+		rate_table = sc->cur_rate_table;
+	}
+
+	ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40);
+	ath_rc_init(sc, priv_sta, sband, sta, rate_table);
+}
+
+static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
+			    struct ieee80211_sta *sta, void *priv_sta,
+			    u32 changed)
+{
+	struct ath_softc *sc = priv;
+	struct ath_rate_priv *ath_rc_priv = priv_sta;
+	const struct ath_rate_table *rate_table = NULL;
+	bool oper_cw40 = false, oper_sgi40;
+	bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
+		true : false;
+	bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
+		true : false;
+
+	/* FIXME: Handle AP mode later when we support CWM */
+
+	if (changed & IEEE80211_RC_HT_CHANGED) {
+		if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+			return;
+
+		if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS ||
+		    sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS)
+			oper_cw40 = true;
+
+		oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+			true : false;
+
+		if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) {
+			rate_table = ath_choose_rate_table(sc, sband->band,
+						   sta->ht_cap.ht_supported,
+						   oper_cw40);
+			ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
+						   oper_cw40, oper_sgi40);
+			ath_rc_init(sc, priv_sta, sband, sta, rate_table);
+
+			DPRINTF(sc, ATH_DBG_CONFIG,
+				"Operating HT Bandwidth changed to: %d\n",
+				sc->hw->conf.channel_type);
+		}
+	}
+}
+
+static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	return aphy->sc;
+}
+
+static void ath_rate_free(void *priv)
+{
+	return;
+}
+
+static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
+{
+	struct ath_softc *sc = priv;
+	struct ath_rate_priv *rate_priv;
+
+	rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
+	if (!rate_priv) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to allocate private rc structure\n");
+		return NULL;
+	}
+
+	rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
+	rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max;
+
+	return rate_priv;
+}
+
+static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
+			      void *priv_sta)
+{
+	struct ath_rate_priv *rate_priv = priv_sta;
+	kfree(rate_priv);
+}
+
+static struct rate_control_ops ath_rate_ops = {
+	.module = NULL,
+	.name = "ath9k_rate_control",
+	.tx_status = ath_tx_status,
+	.get_rate = ath_get_rate,
+	.rate_init = ath_rate_init,
+	.rate_update = ath_rate_update,
+	.alloc = ath_rate_alloc,
+	.free = ath_rate_free,
+	.alloc_sta = ath_rate_alloc_sta,
+	.free_sta = ath_rate_free_sta,
+};
+
+void ath_rate_attach(struct ath_softc *sc)
+{
+	sc->hw_rate_table[ATH9K_MODE_11B] =
+		&ar5416_11b_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11A] =
+		&ar5416_11a_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11G] =
+		&ar5416_11g_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
+		&ar5416_11na_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
+		&ar5416_11ng_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
+		&ar5416_11na_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
+		&ar5416_11na_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
+		&ar5416_11ng_ratetable;
+	sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
+		&ar5416_11ng_ratetable;
+}
+
+int ath_rate_control_register(void)
+{
+	return ieee80211_rate_control_register(&ath_rate_ops);
+}
+
+void ath_rate_control_unregister(void)
+{
+	ieee80211_rate_control_unregister(&ath_rate_ops);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/rc.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/rc.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/rc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/rc.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2004 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004 Video54 Technologies, Inc.
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef RC_H
+#define RC_H
+
+struct ath_softc;
+
+#define ATH_RATE_MAX     30
+#define RATE_TABLE_SIZE  64
+#define MAX_TX_RATE_PHY  48
+
+/* VALID_ALL - valid for 20/40/Legacy,
+ * VALID - Legacy only,
+ * VALID_20 - HT 20 only,
+ * VALID_40 - HT 40 only */
+
+#define INVALID    0x0
+#define VALID      0x1
+#define VALID_20   0x2
+#define VALID_40   0x4
+#define VALID_2040 (VALID_20|VALID_40)
+#define VALID_ALL  (VALID_2040|VALID)
+
+enum {
+	WLAN_RC_PHY_OFDM,
+	WLAN_RC_PHY_CCK,
+	WLAN_RC_PHY_HT_20_SS,
+	WLAN_RC_PHY_HT_20_DS,
+	WLAN_RC_PHY_HT_40_SS,
+	WLAN_RC_PHY_HT_40_DS,
+	WLAN_RC_PHY_HT_20_SS_HGI,
+	WLAN_RC_PHY_HT_20_DS_HGI,
+	WLAN_RC_PHY_HT_40_SS_HGI,
+	WLAN_RC_PHY_HT_40_DS_HGI,
+	WLAN_RC_PHY_MAX
+};
+
+#define WLAN_RC_PHY_DS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_DS)		\
+				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
+				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
+				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_40(_phy)   ((_phy == WLAN_RC_PHY_HT_40_SS)		\
+				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
+				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)	\
+				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_SGI(_phy)  ((_phy == WLAN_RC_PHY_HT_20_SS_HGI)      \
+				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
+				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)   \
+				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+
+#define WLAN_RC_PHY_HT(_phy)    (_phy >= WLAN_RC_PHY_HT_20_SS)
+
+#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ?	\
+		(capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
+
+/* Return TRUE if flag supports HT20 && client supports HT20 or
+ * return TRUE if flag supports HT40 && client supports HT40.
+ * This is used becos some rates overlap between HT20/HT40.
+ */
+#define WLAN_RC_PHY_HT_VALID(flag, capflag)			\
+	(((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
+	 ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
+
+#define WLAN_RC_DS_FLAG         (0x01)
+#define WLAN_RC_40_FLAG         (0x02)
+#define WLAN_RC_SGI_FLAG        (0x04)
+#define WLAN_RC_HT_FLAG         (0x08)
+
+/**
+ * struct ath_rate_table - Rate Control table
+ * @valid: valid for use in rate control
+ * @valid_single_stream: valid for use in rate control for
+ * 	single stream operation
+ * @phy: CCK/OFDM
+ * @ratekbps: rate in Kbits per second
+ * @user_ratekbps: user rate in Kbits per second
+ * @ratecode: rate that goes into HW descriptors
+ * @short_preamble: Mask for enabling short preamble in ratecode for CCK
+ * @dot11rate: value that goes into supported
+ * 	rates info element of MLME
+ * @ctrl_rate: Index of next lower basic rate, used for duration computation
+ * @max_4ms_framelen: maximum frame length(bytes) for tx duration
+ * @probe_interval: interval for rate control to probe for other rates
+ * @rssi_reduce_interval: interval for rate control to reduce rssi
+ * @initial_ratemax: initial ratemax value
+ */
+struct ath_rate_table {
+	int rate_cnt;
+	struct {
+		int valid;
+		int valid_single_stream;
+		u8 phy;
+		u32 ratekbps;
+		u32 user_ratekbps;
+		u8 ratecode;
+		u8 short_preamble;
+		u8 dot11rate;
+		u8 ctrl_rate;
+		int8_t rssi_ack_validmin;
+		int8_t rssi_ack_deltamin;
+		u8 base_index;
+		u8 cw40index;
+		u8 sgi_index;
+		u8 ht_index;
+		u32 max_4ms_framelen;
+	} info[RATE_TABLE_SIZE];
+	u32 probe_interval;
+	u32 rssi_reduce_interval;
+	u8 initial_ratemax;
+};
+
+struct ath_tx_ratectrl_state {
+	int8_t rssi_thres;	/* required rssi for this rate (dB) */
+	u8 per;			/* recent estimate of packet error rate (%) */
+};
+
+struct ath_rateset {
+	u8 rs_nrates;
+	u8 rs_rates[ATH_RATE_MAX];
+};
+
+/**
+ * struct ath_rate_priv - Rate Control priv data
+ * @state: RC state
+ * @rssi_last: last ACK rssi
+ * @rssi_last_lookup: last ACK rssi used for lookup
+ * @rssi_last_prev: previous last ACK rssi
+ * @rssi_last_prev2: 2nd previous last ACK rssi
+ * @rssi_sum_cnt: count of rssi_sum for averaging
+ * @rssi_sum_rate: rate that we are averaging
+ * @rssi_sum: running sum of rssi for averaging
+ * @probe_rate: rate we are probing at
+ * @rssi_time: msec timestamp for last ack rssi
+ * @rssi_down_time: msec timestamp for last down step
+ * @probe_time: msec timestamp for last probe
+ * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
+ * @max_valid_rate: maximum number of valid rate
+ * @per_down_time: msec timestamp for last PER down step
+ * @valid_phy_ratecnt: valid rate count
+ * @rate_max_phy: phy index for the max rate
+ * @probe_interval: interval for ratectrl to probe for other rates
+ * @prev_data_rix: rate idx of last data frame
+ * @ht_cap: HT capabilities
+ * @neg_rates: Negotatied rates
+ * @neg_ht_rates: Negotiated HT rates
+ */
+struct ath_rate_priv {
+	int8_t rssi_last;
+	int8_t rssi_last_lookup;
+	int8_t rssi_last_prev;
+	int8_t rssi_last_prev2;
+	int32_t rssi_sum_cnt;
+	int32_t rssi_sum_rate;
+	int32_t rssi_sum;
+	u8 rate_table_size;
+	u8 probe_rate;
+	u8 hw_maxretry_pktcnt;
+	u8 max_valid_rate;
+	u8 valid_rate_index[RATE_TABLE_SIZE];
+	u8 ht_cap;
+	u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
+	u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
+	u8 rate_max_phy;
+	u32 rssi_time;
+	u32 rssi_down_time;
+	u32 probe_time;
+	u32 per_down_time;
+	u32 probe_interval;
+	u32 prev_data_rix;
+	u32 tx_triglevel_max;
+	struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE];
+	struct ath_rateset neg_rates;
+	struct ath_rateset neg_ht_rates;
+	struct ath_rate_softc *asc;
+};
+
+enum ath9k_internal_frame_type {
+	ATH9K_NOT_INTERNAL,
+	ATH9K_INT_PAUSE,
+	ATH9K_INT_UNPAUSE
+};
+
+struct ath_tx_info_priv {
+	struct ath_wiphy *aphy;
+	struct ath_tx_status tx;
+	int n_frames;
+	int n_bad_frames;
+	bool update_rc;
+	enum ath9k_internal_frame_type frame_type;
+};
+
+#define ATH_TX_INFO_PRIV(tx_info) \
+	((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
+
+void ath_rate_attach(struct ath_softc *sc);
+u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
+int ath_rate_control_register(void);
+void ath_rate_control_unregister(void);
+
+#endif /* RC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/recv.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/recv.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/recv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/recv.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,838 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
+					     struct ieee80211_hdr *hdr)
+{
+	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
+	int i;
+
+	spin_lock_bh(&sc->wiphy_lock);
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		struct ath_wiphy *aphy = sc->sec_wiphy[i];
+		if (aphy == NULL)
+			continue;
+		if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr)
+		    == 0) {
+			hw = aphy->hw;
+			break;
+		}
+	}
+	spin_unlock_bh(&sc->wiphy_lock);
+	return hw;
+}
+
+/*
+ * Setup and link descriptors.
+ *
+ * 11N: we can no longer afford to self link the last descriptor.
+ * MAC acknowledges BA status as long as it copies frames to host
+ * buffer (or rx fifo). This can incorrectly acknowledge packets
+ * to a sender if last desc is self-linked.
+ */
+static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_desc *ds;
+	struct sk_buff *skb;
+
+	ATH_RXBUF_RESET(bf);
+
+	ds = bf->bf_desc;
+	ds->ds_link = 0; /* link to null */
+	ds->ds_data = bf->bf_buf_addr;
+
+	/* virtual addr of the beginning of the buffer. */
+	skb = bf->bf_mpdu;
+	ASSERT(skb != NULL);
+	ds->ds_vdata = skb->data;
+
+	/* setup rx descriptors. The rx.bufsize here tells the harware
+	 * how much data it can DMA to us and that we are prepared
+	 * to process */
+	ath9k_hw_setuprxdesc(ah, ds,
+			     sc->rx.bufsize,
+			     0);
+
+	if (sc->rx.rxlink == NULL)
+		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+	else
+		*sc->rx.rxlink = bf->bf_daddr;
+
+	sc->rx.rxlink = &ds->ds_link;
+	ath9k_hw_rxena(ah);
+}
+
+static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
+{
+	/* XXX block beacon interrupts */
+	ath9k_hw_setantenna(sc->sc_ah, antenna);
+	sc->rx.defant = antenna;
+	sc->rx.rxotherant = 0;
+}
+
+/*
+ *  Extend 15-bit time stamp from rx descriptor to
+ *  a full 64-bit TSF using the current h/w TSF.
+*/
+static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
+{
+	u64 tsf;
+
+	tsf = ath9k_hw_gettsf64(sc->sc_ah);
+	if ((tsf & 0x7fff) < rstamp)
+		tsf -= 0x8000;
+	return (tsf & ~0x7fff) | rstamp;
+}
+
+static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask)
+{
+	struct sk_buff *skb;
+	u32 off;
+
+	/*
+	 * Cache-line-align.  This is important (for the
+	 * 5210 at least) as not doing so causes bogus data
+	 * in rx'd frames.
+	 */
+
+	/* Note: the kernel can allocate a value greater than
+	 * what we ask it to give us. We really only need 4 KB as that
+	 * is this hardware supports and in fact we need at least 3849
+	 * as that is the MAX AMSDU size this hardware supports.
+	 * Unfortunately this means we may get 8 KB here from the
+	 * kernel... and that is actually what is observed on some
+	 * systems :( */
+	skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask);
+	if (skb != NULL) {
+		off = ((unsigned long) skb->data) % sc->cachelsz;
+		if (off != 0)
+			skb_reserve(skb, sc->cachelsz - off);
+	} else {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"skbuff alloc of size %u failed\n", len);
+		return NULL;
+	}
+
+	return skb;
+}
+
+/*
+ * For Decrypt or Demic errors, we only mark packet status here and always push
+ * up the frame up to let mac80211 handle the actual error case, be it no
+ * decryption key or real decryption error. This let us keep statistics there.
+ */
+static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
+			  struct ieee80211_rx_status *rx_status, bool *decrypt_error,
+			  struct ath_softc *sc)
+{
+	struct ieee80211_hdr *hdr;
+	u8 ratecode;
+	__le16 fc;
+	struct ieee80211_hw *hw;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+	memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+	hw = ath_get_virt_hw(sc, hdr);
+
+	if (ds->ds_rxstat.rs_more) {
+		/*
+		 * Frame spans multiple descriptors; this cannot happen yet
+		 * as we don't support jumbograms. If not in monitor mode,
+		 * discard the frame. Enable this if you want to see
+		 * error frames in Monitor mode.
+		 */
+		if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR)
+			goto rx_next;
+	} else if (ds->ds_rxstat.rs_status != 0) {
+		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
+			rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
+			goto rx_next;
+
+		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
+			*decrypt_error = true;
+		} else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
+			if (ieee80211_is_ctl(fc))
+				/*
+				 * Sometimes, we get invalid
+				 * MIC failures on valid control frames.
+				 * Remove these mic errors.
+				 */
+				ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
+			else
+				rx_status->flag |= RX_FLAG_MMIC_ERROR;
+		}
+		/*
+		 * Reject error frames with the exception of
+		 * decryption and MIC failures. For monitor mode,
+		 * we also ignore the CRC error.
+		 */
+		if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) {
+			if (ds->ds_rxstat.rs_status &
+			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+			      ATH9K_RXERR_CRC))
+				goto rx_next;
+		} else {
+			if (ds->ds_rxstat.rs_status &
+			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
+				goto rx_next;
+			}
+		}
+	}
+
+	ratecode = ds->ds_rxstat.rs_rate;
+
+	if (ratecode & 0x80) {
+		/* HT rate */
+		rx_status->flag |= RX_FLAG_HT;
+		if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
+			rx_status->flag |= RX_FLAG_40MHZ;
+		if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
+			rx_status->flag |= RX_FLAG_SHORT_GI;
+		rx_status->rate_idx = ratecode & 0x7f;
+	} else {
+		int i = 0, cur_band, n_rates;
+
+		cur_band = hw->conf.channel->band;
+		n_rates = sc->sbands[cur_band].n_bitrates;
+
+		for (i = 0; i < n_rates; i++) {
+			if (sc->sbands[cur_band].bitrates[i].hw_value ==
+			    ratecode) {
+				rx_status->rate_idx = i;
+				break;
+			}
+
+			if (sc->sbands[cur_band].bitrates[i].hw_value_short ==
+			    ratecode) {
+				rx_status->rate_idx = i;
+				rx_status->flag |= RX_FLAG_SHORTPRE;
+				break;
+			}
+		}
+	}
+
+	rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
+	rx_status->band = hw->conf.channel->band;
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->noise = sc->ani.noise_floor;
+	rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi;
+	rx_status->antenna = ds->ds_rxstat.rs_antenna;
+
+	/* at 45 you will be able to use MCS 15 reliably. A more elaborate
+	 * scheme can be used here but it requires tables of SNR/throughput for
+	 * each possible mode used. */
+	rx_status->qual =  ds->ds_rxstat.rs_rssi * 100 / 45;
+
+	/* rssi can be more than 45 though, anything above that
+	 * should be considered at 100% */
+	if (rx_status->qual > 100)
+		rx_status->qual = 100;
+
+	rx_status->flag |= RX_FLAG_TSFT;
+
+	return 1;
+rx_next:
+	return 0;
+}
+
+static void ath_opmode_init(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	u32 rfilt, mfilt[2];
+
+	/* configure rx filter */
+	rfilt = ath_calcrxfilter(sc);
+	ath9k_hw_setrxfilter(ah, rfilt);
+
+	/* configure bssid mask */
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
+		ath9k_hw_setbssidmask(sc);
+
+	/* configure operational mode */
+	ath9k_hw_setopmode(ah);
+
+	/* Handle any link-level address change. */
+	ath9k_hw_setmac(ah, sc->sc_ah->macaddr);
+
+	/* calculate and install multicast filter */
+	mfilt[0] = mfilt[1] = ~0;
+	ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
+}
+
+int ath_rx_init(struct ath_softc *sc, int nbufs)
+{
+	struct sk_buff *skb;
+	struct ath_buf *bf;
+	int error = 0;
+
+	spin_lock_init(&sc->rx.rxflushlock);
+	sc->sc_flags &= ~SC_OP_RXFLUSH;
+	spin_lock_init(&sc->rx.rxbuflock);
+
+	sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
+				 min(sc->cachelsz, (u16)64));
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
+		sc->cachelsz, sc->rx.bufsize);
+
+	/* Initialize rx descriptors */
+
+	error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
+				  "rx", nbufs, 1);
+	if (error != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"failed to allocate rx descriptors: %d\n", error);
+		goto err;
+	}
+
+	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+		skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
+		if (skb == NULL) {
+			error = -ENOMEM;
+			goto err;
+		}
+
+		bf->bf_mpdu = skb;
+		bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+						 sc->rx.bufsize,
+						 DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(sc->dev,
+					       bf->bf_buf_addr))) {
+			dev_kfree_skb_any(skb);
+			bf->bf_mpdu = NULL;
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"dma_mapping_error() on RX init\n");
+			error = -ENOMEM;
+			goto err;
+		}
+		bf->bf_dmacontext = bf->bf_buf_addr;
+	}
+	sc->rx.rxlink = NULL;
+
+err:
+	if (error)
+		ath_rx_cleanup(sc);
+
+	return error;
+}
+
+void ath_rx_cleanup(struct ath_softc *sc)
+{
+	struct sk_buff *skb;
+	struct ath_buf *bf;
+
+	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+		skb = bf->bf_mpdu;
+		if (skb) {
+			dma_unmap_single(sc->dev, bf->bf_buf_addr,
+					 sc->rx.bufsize, DMA_FROM_DEVICE);
+			dev_kfree_skb(skb);
+		}
+	}
+
+	if (sc->rx.rxdma.dd_desc_len != 0)
+		ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
+}
+
+/*
+ * Calculate the receive filter according to the
+ * operating mode and state:
+ *
+ * o always accept unicast, broadcast, and multicast traffic
+ * o maintain current state of phy error reception (the hal
+ *   may enable phy error frames for noise immunity work)
+ * o probe request frames are accepted only when operating in
+ *   hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ *   - when operating in adhoc mode so the 802.11 layer creates
+ *     node table entries for peers,
+ *   - when operating in station mode for collecting rssi data when
+ *     the station is otherwise quiet, or
+ *   - when operating as a repeater so we see repeater-sta beacons
+ *   - when scanning
+ */
+
+u32 ath_calcrxfilter(struct ath_softc *sc)
+{
+#define	RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
+
+	u32 rfilt;
+
+	rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
+		| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
+		| ATH9K_RX_FILTER_MCAST;
+
+	/* If not a STA, enable processing of Probe Requests */
+	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+		rfilt |= ATH9K_RX_FILTER_PROBEREQ;
+
+	/*
+	 * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
+	 * mode interface or when in monitor mode. AP mode does not need this
+	 * since it receives all in-BSS frames anyway.
+	 */
+	if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
+	     (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
+	    (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR))
+		rfilt |= ATH9K_RX_FILTER_PROM;
+
+	if (sc->rx.rxfilter & FIF_CONTROL)
+		rfilt |= ATH9K_RX_FILTER_CONTROL;
+
+	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
+	    !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
+		rfilt |= ATH9K_RX_FILTER_MYBEACON;
+	else
+		rfilt |= ATH9K_RX_FILTER_BEACON;
+
+	/* If in HOSTAP mode, want to enable reception of PSPOLL frames */
+	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP)
+		rfilt |= ATH9K_RX_FILTER_PSPOLL;
+
+	if (sc->sec_wiphy) {
+		/* TODO: only needed if more than one BSSID is in use in
+		 * station/adhoc mode */
+		/* TODO: for older chips, may need to add ATH9K_RX_FILTER_PROM
+		 */
+		rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
+	}
+
+	return rfilt;
+
+#undef RX_FILTER_PRESERVE
+}
+
+int ath_startrecv(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_buf *bf, *tbf;
+
+	spin_lock_bh(&sc->rx.rxbuflock);
+	if (list_empty(&sc->rx.rxbuf))
+		goto start_recv;
+
+	sc->rx.rxlink = NULL;
+	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
+		ath_rx_buf_link(sc, bf);
+	}
+
+	/* We could have deleted elements so the list may be empty now */
+	if (list_empty(&sc->rx.rxbuf))
+		goto start_recv;
+
+	bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+	ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+	ath9k_hw_rxena(ah);
+
+start_recv:
+	spin_unlock_bh(&sc->rx.rxbuflock);
+	ath_opmode_init(sc);
+	ath9k_hw_startpcureceive(ah);
+
+	return 0;
+}
+
+bool ath_stoprecv(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	bool stopped;
+
+	ath9k_hw_stoppcurecv(ah);
+	ath9k_hw_setrxfilter(ah, 0);
+	stopped = ath9k_hw_stopdmarecv(ah);
+	sc->rx.rxlink = NULL;
+
+	return stopped;
+}
+
+void ath_flushrecv(struct ath_softc *sc)
+{
+	spin_lock_bh(&sc->rx.rxflushlock);
+	sc->sc_flags |= SC_OP_RXFLUSH;
+	ath_rx_tasklet(sc, 1);
+	sc->sc_flags &= ~SC_OP_RXFLUSH;
+	spin_unlock_bh(&sc->rx.rxflushlock);
+}
+
+static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
+{
+	/* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
+	struct ieee80211_mgmt *mgmt;
+	u8 *pos, *end, id, elen;
+	struct ieee80211_tim_ie *tim;
+
+	mgmt = (struct ieee80211_mgmt *)skb->data;
+	pos = mgmt->u.beacon.variable;
+	end = skb->data + skb->len;
+
+	while (pos + 2 < end) {
+		id = *pos++;
+		elen = *pos++;
+		if (pos + elen > end)
+			break;
+
+		if (id == WLAN_EID_TIM) {
+			if (elen < sizeof(*tim))
+				break;
+			tim = (struct ieee80211_tim_ie *) pos;
+			if (tim->dtim_count != 0)
+				break;
+			return tim->bitmap_ctrl & 0x01;
+		}
+
+		pos += elen;
+	}
+
+	return false;
+}
+
+static void ath_rx_ps_back_to_sleep(struct ath_softc *sc)
+{
+	sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
+}
+
+static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
+{
+	struct ieee80211_mgmt *mgmt;
+
+	if (skb->len < 24 + 8 + 2 + 2)
+		return;
+
+	mgmt = (struct ieee80211_mgmt *)skb->data;
+	if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0)
+		return; /* not from our current AP */
+
+	if (sc->sc_flags & SC_OP_BEACON_SYNC) {
+		sc->sc_flags &= ~SC_OP_BEACON_SYNC;
+		DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on "
+			"timestamp from the AP\n");
+		ath_beacon_config(sc, NULL);
+	}
+
+	if (!(sc->hw->conf.flags & IEEE80211_CONF_PS)) {
+		/* We are not in PS mode anymore; remain awake */
+		DPRINTF(sc, ATH_DBG_PS, "Not in PS mode anymore, remain "
+			"awake\n");
+		sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
+		return;
+	}
+
+	if (ath_beacon_dtim_pending_cab(skb)) {
+		/*
+		 * Remain awake waiting for buffered broadcast/multicast
+		 * frames. If the last broadcast/multicast frame is not
+		 * received properly, the next beacon frame will work as
+		 * a backup trigger for returning into NETWORK SLEEP state,
+		 * so we are waiting for it as well.
+		 */
+		DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating "
+			"buffered broadcast/multicast frame(s)\n");
+		sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON;
+		return;
+	}
+
+	if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) {
+		/*
+		 * This can happen if a broadcast frame is dropped or the AP
+		 * fails to send a frame indicating that all CAB frames have
+		 * been delivered.
+		 */
+		DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n");
+	}
+
+	/* No more broadcast/multicast frames to be received at this point. */
+	ath_rx_ps_back_to_sleep(sc);
+}
+
+static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	/* Process Beacon and CAB receive in PS state */
+	if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) &&
+	    ieee80211_is_beacon(hdr->frame_control))
+		ath_rx_ps_beacon(sc, skb);
+	else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) &&
+		 (ieee80211_is_data(hdr->frame_control) ||
+		  ieee80211_is_action(hdr->frame_control)) &&
+		 is_multicast_ether_addr(hdr->addr1) &&
+		 !ieee80211_has_moredata(hdr->frame_control)) {
+		DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to "
+			"sleep\n");
+		/*
+		 * No more broadcast/multicast frames to be received at this
+		 * point.
+		 */
+		ath_rx_ps_back_to_sleep(sc);
+	} else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) &&
+		   !is_multicast_ether_addr(hdr->addr1) &&
+		   !ieee80211_has_morefrags(hdr->frame_control)) {
+		sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA;
+		DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having "
+			"received PS-Poll data (0x%x)\n",
+			sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+					SC_OP_WAIT_FOR_CAB |
+					SC_OP_WAIT_FOR_PSPOLL_DATA |
+					SC_OP_WAIT_FOR_TX_ACK));
+	}
+}
+
+static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
+				    struct ieee80211_rx_status *rx_status)
+{
+	struct ieee80211_hdr *hdr;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	/* Send the frame to mac80211 */
+	if (is_multicast_ether_addr(hdr->addr1)) {
+		int i;
+		/*
+		 * Deliver broadcast/multicast frames to all suitable
+		 * virtual wiphys.
+		 */
+		/* TODO: filter based on channel configuration */
+		for (i = 0; i < sc->num_sec_wiphy; i++) {
+			struct ath_wiphy *aphy = sc->sec_wiphy[i];
+			struct sk_buff *nskb;
+			if (aphy == NULL)
+				continue;
+			nskb = skb_copy(skb, GFP_ATOMIC);
+			if (nskb)
+				__ieee80211_rx(aphy->hw, nskb, rx_status);
+		}
+		__ieee80211_rx(sc->hw, skb, rx_status);
+	} else {
+		/* Deliver unicast frames based on receiver address */
+		__ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, rx_status);
+	}
+}
+
+int ath_rx_tasklet(struct ath_softc *sc, int flush)
+{
+#define PA2DESC(_sc, _pa)                                               \
+	((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc +		\
+			     ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr)))
+
+	struct ath_buf *bf;
+	struct ath_desc *ds;
+	struct sk_buff *skb = NULL, *requeue_skb;
+	struct ieee80211_rx_status rx_status;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ieee80211_hdr *hdr;
+	int hdrlen, padsize, retval;
+	bool decrypt_error = false;
+	u8 keyix;
+	__le16 fc;
+
+	spin_lock_bh(&sc->rx.rxbuflock);
+
+	do {
+		/* If handling rx interrupt and flush is in progress => exit */
+		if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
+			break;
+
+		if (list_empty(&sc->rx.rxbuf)) {
+			sc->rx.rxlink = NULL;
+			break;
+		}
+
+		bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
+		ds = bf->bf_desc;
+
+		/*
+		 * Must provide the virtual address of the current
+		 * descriptor, the physical address, and the virtual
+		 * address of the next descriptor in the h/w chain.
+		 * This allows the HAL to look ahead to see if the
+		 * hardware is done with a descriptor by checking the
+		 * done bit in the following descriptor and the address
+		 * of the current descriptor the DMA engine is working
+		 * on.  All this is necessary because of our use of
+		 * a self-linked list to avoid rx overruns.
+		 */
+		retval = ath9k_hw_rxprocdesc(ah, ds,
+					     bf->bf_daddr,
+					     PA2DESC(sc, ds->ds_link),
+					     0);
+		if (retval == -EINPROGRESS) {
+			struct ath_buf *tbf;
+			struct ath_desc *tds;
+
+			if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
+				sc->rx.rxlink = NULL;
+				break;
+			}
+
+			tbf = list_entry(bf->list.next, struct ath_buf, list);
+
+			/*
+			 * On some hardware the descriptor status words could
+			 * get corrupted, including the done bit. Because of
+			 * this, check if the next descriptor's done bit is
+			 * set or not.
+			 *
+			 * If the next descriptor's done bit is set, the current
+			 * descriptor has been corrupted. Force s/w to discard
+			 * this descriptor and continue...
+			 */
+
+			tds = tbf->bf_desc;
+			retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
+					     PA2DESC(sc, tds->ds_link), 0);
+			if (retval == -EINPROGRESS) {
+				break;
+			}
+		}
+
+		skb = bf->bf_mpdu;
+		if (!skb)
+			continue;
+
+		/*
+		 * Synchronize the DMA transfer with CPU before
+		 * 1. accessing the frame
+		 * 2. requeueing the same buffer to h/w
+		 */
+		dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
+				sc->rx.bufsize,
+				DMA_FROM_DEVICE);
+
+		/*
+		 * If we're asked to flush receive queue, directly
+		 * chain it back at the queue without processing it.
+		 */
+		if (flush)
+			goto requeue;
+
+		if (!ds->ds_rxstat.rs_datalen)
+			goto requeue;
+
+		/* The status portion of the descriptor could get corrupted. */
+		if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen)
+			goto requeue;
+
+		if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
+			goto requeue;
+
+		/* Ensure we always have an skb to requeue once we are done
+		 * processing the current buffer's skb */
+		requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC);
+
+		/* If there is no memory we ignore the current RX'd frame,
+		 * tell hardware it can give us a new frame using the old
+		 * skb and put it at the tail of the sc->rx.rxbuf list for
+		 * processing. */
+		if (!requeue_skb)
+			goto requeue;
+
+		/* Unmap the frame */
+		dma_unmap_single(sc->dev, bf->bf_buf_addr,
+				 sc->rx.bufsize,
+				 DMA_FROM_DEVICE);
+
+		skb_put(skb, ds->ds_rxstat.rs_datalen);
+		skb->protocol = cpu_to_be16(ETH_P_CONTROL);
+
+		/* see if any padding is done by the hw and remove it */
+		hdr = (struct ieee80211_hdr *)skb->data;
+		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+		fc = hdr->frame_control;
+
+		/* The MAC header is padded to have 32-bit boundary if the
+		 * packet payload is non-zero. The general calculation for
+		 * padsize would take into account odd header lengths:
+		 * padsize = (4 - hdrlen % 4) % 4; However, since only
+		 * even-length headers are used, padding can only be 0 or 2
+		 * bytes and we can optimize this a bit. In addition, we must
+		 * not try to remove padding from short control frames that do
+		 * not have payload. */
+		padsize = hdrlen & 3;
+		if (padsize && hdrlen >= 24) {
+			memmove(skb->data + padsize, skb->data, hdrlen);
+			skb_pull(skb, padsize);
+		}
+
+		keyix = ds->ds_rxstat.rs_keyix;
+
+		if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
+			rx_status.flag |= RX_FLAG_DECRYPTED;
+		} else if (ieee80211_has_protected(fc)
+			   && !decrypt_error && skb->len >= hdrlen + 4) {
+			keyix = skb->data[hdrlen + 3] >> 6;
+
+			if (test_bit(keyix, sc->keymap))
+				rx_status.flag |= RX_FLAG_DECRYPTED;
+		}
+		if (ah->sw_mgmt_crypto &&
+		    (rx_status.flag & RX_FLAG_DECRYPTED) &&
+		    ieee80211_is_mgmt(fc)) {
+			/* Use software decrypt for management frames. */
+			rx_status.flag &= ~RX_FLAG_DECRYPTED;
+		}
+
+		/* We will now give hardware our shiny new allocated skb */
+		bf->bf_mpdu = requeue_skb;
+		bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
+					 sc->rx.bufsize,
+					 DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(sc->dev,
+			  bf->bf_buf_addr))) {
+			dev_kfree_skb_any(requeue_skb);
+			bf->bf_mpdu = NULL;
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"dma_mapping_error() on RX\n");
+			ath_rx_send_to_mac80211(sc, skb, &rx_status);
+			break;
+		}
+		bf->bf_dmacontext = bf->bf_buf_addr;
+
+		/*
+		 * change the default rx antenna if rx diversity chooses the
+		 * other antenna 3 times in a row.
+		 */
+		if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
+			if (++sc->rx.rxotherant >= 3)
+				ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
+		} else {
+			sc->rx.rxotherant = 0;
+		}
+
+		if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+					     SC_OP_WAIT_FOR_CAB |
+					     SC_OP_WAIT_FOR_PSPOLL_DATA)))
+			ath_rx_ps(sc, skb);
+
+		ath_rx_send_to_mac80211(sc, skb, &rx_status);
+
+requeue:
+		list_move_tail(&bf->list, &sc->rx.rxbuf);
+		ath_rx_buf_link(sc, bf);
+	} while (1);
+
+	spin_unlock_bh(&sc->rx.rxbuflock);
+
+	return 0;
+#undef PA2DESC
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/reg.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/reg.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/reg.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1511 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REG_H
+#define REG_H
+
+#define AR_CR                0x0008
+#define AR_CR_RXE            0x00000004
+#define AR_CR_RXD            0x00000020
+#define AR_CR_SWI            0x00000040
+
+#define AR_RXDP              0x000C
+
+#define AR_CFG               0x0014
+#define AR_CFG_SWTD          0x00000001
+#define AR_CFG_SWTB          0x00000002
+#define AR_CFG_SWRD          0x00000004
+#define AR_CFG_SWRB          0x00000008
+#define AR_CFG_SWRG          0x00000010
+#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
+#define AR_CFG_PHOK          0x00000100
+#define AR_CFG_CLK_GATE_DIS  0x00000400
+#define AR_CFG_EEBS          0x00000200
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH         0x00060000
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S       17
+
+#define AR_MIRT              0x0020
+#define AR_MIRT_VAL          0x0000ffff
+#define AR_MIRT_VAL_S        16
+
+#define AR_IER               0x0024
+#define AR_IER_ENABLE        0x00000001
+#define AR_IER_DISABLE       0x00000000
+
+#define AR_TIMT              0x0028
+#define AR_TIMT_LAST         0x0000ffff
+#define AR_TIMT_LAST_S       0
+#define AR_TIMT_FIRST        0xffff0000
+#define AR_TIMT_FIRST_S      16
+
+#define AR_RIMT              0x002C
+#define AR_RIMT_LAST         0x0000ffff
+#define AR_RIMT_LAST_S       0
+#define AR_RIMT_FIRST        0xffff0000
+#define AR_RIMT_FIRST_S      16
+
+#define AR_DMASIZE_4B        0x00000000
+#define AR_DMASIZE_8B        0x00000001
+#define AR_DMASIZE_16B       0x00000002
+#define AR_DMASIZE_32B       0x00000003
+#define AR_DMASIZE_64B       0x00000004
+#define AR_DMASIZE_128B      0x00000005
+#define AR_DMASIZE_256B      0x00000006
+#define AR_DMASIZE_512B      0x00000007
+
+#define AR_TXCFG             0x0030
+#define AR_TXCFG_DMASZ_MASK  0x00000007
+#define AR_TXCFG_DMASZ_4B    0
+#define AR_TXCFG_DMASZ_8B    1
+#define AR_TXCFG_DMASZ_16B   2
+#define AR_TXCFG_DMASZ_32B   3
+#define AR_TXCFG_DMASZ_64B   4
+#define AR_TXCFG_DMASZ_128B  5
+#define AR_TXCFG_DMASZ_256B  6
+#define AR_TXCFG_DMASZ_512B  7
+#define AR_FTRIG             0x000003F0
+#define AR_FTRIG_S           4
+#define AR_FTRIG_IMMED       0x00000000
+#define AR_FTRIG_64B         0x00000010
+#define AR_FTRIG_128B        0x00000020
+#define AR_FTRIG_192B        0x00000030
+#define AR_FTRIG_256B        0x00000040
+#define AR_FTRIG_512B        0x00000080
+#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800
+
+#define AR_RXCFG             0x0034
+#define AR_RXCFG_CHIRP       0x00000008
+#define AR_RXCFG_ZLFDMA      0x00000010
+#define AR_RXCFG_DMASZ_MASK  0x00000007
+#define AR_RXCFG_DMASZ_4B    0
+#define AR_RXCFG_DMASZ_8B    1
+#define AR_RXCFG_DMASZ_16B   2
+#define AR_RXCFG_DMASZ_32B   3
+#define AR_RXCFG_DMASZ_64B   4
+#define AR_RXCFG_DMASZ_128B  5
+#define AR_RXCFG_DMASZ_256B  6
+#define AR_RXCFG_DMASZ_512B  7
+
+#define AR_MIBC              0x0040
+#define AR_MIBC_COW          0x00000001
+#define AR_MIBC_FMC          0x00000002
+#define AR_MIBC_CMC          0x00000004
+#define AR_MIBC_MCS          0x00000008
+
+#define AR_TOPS              0x0044
+#define AR_TOPS_MASK         0x0000FFFF
+
+#define AR_RXNPTO            0x0048
+#define AR_RXNPTO_MASK       0x000003FF
+
+#define AR_TXNPTO            0x004C
+#define AR_TXNPTO_MASK       0x000003FF
+#define AR_TXNPTO_QCU_MASK   0x000FFC00
+
+#define AR_RPGTO             0x0050
+#define AR_RPGTO_MASK        0x000003FF
+
+#define AR_RPCNT             0x0054
+#define AR_RPCNT_MASK        0x0000001F
+
+#define AR_MACMISC           0x0058
+#define AR_MACMISC_PCI_EXT_FORCE        0x00000010
+#define AR_MACMISC_DMA_OBS              0x000001E0
+#define AR_MACMISC_DMA_OBS_S            5
+#define AR_MACMISC_DMA_OBS_LINE_0       0
+#define AR_MACMISC_DMA_OBS_LINE_1       1
+#define AR_MACMISC_DMA_OBS_LINE_2       2
+#define AR_MACMISC_DMA_OBS_LINE_3       3
+#define AR_MACMISC_DMA_OBS_LINE_4       4
+#define AR_MACMISC_DMA_OBS_LINE_5       5
+#define AR_MACMISC_DMA_OBS_LINE_6       6
+#define AR_MACMISC_DMA_OBS_LINE_7       7
+#define AR_MACMISC_DMA_OBS_LINE_8       8
+#define AR_MACMISC_MISC_OBS             0x00000E00
+#define AR_MACMISC_MISC_OBS_S           9
+#define AR_MACMISC_MISC_OBS_BUS_LSB     0x00007000
+#define AR_MACMISC_MISC_OBS_BUS_LSB_S   12
+#define AR_MACMISC_MISC_OBS_BUS_MSB     0x00038000
+#define AR_MACMISC_MISC_OBS_BUS_MSB_S   15
+#define AR_MACMISC_MISC_OBS_BUS_1       1
+
+#define AR_GTXTO    0x0064
+#define AR_GTXTO_TIMEOUT_COUNTER    0x0000FFFF
+#define AR_GTXTO_TIMEOUT_LIMIT      0xFFFF0000
+#define AR_GTXTO_TIMEOUT_LIMIT_S    16
+
+#define AR_GTTM     0x0068
+#define AR_GTTM_USEC          0x00000001
+#define AR_GTTM_IGNORE_IDLE   0x00000002
+#define AR_GTTM_RESET_IDLE    0x00000004
+#define AR_GTTM_CST_USEC      0x00000008
+
+#define AR_CST         0x006C
+#define AR_CST_TIMEOUT_COUNTER    0x0000FFFF
+#define AR_CST_TIMEOUT_LIMIT      0xFFFF0000
+#define AR_CST_TIMEOUT_LIMIT_S    16
+
+#define AR_ISR               0x0080
+#define AR_ISR_RXOK          0x00000001
+#define AR_ISR_RXDESC        0x00000002
+#define AR_ISR_RXERR         0x00000004
+#define AR_ISR_RXNOPKT       0x00000008
+#define AR_ISR_RXEOL         0x00000010
+#define AR_ISR_RXORN         0x00000020
+#define AR_ISR_TXOK          0x00000040
+#define AR_ISR_TXDESC        0x00000080
+#define AR_ISR_TXERR         0x00000100
+#define AR_ISR_TXNOPKT       0x00000200
+#define AR_ISR_TXEOL         0x00000400
+#define AR_ISR_TXURN         0x00000800
+#define AR_ISR_MIB           0x00001000
+#define AR_ISR_SWI           0x00002000
+#define AR_ISR_RXPHY         0x00004000
+#define AR_ISR_RXKCM         0x00008000
+#define AR_ISR_SWBA          0x00010000
+#define AR_ISR_BRSSI         0x00020000
+#define AR_ISR_BMISS         0x00040000
+#define AR_ISR_BNR           0x00100000
+#define AR_ISR_RXCHIRP       0x00200000
+#define AR_ISR_BCNMISC       0x00800000
+#define AR_ISR_TIM           0x00800000
+#define AR_ISR_QCBROVF       0x02000000
+#define AR_ISR_QCBRURN       0x04000000
+#define AR_ISR_QTRIG         0x08000000
+#define AR_ISR_GENTMR        0x10000000
+
+#define AR_ISR_TXMINTR       0x00080000
+#define AR_ISR_RXMINTR       0x01000000
+#define AR_ISR_TXINTM        0x40000000
+#define AR_ISR_RXINTM        0x80000000
+
+#define AR_ISR_S0               0x0084
+#define AR_ISR_S0_QCU_TXOK      0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S    0
+#define AR_ISR_S0_QCU_TXDESC    0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S  16
+
+#define AR_ISR_S1              0x0088
+#define AR_ISR_S1_QCU_TXERR    0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S  0
+#define AR_ISR_S1_QCU_TXEOL    0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S  16
+
+#define AR_ISR_S2              0x008c
+#define AR_ISR_S2_QCU_TXURN    0x000003FF
+#define AR_ISR_S2_CST          0x00400000
+#define AR_ISR_S2_GTT          0x00800000
+#define AR_ISR_S2_TIM          0x01000000
+#define AR_ISR_S2_CABEND       0x02000000
+#define AR_ISR_S2_DTIMSYNC     0x04000000
+#define AR_ISR_S2_BCNTO        0x08000000
+#define AR_ISR_S2_CABTO        0x10000000
+#define AR_ISR_S2_DTIM         0x20000000
+#define AR_ISR_S2_TSFOOR       0x40000000
+#define AR_ISR_S2_TBTT_TIME    0x80000000
+
+#define AR_ISR_S3             0x0090
+#define AR_ISR_S3_QCU_QCBROVF    0x000003FF
+#define AR_ISR_S3_QCU_QCBRURN    0x03FF0000
+
+#define AR_ISR_S4              0x0094
+#define AR_ISR_S4_QCU_QTRIG    0x000003FF
+#define AR_ISR_S4_RESV0        0xFFFFFC00
+
+#define AR_ISR_S5                   0x0098
+#define AR_ISR_S5_TIMER_TRIG        0x000000FF
+#define AR_ISR_S5_TIMER_THRESH      0x0007FE00
+#define AR_ISR_S5_TIM_TIMER         0x00000010
+#define AR_ISR_S5_DTIM_TIMER        0x00000020
+#define AR_ISR_S5_S                 0x00d8
+#define AR_IMR_S5                   0x00b8
+#define AR_IMR_S5_TIM_TIMER         0x00000010
+#define AR_IMR_S5_DTIM_TIMER        0x00000020
+
+
+#define AR_IMR               0x00a0
+#define AR_IMR_RXOK          0x00000001
+#define AR_IMR_RXDESC        0x00000002
+#define AR_IMR_RXERR         0x00000004
+#define AR_IMR_RXNOPKT       0x00000008
+#define AR_IMR_RXEOL         0x00000010
+#define AR_IMR_RXORN         0x00000020
+#define AR_IMR_TXOK          0x00000040
+#define AR_IMR_TXDESC        0x00000080
+#define AR_IMR_TXERR         0x00000100
+#define AR_IMR_TXNOPKT       0x00000200
+#define AR_IMR_TXEOL         0x00000400
+#define AR_IMR_TXURN         0x00000800
+#define AR_IMR_MIB           0x00001000
+#define AR_IMR_SWI           0x00002000
+#define AR_IMR_RXPHY         0x00004000
+#define AR_IMR_RXKCM         0x00008000
+#define AR_IMR_SWBA          0x00010000
+#define AR_IMR_BRSSI         0x00020000
+#define AR_IMR_BMISS         0x00040000
+#define AR_IMR_BNR           0x00100000
+#define AR_IMR_RXCHIRP       0x00200000
+#define AR_IMR_BCNMISC       0x00800000
+#define AR_IMR_TIM           0x00800000
+#define AR_IMR_QCBROVF       0x02000000
+#define AR_IMR_QCBRURN       0x04000000
+#define AR_IMR_QTRIG         0x08000000
+#define AR_IMR_GENTMR        0x10000000
+
+#define AR_IMR_TXMINTR       0x00080000
+#define AR_IMR_RXMINTR       0x01000000
+#define AR_IMR_TXINTM        0x40000000
+#define AR_IMR_RXINTM        0x80000000
+
+#define AR_IMR_S0               0x00a4
+#define AR_IMR_S0_QCU_TXOK      0x000003FF
+#define AR_IMR_S0_QCU_TXOK_S    0
+#define AR_IMR_S0_QCU_TXDESC    0x03FF0000
+#define AR_IMR_S0_QCU_TXDESC_S  16
+
+#define AR_IMR_S1              0x00a8
+#define AR_IMR_S1_QCU_TXERR    0x000003FF
+#define AR_IMR_S1_QCU_TXERR_S  0
+#define AR_IMR_S1_QCU_TXEOL    0x03FF0000
+#define AR_IMR_S1_QCU_TXEOL_S  16
+
+#define AR_IMR_S2              0x00ac
+#define AR_IMR_S2_QCU_TXURN    0x000003FF
+#define AR_IMR_S2_QCU_TXURN_S  0
+#define AR_IMR_S2_CST          0x00400000
+#define AR_IMR_S2_GTT          0x00800000
+#define AR_IMR_S2_TIM          0x01000000
+#define AR_IMR_S2_CABEND       0x02000000
+#define AR_IMR_S2_DTIMSYNC     0x04000000
+#define AR_IMR_S2_BCNTO        0x08000000
+#define AR_IMR_S2_CABTO        0x10000000
+#define AR_IMR_S2_DTIM         0x20000000
+#define AR_IMR_S2_TSFOOR       0x40000000
+
+#define AR_IMR_S3                0x00b0
+#define AR_IMR_S3_QCU_QCBROVF    0x000003FF
+#define AR_IMR_S3_QCU_QCBRURN    0x03FF0000
+#define AR_IMR_S3_QCU_QCBRURN_S  16
+
+#define AR_IMR_S4              0x00b4
+#define AR_IMR_S4_QCU_QTRIG    0x000003FF
+#define AR_IMR_S4_RESV0        0xFFFFFC00
+
+#define AR_IMR_S5              0x00b8
+#define AR_IMR_S5_TIMER_TRIG        0x000000FF
+#define AR_IMR_S5_TIMER_THRESH      0x0000FF00
+
+
+#define AR_ISR_RAC            0x00c0
+#define AR_ISR_S0_S           0x00c4
+#define AR_ISR_S0_QCU_TXOK      0x000003FF
+#define AR_ISR_S0_QCU_TXOK_S    0
+#define AR_ISR_S0_QCU_TXDESC    0x03FF0000
+#define AR_ISR_S0_QCU_TXDESC_S  16
+
+#define AR_ISR_S1_S           0x00c8
+#define AR_ISR_S1_QCU_TXERR    0x000003FF
+#define AR_ISR_S1_QCU_TXERR_S  0
+#define AR_ISR_S1_QCU_TXEOL    0x03FF0000
+#define AR_ISR_S1_QCU_TXEOL_S  16
+
+#define AR_ISR_S2_S           0x00cc
+#define AR_ISR_S3_S           0x00d0
+#define AR_ISR_S4_S           0x00d4
+#define AR_ISR_S5_S           0x00d8
+#define AR_DMADBG_0           0x00e0
+#define AR_DMADBG_1           0x00e4
+#define AR_DMADBG_2           0x00e8
+#define AR_DMADBG_3           0x00ec
+#define AR_DMADBG_4           0x00f0
+#define AR_DMADBG_5           0x00f4
+#define AR_DMADBG_6           0x00f8
+#define AR_DMADBG_7           0x00fc
+
+#define AR_NUM_QCU      10
+#define AR_QCU_0        0x0001
+#define AR_QCU_1        0x0002
+#define AR_QCU_2        0x0004
+#define AR_QCU_3        0x0008
+#define AR_QCU_4        0x0010
+#define AR_QCU_5        0x0020
+#define AR_QCU_6        0x0040
+#define AR_QCU_7        0x0080
+#define AR_QCU_8        0x0100
+#define AR_QCU_9        0x0200
+
+#define AR_Q0_TXDP           0x0800
+#define AR_Q1_TXDP           0x0804
+#define AR_Q2_TXDP           0x0808
+#define AR_Q3_TXDP           0x080c
+#define AR_Q4_TXDP           0x0810
+#define AR_Q5_TXDP           0x0814
+#define AR_Q6_TXDP           0x0818
+#define AR_Q7_TXDP           0x081c
+#define AR_Q8_TXDP           0x0820
+#define AR_Q9_TXDP           0x0824
+#define AR_QTXDP(_i)    (AR_Q0_TXDP + ((_i)<<2))
+
+#define AR_Q_TXE             0x0840
+#define AR_Q_TXE_M           0x000003FF
+
+#define AR_Q_TXD             0x0880
+#define AR_Q_TXD_M           0x000003FF
+
+#define AR_Q0_CBRCFG         0x08c0
+#define AR_Q1_CBRCFG         0x08c4
+#define AR_Q2_CBRCFG         0x08c8
+#define AR_Q3_CBRCFG         0x08cc
+#define AR_Q4_CBRCFG         0x08d0
+#define AR_Q5_CBRCFG         0x08d4
+#define AR_Q6_CBRCFG         0x08d8
+#define AR_Q7_CBRCFG         0x08dc
+#define AR_Q8_CBRCFG         0x08e0
+#define AR_Q9_CBRCFG         0x08e4
+#define AR_QCBRCFG(_i)      (AR_Q0_CBRCFG + ((_i)<<2))
+#define AR_Q_CBRCFG_INTERVAL     0x00FFFFFF
+#define AR_Q_CBRCFG_INTERVAL_S   0
+#define AR_Q_CBRCFG_OVF_THRESH   0xFF000000
+#define AR_Q_CBRCFG_OVF_THRESH_S 24
+
+#define AR_Q0_RDYTIMECFG         0x0900
+#define AR_Q1_RDYTIMECFG         0x0904
+#define AR_Q2_RDYTIMECFG         0x0908
+#define AR_Q3_RDYTIMECFG         0x090c
+#define AR_Q4_RDYTIMECFG         0x0910
+#define AR_Q5_RDYTIMECFG         0x0914
+#define AR_Q6_RDYTIMECFG         0x0918
+#define AR_Q7_RDYTIMECFG         0x091c
+#define AR_Q8_RDYTIMECFG         0x0920
+#define AR_Q9_RDYTIMECFG         0x0924
+#define AR_QRDYTIMECFG(_i)       (AR_Q0_RDYTIMECFG + ((_i)<<2))
+#define AR_Q_RDYTIMECFG_DURATION   0x00FFFFFF
+#define AR_Q_RDYTIMECFG_DURATION_S 0
+#define AR_Q_RDYTIMECFG_EN         0x01000000
+
+#define AR_Q_ONESHOTARM_SC       0x0940
+#define AR_Q_ONESHOTARM_SC_M     0x000003FF
+#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00
+
+#define AR_Q_ONESHOTARM_CC       0x0980
+#define AR_Q_ONESHOTARM_CC_M     0x000003FF
+#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00
+
+#define AR_Q0_MISC         0x09c0
+#define AR_Q1_MISC         0x09c4
+#define AR_Q2_MISC         0x09c8
+#define AR_Q3_MISC         0x09cc
+#define AR_Q4_MISC         0x09d0
+#define AR_Q5_MISC         0x09d4
+#define AR_Q6_MISC         0x09d8
+#define AR_Q7_MISC         0x09dc
+#define AR_Q8_MISC         0x09e0
+#define AR_Q9_MISC         0x09e4
+#define AR_QMISC(_i)       (AR_Q0_MISC + ((_i)<<2))
+#define AR_Q_MISC_FSP                     0x0000000F
+#define AR_Q_MISC_FSP_ASAP                0
+#define AR_Q_MISC_FSP_CBR                 1
+#define AR_Q_MISC_FSP_DBA_GATED           2
+#define AR_Q_MISC_FSP_TIM_GATED           3
+#define AR_Q_MISC_FSP_BEACON_SENT_GATED   4
+#define AR_Q_MISC_FSP_BEACON_RCVD_GATED   5
+#define AR_Q_MISC_ONE_SHOT_EN             0x00000010
+#define AR_Q_MISC_CBR_INCR_DIS1           0x00000020
+#define AR_Q_MISC_CBR_INCR_DIS0           0x00000040
+#define AR_Q_MISC_BEACON_USE              0x00000080
+#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN   0x00000100
+#define AR_Q_MISC_RDYTIME_EXP_POLICY      0x00000200
+#define AR_Q_MISC_RESET_CBR_EXP_CTR       0x00000400
+#define AR_Q_MISC_DCU_EARLY_TERM_REQ      0x00000800
+#define AR_Q_MISC_RESV0                   0xFFFFF000
+
+#define AR_Q0_STS         0x0a00
+#define AR_Q1_STS         0x0a04
+#define AR_Q2_STS         0x0a08
+#define AR_Q3_STS         0x0a0c
+#define AR_Q4_STS         0x0a10
+#define AR_Q5_STS         0x0a14
+#define AR_Q6_STS         0x0a18
+#define AR_Q7_STS         0x0a1c
+#define AR_Q8_STS         0x0a20
+#define AR_Q9_STS         0x0a24
+#define AR_QSTS(_i)       (AR_Q0_STS + ((_i)<<2))
+#define AR_Q_STS_PEND_FR_CNT          0x00000003
+#define AR_Q_STS_RESV0                0x000000FC
+#define AR_Q_STS_CBR_EXP_CNT          0x0000FF00
+#define AR_Q_STS_RESV1                0xFFFF0000
+
+#define AR_Q_RDYTIMESHDN    0x0a40
+#define AR_Q_RDYTIMESHDN_M  0x000003FF
+
+
+#define AR_NUM_DCU      10
+#define AR_DCU_0        0x0001
+#define AR_DCU_1        0x0002
+#define AR_DCU_2        0x0004
+#define AR_DCU_3        0x0008
+#define AR_DCU_4        0x0010
+#define AR_DCU_5        0x0020
+#define AR_DCU_6        0x0040
+#define AR_DCU_7        0x0080
+#define AR_DCU_8        0x0100
+#define AR_DCU_9        0x0200
+
+#define AR_D0_QCUMASK     0x1000
+#define AR_D1_QCUMASK     0x1004
+#define AR_D2_QCUMASK     0x1008
+#define AR_D3_QCUMASK     0x100c
+#define AR_D4_QCUMASK     0x1010
+#define AR_D5_QCUMASK     0x1014
+#define AR_D6_QCUMASK     0x1018
+#define AR_D7_QCUMASK     0x101c
+#define AR_D8_QCUMASK     0x1020
+#define AR_D9_QCUMASK     0x1024
+#define AR_DQCUMASK(_i)   (AR_D0_QCUMASK + ((_i)<<2))
+#define AR_D_QCUMASK         0x000003FF
+#define AR_D_QCUMASK_RESV0   0xFFFFFC00
+
+#define AR_D_TXBLK_CMD  0x1038
+#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i))
+
+#define AR_D0_LCL_IFS     0x1040
+#define AR_D1_LCL_IFS     0x1044
+#define AR_D2_LCL_IFS     0x1048
+#define AR_D3_LCL_IFS     0x104c
+#define AR_D4_LCL_IFS     0x1050
+#define AR_D5_LCL_IFS     0x1054
+#define AR_D6_LCL_IFS     0x1058
+#define AR_D7_LCL_IFS     0x105c
+#define AR_D8_LCL_IFS     0x1060
+#define AR_D9_LCL_IFS     0x1064
+#define AR_DLCL_IFS(_i)   (AR_D0_LCL_IFS + ((_i)<<2))
+#define AR_D_LCL_IFS_CWMIN       0x000003FF
+#define AR_D_LCL_IFS_CWMIN_S     0
+#define AR_D_LCL_IFS_CWMAX       0x000FFC00
+#define AR_D_LCL_IFS_CWMAX_S     10
+#define AR_D_LCL_IFS_AIFS        0x0FF00000
+#define AR_D_LCL_IFS_AIFS_S      20
+
+#define AR_D_LCL_IFS_RESV0    0xF0000000
+
+#define AR_D0_RETRY_LIMIT     0x1080
+#define AR_D1_RETRY_LIMIT     0x1084
+#define AR_D2_RETRY_LIMIT     0x1088
+#define AR_D3_RETRY_LIMIT     0x108c
+#define AR_D4_RETRY_LIMIT     0x1090
+#define AR_D5_RETRY_LIMIT     0x1094
+#define AR_D6_RETRY_LIMIT     0x1098
+#define AR_D7_RETRY_LIMIT     0x109c
+#define AR_D8_RETRY_LIMIT     0x10a0
+#define AR_D9_RETRY_LIMIT     0x10a4
+#define AR_DRETRY_LIMIT(_i)   (AR_D0_RETRY_LIMIT + ((_i)<<2))
+#define AR_D_RETRY_LIMIT_FR_SH       0x0000000F
+#define AR_D_RETRY_LIMIT_FR_SH_S     0
+#define AR_D_RETRY_LIMIT_STA_SH      0x00003F00
+#define AR_D_RETRY_LIMIT_STA_SH_S    8
+#define AR_D_RETRY_LIMIT_STA_LG      0x000FC000
+#define AR_D_RETRY_LIMIT_STA_LG_S    14
+#define AR_D_RETRY_LIMIT_RESV0       0xFFF00000
+
+#define AR_D0_CHNTIME     0x10c0
+#define AR_D1_CHNTIME     0x10c4
+#define AR_D2_CHNTIME     0x10c8
+#define AR_D3_CHNTIME     0x10cc
+#define AR_D4_CHNTIME     0x10d0
+#define AR_D5_CHNTIME     0x10d4
+#define AR_D6_CHNTIME     0x10d8
+#define AR_D7_CHNTIME     0x10dc
+#define AR_D8_CHNTIME     0x10e0
+#define AR_D9_CHNTIME     0x10e4
+#define AR_DCHNTIME(_i)   (AR_D0_CHNTIME + ((_i)<<2))
+#define AR_D_CHNTIME_DUR         0x000FFFFF
+#define AR_D_CHNTIME_DUR_S       0
+#define AR_D_CHNTIME_EN          0x00100000
+#define AR_D_CHNTIME_RESV0       0xFFE00000
+
+#define AR_D0_MISC        0x1100
+#define AR_D1_MISC        0x1104
+#define AR_D2_MISC        0x1108
+#define AR_D3_MISC        0x110c
+#define AR_D4_MISC        0x1110
+#define AR_D5_MISC        0x1114
+#define AR_D6_MISC        0x1118
+#define AR_D7_MISC        0x111c
+#define AR_D8_MISC        0x1120
+#define AR_D9_MISC        0x1124
+#define AR_DMISC(_i)      (AR_D0_MISC + ((_i)<<2))
+#define AR_D_MISC_BKOFF_THRESH        0x0000003F
+#define AR_D_MISC_RETRY_CNT_RESET_EN  0x00000040
+#define AR_D_MISC_CW_RESET_EN         0x00000080
+#define AR_D_MISC_FRAG_WAIT_EN        0x00000100
+#define AR_D_MISC_FRAG_BKOFF_EN       0x00000200
+#define AR_D_MISC_CW_BKOFF_EN         0x00001000
+#define AR_D_MISC_VIR_COL_HANDLING    0x0000C000
+#define AR_D_MISC_VIR_COL_HANDLING_S  14
+#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0
+#define AR_D_MISC_VIR_COL_HANDLING_IGNORE  1
+#define AR_D_MISC_BEACON_USE          0x00010000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL   0x00060000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE     0
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL   2
+#define AR_D_MISC_ARB_LOCKOUT_IGNORE  0x00080000
+#define AR_D_MISC_SEQ_NUM_INCR_DIS    0x00100000
+#define AR_D_MISC_POST_FR_BKOFF_DIS   0x00200000
+#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000
+#define AR_D_MISC_BLOWN_IFS_RETRY_EN  0x00800000
+#define AR_D_MISC_RESV0               0xFF000000
+
+#define AR_D_SEQNUM      0x1140
+
+#define AR_D_GBL_IFS_SIFS         0x1030
+#define AR_D_GBL_IFS_SIFS_M       0x0000FFFF
+#define AR_D_GBL_IFS_SIFS_RESV0   0xFFFFFFFF
+
+#define AR_D_TXBLK_BASE            0x1038
+#define AR_D_TXBLK_WRITE_BITMASK    0x0000FFFF
+#define AR_D_TXBLK_WRITE_BITMASK_S  0
+#define AR_D_TXBLK_WRITE_SLICE      0x000F0000
+#define AR_D_TXBLK_WRITE_SLICE_S    16
+#define AR_D_TXBLK_WRITE_DCU        0x00F00000
+#define AR_D_TXBLK_WRITE_DCU_S      20
+#define AR_D_TXBLK_WRITE_COMMAND    0x0F000000
+#define AR_D_TXBLK_WRITE_COMMAND_S      24
+
+#define AR_D_GBL_IFS_SLOT         0x1070
+#define AR_D_GBL_IFS_SLOT_M       0x0000FFFF
+#define AR_D_GBL_IFS_SLOT_RESV0   0xFFFF0000
+
+#define AR_D_GBL_IFS_EIFS         0x10b0
+#define AR_D_GBL_IFS_EIFS_M       0x0000FFFF
+#define AR_D_GBL_IFS_EIFS_RESV0   0xFFFF0000
+
+#define AR_D_GBL_IFS_MISC        0x10f0
+#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007
+#define AR_D_GBL_IFS_MISC_TURBO_MODE            0x00000008
+#define AR_D_GBL_IFS_MISC_USEC_DURATION         0x000FFC00
+#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY       0x00300000
+#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000
+#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN    0x06000000
+#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000
+#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF        0x10000000
+
+#define AR_D_FPCTL                  0x1230
+#define AR_D_FPCTL_DCU              0x0000000F
+#define AR_D_FPCTL_DCU_S            0
+#define AR_D_FPCTL_PREFETCH_EN      0x00000010
+#define AR_D_FPCTL_BURST_PREFETCH   0x00007FE0
+#define AR_D_FPCTL_BURST_PREFETCH_S 5
+
+#define AR_D_TXPSE                 0x1270
+#define AR_D_TXPSE_CTRL            0x000003FF
+#define AR_D_TXPSE_RESV0           0x0000FC00
+#define AR_D_TXPSE_STATUS          0x00010000
+#define AR_D_TXPSE_RESV1           0xFFFE0000
+
+#define AR_D_TXSLOTMASK            0x12f0
+#define AR_D_TXSLOTMASK_NUM        0x0000000F
+
+#define AR_CFG_LED                     0x1f04
+#define AR_CFG_SCLK_RATE_IND           0x00000003
+#define AR_CFG_SCLK_RATE_IND_S         0
+#define AR_CFG_SCLK_32MHZ              0x00000000
+#define AR_CFG_SCLK_4MHZ               0x00000001
+#define AR_CFG_SCLK_1MHZ               0x00000002
+#define AR_CFG_SCLK_32KHZ              0x00000003
+#define AR_CFG_LED_BLINK_SLOW          0x00000008
+#define AR_CFG_LED_BLINK_THRESH_SEL    0x00000070
+#define AR_CFG_LED_MODE_SEL            0x00000380
+#define AR_CFG_LED_MODE_SEL_S          7
+#define AR_CFG_LED_POWER               0x00000280
+#define AR_CFG_LED_POWER_S             7
+#define AR_CFG_LED_NETWORK             0x00000300
+#define AR_CFG_LED_NETWORK_S           7
+#define AR_CFG_LED_MODE_PROP           0x0
+#define AR_CFG_LED_MODE_RPROP          0x1
+#define AR_CFG_LED_MODE_SPLIT          0x2
+#define AR_CFG_LED_MODE_RAND           0x3
+#define AR_CFG_LED_MODE_POWER_OFF      0x4
+#define AR_CFG_LED_MODE_POWER_ON       0x5
+#define AR_CFG_LED_MODE_NETWORK_OFF    0x4
+#define AR_CFG_LED_MODE_NETWORK_ON     0x6
+#define AR_CFG_LED_ASSOC_CTL           0x00000c00
+#define AR_CFG_LED_ASSOC_CTL_S         10
+#define AR_CFG_LED_ASSOC_NONE          0x0
+#define AR_CFG_LED_ASSOC_ACTIVE        0x1
+#define AR_CFG_LED_ASSOC_PENDING       0x2
+
+#define AR_CFG_LED_BLINK_SLOW          0x00000008
+#define AR_CFG_LED_BLINK_SLOW_S        3
+
+#define AR_CFG_LED_BLINK_THRESH_SEL    0x00000070
+#define AR_CFG_LED_BLINK_THRESH_SEL_S  4
+
+#define AR_MAC_SLEEP                0x1f00
+#define AR_MAC_SLEEP_MAC_AWAKE      0x00000000
+#define AR_MAC_SLEEP_MAC_ASLEEP     0x00000001
+
+#define AR_RC                0x4000
+#define AR_RC_AHB            0x00000001
+#define AR_RC_APB            0x00000002
+#define AR_RC_HOSTIF         0x00000100
+
+#define AR_WA                		0x4004
+#define AR9285_WA_DEFAULT 		0x004a05cb
+#define AR9280_WA_DEFAULT           	0x0040073f
+#define AR_WA_DEFAULT               	0x0000073f
+
+
+#define AR_PM_STATE                 0x4008
+#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
+
+#define AR_HOST_TIMEOUT             0x4018
+#define AR_HOST_TIMEOUT_APB_CNTR    0x0000FFFF
+#define AR_HOST_TIMEOUT_APB_CNTR_S  0
+#define AR_HOST_TIMEOUT_LCL_CNTR    0xFFFF0000
+#define AR_HOST_TIMEOUT_LCL_CNTR_S  16
+
+#define AR_EEPROM                0x401c
+#define AR_EEPROM_ABSENT         0x00000100
+#define AR_EEPROM_CORRUPT        0x00000200
+#define AR_EEPROM_PROT_MASK      0x03FFFC00
+#define AR_EEPROM_PROT_MASK_S    10
+
+#define EEPROM_PROTECT_RP_0_31        0x0001
+#define EEPROM_PROTECT_WP_0_31        0x0002
+#define EEPROM_PROTECT_RP_32_63       0x0004
+#define EEPROM_PROTECT_WP_32_63       0x0008
+#define EEPROM_PROTECT_RP_64_127      0x0010
+#define EEPROM_PROTECT_WP_64_127      0x0020
+#define EEPROM_PROTECT_RP_128_191     0x0040
+#define EEPROM_PROTECT_WP_128_191     0x0080
+#define EEPROM_PROTECT_RP_192_255     0x0100
+#define EEPROM_PROTECT_WP_192_255     0x0200
+#define EEPROM_PROTECT_RP_256_511     0x0400
+#define EEPROM_PROTECT_WP_256_511     0x0800
+#define EEPROM_PROTECT_RP_512_1023    0x1000
+#define EEPROM_PROTECT_WP_512_1023    0x2000
+#define EEPROM_PROTECT_RP_1024_2047   0x4000
+#define EEPROM_PROTECT_WP_1024_2047   0x8000
+
+#define AR_SREV \
+	((AR_SREV_9100(ah)) ? 0x0600 : 0x4020)
+
+#define AR_SREV_ID \
+	((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF)
+#define AR_SREV_VERSION                       0x000000F0
+#define AR_SREV_VERSION_S                     4
+#define AR_SREV_REVISION                      0x00000007
+
+#define AR_SREV_ID2                           0xFFFFFFFF
+#define AR_SREV_VERSION2        	      0xFFFC0000
+#define AR_SREV_VERSION2_S                    18
+#define AR_SREV_TYPE2        	      	      0x0003F000
+#define AR_SREV_TYPE2_S                       12
+#define AR_SREV_TYPE2_CHAIN		      0x00001000
+#define AR_SREV_TYPE2_HOST_MODE		      0x00002000
+#define AR_SREV_REVISION2        	      0x00000F00
+#define AR_SREV_REVISION2_S     	      8
+
+#define AR_SREV_VERSION_5416_PCI               0xD
+#define AR_SREV_VERSION_5416_PCIE              0xC
+#define AR_SREV_REVISION_5416_10               0
+#define AR_SREV_REVISION_5416_20               1
+#define AR_SREV_REVISION_5416_22               2
+#define AR_SREV_VERSION_9100                  0x14
+#define AR_SREV_VERSION_9160        	      0x40
+#define AR_SREV_REVISION_9160_10    	      0
+#define AR_SREV_REVISION_9160_11    	      1
+#define AR_SREV_VERSION_9280                0x80
+#define AR_SREV_REVISION_9280_10            0
+#define AR_SREV_REVISION_9280_20            1
+#define AR_SREV_REVISION_9280_21            2
+#define AR_SREV_VERSION_9285                  0xC0
+#define AR_SREV_REVISION_9285_10              0
+#define AR_SREV_REVISION_9285_11              1
+#define AR_SREV_REVISION_9285_12              2
+
+#define AR_SREV_5416(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
+	 ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
+#define AR_SREV_5416_20_OR_LATER(_ah) \
+	(((AR_SREV_5416(_ah)) && \
+	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
+	 ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+#define AR_SREV_5416_22_OR_LATER(_ah) \
+	(((AR_SREV_5416(_ah)) && \
+	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
+	 ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+
+#define AR_SREV_9100(ah) \
+	((ah->hw_version.macVersion) == AR_SREV_VERSION_9100)
+#define AR_SREV_9100_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
+
+#define AR_SREV_9160(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160))
+#define AR_SREV_9160_10_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160))
+#define AR_SREV_9160_11(_ah) \
+	(AR_SREV_9160(_ah) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
+#define AR_SREV_9280(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
+#define AR_SREV_9280_10_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
+#define AR_SREV_9280_20(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
+		((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))
+#define AR_SREV_9280_20_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
+	((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)))
+
+#define AR_SREV_9285(_ah) \
+	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
+#define AR_SREV_9285_10_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
+#define AR_SREV_9285_11(_ah) \
+	(AR_SREV_9285(ah) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11))
+#define AR_SREV_9285_11_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
+	 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
+			       AR_SREV_REVISION_9285_11)))
+#define AR_SREV_9285_12(_ah) \
+	(AR_SREV_9285(ah) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12))
+#define AR_SREV_9285_12_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
+	 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
+			       AR_SREV_REVISION_9285_12)))
+
+#define AR_RADIO_SREV_MAJOR                   0xf0
+#define AR_RAD5133_SREV_MAJOR                 0xc0
+#define AR_RAD2133_SREV_MAJOR                 0xd0
+#define AR_RAD5122_SREV_MAJOR                 0xe0
+#define AR_RAD2122_SREV_MAJOR                 0xf0
+
+#define AR_AHB_MODE                           0x4024
+#define AR_AHB_EXACT_WR_EN                    0x00000000
+#define AR_AHB_BUF_WR_EN                      0x00000001
+#define AR_AHB_EXACT_RD_EN                    0x00000000
+#define AR_AHB_CACHELINE_RD_EN                0x00000002
+#define AR_AHB_PREFETCH_RD_EN                 0x00000004
+#define AR_AHB_PAGE_SIZE_1K                   0x00000000
+#define AR_AHB_PAGE_SIZE_2K                   0x00000008
+#define AR_AHB_PAGE_SIZE_4K                   0x00000010
+
+#define AR_INTR_RTC_IRQ                       0x00000001
+#define AR_INTR_MAC_IRQ                       0x00000002
+#define AR_INTR_EEP_PROT_ACCESS               0x00000004
+#define AR_INTR_MAC_AWAKE                     0x00020000
+#define AR_INTR_MAC_ASLEEP                    0x00040000
+#define AR_INTR_SPURIOUS                      0xFFFFFFFF
+
+
+#define AR_INTR_SYNC_CAUSE_CLR                0x4028
+
+#define AR_INTR_SYNC_CAUSE                    0x4028
+
+#define AR_INTR_SYNC_ENABLE                   0x402c
+#define AR_INTR_SYNC_ENABLE_GPIO              0xFFFC0000
+#define AR_INTR_SYNC_ENABLE_GPIO_S            18
+
+enum {
+	AR_INTR_SYNC_RTC_IRQ = 0x00000001,
+	AR_INTR_SYNC_MAC_IRQ = 0x00000002,
+	AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004,
+	AR_INTR_SYNC_APB_TIMEOUT = 0x00000008,
+	AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010,
+	AR_INTR_SYNC_HOST1_FATAL = 0x00000020,
+	AR_INTR_SYNC_HOST1_PERR = 0x00000040,
+	AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080,
+	AR_INTR_SYNC_RADM_CPL_EP = 0x00000100,
+	AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200,
+	AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400,
+	AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800,
+	AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000,
+	AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000,
+	AR_INTR_SYNC_PM_ACCESS = 0x00004000,
+	AR_INTR_SYNC_MAC_AWAKE = 0x00008000,
+	AR_INTR_SYNC_MAC_ASLEEP = 0x00010000,
+	AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000,
+	AR_INTR_SYNC_ALL = 0x0003FFFF,
+
+
+	AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL |
+				AR_INTR_SYNC_HOST1_PERR |
+				AR_INTR_SYNC_RADM_CPL_EP |
+				AR_INTR_SYNC_RADM_CPL_DLLP_ABORT |
+				AR_INTR_SYNC_RADM_CPL_TLP_ABORT |
+				AR_INTR_SYNC_RADM_CPL_ECRC_ERR |
+				AR_INTR_SYNC_RADM_CPL_TIMEOUT |
+				AR_INTR_SYNC_LOCAL_TIMEOUT |
+				AR_INTR_SYNC_MAC_SLEEP_ACCESS),
+
+	AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
+
+};
+
+#define AR_INTR_ASYNC_MASK                       0x4030
+#define AR_INTR_ASYNC_MASK_GPIO                  0xFFFC0000
+#define AR_INTR_ASYNC_MASK_GPIO_S                18
+
+#define AR_INTR_SYNC_MASK                        0x4034
+#define AR_INTR_SYNC_MASK_GPIO                   0xFFFC0000
+#define AR_INTR_SYNC_MASK_GPIO_S                 18
+
+#define AR_INTR_ASYNC_CAUSE_CLR                  0x4038
+#define AR_INTR_ASYNC_CAUSE                      0x4038
+
+#define AR_INTR_ASYNC_ENABLE                     0x403c
+#define AR_INTR_ASYNC_ENABLE_GPIO                0xFFFC0000
+#define AR_INTR_ASYNC_ENABLE_GPIO_S              18
+
+#define AR_PCIE_SERDES                           0x4040
+#define AR_PCIE_SERDES2                          0x4044
+#define AR_PCIE_PM_CTRL                          0x4014
+#define AR_PCIE_PM_CTRL_ENA                      0x00080000
+
+#define AR_NUM_GPIO                              14
+#define AR928X_NUM_GPIO                          10
+#define AR9285_NUM_GPIO                          12
+
+#define AR_GPIO_IN_OUT                           0x4048
+#define AR_GPIO_IN_VAL                           0x0FFFC000
+#define AR_GPIO_IN_VAL_S                         14
+#define AR928X_GPIO_IN_VAL                       0x000FFC00
+#define AR928X_GPIO_IN_VAL_S                     10
+#define AR9285_GPIO_IN_VAL                       0x00FFF000
+#define AR9285_GPIO_IN_VAL_S                     12
+
+#define AR_GPIO_OE_OUT                           0x404c
+#define AR_GPIO_OE_OUT_DRV                       0x3
+#define AR_GPIO_OE_OUT_DRV_NO                    0x0
+#define AR_GPIO_OE_OUT_DRV_LOW                   0x1
+#define AR_GPIO_OE_OUT_DRV_HI                    0x2
+#define AR_GPIO_OE_OUT_DRV_ALL                   0x3
+
+#define AR_GPIO_INTR_POL                         0x4050
+#define AR_GPIO_INTR_POL_VAL                     0x00001FFF
+#define AR_GPIO_INTR_POL_VAL_S                   0
+
+#define AR_GPIO_INPUT_EN_VAL                     0x4054
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF     0x00000004
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S       2
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF    0x00000008
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S      3
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF       0x00000010
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
+#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000
+#define AR_GPIO_JTAG_DISABLE                     0x00020000
+
+#define AR_GPIO_INPUT_MUX1                       0x4058
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE             0x000f0000
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S           16
+
+#define AR_GPIO_INPUT_MUX2                       0x405c
+#define AR_GPIO_INPUT_MUX2_CLK25                 0x0000000f
+#define AR_GPIO_INPUT_MUX2_CLK25_S               0
+#define AR_GPIO_INPUT_MUX2_RFSILENT              0x000000f0
+#define AR_GPIO_INPUT_MUX2_RFSILENT_S            4
+#define AR_GPIO_INPUT_MUX2_RTC_RESET             0x00000f00
+#define AR_GPIO_INPUT_MUX2_RTC_RESET_S           8
+
+#define AR_GPIO_OUTPUT_MUX1                      0x4060
+#define AR_GPIO_OUTPUT_MUX2                      0x4064
+#define AR_GPIO_OUTPUT_MUX3                      0x4068
+
+#define AR_INPUT_STATE                           0x406c
+
+#define AR_EEPROM_STATUS_DATA                    0x407c
+#define AR_EEPROM_STATUS_DATA_VAL                0x0000ffff
+#define AR_EEPROM_STATUS_DATA_VAL_S              0
+#define AR_EEPROM_STATUS_DATA_BUSY               0x00010000
+#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS        0x00020000
+#define AR_EEPROM_STATUS_DATA_PROT_ACCESS        0x00040000
+#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS      0x00080000
+
+#define AR_OBS                  0x4080
+
+#define AR_PCIE_MSI                              0x4094
+#define AR_PCIE_MSI_ENABLE                       0x00000001
+
+
+#define AR_RTC_9160_PLL_DIV	0x000003ff
+#define AR_RTC_9160_PLL_DIV_S   0
+#define AR_RTC_9160_PLL_REFDIV  0x00003C00
+#define AR_RTC_9160_PLL_REFDIV_S 10
+#define AR_RTC_9160_PLL_CLKSEL	0x0000C000
+#define AR_RTC_9160_PLL_CLKSEL_S 14
+
+#define AR_RTC_BASE             0x00020000
+#define AR_RTC_RC \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000)
+#define AR_RTC_RC_M		0x00000003
+#define AR_RTC_RC_MAC_WARM      0x00000001
+#define AR_RTC_RC_MAC_COLD      0x00000002
+#define AR_RTC_RC_COLD_RESET    0x00000004
+#define AR_RTC_RC_WARM_RESET    0x00000008
+
+#define AR_RTC_PLL_CONTROL \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
+
+#define AR_RTC_PLL_DIV          0x0000001f
+#define AR_RTC_PLL_DIV_S        0
+#define AR_RTC_PLL_DIV2         0x00000020
+#define AR_RTC_PLL_REFDIV_5     0x000000c0
+#define AR_RTC_PLL_CLKSEL       0x00000300
+#define AR_RTC_PLL_CLKSEL_S     8
+
+#define AR_RTC_RESET \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
+#define AR_RTC_RESET_EN		(0x00000001)
+
+#define AR_RTC_STATUS \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044)
+
+#define AR_RTC_STATUS_M \
+	((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f)
+
+#define AR_RTC_PM_STATUS_M      0x0000000f
+
+#define AR_RTC_STATUS_SHUTDOWN  0x00000001
+#define AR_RTC_STATUS_ON        0x00000002
+#define AR_RTC_STATUS_SLEEP     0x00000004
+#define AR_RTC_STATUS_WAKEUP    0x00000008
+
+#define AR_RTC_SLEEP_CLK \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)
+#define AR_RTC_FORCE_DERIVED_CLK    0x2
+
+#define AR_RTC_FORCE_WAKE \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c)
+#define AR_RTC_FORCE_WAKE_EN        0x00000001
+#define AR_RTC_FORCE_WAKE_ON_INT    0x00000002
+
+
+#define AR_RTC_INTR_CAUSE \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050)
+
+#define AR_RTC_INTR_ENABLE \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054)
+
+#define AR_RTC_INTR_MASK \
+	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058)
+
+/* RTC_DERIVED_* - only for AR9100 */
+
+#define AR_RTC_DERIVED_CLK           (AR_RTC_BASE + 0x0038)
+#define AR_RTC_DERIVED_CLK_PERIOD    0x0000fffe
+#define AR_RTC_DERIVED_CLK_PERIOD_S  1
+
+#define	AR_SEQ_MASK	0x8060
+
+#define AR_AN_RF2G1_CH0         0x7810
+#define AR_AN_RF2G1_CH0_OB      0x03800000
+#define AR_AN_RF2G1_CH0_OB_S    23
+#define AR_AN_RF2G1_CH0_DB      0x1C000000
+#define AR_AN_RF2G1_CH0_DB_S    26
+
+#define AR_AN_RF5G1_CH0         0x7818
+#define AR_AN_RF5G1_CH0_OB5     0x00070000
+#define AR_AN_RF5G1_CH0_OB5_S   16
+#define AR_AN_RF5G1_CH0_DB5     0x00380000
+#define AR_AN_RF5G1_CH0_DB5_S   19
+
+#define AR_AN_RF2G1_CH1         0x7834
+#define AR_AN_RF2G1_CH1_OB      0x03800000
+#define AR_AN_RF2G1_CH1_OB_S    23
+#define AR_AN_RF2G1_CH1_DB      0x1C000000
+#define AR_AN_RF2G1_CH1_DB_S    26
+
+#define AR_AN_RF5G1_CH1         0x783C
+#define AR_AN_RF5G1_CH1_OB5     0x00070000
+#define AR_AN_RF5G1_CH1_OB5_S   16
+#define AR_AN_RF5G1_CH1_DB5     0x00380000
+#define AR_AN_RF5G1_CH1_DB5_S   19
+
+#define AR_AN_TOP1                  0x7890
+#define AR_AN_TOP1_DACIPMODE	    0x00040000
+#define AR_AN_TOP1_DACIPMODE_S	    18
+
+#define AR_AN_TOP2                  0x7894
+#define AR_AN_TOP2_XPABIAS_LVL      0xC0000000
+#define AR_AN_TOP2_XPABIAS_LVL_S    30
+#define AR_AN_TOP2_LOCALBIAS        0x00200000
+#define AR_AN_TOP2_LOCALBIAS_S      21
+#define AR_AN_TOP2_PWDCLKIND        0x00400000
+#define AR_AN_TOP2_PWDCLKIND_S      22
+
+#define AR_AN_SYNTH9            0x7868
+#define AR_AN_SYNTH9_REFDIVA    0xf8000000
+#define AR_AN_SYNTH9_REFDIVA_S  27
+
+#define AR9285_AN_RF2G1              0x7820
+#define AR9285_AN_RF2G1_ENPACAL      0x00000800
+#define AR9285_AN_RF2G1_ENPACAL_S    11
+#define AR9285_AN_RF2G1_PDPADRV1     0x02000000
+#define AR9285_AN_RF2G1_PDPADRV1_S   25
+#define AR9285_AN_RF2G1_PDPADRV2     0x01000000
+#define AR9285_AN_RF2G1_PDPADRV2_S   24
+#define AR9285_AN_RF2G1_PDPAOUT      0x00800000
+#define AR9285_AN_RF2G1_PDPAOUT_S    23
+
+
+#define AR9285_AN_RF2G2              0x7824
+#define AR9285_AN_RF2G2_OFFCAL       0x00001000
+#define AR9285_AN_RF2G2_OFFCAL_S     12
+
+#define AR9285_AN_RF2G3             0x7828
+#define AR9285_AN_RF2G3_PDVCCOMP    0x02000000
+#define AR9285_AN_RF2G3_PDVCCOMP_S  25
+#define AR9285_AN_RF2G3_OB_0    0x00E00000
+#define AR9285_AN_RF2G3_OB_0_S    21
+#define AR9285_AN_RF2G3_OB_1    0x001C0000
+#define AR9285_AN_RF2G3_OB_1_S    18
+#define AR9285_AN_RF2G3_OB_2    0x00038000
+#define AR9285_AN_RF2G3_OB_2_S    15
+#define AR9285_AN_RF2G3_OB_3    0x00007000
+#define AR9285_AN_RF2G3_OB_3_S    12
+#define AR9285_AN_RF2G3_OB_4    0x00000E00
+#define AR9285_AN_RF2G3_OB_4_S    9
+
+#define AR9285_AN_RF2G3_DB1_0    0x000001C0
+#define AR9285_AN_RF2G3_DB1_0_S    6
+#define AR9285_AN_RF2G3_DB1_1    0x00000038
+#define AR9285_AN_RF2G3_DB1_1_S    3
+#define AR9285_AN_RF2G3_DB1_2    0x00000007
+#define AR9285_AN_RF2G3_DB1_2_S    0
+#define AR9285_AN_RF2G4         0x782C
+#define AR9285_AN_RF2G4_DB1_3    0xE0000000
+#define AR9285_AN_RF2G4_DB1_3_S    29
+#define AR9285_AN_RF2G4_DB1_4    0x1C000000
+#define AR9285_AN_RF2G4_DB1_4_S    26
+
+#define AR9285_AN_RF2G4_DB2_0    0x03800000
+#define AR9285_AN_RF2G4_DB2_0_S    23
+#define AR9285_AN_RF2G4_DB2_1    0x00700000
+#define AR9285_AN_RF2G4_DB2_1_S    20
+#define AR9285_AN_RF2G4_DB2_2    0x000E0000
+#define AR9285_AN_RF2G4_DB2_2_S    17
+#define AR9285_AN_RF2G4_DB2_3    0x0001C000
+#define AR9285_AN_RF2G4_DB2_3_S    14
+#define AR9285_AN_RF2G4_DB2_4    0x00003800
+#define AR9285_AN_RF2G4_DB2_4_S    11
+
+#define AR9285_AN_RF2G6                 0x7834
+#define AR9285_AN_RF2G6_CCOMP           0x00007800
+#define AR9285_AN_RF2G6_CCOMP_S         11
+#define AR9285_AN_RF2G6_OFFS            0x03f00000
+#define AR9285_AN_RF2G6_OFFS_S          20
+
+#define AR9285_AN_RF2G7                 0x7838
+#define AR9285_AN_RF2G7_PWDDB           0x00000002
+#define AR9285_AN_RF2G7_PWDDB_S         1
+#define AR9285_AN_RF2G7_PADRVGN2TAB0    0xE0000000
+#define AR9285_AN_RF2G7_PADRVGN2TAB0_S  29
+
+#define AR9285_AN_RF2G8                  0x783C
+#define AR9285_AN_RF2G8_PADRVGN2TAB0     0x0001C000
+#define AR9285_AN_RF2G8_PADRVGN2TAB0_S   14
+
+
+#define AR9285_AN_RF2G9          0x7840
+#define AR9285_AN_RXTXBB1              0x7854
+#define AR9285_AN_RXTXBB1_PDRXTXBB1    0x00000020
+#define AR9285_AN_RXTXBB1_PDRXTXBB1_S  5
+#define AR9285_AN_RXTXBB1_PDV2I        0x00000080
+#define AR9285_AN_RXTXBB1_PDV2I_S      7
+#define AR9285_AN_RXTXBB1_PDDACIF      0x00000100
+#define AR9285_AN_RXTXBB1_PDDACIF_S    8
+#define AR9285_AN_RXTXBB1_SPARE9       0x00000001
+#define AR9285_AN_RXTXBB1_SPARE9_S     0
+
+#define AR9285_AN_TOP2           0x7868
+
+#define AR9285_AN_TOP3                  0x786c
+#define AR9285_AN_TOP3_XPABIAS_LVL      0x0000000C
+#define AR9285_AN_TOP3_XPABIAS_LVL_S    2
+#define AR9285_AN_TOP3_PWDDAC           0x00800000
+#define AR9285_AN_TOP3_PWDDAC_S    23
+
+#define AR9285_AN_TOP4           0x7870
+#define AR9285_AN_TOP4_DEFAULT   0x10142c00
+
+#define AR_STA_ID0                 0x8000
+#define AR_STA_ID1                 0x8004
+#define AR_STA_ID1_SADH_MASK       0x0000FFFF
+#define AR_STA_ID1_STA_AP          0x00010000
+#define AR_STA_ID1_ADHOC           0x00020000
+#define AR_STA_ID1_PWR_SAV         0x00040000
+#define AR_STA_ID1_KSRCHDIS        0x00080000
+#define AR_STA_ID1_PCF             0x00100000
+#define AR_STA_ID1_USE_DEFANT      0x00200000
+#define AR_STA_ID1_DEFANT_UPDATE   0x00400000
+#define AR_STA_ID1_RTS_USE_DEF     0x00800000
+#define AR_STA_ID1_ACKCTS_6MB      0x01000000
+#define AR_STA_ID1_BASE_RATE_11B   0x02000000
+#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000
+#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000
+#define AR_STA_ID1_KSRCH_MODE      0x10000000
+#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000
+#define AR_STA_ID1_CBCIV_ENDIAN    0x40000000
+#define AR_STA_ID1_MCAST_KSRCH     0x80000000
+
+#define AR_BSS_ID0          0x8008
+#define AR_BSS_ID1          0x800C
+#define AR_BSS_ID1_U16       0x0000FFFF
+#define AR_BSS_ID1_AID       0x07FF0000
+#define AR_BSS_ID1_AID_S     16
+
+#define AR_BCN_RSSI_AVE      0x8010
+#define AR_BCN_RSSI_AVE_MASK 0x00000FFF
+
+#define AR_TIME_OUT         0x8014
+#define AR_TIME_OUT_ACK      0x00003FFF
+#define AR_TIME_OUT_ACK_S    0
+#define AR_TIME_OUT_CTS      0x3FFF0000
+#define AR_TIME_OUT_CTS_S    16
+
+#define AR_RSSI_THR          0x8018
+#define AR_RSSI_THR_MASK     0x000000FF
+#define AR_RSSI_THR_BM_THR   0x0000FF00
+#define AR_RSSI_THR_BM_THR_S 8
+#define AR_RSSI_BCN_WEIGHT   0x1F000000
+#define AR_RSSI_BCN_WEIGHT_S 24
+#define AR_RSSI_BCN_RSSI_RST 0x20000000
+
+#define AR_USEC              0x801c
+#define AR_USEC_USEC         0x0000007F
+#define AR_USEC_TX_LAT       0x007FC000
+#define AR_USEC_TX_LAT_S     14
+#define AR_USEC_RX_LAT       0x1F800000
+#define AR_USEC_RX_LAT_S     23
+
+#define AR_RESET_TSF        0x8020
+#define AR_RESET_TSF_ONCE   0x01000000
+
+#define AR_MAX_CFP_DUR      0x8038
+#define AR_CFP_VAL          0x0000FFFF
+
+#define AR_RX_FILTER        0x803C
+#define AR_RX_COMPR_BAR     0x00000400
+
+#define AR_MCAST_FIL0       0x8040
+#define AR_MCAST_FIL1       0x8044
+
+#define AR_DIAG_SW                  0x8048
+#define AR_DIAG_CACHE_ACK           0x00000001
+#define AR_DIAG_ACK_DIS             0x00000002
+#define AR_DIAG_CTS_DIS             0x00000004
+#define AR_DIAG_ENCRYPT_DIS         0x00000008
+#define AR_DIAG_DECRYPT_DIS         0x00000010
+#define AR_DIAG_RX_DIS              0x00000020
+#define AR_DIAG_LOOP_BACK           0x00000040
+#define AR_DIAG_CORR_FCS            0x00000080
+#define AR_DIAG_CHAN_INFO           0x00000100
+#define AR_DIAG_SCRAM_SEED          0x0001FE00
+#define AR_DIAG_SCRAM_SEED_S        8
+#define AR_DIAG_FRAME_NV0           0x00020000
+#define AR_DIAG_OBS_PT_SEL1         0x000C0000
+#define AR_DIAG_OBS_PT_SEL1_S       18
+#define AR_DIAG_FORCE_RX_CLEAR      0x00100000
+#define AR_DIAG_IGNORE_VIRT_CS      0x00200000
+#define AR_DIAG_FORCE_CH_IDLE_HIGH  0x00400000
+#define AR_DIAG_EIFS_CTRL_ENA       0x00800000
+#define AR_DIAG_DUAL_CHAIN_INFO     0x01000000
+#define AR_DIAG_RX_ABORT            0x02000000
+#define AR_DIAG_SATURATE_CYCLE_CNT  0x04000000
+#define AR_DIAG_OBS_PT_SEL2         0x08000000
+#define AR_DIAG_RX_CLEAR_CTL_LOW    0x10000000
+#define AR_DIAG_RX_CLEAR_EXT_LOW    0x20000000
+
+#define AR_TSF_L32          0x804c
+#define AR_TSF_U32          0x8050
+
+#define AR_TST_ADDAC        0x8054
+#define AR_DEF_ANTENNA      0x8058
+
+#define AR_AES_MUTE_MASK0       0x805c
+#define AR_AES_MUTE_MASK0_FC    0x0000FFFF
+#define AR_AES_MUTE_MASK0_QOS   0xFFFF0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+#define AR_AES_MUTE_MASK1       0x8060
+#define AR_AES_MUTE_MASK1_SEQ   0x0000FFFF
+#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
+
+#define AR_GATED_CLKS       0x8064
+#define AR_GATED_CLKS_TX    0x00000002
+#define AR_GATED_CLKS_RX    0x00000004
+#define AR_GATED_CLKS_REG   0x00000008
+
+#define AR_OBS_BUS_CTRL     0x8068
+#define AR_OBS_BUS_SEL_1    0x00040000
+#define AR_OBS_BUS_SEL_2    0x00080000
+#define AR_OBS_BUS_SEL_3    0x000C0000
+#define AR_OBS_BUS_SEL_4    0x08040000
+#define AR_OBS_BUS_SEL_5    0x08080000
+
+#define AR_OBS_BUS_1               0x806c
+#define AR_OBS_BUS_1_PCU           0x00000001
+#define AR_OBS_BUS_1_RX_END        0x00000002
+#define AR_OBS_BUS_1_RX_WEP        0x00000004
+#define AR_OBS_BUS_1_RX_BEACON     0x00000008
+#define AR_OBS_BUS_1_RX_FILTER     0x00000010
+#define AR_OBS_BUS_1_TX_HCF        0x00000020
+#define AR_OBS_BUS_1_QUIET_TIME    0x00000040
+#define AR_OBS_BUS_1_CHAN_IDLE     0x00000080
+#define AR_OBS_BUS_1_TX_HOLD       0x00000100
+#define AR_OBS_BUS_1_TX_FRAME      0x00000200
+#define AR_OBS_BUS_1_RX_FRAME      0x00000400
+#define AR_OBS_BUS_1_RX_CLEAR      0x00000800
+#define AR_OBS_BUS_1_WEP_STATE     0x0003F000
+#define AR_OBS_BUS_1_WEP_STATE_S   12
+#define AR_OBS_BUS_1_RX_STATE      0x01F00000
+#define AR_OBS_BUS_1_RX_STATE_S    20
+#define AR_OBS_BUS_1_TX_STATE      0x7E000000
+#define AR_OBS_BUS_1_TX_STATE_S    25
+
+#define AR_LAST_TSTP        0x8080
+#define AR_NAV              0x8084
+#define AR_RTS_OK           0x8088
+#define AR_RTS_FAIL         0x808c
+#define AR_ACK_FAIL         0x8090
+#define AR_FCS_FAIL         0x8094
+#define AR_BEACON_CNT       0x8098
+
+#define AR_SLEEP1               0x80d4
+#define AR_SLEEP1_ASSUME_DTIM   0x00080000
+#define AR_SLEEP1_CAB_TIMEOUT   0xFFE00000
+#define AR_SLEEP1_CAB_TIMEOUT_S 21
+
+#define AR_SLEEP2                   0x80d8
+#define AR_SLEEP2_BEACON_TIMEOUT    0xFFE00000
+#define AR_SLEEP2_BEACON_TIMEOUT_S  21
+
+#define AR_BSSMSKL            0x80e0
+#define AR_BSSMSKU            0x80e4
+
+#define AR_TPC                 0x80e8
+#define AR_TPC_ACK             0x0000003f
+#define AR_TPC_ACK_S           0x00
+#define AR_TPC_CTS             0x00003f00
+#define AR_TPC_CTS_S           0x08
+#define AR_TPC_CHIRP           0x003f0000
+#define AR_TPC_CHIRP_S         0x16
+
+#define AR_TFCNT           0x80ec
+#define AR_RFCNT           0x80f0
+#define AR_RCCNT           0x80f4
+#define AR_CCCNT           0x80f8
+
+#define AR_QUIET1          0x80fc
+#define AR_QUIET1_NEXT_QUIET_S         0
+#define AR_QUIET1_NEXT_QUIET_M         0x0000ffff
+#define AR_QUIET1_QUIET_ENABLE         0x00010000
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
+#define AR_QUIET2          0x8100
+#define AR_QUIET2_QUIET_PERIOD_S       0
+#define AR_QUIET2_QUIET_PERIOD_M       0x0000ffff
+#define AR_QUIET2_QUIET_DUR_S     16
+#define AR_QUIET2_QUIET_DUR       0xffff0000
+
+#define AR_TSF_PARM        0x8104
+#define AR_TSF_INCREMENT_M     0x000000ff
+#define AR_TSF_INCREMENT_S     0x00
+
+#define AR_QOS_NO_ACK              0x8108
+#define AR_QOS_NO_ACK_TWO_BIT      0x0000000f
+#define AR_QOS_NO_ACK_TWO_BIT_S    0
+#define AR_QOS_NO_ACK_BIT_OFF      0x00000070
+#define AR_QOS_NO_ACK_BIT_OFF_S    4
+#define AR_QOS_NO_ACK_BYTE_OFF     0x00000180
+#define AR_QOS_NO_ACK_BYTE_OFF_S   7
+
+#define AR_PHY_ERR         0x810c
+
+#define AR_PHY_ERR_DCHIRP      0x00000008
+#define AR_PHY_ERR_RADAR       0x00000020
+#define AR_PHY_ERR_OFDM_TIMING 0x00020000
+#define AR_PHY_ERR_CCK_TIMING  0x02000000
+
+#define AR_RXFIFO_CFG          0x8114
+
+
+#define AR_MIC_QOS_CONTROL 0x8118
+#define AR_MIC_QOS_SELECT  0x811c
+
+#define AR_PCU_MISC                0x8120
+#define AR_PCU_FORCE_BSSID_MATCH   0x00000001
+#define AR_PCU_MIC_NEW_LOC_ENA     0x00000004
+#define AR_PCU_TX_ADD_TSF          0x00000008
+#define AR_PCU_CCK_SIFS_MODE       0x00000010
+#define AR_PCU_RX_ANT_UPDT         0x00000800
+#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000
+#define AR_PCU_MISS_BCN_IN_SLEEP   0x00004000
+#define AR_PCU_BUG_12306_FIX_ENA   0x00020000
+#define AR_PCU_FORCE_QUIET_COLL    0x00040000
+#define AR_PCU_TBTT_PROTECT        0x00200000
+#define AR_PCU_CLEAR_VMF           0x01000000
+#define AR_PCU_CLEAR_BA_VALID      0x04000000
+
+
+#define AR_FILT_OFDM           0x8124
+#define AR_FILT_OFDM_COUNT     0x00FFFFFF
+
+#define AR_FILT_CCK            0x8128
+#define AR_FILT_CCK_COUNT      0x00FFFFFF
+
+#define AR_PHY_ERR_1           0x812c
+#define AR_PHY_ERR_1_COUNT     0x00FFFFFF
+#define AR_PHY_ERR_MASK_1      0x8130
+
+#define AR_PHY_ERR_2           0x8134
+#define AR_PHY_ERR_2_COUNT     0x00FFFFFF
+#define AR_PHY_ERR_MASK_2      0x8138
+
+#define AR_PHY_COUNTMAX        (3 << 22)
+#define AR_MIBCNT_INTRMASK     (3 << 22)
+
+#define AR_TSFOOR_THRESHOLD       0x813c
+#define AR_TSFOOR_THRESHOLD_VAL   0x0000FFFF
+
+#define AR_PHY_ERR_EIFS_MASK   8144
+
+#define AR_PHY_ERR_3           0x8168
+#define AR_PHY_ERR_3_COUNT     0x00FFFFFF
+#define AR_PHY_ERR_MASK_3      0x816c
+
+#define AR_TXSIFS              0x81d0
+#define AR_TXSIFS_TIME         0x000000FF
+#define AR_TXSIFS_TX_LATENCY   0x00000F00
+#define AR_TXSIFS_TX_LATENCY_S 8
+#define AR_TXSIFS_ACK_SHIFT    0x00007000
+#define AR_TXSIFS_ACK_SHIFT_S  12
+
+#define AR_TXOP_X          0x81ec
+#define AR_TXOP_X_VAL      0x000000FF
+
+
+#define AR_TXOP_0_3    0x81f0
+#define AR_TXOP_4_7    0x81f4
+#define AR_TXOP_8_11   0x81f8
+#define AR_TXOP_12_15  0x81fc
+
+
+#define AR_NEXT_TBTT_TIMER                  0x8200
+#define AR_NEXT_DMA_BEACON_ALERT            0x8204
+#define AR_NEXT_SWBA                        0x8208
+#define AR_NEXT_CFP                         0x8208
+#define AR_NEXT_HCF                         0x820C
+#define AR_NEXT_TIM                         0x8210
+#define AR_NEXT_DTIM                        0x8214
+#define AR_NEXT_QUIET_TIMER                 0x8218
+#define AR_NEXT_NDP_TIMER                   0x821C
+
+#define AR_BEACON_PERIOD                    0x8220
+#define AR_DMA_BEACON_PERIOD                0x8224
+#define AR_SWBA_PERIOD                      0x8228
+#define AR_HCF_PERIOD                       0x822C
+#define AR_TIM_PERIOD                       0x8230
+#define AR_DTIM_PERIOD                      0x8234
+#define AR_QUIET_PERIOD                     0x8238
+#define AR_NDP_PERIOD                       0x823C
+
+#define AR_TIMER_MODE                       0x8240
+#define AR_TBTT_TIMER_EN                    0x00000001
+#define AR_DBA_TIMER_EN                     0x00000002
+#define AR_SWBA_TIMER_EN                    0x00000004
+#define AR_HCF_TIMER_EN                     0x00000008
+#define AR_TIM_TIMER_EN                     0x00000010
+#define AR_DTIM_TIMER_EN                    0x00000020
+#define AR_QUIET_TIMER_EN                   0x00000040
+#define AR_NDP_TIMER_EN                     0x00000080
+#define AR_TIMER_OVERFLOW_INDEX             0x00000700
+#define AR_TIMER_OVERFLOW_INDEX_S           8
+#define AR_TIMER_THRESH                     0xFFFFF000
+#define AR_TIMER_THRESH_S                   12
+
+#define AR_SLP32_MODE                  0x8244
+#define AR_SLP32_HALF_CLK_LATENCY      0x000FFFFF
+#define AR_SLP32_ENA                   0x00100000
+#define AR_SLP32_TSF_WRITE_STATUS      0x00200000
+
+#define AR_SLP32_WAKE              0x8248
+#define AR_SLP32_WAKE_XTL_TIME     0x0000FFFF
+
+#define AR_SLP32_INC               0x824c
+#define AR_SLP32_TST_INC           0x000FFFFF
+
+#define AR_SLP_CNT         0x8250
+#define AR_SLP_CYCLE_CNT   0x8254
+
+#define AR_SLP_MIB_CTRL    0x8258
+#define AR_SLP_MIB_CLEAR   0x00000001
+#define AR_SLP_MIB_PENDING 0x00000002
+
+#define AR_2040_MODE                0x8318
+#define AR_2040_JOINED_RX_CLEAR 0x00000001
+
+
+#define AR_EXTRCCNT         0x8328
+
+#define AR_SELFGEN_MASK         0x832c
+
+#define AR_PCU_TXBUF_CTRL               0x8340
+#define AR_PCU_TXBUF_CTRL_SIZE_MASK     0x7FF
+#define AR_PCU_TXBUF_CTRL_USABLE_SIZE   0x700
+#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE   0x380
+
+#define AR_PCU_MISC_MODE2               0x8344
+#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE           0x00000002
+#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT   0x00000004
+
+#define AR_KEYTABLE_0           0x8800
+#define AR_KEYTABLE(_n)         (AR_KEYTABLE_0 + ((_n)*32))
+#define AR_KEY_CACHE_SIZE       128
+#define AR_RSVD_KEYTABLE_ENTRIES 4
+#define AR_KEY_TYPE             0x00000007
+#define AR_KEYTABLE_TYPE_40     0x00000000
+#define AR_KEYTABLE_TYPE_104    0x00000001
+#define AR_KEYTABLE_TYPE_128    0x00000003
+#define AR_KEYTABLE_TYPE_TKIP   0x00000004
+#define AR_KEYTABLE_TYPE_AES    0x00000005
+#define AR_KEYTABLE_TYPE_CCM    0x00000006
+#define AR_KEYTABLE_TYPE_CLR    0x00000007
+#define AR_KEYTABLE_ANT         0x00000008
+#define AR_KEYTABLE_VALID       0x00008000
+#define AR_KEYTABLE_KEY0(_n)    (AR_KEYTABLE(_n) + 0)
+#define AR_KEYTABLE_KEY1(_n)    (AR_KEYTABLE(_n) + 4)
+#define AR_KEYTABLE_KEY2(_n)    (AR_KEYTABLE(_n) + 8)
+#define AR_KEYTABLE_KEY3(_n)    (AR_KEYTABLE(_n) + 12)
+#define AR_KEYTABLE_KEY4(_n)    (AR_KEYTABLE(_n) + 16)
+#define AR_KEYTABLE_TYPE(_n)    (AR_KEYTABLE(_n) + 20)
+#define AR_KEYTABLE_MAC0(_n)    (AR_KEYTABLE(_n) + 24)
+#define AR_KEYTABLE_MAC1(_n)    (AR_KEYTABLE(_n) + 28)
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/virtual.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/virtual.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/virtual.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/virtual.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+struct ath9k_vif_iter_data {
+	int count;
+	u8 *addr;
+};
+
+static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath9k_vif_iter_data *iter_data = data;
+	u8 *nbuf;
+
+	nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN,
+			GFP_ATOMIC);
+	if (nbuf == NULL)
+		return;
+
+	memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN);
+	iter_data->addr = nbuf;
+	iter_data->count++;
+}
+
+void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath9k_vif_iter_data iter_data;
+	int i, j;
+	u8 mask[ETH_ALEN];
+
+	/*
+	 * Add primary MAC address even if it is not in active use since it
+	 * will be configured to the hardware as the starting point and the
+	 * BSSID mask will need to be changed if another address is active.
+	 */
+	iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
+	if (iter_data.addr) {
+		memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN);
+		iter_data.count = 1;
+	} else
+		iter_data.count = 0;
+
+	/* Get list of all active MAC addresses */
+	spin_lock_bh(&sc->wiphy_lock);
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
+						   &iter_data);
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] == NULL)
+			continue;
+		ieee80211_iterate_active_interfaces_atomic(
+			sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data);
+	}
+	spin_unlock_bh(&sc->wiphy_lock);
+
+	/* Generate an address mask to cover all active addresses */
+	memset(mask, 0, ETH_ALEN);
+	for (i = 0; i < iter_data.count; i++) {
+		u8 *a1 = iter_data.addr + i * ETH_ALEN;
+		for (j = i + 1; j < iter_data.count; j++) {
+			u8 *a2 = iter_data.addr + j * ETH_ALEN;
+			mask[0] |= a1[0] ^ a2[0];
+			mask[1] |= a1[1] ^ a2[1];
+			mask[2] |= a1[2] ^ a2[2];
+			mask[3] |= a1[3] ^ a2[3];
+			mask[4] |= a1[4] ^ a2[4];
+			mask[5] |= a1[5] ^ a2[5];
+		}
+	}
+
+	kfree(iter_data.addr);
+
+	/* Invert the mask and configure hardware */
+	sc->bssidmask[0] = ~mask[0];
+	sc->bssidmask[1] = ~mask[1];
+	sc->bssidmask[2] = ~mask[2];
+	sc->bssidmask[3] = ~mask[3];
+	sc->bssidmask[4] = ~mask[4];
+	sc->bssidmask[5] = ~mask[5];
+
+	ath9k_hw_setbssidmask(sc);
+}
+
+int ath9k_wiphy_add(struct ath_softc *sc)
+{
+	int i, error;
+	struct ath_wiphy *aphy;
+	struct ieee80211_hw *hw;
+	u8 addr[ETH_ALEN];
+
+	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops);
+	if (hw == NULL)
+		return -ENOMEM;
+
+	spin_lock_bh(&sc->wiphy_lock);
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] == NULL)
+			break;
+	}
+
+	if (i == sc->num_sec_wiphy) {
+		/* No empty slot available; increase array length */
+		struct ath_wiphy **n;
+		n = krealloc(sc->sec_wiphy,
+			     (sc->num_sec_wiphy + 1) *
+			     sizeof(struct ath_wiphy *),
+			     GFP_ATOMIC);
+		if (n == NULL) {
+			spin_unlock_bh(&sc->wiphy_lock);
+			ieee80211_free_hw(hw);
+			return -ENOMEM;
+		}
+		n[i] = NULL;
+		sc->sec_wiphy = n;
+		sc->num_sec_wiphy++;
+	}
+
+	SET_IEEE80211_DEV(hw, sc->dev);
+
+	aphy = hw->priv;
+	aphy->sc = sc;
+	aphy->hw = hw;
+	sc->sec_wiphy[i] = aphy;
+	spin_unlock_bh(&sc->wiphy_lock);
+
+	memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN);
+	addr[0] |= 0x02; /* Locally managed address */
+	/*
+	 * XOR virtual wiphy index into the least significant bits to generate
+	 * a different MAC address for each virtual wiphy.
+	 */
+	addr[5] ^= i & 0xff;
+	addr[4] ^= (i & 0xff00) >> 8;
+	addr[3] ^= (i & 0xff0000) >> 16;
+
+	SET_IEEE80211_PERM_ADDR(hw, addr);
+
+	ath_set_hw_capab(sc, hw);
+
+	error = ieee80211_register_hw(hw);
+
+	if (error == 0) {
+		/* Make sure wiphy scheduler is started (if enabled) */
+		ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int);
+	}
+
+	return error;
+}
+
+int ath9k_wiphy_del(struct ath_wiphy *aphy)
+{
+	struct ath_softc *sc = aphy->sc;
+	int i;
+
+	spin_lock_bh(&sc->wiphy_lock);
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (aphy == sc->sec_wiphy[i]) {
+			sc->sec_wiphy[i] = NULL;
+			spin_unlock_bh(&sc->wiphy_lock);
+			ieee80211_unregister_hw(aphy->hw);
+			ieee80211_free_hw(aphy->hw);
+			return 0;
+		}
+	}
+	spin_unlock_bh(&sc->wiphy_lock);
+	return -ENOENT;
+}
+
+static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
+			       struct ieee80211_vif *vif, const u8 *bssid,
+			       int ps)
+{
+	struct ath_softc *sc = aphy->sc;
+	struct ath_tx_control txctl;
+	struct sk_buff *skb;
+	struct ieee80211_hdr *hdr;
+	__le16 fc;
+	struct ieee80211_tx_info *info;
+
+	skb = dev_alloc_skb(24);
+	if (skb == NULL)
+		return -ENOMEM;
+	hdr = (struct ieee80211_hdr *) skb_put(skb, 24);
+	memset(hdr, 0, 24);
+	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
+			 IEEE80211_FCTL_TODS);
+	if (ps)
+		fc |= cpu_to_le16(IEEE80211_FCTL_PM);
+	hdr->frame_control = fc;
+	memcpy(hdr->addr1, bssid, ETH_ALEN);
+	memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN);
+	memcpy(hdr->addr3, bssid, ETH_ALEN);
+
+	info = IEEE80211_SKB_CB(skb);
+	memset(info, 0, sizeof(*info));
+	info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS;
+	info->control.vif = vif;
+	info->control.rates[0].idx = 0;
+	info->control.rates[0].count = 4;
+	info->control.rates[1].idx = -1;
+
+	memset(&txctl, 0, sizeof(struct ath_tx_control));
+	txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]];
+	txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE;
+
+	if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
+		goto exit;
+
+	return 0;
+exit:
+	dev_kfree_skb_any(skb);
+	return -1;
+}
+
+static bool __ath9k_wiphy_pausing(struct ath_softc *sc)
+{
+	int i;
+	if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING)
+		return true;
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] &&
+		    sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING)
+			return true;
+	}
+	return false;
+}
+
+static bool ath9k_wiphy_pausing(struct ath_softc *sc)
+{
+	bool ret;
+	spin_lock_bh(&sc->wiphy_lock);
+	ret = __ath9k_wiphy_pausing(sc);
+	spin_unlock_bh(&sc->wiphy_lock);
+	return ret;
+}
+
+static bool __ath9k_wiphy_scanning(struct ath_softc *sc)
+{
+	int i;
+	if (sc->pri_wiphy->state == ATH_WIPHY_SCAN)
+		return true;
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] &&
+		    sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN)
+			return true;
+	}
+	return false;
+}
+
+bool ath9k_wiphy_scanning(struct ath_softc *sc)
+{
+	bool ret;
+	spin_lock_bh(&sc->wiphy_lock);
+	ret = __ath9k_wiphy_scanning(sc);
+	spin_unlock_bh(&sc->wiphy_lock);
+	return ret;
+}
+
+static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy);
+
+/* caller must hold wiphy_lock */
+static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy)
+{
+	if (aphy == NULL)
+		return;
+	if (aphy->chan_idx != aphy->sc->chan_idx)
+		return; /* wiphy not on the selected channel */
+	__ath9k_wiphy_unpause(aphy);
+}
+
+static void ath9k_wiphy_unpause_channel(struct ath_softc *sc)
+{
+	int i;
+	spin_lock_bh(&sc->wiphy_lock);
+	__ath9k_wiphy_unpause_ch(sc->pri_wiphy);
+	for (i = 0; i < sc->num_sec_wiphy; i++)
+		__ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]);
+	spin_unlock_bh(&sc->wiphy_lock);
+}
+
+void ath9k_wiphy_chan_work(struct work_struct *work)
+{
+	struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
+	struct ath_wiphy *aphy = sc->next_wiphy;
+
+	if (aphy == NULL)
+		return;
+
+	/*
+	 * All pending interfaces paused; ready to change
+	 * channels.
+	 */
+
+	/* Change channels */
+	mutex_lock(&sc->mutex);
+	/* XXX: remove me eventually */
+	ath9k_update_ichannel(sc, aphy->hw,
+			      &sc->sc_ah->channels[sc->chan_idx]);
+	ath_update_chainmask(sc, sc->chan_is_ht);
+	if (ath_set_channel(sc, aphy->hw,
+			    &sc->sc_ah->channels[sc->chan_idx]) < 0) {
+		printk(KERN_DEBUG "ath9k: Failed to set channel for new "
+		       "virtual wiphy\n");
+		mutex_unlock(&sc->mutex);
+		return;
+	}
+	mutex_unlock(&sc->mutex);
+
+	ath9k_wiphy_unpause_channel(sc);
+}
+
+/*
+ * ath9k version of ieee80211_tx_status() for TX frames that are generated
+ * internally in the driver.
+ */
+void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+
+	if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE &&
+	    aphy->state == ATH_WIPHY_PAUSING) {
+		if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
+			printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
+			       "frame\n", wiphy_name(hw->wiphy));
+			/*
+			 * The AP did not reply; ignore this to allow us to
+			 * continue.
+			 */
+		}
+		aphy->state = ATH_WIPHY_PAUSED;
+		if (!ath9k_wiphy_pausing(aphy->sc)) {
+			/*
+			 * Drop from tasklet to work to allow mutex for channel
+			 * change.
+			 */
+			queue_work(aphy->sc->hw->workqueue,
+				   &aphy->sc->chan_work);
+		}
+	}
+
+	kfree(tx_info_priv);
+	tx_info->rate_driver_data[0] = NULL;
+
+	dev_kfree_skb(skb);
+}
+
+static void ath9k_mark_paused(struct ath_wiphy *aphy)
+{
+	struct ath_softc *sc = aphy->sc;
+	aphy->state = ATH_WIPHY_PAUSED;
+	if (!__ath9k_wiphy_pausing(sc))
+		queue_work(sc->hw->workqueue, &sc->chan_work);
+}
+
+static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath_wiphy *aphy = data;
+	struct ath_vif *avp = (void *) vif->drv_priv;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		if (!vif->bss_conf.assoc) {
+			ath9k_mark_paused(aphy);
+			break;
+		}
+		/* TODO: could avoid this if already in PS mode */
+		if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) {
+			printk(KERN_DEBUG "%s: failed to send PS nullfunc\n",
+			       __func__);
+			ath9k_mark_paused(aphy);
+		}
+		break;
+	case NL80211_IFTYPE_AP:
+		/* Beacon transmission is paused by aphy->state change */
+		ath9k_mark_paused(aphy);
+		break;
+	default:
+		break;
+	}
+}
+
+/* caller must hold wiphy_lock */
+static int __ath9k_wiphy_pause(struct ath_wiphy *aphy)
+{
+	ieee80211_stop_queues(aphy->hw);
+	aphy->state = ATH_WIPHY_PAUSING;
+	/*
+	 * TODO: handle PAUSING->PAUSED for the case where there are multiple
+	 * active vifs (now we do it on the first vif getting ready; should be
+	 * on the last)
+	 */
+	ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter,
+						   aphy);
+	return 0;
+}
+
+int ath9k_wiphy_pause(struct ath_wiphy *aphy)
+{
+	int ret;
+	spin_lock_bh(&aphy->sc->wiphy_lock);
+	ret = __ath9k_wiphy_pause(aphy);
+	spin_unlock_bh(&aphy->sc->wiphy_lock);
+	return ret;
+}
+
+static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath_wiphy *aphy = data;
+	struct ath_vif *avp = (void *) vif->drv_priv;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		if (!vif->bss_conf.assoc)
+			break;
+		ath9k_send_nullfunc(aphy, vif, avp->bssid, 0);
+		break;
+	case NL80211_IFTYPE_AP:
+		/* Beacon transmission is re-enabled by aphy->state change */
+		break;
+	default:
+		break;
+	}
+}
+
+/* caller must hold wiphy_lock */
+static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy)
+{
+	ieee80211_iterate_active_interfaces_atomic(aphy->hw,
+						   ath9k_unpause_iter, aphy);
+	aphy->state = ATH_WIPHY_ACTIVE;
+	ieee80211_wake_queues(aphy->hw);
+	return 0;
+}
+
+int ath9k_wiphy_unpause(struct ath_wiphy *aphy)
+{
+	int ret;
+	spin_lock_bh(&aphy->sc->wiphy_lock);
+	ret = __ath9k_wiphy_unpause(aphy);
+	spin_unlock_bh(&aphy->sc->wiphy_lock);
+	return ret;
+}
+
+static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc)
+{
+	int i;
+	if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE)
+		sc->pri_wiphy->state = ATH_WIPHY_PAUSED;
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] &&
+		    sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE)
+			sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED;
+	}
+}
+
+/* caller must hold wiphy_lock */
+static void __ath9k_wiphy_pause_all(struct ath_softc *sc)
+{
+	int i;
+	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
+		__ath9k_wiphy_pause(sc->pri_wiphy);
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] &&
+		    sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
+			__ath9k_wiphy_pause(sc->sec_wiphy[i]);
+	}
+}
+
+int ath9k_wiphy_select(struct ath_wiphy *aphy)
+{
+	struct ath_softc *sc = aphy->sc;
+	bool now;
+
+	spin_lock_bh(&sc->wiphy_lock);
+	if (__ath9k_wiphy_scanning(sc)) {
+		/*
+		 * For now, we are using mac80211 sw scan and it expects to
+		 * have full control over channel changes, so avoid wiphy
+		 * scheduling during a scan. This could be optimized if the
+		 * scanning control were moved into the driver.
+		 */
+		spin_unlock_bh(&sc->wiphy_lock);
+		return -EBUSY;
+	}
+	if (__ath9k_wiphy_pausing(sc)) {
+		if (sc->wiphy_select_failures == 0)
+			sc->wiphy_select_first_fail = jiffies;
+		sc->wiphy_select_failures++;
+		if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2))
+		{
+			printk(KERN_DEBUG "ath9k: Previous wiphy select timed "
+			       "out; disable/enable hw to recover\n");
+			__ath9k_wiphy_mark_all_paused(sc);
+			/*
+			 * TODO: this workaround to fix hardware is unlikely to
+			 * be specific to virtual wiphy changes. It can happen
+			 * on normal channel change, too, and as such, this
+			 * should really be made more generic. For example,
+			 * tricker radio disable/enable on GTT interrupt burst
+			 * (say, 10 GTT interrupts received without any TX
+			 * frame being completed)
+			 */
+			spin_unlock_bh(&sc->wiphy_lock);
+			ath_radio_disable(sc);
+			ath_radio_enable(sc);
+			queue_work(aphy->sc->hw->workqueue,
+				   &aphy->sc->chan_work);
+			return -EBUSY; /* previous select still in progress */
+		}
+		spin_unlock_bh(&sc->wiphy_lock);
+		return -EBUSY; /* previous select still in progress */
+	}
+	sc->wiphy_select_failures = 0;
+
+	/* Store the new channel */
+	sc->chan_idx = aphy->chan_idx;
+	sc->chan_is_ht = aphy->chan_is_ht;
+	sc->next_wiphy = aphy;
+
+	__ath9k_wiphy_pause_all(sc);
+	now = !__ath9k_wiphy_pausing(aphy->sc);
+	spin_unlock_bh(&sc->wiphy_lock);
+
+	if (now) {
+		/* Ready to request channel change immediately */
+		queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work);
+	}
+
+	/*
+	 * wiphys will be unpaused in ath9k_tx_status() once channel has been
+	 * changed if any wiphy needs time to become paused.
+	 */
+
+	return 0;
+}
+
+bool ath9k_wiphy_started(struct ath_softc *sc)
+{
+	int i;
+	spin_lock_bh(&sc->wiphy_lock);
+	if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
+		spin_unlock_bh(&sc->wiphy_lock);
+		return true;
+	}
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] &&
+		    sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) {
+			spin_unlock_bh(&sc->wiphy_lock);
+			return true;
+		}
+	}
+	spin_unlock_bh(&sc->wiphy_lock);
+	return false;
+}
+
+static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy,
+				   struct ath_wiphy *selected)
+{
+	if (selected->state == ATH_WIPHY_SCAN) {
+		if (aphy == selected)
+			return;
+		/*
+		 * Pause all other wiphys for the duration of the scan even if
+		 * they are on the current channel now.
+		 */
+	} else if (aphy->chan_idx == selected->chan_idx)
+		return;
+	aphy->state = ATH_WIPHY_PAUSED;
+	ieee80211_stop_queues(aphy->hw);
+}
+
+void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
+				  struct ath_wiphy *selected)
+{
+	int i;
+	spin_lock_bh(&sc->wiphy_lock);
+	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
+		ath9k_wiphy_pause_chan(sc->pri_wiphy, selected);
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		if (sc->sec_wiphy[i] &&
+		    sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
+			ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected);
+	}
+	spin_unlock_bh(&sc->wiphy_lock);
+}
+
+void ath9k_wiphy_work(struct work_struct *work)
+{
+	struct ath_softc *sc = container_of(work, struct ath_softc,
+					    wiphy_work.work);
+	struct ath_wiphy *aphy = NULL;
+	bool first = true;
+
+	spin_lock_bh(&sc->wiphy_lock);
+
+	if (sc->wiphy_scheduler_int == 0) {
+		/* wiphy scheduler is disabled */
+		spin_unlock_bh(&sc->wiphy_lock);
+		return;
+	}
+
+try_again:
+	sc->wiphy_scheduler_index++;
+	while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) {
+		aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1];
+		if (aphy && aphy->state != ATH_WIPHY_INACTIVE)
+			break;
+
+		sc->wiphy_scheduler_index++;
+		aphy = NULL;
+	}
+	if (aphy == NULL) {
+		sc->wiphy_scheduler_index = 0;
+		if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) {
+			if (first) {
+				first = false;
+				goto try_again;
+			}
+			/* No wiphy is ready to be scheduled */
+		} else
+			aphy = sc->pri_wiphy;
+	}
+
+	spin_unlock_bh(&sc->wiphy_lock);
+
+	if (aphy &&
+	    aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN &&
+	    ath9k_wiphy_select(aphy)) {
+		printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy "
+		       "change\n");
+	}
+
+	queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
+			   sc->wiphy_scheduler_int);
+}
+
+void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
+{
+	cancel_delayed_work_sync(&sc->wiphy_work);
+	sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
+	if (sc->wiphy_scheduler_int)
+		queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
+				   sc->wiphy_scheduler_int);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/xmit.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/xmit.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/ath9k/xmit.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,2190 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+#define BITS_PER_BYTE           8
+#define OFDM_PLCP_BITS          22
+#define HT_RC_2_MCS(_rc)        ((_rc) & 0x0f)
+#define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
+#define L_STF                   8
+#define L_LTF                   8
+#define L_SIG                   4
+#define HT_SIG                  8
+#define HT_STF                  4
+#define HT_LTF(_ns)             (4 * (_ns))
+#define SYMBOL_TIME(_ns)        ((_ns) << 2) /* ns * 4 us */
+#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5)  /* ns * 3.6 us */
+#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
+#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
+
+#define OFDM_SIFS_TIME    	    16
+
+static u32 bits_per_symbol[][2] = {
+	/* 20MHz 40MHz */
+	{    26,   54 },     /*  0: BPSK */
+	{    52,  108 },     /*  1: QPSK 1/2 */
+	{    78,  162 },     /*  2: QPSK 3/4 */
+	{   104,  216 },     /*  3: 16-QAM 1/2 */
+	{   156,  324 },     /*  4: 16-QAM 3/4 */
+	{   208,  432 },     /*  5: 64-QAM 2/3 */
+	{   234,  486 },     /*  6: 64-QAM 3/4 */
+	{   260,  540 },     /*  7: 64-QAM 5/6 */
+	{    52,  108 },     /*  8: BPSK */
+	{   104,  216 },     /*  9: QPSK 1/2 */
+	{   156,  324 },     /* 10: QPSK 3/4 */
+	{   208,  432 },     /* 11: 16-QAM 1/2 */
+	{   312,  648 },     /* 12: 16-QAM 3/4 */
+	{   416,  864 },     /* 13: 64-QAM 2/3 */
+	{   468,  972 },     /* 14: 64-QAM 3/4 */
+	{   520, 1080 },     /* 15: 64-QAM 5/6 */
+};
+
+#define IS_HT_RATE(_rate)     ((_rate) & 0x80)
+
+static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
+				  struct ath_atx_tid *tid,
+				  struct list_head *bf_head);
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+				struct list_head *bf_q,
+				int txok, int sendbar);
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+			     struct list_head *head);
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf);
+static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
+			      int txok);
+static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
+			     int nbad, int txok, bool update_rc);
+
+/*********************/
+/* Aggregation logic */
+/*********************/
+
+static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
+{
+	struct ath_atx_tid *tid;
+	tid = ATH_AN_2_TID(an, tidno);
+
+	if (tid->state & AGGR_ADDBA_COMPLETE ||
+	    tid->state & AGGR_ADDBA_PROGRESS)
+		return 1;
+	else
+		return 0;
+}
+
+static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+{
+	struct ath_atx_ac *ac = tid->ac;
+
+	if (tid->paused)
+		return;
+
+	if (tid->sched)
+		return;
+
+	tid->sched = true;
+	list_add_tail(&tid->list, &ac->tid_q);
+
+	if (ac->sched)
+		return;
+
+	ac->sched = true;
+	list_add_tail(&ac->list, &txq->axq_acq);
+}
+
+static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+{
+	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+
+	spin_lock_bh(&txq->axq_lock);
+	tid->paused++;
+	spin_unlock_bh(&txq->axq_lock);
+}
+
+static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+{
+	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+
+	ASSERT(tid->paused > 0);
+	spin_lock_bh(&txq->axq_lock);
+
+	tid->paused--;
+
+	if (tid->paused > 0)
+		goto unlock;
+
+	if (list_empty(&tid->buf_q))
+		goto unlock;
+
+	ath_tx_queue_tid(txq, tid);
+	ath_txq_schedule(sc, txq);
+unlock:
+	spin_unlock_bh(&txq->axq_lock);
+}
+
+static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+{
+	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+	struct ath_buf *bf;
+	struct list_head bf_head;
+	INIT_LIST_HEAD(&bf_head);
+
+	ASSERT(tid->paused > 0);
+	spin_lock_bh(&txq->axq_lock);
+
+	tid->paused--;
+
+	if (tid->paused > 0) {
+		spin_unlock_bh(&txq->axq_lock);
+		return;
+	}
+
+	while (!list_empty(&tid->buf_q)) {
+		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+		ASSERT(!bf_isretried(bf));
+		list_move_tail(&bf->list, &bf_head);
+		ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
+	}
+
+	spin_unlock_bh(&txq->axq_lock);
+}
+
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+			      int seqno)
+{
+	int index, cindex;
+
+	index  = ATH_BA_INDEX(tid->seq_start, seqno);
+	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+
+	tid->tx_buf[cindex] = NULL;
+
+	while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
+		INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+		INCR(tid->baw_head, ATH_TID_MAX_BUFS);
+	}
+}
+
+static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+			     struct ath_buf *bf)
+{
+	int index, cindex;
+
+	if (bf_isretried(bf))
+		return;
+
+	index  = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
+	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+
+	ASSERT(tid->tx_buf[cindex] == NULL);
+	tid->tx_buf[cindex] = bf;
+
+	if (index >= ((tid->baw_tail - tid->baw_head) &
+		(ATH_TID_MAX_BUFS - 1))) {
+		tid->baw_tail = cindex;
+		INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
+	}
+}
+
+/*
+ * TODO: For frame(s) that are in the retry state, we will reuse the
+ * sequence number(s) without setting the retry bit. The
+ * alternative is to give up on these and BAR the receiver's window
+ * forward.
+ */
+static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
+			  struct ath_atx_tid *tid)
+
+{
+	struct ath_buf *bf;
+	struct list_head bf_head;
+	INIT_LIST_HEAD(&bf_head);
+
+	for (;;) {
+		if (list_empty(&tid->buf_q))
+			break;
+
+		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+		list_move_tail(&bf->list, &bf_head);
+
+		if (bf_isretried(bf))
+			ath_tx_update_baw(sc, tid, bf->bf_seqno);
+
+		spin_unlock(&txq->axq_lock);
+		ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+		spin_lock(&txq->axq_lock);
+	}
+
+	tid->seq_next = tid->seq_start;
+	tid->baw_tail = tid->baw_head;
+}
+
+static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
+{
+	struct sk_buff *skb;
+	struct ieee80211_hdr *hdr;
+
+	bf->bf_state.bf_type |= BUF_RETRY;
+	bf->bf_retries++;
+
+	skb = bf->bf_mpdu;
+	hdr = (struct ieee80211_hdr *)skb->data;
+	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
+}
+
+static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
+{
+	struct ath_buf *tbf;
+
+	spin_lock_bh(&sc->tx.txbuflock);
+	ASSERT(!list_empty((&sc->tx.txbuf)));
+	tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+	list_del(&tbf->list);
+	spin_unlock_bh(&sc->tx.txbuflock);
+
+	ATH_TXBUF_RESET(tbf);
+
+	tbf->bf_mpdu = bf->bf_mpdu;
+	tbf->bf_buf_addr = bf->bf_buf_addr;
+	*(tbf->bf_desc) = *(bf->bf_desc);
+	tbf->bf_state = bf->bf_state;
+	tbf->bf_dmacontext = bf->bf_dmacontext;
+
+	return tbf;
+}
+
+static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+				 struct ath_buf *bf, struct list_head *bf_q,
+				 int txok)
+{
+	struct ath_node *an = NULL;
+	struct sk_buff *skb;
+	struct ieee80211_sta *sta;
+	struct ieee80211_hdr *hdr;
+	struct ath_atx_tid *tid = NULL;
+	struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
+	struct ath_desc *ds = bf_last->bf_desc;
+	struct list_head bf_head, bf_pending;
+	u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
+	u32 ba[WME_BA_BMP_SIZE >> 5];
+	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
+	bool rc_update = true;
+
+	skb = bf->bf_mpdu;
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	rcu_read_lock();
+
+	sta = ieee80211_find_sta(sc->hw, hdr->addr1);
+	if (!sta) {
+		rcu_read_unlock();
+		return;
+	}
+
+	an = (struct ath_node *)sta->drv_priv;
+	tid = ATH_AN_2_TID(an, bf->bf_tidno);
+
+	isaggr = bf_isaggr(bf);
+	memset(ba, 0, WME_BA_BMP_SIZE >> 3);
+
+	if (isaggr && txok) {
+		if (ATH_DS_TX_BA(ds)) {
+			seq_st = ATH_DS_BA_SEQ(ds);
+			memcpy(ba, ATH_DS_BA_BITMAP(ds),
+			       WME_BA_BMP_SIZE >> 3);
+		} else {
+			/*
+			 * AR5416 can become deaf/mute when BA
+			 * issue happens. Chip needs to be reset.
+			 * But AP code may have sychronization issues
+			 * when perform internal reset in this routine.
+			 * Only enable reset in STA mode for now.
+			 */
+			if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION)
+				needreset = 1;
+		}
+	}
+
+	INIT_LIST_HEAD(&bf_pending);
+	INIT_LIST_HEAD(&bf_head);
+
+	nbad = ath_tx_num_badfrms(sc, bf, txok);
+	while (bf) {
+		txfail = txpending = 0;
+		bf_next = bf->bf_next;
+
+		if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
+			/* transmit completion, subframe is
+			 * acked by block ack */
+			acked_cnt++;
+		} else if (!isaggr && txok) {
+			/* transmit completion */
+			acked_cnt++;
+		} else {
+			if (!(tid->state & AGGR_CLEANUP) &&
+			    ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
+				if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
+					ath_tx_set_retry(sc, bf);
+					txpending = 1;
+				} else {
+					bf->bf_state.bf_type |= BUF_XRETRY;
+					txfail = 1;
+					sendbar = 1;
+					txfail_cnt++;
+				}
+			} else {
+				/*
+				 * cleanup in progress, just fail
+				 * the un-acked sub-frames
+				 */
+				txfail = 1;
+			}
+		}
+
+		if (bf_next == NULL) {
+			/*
+			 * Make sure the last desc is reclaimed if it
+			 * not a holding desc.
+			 */
+			if (!bf_last->bf_stale)
+				list_move_tail(&bf->list, &bf_head);
+			else
+				INIT_LIST_HEAD(&bf_head);
+		} else {
+			ASSERT(!list_empty(bf_q));
+			list_move_tail(&bf->list, &bf_head);
+		}
+
+		if (!txpending) {
+			/*
+			 * complete the acked-ones/xretried ones; update
+			 * block-ack window
+			 */
+			spin_lock_bh(&txq->axq_lock);
+			ath_tx_update_baw(sc, tid, bf->bf_seqno);
+			spin_unlock_bh(&txq->axq_lock);
+
+			if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+				ath_tx_rc_status(bf, ds, nbad, txok, true);
+				rc_update = false;
+			} else {
+				ath_tx_rc_status(bf, ds, nbad, txok, false);
+			}
+
+			ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
+		} else {
+			/* retry the un-acked ones */
+			if (bf->bf_next == NULL && bf_last->bf_stale) {
+				struct ath_buf *tbf;
+
+				tbf = ath_clone_txbuf(sc, bf_last);
+				ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc);
+				list_add_tail(&tbf->list, &bf_head);
+			} else {
+				/*
+				 * Clear descriptor status words for
+				 * software retry
+				 */
+				ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc);
+			}
+
+			/*
+			 * Put this buffer to the temporary pending
+			 * queue to retain ordering
+			 */
+			list_splice_tail_init(&bf_head, &bf_pending);
+		}
+
+		bf = bf_next;
+	}
+
+	if (tid->state & AGGR_CLEANUP) {
+		if (tid->baw_head == tid->baw_tail) {
+			tid->state &= ~AGGR_ADDBA_COMPLETE;
+			tid->addba_exchangeattempts = 0;
+			tid->state &= ~AGGR_CLEANUP;
+
+			/* send buffered frames as singles */
+			ath_tx_flush_tid(sc, tid);
+		}
+		rcu_read_unlock();
+		return;
+	}
+
+	/* prepend un-acked frames to the beginning of the pending frame queue */
+	if (!list_empty(&bf_pending)) {
+		spin_lock_bh(&txq->axq_lock);
+		list_splice(&bf_pending, &tid->buf_q);
+		ath_tx_queue_tid(txq, tid);
+		spin_unlock_bh(&txq->axq_lock);
+	}
+
+	rcu_read_unlock();
+
+	if (needreset)
+		ath_reset(sc, false);
+}
+
+static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
+			   struct ath_atx_tid *tid)
+{
+	const struct ath_rate_table *rate_table = sc->cur_rate_table;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *rates;
+	struct ath_tx_info_priv *tx_info_priv;
+	u32 max_4ms_framelen, frmlen;
+	u16 aggr_limit, legacy = 0, maxampdu;
+	int i;
+
+	skb = bf->bf_mpdu;
+	tx_info = IEEE80211_SKB_CB(skb);
+	rates = tx_info->control.rates;
+	tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
+
+	/*
+	 * Find the lowest frame length among the rate series that will have a
+	 * 4ms transmit duration.
+	 * TODO - TXOP limit needs to be considered.
+	 */
+	max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
+
+	for (i = 0; i < 4; i++) {
+		if (rates[i].count) {
+			if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) {
+				legacy = 1;
+				break;
+			}
+
+			frmlen = rate_table->info[rates[i].idx].max_4ms_framelen;
+			max_4ms_framelen = min(max_4ms_framelen, frmlen);
+		}
+	}
+
+	/*
+	 * limit aggregate size by the minimum rate if rate selected is
+	 * not a probe rate, if rate selected is a probe rate then
+	 * avoid aggregation of this packet.
+	 */
+	if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
+		return 0;
+
+	aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT);
+
+	/*
+	 * h/w can accept aggregates upto 16 bit lengths (65535).
+	 * The IE, however can hold upto 65536, which shows up here
+	 * as zero. Ignore 65536 since we  are constrained by hw.
+	 */
+	maxampdu = tid->an->maxampdu;
+	if (maxampdu)
+		aggr_limit = min(aggr_limit, maxampdu);
+
+	return aggr_limit;
+}
+
+/*
+ * Returns the number of delimiters to be added to
+ * meet the minimum required mpdudensity.
+ * caller should make sure that the rate is HT rate .
+ */
+static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
+				  struct ath_buf *bf, u16 frmlen)
+{
+	const struct ath_rate_table *rt = sc->cur_rate_table;
+	struct sk_buff *skb = bf->bf_mpdu;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	u32 nsymbits, nsymbols, mpdudensity;
+	u16 minlen;
+	u8 rc, flags, rix;
+	int width, half_gi, ndelim, mindelim;
+
+	/* Select standard number of delimiters based on frame length alone */
+	ndelim = ATH_AGGR_GET_NDELIM(frmlen);
+
+	/*
+	 * If encryption enabled, hardware requires some more padding between
+	 * subframes.
+	 * TODO - this could be improved to be dependent on the rate.
+	 *      The hardware can keep up at lower rates, but not higher rates
+	 */
+	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR)
+		ndelim += ATH_AGGR_ENCRYPTDELIM;
+
+	/*
+	 * Convert desired mpdu density from microeconds to bytes based
+	 * on highest rate in rate series (i.e. first rate) to determine
+	 * required minimum length for subframe. Take into account
+	 * whether high rate is 20 or 40Mhz and half or full GI.
+	 */
+	mpdudensity = tid->an->mpdudensity;
+
+	/*
+	 * If there is no mpdu density restriction, no further calculation
+	 * is needed.
+	 */
+	if (mpdudensity == 0)
+		return ndelim;
+
+	rix = tx_info->control.rates[0].idx;
+	flags = tx_info->control.rates[0].flags;
+	rc = rt->info[rix].ratecode;
+	width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
+	half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
+
+	if (half_gi)
+		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
+	else
+		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
+
+	if (nsymbols == 0)
+		nsymbols = 1;
+
+	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
+	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
+
+	if (frmlen < minlen) {
+		mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
+		ndelim = max(mindelim, ndelim);
+	}
+
+	return ndelim;
+}
+
+static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
+					     struct ath_atx_tid *tid,
+					     struct list_head *bf_q)
+{
+#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
+	struct ath_buf *bf, *bf_first, *bf_prev = NULL;
+	int rl = 0, nframes = 0, ndelim, prev_al = 0;
+	u16 aggr_limit = 0, al = 0, bpad = 0,
+		al_delta, h_baw = tid->baw_size / 2;
+	enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
+
+	bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
+
+	do {
+		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+
+		/* do not step over block-ack window */
+		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) {
+			status = ATH_AGGR_BAW_CLOSED;
+			break;
+		}
+
+		if (!rl) {
+			aggr_limit = ath_lookup_rate(sc, bf, tid);
+			rl = 1;
+		}
+
+		/* do not exceed aggregation limit */
+		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen;
+
+		if (nframes &&
+		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
+			status = ATH_AGGR_LIMITED;
+			break;
+		}
+
+		/* do not exceed subframe limit */
+		if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
+			status = ATH_AGGR_LIMITED;
+			break;
+		}
+		nframes++;
+
+		/* add padding for previous frame to aggregation length */
+		al += bpad + al_delta;
+
+		/*
+		 * Get the delimiters needed to meet the MPDU
+		 * density for this node.
+		 */
+		ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
+		bpad = PADBYTES(al_delta) + (ndelim << 2);
+
+		bf->bf_next = NULL;
+		bf->bf_desc->ds_link = 0;
+
+		/* link buffers of this frame to the aggregate */
+		ath_tx_addto_baw(sc, tid, bf);
+		ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+		list_move_tail(&bf->list, bf_q);
+		if (bf_prev) {
+			bf_prev->bf_next = bf;
+			bf_prev->bf_desc->ds_link = bf->bf_daddr;
+		}
+		bf_prev = bf;
+	} while (!list_empty(&tid->buf_q));
+
+	bf_first->bf_al = al;
+	bf_first->bf_nframes = nframes;
+
+	return status;
+#undef PADBYTES
+}
+
+static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
+			      struct ath_atx_tid *tid)
+{
+	struct ath_buf *bf;
+	enum ATH_AGGR_STATUS status;
+	struct list_head bf_q;
+
+	do {
+		if (list_empty(&tid->buf_q))
+			return;
+
+		INIT_LIST_HEAD(&bf_q);
+
+		status = ath_tx_form_aggr(sc, tid, &bf_q);
+
+		/*
+		 * no frames picked up to be aggregated;
+		 * block-ack window is not open.
+		 */
+		if (list_empty(&bf_q))
+			break;
+
+		bf = list_first_entry(&bf_q, struct ath_buf, list);
+		bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
+
+		/* if only one frame, send as non-aggregate */
+		if (bf->bf_nframes == 1) {
+			bf->bf_state.bf_type &= ~BUF_AGGR;
+			ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
+			ath_buf_set_rate(sc, bf);
+			ath_tx_txqaddbuf(sc, txq, &bf_q);
+			continue;
+		}
+
+		/* setup first desc of aggregate */
+		bf->bf_state.bf_type |= BUF_AGGR;
+		ath_buf_set_rate(sc, bf);
+		ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
+
+		/* anchor last desc of aggregate */
+		ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
+
+		txq->axq_aggr_depth++;
+		ath_tx_txqaddbuf(sc, txq, &bf_q);
+
+	} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
+		 status != ATH_AGGR_BAW_CLOSED);
+}
+
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+		      u16 tid, u16 *ssn)
+{
+	struct ath_atx_tid *txtid;
+	struct ath_node *an;
+
+	an = (struct ath_node *)sta->drv_priv;
+
+	if (sc->sc_flags & SC_OP_TXAGGR) {
+		txtid = ATH_AN_2_TID(an, tid);
+		txtid->state |= AGGR_ADDBA_PROGRESS;
+		ath_tx_pause_tid(sc, txtid);
+		*ssn = txtid->seq_start;
+	}
+
+	return 0;
+}
+
+int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+{
+	struct ath_node *an = (struct ath_node *)sta->drv_priv;
+	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
+	struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+	struct ath_buf *bf;
+	struct list_head bf_head;
+	INIT_LIST_HEAD(&bf_head);
+
+	if (txtid->state & AGGR_CLEANUP)
+		return 0;
+
+	if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
+		txtid->state &= ~AGGR_ADDBA_PROGRESS;
+		txtid->addba_exchangeattempts = 0;
+		return 0;
+	}
+
+	ath_tx_pause_tid(sc, txtid);
+
+	/* drop all software retried frames and mark this TID */
+	spin_lock_bh(&txq->axq_lock);
+	while (!list_empty(&txtid->buf_q)) {
+		bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
+		if (!bf_isretried(bf)) {
+			/*
+			 * NB: it's based on the assumption that
+			 * software retried frame will always stay
+			 * at the head of software queue.
+			 */
+			break;
+		}
+		list_move_tail(&bf->list, &bf_head);
+		ath_tx_update_baw(sc, txtid, bf->bf_seqno);
+		ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+	}
+	spin_unlock_bh(&txq->axq_lock);
+
+	if (txtid->baw_head != txtid->baw_tail) {
+		txtid->state |= AGGR_CLEANUP;
+	} else {
+		txtid->state &= ~AGGR_ADDBA_COMPLETE;
+		txtid->addba_exchangeattempts = 0;
+		ath_tx_flush_tid(sc, txtid);
+	}
+
+	return 0;
+}
+
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+{
+	struct ath_atx_tid *txtid;
+	struct ath_node *an;
+
+	an = (struct ath_node *)sta->drv_priv;
+
+	if (sc->sc_flags & SC_OP_TXAGGR) {
+		txtid = ATH_AN_2_TID(an, tid);
+		txtid->baw_size =
+			IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
+		txtid->state |= AGGR_ADDBA_COMPLETE;
+		txtid->state &= ~AGGR_ADDBA_PROGRESS;
+		ath_tx_resume_tid(sc, txtid);
+	}
+}
+
+bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
+{
+	struct ath_atx_tid *txtid;
+
+	if (!(sc->sc_flags & SC_OP_TXAGGR))
+		return false;
+
+	txtid = ATH_AN_2_TID(an, tidno);
+
+	if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
+		if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
+		    (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
+			txtid->addba_exchangeattempts++;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/********************/
+/* Queue Management */
+/********************/
+
+static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
+					  struct ath_txq *txq)
+{
+	struct ath_atx_ac *ac, *ac_tmp;
+	struct ath_atx_tid *tid, *tid_tmp;
+
+	list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+		list_del(&ac->list);
+		ac->sched = false;
+		list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
+			list_del(&tid->list);
+			tid->sched = false;
+			ath_tid_drain(sc, txq, tid);
+		}
+	}
+}
+
+struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_tx_queue_info qi;
+	int qnum;
+
+	memset(&qi, 0, sizeof(qi));
+	qi.tqi_subtype = subtype;
+	qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
+	qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+	qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
+	qi.tqi_physCompBuf = 0;
+
+	/*
+	 * Enable interrupts only for EOL and DESC conditions.
+	 * We mark tx descriptors to receive a DESC interrupt
+	 * when a tx queue gets deep; otherwise waiting for the
+	 * EOL to reap descriptors.  Note that this is done to
+	 * reduce interrupt load and this only defers reaping
+	 * descriptors, never transmitting frames.  Aside from
+	 * reducing interrupts this also permits more concurrency.
+	 * The only potential downside is if the tx queue backs
+	 * up in which case the top half of the kernel may backup
+	 * due to a lack of tx descriptors.
+	 *
+	 * The UAPSD queue is an exception, since we take a desc-
+	 * based intr on the EOSP frames.
+	 */
+	if (qtype == ATH9K_TX_QUEUE_UAPSD)
+		qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
+	else
+		qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
+			TXQ_FLAG_TXDESCINT_ENABLE;
+	qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
+	if (qnum == -1) {
+		/*
+		 * NB: don't print a message, this happens
+		 * normally on parts with too few tx queues
+		 */
+		return NULL;
+	}
+	if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"qnum %u out of range, max %u!\n",
+			qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
+		ath9k_hw_releasetxqueue(ah, qnum);
+		return NULL;
+	}
+	if (!ATH_TXQ_SETUP(sc, qnum)) {
+		struct ath_txq *txq = &sc->tx.txq[qnum];
+
+		txq->axq_qnum = qnum;
+		txq->axq_link = NULL;
+		INIT_LIST_HEAD(&txq->axq_q);
+		INIT_LIST_HEAD(&txq->axq_acq);
+		spin_lock_init(&txq->axq_lock);
+		txq->axq_depth = 0;
+		txq->axq_aggr_depth = 0;
+		txq->axq_totalqueued = 0;
+		txq->axq_linkbuf = NULL;
+		sc->tx.txqsetup |= 1<<qnum;
+	}
+	return &sc->tx.txq[qnum];
+}
+
+static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
+{
+	int qnum;
+
+	switch (qtype) {
+	case ATH9K_TX_QUEUE_DATA:
+		if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"HAL AC %u out of range, max %zu!\n",
+				haltype, ARRAY_SIZE(sc->tx.hwq_map));
+			return -1;
+		}
+		qnum = sc->tx.hwq_map[haltype];
+		break;
+	case ATH9K_TX_QUEUE_BEACON:
+		qnum = sc->beacon.beaconq;
+		break;
+	case ATH9K_TX_QUEUE_CAB:
+		qnum = sc->beacon.cabq->axq_qnum;
+		break;
+	default:
+		qnum = -1;
+	}
+	return qnum;
+}
+
+struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
+{
+	struct ath_txq *txq = NULL;
+	int qnum;
+
+	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+	txq = &sc->tx.txq[qnum];
+
+	spin_lock_bh(&txq->axq_lock);
+
+	if (txq->axq_depth >= (ATH_TXBUF - 20)) {
+		DPRINTF(sc, ATH_DBG_XMIT,
+			"TX queue: %d is full, depth: %d\n",
+			qnum, txq->axq_depth);
+		ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
+		txq->stopped = 1;
+		spin_unlock_bh(&txq->axq_lock);
+		return NULL;
+	}
+
+	spin_unlock_bh(&txq->axq_lock);
+
+	return txq;
+}
+
+int ath_txq_update(struct ath_softc *sc, int qnum,
+		   struct ath9k_tx_queue_info *qinfo)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	int error = 0;
+	struct ath9k_tx_queue_info qi;
+
+	if (qnum == sc->beacon.beaconq) {
+		/*
+		 * XXX: for beacon queue, we just save the parameter.
+		 * It will be picked up by ath_beaconq_config when
+		 * it's necessary.
+		 */
+		sc->beacon.beacon_qi = *qinfo;
+		return 0;
+	}
+
+	ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
+
+	ath9k_hw_get_txq_props(ah, qnum, &qi);
+	qi.tqi_aifs = qinfo->tqi_aifs;
+	qi.tqi_cwmin = qinfo->tqi_cwmin;
+	qi.tqi_cwmax = qinfo->tqi_cwmax;
+	qi.tqi_burstTime = qinfo->tqi_burstTime;
+	qi.tqi_readyTime = qinfo->tqi_readyTime;
+
+	if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Unable to update hardware queue %u!\n", qnum);
+		error = -EIO;
+	} else {
+		ath9k_hw_resettxqueue(ah, qnum);
+	}
+
+	return error;
+}
+
+int ath_cabq_update(struct ath_softc *sc)
+{
+	struct ath9k_tx_queue_info qi;
+	int qnum = sc->beacon.cabq->axq_qnum;
+
+	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
+	/*
+	 * Ensure the readytime % is within the bounds.
+	 */
+	if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
+		sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
+	else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
+		sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
+
+	qi.tqi_readyTime = (sc->beacon_interval *
+			    sc->config.cabqReadytime) / 100;
+	ath_txq_update(sc, qnum, &qi);
+
+	return 0;
+}
+
+/*
+ * Drain a given TX queue (could be Beacon or Data)
+ *
+ * This assumes output has been stopped and
+ * we do not need to block ath_tx_tasklet.
+ */
+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+{
+	struct ath_buf *bf, *lastbf;
+	struct list_head bf_head;
+
+	INIT_LIST_HEAD(&bf_head);
+
+	for (;;) {
+		spin_lock_bh(&txq->axq_lock);
+
+		if (list_empty(&txq->axq_q)) {
+			txq->axq_link = NULL;
+			txq->axq_linkbuf = NULL;
+			spin_unlock_bh(&txq->axq_lock);
+			break;
+		}
+
+		bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
+
+		if (bf->bf_stale) {
+			list_del(&bf->list);
+			spin_unlock_bh(&txq->axq_lock);
+
+			spin_lock_bh(&sc->tx.txbuflock);
+			list_add_tail(&bf->list, &sc->tx.txbuf);
+			spin_unlock_bh(&sc->tx.txbuflock);
+			continue;
+		}
+
+		lastbf = bf->bf_lastbf;
+		if (!retry_tx)
+			lastbf->bf_desc->ds_txstat.ts_flags =
+				ATH9K_TX_SW_ABORTED;
+
+		/* remove ath_buf's of the same mpdu from txq */
+		list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
+		txq->axq_depth--;
+
+		spin_unlock_bh(&txq->axq_lock);
+
+		if (bf_isampdu(bf))
+			ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
+		else
+			ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+	}
+
+	/* flush any pending frames if aggregation is enabled */
+	if (sc->sc_flags & SC_OP_TXAGGR) {
+		if (!retry_tx) {
+			spin_lock_bh(&txq->axq_lock);
+			ath_txq_drain_pending_buffers(sc, txq);
+			spin_unlock_bh(&txq->axq_lock);
+		}
+	}
+}
+
+void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_txq *txq;
+	int i, npend = 0;
+
+	if (sc->sc_flags & SC_OP_INVALID)
+		return;
+
+	/* Stop beacon queue */
+	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+
+	/* Stop data queues */
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+		if (ATH_TXQ_SETUP(sc, i)) {
+			txq = &sc->tx.txq[i];
+			ath9k_hw_stoptxdma(ah, txq->axq_qnum);
+			npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
+		}
+	}
+
+	if (npend) {
+		int r;
+
+		DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
+
+		spin_lock_bh(&sc->sc_resetlock);
+		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true);
+		if (r)
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"Unable to reset hardware; reset status %d\n",
+				r);
+		spin_unlock_bh(&sc->sc_resetlock);
+	}
+
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+		if (ATH_TXQ_SETUP(sc, i))
+			ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
+	}
+}
+
+void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
+{
+	ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
+	sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
+}
+
+void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
+{
+	struct ath_atx_ac *ac;
+	struct ath_atx_tid *tid;
+
+	if (list_empty(&txq->axq_acq))
+		return;
+
+	ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
+	list_del(&ac->list);
+	ac->sched = false;
+
+	do {
+		if (list_empty(&ac->tid_q))
+			return;
+
+		tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
+		list_del(&tid->list);
+		tid->sched = false;
+
+		if (tid->paused)
+			continue;
+
+		if ((txq->axq_depth % 2) == 0)
+			ath_tx_sched_aggr(sc, txq, tid);
+
+		/*
+		 * add tid to round-robin queue if more frames
+		 * are pending for the tid
+		 */
+		if (!list_empty(&tid->buf_q))
+			ath_tx_queue_tid(txq, tid);
+
+		break;
+	} while (!list_empty(&ac->tid_q));
+
+	if (!list_empty(&ac->tid_q)) {
+		if (!ac->sched) {
+			ac->sched = true;
+			list_add_tail(&ac->list, &txq->axq_acq);
+		}
+	}
+}
+
+int ath_tx_setup(struct ath_softc *sc, int haltype)
+{
+	struct ath_txq *txq;
+
+	if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"HAL AC %u out of range, max %zu!\n",
+			 haltype, ARRAY_SIZE(sc->tx.hwq_map));
+		return 0;
+	}
+	txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
+	if (txq != NULL) {
+		sc->tx.hwq_map[haltype] = txq->axq_qnum;
+		return 1;
+	} else
+		return 0;
+}
+
+/***********/
+/* TX, DMA */
+/***********/
+
+/*
+ * Insert a chain of ath_buf (descriptors) on a txq and
+ * assume the descriptors are already chained together by caller.
+ */
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+			     struct list_head *head)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_buf *bf;
+
+	/*
+	 * Insert the frame on the outbound list and
+	 * pass it on to the hardware.
+	 */
+
+	if (list_empty(head))
+		return;
+
+	bf = list_first_entry(head, struct ath_buf, list);
+
+	list_splice_tail_init(head, &txq->axq_q);
+	txq->axq_depth++;
+	txq->axq_totalqueued++;
+	txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
+
+	DPRINTF(sc, ATH_DBG_QUEUE,
+		"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
+
+	if (txq->axq_link == NULL) {
+		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+		DPRINTF(sc, ATH_DBG_XMIT,
+			"TXDP[%u] = %llx (%p)\n",
+			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
+	} else {
+		*txq->axq_link = bf->bf_daddr;
+		DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n",
+			txq->axq_qnum, txq->axq_link,
+			ito64(bf->bf_daddr), bf->bf_desc);
+	}
+	txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
+	ath9k_hw_txstart(ah, txq->axq_qnum);
+}
+
+static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
+{
+	struct ath_buf *bf = NULL;
+
+	spin_lock_bh(&sc->tx.txbuflock);
+
+	if (unlikely(list_empty(&sc->tx.txbuf))) {
+		spin_unlock_bh(&sc->tx.txbuflock);
+		return NULL;
+	}
+
+	bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+	list_del(&bf->list);
+
+	spin_unlock_bh(&sc->tx.txbuflock);
+
+	return bf;
+}
+
+static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
+			      struct list_head *bf_head,
+			      struct ath_tx_control *txctl)
+{
+	struct ath_buf *bf;
+
+	bf = list_first_entry(bf_head, struct ath_buf, list);
+	bf->bf_state.bf_type |= BUF_AMPDU;
+
+	/*
+	 * Do not queue to h/w when any of the following conditions is true:
+	 * - there are pending frames in software queue
+	 * - the TID is currently paused for ADDBA/BAR request
+	 * - seqno is not within block-ack window
+	 * - h/w queue depth exceeds low water mark
+	 */
+	if (!list_empty(&tid->buf_q) || tid->paused ||
+	    !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) ||
+	    txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
+		/*
+		 * Add this frame to software queue for scheduling later
+		 * for aggregation.
+		 */
+		list_move_tail(&bf->list, &tid->buf_q);
+		ath_tx_queue_tid(txctl->txq, tid);
+		return;
+	}
+
+	/* Add sub-frame to BAW */
+	ath_tx_addto_baw(sc, tid, bf);
+
+	/* Queue to h/w without aggregation */
+	bf->bf_nframes = 1;
+	bf->bf_lastbf = bf;
+	ath_buf_set_rate(sc, bf);
+	ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
+}
+
+static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
+				  struct ath_atx_tid *tid,
+				  struct list_head *bf_head)
+{
+	struct ath_buf *bf;
+
+	bf = list_first_entry(bf_head, struct ath_buf, list);
+	bf->bf_state.bf_type &= ~BUF_AMPDU;
+
+	/* update starting sequence number for subsequent ADDBA request */
+	INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+
+	bf->bf_nframes = 1;
+	bf->bf_lastbf = bf;
+	ath_buf_set_rate(sc, bf);
+	ath_tx_txqaddbuf(sc, txq, bf_head);
+}
+
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+			       struct list_head *bf_head)
+{
+	struct ath_buf *bf;
+
+	bf = list_first_entry(bf_head, struct ath_buf, list);
+
+	bf->bf_lastbf = bf;
+	bf->bf_nframes = 1;
+	ath_buf_set_rate(sc, bf);
+	ath_tx_txqaddbuf(sc, txq, bf_head);
+}
+
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+	enum ath9k_pkt_type htype;
+	__le16 fc;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+
+	if (ieee80211_is_beacon(fc))
+		htype = ATH9K_PKT_TYPE_BEACON;
+	else if (ieee80211_is_probe_resp(fc))
+		htype = ATH9K_PKT_TYPE_PROBE_RESP;
+	else if (ieee80211_is_atim(fc))
+		htype = ATH9K_PKT_TYPE_ATIM;
+	else if (ieee80211_is_pspoll(fc))
+		htype = ATH9K_PKT_TYPE_PSPOLL;
+	else
+		htype = ATH9K_PKT_TYPE_NORMAL;
+
+	return htype;
+}
+
+static bool is_pae(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+	__le16 fc;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+
+	if (ieee80211_is_data(fc)) {
+		if (ieee80211_is_nullfunc(fc) ||
+		    /* Port Access Entity (IEEE 802.1X) */
+		    (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int get_hw_crypto_keytype(struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+
+	if (tx_info->control.hw_key) {
+		if (tx_info->control.hw_key->alg == ALG_WEP)
+			return ATH9K_KEY_TYPE_WEP;
+		else if (tx_info->control.hw_key->alg == ALG_TKIP)
+			return ATH9K_KEY_TYPE_TKIP;
+		else if (tx_info->control.hw_key->alg == ALG_CCMP)
+			return ATH9K_KEY_TYPE_AES;
+	}
+
+	return ATH9K_KEY_TYPE_CLEAR;
+}
+
+static void assign_aggr_tid_seqno(struct sk_buff *skb,
+				  struct ath_buf *bf)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr;
+	struct ath_node *an;
+	struct ath_atx_tid *tid;
+	__le16 fc;
+	u8 *qc;
+
+	if (!tx_info->control.sta)
+		return;
+
+	an = (struct ath_node *)tx_info->control.sta->drv_priv;
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+
+	if (ieee80211_is_data_qos(fc)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		bf->bf_tidno = qc[0] & 0xf;
+	}
+
+	/*
+	 * For HT capable stations, we save tidno for later use.
+	 * We also override seqno set by upper layer with the one
+	 * in tx aggregation state.
+	 *
+	 * If fragmentation is on, the sequence number is
+	 * not overridden, since it has been
+	 * incremented by the fragmentation routine.
+	 *
+	 * FIXME: check if the fragmentation threshold exceeds
+	 * IEEE80211 max.
+	 */
+	tid = ATH_AN_2_TID(an, bf->bf_tidno);
+	hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
+			IEEE80211_SEQ_SEQ_SHIFT);
+	bf->bf_seqno = tid->seq_next;
+	INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+}
+
+static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
+			  struct ath_txq *txq)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	int flags = 0;
+
+	flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
+	flags |= ATH9K_TXDESC_INTREQ;
+
+	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+		flags |= ATH9K_TXDESC_NOACK;
+
+	return flags;
+}
+
+/*
+ * rix - rate index
+ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
+ * width  - 0 for 20 MHz, 1 for 40 MHz
+ * half_gi - to use 4us v/s 3.6 us for symbol time
+ */
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
+			    int width, int half_gi, bool shortPreamble)
+{
+	const struct ath_rate_table *rate_table = sc->cur_rate_table;
+	u32 nbits, nsymbits, duration, nsymbols;
+	u8 rc;
+	int streams, pktlen;
+
+	pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
+	rc = rate_table->info[rix].ratecode;
+
+	/* for legacy rates, use old function to compute packet duration */
+	if (!IS_HT_RATE(rc))
+		return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
+					      rix, shortPreamble);
+
+	/* find number of symbols: PLCP + data */
+	nbits = (pktlen << 3) + OFDM_PLCP_BITS;
+	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
+	nsymbols = (nbits + nsymbits - 1) / nsymbits;
+
+	if (!half_gi)
+		duration = SYMBOL_TIME(nsymbols);
+	else
+		duration = SYMBOL_TIME_HALFGI(nsymbols);
+
+	/* addup duration for legacy/ht training and signal fields */
+	streams = HT_RC_2_STREAMS(rc);
+	duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+
+	return duration;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
+{
+	const struct ath_rate_table *rt = sc->cur_rate_table;
+	struct ath9k_11n_rate_series series[4];
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *rates;
+	struct ieee80211_hdr *hdr;
+	int i, flags = 0;
+	u8 rix = 0, ctsrate = 0;
+	bool is_pspoll;
+
+	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+
+	skb = bf->bf_mpdu;
+	tx_info = IEEE80211_SKB_CB(skb);
+	rates = tx_info->control.rates;
+	hdr = (struct ieee80211_hdr *)skb->data;
+	is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
+
+	/*
+	 * We check if Short Preamble is needed for the CTS rate by
+	 * checking the BSS's global flag.
+	 * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
+	 */
+	if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
+		ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode |
+			rt->info[tx_info->control.rts_cts_rate_idx].short_preamble;
+	else
+		ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode;
+
+	/*
+	 * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive.
+	 * Check the first rate in the series to decide whether RTS/CTS
+	 * or CTS-to-self has to be used.
+	 */
+	if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+		flags = ATH9K_TXDESC_CTSENA;
+	else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+		flags = ATH9K_TXDESC_RTSENA;
+
+	/* FIXME: Handle aggregation protection */
+	if (sc->config.ath_aggr_prot &&
+	    (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
+		flags = ATH9K_TXDESC_RTSENA;
+	}
+
+	/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+	if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
+		flags &= ~(ATH9K_TXDESC_RTSENA);
+
+	for (i = 0; i < 4; i++) {
+		if (!rates[i].count || (rates[i].idx < 0))
+			continue;
+
+		rix = rates[i].idx;
+		series[i].Tries = rates[i].count;
+		series[i].ChSel = sc->tx_chainmask;
+
+		if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+			series[i].Rate = rt->info[rix].ratecode |
+				rt->info[rix].short_preamble;
+		else
+			series[i].Rate = rt->info[rix].ratecode;
+
+		if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+			series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
+		if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+			series[i].RateFlags |= ATH9K_RATESERIES_2040;
+		if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+			series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
+
+		series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
+			 (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0,
+			 (rates[i].flags & IEEE80211_TX_RC_SHORT_GI),
+			 (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE));
+	}
+
+	/* set dur_update_en for l-sig computation except for PS-Poll frames */
+	ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
+				     bf->bf_lastbf->bf_desc,
+				     !is_pspoll, ctsrate,
+				     0, series, 4, flags);
+
+	if (sc->config.ath_aggr_prot && flags)
+		ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192);
+}
+
+static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
+				struct sk_buff *skb,
+				struct ath_tx_control *txctl)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ath_tx_info_priv *tx_info_priv;
+	int hdrlen;
+	__le16 fc;
+
+	tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
+	if (unlikely(!tx_info_priv))
+		return -ENOMEM;
+	tx_info->rate_driver_data[0] = tx_info_priv;
+	tx_info_priv->aphy = aphy;
+	tx_info_priv->frame_type = txctl->frame_type;
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	fc = hdr->frame_control;
+
+	ATH_TXBUF_RESET(bf);
+
+	bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
+
+	if (conf_is_ht(&sc->hw->conf) && !is_pae(skb))
+		bf->bf_state.bf_type |= BUF_HT;
+
+	bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
+
+	bf->bf_keytype = get_hw_crypto_keytype(skb);
+	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
+		bf->bf_frmlen += tx_info->control.hw_key->icv_len;
+		bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
+	} else {
+		bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
+	}
+
+	if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR))
+		assign_aggr_tid_seqno(skb, bf);
+
+	bf->bf_mpdu = skb;
+
+	bf->bf_dmacontext = dma_map_single(sc->dev, skb->data,
+					   skb->len, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
+		bf->bf_mpdu = NULL;
+		kfree(tx_info_priv);
+		tx_info->rate_driver_data[0] = NULL;
+		DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n");
+		return -ENOMEM;
+	}
+
+	bf->bf_buf_addr = bf->bf_dmacontext;
+	return 0;
+}
+
+/* FIXME: tx power */
+static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+			     struct ath_tx_control *txctl)
+{
+	struct sk_buff *skb = bf->bf_mpdu;
+	struct ieee80211_tx_info *tx_info =  IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ath_node *an = NULL;
+	struct list_head bf_head;
+	struct ath_desc *ds;
+	struct ath_atx_tid *tid;
+	struct ath_hw *ah = sc->sc_ah;
+	int frm_type;
+	__le16 fc;
+
+	frm_type = get_hw_packet_type(skb);
+	fc = hdr->frame_control;
+
+	INIT_LIST_HEAD(&bf_head);
+	list_add_tail(&bf->list, &bf_head);
+
+	ds = bf->bf_desc;
+	ds->ds_link = 0;
+	ds->ds_data = bf->bf_buf_addr;
+
+	ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
+			       bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
+
+	ath9k_hw_filltxdesc(ah, ds,
+			    skb->len,	/* segment length */
+			    true,	/* first segment */
+			    true,	/* last segment */
+			    ds);	/* first descriptor */
+
+	spin_lock_bh(&txctl->txq->axq_lock);
+
+	if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
+	    tx_info->control.sta) {
+		an = (struct ath_node *)tx_info->control.sta->drv_priv;
+		tid = ATH_AN_2_TID(an, bf->bf_tidno);
+
+		if (!ieee80211_is_data_qos(fc)) {
+			ath_tx_send_normal(sc, txctl->txq, &bf_head);
+			goto tx_done;
+		}
+
+		if (ath_aggr_query(sc, an, bf->bf_tidno)) {
+			/*
+			 * Try aggregation if it's a unicast data frame
+			 * and the destination is HT capable.
+			 */
+			ath_tx_send_ampdu(sc, tid, &bf_head, txctl);
+		} else {
+			/*
+			 * Send this frame as regular when ADDBA
+			 * exchange is neither complete nor pending.
+			 */
+			ath_tx_send_ht_normal(sc, txctl->txq,
+					      tid, &bf_head);
+		}
+	} else {
+		ath_tx_send_normal(sc, txctl->txq, &bf_head);
+	}
+
+tx_done:
+	spin_unlock_bh(&txctl->txq->axq_lock);
+}
+
+/* Upon failure caller should free skb */
+int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
+		 struct ath_tx_control *txctl)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_buf *bf;
+	int r;
+
+	bf = ath_tx_get_buffer(sc);
+	if (!bf) {
+		DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n");
+		return -1;
+	}
+
+	r = ath_tx_setup_buffer(hw, bf, skb, txctl);
+	if (unlikely(r)) {
+		struct ath_txq *txq = txctl->txq;
+
+		DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n");
+
+		/* upon ath_tx_processq() this TX queue will be resumed, we
+		 * guarantee this will happen by knowing beforehand that
+		 * we will at least have to run TX completionon one buffer
+		 * on the queue */
+		spin_lock_bh(&txq->axq_lock);
+		if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
+			ieee80211_stop_queue(sc->hw,
+				skb_get_queue_mapping(skb));
+			txq->stopped = 1;
+		}
+		spin_unlock_bh(&txq->axq_lock);
+
+		spin_lock_bh(&sc->tx.txbuflock);
+		list_add_tail(&bf->list, &sc->tx.txbuf);
+		spin_unlock_bh(&sc->tx.txbuflock);
+
+		return r;
+	}
+
+	ath_tx_start_dma(sc, bf, txctl);
+
+	return 0;
+}
+
+void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	int hdrlen, padsize;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ath_tx_control txctl;
+
+	memset(&txctl, 0, sizeof(struct ath_tx_control));
+
+	/*
+	 * As a temporary workaround, assign seq# here; this will likely need
+	 * to be cleaned up to work better with Beacon transmission and virtual
+	 * BSSes.
+	 */
+	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+			sc->tx.seq_no += 0x10;
+		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+	}
+
+	/* Add the padding after the header if this is not already done */
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	if (hdrlen & 3) {
+		padsize = hdrlen % 4;
+		if (skb_headroom(skb) < padsize) {
+			DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n");
+			dev_kfree_skb_any(skb);
+			return;
+		}
+		skb_push(skb, padsize);
+		memmove(skb->data, skb->data + padsize, hdrlen);
+	}
+
+	txctl.txq = sc->beacon.cabq;
+
+	DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);
+
+	if (ath_tx_start(hw, skb, &txctl) != 0) {
+		DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n");
+		goto exit;
+	}
+
+	return;
+exit:
+	dev_kfree_skb_any(skb);
+}
+
+/*****************/
+/* TX Completion */
+/*****************/
+
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+			    int tx_flags)
+{
+	struct ieee80211_hw *hw = sc->hw;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+	int hdrlen, padsize;
+	int frame_type = ATH9K_NOT_INTERNAL;
+
+	DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
+
+	if (tx_info_priv) {
+		hw = tx_info_priv->aphy->hw;
+		frame_type = tx_info_priv->frame_type;
+	}
+
+	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
+	    tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
+		kfree(tx_info_priv);
+		tx_info->rate_driver_data[0] = NULL;
+	}
+
+	if (tx_flags & ATH_TX_BAR)
+		tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+
+	if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
+		/* Frame was ACKed */
+		tx_info->flags |= IEEE80211_TX_STAT_ACK;
+	}
+
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	padsize = hdrlen & 3;
+	if (padsize && hdrlen >= 24) {
+		/*
+		 * Remove MAC header padding before giving the frame back to
+		 * mac80211.
+		 */
+		memmove(skb->data + padsize, skb->data, hdrlen);
+		skb_pull(skb, padsize);
+	}
+
+	if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) {
+		sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK;
+		DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having "
+			"received TX status (0x%x)\n",
+			sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
+					SC_OP_WAIT_FOR_CAB |
+					SC_OP_WAIT_FOR_PSPOLL_DATA |
+					SC_OP_WAIT_FOR_TX_ACK));
+	}
+
+	if (frame_type == ATH9K_NOT_INTERNAL)
+		ieee80211_tx_status(hw, skb);
+	else
+		ath9k_tx_status(hw, skb);
+}
+
+static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+				struct list_head *bf_q,
+				int txok, int sendbar)
+{
+	struct sk_buff *skb = bf->bf_mpdu;
+	unsigned long flags;
+	int tx_flags = 0;
+
+
+	if (sendbar)
+		tx_flags = ATH_TX_BAR;
+
+	if (!txok) {
+		tx_flags |= ATH_TX_ERROR;
+
+		if (bf_isxretried(bf))
+			tx_flags |= ATH_TX_XRETRY;
+	}
+
+	dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
+	ath_tx_complete(sc, skb, tx_flags);
+
+	/*
+	 * Return the list of ath_buf of this mpdu to free queue
+	 */
+	spin_lock_irqsave(&sc->tx.txbuflock, flags);
+	list_splice_tail_init(bf_q, &sc->tx.txbuf);
+	spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
+}
+
+static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
+			      int txok)
+{
+	struct ath_buf *bf_last = bf->bf_lastbf;
+	struct ath_desc *ds = bf_last->bf_desc;
+	u16 seq_st = 0;
+	u32 ba[WME_BA_BMP_SIZE >> 5];
+	int ba_index;
+	int nbad = 0;
+	int isaggr = 0;
+
+	if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
+		return 0;
+
+	isaggr = bf_isaggr(bf);
+	if (isaggr) {
+		seq_st = ATH_DS_BA_SEQ(ds);
+		memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
+	}
+
+	while (bf) {
+		ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno);
+		if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
+			nbad++;
+
+		bf = bf->bf_next;
+	}
+
+	return nbad;
+}
+
+static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
+			     int nbad, int txok, bool update_rc)
+{
+	struct sk_buff *skb = bf->bf_mpdu;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+	struct ieee80211_hw *hw = tx_info_priv->aphy->hw;
+	u8 i, tx_rateindex;
+
+	if (txok)
+		tx_info->status.ack_signal = ds->ds_txstat.ts_rssi;
+
+	tx_rateindex = ds->ds_txstat.ts_rateindex;
+	WARN_ON(tx_rateindex >= hw->max_rates);
+
+	tx_info_priv->update_rc = update_rc;
+	if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
+		tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+
+	if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
+	    (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
+		if (ieee80211_is_data(hdr->frame_control)) {
+			memcpy(&tx_info_priv->tx, &ds->ds_txstat,
+			       sizeof(tx_info_priv->tx));
+			tx_info_priv->n_frames = bf->bf_nframes;
+			tx_info_priv->n_bad_frames = nbad;
+		}
+	}
+
+	for (i = tx_rateindex + 1; i < hw->max_rates; i++)
+		tx_info->status.rates[i].count = 0;
+
+	tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1;
+}
+
+static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
+{
+	int qnum;
+
+	spin_lock_bh(&txq->axq_lock);
+	if (txq->stopped &&
+	    sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
+		qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
+		if (qnum != -1) {
+			ieee80211_wake_queue(sc->hw, qnum);
+			txq->stopped = 0;
+		}
+	}
+	spin_unlock_bh(&txq->axq_lock);
+}
+
+static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_buf *bf, *lastbf, *bf_held = NULL;
+	struct list_head bf_head;
+	struct ath_desc *ds;
+	int txok;
+	int status;
+
+	DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
+		txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
+		txq->axq_link);
+
+	for (;;) {
+		spin_lock_bh(&txq->axq_lock);
+		if (list_empty(&txq->axq_q)) {
+			txq->axq_link = NULL;
+			txq->axq_linkbuf = NULL;
+			spin_unlock_bh(&txq->axq_lock);
+			break;
+		}
+		bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
+
+		/*
+		 * There is a race condition that a BH gets scheduled
+		 * after sw writes TxE and before hw re-load the last
+		 * descriptor to get the newly chained one.
+		 * Software must keep the last DONE descriptor as a
+		 * holding descriptor - software does so by marking
+		 * it with the STALE flag.
+		 */
+		bf_held = NULL;
+		if (bf->bf_stale) {
+			bf_held = bf;
+			if (list_is_last(&bf_held->list, &txq->axq_q)) {
+				txq->axq_link = NULL;
+				txq->axq_linkbuf = NULL;
+				spin_unlock_bh(&txq->axq_lock);
+
+				/*
+				 * The holding descriptor is the last
+				 * descriptor in queue. It's safe to remove
+				 * the last holding descriptor in BH context.
+				 */
+				spin_lock_bh(&sc->tx.txbuflock);
+				list_move_tail(&bf_held->list, &sc->tx.txbuf);
+				spin_unlock_bh(&sc->tx.txbuflock);
+
+				break;
+			} else {
+				bf = list_entry(bf_held->list.next,
+						struct ath_buf, list);
+			}
+		}
+
+		lastbf = bf->bf_lastbf;
+		ds = lastbf->bf_desc;
+
+		status = ath9k_hw_txprocdesc(ah, ds);
+		if (status == -EINPROGRESS) {
+			spin_unlock_bh(&txq->axq_lock);
+			break;
+		}
+		if (bf->bf_desc == txq->axq_lastdsWithCTS)
+			txq->axq_lastdsWithCTS = NULL;
+		if (ds == txq->axq_gatingds)
+			txq->axq_gatingds = NULL;
+
+		/*
+		 * Remove ath_buf's of the same transmit unit from txq,
+		 * however leave the last descriptor back as the holding
+		 * descriptor for hw.
+		 */
+		lastbf->bf_stale = true;
+		INIT_LIST_HEAD(&bf_head);
+		if (!list_is_singular(&lastbf->list))
+			list_cut_position(&bf_head,
+				&txq->axq_q, lastbf->list.prev);
+
+		txq->axq_depth--;
+		if (bf_isaggr(bf))
+			txq->axq_aggr_depth--;
+
+		txok = (ds->ds_txstat.ts_status == 0);
+		spin_unlock_bh(&txq->axq_lock);
+
+		if (bf_held) {
+			spin_lock_bh(&sc->tx.txbuflock);
+			list_move_tail(&bf_held->list, &sc->tx.txbuf);
+			spin_unlock_bh(&sc->tx.txbuflock);
+		}
+
+		if (!bf_isampdu(bf)) {
+			/*
+			 * This frame is sent out as a single frame.
+			 * Use hardware retry status for this frame.
+			 */
+			bf->bf_retries = ds->ds_txstat.ts_longretry;
+			if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
+				bf->bf_state.bf_type |= BUF_XRETRY;
+			ath_tx_rc_status(bf, ds, 0, txok, true);
+		}
+
+		if (bf_isampdu(bf))
+			ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
+		else
+			ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
+
+		ath_wake_mac80211_queue(sc, txq);
+
+		spin_lock_bh(&txq->axq_lock);
+		if (sc->sc_flags & SC_OP_TXAGGR)
+			ath_txq_schedule(sc, txq);
+		spin_unlock_bh(&txq->axq_lock);
+	}
+}
+
+
+void ath_tx_tasklet(struct ath_softc *sc)
+{
+	int i;
+	u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
+
+	ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
+
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+		if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
+			ath_tx_processq(sc, &sc->tx.txq[i]);
+	}
+}
+
+/*****************/
+/* Init, Cleanup */
+/*****************/
+
+int ath_tx_init(struct ath_softc *sc, int nbufs)
+{
+	int error = 0;
+
+	spin_lock_init(&sc->tx.txbuflock);
+
+	error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
+				  "tx", nbufs, 1);
+	if (error != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Failed to allocate tx descriptors: %d\n", error);
+		goto err;
+	}
+
+	error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
+				  "beacon", ATH_BCBUF, 1);
+	if (error != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Failed to allocate beacon descriptors: %d\n", error);
+		goto err;
+	}
+
+err:
+	if (error != 0)
+		ath_tx_cleanup(sc);
+
+	return error;
+}
+
+void ath_tx_cleanup(struct ath_softc *sc)
+{
+	if (sc->beacon.bdma.dd_desc_len != 0)
+		ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
+
+	if (sc->tx.txdma.dd_desc_len != 0)
+		ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
+}
+
+void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
+{
+	struct ath_atx_tid *tid;
+	struct ath_atx_ac *ac;
+	int tidno, acno;
+
+	for (tidno = 0, tid = &an->tid[tidno];
+	     tidno < WME_NUM_TID;
+	     tidno++, tid++) {
+		tid->an        = an;
+		tid->tidno     = tidno;
+		tid->seq_start = tid->seq_next = 0;
+		tid->baw_size  = WME_MAX_BA;
+		tid->baw_head  = tid->baw_tail = 0;
+		tid->sched     = false;
+		tid->paused    = false;
+		tid->state &= ~AGGR_CLEANUP;
+		INIT_LIST_HEAD(&tid->buf_q);
+		acno = TID_TO_WME_AC(tidno);
+		tid->ac = &an->ac[acno];
+		tid->state &= ~AGGR_ADDBA_COMPLETE;
+		tid->state &= ~AGGR_ADDBA_PROGRESS;
+		tid->addba_exchangeattempts = 0;
+	}
+
+	for (acno = 0, ac = &an->ac[acno];
+	     acno < WME_NUM_AC; acno++, ac++) {
+		ac->sched    = false;
+		INIT_LIST_HEAD(&ac->tid_q);
+
+		switch (acno) {
+		case WME_AC_BE:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
+			break;
+		case WME_AC_BK:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK);
+			break;
+		case WME_AC_VI:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI);
+			break;
+		case WME_AC_VO:
+			ac->qnum = ath_tx_get_qnum(sc,
+				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO);
+			break;
+		}
+	}
+}
+
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
+{
+	int i;
+	struct ath_atx_ac *ac, *ac_tmp;
+	struct ath_atx_tid *tid, *tid_tmp;
+	struct ath_txq *txq;
+
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+		if (ATH_TXQ_SETUP(sc, i)) {
+			txq = &sc->tx.txq[i];
+
+			spin_lock(&txq->axq_lock);
+
+			list_for_each_entry_safe(ac,
+					ac_tmp, &txq->axq_acq, list) {
+				tid = list_first_entry(&ac->tid_q,
+						struct ath_atx_tid, list);
+				if (tid && tid->an != an)
+					continue;
+				list_del(&ac->list);
+				ac->sched = false;
+
+				list_for_each_entry_safe(tid,
+						tid_tmp, &ac->tid_q, list) {
+					list_del(&tid->list);
+					tid->sched = false;
+					ath_tid_drain(sc, txq, tid);
+					tid->state &= ~AGGR_ADDBA_COMPLETE;
+					tid->addba_exchangeattempts = 0;
+					tid->state &= ~AGGR_CLEANUP;
+				}
+			}
+
+			spin_unlock(&txq->axq_lock);
+		}
+	}
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/ath/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,9 @@
+config ATH_COMMON
+	tristate "Atheros Wireless Cards"
+	depends on WLAN_80211
+	depends on ATH5K || ATH9K || AR9170_USB
+
+source "drivers/net/wireless/ath/ath5k/Kconfig"
+source "drivers/net/wireless/ath/ath9k/Kconfig"
+source "drivers/net/wireless/ath/ar9170/Kconfig"
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
+MODULE_LICENSE("Dual BSD/GPL");
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/ath/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,6 @@
+obj-$(CONFIG_ATH5K)		+= ath5k/
+obj-$(CONFIG_ATH9K)		+= ath9k/
+obj-$(CONFIG_AR9170_USB)        += ar9170/
+
+obj-$(CONFIG_ATH_COMMON)	+= ath.o
+ath-objs 		:= main.o regd.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/regd.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath/regd.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/regd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/regd.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,592 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include "regd.h"
+#include "regd_common.h"
+
+/*
+ * This is a set of common rules used by our world regulatory domains.
+ * We have 12 world regulatory domains. To save space we consolidate
+ * the regulatory domains in 5 structures by frequency and change
+ * the flags on our reg_notifier() on a case by case basis.
+ */
+
+/* Only these channels all allow active scan on all world regulatory domains */
+#define ATH9K_2GHZ_CH01_11	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
+
+/* We enable active scan on these a case by case basis by regulatory domain */
+#define ATH9K_2GHZ_CH12_13	REG_RULE(2467-10, 2472+10, 40, 0, 20,\
+					NL80211_RRF_PASSIVE_SCAN)
+#define ATH9K_2GHZ_CH14		REG_RULE(2484-10, 2484+10, 40, 0, 20,\
+				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+
+/* We allow IBSS on these on a case by case basis by regulatory domain */
+#define ATH9K_5GHZ_5150_5350	REG_RULE(5150-10, 5350+10, 40, 0, 30,\
+				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+#define ATH9K_5GHZ_5470_5850	REG_RULE(5470-10, 5850+10, 40, 0, 30,\
+				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+#define ATH9K_5GHZ_5725_5850	REG_RULE(5725-10, 5850+10, 40, 0, 30,\
+				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+
+#define ATH9K_2GHZ_ALL		ATH9K_2GHZ_CH01_11, \
+				ATH9K_2GHZ_CH12_13, \
+				ATH9K_2GHZ_CH14
+
+#define ATH9K_5GHZ_ALL		ATH9K_5GHZ_5150_5350, \
+				ATH9K_5GHZ_5470_5850
+/* This one skips what we call "mid band" */
+#define ATH9K_5GHZ_NO_MIDBAND	ATH9K_5GHZ_5150_5350, \
+				ATH9K_5GHZ_5725_5850
+
+/* Can be used for:
+ * 0x60, 0x61, 0x62 */
+static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
+	.n_reg_rules = 5,
+	.alpha2 =  "99",
+	.reg_rules = {
+		ATH9K_2GHZ_ALL,
+		ATH9K_5GHZ_ALL,
+	}
+};
+
+/* Can be used by 0x63 and 0x65 */
+static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
+	.n_reg_rules = 4,
+	.alpha2 =  "99",
+	.reg_rules = {
+		ATH9K_2GHZ_CH01_11,
+		ATH9K_2GHZ_CH12_13,
+		ATH9K_5GHZ_NO_MIDBAND,
+	}
+};
+
+/* Can be used by 0x64 only */
+static const struct ieee80211_regdomain ath_world_regdom_64 = {
+	.n_reg_rules = 3,
+	.alpha2 =  "99",
+	.reg_rules = {
+		ATH9K_2GHZ_CH01_11,
+		ATH9K_5GHZ_NO_MIDBAND,
+	}
+};
+
+/* Can be used by 0x66 and 0x69 */
+static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
+	.n_reg_rules = 3,
+	.alpha2 =  "99",
+	.reg_rules = {
+		ATH9K_2GHZ_CH01_11,
+		ATH9K_5GHZ_ALL,
+	}
+};
+
+/* Can be used by 0x67, 0x6A and 0x68 */
+static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
+	.n_reg_rules = 4,
+	.alpha2 =  "99",
+	.reg_rules = {
+		ATH9K_2GHZ_CH01_11,
+		ATH9K_2GHZ_CH12_13,
+		ATH9K_5GHZ_ALL,
+	}
+};
+
+static inline bool is_wwr_sku(u16 regd)
+{
+	return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
+		(regd == WORLD);
+}
+
+static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
+{
+	return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
+}
+
+bool ath_is_world_regd(struct ath_regulatory *reg)
+{
+	return is_wwr_sku(ath_regd_get_eepromRD(reg));
+}
+EXPORT_SYMBOL(ath_is_world_regd);
+
+static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
+{
+	/* this is the most restrictive */
+	return &ath_world_regdom_64;
+}
+
+static const struct
+ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
+{
+	switch (reg->regpair->regDmnEnum) {
+	case 0x60:
+	case 0x61:
+	case 0x62:
+		return &ath_world_regdom_60_61_62;
+	case 0x63:
+	case 0x65:
+		return &ath_world_regdom_63_65;
+	case 0x64:
+		return &ath_world_regdom_64;
+	case 0x66:
+	case 0x69:
+		return &ath_world_regdom_66_69;
+	case 0x67:
+	case 0x68:
+	case 0x6A:
+		return &ath_world_regdom_67_68_6A;
+	default:
+		WARN_ON(1);
+		return ath_default_world_regdomain();
+	}
+}
+
+/* Frequency is one where radar detection is required */
+static bool ath_is_radar_freq(u16 center_freq)
+{
+	return (center_freq >= 5260 && center_freq <= 5700);
+}
+
+/*
+ * N.B: These exception rules do not apply radar freqs.
+ *
+ * - We enable adhoc (or beaconing) if allowed by 11d
+ * - We enable active scan if the channel is allowed by 11d
+ * - If no country IE has been processed and a we determine we have
+ *   received a beacon on a channel we can enable active scan and
+ *   adhoc (or beaconing).
+ */
+static void
+ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
+			      enum nl80211_reg_initiator initiator)
+{
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	const struct ieee80211_reg_rule *reg_rule;
+	struct ieee80211_channel *ch;
+	unsigned int i;
+	u32 bandwidth = 0;
+	int r;
+
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+		if (!wiphy->bands[band])
+			continue;
+
+		sband = wiphy->bands[band];
+
+		for (i = 0; i < sband->n_channels; i++) {
+
+			ch = &sband->channels[i];
+
+			if (ath_is_radar_freq(ch->center_freq) ||
+			    (ch->flags & IEEE80211_CHAN_RADAR))
+				continue;
+
+			if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
+				r = freq_reg_info(wiphy,
+						  ch->center_freq,
+						  bandwidth,
+						  &reg_rule);
+				if (r)
+					continue;
+				/*
+				 * If 11d had a rule for this channel ensure
+				 * we enable adhoc/beaconing if it allows us to
+				 * use it. Note that we would have disabled it
+				 * by applying our static world regdomain by
+				 * default during init, prior to calling our
+				 * regulatory_hint().
+				 */
+				if (!(reg_rule->flags &
+				    NL80211_RRF_NO_IBSS))
+					ch->flags &=
+					  ~IEEE80211_CHAN_NO_IBSS;
+				if (!(reg_rule->flags &
+				    NL80211_RRF_PASSIVE_SCAN))
+					ch->flags &=
+					  ~IEEE80211_CHAN_PASSIVE_SCAN;
+			} else {
+				if (ch->beacon_found)
+					ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
+					  IEEE80211_CHAN_PASSIVE_SCAN);
+			}
+		}
+	}
+
+}
+
+/* Allows active scan scan on Ch 12 and 13 */
+static void
+ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
+				enum nl80211_reg_initiator initiator)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	const struct ieee80211_reg_rule *reg_rule;
+	u32 bandwidth = 0;
+	int r;
+
+	sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+
+	/*
+	 * If no country IE has been received always enable active scan
+	 * on these channels. This is only done for specific regulatory SKUs
+	 */
+	if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
+		ch = &sband->channels[11]; /* CH 12 */
+		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+		ch = &sband->channels[12]; /* CH 13 */
+		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+		return;
+	}
+
+	/*
+	 * If a country IE has been recieved check its rule for this
+	 * channel first before enabling active scan. The passive scan
+	 * would have been enforced by the initial processing of our
+	 * custom regulatory domain.
+	 */
+
+	ch = &sband->channels[11]; /* CH 12 */
+	r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
+	if (!r) {
+		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
+			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+	}
+
+	ch = &sband->channels[12]; /* CH 13 */
+	r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
+	if (!r) {
+		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
+			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+	}
+}
+
+/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
+static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	unsigned int i;
+
+	if (!wiphy->bands[IEEE80211_BAND_5GHZ])
+		return;
+
+	sband = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+	for (i = 0; i < sband->n_channels; i++) {
+		ch = &sband->channels[i];
+		if (!ath_is_radar_freq(ch->center_freq))
+			continue;
+		/* We always enable radar detection/DFS on this
+		 * frequency range. Additionally we also apply on
+		 * this frequency range:
+		 * - If STA mode does not yet have DFS supports disable
+		 *   active scanning
+		 * - If adhoc mode does not support DFS yet then
+		 *   disable adhoc in the frequency.
+		 * - If AP mode does not yet support radar detection/DFS
+		 *   do not allow AP mode
+		 */
+		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+			ch->flags |= IEEE80211_CHAN_RADAR |
+				     IEEE80211_CHAN_NO_IBSS |
+				     IEEE80211_CHAN_PASSIVE_SCAN;
+	}
+}
+
+static void ath_reg_apply_world_flags(struct wiphy *wiphy,
+				      enum nl80211_reg_initiator initiator,
+				      struct ath_regulatory *reg)
+{
+	switch (reg->regpair->regDmnEnum) {
+	case 0x60:
+	case 0x63:
+	case 0x66:
+	case 0x67:
+		ath_reg_apply_beaconing_flags(wiphy, initiator);
+		break;
+	case 0x68:
+		ath_reg_apply_beaconing_flags(wiphy, initiator);
+		ath_reg_apply_active_scan_flags(wiphy, initiator);
+		break;
+	}
+	return;
+}
+
+int ath_reg_notifier_apply(struct wiphy *wiphy,
+			   struct regulatory_request *request,
+			   struct ath_regulatory *reg)
+{
+	/* We always apply this */
+	ath_reg_apply_radar_flags(wiphy);
+
+	switch (request->initiator) {
+	case NL80211_REGDOM_SET_BY_DRIVER:
+	case NL80211_REGDOM_SET_BY_CORE:
+	case NL80211_REGDOM_SET_BY_USER:
+		break;
+	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+		if (ath_is_world_regd(reg))
+			ath_reg_apply_world_flags(wiphy, request->initiator,
+						  reg);
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ath_reg_notifier_apply);
+
+static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
+{
+	 u16 rd = ath_regd_get_eepromRD(reg);
+	int i;
+
+	if (rd & COUNTRY_ERD_FLAG) {
+		/* EEPROM value is a country code */
+		u16 cc = rd & ~COUNTRY_ERD_FLAG;
+		printk(KERN_DEBUG
+		       "ath: EEPROM indicates we should expect "
+			"a country code\n");
+		for (i = 0; i < ARRAY_SIZE(allCountries); i++)
+			if (allCountries[i].countryCode == cc)
+				return true;
+	} else {
+		/* EEPROM value is a regpair value */
+		if (rd != CTRY_DEFAULT)
+			printk(KERN_DEBUG "ath: EEPROM indicates we "
+			       "should expect a direct regpair map\n");
+		for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
+			if (regDomainPairs[i].regDmnEnum == rd)
+				return true;
+	}
+	printk(KERN_DEBUG
+		 "ath: invalid regulatory domain/country code 0x%x\n", rd);
+	return false;
+}
+
+/* EEPROM country code to regpair mapping */
+static struct country_code_to_enum_rd*
+ath_regd_find_country(u16 countryCode)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+		if (allCountries[i].countryCode == countryCode)
+			return &allCountries[i];
+	}
+	return NULL;
+}
+
+/* EEPROM rd code to regpair mapping */
+static struct country_code_to_enum_rd*
+ath_regd_find_country_by_rd(int regdmn)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+		if (allCountries[i].regDmnEnum == regdmn)
+			return &allCountries[i];
+	}
+	return NULL;
+}
+
+/* Returns the map of the EEPROM set RD to a country code */
+static u16 ath_regd_get_default_country(u16 rd)
+{
+	if (rd & COUNTRY_ERD_FLAG) {
+		struct country_code_to_enum_rd *country = NULL;
+		u16 cc = rd & ~COUNTRY_ERD_FLAG;
+
+		country = ath_regd_find_country(cc);
+		if (country != NULL)
+			return cc;
+	}
+
+	return CTRY_DEFAULT;
+}
+
+static struct reg_dmn_pair_mapping*
+ath_get_regpair(int regdmn)
+{
+	int i;
+
+	if (regdmn == NO_ENUMRD)
+		return NULL;
+	for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
+		if (regDomainPairs[i].regDmnEnum == regdmn)
+			return &regDomainPairs[i];
+	}
+	return NULL;
+}
+
+static int
+ath_regd_init_wiphy(struct ath_regulatory *reg,
+		    struct wiphy *wiphy,
+		    int (*reg_notifier)(struct wiphy *wiphy,
+					struct regulatory_request *request))
+{
+	const struct ieee80211_regdomain *regd;
+
+	wiphy->reg_notifier = reg_notifier;
+	wiphy->strict_regulatory = true;
+
+	if (ath_is_world_regd(reg)) {
+		/*
+		 * Anything applied here (prior to wiphy registration) gets
+		 * saved on the wiphy orig_* parameters
+		 */
+		regd = ath_world_regdomain(reg);
+		wiphy->custom_regulatory = true;
+		wiphy->strict_regulatory = false;
+	} else {
+		/*
+		 * This gets applied in the case of the absense of CRDA,
+		 * it's our own custom world regulatory domain, similar to
+		 * cfg80211's but we enable passive scanning.
+		 */
+		regd = ath_default_world_regdomain();
+	}
+	wiphy_apply_custom_regulatory(wiphy, regd);
+	ath_reg_apply_radar_flags(wiphy);
+	ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
+	return 0;
+}
+
+/*
+ * Some users have reported their EEPROM programmed with
+ * 0x8000 set, this is not a supported regulatory domain
+ * but since we have more than one user with it we need
+ * a solution for them. We default to 0x64, which is the
+ * default Atheros world regulatory domain.
+ */
+static void ath_regd_sanitize(struct ath_regulatory *reg)
+{
+	if (reg->current_rd != COUNTRY_ERD_FLAG)
+		return;
+	printk(KERN_DEBUG "ath: EEPROM regdomain sanitized\n");
+	reg->current_rd = 0x64;
+}
+
+int
+ath_regd_init(struct ath_regulatory *reg,
+	      struct wiphy *wiphy,
+	      int (*reg_notifier)(struct wiphy *wiphy,
+				  struct regulatory_request *request))
+{
+	struct country_code_to_enum_rd *country = NULL;
+	u16 regdmn;
+
+	if (!reg)
+		return -EINVAL;
+
+	ath_regd_sanitize(reg);
+
+	printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
+
+	if (!ath_regd_is_eeprom_valid(reg)) {
+		printk(KERN_ERR "ath: Invalid EEPROM contents\n");
+		return -EINVAL;
+	}
+
+	regdmn = ath_regd_get_eepromRD(reg);
+	reg->country_code = ath_regd_get_default_country(regdmn);
+
+	if (reg->country_code == CTRY_DEFAULT &&
+	    regdmn == CTRY_DEFAULT) {
+		printk(KERN_DEBUG "ath: EEPROM indicates default "
+		       "country code should be used\n");
+		reg->country_code = CTRY_UNITED_STATES;
+	}
+
+	if (reg->country_code == CTRY_DEFAULT) {
+		country = NULL;
+	} else {
+		printk(KERN_DEBUG "ath: doing EEPROM country->regdmn "
+		       "map search\n");
+		country = ath_regd_find_country(reg->country_code);
+		if (country == NULL) {
+			printk(KERN_DEBUG
+				"ath: no valid country maps found for "
+				"country code: 0x%0x\n",
+				reg->country_code);
+			return -EINVAL;
+		} else {
+			regdmn = country->regDmnEnum;
+			printk(KERN_DEBUG "ath: country maps to "
+			       "regdmn code: 0x%0x\n",
+			       regdmn);
+		}
+	}
+
+	reg->regpair = ath_get_regpair(regdmn);
+
+	if (!reg->regpair) {
+		printk(KERN_DEBUG "ath: "
+			"No regulatory domain pair found, cannot continue\n");
+		return -EINVAL;
+	}
+
+	if (!country)
+		country = ath_regd_find_country_by_rd(regdmn);
+
+	if (country) {
+		reg->alpha2[0] = country->isoName[0];
+		reg->alpha2[1] = country->isoName[1];
+	} else {
+		reg->alpha2[0] = '0';
+		reg->alpha2[1] = '0';
+	}
+
+	printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n",
+		reg->alpha2[0], reg->alpha2[1]);
+	printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n",
+		reg->regpair->regDmnEnum);
+
+	ath_regd_init_wiphy(reg, wiphy, reg_notifier);
+	return 0;
+}
+EXPORT_SYMBOL(ath_regd_init);
+
+u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
+			  enum ieee80211_band band)
+{
+	if (!reg->regpair ||
+	    (reg->country_code == CTRY_DEFAULT &&
+	     is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
+		return SD_NO_CTL;
+	}
+
+	switch (band) {
+	case IEEE80211_BAND_2GHZ:
+		return reg->regpair->reg_2ghz_ctl;
+	case IEEE80211_BAND_5GHZ:
+		return reg->regpair->reg_5ghz_ctl;
+	default:
+		return NO_CTL;
+	}
+
+	return NO_CTL;
+}
+EXPORT_SYMBOL(ath_regd_get_band_ctl);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/regd_common.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/regd_common.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/regd_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/regd_common.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REGD_COMMON_H
+#define REGD_COMMON_H
+
+enum EnumRd {
+	NO_ENUMRD = 0x00,
+	NULL1_WORLD = 0x03,
+	NULL1_ETSIB = 0x07,
+	NULL1_ETSIC = 0x08,
+	FCC1_FCCA = 0x10,
+	FCC1_WORLD = 0x11,
+	FCC4_FCCA = 0x12,
+	FCC5_FCCA = 0x13,
+	FCC6_FCCA = 0x14,
+
+	FCC2_FCCA = 0x20,
+	FCC2_WORLD = 0x21,
+	FCC2_ETSIC = 0x22,
+	FCC6_WORLD = 0x23,
+	FRANCE_RES = 0x31,
+	FCC3_FCCA = 0x3A,
+	FCC3_WORLD = 0x3B,
+
+	ETSI1_WORLD = 0x37,
+	ETSI3_ETSIA = 0x32,
+	ETSI2_WORLD = 0x35,
+	ETSI3_WORLD = 0x36,
+	ETSI4_WORLD = 0x30,
+	ETSI4_ETSIC = 0x38,
+	ETSI5_WORLD = 0x39,
+	ETSI6_WORLD = 0x34,
+	ETSI_RESERVED = 0x33,
+
+	MKK1_MKKA = 0x40,
+	MKK1_MKKB = 0x41,
+	APL4_WORLD = 0x42,
+	MKK2_MKKA = 0x43,
+	APL_RESERVED = 0x44,
+	APL2_WORLD = 0x45,
+	APL2_APLC = 0x46,
+	APL3_WORLD = 0x47,
+	MKK1_FCCA = 0x48,
+	APL2_APLD = 0x49,
+	MKK1_MKKA1 = 0x4A,
+	MKK1_MKKA2 = 0x4B,
+	MKK1_MKKC = 0x4C,
+
+	APL3_FCCA = 0x50,
+	APL1_WORLD = 0x52,
+	APL1_FCCA = 0x53,
+	APL1_APLA = 0x54,
+	APL1_ETSIC = 0x55,
+	APL2_ETSIC = 0x56,
+	APL5_WORLD = 0x58,
+	APL6_WORLD = 0x5B,
+	APL7_FCCA = 0x5C,
+	APL8_WORLD = 0x5D,
+	APL9_WORLD = 0x5E,
+
+	WOR0_WORLD = 0x60,
+	WOR1_WORLD = 0x61,
+	WOR2_WORLD = 0x62,
+	WOR3_WORLD = 0x63,
+	WOR4_WORLD = 0x64,
+	WOR5_ETSIC = 0x65,
+
+	WOR01_WORLD = 0x66,
+	WOR02_WORLD = 0x67,
+	EU1_WORLD = 0x68,
+
+	WOR9_WORLD = 0x69,
+	WORA_WORLD = 0x6A,
+	WORB_WORLD = 0x6B,
+
+	MKK3_MKKB = 0x80,
+	MKK3_MKKA2 = 0x81,
+	MKK3_MKKC = 0x82,
+
+	MKK4_MKKB = 0x83,
+	MKK4_MKKA2 = 0x84,
+	MKK4_MKKC = 0x85,
+
+	MKK5_MKKB = 0x86,
+	MKK5_MKKA2 = 0x87,
+	MKK5_MKKC = 0x88,
+
+	MKK6_MKKB = 0x89,
+	MKK6_MKKA2 = 0x8A,
+	MKK6_MKKC = 0x8B,
+
+	MKK7_MKKB = 0x8C,
+	MKK7_MKKA2 = 0x8D,
+	MKK7_MKKC = 0x8E,
+
+	MKK8_MKKB = 0x8F,
+	MKK8_MKKA2 = 0x90,
+	MKK8_MKKC = 0x91,
+
+	MKK14_MKKA1 = 0x92,
+	MKK15_MKKA1 = 0x93,
+
+	MKK10_FCCA = 0xD0,
+	MKK10_MKKA1 = 0xD1,
+	MKK10_MKKC = 0xD2,
+	MKK10_MKKA2 = 0xD3,
+
+	MKK11_MKKA = 0xD4,
+	MKK11_FCCA = 0xD5,
+	MKK11_MKKA1 = 0xD6,
+	MKK11_MKKC = 0xD7,
+	MKK11_MKKA2 = 0xD8,
+
+	MKK12_MKKA = 0xD9,
+	MKK12_FCCA = 0xDA,
+	MKK12_MKKA1 = 0xDB,
+	MKK12_MKKC = 0xDC,
+	MKK12_MKKA2 = 0xDD,
+
+	MKK13_MKKB = 0xDE,
+
+	MKK3_MKKA = 0xF0,
+	MKK3_MKKA1 = 0xF1,
+	MKK3_FCCA = 0xF2,
+	MKK4_MKKA = 0xF3,
+	MKK4_MKKA1 = 0xF4,
+	MKK4_FCCA = 0xF5,
+	MKK9_MKKA = 0xF6,
+	MKK10_MKKA = 0xF7,
+	MKK6_MKKA1 = 0xF8,
+	MKK6_FCCA = 0xF9,
+	MKK7_MKKA1 = 0xFA,
+	MKK7_FCCA = 0xFB,
+	MKK9_FCCA = 0xFC,
+	MKK9_MKKA1 = 0xFD,
+	MKK9_MKKC = 0xFE,
+	MKK9_MKKA2 = 0xFF,
+
+	WORLD = 0x0199,
+	DEBUG_REG_DMN = 0x01ff,
+};
+
+enum ctl_group {
+	CTL_FCC = 0x10,
+	CTL_MKK = 0x40,
+	CTL_ETSI = 0x30,
+};
+
+/* Regpair to CTL band mapping */
+static struct reg_dmn_pair_mapping regDomainPairs[] = {
+	/* regpair, 5 GHz CTL, 2 GHz CTL */
+	{NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN},
+	{NULL1_WORLD, NO_CTL, CTL_ETSI},
+	{NULL1_ETSIB, NO_CTL, CTL_ETSI},
+	{NULL1_ETSIC, NO_CTL, CTL_ETSI},
+
+	{FCC2_FCCA, CTL_FCC, CTL_FCC},
+	{FCC2_WORLD, CTL_FCC, CTL_ETSI},
+	{FCC2_ETSIC, CTL_FCC, CTL_ETSI},
+	{FCC3_FCCA, CTL_FCC, CTL_FCC},
+	{FCC3_WORLD, CTL_FCC, CTL_ETSI},
+	{FCC4_FCCA, CTL_FCC, CTL_FCC},
+	{FCC5_FCCA, CTL_FCC, CTL_FCC},
+	{FCC6_FCCA, CTL_FCC, CTL_FCC},
+	{FCC6_WORLD, CTL_FCC, CTL_ETSI},
+
+	{ETSI1_WORLD, CTL_ETSI, CTL_ETSI},
+	{ETSI2_WORLD, CTL_ETSI, CTL_ETSI},
+	{ETSI3_WORLD, CTL_ETSI, CTL_ETSI},
+	{ETSI4_WORLD, CTL_ETSI, CTL_ETSI},
+	{ETSI5_WORLD, CTL_ETSI, CTL_ETSI},
+	{ETSI6_WORLD, CTL_ETSI, CTL_ETSI},
+
+	/* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */
+	{ETSI3_ETSIA, CTL_ETSI, CTL_ETSI},
+	{FRANCE_RES, CTL_ETSI, CTL_ETSI},
+
+	{FCC1_WORLD, CTL_FCC, CTL_ETSI},
+	{FCC1_FCCA, CTL_FCC, CTL_FCC},
+	{APL1_WORLD, CTL_FCC, CTL_ETSI},
+	{APL2_WORLD, CTL_FCC, CTL_ETSI},
+	{APL3_WORLD, CTL_FCC, CTL_ETSI},
+	{APL4_WORLD, CTL_FCC, CTL_ETSI},
+	{APL5_WORLD, CTL_FCC, CTL_ETSI},
+	{APL6_WORLD, CTL_ETSI, CTL_ETSI},
+	{APL8_WORLD, CTL_ETSI, CTL_ETSI},
+	{APL9_WORLD, CTL_ETSI, CTL_ETSI},
+
+	{APL3_FCCA, CTL_FCC, CTL_FCC},
+	{APL1_ETSIC, CTL_FCC, CTL_ETSI},
+	{APL2_ETSIC, CTL_FCC, CTL_ETSI},
+	{APL2_APLD, CTL_FCC, NO_CTL},
+
+	{MKK1_MKKA, CTL_MKK, CTL_MKK},
+	{MKK1_MKKB, CTL_MKK, CTL_MKK},
+	{MKK1_FCCA, CTL_MKK, CTL_FCC},
+	{MKK1_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK1_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK1_MKKC, CTL_MKK, CTL_MKK},
+
+	{MKK2_MKKA, CTL_MKK, CTL_MKK},
+	{MKK3_MKKA, CTL_MKK, CTL_MKK},
+	{MKK3_MKKB, CTL_MKK, CTL_MKK},
+	{MKK3_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK3_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK3_MKKC, CTL_MKK, CTL_MKK},
+	{MKK3_FCCA, CTL_MKK, CTL_FCC},
+
+	{MKK4_MKKA, CTL_MKK, CTL_MKK},
+	{MKK4_MKKB, CTL_MKK, CTL_MKK},
+	{MKK4_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK4_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK4_MKKC, CTL_MKK, CTL_MKK},
+	{MKK4_FCCA, CTL_MKK, CTL_FCC},
+
+	{MKK5_MKKB, CTL_MKK, CTL_MKK},
+	{MKK5_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK5_MKKC, CTL_MKK, CTL_MKK},
+
+	{MKK6_MKKB, CTL_MKK, CTL_MKK},
+	{MKK6_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK6_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK6_MKKC, CTL_MKK, CTL_MKK},
+	{MKK6_FCCA, CTL_MKK, CTL_FCC},
+
+	{MKK7_MKKB, CTL_MKK, CTL_MKK},
+	{MKK7_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK7_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK7_MKKC, CTL_MKK, CTL_MKK},
+	{MKK7_FCCA, CTL_MKK, CTL_FCC},
+
+	{MKK8_MKKB, CTL_MKK, CTL_MKK},
+	{MKK8_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK8_MKKC, CTL_MKK, CTL_MKK},
+
+	{MKK9_MKKA, CTL_MKK, CTL_MKK},
+	{MKK9_FCCA, CTL_MKK, CTL_FCC},
+	{MKK9_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK9_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK9_MKKC, CTL_MKK, CTL_MKK},
+
+	{MKK10_MKKA, CTL_MKK, CTL_MKK},
+	{MKK10_FCCA, CTL_MKK, CTL_FCC},
+	{MKK10_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK10_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK10_MKKC, CTL_MKK, CTL_MKK},
+
+	{MKK11_MKKA, CTL_MKK, CTL_MKK},
+	{MKK11_FCCA, CTL_MKK, CTL_FCC},
+	{MKK11_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK11_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK11_MKKC, CTL_MKK, CTL_MKK},
+
+	{MKK12_MKKA, CTL_MKK, CTL_MKK},
+	{MKK12_FCCA, CTL_MKK, CTL_FCC},
+	{MKK12_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK12_MKKA2, CTL_MKK, CTL_MKK},
+	{MKK12_MKKC, CTL_MKK, CTL_MKK},
+
+	{MKK13_MKKB, CTL_MKK, CTL_MKK},
+	{MKK14_MKKA1, CTL_MKK, CTL_MKK},
+	{MKK15_MKKA1, CTL_MKK, CTL_MKK},
+
+	{WOR0_WORLD, NO_CTL, NO_CTL},
+	{WOR1_WORLD, NO_CTL, NO_CTL},
+	{WOR2_WORLD, NO_CTL, NO_CTL},
+	{WOR3_WORLD, NO_CTL, NO_CTL},
+	{WOR4_WORLD, NO_CTL, NO_CTL},
+	{WOR5_ETSIC, NO_CTL, NO_CTL},
+	{WOR01_WORLD, NO_CTL, NO_CTL},
+	{WOR02_WORLD, NO_CTL, NO_CTL},
+	{EU1_WORLD, NO_CTL, NO_CTL},
+	{WOR9_WORLD, NO_CTL, NO_CTL},
+	{WORA_WORLD, NO_CTL, NO_CTL},
+	{WORB_WORLD, NO_CTL, NO_CTL},
+};
+
+static struct country_code_to_enum_rd allCountries[] = {
+	{CTRY_DEBUG, NO_ENUMRD, "DB"},
+	{CTRY_DEFAULT, FCC1_FCCA, "CO"},
+	{CTRY_ALBANIA, NULL1_WORLD, "AL"},
+	{CTRY_ALGERIA, NULL1_WORLD, "DZ"},
+	{CTRY_ARGENTINA, APL3_WORLD, "AR"},
+	{CTRY_ARMENIA, ETSI4_WORLD, "AM"},
+	{CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
+	{CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
+	{CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
+	{CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
+	{CTRY_BAHRAIN, APL6_WORLD, "BH"},
+	{CTRY_BELARUS, ETSI1_WORLD, "BY"},
+	{CTRY_BELGIUM, ETSI1_WORLD, "BE"},
+	{CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
+	{CTRY_BELIZE, APL1_ETSIC, "BZ"},
+	{CTRY_BOLIVIA, APL1_ETSIC, "BO"},
+	{CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"},
+	{CTRY_BRAZIL, FCC3_WORLD, "BR"},
+	{CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
+	{CTRY_BULGARIA, ETSI6_WORLD, "BG"},
+	{CTRY_CANADA, FCC2_FCCA, "CA"},
+	{CTRY_CANADA2, FCC6_FCCA, "CA"},
+	{CTRY_CHILE, APL6_WORLD, "CL"},
+	{CTRY_CHINA, APL1_WORLD, "CN"},
+	{CTRY_COLOMBIA, FCC1_FCCA, "CO"},
+	{CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
+	{CTRY_CROATIA, ETSI3_WORLD, "HR"},
+	{CTRY_CYPRUS, ETSI1_WORLD, "CY"},
+	{CTRY_CZECH, ETSI3_WORLD, "CZ"},
+	{CTRY_DENMARK, ETSI1_WORLD, "DK"},
+	{CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"},
+	{CTRY_ECUADOR, FCC1_WORLD, "EC"},
+	{CTRY_EGYPT, ETSI3_WORLD, "EG"},
+	{CTRY_EL_SALVADOR, FCC1_WORLD, "SV"},
+	{CTRY_ESTONIA, ETSI1_WORLD, "EE"},
+	{CTRY_FINLAND, ETSI1_WORLD, "FI"},
+	{CTRY_FRANCE, ETSI1_WORLD, "FR"},
+	{CTRY_GEORGIA, ETSI4_WORLD, "GE"},
+	{CTRY_GERMANY, ETSI1_WORLD, "DE"},
+	{CTRY_GREECE, ETSI1_WORLD, "GR"},
+	{CTRY_GUATEMALA, FCC1_FCCA, "GT"},
+	{CTRY_HONDURAS, NULL1_WORLD, "HN"},
+	{CTRY_HONG_KONG, FCC2_WORLD, "HK"},
+	{CTRY_HUNGARY, ETSI1_WORLD, "HU"},
+	{CTRY_ICELAND, ETSI1_WORLD, "IS"},
+	{CTRY_INDIA, APL6_WORLD, "IN"},
+	{CTRY_INDONESIA, APL1_WORLD, "ID"},
+	{CTRY_IRAN, APL1_WORLD, "IR"},
+	{CTRY_IRELAND, ETSI1_WORLD, "IE"},
+	{CTRY_ISRAEL, NULL1_WORLD, "IL"},
+	{CTRY_ITALY, ETSI1_WORLD, "IT"},
+	{CTRY_JAMAICA, ETSI1_WORLD, "JM"},
+
+	{CTRY_JAPAN, MKK1_MKKA, "JP"},
+	{CTRY_JAPAN1, MKK1_MKKB, "JP"},
+	{CTRY_JAPAN2, MKK1_FCCA, "JP"},
+	{CTRY_JAPAN3, MKK2_MKKA, "JP"},
+	{CTRY_JAPAN4, MKK1_MKKA1, "JP"},
+	{CTRY_JAPAN5, MKK1_MKKA2, "JP"},
+	{CTRY_JAPAN6, MKK1_MKKC, "JP"},
+	{CTRY_JAPAN7, MKK3_MKKB, "JP"},
+	{CTRY_JAPAN8, MKK3_MKKA2, "JP"},
+	{CTRY_JAPAN9, MKK3_MKKC, "JP"},
+	{CTRY_JAPAN10, MKK4_MKKB, "JP"},
+	{CTRY_JAPAN11, MKK4_MKKA2, "JP"},
+	{CTRY_JAPAN12, MKK4_MKKC, "JP"},
+	{CTRY_JAPAN13, MKK5_MKKB, "JP"},
+	{CTRY_JAPAN14, MKK5_MKKA2, "JP"},
+	{CTRY_JAPAN15, MKK5_MKKC, "JP"},
+	{CTRY_JAPAN16, MKK6_MKKB, "JP"},
+	{CTRY_JAPAN17, MKK6_MKKA2, "JP"},
+	{CTRY_JAPAN18, MKK6_MKKC, "JP"},
+	{CTRY_JAPAN19, MKK7_MKKB, "JP"},
+	{CTRY_JAPAN20, MKK7_MKKA2, "JP"},
+	{CTRY_JAPAN21, MKK7_MKKC, "JP"},
+	{CTRY_JAPAN22, MKK8_MKKB, "JP"},
+	{CTRY_JAPAN23, MKK8_MKKA2, "JP"},
+	{CTRY_JAPAN24, MKK8_MKKC, "JP"},
+	{CTRY_JAPAN25, MKK3_MKKA, "JP"},
+	{CTRY_JAPAN26, MKK3_MKKA1, "JP"},
+	{CTRY_JAPAN27, MKK3_FCCA, "JP"},
+	{CTRY_JAPAN28, MKK4_MKKA1, "JP"},
+	{CTRY_JAPAN29, MKK4_FCCA, "JP"},
+	{CTRY_JAPAN30, MKK6_MKKA1, "JP"},
+	{CTRY_JAPAN31, MKK6_FCCA, "JP"},
+	{CTRY_JAPAN32, MKK7_MKKA1, "JP"},
+	{CTRY_JAPAN33, MKK7_FCCA, "JP"},
+	{CTRY_JAPAN34, MKK9_MKKA, "JP"},
+	{CTRY_JAPAN35, MKK10_MKKA, "JP"},
+	{CTRY_JAPAN36, MKK4_MKKA, "JP"},
+	{CTRY_JAPAN37, MKK9_FCCA, "JP"},
+	{CTRY_JAPAN38, MKK9_MKKA1, "JP"},
+	{CTRY_JAPAN39, MKK9_MKKC, "JP"},
+	{CTRY_JAPAN40, MKK9_MKKA2, "JP"},
+	{CTRY_JAPAN41, MKK10_FCCA, "JP"},
+	{CTRY_JAPAN42, MKK10_MKKA1, "JP"},
+	{CTRY_JAPAN43, MKK10_MKKC, "JP"},
+	{CTRY_JAPAN44, MKK10_MKKA2, "JP"},
+	{CTRY_JAPAN45, MKK11_MKKA, "JP"},
+	{CTRY_JAPAN46, MKK11_FCCA, "JP"},
+	{CTRY_JAPAN47, MKK11_MKKA1, "JP"},
+	{CTRY_JAPAN48, MKK11_MKKC, "JP"},
+	{CTRY_JAPAN49, MKK11_MKKA2, "JP"},
+	{CTRY_JAPAN50, MKK12_MKKA, "JP"},
+	{CTRY_JAPAN51, MKK12_FCCA, "JP"},
+	{CTRY_JAPAN52, MKK12_MKKA1, "JP"},
+	{CTRY_JAPAN53, MKK12_MKKC, "JP"},
+	{CTRY_JAPAN54, MKK12_MKKA2, "JP"},
+	{CTRY_JAPAN57, MKK13_MKKB, "JP"},
+	{CTRY_JAPAN58, MKK14_MKKA1, "JP"},
+	{CTRY_JAPAN59, MKK15_MKKA1, "JP"},
+
+	{CTRY_JORDAN, ETSI2_WORLD, "JO"},
+	{CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"},
+	{CTRY_KOREA_NORTH, APL9_WORLD, "KP"},
+	{CTRY_KOREA_ROC, APL9_WORLD, "KR"},
+	{CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
+	{CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
+	{CTRY_KUWAIT, NULL1_WORLD, "KW"},
+	{CTRY_LATVIA, ETSI1_WORLD, "LV"},
+	{CTRY_LEBANON, NULL1_WORLD, "LB"},
+	{CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"},
+	{CTRY_LITHUANIA, ETSI1_WORLD, "LT"},
+	{CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"},
+	{CTRY_MACAU, FCC2_WORLD, "MO"},
+	{CTRY_MACEDONIA, NULL1_WORLD, "MK"},
+	{CTRY_MALAYSIA, APL8_WORLD, "MY"},
+	{CTRY_MALTA, ETSI1_WORLD, "MT"},
+	{CTRY_MEXICO, FCC1_FCCA, "MX"},
+	{CTRY_MONACO, ETSI4_WORLD, "MC"},
+	{CTRY_MOROCCO, NULL1_WORLD, "MA"},
+	{CTRY_NEPAL, APL1_WORLD, "NP"},
+	{CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
+	{CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
+	{CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
+	{CTRY_NORWAY, ETSI1_WORLD, "NO"},
+	{CTRY_OMAN, APL6_WORLD, "OM"},
+	{CTRY_PAKISTAN, NULL1_WORLD, "PK"},
+	{CTRY_PANAMA, FCC1_FCCA, "PA"},
+	{CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
+	{CTRY_PERU, APL1_WORLD, "PE"},
+	{CTRY_PHILIPPINES, APL1_WORLD, "PH"},
+	{CTRY_POLAND, ETSI1_WORLD, "PL"},
+	{CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
+	{CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
+	{CTRY_QATAR, NULL1_WORLD, "QA"},
+	{CTRY_ROMANIA, NULL1_WORLD, "RO"},
+	{CTRY_RUSSIA, NULL1_WORLD, "RU"},
+	{CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
+	{CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"},
+	{CTRY_SINGAPORE, APL6_WORLD, "SG"},
+	{CTRY_SLOVAKIA, ETSI1_WORLD, "SK"},
+	{CTRY_SLOVENIA, ETSI1_WORLD, "SI"},
+	{CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"},
+	{CTRY_SPAIN, ETSI1_WORLD, "ES"},
+	{CTRY_SRI_LANKA, FCC3_WORLD, "LK"},
+	{CTRY_SWEDEN, ETSI1_WORLD, "SE"},
+	{CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
+	{CTRY_SYRIA, NULL1_WORLD, "SY"},
+	{CTRY_TAIWAN, APL3_FCCA, "TW"},
+	{CTRY_THAILAND, NULL1_WORLD, "TH"},
+	{CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"},
+	{CTRY_TUNISIA, ETSI3_WORLD, "TN"},
+	{CTRY_TURKEY, ETSI3_WORLD, "TR"},
+	{CTRY_UKRAINE, NULL1_WORLD, "UA"},
+	{CTRY_UAE, NULL1_WORLD, "AE"},
+	{CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
+	{CTRY_UNITED_STATES, FCC3_FCCA, "US"},
+	/* This "PS" is for US public safety actually... to support this we
+	 * would need to assign new special alpha2 to CRDA db as with the world
+	 * regdomain and use another alpha2 */
+	{CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"},
+	{CTRY_URUGUAY, APL2_WORLD, "UY"},
+	{CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"},
+	{CTRY_VENEZUELA, APL2_ETSIC, "VE"},
+	{CTRY_VIET_NAM, NULL1_WORLD, "VN"},
+	{CTRY_YEMEN, NULL1_WORLD, "YE"},
+	{CTRY_ZIMBABWE, NULL1_WORLD, "ZW"},
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath/regd.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath/regd.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath/regd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath/regd.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef REGD_H
+#define REGD_H
+
+#include <linux/nl80211.h>
+
+#include <net/cfg80211.h>
+
+#define NO_CTL 0xff
+#define SD_NO_CTL               0xE0
+#define NO_CTL                  0xff
+#define CTL_MODE_M              7
+#define CTL_11A                 0
+#define CTL_11B                 1
+#define CTL_11G                 2
+#define CTL_2GHT20              5
+#define CTL_5GHT20              6
+#define CTL_2GHT40              7
+#define CTL_5GHT40              8
+
+#define CTRY_DEBUG 0x1ff
+#define CTRY_DEFAULT 0
+
+#define COUNTRY_ERD_FLAG        0x8000
+#define WORLDWIDE_ROAMING_FLAG  0x4000
+
+#define MULTI_DOMAIN_MASK 0xFF00
+
+#define WORLD_SKU_MASK          0x00F0
+#define WORLD_SKU_PREFIX        0x0060
+
+#define CHANNEL_HALF_BW         10
+#define CHANNEL_QUARTER_BW      5
+
+struct reg_dmn_pair_mapping {
+	u16 regDmnEnum;
+	u16 reg_5ghz_ctl;
+	u16 reg_2ghz_ctl;
+};
+
+struct country_code_to_enum_rd {
+	u16 countryCode;
+	u16 regDmnEnum;
+	const char *isoName;
+};
+
+struct ath_regulatory {
+	char alpha2[2];
+	u16 country_code;
+	u16 max_power_level;
+	u32 tp_scale;
+	u16 current_rd;
+	u16 current_rd_ext;
+	int16_t power_limit;
+	struct reg_dmn_pair_mapping *regpair;
+};
+
+enum CountryCode {
+	CTRY_ALBANIA = 8,
+	CTRY_ALGERIA = 12,
+	CTRY_ARGENTINA = 32,
+	CTRY_ARMENIA = 51,
+	CTRY_AUSTRALIA = 36,
+	CTRY_AUSTRIA = 40,
+	CTRY_AZERBAIJAN = 31,
+	CTRY_BAHRAIN = 48,
+	CTRY_BELARUS = 112,
+	CTRY_BELGIUM = 56,
+	CTRY_BELIZE = 84,
+	CTRY_BOLIVIA = 68,
+	CTRY_BOSNIA_HERZ = 70,
+	CTRY_BRAZIL = 76,
+	CTRY_BRUNEI_DARUSSALAM = 96,
+	CTRY_BULGARIA = 100,
+	CTRY_CANADA = 124,
+	CTRY_CHILE = 152,
+	CTRY_CHINA = 156,
+	CTRY_COLOMBIA = 170,
+	CTRY_COSTA_RICA = 188,
+	CTRY_CROATIA = 191,
+	CTRY_CYPRUS = 196,
+	CTRY_CZECH = 203,
+	CTRY_DENMARK = 208,
+	CTRY_DOMINICAN_REPUBLIC = 214,
+	CTRY_ECUADOR = 218,
+	CTRY_EGYPT = 818,
+	CTRY_EL_SALVADOR = 222,
+	CTRY_ESTONIA = 233,
+	CTRY_FAEROE_ISLANDS = 234,
+	CTRY_FINLAND = 246,
+	CTRY_FRANCE = 250,
+	CTRY_GEORGIA = 268,
+	CTRY_GERMANY = 276,
+	CTRY_GREECE = 300,
+	CTRY_GUATEMALA = 320,
+	CTRY_HONDURAS = 340,
+	CTRY_HONG_KONG = 344,
+	CTRY_HUNGARY = 348,
+	CTRY_ICELAND = 352,
+	CTRY_INDIA = 356,
+	CTRY_INDONESIA = 360,
+	CTRY_IRAN = 364,
+	CTRY_IRAQ = 368,
+	CTRY_IRELAND = 372,
+	CTRY_ISRAEL = 376,
+	CTRY_ITALY = 380,
+	CTRY_JAMAICA = 388,
+	CTRY_JAPAN = 392,
+	CTRY_JORDAN = 400,
+	CTRY_KAZAKHSTAN = 398,
+	CTRY_KENYA = 404,
+	CTRY_KOREA_NORTH = 408,
+	CTRY_KOREA_ROC = 410,
+	CTRY_KOREA_ROC2 = 411,
+	CTRY_KOREA_ROC3 = 412,
+	CTRY_KUWAIT = 414,
+	CTRY_LATVIA = 428,
+	CTRY_LEBANON = 422,
+	CTRY_LIBYA = 434,
+	CTRY_LIECHTENSTEIN = 438,
+	CTRY_LITHUANIA = 440,
+	CTRY_LUXEMBOURG = 442,
+	CTRY_MACAU = 446,
+	CTRY_MACEDONIA = 807,
+	CTRY_MALAYSIA = 458,
+	CTRY_MALTA = 470,
+	CTRY_MEXICO = 484,
+	CTRY_MONACO = 492,
+	CTRY_MOROCCO = 504,
+	CTRY_NEPAL = 524,
+	CTRY_NETHERLANDS = 528,
+	CTRY_NETHERLANDS_ANTILLES = 530,
+	CTRY_NEW_ZEALAND = 554,
+	CTRY_NICARAGUA = 558,
+	CTRY_NORWAY = 578,
+	CTRY_OMAN = 512,
+	CTRY_PAKISTAN = 586,
+	CTRY_PANAMA = 591,
+	CTRY_PAPUA_NEW_GUINEA = 598,
+	CTRY_PARAGUAY = 600,
+	CTRY_PERU = 604,
+	CTRY_PHILIPPINES = 608,
+	CTRY_POLAND = 616,
+	CTRY_PORTUGAL = 620,
+	CTRY_PUERTO_RICO = 630,
+	CTRY_QATAR = 634,
+	CTRY_ROMANIA = 642,
+	CTRY_RUSSIA = 643,
+	CTRY_SAUDI_ARABIA = 682,
+	CTRY_SERBIA_MONTENEGRO = 891,
+	CTRY_SINGAPORE = 702,
+	CTRY_SLOVAKIA = 703,
+	CTRY_SLOVENIA = 705,
+	CTRY_SOUTH_AFRICA = 710,
+	CTRY_SPAIN = 724,
+	CTRY_SRI_LANKA = 144,
+	CTRY_SWEDEN = 752,
+	CTRY_SWITZERLAND = 756,
+	CTRY_SYRIA = 760,
+	CTRY_TAIWAN = 158,
+	CTRY_THAILAND = 764,
+	CTRY_TRINIDAD_Y_TOBAGO = 780,
+	CTRY_TUNISIA = 788,
+	CTRY_TURKEY = 792,
+	CTRY_UAE = 784,
+	CTRY_UKRAINE = 804,
+	CTRY_UNITED_KINGDOM = 826,
+	CTRY_UNITED_STATES = 840,
+	CTRY_UNITED_STATES_FCC49 = 842,
+	CTRY_URUGUAY = 858,
+	CTRY_UZBEKISTAN = 860,
+	CTRY_VENEZUELA = 862,
+	CTRY_VIET_NAM = 704,
+	CTRY_YEMEN = 887,
+	CTRY_ZIMBABWE = 716,
+	CTRY_JAPAN1 = 393,
+	CTRY_JAPAN2 = 394,
+	CTRY_JAPAN3 = 395,
+	CTRY_JAPAN4 = 396,
+	CTRY_JAPAN5 = 397,
+	CTRY_JAPAN6 = 4006,
+	CTRY_JAPAN7 = 4007,
+	CTRY_JAPAN8 = 4008,
+	CTRY_JAPAN9 = 4009,
+	CTRY_JAPAN10 = 4010,
+	CTRY_JAPAN11 = 4011,
+	CTRY_JAPAN12 = 4012,
+	CTRY_JAPAN13 = 4013,
+	CTRY_JAPAN14 = 4014,
+	CTRY_JAPAN15 = 4015,
+	CTRY_JAPAN16 = 4016,
+	CTRY_JAPAN17 = 4017,
+	CTRY_JAPAN18 = 4018,
+	CTRY_JAPAN19 = 4019,
+	CTRY_JAPAN20 = 4020,
+	CTRY_JAPAN21 = 4021,
+	CTRY_JAPAN22 = 4022,
+	CTRY_JAPAN23 = 4023,
+	CTRY_JAPAN24 = 4024,
+	CTRY_JAPAN25 = 4025,
+	CTRY_JAPAN26 = 4026,
+	CTRY_JAPAN27 = 4027,
+	CTRY_JAPAN28 = 4028,
+	CTRY_JAPAN29 = 4029,
+	CTRY_JAPAN30 = 4030,
+	CTRY_JAPAN31 = 4031,
+	CTRY_JAPAN32 = 4032,
+	CTRY_JAPAN33 = 4033,
+	CTRY_JAPAN34 = 4034,
+	CTRY_JAPAN35 = 4035,
+	CTRY_JAPAN36 = 4036,
+	CTRY_JAPAN37 = 4037,
+	CTRY_JAPAN38 = 4038,
+	CTRY_JAPAN39 = 4039,
+	CTRY_JAPAN40 = 4040,
+	CTRY_JAPAN41 = 4041,
+	CTRY_JAPAN42 = 4042,
+	CTRY_JAPAN43 = 4043,
+	CTRY_JAPAN44 = 4044,
+	CTRY_JAPAN45 = 4045,
+	CTRY_JAPAN46 = 4046,
+	CTRY_JAPAN47 = 4047,
+	CTRY_JAPAN48 = 4048,
+	CTRY_JAPAN49 = 4049,
+	CTRY_JAPAN50 = 4050,
+	CTRY_JAPAN51 = 4051,
+	CTRY_JAPAN52 = 4052,
+	CTRY_JAPAN53 = 4053,
+	CTRY_JAPAN54 = 4054,
+	CTRY_JAPAN55 = 4055,
+	CTRY_JAPAN56 = 4056,
+	CTRY_JAPAN57 = 4057,
+	CTRY_JAPAN58 = 4058,
+	CTRY_JAPAN59 = 4059,
+	CTRY_AUSTRALIA2 = 5000,
+	CTRY_CANADA2 = 5001,
+	CTRY_BELGIUM2 = 5002
+};
+
+bool ath_is_world_regd(struct ath_regulatory *reg);
+int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
+		  int (*reg_notifier)(struct wiphy *wiphy,
+		  struct regulatory_request *request));
+u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
+			  enum ieee80211_band band);
+int ath_reg_notifier_apply(struct wiphy *wiphy,
+			   struct regulatory_request *request,
+			   struct ath_regulatory *reg);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/ath5k.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/ath5k.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/ath5k.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/ath5k.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1353 +0,0 @@
-/*
- * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _ATH5K_H
-#define _ATH5K_H
-
-/* TODO: Clean up channel debuging -doesn't work anyway- and start
- * working on reg. control code using all available eeprom information
- * -rev. engineering needed- */
-#define CHAN_DEBUG	0
-
-#include <linux/io.h>
-#include <linux/types.h>
-#include <net/mac80211.h>
-
-/* RX/TX descriptor hw structs
- * TODO: Driver part should only see sw structs */
-#include "desc.h"
-
-/* EEPROM structs/offsets
- * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities)
- * and clean up common bits, then introduce set/get functions in eeprom.c */
-#include "eeprom.h"
-
-/* PCI IDs */
-#define PCI_DEVICE_ID_ATHEROS_AR5210 		0x0007 /* AR5210 */
-#define PCI_DEVICE_ID_ATHEROS_AR5311 		0x0011 /* AR5311 */
-#define PCI_DEVICE_ID_ATHEROS_AR5211 		0x0012 /* AR5211 */
-#define PCI_DEVICE_ID_ATHEROS_AR5212 		0x0013 /* AR5212 */
-#define PCI_DEVICE_ID_3COM_3CRDAG675 		0x0013 /* 3CRDAG675 (Atheros AR5212) */
-#define PCI_DEVICE_ID_3COM_2_3CRPAG175 		0x0013 /* 3CRPAG175 (Atheros AR5212) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 	0x0207 /* AR5210 (Early) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM	0x1014 /* AR5212 (IBM MiniPCI) */
-#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 	0x1107 /* AR5210 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 	0x1113 /* AR5212 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 	0x1112 /* AR5211 (no eeprom) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 	0xf013 /* AR5212 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 	0xff12 /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 	0xf11b /* AR5211 (emulation board) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 	0x0052 /* AR5312 WMAC (AP31) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 	0x0057 /* AR5312 WMAC (AP30-040) */
-#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 	0x0058 /* AR5312 WMAC (AP43-030) */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 	0x0014 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 	0x0015 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 	0x0016 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 	0x0017 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 	0x0018 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 	0x0019 /* AR5212 compatible */
-#define PCI_DEVICE_ID_ATHEROS_AR2413 		0x001a /* AR2413 (Griffin-lite) */
-#define PCI_DEVICE_ID_ATHEROS_AR5413 		0x001b /* AR5413 (Eagle) */
-#define PCI_DEVICE_ID_ATHEROS_AR5424 		0x001c /* AR5424 (Condor PCI-E) */
-#define PCI_DEVICE_ID_ATHEROS_AR5416 		0x0023 /* AR5416 */
-#define PCI_DEVICE_ID_ATHEROS_AR5418 		0x0024 /* AR5418 */
-
-/****************************\
-  GENERIC DRIVER DEFINITIONS
-\****************************/
-
-#define ATH5K_PRINTF(fmt, ...)   printk("%s: " fmt, __func__, ##__VA_ARGS__)
-
-#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
-	printk(_level "ath5k %s: " _fmt, \
-		((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \
-		##__VA_ARGS__)
-
-#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \
-	if (net_ratelimit()) \
-		ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \
-	} while (0)
-
-#define ATH5K_INFO(_sc, _fmt, ...) \
-	ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__)
-
-#define ATH5K_WARN(_sc, _fmt, ...) \
-	ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__)
-
-#define ATH5K_ERR(_sc, _fmt, ...) \
-	ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__)
-
-/*
- * AR5K REGISTER ACCESS
- */
-
-/* Some macros to read/write fields */
-
-/* First shift, then mask */
-#define AR5K_REG_SM(_val, _flags)					\
-	(((_val) << _flags##_S) & (_flags))
-
-/* First mask, then shift */
-#define AR5K_REG_MS(_val, _flags)					\
-	(((_val) & (_flags)) >> _flags##_S)
-
-/* Some registers can hold multiple values of interest. For this
- * reason when we want to write to these registers we must first
- * retrieve the values which we do not want to clear (lets call this
- * old_data) and then set the register with this and our new_value:
- * ( old_data | new_value) */
-#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val)			\
-	ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
-	    (((_val) << _flags##_S) & (_flags)), _reg)
-
-#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask)			\
-	ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) &		\
-			(_mask)) | (_flags), _reg)
-
-#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags)				\
-	ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
-
-#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags)			\
-	ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
-
-/* Access to PHY registers */
-#define AR5K_PHY_READ(ah, _reg)					\
-	ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
-
-#define AR5K_PHY_WRITE(ah, _reg, _val)					\
-	ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
-
-/* Access QCU registers per queue */
-#define AR5K_REG_READ_Q(ah, _reg, _queue)				\
-	(ath5k_hw_reg_read(ah, _reg) & (1 << _queue))			\
-
-#define AR5K_REG_WRITE_Q(ah, _reg, _queue)				\
-	ath5k_hw_reg_write(ah, (1 << _queue), _reg)
-
-#define AR5K_Q_ENABLE_BITS(_reg, _queue) do {				\
-	_reg |= 1 << _queue;						\
-} while (0)
-
-#define AR5K_Q_DISABLE_BITS(_reg, _queue) do {				\
-	_reg &= ~(1 << _queue);						\
-} while (0)
-
-/* Used while writing initvals */
-#define AR5K_REG_WAIT(_i) do {						\
-	if (_i % 64)							\
-		udelay(1);						\
-} while (0)
-
-/* Register dumps are done per operation mode */
-#define AR5K_INI_RFGAIN_5GHZ		0
-#define AR5K_INI_RFGAIN_2GHZ		1
-
-/* TODO: Clean this up */
-#define AR5K_INI_VAL_11A		0
-#define AR5K_INI_VAL_11A_TURBO		1
-#define AR5K_INI_VAL_11B		2
-#define AR5K_INI_VAL_11G		3
-#define AR5K_INI_VAL_11G_TURBO		4
-#define AR5K_INI_VAL_XR			0
-#define AR5K_INI_VAL_MAX		5
-
-/* Used for BSSID etc manipulation */
-#define AR5K_LOW_ID(_a)(				\
-(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24	\
-)
-
-#define AR5K_HIGH_ID(_a)	((_a)[4] | (_a)[5] << 8)
-
-/*
- * Some tuneable values (these should be changeable by the user)
- * TODO: Make use of them and add more options OR use debug/configfs
- */
-#define AR5K_TUNE_DMA_BEACON_RESP		2
-#define AR5K_TUNE_SW_BEACON_RESP		10
-#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF	0
-#define AR5K_TUNE_RADAR_ALERT			false
-#define AR5K_TUNE_MIN_TX_FIFO_THRES		1
-#define AR5K_TUNE_MAX_TX_FIFO_THRES		((IEEE80211_MAX_LEN / 64) + 1)
-#define AR5K_TUNE_REGISTER_TIMEOUT		20000
-/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
- * be the max value. */
-#define AR5K_TUNE_RSSI_THRES			129
-/* This must be set when setting the RSSI threshold otherwise it can
- * prevent a reset. If AR5K_RSSI_THR is read after writing to it
- * the BMISS_THRES will be seen as 0, seems harware doesn't keep
- * track of it. Max value depends on harware. For AR5210 this is just 7.
- * For AR5211+ this seems to be up to 255. */
-#define AR5K_TUNE_BMISS_THRES			7
-#define AR5K_TUNE_REGISTER_DWELL_TIME		20000
-#define AR5K_TUNE_BEACON_INTERVAL		100
-#define AR5K_TUNE_AIFS				2
-#define AR5K_TUNE_AIFS_11B			2
-#define AR5K_TUNE_AIFS_XR			0
-#define AR5K_TUNE_CWMIN				15
-#define AR5K_TUNE_CWMIN_11B			31
-#define AR5K_TUNE_CWMIN_XR			3
-#define AR5K_TUNE_CWMAX				1023
-#define AR5K_TUNE_CWMAX_11B			1023
-#define AR5K_TUNE_CWMAX_XR			7
-#define AR5K_TUNE_NOISE_FLOOR			-72
-#define AR5K_TUNE_MAX_TXPOWER			63
-#define AR5K_TUNE_DEFAULT_TXPOWER		25
-#define AR5K_TUNE_TPC_TXPOWER			false
-#define AR5K_TUNE_ANT_DIVERSITY			true
-#define AR5K_TUNE_HWTXTRIES			4
-
-#define AR5K_INIT_CARR_SENSE_EN			1
-
-/*Swap RX/TX Descriptor for big endian archs*/
-#if defined(__BIG_ENDIAN)
-#define AR5K_INIT_CFG	(		\
-	AR5K_CFG_SWTD | AR5K_CFG_SWRD	\
-)
-#else
-#define AR5K_INIT_CFG	0x00000000
-#endif
-
-/* Initial values */
-#define	AR5K_INIT_CYCRSSI_THR1			2
-#define AR5K_INIT_TX_LATENCY			502
-#define AR5K_INIT_USEC				39
-#define AR5K_INIT_USEC_TURBO			79
-#define AR5K_INIT_USEC_32			31
-#define AR5K_INIT_SLOT_TIME			396
-#define AR5K_INIT_SLOT_TIME_TURBO		480
-#define AR5K_INIT_ACK_CTS_TIMEOUT		1024
-#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO		0x08000800
-#define AR5K_INIT_PROG_IFS			920
-#define AR5K_INIT_PROG_IFS_TURBO		960
-#define AR5K_INIT_EIFS				3440
-#define AR5K_INIT_EIFS_TURBO			6880
-#define AR5K_INIT_SIFS				560
-#define AR5K_INIT_SIFS_TURBO			480
-#define AR5K_INIT_SH_RETRY			10
-#define AR5K_INIT_LG_RETRY			AR5K_INIT_SH_RETRY
-#define AR5K_INIT_SSH_RETRY			32
-#define AR5K_INIT_SLG_RETRY			AR5K_INIT_SSH_RETRY
-#define AR5K_INIT_TX_RETRY			10
-
-#define AR5K_INIT_TRANSMIT_LATENCY		(			\
-	(AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) |	\
-	(AR5K_INIT_USEC)						\
-)
-#define AR5K_INIT_TRANSMIT_LATENCY_TURBO	(			\
-	(AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) |	\
-	(AR5K_INIT_USEC_TURBO)						\
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL		(			\
-	(AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) |	\
-	(AR5K_INIT_PROG_IFS)						\
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO	(			\
-	(AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
-	(AR5K_INIT_PROG_IFS_TURBO)					\
-)
-
-/* token to use for aifs, cwmin, cwmax in MadWiFi */
-#define	AR5K_TXQ_USEDEFAULT	((u32) -1)
-
-/* GENERIC CHIPSET DEFINITIONS */
-
-/* MAC Chips */
-enum ath5k_version {
-	AR5K_AR5210	= 0,
-	AR5K_AR5211	= 1,
-	AR5K_AR5212	= 2,
-};
-
-/* PHY Chips */
-enum ath5k_radio {
-	AR5K_RF5110	= 0,
-	AR5K_RF5111	= 1,
-	AR5K_RF5112	= 2,
-	AR5K_RF2413	= 3,
-	AR5K_RF5413	= 4,
-	AR5K_RF2316	= 5,
-	AR5K_RF2317	= 6,
-	AR5K_RF2425	= 7,
-};
-
-/*
- * Common silicon revision/version values
- */
-
-enum ath5k_srev_type {
-	AR5K_VERSION_MAC,
-	AR5K_VERSION_RAD,
-};
-
-struct ath5k_srev_name {
-	const char		*sr_name;
-	enum ath5k_srev_type	sr_type;
-	u_int			sr_val;
-};
-
-#define AR5K_SREV_UNKNOWN	0xffff
-
-#define AR5K_SREV_AR5210	0x00 /* Crete */
-#define AR5K_SREV_AR5311	0x10 /* Maui 1 */
-#define AR5K_SREV_AR5311A	0x20 /* Maui 2 */
-#define AR5K_SREV_AR5311B	0x30 /* Spirit */
-#define AR5K_SREV_AR5211	0x40 /* Oahu */
-#define AR5K_SREV_AR5212	0x50 /* Venice */
-#define AR5K_SREV_AR5213	0x55 /* ??? */
-#define AR5K_SREV_AR5213A	0x59 /* Hainan */
-#define AR5K_SREV_AR2413	0x78 /* Griffin lite */
-#define AR5K_SREV_AR2414	0x70 /* Griffin */
-#define AR5K_SREV_AR5424	0x90 /* Condor */
-#define AR5K_SREV_AR5413	0xa4 /* Eagle lite */
-#define AR5K_SREV_AR5414	0xa0 /* Eagle */
-#define AR5K_SREV_AR2415	0xb0 /* Talon */
-#define AR5K_SREV_AR5416	0xc0 /* PCI-E */
-#define AR5K_SREV_AR5418	0xca /* PCI-E */
-#define AR5K_SREV_AR2425	0xe0 /* Swan */
-#define AR5K_SREV_AR2417	0xf0 /* Nala */
-
-#define AR5K_SREV_RAD_5110	0x00
-#define AR5K_SREV_RAD_5111	0x10
-#define AR5K_SREV_RAD_5111A	0x15
-#define AR5K_SREV_RAD_2111	0x20
-#define AR5K_SREV_RAD_5112	0x30
-#define AR5K_SREV_RAD_5112A	0x35
-#define	AR5K_SREV_RAD_5112B	0x36
-#define AR5K_SREV_RAD_2112	0x40
-#define AR5K_SREV_RAD_2112A	0x45
-#define	AR5K_SREV_RAD_2112B	0x46
-#define AR5K_SREV_RAD_2413	0x50
-#define AR5K_SREV_RAD_5413	0x60
-#define AR5K_SREV_RAD_2316	0x70 /* Cobra SoC */
-#define AR5K_SREV_RAD_2317	0x80
-#define AR5K_SREV_RAD_5424	0xa0 /* Mostly same as 5413 */
-#define AR5K_SREV_RAD_2425	0xa2
-#define AR5K_SREV_RAD_5133	0xc0
-
-#define AR5K_SREV_PHY_5211	0x30
-#define AR5K_SREV_PHY_5212	0x41
-#define	AR5K_SREV_PHY_5212A	0x42
-#define AR5K_SREV_PHY_5212B	0x43
-#define AR5K_SREV_PHY_2413	0x45
-#define AR5K_SREV_PHY_5413	0x61
-#define AR5K_SREV_PHY_2425	0x70
-
-/* IEEE defs */
-#define IEEE80211_MAX_LEN       2500
-
-/* TODO add support to mac80211 for vendor-specific rates and modes */
-
-/*
- * Some of this information is based on Documentation from:
- *
- * http://madwifi.org/wiki/ChipsetFeatures/SuperAG
- *
- * Modulation for Atheros' eXtended Range - range enhancing extension that is
- * supposed to double the distance an Atheros client device can keep a
- * connection with an Atheros access point. This is achieved by increasing
- * the receiver sensitivity up to, -105dBm, which is about 20dB above what
- * the 802.11 specifications demand. In addition, new (proprietary) data rates
- * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
- *
- * Please note that can you either use XR or TURBO but you cannot use both,
- * they are exclusive.
- *
- */
-#define MODULATION_XR 		0x00000200
-/*
- * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
- * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
- * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
- * channels. To use this feature your Access Point must also suport it.
- * There is also a distinction between "static" and "dynamic" turbo modes:
- *
- * - Static: is the dumb version: devices set to this mode stick to it until
- *     the mode is turned off.
- * - Dynamic: is the intelligent version, the network decides itself if it
- *     is ok to use turbo. As soon as traffic is detected on adjacent channels
- *     (which would get used in turbo mode), or when a non-turbo station joins
- *     the network, turbo mode won't be used until the situation changes again.
- *     Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which
- *     monitors the used radio band in order to decide whether turbo mode may
- *     be used or not.
- *
- * This article claims Super G sticks to bonding of channels 5 and 6 for
- * USA:
- *
- * http://www.pcworld.com/article/id,113428-page,1/article.html
- *
- * The channel bonding seems to be driver specific though. In addition to
- * deciding what channels will be used, these "Turbo" modes are accomplished
- * by also enabling the following features:
- *
- * - Bursting: allows multiple frames to be sent at once, rather than pausing
- *     after each frame. Bursting is a standards-compliant feature that can be
- *     used with any Access Point.
- * - Fast frames: increases the amount of information that can be sent per
- *     frame, also resulting in a reduction of transmission overhead. It is a
- *     proprietary feature that needs to be supported by the Access Point.
- * - Compression: data frames are compressed in real time using a Lempel Ziv
- *     algorithm. This is done transparently. Once this feature is enabled,
- *     compression and decompression takes place inside the chipset, without
- *     putting additional load on the host CPU.
- *
- */
-#define MODULATION_TURBO	0x00000080
-
-enum ath5k_driver_mode {
-	AR5K_MODE_11A		=	0,
-	AR5K_MODE_11A_TURBO	=	1,
-	AR5K_MODE_11B		=	2,
-	AR5K_MODE_11G		=	3,
-	AR5K_MODE_11G_TURBO	=	4,
-	AR5K_MODE_XR		=	0,
-	AR5K_MODE_MAX		=	5
-};
-
-
-/****************\
-  TX DEFINITIONS
-\****************/
-
-/*
- * TX Status descriptor
- */
-struct ath5k_tx_status {
-	u16	ts_seqnum;
-	u16	ts_tstamp;
-	u8	ts_status;
-	u8	ts_rate[4];
-	u8	ts_retry[4];
-	u8	ts_final_idx;
-	s8	ts_rssi;
-	u8	ts_shortretry;
-	u8	ts_longretry;
-	u8	ts_virtcol;
-	u8	ts_antenna;
-};
-
-#define AR5K_TXSTAT_ALTRATE	0x80
-#define AR5K_TXERR_XRETRY	0x01
-#define AR5K_TXERR_FILT		0x02
-#define AR5K_TXERR_FIFO		0x04
-
-/**
- * enum ath5k_tx_queue - Queue types used to classify tx queues.
- * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue
- * @AR5K_TX_QUEUE_DATA: A normal data queue
- * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue
- * @AR5K_TX_QUEUE_BEACON: The beacon queue
- * @AR5K_TX_QUEUE_CAB: The after-beacon queue
- * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue
- */
-enum ath5k_tx_queue {
-	AR5K_TX_QUEUE_INACTIVE = 0,
-	AR5K_TX_QUEUE_DATA,
-	AR5K_TX_QUEUE_XR_DATA,
-	AR5K_TX_QUEUE_BEACON,
-	AR5K_TX_QUEUE_CAB,
-	AR5K_TX_QUEUE_UAPSD,
-};
-
-#define	AR5K_NUM_TX_QUEUES		10
-#define	AR5K_NUM_TX_QUEUES_NOQCU	2
-
-/*
- * Queue syb-types to classify normal data queues.
- * These are the 4 Access Categories as defined in
- * WME spec. 0 is the lowest priority and 4 is the
- * highest. Normal data that hasn't been classified
- * goes to the Best Effort AC.
- */
-enum ath5k_tx_queue_subtype {
-	AR5K_WME_AC_BK = 0,	/*Background traffic*/
-	AR5K_WME_AC_BE, 	/*Best-effort (normal) traffic)*/
-	AR5K_WME_AC_VI, 	/*Video traffic*/
-	AR5K_WME_AC_VO, 	/*Voice traffic*/
-};
-
-/*
- * Queue ID numbers as returned by the hw functions, each number
- * represents a hw queue. If hw does not support hw queues
- * (eg 5210) all data goes in one queue. These match
- * d80211 definitions (net80211/MadWiFi don't use them).
- */
-enum ath5k_tx_queue_id {
-	AR5K_TX_QUEUE_ID_NOQCU_DATA	= 0,
-	AR5K_TX_QUEUE_ID_NOQCU_BEACON	= 1,
-	AR5K_TX_QUEUE_ID_DATA_MIN	= 0, /*IEEE80211_TX_QUEUE_DATA0*/
-	AR5K_TX_QUEUE_ID_DATA_MAX	= 4, /*IEEE80211_TX_QUEUE_DATA4*/
-	AR5K_TX_QUEUE_ID_DATA_SVP	= 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
-	AR5K_TX_QUEUE_ID_CAB		= 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
-	AR5K_TX_QUEUE_ID_BEACON		= 7, /*IEEE80211_TX_QUEUE_BEACON*/
-	AR5K_TX_QUEUE_ID_UAPSD		= 8,
-	AR5K_TX_QUEUE_ID_XR_DATA	= 9,
-};
-
-/*
- * Flags to set hw queue's parameters...
- */
-#define AR5K_TXQ_FLAG_TXOKINT_ENABLE		0x0001	/* Enable TXOK interrupt */
-#define AR5K_TXQ_FLAG_TXERRINT_ENABLE		0x0002	/* Enable TXERR interrupt */
-#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE		0x0004	/* Enable TXEOL interrupt -not used- */
-#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE		0x0008	/* Enable TXDESC interrupt -not used- */
-#define AR5K_TXQ_FLAG_TXURNINT_ENABLE		0x0010	/* Enable TXURN interrupt */
-#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE		0x0020	/* Enable CBRORN interrupt */
-#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE		0x0040	/* Enable CBRURN interrupt */
-#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE		0x0080	/* Enable QTRIG interrupt */
-#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE		0x0100	/* Enable TXNOFRM interrupt */
-#define AR5K_TXQ_FLAG_BACKOFF_DISABLE		0x0200	/* Disable random post-backoff */
-#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE	0x0300	/* Enable ready time expiry policy (?)*/
-#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE	0x0800	/* Enable backoff while bursting */
-#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS		0x1000	/* Disable backoff while bursting */
-#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE	0x2000	/* Enable hw compression -not implemented-*/
-
-/*
- * A struct to hold tx queue's parameters
- */
-struct ath5k_txq_info {
-	enum ath5k_tx_queue tqi_type;
-	enum ath5k_tx_queue_subtype tqi_subtype;
-	u16	tqi_flags;	/* Tx queue flags (see above) */
-	u32	tqi_aifs;	/* Arbitrated Interframe Space */
-	s32	tqi_cw_min;	/* Minimum Contention Window */
-	s32	tqi_cw_max;	/* Maximum Contention Window */
-	u32	tqi_cbr_period; /* Constant bit rate period */
-	u32	tqi_cbr_overflow_limit;
-	u32	tqi_burst_time;
-	u32	tqi_ready_time; /* Not used */
-};
-
-/*
- * Transmit packet types.
- * used on tx control descriptor
- * TODO: Use them inside base.c corectly
- */
-enum ath5k_pkt_type {
-	AR5K_PKT_TYPE_NORMAL		= 0,
-	AR5K_PKT_TYPE_ATIM		= 1,
-	AR5K_PKT_TYPE_PSPOLL		= 2,
-	AR5K_PKT_TYPE_BEACON		= 3,
-	AR5K_PKT_TYPE_PROBE_RESP	= 4,
-	AR5K_PKT_TYPE_PIFS		= 5,
-};
-
-/*
- * TX power and TPC settings
- */
-#define AR5K_TXPOWER_OFDM(_r, _v)	(			\
-	((0 & 1) << ((_v) + 6)) |				\
-	(((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v))	\
-)
-
-#define AR5K_TXPOWER_CCK(_r, _v)	(			\
-	(ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v)	\
-)
-
-/*
- * DMA size definitions (2^n+2)
- */
-enum ath5k_dmasize {
-	AR5K_DMASIZE_4B	= 0,
-	AR5K_DMASIZE_8B,
-	AR5K_DMASIZE_16B,
-	AR5K_DMASIZE_32B,
-	AR5K_DMASIZE_64B,
-	AR5K_DMASIZE_128B,
-	AR5K_DMASIZE_256B,
-	AR5K_DMASIZE_512B
-};
-
-
-/****************\
-  RX DEFINITIONS
-\****************/
-
-/*
- * RX Status descriptor
- */
-struct ath5k_rx_status {
-	u16	rs_datalen;
-	u16	rs_tstamp;
-	u8	rs_status;
-	u8	rs_phyerr;
-	s8	rs_rssi;
-	u8	rs_keyix;
-	u8	rs_rate;
-	u8	rs_antenna;
-	u8	rs_more;
-};
-
-#define AR5K_RXERR_CRC		0x01
-#define AR5K_RXERR_PHY		0x02
-#define AR5K_RXERR_FIFO		0x04
-#define AR5K_RXERR_DECRYPT	0x08
-#define AR5K_RXERR_MIC		0x10
-#define AR5K_RXKEYIX_INVALID	((u8) - 1)
-#define AR5K_TXKEYIX_INVALID	((u32) - 1)
-
-
-/**************************\
- BEACON TIMERS DEFINITIONS
-\**************************/
-
-#define AR5K_BEACON_PERIOD	0x0000ffff
-#define AR5K_BEACON_ENA		0x00800000 /*enable beacon xmit*/
-#define AR5K_BEACON_RESET_TSF	0x01000000 /*force a TSF reset*/
-
-#if 0
-/**
- * struct ath5k_beacon_state - Per-station beacon timer state.
- * @bs_interval: in TU's, can also include the above flags
- * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a
- * 	Point Coordination Function capable AP
- */
-struct ath5k_beacon_state {
-	u32	bs_next_beacon;
-	u32	bs_next_dtim;
-	u32	bs_interval;
-	u8	bs_dtim_period;
-	u8	bs_cfp_period;
-	u16	bs_cfp_max_duration;
-	u16	bs_cfp_du_remain;
-	u16	bs_tim_offset;
-	u16	bs_sleep_duration;
-	u16	bs_bmiss_threshold;
-	u32  	bs_cfp_next;
-};
-#endif
-
-
-/*
- * TSF to TU conversion:
- *
- * TSF is a 64bit value in usec (microseconds).
- * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of
- * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024).
- */
-#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
-
-
-/*******************************\
-  GAIN OPTIMIZATION DEFINITIONS
-\*******************************/
-
-enum ath5k_rfgain {
-	AR5K_RFGAIN_INACTIVE = 0,
-	AR5K_RFGAIN_ACTIVE,
-	AR5K_RFGAIN_READ_REQUESTED,
-	AR5K_RFGAIN_NEED_CHANGE,
-};
-
-struct ath5k_gain {
-	u8			g_step_idx;
-	u8			g_current;
-	u8			g_target;
-	u8			g_low;
-	u8			g_high;
-	u8			g_f_corr;
-	u8			g_state;
-};
-
-/********************\
-  COMMON DEFINITIONS
-\********************/
-
-#define AR5K_SLOT_TIME_9	396
-#define AR5K_SLOT_TIME_20	880
-#define AR5K_SLOT_TIME_MAX	0xffff
-
-/* channel_flags */
-#define	CHANNEL_CW_INT	0x0008	/* Contention Window interference detected */
-#define	CHANNEL_TURBO	0x0010	/* Turbo Channel */
-#define	CHANNEL_CCK	0x0020	/* CCK channel */
-#define	CHANNEL_OFDM	0x0040	/* OFDM channel */
-#define	CHANNEL_2GHZ	0x0080	/* 2GHz channel. */
-#define	CHANNEL_5GHZ	0x0100	/* 5GHz channel */
-#define	CHANNEL_PASSIVE	0x0200	/* Only passive scan allowed */
-#define	CHANNEL_DYN	0x0400	/* Dynamic CCK-OFDM channel (for g operation) */
-#define	CHANNEL_XR	0x0800	/* XR channel */
-
-#define	CHANNEL_A	(CHANNEL_5GHZ|CHANNEL_OFDM)
-#define	CHANNEL_B	(CHANNEL_2GHZ|CHANNEL_CCK)
-#define	CHANNEL_G	(CHANNEL_2GHZ|CHANNEL_OFDM)
-#define	CHANNEL_T	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
-#define	CHANNEL_TG	(CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
-#define	CHANNEL_108A	CHANNEL_T
-#define	CHANNEL_108G	CHANNEL_TG
-#define	CHANNEL_X	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
-
-#define	CHANNEL_ALL 	(CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
-		CHANNEL_TURBO)
-
-#define	CHANNEL_ALL_NOTURBO 	(CHANNEL_ALL & ~CHANNEL_TURBO)
-#define CHANNEL_MODES		CHANNEL_ALL
-
-/*
- * Used internaly for reset_tx_queue).
- * Also see struct struct ieee80211_channel.
- */
-#define IS_CHAN_XR(_c)	((_c.hw_value & CHANNEL_XR) != 0)
-#define IS_CHAN_B(_c)	((_c.hw_value & CHANNEL_B) != 0)
-
-/*
- * The following structure is used to map 2GHz channels to
- * 5GHz Atheros channels.
- * TODO: Clean up
- */
-struct ath5k_athchan_2ghz {
-	u32	a2_flags;
-	u16	a2_athchan;
-};
-
-
-/******************\
-  RATE DEFINITIONS
-\******************/
-
-/**
- * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32.
- *
- * The rate code is used to get the RX rate or set the TX rate on the
- * hardware descriptors. It is also used for internal modulation control
- * and settings.
- *
- * This is the hardware rate map we are aware of:
- *
- * rate_code   0x01    0x02    0x03    0x04    0x05    0x06    0x07    0x08
- * rate_kbps   3000    1000    ?       ?       ?       2000    500     48000
- *
- * rate_code   0x09    0x0A    0x0B    0x0C    0x0D    0x0E    0x0F    0x10
- * rate_kbps   24000   12000   6000    54000   36000   18000   9000    ?
- *
- * rate_code   17      18      19      20      21      22      23      24
- * rate_kbps   ?       ?       ?       ?       ?       ?       ?       11000
- *
- * rate_code   25      26      27      28      29      30      31      32
- * rate_kbps   5500    2000    1000    11000S  5500S   2000S   ?       ?
- *
- * "S" indicates CCK rates with short preamble.
- *
- * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
- * lowest 4 bits, so they are the same as below with a 0xF mask.
- * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
- * We handle this in ath5k_setup_bands().
- */
-#define AR5K_MAX_RATES 32
-
-/* B */
-#define ATH5K_RATE_CODE_1M	0x1B
-#define ATH5K_RATE_CODE_2M	0x1A
-#define ATH5K_RATE_CODE_5_5M	0x19
-#define ATH5K_RATE_CODE_11M	0x18
-/* A and G */
-#define ATH5K_RATE_CODE_6M	0x0B
-#define ATH5K_RATE_CODE_9M	0x0F
-#define ATH5K_RATE_CODE_12M	0x0A
-#define ATH5K_RATE_CODE_18M	0x0E
-#define ATH5K_RATE_CODE_24M	0x09
-#define ATH5K_RATE_CODE_36M	0x0D
-#define ATH5K_RATE_CODE_48M	0x08
-#define ATH5K_RATE_CODE_54M	0x0C
-/* XR */
-#define ATH5K_RATE_CODE_XR_500K	0x07
-#define ATH5K_RATE_CODE_XR_1M	0x02
-#define ATH5K_RATE_CODE_XR_2M	0x06
-#define ATH5K_RATE_CODE_XR_3M	0x01
-
-/* adding this flag to rate_code enables short preamble */
-#define AR5K_SET_SHORT_PREAMBLE 0x04
-
-/*
- * Crypto definitions
- */
-
-#define AR5K_KEYCACHE_SIZE	8
-
-/***********************\
- HW RELATED DEFINITIONS
-\***********************/
-
-/*
- * Misc definitions
- */
-#define	AR5K_RSSI_EP_MULTIPLIER	(1<<7)
-
-#define AR5K_ASSERT_ENTRY(_e, _s) do {		\
-	if (_e >= _s)				\
-		return (false);			\
-} while (0)
-
-/*
- * Hardware interrupt abstraction
- */
-
-/**
- * enum ath5k_int - Hardware interrupt masks helpers
- *
- * @AR5K_INT_RX: mask to identify received frame interrupts, of type
- * 	AR5K_ISR_RXOK or AR5K_ISR_RXERR
- * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
- * @AR5K_INT_RXNOFRM: No frame received (?)
- * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
- * 	Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
- * 	LinkPtr is NULL. For more details, refer to:
- * 	http://www.freepatentsonline.com/20030225739.html
- * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
- * 	Note that Rx overrun is not always fatal, on some chips we can continue
- * 	operation without reseting the card, that's why int_fatal is not
- * 	common for all chips.
- * @AR5K_INT_TX: mask to identify received frame interrupts, of type
- * 	AR5K_ISR_TXOK or AR5K_ISR_TXERR
- * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
- * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
- * 	We currently do increments on interrupt by
- * 	(AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
- * @AR5K_INT_MIB: Indicates the Management Information Base counters should be
- * 	checked. We should do this with ath5k_hw_update_mib_counters() but
- * 	it seems we should also then do some noise immunity work.
- * @AR5K_INT_RXPHY: RX PHY Error
- * @AR5K_INT_RXKCM: RX Key cache miss
- * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
- * 	beacon that must be handled in software. The alternative is if you
- * 	have VEOL support, in that case you let the hardware deal with things.
- * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
- * 	beacons from the AP have associated with, we should probably try to
- * 	reassociate. When in IBSS mode this might mean we have not received
- * 	any beacons from any local stations. Note that every station in an
- * 	IBSS schedules to send beacons at the Target Beacon Transmission Time
- * 	(TBTT) with a random backoff.
- * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
- * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
- * 	until properly handled
- * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
- * 	errors. These types of errors we can enable seem to be of type
- * 	AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
- * @AR5K_INT_GLOBAL: Used to clear and set the IER
- * @AR5K_INT_NOCARD: signals the card has been removed
- * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
- * 	bit value
- *
- * These are mapped to take advantage of some common bits
- * between the MACs, to be able to set intr properties
- * easier. Some of them are not used yet inside hw.c. Most map
- * to the respective hw interrupt value as they are common amogst different
- * MACs.
- */
-enum ath5k_int {
-	AR5K_INT_RXOK	= 0x00000001,
-	AR5K_INT_RXDESC	= 0x00000002,
-	AR5K_INT_RXERR	= 0x00000004,
-	AR5K_INT_RXNOFRM = 0x00000008,
-	AR5K_INT_RXEOL	= 0x00000010,
-	AR5K_INT_RXORN	= 0x00000020,
-	AR5K_INT_TXOK	= 0x00000040,
-	AR5K_INT_TXDESC	= 0x00000080,
-	AR5K_INT_TXERR	= 0x00000100,
-	AR5K_INT_TXNOFRM = 0x00000200,
-	AR5K_INT_TXEOL	= 0x00000400,
-	AR5K_INT_TXURN	= 0x00000800,
-	AR5K_INT_MIB	= 0x00001000,
-	AR5K_INT_SWI	= 0x00002000,
-	AR5K_INT_RXPHY	= 0x00004000,
-	AR5K_INT_RXKCM	= 0x00008000,
-	AR5K_INT_SWBA	= 0x00010000,
-	AR5K_INT_BRSSI	= 0x00020000,
-	AR5K_INT_BMISS	= 0x00040000,
-	AR5K_INT_FATAL	= 0x00080000, /* Non common */
-	AR5K_INT_BNR	= 0x00100000, /* Non common */
-	AR5K_INT_TIM	= 0x00200000, /* Non common */
-	AR5K_INT_DTIM	= 0x00400000, /* Non common */
-	AR5K_INT_DTIM_SYNC =	0x00800000, /* Non common */
-	AR5K_INT_GPIO	=	0x01000000,
-	AR5K_INT_BCN_TIMEOUT =	0x02000000, /* Non common */
-	AR5K_INT_CAB_TIMEOUT =	0x04000000, /* Non common */
-	AR5K_INT_RX_DOPPLER =	0x08000000, /* Non common */
-	AR5K_INT_QCBRORN =	0x10000000, /* Non common */
-	AR5K_INT_QCBRURN =	0x20000000, /* Non common */
-	AR5K_INT_QTRIG	=	0x40000000, /* Non common */
-	AR5K_INT_GLOBAL =	0x80000000,
-
-	AR5K_INT_COMMON  = AR5K_INT_RXOK
-		| AR5K_INT_RXDESC
-		| AR5K_INT_RXERR
-		| AR5K_INT_RXNOFRM
-		| AR5K_INT_RXEOL
-		| AR5K_INT_RXORN
-		| AR5K_INT_TXOK
-		| AR5K_INT_TXDESC
-		| AR5K_INT_TXERR
-		| AR5K_INT_TXNOFRM
-		| AR5K_INT_TXEOL
-		| AR5K_INT_TXURN
-		| AR5K_INT_MIB
-		| AR5K_INT_SWI
-		| AR5K_INT_RXPHY
-		| AR5K_INT_RXKCM
-		| AR5K_INT_SWBA
-		| AR5K_INT_BRSSI
-		| AR5K_INT_BMISS
-		| AR5K_INT_GPIO
-		| AR5K_INT_GLOBAL,
-
-	AR5K_INT_NOCARD	= 0xffffffff
-};
-
-/*
- * Power management
- */
-enum ath5k_power_mode {
-	AR5K_PM_UNDEFINED = 0,
-	AR5K_PM_AUTO,
-	AR5K_PM_AWAKE,
-	AR5K_PM_FULL_SLEEP,
-	AR5K_PM_NETWORK_SLEEP,
-};
-
-/*
- * These match net80211 definitions (not used in
- * mac80211).
- * TODO: Clean this up
- */
-#define AR5K_LED_INIT	0 /*IEEE80211_S_INIT*/
-#define AR5K_LED_SCAN	1 /*IEEE80211_S_SCAN*/
-#define AR5K_LED_AUTH	2 /*IEEE80211_S_AUTH*/
-#define AR5K_LED_ASSOC	3 /*IEEE80211_S_ASSOC*/
-#define AR5K_LED_RUN	4 /*IEEE80211_S_RUN*/
-
-/* GPIO-controlled software LED */
-#define AR5K_SOFTLED_PIN	0
-#define AR5K_SOFTLED_ON		0
-#define AR5K_SOFTLED_OFF	1
-
-/*
- * Chipset capabilities -see ath5k_hw_get_capability-
- * get_capability function is not yet fully implemented
- * in ath5k so most of these don't work yet...
- * TODO: Implement these & merge with _TUNE_ stuff above
- */
-enum ath5k_capability_type {
-	AR5K_CAP_REG_DMN		= 0,	/* Used to get current reg. domain id */
-	AR5K_CAP_TKIP_MIC		= 2,	/* Can handle TKIP MIC in hardware */
-	AR5K_CAP_TKIP_SPLIT		= 3,	/* TKIP uses split keys */
-	AR5K_CAP_PHYCOUNTERS		= 4,	/* PHY error counters */
-	AR5K_CAP_DIVERSITY		= 5,	/* Supports fast diversity */
-	AR5K_CAP_NUM_TXQUEUES		= 6,	/* Used to get max number of hw txqueues */
-	AR5K_CAP_VEOL			= 7,	/* Supports virtual EOL */
-	AR5K_CAP_COMPRESSION		= 8,	/* Supports compression */
-	AR5K_CAP_BURST			= 9,	/* Supports packet bursting */
-	AR5K_CAP_FASTFRAME		= 10,	/* Supports fast frames */
-	AR5K_CAP_TXPOW			= 11,	/* Used to get global tx power limit */
-	AR5K_CAP_TPC			= 12,	/* Can do per-packet tx power control (needed for 802.11a) */
-	AR5K_CAP_BSSIDMASK		= 13,	/* Supports bssid mask */
-	AR5K_CAP_MCAST_KEYSRCH		= 14,	/* Supports multicast key search */
-	AR5K_CAP_TSF_ADJUST		= 15,	/* Supports beacon tsf adjust */
-	AR5K_CAP_XR			= 16,	/* Supports XR mode */
-	AR5K_CAP_WME_TKIPMIC 		= 17,	/* Supports TKIP MIC when using WMM */
-	AR5K_CAP_CHAN_HALFRATE 		= 18,	/* Supports half rate channels */
-	AR5K_CAP_CHAN_QUARTERRATE 	= 19,	/* Supports quarter rate channels */
-	AR5K_CAP_RFSILENT		= 20,	/* Supports RFsilent */
-};
-
-
-/* XXX: we *may* move cap_range stuff to struct wiphy */
-struct ath5k_capabilities {
-	/*
-	 * Supported PHY modes
-	 * (ie. CHANNEL_A, CHANNEL_B, ...)
-	 */
-	DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
-
-	/*
-	 * Frequency range (without regulation restrictions)
-	 */
-	struct {
-		u16	range_2ghz_min;
-		u16	range_2ghz_max;
-		u16	range_5ghz_min;
-		u16	range_5ghz_max;
-	} cap_range;
-
-	/*
-	 * Values stored in the EEPROM (some of them...)
-	 */
-	struct ath5k_eeprom_info	cap_eeprom;
-
-	/*
-	 * Queue information
-	 */
-	struct {
-		u8	q_tx_num;
-	} cap_queues;
-};
-
-
-/***************************************\
-  HARDWARE ABSTRACTION LAYER STRUCTURE
-\***************************************/
-
-/*
- * Misc defines
- */
-
-#define AR5K_MAX_GPIO		10
-#define AR5K_MAX_RF_BANKS	8
-
-/* TODO: Clean up and merge with ath5k_softc */
-struct ath5k_hw {
-	u32			ah_magic;
-
-	struct ath5k_softc	*ah_sc;
-	void __iomem		*ah_iobase;
-
-	enum ath5k_int		ah_imr;
-
-	enum nl80211_iftype	ah_op_mode;
-	enum ath5k_power_mode	ah_power_mode;
-	struct ieee80211_channel ah_current_channel;
-	bool			ah_turbo;
-	bool			ah_calibration;
-	bool			ah_running;
-	bool			ah_single_chip;
-	bool			ah_combined_mic;
-
-	u32			ah_mac_srev;
-	u16			ah_mac_version;
-	u16			ah_mac_revision;
-	u16			ah_phy_revision;
-	u16			ah_radio_5ghz_revision;
-	u16			ah_radio_2ghz_revision;
-
-	enum ath5k_version	ah_version;
-	enum ath5k_radio	ah_radio;
-	u32			ah_phy;
-
-	bool			ah_5ghz;
-	bool			ah_2ghz;
-
-#define ah_regdomain		ah_capabilities.cap_regdomain.reg_current
-#define ah_regdomain_hw		ah_capabilities.cap_regdomain.reg_hw
-#define ah_modes		ah_capabilities.cap_mode
-#define ah_ee_version		ah_capabilities.cap_eeprom.ee_version
-
-	u32			ah_atim_window;
-	u32			ah_aifs;
-	u32			ah_cw_min;
-	u32			ah_cw_max;
-	bool			ah_software_retry;
-	u32			ah_limit_tx_retries;
-
-	u32			ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
-	bool			ah_ant_diversity;
-
-	u8			ah_sta_id[ETH_ALEN];
-
-	/* Current BSSID we are trying to assoc to / create.
-	 * This is passed by mac80211 on config_interface() and cached here for
-	 * use in resets */
-	u8			ah_bssid[ETH_ALEN];
-	u8			ah_bssid_mask[ETH_ALEN];
-
-	u32			ah_gpio[AR5K_MAX_GPIO];
-	int			ah_gpio_npins;
-
-	struct ath5k_capabilities ah_capabilities;
-
-	struct ath5k_txq_info	ah_txq[AR5K_NUM_TX_QUEUES];
-	u32			ah_txq_status;
-	u32			ah_txq_imr_txok;
-	u32			ah_txq_imr_txerr;
-	u32			ah_txq_imr_txurn;
-	u32			ah_txq_imr_txdesc;
-	u32			ah_txq_imr_txeol;
-	u32			ah_txq_imr_cbrorn;
-	u32			ah_txq_imr_cbrurn;
-	u32			ah_txq_imr_qtrig;
-	u32			ah_txq_imr_nofrm;
-	u32			ah_txq_isr;
-	u32			*ah_rf_banks;
-	size_t			ah_rf_banks_size;
-	size_t			ah_rf_regs_count;
-	struct ath5k_gain	ah_gain;
-	u8			ah_offset[AR5K_MAX_RF_BANKS];
-
-
-	struct {
-		/* Temporary tables used for interpolation */
-		u8		tmpL[AR5K_EEPROM_N_PD_GAINS]
-					[AR5K_EEPROM_POWER_TABLE_SIZE];
-		u8		tmpR[AR5K_EEPROM_N_PD_GAINS]
-					[AR5K_EEPROM_POWER_TABLE_SIZE];
-		u8		txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2];
-		u16		txp_rates_power_table[AR5K_MAX_RATES];
-		u8		txp_min_idx;
-		bool		txp_tpc;
-		/* Values in 0.25dB units */
-		s16		txp_min_pwr;
-		s16		txp_max_pwr;
-		s16		txp_offset;
-		s16		txp_ofdm;
-		/* Values in dB units */
-		s16		txp_cck_ofdm_pwr_delta;
-		s16		txp_cck_ofdm_gainf_delta;
-	} ah_txpower;
-
-	struct {
-		bool		r_enabled;
-		int		r_last_alert;
-		struct ieee80211_channel r_last_channel;
-	} ah_radar;
-
-	/* noise floor from last periodic calibration */
-	s32			ah_noise_floor;
-
-	/*
-	 * Function pointers
-	 */
-	int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc,
-				u32 size, unsigned int flags);
-	int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
-		unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
-		unsigned int, unsigned int, unsigned int, unsigned int,
-		unsigned int, unsigned int, unsigned int);
-	int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
-		unsigned int, unsigned int, unsigned int, unsigned int,
-		unsigned int, unsigned int);
-	int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
-		struct ath5k_tx_status *);
-	int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
-		struct ath5k_rx_status *);
-};
-
-/*
- * Prototypes
- */
-
-/* Attach/Detach Functions */
-extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version);
-extern void ath5k_hw_detach(struct ath5k_hw *ah);
-
-/* LED functions */
-extern int ath5k_init_leds(struct ath5k_softc *sc);
-extern void ath5k_led_enable(struct ath5k_softc *sc);
-extern void ath5k_led_off(struct ath5k_softc *sc);
-extern void ath5k_unregister_leds(struct ath5k_softc *sc);
-
-/* Reset Functions */
-extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
-extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
-/* Power management functions */
-extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
-
-/* DMA Related Functions */
-extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
-extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
-extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
-extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
-extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
-extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
-extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
-extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
-				u32 phys_addr);
-extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
-/* Interrupt handling */
-extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
-extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
-extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum
-ath5k_int new_mask);
-extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
-
-/* EEPROM access functions */
-extern int ath5k_eeprom_init(struct ath5k_hw *ah);
-extern void ath5k_eeprom_detach(struct ath5k_hw *ah);
-extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
-extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah);
-
-/* Protocol Control Unit Functions */
-extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
-/* BSSID Functions */
-extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
-extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
-extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
-extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
-/* Receive start/stop functions */
-extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
-extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
-/* RX Filter functions */
-extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
-extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
-extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
-extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
-extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
-/* Beacon control functions */
-extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
-extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
-extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
-extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
-extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
-#if 0
-extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state);
-extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
-extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
-#endif
-/* ACK bit rate */
-void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
-/* ACK/CTS Timeouts */
-extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
-extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
-extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
-extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
-/* Key table (WEP) functions */
-extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
-extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
-extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac);
-extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
-
-/* Queue Control Unit, DFS Control Unit Functions */
-extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info);
-extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
-				const struct ath5k_txq_info *queue_info);
-extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
-				enum ath5k_tx_queue queue_type,
-				struct ath5k_txq_info *queue_info);
-extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
-extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
-extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
-extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah);
-extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
-
-/* Hardware Descriptor Functions */
-extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
-
-/* GPIO Functions */
-extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
-extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
-extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
-extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
-extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
-extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
-
-/* Misc functions */
-int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
-extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
-extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
-extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
-
-/* Initial register settings functions */
-extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
-
-/* Initialize RF */
-extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
-				struct ieee80211_channel *channel,
-				unsigned int mode);
-extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
-extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
-extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
-/* PHY/RF channel functions */
-extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
-extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
-/* PHY calibration */
-extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
-extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
-/* Misc PHY functions */
-extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
-extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
-extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
-extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
-/* TX power setup */
-extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower);
-extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower);
-
-/*
- * Functions used internaly
- */
-
-/*
- * Translate usec to hw clock units
- * TODO: Half/quarter rate
- */
-static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
-{
-	return turbo ? (usec * 80) : (usec * 40);
-}
-
-/*
- * Translate hw clock units to usec
- * TODO: Half/quarter rate
- */
-static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
-{
-	return turbo ? (clock / 80) : (clock / 40);
-}
-
-/*
- * Read from a register
- */
-static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
-{
-	return ioread32(ah->ah_iobase + reg);
-}
-
-/*
- * Write to a register
- */
-static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
-{
-	iowrite32(val, ah->ah_iobase + reg);
-}
-
-#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY)
-/*
- * Check if a register write has been completed
- */
-static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag,
-		u32 val, bool is_set)
-{
-	int i;
-	u32 data;
-
-	for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
-		data = ath5k_hw_reg_read(ah, reg);
-		if (is_set && (data & flag))
-			break;
-		else if ((data & flag) == val)
-			break;
-		udelay(15);
-	}
-
-	return (i <= 0) ? -EAGAIN : 0;
-}
-#endif
-
-static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
-{
-	u32 retval = 0, bit, i;
-
-	for (i = 0; i < bits; i++) {
-		bit = (val >> i) & 1;
-		retval = (retval << 1) | bit;
-	}
-
-	return retval;
-}
-
-static inline int ath5k_pad_size(int hdrlen)
-{
-	return (hdrlen < 24) ? 0 : hdrlen & 3;
-}
-
-#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/attach.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/attach.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/attach.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/attach.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*************************************\
-* Attach/Detach Functions and helpers *
-\*************************************/
-
-#include <linux/pci.h>
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/**
- * ath5k_hw_post - Power On Self Test helper function
- *
- * @ah: The &struct ath5k_hw
- */
-static int ath5k_hw_post(struct ath5k_hw *ah)
-{
-
-	static const u32 static_pattern[4] = {
-		0x55555555,	0xaaaaaaaa,
-		0x66666666,	0x99999999
-	};
-	static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) };
-	int i, c;
-	u16 cur_reg;
-	u32 var_pattern;
-	u32 init_val;
-	u32 cur_val;
-
-	for (c = 0; c < 2; c++) {
-
-		cur_reg = regs[c];
-
-		/* Save previous value */
-		init_val = ath5k_hw_reg_read(ah, cur_reg);
-
-		for (i = 0; i < 256; i++) {
-			var_pattern = i << 16 | i;
-			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-			cur_val = ath5k_hw_reg_read(ah, cur_reg);
-
-			if (cur_val != var_pattern) {
-				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
-				return -EAGAIN;
-			}
-
-			/* Found on ndiswrapper dumps */
-			var_pattern = 0x0039080f;
-			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-		}
-
-		for (i = 0; i < 4; i++) {
-			var_pattern = static_pattern[i];
-			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-			cur_val = ath5k_hw_reg_read(ah, cur_reg);
-
-			if (cur_val != var_pattern) {
-				ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
-				return -EAGAIN;
-			}
-
-			/* Found on ndiswrapper dumps */
-			var_pattern = 0x003b080f;
-			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-		}
-
-		/* Restore previous value */
-		ath5k_hw_reg_write(ah, init_val, cur_reg);
-
-	}
-
-	return 0;
-
-}
-
-/**
- * ath5k_hw_attach - Check if hw is supported and init the needed structs
- *
- * @sc: The &struct ath5k_softc we got from the driver's attach function
- * @mac_version: The mac version id (check out ath5k.h) based on pci id
- *
- * Check if the device is supported, perform a POST and initialize the needed
- * structs. Returns -ENOMEM if we don't have memory for the needed structs,
- * -ENODEV if the device is not supported or prints an error msg if something
- * else went wrong.
- */
-struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
-{
-	struct ath5k_hw *ah;
-	struct pci_dev *pdev = sc->pdev;
-	int ret;
-	u32 srev;
-
-	/*If we passed the test malloc a ath5k_hw struct*/
-	ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
-	if (ah == NULL) {
-		ret = -ENOMEM;
-		ATH5K_ERR(sc, "out of memory\n");
-		goto err;
-	}
-
-	ah->ah_sc = sc;
-	ah->ah_iobase = sc->iobase;
-
-	/*
-	 * HW information
-	 */
-	ah->ah_op_mode = NL80211_IFTYPE_STATION;
-	ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
-	ah->ah_turbo = false;
-	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
-	ah->ah_imr = 0;
-	ah->ah_atim_window = 0;
-	ah->ah_aifs = AR5K_TUNE_AIFS;
-	ah->ah_cw_min = AR5K_TUNE_CWMIN;
-	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
-	ah->ah_software_retry = false;
-	ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
-
-	/*
-	 * Set the mac version based on the pci id
-	 */
-	ah->ah_version = mac_version;
-
-	/*Fill the ath5k_hw struct with the needed functions*/
-	ret = ath5k_hw_init_desc_functions(ah);
-	if (ret)
-		goto err_free;
-
-	/* Bring device out of sleep and reset it's units */
-	ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
-	if (ret)
-		goto err_free;
-
-	/* Get MAC, PHY and RADIO revisions */
-	srev = ath5k_hw_reg_read(ah, AR5K_SREV);
-	ah->ah_mac_srev = srev;
-	ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
-	ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
-	ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
-			0xffffffff;
-	ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
-			CHANNEL_5GHZ);
-	ah->ah_phy = AR5K_PHY(0);
-
-	/* Try to identify radio chip based on it's srev */
-	switch (ah->ah_radio_5ghz_revision & 0xf0) {
-	case AR5K_SREV_RAD_5111:
-		ah->ah_radio = AR5K_RF5111;
-		ah->ah_single_chip = false;
-		ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
-							CHANNEL_2GHZ);
-		break;
-	case AR5K_SREV_RAD_5112:
-	case AR5K_SREV_RAD_2112:
-		ah->ah_radio = AR5K_RF5112;
-		ah->ah_single_chip = false;
-		ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
-							CHANNEL_2GHZ);
-		break;
-	case AR5K_SREV_RAD_2413:
-		ah->ah_radio = AR5K_RF2413;
-		ah->ah_single_chip = true;
-		break;
-	case AR5K_SREV_RAD_5413:
-		ah->ah_radio = AR5K_RF5413;
-		ah->ah_single_chip = true;
-		break;
-	case AR5K_SREV_RAD_2316:
-		ah->ah_radio = AR5K_RF2316;
-		ah->ah_single_chip = true;
-		break;
-	case AR5K_SREV_RAD_2317:
-		ah->ah_radio = AR5K_RF2317;
-		ah->ah_single_chip = true;
-		break;
-	case AR5K_SREV_RAD_5424:
-		if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
-		ah->ah_mac_version == AR5K_SREV_AR2417){
-			ah->ah_radio = AR5K_RF2425;
-			ah->ah_single_chip = true;
-		} else {
-			ah->ah_radio = AR5K_RF5413;
-			ah->ah_single_chip = true;
-		}
-		break;
-	default:
-		/* Identify radio based on mac/phy srev */
-		if (ah->ah_version == AR5K_AR5210) {
-			ah->ah_radio = AR5K_RF5110;
-			ah->ah_single_chip = false;
-		} else if (ah->ah_version == AR5K_AR5211) {
-			ah->ah_radio = AR5K_RF5111;
-			ah->ah_single_chip = false;
-			ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
-								CHANNEL_2GHZ);
-		} else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
-		ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
-		ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
-			ah->ah_radio = AR5K_RF2425;
-			ah->ah_single_chip = true;
-			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
-		} else if (srev == AR5K_SREV_AR5213A &&
-		ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
-			ah->ah_radio = AR5K_RF5112;
-			ah->ah_single_chip = false;
-			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
-		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
-			ah->ah_radio = AR5K_RF2316;
-			ah->ah_single_chip = true;
-			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
-		} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
-		ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
-			ah->ah_radio = AR5K_RF5413;
-			ah->ah_single_chip = true;
-			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
-		} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
-		ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
-			ah->ah_radio = AR5K_RF2413;
-			ah->ah_single_chip = true;
-			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
-		} else {
-			ATH5K_ERR(sc, "Couldn't identify radio revision.\n");
-			ret = -ENODEV;
-			goto err_free;
-		}
-	}
-
-
-	/* Return on unsuported chips (unsupported eeprom etc) */
-	if ((srev >= AR5K_SREV_AR5416) &&
-	(srev < AR5K_SREV_AR2425)) {
-		ATH5K_ERR(sc, "Device not yet supported.\n");
-		ret = -ENODEV;
-		goto err_free;
-	}
-
-	/*
-	 * Write PCI-E power save settings
-	 */
-	if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
-		ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
-		ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
-		/* Shut off RX when elecidle is asserted */
-		ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
-		ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
-		/* TODO: EEPROM work */
-		ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
-		/* Shut off PLL and CLKREQ active in L1 */
-		ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
-		/* Preserce other settings */
-		ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
-		ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
-		ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
-		/* Reset SERDES to load new settings */
-		ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
-		mdelay(1);
-	}
-
-	/*
-	 * POST
-	 */
-	ret = ath5k_hw_post(ah);
-	if (ret)
-		goto err_free;
-
-	/* Enable pci core retry fix on Hainan (5213A) and later chips */
-	if (srev >= AR5K_SREV_AR5213A)
-		ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
-
-	/*
-	 * Get card capabilities, calibration values etc
-	 * TODO: EEPROM work
-	 */
-	ret = ath5k_eeprom_init(ah);
-	if (ret) {
-		ATH5K_ERR(sc, "unable to init EEPROM\n");
-		goto err_free;
-	}
-
-	/* Get misc capabilities */
-	ret = ath5k_hw_set_capabilities(ah);
-	if (ret) {
-		ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
-			sc->pdev->device);
-		goto err_free;
-	}
-
-	if (srev >= AR5K_SREV_AR2414) {
-		ah->ah_combined_mic = true;
-		AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
-			AR5K_MISC_MODE_COMBINED_MIC);
-	}
-
-	/* MAC address is cleared until add_interface */
-	ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){});
-
-	/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
-	memset(ah->ah_bssid, 0xff, ETH_ALEN);
-	ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
-	ath5k_hw_set_opmode(ah);
-
-	ath5k_hw_rfgain_opt_init(ah);
-
-	return ah;
-err_free:
-	kfree(ah);
-err:
-	return ERR_PTR(ret);
-}
-
-/**
- * ath5k_hw_detach - Free the ath5k_hw struct
- *
- * @ah: The &struct ath5k_hw
- */
-void ath5k_hw_detach(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	__set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
-
-	if (ah->ah_rf_banks != NULL)
-		kfree(ah->ah_rf_banks);
-
-	ath5k_eeprom_detach(ah);
-
-	/* assume interrupts are down */
-	kfree(ah);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/base.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/base.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/base.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/base.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3073 +0,0 @@
-/*-
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
- * Copyright (c) 2004-2005 Atheros Communications, Inc.
- * Copyright (c) 2006 Devicescape Software, Inc.
- * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
- * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
- *    redistribution must be conditioned upon including a substantially
- *    similar Disclaimer requirement for further binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
- *
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/hardirq.h>
-#include <linux/if.h>
-#include <linux/io.h>
-#include <linux/netdevice.h>
-#include <linux/cache.h>
-#include <linux/pci.h>
-#include <linux/ethtool.h>
-#include <linux/uaccess.h>
-
-#include <net/ieee80211_radiotap.h>
-
-#include <asm/unaligned.h>
-
-#include "base.h"
-#include "reg.h"
-#include "debug.h"
-
-static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
-static int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-
-/******************\
-* Internal defines *
-\******************/
-
-/* Module info */
-MODULE_AUTHOR("Jiri Slaby");
-MODULE_AUTHOR("Nick Kossifidis");
-MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
-MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
-
-
-/* Known PCI ids */
-static const struct pci_device_id ath5k_pci_id_table[] = {
-	{ PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */
-	{ PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */
-	{ PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/
-	{ PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */
-	{ PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */
-	{ PCI_VDEVICE(3COM_2,  0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */
-	{ PCI_VDEVICE(3COM,    0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */
-	{ PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */
-	{ PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
-	{ PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
-	{ PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
-	{ PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */
-	{ PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
-
-/* Known SREVs */
-static const struct ath5k_srev_name srev_names[] = {
-	{ "5210",	AR5K_VERSION_MAC,	AR5K_SREV_AR5210 },
-	{ "5311",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311 },
-	{ "5311A",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311A },
-	{ "5311B",	AR5K_VERSION_MAC,	AR5K_SREV_AR5311B },
-	{ "5211",	AR5K_VERSION_MAC,	AR5K_SREV_AR5211 },
-	{ "5212",	AR5K_VERSION_MAC,	AR5K_SREV_AR5212 },
-	{ "5213",	AR5K_VERSION_MAC,	AR5K_SREV_AR5213 },
-	{ "5213A",	AR5K_VERSION_MAC,	AR5K_SREV_AR5213A },
-	{ "2413",	AR5K_VERSION_MAC,	AR5K_SREV_AR2413 },
-	{ "2414",	AR5K_VERSION_MAC,	AR5K_SREV_AR2414 },
-	{ "5424",	AR5K_VERSION_MAC,	AR5K_SREV_AR5424 },
-	{ "5413",	AR5K_VERSION_MAC,	AR5K_SREV_AR5413 },
-	{ "5414",	AR5K_VERSION_MAC,	AR5K_SREV_AR5414 },
-	{ "2415",	AR5K_VERSION_MAC,	AR5K_SREV_AR2415 },
-	{ "5416",	AR5K_VERSION_MAC,	AR5K_SREV_AR5416 },
-	{ "5418",	AR5K_VERSION_MAC,	AR5K_SREV_AR5418 },
-	{ "2425",	AR5K_VERSION_MAC,	AR5K_SREV_AR2425 },
-	{ "2417",	AR5K_VERSION_MAC,	AR5K_SREV_AR2417 },
-	{ "xxxxx",	AR5K_VERSION_MAC,	AR5K_SREV_UNKNOWN },
-	{ "5110",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5110 },
-	{ "5111",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5111 },
-	{ "5111A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5111A },
-	{ "2111",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2111 },
-	{ "5112",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5112 },
-	{ "5112A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5112A },
-	{ "5112B",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5112B },
-	{ "2112",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112 },
-	{ "2112A",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112A },
-	{ "2112B",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2112B },
-	{ "2413",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2413 },
-	{ "5413",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5413 },
-	{ "2316",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2316 },
-	{ "2317",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_2317 },
-	{ "5424",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5424 },
-	{ "5133",	AR5K_VERSION_RAD,	AR5K_SREV_RAD_5133 },
-	{ "xxxxx",	AR5K_VERSION_RAD,	AR5K_SREV_UNKNOWN },
-};
-
-static const struct ieee80211_rate ath5k_rates[] = {
-	{ .bitrate = 10,
-	  .hw_value = ATH5K_RATE_CODE_1M, },
-	{ .bitrate = 20,
-	  .hw_value = ATH5K_RATE_CODE_2M,
-	  .hw_value_short = ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE,
-	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-	{ .bitrate = 55,
-	  .hw_value = ATH5K_RATE_CODE_5_5M,
-	  .hw_value_short = ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE,
-	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-	{ .bitrate = 110,
-	  .hw_value = ATH5K_RATE_CODE_11M,
-	  .hw_value_short = ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE,
-	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-	{ .bitrate = 60,
-	  .hw_value = ATH5K_RATE_CODE_6M,
-	  .flags = 0 },
-	{ .bitrate = 90,
-	  .hw_value = ATH5K_RATE_CODE_9M,
-	  .flags = 0 },
-	{ .bitrate = 120,
-	  .hw_value = ATH5K_RATE_CODE_12M,
-	  .flags = 0 },
-	{ .bitrate = 180,
-	  .hw_value = ATH5K_RATE_CODE_18M,
-	  .flags = 0 },
-	{ .bitrate = 240,
-	  .hw_value = ATH5K_RATE_CODE_24M,
-	  .flags = 0 },
-	{ .bitrate = 360,
-	  .hw_value = ATH5K_RATE_CODE_36M,
-	  .flags = 0 },
-	{ .bitrate = 480,
-	  .hw_value = ATH5K_RATE_CODE_48M,
-	  .flags = 0 },
-	{ .bitrate = 540,
-	  .hw_value = ATH5K_RATE_CODE_54M,
-	  .flags = 0 },
-	/* XR missing */
-};
-
-/*
- * Prototypes - PCI stack related functions
- */
-static int __devinit	ath5k_pci_probe(struct pci_dev *pdev,
-				const struct pci_device_id *id);
-static void __devexit	ath5k_pci_remove(struct pci_dev *pdev);
-#ifdef CONFIG_PM
-static int		ath5k_pci_suspend(struct pci_dev *pdev,
-					pm_message_t state);
-static int		ath5k_pci_resume(struct pci_dev *pdev);
-#else
-#define ath5k_pci_suspend NULL
-#define ath5k_pci_resume NULL
-#endif /* CONFIG_PM */
-
-static struct pci_driver ath5k_pci_driver = {
-	.name		= KBUILD_MODNAME,
-	.id_table	= ath5k_pci_id_table,
-	.probe		= ath5k_pci_probe,
-	.remove		= __devexit_p(ath5k_pci_remove),
-	.suspend	= ath5k_pci_suspend,
-	.resume		= ath5k_pci_resume,
-};
-
-
-
-/*
- * Prototypes - MAC 802.11 stack related functions
- */
-static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_reset_wake(struct ath5k_softc *sc);
-static int ath5k_start(struct ieee80211_hw *hw);
-static void ath5k_stop(struct ieee80211_hw *hw);
-static int ath5k_add_interface(struct ieee80211_hw *hw,
-		struct ieee80211_if_init_conf *conf);
-static void ath5k_remove_interface(struct ieee80211_hw *hw,
-		struct ieee80211_if_init_conf *conf);
-static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
-static int ath5k_config_interface(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif,
-		struct ieee80211_if_conf *conf);
-static void ath5k_configure_filter(struct ieee80211_hw *hw,
-		unsigned int changed_flags,
-		unsigned int *new_flags,
-		int mc_count, struct dev_mc_list *mclist);
-static int ath5k_set_key(struct ieee80211_hw *hw,
-		enum set_key_cmd cmd,
-		struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-		struct ieee80211_key_conf *key);
-static int ath5k_get_stats(struct ieee80211_hw *hw,
-		struct ieee80211_low_level_stats *stats);
-static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
-		struct ieee80211_tx_queue_stats *stats);
-static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
-static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
-static void ath5k_reset_tsf(struct ieee80211_hw *hw);
-static int ath5k_beacon_update(struct ath5k_softc *sc,
-		struct sk_buff *skb);
-static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif,
-		struct ieee80211_bss_conf *bss_conf,
-		u32 changes);
-
-static const struct ieee80211_ops ath5k_hw_ops = {
-	.tx 		= ath5k_tx,
-	.start 		= ath5k_start,
-	.stop 		= ath5k_stop,
-	.add_interface 	= ath5k_add_interface,
-	.remove_interface = ath5k_remove_interface,
-	.config 	= ath5k_config,
-	.config_interface = ath5k_config_interface,
-	.configure_filter = ath5k_configure_filter,
-	.set_key 	= ath5k_set_key,
-	.get_stats 	= ath5k_get_stats,
-	.conf_tx 	= NULL,
-	.get_tx_stats 	= ath5k_get_tx_stats,
-	.get_tsf 	= ath5k_get_tsf,
-	.set_tsf 	= ath5k_set_tsf,
-	.reset_tsf 	= ath5k_reset_tsf,
-	.bss_info_changed = ath5k_bss_info_changed,
-};
-
-/*
- * Prototypes - Internal functions
- */
-/* Attach detach */
-static int 	ath5k_attach(struct pci_dev *pdev,
-			struct ieee80211_hw *hw);
-static void 	ath5k_detach(struct pci_dev *pdev,
-			struct ieee80211_hw *hw);
-/* Channel/mode setup */
-static inline short ath5k_ieee2mhz(short chan);
-static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
-				struct ieee80211_channel *channels,
-				unsigned int mode,
-				unsigned int max);
-static int 	ath5k_setup_bands(struct ieee80211_hw *hw);
-static int 	ath5k_chan_set(struct ath5k_softc *sc,
-				struct ieee80211_channel *chan);
-static void	ath5k_setcurmode(struct ath5k_softc *sc,
-				unsigned int mode);
-static void	ath5k_mode_setup(struct ath5k_softc *sc);
-
-/* Descriptor setup */
-static int	ath5k_desc_alloc(struct ath5k_softc *sc,
-				struct pci_dev *pdev);
-static void	ath5k_desc_free(struct ath5k_softc *sc,
-				struct pci_dev *pdev);
-/* Buffers setup */
-static int 	ath5k_rxbuf_setup(struct ath5k_softc *sc,
-				struct ath5k_buf *bf);
-static int 	ath5k_txbuf_setup(struct ath5k_softc *sc,
-				struct ath5k_buf *bf);
-static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
-				struct ath5k_buf *bf)
-{
-	BUG_ON(!bf);
-	if (!bf->skb)
-		return;
-	pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
-			PCI_DMA_TODEVICE);
-	dev_kfree_skb_any(bf->skb);
-	bf->skb = NULL;
-}
-
-static inline void ath5k_rxbuf_free(struct ath5k_softc *sc,
-				struct ath5k_buf *bf)
-{
-	BUG_ON(!bf);
-	if (!bf->skb)
-		return;
-	pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
-			PCI_DMA_FROMDEVICE);
-	dev_kfree_skb_any(bf->skb);
-	bf->skb = NULL;
-}
-
-
-/* Queues setup */
-static struct 	ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc,
-				int qtype, int subtype);
-static int 	ath5k_beaconq_setup(struct ath5k_hw *ah);
-static int 	ath5k_beaconq_config(struct ath5k_softc *sc);
-static void 	ath5k_txq_drainq(struct ath5k_softc *sc,
-				struct ath5k_txq *txq);
-static void 	ath5k_txq_cleanup(struct ath5k_softc *sc);
-static void 	ath5k_txq_release(struct ath5k_softc *sc);
-/* Rx handling */
-static int 	ath5k_rx_start(struct ath5k_softc *sc);
-static void 	ath5k_rx_stop(struct ath5k_softc *sc);
-static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
-					struct ath5k_desc *ds,
-					struct sk_buff *skb,
-					struct ath5k_rx_status *rs);
-static void 	ath5k_tasklet_rx(unsigned long data);
-/* Tx handling */
-static void 	ath5k_tx_processq(struct ath5k_softc *sc,
-				struct ath5k_txq *txq);
-static void 	ath5k_tasklet_tx(unsigned long data);
-/* Beacon handling */
-static int 	ath5k_beacon_setup(struct ath5k_softc *sc,
-					struct ath5k_buf *bf);
-static void 	ath5k_beacon_send(struct ath5k_softc *sc);
-static void 	ath5k_beacon_config(struct ath5k_softc *sc);
-static void	ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
-static void	ath5k_tasklet_beacon(unsigned long data);
-
-static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
-{
-	u64 tsf = ath5k_hw_get_tsf64(ah);
-
-	if ((tsf & 0x7fff) < rstamp)
-		tsf -= 0x8000;
-
-	return (tsf & ~0x7fff) | rstamp;
-}
-
-/* Interrupt handling */
-static int 	ath5k_init(struct ath5k_softc *sc);
-static int 	ath5k_stop_locked(struct ath5k_softc *sc);
-static int 	ath5k_stop_hw(struct ath5k_softc *sc);
-static irqreturn_t ath5k_intr(int irq, void *dev_id);
-static void 	ath5k_tasklet_reset(unsigned long data);
-
-static void 	ath5k_calibrate(unsigned long data);
-
-/*
- * Module init/exit functions
- */
-static int __init
-init_ath5k_pci(void)
-{
-	int ret;
-
-	ath5k_debug_init();
-
-	ret = pci_register_driver(&ath5k_pci_driver);
-	if (ret) {
-		printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static void __exit
-exit_ath5k_pci(void)
-{
-	pci_unregister_driver(&ath5k_pci_driver);
-
-	ath5k_debug_finish();
-}
-
-module_init(init_ath5k_pci);
-module_exit(exit_ath5k_pci);
-
-
-/********************\
-* PCI Initialization *
-\********************/
-
-static const char *
-ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
-{
-	const char *name = "xxxxx";
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
-		if (srev_names[i].sr_type != type)
-			continue;
-
-		if ((val & 0xf0) == srev_names[i].sr_val)
-			name = srev_names[i].sr_name;
-
-		if ((val & 0xff) == srev_names[i].sr_val) {
-			name = srev_names[i].sr_name;
-			break;
-		}
-	}
-
-	return name;
-}
-
-static int __devinit
-ath5k_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *id)
-{
-	void __iomem *mem;
-	struct ath5k_softc *sc;
-	struct ieee80211_hw *hw;
-	int ret;
-	u8 csz;
-
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "can't enable device\n");
-		goto err;
-	}
-
-	/* XXX 32-bit addressing only */
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret) {
-		dev_err(&pdev->dev, "32-bit DMA not available\n");
-		goto err_dis;
-	}
-
-	/*
-	 * Cache line size is used to size and align various
-	 * structures used to communicate with the hardware.
-	 */
-	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
-	if (csz == 0) {
-		/*
-		 * Linux 2.4.18 (at least) writes the cache line size
-		 * register as a 16-bit wide register which is wrong.
-		 * We must have this setup properly for rx buffer
-		 * DMA to work so force a reasonable value here if it
-		 * comes up zero.
-		 */
-		csz = L1_CACHE_BYTES / sizeof(u32);
-		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
-	}
-	/*
-	 * The default setting of latency timer yields poor results,
-	 * set it to the value used by other systems.  It may be worth
-	 * tweaking this setting more.
-	 */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
-
-	/* Enable bus mastering */
-	pci_set_master(pdev);
-
-	/*
-	 * Disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state.
-	 */
-	pci_write_config_byte(pdev, 0x41, 0);
-
-	ret = pci_request_region(pdev, 0, "ath5k");
-	if (ret) {
-		dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
-		goto err_dis;
-	}
-
-	mem = pci_iomap(pdev, 0, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
-		ret = -EIO;
-		goto err_reg;
-	}
-
-	/*
-	 * Allocate hw (mac80211 main struct)
-	 * and hw->priv (driver private data)
-	 */
-	hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
-	if (hw == NULL) {
-		dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
-		ret = -ENOMEM;
-		goto err_map;
-	}
-
-	dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
-
-	/* Initialize driver private data */
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_NOISE_DBM;
-
-	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC) |
-		BIT(NL80211_IFTYPE_MESH_POINT);
-
-	hw->extra_tx_headroom = 2;
-	hw->channel_change_time = 5000;
-	sc = hw->priv;
-	sc->hw = hw;
-	sc->pdev = pdev;
-
-	ath5k_debug_init_device(sc);
-
-	/*
-	 * Mark the device as detached to avoid processing
-	 * interrupts until setup is complete.
-	 */
-	__set_bit(ATH_STAT_INVALID, sc->status);
-
-	sc->iobase = mem; /* So we can unmap it on detach */
-	sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
-	sc->opmode = NL80211_IFTYPE_STATION;
-	mutex_init(&sc->lock);
-	spin_lock_init(&sc->rxbuflock);
-	spin_lock_init(&sc->txbuflock);
-	spin_lock_init(&sc->block);
-
-	/* Set private data */
-	pci_set_drvdata(pdev, hw);
-
-	/* Setup interrupt handler */
-	ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
-	if (ret) {
-		ATH5K_ERR(sc, "request_irq failed\n");
-		goto err_free;
-	}
-
-	/* Initialize device */
-	sc->ah = ath5k_hw_attach(sc, id->driver_data);
-	if (IS_ERR(sc->ah)) {
-		ret = PTR_ERR(sc->ah);
-		goto err_irq;
-	}
-
-	/* set up multi-rate retry capabilities */
-	if (sc->ah->ah_version == AR5K_AR5212) {
-		hw->max_rates = 4;
-		hw->max_rate_tries = 11;
-	}
-
-	/* Finish private driver data initialization */
-	ret = ath5k_attach(pdev, hw);
-	if (ret)
-		goto err_ah;
-
-	ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
-			ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
-					sc->ah->ah_mac_srev,
-					sc->ah->ah_phy_revision);
-
-	if (!sc->ah->ah_single_chip) {
-		/* Single chip radio (!RF5111) */
-		if (sc->ah->ah_radio_5ghz_revision &&
-			!sc->ah->ah_radio_2ghz_revision) {
-			/* No 5GHz support -> report 2GHz radio */
-			if (!test_bit(AR5K_MODE_11A,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			/* No 2GHz support (5110 and some
-			 * 5Ghz only cards) -> report 5Ghz radio */
-			} else if (!test_bit(AR5K_MODE_11B,
-				sc->ah->ah_capabilities.cap_mode)) {
-				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			/* Multiband radio */
-			} else {
-				ATH5K_INFO(sc, "RF%s multiband radio found"
-					" (0x%x)\n",
-					ath5k_chip_name(AR5K_VERSION_RAD,
-						sc->ah->ah_radio_5ghz_revision),
-						sc->ah->ah_radio_5ghz_revision);
-			}
-		}
-		/* Multi chip radio (RF5111 - RF2111) ->
-		 * report both 2GHz/5GHz radios */
-		else if (sc->ah->ah_radio_5ghz_revision &&
-				sc->ah->ah_radio_2ghz_revision){
-			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_5ghz_revision),
-					sc->ah->ah_radio_5ghz_revision);
-			ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-				ath5k_chip_name(AR5K_VERSION_RAD,
-					sc->ah->ah_radio_2ghz_revision),
-					sc->ah->ah_radio_2ghz_revision);
-		}
-	}
-
-
-	/* ready to process interrupts */
-	__clear_bit(ATH_STAT_INVALID, sc->status);
-
-	return 0;
-err_ah:
-	ath5k_hw_detach(sc->ah);
-err_irq:
-	free_irq(pdev->irq, sc);
-err_free:
-	ieee80211_free_hw(hw);
-err_map:
-	pci_iounmap(pdev, mem);
-err_reg:
-	pci_release_region(pdev, 0);
-err_dis:
-	pci_disable_device(pdev);
-err:
-	return ret;
-}
-
-static void __devexit
-ath5k_pci_remove(struct pci_dev *pdev)
-{
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
-
-	ath5k_debug_finish_device(sc);
-	ath5k_detach(pdev, hw);
-	ath5k_hw_detach(sc->ah);
-	free_irq(pdev->irq, sc);
-	pci_iounmap(pdev, sc->iobase);
-	pci_release_region(pdev, 0);
-	pci_disable_device(pdev);
-	ieee80211_free_hw(hw);
-}
-
-#ifdef CONFIG_PM
-static int
-ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
-
-	ath5k_led_off(sc);
-
-	free_irq(pdev->irq, sc);
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int
-ath5k_pci_resume(struct pci_dev *pdev)
-{
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath5k_softc *sc = hw->priv;
-	int err;
-
-	pci_restore_state(pdev);
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-
-	err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
-	if (err) {
-		ATH5K_ERR(sc, "request_irq failed\n");
-		goto err_no_irq;
-	}
-
-	ath5k_led_enable(sc);
-	return 0;
-
-err_no_irq:
-	pci_disable_device(pdev);
-	return err;
-}
-#endif /* CONFIG_PM */
-
-
-/***********************\
-* Driver Initialization *
-\***********************/
-
-static int
-ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	u8 mac[ETH_ALEN] = {};
-	int ret;
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
-
-	/*
-	 * Check if the MAC has multi-rate retry support.
-	 * We do this by trying to setup a fake extended
-	 * descriptor.  MAC's that don't have support will
-	 * return false w/o doing anything.  MAC's that do
-	 * support it will return true w/o doing anything.
-	 */
-	ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
-	if (ret < 0)
-		goto err;
-	if (ret > 0)
-		__set_bit(ATH_STAT_MRRETRY, sc->status);
-
-	/*
-	 * Collect the channel list.  The 802.11 layer
-	 * is resposible for filtering this list based
-	 * on settings like the phy mode and regulatory
-	 * domain restrictions.
-	 */
-	ret = ath5k_setup_bands(hw);
-	if (ret) {
-		ATH5K_ERR(sc, "can't get channels\n");
-		goto err;
-	}
-
-	/* NB: setup here so ath5k_rate_update is happy */
-	if (test_bit(AR5K_MODE_11A, ah->ah_modes))
-		ath5k_setcurmode(sc, AR5K_MODE_11A);
-	else
-		ath5k_setcurmode(sc, AR5K_MODE_11B);
-
-	/*
-	 * Allocate tx+rx descriptors and populate the lists.
-	 */
-	ret = ath5k_desc_alloc(sc, pdev);
-	if (ret) {
-		ATH5K_ERR(sc, "can't allocate descriptors\n");
-		goto err;
-	}
-
-	/*
-	 * Allocate hardware transmit queues: one queue for
-	 * beacon frames and one data queue for each QoS
-	 * priority.  Note that hw functions handle reseting
-	 * these queues at the needed time.
-	 */
-	ret = ath5k_beaconq_setup(ah);
-	if (ret < 0) {
-		ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
-		goto err_desc;
-	}
-	sc->bhalq = ret;
-
-	sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
-	if (IS_ERR(sc->txq)) {
-		ATH5K_ERR(sc, "can't setup xmit queue\n");
-		ret = PTR_ERR(sc->txq);
-		goto err_bhal;
-	}
-
-	tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
-	tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
-	tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
-	tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
-	setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
-
-	ret = ath5k_eeprom_read_mac(ah, mac);
-	if (ret) {
-		ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
-			sc->pdev->device);
-		goto err_queues;
-	}
-
-	SET_IEEE80211_PERM_ADDR(hw, mac);
-	/* All MAC address bits matter for ACKs */
-	memset(sc->bssidmask, 0xff, ETH_ALEN);
-	ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
-
-	ret = ieee80211_register_hw(hw);
-	if (ret) {
-		ATH5K_ERR(sc, "can't register ieee80211 hw\n");
-		goto err_queues;
-	}
-
-	ath5k_init_leds(sc);
-
-	return 0;
-err_queues:
-	ath5k_txq_release(sc);
-err_bhal:
-	ath5k_hw_release_tx_queue(ah, sc->bhalq);
-err_desc:
-	ath5k_desc_free(sc, pdev);
-err:
-	return ret;
-}
-
-static void
-ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	/*
-	 * NB: the order of these is important:
-	 * o call the 802.11 layer before detaching ath5k_hw to
-	 *   insure callbacks into the driver to delete global
-	 *   key cache entries can be handled
-	 * o reclaim the tx queue data structures after calling
-	 *   the 802.11 layer as we'll get called back to reclaim
-	 *   node state and potentially want to use them
-	 * o to cleanup the tx queues the hal is called, so detach
-	 *   it last
-	 * XXX: ??? detach ath5k_hw ???
-	 * Other than that, it's straightforward...
-	 */
-	ieee80211_unregister_hw(hw);
-	ath5k_desc_free(sc, pdev);
-	ath5k_txq_release(sc);
-	ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
-	ath5k_unregister_leds(sc);
-
-	/*
-	 * NB: can't reclaim these until after ieee80211_ifdetach
-	 * returns because we'll get called back to reclaim node
-	 * state and potentially want to use them.
-	 */
-}
-
-
-
-
-/********************\
-* Channel/mode setup *
-\********************/
-
-/*
- * Convert IEEE channel number to MHz frequency.
- */
-static inline short
-ath5k_ieee2mhz(short chan)
-{
-	if (chan <= 14 || chan >= 27)
-		return ieee80211chan2mhz(chan);
-	else
-		return 2212 + chan * 20;
-}
-
-static unsigned int
-ath5k_copy_channels(struct ath5k_hw *ah,
-		struct ieee80211_channel *channels,
-		unsigned int mode,
-		unsigned int max)
-{
-	unsigned int i, count, size, chfreq, freq, ch;
-
-	if (!test_bit(mode, ah->ah_modes))
-		return 0;
-
-	switch (mode) {
-	case AR5K_MODE_11A:
-	case AR5K_MODE_11A_TURBO:
-		/* 1..220, but 2GHz frequencies are filtered by check_channel */
-		size = 220 ;
-		chfreq = CHANNEL_5GHZ;
-		break;
-	case AR5K_MODE_11B:
-	case AR5K_MODE_11G:
-	case AR5K_MODE_11G_TURBO:
-		size = 26;
-		chfreq = CHANNEL_2GHZ;
-		break;
-	default:
-		ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
-		return 0;
-	}
-
-	for (i = 0, count = 0; i < size && max > 0; i++) {
-		ch = i + 1 ;
-		freq = ath5k_ieee2mhz(ch);
-
-		/* Check if channel is supported by the chipset */
-		if (!ath5k_channel_ok(ah, freq, chfreq))
-			continue;
-
-		/* Write channel info and increment counter */
-		channels[count].center_freq = freq;
-		channels[count].band = (chfreq == CHANNEL_2GHZ) ?
-			IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-		switch (mode) {
-		case AR5K_MODE_11A:
-		case AR5K_MODE_11G:
-			channels[count].hw_value = chfreq | CHANNEL_OFDM;
-			break;
-		case AR5K_MODE_11A_TURBO:
-		case AR5K_MODE_11G_TURBO:
-			channels[count].hw_value = chfreq |
-				CHANNEL_OFDM | CHANNEL_TURBO;
-			break;
-		case AR5K_MODE_11B:
-			channels[count].hw_value = CHANNEL_B;
-		}
-
-		count++;
-		max--;
-	}
-
-	return count;
-}
-
-static void
-ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b)
-{
-	u8 i;
-
-	for (i = 0; i < AR5K_MAX_RATES; i++)
-		sc->rate_idx[b->band][i] = -1;
-
-	for (i = 0; i < b->n_bitrates; i++) {
-		sc->rate_idx[b->band][b->bitrates[i].hw_value] = i;
-		if (b->bitrates[i].hw_value_short)
-			sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i;
-	}
-}
-
-static int
-ath5k_setup_bands(struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	struct ieee80211_supported_band *sband;
-	int max_c, count_c = 0;
-	int i;
-
-	BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
-	max_c = ARRAY_SIZE(sc->channels);
-
-	/* 2GHz band */
-	sband = &sc->sbands[IEEE80211_BAND_2GHZ];
-	sband->band = IEEE80211_BAND_2GHZ;
-	sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0];
-
-	if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
-		/* G mode */
-		memcpy(sband->bitrates, &ath5k_rates[0],
-		       sizeof(struct ieee80211_rate) * 12);
-		sband->n_bitrates = 12;
-
-		sband->channels = sc->channels;
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
-					AR5K_MODE_11G, max_c);
-
-		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
-		count_c = sband->n_channels;
-		max_c -= count_c;
-	} else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) {
-		/* B mode */
-		memcpy(sband->bitrates, &ath5k_rates[0],
-		       sizeof(struct ieee80211_rate) * 4);
-		sband->n_bitrates = 4;
-
-		/* 5211 only supports B rates and uses 4bit rate codes
-		 * (e.g normally we have 0x1B for 1M, but on 5211 we have 0x0B)
-		 * fix them up here:
-		 */
-		if (ah->ah_version == AR5K_AR5211) {
-			for (i = 0; i < 4; i++) {
-				sband->bitrates[i].hw_value =
-					sband->bitrates[i].hw_value & 0xF;
-				sband->bitrates[i].hw_value_short =
-					sband->bitrates[i].hw_value_short & 0xF;
-			}
-		}
-
-		sband->channels = sc->channels;
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
-					AR5K_MODE_11B, max_c);
-
-		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
-		count_c = sband->n_channels;
-		max_c -= count_c;
-	}
-	ath5k_setup_rate_idx(sc, sband);
-
-	/* 5GHz band, A mode */
-	if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
-		sband = &sc->sbands[IEEE80211_BAND_5GHZ];
-		sband->band = IEEE80211_BAND_5GHZ;
-		sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0];
-
-		memcpy(sband->bitrates, &ath5k_rates[4],
-		       sizeof(struct ieee80211_rate) * 8);
-		sband->n_bitrates = 8;
-
-		sband->channels = &sc->channels[count_c];
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
-					AR5K_MODE_11A, max_c);
-
-		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
-	}
-	ath5k_setup_rate_idx(sc, sband);
-
-	ath5k_debug_dump_bands(sc);
-
-	return 0;
-}
-
-/*
- * Set/change channels.  If the channel is really being changed,
- * it's done by reseting the chip.  To accomplish this we must
- * first cleanup any pending DMA, then restart stuff after a la
- * ath5k_init.
- *
- * Called with sc->lock.
- */
-static int
-ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
-{
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
-		sc->curchan->center_freq, chan->center_freq);
-
-	if (chan->center_freq != sc->curchan->center_freq ||
-		chan->hw_value != sc->curchan->hw_value) {
-
-		/*
-		 * To switch channels clear any pending DMA operations;
-		 * wait long enough for the RX fifo to drain, reset the
-		 * hardware at the new frequency, and then re-enable
-		 * the relevant bits of the h/w.
-		 */
-		return ath5k_reset(sc, chan);
-	}
-
-	return 0;
-}
-
-static void
-ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
-{
-	sc->curmode = mode;
-
-	if (mode == AR5K_MODE_11A) {
-		sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
-	} else {
-		sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
-	}
-}
-
-static void
-ath5k_mode_setup(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	u32 rfilt;
-
-	/* configure rx filter */
-	rfilt = sc->filter_flags;
-	ath5k_hw_set_rx_filter(ah, rfilt);
-
-	if (ath5k_hw_hasbssidmask(ah))
-		ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
-
-	/* configure operational mode */
-	ath5k_hw_set_opmode(ah);
-
-	ath5k_hw_set_mcast_filter(ah, 0, 0);
-	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
-}
-
-static inline int
-ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
-{
-	int rix;
-
-	/* return base rate on errors */
-	if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES,
-			"hw_rix out of bounds: %x\n", hw_rix))
-		return 0;
-
-	rix = sc->rate_idx[sc->curband->band][hw_rix];
-	if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
-		rix = 0;
-
-	return rix;
-}
-
-/***************\
-* Buffers setup *
-\***************/
-
-static
-struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
-{
-	struct sk_buff *skb;
-	unsigned int off;
-
-	/*
-	 * Allocate buffer with headroom_needed space for the
-	 * fake physical layer header at the start.
-	 */
-	skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
-
-	if (!skb) {
-		ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
-				sc->rxbufsize + sc->cachelsz - 1);
-		return NULL;
-	}
-	/*
-	 * Cache-line-align.  This is important (for the
-	 * 5210 at least) as not doing so causes bogus data
-	 * in rx'd frames.
-	 */
-	off = ((unsigned long)skb->data) % sc->cachelsz;
-	if (off != 0)
-		skb_reserve(skb, sc->cachelsz - off);
-
-	*skb_addr = pci_map_single(sc->pdev,
-		skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
-	if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
-		ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
-		dev_kfree_skb(skb);
-		return NULL;
-	}
-	return skb;
-}
-
-static int
-ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
-{
-	struct ath5k_hw *ah = sc->ah;
-	struct sk_buff *skb = bf->skb;
-	struct ath5k_desc *ds;
-
-	if (!skb) {
-		skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
-		if (!skb)
-			return -ENOMEM;
-		bf->skb = skb;
-	}
-
-	/*
-	 * Setup descriptors.  For receive we always terminate
-	 * the descriptor list with a self-linked entry so we'll
-	 * not get overrun under high load (as can happen with a
-	 * 5212 when ANI processing enables PHY error frames).
-	 *
-	 * To insure the last descriptor is self-linked we create
-	 * each descriptor as self-linked and add it to the end.  As
-	 * each additional descriptor is added the previous self-linked
-	 * entry is ``fixed'' naturally.  This should be safe even
-	 * if DMA is happening.  When processing RX interrupts we
-	 * never remove/process the last, self-linked, entry on the
-	 * descriptor list.  This insures the hardware always has
-	 * someplace to write a new frame.
-	 */
-	ds = bf->desc;
-	ds->ds_link = bf->daddr;	/* link to self */
-	ds->ds_data = bf->skbaddr;
-	ah->ah_setup_rx_desc(ah, ds,
-		skb_tailroom(skb),	/* buffer size */
-		0);
-
-	if (sc->rxlink != NULL)
-		*sc->rxlink = bf->daddr;
-	sc->rxlink = &ds->ds_link;
-	return 0;
-}
-
-static int
-ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
-{
-	struct ath5k_hw *ah = sc->ah;
-	struct ath5k_txq *txq = sc->txq;
-	struct ath5k_desc *ds = bf->desc;
-	struct sk_buff *skb = bf->skb;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
-	struct ieee80211_rate *rate;
-	unsigned int mrr_rate[3], mrr_tries[3];
-	int i, ret;
-	u16 hw_rate;
-	u16 cts_rate = 0;
-	u16 duration = 0;
-	u8 rc_flags;
-
-	flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
-
-	/* XXX endianness */
-	bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
-			PCI_DMA_TODEVICE);
-
-	rate = ieee80211_get_tx_rate(sc->hw, info);
-
-	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
-		flags |= AR5K_TXDESC_NOACK;
-
-	rc_flags = info->control.rates[0].flags;
-	hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
-		rate->hw_value_short : rate->hw_value;
-
-	pktlen = skb->len;
-
-	/* FIXME: If we are in g mode and rate is a CCK rate
-	 * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
-	 * from tx power (value is in dB units already) */
-	if (info->control.hw_key) {
-		keyidx = info->control.hw_key->hw_key_idx;
-		pktlen += info->control.hw_key->icv_len;
-	}
-	if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-		flags |= AR5K_TXDESC_RTSENA;
-		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
-		duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
-			sc->vif, pktlen, info));
-	}
-	if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-		flags |= AR5K_TXDESC_CTSENA;
-		cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
-		duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
-			sc->vif, pktlen, info));
-	}
-	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
-		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
-		(sc->power_level * 2),
-		hw_rate,
-		info->control.rates[0].count, keyidx, 0, flags,
-		cts_rate, duration);
-	if (ret)
-		goto err_unmap;
-
-	memset(mrr_rate, 0, sizeof(mrr_rate));
-	memset(mrr_tries, 0, sizeof(mrr_tries));
-	for (i = 0; i < 3; i++) {
-		rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
-		if (!rate)
-			break;
-
-		mrr_rate[i] = rate->hw_value;
-		mrr_tries[i] = info->control.rates[i + 1].count;
-	}
-
-	ah->ah_setup_mrr_tx_desc(ah, ds,
-		mrr_rate[0], mrr_tries[0],
-		mrr_rate[1], mrr_tries[1],
-		mrr_rate[2], mrr_tries[2]);
-
-	ds->ds_link = 0;
-	ds->ds_data = bf->skbaddr;
-
-	spin_lock_bh(&txq->lock);
-	list_add_tail(&bf->list, &txq->q);
-	sc->tx_stats[txq->qnum].len++;
-	if (txq->link == NULL) /* is this first packet? */
-		ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
-	else /* no, so only link it */
-		*txq->link = bf->daddr;
-
-	txq->link = &ds->ds_link;
-	ath5k_hw_start_tx_dma(ah, txq->qnum);
-	mmiowb();
-	spin_unlock_bh(&txq->lock);
-
-	return 0;
-err_unmap:
-	pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
-	return ret;
-}
-
-/*******************\
-* Descriptors setup *
-\*******************/
-
-static int
-ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
-{
-	struct ath5k_desc *ds;
-	struct ath5k_buf *bf;
-	dma_addr_t da;
-	unsigned int i;
-	int ret;
-
-	/* allocate descriptors */
-	sc->desc_len = sizeof(struct ath5k_desc) *
-			(ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
-	sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
-	if (sc->desc == NULL) {
-		ATH5K_ERR(sc, "can't allocate descriptors\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-	ds = sc->desc;
-	da = sc->desc_daddr;
-	ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
-		ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
-
-	bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
-			sizeof(struct ath5k_buf), GFP_KERNEL);
-	if (bf == NULL) {
-		ATH5K_ERR(sc, "can't allocate bufptr\n");
-		ret = -ENOMEM;
-		goto err_free;
-	}
-	sc->bufptr = bf;
-
-	INIT_LIST_HEAD(&sc->rxbuf);
-	for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
-		bf->desc = ds;
-		bf->daddr = da;
-		list_add_tail(&bf->list, &sc->rxbuf);
-	}
-
-	INIT_LIST_HEAD(&sc->txbuf);
-	sc->txbuf_len = ATH_TXBUF;
-	for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
-			da += sizeof(*ds)) {
-		bf->desc = ds;
-		bf->daddr = da;
-		list_add_tail(&bf->list, &sc->txbuf);
-	}
-
-	/* beacon buffer */
-	bf->desc = ds;
-	bf->daddr = da;
-	sc->bbuf = bf;
-
-	return 0;
-err_free:
-	pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
-err:
-	sc->desc = NULL;
-	return ret;
-}
-
-static void
-ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
-{
-	struct ath5k_buf *bf;
-
-	ath5k_txbuf_free(sc, sc->bbuf);
-	list_for_each_entry(bf, &sc->txbuf, list)
-		ath5k_txbuf_free(sc, bf);
-	list_for_each_entry(bf, &sc->rxbuf, list)
-		ath5k_rxbuf_free(sc, bf);
-
-	/* Free memory associated with all descriptors */
-	pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
-
-	kfree(sc->bufptr);
-	sc->bufptr = NULL;
-}
-
-
-
-
-
-/**************\
-* Queues setup *
-\**************/
-
-static struct ath5k_txq *
-ath5k_txq_setup(struct ath5k_softc *sc,
-		int qtype, int subtype)
-{
-	struct ath5k_hw *ah = sc->ah;
-	struct ath5k_txq *txq;
-	struct ath5k_txq_info qi = {
-		.tqi_subtype = subtype,
-		.tqi_aifs = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_max = AR5K_TXQ_USEDEFAULT
-	};
-	int qnum;
-
-	/*
-	 * Enable interrupts only for EOL and DESC conditions.
-	 * We mark tx descriptors to receive a DESC interrupt
-	 * when a tx queue gets deep; otherwise waiting for the
-	 * EOL to reap descriptors.  Note that this is done to
-	 * reduce interrupt load and this only defers reaping
-	 * descriptors, never transmitting frames.  Aside from
-	 * reducing interrupts this also permits more concurrency.
-	 * The only potential downside is if the tx queue backs
-	 * up in which case the top half of the kernel may backup
-	 * due to a lack of tx descriptors.
-	 */
-	qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
-				AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
-	qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
-	if (qnum < 0) {
-		/*
-		 * NB: don't print a message, this happens
-		 * normally on parts with too few tx queues
-		 */
-		return ERR_PTR(qnum);
-	}
-	if (qnum >= ARRAY_SIZE(sc->txqs)) {
-		ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
-			qnum, ARRAY_SIZE(sc->txqs));
-		ath5k_hw_release_tx_queue(ah, qnum);
-		return ERR_PTR(-EINVAL);
-	}
-	txq = &sc->txqs[qnum];
-	if (!txq->setup) {
-		txq->qnum = qnum;
-		txq->link = NULL;
-		INIT_LIST_HEAD(&txq->q);
-		spin_lock_init(&txq->lock);
-		txq->setup = true;
-	}
-	return &sc->txqs[qnum];
-}
-
-static int
-ath5k_beaconq_setup(struct ath5k_hw *ah)
-{
-	struct ath5k_txq_info qi = {
-		.tqi_aifs = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_min = AR5K_TXQ_USEDEFAULT,
-		.tqi_cw_max = AR5K_TXQ_USEDEFAULT,
-		/* NB: for dynamic turbo, don't enable any other interrupts */
-		.tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
-	};
-
-	return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi);
-}
-
-static int
-ath5k_beaconq_config(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	struct ath5k_txq_info qi;
-	int ret;
-
-	ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
-	if (ret)
-		return ret;
-	if (sc->opmode == NL80211_IFTYPE_AP ||
-		sc->opmode == NL80211_IFTYPE_MESH_POINT) {
-		/*
-		 * Always burst out beacon and CAB traffic
-		 * (aifs = cwmin = cwmax = 0)
-		 */
-		qi.tqi_aifs = 0;
-		qi.tqi_cw_min = 0;
-		qi.tqi_cw_max = 0;
-	} else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
-		/*
-		 * Adhoc mode; backoff between 0 and (2 * cw_min).
-		 */
-		qi.tqi_aifs = 0;
-		qi.tqi_cw_min = 0;
-		qi.tqi_cw_max = 2 * ah->ah_cw_min;
-	}
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-		"beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
-		qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
-
-	ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi);
-	if (ret) {
-		ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
-			"hardware queue!\n", __func__);
-		return ret;
-	}
-
-	return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */;
-}
-
-static void
-ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
-{
-	struct ath5k_buf *bf, *bf0;
-
-	/*
-	 * NB: this assumes output has been stopped and
-	 *     we do not need to block ath5k_tx_tasklet
-	 */
-	spin_lock_bh(&txq->lock);
-	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-		ath5k_debug_printtxbuf(sc, bf);
-
-		ath5k_txbuf_free(sc, bf);
-
-		spin_lock_bh(&sc->txbuflock);
-		sc->tx_stats[txq->qnum].len--;
-		list_move_tail(&bf->list, &sc->txbuf);
-		sc->txbuf_len++;
-		spin_unlock_bh(&sc->txbuflock);
-	}
-	txq->link = NULL;
-	spin_unlock_bh(&txq->lock);
-}
-
-/*
- * Drain the transmit queues and reclaim resources.
- */
-static void
-ath5k_txq_cleanup(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	unsigned int i;
-
-	/* XXX return value */
-	if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) {
-		/* don't touch the hardware if marked invalid */
-		ath5k_hw_stop_tx_dma(ah, sc->bhalq);
-		ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
-			ath5k_hw_get_txdp(ah, sc->bhalq));
-		for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
-			if (sc->txqs[i].setup) {
-				ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
-				ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
-					"link %p\n",
-					sc->txqs[i].qnum,
-					ath5k_hw_get_txdp(ah,
-							sc->txqs[i].qnum),
-					sc->txqs[i].link);
-			}
-	}
-	ieee80211_wake_queues(sc->hw); /* XXX move to callers */
-
-	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
-		if (sc->txqs[i].setup)
-			ath5k_txq_drainq(sc, &sc->txqs[i]);
-}
-
-static void
-ath5k_txq_release(struct ath5k_softc *sc)
-{
-	struct ath5k_txq *txq = sc->txqs;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
-		if (txq->setup) {
-			ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
-			txq->setup = false;
-		}
-}
-
-
-
-
-/*************\
-* RX Handling *
-\*************/
-
-/*
- * Enable the receive h/w following a reset.
- */
-static int
-ath5k_rx_start(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	struct ath5k_buf *bf;
-	int ret;
-
-	sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz);
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
-		sc->cachelsz, sc->rxbufsize);
-
-	sc->rxlink = NULL;
-
-	spin_lock_bh(&sc->rxbuflock);
-	list_for_each_entry(bf, &sc->rxbuf, list) {
-		ret = ath5k_rxbuf_setup(sc, bf);
-		if (ret != 0) {
-			spin_unlock_bh(&sc->rxbuflock);
-			goto err;
-		}
-	}
-	bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
-	spin_unlock_bh(&sc->rxbuflock);
-
-	ath5k_hw_set_rxdp(ah, bf->daddr);
-	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
-	ath5k_mode_setup(sc);		/* set filters, etc. */
-	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
-
-	return 0;
-err:
-	return ret;
-}
-
-/*
- * Disable the receive h/w in preparation for a reset.
- */
-static void
-ath5k_rx_stop(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-
-	ath5k_hw_stop_rx_pcu(ah);	/* disable PCU */
-	ath5k_hw_set_rx_filter(ah, 0);	/* clear recv filter */
-	ath5k_hw_stop_rx_dma(ah);	/* disable DMA engine */
-
-	ath5k_debug_printrxbuffs(sc, ah);
-
-	sc->rxlink = NULL;		/* just in case */
-}
-
-static unsigned int
-ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
-		struct sk_buff *skb, struct ath5k_rx_status *rs)
-{
-	struct ieee80211_hdr *hdr = (void *)skb->data;
-	unsigned int keyix, hlen;
-
-	if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
-			rs->rs_keyix != AR5K_RXKEYIX_INVALID)
-		return RX_FLAG_DECRYPTED;
-
-	/* Apparently when a default key is used to decrypt the packet
-	   the hw does not set the index used to decrypt.  In such cases
-	   get the index from the packet. */
-	hlen = ieee80211_hdrlen(hdr->frame_control);
-	if (ieee80211_has_protected(hdr->frame_control) &&
-	    !(rs->rs_status & AR5K_RXERR_DECRYPT) &&
-	    skb->len >= hlen + 4) {
-		keyix = skb->data[hlen + 3] >> 6;
-
-		if (test_bit(keyix, sc->keymap))
-			return RX_FLAG_DECRYPTED;
-	}
-
-	return 0;
-}
-
-
-static void
-ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
-		     struct ieee80211_rx_status *rxs)
-{
-	u64 tsf, bc_tstamp;
-	u32 hw_tu;
-	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-
-	if (ieee80211_is_beacon(mgmt->frame_control) &&
-	    le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
-	    memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
-		/*
-		 * Received an IBSS beacon with the same BSSID. Hardware *must*
-		 * have updated the local TSF. We have to work around various
-		 * hardware bugs, though...
-		 */
-		tsf = ath5k_hw_get_tsf64(sc->ah);
-		bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
-		hw_tu = TSF_TO_TU(tsf);
-
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-			"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
-			(unsigned long long)bc_tstamp,
-			(unsigned long long)rxs->mactime,
-			(unsigned long long)(rxs->mactime - bc_tstamp),
-			(unsigned long long)tsf);
-
-		/*
-		 * Sometimes the HW will give us a wrong tstamp in the rx
-		 * status, causing the timestamp extension to go wrong.
-		 * (This seems to happen especially with beacon frames bigger
-		 * than 78 byte (incl. FCS))
-		 * But we know that the receive timestamp must be later than the
-		 * timestamp of the beacon since HW must have synced to that.
-		 *
-		 * NOTE: here we assume mactime to be after the frame was
-		 * received, not like mac80211 which defines it at the start.
-		 */
-		if (bc_tstamp > rxs->mactime) {
-			ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-				"fixing mactime from %llx to %llx\n",
-				(unsigned long long)rxs->mactime,
-				(unsigned long long)tsf);
-			rxs->mactime = tsf;
-		}
-
-		/*
-		 * Local TSF might have moved higher than our beacon timers,
-		 * in that case we have to update them to continue sending
-		 * beacons. This also takes care of synchronizing beacon sending
-		 * times with other stations.
-		 */
-		if (hw_tu >= sc->nexttbtt)
-			ath5k_beacon_update_timers(sc, bc_tstamp);
-	}
-}
-
-static void ath5k_tasklet_beacon(unsigned long data)
-{
-	struct ath5k_softc *sc = (struct ath5k_softc *) data;
-
-	/*
-	 * Software beacon alert--time to send a beacon.
-	 *
-	 * In IBSS mode we use this interrupt just to
-	 * keep track of the next TBTT (target beacon
-	 * transmission time) in order to detect wether
-	 * automatic TSF updates happened.
-	 */
-	if (sc->opmode == NL80211_IFTYPE_ADHOC) {
-		/* XXX: only if VEOL suppported */
-		u64 tsf = ath5k_hw_get_tsf64(sc->ah);
-		sc->nexttbtt += sc->bintval;
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-				"SWBA nexttbtt: %x hw_tu: %x "
-				"TSF: %llx\n",
-				sc->nexttbtt,
-				TSF_TO_TU(tsf),
-				(unsigned long long) tsf);
-	} else {
-		spin_lock(&sc->block);
-		ath5k_beacon_send(sc);
-		spin_unlock(&sc->block);
-	}
-}
-
-static void
-ath5k_tasklet_rx(unsigned long data)
-{
-	struct ieee80211_rx_status rxs = {};
-	struct ath5k_rx_status rs = {};
-	struct sk_buff *skb, *next_skb;
-	dma_addr_t next_skb_addr;
-	struct ath5k_softc *sc = (void *)data;
-	struct ath5k_buf *bf, *bf_last;
-	struct ath5k_desc *ds;
-	int ret;
-	int hdrlen;
-	int padsize;
-
-	spin_lock(&sc->rxbuflock);
-	if (list_empty(&sc->rxbuf)) {
-		ATH5K_WARN(sc, "empty rx buf pool\n");
-		goto unlock;
-	}
-	bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
-	do {
-		rxs.flag = 0;
-
-		bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
-		BUG_ON(bf->skb == NULL);
-		skb = bf->skb;
-		ds = bf->desc;
-
-		/*
-		 * last buffer must not be freed to ensure proper hardware
-		 * function. When the hardware finishes also a packet next to
-		 * it, we are sure, it doesn't use it anymore and we can go on.
-		 */
-		if (bf_last == bf)
-			bf->flags |= 1;
-		if (bf->flags) {
-			struct ath5k_buf *bf_next = list_entry(bf->list.next,
-					struct ath5k_buf, list);
-			ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
-					&rs);
-			if (ret)
-				break;
-			bf->flags &= ~1;
-			/* skip the overwritten one (even status is martian) */
-			goto next;
-		}
-
-		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
-		if (unlikely(ret == -EINPROGRESS))
-			break;
-		else if (unlikely(ret)) {
-			ATH5K_ERR(sc, "error in processing rx descriptor\n");
-			spin_unlock(&sc->rxbuflock);
-			return;
-		}
-
-		if (unlikely(rs.rs_more)) {
-			ATH5K_WARN(sc, "unsupported jumbo\n");
-			goto next;
-		}
-
-		if (unlikely(rs.rs_status)) {
-			if (rs.rs_status & AR5K_RXERR_PHY)
-				goto next;
-			if (rs.rs_status & AR5K_RXERR_DECRYPT) {
-				/*
-				 * Decrypt error.  If the error occurred
-				 * because there was no hardware key, then
-				 * let the frame through so the upper layers
-				 * can process it.  This is necessary for 5210
-				 * parts which have no way to setup a ``clear''
-				 * key cache entry.
-				 *
-				 * XXX do key cache faulting
-				 */
-				if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
-				    !(rs.rs_status & AR5K_RXERR_CRC))
-					goto accept;
-			}
-			if (rs.rs_status & AR5K_RXERR_MIC) {
-				rxs.flag |= RX_FLAG_MMIC_ERROR;
-				goto accept;
-			}
-
-			/* let crypto-error packets fall through in MNTR */
-			if ((rs.rs_status &
-				~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
-					sc->opmode != NL80211_IFTYPE_MONITOR)
-				goto next;
-		}
-accept:
-		next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
-
-		/*
-		 * If we can't replace bf->skb with a new skb under memory
-		 * pressure, just skip this packet
-		 */
-		if (!next_skb)
-			goto next;
-
-		pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
-				PCI_DMA_FROMDEVICE);
-		skb_put(skb, rs.rs_datalen);
-
-		/* The MAC header is padded to have 32-bit boundary if the
-		 * packet payload is non-zero. The general calculation for
-		 * padsize would take into account odd header lengths:
-		 * padsize = (4 - hdrlen % 4) % 4; However, since only
-		 * even-length headers are used, padding can only be 0 or 2
-		 * bytes and we can optimize this a bit. In addition, we must
-		 * not try to remove padding from short control frames that do
-		 * not have payload. */
-		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-		padsize = ath5k_pad_size(hdrlen);
-		if (padsize) {
-			memmove(skb->data + padsize, skb->data, hdrlen);
-			skb_pull(skb, padsize);
-		}
-
-		/*
-		 * always extend the mac timestamp, since this information is
-		 * also needed for proper IBSS merging.
-		 *
-		 * XXX: it might be too late to do it here, since rs_tstamp is
-		 * 15bit only. that means TSF extension has to be done within
-		 * 32768usec (about 32ms). it might be necessary to move this to
-		 * the interrupt handler, like it is done in madwifi.
-		 *
-		 * Unfortunately we don't know when the hardware takes the rx
-		 * timestamp (beginning of phy frame, data frame, end of rx?).
-		 * The only thing we know is that it is hardware specific...
-		 * On AR5213 it seems the rx timestamp is at the end of the
-		 * frame, but i'm not sure.
-		 *
-		 * NOTE: mac80211 defines mactime at the beginning of the first
-		 * data symbol. Since we don't have any time references it's
-		 * impossible to comply to that. This affects IBSS merge only
-		 * right now, so it's not too bad...
-		 */
-		rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
-		rxs.flag |= RX_FLAG_TSFT;
-
-		rxs.freq = sc->curchan->center_freq;
-		rxs.band = sc->curband->band;
-
-		rxs.noise = sc->ah->ah_noise_floor;
-		rxs.signal = rxs.noise + rs.rs_rssi;
-
-		/* An rssi of 35 indicates you should be able use
-		 * 54 Mbps reliably. A more elaborate scheme can be used
-		 * here but it requires a map of SNR/throughput for each
-		 * possible mode used */
-		rxs.qual = rs.rs_rssi * 100 / 35;
-
-		/* rssi can be more than 35 though, anything above that
-		 * should be considered at 100% */
-		if (rxs.qual > 100)
-			rxs.qual = 100;
-
-		rxs.antenna = rs.rs_antenna;
-		rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
-		rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
-
-		if (rxs.rate_idx >= 0 && rs.rs_rate ==
-		    sc->curband->bitrates[rxs.rate_idx].hw_value_short)
-			rxs.flag |= RX_FLAG_SHORTPRE;
-
-		ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
-
-		/* check beacons in IBSS mode */
-		if (sc->opmode == NL80211_IFTYPE_ADHOC)
-			ath5k_check_ibss_tsf(sc, skb, &rxs);
-
-		__ieee80211_rx(sc->hw, skb, &rxs);
-
-		bf->skb = next_skb;
-		bf->skbaddr = next_skb_addr;
-next:
-		list_move_tail(&bf->list, &sc->rxbuf);
-	} while (ath5k_rxbuf_setup(sc, bf) == 0);
-unlock:
-	spin_unlock(&sc->rxbuflock);
-}
-
-
-
-
-/*************\
-* TX Handling *
-\*************/
-
-static void
-ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
-{
-	struct ath5k_tx_status ts = {};
-	struct ath5k_buf *bf, *bf0;
-	struct ath5k_desc *ds;
-	struct sk_buff *skb;
-	struct ieee80211_tx_info *info;
-	int i, ret;
-
-	spin_lock(&txq->lock);
-	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-		ds = bf->desc;
-
-		ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
-		if (unlikely(ret == -EINPROGRESS))
-			break;
-		else if (unlikely(ret)) {
-			ATH5K_ERR(sc, "error %d while processing queue %u\n",
-				ret, txq->qnum);
-			break;
-		}
-
-		skb = bf->skb;
-		info = IEEE80211_SKB_CB(skb);
-		bf->skb = NULL;
-
-		pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
-				PCI_DMA_TODEVICE);
-
-		ieee80211_tx_info_clear_status(info);
-		for (i = 0; i < 4; i++) {
-			struct ieee80211_tx_rate *r =
-				&info->status.rates[i];
-
-			if (ts.ts_rate[i]) {
-				r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
-				r->count = ts.ts_retry[i];
-			} else {
-				r->idx = -1;
-				r->count = 0;
-			}
-		}
-
-		/* count the successful attempt as well */
-		info->status.rates[ts.ts_final_idx].count++;
-
-		if (unlikely(ts.ts_status)) {
-			sc->ll_stats.dot11ACKFailureCount++;
-			if (ts.ts_status & AR5K_TXERR_FILT)
-				info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-		} else {
-			info->flags |= IEEE80211_TX_STAT_ACK;
-			info->status.ack_signal = ts.ts_rssi;
-		}
-
-		ieee80211_tx_status(sc->hw, skb);
-		sc->tx_stats[txq->qnum].count++;
-
-		spin_lock(&sc->txbuflock);
-		sc->tx_stats[txq->qnum].len--;
-		list_move_tail(&bf->list, &sc->txbuf);
-		sc->txbuf_len++;
-		spin_unlock(&sc->txbuflock);
-	}
-	if (likely(list_empty(&txq->q)))
-		txq->link = NULL;
-	spin_unlock(&txq->lock);
-	if (sc->txbuf_len > ATH_TXBUF / 5)
-		ieee80211_wake_queues(sc->hw);
-}
-
-static void
-ath5k_tasklet_tx(unsigned long data)
-{
-	struct ath5k_softc *sc = (void *)data;
-
-	ath5k_tx_processq(sc, sc->txq);
-}
-
-
-/*****************\
-* Beacon handling *
-\*****************/
-
-/*
- * Setup the beacon frame for transmit.
- */
-static int
-ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
-{
-	struct sk_buff *skb = bf->skb;
-	struct	ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ath5k_hw *ah = sc->ah;
-	struct ath5k_desc *ds;
-	int ret, antenna = 0;
-	u32 flags;
-
-	bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
-			PCI_DMA_TODEVICE);
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
-			"skbaddr %llx\n", skb, skb->data, skb->len,
-			(unsigned long long)bf->skbaddr);
-	if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) {
-		ATH5K_ERR(sc, "beacon DMA mapping failed\n");
-		return -EIO;
-	}
-
-	ds = bf->desc;
-
-	flags = AR5K_TXDESC_NOACK;
-	if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) {
-		ds->ds_link = bf->daddr;	/* self-linked */
-		flags |= AR5K_TXDESC_VEOL;
-		/*
-		 * Let hardware handle antenna switching if txantenna is not set
-		 */
-	} else {
-		ds->ds_link = 0;
-		/*
-		 * Switch antenna every 4 beacons if txantenna is not set
-		 * XXX assumes two antennas
-		 */
-		if (antenna == 0)
-			antenna = sc->bsent & 4 ? 2 : 1;
-	}
-
-	/* FIXME: If we are in g mode and rate is a CCK rate
-	 * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta
-	 * from tx power (value is in dB units already) */
-	ds->ds_data = bf->skbaddr;
-	ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
-			ieee80211_get_hdrlen_from_skb(skb),
-			AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
-			ieee80211_get_tx_rate(sc->hw, info)->hw_value,
-			1, AR5K_TXKEYIX_INVALID,
-			antenna, flags, 0, 0);
-	if (ret)
-		goto err_unmap;
-
-	return 0;
-err_unmap:
-	pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
-	return ret;
-}
-
-/*
- * Transmit a beacon frame at SWBA.  Dynamic updates to the
- * frame contents are done as needed and the slot time is
- * also adjusted based on current state.
- *
- * This is called from software irq context (beacontq or restq
- * tasklets) or user context from ath5k_beacon_config.
- */
-static void
-ath5k_beacon_send(struct ath5k_softc *sc)
-{
-	struct ath5k_buf *bf = sc->bbuf;
-	struct ath5k_hw *ah = sc->ah;
-
-	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
-
-	if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
-			sc->opmode == NL80211_IFTYPE_MONITOR)) {
-		ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
-		return;
-	}
-	/*
-	 * Check if the previous beacon has gone out.  If
-	 * not don't don't try to post another, skip this
-	 * period and wait for the next.  Missed beacons
-	 * indicate a problem and should not occur.  If we
-	 * miss too many consecutive beacons reset the device.
-	 */
-	if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
-		sc->bmisscount++;
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-			"missed %u consecutive beacons\n", sc->bmisscount);
-		if (sc->bmisscount > 3) {		/* NB: 3 is a guess */
-			ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-				"stuck beacon time (%u missed)\n",
-				sc->bmisscount);
-			tasklet_schedule(&sc->restq);
-		}
-		return;
-	}
-	if (unlikely(sc->bmisscount != 0)) {
-		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-			"resume beacon xmit after %u misses\n",
-			sc->bmisscount);
-		sc->bmisscount = 0;
-	}
-
-	/*
-	 * Stop any current dma and put the new frame on the queue.
-	 * This should never fail since we check above that no frames
-	 * are still pending on the queue.
-	 */
-	if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
-		ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq);
-		/* NB: hw still stops DMA, so proceed */
-	}
-
-	ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
-	ath5k_hw_start_tx_dma(ah, sc->bhalq);
-	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
-		sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
-
-	sc->bsent++;
-}
-
-
-/**
- * ath5k_beacon_update_timers - update beacon timers
- *
- * @sc: struct ath5k_softc pointer we are operating on
- * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
- *          beacon timer update based on the current HW TSF.
- *
- * Calculate the next target beacon transmit time (TBTT) based on the timestamp
- * of a received beacon or the current local hardware TSF and write it to the
- * beacon timer registers.
- *
- * This is called in a variety of situations, e.g. when a beacon is received,
- * when a TSF update has been detected, but also when an new IBSS is created or
- * when we otherwise know we have to update the timers, but we keep it in this
- * function to have it all together in one place.
- */
-static void
-ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
-{
-	struct ath5k_hw *ah = sc->ah;
-	u32 nexttbtt, intval, hw_tu, bc_tu;
-	u64 hw_tsf;
-
-	intval = sc->bintval & AR5K_BEACON_PERIOD;
-	if (WARN_ON(!intval))
-		return;
-
-	/* beacon TSF converted to TU */
-	bc_tu = TSF_TO_TU(bc_tsf);
-
-	/* current TSF converted to TU */
-	hw_tsf = ath5k_hw_get_tsf64(ah);
-	hw_tu = TSF_TO_TU(hw_tsf);
-
-#define FUDGE 3
-	/* we use FUDGE to make sure the next TBTT is ahead of the current TU */
-	if (bc_tsf == -1) {
-		/*
-		 * no beacons received, called internally.
-		 * just need to refresh timers based on HW TSF.
-		 */
-		nexttbtt = roundup(hw_tu + FUDGE, intval);
-	} else if (bc_tsf == 0) {
-		/*
-		 * no beacon received, probably called by ath5k_reset_tsf().
-		 * reset TSF to start with 0.
-		 */
-		nexttbtt = intval;
-		intval |= AR5K_BEACON_RESET_TSF;
-	} else if (bc_tsf > hw_tsf) {
-		/*
-		 * beacon received, SW merge happend but HW TSF not yet updated.
-		 * not possible to reconfigure timers yet, but next time we
-		 * receive a beacon with the same BSSID, the hardware will
-		 * automatically update the TSF and then we need to reconfigure
-		 * the timers.
-		 */
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-			"need to wait for HW TSF sync\n");
-		return;
-	} else {
-		/*
-		 * most important case for beacon synchronization between STA.
-		 *
-		 * beacon received and HW TSF has been already updated by HW.
-		 * update next TBTT based on the TSF of the beacon, but make
-		 * sure it is ahead of our local TSF timer.
-		 */
-		nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval);
-	}
-#undef FUDGE
-
-	sc->nexttbtt = nexttbtt;
-
-	intval |= AR5K_BEACON_ENA;
-	ath5k_hw_init_beacon(ah, nexttbtt, intval);
-
-	/*
-	 * debugging output last in order to preserve the time critical aspect
-	 * of this function
-	 */
-	if (bc_tsf == -1)
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-			"reconfigured timers based on HW TSF\n");
-	else if (bc_tsf == 0)
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-			"reset HW TSF and timers\n");
-	else
-		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-			"updated timers based on beacon TSF\n");
-
-	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-			  "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
-			  (unsigned long long) bc_tsf,
-			  (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt);
-	ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
-		intval & AR5K_BEACON_PERIOD,
-		intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
-		intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
-}
-
-
-/**
- * ath5k_beacon_config - Configure the beacon queues and interrupts
- *
- * @sc: struct ath5k_softc pointer we are operating on
- *
- * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
- * interrupts to detect TSF updates only.
- */
-static void
-ath5k_beacon_config(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	unsigned long flags;
-
-	ath5k_hw_set_imr(ah, 0);
-	sc->bmisscount = 0;
-	sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
-
-	if (sc->opmode == NL80211_IFTYPE_ADHOC ||
-			sc->opmode == NL80211_IFTYPE_MESH_POINT ||
-			sc->opmode == NL80211_IFTYPE_AP) {
-		/*
-		 * In IBSS mode we use a self-linked tx descriptor and let the
-		 * hardware send the beacons automatically. We have to load it
-		 * only once here.
-		 * We use the SWBA interrupt only to keep track of the beacon
-		 * timers in order to detect automatic TSF updates.
-		 */
-		ath5k_beaconq_config(sc);
-
-		sc->imask |= AR5K_INT_SWBA;
-
-		if (sc->opmode == NL80211_IFTYPE_ADHOC) {
-			if (ath5k_hw_hasveol(ah)) {
-				spin_lock_irqsave(&sc->block, flags);
-				ath5k_beacon_send(sc);
-				spin_unlock_irqrestore(&sc->block, flags);
-			}
-		} else
-			ath5k_beacon_update_timers(sc, -1);
-	}
-
-	ath5k_hw_set_imr(ah, sc->imask);
-}
-
-
-/********************\
-* Interrupt handling *
-\********************/
-
-static int
-ath5k_init(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-	int ret, i;
-
-	mutex_lock(&sc->lock);
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
-
-	/*
-	 * Stop anything previously setup.  This is safe
-	 * no matter this is the first time through or not.
-	 */
-	ath5k_stop_locked(sc);
-
-	/*
-	 * The basic interface to setting the hardware in a good
-	 * state is ``reset''.  On return the hardware is known to
-	 * be powered up and with interrupts disabled.  This must
-	 * be followed by initialization of the appropriate bits
-	 * and then setup of the interrupt mask.
-	 */
-	sc->curchan = sc->hw->conf.channel;
-	sc->curband = &sc->sbands[sc->curchan->band];
-	sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
-		AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
-		AR5K_INT_FATAL | AR5K_INT_GLOBAL;
-	ret = ath5k_reset(sc, NULL);
-	if (ret)
-		goto done;
-
-	/*
-	 * Reset the key cache since some parts do not reset the
-	 * contents on initial power up or resume from suspend.
-	 */
-	for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
-		ath5k_hw_reset_key(ah, i);
-
-	/* Set ack to be sent at low bit-rates */
-	ath5k_hw_set_ack_bitrate_high(ah, false);
-
-	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
-			msecs_to_jiffies(ath5k_calinterval * 1000)));
-
-	ret = 0;
-done:
-	mmiowb();
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static int
-ath5k_stop_locked(struct ath5k_softc *sc)
-{
-	struct ath5k_hw *ah = sc->ah;
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
-			test_bit(ATH_STAT_INVALID, sc->status));
-
-	/*
-	 * Shutdown the hardware and driver:
-	 *    stop output from above
-	 *    disable interrupts
-	 *    turn off timers
-	 *    turn off the radio
-	 *    clear transmit machinery
-	 *    clear receive machinery
-	 *    drain and release tx queues
-	 *    reclaim beacon resources
-	 *    power down hardware
-	 *
-	 * Note that some of this work is not possible if the
-	 * hardware is gone (invalid).
-	 */
-	ieee80211_stop_queues(sc->hw);
-
-	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
-		ath5k_led_off(sc);
-		ath5k_hw_set_imr(ah, 0);
-		synchronize_irq(sc->pdev->irq);
-	}
-	ath5k_txq_cleanup(sc);
-	if (!test_bit(ATH_STAT_INVALID, sc->status)) {
-		ath5k_rx_stop(sc);
-		ath5k_hw_phy_disable(ah);
-	} else
-		sc->rxlink = NULL;
-
-	return 0;
-}
-
-/*
- * Stop the device, grabbing the top-level lock to protect
- * against concurrent entry through ath5k_init (which can happen
- * if another thread does a system call and the thread doing the
- * stop is preempted).
- */
-static int
-ath5k_stop_hw(struct ath5k_softc *sc)
-{
-	int ret;
-
-	mutex_lock(&sc->lock);
-	ret = ath5k_stop_locked(sc);
-	if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
-		/*
-		 * Set the chip in full sleep mode.  Note that we are
-		 * careful to do this only when bringing the interface
-		 * completely to a stop.  When the chip is in this state
-		 * it must be carefully woken up or references to
-		 * registers in the PCI clock domain may freeze the bus
-		 * (and system).  This varies by chip and is mostly an
-		 * issue with newer parts that go to sleep more quickly.
-		 */
-		if (sc->ah->ah_mac_srev >= 0x78) {
-			/*
-			 * XXX
-			 * don't put newer MAC revisions > 7.8 to sleep because
-			 * of the above mentioned problems
-			 */
-			ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
-				"not putting device to sleep\n");
-		} else {
-			ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
-				"putting device to full sleep\n");
-			ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
-		}
-	}
-	ath5k_txbuf_free(sc, sc->bbuf);
-
-	mmiowb();
-	mutex_unlock(&sc->lock);
-
-	del_timer_sync(&sc->calib_tim);
-	tasklet_kill(&sc->rxtq);
-	tasklet_kill(&sc->txtq);
-	tasklet_kill(&sc->restq);
-	tasklet_kill(&sc->beacontq);
-
-	return ret;
-}
-
-static irqreturn_t
-ath5k_intr(int irq, void *dev_id)
-{
-	struct ath5k_softc *sc = dev_id;
-	struct ath5k_hw *ah = sc->ah;
-	enum ath5k_int status;
-	unsigned int counter = 1000;
-
-	if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
-				!ath5k_hw_is_intr_pending(ah)))
-		return IRQ_NONE;
-
-	do {
-		ath5k_hw_get_isr(ah, &status);		/* NB: clears IRQ too */
-		ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
-				status, sc->imask);
-		if (unlikely(status & AR5K_INT_FATAL)) {
-			/*
-			 * Fatal errors are unrecoverable.
-			 * Typically these are caused by DMA errors.
-			 */
-			tasklet_schedule(&sc->restq);
-		} else if (unlikely(status & AR5K_INT_RXORN)) {
-			tasklet_schedule(&sc->restq);
-		} else {
-			if (status & AR5K_INT_SWBA) {
-				tasklet_schedule(&sc->beacontq);
-			}
-			if (status & AR5K_INT_RXEOL) {
-				/*
-				* NB: the hardware should re-read the link when
-				*     RXE bit is written, but it doesn't work at
-				*     least on older hardware revs.
-				*/
-				sc->rxlink = NULL;
-			}
-			if (status & AR5K_INT_TXURN) {
-				/* bump tx trigger level */
-				ath5k_hw_update_tx_triglevel(ah, true);
-			}
-			if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
-				tasklet_schedule(&sc->rxtq);
-			if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
-					| AR5K_INT_TXERR | AR5K_INT_TXEOL))
-				tasklet_schedule(&sc->txtq);
-			if (status & AR5K_INT_BMISS) {
-				/* TODO */
-			}
-			if (status & AR5K_INT_MIB) {
-				/*
-				 * These stats are also used for ANI i think
-				 * so how about updating them more often ?
-				 */
-				ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
-			}
-		}
-	} while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
-
-	if (unlikely(!counter))
-		ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
-
-	return IRQ_HANDLED;
-}
-
-static void
-ath5k_tasklet_reset(unsigned long data)
-{
-	struct ath5k_softc *sc = (void *)data;
-
-	ath5k_reset_wake(sc);
-}
-
-/*
- * Periodically recalibrate the PHY to account
- * for temperature/environment changes.
- */
-static void
-ath5k_calibrate(unsigned long data)
-{
-	struct ath5k_softc *sc = (void *)data;
-	struct ath5k_hw *ah = sc->ah;
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
-		ieee80211_frequency_to_channel(sc->curchan->center_freq),
-		sc->curchan->hw_value);
-
-	if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) {
-		/*
-		 * Rfgain is out of bounds, reset the chip
-		 * to load new gain values.
-		 */
-		ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
-		ath5k_reset_wake(sc);
-	}
-	if (ath5k_hw_phy_calibrate(ah, sc->curchan))
-		ATH5K_ERR(sc, "calibration of channel %u failed\n",
-			ieee80211_frequency_to_channel(
-				sc->curchan->center_freq));
-
-	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
-			msecs_to_jiffies(ath5k_calinterval * 1000)));
-}
-
-
-/********************\
-* Mac80211 functions *
-\********************/
-
-static int
-ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_buf *bf;
-	unsigned long flags;
-	int hdrlen;
-	int padsize;
-
-	ath5k_debug_dump_skb(sc, skb, "TX  ", 1);
-
-	if (sc->opmode == NL80211_IFTYPE_MONITOR)
-		ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
-
-	/*
-	 * the hardware expects the header padded to 4 byte boundaries
-	 * if this is not the case we add the padding after the header
-	 */
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	padsize = ath5k_pad_size(hdrlen);
-	if (padsize) {
-
-		if (skb_headroom(skb) < padsize) {
-			ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
-				  " headroom to pad %d\n", hdrlen, padsize);
-			goto drop_packet;
-		}
-		skb_push(skb, padsize);
-		memmove(skb->data, skb->data+padsize, hdrlen);
-	}
-
-	spin_lock_irqsave(&sc->txbuflock, flags);
-	if (list_empty(&sc->txbuf)) {
-		ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
-		spin_unlock_irqrestore(&sc->txbuflock, flags);
-		ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
-		goto drop_packet;
-	}
-	bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
-	list_del(&bf->list);
-	sc->txbuf_len--;
-	if (list_empty(&sc->txbuf))
-		ieee80211_stop_queues(hw);
-	spin_unlock_irqrestore(&sc->txbuflock, flags);
-
-	bf->skb = skb;
-
-	if (ath5k_txbuf_setup(sc, bf)) {
-		bf->skb = NULL;
-		spin_lock_irqsave(&sc->txbuflock, flags);
-		list_add_tail(&bf->list, &sc->txbuf);
-		sc->txbuf_len++;
-		spin_unlock_irqrestore(&sc->txbuflock, flags);
-		goto drop_packet;
-	}
-	return NETDEV_TX_OK;
-
-drop_packet:
-	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
-}
-
-/*
- * Reset the hardware.  If chan is not NULL, then also pause rx/tx
- * and change to the given channel.
- */
-static int
-ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
-{
-	struct ath5k_hw *ah = sc->ah;
-	int ret;
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
-
-	if (chan) {
-		ath5k_hw_set_imr(ah, 0);
-		ath5k_txq_cleanup(sc);
-		ath5k_rx_stop(sc);
-
-		sc->curchan = chan;
-		sc->curband = &sc->sbands[chan->band];
-	}
-	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
-	if (ret) {
-		ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
-		goto err;
-	}
-
-	ret = ath5k_rx_start(sc);
-	if (ret) {
-		ATH5K_ERR(sc, "can't start recv logic\n");
-		goto err;
-	}
-
-	/*
-	 * Change channels and update the h/w rate map if we're switching;
-	 * e.g. 11a to 11b/g.
-	 *
-	 * We may be doing a reset in response to an ioctl that changes the
-	 * channel so update any state that might change as a result.
-	 *
-	 * XXX needed?
-	 */
-/*	ath5k_chan_change(sc, c); */
-
-	ath5k_beacon_config(sc);
-	/* intrs are enabled by ath5k_beacon_config */
-
-	return 0;
-err:
-	return ret;
-}
-
-static int
-ath5k_reset_wake(struct ath5k_softc *sc)
-{
-	int ret;
-
-	ret = ath5k_reset(sc, sc->curchan);
-	if (!ret)
-		ieee80211_wake_queues(sc->hw);
-
-	return ret;
-}
-
-static int ath5k_start(struct ieee80211_hw *hw)
-{
-	return ath5k_init(hw->priv);
-}
-
-static void ath5k_stop(struct ieee80211_hw *hw)
-{
-	ath5k_stop_hw(hw->priv);
-}
-
-static int ath5k_add_interface(struct ieee80211_hw *hw,
-		struct ieee80211_if_init_conf *conf)
-{
-	struct ath5k_softc *sc = hw->priv;
-	int ret;
-
-	mutex_lock(&sc->lock);
-	if (sc->vif) {
-		ret = 0;
-		goto end;
-	}
-
-	sc->vif = conf->vif;
-
-	switch (conf->type) {
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_MESH_POINT:
-	case NL80211_IFTYPE_MONITOR:
-		sc->opmode = conf->type;
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-		goto end;
-	}
-
-	/* Set to a reasonable value. Note that this will
-	 * be set to mac80211's value at ath5k_config(). */
-	sc->bintval = 1000;
-	ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
-
-	ret = 0;
-end:
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static void
-ath5k_remove_interface(struct ieee80211_hw *hw,
-			struct ieee80211_if_init_conf *conf)
-{
-	struct ath5k_softc *sc = hw->priv;
-	u8 mac[ETH_ALEN] = {};
-
-	mutex_lock(&sc->lock);
-	if (sc->vif != conf->vif)
-		goto end;
-
-	ath5k_hw_set_lladdr(sc->ah, mac);
-	sc->vif = NULL;
-end:
-	mutex_unlock(&sc->lock);
-}
-
-/*
- * TODO: Phy disable/diversity etc
- */
-static int
-ath5k_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ieee80211_conf *conf = &hw->conf;
-	int ret;
-
-	mutex_lock(&sc->lock);
-
-	sc->bintval = conf->beacon_int;
-	sc->power_level = conf->power_level;
-
-	ret = ath5k_chan_set(sc, conf->channel);
-
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static int
-ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			struct ieee80211_if_conf *conf)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	int ret = 0;
-
-	mutex_lock(&sc->lock);
-	if (sc->vif != vif) {
-		ret = -EIO;
-		goto unlock;
-	}
-	if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
-		/* Cache for later use during resets */
-		memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN);
-		/* XXX: assoc id is set to 0 for now, mac80211 doesn't have
-		 * a clean way of letting us retrieve this yet. */
-		ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
-		mmiowb();
-	}
-	if (conf->changed & IEEE80211_IFCC_BEACON &&
-			(vif->type == NL80211_IFTYPE_ADHOC ||
-			 vif->type == NL80211_IFTYPE_MESH_POINT ||
-			 vif->type == NL80211_IFTYPE_AP)) {
-		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-		if (!beacon) {
-			ret = -ENOMEM;
-			goto unlock;
-		}
-		ath5k_beacon_update(sc, beacon);
-	}
-
-unlock:
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-#define SUPPORTED_FIF_FLAGS \
-	FIF_PROMISC_IN_BSS |  FIF_ALLMULTI | FIF_FCSFAIL | \
-	FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
-	FIF_BCN_PRBRESP_PROMISC
-/*
- * o always accept unicast, broadcast, and multicast traffic
- * o multicast traffic for all BSSIDs will be enabled if mac80211
- *   says it should be
- * o maintain current state of phy ofdm or phy cck error reception.
- *   If the hardware detects any of these type of errors then
- *   ath5k_hw_get_rx_filter() will pass to us the respective
- *   hardware filters to be able to receive these type of frames.
- * o probe request frames are accepted only when operating in
- *   hostap, adhoc, or monitor modes
- * o enable promiscuous mode according to the interface state
- * o accept beacons:
- *   - when operating in adhoc mode so the 802.11 layer creates
- *     node table entries for peers,
- *   - when operating in station mode for collecting rssi data when
- *     the station is otherwise quiet, or
- *   - when scanning
- */
-static void ath5k_configure_filter(struct ieee80211_hw *hw,
-		unsigned int changed_flags,
-		unsigned int *new_flags,
-		int mc_count, struct dev_mc_list *mclist)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	u32 mfilt[2], val, rfilt;
-	u8 pos;
-	int i;
-
-	mfilt[0] = 0;
-	mfilt[1] = 0;
-
-	/* Only deal with supported flags */
-	changed_flags &= SUPPORTED_FIF_FLAGS;
-	*new_flags &= SUPPORTED_FIF_FLAGS;
-
-	/* If HW detects any phy or radar errors, leave those filters on.
-	 * Also, always enable Unicast, Broadcasts and Multicast
-	 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
-	rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
-		(AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
-		AR5K_RX_FILTER_MCAST);
-
-	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
-		if (*new_flags & FIF_PROMISC_IN_BSS) {
-			rfilt |= AR5K_RX_FILTER_PROM;
-			__set_bit(ATH_STAT_PROMISC, sc->status);
-		} else {
-			__clear_bit(ATH_STAT_PROMISC, sc->status);
-		}
-	}
-
-	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
-	if (*new_flags & FIF_ALLMULTI) {
-		mfilt[0] =  ~0;
-		mfilt[1] =  ~0;
-	} else {
-		for (i = 0; i < mc_count; i++) {
-			if (!mclist)
-				break;
-			/* calculate XOR of eight 6-bit values */
-			val = get_unaligned_le32(mclist->dmi_addr + 0);
-			pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
-			val = get_unaligned_le32(mclist->dmi_addr + 3);
-			pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
-			pos &= 0x3f;
-			mfilt[pos / 32] |= (1 << (pos % 32));
-			/* XXX: we might be able to just do this instead,
-			* but not sure, needs testing, if we do use this we'd
-			* neet to inform below to not reset the mcast */
-			/* ath5k_hw_set_mcast_filterindex(ah,
-			 *      mclist->dmi_addr[5]); */
-			mclist = mclist->next;
-		}
-	}
-
-	/* This is the best we can do */
-	if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
-		rfilt |= AR5K_RX_FILTER_PHYERR;
-
-	/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
-	* and probes for any BSSID, this needs testing */
-	if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
-		rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ;
-
-	/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
-	 * set we should only pass on control frames for this
-	 * station. This needs testing. I believe right now this
-	 * enables *all* control frames, which is OK.. but
-	 * but we should see if we can improve on granularity */
-	if (*new_flags & FIF_CONTROL)
-		rfilt |= AR5K_RX_FILTER_CONTROL;
-
-	/* Additional settings per mode -- this is per ath5k */
-
-	/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
-
-	if (sc->opmode == NL80211_IFTYPE_MONITOR)
-		rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
-			AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
-	if (sc->opmode != NL80211_IFTYPE_STATION)
-		rfilt |= AR5K_RX_FILTER_PROBEREQ;
-	if (sc->opmode != NL80211_IFTYPE_AP &&
-		sc->opmode != NL80211_IFTYPE_MESH_POINT &&
-		test_bit(ATH_STAT_PROMISC, sc->status))
-		rfilt |= AR5K_RX_FILTER_PROM;
-	if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) ||
-		sc->opmode == NL80211_IFTYPE_ADHOC ||
-		sc->opmode == NL80211_IFTYPE_AP)
-		rfilt |= AR5K_RX_FILTER_BEACON;
-	if (sc->opmode == NL80211_IFTYPE_MESH_POINT)
-		rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
-			AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
-
-	/* Set filters */
-	ath5k_hw_set_rx_filter(ah, rfilt);
-
-	/* Set multicast bits */
-	ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
-	/* Set the cached hw filter flags, this will alter actually
-	 * be set in HW */
-	sc->filter_flags = rfilt;
-}
-
-static int
-ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-	      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-	      struct ieee80211_key_conf *key)
-{
-	struct ath5k_softc *sc = hw->priv;
-	int ret = 0;
-
-	if (modparam_nohwcrypt)
-		return -EOPNOTSUPP;
-
-	switch (key->alg) {
-	case ALG_WEP:
-	case ALG_TKIP:
-		break;
-	case ALG_CCMP:
-		return -EOPNOTSUPP;
-	default:
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	mutex_lock(&sc->lock);
-
-	switch (cmd) {
-	case SET_KEY:
-		ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
-				       sta ? sta->addr : NULL);
-		if (ret) {
-			ATH5K_ERR(sc, "can't set the key\n");
-			goto unlock;
-		}
-		__set_bit(key->keyidx, sc->keymap);
-		key->hw_key_idx = key->keyidx;
-		key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
-			       IEEE80211_KEY_FLAG_GENERATE_MMIC);
-		break;
-	case DISABLE_KEY:
-		ath5k_hw_reset_key(sc->ah, key->keyidx);
-		__clear_bit(key->keyidx, sc->keymap);
-		break;
-	default:
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-unlock:
-	mmiowb();
-	mutex_unlock(&sc->lock);
-	return ret;
-}
-
-static int
-ath5k_get_stats(struct ieee80211_hw *hw,
-		struct ieee80211_low_level_stats *stats)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-
-	/* Force update */
-	ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
-
-	memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
-
-	return 0;
-}
-
-static int
-ath5k_get_tx_stats(struct ieee80211_hw *hw,
-		struct ieee80211_tx_queue_stats *stats)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats));
-
-	return 0;
-}
-
-static u64
-ath5k_get_tsf(struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	return ath5k_hw_get_tsf64(sc->ah);
-}
-
-static void
-ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	ath5k_hw_set_tsf64(sc->ah, tsf);
-}
-
-static void
-ath5k_reset_tsf(struct ieee80211_hw *hw)
-{
-	struct ath5k_softc *sc = hw->priv;
-
-	/*
-	 * in IBSS mode we need to update the beacon timers too.
-	 * this will also reset the TSF if we call it with 0
-	 */
-	if (sc->opmode == NL80211_IFTYPE_ADHOC)
-		ath5k_beacon_update_timers(sc, 0);
-	else
-		ath5k_hw_reset_tsf(sc->ah);
-}
-
-static int
-ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb)
-{
-	unsigned long flags;
-	int ret;
-
-	ath5k_debug_dump_skb(sc, skb, "BC  ", 1);
-
-	spin_lock_irqsave(&sc->block, flags);
-	ath5k_txbuf_free(sc, sc->bbuf);
-	sc->bbuf->skb = skb;
-	ret = ath5k_beacon_setup(sc, sc->bbuf);
-	if (ret)
-		sc->bbuf->skb = NULL;
-	spin_unlock_irqrestore(&sc->block, flags);
-	if (!ret) {
-		ath5k_beacon_config(sc);
-		mmiowb();
-	}
-
-	return ret;
-}
-static void
-set_beacon_filter(struct ieee80211_hw *hw, bool enable)
-{
-	struct ath5k_softc *sc = hw->priv;
-	struct ath5k_hw *ah = sc->ah;
-	u32 rfilt;
-	rfilt = ath5k_hw_get_rx_filter(ah);
-	if (enable)
-		rfilt |= AR5K_RX_FILTER_BEACON;
-	else
-		rfilt &= ~AR5K_RX_FILTER_BEACON;
-	ath5k_hw_set_rx_filter(ah, rfilt);
-	sc->filter_flags = rfilt;
-}
-
-static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_bss_conf *bss_conf,
-				    u32 changes)
-{
-	struct ath5k_softc *sc = hw->priv;
-	if (changes & BSS_CHANGED_ASSOC) {
-		mutex_lock(&sc->lock);
-		sc->assoc = bss_conf->assoc;
-		if (sc->opmode == NL80211_IFTYPE_STATION)
-			set_beacon_filter(hw, sc->assoc);
-		mutex_unlock(&sc->lock);
-	}
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/base.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/base.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/base.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/base.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,190 +0,0 @@
-/*-
- * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
- *    redistribution must be conditioned upon including a substantially
- *    similar Disclaimer requirement for further binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
- *
- */
-
-/*
- * Defintions for the Atheros Wireless LAN controller driver.
- */
-#ifndef _DEV_ATH_ATHVAR_H
-#define _DEV_ATH_ATHVAR_H
-
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/wireless.h>
-#include <linux/if_ether.h>
-#include <linux/leds.h>
-
-#include "ath5k.h"
-#include "debug.h"
-
-#define	ATH_RXBUF	40		/* number of RX buffers */
-#define	ATH_TXBUF	200		/* number of TX buffers */
-#define ATH_BCBUF	1		/* number of beacon buffers */
-
-struct ath5k_buf {
-	struct list_head	list;
-	unsigned int		flags;	/* rx descriptor flags */
-	struct ath5k_desc	*desc;	/* virtual addr of desc */
-	dma_addr_t		daddr;	/* physical addr of desc */
-	struct sk_buff		*skb;	/* skbuff for buf */
-	dma_addr_t		skbaddr;/* physical addr of skb data */
-};
-
-/*
- * Data transmit queue state.  One of these exists for each
- * hardware transmit queue.  Packets sent to us from above
- * are assigned to queues based on their priority.  Not all
- * devices support a complete set of hardware transmit queues.
- * For those devices the array sc_ac2q will map multiple
- * priorities to fewer hardware queues (typically all to one
- * hardware queue).
- */
-struct ath5k_txq {
-	unsigned int		qnum;	/* hardware q number */
-	u32			*link;	/* link ptr in last TX desc */
-	struct list_head	q;	/* transmit queue */
-	spinlock_t		lock;	/* lock on q and link */
-	bool			setup;
-};
-
-#define ATH5K_LED_MAX_NAME_LEN 31
-
-/*
- * State for LED triggers
- */
-struct ath5k_led
-{
-	char name[ATH5K_LED_MAX_NAME_LEN + 1];	/* name of the LED in sysfs */
-	struct ath5k_softc *sc;			/* driver state */
-	struct led_classdev led_dev;		/* led classdev */
-};
-
-
-#if CHAN_DEBUG
-#define ATH_CHAN_MAX	(26+26+26+200+200)
-#else
-#define ATH_CHAN_MAX	(14+14+14+252+20)
-#endif
-
-/* Software Carrier, keeps track of the driver state
- * associated with an instance of a device */
-struct ath5k_softc {
-	struct pci_dev		*pdev;		/* for dma mapping */
-	void __iomem		*iobase;	/* address of the device */
-	struct mutex		lock;		/* dev-level lock */
-	/* FIXME: how many does it really need? */
-	struct ieee80211_tx_queue_stats tx_stats[16];
-	struct ieee80211_low_level_stats ll_stats;
-	struct ieee80211_hw	*hw;		/* IEEE 802.11 common */
-	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
-	struct ieee80211_channel channels[ATH_CHAN_MAX];
-	struct ieee80211_rate	rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
-	s8			rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
-	enum nl80211_iftype	opmode;
-	struct ath5k_hw		*ah;		/* Atheros HW */
-
-	struct ieee80211_supported_band		*curband;
-
-#ifdef CONFIG_ATH5K_DEBUG
-	struct ath5k_dbg_info	debug;		/* debug info */
-#endif /* CONFIG_ATH5K_DEBUG */
-
-	struct ath5k_buf	*bufptr;	/* allocated buffer ptr */
-	struct ath5k_desc	*desc;		/* TX/RX descriptors */
-	dma_addr_t		desc_daddr;	/* DMA (physical) address */
-	size_t			desc_len;	/* size of TX/RX descriptors */
-	u16			cachelsz;	/* cache line size */
-
-	DECLARE_BITMAP(status, 5);
-#define ATH_STAT_INVALID	0		/* disable hardware accesses */
-#define ATH_STAT_MRRETRY	1		/* multi-rate retry support */
-#define ATH_STAT_PROMISC	2
-#define ATH_STAT_LEDSOFT	3		/* enable LED gpio status */
-#define ATH_STAT_STARTED	4		/* opened & irqs enabled */
-
-	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
-	unsigned int		curmode;	/* current phy mode */
-	struct ieee80211_channel *curchan;	/* current h/w channel */
-
-	struct ieee80211_vif *vif;
-
-	enum ath5k_int		imask;		/* interrupt mask copy */
-
-	DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */
-
-	u8			bssidmask[ETH_ALEN];
-
-	unsigned int		led_pin,	/* GPIO pin for driving LED */
-				led_on;		/* pin setting for LED on */
-
-	struct tasklet_struct	restq;		/* reset tasklet */
-
-	unsigned int		rxbufsize;	/* rx size based on mtu */
-	struct list_head	rxbuf;		/* receive buffer */
-	spinlock_t		rxbuflock;
-	u32			*rxlink;	/* link ptr in last RX desc */
-	struct tasklet_struct	rxtq;		/* rx intr tasklet */
-	struct ath5k_led	rx_led;		/* rx led */
-
-	struct list_head	txbuf;		/* transmit buffer */
-	spinlock_t		txbuflock;
-	unsigned int		txbuf_len;	/* buf count in txbuf list */
-	struct ath5k_txq	txqs[2];	/* beacon and tx */
-
-	struct ath5k_txq	*txq;		/* beacon and tx*/
-	struct tasklet_struct	txtq;		/* tx intr tasklet */
-	struct ath5k_led	tx_led;		/* tx led */
-
-	spinlock_t		block;		/* protects beacon */
-	struct tasklet_struct	beacontq;	/* beacon intr tasklet */
-	struct ath5k_buf	*bbuf;		/* beacon buffer */
-	unsigned int		bhalq,		/* SW q for outgoing beacons */
-				bmisscount,	/* missed beacon transmits */
-				bintval,	/* beacon interval in TU */
-				bsent;
-	unsigned int		nexttbtt;	/* next beacon time in TU */
-
-	struct timer_list	calib_tim;	/* calibration timer */
-	int 			power_level;	/* Requested tx power in dbm */
-	bool			assoc;		/* assocate state */
-};
-
-#define ath5k_hw_hasbssidmask(_ah) \
-	(ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
-#define ath5k_hw_hasveol(_ah) \
-	(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/caps.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/caps.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/caps.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/caps.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/**************\
-* Capabilities *
-\**************/
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*
- * Fill the capabilities struct
- * TODO: Merge this with EEPROM code when we are done with it
- */
-int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
-{
-	u16 ee_header;
-
-	ATH5K_TRACE(ah->ah_sc);
-	/* Capabilities stored in the EEPROM */
-	ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
-
-	if (ah->ah_version == AR5K_AR5210) {
-		/*
-		 * Set radio capabilities
-		 * (The AR5110 only supports the middle 5GHz band)
-		 */
-		ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
-		ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
-		ah->ah_capabilities.cap_range.range_2ghz_min = 0;
-		ah->ah_capabilities.cap_range.range_2ghz_max = 0;
-
-		/* Set supported modes */
-		__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
-		__set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
-	} else {
-		/*
-		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
-		 * XXX and from 2312 to 2732GHz. There are problems with the
-		 * XXX current ieee80211 implementation because the IEEE
-		 * XXX channel mapping does not support negative channel
-		 * XXX numbers (2312MHz is channel -19). Of course, this
-		 * XXX doesn't matter because these channels are out of range
-		 * XXX but some regulation domains like MKK (Japan) will
-		 * XXX support frequencies somewhere around 4.8GHz.
-		 */
-
-		/*
-		 * Set radio capabilities
-		 */
-
-		if (AR5K_EEPROM_HDR_11A(ee_header)) {
-			/* 4920 */
-			ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
-			ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
-
-			/* Set supported modes */
-			__set_bit(AR5K_MODE_11A,
-					ah->ah_capabilities.cap_mode);
-			__set_bit(AR5K_MODE_11A_TURBO,
-					ah->ah_capabilities.cap_mode);
-			if (ah->ah_version == AR5K_AR5212)
-				__set_bit(AR5K_MODE_11G_TURBO,
-						ah->ah_capabilities.cap_mode);
-		}
-
-		/* Enable  802.11b if a 2GHz capable radio (2111/5112) is
-		 * connected */
-		if (AR5K_EEPROM_HDR_11B(ee_header) ||
-		    (AR5K_EEPROM_HDR_11G(ee_header) &&
-		     ah->ah_version != AR5K_AR5211)) {
-			/* 2312 */
-			ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
-			ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
-
-			if (AR5K_EEPROM_HDR_11B(ee_header))
-				__set_bit(AR5K_MODE_11B,
-						ah->ah_capabilities.cap_mode);
-
-			if (AR5K_EEPROM_HDR_11G(ee_header) &&
-			    ah->ah_version != AR5K_AR5211)
-				__set_bit(AR5K_MODE_11G,
-						ah->ah_capabilities.cap_mode);
-		}
-	}
-
-	/* GPIO */
-	ah->ah_gpio_npins = AR5K_NUM_GPIO;
-
-	/* Set number of supported TX queues */
-	if (ah->ah_version == AR5K_AR5210)
-		ah->ah_capabilities.cap_queues.q_tx_num =
-			AR5K_NUM_TX_QUEUES_NOQCU;
-	else
-		ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
-
-	return 0;
-}
-
-/* Main function used by the driver part to check caps */
-int ath5k_hw_get_capability(struct ath5k_hw *ah,
-		enum ath5k_capability_type cap_type,
-		u32 capability, u32 *result)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	switch (cap_type) {
-	case AR5K_CAP_NUM_TXQUEUES:
-		if (result) {
-			if (ah->ah_version == AR5K_AR5210)
-				*result = AR5K_NUM_TX_QUEUES_NOQCU;
-			else
-				*result = AR5K_NUM_TX_QUEUES;
-			goto yes;
-		}
-	case AR5K_CAP_VEOL:
-		goto yes;
-	case AR5K_CAP_COMPRESSION:
-		if (ah->ah_version == AR5K_AR5212)
-			goto yes;
-		else
-			goto no;
-	case AR5K_CAP_BURST:
-		goto yes;
-	case AR5K_CAP_TPC:
-		goto yes;
-	case AR5K_CAP_BSSIDMASK:
-		if (ah->ah_version == AR5K_AR5212)
-			goto yes;
-		else
-			goto no;
-	case AR5K_CAP_XR:
-		if (ah->ah_version == AR5K_AR5212)
-			goto yes;
-		else
-			goto no;
-	default:
-		goto no;
-	}
-
-no:
-	return -EINVAL;
-yes:
-	return 0;
-}
-
-/*
- * TODO: Following functions should be part of a new function
- * set_capability
- */
-
-int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
-		u16 assoc_id)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	if (ah->ah_version == AR5K_AR5210) {
-		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
-			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
-		return 0;
-	}
-
-	return -EIO;
-}
-
-int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	if (ah->ah_version == AR5K_AR5210) {
-		AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
-			AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
-		return 0;
-	}
-
-	return -EIO;
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/debug.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/debug.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/debug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/debug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,538 +0,0 @@
-/*
- * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com>
- *
- *  This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
- *
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
- * Copyright (c) 2004-2005 Atheros Communications, Inc.
- * Copyright (c) 2006 Devicescape Software, Inc.
- * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
- * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
- *    redistribution must be conditioned upon including a substantially
- *    similar Disclaimer requirement for further binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
- */
-
-#include "base.h"
-#include "debug.h"
-
-static unsigned int ath5k_debug;
-module_param_named(debug, ath5k_debug, uint, 0);
-
-
-#ifdef CONFIG_ATH5K_DEBUG
-
-#include <linux/seq_file.h>
-#include "reg.h"
-
-static struct dentry *ath5k_global_debugfs;
-
-static int ath5k_debugfs_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-
-/* debugfs: registers */
-
-struct reg {
-	const char *name;
-	int addr;
-};
-
-#define REG_STRUCT_INIT(r) { #r, r }
-
-/* just a few random registers, might want to add more */
-static const struct reg regs[] = {
-	REG_STRUCT_INIT(AR5K_CR),
-	REG_STRUCT_INIT(AR5K_RXDP),
-	REG_STRUCT_INIT(AR5K_CFG),
-	REG_STRUCT_INIT(AR5K_IER),
-	REG_STRUCT_INIT(AR5K_BCR),
-	REG_STRUCT_INIT(AR5K_RTSD0),
-	REG_STRUCT_INIT(AR5K_RTSD1),
-	REG_STRUCT_INIT(AR5K_TXCFG),
-	REG_STRUCT_INIT(AR5K_RXCFG),
-	REG_STRUCT_INIT(AR5K_RXJLA),
-	REG_STRUCT_INIT(AR5K_MIBC),
-	REG_STRUCT_INIT(AR5K_TOPS),
-	REG_STRUCT_INIT(AR5K_RXNOFRM),
-	REG_STRUCT_INIT(AR5K_TXNOFRM),
-	REG_STRUCT_INIT(AR5K_RPGTO),
-	REG_STRUCT_INIT(AR5K_RFCNT),
-	REG_STRUCT_INIT(AR5K_MISC),
-	REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
-	REG_STRUCT_INIT(AR5K_ISR),
-	REG_STRUCT_INIT(AR5K_PISR),
-	REG_STRUCT_INIT(AR5K_SISR0),
-	REG_STRUCT_INIT(AR5K_SISR1),
-	REG_STRUCT_INIT(AR5K_SISR2),
-	REG_STRUCT_INIT(AR5K_SISR3),
-	REG_STRUCT_INIT(AR5K_SISR4),
-	REG_STRUCT_INIT(AR5K_IMR),
-	REG_STRUCT_INIT(AR5K_PIMR),
-	REG_STRUCT_INIT(AR5K_SIMR0),
-	REG_STRUCT_INIT(AR5K_SIMR1),
-	REG_STRUCT_INIT(AR5K_SIMR2),
-	REG_STRUCT_INIT(AR5K_SIMR3),
-	REG_STRUCT_INIT(AR5K_SIMR4),
-	REG_STRUCT_INIT(AR5K_DCM_ADDR),
-	REG_STRUCT_INIT(AR5K_DCCFG),
-	REG_STRUCT_INIT(AR5K_CCFG),
-	REG_STRUCT_INIT(AR5K_CPC0),
-	REG_STRUCT_INIT(AR5K_CPC1),
-	REG_STRUCT_INIT(AR5K_CPC2),
-	REG_STRUCT_INIT(AR5K_CPC3),
-	REG_STRUCT_INIT(AR5K_CPCOVF),
-	REG_STRUCT_INIT(AR5K_RESET_CTL),
-	REG_STRUCT_INIT(AR5K_SLEEP_CTL),
-	REG_STRUCT_INIT(AR5K_INTPEND),
-	REG_STRUCT_INIT(AR5K_SFR),
-	REG_STRUCT_INIT(AR5K_PCICFG),
-	REG_STRUCT_INIT(AR5K_GPIOCR),
-	REG_STRUCT_INIT(AR5K_GPIODO),
-	REG_STRUCT_INIT(AR5K_SREV),
-};
-
-static void *reg_start(struct seq_file *seq, loff_t *pos)
-{
-	return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
-}
-
-static void reg_stop(struct seq_file *seq, void *p)
-{
-	/* nothing to do */
-}
-
-static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
-{
-	++*pos;
-	return *pos < ARRAY_SIZE(regs) ? (void *)&regs[*pos] : NULL;
-}
-
-static int reg_show(struct seq_file *seq, void *p)
-{
-	struct ath5k_softc *sc = seq->private;
-	struct reg *r = p;
-	seq_printf(seq, "%-25s0x%08x\n", r->name,
-		ath5k_hw_reg_read(sc->ah, r->addr));
-	return 0;
-}
-
-static const struct seq_operations register_seq_ops = {
-	.start = reg_start,
-	.next  = reg_next,
-	.stop  = reg_stop,
-	.show  = reg_show
-};
-
-static int open_file_registers(struct inode *inode, struct file *file)
-{
-	struct seq_file *s;
-	int res;
-	res = seq_open(file, &register_seq_ops);
-	if (res == 0) {
-		s = file->private_data;
-		s->private = inode->i_private;
-	}
-	return res;
-}
-
-static const struct file_operations fops_registers = {
-	.open = open_file_registers,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-	.owner = THIS_MODULE,
-};
-
-
-/* debugfs: beacons */
-
-static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
-				   size_t count, loff_t *ppos)
-{
-	struct ath5k_softc *sc = file->private_data;
-	struct ath5k_hw *ah = sc->ah;
-	char buf[500];
-	unsigned int len = 0;
-	unsigned int v;
-	u64 tsf;
-
-	v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
-	len += snprintf(buf+len, sizeof(buf)-len,
-		"%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
-		"AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
-		(v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
-
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
-		"AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
-
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
-		"AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
-
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
-		"AR5K_TIMER0 (TBTT)", v, v);
-
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
-		"AR5K_TIMER1 (DMA)", v, v >> 3);
-
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
-		"AR5K_TIMER2 (SWBA)", v, v >> 3);
-
-	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
-	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
-		"AR5K_TIMER3 (ATIM)", v, v);
-
-	tsf = ath5k_hw_get_tsf64(sc->ah);
-	len += snprintf(buf+len, sizeof(buf)-len,
-		"TSF\t\t0x%016llx\tTU: %08x\n",
-		(unsigned long long)tsf, TSF_TO_TU(tsf));
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_beacon(struct file *file,
-				 const char __user *userbuf,
-				 size_t count, loff_t *ppos)
-{
-	struct ath5k_softc *sc = file->private_data;
-	struct ath5k_hw *ah = sc->ah;
-	char buf[20];
-
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
-		return -EFAULT;
-
-	if (strncmp(buf, "disable", 7) == 0) {
-		AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
-		printk(KERN_INFO "debugfs disable beacons\n");
-	} else if (strncmp(buf, "enable", 6) == 0) {
-		AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
-		printk(KERN_INFO "debugfs enable beacons\n");
-	}
-	return count;
-}
-
-static const struct file_operations fops_beacon = {
-	.read = read_file_beacon,
-	.write = write_file_beacon,
-	.open = ath5k_debugfs_open,
-	.owner = THIS_MODULE,
-};
-
-
-/* debugfs: reset */
-
-static ssize_t write_file_reset(struct file *file,
-				 const char __user *userbuf,
-				 size_t count, loff_t *ppos)
-{
-	struct ath5k_softc *sc = file->private_data;
-	tasklet_schedule(&sc->restq);
-	return count;
-}
-
-static const struct file_operations fops_reset = {
-	.write = write_file_reset,
-	.open = ath5k_debugfs_open,
-	.owner = THIS_MODULE,
-};
-
-
-/* debugfs: debug level */
-
-static const struct {
-	enum ath5k_debug_level level;
-	const char *name;
-	const char *desc;
-} dbg_info[] = {
-	{ ATH5K_DEBUG_RESET,	"reset",	"reset and initialization" },
-	{ ATH5K_DEBUG_INTR,	"intr",		"interrupt handling" },
-	{ ATH5K_DEBUG_MODE,	"mode",		"mode init/setup" },
-	{ ATH5K_DEBUG_XMIT,	"xmit",		"basic xmit operation" },
-	{ ATH5K_DEBUG_BEACON,	"beacon",	"beacon handling" },
-	{ ATH5K_DEBUG_CALIBRATE, "calib",	"periodic calibration" },
-	{ ATH5K_DEBUG_TXPOWER,	"txpower",	"transmit power setting" },
-	{ ATH5K_DEBUG_LED,	"led",		"LED management" },
-	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
-	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
-	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
-	{ ATH5K_DEBUG_TRACE,	"trace",	"trace function calls" },
-	{ ATH5K_DEBUG_ANY,	"all",		"show all debug levels" },
-};
-
-static ssize_t read_file_debug(struct file *file, char __user *user_buf,
-				   size_t count, loff_t *ppos)
-{
-	struct ath5k_softc *sc = file->private_data;
-	char buf[700];
-	unsigned int len = 0;
-	unsigned int i;
-
-	len += snprintf(buf+len, sizeof(buf)-len,
-		"DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);
-
-	for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
-		len += snprintf(buf+len, sizeof(buf)-len,
-			"%10s %c 0x%08x - %s\n", dbg_info[i].name,
-			sc->debug.level & dbg_info[i].level ? '+' : ' ',
-			dbg_info[i].level, dbg_info[i].desc);
-	}
-	len += snprintf(buf+len, sizeof(buf)-len,
-		"%10s %c 0x%08x - %s\n", dbg_info[i].name,
-		sc->debug.level == dbg_info[i].level ? '+' : ' ',
-		dbg_info[i].level, dbg_info[i].desc);
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_debug(struct file *file,
-				 const char __user *userbuf,
-				 size_t count, loff_t *ppos)
-{
-	struct ath5k_softc *sc = file->private_data;
-	unsigned int i;
-	char buf[20];
-
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
-		return -EFAULT;
-
-	for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
-		if (strncmp(buf, dbg_info[i].name,
-					strlen(dbg_info[i].name)) == 0) {
-			sc->debug.level ^= dbg_info[i].level; /* toggle bit */
-			break;
-		}
-	}
-	return count;
-}
-
-static const struct file_operations fops_debug = {
-	.read = read_file_debug,
-	.write = write_file_debug,
-	.open = ath5k_debugfs_open,
-	.owner = THIS_MODULE,
-};
-
-
-/* init */
-
-void
-ath5k_debug_init(void)
-{
-	ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
-}
-
-void
-ath5k_debug_init_device(struct ath5k_softc *sc)
-{
-	sc->debug.level = ath5k_debug;
-
-	sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
-				ath5k_global_debugfs);
-
-	sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO,
-				sc->debug.debugfs_phydir, sc, &fops_debug);
-
-	sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
-				sc->debug.debugfs_phydir, sc, &fops_registers);
-
-	sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
-				sc->debug.debugfs_phydir, sc, &fops_beacon);
-
-	sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
-				sc->debug.debugfs_phydir, sc, &fops_reset);
-}
-
-void
-ath5k_debug_finish(void)
-{
-	debugfs_remove(ath5k_global_debugfs);
-}
-
-void
-ath5k_debug_finish_device(struct ath5k_softc *sc)
-{
-	debugfs_remove(sc->debug.debugfs_debug);
-	debugfs_remove(sc->debug.debugfs_registers);
-	debugfs_remove(sc->debug.debugfs_beacon);
-	debugfs_remove(sc->debug.debugfs_reset);
-	debugfs_remove(sc->debug.debugfs_phydir);
-}
-
-
-/* functions used in other places */
-
-void
-ath5k_debug_dump_bands(struct ath5k_softc *sc)
-{
-	unsigned int b, i;
-
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
-		return;
-
-	BUG_ON(!sc->sbands);
-
-	for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
-		struct ieee80211_supported_band *band = &sc->sbands[b];
-		char bname[6];
-		switch (band->band) {
-		case IEEE80211_BAND_2GHZ:
-			strcpy(bname, "2 GHz");
-			break;
-		case IEEE80211_BAND_5GHZ:
-			strcpy(bname, "5 GHz");
-			break;
-		default:
-			printk(KERN_DEBUG "Band not supported: %d\n",
-				band->band);
-			return;
-		}
-		printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
-				band->n_channels, band->n_bitrates);
-		printk(KERN_DEBUG " channels:\n");
-		for (i = 0; i < band->n_channels; i++)
-			printk(KERN_DEBUG "  %3d %d %.4x %.4x\n",
-					ieee80211_frequency_to_channel(
-						band->channels[i].center_freq),
-					band->channels[i].center_freq,
-					band->channels[i].hw_value,
-					band->channels[i].flags);
-		printk(KERN_DEBUG " rates:\n");
-		for (i = 0; i < band->n_bitrates; i++)
-			printk(KERN_DEBUG "  %4d %.4x %.4x %.4x\n",
-					band->bitrates[i].bitrate,
-					band->bitrates[i].hw_value,
-					band->bitrates[i].flags,
-					band->bitrates[i].hw_value_short);
-	}
-}
-
-static inline void
-ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
-		       struct ath5k_rx_status *rs)
-{
-	struct ath5k_desc *ds = bf->desc;
-	struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
-
-	printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
-		ds, (unsigned long long)bf->daddr,
-		ds->ds_link, ds->ds_data,
-		rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
-		rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
-		!done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
-}
-
-void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
-{
-	struct ath5k_desc *ds;
-	struct ath5k_buf *bf;
-	struct ath5k_rx_status rs = {};
-	int status;
-
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
-		return;
-
-	printk(KERN_DEBUG "rx queue %x, link %p\n",
-		ath5k_hw_get_rxdp(ah), sc->rxlink);
-
-	spin_lock_bh(&sc->rxbuflock);
-	list_for_each_entry(bf, &sc->rxbuf, list) {
-		ds = bf->desc;
-		status = ah->ah_proc_rx_desc(ah, ds, &rs);
-		if (!status)
-			ath5k_debug_printrxbuf(bf, status == 0, &rs);
-	}
-	spin_unlock_bh(&sc->rxbuflock);
-}
-
-void
-ath5k_debug_dump_skb(struct ath5k_softc *sc,
-			struct sk_buff *skb, const char *prefix, int tx)
-{
-	char buf[16];
-
-	if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) ||
-		     (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX)))))
-		return;
-
-	snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix);
-
-	print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data,
-		min(200U, skb->len));
-
-	printk(KERN_DEBUG "\n");
-}
-
-void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
-{
-	struct ath5k_desc *ds = bf->desc;
-	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
-	struct ath5k_tx_status ts = {};
-	int done;
-
-	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
-		return;
-
-	done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
-
-	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
-		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
-		ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
-		td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
-		td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
-		done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
-}
-
-#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/debug.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/debug.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/debug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/debug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
- *
- *  This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
- *
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
- * Copyright (c) 2004-2005 Atheros Communications, Inc.
- * Copyright (c) 2006 Devicescape Software, Inc.
- * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
- * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
- *    redistribution must be conditioned upon including a substantially
- *    similar Disclaimer requirement for further binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
- */
-
-#ifndef _ATH5K_DEBUG_H
-#define _ATH5K_DEBUG_H
-
-struct ath5k_softc;
-struct ath5k_hw;
-struct sk_buff;
-struct ath5k_buf;
-
-struct ath5k_dbg_info {
-	unsigned int		level;		/* debug level */
-	/* debugfs entries */
-	struct dentry		*debugfs_phydir;
-	struct dentry		*debugfs_debug;
-	struct dentry		*debugfs_registers;
-	struct dentry		*debugfs_beacon;
-	struct dentry		*debugfs_reset;
-};
-
-/**
- * enum ath5k_debug_level - ath5k debug level
- *
- * @ATH5K_DEBUG_RESET: reset processing
- * @ATH5K_DEBUG_INTR: interrupt handling
- * @ATH5K_DEBUG_MODE: mode init/setup
- * @ATH5K_DEBUG_XMIT: basic xmit operation
- * @ATH5K_DEBUG_BEACON: beacon handling
- * @ATH5K_DEBUG_CALIBRATE: periodic calibration
- * @ATH5K_DEBUG_TXPOWER: transmit power setting
- * @ATH5K_DEBUG_LED: led management
- * @ATH5K_DEBUG_DUMP_RX: print received skb content
- * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
- * @ATH5K_DEBUG_DUMPBANDS: dump bands
- * @ATH5K_DEBUG_TRACE: trace function calls
- * @ATH5K_DEBUG_ANY: show at any debug level
- *
- * The debug level is used to control the amount and type of debugging output
- * we want to see. The debug level is given in calls to ATH5K_DBG to specify
- * where the message should appear, and the user can control the debugging
- * messages he wants to see, either by the module parameter 'debug' on module
- * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can
- * be combined together by bitwise OR.
- */
-enum ath5k_debug_level {
-	ATH5K_DEBUG_RESET	= 0x00000001,
-	ATH5K_DEBUG_INTR	= 0x00000002,
-	ATH5K_DEBUG_MODE	= 0x00000004,
-	ATH5K_DEBUG_XMIT	= 0x00000008,
-	ATH5K_DEBUG_BEACON	= 0x00000010,
-	ATH5K_DEBUG_CALIBRATE	= 0x00000020,
-	ATH5K_DEBUG_TXPOWER	= 0x00000040,
-	ATH5K_DEBUG_LED		= 0x00000080,
-	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
-	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
-	ATH5K_DEBUG_DUMPBANDS	= 0x00000400,
-	ATH5K_DEBUG_TRACE	= 0x00001000,
-	ATH5K_DEBUG_ANY		= 0xffffffff
-};
-
-#ifdef CONFIG_ATH5K_DEBUG
-
-#define ATH5K_TRACE(_sc) do { \
-	if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
-		printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \
-	} while (0)
-
-#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \
-	if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \
-		ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
-			__func__, __LINE__, ##__VA_ARGS__); \
-	} while (0)
-
-#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \
-	if (unlikely((_sc)->debug.level & (_m))) \
-		ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
-			__func__, __LINE__, ##__VA_ARGS__); \
-	} while (0)
-
-void
-ath5k_debug_init(void);
-
-void
-ath5k_debug_init_device(struct ath5k_softc *sc);
-
-void
-ath5k_debug_finish(void);
-
-void
-ath5k_debug_finish_device(struct ath5k_softc *sc);
-
-void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
-
-void
-ath5k_debug_dump_bands(struct ath5k_softc *sc);
-
-void
-ath5k_debug_dump_skb(struct ath5k_softc *sc,
-			struct sk_buff *skb, const char *prefix, int tx);
-
-void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
-
-#else /* no debugging */
-
-#include <linux/compiler.h>
-
-#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
-
-static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
-
-static inline void __attribute__ ((format (printf, 3, 4)))
-ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
-{}
-
-static inline void
-ath5k_debug_init(void) {}
-
-static inline void
-ath5k_debug_init_device(struct ath5k_softc *sc) {}
-
-static inline void
-ath5k_debug_finish(void) {}
-
-static inline void
-ath5k_debug_finish_device(struct ath5k_softc *sc) {}
-
-static inline void
-ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
-
-static inline void
-ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
-
-static inline void
-ath5k_debug_dump_skb(struct ath5k_softc *sc,
-			struct sk_buff *skb, const char *prefix, int tx) {}
-
-static inline void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
-
-#endif /* ifdef CONFIG_ATH5K_DEBUG */
-
-#endif /* ifndef _ATH5K_DEBUG_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/desc.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/desc.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/desc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/desc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,696 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/******************************\
- Hardware Descriptor Functions
-\******************************/
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*
- * TX Descriptors
- */
-
-/*
- * Initialize the 2-word tx control descriptor on 5210/5211
- */
-static int
-ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
-	unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
-	unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
-	unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
-	unsigned int rtscts_rate, unsigned int rtscts_duration)
-{
-	u32 frame_type;
-	struct ath5k_hw_2w_tx_ctl *tx_ctl;
-	unsigned int frame_len;
-
-	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
-
-	/*
-	 * Validate input
-	 * - Zero retries don't make sense.
-	 * - A zero rate will put the HW into a mode where it continously sends
-	 *   noise on the channel, so it is important to avoid this.
-	 */
-	if (unlikely(tx_tries0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero retries\n");
-		WARN_ON(1);
-		return -EINVAL;
-	}
-	if (unlikely(tx_rate0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero rate\n");
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	/* Clear descriptor */
-	memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
-
-	/* Setup control descriptor */
-
-	/* Verify and set frame length */
-
-	/* remove padding we might have added before */
-	frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
-
-	if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
-		return -EINVAL;
-
-	tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
-
-	/* Verify and set buffer length */
-
-	/* NB: beacon's BufLen must be a multiple of 4 bytes */
-	if (type == AR5K_PKT_TYPE_BEACON)
-		pkt_len = roundup(pkt_len, 4);
-
-	if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
-		return -EINVAL;
-
-	tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
-
-	/*
-	 * Verify and set header length
-	 * XXX: I only found that on 5210 code, does it work on 5211 ?
-	 */
-	if (ah->ah_version == AR5K_AR5210) {
-		if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
-			return -EINVAL;
-		tx_ctl->tx_control_0 |=
-			AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
-	}
-
-	/*Diferences between 5210-5211*/
-	if (ah->ah_version == AR5K_AR5210) {
-		switch (type) {
-		case AR5K_PKT_TYPE_BEACON:
-		case AR5K_PKT_TYPE_PROBE_RESP:
-			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
-		case AR5K_PKT_TYPE_PIFS:
-			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
-		default:
-			frame_type = type /*<< 2 ?*/;
-		}
-
-		tx_ctl->tx_control_0 |=
-		AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
-		AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
-
-	} else {
-		tx_ctl->tx_control_0 |=
-			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
-			AR5K_REG_SM(antenna_mode,
-				AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
-		tx_ctl->tx_control_1 |=
-			AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
-	}
-#define _TX_FLAGS(_c, _flag)					\
-	if (flags & AR5K_TXDESC_##_flag) {			\
-		tx_ctl->tx_control_##_c |=			\
-			AR5K_2W_TX_DESC_CTL##_c##_##_flag;	\
-	}
-
-	_TX_FLAGS(0, CLRDMASK);
-	_TX_FLAGS(0, VEOL);
-	_TX_FLAGS(0, INTREQ);
-	_TX_FLAGS(0, RTSENA);
-	_TX_FLAGS(1, NOACK);
-
-#undef _TX_FLAGS
-
-	/*
-	 * WEP crap
-	 */
-	if (key_index != AR5K_TXKEYIX_INVALID) {
-		tx_ctl->tx_control_0 |=
-			AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-		tx_ctl->tx_control_1 |=
-			AR5K_REG_SM(key_index,
-			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
-	}
-
-	/*
-	 * RTS/CTS Duration [5210 ?]
-	 */
-	if ((ah->ah_version == AR5K_AR5210) &&
-			(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
-		tx_ctl->tx_control_1 |= rtscts_duration &
-				AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
-
-	return 0;
-}
-
-/*
- * Initialize the 4-word tx control descriptor on 5212
- */
-static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
-	struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
-	enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
-	unsigned int tx_tries0, unsigned int key_index,
-	unsigned int antenna_mode, unsigned int flags,
-	unsigned int rtscts_rate,
-	unsigned int rtscts_duration)
-{
-	struct ath5k_hw_4w_tx_ctl *tx_ctl;
-	unsigned int frame_len;
-
-	ATH5K_TRACE(ah->ah_sc);
-	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-
-	/*
-	 * Validate input
-	 * - Zero retries don't make sense.
-	 * - A zero rate will put the HW into a mode where it continously sends
-	 *   noise on the channel, so it is important to avoid this.
-	 */
-	if (unlikely(tx_tries0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero retries\n");
-		WARN_ON(1);
-		return -EINVAL;
-	}
-	if (unlikely(tx_rate0 == 0)) {
-		ATH5K_ERR(ah->ah_sc, "zero rate\n");
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	tx_power += ah->ah_txpower.txp_offset;
-	if (tx_power > AR5K_TUNE_MAX_TXPOWER)
-		tx_power = AR5K_TUNE_MAX_TXPOWER;
-
-	/* Clear descriptor */
-	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
-
-	/* Setup control descriptor */
-
-	/* Verify and set frame length */
-
-	/* remove padding we might have added before */
-	frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
-
-	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
-		return -EINVAL;
-
-	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
-
-	/* Verify and set buffer length */
-
-	/* NB: beacon's BufLen must be a multiple of 4 bytes */
-	if (type == AR5K_PKT_TYPE_BEACON)
-		pkt_len = roundup(pkt_len, 4);
-
-	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
-		return -EINVAL;
-
-	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
-
-	tx_ctl->tx_control_0 |=
-		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
-		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
-	tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
-					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
-	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
-					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
-	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
-
-#define _TX_FLAGS(_c, _flag)					\
-	if (flags & AR5K_TXDESC_##_flag) {			\
-		tx_ctl->tx_control_##_c |=			\
-			AR5K_4W_TX_DESC_CTL##_c##_##_flag;	\
-	}
-
-	_TX_FLAGS(0, CLRDMASK);
-	_TX_FLAGS(0, VEOL);
-	_TX_FLAGS(0, INTREQ);
-	_TX_FLAGS(0, RTSENA);
-	_TX_FLAGS(0, CTSENA);
-	_TX_FLAGS(1, NOACK);
-
-#undef _TX_FLAGS
-
-	/*
-	 * WEP crap
-	 */
-	if (key_index != AR5K_TXKEYIX_INVALID) {
-		tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-		tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
-				AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
-	}
-
-	/*
-	 * RTS/CTS
-	 */
-	if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
-		if ((flags & AR5K_TXDESC_RTSENA) &&
-				(flags & AR5K_TXDESC_CTSENA))
-			return -EINVAL;
-		tx_ctl->tx_control_2 |= rtscts_duration &
-				AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
-		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
-				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
-	}
-
-	return 0;
-}
-
-/*
- * Initialize a 4-word multi rate retry tx control descriptor on 5212
- */
-static int
-ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
-	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
-	u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
-{
-	struct ath5k_hw_4w_tx_ctl *tx_ctl;
-
-	/*
-	 * Rates can be 0 as long as the retry count is 0 too.
-	 * A zero rate and nonzero retry count will put the HW into a mode where
-	 * it continously sends noise on the channel, so it is important to
-	 * avoid this.
-	 */
-	if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
-		     (tx_rate2 == 0 && tx_tries2 != 0) ||
-		     (tx_rate3 == 0 && tx_tries3 != 0))) {
-		ATH5K_ERR(ah->ah_sc, "zero rate\n");
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	if (ah->ah_version == AR5K_AR5212) {
-		tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-
-#define _XTX_TRIES(_n)							\
-	if (tx_tries##_n) {						\
-		tx_ctl->tx_control_2 |=					\
-		    AR5K_REG_SM(tx_tries##_n,				\
-		    AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n);		\
-		tx_ctl->tx_control_3 |=					\
-		    AR5K_REG_SM(tx_rate##_n,				\
-		    AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n);		\
-	}
-
-		_XTX_TRIES(1);
-		_XTX_TRIES(2);
-		_XTX_TRIES(3);
-
-#undef _XTX_TRIES
-
-		return 1;
-	}
-
-	return 0;
-}
-
-/* no mrr support for cards older than 5212 */
-static int
-ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc,
-	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
-	u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
-{
-	return 0;
-}
-
-/*
- * Proccess the tx status descriptor on 5210/5211
- */
-static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
-{
-	struct ath5k_hw_2w_tx_ctl *tx_ctl;
-	struct ath5k_hw_tx_status *tx_status;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
-	tx_status = &desc->ud.ds_tx5210.tx_stat;
-
-	/* No frame has been send or error */
-	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
-		return -EINPROGRESS;
-
-	/*
-	 * Get descriptor status
-	 */
-	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
-		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
-	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
-		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
-		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
-	/*TODO: ts->ts_virtcol + test*/
-	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
-		AR5K_DESC_TX_STATUS1_SEQ_NUM);
-	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
-		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
-	ts->ts_antenna = 1;
-	ts->ts_status = 0;
-	ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
-		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
-	ts->ts_retry[0] = ts->ts_longretry;
-	ts->ts_final_idx = 0;
-
-	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
-		if (tx_status->tx_status_0 &
-				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
-			ts->ts_status |= AR5K_TXERR_XRETRY;
-
-		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
-			ts->ts_status |= AR5K_TXERR_FIFO;
-
-		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
-			ts->ts_status |= AR5K_TXERR_FILT;
-	}
-
-	return 0;
-}
-
-/*
- * Proccess a tx status descriptor on 5212
- */
-static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
-{
-	struct ath5k_hw_4w_tx_ctl *tx_ctl;
-	struct ath5k_hw_tx_status *tx_status;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-	tx_status = &desc->ud.ds_tx5212.tx_stat;
-
-	/* No frame has been send or error */
-	if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
-		return -EINPROGRESS;
-
-	/*
-	 * Get descriptor status
-	 */
-	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
-		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
-	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
-		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
-		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
-	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
-		AR5K_DESC_TX_STATUS1_SEQ_NUM);
-	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
-		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
-	ts->ts_antenna = (tx_status->tx_status_1 &
-		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
-	ts->ts_status = 0;
-
-	ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
-			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
-
-	/* The longretry counter has the number of un-acked retries
-	 * for the final rate. To get the total number of retries
-	 * we have to add the retry counters for the other rates
-	 * as well
-	 */
-	ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
-	switch (ts->ts_final_idx) {
-	case 3:
-		ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
-			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
-
-		ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
-			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
-		ts->ts_longretry += ts->ts_retry[2];
-		/* fall through */
-	case 2:
-		ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
-			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
-
-		ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
-			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
-		ts->ts_longretry += ts->ts_retry[1];
-		/* fall through */
-	case 1:
-		ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
-			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
-
-		ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
-			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
-		ts->ts_longretry += ts->ts_retry[0];
-		/* fall through */
-	case 0:
-		ts->ts_rate[0] = tx_ctl->tx_control_3 &
-			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
-		break;
-	}
-
-	/* TX error */
-	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
-		if (tx_status->tx_status_0 &
-				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
-			ts->ts_status |= AR5K_TXERR_XRETRY;
-
-		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
-			ts->ts_status |= AR5K_TXERR_FIFO;
-
-		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
-			ts->ts_status |= AR5K_TXERR_FILT;
-	}
-
-	return 0;
-}
-
-/*
- * RX Descriptors
- */
-
-/*
- * Initialize an rx control descriptor
- */
-static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
-			u32 size, unsigned int flags)
-{
-	struct ath5k_hw_rx_ctl *rx_ctl;
-
-	ATH5K_TRACE(ah->ah_sc);
-	rx_ctl = &desc->ud.ds_rx.rx_ctl;
-
-	/*
-	 * Clear the descriptor
-	 * If we don't clean the status descriptor,
-	 * while scanning we get too many results,
-	 * most of them virtual, after some secs
-	 * of scanning system hangs. M.F.
-	*/
-	memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
-
-	/* Setup descriptor */
-	rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
-	if (unlikely(rx_ctl->rx_control_1 != size))
-		return -EINVAL;
-
-	if (flags & AR5K_RXDESC_INTREQ)
-		rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
-
-	return 0;
-}
-
-/*
- * Proccess the rx status descriptor on 5210/5211
- */
-static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
-{
-	struct ath5k_hw_rx_status *rx_status;
-
-	rx_status = &desc->ud.ds_rx.u.rx_stat;
-
-	/* No frame received / not ready */
-	if (unlikely(!(rx_status->rx_status_1 &
-	AR5K_5210_RX_DESC_STATUS1_DONE)))
-		return -EINPROGRESS;
-
-	/*
-	 * Frame receive status
-	 */
-	rs->rs_datalen = rx_status->rx_status_0 &
-		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
-	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
-	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
-	rs->rs_more = !!(rx_status->rx_status_0 &
-		AR5K_5210_RX_DESC_STATUS0_MORE);
-	/* TODO: this timestamp is 13 bit, later on we assume 15 bit */
-	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-	rs->rs_status = 0;
-	rs->rs_phyerr = 0;
-
-	/*
-	 * Key table status
-	 */
-	if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
-		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-			AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
-	else
-		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
-
-	/*
-	 * Receive/descriptor errors
-	 */
-	if (!(rx_status->rx_status_1 &
-	AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
-		if (rx_status->rx_status_1 &
-				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
-			rs->rs_status |= AR5K_RXERR_CRC;
-
-		if (rx_status->rx_status_1 &
-				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
-			rs->rs_status |= AR5K_RXERR_FIFO;
-
-		if (rx_status->rx_status_1 &
-				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
-			rs->rs_status |= AR5K_RXERR_PHY;
-			rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
-				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
-		}
-
-		if (rx_status->rx_status_1 &
-				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-			rs->rs_status |= AR5K_RXERR_DECRYPT;
-	}
-
-	return 0;
-}
-
-/*
- * Proccess the rx status descriptor on 5212
- */
-static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
-{
-	struct ath5k_hw_rx_status *rx_status;
-	struct ath5k_hw_rx_error *rx_err;
-
-	ATH5K_TRACE(ah->ah_sc);
-	rx_status = &desc->ud.ds_rx.u.rx_stat;
-
-	/* Overlay on error */
-	rx_err = &desc->ud.ds_rx.u.rx_err;
-
-	/* No frame received / not ready */
-	if (unlikely(!(rx_status->rx_status_1 &
-	AR5K_5212_RX_DESC_STATUS1_DONE)))
-		return -EINPROGRESS;
-
-	/*
-	 * Frame receive status
-	 */
-	rs->rs_datalen = rx_status->rx_status_0 &
-		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
-	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
-	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
-	rs->rs_more = !!(rx_status->rx_status_0 &
-		AR5K_5212_RX_DESC_STATUS0_MORE);
-	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-	rs->rs_status = 0;
-	rs->rs_phyerr = 0;
-
-	/*
-	 * Key table status
-	 */
-	if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
-		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-				AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
-	else
-		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
-
-	/*
-	 * Receive/descriptor errors
-	 */
-	if (!(rx_status->rx_status_1 &
-	AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
-		if (rx_status->rx_status_1 &
-				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
-			rs->rs_status |= AR5K_RXERR_CRC;
-
-		if (rx_status->rx_status_1 &
-				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
-			rs->rs_status |= AR5K_RXERR_PHY;
-			rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
-					   AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
-		}
-
-		if (rx_status->rx_status_1 &
-				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-			rs->rs_status |= AR5K_RXERR_DECRYPT;
-
-		if (rx_status->rx_status_1 &
-				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
-			rs->rs_status |= AR5K_RXERR_MIC;
-	}
-
-	return 0;
-}
-
-/*
- * Init function pointers inside ath5k_hw struct
- */
-int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
-{
-
-	if (ah->ah_version != AR5K_AR5210 &&
-		ah->ah_version != AR5K_AR5211 &&
-		ah->ah_version != AR5K_AR5212)
-			return -ENOTSUPP;
-
-	/* XXX: What is this magic value and where is it used ? */
-	if (ah->ah_version == AR5K_AR5212)
-		ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
-	else if (ah->ah_version == AR5K_AR5211)
-		ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
-
-	if (ah->ah_version == AR5K_AR5212) {
-		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
-		ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
-		ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
-		ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
-	} else {
-		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
-		ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
-		ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr;
-		ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
-	}
-
-	if (ah->ah_version == AR5K_AR5212)
-		ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
-	else if (ah->ah_version <= AR5K_AR5211)
-		ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
-
-	return 0;
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/desc.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/desc.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/desc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/desc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*
- * Internal RX/TX descriptor structures
- * (rX: reserved fields possibily used by future versions of the ar5k chipset)
- */
-
-/*
- * common hardware RX control descriptor
- */
-struct ath5k_hw_rx_ctl {
-	u32	rx_control_0; /* RX control word 0 */
-	u32	rx_control_1; /* RX control word 1 */
-} __packed;
-
-/* RX control word 0 field/sflags */
-#define AR5K_DESC_RX_CTL0			0x00000000
-
-/* RX control word 1 fields/flags */
-#define AR5K_DESC_RX_CTL1_BUF_LEN		0x00000fff
-#define AR5K_DESC_RX_CTL1_INTREQ		0x00002000
-
-/*
- * common hardware RX status descriptor
- * 5210/11 and 5212 differ only in the flags defined below
- */
-struct ath5k_hw_rx_status {
-	u32	rx_status_0; /* RX status word 0 */
-	u32	rx_status_1; /* RX status word 1 */
-} __packed;
-
-/* 5210/5211 */
-/* RX status word 0 fields/flags */
-#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN		0x00000fff
-#define AR5K_5210_RX_DESC_STATUS0_MORE			0x00001000
-#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
-#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S	15
-#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x07f80000
-#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
-#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
-#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
-
-/* RX status word 1 fields/flags */
-#define AR5K_5210_RX_DESC_STATUS1_DONE			0x00000001
-#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
-#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004
-#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
-#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
-#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
-#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5
-#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
-#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
-#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9
-#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
-#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
-#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS	0x10000000
-
-/* 5212 */
-/* RX status word 0 fields/flags */
-#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN		0x00000fff
-#define AR5K_5212_RX_DESC_STATUS0_MORE			0x00001000
-#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
-#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
-#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S	15
-#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x0ff00000
-#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
-#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
-#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
-
-/* RX status word 1 fields/flags */
-#define AR5K_5212_RX_DESC_STATUS1_DONE			0x00000001
-#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
-#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR		0x00000004
-#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
-#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR		0x00000010
-#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR		0x00000020
-#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
-#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
-#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S		9
-#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
-#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
-#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS	0x80000000
-
-/*
- * common hardware RX error descriptor
- */
-struct ath5k_hw_rx_error {
-	u32	rx_error_0; /* RX status word 0 */
-	u32	rx_error_1; /* RX status word 1 */
-} __packed;
-
-/* RX error word 0 fields/flags */
-#define AR5K_RX_DESC_ERROR0			0x00000000
-
-/* RX error word 1 fields/flags */
-#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE	0x0000ff00
-#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S	8
-
-/* PHY Error codes */
-#define AR5K_DESC_RX_PHY_ERROR_NONE		0x00
-#define AR5K_DESC_RX_PHY_ERROR_TIMING		0x20
-#define AR5K_DESC_RX_PHY_ERROR_PARITY		0x40
-#define AR5K_DESC_RX_PHY_ERROR_RATE		0x60
-#define AR5K_DESC_RX_PHY_ERROR_LENGTH		0x80
-#define AR5K_DESC_RX_PHY_ERROR_64QAM		0xa0
-#define AR5K_DESC_RX_PHY_ERROR_SERVICE		0xc0
-#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR	0xe0
-
-/*
- * 5210/5211 hardware 2-word TX control descriptor
- */
-struct ath5k_hw_2w_tx_ctl {
-	u32	tx_control_0; /* TX control word 0 */
-	u32	tx_control_1; /* TX control word 1 */
-} __packed;
-
-/* TX control word 0 fields/flags */
-#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
-#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN		0x0003f000 /*[5210 ?]*/
-#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S	12
-#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE		0x003c0000
-#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S	18
-#define AR5K_2W_TX_DESC_CTL0_RTSENA		0x00400000
-#define AR5K_2W_TX_DESC_CTL0_CLRDMASK		0x01000000
-#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET	0x00800000 /*[5210]*/
-#define AR5K_2W_TX_DESC_CTL0_VEOL		0x00800000 /*[5211]*/
-#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE		0x1c000000 /*[5210]*/
-#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S	26
-#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210	0x02000000
-#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211	0x1e000000
-
-#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT			\
-		(ah->ah_version == AR5K_AR5210 ?		\
-		AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 :	\
-		AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
-
-#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S	25
-#define AR5K_2W_TX_DESC_CTL0_INTREQ		0x20000000
-#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID	0x40000000
-
-/* TX control word 1 fields/flags */
-#define AR5K_2W_TX_DESC_CTL1_BUF_LEN		0x00000fff
-#define AR5K_2W_TX_DESC_CTL1_MORE		0x00001000
-#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210	0x0007e000
-#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211	0x000fe000
-
-#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX				\
-			(ah->ah_version == AR5K_AR5210 ?		\
-			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 :	\
-			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
-
-#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S	13
-#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE		0x00700000 /*[5211]*/
-#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S	20
-#define AR5K_2W_TX_DESC_CTL1_NOACK		0x00800000 /*[5211]*/
-#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION	0xfff80000 /*[5210 ?]*/
-
-/* Frame types */
-#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL   0x00
-#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM     0x04
-#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL   0x08
-#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
-#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS     0x10
-
-/*
- * 5212 hardware 4-word TX control descriptor
- */
-struct ath5k_hw_4w_tx_ctl {
-	u32	tx_control_0; /* TX control word 0 */
-
-#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
-#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER		0x003f0000
-#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S	16
-#define AR5K_4W_TX_DESC_CTL0_RTSENA		0x00400000
-#define AR5K_4W_TX_DESC_CTL0_VEOL		0x00800000
-#define AR5K_4W_TX_DESC_CTL0_CLRDMASK		0x01000000
-#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT	0x1e000000
-#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S	25
-#define AR5K_4W_TX_DESC_CTL0_INTREQ		0x20000000
-#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID	0x40000000
-#define AR5K_4W_TX_DESC_CTL0_CTSENA		0x80000000
-
-	u32	tx_control_1; /* TX control word 1 */
-
-#define AR5K_4W_TX_DESC_CTL1_BUF_LEN		0x00000fff
-#define AR5K_4W_TX_DESC_CTL1_MORE		0x00001000
-#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX	0x000fe000
-#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S	13
-#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE		0x00f00000
-#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S	20
-#define AR5K_4W_TX_DESC_CTL1_NOACK		0x01000000
-#define AR5K_4W_TX_DESC_CTL1_COMP_PROC		0x06000000
-#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S	25
-#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN	0x18000000
-#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S	27
-#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN	0x60000000
-#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S	29
-
-	u32	tx_control_2; /* TX control word 2 */
-
-#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION		0x00007fff
-#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE	0x00008000
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0		0x000f0000
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S		16
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1		0x00f00000
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S		20
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2		0x0f000000
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S		24
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3		0xf0000000
-#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S		28
-
-	u32	tx_control_3; /* TX control word 3 */
-
-#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0		0x0000001f
-#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1		0x000003e0
-#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S	5
-#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2		0x00007c00
-#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S	10
-#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3		0x000f8000
-#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S	15
-#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE	0x01f00000
-#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S	20
-} __packed;
-
-/*
- * Common TX status descriptor
- */
-struct ath5k_hw_tx_status {
-	u32	tx_status_0; /* TX status word 0 */
-	u32	tx_status_1; /* TX status word 1 */
-} __packed;
-
-/* TX status word 0 fields/flags */
-#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK	0x00000001
-#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES	0x00000002
-#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN	0x00000004
-#define AR5K_DESC_TX_STATUS0_FILTERED		0x00000008
-/*???
-#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT	0x000000f0
-#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S	4
-*/
-#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT	0x000000f0
-#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S	4
-/*???
-#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT	0x00000f00
-#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S	8
-*/
-#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT	0x00000f00
-#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S	8
-#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT	0x0000f000
-#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S	12
-#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP	0xffff0000
-#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S	16
-
-/* TX status word 1 fields/flags */
-#define AR5K_DESC_TX_STATUS1_DONE		0x00000001
-#define AR5K_DESC_TX_STATUS1_SEQ_NUM		0x00001ffe
-#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S		1
-#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH	0x001fe000
-#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S	13
-#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX	0x00600000
-#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S	21
-#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS	0x00800000
-#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA	0x01000000
-
-/*
- * 5210/5211 hardware TX descriptor
- */
-struct ath5k_hw_5210_tx_desc {
-	struct ath5k_hw_2w_tx_ctl	tx_ctl;
-	struct ath5k_hw_tx_status	tx_stat;
-} __packed;
-
-/*
- * 5212 hardware TX descriptor
- */
-struct ath5k_hw_5212_tx_desc {
-	struct ath5k_hw_4w_tx_ctl	tx_ctl;
-	struct ath5k_hw_tx_status	tx_stat;
-} __packed;
-
-/*
- * common hardware RX descriptor
- */
-struct ath5k_hw_all_rx_desc {
-	struct ath5k_hw_rx_ctl			rx_ctl;
-	union {
-		struct ath5k_hw_rx_status	rx_stat;
-		struct ath5k_hw_rx_error	rx_err;
-	} u;
-} __packed;
-
-/*
- * Atheros hardware descriptor
- * This is read and written to by the hardware
- */
-struct ath5k_desc {
-	u32	ds_link;	/* physical address of the next descriptor */
-	u32	ds_data;	/* physical address of data buffer (skb) */
-
-	union {
-		struct ath5k_hw_5210_tx_desc	ds_tx5210;
-		struct ath5k_hw_5212_tx_desc	ds_tx5212;
-		struct ath5k_hw_all_rx_desc	ds_rx;
-	} ud;
-} __packed;
-
-#define AR5K_RXDESC_INTREQ	0x0020
-
-#define AR5K_TXDESC_CLRDMASK	0x0001
-#define AR5K_TXDESC_NOACK	0x0002	/*[5211+]*/
-#define AR5K_TXDESC_RTSENA	0x0004
-#define AR5K_TXDESC_CTSENA	0x0008
-#define AR5K_TXDESC_INTREQ	0x0010
-#define AR5K_TXDESC_VEOL	0x0020	/*[5211+]*/
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/dma.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/dma.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,705 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*************************************\
-* DMA and interrupt masking functions *
-\*************************************/
-
-/*
- * dma.c - DMA and interrupt masking functions
- *
- * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
- * handle queue setup for 5210 chipset (rest are handled on qcu.c).
- * Also we setup interrupt mask register (IMR) and read the various iterrupt
- * status registers (ISR).
- *
- * TODO: Handle SISR on 5211+ and introduce a function to return the queue
- * number that resulted the interrupt.
- */
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*********\
-* Receive *
-\*********/
-
-/**
- * ath5k_hw_start_rx_dma - Start DMA receive
- *
- * @ah:	The &struct ath5k_hw
- */
-void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
-	ath5k_hw_reg_read(ah, AR5K_CR);
-}
-
-/**
- * ath5k_hw_stop_rx_dma - Stop DMA receive
- *
- * @ah:	The &struct ath5k_hw
- */
-int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
-{
-	unsigned int i;
-
-	ATH5K_TRACE(ah->ah_sc);
-	ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
-
-	/*
-	 * It may take some time to disable the DMA receive unit
-	 */
-	for (i = 1000; i > 0 &&
-			(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
-			i--)
-		udelay(10);
-
-	return i ? 0 : -EBUSY;
-}
-
-/**
- * ath5k_hw_get_rxdp - Get RX Descriptor's address
- *
- * @ah: The &struct ath5k_hw
- *
- * XXX: Is RXDP read and clear ?
- */
-u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
-{
-	return ath5k_hw_reg_read(ah, AR5K_RXDP);
-}
-
-/**
- * ath5k_hw_set_rxdp - Set RX Descriptor's address
- *
- * @ah: The &struct ath5k_hw
- * @phys_addr: RX descriptor address
- *
- * XXX: Should we check if rx is enabled before setting rxdp ?
- */
-void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
-}
-
-
-/**********\
-* Transmit *
-\**********/
-
-/**
- * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
- *
- * @ah: The &struct ath5k_hw
- * @queue: The hw queue number
- *
- * Start DMA transmit for a specific queue and since 5210 doesn't have
- * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
- * queue for normal data and one queue for beacons). For queue setup
- * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
- * of range or if queue is already disabled.
- *
- * NOTE: Must be called after setting up tx control descriptor for that
- * queue (see below).
- */
-int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
-{
-	u32 tx_queue;
-
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	/* Return if queue is declared inactive */
-	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return -EIO;
-
-	if (ah->ah_version == AR5K_AR5210) {
-		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
-
-		/*
-		 * Set the queue by type on 5210
-		 */
-		switch (ah->ah_txq[queue].tqi_type) {
-		case AR5K_TX_QUEUE_DATA:
-			tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
-			break;
-		case AR5K_TX_QUEUE_BEACON:
-			tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
-			ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
-					AR5K_BSR);
-			break;
-		case AR5K_TX_QUEUE_CAB:
-			tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
-			ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
-				AR5K_BCR_BDMAE, AR5K_BSR);
-			break;
-		default:
-			return -EINVAL;
-		}
-		/* Start queue */
-		ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
-		ath5k_hw_reg_read(ah, AR5K_CR);
-	} else {
-		/* Return if queue is disabled */
-		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
-			return -EIO;
-
-		/* Start queue */
-		AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
-	}
-
-	return 0;
-}
-
-/**
- * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
- *
- * @ah: The &struct ath5k_hw
- * @queue: The hw queue number
- *
- * Stop DMA transmit on a specific hw queue and drain queue so we don't
- * have any pending frames. Returns -EBUSY if we still have pending frames,
- * -EINVAL if queue number is out of range.
- *
- */
-int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
-{
-	unsigned int i = 40;
-	u32 tx_queue, pending;
-
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	/* Return if queue is declared inactive */
-	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return -EIO;
-
-	if (ah->ah_version == AR5K_AR5210) {
-		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
-
-		/*
-		 * Set by queue type
-		 */
-		switch (ah->ah_txq[queue].tqi_type) {
-		case AR5K_TX_QUEUE_DATA:
-			tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
-			break;
-		case AR5K_TX_QUEUE_BEACON:
-		case AR5K_TX_QUEUE_CAB:
-			/* XXX Fix me... */
-			tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
-			ath5k_hw_reg_write(ah, 0, AR5K_BSR);
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		/* Stop queue */
-		ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
-		ath5k_hw_reg_read(ah, AR5K_CR);
-	} else {
-		/*
-		 * Schedule TX disable and wait until queue is empty
-		 */
-		AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
-
-		/*Check for pending frames*/
-		do {
-			pending = ath5k_hw_reg_read(ah,
-				AR5K_QUEUE_STATUS(queue)) &
-				AR5K_QCU_STS_FRMPENDCNT;
-			udelay(100);
-		} while (--i && pending);
-
-		/* For 2413+ order PCU to drop packets using
-		 * QUIET mechanism */
-		if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
-		pending){
-			/* Set periodicity and duration */
-			ath5k_hw_reg_write(ah,
-				AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
-				AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
-				AR5K_QUIET_CTL2);
-
-			/* Enable quiet period for current TSF */
-			ath5k_hw_reg_write(ah,
-				AR5K_QUIET_CTL1_QT_EN |
-				AR5K_REG_SM(ath5k_hw_reg_read(ah,
-						AR5K_TSF_L32_5211) >> 10,
-						AR5K_QUIET_CTL1_NEXT_QT_TSF),
-				AR5K_QUIET_CTL1);
-
-			/* Force channel idle high */
-			AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
-					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
-
-			/* Wait a while and disable mechanism */
-			udelay(200);
-			AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
-						AR5K_QUIET_CTL1_QT_EN);
-
-			/* Re-check for pending frames */
-			i = 40;
-			do {
-				pending = ath5k_hw_reg_read(ah,
-					AR5K_QUEUE_STATUS(queue)) &
-					AR5K_QCU_STS_FRMPENDCNT;
-				udelay(100);
-			} while (--i && pending);
-
-			AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
-					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
-		}
-
-		/* Clear register */
-		ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
-		if (pending)
-			return -EBUSY;
-	}
-
-	/* TODO: Check for success on 5210 else return error */
-	return 0;
-}
-
-/**
- * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
- *
- * @ah: The &struct ath5k_hw
- * @queue: The hw queue number
- *
- * Get TX descriptor's address for a specific queue. For 5210 we ignore
- * the queue number and use tx queue type since we only have 2 queues.
- * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
- * For newer chips with QCU/DCU we just read the corresponding TXDP register.
- *
- * XXX: Is TXDP read and clear ?
- */
-u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
-{
-	u16 tx_reg;
-
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	/*
-	 * Get the transmit queue descriptor pointer from the selected queue
-	 */
-	/*5210 doesn't have QCU*/
-	if (ah->ah_version == AR5K_AR5210) {
-		switch (ah->ah_txq[queue].tqi_type) {
-		case AR5K_TX_QUEUE_DATA:
-			tx_reg = AR5K_NOQCU_TXDP0;
-			break;
-		case AR5K_TX_QUEUE_BEACON:
-		case AR5K_TX_QUEUE_CAB:
-			tx_reg = AR5K_NOQCU_TXDP1;
-			break;
-		default:
-			return 0xffffffff;
-		}
-	} else {
-		tx_reg = AR5K_QUEUE_TXDP(queue);
-	}
-
-	return ath5k_hw_reg_read(ah, tx_reg);
-}
-
-/**
- * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
- *
- * @ah: The &struct ath5k_hw
- * @queue: The hw queue number
- *
- * Set TX descriptor's address for a specific queue. For 5210 we ignore
- * the queue number and we use tx queue type since we only have 2 queues
- * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
- * For newer chips with QCU/DCU we just set the corresponding TXDP register.
- * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
- * active.
- */
-int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
-{
-	u16 tx_reg;
-
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	/*
-	 * Set the transmit queue descriptor pointer register by type
-	 * on 5210
-	 */
-	if (ah->ah_version == AR5K_AR5210) {
-		switch (ah->ah_txq[queue].tqi_type) {
-		case AR5K_TX_QUEUE_DATA:
-			tx_reg = AR5K_NOQCU_TXDP0;
-			break;
-		case AR5K_TX_QUEUE_BEACON:
-		case AR5K_TX_QUEUE_CAB:
-			tx_reg = AR5K_NOQCU_TXDP1;
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
-		/*
-		 * Set the transmit queue descriptor pointer for
-		 * the selected queue on QCU for 5211+
-		 * (this won't work if the queue is still active)
-		 */
-		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
-			return -EIO;
-
-		tx_reg = AR5K_QUEUE_TXDP(queue);
-	}
-
-	/* Set descriptor pointer */
-	ath5k_hw_reg_write(ah, phys_addr, tx_reg);
-
-	return 0;
-}
-
-/**
- * ath5k_hw_update_tx_triglevel - Update tx trigger level
- *
- * @ah: The &struct ath5k_hw
- * @increase: Flag to force increase of trigger level
- *
- * This function increases/decreases the tx trigger level for the tx fifo
- * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
- * the buffer and transmits it's data. Lowering this results sending small
- * frames more quickly but can lead to tx underruns, raising it a lot can
- * result other problems (i think bmiss is related). Right now we start with
- * the lowest possible (64Bytes) and if we get tx underrun we increase it using
- * the increase flag. Returns -EIO if we have have reached maximum/minimum.
- *
- * XXX: Link this with tx DMA size ?
- * XXX: Use it to save interrupts ?
- * TODO: Needs testing, i think it's related to bmiss...
- */
-int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
-{
-	u32 trigger_level, imr;
-	int ret = -EIO;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/*
-	 * Disable interrupts by setting the mask
-	 */
-	imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
-
-	trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
-			AR5K_TXCFG_TXFULL);
-
-	if (!increase) {
-		if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
-			goto done;
-	} else
-		trigger_level +=
-			((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
-
-	/*
-	 * Update trigger level on success
-	 */
-	if (ah->ah_version == AR5K_AR5210)
-		ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
-	else
-		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
-				AR5K_TXCFG_TXFULL, trigger_level);
-
-	ret = 0;
-
-done:
-	/*
-	 * Restore interrupt mask
-	 */
-	ath5k_hw_set_imr(ah, imr);
-
-	return ret;
-}
-
-/*******************\
-* Interrupt masking *
-\*******************/
-
-/**
- * ath5k_hw_is_intr_pending - Check if we have pending interrupts
- *
- * @ah: The &struct ath5k_hw
- *
- * Check if we have pending interrupts to process. Returns 1 if we
- * have pending interrupts and 0 if we haven't.
- */
-bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
-}
-
-/**
- * ath5k_hw_get_isr - Get interrupt status
- *
- * @ah: The @struct ath5k_hw
- * @interrupt_mask: Driver's interrupt mask used to filter out
- * interrupts in sw.
- *
- * This function is used inside our interrupt handler to determine the reason
- * for the interrupt by reading Primary Interrupt Status Register. Returns an
- * abstract interrupt status mask which is mostly ISR with some uncommon bits
- * being mapped on some standard non hw-specific positions
- * (check out &ath5k_int).
- *
- * NOTE: We use read-and-clear register, so after this function is called ISR
- * is zeroed.
- */
-int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
-{
-	u32 data;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/*
-	 * Read interrupt status from the Interrupt Status register
-	 * on 5210
-	 */
-	if (ah->ah_version == AR5K_AR5210) {
-		data = ath5k_hw_reg_read(ah, AR5K_ISR);
-		if (unlikely(data == AR5K_INT_NOCARD)) {
-			*interrupt_mask = data;
-			return -ENODEV;
-		}
-	} else {
-		/*
-		 * Read interrupt status from Interrupt
-		 * Status Register shadow copy (Read And Clear)
-		 *
-		 * Note: PISR/SISR Not available on 5210
-		 */
-		data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
-		if (unlikely(data == AR5K_INT_NOCARD)) {
-			*interrupt_mask = data;
-			return -ENODEV;
-		}
-	}
-
-	/*
-	 * Get abstract interrupt mask (driver-compatible)
-	 */
-	*interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
-
-	if (ah->ah_version != AR5K_AR5210) {
-		u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
-
-		/*HIU = Host Interface Unit (PCI etc)*/
-		if (unlikely(data & (AR5K_ISR_HIUERR)))
-			*interrupt_mask |= AR5K_INT_FATAL;
-
-		/*Beacon Not Ready*/
-		if (unlikely(data & (AR5K_ISR_BNR)))
-			*interrupt_mask |= AR5K_INT_BNR;
-
-		if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
-					AR5K_SISR2_DPERR |
-					AR5K_SISR2_MCABT)))
-			*interrupt_mask |= AR5K_INT_FATAL;
-
-		if (data & AR5K_ISR_TIM)
-			*interrupt_mask |= AR5K_INT_TIM;
-
-		if (data & AR5K_ISR_BCNMISC) {
-			if (sisr2 & AR5K_SISR2_TIM)
-				*interrupt_mask |= AR5K_INT_TIM;
-			if (sisr2 & AR5K_SISR2_DTIM)
-				*interrupt_mask |= AR5K_INT_DTIM;
-			if (sisr2 & AR5K_SISR2_DTIM_SYNC)
-				*interrupt_mask |= AR5K_INT_DTIM_SYNC;
-			if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
-				*interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
-			if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
-				*interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
-		}
-
-		if (data & AR5K_ISR_RXDOPPLER)
-			*interrupt_mask |= AR5K_INT_RX_DOPPLER;
-		if (data & AR5K_ISR_QCBRORN) {
-			*interrupt_mask |= AR5K_INT_QCBRORN;
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
-					AR5K_SISR3_QCBRORN);
-		}
-		if (data & AR5K_ISR_QCBRURN) {
-			*interrupt_mask |= AR5K_INT_QCBRURN;
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
-					AR5K_SISR3_QCBRURN);
-		}
-		if (data & AR5K_ISR_QTRIG) {
-			*interrupt_mask |= AR5K_INT_QTRIG;
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
-					AR5K_SISR4_QTRIG);
-		}
-
-		if (data & AR5K_ISR_TXOK)
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
-					AR5K_SISR0_QCU_TXOK);
-
-		if (data & AR5K_ISR_TXDESC)
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
-					AR5K_SISR0_QCU_TXDESC);
-
-		if (data & AR5K_ISR_TXERR)
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
-					AR5K_SISR1_QCU_TXERR);
-
-		if (data & AR5K_ISR_TXEOL)
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
-					AR5K_SISR1_QCU_TXEOL);
-
-		if (data & AR5K_ISR_TXURN)
-			ah->ah_txq_isr |= AR5K_REG_MS(
-					ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
-					AR5K_SISR2_QCU_TXURN);
-	} else {
-		if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
-				| AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
-			*interrupt_mask |= AR5K_INT_FATAL;
-
-		/*
-		 * XXX: BMISS interrupts may occur after association.
-		 * I found this on 5210 code but it needs testing. If this is
-		 * true we should disable them before assoc and re-enable them
-		 * after a successful assoc + some jiffies.
-			interrupt_mask &= ~AR5K_INT_BMISS;
-		 */
-	}
-
-	/*
-	 * In case we didn't handle anything,
-	 * print the register value.
-	 */
-	if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
-		ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
-
-	return 0;
-}
-
-/**
- * ath5k_hw_set_imr - Set interrupt mask
- *
- * @ah: The &struct ath5k_hw
- * @new_mask: The new interrupt mask to be set
- *
- * Set the interrupt mask in hw to save interrupts. We do that by mapping
- * ath5k_int bits to hw-specific bits to remove abstraction and writing
- * Interrupt Mask Register.
- */
-enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
-{
-	enum ath5k_int old_mask, int_mask;
-
-	old_mask = ah->ah_imr;
-
-	/*
-	 * Disable card interrupts to prevent any race conditions
-	 * (they will be re-enabled afterwards if AR5K_INT GLOBAL
-	 * is set again on the new mask).
-	 */
-	if (old_mask & AR5K_INT_GLOBAL) {
-		ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
-		ath5k_hw_reg_read(ah, AR5K_IER);
-	}
-
-	/*
-	 * Add additional, chipset-dependent interrupt mask flags
-	 * and write them to the IMR (interrupt mask register).
-	 */
-	int_mask = new_mask & AR5K_INT_COMMON;
-
-	if (ah->ah_version != AR5K_AR5210) {
-		/* Preserve per queue TXURN interrupt mask */
-		u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
-				& AR5K_SIMR2_QCU_TXURN;
-
-		if (new_mask & AR5K_INT_FATAL) {
-			int_mask |= AR5K_IMR_HIUERR;
-			simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
-				| AR5K_SIMR2_DPERR);
-		}
-
-		/*Beacon Not Ready*/
-		if (new_mask & AR5K_INT_BNR)
-			int_mask |= AR5K_INT_BNR;
-
-		if (new_mask & AR5K_INT_TIM)
-			int_mask |= AR5K_IMR_TIM;
-
-		if (new_mask & AR5K_INT_TIM)
-			simr2 |= AR5K_SISR2_TIM;
-		if (new_mask & AR5K_INT_DTIM)
-			simr2 |= AR5K_SISR2_DTIM;
-		if (new_mask & AR5K_INT_DTIM_SYNC)
-			simr2 |= AR5K_SISR2_DTIM_SYNC;
-		if (new_mask & AR5K_INT_BCN_TIMEOUT)
-			simr2 |= AR5K_SISR2_BCN_TIMEOUT;
-		if (new_mask & AR5K_INT_CAB_TIMEOUT)
-			simr2 |= AR5K_SISR2_CAB_TIMEOUT;
-
-		if (new_mask & AR5K_INT_RX_DOPPLER)
-			int_mask |= AR5K_IMR_RXDOPPLER;
-
-		/* Note: Per queue interrupt masks
-		 * are set via reset_tx_queue (qcu.c) */
-		ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
-		ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
-
-	} else {
-		if (new_mask & AR5K_INT_FATAL)
-			int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
-				| AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
-
-		ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
-	}
-
-	/* If RXNOFRM interrupt is masked disable it
-	 * by setting AR5K_RXNOFRM to zero */
-	if (!(new_mask & AR5K_INT_RXNOFRM))
-		ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
-
-	/* Store new interrupt mask */
-	ah->ah_imr = new_mask;
-
-	/* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
-	if (new_mask & AR5K_INT_GLOBAL) {
-		ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
-		ath5k_hw_reg_read(ah, AR5K_IER);
-	}
-
-	return old_mask;
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/eeprom.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/eeprom.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/eeprom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/eeprom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1769 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*************************************\
-* EEPROM access functions and helpers *
-\*************************************/
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*
- * Read from eeprom
- */
-static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
-{
-	u32 status, timeout;
-
-	ATH5K_TRACE(ah->ah_sc);
-	/*
-	 * Initialize EEPROM access
-	 */
-	if (ah->ah_version == AR5K_AR5210) {
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
-		(void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
-	} else {
-		ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
-		AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
-				AR5K_EEPROM_CMD_READ);
-	}
-
-	for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
-		status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
-		if (status & AR5K_EEPROM_STAT_RDDONE) {
-			if (status & AR5K_EEPROM_STAT_RDERR)
-				return -EIO;
-			*data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
-					0xffff);
-			return 0;
-		}
-		udelay(15);
-	}
-
-	return -ETIMEDOUT;
-}
-
-/*
- * Translate binary channel representation in EEPROM to frequency
- */
-static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
-                                 unsigned int mode)
-{
-	u16 val;
-
-	if (bin == AR5K_EEPROM_CHANNEL_DIS)
-		return bin;
-
-	if (mode == AR5K_EEPROM_MODE_11A) {
-		if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
-			val = (5 * bin) + 4800;
-		else
-			val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
-				(bin * 10) + 5100;
-	} else {
-		if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
-			val = bin + 2300;
-		else
-			val = bin + 2400;
-	}
-
-	return val;
-}
-
-/*
- * Initialize eeprom & capabilities structs
- */
-static int
-ath5k_eeprom_init_header(struct ath5k_hw *ah)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	int ret;
-	u16 val;
-
-	/*
-	 * Read values from EEPROM and store them in the capability structure
-	 */
-	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
-	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
-	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
-	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
-	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
-
-	/* Return if we have an old EEPROM */
-	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
-		return 0;
-
-#ifdef notyet
-	/*
-	 * Validate the checksum of the EEPROM date. There are some
-	 * devices with invalid EEPROMs.
-	 */
-	for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
-		AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
-		cksum ^= val;
-	}
-	if (cksum != AR5K_EEPROM_INFO_CKSUM) {
-		ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
-		return -EIO;
-	}
-#endif
-
-	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
-	    ee_ant_gain);
-
-	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
-		AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
-		AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
-
-		/* XXX: Don't know which versions include these two */
-		AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
-
-		if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
-			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
-
-		if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
-			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
-			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
-			AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
-		}
-	}
-
-	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
-		AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
-		ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
-		ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
-
-		AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
-		ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
-		ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
-	}
-
-	return 0;
-}
-
-
-/*
- * Read antenna infos from eeprom
- */
-static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
-		unsigned int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u32 o = *offset;
-	u16 val;
-	int ret, i = 0;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_switch_settling[mode]	= (val >> 8) & 0x7f;
-	ee->ee_atn_tx_rx[mode]		= (val >> 2) & 0x3f;
-	ee->ee_ant_control[mode][i]	= (val << 4) & 0x3f;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_ant_control[mode][i++]	|= (val >> 12) & 0xf;
-	ee->ee_ant_control[mode][i++]	= (val >> 6) & 0x3f;
-	ee->ee_ant_control[mode][i++]	= val & 0x3f;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_ant_control[mode][i++]	= (val >> 10) & 0x3f;
-	ee->ee_ant_control[mode][i++]	= (val >> 4) & 0x3f;
-	ee->ee_ant_control[mode][i]	= (val << 2) & 0x3f;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_ant_control[mode][i++]	|= (val >> 14) & 0x3;
-	ee->ee_ant_control[mode][i++]	= (val >> 8) & 0x3f;
-	ee->ee_ant_control[mode][i++]	= (val >> 2) & 0x3f;
-	ee->ee_ant_control[mode][i]	= (val << 4) & 0x3f;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_ant_control[mode][i++]	|= (val >> 12) & 0xf;
-	ee->ee_ant_control[mode][i++]	= (val >> 6) & 0x3f;
-	ee->ee_ant_control[mode][i++]	= val & 0x3f;
-
-	/* Get antenna modes */
-	ah->ah_antenna[mode][0] =
-	    (ee->ee_ant_control[mode][0] << 4);
-	ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
-	     ee->ee_ant_control[mode][1] 	|
-	    (ee->ee_ant_control[mode][2] << 6) 	|
-	    (ee->ee_ant_control[mode][3] << 12) |
-	    (ee->ee_ant_control[mode][4] << 18) |
-	    (ee->ee_ant_control[mode][5] << 24);
-	ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
-	     ee->ee_ant_control[mode][6] 	|
-	    (ee->ee_ant_control[mode][7] << 6) 	|
-	    (ee->ee_ant_control[mode][8] << 12) |
-	    (ee->ee_ant_control[mode][9] << 18) |
-	    (ee->ee_ant_control[mode][10] << 24);
-
-	/* return new offset */
-	*offset = o;
-
-	return 0;
-}
-
-/*
- * Read supported modes and some mode-specific calibration data
- * from eeprom
- */
-static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
-		unsigned int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u32 o = *offset;
-	u16 val;
-	int ret;
-
-	ee->ee_n_piers[mode] = 0;
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_adc_desired_size[mode]	= (s8)((val >> 8) & 0xff);
-	switch(mode) {
-	case AR5K_EEPROM_MODE_11A:
-		ee->ee_ob[mode][3]	= (val >> 5) & 0x7;
-		ee->ee_db[mode][3]	= (val >> 2) & 0x7;
-		ee->ee_ob[mode][2]	= (val << 1) & 0x7;
-
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_ob[mode][2]	|= (val >> 15) & 0x1;
-		ee->ee_db[mode][2]	= (val >> 12) & 0x7;
-		ee->ee_ob[mode][1]	= (val >> 9) & 0x7;
-		ee->ee_db[mode][1]	= (val >> 6) & 0x7;
-		ee->ee_ob[mode][0]	= (val >> 3) & 0x7;
-		ee->ee_db[mode][0]	= val & 0x7;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-	case AR5K_EEPROM_MODE_11B:
-		ee->ee_ob[mode][1]	= (val >> 4) & 0x7;
-		ee->ee_db[mode][1]	= val & 0x7;
-		break;
-	}
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_tx_end2xlna_enable[mode]	= (val >> 8) & 0xff;
-	ee->ee_thr_62[mode]		= val & 0xff;
-
-	if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
-		ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_tx_end2xpa_disable[mode]	= (val >> 8) & 0xff;
-	ee->ee_tx_frm2xpa_enable[mode]	= val & 0xff;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_pga_desired_size[mode]	= (val >> 8) & 0xff;
-
-	if ((val & 0xff) & 0x80)
-		ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
-	else
-		ee->ee_noise_floor_thr[mode] = val & 0xff;
-
-	if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
-		ee->ee_noise_floor_thr[mode] =
-		    mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
-
-	AR5K_EEPROM_READ(o++, val);
-	ee->ee_xlna_gain[mode]		= (val >> 5) & 0xff;
-	ee->ee_x_gain[mode]		= (val >> 1) & 0xf;
-	ee->ee_xpd[mode]		= val & 0x1;
-
-	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
-		ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
-
-	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
-
-		if (mode == AR5K_EEPROM_MODE_11A)
-			ee->ee_xr_power[mode] = val & 0x3f;
-		else {
-			ee->ee_ob[mode][0] = val & 0x7;
-			ee->ee_db[mode][0] = (val >> 3) & 0x7;
-		}
-	}
-
-	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
-		ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
-		ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
-	} else {
-		ee->ee_i_gain[mode] = (val >> 13) & 0x7;
-
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_i_gain[mode] |= (val << 3) & 0x38;
-
-		if (mode == AR5K_EEPROM_MODE_11G) {
-			ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
-			if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6)
-				ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
-		}
-	}
-
-	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
-			mode == AR5K_EEPROM_MODE_11A) {
-		ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
-		ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
-	}
-
-	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
-		goto done;
-
-	/* Note: >= v5 have bg freq piers on another location
-	 * so these freq piers are ignored for >= v5 (should be 0xff
-	 * anyway) */
-	switch(mode) {
-	case AR5K_EEPROM_MODE_11A:
-		if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
-			break;
-
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_margin_tx_rx[mode] = val & 0x3f;
-		break;
-	case AR5K_EEPROM_MODE_11B:
-		AR5K_EEPROM_READ(o++, val);
-
-		ee->ee_pwr_cal_b[0].freq =
-			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
-		if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
-			ee->ee_n_piers[mode]++;
-
-		ee->ee_pwr_cal_b[1].freq =
-			ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
-		if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
-			ee->ee_n_piers[mode]++;
-
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_pwr_cal_b[2].freq =
-			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
-		if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
-			ee->ee_n_piers[mode]++;
-
-		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
-			ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		AR5K_EEPROM_READ(o++, val);
-
-		ee->ee_pwr_cal_g[0].freq =
-			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
-		if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
-			ee->ee_n_piers[mode]++;
-
-		ee->ee_pwr_cal_g[1].freq =
-			ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
-		if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
-			ee->ee_n_piers[mode]++;
-
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_turbo_max_power[mode] = val & 0x7f;
-		ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
-
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_pwr_cal_g[2].freq =
-			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
-		if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
-			ee->ee_n_piers[mode]++;
-
-		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
-			ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
-
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
-		ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
-
-		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
-			AR5K_EEPROM_READ(o++, val);
-			ee->ee_cck_ofdm_gain_delta = val & 0xff;
-		}
-		break;
-	}
-
-done:
-	/* return new offset */
-	*offset = o;
-
-	return 0;
-}
-
-/*
- * Read turbo mode information on newer EEPROM versions
- */
-static int
-ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
-			      u32 *offset, unsigned int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u32 o = *offset;
-	u16 val;
-	int ret;
-
-	if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
-		return 0;
-
-	switch (mode){
-	case AR5K_EEPROM_MODE_11A:
-		ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
-
-		ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7;
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3;
-		ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f;
-
-		ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f;
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
-		ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
-
-		if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
-			ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f;
-
-		ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7;
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1;
-		ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f;
-
-		ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f;
-		AR5K_EEPROM_READ(o++, val);
-		ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5;
-		ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff;
-		break;
-	}
-
-	/* return new offset */
-	*offset = o;
-
-	return 0;
-}
-
-/* Read mode-specific data (except power calibration data) */
-static int
-ath5k_eeprom_init_modes(struct ath5k_hw *ah)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u32 mode_offset[3];
-	unsigned int mode;
-	u32 offset;
-	int ret;
-
-	/*
-	 * Get values for all modes
-	 */
-	mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
-	mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
-	mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
-
-	ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] =
-		AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
-
-	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
-		offset = mode_offset[mode];
-
-		ret = ath5k_eeprom_read_ants(ah, &offset, mode);
-		if (ret)
-			return ret;
-
-		ret = ath5k_eeprom_read_modes(ah, &offset, mode);
-		if (ret)
-			return ret;
-
-		ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
-		if (ret)
-			return ret;
-	}
-
-	/* override for older eeprom versions for better performance */
-	if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) {
-		ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15;
-		ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28;
-		ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28;
-	}
-
-	return 0;
-}
-
-/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
- * frequency mask) */
-static inline int
-ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
-			struct ath5k_chan_pcal_info *pc, unsigned int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	int o = *offset;
-	int i = 0;
-	u8 freq1, freq2;
-	int ret;
-	u16 val;
-
-	ee->ee_n_piers[mode] = 0;
-	while(i < max) {
-		AR5K_EEPROM_READ(o++, val);
-
-		freq1 = val & 0xff;
-		if (!freq1)
-			break;
-
-		pc[i++].freq = ath5k_eeprom_bin2freq(ee,
-				freq1, mode);
-		ee->ee_n_piers[mode]++;
-
-		freq2 = (val >> 8) & 0xff;
-		if (!freq2)
-			break;
-
-		pc[i++].freq = ath5k_eeprom_bin2freq(ee,
-				freq2, mode);
-		ee->ee_n_piers[mode]++;
-	}
-
-	/* return new offset */
-	*offset = o;
-
-	return 0;
-}
-
-/* Read frequency piers for 802.11a */
-static int
-ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
-	int i, ret;
-	u16 val;
-	u8 mask;
-
-	if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
-		ath5k_eeprom_read_freq_list(ah, &offset,
-			AR5K_EEPROM_N_5GHZ_CHAN, pcal,
-			AR5K_EEPROM_MODE_11A);
-	} else {
-		mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
-
-		AR5K_EEPROM_READ(offset++, val);
-		pcal[0].freq  = (val >> 9) & mask;
-		pcal[1].freq  = (val >> 2) & mask;
-		pcal[2].freq  = (val << 5) & mask;
-
-		AR5K_EEPROM_READ(offset++, val);
-		pcal[2].freq |= (val >> 11) & 0x1f;
-		pcal[3].freq  = (val >> 4) & mask;
-		pcal[4].freq  = (val << 3) & mask;
-
-		AR5K_EEPROM_READ(offset++, val);
-		pcal[4].freq |= (val >> 13) & 0x7;
-		pcal[5].freq  = (val >> 6) & mask;
-		pcal[6].freq  = (val << 1) & mask;
-
-		AR5K_EEPROM_READ(offset++, val);
-		pcal[6].freq |= (val >> 15) & 0x1;
-		pcal[7].freq  = (val >> 8) & mask;
-		pcal[8].freq  = (val >> 1) & mask;
-		pcal[9].freq  = (val << 6) & mask;
-
-		AR5K_EEPROM_READ(offset++, val);
-		pcal[9].freq |= (val >> 10) & 0x3f;
-
-		/* Fixed number of piers */
-		ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
-
-		for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
-			pcal[i].freq = ath5k_eeprom_bin2freq(ee,
-				pcal[i].freq, AR5K_EEPROM_MODE_11A);
-		}
-	}
-
-	return 0;
-}
-
-/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
-static inline int
-ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info *pcal;
-
-	switch(mode) {
-	case AR5K_EEPROM_MODE_11B:
-		pcal = ee->ee_pwr_cal_b;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		pcal = ee->ee_pwr_cal_g;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	ath5k_eeprom_read_freq_list(ah, &offset,
-		AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
-		mode);
-
-	return 0;
-}
-
-/*
- * Read power calibration for RF5111 chips
- *
- * For RF5111 we have an XPD -eXternal Power Detector- curve
- * for each calibrated channel. Each curve has 0,5dB Power steps
- * on x axis and PCDAC steps (offsets) on y axis and looks like an
- * exponential function. To recreate the curve we read 11 points
- * here and interpolate later.
- */
-
-/* Used to match PCDAC steps with power values on RF5111 chips
- * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
- * steps that match with the power values we read from eeprom. On
- * older eeprom versions (< 3.2) these steps are equaly spaced at
- * 10% of the pcdac curve -until the curve reaches it's maximum-
- * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
- * these 11 steps are spaced in a different way. This function returns
- * the pcdac steps based on eeprom version and curve min/max so that we
- * can have pcdac/pwr points.
- */
-static inline void
-ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
-{
-	const static u16 intercepts3[] =
-		{ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
-	const static u16 intercepts3_2[] =
-		{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
-	const u16 *ip;
-	int i;
-
-	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
-		ip = intercepts3_2;
-	else
-		ip = intercepts3;
-
-	for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
-		vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
-}
-
-/* Convert RF5111 specific data to generic raw data
- * used by interpolation code */
-static int
-ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
-				struct ath5k_chan_pcal_info *chinfo)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info_rf5111 *pcinfo;
-	struct ath5k_pdgain_info *pd;
-	u8 pier, point, idx;
-	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
-
-	/* Fill raw data for each calibration pier */
-	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
-
-		pcinfo = &chinfo[pier].rf5111_info;
-
-		/* Allocate pd_curves for this cal pier */
-		chinfo[pier].pd_curves =
-			kcalloc(AR5K_EEPROM_N_PD_CURVES,
-				sizeof(struct ath5k_pdgain_info),
-				GFP_KERNEL);
-
-		if (!chinfo[pier].pd_curves)
-			return -ENOMEM;
-
-		/* Only one curve for RF5111
-		 * find out which one and place
-		 * in in pd_curves.
-		 * Note: ee_x_gain is reversed here */
-		for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
-
-			if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) {
-				pdgain_idx[0] = idx;
-				break;
-			}
-		}
-
-		ee->ee_pd_gains[mode] = 1;
-
-		pd = &chinfo[pier].pd_curves[idx];
-
-		pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111;
-
-		/* Allocate pd points for this curve */
-		pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
-					sizeof(u8), GFP_KERNEL);
-		if (!pd->pd_step)
-			return -ENOMEM;
-
-		pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
-					sizeof(s16), GFP_KERNEL);
-		if (!pd->pd_pwr)
-			return -ENOMEM;
-
-		/* Fill raw dataset
-		 * (convert power to 0.25dB units
-		 * for RF5112 combatibility) */
-		for (point = 0; point < pd->pd_points; point++) {
-
-			/* Absolute values */
-			pd->pd_pwr[point] = 2 * pcinfo->pwr[point];
-
-			/* Already sorted */
-			pd->pd_step[point] = pcinfo->pcdac[point];
-		}
-
-		/* Set min/max pwr */
-		chinfo[pier].min_pwr = pd->pd_pwr[0];
-		chinfo[pier].max_pwr = pd->pd_pwr[10];
-
-	}
-
-	return 0;
-}
-
-/* Parse EEPROM data */
-static int
-ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info *pcal;
-	int offset, ret;
-	int i;
-	u16 val;
-
-	offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
-	switch(mode) {
-	case AR5K_EEPROM_MODE_11A:
-		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
-			return 0;
-
-		ret = ath5k_eeprom_init_11a_pcal_freq(ah,
-			offset + AR5K_EEPROM_GROUP1_OFFSET);
-		if (ret < 0)
-			return ret;
-
-		offset += AR5K_EEPROM_GROUP2_OFFSET;
-		pcal = ee->ee_pwr_cal_a;
-		break;
-	case AR5K_EEPROM_MODE_11B:
-		if (!AR5K_EEPROM_HDR_11B(ee->ee_header) &&
-		    !AR5K_EEPROM_HDR_11G(ee->ee_header))
-			return 0;
-
-		pcal = ee->ee_pwr_cal_b;
-		offset += AR5K_EEPROM_GROUP3_OFFSET;
-
-		/* fixed piers */
-		pcal[0].freq = 2412;
-		pcal[1].freq = 2447;
-		pcal[2].freq = 2484;
-		ee->ee_n_piers[mode] = 3;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
-			return 0;
-
-		pcal = ee->ee_pwr_cal_g;
-		offset += AR5K_EEPROM_GROUP4_OFFSET;
-
-		/* fixed piers */
-		pcal[0].freq = 2312;
-		pcal[1].freq = 2412;
-		pcal[2].freq = 2484;
-		ee->ee_n_piers[mode] = 3;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
-		struct ath5k_chan_pcal_info_rf5111 *cdata =
-			&pcal[i].rf5111_info;
-
-		AR5K_EEPROM_READ(offset++, val);
-		cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M);
-		cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M);
-		cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M);
-
-		AR5K_EEPROM_READ(offset++, val);
-		cdata->pwr[0] |= ((val >> 14) & 0x3);
-		cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M);
-		cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M);
-		cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M);
-
-		AR5K_EEPROM_READ(offset++, val);
-		cdata->pwr[3] |= ((val >> 12) & 0xf);
-		cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M);
-		cdata->pwr[5] = (val  & AR5K_EEPROM_POWER_M);
-
-		AR5K_EEPROM_READ(offset++, val);
-		cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M);
-		cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M);
-		cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M);
-
-		AR5K_EEPROM_READ(offset++, val);
-		cdata->pwr[8] |= ((val >> 14) & 0x3);
-		cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M);
-		cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M);
-
-		ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
-			cdata->pcdac_max, cdata->pcdac);
-	}
-
-	return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
-}
-
-
-/*
- * Read power calibration for RF5112 chips
- *
- * For RF5112 we have 4 XPD -eXternal Power Detector- curves
- * for each calibrated channel on 0, -6, -12 and -18dbm but we only
- * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
- * power steps on x axis and PCDAC steps on y axis and looks like a
- * linear function. To recreate the curve and pass the power values
- * on hw, we read 4 points for xpd 0 (lower gain -> max power)
- * and 3 points for xpd 3 (higher gain -> lower power) here and
- * interpolate later.
- *
- * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
- */
-
-/* Convert RF5112 specific data to generic raw data
- * used by interpolation code */
-static int
-ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
-				struct ath5k_chan_pcal_info *chinfo)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info_rf5112 *pcinfo;
-	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
-	unsigned int pier, pdg, point;
-
-	/* Fill raw data for each calibration pier */
-	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
-
-		pcinfo = &chinfo[pier].rf5112_info;
-
-		/* Allocate pd_curves for this cal pier */
-		chinfo[pier].pd_curves =
-				kcalloc(AR5K_EEPROM_N_PD_CURVES,
-					sizeof(struct ath5k_pdgain_info),
-					GFP_KERNEL);
-
-		if (!chinfo[pier].pd_curves)
-			return -ENOMEM;
-
-		/* Fill pd_curves */
-		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
-
-			u8 idx = pdgain_idx[pdg];
-			struct ath5k_pdgain_info *pd =
-					&chinfo[pier].pd_curves[idx];
-
-			/* Lowest gain curve (max power) */
-			if (pdg == 0) {
-				/* One more point for better accuracy */
-				pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS;
-
-				/* Allocate pd points for this curve */
-				pd->pd_step = kcalloc(pd->pd_points,
-						sizeof(u8), GFP_KERNEL);
-
-				if (!pd->pd_step)
-					return -ENOMEM;
-
-				pd->pd_pwr = kcalloc(pd->pd_points,
-						sizeof(s16), GFP_KERNEL);
-
-				if (!pd->pd_pwr)
-					return -ENOMEM;
-
-
-				/* Fill raw dataset
-				 * (all power levels are in 0.25dB units) */
-				pd->pd_step[0] = pcinfo->pcdac_x0[0];
-				pd->pd_pwr[0] = pcinfo->pwr_x0[0];
-
-				for (point = 1; point < pd->pd_points;
-				point++) {
-					/* Absolute values */
-					pd->pd_pwr[point] =
-						pcinfo->pwr_x0[point];
-
-					/* Deltas */
-					pd->pd_step[point] =
-						pd->pd_step[point - 1] +
-						pcinfo->pcdac_x0[point];
-				}
-
-				/* Set min power for this frequency */
-				chinfo[pier].min_pwr = pd->pd_pwr[0];
-
-			/* Highest gain curve (min power) */
-			} else if (pdg == 1) {
-
-				pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS;
-
-				/* Allocate pd points for this curve */
-				pd->pd_step = kcalloc(pd->pd_points,
-						sizeof(u8), GFP_KERNEL);
-
-				if (!pd->pd_step)
-					return -ENOMEM;
-
-				pd->pd_pwr = kcalloc(pd->pd_points,
-						sizeof(s16), GFP_KERNEL);
-
-				if (!pd->pd_pwr)
-					return -ENOMEM;
-
-				/* Fill raw dataset
-				 * (all power levels are in 0.25dB units) */
-				for (point = 0; point < pd->pd_points;
-				point++) {
-					/* Absolute values */
-					pd->pd_pwr[point] =
-						pcinfo->pwr_x3[point];
-
-					/* Fixed points */
-					pd->pd_step[point] =
-						pcinfo->pcdac_x3[point];
-				}
-
-				/* Since we have a higher gain curve
-				 * override min power */
-				chinfo[pier].min_pwr = pd->pd_pwr[0];
-			}
-		}
-	}
-
-	return 0;
-}
-
-/* Parse EEPROM data */
-static int
-ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
-	struct ath5k_chan_pcal_info *gen_chan_info;
-	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
-	u32 offset;
-	u8 i, c;
-	u16 val;
-	int ret;
-	u8 pd_gains = 0;
-
-	/* Count how many curves we have and
-	 * identify them (which one of the 4
-	 * available curves we have on each count).
-	 * Curves are stored from lower (x0) to
-	 * higher (x3) gain */
-	for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) {
-		/* ee_x_gain[mode] is x gain mask */
-		if ((ee->ee_x_gain[mode] >> i) & 0x1)
-			pdgain_idx[pd_gains++] = i;
-	}
-	ee->ee_pd_gains[mode] = pd_gains;
-
-	if (pd_gains == 0 || pd_gains > 2)
-		return -EINVAL;
-
-	switch (mode) {
-	case AR5K_EEPROM_MODE_11A:
-		/*
-		 * Read 5GHz EEPROM channels
-		 */
-		offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
-		ath5k_eeprom_init_11a_pcal_freq(ah, offset);
-
-		offset += AR5K_EEPROM_GROUP2_OFFSET;
-		gen_chan_info = ee->ee_pwr_cal_a;
-		break;
-	case AR5K_EEPROM_MODE_11B:
-		offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
-		if (AR5K_EEPROM_HDR_11A(ee->ee_header))
-			offset += AR5K_EEPROM_GROUP3_OFFSET;
-
-		/* NB: frequency piers parsed during mode init */
-		gen_chan_info = ee->ee_pwr_cal_b;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
-		if (AR5K_EEPROM_HDR_11A(ee->ee_header))
-			offset += AR5K_EEPROM_GROUP4_OFFSET;
-		else if (AR5K_EEPROM_HDR_11B(ee->ee_header))
-			offset += AR5K_EEPROM_GROUP2_OFFSET;
-
-		/* NB: frequency piers parsed during mode init */
-		gen_chan_info = ee->ee_pwr_cal_g;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
-		chan_pcal_info = &gen_chan_info[i].rf5112_info;
-
-		/* Power values in quarter dB
-		 * for the lower xpd gain curve
-		 * (0 dBm -> higher output power) */
-		for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
-			AR5K_EEPROM_READ(offset++, val);
-			chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff);
-			chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff);
-		}
-
-		/* PCDAC steps
-		 * corresponding to the above power
-		 * measurements */
-		AR5K_EEPROM_READ(offset++, val);
-		chan_pcal_info->pcdac_x0[1] = (val & 0x1f);
-		chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
-		chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
-
-		/* Power values in quarter dB
-		 * for the higher xpd gain curve
-		 * (18 dBm -> lower output power) */
-		AR5K_EEPROM_READ(offset++, val);
-		chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff);
-		chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff);
-
-		AR5K_EEPROM_READ(offset++, val);
-		chan_pcal_info->pwr_x3[2] = (val & 0xff);
-
-		/* PCDAC steps
-		 * corresponding to the above power
-		 * measurements (fixed) */
-		chan_pcal_info->pcdac_x3[0] = 20;
-		chan_pcal_info->pcdac_x3[1] = 35;
-		chan_pcal_info->pcdac_x3[2] = 63;
-
-		if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
-			chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f);
-
-			/* Last xpd0 power level is also channel maximum */
-			gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
-		} else {
-			chan_pcal_info->pcdac_x0[0] = 1;
-			gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff);
-		}
-
-	}
-
-	return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
-}
-
-
-/*
- * Read power calibration for RF2413 chips
- *
- * For RF2413 we have a Power to PDDAC table (Power Detector)
- * instead of a PCDAC and 4 pd gain curves for each calibrated channel.
- * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y
- * axis and looks like an exponential function like the RF5111 curve.
- *
- * To recreate the curves we read here the points and interpolate
- * later. Note that in most cases only 2 (higher and lower) curves are
- * used (like RF5112) but vendors have the oportunity to include all
- * 4 curves on eeprom. The final curve (higher power) has an extra
- * point for better accuracy like RF5112.
- */
-
-/* For RF2413 power calibration data doesn't start on a fixed location and
- * if a mode is not supported, it's section is missing -not zeroed-.
- * So we need to calculate the starting offset for each section by using
- * these two functions */
-
-/* Return the size of each section based on the mode and the number of pd
- * gains available (maximum 4). */
-static inline unsigned int
-ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
-{
-	static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
-	unsigned int sz;
-
-	sz = pdgains_size[ee->ee_pd_gains[mode] - 1];
-	sz *= ee->ee_n_piers[mode];
-
-	return sz;
-}
-
-/* Return the starting offset for a section based on the modes supported
- * and each section's size. */
-static unsigned int
-ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
-{
-	u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
-
-	switch(mode) {
-	case AR5K_EEPROM_MODE_11G:
-		if (AR5K_EEPROM_HDR_11B(ee->ee_header))
-			offset += ath5k_pdgains_size_2413(ee,
-					AR5K_EEPROM_MODE_11B) +
-					AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
-		/* fall through */
-	case AR5K_EEPROM_MODE_11B:
-		if (AR5K_EEPROM_HDR_11A(ee->ee_header))
-			offset += ath5k_pdgains_size_2413(ee,
-					AR5K_EEPROM_MODE_11A) +
-					AR5K_EEPROM_N_5GHZ_CHAN / 2;
-		/* fall through */
-	case AR5K_EEPROM_MODE_11A:
-		break;
-	default:
-		break;
-	}
-
-	return offset;
-}
-
-/* Convert RF2413 specific data to generic raw data
- * used by interpolation code */
-static int
-ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
-				struct ath5k_chan_pcal_info *chinfo)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info_rf2413 *pcinfo;
-	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
-	unsigned int pier, pdg, point;
-
-	/* Fill raw data for each calibration pier */
-	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
-
-		pcinfo = &chinfo[pier].rf2413_info;
-
-		/* Allocate pd_curves for this cal pier */
-		chinfo[pier].pd_curves =
-				kcalloc(AR5K_EEPROM_N_PD_CURVES,
-					sizeof(struct ath5k_pdgain_info),
-					GFP_KERNEL);
-
-		if (!chinfo[pier].pd_curves)
-			return -ENOMEM;
-
-		/* Fill pd_curves */
-		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
-
-			u8 idx = pdgain_idx[pdg];
-			struct ath5k_pdgain_info *pd =
-					&chinfo[pier].pd_curves[idx];
-
-			/* One more point for the highest power
-			 * curve (lowest gain) */
-			if (pdg == ee->ee_pd_gains[mode] - 1)
-				pd->pd_points = AR5K_EEPROM_N_PD_POINTS;
-			else
-				pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1;
-
-			/* Allocate pd points for this curve */
-			pd->pd_step = kcalloc(pd->pd_points,
-					sizeof(u8), GFP_KERNEL);
-
-			if (!pd->pd_step)
-				return -ENOMEM;
-
-			pd->pd_pwr = kcalloc(pd->pd_points,
-					sizeof(s16), GFP_KERNEL);
-
-			if (!pd->pd_pwr)
-				return -ENOMEM;
-
-			/* Fill raw dataset
-			 * convert all pwr levels to
-			 * quarter dB for RF5112 combatibility */
-			pd->pd_step[0] = pcinfo->pddac_i[pdg];
-			pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
-
-			for (point = 1; point < pd->pd_points; point++) {
-
-				pd->pd_pwr[point] = pd->pd_pwr[point - 1] +
-					2 * pcinfo->pwr[pdg][point - 1];
-
-				pd->pd_step[point] = pd->pd_step[point - 1] +
-						pcinfo->pddac[pdg][point - 1];
-
-			}
-
-			/* Highest gain curve -> min power */
-			if (pdg == 0)
-				chinfo[pier].min_pwr = pd->pd_pwr[0];
-
-			/* Lowest gain curve -> max power */
-			if (pdg == ee->ee_pd_gains[mode] - 1)
-				chinfo[pier].max_pwr =
-					pd->pd_pwr[pd->pd_points - 1];
-		}
-	}
-
-	return 0;
-}
-
-/* Parse EEPROM data */
-static int
-ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info_rf2413 *pcinfo;
-	struct ath5k_chan_pcal_info *chinfo;
-	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
-	u32 offset;
-	int idx, i, ret;
-	u16 val;
-	u8 pd_gains = 0;
-
-	/* Count how many curves we have and
-	 * identify them (which one of the 4
-	 * available curves we have on each count).
-	 * Curves are stored from higher to
-	 * lower gain so we go backwards */
-	for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
-		/* ee_x_gain[mode] is x gain mask */
-		if ((ee->ee_x_gain[mode] >> idx) & 0x1)
-			pdgain_idx[pd_gains++] = idx;
-
-	}
-	ee->ee_pd_gains[mode] = pd_gains;
-
-	if (pd_gains == 0)
-		return -EINVAL;
-
-	offset = ath5k_cal_data_offset_2413(ee, mode);
-	switch (mode) {
-	case AR5K_EEPROM_MODE_11A:
-		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
-			return 0;
-
-		ath5k_eeprom_init_11a_pcal_freq(ah, offset);
-		offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
-		chinfo = ee->ee_pwr_cal_a;
-		break;
-	case AR5K_EEPROM_MODE_11B:
-		if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
-			return 0;
-
-		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
-		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
-		chinfo = ee->ee_pwr_cal_b;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
-			return 0;
-
-		ath5k_eeprom_init_11bg_2413(ah, mode, offset);
-		offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
-		chinfo = ee->ee_pwr_cal_g;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (i = 0; i < ee->ee_n_piers[mode]; i++) {
-		pcinfo = &chinfo[i].rf2413_info;
-
-		/*
-		 * Read pwr_i, pddac_i and the first
-		 * 2 pd points (pwr, pddac)
-		 */
-		AR5K_EEPROM_READ(offset++, val);
-		pcinfo->pwr_i[0] = val & 0x1f;
-		pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
-		pcinfo->pwr[0][0] = (val >> 12) & 0xf;
-
-		AR5K_EEPROM_READ(offset++, val);
-		pcinfo->pddac[0][0] = val & 0x3f;
-		pcinfo->pwr[0][1] = (val >> 6) & 0xf;
-		pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
-
-		AR5K_EEPROM_READ(offset++, val);
-		pcinfo->pwr[0][2] = val & 0xf;
-		pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
-
-		pcinfo->pwr[0][3] = 0;
-		pcinfo->pddac[0][3] = 0;
-
-		if (pd_gains > 1) {
-			/*
-			 * Pd gain 0 is not the last pd gain
-			 * so it only has 2 pd points.
-			 * Continue wih pd gain 1.
-			 */
-			pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
-
-			pcinfo->pddac_i[1] = (val >> 15) & 0x1;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
-
-			pcinfo->pwr[1][0] = (val >> 6) & 0xf;
-			pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
-
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pwr[1][1] = val & 0xf;
-			pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
-			pcinfo->pwr[1][2] = (val >> 10) & 0xf;
-
-			pcinfo->pddac[1][2] = (val >> 14) & 0x3;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pddac[1][2] |= (val & 0xF) << 2;
-
-			pcinfo->pwr[1][3] = 0;
-			pcinfo->pddac[1][3] = 0;
-		} else if (pd_gains == 1) {
-			/*
-			 * Pd gain 0 is the last one so
-			 * read the extra point.
-			 */
-			pcinfo->pwr[0][3] = (val >> 10) & 0xf;
-
-			pcinfo->pddac[0][3] = (val >> 14) & 0x3;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pddac[0][3] |= (val & 0xF) << 2;
-		}
-
-		/*
-		 * Proceed with the other pd_gains
-		 * as above.
-		 */
-		if (pd_gains > 2) {
-			pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
-			pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
-
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pwr[2][0] = (val >> 0) & 0xf;
-			pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
-			pcinfo->pwr[2][1] = (val >> 10) & 0xf;
-
-			pcinfo->pddac[2][1] = (val >> 14) & 0x3;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pddac[2][1] |= (val & 0xF) << 2;
-
-			pcinfo->pwr[2][2] = (val >> 4) & 0xf;
-			pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
-
-			pcinfo->pwr[2][3] = 0;
-			pcinfo->pddac[2][3] = 0;
-		} else if (pd_gains == 2) {
-			pcinfo->pwr[1][3] = (val >> 4) & 0xf;
-			pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
-		}
-
-		if (pd_gains > 3) {
-			pcinfo->pwr_i[3] = (val >> 14) & 0x3;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
-
-			pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
-			pcinfo->pwr[3][0] = (val >> 10) & 0xf;
-			pcinfo->pddac[3][0] = (val >> 14) & 0x3;
-
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pddac[3][0] |= (val & 0xF) << 2;
-			pcinfo->pwr[3][1] = (val >> 4) & 0xf;
-			pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
-
-			pcinfo->pwr[3][2] = (val >> 14) & 0x3;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
-
-			pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
-			pcinfo->pwr[3][3] = (val >> 8) & 0xf;
-
-			pcinfo->pddac[3][3] = (val >> 12) & 0xF;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
-		} else if (pd_gains == 3) {
-			pcinfo->pwr[2][3] = (val >> 14) & 0x3;
-			AR5K_EEPROM_READ(offset++, val);
-			pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
-
-			pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
-		}
-	}
-
-	return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
-}
-
-
-/*
- * Read per rate target power (this is the maximum tx power
- * supported by the card). This info is used when setting
- * tx power, no matter the channel.
- *
- * This also works for v5 EEPROMs.
- */
-static int
-ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_rate_pcal_info *rate_pcal_info;
-	u8 *rate_target_pwr_num;
-	u32 offset;
-	u16 val;
-	int ret, i;
-
-	offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
-	rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
-	switch (mode) {
-	case AR5K_EEPROM_MODE_11A:
-		offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
-		rate_pcal_info = ee->ee_rate_tpwr_a;
-		ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
-		break;
-	case AR5K_EEPROM_MODE_11B:
-		offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
-		rate_pcal_info = ee->ee_rate_tpwr_b;
-		ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
-		rate_pcal_info = ee->ee_rate_tpwr_g;
-		ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Different freq mask for older eeproms (<= v3.2) */
-	if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) {
-		for (i = 0; i < (*rate_target_pwr_num); i++) {
-			AR5K_EEPROM_READ(offset++, val);
-			rate_pcal_info[i].freq =
-			    ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
-
-			rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
-			rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
-
-			AR5K_EEPROM_READ(offset++, val);
-
-			if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
-			    val == 0) {
-				(*rate_target_pwr_num) = i;
-				break;
-			}
-
-			rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
-			rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
-			rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
-		}
-	} else {
-		for (i = 0; i < (*rate_target_pwr_num); i++) {
-			AR5K_EEPROM_READ(offset++, val);
-			rate_pcal_info[i].freq =
-			    ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
-
-			rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
-			rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
-
-			AR5K_EEPROM_READ(offset++, val);
-
-			if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
-			    val == 0) {
-				(*rate_target_pwr_num) = i;
-				break;
-			}
-
-			rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
-			rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
-			rate_pcal_info[i].target_power_54 = (val & 0x3f);
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Read per channel calibration info from EEPROM
- *
- * This info is used to calibrate the baseband power table. Imagine
- * that for each channel there is a power curve that's hw specific
- * (depends on amplifier etc) and we try to "correct" this curve using
- * offests we pass on to phy chip (baseband -> before amplifier) so that
- * it can use accurate power values when setting tx power (takes amplifier's
- * performance on each channel into account).
- *
- * EEPROM provides us with the offsets for some pre-calibrated channels
- * and we have to interpolate to create the full table for these channels and
- * also the table for any channel.
- */
-static int
-ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	int (*read_pcal)(struct ath5k_hw *hw, int mode);
-	int mode;
-	int err;
-
-	if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) &&
-			(AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1))
-		read_pcal = ath5k_eeprom_read_pcal_info_5112;
-	else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) &&
-			(AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2))
-		read_pcal = ath5k_eeprom_read_pcal_info_2413;
-	else
-		read_pcal = ath5k_eeprom_read_pcal_info_5111;
-
-
-	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G;
-	mode++) {
-		err = read_pcal(ah, mode);
-		if (err)
-			return err;
-
-		err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
-static int
-ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info *chinfo;
-	u8 pier, pdg;
-
-	switch (mode) {
-	case AR5K_EEPROM_MODE_11A:
-		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
-			return 0;
-		chinfo = ee->ee_pwr_cal_a;
-		break;
-	case AR5K_EEPROM_MODE_11B:
-		if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
-			return 0;
-		chinfo = ee->ee_pwr_cal_b;
-		break;
-	case AR5K_EEPROM_MODE_11G:
-		if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
-			return 0;
-		chinfo = ee->ee_pwr_cal_g;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
-		if (!chinfo[pier].pd_curves)
-			continue;
-
-		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
-			struct ath5k_pdgain_info *pd =
-					&chinfo[pier].pd_curves[pdg];
-
-			if (pd != NULL) {
-				kfree(pd->pd_step);
-				kfree(pd->pd_pwr);
-			}
-		}
-
-		kfree(chinfo[pier].pd_curves);
-	}
-
-	return 0;
-}
-
-void
-ath5k_eeprom_detach(struct ath5k_hw *ah)
-{
-	u8 mode;
-
-	for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
-		ath5k_eeprom_free_pcal_info(ah, mode);
-}
-
-/* Read conformance test limits used for regulatory control */
-static int
-ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_edge_power *rep;
-	unsigned int fmask, pmask;
-	unsigned int ctl_mode;
-	int ret, i, j;
-	u32 offset;
-	u16 val;
-
-	pmask = AR5K_EEPROM_POWER_M;
-	fmask = AR5K_EEPROM_FREQ_M(ee->ee_version);
-	offset = AR5K_EEPROM_CTL(ee->ee_version);
-	ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version);
-	for (i = 0; i < ee->ee_ctls; i += 2) {
-		AR5K_EEPROM_READ(offset++, val);
-		ee->ee_ctl[i] = (val >> 8) & 0xff;
-		ee->ee_ctl[i + 1] = val & 0xff;
-	}
-
-	offset = AR5K_EEPROM_GROUP8_OFFSET;
-	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
-		offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) -
-			AR5K_EEPROM_GROUP5_OFFSET;
-	else
-		offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
-
-	rep = ee->ee_ctl_pwr;
-	for(i = 0; i < ee->ee_ctls; i++) {
-		switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
-		case AR5K_CTL_11A:
-		case AR5K_CTL_TURBO:
-			ctl_mode = AR5K_EEPROM_MODE_11A;
-			break;
-		default:
-			ctl_mode = AR5K_EEPROM_MODE_11G;
-			break;
-		}
-		if (ee->ee_ctl[i] == 0) {
-			if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3)
-				offset += 8;
-			else
-				offset += 7;
-			rep += AR5K_EEPROM_N_EDGES;
-			continue;
-		}
-		if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
-			for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
-				AR5K_EEPROM_READ(offset++, val);
-				rep[j].freq = (val >> 8) & fmask;
-				rep[j + 1].freq = val & fmask;
-			}
-			for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
-				AR5K_EEPROM_READ(offset++, val);
-				rep[j].edge = (val >> 8) & pmask;
-				rep[j].flag = (val >> 14) & 1;
-				rep[j + 1].edge = val & pmask;
-				rep[j + 1].flag = (val >> 6) & 1;
-			}
-		} else {
-			AR5K_EEPROM_READ(offset++, val);
-			rep[0].freq = (val >> 9) & fmask;
-			rep[1].freq = (val >> 2) & fmask;
-			rep[2].freq = (val << 5) & fmask;
-
-			AR5K_EEPROM_READ(offset++, val);
-			rep[2].freq |= (val >> 11) & 0x1f;
-			rep[3].freq = (val >> 4) & fmask;
-			rep[4].freq = (val << 3) & fmask;
-
-			AR5K_EEPROM_READ(offset++, val);
-			rep[4].freq |= (val >> 13) & 0x7;
-			rep[5].freq = (val >> 6) & fmask;
-			rep[6].freq = (val << 1) & fmask;
-
-			AR5K_EEPROM_READ(offset++, val);
-			rep[6].freq |= (val >> 15) & 0x1;
-			rep[7].freq = (val >> 8) & fmask;
-
-			rep[0].edge = (val >> 2) & pmask;
-			rep[1].edge = (val << 4) & pmask;
-
-			AR5K_EEPROM_READ(offset++, val);
-			rep[1].edge |= (val >> 12) & 0xf;
-			rep[2].edge = (val >> 6) & pmask;
-			rep[3].edge = val & pmask;
-
-			AR5K_EEPROM_READ(offset++, val);
-			rep[4].edge = (val >> 10) & pmask;
-			rep[5].edge = (val >> 4) & pmask;
-			rep[6].edge = (val << 2) & pmask;
-
-			AR5K_EEPROM_READ(offset++, val);
-			rep[6].edge |= (val >> 14) & 0x3;
-			rep[7].edge = (val >> 8) & pmask;
-		}
-		for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) {
-			rep[j].freq = ath5k_eeprom_bin2freq(ee,
-				rep[j].freq, ctl_mode);
-		}
-		rep += AR5K_EEPROM_N_EDGES;
-	}
-
-	return 0;
-}
-
-
-/*
- * Initialize eeprom power tables
- */
-int
-ath5k_eeprom_init(struct ath5k_hw *ah)
-{
-	int err;
-
-	err = ath5k_eeprom_init_header(ah);
-	if (err < 0)
-		return err;
-
-	err = ath5k_eeprom_init_modes(ah);
-	if (err < 0)
-		return err;
-
-	err = ath5k_eeprom_read_pcal_info(ah);
-	if (err < 0)
-		return err;
-
-	err = ath5k_eeprom_read_ctl_info(ah);
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-/*
- * Read the MAC address from eeprom
- */
-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
-{
-	u8 mac_d[ETH_ALEN] = {};
-	u32 total, offset;
-	u16 data;
-	int octet, ret;
-
-	ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
-	if (ret)
-		return ret;
-
-	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
-		ret = ath5k_hw_eeprom_read(ah, offset, &data);
-		if (ret)
-			return ret;
-
-		total += data;
-		mac_d[octet + 1] = data & 0xff;
-		mac_d[octet] = data >> 8;
-		octet += 2;
-	}
-
-	if (!total || total == 3 * 0xffff)
-		return -EINVAL;
-
-	memcpy(mac, mac_d, ETH_ALEN);
-
-	return 0;
-}
-
-bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
-{
-	u16 data;
-
-	ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
-
-	if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)
-		return true;
-	else
-		return false;
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/eeprom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/eeprom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,441 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*
- * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
- */
-#define AR5K_EEPROM_MAGIC		0x003d	/* EEPROM Magic number */
-#define AR5K_EEPROM_MAGIC_VALUE		0x5aa5	/* Default - found on EEPROM */
-#define AR5K_EEPROM_MAGIC_5212		0x0000145c /* 5212 */
-#define AR5K_EEPROM_MAGIC_5211		0x0000145b /* 5211 */
-#define AR5K_EEPROM_MAGIC_5210		0x0000145a /* 5210 */
-
-#define	AR5K_EEPROM_IS_HB63		0x000b	/* Talon detect */
-#define AR5K_EEPROM_REG_DOMAIN		0x00bf	/* EEPROM regdom */
-#define AR5K_EEPROM_CHECKSUM		0x00c0	/* EEPROM checksum */
-#define AR5K_EEPROM_INFO_BASE		0x00c0	/* EEPROM header */
-#define AR5K_EEPROM_INFO_MAX		(0x400 - AR5K_EEPROM_INFO_BASE)
-#define AR5K_EEPROM_INFO_CKSUM		0xffff
-#define AR5K_EEPROM_INFO(_n)		(AR5K_EEPROM_INFO_BASE + (_n))
-
-#define AR5K_EEPROM_VERSION		AR5K_EEPROM_INFO(1)	/* EEPROM Version */
-#define AR5K_EEPROM_VERSION_3_0		0x3000	/* No idea what's going on before this version */
-#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2Ghz (ar5211_rfregs) */
-#define AR5K_EEPROM_VERSION_3_2		0x3002	/* different frequency representation (eeprom_bin2freq) */
-#define AR5K_EEPROM_VERSION_3_3		0x3003	/* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
-#define AR5K_EEPROM_VERSION_3_4		0x3004	/* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
-#define AR5K_EEPROM_VERSION_4_0		0x4000	/* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
-#define AR5K_EEPROM_VERSION_4_1		0x4001	/* has ee_margin_tx_rx (eeprom_init) */
-#define AR5K_EEPROM_VERSION_4_2		0x4002	/* has ee_cck_ofdm_gain_delta (eeprom_init) */
-#define AR5K_EEPROM_VERSION_4_3		0x4003	/* power calibration changes */
-#define AR5K_EEPROM_VERSION_4_4		0x4004
-#define AR5K_EEPROM_VERSION_4_5		0x4005
-#define AR5K_EEPROM_VERSION_4_6		0x4006	/* has ee_scaled_cck_delta */
-#define AR5K_EEPROM_VERSION_4_7		0x3007	/* 4007 ? */
-#define AR5K_EEPROM_VERSION_4_9		0x4009	/* EAR futureproofing */
-#define AR5K_EEPROM_VERSION_5_0		0x5000	/* Has 2413 PDADC calibration etc */
-#define AR5K_EEPROM_VERSION_5_1		0x5001	/* Has capability values */
-#define AR5K_EEPROM_VERSION_5_3		0x5003	/* Has spur mitigation tables */
-
-#define AR5K_EEPROM_MODE_11A		0
-#define AR5K_EEPROM_MODE_11B		1
-#define AR5K_EEPROM_MODE_11G		2
-
-#define AR5K_EEPROM_HDR			AR5K_EEPROM_INFO(2)	/* Header that contains the device caps */
-#define AR5K_EEPROM_HDR_11A(_v)		(((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
-#define AR5K_EEPROM_HDR_11B(_v)		(((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
-#define AR5K_EEPROM_HDR_11G(_v)		(((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
-#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2Ghz (?) */
-#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v)	(((_v) >> 4) & 0x7f)	/* Max turbo power for a/XR mode (eeprom_init) */
-#define AR5K_EEPROM_HDR_DEVICE(_v)	(((_v) >> 11) & 0x7)
-#define AR5K_EEPROM_HDR_RFKILL(_v)	(((_v) >> 14) & 0x1)	/* Device has RFKill support */
-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5Ghz */
-
-#define AR5K_EEPROM_RFKILL_GPIO_SEL	0x0000001c
-#define AR5K_EEPROM_RFKILL_GPIO_SEL_S	2
-#define AR5K_EEPROM_RFKILL_POLARITY	0x00000002
-#define AR5K_EEPROM_RFKILL_POLARITY_S	1
-
-/* Newer EEPROMs are using a different offset */
-#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
-	(((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
-
-#define AR5K_EEPROM_ANT_GAIN(_v)	AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
-#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v)	((s8)(((_v) >> 8) & 0xff))
-#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v)	((s8)((_v) & 0xff))
-
-/* Misc values available since EEPROM 4.0 */
-#define AR5K_EEPROM_MISC0		AR5K_EEPROM_INFO(4)
-#define AR5K_EEPROM_EARSTART(_v)	((_v) & 0xfff)
-#define AR5K_EEPROM_HDR_XR2_DIS(_v)	(((_v) >> 12) & 0x1)
-#define AR5K_EEPROM_HDR_XR5_DIS(_v)	(((_v) >> 13) & 0x1)
-#define AR5K_EEPROM_EEMAP(_v)		(((_v) >> 14) & 0x3)
-
-#define AR5K_EEPROM_MISC1			AR5K_EEPROM_INFO(5)
-#define AR5K_EEPROM_TARGET_PWRSTART(_v)		((_v) & 0xfff)
-#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)		(((_v) >> 14) & 0x1)
-#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v)	(((_v) >> 15) & 0x1)
-
-#define AR5K_EEPROM_MISC2			AR5K_EEPROM_INFO(6)
-#define AR5K_EEPROM_EEP_FILE_VERSION(_v)	(((_v) >> 8) & 0xff)
-#define AR5K_EEPROM_EAR_FILE_VERSION(_v)	((_v) & 0xff)
-
-#define AR5K_EEPROM_MISC3		AR5K_EEPROM_INFO(7)
-#define AR5K_EEPROM_ART_BUILD_NUM(_v)	(((_v) >> 10) & 0x3f)
-#define AR5K_EEPROM_EAR_FILE_ID(_v)	((_v) & 0xff)
-
-#define AR5K_EEPROM_MISC4		AR5K_EEPROM_INFO(8)
-#define AR5K_EEPROM_CAL_DATA_START(_v)	(((_v) >> 4) & 0xfff)
-#define AR5K_EEPROM_MASK_R0(_v)		(((_v) >> 2) & 0x3)
-#define AR5K_EEPROM_MASK_R1(_v)		((_v) & 0x3)
-
-#define AR5K_EEPROM_MISC5		AR5K_EEPROM_INFO(9)
-#define AR5K_EEPROM_COMP_DIS(_v)	((_v) & 0x1)
-#define AR5K_EEPROM_AES_DIS(_v)		(((_v) >> 1) & 0x1)
-#define AR5K_EEPROM_FF_DIS(_v)		(((_v) >> 2) & 0x1)
-#define AR5K_EEPROM_BURST_DIS(_v)	(((_v) >> 3) & 0x1)
-#define AR5K_EEPROM_MAX_QCU(_v)		(((_v) >> 4) & 0xf)
-#define AR5K_EEPROM_HEAVY_CLIP_EN(_v)	(((_v) >> 8) & 0x1)
-#define AR5K_EEPROM_KEY_CACHE_SIZE(_v)	(((_v) >> 12) & 0xf)
-
-#define AR5K_EEPROM_MISC6		AR5K_EEPROM_INFO(10)
-#define AR5K_EEPROM_TX_CHAIN_DIS	((_v) & 0x8)
-#define AR5K_EEPROM_RX_CHAIN_DIS	(((_v) >> 3) & 0x8)
-#define AR5K_EEPROM_FCC_MID_EN		(((_v) >> 6) & 0x1)
-#define AR5K_EEPROM_JAP_U1EVEN_EN	(((_v) >> 7) & 0x1)
-#define AR5K_EEPROM_JAP_U2_EN		(((_v) >> 8) & 0x1)
-#define AR5K_EEPROM_JAP_U1ODD_EN	(((_v) >> 9) & 0x1)
-#define AR5K_EEPROM_JAP_11A_NEW_EN	(((_v) >> 10) & 0x1)
-
-/* calibration settings */
-#define AR5K_EEPROM_MODES_11A(_v)	AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
-#define AR5K_EEPROM_MODES_11B(_v)	AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
-#define AR5K_EEPROM_MODES_11G(_v)	AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
-#define AR5K_EEPROM_CTL(_v)		AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128)	/* Conformance test limits */
-#define AR5K_EEPROM_GROUPS_START(_v)	AR5K_EEPROM_OFF(_v, 0x0100, 0x0150)	/* Start of Groups */
-#define AR5K_EEPROM_GROUP1_OFFSET	0x0
-#define AR5K_EEPROM_GROUP2_OFFSET	0x5
-#define AR5K_EEPROM_GROUP3_OFFSET	0x37
-#define AR5K_EEPROM_GROUP4_OFFSET	0x46
-#define AR5K_EEPROM_GROUP5_OFFSET	0x55
-#define AR5K_EEPROM_GROUP6_OFFSET	0x65
-#define AR5K_EEPROM_GROUP7_OFFSET	0x69
-#define AR5K_EEPROM_GROUP8_OFFSET	0x6f
-
-#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
-								AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
-#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
-								AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
-#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
-								AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
-
-/* [3.1 - 3.3] */
-#define AR5K_EEPROM_OBDB0_2GHZ		0x00ec
-#define AR5K_EEPROM_OBDB1_2GHZ		0x00ed
-
-#define AR5K_EEPROM_PROTECT		0x003f	/* EEPROM protect status */
-#define AR5K_EEPROM_PROTECT_RD_0_31	0x0001	/* Read protection bit for offsets 0x0 - 0x1f */
-#define AR5K_EEPROM_PROTECT_WR_0_31	0x0002	/* Write protection bit for offsets 0x0 - 0x1f */
-#define AR5K_EEPROM_PROTECT_RD_32_63	0x0004	/* 0x20 - 0x3f */
-#define AR5K_EEPROM_PROTECT_WR_32_63	0x0008
-#define AR5K_EEPROM_PROTECT_RD_64_127	0x0010	/* 0x40 - 0x7f */
-#define AR5K_EEPROM_PROTECT_WR_64_127	0x0020
-#define AR5K_EEPROM_PROTECT_RD_128_191	0x0040	/* 0x80 - 0xbf (regdom) */
-#define AR5K_EEPROM_PROTECT_WR_128_191	0x0080
-#define AR5K_EEPROM_PROTECT_RD_192_207	0x0100	/* 0xc0 - 0xcf */
-#define AR5K_EEPROM_PROTECT_WR_192_207	0x0200
-#define AR5K_EEPROM_PROTECT_RD_208_223	0x0400	/* 0xd0 - 0xdf */
-#define AR5K_EEPROM_PROTECT_WR_208_223	0x0800
-#define AR5K_EEPROM_PROTECT_RD_224_239	0x1000	/* 0xe0 - 0xef */
-#define AR5K_EEPROM_PROTECT_WR_224_239	0x2000
-#define AR5K_EEPROM_PROTECT_RD_240_255	0x4000	/* 0xf0 - 0xff */
-#define AR5K_EEPROM_PROTECT_WR_240_255	0x8000
-
-/* Some EEPROM defines */
-#define AR5K_EEPROM_EEP_SCALE		100
-#define AR5K_EEPROM_EEP_DELTA		10
-#define AR5K_EEPROM_N_MODES		3
-#define AR5K_EEPROM_N_5GHZ_CHAN		10
-#define AR5K_EEPROM_N_2GHZ_CHAN		3
-#define AR5K_EEPROM_N_2GHZ_CHAN_2413	4
-#define	AR5K_EEPROM_N_2GHZ_CHAN_MAX	4
-#define AR5K_EEPROM_MAX_CHAN		10
-#define AR5K_EEPROM_N_PWR_POINTS_5111	11
-#define AR5K_EEPROM_N_PCDAC		11
-#define AR5K_EEPROM_N_PHASE_CAL		5
-#define AR5K_EEPROM_N_TEST_FREQ		8
-#define AR5K_EEPROM_N_EDGES		8
-#define AR5K_EEPROM_N_INTERCEPTS	11
-#define AR5K_EEPROM_FREQ_M(_v)		AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
-#define AR5K_EEPROM_PCDAC_M		0x3f
-#define AR5K_EEPROM_PCDAC_START		1
-#define AR5K_EEPROM_PCDAC_STOP		63
-#define AR5K_EEPROM_PCDAC_STEP		1
-#define AR5K_EEPROM_NON_EDGE_M		0x40
-#define AR5K_EEPROM_CHANNEL_POWER	8
-#define AR5K_EEPROM_N_OBDB		4
-#define AR5K_EEPROM_OBDB_DIS		0xffff
-#define AR5K_EEPROM_CHANNEL_DIS		0xff
-#define AR5K_EEPROM_SCALE_OC_DELTA(_x)	(((_x) * 2) / 10)
-#define AR5K_EEPROM_N_CTLS(_v)		AR5K_EEPROM_OFF(_v, 16, 32)
-#define AR5K_EEPROM_MAX_CTLS		32
-#define AR5K_EEPROM_N_PD_CURVES		4
-#define AR5K_EEPROM_N_XPD0_POINTS	4
-#define AR5K_EEPROM_N_XPD3_POINTS	3
-#define AR5K_EEPROM_N_PD_GAINS		4
-#define AR5K_EEPROM_N_PD_POINTS		5
-#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ	35
-#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ	55
-#define AR5K_EEPROM_POWER_M		0x3f
-#define AR5K_EEPROM_POWER_MIN		0
-#define AR5K_EEPROM_POWER_MAX		3150
-#define AR5K_EEPROM_POWER_STEP		50
-#define AR5K_EEPROM_POWER_TABLE_SIZE	64
-#define AR5K_EEPROM_N_POWER_LOC_11B	4
-#define AR5K_EEPROM_N_POWER_LOC_11G	6
-#define AR5K_EEPROM_I_GAIN		10
-#define AR5K_EEPROM_CCK_OFDM_DELTA	15
-#define AR5K_EEPROM_N_IQ_CAL		2
-
-#define AR5K_EEPROM_READ(_o, _v) do {			\
-	ret = ath5k_hw_eeprom_read(ah, (_o), &(_v));	\
-	if (ret)					\
-		return ret;				\
-} while (0)
-
-#define AR5K_EEPROM_READ_HDR(_o, _v)					\
-	AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v);	\
-
-enum ath5k_ant_setting {
-	AR5K_ANT_VARIABLE	= 0,	/* variable by programming */
-	AR5K_ANT_FIXED_A	= 1,	/* fixed to 11a frequencies */
-	AR5K_ANT_FIXED_B	= 2,	/* fixed to 11b frequencies */
-	AR5K_ANT_MAX		= 3,
-};
-
-enum ath5k_ctl_mode {
-	AR5K_CTL_11A = 0,
-	AR5K_CTL_11B = 1,
-	AR5K_CTL_11G = 2,
-	AR5K_CTL_TURBO = 3,
-	AR5K_CTL_TURBOG = 4,
-	AR5K_CTL_2GHT20 = 5,
-	AR5K_CTL_5GHT20 = 6,
-	AR5K_CTL_2GHT40 = 7,
-	AR5K_CTL_5GHT40 = 8,
-	AR5K_CTL_MODE_M = 15,
-};
-
-/* Default CTL ids for the 3 main reg domains.
- * Atheros only uses these by default but vendors
- * can have up to 32 different CTLs for different
- * scenarios. Note that theese values are ORed with
- * the mode id (above) so we can have up to 24 CTL
- * datasets out of these 3 main regdomains. That leaves
- * 8 ids that can be used by vendors and since 0x20 is
- * missing from HAL sources i guess this is the set of
- * custom CTLs vendors can use. */
-#define	AR5K_CTL_FCC	0x10
-#define	AR5K_CTL_CUSTOM	0x20
-#define	AR5K_CTL_ETSI	0x30
-#define	AR5K_CTL_MKK	0x40
-
-/* Indicates a CTL with only mode set and
- * no reg domain mapping, such CTLs are used
- * for world roaming domains or simply when
- * a reg domain is not set */
-#define	AR5K_CTL_NO_REGDOMAIN	0xf0
-
-/* Indicates an empty (invalid) CTL */
-#define AR5K_CTL_NO_CTL		0xff
-
-/* Per channel calibration data, used for power table setup */
-struct ath5k_chan_pcal_info_rf5111 {
-	/* Power levels in half dbm units
-	 * for one power curve. */
-	u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
-	/* PCDAC table steps
-	 * for the above values */
-	u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
-	/* Starting PCDAC step */
-	u8 pcdac_min;
-	/* Final PCDAC step */
-	u8 pcdac_max;
-};
-
-struct ath5k_chan_pcal_info_rf5112 {
-	/* Power levels in quarter dBm units
-	 * for lower (0) and higher (3)
-	 * level curves in 0.25dB units */
-	s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
-	s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
-	/* PCDAC table steps
-	 * for the above values */
-	u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
-	u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
-};
-
-struct ath5k_chan_pcal_info_rf2413 {
-	/* Starting pwr/pddac values */
-	s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
-	u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
-	/* (pwr,pddac) points
-	 * power levels in 0.5dB units */
-	s8 pwr[AR5K_EEPROM_N_PD_GAINS]
-		[AR5K_EEPROM_N_PD_POINTS];
-	u8 pddac[AR5K_EEPROM_N_PD_GAINS]
-		[AR5K_EEPROM_N_PD_POINTS];
-};
-
-enum ath5k_powertable_type {
-	AR5K_PWRTABLE_PWR_TO_PCDAC = 0,
-	AR5K_PWRTABLE_LINEAR_PCDAC = 1,
-	AR5K_PWRTABLE_PWR_TO_PDADC = 2,
-};
-
-struct ath5k_pdgain_info {
-	u8 pd_points;
-	u8 *pd_step;
-	/* Power values are in
-	 * 0.25dB units */
-	s16 *pd_pwr;
-};
-
-struct ath5k_chan_pcal_info {
-	/* Frequency */
-	u16	freq;
-	/* Tx power boundaries */
-	s16	max_pwr;
-	s16	min_pwr;
-	union {
-		struct ath5k_chan_pcal_info_rf5111 rf5111_info;
-		struct ath5k_chan_pcal_info_rf5112 rf5112_info;
-		struct ath5k_chan_pcal_info_rf2413 rf2413_info;
-	};
-	/* Raw values used by phy code
-	 * Curves are stored in order from lower
-	 * gain to higher gain (max txpower -> min txpower) */
-	struct ath5k_pdgain_info *pd_curves;
-};
-
-/* Per rate calibration data for each mode,
- * used for rate power table setup.
- * Note: Values in 0.5dB units */
-struct ath5k_rate_pcal_info {
-	u16	freq; /* Frequency */
-	/* Power level for 6-24Mbit/s rates or
-	 * 1Mb rate */
-	u16	target_power_6to24;
-	/* Power level for 36Mbit rate or
-	 * 2Mb rate */
-	u16	target_power_36;
-	/* Power level for 48Mbit rate or
-	 * 5.5Mbit rate */
-	u16	target_power_48;
-	/* Power level for 54Mbit rate or
-	 * 11Mbit rate */
-	u16	target_power_54;
-};
-
-/* Power edges for conformance test limits */
-struct ath5k_edge_power {
-	u16 freq;
-	u16 edge; /* in half dBm */
-	bool flag;
-};
-
-/* EEPROM calibration data */
-struct ath5k_eeprom_info {
-
-	/* Header information */
-	u16	ee_magic;
-	u16	ee_protect;
-	u16	ee_regdomain;
-	u16	ee_version;
-	u16	ee_header;
-	u16	ee_ant_gain;
-	u16	ee_misc0;
-	u16	ee_misc1;
-	u16	ee_misc2;
-	u16	ee_misc3;
-	u16	ee_misc4;
-	u16	ee_misc5;
-	u16	ee_misc6;
-	u16	ee_cck_ofdm_gain_delta;
-	u16	ee_cck_ofdm_power_delta;
-	u16	ee_scaled_cck_delta;
-
-	/* RF Calibration settings (reset, rfregs) */
-	u16	ee_i_cal[AR5K_EEPROM_N_MODES];
-	u16	ee_q_cal[AR5K_EEPROM_N_MODES];
-	u16	ee_fixed_bias[AR5K_EEPROM_N_MODES];
-	u16	ee_turbo_max_power[AR5K_EEPROM_N_MODES];
-	u16	ee_xr_power[AR5K_EEPROM_N_MODES];
-	u16	ee_switch_settling[AR5K_EEPROM_N_MODES];
-	u16	ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
-	u16	ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
-	u16	ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
-	u16	ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
-	u16	ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
-	u16	ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
-	u16	ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
-	u16	ee_thr_62[AR5K_EEPROM_N_MODES];
-	u16	ee_xlna_gain[AR5K_EEPROM_N_MODES];
-	u16	ee_xpd[AR5K_EEPROM_N_MODES];
-	u16	ee_x_gain[AR5K_EEPROM_N_MODES];
-	u16	ee_i_gain[AR5K_EEPROM_N_MODES];
-	u16	ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
-	u16	ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
-	u16	ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
-	u16	ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
-
-	/* Power calibration data */
-	u16	ee_false_detect[AR5K_EEPROM_N_MODES];
-
-	/* Number of pd gain curves per mode */
-	u8	ee_pd_gains[AR5K_EEPROM_N_MODES];
-	/* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */
-	u8	ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS];
-
-	u8	ee_n_piers[AR5K_EEPROM_N_MODES];
-	struct ath5k_chan_pcal_info	ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
-	struct ath5k_chan_pcal_info	ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
-	struct ath5k_chan_pcal_info	ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
-
-	/* Per rate target power levels */
-	u8	ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
-	struct ath5k_rate_pcal_info	ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
-	struct ath5k_rate_pcal_info	ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
-	struct ath5k_rate_pcal_info	ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
-
-	/* Conformance test limits (Unused) */
-	u8	ee_ctls;
-	u8	ee_ctl[AR5K_EEPROM_MAX_CTLS];
-	struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
-
-	/* Noise Floor Calibration settings */
-	s16	ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
-	s8	ee_adc_desired_size[AR5K_EEPROM_N_MODES];
-	s8	ee_pga_desired_size[AR5K_EEPROM_N_MODES];
-	s8	ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
-	s8	ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
-	s8	ee_pd_gain_overlap;
-
-	u32	ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
-};
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/gpio.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/gpio.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/gpio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/****************\
-  GPIO Functions
-\****************/
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*
- * Set led state
- */
-void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
-{
-	u32 led;
-	/*5210 has different led mode handling*/
-	u32 led_5210;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/*Reset led status*/
-	if (ah->ah_version != AR5K_AR5210)
-		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
-			AR5K_PCICFG_LEDMODE |  AR5K_PCICFG_LED);
-	else
-		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
-
-	/*
-	 * Some blinking values, define at your wish
-	 */
-	switch (state) {
-	case AR5K_LED_SCAN:
-	case AR5K_LED_AUTH:
-		led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
-		led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
-		break;
-
-	case AR5K_LED_INIT:
-		led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
-		led_5210 = AR5K_PCICFG_LED_PEND;
-		break;
-
-	case AR5K_LED_ASSOC:
-	case AR5K_LED_RUN:
-		led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
-		led_5210 = AR5K_PCICFG_LED_ASSOC;
-		break;
-
-	default:
-		led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
-		led_5210 = AR5K_PCICFG_LED_PEND;
-		break;
-	}
-
-	/*Write new status to the register*/
-	if (ah->ah_version != AR5K_AR5210)
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
-	else
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
-}
-
-/*
- * Set GPIO inputs
- */
-int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (gpio >= AR5K_NUM_GPIO)
-		return -EINVAL;
-
-	ath5k_hw_reg_write(ah,
-		(ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
-		| AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
-
-	return 0;
-}
-
-/*
- * Set GPIO outputs
- */
-int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (gpio >= AR5K_NUM_GPIO)
-		return -EINVAL;
-
-	ath5k_hw_reg_write(ah,
-		(ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
-		| AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
-
-	return 0;
-}
-
-/*
- * Get GPIO state
- */
-u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (gpio >= AR5K_NUM_GPIO)
-		return 0xffffffff;
-
-	/* GPIO input magic */
-	return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
-		0x1;
-}
-
-/*
- * Set GPIO state
- */
-int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
-{
-	u32 data;
-	ATH5K_TRACE(ah->ah_sc);
-
-	if (gpio >= AR5K_NUM_GPIO)
-		return -EINVAL;
-
-	/* GPIO output magic */
-	data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
-
-	data &= ~(1 << gpio);
-	data |= (val & 1) << gpio;
-
-	ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
-
-	return 0;
-}
-
-/*
- * Initialize the GPIO interrupt (RFKill switch)
- */
-void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
-		u32 interrupt_level)
-{
-	u32 data;
-
-	ATH5K_TRACE(ah->ah_sc);
-	if (gpio >= AR5K_NUM_GPIO)
-		return;
-
-	/*
-	 * Set the GPIO interrupt
-	 */
-	data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
-		~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
-		AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
-		(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
-
-	ath5k_hw_reg_write(ah, interrupt_level ? data :
-		(data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
-
-	ah->ah_imr |= AR5K_IMR_GPIO;
-
-	/* Enable GPIO interrupts */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/initvals.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/initvals.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/initvals.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/initvals.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1557 +0,0 @@
-/*
- * Initial register settings functions
- *
- * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*
- * Mode-independent initial register writes
- */
-
-struct ath5k_ini {
-	u16	ini_register;
-	u32	ini_value;
-
-	enum {
-		AR5K_INI_WRITE = 0,	/* Default */
-		AR5K_INI_READ = 1,	/* Cleared on read */
-	} ini_mode;
-};
-
-/*
- * Mode specific initial register values
- */
-
-struct ath5k_ini_mode {
-	u16	mode_register;
-	u32	mode_value[5];
-};
-
-/* Initial register settings for AR5210 */
-static const struct ath5k_ini ar5210_ini[] = {
-	/* PCU and MAC registers */
-	{ AR5K_NOQCU_TXDP0,	0 },
-	{ AR5K_NOQCU_TXDP1,	0 },
-	{ AR5K_RXDP,		0 },
-	{ AR5K_CR,		0 },
-	{ AR5K_ISR,		0, AR5K_INI_READ },
-	{ AR5K_IMR,		0 },
-	{ AR5K_IER,		AR5K_IER_DISABLE },
-	{ AR5K_BSR,		0, AR5K_INI_READ },
-	{ AR5K_TXCFG,		AR5K_DMASIZE_128B },
-	{ AR5K_RXCFG,		AR5K_DMASIZE_128B },
-	{ AR5K_CFG,		AR5K_INIT_CFG },
-	{ AR5K_TOPS,		8 },
-	{ AR5K_RXNOFRM,		8 },
-	{ AR5K_RPGTO,		0 },
-	{ AR5K_TXNOFRM,		0 },
-	{ AR5K_SFR,		0 },
-	{ AR5K_MIBC,		0 },
-	{ AR5K_MISC,		0 },
-	{ AR5K_RX_FILTER_5210,	0 },
-	{ AR5K_MCAST_FILTER0_5210, 0 },
-	{ AR5K_MCAST_FILTER1_5210, 0 },
-	{ AR5K_TX_MASK0,	0 },
-	{ AR5K_TX_MASK1,	0 },
-	{ AR5K_CLR_TMASK,	0 },
-	{ AR5K_TRIG_LVL,	AR5K_TUNE_MIN_TX_FIFO_THRES },
-	{ AR5K_DIAG_SW_5210,	0 },
-	{ AR5K_RSSI_THR,	AR5K_TUNE_RSSI_THRES },
-	{ AR5K_TSF_L32_5210,	0 },
-	{ AR5K_TIMER0_5210,	0 },
-	{ AR5K_TIMER1_5210,	0xffffffff },
-	{ AR5K_TIMER2_5210,	0xffffffff },
-	{ AR5K_TIMER3_5210,	1 },
-	{ AR5K_CFP_DUR_5210,	0 },
-	{ AR5K_CFP_PERIOD_5210,	0 },
-	/* PHY registers */
-	{ AR5K_PHY(0),	0x00000047 },
-	{ AR5K_PHY_AGC,	0x00000000 },
-	{ AR5K_PHY(3),	0x09848ea6 },
-	{ AR5K_PHY(4),	0x3d32e000 },
-	{ AR5K_PHY(5),	0x0000076b },
-	{ AR5K_PHY_ACT,	AR5K_PHY_ACT_DISABLE },
-	{ AR5K_PHY(8),	0x02020200 },
-	{ AR5K_PHY(9),	0x00000e0e },
-	{ AR5K_PHY(10),	0x0a020201 },
-	{ AR5K_PHY(11),	0x00036ffc },
-	{ AR5K_PHY(12),	0x00000000 },
-	{ AR5K_PHY(13),	0x00000e0e },
-	{ AR5K_PHY(14),	0x00000007 },
-	{ AR5K_PHY(15),	0x00020100 },
-	{ AR5K_PHY(16),	0x89630000 },
-	{ AR5K_PHY(17),	0x1372169c },
-	{ AR5K_PHY(18),	0x0018b633 },
-	{ AR5K_PHY(19),	0x1284613c },
-	{ AR5K_PHY(20),	0x0de8b8e0 },
-	{ AR5K_PHY(21),	0x00074859 },
-	{ AR5K_PHY(22),	0x7e80beba },
-	{ AR5K_PHY(23),	0x313a665e },
-	{ AR5K_PHY_AGCCTL, 0x00001d08 },
-	{ AR5K_PHY(25),	0x0001ce00 },
-	{ AR5K_PHY(26),	0x409a4190 },
-	{ AR5K_PHY(28),	0x0000000f },
-	{ AR5K_PHY(29),	0x00000080 },
-	{ AR5K_PHY(30),	0x00000004 },
-	{ AR5K_PHY(31),	0x00000018 }, 	/* 0x987c */
-	{ AR5K_PHY(64),	0x00000000 }, 	/* 0x9900 */
-	{ AR5K_PHY(65),	0x00000000 },
-	{ AR5K_PHY(66),	0x00000000 },
-	{ AR5K_PHY(67),	0x00800000 },
-	{ AR5K_PHY(68),	0x00000003 },
-	/* BB gain table (64bytes) */
-	{ AR5K_BB_GAIN(0), 0x00000000 },
-	{ AR5K_BB_GAIN(1), 0x00000020 },
-	{ AR5K_BB_GAIN(2), 0x00000010 },
-	{ AR5K_BB_GAIN(3), 0x00000030 },
-	{ AR5K_BB_GAIN(4), 0x00000008 },
-	{ AR5K_BB_GAIN(5), 0x00000028 },
-	{ AR5K_BB_GAIN(6), 0x00000028 },
-	{ AR5K_BB_GAIN(7), 0x00000004 },
-	{ AR5K_BB_GAIN(8), 0x00000024 },
-	{ AR5K_BB_GAIN(9), 0x00000014 },
-	{ AR5K_BB_GAIN(10), 0x00000034 },
-	{ AR5K_BB_GAIN(11), 0x0000000c },
-	{ AR5K_BB_GAIN(12), 0x0000002c },
-	{ AR5K_BB_GAIN(13), 0x00000002 },
-	{ AR5K_BB_GAIN(14), 0x00000022 },
-	{ AR5K_BB_GAIN(15), 0x00000012 },
-	{ AR5K_BB_GAIN(16), 0x00000032 },
-	{ AR5K_BB_GAIN(17), 0x0000000a },
-	{ AR5K_BB_GAIN(18), 0x0000002a },
-	{ AR5K_BB_GAIN(19), 0x00000001 },
-	{ AR5K_BB_GAIN(20), 0x00000021 },
-	{ AR5K_BB_GAIN(21), 0x00000011 },
-	{ AR5K_BB_GAIN(22), 0x00000031 },
-	{ AR5K_BB_GAIN(23), 0x00000009 },
-	{ AR5K_BB_GAIN(24), 0x00000029 },
-	{ AR5K_BB_GAIN(25), 0x00000005 },
-	{ AR5K_BB_GAIN(26), 0x00000025 },
-	{ AR5K_BB_GAIN(27), 0x00000015 },
-	{ AR5K_BB_GAIN(28), 0x00000035 },
-	{ AR5K_BB_GAIN(29), 0x0000000d },
-	{ AR5K_BB_GAIN(30), 0x0000002d },
-	{ AR5K_BB_GAIN(31), 0x00000003 },
-	{ AR5K_BB_GAIN(32), 0x00000023 },
-	{ AR5K_BB_GAIN(33), 0x00000013 },
-	{ AR5K_BB_GAIN(34), 0x00000033 },
-	{ AR5K_BB_GAIN(35), 0x0000000b },
-	{ AR5K_BB_GAIN(36), 0x0000002b },
-	{ AR5K_BB_GAIN(37), 0x00000007 },
-	{ AR5K_BB_GAIN(38), 0x00000027 },
-	{ AR5K_BB_GAIN(39), 0x00000017 },
-	{ AR5K_BB_GAIN(40), 0x00000037 },
-	{ AR5K_BB_GAIN(41), 0x0000000f },
-	{ AR5K_BB_GAIN(42), 0x0000002f },
-	{ AR5K_BB_GAIN(43), 0x0000002f },
-	{ AR5K_BB_GAIN(44), 0x0000002f },
-	{ AR5K_BB_GAIN(45), 0x0000002f },
-	{ AR5K_BB_GAIN(46), 0x0000002f },
-	{ AR5K_BB_GAIN(47), 0x0000002f },
-	{ AR5K_BB_GAIN(48), 0x0000002f },
-	{ AR5K_BB_GAIN(49), 0x0000002f },
-	{ AR5K_BB_GAIN(50), 0x0000002f },
-	{ AR5K_BB_GAIN(51), 0x0000002f },
-	{ AR5K_BB_GAIN(52), 0x0000002f },
-	{ AR5K_BB_GAIN(53), 0x0000002f },
-	{ AR5K_BB_GAIN(54), 0x0000002f },
-	{ AR5K_BB_GAIN(55), 0x0000002f },
-	{ AR5K_BB_GAIN(56), 0x0000002f },
-	{ AR5K_BB_GAIN(57), 0x0000002f },
-	{ AR5K_BB_GAIN(58), 0x0000002f },
-	{ AR5K_BB_GAIN(59), 0x0000002f },
-	{ AR5K_BB_GAIN(60), 0x0000002f },
-	{ AR5K_BB_GAIN(61), 0x0000002f },
-	{ AR5K_BB_GAIN(62), 0x0000002f },
-	{ AR5K_BB_GAIN(63), 0x0000002f },
-	/* 5110 RF gain table (64btes) */
-	{ AR5K_RF_GAIN(0), 0x0000001d },
-	{ AR5K_RF_GAIN(1), 0x0000005d },
-	{ AR5K_RF_GAIN(2), 0x0000009d },
-	{ AR5K_RF_GAIN(3), 0x000000dd },
-	{ AR5K_RF_GAIN(4), 0x0000011d },
-	{ AR5K_RF_GAIN(5), 0x00000021 },
-	{ AR5K_RF_GAIN(6), 0x00000061 },
-	{ AR5K_RF_GAIN(7), 0x000000a1 },
-	{ AR5K_RF_GAIN(8), 0x000000e1 },
-	{ AR5K_RF_GAIN(9), 0x00000031 },
-	{ AR5K_RF_GAIN(10), 0x00000071 },
-	{ AR5K_RF_GAIN(11), 0x000000b1 },
-	{ AR5K_RF_GAIN(12), 0x0000001c },
-	{ AR5K_RF_GAIN(13), 0x0000005c },
-	{ AR5K_RF_GAIN(14), 0x00000029 },
-	{ AR5K_RF_GAIN(15), 0x00000069 },
-	{ AR5K_RF_GAIN(16), 0x000000a9 },
-	{ AR5K_RF_GAIN(17), 0x00000020 },
-	{ AR5K_RF_GAIN(18), 0x00000019 },
-	{ AR5K_RF_GAIN(19), 0x00000059 },
-	{ AR5K_RF_GAIN(20), 0x00000099 },
-	{ AR5K_RF_GAIN(21), 0x00000030 },
-	{ AR5K_RF_GAIN(22), 0x00000005 },
-	{ AR5K_RF_GAIN(23), 0x00000025 },
-	{ AR5K_RF_GAIN(24), 0x00000065 },
-	{ AR5K_RF_GAIN(25), 0x000000a5 },
-	{ AR5K_RF_GAIN(26), 0x00000028 },
-	{ AR5K_RF_GAIN(27), 0x00000068 },
-	{ AR5K_RF_GAIN(28), 0x0000001f },
-	{ AR5K_RF_GAIN(29), 0x0000001e },
-	{ AR5K_RF_GAIN(30), 0x00000018 },
-	{ AR5K_RF_GAIN(31), 0x00000058 },
-	{ AR5K_RF_GAIN(32), 0x00000098 },
-	{ AR5K_RF_GAIN(33), 0x00000003 },
-	{ AR5K_RF_GAIN(34), 0x00000004 },
-	{ AR5K_RF_GAIN(35), 0x00000044 },
-	{ AR5K_RF_GAIN(36), 0x00000084 },
-	{ AR5K_RF_GAIN(37), 0x00000013 },
-	{ AR5K_RF_GAIN(38), 0x00000012 },
-	{ AR5K_RF_GAIN(39), 0x00000052 },
-	{ AR5K_RF_GAIN(40), 0x00000092 },
-	{ AR5K_RF_GAIN(41), 0x000000d2 },
-	{ AR5K_RF_GAIN(42), 0x0000002b },
-	{ AR5K_RF_GAIN(43), 0x0000002a },
-	{ AR5K_RF_GAIN(44), 0x0000006a },
-	{ AR5K_RF_GAIN(45), 0x000000aa },
-	{ AR5K_RF_GAIN(46), 0x0000001b },
-	{ AR5K_RF_GAIN(47), 0x0000001a },
-	{ AR5K_RF_GAIN(48), 0x0000005a },
-	{ AR5K_RF_GAIN(49), 0x0000009a },
-	{ AR5K_RF_GAIN(50), 0x000000da },
-	{ AR5K_RF_GAIN(51), 0x00000006 },
-	{ AR5K_RF_GAIN(52), 0x00000006 },
-	{ AR5K_RF_GAIN(53), 0x00000006 },
-	{ AR5K_RF_GAIN(54), 0x00000006 },
-	{ AR5K_RF_GAIN(55), 0x00000006 },
-	{ AR5K_RF_GAIN(56), 0x00000006 },
-	{ AR5K_RF_GAIN(57), 0x00000006 },
-	{ AR5K_RF_GAIN(58), 0x00000006 },
-	{ AR5K_RF_GAIN(59), 0x00000006 },
-	{ AR5K_RF_GAIN(60), 0x00000006 },
-	{ AR5K_RF_GAIN(61), 0x00000006 },
-	{ AR5K_RF_GAIN(62), 0x00000006 },
-	{ AR5K_RF_GAIN(63), 0x00000006 },
-	/* PHY activation */
-	{ AR5K_PHY(53), 0x00000020 },
-	{ AR5K_PHY(51), 0x00000004 },
-	{ AR5K_PHY(50), 0x00060106 },
-	{ AR5K_PHY(39), 0x0000006d },
-	{ AR5K_PHY(48), 0x00000000 },
-	{ AR5K_PHY(52), 0x00000014 },
-	{ AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE },
-};
-
-/* Initial register settings for AR5211 */
-static const struct ath5k_ini ar5211_ini[] = {
-	{ AR5K_RXDP,		0x00000000 },
-	{ AR5K_RTSD0,		0x84849c9c },
-	{ AR5K_RTSD1,		0x7c7c7c7c },
-	{ AR5K_RXCFG,		0x00000005 },
-	{ AR5K_MIBC,		0x00000000 },
-	{ AR5K_TOPS,		0x00000008 },
-	{ AR5K_RXNOFRM,		0x00000008 },
-	{ AR5K_TXNOFRM,		0x00000010 },
-	{ AR5K_RPGTO,		0x00000000 },
-	{ AR5K_RFCNT,		0x0000001f },
-	{ AR5K_QUEUE_TXDP(0),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(1),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(2),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(3),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(4),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(5),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(6),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(7),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(8),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(9),	0x00000000 },
-	{ AR5K_DCU_FP,		0x00000000 },
-	{ AR5K_STA_ID1,		0x00000000 },
-	{ AR5K_BSS_ID0,		0x00000000 },
-	{ AR5K_BSS_ID1,		0x00000000 },
-	{ AR5K_RSSI_THR,	0x00000000 },
-	{ AR5K_CFP_PERIOD_5211,	0x00000000 },
-	{ AR5K_TIMER0_5211,	0x00000030 },
-	{ AR5K_TIMER1_5211,	0x0007ffff },
-	{ AR5K_TIMER2_5211,	0x01ffffff },
-	{ AR5K_TIMER3_5211,	0x00000031 },
-	{ AR5K_CFP_DUR_5211,	0x00000000 },
-	{ AR5K_RX_FILTER_5211,	0x00000000 },
-	{ AR5K_MCAST_FILTER0_5211, 0x00000000 },
-	{ AR5K_MCAST_FILTER1_5211, 0x00000002 },
-	{ AR5K_DIAG_SW_5211,	0x00000000 },
-	{ AR5K_ADDAC_TEST,	0x00000000 },
-	{ AR5K_DEFAULT_ANTENNA,	0x00000000 },
-	/* PHY registers */
-	{ AR5K_PHY_AGC,	0x00000000 },
-	{ AR5K_PHY(3),	0x2d849093 },
-	{ AR5K_PHY(4),	0x7d32e000 },
-	{ AR5K_PHY(5),	0x00000f6b },
-	{ AR5K_PHY_ACT,	0x00000000 },
-	{ AR5K_PHY(11),	0x00026ffe },
-	{ AR5K_PHY(12),	0x00000000 },
-	{ AR5K_PHY(15),	0x00020100 },
-	{ AR5K_PHY(16),	0x206a017a },
-	{ AR5K_PHY(19),	0x1284613c },
-	{ AR5K_PHY(21),	0x00000859 },
-	{ AR5K_PHY(26),	0x409a4190 },	/* 0x9868 */
-	{ AR5K_PHY(27),	0x050cb081 },
-	{ AR5K_PHY(28),	0x0000000f },
-	{ AR5K_PHY(29),	0x00000080 },
-	{ AR5K_PHY(30),	0x0000000c },
-	{ AR5K_PHY(64),	0x00000000 },
-	{ AR5K_PHY(65),	0x00000000 },
-	{ AR5K_PHY(66),	0x00000000 },
-	{ AR5K_PHY(67),	0x00800000 },
-	{ AR5K_PHY(68),	0x00000001 },
-	{ AR5K_PHY(71),	0x0000092a },
-	{ AR5K_PHY_IQ,	0x00000000 },
-	{ AR5K_PHY(73),	0x00058a05 },
-	{ AR5K_PHY(74),	0x00000001 },
-	{ AR5K_PHY(75),	0x00000000 },
-	{ AR5K_PHY_PAPD_PROBE, 0x00000000 },
-	{ AR5K_PHY(77),	0x00000000 },	/* 0x9934 */
-	{ AR5K_PHY(78),	0x00000000 },	/* 0x9938 */
-	{ AR5K_PHY(79),	0x0000003f },	/* 0x993c */
-	{ AR5K_PHY(80),	0x00000004 },
-	{ AR5K_PHY(82),	0x00000000 },
-	{ AR5K_PHY(83),	0x00000000 },
-	{ AR5K_PHY(84),	0x00000000 },
-	{ AR5K_PHY_RADAR, 0x5d50f14c },
-	{ AR5K_PHY(86),	0x00000018 },
-	{ AR5K_PHY(87),	0x004b6a8e },
-	/* Initial Power table (32bytes)
-	 * common on all cards/modes.
-	 * Note: Table is rewritten during
-	 * txpower setup later using calibration
-	 * data etc. so next write is non-common */
-	{ AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff },
-	{ AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff },
-	{ AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff },
-	{ AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff },
-	{ AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff },
-	{ AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff },
-	{ AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff },
-	{ AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff },
-	{ AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff },
-	{ AR5K_PHY_CCKTXCTL, 0x00000000 },
-	{ AR5K_PHY(642), 0x503e4646 },
-	{ AR5K_PHY_GAIN_2GHZ, 0x6480416c },
-	{ AR5K_PHY(644), 0x0199a003 },
-	{ AR5K_PHY(645), 0x044cd610 },
-	{ AR5K_PHY(646), 0x13800040 },
-	{ AR5K_PHY(647), 0x1be00060 },
-	{ AR5K_PHY(648), 0x0c53800a },
-	{ AR5K_PHY(649), 0x0014df3b },
-	{ AR5K_PHY(650), 0x000001b5 },
-	{ AR5K_PHY(651), 0x00000020 },
-};
-
-/* Initial mode-specific settings for AR5211
- * 5211 supports OFDM-only g (draft g) but we
- * need to test it !
- */
-static const struct ath5k_ini_mode ar5211_ini_mode[] = {
-	{ AR5K_TXCFG,
-	/*	  a	    aTurbo	  b	  g (OFDM)    */
-	   { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
-	{ AR5K_DCU_GBL_IFS_SLOT,
-	   { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } },
-	{ AR5K_DCU_GBL_IFS_SIFS,
-	   { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } },
-	{ AR5K_DCU_GBL_IFS_EIFS,
-	   { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } },
-	{ AR5K_DCU_GBL_IFS_MISC,
-	   { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } },
-	{ AR5K_TIME_OUT,
-	   { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } },
-	{ AR5K_USEC_5211,
-	   { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } },
-	{ AR5K_PHY_TURBO,
-	   { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } },
-	{ AR5K_PHY(8),
-	   { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } },
-	{ AR5K_PHY(9),
-	   { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } },
-	{ AR5K_PHY(10),
-	   { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } },
-	{ AR5K_PHY(13),
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
-	{ AR5K_PHY(14),
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } },
-	{ AR5K_PHY(17),
-	   { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } },
-	{ AR5K_PHY(18),
-	   { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
-	{ AR5K_PHY(20),
-	   { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
-	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
-	{ AR5K_PHY_AGCCOARSE,
-	   { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
-	{ AR5K_PHY_AGCCTL,
-	   { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
-	{ AR5K_PHY_NF,
-	   { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
-	{ AR5K_PHY_RX_DELAY,
-	   { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } },
-	{ AR5K_PHY(70),
-	   { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } },
-	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
-	{ AR5K_PHY_PCDAC_TXPOWER_BASE,
-	   { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
-	{ AR5K_RF_BUFFER_CONTROL_4,
-	   { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } },
-};
-
-/* Initial register settings for AR5212 */
-static const struct ath5k_ini ar5212_ini_common_start[] = {
-	{ AR5K_RXDP,		0x00000000 },
-	{ AR5K_RXCFG,		0x00000005 },
-	{ AR5K_MIBC,		0x00000000 },
-	{ AR5K_TOPS,		0x00000008 },
-	{ AR5K_RXNOFRM,		0x00000008 },
-	{ AR5K_TXNOFRM,		0x00000010 },
-	{ AR5K_RPGTO,		0x00000000 },
-	{ AR5K_RFCNT,		0x0000001f },
-	{ AR5K_QUEUE_TXDP(0),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(1),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(2),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(3),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(4),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(5),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(6),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(7),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(8),	0x00000000 },
-	{ AR5K_QUEUE_TXDP(9),	0x00000000 },
-	{ AR5K_DCU_FP,		0x00000000 },
-	{ AR5K_DCU_TXP,		0x00000000 },
-	/* Tx filter table 0 (32 entries) */
-	{ AR5K_DCU_TX_FILTER_0(0),  0x00000000 }, /* DCU 0 */
-	{ AR5K_DCU_TX_FILTER_0(1),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(2),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(3),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(4),  0x00000000 }, /* DCU 1 */
-	{ AR5K_DCU_TX_FILTER_0(5),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(6),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(7),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(8),  0x00000000 }, /* DCU 2 */
-	{ AR5K_DCU_TX_FILTER_0(9),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(10), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(11), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(12), 0x00000000 }, /* DCU 3 */
-	{ AR5K_DCU_TX_FILTER_0(13), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(14), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(15), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(16), 0x00000000 }, /* DCU 4 */
-	{ AR5K_DCU_TX_FILTER_0(17), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(18), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(19), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(20), 0x00000000 }, /* DCU 5 */
-	{ AR5K_DCU_TX_FILTER_0(21), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(22), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(23), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(24), 0x00000000 }, /* DCU 6 */
-	{ AR5K_DCU_TX_FILTER_0(25), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(26), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(27), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(28), 0x00000000 }, /* DCU 7 */
-	{ AR5K_DCU_TX_FILTER_0(29), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(30), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_0(31), 0x00000000 },
-	/* Tx filter table 1 (16 entries) */
-	{ AR5K_DCU_TX_FILTER_1(0),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(1),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(2),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(3),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(4),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(5),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(6),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(7),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(8),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(9),  0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(10), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(11), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(12), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(13), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(14), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_1(15), 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_SET, 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_SET, 0x00000000 },
-	{ AR5K_STA_ID1,		0x00000000 },
-	{ AR5K_BSS_ID0,		0x00000000 },
-	{ AR5K_BSS_ID1,		0x00000000 },
-	{ AR5K_BEACON_5211,	0x00000000 },
-	{ AR5K_CFP_PERIOD_5211, 0x00000000 },
-	{ AR5K_TIMER0_5211,	0x00000030 },
-	{ AR5K_TIMER1_5211,	0x0007ffff },
-	{ AR5K_TIMER2_5211,	0x01ffffff },
-	{ AR5K_TIMER3_5211,	0x00000031 },
-	{ AR5K_CFP_DUR_5211,	0x00000000 },
-	{ AR5K_RX_FILTER_5211,	0x00000000 },
-	{ AR5K_DIAG_SW_5211,	0x00000000 },
-	{ AR5K_ADDAC_TEST,	0x00000000 },
-	{ AR5K_DEFAULT_ANTENNA,	0x00000000 },
-	{ AR5K_FRAME_CTL_QOSM, 	0x000fc78f },
-	{ AR5K_XRMODE,		0x2a82301a },
-	{ AR5K_XRDELAY,		0x05dc01e0 },
-	{ AR5K_XRTIMEOUT,	0x1f402710 },
-	{ AR5K_XRCHIRP,		0x01f40000 },
-	{ AR5K_XRSTOMP,		0x00001e1c },
-	{ AR5K_SLEEP0,		0x0002aaaa },
-	{ AR5K_SLEEP1,		0x02005555 },
-	{ AR5K_SLEEP2,		0x00000000 },
-	{ AR5K_BSS_IDM0,	0xffffffff },
-	{ AR5K_BSS_IDM1,	0x0000ffff },
-	{ AR5K_TXPC,		0x00000000 },
-	{ AR5K_PROFCNT_TX,	0x00000000 },
-	{ AR5K_PROFCNT_RX,	0x00000000 },
-	{ AR5K_PROFCNT_RXCLR,	0x00000000 },
-	{ AR5K_PROFCNT_CYCLE,	0x00000000 },
-	{ AR5K_QUIET_CTL1,	0x00000088 },
-	/* Initial rate duration table (32 entries )*/
-	{ AR5K_RATE_DUR(0),	0x00000000 },
-	{ AR5K_RATE_DUR(1),	0x0000008c },
-	{ AR5K_RATE_DUR(2),	0x000000e4 },
-	{ AR5K_RATE_DUR(3),	0x000002d5 },
-	{ AR5K_RATE_DUR(4),	0x00000000 },
-	{ AR5K_RATE_DUR(5),	0x00000000 },
-	{ AR5K_RATE_DUR(6),	0x000000a0 },
-	{ AR5K_RATE_DUR(7),	0x000001c9 },
-	{ AR5K_RATE_DUR(8),	0x0000002c },
-	{ AR5K_RATE_DUR(9),	0x0000002c },
-	{ AR5K_RATE_DUR(10),	0x00000030 },
-	{ AR5K_RATE_DUR(11),	0x0000003c },
-	{ AR5K_RATE_DUR(12),	0x0000002c },
-	{ AR5K_RATE_DUR(13),	0x0000002c },
-	{ AR5K_RATE_DUR(14),	0x00000030 },
-	{ AR5K_RATE_DUR(15),	0x0000003c },
-	{ AR5K_RATE_DUR(16),	0x00000000 },
-	{ AR5K_RATE_DUR(17),	0x00000000 },
-	{ AR5K_RATE_DUR(18),	0x00000000 },
-	{ AR5K_RATE_DUR(19),	0x00000000 },
-	{ AR5K_RATE_DUR(20),	0x00000000 },
-	{ AR5K_RATE_DUR(21),	0x00000000 },
-	{ AR5K_RATE_DUR(22),	0x00000000 },
-	{ AR5K_RATE_DUR(23),	0x00000000 },
-	{ AR5K_RATE_DUR(24),	0x000000d5 },
-	{ AR5K_RATE_DUR(25),	0x000000df },
-	{ AR5K_RATE_DUR(26),	0x00000102 },
-	{ AR5K_RATE_DUR(27),	0x0000013a },
-	{ AR5K_RATE_DUR(28),	0x00000075 },
-	{ AR5K_RATE_DUR(29),	0x0000007f },
-	{ AR5K_RATE_DUR(30),	0x000000a2 },
-	{ AR5K_RATE_DUR(31),	0x00000000 },
-	{ AR5K_QUIET_CTL2,	0x00010002 },
-	{ AR5K_TSF_PARM,	0x00000001 },
-	{ AR5K_QOS_NOACK,	0x000000c0 },
-	{ AR5K_PHY_ERR_FIL,	0x00000000 },
-	{ AR5K_XRLAT_TX,	0x00000168 },
-	{ AR5K_ACKSIFS,		0x00000000 },
-	/* Rate -> db table
-	 * notice ...03<-02<-01<-00 ! */
-	{ AR5K_RATE2DB(0),	0x03020100 },
-	{ AR5K_RATE2DB(1),	0x07060504 },
-	{ AR5K_RATE2DB(2),	0x0b0a0908 },
-	{ AR5K_RATE2DB(3),	0x0f0e0d0c },
-	{ AR5K_RATE2DB(4),	0x13121110 },
-	{ AR5K_RATE2DB(5),	0x17161514 },
-	{ AR5K_RATE2DB(6),	0x1b1a1918 },
-	{ AR5K_RATE2DB(7),	0x1f1e1d1c },
-	/* Db -> Rate table */
-	{ AR5K_DB2RATE(0),	0x03020100 },
-	{ AR5K_DB2RATE(1),	0x07060504 },
-	{ AR5K_DB2RATE(2),	0x0b0a0908 },
-	{ AR5K_DB2RATE(3),	0x0f0e0d0c },
-	{ AR5K_DB2RATE(4),	0x13121110 },
-	{ AR5K_DB2RATE(5),	0x17161514 },
-	{ AR5K_DB2RATE(6),	0x1b1a1918 },
-	{ AR5K_DB2RATE(7),	0x1f1e1d1c },
-	/* PHY registers (Common settings
-	 * for all chips/modes) */
-	{ AR5K_PHY(3),		0xad848e19 },
-	{ AR5K_PHY(4),		0x7d28e000 },
-	{ AR5K_PHY_TIMING_3,	0x9c0a9f6b },
-	{ AR5K_PHY_ACT,		0x00000000 },
-	{ AR5K_PHY(16),		0x206a017a },
-	{ AR5K_PHY(21),		0x00000859 },
-	{ AR5K_PHY_BIN_MASK_1,	0x00000000 },
-	{ AR5K_PHY_BIN_MASK_2,	0x00000000 },
-	{ AR5K_PHY_BIN_MASK_3,	0x00000000 },
-	{ AR5K_PHY_BIN_MASK_CTL, 0x00800000 },
-	{ AR5K_PHY_ANT_CTL,	0x00000001 },
-	/*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */
-	{ AR5K_PHY_MAX_RX_LEN,	0x00000c80 },
-	{ AR5K_PHY_IQ,		0x05100000 },
-	{ AR5K_PHY_WARM_RESET,	0x00000001 },
-	{ AR5K_PHY_CTL,		0x00000004 },
-	{ AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 },
-	{ AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d },
-	{ AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f },
-	{ AR5K_PHY(82),		0x9280b212 },
-	{ AR5K_PHY_RADAR,	0x5d50e188 },
-	/*{ AR5K_PHY(86), 0x000000ff },*/
-	{ AR5K_PHY(87),		0x004b6a8e },
-	{ AR5K_PHY_NFTHRES,	0x000003ce },
-	{ AR5K_PHY_RESTART,	0x192fb515 },
-	{ AR5K_PHY(94),		0x00000001 },
-	{ AR5K_PHY_RFBUS_REQ,	0x00000000 },
-	/*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */
-	/*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */
-	{ AR5K_PHY(644),	0x00806333 },
-	{ AR5K_PHY(645),	0x00106c10 },
-	{ AR5K_PHY(646),	0x009c4060 },
-	/* { AR5K_PHY(647), 0x1483800a }, */
-	/* { AR5K_PHY(648), 0x01831061 }, */ /* Old value */
-	{ AR5K_PHY(648),	0x018830c6 },
-	{ AR5K_PHY(649),	0x00000400 },
-	/*{ AR5K_PHY(650), 0x000001b5 },*/
-	{ AR5K_PHY(651),	0x00000000 },
-	{ AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
-	{ AR5K_PHY_TXPOWER_RATE2, 0x20202020 },
-	/*{ AR5K_PHY(655), 0x13c889af },*/
-	{ AR5K_PHY(656),	0x38490a20 },
-	{ AR5K_PHY(657),	0x00007bb6 },
-	{ AR5K_PHY(658),	0x0fff3ffc },
-};
-
-/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
-static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
-	   { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
-	{ AR5K_DCU_GBL_IFS_SIFS,
-	   { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
-	{ AR5K_DCU_GBL_IFS_SLOT,
-	   { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
-	{ AR5K_DCU_GBL_IFS_EIFS,
-	   { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
-	{ AR5K_DCU_GBL_IFS_MISC,
-	   { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
-	{ AR5K_TIME_OUT,
-	   { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
-	{ AR5K_PHY_TURBO,
-	   { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
-	{ AR5K_PHY(8),
-	   { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
-	{ AR5K_PHY_RF_CTL2,
-	   { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
-	{ AR5K_PHY_SETTLING,
-	   { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
-	{ AR5K_PHY_AGCCTL,
-	   { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
-	{ AR5K_PHY_NF,
-	   { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
-	{ AR5K_PHY_WEAK_OFDM_HIGH_THR,
-	   { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
-	{ AR5K_PHY(70),
-	   { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
-	{ AR5K_PHY_OFDM_SELFCORR,
-	   { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
-	{ 0xa230,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
-};
-
-/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
-static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
-	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
-	{ AR5K_USEC_5211,
-	   { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
-	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
-	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
-	{ AR5K_PHY_PA_CTL,
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
-	{ AR5K_PHY_GAIN,
-	   { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
-	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
-	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
-	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
-	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
-	{ AR5K_PHY_RX_DELAY,
-	   { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
-	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
-	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
-	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
-};
-
-static const struct ath5k_ini rf5111_ini_common_end[] = {
-	{ AR5K_DCU_FP,		0x00000000 },
-	{ AR5K_PHY_AGC, 	0x00000000 },
-	{ AR5K_PHY_ADC_CTL, 	0x00022ffe },
-	{ 0x983c, 		0x00020100 },
-	{ AR5K_PHY_GAIN_OFFSET,	0x1284613c },
-	{ AR5K_PHY_PAPD_PROBE,	0x00004883 },
-	{ 0x9940,		0x00000004 },
-	{ 0x9958,		0x000000ff },
-	{ 0x9974,		0x00000000 },
-	{ AR5K_PHY_SPENDING,	0x00000018 },
-	{ AR5K_PHY_CCKTXCTL,	0x00000000 },
-	{ AR5K_PHY_CCK_CROSSCORR, 0xd03e6788 },
-	{ AR5K_PHY_DAG_CCK_CTL,	0x000001b5 },
-	{ 0xa23c,		0x13c889af },
-};
-
-/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
-static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
-	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
-	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
-	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
-	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
-	{ AR5K_PHY_PA_CTL,
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
-	{ AR5K_PHY_GAIN,
-	   { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
-	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
-	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
-	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
-	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
-	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
-	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
-	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
-	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
-	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
-	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
-};
-
-static const struct ath5k_ini rf5112_ini_common_end[] = {
-	{ AR5K_DCU_FP,		0x00000000 },
-	{ AR5K_PHY_AGC,		0x00000000 },
-	{ AR5K_PHY_ADC_CTL,	0x00022ffe },
-	{ 0x983c,		0x00020100 },
-	{ AR5K_PHY_GAIN_OFFSET,	0x1284613c },
-	{ AR5K_PHY_PAPD_PROBE,	0x00004882 },
-	{ 0x9940,		0x00000004 },
-	{ 0x9958,		0x000000ff },
-	{ 0x9974,		0x00000000 },
-	{ AR5K_PHY_DAG_CCK_CTL,	0x000001b5 },
-	{ 0xa23c,		0x13c889af },
-};
-
-/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
-static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
-	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
-	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
-	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
-	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
-	{ AR5K_PHY_PA_CTL,
-	   { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
-	{ AR5K_PHY_GAIN,
-	   { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
-	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
-	{ AR5K_PHY_SIG,
-	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
-	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
-	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
-	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
-	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
-	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
-	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
-	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
-	{ 0xa300,
-	   { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
-	{ 0xa304,
-	   { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
-	{ 0xa308,
-	   { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
-	{ 0xa30c,
-	   { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
-	{ 0xa310,
-	   { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
-	{ 0xa314,
-	   { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
-	{ 0xa318,
-	   { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
-	{ 0xa31c,
-	   { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
-	{ 0xa320,
-	   { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
-	{ 0xa324,
-	   { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
-	{ 0xa328,
-	   { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
-	{ 0xa32c,
-	   { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
-	{ 0xa330,
-	   { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
-	{ 0xa334,
-	   { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
-};
-
-static const struct ath5k_ini rf5413_ini_common_end[] = {
-	{ AR5K_DCU_FP,		0x000003e0 },
-	{ AR5K_5414_CBCFG,	0x00000010 },
-	{ AR5K_SEQ_MASK,	0x0000000f },
-	{ 0x809c,		0x00000000 },
-	{ 0x80a0,		0x00000000 },
-	{ AR5K_MIC_QOS_CTL,	0x00000000 },
-	{ AR5K_MIC_QOS_SEL,	0x00000000 },
-	{ AR5K_MISC_MODE,	0x00000000 },
-	{ AR5K_OFDM_FIL_CNT,	0x00000000 },
-	{ AR5K_CCK_FIL_CNT,	0x00000000 },
-	{ AR5K_PHYERR_CNT1,	0x00000000 },
-	{ AR5K_PHYERR_CNT1_MASK, 0x00000000 },
-	{ AR5K_PHYERR_CNT2,	0x00000000 },
-	{ AR5K_PHYERR_CNT2_MASK, 0x00000000 },
-	{ AR5K_TSF_THRES,	0x00000000 },
-	{ 0x8140,		0x800003f9 },
-	{ 0x8144,		0x00000000 },
-	{ AR5K_PHY_AGC,		0x00000000 },
-	{ AR5K_PHY_ADC_CTL,	0x0000a000 },
-	{ 0x983c,		0x00200400 },
-	{ AR5K_PHY_GAIN_OFFSET, 0x1284233c },
-	{ AR5K_PHY_SCR,		0x0000001f },
-	{ AR5K_PHY_SLMT,	0x00000080 },
-	{ AR5K_PHY_SCAL,	0x0000000e },
-	{ 0x9958,		0x00081fff },
-	{ AR5K_PHY_TIMING_7,	0x00000000 },
-	{ AR5K_PHY_TIMING_8,	0x02800000 },
-	{ AR5K_PHY_TIMING_11,	0x00000000 },
-	{ AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
-	{ 0x99e4,		0xaaaaaaaa },
-	{ 0x99e8,		0x3c466478 },
-	{ 0x99ec,		0x000000aa },
-	{ AR5K_PHY_SCLOCK,	0x0000000c },
-	{ AR5K_PHY_SDELAY,	0x000000ff },
-	{ AR5K_PHY_SPENDING,	0x00000014 },
-	{ AR5K_PHY_DAG_CCK_CTL, 0x000009b5 },
-	{ 0xa23c,		0x93c889af },
-	{ AR5K_PHY_FAST_ADC,	0x00000001 },
-	{ 0xa250,		0x0000a000 },
-	{ AR5K_PHY_BLUETOOTH,	0x00000000 },
-	{ AR5K_PHY_TPC_RG1,	0x0cc75380 },
-	{ 0xa25c,		0x0f0f0f01 },
-	{ 0xa260,		0x5f690f01 },
-	{ 0xa264,		0x00418a11 },
-	{ 0xa268,		0x00000000 },
-	{ AR5K_PHY_TPC_RG5,	0x0c30c16a },
-	{ 0xa270, 0x00820820 },
-	{ 0xa274, 0x081b7caa },
-	{ 0xa278, 0x1ce739ce },
-	{ 0xa27c, 0x051701ce },
-	{ 0xa338, 0x00000000 },
-	{ 0xa33c, 0x00000000 },
-	{ 0xa340, 0x00000000 },
-	{ 0xa344, 0x00000000 },
-	{ 0xa348, 0x3fffffff },
-	{ 0xa34c, 0x3fffffff },
-	{ 0xa350, 0x3fffffff },
-	{ 0xa354, 0x0003ffff },
-	{ 0xa358, 0x79a8aa1f },
-	{ 0xa35c, 0x066c420f },
-	{ 0xa360, 0x0f282207 },
-	{ 0xa364, 0x17601685 },
-	{ 0xa368, 0x1f801104 },
-	{ 0xa36c, 0x37a00c03 },
-	{ 0xa370, 0x3fc40883 },
-	{ 0xa374, 0x57c00803 },
-	{ 0xa378, 0x5fd80682 },
-	{ 0xa37c, 0x7fe00482 },
-	{ 0xa380, 0x7f3c7bba },
-	{ 0xa384, 0xf3307ff0 },
-};
-
-/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
-/* XXX: a mode ? */
-static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
-	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
-	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
-	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } },
-	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } },
-	{ AR5K_PHY_PA_CTL,
-	   { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } },
-	{ AR5K_PHY_GAIN,
-	   { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
-	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } },
-	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } },
-	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } },
-	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
-	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
-	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
-	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
-	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } },
-	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
-};
-
-static const struct ath5k_ini rf2413_ini_common_end[] = {
-	{ AR5K_DCU_FP,		0x000003e0 },
-	{ AR5K_SEQ_MASK,	0x0000000f },
-	{ AR5K_MIC_QOS_CTL,	0x00000000 },
-	{ AR5K_MIC_QOS_SEL,	0x00000000 },
-	{ AR5K_MISC_MODE,	0x00000000 },
-	{ AR5K_OFDM_FIL_CNT,	0x00000000 },
-	{ AR5K_CCK_FIL_CNT,	0x00000000 },
-	{ AR5K_PHYERR_CNT1,	0x00000000 },
-	{ AR5K_PHYERR_CNT1_MASK, 0x00000000 },
-	{ AR5K_PHYERR_CNT2,	0x00000000 },
-	{ AR5K_PHYERR_CNT2_MASK, 0x00000000 },
-	{ AR5K_TSF_THRES,	0x00000000 },
-	{ 0x8140,		0x800000a8 },
-	{ 0x8144,		0x00000000 },
-	{ AR5K_PHY_AGC,		0x00000000 },
-	{ AR5K_PHY_ADC_CTL,	0x0000a000 },
-	{ 0x983c,		0x00200400 },
-	{ AR5K_PHY_GAIN_OFFSET,	0x1284233c },
-	{ AR5K_PHY_SCR,		0x0000001f },
-	{ AR5K_PHY_SLMT,	0x00000080 },
-	{ AR5K_PHY_SCAL,	0x0000000e },
-	{ 0x9958,		0x000000ff },
-	{ AR5K_PHY_TIMING_7,	0x00000000 },
-	{ AR5K_PHY_TIMING_8,	0x02800000 },
-	{ AR5K_PHY_TIMING_11,	0x00000000 },
-	{ AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
-	{ 0x99e4,		0xaaaaaaaa },
-	{ 0x99e8,		0x3c466478 },
-	{ 0x99ec,		0x000000aa },
-	{ AR5K_PHY_SCLOCK,	0x0000000c },
-	{ AR5K_PHY_SDELAY,	0x000000ff },
-	{ AR5K_PHY_SPENDING,	0x00000014 },
-	{ AR5K_PHY_DAG_CCK_CTL,	0x000009b5 },
-	{ 0xa23c,		0x93c889af },
-	{ AR5K_PHY_FAST_ADC,	0x00000001 },
-	{ 0xa250,		0x0000a000 },
-	{ AR5K_PHY_BLUETOOTH,	0x00000000 },
-	{ AR5K_PHY_TPC_RG1,	0x0cc75380 },
-	{ 0xa25c,		0x0f0f0f01 },
-	{ 0xa260,		0x5f690f01 },
-	{ 0xa264,		0x00418a11 },
-	{ 0xa268,		0x00000000 },
-	{ AR5K_PHY_TPC_RG5,	0x0c30c16a },
-	{ 0xa270, 0x00820820 },
-	{ 0xa274, 0x001b7caa },
-	{ 0xa278, 0x1ce739ce },
-	{ 0xa27c, 0x051701ce },
-	{ 0xa300, 0x18010000 },
-	{ 0xa304, 0x30032602 },
-	{ 0xa308, 0x48073e06 },
-	{ 0xa30c, 0x560b4c0a },
-	{ 0xa310, 0x641a600f },
-	{ 0xa314, 0x784f6e1b },
-	{ 0xa318, 0x868f7c5a },
-	{ 0xa31c, 0x8ecf865b },
-	{ 0xa320, 0x9d4f970f },
-	{ 0xa324, 0xa5cfa18f },
-	{ 0xa328, 0xb55faf1f },
-	{ 0xa32c, 0xbddfb99f },
-	{ 0xa330, 0xcd7fc73f },
-	{ 0xa334, 0xd5ffd1bf },
-	{ 0xa338, 0x00000000 },
-	{ 0xa33c, 0x00000000 },
-	{ 0xa340, 0x00000000 },
-	{ 0xa344, 0x00000000 },
-	{ 0xa348, 0x3fffffff },
-	{ 0xa34c, 0x3fffffff },
-	{ 0xa350, 0x3fffffff },
-	{ 0xa354, 0x0003ffff },
-	{ 0xa358, 0x79a8aa1f },
-	{ 0xa35c, 0x066c420f },
-	{ 0xa360, 0x0f282207 },
-	{ 0xa364, 0x17601685 },
-	{ 0xa368, 0x1f801104 },
-	{ 0xa36c, 0x37a00c03 },
-	{ 0xa370, 0x3fc40883 },
-	{ 0xa374, 0x57c00803 },
-	{ 0xa378, 0x5fd80682 },
-	{ 0xa37c, 0x7fe00482 },
-	{ 0xa380, 0x7f3c7bba },
-	{ 0xa384, 0xf3307ff0 },
-};
-
-/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
-/* XXX: a mode ? */
-static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
-	{ AR5K_TXCFG,
-	/*	a/XR	   aTurbo	  b	   g (DYN)     gTurbo     */
-	   { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
-	{ AR5K_USEC_5211,
-	   { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
-	{ AR5K_PHY_TURBO,
-	   { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } },
-	{ AR5K_PHY_RF_CTL3,
-	   { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
-	{ AR5K_PHY_RF_CTL4,
-	   { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
-	{ AR5K_PHY_PA_CTL,
-	   { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } },
-	{ AR5K_PHY_SETTLING,
-	   { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } },
-	{ AR5K_PHY_GAIN,
-	   { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } },
-	{ AR5K_PHY_DESIRED_SIZE,
-	   { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
-	{ AR5K_PHY_SIG,
-	   { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
-	{ AR5K_PHY_AGCCOARSE,
-	   { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
-	{ AR5K_PHY_WEAK_OFDM_LOW_THR,
-	   { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
-	{ AR5K_PHY_RX_DELAY,
-	   { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
-	{ AR5K_PHY_FRAME_CTL_5211,
-	   { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
-	{ AR5K_PHY_CCKTXCTL,
-	   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ AR5K_PHY_CCK_CROSSCORR,
-	   { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
-	{ AR5K_PHY_GAIN_2GHZ,
-	   { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } },
-	{ AR5K_PHY_CCK_RX_CTL_4,
-	   { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
-	{ 0xa324,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
-	{ 0xa328,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
-	{ 0xa32c,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
-	{ 0xa330,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
-	{ 0xa334,
-	   { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
-};
-
-static const struct ath5k_ini rf2425_ini_common_end[] = {
-	{ AR5K_DCU_FP,		0x000003e0 },
-	{ AR5K_SEQ_MASK,	0x0000000f },
-	{ 0x809c,		0x00000000 },
-	{ 0x80a0,		0x00000000 },
-	{ AR5K_MIC_QOS_CTL,	0x00000000 },
-	{ AR5K_MIC_QOS_SEL,	0x00000000 },
-	{ AR5K_MISC_MODE,	0x00000000 },
-	{ AR5K_OFDM_FIL_CNT,	0x00000000 },
-	{ AR5K_CCK_FIL_CNT,	0x00000000 },
-	{ AR5K_PHYERR_CNT1,	0x00000000 },
-	{ AR5K_PHYERR_CNT1_MASK, 0x00000000 },
-	{ AR5K_PHYERR_CNT2,	0x00000000 },
-	{ AR5K_PHYERR_CNT2_MASK, 0x00000000 },
-	{ AR5K_TSF_THRES,	0x00000000 },
-	{ 0x8140,		0x800003f9 },
-	{ 0x8144,		0x00000000 },
-	{ AR5K_PHY_AGC,		0x00000000 },
-	{ AR5K_PHY_ADC_CTL,	0x0000a000 },
-	{ 0x983c,		0x00200400 },
-	{ AR5K_PHY_GAIN_OFFSET, 0x1284233c },
-	{ AR5K_PHY_SCR,		0x0000001f },
-	{ AR5K_PHY_SLMT,	0x00000080 },
-	{ AR5K_PHY_SCAL,	0x0000000e },
-	{ 0x9958,		0x00081fff },
-	{ AR5K_PHY_TIMING_7,	0x00000000 },
-	{ AR5K_PHY_TIMING_8,	0x02800000 },
-	{ AR5K_PHY_TIMING_11,	0x00000000 },
-	{ 0x99dc,		0xfebadbe8 },
-	{ AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 },
-	{ 0x99e4,		0xaaaaaaaa },
-	{ 0x99e8,		0x3c466478 },
-	{ 0x99ec,		0x000000aa },
-	{ AR5K_PHY_SCLOCK,	0x0000000c },
-	{ AR5K_PHY_SDELAY,	0x000000ff },
-	{ AR5K_PHY_SPENDING,	0x00000014 },
-	{ AR5K_PHY_DAG_CCK_CTL,	0x000009b5 },
-	{ AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
-	{ AR5K_PHY_TXPOWER_RATE4, 0x20202020 },
-	{ 0xa23c,		0x93c889af },
-	{ AR5K_PHY_FAST_ADC,	0x00000001 },
-	{ 0xa250,		0x0000a000 },
-	{ AR5K_PHY_BLUETOOTH,	0x00000000 },
-	{ AR5K_PHY_TPC_RG1,	0x0cc75380 },
-	{ 0xa25c,		0x0f0f0f01 },
-	{ 0xa260,		0x5f690f01 },
-	{ 0xa264,		0x00418a11 },
-	{ 0xa268,		0x00000000 },
-	{ AR5K_PHY_TPC_RG5,	0x0c30c166 },
-	{ 0xa270, 0x00820820 },
-	{ 0xa274, 0x081a3caa },
-	{ 0xa278, 0x1ce739ce },
-	{ 0xa27c, 0x051701ce },
-	{ 0xa300, 0x16010000 },
-	{ 0xa304, 0x2c032402 },
-	{ 0xa308, 0x48433e42 },
-	{ 0xa30c, 0x5a0f500b },
-	{ 0xa310, 0x6c4b624a },
-	{ 0xa314, 0x7e8b748a },
-	{ 0xa318, 0x96cf8ccb },
-	{ 0xa31c, 0xa34f9d0f },
-	{ 0xa320, 0xa7cfa58f },
-	{ 0xa348, 0x3fffffff },
-	{ 0xa34c, 0x3fffffff },
-	{ 0xa350, 0x3fffffff },
-	{ 0xa354, 0x0003ffff },
-	{ 0xa358, 0x79a8aa1f },
-	{ 0xa35c, 0x066c420f },
-	{ 0xa360, 0x0f282207 },
-	{ 0xa364, 0x17601685 },
-	{ 0xa368, 0x1f801104 },
-	{ 0xa36c, 0x37a00c03 },
-	{ 0xa370, 0x3fc40883 },
-	{ 0xa374, 0x57c00803 },
-	{ 0xa378, 0x5fd80682 },
-	{ 0xa37c, 0x7fe00482 },
-	{ 0xa380, 0x7f3c7bba },
-	{ 0xa384, 0xf3307ff0 },
-};
-
-/*
- * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
- * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
- */
-
-/* RF5111 Initial BaseBand Gain settings */
-static const struct ath5k_ini rf5111_ini_bbgain[] = {
-	{ AR5K_BB_GAIN(0), 0x00000000 },
-	{ AR5K_BB_GAIN(1), 0x00000020 },
-	{ AR5K_BB_GAIN(2), 0x00000010 },
-	{ AR5K_BB_GAIN(3), 0x00000030 },
-	{ AR5K_BB_GAIN(4), 0x00000008 },
-	{ AR5K_BB_GAIN(5), 0x00000028 },
-	{ AR5K_BB_GAIN(6), 0x00000004 },
-	{ AR5K_BB_GAIN(7), 0x00000024 },
-	{ AR5K_BB_GAIN(8), 0x00000014 },
-	{ AR5K_BB_GAIN(9), 0x00000034 },
-	{ AR5K_BB_GAIN(10), 0x0000000c },
-	{ AR5K_BB_GAIN(11), 0x0000002c },
-	{ AR5K_BB_GAIN(12), 0x00000002 },
-	{ AR5K_BB_GAIN(13), 0x00000022 },
-	{ AR5K_BB_GAIN(14), 0x00000012 },
-	{ AR5K_BB_GAIN(15), 0x00000032 },
-	{ AR5K_BB_GAIN(16), 0x0000000a },
-	{ AR5K_BB_GAIN(17), 0x0000002a },
-	{ AR5K_BB_GAIN(18), 0x00000006 },
-	{ AR5K_BB_GAIN(19), 0x00000026 },
-	{ AR5K_BB_GAIN(20), 0x00000016 },
-	{ AR5K_BB_GAIN(21), 0x00000036 },
-	{ AR5K_BB_GAIN(22), 0x0000000e },
-	{ AR5K_BB_GAIN(23), 0x0000002e },
-	{ AR5K_BB_GAIN(24), 0x00000001 },
-	{ AR5K_BB_GAIN(25), 0x00000021 },
-	{ AR5K_BB_GAIN(26), 0x00000011 },
-	{ AR5K_BB_GAIN(27), 0x00000031 },
-	{ AR5K_BB_GAIN(28), 0x00000009 },
-	{ AR5K_BB_GAIN(29), 0x00000029 },
-	{ AR5K_BB_GAIN(30), 0x00000005 },
-	{ AR5K_BB_GAIN(31), 0x00000025 },
-	{ AR5K_BB_GAIN(32), 0x00000015 },
-	{ AR5K_BB_GAIN(33), 0x00000035 },
-	{ AR5K_BB_GAIN(34), 0x0000000d },
-	{ AR5K_BB_GAIN(35), 0x0000002d },
-	{ AR5K_BB_GAIN(36), 0x00000003 },
-	{ AR5K_BB_GAIN(37), 0x00000023 },
-	{ AR5K_BB_GAIN(38), 0x00000013 },
-	{ AR5K_BB_GAIN(39), 0x00000033 },
-	{ AR5K_BB_GAIN(40), 0x0000000b },
-	{ AR5K_BB_GAIN(41), 0x0000002b },
-	{ AR5K_BB_GAIN(42), 0x0000002b },
-	{ AR5K_BB_GAIN(43), 0x0000002b },
-	{ AR5K_BB_GAIN(44), 0x0000002b },
-	{ AR5K_BB_GAIN(45), 0x0000002b },
-	{ AR5K_BB_GAIN(46), 0x0000002b },
-	{ AR5K_BB_GAIN(47), 0x0000002b },
-	{ AR5K_BB_GAIN(48), 0x0000002b },
-	{ AR5K_BB_GAIN(49), 0x0000002b },
-	{ AR5K_BB_GAIN(50), 0x0000002b },
-	{ AR5K_BB_GAIN(51), 0x0000002b },
-	{ AR5K_BB_GAIN(52), 0x0000002b },
-	{ AR5K_BB_GAIN(53), 0x0000002b },
-	{ AR5K_BB_GAIN(54), 0x0000002b },
-	{ AR5K_BB_GAIN(55), 0x0000002b },
-	{ AR5K_BB_GAIN(56), 0x0000002b },
-	{ AR5K_BB_GAIN(57), 0x0000002b },
-	{ AR5K_BB_GAIN(58), 0x0000002b },
-	{ AR5K_BB_GAIN(59), 0x0000002b },
-	{ AR5K_BB_GAIN(60), 0x0000002b },
-	{ AR5K_BB_GAIN(61), 0x0000002b },
-	{ AR5K_BB_GAIN(62), 0x00000002 },
-	{ AR5K_BB_GAIN(63), 0x00000016 },
-};
-
-/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */
-static const struct ath5k_ini rf5112_ini_bbgain[] = {
-	{ AR5K_BB_GAIN(0), 0x00000000 },
-	{ AR5K_BB_GAIN(1), 0x00000001 },
-	{ AR5K_BB_GAIN(2), 0x00000002 },
-	{ AR5K_BB_GAIN(3), 0x00000003 },
-	{ AR5K_BB_GAIN(4), 0x00000004 },
-	{ AR5K_BB_GAIN(5), 0x00000005 },
-	{ AR5K_BB_GAIN(6), 0x00000008 },
-	{ AR5K_BB_GAIN(7), 0x00000009 },
-	{ AR5K_BB_GAIN(8), 0x0000000a },
-	{ AR5K_BB_GAIN(9), 0x0000000b },
-	{ AR5K_BB_GAIN(10), 0x0000000c },
-	{ AR5K_BB_GAIN(11), 0x0000000d },
-	{ AR5K_BB_GAIN(12), 0x00000010 },
-	{ AR5K_BB_GAIN(13), 0x00000011 },
-	{ AR5K_BB_GAIN(14), 0x00000012 },
-	{ AR5K_BB_GAIN(15), 0x00000013 },
-	{ AR5K_BB_GAIN(16), 0x00000014 },
-	{ AR5K_BB_GAIN(17), 0x00000015 },
-	{ AR5K_BB_GAIN(18), 0x00000018 },
-	{ AR5K_BB_GAIN(19), 0x00000019 },
-	{ AR5K_BB_GAIN(20), 0x0000001a },
-	{ AR5K_BB_GAIN(21), 0x0000001b },
-	{ AR5K_BB_GAIN(22), 0x0000001c },
-	{ AR5K_BB_GAIN(23), 0x0000001d },
-	{ AR5K_BB_GAIN(24), 0x00000020 },
-	{ AR5K_BB_GAIN(25), 0x00000021 },
-	{ AR5K_BB_GAIN(26), 0x00000022 },
-	{ AR5K_BB_GAIN(27), 0x00000023 },
-	{ AR5K_BB_GAIN(28), 0x00000024 },
-	{ AR5K_BB_GAIN(29), 0x00000025 },
-	{ AR5K_BB_GAIN(30), 0x00000028 },
-	{ AR5K_BB_GAIN(31), 0x00000029 },
-	{ AR5K_BB_GAIN(32), 0x0000002a },
-	{ AR5K_BB_GAIN(33), 0x0000002b },
-	{ AR5K_BB_GAIN(34), 0x0000002c },
-	{ AR5K_BB_GAIN(35), 0x0000002d },
-	{ AR5K_BB_GAIN(36), 0x00000030 },
-	{ AR5K_BB_GAIN(37), 0x00000031 },
-	{ AR5K_BB_GAIN(38), 0x00000032 },
-	{ AR5K_BB_GAIN(39), 0x00000033 },
-	{ AR5K_BB_GAIN(40), 0x00000034 },
-	{ AR5K_BB_GAIN(41), 0x00000035 },
-	{ AR5K_BB_GAIN(42), 0x00000035 },
-	{ AR5K_BB_GAIN(43), 0x00000035 },
-	{ AR5K_BB_GAIN(44), 0x00000035 },
-	{ AR5K_BB_GAIN(45), 0x00000035 },
-	{ AR5K_BB_GAIN(46), 0x00000035 },
-	{ AR5K_BB_GAIN(47), 0x00000035 },
-	{ AR5K_BB_GAIN(48), 0x00000035 },
-	{ AR5K_BB_GAIN(49), 0x00000035 },
-	{ AR5K_BB_GAIN(50), 0x00000035 },
-	{ AR5K_BB_GAIN(51), 0x00000035 },
-	{ AR5K_BB_GAIN(52), 0x00000035 },
-	{ AR5K_BB_GAIN(53), 0x00000035 },
-	{ AR5K_BB_GAIN(54), 0x00000035 },
-	{ AR5K_BB_GAIN(55), 0x00000035 },
-	{ AR5K_BB_GAIN(56), 0x00000035 },
-	{ AR5K_BB_GAIN(57), 0x00000035 },
-	{ AR5K_BB_GAIN(58), 0x00000035 },
-	{ AR5K_BB_GAIN(59), 0x00000035 },
-	{ AR5K_BB_GAIN(60), 0x00000035 },
-	{ AR5K_BB_GAIN(61), 0x00000035 },
-	{ AR5K_BB_GAIN(62), 0x00000010 },
-	{ AR5K_BB_GAIN(63), 0x0000001a },
-};
-
-
-/*
- * Write initial register dump
- */
-static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
-		const struct ath5k_ini *ini_regs, bool change_channel)
-{
-	unsigned int i;
-
-	/* Write initial registers */
-	for (i = 0; i < size; i++) {
-		/* On channel change there is
-		 * no need to mess with PCU */
-		if (change_channel &&
-				ini_regs[i].ini_register >= AR5K_PCU_MIN &&
-				ini_regs[i].ini_register <= AR5K_PCU_MAX)
-			continue;
-
-		switch (ini_regs[i].ini_mode) {
-		case AR5K_INI_READ:
-			/* Cleared on read */
-			ath5k_hw_reg_read(ah, ini_regs[i].ini_register);
-			break;
-		case AR5K_INI_WRITE:
-		default:
-			AR5K_REG_WAIT(i);
-			ath5k_hw_reg_write(ah, ini_regs[i].ini_value,
-					ini_regs[i].ini_register);
-		}
-	}
-}
-
-static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
-		unsigned int size, const struct ath5k_ini_mode *ini_mode,
-		u8 mode)
-{
-	unsigned int i;
-
-	for (i = 0; i < size; i++) {
-		AR5K_REG_WAIT(i);
-		ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode],
-			(u32)ini_mode[i].mode_register);
-	}
-
-}
-
-int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
-{
-	/*
-	 * Write initial register settings
-	 */
-
-	/* For AR5212 and combatible */
-	if (ah->ah_version == AR5K_AR5212) {
-
-		/* First set of mode-specific settings */
-		ath5k_hw_ini_mode_registers(ah,
-			ARRAY_SIZE(ar5212_ini_mode_start),
-			ar5212_ini_mode_start, mode);
-
-		/*
-		 * Write initial settings common for all modes
-		 */
-		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start),
-				ar5212_ini_common_start, change_channel);
-
-		/* Second set of mode-specific settings */
-		switch (ah->ah_radio) {
-		case AR5K_RF5111:
-
-			ath5k_hw_ini_mode_registers(ah,
-					ARRAY_SIZE(rf5111_ini_mode_end),
-					rf5111_ini_mode_end, mode);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5111_ini_common_end),
-					rf5111_ini_common_end, change_channel);
-
-			/* Baseband gain table */
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5111_ini_bbgain),
-					rf5111_ini_bbgain, change_channel);
-
-			break;
-		case AR5K_RF5112:
-
-			ath5k_hw_ini_mode_registers(ah,
-					ARRAY_SIZE(rf5112_ini_mode_end),
-					rf5112_ini_mode_end, mode);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5112_ini_common_end),
-					rf5112_ini_common_end, change_channel);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
-
-			break;
-		case AR5K_RF5413:
-
-			ath5k_hw_ini_mode_registers(ah,
-					ARRAY_SIZE(rf5413_ini_mode_end),
-					rf5413_ini_mode_end, mode);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5413_ini_common_end),
-					rf5413_ini_common_end, change_channel);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
-
-			break;
-		case AR5K_RF2316:
-		case AR5K_RF2413:
-
-			ath5k_hw_ini_mode_registers(ah,
-					ARRAY_SIZE(rf2413_ini_mode_end),
-					rf2413_ini_mode_end, mode);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf2413_ini_common_end),
-					rf2413_ini_common_end, change_channel);
-
-			/* Override settings from rf2413_ini_common_end */
-			if (ah->ah_radio == AR5K_RF2316) {
-				ath5k_hw_reg_write(ah, 0x00004000,
-							AR5K_PHY_AGC);
-				ath5k_hw_reg_write(ah, 0x081b7caa,
-							0xa274);
-			}
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
-			break;
-		case AR5K_RF2317:
-		case AR5K_RF2425:
-
-			ath5k_hw_ini_mode_registers(ah,
-					ARRAY_SIZE(rf2425_ini_mode_end),
-					rf2425_ini_mode_end, mode);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf2425_ini_common_end),
-					rf2425_ini_common_end, change_channel);
-
-			ath5k_hw_ini_registers(ah,
-					ARRAY_SIZE(rf5112_ini_bbgain),
-					rf5112_ini_bbgain, change_channel);
-			break;
-		default:
-			return -EINVAL;
-
-		}
-
-	/* For AR5211 */
-	} else if (ah->ah_version == AR5K_AR5211) {
-
-		/* AR5K_MODE_11B */
-		if (mode > 2) {
-			ATH5K_ERR(ah->ah_sc,
-				"unsupported channel mode: %d\n", mode);
-			return -EINVAL;
-		}
-
-		/* Mode-specific settings */
-		ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode),
-				ar5211_ini_mode, mode);
-
-		/*
-		 * Write initial settings common for all modes
-		 */
-		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
-				ar5211_ini, change_channel);
-
-		/* AR5211 only comes with 5111 */
-
-		/* Baseband gain table */
-		ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
-				rf5111_ini_bbgain, change_channel);
-	/* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
-	} else if (ah->ah_version == AR5K_AR5210) {
-		ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
-				ar5210_ini, change_channel);
-	}
-
-	return 0;
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-config ATH5K
-	tristate "Atheros 5xxx wireless cards support"
-	depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
-	select MAC80211_LEDS
-	select LEDS_CLASS
-	select NEW_LEDS
-	---help---
-	  This module adds support for wireless adapters based on
-	  Atheros 5xxx chipset.
-
-	  Currently the following chip versions are supported:
-
-	  MAC: AR5211 AR5212
-	  PHY: RF5111/2111 RF5112/2112 RF5413/2413
-
-	  This driver uses the kernel's mac80211 subsystem.
-
-	  If you choose to build a module, it'll be called ath5k. Say M if
-	  unsure.
-
-config ATH5K_DEBUG
-	bool "Atheros 5xxx debugging"
-	depends on ATH5K
-	---help---
-	  Atheros 5xxx debugging messages.
-
-	  Say Y, if and you will get debug options for ath5k.
-	  To use this, you need to mount debugfs:
-
-	  mkdir /debug/
-	  mount -t debugfs debug /debug/
-
-	  You will get access to files under:
-	  /debug/ath5k/phy0/
-
-	  To enable debug, pass the debug level to the debug module
-	  parameter. For example:
-
-	  modprobe ath5k debug=0x00000400
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/led.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/led.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/led.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/led.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
- * Copyright (c) 2004-2005 Atheros Communications, Inc.
- * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
- * Copyright (c) 2009 Bob Copeland <me@bobcopeland.com>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
- *    redistribution must be conditioned upon including a substantially
- *    similar Disclaimer requirement for further binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
- *
- */
-
-#include <linux/pci.h>
-#include "ath5k.h"
-#include "base.h"
-
-#define ATH_SDEVICE(subv,subd) \
-	.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
-	.subvendor = (subv), .subdevice = (subd)
-
-#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity))
-#define ATH_PIN(data) ((data) >> 8)
-#define ATH_POLARITY(data) ((data) & 0xff)
-
-/* Devices we match on for LED config info (typically laptops) */
-static const struct pci_device_id ath5k_led_devices[] = {
-	/* IBM-specific AR5212 */
-	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
-	/* AR5211 */
-	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
-	/* HP Compaq nc6xx, nc4000, nx6000 */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) },
-	/* Acer Aspire One A150 (maximlevitsky@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) },
-	/* Acer Ferrari 5000 (russ.dill@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) },
-	/* E-machines E510 (tuliom@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) },
-	/* Acer Extensa 5620z (nekoreeve@gmail.com) */
-	{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) },
-	{ }
-};
-
-void ath5k_led_enable(struct ath5k_softc *sc)
-{
-	if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
-		ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
-		ath5k_led_off(sc);
-	}
-}
-
-void ath5k_led_on(struct ath5k_softc *sc)
-{
-	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
-		return;
-	ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
-}
-
-void ath5k_led_off(struct ath5k_softc *sc)
-{
-	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
-		return;
-	ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
-}
-
-static void
-ath5k_led_brightness_set(struct led_classdev *led_dev,
-	enum led_brightness brightness)
-{
-	struct ath5k_led *led = container_of(led_dev, struct ath5k_led,
-		led_dev);
-
-	if (brightness == LED_OFF)
-		ath5k_led_off(led->sc);
-	else
-		ath5k_led_on(led->sc);
-}
-
-static int
-ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
-		   const char *name, char *trigger)
-{
-	int err;
-
-	led->sc = sc;
-	strncpy(led->name, name, sizeof(led->name));
-	led->led_dev.name = led->name;
-	led->led_dev.default_trigger = trigger;
-	led->led_dev.brightness_set = ath5k_led_brightness_set;
-
-	err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
-	if (err) {
-		ATH5K_WARN(sc, "could not register LED %s\n", name);
-		led->sc = NULL;
-	}
-	return err;
-}
-
-static void
-ath5k_unregister_led(struct ath5k_led *led)
-{
-	if (!led->sc)
-		return;
-	led_classdev_unregister(&led->led_dev);
-	ath5k_led_off(led->sc);
-	led->sc = NULL;
-}
-
-void ath5k_unregister_leds(struct ath5k_softc *sc)
-{
-	ath5k_unregister_led(&sc->rx_led);
-	ath5k_unregister_led(&sc->tx_led);
-}
-
-int ath5k_init_leds(struct ath5k_softc *sc)
-{
-	int ret = 0;
-	struct ieee80211_hw *hw = sc->hw;
-	struct pci_dev *pdev = sc->pdev;
-	char name[ATH5K_LED_MAX_NAME_LEN + 1];
-	const struct pci_device_id *match;
-
-	match = pci_match_id(&ath5k_led_devices[0], pdev);
-	if (match) {
-		__set_bit(ATH_STAT_LEDSOFT, sc->status);
-		sc->led_pin = ATH_PIN(match->driver_data);
-		sc->led_on = ATH_POLARITY(match->driver_data);
-	}
-
-	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
-		goto out;
-
-	ath5k_led_enable(sc);
-
-	snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
-	ret = ath5k_register_led(sc, &sc->rx_led, name,
-		ieee80211_get_rx_led_name(hw));
-	if (ret)
-		goto out;
-
-	snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
-	ret = ath5k_register_led(sc, &sc->tx_led, name,
-		ieee80211_get_tx_led_name(hw));
-out:
-	return ret;
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-ath5k-y				+= caps.o
-ath5k-y				+= initvals.o
-ath5k-y				+= eeprom.o
-ath5k-y				+= gpio.o
-ath5k-y				+= desc.o
-ath5k-y				+= dma.o
-ath5k-y				+= qcu.o
-ath5k-y				+= pcu.o
-ath5k-y				+= phy.o
-ath5k-y				+= reset.o
-ath5k-y				+= attach.o
-ath5k-y				+= base.o
-ath5k-y				+= led.o
-ath5k-$(CONFIG_ATH5K_DEBUG)	+= debug.o
-obj-$(CONFIG_ATH5K)		+= ath5k.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/pcu.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/pcu.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/pcu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/pcu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1174 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007-2008 Matthew W. S. Bell  <mentor@madwifi.org>
- * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
- * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
- * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*********************************\
-* Protocol Control Unit Functions *
-\*********************************/
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*******************\
-* Generic functions *
-\*******************/
-
-/**
- * ath5k_hw_set_opmode - Set PCU operating mode
- *
- * @ah: The &struct ath5k_hw
- *
- * Initialize PCU for the various operating modes (AP/STA etc)
- *
- * NOTE: ah->ah_op_mode must be set before calling this.
- */
-int ath5k_hw_set_opmode(struct ath5k_hw *ah)
-{
-	u32 pcu_reg, beacon_reg, low_id, high_id;
-
-
-	/* Preserve rest settings */
-	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
-	pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
-			| AR5K_STA_ID1_KEYSRCH_MODE
-			| (ah->ah_version == AR5K_AR5210 ?
-			(AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
-
-	beacon_reg = 0;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	switch (ah->ah_op_mode) {
-	case NL80211_IFTYPE_ADHOC:
-		pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
-		beacon_reg |= AR5K_BCR_ADHOC;
-		if (ah->ah_version == AR5K_AR5210)
-			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
-		else
-			AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
-		break;
-
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_MESH_POINT:
-		pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
-		beacon_reg |= AR5K_BCR_AP;
-		if (ah->ah_version == AR5K_AR5210)
-			pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
-		else
-			AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
-		break;
-
-	case NL80211_IFTYPE_STATION:
-		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
-			| (ah->ah_version == AR5K_AR5210 ?
-				AR5K_STA_ID1_PWR_SV : 0);
-	case NL80211_IFTYPE_MONITOR:
-		pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
-			| (ah->ah_version == AR5K_AR5210 ?
-				AR5K_STA_ID1_NO_PSPOLL : 0);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * Set PCU registers
-	 */
-	low_id = AR5K_LOW_ID(ah->ah_sta_id);
-	high_id = AR5K_HIGH_ID(ah->ah_sta_id);
-	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
-	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
-
-	/*
-	 * Set Beacon Control Register on 5210
-	 */
-	if (ah->ah_version == AR5K_AR5210)
-		ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
-
-	return 0;
-}
-
-/**
- * ath5k_hw_update - Update mib counters (mac layer statistics)
- *
- * @ah: The &struct ath5k_hw
- * @stats: The &struct ieee80211_low_level_stats we use to track
- * statistics on the driver
- *
- * Reads MIB counters from PCU and updates sw statistics. Must be
- * called after a MIB interrupt.
- */
-void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
-		struct ieee80211_low_level_stats  *stats)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	/* Read-And-Clear */
-	stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
-	stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
-	stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
-	stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
-
-	/* XXX: Should we use this to track beacon count ?
-	 * -we read it anyway to clear the register */
-	ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
-
-	/* Reset profile count registers on 5212*/
-	if (ah->ah_version == AR5K_AR5212) {
-		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
-		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
-		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
-		ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
-	}
-
-	/* TODO: Handle ANI stats */
-}
-
-/**
- * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
- *
- * @ah: The &struct ath5k_hw
- * @high: Flag to determine if we want to use high transmition rate
- * for ACKs or not
- *
- * If high flag is set, we tell hw to use a set of control rates based on
- * the current transmition rate (check out control_rates array inside reset.c).
- * If not hw just uses the lowest rate available for the current modulation
- * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
- */
-void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
-{
-	if (ah->ah_version != AR5K_AR5212)
-		return;
-	else {
-		u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
-		if (high)
-			AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
-		else
-			AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
-	}
-}
-
-
-/******************\
-* ACK/CTS Timeouts *
-\******************/
-
-/**
- * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
- *
- * @ah: The &struct ath5k_hw
- */
-unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
-			AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
-}
-
-/**
- * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
- *
- * @ah: The &struct ath5k_hw
- * @timeout: Timeout in usec
- */
-int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
-			ah->ah_turbo) <= timeout)
-		return -EINVAL;
-
-	AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
-		ath5k_hw_htoclock(timeout, ah->ah_turbo));
-
-	return 0;
-}
-
-/**
- * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
- *
- * @ah: The &struct ath5k_hw
- */
-unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
-			AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
-}
-
-/**
- * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
- *
- * @ah: The &struct ath5k_hw
- * @timeout: Timeout in usec
- */
-int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
-			ah->ah_turbo) <= timeout)
-		return -EINVAL;
-
-	AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
-			ath5k_hw_htoclock(timeout, ah->ah_turbo));
-
-	return 0;
-}
-
-
-/****************\
-* BSSID handling *
-\****************/
-
-/**
- * ath5k_hw_get_lladdr - Get station id
- *
- * @ah: The &struct ath5k_hw
- * @mac: The card's mac address
- *
- * Initialize ah->ah_sta_id using the mac address provided
- * (just a memcpy).
- *
- * TODO: Remove it once we merge ath5k_softc and ath5k_hw
- */
-void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	memcpy(mac, ah->ah_sta_id, ETH_ALEN);
-}
-
-/**
- * ath5k_hw_set_lladdr - Set station id
- *
- * @ah: The &struct ath5k_hw
- * @mac: The card's mac address
- *
- * Set station id on hw using the provided mac address
- */
-int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
-{
-	u32 low_id, high_id;
-	u32 pcu_reg;
-
-	ATH5K_TRACE(ah->ah_sc);
-	/* Set new station ID */
-	memcpy(ah->ah_sta_id, mac, ETH_ALEN);
-
-	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
-
-	low_id = AR5K_LOW_ID(mac);
-	high_id = AR5K_HIGH_ID(mac);
-
-	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
-	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
-
-	return 0;
-}
-
-/**
- * ath5k_hw_set_associd - Set BSSID for association
- *
- * @ah: The &struct ath5k_hw
- * @bssid: BSSID
- * @assoc_id: Assoc id
- *
- * Sets the BSSID which trigers the "SME Join" operation
- */
-void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
-{
-	u32 low_id, high_id;
-	u16 tim_offset = 0;
-
-	/*
-	 * Set simple BSSID mask on 5212
-	 */
-	if (ah->ah_version == AR5K_AR5212) {
-		ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
-							AR5K_BSS_IDM0);
-		ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
-							AR5K_BSS_IDM1);
-	}
-
-	/*
-	 * Set BSSID which triggers the "SME Join" operation
-	 */
-	low_id = AR5K_LOW_ID(bssid);
-	high_id = AR5K_HIGH_ID(bssid);
-	ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
-	ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
-				AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
-
-	if (assoc_id == 0) {
-		ath5k_hw_disable_pspoll(ah);
-		return;
-	}
-
-	AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
-			tim_offset ? tim_offset + 4 : 0);
-
-	ath5k_hw_enable_pspoll(ah, NULL, 0);
-}
-
-/**
- * ath5k_hw_set_bssid_mask - filter out bssids we listen
- *
- * @ah: the &struct ath5k_hw
- * @mask: the bssid_mask, a u8 array of size ETH_ALEN
- *
- * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
- * which bits of the interface's MAC address should be looked at when trying
- * to decide which packets to ACK. In station mode and AP mode with a single
- * BSS every bit matters since we lock to only one BSS. In AP mode with
- * multiple BSSes (virtual interfaces) not every bit matters because hw must
- * accept frames for all BSSes and so we tweak some bits of our mac address
- * in order to have multiple BSSes.
- *
- * NOTE: This is a simple filter and does *not* filter out all
- * relevant frames. Some frames that are not for us might get ACKed from us
- * by PCU because they just match the mask.
- *
- * When handling multiple BSSes you can get the BSSID mask by computing the
- * set of  ~ ( MAC XOR BSSID ) for all bssids we handle.
- *
- * When you do this you are essentially computing the common bits of all your
- * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
- * the MAC address to obtain the relevant bits and compare the result with
- * (frame's BSSID & mask) to see if they match.
- */
-/*
- * Simple example: on your card you have have two BSSes you have created with
- * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
- * There is another BSSID-03 but you are not part of it. For simplicity's sake,
- * assuming only 4 bits for a mac address and for BSSIDs you can then have:
- *
- *                  \
- * MAC:                0001 |
- * BSSID-01:   0100 | --> Belongs to us
- * BSSID-02:   1001 |
- *                  /
- * -------------------
- * BSSID-03:   0110  | --> External
- * -------------------
- *
- * Our bssid_mask would then be:
- *
- *             On loop iteration for BSSID-01:
- *             ~(0001 ^ 0100)  -> ~(0101)
- *                             ->   1010
- *             bssid_mask      =    1010
- *
- *             On loop iteration for BSSID-02:
- *             bssid_mask &= ~(0001   ^   1001)
- *             bssid_mask =   (1010)  & ~(0001 ^ 1001)
- *             bssid_mask =   (1010)  & ~(1001)
- *             bssid_mask =   (1010)  &  (0110)
- *             bssid_mask =   0010
- *
- * A bssid_mask of 0010 means "only pay attention to the second least
- * significant bit". This is because its the only bit common
- * amongst the MAC and all BSSIDs we support. To findout what the real
- * common bit is we can simply "&" the bssid_mask now with any BSSID we have
- * or our MAC address (we assume the hardware uses the MAC address).
- *
- * Now, suppose there's an incoming frame for BSSID-03:
- *
- * IFRAME-01:  0110
- *
- * An easy eye-inspeciton of this already should tell you that this frame
- * will not pass our check. This is beacuse the bssid_mask tells the
- * hardware to only look at the second least significant bit and the
- * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
- * as 1, which does not match 0.
- *
- * So with IFRAME-01 we *assume* the hardware will do:
- *
- *     allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
- *  --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
- *  --> allow = (0010) == 0000 ? 1 : 0;
- *  --> allow = 0
- *
- *  Lets now test a frame that should work:
- *
- * IFRAME-02:  0001 (we should allow)
- *
- *     allow = (0001 & 1010) == 1010
- *
- *     allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
- *  --> allow = (0001 & 0010) ==  (0010 & 0001) ? 1 :0;
- *  --> allow = (0010) == (0010)
- *  --> allow = 1
- *
- * Other examples:
- *
- * IFRAME-03:  0100 --> allowed
- * IFRAME-04:  1001 --> allowed
- * IFRAME-05:  1101 --> allowed but its not for us!!!
- *
- */
-int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
-{
-	u32 low_id, high_id;
-	ATH5K_TRACE(ah->ah_sc);
-
-	/* Cache bssid mask so that we can restore it
-	 * on reset */
-	memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
-	if (ah->ah_version == AR5K_AR5212) {
-		low_id = AR5K_LOW_ID(mask);
-		high_id = AR5K_HIGH_ID(mask);
-
-		ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
-		ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
-
-		return 0;
-	}
-
-	return -EIO;
-}
-
-
-/************\
-* RX Control *
-\************/
-
-/**
- * ath5k_hw_start_rx_pcu - Start RX engine
- *
- * @ah: The &struct ath5k_hw
- *
- * Starts RX engine on PCU so that hw can process RXed frames
- * (ACK etc).
- *
- * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
- * TODO: Init ANI here
- */
-void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-}
-
-/**
- * at5k_hw_stop_rx_pcu - Stop RX engine
- *
- * @ah: The &struct ath5k_hw
- *
- * Stops RX engine on PCU
- *
- * TODO: Detach ANI here
- */
-void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-}
-
-/*
- * Set multicast filter
- */
-void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	/* Set the multicat filter */
-	ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
-	ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
-}
-
-/*
- * Set multicast filter by index
- */
-int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
-{
-
-	ATH5K_TRACE(ah->ah_sc);
-	if (index >= 64)
-		return -EINVAL;
-	else if (index >= 32)
-		AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
-				(1 << (index - 32)));
-	else
-		AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
-
-	return 0;
-}
-
-/*
- * Clear Multicast filter by index
- */
-int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
-{
-
-	ATH5K_TRACE(ah->ah_sc);
-	if (index >= 64)
-		return -EINVAL;
-	else if (index >= 32)
-		AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
-				(1 << (index - 32)));
-	else
-		AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
-
-	return 0;
-}
-
-/**
- * ath5k_hw_get_rx_filter - Get current rx filter
- *
- * @ah: The &struct ath5k_hw
- *
- * Returns the RX filter by reading rx filter and
- * phy error filter registers. RX filter is used
- * to set the allowed frame types that PCU will accept
- * and pass to the driver. For a list of frame types
- * check out reg.h.
- */
-u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
-{
-	u32 data, filter = 0;
-
-	ATH5K_TRACE(ah->ah_sc);
-	filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
-
-	/*Radar detection for 5212*/
-	if (ah->ah_version == AR5K_AR5212) {
-		data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
-
-		if (data & AR5K_PHY_ERR_FIL_RADAR)
-			filter |= AR5K_RX_FILTER_RADARERR;
-		if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
-			filter |= AR5K_RX_FILTER_PHYERR;
-	}
-
-	return filter;
-}
-
-/**
- * ath5k_hw_set_rx_filter - Set rx filter
- *
- * @ah: The &struct ath5k_hw
- * @filter: RX filter mask (see reg.h)
- *
- * Sets RX filter register and also handles PHY error filter
- * register on 5212 and newer chips so that we have proper PHY
- * error reporting.
- */
-void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
-{
-	u32 data = 0;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/* Set PHY error filter register on 5212*/
-	if (ah->ah_version == AR5K_AR5212) {
-		if (filter & AR5K_RX_FILTER_RADARERR)
-			data |= AR5K_PHY_ERR_FIL_RADAR;
-		if (filter & AR5K_RX_FILTER_PHYERR)
-			data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
-	}
-
-	/*
-	 * The AR5210 uses promiscous mode to detect radar activity
-	 */
-	if (ah->ah_version == AR5K_AR5210 &&
-			(filter & AR5K_RX_FILTER_RADARERR)) {
-		filter &= ~AR5K_RX_FILTER_RADARERR;
-		filter |= AR5K_RX_FILTER_PROM;
-	}
-
-	/*Zero length DMA (phy error reporting) */
-	if (data)
-		AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
-	else
-		AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
-
-	/*Write RX Filter register*/
-	ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
-
-	/*Write PHY error filter register on 5212*/
-	if (ah->ah_version == AR5K_AR5212)
-		ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
-
-}
-
-
-/****************\
-* Beacon control *
-\****************/
-
-/**
- * ath5k_hw_get_tsf32 - Get a 32bit TSF
- *
- * @ah: The &struct ath5k_hw
- *
- * Returns lower 32 bits of current TSF
- */
-u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
-}
-
-/**
- * ath5k_hw_get_tsf64 - Get the full 64bit TSF
- *
- * @ah: The &struct ath5k_hw
- *
- * Returns the current TSF
- */
-u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
-{
-	u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
-	ATH5K_TRACE(ah->ah_sc);
-
-	return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
-}
-
-/**
- * ath5k_hw_set_tsf64 - Set a new 64bit TSF
- *
- * @ah: The &struct ath5k_hw
- * @tsf64: The new 64bit TSF
- *
- * Sets the new TSF
- */
-void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
-{
-	ATH5K_TRACE(ah->ah_sc);
-
-	ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
-	ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
-}
-
-/**
- * ath5k_hw_reset_tsf - Force a TSF reset
- *
- * @ah: The &struct ath5k_hw
- *
- * Forces a TSF reset on PCU
- */
-void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
-{
-	u32 val;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF;
-
-	/*
-	 * Each write to the RESET_TSF bit toggles a hardware internal
-	 * signal to reset TSF, but if left high it will cause a TSF reset
-	 * on the next chip reset as well.  Thus we always write the value
-	 * twice to clear the signal.
-	 */
-	ath5k_hw_reg_write(ah, val, AR5K_BEACON);
-	ath5k_hw_reg_write(ah, val, AR5K_BEACON);
-}
-
-/*
- * Initialize beacon timers
- */
-void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
-{
-	u32 timer1, timer2, timer3;
-
-	ATH5K_TRACE(ah->ah_sc);
-	/*
-	 * Set the additional timers by mode
-	 */
-	switch (ah->ah_op_mode) {
-	case NL80211_IFTYPE_MONITOR:
-	case NL80211_IFTYPE_STATION:
-		/* In STA mode timer1 is used as next wakeup
-		 * timer and timer2 as next CFP duration start
-		 * timer. Both in 1/8TUs. */
-		/* TODO: PCF handling */
-		if (ah->ah_version == AR5K_AR5210) {
-			timer1 = 0xffffffff;
-			timer2 = 0xffffffff;
-		} else {
-			timer1 = 0x0000ffff;
-			timer2 = 0x0007ffff;
-		}
-		/* Mark associated AP as PCF incapable for now */
-		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF);
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
-	default:
-		/* On non-STA modes timer1 is used as next DMA
-		 * beacon alert (DBA) timer and timer2 as next
-		 * software beacon alert. Both in 1/8TUs. */
-		timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
-		timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
-		break;
-	}
-
-	/* Timer3 marks the end of our ATIM window
-	 * a zero length window is not allowed because
-	 * we 'll get no beacons */
-	timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
-
-	/*
-	 * Set the beacon register and enable all timers.
-	 */
-	/* When in AP mode zero timer0 to start TSF */
-	if (ah->ah_op_mode == NL80211_IFTYPE_AP)
-		ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
-	else
-		ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
-	ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
-	ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
-	ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
-
-	/* Force a TSF reset if requested and enable beacons */
-	if (interval & AR5K_BEACON_RESET_TSF)
-		ath5k_hw_reset_tsf(ah);
-
-	ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
-					AR5K_BEACON_ENABLE),
-						AR5K_BEACON);
-
-	/* Flush any pending BMISS interrupts on ISR by
-	 * performing a clear-on-write operation on PISR
-	 * register for the BMISS bit (writing a bit on
-	 * ISR togles a reset for that bit and leaves
-	 * the rest bits intact) */
-	if (ah->ah_version == AR5K_AR5210)
-		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
-	else
-		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
-
-	/* TODO: Set enchanced sleep registers on AR5212
-	 * based on vif->bss_conf params, until then
-	 * disable power save reporting.*/
-	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
-
-}
-
-#if 0
-/*
- * Set beacon timers
- */
-int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
-		const struct ath5k_beacon_state *state)
-{
-	u32 cfp_period, next_cfp, dtim, interval, next_beacon;
-
-	/*
-	 * TODO: should be changed through *state
-	 * review struct ath5k_beacon_state struct
-	 *
-	 * XXX: These are used for cfp period bellow, are they
-	 * ok ? Is it O.K. for tsf here to be 0 or should we use
-	 * get_tsf ?
-	 */
-	u32 dtim_count = 0; /* XXX */
-	u32 cfp_count = 0; /* XXX */
-	u32 tsf = 0; /* XXX */
-
-	ATH5K_TRACE(ah->ah_sc);
-	/* Return on an invalid beacon state */
-	if (state->bs_interval < 1)
-		return -EINVAL;
-
-	interval = state->bs_interval;
-	dtim = state->bs_dtim_period;
-
-	/*
-	 * PCF support?
-	 */
-	if (state->bs_cfp_period > 0) {
-		/*
-		 * Enable PCF mode and set the CFP
-		 * (Contention Free Period) and timer registers
-		 */
-		cfp_period = state->bs_cfp_period * state->bs_dtim_period *
-			state->bs_interval;
-		next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
-			state->bs_interval;
-
-		AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
-				AR5K_STA_ID1_DEFAULT_ANTENNA |
-				AR5K_STA_ID1_PCF);
-		ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
-		ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
-				AR5K_CFP_DUR);
-		ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
-						next_cfp)) << 3, AR5K_TIMER2);
-	} else {
-		/* Disable PCF mode */
-		AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
-				AR5K_STA_ID1_DEFAULT_ANTENNA |
-				AR5K_STA_ID1_PCF);
-	}
-
-	/*
-	 * Enable the beacon timer register
-	 */
-	ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
-
-	/*
-	 * Start the beacon timers
-	 */
-	ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &
-		~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
-		AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
-		AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
-		AR5K_BEACON_PERIOD), AR5K_BEACON);
-
-	/*
-	 * Write new beacon miss threshold, if it appears to be valid
-	 * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
-	 * and return if its not in range. We can test this by reading value and
-	 * setting value to a largest value and seeing which values register.
-	 */
-
-	AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
-			state->bs_bmiss_threshold);
-
-	/*
-	 * Set sleep control register
-	 * XXX: Didn't find this in 5210 code but since this register
-	 * exists also in ar5k's 5210 headers i leave it as common code.
-	 */
-	AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
-			(state->bs_sleep_duration - 3) << 3);
-
-	/*
-	 * Set enhanced sleep registers on 5212
-	 */
-	if (ah->ah_version == AR5K_AR5212) {
-		if (state->bs_sleep_duration > state->bs_interval &&
-				roundup(state->bs_sleep_duration, interval) ==
-				state->bs_sleep_duration)
-			interval = state->bs_sleep_duration;
-
-		if (state->bs_sleep_duration > dtim && (dtim == 0 ||
-				roundup(state->bs_sleep_duration, dtim) ==
-				state->bs_sleep_duration))
-			dtim = state->bs_sleep_duration;
-
-		if (interval > dtim)
-			return -EINVAL;
-
-		next_beacon = interval == dtim ? state->bs_next_dtim :
-			state->bs_next_beacon;
-
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
-			AR5K_SLEEP0_NEXT_DTIM) |
-			AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
-			AR5K_SLEEP0_ENH_SLEEP_EN |
-			AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
-
-		ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
-			AR5K_SLEEP1_NEXT_TIM) |
-			AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
-
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
-			AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
-	}
-
-	return 0;
-}
-
-/*
- * Reset beacon timers
- */
-void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	/*
-	 * Disable beacon timer
-	 */
-	ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
-
-	/*
-	 * Disable some beacon register values
-	 */
-	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
-			AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
-	ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
-}
-
-/*
- * Wait for beacon queue to finish
- */
-int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
-{
-	unsigned int i;
-	int ret;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/* 5210 doesn't have QCU*/
-	if (ah->ah_version == AR5K_AR5210) {
-		/*
-		 * Wait for beaconn queue to finish by checking
-		 * Control Register and Beacon Status Register.
-		 */
-		for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
-			if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
-					||
-			    !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
-				break;
-			udelay(10);
-		}
-
-		/* Timeout... */
-		if (i <= 0) {
-			/*
-			 * Re-schedule the beacon queue
-			 */
-			ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
-			ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
-					AR5K_BCR);
-
-			return -EIO;
-		}
-		ret = 0;
-	} else {
-	/*5211/5212*/
-		ret = ath5k_hw_register_timeout(ah,
-			AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
-			AR5K_QCU_STS_FRMPENDCNT, 0, false);
-
-		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
-			return -EIO;
-	}
-
-	return ret;
-}
-#endif
-
-
-/*********************\
-* Key table functions *
-\*********************/
-
-/*
- * Reset a key entry on the table
- */
-int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
-{
-	unsigned int i, type;
-	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
-
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
-	type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
-
-	for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
-		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
-
-	/* Reset associated MIC entry if TKIP
-	 * is enabled located at offset (entry + 64) */
-	if (type == AR5K_KEYTABLE_TYPE_TKIP) {
-		AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
-		for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
-			ath5k_hw_reg_write(ah, 0,
-				AR5K_KEYTABLE_OFF(micentry, i));
-	}
-
-	/*
-	 * Set NULL encryption on AR5212+
-	 *
-	 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
-	 *       AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
-	 *
-	 * Note2: Windows driver (ndiswrapper) sets this to
-	 *        0x00000714 instead of 0x00000007
-	 */
-	if (ah->ah_version > AR5K_AR5211) {
-		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
-				AR5K_KEYTABLE_TYPE(entry));
-
-		if (type == AR5K_KEYTABLE_TYPE_TKIP) {
-			ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
-				AR5K_KEYTABLE_TYPE(micentry));
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Check if a table entry is valid
- */
-int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
-	/* Check the validation flag at the end of the entry */
-	return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
-		AR5K_KEYTABLE_VALID;
-}
-
-static
-int ath5k_keycache_type(const struct ieee80211_key_conf *key)
-{
-	switch (key->alg) {
-	case ALG_TKIP:
-		return AR5K_KEYTABLE_TYPE_TKIP;
-	case ALG_CCMP:
-		return AR5K_KEYTABLE_TYPE_CCM;
-	case ALG_WEP:
-		if (key->keylen == LEN_WEP40)
-			return AR5K_KEYTABLE_TYPE_40;
-		else if (key->keylen == LEN_WEP104)
-			return AR5K_KEYTABLE_TYPE_104;
-		return -EINVAL;
-	default:
-		return -EINVAL;
-	}
-	return -EINVAL;
-}
-
-/*
- * Set a key entry on the table
- */
-int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
-		const struct ieee80211_key_conf *key, const u8 *mac)
-{
-	unsigned int i;
-	int keylen;
-	__le32 key_v[5] = {};
-	__le32 key0 = 0, key1 = 0;
-	__le32 *rxmic, *txmic;
-	int keytype;
-	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
-	bool is_tkip;
-	const u8 *key_ptr;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	is_tkip = (key->alg == ALG_TKIP);
-
-	/*
-	 * key->keylen comes in from mac80211 in bytes.
-	 * TKIP is 128 bit + 128 bit mic
-	 */
-	keylen = (is_tkip) ? (128 / 8) : key->keylen;
-
-	if (entry > AR5K_KEYTABLE_SIZE ||
-		(is_tkip && micentry > AR5K_KEYTABLE_SIZE))
-		return -EOPNOTSUPP;
-
-	if (unlikely(keylen > 16))
-		return -EOPNOTSUPP;
-
-	keytype = ath5k_keycache_type(key);
-	if (keytype < 0)
-		return keytype;
-
-	/*
-	 * each key block is 6 bytes wide, written as pairs of
-	 * alternating 32 and 16 bit le values.
-	 */
-	key_ptr = key->key;
-	for (i = 0; keylen >= 6; keylen -= 6) {
-		memcpy(&key_v[i], key_ptr, 6);
-		i += 2;
-		key_ptr += 6;
-	}
-	if (keylen)
-		memcpy(&key_v[i], key_ptr, keylen);
-
-	/* intentionally corrupt key until mic is installed */
-	if (is_tkip) {
-		key0 = key_v[0] = ~key_v[0];
-		key1 = key_v[1] = ~key_v[1];
-	}
-
-	for (i = 0; i < ARRAY_SIZE(key_v); i++)
-		ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
-				AR5K_KEYTABLE_OFF(entry, i));
-
-	ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
-
-	if (is_tkip) {
-		/* Install rx/tx MIC */
-		rxmic = (__le32 *) &key->key[16];
-		txmic = (__le32 *) &key->key[24];
-
-		if (ah->ah_combined_mic) {
-			key_v[0] = rxmic[0];
-			key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16);
-			key_v[2] = rxmic[1];
-			key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff);
-			key_v[4] = txmic[1];
-		} else {
-			key_v[0] = rxmic[0];
-			key_v[1] = 0;
-			key_v[2] = rxmic[1];
-			key_v[3] = 0;
-			key_v[4] = 0;
-		}
-		for (i = 0; i < ARRAY_SIZE(key_v); i++)
-			ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
-				AR5K_KEYTABLE_OFF(micentry, i));
-
-		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
-			AR5K_KEYTABLE_TYPE(micentry));
-		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
-		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
-
-		/* restore first 2 words of key */
-		ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
-			AR5K_KEYTABLE_OFF(entry, 0));
-		ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
-			AR5K_KEYTABLE_OFF(entry, 1));
-	}
-
-	return ath5k_hw_set_key_lladdr(ah, entry, mac);
-}
-
-int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
-{
-	u32 low_id, high_id;
-
-	ATH5K_TRACE(ah->ah_sc);
-	 /* Invalid entry (key table overflow) */
-	AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
-	/* MAC may be NULL if it's a broadcast key. In this case no need to
-	 * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
-	if (!mac) {
-		low_id = 0xffffffff;
-		high_id = 0xffff | AR5K_KEYTABLE_VALID;
-	} else {
-		low_id = AR5K_LOW_ID(mac);
-		high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
-	}
-
-	ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
-	ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
-
-	return 0;
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/phy.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/phy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2606 +0,0 @@
-/*
- * PHY functions
- *
- * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
- * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#define _ATH5K_PHY
-
-#include <linux/delay.h>
-
-#include "ath5k.h"
-#include "reg.h"
-#include "base.h"
-#include "rfbuffer.h"
-#include "rfgain.h"
-
-/*
- * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
- */
-static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
-					const struct ath5k_rf_reg *rf_regs,
-					u32 val, u8 reg_id, bool set)
-{
-	const struct ath5k_rf_reg *rfreg = NULL;
-	u8 offset, bank, num_bits, col, position;
-	u16 entry;
-	u32 mask, data, last_bit, bits_shifted, first_bit;
-	u32 *rfb;
-	s32 bits_left;
-	int i;
-
-	data = 0;
-	rfb = ah->ah_rf_banks;
-
-	for (i = 0; i < ah->ah_rf_regs_count; i++) {
-		if (rf_regs[i].index == reg_id) {
-			rfreg = &rf_regs[i];
-			break;
-		}
-	}
-
-	if (rfb == NULL || rfreg == NULL) {
-		ATH5K_PRINTF("Rf register not found!\n");
-		/* should not happen */
-		return 0;
-	}
-
-	bank = rfreg->bank;
-	num_bits = rfreg->field.len;
-	first_bit = rfreg->field.pos;
-	col = rfreg->field.col;
-
-	/* first_bit is an offset from bank's
-	 * start. Since we have all banks on
-	 * the same array, we use this offset
-	 * to mark each bank's start */
-	offset = ah->ah_offset[bank];
-
-	/* Boundary check */
-	if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) {
-		ATH5K_PRINTF("invalid values at offset %u\n", offset);
-		return 0;
-	}
-
-	entry = ((first_bit - 1) / 8) + offset;
-	position = (first_bit - 1) % 8;
-
-	if (set)
-		data = ath5k_hw_bitswap(val, num_bits);
-
-	for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
-	position = 0, entry++) {
-
-		last_bit = (position + bits_left > 8) ? 8 :
-					position + bits_left;
-
-		mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) <<
-								(col * 8);
-
-		if (set) {
-			rfb[entry] &= ~mask;
-			rfb[entry] |= ((data << position) << (col * 8)) & mask;
-			data >>= (8 - position);
-		} else {
-			data |= (((rfb[entry] & mask) >> (col * 8)) >> position)
-				<< bits_shifted;
-			bits_shifted += last_bit - position;
-		}
-
-		bits_left -= 8 - position;
-	}
-
-	data = set ? 1 : ath5k_hw_bitswap(data, num_bits);
-
-	return data;
-}
-
-/**********************\
-* RF Gain optimization *
-\**********************/
-
-/*
- * This code is used to optimize rf gain on different environments
- * (temprature mostly) based on feedback from a power detector.
- *
- * It's only used on RF5111 and RF5112, later RF chips seem to have
- * auto adjustment on hw -notice they have a much smaller BANK 7 and
- * no gain optimization ladder-.
- *
- * For more infos check out this patent doc
- * http://www.freepatentsonline.com/7400691.html
- *
- * This paper describes power drops as seen on the receiver due to
- * probe packets
- * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues
- * %20of%20Power%20Control.pdf
- *
- * And this is the MadWiFi bug entry related to the above
- * http://madwifi-project.org/ticket/1659
- * with various measurements and diagrams
- *
- * TODO: Deal with power drops due to probes by setting an apropriate
- * tx power on the probe packets ! Make this part of the calibration process.
- */
-
-/* Initialize ah_gain durring attach */
-int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
-{
-	/* Initialize the gain optimization values */
-	switch (ah->ah_radio) {
-	case AR5K_RF5111:
-		ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
-		ah->ah_gain.g_low = 20;
-		ah->ah_gain.g_high = 35;
-		ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
-		break;
-	case AR5K_RF5112:
-		ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
-		ah->ah_gain.g_low = 20;
-		ah->ah_gain.g_high = 85;
-		ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* Schedule a gain probe check on the next transmited packet.
- * That means our next packet is going to be sent with lower
- * tx power and a Peak to Average Power Detector (PAPD) will try
- * to measure the gain.
- *
- * TODO: Use propper tx power setting for the probe packet so
- * that we don't observe a serious power drop on the receiver
- *
- * XXX:  How about forcing a tx packet (bypassing PCU arbitrator etc)
- * just after we enable the probe so that we don't mess with
- * standard traffic ? Maybe it's time to use sw interrupts and
- * a probe tasklet !!!
- */
-static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
-{
-
-	/* Skip if gain calibration is inactive or
-	 * we already handle a probe request */
-	if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE)
-		return;
-
-	/* Send the packet with 2dB below max power as
-	 * patent doc suggest */
-	ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4,
-			AR5K_PHY_PAPD_PROBE_TXPOWER) |
-			AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
-
-	ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED;
-
-}
-
-/* Calculate gain_F measurement correction
- * based on the current step for RF5112 rev. 2 */
-static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
-{
-	u32 mix, step;
-	u32 *rf;
-	const struct ath5k_gain_opt *go;
-	const struct ath5k_gain_opt_step *g_step;
-	const struct ath5k_rf_reg *rf_regs;
-
-	/* Only RF5112 Rev. 2 supports it */
-	if ((ah->ah_radio != AR5K_RF5112) ||
-	(ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A))
-		return 0;
-
-	go = &rfgain_opt_5112;
-	rf_regs = rf_regs_5112a;
-	ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
-
-	g_step = &go->go_step[ah->ah_gain.g_step_idx];
-
-	if (ah->ah_rf_banks == NULL)
-		return 0;
-
-	rf = ah->ah_rf_banks;
-	ah->ah_gain.g_f_corr = 0;
-
-	/* No VGA (Variable Gain Amplifier) override, skip */
-	if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1)
-		return 0;
-
-	/* Mix gain stepping */
-	step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false);
-
-	/* Mix gain override */
-	mix = g_step->gos_param[0];
-
-	switch (mix) {
-	case 3:
-		ah->ah_gain.g_f_corr = step * 2;
-		break;
-	case 2:
-		ah->ah_gain.g_f_corr = (step - 5) * 2;
-		break;
-	case 1:
-		ah->ah_gain.g_f_corr = step;
-		break;
-	default:
-		ah->ah_gain.g_f_corr = 0;
-		break;
-	}
-
-	return ah->ah_gain.g_f_corr;
-}
-
-/* Check if current gain_F measurement is in the range of our
- * power detector windows. If we get a measurement outside range
- * we know it's not accurate (detectors can't measure anything outside
- * their detection window) so we must ignore it */
-static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
-{
-	const struct ath5k_rf_reg *rf_regs;
-	u32 step, mix_ovr, level[4];
-	u32 *rf;
-
-	if (ah->ah_rf_banks == NULL)
-		return false;
-
-	rf = ah->ah_rf_banks;
-
-	if (ah->ah_radio == AR5K_RF5111) {
-
-		rf_regs = rf_regs_5111;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
-
-		step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP,
-			false);
-
-		level[0] = 0;
-		level[1] = (step == 63) ? 50 : step + 4;
-		level[2] = (step != 63) ? 64 : level[0];
-		level[3] = level[2] + 50 ;
-
-		ah->ah_gain.g_high = level[3] -
-			(step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
-		ah->ah_gain.g_low = level[0] +
-			(step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
-	} else {
-
-		rf_regs = rf_regs_5112;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
-
-		mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR,
-			false);
-
-		level[0] = level[2] = 0;
-
-		if (mix_ovr == 1) {
-			level[1] = level[3] = 83;
-		} else {
-			level[1] = level[3] = 107;
-			ah->ah_gain.g_high = 55;
-		}
-	}
-
-	return (ah->ah_gain.g_current >= level[0] &&
-			ah->ah_gain.g_current <= level[1]) ||
-		(ah->ah_gain.g_current >= level[2] &&
-			ah->ah_gain.g_current <= level[3]);
-}
-
-/* Perform gain_F adjustment by choosing the right set
- * of parameters from rf gain optimization ladder */
-static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
-{
-	const struct ath5k_gain_opt *go;
-	const struct ath5k_gain_opt_step *g_step;
-	int ret = 0;
-
-	switch (ah->ah_radio) {
-	case AR5K_RF5111:
-		go = &rfgain_opt_5111;
-		break;
-	case AR5K_RF5112:
-		go = &rfgain_opt_5112;
-		break;
-	default:
-		return 0;
-	}
-
-	g_step = &go->go_step[ah->ah_gain.g_step_idx];
-
-	if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
-
-		/* Reached maximum */
-		if (ah->ah_gain.g_step_idx == 0)
-			return -1;
-
-		for (ah->ah_gain.g_target = ah->ah_gain.g_current;
-				ah->ah_gain.g_target >=  ah->ah_gain.g_high &&
-				ah->ah_gain.g_step_idx > 0;
-				g_step = &go->go_step[ah->ah_gain.g_step_idx])
-			ah->ah_gain.g_target -= 2 *
-			    (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
-			    g_step->gos_gain);
-
-		ret = 1;
-		goto done;
-	}
-
-	if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
-
-		/* Reached minimum */
-		if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
-			return -2;
-
-		for (ah->ah_gain.g_target = ah->ah_gain.g_current;
-				ah->ah_gain.g_target <= ah->ah_gain.g_low &&
-				ah->ah_gain.g_step_idx < go->go_steps_count-1;
-				g_step = &go->go_step[ah->ah_gain.g_step_idx])
-			ah->ah_gain.g_target -= 2 *
-			    (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
-			    g_step->gos_gain);
-
-		ret = 2;
-		goto done;
-	}
-
-done:
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
-		"ret %d, gain step %u, current gain %u, target gain %u\n",
-		ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
-		ah->ah_gain.g_target);
-
-	return ret;
-}
-
-/* Main callback for thermal rf gain calibration engine
- * Check for a new gain reading and schedule an adjustment
- * if needed.
- *
- * TODO: Use sw interrupt to schedule reset if gain_F needs
- * adjustment */
-enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
-{
-	u32 data, type;
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	if (ah->ah_rf_banks == NULL ||
-	ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
-		return AR5K_RFGAIN_INACTIVE;
-
-	/* No check requested, either engine is inactive
-	 * or an adjustment is already requested */
-	if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED)
-		goto done;
-
-	/* Read the PAPD (Peak to Average Power Detector)
-	 * register */
-	data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
-
-	/* No probe is scheduled, read gain_F measurement */
-	if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
-		ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
-		type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
-
-		/* If tx packet is CCK correct the gain_F measurement
-		 * by cck ofdm gain delta */
-		if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) {
-			if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
-				ah->ah_gain.g_current +=
-					ee->ee_cck_ofdm_gain_delta;
-			else
-				ah->ah_gain.g_current +=
-					AR5K_GAIN_CCK_PROBE_CORR;
-		}
-
-		/* Further correct gain_F measurement for
-		 * RF5112A radios */
-		if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
-			ath5k_hw_rf_gainf_corr(ah);
-			ah->ah_gain.g_current =
-				ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
-				(ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
-				0;
-		}
-
-		/* Check if measurement is ok and if we need
-		 * to adjust gain, schedule a gain adjustment,
-		 * else switch back to the acive state */
-		if (ath5k_hw_rf_check_gainf_readback(ah) &&
-		AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
-		ath5k_hw_rf_gainf_adjust(ah)) {
-			ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE;
-		} else {
-			ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
-		}
-	}
-
-done:
-	return ah->ah_gain.g_state;
-}
-
-/* Write initial rf gain table to set the RF sensitivity
- * this one works on all RF chips and has nothing to do
- * with gain_F calibration */
-int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
-{
-	const struct ath5k_ini_rfgain *ath5k_rfg;
-	unsigned int i, size;
-
-	switch (ah->ah_radio) {
-	case AR5K_RF5111:
-		ath5k_rfg = rfgain_5111;
-		size = ARRAY_SIZE(rfgain_5111);
-		break;
-	case AR5K_RF5112:
-		ath5k_rfg = rfgain_5112;
-		size = ARRAY_SIZE(rfgain_5112);
-		break;
-	case AR5K_RF2413:
-		ath5k_rfg = rfgain_2413;
-		size = ARRAY_SIZE(rfgain_2413);
-		break;
-	case AR5K_RF2316:
-		ath5k_rfg = rfgain_2316;
-		size = ARRAY_SIZE(rfgain_2316);
-		break;
-	case AR5K_RF5413:
-		ath5k_rfg = rfgain_5413;
-		size = ARRAY_SIZE(rfgain_5413);
-		break;
-	case AR5K_RF2317:
-	case AR5K_RF2425:
-		ath5k_rfg = rfgain_2425;
-		size = ARRAY_SIZE(rfgain_2425);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (freq) {
-	case AR5K_INI_RFGAIN_2GHZ:
-	case AR5K_INI_RFGAIN_5GHZ:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (i = 0; i < size; i++) {
-		AR5K_REG_WAIT(i);
-		ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
-			(u32)ath5k_rfg[i].rfg_register);
-	}
-
-	return 0;
-}
-
-
-
-/********************\
-* RF Registers setup *
-\********************/
-
-
-/*
- * Setup RF registers by writing rf buffer on hw
- */
-int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
-		unsigned int mode)
-{
-	const struct ath5k_rf_reg *rf_regs;
-	const struct ath5k_ini_rfbuffer *ini_rfb;
-	const struct ath5k_gain_opt *go = NULL;
-	const struct ath5k_gain_opt_step *g_step;
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u8 ee_mode = 0;
-	u32 *rfb;
-	int i, obdb = -1, bank = -1;
-
-	switch (ah->ah_radio) {
-	case AR5K_RF5111:
-		rf_regs = rf_regs_5111;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
-		ini_rfb = rfb_5111;
-		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111);
-		go = &rfgain_opt_5111;
-		break;
-	case AR5K_RF5112:
-		if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
-			rf_regs = rf_regs_5112a;
-			ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
-			ini_rfb = rfb_5112a;
-			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a);
-		} else {
-			rf_regs = rf_regs_5112;
-			ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
-			ini_rfb = rfb_5112;
-			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112);
-		}
-		go = &rfgain_opt_5112;
-		break;
-	case AR5K_RF2413:
-		rf_regs = rf_regs_2413;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413);
-		ini_rfb = rfb_2413;
-		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413);
-		break;
-	case AR5K_RF2316:
-		rf_regs = rf_regs_2316;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316);
-		ini_rfb = rfb_2316;
-		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316);
-		break;
-	case AR5K_RF5413:
-		rf_regs = rf_regs_5413;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413);
-		ini_rfb = rfb_5413;
-		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413);
-		break;
-	case AR5K_RF2317:
-		rf_regs = rf_regs_2425;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
-		ini_rfb = rfb_2317;
-		ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317);
-		break;
-	case AR5K_RF2425:
-		rf_regs = rf_regs_2425;
-		ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
-		if (ah->ah_mac_srev < AR5K_SREV_AR2417) {
-			ini_rfb = rfb_2425;
-			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425);
-		} else {
-			ini_rfb = rfb_2417;
-			ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417);
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* If it's the first time we set rf buffer, allocate
-	 * ah->ah_rf_banks based on ah->ah_rf_banks_size
-	 * we set above */
-	if (ah->ah_rf_banks == NULL) {
-		ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
-								GFP_KERNEL);
-		if (ah->ah_rf_banks == NULL) {
-			ATH5K_ERR(ah->ah_sc, "out of memory\n");
-			return -ENOMEM;
-		}
-	}
-
-	/* Copy values to modify them */
-	rfb = ah->ah_rf_banks;
-
-	for (i = 0; i < ah->ah_rf_banks_size; i++) {
-		if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
-			ATH5K_ERR(ah->ah_sc, "invalid bank\n");
-			return -EINVAL;
-		}
-
-		/* Bank changed, write down the offset */
-		if (bank != ini_rfb[i].rfb_bank) {
-			bank = ini_rfb[i].rfb_bank;
-			ah->ah_offset[bank] = i;
-		}
-
-		rfb[i] = ini_rfb[i].rfb_mode_data[mode];
-	}
-
-	/* Set Output and Driver bias current (OB/DB) */
-	if (channel->hw_value & CHANNEL_2GHZ) {
-
-		if (channel->hw_value & CHANNEL_CCK)
-			ee_mode = AR5K_EEPROM_MODE_11B;
-		else
-			ee_mode = AR5K_EEPROM_MODE_11G;
-
-		/* For RF511X/RF211X combination we
-		 * use b_OB and b_DB parameters stored
-		 * in eeprom on ee->ee_ob[ee_mode][0]
-		 *
-		 * For all other chips we use OB/DB for 2Ghz
-		 * stored in the b/g modal section just like
-		 * 802.11a on ee->ee_ob[ee_mode][1] */
-		if ((ah->ah_radio == AR5K_RF5111) ||
-		(ah->ah_radio == AR5K_RF5112))
-			obdb = 0;
-		else
-			obdb = 1;
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
-						AR5K_RF_OB_2GHZ, true);
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
-						AR5K_RF_DB_2GHZ, true);
-
-	/* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
-	} else if ((channel->hw_value & CHANNEL_5GHZ) ||
-			(ah->ah_radio == AR5K_RF5111)) {
-
-		/* For 11a, Turbo and XR we need to choose
-		 * OB/DB based on frequency range */
-		ee_mode = AR5K_EEPROM_MODE_11A;
-		obdb =	 channel->center_freq >= 5725 ? 3 :
-			(channel->center_freq >= 5500 ? 2 :
-			(channel->center_freq >= 5260 ? 1 :
-			 (channel->center_freq > 4000 ? 0 : -1)));
-
-		if (obdb < 0)
-			return -EINVAL;
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
-						AR5K_RF_OB_5GHZ, true);
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
-						AR5K_RF_DB_5GHZ, true);
-	}
-
-	g_step = &go->go_step[ah->ah_gain.g_step_idx];
-
-	/* Bank Modifications (chip-specific) */
-	if (ah->ah_radio == AR5K_RF5111) {
-
-		/* Set gain_F settings according to current step */
-		if (channel->hw_value & CHANNEL_OFDM) {
-
-			AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
-					AR5K_PHY_FRAME_CTL_TX_CLIP,
-					g_step->gos_param[0]);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
-							AR5K_RF_PWD_90, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
-							AR5K_RF_PWD_84, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
-						AR5K_RF_RFGAIN_SEL, true);
-
-			/* We programmed gain_F parameters, switch back
-			 * to active state */
-			ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
-
-		}
-
-		/* Bank 6/7 setup */
-
-		ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode],
-						AR5K_RF_PWD_XPD, true);
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode],
-						AR5K_RF_XPD_GAIN, true);
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
-						AR5K_RF_GAIN_I, true);
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
-						AR5K_RF_PLO_SEL, true);
-
-		/* TODO: Half/quarter channel support */
-	}
-
-	if (ah->ah_radio == AR5K_RF5112) {
-
-		/* Set gain_F settings according to current step */
-		if (channel->hw_value & CHANNEL_OFDM) {
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
-						AR5K_RF_MIXGAIN_OVR, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
-						AR5K_RF_PWD_138, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
-						AR5K_RF_PWD_137, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
-						AR5K_RF_PWD_136, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4],
-						AR5K_RF_PWD_132, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5],
-						AR5K_RF_PWD_131, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6],
-						AR5K_RF_PWD_130, true);
-
-			/* We programmed gain_F parameters, switch back
-			 * to active state */
-			ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
-		}
-
-		/* Bank 6/7 setup */
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
-						AR5K_RF_XPD_SEL, true);
-
-		if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
-			/* Rev. 1 supports only one xpd */
-			ath5k_hw_rfb_op(ah, rf_regs,
-						ee->ee_x_gain[ee_mode],
-						AR5K_RF_XPD_GAIN, true);
-
-		} else {
-			/* TODO: Set high and low gain bits */
-			ath5k_hw_rfb_op(ah, rf_regs,
-						ee->ee_x_gain[ee_mode],
-						AR5K_RF_PD_GAIN_LO, true);
-			ath5k_hw_rfb_op(ah, rf_regs,
-						ee->ee_x_gain[ee_mode],
-						AR5K_RF_PD_GAIN_HI, true);
-
-			/* Lower synth voltage on Rev 2 */
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_HIGH_VC_CP, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_MID_VC_CP, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_LOW_VC_CP, true);
-
-			ath5k_hw_rfb_op(ah, rf_regs, 2,
-					AR5K_RF_PUSH_UP, true);
-
-			/* Decrease power consumption on 5213+ BaseBand */
-			if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
-				ath5k_hw_rfb_op(ah, rf_regs, 1,
-						AR5K_RF_PAD2GND, true);
-
-				ath5k_hw_rfb_op(ah, rf_regs, 1,
-						AR5K_RF_XB2_LVL, true);
-
-				ath5k_hw_rfb_op(ah, rf_regs, 1,
-						AR5K_RF_XB5_LVL, true);
-
-				ath5k_hw_rfb_op(ah, rf_regs, 1,
-						AR5K_RF_PWD_167, true);
-
-				ath5k_hw_rfb_op(ah, rf_regs, 1,
-						AR5K_RF_PWD_166, true);
-			}
-		}
-
-		ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
-						AR5K_RF_GAIN_I, true);
-
-		/* TODO: Half/quarter channel support */
-
-	}
-
-	if (ah->ah_radio == AR5K_RF5413 &&
-	channel->hw_value & CHANNEL_2GHZ) {
-
-		ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
-									true);
-
-		/* Set optimum value for early revisions (on pci-e chips) */
-		if (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
-		ah->ah_mac_srev < AR5K_SREV_AR5413)
-			ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3),
-						AR5K_RF_PWD_ICLOBUF_2G, true);
-
-	}
-
-	/* Write RF banks on hw */
-	for (i = 0; i < ah->ah_rf_banks_size; i++) {
-		AR5K_REG_WAIT(i);
-		ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register);
-	}
-
-	return 0;
-}
-
-
-/**************************\
-  PHY/RF channel functions
-\**************************/
-
-/*
- * Check if a channel is supported
- */
-bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
-{
-	/* Check if the channel is in our supported range */
-	if (flags & CHANNEL_2GHZ) {
-		if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
-		    (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
-			return true;
-	} else if (flags & CHANNEL_5GHZ)
-		if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
-		    (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
-			return true;
-
-	return false;
-}
-
-/*
- * Convertion needed for RF5110
- */
-static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
-{
-	u32 athchan;
-
-	/*
-	 * Convert IEEE channel/MHz to an internal channel value used
-	 * by the AR5210 chipset. This has not been verified with
-	 * newer chipsets like the AR5212A who have a completely
-	 * different RF/PHY part.
-	 */
-	athchan = (ath5k_hw_bitswap(
-			(ieee80211_frequency_to_channel(
-				channel->center_freq) - 24) / 2, 5)
-				<< 1) | (1 << 6) | 0x1;
-	return athchan;
-}
-
-/*
- * Set channel on RF5110
- */
-static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
-{
-	u32 data;
-
-	/*
-	 * Set the channel and wait
-	 */
-	data = ath5k_hw_rf5110_chan2athchan(channel);
-	ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
-	ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
-	mdelay(1);
-
-	return 0;
-}
-
-/*
- * Convertion needed for 5111
- */
-static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
-		struct ath5k_athchan_2ghz *athchan)
-{
-	int channel;
-
-	/* Cast this value to catch negative channel numbers (>= -19) */
-	channel = (int)ieee;
-
-	/*
-	 * Map 2GHz IEEE channel to 5GHz Atheros channel
-	 */
-	if (channel <= 13) {
-		athchan->a2_athchan = 115 + channel;
-		athchan->a2_flags = 0x46;
-	} else if (channel == 14) {
-		athchan->a2_athchan = 124;
-		athchan->a2_flags = 0x44;
-	} else if (channel >= 15 && channel <= 26) {
-		athchan->a2_athchan = ((channel - 14) * 4) + 132;
-		athchan->a2_flags = 0x46;
-	} else
-		return -EINVAL;
-
-	return 0;
-}
-
-/*
- * Set channel on 5111
- */
-static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
-{
-	struct ath5k_athchan_2ghz ath5k_channel_2ghz;
-	unsigned int ath5k_channel =
-		ieee80211_frequency_to_channel(channel->center_freq);
-	u32 data0, data1, clock;
-	int ret;
-
-	/*
-	 * Set the channel on the RF5111 radio
-	 */
-	data0 = data1 = 0;
-
-	if (channel->hw_value & CHANNEL_2GHZ) {
-		/* Map 2GHz channel to 5GHz Atheros channel ID */
-		ret = ath5k_hw_rf5111_chan2athchan(
-			ieee80211_frequency_to_channel(channel->center_freq),
-			&ath5k_channel_2ghz);
-		if (ret)
-			return ret;
-
-		ath5k_channel = ath5k_channel_2ghz.a2_athchan;
-		data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
-		    << 5) | (1 << 4);
-	}
-
-	if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
-		clock = 1;
-		data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
-			(clock << 1) | (1 << 10) | 1;
-	} else {
-		clock = 0;
-		data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
-			<< 2) | (clock << 1) | (1 << 10) | 1;
-	}
-
-	ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
-			AR5K_RF_BUFFER);
-	ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
-			AR5K_RF_BUFFER_CONTROL_3);
-
-	return 0;
-}
-
-/*
- * Set channel on 5112 and newer
- */
-static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
-{
-	u32 data, data0, data1, data2;
-	u16 c;
-
-	data = data0 = data1 = data2 = 0;
-	c = channel->center_freq;
-
-	if (c < 4800) {
-		if (!((c - 2224) % 5)) {
-			data0 = ((2 * (c - 704)) - 3040) / 10;
-			data1 = 1;
-		} else if (!((c - 2192) % 5)) {
-			data0 = ((2 * (c - 672)) - 3040) / 10;
-			data1 = 0;
-		} else
-			return -EINVAL;
-
-		data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
-	} else if ((c - (c % 5)) != 2 || c > 5435) {
-		if (!(c % 20) && c >= 5120) {
-			data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
-			data2 = ath5k_hw_bitswap(3, 2);
-		} else if (!(c % 10)) {
-			data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
-			data2 = ath5k_hw_bitswap(2, 2);
-		} else if (!(c % 5)) {
-			data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
-			data2 = ath5k_hw_bitswap(1, 2);
-		} else
-			return -EINVAL;
-	} else {
-		data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
-		data2 = ath5k_hw_bitswap(0, 2);
-	}
-
-	data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
-
-	ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
-	ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
-
-	return 0;
-}
-
-/*
- * Set the channel on the RF2425
- */
-static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
-{
-	u32 data, data0, data2;
-	u16 c;
-
-	data = data0 = data2 = 0;
-	c = channel->center_freq;
-
-	if (c < 4800) {
-		data0 = ath5k_hw_bitswap((c - 2272), 8);
-		data2 = 0;
-	/* ? 5GHz ? */
-	} else if ((c - (c % 5)) != 2 || c > 5435) {
-		if (!(c % 20) && c < 5120)
-			data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
-		else if (!(c % 10))
-			data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
-		else if (!(c % 5))
-			data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
-		else
-			return -EINVAL;
-		data2 = ath5k_hw_bitswap(1, 2);
-	} else {
-		data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
-		data2 = ath5k_hw_bitswap(0, 2);
-	}
-
-	data = (data0 << 4) | data2 << 2 | 0x1001;
-
-	ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
-	ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
-
-	return 0;
-}
-
-/*
- * Set a channel on the radio chip
- */
-int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
-{
-	int ret;
-	/*
-	 * Check bounds supported by the PHY (we don't care about regultory
-	 * restrictions at this point). Note: hw_value already has the band
-	 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
-	 * of the band by that */
-	if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
-		ATH5K_ERR(ah->ah_sc,
-			"channel frequency (%u MHz) out of supported "
-			"band range\n",
-			channel->center_freq);
-			return -EINVAL;
-	}
-
-	/*
-	 * Set the channel and wait
-	 */
-	switch (ah->ah_radio) {
-	case AR5K_RF5110:
-		ret = ath5k_hw_rf5110_channel(ah, channel);
-		break;
-	case AR5K_RF5111:
-		ret = ath5k_hw_rf5111_channel(ah, channel);
-		break;
-	case AR5K_RF2425:
-		ret = ath5k_hw_rf2425_channel(ah, channel);
-		break;
-	default:
-		ret = ath5k_hw_rf5112_channel(ah, channel);
-		break;
-	}
-
-	if (ret)
-		return ret;
-
-	/* Set JAPAN setting for channel 14 */
-	if (channel->center_freq == 2484) {
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
-				AR5K_PHY_CCKTXCTL_JAPAN);
-	} else {
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
-				AR5K_PHY_CCKTXCTL_WORLD);
-	}
-
-	ah->ah_current_channel.center_freq = channel->center_freq;
-	ah->ah_current_channel.hw_value = channel->hw_value;
-	ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
-
-	return 0;
-}
-
-/*****************\
-  PHY calibration
-\*****************/
-
-/**
- * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
- *
- * @ah: struct ath5k_hw pointer we are operating on
- * @freq: the channel frequency, just used for error logging
- *
- * This function performs a noise floor calibration of the PHY and waits for
- * it to complete. Then the noise floor value is compared to some maximum
- * noise floor we consider valid.
- *
- * Note that this is different from what the madwifi HAL does: it reads the
- * noise floor and afterwards initiates the calibration. Since the noise floor
- * calibration can take some time to finish, depending on the current channel
- * use, that avoids the occasional timeout warnings we are seeing now.
- *
- * See the following link for an Atheros patent on noise floor calibration:
- * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
- * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
- *
- * XXX: Since during noise floor calibration antennas are detached according to
- * the patent, we should stop tx queues here.
- */
-int
-ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
-{
-	int ret;
-	unsigned int i;
-	s32 noise_floor;
-
-	/*
-	 * Enable noise floor calibration
-	 */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
-				AR5K_PHY_AGCCTL_NF);
-
-	ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-			AR5K_PHY_AGCCTL_NF, 0, false);
-	if (ret) {
-		ATH5K_ERR(ah->ah_sc,
-			"noise floor calibration timeout (%uMHz)\n", freq);
-		return -EAGAIN;
-	}
-
-	/* Wait until the noise floor is calibrated and read the value */
-	for (i = 20; i > 0; i--) {
-		mdelay(1);
-		noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
-		noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
-		if (noise_floor & AR5K_PHY_NF_ACTIVE) {
-			noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
-
-			if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
-				break;
-		}
-	}
-
-	ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
-		"noise floor %d\n", noise_floor);
-
-	if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
-		ATH5K_ERR(ah->ah_sc,
-			"noise floor calibration failed (%uMHz)\n", freq);
-		return -EAGAIN;
-	}
-
-	ah->ah_noise_floor = noise_floor;
-
-	return 0;
-}
-
-/*
- * Perform a PHY calibration on RF5110
- * -Fix BPSK/QAM Constellation (I/Q correction)
- * -Calculate Noise Floor
- */
-static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
-{
-	u32 phy_sig, phy_agc, phy_sat, beacon;
-	int ret;
-
-	/*
-	 * Disable beacons and RX/TX queues, wait
-	 */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
-		AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
-	beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
-	ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
-
-	mdelay(2);
-
-	/*
-	 * Set the channel (with AGC turned off)
-	 */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
-	udelay(10);
-	ret = ath5k_hw_channel(ah, channel);
-
-	/*
-	 * Activate PHY and wait
-	 */
-	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
-	mdelay(1);
-
-	AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
-
-	if (ret)
-		return ret;
-
-	/*
-	 * Calibrate the radio chip
-	 */
-
-	/* Remember normal state */
-	phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
-	phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
-	phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
-
-	/* Update radio registers */
-	ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
-		AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
-
-	ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
-			AR5K_PHY_AGCCOARSE_LO)) |
-		AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
-		AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
-
-	ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
-			AR5K_PHY_ADCSAT_THR)) |
-		AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
-		AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
-
-	udelay(20);
-
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
-	udelay(10);
-	ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
-	AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
-
-	mdelay(1);
-
-	/*
-	 * Enable calibration and wait until completion
-	 */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
-
-	ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-			AR5K_PHY_AGCCTL_CAL, 0, false);
-
-	/* Reset to normal state */
-	ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
-	ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
-	ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
-
-	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
-				channel->center_freq);
-		return ret;
-	}
-
-	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
-
-	/*
-	 * Re-enable RX/TX and beacons
-	 */
-	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
-		AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
-	ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
-
-	return 0;
-}
-
-/*
- * Perform a PHY calibration on RF5111/5112 and newer chips
- */
-static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
-{
-	u32 i_pwr, q_pwr;
-	s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
-	int i;
-	ATH5K_TRACE(ah->ah_sc);
-
-	if (!ah->ah_calibration ||
-		ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
-		goto done;
-
-	/* Calibration has finished, get the results and re-run */
-	for (i = 0; i <= 10; i++) {
-		iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
-		i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
-		q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
-	}
-
-	i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
-	q_coffd = q_pwr >> 7;
-
-	/* No correction */
-	if (i_coffd == 0 || q_coffd == 0)
-		goto done;
-
-	i_coff = ((-iq_corr) / i_coffd) & 0x3f;
-
-	/* Boundary check */
-	if (i_coff > 31)
-		i_coff = 31;
-	if (i_coff < -32)
-		i_coff = -32;
-
-	q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
-
-	/* Boundary check */
-	if (q_coff > 15)
-		q_coff = 15;
-	if (q_coff < -16)
-		q_coff = -16;
-
-	/* Commit new I/Q value */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
-		((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
-
-	/* Re-enable calibration -if we don't we'll commit
-	 * the same values again and again */
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
-			AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
-
-done:
-
-	/* TODO: Separate noise floor calibration from I/Q calibration
-	 * since noise floor calibration interrupts rx path while I/Q
-	 * calibration doesn't. We don't need to run noise floor calibration
-	 * as often as I/Q calibration.*/
-	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
-
-	/* Initiate a gain_F calibration */
-	ath5k_hw_request_rfgain_probe(ah);
-
-	return 0;
-}
-
-/*
- * Perform a PHY calibration
- */
-int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel)
-{
-	int ret;
-
-	if (ah->ah_radio == AR5K_RF5110)
-		ret = ath5k_hw_rf5110_calibrate(ah, channel);
-	else
-		ret = ath5k_hw_rf511x_calibrate(ah, channel);
-
-	return ret;
-}
-
-int ath5k_hw_phy_disable(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	/*Just a try M.F.*/
-	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
-
-	return 0;
-}
-
-/********************\
-  Misc PHY functions
-\********************/
-
-/*
- * Get the PHY Chip revision
- */
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
-{
-	unsigned int i;
-	u32 srev;
-	u16 ret;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/*
-	 * Set the radio chip access register
-	 */
-	switch (chan) {
-	case CHANNEL_2GHZ:
-		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
-		break;
-	case CHANNEL_5GHZ:
-		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
-		break;
-	default:
-		return 0;
-	}
-
-	mdelay(2);
-
-	/* ...wait until PHY is ready and read the selected radio revision */
-	ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
-
-	for (i = 0; i < 8; i++)
-		ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
-
-	if (ah->ah_version == AR5K_AR5210) {
-		srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
-		ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
-	} else {
-		srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
-		ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
-				((srev & 0x0f) << 4), 8);
-	}
-
-	/* Reset to the 5GHz mode */
-	ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
-
-	return ret;
-}
-
-void /*TODO:Boundary check*/
-ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	/*Just a try M.F.*/
-	if (ah->ah_version != AR5K_AR5210)
-		ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA);
-}
-
-unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	/*Just a try M.F.*/
-	if (ah->ah_version != AR5K_AR5210)
-		return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
-
-	return false; /*XXX: What do we return for 5210 ?*/
-}
-
-
-/****************\
-* TX power setup *
-\****************/
-
-/*
- * Helper functions
- */
-
-/*
- * Do linear interpolation between two given (x, y) points
- */
-static s16
-ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,
-					s16 y_left, s16 y_right)
-{
-	s16 ratio, result;
-
-	/* Avoid divide by zero and skip interpolation
-	 * if we have the same point */
-	if ((x_left == x_right) || (y_left == y_right))
-		return y_left;
-
-	/*
-	 * Since we use ints and not fps, we need to scale up in
-	 * order to get a sane ratio value (or else we 'll eg. get
-	 * always 1 instead of 1.25, 1.75 etc). We scale up by 100
-	 * to have some accuracy both for 0.5 and 0.25 steps.
-	 */
-	ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
-
-	/* Now scale down to be in range */
-	result = y_left + (ratio * (target - x_left) / 100);
-
-	return result;
-}
-
-/*
- * Find vertical boundary (min pwr) for the linear PCDAC curve.
- *
- * Since we have the top of the curve and we draw the line below
- * until we reach 1 (1 pcdac step) we need to know which point
- * (x value) that is so that we don't go below y axis and have negative
- * pcdac values when creating the curve, or fill the table with zeroes.
- */
-static s16
-ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
-				const s16 *pwrL, const s16 *pwrR)
-{
-	s8 tmp;
-	s16 min_pwrL, min_pwrR;
-	s16 pwr_i;
-
-	if (pwrL[0] == pwrL[1])
-		min_pwrL = pwrL[0];
-	else {
-		pwr_i = pwrL[0];
-		do {
-			pwr_i--;
-			tmp = (s8) ath5k_get_interpolated_value(pwr_i,
-							pwrL[0], pwrL[1],
-							stepL[0], stepL[1]);
-		} while (tmp > 1);
-
-		min_pwrL = pwr_i;
-	}
-
-	if (pwrR[0] == pwrR[1])
-		min_pwrR = pwrR[0];
-	else {
-		pwr_i = pwrR[0];
-		do {
-			pwr_i--;
-			tmp = (s8) ath5k_get_interpolated_value(pwr_i,
-							pwrR[0], pwrR[1],
-							stepR[0], stepR[1]);
-		} while (tmp > 1);
-
-		min_pwrR = pwr_i;
-	}
-
-	/* Keep the right boundary so that it works for both curves */
-	return max(min_pwrL, min_pwrR);
-}
-
-/*
- * Interpolate (pwr,vpd) points to create a Power to PDADC or a
- * Power to PCDAC curve.
- *
- * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC
- * steps (offsets) on y axis. Power can go up to 31.5dB and max
- * PCDAC/PDADC step for each curve is 64 but we can write more than
- * one curves on hw so we can go up to 128 (which is the max step we
- * can write on the final table).
- *
- * We write y values (PCDAC/PDADC steps) on hw.
- */
-static void
-ath5k_create_power_curve(s16 pmin, s16 pmax,
-			const s16 *pwr, const u8 *vpd,
-			u8 num_points,
-			u8 *vpd_table, u8 type)
-{
-	u8 idx[2] = { 0, 1 };
-	s16 pwr_i = 2*pmin;
-	int i;
-
-	if (num_points < 2)
-		return;
-
-	/* We want the whole line, so adjust boundaries
-	 * to cover the entire power range. Note that
-	 * power values are already 0.25dB so no need
-	 * to multiply pwr_i by 2 */
-	if (type == AR5K_PWRTABLE_LINEAR_PCDAC) {
-		pwr_i = pmin;
-		pmin = 0;
-		pmax = 63;
-	}
-
-	/* Find surrounding turning points (TPs)
-	 * and interpolate between them */
-	for (i = 0; (i <= (u16) (pmax - pmin)) &&
-	(i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
-
-		/* We passed the right TP, move to the next set of TPs
-		 * if we pass the last TP, extrapolate above using the last
-		 * two TPs for ratio */
-		if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) {
-			idx[0]++;
-			idx[1]++;
-		}
-
-		vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i,
-						pwr[idx[0]], pwr[idx[1]],
-						vpd[idx[0]], vpd[idx[1]]);
-
-		/* Increase by 0.5dB
-		 * (0.25 dB units) */
-		pwr_i += 2;
-	}
-}
-
-/*
- * Get the surrounding per-channel power calibration piers
- * for a given frequency so that we can interpolate between
- * them and come up with an apropriate dataset for our current
- * channel.
- */
-static void
-ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
-			struct ieee80211_channel *channel,
-			struct ath5k_chan_pcal_info **pcinfo_l,
-			struct ath5k_chan_pcal_info **pcinfo_r)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_chan_pcal_info *pcinfo;
-	u8 idx_l, idx_r;
-	u8 mode, max, i;
-	u32 target = channel->center_freq;
-
-	idx_l = 0;
-	idx_r = 0;
-
-	if (!(channel->hw_value & CHANNEL_OFDM)) {
-		pcinfo = ee->ee_pwr_cal_b;
-		mode = AR5K_EEPROM_MODE_11B;
-	} else if (channel->hw_value & CHANNEL_2GHZ) {
-		pcinfo = ee->ee_pwr_cal_g;
-		mode = AR5K_EEPROM_MODE_11G;
-	} else {
-		pcinfo = ee->ee_pwr_cal_a;
-		mode = AR5K_EEPROM_MODE_11A;
-	}
-	max = ee->ee_n_piers[mode] - 1;
-
-	/* Frequency is below our calibrated
-	 * range. Use the lowest power curve
-	 * we have */
-	if (target < pcinfo[0].freq) {
-		idx_l = idx_r = 0;
-		goto done;
-	}
-
-	/* Frequency is above our calibrated
-	 * range. Use the highest power curve
-	 * we have */
-	if (target > pcinfo[max].freq) {
-		idx_l = idx_r = max;
-		goto done;
-	}
-
-	/* Frequency is inside our calibrated
-	 * channel range. Pick the surrounding
-	 * calibration piers so that we can
-	 * interpolate */
-	for (i = 0; i <= max; i++) {
-
-		/* Frequency matches one of our calibration
-		 * piers, no need to interpolate, just use
-		 * that calibration pier */
-		if (pcinfo[i].freq == target) {
-			idx_l = idx_r = i;
-			goto done;
-		}
-
-		/* We found a calibration pier that's above
-		 * frequency, use this pier and the previous
-		 * one to interpolate */
-		if (target < pcinfo[i].freq) {
-			idx_r = i;
-			idx_l = idx_r - 1;
-			goto done;
-		}
-	}
-
-done:
-	*pcinfo_l = &pcinfo[idx_l];
-	*pcinfo_r = &pcinfo[idx_r];
-
-	return;
-}
-
-/*
- * Get the surrounding per-rate power calibration data
- * for a given frequency and interpolate between power
- * values to set max target power supported by hw for
- * each rate.
- */
-static void
-ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
-			struct ieee80211_channel *channel,
-			struct ath5k_rate_pcal_info *rates)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_rate_pcal_info *rpinfo;
-	u8 idx_l, idx_r;
-	u8 mode, max, i;
-	u32 target = channel->center_freq;
-
-	idx_l = 0;
-	idx_r = 0;
-
-	if (!(channel->hw_value & CHANNEL_OFDM)) {
-		rpinfo = ee->ee_rate_tpwr_b;
-		mode = AR5K_EEPROM_MODE_11B;
-	} else if (channel->hw_value & CHANNEL_2GHZ) {
-		rpinfo = ee->ee_rate_tpwr_g;
-		mode = AR5K_EEPROM_MODE_11G;
-	} else {
-		rpinfo = ee->ee_rate_tpwr_a;
-		mode = AR5K_EEPROM_MODE_11A;
-	}
-	max = ee->ee_rate_target_pwr_num[mode] - 1;
-
-	/* Get the surrounding calibration
-	 * piers - same as above */
-	if (target < rpinfo[0].freq) {
-		idx_l = idx_r = 0;
-		goto done;
-	}
-
-	if (target > rpinfo[max].freq) {
-		idx_l = idx_r = max;
-		goto done;
-	}
-
-	for (i = 0; i <= max; i++) {
-
-		if (rpinfo[i].freq == target) {
-			idx_l = idx_r = i;
-			goto done;
-		}
-
-		if (target < rpinfo[i].freq) {
-			idx_r = i;
-			idx_l = idx_r - 1;
-			goto done;
-		}
-	}
-
-done:
-	/* Now interpolate power value, based on the frequency */
-	rates->freq = target;
-
-	rates->target_power_6to24 =
-		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
-					rpinfo[idx_r].freq,
-					rpinfo[idx_l].target_power_6to24,
-					rpinfo[idx_r].target_power_6to24);
-
-	rates->target_power_36 =
-		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
-					rpinfo[idx_r].freq,
-					rpinfo[idx_l].target_power_36,
-					rpinfo[idx_r].target_power_36);
-
-	rates->target_power_48 =
-		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
-					rpinfo[idx_r].freq,
-					rpinfo[idx_l].target_power_48,
-					rpinfo[idx_r].target_power_48);
-
-	rates->target_power_54 =
-		ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
-					rpinfo[idx_r].freq,
-					rpinfo[idx_l].target_power_54,
-					rpinfo[idx_r].target_power_54);
-}
-
-/*
- * Get the max edge power for this channel if
- * we have such data from EEPROM's Conformance Test
- * Limits (CTL), and limit max power if needed.
- *
- * FIXME: Only works for world regulatory domains
- */
-static void
-ath5k_get_max_ctl_power(struct ath5k_hw *ah,
-			struct ieee80211_channel *channel)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
-	u8 *ctl_val = ee->ee_ctl;
-	s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4;
-	s16 edge_pwr = 0;
-	u8 rep_idx;
-	u8 i, ctl_mode;
-	u8 ctl_idx = 0xFF;
-	u32 target = channel->center_freq;
-
-	/* Find out a CTL for our mode that's not mapped
-	 * on a specific reg domain.
-	 *
-	 * TODO: Map our current reg domain to one of the 3 available
-	 * reg domain ids so that we can support more CTLs. */
-	switch (channel->hw_value & CHANNEL_MODES) {
-	case CHANNEL_A:
-		ctl_mode = AR5K_CTL_11A | AR5K_CTL_NO_REGDOMAIN;
-		break;
-	case CHANNEL_G:
-		ctl_mode = AR5K_CTL_11G | AR5K_CTL_NO_REGDOMAIN;
-		break;
-	case CHANNEL_B:
-		ctl_mode = AR5K_CTL_11B | AR5K_CTL_NO_REGDOMAIN;
-		break;
-	case CHANNEL_T:
-		ctl_mode = AR5K_CTL_TURBO | AR5K_CTL_NO_REGDOMAIN;
-		break;
-	case CHANNEL_TG:
-		ctl_mode = AR5K_CTL_TURBOG | AR5K_CTL_NO_REGDOMAIN;
-		break;
-	case CHANNEL_XR:
-		/* Fall through */
-	default:
-		return;
-	}
-
-	for (i = 0; i < ee->ee_ctls; i++) {
-		if (ctl_val[i] == ctl_mode) {
-			ctl_idx = i;
-			break;
-		}
-	}
-
-	/* If we have a CTL dataset available grab it and find the
-	 * edge power for our frequency */
-	if (ctl_idx == 0xFF)
-		return;
-
-	/* Edge powers are sorted by frequency from lower
-	 * to higher. Each CTL corresponds to 8 edge power
-	 * measurements. */
-	rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES;
-
-	/* Don't do boundaries check because we
-	 * might have more that one bands defined
-	 * for this mode */
-
-	/* Get the edge power that's closer to our
-	 * frequency */
-	for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) {
-		rep_idx += i;
-		if (target <= rep[rep_idx].freq)
-			edge_pwr = (s16) rep[rep_idx].edge;
-	}
-
-	if (edge_pwr)
-		ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
-}
-
-
-/*
- * Power to PCDAC table functions
- */
-
-/*
- * Fill Power to PCDAC table on RF5111
- *
- * No further processing is needed for RF5111, the only thing we have to
- * do is fill the values below and above calibration range since eeprom data
- * may not cover the entire PCDAC table.
- */
-static void
-ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,
-							s16 *table_max)
-{
-	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
-	u8	*pcdac_tmp = ah->ah_txpower.tmpL[0];
-	u8	pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
-	s16	min_pwr, max_pwr;
-
-	/* Get table boundaries */
-	min_pwr = table_min[0];
-	pcdac_0 = pcdac_tmp[0];
-
-	max_pwr = table_max[0];
-	pcdac_n = pcdac_tmp[table_max[0] - table_min[0]];
-
-	/* Extrapolate below minimum using pcdac_0 */
-	pcdac_i = 0;
-	for (i = 0; i < min_pwr; i++)
-		pcdac_out[pcdac_i++] = pcdac_0;
-
-	/* Copy values from pcdac_tmp */
-	pwr_idx = min_pwr;
-	for (i = 0 ; pwr_idx <= max_pwr &&
-	pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
-		pcdac_out[pcdac_i++] = pcdac_tmp[i];
-		pwr_idx++;
-	}
-
-	/* Extrapolate above maximum */
-	while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE)
-		pcdac_out[pcdac_i++] = pcdac_n;
-
-}
-
-/*
- * Combine available XPD Curves and fill Linear Power to PCDAC table
- * on RF5112
- *
- * RFX112 can have up to 2 curves (one for low txpower range and one for
- * higher txpower range). We need to put them both on pcdac_out and place
- * them in the correct location. In case we only have one curve available
- * just fit it on pcdac_out (it's supposed to cover the entire range of
- * available pwr levels since it's always the higher power curve). Extrapolate
- * below and above final table if needed.
- */
-static void
-ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,
-						s16 *table_max, u8 pdcurves)
-{
-	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
-	u8	*pcdac_low_pwr;
-	u8	*pcdac_high_pwr;
-	u8	*pcdac_tmp;
-	u8	pwr;
-	s16	max_pwr_idx;
-	s16	min_pwr_idx;
-	s16	mid_pwr_idx = 0;
-	/* Edge flag turs on the 7nth bit on the PCDAC
-	 * to delcare the higher power curve (force values
-	 * to be greater than 64). If we only have one curve
-	 * we don't need to set this, if we have 2 curves and
-	 * fill the table backwards this can also be used to
-	 * switch from higher power curve to lower power curve */
-	u8	edge_flag;
-	int	i;
-
-	/* When we have only one curve available
-	 * that's the higher power curve. If we have
-	 * two curves the first is the high power curve
-	 * and the next is the low power curve. */
-	if (pdcurves > 1) {
-		pcdac_low_pwr = ah->ah_txpower.tmpL[1];
-		pcdac_high_pwr = ah->ah_txpower.tmpL[0];
-		mid_pwr_idx = table_max[1] - table_min[1] - 1;
-		max_pwr_idx = (table_max[0] - table_min[0]) / 2;
-
-		/* If table size goes beyond 31.5dB, keep the
-		 * upper 31.5dB range when setting tx power.
-		 * Note: 126 = 31.5 dB in quarter dB steps */
-		if (table_max[0] - table_min[1] > 126)
-			min_pwr_idx = table_max[0] - 126;
-		else
-			min_pwr_idx = table_min[1];
-
-		/* Since we fill table backwards
-		 * start from high power curve */
-		pcdac_tmp = pcdac_high_pwr;
-
-		edge_flag = 0x40;
-#if 0
-		/* If both min and max power limits are in lower
-		 * power curve's range, only use the low power curve.
-		 * TODO: min/max levels are related to target
-		 * power values requested from driver/user
-		 * XXX: Is this really needed ? */
-		if (min_pwr < table_max[1] &&
-		max_pwr < table_max[1]) {
-			edge_flag = 0;
-			pcdac_tmp = pcdac_low_pwr;
-			max_pwr_idx = (table_max[1] - table_min[1])/2;
-		}
-#endif
-	} else {
-		pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */
-		pcdac_high_pwr = ah->ah_txpower.tmpL[0];
-		min_pwr_idx = table_min[0];
-		max_pwr_idx = (table_max[0] - table_min[0]) / 2;
-		pcdac_tmp = pcdac_high_pwr;
-		edge_flag = 0;
-	}
-
-	/* This is used when setting tx power*/
-	ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
-
-	/* Fill Power to PCDAC table backwards */
-	pwr = max_pwr_idx;
-	for (i = 63; i >= 0; i--) {
-		/* Entering lower power range, reset
-		 * edge flag and set pcdac_tmp to lower
-		 * power curve.*/
-		if (edge_flag == 0x40 &&
-		(2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
-			edge_flag = 0x00;
-			pcdac_tmp = pcdac_low_pwr;
-			pwr = mid_pwr_idx/2;
-		}
-
-		/* Don't go below 1, extrapolate below if we have
-		 * already swithced to the lower power curve -or
-		 * we only have one curve and edge_flag is zero
-		 * anyway */
-		if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
-			while (i >= 0) {
-				pcdac_out[i] = pcdac_out[i + 1];
-				i--;
-			}
-			break;
-		}
-
-		pcdac_out[i] = pcdac_tmp[pwr] | edge_flag;
-
-		/* Extrapolate above if pcdac is greater than
-		 * 126 -this can happen because we OR pcdac_out
-		 * value with edge_flag on high power curve */
-		if (pcdac_out[i] > 126)
-			pcdac_out[i] = 126;
-
-		/* Decrease by a 0.5dB step */
-		pwr--;
-	}
-}
-
-/* Write PCDAC values on hw */
-static void
-ath5k_setup_pcdac_table(struct ath5k_hw *ah)
-{
-	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table;
-	int	i;
-
-	/*
-	 * Write TX power values
-	 */
-	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
-		ath5k_hw_reg_write(ah,
-			(((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
-			(((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
-			AR5K_PHY_PCDAC_TXPOWER(i));
-	}
-}
-
-
-/*
- * Power to PDADC table functions
- */
-
-/*
- * Set the gain boundaries and create final Power to PDADC table
- *
- * We can have up to 4 pd curves, we need to do a simmilar process
- * as we do for RF5112. This time we don't have an edge_flag but we
- * set the gain boundaries on a separate register.
- */
-static void
-ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah,
-			s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
-{
-	u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS];
-	u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
-	u8 *pdadc_tmp;
-	s16 pdadc_0;
-	u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size;
-	u8 pd_gain_overlap;
-
-	/* Note: Register value is initialized on initvals
-	 * there is no feedback from hw.
-	 * XXX: What about pd_gain_overlap from EEPROM ? */
-	pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) &
-		AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP;
-
-	/* Create final PDADC table */
-	for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) {
-		pdadc_tmp = ah->ah_txpower.tmpL[pdg];
-
-		if (pdg == pdcurves - 1)
-			/* 2 dB boundary stretch for last
-			 * (higher power) curve */
-			gain_boundaries[pdg] = pwr_max[pdg] + 4;
-		else
-			/* Set gain boundary in the middle
-			 * between this curve and the next one */
-			gain_boundaries[pdg] =
-				(pwr_max[pdg] + pwr_min[pdg + 1]) / 2;
-
-		/* Sanity check in case our 2 db stretch got out of
-		 * range. */
-		if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER)
-			gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER;
-
-		/* For the first curve (lower power)
-		 * start from 0 dB */
-		if (pdg == 0)
-			pdadc_0 = 0;
-		else
-			/* For the other curves use the gain overlap */
-			pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) -
-							pd_gain_overlap;
-
-		/* Force each power step to be at least 0.5 dB */
-		if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1)
-			pwr_step = pdadc_tmp[1] - pdadc_tmp[0];
-		else
-			pwr_step = 1;
-
-		/* If pdadc_0 is negative, we need to extrapolate
-		 * below this pdgain by a number of pwr_steps */
-		while ((pdadc_0 < 0) && (pdadc_i < 128)) {
-			s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step;
-			pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp;
-			pdadc_0++;
-		}
-
-		/* Set last pwr level, using gain boundaries */
-		pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg];
-		/* Limit it to be inside pwr range */
-		table_size = pwr_max[pdg] - pwr_min[pdg];
-		max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
-
-		/* Fill pdadc_out table */
-		while (pdadc_0 < max_idx)
-			pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
-
-		/* Need to extrapolate above this pdgain? */
-		if (pdadc_n <= max_idx)
-			continue;
-
-		/* Force each power step to be at least 0.5 dB */
-		if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1)
-			pwr_step = pdadc_tmp[table_size - 1] -
-						pdadc_tmp[table_size - 2];
-		else
-			pwr_step = 1;
-
-		/* Extrapolate above */
-		while ((pdadc_0 < (s16) pdadc_n) &&
-		(pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) {
-			s16 tmp = pdadc_tmp[table_size - 1] +
-					(pdadc_0 - max_idx) * pwr_step;
-			pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp;
-			pdadc_0++;
-		}
-	}
-
-	while (pdg < AR5K_EEPROM_N_PD_GAINS) {
-		gain_boundaries[pdg] = gain_boundaries[pdg - 1];
-		pdg++;
-	}
-
-	while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) {
-		pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1];
-		pdadc_i++;
-	}
-
-	/* Set gain boundaries */
-	ath5k_hw_reg_write(ah,
-		AR5K_REG_SM(pd_gain_overlap,
-			AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) |
-		AR5K_REG_SM(gain_boundaries[0],
-			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) |
-		AR5K_REG_SM(gain_boundaries[1],
-			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) |
-		AR5K_REG_SM(gain_boundaries[2],
-			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) |
-		AR5K_REG_SM(gain_boundaries[3],
-			AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4),
-		AR5K_PHY_TPC_RG5);
-
-	/* Used for setting rate power table */
-	ah->ah_txpower.txp_min_idx = pwr_min[0];
-
-}
-
-/* Write PDADC values on hw */
-static void
-ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah,
-			u8 pdcurves, u8 *pdg_to_idx)
-{
-	u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
-	u32 reg;
-	u8 i;
-
-	/* Select the right pdgain curves */
-
-	/* Clear current settings */
-	reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1);
-	reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 |
-		AR5K_PHY_TPC_RG1_PDGAIN_2 |
-		AR5K_PHY_TPC_RG1_PDGAIN_3 |
-		AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
-
-	/*
-	 * Use pd_gains curve from eeprom
-	 *
-	 * This overrides the default setting from initvals
-	 * in case some vendors (e.g. Zcomax) don't use the default
-	 * curves. If we don't honor their settings we 'll get a
-	 * 5dB (1 * gain overlap ?) drop.
-	 */
-	reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN);
-
-	switch (pdcurves) {
-	case 3:
-		reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
-		/* Fall through */
-	case 2:
-		reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
-		/* Fall through */
-	case 1:
-		reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
-		break;
-	}
-	ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1);
-
-	/*
-	 * Write TX power values
-	 */
-	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
-		ath5k_hw_reg_write(ah,
-			((pdadc_out[4*i + 0] & 0xff) << 0) |
-			((pdadc_out[4*i + 1] & 0xff) << 8) |
-			((pdadc_out[4*i + 2] & 0xff) << 16) |
-			((pdadc_out[4*i + 3] & 0xff) << 24),
-			AR5K_PHY_PDADC_TXPOWER(i));
-	}
-}
-
-
-/*
- * Common code for PCDAC/PDADC tables
- */
-
-/*
- * This is the main function that uses all of the above
- * to set PCDAC/PDADC table on hw for the current channel.
- * This table is used for tx power calibration on the basband,
- * without it we get weird tx power levels and in some cases
- * distorted spectral mask
- */
-static int
-ath5k_setup_channel_powertable(struct ath5k_hw *ah,
-			struct ieee80211_channel *channel,
-			u8 ee_mode, u8 type)
-{
-	struct ath5k_pdgain_info *pdg_L, *pdg_R;
-	struct ath5k_chan_pcal_info *pcinfo_L;
-	struct ath5k_chan_pcal_info *pcinfo_R;
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
-	s16 table_min[AR5K_EEPROM_N_PD_GAINS];
-	s16 table_max[AR5K_EEPROM_N_PD_GAINS];
-	u8 *tmpL;
-	u8 *tmpR;
-	u32 target = channel->center_freq;
-	int pdg, i;
-
-	/* Get surounding freq piers for this channel */
-	ath5k_get_chan_pcal_surrounding_piers(ah, channel,
-						&pcinfo_L,
-						&pcinfo_R);
-
-	/* Loop over pd gain curves on
-	 * surounding freq piers by index */
-	for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
-
-		/* Fill curves in reverse order
-		 * from lower power (max gain)
-		 * to higher power. Use curve -> idx
-		 * backmaping we did on eeprom init */
-		u8 idx = pdg_curve_to_idx[pdg];
-
-		/* Grab the needed curves by index */
-		pdg_L = &pcinfo_L->pd_curves[idx];
-		pdg_R = &pcinfo_R->pd_curves[idx];
-
-		/* Initialize the temp tables */
-		tmpL = ah->ah_txpower.tmpL[pdg];
-		tmpR = ah->ah_txpower.tmpR[pdg];
-
-		/* Set curve's x boundaries and create
-		 * curves so that they cover the same
-		 * range (if we don't do that one table
-		 * will have values on some range and the
-		 * other one won't have any so interpolation
-		 * will fail) */
-		table_min[pdg] = min(pdg_L->pd_pwr[0],
-					pdg_R->pd_pwr[0]) / 2;
-
-		table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
-				pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2;
-
-		/* Now create the curves on surrounding channels
-		 * and interpolate if needed to get the final
-		 * curve for this gain on this channel */
-		switch (type) {
-		case AR5K_PWRTABLE_LINEAR_PCDAC:
-			/* Override min/max so that we don't loose
-			 * accuracy (don't divide by 2) */
-			table_min[pdg] = min(pdg_L->pd_pwr[0],
-						pdg_R->pd_pwr[0]);
-
-			table_max[pdg] =
-				max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
-					pdg_R->pd_pwr[pdg_R->pd_points - 1]);
-
-			/* Override minimum so that we don't get
-			 * out of bounds while extrapolating
-			 * below. Don't do this when we have 2
-			 * curves and we are on the high power curve
-			 * because table_min is ok in this case */
-			if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) {
-
-				table_min[pdg] =
-					ath5k_get_linear_pcdac_min(pdg_L->pd_step,
-								pdg_R->pd_step,
-								pdg_L->pd_pwr,
-								pdg_R->pd_pwr);
-
-				/* Don't go too low because we will
-				 * miss the upper part of the curve.
-				 * Note: 126 = 31.5dB (max power supported)
-				 * in 0.25dB units */
-				if (table_max[pdg] - table_min[pdg] > 126)
-					table_min[pdg] = table_max[pdg] - 126;
-			}
-
-			/* Fall through */
-		case AR5K_PWRTABLE_PWR_TO_PCDAC:
-		case AR5K_PWRTABLE_PWR_TO_PDADC:
-
-			ath5k_create_power_curve(table_min[pdg],
-						table_max[pdg],
-						pdg_L->pd_pwr,
-						pdg_L->pd_step,
-						pdg_L->pd_points, tmpL, type);
-
-			/* We are in a calibration
-			 * pier, no need to interpolate
-			 * between freq piers */
-			if (pcinfo_L == pcinfo_R)
-				continue;
-
-			ath5k_create_power_curve(table_min[pdg],
-						table_max[pdg],
-						pdg_R->pd_pwr,
-						pdg_R->pd_step,
-						pdg_R->pd_points, tmpR, type);
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		/* Interpolate between curves
-		 * of surounding freq piers to
-		 * get the final curve for this
-		 * pd gain. Re-use tmpL for interpolation
-		 * output */
-		for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) &&
-		(i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
-			tmpL[i] = (u8) ath5k_get_interpolated_value(target,
-							(s16) pcinfo_L->freq,
-							(s16) pcinfo_R->freq,
-							(s16) tmpL[i],
-							(s16) tmpR[i]);
-		}
-	}
-
-	/* Now we have a set of curves for this
-	 * channel on tmpL (x range is table_max - table_min
-	 * and y values are tmpL[pdg][]) sorted in the same
-	 * order as EEPROM (because we've used the backmaping).
-	 * So for RF5112 it's from higher power to lower power
-	 * and for RF2413 it's from lower power to higher power.
-	 * For RF5111 we only have one curve. */
-
-	/* Fill min and max power levels for this
-	 * channel by interpolating the values on
-	 * surounding channels to complete the dataset */
-	ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
-					(s16) pcinfo_L->freq,
-					(s16) pcinfo_R->freq,
-					pcinfo_L->min_pwr, pcinfo_R->min_pwr);
-
-	ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target,
-					(s16) pcinfo_L->freq,
-					(s16) pcinfo_R->freq,
-					pcinfo_L->max_pwr, pcinfo_R->max_pwr);
-
-	/* We are ready to go, fill PCDAC/PDADC
-	 * table and write settings on hardware */
-	switch (type) {
-	case AR5K_PWRTABLE_LINEAR_PCDAC:
-		/* For RF5112 we can have one or two curves
-		 * and each curve covers a certain power lvl
-		 * range so we need to do some more processing */
-		ath5k_combine_linear_pcdac_curves(ah, table_min, table_max,
-						ee->ee_pd_gains[ee_mode]);
-
-		/* Set txp.offset so that we can
-		 * match max power value with max
-		 * table index */
-		ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
-
-		/* Write settings on hw */
-		ath5k_setup_pcdac_table(ah);
-		break;
-	case AR5K_PWRTABLE_PWR_TO_PCDAC:
-		/* We are done for RF5111 since it has only
-		 * one curve, just fit the curve on the table */
-		ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max);
-
-		/* No rate powertable adjustment for RF5111 */
-		ah->ah_txpower.txp_min_idx = 0;
-		ah->ah_txpower.txp_offset = 0;
-
-		/* Write settings on hw */
-		ath5k_setup_pcdac_table(ah);
-		break;
-	case AR5K_PWRTABLE_PWR_TO_PDADC:
-		/* Set PDADC boundaries and fill
-		 * final PDADC table */
-		ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
-						ee->ee_pd_gains[ee_mode]);
-
-		/* Write settings on hw */
-		ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
-
-		/* Set txp.offset, note that table_min
-		 * can be negative */
-		ah->ah_txpower.txp_offset = table_min[0];
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
-/*
- * Per-rate tx power setting
- *
- * This is the code that sets the desired tx power (below
- * maximum) on hw for each rate (we also have TPC that sets
- * power per packet). We do that by providing an index on the
- * PCDAC/PDADC table we set up.
- */
-
-/*
- * Set rate power table
- *
- * For now we only limit txpower based on maximum tx power
- * supported by hw (what's inside rate_info). We need to limit
- * this even more, based on regulatory domain etc.
- *
- * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps)
- * and is indexed as follows:
- * rates[0] - rates[7] -> OFDM rates
- * rates[8] - rates[14] -> CCK rates
- * rates[15] -> XR rates (they all have the same power)
- */
-static void
-ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
-			struct ath5k_rate_pcal_info *rate_info,
-			u8 ee_mode)
-{
-	unsigned int i;
-	u16 *rates;
-
-	/* max_pwr is power level we got from driver/user in 0.5dB
-	 * units, switch to 0.25dB units so we can compare */
-	max_pwr *= 2;
-	max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2;
-
-	/* apply rate limits */
-	rates = ah->ah_txpower.txp_rates_power_table;
-
-	/* OFDM rates 6 to 24Mb/s */
-	for (i = 0; i < 5; i++)
-		rates[i] = min(max_pwr, rate_info->target_power_6to24);
-
-	/* Rest OFDM rates */
-	rates[5] = min(rates[0], rate_info->target_power_36);
-	rates[6] = min(rates[0], rate_info->target_power_48);
-	rates[7] = min(rates[0], rate_info->target_power_54);
-
-	/* CCK rates */
-	/* 1L */
-	rates[8] = min(rates[0], rate_info->target_power_6to24);
-	/* 2L */
-	rates[9] = min(rates[0], rate_info->target_power_36);
-	/* 2S */
-	rates[10] = min(rates[0], rate_info->target_power_36);
-	/* 5L */
-	rates[11] = min(rates[0], rate_info->target_power_48);
-	/* 5S */
-	rates[12] = min(rates[0], rate_info->target_power_48);
-	/* 11L */
-	rates[13] = min(rates[0], rate_info->target_power_54);
-	/* 11S */
-	rates[14] = min(rates[0], rate_info->target_power_54);
-
-	/* XR rates */
-	rates[15] = min(rates[0], rate_info->target_power_6to24);
-
-	/* CCK rates have different peak to average ratio
-	 * so we have to tweak their power so that gainf
-	 * correction works ok. For this we use OFDM to
-	 * CCK delta from eeprom */
-	if ((ee_mode == AR5K_EEPROM_MODE_11G) &&
-	(ah->ah_phy_revision < AR5K_SREV_PHY_5212A))
-		for (i = 8; i <= 15; i++)
-			rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
-
-	ah->ah_txpower.txp_min_pwr = rates[7];
-	ah->ah_txpower.txp_max_pwr = rates[0];
-	ah->ah_txpower.txp_ofdm = rates[7];
-}
-
-
-/*
- * Set transmition power
- */
-int
-ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
-		u8 ee_mode, u8 txpower)
-{
-	struct ath5k_rate_pcal_info rate_info;
-	u8 type;
-	int ret;
-
-	ATH5K_TRACE(ah->ah_sc);
-	if (txpower > AR5K_TUNE_MAX_TXPOWER) {
-		ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
-		return -EINVAL;
-	}
-	if (txpower == 0)
-		txpower = AR5K_TUNE_DEFAULT_TXPOWER;
-
-	/* Reset TX power values */
-	memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
-	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
-	ah->ah_txpower.txp_min_pwr = 0;
-	ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
-
-	/* Initialize TX power table */
-	switch (ah->ah_radio) {
-	case AR5K_RF5111:
-		type = AR5K_PWRTABLE_PWR_TO_PCDAC;
-		break;
-	case AR5K_RF5112:
-		type = AR5K_PWRTABLE_LINEAR_PCDAC;
-		break;
-	case AR5K_RF2413:
-	case AR5K_RF5413:
-	case AR5K_RF2316:
-	case AR5K_RF2317:
-	case AR5K_RF2425:
-		type = AR5K_PWRTABLE_PWR_TO_PDADC;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* FIXME: Only on channel/mode change */
-	ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
-	if (ret)
-		return ret;
-
-	/* Limit max power if we have a CTL available */
-	ath5k_get_max_ctl_power(ah, channel);
-
-	/* FIXME: Tx power limit for this regdomain
-	 * XXX: Mac80211/CRDA will do that anyway ? */
-
-	/* FIXME: Antenna reduction stuff */
-
-	/* FIXME: Limit power on turbo modes */
-
-	/* FIXME: TPC scale reduction */
-
-	/* Get surounding channels for per-rate power table
-	 * calibration */
-	ath5k_get_rate_pcal_data(ah, channel, &rate_info);
-
-	/* Setup rate power table */
-	ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode);
-
-	/* Write rate power table on hw */
-	ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
-		AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
-		AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
-
-	ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
-		AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
-		AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
-
-	ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
-		AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
-		AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
-
-	ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
-		AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
-		AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
-
-	/* FIXME: TPC support */
-	if (ah->ah_txpower.txp_tpc) {
-		ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
-			AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
-
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) |
-			AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) |
-			AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
-			AR5K_TPC);
-	} else {
-		ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
-			AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
-	}
-
-	return 0;
-}
-
-int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower)
-{
-	/*Just a try M.F.*/
-	struct ieee80211_channel *channel = &ah->ah_current_channel;
-
-	ATH5K_TRACE(ah->ah_sc);
-	ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
-		"changing txpower to %d\n", txpower);
-
-	return ath5k_hw_txpower(ah, channel, mode, txpower);
-}
-
-#undef _ATH5K_PHY
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/qcu.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/qcu.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/qcu.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/qcu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,546 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/********************************************\
-Queue Control Unit, DFS Control Unit Functions
-\********************************************/
-
-#include "ath5k.h"
-#include "reg.h"
-#include "debug.h"
-#include "base.h"
-
-/*
- * Get properties for a transmit queue
- */
-int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
-		struct ath5k_txq_info *queue_info)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
-	return 0;
-}
-
-/*
- * Set properties for a transmit queue
- */
-int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
-				const struct ath5k_txq_info *queue_info)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return -EIO;
-
-	memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
-
-	/*XXX: Is this supported on 5210 ?*/
-	if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
-			((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
-			(queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
-			queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
-		ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
-
-	return 0;
-}
-
-/*
- * Initialize a transmit queue
- */
-int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
-		struct ath5k_txq_info *queue_info)
-{
-	unsigned int queue;
-	int ret;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/*
-	 * Get queue by type
-	 */
-	/*5210 only has 2 queues*/
-	if (ah->ah_version == AR5K_AR5210) {
-		switch (queue_type) {
-		case AR5K_TX_QUEUE_DATA:
-			queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
-			break;
-		case AR5K_TX_QUEUE_BEACON:
-		case AR5K_TX_QUEUE_CAB:
-			queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
-		switch (queue_type) {
-		case AR5K_TX_QUEUE_DATA:
-			for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
-				ah->ah_txq[queue].tqi_type !=
-				AR5K_TX_QUEUE_INACTIVE; queue++) {
-
-				if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
-					return -EINVAL;
-			}
-			break;
-		case AR5K_TX_QUEUE_UAPSD:
-			queue = AR5K_TX_QUEUE_ID_UAPSD;
-			break;
-		case AR5K_TX_QUEUE_BEACON:
-			queue = AR5K_TX_QUEUE_ID_BEACON;
-			break;
-		case AR5K_TX_QUEUE_CAB:
-			queue = AR5K_TX_QUEUE_ID_CAB;
-			break;
-		case AR5K_TX_QUEUE_XR_DATA:
-			if (ah->ah_version != AR5K_AR5212)
-				ATH5K_ERR(ah->ah_sc,
-					"XR data queues only supported in"
-					" 5212!\n");
-			queue = AR5K_TX_QUEUE_ID_XR_DATA;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-
-	/*
-	 * Setup internal queue structure
-	 */
-	memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
-	ah->ah_txq[queue].tqi_type = queue_type;
-
-	if (queue_info != NULL) {
-		queue_info->tqi_type = queue_type;
-		ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
-		if (ret)
-			return ret;
-	}
-
-	/*
-	 * We use ah_txq_status to hold a temp value for
-	 * the Secondary interrupt mask registers on 5211+
-	 * check out ath5k_hw_reset_tx_queue
-	 */
-	AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
-
-	return queue;
-}
-
-/*
- * Get number of pending frames
- * for a specific queue [5211+]
- */
-u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
-{
-	u32 pending;
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	/* Return if queue is declared inactive */
-	if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return false;
-
-	/* XXX: How about AR5K_CFG_TXCNT ? */
-	if (ah->ah_version == AR5K_AR5210)
-		return false;
-
-	pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT);
-
-	/* It's possible to have no frames pending even if TXE
-	 * is set. To indicate that q has not stopped return
-	 * true */
-	if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
-		return true;
-
-	return pending;
-}
-
-/*
- * Set a transmit queue inactive
- */
-void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
-		return;
-
-	/* This queue will be skipped in further operations */
-	ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
-	/*For SIMR setup*/
-	AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
-}
-
-/*
- * Set DFS properties for a transmit queue on DCU
- */
-int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
-{
-	u32 cw_min, cw_max, retry_lg, retry_sh;
-	struct ath5k_txq_info *tq = &ah->ah_txq[queue];
-
-	ATH5K_TRACE(ah->ah_sc);
-	AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
-	tq = &ah->ah_txq[queue];
-
-	if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
-		return 0;
-
-	if (ah->ah_version == AR5K_AR5210) {
-		/* Only handle data queues, others will be ignored */
-		if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
-			return 0;
-
-		/* Set Slot time */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
-			AR5K_SLOT_TIME);
-		/* Set ACK_CTS timeout */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
-			AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
-		/* Set Transmit Latency */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_TRANSMIT_LATENCY_TURBO :
-			AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
-
-		/* Set IFS0 */
-		if (ah->ah_turbo) {
-			 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
-				(ah->ah_aifs + tq->tqi_aifs) *
-				AR5K_INIT_SLOT_TIME_TURBO) <<
-				AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
-				AR5K_IFS0);
-		} else {
-			ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
-				(ah->ah_aifs + tq->tqi_aifs) *
-				AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
-				AR5K_INIT_SIFS, AR5K_IFS0);
-		}
-
-		/* Set IFS1 */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
-			AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
-		/* Set AR5K_PHY_SETTLING */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
-			| 0x38 :
-			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
-			| 0x1C,
-			AR5K_PHY_SETTLING);
-		/* Set Frame Control Register */
-		ath5k_hw_reg_write(ah, ah->ah_turbo ?
-			(AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
-			AR5K_PHY_TURBO_SHORT | 0x2020) :
-			(AR5K_PHY_FRAME_CTL_INI | 0x1020),
-			AR5K_PHY_FRAME_CTL_5210);
-	}
-
-	/*
-	 * Calculate cwmin/max by channel mode
-	 */
-	cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
-	cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
-	ah->ah_aifs = AR5K_TUNE_AIFS;
-	/*XR is only supported on 5212*/
-	if (IS_CHAN_XR(ah->ah_current_channel) &&
-			ah->ah_version == AR5K_AR5212) {
-		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
-		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
-		ah->ah_aifs = AR5K_TUNE_AIFS_XR;
-	/*B mode is not supported on 5210*/
-	} else if (IS_CHAN_B(ah->ah_current_channel) &&
-			ah->ah_version != AR5K_AR5210) {
-		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
-		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
-		ah->ah_aifs = AR5K_TUNE_AIFS_11B;
-	}
-
-	cw_min = 1;
-	while (cw_min < ah->ah_cw_min)
-		cw_min = (cw_min << 1) | 1;
-
-	cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
-		((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
-	cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
-		((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
-
-	/*
-	 * Calculate and set retry limits
-	 */
-	if (ah->ah_software_retry) {
-		/* XXX Need to test this */
-		retry_lg = ah->ah_limit_tx_retries;
-		retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
-			AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
-	} else {
-		retry_lg = AR5K_INIT_LG_RETRY;
-		retry_sh = AR5K_INIT_SH_RETRY;
-	}
-
-	/*No QCU/DCU [5210]*/
-	if (ah->ah_version == AR5K_AR5210) {
-		ath5k_hw_reg_write(ah,
-			(cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
-			| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
-				AR5K_NODCU_RETRY_LMT_SLG_RETRY)
-			| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
-				AR5K_NODCU_RETRY_LMT_SSH_RETRY)
-			| AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
-			| AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
-			AR5K_NODCU_RETRY_LMT);
-	} else {
-		/*QCU/DCU [5211+]*/
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
-				AR5K_DCU_RETRY_LMT_SLG_RETRY) |
-			AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
-				AR5K_DCU_RETRY_LMT_SSH_RETRY) |
-			AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
-			AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
-			AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
-
-	/*===Rest is also for QCU/DCU only [5211+]===*/
-
-		/*
-		 * Set initial content window (cw_min/cw_max)
-		 * and arbitrated interframe space (aifs)...
-		 */
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
-			AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
-			AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
-				AR5K_DCU_LCL_IFS_AIFS),
-			AR5K_QUEUE_DFS_LOCAL_IFS(queue));
-
-		/*
-		 * Set misc registers
-		 */
-		/* Enable DCU early termination for this queue */
-		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-					AR5K_QCU_MISC_DCU_EARLY);
-
-		/* Enable DCU to wait for next fragment from QCU */
-		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
-					AR5K_DCU_MISC_FRAG_WAIT);
-
-		/* On Maui and Spirit use the global seqnum on DCU */
-		if (ah->ah_mac_version < AR5K_SREV_AR5211)
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
-						AR5K_DCU_MISC_SEQNUM_CTL);
-
-		if (tq->tqi_cbr_period) {
-			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
-				AR5K_QCU_CBRCFG_INTVAL) |
-				AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
-				AR5K_QCU_CBRCFG_ORN_THRES),
-				AR5K_QUEUE_CBRCFG(queue));
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_FRSHED_CBR);
-			if (tq->tqi_cbr_overflow_limit)
-				AR5K_REG_ENABLE_BITS(ah,
-					AR5K_QUEUE_MISC(queue),
-					AR5K_QCU_MISC_CBR_THRES_ENABLE);
-		}
-
-		if (tq->tqi_ready_time &&
-		(tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
-			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
-				AR5K_QCU_RDYTIMECFG_INTVAL) |
-				AR5K_QCU_RDYTIMECFG_ENABLE,
-				AR5K_QUEUE_RDYTIMECFG(queue));
-
-		if (tq->tqi_burst_time) {
-			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
-				AR5K_DCU_CHAN_TIME_DUR) |
-				AR5K_DCU_CHAN_TIME_ENABLE,
-				AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
-
-			if (tq->tqi_flags
-			& AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
-				AR5K_REG_ENABLE_BITS(ah,
-					AR5K_QUEUE_MISC(queue),
-					AR5K_QCU_MISC_RDY_VEOL_POLICY);
-		}
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
-			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
-				AR5K_QUEUE_DFS_MISC(queue));
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
-			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
-				AR5K_QUEUE_DFS_MISC(queue));
-
-		/*
-		 * Set registers by queue type
-		 */
-		switch (tq->tqi_type) {
-		case AR5K_TX_QUEUE_BEACON:
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_FRSHED_DBA_GT |
-				AR5K_QCU_MISC_CBREXP_BCN_DIS |
-				AR5K_QCU_MISC_BCN_ENABLE);
-
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
-				(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
-				AR5K_DCU_MISC_ARBLOCK_CTL_S) |
-				AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
-				AR5K_DCU_MISC_BCN_ENABLE);
-			break;
-
-		case AR5K_TX_QUEUE_CAB:
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_FRSHED_DBA_GT |
-				AR5K_QCU_MISC_CBREXP_DIS |
-				AR5K_QCU_MISC_CBREXP_BCN_DIS);
-
-			ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
-				(AR5K_TUNE_SW_BEACON_RESP -
-				AR5K_TUNE_DMA_BEACON_RESP) -
-				AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
-				AR5K_QCU_RDYTIMECFG_ENABLE,
-				AR5K_QUEUE_RDYTIMECFG(queue));
-
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
-				(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
-				AR5K_DCU_MISC_ARBLOCK_CTL_S));
-			break;
-
-		case AR5K_TX_QUEUE_UAPSD:
-			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_CBREXP_DIS);
-			break;
-
-		case AR5K_TX_QUEUE_DATA:
-		default:
-			break;
-		}
-
-		/* TODO: Handle frame compression */
-
-		/*
-		 * Enable interrupts for this tx queue
-		 * in the secondary interrupt mask registers
-		 */
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
-
-		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
-			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
-
-		/* Update secondary interrupt mask registers */
-
-		/* Filter out inactive queues */
-		ah->ah_txq_imr_txok &= ah->ah_txq_status;
-		ah->ah_txq_imr_txerr &= ah->ah_txq_status;
-		ah->ah_txq_imr_txurn &= ah->ah_txq_status;
-		ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
-		ah->ah_txq_imr_txeol &= ah->ah_txq_status;
-		ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
-		ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
-		ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
-		ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
-
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
-			AR5K_SIMR0_QCU_TXOK) |
-			AR5K_REG_SM(ah->ah_txq_imr_txdesc,
-			AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
-			AR5K_SIMR1_QCU_TXERR) |
-			AR5K_REG_SM(ah->ah_txq_imr_txeol,
-			AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
-		/* Update simr2 but don't overwrite rest simr2 settings */
-		AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
-		AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
-			AR5K_REG_SM(ah->ah_txq_imr_txurn,
-			AR5K_SIMR2_QCU_TXURN));
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
-			AR5K_SIMR3_QCBRORN) |
-			AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
-			AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
-			AR5K_SIMR4_QTRIG), AR5K_SIMR4);
-		/* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
-		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
-			AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
-		/* No queue has TXNOFRM enabled, disable the interrupt
-		 * by setting AR5K_TXNOFRM to zero */
-		if (ah->ah_txq_imr_nofrm == 0)
-			ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
-
-		/* Set QCU mask for this DCU to save power */
-		AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
-	}
-
-	return 0;
-}
-
-/*
- * Get slot time from DCU
- */
-unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (ah->ah_version == AR5K_AR5210)
-		return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
-				AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
-	else
-		return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
-}
-
-/*
- * Set slot time on DCU
- */
-int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
-{
-	ATH5K_TRACE(ah->ah_sc);
-	if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
-		return -EINVAL;
-
-	if (ah->ah_version == AR5K_AR5210)
-		ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
-				ah->ah_turbo), AR5K_SLOT_TIME);
-	else
-		ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
-
-	return 0;
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/reg.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/reg.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/reg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,2589 +0,0 @@
-/*
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2007-2008 Michael Taylor <mike.taylor@apprion.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*
- * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k
- * maintained by Reyk Floeter
- *
- * I tried to document those registers by looking at ar5k code, some
- * 802.11 (802.11e mostly) papers and by reading various public available
- * Atheros presentations and papers like these:
- *
- * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf
- *        http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
- *
- * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
- *
- * This file also contains register values found on a memory dump of
- * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal
- * released by Atheros and on various debug messages found on the net.
- */
-
-
-
-/*====MAC DMA REGISTERS====*/
-
-/*
- * AR5210-Specific TXDP registers
- * 5210 has only 2 transmit queues so no DCU/QCU, just
- * 2 transmit descriptor pointers...
- */
-#define AR5K_NOQCU_TXDP0	0x0000		/* Queue 0 - data */
-#define AR5K_NOQCU_TXDP1	0x0004		/* Queue 1 - beacons */
-
-/*
- * Mac Control Register
- */
-#define	AR5K_CR		0x0008			/* Register Address */
-#define AR5K_CR_TXE0	0x00000001	/* TX Enable for queue 0 on 5210 */
-#define AR5K_CR_TXE1	0x00000002	/* TX Enable for queue 1 on 5210 */
-#define	AR5K_CR_RXE	0x00000004	/* RX Enable */
-#define AR5K_CR_TXD0	0x00000008	/* TX Disable for queue 0 on 5210 */
-#define AR5K_CR_TXD1	0x00000010	/* TX Disable for queue 1 on 5210 */
-#define	AR5K_CR_RXD	0x00000020	/* RX Disable */
-#define	AR5K_CR_SWI	0x00000040	/* Software Interrupt */
-
-/*
- * RX Descriptor Pointer register
- */
-#define	AR5K_RXDP	0x000c
-
-/*
- * Configuration and status register
- */
-#define	AR5K_CFG		0x0014			/* Register Address */
-#define	AR5K_CFG_SWTD		0x00000001	/* Byte-swap TX descriptor (for big endian archs) */
-#define	AR5K_CFG_SWTB		0x00000002	/* Byte-swap TX buffer */
-#define	AR5K_CFG_SWRD		0x00000004	/* Byte-swap RX descriptor */
-#define	AR5K_CFG_SWRB		0x00000008	/* Byte-swap RX buffer */
-#define	AR5K_CFG_SWRG		0x00000010	/* Byte-swap Register access */
-#define AR5K_CFG_IBSS		0x00000020 	/* 0-BSS, 1-IBSS [5211+] */
-#define AR5K_CFG_PHY_OK		0x00000100	/* [5211+] */
-#define AR5K_CFG_EEBS		0x00000200	/* EEPROM is busy */
-#define	AR5K_CFG_CLKGD		0x00000400	/* Clock gated (Disable dynamic clock) */
-#define AR5K_CFG_TXCNT		0x00007800	/* Tx frame count (?) [5210] */
-#define AR5K_CFG_TXCNT_S	11
-#define AR5K_CFG_TXFSTAT	0x00008000	/* Tx frame status (?) [5210] */
-#define AR5K_CFG_TXFSTRT	0x00010000	/* [5210] */
-#define	AR5K_CFG_PCI_THRES	0x00060000	/* PCI Master req q threshold [5211+] */
-#define	AR5K_CFG_PCI_THRES_S	17
-
-/*
- * Interrupt enable register
- */
-#define AR5K_IER		0x0024		/* Register Address */
-#define AR5K_IER_DISABLE	0x00000000	/* Disable card interrupts */
-#define AR5K_IER_ENABLE		0x00000001	/* Enable card interrupts */
-
-
-/*
- * 0x0028 is Beacon Control Register on 5210
- * and first RTS duration register on 5211
- */
-
-/*
- * Beacon control register [5210]
- */
-#define AR5K_BCR		0x0028		/* Register Address */
-#define AR5K_BCR_AP		0x00000000	/* AP mode */
-#define AR5K_BCR_ADHOC		0x00000001	/* Ad-Hoc mode */
-#define AR5K_BCR_BDMAE		0x00000002	/* DMA enable */
-#define AR5K_BCR_TQ1FV		0x00000004	/* Use Queue1 for CAB traffic */
-#define AR5K_BCR_TQ1V		0x00000008	/* Use Queue1 for Beacon traffic */
-#define AR5K_BCR_BCGET		0x00000010
-
-/*
- * First RTS duration register [5211]
- */
-#define AR5K_RTSD0		0x0028		/* Register Address */
-#define	AR5K_RTSD0_6		0x000000ff	/* 6Mb RTS duration mask (?) */
-#define	AR5K_RTSD0_6_S		0		/* 6Mb RTS duration shift (?) */
-#define	AR5K_RTSD0_9		0x0000ff00	/* 9Mb*/
-#define	AR5K_RTSD0_9_S		8
-#define	AR5K_RTSD0_12		0x00ff0000	/* 12Mb*/
-#define	AR5K_RTSD0_12_S		16
-#define	AR5K_RTSD0_18		0xff000000	/* 16Mb*/
-#define	AR5K_RTSD0_18_S		24
-
-
-/*
- * 0x002c is Beacon Status Register on 5210
- * and second RTS duration register on 5211
- */
-
-/*
- * Beacon status register [5210]
- *
- * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR
- * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning
- * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR).
- * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i
- * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what
- * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
- */
-#define AR5K_BSR		0x002c			/* Register Address */
-#define AR5K_BSR_BDLYSW		0x00000001	/* SW Beacon delay (?) */
-#define AR5K_BSR_BDLYDMA	0x00000002	/* DMA Beacon delay (?) */
-#define AR5K_BSR_TXQ1F		0x00000004	/* Beacon queue (1) finished */
-#define AR5K_BSR_ATIMDLY	0x00000008	/* ATIM delay (?) */
-#define AR5K_BSR_SNPADHOC	0x00000100	/* Ad-hoc mode set (?) */
-#define AR5K_BSR_SNPBDMAE	0x00000200	/* Beacon DMA enabled (?) */
-#define AR5K_BSR_SNPTQ1FV	0x00000400	/* Queue1 is used for CAB traffic (?) */
-#define AR5K_BSR_SNPTQ1V	0x00000800	/* Queue1 is used for Beacon traffic (?) */
-#define AR5K_BSR_SNAPSHOTSVALID	0x00001000	/* BCR snapshots are valid (?) */
-#define AR5K_BSR_SWBA_CNT	0x00ff0000
-
-/*
- * Second RTS duration register [5211]
- */
-#define AR5K_RTSD1		0x002c			/* Register Address */
-#define	AR5K_RTSD1_24		0x000000ff	/* 24Mb */
-#define	AR5K_RTSD1_24_S		0
-#define	AR5K_RTSD1_36		0x0000ff00	/* 36Mb */
-#define	AR5K_RTSD1_36_S		8
-#define	AR5K_RTSD1_48		0x00ff0000	/* 48Mb */
-#define	AR5K_RTSD1_48_S		16
-#define	AR5K_RTSD1_54		0xff000000	/* 54Mb */
-#define	AR5K_RTSD1_54_S		24
-
-
-/*
- * Transmit configuration register
- */
-#define AR5K_TXCFG			0x0030			/* Register Address */
-#define AR5K_TXCFG_SDMAMR		0x00000007	/* DMA size (read) */
-#define AR5K_TXCFG_SDMAMR_S		0
-#define AR5K_TXCFG_B_MODE		0x00000008	/* Set b mode for 5111 (enable 2111) */
-#define AR5K_TXCFG_TXFSTP		0x00000008	/* TX DMA full Stop [5210] */
-#define AR5K_TXCFG_TXFULL		0x000003f0	/* TX Triger level mask */
-#define AR5K_TXCFG_TXFULL_S		4
-#define AR5K_TXCFG_TXFULL_0B		0x00000000
-#define AR5K_TXCFG_TXFULL_64B		0x00000010
-#define AR5K_TXCFG_TXFULL_128B		0x00000020
-#define AR5K_TXCFG_TXFULL_192B		0x00000030
-#define AR5K_TXCFG_TXFULL_256B		0x00000040
-#define AR5K_TXCFG_TXCONT_EN		0x00000080
-#define AR5K_TXCFG_DMASIZE		0x00000100	/* Flag for passing DMA size [5210] */
-#define AR5K_TXCFG_JUMBO_DESC_EN	0x00000400	/* Enable jumbo tx descriptors [5211+] */
-#define AR5K_TXCFG_ADHOC_BCN_ATIM	0x00000800	/* Adhoc Beacon ATIM Policy */
-#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS	0x00001000	/* Disable ATIM window defer [5211+] */
-#define AR5K_TXCFG_RTSRND		0x00001000	/* [5211+] */
-#define AR5K_TXCFG_FRMPAD_DIS		0x00002000	/* [5211+] */
-#define AR5K_TXCFG_RDY_CBR_DIS		0x00004000	/* Ready time CBR disable [5211+] */
-#define AR5K_TXCFG_JUMBO_FRM_MODE	0x00008000	/* Jumbo frame mode [5211+] */
-#define	AR5K_TXCFG_DCU_DBL_BUF_DIS	0x00008000	/* Disable double buffering on DCU */
-#define AR5K_TXCFG_DCU_CACHING_DIS	0x00010000	/* Disable DCU caching */
-
-/*
- * Receive configuration register
- */
-#define AR5K_RXCFG		0x0034			/* Register Address */
-#define AR5K_RXCFG_SDMAMW	0x00000007	/* DMA size (write) */
-#define AR5K_RXCFG_SDMAMW_S	0
-#define AR5K_RXCFG_ZLFDMA	0x00000008	/* Enable Zero-length frame DMA */
-#define	AR5K_RXCFG_DEF_ANTENNA	0x00000010	/* Default antenna (?) */
-#define AR5K_RXCFG_JUMBO_RXE	0x00000020	/* Enable jumbo rx descriptors [5211+] */
-#define AR5K_RXCFG_JUMBO_WRAP	0x00000040	/* Wrap jumbo frames [5211+] */
-#define AR5K_RXCFG_SLE_ENTRY	0x00000080	/* Sleep entry policy */
-
-/*
- * Receive jumbo descriptor last address register
- * Only found in 5211 (?)
- */
-#define AR5K_RXJLA		0x0038
-
-/*
- * MIB control register
- */
-#define AR5K_MIBC		0x0040			/* Register Address */
-#define AR5K_MIBC_COW		0x00000001	/* Warn test indicator */
-#define AR5K_MIBC_FMC		0x00000002	/* Freeze MIB Counters  */
-#define AR5K_MIBC_CMC		0x00000004	/* Clean MIB Counters  */
-#define AR5K_MIBC_MCS		0x00000008	/* MIB counter strobe */
-
-/*
- * Timeout prescale register
- */
-#define AR5K_TOPS		0x0044
-#define	AR5K_TOPS_M		0x0000ffff
-
-/*
- * Receive timeout register (no frame received)
- */
-#define AR5K_RXNOFRM		0x0048
-#define	AR5K_RXNOFRM_M		0x000003ff
-
-/*
- * Transmit timeout register (no frame sent)
- */
-#define AR5K_TXNOFRM		0x004c
-#define	AR5K_TXNOFRM_M		0x000003ff
-#define	AR5K_TXNOFRM_QCU	0x000ffc00
-#define	AR5K_TXNOFRM_QCU_S	10
-
-/*
- * Receive frame gap timeout register
- */
-#define AR5K_RPGTO		0x0050
-#define AR5K_RPGTO_M		0x000003ff
-
-/*
- * Receive frame count limit register
- */
-#define AR5K_RFCNT		0x0054
-#define AR5K_RFCNT_M		0x0000001f	/* [5211+] (?) */
-#define AR5K_RFCNT_RFCL		0x0000000f	/* [5210] */
-
-/*
- * Misc settings register
- * (reserved0-3)
- */
-#define AR5K_MISC		0x0058			/* Register Address */
-#define	AR5K_MISC_DMA_OBS_M	0x000001e0
-#define	AR5K_MISC_DMA_OBS_S	5
-#define	AR5K_MISC_MISC_OBS_M	0x00000e00
-#define	AR5K_MISC_MISC_OBS_S	9
-#define	AR5K_MISC_MAC_OBS_LSB_M	0x00007000
-#define	AR5K_MISC_MAC_OBS_LSB_S	12
-#define	AR5K_MISC_MAC_OBS_MSB_M	0x00038000
-#define	AR5K_MISC_MAC_OBS_MSB_S	15
-#define AR5K_MISC_LED_DECAY	0x001c0000	/* [5210] */
-#define AR5K_MISC_LED_BLINK	0x00e00000	/* [5210] */
-
-/*
- * QCU/DCU clock gating register (5311)
- * (reserved4-5)
- */
-#define	AR5K_QCUDCU_CLKGT	0x005c			/* Register Address (?) */
-#define	AR5K_QCUDCU_CLKGT_QCU	0x0000ffff	/* Mask for QCU clock */
-#define	AR5K_QCUDCU_CLKGT_DCU	0x07ff0000	/* Mask for DCU clock */
-
-/*
- * Interrupt Status Registers
- *
- * For 5210 there is only one status register but for
- * 5211/5212 we have one primary and 4 secondary registers.
- * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
- * Most of these bits are common for all chipsets.
- */
-#define AR5K_ISR		0x001c			/* Register Address [5210] */
-#define AR5K_PISR		0x0080			/* Register Address [5211+] */
-#define AR5K_ISR_RXOK		0x00000001	/* Frame successfuly recieved */
-#define AR5K_ISR_RXDESC		0x00000002	/* RX descriptor request */
-#define AR5K_ISR_RXERR		0x00000004	/* Receive error */
-#define AR5K_ISR_RXNOFRM	0x00000008	/* No frame received (receive timeout) */
-#define AR5K_ISR_RXEOL		0x00000010	/* Empty RX descriptor */
-#define AR5K_ISR_RXORN		0x00000020	/* Receive FIFO overrun */
-#define AR5K_ISR_TXOK		0x00000040	/* Frame successfuly transmited */
-#define AR5K_ISR_TXDESC		0x00000080	/* TX descriptor request */
-#define AR5K_ISR_TXERR		0x00000100	/* Transmit error */
-#define AR5K_ISR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout) */
-#define AR5K_ISR_TXEOL		0x00000400	/* Empty TX descriptor */
-#define AR5K_ISR_TXURN		0x00000800	/* Transmit FIFO underrun */
-#define AR5K_ISR_MIB		0x00001000	/* Update MIB counters */
-#define AR5K_ISR_SWI		0x00002000	/* Software interrupt */
-#define AR5K_ISR_RXPHY		0x00004000	/* PHY error */
-#define AR5K_ISR_RXKCM		0x00008000	/* RX Key cache miss */
-#define AR5K_ISR_SWBA		0x00010000	/* Software beacon alert */
-#define AR5K_ISR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */
-#define AR5K_ISR_BMISS		0x00040000	/* Beacon missed */
-#define AR5K_ISR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */
-#define AR5K_ISR_BNR		0x00100000 	/* Beacon not ready [5211+] */
-#define AR5K_ISR_MCABT		0x00100000	/* Master Cycle Abort [5210] */
-#define AR5K_ISR_RXCHIRP	0x00200000	/* CHIRP Received [5212+] */
-#define AR5K_ISR_SSERR		0x00200000	/* Signaled System Error [5210] */
-#define AR5K_ISR_DPERR		0x00400000	/* Det par Error (?) [5210] */
-#define AR5K_ISR_RXDOPPLER	0x00400000	/* Doppler chirp received [5212+] */
-#define AR5K_ISR_TIM		0x00800000	/* [5211+] */
-#define AR5K_ISR_BCNMISC	0x00800000	/* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
-						CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
-#define AR5K_ISR_GPIO		0x01000000	/* GPIO (rf kill) */
-#define AR5K_ISR_QCBRORN	0x02000000	/* QCU CBR overrun [5211+] */
-#define AR5K_ISR_QCBRURN	0x04000000	/* QCU CBR underrun [5211+] */
-#define AR5K_ISR_QTRIG		0x08000000	/* QCU scheduling trigger [5211+] */
-
-/*
- * Secondary status registers [5211+] (0 - 4)
- *
- * These give the status for each QCU, only QCUs 0-9 are
- * represented.
- */
-#define AR5K_SISR0		0x0084			/* Register Address [5211+] */
-#define AR5K_SISR0_QCU_TXOK	0x000003ff	/* Mask for QCU_TXOK */
-#define AR5K_SISR0_QCU_TXOK_S	0
-#define AR5K_SISR0_QCU_TXDESC	0x03ff0000	/* Mask for QCU_TXDESC */
-#define AR5K_SISR0_QCU_TXDESC_S	16
-
-#define AR5K_SISR1		0x0088			/* Register Address [5211+] */
-#define AR5K_SISR1_QCU_TXERR	0x000003ff	/* Mask for QCU_TXERR */
-#define AR5K_SISR1_QCU_TXERR_S	0
-#define AR5K_SISR1_QCU_TXEOL	0x03ff0000	/* Mask for QCU_TXEOL */
-#define AR5K_SISR1_QCU_TXEOL_S	16
-
-#define AR5K_SISR2		0x008c			/* Register Address [5211+] */
-#define AR5K_SISR2_QCU_TXURN	0x000003ff	/* Mask for QCU_TXURN */
-#define	AR5K_SISR2_QCU_TXURN_S	0
-#define	AR5K_SISR2_MCABT	0x00100000	/* Master Cycle Abort */
-#define	AR5K_SISR2_SSERR	0x00200000	/* Signaled System Error */
-#define	AR5K_SISR2_DPERR	0x00400000	/* Bus parity error */
-#define	AR5K_SISR2_TIM		0x01000000	/* [5212+] */
-#define	AR5K_SISR2_CAB_END	0x02000000	/* [5212+] */
-#define	AR5K_SISR2_DTIM_SYNC	0x04000000	/* DTIM sync lost [5212+] */
-#define	AR5K_SISR2_BCN_TIMEOUT	0x08000000	/* Beacon Timeout [5212+] */
-#define	AR5K_SISR2_CAB_TIMEOUT	0x10000000	/* CAB Timeout [5212+] */
-#define	AR5K_SISR2_DTIM		0x20000000	/* [5212+] */
-#define	AR5K_SISR2_TSFOOR	0x80000000	/* TSF OOR (?) */
-
-#define AR5K_SISR3		0x0090			/* Register Address [5211+] */
-#define AR5K_SISR3_QCBRORN	0x000003ff	/* Mask for QCBRORN */
-#define AR5K_SISR3_QCBRORN_S	0
-#define AR5K_SISR3_QCBRURN	0x03ff0000	/* Mask for QCBRURN */
-#define AR5K_SISR3_QCBRURN_S	16
-
-#define AR5K_SISR4		0x0094			/* Register Address [5211+] */
-#define AR5K_SISR4_QTRIG	0x000003ff	/* Mask for QTRIG */
-#define AR5K_SISR4_QTRIG_S	0
-
-/*
- * Shadow read-and-clear interrupt status registers [5211+]
- */
-#define AR5K_RAC_PISR		0x00c0		/* Read and clear PISR */
-#define AR5K_RAC_SISR0		0x00c4		/* Read and clear SISR0 */
-#define AR5K_RAC_SISR1		0x00c8		/* Read and clear SISR1 */
-#define AR5K_RAC_SISR2		0x00cc		/* Read and clear SISR2 */
-#define AR5K_RAC_SISR3		0x00d0		/* Read and clear SISR3 */
-#define AR5K_RAC_SISR4		0x00d4		/* Read and clear SISR4 */
-
-/*
- * Interrupt Mask Registers
- *
- * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
- * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match.
- */
-#define	AR5K_IMR		0x0020			/* Register Address [5210] */
-#define AR5K_PIMR		0x00a0			/* Register Address [5211+] */
-#define AR5K_IMR_RXOK		0x00000001	/* Frame successfuly recieved*/
-#define AR5K_IMR_RXDESC		0x00000002	/* RX descriptor request*/
-#define AR5K_IMR_RXERR		0x00000004	/* Receive error*/
-#define AR5K_IMR_RXNOFRM	0x00000008	/* No frame received (receive timeout)*/
-#define AR5K_IMR_RXEOL		0x00000010	/* Empty RX descriptor*/
-#define AR5K_IMR_RXORN		0x00000020	/* Receive FIFO overrun*/
-#define AR5K_IMR_TXOK		0x00000040	/* Frame successfuly transmited*/
-#define AR5K_IMR_TXDESC		0x00000080	/* TX descriptor request*/
-#define AR5K_IMR_TXERR		0x00000100	/* Transmit error*/
-#define AR5K_IMR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout)*/
-#define AR5K_IMR_TXEOL		0x00000400	/* Empty TX descriptor*/
-#define AR5K_IMR_TXURN		0x00000800	/* Transmit FIFO underrun*/
-#define AR5K_IMR_MIB		0x00001000	/* Update MIB counters*/
-#define AR5K_IMR_SWI		0x00002000	/* Software interrupt */
-#define AR5K_IMR_RXPHY		0x00004000	/* PHY error*/
-#define AR5K_IMR_RXKCM		0x00008000	/* RX Key cache miss */
-#define AR5K_IMR_SWBA		0x00010000	/* Software beacon alert*/
-#define AR5K_IMR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */
-#define AR5K_IMR_BMISS		0x00040000	/* Beacon missed*/
-#define AR5K_IMR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */
-#define AR5K_IMR_BNR		0x00100000 	/* Beacon not ready [5211+] */
-#define AR5K_IMR_MCABT		0x00100000	/* Master Cycle Abort [5210] */
-#define AR5K_IMR_RXCHIRP	0x00200000	/* CHIRP Received [5212+]*/
-#define AR5K_IMR_SSERR		0x00200000	/* Signaled System Error [5210] */
-#define AR5K_IMR_DPERR		0x00400000	/* Det par Error (?) [5210] */
-#define AR5K_IMR_RXDOPPLER	0x00400000	/* Doppler chirp received [5212+] */
-#define AR5K_IMR_TIM		0x00800000	/* [5211+] */
-#define AR5K_IMR_BCNMISC	0x00800000	/* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT,
-						CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */
-#define AR5K_IMR_GPIO		0x01000000	/* GPIO (rf kill)*/
-#define AR5K_IMR_QCBRORN	0x02000000	/* QCU CBR overrun (?) [5211+] */
-#define AR5K_IMR_QCBRURN	0x04000000	/* QCU CBR underrun (?) [5211+] */
-#define AR5K_IMR_QTRIG		0x08000000	/* QCU scheduling trigger [5211+] */
-
-/*
- * Secondary interrupt mask registers [5211+] (0 - 4)
- */
-#define AR5K_SIMR0		0x00a4			/* Register Address [5211+] */
-#define AR5K_SIMR0_QCU_TXOK	0x000003ff	/* Mask for QCU_TXOK */
-#define AR5K_SIMR0_QCU_TXOK_S	0
-#define AR5K_SIMR0_QCU_TXDESC	0x03ff0000	/* Mask for QCU_TXDESC */
-#define AR5K_SIMR0_QCU_TXDESC_S	16
-
-#define AR5K_SIMR1		0x00a8			/* Register Address [5211+] */
-#define AR5K_SIMR1_QCU_TXERR	0x000003ff	/* Mask for QCU_TXERR */
-#define AR5K_SIMR1_QCU_TXERR_S	0
-#define AR5K_SIMR1_QCU_TXEOL	0x03ff0000	/* Mask for QCU_TXEOL */
-#define AR5K_SIMR1_QCU_TXEOL_S	16
-
-#define AR5K_SIMR2		0x00ac			/* Register Address [5211+] */
-#define AR5K_SIMR2_QCU_TXURN	0x000003ff	/* Mask for QCU_TXURN */
-#define AR5K_SIMR2_QCU_TXURN_S	0
-#define	AR5K_SIMR2_MCABT	0x00100000	/* Master Cycle Abort */
-#define	AR5K_SIMR2_SSERR	0x00200000	/* Signaled System Error */
-#define	AR5K_SIMR2_DPERR	0x00400000	/* Bus parity error */
-#define	AR5K_SIMR2_TIM		0x01000000	/* [5212+] */
-#define	AR5K_SIMR2_CAB_END	0x02000000	/* [5212+] */
-#define	AR5K_SIMR2_DTIM_SYNC	0x04000000	/* DTIM Sync lost [5212+] */
-#define	AR5K_SIMR2_BCN_TIMEOUT	0x08000000	/* Beacon Timeout [5212+] */
-#define	AR5K_SIMR2_CAB_TIMEOUT	0x10000000	/* CAB Timeout [5212+] */
-#define	AR5K_SIMR2_DTIM		0x20000000	/* [5212+] */
-#define	AR5K_SIMR2_TSFOOR	0x80000000	/* TSF OOR (?) */
-
-#define AR5K_SIMR3		0x00b0			/* Register Address [5211+] */
-#define AR5K_SIMR3_QCBRORN	0x000003ff	/* Mask for QCBRORN */
-#define AR5K_SIMR3_QCBRORN_S	0
-#define AR5K_SIMR3_QCBRURN	0x03ff0000	/* Mask for QCBRURN */
-#define AR5K_SIMR3_QCBRURN_S	16
-
-#define AR5K_SIMR4		0x00b4			/* Register Address [5211+] */
-#define AR5K_SIMR4_QTRIG	0x000003ff	/* Mask for QTRIG */
-#define AR5K_SIMR4_QTRIG_S	0
-
-/*
- * DMA Debug registers 0-7
- * 0xe0 - 0xfc
- */
-
-/*
- * Decompression mask registers [5212+]
- */
-#define AR5K_DCM_ADDR		0x0400		/*Decompression mask address (index) */
-#define AR5K_DCM_DATA		0x0404		/*Decompression mask data */
-
-/*
- * Wake On Wireless pattern control register [5212+]
- */
-#define	AR5K_WOW_PCFG			0x0410			/* Register Address */
-#define	AR5K_WOW_PCFG_PAT_MATCH_EN	0x00000001	/* Pattern match enable */
-#define	AR5K_WOW_PCFG_LONG_FRAME_POL	0x00000002	/* Long frame policy */
-#define	AR5K_WOW_PCFG_WOBMISS		0x00000004	/* Wake on bea(con) miss (?) */
-#define	AR5K_WOW_PCFG_PAT_0_EN		0x00000100	/* Enable pattern 0 */
-#define	AR5K_WOW_PCFG_PAT_1_EN		0x00000200	/* Enable pattern 1 */
-#define	AR5K_WOW_PCFG_PAT_2_EN		0x00000400	/* Enable pattern 2 */
-#define	AR5K_WOW_PCFG_PAT_3_EN		0x00000800	/* Enable pattern 3 */
-#define	AR5K_WOW_PCFG_PAT_4_EN		0x00001000	/* Enable pattern 4 */
-#define	AR5K_WOW_PCFG_PAT_5_EN		0x00002000	/* Enable pattern 5 */
-
-/*
- * Wake On Wireless pattern index register (?) [5212+]
- */
-#define	AR5K_WOW_PAT_IDX	0x0414
-
-/*
- * Wake On Wireless pattern data register [5212+]
- */
-#define	AR5K_WOW_PAT_DATA	0x0418			/* Register Address */
-#define	AR5K_WOW_PAT_DATA_0_3_V	0x00000001	/* Pattern 0, 3 value */
-#define	AR5K_WOW_PAT_DATA_1_4_V	0x00000100	/* Pattern 1, 4 value */
-#define	AR5K_WOW_PAT_DATA_2_5_V	0x00010000	/* Pattern 2, 5 value */
-#define	AR5K_WOW_PAT_DATA_0_3_M	0x01000000	/* Pattern 0, 3 mask */
-#define	AR5K_WOW_PAT_DATA_1_4_M	0x04000000	/* Pattern 1, 4 mask */
-#define	AR5K_WOW_PAT_DATA_2_5_M	0x10000000	/* Pattern 2, 5 mask */
-
-/*
- * Decompression configuration registers [5212+]
- */
-#define AR5K_DCCFG		0x0420			/* Register Address */
-#define AR5K_DCCFG_GLOBAL_EN	0x00000001	/* Enable decompression on all queues */
-#define AR5K_DCCFG_BYPASS_EN	0x00000002	/* Bypass decompression */
-#define AR5K_DCCFG_BCAST_EN	0x00000004	/* Enable decompression for bcast frames */
-#define AR5K_DCCFG_MCAST_EN	0x00000008	/* Enable decompression for mcast frames */
-
-/*
- * Compression configuration registers [5212+]
- */
-#define AR5K_CCFG		0x0600			/* Register Address */
-#define	AR5K_CCFG_WINDOW_SIZE	0x00000007	/* Compression window size */
-#define	AR5K_CCFG_CPC_EN	0x00000008	/* Enable performance counters */
-
-#define AR5K_CCFG_CCU		0x0604			/* Register Address */
-#define AR5K_CCFG_CCU_CUP_EN	0x00000001	/* CCU Catchup enable */
-#define AR5K_CCFG_CCU_CREDIT	0x00000002	/* CCU Credit (field) */
-#define AR5K_CCFG_CCU_CD_THRES	0x00000080	/* CCU Cyc(lic?) debt threshold (field) */
-#define AR5K_CCFG_CCU_CUP_LCNT	0x00010000	/* CCU Catchup lit(?) count */
-#define	AR5K_CCFG_CCU_INIT	0x00100200	/* Initial value during reset */
-
-/*
- * Compression performance counter registers [5212+]
- */
-#define AR5K_CPC0		0x0610		/* Compression performance counter 0 */
-#define AR5K_CPC1		0x0614		/* Compression performance counter 1*/
-#define AR5K_CPC2		0x0618		/* Compression performance counter 2 */
-#define AR5K_CPC3		0x061c		/* Compression performance counter 3 */
-#define AR5K_CPCOVF		0x0620		/* Compression performance overflow */
-
-
-/*
- * Queue control unit (QCU) registers [5211+]
- *
- * Card has 12 TX Queues but i see that only 0-9 are used (?)
- * both in binary HAL (see ah.h) and ar5k. Each queue has it's own
- * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate)
- * configuration register (0x08c0 - 0x08ec), a ready time configuration
- * register (0x0900 - 0x092c), a misc configuration register (0x09c0 -
- * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some
- * global registers, QCU transmit enable/disable and "one shot arm (?)"
- * set/clear, which contain status for all queues (we shift by 1 for each
- * queue). To access these registers easily we define some macros here
- * that are used inside HAL. For more infos check out *_tx_queue functs.
- */
-
-/*
- * Generic QCU Register access macros
- */
-#define	AR5K_QUEUE_REG(_r, _q)		(((_q) << 2) + _r)
-#define AR5K_QCU_GLOBAL_READ(_r, _q)	(AR5K_REG_READ(_r) & (1 << _q))
-#define AR5K_QCU_GLOBAL_WRITE(_r, _q)	AR5K_REG_WRITE(_r, (1 << _q))
-
-/*
- * QCU Transmit descriptor pointer registers
- */
-#define AR5K_QCU_TXDP_BASE	0x0800		/* Register Address - Queue0 TXDP */
-#define AR5K_QUEUE_TXDP(_q)	AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q)
-
-/*
- * QCU Transmit enable register
- */
-#define AR5K_QCU_TXE		0x0840
-#define AR5K_ENABLE_QUEUE(_q)	AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q)
-#define AR5K_QUEUE_ENABLED(_q)	AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q)
-
-/*
- * QCU Transmit disable register
- */
-#define AR5K_QCU_TXD		0x0880
-#define AR5K_DISABLE_QUEUE(_q)	AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q)
-#define AR5K_QUEUE_DISABLED(_q)	AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q)
-
-/*
- * QCU Constant Bit Rate configuration registers
- */
-#define	AR5K_QCU_CBRCFG_BASE		0x08c0	/* Register Address - Queue0 CBRCFG */
-#define	AR5K_QCU_CBRCFG_INTVAL		0x00ffffff	/* CBR Interval mask */
-#define AR5K_QCU_CBRCFG_INTVAL_S	0
-#define	AR5K_QCU_CBRCFG_ORN_THRES	0xff000000	/* CBR overrun threshold mask */
-#define AR5K_QCU_CBRCFG_ORN_THRES_S	24
-#define	AR5K_QUEUE_CBRCFG(_q)		AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q)
-
-/*
- * QCU Ready time configuration registers
- */
-#define	AR5K_QCU_RDYTIMECFG_BASE	0x0900	/* Register Address - Queue0 RDYTIMECFG */
-#define	AR5K_QCU_RDYTIMECFG_INTVAL	0x00ffffff	/* Ready time interval mask */
-#define AR5K_QCU_RDYTIMECFG_INTVAL_S	0
-#define	AR5K_QCU_RDYTIMECFG_ENABLE	0x01000000	/* Ready time enable mask */
-#define AR5K_QUEUE_RDYTIMECFG(_q)	AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q)
-
-/*
- * QCU one shot arm set registers
- */
-#define	AR5K_QCU_ONESHOTARM_SET		0x0940	/* Register Address -QCU "one shot arm set (?)" */
-#define	AR5K_QCU_ONESHOTARM_SET_M	0x0000ffff
-
-/*
- * QCU one shot arm clear registers
- */
-#define	AR5K_QCU_ONESHOTARM_CLEAR	0x0980	/* Register Address -QCU "one shot arm clear (?)" */
-#define	AR5K_QCU_ONESHOTARM_CLEAR_M	0x0000ffff
-
-/*
- * QCU misc registers
- */
-#define AR5K_QCU_MISC_BASE		0x09c0			/* Register Address -Queue0 MISC */
-#define	AR5K_QCU_MISC_FRSHED_M		0x0000000f	/* Frame sheduling mask */
-#define	AR5K_QCU_MISC_FRSHED_ASAP		0	/* ASAP */
-#define	AR5K_QCU_MISC_FRSHED_CBR		1	/* Constant Bit Rate */
-#define	AR5K_QCU_MISC_FRSHED_DBA_GT		2	/* DMA Beacon alert gated */
-#define	AR5K_QCU_MISC_FRSHED_TIM_GT		3	/* TIMT gated */
-#define	AR5K_QCU_MISC_FRSHED_BCN_SENT_GT	4	/* Beacon sent gated */
-#define	AR5K_QCU_MISC_ONESHOT_ENABLE	0x00000010	/* Oneshot enable */
-#define	AR5K_QCU_MISC_CBREXP_DIS	0x00000020	/* Disable CBR expired counter (normal queue) */
-#define	AR5K_QCU_MISC_CBREXP_BCN_DIS	0x00000040	/* Disable CBR expired counter (beacon queue) */
-#define	AR5K_QCU_MISC_BCN_ENABLE	0x00000080	/* Enable Beacon use */
-#define	AR5K_QCU_MISC_CBR_THRES_ENABLE	0x00000100	/* CBR expired threshold enabled */
-#define	AR5K_QCU_MISC_RDY_VEOL_POLICY	0x00000200	/* TXE reset when RDYTIME expired or VEOL */
-#define	AR5K_QCU_MISC_CBR_RESET_CNT	0x00000400	/* CBR threshold (counter) reset */
-#define	AR5K_QCU_MISC_DCU_EARLY		0x00000800	/* DCU early termination */
-#define AR5K_QCU_MISC_DCU_CMP_EN	0x00001000	/* Enable frame compression */
-#define AR5K_QUEUE_MISC(_q)		AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q)
-
-
-/*
- * QCU status registers
- */
-#define AR5K_QCU_STS_BASE	0x0a00			/* Register Address - Queue0 STS */
-#define	AR5K_QCU_STS_FRMPENDCNT	0x00000003	/* Frames pending counter */
-#define	AR5K_QCU_STS_CBREXPCNT	0x0000ff00	/* CBR expired counter */
-#define	AR5K_QUEUE_STATUS(_q)	AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q)
-
-/*
- * QCU ready time shutdown register
- */
-#define AR5K_QCU_RDYTIMESHDN	0x0a40
-#define AR5K_QCU_RDYTIMESHDN_M	0x000003ff
-
-/*
- * QCU compression buffer base registers [5212+]
- */
-#define AR5K_QCU_CBB_SELECT	0x0b00
-#define AR5K_QCU_CBB_ADDR	0x0b04
-#define AR5K_QCU_CBB_ADDR_S	9
-
-/*
- * QCU compression buffer configuration register [5212+]
- * (buffer size)
- */
-#define AR5K_QCU_CBCFG		0x0b08
-
-
-
-/*
- * Distributed Coordination Function (DCF) control unit (DCU)
- * registers [5211+]
- *
- * These registers control the various characteristics of each queue
- * for 802.11e (WME) combatibility so they go together with
- * QCU registers in pairs. For each queue we have a QCU mask register,
- * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
- * a retry limit register (0x1080 - 0x10ac), a channel time register
- * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
- * a sequence number register (0x1140 - 0x116c). It seems that "global"
- * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
- * We use the same macros here for easier register access.
- *
- */
-
-/*
- * DCU QCU mask registers
- */
-#define AR5K_DCU_QCUMASK_BASE	0x1000		/* Register Address -Queue0 DCU_QCUMASK */
-#define AR5K_DCU_QCUMASK_M	0x000003ff
-#define AR5K_QUEUE_QCUMASK(_q)	AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q)
-
-/*
- * DCU local Inter Frame Space settings register
- */
-#define AR5K_DCU_LCL_IFS_BASE		0x1040			/* Register Address -Queue0 DCU_LCL_IFS */
-#define	AR5K_DCU_LCL_IFS_CW_MIN	        0x000003ff	/* Minimum Contention Window */
-#define	AR5K_DCU_LCL_IFS_CW_MIN_S	0
-#define	AR5K_DCU_LCL_IFS_CW_MAX	        0x000ffc00	/* Maximum Contention Window */
-#define	AR5K_DCU_LCL_IFS_CW_MAX_S	10
-#define	AR5K_DCU_LCL_IFS_AIFS		0x0ff00000	/* Arbitrated Interframe Space */
-#define	AR5K_DCU_LCL_IFS_AIFS_S		20
-#define	AR5K_DCU_LCL_IFS_AIFS_MAX	0xfc		/* Anything above that can cause DCU to hang */
-#define	AR5K_QUEUE_DFS_LOCAL_IFS(_q)	AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
-
-/*
- * DCU retry limit registers
- */
-#define AR5K_DCU_RETRY_LMT_BASE		0x1080			/* Register Address -Queue0 DCU_RETRY_LMT */
-#define AR5K_DCU_RETRY_LMT_SH_RETRY	0x0000000f	/* Short retry limit mask */
-#define AR5K_DCU_RETRY_LMT_SH_RETRY_S	0
-#define AR5K_DCU_RETRY_LMT_LG_RETRY	0x000000f0	/* Long retry limit mask */
-#define AR5K_DCU_RETRY_LMT_LG_RETRY_S	4
-#define AR5K_DCU_RETRY_LMT_SSH_RETRY	0x00003f00	/* Station short retry limit mask (?) */
-#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S	8
-#define AR5K_DCU_RETRY_LMT_SLG_RETRY	0x000fc000	/* Station long retry limit mask (?) */
-#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S	14
-#define	AR5K_QUEUE_DFS_RETRY_LIMIT(_q)	AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
-
-/*
- * DCU channel time registers
- */
-#define AR5K_DCU_CHAN_TIME_BASE		0x10c0			/* Register Address -Queue0 DCU_CHAN_TIME */
-#define	AR5K_DCU_CHAN_TIME_DUR		0x000fffff	/* Channel time duration */
-#define	AR5K_DCU_CHAN_TIME_DUR_S	0
-#define	AR5K_DCU_CHAN_TIME_ENABLE	0x00100000	/* Enable channel time */
-#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q)	AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q)
-
-/*
- * DCU misc registers [5211+]
- *
- * Note: Arbiter lockout control controls the
- * behaviour on low priority queues when we have multiple queues
- * with pending frames. Intra-frame lockout means we wait until
- * the queue's current frame transmits (with post frame backoff and bursting)
- * before we transmit anything else and global lockout means we
- * wait for the whole queue to finish before higher priority queues
- * can transmit (this is used on beacon and CAB queues).
- * No lockout means there is no special handling.
- */
-#define AR5K_DCU_MISC_BASE		0x1100			/* Register Address -Queue0 DCU_MISC */
-#define	AR5K_DCU_MISC_BACKOFF		0x0000003f	/* Mask for backoff threshold */
-#define	AR5K_DCU_MISC_ETS_RTS_POL	0x00000040	/* End of transmission series
-							station RTS/data failure count
-							reset policy (?) */
-#define AR5K_DCU_MISC_ETS_CW_POL	0x00000080	/* End of transmission series
-							CW reset policy */
-#define	AR5K_DCU_MISC_FRAG_WAIT		0x00000100	/* Wait for next fragment */
-#define AR5K_DCU_MISC_BACKOFF_FRAG	0x00000200	/* Enable backoff while bursting */
-#define	AR5K_DCU_MISC_HCFPOLL_ENABLE	0x00000800	/* CF - Poll enable */
-#define	AR5K_DCU_MISC_BACKOFF_PERSIST	0x00001000	/* Persistent backoff */
-#define	AR5K_DCU_MISC_FRMPRFTCH_ENABLE	0x00002000	/* Enable frame pre-fetch */
-#define	AR5K_DCU_MISC_VIRTCOL		0x0000c000	/* Mask for Virtual Collision (?) */
-#define	AR5K_DCU_MISC_VIRTCOL_NORMAL	0
-#define	AR5K_DCU_MISC_VIRTCOL_IGNORE	1
-#define	AR5K_DCU_MISC_BCN_ENABLE	0x00010000	/* Enable Beacon use */
-#define	AR5K_DCU_MISC_ARBLOCK_CTL	0x00060000	/* Arbiter lockout control mask */
-#define	AR5K_DCU_MISC_ARBLOCK_CTL_S	17
-#define	AR5K_DCU_MISC_ARBLOCK_CTL_NONE		0	/* No arbiter lockout */
-#define	AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM	1	/* Intra-frame lockout */
-#define	AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL	2	/* Global lockout */
-#define	AR5K_DCU_MISC_ARBLOCK_IGNORE	0x00080000	/* Ignore Arbiter lockout */
-#define	AR5K_DCU_MISC_SEQ_NUM_INCR_DIS	0x00100000	/* Disable sequence number increment */
-#define	AR5K_DCU_MISC_POST_FR_BKOFF_DIS	0x00200000	/* Disable post-frame backoff */
-#define	AR5K_DCU_MISC_VIRT_COLL_POLICY	0x00400000	/* Virtual Collision cw policy */
-#define	AR5K_DCU_MISC_BLOWN_IFS_POLICY	0x00800000	/* Blown IFS policy (?) */
-#define	AR5K_DCU_MISC_SEQNUM_CTL	0x01000000	/* Sequence number control (?) */
-#define AR5K_QUEUE_DFS_MISC(_q)		AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q)
-
-/*
- * DCU frame sequence number registers
- */
-#define AR5K_DCU_SEQNUM_BASE		0x1140
-#define	AR5K_DCU_SEQNUM_M		0x00000fff
-#define	AR5K_QUEUE_DCU_SEQNUM(_q)	AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
-
-/*
- * DCU global IFS SIFS register
- */
-#define AR5K_DCU_GBL_IFS_SIFS	0x1030
-#define AR5K_DCU_GBL_IFS_SIFS_M	0x0000ffff
-
-/*
- * DCU global IFS slot interval register
- */
-#define AR5K_DCU_GBL_IFS_SLOT	0x1070
-#define AR5K_DCU_GBL_IFS_SLOT_M	0x0000ffff
-
-/*
- * DCU global IFS EIFS register
- */
-#define AR5K_DCU_GBL_IFS_EIFS	0x10b0
-#define AR5K_DCU_GBL_IFS_EIFS_M	0x0000ffff
-
-/*
- * DCU global IFS misc register
- *
- * LFSR stands for Linear Feedback Shift Register
- * and it's used for generating pseudo-random
- * number sequences.
- *
- * (If i understand corectly, random numbers are
- * used for idle sensing -multiplied with cwmin/max etc-)
- */
-#define AR5K_DCU_GBL_IFS_MISC			0x10f0			/* Register Address */
-#define	AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE	0x00000007	/* LFSR Slice Select */
-#define	AR5K_DCU_GBL_IFS_MISC_TURBO_MODE	0x00000008	/* Turbo mode */
-#define	AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC	0x000003f0	/* SIFS Duration mask */
-#define	AR5K_DCU_GBL_IFS_MISC_USEC_DUR		0x000ffc00	/* USEC Duration mask */
-#define	AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S	10
-#define	AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY	0x00300000	/* DCU Arbiter delay mask */
-#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST	0x00400000	/* SIFS cnt reset policy (?) */
-#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST	0x00800000	/* AIFS cnt reset policy (?) */
-#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS	0x01000000	/* Disable random LFSR slice */
-
-/*
- * DCU frame prefetch control register
- */
-#define AR5K_DCU_FP			0x1230			/* Register Address */
-#define AR5K_DCU_FP_NOBURST_DCU_EN	0x00000001	/* Enable non-burst prefetch on DCU (?) */
-#define AR5K_DCU_FP_NOBURST_EN		0x00000010	/* Enable non-burst prefetch (?) */
-#define AR5K_DCU_FP_BURST_DCU_EN	0x00000020	/* Enable burst prefetch on DCU (?) */
-
-/*
- * DCU transmit pause control/status register
- */
-#define AR5K_DCU_TXP		0x1270			/* Register Address */
-#define	AR5K_DCU_TXP_M		0x000003ff	/* Tx pause mask */
-#define	AR5K_DCU_TXP_STATUS	0x00010000	/* Tx pause status */
-
-/*
- * DCU transmit filter table 0 (32 entries)
- * each entry contains a 32bit slice of the
- * 128bit tx filter for each DCU (4 slices per DCU)
- */
-#define AR5K_DCU_TX_FILTER_0_BASE	0x1038
-#define	AR5K_DCU_TX_FILTER_0(_n)	(AR5K_DCU_TX_FILTER_0_BASE + (_n * 64))
-
-/*
- * DCU transmit filter table 1 (16 entries)
- */
-#define AR5K_DCU_TX_FILTER_1_BASE	0x103c
-#define	AR5K_DCU_TX_FILTER_1(_n)	(AR5K_DCU_TX_FILTER_1_BASE + (_n * 64))
-
-/*
- * DCU clear transmit filter register
- */
-#define AR5K_DCU_TX_FILTER_CLR	0x143c
-
-/*
- * DCU set transmit filter register
- */
-#define AR5K_DCU_TX_FILTER_SET	0x147c
-
-/*
- * Reset control register
- */
-#define AR5K_RESET_CTL		0x4000			/* Register Address */
-#define AR5K_RESET_CTL_PCU	0x00000001	/* Protocol Control Unit reset */
-#define AR5K_RESET_CTL_DMA	0x00000002	/* DMA (Rx/Tx) reset [5210] */
-#define	AR5K_RESET_CTL_BASEBAND	0x00000002	/* Baseband reset [5211+] */
-#define AR5K_RESET_CTL_MAC	0x00000004	/* MAC reset (PCU+Baseband ?) [5210] */
-#define AR5K_RESET_CTL_PHY	0x00000008	/* PHY reset [5210] */
-#define AR5K_RESET_CTL_PCI	0x00000010	/* PCI Core reset (interrupts etc) */
-
-/*
- * Sleep control register
- */
-#define AR5K_SLEEP_CTL			0x4004			/* Register Address */
-#define AR5K_SLEEP_CTL_SLDUR		0x0000ffff	/* Sleep duration mask */
-#define AR5K_SLEEP_CTL_SLDUR_S		0
-#define AR5K_SLEEP_CTL_SLE		0x00030000	/* Sleep enable mask */
-#define AR5K_SLEEP_CTL_SLE_S		16
-#define AR5K_SLEEP_CTL_SLE_WAKE		0x00000000	/* Force chip awake */
-#define AR5K_SLEEP_CTL_SLE_SLP		0x00010000	/* Force chip sleep */
-#define AR5K_SLEEP_CTL_SLE_ALLOW	0x00020000	/* Normal sleep policy */
-#define AR5K_SLEEP_CTL_SLE_UNITS	0x00000008	/* [5211+] */
-#define AR5K_SLEEP_CTL_DUR_TIM_POL	0x00040000	/* Sleep duration timing policy */
-#define AR5K_SLEEP_CTL_DUR_WRITE_POL	0x00080000	/* Sleep duration write policy */
-#define AR5K_SLEEP_CTL_SLE_POL		0x00100000	/* Sleep policy mode */
-
-/*
- * Interrupt pending register
- */
-#define AR5K_INTPEND	0x4008
-#define AR5K_INTPEND_M	0x00000001
-
-/*
- * Sleep force register
- */
-#define AR5K_SFR	0x400c
-#define AR5K_SFR_EN	0x00000001
-
-/*
- * PCI configuration register
- * TODO: Fix LED stuff
- */
-#define AR5K_PCICFG			0x4010			/* Register Address */
-#define AR5K_PCICFG_EEAE		0x00000001	/* Eeprom access enable [5210] */
-#define AR5K_PCICFG_SLEEP_CLOCK_EN	0x00000002	/* Enable sleep clock */
-#define AR5K_PCICFG_CLKRUNEN		0x00000004	/* CLKRUN enable [5211+] */
-#define AR5K_PCICFG_EESIZE		0x00000018	/* Mask for EEPROM size [5211+] */
-#define AR5K_PCICFG_EESIZE_S		3
-#define AR5K_PCICFG_EESIZE_4K		0		/* 4K */
-#define AR5K_PCICFG_EESIZE_8K		1		/* 8K */
-#define AR5K_PCICFG_EESIZE_16K		2		/* 16K */
-#define AR5K_PCICFG_EESIZE_FAIL		3		/* Failed to get size [5211+] */
-#define AR5K_PCICFG_LED			0x00000060	/* Led status [5211+] */
-#define AR5K_PCICFG_LED_NONE		0x00000000	/* Default [5211+] */
-#define AR5K_PCICFG_LED_PEND		0x00000020	/* Scan / Auth pending */
-#define AR5K_PCICFG_LED_ASSOC		0x00000040	/* Associated */
-#define	AR5K_PCICFG_BUS_SEL		0x00000380	/* Mask for "bus select" [5211+] (?) */
-#define AR5K_PCICFG_CBEFIX_DIS		0x00000400	/* Disable CBE fix */
-#define AR5K_PCICFG_SL_INTEN		0x00000800	/* Enable interrupts when asleep */
-#define AR5K_PCICFG_LED_BCTL		0x00001000	/* Led blink (?) [5210] */
-#define AR5K_PCICFG_RETRY_FIX		0x00001000	/* Enable pci core retry fix */
-#define AR5K_PCICFG_SL_INPEN		0x00002000	/* Sleep even whith pending interrupts*/
-#define AR5K_PCICFG_SPWR_DN		0x00010000	/* Mask for power status */
-#define AR5K_PCICFG_LEDMODE		0x000e0000	/* Ledmode [5211+] */
-#define AR5K_PCICFG_LEDMODE_PROP	0x00000000	/* Blink on standard traffic [5211+] */
-#define AR5K_PCICFG_LEDMODE_PROM	0x00020000	/* Default mode (blink on any traffic) [5211+] */
-#define AR5K_PCICFG_LEDMODE_PWR		0x00040000	/* Some other blinking mode  (?) [5211+] */
-#define AR5K_PCICFG_LEDMODE_RAND	0x00060000	/* Random blinking (?) [5211+] */
-#define AR5K_PCICFG_LEDBLINK		0x00700000	/* Led blink rate */
-#define AR5K_PCICFG_LEDBLINK_S		20
-#define AR5K_PCICFG_LEDSLOW		0x00800000	/* Slowest led blink rate [5211+] */
-#define AR5K_PCICFG_LEDSTATE				\
-	(AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE |	\
-	AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
-#define	AR5K_PCICFG_SLEEP_CLOCK_RATE	0x03000000	/* Sleep clock rate */
-#define	AR5K_PCICFG_SLEEP_CLOCK_RATE_S	24
-
-/*
- * "General Purpose Input/Output" (GPIO) control register
- *
- * I'm not sure about this but after looking at the code
- * for all chipsets here is what i got.
- *
- * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits)
- * Mode 0 -> always input
- * Mode 1 -> output when GPIODO for this GPIO is set to 0
- * Mode 2 -> output when GPIODO for this GPIO is set to 1
- * Mode 3 -> always output
- *
- * For more infos check out get_gpio/set_gpio and
- * set_gpio_input/set_gpio_output functs.
- * For more infos on gpio interrupt check out set_gpio_intr.
- */
-#define AR5K_NUM_GPIO	6
-
-#define AR5K_GPIOCR		0x4014				/* Register Address */
-#define AR5K_GPIOCR_INT_ENA	0x00008000		/* Enable GPIO interrupt */
-#define AR5K_GPIOCR_INT_SELL	0x00000000		/* Generate interrupt when pin is low */
-#define AR5K_GPIOCR_INT_SELH	0x00010000		/* Generate interrupt when pin is high */
-#define AR5K_GPIOCR_IN(n)	(0 << ((n) * 2))	/* Mode 0 for pin n */
-#define AR5K_GPIOCR_OUT0(n)	(1 << ((n) * 2))	/* Mode 1 for pin n */
-#define AR5K_GPIOCR_OUT1(n)	(2 << ((n) * 2))	/* Mode 2 for pin n */
-#define AR5K_GPIOCR_OUT(n)	(3 << ((n) * 2))	/* Mode 3 for pin n */
-#define AR5K_GPIOCR_INT_SEL(n)	((n) << 12)		/* Interrupt for GPIO pin n */
-
-/*
- * "General Purpose Input/Output" (GPIO) data output register
- */
-#define AR5K_GPIODO	0x4018
-
-/*
- * "General Purpose Input/Output" (GPIO) data input register
- */
-#define AR5K_GPIODI	0x401c
-#define AR5K_GPIODI_M	0x0000002f
-
-/*
- * Silicon revision register
- */
-#define AR5K_SREV		0x4020			/* Register Address */
-#define AR5K_SREV_REV		0x0000000f	/* Mask for revision */
-#define AR5K_SREV_REV_S		0
-#define AR5K_SREV_VER		0x000000ff	/* Mask for version */
-#define AR5K_SREV_VER_S		4
-
-/*
- * TXE write posting register
- */
-#define	AR5K_TXEPOST	0x4028
-
-/*
- * QCU sleep mask
- */
-#define	AR5K_QCU_SLEEP_MASK	0x402c
-
-/* 0x4068 is compression buffer configuration
- * register on 5414 and pm configuration register
- * on 5424 and newer pci-e chips. */
-
-/*
- * Compression buffer configuration
- * register (enable/disable) [5414]
- */
-#define AR5K_5414_CBCFG		0x4068
-#define AR5K_5414_CBCFG_BUF_DIS	0x10	/* Disable buffer */
-
-/*
- * PCI-E Power managment configuration
- * and status register [5424+]
- */
-#define	AR5K_PCIE_PM_CTL		0x4068			/* Register address */
-/* Only 5424 */
-#define	AR5K_PCIE_PM_CTL_L1_WHEN_D2	0x00000001	/* enable PCIe core enter L1
-							when d2_sleep_en is asserted */
-#define	AR5K_PCIE_PM_CTL_L0_L0S_CLEAR	0x00000002	/* Clear L0 and L0S counters */
-#define	AR5K_PCIE_PM_CTL_L0_L0S_EN	0x00000004	/* Start L0 nd L0S counters */
-#define	AR5K_PCIE_PM_CTL_LDRESET_EN	0x00000008	/* Enable reset when link goes
-							down */
-/* Wake On Wireless */
-#define	AR5K_PCIE_PM_CTL_PME_EN		0x00000010	/* PME Enable */
-#define	AR5K_PCIE_PM_CTL_AUX_PWR_DET	0x00000020	/* Aux power detect */
-#define	AR5K_PCIE_PM_CTL_PME_CLEAR	0x00000040	/* Clear PME */
-#define	AR5K_PCIE_PM_CTL_PSM_D0		0x00000080
-#define	AR5K_PCIE_PM_CTL_PSM_D1		0x00000100
-#define	AR5K_PCIE_PM_CTL_PSM_D2		0x00000200
-#define	AR5K_PCIE_PM_CTL_PSM_D3		0x00000400
-
-/*
- * PCI-E Workaround enable register
- */
-#define	AR5K_PCIE_WAEN	0x407c
-
-/*
- * PCI-E Serializer/Desirializer
- * registers
- */
-#define	AR5K_PCIE_SERDES	0x4080
-#define	AR5K_PCIE_SERDES_RESET	0x4084
-
-/*====EEPROM REGISTERS====*/
-
-/*
- * EEPROM access registers
- *
- * Here we got a difference between 5210/5211-12
- * read data register for 5210 is at 0x6800 and
- * status register is at 0x6c00. There is also
- * no eeprom command register on 5210 and the
- * offsets are different.
- *
- * To read eeprom data for a specific offset:
- * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
- *        read AR5K_EEPROM_BASE +(4 * offset)
- *        check the eeprom status register
- *        and read eeprom data register.
- *
- * 5211 - write offset to AR5K_EEPROM_BASE
- * 5212   write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD
- *        check the eeprom status register
- *        and read eeprom data register.
- *
- * To write eeprom data for a specific offset:
- * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
- *        write data to AR5K_EEPROM_BASE +(4 * offset)
- *        check the eeprom status register
- * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD
- * 5212   write offset to AR5K_EEPROM_BASE
- *        write data to data register
- *	  write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD
- *        check the eeprom status register
- *
- * For more infos check eeprom_* functs and the ar5k.c
- * file posted in madwifi-devel mailing list.
- * http://sourceforge.net/mailarchive/message.php?msg_id=8966525
- *
- */
-#define AR5K_EEPROM_BASE	0x6000
-
-/*
- * EEPROM data register
- */
-#define AR5K_EEPROM_DATA_5211	0x6004
-#define AR5K_EEPROM_DATA_5210	0x6800
-#define	AR5K_EEPROM_DATA	(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
-
-/*
- * EEPROM command register
- */
-#define AR5K_EEPROM_CMD		0x6008			/* Register Addres */
-#define AR5K_EEPROM_CMD_READ	0x00000001	/* EEPROM read */
-#define AR5K_EEPROM_CMD_WRITE	0x00000002	/* EEPROM write */
-#define AR5K_EEPROM_CMD_RESET	0x00000004	/* EEPROM reset */
-
-/*
- * EEPROM status register
- */
-#define AR5K_EEPROM_STAT_5210	0x6c00			/* Register Address [5210] */
-#define AR5K_EEPROM_STAT_5211	0x600c			/* Register Address [5211+] */
-#define	AR5K_EEPROM_STATUS	(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
-#define AR5K_EEPROM_STAT_RDERR	0x00000001	/* EEPROM read failed */
-#define AR5K_EEPROM_STAT_RDDONE	0x00000002	/* EEPROM read successful */
-#define AR5K_EEPROM_STAT_WRERR	0x00000004	/* EEPROM write failed */
-#define AR5K_EEPROM_STAT_WRDONE	0x00000008	/* EEPROM write successful */
-
-/*
- * EEPROM config register
- */
-#define AR5K_EEPROM_CFG			0x6010			/* Register Addres */
-#define AR5K_EEPROM_CFG_SIZE		0x00000003		/* Size determination override */
-#define AR5K_EEPROM_CFG_SIZE_AUTO	0
-#define AR5K_EEPROM_CFG_SIZE_4KBIT	1
-#define AR5K_EEPROM_CFG_SIZE_8KBIT	2
-#define AR5K_EEPROM_CFG_SIZE_16KBIT	3
-#define AR5K_EEPROM_CFG_WR_WAIT_DIS	0x00000004	/* Disable write wait */
-#define AR5K_EEPROM_CFG_CLK_RATE	0x00000018	/* Clock rate */
-#define AR5K_EEPROM_CFG_CLK_RATE_S		3
-#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ	0
-#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ	1
-#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ	2
-#define AR5K_EEPROM_CFG_PROT_KEY	0x00ffff00      /* Protection key */
-#define AR5K_EEPROM_CFG_PROT_KEY_S	8
-#define AR5K_EEPROM_CFG_LIND_EN		0x01000000	/* Enable length indicator (?) */
-
-
-/*
- * TODO: Wake On Wireless registers
- * Range 0x7000 - 0x7ce0
- */
-
-/*
- * Protocol Control Unit (PCU) registers
- */
-/*
- * Used for checking initial register writes
- * during channel reset (see reset func)
- */
-#define AR5K_PCU_MIN	0x8000
-#define AR5K_PCU_MAX	0x8fff
-
-/*
- * First station id register (Lower 32 bits of MAC address)
- */
-#define AR5K_STA_ID0		0x8000
-#define	AR5K_STA_ID0_ARRD_L32	0xffffffff
-
-/*
- * Second station id register (Upper 16 bits of MAC address + PCU settings)
- */
-#define AR5K_STA_ID1			0x8004			/* Register Address */
-#define	AR5K_STA_ID1_ADDR_U16		0x0000ffff	/* Upper 16 bits of MAC addres */
-#define AR5K_STA_ID1_AP			0x00010000	/* Set AP mode */
-#define AR5K_STA_ID1_ADHOC		0x00020000	/* Set Ad-Hoc mode */
-#define AR5K_STA_ID1_PWR_SV		0x00040000	/* Power save reporting */
-#define AR5K_STA_ID1_NO_KEYSRCH		0x00080000	/* No key search */
-#define AR5K_STA_ID1_NO_PSPOLL		0x00100000	/* No power save polling [5210] */
-#define AR5K_STA_ID1_PCF_5211		0x00100000	/* Enable PCF on [5211+] */
-#define AR5K_STA_ID1_PCF_5210		0x00200000	/* Enable PCF on [5210]*/
-#define	AR5K_STA_ID1_PCF		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211)
-#define AR5K_STA_ID1_DEFAULT_ANTENNA	0x00200000	/* Use default antenna */
-#define AR5K_STA_ID1_DESC_ANTENNA	0x00400000	/* Update antenna from descriptor */
-#define AR5K_STA_ID1_RTS_DEF_ANTENNA	0x00800000	/* Use default antenna for RTS */
-#define AR5K_STA_ID1_ACKCTS_6MB		0x01000000	/* Use 6Mbit/s for ACK/CTS */
-#define AR5K_STA_ID1_BASE_RATE_11B	0x02000000	/* Use 11b base rate for ACK/CTS [5211+] */
-#define AR5K_STA_ID1_SELFGEN_DEF_ANT	0x04000000	/* Use def. antenna for self generated frames */
-#define AR5K_STA_ID1_CRYPT_MIC_EN	0x08000000	/* Enable MIC */
-#define AR5K_STA_ID1_KEYSRCH_MODE	0x10000000	/* Look up key when key id != 0 */
-#define AR5K_STA_ID1_PRESERVE_SEQ_NUM	0x20000000	/* Preserve sequence number */
-#define AR5K_STA_ID1_CBCIV_ENDIAN	0x40000000	/* ??? */
-#define AR5K_STA_ID1_KEYSRCH_MCAST	0x80000000	/* Do key cache search for mcast frames */
-
-/*
- * First BSSID register (MAC address, lower 32bits)
- */
-#define AR5K_BSS_ID0	0x8008
-
-/*
- * Second BSSID register (MAC address in upper 16 bits)
- *
- * AID: Association ID
- */
-#define AR5K_BSS_ID1		0x800c
-#define AR5K_BSS_ID1_AID	0xffff0000
-#define AR5K_BSS_ID1_AID_S	16
-
-/*
- * Backoff slot time register
- */
-#define AR5K_SLOT_TIME	0x8010
-
-/*
- * ACK/CTS timeout register
- */
-#define AR5K_TIME_OUT		0x8014			/* Register Address */
-#define AR5K_TIME_OUT_ACK	0x00001fff	/* ACK timeout mask */
-#define AR5K_TIME_OUT_ACK_S	0
-#define AR5K_TIME_OUT_CTS	0x1fff0000	/* CTS timeout mask */
-#define AR5K_TIME_OUT_CTS_S	16
-
-/*
- * RSSI threshold register
- */
-#define AR5K_RSSI_THR			0x8018		/* Register Address */
-#define AR5K_RSSI_THR_M			0x000000ff	/* Mask for RSSI threshold [5211+] */
-#define AR5K_RSSI_THR_BMISS_5210	0x00000700	/* Mask for Beacon Missed threshold [5210] */
-#define AR5K_RSSI_THR_BMISS_5210_S	8
-#define AR5K_RSSI_THR_BMISS_5211	0x0000ff00	/* Mask for Beacon Missed threshold [5211+] */
-#define AR5K_RSSI_THR_BMISS_5211_S	8
-#define	AR5K_RSSI_THR_BMISS		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211)
-#define	AR5K_RSSI_THR_BMISS_S		8
-
-/*
- * 5210 has more PCU registers because there is no QCU/DCU
- * so queue parameters are set here, this way a lot common
- * registers have different address for 5210. To make things
- * easier we define a macro based on ah->ah_version for common
- * registers with different addresses and common flags.
- */
-
-/*
- * Retry limit register
- *
- * Retry limit register for 5210 (no QCU/DCU so it's done in PCU)
- */
-#define AR5K_NODCU_RETRY_LMT		0x801c			/* Register Address */
-#define AR5K_NODCU_RETRY_LMT_SH_RETRY	0x0000000f	/* Short retry limit mask */
-#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S	0
-#define AR5K_NODCU_RETRY_LMT_LG_RETRY	0x000000f0	/* Long retry mask */
-#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S	4
-#define AR5K_NODCU_RETRY_LMT_SSH_RETRY	0x00003f00	/* Station short retry limit mask */
-#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S	8
-#define AR5K_NODCU_RETRY_LMT_SLG_RETRY	0x000fc000	/* Station long retry limit mask */
-#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S	14
-#define AR5K_NODCU_RETRY_LMT_CW_MIN	0x3ff00000	/* Minimum contention window mask */
-#define AR5K_NODCU_RETRY_LMT_CW_MIN_S	20
-
-/*
- * Transmit latency register
- */
-#define AR5K_USEC_5210			0x8020			/* Register Address [5210] */
-#define AR5K_USEC_5211			0x801c			/* Register Address [5211+] */
-#define AR5K_USEC			(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_USEC_5210 : AR5K_USEC_5211)
-#define AR5K_USEC_1			0x0000007f	/* clock cycles for 1us */
-#define AR5K_USEC_1_S			0
-#define AR5K_USEC_32			0x00003f80	/* clock cycles for 1us while on 32Mhz clock */
-#define AR5K_USEC_32_S			7
-#define AR5K_USEC_TX_LATENCY_5211	0x007fc000
-#define AR5K_USEC_TX_LATENCY_5211_S	14
-#define AR5K_USEC_RX_LATENCY_5211	0x1f800000
-#define AR5K_USEC_RX_LATENCY_5211_S	23
-#define AR5K_USEC_TX_LATENCY_5210	0x000fc000	/* also for 5311 */
-#define AR5K_USEC_TX_LATENCY_5210_S	14
-#define AR5K_USEC_RX_LATENCY_5210	0x03f00000	/* also for 5311 */
-#define AR5K_USEC_RX_LATENCY_5210_S	20
-
-/*
- * PCU beacon control register
- */
-#define AR5K_BEACON_5210	0x8024			/*Register Address [5210] */
-#define AR5K_BEACON_5211	0x8020			/*Register Address [5211+] */
-#define AR5K_BEACON		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_BEACON_5210 : AR5K_BEACON_5211)
-#define AR5K_BEACON_PERIOD	0x0000ffff	/* Mask for beacon period */
-#define AR5K_BEACON_PERIOD_S	0
-#define AR5K_BEACON_TIM		0x007f0000	/* Mask for TIM offset */
-#define AR5K_BEACON_TIM_S	16
-#define AR5K_BEACON_ENABLE	0x00800000	/* Enable beacons */
-#define AR5K_BEACON_RESET_TSF	0x01000000	/* Force TSF reset */
-
-/*
- * CFP period register
- */
-#define AR5K_CFP_PERIOD_5210	0x8028
-#define AR5K_CFP_PERIOD_5211	0x8024
-#define AR5K_CFP_PERIOD		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211)
-
-/*
- * Next beacon time register
- */
-#define AR5K_TIMER0_5210	0x802c
-#define AR5K_TIMER0_5211	0x8028
-#define AR5K_TIMER0		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
-
-/*
- * Next DMA beacon alert register
- */
-#define AR5K_TIMER1_5210	0x8030
-#define AR5K_TIMER1_5211	0x802c
-#define AR5K_TIMER1		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
-
-/*
- * Next software beacon alert register
- */
-#define AR5K_TIMER2_5210	0x8034
-#define AR5K_TIMER2_5211	0x8030
-#define AR5K_TIMER2		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
-
-/*
- * Next ATIM window time register
- */
-#define AR5K_TIMER3_5210	0x8038
-#define AR5K_TIMER3_5211	0x8034
-#define AR5K_TIMER3		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
-
-
-/*
- * 5210 First inter frame spacing register (IFS)
- */
-#define AR5K_IFS0		0x8040
-#define AR5K_IFS0_SIFS		0x000007ff
-#define AR5K_IFS0_SIFS_S	0
-#define AR5K_IFS0_DIFS		0x007ff800
-#define AR5K_IFS0_DIFS_S	11
-
-/*
- * 5210 Second inter frame spacing register (IFS)
- */
-#define AR5K_IFS1		0x8044
-#define AR5K_IFS1_PIFS		0x00000fff
-#define AR5K_IFS1_PIFS_S	0
-#define AR5K_IFS1_EIFS		0x03fff000
-#define AR5K_IFS1_EIFS_S	12
-#define AR5K_IFS1_CS_EN		0x04000000
-
-
-/*
- * CFP duration register
- */
-#define AR5K_CFP_DUR_5210	0x8048
-#define AR5K_CFP_DUR_5211	0x8038
-#define AR5K_CFP_DUR		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211)
-
-/*
- * Receive filter register
- */
-#define AR5K_RX_FILTER_5210	0x804c			/* Register Address [5210] */
-#define AR5K_RX_FILTER_5211	0x803c			/* Register Address [5211+] */
-#define AR5K_RX_FILTER		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
-#define	AR5K_RX_FILTER_UCAST 	0x00000001	/* Don't filter unicast frames */
-#define	AR5K_RX_FILTER_MCAST 	0x00000002	/* Don't filter multicast frames */
-#define	AR5K_RX_FILTER_BCAST 	0x00000004	/* Don't filter broadcast frames */
-#define	AR5K_RX_FILTER_CONTROL 	0x00000008	/* Don't filter control frames */
-#define	AR5K_RX_FILTER_BEACON 	0x00000010	/* Don't filter beacon frames */
-#define	AR5K_RX_FILTER_PROM 	0x00000020	/* Set promiscuous mode */
-#define	AR5K_RX_FILTER_XRPOLL 	0x00000040	/* Don't filter XR poll frame [5212+] */
-#define	AR5K_RX_FILTER_PROBEREQ 0x00000080	/* Don't filter probe requests [5212+] */
-#define	AR5K_RX_FILTER_PHYERR_5212	0x00000100	/* Don't filter phy errors [5212+] */
-#define	AR5K_RX_FILTER_RADARERR_5212 	0x00000200	/* Don't filter phy radar errors [5212+] */
-#define AR5K_RX_FILTER_PHYERR_5211	0x00000040	/* [5211] */
-#define AR5K_RX_FILTER_RADARERR_5211	0x00000080	/* [5211] */
-#define AR5K_RX_FILTER_PHYERR  \
-	((ah->ah_version == AR5K_AR5211 ? \
-	AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212))
-#define        AR5K_RX_FILTER_RADARERR \
-	((ah->ah_version == AR5K_AR5211 ? \
-	AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212))
-
-/*
- * Multicast filter register (lower 32 bits)
- */
-#define AR5K_MCAST_FILTER0_5210	0x8050
-#define AR5K_MCAST_FILTER0_5211	0x8040
-#define AR5K_MCAST_FILTER0	(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211)
-
-/*
- * Multicast filter register (higher 16 bits)
- */
-#define AR5K_MCAST_FILTER1_5210	0x8054
-#define AR5K_MCAST_FILTER1_5211	0x8044
-#define AR5K_MCAST_FILTER1	(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211)
-
-
-/*
- * Transmit mask register (lower 32 bits) [5210]
- */
-#define AR5K_TX_MASK0	0x8058
-
-/*
- * Transmit mask register (higher 16 bits) [5210]
- */
-#define AR5K_TX_MASK1	0x805c
-
-/*
- * Clear transmit mask [5210]
- */
-#define AR5K_CLR_TMASK	0x8060
-
-/*
- * Trigger level register (before transmission) [5210]
- */
-#define AR5K_TRIG_LVL	0x8064
-
-
-/*
- * PCU control register
- *
- * Only DIS_RX is used in the code, the rest i guess are
- * for tweaking/diagnostics.
- */
-#define AR5K_DIAG_SW_5210		0x8068			/* Register Address [5210] */
-#define AR5K_DIAG_SW_5211		0x8048			/* Register Address [5211+] */
-#define AR5K_DIAG_SW			(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211)
-#define AR5K_DIAG_SW_DIS_WEP_ACK	0x00000001	/* Disable ACKs if WEP key is invalid */
-#define AR5K_DIAG_SW_DIS_ACK		0x00000002	/* Disable ACKs */
-#define AR5K_DIAG_SW_DIS_CTS		0x00000004	/* Disable CTSs */
-#define AR5K_DIAG_SW_DIS_ENC		0x00000008	/* Disable encryption */
-#define AR5K_DIAG_SW_DIS_DEC		0x00000010	/* Disable decryption */
-#define AR5K_DIAG_SW_DIS_TX		0x00000020	/* Disable transmit [5210] */
-#define AR5K_DIAG_SW_DIS_RX_5210	0x00000040	/* Disable recieve */
-#define AR5K_DIAG_SW_DIS_RX_5211	0x00000020
-#define	AR5K_DIAG_SW_DIS_RX		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
-#define AR5K_DIAG_SW_LOOP_BACK_5210	0x00000080	/* Loopback (i guess it goes with DIS_TX) [5210] */
-#define AR5K_DIAG_SW_LOOP_BACK_5211	0x00000040
-#define AR5K_DIAG_SW_LOOP_BACK		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
-#define AR5K_DIAG_SW_CORR_FCS_5210	0x00000100	/* Corrupted FCS */
-#define AR5K_DIAG_SW_CORR_FCS_5211	0x00000080
-#define AR5K_DIAG_SW_CORR_FCS		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
-#define AR5K_DIAG_SW_CHAN_INFO_5210	0x00000200	/* Dump channel info */
-#define AR5K_DIAG_SW_CHAN_INFO_5211	0x00000100
-#define AR5K_DIAG_SW_CHAN_INFO		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
-#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210	0x00000400	/* Enable fixed scrambler seed */
-#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211	0x00000200
-#define AR5K_DIAG_SW_EN_SCRAM_SEED	(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
-#define AR5K_DIAG_SW_ECO_ENABLE		0x00000400	/* [5211+] */
-#define AR5K_DIAG_SW_SCVRAM_SEED	0x0003f800	/* [5210] */
-#define AR5K_DIAG_SW_SCRAM_SEED_M	0x0001fc00	/* Scrambler seed mask */
-#define AR5K_DIAG_SW_SCRAM_SEED_S	10
-#define AR5K_DIAG_SW_DIS_SEQ_INC	0x00040000	/* Disable seqnum increment (?)[5210] */
-#define AR5K_DIAG_SW_FRAME_NV0_5210	0x00080000
-#define AR5K_DIAG_SW_FRAME_NV0_5211	0x00020000	/* Accept frames of non-zero protocol number */
-#define	AR5K_DIAG_SW_FRAME_NV0		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
-#define AR5K_DIAG_SW_OBSPT_M		0x000c0000	/* Observation point select (?) */
-#define AR5K_DIAG_SW_OBSPT_S		18
-#define AR5K_DIAG_SW_RX_CLEAR_HIGH	0x0010000	/* Force RX Clear high */
-#define AR5K_DIAG_SW_IGNORE_CARR_SENSE	0x0020000	/* Ignore virtual carrier sense */
-#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH	0x0040000	/* Force channel idle high */
-#define AR5K_DIAG_SW_PHEAR_ME		0x0080000	/* ??? */
-
-/*
- * TSF (clock) register (lower 32 bits)
- */
-#define AR5K_TSF_L32_5210	0x806c
-#define AR5K_TSF_L32_5211	0x804c
-#define	AR5K_TSF_L32		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
-
-/*
- * TSF (clock) register (higher 32 bits)
- */
-#define AR5K_TSF_U32_5210	0x8070
-#define AR5K_TSF_U32_5211	0x8050
-#define	AR5K_TSF_U32		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
-
-/*
- * Last beacon timestamp register (Read Only)
- */
-#define AR5K_LAST_TSTP	0x8080
-
-/*
- * ADDAC test register [5211+]
- */
-#define AR5K_ADDAC_TEST			0x8054			/* Register Address */
-#define AR5K_ADDAC_TEST_TXCONT 		0x00000001	/* Test continuous tx */
-#define AR5K_ADDAC_TEST_TST_MODE	0x00000002	/* Test mode */
-#define AR5K_ADDAC_TEST_LOOP_EN		0x00000004	/* Enable loop */
-#define AR5K_ADDAC_TEST_LOOP_LEN	0x00000008	/* Loop length (field) */
-#define AR5K_ADDAC_TEST_USE_U8		0x00004000	/* Use upper 8 bits */
-#define AR5K_ADDAC_TEST_MSB		0x00008000	/* State of MSB */
-#define AR5K_ADDAC_TEST_TRIG_SEL	0x00010000	/* Trigger select */
-#define AR5K_ADDAC_TEST_TRIG_PTY	0x00020000	/* Trigger polarity */
-#define AR5K_ADDAC_TEST_RXCONT		0x00040000	/* Continuous capture */
-#define AR5K_ADDAC_TEST_CAPTURE		0x00080000	/* Begin capture */
-#define AR5K_ADDAC_TEST_TST_ARM		0x00100000	/* ARM rx buffer for capture */
-
-/*
- * Default antenna register [5211+]
- */
-#define AR5K_DEFAULT_ANTENNA	0x8058
-
-/*
- * Frame control QoS mask register (?) [5211+]
- * (FC_QOS_MASK)
- */
-#define AR5K_FRAME_CTL_QOSM	0x805c
-
-/*
- * Seq mask register (?) [5211+]
- */
-#define AR5K_SEQ_MASK	0x8060
-
-/*
- * Retry count register [5210]
- */
-#define AR5K_RETRY_CNT		0x8084			/* Register Address [5210] */
-#define AR5K_RETRY_CNT_SSH	0x0000003f	/* Station short retry count (?) */
-#define AR5K_RETRY_CNT_SLG	0x00000fc0	/* Station long retry count (?) */
-
-/*
- * Back-off status register [5210]
- */
-#define AR5K_BACKOFF		0x8088			/* Register Address [5210] */
-#define AR5K_BACKOFF_CW		0x000003ff	/* Backoff Contention Window (?) */
-#define AR5K_BACKOFF_CNT	0x03ff0000	/* Backoff count (?) */
-
-
-
-/*
- * NAV register (current)
- */
-#define AR5K_NAV_5210		0x808c
-#define AR5K_NAV_5211		0x8084
-#define	AR5K_NAV		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_NAV_5210 : AR5K_NAV_5211)
-
-/*
- * RTS success register
- */
-#define AR5K_RTS_OK_5210	0x8090
-#define AR5K_RTS_OK_5211	0x8088
-#define	AR5K_RTS_OK		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
-
-/*
- * RTS failure register
- */
-#define AR5K_RTS_FAIL_5210	0x8094
-#define AR5K_RTS_FAIL_5211	0x808c
-#define	AR5K_RTS_FAIL		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
-
-/*
- * ACK failure register
- */
-#define AR5K_ACK_FAIL_5210	0x8098
-#define AR5K_ACK_FAIL_5211	0x8090
-#define	AR5K_ACK_FAIL		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
-
-/*
- * FCS failure register
- */
-#define AR5K_FCS_FAIL_5210	0x809c
-#define AR5K_FCS_FAIL_5211	0x8094
-#define	AR5K_FCS_FAIL		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211)
-
-/*
- * Beacon count register
- */
-#define AR5K_BEACON_CNT_5210	0x80a0
-#define AR5K_BEACON_CNT_5211	0x8098
-#define	AR5K_BEACON_CNT		(ah->ah_version == AR5K_AR5210 ? \
-				AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211)
-
-
-/*===5212 Specific PCU registers===*/
-
-/*
- * Transmit power control register
- */
-#define AR5K_TPC			0x80e8
-#define AR5K_TPC_ACK			0x0000003f	/* ack frames */
-#define AR5K_TPC_ACK_S			0
-#define AR5K_TPC_CTS			0x00003f00	/* cts frames */
-#define AR5K_TPC_CTS_S			8
-#define AR5K_TPC_CHIRP			0x003f0000	/* chirp frames */
-#define AR5K_TPC_CHIRP_S		16
-#define AR5K_TPC_DOPPLER		0x0f000000	/* doppler chirp span */
-#define AR5K_TPC_DOPPLER_S		24
-
-/*
- * XR (eXtended Range) mode register
- */
-#define AR5K_XRMODE			0x80c0			/* Register Address */
-#define	AR5K_XRMODE_POLL_TYPE_M		0x0000003f	/* Mask for Poll type (?) */
-#define	AR5K_XRMODE_POLL_TYPE_S		0
-#define	AR5K_XRMODE_POLL_SUBTYPE_M	0x0000003c	/* Mask for Poll subtype (?) */
-#define	AR5K_XRMODE_POLL_SUBTYPE_S	2
-#define	AR5K_XRMODE_POLL_WAIT_ALL	0x00000080	/* Wait for poll */
-#define	AR5K_XRMODE_SIFS_DELAY		0x000fff00	/* Mask for SIFS delay */
-#define	AR5K_XRMODE_FRAME_HOLD_M	0xfff00000	/* Mask for frame hold (?) */
-#define	AR5K_XRMODE_FRAME_HOLD_S	20
-
-/*
- * XR delay register
- */
-#define AR5K_XRDELAY			0x80c4			/* Register Address */
-#define AR5K_XRDELAY_SLOT_DELAY_M	0x0000ffff	/* Mask for slot delay */
-#define AR5K_XRDELAY_SLOT_DELAY_S	0
-#define AR5K_XRDELAY_CHIRP_DELAY_M	0xffff0000	/* Mask for CHIRP data delay */
-#define AR5K_XRDELAY_CHIRP_DELAY_S	16
-
-/*
- * XR timeout register
- */
-#define AR5K_XRTIMEOUT			0x80c8			/* Register Address */
-#define AR5K_XRTIMEOUT_CHIRP_M		0x0000ffff	/* Mask for CHIRP timeout */
-#define AR5K_XRTIMEOUT_CHIRP_S		0
-#define AR5K_XRTIMEOUT_POLL_M		0xffff0000	/* Mask for Poll timeout */
-#define AR5K_XRTIMEOUT_POLL_S		16
-
-/*
- * XR chirp register
- */
-#define AR5K_XRCHIRP			0x80cc			/* Register Address */
-#define AR5K_XRCHIRP_SEND		0x00000001	/* Send CHIRP */
-#define AR5K_XRCHIRP_GAP		0xffff0000	/* Mask for CHIRP gap (?) */
-
-/*
- * XR stomp register
- */
-#define AR5K_XRSTOMP			0x80d0			/* Register Address */
-#define AR5K_XRSTOMP_TX			0x00000001	/* Stomp Tx (?) */
-#define AR5K_XRSTOMP_RX			0x00000002	/* Stomp Rx (?) */
-#define AR5K_XRSTOMP_TX_RSSI		0x00000004	/* Stomp Tx RSSI (?) */
-#define AR5K_XRSTOMP_TX_BSSID		0x00000008	/* Stomp Tx BSSID (?) */
-#define AR5K_XRSTOMP_DATA		0x00000010	/* Stomp data (?)*/
-#define AR5K_XRSTOMP_RSSI_THRES		0x0000ff00	/* Mask for XR RSSI threshold */
-
-/*
- * First enhanced sleep register
- */
-#define AR5K_SLEEP0			0x80d4			/* Register Address */
-#define AR5K_SLEEP0_NEXT_DTIM		0x0007ffff	/* Mask for next DTIM (?) */
-#define AR5K_SLEEP0_NEXT_DTIM_S		0
-#define AR5K_SLEEP0_ASSUME_DTIM		0x00080000	/* Assume DTIM */
-#define AR5K_SLEEP0_ENH_SLEEP_EN	0x00100000	/* Enable enchanced sleep control */
-#define AR5K_SLEEP0_CABTO		0xff000000	/* Mask for CAB Time Out */
-#define AR5K_SLEEP0_CABTO_S		24
-
-/*
- * Second enhanced sleep register
- */
-#define AR5K_SLEEP1			0x80d8			/* Register Address */
-#define AR5K_SLEEP1_NEXT_TIM		0x0007ffff	/* Mask for next TIM (?) */
-#define AR5K_SLEEP1_NEXT_TIM_S		0
-#define AR5K_SLEEP1_BEACON_TO		0xff000000	/* Mask for Beacon Time Out */
-#define AR5K_SLEEP1_BEACON_TO_S		24
-
-/*
- * Third enhanced sleep register
- */
-#define AR5K_SLEEP2			0x80dc			/* Register Address */
-#define AR5K_SLEEP2_TIM_PER		0x0000ffff	/* Mask for TIM period (?) */
-#define AR5K_SLEEP2_TIM_PER_S		0
-#define AR5K_SLEEP2_DTIM_PER		0xffff0000	/* Mask for DTIM period (?) */
-#define AR5K_SLEEP2_DTIM_PER_S		16
-
-/*
- * BSSID mask registers
- */
-#define AR5K_BSS_IDM0			0x80e0	/* Upper bits */
-#define AR5K_BSS_IDM1			0x80e4	/* Lower bits */
-
-/*
- * TX power control (TPC) register
- *
- * XXX: PCDAC steps (0.5dbm) or DBM ?
- *
- */
-#define AR5K_TXPC			0x80e8			/* Register Address */
-#define AR5K_TXPC_ACK_M			0x0000003f	/* ACK tx power */
-#define AR5K_TXPC_ACK_S			0
-#define AR5K_TXPC_CTS_M			0x00003f00	/* CTS tx power */
-#define AR5K_TXPC_CTS_S			8
-#define AR5K_TXPC_CHIRP_M		0x003f0000	/* CHIRP tx power */
-#define AR5K_TXPC_CHIRP_S		16
-#define AR5K_TXPC_DOPPLER		0x0f000000	/* Doppler chirp span (?) */
-#define AR5K_TXPC_DOPPLER_S		24
-
-/*
- * Profile count registers
- */
-#define AR5K_PROFCNT_TX			0x80ec	/* Tx count */
-#define AR5K_PROFCNT_RX			0x80f0	/* Rx count */
-#define AR5K_PROFCNT_RXCLR		0x80f4	/* Clear Rx count */
-#define AR5K_PROFCNT_CYCLE		0x80f8	/* Cycle count (?) */
-
-/*
- * Quiet period control registers
- */
-#define AR5K_QUIET_CTL1			0x80fc			/* Register Address */
-#define AR5K_QUIET_CTL1_NEXT_QT_TSF	0x0000ffff	/* Next quiet period TSF (TU) */
-#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S	0
-#define AR5K_QUIET_CTL1_QT_EN		0x00010000	/* Enable quiet period */
-#define AR5K_QUIET_CTL1_ACK_CTS_EN	0x00020000	/* Send ACK/CTS during quiet period */
-
-#define AR5K_QUIET_CTL2			0x8100			/* Register Address */
-#define AR5K_QUIET_CTL2_QT_PER		0x0000ffff	/* Mask for quiet period periodicity */
-#define AR5K_QUIET_CTL2_QT_PER_S	0
-#define AR5K_QUIET_CTL2_QT_DUR		0xffff0000	/* Mask for quiet period duration */
-#define AR5K_QUIET_CTL2_QT_DUR_S	16
-
-/*
- * TSF parameter register
- */
-#define AR5K_TSF_PARM			0x8104			/* Register Address */
-#define AR5K_TSF_PARM_INC		0x000000ff	/* Mask for TSF increment */
-#define AR5K_TSF_PARM_INC_S		0
-
-/*
- * QoS NOACK policy
- */
-#define AR5K_QOS_NOACK			0x8108			/* Register Address */
-#define AR5K_QOS_NOACK_2BIT_VALUES	0x0000000f	/* ??? */
-#define AR5K_QOS_NOACK_2BIT_VALUES_S	0
-#define AR5K_QOS_NOACK_BIT_OFFSET	0x00000070	/* ??? */
-#define AR5K_QOS_NOACK_BIT_OFFSET_S	4
-#define AR5K_QOS_NOACK_BYTE_OFFSET	0x00000180	/* ??? */
-#define AR5K_QOS_NOACK_BYTE_OFFSET_S	7
-
-/*
- * PHY error filter register
- */
-#define AR5K_PHY_ERR_FIL		0x810c
-#define AR5K_PHY_ERR_FIL_RADAR		0x00000020	/* Radar signal */
-#define AR5K_PHY_ERR_FIL_OFDM		0x00020000	/* OFDM false detect (ANI) */
-#define AR5K_PHY_ERR_FIL_CCK		0x02000000	/* CCK false detect (ANI) */
-
-/*
- * XR latency register
- */
-#define AR5K_XRLAT_TX		0x8110
-
-/*
- * ACK SIFS register
- */
-#define AR5K_ACKSIFS		0x8114			/* Register Address */
-#define AR5K_ACKSIFS_INC	0x00000000	/* ACK SIFS Increment (field) */
-
-/*
- * MIC QoS control register (?)
- */
-#define	AR5K_MIC_QOS_CTL		0x8118			/* Register Address */
-#define	AR5K_MIC_QOS_CTL_OFF(_n)	(1 << (_n * 2))
-#define	AR5K_MIC_QOS_CTL_MQ_EN		0x00010000	/* Enable MIC QoS */
-
-/*
- * MIC QoS select register (?)
- */
-#define	AR5K_MIC_QOS_SEL		0x811c
-#define	AR5K_MIC_QOS_SEL_OFF(_n)	(1 << (_n * 4))
-
-/*
- * Misc mode control register (?)
- */
-#define	AR5K_MISC_MODE			0x8120			/* Register Address */
-#define	AR5K_MISC_MODE_FBSSID_MATCH	0x00000001	/* Force BSSID match */
-#define	AR5K_MISC_MODE_ACKSIFS_MEM	0x00000002	/* ACK SIFS memory (?) */
-#define	AR5K_MISC_MODE_COMBINED_MIC	0x00000004	/* use rx/tx MIC key */
-/* more bits */
-
-/*
- * OFDM Filter counter
- */
-#define	AR5K_OFDM_FIL_CNT		0x8124
-
-/*
- * CCK Filter counter
- */
-#define	AR5K_CCK_FIL_CNT		0x8128
-
-/*
- * PHY Error Counters (?)
- */
-#define	AR5K_PHYERR_CNT1		0x812c
-#define	AR5K_PHYERR_CNT1_MASK		0x8130
-
-#define	AR5K_PHYERR_CNT2		0x8134
-#define	AR5K_PHYERR_CNT2_MASK		0x8138
-
-/*
- * TSF Threshold register (?)
- */
-#define	AR5K_TSF_THRES			0x813c
-
-/*
- * TODO: Wake On Wireless registers
- * Range: 0x8147 - 0x818c
- */
-
-/*
- * Rate -> ACK SIFS mapping table (32 entries)
- */
-#define	AR5K_RATE_ACKSIFS_BASE		0x8680			/* Register Address */
-#define	AR5K_RATE_ACKSIFS(_n)		(AR5K_RATE_ACKSIFS_BSE + ((_n) << 2))
-#define	AR5K_RATE_ACKSIFS_NORMAL	0x00000001	/* Normal SIFS (field) */
-#define	AR5K_RATE_ACKSIFS_TURBO		0x00000400	/* Turbo SIFS (field) */
-
-/*
- * Rate -> duration mapping table (32 entries)
- */
-#define AR5K_RATE_DUR_BASE		0x8700
-#define AR5K_RATE_DUR(_n)		(AR5K_RATE_DUR_BASE + ((_n) << 2))
-
-/*
- * Rate -> db mapping table
- * (8 entries, each one has 4 8bit fields)
- */
-#define AR5K_RATE2DB_BASE		0x87c0
-#define AR5K_RATE2DB(_n)		(AR5K_RATE2DB_BASE + ((_n) << 2))
-
-/*
- * db -> Rate mapping table
- * (8 entries, each one has 4 8bit fields)
- */
-#define AR5K_DB2RATE_BASE		0x87e0
-#define AR5K_DB2RATE(_n)		(AR5K_DB2RATE_BASE + ((_n) << 2))
-
-/*===5212 end===*/
-
-/*
- * Key table (WEP) register
- */
-#define AR5K_KEYTABLE_0_5210		0x9000
-#define AR5K_KEYTABLE_0_5211		0x8800
-#define AR5K_KEYTABLE_5210(_n)		(AR5K_KEYTABLE_0_5210 + ((_n) << 5))
-#define AR5K_KEYTABLE_5211(_n)		(AR5K_KEYTABLE_0_5211 + ((_n) << 5))
-#define	AR5K_KEYTABLE(_n)		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
-#define AR5K_KEYTABLE_OFF(_n, x)	(AR5K_KEYTABLE(_n) + (x << 2))
-#define AR5K_KEYTABLE_TYPE(_n)		AR5K_KEYTABLE_OFF(_n, 5)
-#define AR5K_KEYTABLE_TYPE_40		0x00000000
-#define AR5K_KEYTABLE_TYPE_104		0x00000001
-#define AR5K_KEYTABLE_TYPE_128		0x00000003
-#define AR5K_KEYTABLE_TYPE_TKIP		0x00000004	/* [5212+] */
-#define AR5K_KEYTABLE_TYPE_AES		0x00000005	/* [5211+] */
-#define AR5K_KEYTABLE_TYPE_CCM		0x00000006	/* [5212+] */
-#define AR5K_KEYTABLE_TYPE_NULL		0x00000007	/* [5211+] */
-#define AR5K_KEYTABLE_ANTENNA		0x00000008	/* [5212+] */
-#define AR5K_KEYTABLE_MAC0(_n)		AR5K_KEYTABLE_OFF(_n, 6)
-#define AR5K_KEYTABLE_MAC1(_n)		AR5K_KEYTABLE_OFF(_n, 7)
-#define AR5K_KEYTABLE_VALID		0x00008000
-
-/* If key type is TKIP and MIC is enabled
- * MIC key goes in offset entry + 64 */
-#define	AR5K_KEYTABLE_MIC_OFFSET	64
-
-/* WEP 40-bit	= 40-bit  entered key + 24 bit IV = 64-bit
- * WEP 104-bit	= 104-bit entered key + 24-bit IV = 128-bit
- * WEP 128-bit	= 128-bit entered key + 24 bit IV = 152-bit
- *
- * Some vendors have introduced bigger WEP keys to address
- * security vulnerabilities in WEP. This includes:
- *
- * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
- *
- * We can expand this if we find ar5k Atheros cards with a larger
- * key table size.
- */
-#define AR5K_KEYTABLE_SIZE_5210		64
-#define AR5K_KEYTABLE_SIZE_5211		128
-#define	AR5K_KEYTABLE_SIZE		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
-
-
-/*===PHY REGISTERS===*/
-
-/*
- * PHY registers start
- */
-#define	AR5K_PHY_BASE			0x9800
-#define	AR5K_PHY(_n)			(AR5K_PHY_BASE + ((_n) << 2))
-
-/*
- * TST_2 (Misc config parameters)
- */
-#define	AR5K_PHY_TST2			0x9800			/* Register Address */
-#define AR5K_PHY_TST2_TRIG_SEL		0x00000007	/* Trigger select (?)*/
-#define AR5K_PHY_TST2_TRIG		0x00000010	/* Trigger (?) */
-#define AR5K_PHY_TST2_CBUS_MODE		0x00000060	/* Cardbus mode (?) */
-#define AR5K_PHY_TST2_CLK32		0x00000400	/* CLK_OUT is CLK32 (32Khz external) */
-#define AR5K_PHY_TST2_CHANCOR_DUMP_EN	0x00000800	/* Enable Chancor dump (?) */
-#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP	0x00001000	/* Even Chancor dump (?) */
-#define AR5K_PHY_TST2_RFSILENT_EN	0x00002000	/* Enable RFSILENT */
-#define AR5K_PHY_TST2_ALT_RFDATA	0x00004000	/* Alternate RFDATA (5-2GHz switch ?) */
-#define AR5K_PHY_TST2_MINI_OBS_EN	0x00008000	/* Enable mini OBS (?) */
-#define AR5K_PHY_TST2_RX2_IS_RX5_INV	0x00010000	/* 2GHz rx path is the 5GHz path inverted (?) */
-#define AR5K_PHY_TST2_SLOW_CLK160	0x00020000	/* Slow CLK160 (?) */
-#define AR5K_PHY_TST2_AGC_OBS_SEL_3	0x00040000	/* AGC OBS Select 3 (?) */
-#define AR5K_PHY_TST2_BBB_OBS_SEL	0x00080000	/* BB OBS Select (field ?) */
-#define AR5K_PHY_TST2_ADC_OBS_SEL	0x00800000	/* ADC OBS Select (field ?) */
-#define AR5K_PHY_TST2_RX_CLR_SEL	0x08000000	/* RX Clear Select (?) */
-#define AR5K_PHY_TST2_FORCE_AGC_CLR	0x10000000	/* Force AGC clear (?) */
-#define AR5K_PHY_SHIFT_2GHZ		0x00004007	/* Used to access 2GHz radios */
-#define AR5K_PHY_SHIFT_5GHZ		0x00000007	/* Used to access 5GHz radios (default) */
-
-/*
- * PHY frame control register [5110] /turbo mode register [5111+]
- *
- * There is another frame control register for [5111+]
- * at address 0x9944 (see below) but the 2 first flags
- * are common here between 5110 frame control register
- * and [5111+] turbo mode register, so this also works as
- * a "turbo mode register" for 5110. We treat this one as
- * a frame control register for 5110 below.
- */
-#define	AR5K_PHY_TURBO			0x9804			/* Register Address */
-#define	AR5K_PHY_TURBO_MODE		0x00000001	/* Enable turbo mode */
-#define	AR5K_PHY_TURBO_SHORT		0x00000002	/* Set short symbols to turbo mode */
-#define	AR5K_PHY_TURBO_MIMO		0x00000004	/* Set turbo for mimo mimo */
-
-/*
- * PHY agility command register
- * (aka TST_1)
- */
-#define	AR5K_PHY_AGC			0x9808			/* Register Address */
-#define	AR5K_PHY_TST1			0x9808
-#define	AR5K_PHY_AGC_DISABLE		0x08000000	/* Disable AGC to A2 (?)*/
-#define	AR5K_PHY_TST1_TXHOLD		0x00003800	/* Set tx hold (?) */
-#define	AR5K_PHY_TST1_TXSRC_SRC		0x00000002	/* Used with bit 7 (?) */
-#define	AR5K_PHY_TST1_TXSRC_SRC_S	1
-#define	AR5K_PHY_TST1_TXSRC_ALT		0x00000080	/* Set input to tsdac (?) */
-#define	AR5K_PHY_TST1_TXSRC_ALT_S	7
-
-
-/*
- * PHY timing register 3 [5112+]
- */
-#define	AR5K_PHY_TIMING_3		0x9814
-#define	AR5K_PHY_TIMING_3_DSC_MAN	0xfffe0000
-#define	AR5K_PHY_TIMING_3_DSC_MAN_S	17
-#define	AR5K_PHY_TIMING_3_DSC_EXP	0x0001e000
-#define	AR5K_PHY_TIMING_3_DSC_EXP_S	13
-
-/*
- * PHY chip revision register
- */
-#define	AR5K_PHY_CHIP_ID		0x9818
-
-/*
- * PHY activation register
- */
-#define	AR5K_PHY_ACT			0x981c			/* Register Address */
-#define	AR5K_PHY_ACT_ENABLE		0x00000001	/* Activate PHY */
-#define	AR5K_PHY_ACT_DISABLE		0x00000002	/* Deactivate PHY */
-
-/*
- * PHY RF control registers
- */
-#define AR5K_PHY_RF_CTL2		0x9824			/* Register Address */
-#define	AR5K_PHY_RF_CTL2_TXF2TXD_START	0x0000000f	/* TX frame to TX data start */
-#define	AR5K_PHY_RF_CTL2_TXF2TXD_START_S	0
-
-#define AR5K_PHY_RF_CTL3		0x9828			/* Register Address */
-#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON	0x0000ff00	/* TX end to XLNA on */
-#define	AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S	8
-
-#define	AR5K_PHY_ADC_CTL			0x982c
-#define	AR5K_PHY_ADC_CTL_INBUFGAIN_OFF		0x00000003
-#define	AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S	0
-#define	AR5K_PHY_ADC_CTL_PWD_DAC_OFF		0x00002000
-#define	AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF	0x00004000
-#define	AR5K_PHY_ADC_CTL_PWD_ADC_OFF		0x00008000
-#define	AR5K_PHY_ADC_CTL_INBUFGAIN_ON		0x00030000
-#define	AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S		16
-
-#define AR5K_PHY_RF_CTL4		0x9834			/* Register Address */
-#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON	0x00000001	/* TX frame to XPA A on (field) */
-#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON	0x00000100	/* TX frame to XPA B on (field) */
-#define	AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF	0x00010000	/* TX end to XPA A off (field) */
-#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF	0x01000000	/* TX end to XPA B off (field) */
-
-/*
- * Pre-Amplifier control register
- * (XPA -> external pre-amplifier)
- */
-#define	AR5K_PHY_PA_CTL			0x9838			/* Register Address */
-#define	AR5K_PHY_PA_CTL_XPA_A_HI	0x00000001	/* XPA A high (?) */
-#define	AR5K_PHY_PA_CTL_XPA_B_HI	0x00000002	/* XPA B high (?) */
-#define	AR5K_PHY_PA_CTL_XPA_A_EN	0x00000004	/* Enable XPA A */
-#define	AR5K_PHY_PA_CTL_XPA_B_EN	0x00000008	/* Enable XPA B */
-
-/*
- * PHY settling register
- */
-#define AR5K_PHY_SETTLING		0x9844			/* Register Address */
-#define	AR5K_PHY_SETTLING_AGC		0x0000007f	/* AGC settling time */
-#define	AR5K_PHY_SETTLING_AGC_S		0
-#define	AR5K_PHY_SETTLING_SWITCH	0x00003f80	/* Switch settlig time */
-#define	AR5K_PHY_SETTLING_SWITCH_S	7
-
-/*
- * PHY Gain registers
- */
-#define AR5K_PHY_GAIN			0x9848			/* Register Address */
-#define	AR5K_PHY_GAIN_TXRX_ATTEN	0x0003f000	/* TX-RX Attenuation */
-#define	AR5K_PHY_GAIN_TXRX_ATTEN_S	12
-#define	AR5K_PHY_GAIN_TXRX_RF_MAX	0x007c0000
-#define	AR5K_PHY_GAIN_TXRX_RF_MAX_S	18
-
-#define	AR5K_PHY_GAIN_OFFSET		0x984c			/* Register Address */
-#define	AR5K_PHY_GAIN_OFFSET_RXTX_FLAG	0x00020000	/* RX-TX flag (?) */
-
-/*
- * Desired ADC/PGA size register
- * (for more infos read ANI patent)
- */
-#define AR5K_PHY_DESIRED_SIZE		0x9850			/* Register Address */
-#define	AR5K_PHY_DESIRED_SIZE_ADC	0x000000ff	/* ADC desired size */
-#define	AR5K_PHY_DESIRED_SIZE_ADC_S	0
-#define	AR5K_PHY_DESIRED_SIZE_PGA	0x0000ff00	/* PGA desired size */
-#define	AR5K_PHY_DESIRED_SIZE_PGA_S	8
-#define	AR5K_PHY_DESIRED_SIZE_TOT	0x0ff00000	/* Total desired size */
-#define	AR5K_PHY_DESIRED_SIZE_TOT_S	20
-
-/*
- * PHY signal register
- * (for more infos read ANI patent)
- */
-#define	AR5K_PHY_SIG			0x9858			/* Register Address */
-#define	AR5K_PHY_SIG_FIRSTEP		0x0003f000	/* FIRSTEP */
-#define	AR5K_PHY_SIG_FIRSTEP_S		12
-#define	AR5K_PHY_SIG_FIRPWR		0x03fc0000	/* FIPWR */
-#define	AR5K_PHY_SIG_FIRPWR_S		18
-
-/*
- * PHY coarse agility control register
- * (for more infos read ANI patent)
- */
-#define	AR5K_PHY_AGCCOARSE		0x985c			/* Register Address */
-#define	AR5K_PHY_AGCCOARSE_LO		0x00007f80	/* AGC Coarse low */
-#define	AR5K_PHY_AGCCOARSE_LO_S		7
-#define	AR5K_PHY_AGCCOARSE_HI		0x003f8000	/* AGC Coarse high */
-#define	AR5K_PHY_AGCCOARSE_HI_S		15
-
-/*
- * PHY agility control register
- */
-#define	AR5K_PHY_AGCCTL			0x9860			/* Register address */
-#define	AR5K_PHY_AGCCTL_CAL		0x00000001	/* Enable PHY calibration */
-#define	AR5K_PHY_AGCCTL_NF		0x00000002	/* Enable Noise Floor calibration */
-#define	AR5K_PHY_AGCCTL_NF_EN		0x00008000	/* Enable nf calibration to happen (?) */
-#define	AR5K_PHY_AGCCTL_NF_NOUPDATE	0x00020000	/* Don't update nf automaticaly */
-
-/*
- * PHY noise floor status register
- */
-#define AR5K_PHY_NF			0x9864			/* Register address */
-#define AR5K_PHY_NF_M			0x000001ff	/* Noise floor mask */
-#define AR5K_PHY_NF_ACTIVE		0x00000100	/* Noise floor calibration still active */
-#define AR5K_PHY_NF_RVAL(_n)		(((_n) >> 19) & AR5K_PHY_NF_M)
-#define AR5K_PHY_NF_AVAL(_n)		(-((_n) ^ AR5K_PHY_NF_M) + 1)
-#define AR5K_PHY_NF_SVAL(_n)		(((_n) & AR5K_PHY_NF_M) | (1 << 9))
-#define	AR5K_PHY_NF_THRESH62		0x0007f000	/* Thresh62 -check ANI patent- (field) */
-#define	AR5K_PHY_NF_THRESH62_S		12
-#define	AR5K_PHY_NF_MINCCA_PWR		0x0ff80000	/* ??? */
-#define	AR5K_PHY_NF_MINCCA_PWR_S	19
-
-/*
- * PHY ADC saturation register [5110]
- */
-#define	AR5K_PHY_ADCSAT			0x9868
-#define	AR5K_PHY_ADCSAT_ICNT		0x0001f800
-#define	AR5K_PHY_ADCSAT_ICNT_S		11
-#define	AR5K_PHY_ADCSAT_THR		0x000007e0
-#define	AR5K_PHY_ADCSAT_THR_S		5
-
-/*
- * PHY Weak ofdm signal detection threshold registers (ANI) [5212+]
- */
-
-/* High thresholds */
-#define AR5K_PHY_WEAK_OFDM_HIGH_THR		0x9868
-#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT	0x0000001f
-#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S	0
-#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1		0x00fe0000
-#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S	17
-#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2		0x7f000000
-#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S	24
-
-/* Low thresholds */
-#define AR5K_PHY_WEAK_OFDM_LOW_THR 		0x986c
-#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN	0x00000001
-#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT	0x00003f00
-#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S	8
-#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1		0x001fc000
-#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S		14
-#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2		0x0fe00000
-#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S		21
-
-
-/*
- * PHY sleep registers [5112+]
- */
-#define AR5K_PHY_SCR			0x9870
-
-#define AR5K_PHY_SLMT			0x9874
-#define AR5K_PHY_SLMT_32MHZ		0x0000007f
-
-#define AR5K_PHY_SCAL			0x9878
-#define AR5K_PHY_SCAL_32MHZ		0x0000000e
-#define	AR5K_PHY_SCAL_32MHZ_2417	0x0000000a
-#define	AR5K_PHY_SCAL_32MHZ_HB63	0x00000032
-
-/*
- * PHY PLL (Phase Locked Loop) control register
- */
-#define	AR5K_PHY_PLL			0x987c
-#define	AR5K_PHY_PLL_20MHZ		0x00000013	/* For half rate (?) */
-/* 40MHz -> 5GHz band */
-#define	AR5K_PHY_PLL_40MHZ_5211		0x00000018
-#define	AR5K_PHY_PLL_40MHZ_5212		0x000000aa
-#define	AR5K_PHY_PLL_40MHZ_5413		0x00000004
-#define	AR5K_PHY_PLL_40MHZ		(ah->ah_version == AR5K_AR5211 ? \
-					AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
-/* 44MHz -> 2.4GHz band */
-#define	AR5K_PHY_PLL_44MHZ_5211		0x00000019
-#define	AR5K_PHY_PLL_44MHZ_5212		0x000000ab
-#define	AR5K_PHY_PLL_44MHZ		(ah->ah_version == AR5K_AR5211 ? \
-					AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
-
-#define AR5K_PHY_PLL_RF5111		0x00000000
-#define AR5K_PHY_PLL_RF5112		0x00000040
-#define	AR5K_PHY_PLL_HALF_RATE		0x00000100
-#define	AR5K_PHY_PLL_QUARTER_RATE	0x00000200
-
-/*
- * RF Buffer register
- *
- * It's obvious from the code that 0x989c is the buffer register but
- * for the other special registers that we write to after sending each
- * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
- * for now. It's interesting that they are also used for some other operations.
- */
-
-#define AR5K_RF_BUFFER			0x989c
-#define AR5K_RF_BUFFER_CONTROL_0	0x98c0	/* Channel on 5110 */
-#define AR5K_RF_BUFFER_CONTROL_1	0x98c4	/* Bank 7 on 5112 */
-#define AR5K_RF_BUFFER_CONTROL_2	0x98cc	/* Bank 7 on 5111 */
-
-#define AR5K_RF_BUFFER_CONTROL_3	0x98d0	/* Bank 2 on 5112 */
-						/* Channel set on 5111 */
-						/* Used to read radio revision*/
-
-#define AR5K_RF_BUFFER_CONTROL_4	0x98d4  /* RF Stage register on 5110 */
-						/* Bank 0,1,2,6 on 5111 */
-						/* Bank 1 on 5112 */
-						/* Used during activation on 5111 */
-
-#define AR5K_RF_BUFFER_CONTROL_5	0x98d8	/* Bank 3 on 5111 */
-						/* Used during activation on 5111 */
-						/* Channel on 5112 */
-						/* Bank 6 on 5112 */
-
-#define AR5K_RF_BUFFER_CONTROL_6	0x98dc	/* Bank 3 on 5112 */
-
-/*
- * PHY RF stage register [5210]
- */
-#define AR5K_PHY_RFSTG			0x98d4
-#define AR5K_PHY_RFSTG_DISABLE		0x00000021
-
-/*
- * BIN masks (?)
- */
-#define	AR5K_PHY_BIN_MASK_1	0x9900
-#define	AR5K_PHY_BIN_MASK_2	0x9904
-#define	AR5K_PHY_BIN_MASK_3	0x9908
-
-#define	AR5K_PHY_BIN_MASK_CTL		0x990c
-#define	AR5K_PHY_BIN_MASK_CTL_MASK_4	0x00003fff
-#define	AR5K_PHY_BIN_MASK_CTL_MASK_4_S	0
-#define	AR5K_PHY_BIN_MASK_CTL_RATE	0xff000000
-#define	AR5K_PHY_BIN_MASK_CTL_RATE_S	24
-
-/*
- * PHY Antenna control register
- */
-#define AR5K_PHY_ANT_CTL		0x9910			/* Register Address */
-#define	AR5K_PHY_ANT_CTL_TXRX_EN	0x00000001	/* Enable TX/RX (?) */
-#define	AR5K_PHY_ANT_CTL_SECTORED_ANT	0x00000004	/* Sectored Antenna */
-#define	AR5K_PHY_ANT_CTL_HITUNE5	0x00000008	/* Hitune5 (?) */
-#define	AR5K_PHY_ANT_CTL_SWTABLE_IDLE	0x000003f0	/* Switch table idle (?) */
-#define	AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S	4
-
-/*
- * PHY receiver delay register [5111+]
- */
-#define	AR5K_PHY_RX_DELAY		0x9914			/* Register Address */
-#define	AR5K_PHY_RX_DELAY_M		0x00003fff	/* Mask for RX activate to receive delay (/100ns) */
-
-/*
- * PHY max rx length register (?) [5111]
- */
-#define	AR5K_PHY_MAX_RX_LEN		0x991c
-
-/*
- * PHY timing register 4
- * I(nphase)/Q(adrature) calibration register [5111+]
- */
-#define	AR5K_PHY_IQ			0x9920			/* Register Address */
-#define	AR5K_PHY_IQ_CORR_Q_Q_COFF	0x0000001f	/* Mask for q correction info */
-#define	AR5K_PHY_IQ_CORR_Q_I_COFF	0x000007e0	/* Mask for i correction info */
-#define	AR5K_PHY_IQ_CORR_Q_I_COFF_S	5
-#define	AR5K_PHY_IQ_CORR_ENABLE		0x00000800	/* Enable i/q correction */
-#define	AR5K_PHY_IQ_CAL_NUM_LOG_MAX	0x0000f000	/* Mask for max number of samples in log scale */
-#define	AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S	12
-#define	AR5K_PHY_IQ_RUN			0x00010000	/* Run i/q calibration */
-#define	AR5K_PHY_IQ_USE_PT_DF		0x00020000	/* Use pilot track df (?) */
-#define	AR5K_PHY_IQ_EARLY_TRIG_THR	0x00200000	/* Early trigger threshold (?) (field) */
-#define	AR5K_PHY_IQ_PILOT_MASK_EN	0x10000000	/* Enable pilot mask (?) */
-#define	AR5K_PHY_IQ_CHAN_MASK_EN	0x20000000	/* Enable channel mask (?) */
-#define	AR5K_PHY_IQ_SPUR_FILT_EN	0x40000000	/* Enable spur filter */
-#define	AR5K_PHY_IQ_SPUR_RSSI_EN	0x80000000	/* Enable spur rssi */
-
-/*
- * PHY timing register 5
- * OFDM Self-correlator Cyclic RSSI threshold params
- * (Check out bb_cycpwr_thr1 on ANI patent)
- */
-#define	AR5K_PHY_OFDM_SELFCORR			0x9924			/* Register Address */
-#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN	0x00000001	/* Enable cyclic RSSI thr 1 */
-#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1	0x000000fe	/* Mask for Cyclic RSSI threshold 1 */
-#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S	1
-#define	AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3	0x00000100	/* Cyclic RSSI threshold 3 (field) (?) */
-#define	AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN	0x00008000	/* Enable 1A RSSI threshold (?) */
-#define	AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR	0x00010000	/* 1A RSSI threshold (field) (?) */
-#define	AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI	0x00800000	/* Long sc threshold hi rssi (?) */
-
-/*
- * PHY-only warm reset register
- */
-#define	AR5K_PHY_WARM_RESET		0x9928
-
-/*
- * PHY-only control register
- */
-#define AR5K_PHY_CTL			0x992c			/* Register Address */
-#define	AR5K_PHY_CTL_RX_DRAIN_RATE	0x00000001	/* RX drain rate (?) */
-#define	AR5K_PHY_CTL_LATE_TX_SIG_SYM	0x00000002	/* Late tx signal symbol (?) */
-#define	AR5K_PHY_CTL_GEN_SCRAMBLER	0x00000004	/* Generate scrambler */
-#define	AR5K_PHY_CTL_TX_ANT_SEL		0x00000008	/* TX antenna select */
-#define	AR5K_PHY_CTL_TX_ANT_STATIC	0x00000010	/* Static TX antenna */
-#define	AR5K_PHY_CTL_RX_ANT_SEL		0x00000020	/* RX antenna select */
-#define	AR5K_PHY_CTL_RX_ANT_STATIC	0x00000040	/* Static RX antenna */
-#define	AR5K_PHY_CTL_LOW_FREQ_SLE_EN	0x00000080	/* Enable low freq sleep */
-
-/*
- * PHY PAPD probe register [5111+]
- */
-#define	AR5K_PHY_PAPD_PROBE		0x9930
-#define	AR5K_PHY_PAPD_PROBE_SH_HI_PAR	0x00000001
-#define	AR5K_PHY_PAPD_PROBE_PCDAC_BIAS	0x00000002
-#define	AR5K_PHY_PAPD_PROBE_COMP_GAIN	0x00000040
-#define	AR5K_PHY_PAPD_PROBE_TXPOWER	0x00007e00
-#define	AR5K_PHY_PAPD_PROBE_TXPOWER_S	9
-#define	AR5K_PHY_PAPD_PROBE_TX_NEXT	0x00008000
-#define	AR5K_PHY_PAPD_PROBE_PREDIST_EN	0x00010000
-#define	AR5K_PHY_PAPD_PROBE_TYPE	0x01800000	/* [5112+] */
-#define	AR5K_PHY_PAPD_PROBE_TYPE_S	23
-#define	AR5K_PHY_PAPD_PROBE_TYPE_OFDM	0
-#define	AR5K_PHY_PAPD_PROBE_TYPE_XR	1
-#define	AR5K_PHY_PAPD_PROBE_TYPE_CCK	2
-#define	AR5K_PHY_PAPD_PROBE_GAINF	0xfe000000
-#define	AR5K_PHY_PAPD_PROBE_GAINF_S	25
-#define	AR5K_PHY_PAPD_PROBE_INI_5111	0x00004883	/* [5212+] */
-#define	AR5K_PHY_PAPD_PROBE_INI_5112	0x00004882	/* [5212+] */
-
-/*
- * PHY TX rate power registers [5112+]
- */
-#define	AR5K_PHY_TXPOWER_RATE1			0x9934
-#define	AR5K_PHY_TXPOWER_RATE2			0x9938
-#define	AR5K_PHY_TXPOWER_RATE_MAX		0x993c
-#define	AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE	0x00000040
-#define	AR5K_PHY_TXPOWER_RATE3			0xa234
-#define	AR5K_PHY_TXPOWER_RATE4			0xa238
-
-/*
- * PHY frame control register [5111+]
- */
-#define	AR5K_PHY_FRAME_CTL_5210		0x9804
-#define	AR5K_PHY_FRAME_CTL_5211		0x9944
-#define	AR5K_PHY_FRAME_CTL		(ah->ah_version == AR5K_AR5210 ? \
-					AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
-/*---[5111+]---*/
-#define	AR5K_PHY_FRAME_CTL_TX_CLIP	0x00000038	/* Mask for tx clip (?) */
-#define	AR5K_PHY_FRAME_CTL_TX_CLIP_S	3
-#define	AR5K_PHY_FRAME_CTL_PREP_CHINFO	0x00010000	/* Prepend chan info */
-#define	AR5K_PHY_FRAME_CTL_EMU		0x80000000
-#define	AR5K_PHY_FRAME_CTL_EMU_S	31
-/*---[5110/5111]---*/
-#define	AR5K_PHY_FRAME_CTL_TIMING_ERR	0x01000000	/* PHY timing error */
-#define	AR5K_PHY_FRAME_CTL_PARITY_ERR	0x02000000	/* Parity error */
-#define	AR5K_PHY_FRAME_CTL_ILLRATE_ERR	0x04000000	/* Illegal rate */
-#define	AR5K_PHY_FRAME_CTL_ILLLEN_ERR	0x08000000	/* Illegal length */
-#define	AR5K_PHY_FRAME_CTL_SERVICE_ERR	0x20000000
-#define	AR5K_PHY_FRAME_CTL_TXURN_ERR	0x40000000	/* TX underrun */
-#define AR5K_PHY_FRAME_CTL_INI		AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
-			AR5K_PHY_FRAME_CTL_TXURN_ERR | \
-			AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
-			AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
-			AR5K_PHY_FRAME_CTL_PARITY_ERR | \
-			AR5K_PHY_FRAME_CTL_TIMING_ERR
-
-/*
- * PHY Tx Power adjustment register [5212A+]
- */
-#define	AR5K_PHY_TX_PWR_ADJ			0x994c
-#define	AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA	0x00000fc0
-#define	AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S	6
-#define	AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX	0x00fc0000
-#define	AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S	18
-
-/*
- * PHY radar detection register [5111+]
- */
-#define	AR5K_PHY_RADAR			0x9954
-#define	AR5K_PHY_RADAR_ENABLE		0x00000001
-#define	AR5K_PHY_RADAR_DISABLE		0x00000000
-#define AR5K_PHY_RADAR_INBANDTHR    	0x0000003e	/* Inband threshold
-							5-bits, units unknown {0..31}
-							(? MHz ?) */
-#define AR5K_PHY_RADAR_INBANDTHR_S	1
-
-#define AR5K_PHY_RADAR_PRSSI_THR    	0x00000fc0	/* Pulse RSSI/SNR threshold
-							6-bits, dBm range {0..63}
-							in dBm units. */
-#define AR5K_PHY_RADAR_PRSSI_THR_S	6
-
-#define AR5K_PHY_RADAR_PHEIGHT_THR   	0x0003f000	/* Pulse height threshold
-							6-bits, dBm range {0..63}
-							in dBm units. */
-#define AR5K_PHY_RADAR_PHEIGHT_THR_S	12
-
-#define AR5K_PHY_RADAR_RSSI_THR    	0x00fc0000	/* Radar RSSI/SNR threshold.
-							6-bits, dBm range {0..63}
-							in dBm units. */
-#define AR5K_PHY_RADAR_RSSI_THR_S	18
-
-#define AR5K_PHY_RADAR_FIRPWR_THR	0x7f000000	/* Finite Impulse Response
-							filter power out threshold.
-							7-bits, standard power range
-							{0..127} in 1/2 dBm units. */
-#define AR5K_PHY_RADAR_FIRPWR_THRS	24
-
-/*
- * PHY antenna switch table registers
- */
-#define AR5K_PHY_ANT_SWITCH_TABLE_0	0x9960
-#define AR5K_PHY_ANT_SWITCH_TABLE_1	0x9964
-
-/*
- * PHY Noise floor threshold
- */
-#define AR5K_PHY_NFTHRES		0x9968
-
-/*
- * Sigma Delta register (?) [5213]
- */
-#define AR5K_PHY_SIGMA_DELTA		0x996C
-#define AR5K_PHY_SIGMA_DELTA_ADC_SEL	0x00000003
-#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S	0
-#define AR5K_PHY_SIGMA_DELTA_FILT2	0x000000f8
-#define AR5K_PHY_SIGMA_DELTA_FILT2_S	3
-#define AR5K_PHY_SIGMA_DELTA_FILT1	0x00001f00
-#define AR5K_PHY_SIGMA_DELTA_FILT1_S	8
-#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP	0x01ffe000
-#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S	13
-
-/*
- * RF restart register [5112+] (?)
- */
-#define AR5K_PHY_RESTART		0x9970		/* restart */
-#define AR5K_PHY_RESTART_DIV_GC		0x001c0000	/* Fast diversity gc_limit (?) */
-#define AR5K_PHY_RESTART_DIV_GC_S	18
-
-/*
- * RF Bus access request register (for synth-oly channel switching)
- */
-#define AR5K_PHY_RFBUS_REQ		0x997C
-#define AR5K_PHY_RFBUS_REQ_REQUEST	0x00000001
-
-/*
- * Spur mitigation masks (?)
- */
-#define AR5K_PHY_TIMING_7		0x9980
-#define AR5K_PHY_TIMING_8		0x9984
-#define AR5K_PHY_TIMING_8_PILOT_MASK_2		0x000fffff
-#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S	0
-
-#define AR5K_PHY_BIN_MASK2_1		0x9988
-#define AR5K_PHY_BIN_MASK2_2		0x998c
-#define AR5K_PHY_BIN_MASK2_3		0x9990
-
-#define AR5K_PHY_BIN_MASK2_4		0x9994
-#define AR5K_PHY_BIN_MASK2_4_MASK_4	0x00003fff
-#define AR5K_PHY_BIN_MASK2_4_MASK_4_S	0
-
-#define AR5K_PHY_TIMING_9			0x9998
-#define AR5K_PHY_TIMING_10			0x999c
-#define AR5K_PHY_TIMING_10_PILOT_MASK_2		0x000fffff
-#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S	0
-
-/*
- * Spur mitigation control
- */
-#define AR5K_PHY_TIMING_11			0x99a0		/* Register address */
-#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE	0x000fffff	/* Spur delta phase */
-#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S	0
-#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD		0x3ff00000	/* Freq sigma delta */
-#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S	20
-#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC	0x40000000	/* Spur filter in AGC detector */
-#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR	0x80000000	/* Spur filter in OFDM self correlator */
-
-/*
- * Gain tables
- */
-#define	AR5K_BB_GAIN_BASE		0x9b00	/* BaseBand Amplifier Gain table base address */
-#define AR5K_BB_GAIN(_n)		(AR5K_BB_GAIN_BASE + ((_n) << 2))
-#define	AR5K_RF_GAIN_BASE		0x9a00	/* RF Amplrifier Gain table base address */
-#define AR5K_RF_GAIN(_n)		(AR5K_RF_GAIN_BASE + ((_n) << 2))
-
-/*
- * PHY timing IQ calibration result register [5111+]
- */
-#define	AR5K_PHY_IQRES_CAL_PWR_I	0x9c10	/* I (Inphase) power value */
-#define	AR5K_PHY_IQRES_CAL_PWR_Q	0x9c14	/* Q (Quadrature) power value */
-#define	AR5K_PHY_IQRES_CAL_CORR		0x9c18	/* I/Q Correlation */
-
-/*
- * PHY current RSSI register [5111+]
- */
-#define	AR5K_PHY_CURRENT_RSSI	0x9c1c
-
-/*
- * PHY RF Bus grant register
- */
-#define	AR5K_PHY_RFBUS_GRANT	0x9c20
-#define	AR5K_PHY_RFBUS_GRANT_OK	0x00000001
-
-/*
- * PHY ADC test register
- */
-#define	AR5K_PHY_ADC_TEST	0x9c24
-#define	AR5K_PHY_ADC_TEST_I	0x00000001
-#define	AR5K_PHY_ADC_TEST_Q	0x00000200
-
-/*
- * PHY DAC test register
- */
-#define	AR5K_PHY_DAC_TEST	0x9c28
-#define	AR5K_PHY_DAC_TEST_I	0x00000001
-#define	AR5K_PHY_DAC_TEST_Q	0x00000200
-
-/*
- * PHY PTAT register (?)
- */
-#define	AR5K_PHY_PTAT		0x9c2c
-
-/*
- * PHY Illegal TX rate register [5112+]
- */
-#define	AR5K_PHY_BAD_TX_RATE	0x9c30
-
-/*
- * PHY SPUR Power register [5112+]
- */
-#define	AR5K_PHY_SPUR_PWR	0x9c34			/* Register Address */
-#define	AR5K_PHY_SPUR_PWR_I	0x00000001	/* SPUR Power estimate for I (field) */
-#define	AR5K_PHY_SPUR_PWR_Q	0x00000100	/* SPUR Power estimate for Q (field) */
-#define	AR5K_PHY_SPUR_PWR_FILT	0x00010000	/* Power with SPUR removed (field) */
-
-/*
- * PHY Channel status register [5112+] (?)
- */
-#define	AR5K_PHY_CHAN_STATUS		0x9c38
-#define	AR5K_PHY_CHAN_STATUS_BT_ACT	0x00000001
-#define	AR5K_PHY_CHAN_STATUS_RX_CLR_RAW	0x00000002
-#define	AR5K_PHY_CHAN_STATUS_RX_CLR_MAC	0x00000004
-#define	AR5K_PHY_CHAN_STATUS_RX_CLR_PAP	0x00000008
-
-/*
- * Heavy clip enable register
- */
-#define	AR5K_PHY_HEAVY_CLIP_ENABLE	0x99e0
-
-/*
- * PHY clock sleep registers [5112+]
- */
-#define AR5K_PHY_SCLOCK			0x99f0
-#define AR5K_PHY_SCLOCK_32MHZ		0x0000000c
-#define AR5K_PHY_SDELAY			0x99f4
-#define AR5K_PHY_SDELAY_32MHZ		0x000000ff
-#define AR5K_PHY_SPENDING		0x99f8
-
-
-/*
- * PHY PAPD I (power?) table (?)
- * (92! entries)
- */
-#define	AR5K_PHY_PAPD_I_BASE	0xa000
-#define	AR5K_PHY_PAPD_I(_n)	(AR5K_PHY_PAPD_I_BASE + ((_n) << 2))
-
-/*
- * PHY PCDAC TX power table
- */
-#define	AR5K_PHY_PCDAC_TXPOWER_BASE	0xa180
-#define	AR5K_PHY_PCDAC_TXPOWER(_n)	(AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2))
-
-/*
- * PHY mode register [5111+]
- */
-#define	AR5K_PHY_MODE			0x0a200			/* Register Address */
-#define	AR5K_PHY_MODE_MOD		0x00000001	/* PHY Modulation bit */
-#define AR5K_PHY_MODE_MOD_OFDM		0
-#define AR5K_PHY_MODE_MOD_CCK		1
-#define AR5K_PHY_MODE_FREQ		0x00000002	/* Freq mode bit */
-#define	AR5K_PHY_MODE_FREQ_5GHZ		0
-#define	AR5K_PHY_MODE_FREQ_2GHZ		2
-#define AR5K_PHY_MODE_MOD_DYN		0x00000004	/* Enable Dynamic OFDM/CCK mode [5112+] */
-#define AR5K_PHY_MODE_RAD		0x00000008	/* [5212+] */
-#define AR5K_PHY_MODE_RAD_RF5111	0
-#define AR5K_PHY_MODE_RAD_RF5112	8
-#define AR5K_PHY_MODE_XR		0x00000010	/* Enable XR mode [5112+] */
-#define	AR5K_PHY_MODE_HALF_RATE		0x00000020	/* Enable Half rate (test) */
-#define	AR5K_PHY_MODE_QUARTER_RATE	0x00000040	/* Enable Quarter rat (test) */
-
-/*
- * PHY CCK transmit control register [5111+ (?)]
- */
-#define AR5K_PHY_CCKTXCTL		0xa204
-#define AR5K_PHY_CCKTXCTL_WORLD		0x00000000
-#define AR5K_PHY_CCKTXCTL_JAPAN		0x00000010
-#define	AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS	0x00000001
-#define	AR5K_PHY_CCKTXCTK_DAC_SCALE	0x00000004
-
-/*
- * PHY CCK Cross-correlator Barker RSSI threshold register [5212+]
- */
-#define AR5K_PHY_CCK_CROSSCORR			0xa208
-#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR	0x0000000f
-#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S	0
-
-/* Same address is used for antenna diversity activation */
-#define	AR5K_PHY_FAST_ANT_DIV		0xa208
-#define	AR5K_PHY_FAST_ANT_DIV_EN	0x00002000
-
-/*
- * PHY 2GHz gain register [5111+]
- */
-#define	AR5K_PHY_GAIN_2GHZ			0xa20c
-#define	AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX		0x00fc0000
-#define	AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S	18
-#define	AR5K_PHY_GAIN_2GHZ_INI_5111		0x6480416c
-
-#define	AR5K_PHY_CCK_RX_CTL_4			0xa21c
-#define	AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT	0x01f80000
-#define	AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S	19
-
-#define	AR5K_PHY_DAG_CCK_CTL			0xa228
-#define	AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR	0x00000200
-#define	AR5K_PHY_DAG_CCK_CTL_RSSI_THR		0x0001fc00
-#define	AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S		10
-
-#define	AR5K_PHY_FAST_ADC	0xa24c
-
-#define	AR5K_PHY_BLUETOOTH	0xa254
-
-/*
- * Transmit Power Control register
- * [2413+]
- */
-#define	AR5K_PHY_TPC_RG1		0xa258
-#define	AR5K_PHY_TPC_RG1_NUM_PD_GAIN	0x0000c000
-#define	AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S	14
-#define AR5K_PHY_TPC_RG1_PDGAIN_1	0x00030000
-#define AR5K_PHY_TPC_RG1_PDGAIN_1_S	16
-#define AR5K_PHY_TPC_RG1_PDGAIN_2	0x000c0000
-#define AR5K_PHY_TPC_RG1_PDGAIN_2_S	18
-#define AR5K_PHY_TPC_RG1_PDGAIN_3	0x00300000
-#define AR5K_PHY_TPC_RG1_PDGAIN_3_S	20
-
-#define	AR5K_PHY_TPC_RG5			0xa26C
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP	0x0000000F
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S	0
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1	0x000003F0
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S	4
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2	0x0000FC00
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S	10
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3	0x003F0000
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S	16
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4	0x0FC00000
-#define	AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S	22
-
-/*
- * PHY PDADC Tx power table
- */
-#define AR5K_PHY_PDADC_TXPOWER_BASE	0xa280
-#define	AR5K_PHY_PDADC_TXPOWER(_n)	(AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2))
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/reset.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/reset.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/reset.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/reset.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1347 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
- * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
- * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#define _ATH5K_RESET
-
-/*****************************\
-  Reset functions and helpers
-\*****************************/
-
-#include <linux/pci.h> 		/* To determine if a card is pci-e */
-#include <linux/log2.h>
-#include "ath5k.h"
-#include "reg.h"
-#include "base.h"
-#include "debug.h"
-
-/**
- * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
- *
- * @ah: the &struct ath5k_hw
- * @channel: the currently set channel upon reset
- *
- * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
- * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
- *
- * Since delta slope is floating point we split it on its exponent and
- * mantissa and provide these values on hw.
- *
- * For more infos i think this patent is related
- * http://www.freepatentsonline.com/7184495.html
- */
-static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
-	struct ieee80211_channel *channel)
-{
-	/* Get exponent and mantissa and set it */
-	u32 coef_scaled, coef_exp, coef_man,
-		ds_coef_exp, ds_coef_man, clock;
-
-	if (!(ah->ah_version == AR5K_AR5212) ||
-		!(channel->hw_value & CHANNEL_OFDM))
-		BUG();
-
-	/* Get coefficient
-	 * ALGO: coef = (5 * clock * carrier_freq) / 2)
-	 * we scale coef by shifting clock value by 24 for
-	 * better precision since we use integers */
-	/* TODO: Half/quarter rate */
-	clock =  ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO);
-
-	coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
-
-	/* Get exponent
-	 * ALGO: coef_exp = 14 - highest set bit position */
-	coef_exp = ilog2(coef_scaled);
-
-	/* Doesn't make sense if it's zero*/
-	if (!coef_scaled || !coef_exp)
-		return -EINVAL;
-
-	/* Note: we've shifted coef_scaled by 24 */
-	coef_exp = 14 - (coef_exp - 24);
-
-
-	/* Get mantissa (significant digits)
-	 * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
-	coef_man = coef_scaled +
-		(1 << (24 - coef_exp - 1));
-
-	/* Calculate delta slope coefficient exponent
-	 * and mantissa (remove scaling) and set them on hw */
-	ds_coef_man = coef_man >> (24 - coef_exp);
-	ds_coef_exp = coef_exp - 16;
-
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
-		AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
-		AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
-
-	return 0;
-}
-
-
-/*
- * index into rates for control rates, we can set it up like this because
- * this is only used for AR5212 and we know it supports G mode
- */
-static const unsigned int control_rates[] =
-	{ 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
-
-/**
- * ath5k_hw_write_rate_duration - fill rate code to duration table
- *
- * @ah: the &struct ath5k_hw
- * @mode: one of enum ath5k_driver_mode
- *
- * Write the rate code to duration table upon hw reset. This is a helper for
- * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
- * the hardware, based on current mode, for each rate. The rates which are
- * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
- * different rate code so we write their value twice (one for long preample
- * and one for short).
- *
- * Note: Band doesn't matter here, if we set the values for OFDM it works
- * on both a and g modes. So all we have to do is set values for all g rates
- * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
- * quarter rate mode, we need to use another set of bitrates (that's why we
- * need the mode parameter) but we don't handle these proprietary modes yet.
- */
-static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
-       unsigned int mode)
-{
-	struct ath5k_softc *sc = ah->ah_sc;
-	struct ieee80211_rate *rate;
-	unsigned int i;
-
-	/* Write rate duration table */
-	for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
-		u32 reg;
-		u16 tx_time;
-
-		rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
-
-		/* Set ACK timeout */
-		reg = AR5K_RATE_DUR(rate->hw_value);
-
-		/* An ACK frame consists of 10 bytes. If you add the FCS,
-		 * which ieee80211_generic_frame_duration() adds,
-		 * its 14 bytes. Note we use the control rate and not the
-		 * actual rate for this rate. See mac80211 tx.c
-		 * ieee80211_duration() for a brief description of
-		 * what rate we should choose to TX ACKs. */
-		tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
-							sc->vif, 10, rate));
-
-		ath5k_hw_reg_write(ah, tx_time, reg);
-
-		if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
-			continue;
-
-		/*
-		 * We're not distinguishing short preamble here,
-		 * This is true, all we'll get is a longer value here
-		 * which is not necessarilly bad. We could use
-		 * export ieee80211_frame_duration() but that needs to be
-		 * fixed first to be properly used by mac802111 drivers:
-		 *
-		 *  - remove erp stuff and let the routine figure ofdm
-		 *    erp rates
-		 *  - remove passing argument ieee80211_local as
-		 *    drivers don't have access to it
-		 *  - move drivers using ieee80211_generic_frame_duration()
-		 *    to this
-		 */
-		ath5k_hw_reg_write(ah, tx_time,
-			reg + (AR5K_SET_SHORT_PREAMBLE << 2));
-	}
-}
-
-/*
- * Reset chipset
- */
-static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
-{
-	int ret;
-	u32 mask = val ? val : ~0U;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/* Read-and-clear RX Descriptor Pointer*/
-	ath5k_hw_reg_read(ah, AR5K_RXDP);
-
-	/*
-	 * Reset the device and wait until success
-	 */
-	ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
-
-	/* Wait at least 128 PCI clocks */
-	udelay(15);
-
-	if (ah->ah_version == AR5K_AR5210) {
-		val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
-			| AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
-		mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
-			| AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
-	} else {
-		val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
-		mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
-	}
-
-	ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
-
-	/*
-	 * Reset configuration register (for hw byte-swap). Note that this
-	 * is only set for big endian. We do the necessary magic in
-	 * AR5K_INIT_CFG.
-	 */
-	if ((val & AR5K_RESET_CTL_PCU) == 0)
-		ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
-
-	return ret;
-}
-
-/*
- * Sleep control
- */
-int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
-		bool set_chip, u16 sleep_duration)
-{
-	unsigned int i;
-	u32 staid, data;
-
-	ATH5K_TRACE(ah->ah_sc);
-	staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
-
-	switch (mode) {
-	case AR5K_PM_AUTO:
-		staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
-		/* fallthrough */
-	case AR5K_PM_NETWORK_SLEEP:
-		if (set_chip)
-			ath5k_hw_reg_write(ah,
-				AR5K_SLEEP_CTL_SLE_ALLOW |
-				sleep_duration,
-				AR5K_SLEEP_CTL);
-
-		staid |= AR5K_STA_ID1_PWR_SV;
-		break;
-
-	case AR5K_PM_FULL_SLEEP:
-		if (set_chip)
-			ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
-				AR5K_SLEEP_CTL);
-
-		staid |= AR5K_STA_ID1_PWR_SV;
-		break;
-
-	case AR5K_PM_AWAKE:
-
-		staid &= ~AR5K_STA_ID1_PWR_SV;
-
-		if (!set_chip)
-			goto commit;
-
-		/* Preserve sleep duration */
-		data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
-		if (data & 0xffc00000)
-			data = 0;
-		else
-			data = data & 0xfffcffff;
-
-		ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
-		udelay(15);
-
-		for (i = 50; i > 0; i--) {
-			/* Check if the chip did wake up */
-			if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
-					AR5K_PCICFG_SPWR_DN) == 0)
-				break;
-
-			/* Wait a bit and retry */
-			udelay(200);
-			ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
-		}
-
-		/* Fail if the chip didn't wake up */
-		if (i <= 0)
-			return -EIO;
-
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-commit:
-	ah->ah_power_mode = mode;
-	ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
-
-	return 0;
-}
-
-/*
- * Bring up MAC + PHY Chips and program PLL
- * TODO: Half/Quarter rate support
- */
-int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
-{
-	struct pci_dev *pdev = ah->ah_sc->pdev;
-	u32 turbo, mode, clock, bus_flags;
-	int ret;
-
-	turbo = 0;
-	mode = 0;
-	clock = 0;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	/* Wakeup the device */
-	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
-	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
-		return ret;
-	}
-
-	if (ah->ah_version != AR5K_AR5210) {
-		/*
-		 * Get channel mode flags
-		 */
-
-		if (ah->ah_radio >= AR5K_RF5112) {
-			mode = AR5K_PHY_MODE_RAD_RF5112;
-			clock = AR5K_PHY_PLL_RF5112;
-		} else {
-			mode = AR5K_PHY_MODE_RAD_RF5111;	/*Zero*/
-			clock = AR5K_PHY_PLL_RF5111;		/*Zero*/
-		}
-
-		if (flags & CHANNEL_2GHZ) {
-			mode |= AR5K_PHY_MODE_FREQ_2GHZ;
-			clock |= AR5K_PHY_PLL_44MHZ;
-
-			if (flags & CHANNEL_CCK) {
-				mode |= AR5K_PHY_MODE_MOD_CCK;
-			} else if (flags & CHANNEL_OFDM) {
-				/* XXX Dynamic OFDM/CCK is not supported by the
-				 * AR5211 so we set MOD_OFDM for plain g (no
-				 * CCK headers) operation. We need to test
-				 * this, 5211 might support ofdm-only g after
-				 * all, there are also initial register values
-				 * in the code for g mode (see initvals.c). */
-				if (ah->ah_version == AR5K_AR5211)
-					mode |= AR5K_PHY_MODE_MOD_OFDM;
-				else
-					mode |= AR5K_PHY_MODE_MOD_DYN;
-			} else {
-				ATH5K_ERR(ah->ah_sc,
-					"invalid radio modulation mode\n");
-				return -EINVAL;
-			}
-		} else if (flags & CHANNEL_5GHZ) {
-			mode |= AR5K_PHY_MODE_FREQ_5GHZ;
-
-			if (ah->ah_radio == AR5K_RF5413)
-				clock = AR5K_PHY_PLL_40MHZ_5413;
-			else
-				clock |= AR5K_PHY_PLL_40MHZ;
-
-			if (flags & CHANNEL_OFDM)
-				mode |= AR5K_PHY_MODE_MOD_OFDM;
-			else {
-				ATH5K_ERR(ah->ah_sc,
-					"invalid radio modulation mode\n");
-				return -EINVAL;
-			}
-		} else {
-			ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
-			return -EINVAL;
-		}
-
-		if (flags & CHANNEL_TURBO)
-			turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
-	} else { /* Reset the device */
-
-		/* ...enable Atheros turbo mode if requested */
-		if (flags & CHANNEL_TURBO)
-			ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
-					AR5K_PHY_TURBO);
-	}
-
-	/* reseting PCI on PCI-E cards results card to hang
-	 * and always return 0xffff... so we ingore that flag
-	 * for PCI-E cards */
-	bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
-
-	/* Reset chipset */
-	if (ah->ah_version == AR5K_AR5210) {
-		ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
-			AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
-			AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
-			mdelay(2);
-	} else {
-		ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
-			AR5K_RESET_CTL_BASEBAND | bus_flags);
-	}
-	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
-		return -EIO;
-	}
-
-	/* ...wakeup again!*/
-	ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
-	if (ret) {
-		ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
-		return ret;
-	}
-
-	/* ...final warm reset */
-	if (ath5k_hw_nic_reset(ah, 0)) {
-		ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
-		return -EIO;
-	}
-
-	if (ah->ah_version != AR5K_AR5210) {
-
-		/* ...update PLL if needed */
-		if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
-			ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
-			udelay(300);
-		}
-
-		/* ...set the PHY operating mode */
-		ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
-		ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
-	}
-
-	return 0;
-}
-
-/*
- * If there is an external 32KHz crystal available, use it
- * as ref. clock instead of 32/40MHz clock and baseband clocks
- * to save power during sleep or restore normal 32/40MHz
- * operation.
- *
- * XXX: When operating on 32KHz certain PHY registers (27 - 31,
- * 	123 - 127) require delay on access.
- */
-static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	u32 scal, spending, usec32;
-
-	/* Only set 32KHz settings if we have an external
-	 * 32KHz crystal present */
-	if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
-	AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
-	enable) {
-
-		/* 1 usec/cycle */
-		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
-		/* Set up tsf increment on each cycle */
-		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
-
-		/* Set baseband sleep control registers
-		 * and sleep control rate */
-		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413) ||
-		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
-			spending = 0x14;
-		else
-			spending = 0x18;
-		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413) ||
-		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
-			ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
-			ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
-			ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
-			ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
-			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
-		} else {
-			ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
-			ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
-			ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
-			ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
-			AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
-		}
-
-		/* Enable sleep clock operation */
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_EN);
-
-	} else {
-
-		/* Disable sleep clock operation and
-		 * restore default parameters */
-		AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_EN);
-
-		AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
-				AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
-
-		ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
-		ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
-
-		if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
-			scal = AR5K_PHY_SCAL_32MHZ_2417;
-		else if (ath5k_eeprom_is_hb63(ah))
-			scal = AR5K_PHY_SCAL_32MHZ_HB63;
-		else
-			scal = AR5K_PHY_SCAL_32MHZ;
-		ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
-
-		ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
-		ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413) ||
-		(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
-			spending = 0x14;
-		else
-			spending = 0x18;
-		ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
-
-		if ((ah->ah_radio == AR5K_RF5112) ||
-		(ah->ah_radio == AR5K_RF5413))
-			usec32 = 39;
-		else
-			usec32 = 31;
-		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
-
-		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
-	}
-	return;
-}
-
-static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
-				struct ieee80211_channel *channel)
-{
-	u8 refclk_freq;
-
-	if ((ah->ah_radio == AR5K_RF5112) ||
-	(ah->ah_radio == AR5K_RF5413) ||
-	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
-		refclk_freq = 40;
-	else
-		refclk_freq = 32;
-
-	if ((channel->center_freq % refclk_freq != 0) &&
-	((channel->center_freq % refclk_freq < 10) ||
-	(channel->center_freq % refclk_freq > 22)))
-		return true;
-	else
-		return false;
-}
-
-/* TODO: Half/Quarter rate */
-static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
-				struct ieee80211_channel *channel)
-{
-	if (ah->ah_version == AR5K_AR5212 &&
-	    ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
-
-		/* Setup ADC control */
-		ath5k_hw_reg_write(ah,
-				(AR5K_REG_SM(2,
-				AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
-				AR5K_REG_SM(2,
-				AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
-				AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
-				AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
-				AR5K_PHY_ADC_CTL);
-
-
-
-		/* Disable barker RSSI threshold */
-		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
-				AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
-
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
-			AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
-
-		/* Set the mute mask */
-		ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
-	}
-
-	/* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
-	if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
-		ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
-
-	/* Enable DCU double buffering */
-	if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
-		AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
-				AR5K_TXCFG_DCU_DBL_BUF_DIS);
-
-	/* Set DAC/ADC delays */
-	if (ah->ah_version == AR5K_AR5212) {
-		u32 scal;
-		if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
-			scal = AR5K_PHY_SCAL_32MHZ_2417;
-		else if (ath5k_eeprom_is_hb63(ah))
-			scal = AR5K_PHY_SCAL_32MHZ_HB63;
-		else
-			scal = AR5K_PHY_SCAL_32MHZ;
-		ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
-	}
-
-	/* Set fast ADC */
-	if ((ah->ah_radio == AR5K_RF5413) ||
-	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
-		u32 fast_adc = true;
-
-		if (channel->center_freq == 2462 ||
-		channel->center_freq == 2467)
-			fast_adc = 0;
-
-		/* Only update if needed */
-		if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
-				ath5k_hw_reg_write(ah, fast_adc,
-						AR5K_PHY_FAST_ADC);
-	}
-
-	/* Fix for first revision of the RF5112 RF chipset */
-	if (ah->ah_radio == AR5K_RF5112 &&
-			ah->ah_radio_5ghz_revision <
-			AR5K_SREV_RAD_5112A) {
-		u32 data;
-		ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
-				AR5K_PHY_CCKTXCTL);
-		if (channel->hw_value & CHANNEL_5GHZ)
-			data = 0xffb81020;
-		else
-			data = 0xffb80d20;
-		ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
-	}
-
-	if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
-		u32 usec_reg;
-		/* 5311 has different tx/rx latency masks
-		 * from 5211, since we deal 5311 the same
-		 * as 5211 when setting initvals, shift
-		 * values here to their proper locations */
-		usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
-		ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
-				AR5K_USEC_32 |
-				AR5K_USEC_TX_LATENCY_5211 |
-				AR5K_REG_SM(29,
-				AR5K_USEC_RX_LATENCY_5210)),
-				AR5K_USEC_5211);
-		/* Clear QCU/DCU clock gating register */
-		ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
-		/* Set DAC/ADC delays */
-		ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
-		/* Enable PCU FIFO corruption ECO */
-		AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
-					AR5K_DIAG_SW_ECO_ENABLE);
-	}
-}
-
-static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
-		struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
-{
-	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	s16 cck_ofdm_pwr_delta;
-
-	/* Adjust power delta for channel 14 */
-	if (channel->center_freq == 2484)
-		cck_ofdm_pwr_delta =
-			((ee->ee_cck_ofdm_power_delta -
-			ee->ee_scaled_cck_delta) * 2) / 10;
-	else
-		cck_ofdm_pwr_delta =
-			(ee->ee_cck_ofdm_power_delta * 2) / 10;
-
-	/* Set CCK to OFDM power delta on tx power
-	 * adjustment register */
-	if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
-		if (channel->hw_value == CHANNEL_G)
-			ath5k_hw_reg_write(ah,
-			AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
-				AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
-			AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
-				AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
-				AR5K_PHY_TX_PWR_ADJ);
-		else
-			ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
-	} else {
-		/* For older revs we scale power on sw during tx power
-		 * setup */
-		ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
-		ah->ah_txpower.txp_cck_ofdm_gainf_delta =
-						ee->ee_cck_ofdm_gain_delta;
-	}
-
-	/* Set antenna idle switch table */
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
-			AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
-			(ah->ah_antenna[ee_mode][0] |
-			AR5K_PHY_ANT_CTL_TXRX_EN));
-
-	/* Set antenna switch table */
-	ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
-		AR5K_PHY_ANT_SWITCH_TABLE_0);
-	ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
-		AR5K_PHY_ANT_SWITCH_TABLE_1);
-
-	/* Noise floor threshold */
-	ath5k_hw_reg_write(ah,
-		AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
-		AR5K_PHY_NFTHRES);
-
-	if ((channel->hw_value & CHANNEL_TURBO) &&
-	(ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
-		/* Switch settling time (Turbo) */
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
-				AR5K_PHY_SETTLING_SWITCH,
-				ee->ee_switch_settling_turbo[ee_mode]);
-
-		/* Tx/Rx attenuation (Turbo) */
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
-				AR5K_PHY_GAIN_TXRX_ATTEN,
-				ee->ee_atn_tx_rx_turbo[ee_mode]);
-
-		/* ADC/PGA desired size (Turbo) */
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
-				AR5K_PHY_DESIRED_SIZE_ADC,
-				ee->ee_adc_desired_size_turbo[ee_mode]);
-
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
-				AR5K_PHY_DESIRED_SIZE_PGA,
-				ee->ee_pga_desired_size_turbo[ee_mode]);
-
-		/* Tx/Rx margin (Turbo) */
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
-				AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
-				ee->ee_margin_tx_rx_turbo[ee_mode]);
-
-	} else {
-		/* Switch settling time */
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
-				AR5K_PHY_SETTLING_SWITCH,
-				ee->ee_switch_settling[ee_mode]);
-
-		/* Tx/Rx attenuation */
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
-				AR5K_PHY_GAIN_TXRX_ATTEN,
-				ee->ee_atn_tx_rx[ee_mode]);
-
-		/* ADC/PGA desired size */
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
-				AR5K_PHY_DESIRED_SIZE_ADC,
-				ee->ee_adc_desired_size[ee_mode]);
-
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
-				AR5K_PHY_DESIRED_SIZE_PGA,
-				ee->ee_pga_desired_size[ee_mode]);
-
-		/* Tx/Rx margin */
-		if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
-			AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
-				AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
-				ee->ee_margin_tx_rx[ee_mode]);
-	}
-
-	/* XPA delays */
-	ath5k_hw_reg_write(ah,
-		(ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
-		(ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
-		(ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
-		(ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
-
-	/* XLNA delay */
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
-			AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
-			ee->ee_tx_end2xlna_enable[ee_mode]);
-
-	/* Thresh64 (ANI) */
-	AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
-			AR5K_PHY_NF_THRESH62,
-			ee->ee_thr_62[ee_mode]);
-
-
-	/* False detect backoff for channels
-	 * that have spur noise. Write the new
-	 * cyclic power RSSI threshold. */
-	if (ath5k_hw_chan_has_spur_noise(ah, channel))
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
-				AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
-				AR5K_INIT_CYCRSSI_THR1 +
-				ee->ee_false_detect[ee_mode]);
-	else
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
-				AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
-				AR5K_INIT_CYCRSSI_THR1);
-
-	/* I/Q correction
-	 * TODO: Per channel i/q infos ? */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
-		AR5K_PHY_IQ_CORR_ENABLE |
-		(ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
-		ee->ee_q_cal[ee_mode]);
-
-	/* Heavy clipping -disable for now */
-	if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
-		ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
-
-	return;
-}
-
-/*
- * Main reset function
- */
-int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
-	struct ieee80211_channel *channel, bool change_channel)
-{
-	u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
-	u32 phy_tst1;
-	u8 mode, freq, ee_mode, ant[2];
-	int i, ret;
-
-	ATH5K_TRACE(ah->ah_sc);
-
-	s_ant = 0;
-	ee_mode = 0;
-	staid1_flags = 0;
-	tsf_up = 0;
-	tsf_lo = 0;
-	freq = 0;
-	mode = 0;
-
-	/*
-	 * Save some registers before a reset
-	 */
-	/*DCU/Antenna selection not available on 5210*/
-	if (ah->ah_version != AR5K_AR5210) {
-
-		switch (channel->hw_value & CHANNEL_MODES) {
-		case CHANNEL_A:
-			mode = AR5K_MODE_11A;
-			freq = AR5K_INI_RFGAIN_5GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11A;
-			break;
-		case CHANNEL_G:
-			mode = AR5K_MODE_11G;
-			freq = AR5K_INI_RFGAIN_2GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11G;
-			break;
-		case CHANNEL_B:
-			mode = AR5K_MODE_11B;
-			freq = AR5K_INI_RFGAIN_2GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11B;
-			break;
-		case CHANNEL_T:
-			mode = AR5K_MODE_11A_TURBO;
-			freq = AR5K_INI_RFGAIN_5GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11A;
-			break;
-		case CHANNEL_TG:
-			if (ah->ah_version == AR5K_AR5211) {
-				ATH5K_ERR(ah->ah_sc,
-					"TurboG mode not available on 5211");
-				return -EINVAL;
-			}
-			mode = AR5K_MODE_11G_TURBO;
-			freq = AR5K_INI_RFGAIN_2GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11G;
-			break;
-		case CHANNEL_XR:
-			if (ah->ah_version == AR5K_AR5211) {
-				ATH5K_ERR(ah->ah_sc,
-					"XR mode not available on 5211");
-				return -EINVAL;
-			}
-			mode = AR5K_MODE_XR;
-			freq = AR5K_INI_RFGAIN_5GHZ;
-			ee_mode = AR5K_EEPROM_MODE_11A;
-			break;
-		default:
-			ATH5K_ERR(ah->ah_sc,
-				"invalid channel: %d\n", channel->center_freq);
-			return -EINVAL;
-		}
-
-		if (change_channel) {
-			/*
-			 * Save frame sequence count
-			 * For revs. after Oahu, only save
-			 * seq num for DCU 0 (Global seq num)
-			 */
-			if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
-
-				for (i = 0; i < 10; i++)
-					s_seq[i] = ath5k_hw_reg_read(ah,
-						AR5K_QUEUE_DCU_SEQNUM(i));
-
-			} else {
-				s_seq[0] = ath5k_hw_reg_read(ah,
-						AR5K_QUEUE_DCU_SEQNUM(0));
-			}
-
-			/* TSF accelerates on AR5211 durring reset
-			 * As a workaround save it here and restore
-			 * it later so that it's back in time after
-			 * reset. This way it'll get re-synced on the
-			 * next beacon without breaking ad-hoc.
-			 *
-			 * On AR5212 TSF is almost preserved across a
-			 * reset so it stays back in time anyway and
-			 * we don't have to save/restore it.
-			 *
-			 * XXX: Since this breaks power saving we have
-			 * to disable power saving until we receive the
-			 * next beacon, so we can resync beacon timers */
-			if (ah->ah_version == AR5K_AR5211) {
-				tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
-				tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
-			}
-		}
-
-		/* Save default antenna */
-		s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
-
-		if (ah->ah_version == AR5K_AR5212) {
-			/* Restore normal 32/40MHz clock operation
-			 * to avoid register access delay on certain
-			 * PHY registers */
-			ath5k_hw_set_sleep_clock(ah, false);
-
-			/* Since we are going to write rf buffer
-			 * check if we have any pending gain_F
-			 * optimization settings */
-			if (change_channel && ah->ah_rf_banks != NULL)
-				ath5k_hw_gainf_calibrate(ah);
-		}
-	}
-
-	/*GPIOs*/
-	s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
-					AR5K_PCICFG_LEDSTATE;
-	s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
-	s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
-
-	/* AR5K_STA_ID1 flags, only preserve antenna
-	 * settings and ack/cts rate mode */
-	staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
-			(AR5K_STA_ID1_DEFAULT_ANTENNA |
-			AR5K_STA_ID1_DESC_ANTENNA |
-			AR5K_STA_ID1_RTS_DEF_ANTENNA |
-			AR5K_STA_ID1_ACKCTS_6MB |
-			AR5K_STA_ID1_BASE_RATE_11B |
-			AR5K_STA_ID1_SELFGEN_DEF_ANT);
-
-	/* Wakeup the device */
-	ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
-	if (ret)
-		return ret;
-
-	/*
-	 * Initialize operating mode
-	 */
-	ah->ah_op_mode = op_mode;
-
-	/* PHY access enable */
-	if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
-		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
-	else
-		ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
-							AR5K_PHY(0));
-
-	/* Write initial settings */
-	ret = ath5k_hw_write_initvals(ah, mode, change_channel);
-	if (ret)
-		return ret;
-
-	/*
-	 * 5211/5212 Specific
-	 */
-	if (ah->ah_version != AR5K_AR5210) {
-
-		/*
-		 * Write initial RF gain settings
-		 * This should work for both 5111/5112
-		 */
-		ret = ath5k_hw_rfgain_init(ah, freq);
-		if (ret)
-			return ret;
-
-		mdelay(1);
-
-		/*
-		 * Tweak initval settings for revised
-		 * chipsets and add some more config
-		 * bits
-		 */
-		ath5k_hw_tweak_initval_settings(ah, channel);
-
-		/*
-		 * Set TX power (FIXME)
-		 */
-		ret = ath5k_hw_txpower(ah, channel, ee_mode,
-					AR5K_TUNE_DEFAULT_TXPOWER);
-		if (ret)
-			return ret;
-
-		/* Write rate duration table only on AR5212 and if
-		 * virtual interface has already been brought up
-		 * XXX: rethink this after new mode changes to
-		 * mac80211 are integrated */
-		if (ah->ah_version == AR5K_AR5212 &&
-			ah->ah_sc->vif != NULL)
-			ath5k_hw_write_rate_duration(ah, mode);
-
-		/*
-		 * Write RF buffer
-		 */
-		ret = ath5k_hw_rfregs_init(ah, channel, mode);
-		if (ret)
-			return ret;
-
-
-		/* Write OFDM timings on 5212*/
-		if (ah->ah_version == AR5K_AR5212 &&
-			channel->hw_value & CHANNEL_OFDM) {
-			ret = ath5k_hw_write_ofdm_timings(ah, channel);
-			if (ret)
-				return ret;
-		}
-
-		/*Enable/disable 802.11b mode on 5111
-		(enable 2111 frequency converter + CCK)*/
-		if (ah->ah_radio == AR5K_RF5111) {
-			if (mode == AR5K_MODE_11B)
-				AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
-				    AR5K_TXCFG_B_MODE);
-			else
-				AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
-				    AR5K_TXCFG_B_MODE);
-		}
-
-		/*
-		 * In case a fixed antenna was set as default
-		 * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
-		 * registers.
-		 */
-		if (s_ant != 0) {
-			if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
-				ant[0] = ant[1] = AR5K_ANT_FIXED_A;
-			else	/* 2 - Aux */
-				ant[0] = ant[1] = AR5K_ANT_FIXED_B;
-		} else {
-			ant[0] = AR5K_ANT_FIXED_A;
-			ant[1] = AR5K_ANT_FIXED_B;
-		}
-
-		/* Commit values from EEPROM */
-		ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);
-
-	} else {
-		/*
-		 * For 5210 we do all initialization using
-		 * initvals, so we don't have to modify
-		 * any settings (5210 also only supports
-		 * a/aturbo modes)
-		 */
-		mdelay(1);
-		/* Disable phy and wait */
-		ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
-		mdelay(1);
-	}
-
-	/*
-	 * Restore saved values
-	 */
-
-	/*DCU/Antenna selection not available on 5210*/
-	if (ah->ah_version != AR5K_AR5210) {
-
-		if (change_channel) {
-			if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
-				for (i = 0; i < 10; i++)
-					ath5k_hw_reg_write(ah, s_seq[i],
-						AR5K_QUEUE_DCU_SEQNUM(i));
-			} else {
-				ath5k_hw_reg_write(ah, s_seq[0],
-					AR5K_QUEUE_DCU_SEQNUM(0));
-			}
-
-
-			if (ah->ah_version == AR5K_AR5211) {
-				ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
-				ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
-			}
-		}
-
-		ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
-	}
-
-	/* Ledstate */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
-
-	/* Gpio settings */
-	ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
-	ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
-
-	/* Restore sta_id flags and preserve our mac address*/
-	ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id),
-						AR5K_STA_ID0);
-	ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id),
-						AR5K_STA_ID1);
-
-
-	/*
-	 * Configure PCU
-	 */
-
-	/* Restore bssid and bssid mask */
-	/* XXX: add ah->aid once mac80211 gives this to us */
-	ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
-
-	/* Set PCU config */
-	ath5k_hw_set_opmode(ah);
-
-	/* Clear any pending interrupts
-	 * PISR/SISR Not available on 5210 */
-	if (ah->ah_version != AR5K_AR5210)
-		ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
-
-	/* Set RSSI/BRSSI thresholds
-	 *
-	 * Note: If we decide to set this value
-	 * dynamicaly, have in mind that when AR5K_RSSI_THR
-	 * register is read it might return 0x40 if we haven't
-	 * wrote anything to it plus BMISS RSSI threshold is zeroed.
-	 * So doing a save/restore procedure here isn't the right
-	 * choice. Instead store it on ath5k_hw */
-	ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
-				AR5K_TUNE_BMISS_THRES <<
-				AR5K_RSSI_THR_BMISS_S),
-				AR5K_RSSI_THR);
-
-	/* MIC QoS support */
-	if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
-		ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
-		ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
-	}
-
-	/* QoS NOACK Policy */
-	if (ah->ah_version == AR5K_AR5212) {
-		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
-			AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET)  |
-			AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
-			AR5K_QOS_NOACK);
-	}
-
-
-	/*
-	 * Configure PHY
-	 */
-
-	/* Set channel on PHY */
-	ret = ath5k_hw_channel(ah, channel);
-	if (ret)
-		return ret;
-
-	/*
-	 * Enable the PHY and wait until completion
-	 * This includes BaseBand and Synthesizer
-	 * activation.
-	 */
-	ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
-
-	/*
-	 * On 5211+ read activation -> rx delay
-	 * and use it.
-	 *
-	 * TODO: Half/quarter rate support
-	 */
-	if (ah->ah_version != AR5K_AR5210) {
-		u32 delay;
-		delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
-			AR5K_PHY_RX_DELAY_M;
-		delay = (channel->hw_value & CHANNEL_CCK) ?
-			((delay << 2) / 22) : (delay / 10);
-
-		udelay(100 + (2 * delay));
-	} else {
-		mdelay(1);
-	}
-
-	/*
-	 * Perform ADC test to see if baseband is ready
-	 * Set tx hold and check adc test register
-	 */
-	phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
-	ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
-	for (i = 0; i <= 20; i++) {
-		if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
-			break;
-		udelay(200);
-	}
-	ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
-
-	/*
-	 * Start automatic gain control calibration
-	 *
-	 * During AGC calibration RX path is re-routed to
-	 * a power detector so we don't receive anything.
-	 *
-	 * This method is used to calibrate some static offsets
-	 * used together with on-the fly I/Q calibration (the
-	 * one performed via ath5k_hw_phy_calibrate), that doesn't
-	 * interrupt rx path.
-	 *
-	 * While rx path is re-routed to the power detector we also
-	 * start a noise floor calibration, to measure the
-	 * card's noise floor (the noise we measure when we are not
-	 * transmiting or receiving anything).
-	 *
-	 * If we are in a noisy environment AGC calibration may time
-	 * out and/or noise floor calibration might timeout.
-	 */
-	AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
-				AR5K_PHY_AGCCTL_CAL);
-
-	/* At the same time start I/Q calibration for QAM constellation
-	 * -no need for CCK- */
-	ah->ah_calibration = false;
-	if (!(mode == AR5K_MODE_11B)) {
-		ah->ah_calibration = true;
-		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
-				AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
-		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
-				AR5K_PHY_IQ_RUN);
-	}
-
-	/* Wait for gain calibration to finish (we check for I/Q calibration
-	 * during ath5k_phy_calibrate) */
-	if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-			AR5K_PHY_AGCCTL_CAL, 0, false)) {
-		ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
-			channel->center_freq);
-	}
-
-	/*
-	 * If we run NF calibration before AGC, it always times out.
-	 * Binary HAL starts NF and AGC calibration at the same time
-	 * and only waits for AGC to finish. Also if AGC or NF cal.
-	 * times out, reset doesn't fail on binary HAL. I believe
-	 * that's wrong because since rx path is routed to a detector,
-	 * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
-	 * enables noise floor calibration after offset calibration and if noise
-	 * floor calibration fails, reset fails. I believe that's
-	 * a better approach, we just need to find a polling interval
-	 * that suits best, even if reset continues we need to make
-	 * sure that rx path is ready.
-	 */
-	ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
-
-
-	/*
-	 * Configure QCUs/DCUs
-	 */
-
-	/* TODO: HW Compression support for data queues */
-	/* TODO: Burst prefetch for data queues */
-
-	/*
-	 * Reset queues and start beacon timers at the end of the reset routine
-	 * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
-	 * Note: If we want we can assign multiple qcus on one dcu.
-	 */
-	for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
-		ret = ath5k_hw_reset_tx_queue(ah, i);
-		if (ret) {
-			ATH5K_ERR(ah->ah_sc,
-				"failed to reset TX queue #%d\n", i);
-			return ret;
-		}
-	}
-
-
-	/*
-	 * Configure DMA/Interrupts
-	 */
-
-	/*
-	 * Set Rx/Tx DMA Configuration
-	 *
-	 * Set standard DMA size (128). Note that
-	 * a DMA size of 512 causes rx overruns and tx errors
-	 * on pci-e cards (tested on 5424 but since rx overruns
-	 * also occur on 5416/5418 with madwifi we set 128
-	 * for all PCI-E cards to be safe).
-	 *
-	 * XXX: need to check 5210 for this
-	 * TODO: Check out tx triger level, it's always 64 on dumps but I
-	 * guess we can tweak it and see how it goes ;-)
-	 */
-	if (ah->ah_version != AR5K_AR5210) {
-		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
-			AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
-		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
-			AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
-	}
-
-	/* Pre-enable interrupts on 5211/5212*/
-	if (ah->ah_version != AR5K_AR5210)
-		ath5k_hw_set_imr(ah, ah->ah_imr);
-
-	/*
-	 * Setup RFKill interrupt if rfkill flag is set on eeprom.
-	 * TODO: Use gpio pin and polarity infos from eeprom
-	 * TODO: Handle this in ath5k_intr because it'll result
-	 * 	 a nasty interrupt storm.
-	 */
-#if 0
-	if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
-		ath5k_hw_set_gpio_input(ah, 0);
-		ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
-		if (ah->ah_gpio[0] == 0)
-			ath5k_hw_set_gpio_intr(ah, 0, 1);
-		else
-			ath5k_hw_set_gpio_intr(ah, 0, 0);
-	}
-#endif
-
-	/* Enable 32KHz clock function for AR5212+ chips
-	 * Set clocks to 32KHz operation and use an
-	 * external 32KHz crystal when sleeping if one
-	 * exists */
-	if (ah->ah_version == AR5K_AR5212)
-			ath5k_hw_set_sleep_clock(ah, true);
-
-	/*
-	 * Disable beacons and reset the register
-	 */
-	AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
-			AR5K_BEACON_RESET_TSF);
-
-	return 0;
-}
-
-#undef _ATH5K_RESET
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/rfbuffer.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/rfbuffer.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/rfbuffer.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/rfbuffer.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1181 +0,0 @@
-/*
- * RF Buffer handling functions
- *
- * Copyright (c) 2009 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-
-/*
- * There are some special registers on the RF chip
- * that control various operation settings related mostly to
- * the analog parts (channel, gain adjustment etc).
- *
- * We don't write on those registers directly but
- * we send a data packet on the chip, using a special register,
- * that holds all the settings we need. After we 've sent the
- * data packet, we write on another special register to notify hw
- * to apply the settings. This is done so that control registers
- * can be dynamicaly programmed during operation and the settings
- * are applied faster on the hw.
- *
- * We call each data packet an "RF Bank" and all the data we write
- * (all RF Banks) "RF Buffer". This file holds initial RF Buffer
- * data for the different RF chips, and various info to match RF
- * Buffer offsets with specific RF registers so that we can access
- * them. We tweak these settings on rfregs_init function.
- *
- * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer
- * registers and control registers):
- *
- * http://www.google.com/patents?id=qNURAAAAEBAJ
- */
-
-
-/*
- * Struct to hold default mode specific RF
- * register values (RF Banks)
- */
-struct ath5k_ini_rfbuffer {
-	u8	rfb_bank;		/* RF Bank number */
-	u16	rfb_ctrl_register;	/* RF Buffer control register */
-	u32	rfb_mode_data[5];	/* RF Buffer data for each mode */
-};
-
-/*
- * Struct to hold RF Buffer field
- * infos used to access certain RF
- * analog registers
- */
-struct ath5k_rfb_field {
-	u8	len;	/* Field length */
-	u16	pos;	/* Offset on the raw packet */
-	u8	col;	/* Column -used for shifting */
-};
-
-/*
- * RF analog register definition
- */
-struct ath5k_rf_reg {
-	u8			bank;	/* RF Buffer Bank number */
-	u8			index;	/* Register's index on rf_regs_idx */
-	struct ath5k_rfb_field	field;	/* RF Buffer field for this register */
-};
-
-/* Map RF registers to indexes
- * We do this to handle common bits and make our
- * life easier by using an index for each register
- * instead of a full rfb_field */
-enum ath5k_rf_regs_idx {
-	/* BANK 6 */
-	AR5K_RF_OB_2GHZ = 0,
-	AR5K_RF_OB_5GHZ,
-	AR5K_RF_DB_2GHZ,
-	AR5K_RF_DB_5GHZ,
-	AR5K_RF_FIXED_BIAS_A,
-	AR5K_RF_FIXED_BIAS_B,
-	AR5K_RF_PWD_XPD,
-	AR5K_RF_XPD_SEL,
-	AR5K_RF_XPD_GAIN,
-	AR5K_RF_PD_GAIN_LO,
-	AR5K_RF_PD_GAIN_HI,
-	AR5K_RF_HIGH_VC_CP,
-	AR5K_RF_MID_VC_CP,
-	AR5K_RF_LOW_VC_CP,
-	AR5K_RF_PUSH_UP,
-	AR5K_RF_PAD2GND,
-	AR5K_RF_XB2_LVL,
-	AR5K_RF_XB5_LVL,
-	AR5K_RF_PWD_ICLOBUF_2G,
-	AR5K_RF_PWD_84,
-	AR5K_RF_PWD_90,
-	AR5K_RF_PWD_130,
-	AR5K_RF_PWD_131,
-	AR5K_RF_PWD_132,
-	AR5K_RF_PWD_136,
-	AR5K_RF_PWD_137,
-	AR5K_RF_PWD_138,
-	AR5K_RF_PWD_166,
-	AR5K_RF_PWD_167,
-	AR5K_RF_DERBY_CHAN_SEL_MODE,
-	/* BANK 7 */
-	AR5K_RF_GAIN_I,
-	AR5K_RF_PLO_SEL,
-	AR5K_RF_RFGAIN_SEL,
-	AR5K_RF_RFGAIN_STEP,
-	AR5K_RF_WAIT_S,
-	AR5K_RF_WAIT_I,
-	AR5K_RF_MAX_TIME,
-	AR5K_RF_MIXVGA_OVR,
-	AR5K_RF_MIXGAIN_OVR,
-	AR5K_RF_MIXGAIN_STEP,
-	AR5K_RF_PD_DELAY_A,
-	AR5K_RF_PD_DELAY_B,
-	AR5K_RF_PD_DELAY_XR,
-	AR5K_RF_PD_PERIOD_A,
-	AR5K_RF_PD_PERIOD_B,
-	AR5K_RF_PD_PERIOD_XR,
-};
-
-
-/*******************\
-* RF5111 (Sombrero) *
-\*******************/
-
-/* BANK 6				len  pos col */
-#define	AR5K_RF5111_OB_2GHZ		{ 3, 119, 0 }
-#define	AR5K_RF5111_DB_2GHZ		{ 3, 122, 0 }
-
-#define	AR5K_RF5111_OB_5GHZ		{ 3, 104, 0 }
-#define	AR5K_RF5111_DB_5GHZ		{ 3, 107, 0 }
-
-#define	AR5K_RF5111_PWD_XPD		{ 1, 95,  0 }
-#define	AR5K_RF5111_XPD_GAIN		{ 4, 96,  0 }
-
-/* Access to PWD registers */
-#define AR5K_RF5111_PWD(_n)		{ 1, (135 - _n), 3 }
-
-/* BANK 7				len  pos col */
-#define	AR5K_RF5111_GAIN_I		{ 6, 29,  0 }
-#define	AR5K_RF5111_PLO_SEL		{ 1, 4,   0 }
-#define	AR5K_RF5111_RFGAIN_SEL		{ 1, 36,  0 }
-#define AR5K_RF5111_RFGAIN_STEP		{ 6, 37,  0 }
-/* Only on AR5212 BaseBand and up */
-#define	AR5K_RF5111_WAIT_S		{ 5, 19,  0 }
-#define	AR5K_RF5111_WAIT_I		{ 5, 24,  0 }
-#define	AR5K_RF5111_MAX_TIME		{ 2, 49,  0 }
-
-static const struct ath5k_rf_reg rf_regs_5111[] = {
-	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5111_OB_2GHZ},
-	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5111_DB_2GHZ},
-	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5111_OB_5GHZ},
-	{6, AR5K_RF_DB_5GHZ,		AR5K_RF5111_DB_5GHZ},
-	{6, AR5K_RF_PWD_XPD,		AR5K_RF5111_PWD_XPD},
-	{6, AR5K_RF_XPD_GAIN,		AR5K_RF5111_XPD_GAIN},
-	{6, AR5K_RF_PWD_84,		AR5K_RF5111_PWD(84)},
-	{6, AR5K_RF_PWD_90,		AR5K_RF5111_PWD(90)},
-	{7, AR5K_RF_GAIN_I,		AR5K_RF5111_GAIN_I},
-	{7, AR5K_RF_PLO_SEL,		AR5K_RF5111_PLO_SEL},
-	{7, AR5K_RF_RFGAIN_SEL,		AR5K_RF5111_RFGAIN_SEL},
-	{7, AR5K_RF_RFGAIN_STEP,	AR5K_RF5111_RFGAIN_STEP},
-	{7, AR5K_RF_WAIT_S,		AR5K_RF5111_WAIT_S},
-	{7, AR5K_RF_WAIT_I,		AR5K_RF5111_WAIT_I},
-	{7, AR5K_RF_MAX_TIME,		AR5K_RF5111_MAX_TIME}
-};
-
-/* Default mode specific settings */
-static const struct ath5k_ini_rfbuffer rfb_5111[] = {
-	{ 0, 0x989c,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 0, 0x989c,
-	    { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
-	{ 0, 0x989c,
-	    { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
-	{ 0, 0x98d4,
-	    { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
-	{ 1, 0x98d4,
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d4,
-	    { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
-	{ 3, 0x98d8,
-	    { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
-	{ 6, 0x989c,
-	    { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
-	{ 6, 0x989c,
-	    { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
-	{ 6, 0x989c,
-	    { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
-	{ 6, 0x989c,
-	    { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
-	{ 6, 0x98d4,
-	    { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
-	{ 7, 0x989c,
-	    { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
-	{ 7, 0x989c,
-	    { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
-	{ 7, 0x989c,
-	    { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
-	{ 7, 0x989c,
-	    { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
-	{ 7, 0x989c,
-	    { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
-	{ 7, 0x989c,
-	    { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
-	{ 7, 0x989c,
-	    { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
-};
-
-
-
-/***********************\
-* RF5112/RF2112 (Derby) *
-\***********************/
-
-/* BANK 7 (Common)			len  pos col */
-#define	AR5K_RF5112X_GAIN_I		{ 6, 14,  0 }
-#define	AR5K_RF5112X_MIXVGA_OVR		{ 1, 36,  0 }
-#define	AR5K_RF5112X_MIXGAIN_OVR	{ 2, 37,  0 }
-#define AR5K_RF5112X_MIXGAIN_STEP	{ 4, 32,  0 }
-#define	AR5K_RF5112X_PD_DELAY_A		{ 4, 58,  0 }
-#define	AR5K_RF5112X_PD_DELAY_B		{ 4, 62,  0 }
-#define	AR5K_RF5112X_PD_DELAY_XR	{ 4, 66,  0 }
-#define	AR5K_RF5112X_PD_PERIOD_A	{ 4, 70,  0 }
-#define	AR5K_RF5112X_PD_PERIOD_B	{ 4, 74,  0 }
-#define	AR5K_RF5112X_PD_PERIOD_XR	{ 4, 78,  0 }
-
-/* RFX112 (Derby 1) */
-
-/* BANK 6 				len  pos col */
-#define	AR5K_RF5112_OB_2GHZ		{ 3, 269, 0 }
-#define	AR5K_RF5112_DB_2GHZ		{ 3, 272, 0 }
-
-#define	AR5K_RF5112_OB_5GHZ		{ 3, 261, 0 }
-#define	AR5K_RF5112_DB_5GHZ		{ 3, 264, 0 }
-
-#define	AR5K_RF5112_FIXED_BIAS_A	{ 1, 260, 0 }
-#define	AR5K_RF5112_FIXED_BIAS_B	{ 1, 259, 0 }
-
-#define	AR5K_RF5112_XPD_SEL		{ 1, 284, 0 }
-#define	AR5K_RF5112_XPD_GAIN		{ 2, 252, 0 }
-
-/* Access to PWD registers */
-#define AR5K_RF5112_PWD(_n)		{ 1, (302 - _n), 3 }
-
-static const struct ath5k_rf_reg rf_regs_5112[] = {
-	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5112_OB_2GHZ},
-	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5112_DB_2GHZ},
-	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5112_OB_5GHZ},
-	{6, AR5K_RF_DB_5GHZ,		AR5K_RF5112_DB_5GHZ},
-	{6, AR5K_RF_FIXED_BIAS_A,	AR5K_RF5112_FIXED_BIAS_A},
-	{6, AR5K_RF_FIXED_BIAS_B,	AR5K_RF5112_FIXED_BIAS_B},
-	{6, AR5K_RF_XPD_SEL,		AR5K_RF5112_XPD_SEL},
-	{6, AR5K_RF_XPD_GAIN,		AR5K_RF5112_XPD_GAIN},
-	{6, AR5K_RF_PWD_130,		AR5K_RF5112_PWD(130)},
-	{6, AR5K_RF_PWD_131,		AR5K_RF5112_PWD(131)},
-	{6, AR5K_RF_PWD_132,		AR5K_RF5112_PWD(132)},
-	{6, AR5K_RF_PWD_136,		AR5K_RF5112_PWD(136)},
-	{6, AR5K_RF_PWD_137,		AR5K_RF5112_PWD(137)},
-	{6, AR5K_RF_PWD_138,		AR5K_RF5112_PWD(138)},
-	{7, AR5K_RF_GAIN_I,		AR5K_RF5112X_GAIN_I},
-	{7, AR5K_RF_MIXVGA_OVR,		AR5K_RF5112X_MIXVGA_OVR},
-	{7, AR5K_RF_MIXGAIN_OVR,	AR5K_RF5112X_MIXGAIN_OVR},
-	{7, AR5K_RF_MIXGAIN_STEP,	AR5K_RF5112X_MIXGAIN_STEP},
-	{7, AR5K_RF_PD_DELAY_A,		AR5K_RF5112X_PD_DELAY_A},
-	{7, AR5K_RF_PD_DELAY_B,		AR5K_RF5112X_PD_DELAY_B},
-	{7, AR5K_RF_PD_DELAY_XR,	AR5K_RF5112X_PD_DELAY_XR},
-	{7, AR5K_RF_PD_PERIOD_A,	AR5K_RF5112X_PD_PERIOD_A},
-	{7, AR5K_RF_PD_PERIOD_B,	AR5K_RF5112X_PD_PERIOD_B},
-	{7, AR5K_RF_PD_PERIOD_XR,	AR5K_RF5112X_PD_PERIOD_XR},
-};
-
-/* Default mode specific settings */
-static const struct ath5k_ini_rfbuffer rfb_5112[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
-	{ 3, 0x98dc,
-	    { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
-	{ 6, 0x989c,
-	    { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
-	{ 6, 0x989c,
-	    { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
-	{ 6, 0x989c,
-	    { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
-	{ 6, 0x989c,
-	    { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
-	{ 6, 0x989c,
-	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
-	{ 6, 0x989c,
-	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
-	{ 6, 0x989c,
-	    { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
-	{ 6, 0x989c,
-	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
-	{ 6, 0x989c,
-	    { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
-	{ 6, 0x989c,
-	    { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
-	{ 6, 0x989c,
-	    { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
-	{ 6, 0x989c,
-	    { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
-	{ 6, 0x989c,
-	    { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
-	{ 6, 0x989c,
-	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
-	{ 6, 0x989c,
-	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
-	{ 6, 0x989c,
-	    { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
-	{ 6, 0x989c,
-	    { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
-	{ 6, 0x989c,
-	    { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
-	{ 6, 0x989c,
-	    { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
-	{ 6, 0x989c,
-	    { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
-	{ 6, 0x989c,
-	    { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
-	{ 6, 0x989c,
-	    { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
-	{ 6, 0x989c,
-	    { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
-	{ 6, 0x989c,
-	    { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
-	{ 6, 0x989c,
-	    { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
-	{ 6, 0x989c,
-	    { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
-	{ 6, 0x989c,
-	    { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
-	{ 6, 0x989c,
-	    { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
-	{ 6, 0x98d0,
-	    { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
-	{ 7, 0x989c,
-	    { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
-	{ 7, 0x989c,
-	    { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
-	{ 7, 0x989c,
-	    { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
-	{ 7, 0x989c,
-	    { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
-	{ 7, 0x989c,
-	    { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
-	{ 7, 0x989c,
-	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
-	{ 7, 0x989c,
-	    { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
-	{ 7, 0x989c,
-	    { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
-	{ 7, 0x989c,
-	    { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
-	{ 7, 0x989c,
-	    { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
-	{ 7, 0x989c,
-	    { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
-	{ 7, 0x989c,
-	    { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
-	{ 7, 0x98c4,
-	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
-};
-
-/* RFX112A (Derby 2) */
-
-/* BANK 6				len  pos col */
-#define	AR5K_RF5112A_OB_2GHZ		{ 3, 287, 0 }
-#define	AR5K_RF5112A_DB_2GHZ		{ 3, 290, 0 }
-
-#define	AR5K_RF5112A_OB_5GHZ		{ 3, 279, 0 }
-#define	AR5K_RF5112A_DB_5GHZ		{ 3, 282, 0 }
-
-#define	AR5K_RF5112A_FIXED_BIAS_A	{ 1, 278, 0 }
-#define	AR5K_RF5112A_FIXED_BIAS_B	{ 1, 277, 0 }
-
-#define	AR5K_RF5112A_XPD_SEL		{ 1, 302, 0 }
-#define	AR5K_RF5112A_PDGAINLO		{ 2, 270, 0 }
-#define	AR5K_RF5112A_PDGAINHI		{ 2, 257, 0 }
-
-/* Access to PWD registers */
-#define AR5K_RF5112A_PWD(_n)		{ 1, (306 - _n), 3 }
-
-/* Voltage regulators */
-#define	AR5K_RF5112A_HIGH_VC_CP		{ 2, 90,  2 }
-#define	AR5K_RF5112A_MID_VC_CP		{ 2, 92,  2 }
-#define	AR5K_RF5112A_LOW_VC_CP		{ 2, 94,  2 }
-#define	AR5K_RF5112A_PUSH_UP		{ 1, 254,  2 }
-
-/* Power consumption */
-#define	AR5K_RF5112A_PAD2GND		{ 1, 281, 1 }
-#define	AR5K_RF5112A_XB2_LVL		{ 2, 1,	  3 }
-#define	AR5K_RF5112A_XB5_LVL		{ 2, 3,	  3 }
-
-static const struct ath5k_rf_reg rf_regs_5112a[] = {
-	{6, AR5K_RF_OB_2GHZ,		AR5K_RF5112A_OB_2GHZ},
-	{6, AR5K_RF_DB_2GHZ,		AR5K_RF5112A_DB_2GHZ},
-	{6, AR5K_RF_OB_5GHZ,		AR5K_RF5112A_OB_5GHZ},
-	{6, AR5K_RF_DB_5GHZ,		AR5K_RF5112A_DB_5GHZ},
-	{6, AR5K_RF_FIXED_BIAS_A,	AR5K_RF5112A_FIXED_BIAS_A},
-	{6, AR5K_RF_FIXED_BIAS_B,	AR5K_RF5112A_FIXED_BIAS_B},
-	{6, AR5K_RF_XPD_SEL,		AR5K_RF5112A_XPD_SEL},
-	{6, AR5K_RF_PD_GAIN_LO,		AR5K_RF5112A_PDGAINLO},
-	{6, AR5K_RF_PD_GAIN_HI,		AR5K_RF5112A_PDGAINHI},
-	{6, AR5K_RF_PWD_130,		AR5K_RF5112A_PWD(130)},
-	{6, AR5K_RF_PWD_131,		AR5K_RF5112A_PWD(131)},
-	{6, AR5K_RF_PWD_132,		AR5K_RF5112A_PWD(132)},
-	{6, AR5K_RF_PWD_136,		AR5K_RF5112A_PWD(136)},
-	{6, AR5K_RF_PWD_137,		AR5K_RF5112A_PWD(137)},
-	{6, AR5K_RF_PWD_138,		AR5K_RF5112A_PWD(138)},
-	{6, AR5K_RF_PWD_166,		AR5K_RF5112A_PWD(166)},
-	{6, AR5K_RF_PWD_167,		AR5K_RF5112A_PWD(167)},
-	{6, AR5K_RF_HIGH_VC_CP,		AR5K_RF5112A_HIGH_VC_CP},
-	{6, AR5K_RF_MID_VC_CP,		AR5K_RF5112A_MID_VC_CP},
-	{6, AR5K_RF_LOW_VC_CP,		AR5K_RF5112A_LOW_VC_CP},
-	{6, AR5K_RF_PUSH_UP,		AR5K_RF5112A_PUSH_UP},
-	{6, AR5K_RF_PAD2GND,		AR5K_RF5112A_PAD2GND},
-	{6, AR5K_RF_XB2_LVL,		AR5K_RF5112A_XB2_LVL},
-	{6, AR5K_RF_XB5_LVL,		AR5K_RF5112A_XB5_LVL},
-	{7, AR5K_RF_GAIN_I,		AR5K_RF5112X_GAIN_I},
-	{7, AR5K_RF_MIXVGA_OVR,		AR5K_RF5112X_MIXVGA_OVR},
-	{7, AR5K_RF_MIXGAIN_OVR,	AR5K_RF5112X_MIXGAIN_OVR},
-	{7, AR5K_RF_MIXGAIN_STEP,	AR5K_RF5112X_MIXGAIN_STEP},
-	{7, AR5K_RF_PD_DELAY_A,		AR5K_RF5112X_PD_DELAY_A},
-	{7, AR5K_RF_PD_DELAY_B,		AR5K_RF5112X_PD_DELAY_B},
-	{7, AR5K_RF_PD_DELAY_XR,	AR5K_RF5112X_PD_DELAY_XR},
-	{7, AR5K_RF_PD_PERIOD_A,	AR5K_RF5112X_PD_PERIOD_A},
-	{7, AR5K_RF_PD_PERIOD_B,	AR5K_RF5112X_PD_PERIOD_B},
-	{7, AR5K_RF_PD_PERIOD_XR,	AR5K_RF5112X_PD_PERIOD_XR},
-};
-
-/* Default mode specific settings */
-static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
-	{ 6, 0x989c,
-	    { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
-	{ 6, 0x989c,
-	    { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
-	{ 6, 0x989c,
-	    { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
-	{ 6, 0x989c,
-	    { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
-	{ 6, 0x989c,
-	    { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } },
-	{ 6, 0x989c,
-	    { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
-	{ 6, 0x989c,
-	    { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
-	{ 6, 0x989c,
-	    { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } },
-	{ 6, 0x989c,
-	    { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
-	{ 6, 0x989c,
-	    { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
-	{ 6, 0x989c,
-	    { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
-	{ 6, 0x989c,
-	    { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
-	{ 6, 0x989c,
-	    { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
-	{ 6, 0x989c,
-	    { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
-	{ 6, 0x989c,
-	    { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
-	{ 6, 0x989c,
-	    { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
-	{ 6, 0x989c,
-	    { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
-	{ 6, 0x989c,
-	    { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } },
-	{ 6, 0x989c,
-	    { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } },
-	{ 6, 0x989c,
-	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
-	{ 6, 0x989c,
-	    { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
-	{ 6, 0x989c,
-	    { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
-	{ 6, 0x989c,
-	    { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
-	{ 6, 0x989c,
-	    { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
-	{ 6, 0x98d8,
-	    { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
-	{ 7, 0x989c,
-	    { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
-	{ 7, 0x989c,
-	    { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
-	{ 7, 0x989c,
-	    { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
-	{ 7, 0x989c,
-	    { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
-	{ 7, 0x989c,
-	    { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
-	{ 7, 0x989c,
-	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
-	{ 7, 0x989c,
-	    { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
-	{ 7, 0x989c,
-	    { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
-	{ 7, 0x989c,
-	    { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
-	{ 7, 0x989c,
-	    { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
-	{ 7, 0x989c,
-	    { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
-	{ 7, 0x989c,
-	    { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
-	{ 7, 0x98c4,
-	    { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
-};
-
-
-
-/******************\
-* RF2413 (Griffin) *
-\******************/
-
-/* BANK 6 				len  pos col */
-#define	AR5K_RF2413_OB_2GHZ		{ 3, 168, 0 }
-#define	AR5K_RF2413_DB_2GHZ		{ 3, 165, 0 }
-
-static const struct ath5k_rf_reg rf_regs_2413[] = {
-	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2413_OB_2GHZ},
-	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2413_DB_2GHZ},
-};
-
-/* Default mode specific settings
- * XXX: a/aTurbo ???
- */
-static const struct ath5k_ini_rfbuffer rfb_2413[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } },
-	{ 6, 0x989c,
-	    { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } },
-	{ 6, 0x989c,
-	    { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } },
-	{ 6, 0x989c,
-	    { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } },
-	{ 6, 0x989c,
-	    { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } },
-	{ 6, 0x989c,
-	    { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } },
-	{ 6, 0x989c,
-	    { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
-	{ 6, 0x989c,
-	    { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } },
-	{ 6, 0x989c,
-	    { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } },
-	{ 6, 0x989c,
-	    { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } },
-	{ 6, 0x989c,
-	    { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } },
-	{ 6, 0x989c,
-	    { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } },
-	{ 6, 0x989c,
-	    { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } },
-	{ 6, 0x98d8,
-	    { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
-};
-
-
-
-/***************************\
-* RF2315/RF2316 (Cobra SoC) *
-\***************************/
-
-/* BANK 6				len  pos col */
-#define	AR5K_RF2316_OB_2GHZ		{ 3, 178, 0 }
-#define	AR5K_RF2316_DB_2GHZ		{ 3, 175, 0 }
-
-static const struct ath5k_rf_reg rf_regs_2316[] = {
-	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2316_OB_2GHZ},
-	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2316_DB_2GHZ},
-};
-
-/* Default mode specific settings */
-static const struct ath5k_ini_rfbuffer rfb_2316[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } },
-	{ 6, 0x989c,
-	    { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
-	{ 6, 0x989c,
-	    { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } },
-	{ 6, 0x989c,
-	    { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } },
-	{ 6, 0x989c,
-	    { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } },
-	{ 6, 0x989c,
-	    { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } },
-	{ 6, 0x989c,
-	    { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
-	{ 6, 0x989c,
-	    { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
-	{ 6, 0x989c,
-	    { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } },
-	{ 6, 0x989c,
-	    { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } },
-	{ 6, 0x989c,
-	    { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } },
-	{ 6, 0x989c,
-	    { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } },
-	{ 6, 0x989c,
-	    { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } },
-	{ 6, 0x989c,
-	    { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } },
-	{ 6, 0x989c,
-	    { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
-	{ 6, 0x989c,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 6, 0x989c,
-	    { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } },
-	{ 6, 0x989c,
-	    { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } },
-	{ 6, 0x98c0,
-	    { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
-};
-
-
-
-/******************************\
-* RF5413/RF5424 (Eagle/Condor) *
-\******************************/
-
-/* BANK 6				len  pos col */
-#define	AR5K_RF5413_OB_2GHZ		{ 3, 241, 0 }
-#define	AR5K_RF5413_DB_2GHZ		{ 3, 238, 0 }
-
-#define	AR5K_RF5413_OB_5GHZ		{ 3, 247, 0 }
-#define	AR5K_RF5413_DB_5GHZ		{ 3, 244, 0 }
-
-#define	AR5K_RF5413_PWD_ICLOBUF2G	{ 3, 131, 3 }
-#define	AR5K_RF5413_DERBY_CHAN_SEL_MODE	{ 1, 291, 2 }
-
-static const struct ath5k_rf_reg rf_regs_5413[] = {
-	{6, AR5K_RF_OB_2GHZ,		 AR5K_RF5413_OB_2GHZ},
-	{6, AR5K_RF_DB_2GHZ,		 AR5K_RF5413_DB_2GHZ},
-	{6, AR5K_RF_OB_5GHZ,		 AR5K_RF5413_OB_5GHZ},
-	{6, AR5K_RF_DB_5GHZ,		 AR5K_RF5413_DB_5GHZ},
-	{6, AR5K_RF_PWD_ICLOBUF_2G,	 AR5K_RF5413_PWD_ICLOBUF2G},
-	{6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE},
-};
-
-/* Default mode specific settings */
-static const struct ath5k_ini_rfbuffer rfb_5413[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
-	{ 3, 0x98dc,
-	    { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
-	{ 6, 0x989c,
-	    { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
-	{ 6, 0x989c,
-	    { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
-	{ 6, 0x989c,
-	    { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
-	{ 6, 0x989c,
-	    { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
-	{ 6, 0x989c,
-	    { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
-	{ 6, 0x989c,
-	    { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
-	{ 6, 0x989c,
-	    { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
-	{ 6, 0x989c,
-	    { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
-	{ 6, 0x989c,
-	    { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
-	{ 6, 0x989c,
-	    { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
-	{ 6, 0x989c,
-	    { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
-	{ 6, 0x989c,
-	    { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
-	{ 6, 0x989c,
-	    { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
-	{ 6, 0x989c,
-	    { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
-	{ 6, 0x989c,
-	    { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
-	{ 6, 0x989c,
-	    { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
-	{ 6, 0x989c,
-	    { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
-	{ 6, 0x989c,
-	    { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
-	{ 6, 0x989c,
-	    { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
-	{ 6, 0x989c,
-	    { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } },
-	{ 6, 0x989c,
-	    { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
-	{ 6, 0x989c,
-	    { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } },
-	{ 6, 0x98c8,
-	    { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
-};
-
-
-
-/***************************\
-* RF2425/RF2417 (Swan/Nala) *
-* AR2317 (Spider SoC)       *
-\***************************/
-
-/* BANK 6				len  pos col */
-#define	AR5K_RF2425_OB_2GHZ		{ 3, 193, 0 }
-#define	AR5K_RF2425_DB_2GHZ		{ 3, 190, 0 }
-
-static const struct ath5k_rf_reg rf_regs_2425[] = {
-	{6, AR5K_RF_OB_2GHZ,		AR5K_RF2425_OB_2GHZ},
-	{6, AR5K_RF_DB_2GHZ,		AR5K_RF2425_DB_2GHZ},
-};
-
-/* Default mode specific settings
- * XXX: a/aTurbo ?
- */
-static const struct ath5k_ini_rfbuffer rfb_2425[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
-	{ 6, 0x989c,
-	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
-	{ 6, 0x989c,
-	    { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
-	{ 6, 0x989c,
-	    { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
-	{ 6, 0x989c,
-	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
-	{ 6, 0x989c,
-	    { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
-	{ 6, 0x989c,
-	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
-	{ 6, 0x989c,
-	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
-	{ 6, 0x989c,
-	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
-	{ 6, 0x989c,
-	    { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
-	{ 6, 0x98c4,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
-};
-
-/*
- * TODO: Handle the few differences with swan during
- * bank modification and get rid of this
- */
-static const struct ath5k_ini_rfbuffer rfb_2317[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
-	{ 6, 0x989c,
-	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
-	{ 6, 0x989c,
-	    { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
-	{ 6, 0x989c,
-	    { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } },
-	{ 6, 0x989c,
-	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
-	{ 6, 0x989c,
-	    { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
-	{ 6, 0x989c,
-	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
-	{ 6, 0x989c,
-	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
-	{ 6, 0x989c,
-	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
-	{ 6, 0x989c,
-	    { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } },
-	{ 6, 0x98c4,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
-};
-
-/*
- * TODO: Handle the few differences with swan during
- * bank modification and get rid of this
- * XXX: a/aTurbo ?
- */
-static const struct ath5k_ini_rfbuffer rfb_2417[] = {
-	{ 1, 0x98d4,
-	/*     mode a/XR  mode aTurbo    mode b     mode g    mode gTurbo */
-	    { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
-	{ 2, 0x98d0,
-	    { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
-	{ 3, 0x98dc,
-	    { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-	{ 6, 0x989c,
-	    { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
-	{ 6, 0x989c,
-	    { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
-	{ 6, 0x989c,
-	    { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
-	{ 6, 0x989c,
-	    { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
-	{ 6, 0x989c,
-	    { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } },
-	{ 6, 0x989c,
-	    { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
-	{ 6, 0x989c,
-	    { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
-	{ 6, 0x989c,
-	    { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } },
-	{ 6, 0x989c,
-	    { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
-	{ 6, 0x989c,
-	    { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
-	{ 6, 0x989c,
-	    { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
-	{ 6, 0x989c,
-	    { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
-	{ 6, 0x989c,
-	    { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
-	{ 6, 0x98c4,
-	    { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
-	{ 7, 0x989c,
-	    { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
-	{ 7, 0x989c,
-	    { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
-	{ 7, 0x98cc,
-	    { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
-};
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/rfgain.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/rfgain.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath5k/rfgain.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath5k/rfgain.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,516 +0,0 @@
-/*
- * RF Gain optimization
- *
- * Copyright (c) 2004-2009 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*
- * Mode-specific RF Gain table (64bytes) for RF5111/5112
- * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
- * RF Gain values are included in AR5K_AR5210_INI)
- */
-struct ath5k_ini_rfgain {
-	u16	rfg_register;	/* RF Gain register address */
-	u32	rfg_value[2];	/* [freq (see below)] */
-};
-
-/* Initial RF Gain settings for RF5111 */
-static const struct ath5k_ini_rfgain rfgain_5111[] = {
-	/*			      5Ghz	2Ghz	*/
-	{ AR5K_RF_GAIN(0),	{ 0x000001a9, 0x00000000 } },
-	{ AR5K_RF_GAIN(1),	{ 0x000001e9, 0x00000040 } },
-	{ AR5K_RF_GAIN(2),	{ 0x00000029, 0x00000080 } },
-	{ AR5K_RF_GAIN(3),	{ 0x00000069, 0x00000150 } },
-	{ AR5K_RF_GAIN(4),	{ 0x00000199, 0x00000190 } },
-	{ AR5K_RF_GAIN(5),	{ 0x000001d9, 0x000001d0 } },
-	{ AR5K_RF_GAIN(6),	{ 0x00000019, 0x00000010 } },
-	{ AR5K_RF_GAIN(7),	{ 0x00000059, 0x00000044 } },
-	{ AR5K_RF_GAIN(8),	{ 0x00000099, 0x00000084 } },
-	{ AR5K_RF_GAIN(9),	{ 0x000001a5, 0x00000148 } },
-	{ AR5K_RF_GAIN(10),	{ 0x000001e5, 0x00000188 } },
-	{ AR5K_RF_GAIN(11),	{ 0x00000025, 0x000001c8 } },
-	{ AR5K_RF_GAIN(12),	{ 0x000001c8, 0x00000014 } },
-	{ AR5K_RF_GAIN(13),	{ 0x00000008, 0x00000042 } },
-	{ AR5K_RF_GAIN(14),	{ 0x00000048, 0x00000082 } },
-	{ AR5K_RF_GAIN(15),	{ 0x00000088, 0x00000178 } },
-	{ AR5K_RF_GAIN(16),	{ 0x00000198, 0x000001b8 } },
-	{ AR5K_RF_GAIN(17),	{ 0x000001d8, 0x000001f8 } },
-	{ AR5K_RF_GAIN(18),	{ 0x00000018, 0x00000012 } },
-	{ AR5K_RF_GAIN(19),	{ 0x00000058, 0x00000052 } },
-	{ AR5K_RF_GAIN(20),	{ 0x00000098, 0x00000092 } },
-	{ AR5K_RF_GAIN(21),	{ 0x000001a4, 0x0000017c } },
-	{ AR5K_RF_GAIN(22),	{ 0x000001e4, 0x000001bc } },
-	{ AR5K_RF_GAIN(23),	{ 0x00000024, 0x000001fc } },
-	{ AR5K_RF_GAIN(24),	{ 0x00000064, 0x0000000a } },
-	{ AR5K_RF_GAIN(25),	{ 0x000000a4, 0x0000004a } },
-	{ AR5K_RF_GAIN(26),	{ 0x000000e4, 0x0000008a } },
-	{ AR5K_RF_GAIN(27),	{ 0x0000010a, 0x0000015a } },
-	{ AR5K_RF_GAIN(28),	{ 0x0000014a, 0x0000019a } },
-	{ AR5K_RF_GAIN(29),	{ 0x0000018a, 0x000001da } },
-	{ AR5K_RF_GAIN(30),	{ 0x000001ca, 0x0000000e } },
-	{ AR5K_RF_GAIN(31),	{ 0x0000000a, 0x0000004e } },
-	{ AR5K_RF_GAIN(32),	{ 0x0000004a, 0x0000008e } },
-	{ AR5K_RF_GAIN(33),	{ 0x0000008a, 0x0000015e } },
-	{ AR5K_RF_GAIN(34),	{ 0x000001ba, 0x0000019e } },
-	{ AR5K_RF_GAIN(35),	{ 0x000001fa, 0x000001de } },
-	{ AR5K_RF_GAIN(36),	{ 0x0000003a, 0x00000009 } },
-	{ AR5K_RF_GAIN(37),	{ 0x0000007a, 0x00000049 } },
-	{ AR5K_RF_GAIN(38),	{ 0x00000186, 0x00000089 } },
-	{ AR5K_RF_GAIN(39),	{ 0x000001c6, 0x00000179 } },
-	{ AR5K_RF_GAIN(40),	{ 0x00000006, 0x000001b9 } },
-	{ AR5K_RF_GAIN(41),	{ 0x00000046, 0x000001f9 } },
-	{ AR5K_RF_GAIN(42),	{ 0x00000086, 0x00000039 } },
-	{ AR5K_RF_GAIN(43),	{ 0x000000c6, 0x00000079 } },
-	{ AR5K_RF_GAIN(44),	{ 0x000000c6, 0x000000b9 } },
-	{ AR5K_RF_GAIN(45),	{ 0x000000c6, 0x000001bd } },
-	{ AR5K_RF_GAIN(46),	{ 0x000000c6, 0x000001fd } },
-	{ AR5K_RF_GAIN(47),	{ 0x000000c6, 0x0000003d } },
-	{ AR5K_RF_GAIN(48),	{ 0x000000c6, 0x0000007d } },
-	{ AR5K_RF_GAIN(49),	{ 0x000000c6, 0x000000bd } },
-	{ AR5K_RF_GAIN(50),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(51),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(52),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(53),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(54),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(55),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(56),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(57),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(58),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(59),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(60),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(61),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(62),	{ 0x000000c6, 0x000000fd } },
-	{ AR5K_RF_GAIN(63),	{ 0x000000c6, 0x000000fd } },
-};
-
-/* Initial RF Gain settings for RF5112 */
-static const struct ath5k_ini_rfgain rfgain_5112[] = {
-	/*			      5Ghz	2Ghz	*/
-	{ AR5K_RF_GAIN(0),	{ 0x00000007, 0x00000007 } },
-	{ AR5K_RF_GAIN(1),	{ 0x00000047, 0x00000047 } },
-	{ AR5K_RF_GAIN(2),	{ 0x00000087, 0x00000087 } },
-	{ AR5K_RF_GAIN(3),	{ 0x000001a0, 0x000001a0 } },
-	{ AR5K_RF_GAIN(4),	{ 0x000001e0, 0x000001e0 } },
-	{ AR5K_RF_GAIN(5),	{ 0x00000020, 0x00000020 } },
-	{ AR5K_RF_GAIN(6),	{ 0x00000060, 0x00000060 } },
-	{ AR5K_RF_GAIN(7),	{ 0x000001a1, 0x000001a1 } },
-	{ AR5K_RF_GAIN(8),	{ 0x000001e1, 0x000001e1 } },
-	{ AR5K_RF_GAIN(9),	{ 0x00000021, 0x00000021 } },
-	{ AR5K_RF_GAIN(10),	{ 0x00000061, 0x00000061 } },
-	{ AR5K_RF_GAIN(11),	{ 0x00000162, 0x00000162 } },
-	{ AR5K_RF_GAIN(12),	{ 0x000001a2, 0x000001a2 } },
-	{ AR5K_RF_GAIN(13),	{ 0x000001e2, 0x000001e2 } },
-	{ AR5K_RF_GAIN(14),	{ 0x00000022, 0x00000022 } },
-	{ AR5K_RF_GAIN(15),	{ 0x00000062, 0x00000062 } },
-	{ AR5K_RF_GAIN(16),	{ 0x00000163, 0x00000163 } },
-	{ AR5K_RF_GAIN(17),	{ 0x000001a3, 0x000001a3 } },
-	{ AR5K_RF_GAIN(18),	{ 0x000001e3, 0x000001e3 } },
-	{ AR5K_RF_GAIN(19),	{ 0x00000023, 0x00000023 } },
-	{ AR5K_RF_GAIN(20),	{ 0x00000063, 0x00000063 } },
-	{ AR5K_RF_GAIN(21),	{ 0x00000184, 0x00000184 } },
-	{ AR5K_RF_GAIN(22),	{ 0x000001c4, 0x000001c4 } },
-	{ AR5K_RF_GAIN(23),	{ 0x00000004, 0x00000004 } },
-	{ AR5K_RF_GAIN(24),	{ 0x000001ea, 0x0000000b } },
-	{ AR5K_RF_GAIN(25),	{ 0x0000002a, 0x0000004b } },
-	{ AR5K_RF_GAIN(26),	{ 0x0000006a, 0x0000008b } },
-	{ AR5K_RF_GAIN(27),	{ 0x000000aa, 0x000001ac } },
-	{ AR5K_RF_GAIN(28),	{ 0x000001ab, 0x000001ec } },
-	{ AR5K_RF_GAIN(29),	{ 0x000001eb, 0x0000002c } },
-	{ AR5K_RF_GAIN(30),	{ 0x0000002b, 0x00000012 } },
-	{ AR5K_RF_GAIN(31),	{ 0x0000006b, 0x00000052 } },
-	{ AR5K_RF_GAIN(32),	{ 0x000000ab, 0x00000092 } },
-	{ AR5K_RF_GAIN(33),	{ 0x000001ac, 0x00000193 } },
-	{ AR5K_RF_GAIN(34),	{ 0x000001ec, 0x000001d3 } },
-	{ AR5K_RF_GAIN(35),	{ 0x0000002c, 0x00000013 } },
-	{ AR5K_RF_GAIN(36),	{ 0x0000003a, 0x00000053 } },
-	{ AR5K_RF_GAIN(37),	{ 0x0000007a, 0x00000093 } },
-	{ AR5K_RF_GAIN(38),	{ 0x000000ba, 0x00000194 } },
-	{ AR5K_RF_GAIN(39),	{ 0x000001bb, 0x000001d4 } },
-	{ AR5K_RF_GAIN(40),	{ 0x000001fb, 0x00000014 } },
-	{ AR5K_RF_GAIN(41),	{ 0x0000003b, 0x0000003a } },
-	{ AR5K_RF_GAIN(42),	{ 0x0000007b, 0x0000007a } },
-	{ AR5K_RF_GAIN(43),	{ 0x000000bb, 0x000000ba } },
-	{ AR5K_RF_GAIN(44),	{ 0x000001bc, 0x000001bb } },
-	{ AR5K_RF_GAIN(45),	{ 0x000001fc, 0x000001fb } },
-	{ AR5K_RF_GAIN(46),	{ 0x0000003c, 0x0000003b } },
-	{ AR5K_RF_GAIN(47),	{ 0x0000007c, 0x0000007b } },
-	{ AR5K_RF_GAIN(48),	{ 0x000000bc, 0x000000bb } },
-	{ AR5K_RF_GAIN(49),	{ 0x000000fc, 0x000001bc } },
-	{ AR5K_RF_GAIN(50),	{ 0x000000fc, 0x000001fc } },
-	{ AR5K_RF_GAIN(51),	{ 0x000000fc, 0x0000003c } },
-	{ AR5K_RF_GAIN(52),	{ 0x000000fc, 0x0000007c } },
-	{ AR5K_RF_GAIN(53),	{ 0x000000fc, 0x000000bc } },
-	{ AR5K_RF_GAIN(54),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(55),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(56),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(57),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(58),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(59),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(60),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(61),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(62),	{ 0x000000fc, 0x000000fc } },
-	{ AR5K_RF_GAIN(63),	{ 0x000000fc, 0x000000fc } },
-};
-
-/* Initial RF Gain settings for RF2413 */
-static const struct ath5k_ini_rfgain rfgain_2413[] = {
-	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
-	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
-	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
-	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x00000181 } },
-	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000001c1 } },
-	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x00000001 } },
-	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000041 } },
-	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000081 } },
-	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000168 } },
-	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x000001a8 } },
-	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x000001e8 } },
-	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x00000028 } },
-	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000068 } },
-	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000189 } },
-	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000001c9 } },
-	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x00000009 } },
-	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x00000049 } },
-	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000089 } },
-	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x00000190 } },
-	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x000001d0 } },
-	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x00000010 } },
-	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x00000050 } },
-	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000090 } },
-	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x00000191 } },
-	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000001d1 } },
-	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x00000011 } },
-	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x00000051 } },
-	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x00000091 } },
-	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x00000178 } },
-	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x000001b8 } },
-	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x000001f8 } },
-	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x00000038 } },
-	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x00000078 } },
-	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x00000199 } },
-	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x000001d9 } },
-	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x00000019 } },
-	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x00000059 } },
-	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x00000099 } },
-	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000d9 } },
-	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f9 } },
-};
-
-/* Initial RF Gain settings for AR2316 */
-static const struct ath5k_ini_rfgain rfgain_2316[] = {
-	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
-	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
-	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
-	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x000000c0 } },
-	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000000e0 } },
-	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x000000e0 } },
-	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000128 } },
-	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000128 } },
-	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000128 } },
-	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x00000168 } },
-	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x000001a8 } },
-	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x000001e8 } },
-	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000028 } },
-	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000068 } },
-	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000000a8 } },
-	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x000000e8 } },
-	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x000000e8 } },
-	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000130 } },
-	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x00000130 } },
-	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x00000170 } },
-	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x000001b0 } },
-	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x000001f0 } },
-	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000030 } },
-	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x00000070 } },
-	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000000b0 } },
-	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f0 } },
-	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f0 } },
-};
-
-
-/* Initial RF Gain settings for RF5413 */
-static const struct ath5k_ini_rfgain rfgain_5413[] = {
-	/*			      5Ghz	2Ghz	*/
-	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
-	{ AR5K_RF_GAIN(1),	{ 0x00000040, 0x00000040 } },
-	{ AR5K_RF_GAIN(2),	{ 0x00000080, 0x00000080 } },
-	{ AR5K_RF_GAIN(3),	{ 0x000001a1, 0x00000161 } },
-	{ AR5K_RF_GAIN(4),	{ 0x000001e1, 0x000001a1 } },
-	{ AR5K_RF_GAIN(5),	{ 0x00000021, 0x000001e1 } },
-	{ AR5K_RF_GAIN(6),	{ 0x00000061, 0x00000021 } },
-	{ AR5K_RF_GAIN(7),	{ 0x00000188, 0x00000061 } },
-	{ AR5K_RF_GAIN(8),	{ 0x000001c8, 0x00000188 } },
-	{ AR5K_RF_GAIN(9),	{ 0x00000008, 0x000001c8 } },
-	{ AR5K_RF_GAIN(10),	{ 0x00000048, 0x00000008 } },
-	{ AR5K_RF_GAIN(11),	{ 0x00000088, 0x00000048 } },
-	{ AR5K_RF_GAIN(12),	{ 0x000001a9, 0x00000088 } },
-	{ AR5K_RF_GAIN(13),	{ 0x000001e9, 0x00000169 } },
-	{ AR5K_RF_GAIN(14),	{ 0x00000029, 0x000001a9 } },
-	{ AR5K_RF_GAIN(15),	{ 0x00000069, 0x000001e9 } },
-	{ AR5K_RF_GAIN(16),	{ 0x000001d0, 0x00000029 } },
-	{ AR5K_RF_GAIN(17),	{ 0x00000010, 0x00000069 } },
-	{ AR5K_RF_GAIN(18),	{ 0x00000050, 0x00000190 } },
-	{ AR5K_RF_GAIN(19),	{ 0x00000090, 0x000001d0 } },
-	{ AR5K_RF_GAIN(20),	{ 0x000001b1, 0x00000010 } },
-	{ AR5K_RF_GAIN(21),	{ 0x000001f1, 0x00000050 } },
-	{ AR5K_RF_GAIN(22),	{ 0x00000031, 0x00000090 } },
-	{ AR5K_RF_GAIN(23),	{ 0x00000071, 0x00000171 } },
-	{ AR5K_RF_GAIN(24),	{ 0x000001b8, 0x000001b1 } },
-	{ AR5K_RF_GAIN(25),	{ 0x000001f8, 0x000001f1 } },
-	{ AR5K_RF_GAIN(26),	{ 0x00000038, 0x00000031 } },
-	{ AR5K_RF_GAIN(27),	{ 0x00000078, 0x00000071 } },
-	{ AR5K_RF_GAIN(28),	{ 0x00000199, 0x00000198 } },
-	{ AR5K_RF_GAIN(29),	{ 0x000001d9, 0x000001d8 } },
-	{ AR5K_RF_GAIN(30),	{ 0x00000019, 0x00000018 } },
-	{ AR5K_RF_GAIN(31),	{ 0x00000059, 0x00000058 } },
-	{ AR5K_RF_GAIN(32),	{ 0x00000099, 0x00000098 } },
-	{ AR5K_RF_GAIN(33),	{ 0x000000d9, 0x00000179 } },
-	{ AR5K_RF_GAIN(34),	{ 0x000000f9, 0x000001b9 } },
-	{ AR5K_RF_GAIN(35),	{ 0x000000f9, 0x000001f9 } },
-	{ AR5K_RF_GAIN(36),	{ 0x000000f9, 0x00000039 } },
-	{ AR5K_RF_GAIN(37),	{ 0x000000f9, 0x00000079 } },
-	{ AR5K_RF_GAIN(38),	{ 0x000000f9, 0x000000b9 } },
-	{ AR5K_RF_GAIN(39),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(40),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(41),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(42),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(43),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(44),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(45),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(46),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(47),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(48),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(49),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(50),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(51),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(52),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(53),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(54),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(55),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(56),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(57),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(58),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(59),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(60),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(61),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(62),	{ 0x000000f9, 0x000000f9 } },
-	{ AR5K_RF_GAIN(63),	{ 0x000000f9, 0x000000f9 } },
-};
-
-
-/* Initial RF Gain settings for RF2425 */
-static const struct ath5k_ini_rfgain rfgain_2425[] = {
-	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
-	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
-	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
-	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x00000181 } },
-	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000001c1 } },
-	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x00000001 } },
-	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000041 } },
-	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000081 } },
-	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000188 } },
-	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x000001c8 } },
-	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x00000008 } },
-	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x00000048 } },
-	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000088 } },
-	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000189 } },
-	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000001c9 } },
-	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x00000009 } },
-	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x00000049 } },
-	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000089 } },
-	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x000001b0 } },
-	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x000001f0 } },
-	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x00000030 } },
-	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x00000070 } },
-	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000171 } },
-	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x000001b1 } },
-	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000001f1 } },
-	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x00000031 } },
-	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x00000071 } },
-	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x000001b8 } },
-	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x000001f8 } },
-	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x00000038 } },
-	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x00000078 } },
-	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x000000b8 } },
-	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x000001b9 } },
-	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x000001f9 } },
-	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x00000039 } },
-	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x00000079 } },
-	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x000000b9 } },
-	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f9 } },
-	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f9 } },
-};
-
-#define AR5K_GAIN_CRN_FIX_BITS_5111		4
-#define AR5K_GAIN_CRN_FIX_BITS_5112		7
-#define AR5K_GAIN_CRN_MAX_FIX_BITS		AR5K_GAIN_CRN_FIX_BITS_5112
-#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN		15
-#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN		20
-#define AR5K_GAIN_CCK_PROBE_CORR		5
-#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA		15
-#define AR5K_GAIN_STEP_COUNT			10
-
-/* Check if our current measurement is inside our
- * current variable attenuation window */
-#define AR5K_GAIN_CHECK_ADJUST(_g) 		\
-	((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
-
-struct ath5k_gain_opt_step {
-	s8				gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
-	s8				gos_gain;
-};
-
-struct ath5k_gain_opt {
-	u8				go_default;
-	u8				go_steps_count;
-	const struct ath5k_gain_opt_step	go_step[AR5K_GAIN_STEP_COUNT];
-};
-
-/*
- * Parameters on gos_param:
- * 1) Tx clip PHY register
- * 2) PWD 90 RF register
- * 3) PWD 84 RF register
- * 4) RFGainSel RF register
- */
-static const struct ath5k_gain_opt rfgain_opt_5111 = {
-	4,
-	9,
-	{
-		{ { 4, 1, 1, 1 }, 6 },
-		{ { 4, 0, 1, 1 }, 4 },
-		{ { 3, 1, 1, 1 }, 3 },
-		{ { 4, 0, 0, 1 }, 1 },
-		{ { 4, 1, 1, 0 }, 0 },
-		{ { 4, 0, 1, 0 }, -2 },
-		{ { 3, 1, 1, 0 }, -3 },
-		{ { 4, 0, 0, 0 }, -4 },
-		{ { 2, 1, 1, 0 }, -6 }
-	}
-};
-
-/*
- * Parameters on gos_param:
- * 1) Mixgain ovr RF register
- * 2) PWD 138 RF register
- * 3) PWD 137 RF register
- * 4) PWD 136 RF register
- * 5) PWD 132 RF register
- * 6) PWD 131 RF register
- * 7) PWD 130 RF register
- */
-static const struct ath5k_gain_opt rfgain_opt_5112 = {
-	1,
-	8,
-	{
-		{ { 3, 0, 0, 0, 0, 0, 0 }, 6 },
-		{ { 2, 0, 0, 0, 0, 0, 0 }, 0 },
-		{ { 1, 0, 0, 0, 0, 0, 0 }, -3 },
-		{ { 0, 0, 0, 0, 0, 0, 0 }, -6 },
-		{ { 0, 1, 1, 0, 0, 0, 0 }, -8 },
-		{ { 0, 1, 1, 0, 1, 1, 0 }, -10 },
-		{ { 0, 1, 0, 1, 1, 1, 0 }, -13 },
-		{ { 0, 1, 0, 1, 1, 0, 1 }, -16 },
-	}
-};
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ahb.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ahb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ahb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ahb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/nl80211.h>
-#include <linux/platform_device.h>
-#include <linux/ath9k_platform.h>
-#include "ath9k.h"
-
-/* return bus cachesize in 4B word units */
-static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz)
-{
-	*csz = L1_CACHE_BYTES >> 2;
-}
-
-static void ath_ahb_cleanup(struct ath_softc *sc)
-{
-	iounmap(sc->mem);
-}
-
-static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
-{
-	struct ath_softc *sc = ah->ah_sc;
-	struct platform_device *pdev = to_platform_device(sc->dev);
-	struct ath9k_platform_data *pdata;
-
-	pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
-	if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
-		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-			"%s: flash read failed, offset %08x is out of range\n",
-				__func__, off);
-		return false;
-	}
-
-	*data = pdata->eeprom_data[off];
-	return true;
-}
-
-static struct ath_bus_ops ath_ahb_bus_ops  = {
-	.read_cachesize = ath_ahb_read_cachesize,
-	.cleanup = ath_ahb_cleanup,
-
-	.eeprom_read = ath_ahb_eeprom_read,
-};
-
-static int ath_ahb_probe(struct platform_device *pdev)
-{
-	void __iomem *mem;
-	struct ath_wiphy *aphy;
-	struct ath_softc *sc;
-	struct ieee80211_hw *hw;
-	struct resource *res;
-	int irq;
-	int ret = 0;
-	struct ath_hw *ah;
-
-	if (!pdev->dev.platform_data) {
-		dev_err(&pdev->dev, "no platform data specified\n");
-		ret = -EINVAL;
-		goto err_out;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no memory resource found\n");
-		ret = -ENXIO;
-		goto err_out;
-	}
-
-	mem = ioremap_nocache(res->start, res->end - res->start + 1);
-	if (mem == NULL) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_out;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "no IRQ resource found\n");
-		ret = -ENXIO;
-		goto err_iounmap;
-	}
-
-	irq = res->start;
-
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
-				sizeof(struct ath_softc), &ath9k_ops);
-	if (hw == NULL) {
-		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
-		ret = -ENOMEM;
-		goto err_iounmap;
-	}
-
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-	platform_set_drvdata(pdev, hw);
-
-	aphy = hw->priv;
-	sc = (struct ath_softc *) (aphy + 1);
-	aphy->sc = sc;
-	aphy->hw = hw;
-	sc->pri_wiphy = aphy;
-	sc->hw = hw;
-	sc->dev = &pdev->dev;
-	sc->mem = mem;
-	sc->bus_ops = &ath_ahb_bus_ops;
-	sc->irq = irq;
-
-	ret = ath_attach(AR5416_AR9100_DEVID, sc);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
-		ret = -ENODEV;
-		goto err_free_hw;
-	}
-
-	ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
-	if (ret) {
-		dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret);
-		ret = -EIO;
-		goto err_detach;
-	}
-
-	ah = sc->sc_ah;
-	printk(KERN_INFO
-	       "%s: Atheros AR%s MAC/BB Rev:%x, "
-	       "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n",
-	       wiphy_name(hw->wiphy),
-	       ath_mac_bb_name(ah->hw_version.macVersion),
-	       ah->hw_version.macRev,
-	       ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
-	       ah->hw_version.phyRev,
-	       (unsigned long)mem, irq);
-
-	return 0;
-
- err_detach:
-	ath_detach(sc);
- err_free_hw:
-	ieee80211_free_hw(hw);
-	platform_set_drvdata(pdev, NULL);
- err_iounmap:
-	iounmap(mem);
- err_out:
-	return ret;
-}
-
-static int ath_ahb_remove(struct platform_device *pdev)
-{
-	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
-
-	if (hw) {
-		struct ath_wiphy *aphy = hw->priv;
-		struct ath_softc *sc = aphy->sc;
-
-		ath_cleanup(sc);
-		platform_set_drvdata(pdev, NULL);
-	}
-
-	return 0;
-}
-
-static struct platform_driver ath_ahb_driver = {
-	.probe      = ath_ahb_probe,
-	.remove     = ath_ahb_remove,
-	.driver		= {
-		.name	= "ath9k",
-		.owner	= THIS_MODULE,
-	},
-};
-
-int ath_ahb_init(void)
-{
-	return platform_driver_register(&ath_ahb_driver);
-}
-
-void ath_ahb_exit(void)
-{
-	platform_driver_unregister(&ath_ahb_driver);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ani.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ani.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ani.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ani.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,824 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
-					struct ath9k_channel *chan)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
-		if (ah->ani[i].c &&
-		    ah->ani[i].c->channel == chan->channel)
-			return i;
-		if (ah->ani[i].c == NULL) {
-			ah->ani[i].c = chan;
-			return i;
-		}
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"No more channel states left. Using channel 0\n");
-
-	return 0;
-}
-
-static bool ath9k_hw_ani_control(struct ath_hw *ah,
-				 enum ath9k_ani_cmd cmd, int param)
-{
-	struct ar5416AniState *aniState = ah->curani;
-
-	switch (cmd & ah->ani_function) {
-	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
-		u32 level = param;
-
-		if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				"level out of range (%u > %u)\n",
-				level,
-				(unsigned)ARRAY_SIZE(ah->totalSizeDesired));
-			return false;
-		}
-
-		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
-			      AR_PHY_DESIRED_SZ_TOT_DES,
-			      ah->totalSizeDesired[level]);
-		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
-			      AR_PHY_AGC_CTL1_COARSE_LOW,
-			      ah->coarse_low[level]);
-		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
-			      AR_PHY_AGC_CTL1_COARSE_HIGH,
-			      ah->coarse_high[level]);
-		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-			      AR_PHY_FIND_SIG_FIRPWR,
-			      ah->firpwr[level]);
-
-		if (level > aniState->noiseImmunityLevel)
-			ah->stats.ast_ani_niup++;
-		else if (level < aniState->noiseImmunityLevel)
-			ah->stats.ast_ani_nidown++;
-		aniState->noiseImmunityLevel = level;
-		break;
-	}
-	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
-		const int m1ThreshLow[] = { 127, 50 };
-		const int m2ThreshLow[] = { 127, 40 };
-		const int m1Thresh[] = { 127, 0x4d };
-		const int m2Thresh[] = { 127, 0x40 };
-		const int m2CountThr[] = { 31, 16 };
-		const int m2CountThrLow[] = { 63, 48 };
-		u32 on = param ? 1 : 0;
-
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
-			      m1ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
-			      m2ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-			      AR_PHY_SFCORR_M1_THRESH,
-			      m1Thresh[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-			      AR_PHY_SFCORR_M2_THRESH,
-			      m2Thresh[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-			      AR_PHY_SFCORR_M2COUNT_THR,
-			      m2CountThr[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
-			      m2CountThrLow[on]);
-
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
-			      m1ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
-			      m2ThreshLow[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M1_THRESH,
-			      m1Thresh[on]);
-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-			      AR_PHY_SFCORR_EXT_M2_THRESH,
-			      m2Thresh[on]);
-
-		if (on)
-			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
-				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-		else
-			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
-				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-
-		if (!on != aniState->ofdmWeakSigDetectOff) {
-			if (on)
-				ah->stats.ast_ani_ofdmon++;
-			else
-				ah->stats.ast_ani_ofdmoff++;
-			aniState->ofdmWeakSigDetectOff = !on;
-		}
-		break;
-	}
-	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
-		const int weakSigThrCck[] = { 8, 6 };
-		u32 high = param ? 1 : 0;
-
-		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
-			      AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
-			      weakSigThrCck[high]);
-		if (high != aniState->cckWeakSigThreshold) {
-			if (high)
-				ah->stats.ast_ani_cckhigh++;
-			else
-				ah->stats.ast_ani_ccklow++;
-			aniState->cckWeakSigThreshold = high;
-		}
-		break;
-	}
-	case ATH9K_ANI_FIRSTEP_LEVEL:{
-		const int firstep[] = { 0, 4, 8 };
-		u32 level = param;
-
-		if (level >= ARRAY_SIZE(firstep)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				"level out of range (%u > %u)\n",
-				level,
-				(unsigned) ARRAY_SIZE(firstep));
-			return false;
-		}
-		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-			      AR_PHY_FIND_SIG_FIRSTEP,
-			      firstep[level]);
-		if (level > aniState->firstepLevel)
-			ah->stats.ast_ani_stepup++;
-		else if (level < aniState->firstepLevel)
-			ah->stats.ast_ani_stepdown++;
-		aniState->firstepLevel = level;
-		break;
-	}
-	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
-		const int cycpwrThr1[] =
-			{ 2, 4, 6, 8, 10, 12, 14, 16 };
-		u32 level = param;
-
-		if (level >= ARRAY_SIZE(cycpwrThr1)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				"level out of range (%u > %u)\n",
-				level,
-				(unsigned)
-				ARRAY_SIZE(cycpwrThr1));
-			return false;
-		}
-		REG_RMW_FIELD(ah, AR_PHY_TIMING5,
-			      AR_PHY_TIMING5_CYCPWR_THR1,
-			      cycpwrThr1[level]);
-		if (level > aniState->spurImmunityLevel)
-			ah->stats.ast_ani_spurup++;
-		else if (level < aniState->spurImmunityLevel)
-			ah->stats.ast_ani_spurdown++;
-		aniState->spurImmunityLevel = level;
-		break;
-	}
-	case ATH9K_ANI_PRESENT:
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"invalid cmd %u\n", cmd);
-		return false;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n");
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
-		"ofdmWeakSigDetectOff=%d\n",
-		aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
-		!aniState->ofdmWeakSigDetectOff);
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"cckWeakSigThreshold=%d, "
-		"firstepLevel=%d, listenTime=%d\n",
-		aniState->cckWeakSigThreshold, aniState->firstepLevel,
-		aniState->listenTime);
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
-		aniState->cycleCount, aniState->ofdmPhyErrCount,
-		aniState->cckPhyErrCount);
-
-	return true;
-}
-
-static void ath9k_hw_update_mibstats(struct ath_hw *ah,
-				     struct ath9k_mib_stats *stats)
-{
-	stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
-	stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
-	stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
-	stats->rts_good += REG_READ(ah, AR_RTS_OK);
-	stats->beacons += REG_READ(ah, AR_BEACON_CNT);
-}
-
-static void ath9k_ani_restart(struct ath_hw *ah)
-{
-	struct ar5416AniState *aniState;
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ah->curani;
-
-	aniState->listenTime = 0;
-	if (ah->has_hw_phycounters) {
-		if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
-			aniState->ofdmPhyErrBase = 0;
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				"OFDM Trigger is too high for hw counters\n");
-		} else {
-			aniState->ofdmPhyErrBase =
-				AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
-		}
-		if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
-			aniState->cckPhyErrBase = 0;
-			DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-				"CCK Trigger is too high for hw counters\n");
-		} else {
-			aniState->cckPhyErrBase =
-				AR_PHY_COUNTMAX - aniState->cckTrigHigh;
-		}
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"Writing ofdmbase=%u   cckbase=%u\n",
-			aniState->ofdmPhyErrBase,
-			aniState->cckPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
-		ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-	}
-	aniState->ofdmPhyErrCount = 0;
-	aniState->cckPhyErrCount = 0;
-}
-
-static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-	struct ar5416AniState *aniState;
-	int32_t rssi;
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ah->curani;
-
-	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-					 aniState->noiseImmunityLevel + 1)) {
-			return;
-		}
-	}
-
-	if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
-					 aniState->spurImmunityLevel + 1)) {
-			return;
-		}
-	}
-
-	if (ah->opmode == NL80211_IFTYPE_AP) {
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-		}
-		return;
-	}
-	rssi = BEACON_RSSI(ah);
-	if (rssi > aniState->rssiThrHigh) {
-		if (!aniState->ofdmWeakSigDetectOff) {
-			if (ath9k_hw_ani_control(ah,
-					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-					 false)) {
-				ath9k_hw_ani_control(ah,
-					ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
-				return;
-			}
-		}
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-			return;
-		}
-	} else if (rssi > aniState->rssiThrLow) {
-		if (aniState->ofdmWeakSigDetectOff)
-			ath9k_hw_ani_control(ah,
-				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     true);
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-		return;
-	} else {
-		if (conf->channel->band == IEEE80211_BAND_2GHZ) {
-			if (!aniState->ofdmWeakSigDetectOff)
-				ath9k_hw_ani_control(ah,
-				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     false);
-			if (aniState->firstepLevel > 0)
-				ath9k_hw_ani_control(ah,
-					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
-			return;
-		}
-	}
-}
-
-static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-	struct ar5416AniState *aniState;
-	int32_t rssi;
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ah->curani;
-	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-					 aniState->noiseImmunityLevel + 1)) {
-			return;
-		}
-	}
-	if (ah->opmode == NL80211_IFTYPE_AP) {
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-		}
-		return;
-	}
-	rssi = BEACON_RSSI(ah);
-	if (rssi > aniState->rssiThrLow) {
-		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
-			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-					     aniState->firstepLevel + 1);
-	} else {
-		if (conf->channel->band == IEEE80211_BAND_2GHZ) {
-			if (aniState->firstepLevel > 0)
-				ath9k_hw_ani_control(ah,
-					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
-		}
-	}
-}
-
-static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
-{
-	struct ar5416AniState *aniState;
-	int32_t rssi;
-
-	aniState = ah->curani;
-
-	if (ah->opmode == NL80211_IFTYPE_AP) {
-		if (aniState->firstepLevel > 0) {
-			if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-						 aniState->firstepLevel - 1))
-				return;
-		}
-	} else {
-		rssi = BEACON_RSSI(ah);
-		if (rssi > aniState->rssiThrHigh) {
-			/* XXX: Handle me */
-		} else if (rssi > aniState->rssiThrLow) {
-			if (aniState->ofdmWeakSigDetectOff) {
-				if (ath9k_hw_ani_control(ah,
-					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-					 true) == true)
-					return;
-			}
-			if (aniState->firstepLevel > 0) {
-				if (ath9k_hw_ani_control(ah,
-					 ATH9K_ANI_FIRSTEP_LEVEL,
-					 aniState->firstepLevel - 1) == true)
-					return;
-			}
-		} else {
-			if (aniState->firstepLevel > 0) {
-				if (ath9k_hw_ani_control(ah,
-					 ATH9K_ANI_FIRSTEP_LEVEL,
-					 aniState->firstepLevel - 1) == true)
-					return;
-			}
-		}
-	}
-
-	if (aniState->spurImmunityLevel > 0) {
-		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
-					 aniState->spurImmunityLevel - 1))
-			return;
-	}
-
-	if (aniState->noiseImmunityLevel > 0) {
-		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-				     aniState->noiseImmunityLevel - 1);
-		return;
-	}
-}
-
-static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
-{
-	struct ar5416AniState *aniState;
-	u32 txFrameCount, rxFrameCount, cycleCount;
-	int32_t listenTime;
-
-	txFrameCount = REG_READ(ah, AR_TFCNT);
-	rxFrameCount = REG_READ(ah, AR_RFCNT);
-	cycleCount = REG_READ(ah, AR_CCCNT);
-
-	aniState = ah->curani;
-	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
-
-		listenTime = 0;
-		ah->stats.ast_ani_lzero++;
-	} else {
-		int32_t ccdelta = cycleCount - aniState->cycleCount;
-		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
-		int32_t tfdelta = txFrameCount - aniState->txFrameCount;
-		listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
-	}
-	aniState->cycleCount = cycleCount;
-	aniState->txFrameCount = txFrameCount;
-	aniState->rxFrameCount = rxFrameCount;
-
-	return listenTime;
-}
-
-void ath9k_ani_reset(struct ath_hw *ah)
-{
-	struct ar5416AniState *aniState;
-	struct ath9k_channel *chan = ah->curchan;
-	int index;
-
-	if (!DO_ANI(ah))
-		return;
-
-	index = ath9k_hw_get_ani_channel_idx(ah, chan);
-	aniState = &ah->ani[index];
-	ah->curani = aniState;
-
-	if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
-	    && ah->opmode != NL80211_IFTYPE_ADHOC) {
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"Reset ANI state opmode %u\n", ah->opmode);
-		ah->stats.ast_ani_reset++;
-
-		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
-		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
-		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
-		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     !ATH9K_ANI_USE_OFDM_WEAK_SIG);
-		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
-				     ATH9K_ANI_CCK_WEAK_SIG_THR);
-
-		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
-				     ATH9K_RX_FILTER_PHYERR);
-
-		if (ah->opmode == NL80211_IFTYPE_AP) {
-			ah->curani->ofdmTrigHigh =
-				ah->config.ofdm_trig_high;
-			ah->curani->ofdmTrigLow =
-				ah->config.ofdm_trig_low;
-			ah->curani->cckTrigHigh =
-				ah->config.cck_trig_high;
-			ah->curani->cckTrigLow =
-				ah->config.cck_trig_low;
-		}
-		ath9k_ani_restart(ah);
-		return;
-	}
-
-	if (aniState->noiseImmunityLevel != 0)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
-				     aniState->noiseImmunityLevel);
-	if (aniState->spurImmunityLevel != 0)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
-				     aniState->spurImmunityLevel);
-	if (aniState->ofdmWeakSigDetectOff)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-				     !aniState->ofdmWeakSigDetectOff);
-	if (aniState->cckWeakSigThreshold)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
-				     aniState->cckWeakSigThreshold);
-	if (aniState->firstepLevel != 0)
-		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
-				     aniState->firstepLevel);
-	if (ah->has_hw_phycounters) {
-		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
-				     ~ATH9K_RX_FILTER_PHYERR);
-		ath9k_ani_restart(ah);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-		REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
-	} else {
-		ath9k_ani_restart(ah);
-		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
-				     ATH9K_RX_FILTER_PHYERR);
-	}
-}
-
-void ath9k_hw_ani_monitor(struct ath_hw *ah,
-			  const struct ath9k_node_stats *stats,
-			  struct ath9k_channel *chan)
-{
-	struct ar5416AniState *aniState;
-	int32_t listenTime;
-
-	if (!DO_ANI(ah))
-		return;
-
-	aniState = ah->curani;
-	ah->stats.ast_nodestats = *stats;
-
-	listenTime = ath9k_hw_ani_get_listen_time(ah);
-	if (listenTime < 0) {
-		ah->stats.ast_ani_lneg++;
-		ath9k_ani_restart(ah);
-		return;
-	}
-
-	aniState->listenTime += listenTime;
-
-	if (ah->has_hw_phycounters) {
-		u32 phyCnt1, phyCnt2;
-		u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
-		ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
-		phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
-		phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
-		if (phyCnt1 < aniState->ofdmPhyErrBase ||
-		    phyCnt2 < aniState->cckPhyErrBase) {
-			if (phyCnt1 < aniState->ofdmPhyErrBase) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-					"phyCnt1 0x%x, resetting "
-					"counter value to 0x%x\n",
-					phyCnt1,
-					aniState->ofdmPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_1,
-					  aniState->ofdmPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_MASK_1,
-					  AR_PHY_ERR_OFDM_TIMING);
-			}
-			if (phyCnt2 < aniState->cckPhyErrBase) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-					"phyCnt2 0x%x, resetting "
-					"counter value to 0x%x\n",
-					phyCnt2,
-					aniState->cckPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_2,
-					  aniState->cckPhyErrBase);
-				REG_WRITE(ah, AR_PHY_ERR_MASK_2,
-					  AR_PHY_ERR_CCK_TIMING);
-			}
-			return;
-		}
-
-		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
-		ah->stats.ast_ani_ofdmerrs +=
-			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
-		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
-		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
-		ah->stats.ast_ani_cckerrs +=
-			cckPhyErrCnt - aniState->cckPhyErrCount;
-		aniState->cckPhyErrCount = cckPhyErrCnt;
-	}
-
-	if (aniState->listenTime > 5 * ah->aniperiod) {
-		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
-		    aniState->ofdmTrigLow / 1000 &&
-		    aniState->cckPhyErrCount <= aniState->listenTime *
-		    aniState->cckTrigLow / 1000)
-			ath9k_hw_ani_lower_immunity(ah);
-		ath9k_ani_restart(ah);
-	} else if (aniState->listenTime > ah->aniperiod) {
-		if (aniState->ofdmPhyErrCount > aniState->listenTime *
-		    aniState->ofdmTrigHigh / 1000) {
-			ath9k_hw_ani_ofdm_err_trigger(ah);
-			ath9k_ani_restart(ah);
-		} else if (aniState->cckPhyErrCount >
-			   aniState->listenTime * aniState->cckTrigHigh /
-			   1000) {
-			ath9k_hw_ani_cck_err_trigger(ah);
-			ath9k_ani_restart(ah);
-		}
-	}
-}
-
-bool ath9k_hw_phycounters(struct ath_hw *ah)
-{
-	return ah->has_hw_phycounters ? true : false;
-}
-
-void ath9k_enable_mib_counters(struct ath_hw *ah)
-{
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
-
-	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
-	REG_WRITE(ah, AR_FILT_OFDM, 0);
-	REG_WRITE(ah, AR_FILT_CCK, 0);
-	REG_WRITE(ah, AR_MIBC,
-		  ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
-		  & 0x0f);
-	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-}
-
-/* Freeze the MIB counters, get the stats and then clear them */
-void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
-{
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
-	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
-	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-	REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
-	REG_WRITE(ah, AR_FILT_OFDM, 0);
-	REG_WRITE(ah, AR_FILT_CCK, 0);
-}
-
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
-				  u32 *rxc_pcnt,
-				  u32 *rxf_pcnt,
-				  u32 *txf_pcnt)
-{
-	static u32 cycles, rx_clear, rx_frame, tx_frame;
-	u32 good = 1;
-
-	u32 rc = REG_READ(ah, AR_RCCNT);
-	u32 rf = REG_READ(ah, AR_RFCNT);
-	u32 tf = REG_READ(ah, AR_TFCNT);
-	u32 cc = REG_READ(ah, AR_CCCNT);
-
-	if (cycles == 0 || cycles > cc) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			"cycle counter wrap. ExtBusy = 0\n");
-		good = 0;
-	} else {
-		u32 cc_d = cc - cycles;
-		u32 rc_d = rc - rx_clear;
-		u32 rf_d = rf - rx_frame;
-		u32 tf_d = tf - tx_frame;
-
-		if (cc_d != 0) {
-			*rxc_pcnt = rc_d * 100 / cc_d;
-			*rxf_pcnt = rf_d * 100 / cc_d;
-			*txf_pcnt = tf_d * 100 / cc_d;
-		} else {
-			good = 0;
-		}
-	}
-
-	cycles = cc;
-	rx_frame = rf;
-	rx_clear = rc;
-	tx_frame = tf;
-
-	return good;
-}
-
-/*
- * Process a MIB interrupt.  We may potentially be invoked because
- * any of the MIB counters overflow/trigger so don't assume we're
- * here because a PHY error counter triggered.
- */
-void ath9k_hw_procmibevent(struct ath_hw *ah,
-			   const struct ath9k_node_stats *stats)
-{
-	u32 phyCnt1, phyCnt2;
-
-	/* Reset these counters regardless */
-	REG_WRITE(ah, AR_FILT_OFDM, 0);
-	REG_WRITE(ah, AR_FILT_CCK, 0);
-	if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
-		REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
-
-	/* Clear the mib counters and save them in the stats */
-	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-	ah->stats.ast_nodestats = *stats;
-
-	if (!DO_ANI(ah))
-		return;
-
-	/* NB: these are not reset-on-read */
-	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
-	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
-	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
-		struct ar5416AniState *aniState = ah->curani;
-		u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
-		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
-		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
-		ah->stats.ast_ani_ofdmerrs +=
-			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
-		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
-		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
-		ah->stats.ast_ani_cckerrs +=
-			cckPhyErrCnt - aniState->cckPhyErrCount;
-		aniState->cckPhyErrCount = cckPhyErrCnt;
-
-		/*
-		 * NB: figure out which counter triggered.  If both
-		 * trigger we'll only deal with one as the processing
-		 * clobbers the error counter so the trigger threshold
-		 * check will never be true.
-		 */
-		if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
-			ath9k_hw_ani_ofdm_err_trigger(ah);
-		if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
-			ath9k_hw_ani_cck_err_trigger(ah);
-		/* NB: always restart to insure the h/w counters are reset */
-		ath9k_ani_restart(ah);
-	}
-}
-
-void ath9k_hw_ani_setup(struct ath_hw *ah)
-{
-	int i;
-
-	const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
-	const int coarseHigh[] = { -14, -14, -14, -14, -12 };
-	const int coarseLow[] = { -64, -64, -64, -64, -70 };
-	const int firpwr[] = { -78, -78, -78, -78, -80 };
-
-	for (i = 0; i < 5; i++) {
-		ah->totalSizeDesired[i] = totalSizeDesired[i];
-		ah->coarse_high[i] = coarseHigh[i];
-		ah->coarse_low[i] = coarseLow[i];
-		ah->firpwr[i] = firpwr[i];
-	}
-}
-
-void ath9k_hw_ani_attach(struct ath_hw *ah)
-{
-	int i;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
-
-	ah->has_hw_phycounters = 1;
-
-	memset(ah->ani, 0, sizeof(ah->ani));
-	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
-		ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
-		ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
-		ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
-		ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
-		ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
-		ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
-		ah->ani[i].ofdmWeakSigDetectOff =
-			!ATH9K_ANI_USE_OFDM_WEAK_SIG;
-		ah->ani[i].cckWeakSigThreshold =
-			ATH9K_ANI_CCK_WEAK_SIG_THR;
-		ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
-		ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
-		if (ah->has_hw_phycounters) {
-			ah->ani[i].ofdmPhyErrBase =
-				AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
-			ah->ani[i].cckPhyErrBase =
-				AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
-		}
-	}
-	if (ah->has_hw_phycounters) {
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"Setting OfdmErrBase = 0x%08x\n",
-			ah->ani[0].ofdmPhyErrBase);
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
-			ah->ani[0].cckPhyErrBase);
-
-		REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
-		REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
-		ath9k_enable_mib_counters(ah);
-	}
-	ah->aniperiod = ATH9K_ANI_PERIOD;
-	if (ah->config.enable_ani)
-		ah->proc_phyerr |= HAL_PROCESS_ANI;
-}
-
-void ath9k_hw_ani_detach(struct ath_hw *ah)
-{
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
-
-	if (ah->has_hw_phycounters) {
-		ath9k_hw_disable_mib_counters(ah);
-		REG_WRITE(ah, AR_PHY_ERR_1, 0);
-		REG_WRITE(ah, AR_PHY_ERR_2, 0);
-	}
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ani.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ani.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ani.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ani.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef ANI_H
-#define ANI_H
-
-#define HAL_PROCESS_ANI           0x00000001
-#define ATH9K_RSSI_EP_MULTIPLIER  (1<<7)
-
-#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
-
-#define HAL_EP_RND(x, mul)						\
-	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
-#define BEACON_RSSI(ahp)					\
-	HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi,	\
-		   ATH9K_RSSI_EP_MULTIPLIER)
-
-#define ATH9K_ANI_OFDM_TRIG_HIGH          500
-#define ATH9K_ANI_OFDM_TRIG_LOW           200
-#define ATH9K_ANI_CCK_TRIG_HIGH           200
-#define ATH9K_ANI_CCK_TRIG_LOW            100
-#define ATH9K_ANI_NOISE_IMMUNE_LVL        4
-#define ATH9K_ANI_USE_OFDM_WEAK_SIG       true
-#define ATH9K_ANI_CCK_WEAK_SIG_THR        false
-#define ATH9K_ANI_SPUR_IMMUNE_LVL         7
-#define ATH9K_ANI_FIRSTEP_LVL             0
-#define ATH9K_ANI_RSSI_THR_HIGH           40
-#define ATH9K_ANI_RSSI_THR_LOW            7
-#define ATH9K_ANI_PERIOD                  100
-
-#define HAL_NOISE_IMMUNE_MAX              4
-#define HAL_SPUR_IMMUNE_MAX               7
-#define HAL_FIRST_STEP_MAX                2
-
-enum ath9k_ani_cmd {
-	ATH9K_ANI_PRESENT = 0x1,
-	ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
-	ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4,
-	ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8,
-	ATH9K_ANI_FIRSTEP_LEVEL = 0x10,
-	ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
-	ATH9K_ANI_MODE = 0x40,
-	ATH9K_ANI_PHYERR_RESET = 0x80,
-	ATH9K_ANI_ALL = 0xff
-};
-
-struct ath9k_mib_stats {
-	u32 ackrcv_bad;
-	u32 rts_bad;
-	u32 rts_good;
-	u32 fcs_bad;
-	u32 beacons;
-};
-
-struct ath9k_node_stats {
-	u32 ns_avgbrssi;
-	u32 ns_avgrssi;
-	u32 ns_avgtxrssi;
-	u32 ns_avgtxrate;
-};
-
-struct ar5416AniState {
-	struct ath9k_channel *c;
-	u8 noiseImmunityLevel;
-	u8 spurImmunityLevel;
-	u8 firstepLevel;
-	u8 ofdmWeakSigDetectOff;
-	u8 cckWeakSigThreshold;
-	u32 listenTime;
-	u32 ofdmTrigHigh;
-	u32 ofdmTrigLow;
-	int32_t cckTrigHigh;
-	int32_t cckTrigLow;
-	int32_t rssiThrLow;
-	int32_t rssiThrHigh;
-	u32 noiseFloor;
-	u32 txFrameCount;
-	u32 rxFrameCount;
-	u32 cycleCount;
-	u32 ofdmPhyErrCount;
-	u32 cckPhyErrCount;
-	u32 ofdmPhyErrBase;
-	u32 cckPhyErrBase;
-	int16_t pktRssi[2];
-	int16_t ofdmErrRssi[2];
-	int16_t cckErrRssi[2];
-};
-
-struct ar5416Stats {
-	u32 ast_ani_niup;
-	u32 ast_ani_nidown;
-	u32 ast_ani_spurup;
-	u32 ast_ani_spurdown;
-	u32 ast_ani_ofdmon;
-	u32 ast_ani_ofdmoff;
-	u32 ast_ani_cckhigh;
-	u32 ast_ani_ccklow;
-	u32 ast_ani_stepup;
-	u32 ast_ani_stepdown;
-	u32 ast_ani_ofdmerrs;
-	u32 ast_ani_cckerrs;
-	u32 ast_ani_reset;
-	u32 ast_ani_lzero;
-	u32 ast_ani_lneg;
-	struct ath9k_mib_stats ast_mibstats;
-	struct ath9k_node_stats ast_nodestats;
-};
-#define ah_mibStats stats.ast_mibstats
-
-void ath9k_ani_reset(struct ath_hw *ah);
-void ath9k_hw_ani_monitor(struct ath_hw *ah,
-			  const struct ath9k_node_stats *stats,
-			  struct ath9k_channel *chan);
-bool ath9k_hw_phycounters(struct ath_hw *ah);
-void ath9k_enable_mib_counters(struct ath_hw *ah);
-void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
-				  u32 *rxf_pcnt, u32 *txf_pcnt);
-void ath9k_hw_procmibevent(struct ath_hw *ah,
-			   const struct ath9k_node_stats *stats);
-void ath9k_hw_ani_setup(struct ath_hw *ah);
-void ath9k_hw_ani_attach(struct ath_hw *ah);
-void ath9k_hw_ani_detach(struct ath_hw *ah);
-
-#endif /* ANI_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ath9k.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ath9k.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/ath9k.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/ath9k.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,757 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef ATH9K_H
-#define ATH9K_H
-
-#include <linux/etherdevice.h>
-#include <linux/device.h>
-#include <net/mac80211.h>
-#include <linux/leds.h>
-#include <linux/rfkill.h>
-
-#include "hw.h"
-#include "rc.h"
-#include "debug.h"
-
-struct ath_node;
-
-/* Macro to expand scalars to 64-bit objects */
-
-#define	ito64(x) (sizeof(x) == 8) ?			\
-	(((unsigned long long int)(x)) & (0xff)) :	\
-	(sizeof(x) == 16) ?				\
-	(((unsigned long long int)(x)) & 0xffff) :	\
-	((sizeof(x) == 32) ?				\
-	 (((unsigned long long int)(x)) & 0xffffffff) : \
-	 (unsigned long long int)(x))
-
-/* increment with wrap-around */
-#define INCR(_l, _sz)   do {			\
-		(_l)++;				\
-		(_l) &= ((_sz) - 1);		\
-	} while (0)
-
-/* decrement with wrap-around */
-#define DECR(_l,  _sz)  do {			\
-		(_l)--;				\
-		(_l) &= ((_sz) - 1);		\
-	} while (0)
-
-#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
-
-#define ASSERT(exp) do {			\
-		if (unlikely(!(exp))) {		\
-			BUG();			\
-		}				\
-	} while (0)
-
-#define TSF_TO_TU(_h,_l) \
-	((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
-
-#define	ATH_TXQ_SETUP(sc, i)        ((sc)->tx.txqsetup & (1<<i))
-
-static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-struct ath_config {
-	u32 ath_aggr_prot;
-	u16 txpowlimit;
-	u8 cabqReadytime;
-	u8 swBeaconProcess;
-};
-
-/*************************/
-/* Descriptor Management */
-/*************************/
-
-#define ATH_TXBUF_RESET(_bf) do {				\
-		(_bf)->bf_status = 0;				\
-		(_bf)->bf_lastbf = NULL;			\
-		(_bf)->bf_next = NULL;				\
-		memset(&((_bf)->bf_state), 0,			\
-		       sizeof(struct ath_buf_state));		\
-	} while (0)
-
-/**
- * enum buffer_type - Buffer type flags
- *
- * @BUF_HT: Send this buffer using HT capabilities
- * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
- * @BUF_AGGR: Indicates whether the buffer can be aggregated
- *	(used in aggregation scheduling)
- * @BUF_RETRY: Indicates whether the buffer is retried
- * @BUF_XRETRY: To denote excessive retries of the buffer
- */
-enum buffer_type {
-	BUF_HT			= BIT(1),
-	BUF_AMPDU		= BIT(2),
-	BUF_AGGR		= BIT(3),
-	BUF_RETRY		= BIT(4),
-	BUF_XRETRY		= BIT(5),
-};
-
-struct ath_buf_state {
-	int bfs_nframes;
-	u16 bfs_al;
-	u16 bfs_frmlen;
-	int bfs_seqno;
-	int bfs_tidno;
-	int bfs_retries;
-	u32 bf_type;
-	u32 bfs_keyix;
-	enum ath9k_key_type bfs_keytype;
-};
-
-#define bf_nframes      	bf_state.bfs_nframes
-#define bf_al           	bf_state.bfs_al
-#define bf_frmlen       	bf_state.bfs_frmlen
-#define bf_retries      	bf_state.bfs_retries
-#define bf_seqno        	bf_state.bfs_seqno
-#define bf_tidno        	bf_state.bfs_tidno
-#define bf_keyix                bf_state.bfs_keyix
-#define bf_keytype      	bf_state.bfs_keytype
-#define bf_isht(bf)		(bf->bf_state.bf_type & BUF_HT)
-#define bf_isampdu(bf)		(bf->bf_state.bf_type & BUF_AMPDU)
-#define bf_isaggr(bf)		(bf->bf_state.bf_type & BUF_AGGR)
-#define bf_isretried(bf)	(bf->bf_state.bf_type & BUF_RETRY)
-#define bf_isxretried(bf)	(bf->bf_state.bf_type & BUF_XRETRY)
-
-struct ath_buf {
-	struct list_head list;
-	struct ath_buf *bf_lastbf;	/* last buf of this unit (a frame or
-					   an aggregate) */
-	struct ath_buf *bf_next;	/* next subframe in the aggregate */
-	void *bf_mpdu;			/* enclosing frame structure */
-	struct ath_desc *bf_desc;	/* virtual addr of desc */
-	dma_addr_t bf_daddr;		/* physical addr of desc */
-	dma_addr_t bf_buf_addr;		/* physical addr of data buffer */
-	u32 bf_status;
-	u16 bf_flags;
-	struct ath_buf_state bf_state;
-	dma_addr_t bf_dmacontext;
-};
-
-#define ATH_RXBUF_RESET(_bf)    ((_bf)->bf_status = 0)
-#define ATH_BUFSTATUS_STALE     0x00000002
-
-struct ath_descdma {
-	const char *dd_name;
-	struct ath_desc *dd_desc;
-	dma_addr_t dd_desc_paddr;
-	u32 dd_desc_len;
-	struct ath_buf *dd_bufptr;
-	dma_addr_t dd_dmacontext;
-};
-
-int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
-		      struct list_head *head, const char *name,
-		      int nbuf, int ndesc);
-void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
-			 struct list_head *head);
-
-/***********/
-/* RX / TX */
-/***********/
-
-#define ATH_MAX_ANTENNA         3
-#define ATH_RXBUF               512
-#define WME_NUM_TID             16
-#define ATH_TXBUF               512
-#define ATH_TXMAXTRY            13
-#define ATH_11N_TXMAXTRY        10
-#define ATH_MGT_TXMAXTRY        4
-#define WME_BA_BMP_SIZE         64
-#define WME_MAX_BA              WME_BA_BMP_SIZE
-#define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
-
-#define TID_TO_WME_AC(_tid)				\
-	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
-	 (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK :	\
-	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
-	 WME_AC_VO)
-
-#define WME_AC_BE   0
-#define WME_AC_BK   1
-#define WME_AC_VI   2
-#define WME_AC_VO   3
-#define WME_NUM_AC  4
-
-#define ADDBA_EXCHANGE_ATTEMPTS    10
-#define ATH_AGGR_DELIM_SZ          4
-#define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
-/* number of delimiters for encryption padding */
-#define ATH_AGGR_ENCRYPTDELIM      10
-/* minimum h/w qdepth to be sustained to maximize aggregation */
-#define ATH_AGGR_MIN_QDEPTH        2
-#define ATH_AMPDU_SUBFRAME_DEFAULT 32
-#define ATH_AMPDU_LIMIT_MAX        (64 * 1024 - 1)
-#define ATH_AMPDU_LIMIT_DEFAULT    ATH_AMPDU_LIMIT_MAX
-
-#define IEEE80211_SEQ_SEQ_SHIFT    4
-#define IEEE80211_SEQ_MAX          4096
-#define IEEE80211_MIN_AMPDU_BUF    0x8
-#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
-#define IEEE80211_WEP_IVLEN        3
-#define IEEE80211_WEP_KIDLEN       1
-#define IEEE80211_WEP_CRCLEN       4
-#define IEEE80211_MAX_MPDU_LEN     (3840 + FCS_LEN +		\
-				    (IEEE80211_WEP_IVLEN +	\
-				     IEEE80211_WEP_KIDLEN +	\
-				     IEEE80211_WEP_CRCLEN))
-
-/* return whether a bit at index _n in bitmap _bm is set
- * _sz is the size of the bitmap  */
-#define ATH_BA_ISSET(_bm, _n)  (((_n) < (WME_BA_BMP_SIZE)) &&		\
-				((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
-
-/* return block-ack bitmap index given sequence and starting sequence */
-#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
-
-/* returns delimiter padding required given the packet length */
-#define ATH_AGGR_GET_NDELIM(_len)					\
-	(((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?           \
-	  (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
-
-#define BAW_WITHIN(_start, _bawsz, _seqno) \
-	((((_seqno) - (_start)) & 4095) < (_bawsz))
-
-#define ATH_DS_BA_SEQ(_ds)         ((_ds)->ds_us.tx.ts_seqnum)
-#define ATH_DS_BA_BITMAP(_ds)      (&(_ds)->ds_us.tx.ba_low)
-#define ATH_DS_TX_BA(_ds)          ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
-#define ATH_AN_2_TID(_an, _tidno)  (&(_an)->tid[(_tidno)])
-
-enum ATH_AGGR_STATUS {
-	ATH_AGGR_DONE,
-	ATH_AGGR_BAW_CLOSED,
-	ATH_AGGR_LIMITED,
-};
-
-struct ath_txq {
-	u32 axq_qnum;
-	u32 *axq_link;
-	struct list_head axq_q;
-	spinlock_t axq_lock;
-	u32 axq_depth;
-	u8 axq_aggr_depth;
-	u32 axq_totalqueued;
-	bool stopped;
-	struct ath_buf *axq_linkbuf;
-
-	/* first desc of the last descriptor that contains CTS */
-	struct ath_desc *axq_lastdsWithCTS;
-
-	/* final desc of the gating desc that determines whether
-	   lastdsWithCTS has been DMA'ed or not */
-	struct ath_desc *axq_gatingds;
-
-	struct list_head axq_acq;
-};
-
-#define AGGR_CLEANUP         BIT(1)
-#define AGGR_ADDBA_COMPLETE  BIT(2)
-#define AGGR_ADDBA_PROGRESS  BIT(3)
-
-struct ath_atx_tid {
-	struct list_head list;
-	struct list_head buf_q;
-	struct ath_node *an;
-	struct ath_atx_ac *ac;
-	struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
-	u16 seq_start;
-	u16 seq_next;
-	u16 baw_size;
-	int tidno;
-	int baw_head;	/* first un-acked tx buffer */
-	int baw_tail;	/* next unused tx buffer slot */
-	int sched;
-	int paused;
-	u8 state;
-	int addba_exchangeattempts;
-};
-
-struct ath_atx_ac {
-	int sched;
-	int qnum;
-	struct list_head list;
-	struct list_head tid_q;
-};
-
-struct ath_tx_control {
-	struct ath_txq *txq;
-	int if_id;
-	enum ath9k_internal_frame_type frame_type;
-};
-
-#define ATH_TX_ERROR        0x01
-#define ATH_TX_XRETRY       0x02
-#define ATH_TX_BAR          0x04
-
-/* All RSSI values are noise floor adjusted */
-struct ath_tx_stat {
-	int rssi;
-	int rssictl[ATH_MAX_ANTENNA];
-	int rssiextn[ATH_MAX_ANTENNA];
-	int rateieee;
-	int rateKbps;
-	int ratecode;
-	int flags;
-	u32 airtime;	/* time on air per final tx rate */
-};
-
-struct aggr_rifs_param {
-	int param_max_frames;
-	int param_max_len;
-	int param_rl;
-	int param_al;
-	struct ath_rc_series *param_rcs;
-};
-
-struct ath_node {
-	struct ath_softc *an_sc;
-	struct ath_atx_tid tid[WME_NUM_TID];
-	struct ath_atx_ac ac[WME_NUM_AC];
-	u16 maxampdu;
-	u8 mpdudensity;
-};
-
-struct ath_tx {
-	u16 seq_no;
-	u32 txqsetup;
-	int hwq_map[ATH9K_WME_AC_VO+1];
-	spinlock_t txbuflock;
-	struct list_head txbuf;
-	struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
-	struct ath_descdma txdma;
-};
-
-struct ath_rx {
-	u8 defant;
-	u8 rxotherant;
-	u32 *rxlink;
-	int bufsize;
-	unsigned int rxfilter;
-	spinlock_t rxflushlock;
-	spinlock_t rxbuflock;
-	struct list_head rxbuf;
-	struct ath_descdma rxdma;
-};
-
-int ath_startrecv(struct ath_softc *sc);
-bool ath_stoprecv(struct ath_softc *sc);
-void ath_flushrecv(struct ath_softc *sc);
-u32 ath_calcrxfilter(struct ath_softc *sc);
-int ath_rx_init(struct ath_softc *sc, int nbufs);
-void ath_rx_cleanup(struct ath_softc *sc);
-int ath_rx_tasklet(struct ath_softc *sc, int flush);
-struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
-void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
-int ath_tx_setup(struct ath_softc *sc, int haltype);
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
-void ath_draintxq(struct ath_softc *sc,
-		     struct ath_txq *txq, bool retry_tx);
-void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
-void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
-void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
-int ath_tx_init(struct ath_softc *sc, int nbufs);
-int ath_tx_cleanup(struct ath_softc *sc);
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
-int ath_txq_update(struct ath_softc *sc, int qnum,
-		   struct ath9k_tx_queue_info *q);
-int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
-		 struct ath_tx_control *txctl);
-void ath_tx_tasklet(struct ath_softc *sc);
-void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
-bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
-int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-		      u16 tid, u16 *ssn);
-int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-
-/********/
-/* VIFs */
-/********/
-
-struct ath_vif {
-	int av_bslot;
-	__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
-	enum nl80211_iftype av_opmode;
-	struct ath_buf *av_bcbuf;
-	struct ath_tx_control av_btxctl;
-	u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */
-};
-
-/*******************/
-/* Beacon Handling */
-/*******************/
-
-/*
- * Regardless of the number of beacons we stagger, (i.e. regardless of the
- * number of BSSIDs) if a given beacon does not go out even after waiting this
- * number of beacon intervals, the game's up.
- */
-#define BSTUCK_THRESH           	(9 * ATH_BCBUF)
-#define	ATH_BCBUF               	4
-#define ATH_DEFAULT_BINTVAL     	100 /* TU */
-#define ATH_DEFAULT_BMISS_LIMIT 	10
-#define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
-
-struct ath_beacon_config {
-	u16 beacon_interval;
-	u16 listen_interval;
-	u16 dtim_period;
-	u16 bmiss_timeout;
-	u8 dtim_count;
-};
-
-struct ath_beacon {
-	enum {
-		OK,		/* no change needed */
-		UPDATE,		/* update pending */
-		COMMIT		/* beacon sent, commit change */
-	} updateslot;		/* slot time update fsm */
-
-	u32 beaconq;
-	u32 bmisscnt;
-	u32 ast_be_xmit;
-	u64 bc_tstamp;
-	struct ieee80211_vif *bslot[ATH_BCBUF];
-	struct ath_wiphy *bslot_aphy[ATH_BCBUF];
-	int slottime;
-	int slotupdate;
-	struct ath9k_tx_queue_info beacon_qi;
-	struct ath_descdma bdma;
-	struct ath_txq *cabq;
-	struct list_head bbuf;
-};
-
-void ath_beacon_tasklet(unsigned long data);
-void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
-int ath_beaconq_setup(struct ath_hw *ah);
-int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
-void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
-
-/*******/
-/* ANI */
-/*******/
-
-#define ATH_STA_SHORT_CALINTERVAL 1000    /* 1 second */
-#define ATH_AP_SHORT_CALINTERVAL  100     /* 100 ms */
-#define ATH_ANI_POLLINTERVAL      100     /* 100 ms */
-#define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
-#define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
-
-struct ath_ani {
-	bool caldone;
-	int16_t noise_floor;
-	unsigned int longcal_timer;
-	unsigned int shortcal_timer;
-	unsigned int resetcal_timer;
-	unsigned int checkani_timer;
-	struct timer_list timer;
-};
-
-/********************/
-/*   LED Control    */
-/********************/
-
-#define ATH_LED_PIN	1
-#define ATH_LED_ON_DURATION_IDLE	350	/* in msecs */
-#define ATH_LED_OFF_DURATION_IDLE	250	/* in msecs */
-
-enum ath_led_type {
-	ATH_LED_RADIO,
-	ATH_LED_ASSOC,
-	ATH_LED_TX,
-	ATH_LED_RX
-};
-
-struct ath_led {
-	struct ath_softc *sc;
-	struct led_classdev led_cdev;
-	enum ath_led_type led_type;
-	char name[32];
-	bool registered;
-};
-
-/* Rfkill */
-#define ATH_RFKILL_POLL_INTERVAL	2000 /* msecs */
-
-struct ath_rfkill {
-	struct rfkill *rfkill;
-	struct delayed_work rfkill_poll;
-	char rfkill_name[32];
-};
-
-/********************/
-/* Main driver core */
-/********************/
-
-/*
- * Default cache line size, in bytes.
- * Used when PCI device not fully initialized by bootrom/BIOS
-*/
-#define DEFAULT_CACHELINE       32
-#define	ATH_DEFAULT_NOISE_FLOOR -95
-#define ATH_REGCLASSIDS_MAX     10
-#define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
-#define ATH_MAX_SW_RETRIES      10
-#define ATH_CHAN_MAX            255
-#define IEEE80211_WEP_NKID      4       /* number of key ids */
-
-/*
- * The key cache is used for h/w cipher state and also for
- * tracking station state such as the current tx antenna.
- * We also setup a mapping table between key cache slot indices
- * and station state to short-circuit node lookups on rx.
- * Different parts have different size key caches.  We handle
- * up to ATH_KEYMAX entries (could dynamically allocate state).
- */
-#define	ATH_KEYMAX	        128     /* max key cache size we handle */
-
-#define ATH_TXPOWER_MAX         100     /* .5 dBm units */
-#define ATH_RSSI_DUMMY_MARKER   0x127
-#define ATH_RATE_DUMMY_MARKER   0
-
-#define SC_OP_INVALID           BIT(0)
-#define SC_OP_BEACONS           BIT(1)
-#define SC_OP_RXAGGR            BIT(2)
-#define SC_OP_TXAGGR            BIT(3)
-#define SC_OP_CHAINMASK_UPDATE  BIT(4)
-#define SC_OP_FULL_RESET        BIT(5)
-#define SC_OP_PREAMBLE_SHORT    BIT(6)
-#define SC_OP_PROTECT_ENABLE    BIT(7)
-#define SC_OP_RXFLUSH           BIT(8)
-#define SC_OP_LED_ASSOCIATED    BIT(9)
-#define SC_OP_RFKILL_REGISTERED BIT(10)
-#define SC_OP_RFKILL_SW_BLOCKED BIT(11)
-#define SC_OP_RFKILL_HW_BLOCKED BIT(12)
-#define SC_OP_WAIT_FOR_BEACON   BIT(13)
-#define SC_OP_LED_ON            BIT(14)
-#define SC_OP_SCANNING          BIT(15)
-#define SC_OP_TSF_RESET         BIT(16)
-
-struct ath_bus_ops {
-	void		(*read_cachesize)(struct ath_softc *sc, int *csz);
-	void		(*cleanup)(struct ath_softc *sc);
-	bool		(*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data);
-};
-
-struct ath_wiphy;
-
-struct ath_softc {
-	struct ieee80211_hw *hw;
-	struct device *dev;
-
-	spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
-	struct ath_wiphy *pri_wiphy;
-	struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
-				       * have NULL entries */
-	int num_sec_wiphy; /* number of sec_wiphy pointers in the array */
-	int chan_idx;
-	int chan_is_ht;
-	struct ath_wiphy *next_wiphy;
-	struct work_struct chan_work;
-	int wiphy_select_failures;
-	unsigned long wiphy_select_first_fail;
-	struct delayed_work wiphy_work;
-	unsigned long wiphy_scheduler_int;
-	int wiphy_scheduler_index;
-
-	struct tasklet_struct intr_tq;
-	struct tasklet_struct bcon_tasklet;
-	struct ath_hw *sc_ah;
-	void __iomem *mem;
-	int irq;
-	spinlock_t sc_resetlock;
-	spinlock_t sc_serial_rw;
-	struct mutex mutex;
-
-	u8 curbssid[ETH_ALEN];
-	u8 bssidmask[ETH_ALEN];
-	u32 intrstatus;
-	u32 sc_flags; /* SC_OP_* */
-	u16 curtxpow;
-	u16 curaid;
-	u16 cachelsz;
-	u8 nbcnvifs;
-	u16 nvifs;
-	u8 tx_chainmask;
-	u8 rx_chainmask;
-	u32 keymax;
-	DECLARE_BITMAP(keymap, ATH_KEYMAX);
-	u8 splitmic;
-	atomic_t ps_usecount;
-	enum ath9k_int imask;
-	enum ath9k_ht_extprotspacing ht_extprotspacing;
-	enum ath9k_ht_macmode tx_chan_width;
-
-	struct ath_config config;
-	struct ath_rx rx;
-	struct ath_tx tx;
-	struct ath_beacon beacon;
-	struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
-	struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
-	struct ath_rate_table *cur_rate_table;
-	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
-
-	struct ath_led radio_led;
-	struct ath_led assoc_led;
-	struct ath_led tx_led;
-	struct ath_led rx_led;
-	struct delayed_work ath_led_blink_work;
-	int led_on_duration;
-	int led_off_duration;
-	int led_on_cnt;
-	int led_off_cnt;
-
-	struct ath_rfkill rf_kill;
-	struct ath_ani ani;
-	struct ath9k_node_stats nodestats;
-#ifdef CONFIG_ATH9K_DEBUG
-	struct ath9k_debug debug;
-#endif
-	struct ath_bus_ops *bus_ops;
-};
-
-struct ath_wiphy {
-	struct ath_softc *sc; /* shared for all virtual wiphys */
-	struct ieee80211_hw *hw;
-	enum ath_wiphy_state {
-		ATH_WIPHY_INACTIVE,
-		ATH_WIPHY_ACTIVE,
-		ATH_WIPHY_PAUSING,
-		ATH_WIPHY_PAUSED,
-		ATH_WIPHY_SCAN,
-	} state;
-	int chan_idx;
-	int chan_is_ht;
-};
-
-int ath_reset(struct ath_softc *sc, bool retry_tx);
-int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
-int ath_cabq_update(struct ath_softc *);
-
-static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
-{
-	sc->bus_ops->read_cachesize(sc, csz);
-}
-
-static inline void ath_bus_cleanup(struct ath_softc *sc)
-{
-	sc->bus_ops->cleanup(sc);
-}
-
-extern struct ieee80211_ops ath9k_ops;
-
-irqreturn_t ath_isr(int irq, void *dev);
-void ath_cleanup(struct ath_softc *sc);
-int ath_attach(u16 devid, struct ath_softc *sc);
-void ath_detach(struct ath_softc *sc);
-const char *ath_mac_bb_name(u32 mac_bb_version);
-const char *ath_rf_name(u16 rf_version);
-void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
-void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
-			   struct ath9k_channel *ichan);
-void ath_update_chainmask(struct ath_softc *sc, int is_ht);
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
-		    struct ath9k_channel *hchan);
-void ath_radio_enable(struct ath_softc *sc);
-void ath_radio_disable(struct ath_softc *sc);
-
-#ifdef CONFIG_PCI
-int ath_pci_init(void);
-void ath_pci_exit(void);
-#else
-static inline int ath_pci_init(void) { return 0; };
-static inline void ath_pci_exit(void) {};
-#endif
-
-#ifdef CONFIG_ATHEROS_AR71XX
-int ath_ahb_init(void);
-void ath_ahb_exit(void);
-#else
-static inline int ath_ahb_init(void) { return 0; };
-static inline void ath_ahb_exit(void) {};
-#endif
-
-static inline void ath9k_ps_wakeup(struct ath_softc *sc)
-{
-	if (atomic_inc_return(&sc->ps_usecount) == 1)
-		if (sc->sc_ah->power_mode !=  ATH9K_PM_AWAKE) {
-			sc->sc_ah->restore_mode = sc->sc_ah->power_mode;
-			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
-		}
-}
-
-static inline void ath9k_ps_restore(struct ath_softc *sc)
-{
-	if (atomic_dec_and_test(&sc->ps_usecount))
-		if ((sc->hw->conf.flags & IEEE80211_CONF_PS) &&
-		    !(sc->sc_flags & SC_OP_WAIT_FOR_BEACON))
-			ath9k_hw_setpower(sc->sc_ah,
-					  sc->sc_ah->restore_mode);
-}
-
-
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
-int ath9k_wiphy_add(struct ath_softc *sc);
-int ath9k_wiphy_del(struct ath_wiphy *aphy);
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
-int ath9k_wiphy_pause(struct ath_wiphy *aphy);
-int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
-int ath9k_wiphy_select(struct ath_wiphy *aphy);
-void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int);
-void ath9k_wiphy_chan_work(struct work_struct *work);
-bool ath9k_wiphy_started(struct ath_softc *sc);
-void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
-				  struct ath_wiphy *selected);
-bool ath9k_wiphy_scanning(struct ath_softc *sc);
-void ath9k_wiphy_work(struct work_struct *work);
-
-/*
- * Read and write, they both share the same lock. We do this to serialize
- * reads and writes on Atheros 802.11n PCI devices only. This is required
- * as the FIFO on these devices can only accept sanely 2 requests. After
- * that the device goes bananas. Serializing the reads/writes prevents this
- * from happening.
- */
-
-static inline void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val)
-{
-	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
-		unsigned long flags;
-		spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
-		iowrite32(val, ah->ah_sc->mem + reg_offset);
-		spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
-	} else
-		iowrite32(val, ah->ah_sc->mem + reg_offset);
-}
-
-static inline unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset)
-{
-	u32 val;
-	if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
-		unsigned long flags;
-		spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
-		val = ioread32(ah->ah_sc->mem + reg_offset);
-		spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
-	} else
-		val = ioread32(ah->ah_sc->mem + reg_offset);
-	return val;
-}
-
-#endif /* ATH9K_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/beacon.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/beacon.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/beacon.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/beacon.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,746 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-#define FUDGE 2
-
-/*
- *  This function will modify certain transmit queue properties depending on
- *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
- *  settings and channel width min/max
-*/
-static int ath_beaconq_config(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath9k_tx_queue_info qi;
-
-	ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
-	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
-		/* Always burst out beacon and CAB traffic. */
-		qi.tqi_aifs = 1;
-		qi.tqi_cwmin = 0;
-		qi.tqi_cwmax = 0;
-	} else {
-		/* Adhoc mode; important thing is to use 2x cwmin. */
-		qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs;
-		qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin;
-		qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax;
-	}
-
-	if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"unable to update h/w beacon queue parameters\n");
-		return 0;
-	} else {
-		ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
-		return 1;
-	}
-}
-
-/*
- *  Associates the beacon frame buffer with a transmit descriptor.  Will set
- *  up all required antenna switch parameters, rate codes, and channel flags.
- *  Beacons are always sent out at the lowest rate, and are not retried.
-*/
-static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
-			     struct ath_buf *bf)
-{
-	struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_desc *ds;
-	struct ath9k_11n_rate_series series[4];
-	struct ath_rate_table *rt;
-	int flags, antenna, ctsrate = 0, ctsduration = 0;
-	u8 rate;
-
-	ds = bf->bf_desc;
-	flags = ATH9K_TXDESC_NOACK;
-
-	if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
-	     (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
-	    (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
-		ds->ds_link = bf->bf_daddr; /* self-linked */
-		flags |= ATH9K_TXDESC_VEOL;
-		/* Let hardware handle antenna switching. */
-		antenna = 0;
-	} else {
-		ds->ds_link = 0;
-		/*
-		 * Switch antenna every beacon.
-		 * Should only switch every beacon period, not for every SWBA
-		 * XXX assumes two antennae
-		 */
-		antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
-	}
-
-	ds->ds_data = bf->bf_buf_addr;
-
-	rt = sc->cur_rate_table;
-	rate = rt->info[0].ratecode;
-	if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
-		rate |= rt->info[0].short_preamble;
-
-	ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
-			       ATH9K_PKT_TYPE_BEACON,
-			       MAX_RATE_POWER,
-			       ATH9K_TXKEYIX_INVALID,
-			       ATH9K_KEY_TYPE_CLEAR,
-			       flags);
-
-	/* NB: beacon's BufLen must be a multiple of 4 bytes */
-	ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
-			    true, true, ds);
-
-	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
-	series[0].Tries = 1;
-	series[0].Rate = rate;
-	series[0].ChSel = sc->tx_chainmask;
-	series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
-	ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
-				     series, 4, 0);
-}
-
-static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
-					   struct ieee80211_vif *vif)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_buf *bf;
-	struct ath_vif *avp;
-	struct sk_buff *skb;
-	struct ath_txq *cabq;
-	struct ieee80211_tx_info *info;
-	int cabq_depth;
-
-	if (aphy->state != ATH_WIPHY_ACTIVE)
-		return NULL;
-
-	avp = (void *)vif->drv_priv;
-	cabq = sc->beacon.cabq;
-
-	if (avp->av_bcbuf == NULL) {
-		DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n",
-			avp, avp->av_bcbuf);
-		return NULL;
-	}
-
-	/* Release the old beacon first */
-
-	bf = avp->av_bcbuf;
-	skb = (struct sk_buff *)bf->bf_mpdu;
-	if (skb) {
-		dma_unmap_single(sc->dev, bf->bf_dmacontext,
-				 skb->len, DMA_TO_DEVICE);
-		dev_kfree_skb_any(skb);
-	}
-
-	/* Get a new beacon from mac80211 */
-
-	skb = ieee80211_beacon_get(hw, vif);
-	bf->bf_mpdu = skb;
-	if (skb == NULL)
-		return NULL;
-	((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
-		avp->tsf_adjust;
-
-	info = IEEE80211_SKB_CB(skb);
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		/*
-		 * TODO: make sure the seq# gets assigned properly (vs. other
-		 * TX frames)
-		 */
-		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-		sc->tx.seq_no += 0x10;
-		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
-	}
-
-	bf->bf_buf_addr = bf->bf_dmacontext =
-		dma_map_single(sc->dev, skb->data,
-			       skb->len, DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
-		dev_kfree_skb_any(skb);
-		bf->bf_mpdu = NULL;
-		DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n");
-		return NULL;
-	}
-
-	skb = ieee80211_get_buffered_bc(hw, vif);
-
-	/*
-	 * if the CABQ traffic from previous DTIM is pending and the current
-	 *  beacon is also a DTIM.
-	 *  1) if there is only one vif let the cab traffic continue.
-	 *  2) if there are more than one vif and we are using staggered
-	 *     beacons, then drain the cabq by dropping all the frames in
-	 *     the cabq so that the current vifs cab traffic can be scheduled.
-	 */
-	spin_lock_bh(&cabq->axq_lock);
-	cabq_depth = cabq->axq_depth;
-	spin_unlock_bh(&cabq->axq_lock);
-
-	if (skb && cabq_depth) {
-		if (sc->nvifs > 1) {
-			DPRINTF(sc, ATH_DBG_BEACON,
-				"Flushing previous cabq traffic\n");
-			ath_draintxq(sc, cabq, false);
-		}
-	}
-
-	ath_beacon_setup(sc, avp, bf);
-
-	while (skb) {
-		ath_tx_cabq(hw, skb);
-		skb = ieee80211_get_buffered_bc(hw, vif);
-	}
-
-	return bf;
-}
-
-/*
- * Startup beacon transmission for adhoc mode when they are sent entirely
- * by the hardware using the self-linked descriptor + veol trick.
-*/
-static void ath_beacon_start_adhoc(struct ath_softc *sc,
-				   struct ieee80211_vif *vif)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_buf *bf;
-	struct ath_vif *avp;
-	struct sk_buff *skb;
-
-	avp = (void *)vif->drv_priv;
-
-	if (avp->av_bcbuf == NULL)
-		return;
-
-	bf = avp->av_bcbuf;
-	skb = (struct sk_buff *) bf->bf_mpdu;
-
-	ath_beacon_setup(sc, avp, bf);
-
-	/* NB: caller is known to have already stopped tx dma */
-	ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
-	ath9k_hw_txstart(ah, sc->beacon.beaconq);
-	DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
-		sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
-}
-
-int ath_beaconq_setup(struct ath_hw *ah)
-{
-	struct ath9k_tx_queue_info qi;
-
-	memset(&qi, 0, sizeof(qi));
-	qi.tqi_aifs = 1;
-	qi.tqi_cwmin = 0;
-	qi.tqi_cwmax = 0;
-	/* NB: don't enable any interrupts */
-	return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
-}
-
-int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
-{
-	struct ath_softc *sc = aphy->sc;
-	struct ath_vif *avp;
-	struct ath_buf *bf;
-	struct sk_buff *skb;
-	__le64 tstamp;
-
-	avp = (void *)vif->drv_priv;
-
-	/* Allocate a beacon descriptor if we haven't done so. */
-	if (!avp->av_bcbuf) {
-		/* Allocate beacon state for hostap/ibss.  We know
-		 * a buffer is available. */
-		avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
-						 struct ath_buf, list);
-		list_del(&avp->av_bcbuf->list);
-
-		if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
-		    !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
-			int slot;
-			/*
-			 * Assign the vif to a beacon xmit slot. As
-			 * above, this cannot fail to find one.
-			 */
-			avp->av_bslot = 0;
-			for (slot = 0; slot < ATH_BCBUF; slot++)
-				if (sc->beacon.bslot[slot] == NULL) {
-					/*
-					 * XXX hack, space out slots to better
-					 * deal with misses
-					 */
-					if (slot+1 < ATH_BCBUF &&
-					    sc->beacon.bslot[slot+1] == NULL) {
-						avp->av_bslot = slot+1;
-						break;
-					}
-					avp->av_bslot = slot;
-					/* NB: keep looking for a double slot */
-				}
-			BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
-			sc->beacon.bslot[avp->av_bslot] = vif;
-			sc->beacon.bslot_aphy[avp->av_bslot] = aphy;
-			sc->nbcnvifs++;
-		}
-	}
-
-	/* release the previous beacon frame, if it already exists. */
-	bf = avp->av_bcbuf;
-	if (bf->bf_mpdu != NULL) {
-		skb = (struct sk_buff *)bf->bf_mpdu;
-		dma_unmap_single(sc->dev, bf->bf_dmacontext,
-				 skb->len, DMA_TO_DEVICE);
-		dev_kfree_skb_any(skb);
-		bf->bf_mpdu = NULL;
-	}
-
-	/* NB: the beacon data buffer must be 32-bit aligned. */
-	skb = ieee80211_beacon_get(sc->hw, vif);
-	if (skb == NULL) {
-		DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n");
-		return -ENOMEM;
-	}
-
-	tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-	sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
-	/* Calculate a TSF adjustment factor required for staggered beacons. */
-	if (avp->av_bslot > 0) {
-		u64 tsfadjust;
-		int intval;
-
-		intval = sc->hw->conf.beacon_int ?
-			sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
-
-		/*
-		 * Calculate the TSF offset for this beacon slot, i.e., the
-		 * number of usecs that need to be added to the timestamp field
-		 * in Beacon and Probe Response frames. Beacon slot 0 is
-		 * processed at the correct offset, so it does not require TSF
-		 * adjustment. Other slots are adjusted to get the timestamp
-		 * close to the TBTT for the BSS.
-		 */
-		tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
-		avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
-
-		DPRINTF(sc, ATH_DBG_BEACON,
-			"stagger beacons, bslot %d intval %u tsfadjust %llu\n",
-			avp->av_bslot, intval, (unsigned long long)tsfadjust);
-
-		((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
-			avp->tsf_adjust;
-	} else
-		avp->tsf_adjust = cpu_to_le64(0);
-
-	bf->bf_mpdu = skb;
-	bf->bf_buf_addr = bf->bf_dmacontext =
-		dma_map_single(sc->dev, skb->data,
-			       skb->len, DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
-		dev_kfree_skb_any(skb);
-		bf->bf_mpdu = NULL;
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"dma_mapping_error on beacon alloc\n");
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
-{
-	if (avp->av_bcbuf != NULL) {
-		struct ath_buf *bf;
-
-		if (avp->av_bslot != -1) {
-			sc->beacon.bslot[avp->av_bslot] = NULL;
-			sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
-			sc->nbcnvifs--;
-		}
-
-		bf = avp->av_bcbuf;
-		if (bf->bf_mpdu != NULL) {
-			struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
-			dma_unmap_single(sc->dev, bf->bf_dmacontext,
-					 skb->len, DMA_TO_DEVICE);
-			dev_kfree_skb_any(skb);
-			bf->bf_mpdu = NULL;
-		}
-		list_add_tail(&bf->list, &sc->beacon.bbuf);
-
-		avp->av_bcbuf = NULL;
-	}
-}
-
-void ath_beacon_tasklet(unsigned long data)
-{
-	struct ath_softc *sc = (struct ath_softc *)data;
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_buf *bf = NULL;
-	struct ieee80211_vif *vif;
-	struct ath_wiphy *aphy;
-	int slot;
-	u32 bfaddr, bc = 0, tsftu;
-	u64 tsf;
-	u16 intval;
-
-	/*
-	 * Check if the previous beacon has gone out.  If
-	 * not don't try to post another, skip this period
-	 * and wait for the next.  Missed beacons indicate
-	 * a problem and should not occur.  If we miss too
-	 * many consecutive beacons reset the device.
-	 */
-	if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
-		sc->beacon.bmisscnt++;
-
-		if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
-			DPRINTF(sc, ATH_DBG_BEACON,
-				"missed %u consecutive beacons\n",
-				sc->beacon.bmisscnt);
-		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
-			DPRINTF(sc, ATH_DBG_BEACON,
-				"beacon is officially stuck\n");
-			ath_reset(sc, false);
-		}
-
-		return;
-	}
-
-	if (sc->beacon.bmisscnt != 0) {
-		DPRINTF(sc, ATH_DBG_BEACON,
-			"resume beacon xmit after %u misses\n",
-			sc->beacon.bmisscnt);
-		sc->beacon.bmisscnt = 0;
-	}
-
-	/*
-	 * Generate beacon frames. we are sending frames
-	 * staggered so calculate the slot for this frame based
-	 * on the tsf to safeguard against missing an swba.
-	 */
-
-	intval = sc->hw->conf.beacon_int ?
-		sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
-
-	tsf = ath9k_hw_gettsf64(ah);
-	tsftu = TSF_TO_TU(tsf>>32, tsf);
-	slot = ((tsftu % intval) * ATH_BCBUF) / intval;
-	/*
-	 * Reverse the slot order to get slot 0 on the TBTT offset that does
-	 * not require TSF adjustment and other slots adding
-	 * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
-	 * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
-	 * and slot 0 is at correct offset to TBTT.
-	 */
-	slot = ATH_BCBUF - slot - 1;
-	vif = sc->beacon.bslot[slot];
-	aphy = sc->beacon.bslot_aphy[slot];
-
-	DPRINTF(sc, ATH_DBG_BEACON,
-		"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
-		slot, tsf, tsftu, intval, vif);
-
-	bfaddr = 0;
-	if (vif) {
-		bf = ath_beacon_generate(aphy->hw, vif);
-		if (bf != NULL) {
-			bfaddr = bf->bf_daddr;
-			bc = 1;
-		}
-	}
-
-	/*
-	 * Handle slot time change when a non-ERP station joins/leaves
-	 * an 11g network.  The 802.11 layer notifies us via callback,
-	 * we mark updateslot, then wait one beacon before effecting
-	 * the change.  This gives associated stations at least one
-	 * beacon interval to note the state change.
-	 *
-	 * NB: The slot time change state machine is clocked according
-	 *     to whether we are bursting or staggering beacons.  We
-	 *     recognize the request to update and record the current
-	 *     slot then don't transition until that slot is reached
-	 *     again.  If we miss a beacon for that slot then we'll be
-	 *     slow to transition but we'll be sure at least one beacon
-	 *     interval has passed.  When bursting slot is always left
-	 *     set to ATH_BCBUF so this check is a noop.
-	 */
-	if (sc->beacon.updateslot == UPDATE) {
-		sc->beacon.updateslot = COMMIT; /* commit next beacon */
-		sc->beacon.slotupdate = slot;
-	} else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
-		ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime);
-		sc->beacon.updateslot = OK;
-	}
-	if (bfaddr != 0) {
-		/*
-		 * Stop any current dma and put the new frame(s) on the queue.
-		 * This should never fail since we check above that no frames
-		 * are still pending on the queue.
-		 */
-		if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"beacon queue %u did not stop?\n", sc->beacon.beaconq);
-		}
-
-		/* NB: cabq traffic should already be queued and primed */
-		ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
-		ath9k_hw_txstart(ah, sc->beacon.beaconq);
-
-		sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
-	}
-}
-
-/*
- * For multi-bss ap support beacons are either staggered evenly over N slots or
- * burst together.  For the former arrange for the SWBA to be delivered for each
- * slot. Slots that are not occupied will generate nothing.
- */
-static void ath_beacon_config_ap(struct ath_softc *sc,
-				 struct ath_beacon_config *conf,
-				 struct ath_vif *avp)
-{
-	u32 nexttbtt, intval;
-
-	/* Configure the timers only when the TSF has to be reset */
-
-	if (!(sc->sc_flags & SC_OP_TSF_RESET))
-		return;
-
-	/* NB: the beacon interval is kept internally in TU's */
-	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
-	intval /= ATH_BCBUF;    /* for staggered beacons */
-	nexttbtt = intval;
-	intval |= ATH9K_BEACON_RESET_TSF;
-
-	/*
-	 * In AP mode we enable the beacon timers and SWBA interrupts to
-	 * prepare beacon frames.
-	 */
-	intval |= ATH9K_BEACON_ENA;
-	sc->imask |= ATH9K_INT_SWBA;
-	ath_beaconq_config(sc);
-
-	/* Set the computed AP beacon timers */
-
-	ath9k_hw_set_interrupts(sc->sc_ah, 0);
-	ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
-	sc->beacon.bmisscnt = 0;
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
-
-	/* Clear the reset TSF flag, so that subsequent beacon updation
-	   will not reset the HW TSF. */
-
-	sc->sc_flags &= ~SC_OP_TSF_RESET;
-}
-
-/*
- * This sets up the beacon timers according to the timestamp of the last
- * received beacon and the current TSF, configures PCF and DTIM
- * handling, programs the sleep registers so the hardware will wakeup in
- * time to receive beacons, and configures the beacon miss handling so
- * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
- * we've associated with.
- */
-static void ath_beacon_config_sta(struct ath_softc *sc,
-				  struct ath_beacon_config *conf,
-				  struct ath_vif *avp)
-{
-	struct ath9k_beacon_state bs;
-	int dtimperiod, dtimcount, sleepduration;
-	int cfpperiod, cfpcount;
-	u32 nexttbtt = 0, intval, tsftu;
-	u64 tsf;
-
-	memset(&bs, 0, sizeof(bs));
-	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
-
-	/*
-	 * Setup dtim and cfp parameters according to
-	 * last beacon we received (which may be none).
-	 */
-	dtimperiod = conf->dtim_period;
-	if (dtimperiod <= 0)		/* NB: 0 if not known */
-		dtimperiod = 1;
-	dtimcount = conf->dtim_count;
-	if (dtimcount >= dtimperiod)	/* NB: sanity check */
-		dtimcount = 0;
-	cfpperiod = 1;			/* NB: no PCF support yet */
-	cfpcount = 0;
-
-	sleepduration = conf->listen_interval * intval;
-	if (sleepduration <= 0)
-		sleepduration = intval;
-
-	/*
-	 * Pull nexttbtt forward to reflect the current
-	 * TSF and calculate dtim+cfp state for the result.
-	 */
-	tsf = ath9k_hw_gettsf64(sc->sc_ah);
-	tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
-	do {
-		nexttbtt += intval;
-		if (--dtimcount < 0) {
-			dtimcount = dtimperiod - 1;
-			if (--cfpcount < 0)
-				cfpcount = cfpperiod - 1;
-		}
-	} while (nexttbtt < tsftu);
-
-	bs.bs_intval = intval;
-	bs.bs_nexttbtt = nexttbtt;
-	bs.bs_dtimperiod = dtimperiod*intval;
-	bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
-	bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
-	bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
-	bs.bs_cfpmaxduration = 0;
-
-	/*
-	 * Calculate the number of consecutive beacons to miss* before taking
-	 * a BMISS interrupt. The configuration is specified in TU so we only
-	 * need calculate based	on the beacon interval.  Note that we clamp the
-	 * result to at most 15 beacons.
-	 */
-	if (sleepduration > intval) {
-		bs.bs_bmissthreshold = conf->listen_interval *
-			ATH_DEFAULT_BMISS_LIMIT / 2;
-	} else {
-		bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval);
-		if (bs.bs_bmissthreshold > 15)
-			bs.bs_bmissthreshold = 15;
-		else if (bs.bs_bmissthreshold <= 0)
-			bs.bs_bmissthreshold = 1;
-	}
-
-	/*
-	 * Calculate sleep duration. The configuration is given in ms.
-	 * We ensure a multiple of the beacon period is used. Also, if the sleep
-	 * duration is greater than the DTIM period then it makes senses
-	 * to make it a multiple of that.
-	 *
-	 * XXX fixed at 100ms
-	 */
-
-	bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
-	if (bs.bs_sleepduration > bs.bs_dtimperiod)
-		bs.bs_sleepduration = bs.bs_dtimperiod;
-
-	/* TSF out of range threshold fixed at 1 second */
-	bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
-
-	DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-	DPRINTF(sc, ATH_DBG_BEACON,
-		"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
-		bs.bs_bmissthreshold, bs.bs_sleepduration,
-		bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
-
-	/* Set the computed STA beacon timers */
-
-	ath9k_hw_set_interrupts(sc->sc_ah, 0);
-	ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs);
-	sc->imask |= ATH9K_INT_BMISS;
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
-}
-
-static void ath_beacon_config_adhoc(struct ath_softc *sc,
-				    struct ath_beacon_config *conf,
-				    struct ath_vif *avp,
-				    struct ieee80211_vif *vif)
-{
-	u64 tsf;
-	u32 tsftu, intval, nexttbtt;
-
-	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
-
-	/* Pull nexttbtt forward to reflect the current TSF */
-
-	nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
-	if (nexttbtt == 0)
-                nexttbtt = intval;
-        else if (intval)
-                nexttbtt = roundup(nexttbtt, intval);
-
-	tsf = ath9k_hw_gettsf64(sc->sc_ah);
-	tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE;
-	do {
-		nexttbtt += intval;
-	} while (nexttbtt < tsftu);
-
-	DPRINTF(sc, ATH_DBG_BEACON,
-		"IBSS nexttbtt %u intval %u (%u)\n",
-		nexttbtt, intval, conf->beacon_interval);
-
-	/*
-	 * In IBSS mode enable the beacon timers but only enable SWBA interrupts
-	 * if we need to manually prepare beacon frames.  Otherwise we use a
-	 * self-linked tx descriptor and let the hardware deal with things.
-	 */
-	intval |= ATH9K_BEACON_ENA;
-	if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
-		sc->imask |= ATH9K_INT_SWBA;
-
-	ath_beaconq_config(sc);
-
-	/* Set the computed ADHOC beacon timers */
-
-	ath9k_hw_set_interrupts(sc->sc_ah, 0);
-	ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
-	sc->beacon.bmisscnt = 0;
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
-
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
-		ath_beacon_start_adhoc(sc, vif);
-}
-
-void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
-{
-	struct ath_beacon_config conf;
-
-	/* Setup the beacon configuration parameters */
-
-	memset(&conf, 0, sizeof(struct ath_beacon_config));
-	conf.beacon_interval = sc->hw->conf.beacon_int ?
-		sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
-	conf.listen_interval = 1;
-	conf.dtim_period = conf.beacon_interval;
-	conf.dtim_count = 1;
-	conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
-
-	if (vif) {
-		struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
-
-		switch(avp->av_opmode) {
-		case NL80211_IFTYPE_AP:
-			ath_beacon_config_ap(sc, &conf, avp);
-			break;
-		case NL80211_IFTYPE_ADHOC:
-		case NL80211_IFTYPE_MESH_POINT:
-			ath_beacon_config_adhoc(sc, &conf, avp, vif);
-			break;
-		case NL80211_IFTYPE_STATION:
-			ath_beacon_config_sta(sc, &conf, avp);
-			break;
-		default:
-			DPRINTF(sc, ATH_DBG_CONFIG,
-				"Unsupported beaconing mode\n");
-			return;
-		}
-
-		sc->sc_flags |= SC_OP_BEACONS;
-	}
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/calib.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/calib.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/calib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/calib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1060 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-/* We can tune this as we go by monitoring really low values */
-#define ATH9K_NF_TOO_LOW	-60
-
-/* AR5416 may return very high value (like -31 dBm), in those cases the nf
- * is incorrect and we should use the static NF value. Later we can try to
- * find out why they are reporting these values */
-
-static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
-{
-	if (nf > ATH9K_NF_TOO_LOW) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"noise floor value detected (%d) is "
-			"lower than what we think is a "
-			"reasonable value (%d)\n",
-			nf, ATH9K_NF_TOO_LOW);
-		return false;
-	}
-	return true;
-}
-
-static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
-{
-	int16_t nfval;
-	int16_t sort[ATH9K_NF_CAL_HIST_MAX];
-	int i, j;
-
-	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
-		sort[i] = nfCalBuffer[i];
-
-	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
-		for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
-			if (sort[j] > sort[j - 1]) {
-				nfval = sort[j];
-				sort[j] = sort[j - 1];
-				sort[j - 1] = nfval;
-			}
-		}
-	}
-	nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
-
-	return nfval;
-}
-
-static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
-					      int16_t *nfarray)
-{
-	int i;
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
-
-		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
-			h[i].currIndex = 0;
-
-		if (h[i].invalidNFcount > 0) {
-			if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
-			    nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
-				h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
-			} else {
-				h[i].invalidNFcount--;
-				h[i].privNF = nfarray[i];
-			}
-		} else {
-			h[i].privNF =
-				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
-		}
-	}
-	return;
-}
-
-static void ath9k_hw_do_getnf(struct ath_hw *ah,
-			      int16_t nfarray[NUM_NF_READINGS])
-{
-	int16_t nf;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
-	else
-		nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
-
-	if (nf & 0x100)
-		nf = 0 - ((nf ^ 0x1ff) + 1);
-	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-		"NF calibrated [ctl] [chain 0] is %d\n", nf);
-	nfarray[0] = nf;
-
-	if (!AR_SREV_9285(ah)) {
-		if (AR_SREV_9280_10_OR_LATER(ah))
-			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
-					AR9280_PHY_CH1_MINCCA_PWR);
-		else
-			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
-					AR_PHY_CH1_MINCCA_PWR);
-
-		if (nf & 0x100)
-			nf = 0 - ((nf ^ 0x1ff) + 1);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"NF calibrated [ctl] [chain 1] is %d\n", nf);
-		nfarray[1] = nf;
-
-		if (!AR_SREV_9280(ah)) {
-			nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
-					AR_PHY_CH2_MINCCA_PWR);
-			if (nf & 0x100)
-				nf = 0 - ((nf ^ 0x1ff) + 1);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"NF calibrated [ctl] [chain 2] is %d\n", nf);
-			nfarray[2] = nf;
-		}
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
-			AR9280_PHY_EXT_MINCCA_PWR);
-	else
-		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
-			AR_PHY_EXT_MINCCA_PWR);
-
-	if (nf & 0x100)
-		nf = 0 - ((nf ^ 0x1ff) + 1);
-	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-		"NF calibrated [ext] [chain 0] is %d\n", nf);
-	nfarray[3] = nf;
-
-	if (!AR_SREV_9285(ah)) {
-		if (AR_SREV_9280_10_OR_LATER(ah))
-			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
-					AR9280_PHY_CH1_EXT_MINCCA_PWR);
-		else
-			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
-					AR_PHY_CH1_EXT_MINCCA_PWR);
-
-		if (nf & 0x100)
-			nf = 0 - ((nf ^ 0x1ff) + 1);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"NF calibrated [ext] [chain 1] is %d\n", nf);
-		nfarray[4] = nf;
-
-		if (!AR_SREV_9280(ah)) {
-			nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
-					AR_PHY_CH2_EXT_MINCCA_PWR);
-			if (nf & 0x100)
-				nf = 0 - ((nf ^ 0x1ff) + 1);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"NF calibrated [ext] [chain 2] is %d\n", nf);
-			nfarray[5] = nf;
-		}
-	}
-}
-
-static bool getNoiseFloorThresh(struct ath_hw *ah,
-				enum ieee80211_band band,
-				int16_t *nft)
-{
-	switch (band) {
-	case IEEE80211_BAND_5GHZ:
-		*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
-		break;
-	case IEEE80211_BAND_2GHZ:
-		*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
-		break;
-	default:
-		BUG_ON(1);
-		return false;
-	}
-
-	return true;
-}
-
-static void ath9k_hw_setup_calibration(struct ath_hw *ah,
-				       struct hal_cal_list *currCal)
-{
-	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
-		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
-		      currCal->calData->calCountMax);
-
-	switch (currCal->calData->calType) {
-	case IQ_MISMATCH_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"starting IQ Mismatch Calibration\n");
-		break;
-	case ADC_GAIN_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"starting ADC Gain Calibration\n");
-		break;
-	case ADC_DC_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"starting ADC DC Calibration\n");
-		break;
-	case ADC_DC_INIT_CAL:
-		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"starting Init ADC DC Calibration\n");
-		break;
-	}
-
-	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
-		    AR_PHY_TIMING_CTRL4_DO_CAL);
-}
-
-static void ath9k_hw_reset_calibration(struct ath_hw *ah,
-				       struct hal_cal_list *currCal)
-{
-	int i;
-
-	ath9k_hw_setup_calibration(ah, currCal);
-
-	currCal->calState = CAL_RUNNING;
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ah->meas0.sign[i] = 0;
-		ah->meas1.sign[i] = 0;
-		ah->meas2.sign[i] = 0;
-		ah->meas3.sign[i] = 0;
-	}
-
-	ah->cal_samples = 0;
-}
-
-static void ath9k_hw_per_calibration(struct ath_hw *ah,
-				     struct ath9k_channel *ichan,
-				     u8 rxchainmask,
-				     struct hal_cal_list *currCal,
-				     bool *isCalDone)
-{
-	*isCalDone = false;
-
-	if (currCal->calState == CAL_RUNNING) {
-		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
-		      AR_PHY_TIMING_CTRL4_DO_CAL)) {
-
-			currCal->calData->calCollect(ah);
-			ah->cal_samples++;
-
-			if (ah->cal_samples >= currCal->calData->calNumSamples) {
-				int i, numChains = 0;
-				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-					if (rxchainmask & (1 << i))
-						numChains++;
-				}
-
-				currCal->calData->calPostProc(ah, numChains);
-				ichan->CalValid |= currCal->calData->calType;
-				currCal->calState = CAL_DONE;
-				*isCalDone = true;
-			} else {
-				ath9k_hw_setup_calibration(ah, currCal);
-			}
-		}
-	} else if (!(ichan->CalValid & currCal->calData->calType)) {
-		ath9k_hw_reset_calibration(ah, currCal);
-	}
-}
-
-/* Assumes you are talking about the currently configured channel */
-static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
-				     enum hal_cal_types calType)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-
-	switch (calType & ah->supp_cals) {
-	case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
-		return true;
-	case ADC_GAIN_CAL:
-	case ADC_DC_CAL:
-		if (conf->channel->band == IEEE80211_BAND_5GHZ &&
-		  conf_is_ht20(conf))
-			return true;
-		break;
-	}
-	return false;
-}
-
-static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
-{
-	int i;
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ah->totalPowerMeasI[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
-		ah->totalPowerMeasQ[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
-		ah->totalIqCorrMeas[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
-			ah->cal_samples, i, ah->totalPowerMeasI[i],
-			ah->totalPowerMeasQ[i],
-			ah->totalIqCorrMeas[i]);
-	}
-}
-
-static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
-{
-	int i;
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ah->totalAdcIOddPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
-		ah->totalAdcIEvenPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
-		ah->totalAdcQOddPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		ah->totalAdcQEvenPhase[i] +=
-			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
-			"oddq=0x%08x; evenq=0x%08x;\n",
-			ah->cal_samples, i,
-			ah->totalAdcIOddPhase[i],
-			ah->totalAdcIEvenPhase[i],
-			ah->totalAdcQOddPhase[i],
-			ah->totalAdcQEvenPhase[i]);
-	}
-}
-
-static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
-{
-	int i;
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		ah->totalAdcDcOffsetIOddPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
-		ah->totalAdcDcOffsetIEvenPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
-		ah->totalAdcDcOffsetQOddPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
-		ah->totalAdcDcOffsetQEvenPhase[i] +=
-			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
-			"oddq=0x%08x; evenq=0x%08x;\n",
-			ah->cal_samples, i,
-			ah->totalAdcDcOffsetIOddPhase[i],
-			ah->totalAdcDcOffsetIEvenPhase[i],
-			ah->totalAdcDcOffsetQOddPhase[i],
-			ah->totalAdcDcOffsetQEvenPhase[i]);
-	}
-}
-
-static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
-{
-	u32 powerMeasQ, powerMeasI, iqCorrMeas;
-	u32 qCoffDenom, iCoffDenom;
-	int32_t qCoff, iCoff;
-	int iqCorrNeg, i;
-
-	for (i = 0; i < numChains; i++) {
-		powerMeasI = ah->totalPowerMeasI[i];
-		powerMeasQ = ah->totalPowerMeasQ[i];
-		iqCorrMeas = ah->totalIqCorrMeas[i];
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Starting IQ Cal and Correction for Chain %d\n",
-			i);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Orignal: Chn %diq_corr_meas = 0x%08x\n",
-			i, ah->totalIqCorrMeas[i]);
-
-		iqCorrNeg = 0;
-
-		if (iqCorrMeas > 0x80000000) {
-			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
-			iqCorrNeg = 1;
-		}
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
-			iqCorrNeg);
-
-		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
-		qCoffDenom = powerMeasQ / 64;
-
-		if (powerMeasQ != 0) {
-			iCoff = iqCorrMeas / iCoffDenom;
-			qCoff = powerMeasI / qCoffDenom - 64;
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"Chn %d iCoff = 0x%08x\n", i, iCoff);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"Chn %d qCoff = 0x%08x\n", i, qCoff);
-
-			iCoff = iCoff & 0x3f;
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
-			if (iqCorrNeg == 0x0)
-				iCoff = 0x40 - iCoff;
-
-			if (qCoff > 15)
-				qCoff = 15;
-			else if (qCoff <= -16)
-				qCoff = 16;
-
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
-				i, iCoff, qCoff);
-
-			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
-				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
-				      iCoff);
-			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
-				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
-				      qCoff);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"IQ Cal and Correction done for Chain %d\n",
-				i);
-		}
-	}
-
-	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
-		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
-}
-
-static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
-{
-	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
-	u32 qGainMismatch, iGainMismatch, val, i;
-
-	for (i = 0; i < numChains; i++) {
-		iOddMeasOffset = ah->totalAdcIOddPhase[i];
-		iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
-		qOddMeasOffset = ah->totalAdcQOddPhase[i];
-		qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Starting ADC Gain Cal for Chain %d\n", i);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
-			iOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_even_i = 0x%08x\n", i,
-			iEvenMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
-			qOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_even_q = 0x%08x\n", i,
-			qEvenMeasOffset);
-
-		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
-			iGainMismatch =
-				((iEvenMeasOffset * 32) /
-				 iOddMeasOffset) & 0x3f;
-			qGainMismatch =
-				((qOddMeasOffset * 32) /
-				 qEvenMeasOffset) & 0x3f;
-
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"Chn %d gain_mismatch_i = 0x%08x\n", i,
-				iGainMismatch);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"Chn %d gain_mismatch_q = 0x%08x\n", i,
-				qGainMismatch);
-
-			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
-			val &= 0xfffff000;
-			val |= (qGainMismatch) | (iGainMismatch << 6);
-			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
-
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"ADC Gain Cal done for Chain %d\n", i);
-		}
-	}
-
-	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
-		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
-		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
-}
-
-static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
-{
-	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
-	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
-	const struct hal_percal_data *calData =
-		ah->cal_list_curr->calData;
-	u32 numSamples =
-		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
-
-	for (i = 0; i < numChains; i++) {
-		iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
-		iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
-		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
-		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Starting ADC DC Offset Cal for Chain %d\n", i);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_odd_i = %d\n", i,
-			iOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_even_i = %d\n", i,
-			iEvenMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_odd_q = %d\n", i,
-			qOddMeasOffset);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d pwr_meas_even_q = %d\n", i,
-			qEvenMeasOffset);
-
-		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
-			       numSamples) & 0x1ff;
-		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
-			       numSamples) & 0x1ff;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
-			iDcMismatch);
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
-			qDcMismatch);
-
-		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
-		val &= 0xc0000fff;
-		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
-		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"ADC DC Offset Cal done for Chain %d\n", i);
-	}
-
-	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
-		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
-		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
-}
-
-/* This is done for the currently configured channel */
-bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-	struct hal_cal_list *currCal = ah->cal_list_curr;
-
-	if (!ah->curchan)
-		return true;
-
-	if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
-		return true;
-
-	if (currCal == NULL)
-		return true;
-
-	if (currCal->calState != CAL_DONE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"Calibration state incorrect, %d\n",
-			currCal->calState);
-		return true;
-	}
-
-	if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
-		return true;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-		"Resetting Cal %d state for channel %u\n",
-		currCal->calData->calType, conf->channel->center_freq);
-
-	ah->curchan->CalValid &= ~currCal->calData->calType;
-	currCal->calState = CAL_WAITING;
-
-	return false;
-}
-
-void ath9k_hw_start_nfcal(struct ath_hw *ah)
-{
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_ENABLE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-}
-
-void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	struct ath9k_nfcal_hist *h;
-	int i, j;
-	int32_t val;
-	const u32 ar5416_cca_regs[6] = {
-		AR_PHY_CCA,
-		AR_PHY_CH1_CCA,
-		AR_PHY_CH2_CCA,
-		AR_PHY_EXT_CCA,
-		AR_PHY_CH1_EXT_CCA,
-		AR_PHY_CH2_EXT_CCA
-	};
-	u8 chainmask;
-
-	if (AR_SREV_9285(ah))
-		chainmask = 0x9;
-	else if (AR_SREV_9280(ah))
-		chainmask = 0x1B;
-	else
-		chainmask = 0x3F;
-
-	h = ah->nfCalHist;
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar5416_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
-			REG_WRITE(ah, ar5416_cca_regs[i], val);
-		}
-	}
-
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_ENABLE_NF);
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-
-	for (j = 0; j < 1000; j++) {
-		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
-		     AR_PHY_AGC_CONTROL_NF) == 0)
-			break;
-		udelay(10);
-	}
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar5416_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (-50) << 1) & 0x1ff);
-			REG_WRITE(ah, ar5416_cca_regs[i], val);
-		}
-	}
-}
-
-int16_t ath9k_hw_getnf(struct ath_hw *ah,
-		       struct ath9k_channel *chan)
-{
-	int16_t nf, nfThresh;
-	int16_t nfarray[NUM_NF_READINGS] = { 0 };
-	struct ath9k_nfcal_hist *h;
-	struct ieee80211_channel *c = chan->chan;
-
-	chan->channelFlags &= (~CHANNEL_CW_INT);
-	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"NF did not complete in calibration window\n");
-		nf = 0;
-		chan->rawNoiseFloor = nf;
-		return chan->rawNoiseFloor;
-	} else {
-		ath9k_hw_do_getnf(ah, nfarray);
-		nf = nfarray[0];
-		if (getNoiseFloorThresh(ah, c->band, &nfThresh)
-		    && nf > nfThresh) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"noise floor failed detected; "
-				"detected %d, threshold %d\n",
-				nf, nfThresh);
-			chan->channelFlags |= CHANNEL_CW_INT;
-		}
-	}
-
-	h = ah->nfCalHist;
-
-	ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
-	chan->rawNoiseFloor = h[0].privNF;
-
-	return chan->rawNoiseFloor;
-}
-
-void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
-{
-	int i, j;
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		ah->nfCalHist[i].currIndex = 0;
-		ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
-		ah->nfCalHist[i].invalidNFcount =
-			AR_PHY_CCA_FILTERWINDOW_LENGTH;
-		for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
-			ah->nfCalHist[i].nfCalBuffer[j] =
-				AR_PHY_CCA_MAX_GOOD_VALUE;
-		}
-	}
-}
-
-s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	s16 nf;
-
-	if (chan->rawNoiseFloor == 0)
-		nf = -96;
-	else
-		nf = chan->rawNoiseFloor;
-
-	if (!ath9k_hw_nf_in_range(ah, nf))
-		nf = ATH_DEFAULT_NOISE_FLOOR;
-
-	return nf;
-}
-
-static void ath9k_olc_temp_compensation(struct ath_hw *ah)
-{
-	u32 rddata, i;
-	int delta, currPDADC, regval;
-
-	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
-
-	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
-
-	if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
-		delta = (currPDADC - ah->initPDADC + 4) / 8;
-	else
-		delta = (currPDADC - ah->initPDADC + 5) / 10;
-
-	if (delta != ah->PDADCdelta) {
-		ah->PDADCdelta = delta;
-		for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
-			regval = ah->originalGain[i] - delta;
-			if (regval < 0)
-				regval = 0;
-
-			REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
-					AR_PHY_TX_GAIN, regval);
-		}
-	}
-}
-
-static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
-{
-
-	u32 regVal;
-	int i, offset, offs_6_1, offs_0;
-	u32 ccomp_org, reg_field;
-	u32 regList[][2] = {
-		{ 0x786c, 0 },
-		{ 0x7854, 0 },
-		{ 0x7820, 0 },
-		{ 0x7824, 0 },
-		{ 0x7868, 0 },
-		{ 0x783c, 0 },
-		{ 0x7838, 0 },
-	};
-
-	if (AR_SREV_9285_11(ah)) {
-		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
-		udelay(10);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(regList); i++)
-		regList[i][1] = REG_READ(ah, regList[i][0]);
-
-	regVal = REG_READ(ah, 0x7834);
-	regVal &= (~(0x1));
-	REG_WRITE(ah, 0x7834, regVal);
-	regVal = REG_READ(ah, 0x9808);
-	regVal |= (0x1 << 27);
-	REG_WRITE(ah, 0x9808, regVal);
-
-	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
-	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
-	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
-	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
-	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
-
-	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
-	udelay(30);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
-
-	for (i = 6; i > 0; i--) {
-		regVal = REG_READ(ah, 0x7834);
-		regVal |= (1 << (19 + i));
-		REG_WRITE(ah, 0x7834, regVal);
-		udelay(1);
-		regVal = REG_READ(ah, 0x7834);
-		regVal &= (~(0x1 << (19 + i)));
-		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
-		regVal |= (reg_field << (19 + i));
-		REG_WRITE(ah, 0x7834, regVal);
-	}
-
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
-	udelay(1);
-	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
-	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
-	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
-
-	offset = (offs_6_1<<1) | offs_0;
-	offset = offset - 0;
-	offs_6_1 = offset>>1;
-	offs_0 = offset & 1;
-
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
-
-	regVal = REG_READ(ah, 0x7834);
-	regVal |= 0x1;
-	REG_WRITE(ah, 0x7834, regVal);
-	regVal = REG_READ(ah, 0x9808);
-	regVal &= (~(0x1 << 27));
-	REG_WRITE(ah, 0x9808, regVal);
-
-	for (i = 0; i < ARRAY_SIZE(regList); i++)
-		REG_WRITE(ah, regList[i][0], regList[i][1]);
-
-	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
-
-	if (AR_SREV_9285_11(ah))
-		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
-
-}
-
-bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
-			u8 rxchainmask, bool longcal,
-			bool *isCalDone)
-{
-	struct hal_cal_list *currCal = ah->cal_list_curr;
-
-	*isCalDone = true;
-
-	if (currCal &&
-	    (currCal->calState == CAL_RUNNING ||
-	     currCal->calState == CAL_WAITING)) {
-		ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal,
-					 isCalDone);
-		if (*isCalDone) {
-			ah->cal_list_curr = currCal = currCal->calNext;
-
-			if (currCal->calState == CAL_WAITING) {
-				*isCalDone = false;
-				ath9k_hw_reset_calibration(ah, currCal);
-			}
-		}
-	}
-
-	if (longcal) {
-		if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
-			ath9k_hw_9285_pa_cal(ah);
-
-		if (OLC_FOR_AR9280_20_LATER)
-			ath9k_olc_temp_compensation(ah);
-		ath9k_hw_getnf(ah, chan);
-		ath9k_hw_loadnf(ah, ah->curchan);
-		ath9k_hw_start_nfcal(ah);
-
-		if (chan->channelFlags & CHANNEL_CW_INT)
-			chan->channelFlags &= ~CHANNEL_CW_INT;
-	}
-
-	return true;
-}
-
-static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-	if (chan->channelFlags & CHANNEL_HT20) {
-		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
-		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
-		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-			    AR_PHY_AGC_CONTROL_FLTR_CAL);
-		REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
-		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
-		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
-				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset "
-				"calibration failed to complete in "
-				"1ms; noisy ??\n");
-			return false;
-		}
-		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
-		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
-		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-	}
-	REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-	REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
-	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
-			  0, AH_WAIT_TIMEOUT)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration "
-				"failed to complete in 1ms; noisy ??\n");
-		return false;
-	}
-
-	REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-	REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-
-	return true;
-}
-
-bool ath9k_hw_init_cal(struct ath_hw *ah,
-		       struct ath9k_channel *chan)
-{
-	if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
-		if (!ar9285_clc(ah, chan))
-			return false;
-	} else if (AR_SREV_9280_10_OR_LATER(ah)) {
-		REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-
-		/* Kick off the cal */
-		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-				REG_READ(ah, AR_PHY_AGC_CONTROL) |
-				AR_PHY_AGC_CONTROL_CAL);
-
-		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
-					AR_PHY_AGC_CONTROL_CAL, 0,
-					AH_WAIT_TIMEOUT)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-				"offset calibration failed to complete in 1ms; "
-				"noisy environment?\n");
-			return false;
-		}
-
-		REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-	}
-
-	/* Calibrate the AGC */
-	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-			REG_READ(ah, AR_PHY_AGC_CONTROL) |
-			AR_PHY_AGC_CONTROL_CAL);
-
-	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
-				0, AH_WAIT_TIMEOUT)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"offset calibration failed to complete in 1ms; "
-			"noisy environment?\n");
-		return false;
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-	}
-
-	/* Do PA Calibration */
-	if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
-		ath9k_hw_9285_pa_cal(ah);
-
-	/* Do NF Calibration */
-	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-			REG_READ(ah, AR_PHY_AGC_CONTROL) |
-			AR_PHY_AGC_CONTROL_NF);
-
-	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
-
-	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
-		if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
-			INIT_CAL(&ah->adcgain_caldata);
-			INSERT_CAL(ah, &ah->adcgain_caldata);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-					"enabling ADC Gain Calibration.\n");
-		}
-		if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
-			INIT_CAL(&ah->adcdc_caldata);
-			INSERT_CAL(ah, &ah->adcdc_caldata);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-					"enabling ADC DC Calibration.\n");
-		}
-		if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
-			INIT_CAL(&ah->iq_caldata);
-			INSERT_CAL(ah, &ah->iq_caldata);
-			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-					"enabling IQ Calibration.\n");
-		}
-
-		ah->cal_list_curr = ah->cal_list;
-
-		if (ah->cal_list_curr)
-			ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
-	}
-
-	chan->CalValid = 0;
-
-	return true;
-}
-
-const struct hal_percal_data iq_cal_multi_sample = {
-	IQ_MISMATCH_CAL,
-	MAX_CAL_SAMPLES,
-	PER_MIN_LOG_COUNT,
-	ath9k_hw_iqcal_collect,
-	ath9k_hw_iqcalibrate
-};
-const struct hal_percal_data iq_cal_single_sample = {
-	IQ_MISMATCH_CAL,
-	MIN_CAL_SAMPLES,
-	PER_MAX_LOG_COUNT,
-	ath9k_hw_iqcal_collect,
-	ath9k_hw_iqcalibrate
-};
-const struct hal_percal_data adc_gain_cal_multi_sample = {
-	ADC_GAIN_CAL,
-	MAX_CAL_SAMPLES,
-	PER_MIN_LOG_COUNT,
-	ath9k_hw_adc_gaincal_collect,
-	ath9k_hw_adc_gaincal_calibrate
-};
-const struct hal_percal_data adc_gain_cal_single_sample = {
-	ADC_GAIN_CAL,
-	MIN_CAL_SAMPLES,
-	PER_MAX_LOG_COUNT,
-	ath9k_hw_adc_gaincal_collect,
-	ath9k_hw_adc_gaincal_calibrate
-};
-const struct hal_percal_data adc_dc_cal_multi_sample = {
-	ADC_DC_CAL,
-	MAX_CAL_SAMPLES,
-	PER_MIN_LOG_COUNT,
-	ath9k_hw_adc_dccal_collect,
-	ath9k_hw_adc_dccal_calibrate
-};
-const struct hal_percal_data adc_dc_cal_single_sample = {
-	ADC_DC_CAL,
-	MIN_CAL_SAMPLES,
-	PER_MAX_LOG_COUNT,
-	ath9k_hw_adc_dccal_collect,
-	ath9k_hw_adc_dccal_calibrate
-};
-const struct hal_percal_data adc_init_dc_cal = {
-	ADC_DC_INIT_CAL,
-	MIN_CAL_SAMPLES,
-	INIT_LOG_COUNT,
-	ath9k_hw_adc_dccal_collect,
-	ath9k_hw_adc_dccal_calibrate
-};
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/calib.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/calib.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/calib.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/calib.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef CALIB_H
-#define CALIB_H
-
-extern const struct hal_percal_data iq_cal_multi_sample;
-extern const struct hal_percal_data iq_cal_single_sample;
-extern const struct hal_percal_data adc_gain_cal_multi_sample;
-extern const struct hal_percal_data adc_gain_cal_single_sample;
-extern const struct hal_percal_data adc_dc_cal_multi_sample;
-extern const struct hal_percal_data adc_dc_cal_single_sample;
-extern const struct hal_percal_data adc_init_dc_cal;
-
-#define AR_PHY_CCA_MAX_GOOD_VALUE      		-85
-#define AR_PHY_CCA_MAX_HIGH_VALUE      		-62
-#define AR_PHY_CCA_MIN_BAD_VALUE       		-140
-#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT     3
-#define AR_PHY_CCA_FILTERWINDOW_LENGTH          5
-
-#define NUM_NF_READINGS       6
-#define ATH9K_NF_CAL_HIST_MAX 5
-
-struct ar5416IniArray {
-	u32 *ia_array;
-	u32 ia_rows;
-	u32 ia_columns;
-};
-
-#define INIT_INI_ARRAY(iniarray, array, rows, columns) do {	\
-		(iniarray)->ia_array = (u32 *)(array);		\
-		(iniarray)->ia_rows = (rows);			\
-		(iniarray)->ia_columns = (columns);		\
-	} while (0)
-
-#define INI_RA(iniarray, row, column) \
-	(((iniarray)->ia_array)[(row) *	((iniarray)->ia_columns) + (column)])
-
-#define INIT_CAL(_perCal) do {				\
-		(_perCal)->calState = CAL_WAITING;	\
-		(_perCal)->calNext = NULL;		\
-	} while (0)
-
-#define INSERT_CAL(_ahp, _perCal)					\
-	do {								\
-		if ((_ahp)->cal_list_last == NULL) {			\
-			(_ahp)->cal_list =				\
-				(_ahp)->cal_list_last = (_perCal);	\
-			((_ahp)->cal_list_last)->calNext = (_perCal); \
-		} else {						\
-			((_ahp)->cal_list_last)->calNext = (_perCal); \
-			(_ahp)->cal_list_last = (_perCal);		\
-			(_perCal)->calNext = (_ahp)->cal_list;	\
-		}							\
-	} while (0)
-
-enum hal_cal_types {
-	ADC_DC_INIT_CAL = 0x1,
-	ADC_GAIN_CAL = 0x2,
-	ADC_DC_CAL = 0x4,
-	IQ_MISMATCH_CAL = 0x8
-};
-
-enum hal_cal_state {
-	CAL_INACTIVE,
-	CAL_WAITING,
-	CAL_RUNNING,
-	CAL_DONE
-};
-
-#define MIN_CAL_SAMPLES     1
-#define MAX_CAL_SAMPLES    64
-#define INIT_LOG_COUNT      5
-#define PER_MIN_LOG_COUNT   2
-#define PER_MAX_LOG_COUNT  10
-
-struct hal_percal_data {
-	enum hal_cal_types calType;
-	u32 calNumSamples;
-	u32 calCountMax;
-	void (*calCollect) (struct ath_hw *);
-	void (*calPostProc) (struct ath_hw *, u8);
-};
-
-struct hal_cal_list {
-	const struct hal_percal_data *calData;
-	enum hal_cal_state calState;
-	struct hal_cal_list *calNext;
-};
-
-struct ath9k_nfcal_hist {
-	int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX];
-	u8 currIndex;
-	int16_t privNF;
-	u8 invalidNFcount;
-};
-
-bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
-void ath9k_hw_start_nfcal(struct ath_hw *ah);
-void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
-int16_t ath9k_hw_getnf(struct ath_hw *ah,
-		       struct ath9k_channel *chan);
-void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
-s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
-bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
-			u8 rxchainmask, bool longcal,
-			bool *isCalDone);
-bool ath9k_hw_init_cal(struct ath_hw *ah,
-		       struct ath9k_channel *chan);
-
-#endif /* CALIB_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/debug.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/debug.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/debug.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/debug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,559 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <asm/unaligned.h>
-
-#include "ath9k.h"
-
-static unsigned int ath9k_debug = DBG_DEFAULT;
-module_param_named(debug, ath9k_debug, uint, 0);
-
-static struct dentry *ath9k_debugfs_root;
-
-void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...)
-{
-	if (!sc)
-		return;
-
-	if (sc->debug.debug_mask & dbg_mask) {
-		va_list args;
-
-		va_start(args, fmt);
-		printk(KERN_DEBUG "ath9k: ");
-		vprintk(fmt, args);
-		va_end(args);
-	}
-}
-
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t read_file_dma(struct file *file, char __user *user_buf,
-			     size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-	struct ath_hw *ah = sc->sc_ah;
-	char buf[1024];
-	unsigned int len = 0;
-	u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
-	int i, qcuOffset = 0, dcuOffset = 0;
-	u32 *qcuBase = &val[0], *dcuBase = &val[4];
-
-	REG_WRITE(ah, AR_MACMISC,
-		  ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
-		   (AR_MACMISC_MISC_OBS_BUS_1 <<
-		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
-
-	len += snprintf(buf + len, sizeof(buf) - len,
-			"Raw DMA Debug values:\n");
-
-	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
-		if (i % 4 == 0)
-			len += snprintf(buf + len, sizeof(buf) - len, "\n");
-
-		val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
-		len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
-				i, val[i]);
-	}
-
-	len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
-	len += snprintf(buf + len, sizeof(buf) - len,
-			"Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
-
-	for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
-		if (i == 8) {
-			qcuOffset = 0;
-			qcuBase++;
-		}
-
-		if (i == 6) {
-			dcuOffset = 0;
-			dcuBase++;
-		}
-
-		len += snprintf(buf + len, sizeof(buf) - len,
-			"%2d          %2x      %1x     %2x           %2x\n",
-			i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
-			(*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
-			val[2] & (0x7 << (i * 3)) >> (i * 3),
-			(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
-	}
-
-	len += snprintf(buf + len, sizeof(buf) - len, "\n");
-
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
-		(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"qcu_complete state: %2x    dcu_complete state:     %2x\n",
-		(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"dcu_arb state:      %2x    dcu_fp state:           %2x\n",
-		(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
-		(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
-		(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
-		(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
-
-	len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
-			REG_READ(ah, AR_OBS_BUS_1));
-	len += snprintf(buf + len, sizeof(buf) - len,
-			"AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_dma = {
-	.read = read_file_dma,
-	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
-};
-
-
-void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
-{
-	if (status)
-		sc->debug.stats.istats.total++;
-	if (status & ATH9K_INT_RX)
-		sc->debug.stats.istats.rxok++;
-	if (status & ATH9K_INT_RXEOL)
-		sc->debug.stats.istats.rxeol++;
-	if (status & ATH9K_INT_RXORN)
-		sc->debug.stats.istats.rxorn++;
-	if (status & ATH9K_INT_TX)
-		sc->debug.stats.istats.txok++;
-	if (status & ATH9K_INT_TXURN)
-		sc->debug.stats.istats.txurn++;
-	if (status & ATH9K_INT_MIB)
-		sc->debug.stats.istats.mib++;
-	if (status & ATH9K_INT_RXPHY)
-		sc->debug.stats.istats.rxphyerr++;
-	if (status & ATH9K_INT_RXKCM)
-		sc->debug.stats.istats.rx_keycache_miss++;
-	if (status & ATH9K_INT_SWBA)
-		sc->debug.stats.istats.swba++;
-	if (status & ATH9K_INT_BMISS)
-		sc->debug.stats.istats.bmiss++;
-	if (status & ATH9K_INT_BNR)
-		sc->debug.stats.istats.bnr++;
-	if (status & ATH9K_INT_CST)
-		sc->debug.stats.istats.cst++;
-	if (status & ATH9K_INT_GTT)
-		sc->debug.stats.istats.gtt++;
-	if (status & ATH9K_INT_TIM)
-		sc->debug.stats.istats.tim++;
-	if (status & ATH9K_INT_CABEND)
-		sc->debug.stats.istats.cabend++;
-	if (status & ATH9K_INT_DTIMSYNC)
-		sc->debug.stats.istats.dtimsync++;
-	if (status & ATH9K_INT_DTIM)
-		sc->debug.stats.istats.dtim++;
-}
-
-static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
-				   size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-	char buf[512];
-	unsigned int len = 0;
-
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "TIM", sc->debug.stats.istats.tim);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim);
-	len += snprintf(buf + len, sizeof(buf) - len,
-		"%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_interrupt = {
-	.read = read_file_interrupt,
-	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
-};
-
-static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb)
-{
-	struct ath_tx_info_priv *tx_info_priv = NULL;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_rate *rates = tx_info->status.rates;
-	int final_ts_idx, idx;
-
-	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-	final_ts_idx = tx_info_priv->tx.ts_rateindex;
-	idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate;
-
-	sc->debug.stats.n_rcstats[idx].success++;
-}
-
-static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb)
-{
-	struct ath_tx_info_priv *tx_info_priv = NULL;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_rate *rates = tx_info->status.rates;
-	int final_ts_idx, idx;
-
-	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-	final_ts_idx = tx_info_priv->tx.ts_rateindex;
-	idx = rates[final_ts_idx].idx;
-
-	sc->debug.stats.legacy_rcstats[idx].success++;
-}
-
-void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
-{
-	if (conf_is_ht(&sc->hw->conf))
-		ath_debug_stat_11n_rc(sc, skb);
-	else
-		ath_debug_stat_legacy_rc(sc, skb);
-}
-
-/* FIXME: legacy rates, later on .. */
-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
-			    int xretries, int retries, u8 per)
-{
-	if (conf_is_ht(&sc->hw->conf)) {
-		int idx = sc->cur_rate_table->info[rix].dot11rate;
-
-		sc->debug.stats.n_rcstats[idx].xretries += xretries;
-		sc->debug.stats.n_rcstats[idx].retries += retries;
-		sc->debug.stats.n_rcstats[idx].per = per;
-	}
-}
-
-static ssize_t ath_read_file_stat_11n_rc(struct file *file,
-					 char __user *user_buf,
-					 size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-	char buf[1024];
-	unsigned int len = 0;
-	int i = 0;
-
-	len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success",
-		       "Retries", "XRetries", "PER");
-
-	for (i = 0; i <= 15; i++) {
-		len += snprintf(buf + len, sizeof(buf) - len,
-				"%5s%3d: %8u %8u %8u %8u\n", "MCS", i,
-				sc->debug.stats.n_rcstats[i].success,
-				sc->debug.stats.n_rcstats[i].retries,
-				sc->debug.stats.n_rcstats[i].xretries,
-				sc->debug.stats.n_rcstats[i].per);
-	}
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t ath_read_file_stat_legacy_rc(struct file *file,
-					    char __user *user_buf,
-					    size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-	char buf[512];
-	unsigned int len = 0;
-	int i = 0;
-
-	len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success");
-
-	for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
-		len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n",
-				sc->cur_rate_table->info[i].ratekbps / 1000,
-				sc->debug.stats.legacy_rcstats[i].success);
-	}
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
-				size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-
-	if (sc->cur_rate_table == NULL)
-		return 0;
-
-	if (conf_is_ht(&sc->hw->conf))
-		return ath_read_file_stat_11n_rc(file, user_buf, count, ppos);
-	else
-		return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos);
-}
-
-static const struct file_operations fops_rcstat = {
-	.read = read_file_rcstat,
-	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
-};
-
-static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
-{
-	switch (state) {
-	case ATH_WIPHY_INACTIVE:
-		return "INACTIVE";
-	case ATH_WIPHY_ACTIVE:
-		return "ACTIVE";
-	case ATH_WIPHY_PAUSING:
-		return "PAUSING";
-	case ATH_WIPHY_PAUSED:
-		return "PAUSED";
-	case ATH_WIPHY_SCAN:
-		return "SCAN";
-	}
-	return "?";
-}
-
-static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
-			       size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-	char buf[512];
-	unsigned int len = 0;
-	int i;
-	u8 addr[ETH_ALEN];
-
-	len += snprintf(buf + len, sizeof(buf) - len,
-			"primary: %s (%s chan=%d ht=%d)\n",
-			wiphy_name(sc->pri_wiphy->hw->wiphy),
-			ath_wiphy_state_str(sc->pri_wiphy->state),
-			sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy == NULL)
-			continue;
-		len += snprintf(buf + len, sizeof(buf) - len,
-				"secondary: %s (%s chan=%d ht=%d)\n",
-				wiphy_name(aphy->hw->wiphy),
-				ath_wiphy_state_str(aphy->state),
-				aphy->chan_idx, aphy->chan_is_ht);
-	}
-
-	put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr);
-	put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
-	len += snprintf(buf + len, sizeof(buf) - len,
-			"addr: %pM\n", addr);
-	put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr);
-	put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
-	len += snprintf(buf + len, sizeof(buf) - len,
-			"addrmask: %pM\n", addr);
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name)
-{
-	int i;
-	if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0)
-		return sc->pri_wiphy;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0)
-			return aphy;
-	}
-	return NULL;
-}
-
-static int del_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_del(aphy);
-}
-
-static int pause_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_pause(aphy);
-}
-
-static int unpause_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_unpause(aphy);
-}
-
-static int select_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_select(aphy);
-}
-
-static int schedule_wiphy(struct ath_softc *sc, const char *msec)
-{
-	ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0));
-	return 0;
-}
-
-static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf,
-				size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-	char buf[50];
-	size_t len;
-
-	len = min(count, sizeof(buf) - 1);
-	if (copy_from_user(buf, user_buf, len))
-		return -EFAULT;
-	buf[len] = '\0';
-	if (len > 0 && buf[len - 1] == '\n')
-		buf[len - 1] = '\0';
-
-	if (strncmp(buf, "add", 3) == 0) {
-		int res = ath9k_wiphy_add(sc);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "del=", 4) == 0) {
-		int res = del_wiphy(sc, buf + 4);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "pause=", 6) == 0) {
-		int res = pause_wiphy(sc, buf + 6);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "unpause=", 8) == 0) {
-		int res = unpause_wiphy(sc, buf + 8);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "select=", 7) == 0) {
-		int res = select_wiphy(sc, buf + 7);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "schedule=", 9) == 0) {
-		int res = schedule_wiphy(sc, buf + 9);
-		if (res < 0)
-			return res;
-	} else
-		return -EOPNOTSUPP;
-
-	return count;
-}
-
-static const struct file_operations fops_wiphy = {
-	.read = read_file_wiphy,
-	.write = write_file_wiphy,
-	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
-};
-
-
-int ath9k_init_debug(struct ath_softc *sc)
-{
-	sc->debug.debug_mask = ath9k_debug;
-
-	sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
-						      ath9k_debugfs_root);
-	if (!sc->debug.debugfs_phy)
-		goto err;
-
-	sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
-				       sc->debug.debugfs_phy, sc, &fops_dma);
-	if (!sc->debug.debugfs_dma)
-		goto err;
-
-	sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
-						     S_IRUGO,
-						     sc->debug.debugfs_phy,
-						     sc, &fops_interrupt);
-	if (!sc->debug.debugfs_interrupt)
-		goto err;
-
-	sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
-						  S_IRUGO,
-						  sc->debug.debugfs_phy,
-						  sc, &fops_rcstat);
-	if (!sc->debug.debugfs_rcstat)
-		goto err;
-
-	sc->debug.debugfs_wiphy = debugfs_create_file(
-		"wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc,
-		&fops_wiphy);
-	if (!sc->debug.debugfs_wiphy)
-		goto err;
-
-	return 0;
-err:
-	ath9k_exit_debug(sc);
-	return -ENOMEM;
-}
-
-void ath9k_exit_debug(struct ath_softc *sc)
-{
-	debugfs_remove(sc->debug.debugfs_wiphy);
-	debugfs_remove(sc->debug.debugfs_rcstat);
-	debugfs_remove(sc->debug.debugfs_interrupt);
-	debugfs_remove(sc->debug.debugfs_dma);
-	debugfs_remove(sc->debug.debugfs_phy);
-}
-
-int ath9k_debug_create_root(void)
-{
-	ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-	if (!ath9k_debugfs_root)
-		return -ENOENT;
-
-	return 0;
-}
-
-void ath9k_debug_remove_root(void)
-{
-	debugfs_remove(ath9k_debugfs_root);
-	ath9k_debugfs_root = NULL;
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/debug.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/debug.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/debug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/debug.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef DEBUG_H
-#define DEBUG_H
-
-enum ATH_DEBUG {
-	ATH_DBG_RESET		= 0x00000001,
-	ATH_DBG_REG_IO		= 0x00000002,
-	ATH_DBG_QUEUE		= 0x00000004,
-	ATH_DBG_EEPROM		= 0x00000008,
-	ATH_DBG_CALIBRATE	= 0x00000010,
-	ATH_DBG_CHANNEL		= 0x00000020,
-	ATH_DBG_INTERRUPT	= 0x00000040,
-	ATH_DBG_REGULATORY	= 0x00000080,
-	ATH_DBG_ANI		= 0x00000100,
-	ATH_DBG_POWER_MGMT	= 0x00000200,
-	ATH_DBG_XMIT		= 0x00000400,
-	ATH_DBG_BEACON		= 0x00001000,
-	ATH_DBG_CONFIG		= 0x00002000,
-	ATH_DBG_KEYCACHE	= 0x00004000,
-	ATH_DBG_FATAL		= 0x00008000,
-	ATH_DBG_ANY		= 0xffffffff
-};
-
-#define DBG_DEFAULT (ATH_DBG_FATAL)
-
-#ifdef CONFIG_ATH9K_DEBUG
-
-/**
- * struct ath_interrupt_stats - Contains statistics about interrupts
- * @total: Total no. of interrupts generated so far
- * @rxok: RX with no errors
- * @rxeol: RX with no more RXDESC available
- * @rxorn: RX FIFO overrun
- * @txok: TX completed at the requested rate
- * @txurn: TX FIFO underrun
- * @mib: MIB regs reaching its threshold
- * @rxphyerr: RX with phy errors
- * @rx_keycache_miss: RX with key cache misses
- * @swba: Software Beacon Alert
- * @bmiss: Beacon Miss
- * @bnr: Beacon Not Ready
- * @cst: Carrier Sense TImeout
- * @gtt: Global TX Timeout
- * @tim: RX beacon TIM occurrence
- * @cabend: RX End of CAB traffic
- * @dtimsync: DTIM sync lossage
- * @dtim: RX Beacon with DTIM
- */
-struct ath_interrupt_stats {
-	u32 total;
-	u32 rxok;
-	u32 rxeol;
-	u32 rxorn;
-	u32 txok;
-	u32 txeol;
-	u32 txurn;
-	u32 mib;
-	u32 rxphyerr;
-	u32 rx_keycache_miss;
-	u32 swba;
-	u32 bmiss;
-	u32 bnr;
-	u32 cst;
-	u32 gtt;
-	u32 tim;
-	u32 cabend;
-	u32 dtimsync;
-	u32 dtim;
-};
-
-struct ath_legacy_rc_stats {
-	u32 success;
-};
-
-struct ath_11n_rc_stats {
-	u32 success;
-	u32 retries;
-	u32 xretries;
-	u8 per;
-};
-
-struct ath_stats {
-	struct ath_interrupt_stats istats;
-	struct ath_legacy_rc_stats legacy_rcstats[12];	/* max(11a,11b,11g) */
-	struct ath_11n_rc_stats n_rcstats[16];		/* 0..15 MCS rates */
-};
-
-struct ath9k_debug {
-	int debug_mask;
-	struct dentry *debugfs_phy;
-	struct dentry *debugfs_dma;
-	struct dentry *debugfs_interrupt;
-	struct dentry *debugfs_rcstat;
-	struct dentry *debugfs_wiphy;
-	struct ath_stats stats;
-};
-
-void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...);
-int ath9k_init_debug(struct ath_softc *sc);
-void ath9k_exit_debug(struct ath_softc *sc);
-int ath9k_debug_create_root(void);
-void ath9k_debug_remove_root(void);
-void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
-void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
-			    int xretries, int retries, u8 per);
-
-#else
-
-static inline void DPRINTF(struct ath_softc *sc, int dbg_mask,
-			   const char *fmt, ...)
-{
-}
-
-static inline int ath9k_init_debug(struct ath_softc *sc)
-{
-	return 0;
-}
-
-static inline void ath9k_exit_debug(struct ath_softc *sc)
-{
-}
-
-static inline int ath9k_debug_create_root(void)
-{
-	return 0;
-}
-
-static inline void ath9k_debug_remove_root(void)
-{
-}
-
-static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
-					    enum ath9k_int status)
-{
-}
-
-static inline void ath_debug_stat_rc(struct ath_softc *sc,
-				     struct sk_buff *skb)
-{
-}
-
-static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
-					  int xretries, int retries, u8 per)
-{
-}
-
-#endif /* CONFIG_ATH9K_DEBUG */
-
-#endif /* DEBUG_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/eeprom.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/eeprom.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/eeprom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/eeprom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2813 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah,
-				      u32 reg, u32 mask,
-				      u32 shift, u32 val)
-{
-	u32 regVal;
-
-	regVal = REG_READ(ah, reg) & ~mask;
-	regVal |= (val << shift) & mask;
-
-	REG_WRITE(ah, reg, regVal);
-
-	if (ah->config.analog_shiftreg)
-		udelay(100);
-
-	return;
-}
-
-static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
-{
-
-	if (fbin == AR5416_BCHAN_UNUSED)
-		return fbin;
-
-	return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
-}
-
-static inline int16_t ath9k_hw_interpolate(u16 target,
-					   u16 srcLeft, u16 srcRight,
-					   int16_t targetLeft,
-					   int16_t targetRight)
-{
-	int16_t rv;
-
-	if (srcRight == srcLeft) {
-		rv = targetLeft;
-	} else {
-		rv = (int16_t) (((target - srcLeft) * targetRight +
-				 (srcRight - target) * targetLeft) /
-				(srcRight - srcLeft));
-	}
-	return rv;
-}
-
-static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
-						  u16 listSize, u16 *indexL,
-						  u16 *indexR)
-{
-	u16 i;
-
-	if (target <= pList[0]) {
-		*indexL = *indexR = 0;
-		return true;
-	}
-	if (target >= pList[listSize - 1]) {
-		*indexL = *indexR = (u16) (listSize - 1);
-		return true;
-	}
-
-	for (i = 0; i < listSize - 1; i++) {
-		if (pList[i] == target) {
-			*indexL = *indexR = i;
-			return true;
-		}
-		if (target < pList[i + 1]) {
-			*indexL = i;
-			*indexR = (u16) (i + 1);
-			return false;
-		}
-	}
-	return false;
-}
-
-static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
-{
-	struct ath_softc *sc = ah->ah_sc;
-
-	return sc->bus_ops->eeprom_read(ah, off, data);
-}
-
-static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
-					   u8 *pVpdList, u16 numIntercepts,
-					   u8 *pRetVpdList)
-{
-	u16 i, k;
-	u8 currPwr = pwrMin;
-	u16 idxL = 0, idxR = 0;
-
-	for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
-		ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
-					       numIntercepts, &(idxL),
-					       &(idxR));
-		if (idxR < 1)
-			idxR = 1;
-		if (idxL == numIntercepts - 1)
-			idxL = (u16) (numIntercepts - 2);
-		if (pPwrList[idxL] == pPwrList[idxR])
-			k = pVpdList[idxL];
-		else
-			k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
-				   (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
-				  (pPwrList[idxR] - pPwrList[idxL]));
-		pRetVpdList[i] = (u8) k;
-		currPwr += 2;
-	}
-
-	return true;
-}
-
-static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
-				      struct ath9k_channel *chan,
-				      struct cal_target_power_leg *powInfo,
-				      u16 numChannels,
-				      struct cal_target_power_leg *pNewPower,
-				      u16 numRates, bool isExtTarget)
-{
-	struct chan_centers centers;
-	u16 clo, chi;
-	int i;
-	int matchIndex = -1, lowIndex = -1;
-	u16 freq;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
-
-	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
-				       IS_CHAN_2GHZ(chan))) {
-		matchIndex = 0;
-	} else {
-		for (i = 0; (i < numChannels) &&
-			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
-			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
-						       IS_CHAN_2GHZ(chan))) {
-				matchIndex = i;
-				break;
-			} else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
-						      IS_CHAN_2GHZ(chan))) &&
-				   (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
-						      IS_CHAN_2GHZ(chan)))) {
-				lowIndex = i - 1;
-				break;
-			}
-		}
-		if ((matchIndex == -1) && (lowIndex == -1))
-			matchIndex = i - 1;
-	}
-
-	if (matchIndex != -1) {
-		*pNewPower = powInfo[matchIndex];
-	} else {
-		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
-					 IS_CHAN_2GHZ(chan));
-		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
-					 IS_CHAN_2GHZ(chan));
-
-		for (i = 0; i < numRates; i++) {
-			pNewPower->tPow2x[i] =
-				(u8)ath9k_hw_interpolate(freq, clo, chi,
-						powInfo[lowIndex].tPow2x[i],
-						powInfo[lowIndex + 1].tPow2x[i]);
-		}
-	}
-}
-
-static void ath9k_get_txgain_index(struct ath_hw *ah,
-		struct ath9k_channel *chan,
-		struct calDataPerFreqOpLoop *rawDatasetOpLoop,
-		u8 *calChans,  u16 availPiers, u8 *pwr, u8 *pcdacIdx)
-{
-	u8 pcdac, i = 0;
-	u16 idxL = 0, idxR = 0, numPiers;
-	bool match;
-	struct chan_centers centers;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	for (numPiers = 0; numPiers < availPiers; numPiers++)
-		if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
-			break;
-
-	match = ath9k_hw_get_lower_upper_index(
-			(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
-			calChans, numPiers, &idxL, &idxR);
-	if (match) {
-		pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
-		*pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
-	} else {
-		pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
-		*pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
-				rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
-	}
-
-	while (pcdac > ah->originalGain[i] &&
-			i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
-		i++;
-
-	*pcdacIdx = i;
-	return;
-}
-
-static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
-				u32 initTxGain,
-				int txPower,
-				u8 *pPDADCValues)
-{
-	u32 i;
-	u32 offset;
-
-	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
-			AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
-	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
-			AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
-
-	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
-			AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
-
-	offset = txPower;
-	for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
-		if (i < offset)
-			pPDADCValues[i] = 0x0;
-		else
-			pPDADCValues[i] = 0xFF;
-}
-
-
-
-
-static void ath9k_hw_get_target_powers(struct ath_hw *ah,
-				       struct ath9k_channel *chan,
-				       struct cal_target_power_ht *powInfo,
-				       u16 numChannels,
-				       struct cal_target_power_ht *pNewPower,
-				       u16 numRates, bool isHt40Target)
-{
-	struct chan_centers centers;
-	u16 clo, chi;
-	int i;
-	int matchIndex = -1, lowIndex = -1;
-	u16 freq;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	freq = isHt40Target ? centers.synth_center : centers.ctl_center;
-
-	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
-		matchIndex = 0;
-	} else {
-		for (i = 0; (i < numChannels) &&
-			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
-			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
-						       IS_CHAN_2GHZ(chan))) {
-				matchIndex = i;
-				break;
-			} else
-				if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
-						       IS_CHAN_2GHZ(chan))) &&
-				    (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
-						       IS_CHAN_2GHZ(chan)))) {
-					lowIndex = i - 1;
-					break;
-				}
-		}
-		if ((matchIndex == -1) && (lowIndex == -1))
-			matchIndex = i - 1;
-	}
-
-	if (matchIndex != -1) {
-		*pNewPower = powInfo[matchIndex];
-	} else {
-		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
-					 IS_CHAN_2GHZ(chan));
-		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
-					 IS_CHAN_2GHZ(chan));
-
-		for (i = 0; i < numRates; i++) {
-			pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
-						clo, chi,
-						powInfo[lowIndex].tPow2x[i],
-						powInfo[lowIndex + 1].tPow2x[i]);
-		}
-	}
-}
-
-static u16 ath9k_hw_get_max_edge_power(u16 freq,
-				       struct cal_ctl_edges *pRdEdgesPower,
-				       bool is2GHz, int num_band_edges)
-{
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-	int i;
-
-	for (i = 0; (i < num_band_edges) &&
-		     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
-		if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
-			twiceMaxEdgePower = pRdEdgesPower[i].tPower;
-			break;
-		} else if ((i > 0) &&
-			   (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
-						      is2GHz))) {
-			if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
-					       is2GHz) < freq &&
-			    pRdEdgesPower[i - 1].flag) {
-				twiceMaxEdgePower =
-					pRdEdgesPower[i - 1].tPower;
-			}
-			break;
-		}
-	}
-
-	return twiceMaxEdgePower;
-}
-
-/****************************************/
-/* EEPROM Operations for 4K sized cards */
-/****************************************/
-
-static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
-{
-	return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
-}
-
-static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
-{
-	return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
-}
-
-static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
-{
-#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
-	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
-	int addr, eep_start_loc = 0;
-
-	eep_start_loc = 64;
-
-	if (!ath9k_hw_use_flash(ah)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"Reading from EEPROM, not flash\n");
-	}
-
-	for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
-		if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			       "Unable to read eeprom region \n");
-			return false;
-		}
-		eep_data++;
-	}
-
-	return true;
-#undef SIZE_EEPROM_4K
-}
-
-static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
-{
-#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
-	struct ar5416_eeprom_4k *eep =
-		(struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
-	u16 *eepdata, temp, magic, magic2;
-	u32 sum = 0, el;
-	bool need_swap = false;
-	int i, addr;
-
-
-	if (!ath9k_hw_use_flash(ah)) {
-		if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
-					 &magic)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"Reading Magic # failed\n");
-			return false;
-		}
-
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"Read Magic = 0x%04X\n", magic);
-
-		if (magic != AR5416_EEPROM_MAGIC) {
-			magic2 = swab16(magic);
-
-			if (magic2 == AR5416_EEPROM_MAGIC) {
-				need_swap = true;
-				eepdata = (u16 *) (&ah->eeprom);
-
-				for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
-					temp = swab16(*eepdata);
-					*eepdata = temp;
-					eepdata++;
-				}
-			} else {
-				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-					"Invalid EEPROM Magic. "
-					"endianness mismatch.\n");
-				return -EINVAL;
-			}
-		}
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
-		need_swap ? "True" : "False");
-
-	if (need_swap)
-		el = swab16(ah->eeprom.map4k.baseEepHeader.length);
-	else
-		el = ah->eeprom.map4k.baseEepHeader.length;
-
-	if (el > sizeof(struct ar5416_eeprom_4k))
-		el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
-	else
-		el = el / sizeof(u16);
-
-	eepdata = (u16 *)(&ah->eeprom);
-
-	for (i = 0; i < el; i++)
-		sum ^= *eepdata++;
-
-	if (need_swap) {
-		u32 integer;
-		u16 word;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"EEPROM Endianness is not native.. Changing\n");
-
-		word = swab16(eep->baseEepHeader.length);
-		eep->baseEepHeader.length = word;
-
-		word = swab16(eep->baseEepHeader.checksum);
-		eep->baseEepHeader.checksum = word;
-
-		word = swab16(eep->baseEepHeader.version);
-		eep->baseEepHeader.version = word;
-
-		word = swab16(eep->baseEepHeader.regDmn[0]);
-		eep->baseEepHeader.regDmn[0] = word;
-
-		word = swab16(eep->baseEepHeader.regDmn[1]);
-		eep->baseEepHeader.regDmn[1] = word;
-
-		word = swab16(eep->baseEepHeader.rfSilent);
-		eep->baseEepHeader.rfSilent = word;
-
-		word = swab16(eep->baseEepHeader.blueToothOptions);
-		eep->baseEepHeader.blueToothOptions = word;
-
-		word = swab16(eep->baseEepHeader.deviceCap);
-		eep->baseEepHeader.deviceCap = word;
-
-		integer = swab32(eep->modalHeader.antCtrlCommon);
-		eep->modalHeader.antCtrlCommon = integer;
-
-		for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-			integer = swab32(eep->modalHeader.antCtrlChain[i]);
-			eep->modalHeader.antCtrlChain[i] = integer;
-		}
-
-		for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
-			word = swab16(eep->modalHeader.spurChans[i].spurChan);
-			eep->modalHeader.spurChans[i].spurChan = word;
-		}
-	}
-
-	if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
-	    ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
-		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-			"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
-			sum, ah->eep_ops->get_eeprom_ver(ah));
-		return -EINVAL;
-	}
-
-	return 0;
-#undef EEPROM_4K_SIZE
-}
-
-static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
-				  enum eeprom_param param)
-{
-	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
-	struct modal_eep_4k_header *pModal = &eep->modalHeader;
-	struct base_eep_header_4k *pBase = &eep->baseEepHeader;
-
-	switch (param) {
-	case EEP_NFTHRESH_2:
-		return pModal->noiseFloorThreshCh[0];
-	case AR_EEPROM_MAC(0):
-		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
-	case AR_EEPROM_MAC(1):
-		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
-	case AR_EEPROM_MAC(2):
-		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
-	case EEP_REG_0:
-		return pBase->regDmn[0];
-	case EEP_REG_1:
-		return pBase->regDmn[1];
-	case EEP_OP_CAP:
-		return pBase->deviceCap;
-	case EEP_OP_MODE:
-		return pBase->opCapFlags;
-	case EEP_RF_SILENT:
-		return pBase->rfSilent;
-	case EEP_OB_2:
-		return pModal->ob_01;
-	case EEP_DB_2:
-		return pModal->db1_01;
-	case EEP_MINOR_REV:
-		return pBase->version & AR5416_EEP_VER_MINOR_MASK;
-	case EEP_TX_MASK:
-		return pBase->txMask;
-	case EEP_RX_MASK:
-		return pBase->rxMask;
-	case EEP_FRAC_N_5G:
-		return 0;
-	default:
-		return 0;
-	}
-}
-
-static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
-				struct ath9k_channel *chan,
-				struct cal_data_per_freq_4k *pRawDataSet,
-				u8 *bChans, u16 availPiers,
-				u16 tPdGainOverlap, int16_t *pMinCalPower,
-				u16 *pPdGainBoundaries, u8 *pPDADCValues,
-				u16 numXpdGains)
-{
-#define TMP_VAL_VPD_TABLE \
-	((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
-	int i, j, k;
-	int16_t ss;
-	u16 idxL = 0, idxR = 0, numPiers;
-	static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
-	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
-	u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
-	u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
-	int16_t vpdStep;
-	int16_t tmpVal;
-	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
-	bool match;
-	int16_t minDelta = 0;
-	struct chan_centers centers;
-#define PD_GAIN_BOUNDARY_DEFAULT 58;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	for (numPiers = 0; numPiers < availPiers; numPiers++) {
-		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
-			break;
-	}
-
-	match = ath9k_hw_get_lower_upper_index(
-					(u8)FREQ2FBIN(centers.synth_center,
-					IS_CHAN_2GHZ(chan)), bChans, numPiers,
-					&idxL, &idxR);
-
-	if (match) {
-		for (i = 0; i < numXpdGains; i++) {
-			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
-			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-					pRawDataSet[idxL].pwrPdg[i],
-					pRawDataSet[idxL].vpdPdg[i],
-					AR5416_EEP4K_PD_GAIN_ICEPTS,
-					vpdTableI[i]);
-		}
-	} else {
-		for (i = 0; i < numXpdGains; i++) {
-			pVpdL = pRawDataSet[idxL].vpdPdg[i];
-			pPwrL = pRawDataSet[idxL].pwrPdg[i];
-			pVpdR = pRawDataSet[idxR].vpdPdg[i];
-			pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
-			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
-			maxPwrT4[i] =
-				min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
-				    pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
-
-
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrL, pVpdL,
-						AR5416_EEP4K_PD_GAIN_ICEPTS,
-						vpdTableL[i]);
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrR, pVpdR,
-						AR5416_EEP4K_PD_GAIN_ICEPTS,
-						vpdTableR[i]);
-
-			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
-				vpdTableI[i][j] =
-					(u8)(ath9k_hw_interpolate((u16)
-					     FREQ2FBIN(centers.
-						       synth_center,
-						       IS_CHAN_2GHZ
-						       (chan)),
-					     bChans[idxL], bChans[idxR],
-					     vpdTableL[i][j], vpdTableR[i][j]));
-			}
-		}
-	}
-
-	*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
-
-	k = 0;
-
-	for (i = 0; i < numXpdGains; i++) {
-		if (i == (numXpdGains - 1))
-			pPdGainBoundaries[i] =
-				(u16)(maxPwrT4[i] / 2);
-		else
-			pPdGainBoundaries[i] =
-				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
-
-		pPdGainBoundaries[i] =
-			min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
-
-		if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
-			minDelta = pPdGainBoundaries[0] - 23;
-			pPdGainBoundaries[0] = 23;
-		} else {
-			minDelta = 0;
-		}
-
-		if (i == 0) {
-			if (AR_SREV_9280_10_OR_LATER(ah))
-				ss = (int16_t)(0 - (minPwrT4[i] / 2));
-			else
-				ss = 0;
-		} else {
-			ss = (int16_t)((pPdGainBoundaries[i - 1] -
-					(minPwrT4[i] / 2)) -
-				       tPdGainOverlap + 1 + minDelta);
-		}
-		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
-			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
-			ss++;
-		}
-
-		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
-		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
-				(minPwrT4[i] / 2));
-		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
-			tgtIndex : sizeCurrVpdTable;
-
-		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
-			pPDADCValues[k++] = vpdTableI[i][ss++];
-
-		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
-				    vpdTableI[i][sizeCurrVpdTable - 2]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		if (tgtIndex >= maxIndex) {
-			while ((ss <= tgtIndex) &&
-			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-				tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
-				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
-							 255 : tmpVal);
-				ss++;
-			}
-		}
-	}
-
-	while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
-		pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
-		i++;
-	}
-
-	while (k < AR5416_NUM_PDADC_VALUES) {
-		pPDADCValues[k] = pPDADCValues[k - 1];
-		k++;
-	}
-
-	return;
-#undef TMP_VAL_VPD_TABLE
-}
-
-static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
-				  struct ath9k_channel *chan,
-				  int16_t *pTxPowerIndexOffset)
-{
-	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-	struct cal_data_per_freq_4k *pRawDataset;
-	u8 *pCalBChans = NULL;
-	u16 pdGainOverlap_t2;
-	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
-	u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
-	u16 numPiers, i, j;
-	int16_t tMinCalPower;
-	u16 numXpdGain, xpdMask;
-	u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
-	u32 reg32, regOffset, regChainOffset;
-
-	xpdMask = pEepData->modalHeader.xpdGain;
-
-	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_2) {
-		pdGainOverlap_t2 =
-			pEepData->modalHeader.pdGainOverlap;
-	} else {
-		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
-					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
-	}
-
-	pCalBChans = pEepData->calFreqPier2G;
-	numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
-
-	numXpdGain = 0;
-
-	for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
-		if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
-			if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
-				break;
-			xpdGainValues[numXpdGain] =
-				(u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
-			numXpdGain++;
-		}
-	}
-
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
-		      (numXpdGain - 1) & 0x3);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
-		      xpdGainValues[0]);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
-		      xpdGainValues[1]);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
-
-	for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
-		if (AR_SREV_5416_20_OR_LATER(ah) &&
-		    (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
-		    (i != 0)) {
-			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
-		} else
-			regChainOffset = i * 0x1000;
-
-		if (pEepData->baseEepHeader.txMask & (1 << i)) {
-			pRawDataset = pEepData->calPierData2G[i];
-
-			ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
-					    pRawDataset, pCalBChans,
-					    numPiers, pdGainOverlap_t2,
-					    &tMinCalPower, gainBoundaries,
-					    pdadcValues, numXpdGain);
-
-			if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
-				REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
-					  SM(pdGainOverlap_t2,
-					     AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
-					  | SM(gainBoundaries[0],
-					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
-					  | SM(gainBoundaries[1],
-					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
-					  | SM(gainBoundaries[2],
-					       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
-					  | SM(gainBoundaries[3],
-				       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
-			}
-
-			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
-			for (j = 0; j < 32; j++) {
-				reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
-					((pdadcValues[4 * j + 1] & 0xFF) << 8) |
-					((pdadcValues[4 * j + 2] & 0xFF) << 16)|
-					((pdadcValues[4 * j + 3] & 0xFF) << 24);
-				REG_WRITE(ah, regOffset, reg32);
-
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-					"PDADC (%d,%4x): %4.4x %8.8x\n",
-					i, regChainOffset, regOffset,
-					reg32);
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-					"PDADC: Chain %d | "
-					"PDADC %3d Value %3d | "
-					"PDADC %3d Value %3d | "
-					"PDADC %3d Value %3d | "
-					"PDADC %3d Value %3d |\n",
-					i, 4 * j, pdadcValues[4 * j],
-					4 * j + 1, pdadcValues[4 * j + 1],
-					4 * j + 2, pdadcValues[4 * j + 2],
-					4 * j + 3,
-					pdadcValues[4 * j + 3]);
-
-				regOffset += 4;
-			}
-		}
-	}
-
-	*pTxPowerIndexOffset = 0;
-
-	return true;
-}
-
-static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
-						 struct ath9k_channel *chan,
-						 int16_t *ratesArray,
-						 u16 cfgCtl,
-						 u16 AntennaReduction,
-						 u16 twiceMaxRegulatoryPower,
-						 u16 powerLimit)
-{
-	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-	static const u16 tpScaleReductionTable[5] =
-		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
-
-	int i;
-	int16_t twiceLargestAntenna;
-	struct cal_ctl_data_4k *rep;
-	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
-		0, { 0, 0, 0, 0}
-	};
-	struct cal_target_power_leg targetPowerOfdmExt = {
-		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
-		0, { 0, 0, 0, 0 }
-	};
-	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
-		0, {0, 0, 0, 0}
-	};
-	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-	u16 ctlModesFor11g[] =
-		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
-		  CTL_2GHT40
-		};
-	u16 numCtlModes, *pCtlMode, ctlMode, freq;
-	struct chan_centers centers;
-	int tx_chainmask;
-	u16 twiceMinEdgePower;
-
-	tx_chainmask = ah->txchainmask;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
-
-	twiceLargestAntenna = (int16_t)min(AntennaReduction -
-					   twiceLargestAntenna, 0);
-
-	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
-	if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
-		maxRegAllowedPower -=
-			(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
-	}
-
-	scaledPower = min(powerLimit, maxRegAllowedPower);
-	scaledPower = max((u16)0, scaledPower);
-
-	numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
-	pCtlMode = ctlModesFor11g;
-
-	ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->calTargetPowerCck,
-			AR5416_NUM_2G_CCK_TARGET_POWERS,
-			&targetPowerCck, 4, false);
-	ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->calTargetPower2G,
-			AR5416_NUM_2G_20_TARGET_POWERS,
-			&targetPowerOfdm, 4, false);
-	ath9k_hw_get_target_powers(ah, chan,
-			pEepData->calTargetPower2GHT20,
-			AR5416_NUM_2G_20_TARGET_POWERS,
-			&targetPowerHt20, 8, false);
-
-	if (IS_CHAN_HT40(chan)) {
-		numCtlModes = ARRAY_SIZE(ctlModesFor11g);
-		ath9k_hw_get_target_powers(ah, chan,
-				pEepData->calTargetPower2GHT40,
-				AR5416_NUM_2G_40_TARGET_POWERS,
-				&targetPowerHt40, 8, true);
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->calTargetPowerCck,
-				AR5416_NUM_2G_CCK_TARGET_POWERS,
-				&targetPowerCckExt, 4, true);
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->calTargetPower2G,
-				AR5416_NUM_2G_20_TARGET_POWERS,
-				&targetPowerOfdmExt, 4, true);
-	}
-
-	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
-		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
-			(pCtlMode[ctlMode] == CTL_2GHT40);
-		if (isHt40CtlMode)
-			freq = centers.synth_center;
-		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
-			freq = centers.ext_center;
-		else
-			freq = centers.ctl_center;
-
-		if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
-		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
-			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
-			"EXT_ADDITIVE %d\n",
-			ctlMode, numCtlModes, isHt40CtlMode,
-			(pCtlMode[ctlMode] & EXT_ADDITIVE));
-
-		for (i = 0; (i < AR5416_NUM_CTLS) &&
-				pEepData->ctlIndex[i]; i++) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
-				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
-				"chan %d\n",
-				i, cfgCtl, pCtlMode[ctlMode],
-				pEepData->ctlIndex[i], chan->channel);
-
-			if ((((cfgCtl & ~CTL_MODE_M) |
-			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
-			     pEepData->ctlIndex[i]) ||
-			    (((cfgCtl & ~CTL_MODE_M) |
-			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
-			     ((pEepData->ctlIndex[i] & CTL_MODE_M) |
-			      SD_NO_CTL))) {
-				rep = &(pEepData->ctlData[i]);
-
-				twiceMinEdgePower =
-					ath9k_hw_get_max_edge_power(freq,
-				rep->ctlEdges[ar5416_get_ntxchains
-						(tx_chainmask) - 1],
-				IS_CHAN_2GHZ(chan),
-				AR5416_EEP4K_NUM_BAND_EDGES);
-
-				DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-					"    MATCH-EE_IDX %d: ch %d is2 %d "
-					"2xMinEdge %d chainmask %d chains %d\n",
-					i, freq, IS_CHAN_2GHZ(chan),
-					twiceMinEdgePower, tx_chainmask,
-					ar5416_get_ntxchains
-					(tx_chainmask));
-				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
-					twiceMaxEdgePower =
-						min(twiceMaxEdgePower,
-						    twiceMinEdgePower);
-				} else {
-					twiceMaxEdgePower = twiceMinEdgePower;
-					break;
-				}
-			}
-		}
-
-		minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"    SEL-Min ctlMode %d pCtlMode %d "
-			"2xMaxEdge %d sP %d minCtlPwr %d\n",
-			ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
-			scaledPower, minCtlPower);
-
-		switch (pCtlMode[ctlMode]) {
-		case CTL_11B:
-			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
-					i++) {
-				targetPowerCck.tPow2x[i] =
-					min((u16)targetPowerCck.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_11G:
-			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
-					i++) {
-				targetPowerOfdm.tPow2x[i] =
-					min((u16)targetPowerOfdm.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_2GHT20:
-			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
-					i++) {
-				targetPowerHt20.tPow2x[i] =
-					min((u16)targetPowerHt20.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_11B_EXT:
-			targetPowerCckExt.tPow2x[0] = min((u16)
-					targetPowerCckExt.tPow2x[0],
-					minCtlPower);
-			break;
-		case CTL_11G_EXT:
-			targetPowerOfdmExt.tPow2x[0] = min((u16)
-					targetPowerOfdmExt.tPow2x[0],
-					minCtlPower);
-			break;
-		case CTL_2GHT40:
-			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
-					i++) {
-				targetPowerHt40.tPow2x[i] =
-					min((u16)targetPowerHt40.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		default:
-			break;
-		}
-	}
-
-	ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
-		ratesArray[rate18mb] = ratesArray[rate24mb] =
-		targetPowerOfdm.tPow2x[0];
-	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
-	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
-	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
-	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
-
-	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
-		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
-
-	ratesArray[rate1l] = targetPowerCck.tPow2x[0];
-	ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
-	ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
-	ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
-
-	if (IS_CHAN_HT40(chan)) {
-		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
-			ratesArray[rateHt40_0 + i] =
-				targetPowerHt40.tPow2x[i];
-		}
-		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
-		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
-		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
-		ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
-	}
-	return true;
-}
-
-static int ath9k_hw_4k_set_txpower(struct ath_hw *ah,
-				   struct ath9k_channel *chan,
-				   u16 cfgCtl,
-				   u8 twiceAntennaReduction,
-				   u8 twiceMaxRegulatoryPower,
-				   u8 powerLimit)
-{
-	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-	struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
-	int16_t ratesArray[Ar5416RateSize];
-	int16_t txPowerIndexOffset = 0;
-	u8 ht40PowerIncForPdadc = 2;
-	int i;
-
-	memset(ratesArray, 0, sizeof(ratesArray));
-
-	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_2) {
-		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
-	}
-
-	if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan,
-					       &ratesArray[0], cfgCtl,
-					       twiceAntennaReduction,
-					       twiceMaxRegulatoryPower,
-					       powerLimit)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"ath9k_hw_set_txpower: unable to set "
-			"tx power per rate table\n");
-		return -EIO;
-	}
-
-	if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "ath9k_hw_set_txpower: unable to set power table\n");
-		return -EIO;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
-		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
-		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-			ratesArray[i] = AR5416_MAX_RATE_POWER;
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		for (i = 0; i < Ar5416RateSize; i++)
-			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
-		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
-		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
-		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
-		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
-		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
-		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
-		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
-		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
-
-	if (IS_CHAN_2GHZ(chan)) {
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
-			  ATH9K_POW_SM(ratesArray[rate2s], 24)
-			  | ATH9K_POW_SM(ratesArray[rate2l], 16)
-			  | ATH9K_POW_SM(ratesArray[rateXr], 8)
-			  | ATH9K_POW_SM(ratesArray[rate1l], 0));
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
-			  ATH9K_POW_SM(ratesArray[rate11s], 24)
-			  | ATH9K_POW_SM(ratesArray[rate11l], 16)
-			  | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
-			  | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
-		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
-		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
-
-	if (IS_CHAN_HT40(chan)) {
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
-			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
-				       ht40PowerIncForPdadc, 24)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
-					 ht40PowerIncForPdadc, 16)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
-					 ht40PowerIncForPdadc, 8)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
-					 ht40PowerIncForPdadc, 0));
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
-			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
-				       ht40PowerIncForPdadc, 24)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
-					 ht40PowerIncForPdadc, 16)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
-					 ht40PowerIncForPdadc, 8)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
-					 ht40PowerIncForPdadc, 0));
-
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
-			  ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
-			  | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
-			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
-			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
-	}
-
-	i = rate6mb;
-
-	if (IS_CHAN_HT40(chan))
-		i = rateHt40_0;
-	else if (IS_CHAN_HT20(chan))
-		i = rateHt20_0;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		ah->regulatory.max_power_level =
-			ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
-	else
-		ah->regulatory.max_power_level = ratesArray[i];
-
-	return 0;
-}
-
-static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
-				  struct ath9k_channel *chan)
-{
-	struct modal_eep_4k_header *pModal;
-	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
-	u8 biaslevel;
-
-	if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
-		return;
-
-	if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
-		return;
-
-	pModal = &eep->modalHeader;
-
-	if (pModal->xpaBiasLvl != 0xff) {
-		biaslevel = pModal->xpaBiasLvl;
-		INI_RA(&ah->iniAddac, 7, 1) =
-		  (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
-	}
-}
-
-static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
-				 struct modal_eep_4k_header *pModal,
-				 struct ar5416_eeprom_4k *eep,
-				 u8 txRxAttenLocal, int regChainOffset)
-{
-	REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
-		  pModal->antCtrlChain[0]);
-
-	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
-		  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
-		   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
-		     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
-		  SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
-		  SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
-
-	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_3) {
-		txRxAttenLocal = pModal->txRxAttenCh[0];
-
-		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
-		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
-		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
-			      pModal->xatten2Margin[0]);
-		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
-	}
-
-	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
-		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
-	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
-		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
-
-	if (AR_SREV_9285_11(ah))
-		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
-}
-
-static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
-					 struct ath9k_channel *chan)
-{
-	struct modal_eep_4k_header *pModal;
-	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
-	u8 txRxAttenLocal;
-	u8 ob[5], db1[5], db2[5];
-	u8 ant_div_control1, ant_div_control2;
-	u32 regVal;
-
-	pModal = &eep->modalHeader;
-	txRxAttenLocal = 23;
-
-	REG_WRITE(ah, AR_PHY_SWITCH_COM,
-		  ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
-
-	/* Single chain for 4K EEPROM*/
-	ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0);
-
-	/* Initialize Ant Diversity settings from EEPROM */
-	if (pModal->version == 3) {
-		ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
-		ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
-		regVal = REG_READ(ah, 0x99ac);
-		regVal &= (~(0x7f000000));
-		regVal |= ((ant_div_control1 & 0x1) << 24);
-		regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
-		regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
-		regVal |= ((ant_div_control2 & 0x3) << 25);
-		regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
-		REG_WRITE(ah, 0x99ac, regVal);
-		regVal = REG_READ(ah, 0x99ac);
-		regVal = REG_READ(ah, 0xa208);
-		regVal &= (~(0x1 << 13));
-		regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
-		REG_WRITE(ah, 0xa208, regVal);
-		regVal = REG_READ(ah, 0xa208);
-	}
-
-	if (pModal->version >= 2) {
-		ob[0] = (pModal->ob_01 & 0xf);
-		ob[1] = (pModal->ob_01 >> 4) & 0xf;
-		ob[2] = (pModal->ob_234 & 0xf);
-		ob[3] = ((pModal->ob_234 >> 4) & 0xf);
-		ob[4] = ((pModal->ob_234 >> 8) & 0xf);
-
-		db1[0] = (pModal->db1_01 & 0xf);
-		db1[1] = ((pModal->db1_01 >> 4) & 0xf);
-		db1[2] = (pModal->db1_234 & 0xf);
-		db1[3] = ((pModal->db1_234 >> 4) & 0xf);
-		db1[4] = ((pModal->db1_234 >> 8) & 0xf);
-
-		db2[0] = (pModal->db2_01 & 0xf);
-		db2[1] = ((pModal->db2_01 >> 4) & 0xf);
-		db2[2] = (pModal->db2_234 & 0xf);
-		db2[3] = ((pModal->db2_234 >> 4) & 0xf);
-		db2[4] = ((pModal->db2_234 >> 8) & 0xf);
-
-	} else if (pModal->version == 1) {
-		ob[0] = (pModal->ob_01 & 0xf);
-		ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
-		db1[0] = (pModal->db1_01 & 0xf);
-		db1[1] = db1[2] = db1[3] =
-			db1[4] = ((pModal->db1_01 >> 4) & 0xf);
-		db2[0] = (pModal->db2_01 & 0xf);
-		db2[1] = db2[2] = db2[3] =
-			db2[4] = ((pModal->db2_01 >> 4) & 0xf);
-	} else {
-		int i;
-		for (i = 0; i < 5; i++) {
-			ob[i] = pModal->ob_01;
-			db1[i] = pModal->db1_01;
-			db2[i] = pModal->db1_01;
-		}
-	}
-
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
-
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
-			AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
-			AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
-			AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
-
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
-			AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
-			AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
-			AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
-			AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
-	ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
-			AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
-
-
-	if (AR_SREV_9285_11(ah))
-		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
-
-	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
-		      pModal->switchSettling);
-	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
-		      pModal->adcDesiredSize);
-
-	REG_WRITE(ah, AR_PHY_RF_CTL4,
-		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
-		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
-		  SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)  |
-		  SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
-
-	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
-		      pModal->txEndToRxOn);
-	REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
-		      pModal->thresh62);
-	REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
-		      pModal->thresh62);
-
-	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-						AR5416_EEP_MINOR_VER_2) {
-		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
-			      pModal->txFrameToDataStart);
-		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
-			      pModal->txFrameToPaOn);
-	}
-
-	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-						AR5416_EEP_MINOR_VER_3) {
-		if (IS_CHAN_HT40(chan))
-			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
-				      AR_PHY_SETTLING_SWITCH,
-				      pModal->swSettleHt40);
-	}
-}
-
-static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
-					      struct ath9k_channel *chan)
-{
-	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
-	struct modal_eep_4k_header *pModal = &eep->modalHeader;
-
-	return pModal->antCtrlCommon & 0xFFFF;
-}
-
-static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
-					 enum ieee80211_band freq_band)
-{
-	return 1;
-}
-
-static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
-{
-#define EEP_MAP4K_SPURCHAN \
-	(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
-
-	u16 spur_val = AR_NO_SPUR;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"Getting spur idx %d is2Ghz. %d val %x\n",
-		i, is2GHz, ah->config.spurchans[i][is2GHz]);
-
-	switch (ah->config.spurmode) {
-	case SPUR_DISABLE:
-		break;
-	case SPUR_ENABLE_IOCTL:
-		spur_val = ah->config.spurchans[i][is2GHz];
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"Getting spur val from new loc. %d\n", spur_val);
-		break;
-	case SPUR_ENABLE_EEPROM:
-		spur_val = EEP_MAP4K_SPURCHAN;
-		break;
-	}
-
-	return spur_val;
-
-#undef EEP_MAP4K_SPURCHAN
-}
-
-static struct eeprom_ops eep_4k_ops = {
-	.check_eeprom		= ath9k_hw_4k_check_eeprom,
-	.get_eeprom		= ath9k_hw_4k_get_eeprom,
-	.fill_eeprom		= ath9k_hw_4k_fill_eeprom,
-	.get_eeprom_ver		= ath9k_hw_4k_get_eeprom_ver,
-	.get_eeprom_rev		= ath9k_hw_4k_get_eeprom_rev,
-	.get_num_ant_config	= ath9k_hw_4k_get_num_ant_config,
-	.get_eeprom_antenna_cfg	= ath9k_hw_4k_get_eeprom_antenna_cfg,
-	.set_board_values	= ath9k_hw_4k_set_board_values,
-	.set_addac		= ath9k_hw_4k_set_addac,
-	.set_txpower		= ath9k_hw_4k_set_txpower,
-	.get_spur_channel	= ath9k_hw_4k_get_spur_channel
-};
-
-/************************************************/
-/* EEPROM Operations for non-4K (Default) cards */
-/************************************************/
-
-static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
-{
-	return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
-}
-
-static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
-{
-	return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
-}
-
-static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
-{
-#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
-	u16 *eep_data = (u16 *)&ah->eeprom.def;
-	int addr, ar5416_eep_start_loc = 0x100;
-
-	for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
-		if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
-					 eep_data)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"Unable to read eeprom region\n");
-			return false;
-		}
-		eep_data++;
-	}
-	return true;
-#undef SIZE_EEPROM_DEF
-}
-
-static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
-{
-	struct ar5416_eeprom_def *eep =
-		(struct ar5416_eeprom_def *) &ah->eeprom.def;
-	u16 *eepdata, temp, magic, magic2;
-	u32 sum = 0, el;
-	bool need_swap = false;
-	int i, addr, size;
-
-	if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
-		return false;
-	}
-
-	if (!ath9k_hw_use_flash(ah)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"Read Magic = 0x%04X\n", magic);
-
-		if (magic != AR5416_EEPROM_MAGIC) {
-			magic2 = swab16(magic);
-
-			if (magic2 == AR5416_EEPROM_MAGIC) {
-				size = sizeof(struct ar5416_eeprom_def);
-				need_swap = true;
-				eepdata = (u16 *) (&ah->eeprom);
-
-				for (addr = 0; addr < size / sizeof(u16); addr++) {
-					temp = swab16(*eepdata);
-					*eepdata = temp;
-					eepdata++;
-				}
-			} else {
-				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-					"Invalid EEPROM Magic. "
-					"Endianness mismatch.\n");
-				return -EINVAL;
-			}
-		}
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
-		need_swap ? "True" : "False");
-
-	if (need_swap)
-		el = swab16(ah->eeprom.def.baseEepHeader.length);
-	else
-		el = ah->eeprom.def.baseEepHeader.length;
-
-	if (el > sizeof(struct ar5416_eeprom_def))
-		el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
-	else
-		el = el / sizeof(u16);
-
-	eepdata = (u16 *)(&ah->eeprom);
-
-	for (i = 0; i < el; i++)
-		sum ^= *eepdata++;
-
-	if (need_swap) {
-		u32 integer, j;
-		u16 word;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"EEPROM Endianness is not native.. Changing.\n");
-
-		word = swab16(eep->baseEepHeader.length);
-		eep->baseEepHeader.length = word;
-
-		word = swab16(eep->baseEepHeader.checksum);
-		eep->baseEepHeader.checksum = word;
-
-		word = swab16(eep->baseEepHeader.version);
-		eep->baseEepHeader.version = word;
-
-		word = swab16(eep->baseEepHeader.regDmn[0]);
-		eep->baseEepHeader.regDmn[0] = word;
-
-		word = swab16(eep->baseEepHeader.regDmn[1]);
-		eep->baseEepHeader.regDmn[1] = word;
-
-		word = swab16(eep->baseEepHeader.rfSilent);
-		eep->baseEepHeader.rfSilent = word;
-
-		word = swab16(eep->baseEepHeader.blueToothOptions);
-		eep->baseEepHeader.blueToothOptions = word;
-
-		word = swab16(eep->baseEepHeader.deviceCap);
-		eep->baseEepHeader.deviceCap = word;
-
-		for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
-			struct modal_eep_header *pModal =
-				&eep->modalHeader[j];
-			integer = swab32(pModal->antCtrlCommon);
-			pModal->antCtrlCommon = integer;
-
-			for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-				integer = swab32(pModal->antCtrlChain[i]);
-				pModal->antCtrlChain[i] = integer;
-			}
-
-			for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
-				word = swab16(pModal->spurChans[i].spurChan);
-				pModal->spurChans[i].spurChan = word;
-			}
-		}
-	}
-
-	if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
-	    ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
-		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-			"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
-			sum, ah->eep_ops->get_eeprom_ver(ah));
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
-				   enum eeprom_param param)
-{
-	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
-	struct modal_eep_header *pModal = eep->modalHeader;
-	struct base_eep_header *pBase = &eep->baseEepHeader;
-
-	switch (param) {
-	case EEP_NFTHRESH_5:
-		return pModal[0].noiseFloorThreshCh[0];
-	case EEP_NFTHRESH_2:
-		return pModal[1].noiseFloorThreshCh[0];
-	case AR_EEPROM_MAC(0):
-		return pBase->macAddr[0] << 8 | pBase->macAddr[1];
-	case AR_EEPROM_MAC(1):
-		return pBase->macAddr[2] << 8 | pBase->macAddr[3];
-	case AR_EEPROM_MAC(2):
-		return pBase->macAddr[4] << 8 | pBase->macAddr[5];
-	case EEP_REG_0:
-		return pBase->regDmn[0];
-	case EEP_REG_1:
-		return pBase->regDmn[1];
-	case EEP_OP_CAP:
-		return pBase->deviceCap;
-	case EEP_OP_MODE:
-		return pBase->opCapFlags;
-	case EEP_RF_SILENT:
-		return pBase->rfSilent;
-	case EEP_OB_5:
-		return pModal[0].ob;
-	case EEP_DB_5:
-		return pModal[0].db;
-	case EEP_OB_2:
-		return pModal[1].ob;
-	case EEP_DB_2:
-		return pModal[1].db;
-	case EEP_MINOR_REV:
-		return AR5416_VER_MASK;
-	case EEP_TX_MASK:
-		return pBase->txMask;
-	case EEP_RX_MASK:
-		return pBase->rxMask;
-	case EEP_RXGAIN_TYPE:
-		return pBase->rxGainType;
-	case EEP_TXGAIN_TYPE:
-		return pBase->txGainType;
-	case EEP_OL_PWRCTRL:
-		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
-			return pBase->openLoopPwrCntl ? true : false;
-		else
-			return false;
-	case EEP_RC_CHAIN_MASK:
-		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
-			return pBase->rcChainMask;
-		else
-			return 0;
-	case EEP_DAC_HPWR_5G:
-		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
-			return pBase->dacHiPwrMode_5G;
-		else
-			return 0;
-	case EEP_FRAC_N_5G:
-		if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
-			return pBase->frac_n_5g;
-		else
-			return 0;
-	default:
-		return 0;
-	}
-}
-
-static void ath9k_hw_def_set_gain(struct ath_hw *ah,
-				  struct modal_eep_header *pModal,
-				  struct ar5416_eeprom_def *eep,
-				  u8 txRxAttenLocal, int regChainOffset, int i)
-{
-	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
-		txRxAttenLocal = pModal->txRxAttenCh[i];
-
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
-			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
-			      pModal->bswMargin[i]);
-			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN1_DB,
-			      pModal->bswAtten[i]);
-			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
-			      pModal->xatten2Margin[i]);
-			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			      AR_PHY_GAIN_2GHZ_XATTEN2_DB,
-			      pModal->xatten2Db[i]);
-		} else {
-			REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
-			   ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
-			  | SM(pModal-> bswMargin[i],
-			       AR_PHY_GAIN_2GHZ_BSW_MARGIN));
-			REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
-			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
-			   ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
-			  | SM(pModal->bswAtten[i],
-			       AR_PHY_GAIN_2GHZ_BSW_ATTEN));
-		}
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		REG_RMW_FIELD(ah,
-		      AR_PHY_RXGAIN + regChainOffset,
-		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
-		REG_RMW_FIELD(ah,
-		      AR_PHY_RXGAIN + regChainOffset,
-		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
-	} else {
-		REG_WRITE(ah,
-			  AR_PHY_RXGAIN + regChainOffset,
-			  (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
-			   ~AR_PHY_RXGAIN_TXRX_ATTEN)
-			  | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
-		REG_WRITE(ah,
-			  AR_PHY_GAIN_2GHZ + regChainOffset,
-			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
-			   ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
-			  SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
-	}
-}
-
-static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
-					  struct ath9k_channel *chan)
-{
-	struct modal_eep_header *pModal;
-	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
-	int i, regChainOffset;
-	u8 txRxAttenLocal;
-
-	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-	txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
-
-	REG_WRITE(ah, AR_PHY_SWITCH_COM,
-		  ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		if (AR_SREV_9280(ah)) {
-			if (i >= 2)
-				break;
-		}
-
-		if (AR_SREV_5416_20_OR_LATER(ah) &&
-		    (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
-			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
-		else
-			regChainOffset = i * 0x1000;
-
-		REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
-			  pModal->antCtrlChain[i]);
-
-		REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
-			  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
-			   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
-			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
-			  SM(pModal->iqCalICh[i],
-			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
-			  SM(pModal->iqCalQCh[i],
-			     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
-
-		if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
-			ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
-					      regChainOffset, i);
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		if (IS_CHAN_2GHZ(chan)) {
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
-						  AR_AN_RF2G1_CH0_OB,
-						  AR_AN_RF2G1_CH0_OB_S,
-						  pModal->ob);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
-						  AR_AN_RF2G1_CH0_DB,
-						  AR_AN_RF2G1_CH0_DB_S,
-						  pModal->db);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
-						  AR_AN_RF2G1_CH1_OB,
-						  AR_AN_RF2G1_CH1_OB_S,
-						  pModal->ob_ch1);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
-						  AR_AN_RF2G1_CH1_DB,
-						  AR_AN_RF2G1_CH1_DB_S,
-						  pModal->db_ch1);
-		} else {
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
-						  AR_AN_RF5G1_CH0_OB5,
-						  AR_AN_RF5G1_CH0_OB5_S,
-						  pModal->ob);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
-						  AR_AN_RF5G1_CH0_DB5,
-						  AR_AN_RF5G1_CH0_DB5_S,
-						  pModal->db);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
-						  AR_AN_RF5G1_CH1_OB5,
-						  AR_AN_RF5G1_CH1_OB5_S,
-						  pModal->ob_ch1);
-			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
-						  AR_AN_RF5G1_CH1_DB5,
-						  AR_AN_RF5G1_CH1_DB5_S,
-						  pModal->db_ch1);
-		}
-		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
-					  AR_AN_TOP2_XPABIAS_LVL,
-					  AR_AN_TOP2_XPABIAS_LVL_S,
-					  pModal->xpaBiasLvl);
-		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
-					  AR_AN_TOP2_LOCALBIAS,
-					  AR_AN_TOP2_LOCALBIAS_S,
-					  pModal->local_bias);
-		REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
-			      pModal->force_xpaon);
-	}
-
-	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
-		      pModal->switchSettling);
-	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
-		      pModal->adcDesiredSize);
-
-	if (!AR_SREV_9280_10_OR_LATER(ah))
-		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
-			      AR_PHY_DESIRED_SZ_PGA,
-			      pModal->pgaDesiredSize);
-
-	REG_WRITE(ah, AR_PHY_RF_CTL4,
-		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
-		  | SM(pModal->txEndToXpaOff,
-		       AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
-		  | SM(pModal->txFrameToXpaOn,
-		       AR_PHY_RF_CTL4_FRAME_XPAA_ON)
-		  | SM(pModal->txFrameToXpaOn,
-		       AR_PHY_RF_CTL4_FRAME_XPAB_ON));
-
-	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
-		      pModal->txEndToRxOn);
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
-			      pModal->thresh62);
-		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
-			      AR_PHY_EXT_CCA0_THRESH62,
-			      pModal->thresh62);
-	} else {
-		REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
-			      pModal->thresh62);
-		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
-			      AR_PHY_EXT_CCA_THRESH62,
-			      pModal->thresh62);
-	}
-
-	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
-		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
-			      AR_PHY_TX_END_DATA_START,
-			      pModal->txFrameToDataStart);
-		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
-			      pModal->txFrameToPaOn);
-	}
-
-	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
-		if (IS_CHAN_HT40(chan))
-			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
-				      AR_PHY_SETTLING_SWITCH,
-				      pModal->swSettleHt40);
-	}
-
-	if (AR_SREV_9280_20_OR_LATER(ah) &&
-	    AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
-		REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
-			      AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
-			      pModal->miscBits);
-
-
-	if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
-		if (IS_CHAN_2GHZ(chan))
-			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
-					eep->baseEepHeader.dacLpMode);
-		else if (eep->baseEepHeader.dacHiPwrMode_5G)
-			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
-		else
-			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
-				      eep->baseEepHeader.dacLpMode);
-
-		REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
-			      pModal->miscBits >> 2);
-
-		REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
-			      AR_PHY_TX_DESIRED_SCALE_CCK,
-			      eep->baseEepHeader.desiredScaleCCK);
-	}
-}
-
-static void ath9k_hw_def_set_addac(struct ath_hw *ah,
-				   struct ath9k_channel *chan)
-{
-#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
-	struct modal_eep_header *pModal;
-	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
-	u8 biaslevel;
-
-	if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
-		return;
-
-	if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
-		return;
-
-	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
-	if (pModal->xpaBiasLvl != 0xff) {
-		biaslevel = pModal->xpaBiasLvl;
-	} else {
-		u16 resetFreqBin, freqBin, freqCount = 0;
-		struct chan_centers centers;
-
-		ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-		resetFreqBin = FREQ2FBIN(centers.synth_center,
-					 IS_CHAN_2GHZ(chan));
-		freqBin = XPA_LVL_FREQ(0) & 0xff;
-		biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
-
-		freqCount++;
-
-		while (freqCount < 3) {
-			if (XPA_LVL_FREQ(freqCount) == 0x0)
-				break;
-
-			freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
-			if (resetFreqBin >= freqBin)
-				biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
-			else
-				break;
-			freqCount++;
-		}
-	}
-
-	if (IS_CHAN_2GHZ(chan)) {
-		INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
-					7, 1) & (~0x18)) | biaslevel << 3;
-	} else {
-		INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
-					6, 1) & (~0xc0)) | biaslevel << 6;
-	}
-#undef XPA_LVL_FREQ
-}
-
-static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
-				struct ath9k_channel *chan,
-				struct cal_data_per_freq *pRawDataSet,
-				u8 *bChans, u16 availPiers,
-				u16 tPdGainOverlap, int16_t *pMinCalPower,
-				u16 *pPdGainBoundaries, u8 *pPDADCValues,
-				u16 numXpdGains)
-{
-	int i, j, k;
-	int16_t ss;
-	u16 idxL = 0, idxR = 0, numPiers;
-	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
-		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
-	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
-	u8 minPwrT4[AR5416_NUM_PD_GAINS];
-	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
-	int16_t vpdStep;
-	int16_t tmpVal;
-	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
-	bool match;
-	int16_t minDelta = 0;
-	struct chan_centers centers;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	for (numPiers = 0; numPiers < availPiers; numPiers++) {
-		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
-			break;
-	}
-
-	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
-							     IS_CHAN_2GHZ(chan)),
-					       bChans, numPiers, &idxL, &idxR);
-
-	if (match) {
-		for (i = 0; i < numXpdGains; i++) {
-			minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
-			maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-					pRawDataSet[idxL].pwrPdg[i],
-					pRawDataSet[idxL].vpdPdg[i],
-					AR5416_PD_GAIN_ICEPTS,
-					vpdTableI[i]);
-		}
-	} else {
-		for (i = 0; i < numXpdGains; i++) {
-			pVpdL = pRawDataSet[idxL].vpdPdg[i];
-			pPwrL = pRawDataSet[idxL].pwrPdg[i];
-			pVpdR = pRawDataSet[idxR].vpdPdg[i];
-			pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
-			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
-			maxPwrT4[i] =
-				min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
-				    pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
-
-
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrL, pVpdL,
-						AR5416_PD_GAIN_ICEPTS,
-						vpdTableL[i]);
-			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
-						pPwrR, pVpdR,
-						AR5416_PD_GAIN_ICEPTS,
-						vpdTableR[i]);
-
-			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
-				vpdTableI[i][j] =
-					(u8)(ath9k_hw_interpolate((u16)
-					     FREQ2FBIN(centers.
-						       synth_center,
-						       IS_CHAN_2GHZ
-						       (chan)),
-					     bChans[idxL], bChans[idxR],
-					     vpdTableL[i][j], vpdTableR[i][j]));
-			}
-		}
-	}
-
-	*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
-
-	k = 0;
-
-	for (i = 0; i < numXpdGains; i++) {
-		if (i == (numXpdGains - 1))
-			pPdGainBoundaries[i] =
-				(u16)(maxPwrT4[i] / 2);
-		else
-			pPdGainBoundaries[i] =
-				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
-
-		pPdGainBoundaries[i] =
-			min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
-
-		if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
-			minDelta = pPdGainBoundaries[0] - 23;
-			pPdGainBoundaries[0] = 23;
-		} else {
-			minDelta = 0;
-		}
-
-		if (i == 0) {
-			if (AR_SREV_9280_10_OR_LATER(ah))
-				ss = (int16_t)(0 - (minPwrT4[i] / 2));
-			else
-				ss = 0;
-		} else {
-			ss = (int16_t)((pPdGainBoundaries[i - 1] -
-					(minPwrT4[i] / 2)) -
-				       tPdGainOverlap + 1 + minDelta);
-		}
-		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
-			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
-			ss++;
-		}
-
-		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
-		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
-				(minPwrT4[i] / 2));
-		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
-			tgtIndex : sizeCurrVpdTable;
-
-		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-			pPDADCValues[k++] = vpdTableI[i][ss++];
-		}
-
-		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
-				    vpdTableI[i][sizeCurrVpdTable - 2]);
-		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
-
-		if (tgtIndex > maxIndex) {
-			while ((ss <= tgtIndex) &&
-			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
-				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
-						    (ss - maxIndex + 1) * vpdStep));
-				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
-							 255 : tmpVal);
-				ss++;
-			}
-		}
-	}
-
-	while (i < AR5416_PD_GAINS_IN_MASK) {
-		pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
-		i++;
-	}
-
-	while (k < AR5416_NUM_PDADC_VALUES) {
-		pPDADCValues[k] = pPDADCValues[k - 1];
-		k++;
-	}
-
-	return;
-}
-
-static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
-				  struct ath9k_channel *chan,
-				  int16_t *pTxPowerIndexOffset)
-{
-#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
-#define SM_PDGAIN_B(x, y) \
-		SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
-
-	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
-	struct cal_data_per_freq *pRawDataset;
-	u8 *pCalBChans = NULL;
-	u16 pdGainOverlap_t2;
-	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
-	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
-	u16 numPiers, i, j;
-	int16_t tMinCalPower;
-	u16 numXpdGain, xpdMask;
-	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
-	u32 reg32, regOffset, regChainOffset;
-	int16_t modalIdx;
-
-	modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
-	xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
-
-	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_2) {
-		pdGainOverlap_t2 =
-			pEepData->modalHeader[modalIdx].pdGainOverlap;
-	} else {
-		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
-					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
-	}
-
-	if (IS_CHAN_2GHZ(chan)) {
-		pCalBChans = pEepData->calFreqPier2G;
-		numPiers = AR5416_NUM_2G_CAL_PIERS;
-	} else {
-		pCalBChans = pEepData->calFreqPier5G;
-		numPiers = AR5416_NUM_5G_CAL_PIERS;
-	}
-
-	if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
-		pRawDataset = pEepData->calPierData2G[0];
-		ah->initPDADC = ((struct calDataPerFreqOpLoop *)
-				 pRawDataset)->vpdPdg[0][0];
-	}
-
-	numXpdGain = 0;
-
-	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
-		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
-			if (numXpdGain >= AR5416_NUM_PD_GAINS)
-				break;
-			xpdGainValues[numXpdGain] =
-				(u16)(AR5416_PD_GAINS_IN_MASK - i);
-			numXpdGain++;
-		}
-	}
-
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
-		      (numXpdGain - 1) & 0x3);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
-		      xpdGainValues[0]);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
-		      xpdGainValues[1]);
-	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
-		      xpdGainValues[2]);
-
-	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-		if (AR_SREV_5416_20_OR_LATER(ah) &&
-		    (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
-		    (i != 0)) {
-			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
-		} else
-			regChainOffset = i * 0x1000;
-
-		if (pEepData->baseEepHeader.txMask & (1 << i)) {
-			if (IS_CHAN_2GHZ(chan))
-				pRawDataset = pEepData->calPierData2G[i];
-			else
-				pRawDataset = pEepData->calPierData5G[i];
-
-
-			if (OLC_FOR_AR9280_20_LATER) {
-				u8 pcdacIdx;
-				u8 txPower;
-
-				ath9k_get_txgain_index(ah, chan,
-				(struct calDataPerFreqOpLoop *)pRawDataset,
-				pCalBChans, numPiers, &txPower, &pcdacIdx);
-				ath9k_olc_get_pdadcs(ah, pcdacIdx,
-						     txPower/2, pdadcValues);
-			} else {
-				ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
-							chan, pRawDataset,
-							pCalBChans, numPiers,
-							pdGainOverlap_t2,
-							&tMinCalPower,
-							gainBoundaries,
-							pdadcValues,
-							numXpdGain);
-			}
-
-			if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
-				if (OLC_FOR_AR9280_20_LATER) {
-					REG_WRITE(ah,
-						AR_PHY_TPCRG5 + regChainOffset,
-						SM(0x6,
-						AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
-						SM_PD_GAIN(1) | SM_PD_GAIN(2) |
-						SM_PD_GAIN(3) | SM_PD_GAIN(4));
-				} else {
-					REG_WRITE(ah,
-						AR_PHY_TPCRG5 + regChainOffset,
-						SM(pdGainOverlap_t2,
-						AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
-						SM_PDGAIN_B(0, 1) |
-						SM_PDGAIN_B(1, 2) |
-						SM_PDGAIN_B(2, 3) |
-						SM_PDGAIN_B(3, 4));
-				}
-			}
-
-			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
-			for (j = 0; j < 32; j++) {
-				reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
-					((pdadcValues[4 * j + 1] & 0xFF) << 8) |
-					((pdadcValues[4 * j + 2] & 0xFF) << 16)|
-					((pdadcValues[4 * j + 3] & 0xFF) << 24);
-				REG_WRITE(ah, regOffset, reg32);
-
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-					"PDADC (%d,%4x): %4.4x %8.8x\n",
-					i, regChainOffset, regOffset,
-					reg32);
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-					"PDADC: Chain %d | PDADC %3d "
-					"Value %3d | PDADC %3d Value %3d | "
-					"PDADC %3d Value %3d | PDADC %3d "
-					"Value %3d |\n",
-					i, 4 * j, pdadcValues[4 * j],
-					4 * j + 1, pdadcValues[4 * j + 1],
-					4 * j + 2, pdadcValues[4 * j + 2],
-					4 * j + 3,
-					pdadcValues[4 * j + 3]);
-
-				regOffset += 4;
-			}
-		}
-	}
-
-	*pTxPowerIndexOffset = 0;
-
-	return true;
-#undef SM_PD_GAIN
-#undef SM_PDGAIN_B
-}
-
-static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
-						  struct ath9k_channel *chan,
-						  int16_t *ratesArray,
-						  u16 cfgCtl,
-						  u16 AntennaReduction,
-						  u16 twiceMaxRegulatoryPower,
-						  u16 powerLimit)
-{
-#define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
-#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10 /* 10*log10(3)*2 */
-
-	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
-	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-	static const u16 tpScaleReductionTable[5] =
-		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
-
-	int i;
-	int16_t twiceLargestAntenna;
-	struct cal_ctl_data *rep;
-	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
-		0, { 0, 0, 0, 0}
-	};
-	struct cal_target_power_leg targetPowerOfdmExt = {
-		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
-		0, { 0, 0, 0, 0 }
-	};
-	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
-		0, {0, 0, 0, 0}
-	};
-	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-	u16 ctlModesFor11a[] =
-		{ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
-	u16 ctlModesFor11g[] =
-		{ CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
-		  CTL_2GHT40
-		};
-	u16 numCtlModes, *pCtlMode, ctlMode, freq;
-	struct chan_centers centers;
-	int tx_chainmask;
-	u16 twiceMinEdgePower;
-
-	tx_chainmask = ah->txchainmask;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-	twiceLargestAntenna = max(
-		pEepData->modalHeader
-			[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
-		pEepData->modalHeader
-			[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
-
-	twiceLargestAntenna = max((u8)twiceLargestAntenna,
-				  pEepData->modalHeader
-				  [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
-
-	twiceLargestAntenna = (int16_t)min(AntennaReduction -
-					   twiceLargestAntenna, 0);
-
-	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
-	if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
-		maxRegAllowedPower -=
-			(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
-	}
-
-	scaledPower = min(powerLimit, maxRegAllowedPower);
-
-	switch (ar5416_get_ntxchains(tx_chainmask)) {
-	case 1:
-		break;
-	case 2:
-		scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
-		break;
-	case 3:
-		scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
-		break;
-	}
-
-	scaledPower = max((u16)0, scaledPower);
-
-	if (IS_CHAN_2GHZ(chan)) {
-		numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
-			SUB_NUM_CTL_MODES_AT_2G_40;
-		pCtlMode = ctlModesFor11g;
-
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->calTargetPowerCck,
-			AR5416_NUM_2G_CCK_TARGET_POWERS,
-			&targetPowerCck, 4, false);
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->calTargetPower2G,
-			AR5416_NUM_2G_20_TARGET_POWERS,
-			&targetPowerOfdm, 4, false);
-		ath9k_hw_get_target_powers(ah, chan,
-			pEepData->calTargetPower2GHT20,
-			AR5416_NUM_2G_20_TARGET_POWERS,
-			&targetPowerHt20, 8, false);
-
-		if (IS_CHAN_HT40(chan)) {
-			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
-			ath9k_hw_get_target_powers(ah, chan,
-				pEepData->calTargetPower2GHT40,
-				AR5416_NUM_2G_40_TARGET_POWERS,
-				&targetPowerHt40, 8, true);
-			ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->calTargetPowerCck,
-				AR5416_NUM_2G_CCK_TARGET_POWERS,
-				&targetPowerCckExt, 4, true);
-			ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->calTargetPower2G,
-				AR5416_NUM_2G_20_TARGET_POWERS,
-				&targetPowerOfdmExt, 4, true);
-		}
-	} else {
-		numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
-			SUB_NUM_CTL_MODES_AT_5G_40;
-		pCtlMode = ctlModesFor11a;
-
-		ath9k_hw_get_legacy_target_powers(ah, chan,
-			pEepData->calTargetPower5G,
-			AR5416_NUM_5G_20_TARGET_POWERS,
-			&targetPowerOfdm, 4, false);
-		ath9k_hw_get_target_powers(ah, chan,
-			pEepData->calTargetPower5GHT20,
-			AR5416_NUM_5G_20_TARGET_POWERS,
-			&targetPowerHt20, 8, false);
-
-		if (IS_CHAN_HT40(chan)) {
-			numCtlModes = ARRAY_SIZE(ctlModesFor11a);
-			ath9k_hw_get_target_powers(ah, chan,
-				pEepData->calTargetPower5GHT40,
-				AR5416_NUM_5G_40_TARGET_POWERS,
-				&targetPowerHt40, 8, true);
-			ath9k_hw_get_legacy_target_powers(ah, chan,
-				pEepData->calTargetPower5G,
-				AR5416_NUM_5G_20_TARGET_POWERS,
-				&targetPowerOfdmExt, 4, true);
-		}
-	}
-
-	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
-		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
-			(pCtlMode[ctlMode] == CTL_2GHT40);
-		if (isHt40CtlMode)
-			freq = centers.synth_center;
-		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
-			freq = centers.ext_center;
-		else
-			freq = centers.ctl_center;
-
-		if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
-		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
-			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
-
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
-			"EXT_ADDITIVE %d\n",
-			ctlMode, numCtlModes, isHt40CtlMode,
-			(pCtlMode[ctlMode] & EXT_ADDITIVE));
-
-		for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
-				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
-				"chan %d\n",
-				i, cfgCtl, pCtlMode[ctlMode],
-				pEepData->ctlIndex[i], chan->channel);
-
-			if ((((cfgCtl & ~CTL_MODE_M) |
-			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
-			     pEepData->ctlIndex[i]) ||
-			    (((cfgCtl & ~CTL_MODE_M) |
-			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
-			     ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
-				rep = &(pEepData->ctlData[i]);
-
-				twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
-				rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
-				IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
-
-				DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-					"    MATCH-EE_IDX %d: ch %d is2 %d "
-					"2xMinEdge %d chainmask %d chains %d\n",
-					i, freq, IS_CHAN_2GHZ(chan),
-					twiceMinEdgePower, tx_chainmask,
-					ar5416_get_ntxchains
-					(tx_chainmask));
-				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
-					twiceMaxEdgePower = min(twiceMaxEdgePower,
-								twiceMinEdgePower);
-				} else {
-					twiceMaxEdgePower = twiceMinEdgePower;
-					break;
-				}
-			}
-		}
-
-		minCtlPower = min(twiceMaxEdgePower, scaledPower);
-
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"    SEL-Min ctlMode %d pCtlMode %d "
-			"2xMaxEdge %d sP %d minCtlPwr %d\n",
-			ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
-			scaledPower, minCtlPower);
-
-		switch (pCtlMode[ctlMode]) {
-		case CTL_11B:
-			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
-				targetPowerCck.tPow2x[i] =
-					min((u16)targetPowerCck.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_11A:
-		case CTL_11G:
-			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
-				targetPowerOfdm.tPow2x[i] =
-					min((u16)targetPowerOfdm.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_5GHT20:
-		case CTL_2GHT20:
-			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
-				targetPowerHt20.tPow2x[i] =
-					min((u16)targetPowerHt20.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		case CTL_11B_EXT:
-			targetPowerCckExt.tPow2x[0] = min((u16)
-					targetPowerCckExt.tPow2x[0],
-					minCtlPower);
-			break;
-		case CTL_11A_EXT:
-		case CTL_11G_EXT:
-			targetPowerOfdmExt.tPow2x[0] = min((u16)
-					targetPowerOfdmExt.tPow2x[0],
-					minCtlPower);
-			break;
-		case CTL_5GHT40:
-		case CTL_2GHT40:
-			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
-				targetPowerHt40.tPow2x[i] =
-					min((u16)targetPowerHt40.tPow2x[i],
-					    minCtlPower);
-			}
-			break;
-		default:
-			break;
-		}
-	}
-
-	ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
-		ratesArray[rate18mb] = ratesArray[rate24mb] =
-		targetPowerOfdm.tPow2x[0];
-	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
-	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
-	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
-	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
-
-	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
-		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
-
-	if (IS_CHAN_2GHZ(chan)) {
-		ratesArray[rate1l] = targetPowerCck.tPow2x[0];
-		ratesArray[rate2s] = ratesArray[rate2l] =
-			targetPowerCck.tPow2x[1];
-		ratesArray[rate5_5s] = ratesArray[rate5_5l] =
-			targetPowerCck.tPow2x[2];
-		;
-		ratesArray[rate11s] = ratesArray[rate11l] =
-			targetPowerCck.tPow2x[3];
-		;
-	}
-	if (IS_CHAN_HT40(chan)) {
-		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
-			ratesArray[rateHt40_0 + i] =
-				targetPowerHt40.tPow2x[i];
-		}
-		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
-		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
-		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
-		if (IS_CHAN_2GHZ(chan)) {
-			ratesArray[rateExtCck] =
-				targetPowerCckExt.tPow2x[0];
-		}
-	}
-	return true;
-}
-
-static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
-				    struct ath9k_channel *chan,
-				    u16 cfgCtl,
-				    u8 twiceAntennaReduction,
-				    u8 twiceMaxRegulatoryPower,
-				    u8 powerLimit)
-{
-#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
-	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
-	struct modal_eep_header *pModal =
-		&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
-	int16_t ratesArray[Ar5416RateSize];
-	int16_t txPowerIndexOffset = 0;
-	u8 ht40PowerIncForPdadc = 2;
-	int i, cck_ofdm_delta = 0;
-
-	memset(ratesArray, 0, sizeof(ratesArray));
-
-	if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
-	    AR5416_EEP_MINOR_VER_2) {
-		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
-	}
-
-	if (!ath9k_hw_set_def_power_per_rate_table(ah, chan,
-					       &ratesArray[0], cfgCtl,
-					       twiceAntennaReduction,
-					       twiceMaxRegulatoryPower,
-					       powerLimit)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"ath9k_hw_set_txpower: unable to set "
-			"tx power per rate table\n");
-		return -EIO;
-	}
-
-	if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			 "ath9k_hw_set_txpower: unable to set power table\n");
-		return -EIO;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
-		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
-		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-			ratesArray[i] = AR5416_MAX_RATE_POWER;
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		for (i = 0; i < Ar5416RateSize; i++)
-			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
-		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
-		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
-		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
-		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
-		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
-		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
-		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
-		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
-
-	if (IS_CHAN_2GHZ(chan)) {
-		if (OLC_FOR_AR9280_20_LATER) {
-			cck_ofdm_delta = 2;
-			REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
-				ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
-				| ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
-				| ATH9K_POW_SM(ratesArray[rateXr], 8)
-				| ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
-			REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
-				ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
-				| ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
-				| ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
-				| ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
-		} else {
-			REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
-				ATH9K_POW_SM(ratesArray[rate2s], 24)
-				| ATH9K_POW_SM(ratesArray[rate2l], 16)
-				| ATH9K_POW_SM(ratesArray[rateXr], 8)
-				| ATH9K_POW_SM(ratesArray[rate1l], 0));
-			REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
-				ATH9K_POW_SM(ratesArray[rate11s], 24)
-				| ATH9K_POW_SM(ratesArray[rate11l], 16)
-				| ATH9K_POW_SM(ratesArray[rate5_5s], 8)
-				| ATH9K_POW_SM(ratesArray[rate5_5l], 0));
-		}
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
-		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
-	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
-		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
-		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
-
-	if (IS_CHAN_HT40(chan)) {
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
-			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
-				       ht40PowerIncForPdadc, 24)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
-					 ht40PowerIncForPdadc, 16)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
-					 ht40PowerIncForPdadc, 8)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
-					 ht40PowerIncForPdadc, 0));
-		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
-			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
-				       ht40PowerIncForPdadc, 24)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
-					 ht40PowerIncForPdadc, 16)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
-					 ht40PowerIncForPdadc, 8)
-			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
-					 ht40PowerIncForPdadc, 0));
-		if (OLC_FOR_AR9280_20_LATER) {
-			REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
-				ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
-				| ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
-				| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
-				| ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
-		} else {
-			REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
-				ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
-				| ATH9K_POW_SM(ratesArray[rateExtCck], 16)
-				| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
-				| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
-		}
-	}
-
-	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
-		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
-		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
-
-	i = rate6mb;
-
-	if (IS_CHAN_HT40(chan))
-		i = rateHt40_0;
-	else if (IS_CHAN_HT20(chan))
-		i = rateHt20_0;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		ah->regulatory.max_power_level =
-			ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
-	else
-		ah->regulatory.max_power_level = ratesArray[i];
-
-	switch(ar5416_get_ntxchains(ah->txchainmask)) {
-	case 1:
-		break;
-	case 2:
-		ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
-		break;
-	case 3:
-		ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"Invalid chainmask configuration\n");
-		break;
-	}
-
-	return 0;
-}
-
-static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
-					  enum ieee80211_band freq_band)
-{
-	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
-	struct modal_eep_header *pModal =
-		&(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
-	struct base_eep_header *pBase = &eep->baseEepHeader;
-	u8 num_ant_config;
-
-	num_ant_config = 1;
-
-	if (pBase->version >= 0x0E0D)
-		if (pModal->useAnt1)
-			num_ant_config += 1;
-
-	return num_ant_config;
-}
-
-static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
-					       struct ath9k_channel *chan)
-{
-	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
-	struct modal_eep_header *pModal =
-		&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
-	return pModal->antCtrlCommon & 0xFFFF;
-}
-
-static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
-{
-#define EEP_DEF_SPURCHAN \
-	(ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
-
-	u16 spur_val = AR_NO_SPUR;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-		"Getting spur idx %d is2Ghz. %d val %x\n",
-		i, is2GHz, ah->config.spurchans[i][is2GHz]);
-
-	switch (ah->config.spurmode) {
-	case SPUR_DISABLE:
-		break;
-	case SPUR_ENABLE_IOCTL:
-		spur_val = ah->config.spurchans[i][is2GHz];
-		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
-			"Getting spur val from new loc. %d\n", spur_val);
-		break;
-	case SPUR_ENABLE_EEPROM:
-		spur_val = EEP_DEF_SPURCHAN;
-		break;
-	}
-
-	return spur_val;
-
-#undef EEP_DEF_SPURCHAN
-}
-
-static struct eeprom_ops eep_def_ops = {
-	.check_eeprom		= ath9k_hw_def_check_eeprom,
-	.get_eeprom		= ath9k_hw_def_get_eeprom,
-	.fill_eeprom		= ath9k_hw_def_fill_eeprom,
-	.get_eeprom_ver		= ath9k_hw_def_get_eeprom_ver,
-	.get_eeprom_rev		= ath9k_hw_def_get_eeprom_rev,
-	.get_num_ant_config	= ath9k_hw_def_get_num_ant_config,
-	.get_eeprom_antenna_cfg	= ath9k_hw_def_get_eeprom_antenna_cfg,
-	.set_board_values	= ath9k_hw_def_set_board_values,
-	.set_addac		= ath9k_hw_def_set_addac,
-	.set_txpower		= ath9k_hw_def_set_txpower,
-	.get_spur_channel	= ath9k_hw_def_get_spur_channel
-};
-
-int ath9k_hw_eeprom_attach(struct ath_hw *ah)
-{
-	int status;
-
-	if (AR_SREV_9285(ah)) {
-		ah->eep_map = EEP_MAP_4KBITS;
-		ah->eep_ops = &eep_4k_ops;
-	} else {
-		ah->eep_map = EEP_MAP_DEFAULT;
-		ah->eep_ops = &eep_def_ops;
-	}
-
-	if (!ah->eep_ops->fill_eeprom(ah))
-		return -EIO;
-
-	status = ah->eep_ops->check_eeprom(ah);
-
-	return status;
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/eeprom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/eeprom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,507 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef EEPROM_H
-#define EEPROM_H
-
-#define AH_USE_EEPROM   0x1
-
-#ifdef __BIG_ENDIAN
-#define AR5416_EEPROM_MAGIC 0x5aa5
-#else
-#define AR5416_EEPROM_MAGIC 0xa55a
-#endif
-
-#define CTRY_DEBUG   0x1ff
-#define	CTRY_DEFAULT 0
-
-#define AR_EEPROM_EEPCAP_COMPRESS_DIS   0x0001
-#define AR_EEPROM_EEPCAP_AES_DIS        0x0002
-#define AR_EEPROM_EEPCAP_FASTFRAME_DIS  0x0004
-#define AR_EEPROM_EEPCAP_BURST_DIS      0x0008
-#define AR_EEPROM_EEPCAP_MAXQCU         0x01F0
-#define AR_EEPROM_EEPCAP_MAXQCU_S       4
-#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN  0x0200
-#define AR_EEPROM_EEPCAP_KC_ENTRIES     0xF000
-#define AR_EEPROM_EEPCAP_KC_ENTRIES_S   12
-
-#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND   0x0040
-#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN    0x0080
-#define AR_EEPROM_EEREGCAP_EN_KK_U2         0x0100
-#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND    0x0200
-#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD     0x0400
-#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A    0x0800
-
-#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0  0x4000
-#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000
-
-#define AR5416_EEPROM_MAGIC_OFFSET  0x0
-#define AR5416_EEPROM_S             2
-#define AR5416_EEPROM_OFFSET        0x2000
-#define AR5416_EEPROM_MAX           0xae0
-
-#define AR5416_EEPROM_START_ADDR \
-	(AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
-
-#define SD_NO_CTL               0xE0
-#define NO_CTL                  0xff
-#define CTL_MODE_M              7
-#define CTL_11A                 0
-#define CTL_11B                 1
-#define CTL_11G                 2
-#define CTL_2GHT20              5
-#define CTL_5GHT20              6
-#define CTL_2GHT40              7
-#define CTL_5GHT40              8
-
-#define EXT_ADDITIVE (0x8000)
-#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
-#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
-#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
-
-#define SUB_NUM_CTL_MODES_AT_5G_40 2
-#define SUB_NUM_CTL_MODES_AT_2G_40 3
-
-#define INCREASE_MAXPOW_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
-#define INCREASE_MAXPOW_BY_THREE_CHAIN   10 /* 10*log10(3)*2 */
-
-/*
- * For AR9285 and later chipsets, the following bits are not being programmed
- * in EEPROM and so need to be enabled always.
- *
- * Bit 0: en_fcc_mid
- * Bit 1: en_jap_mid
- * Bit 2: en_fcc_dfs_ht40
- * Bit 3: en_jap_ht40
- * Bit 4: en_jap_dfs_ht40
- */
-#define AR9285_RDEXT_DEFAULT    0x1F
-
-#define AR_EEPROM_MAC(i)	(0x1d+(i))
-#define ATH9K_POW_SM(_r, _s)	(((_r) & 0x3f) << (_s))
-#define FREQ2FBIN(x, y)		((y) ? ((x) - 2300) : (((x) - 4800) / 5))
-#define ath9k_hw_use_flash(_ah)	(!(_ah->ah_flags & AH_USE_EEPROM))
-
-#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
-#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
-				 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
-
-#define AR_EEPROM_RFSILENT_GPIO_SEL     0x001c
-#define AR_EEPROM_RFSILENT_GPIO_SEL_S   2
-#define AR_EEPROM_RFSILENT_POLARITY     0x0002
-#define AR_EEPROM_RFSILENT_POLARITY_S   1
-
-#define EEP_RFSILENT_ENABLED        0x0001
-#define EEP_RFSILENT_ENABLED_S      0
-#define EEP_RFSILENT_POLARITY       0x0002
-#define EEP_RFSILENT_POLARITY_S     1
-#define EEP_RFSILENT_GPIO_SEL       0x001c
-#define EEP_RFSILENT_GPIO_SEL_S     2
-
-#define AR5416_OPFLAGS_11A           0x01
-#define AR5416_OPFLAGS_11G           0x02
-#define AR5416_OPFLAGS_N_5G_HT40     0x04
-#define AR5416_OPFLAGS_N_2G_HT40     0x08
-#define AR5416_OPFLAGS_N_5G_HT20     0x10
-#define AR5416_OPFLAGS_N_2G_HT20     0x20
-
-#define AR5416_EEP_NO_BACK_VER       0x1
-#define AR5416_EEP_VER               0xE
-#define AR5416_EEP_VER_MINOR_MASK    0x0FFF
-#define AR5416_EEP_MINOR_VER_2       0x2
-#define AR5416_EEP_MINOR_VER_3       0x3
-#define AR5416_EEP_MINOR_VER_7       0x7
-#define AR5416_EEP_MINOR_VER_9       0x9
-#define AR5416_EEP_MINOR_VER_16      0x10
-#define AR5416_EEP_MINOR_VER_17      0x11
-#define AR5416_EEP_MINOR_VER_19      0x13
-#define AR5416_EEP_MINOR_VER_20      0x14
-#define AR5416_EEP_MINOR_VER_22      0x16
-
-#define AR5416_NUM_5G_CAL_PIERS         8
-#define AR5416_NUM_2G_CAL_PIERS         4
-#define AR5416_NUM_5G_20_TARGET_POWERS  8
-#define AR5416_NUM_5G_40_TARGET_POWERS  8
-#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
-#define AR5416_NUM_2G_20_TARGET_POWERS  4
-#define AR5416_NUM_2G_40_TARGET_POWERS  4
-#define AR5416_NUM_CTLS                 24
-#define AR5416_NUM_BAND_EDGES           8
-#define AR5416_NUM_PD_GAINS             4
-#define AR5416_PD_GAINS_IN_MASK         4
-#define AR5416_PD_GAIN_ICEPTS           5
-#define AR5416_EEPROM_MODAL_SPURS       5
-#define AR5416_MAX_RATE_POWER           63
-#define AR5416_NUM_PDADC_VALUES         128
-#define AR5416_BCHAN_UNUSED             0xFF
-#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
-#define AR5416_MAX_CHAINS               3
-#define AR5416_PWR_TABLE_OFFSET         -5
-
-/* Rx gain type values */
-#define AR5416_EEP_RXGAIN_23DB_BACKOFF     0
-#define AR5416_EEP_RXGAIN_13DB_BACKOFF     1
-#define AR5416_EEP_RXGAIN_ORIG             2
-
-/* Tx gain type values */
-#define AR5416_EEP_TXGAIN_ORIGINAL         0
-#define AR5416_EEP_TXGAIN_HIGH_POWER       1
-
-#define AR5416_EEP4K_START_LOC                64
-#define AR5416_EEP4K_NUM_2G_CAL_PIERS         3
-#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
-#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS  3
-#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS  3
-#define AR5416_EEP4K_NUM_CTLS                 12
-#define AR5416_EEP4K_NUM_BAND_EDGES           4
-#define AR5416_EEP4K_NUM_PD_GAINS             2
-#define AR5416_EEP4K_PD_GAINS_IN_MASK         4
-#define AR5416_EEP4K_PD_GAIN_ICEPTS           5
-#define AR5416_EEP4K_MAX_CHAINS               1
-
-#define AR9280_TX_GAIN_TABLE_SIZE 22
-
-enum eeprom_param {
-	EEP_NFTHRESH_5,
-	EEP_NFTHRESH_2,
-	EEP_MAC_MSW,
-	EEP_MAC_MID,
-	EEP_MAC_LSW,
-	EEP_REG_0,
-	EEP_REG_1,
-	EEP_OP_CAP,
-	EEP_OP_MODE,
-	EEP_RF_SILENT,
-	EEP_OB_5,
-	EEP_DB_5,
-	EEP_OB_2,
-	EEP_DB_2,
-	EEP_MINOR_REV,
-	EEP_TX_MASK,
-	EEP_RX_MASK,
-	EEP_RXGAIN_TYPE,
-	EEP_TXGAIN_TYPE,
-	EEP_OL_PWRCTRL,
-	EEP_RC_CHAIN_MASK,
-	EEP_DAC_HPWR_5G,
-	EEP_FRAC_N_5G
-};
-
-enum ar5416_rates {
-	rate6mb, rate9mb, rate12mb, rate18mb,
-	rate24mb, rate36mb, rate48mb, rate54mb,
-	rate1l, rate2l, rate2s, rate5_5l,
-	rate5_5s, rate11l, rate11s, rateXr,
-	rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
-	rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
-	rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
-	rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
-	rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
-	Ar5416RateSize
-};
-
-enum ath9k_hal_freq_band {
-	ATH9K_HAL_FREQ_BAND_5GHZ = 0,
-	ATH9K_HAL_FREQ_BAND_2GHZ = 1
-};
-
-struct base_eep_header {
-	u16 length;
-	u16 checksum;
-	u16 version;
-	u8 opCapFlags;
-	u8 eepMisc;
-	u16 regDmn[2];
-	u8 macAddr[6];
-	u8 rxMask;
-	u8 txMask;
-	u16 rfSilent;
-	u16 blueToothOptions;
-	u16 deviceCap;
-	u32 binBuildNumber;
-	u8 deviceType;
-	u8 pwdclkind;
-	u8 futureBase_1[2];
-	u8 rxGainType;
-	u8 dacHiPwrMode_5G;
-	u8 openLoopPwrCntl;
-	u8 dacLpMode;
-	u8 txGainType;
-	u8 rcChainMask;
-	u8 desiredScaleCCK;
-	u8 power_table_offset;
-	u8 frac_n_5g;
-	u8 futureBase_3[21];
-} __packed;
-
-struct base_eep_header_4k {
-	u16 length;
-	u16 checksum;
-	u16 version;
-	u8 opCapFlags;
-	u8 eepMisc;
-	u16 regDmn[2];
-	u8 macAddr[6];
-	u8 rxMask;
-	u8 txMask;
-	u16 rfSilent;
-	u16 blueToothOptions;
-	u16 deviceCap;
-	u32 binBuildNumber;
-	u8 deviceType;
-	u8 txGainType;
-} __packed;
-
-
-struct spur_chan {
-	u16 spurChan;
-	u8 spurRangeLow;
-	u8 spurRangeHigh;
-} __packed;
-
-struct modal_eep_header {
-	u32 antCtrlChain[AR5416_MAX_CHAINS];
-	u32 antCtrlCommon;
-	u8 antennaGainCh[AR5416_MAX_CHAINS];
-	u8 switchSettling;
-	u8 txRxAttenCh[AR5416_MAX_CHAINS];
-	u8 rxTxMarginCh[AR5416_MAX_CHAINS];
-	u8 adcDesiredSize;
-	u8 pgaDesiredSize;
-	u8 xlnaGainCh[AR5416_MAX_CHAINS];
-	u8 txEndToXpaOff;
-	u8 txEndToRxOn;
-	u8 txFrameToXpaOn;
-	u8 thresh62;
-	u8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
-	u8 xpdGain;
-	u8 xpd;
-	u8 iqCalICh[AR5416_MAX_CHAINS];
-	u8 iqCalQCh[AR5416_MAX_CHAINS];
-	u8 pdGainOverlap;
-	u8 ob;
-	u8 db;
-	u8 xpaBiasLvl;
-	u8 pwrDecreaseFor2Chain;
-	u8 pwrDecreaseFor3Chain;
-	u8 txFrameToDataStart;
-	u8 txFrameToPaOn;
-	u8 ht40PowerIncForPdadc;
-	u8 bswAtten[AR5416_MAX_CHAINS];
-	u8 bswMargin[AR5416_MAX_CHAINS];
-	u8 swSettleHt40;
-	u8 xatten2Db[AR5416_MAX_CHAINS];
-	u8 xatten2Margin[AR5416_MAX_CHAINS];
-	u8 ob_ch1;
-	u8 db_ch1;
-	u8 useAnt1:1,
-	    force_xpaon:1,
-	    local_bias:1,
-	    femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
-	u8 miscBits;
-	u16 xpaBiasLvlFreq[3];
-	u8 futureModal[6];
-
-	struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
-} __packed;
-
-struct calDataPerFreqOpLoop {
-	u8 pwrPdg[2][5];
-	u8 vpdPdg[2][5];
-	u8 pcdac[2][5];
-	u8 empty[2][5];
-} __packed;
-
-struct modal_eep_4k_header {
-	u32  antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
-	u32  antCtrlCommon;
-	u8   antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
-	u8   switchSettling;
-	u8   txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
-	u8   rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
-	u8   adcDesiredSize;
-	u8   pgaDesiredSize;
-	u8   xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
-	u8   txEndToXpaOff;
-	u8   txEndToRxOn;
-	u8   txFrameToXpaOn;
-	u8   thresh62;
-	u8   noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
-	u8   xpdGain;
-	u8   xpd;
-	u8   iqCalICh[AR5416_EEP4K_MAX_CHAINS];
-	u8   iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
-	u8   pdGainOverlap;
-	u8   ob_01;
-	u8   db1_01;
-	u8   xpaBiasLvl;
-	u8   txFrameToDataStart;
-	u8   txFrameToPaOn;
-	u8   ht40PowerIncForPdadc;
-	u8   bswAtten[AR5416_EEP4K_MAX_CHAINS];
-	u8   bswMargin[AR5416_EEP4K_MAX_CHAINS];
-	u8   swSettleHt40;
-	u8   xatten2Db[AR5416_EEP4K_MAX_CHAINS];
-	u8   xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
-	u8   db2_01;
-	u8   version;
-	u16  ob_234;
-	u16  db1_234;
-	u16  db2_234;
-	u8   futureModal[4];
-
-	struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
-} __packed;
-
-
-struct cal_data_per_freq {
-	u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
-	u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
-} __packed;
-
-struct cal_data_per_freq_4k {
-	u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
-	u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
-} __packed;
-
-struct cal_target_power_leg {
-	u8 bChannel;
-	u8 tPow2x[4];
-} __packed;
-
-struct cal_target_power_ht {
-	u8 bChannel;
-	u8 tPow2x[8];
-} __packed;
-
-
-#ifdef __BIG_ENDIAN_BITFIELD
-struct cal_ctl_edges {
-	u8 bChannel;
-	u8 flag:2, tPower:6;
-} __packed;
-#else
-struct cal_ctl_edges {
-	u8 bChannel;
-	u8 tPower:6, flag:2;
-} __packed;
-#endif
-
-struct cal_ctl_data {
-	struct cal_ctl_edges
-	ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
-} __packed;
-
-struct cal_ctl_data_4k {
-	struct cal_ctl_edges
-	ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
-} __packed;
-
-struct ar5416_eeprom_def {
-	struct base_eep_header baseEepHeader;
-	u8 custData[64];
-	struct modal_eep_header modalHeader[2];
-	u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
-	u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
-	struct cal_data_per_freq
-	 calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
-	struct cal_data_per_freq
-	 calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
-	struct cal_target_power_leg
-	 calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
-	struct cal_target_power_ht
-	 calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
-	struct cal_target_power_ht
-	 calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
-	struct cal_target_power_leg
-	 calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
-	struct cal_target_power_leg
-	 calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
-	struct cal_target_power_ht
-	 calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
-	struct cal_target_power_ht
-	 calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
-	u8 ctlIndex[AR5416_NUM_CTLS];
-	struct cal_ctl_data ctlData[AR5416_NUM_CTLS];
-	u8 padding;
-} __packed;
-
-struct ar5416_eeprom_4k {
-	struct base_eep_header_4k baseEepHeader;
-	u8 custData[20];
-	struct modal_eep_4k_header modalHeader;
-	u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
-	struct cal_data_per_freq_4k
-	calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
-	struct cal_target_power_leg
-	calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
-	struct cal_target_power_leg
-	calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
-	struct cal_target_power_ht
-	calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
-	struct cal_target_power_ht
-	calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
-	u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
-	struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
-	u8 padding;
-} __packed;
-
-enum reg_ext_bitmap {
-	REG_EXT_JAPAN_MIDBAND = 1,
-	REG_EXT_FCC_DFS_HT40 = 2,
-	REG_EXT_JAPAN_NONDFS_HT40 = 3,
-	REG_EXT_JAPAN_DFS_HT40 = 4
-};
-
-struct ath9k_country_entry {
-	u16 countryCode;
-	u16 regDmnEnum;
-	u16 regDmn5G;
-	u16 regDmn2G;
-	u8 isMultidomain;
-	u8 iso[3];
-};
-
-enum ath9k_eep_map {
-	EEP_MAP_DEFAULT = 0x0,
-	EEP_MAP_4KBITS,
-	EEP_MAP_MAX
-};
-
-struct eeprom_ops {
-	int (*check_eeprom)(struct ath_hw *hw);
-	u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
-	bool (*fill_eeprom)(struct ath_hw *hw);
-	int (*get_eeprom_ver)(struct ath_hw *hw);
-	int (*get_eeprom_rev)(struct ath_hw *hw);
-	u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band);
-	u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
-				      struct ath9k_channel *chan);
-	void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
-	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
-	int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
-			   u16 cfgCtl, u8 twiceAntennaReduction,
-			   u8 twiceMaxRegulatoryPower, u8 powerLimit);
-	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
-};
-
-#define ar5416_get_ntxchains(_txchainmask)			\
-	(((_txchainmask >> 2) & 1) +                            \
-	 ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
-
-int ath9k_hw_eeprom_attach(struct ath_hw *ah);
-
-#endif /* EEPROM_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/hw.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/hw.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/hw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/hw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3898 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/io.h>
-#include <asm/unaligned.h>
-
-#include "ath9k.h"
-#include "initvals.h"
-
-static int btcoex_enable;
-module_param(btcoex_enable, bool, 0);
-MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support");
-
-#define ATH9K_CLOCK_RATE_CCK		22
-#define ATH9K_CLOCK_RATE_5GHZ_OFDM	40
-#define ATH9K_CLOCK_RATE_2GHZ_OFDM	44
-
-static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
-static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
-			      enum ath9k_ht_macmode macmode);
-static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
-			      struct ar5416_eeprom_def *pEepData,
-			      u32 reg, u32 value);
-static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
-static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
-
-/********************/
-/* Helper Functions */
-/********************/
-
-static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-
-	if (!ah->curchan) /* should really check for CCK instead */
-		return clks / ATH9K_CLOCK_RATE_CCK;
-	if (conf->channel->band == IEEE80211_BAND_2GHZ)
-		return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
-
-	return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
-}
-
-static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-
-	if (conf_is_ht40(conf))
-		return ath9k_hw_mac_usec(ah, clks) / 2;
-	else
-		return ath9k_hw_mac_usec(ah, clks);
-}
-
-static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-
-	if (!ah->curchan) /* should really check for CCK instead */
-		return usecs *ATH9K_CLOCK_RATE_CCK;
-	if (conf->channel->band == IEEE80211_BAND_2GHZ)
-		return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
-	return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM;
-}
-
-static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
-{
-	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-
-	if (conf_is_ht40(conf))
-		return ath9k_hw_mac_clks(ah, usecs) * 2;
-	else
-		return ath9k_hw_mac_clks(ah, usecs);
-}
-
-bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
-{
-	int i;
-
-	BUG_ON(timeout < AH_TIME_QUANTUM);
-
-	for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) {
-		if ((REG_READ(ah, reg) & mask) == val)
-			return true;
-
-		udelay(AH_TIME_QUANTUM);
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-		"timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
-		timeout, reg, REG_READ(ah, reg), mask, val);
-
-	return false;
-}
-
-u32 ath9k_hw_reverse_bits(u32 val, u32 n)
-{
-	u32 retval;
-	int i;
-
-	for (i = 0, retval = 0; i < n; i++) {
-		retval = (retval << 1) | (val & 1);
-		val >>= 1;
-	}
-	return retval;
-}
-
-bool ath9k_get_channel_edges(struct ath_hw *ah,
-			     u16 flags, u16 *low,
-			     u16 *high)
-{
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-
-	if (flags & CHANNEL_5GHZ) {
-		*low = pCap->low_5ghz_chan;
-		*high = pCap->high_5ghz_chan;
-		return true;
-	}
-	if ((flags & CHANNEL_2GHZ)) {
-		*low = pCap->low_2ghz_chan;
-		*high = pCap->high_2ghz_chan;
-		return true;
-	}
-	return false;
-}
-
-u16 ath9k_hw_computetxtime(struct ath_hw *ah,
-			   struct ath_rate_table *rates,
-			   u32 frameLen, u16 rateix,
-			   bool shortPreamble)
-{
-	u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
-	u32 kbps;
-
-	kbps = rates->info[rateix].ratekbps;
-
-	if (kbps == 0)
-		return 0;
-
-	switch (rates->info[rateix].phy) {
-	case WLAN_RC_PHY_CCK:
-		phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
-		if (shortPreamble && rates->info[rateix].short_preamble)
-			phyTime >>= 1;
-		numBits = frameLen << 3;
-		txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
-		break;
-	case WLAN_RC_PHY_OFDM:
-		if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) {
-			bitsPerSymbol =	(kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
-			numBits = OFDM_PLCP_BITS + (frameLen << 3);
-			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
-			txTime = OFDM_SIFS_TIME_QUARTER
-				+ OFDM_PREAMBLE_TIME_QUARTER
-				+ (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
-		} else if (ah->curchan &&
-			   IS_CHAN_HALF_RATE(ah->curchan)) {
-			bitsPerSymbol =	(kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
-			numBits = OFDM_PLCP_BITS + (frameLen << 3);
-			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
-			txTime = OFDM_SIFS_TIME_HALF +
-				OFDM_PREAMBLE_TIME_HALF
-				+ (numSymbols * OFDM_SYMBOL_TIME_HALF);
-		} else {
-			bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
-			numBits = OFDM_PLCP_BITS + (frameLen << 3);
-			numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
-			txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
-				+ (numSymbols * OFDM_SYMBOL_TIME);
-		}
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			"Unknown phy %u (rate ix %u)\n",
-			rates->info[rateix].phy, rateix);
-		txTime = 0;
-		break;
-	}
-
-	return txTime;
-}
-
-void ath9k_hw_get_channel_centers(struct ath_hw *ah,
-				  struct ath9k_channel *chan,
-				  struct chan_centers *centers)
-{
-	int8_t extoff;
-
-	if (!IS_CHAN_HT40(chan)) {
-		centers->ctl_center = centers->ext_center =
-			centers->synth_center = chan->channel;
-		return;
-	}
-
-	if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
-	    (chan->chanmode == CHANNEL_G_HT40PLUS)) {
-		centers->synth_center =
-			chan->channel + HT40_CHANNEL_CENTER_SHIFT;
-		extoff = 1;
-	} else {
-		centers->synth_center =
-			chan->channel - HT40_CHANNEL_CENTER_SHIFT;
-		extoff = -1;
-	}
-
-	centers->ctl_center =
-		centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
-	centers->ext_center =
-		centers->synth_center + (extoff *
-			 ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ?
-			  HT40_CHANNEL_CENTER_SHIFT : 15));
-}
-
-/******************/
-/* Chip Revisions */
-/******************/
-
-static void ath9k_hw_read_revisions(struct ath_hw *ah)
-{
-	u32 val;
-
-	val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
-
-	if (val == 0xFF) {
-		val = REG_READ(ah, AR_SREV);
-		ah->hw_version.macVersion =
-			(val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
-		ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
-		ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
-	} else {
-		if (!AR_SREV_9100(ah))
-			ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
-
-		ah->hw_version.macRev = val & AR_SREV_REVISION;
-
-		if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)
-			ah->is_pciexpress = true;
-	}
-}
-
-static int ath9k_hw_get_radiorev(struct ath_hw *ah)
-{
-	u32 val;
-	int i;
-
-	REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
-
-	for (i = 0; i < 8; i++)
-		REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
-	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
-	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
-
-	return ath9k_hw_reverse_bits(val, 8);
-}
-
-/************************************/
-/* HW Attach, Detach, Init Routines */
-/************************************/
-
-static void ath9k_hw_disablepcie(struct ath_hw *ah)
-{
-	if (AR_SREV_9100(ah))
-		return;
-
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-	REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
-
-	REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-}
-
-static bool ath9k_hw_chip_test(struct ath_hw *ah)
-{
-	u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
-	u32 regHold[2];
-	u32 patternData[4] = { 0x55555555,
-			       0xaaaaaaaa,
-			       0x66666666,
-			       0x99999999 };
-	int i, j;
-
-	for (i = 0; i < 2; i++) {
-		u32 addr = regAddr[i];
-		u32 wrData, rdData;
-
-		regHold[i] = REG_READ(ah, addr);
-		for (j = 0; j < 0x100; j++) {
-			wrData = (j << 16) | j;
-			REG_WRITE(ah, addr, wrData);
-			rdData = REG_READ(ah, addr);
-			if (rdData != wrData) {
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-					"address test failed "
-					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
-					addr, wrData, rdData);
-				return false;
-			}
-		}
-		for (j = 0; j < 4; j++) {
-			wrData = patternData[j];
-			REG_WRITE(ah, addr, wrData);
-			rdData = REG_READ(ah, addr);
-			if (wrData != rdData) {
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-					"address test failed "
-					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
-					addr, wrData, rdData);
-				return false;
-			}
-		}
-		REG_WRITE(ah, regAddr[i], regHold[i]);
-	}
-	udelay(100);
-
-	return true;
-}
-
-static const char *ath9k_hw_devname(u16 devid)
-{
-	switch (devid) {
-	case AR5416_DEVID_PCI:
-		return "Atheros 5416";
-	case AR5416_DEVID_PCIE:
-		return "Atheros 5418";
-	case AR9160_DEVID_PCI:
-		return "Atheros 9160";
-	case AR5416_AR9100_DEVID:
-		return "Atheros 9100";
-	case AR9280_DEVID_PCI:
-	case AR9280_DEVID_PCIE:
-		return "Atheros 9280";
-	case AR9285_DEVID_PCIE:
-		return "Atheros 9285";
-	}
-
-	return NULL;
-}
-
-static void ath9k_hw_set_defaults(struct ath_hw *ah)
-{
-	int i;
-
-	ah->config.dma_beacon_response_time = 2;
-	ah->config.sw_beacon_response_time = 10;
-	ah->config.additional_swba_backoff = 0;
-	ah->config.ack_6mb = 0x0;
-	ah->config.cwm_ignore_extcca = 0;
-	ah->config.pcie_powersave_enable = 0;
-	ah->config.pcie_l1skp_enable = 0;
-	ah->config.pcie_clock_req = 0;
-	ah->config.pcie_power_reset = 0x100;
-	ah->config.pcie_restore = 0;
-	ah->config.pcie_waen = 0;
-	ah->config.analog_shiftreg = 1;
-	ah->config.ht_enable = 1;
-	ah->config.ofdm_trig_low = 200;
-	ah->config.ofdm_trig_high = 500;
-	ah->config.cck_trig_high = 200;
-	ah->config.cck_trig_low = 100;
-	ah->config.enable_ani = 1;
-	ah->config.noise_immunity_level = 4;
-	ah->config.ofdm_weaksignal_det = 1;
-	ah->config.cck_weaksignal_thr = 0;
-	ah->config.spur_immunity_level = 2;
-	ah->config.firstep_level = 0;
-	ah->config.rssi_thr_high = 40;
-	ah->config.rssi_thr_low = 7;
-	ah->config.diversity_control = 0;
-	ah->config.antenna_switch_swap = 0;
-
-	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
-		ah->config.spurchans[i][0] = AR_NO_SPUR;
-		ah->config.spurchans[i][1] = AR_NO_SPUR;
-	}
-
-	ah->config.intr_mitigation = 1;
-
-	/*
-	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
-	 * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
-	 * This means we use it for all AR5416 devices, and the few
-	 * minor PCI AR9280 devices out there.
-	 *
-	 * Serialization is required because these devices do not handle
-	 * well the case of two concurrent reads/writes due to the latency
-	 * involved. During one read/write another read/write can be issued
-	 * on another CPU while the previous read/write may still be working
-	 * on our hardware, if we hit this case the hardware poops in a loop.
-	 * We prevent this by serializing reads and writes.
-	 *
-	 * This issue is not present on PCI-Express devices or pre-AR5416
-	 * devices (legacy, 802.11abg).
-	 */
-	if (num_possible_cpus() > 1)
-		ah->config.serialize_regmode = SER_REG_MODE_AUTO;
-}
-
-static struct ath_hw *ath9k_hw_newstate(u16 devid, struct ath_softc *sc,
-					int *status)
-{
-	struct ath_hw *ah;
-
-	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
-	if (ah == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Cannot allocate memory for state block\n");
-		*status = -ENOMEM;
-		return NULL;
-	}
-
-	ah->ah_sc = sc;
-	ah->hw_version.magic = AR5416_MAGIC;
-	ah->regulatory.country_code = CTRY_DEFAULT;
-	ah->hw_version.devid = devid;
-	ah->hw_version.subvendorid = 0;
-
-	ah->ah_flags = 0;
-	if ((devid == AR5416_AR9100_DEVID))
-		ah->hw_version.macVersion = AR_SREV_VERSION_9100;
-	if (!AR_SREV_9100(ah))
-		ah->ah_flags = AH_USE_EEPROM;
-
-	ah->regulatory.power_limit = MAX_RATE_POWER;
-	ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
-	ah->atim_window = 0;
-	ah->diversity_control = ah->config.diversity_control;
-	ah->antenna_switch_swap =
-		ah->config.antenna_switch_swap;
-	ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
-	ah->beacon_interval = 100;
-	ah->enable_32kHz_clock = DONT_USE_32KHZ;
-	ah->slottime = (u32) -1;
-	ah->acktimeout = (u32) -1;
-	ah->ctstimeout = (u32) -1;
-	ah->globaltxtimeout = (u32) -1;
-
-	ah->gbeacon_rate = 0;
-
-	return ah;
-}
-
-static int ath9k_hw_rfattach(struct ath_hw *ah)
-{
-	bool rfStatus = false;
-	int ecode = 0;
-
-	rfStatus = ath9k_hw_init_rf(ah, &ecode);
-	if (!rfStatus) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			"RF setup failed, status %u\n", ecode);
-		return ecode;
-	}
-
-	return 0;
-}
-
-static int ath9k_hw_rf_claim(struct ath_hw *ah)
-{
-	u32 val;
-
-	REG_WRITE(ah, AR_PHY(0), 0x00000007);
-
-	val = ath9k_hw_get_radiorev(ah);
-	switch (val & AR_RADIO_SREV_MAJOR) {
-	case 0:
-		val = AR_RAD5133_SREV_MAJOR;
-		break;
-	case AR_RAD5133_SREV_MAJOR:
-	case AR_RAD5122_SREV_MAJOR:
-	case AR_RAD2133_SREV_MAJOR:
-	case AR_RAD2122_SREV_MAJOR:
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			"5G Radio Chip Rev 0x%02X is not "
-			"supported by this driver\n",
-			ah->hw_version.analog5GhzRev);
-		return -EOPNOTSUPP;
-	}
-
-	ah->hw_version.analog5GhzRev = val;
-
-	return 0;
-}
-
-static int ath9k_hw_init_macaddr(struct ath_hw *ah)
-{
-	u32 sum;
-	int i;
-	u16 eeval;
-
-	sum = 0;
-	for (i = 0; i < 3; i++) {
-		eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i));
-		sum += eeval;
-		ah->macaddr[2 * i] = eeval >> 8;
-		ah->macaddr[2 * i + 1] = eeval & 0xff;
-	}
-	if (sum == 0 || sum == 0xffff * 3) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"mac address read failed: %pM\n",
-			ah->macaddr);
-		return -EADDRNOTAVAIL;
-	}
-
-	return 0;
-}
-
-static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah)
-{
-	u32 rxgain_type;
-
-	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
-		rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
-
-		if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-			ar9280Modes_backoff_13db_rxgain_9280_2,
-			ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
-		else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-			ar9280Modes_backoff_23db_rxgain_9280_2,
-			ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
-		else
-			INIT_INI_ARRAY(&ah->iniModesRxGain,
-			ar9280Modes_original_rxgain_9280_2,
-			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
-	} else {
-		INIT_INI_ARRAY(&ah->iniModesRxGain,
-			ar9280Modes_original_rxgain_9280_2,
-			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
-	}
-}
-
-static void ath9k_hw_init_txgain_ini(struct ath_hw *ah)
-{
-	u32 txgain_type;
-
-	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
-		txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-
-		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-			ar9280Modes_high_power_tx_gain_9280_2,
-			ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
-		else
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-			ar9280Modes_original_tx_gain_9280_2,
-			ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
-	} else {
-		INIT_INI_ARRAY(&ah->iniModesTxGain,
-		ar9280Modes_original_tx_gain_9280_2,
-		ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
-	}
-}
-
-static int ath9k_hw_post_attach(struct ath_hw *ah)
-{
-	int ecode;
-
-	if (!ath9k_hw_chip_test(ah)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			"hardware self-test failed\n");
-		return -ENODEV;
-	}
-
-	ecode = ath9k_hw_rf_claim(ah);
-	if (ecode != 0)
-		return ecode;
-
-	ecode = ath9k_hw_eeprom_attach(ah);
-	if (ecode != 0)
-		return ecode;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n",
-		ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah));
-
-	ecode = ath9k_hw_rfattach(ah);
-	if (ecode != 0)
-		return ecode;
-
-	if (!AR_SREV_9100(ah)) {
-		ath9k_hw_ani_setup(ah);
-		ath9k_hw_ani_attach(ah);
-	}
-
-	return 0;
-}
-
-static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
-					 int *status)
-{
-	struct ath_hw *ah;
-	int ecode;
-	u32 i, j;
-
-	ah = ath9k_hw_newstate(devid, sc, status);
-	if (ah == NULL)
-		return NULL;
-
-	ath9k_hw_set_defaults(ah);
-
-	if (ah->config.intr_mitigation != 0)
-		ah->intr_mitigation = true;
-
-	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
-		DPRINTF(sc, ATH_DBG_RESET, "Couldn't reset chip\n");
-		ecode = -EIO;
-		goto bad;
-	}
-
-	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
-		DPRINTF(sc, ATH_DBG_RESET, "Couldn't wakeup chip\n");
-		ecode = -EIO;
-		goto bad;
-	}
-
-	if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
-		if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
-		    (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
-			ah->config.serialize_regmode =
-				SER_REG_MODE_ON;
-		} else {
-			ah->config.serialize_regmode =
-				SER_REG_MODE_OFF;
-		}
-	}
-
-	DPRINTF(sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
-		ah->config.serialize_regmode);
-
-	if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) &&
-	    (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
-	    (ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
-	    (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
-		DPRINTF(sc, ATH_DBG_RESET,
-			"Mac Chip Rev 0x%02x.%x is not supported by "
-			"this driver\n", ah->hw_version.macVersion,
-			ah->hw_version.macRev);
-		ecode = -EOPNOTSUPP;
-		goto bad;
-	}
-
-	if (AR_SREV_9100(ah)) {
-		ah->iq_caldata.calData = &iq_cal_multi_sample;
-		ah->supp_cals = IQ_MISMATCH_CAL;
-		ah->is_pciexpress = false;
-	}
-	ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
-
-	if (AR_SREV_9160_10_OR_LATER(ah)) {
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
-			ah->iq_caldata.calData = &iq_cal_single_sample;
-			ah->adcgain_caldata.calData =
-				&adc_gain_cal_single_sample;
-			ah->adcdc_caldata.calData =
-				&adc_dc_cal_single_sample;
-			ah->adcdc_calinitdata.calData =
-				&adc_init_dc_cal;
-		} else {
-			ah->iq_caldata.calData = &iq_cal_multi_sample;
-			ah->adcgain_caldata.calData =
-				&adc_gain_cal_multi_sample;
-			ah->adcdc_caldata.calData =
-				&adc_dc_cal_multi_sample;
-			ah->adcdc_calinitdata.calData =
-				&adc_init_dc_cal;
-		}
-		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
-	}
-
-	ah->ani_function = ATH9K_ANI_ALL;
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
-
-	DPRINTF(sc, ATH_DBG_RESET,
-		"This Mac Chip Rev 0x%02x.%x is \n",
-		ah->hw_version.macVersion, ah->hw_version.macRev);
-
-	if (AR_SREV_9285_12_OR_LATER(ah)) {
-
-		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
-			       ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
-		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
-			       ARRAY_SIZE(ar9285Common_9285_1_2), 2);
-
-		if (ah->config.pcie_clock_req) {
-			INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			ar9285PciePhy_clkreq_off_L1_9285_1_2,
-			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
-		} else {
-			INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
-			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
-				  2);
-		}
-	} else if (AR_SREV_9285_10_OR_LATER(ah)) {
-		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285,
-			       ARRAY_SIZE(ar9285Modes_9285), 6);
-		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285,
-			       ARRAY_SIZE(ar9285Common_9285), 2);
-
-		if (ah->config.pcie_clock_req) {
-			INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			ar9285PciePhy_clkreq_off_L1_9285,
-			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
-		} else {
-			INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			ar9285PciePhy_clkreq_always_on_L1_9285,
-			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
-		}
-	} else if (AR_SREV_9280_20_OR_LATER(ah)) {
-		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
-			       ARRAY_SIZE(ar9280Modes_9280_2), 6);
-		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
-			       ARRAY_SIZE(ar9280Common_9280_2), 2);
-
-		if (ah->config.pcie_clock_req) {
-			INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			       ar9280PciePhy_clkreq_off_L1_9280,
-			       ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2);
-		} else {
-			INIT_INI_ARRAY(&ah->iniPcieSerdes,
-			       ar9280PciePhy_clkreq_always_on_L1_9280,
-			       ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
-		}
-		INIT_INI_ARRAY(&ah->iniModesAdditional,
-			       ar9280Modes_fast_clock_9280_2,
-			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
-	} else if (AR_SREV_9280_10_OR_LATER(ah)) {
-		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280,
-			       ARRAY_SIZE(ar9280Modes_9280), 6);
-		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280,
-			       ARRAY_SIZE(ar9280Common_9280), 2);
-	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
-		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
-			       ARRAY_SIZE(ar5416Modes_9160), 6);
-		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
-			       ARRAY_SIZE(ar5416Common_9160), 2);
-		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
-			       ARRAY_SIZE(ar5416Bank0_9160), 2);
-		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
-			       ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
-		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
-			       ARRAY_SIZE(ar5416Bank1_9160), 2);
-		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
-			       ARRAY_SIZE(ar5416Bank2_9160), 2);
-		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
-			       ARRAY_SIZE(ar5416Bank3_9160), 3);
-		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
-			       ARRAY_SIZE(ar5416Bank6_9160), 3);
-		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
-			       ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
-		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
-			       ARRAY_SIZE(ar5416Bank7_9160), 2);
-		if (AR_SREV_9160_11(ah)) {
-			INIT_INI_ARRAY(&ah->iniAddac,
-				       ar5416Addac_91601_1,
-				       ARRAY_SIZE(ar5416Addac_91601_1), 2);
-		} else {
-			INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
-				       ARRAY_SIZE(ar5416Addac_9160), 2);
-		}
-	} else if (AR_SREV_9100_OR_LATER(ah)) {
-		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
-			       ARRAY_SIZE(ar5416Modes_9100), 6);
-		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
-			       ARRAY_SIZE(ar5416Common_9100), 2);
-		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
-			       ARRAY_SIZE(ar5416Bank0_9100), 2);
-		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
-			       ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
-		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
-			       ARRAY_SIZE(ar5416Bank1_9100), 2);
-		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
-			       ARRAY_SIZE(ar5416Bank2_9100), 2);
-		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
-			       ARRAY_SIZE(ar5416Bank3_9100), 3);
-		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
-			       ARRAY_SIZE(ar5416Bank6_9100), 3);
-		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
-			       ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
-		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
-			       ARRAY_SIZE(ar5416Bank7_9100), 2);
-		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
-			       ARRAY_SIZE(ar5416Addac_9100), 2);
-	} else {
-		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
-			       ARRAY_SIZE(ar5416Modes), 6);
-		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
-			       ARRAY_SIZE(ar5416Common), 2);
-		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
-			       ARRAY_SIZE(ar5416Bank0), 2);
-		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
-			       ARRAY_SIZE(ar5416BB_RfGain), 3);
-		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
-			       ARRAY_SIZE(ar5416Bank1), 2);
-		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
-			       ARRAY_SIZE(ar5416Bank2), 2);
-		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
-			       ARRAY_SIZE(ar5416Bank3), 3);
-		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
-			       ARRAY_SIZE(ar5416Bank6), 3);
-		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
-			       ARRAY_SIZE(ar5416Bank6TPC), 3);
-		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
-			       ARRAY_SIZE(ar5416Bank7), 2);
-		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
-			       ARRAY_SIZE(ar5416Addac), 2);
-	}
-
-	if (ah->is_pciexpress)
-		ath9k_hw_configpcipowersave(ah, 0);
-	else
-		ath9k_hw_disablepcie(ah);
-
-	ecode = ath9k_hw_post_attach(ah);
-	if (ecode != 0)
-		goto bad;
-
-	if (AR_SREV_9285_12_OR_LATER(ah)) {
-		u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-
-		/* txgain table */
-		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-			ar9285Modes_high_power_tx_gain_9285_1_2,
-			ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6);
-		} else {
-			INIT_INI_ARRAY(&ah->iniModesTxGain,
-			ar9285Modes_original_tx_gain_9285_1_2,
-			ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6);
-		}
-
-	}
-
-	/* rxgain table */
-	if (AR_SREV_9280_20(ah))
-		ath9k_hw_init_rxgain_ini(ah);
-
-	/* txgain table */
-	if (AR_SREV_9280_20(ah))
-		ath9k_hw_init_txgain_ini(ah);
-
-	if (!ath9k_hw_fill_cap_info(ah)) {
-		DPRINTF(sc, ATH_DBG_RESET, "failed ath9k_hw_fill_cap_info\n");
-		ecode = -EINVAL;
-		goto bad;
-	}
-
-	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
-	    test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
-
-		/* EEPROM Fixup */
-		for (i = 0; i < ah->iniModes.ia_rows; i++) {
-			u32 reg = INI_RA(&ah->iniModes, i, 0);
-
-			for (j = 1; j < ah->iniModes.ia_columns; j++) {
-				u32 val = INI_RA(&ah->iniModes, i, j);
-
-				INI_RA(&ah->iniModes, i, j) =
-					ath9k_hw_ini_fixup(ah,
-							   &ah->eeprom.def,
-							   reg, val);
-			}
-		}
-	}
-
-	ecode = ath9k_hw_init_macaddr(ah);
-	if (ecode != 0) {
-		DPRINTF(sc, ATH_DBG_RESET,
-			"failed initializing mac address\n");
-		goto bad;
-	}
-
-	if (AR_SREV_9285(ah))
-		ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S);
-	else
-		ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
-
-	ath9k_init_nfcal_hist_buffer(ah);
-
-	return ah;
-bad:
-	if (ah)
-		ath9k_hw_detach(ah);
-	if (status)
-		*status = ecode;
-
-	return NULL;
-}
-
-static void ath9k_hw_init_bb(struct ath_hw *ah,
-			     struct ath9k_channel *chan)
-{
-	u32 synthDelay;
-
-	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-	if (IS_CHAN_B(chan))
-		synthDelay = (4 * synthDelay) / 22;
-	else
-		synthDelay /= 10;
-
-	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-
-	udelay(synthDelay + BASE_ACTIVATE_DELAY);
-}
-
-static void ath9k_hw_init_qos(struct ath_hw *ah)
-{
-	REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
-	REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
-
-	REG_WRITE(ah, AR_QOS_NO_ACK,
-		  SM(2, AR_QOS_NO_ACK_TWO_BIT) |
-		  SM(5, AR_QOS_NO_ACK_BIT_OFF) |
-		  SM(0, AR_QOS_NO_ACK_BYTE_OFF));
-
-	REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
-	REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
-	REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
-	REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
-	REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
-}
-
-static void ath9k_hw_init_pll(struct ath_hw *ah,
-			      struct ath9k_channel *chan)
-{
-	u32 pll;
-
-	if (AR_SREV_9100(ah)) {
-		if (chan && IS_CHAN_5GHZ(chan))
-			pll = 0x1450;
-		else
-			pll = 0x1458;
-	} else {
-		if (AR_SREV_9280_10_OR_LATER(ah)) {
-			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
-			if (chan && IS_CHAN_HALF_RATE(chan))
-				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-			else if (chan && IS_CHAN_QUARTER_RATE(chan))
-				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
-			if (chan && IS_CHAN_5GHZ(chan)) {
-				pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-
-
-				if (AR_SREV_9280_20(ah)) {
-					if (((chan->channel % 20) == 0)
-					    || ((chan->channel % 10) == 0))
-						pll = 0x2850;
-					else
-						pll = 0x142c;
-				}
-			} else {
-				pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
-			}
-
-		} else if (AR_SREV_9160_10_OR_LATER(ah)) {
-
-			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
-			if (chan && IS_CHAN_HALF_RATE(chan))
-				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-			else if (chan && IS_CHAN_QUARTER_RATE(chan))
-				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
-			if (chan && IS_CHAN_5GHZ(chan))
-				pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
-			else
-				pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
-		} else {
-			pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
-
-			if (chan && IS_CHAN_HALF_RATE(chan))
-				pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
-			else if (chan && IS_CHAN_QUARTER_RATE(chan))
-				pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
-
-			if (chan && IS_CHAN_5GHZ(chan))
-				pll |= SM(0xa, AR_RTC_PLL_DIV);
-			else
-				pll |= SM(0xb, AR_RTC_PLL_DIV);
-		}
-	}
-	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
-
-	udelay(RTC_PLL_SETTLE_DELAY);
-
-	REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
-}
-
-static void ath9k_hw_init_chain_masks(struct ath_hw *ah)
-{
-	int rx_chainmask, tx_chainmask;
-
-	rx_chainmask = ah->rxchainmask;
-	tx_chainmask = ah->txchainmask;
-
-	switch (rx_chainmask) {
-	case 0x5:
-		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-			    AR_PHY_SWAP_ALT_CHAIN);
-	case 0x3:
-		if (((ah)->hw_version.macVersion <= AR_SREV_VERSION_9160)) {
-			REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
-			REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
-			break;
-		}
-	case 0x1:
-	case 0x2:
-	case 0x7:
-		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
-		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
-		break;
-	default:
-		break;
-	}
-
-	REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
-	if (tx_chainmask == 0x5) {
-		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-			    AR_PHY_SWAP_ALT_CHAIN);
-	}
-	if (AR_SREV_9100(ah))
-		REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
-			  REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
-}
-
-static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
-					  enum nl80211_iftype opmode)
-{
-	ah->mask_reg = AR_IMR_TXERR |
-		AR_IMR_TXURN |
-		AR_IMR_RXERR |
-		AR_IMR_RXORN |
-		AR_IMR_BCNMISC;
-
-	if (ah->intr_mitigation)
-		ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
-	else
-		ah->mask_reg |= AR_IMR_RXOK;
-
-	ah->mask_reg |= AR_IMR_TXOK;
-
-	if (opmode == NL80211_IFTYPE_AP)
-		ah->mask_reg |= AR_IMR_MIB;
-
-	REG_WRITE(ah, AR_IMR, ah->mask_reg);
-	REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
-
-	if (!AR_SREV_9100(ah)) {
-		REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
-		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
-		REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
-	}
-}
-
-static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
-{
-	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us);
-		ah->acktimeout = (u32) -1;
-		return false;
-	} else {
-		REG_RMW_FIELD(ah, AR_TIME_OUT,
-			      AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
-		ah->acktimeout = us;
-		return true;
-	}
-}
-
-static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
-{
-	if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us);
-		ah->ctstimeout = (u32) -1;
-		return false;
-	} else {
-		REG_RMW_FIELD(ah, AR_TIME_OUT,
-			      AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
-		ah->ctstimeout = us;
-		return true;
-	}
-}
-
-static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
-{
-	if (tu > 0xFFFF) {
-		DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
-			"bad global tx timeout %u\n", tu);
-		ah->globaltxtimeout = (u32) -1;
-		return false;
-	} else {
-		REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
-		ah->globaltxtimeout = tu;
-		return true;
-	}
-}
-
-static void ath9k_hw_init_user_settings(struct ath_hw *ah)
-{
-	DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
-		ah->misc_mode);
-
-	if (ah->misc_mode != 0)
-		REG_WRITE(ah, AR_PCU_MISC,
-			  REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
-	if (ah->slottime != (u32) -1)
-		ath9k_hw_setslottime(ah, ah->slottime);
-	if (ah->acktimeout != (u32) -1)
-		ath9k_hw_set_ack_timeout(ah, ah->acktimeout);
-	if (ah->ctstimeout != (u32) -1)
-		ath9k_hw_set_cts_timeout(ah, ah->ctstimeout);
-	if (ah->globaltxtimeout != (u32) -1)
-		ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
-}
-
-const char *ath9k_hw_probe(u16 vendorid, u16 devid)
-{
-	return vendorid == ATHEROS_VENDOR_ID ?
-		ath9k_hw_devname(devid) : NULL;
-}
-
-void ath9k_hw_detach(struct ath_hw *ah)
-{
-	if (!AR_SREV_9100(ah))
-		ath9k_hw_ani_detach(ah);
-
-	ath9k_hw_rfdetach(ah);
-	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
-	kfree(ah);
-}
-
-struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error)
-{
-	struct ath_hw *ah = NULL;
-
-	switch (devid) {
-	case AR5416_DEVID_PCI:
-	case AR5416_DEVID_PCIE:
-	case AR5416_AR9100_DEVID:
-	case AR9160_DEVID_PCI:
-	case AR9280_DEVID_PCI:
-	case AR9280_DEVID_PCIE:
-	case AR9285_DEVID_PCIE:
-		ah = ath9k_hw_do_attach(devid, sc, error);
-		break;
-	default:
-		*error = -ENXIO;
-		break;
-	}
-
-	return ah;
-}
-
-/*******/
-/* INI */
-/*******/
-
-static void ath9k_hw_override_ini(struct ath_hw *ah,
-				  struct ath9k_channel *chan)
-{
-	/*
-	 * Set the RX_ABORT and RX_DIS and clear if off only after
-	 * RXE is set for MAC. This prevents frames with corrupted
-	 * descriptor status.
-	 */
-	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-
-
-	if (!AR_SREV_5416_20_OR_LATER(ah) ||
-	    AR_SREV_9280_10_OR_LATER(ah))
-		return;
-
-	REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
-}
-
-static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
-			      struct ar5416_eeprom_def *pEepData,
-			      u32 reg, u32 value)
-{
-	struct base_eep_header *pBase = &(pEepData->baseEepHeader);
-
-	switch (ah->hw_version.devid) {
-	case AR9280_DEVID_PCI:
-		if (reg == 0x7894) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-				"ini VAL: %x  EEPROM: %x\n", value,
-				(pBase->version & 0xff));
-
-			if ((pBase->version & 0xff) > 0x0a) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					"PWDCLKIND: %d\n",
-					pBase->pwdclkind);
-				value &= ~AR_AN_TOP2_PWDCLKIND;
-				value |= AR_AN_TOP2_PWDCLKIND &
-					(pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
-			} else {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					"PWDCLKIND Earlier Rev\n");
-			}
-
-			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-				"final ini VAL: %x\n", value);
-		}
-		break;
-	}
-
-	return value;
-}
-
-static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
-			      struct ar5416_eeprom_def *pEepData,
-			      u32 reg, u32 value)
-{
-	if (ah->eep_map == EEP_MAP_4KBITS)
-		return value;
-	else
-		return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
-}
-
-static void ath9k_olc_init(struct ath_hw *ah)
-{
-	u32 i;
-
-	for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
-		ah->originalGain[i] =
-			MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
-					AR_PHY_TX_GAIN);
-	ah->PDADCdelta = 0;
-}
-
-static int ath9k_hw_process_ini(struct ath_hw *ah,
-				struct ath9k_channel *chan,
-				enum ath9k_ht_macmode macmode)
-{
-	int i, regWrites = 0;
-	struct ieee80211_channel *channel = chan->chan;
-	u32 modesIndex, freqIndex;
-	int status;
-
-	switch (chan->chanmode) {
-	case CHANNEL_A:
-	case CHANNEL_A_HT20:
-		modesIndex = 1;
-		freqIndex = 1;
-		break;
-	case CHANNEL_A_HT40PLUS:
-	case CHANNEL_A_HT40MINUS:
-		modesIndex = 2;
-		freqIndex = 1;
-		break;
-	case CHANNEL_G:
-	case CHANNEL_G_HT20:
-	case CHANNEL_B:
-		modesIndex = 4;
-		freqIndex = 2;
-		break;
-	case CHANNEL_G_HT40PLUS:
-	case CHANNEL_G_HT40MINUS:
-		modesIndex = 3;
-		freqIndex = 2;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	REG_WRITE(ah, AR_PHY(0), 0x00000007);
-	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
-	ah->eep_ops->set_addac(ah, chan);
-
-	if (AR_SREV_5416_22_OR_LATER(ah)) {
-		REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
-	} else {
-		struct ar5416IniArray temp;
-		u32 addacSize =
-			sizeof(u32) * ah->iniAddac.ia_rows *
-			ah->iniAddac.ia_columns;
-
-		memcpy(ah->addac5416_21,
-		       ah->iniAddac.ia_array, addacSize);
-
-		(ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
-
-		temp.ia_array = ah->addac5416_21;
-		temp.ia_columns = ah->iniAddac.ia_columns;
-		temp.ia_rows = ah->iniAddac.ia_rows;
-		REG_WRITE_ARRAY(&temp, 1, regWrites);
-	}
-
-	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
-
-	for (i = 0; i < ah->iniModes.ia_rows; i++) {
-		u32 reg = INI_RA(&ah->iniModes, i, 0);
-		u32 val = INI_RA(&ah->iniModes, i, modesIndex);
-
-		REG_WRITE(ah, reg, val);
-
-		if (reg >= 0x7800 && reg < 0x78a0
-		    && ah->config.analog_shiftreg) {
-			udelay(100);
-		}
-
-		DO_DELAY(regWrites);
-	}
-
-	if (AR_SREV_9280(ah))
-		REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
-
-	if (AR_SREV_9280(ah) || (AR_SREV_9285(ah) &&
-	    AR_SREV_9285_12_OR_LATER(ah)))
-		REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
-
-	for (i = 0; i < ah->iniCommon.ia_rows; i++) {
-		u32 reg = INI_RA(&ah->iniCommon, i, 0);
-		u32 val = INI_RA(&ah->iniCommon, i, 1);
-
-		REG_WRITE(ah, reg, val);
-
-		if (reg >= 0x7800 && reg < 0x78a0
-		    && ah->config.analog_shiftreg) {
-			udelay(100);
-		}
-
-		DO_DELAY(regWrites);
-	}
-
-	ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
-
-	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
-		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
-				regWrites);
-	}
-
-	ath9k_hw_override_ini(ah, chan);
-	ath9k_hw_set_regs(ah, chan, macmode);
-	ath9k_hw_init_chain_masks(ah);
-
-	if (OLC_FOR_AR9280_20_LATER)
-		ath9k_olc_init(ah);
-
-	status = ah->eep_ops->set_txpower(ah, chan,
-				  ath9k_regd_get_ctl(ah, chan),
-				  channel->max_antenna_gain * 2,
-				  channel->max_power * 2,
-				  min((u32) MAX_RATE_POWER,
-				      (u32) ah->regulatory.power_limit));
-	if (status != 0) {
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"error init'ing transmit power\n");
-		return -EIO;
-	}
-
-	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			"ar5416SetRfRegs failed\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/****************************************/
-/* Reset and Channel Switching Routines */
-/****************************************/
-
-static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	u32 rfMode = 0;
-
-	if (chan == NULL)
-		return;
-
-	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
-		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
-
-	if (!AR_SREV_9280_10_OR_LATER(ah))
-		rfMode |= (IS_CHAN_5GHZ(chan)) ?
-			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
-
-	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
-		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
-
-	REG_WRITE(ah, AR_PHY_MODE, rfMode);
-}
-
-static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
-{
-	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
-}
-
-static inline void ath9k_hw_set_dma(struct ath_hw *ah)
-{
-	u32 regval;
-
-	regval = REG_READ(ah, AR_AHB_MODE);
-	REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
-
-	regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
-	REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
-
-	REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
-
-	regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
-	REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
-
-	REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
-
-	if (AR_SREV_9285(ah)) {
-		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
-			  AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
-	} else {
-		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
-			  AR_PCU_TXBUF_CTRL_USABLE_SIZE);
-	}
-}
-
-static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
-{
-	u32 val;
-
-	val = REG_READ(ah, AR_STA_ID1);
-	val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
-	switch (opmode) {
-	case NL80211_IFTYPE_AP:
-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
-			  | AR_STA_ID1_KSRCH_MODE);
-		REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
-		break;
-	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_MESH_POINT:
-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
-			  | AR_STA_ID1_KSRCH_MODE);
-		REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
-		break;
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_MONITOR:
-		REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
-		break;
-	}
-}
-
-static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah,
-						 u32 coef_scaled,
-						 u32 *coef_mantissa,
-						 u32 *coef_exponent)
-{
-	u32 coef_exp, coef_man;
-
-	for (coef_exp = 31; coef_exp > 0; coef_exp--)
-		if ((coef_scaled >> coef_exp) & 0x1)
-			break;
-
-	coef_exp = 14 - (coef_exp - COEF_SCALE_S);
-
-	coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
-
-	*coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
-	*coef_exponent = coef_exp - 16;
-}
-
-static void ath9k_hw_set_delta_slope(struct ath_hw *ah,
-				     struct ath9k_channel *chan)
-{
-	u32 coef_scaled, ds_coef_exp, ds_coef_man;
-	u32 clockMhzScaled = 0x64000000;
-	struct chan_centers centers;
-
-	if (IS_CHAN_HALF_RATE(chan))
-		clockMhzScaled = clockMhzScaled >> 1;
-	else if (IS_CHAN_QUARTER_RATE(chan))
-		clockMhzScaled = clockMhzScaled >> 2;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	coef_scaled = clockMhzScaled / centers.synth_center;
-
-	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
-				      &ds_coef_exp);
-
-	REG_RMW_FIELD(ah, AR_PHY_TIMING3,
-		      AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
-	REG_RMW_FIELD(ah, AR_PHY_TIMING3,
-		      AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
-
-	coef_scaled = (9 * coef_scaled) / 10;
-
-	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
-				      &ds_coef_exp);
-
-	REG_RMW_FIELD(ah, AR_PHY_HALFGI,
-		      AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
-	REG_RMW_FIELD(ah, AR_PHY_HALFGI,
-		      AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
-}
-
-static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
-{
-	u32 rst_flags;
-	u32 tmpReg;
-
-	if (AR_SREV_9100(ah)) {
-		u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK);
-		val &= ~AR_RTC_DERIVED_CLK_PERIOD;
-		val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD);
-		REG_WRITE(ah, AR_RTC_DERIVED_CLK, val);
-		(void)REG_READ(ah, AR_RTC_DERIVED_CLK);
-	}
-
-	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
-		  AR_RTC_FORCE_WAKE_ON_INT);
-
-	if (AR_SREV_9100(ah)) {
-		rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
-			AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
-	} else {
-		tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
-		if (tmpReg &
-		    (AR_INTR_SYNC_LOCAL_TIMEOUT |
-		     AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
-		} else {
-			REG_WRITE(ah, AR_RC, AR_RC_AHB);
-		}
-
-		rst_flags = AR_RTC_RC_MAC_WARM;
-		if (type == ATH9K_RESET_COLD)
-			rst_flags |= AR_RTC_RC_MAC_COLD;
-	}
-
-	REG_WRITE(ah, AR_RTC_RC, rst_flags);
-	udelay(50);
-
-	REG_WRITE(ah, AR_RTC_RC, 0);
-	if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			"RTC stuck in MAC reset\n");
-		return false;
-	}
-
-	if (!AR_SREV_9100(ah))
-		REG_WRITE(ah, AR_RC, 0);
-
-	ath9k_hw_init_pll(ah, NULL);
-
-	if (AR_SREV_9100(ah))
-		udelay(50);
-
-	return true;
-}
-
-static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
-{
-	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
-		  AR_RTC_FORCE_WAKE_ON_INT);
-
-	REG_WRITE(ah, AR_RTC_RESET, 0);
-	udelay(2);
-	REG_WRITE(ah, AR_RTC_RESET, 1);
-
-	if (!ath9k_hw_wait(ah,
-			   AR_RTC_STATUS,
-			   AR_RTC_STATUS_M,
-			   AR_RTC_STATUS_ON,
-			   AH_WAIT_TIMEOUT)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n");
-		return false;
-	}
-
-	ath9k_hw_read_revisions(ah);
-
-	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
-}
-
-static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
-{
-	REG_WRITE(ah, AR_RTC_FORCE_WAKE,
-		  AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
-
-	switch (type) {
-	case ATH9K_RESET_POWER_ON:
-		return ath9k_hw_set_reset_power_on(ah);
-		break;
-	case ATH9K_RESET_WARM:
-	case ATH9K_RESET_COLD:
-		return ath9k_hw_set_reset(ah, type);
-		break;
-	default:
-		return false;
-	}
-}
-
-static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
-			      enum ath9k_ht_macmode macmode)
-{
-	u32 phymode;
-	u32 enableDacFifo = 0;
-
-	if (AR_SREV_9285_10_OR_LATER(ah))
-		enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
-					 AR_PHY_FC_ENABLE_DAC_FIFO);
-
-	phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
-		| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
-
-	if (IS_CHAN_HT40(chan)) {
-		phymode |= AR_PHY_FC_DYN2040_EN;
-
-		if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
-		    (chan->chanmode == CHANNEL_G_HT40PLUS))
-			phymode |= AR_PHY_FC_DYN2040_PRI_CH;
-
-		if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
-			phymode |= AR_PHY_FC_DYN2040_EXT_CH;
-	}
-	REG_WRITE(ah, AR_PHY_TURBO, phymode);
-
-	ath9k_hw_set11nmac2040(ah, macmode);
-
-	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
-	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
-}
-
-static bool ath9k_hw_chip_reset(struct ath_hw *ah,
-				struct ath9k_channel *chan)
-{
-	if (OLC_FOR_AR9280_20_LATER) {
-		if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
-			return false;
-	} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
-		return false;
-
-	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
-		return false;
-
-	ah->chip_fullsleep = false;
-	ath9k_hw_init_pll(ah, chan);
-	ath9k_hw_set_rfmode(ah, chan);
-
-	return true;
-}
-
-static bool ath9k_hw_channel_change(struct ath_hw *ah,
-				    struct ath9k_channel *chan,
-				    enum ath9k_ht_macmode macmode)
-{
-	struct ieee80211_channel *channel = chan->chan;
-	u32 synthDelay, qnum;
-
-	for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
-		if (ath9k_hw_numtxpending(ah, qnum)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				"Transmit frames pending on queue %d\n", qnum);
-			return false;
-		}
-	}
-
-	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
-	if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
-			   AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			"Could not kill baseband RX\n");
-		return false;
-	}
-
-	ath9k_hw_set_regs(ah, chan, macmode);
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-				"failed to set channel\n");
-			return false;
-		}
-	} else {
-		if (!(ath9k_hw_set_channel(ah, chan))) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-				"failed to set channel\n");
-			return false;
-		}
-	}
-
-	if (ah->eep_ops->set_txpower(ah, chan,
-			     ath9k_regd_get_ctl(ah, chan),
-			     channel->max_antenna_gain * 2,
-			     channel->max_power * 2,
-			     min((u32) MAX_RATE_POWER,
-				 (u32) ah->regulatory.power_limit)) != 0) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"error init'ing transmit power\n");
-		return false;
-	}
-
-	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-	if (IS_CHAN_B(chan))
-		synthDelay = (4 * synthDelay) / 22;
-	else
-		synthDelay /= 10;
-
-	udelay(synthDelay + BASE_ACTIVATE_DELAY);
-
-	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
-
-	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
-		ath9k_hw_set_delta_slope(ah, chan);
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		ath9k_hw_9280_spur_mitigate(ah, chan);
-	else
-		ath9k_hw_spur_mitigate(ah, chan);
-
-	if (!chan->oneTimeCalsDone)
-		chan->oneTimeCalsDone = true;
-
-	return true;
-}
-
-static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	int bb_spur = AR_NO_SPUR;
-	int freq;
-	int bin, cur_bin;
-	int bb_spur_off, spur_subchannel_sd;
-	int spur_freq_sd;
-	int spur_delta_phase;
-	int denominator;
-	int upper, lower, cur_vit_mask;
-	int tmp, newVal;
-	int i;
-	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
-			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
-	};
-	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
-			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
-	};
-	int inc[4] = { 0, 100, 0, 0 };
-	struct chan_centers centers;
-
-	int8_t mask_m[123];
-	int8_t mask_p[123];
-	int8_t mask_amt;
-	int tmp_mask;
-	int cur_bb_spur;
-	bool is2GHz = IS_CHAN_2GHZ(chan);
-
-	memset(&mask_m, 0, sizeof(int8_t) * 123);
-	memset(&mask_p, 0, sizeof(int8_t) * 123);
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	freq = centers.synth_center;
-
-	ah->config.spurmode = SPUR_ENABLE_EEPROM;
-	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
-		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
-
-		if (is2GHz)
-			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
-		else
-			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
-
-		if (AR_NO_SPUR == cur_bb_spur)
-			break;
-		cur_bb_spur = cur_bb_spur - freq;
-
-		if (IS_CHAN_HT40(chan)) {
-			if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
-			    (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
-				bb_spur = cur_bb_spur;
-				break;
-			}
-		} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
-			   (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
-			bb_spur = cur_bb_spur;
-			break;
-		}
-	}
-
-	if (AR_NO_SPUR == bb_spur) {
-		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
-			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
-		return;
-	} else {
-		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
-			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
-	}
-
-	bin = bb_spur * 320;
-
-	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
-
-	newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
-			AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
-			AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
-			AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
-	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
-
-	newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
-		  AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
-		  AR_PHY_SPUR_REG_MASK_RATE_SELECT |
-		  AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
-		  SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
-	REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
-
-	if (IS_CHAN_HT40(chan)) {
-		if (bb_spur < 0) {
-			spur_subchannel_sd = 1;
-			bb_spur_off = bb_spur + 10;
-		} else {
-			spur_subchannel_sd = 0;
-			bb_spur_off = bb_spur - 10;
-		}
-	} else {
-		spur_subchannel_sd = 0;
-		bb_spur_off = bb_spur;
-	}
-
-	if (IS_CHAN_HT40(chan))
-		spur_delta_phase =
-			((bb_spur * 262144) /
-			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
-	else
-		spur_delta_phase =
-			((bb_spur * 524288) /
-			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
-
-	denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
-	spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
-
-	newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
-		  SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
-		  SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
-	REG_WRITE(ah, AR_PHY_TIMING11, newVal);
-
-	newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
-	REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
-
-	cur_bin = -6000;
-	upper = bin + 100;
-	lower = bin - 100;
-
-	for (i = 0; i < 4; i++) {
-		int pilot_mask = 0;
-		int chan_mask = 0;
-		int bp = 0;
-		for (bp = 0; bp < 30; bp++) {
-			if ((cur_bin > lower) && (cur_bin < upper)) {
-				pilot_mask = pilot_mask | 0x1 << bp;
-				chan_mask = chan_mask | 0x1 << bp;
-			}
-			cur_bin += 100;
-		}
-		cur_bin += inc[i];
-		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
-		REG_WRITE(ah, chan_mask_reg[i], chan_mask);
-	}
-
-	cur_vit_mask = 6100;
-	upper = bin + 120;
-	lower = bin - 120;
-
-	for (i = 0; i < 123; i++) {
-		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
-
-			/* workaround for gcc bug #37014 */
-			volatile int tmp_v = abs(cur_vit_mask - bin);
-
-			if (tmp_v < 75)
-				mask_amt = 1;
-			else
-				mask_amt = 0;
-			if (cur_vit_mask < 0)
-				mask_m[abs(cur_vit_mask / 100)] = mask_amt;
-			else
-				mask_p[cur_vit_mask / 100] = mask_amt;
-		}
-		cur_vit_mask -= 100;
-	}
-
-	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
-		| (mask_m[48] << 26) | (mask_m[49] << 24)
-		| (mask_m[50] << 22) | (mask_m[51] << 20)
-		| (mask_m[52] << 18) | (mask_m[53] << 16)
-		| (mask_m[54] << 14) | (mask_m[55] << 12)
-		| (mask_m[56] << 10) | (mask_m[57] << 8)
-		| (mask_m[58] << 6) | (mask_m[59] << 4)
-		| (mask_m[60] << 2) | (mask_m[61] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
-	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
-
-	tmp_mask = (mask_m[31] << 28)
-		| (mask_m[32] << 26) | (mask_m[33] << 24)
-		| (mask_m[34] << 22) | (mask_m[35] << 20)
-		| (mask_m[36] << 18) | (mask_m[37] << 16)
-		| (mask_m[48] << 14) | (mask_m[39] << 12)
-		| (mask_m[40] << 10) | (mask_m[41] << 8)
-		| (mask_m[42] << 6) | (mask_m[43] << 4)
-		| (mask_m[44] << 2) | (mask_m[45] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
-
-	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
-		| (mask_m[18] << 26) | (mask_m[18] << 24)
-		| (mask_m[20] << 22) | (mask_m[20] << 20)
-		| (mask_m[22] << 18) | (mask_m[22] << 16)
-		| (mask_m[24] << 14) | (mask_m[24] << 12)
-		| (mask_m[25] << 10) | (mask_m[26] << 8)
-		| (mask_m[27] << 6) | (mask_m[28] << 4)
-		| (mask_m[29] << 2) | (mask_m[30] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
-
-	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
-		| (mask_m[2] << 26) | (mask_m[3] << 24)
-		| (mask_m[4] << 22) | (mask_m[5] << 20)
-		| (mask_m[6] << 18) | (mask_m[7] << 16)
-		| (mask_m[8] << 14) | (mask_m[9] << 12)
-		| (mask_m[10] << 10) | (mask_m[11] << 8)
-		| (mask_m[12] << 6) | (mask_m[13] << 4)
-		| (mask_m[14] << 2) | (mask_m[15] << 0);
-	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
-
-	tmp_mask = (mask_p[15] << 28)
-		| (mask_p[14] << 26) | (mask_p[13] << 24)
-		| (mask_p[12] << 22) | (mask_p[11] << 20)
-		| (mask_p[10] << 18) | (mask_p[9] << 16)
-		| (mask_p[8] << 14) | (mask_p[7] << 12)
-		| (mask_p[6] << 10) | (mask_p[5] << 8)
-		| (mask_p[4] << 6) | (mask_p[3] << 4)
-		| (mask_p[2] << 2) | (mask_p[1] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
-
-	tmp_mask = (mask_p[30] << 28)
-		| (mask_p[29] << 26) | (mask_p[28] << 24)
-		| (mask_p[27] << 22) | (mask_p[26] << 20)
-		| (mask_p[25] << 18) | (mask_p[24] << 16)
-		| (mask_p[23] << 14) | (mask_p[22] << 12)
-		| (mask_p[21] << 10) | (mask_p[20] << 8)
-		| (mask_p[19] << 6) | (mask_p[18] << 4)
-		| (mask_p[17] << 2) | (mask_p[16] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
-
-	tmp_mask = (mask_p[45] << 28)
-		| (mask_p[44] << 26) | (mask_p[43] << 24)
-		| (mask_p[42] << 22) | (mask_p[41] << 20)
-		| (mask_p[40] << 18) | (mask_p[39] << 16)
-		| (mask_p[38] << 14) | (mask_p[37] << 12)
-		| (mask_p[36] << 10) | (mask_p[35] << 8)
-		| (mask_p[34] << 6) | (mask_p[33] << 4)
-		| (mask_p[32] << 2) | (mask_p[31] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
-
-	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
-		| (mask_p[59] << 26) | (mask_p[58] << 24)
-		| (mask_p[57] << 22) | (mask_p[56] << 20)
-		| (mask_p[55] << 18) | (mask_p[54] << 16)
-		| (mask_p[53] << 14) | (mask_p[52] << 12)
-		| (mask_p[51] << 10) | (mask_p[50] << 8)
-		| (mask_p[49] << 6) | (mask_p[48] << 4)
-		| (mask_p[47] << 2) | (mask_p[46] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
-}
-
-static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	int bb_spur = AR_NO_SPUR;
-	int bin, cur_bin;
-	int spur_freq_sd;
-	int spur_delta_phase;
-	int denominator;
-	int upper, lower, cur_vit_mask;
-	int tmp, new;
-	int i;
-	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
-			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
-	};
-	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
-			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
-	};
-	int inc[4] = { 0, 100, 0, 0 };
-
-	int8_t mask_m[123];
-	int8_t mask_p[123];
-	int8_t mask_amt;
-	int tmp_mask;
-	int cur_bb_spur;
-	bool is2GHz = IS_CHAN_2GHZ(chan);
-
-	memset(&mask_m, 0, sizeof(int8_t) * 123);
-	memset(&mask_p, 0, sizeof(int8_t) * 123);
-
-	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
-		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
-		if (AR_NO_SPUR == cur_bb_spur)
-			break;
-		cur_bb_spur = cur_bb_spur - (chan->channel * 10);
-		if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
-			bb_spur = cur_bb_spur;
-			break;
-		}
-	}
-
-	if (AR_NO_SPUR == bb_spur)
-		return;
-
-	bin = bb_spur * 32;
-
-	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
-	new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
-		     AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
-		     AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
-		     AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
-
-	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
-
-	new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
-	       AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
-	       AR_PHY_SPUR_REG_MASK_RATE_SELECT |
-	       AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
-	       SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
-	REG_WRITE(ah, AR_PHY_SPUR_REG, new);
-
-	spur_delta_phase = ((bb_spur * 524288) / 100) &
-		AR_PHY_TIMING11_SPUR_DELTA_PHASE;
-
-	denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
-	spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
-
-	new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
-	       SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
-	       SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
-	REG_WRITE(ah, AR_PHY_TIMING11, new);
-
-	cur_bin = -6000;
-	upper = bin + 100;
-	lower = bin - 100;
-
-	for (i = 0; i < 4; i++) {
-		int pilot_mask = 0;
-		int chan_mask = 0;
-		int bp = 0;
-		for (bp = 0; bp < 30; bp++) {
-			if ((cur_bin > lower) && (cur_bin < upper)) {
-				pilot_mask = pilot_mask | 0x1 << bp;
-				chan_mask = chan_mask | 0x1 << bp;
-			}
-			cur_bin += 100;
-		}
-		cur_bin += inc[i];
-		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
-		REG_WRITE(ah, chan_mask_reg[i], chan_mask);
-	}
-
-	cur_vit_mask = 6100;
-	upper = bin + 120;
-	lower = bin - 120;
-
-	for (i = 0; i < 123; i++) {
-		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
-
-			/* workaround for gcc bug #37014 */
-			volatile int tmp_v = abs(cur_vit_mask - bin);
-
-			if (tmp_v < 75)
-				mask_amt = 1;
-			else
-				mask_amt = 0;
-			if (cur_vit_mask < 0)
-				mask_m[abs(cur_vit_mask / 100)] = mask_amt;
-			else
-				mask_p[cur_vit_mask / 100] = mask_amt;
-		}
-		cur_vit_mask -= 100;
-	}
-
-	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
-		| (mask_m[48] << 26) | (mask_m[49] << 24)
-		| (mask_m[50] << 22) | (mask_m[51] << 20)
-		| (mask_m[52] << 18) | (mask_m[53] << 16)
-		| (mask_m[54] << 14) | (mask_m[55] << 12)
-		| (mask_m[56] << 10) | (mask_m[57] << 8)
-		| (mask_m[58] << 6) | (mask_m[59] << 4)
-		| (mask_m[60] << 2) | (mask_m[61] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
-	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
-
-	tmp_mask = (mask_m[31] << 28)
-		| (mask_m[32] << 26) | (mask_m[33] << 24)
-		| (mask_m[34] << 22) | (mask_m[35] << 20)
-		| (mask_m[36] << 18) | (mask_m[37] << 16)
-		| (mask_m[48] << 14) | (mask_m[39] << 12)
-		| (mask_m[40] << 10) | (mask_m[41] << 8)
-		| (mask_m[42] << 6) | (mask_m[43] << 4)
-		| (mask_m[44] << 2) | (mask_m[45] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
-
-	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
-		| (mask_m[18] << 26) | (mask_m[18] << 24)
-		| (mask_m[20] << 22) | (mask_m[20] << 20)
-		| (mask_m[22] << 18) | (mask_m[22] << 16)
-		| (mask_m[24] << 14) | (mask_m[24] << 12)
-		| (mask_m[25] << 10) | (mask_m[26] << 8)
-		| (mask_m[27] << 6) | (mask_m[28] << 4)
-		| (mask_m[29] << 2) | (mask_m[30] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
-
-	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
-		| (mask_m[2] << 26) | (mask_m[3] << 24)
-		| (mask_m[4] << 22) | (mask_m[5] << 20)
-		| (mask_m[6] << 18) | (mask_m[7] << 16)
-		| (mask_m[8] << 14) | (mask_m[9] << 12)
-		| (mask_m[10] << 10) | (mask_m[11] << 8)
-		| (mask_m[12] << 6) | (mask_m[13] << 4)
-		| (mask_m[14] << 2) | (mask_m[15] << 0);
-	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
-
-	tmp_mask = (mask_p[15] << 28)
-		| (mask_p[14] << 26) | (mask_p[13] << 24)
-		| (mask_p[12] << 22) | (mask_p[11] << 20)
-		| (mask_p[10] << 18) | (mask_p[9] << 16)
-		| (mask_p[8] << 14) | (mask_p[7] << 12)
-		| (mask_p[6] << 10) | (mask_p[5] << 8)
-		| (mask_p[4] << 6) | (mask_p[3] << 4)
-		| (mask_p[2] << 2) | (mask_p[1] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
-
-	tmp_mask = (mask_p[30] << 28)
-		| (mask_p[29] << 26) | (mask_p[28] << 24)
-		| (mask_p[27] << 22) | (mask_p[26] << 20)
-		| (mask_p[25] << 18) | (mask_p[24] << 16)
-		| (mask_p[23] << 14) | (mask_p[22] << 12)
-		| (mask_p[21] << 10) | (mask_p[20] << 8)
-		| (mask_p[19] << 6) | (mask_p[18] << 4)
-		| (mask_p[17] << 2) | (mask_p[16] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
-
-	tmp_mask = (mask_p[45] << 28)
-		| (mask_p[44] << 26) | (mask_p[43] << 24)
-		| (mask_p[42] << 22) | (mask_p[41] << 20)
-		| (mask_p[40] << 18) | (mask_p[39] << 16)
-		| (mask_p[38] << 14) | (mask_p[37] << 12)
-		| (mask_p[36] << 10) | (mask_p[35] << 8)
-		| (mask_p[34] << 6) | (mask_p[33] << 4)
-		| (mask_p[32] << 2) | (mask_p[31] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
-
-	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
-		| (mask_p[59] << 26) | (mask_p[58] << 24)
-		| (mask_p[57] << 22) | (mask_p[56] << 20)
-		| (mask_p[55] << 18) | (mask_p[54] << 16)
-		| (mask_p[53] << 14) | (mask_p[52] << 12)
-		| (mask_p[51] << 10) | (mask_p[50] << 8)
-		| (mask_p[49] << 6) | (mask_p[48] << 4)
-		| (mask_p[47] << 2) | (mask_p[46] << 0);
-	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
-	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
-}
-
-int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
-		    bool bChannelChange)
-{
-	u32 saveLedState;
-	struct ath_softc *sc = ah->ah_sc;
-	struct ath9k_channel *curchan = ah->curchan;
-	u32 saveDefAntenna;
-	u32 macStaId1;
-	int i, rx_chainmask, r;
-
-	ah->extprotspacing = sc->ht_extprotspacing;
-	ah->txchainmask = sc->tx_chainmask;
-	ah->rxchainmask = sc->rx_chainmask;
-
-	if (AR_SREV_9285(ah)) {
-		ah->txchainmask &= 0x1;
-		ah->rxchainmask &= 0x1;
-	} else if (AR_SREV_9280(ah)) {
-		ah->txchainmask &= 0x3;
-		ah->rxchainmask &= 0x3;
-	}
-
-	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
-		return -EIO;
-
-	if (curchan)
-		ath9k_hw_getnf(ah, curchan);
-
-	if (bChannelChange &&
-	    (ah->chip_fullsleep != true) &&
-	    (ah->curchan != NULL) &&
-	    (chan->channel != ah->curchan->channel) &&
-	    ((chan->channelFlags & CHANNEL_ALL) ==
-	     (ah->curchan->channelFlags & CHANNEL_ALL)) &&
-	    (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
-				   !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) {
-
-		if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
-			ath9k_hw_loadnf(ah, ah->curchan);
-			ath9k_hw_start_nfcal(ah);
-			return 0;
-		}
-	}
-
-	saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
-	if (saveDefAntenna == 0)
-		saveDefAntenna = 1;
-
-	macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
-
-	saveLedState = REG_READ(ah, AR_CFG_LED) &
-		(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
-		 AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
-
-	ath9k_hw_mark_phy_inactive(ah);
-
-	if (!ath9k_hw_chip_reset(ah, chan)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n");
-		return -EINVAL;
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
-
-	r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width);
-	if (r)
-		return r;
-
-	/* Setup MFP options for CCMP */
-	if (AR_SREV_9280_20_OR_LATER(ah)) {
-		/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
-		 * frames when constructing CCMP AAD. */
-		REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
-			      0xc7ff);
-		ah->sw_mgmt_crypto = false;
-	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
-		/* Disable hardware crypto for management frames */
-		REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
-			    AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
-		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-			    AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
-		ah->sw_mgmt_crypto = true;
-	} else
-		ah->sw_mgmt_crypto = true;
-
-	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
-		ath9k_hw_set_delta_slope(ah, chan);
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		ath9k_hw_9280_spur_mitigate(ah, chan);
-	else
-		ath9k_hw_spur_mitigate(ah, chan);
-
-	ah->eep_ops->set_board_values(ah, chan);
-
-	ath9k_hw_decrease_chain_power(ah, chan);
-
-	REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr));
-	REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4)
-		  | macStaId1
-		  | AR_STA_ID1_RTS_USE_DEF
-		  | (ah->config.
-		     ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
-		  | ah->sta_id1_defaults);
-	ath9k_hw_set_operating_mode(ah, ah->opmode);
-
-	REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask));
-	REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4));
-
-	REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
-
-	REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid));
-	REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) |
-		  ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
-
-	REG_WRITE(ah, AR_ISR, ~0);
-
-	REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		if (!(ath9k_hw_ar9280_set_channel(ah, chan)))
-			return -EIO;
-	} else {
-		if (!(ath9k_hw_set_channel(ah, chan)))
-			return -EIO;
-	}
-
-	for (i = 0; i < AR_NUM_DCU; i++)
-		REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
-
-	ah->intr_txqs = 0;
-	for (i = 0; i < ah->caps.total_queues; i++)
-		ath9k_hw_resettxqueue(ah, i);
-
-	ath9k_hw_init_interrupt_masks(ah, ah->opmode);
-	ath9k_hw_init_qos(ah);
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		ath9k_enable_rfkill(ah);
-#endif
-	ath9k_hw_init_user_settings(ah);
-
-	REG_WRITE(ah, AR_STA_ID1,
-		  REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
-
-	ath9k_hw_set_dma(ah);
-
-	REG_WRITE(ah, AR_OBS, 8);
-
-	if (ah->intr_mitigation) {
-
-		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
-		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
-	}
-
-	ath9k_hw_init_bb(ah, chan);
-
-	if (!ath9k_hw_init_cal(ah, chan))
-		return -EIO;;
-
-	rx_chainmask = ah->rxchainmask;
-	if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
-		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
-		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
-	}
-
-	REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
-
-	if (AR_SREV_9100(ah)) {
-		u32 mask;
-		mask = REG_READ(ah, AR_CFG);
-		if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-				"CFG Byte Swap Set 0x%x\n", mask);
-		} else {
-			mask =
-				INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
-			REG_WRITE(ah, AR_CFG, mask);
-			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-				"Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
-		}
-	} else {
-#ifdef __BIG_ENDIAN
-		REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
-#endif
-	}
-
-	return 0;
-}
-
-/************************/
-/* Key Cache Management */
-/************************/
-
-bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
-{
-	u32 keyType;
-
-	if (entry >= ah->caps.keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			"entry %u out of range\n", entry);
-		return false;
-	}
-
-	keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
-
-	REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
-	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
-	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
-
-	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
-		u16 micentry = entry + 64;
-
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-
-	}
-
-	if (ah->curchan == NULL)
-		return true;
-
-	return true;
-}
-
-bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
-{
-	u32 macHi, macLo;
-
-	if (entry >= ah->caps.keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			"entry %u out of range\n", entry);
-		return false;
-	}
-
-	if (mac != NULL) {
-		macHi = (mac[5] << 8) | mac[4];
-		macLo = (mac[3] << 24) |
-			(mac[2] << 16) |
-			(mac[1] << 8) |
-			mac[0];
-		macLo >>= 1;
-		macLo |= (macHi & 1) << 31;
-		macHi >>= 1;
-	} else {
-		macLo = macHi = 0;
-	}
-	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
-	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
-
-	return true;
-}
-
-bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
-				 const struct ath9k_keyval *k,
-				 const u8 *mac)
-{
-	const struct ath9k_hw_capabilities *pCap = &ah->caps;
-	u32 key0, key1, key2, key3, key4;
-	u32 keyType;
-
-	if (entry >= pCap->keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			"entry %u out of range\n", entry);
-		return false;
-	}
-
-	switch (k->kv_type) {
-	case ATH9K_CIPHER_AES_OCB:
-		keyType = AR_KEYTABLE_TYPE_AES;
-		break;
-	case ATH9K_CIPHER_AES_CCM:
-		if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-				"AES-CCM not supported by mac rev 0x%x\n",
-				ah->hw_version.macRev);
-			return false;
-		}
-		keyType = AR_KEYTABLE_TYPE_CCM;
-		break;
-	case ATH9K_CIPHER_TKIP:
-		keyType = AR_KEYTABLE_TYPE_TKIP;
-		if (ATH9K_IS_MIC_ENABLED(ah)
-		    && entry + 64 >= pCap->keycache_size) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-				"entry %u inappropriate for TKIP\n", entry);
-			return false;
-		}
-		break;
-	case ATH9K_CIPHER_WEP:
-		if (k->kv_len < LEN_WEP40) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-				"WEP key length %u too small\n", k->kv_len);
-			return false;
-		}
-		if (k->kv_len <= LEN_WEP40)
-			keyType = AR_KEYTABLE_TYPE_40;
-		else if (k->kv_len <= LEN_WEP104)
-			keyType = AR_KEYTABLE_TYPE_104;
-		else
-			keyType = AR_KEYTABLE_TYPE_128;
-		break;
-	case ATH9K_CIPHER_CLR:
-		keyType = AR_KEYTABLE_TYPE_CLR;
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			"cipher %u not supported\n", k->kv_type);
-		return false;
-	}
-
-	key0 = get_unaligned_le32(k->kv_val + 0);
-	key1 = get_unaligned_le16(k->kv_val + 4);
-	key2 = get_unaligned_le32(k->kv_val + 6);
-	key3 = get_unaligned_le16(k->kv_val + 10);
-	key4 = get_unaligned_le32(k->kv_val + 12);
-	if (k->kv_len <= LEN_WEP104)
-		key4 &= 0xff;
-
-	/*
-	 * Note: Key cache registers access special memory area that requires
-	 * two 32-bit writes to actually update the values in the internal
-	 * memory. Consequently, the exact order and pairs used here must be
-	 * maintained.
-	 */
-
-	if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
-		u16 micentry = entry + 64;
-
-		/*
-		 * Write inverted key[47:0] first to avoid Michael MIC errors
-		 * on frames that could be sent or received at the same time.
-		 * The correct key will be written in the end once everything
-		 * else is ready.
-		 */
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
-
-		/* Write key[95:48] */
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-
-		/* Write key[127:96] and key type */
-		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
-		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
-		/* Write MAC address for the entry */
-		(void) ath9k_hw_keysetmac(ah, entry, mac);
-
-		if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
-			/*
-			 * TKIP uses two key cache entries:
-			 * Michael MIC TX/RX keys in the same key cache entry
-			 * (idx = main index + 64):
-			 * key0 [31:0] = RX key [31:0]
-			 * key1 [15:0] = TX key [31:16]
-			 * key1 [31:16] = reserved
-			 * key2 [31:0] = RX key [63:32]
-			 * key3 [15:0] = TX key [15:0]
-			 * key3 [31:16] = reserved
-			 * key4 [31:0] = TX key [63:32]
-			 */
-			u32 mic0, mic1, mic2, mic3, mic4;
-
-			mic0 = get_unaligned_le32(k->kv_mic + 0);
-			mic2 = get_unaligned_le32(k->kv_mic + 4);
-			mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
-			mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
-			mic4 = get_unaligned_le32(k->kv_txmic + 4);
-
-			/* Write RX[31:0] and TX[31:16] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
-
-			/* Write RX[63:32] and TX[15:0] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
-			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
-
-			/* Write TX[63:32] and keyType(reserved) */
-			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
-			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
-				  AR_KEYTABLE_TYPE_CLR);
-
-		} else {
-			/*
-			 * TKIP uses four key cache entries (two for group
-			 * keys):
-			 * Michael MIC TX/RX keys are in different key cache
-			 * entries (idx = main index + 64 for TX and
-			 * main index + 32 + 96 for RX):
-			 * key0 [31:0] = TX/RX MIC key [31:0]
-			 * key1 [31:0] = reserved
-			 * key2 [31:0] = TX/RX MIC key [63:32]
-			 * key3 [31:0] = reserved
-			 * key4 [31:0] = reserved
-			 *
-			 * Upper layer code will call this function separately
-			 * for TX and RX keys when these registers offsets are
-			 * used.
-			 */
-			u32 mic0, mic2;
-
-			mic0 = get_unaligned_le32(k->kv_mic + 0);
-			mic2 = get_unaligned_le32(k->kv_mic + 4);
-
-			/* Write MIC key[31:0] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
-			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
-
-			/* Write MIC key[63:32] */
-			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
-			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-
-			/* Write TX[63:32] and keyType(reserved) */
-			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
-			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
-				  AR_KEYTABLE_TYPE_CLR);
-		}
-
-		/* MAC address registers are reserved for the MIC entry */
-		REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
-		REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
-
-		/*
-		 * Write the correct (un-inverted) key[47:0] last to enable
-		 * TKIP now that all other registers are set with correct
-		 * values.
-		 */
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
-	} else {
-		/* Write key[47:0] */
-		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
-		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
-
-		/* Write key[95:48] */
-		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
-		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-
-		/* Write key[127:96] and key type */
-		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
-		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
-		/* Write MAC address for the entry */
-		(void) ath9k_hw_keysetmac(ah, entry, mac);
-	}
-
-	return true;
-}
-
-bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry)
-{
-	if (entry < ah->caps.keycache_size) {
-		u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
-		if (val & AR_KEYTABLE_VALID)
-			return true;
-	}
-	return false;
-}
-
-/******************************/
-/* Power Management (Chipset) */
-/******************************/
-
-static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
-{
-	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
-	if (setChip) {
-		REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
-			    AR_RTC_FORCE_WAKE_EN);
-		if (!AR_SREV_9100(ah))
-			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
-
-		REG_CLR_BIT(ah, (AR_RTC_RESET),
-			    AR_RTC_RESET_EN);
-	}
-}
-
-static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
-{
-	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
-	if (setChip) {
-		struct ath9k_hw_capabilities *pCap = &ah->caps;
-
-		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-			REG_WRITE(ah, AR_RTC_FORCE_WAKE,
-				  AR_RTC_FORCE_WAKE_ON_INT);
-		} else {
-			REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
-				    AR_RTC_FORCE_WAKE_EN);
-		}
-	}
-}
-
-static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
-{
-	u32 val;
-	int i;
-
-	if (setChip) {
-		if ((REG_READ(ah, AR_RTC_STATUS) &
-		     AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
-			if (ath9k_hw_set_reset_reg(ah,
-					   ATH9K_RESET_POWER_ON) != true) {
-				return false;
-			}
-		}
-		if (AR_SREV_9100(ah))
-			REG_SET_BIT(ah, AR_RTC_RESET,
-				    AR_RTC_RESET_EN);
-
-		REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
-			    AR_RTC_FORCE_WAKE_EN);
-		udelay(50);
-
-		for (i = POWER_UP_TIME / 50; i > 0; i--) {
-			val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
-			if (val == AR_RTC_STATUS_ON)
-				break;
-			udelay(50);
-			REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
-				    AR_RTC_FORCE_WAKE_EN);
-		}
-		if (i == 0) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-				"Failed to wakeup in %uus\n", POWER_UP_TIME / 20);
-			return false;
-		}
-	}
-
-	REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
-
-	return true;
-}
-
-bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
-{
-	int status = true, setChip = true;
-	static const char *modes[] = {
-		"AWAKE",
-		"FULL-SLEEP",
-		"NETWORK SLEEP",
-		"UNDEFINED"
-	};
-
-	DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n",
-		modes[ah->power_mode], modes[mode],
-		setChip ? "set chip " : "");
-
-	switch (mode) {
-	case ATH9K_PM_AWAKE:
-		status = ath9k_hw_set_power_awake(ah, setChip);
-		break;
-	case ATH9K_PM_FULL_SLEEP:
-		ath9k_set_power_sleep(ah, setChip);
-		ah->chip_fullsleep = true;
-		break;
-	case ATH9K_PM_NETWORK_SLEEP:
-		ath9k_set_power_network_sleep(ah, setChip);
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"Unknown power mode %u\n", mode);
-		return false;
-	}
-	ah->power_mode = mode;
-
-	return status;
-}
-
-/*
- * Helper for ASPM support.
- *
- * Disable PLL when in L0s as well as receiver clock when in L1.
- * This power saving option must be enabled through the SerDes.
- *
- * Programming the SerDes must go through the same 288 bit serial shift
- * register as the other analog registers.  Hence the 9 writes.
- */
-void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
-{
-	u8 i;
-
-	if (ah->is_pciexpress != true)
-		return;
-
-	/* Do not touch SerDes registers */
-	if (ah->config.pcie_powersave_enable == 2)
-		return;
-
-	/* Nothing to do on restore for 11N */
-	if (restore)
-		return;
-
-	if (AR_SREV_9280_20_OR_LATER(ah)) {
-		/*
-		 * AR9280 2.0 or later chips use SerDes values from the
-		 * initvals.h initialized depending on chipset during
-		 * ath9k_hw_do_attach()
-		 */
-		for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
-			REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
-				  INI_RA(&ah->iniPcieSerdes, i, 1));
-		}
-	} else if (AR_SREV_9280(ah) &&
-		   (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-
-		/* RX shut off when elecidle is asserted */
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
-
-		/* Shut off CLKREQ active in L1 */
-		if (ah->config.pcie_clock_req)
-			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
-		else
-			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
-
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
-
-		/* Load the new settings */
-		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-
-	} else {
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-
-		/* RX shut off when elecidle is asserted */
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
-
-		/*
-		 * Ignore ah->ah_config.pcie_clock_req setting for
-		 * pre-AR9280 11n
-		 */
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
-
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
-
-		/* Load the new settings */
-		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-	}
-
-	udelay(1000);
-
-	/* set bit 19 to allow forcing of pcie core into L1 state */
-	REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
-
-	/* Several PCIe massages to ensure proper behaviour */
-	if (ah->config.pcie_waen) {
-		REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
-	} else {
-		if (AR_SREV_9285(ah))
-			REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
-		/*
-		 * On AR9280 chips bit 22 of 0x4004 needs to be set to
-		 * otherwise card may disappear.
-		 */
-		else if (AR_SREV_9280(ah))
-			REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
-		else
-			REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
-	}
-}
-
-/**********************/
-/* Interrupt Handling */
-/**********************/
-
-bool ath9k_hw_intrpend(struct ath_hw *ah)
-{
-	u32 host_isr;
-
-	if (AR_SREV_9100(ah))
-		return true;
-
-	host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
-	if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
-		return true;
-
-	host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
-	if ((host_isr & AR_INTR_SYNC_DEFAULT)
-	    && (host_isr != AR_INTR_SPURIOUS))
-		return true;
-
-	return false;
-}
-
-bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
-{
-	u32 isr = 0;
-	u32 mask2 = 0;
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	u32 sync_cause = 0;
-	bool fatal_int = false;
-
-	if (!AR_SREV_9100(ah)) {
-		if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
-			if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
-			    == AR_RTC_STATUS_ON) {
-				isr = REG_READ(ah, AR_ISR);
-			}
-		}
-
-		sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
-			AR_INTR_SYNC_DEFAULT;
-
-		*masked = 0;
-
-		if (!isr && !sync_cause)
-			return false;
-	} else {
-		*masked = 0;
-		isr = REG_READ(ah, AR_ISR);
-	}
-
-	if (isr) {
-		if (isr & AR_ISR_BCNMISC) {
-			u32 isr2;
-			isr2 = REG_READ(ah, AR_ISR_S2);
-			if (isr2 & AR_ISR_S2_TIM)
-				mask2 |= ATH9K_INT_TIM;
-			if (isr2 & AR_ISR_S2_DTIM)
-				mask2 |= ATH9K_INT_DTIM;
-			if (isr2 & AR_ISR_S2_DTIMSYNC)
-				mask2 |= ATH9K_INT_DTIMSYNC;
-			if (isr2 & (AR_ISR_S2_CABEND))
-				mask2 |= ATH9K_INT_CABEND;
-			if (isr2 & AR_ISR_S2_GTT)
-				mask2 |= ATH9K_INT_GTT;
-			if (isr2 & AR_ISR_S2_CST)
-				mask2 |= ATH9K_INT_CST;
-			if (isr2 & AR_ISR_S2_TSFOOR)
-				mask2 |= ATH9K_INT_TSFOOR;
-		}
-
-		isr = REG_READ(ah, AR_ISR_RAC);
-		if (isr == 0xffffffff) {
-			*masked = 0;
-			return false;
-		}
-
-		*masked = isr & ATH9K_INT_COMMON;
-
-		if (ah->intr_mitigation) {
-			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
-				*masked |= ATH9K_INT_RX;
-		}
-
-		if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
-			*masked |= ATH9K_INT_RX;
-		if (isr &
-		    (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
-		     AR_ISR_TXEOL)) {
-			u32 s0_s, s1_s;
-
-			*masked |= ATH9K_INT_TX;
-
-			s0_s = REG_READ(ah, AR_ISR_S0_S);
-			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
-			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
-			s1_s = REG_READ(ah, AR_ISR_S1_S);
-			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
-			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
-		}
-
-		if (isr & AR_ISR_RXORN) {
-			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-				"receive FIFO overrun interrupt\n");
-		}
-
-		if (!AR_SREV_9100(ah)) {
-			if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-				u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
-				if (isr5 & AR_ISR_S5_TIM_TIMER)
-					*masked |= ATH9K_INT_TIM_TIMER;
-			}
-		}
-
-		*masked |= mask2;
-	}
-
-	if (AR_SREV_9100(ah))
-		return true;
-
-	if (sync_cause) {
-		fatal_int =
-			(sync_cause &
-			 (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
-			? true : false;
-
-		if (fatal_int) {
-			if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					"received PCI FATAL interrupt\n");
-			}
-			if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
-					"received PCI PERR interrupt\n");
-			}
-		}
-		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
-			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-				"AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
-			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
-			REG_WRITE(ah, AR_RC, 0);
-			*masked |= ATH9K_INT_FATAL;
-		}
-		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
-			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-				"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
-		}
-
-		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
-		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
-	}
-
-	return true;
-}
-
-enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah)
-{
-	return ah->mask_reg;
-}
-
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
-{
-	u32 omask = ah->mask_reg;
-	u32 mask, mask2;
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
-
-	if (omask & ATH9K_INT_GLOBAL) {
-		DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n");
-		REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
-		(void) REG_READ(ah, AR_IER);
-		if (!AR_SREV_9100(ah)) {
-			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
-			(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
-
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-			(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
-		}
-	}
-
-	mask = ints & ATH9K_INT_COMMON;
-	mask2 = 0;
-
-	if (ints & ATH9K_INT_TX) {
-		if (ah->txok_interrupt_mask)
-			mask |= AR_IMR_TXOK;
-		if (ah->txdesc_interrupt_mask)
-			mask |= AR_IMR_TXDESC;
-		if (ah->txerr_interrupt_mask)
-			mask |= AR_IMR_TXERR;
-		if (ah->txeol_interrupt_mask)
-			mask |= AR_IMR_TXEOL;
-	}
-	if (ints & ATH9K_INT_RX) {
-		mask |= AR_IMR_RXERR;
-		if (ah->intr_mitigation)
-			mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
-		else
-			mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
-		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
-			mask |= AR_IMR_GENTMR;
-	}
-
-	if (ints & (ATH9K_INT_BMISC)) {
-		mask |= AR_IMR_BCNMISC;
-		if (ints & ATH9K_INT_TIM)
-			mask2 |= AR_IMR_S2_TIM;
-		if (ints & ATH9K_INT_DTIM)
-			mask2 |= AR_IMR_S2_DTIM;
-		if (ints & ATH9K_INT_DTIMSYNC)
-			mask2 |= AR_IMR_S2_DTIMSYNC;
-		if (ints & ATH9K_INT_CABEND)
-			mask2 |= AR_IMR_S2_CABEND;
-		if (ints & ATH9K_INT_TSFOOR)
-			mask2 |= AR_IMR_S2_TSFOOR;
-	}
-
-	if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
-		mask |= AR_IMR_BCNMISC;
-		if (ints & ATH9K_INT_GTT)
-			mask2 |= AR_IMR_S2_GTT;
-		if (ints & ATH9K_INT_CST)
-			mask2 |= AR_IMR_S2_CST;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
-	REG_WRITE(ah, AR_IMR, mask);
-	mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
-					   AR_IMR_S2_DTIM |
-					   AR_IMR_S2_DTIMSYNC |
-					   AR_IMR_S2_CABEND |
-					   AR_IMR_S2_CABTO |
-					   AR_IMR_S2_TSFOOR |
-					   AR_IMR_S2_GTT | AR_IMR_S2_CST);
-	REG_WRITE(ah, AR_IMR_S2, mask | mask2);
-	ah->mask_reg = ints;
-
-	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-		if (ints & ATH9K_INT_TIM_TIMER)
-			REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
-		else
-			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
-	}
-
-	if (ints & ATH9K_INT_GLOBAL) {
-		DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n");
-		REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
-		if (!AR_SREV_9100(ah)) {
-			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
-				  AR_INTR_MAC_IRQ);
-			REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
-
-
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
-				  AR_INTR_SYNC_DEFAULT);
-			REG_WRITE(ah, AR_INTR_SYNC_MASK,
-				  AR_INTR_SYNC_DEFAULT);
-		}
-		DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
-			 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
-	}
-
-	return omask;
-}
-
-/*******************/
-/* Beacon Handling */
-/*******************/
-
-void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
-{
-	int flags = 0;
-
-	ah->beacon_interval = beacon_period;
-
-	switch (ah->opmode) {
-	case NL80211_IFTYPE_STATION:
-	case NL80211_IFTYPE_MONITOR:
-		REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
-		REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
-		REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
-		flags |= AR_TBTT_TIMER_EN;
-		break;
-	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_MESH_POINT:
-		REG_SET_BIT(ah, AR_TXCFG,
-			    AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
-		REG_WRITE(ah, AR_NEXT_NDP_TIMER,
-			  TU_TO_USEC(next_beacon +
-				     (ah->atim_window ? ah->
-				      atim_window : 1)));
-		flags |= AR_NDP_TIMER_EN;
-	case NL80211_IFTYPE_AP:
-		REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
-		REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
-			  TU_TO_USEC(next_beacon -
-				     ah->config.
-				     dma_beacon_response_time));
-		REG_WRITE(ah, AR_NEXT_SWBA,
-			  TU_TO_USEC(next_beacon -
-				     ah->config.
-				     sw_beacon_response_time));
-		flags |=
-			AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_BEACON,
-			"%s: unsupported opmode: %d\n",
-			__func__, ah->opmode);
-		return;
-		break;
-	}
-
-	REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period));
-	REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period));
-	REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
-	REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
-
-	beacon_period &= ~ATH9K_BEACON_ENA;
-	if (beacon_period & ATH9K_BEACON_RESET_TSF) {
-		beacon_period &= ~ATH9K_BEACON_RESET_TSF;
-		ath9k_hw_reset_tsf(ah);
-	}
-
-	REG_SET_BIT(ah, AR_TIMER_MODE, flags);
-}
-
-void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
-				    const struct ath9k_beacon_state *bs)
-{
-	u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-
-	REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
-
-	REG_WRITE(ah, AR_BEACON_PERIOD,
-		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
-	REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
-		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
-
-	REG_RMW_FIELD(ah, AR_RSSI_THR,
-		      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
-
-	beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
-
-	if (bs->bs_sleepduration > beaconintval)
-		beaconintval = bs->bs_sleepduration;
-
-	dtimperiod = bs->bs_dtimperiod;
-	if (bs->bs_sleepduration > dtimperiod)
-		dtimperiod = bs->bs_sleepduration;
-
-	if (beaconintval == dtimperiod)
-		nextTbtt = bs->bs_nextdtim;
-	else
-		nextTbtt = bs->bs_nexttbtt;
-
-	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim);
-	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt);
-	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
-	DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
-
-	REG_WRITE(ah, AR_NEXT_DTIM,
-		  TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
-	REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
-
-	REG_WRITE(ah, AR_SLEEP1,
-		  SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
-		  | AR_SLEEP1_ASSUME_DTIM);
-
-	if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)
-		beacontimeout = (BEACON_TIMEOUT_VAL << 3);
-	else
-		beacontimeout = MIN_BEACON_TIMEOUT_VAL;
-
-	REG_WRITE(ah, AR_SLEEP2,
-		  SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
-
-	REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
-	REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
-
-	REG_SET_BIT(ah, AR_TIMER_MODE,
-		    AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
-		    AR_DTIM_TIMER_EN);
-
-	/* TSF Out of Range Threshold */
-	REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold);
-}
-
-/*******************/
-/* HW Capabilities */
-/*******************/
-
-bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
-{
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	u16 capField = 0, eeval;
-
-	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
-	ah->regulatory.current_rd = eeval;
-
-	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
-	if (AR_SREV_9285_10_OR_LATER(ah))
-		eeval |= AR9285_RDEXT_DEFAULT;
-	ah->regulatory.current_rd_ext = eeval;
-
-	capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP);
-
-	if (ah->opmode != NL80211_IFTYPE_AP &&
-	    ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
-		if (ah->regulatory.current_rd == 0x64 ||
-		    ah->regulatory.current_rd == 0x65)
-			ah->regulatory.current_rd += 5;
-		else if (ah->regulatory.current_rd == 0x41)
-			ah->regulatory.current_rd = 0x43;
-		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-			"regdomain mapped to 0x%x\n", ah->regulatory.current_rd);
-	}
-
-	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
-	bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
-
-	if (eeval & AR5416_OPFLAGS_11A) {
-		set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
-		if (ah->config.ht_enable) {
-			if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
-				set_bit(ATH9K_MODE_11NA_HT20,
-					pCap->wireless_modes);
-			if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
-				set_bit(ATH9K_MODE_11NA_HT40PLUS,
-					pCap->wireless_modes);
-				set_bit(ATH9K_MODE_11NA_HT40MINUS,
-					pCap->wireless_modes);
-			}
-		}
-	}
-
-	if (eeval & AR5416_OPFLAGS_11G) {
-		set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
-		set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
-		if (ah->config.ht_enable) {
-			if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
-				set_bit(ATH9K_MODE_11NG_HT20,
-					pCap->wireless_modes);
-			if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
-				set_bit(ATH9K_MODE_11NG_HT40PLUS,
-					pCap->wireless_modes);
-				set_bit(ATH9K_MODE_11NG_HT40MINUS,
-					pCap->wireless_modes);
-			}
-		}
-	}
-
-	pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
-	if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
-	    !(eeval & AR5416_OPFLAGS_11A))
-		pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7;
-	else
-		pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
-
-	if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
-		ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
-
-	pCap->low_2ghz_chan = 2312;
-	pCap->high_2ghz_chan = 2732;
-
-	pCap->low_5ghz_chan = 4920;
-	pCap->high_5ghz_chan = 6100;
-
-	pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
-
-	pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
-	pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
-
-	pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
-
-	if (ah->config.ht_enable)
-		pCap->hw_caps |= ATH9K_HW_CAP_HT;
-	else
-		pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
-
-	pCap->hw_caps |= ATH9K_HW_CAP_GTT;
-	pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
-	pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
-	pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
-
-	if (capField & AR_EEPROM_EEPCAP_MAXQCU)
-		pCap->total_queues =
-			MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
-	else
-		pCap->total_queues = ATH9K_NUM_TX_QUEUES;
-
-	if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
-		pCap->keycache_size =
-			1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
-	else
-		pCap->keycache_size = AR_KEYTABLE_SIZE;
-
-	pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
-	pCap->num_mr_retries = 4;
-	pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
-
-	if (AR_SREV_9285_10_OR_LATER(ah))
-		pCap->num_gpio_pins = AR9285_NUM_GPIO;
-	else if (AR_SREV_9280_10_OR_LATER(ah))
-		pCap->num_gpio_pins = AR928X_NUM_GPIO;
-	else
-		pCap->num_gpio_pins = AR_NUM_GPIO;
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		pCap->hw_caps |= ATH9K_HW_CAP_WOW;
-		pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
-	} else {
-		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
-		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
-	}
-
-	if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
-		pCap->hw_caps |= ATH9K_HW_CAP_CST;
-		pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
-	} else {
-		pCap->rts_aggr_limit = (8 * 1024);
-	}
-
-	pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
-	if (ah->rfsilent & EEP_RFSILENT_ENABLED) {
-		ah->rfkill_gpio =
-			MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL);
-		ah->rfkill_polarity =
-			MS(ah->rfsilent, EEP_RFSILENT_POLARITY);
-
-		pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
-	}
-#endif
-
-	if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9280))
-		pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
-	else
-		pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
-
-	if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
-		pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
-	else
-		pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
-
-	if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
-		pCap->reg_cap =
-			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
-			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
-			AR_EEPROM_EEREGCAP_EN_KK_U2 |
-			AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
-	} else {
-		pCap->reg_cap =
-			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
-			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
-	}
-
-	pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
-
-	pCap->num_antcfg_5ghz =
-		ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ);
-	pCap->num_antcfg_2ghz =
-		ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
-
-	if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) {
-		pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX;
-		ah->btactive_gpio = 6;
-		ah->wlanactive_gpio = 5;
-	}
-
-	return true;
-}
-
-bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
-			    u32 capability, u32 *result)
-{
-	switch (type) {
-	case ATH9K_CAP_CIPHER:
-		switch (capability) {
-		case ATH9K_CIPHER_AES_CCM:
-		case ATH9K_CIPHER_AES_OCB:
-		case ATH9K_CIPHER_TKIP:
-		case ATH9K_CIPHER_WEP:
-		case ATH9K_CIPHER_MIC:
-		case ATH9K_CIPHER_CLR:
-			return true;
-		default:
-			return false;
-		}
-	case ATH9K_CAP_TKIP_MIC:
-		switch (capability) {
-		case 0:
-			return true;
-		case 1:
-			return (ah->sta_id1_defaults &
-				AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
-			false;
-		}
-	case ATH9K_CAP_TKIP_SPLIT:
-		return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ?
-			false : true;
-	case ATH9K_CAP_DIVERSITY:
-		return (REG_READ(ah, AR_PHY_CCK_DETECT) &
-			AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
-			true : false;
-	case ATH9K_CAP_MCAST_KEYSRCH:
-		switch (capability) {
-		case 0:
-			return true;
-		case 1:
-			if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
-				return false;
-			} else {
-				return (ah->sta_id1_defaults &
-					AR_STA_ID1_MCAST_KSRCH) ? true :
-					false;
-			}
-		}
-		return false;
-	case ATH9K_CAP_TXPOW:
-		switch (capability) {
-		case 0:
-			return 0;
-		case 1:
-			*result = ah->regulatory.power_limit;
-			return 0;
-		case 2:
-			*result = ah->regulatory.max_power_level;
-			return 0;
-		case 3:
-			*result = ah->regulatory.tp_scale;
-			return 0;
-		}
-		return false;
-	case ATH9K_CAP_DS:
-		return (AR_SREV_9280_20_OR_LATER(ah) &&
-			(ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1))
-			? false : true;
-	default:
-		return false;
-	}
-}
-
-bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
-			    u32 capability, u32 setting, int *status)
-{
-	u32 v;
-
-	switch (type) {
-	case ATH9K_CAP_TKIP_MIC:
-		if (setting)
-			ah->sta_id1_defaults |=
-				AR_STA_ID1_CRPT_MIC_ENABLE;
-		else
-			ah->sta_id1_defaults &=
-				~AR_STA_ID1_CRPT_MIC_ENABLE;
-		return true;
-	case ATH9K_CAP_DIVERSITY:
-		v = REG_READ(ah, AR_PHY_CCK_DETECT);
-		if (setting)
-			v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-		else
-			v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-		REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-		return true;
-	case ATH9K_CAP_MCAST_KEYSRCH:
-		if (setting)
-			ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH;
-		else
-			ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH;
-		return true;
-	default:
-		return false;
-	}
-}
-
-/****************************/
-/* GPIO / RFKILL / Antennae */
-/****************************/
-
-static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
-					 u32 gpio, u32 type)
-{
-	int addr;
-	u32 gpio_shift, tmp;
-
-	if (gpio > 11)
-		addr = AR_GPIO_OUTPUT_MUX3;
-	else if (gpio > 5)
-		addr = AR_GPIO_OUTPUT_MUX2;
-	else
-		addr = AR_GPIO_OUTPUT_MUX1;
-
-	gpio_shift = (gpio % 6) * 5;
-
-	if (AR_SREV_9280_20_OR_LATER(ah)
-	    || (addr != AR_GPIO_OUTPUT_MUX1)) {
-		REG_RMW(ah, addr, (type << gpio_shift),
-			(0x1f << gpio_shift));
-	} else {
-		tmp = REG_READ(ah, addr);
-		tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
-		tmp &= ~(0x1f << gpio_shift);
-		tmp |= (type << gpio_shift);
-		REG_WRITE(ah, addr, tmp);
-	}
-}
-
-void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
-{
-	u32 gpio_shift;
-
-	ASSERT(gpio < ah->caps.num_gpio_pins);
-
-	gpio_shift = gpio << 1;
-
-	REG_RMW(ah,
-		AR_GPIO_OE_OUT,
-		(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
-		(AR_GPIO_OE_OUT_DRV << gpio_shift));
-}
-
-u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
-{
-#define MS_REG_READ(x, y) \
-	(MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
-
-	if (gpio >= ah->caps.num_gpio_pins)
-		return 0xffffffff;
-
-	if (AR_SREV_9285_10_OR_LATER(ah))
-		return MS_REG_READ(AR9285, gpio) != 0;
-	else if (AR_SREV_9280_10_OR_LATER(ah))
-		return MS_REG_READ(AR928X, gpio) != 0;
-	else
-		return MS_REG_READ(AR, gpio) != 0;
-}
-
-void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
-			 u32 ah_signal_type)
-{
-	u32 gpio_shift;
-
-	ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
-
-	gpio_shift = 2 * gpio;
-
-	REG_RMW(ah,
-		AR_GPIO_OE_OUT,
-		(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
-		(AR_GPIO_OE_OUT_DRV << gpio_shift));
-}
-
-void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
-{
-	REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
-		AR_GPIO_BIT(gpio));
-}
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-void ath9k_enable_rfkill(struct ath_hw *ah)
-{
-	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
-
-	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
-		    AR_GPIO_INPUT_MUX2_RFSILENT);
-
-	ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
-	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
-}
-#endif
-
-u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
-{
-	return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
-}
-
-void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
-{
-	REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
-}
-
-bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
-			       enum ath9k_ant_setting settings,
-			       struct ath9k_channel *chan,
-			       u8 *tx_chainmask,
-			       u8 *rx_chainmask,
-			       u8 *antenna_cfgd)
-{
-	static u8 tx_chainmask_cfg, rx_chainmask_cfg;
-
-	if (AR_SREV_9280(ah)) {
-		if (!tx_chainmask_cfg) {
-
-			tx_chainmask_cfg = *tx_chainmask;
-			rx_chainmask_cfg = *rx_chainmask;
-		}
-
-		switch (settings) {
-		case ATH9K_ANT_FIXED_A:
-			*tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
-			*rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
-			*antenna_cfgd = true;
-			break;
-		case ATH9K_ANT_FIXED_B:
-			if (ah->caps.tx_chainmask >
-			    ATH9K_ANTENNA1_CHAINMASK) {
-				*tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
-			}
-			*rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
-			*antenna_cfgd = true;
-			break;
-		case ATH9K_ANT_VARIABLE:
-			*tx_chainmask = tx_chainmask_cfg;
-			*rx_chainmask = rx_chainmask_cfg;
-			*antenna_cfgd = true;
-			break;
-		default:
-			break;
-		}
-	} else {
-		ah->diversity_control = settings;
-	}
-
-	return true;
-}
-
-/*********************/
-/* General Operation */
-/*********************/
-
-u32 ath9k_hw_getrxfilter(struct ath_hw *ah)
-{
-	u32 bits = REG_READ(ah, AR_RX_FILTER);
-	u32 phybits = REG_READ(ah, AR_PHY_ERR);
-
-	if (phybits & AR_PHY_ERR_RADAR)
-		bits |= ATH9K_RX_FILTER_PHYRADAR;
-	if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
-		bits |= ATH9K_RX_FILTER_PHYERR;
-
-	return bits;
-}
-
-void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
-{
-	u32 phybits;
-
-	REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
-	phybits = 0;
-	if (bits & ATH9K_RX_FILTER_PHYRADAR)
-		phybits |= AR_PHY_ERR_RADAR;
-	if (bits & ATH9K_RX_FILTER_PHYERR)
-		phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
-	REG_WRITE(ah, AR_PHY_ERR, phybits);
-
-	if (phybits)
-		REG_WRITE(ah, AR_RXCFG,
-			  REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
-	else
-		REG_WRITE(ah, AR_RXCFG,
-			  REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
-}
-
-bool ath9k_hw_phy_disable(struct ath_hw *ah)
-{
-	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
-}
-
-bool ath9k_hw_disable(struct ath_hw *ah)
-{
-	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
-		return false;
-
-	return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
-}
-
-bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
-{
-	struct ath9k_channel *chan = ah->curchan;
-	struct ieee80211_channel *channel = chan->chan;
-
-	ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
-
-	if (ah->eep_ops->set_txpower(ah, chan,
-			     ath9k_regd_get_ctl(ah, chan),
-			     channel->max_antenna_gain * 2,
-			     channel->max_power * 2,
-			     min((u32) MAX_RATE_POWER,
-				 (u32) ah->regulatory.power_limit)) != 0)
-		return false;
-
-	return true;
-}
-
-void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac)
-{
-	memcpy(ah->macaddr, mac, ETH_ALEN);
-}
-
-void ath9k_hw_setopmode(struct ath_hw *ah)
-{
-	ath9k_hw_set_operating_mode(ah, ah->opmode);
-}
-
-void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1)
-{
-	REG_WRITE(ah, AR_MCAST_FIL0, filter0);
-	REG_WRITE(ah, AR_MCAST_FIL1, filter1);
-}
-
-void ath9k_hw_setbssidmask(struct ath_softc *sc)
-{
-	REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask));
-	REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4));
-}
-
-void ath9k_hw_write_associd(struct ath_softc *sc)
-{
-	REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid));
-	REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) |
-		  ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S));
-}
-
-u64 ath9k_hw_gettsf64(struct ath_hw *ah)
-{
-	u64 tsf;
-
-	tsf = REG_READ(ah, AR_TSF_U32);
-	tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
-
-	return tsf;
-}
-
-void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64)
-{
-	REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
-	REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
-}
-
-void ath9k_hw_reset_tsf(struct ath_hw *ah)
-{
-	int count;
-
-	count = 0;
-	while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
-		count++;
-		if (count > 10) {
-			DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-				"AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
-			break;
-		}
-		udelay(10);
-	}
-	REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
-}
-
-bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
-{
-	if (setting)
-		ah->misc_mode |= AR_PCU_TX_ADD_TSF;
-	else
-		ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
-
-	return true;
-}
-
-bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
-{
-	if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us);
-		ah->slottime = (u32) -1;
-		return false;
-	} else {
-		REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
-		ah->slottime = us;
-		return true;
-	}
-}
-
-void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode)
-{
-	u32 macmode;
-
-	if (mode == ATH9K_HT_MACMODE_2040 &&
-	    !ah->config.cwm_ignore_extcca)
-		macmode = AR_2040_JOINED_RX_CLEAR;
-	else
-		macmode = 0;
-
-	REG_WRITE(ah, AR_2040_MODE, macmode);
-}
-
-/***************************/
-/*  Bluetooth Coexistence  */
-/***************************/
-
-void ath9k_hw_btcoex_enable(struct ath_hw *ah)
-{
-	/* connect bt_active to baseband */
-	REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-			(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
-			 AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
-
-	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-			AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
-
-	/* Set input mux for bt_active to gpio pin */
-	REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
-			AR_GPIO_INPUT_MUX1_BT_ACTIVE,
-			ah->btactive_gpio);
-
-	/* Configure the desired gpio port for input */
-	ath9k_hw_cfg_gpio_input(ah, ah->btactive_gpio);
-
-	/* Configure the desired GPIO port for TX_FRAME output */
-	ath9k_hw_cfg_output(ah, ah->wlanactive_gpio,
-			    AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/hw.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/hw.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/hw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,647 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef HW_H
-#define HW_H
-
-#include <linux/if_ether.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include "mac.h"
-#include "ani.h"
-#include "eeprom.h"
-#include "calib.h"
-#include "regd.h"
-#include "reg.h"
-#include "phy.h"
-
-#define ATHEROS_VENDOR_ID	0x168c
-#define AR5416_DEVID_PCI	0x0023
-#define AR5416_DEVID_PCIE	0x0024
-#define AR9160_DEVID_PCI	0x0027
-#define AR9280_DEVID_PCI	0x0029
-#define AR9280_DEVID_PCIE	0x002a
-#define AR9285_DEVID_PCIE	0x002b
-#define AR5416_AR9100_DEVID	0x000b
-#define	AR_SUBVENDOR_ID_NOG	0x0e11
-#define AR_SUBVENDOR_ID_NEW_A	0x7065
-#define AR5416_MAGIC		0x19641014
-
-/* Register read/write primitives */
-#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
-#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
-
-#define SM(_v, _f)  (((_v) << _f##_S) & _f)
-#define MS(_v, _f)  (((_v) & _f) >> _f##_S)
-#define REG_RMW(_a, _r, _set, _clr)    \
-	REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set))
-#define REG_RMW_FIELD(_a, _r, _f, _v) \
-	REG_WRITE(_a, _r, \
-	(REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f))
-#define REG_SET_BIT(_a, _r, _f) \
-	REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
-#define REG_CLR_BIT(_a, _r, _f) \
-	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
-
-#define DO_DELAY(x) do {			\
-		if ((++(x) % 64) == 0)          \
-			udelay(1);		\
-	} while (0)
-
-#define REG_WRITE_ARRAY(iniarray, column, regWr) do {                   \
-		int r;							\
-		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\
-			REG_WRITE(ah, INI_RA((iniarray), (r), 0),	\
-				  INI_RA((iniarray), r, (column)));	\
-			DO_DELAY(regWr);				\
-		}							\
-	} while (0)
-
-#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
-#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
-#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     2
-#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME           3
-#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    5
-#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      6
-
-#define AR_GPIOD_MASK               0x00001FFF
-#define AR_GPIO_BIT(_gpio)          (1 << (_gpio))
-
-#define BASE_ACTIVATE_DELAY         100
-#define RTC_PLL_SETTLE_DELAY        1000
-#define COEF_SCALE_S                24
-#define HT40_CHANNEL_CENTER_SHIFT   10
-
-#define ATH9K_ANTENNA0_CHAINMASK    0x1
-#define ATH9K_ANTENNA1_CHAINMASK    0x2
-
-#define ATH9K_NUM_DMA_DEBUG_REGS    8
-#define ATH9K_NUM_QUEUES            10
-
-#define MAX_RATE_POWER              63
-#define AH_WAIT_TIMEOUT             100000 /* (us) */
-#define AH_TIME_QUANTUM             10
-#define AR_KEYTABLE_SIZE            128
-#define POWER_UP_TIME               200000
-#define SPUR_RSSI_THRESH            40
-
-#define CAB_TIMEOUT_VAL             10
-#define BEACON_TIMEOUT_VAL          10
-#define MIN_BEACON_TIMEOUT_VAL      1
-#define SLEEP_SLOP                  3
-
-#define INIT_CONFIG_STATUS          0x00000000
-#define INIT_RSSI_THR               0x00000700
-#define INIT_BCON_CNTRL_REG         0x00000000
-
-#define TU_TO_USEC(_tu)             ((_tu) << 10)
-
-enum wireless_mode {
-	ATH9K_MODE_11A = 0,
-	ATH9K_MODE_11B = 2,
-	ATH9K_MODE_11G = 3,
-	ATH9K_MODE_11NA_HT20 = 6,
-	ATH9K_MODE_11NG_HT20 = 7,
-	ATH9K_MODE_11NA_HT40PLUS = 8,
-	ATH9K_MODE_11NA_HT40MINUS = 9,
-	ATH9K_MODE_11NG_HT40PLUS = 10,
-	ATH9K_MODE_11NG_HT40MINUS = 11,
-	ATH9K_MODE_MAX
-};
-
-enum ath9k_hw_caps {
-	ATH9K_HW_CAP_CHAN_SPREAD		= BIT(0),
-	ATH9K_HW_CAP_MIC_AESCCM                 = BIT(1),
-	ATH9K_HW_CAP_MIC_CKIP                   = BIT(2),
-	ATH9K_HW_CAP_MIC_TKIP                   = BIT(3),
-	ATH9K_HW_CAP_CIPHER_AESCCM              = BIT(4),
-	ATH9K_HW_CAP_CIPHER_CKIP                = BIT(5),
-	ATH9K_HW_CAP_CIPHER_TKIP                = BIT(6),
-	ATH9K_HW_CAP_VEOL                       = BIT(7),
-	ATH9K_HW_CAP_BSSIDMASK                  = BIT(8),
-	ATH9K_HW_CAP_MCAST_KEYSEARCH            = BIT(9),
-	ATH9K_HW_CAP_CHAN_HALFRATE              = BIT(10),
-	ATH9K_HW_CAP_CHAN_QUARTERRATE           = BIT(11),
-	ATH9K_HW_CAP_HT                         = BIT(12),
-	ATH9K_HW_CAP_GTT                        = BIT(13),
-	ATH9K_HW_CAP_FASTCC                     = BIT(14),
-	ATH9K_HW_CAP_RFSILENT                   = BIT(15),
-	ATH9K_HW_CAP_WOW                        = BIT(16),
-	ATH9K_HW_CAP_CST                        = BIT(17),
-	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(18),
-	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(19),
-	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(20),
-	ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT     = BIT(21),
-	ATH9K_HW_CAP_BT_COEX			= BIT(22)
-};
-
-enum ath9k_capability_type {
-	ATH9K_CAP_CIPHER = 0,
-	ATH9K_CAP_TKIP_MIC,
-	ATH9K_CAP_TKIP_SPLIT,
-	ATH9K_CAP_DIVERSITY,
-	ATH9K_CAP_TXPOW,
-	ATH9K_CAP_MCAST_KEYSRCH,
-	ATH9K_CAP_DS
-};
-
-struct ath9k_hw_capabilities {
-	u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
-	DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
-	u16 total_queues;
-	u16 keycache_size;
-	u16 low_5ghz_chan, high_5ghz_chan;
-	u16 low_2ghz_chan, high_2ghz_chan;
-	u16 num_mr_retries;
-	u16 rts_aggr_limit;
-	u8 tx_chainmask;
-	u8 rx_chainmask;
-	u16 tx_triglevel_max;
-	u16 reg_cap;
-	u8 num_gpio_pins;
-	u8 num_antcfg_2ghz;
-	u8 num_antcfg_5ghz;
-};
-
-struct ath9k_ops_config {
-	int dma_beacon_response_time;
-	int sw_beacon_response_time;
-	int additional_swba_backoff;
-	int ack_6mb;
-	int cwm_ignore_extcca;
-	u8 pcie_powersave_enable;
-	u8 pcie_l1skp_enable;
-	u8 pcie_clock_req;
-	u32 pcie_waen;
-	int pcie_power_reset;
-	u8 pcie_restore;
-	u8 analog_shiftreg;
-	u8 ht_enable;
-	u32 ofdm_trig_low;
-	u32 ofdm_trig_high;
-	u32 cck_trig_high;
-	u32 cck_trig_low;
-	u32 enable_ani;
-	u8 noise_immunity_level;
-	u32 ofdm_weaksignal_det;
-	u32 cck_weaksignal_thr;
-	u8 spur_immunity_level;
-	u8 firstep_level;
-	int8_t rssi_thr_high;
-	int8_t rssi_thr_low;
-	u16 diversity_control;
-	u16 antenna_switch_swap;
-	int serialize_regmode;
-	int intr_mitigation;
-#define SPUR_DISABLE        	0
-#define SPUR_ENABLE_IOCTL   	1
-#define SPUR_ENABLE_EEPROM  	2
-#define AR_EEPROM_MODAL_SPURS   5
-#define AR_SPUR_5413_1      	1640
-#define AR_SPUR_5413_2      	1200
-#define AR_NO_SPUR      	0x8000
-#define AR_BASE_FREQ_2GHZ   	2300
-#define AR_BASE_FREQ_5GHZ   	4900
-#define AR_SPUR_FEEQ_BOUND_HT40 19
-#define AR_SPUR_FEEQ_BOUND_HT20 10
-	int spurmode;
-	u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
-};
-
-enum ath9k_int {
-	ATH9K_INT_RX = 0x00000001,
-	ATH9K_INT_RXDESC = 0x00000002,
-	ATH9K_INT_RXNOFRM = 0x00000008,
-	ATH9K_INT_RXEOL = 0x00000010,
-	ATH9K_INT_RXORN = 0x00000020,
-	ATH9K_INT_TX = 0x00000040,
-	ATH9K_INT_TXDESC = 0x00000080,
-	ATH9K_INT_TIM_TIMER = 0x00000100,
-	ATH9K_INT_TXURN = 0x00000800,
-	ATH9K_INT_MIB = 0x00001000,
-	ATH9K_INT_RXPHY = 0x00004000,
-	ATH9K_INT_RXKCM = 0x00008000,
-	ATH9K_INT_SWBA = 0x00010000,
-	ATH9K_INT_BMISS = 0x00040000,
-	ATH9K_INT_BNR = 0x00100000,
-	ATH9K_INT_TIM = 0x00200000,
-	ATH9K_INT_DTIM = 0x00400000,
-	ATH9K_INT_DTIMSYNC = 0x00800000,
-	ATH9K_INT_GPIO = 0x01000000,
-	ATH9K_INT_CABEND = 0x02000000,
-	ATH9K_INT_TSFOOR = 0x04000000,
-	ATH9K_INT_CST = 0x10000000,
-	ATH9K_INT_GTT = 0x20000000,
-	ATH9K_INT_FATAL = 0x40000000,
-	ATH9K_INT_GLOBAL = 0x80000000,
-	ATH9K_INT_BMISC = ATH9K_INT_TIM |
-		ATH9K_INT_DTIM |
-		ATH9K_INT_DTIMSYNC |
-		ATH9K_INT_TSFOOR |
-		ATH9K_INT_CABEND,
-	ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM |
-		ATH9K_INT_RXDESC |
-		ATH9K_INT_RXEOL |
-		ATH9K_INT_RXORN |
-		ATH9K_INT_TXURN |
-		ATH9K_INT_TXDESC |
-		ATH9K_INT_MIB |
-		ATH9K_INT_RXPHY |
-		ATH9K_INT_RXKCM |
-		ATH9K_INT_SWBA |
-		ATH9K_INT_BMISS |
-		ATH9K_INT_GPIO,
-	ATH9K_INT_NOCARD = 0xffffffff
-};
-
-#define CHANNEL_CW_INT    0x00002
-#define CHANNEL_CCK       0x00020
-#define CHANNEL_OFDM      0x00040
-#define CHANNEL_2GHZ      0x00080
-#define CHANNEL_5GHZ      0x00100
-#define CHANNEL_PASSIVE   0x00200
-#define CHANNEL_DYN       0x00400
-#define CHANNEL_HALF      0x04000
-#define CHANNEL_QUARTER   0x08000
-#define CHANNEL_HT20      0x10000
-#define CHANNEL_HT40PLUS  0x20000
-#define CHANNEL_HT40MINUS 0x40000
-
-#define CHANNEL_INTERFERENCE    0x01
-#define CHANNEL_DFS             0x02
-#define CHANNEL_4MS_LIMIT       0x04
-#define CHANNEL_DFS_CLEAR       0x08
-#define CHANNEL_DISALLOW_ADHOC  0x10
-#define CHANNEL_PER_11D_ADHOC   0x20
-
-#define CHANNEL_A           (CHANNEL_5GHZ|CHANNEL_OFDM)
-#define CHANNEL_B           (CHANNEL_2GHZ|CHANNEL_CCK)
-#define CHANNEL_G           (CHANNEL_2GHZ|CHANNEL_OFDM)
-#define CHANNEL_G_HT20      (CHANNEL_2GHZ|CHANNEL_HT20)
-#define CHANNEL_A_HT20      (CHANNEL_5GHZ|CHANNEL_HT20)
-#define CHANNEL_G_HT40PLUS  (CHANNEL_2GHZ|CHANNEL_HT40PLUS)
-#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS)
-#define CHANNEL_A_HT40PLUS  (CHANNEL_5GHZ|CHANNEL_HT40PLUS)
-#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS)
-#define CHANNEL_ALL				\
-	(CHANNEL_OFDM|				\
-	 CHANNEL_CCK|				\
-	 CHANNEL_2GHZ |				\
-	 CHANNEL_5GHZ |				\
-	 CHANNEL_HT20 |				\
-	 CHANNEL_HT40PLUS |			\
-	 CHANNEL_HT40MINUS)
-
-struct ath9k_channel {
-	struct ieee80211_channel *chan;
-	u16 channel;
-	u32 channelFlags;
-	u32 chanmode;
-	int32_t CalValid;
-	bool oneTimeCalsDone;
-	int8_t iCoff;
-	int8_t qCoff;
-	int16_t rawNoiseFloor;
-};
-
-#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
-       (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \
-       (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \
-       (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS))
-#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
-       (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
-       (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
-       (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
-#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
-#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
-#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
-#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0)
-#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
-#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
-#define IS_CHAN_A_5MHZ_SPACED(_c)			\
-	((((_c)->channelFlags & CHANNEL_5GHZ) != 0) &&	\
-	 (((_c)->channel % 20) != 0) &&			\
-	 (((_c)->channel % 10) != 0))
-
-/* These macros check chanmode and not channelFlags */
-#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
-#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) ||	\
-			  ((_c)->chanmode == CHANNEL_G_HT20))
-#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) ||	\
-			  ((_c)->chanmode == CHANNEL_A_HT40MINUS) ||	\
-			  ((_c)->chanmode == CHANNEL_G_HT40PLUS) ||	\
-			  ((_c)->chanmode == CHANNEL_G_HT40MINUS))
-#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
-
-enum ath9k_power_mode {
-	ATH9K_PM_AWAKE = 0,
-	ATH9K_PM_FULL_SLEEP,
-	ATH9K_PM_NETWORK_SLEEP,
-	ATH9K_PM_UNDEFINED
-};
-
-enum ath9k_ant_setting {
-	ATH9K_ANT_VARIABLE = 0,
-	ATH9K_ANT_FIXED_A,
-	ATH9K_ANT_FIXED_B
-};
-
-enum ath9k_tp_scale {
-	ATH9K_TP_SCALE_MAX = 0,
-	ATH9K_TP_SCALE_50,
-	ATH9K_TP_SCALE_25,
-	ATH9K_TP_SCALE_12,
-	ATH9K_TP_SCALE_MIN
-};
-
-enum ser_reg_mode {
-	SER_REG_MODE_OFF = 0,
-	SER_REG_MODE_ON = 1,
-	SER_REG_MODE_AUTO = 2,
-};
-
-struct ath9k_beacon_state {
-	u32 bs_nexttbtt;
-	u32 bs_nextdtim;
-	u32 bs_intval;
-#define ATH9K_BEACON_PERIOD       0x0000ffff
-#define ATH9K_BEACON_ENA          0x00800000
-#define ATH9K_BEACON_RESET_TSF    0x01000000
-#define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */
-	u32 bs_dtimperiod;
-	u16 bs_cfpperiod;
-	u16 bs_cfpmaxduration;
-	u32 bs_cfpnext;
-	u16 bs_timoffset;
-	u16 bs_bmissthreshold;
-	u32 bs_sleepduration;
-	u32 bs_tsfoor_threshold;
-};
-
-struct chan_centers {
-	u16 synth_center;
-	u16 ctl_center;
-	u16 ext_center;
-};
-
-enum {
-	ATH9K_RESET_POWER_ON,
-	ATH9K_RESET_WARM,
-	ATH9K_RESET_COLD,
-};
-
-struct ath9k_hw_version {
-	u32 magic;
-	u16 devid;
-	u16 subvendorid;
-	u32 macVersion;
-	u16 macRev;
-	u16 phyRev;
-	u16 analog5GhzRev;
-	u16 analog2GhzRev;
-};
-
-struct ath_hw {
-	struct ath_softc *ah_sc;
-	struct ath9k_hw_version hw_version;
-	struct ath9k_ops_config config;
-	struct ath9k_hw_capabilities caps;
-	struct ath9k_regulatory regulatory;
-	struct ath9k_channel channels[38];
-	struct ath9k_channel *curchan;
-
-	union {
-		struct ar5416_eeprom_def def;
-		struct ar5416_eeprom_4k map4k;
-	} eeprom;
-	const struct eeprom_ops *eep_ops;
-	enum ath9k_eep_map eep_map;
-
-	bool sw_mgmt_crypto;
-	bool is_pciexpress;
-	u8 macaddr[ETH_ALEN];
-	u16 tx_trig_level;
-	u16 rfsilent;
-	u32 rfkill_gpio;
-	u32 rfkill_polarity;
-	u32 btactive_gpio;
-	u32 wlanactive_gpio;
-	u32 ah_flags;
-
-	enum nl80211_iftype opmode;
-	enum ath9k_power_mode power_mode;
-	enum ath9k_power_mode restore_mode;
-
-	struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
-	struct ar5416Stats stats;
-	struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
-
-	int16_t curchan_rad_index;
-	u32 mask_reg;
-	u32 txok_interrupt_mask;
-	u32 txerr_interrupt_mask;
-	u32 txdesc_interrupt_mask;
-	u32 txeol_interrupt_mask;
-	u32 txurn_interrupt_mask;
-	bool chip_fullsleep;
-	u32 atim_window;
-	u16 antenna_switch_swap;
-	enum ath9k_ant_setting diversity_control;
-
-	/* Calibration */
-	enum hal_cal_types supp_cals;
-	struct hal_cal_list iq_caldata;
-	struct hal_cal_list adcgain_caldata;
-	struct hal_cal_list adcdc_calinitdata;
-	struct hal_cal_list adcdc_caldata;
-	struct hal_cal_list *cal_list;
-	struct hal_cal_list *cal_list_last;
-	struct hal_cal_list *cal_list_curr;
-#define totalPowerMeasI meas0.unsign
-#define totalPowerMeasQ meas1.unsign
-#define totalIqCorrMeas meas2.sign
-#define totalAdcIOddPhase  meas0.unsign
-#define totalAdcIEvenPhase meas1.unsign
-#define totalAdcQOddPhase  meas2.unsign
-#define totalAdcQEvenPhase meas3.unsign
-#define totalAdcDcOffsetIOddPhase  meas0.sign
-#define totalAdcDcOffsetIEvenPhase meas1.sign
-#define totalAdcDcOffsetQOddPhase  meas2.sign
-#define totalAdcDcOffsetQEvenPhase meas3.sign
-	union {
-		u32 unsign[AR5416_MAX_CHAINS];
-		int32_t sign[AR5416_MAX_CHAINS];
-	} meas0;
-	union {
-		u32 unsign[AR5416_MAX_CHAINS];
-		int32_t sign[AR5416_MAX_CHAINS];
-	} meas1;
-	union {
-		u32 unsign[AR5416_MAX_CHAINS];
-		int32_t sign[AR5416_MAX_CHAINS];
-	} meas2;
-	union {
-		u32 unsign[AR5416_MAX_CHAINS];
-		int32_t sign[AR5416_MAX_CHAINS];
-	} meas3;
-	u16 cal_samples;
-
-	u32 sta_id1_defaults;
-	u32 misc_mode;
-	enum {
-		AUTO_32KHZ,
-		USE_32KHZ,
-		DONT_USE_32KHZ,
-	} enable_32kHz_clock;
-
-	/* RF */
-	u32 *analogBank0Data;
-	u32 *analogBank1Data;
-	u32 *analogBank2Data;
-	u32 *analogBank3Data;
-	u32 *analogBank6Data;
-	u32 *analogBank6TPCData;
-	u32 *analogBank7Data;
-	u32 *addac5416_21;
-	u32 *bank6Temp;
-
-	int16_t txpower_indexoffset;
-	u32 beacon_interval;
-	u32 slottime;
-	u32 acktimeout;
-	u32 ctstimeout;
-	u32 globaltxtimeout;
-	u8 gbeacon_rate;
-
-	/* ANI */
-	u32 proc_phyerr;
-	bool has_hw_phycounters;
-	u32 aniperiod;
-	struct ar5416AniState *curani;
-	struct ar5416AniState ani[255];
-	int totalSizeDesired[5];
-	int coarse_high[5];
-	int coarse_low[5];
-	int firpwr[5];
-	enum ath9k_ani_cmd ani_function;
-
-	u32 intr_txqs;
-	bool intr_mitigation;
-	enum ath9k_ht_extprotspacing extprotspacing;
-	u8 txchainmask;
-	u8 rxchainmask;
-
-	u32 originalGain[22];
-	int initPDADC;
-	int PDADCdelta;
-
-	struct ar5416IniArray iniModes;
-	struct ar5416IniArray iniCommon;
-	struct ar5416IniArray iniBank0;
-	struct ar5416IniArray iniBB_RfGain;
-	struct ar5416IniArray iniBank1;
-	struct ar5416IniArray iniBank2;
-	struct ar5416IniArray iniBank3;
-	struct ar5416IniArray iniBank6;
-	struct ar5416IniArray iniBank6TPC;
-	struct ar5416IniArray iniBank7;
-	struct ar5416IniArray iniAddac;
-	struct ar5416IniArray iniPcieSerdes;
-	struct ar5416IniArray iniModesAdditional;
-	struct ar5416IniArray iniModesRxGain;
-	struct ar5416IniArray iniModesTxGain;
-};
-
-/* Attach, Detach, Reset */
-const char *ath9k_hw_probe(u16 vendorid, u16 devid);
-void ath9k_hw_detach(struct ath_hw *ah);
-struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error);
-void ath9k_hw_rfdetach(struct ath_hw *ah);
-int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
-		   bool bChannelChange);
-bool ath9k_hw_fill_cap_info(struct ath_hw *ah);
-bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
-			    u32 capability, u32 *result);
-bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
-			    u32 capability, u32 setting, int *status);
-
-/* Key Cache Management */
-bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
-bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac);
-bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
-				 const struct ath9k_keyval *k,
-				 const u8 *mac);
-bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry);
-
-/* GPIO / RFKILL / Antennae */
-void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
-u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
-void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
-			 u32 ah_signal_type);
-void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-void ath9k_enable_rfkill(struct ath_hw *ah);
-#endif
-u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
-void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
-bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
-			       enum ath9k_ant_setting settings,
-			       struct ath9k_channel *chan,
-			       u8 *tx_chainmask, u8 *rx_chainmask,
-			       u8 *antenna_cfgd);
-
-/* General Operation */
-bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
-u32 ath9k_hw_reverse_bits(u32 val, u32 n);
-bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high);
-u16 ath9k_hw_computetxtime(struct ath_hw *ah, struct ath_rate_table *rates,
-			   u32 frameLen, u16 rateix, bool shortPreamble);
-void ath9k_hw_get_channel_centers(struct ath_hw *ah,
-				  struct ath9k_channel *chan,
-				  struct chan_centers *centers);
-u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
-void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
-bool ath9k_hw_phy_disable(struct ath_hw *ah);
-bool ath9k_hw_disable(struct ath_hw *ah);
-bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
-void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac);
-void ath9k_hw_setopmode(struct ath_hw *ah);
-void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
-void ath9k_hw_setbssidmask(struct ath_softc *sc);
-void ath9k_hw_write_associd(struct ath_softc *sc);
-u64 ath9k_hw_gettsf64(struct ath_hw *ah);
-void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
-void ath9k_hw_reset_tsf(struct ath_hw *ah);
-bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
-bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
-void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode);
-void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
-void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
-				    const struct ath9k_beacon_state *bs);
-bool ath9k_hw_setpower(struct ath_hw *ah,
-		       enum ath9k_power_mode mode);
-void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore);
-
-/* Interrupt Handling */
-bool ath9k_hw_intrpend(struct ath_hw *ah);
-bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked);
-enum ath9k_int ath9k_hw_intrget(struct ath_hw *ah);
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
-
-void ath9k_hw_btcoex_enable(struct ath_hw *ah);
-
-#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/initvals.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/initvals.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/initvals.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/initvals.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,4848 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-static const u32 ar5416Modes[][6] = {
-    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
-    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
-    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
-    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
-    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
-    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
-    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
-    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
-    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
-    { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
-    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de },
-    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
-    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
-    { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 },
-    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
-    { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
-    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
-    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
-    { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 },
-    { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b },
-    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
-    { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
-    { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
-    { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
-    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
-    { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
-    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
-    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
-    { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
-    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
-    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
-    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
-    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
-    { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
-    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
-    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
-    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
-    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
-    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
-    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
-    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
-    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
-    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
-    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
-    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
-    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
-    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-};
-
-static const u32 ar5416Common[][2] = {
-    { 0x0000000c, 0x00000000 },
-    { 0x00000030, 0x00020015 },
-    { 0x00000034, 0x00000005 },
-    { 0x00000040, 0x00000000 },
-    { 0x00000044, 0x00000008 },
-    { 0x00000048, 0x00000008 },
-    { 0x0000004c, 0x00000010 },
-    { 0x00000050, 0x00000000 },
-    { 0x00000054, 0x0000001f },
-    { 0x00000800, 0x00000000 },
-    { 0x00000804, 0x00000000 },
-    { 0x00000808, 0x00000000 },
-    { 0x0000080c, 0x00000000 },
-    { 0x00000810, 0x00000000 },
-    { 0x00000814, 0x00000000 },
-    { 0x00000818, 0x00000000 },
-    { 0x0000081c, 0x00000000 },
-    { 0x00000820, 0x00000000 },
-    { 0x00000824, 0x00000000 },
-    { 0x00001040, 0x002ffc0f },
-    { 0x00001044, 0x002ffc0f },
-    { 0x00001048, 0x002ffc0f },
-    { 0x0000104c, 0x002ffc0f },
-    { 0x00001050, 0x002ffc0f },
-    { 0x00001054, 0x002ffc0f },
-    { 0x00001058, 0x002ffc0f },
-    { 0x0000105c, 0x002ffc0f },
-    { 0x00001060, 0x002ffc0f },
-    { 0x00001064, 0x002ffc0f },
-    { 0x00001230, 0x00000000 },
-    { 0x00001270, 0x00000000 },
-    { 0x00001038, 0x00000000 },
-    { 0x00001078, 0x00000000 },
-    { 0x000010b8, 0x00000000 },
-    { 0x000010f8, 0x00000000 },
-    { 0x00001138, 0x00000000 },
-    { 0x00001178, 0x00000000 },
-    { 0x000011b8, 0x00000000 },
-    { 0x000011f8, 0x00000000 },
-    { 0x00001238, 0x00000000 },
-    { 0x00001278, 0x00000000 },
-    { 0x000012b8, 0x00000000 },
-    { 0x000012f8, 0x00000000 },
-    { 0x00001338, 0x00000000 },
-    { 0x00001378, 0x00000000 },
-    { 0x000013b8, 0x00000000 },
-    { 0x000013f8, 0x00000000 },
-    { 0x00001438, 0x00000000 },
-    { 0x00001478, 0x00000000 },
-    { 0x000014b8, 0x00000000 },
-    { 0x000014f8, 0x00000000 },
-    { 0x00001538, 0x00000000 },
-    { 0x00001578, 0x00000000 },
-    { 0x000015b8, 0x00000000 },
-    { 0x000015f8, 0x00000000 },
-    { 0x00001638, 0x00000000 },
-    { 0x00001678, 0x00000000 },
-    { 0x000016b8, 0x00000000 },
-    { 0x000016f8, 0x00000000 },
-    { 0x00001738, 0x00000000 },
-    { 0x00001778, 0x00000000 },
-    { 0x000017b8, 0x00000000 },
-    { 0x000017f8, 0x00000000 },
-    { 0x0000103c, 0x00000000 },
-    { 0x0000107c, 0x00000000 },
-    { 0x000010bc, 0x00000000 },
-    { 0x000010fc, 0x00000000 },
-    { 0x0000113c, 0x00000000 },
-    { 0x0000117c, 0x00000000 },
-    { 0x000011bc, 0x00000000 },
-    { 0x000011fc, 0x00000000 },
-    { 0x0000123c, 0x00000000 },
-    { 0x0000127c, 0x00000000 },
-    { 0x000012bc, 0x00000000 },
-    { 0x000012fc, 0x00000000 },
-    { 0x0000133c, 0x00000000 },
-    { 0x0000137c, 0x00000000 },
-    { 0x000013bc, 0x00000000 },
-    { 0x000013fc, 0x00000000 },
-    { 0x0000143c, 0x00000000 },
-    { 0x0000147c, 0x00000000 },
-    { 0x00004030, 0x00000002 },
-    { 0x0000403c, 0x00000002 },
-    { 0x00007010, 0x00000000 },
-    { 0x00007038, 0x000004c2 },
-    { 0x00008004, 0x00000000 },
-    { 0x00008008, 0x00000000 },
-    { 0x0000800c, 0x00000000 },
-    { 0x00008018, 0x00000700 },
-    { 0x00008020, 0x00000000 },
-    { 0x00008038, 0x00000000 },
-    { 0x0000803c, 0x00000000 },
-    { 0x00008048, 0x40000000 },
-    { 0x00008054, 0x00000000 },
-    { 0x00008058, 0x00000000 },
-    { 0x0000805c, 0x000fc78f },
-    { 0x00008060, 0x0000000f },
-    { 0x00008064, 0x00000000 },
-    { 0x000080c0, 0x2a82301a },
-    { 0x000080c4, 0x05dc01e0 },
-    { 0x000080c8, 0x1f402710 },
-    { 0x000080cc, 0x01f40000 },
-    { 0x000080d0, 0x00001e00 },
-    { 0x000080d4, 0x00000000 },
-    { 0x000080d8, 0x00400000 },
-    { 0x000080e0, 0xffffffff },
-    { 0x000080e4, 0x0000ffff },
-    { 0x000080e8, 0x003f3f3f },
-    { 0x000080ec, 0x00000000 },
-    { 0x000080f0, 0x00000000 },
-    { 0x000080f4, 0x00000000 },
-    { 0x000080f8, 0x00000000 },
-    { 0x000080fc, 0x00020000 },
-    { 0x00008100, 0x00020000 },
-    { 0x00008104, 0x00000001 },
-    { 0x00008108, 0x00000052 },
-    { 0x0000810c, 0x00000000 },
-    { 0x00008110, 0x00000168 },
-    { 0x00008118, 0x000100aa },
-    { 0x0000811c, 0x00003210 },
-    { 0x00008120, 0x08f04800 },
-    { 0x00008124, 0x00000000 },
-    { 0x00008128, 0x00000000 },
-    { 0x0000812c, 0x00000000 },
-    { 0x00008130, 0x00000000 },
-    { 0x00008134, 0x00000000 },
-    { 0x00008138, 0x00000000 },
-    { 0x0000813c, 0x00000000 },
-    { 0x00008144, 0xffffffff },
-    { 0x00008168, 0x00000000 },
-    { 0x0000816c, 0x00000000 },
-    { 0x00008170, 0x32143320 },
-    { 0x00008174, 0xfaa4fa50 },
-    { 0x00008178, 0x00000100 },
-    { 0x0000817c, 0x00000000 },
-    { 0x000081c4, 0x00000000 },
-    { 0x000081d0, 0x00003210 },
-    { 0x000081ec, 0x00000000 },
-    { 0x000081f0, 0x00000000 },
-    { 0x000081f4, 0x00000000 },
-    { 0x000081f8, 0x00000000 },
-    { 0x000081fc, 0x00000000 },
-    { 0x00008200, 0x00000000 },
-    { 0x00008204, 0x00000000 },
-    { 0x00008208, 0x00000000 },
-    { 0x0000820c, 0x00000000 },
-    { 0x00008210, 0x00000000 },
-    { 0x00008214, 0x00000000 },
-    { 0x00008218, 0x00000000 },
-    { 0x0000821c, 0x00000000 },
-    { 0x00008220, 0x00000000 },
-    { 0x00008224, 0x00000000 },
-    { 0x00008228, 0x00000000 },
-    { 0x0000822c, 0x00000000 },
-    { 0x00008230, 0x00000000 },
-    { 0x00008234, 0x00000000 },
-    { 0x00008238, 0x00000000 },
-    { 0x0000823c, 0x00000000 },
-    { 0x00008240, 0x00100000 },
-    { 0x00008244, 0x0010f400 },
-    { 0x00008248, 0x00000100 },
-    { 0x0000824c, 0x0001e800 },
-    { 0x00008250, 0x00000000 },
-    { 0x00008254, 0x00000000 },
-    { 0x00008258, 0x00000000 },
-    { 0x0000825c, 0x400000ff },
-    { 0x00008260, 0x00080922 },
-    { 0x00008270, 0x00000000 },
-    { 0x00008274, 0x40000000 },
-    { 0x00008278, 0x003e4180 },
-    { 0x0000827c, 0x00000000 },
-    { 0x00008284, 0x0000002c },
-    { 0x00008288, 0x0000002c },
-    { 0x0000828c, 0x00000000 },
-    { 0x00008294, 0x00000000 },
-    { 0x00008298, 0x00000000 },
-    { 0x00008300, 0x00000000 },
-    { 0x00008304, 0x00000000 },
-    { 0x00008308, 0x00000000 },
-    { 0x0000830c, 0x00000000 },
-    { 0x00008310, 0x00000000 },
-    { 0x00008314, 0x00000000 },
-    { 0x00008318, 0x00000000 },
-    { 0x00008328, 0x00000000 },
-    { 0x0000832c, 0x00000007 },
-    { 0x00008330, 0x00000302 },
-    { 0x00008334, 0x00000e00 },
-    { 0x00008338, 0x00070000 },
-    { 0x0000833c, 0x00000000 },
-    { 0x00008340, 0x000107ff },
-    { 0x00009808, 0x00000000 },
-    { 0x0000980c, 0xad848e19 },
-    { 0x00009810, 0x7d14e000 },
-    { 0x00009814, 0x9c0a9f6b },
-    { 0x0000981c, 0x00000000 },
-    { 0x0000982c, 0x0000a000 },
-    { 0x00009830, 0x00000000 },
-    { 0x0000983c, 0x00200400 },
-    { 0x00009840, 0x206a002e },
-    { 0x0000984c, 0x1284233c },
-    { 0x00009854, 0x00000859 },
-    { 0x00009900, 0x00000000 },
-    { 0x00009904, 0x00000000 },
-    { 0x00009908, 0x00000000 },
-    { 0x0000990c, 0x00000000 },
-    { 0x0000991c, 0x10000fff },
-    { 0x00009920, 0x05100000 },
-    { 0x0000a920, 0x05100000 },
-    { 0x0000b920, 0x05100000 },
-    { 0x00009928, 0x00000001 },
-    { 0x0000992c, 0x00000004 },
-    { 0x00009934, 0x1e1f2022 },
-    { 0x00009938, 0x0a0b0c0d },
-    { 0x0000993c, 0x00000000 },
-    { 0x00009948, 0x9280b212 },
-    { 0x0000994c, 0x00020028 },
-    { 0x00009954, 0x5d50e188 },
-    { 0x00009958, 0x00081fff },
-    { 0x0000c95c, 0x004b6a8e },
-    { 0x0000c968, 0x000003ce },
-    { 0x00009970, 0x190fb515 },
-    { 0x00009974, 0x00000000 },
-    { 0x00009978, 0x00000001 },
-    { 0x0000997c, 0x00000000 },
-    { 0x00009980, 0x00000000 },
-    { 0x00009984, 0x00000000 },
-    { 0x00009988, 0x00000000 },
-    { 0x0000998c, 0x00000000 },
-    { 0x00009990, 0x00000000 },
-    { 0x00009994, 0x00000000 },
-    { 0x00009998, 0x00000000 },
-    { 0x0000999c, 0x00000000 },
-    { 0x000099a0, 0x00000000 },
-    { 0x000099a4, 0x00000001 },
-    { 0x000099a8, 0x001fff00 },
-    { 0x000099ac, 0x00000000 },
-    { 0x000099b0, 0x03051000 },
-    { 0x000099dc, 0x00000000 },
-    { 0x000099e0, 0x00000200 },
-    { 0x000099e4, 0xaaaaaaaa },
-    { 0x000099e8, 0x3c466478 },
-    { 0x000099ec, 0x000000aa },
-    { 0x000099fc, 0x00001042 },
-    { 0x00009b00, 0x00000000 },
-    { 0x00009b04, 0x00000001 },
-    { 0x00009b08, 0x00000002 },
-    { 0x00009b0c, 0x00000003 },
-    { 0x00009b10, 0x00000004 },
-    { 0x00009b14, 0x00000005 },
-    { 0x00009b18, 0x00000008 },
-    { 0x00009b1c, 0x00000009 },
-    { 0x00009b20, 0x0000000a },
-    { 0x00009b24, 0x0000000b },
-    { 0x00009b28, 0x0000000c },
-    { 0x00009b2c, 0x0000000d },
-    { 0x00009b30, 0x00000010 },
-    { 0x00009b34, 0x00000011 },
-    { 0x00009b38, 0x00000012 },
-    { 0x00009b3c, 0x00000013 },
-    { 0x00009b40, 0x00000014 },
-    { 0x00009b44, 0x00000015 },
-    { 0x00009b48, 0x00000018 },
-    { 0x00009b4c, 0x00000019 },
-    { 0x00009b50, 0x0000001a },
-    { 0x00009b54, 0x0000001b },
-    { 0x00009b58, 0x0000001c },
-    { 0x00009b5c, 0x0000001d },
-    { 0x00009b60, 0x00000020 },
-    { 0x00009b64, 0x00000021 },
-    { 0x00009b68, 0x00000022 },
-    { 0x00009b6c, 0x00000023 },
-    { 0x00009b70, 0x00000024 },
-    { 0x00009b74, 0x00000025 },
-    { 0x00009b78, 0x00000028 },
-    { 0x00009b7c, 0x00000029 },
-    { 0x00009b80, 0x0000002a },
-    { 0x00009b84, 0x0000002b },
-    { 0x00009b88, 0x0000002c },
-    { 0x00009b8c, 0x0000002d },
-    { 0x00009b90, 0x00000030 },
-    { 0x00009b94, 0x00000031 },
-    { 0x00009b98, 0x00000032 },
-    { 0x00009b9c, 0x00000033 },
-    { 0x00009ba0, 0x00000034 },
-    { 0x00009ba4, 0x00000035 },
-    { 0x00009ba8, 0x00000035 },
-    { 0x00009bac, 0x00000035 },
-    { 0x00009bb0, 0x00000035 },
-    { 0x00009bb4, 0x00000035 },
-    { 0x00009bb8, 0x00000035 },
-    { 0x00009bbc, 0x00000035 },
-    { 0x00009bc0, 0x00000035 },
-    { 0x00009bc4, 0x00000035 },
-    { 0x00009bc8, 0x00000035 },
-    { 0x00009bcc, 0x00000035 },
-    { 0x00009bd0, 0x00000035 },
-    { 0x00009bd4, 0x00000035 },
-    { 0x00009bd8, 0x00000035 },
-    { 0x00009bdc, 0x00000035 },
-    { 0x00009be0, 0x00000035 },
-    { 0x00009be4, 0x00000035 },
-    { 0x00009be8, 0x00000035 },
-    { 0x00009bec, 0x00000035 },
-    { 0x00009bf0, 0x00000035 },
-    { 0x00009bf4, 0x00000035 },
-    { 0x00009bf8, 0x00000010 },
-    { 0x00009bfc, 0x0000001a },
-    { 0x0000a210, 0x40806333 },
-    { 0x0000a214, 0x00106c10 },
-    { 0x0000a218, 0x009c4060 },
-    { 0x0000a220, 0x018830c6 },
-    { 0x0000a224, 0x00000400 },
-    { 0x0000a228, 0x00000bb5 },
-    { 0x0000a22c, 0x00000011 },
-    { 0x0000a234, 0x20202020 },
-    { 0x0000a238, 0x20202020 },
-    { 0x0000a23c, 0x13c889af },
-    { 0x0000a240, 0x38490a20 },
-    { 0x0000a244, 0x00007bb6 },
-    { 0x0000a248, 0x0fff3ffc },
-    { 0x0000a24c, 0x00000001 },
-    { 0x0000a250, 0x0000a000 },
-    { 0x0000a254, 0x00000000 },
-    { 0x0000a258, 0x0cc75380 },
-    { 0x0000a25c, 0x0f0f0f01 },
-    { 0x0000a260, 0xdfa91f01 },
-    { 0x0000a268, 0x00000000 },
-    { 0x0000a26c, 0x0ebae9c6 },
-    { 0x0000b26c, 0x0ebae9c6 },
-    { 0x0000c26c, 0x0ebae9c6 },
-    { 0x0000d270, 0x00820820 },
-    { 0x0000a278, 0x1ce739ce },
-    { 0x0000a27c, 0x051701ce },
-    { 0x0000a338, 0x00000000 },
-    { 0x0000a33c, 0x00000000 },
-    { 0x0000a340, 0x00000000 },
-    { 0x0000a344, 0x00000000 },
-    { 0x0000a348, 0x3fffffff },
-    { 0x0000a34c, 0x3fffffff },
-    { 0x0000a350, 0x3fffffff },
-    { 0x0000a354, 0x0003ffff },
-    { 0x0000a358, 0x79a8aa1f },
-    { 0x0000d35c, 0x07ffffef },
-    { 0x0000d360, 0x0fffffe7 },
-    { 0x0000d364, 0x17ffffe5 },
-    { 0x0000d368, 0x1fffffe4 },
-    { 0x0000d36c, 0x37ffffe3 },
-    { 0x0000d370, 0x3fffffe3 },
-    { 0x0000d374, 0x57ffffe3 },
-    { 0x0000d378, 0x5fffffe2 },
-    { 0x0000d37c, 0x7fffffe2 },
-    { 0x0000d380, 0x7f3c7bba },
-    { 0x0000d384, 0xf3307ff0 },
-    { 0x0000a388, 0x08000000 },
-    { 0x0000a38c, 0x20202020 },
-    { 0x0000a390, 0x20202020 },
-    { 0x0000a394, 0x1ce739ce },
-    { 0x0000a398, 0x000001ce },
-    { 0x0000a39c, 0x00000001 },
-    { 0x0000a3a0, 0x00000000 },
-    { 0x0000a3a4, 0x00000000 },
-    { 0x0000a3a8, 0x00000000 },
-    { 0x0000a3ac, 0x00000000 },
-    { 0x0000a3b0, 0x00000000 },
-    { 0x0000a3b4, 0x00000000 },
-    { 0x0000a3b8, 0x00000000 },
-    { 0x0000a3bc, 0x00000000 },
-    { 0x0000a3c0, 0x00000000 },
-    { 0x0000a3c4, 0x00000000 },
-    { 0x0000a3c8, 0x00000246 },
-    { 0x0000a3cc, 0x20202020 },
-    { 0x0000a3d0, 0x20202020 },
-    { 0x0000a3d4, 0x20202020 },
-    { 0x0000a3dc, 0x1ce739ce },
-    { 0x0000a3e0, 0x000001ce },
-};
-
-static const u32 ar5416Bank0[][2] = {
-    { 0x000098b0, 0x1e5795e5 },
-    { 0x000098e0, 0x02008020 },
-};
-
-static const u32 ar5416BB_RfGain[][3] = {
-    { 0x00009a00, 0x00000000, 0x00000000 },
-    { 0x00009a04, 0x00000040, 0x00000040 },
-    { 0x00009a08, 0x00000080, 0x00000080 },
-    { 0x00009a0c, 0x000001a1, 0x00000141 },
-    { 0x00009a10, 0x000001e1, 0x00000181 },
-    { 0x00009a14, 0x00000021, 0x000001c1 },
-    { 0x00009a18, 0x00000061, 0x00000001 },
-    { 0x00009a1c, 0x00000168, 0x00000041 },
-    { 0x00009a20, 0x000001a8, 0x000001a8 },
-    { 0x00009a24, 0x000001e8, 0x000001e8 },
-    { 0x00009a28, 0x00000028, 0x00000028 },
-    { 0x00009a2c, 0x00000068, 0x00000068 },
-    { 0x00009a30, 0x00000189, 0x000000a8 },
-    { 0x00009a34, 0x000001c9, 0x00000169 },
-    { 0x00009a38, 0x00000009, 0x000001a9 },
-    { 0x00009a3c, 0x00000049, 0x000001e9 },
-    { 0x00009a40, 0x00000089, 0x00000029 },
-    { 0x00009a44, 0x00000170, 0x00000069 },
-    { 0x00009a48, 0x000001b0, 0x00000190 },
-    { 0x00009a4c, 0x000001f0, 0x000001d0 },
-    { 0x00009a50, 0x00000030, 0x00000010 },
-    { 0x00009a54, 0x00000070, 0x00000050 },
-    { 0x00009a58, 0x00000191, 0x00000090 },
-    { 0x00009a5c, 0x000001d1, 0x00000151 },
-    { 0x00009a60, 0x00000011, 0x00000191 },
-    { 0x00009a64, 0x00000051, 0x000001d1 },
-    { 0x00009a68, 0x00000091, 0x00000011 },
-    { 0x00009a6c, 0x000001b8, 0x00000051 },
-    { 0x00009a70, 0x000001f8, 0x00000198 },
-    { 0x00009a74, 0x00000038, 0x000001d8 },
-    { 0x00009a78, 0x00000078, 0x00000018 },
-    { 0x00009a7c, 0x00000199, 0x00000058 },
-    { 0x00009a80, 0x000001d9, 0x00000098 },
-    { 0x00009a84, 0x00000019, 0x00000159 },
-    { 0x00009a88, 0x00000059, 0x00000199 },
-    { 0x00009a8c, 0x00000099, 0x000001d9 },
-    { 0x00009a90, 0x000000d9, 0x00000019 },
-    { 0x00009a94, 0x000000f9, 0x00000059 },
-    { 0x00009a98, 0x000000f9, 0x00000099 },
-    { 0x00009a9c, 0x000000f9, 0x000000d9 },
-    { 0x00009aa0, 0x000000f9, 0x000000f9 },
-    { 0x00009aa4, 0x000000f9, 0x000000f9 },
-    { 0x00009aa8, 0x000000f9, 0x000000f9 },
-    { 0x00009aac, 0x000000f9, 0x000000f9 },
-    { 0x00009ab0, 0x000000f9, 0x000000f9 },
-    { 0x00009ab4, 0x000000f9, 0x000000f9 },
-    { 0x00009ab8, 0x000000f9, 0x000000f9 },
-    { 0x00009abc, 0x000000f9, 0x000000f9 },
-    { 0x00009ac0, 0x000000f9, 0x000000f9 },
-    { 0x00009ac4, 0x000000f9, 0x000000f9 },
-    { 0x00009ac8, 0x000000f9, 0x000000f9 },
-    { 0x00009acc, 0x000000f9, 0x000000f9 },
-    { 0x00009ad0, 0x000000f9, 0x000000f9 },
-    { 0x00009ad4, 0x000000f9, 0x000000f9 },
-    { 0x00009ad8, 0x000000f9, 0x000000f9 },
-    { 0x00009adc, 0x000000f9, 0x000000f9 },
-    { 0x00009ae0, 0x000000f9, 0x000000f9 },
-    { 0x00009ae4, 0x000000f9, 0x000000f9 },
-    { 0x00009ae8, 0x000000f9, 0x000000f9 },
-    { 0x00009aec, 0x000000f9, 0x000000f9 },
-    { 0x00009af0, 0x000000f9, 0x000000f9 },
-    { 0x00009af4, 0x000000f9, 0x000000f9 },
-    { 0x00009af8, 0x000000f9, 0x000000f9 },
-    { 0x00009afc, 0x000000f9, 0x000000f9 },
-};
-
-static const u32 ar5416Bank1[][2] = {
-    { 0x000098b0, 0x02108421 },
-    { 0x000098ec, 0x00000008 },
-};
-
-static const u32 ar5416Bank2[][2] = {
-    { 0x000098b0, 0x0e73ff17 },
-    { 0x000098e0, 0x00000420 },
-};
-
-static const u32 ar5416Bank3[][3] = {
-    { 0x000098f0, 0x01400018, 0x01c00018 },
-};
-
-static const u32 ar5416Bank6[][3] = {
-
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00e00000, 0x00e00000 },
-    { 0x0000989c, 0x005e0000, 0x005e0000 },
-    { 0x0000989c, 0x00120000, 0x00120000 },
-    { 0x0000989c, 0x00620000, 0x00620000 },
-    { 0x0000989c, 0x00020000, 0x00020000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
-    { 0x0000989c, 0x005f0000, 0x005f0000 },
-    { 0x0000989c, 0x00870000, 0x00870000 },
-    { 0x0000989c, 0x00f90000, 0x00f90000 },
-    { 0x0000989c, 0x007b0000, 0x007b0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00f50000, 0x00f50000 },
-    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
-    { 0x0000989c, 0x00110000, 0x00110000 },
-    { 0x0000989c, 0x006100a8, 0x006100a8 },
-    { 0x0000989c, 0x004210a2, 0x004210a2 },
-    { 0x0000989c, 0x0014008f, 0x0014008f },
-    { 0x0000989c, 0x00c40003, 0x00c40003 },
-    { 0x0000989c, 0x003000f2, 0x003000f2 },
-    { 0x0000989c, 0x00440016, 0x00440016 },
-    { 0x0000989c, 0x00410040, 0x00410040 },
-    { 0x0000989c, 0x0001805e, 0x0001805e },
-    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
-    { 0x0000989c, 0x000000f1, 0x000000f1 },
-    { 0x0000989c, 0x00002081, 0x00002081 },
-    { 0x0000989c, 0x000000d4, 0x000000d4 },
-    { 0x000098d0, 0x0000000f, 0x0010000f },
-};
-
-static const u32 ar5416Bank6TPC[][3] = {
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00e00000, 0x00e00000 },
-    { 0x0000989c, 0x005e0000, 0x005e0000 },
-    { 0x0000989c, 0x00120000, 0x00120000 },
-    { 0x0000989c, 0x00620000, 0x00620000 },
-    { 0x0000989c, 0x00020000, 0x00020000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
-    { 0x0000989c, 0x005f0000, 0x005f0000 },
-    { 0x0000989c, 0x00870000, 0x00870000 },
-    { 0x0000989c, 0x00f90000, 0x00f90000 },
-    { 0x0000989c, 0x007b0000, 0x007b0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00f50000, 0x00f50000 },
-    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
-    { 0x0000989c, 0x00110000, 0x00110000 },
-    { 0x0000989c, 0x006100a8, 0x006100a8 },
-    { 0x0000989c, 0x00423022, 0x00423022 },
-    { 0x0000989c, 0x201400df, 0x201400df },
-    { 0x0000989c, 0x00c40002, 0x00c40002 },
-    { 0x0000989c, 0x003000f2, 0x003000f2 },
-    { 0x0000989c, 0x00440016, 0x00440016 },
-    { 0x0000989c, 0x00410040, 0x00410040 },
-    { 0x0000989c, 0x0001805e, 0x0001805e },
-    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
-    { 0x0000989c, 0x000000e1, 0x000000e1 },
-    { 0x0000989c, 0x00007081, 0x00007081 },
-    { 0x0000989c, 0x000000d4, 0x000000d4 },
-    { 0x000098d0, 0x0000000f, 0x0010000f },
-};
-
-static const u32 ar5416Bank7[][2] = {
-    { 0x0000989c, 0x00000500 },
-    { 0x0000989c, 0x00000800 },
-    { 0x000098cc, 0x0000000e },
-};
-
-static const u32 ar5416Addac[][2] = {
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000003 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x0000000c },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000030 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000060 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000058 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x000098cc,  0x00000000 },
-};
-
-static const u32 ar5416Modes_9100[][6] = {
-    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
-    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
-    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
-    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
-    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
-    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
-    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
-    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
-    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
-    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
-    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
-    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e },
-    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
-    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
-    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
-    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
-    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
-    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
-    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
-    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d },
-    { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 },
-    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
-    { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e },
-    { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff },
-#ifdef TB243
-    { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
-    { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
-    { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
-    { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 },
-#else
-    { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
-    { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
-    { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
-    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
-#endif
-    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 },
-    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
-    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
-    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
-    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
-    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
-    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
-    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
-    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
-    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
-    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
-    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
-    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
-    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
-    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
-    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
-    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
-    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
-    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
-    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
-    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
-    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-};
-
-static const u32 ar5416Common_9100[][2] = {
-    { 0x0000000c, 0x00000000 },
-    { 0x00000030, 0x00020015 },
-    { 0x00000034, 0x00000005 },
-    { 0x00000040, 0x00000000 },
-    { 0x00000044, 0x00000008 },
-    { 0x00000048, 0x00000008 },
-    { 0x0000004c, 0x00000010 },
-    { 0x00000050, 0x00000000 },
-    { 0x00000054, 0x0000001f },
-    { 0x00000800, 0x00000000 },
-    { 0x00000804, 0x00000000 },
-    { 0x00000808, 0x00000000 },
-    { 0x0000080c, 0x00000000 },
-    { 0x00000810, 0x00000000 },
-    { 0x00000814, 0x00000000 },
-    { 0x00000818, 0x00000000 },
-    { 0x0000081c, 0x00000000 },
-    { 0x00000820, 0x00000000 },
-    { 0x00000824, 0x00000000 },
-    { 0x00001040, 0x002ffc0f },
-    { 0x00001044, 0x002ffc0f },
-    { 0x00001048, 0x002ffc0f },
-    { 0x0000104c, 0x002ffc0f },
-    { 0x00001050, 0x002ffc0f },
-    { 0x00001054, 0x002ffc0f },
-    { 0x00001058, 0x002ffc0f },
-    { 0x0000105c, 0x002ffc0f },
-    { 0x00001060, 0x002ffc0f },
-    { 0x00001064, 0x002ffc0f },
-    { 0x00001230, 0x00000000 },
-    { 0x00001270, 0x00000000 },
-    { 0x00001038, 0x00000000 },
-    { 0x00001078, 0x00000000 },
-    { 0x000010b8, 0x00000000 },
-    { 0x000010f8, 0x00000000 },
-    { 0x00001138, 0x00000000 },
-    { 0x00001178, 0x00000000 },
-    { 0x000011b8, 0x00000000 },
-    { 0x000011f8, 0x00000000 },
-    { 0x00001238, 0x00000000 },
-    { 0x00001278, 0x00000000 },
-    { 0x000012b8, 0x00000000 },
-    { 0x000012f8, 0x00000000 },
-    { 0x00001338, 0x00000000 },
-    { 0x00001378, 0x00000000 },
-    { 0x000013b8, 0x00000000 },
-    { 0x000013f8, 0x00000000 },
-    { 0x00001438, 0x00000000 },
-    { 0x00001478, 0x00000000 },
-    { 0x000014b8, 0x00000000 },
-    { 0x000014f8, 0x00000000 },
-    { 0x00001538, 0x00000000 },
-    { 0x00001578, 0x00000000 },
-    { 0x000015b8, 0x00000000 },
-    { 0x000015f8, 0x00000000 },
-    { 0x00001638, 0x00000000 },
-    { 0x00001678, 0x00000000 },
-    { 0x000016b8, 0x00000000 },
-    { 0x000016f8, 0x00000000 },
-    { 0x00001738, 0x00000000 },
-    { 0x00001778, 0x00000000 },
-    { 0x000017b8, 0x00000000 },
-    { 0x000017f8, 0x00000000 },
-    { 0x0000103c, 0x00000000 },
-    { 0x0000107c, 0x00000000 },
-    { 0x000010bc, 0x00000000 },
-    { 0x000010fc, 0x00000000 },
-    { 0x0000113c, 0x00000000 },
-    { 0x0000117c, 0x00000000 },
-    { 0x000011bc, 0x00000000 },
-    { 0x000011fc, 0x00000000 },
-    { 0x0000123c, 0x00000000 },
-    { 0x0000127c, 0x00000000 },
-    { 0x000012bc, 0x00000000 },
-    { 0x000012fc, 0x00000000 },
-    { 0x0000133c, 0x00000000 },
-    { 0x0000137c, 0x00000000 },
-    { 0x000013bc, 0x00000000 },
-    { 0x000013fc, 0x00000000 },
-    { 0x0000143c, 0x00000000 },
-    { 0x0000147c, 0x00000000 },
-    { 0x00020010, 0x00000003 },
-    { 0x00020038, 0x000004c2 },
-    { 0x00008004, 0x00000000 },
-    { 0x00008008, 0x00000000 },
-    { 0x0000800c, 0x00000000 },
-    { 0x00008018, 0x00000700 },
-    { 0x00008020, 0x00000000 },
-    { 0x00008038, 0x00000000 },
-    { 0x0000803c, 0x00000000 },
-    { 0x00008048, 0x40000000 },
-    { 0x00008054, 0x00004000 },
-    { 0x00008058, 0x00000000 },
-    { 0x0000805c, 0x000fc78f },
-    { 0x00008060, 0x0000000f },
-    { 0x00008064, 0x00000000 },
-    { 0x000080c0, 0x2a82301a },
-    { 0x000080c4, 0x05dc01e0 },
-    { 0x000080c8, 0x1f402710 },
-    { 0x000080cc, 0x01f40000 },
-    { 0x000080d0, 0x00001e00 },
-    { 0x000080d4, 0x00000000 },
-    { 0x000080d8, 0x00400000 },
-    { 0x000080e0, 0xffffffff },
-    { 0x000080e4, 0x0000ffff },
-    { 0x000080e8, 0x003f3f3f },
-    { 0x000080ec, 0x00000000 },
-    { 0x000080f0, 0x00000000 },
-    { 0x000080f4, 0x00000000 },
-    { 0x000080f8, 0x00000000 },
-    { 0x000080fc, 0x00020000 },
-    { 0x00008100, 0x00020000 },
-    { 0x00008104, 0x00000001 },
-    { 0x00008108, 0x00000052 },
-    { 0x0000810c, 0x00000000 },
-    { 0x00008110, 0x00000168 },
-    { 0x00008118, 0x000100aa },
-    { 0x0000811c, 0x00003210 },
-    { 0x00008120, 0x08f04800 },
-    { 0x00008124, 0x00000000 },
-    { 0x00008128, 0x00000000 },
-    { 0x0000812c, 0x00000000 },
-    { 0x00008130, 0x00000000 },
-    { 0x00008134, 0x00000000 },
-    { 0x00008138, 0x00000000 },
-    { 0x0000813c, 0x00000000 },
-    { 0x00008144, 0x00000000 },
-    { 0x00008168, 0x00000000 },
-    { 0x0000816c, 0x00000000 },
-    { 0x00008170, 0x32143320 },
-    { 0x00008174, 0xfaa4fa50 },
-    { 0x00008178, 0x00000100 },
-    { 0x0000817c, 0x00000000 },
-    { 0x000081c4, 0x00000000 },
-    { 0x000081d0, 0x00003210 },
-    { 0x000081ec, 0x00000000 },
-    { 0x000081f0, 0x00000000 },
-    { 0x000081f4, 0x00000000 },
-    { 0x000081f8, 0x00000000 },
-    { 0x000081fc, 0x00000000 },
-    { 0x00008200, 0x00000000 },
-    { 0x00008204, 0x00000000 },
-    { 0x00008208, 0x00000000 },
-    { 0x0000820c, 0x00000000 },
-    { 0x00008210, 0x00000000 },
-    { 0x00008214, 0x00000000 },
-    { 0x00008218, 0x00000000 },
-    { 0x0000821c, 0x00000000 },
-    { 0x00008220, 0x00000000 },
-    { 0x00008224, 0x00000000 },
-    { 0x00008228, 0x00000000 },
-    { 0x0000822c, 0x00000000 },
-    { 0x00008230, 0x00000000 },
-    { 0x00008234, 0x00000000 },
-    { 0x00008238, 0x00000000 },
-    { 0x0000823c, 0x00000000 },
-    { 0x00008240, 0x00100000 },
-    { 0x00008244, 0x0010f400 },
-    { 0x00008248, 0x00000100 },
-    { 0x0000824c, 0x0001e800 },
-    { 0x00008250, 0x00000000 },
-    { 0x00008254, 0x00000000 },
-    { 0x00008258, 0x00000000 },
-    { 0x0000825c, 0x400000ff },
-    { 0x00008260, 0x00080922 },
-    { 0x00008270, 0x00000000 },
-    { 0x00008274, 0x40000000 },
-    { 0x00008278, 0x003e4180 },
-    { 0x0000827c, 0x00000000 },
-    { 0x00008284, 0x0000002c },
-    { 0x00008288, 0x0000002c },
-    { 0x0000828c, 0x00000000 },
-    { 0x00008294, 0x00000000 },
-    { 0x00008298, 0x00000000 },
-    { 0x00008300, 0x00000000 },
-    { 0x00008304, 0x00000000 },
-    { 0x00008308, 0x00000000 },
-    { 0x0000830c, 0x00000000 },
-    { 0x00008310, 0x00000000 },
-    { 0x00008314, 0x00000000 },
-    { 0x00008318, 0x00000000 },
-    { 0x00008328, 0x00000000 },
-    { 0x0000832c, 0x00000007 },
-    { 0x00008330, 0x00000302 },
-    { 0x00008334, 0x00000e00 },
-    { 0x00008338, 0x00000000 },
-    { 0x0000833c, 0x00000000 },
-    { 0x00008340, 0x000107ff },
-    { 0x00009808, 0x00000000 },
-    { 0x0000980c, 0xad848e19 },
-    { 0x00009810, 0x7d14e000 },
-    { 0x00009814, 0x9c0a9f6b },
-    { 0x0000981c, 0x00000000 },
-    { 0x0000982c, 0x0000a000 },
-    { 0x00009830, 0x00000000 },
-    { 0x0000983c, 0x00200400 },
-    { 0x00009840, 0x206a01ae },
-    { 0x0000984c, 0x1284233c },
-    { 0x00009854, 0x00000859 },
-    { 0x00009900, 0x00000000 },
-    { 0x00009904, 0x00000000 },
-    { 0x00009908, 0x00000000 },
-    { 0x0000990c, 0x00000000 },
-    { 0x0000991c, 0x10000fff },
-    { 0x00009920, 0x05100000 },
-    { 0x0000a920, 0x05100000 },
-    { 0x0000b920, 0x05100000 },
-    { 0x00009928, 0x00000001 },
-    { 0x0000992c, 0x00000004 },
-    { 0x00009934, 0x1e1f2022 },
-    { 0x00009938, 0x0a0b0c0d },
-    { 0x0000993c, 0x00000000 },
-    { 0x00009948, 0x9280b212 },
-    { 0x0000994c, 0x00020028 },
-    { 0x0000c95c, 0x004b6a8e },
-    { 0x0000c968, 0x000003ce },
-    { 0x00009970, 0x190fb515 },
-    { 0x00009974, 0x00000000 },
-    { 0x00009978, 0x00000001 },
-    { 0x0000997c, 0x00000000 },
-    { 0x00009980, 0x00000000 },
-    { 0x00009984, 0x00000000 },
-    { 0x00009988, 0x00000000 },
-    { 0x0000998c, 0x00000000 },
-    { 0x00009990, 0x00000000 },
-    { 0x00009994, 0x00000000 },
-    { 0x00009998, 0x00000000 },
-    { 0x0000999c, 0x00000000 },
-    { 0x000099a0, 0x00000000 },
-    { 0x000099a4, 0x00000001 },
-    { 0x000099a8, 0x201fff00 },
-    { 0x000099ac, 0x006f0000 },
-    { 0x000099b0, 0x03051000 },
-    { 0x000099dc, 0x00000000 },
-    { 0x000099e0, 0x00000200 },
-    { 0x000099e4, 0xaaaaaaaa },
-    { 0x000099e8, 0x3c466478 },
-    { 0x000099ec, 0x0cc80caa },
-    { 0x000099fc, 0x00001042 },
-    { 0x00009b00, 0x00000000 },
-    { 0x00009b04, 0x00000001 },
-    { 0x00009b08, 0x00000002 },
-    { 0x00009b0c, 0x00000003 },
-    { 0x00009b10, 0x00000004 },
-    { 0x00009b14, 0x00000005 },
-    { 0x00009b18, 0x00000008 },
-    { 0x00009b1c, 0x00000009 },
-    { 0x00009b20, 0x0000000a },
-    { 0x00009b24, 0x0000000b },
-    { 0x00009b28, 0x0000000c },
-    { 0x00009b2c, 0x0000000d },
-    { 0x00009b30, 0x00000010 },
-    { 0x00009b34, 0x00000011 },
-    { 0x00009b38, 0x00000012 },
-    { 0x00009b3c, 0x00000013 },
-    { 0x00009b40, 0x00000014 },
-    { 0x00009b44, 0x00000015 },
-    { 0x00009b48, 0x00000018 },
-    { 0x00009b4c, 0x00000019 },
-    { 0x00009b50, 0x0000001a },
-    { 0x00009b54, 0x0000001b },
-    { 0x00009b58, 0x0000001c },
-    { 0x00009b5c, 0x0000001d },
-    { 0x00009b60, 0x00000020 },
-    { 0x00009b64, 0x00000021 },
-    { 0x00009b68, 0x00000022 },
-    { 0x00009b6c, 0x00000023 },
-    { 0x00009b70, 0x00000024 },
-    { 0x00009b74, 0x00000025 },
-    { 0x00009b78, 0x00000028 },
-    { 0x00009b7c, 0x00000029 },
-    { 0x00009b80, 0x0000002a },
-    { 0x00009b84, 0x0000002b },
-    { 0x00009b88, 0x0000002c },
-    { 0x00009b8c, 0x0000002d },
-    { 0x00009b90, 0x00000030 },
-    { 0x00009b94, 0x00000031 },
-    { 0x00009b98, 0x00000032 },
-    { 0x00009b9c, 0x00000033 },
-    { 0x00009ba0, 0x00000034 },
-    { 0x00009ba4, 0x00000035 },
-    { 0x00009ba8, 0x00000035 },
-    { 0x00009bac, 0x00000035 },
-    { 0x00009bb0, 0x00000035 },
-    { 0x00009bb4, 0x00000035 },
-    { 0x00009bb8, 0x00000035 },
-    { 0x00009bbc, 0x00000035 },
-    { 0x00009bc0, 0x00000035 },
-    { 0x00009bc4, 0x00000035 },
-    { 0x00009bc8, 0x00000035 },
-    { 0x00009bcc, 0x00000035 },
-    { 0x00009bd0, 0x00000035 },
-    { 0x00009bd4, 0x00000035 },
-    { 0x00009bd8, 0x00000035 },
-    { 0x00009bdc, 0x00000035 },
-    { 0x00009be0, 0x00000035 },
-    { 0x00009be4, 0x00000035 },
-    { 0x00009be8, 0x00000035 },
-    { 0x00009bec, 0x00000035 },
-    { 0x00009bf0, 0x00000035 },
-    { 0x00009bf4, 0x00000035 },
-    { 0x00009bf8, 0x00000010 },
-    { 0x00009bfc, 0x0000001a },
-    { 0x0000a210, 0x40806333 },
-    { 0x0000a214, 0x00106c10 },
-    { 0x0000a218, 0x009c4060 },
-    { 0x0000a220, 0x018830c6 },
-    { 0x0000a224, 0x00000400 },
-    { 0x0000a228, 0x001a0bb5 },
-    { 0x0000a22c, 0x00000000 },
-    { 0x0000a234, 0x20202020 },
-    { 0x0000a238, 0x20202020 },
-    { 0x0000a23c, 0x13c889ae },
-    { 0x0000a240, 0x38490a20 },
-    { 0x0000a244, 0x00007bb6 },
-    { 0x0000a248, 0x0fff3ffc },
-    { 0x0000a24c, 0x00000001 },
-    { 0x0000a250, 0x0000a000 },
-    { 0x0000a254, 0x00000000 },
-    { 0x0000a258, 0x0cc75380 },
-    { 0x0000a25c, 0x0f0f0f01 },
-    { 0x0000a260, 0xdfa91f01 },
-    { 0x0000a268, 0x00000001 },
-    { 0x0000a26c, 0x0ebae9c6 },
-    { 0x0000b26c, 0x0ebae9c6 },
-    { 0x0000c26c, 0x0ebae9c6 },
-    { 0x0000d270, 0x00820820 },
-    { 0x0000a278, 0x1ce739ce },
-    { 0x0000a27c, 0x050701ce },
-    { 0x0000a338, 0x00000000 },
-    { 0x0000a33c, 0x00000000 },
-    { 0x0000a340, 0x00000000 },
-    { 0x0000a344, 0x00000000 },
-    { 0x0000a348, 0x3fffffff },
-    { 0x0000a34c, 0x3fffffff },
-    { 0x0000a350, 0x3fffffff },
-    { 0x0000a354, 0x0003ffff },
-    { 0x0000a358, 0x79a8aa33 },
-    { 0x0000d35c, 0x07ffffef },
-    { 0x0000d360, 0x0fffffe7 },
-    { 0x0000d364, 0x17ffffe5 },
-    { 0x0000d368, 0x1fffffe4 },
-    { 0x0000d36c, 0x37ffffe3 },
-    { 0x0000d370, 0x3fffffe3 },
-    { 0x0000d374, 0x57ffffe3 },
-    { 0x0000d378, 0x5fffffe2 },
-    { 0x0000d37c, 0x7fffffe2 },
-    { 0x0000d380, 0x7f3c7bba },
-    { 0x0000d384, 0xf3307ff0 },
-    { 0x0000a388, 0x0c000000 },
-    { 0x0000a38c, 0x20202020 },
-    { 0x0000a390, 0x20202020 },
-    { 0x0000a394, 0x1ce739ce },
-    { 0x0000a398, 0x000001ce },
-    { 0x0000a39c, 0x00000001 },
-    { 0x0000a3a0, 0x00000000 },
-    { 0x0000a3a4, 0x00000000 },
-    { 0x0000a3a8, 0x00000000 },
-    { 0x0000a3ac, 0x00000000 },
-    { 0x0000a3b0, 0x00000000 },
-    { 0x0000a3b4, 0x00000000 },
-    { 0x0000a3b8, 0x00000000 },
-    { 0x0000a3bc, 0x00000000 },
-    { 0x0000a3c0, 0x00000000 },
-    { 0x0000a3c4, 0x00000000 },
-    { 0x0000a3c8, 0x00000246 },
-    { 0x0000a3cc, 0x20202020 },
-    { 0x0000a3d0, 0x20202020 },
-    { 0x0000a3d4, 0x20202020 },
-    { 0x0000a3dc, 0x1ce739ce },
-    { 0x0000a3e0, 0x000001ce },
-};
-
-static const u32 ar5416Bank0_9100[][2] = {
-    { 0x000098b0, 0x1e5795e5 },
-    { 0x000098e0, 0x02008020 },
-};
-
-static const u32 ar5416BB_RfGain_9100[][3] = {
-    { 0x00009a00, 0x00000000, 0x00000000 },
-    { 0x00009a04, 0x00000040, 0x00000040 },
-    { 0x00009a08, 0x00000080, 0x00000080 },
-    { 0x00009a0c, 0x000001a1, 0x00000141 },
-    { 0x00009a10, 0x000001e1, 0x00000181 },
-    { 0x00009a14, 0x00000021, 0x000001c1 },
-    { 0x00009a18, 0x00000061, 0x00000001 },
-    { 0x00009a1c, 0x00000168, 0x00000041 },
-    { 0x00009a20, 0x000001a8, 0x000001a8 },
-    { 0x00009a24, 0x000001e8, 0x000001e8 },
-    { 0x00009a28, 0x00000028, 0x00000028 },
-    { 0x00009a2c, 0x00000068, 0x00000068 },
-    { 0x00009a30, 0x00000189, 0x000000a8 },
-    { 0x00009a34, 0x000001c9, 0x00000169 },
-    { 0x00009a38, 0x00000009, 0x000001a9 },
-    { 0x00009a3c, 0x00000049, 0x000001e9 },
-    { 0x00009a40, 0x00000089, 0x00000029 },
-    { 0x00009a44, 0x00000170, 0x00000069 },
-    { 0x00009a48, 0x000001b0, 0x00000190 },
-    { 0x00009a4c, 0x000001f0, 0x000001d0 },
-    { 0x00009a50, 0x00000030, 0x00000010 },
-    { 0x00009a54, 0x00000070, 0x00000050 },
-    { 0x00009a58, 0x00000191, 0x00000090 },
-    { 0x00009a5c, 0x000001d1, 0x00000151 },
-    { 0x00009a60, 0x00000011, 0x00000191 },
-    { 0x00009a64, 0x00000051, 0x000001d1 },
-    { 0x00009a68, 0x00000091, 0x00000011 },
-    { 0x00009a6c, 0x000001b8, 0x00000051 },
-    { 0x00009a70, 0x000001f8, 0x00000198 },
-    { 0x00009a74, 0x00000038, 0x000001d8 },
-    { 0x00009a78, 0x00000078, 0x00000018 },
-    { 0x00009a7c, 0x00000199, 0x00000058 },
-    { 0x00009a80, 0x000001d9, 0x00000098 },
-    { 0x00009a84, 0x00000019, 0x00000159 },
-    { 0x00009a88, 0x00000059, 0x00000199 },
-    { 0x00009a8c, 0x00000099, 0x000001d9 },
-    { 0x00009a90, 0x000000d9, 0x00000019 },
-    { 0x00009a94, 0x000000f9, 0x00000059 },
-    { 0x00009a98, 0x000000f9, 0x00000099 },
-    { 0x00009a9c, 0x000000f9, 0x000000d9 },
-    { 0x00009aa0, 0x000000f9, 0x000000f9 },
-    { 0x00009aa4, 0x000000f9, 0x000000f9 },
-    { 0x00009aa8, 0x000000f9, 0x000000f9 },
-    { 0x00009aac, 0x000000f9, 0x000000f9 },
-    { 0x00009ab0, 0x000000f9, 0x000000f9 },
-    { 0x00009ab4, 0x000000f9, 0x000000f9 },
-    { 0x00009ab8, 0x000000f9, 0x000000f9 },
-    { 0x00009abc, 0x000000f9, 0x000000f9 },
-    { 0x00009ac0, 0x000000f9, 0x000000f9 },
-    { 0x00009ac4, 0x000000f9, 0x000000f9 },
-    { 0x00009ac8, 0x000000f9, 0x000000f9 },
-    { 0x00009acc, 0x000000f9, 0x000000f9 },
-    { 0x00009ad0, 0x000000f9, 0x000000f9 },
-    { 0x00009ad4, 0x000000f9, 0x000000f9 },
-    { 0x00009ad8, 0x000000f9, 0x000000f9 },
-    { 0x00009adc, 0x000000f9, 0x000000f9 },
-    { 0x00009ae0, 0x000000f9, 0x000000f9 },
-    { 0x00009ae4, 0x000000f9, 0x000000f9 },
-    { 0x00009ae8, 0x000000f9, 0x000000f9 },
-    { 0x00009aec, 0x000000f9, 0x000000f9 },
-    { 0x00009af0, 0x000000f9, 0x000000f9 },
-    { 0x00009af4, 0x000000f9, 0x000000f9 },
-    { 0x00009af8, 0x000000f9, 0x000000f9 },
-    { 0x00009afc, 0x000000f9, 0x000000f9 },
-};
-
-static const u32 ar5416Bank1_9100[][2] = {
-    { 0x000098b0, 0x02108421},
-    { 0x000098ec, 0x00000008},
-};
-
-static const u32 ar5416Bank2_9100[][2] = {
-    { 0x000098b0, 0x0e73ff17},
-    { 0x000098e0, 0x00000420},
-};
-
-static const u32 ar5416Bank3_9100[][3] = {
-    { 0x000098f0, 0x01400018, 0x01c00018 },
-};
-
-static const u32 ar5416Bank6_9100[][3] = {
-
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00e00000, 0x00e00000 },
-    { 0x0000989c, 0x005e0000, 0x005e0000 },
-    { 0x0000989c, 0x00120000, 0x00120000 },
-    { 0x0000989c, 0x00620000, 0x00620000 },
-    { 0x0000989c, 0x00020000, 0x00020000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x005f0000, 0x005f0000 },
-    { 0x0000989c, 0x00870000, 0x00870000 },
-    { 0x0000989c, 0x00f90000, 0x00f90000 },
-    { 0x0000989c, 0x007b0000, 0x007b0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00f50000, 0x00f50000 },
-    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
-    { 0x0000989c, 0x00110000, 0x00110000 },
-    { 0x0000989c, 0x006100a8, 0x006100a8 },
-    { 0x0000989c, 0x004210a2, 0x004210a2 },
-    { 0x0000989c, 0x0014000f, 0x0014000f },
-    { 0x0000989c, 0x00c40002, 0x00c40002 },
-    { 0x0000989c, 0x003000f2, 0x003000f2 },
-    { 0x0000989c, 0x00440016, 0x00440016 },
-    { 0x0000989c, 0x00410040, 0x00410040 },
-    { 0x0000989c, 0x000180d6, 0x000180d6 },
-    { 0x0000989c, 0x0000c0aa, 0x0000c0aa },
-    { 0x0000989c, 0x000000b1, 0x000000b1 },
-    { 0x0000989c, 0x00002000, 0x00002000 },
-    { 0x0000989c, 0x000000d4, 0x000000d4 },
-    { 0x000098d0, 0x0000000f, 0x0010000f },
-};
-
-
-static const u32 ar5416Bank6TPC_9100[][3] = {
-
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00e00000, 0x00e00000 },
-    { 0x0000989c, 0x005e0000, 0x005e0000 },
-    { 0x0000989c, 0x00120000, 0x00120000 },
-    { 0x0000989c, 0x00620000, 0x00620000 },
-    { 0x0000989c, 0x00020000, 0x00020000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
-    { 0x0000989c, 0x005f0000, 0x005f0000 },
-    { 0x0000989c, 0x00870000, 0x00870000 },
-    { 0x0000989c, 0x00f90000, 0x00f90000 },
-    { 0x0000989c, 0x007b0000, 0x007b0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00f50000, 0x00f50000 },
-    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
-    { 0x0000989c, 0x00110000, 0x00110000 },
-    { 0x0000989c, 0x006100a8, 0x006100a8 },
-    { 0x0000989c, 0x00423022, 0x00423022 },
-    { 0x0000989c, 0x2014008f, 0x2014008f },
-    { 0x0000989c, 0x00c40002, 0x00c40002 },
-    { 0x0000989c, 0x003000f2, 0x003000f2 },
-    { 0x0000989c, 0x00440016, 0x00440016 },
-    { 0x0000989c, 0x00410040, 0x00410040 },
-    { 0x0000989c, 0x0001805e, 0x0001805e },
-    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
-    { 0x0000989c, 0x000000e1, 0x000000e1 },
-    { 0x0000989c, 0x00007080, 0x00007080 },
-    { 0x0000989c, 0x000000d4, 0x000000d4 },
-    { 0x000098d0, 0x0000000f, 0x0010000f },
-};
-
-static const u32 ar5416Bank7_9100[][2] = {
-    { 0x0000989c, 0x00000500 },
-    { 0x0000989c, 0x00000800 },
-    { 0x000098cc, 0x0000000e },
-};
-
-static const u32 ar5416Addac_9100[][2] = {
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000010 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x000000c0 },
-    {0x0000989c, 0x00000015 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x0000989c, 0x00000000 },
-    {0x000098cc, 0x00000000 },
-};
-
-static const u32 ar5416Modes_9160[][6] = {
-    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
-    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
-    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
-    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
-    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
-    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
-    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
-    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
-    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
-    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
-    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
-    { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 },
-    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
-    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
-    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
-    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
-    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
-    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
-    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
-    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
-    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
-    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
-    { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
-    { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
-    { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
-    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
-    { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
-    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 },
-    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
-    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
-    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
-    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
-    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
-    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
-    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
-    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
-    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
-    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
-    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
-    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
-    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
-    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
-    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
-    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
-    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
-    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
-    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
-    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
-    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
-    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-};
-
-static const u32 ar5416Common_9160[][2] = {
-    { 0x0000000c, 0x00000000 },
-    { 0x00000030, 0x00020015 },
-    { 0x00000034, 0x00000005 },
-    { 0x00000040, 0x00000000 },
-    { 0x00000044, 0x00000008 },
-    { 0x00000048, 0x00000008 },
-    { 0x0000004c, 0x00000010 },
-    { 0x00000050, 0x00000000 },
-    { 0x00000054, 0x0000001f },
-    { 0x00000800, 0x00000000 },
-    { 0x00000804, 0x00000000 },
-    { 0x00000808, 0x00000000 },
-    { 0x0000080c, 0x00000000 },
-    { 0x00000810, 0x00000000 },
-    { 0x00000814, 0x00000000 },
-    { 0x00000818, 0x00000000 },
-    { 0x0000081c, 0x00000000 },
-    { 0x00000820, 0x00000000 },
-    { 0x00000824, 0x00000000 },
-    { 0x00001040, 0x002ffc0f },
-    { 0x00001044, 0x002ffc0f },
-    { 0x00001048, 0x002ffc0f },
-    { 0x0000104c, 0x002ffc0f },
-    { 0x00001050, 0x002ffc0f },
-    { 0x00001054, 0x002ffc0f },
-    { 0x00001058, 0x002ffc0f },
-    { 0x0000105c, 0x002ffc0f },
-    { 0x00001060, 0x002ffc0f },
-    { 0x00001064, 0x002ffc0f },
-    { 0x00001230, 0x00000000 },
-    { 0x00001270, 0x00000000 },
-    { 0x00001038, 0x00000000 },
-    { 0x00001078, 0x00000000 },
-    { 0x000010b8, 0x00000000 },
-    { 0x000010f8, 0x00000000 },
-    { 0x00001138, 0x00000000 },
-    { 0x00001178, 0x00000000 },
-    { 0x000011b8, 0x00000000 },
-    { 0x000011f8, 0x00000000 },
-    { 0x00001238, 0x00000000 },
-    { 0x00001278, 0x00000000 },
-    { 0x000012b8, 0x00000000 },
-    { 0x000012f8, 0x00000000 },
-    { 0x00001338, 0x00000000 },
-    { 0x00001378, 0x00000000 },
-    { 0x000013b8, 0x00000000 },
-    { 0x000013f8, 0x00000000 },
-    { 0x00001438, 0x00000000 },
-    { 0x00001478, 0x00000000 },
-    { 0x000014b8, 0x00000000 },
-    { 0x000014f8, 0x00000000 },
-    { 0x00001538, 0x00000000 },
-    { 0x00001578, 0x00000000 },
-    { 0x000015b8, 0x00000000 },
-    { 0x000015f8, 0x00000000 },
-    { 0x00001638, 0x00000000 },
-    { 0x00001678, 0x00000000 },
-    { 0x000016b8, 0x00000000 },
-    { 0x000016f8, 0x00000000 },
-    { 0x00001738, 0x00000000 },
-    { 0x00001778, 0x00000000 },
-    { 0x000017b8, 0x00000000 },
-    { 0x000017f8, 0x00000000 },
-    { 0x0000103c, 0x00000000 },
-    { 0x0000107c, 0x00000000 },
-    { 0x000010bc, 0x00000000 },
-    { 0x000010fc, 0x00000000 },
-    { 0x0000113c, 0x00000000 },
-    { 0x0000117c, 0x00000000 },
-    { 0x000011bc, 0x00000000 },
-    { 0x000011fc, 0x00000000 },
-    { 0x0000123c, 0x00000000 },
-    { 0x0000127c, 0x00000000 },
-    { 0x000012bc, 0x00000000 },
-    { 0x000012fc, 0x00000000 },
-    { 0x0000133c, 0x00000000 },
-    { 0x0000137c, 0x00000000 },
-    { 0x000013bc, 0x00000000 },
-    { 0x000013fc, 0x00000000 },
-    { 0x0000143c, 0x00000000 },
-    { 0x0000147c, 0x00000000 },
-    { 0x00004030, 0x00000002 },
-    { 0x0000403c, 0x00000002 },
-    { 0x00007010, 0x00000020 },
-    { 0x00007038, 0x000004c2 },
-    { 0x00008004, 0x00000000 },
-    { 0x00008008, 0x00000000 },
-    { 0x0000800c, 0x00000000 },
-    { 0x00008018, 0x00000700 },
-    { 0x00008020, 0x00000000 },
-    { 0x00008038, 0x00000000 },
-    { 0x0000803c, 0x00000000 },
-    { 0x00008048, 0x40000000 },
-    { 0x00008054, 0x00000000 },
-    { 0x00008058, 0x00000000 },
-    { 0x0000805c, 0x000fc78f },
-    { 0x00008060, 0x0000000f },
-    { 0x00008064, 0x00000000 },
-    { 0x000080c0, 0x2a82301a },
-    { 0x000080c4, 0x05dc01e0 },
-    { 0x000080c8, 0x1f402710 },
-    { 0x000080cc, 0x01f40000 },
-    { 0x000080d0, 0x00001e00 },
-    { 0x000080d4, 0x00000000 },
-    { 0x000080d8, 0x00400000 },
-    { 0x000080e0, 0xffffffff },
-    { 0x000080e4, 0x0000ffff },
-    { 0x000080e8, 0x003f3f3f },
-    { 0x000080ec, 0x00000000 },
-    { 0x000080f0, 0x00000000 },
-    { 0x000080f4, 0x00000000 },
-    { 0x000080f8, 0x00000000 },
-    { 0x000080fc, 0x00020000 },
-    { 0x00008100, 0x00020000 },
-    { 0x00008104, 0x00000001 },
-    { 0x00008108, 0x00000052 },
-    { 0x0000810c, 0x00000000 },
-    { 0x00008110, 0x00000168 },
-    { 0x00008118, 0x000100aa },
-    { 0x0000811c, 0x00003210 },
-    { 0x00008120, 0x08f04800 },
-    { 0x00008124, 0x00000000 },
-    { 0x00008128, 0x00000000 },
-    { 0x0000812c, 0x00000000 },
-    { 0x00008130, 0x00000000 },
-    { 0x00008134, 0x00000000 },
-    { 0x00008138, 0x00000000 },
-    { 0x0000813c, 0x00000000 },
-    { 0x00008144, 0xffffffff },
-    { 0x00008168, 0x00000000 },
-    { 0x0000816c, 0x00000000 },
-    { 0x00008170, 0x32143320 },
-    { 0x00008174, 0xfaa4fa50 },
-    { 0x00008178, 0x00000100 },
-    { 0x0000817c, 0x00000000 },
-    { 0x000081c4, 0x00000000 },
-    { 0x000081d0, 0x00003210 },
-    { 0x000081ec, 0x00000000 },
-    { 0x000081f0, 0x00000000 },
-    { 0x000081f4, 0x00000000 },
-    { 0x000081f8, 0x00000000 },
-    { 0x000081fc, 0x00000000 },
-    { 0x00008200, 0x00000000 },
-    { 0x00008204, 0x00000000 },
-    { 0x00008208, 0x00000000 },
-    { 0x0000820c, 0x00000000 },
-    { 0x00008210, 0x00000000 },
-    { 0x00008214, 0x00000000 },
-    { 0x00008218, 0x00000000 },
-    { 0x0000821c, 0x00000000 },
-    { 0x00008220, 0x00000000 },
-    { 0x00008224, 0x00000000 },
-    { 0x00008228, 0x00000000 },
-    { 0x0000822c, 0x00000000 },
-    { 0x00008230, 0x00000000 },
-    { 0x00008234, 0x00000000 },
-    { 0x00008238, 0x00000000 },
-    { 0x0000823c, 0x00000000 },
-    { 0x00008240, 0x00100000 },
-    { 0x00008244, 0x0010f400 },
-    { 0x00008248, 0x00000100 },
-    { 0x0000824c, 0x0001e800 },
-    { 0x00008250, 0x00000000 },
-    { 0x00008254, 0x00000000 },
-    { 0x00008258, 0x00000000 },
-    { 0x0000825c, 0x400000ff },
-    { 0x00008260, 0x00080922 },
-    { 0x00008270, 0x00000000 },
-    { 0x00008274, 0x40000000 },
-    { 0x00008278, 0x003e4180 },
-    { 0x0000827c, 0x00000000 },
-    { 0x00008284, 0x0000002c },
-    { 0x00008288, 0x0000002c },
-    { 0x0000828c, 0x00000000 },
-    { 0x00008294, 0x00000000 },
-    { 0x00008298, 0x00000000 },
-    { 0x00008300, 0x00000000 },
-    { 0x00008304, 0x00000000 },
-    { 0x00008308, 0x00000000 },
-    { 0x0000830c, 0x00000000 },
-    { 0x00008310, 0x00000000 },
-    { 0x00008314, 0x00000000 },
-    { 0x00008318, 0x00000000 },
-    { 0x00008328, 0x00000000 },
-    { 0x0000832c, 0x00000007 },
-    { 0x00008330, 0x00000302 },
-    { 0x00008334, 0x00000e00 },
-    { 0x00008338, 0x00ff0000 },
-    { 0x0000833c, 0x00000000 },
-    { 0x00008340, 0x000107ff },
-    { 0x00009808, 0x00000000 },
-    { 0x0000980c, 0xad848e19 },
-    { 0x00009810, 0x7d14e000 },
-    { 0x00009814, 0x9c0a9f6b },
-    { 0x0000981c, 0x00000000 },
-    { 0x0000982c, 0x0000a000 },
-    { 0x00009830, 0x00000000 },
-    { 0x0000983c, 0x00200400 },
-    { 0x00009840, 0x206a01ae },
-    { 0x0000984c, 0x1284233c },
-    { 0x00009854, 0x00000859 },
-    { 0x00009900, 0x00000000 },
-    { 0x00009904, 0x00000000 },
-    { 0x00009908, 0x00000000 },
-    { 0x0000990c, 0x00000000 },
-    { 0x0000991c, 0x10000fff },
-    { 0x00009920, 0x05100000 },
-    { 0x0000a920, 0x05100000 },
-    { 0x0000b920, 0x05100000 },
-    { 0x00009928, 0x00000001 },
-    { 0x0000992c, 0x00000004 },
-    { 0x00009934, 0x1e1f2022 },
-    { 0x00009938, 0x0a0b0c0d },
-    { 0x0000993c, 0x00000000 },
-    { 0x00009948, 0x9280b212 },
-    { 0x0000994c, 0x00020028 },
-    { 0x00009954, 0x5f3ca3de },
-    { 0x00009958, 0x2108ecff },
-    { 0x00009940, 0x00750604 },
-    { 0x0000c95c, 0x004b6a8e },
-    { 0x00009970, 0x190fb515 },
-    { 0x00009974, 0x00000000 },
-    { 0x00009978, 0x00000001 },
-    { 0x0000997c, 0x00000000 },
-    { 0x00009980, 0x00000000 },
-    { 0x00009984, 0x00000000 },
-    { 0x00009988, 0x00000000 },
-    { 0x0000998c, 0x00000000 },
-    { 0x00009990, 0x00000000 },
-    { 0x00009994, 0x00000000 },
-    { 0x00009998, 0x00000000 },
-    { 0x0000999c, 0x00000000 },
-    { 0x000099a0, 0x00000000 },
-    { 0x000099a4, 0x00000001 },
-    { 0x000099a8, 0x201fff00 },
-    { 0x000099ac, 0x006f0000 },
-    { 0x000099b0, 0x03051000 },
-    { 0x000099dc, 0x00000000 },
-    { 0x000099e0, 0x00000200 },
-    { 0x000099e4, 0xaaaaaaaa },
-    { 0x000099e8, 0x3c466478 },
-    { 0x000099ec, 0x0cc80caa },
-    { 0x000099fc, 0x00001042 },
-    { 0x00009b00, 0x00000000 },
-    { 0x00009b04, 0x00000001 },
-    { 0x00009b08, 0x00000002 },
-    { 0x00009b0c, 0x00000003 },
-    { 0x00009b10, 0x00000004 },
-    { 0x00009b14, 0x00000005 },
-    { 0x00009b18, 0x00000008 },
-    { 0x00009b1c, 0x00000009 },
-    { 0x00009b20, 0x0000000a },
-    { 0x00009b24, 0x0000000b },
-    { 0x00009b28, 0x0000000c },
-    { 0x00009b2c, 0x0000000d },
-    { 0x00009b30, 0x00000010 },
-    { 0x00009b34, 0x00000011 },
-    { 0x00009b38, 0x00000012 },
-    { 0x00009b3c, 0x00000013 },
-    { 0x00009b40, 0x00000014 },
-    { 0x00009b44, 0x00000015 },
-    { 0x00009b48, 0x00000018 },
-    { 0x00009b4c, 0x00000019 },
-    { 0x00009b50, 0x0000001a },
-    { 0x00009b54, 0x0000001b },
-    { 0x00009b58, 0x0000001c },
-    { 0x00009b5c, 0x0000001d },
-    { 0x00009b60, 0x00000020 },
-    { 0x00009b64, 0x00000021 },
-    { 0x00009b68, 0x00000022 },
-    { 0x00009b6c, 0x00000023 },
-    { 0x00009b70, 0x00000024 },
-    { 0x00009b74, 0x00000025 },
-    { 0x00009b78, 0x00000028 },
-    { 0x00009b7c, 0x00000029 },
-    { 0x00009b80, 0x0000002a },
-    { 0x00009b84, 0x0000002b },
-    { 0x00009b88, 0x0000002c },
-    { 0x00009b8c, 0x0000002d },
-    { 0x00009b90, 0x00000030 },
-    { 0x00009b94, 0x00000031 },
-    { 0x00009b98, 0x00000032 },
-    { 0x00009b9c, 0x00000033 },
-    { 0x00009ba0, 0x00000034 },
-    { 0x00009ba4, 0x00000035 },
-    { 0x00009ba8, 0x00000035 },
-    { 0x00009bac, 0x00000035 },
-    { 0x00009bb0, 0x00000035 },
-    { 0x00009bb4, 0x00000035 },
-    { 0x00009bb8, 0x00000035 },
-    { 0x00009bbc, 0x00000035 },
-    { 0x00009bc0, 0x00000035 },
-    { 0x00009bc4, 0x00000035 },
-    { 0x00009bc8, 0x00000035 },
-    { 0x00009bcc, 0x00000035 },
-    { 0x00009bd0, 0x00000035 },
-    { 0x00009bd4, 0x00000035 },
-    { 0x00009bd8, 0x00000035 },
-    { 0x00009bdc, 0x00000035 },
-    { 0x00009be0, 0x00000035 },
-    { 0x00009be4, 0x00000035 },
-    { 0x00009be8, 0x00000035 },
-    { 0x00009bec, 0x00000035 },
-    { 0x00009bf0, 0x00000035 },
-    { 0x00009bf4, 0x00000035 },
-    { 0x00009bf8, 0x00000010 },
-    { 0x00009bfc, 0x0000001a },
-    { 0x0000a210, 0x40806333 },
-    { 0x0000a214, 0x00106c10 },
-    { 0x0000a218, 0x009c4060 },
-    { 0x0000a220, 0x018830c6 },
-    { 0x0000a224, 0x00000400 },
-    { 0x0000a228, 0x001a0bb5 },
-    { 0x0000a22c, 0x00000000 },
-    { 0x0000a234, 0x20202020 },
-    { 0x0000a238, 0x20202020 },
-    { 0x0000a23c, 0x13c889af },
-    { 0x0000a240, 0x38490a20 },
-    { 0x0000a244, 0x00007bb6 },
-    { 0x0000a248, 0x0fff3ffc },
-    { 0x0000a24c, 0x00000001 },
-    { 0x0000a250, 0x0000e000 },
-    { 0x0000a254, 0x00000000 },
-    { 0x0000a258, 0x0cc75380 },
-    { 0x0000a25c, 0x0f0f0f01 },
-    { 0x0000a260, 0xdfa91f01 },
-    { 0x0000a268, 0x00000001 },
-    { 0x0000a26c, 0x0ebae9c6 },
-    { 0x0000b26c, 0x0ebae9c6 },
-    { 0x0000c26c, 0x0ebae9c6 },
-    { 0x0000d270, 0x00820820 },
-    { 0x0000a278, 0x1ce739ce },
-    { 0x0000a27c, 0x050701ce },
-    { 0x0000a338, 0x00000000 },
-    { 0x0000a33c, 0x00000000 },
-    { 0x0000a340, 0x00000000 },
-    { 0x0000a344, 0x00000000 },
-    { 0x0000a348, 0x3fffffff },
-    { 0x0000a34c, 0x3fffffff },
-    { 0x0000a350, 0x3fffffff },
-    { 0x0000a354, 0x0003ffff },
-    { 0x0000a358, 0x79bfaa03 },
-    { 0x0000d35c, 0x07ffffef },
-    { 0x0000d360, 0x0fffffe7 },
-    { 0x0000d364, 0x17ffffe5 },
-    { 0x0000d368, 0x1fffffe4 },
-    { 0x0000d36c, 0x37ffffe3 },
-    { 0x0000d370, 0x3fffffe3 },
-    { 0x0000d374, 0x57ffffe3 },
-    { 0x0000d378, 0x5fffffe2 },
-    { 0x0000d37c, 0x7fffffe2 },
-    { 0x0000d380, 0x7f3c7bba },
-    { 0x0000d384, 0xf3307ff0 },
-    { 0x0000a388, 0x0c000000 },
-    { 0x0000a38c, 0x20202020 },
-    { 0x0000a390, 0x20202020 },
-    { 0x0000a394, 0x1ce739ce },
-    { 0x0000a398, 0x000001ce },
-    { 0x0000a39c, 0x00000001 },
-    { 0x0000a3a0, 0x00000000 },
-    { 0x0000a3a4, 0x00000000 },
-    { 0x0000a3a8, 0x00000000 },
-    { 0x0000a3ac, 0x00000000 },
-    { 0x0000a3b0, 0x00000000 },
-    { 0x0000a3b4, 0x00000000 },
-    { 0x0000a3b8, 0x00000000 },
-    { 0x0000a3bc, 0x00000000 },
-    { 0x0000a3c0, 0x00000000 },
-    { 0x0000a3c4, 0x00000000 },
-    { 0x0000a3c8, 0x00000246 },
-    { 0x0000a3cc, 0x20202020 },
-    { 0x0000a3d0, 0x20202020 },
-    { 0x0000a3d4, 0x20202020 },
-    { 0x0000a3dc, 0x1ce739ce },
-    { 0x0000a3e0, 0x000001ce },
-};
-
-static const u32 ar5416Bank0_9160[][2] = {
-    { 0x000098b0, 0x1e5795e5 },
-    { 0x000098e0, 0x02008020 },
-};
-
-static const u32 ar5416BB_RfGain_9160[][3] = {
-    { 0x00009a00, 0x00000000, 0x00000000 },
-    { 0x00009a04, 0x00000040, 0x00000040 },
-    { 0x00009a08, 0x00000080, 0x00000080 },
-    { 0x00009a0c, 0x000001a1, 0x00000141 },
-    { 0x00009a10, 0x000001e1, 0x00000181 },
-    { 0x00009a14, 0x00000021, 0x000001c1 },
-    { 0x00009a18, 0x00000061, 0x00000001 },
-    { 0x00009a1c, 0x00000168, 0x00000041 },
-    { 0x00009a20, 0x000001a8, 0x000001a8 },
-    { 0x00009a24, 0x000001e8, 0x000001e8 },
-    { 0x00009a28, 0x00000028, 0x00000028 },
-    { 0x00009a2c, 0x00000068, 0x00000068 },
-    { 0x00009a30, 0x00000189, 0x000000a8 },
-    { 0x00009a34, 0x000001c9, 0x00000169 },
-    { 0x00009a38, 0x00000009, 0x000001a9 },
-    { 0x00009a3c, 0x00000049, 0x000001e9 },
-    { 0x00009a40, 0x00000089, 0x00000029 },
-    { 0x00009a44, 0x00000170, 0x00000069 },
-    { 0x00009a48, 0x000001b0, 0x00000190 },
-    { 0x00009a4c, 0x000001f0, 0x000001d0 },
-    { 0x00009a50, 0x00000030, 0x00000010 },
-    { 0x00009a54, 0x00000070, 0x00000050 },
-    { 0x00009a58, 0x00000191, 0x00000090 },
-    { 0x00009a5c, 0x000001d1, 0x00000151 },
-    { 0x00009a60, 0x00000011, 0x00000191 },
-    { 0x00009a64, 0x00000051, 0x000001d1 },
-    { 0x00009a68, 0x00000091, 0x00000011 },
-    { 0x00009a6c, 0x000001b8, 0x00000051 },
-    { 0x00009a70, 0x000001f8, 0x00000198 },
-    { 0x00009a74, 0x00000038, 0x000001d8 },
-    { 0x00009a78, 0x00000078, 0x00000018 },
-    { 0x00009a7c, 0x00000199, 0x00000058 },
-    { 0x00009a80, 0x000001d9, 0x00000098 },
-    { 0x00009a84, 0x00000019, 0x00000159 },
-    { 0x00009a88, 0x00000059, 0x00000199 },
-    { 0x00009a8c, 0x00000099, 0x000001d9 },
-    { 0x00009a90, 0x000000d9, 0x00000019 },
-    { 0x00009a94, 0x000000f9, 0x00000059 },
-    { 0x00009a98, 0x000000f9, 0x00000099 },
-    { 0x00009a9c, 0x000000f9, 0x000000d9 },
-    { 0x00009aa0, 0x000000f9, 0x000000f9 },
-    { 0x00009aa4, 0x000000f9, 0x000000f9 },
-    { 0x00009aa8, 0x000000f9, 0x000000f9 },
-    { 0x00009aac, 0x000000f9, 0x000000f9 },
-    { 0x00009ab0, 0x000000f9, 0x000000f9 },
-    { 0x00009ab4, 0x000000f9, 0x000000f9 },
-    { 0x00009ab8, 0x000000f9, 0x000000f9 },
-    { 0x00009abc, 0x000000f9, 0x000000f9 },
-    { 0x00009ac0, 0x000000f9, 0x000000f9 },
-    { 0x00009ac4, 0x000000f9, 0x000000f9 },
-    { 0x00009ac8, 0x000000f9, 0x000000f9 },
-    { 0x00009acc, 0x000000f9, 0x000000f9 },
-    { 0x00009ad0, 0x000000f9, 0x000000f9 },
-    { 0x00009ad4, 0x000000f9, 0x000000f9 },
-    { 0x00009ad8, 0x000000f9, 0x000000f9 },
-    { 0x00009adc, 0x000000f9, 0x000000f9 },
-    { 0x00009ae0, 0x000000f9, 0x000000f9 },
-    { 0x00009ae4, 0x000000f9, 0x000000f9 },
-    { 0x00009ae8, 0x000000f9, 0x000000f9 },
-    { 0x00009aec, 0x000000f9, 0x000000f9 },
-    { 0x00009af0, 0x000000f9, 0x000000f9 },
-    { 0x00009af4, 0x000000f9, 0x000000f9 },
-    { 0x00009af8, 0x000000f9, 0x000000f9 },
-    { 0x00009afc, 0x000000f9, 0x000000f9 },
-};
-
-static const u32 ar5416Bank1_9160[][2] = {
-    { 0x000098b0, 0x02108421 },
-    { 0x000098ec, 0x00000008 },
-};
-
-static const u32 ar5416Bank2_9160[][2] = {
-    { 0x000098b0, 0x0e73ff17 },
-    { 0x000098e0, 0x00000420 },
-};
-
-static const u32 ar5416Bank3_9160[][3] = {
-    { 0x000098f0, 0x01400018, 0x01c00018 },
-};
-
-static const u32 ar5416Bank6_9160[][3] = {
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00e00000, 0x00e00000 },
-    { 0x0000989c, 0x005e0000, 0x005e0000 },
-    { 0x0000989c, 0x00120000, 0x00120000 },
-    { 0x0000989c, 0x00620000, 0x00620000 },
-    { 0x0000989c, 0x00020000, 0x00020000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
-    { 0x0000989c, 0x005f0000, 0x005f0000 },
-    { 0x0000989c, 0x00870000, 0x00870000 },
-    { 0x0000989c, 0x00f90000, 0x00f90000 },
-    { 0x0000989c, 0x007b0000, 0x007b0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00f50000, 0x00f50000 },
-    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
-    { 0x0000989c, 0x00110000, 0x00110000 },
-    { 0x0000989c, 0x006100a8, 0x006100a8 },
-    { 0x0000989c, 0x004210a2, 0x004210a2 },
-    { 0x0000989c, 0x0014008f, 0x0014008f },
-    { 0x0000989c, 0x00c40003, 0x00c40003 },
-    { 0x0000989c, 0x003000f2, 0x003000f2 },
-    { 0x0000989c, 0x00440016, 0x00440016 },
-    { 0x0000989c, 0x00410040, 0x00410040 },
-    { 0x0000989c, 0x0001805e, 0x0001805e },
-    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
-    { 0x0000989c, 0x000000f1, 0x000000f1 },
-    { 0x0000989c, 0x00002081, 0x00002081 },
-    { 0x0000989c, 0x000000d4, 0x000000d4 },
-    { 0x000098d0, 0x0000000f, 0x0010000f },
-};
-
-static const u32 ar5416Bank6TPC_9160[][3] = {
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00000000, 0x00000000 },
-    { 0x0000989c, 0x00e00000, 0x00e00000 },
-    { 0x0000989c, 0x005e0000, 0x005e0000 },
-    { 0x0000989c, 0x00120000, 0x00120000 },
-    { 0x0000989c, 0x00620000, 0x00620000 },
-    { 0x0000989c, 0x00020000, 0x00020000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x40ff0000, 0x40ff0000 },
-    { 0x0000989c, 0x005f0000, 0x005f0000 },
-    { 0x0000989c, 0x00870000, 0x00870000 },
-    { 0x0000989c, 0x00f90000, 0x00f90000 },
-    { 0x0000989c, 0x007b0000, 0x007b0000 },
-    { 0x0000989c, 0x00ff0000, 0x00ff0000 },
-    { 0x0000989c, 0x00f50000, 0x00f50000 },
-    { 0x0000989c, 0x00dc0000, 0x00dc0000 },
-    { 0x0000989c, 0x00110000, 0x00110000 },
-    { 0x0000989c, 0x006100a8, 0x006100a8 },
-    { 0x0000989c, 0x00423022, 0x00423022 },
-    { 0x0000989c, 0x2014008f, 0x2014008f },
-    { 0x0000989c, 0x00c40002, 0x00c40002 },
-    { 0x0000989c, 0x003000f2, 0x003000f2 },
-    { 0x0000989c, 0x00440016, 0x00440016 },
-    { 0x0000989c, 0x00410040, 0x00410040 },
-    { 0x0000989c, 0x0001805e, 0x0001805e },
-    { 0x0000989c, 0x0000c0ab, 0x0000c0ab },
-    { 0x0000989c, 0x000000e1, 0x000000e1 },
-    { 0x0000989c, 0x00007080, 0x00007080 },
-    { 0x0000989c, 0x000000d4, 0x000000d4 },
-    { 0x000098d0, 0x0000000f, 0x0010000f },
-};
-
-static const u32 ar5416Bank7_9160[][2] = {
-    { 0x0000989c, 0x00000500 },
-    { 0x0000989c, 0x00000800 },
-    { 0x000098cc, 0x0000000e },
-};
-
-static u32 ar5416Addac_9160[][2] = {
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x000000c0 },
-    {0x0000989c,  0x00000018 },
-    {0x0000989c,  0x00000004 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x000000c0 },
-    {0x0000989c,  0x00000019 },
-    {0x0000989c,  0x00000004 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000004 },
-    {0x0000989c,  0x00000003 },
-    {0x0000989c,  0x00000008 },
-    {0x0000989c,  0x00000000 },
-    {0x000098cc,  0x00000000 },
-};
-
-static u32 ar5416Addac_91601_1[][2] = {
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x000000c0 },
-    {0x0000989c,  0x00000018 },
-    {0x0000989c,  0x00000004 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x000000c0 },
-    {0x0000989c,  0x00000019 },
-    {0x0000989c,  0x00000004 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x0000989c,  0x00000000 },
-    {0x000098cc,  0x00000000 },
-};
-
-/* XXX 9280 1 */
-static const u32 ar9280Modes_9280[][6] = {
-    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
-    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
-    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
-    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
-    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 },
-    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
-    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
-    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
-    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
-    { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
-    { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
-    { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
-    { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
-    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
-    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
-    { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 },
-    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
-    { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 },
-    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
-    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
-    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
-    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
-    { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 },
-    { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
-    { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
-    { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
-    { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a },
-    { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
-    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
-    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
-    { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
-    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
-    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
-    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 },
-    { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 },
-    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 },
-    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 },
-    { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c },
-    { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 },
-    { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 },
-    { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 },
-    { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac },
-    { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 },
-    { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 },
-    { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 },
-    { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 },
-    { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 },
-    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 },
-    { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 },
-    { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 },
-    { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac },
-    { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 },
-    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 },
-    { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 },
-    { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 },
-    { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 },
-    { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad },
-    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
-    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
-    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
-    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
-    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
-    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
-    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
-    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
-    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
-    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
-    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
-    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
-    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
-    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
-    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
-    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
-    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
-    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
-    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
-    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
-    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
-    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
-    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
-    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
-    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
-    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
-    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
-    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
-    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
-    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
-    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
-    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
-    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
-    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
-    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
-    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
-    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
-    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
-    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
-    { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
-    { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
-    { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
-    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
-    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
-    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
-    { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
-    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
-    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
-    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
-    { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
-    { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
-    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
-    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
-    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
-    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
-    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
-    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
-    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
-    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
-    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
-    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
-    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
-    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
-    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
-    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
-    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
-    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
-    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
-    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
-    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
-    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
-    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
-    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
-    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
-    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
-    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
-    { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 },
-    { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
-    { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
-    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
-    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
-    { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
-    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
-    { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
-    { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
-    { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
-    { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
-    { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
-    { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
-    { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
-    { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
-    { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
-    { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
-    { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
-    { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
-    { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
-    { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
-    { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
-    { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
-    { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
-    { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
-    { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
-    { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
-    { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c },
-    { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 },
-    { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 },
-    { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 },
-};
-
-static const u32 ar9280Common_9280[][2] = {
-    { 0x0000000c, 0x00000000 },
-    { 0x00000030, 0x00020015 },
-    { 0x00000034, 0x00000005 },
-    { 0x00000040, 0x00000000 },
-    { 0x00000044, 0x00000008 },
-    { 0x00000048, 0x00000008 },
-    { 0x0000004c, 0x00000010 },
-    { 0x00000050, 0x00000000 },
-    { 0x00000054, 0x0000001f },
-    { 0x00000800, 0x00000000 },
-    { 0x00000804, 0x00000000 },
-    { 0x00000808, 0x00000000 },
-    { 0x0000080c, 0x00000000 },
-    { 0x00000810, 0x00000000 },
-    { 0x00000814, 0x00000000 },
-    { 0x00000818, 0x00000000 },
-    { 0x0000081c, 0x00000000 },
-    { 0x00000820, 0x00000000 },
-    { 0x00000824, 0x00000000 },
-    { 0x00001040, 0x002ffc0f },
-    { 0x00001044, 0x002ffc0f },
-    { 0x00001048, 0x002ffc0f },
-    { 0x0000104c, 0x002ffc0f },
-    { 0x00001050, 0x002ffc0f },
-    { 0x00001054, 0x002ffc0f },
-    { 0x00001058, 0x002ffc0f },
-    { 0x0000105c, 0x002ffc0f },
-    { 0x00001060, 0x002ffc0f },
-    { 0x00001064, 0x002ffc0f },
-    { 0x00001230, 0x00000000 },
-    { 0x00001270, 0x00000000 },
-    { 0x00001038, 0x00000000 },
-    { 0x00001078, 0x00000000 },
-    { 0x000010b8, 0x00000000 },
-    { 0x000010f8, 0x00000000 },
-    { 0x00001138, 0x00000000 },
-    { 0x00001178, 0x00000000 },
-    { 0x000011b8, 0x00000000 },
-    { 0x000011f8, 0x00000000 },
-    { 0x00001238, 0x00000000 },
-    { 0x00001278, 0x00000000 },
-    { 0x000012b8, 0x00000000 },
-    { 0x000012f8, 0x00000000 },
-    { 0x00001338, 0x00000000 },
-    { 0x00001378, 0x00000000 },
-    { 0x000013b8, 0x00000000 },
-    { 0x000013f8, 0x00000000 },
-    { 0x00001438, 0x00000000 },
-    { 0x00001478, 0x00000000 },
-    { 0x000014b8, 0x00000000 },
-    { 0x000014f8, 0x00000000 },
-    { 0x00001538, 0x00000000 },
-    { 0x00001578, 0x00000000 },
-    { 0x000015b8, 0x00000000 },
-    { 0x000015f8, 0x00000000 },
-    { 0x00001638, 0x00000000 },
-    { 0x00001678, 0x00000000 },
-    { 0x000016b8, 0x00000000 },
-    { 0x000016f8, 0x00000000 },
-    { 0x00001738, 0x00000000 },
-    { 0x00001778, 0x00000000 },
-    { 0x000017b8, 0x00000000 },
-    { 0x000017f8, 0x00000000 },
-    { 0x0000103c, 0x00000000 },
-    { 0x0000107c, 0x00000000 },
-    { 0x000010bc, 0x00000000 },
-    { 0x000010fc, 0x00000000 },
-    { 0x0000113c, 0x00000000 },
-    { 0x0000117c, 0x00000000 },
-    { 0x000011bc, 0x00000000 },
-    { 0x000011fc, 0x00000000 },
-    { 0x0000123c, 0x00000000 },
-    { 0x0000127c, 0x00000000 },
-    { 0x000012bc, 0x00000000 },
-    { 0x000012fc, 0x00000000 },
-    { 0x0000133c, 0x00000000 },
-    { 0x0000137c, 0x00000000 },
-    { 0x000013bc, 0x00000000 },
-    { 0x000013fc, 0x00000000 },
-    { 0x0000143c, 0x00000000 },
-    { 0x0000147c, 0x00000000 },
-    { 0x00004030, 0x00000002 },
-    { 0x0000403c, 0x00000002 },
-    { 0x00004024, 0x0000001f },
-    { 0x00007010, 0x00000033 },
-    { 0x00007038, 0x000004c2 },
-    { 0x00008004, 0x00000000 },
-    { 0x00008008, 0x00000000 },
-    { 0x0000800c, 0x00000000 },
-    { 0x00008018, 0x00000700 },
-    { 0x00008020, 0x00000000 },
-    { 0x00008038, 0x00000000 },
-    { 0x0000803c, 0x00000000 },
-    { 0x00008048, 0x40000000 },
-    { 0x00008054, 0x00000000 },
-    { 0x00008058, 0x00000000 },
-    { 0x0000805c, 0x000fc78f },
-    { 0x00008060, 0x0000000f },
-    { 0x00008064, 0x00000000 },
-    { 0x00008070, 0x00000000 },
-    { 0x000080c0, 0x2a82301a },
-    { 0x000080c4, 0x05dc01e0 },
-    { 0x000080c8, 0x1f402710 },
-    { 0x000080cc, 0x01f40000 },
-    { 0x000080d0, 0x00001e00 },
-    { 0x000080d4, 0x00000000 },
-    { 0x000080d8, 0x00400000 },
-    { 0x000080e0, 0xffffffff },
-    { 0x000080e4, 0x0000ffff },
-    { 0x000080e8, 0x003f3f3f },
-    { 0x000080ec, 0x00000000 },
-    { 0x000080f0, 0x00000000 },
-    { 0x000080f4, 0x00000000 },
-    { 0x000080f8, 0x00000000 },
-    { 0x000080fc, 0x00020000 },
-    { 0x00008100, 0x00020000 },
-    { 0x00008104, 0x00000001 },
-    { 0x00008108, 0x00000052 },
-    { 0x0000810c, 0x00000000 },
-    { 0x00008110, 0x00000168 },
-    { 0x00008118, 0x000100aa },
-    { 0x0000811c, 0x00003210 },
-    { 0x00008120, 0x08f04800 },
-    { 0x00008124, 0x00000000 },
-    { 0x00008128, 0x00000000 },
-    { 0x0000812c, 0x00000000 },
-    { 0x00008130, 0x00000000 },
-    { 0x00008134, 0x00000000 },
-    { 0x00008138, 0x00000000 },
-    { 0x0000813c, 0x00000000 },
-    { 0x00008144, 0x00000000 },
-    { 0x00008168, 0x00000000 },
-    { 0x0000816c, 0x00000000 },
-    { 0x00008170, 0x32143320 },
-    { 0x00008174, 0xfaa4fa50 },
-    { 0x00008178, 0x00000100 },
-    { 0x0000817c, 0x00000000 },
-    { 0x000081c4, 0x00000000 },
-    { 0x000081d0, 0x00003210 },
-    { 0x000081ec, 0x00000000 },
-    { 0x000081f0, 0x00000000 },
-    { 0x000081f4, 0x00000000 },
-    { 0x000081f8, 0x00000000 },
-    { 0x000081fc, 0x00000000 },
-    { 0x00008200, 0x00000000 },
-    { 0x00008204, 0x00000000 },
-    { 0x00008208, 0x00000000 },
-    { 0x0000820c, 0x00000000 },
-    { 0x00008210, 0x00000000 },
-    { 0x00008214, 0x00000000 },
-    { 0x00008218, 0x00000000 },
-    { 0x0000821c, 0x00000000 },
-    { 0x00008220, 0x00000000 },
-    { 0x00008224, 0x00000000 },
-    { 0x00008228, 0x00000000 },
-    { 0x0000822c, 0x00000000 },
-    { 0x00008230, 0x00000000 },
-    { 0x00008234, 0x00000000 },
-    { 0x00008238, 0x00000000 },
-    { 0x0000823c, 0x00000000 },
-    { 0x00008240, 0x00100000 },
-    { 0x00008244, 0x0010f400 },
-    { 0x00008248, 0x00000100 },
-    { 0x0000824c, 0x0001e800 },
-    { 0x00008250, 0x00000000 },
-    { 0x00008254, 0x00000000 },
-    { 0x00008258, 0x00000000 },
-    { 0x0000825c, 0x400000ff },
-    { 0x00008260, 0x00080922 },
-    { 0x00008270, 0x00000000 },
-    { 0x00008274, 0x40000000 },
-    { 0x00008278, 0x003e4180 },
-    { 0x0000827c, 0x00000000 },
-    { 0x00008284, 0x0000002c },
-    { 0x00008288, 0x0000002c },
-    { 0x0000828c, 0x00000000 },
-    { 0x00008294, 0x00000000 },
-    { 0x00008298, 0x00000000 },
-    { 0x00008300, 0x00000000 },
-    { 0x00008304, 0x00000000 },
-    { 0x00008308, 0x00000000 },
-    { 0x0000830c, 0x00000000 },
-    { 0x00008310, 0x00000000 },
-    { 0x00008314, 0x00000000 },
-    { 0x00008318, 0x00000000 },
-    { 0x00008328, 0x00000000 },
-    { 0x0000832c, 0x00000007 },
-    { 0x00008330, 0x00000302 },
-    { 0x00008334, 0x00000e00 },
-    { 0x00008338, 0x00000000 },
-    { 0x0000833c, 0x00000000 },
-    { 0x00008340, 0x000107ff },
-    { 0x00008344, 0x00000000 },
-    { 0x00009808, 0x00000000 },
-    { 0x0000980c, 0xaf268e30 },
-    { 0x00009810, 0xfd14e000 },
-    { 0x00009814, 0x9c0a9f6b },
-    { 0x0000981c, 0x00000000 },
-    { 0x0000982c, 0x0000a000 },
-    { 0x00009830, 0x00000000 },
-    { 0x0000983c, 0x00200400 },
-    { 0x00009840, 0x206a01ae },
-    { 0x0000984c, 0x0040233c },
-    { 0x0000a84c, 0x0040233c },
-    { 0x00009854, 0x00000044 },
-    { 0x00009900, 0x00000000 },
-    { 0x00009904, 0x00000000 },
-    { 0x00009908, 0x00000000 },
-    { 0x0000990c, 0x00000000 },
-    { 0x0000991c, 0x10000fff },
-    { 0x00009920, 0x04900000 },
-    { 0x0000a920, 0x04900000 },
-    { 0x00009928, 0x00000001 },
-    { 0x0000992c, 0x00000004 },
-    { 0x00009934, 0x1e1f2022 },
-    { 0x00009938, 0x0a0b0c0d },
-    { 0x0000993c, 0x00000000 },
-    { 0x00009948, 0x9280c00a },
-    { 0x0000994c, 0x00020028 },
-    { 0x00009954, 0xe250a51e },
-    { 0x00009958, 0x3388ffff },
-    { 0x00009940, 0x00781204 },
-    { 0x0000c95c, 0x004b6a8e },
-    { 0x0000c968, 0x000003ce },
-    { 0x00009970, 0x190fb514 },
-    { 0x00009974, 0x00000000 },
-    { 0x00009978, 0x00000001 },
-    { 0x0000997c, 0x00000000 },
-    { 0x00009980, 0x00000000 },
-    { 0x00009984, 0x00000000 },
-    { 0x00009988, 0x00000000 },
-    { 0x0000998c, 0x00000000 },
-    { 0x00009990, 0x00000000 },
-    { 0x00009994, 0x00000000 },
-    { 0x00009998, 0x00000000 },
-    { 0x0000999c, 0x00000000 },
-    { 0x000099a0, 0x00000000 },
-    { 0x000099a4, 0x00000001 },
-    { 0x000099a8, 0x201fff00 },
-    { 0x000099ac, 0x006f00c4 },
-    { 0x000099b0, 0x03051000 },
-    { 0x000099b4, 0x00000820 },
-    { 0x000099dc, 0x00000000 },
-    { 0x000099e0, 0x00000000 },
-    { 0x000099e4, 0xaaaaaaaa },
-    { 0x000099e8, 0x3c466478 },
-    { 0x000099ec, 0x0cc80caa },
-    { 0x000099fc, 0x00001042 },
-    { 0x0000a210, 0x4080a333 },
-    { 0x0000a214, 0x40206c10 },
-    { 0x0000a218, 0x009c4060 },
-    { 0x0000a220, 0x01834061 },
-    { 0x0000a224, 0x00000400 },
-    { 0x0000a228, 0x000003b5 },
-    { 0x0000a22c, 0x23277200 },
-    { 0x0000a234, 0x20202020 },
-    { 0x0000a238, 0x20202020 },
-    { 0x0000a23c, 0x13c889af },
-    { 0x0000a240, 0x38490a20 },
-    { 0x0000a244, 0x00007bb6 },
-    { 0x0000a248, 0x0fff3ffc },
-    { 0x0000a24c, 0x00000001 },
-    { 0x0000a250, 0x001da000 },
-    { 0x0000a254, 0x00000000 },
-    { 0x0000a258, 0x0cdbd380 },
-    { 0x0000a25c, 0x0f0f0f01 },
-    { 0x0000a260, 0xdfa91f01 },
-    { 0x0000a268, 0x00000000 },
-    { 0x0000a26c, 0x0ebae9c6 },
-    { 0x0000b26c, 0x0ebae9c6 },
-    { 0x0000d270, 0x00820820 },
-    { 0x0000a278, 0x1ce739ce },
-    { 0x0000a27c, 0x050701ce },
-    { 0x0000a358, 0x7999aa0f },
-    { 0x0000d35c, 0x07ffffef },
-    { 0x0000d360, 0x0fffffe7 },
-    { 0x0000d364, 0x17ffffe5 },
-    { 0x0000d368, 0x1fffffe4 },
-    { 0x0000d36c, 0x37ffffe3 },
-    { 0x0000d370, 0x3fffffe3 },
-    { 0x0000d374, 0x57ffffe3 },
-    { 0x0000d378, 0x5fffffe2 },
-    { 0x0000d37c, 0x7fffffe2 },
-    { 0x0000d380, 0x7f3c7bba },
-    { 0x0000d384, 0xf3307ff0 },
-    { 0x0000a388, 0x0c000000 },
-    { 0x0000a38c, 0x20202020 },
-    { 0x0000a390, 0x20202020 },
-    { 0x0000a394, 0x1ce739ce },
-    { 0x0000a398, 0x000001ce },
-    { 0x0000a39c, 0x00000001 },
-    { 0x0000a3a0, 0x00000000 },
-    { 0x0000a3a4, 0x00000000 },
-    { 0x0000a3a8, 0x00000000 },
-    { 0x0000a3ac, 0x00000000 },
-    { 0x0000a3b0, 0x00000000 },
-    { 0x0000a3b4, 0x00000000 },
-    { 0x0000a3b8, 0x00000000 },
-    { 0x0000a3bc, 0x00000000 },
-    { 0x0000a3c0, 0x00000000 },
-    { 0x0000a3c4, 0x00000000 },
-    { 0x0000a3c8, 0x00000246 },
-    { 0x0000a3cc, 0x20202020 },
-    { 0x0000a3d0, 0x20202020 },
-    { 0x0000a3d4, 0x20202020 },
-    { 0x0000a3dc, 0x1ce739ce },
-    { 0x0000a3e0, 0x000001ce },
-    { 0x0000a3e4, 0x00000000 },
-    { 0x0000a3e8, 0x18c43433 },
-    { 0x0000a3ec, 0x00f38081 },
-    { 0x00007800, 0x00040000 },
-    { 0x00007804, 0xdb005012 },
-    { 0x00007808, 0x04924914 },
-    { 0x0000780c, 0x21084210 },
-    { 0x00007810, 0x6d801300 },
-    { 0x00007814, 0x0019beff },
-    { 0x00007818, 0x07e40000 },
-    { 0x0000781c, 0x00492000 },
-    { 0x00007820, 0x92492480 },
-    { 0x00007824, 0x00040000 },
-    { 0x00007828, 0xdb005012 },
-    { 0x0000782c, 0x04924914 },
-    { 0x00007830, 0x21084210 },
-    { 0x00007834, 0x6d801300 },
-    { 0x00007838, 0x0019beff },
-    { 0x0000783c, 0x07e40000 },
-    { 0x00007840, 0x00492000 },
-    { 0x00007844, 0x92492480 },
-    { 0x00007848, 0x00120000 },
-    { 0x00007850, 0x54214514 },
-    { 0x00007858, 0x92592692 },
-    { 0x00007860, 0x52802000 },
-    { 0x00007864, 0x0a8e370e },
-    { 0x00007868, 0xc0102850 },
-    { 0x0000786c, 0x812d4000 },
-    { 0x00007874, 0x001b6db0 },
-    { 0x00007878, 0x00376b63 },
-    { 0x0000787c, 0x06db6db6 },
-    { 0x00007880, 0x006d8000 },
-    { 0x00007884, 0xffeffffe },
-    { 0x00007888, 0xffeffffe },
-    { 0x00007890, 0x00060aeb },
-    { 0x00007894, 0x5a108000 },
-    { 0x00007898, 0x2a850160 },
-};
-
-/* XXX 9280 2 */
-static const u32 ar9280Modes_9280_2[][6] = {
-    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
-    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
-    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
-    { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
-    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
-    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
-    { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
-    { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a },
-    { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
-    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
-    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
-    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
-    { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e },
-    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
-    { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
-    { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
-    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e },
-    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
-    { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
-    { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
-    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
-    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
-    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
-    { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
-    { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 },
-    { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
-    { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
-    { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
-    { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c },
-    { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 },
-    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
-    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
-    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
-    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
-    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
-    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
-    { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
-    { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
-    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
-    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
-    { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 },
-    { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
-    { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
-};
-
-static const u32 ar9280Common_9280_2[][2] = {
-    { 0x0000000c, 0x00000000 },
-    { 0x00000030, 0x00020015 },
-    { 0x00000034, 0x00000005 },
-    { 0x00000040, 0x00000000 },
-    { 0x00000044, 0x00000008 },
-    { 0x00000048, 0x00000008 },
-    { 0x0000004c, 0x00000010 },
-    { 0x00000050, 0x00000000 },
-    { 0x00000054, 0x0000001f },
-    { 0x00000800, 0x00000000 },
-    { 0x00000804, 0x00000000 },
-    { 0x00000808, 0x00000000 },
-    { 0x0000080c, 0x00000000 },
-    { 0x00000810, 0x00000000 },
-    { 0x00000814, 0x00000000 },
-    { 0x00000818, 0x00000000 },
-    { 0x0000081c, 0x00000000 },
-    { 0x00000820, 0x00000000 },
-    { 0x00000824, 0x00000000 },
-    { 0x00001040, 0x002ffc0f },
-    { 0x00001044, 0x002ffc0f },
-    { 0x00001048, 0x002ffc0f },
-    { 0x0000104c, 0x002ffc0f },
-    { 0x00001050, 0x002ffc0f },
-    { 0x00001054, 0x002ffc0f },
-    { 0x00001058, 0x002ffc0f },
-    { 0x0000105c, 0x002ffc0f },
-    { 0x00001060, 0x002ffc0f },
-    { 0x00001064, 0x002ffc0f },
-    { 0x00001230, 0x00000000 },
-    { 0x00001270, 0x00000000 },
-    { 0x00001038, 0x00000000 },
-    { 0x00001078, 0x00000000 },
-    { 0x000010b8, 0x00000000 },
-    { 0x000010f8, 0x00000000 },
-    { 0x00001138, 0x00000000 },
-    { 0x00001178, 0x00000000 },
-    { 0x000011b8, 0x00000000 },
-    { 0x000011f8, 0x00000000 },
-    { 0x00001238, 0x00000000 },
-    { 0x00001278, 0x00000000 },
-    { 0x000012b8, 0x00000000 },
-    { 0x000012f8, 0x00000000 },
-    { 0x00001338, 0x00000000 },
-    { 0x00001378, 0x00000000 },
-    { 0x000013b8, 0x00000000 },
-    { 0x000013f8, 0x00000000 },
-    { 0x00001438, 0x00000000 },
-    { 0x00001478, 0x00000000 },
-    { 0x000014b8, 0x00000000 },
-    { 0x000014f8, 0x00000000 },
-    { 0x00001538, 0x00000000 },
-    { 0x00001578, 0x00000000 },
-    { 0x000015b8, 0x00000000 },
-    { 0x000015f8, 0x00000000 },
-    { 0x00001638, 0x00000000 },
-    { 0x00001678, 0x00000000 },
-    { 0x000016b8, 0x00000000 },
-    { 0x000016f8, 0x00000000 },
-    { 0x00001738, 0x00000000 },
-    { 0x00001778, 0x00000000 },
-    { 0x000017b8, 0x00000000 },
-    { 0x000017f8, 0x00000000 },
-    { 0x0000103c, 0x00000000 },
-    { 0x0000107c, 0x00000000 },
-    { 0x000010bc, 0x00000000 },
-    { 0x000010fc, 0x00000000 },
-    { 0x0000113c, 0x00000000 },
-    { 0x0000117c, 0x00000000 },
-    { 0x000011bc, 0x00000000 },
-    { 0x000011fc, 0x00000000 },
-    { 0x0000123c, 0x00000000 },
-    { 0x0000127c, 0x00000000 },
-    { 0x000012bc, 0x00000000 },
-    { 0x000012fc, 0x00000000 },
-    { 0x0000133c, 0x00000000 },
-    { 0x0000137c, 0x00000000 },
-    { 0x000013bc, 0x00000000 },
-    { 0x000013fc, 0x00000000 },
-    { 0x0000143c, 0x00000000 },
-    { 0x0000147c, 0x00000000 },
-    { 0x00004030, 0x00000002 },
-    { 0x0000403c, 0x00000002 },
-    { 0x00004024, 0x0000001f },
-    { 0x00004060, 0x00000000 },
-    { 0x00004064, 0x00000000 },
-    { 0x00007010, 0x00000033 },
-    { 0x00007034, 0x00000002 },
-    { 0x00007038, 0x000004c2 },
-    { 0x00008004, 0x00000000 },
-    { 0x00008008, 0x00000000 },
-    { 0x0000800c, 0x00000000 },
-    { 0x00008018, 0x00000700 },
-    { 0x00008020, 0x00000000 },
-    { 0x00008038, 0x00000000 },
-    { 0x0000803c, 0x00000000 },
-    { 0x00008048, 0x40000000 },
-    { 0x00008054, 0x00000000 },
-    { 0x00008058, 0x00000000 },
-    { 0x0000805c, 0x000fc78f },
-    { 0x00008060, 0x0000000f },
-    { 0x00008064, 0x00000000 },
-    { 0x00008070, 0x00000000 },
-    { 0x000080c0, 0x2a80001a },
-    { 0x000080c4, 0x05dc01e0 },
-    { 0x000080c8, 0x1f402710 },
-    { 0x000080cc, 0x01f40000 },
-    { 0x000080d0, 0x00001e00 },
-    { 0x000080d4, 0x00000000 },
-    { 0x000080d8, 0x00400000 },
-    { 0x000080e0, 0xffffffff },
-    { 0x000080e4, 0x0000ffff },
-    { 0x000080e8, 0x003f3f3f },
-    { 0x000080ec, 0x00000000 },
-    { 0x000080f0, 0x00000000 },
-    { 0x000080f4, 0x00000000 },
-    { 0x000080f8, 0x00000000 },
-    { 0x000080fc, 0x00020000 },
-    { 0x00008100, 0x00020000 },
-    { 0x00008104, 0x00000001 },
-    { 0x00008108, 0x00000052 },
-    { 0x0000810c, 0x00000000 },
-    { 0x00008110, 0x00000168 },
-    { 0x00008118, 0x000100aa },
-    { 0x0000811c, 0x00003210 },
-    { 0x00008124, 0x00000000 },
-    { 0x00008128, 0x00000000 },
-    { 0x0000812c, 0x00000000 },
-    { 0x00008130, 0x00000000 },
-    { 0x00008134, 0x00000000 },
-    { 0x00008138, 0x00000000 },
-    { 0x0000813c, 0x00000000 },
-    { 0x00008144, 0xffffffff },
-    { 0x00008168, 0x00000000 },
-    { 0x0000816c, 0x00000000 },
-    { 0x00008170, 0x32143320 },
-    { 0x00008174, 0xfaa4fa50 },
-    { 0x00008178, 0x00000100 },
-    { 0x0000817c, 0x00000000 },
-    { 0x000081c0, 0x00000000 },
-    { 0x000081ec, 0x00000000 },
-    { 0x000081f0, 0x00000000 },
-    { 0x000081f4, 0x00000000 },
-    { 0x000081f8, 0x00000000 },
-    { 0x000081fc, 0x00000000 },
-    { 0x00008200, 0x00000000 },
-    { 0x00008204, 0x00000000 },
-    { 0x00008208, 0x00000000 },
-    { 0x0000820c, 0x00000000 },
-    { 0x00008210, 0x00000000 },
-    { 0x00008214, 0x00000000 },
-    { 0x00008218, 0x00000000 },
-    { 0x0000821c, 0x00000000 },
-    { 0x00008220, 0x00000000 },
-    { 0x00008224, 0x00000000 },
-    { 0x00008228, 0x00000000 },
-    { 0x0000822c, 0x00000000 },
-    { 0x00008230, 0x00000000 },
-    { 0x00008234, 0x00000000 },
-    { 0x00008238, 0x00000000 },
-    { 0x0000823c, 0x00000000 },
-    { 0x00008240, 0x00100000 },
-    { 0x00008244, 0x0010f400 },
-    { 0x00008248, 0x00000100 },
-    { 0x0000824c, 0x0001e800 },
-    { 0x00008250, 0x00000000 },
-    { 0x00008254, 0x00000000 },
-    { 0x00008258, 0x00000000 },
-    { 0x0000825c, 0x400000ff },
-    { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
-    { 0x00008270, 0x00000000 },
-    { 0x00008274, 0x40000000 },
-    { 0x00008278, 0x003e4180 },
-    { 0x0000827c, 0x00000000 },
-    { 0x00008284, 0x0000002c },
-    { 0x00008288, 0x0000002c },
-    { 0x0000828c, 0x00000000 },
-    { 0x00008294, 0x00000000 },
-    { 0x00008298, 0x00000000 },
-    { 0x0000829c, 0x00000000 },
-    { 0x00008300, 0x00000040 },
-    { 0x00008314, 0x00000000 },
-    { 0x00008328, 0x00000000 },
-    { 0x0000832c, 0x00000007 },
-    { 0x00008330, 0x00000302 },
-    { 0x00008334, 0x00000e00 },
-    { 0x00008338, 0x00ff0000 },
-    { 0x0000833c, 0x00000000 },
-    { 0x00008340, 0x000107ff },
-    { 0x00008344, 0x00581043 },
-    { 0x00009808, 0x00000000 },
-    { 0x0000980c, 0xafa68e30 },
-    { 0x00009810, 0xfd14e000 },
-    { 0x00009814, 0x9c0a9f6b },
-    { 0x0000981c, 0x00000000 },
-    { 0x0000982c, 0x0000a000 },
-    { 0x00009830, 0x00000000 },
-    { 0x0000983c, 0x00200400 },
-    { 0x0000984c, 0x0040233c },
-    { 0x0000a84c, 0x0040233c },
-    { 0x00009854, 0x00000044 },
-    { 0x00009900, 0x00000000 },
-    { 0x00009904, 0x00000000 },
-    { 0x00009908, 0x00000000 },
-    { 0x0000990c, 0x00000000 },
-    { 0x00009910, 0x01002310 },
-    { 0x0000991c, 0x10000fff },
-    { 0x00009920, 0x04900000 },
-    { 0x0000a920, 0x04900000 },
-    { 0x00009928, 0x00000001 },
-    { 0x0000992c, 0x00000004 },
-    { 0x00009934, 0x1e1f2022 },
-    { 0x00009938, 0x0a0b0c0d },
-    { 0x0000993c, 0x00000000 },
-    { 0x00009948, 0x9280c00a },
-    { 0x0000994c, 0x00020028 },
-    { 0x00009954, 0x5f3ca3de },
-    { 0x00009958, 0x2108ecff },
-    { 0x00009940, 0x14750604 },
-    { 0x0000c95c, 0x004b6a8e },
-    { 0x0000c968, 0x000003ce },
-    { 0x00009970, 0x190fb515 },
-    { 0x00009974, 0x00000000 },
-    { 0x00009978, 0x00000001 },
-    { 0x0000997c, 0x00000000 },
-    { 0x00009980, 0x00000000 },
-    { 0x00009984, 0x00000000 },
-    { 0x00009988, 0x00000000 },
-    { 0x0000998c, 0x00000000 },
-    { 0x00009990, 0x00000000 },
-    { 0x00009994, 0x00000000 },
-    { 0x00009998, 0x00000000 },
-    { 0x0000999c, 0x00000000 },
-    { 0x000099a0, 0x00000000 },
-    { 0x000099a4, 0x00000001 },
-    { 0x000099a8, 0x201fff00 },
-    { 0x000099ac, 0x006f0000 },
-    { 0x000099b0, 0x03051000 },
-    { 0x000099b4, 0x00000820 },
-    { 0x000099dc, 0x00000000 },
-    { 0x000099e0, 0x00000000 },
-    { 0x000099e4, 0xaaaaaaaa },
-    { 0x000099e8, 0x3c466478 },
-    { 0x000099ec, 0x0cc80caa },
-    { 0x000099f0, 0x00000000 },
-    { 0x000099fc, 0x00001042 },
-    { 0x0000a208, 0x803e4788 },
-    { 0x0000a210, 0x4080a333 },
-    { 0x0000a214, 0x40206c10 },
-    { 0x0000a218, 0x009c4060 },
-    { 0x0000a220, 0x01834061 },
-    { 0x0000a224, 0x00000400 },
-    { 0x0000a228, 0x000003b5 },
-    { 0x0000a22c, 0x233f7180 },
-    { 0x0000a234, 0x20202020 },
-    { 0x0000a238, 0x20202020 },
-    { 0x0000a23c, 0x13c88000 },
-    { 0x0000a240, 0x38490a20 },
-    { 0x0000a244, 0x00007bb6 },
-    { 0x0000a248, 0x0fff3ffc },
-    { 0x0000a24c, 0x00000000 },
-    { 0x0000a254, 0x00000000 },
-    { 0x0000a258, 0x0cdbd380 },
-    { 0x0000a25c, 0x0f0f0f01 },
-    { 0x0000a260, 0xdfa91f01 },
-    { 0x0000a268, 0x00000000 },
-    { 0x0000a26c, 0x0ebae9c6 },
-    { 0x0000b26c, 0x0ebae9c6 },
-    { 0x0000d270, 0x00820820 },
-    { 0x0000a278, 0x1ce739ce },
-    { 0x0000d35c, 0x07ffffef },
-    { 0x0000d360, 0x0fffffe7 },
-    { 0x0000d364, 0x17ffffe5 },
-    { 0x0000d368, 0x1fffffe4 },
-    { 0x0000d36c, 0x37ffffe3 },
-    { 0x0000d370, 0x3fffffe3 },
-    { 0x0000d374, 0x57ffffe3 },
-    { 0x0000d378, 0x5fffffe2 },
-    { 0x0000d37c, 0x7fffffe2 },
-    { 0x0000d380, 0x7f3c7bba },
-    { 0x0000d384, 0xf3307ff0 },
-    { 0x0000a388, 0x0c000000 },
-    { 0x0000a38c, 0x20202020 },
-    { 0x0000a390, 0x20202020 },
-    { 0x0000a394, 0x1ce739ce },
-    { 0x0000a398, 0x000001ce },
-    { 0x0000a39c, 0x00000001 },
-    { 0x0000a3a0, 0x00000000 },
-    { 0x0000a3a4, 0x00000000 },
-    { 0x0000a3a8, 0x00000000 },
-    { 0x0000a3ac, 0x00000000 },
-    { 0x0000a3b0, 0x00000000 },
-    { 0x0000a3b4, 0x00000000 },
-    { 0x0000a3b8, 0x00000000 },
-    { 0x0000a3bc, 0x00000000 },
-    { 0x0000a3c0, 0x00000000 },
-    { 0x0000a3c4, 0x00000000 },
-    { 0x0000a3c8, 0x00000246 },
-    { 0x0000a3cc, 0x20202020 },
-    { 0x0000a3d0, 0x20202020 },
-    { 0x0000a3d4, 0x20202020 },
-    { 0x0000a3dc, 0x1ce739ce },
-    { 0x0000a3e0, 0x000001ce },
-    { 0x0000a3e4, 0x00000000 },
-    { 0x0000a3e8, 0x18c43433 },
-    { 0x0000a3ec, 0x00f70081 },
-    { 0x00007800, 0x00040000 },
-    { 0x00007804, 0xdb005012 },
-    { 0x00007808, 0x04924914 },
-    { 0x0000780c, 0x21084210 },
-    { 0x00007810, 0x6d801300 },
-    { 0x00007818, 0x07e41000 },
-    { 0x00007824, 0x00040000 },
-    { 0x00007828, 0xdb005012 },
-    { 0x0000782c, 0x04924914 },
-    { 0x00007830, 0x21084210 },
-    { 0x00007834, 0x6d801300 },
-    { 0x0000783c, 0x07e40000 },
-    { 0x00007848, 0x00100000 },
-    { 0x0000784c, 0x773f0567 },
-    { 0x00007850, 0x54214514 },
-    { 0x00007854, 0x12035828 },
-    { 0x00007858, 0x9259269a },
-    { 0x00007860, 0x52802000 },
-    { 0x00007864, 0x0a8e370e },
-    { 0x00007868, 0xc0102850 },
-    { 0x0000786c, 0x812d4000 },
-    { 0x00007870, 0x807ec400 },
-    { 0x00007874, 0x001b6db0 },
-    { 0x00007878, 0x00376b63 },
-    { 0x0000787c, 0x06db6db6 },
-    { 0x00007880, 0x006d8000 },
-    { 0x00007884, 0xffeffffe },
-    { 0x00007888, 0xffeffffe },
-    { 0x0000788c, 0x00010000 },
-    { 0x00007890, 0x02060aeb },
-    { 0x00007898, 0x2a850160 },
-};
-
-static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
-    { 0x00001030, 0x00000268, 0x000004d0 },
-    { 0x00001070, 0x0000018c, 0x00000318 },
-    { 0x000010b0, 0x00000fd0, 0x00001fa0 },
-    { 0x00008014, 0x044c044c, 0x08980898 },
-    { 0x0000801c, 0x148ec02b, 0x148ec057 },
-    { 0x00008318, 0x000044c0, 0x00008980 },
-    { 0x00009820, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000f0f, 0x00000f0f },
-    { 0x00009828, 0x0b020001, 0x0b020001 },
-    { 0x00009834, 0x00000f0f, 0x00000f0f },
-    { 0x00009844, 0x03721821, 0x03721821 },
-    { 0x00009914, 0x00000898, 0x00001130 },
-    { 0x00009918, 0x0000000b, 0x00000016 },
-};
-
-static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
-    { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
-    { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
-    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
-    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
-    { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
-    { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
-    { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
-    { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
-    { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
-    { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
-    { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
-    { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
-    { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
-    { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
-    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
-    { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
-    { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
-    { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
-    { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
-    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
-    { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
-    { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
-    { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
-    { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
-    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
-    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
-    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
-    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
-    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
-    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
-    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
-    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
-    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
-    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
-    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
-    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
-    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
-    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
-    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
-    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
-    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
-    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
-    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
-    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
-    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
-    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
-    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
-    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
-    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 },
-    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 },
-    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 },
-    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 },
-    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 },
-    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d },
-    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 },
-    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 },
-    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 },
-    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 },
-    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a },
-    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e },
-    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 },
-    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 },
-    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 },
-    { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 },
-    { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b },
-    { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f },
-    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 },
-    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 },
-    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 },
-    { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 },
-    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b },
-    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f },
-    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 },
-    { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 },
-    { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 },
-    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 },
-    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b },
-    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f },
-    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 },
-    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 },
-    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
-    { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
-    { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
-};
-
-static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
-    { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
-    { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
-    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
-    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
-    { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
-    { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
-    { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
-    { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
-    { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
-    { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
-    { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
-    { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
-    { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
-    { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
-    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
-    { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
-    { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
-    { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
-    { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
-    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
-    { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
-    { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
-    { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
-    { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
-    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
-    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
-    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
-    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
-    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
-    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
-    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
-    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
-    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
-    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
-    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
-    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
-    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
-    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
-    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
-    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
-    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
-    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
-    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
-    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
-    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
-    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
-    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
-    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
-    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
-    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
-    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
-    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
-    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
-    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
-    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
-    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
-    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
-    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
-    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
-    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
-    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
-    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
-    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
-    { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
-    { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
-    { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
-    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
-    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
-    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
-    { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
-    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
-    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
-    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
-    { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
-    { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
-    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
-    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
-    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
-    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
-    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
-    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
-    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
-    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
-    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
-    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
-    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
-    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
-    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
-    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
-    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
-    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
-    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
-    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
-    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
-    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
-    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
-    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
-    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
-    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
-    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
-    { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
-    { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
-};
-
-static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
-    { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
-    { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
-    { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
-    { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
-    { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
-    { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
-    { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
-    { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
-    { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
-    { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
-    { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
-    { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
-    { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
-    { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
-    { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
-    { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
-    { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
-    { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
-    { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
-    { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
-    { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
-    { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
-    { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
-    { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
-    { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
-    { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
-    { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
-    { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
-    { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
-    { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
-    { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
-    { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
-    { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
-    { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
-    { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
-    { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
-    { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
-    { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
-    { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
-    { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
-    { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
-    { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
-    { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
-    { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
-    { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
-    { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
-    { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
-    { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
-    { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
-    { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
-    { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
-    { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
-    { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
-    { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
-    { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
-    { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
-    { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
-    { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
-    { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 },
-    { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 },
-    { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 },
-    { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 },
-    { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 },
-    { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c },
-    { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 },
-    { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 },
-    { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 },
-    { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 },
-    { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 },
-    { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d },
-    { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 },
-    { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 },
-    { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 },
-    { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 },
-    { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a },
-    { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e },
-    { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 },
-    { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 },
-    { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 },
-    { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 },
-    { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b },
-    { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f },
-    { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 },
-    { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 },
-    { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 },
-    { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 },
-    { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b },
-    { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f },
-    { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 },
-    { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 },
-    { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
-    { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
-    { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
-};
-
-static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
-    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 },
-    { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 },
-    { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 },
-    { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 },
-    { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 },
-    { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a },
-    { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 },
-    { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
-    { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 },
-    { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 },
-    { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 },
-    { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 },
-    { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 },
-    { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 },
-    { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c },
-    { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a },
-    { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 },
-    { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 },
-    { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 },
-    { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 },
-    { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 },
-    { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
-    { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
-    { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
-    { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 },
-    { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
-    { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 },
-    { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
-    { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
-};
-
-static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
-    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
-    { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
-    { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
-    { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
-    { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
-    { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
-    { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
-    { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
-    { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
-    { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
-    { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
-    { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
-    { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
-    { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
-    { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
-    { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
-    { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
-    { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
-    { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
-    { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
-    { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
-    { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
-    { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
-    { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
-    { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 },
-    { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
-    { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 },
-    { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
-    { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
-};
-
-static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
-    {0x00004040,  0x9248fd00 },
-    {0x00004040,  0x24924924 },
-    {0x00004040,  0xa8000019 },
-    {0x00004040,  0x13160820 },
-    {0x00004040,  0xe5980560 },
-    {0x00004040,  0xc01dcffc },
-    {0x00004040,  0x1aaabe41 },
-    {0x00004040,  0xbe105554 },
-    {0x00004040,  0x00043007 },
-    {0x00004044,  0x00000000 },
-};
-
-static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
-    {0x00004040,  0x9248fd00 },
-    {0x00004040,  0x24924924 },
-    {0x00004040,  0xa8000019 },
-    {0x00004040,  0x13160820 },
-    {0x00004040,  0xe5980560 },
-    {0x00004040,  0xc01dcffd },
-    {0x00004040,  0x1aaabe41 },
-    {0x00004040,  0xbe105554 },
-    {0x00004040,  0x00043007 },
-    {0x00004044,  0x00000000 },
-};
-
-/* AR9285 */
-static const u_int32_t ar9285Modes_9285[][6] = {
-    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
-    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
-    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
-    { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
-    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
-    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
-    { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
-    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
-    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
-    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
-    { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
-    { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 },
-    { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 },
-    { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
-    { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
-    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e },
-    { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
-    { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
-    { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
-    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
-    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
-    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
-    { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
-    { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 },
-    { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c },
-    { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
-    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
-    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
-    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
-    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
-    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
-    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
-    { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
-    { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
-    { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
-    { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
-    { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
-    { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
-    { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
-    { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 },
-    { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
-    { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
-    { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
-    { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
-    { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
-    { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
-    { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
-    { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
-    { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
-    { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 },
-    { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 },
-    { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 },
-    { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
-    { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
-    { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 },
-    { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
-    { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
-    { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 },
-    { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 },
-    { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
-    { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
-    { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
-    { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
-    { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
-    { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
-    { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 },
-    { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
-    { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
-    { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 },
-    { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 },
-    { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 },
-    { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 },
-    { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 },
-    { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 },
-    { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 },
-    { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
-    { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
-    { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 },
-    { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 },
-    { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 },
-    { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 },
-    { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
-    { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
-    { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 },
-    { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 },
-    { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 },
-    { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 },
-    { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
-    { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
-    { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 },
-    { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 },
-    { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 },
-    { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 },
-    { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 },
-    { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 },
-    { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
-    { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
-    { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 },
-    { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
-    { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
-    { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
-    { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 },
-    { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
-    { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
-    { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 },
-    { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 },
-    { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
-    { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
-    { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 },
-    { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
-    { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
-    { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
-    { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
-    { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
-    { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
-    { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
-    { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 },
-    { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
-    { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 },
-    { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 },
-    { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
-    { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 },
-    { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 },
-    { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
-    { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
-    { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
-    { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
-    { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
-    { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
-    { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
-    { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
-    { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
-    { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
-    { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
-    { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
-    { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
-    { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
-    { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
-    { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
-    { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
-    { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
-    { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 },
-    { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 },
-    { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 },
-    { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
-    { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
-    { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
-    { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
-    { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 },
-    { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 },
-    { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 },
-    { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 },
-    { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 },
-    { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 },
-    { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 },
-    { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 },
-    { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 },
-    { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 },
-    { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 },
-    { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 },
-    { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 },
-    { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 },
-    { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 },
-    { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 },
-    { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 },
-    { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 },
-    { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
-    { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
-    { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
-    { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 },
-    { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
-    { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
-    { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 },
-    { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 },
-    { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 },
-    { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 },
-    { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
-    { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
-    { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 },
-    { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 },
-    { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 },
-    { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 },
-    { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 },
-    { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 },
-    { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 },
-    { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 },
-    { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
-    { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
-    { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
-    { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
-    { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
-    { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 },
-    { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 },
-    { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
-    { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
-    { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
-    { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
-    { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 },
-    { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
-    { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 },
-    { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
-    { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
-    { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 },
-    { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
-    { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
-    { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
-    { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
-    { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
-    { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
-    { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
-    { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
-    { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
-    { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 },
-    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
-    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
-    { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 },
-    { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 },
-    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
-    { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 },
-    { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 },
-    { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 },
-    { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 },
-    { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 },
-    { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 },
-    { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 },
-    { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 },
-    { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 },
-    { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 },
-    { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 },
-    { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 },
-    { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 },
-    { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 },
-    { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 },
-    { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
-};
-
-static const u_int32_t ar9285Common_9285[][2] = {
-    { 0x0000000c, 0x00000000 },
-    { 0x00000030, 0x00020045 },
-    { 0x00000034, 0x00000005 },
-    { 0x00000040, 0x00000000 },
-    { 0x00000044, 0x00000008 },
-    { 0x00000048, 0x00000008 },
-    { 0x0000004c, 0x00000010 },
-    { 0x00000050, 0x00000000 },
-    { 0x00000054, 0x0000001f },
-    { 0x00000800, 0x00000000 },
-    { 0x00000804, 0x00000000 },
-    { 0x00000808, 0x00000000 },
-    { 0x0000080c, 0x00000000 },
-    { 0x00000810, 0x00000000 },
-    { 0x00000814, 0x00000000 },
-    { 0x00000818, 0x00000000 },
-    { 0x0000081c, 0x00000000 },
-    { 0x00000820, 0x00000000 },
-    { 0x00000824, 0x00000000 },
-    { 0x00001040, 0x002ffc0f },
-    { 0x00001044, 0x002ffc0f },
-    { 0x00001048, 0x002ffc0f },
-    { 0x0000104c, 0x002ffc0f },
-    { 0x00001050, 0x002ffc0f },
-    { 0x00001054, 0x002ffc0f },
-    { 0x00001058, 0x002ffc0f },
-    { 0x0000105c, 0x002ffc0f },
-    { 0x00001060, 0x002ffc0f },
-    { 0x00001064, 0x002ffc0f },
-    { 0x00001230, 0x00000000 },
-    { 0x00001270, 0x00000000 },
-    { 0x00001038, 0x00000000 },
-    { 0x00001078, 0x00000000 },
-    { 0x000010b8, 0x00000000 },
-    { 0x000010f8, 0x00000000 },
-    { 0x00001138, 0x00000000 },
-    { 0x00001178, 0x00000000 },
-    { 0x000011b8, 0x00000000 },
-    { 0x000011f8, 0x00000000 },
-    { 0x00001238, 0x00000000 },
-    { 0x00001278, 0x00000000 },
-    { 0x000012b8, 0x00000000 },
-    { 0x000012f8, 0x00000000 },
-    { 0x00001338, 0x00000000 },
-    { 0x00001378, 0x00000000 },
-    { 0x000013b8, 0x00000000 },
-    { 0x000013f8, 0x00000000 },
-    { 0x00001438, 0x00000000 },
-    { 0x00001478, 0x00000000 },
-    { 0x000014b8, 0x00000000 },
-    { 0x000014f8, 0x00000000 },
-    { 0x00001538, 0x00000000 },
-    { 0x00001578, 0x00000000 },
-    { 0x000015b8, 0x00000000 },
-    { 0x000015f8, 0x00000000 },
-    { 0x00001638, 0x00000000 },
-    { 0x00001678, 0x00000000 },
-    { 0x000016b8, 0x00000000 },
-    { 0x000016f8, 0x00000000 },
-    { 0x00001738, 0x00000000 },
-    { 0x00001778, 0x00000000 },
-    { 0x000017b8, 0x00000000 },
-    { 0x000017f8, 0x00000000 },
-    { 0x0000103c, 0x00000000 },
-    { 0x0000107c, 0x00000000 },
-    { 0x000010bc, 0x00000000 },
-    { 0x000010fc, 0x00000000 },
-    { 0x0000113c, 0x00000000 },
-    { 0x0000117c, 0x00000000 },
-    { 0x000011bc, 0x00000000 },
-    { 0x000011fc, 0x00000000 },
-    { 0x0000123c, 0x00000000 },
-    { 0x0000127c, 0x00000000 },
-    { 0x000012bc, 0x00000000 },
-    { 0x000012fc, 0x00000000 },
-    { 0x0000133c, 0x00000000 },
-    { 0x0000137c, 0x00000000 },
-    { 0x000013bc, 0x00000000 },
-    { 0x000013fc, 0x00000000 },
-    { 0x0000143c, 0x00000000 },
-    { 0x0000147c, 0x00000000 },
-    { 0x00004030, 0x00000002 },
-    { 0x0000403c, 0x00000002 },
-    { 0x00004024, 0x0000001f },
-    { 0x00004060, 0x00000000 },
-    { 0x00004064, 0x00000000 },
-    { 0x00007010, 0x00000031 },
-    { 0x00007034, 0x00000002 },
-    { 0x00007038, 0x000004c2 },
-    { 0x00008004, 0x00000000 },
-    { 0x00008008, 0x00000000 },
-    { 0x0000800c, 0x00000000 },
-    { 0x00008018, 0x00000700 },
-    { 0x00008020, 0x00000000 },
-    { 0x00008038, 0x00000000 },
-    { 0x0000803c, 0x00000000 },
-    { 0x00008048, 0x00000000 },
-    { 0x00008054, 0x00000000 },
-    { 0x00008058, 0x00000000 },
-    { 0x0000805c, 0x000fc78f },
-    { 0x00008060, 0x0000000f },
-    { 0x00008064, 0x00000000 },
-    { 0x00008070, 0x00000000 },
-    { 0x000080c0, 0x2a80001a },
-    { 0x000080c4, 0x05dc01e0 },
-    { 0x000080c8, 0x1f402710 },
-    { 0x000080cc, 0x01f40000 },
-    { 0x000080d0, 0x00001e00 },
-    { 0x000080d4, 0x00000000 },
-    { 0x000080d8, 0x00400000 },
-    { 0x000080e0, 0xffffffff },
-    { 0x000080e4, 0x0000ffff },
-    { 0x000080e8, 0x003f3f3f },
-    { 0x000080ec, 0x00000000 },
-    { 0x000080f0, 0x00000000 },
-    { 0x000080f4, 0x00000000 },
-    { 0x000080f8, 0x00000000 },
-    { 0x000080fc, 0x00020000 },
-    { 0x00008100, 0x00020000 },
-    { 0x00008104, 0x00000001 },
-    { 0x00008108, 0x00000052 },
-    { 0x0000810c, 0x00000000 },
-    { 0x00008110, 0x00000168 },
-    { 0x00008118, 0x000100aa },
-    { 0x0000811c, 0x00003210 },
-    { 0x00008120, 0x08f04800 },
-    { 0x00008124, 0x00000000 },
-    { 0x00008128, 0x00000000 },
-    { 0x0000812c, 0x00000000 },
-    { 0x00008130, 0x00000000 },
-    { 0x00008134, 0x00000000 },
-    { 0x00008138, 0x00000000 },
-    { 0x0000813c, 0x00000000 },
-    { 0x00008144, 0x00000000 },
-    { 0x00008168, 0x00000000 },
-    { 0x0000816c, 0x00000000 },
-    { 0x00008170, 0x32143320 },
-    { 0x00008174, 0xfaa4fa50 },
-    { 0x00008178, 0x00000100 },
-    { 0x0000817c, 0x00000000 },
-    { 0x000081c0, 0x00000000 },
-    { 0x000081d0, 0x00003210 },
-    { 0x000081ec, 0x00000000 },
-    { 0x000081f0, 0x00000000 },
-    { 0x000081f4, 0x00000000 },
-    { 0x000081f8, 0x00000000 },
-    { 0x000081fc, 0x00000000 },
-    { 0x00008200, 0x00000000 },
-    { 0x00008204, 0x00000000 },
-    { 0x00008208, 0x00000000 },
-    { 0x0000820c, 0x00000000 },
-    { 0x00008210, 0x00000000 },
-    { 0x00008214, 0x00000000 },
-    { 0x00008218, 0x00000000 },
-    { 0x0000821c, 0x00000000 },
-    { 0x00008220, 0x00000000 },
-    { 0x00008224, 0x00000000 },
-    { 0x00008228, 0x00000000 },
-    { 0x0000822c, 0x00000000 },
-    { 0x00008230, 0x00000000 },
-    { 0x00008234, 0x00000000 },
-    { 0x00008238, 0x00000000 },
-    { 0x0000823c, 0x00000000 },
-    { 0x00008240, 0x00100000 },
-    { 0x00008244, 0x0010f400 },
-    { 0x00008248, 0x00000100 },
-    { 0x0000824c, 0x0001e800 },
-    { 0x00008250, 0x00000000 },
-    { 0x00008254, 0x00000000 },
-    { 0x00008258, 0x00000000 },
-    { 0x0000825c, 0x400000ff },
-    { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
-    { 0x00008270, 0x00000000 },
-    { 0x00008274, 0x40000000 },
-    { 0x00008278, 0x003e4180 },
-    { 0x0000827c, 0x00000000 },
-    { 0x00008284, 0x0000002c },
-    { 0x00008288, 0x0000002c },
-    { 0x0000828c, 0x00000000 },
-    { 0x00008294, 0x00000000 },
-    { 0x00008298, 0x00000000 },
-    { 0x0000829c, 0x00000000 },
-    { 0x00008300, 0x00000040 },
-    { 0x00008314, 0x00000000 },
-    { 0x00008328, 0x00000000 },
-    { 0x0000832c, 0x00000001 },
-    { 0x00008330, 0x00000302 },
-    { 0x00008334, 0x00000e00 },
-    { 0x00008338, 0x00000000 },
-    { 0x0000833c, 0x00000000 },
-    { 0x00008340, 0x00010380 },
-    { 0x00008344, 0x00581043 },
-    { 0x00009808, 0x00000000 },
-    { 0x0000980c, 0xafe68e30 },
-    { 0x00009810, 0xfd14e000 },
-    { 0x00009814, 0x9c0a9f6b },
-    { 0x0000981c, 0x00000000 },
-    { 0x0000982c, 0x0000a000 },
-    { 0x00009830, 0x00000000 },
-    { 0x0000983c, 0x00200400 },
-    { 0x0000984c, 0x0040233c },
-    { 0x00009854, 0x00000044 },
-    { 0x00009900, 0x00000000 },
-    { 0x00009904, 0x00000000 },
-    { 0x00009908, 0x00000000 },
-    { 0x0000990c, 0x00000000 },
-    { 0x00009910, 0x01002310 },
-    { 0x0000991c, 0x10000fff },
-    { 0x00009920, 0x04900000 },
-    { 0x00009928, 0x00000001 },
-    { 0x0000992c, 0x00000004 },
-    { 0x00009934, 0x1e1f2022 },
-    { 0x00009938, 0x0a0b0c0d },
-    { 0x0000993c, 0x00000000 },
-    { 0x00009940, 0x14750604 },
-    { 0x00009948, 0x9280c00a },
-    { 0x0000994c, 0x00020028 },
-    { 0x00009954, 0x5f3ca3de },
-    { 0x00009958, 0x2108ecff },
-    { 0x00009968, 0x000003ce },
-    { 0x00009970, 0x1927b515 },
-    { 0x00009974, 0x00000000 },
-    { 0x00009978, 0x00000001 },
-    { 0x0000997c, 0x00000000 },
-    { 0x00009980, 0x00000000 },
-    { 0x00009984, 0x00000000 },
-    { 0x00009988, 0x00000000 },
-    { 0x0000998c, 0x00000000 },
-    { 0x00009990, 0x00000000 },
-    { 0x00009994, 0x00000000 },
-    { 0x00009998, 0x00000000 },
-    { 0x0000999c, 0x00000000 },
-    { 0x000099a0, 0x00000000 },
-    { 0x000099a4, 0x00000001 },
-    { 0x000099a8, 0x201fff00 },
-    { 0x000099ac, 0x2def0a00 },
-    { 0x000099b0, 0x03051000 },
-    { 0x000099b4, 0x00000820 },
-    { 0x000099dc, 0x00000000 },
-    { 0x000099e0, 0x00000000 },
-    { 0x000099e4, 0xaaaaaaaa },
-    { 0x000099e8, 0x3c466478 },
-    { 0x000099ec, 0x0cc80caa },
-    { 0x000099f0, 0x00000000 },
-    { 0x0000a208, 0x803e6788 },
-    { 0x0000a210, 0x4080a333 },
-    { 0x0000a214, 0x00206c10 },
-    { 0x0000a218, 0x009c4060 },
-    { 0x0000a220, 0x01834061 },
-    { 0x0000a224, 0x00000400 },
-    { 0x0000a228, 0x000003b5 },
-    { 0x0000a22c, 0x00000000 },
-    { 0x0000a234, 0x20202020 },
-    { 0x0000a238, 0x20202020 },
-    { 0x0000a244, 0x00000000 },
-    { 0x0000a248, 0xfffffffc },
-    { 0x0000a24c, 0x00000000 },
-    { 0x0000a254, 0x00000000 },
-    { 0x0000a258, 0x0ccb5380 },
-    { 0x0000a25c, 0x15151501 },
-    { 0x0000a260, 0xdfa90f01 },
-    { 0x0000a268, 0x00000000 },
-    { 0x0000a26c, 0x0ebae9e6 },
-    { 0x0000d270, 0x0d820820 },
-    { 0x0000a278, 0x39ce739c },
-    { 0x0000a27c, 0x050e039c },
-    { 0x0000d35c, 0x07ffffef },
-    { 0x0000d360, 0x0fffffe7 },
-    { 0x0000d364, 0x17ffffe5 },
-    { 0x0000d368, 0x1fffffe4 },
-    { 0x0000d36c, 0x37ffffe3 },
-    { 0x0000d370, 0x3fffffe3 },
-    { 0x0000d374, 0x57ffffe3 },
-    { 0x0000d378, 0x5fffffe2 },
-    { 0x0000d37c, 0x7fffffe2 },
-    { 0x0000d380, 0x7f3c7bba },
-    { 0x0000d384, 0xf3307ff0 },
-    { 0x0000a388, 0x0c000000 },
-    { 0x0000a38c, 0x20202020 },
-    { 0x0000a390, 0x20202020 },
-    { 0x0000a394, 0x39ce739c },
-    { 0x0000a398, 0x0000039c },
-    { 0x0000a39c, 0x00000001 },
-    { 0x0000a3a0, 0x00000000 },
-    { 0x0000a3a4, 0x00000000 },
-    { 0x0000a3a8, 0x00000000 },
-    { 0x0000a3ac, 0x00000000 },
-    { 0x0000a3b0, 0x00000000 },
-    { 0x0000a3b4, 0x00000000 },
-    { 0x0000a3b8, 0x00000000 },
-    { 0x0000a3bc, 0x00000000 },
-    { 0x0000a3c0, 0x00000000 },
-    { 0x0000a3c4, 0x00000000 },
-    { 0x0000a3cc, 0x20202020 },
-    { 0x0000a3d0, 0x20202020 },
-    { 0x0000a3d4, 0x20202020 },
-    { 0x0000a3dc, 0x39ce739c },
-    { 0x0000a3e0, 0x0000039c },
-    { 0x0000a3e4, 0x00000000 },
-    { 0x0000a3e8, 0x18c43433 },
-    { 0x0000a3ec, 0x00f70081 },
-    { 0x00007800, 0x00140000 },
-    { 0x00007804, 0x0e4548d8 },
-    { 0x00007808, 0x54214514 },
-    { 0x0000780c, 0x02025820 },
-    { 0x00007810, 0x71c0d388 },
-    { 0x00007814, 0x924934a8 },
-    { 0x0000781c, 0x00000000 },
-    { 0x00007820, 0x00000c04 },
-    { 0x00007824, 0x00d86fff },
-    { 0x00007828, 0x26d2491b },
-    { 0x0000782c, 0x6e36d97b },
-    { 0x00007830, 0xedb6d96c },
-    { 0x00007834, 0x71400086 },
-    { 0x00007838, 0xfac68800 },
-    { 0x0000783c, 0x0001fffe },
-    { 0x00007840, 0xffeb1a20 },
-    { 0x00007844, 0x000c0db6 },
-    { 0x00007848, 0x6db61b6f },
-    { 0x0000784c, 0x6d9b66db },
-    { 0x00007850, 0x6d8c6dba },
-    { 0x00007854, 0x00040000 },
-    { 0x00007858, 0xdb003012 },
-    { 0x0000785c, 0x04924914 },
-    { 0x00007860, 0x21084210 },
-    { 0x00007864, 0xf7d7ffde },
-    { 0x00007868, 0xc2034080 },
-    { 0x0000786c, 0x48609eb4 },
-    { 0x00007870, 0x10142c00 },
-};
-
-static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {
-    {0x00004040,  0x9248fd00 },
-    {0x00004040,  0x24924924 },
-    {0x00004040,  0xa8000019 },
-    {0x00004040,  0x13160820 },
-    {0x00004040,  0xe5980560 },
-    {0x00004040,  0xc01dcffd },
-    {0x00004040,  0x1aaabe41 },
-    {0x00004040,  0xbe105554 },
-    {0x00004040,  0x00043007 },
-    {0x00004044,  0x00000000 },
-};
-
-static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = {
-    {0x00004040,  0x9248fd00 },
-    {0x00004040,  0x24924924 },
-    {0x00004040,  0xa8000019 },
-    {0x00004040,  0x13160820 },
-    {0x00004040,  0xe5980560 },
-    {0x00004040,  0xc01dcffc },
-    {0x00004040,  0x1aaabe41 },
-    {0x00004040,  0xbe105554 },
-    {0x00004040,  0x00043007 },
-    {0x00004044,  0x00000000 },
-};
-
-/* AR9285 v1_2 PCI Register Writes.  Created: 03/04/09 */
-static const u_int32_t ar9285Modes_9285_1_2[][6] = {
-    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
-    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
-    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
-    { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
-    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
-    { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
-    { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
-    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
-    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
-    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
-    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
-    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
-    { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
-    { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 },
-    { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 },
-    { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
-    { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
-    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },
-    { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
-    { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
-    { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
-    { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
-    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
-    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
-    { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
-    { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 },
-    { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c },
-    { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
-    { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
-    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
-    { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 },
-    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
-    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
-    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
-    { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
-    { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
-    { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
-    { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
-    { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
-    { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
-    { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
-    { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
-    { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
-    { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
-    { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
-    { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
-    { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
-    { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
-    { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
-    { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
-    { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
-    { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
-    { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
-    { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
-    { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
-    { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
-    { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
-    { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
-    { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
-    { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
-    { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
-    { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
-    { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
-    { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
-    { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
-    { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
-    { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
-    { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
-    { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
-    { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
-    { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
-    { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
-    { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
-    { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
-    { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
-    { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
-    { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
-    { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
-    { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
-    { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
-    { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
-    { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
-    { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
-    { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
-    { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
-    { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
-    { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
-    { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
-    { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
-    { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
-    { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
-    { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
-    { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
-    { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
-    { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
-    { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
-    { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
-    { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
-    { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
-    { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
-    { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
-    { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
-    { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
-    { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
-    { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
-    { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
-    { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
-    { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
-    { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
-    { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
-    { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
-    { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
-    { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
-    { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
-    { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
-    { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
-    { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
-    { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
-    { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
-    { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
-    { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
-    { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
-    { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 },
-    { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 },
-    { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 },
-    { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 },
-    { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 },
-    { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 },
-    { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 },
-    { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 },
-    { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 },
-    { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 },
-    { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 },
-    { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 },
-    { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 },
-    { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 },
-    { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 },
-    { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 },
-    { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 },
-    { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 },
-    { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 },
-    { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 },
-    { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 },
-    { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 },
-    { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 },
-    { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 },
-    { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 },
-    { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 },
-    { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 },
-    { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 },
-    { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
-    { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
-    { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
-    { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
-    { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
-    { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
-    { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 },
-    { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
-    { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 },
-    { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 },
-    { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 },
-    { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 },
-    { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 },
-    { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 },
-    { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 },
-    { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 },
-    { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 },
-    { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 },
-    { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 },
-    { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 },
-    { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 },
-    { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 },
-    { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 },
-    { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 },
-    { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 },
-    { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 },
-    { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 },
-    { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 },
-    { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 },
-    { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 },
-    { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 },
-    { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 },
-    { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 },
-    { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 },
-    { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 },
-    { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 },
-    { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 },
-    { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 },
-    { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 },
-    { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 },
-    { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 },
-    { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 },
-    { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 },
-    { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 },
-    { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 },
-    { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 },
-    { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 },
-    { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 },
-    { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 },
-    { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 },
-    { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 },
-    { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 },
-    { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 },
-    { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 },
-    { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 },
-    { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 },
-    { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 },
-    { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 },
-    { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 },
-    { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 },
-    { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 },
-    { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 },
-    { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
-    { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 },
-    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
-    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
-    { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
-    { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
-};
-
-static const u_int32_t ar9285Common_9285_1_2[][2] = {
-    { 0x0000000c, 0x00000000 },
-    { 0x00000030, 0x00020045 },
-    { 0x00000034, 0x00000005 },
-    { 0x00000040, 0x00000000 },
-    { 0x00000044, 0x00000008 },
-    { 0x00000048, 0x00000008 },
-    { 0x0000004c, 0x00000010 },
-    { 0x00000050, 0x00000000 },
-    { 0x00000054, 0x0000001f },
-    { 0x00000800, 0x00000000 },
-    { 0x00000804, 0x00000000 },
-    { 0x00000808, 0x00000000 },
-    { 0x0000080c, 0x00000000 },
-    { 0x00000810, 0x00000000 },
-    { 0x00000814, 0x00000000 },
-    { 0x00000818, 0x00000000 },
-    { 0x0000081c, 0x00000000 },
-    { 0x00000820, 0x00000000 },
-    { 0x00000824, 0x00000000 },
-    { 0x00001040, 0x002ffc0f },
-    { 0x00001044, 0x002ffc0f },
-    { 0x00001048, 0x002ffc0f },
-    { 0x0000104c, 0x002ffc0f },
-    { 0x00001050, 0x002ffc0f },
-    { 0x00001054, 0x002ffc0f },
-    { 0x00001058, 0x002ffc0f },
-    { 0x0000105c, 0x002ffc0f },
-    { 0x00001060, 0x002ffc0f },
-    { 0x00001064, 0x002ffc0f },
-    { 0x00001230, 0x00000000 },
-    { 0x00001270, 0x00000000 },
-    { 0x00001038, 0x00000000 },
-    { 0x00001078, 0x00000000 },
-    { 0x000010b8, 0x00000000 },
-    { 0x000010f8, 0x00000000 },
-    { 0x00001138, 0x00000000 },
-    { 0x00001178, 0x00000000 },
-    { 0x000011b8, 0x00000000 },
-    { 0x000011f8, 0x00000000 },
-    { 0x00001238, 0x00000000 },
-    { 0x00001278, 0x00000000 },
-    { 0x000012b8, 0x00000000 },
-    { 0x000012f8, 0x00000000 },
-    { 0x00001338, 0x00000000 },
-    { 0x00001378, 0x00000000 },
-    { 0x000013b8, 0x00000000 },
-    { 0x000013f8, 0x00000000 },
-    { 0x00001438, 0x00000000 },
-    { 0x00001478, 0x00000000 },
-    { 0x000014b8, 0x00000000 },
-    { 0x000014f8, 0x00000000 },
-    { 0x00001538, 0x00000000 },
-    { 0x00001578, 0x00000000 },
-    { 0x000015b8, 0x00000000 },
-    { 0x000015f8, 0x00000000 },
-    { 0x00001638, 0x00000000 },
-    { 0x00001678, 0x00000000 },
-    { 0x000016b8, 0x00000000 },
-    { 0x000016f8, 0x00000000 },
-    { 0x00001738, 0x00000000 },
-    { 0x00001778, 0x00000000 },
-    { 0x000017b8, 0x00000000 },
-    { 0x000017f8, 0x00000000 },
-    { 0x0000103c, 0x00000000 },
-    { 0x0000107c, 0x00000000 },
-    { 0x000010bc, 0x00000000 },
-    { 0x000010fc, 0x00000000 },
-    { 0x0000113c, 0x00000000 },
-    { 0x0000117c, 0x00000000 },
-    { 0x000011bc, 0x00000000 },
-    { 0x000011fc, 0x00000000 },
-    { 0x0000123c, 0x00000000 },
-    { 0x0000127c, 0x00000000 },
-    { 0x000012bc, 0x00000000 },
-    { 0x000012fc, 0x00000000 },
-    { 0x0000133c, 0x00000000 },
-    { 0x0000137c, 0x00000000 },
-    { 0x000013bc, 0x00000000 },
-    { 0x000013fc, 0x00000000 },
-    { 0x0000143c, 0x00000000 },
-    { 0x0000147c, 0x00000000 },
-    { 0x00004030, 0x00000002 },
-    { 0x0000403c, 0x00000002 },
-    { 0x00004024, 0x0000001f },
-    { 0x00004060, 0x00000000 },
-    { 0x00004064, 0x00000000 },
-    { 0x00007010, 0x00000031 },
-    { 0x00007034, 0x00000002 },
-    { 0x00007038, 0x000004c2 },
-    { 0x00008004, 0x00000000 },
-    { 0x00008008, 0x00000000 },
-    { 0x0000800c, 0x00000000 },
-    { 0x00008018, 0x00000700 },
-    { 0x00008020, 0x00000000 },
-    { 0x00008038, 0x00000000 },
-    { 0x0000803c, 0x00000000 },
-    { 0x00008048, 0x00000000 },
-    { 0x00008054, 0x00000000 },
-    { 0x00008058, 0x00000000 },
-    { 0x0000805c, 0x000fc78f },
-    { 0x00008060, 0x0000000f },
-    { 0x00008064, 0x00000000 },
-    { 0x00008070, 0x00000000 },
-    { 0x000080c0, 0x2a80001a },
-    { 0x000080c4, 0x05dc01e0 },
-    { 0x000080c8, 0x1f402710 },
-    { 0x000080cc, 0x01f40000 },
-    { 0x000080d0, 0x00001e00 },
-    { 0x000080d4, 0x00000000 },
-    { 0x000080d8, 0x00400000 },
-    { 0x000080e0, 0xffffffff },
-    { 0x000080e4, 0x0000ffff },
-    { 0x000080e8, 0x003f3f3f },
-    { 0x000080ec, 0x00000000 },
-    { 0x000080f0, 0x00000000 },
-    { 0x000080f4, 0x00000000 },
-    { 0x000080f8, 0x00000000 },
-    { 0x000080fc, 0x00020000 },
-    { 0x00008100, 0x00020000 },
-    { 0x00008104, 0x00000001 },
-    { 0x00008108, 0x00000052 },
-    { 0x0000810c, 0x00000000 },
-    { 0x00008110, 0x00000168 },
-    { 0x00008118, 0x000100aa },
-    { 0x0000811c, 0x00003210 },
-    { 0x00008120, 0x08f04810 },
-    { 0x00008124, 0x00000000 },
-    { 0x00008128, 0x00000000 },
-    { 0x0000812c, 0x00000000 },
-    { 0x00008130, 0x00000000 },
-    { 0x00008134, 0x00000000 },
-    { 0x00008138, 0x00000000 },
-    { 0x0000813c, 0x00000000 },
-    { 0x00008144, 0xffffffff },
-    { 0x00008168, 0x00000000 },
-    { 0x0000816c, 0x00000000 },
-    { 0x00008170, 0x32143320 },
-    { 0x00008174, 0xfaa4fa50 },
-    { 0x00008178, 0x00000100 },
-    { 0x0000817c, 0x00000000 },
-    { 0x000081c0, 0x00000000 },
-    { 0x000081d0, 0x0000320a },
-    { 0x000081ec, 0x00000000 },
-    { 0x000081f0, 0x00000000 },
-    { 0x000081f4, 0x00000000 },
-    { 0x000081f8, 0x00000000 },
-    { 0x000081fc, 0x00000000 },
-    { 0x00008200, 0x00000000 },
-    { 0x00008204, 0x00000000 },
-    { 0x00008208, 0x00000000 },
-    { 0x0000820c, 0x00000000 },
-    { 0x00008210, 0x00000000 },
-    { 0x00008214, 0x00000000 },
-    { 0x00008218, 0x00000000 },
-    { 0x0000821c, 0x00000000 },
-    { 0x00008220, 0x00000000 },
-    { 0x00008224, 0x00000000 },
-    { 0x00008228, 0x00000000 },
-    { 0x0000822c, 0x00000000 },
-    { 0x00008230, 0x00000000 },
-    { 0x00008234, 0x00000000 },
-    { 0x00008238, 0x00000000 },
-    { 0x0000823c, 0x00000000 },
-    { 0x00008240, 0x00100000 },
-    { 0x00008244, 0x0010f400 },
-    { 0x00008248, 0x00000100 },
-    { 0x0000824c, 0x0001e800 },
-    { 0x00008250, 0x00000000 },
-    { 0x00008254, 0x00000000 },
-    { 0x00008258, 0x00000000 },
-    { 0x0000825c, 0x400000ff },
-    { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
-    { 0x00008270, 0x00000000 },
-    { 0x00008274, 0x40000000 },
-    { 0x00008278, 0x003e4180 },
-    { 0x0000827c, 0x00000000 },
-    { 0x00008284, 0x0000002c },
-    { 0x00008288, 0x0000002c },
-    { 0x0000828c, 0x00000000 },
-    { 0x00008294, 0x00000000 },
-    { 0x00008298, 0x00000000 },
-    { 0x0000829c, 0x00000000 },
-    { 0x00008300, 0x00000040 },
-    { 0x00008314, 0x00000000 },
-    { 0x00008328, 0x00000000 },
-    { 0x0000832c, 0x00000001 },
-    { 0x00008330, 0x00000302 },
-    { 0x00008334, 0x00000e00 },
-    { 0x00008338, 0x00ff0000 },
-    { 0x0000833c, 0x00000000 },
-    { 0x00008340, 0x00010380 },
-    { 0x00008344, 0x00581043 },
-    { 0x00009808, 0x00000000 },
-    { 0x0000980c, 0xafe68e30 },
-    { 0x00009810, 0xfd14e000 },
-    { 0x00009814, 0x9c0a9f6b },
-    { 0x0000981c, 0x00000000 },
-    { 0x0000982c, 0x0000a000 },
-    { 0x00009830, 0x00000000 },
-    { 0x0000983c, 0x00200400 },
-    { 0x0000984c, 0x0040233c },
-    { 0x00009854, 0x00000044 },
-    { 0x00009900, 0x00000000 },
-    { 0x00009904, 0x00000000 },
-    { 0x00009908, 0x00000000 },
-    { 0x0000990c, 0x00000000 },
-    { 0x00009910, 0x01002310 },
-    { 0x0000991c, 0x10000fff },
-    { 0x00009920, 0x04900000 },
-    { 0x00009928, 0x00000001 },
-    { 0x0000992c, 0x00000004 },
-    { 0x00009934, 0x1e1f2022 },
-    { 0x00009938, 0x0a0b0c0d },
-    { 0x0000993c, 0x00000000 },
-    { 0x00009940, 0x14750604 },
-    { 0x00009948, 0x9280c00a },
-    { 0x0000994c, 0x00020028 },
-    { 0x00009954, 0x5f3ca3de },
-    { 0x00009958, 0x2108ecff },
-    { 0x00009968, 0x000003ce },
-    { 0x00009970, 0x192bb515 },
-    { 0x00009974, 0x00000000 },
-    { 0x00009978, 0x00000001 },
-    { 0x0000997c, 0x00000000 },
-    { 0x00009980, 0x00000000 },
-    { 0x00009984, 0x00000000 },
-    { 0x00009988, 0x00000000 },
-    { 0x0000998c, 0x00000000 },
-    { 0x00009990, 0x00000000 },
-    { 0x00009994, 0x00000000 },
-    { 0x00009998, 0x00000000 },
-    { 0x0000999c, 0x00000000 },
-    { 0x000099a0, 0x00000000 },
-    { 0x000099a4, 0x00000001 },
-    { 0x000099a8, 0x201fff00 },
-    { 0x000099ac, 0x2def0400 },
-    { 0x000099b0, 0x03051000 },
-    { 0x000099b4, 0x00000820 },
-    { 0x000099dc, 0x00000000 },
-    { 0x000099e0, 0x00000000 },
-    { 0x000099e4, 0xaaaaaaaa },
-    { 0x000099e8, 0x3c466478 },
-    { 0x000099ec, 0x0cc80caa },
-    { 0x000099f0, 0x00000000 },
-    { 0x0000a208, 0x803e68c8 },
-    { 0x0000a210, 0x4080a333 },
-    { 0x0000a214, 0x00206c10 },
-    { 0x0000a218, 0x009c4060 },
-    { 0x0000a220, 0x01834061 },
-    { 0x0000a224, 0x00000400 },
-    { 0x0000a228, 0x000003b5 },
-    { 0x0000a22c, 0x00000000 },
-    { 0x0000a234, 0x20202020 },
-    { 0x0000a238, 0x20202020 },
-    { 0x0000a244, 0x00000000 },
-    { 0x0000a248, 0xfffffffc },
-    { 0x0000a24c, 0x00000000 },
-    { 0x0000a254, 0x00000000 },
-    { 0x0000a258, 0x0ccb5380 },
-    { 0x0000a25c, 0x15151501 },
-    { 0x0000a260, 0xdfa90f01 },
-    { 0x0000a268, 0x00000000 },
-    { 0x0000a26c, 0x0ebae9e6 },
-    { 0x0000d270, 0x0d820820 },
-    { 0x0000d35c, 0x07ffffef },
-    { 0x0000d360, 0x0fffffe7 },
-    { 0x0000d364, 0x17ffffe5 },
-    { 0x0000d368, 0x1fffffe4 },
-    { 0x0000d36c, 0x37ffffe3 },
-    { 0x0000d370, 0x3fffffe3 },
-    { 0x0000d374, 0x57ffffe3 },
-    { 0x0000d378, 0x5fffffe2 },
-    { 0x0000d37c, 0x7fffffe2 },
-    { 0x0000d380, 0x7f3c7bba },
-    { 0x0000d384, 0xf3307ff0 },
-    { 0x0000a388, 0x0c000000 },
-    { 0x0000a38c, 0x20202020 },
-    { 0x0000a390, 0x20202020 },
-    { 0x0000a39c, 0x00000001 },
-    { 0x0000a3a0, 0x00000000 },
-    { 0x0000a3a4, 0x00000000 },
-    { 0x0000a3a8, 0x00000000 },
-    { 0x0000a3ac, 0x00000000 },
-    { 0x0000a3b0, 0x00000000 },
-    { 0x0000a3b4, 0x00000000 },
-    { 0x0000a3b8, 0x00000000 },
-    { 0x0000a3bc, 0x00000000 },
-    { 0x0000a3c0, 0x00000000 },
-    { 0x0000a3c4, 0x00000000 },
-    { 0x0000a3cc, 0x20202020 },
-    { 0x0000a3d0, 0x20202020 },
-    { 0x0000a3d4, 0x20202020 },
-    { 0x0000a3e4, 0x00000000 },
-    { 0x0000a3e8, 0x18c43433 },
-    { 0x0000a3ec, 0x00f70081 },
-    { 0x00007800, 0x00140000 },
-    { 0x00007804, 0x0e4548d8 },
-    { 0x00007808, 0x54214514 },
-    { 0x0000780c, 0x02025820 },
-    { 0x00007810, 0x71c0d388 },
-    { 0x00007814, 0x924934a8 },
-    { 0x0000781c, 0x00000000 },
-    { 0x00007824, 0x00d86fff },
-    { 0x00007828, 0x26d2491b },
-    { 0x0000782c, 0x6e36d97b },
-    { 0x00007830, 0xedb6d96e },
-    { 0x00007834, 0x71400087 },
-    { 0x0000783c, 0x0001fffe },
-    { 0x00007840, 0xffeb1a20 },
-    { 0x00007844, 0x000c0db6 },
-    { 0x00007848, 0x6db61b6f },
-    { 0x0000784c, 0x6d9b66db },
-    { 0x00007850, 0x6d8c6dba },
-    { 0x00007854, 0x00040000 },
-    { 0x00007858, 0xdb003012 },
-    { 0x0000785c, 0x04924914 },
-    { 0x00007860, 0x21084210 },
-    { 0x00007864, 0xf7d7ffde },
-    { 0x00007868, 0xc2034080 },
-    { 0x00007870, 0x10142c00 },
-};
-
-static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {
-    /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */
-    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 },
-    { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
-    { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 },
-    { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 },
-    { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 },
-    { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 },
-    { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 },
-    { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 },
-    { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 },
-    { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 },
-    { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 },
-    { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 },
-    { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 },
-    { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
-    { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
-    { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 },
-    { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe },
-    { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 },
-    { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
-    { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
-    { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
-    { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
-    { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
-    { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce },
-    { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce },
-};
-
-static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = {
-    /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */
-    { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-    { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },
-    { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 },
-    { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 },
-    { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 },
-    { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 },
-    { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 },
-    { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 },
-    { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 },
-    { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 },
-    { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 },
-    { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 },
-    { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 },
-    { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 },
-    { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 },
-    { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 },
-    { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
-    { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 },
-    { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 },
-    { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 },
-    { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 },
-    { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
-    { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c },
-    { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
-    { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
-    { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c },
-    { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },
-};
-
-static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
-    {0x00004040,  0x9248fd00 },
-    {0x00004040,  0x24924924 },
-    {0x00004040,  0xa8000019 },
-    {0x00004040,  0x13160820 },
-    {0x00004040,  0xe5980560 },
-    {0x00004040,  0xc01dcffd },
-    {0x00004040,  0x1aaabe41 },
-    {0x00004040,  0xbe105554 },
-    {0x00004040,  0x00043007 },
-    {0x00004044,  0x00000000 },
-};
-
-static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
-    {0x00004040,  0x9248fd00 },
-    {0x00004040,  0x24924924 },
-    {0x00004040,  0xa8000019 },
-    {0x00004040,  0x13160820 },
-    {0x00004040,  0xe5980560 },
-    {0x00004040,  0xc01dcffc },
-    {0x00004040,  0x1aaabe41 },
-    {0x00004040,  0xbe105554 },
-    {0x00004040,  0x00043007 },
-    {0x00004044,  0x00000000 },
-};
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-config ATH9K
-	tristate "Atheros 802.11n wireless cards support"
-	depends on PCI && MAC80211 && WLAN_80211
-	depends on RFKILL || RFKILL=n
-	select MAC80211_LEDS
-	select LEDS_CLASS
-	select NEW_LEDS
-	---help---
-	  This module adds support for wireless adapters based on
-	  Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
-
-	  If you choose to build a module, it'll be called ath9k.
-
-config ATH9K_DEBUG
-	bool "Atheros ath9k debugging"
-	depends on ATH9K
-	---help---
-	  Say Y, if you need ath9k to display debug messages.
-	  Pass the debug mask as a module parameter:
-
-	  modprobe ath9k debug=0x00002000
-
-	  Look in ath9k/core.h for possible debug masks
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/mac.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/mac.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/mac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/mac.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,965 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
-					struct ath9k_tx_queue_info *qi)
-{
-	DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
-		"tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
-		ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
-		ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
-		ah->txurn_interrupt_mask);
-
-	REG_WRITE(ah, AR_IMR_S0,
-		  SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
-		  | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
-	REG_WRITE(ah, AR_IMR_S1,
-		  SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
-		  | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
-	REG_RMW_FIELD(ah, AR_IMR_S2,
-		      AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask);
-}
-
-u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
-{
-	return REG_READ(ah, AR_QTXDP(q));
-}
-
-bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
-{
-	REG_WRITE(ah, AR_QTXDP(q), txdp);
-
-	return true;
-}
-
-bool ath9k_hw_txstart(struct ath_hw *ah, u32 q)
-{
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
-
-	REG_WRITE(ah, AR_Q_TXE, 1 << q);
-
-	return true;
-}
-
-u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
-{
-	u32 npend;
-
-	npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
-	if (npend == 0) {
-
-		if (REG_READ(ah, AR_Q_TXE) & (1 << q))
-			npend = 1;
-	}
-
-	return npend;
-}
-
-bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
-{
-	u32 txcfg, curLevel, newLevel;
-	enum ath9k_int omask;
-
-	if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD)
-		return false;
-
-	omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
-
-	txcfg = REG_READ(ah, AR_TXCFG);
-	curLevel = MS(txcfg, AR_FTRIG);
-	newLevel = curLevel;
-	if (bIncTrigLevel) {
-		if (curLevel < MAX_TX_FIFO_THRESHOLD)
-			newLevel++;
-	} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
-		newLevel--;
-	if (newLevel != curLevel)
-		REG_WRITE(ah, AR_TXCFG,
-			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
-
-	ath9k_hw_set_interrupts(ah, omask);
-
-	ah->tx_trig_level = newLevel;
-
-	return newLevel != curLevel;
-}
-
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
-{
-#define ATH9K_TX_STOP_DMA_TIMEOUT	4000    /* usec */
-#define ATH9K_TIME_QUANTUM		100     /* usec */
-
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	struct ath9k_tx_queue_info *qi;
-	u32 tsfLow, j, wait;
-	u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
-		return false;
-	}
-
-	qi = &ah->txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
-		return false;
-	}
-
-	REG_WRITE(ah, AR_Q_TXD, 1 << q);
-
-	for (wait = wait_time; wait != 0; wait--) {
-		if (ath9k_hw_numtxpending(ah, q) == 0)
-			break;
-		udelay(ATH9K_TIME_QUANTUM);
-	}
-
-	if (ath9k_hw_numtxpending(ah, q)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			"%s: Num of pending TX Frames %d on Q %d\n",
-			__func__, ath9k_hw_numtxpending(ah, q), q);
-
-		for (j = 0; j < 2; j++) {
-			tsfLow = REG_READ(ah, AR_TSF_L32);
-			REG_WRITE(ah, AR_QUIET2,
-				  SM(10, AR_QUIET2_QUIET_DUR));
-			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
-			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
-			REG_SET_BIT(ah, AR_TIMER_MODE,
-				       AR_QUIET_TIMER_EN);
-
-			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
-				break;
-
-			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				"TSF have moved while trying to set "
-				"quiet time TSF: 0x%08x\n", tsfLow);
-		}
-
-		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-
-		udelay(200);
-		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
-
-		wait = wait_time;
-		while (ath9k_hw_numtxpending(ah, q)) {
-			if ((--wait) == 0) {
-				DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
-					"Failed to stop Tx DMA in 100 "
-					"msec after killing last frame\n");
-				break;
-			}
-			udelay(ATH9K_TIME_QUANTUM);
-		}
-
-		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
-	}
-
-	REG_WRITE(ah, AR_Q_TXD, 0);
-	return wait != 0;
-
-#undef ATH9K_TX_STOP_DMA_TIMEOUT
-#undef ATH9K_TIME_QUANTUM
-}
-
-bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
-			 u32 segLen, bool firstSeg,
-			 bool lastSeg, const struct ath_desc *ds0)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	if (firstSeg) {
-		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
-	} else if (lastSeg) {
-		ads->ds_ctl0 = 0;
-		ads->ds_ctl1 = segLen;
-		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
-		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
-	} else {
-		ads->ds_ctl0 = 0;
-		ads->ds_ctl1 = segLen | AR_TxMore;
-		ads->ds_ctl2 = 0;
-		ads->ds_ctl3 = 0;
-	}
-	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
-	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
-	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
-	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
-	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-
-	return true;
-}
-
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
-	ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
-	ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
-	ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
-	ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-}
-
-int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	if ((ads->ds_txstatus9 & AR_TxDone) == 0)
-		return -EINPROGRESS;
-
-	ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
-	ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
-	ds->ds_txstat.ts_status = 0;
-	ds->ds_txstat.ts_flags = 0;
-
-	if (ads->ds_txstatus1 & AR_ExcessiveRetries)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
-	if (ads->ds_txstatus1 & AR_Filtered)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
-	if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
-		ath9k_hw_updatetxtriglevel(ah, true);
-	}
-	if (ads->ds_txstatus9 & AR_TxOpExceeded)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
-	if (ads->ds_txstatus1 & AR_TxTimerExpired)
-		ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
-	if (ads->ds_txstatus1 & AR_DescCfgErr)
-		ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
-	if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
-		ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
-		ath9k_hw_updatetxtriglevel(ah, true);
-	}
-	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
-		ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
-		ath9k_hw_updatetxtriglevel(ah, true);
-	}
-	if (ads->ds_txstatus0 & AR_TxBaStatus) {
-		ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
-		ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
-		ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
-	}
-
-	ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
-	switch (ds->ds_txstat.ts_rateindex) {
-	case 0:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
-		break;
-	case 1:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
-		break;
-	case 2:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
-		break;
-	case 3:
-		ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
-		break;
-	}
-
-	ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
-	ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
-	ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
-	ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
-	ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
-	ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
-	ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
-	ds->ds_txstat.evm0 = ads->AR_TxEVM0;
-	ds->ds_txstat.evm1 = ads->AR_TxEVM1;
-	ds->ds_txstat.evm2 = ads->AR_TxEVM2;
-	ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
-	ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
-	ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
-	ds->ds_txstat.ts_antenna = 0;
-
-	return 0;
-}
-
-void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
-			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
-			    u32 keyIx, enum ath9k_key_type keyType, u32 flags)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	txPower += ah->txpower_indexoffset;
-	if (txPower > 63)
-		txPower = 63;
-
-	ads->ds_ctl0 = (pktLen & AR_FrameLen)
-		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-		| SM(txPower, AR_XmitPower)
-		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
-		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
-		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
-
-	ads->ds_ctl1 =
-		(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
-		| SM(type, AR_FrameType)
-		| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-		| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-		| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-
-	ads->ds_ctl6 = SM(keyType, AR_EncrType);
-
-	if (AR_SREV_9285(ah)) {
-		ads->ds_ctl8 = 0;
-		ads->ds_ctl9 = 0;
-		ads->ds_ctl10 = 0;
-		ads->ds_ctl11 = 0;
-	}
-}
-
-void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
-				  struct ath_desc *lastds,
-				  u32 durUpdateEn, u32 rtsctsRate,
-				  u32 rtsctsDuration,
-				  struct ath9k_11n_rate_series series[],
-				  u32 nseries, u32 flags)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-	struct ar5416_desc *last_ads = AR5416DESC(lastds);
-	u32 ds_ctl0;
-
-	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
-		ds_ctl0 = ads->ds_ctl0;
-
-		if (flags & ATH9K_TXDESC_RTSENA) {
-			ds_ctl0 &= ~AR_CTSEnable;
-			ds_ctl0 |= AR_RTSEnable;
-		} else {
-			ds_ctl0 &= ~AR_RTSEnable;
-			ds_ctl0 |= AR_CTSEnable;
-		}
-
-		ads->ds_ctl0 = ds_ctl0;
-	} else {
-		ads->ds_ctl0 =
-			(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
-	}
-
-	ads->ds_ctl2 = set11nTries(series, 0)
-		| set11nTries(series, 1)
-		| set11nTries(series, 2)
-		| set11nTries(series, 3)
-		| (durUpdateEn ? AR_DurUpdateEna : 0)
-		| SM(0, AR_BurstDur);
-
-	ads->ds_ctl3 = set11nRate(series, 0)
-		| set11nRate(series, 1)
-		| set11nRate(series, 2)
-		| set11nRate(series, 3);
-
-	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
-		| set11nPktDurRTSCTS(series, 1);
-
-	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
-		| set11nPktDurRTSCTS(series, 3);
-
-	ads->ds_ctl7 = set11nRateFlags(series, 0)
-		| set11nRateFlags(series, 1)
-		| set11nRateFlags(series, 2)
-		| set11nRateFlags(series, 3)
-		| SM(rtsctsRate, AR_RTSCTSRate);
-	last_ads->ds_ctl2 = ads->ds_ctl2;
-	last_ads->ds_ctl3 = ads->ds_ctl3;
-}
-
-void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
-				u32 aggrLen)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-	ads->ds_ctl6 &= ~AR_AggrLen;
-	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
-}
-
-void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
-				 u32 numDelims)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-	unsigned int ctl6;
-
-	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-
-	ctl6 = ads->ds_ctl6;
-	ctl6 &= ~AR_PadDelim;
-	ctl6 |= SM(numDelims, AR_PadDelim);
-	ads->ds_ctl6 = ctl6;
-}
-
-void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl1 |= AR_IsAggr;
-	ads->ds_ctl1 &= ~AR_MoreAggr;
-	ads->ds_ctl6 &= ~AR_PadDelim;
-}
-
-void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
-}
-
-void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
-				   u32 burstDuration)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	ads->ds_ctl2 &= ~AR_BurstDur;
-	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
-}
-
-void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
-				     u32 vmf)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-
-	if (vmf)
-		ads->ds_ctl0 |= AR_VirtMoreFrag;
-	else
-		ads->ds_ctl0 &= ~AR_VirtMoreFrag;
-}
-
-void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
-{
-	*txqs &= ah->intr_txqs;
-	ah->intr_txqs &= ~(*txqs);
-}
-
-bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
-			    const struct ath9k_tx_queue_info *qinfo)
-{
-	u32 cw;
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	struct ath9k_tx_queue_info *qi;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
-		return false;
-	}
-
-	qi = &ah->txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
-		return false;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %p\n", qi);
-
-	qi->tqi_ver = qinfo->tqi_ver;
-	qi->tqi_subtype = qinfo->tqi_subtype;
-	qi->tqi_qflags = qinfo->tqi_qflags;
-	qi->tqi_priority = qinfo->tqi_priority;
-	if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
-		qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
-	else
-		qi->tqi_aifs = INIT_AIFS;
-	if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
-		cw = min(qinfo->tqi_cwmin, 1024U);
-		qi->tqi_cwmin = 1;
-		while (qi->tqi_cwmin < cw)
-			qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
-	} else
-		qi->tqi_cwmin = qinfo->tqi_cwmin;
-	if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
-		cw = min(qinfo->tqi_cwmax, 1024U);
-		qi->tqi_cwmax = 1;
-		while (qi->tqi_cwmax < cw)
-			qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
-	} else
-		qi->tqi_cwmax = INIT_CWMAX;
-
-	if (qinfo->tqi_shretry != 0)
-		qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
-	else
-		qi->tqi_shretry = INIT_SH_RETRY;
-	if (qinfo->tqi_lgretry != 0)
-		qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
-	else
-		qi->tqi_lgretry = INIT_LG_RETRY;
-	qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
-	qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
-	qi->tqi_burstTime = qinfo->tqi_burstTime;
-	qi->tqi_readyTime = qinfo->tqi_readyTime;
-
-	switch (qinfo->tqi_subtype) {
-	case ATH9K_WME_UPSD:
-		if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
-			qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
-		break;
-	default:
-		break;
-	}
-
-	return true;
-}
-
-bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
-			    struct ath9k_tx_queue_info *qinfo)
-{
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	struct ath9k_tx_queue_info *qi;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
-		return false;
-	}
-
-	qi = &ah->txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
-		return false;
-	}
-
-	qinfo->tqi_qflags = qi->tqi_qflags;
-	qinfo->tqi_ver = qi->tqi_ver;
-	qinfo->tqi_subtype = qi->tqi_subtype;
-	qinfo->tqi_qflags = qi->tqi_qflags;
-	qinfo->tqi_priority = qi->tqi_priority;
-	qinfo->tqi_aifs = qi->tqi_aifs;
-	qinfo->tqi_cwmin = qi->tqi_cwmin;
-	qinfo->tqi_cwmax = qi->tqi_cwmax;
-	qinfo->tqi_shretry = qi->tqi_shretry;
-	qinfo->tqi_lgretry = qi->tqi_lgretry;
-	qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
-	qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
-	qinfo->tqi_burstTime = qi->tqi_burstTime;
-	qinfo->tqi_readyTime = qi->tqi_readyTime;
-
-	return true;
-}
-
-int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
-			  const struct ath9k_tx_queue_info *qinfo)
-{
-	struct ath9k_tx_queue_info *qi;
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	int q;
-
-	switch (type) {
-	case ATH9K_TX_QUEUE_BEACON:
-		q = pCap->total_queues - 1;
-		break;
-	case ATH9K_TX_QUEUE_CAB:
-		q = pCap->total_queues - 2;
-		break;
-	case ATH9K_TX_QUEUE_PSPOLL:
-		q = 1;
-		break;
-	case ATH9K_TX_QUEUE_UAPSD:
-		q = pCap->total_queues - 3;
-		break;
-	case ATH9K_TX_QUEUE_DATA:
-		for (q = 0; q < pCap->total_queues; q++)
-			if (ah->txq[q].tqi_type ==
-			    ATH9K_TX_QUEUE_INACTIVE)
-				break;
-		if (q == pCap->total_queues) {
-			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				"no available tx queue\n");
-			return -1;
-		}
-		break;
-	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "bad tx queue type %u\n", type);
-		return -1;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
-
-	qi = &ah->txq[q];
-	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			"tx queue %u already active\n", q);
-		return -1;
-	}
-	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
-	qi->tqi_type = type;
-	if (qinfo == NULL) {
-		qi->tqi_qflags =
-			TXQ_FLAG_TXOKINT_ENABLE
-			| TXQ_FLAG_TXERRINT_ENABLE
-			| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
-		qi->tqi_aifs = INIT_AIFS;
-		qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
-		qi->tqi_cwmax = INIT_CWMAX;
-		qi->tqi_shretry = INIT_SH_RETRY;
-		qi->tqi_lgretry = INIT_LG_RETRY;
-		qi->tqi_physCompBuf = 0;
-	} else {
-		qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
-		(void) ath9k_hw_set_txq_props(ah, q, qinfo);
-	}
-
-	return q;
-}
-
-bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
-{
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	struct ath9k_tx_queue_info *qi;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
-		return false;
-	}
-	qi = &ah->txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
-		return false;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "release queue %u\n", q);
-
-	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
-	ah->txok_interrupt_mask &= ~(1 << q);
-	ah->txerr_interrupt_mask &= ~(1 << q);
-	ah->txdesc_interrupt_mask &= ~(1 << q);
-	ah->txeol_interrupt_mask &= ~(1 << q);
-	ah->txurn_interrupt_mask &= ~(1 << q);
-	ath9k_hw_set_txq_interrupts(ah, qi);
-
-	return true;
-}
-
-bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
-{
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	struct ath9k_channel *chan = ah->curchan;
-	struct ath9k_tx_queue_info *qi;
-	u32 cwMin, chanCwMin, value;
-
-	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
-		return false;
-	}
-
-	qi = &ah->txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
-		return true;
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "reset queue %u\n", q);
-
-	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
-		if (chan && IS_CHAN_B(chan))
-			chanCwMin = INIT_CWMIN_11B;
-		else
-			chanCwMin = INIT_CWMIN;
-
-		for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
-	} else
-		cwMin = qi->tqi_cwmin;
-
-	REG_WRITE(ah, AR_DLCL_IFS(q),
-		  SM(cwMin, AR_D_LCL_IFS_CWMIN) |
-		  SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
-		  SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
-
-	REG_WRITE(ah, AR_DRETRY_LIMIT(q),
-		  SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
-		  SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
-		  SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
-
-	REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
-	REG_WRITE(ah, AR_DMISC(q),
-		  AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
-
-	if (qi->tqi_cbrPeriod) {
-		REG_WRITE(ah, AR_QCBRCFG(q),
-			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
-			  SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
-		REG_WRITE(ah, AR_QMISC(q),
-			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
-			  (qi->tqi_cbrOverflowLimit ?
-			   AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
-	}
-	if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
-		REG_WRITE(ah, AR_QRDYTIMECFG(q),
-			  SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
-			  AR_Q_RDYTIMECFG_EN);
-	}
-
-	REG_WRITE(ah, AR_DCHNTIME(q),
-		  SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
-		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
-
-	if (qi->tqi_burstTime
-	    && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
-		REG_WRITE(ah, AR_QMISC(q),
-			  REG_READ(ah, AR_QMISC(q)) |
-			  AR_Q_MISC_RDYTIME_EXP_POLICY);
-
-	}
-
-	if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
-		REG_WRITE(ah, AR_DMISC(q),
-			  REG_READ(ah, AR_DMISC(q)) |
-			  AR_D_MISC_POST_FR_BKOFF_DIS);
-	}
-	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
-		REG_WRITE(ah, AR_DMISC(q),
-			  REG_READ(ah, AR_DMISC(q)) |
-			  AR_D_MISC_FRAG_BKOFF_EN);
-	}
-	switch (qi->tqi_type) {
-	case ATH9K_TX_QUEUE_BEACON:
-		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
-			  | AR_Q_MISC_FSP_DBA_GATED
-			  | AR_Q_MISC_BEACON_USE
-			  | AR_Q_MISC_CBR_INCR_DIS1);
-
-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
-			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
-			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
-			  | AR_D_MISC_BEACON_USE
-			  | AR_D_MISC_POST_FR_BKOFF_DIS);
-		break;
-	case ATH9K_TX_QUEUE_CAB:
-		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
-			  | AR_Q_MISC_FSP_DBA_GATED
-			  | AR_Q_MISC_CBR_INCR_DIS1
-			  | AR_Q_MISC_CBR_INCR_DIS0);
-		value = (qi->tqi_readyTime -
-			 (ah->config.sw_beacon_response_time -
-			  ah->config.dma_beacon_response_time) -
-			 ah->config.additional_swba_backoff) * 1024;
-		REG_WRITE(ah, AR_QRDYTIMECFG(q),
-			  value | AR_Q_RDYTIMECFG_EN);
-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
-			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
-			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
-		break;
-	case ATH9K_TX_QUEUE_PSPOLL:
-		REG_WRITE(ah, AR_QMISC(q),
-			  REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
-		break;
-	case ATH9K_TX_QUEUE_UAPSD:
-		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
-			  AR_D_MISC_POST_FR_BKOFF_DIS);
-		break;
-	default:
-		break;
-	}
-
-	if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
-		REG_WRITE(ah, AR_DMISC(q),
-			  REG_READ(ah, AR_DMISC(q)) |
-			  SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
-			     AR_D_MISC_ARB_LOCKOUT_CNTRL) |
-			  AR_D_MISC_POST_FR_BKOFF_DIS);
-	}
-
-	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
-		ah->txok_interrupt_mask |= 1 << q;
-	else
-		ah->txok_interrupt_mask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
-		ah->txerr_interrupt_mask |= 1 << q;
-	else
-		ah->txerr_interrupt_mask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
-		ah->txdesc_interrupt_mask |= 1 << q;
-	else
-		ah->txdesc_interrupt_mask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
-		ah->txeol_interrupt_mask |= 1 << q;
-	else
-		ah->txeol_interrupt_mask &= ~(1 << q);
-	if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
-		ah->txurn_interrupt_mask |= 1 << q;
-	else
-		ah->txurn_interrupt_mask &= ~(1 << q);
-	ath9k_hw_set_txq_interrupts(ah, qi);
-
-	return true;
-}
-
-int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
-			u32 pa, struct ath_desc *nds, u64 tsf)
-{
-	struct ar5416_desc ads;
-	struct ar5416_desc *adsp = AR5416DESC(ds);
-	u32 phyerr;
-
-	if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
-		return -EINPROGRESS;
-
-	ads.u.rx = adsp->u.rx;
-
-	ds->ds_rxstat.rs_status = 0;
-	ds->ds_rxstat.rs_flags = 0;
-
-	ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
-	ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
-
-	ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
-	ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
-	ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
-	ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
-	ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
-	ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
-	ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
-	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
-		ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
-	else
-		ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
-
-	ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
-	ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
-
-	ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
-	ds->ds_rxstat.rs_moreaggr =
-		(ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
-	ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
-	ds->ds_rxstat.rs_flags =
-		(ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
-	ds->ds_rxstat.rs_flags |=
-		(ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
-
-	if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
-		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
-	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
-		ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
-	if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
-		ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
-
-	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
-		if (ads.ds_rxstatus8 & AR_CRCErr)
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
-		else if (ads.ds_rxstatus8 & AR_PHYErr) {
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
-			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
-			ds->ds_rxstat.rs_phyerr = phyerr;
-		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
-		else if (ads.ds_rxstatus8 & AR_MichaelErr)
-			ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
-	}
-
-	return 0;
-}
-
-bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
-			  u32 size, u32 flags)
-{
-	struct ar5416_desc *ads = AR5416DESC(ds);
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-
-	ads->ds_ctl1 = size & AR_BufLen;
-	if (flags & ATH9K_RXDESC_INTREQ)
-		ads->ds_ctl1 |= AR_RxIntrReq;
-
-	ads->ds_rxstatus8 &= ~AR_RxDone;
-	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
-		memset(&(ads->u), 0, sizeof(ads->u));
-
-	return true;
-}
-
-bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
-{
-	u32 reg;
-
-	if (set) {
-		REG_SET_BIT(ah, AR_DIAG_SW,
-			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-
-		if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
-				   0, AH_WAIT_TIMEOUT)) {
-			REG_CLR_BIT(ah, AR_DIAG_SW,
-				    (AR_DIAG_RX_DIS |
-				     AR_DIAG_RX_ABORT));
-
-			reg = REG_READ(ah, AR_OBS_BUS_1);
-			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"rx failed to go idle in 10 ms RXSM=0x%x\n", reg);
-
-			return false;
-		}
-	} else {
-		REG_CLR_BIT(ah, AR_DIAG_SW,
-			    (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-	}
-
-	return true;
-}
-
-void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
-{
-	REG_WRITE(ah, AR_RXDP, rxdp);
-}
-
-void ath9k_hw_rxena(struct ath_hw *ah)
-{
-	REG_WRITE(ah, AR_CR, AR_CR_RXE);
-}
-
-void ath9k_hw_startpcureceive(struct ath_hw *ah)
-{
-	ath9k_enable_mib_counters(ah);
-
-	ath9k_ani_reset(ah);
-
-	REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-}
-
-void ath9k_hw_stoppcurecv(struct ath_hw *ah)
-{
-	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-
-	ath9k_hw_disable_mib_counters(ah);
-}
-
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
-{
-#define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
-#define AH_RX_TIME_QUANTUM     100     /* usec */
-
-	int i;
-
-	REG_WRITE(ah, AR_CR, AR_CR_RXD);
-
-	/* Wait for rx enable bit to go low */
-	for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
-		if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
-			break;
-		udelay(AH_TIME_QUANTUM);
-	}
-
-	if (i == 0) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			"dma failed to stop in %d ms "
-			"AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
-			AH_RX_STOP_DMA_TIMEOUT / 1000,
-			REG_READ(ah, AR_CR),
-			REG_READ(ah, AR_DIAG_SW));
-		return false;
-	} else {
-		return true;
-	}
-
-#undef AH_RX_TIME_QUANTUM
-#undef AH_RX_STOP_DMA_TIMEOUT
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/mac.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/mac.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/mac.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/mac.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,680 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MAC_H
-#define MAC_H
-
-#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ?		\
-				MS(ads->ds_rxstatus0, AR_RxRate) :	\
-				(ads->ds_rxstatus3 >> 2) & 0xFF)
-
-#define set11nTries(_series, _index) \
-	(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
-
-#define set11nRate(_series, _index) \
-	(SM((_series)[_index].Rate, AR_XmitRate##_index))
-
-#define set11nPktDurRTSCTS(_series, _index)				\
-	(SM((_series)[_index].PktDuration, AR_PacketDur##_index) |	\
-	 ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS   ?	\
-	  AR_RTSCTSQual##_index : 0))
-
-#define set11nRateFlags(_series, _index)				\
-	(((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ?		\
-	  AR_2040_##_index : 0)						\
-	 |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ?	\
-	   AR_GI##_index : 0)						\
-	 |SM((_series)[_index].ChSel, AR_ChainSel##_index))
-
-#define CCK_SIFS_TIME        10
-#define CCK_PREAMBLE_BITS   144
-#define CCK_PLCP_BITS        48
-
-#define OFDM_SIFS_TIME        16
-#define OFDM_PREAMBLE_TIME    20
-#define OFDM_PLCP_BITS        22
-#define OFDM_SYMBOL_TIME      4
-
-#define OFDM_SIFS_TIME_HALF     32
-#define OFDM_PREAMBLE_TIME_HALF 40
-#define OFDM_PLCP_BITS_HALF     22
-#define OFDM_SYMBOL_TIME_HALF   8
-
-#define OFDM_SIFS_TIME_QUARTER      64
-#define OFDM_PREAMBLE_TIME_QUARTER  80
-#define OFDM_PLCP_BITS_QUARTER      22
-#define OFDM_SYMBOL_TIME_QUARTER    16
-
-#define INIT_AIFS       2
-#define INIT_CWMIN      15
-#define INIT_CWMIN_11B  31
-#define INIT_CWMAX      1023
-#define INIT_SH_RETRY   10
-#define INIT_LG_RETRY   10
-#define INIT_SSH_RETRY  32
-#define INIT_SLG_RETRY  32
-
-#define ATH9K_SLOT_TIME_6 6
-#define ATH9K_SLOT_TIME_9 9
-#define ATH9K_SLOT_TIME_20 20
-
-#define ATH9K_TXERR_XRETRY         0x01
-#define ATH9K_TXERR_FILT           0x02
-#define ATH9K_TXERR_FIFO           0x04
-#define ATH9K_TXERR_XTXOP          0x08
-#define ATH9K_TXERR_TIMER_EXPIRED  0x10
-
-#define ATH9K_TX_BA                0x01
-#define ATH9K_TX_PWRMGMT           0x02
-#define ATH9K_TX_DESC_CFG_ERR      0x04
-#define ATH9K_TX_DATA_UNDERRUN     0x08
-#define ATH9K_TX_DELIM_UNDERRUN    0x10
-#define ATH9K_TX_SW_ABORTED        0x40
-#define ATH9K_TX_SW_FILTERED       0x80
-
-#define MIN_TX_FIFO_THRESHOLD   0x1
-#define MAX_TX_FIFO_THRESHOLD   ((4096 / 64) - 1)
-#define INIT_TX_FIFO_THRESHOLD  MIN_TX_FIFO_THRESHOLD
-
-struct ath_tx_status {
-	u32 ts_tstamp;
-	u16 ts_seqnum;
-	u8 ts_status;
-	u8 ts_ratecode;
-	u8 ts_rateindex;
-	int8_t ts_rssi;
-	u8 ts_shortretry;
-	u8 ts_longretry;
-	u8 ts_virtcol;
-	u8 ts_antenna;
-	u8 ts_flags;
-	int8_t ts_rssi_ctl0;
-	int8_t ts_rssi_ctl1;
-	int8_t ts_rssi_ctl2;
-	int8_t ts_rssi_ext0;
-	int8_t ts_rssi_ext1;
-	int8_t ts_rssi_ext2;
-	u8 pad[3];
-	u32 ba_low;
-	u32 ba_high;
-	u32 evm0;
-	u32 evm1;
-	u32 evm2;
-};
-
-struct ath_rx_status {
-	u32 rs_tstamp;
-	u16 rs_datalen;
-	u8 rs_status;
-	u8 rs_phyerr;
-	int8_t rs_rssi;
-	u8 rs_keyix;
-	u8 rs_rate;
-	u8 rs_antenna;
-	u8 rs_more;
-	int8_t rs_rssi_ctl0;
-	int8_t rs_rssi_ctl1;
-	int8_t rs_rssi_ctl2;
-	int8_t rs_rssi_ext0;
-	int8_t rs_rssi_ext1;
-	int8_t rs_rssi_ext2;
-	u8 rs_isaggr;
-	u8 rs_moreaggr;
-	u8 rs_num_delims;
-	u8 rs_flags;
-	u32 evm0;
-	u32 evm1;
-	u32 evm2;
-};
-
-#define ATH9K_RXERR_CRC           0x01
-#define ATH9K_RXERR_PHY           0x02
-#define ATH9K_RXERR_FIFO          0x04
-#define ATH9K_RXERR_DECRYPT       0x08
-#define ATH9K_RXERR_MIC           0x10
-
-#define ATH9K_RX_MORE             0x01
-#define ATH9K_RX_MORE_AGGR        0x02
-#define ATH9K_RX_GI               0x04
-#define ATH9K_RX_2040             0x08
-#define ATH9K_RX_DELIM_CRC_PRE    0x10
-#define ATH9K_RX_DELIM_CRC_POST   0x20
-#define ATH9K_RX_DECRYPT_BUSY     0x40
-
-#define ATH9K_RXKEYIX_INVALID	((u8)-1)
-#define ATH9K_TXKEYIX_INVALID	((u32)-1)
-
-struct ath_desc {
-	u32 ds_link;
-	u32 ds_data;
-	u32 ds_ctl0;
-	u32 ds_ctl1;
-	u32 ds_hw[20];
-	union {
-		struct ath_tx_status tx;
-		struct ath_rx_status rx;
-		void *stats;
-	} ds_us;
-	void *ds_vdata;
-} __packed;
-
-#define	ds_txstat	ds_us.tx
-#define	ds_rxstat	ds_us.rx
-#define ds_stat		ds_us.stats
-
-#define ATH9K_TXDESC_CLRDMASK		0x0001
-#define ATH9K_TXDESC_NOACK		0x0002
-#define ATH9K_TXDESC_RTSENA		0x0004
-#define ATH9K_TXDESC_CTSENA		0x0008
-/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
- * the descriptor its marked on.  We take a tx interrupt to reap
- * descriptors when the h/w hits an EOL condition or
- * when the descriptor is specifically marked to generate
- * an interrupt with this flag. Descriptors should be
- * marked periodically to insure timely replenishing of the
- * supply needed for sending frames. Defering interrupts
- * reduces system load and potentially allows more concurrent
- * work to be done but if done to aggressively can cause
- * senders to backup. When the hardware queue is left too
- * large rate control information may also be too out of
- * date. An Alternative for this is TX interrupt mitigation
- * but this needs more testing. */
-#define ATH9K_TXDESC_INTREQ		0x0010
-#define ATH9K_TXDESC_VEOL		0x0020
-#define ATH9K_TXDESC_EXT_ONLY		0x0040
-#define ATH9K_TXDESC_EXT_AND_CTL	0x0080
-#define ATH9K_TXDESC_VMF		0x0100
-#define ATH9K_TXDESC_FRAG_IS_ON 	0x0200
-#define ATH9K_TXDESC_CAB		0x0400
-
-#define ATH9K_RXDESC_INTREQ		0x0020
-
-struct ar5416_desc {
-	u32 ds_link;
-	u32 ds_data;
-	u32 ds_ctl0;
-	u32 ds_ctl1;
-	union {
-		struct {
-			u32 ctl2;
-			u32 ctl3;
-			u32 ctl4;
-			u32 ctl5;
-			u32 ctl6;
-			u32 ctl7;
-			u32 ctl8;
-			u32 ctl9;
-			u32 ctl10;
-			u32 ctl11;
-			u32 status0;
-			u32 status1;
-			u32 status2;
-			u32 status3;
-			u32 status4;
-			u32 status5;
-			u32 status6;
-			u32 status7;
-			u32 status8;
-			u32 status9;
-		} tx;
-		struct {
-			u32 status0;
-			u32 status1;
-			u32 status2;
-			u32 status3;
-			u32 status4;
-			u32 status5;
-			u32 status6;
-			u32 status7;
-			u32 status8;
-		} rx;
-	} u;
-} __packed;
-
-#define AR5416DESC(_ds)         ((struct ar5416_desc *)(_ds))
-#define AR5416DESC_CONST(_ds)   ((const struct ar5416_desc *)(_ds))
-
-#define ds_ctl2     u.tx.ctl2
-#define ds_ctl3     u.tx.ctl3
-#define ds_ctl4     u.tx.ctl4
-#define ds_ctl5     u.tx.ctl5
-#define ds_ctl6     u.tx.ctl6
-#define ds_ctl7     u.tx.ctl7
-#define ds_ctl8     u.tx.ctl8
-#define ds_ctl9     u.tx.ctl9
-#define ds_ctl10    u.tx.ctl10
-#define ds_ctl11    u.tx.ctl11
-
-#define ds_txstatus0    u.tx.status0
-#define ds_txstatus1    u.tx.status1
-#define ds_txstatus2    u.tx.status2
-#define ds_txstatus3    u.tx.status3
-#define ds_txstatus4    u.tx.status4
-#define ds_txstatus5    u.tx.status5
-#define ds_txstatus6    u.tx.status6
-#define ds_txstatus7    u.tx.status7
-#define ds_txstatus8    u.tx.status8
-#define ds_txstatus9    u.tx.status9
-
-#define ds_rxstatus0    u.rx.status0
-#define ds_rxstatus1    u.rx.status1
-#define ds_rxstatus2    u.rx.status2
-#define ds_rxstatus3    u.rx.status3
-#define ds_rxstatus4    u.rx.status4
-#define ds_rxstatus5    u.rx.status5
-#define ds_rxstatus6    u.rx.status6
-#define ds_rxstatus7    u.rx.status7
-#define ds_rxstatus8    u.rx.status8
-
-#define AR_FrameLen         0x00000fff
-#define AR_VirtMoreFrag     0x00001000
-#define AR_TxCtlRsvd00      0x0000e000
-#define AR_XmitPower        0x003f0000
-#define AR_XmitPower_S      16
-#define AR_RTSEnable        0x00400000
-#define AR_VEOL             0x00800000
-#define AR_ClrDestMask      0x01000000
-#define AR_TxCtlRsvd01      0x1e000000
-#define AR_TxIntrReq        0x20000000
-#define AR_DestIdxValid     0x40000000
-#define AR_CTSEnable        0x80000000
-
-#define AR_BufLen           0x00000fff
-#define AR_TxMore           0x00001000
-#define AR_DestIdx          0x000fe000
-#define AR_DestIdx_S        13
-#define AR_FrameType        0x00f00000
-#define AR_FrameType_S      20
-#define AR_NoAck            0x01000000
-#define AR_InsertTS         0x02000000
-#define AR_CorruptFCS       0x04000000
-#define AR_ExtOnly          0x08000000
-#define AR_ExtAndCtl        0x10000000
-#define AR_MoreAggr         0x20000000
-#define AR_IsAggr           0x40000000
-
-#define AR_BurstDur         0x00007fff
-#define AR_BurstDur_S       0
-#define AR_DurUpdateEna     0x00008000
-#define AR_XmitDataTries0   0x000f0000
-#define AR_XmitDataTries0_S 16
-#define AR_XmitDataTries1   0x00f00000
-#define AR_XmitDataTries1_S 20
-#define AR_XmitDataTries2   0x0f000000
-#define AR_XmitDataTries2_S 24
-#define AR_XmitDataTries3   0xf0000000
-#define AR_XmitDataTries3_S 28
-
-#define AR_XmitRate0        0x000000ff
-#define AR_XmitRate0_S      0
-#define AR_XmitRate1        0x0000ff00
-#define AR_XmitRate1_S      8
-#define AR_XmitRate2        0x00ff0000
-#define AR_XmitRate2_S      16
-#define AR_XmitRate3        0xff000000
-#define AR_XmitRate3_S      24
-
-#define AR_PacketDur0       0x00007fff
-#define AR_PacketDur0_S     0
-#define AR_RTSCTSQual0      0x00008000
-#define AR_PacketDur1       0x7fff0000
-#define AR_PacketDur1_S     16
-#define AR_RTSCTSQual1      0x80000000
-
-#define AR_PacketDur2       0x00007fff
-#define AR_PacketDur2_S     0
-#define AR_RTSCTSQual2      0x00008000
-#define AR_PacketDur3       0x7fff0000
-#define AR_PacketDur3_S     16
-#define AR_RTSCTSQual3      0x80000000
-
-#define AR_AggrLen          0x0000ffff
-#define AR_AggrLen_S        0
-#define AR_TxCtlRsvd60      0x00030000
-#define AR_PadDelim         0x03fc0000
-#define AR_PadDelim_S       18
-#define AR_EncrType         0x0c000000
-#define AR_EncrType_S       26
-#define AR_TxCtlRsvd61      0xf0000000
-
-#define AR_2040_0           0x00000001
-#define AR_GI0              0x00000002
-#define AR_ChainSel0        0x0000001c
-#define AR_ChainSel0_S      2
-#define AR_2040_1           0x00000020
-#define AR_GI1              0x00000040
-#define AR_ChainSel1        0x00000380
-#define AR_ChainSel1_S      7
-#define AR_2040_2           0x00000400
-#define AR_GI2              0x00000800
-#define AR_ChainSel2        0x00007000
-#define AR_ChainSel2_S      12
-#define AR_2040_3           0x00008000
-#define AR_GI3              0x00010000
-#define AR_ChainSel3        0x000e0000
-#define AR_ChainSel3_S      17
-#define AR_RTSCTSRate       0x0ff00000
-#define AR_RTSCTSRate_S     20
-#define AR_TxCtlRsvd70      0xf0000000
-
-#define AR_TxRSSIAnt00      0x000000ff
-#define AR_TxRSSIAnt00_S    0
-#define AR_TxRSSIAnt01      0x0000ff00
-#define AR_TxRSSIAnt01_S    8
-#define AR_TxRSSIAnt02      0x00ff0000
-#define AR_TxRSSIAnt02_S    16
-#define AR_TxStatusRsvd00   0x3f000000
-#define AR_TxBaStatus       0x40000000
-#define AR_TxStatusRsvd01   0x80000000
-
-#define AR_FrmXmitOK            0x00000001
-#define AR_ExcessiveRetries     0x00000002
-#define AR_FIFOUnderrun         0x00000004
-#define AR_Filtered             0x00000008
-#define AR_RTSFailCnt           0x000000f0
-#define AR_RTSFailCnt_S         4
-#define AR_DataFailCnt          0x00000f00
-#define AR_DataFailCnt_S        8
-#define AR_VirtRetryCnt         0x0000f000
-#define AR_VirtRetryCnt_S       12
-#define AR_TxDelimUnderrun      0x00010000
-#define AR_TxDataUnderrun       0x00020000
-#define AR_DescCfgErr           0x00040000
-#define AR_TxTimerExpired       0x00080000
-#define AR_TxStatusRsvd10       0xfff00000
-
-#define AR_SendTimestamp    ds_txstatus2
-#define AR_BaBitmapLow      ds_txstatus3
-#define AR_BaBitmapHigh     ds_txstatus4
-
-#define AR_TxRSSIAnt10      0x000000ff
-#define AR_TxRSSIAnt10_S    0
-#define AR_TxRSSIAnt11      0x0000ff00
-#define AR_TxRSSIAnt11_S    8
-#define AR_TxRSSIAnt12      0x00ff0000
-#define AR_TxRSSIAnt12_S    16
-#define AR_TxRSSICombined   0xff000000
-#define AR_TxRSSICombined_S 24
-
-#define AR_TxEVM0           ds_txstatus5
-#define AR_TxEVM1           ds_txstatus6
-#define AR_TxEVM2           ds_txstatus7
-
-#define AR_TxDone           0x00000001
-#define AR_SeqNum           0x00001ffe
-#define AR_SeqNum_S         1
-#define AR_TxStatusRsvd80   0x0001e000
-#define AR_TxOpExceeded     0x00020000
-#define AR_TxStatusRsvd81   0x001c0000
-#define AR_FinalTxIdx       0x00600000
-#define AR_FinalTxIdx_S     21
-#define AR_TxStatusRsvd82   0x01800000
-#define AR_PowerMgmt        0x02000000
-#define AR_TxStatusRsvd83   0xfc000000
-
-#define AR_RxCTLRsvd00  0xffffffff
-
-#define AR_BufLen       0x00000fff
-#define AR_RxCtlRsvd00  0x00001000
-#define AR_RxIntrReq    0x00002000
-#define AR_RxCtlRsvd01  0xffffc000
-
-#define AR_RxRSSIAnt00      0x000000ff
-#define AR_RxRSSIAnt00_S    0
-#define AR_RxRSSIAnt01      0x0000ff00
-#define AR_RxRSSIAnt01_S    8
-#define AR_RxRSSIAnt02      0x00ff0000
-#define AR_RxRSSIAnt02_S    16
-#define AR_RxRate           0xff000000
-#define AR_RxRate_S         24
-#define AR_RxStatusRsvd00   0xff000000
-
-#define AR_DataLen          0x00000fff
-#define AR_RxMore           0x00001000
-#define AR_NumDelim         0x003fc000
-#define AR_NumDelim_S       14
-#define AR_RxStatusRsvd10   0xff800000
-
-#define AR_RcvTimestamp     ds_rxstatus2
-
-#define AR_GI               0x00000001
-#define AR_2040             0x00000002
-#define AR_Parallel40       0x00000004
-#define AR_Parallel40_S     2
-#define AR_RxStatusRsvd30   0x000000f8
-#define AR_RxAntenna	    0xffffff00
-#define AR_RxAntenna_S	    8
-
-#define AR_RxRSSIAnt10            0x000000ff
-#define AR_RxRSSIAnt10_S          0
-#define AR_RxRSSIAnt11            0x0000ff00
-#define AR_RxRSSIAnt11_S          8
-#define AR_RxRSSIAnt12            0x00ff0000
-#define AR_RxRSSIAnt12_S          16
-#define AR_RxRSSICombined         0xff000000
-#define AR_RxRSSICombined_S       24
-
-#define AR_RxEVM0           ds_rxstatus4
-#define AR_RxEVM1           ds_rxstatus5
-#define AR_RxEVM2           ds_rxstatus6
-
-#define AR_RxDone           0x00000001
-#define AR_RxFrameOK        0x00000002
-#define AR_CRCErr           0x00000004
-#define AR_DecryptCRCErr    0x00000008
-#define AR_PHYErr           0x00000010
-#define AR_MichaelErr       0x00000020
-#define AR_PreDelimCRCErr   0x00000040
-#define AR_RxStatusRsvd70   0x00000080
-#define AR_RxKeyIdxValid    0x00000100
-#define AR_KeyIdx           0x0000fe00
-#define AR_KeyIdx_S         9
-#define AR_PHYErrCode       0x0000ff00
-#define AR_PHYErrCode_S     8
-#define AR_RxMoreAggr       0x00010000
-#define AR_RxAggr           0x00020000
-#define AR_PostDelimCRCErr  0x00040000
-#define AR_RxStatusRsvd71   0x3ff80000
-#define AR_DecryptBusyErr   0x40000000
-#define AR_KeyMiss          0x80000000
-
-enum ath9k_tx_queue {
-	ATH9K_TX_QUEUE_INACTIVE = 0,
-	ATH9K_TX_QUEUE_DATA,
-	ATH9K_TX_QUEUE_BEACON,
-	ATH9K_TX_QUEUE_CAB,
-	ATH9K_TX_QUEUE_UAPSD,
-	ATH9K_TX_QUEUE_PSPOLL
-};
-
-#define	ATH9K_NUM_TX_QUEUES 10
-
-enum ath9k_tx_queue_subtype {
-	ATH9K_WME_AC_BK = 0,
-	ATH9K_WME_AC_BE,
-	ATH9K_WME_AC_VI,
-	ATH9K_WME_AC_VO,
-	ATH9K_WME_UPSD
-};
-
-enum ath9k_tx_queue_flags {
-	TXQ_FLAG_TXOKINT_ENABLE = 0x0001,
-	TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
-	TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
-	TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
-	TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
-	TXQ_FLAG_BACKOFF_DISABLE = 0x0010,
-	TXQ_FLAG_COMPRESSION_ENABLE = 0x0020,
-	TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040,
-	TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080,
-};
-
-#define ATH9K_TXQ_USEDEFAULT ((u32) -1)
-#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
-
-#define ATH9K_DECOMP_MASK_SIZE     128
-#define ATH9K_READY_TIME_LO_BOUND  50
-#define ATH9K_READY_TIME_HI_BOUND  96
-
-enum ath9k_pkt_type {
-	ATH9K_PKT_TYPE_NORMAL = 0,
-	ATH9K_PKT_TYPE_ATIM,
-	ATH9K_PKT_TYPE_PSPOLL,
-	ATH9K_PKT_TYPE_BEACON,
-	ATH9K_PKT_TYPE_PROBE_RESP,
-	ATH9K_PKT_TYPE_CHIRP,
-	ATH9K_PKT_TYPE_GRP_POLL,
-};
-
-struct ath9k_tx_queue_info {
-	u32 tqi_ver;
-	enum ath9k_tx_queue tqi_type;
-	enum ath9k_tx_queue_subtype tqi_subtype;
-	enum ath9k_tx_queue_flags tqi_qflags;
-	u32 tqi_priority;
-	u32 tqi_aifs;
-	u32 tqi_cwmin;
-	u32 tqi_cwmax;
-	u16 tqi_shretry;
-	u16 tqi_lgretry;
-	u32 tqi_cbrPeriod;
-	u32 tqi_cbrOverflowLimit;
-	u32 tqi_burstTime;
-	u32 tqi_readyTime;
-	u32 tqi_physCompBuf;
-	u32 tqi_intFlags;
-};
-
-enum ath9k_rx_filter {
-	ATH9K_RX_FILTER_UCAST = 0x00000001,
-	ATH9K_RX_FILTER_MCAST = 0x00000002,
-	ATH9K_RX_FILTER_BCAST = 0x00000004,
-	ATH9K_RX_FILTER_CONTROL = 0x00000008,
-	ATH9K_RX_FILTER_BEACON = 0x00000010,
-	ATH9K_RX_FILTER_PROM = 0x00000020,
-	ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
-	ATH9K_RX_FILTER_PHYERR = 0x00000100,
-	ATH9K_RX_FILTER_MYBEACON = 0x00000200,
-	ATH9K_RX_FILTER_PSPOLL = 0x00004000,
-	ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
-	ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
-};
-
-#define ATH9K_RATESERIES_RTS_CTS  0x0001
-#define ATH9K_RATESERIES_2040     0x0002
-#define ATH9K_RATESERIES_HALFGI   0x0004
-
-struct ath9k_11n_rate_series {
-	u32 Tries;
-	u32 Rate;
-	u32 PktDuration;
-	u32 ChSel;
-	u32 RateFlags;
-};
-
-struct ath9k_keyval {
-	u8 kv_type;
-	u8 kv_pad;
-	u16 kv_len;
-	u8 kv_val[16]; /* TK */
-	u8 kv_mic[8]; /* Michael MIC key */
-	u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
-			 * supports both MIC keys in the same key cache entry;
-			 * in that case, kv_mic is the RX key) */
-};
-
-enum ath9k_key_type {
-	ATH9K_KEY_TYPE_CLEAR,
-	ATH9K_KEY_TYPE_WEP,
-	ATH9K_KEY_TYPE_AES,
-	ATH9K_KEY_TYPE_TKIP,
-};
-
-enum ath9k_cipher {
-	ATH9K_CIPHER_WEP = 0,
-	ATH9K_CIPHER_AES_OCB = 1,
-	ATH9K_CIPHER_AES_CCM = 2,
-	ATH9K_CIPHER_CKIP = 3,
-	ATH9K_CIPHER_TKIP = 4,
-	ATH9K_CIPHER_CLR = 5,
-	ATH9K_CIPHER_MIC = 127
-};
-
-enum ath9k_ht_macmode {
-	ATH9K_HT_MACMODE_20 = 0,
-	ATH9K_HT_MACMODE_2040 = 1,
-};
-
-enum ath9k_ht_extprotspacing {
-	ATH9K_HT_EXTPROTSPACING_20 = 0,
-	ATH9K_HT_EXTPROTSPACING_25 = 1,
-};
-
-struct ath_hw;
-struct ath9k_channel;
-struct ath_rate_table;
-
-u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
-bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
-bool ath9k_hw_txstart(struct ath_hw *ah, u32 q);
-u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
-bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
-bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
-			 u32 segLen, bool firstSeg,
-			 bool lastSeg, const struct ath_desc *ds0);
-void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
-int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds);
-void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
-			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
-			    u32 keyIx, enum ath9k_key_type keyType, u32 flags);
-void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
-				  struct ath_desc *lastds,
-				  u32 durUpdateEn, u32 rtsctsRate,
-				  u32 rtsctsDuration,
-				  struct ath9k_11n_rate_series series[],
-				  u32 nseries, u32 flags);
-void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
-				u32 aggrLen);
-void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
-				 u32 numDelims);
-void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds);
-void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds);
-void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
-				   u32 burstDuration);
-void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
-				     u32 vmf);
-void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
-bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
-			    const struct ath9k_tx_queue_info *qinfo);
-bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
-			    struct ath9k_tx_queue_info *qinfo);
-int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
-			  const struct ath9k_tx_queue_info *qinfo);
-bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
-bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
-int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
-			u32 pa, struct ath_desc *nds, u64 tsf);
-bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
-			  u32 size, u32 flags);
-bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
-void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
-void ath9k_hw_rxena(struct ath_hw *ah);
-void ath9k_hw_startpcureceive(struct ath_hw *ah);
-void ath9k_hw_stoppcurecv(struct ath_hw *ah);
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
-
-#endif /* MAC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2913 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/nl80211.h>
-#include "ath9k.h"
-
-#define ATH_PCI_VERSION "0.1"
-
-static char *dev_info = "ath9k";
-
-MODULE_AUTHOR("Atheros Communications");
-MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
-MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
-static int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
-
-/* We use the hw_value as an index into our private channel structure */
-
-#define CHAN2G(_freq, _idx)  { \
-	.center_freq = (_freq), \
-	.hw_value = (_idx), \
-	.max_power = 30, \
-}
-
-#define CHAN5G(_freq, _idx) { \
-	.band = IEEE80211_BAND_5GHZ, \
-	.center_freq = (_freq), \
-	.hw_value = (_idx), \
-	.max_power = 30, \
-}
-
-/* Some 2 GHz radios are actually tunable on 2312-2732
- * on 5 MHz steps, we support the channels which we know
- * we have calibration data for all cards though to make
- * this static */
-static struct ieee80211_channel ath9k_2ghz_chantable[] = {
-	CHAN2G(2412, 0), /* Channel 1 */
-	CHAN2G(2417, 1), /* Channel 2 */
-	CHAN2G(2422, 2), /* Channel 3 */
-	CHAN2G(2427, 3), /* Channel 4 */
-	CHAN2G(2432, 4), /* Channel 5 */
-	CHAN2G(2437, 5), /* Channel 6 */
-	CHAN2G(2442, 6), /* Channel 7 */
-	CHAN2G(2447, 7), /* Channel 8 */
-	CHAN2G(2452, 8), /* Channel 9 */
-	CHAN2G(2457, 9), /* Channel 10 */
-	CHAN2G(2462, 10), /* Channel 11 */
-	CHAN2G(2467, 11), /* Channel 12 */
-	CHAN2G(2472, 12), /* Channel 13 */
-	CHAN2G(2484, 13), /* Channel 14 */
-};
-
-/* Some 5 GHz radios are actually tunable on XXXX-YYYY
- * on 5 MHz steps, we support the channels which we know
- * we have calibration data for all cards though to make
- * this static */
-static struct ieee80211_channel ath9k_5ghz_chantable[] = {
-	/* _We_ call this UNII 1 */
-	CHAN5G(5180, 14), /* Channel 36 */
-	CHAN5G(5200, 15), /* Channel 40 */
-	CHAN5G(5220, 16), /* Channel 44 */
-	CHAN5G(5240, 17), /* Channel 48 */
-	/* _We_ call this UNII 2 */
-	CHAN5G(5260, 18), /* Channel 52 */
-	CHAN5G(5280, 19), /* Channel 56 */
-	CHAN5G(5300, 20), /* Channel 60 */
-	CHAN5G(5320, 21), /* Channel 64 */
-	/* _We_ call this "Middle band" */
-	CHAN5G(5500, 22), /* Channel 100 */
-	CHAN5G(5520, 23), /* Channel 104 */
-	CHAN5G(5540, 24), /* Channel 108 */
-	CHAN5G(5560, 25), /* Channel 112 */
-	CHAN5G(5580, 26), /* Channel 116 */
-	CHAN5G(5600, 27), /* Channel 120 */
-	CHAN5G(5620, 28), /* Channel 124 */
-	CHAN5G(5640, 29), /* Channel 128 */
-	CHAN5G(5660, 30), /* Channel 132 */
-	CHAN5G(5680, 31), /* Channel 136 */
-	CHAN5G(5700, 32), /* Channel 140 */
-	/* _We_ call this UNII 3 */
-	CHAN5G(5745, 33), /* Channel 149 */
-	CHAN5G(5765, 34), /* Channel 153 */
-	CHAN5G(5785, 35), /* Channel 157 */
-	CHAN5G(5805, 36), /* Channel 161 */
-	CHAN5G(5825, 37), /* Channel 165 */
-};
-
-static void ath_cache_conf_rate(struct ath_softc *sc,
-				struct ieee80211_conf *conf)
-{
-	switch (conf->channel->band) {
-	case IEEE80211_BAND_2GHZ:
-		if (conf_is_ht20(conf))
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
-		else if (conf_is_ht40_minus(conf))
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
-		else if (conf_is_ht40_plus(conf))
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
-		else
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11G];
-		break;
-	case IEEE80211_BAND_5GHZ:
-		if (conf_is_ht20(conf))
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
-		else if (conf_is_ht40_minus(conf))
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
-		else if (conf_is_ht40_plus(conf))
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
-		else
-			sc->cur_rate_table =
-			  sc->hw_rate_table[ATH9K_MODE_11A];
-		break;
-	default:
-		BUG_ON(1);
-		break;
-	}
-}
-
-static void ath_update_txpow(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	u32 txpow;
-
-	if (sc->curtxpow != sc->config.txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
-		/* read back in case value is clamped */
-		ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
-		sc->curtxpow = txpow;
-	}
-}
-
-static u8 parse_mpdudensity(u8 mpdudensity)
-{
-	/*
-	 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
-	 *   0 for no restriction
-	 *   1 for 1/4 us
-	 *   2 for 1/2 us
-	 *   3 for 1 us
-	 *   4 for 2 us
-	 *   5 for 4 us
-	 *   6 for 8 us
-	 *   7 for 16 us
-	 */
-	switch (mpdudensity) {
-	case 0:
-		return 0;
-	case 1:
-	case 2:
-	case 3:
-		/* Our lower layer calculations limit our precision to
-		   1 microsecond */
-		return 1;
-	case 4:
-		return 2;
-	case 5:
-		return 4;
-	case 6:
-		return 8;
-	case 7:
-		return 16;
-	default:
-		return 0;
-	}
-}
-
-static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
-{
-	struct ath_rate_table *rate_table = NULL;
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_rate *rate;
-	int i, maxrates;
-
-	switch (band) {
-	case IEEE80211_BAND_2GHZ:
-		rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
-		break;
-	case IEEE80211_BAND_5GHZ:
-		rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
-		break;
-	default:
-		break;
-	}
-
-	if (rate_table == NULL)
-		return;
-
-	sband = &sc->sbands[band];
-	rate = sc->rates[band];
-
-	if (rate_table->rate_cnt > ATH_RATE_MAX)
-		maxrates = ATH_RATE_MAX;
-	else
-		maxrates = rate_table->rate_cnt;
-
-	for (i = 0; i < maxrates; i++) {
-		rate[i].bitrate = rate_table->info[i].ratekbps / 100;
-		rate[i].hw_value = rate_table->info[i].ratecode;
-		if (rate_table->info[i].short_preamble) {
-			rate[i].hw_value_short = rate_table->info[i].ratecode |
-				rate_table->info[i].short_preamble;
-			rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE;
-		}
-		sband->n_bitrates++;
-
-		DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n",
-			rate[i].bitrate / 10, rate[i].hw_value);
-	}
-}
-
-/*
- * Set/change channels.  If the channel is really being changed, it's done
- * by reseting the chip.  To accomplish this we must first cleanup any pending
- * DMA, then restart stuff.
-*/
-int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
-		    struct ath9k_channel *hchan)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	bool fastcc = true, stopped;
-	struct ieee80211_channel *channel = hw->conf.channel;
-	int r;
-
-	if (sc->sc_flags & SC_OP_INVALID)
-		return -EIO;
-
-	ath9k_ps_wakeup(sc);
-
-	/*
-	 * This is only performed if the channel settings have
-	 * actually changed.
-	 *
-	 * To switch channels clear any pending DMA operations;
-	 * wait long enough for the RX fifo to drain, reset the
-	 * hardware at the new frequency, and then re-enable
-	 * the relevant bits of the h/w.
-	 */
-	ath9k_hw_set_interrupts(ah, 0);
-	ath_drain_all_txq(sc, false);
-	stopped = ath_stoprecv(sc);
-
-	/* XXX: do not flush receive queue here. We don't want
-	 * to flush data frames already in queue because of
-	 * changing channel. */
-
-	if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
-		fastcc = false;
-
-	DPRINTF(sc, ATH_DBG_CONFIG,
-		"(%u MHz) -> (%u MHz), chanwidth: %d\n",
-		sc->sc_ah->curchan->channel,
-		channel->center_freq, sc->tx_chan_width);
-
-	spin_lock_bh(&sc->sc_resetlock);
-
-	r = ath9k_hw_reset(ah, hchan, fastcc);
-	if (r) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to reset channel (%u Mhz) "
-			"reset status %u\n",
-			channel->center_freq, r);
-		spin_unlock_bh(&sc->sc_resetlock);
-		return r;
-	}
-	spin_unlock_bh(&sc->sc_resetlock);
-
-	sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
-	sc->sc_flags &= ~SC_OP_FULL_RESET;
-
-	if (ath_startrecv(sc) != 0) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to restart recv logic\n");
-		return -EIO;
-	}
-
-	ath_cache_conf_rate(sc, &hw->conf);
-	ath_update_txpow(sc);
-	ath9k_hw_set_interrupts(ah, sc->imask);
-	ath9k_ps_restore(sc);
-	return 0;
-}
-
-/*
- *  This routine performs the periodic noise floor calibration function
- *  that is used to adjust and optimize the chip performance.  This
- *  takes environmental changes (location, temperature) into account.
- *  When the task is complete, it reschedules itself depending on the
- *  appropriate interval that was calculated.
- */
-static void ath_ani_calibrate(unsigned long data)
-{
-	struct ath_softc *sc = (struct ath_softc *)data;
-	struct ath_hw *ah = sc->sc_ah;
-	bool longcal = false;
-	bool shortcal = false;
-	bool aniflag = false;
-	unsigned int timestamp = jiffies_to_msecs(jiffies);
-	u32 cal_interval, short_cal_interval;
-
-	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
-		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
-
-	/*
-	* don't calibrate when we're scanning.
-	* we are most likely not on our home channel.
-	*/
-	if (sc->sc_flags & SC_OP_SCANNING)
-		goto set_timer;
-
-	/* Long calibration runs independently of short calibration. */
-	if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
-		longcal = true;
-		DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
-		sc->ani.longcal_timer = timestamp;
-	}
-
-	/* Short calibration applies only while caldone is false */
-	if (!sc->ani.caldone) {
-		if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) {
-			shortcal = true;
-			DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies);
-			sc->ani.shortcal_timer = timestamp;
-			sc->ani.resetcal_timer = timestamp;
-		}
-	} else {
-		if ((timestamp - sc->ani.resetcal_timer) >=
-		    ATH_RESTART_CALINTERVAL) {
-			sc->ani.caldone = ath9k_hw_reset_calvalid(ah);
-			if (sc->ani.caldone)
-				sc->ani.resetcal_timer = timestamp;
-		}
-	}
-
-	/* Verify whether we must check ANI */
-	if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
-		aniflag = true;
-		sc->ani.checkani_timer = timestamp;
-	}
-
-	/* Skip all processing if there's nothing to do. */
-	if (longcal || shortcal || aniflag) {
-		/* Call ANI routine if necessary */
-		if (aniflag)
-			ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan);
-
-		/* Perform calibration if necessary */
-		if (longcal || shortcal) {
-			bool iscaldone = false;
-
-			if (ath9k_hw_calibrate(ah, ah->curchan,
-					       sc->rx_chainmask, longcal,
-					       &iscaldone)) {
-				if (longcal)
-					sc->ani.noise_floor =
-						ath9k_hw_getchan_noise(ah,
-							       ah->curchan);
-
-				DPRINTF(sc, ATH_DBG_ANI,
-					"calibrate chan %u/%x nf: %d\n",
-					ah->curchan->channel,
-					ah->curchan->channelFlags,
-					sc->ani.noise_floor);
-			} else {
-				DPRINTF(sc, ATH_DBG_ANY,
-					"calibrate chan %u/%x failed\n",
-					ah->curchan->channel,
-					ah->curchan->channelFlags);
-			}
-			sc->ani.caldone = iscaldone;
-		}
-	}
-
-set_timer:
-	/*
-	* Set timer interval based on previous results.
-	* The interval must be the shortest necessary to satisfy ANI,
-	* short calibration and long calibration.
-	*/
-	cal_interval = ATH_LONG_CALINTERVAL;
-	if (sc->sc_ah->config.enable_ani)
-		cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
-	if (!sc->ani.caldone)
-		cal_interval = min(cal_interval, (u32)short_cal_interval);
-
-	mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
-}
-
-/*
- * Update tx/rx chainmask. For legacy association,
- * hard code chainmask to 1x1, for 11n association, use
- * the chainmask configuration, for bt coexistence, use
- * the chainmask configuration even in legacy mode.
- */
-void ath_update_chainmask(struct ath_softc *sc, int is_ht)
-{
-	sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
-	if (is_ht ||
-	    (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
-		sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
-		sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
-	} else {
-		sc->tx_chainmask = 1;
-		sc->rx_chainmask = 1;
-	}
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n",
-		sc->tx_chainmask, sc->rx_chainmask);
-}
-
-static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
-{
-	struct ath_node *an;
-
-	an = (struct ath_node *)sta->drv_priv;
-
-	if (sc->sc_flags & SC_OP_TXAGGR)
-		ath_tx_node_init(sc, an);
-
-	an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
-			     sta->ht_cap.ampdu_factor);
-	an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
-}
-
-static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
-{
-	struct ath_node *an = (struct ath_node *)sta->drv_priv;
-
-	if (sc->sc_flags & SC_OP_TXAGGR)
-		ath_tx_node_cleanup(sc, an);
-}
-
-static void ath9k_tasklet(unsigned long data)
-{
-	struct ath_softc *sc = (struct ath_softc *)data;
-	u32 status = sc->intrstatus;
-
-	if (status & ATH9K_INT_FATAL) {
-		/* need a chip reset */
-		ath_reset(sc, false);
-		return;
-	} else {
-
-		if (status &
-		    (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
-			spin_lock_bh(&sc->rx.rxflushlock);
-			ath_rx_tasklet(sc, 0);
-			spin_unlock_bh(&sc->rx.rxflushlock);
-		}
-		/* XXX: optimize this */
-		if (status & ATH9K_INT_TX)
-			ath_tx_tasklet(sc);
-	}
-
-	/* re-enable hardware interrupt */
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
-}
-
-irqreturn_t ath_isr(int irq, void *dev)
-{
-	struct ath_softc *sc = dev;
-	struct ath_hw *ah = sc->sc_ah;
-	enum ath9k_int status;
-	bool sched = false;
-
-	do {
-		if (sc->sc_flags & SC_OP_INVALID) {
-			/*
-			 * The hardware is not ready/present, don't
-			 * touch anything. Note this can happen early
-			 * on if the IRQ is shared.
-			 */
-			return IRQ_NONE;
-		}
-		if (!ath9k_hw_intrpend(ah)) {	/* shared irq, not for us */
-			return IRQ_NONE;
-		}
-
-		/*
-		 * Figure out the reason(s) for the interrupt.  Note
-		 * that the hal returns a pseudo-ISR that may include
-		 * bits we haven't explicitly enabled so we mask the
-		 * value to insure we only process bits we requested.
-		 */
-		ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
-
-		status &= sc->imask;	/* discard unasked-for bits */
-
-		/*
-		 * If there are no status bits set, then this interrupt was not
-		 * for me (should have been caught above).
-		 */
-		if (!status)
-			return IRQ_NONE;
-
-		sc->intrstatus = status;
-		ath9k_ps_wakeup(sc);
-
-		if (status & ATH9K_INT_FATAL) {
-			/* need a chip reset */
-			sched = true;
-		} else if (status & ATH9K_INT_RXORN) {
-			/* need a chip reset */
-			sched = true;
-		} else {
-			if (status & ATH9K_INT_SWBA) {
-				/* schedule a tasklet for beacon handling */
-				tasklet_schedule(&sc->bcon_tasklet);
-			}
-			if (status & ATH9K_INT_RXEOL) {
-				/*
-				 * NB: the hardware should re-read the link when
-				 *     RXE bit is written, but it doesn't work
-				 *     at least on older hardware revs.
-				 */
-				sched = true;
-			}
-
-			if (status & ATH9K_INT_TXURN)
-				/* bump tx trigger level */
-				ath9k_hw_updatetxtriglevel(ah, true);
-			/* XXX: optimize this */
-			if (status & ATH9K_INT_RX)
-				sched = true;
-			if (status & ATH9K_INT_TX)
-				sched = true;
-			if (status & ATH9K_INT_BMISS)
-				sched = true;
-			/* carrier sense timeout */
-			if (status & ATH9K_INT_CST)
-				sched = true;
-			if (status & ATH9K_INT_MIB) {
-				/*
-				 * Disable interrupts until we service the MIB
-				 * interrupt; otherwise it will continue to
-				 * fire.
-				 */
-				ath9k_hw_set_interrupts(ah, 0);
-				/*
-				 * Let the hal handle the event. We assume
-				 * it will clear whatever condition caused
-				 * the interrupt.
-				 */
-				ath9k_hw_procmibevent(ah, &sc->nodestats);
-				ath9k_hw_set_interrupts(ah, sc->imask);
-			}
-			if (status & ATH9K_INT_TIM_TIMER) {
-				if (!(ah->caps.hw_caps &
-				      ATH9K_HW_CAP_AUTOSLEEP)) {
-					/* Clear RxAbort bit so that we can
-					 * receive frames */
-					ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
-					ath9k_hw_setrxabort(ah, 0);
-					sched = true;
-					sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
-				}
-			}
-			if (status & ATH9K_INT_TSFOOR) {
-				/* FIXME: Handle this interrupt for power save */
-				sched = true;
-			}
-		}
-		ath9k_ps_restore(sc);
-	} while (0);
-
-	ath_debug_stat_interrupt(sc, status);
-
-	if (sched) {
-		/* turn off every interrupt except SWBA */
-		ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA));
-		tasklet_schedule(&sc->intr_tq);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static u32 ath_get_extchanmode(struct ath_softc *sc,
-			       struct ieee80211_channel *chan,
-			       enum nl80211_channel_type channel_type)
-{
-	u32 chanmode = 0;
-
-	switch (chan->band) {
-	case IEEE80211_BAND_2GHZ:
-		switch(channel_type) {
-		case NL80211_CHAN_NO_HT:
-		case NL80211_CHAN_HT20:
-			chanmode = CHANNEL_G_HT20;
-			break;
-		case NL80211_CHAN_HT40PLUS:
-			chanmode = CHANNEL_G_HT40PLUS;
-			break;
-		case NL80211_CHAN_HT40MINUS:
-			chanmode = CHANNEL_G_HT40MINUS;
-			break;
-		}
-		break;
-	case IEEE80211_BAND_5GHZ:
-		switch(channel_type) {
-		case NL80211_CHAN_NO_HT:
-		case NL80211_CHAN_HT20:
-			chanmode = CHANNEL_A_HT20;
-			break;
-		case NL80211_CHAN_HT40PLUS:
-			chanmode = CHANNEL_A_HT40PLUS;
-			break;
-		case NL80211_CHAN_HT40MINUS:
-			chanmode = CHANNEL_A_HT40MINUS;
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-
-	return chanmode;
-}
-
-static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
-			   struct ath9k_keyval *hk, const u8 *addr,
-			   bool authenticator)
-{
-	const u8 *key_rxmic;
-	const u8 *key_txmic;
-
-	key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
-	key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
-
-	if (addr == NULL) {
-		/*
-		 * Group key installation - only two key cache entries are used
-		 * regardless of splitmic capability since group key is only
-		 * used either for TX or RX.
-		 */
-		if (authenticator) {
-			memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
-			memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
-		} else {
-			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
-			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
-		}
-		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
-	}
-	if (!sc->splitmic) {
-		/* TX and RX keys share the same key cache entry. */
-		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
-		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
-		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
-	}
-
-	/* Separate key cache entries for TX and RX */
-
-	/* TX key goes at first index, RX key at +32. */
-	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
-	if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) {
-		/* TX MIC entry failed. No need to proceed further */
-		DPRINTF(sc, ATH_DBG_KEYCACHE,
-			"Setting TX MIC Key Failed\n");
-		return 0;
-	}
-
-	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
-	/* XXX delete tx key on failure? */
-	return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr);
-}
-
-static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
-{
-	int i;
-
-	for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
-		if (test_bit(i, sc->keymap) ||
-		    test_bit(i + 64, sc->keymap))
-			continue; /* At least one part of TKIP key allocated */
-		if (sc->splitmic &&
-		    (test_bit(i + 32, sc->keymap) ||
-		     test_bit(i + 64 + 32, sc->keymap)))
-			continue; /* At least one part of TKIP key allocated */
-
-		/* Found a free slot for a TKIP key */
-		return i;
-	}
-	return -1;
-}
-
-static int ath_reserve_key_cache_slot(struct ath_softc *sc)
-{
-	int i;
-
-	/* First, try to find slots that would not be available for TKIP. */
-	if (sc->splitmic) {
-		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) {
-			if (!test_bit(i, sc->keymap) &&
-			    (test_bit(i + 32, sc->keymap) ||
-			     test_bit(i + 64, sc->keymap) ||
-			     test_bit(i + 64 + 32, sc->keymap)))
-				return i;
-			if (!test_bit(i + 32, sc->keymap) &&
-			    (test_bit(i, sc->keymap) ||
-			     test_bit(i + 64, sc->keymap) ||
-			     test_bit(i + 64 + 32, sc->keymap)))
-				return i + 32;
-			if (!test_bit(i + 64, sc->keymap) &&
-			    (test_bit(i , sc->keymap) ||
-			     test_bit(i + 32, sc->keymap) ||
-			     test_bit(i + 64 + 32, sc->keymap)))
-				return i + 64;
-			if (!test_bit(i + 64 + 32, sc->keymap) &&
-			    (test_bit(i, sc->keymap) ||
-			     test_bit(i + 32, sc->keymap) ||
-			     test_bit(i + 64, sc->keymap)))
-				return i + 64 + 32;
-		}
-	} else {
-		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
-			if (!test_bit(i, sc->keymap) &&
-			    test_bit(i + 64, sc->keymap))
-				return i;
-			if (test_bit(i, sc->keymap) &&
-			    !test_bit(i + 64, sc->keymap))
-				return i + 64;
-		}
-	}
-
-	/* No partially used TKIP slots, pick any available slot */
-	for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) {
-		/* Do not allow slots that could be needed for TKIP group keys
-		 * to be used. This limitation could be removed if we know that
-		 * TKIP will not be used. */
-		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
-			continue;
-		if (sc->splitmic) {
-			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
-				continue;
-			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
-				continue;
-		}
-
-		if (!test_bit(i, sc->keymap))
-			return i; /* Found a free slot for a key */
-	}
-
-	/* No free slot found */
-	return -1;
-}
-
-static int ath_key_config(struct ath_softc *sc,
-			  struct ieee80211_vif *vif,
-			  struct ieee80211_sta *sta,
-			  struct ieee80211_key_conf *key)
-{
-	struct ath9k_keyval hk;
-	const u8 *mac = NULL;
-	int ret = 0;
-	int idx;
-
-	memset(&hk, 0, sizeof(hk));
-
-	switch (key->alg) {
-	case ALG_WEP:
-		hk.kv_type = ATH9K_CIPHER_WEP;
-		break;
-	case ALG_TKIP:
-		hk.kv_type = ATH9K_CIPHER_TKIP;
-		break;
-	case ALG_CCMP:
-		hk.kv_type = ATH9K_CIPHER_AES_CCM;
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	hk.kv_len = key->keylen;
-	memcpy(hk.kv_val, key->key, key->keylen);
-
-	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
-		/* For now, use the default keys for broadcast keys. This may
-		 * need to change with virtual interfaces. */
-		idx = key->keyidx;
-	} else if (key->keyidx) {
-		if (WARN_ON(!sta))
-			return -EOPNOTSUPP;
-		mac = sta->addr;
-
-		if (vif->type != NL80211_IFTYPE_AP) {
-			/* Only keyidx 0 should be used with unicast key, but
-			 * allow this for client mode for now. */
-			idx = key->keyidx;
-		} else
-			return -EIO;
-	} else {
-		if (WARN_ON(!sta))
-			return -EOPNOTSUPP;
-		mac = sta->addr;
-
-		if (key->alg == ALG_TKIP)
-			idx = ath_reserve_key_cache_slot_tkip(sc);
-		else
-			idx = ath_reserve_key_cache_slot(sc);
-		if (idx < 0)
-			return -ENOSPC; /* no free key cache entries */
-	}
-
-	if (key->alg == ALG_TKIP)
-		ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac,
-				      vif->type == NL80211_IFTYPE_AP);
-	else
-		ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac);
-
-	if (!ret)
-		return -EIO;
-
-	set_bit(idx, sc->keymap);
-	if (key->alg == ALG_TKIP) {
-		set_bit(idx + 64, sc->keymap);
-		if (sc->splitmic) {
-			set_bit(idx + 32, sc->keymap);
-			set_bit(idx + 64 + 32, sc->keymap);
-		}
-	}
-
-	return idx;
-}
-
-static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
-{
-	ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx);
-	if (key->hw_key_idx < IEEE80211_WEP_NKID)
-		return;
-
-	clear_bit(key->hw_key_idx, sc->keymap);
-	if (key->alg != ALG_TKIP)
-		return;
-
-	clear_bit(key->hw_key_idx + 64, sc->keymap);
-	if (sc->splitmic) {
-		clear_bit(key->hw_key_idx + 32, sc->keymap);
-		clear_bit(key->hw_key_idx + 64 + 32, sc->keymap);
-	}
-}
-
-static void setup_ht_cap(struct ath_softc *sc,
-			 struct ieee80211_sta_ht_cap *ht_info)
-{
-#define	ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3	/* 2 ^ 16 */
-#define	ATH9K_HT_CAP_MPDUDENSITY_8 0x6		/* 8 usec */
-
-	ht_info->ht_supported = true;
-	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
-		       IEEE80211_HT_CAP_SM_PS |
-		       IEEE80211_HT_CAP_SGI_40 |
-		       IEEE80211_HT_CAP_DSSSCCK40;
-
-	ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
-	ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
-
-	/* set up supported mcs set */
-	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
-
-	switch(sc->rx_chainmask) {
-	case 1:
-		ht_info->mcs.rx_mask[0] = 0xff;
-		break;
-	case 3:
-	case 5:
-	case 7:
-	default:
-		ht_info->mcs.rx_mask[0] = 0xff;
-		ht_info->mcs.rx_mask[1] = 0xff;
-		break;
-	}
-
-	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
-}
-
-static void ath9k_bss_assoc_info(struct ath_softc *sc,
-				 struct ieee80211_vif *vif,
-				 struct ieee80211_bss_conf *bss_conf)
-{
-	struct ath_vif *avp = (void *)vif->drv_priv;
-
-	if (bss_conf->assoc) {
-		DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
-			bss_conf->aid, sc->curbssid);
-
-		/* New association, store aid */
-		if (avp->av_opmode == NL80211_IFTYPE_STATION) {
-			sc->curaid = bss_conf->aid;
-			ath9k_hw_write_associd(sc);
-		}
-
-		/* Configure the beacon */
-		ath_beacon_config(sc, vif);
-
-		/* Reset rssi stats */
-		sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
-		sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
-		sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
-		sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
-
-		/* Start ANI */
-		mod_timer(&sc->ani.timer,
-			  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
-	} else {
-		DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISSOC\n");
-		sc->curaid = 0;
-	}
-}
-
-/********************************/
-/*	 LED functions		*/
-/********************************/
-
-static void ath_led_blink_work(struct work_struct *work)
-{
-	struct ath_softc *sc = container_of(work, struct ath_softc,
-					    ath_led_blink_work.work);
-
-	if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
-		return;
-
-	if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
-	    (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
-		ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
-	else
-		ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
-				  (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
-
-	queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work,
-			   (sc->sc_flags & SC_OP_LED_ON) ?
-			   msecs_to_jiffies(sc->led_off_duration) :
-			   msecs_to_jiffies(sc->led_on_duration));
-
-	sc->led_on_duration = sc->led_on_cnt ?
-			max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
-			ATH_LED_ON_DURATION_IDLE;
-	sc->led_off_duration = sc->led_off_cnt ?
-			max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
-			ATH_LED_OFF_DURATION_IDLE;
-	sc->led_on_cnt = sc->led_off_cnt = 0;
-	if (sc->sc_flags & SC_OP_LED_ON)
-		sc->sc_flags &= ~SC_OP_LED_ON;
-	else
-		sc->sc_flags |= SC_OP_LED_ON;
-}
-
-static void ath_led_brightness(struct led_classdev *led_cdev,
-			       enum led_brightness brightness)
-{
-	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
-	struct ath_softc *sc = led->sc;
-
-	switch (brightness) {
-	case LED_OFF:
-		if (led->led_type == ATH_LED_ASSOC ||
-		    led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
-				(led->led_type == ATH_LED_RADIO));
-			sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
-			if (led->led_type == ATH_LED_RADIO)
-				sc->sc_flags &= ~SC_OP_LED_ON;
-		} else {
-			sc->led_off_cnt++;
-		}
-		break;
-	case LED_FULL:
-		if (led->led_type == ATH_LED_ASSOC) {
-			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
-			queue_delayed_work(sc->hw->workqueue,
-					   &sc->ath_led_blink_work, 0);
-		} else if (led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
-			sc->sc_flags |= SC_OP_LED_ON;
-		} else {
-			sc->led_on_cnt++;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
-			    char *trigger)
-{
-	int ret;
-
-	led->sc = sc;
-	led->led_cdev.name = led->name;
-	led->led_cdev.default_trigger = trigger;
-	led->led_cdev.brightness_set = ath_led_brightness;
-
-	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
-	if (ret)
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Failed to register led:%s", led->name);
-	else
-		led->registered = 1;
-	return ret;
-}
-
-static void ath_unregister_led(struct ath_led *led)
-{
-	if (led->registered) {
-		led_classdev_unregister(&led->led_cdev);
-		led->registered = 0;
-	}
-}
-
-static void ath_deinit_leds(struct ath_softc *sc)
-{
-	cancel_delayed_work_sync(&sc->ath_led_blink_work);
-	ath_unregister_led(&sc->assoc_led);
-	sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
-	ath_unregister_led(&sc->tx_led);
-	ath_unregister_led(&sc->rx_led);
-	ath_unregister_led(&sc->radio_led);
-	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-}
-
-static void ath_init_leds(struct ath_softc *sc)
-{
-	char *trigger;
-	int ret;
-
-	/* Configure gpio 1 for output */
-	ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
-			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-	/* LED off, active low */
-	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-
-	INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
-
-	trigger = ieee80211_get_radio_led_name(sc->hw);
-	snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
-		"ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->radio_led, trigger);
-	sc->radio_led.led_type = ATH_LED_RADIO;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_assoc_led_name(sc->hw);
-	snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
-		"ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->assoc_led, trigger);
-	sc->assoc_led.led_type = ATH_LED_ASSOC;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_tx_led_name(sc->hw);
-	snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
-		"ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->tx_led, trigger);
-	sc->tx_led.led_type = ATH_LED_TX;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_rx_led_name(sc->hw);
-	snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
-		"ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->rx_led, trigger);
-	sc->rx_led.led_type = ATH_LED_RX;
-	if (ret)
-		goto fail;
-
-	return;
-
-fail:
-	ath_deinit_leds(sc);
-}
-
-void ath_radio_enable(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ieee80211_channel *channel = sc->hw->conf.channel;
-	int r;
-
-	ath9k_ps_wakeup(sc);
-	spin_lock_bh(&sc->sc_resetlock);
-
-	r = ath9k_hw_reset(ah, ah->curchan, false);
-
-	if (r) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to reset channel %u (%uMhz) ",
-			"reset status %u\n",
-			channel->center_freq, r);
-	}
-	spin_unlock_bh(&sc->sc_resetlock);
-
-	ath_update_txpow(sc);
-	if (ath_startrecv(sc) != 0) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to restart recv logic\n");
-		return;
-	}
-
-	if (sc->sc_flags & SC_OP_BEACONS)
-		ath_beacon_config(sc, NULL);	/* restart beacons */
-
-	/* Re-Enable  interrupts */
-	ath9k_hw_set_interrupts(ah, sc->imask);
-
-	/* Enable LED */
-	ath9k_hw_cfg_output(ah, ATH_LED_PIN,
-			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-	ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
-
-	ieee80211_wake_queues(sc->hw);
-	ath9k_ps_restore(sc);
-}
-
-void ath_radio_disable(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ieee80211_channel *channel = sc->hw->conf.channel;
-	int r;
-
-	ath9k_ps_wakeup(sc);
-	ieee80211_stop_queues(sc->hw);
-
-	/* Disable LED */
-	ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1);
-	ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN);
-
-	/* Disable interrupts */
-	ath9k_hw_set_interrupts(ah, 0);
-
-	ath_drain_all_txq(sc, false);	/* clear pending tx frames */
-	ath_stoprecv(sc);		/* turn off frame recv */
-	ath_flushrecv(sc);		/* flush recv queue */
-
-	spin_lock_bh(&sc->sc_resetlock);
-	r = ath9k_hw_reset(ah, ah->curchan, false);
-	if (r) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to reset channel %u (%uMhz) "
-			"reset status %u\n",
-			channel->center_freq, r);
-	}
-	spin_unlock_bh(&sc->sc_resetlock);
-
-	ath9k_hw_phy_disable(ah);
-	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
-	ath9k_ps_restore(sc);
-}
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-
-/*******************/
-/*	Rfkill	   */
-/*******************/
-
-static bool ath_is_rfkill_set(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-
-	return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
-				  ah->rfkill_polarity;
-}
-
-/* h/w rfkill poll function */
-static void ath_rfkill_poll(struct work_struct *work)
-{
-	struct ath_softc *sc = container_of(work, struct ath_softc,
-					    rf_kill.rfkill_poll.work);
-	bool radio_on;
-
-	if (sc->sc_flags & SC_OP_INVALID)
-		return;
-
-	radio_on = !ath_is_rfkill_set(sc);
-
-	/*
-	 * enable/disable radio only when there is a
-	 * state change in RF switch
-	 */
-	if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) {
-		enum rfkill_state state;
-
-		if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) {
-			state = radio_on ? RFKILL_STATE_SOFT_BLOCKED
-				: RFKILL_STATE_HARD_BLOCKED;
-		} else if (radio_on) {
-			ath_radio_enable(sc);
-			state = RFKILL_STATE_UNBLOCKED;
-		} else {
-			ath_radio_disable(sc);
-			state = RFKILL_STATE_HARD_BLOCKED;
-		}
-
-		if (state == RFKILL_STATE_HARD_BLOCKED)
-			sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED;
-		else
-			sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED;
-
-		rfkill_force_state(sc->rf_kill.rfkill, state);
-	}
-
-	queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll,
-			   msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL));
-}
-
-/* s/w rfkill handler */
-static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
-{
-	struct ath_softc *sc = data;
-
-	switch (state) {
-	case RFKILL_STATE_SOFT_BLOCKED:
-		if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED |
-		    SC_OP_RFKILL_SW_BLOCKED)))
-			ath_radio_disable(sc);
-		sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED;
-		return 0;
-	case RFKILL_STATE_UNBLOCKED:
-		if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) {
-			sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
-			if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
-				DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
-					"radio as it is disabled by h/w\n");
-				return -EPERM;
-			}
-			ath_radio_enable(sc);
-		}
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-/* Init s/w rfkill */
-static int ath_init_sw_rfkill(struct ath_softc *sc)
-{
-	sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy),
-					     RFKILL_TYPE_WLAN);
-	if (!sc->rf_kill.rfkill) {
-		DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n");
-		return -ENOMEM;
-	}
-
-	snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name),
-		"ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy));
-	sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name;
-	sc->rf_kill.rfkill->data = sc;
-	sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
-	sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
-	sc->rf_kill.rfkill->user_claim_unsupported = 1;
-
-	return 0;
-}
-
-/* Deinitialize rfkill */
-static void ath_deinit_rfkill(struct ath_softc *sc)
-{
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
-
-	if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) {
-		rfkill_unregister(sc->rf_kill.rfkill);
-		sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED;
-		sc->rf_kill.rfkill = NULL;
-	}
-}
-
-static int ath_start_rfkill_poll(struct ath_softc *sc)
-{
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		queue_delayed_work(sc->hw->workqueue,
-				   &sc->rf_kill.rfkill_poll, 0);
-
-	if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
-		if (rfkill_register(sc->rf_kill.rfkill)) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Unable to register rfkill\n");
-			rfkill_free(sc->rf_kill.rfkill);
-
-			/* Deinitialize the device */
-			ath_cleanup(sc);
-			return -EIO;
-		} else {
-			sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
-		}
-	}
-
-	return 0;
-}
-#endif /* CONFIG_RFKILL */
-
-void ath_cleanup(struct ath_softc *sc)
-{
-	ath_detach(sc);
-	free_irq(sc->irq, sc);
-	ath_bus_cleanup(sc);
-	kfree(sc->sec_wiphy);
-	ieee80211_free_hw(sc->hw);
-}
-
-void ath_detach(struct ath_softc *sc)
-{
-	struct ieee80211_hw *hw = sc->hw;
-	int i = 0;
-
-	ath9k_ps_wakeup(sc);
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	ath_deinit_rfkill(sc);
-#endif
-	ath_deinit_leds(sc);
-	cancel_work_sync(&sc->chan_work);
-	cancel_delayed_work_sync(&sc->wiphy_work);
-
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy == NULL)
-			continue;
-		sc->sec_wiphy[i] = NULL;
-		ieee80211_unregister_hw(aphy->hw);
-		ieee80211_free_hw(aphy->hw);
-	}
-	ieee80211_unregister_hw(hw);
-	ath_rx_cleanup(sc);
-	ath_tx_cleanup(sc);
-
-	tasklet_kill(&sc->intr_tq);
-	tasklet_kill(&sc->bcon_tasklet);
-
-	if (!(sc->sc_flags & SC_OP_INVALID))
-		ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
-
-	/* cleanup tx queues */
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
-	ath9k_hw_detach(sc->sc_ah);
-	ath9k_exit_debug(sc);
-	ath9k_ps_restore(sc);
-}
-
-static int ath_init(u16 devid, struct ath_softc *sc)
-{
-	struct ath_hw *ah = NULL;
-	int status;
-	int error = 0, i;
-	int csz = 0;
-
-	/* XXX: hardware will not be ready until ath_open() being called */
-	sc->sc_flags |= SC_OP_INVALID;
-
-	if (ath9k_init_debug(sc) < 0)
-		printk(KERN_ERR "Unable to create debugfs files\n");
-
-	spin_lock_init(&sc->wiphy_lock);
-	spin_lock_init(&sc->sc_resetlock);
-	spin_lock_init(&sc->sc_serial_rw);
-	mutex_init(&sc->mutex);
-	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
-	tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
-		     (unsigned long)sc);
-
-	/*
-	 * Cache line size is used to size and align various
-	 * structures used to communicate with the hardware.
-	 */
-	ath_read_cachesize(sc, &csz);
-	/* XXX assert csz is non-zero */
-	sc->cachelsz = csz << 2;	/* convert to bytes */
-
-	ah = ath9k_hw_attach(devid, sc, &status);
-	if (ah == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to attach hardware; HAL status %d\n", status);
-		error = -ENXIO;
-		goto bad;
-	}
-	sc->sc_ah = ah;
-
-	/* Get the hardware key cache size. */
-	sc->keymax = ah->caps.keycache_size;
-	if (sc->keymax > ATH_KEYMAX) {
-		DPRINTF(sc, ATH_DBG_KEYCACHE,
-			"Warning, using only %u entries in %u key cache\n",
-			ATH_KEYMAX, sc->keymax);
-		sc->keymax = ATH_KEYMAX;
-	}
-
-	/*
-	 * Reset the key cache since some parts do not
-	 * reset the contents on initial power up.
-	 */
-	for (i = 0; i < sc->keymax; i++)
-		ath9k_hw_keyreset(ah, (u16) i);
-
-	if (ath9k_regd_init(sc->sc_ah))
-		goto bad;
-
-	/* default to MONITOR mode */
-	sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
-
-	/* Setup rate tables */
-
-	ath_rate_attach(sc);
-	ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
-	ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
-
-	/*
-	 * Allocate hardware transmit queues: one queue for
-	 * beacon frames and one data queue for each QoS
-	 * priority.  Note that the hal handles reseting
-	 * these queues at the needed time.
-	 */
-	sc->beacon.beaconq = ath_beaconq_setup(ah);
-	if (sc->beacon.beaconq == -1) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to setup a beacon xmit queue\n");
-		error = -EIO;
-		goto bad2;
-	}
-	sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
-	if (sc->beacon.cabq == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to setup CAB xmit queue\n");
-		error = -EIO;
-		goto bad2;
-	}
-
-	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
-	ath_cabq_update(sc);
-
-	for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
-		sc->tx.hwq_map[i] = -1;
-
-	/* Setup data queues */
-	/* NB: ensure BK queue is the lowest priority h/w queue */
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to setup xmit queue for BK traffic\n");
-		error = -EIO;
-		goto bad2;
-	}
-
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to setup xmit queue for BE traffic\n");
-		error = -EIO;
-		goto bad2;
-	}
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to setup xmit queue for VI traffic\n");
-		error = -EIO;
-		goto bad2;
-	}
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to setup xmit queue for VO traffic\n");
-		error = -EIO;
-		goto bad2;
-	}
-
-	/* Initializes the noise floor to a reasonable default value.
-	 * Later on this will be updated during ANI processing. */
-
-	sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
-	setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc);
-
-	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
-				   ATH9K_CIPHER_TKIP, NULL)) {
-		/*
-		 * Whether we should enable h/w TKIP MIC.
-		 * XXX: if we don't support WME TKIP MIC, then we wouldn't
-		 * report WMM capable, so it's always safe to turn on
-		 * TKIP MIC in this case.
-		 */
-		ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
-				       0, 1, NULL);
-	}
-
-	/*
-	 * Check whether the separate key cache entries
-	 * are required to handle both tx+rx MIC keys.
-	 * With split mic keys the number of stations is limited
-	 * to 27 otherwise 59.
-	 */
-	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
-				   ATH9K_CIPHER_TKIP, NULL)
-	    && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
-				      ATH9K_CIPHER_MIC, NULL)
-	    && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
-				      0, NULL))
-		sc->splitmic = 1;
-
-	/* turn on mcast key search if possible */
-	if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
-		(void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
-					     1, NULL);
-
-	sc->config.txpowlimit = ATH_TXPOWER_MAX;
-
-	/* 11n Capabilities */
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
-		sc->sc_flags |= SC_OP_TXAGGR;
-		sc->sc_flags |= SC_OP_RXAGGR;
-	}
-
-	sc->tx_chainmask = ah->caps.tx_chainmask;
-	sc->rx_chainmask = ah->caps.rx_chainmask;
-
-	ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
-	sc->rx.defant = ath9k_hw_getdefantenna(ah);
-
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
-
-	sc->beacon.slottime = ATH9K_SLOT_TIME_9;	/* default to short slot time */
-
-	/* initialize beacon slots */
-	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
-		sc->beacon.bslot[i] = NULL;
-		sc->beacon.bslot_aphy[i] = NULL;
-	}
-
-	/* save MISC configurations */
-	sc->config.swBeaconProcess = 1;
-
-	/* setup channels and rates */
-
-	sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
-	sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
-		sc->rates[IEEE80211_BAND_2GHZ];
-	sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
-	sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
-		ARRAY_SIZE(ath9k_2ghz_chantable);
-
-	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
-		sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
-		sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
-			sc->rates[IEEE80211_BAND_5GHZ];
-		sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
-		sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
-			ARRAY_SIZE(ath9k_5ghz_chantable);
-	}
-
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)
-		ath9k_hw_btcoex_enable(sc->sc_ah);
-
-	return 0;
-bad2:
-	/* cleanup tx queues */
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-bad:
-	if (ah)
-		ath9k_hw_detach(ah);
-	ath9k_exit_debug(sc);
-
-	return error;
-}
-
-void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
-{
-	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-		IEEE80211_HW_SIGNAL_DBM |
-		IEEE80211_HW_AMPDU_AGGREGATION |
-		IEEE80211_HW_SUPPORTS_PS |
-		IEEE80211_HW_PS_NULLFUNC_STACK |
-		IEEE80211_HW_SPECTRUM_MGMT;
-
-	if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
-		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
-
-	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_AP) |
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC) |
-		BIT(NL80211_IFTYPE_MESH_POINT);
-
-	hw->wiphy->reg_notifier = ath9k_reg_notifier;
-	hw->wiphy->strict_regulatory = true;
-
-	hw->queues = 4;
-	hw->max_rates = 4;
-	hw->channel_change_time = 5000;
-	hw->max_listen_interval = 10;
-	hw->max_rate_tries = ATH_11N_TXMAXTRY;
-	hw->sta_data_size = sizeof(struct ath_node);
-	hw->vif_data_size = sizeof(struct ath_vif);
-
-	hw->rate_control_algorithm = "ath9k_rate_control";
-
-	hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-		&sc->sbands[IEEE80211_BAND_2GHZ];
-	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
-		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-			&sc->sbands[IEEE80211_BAND_5GHZ];
-}
-
-int ath_attach(u16 devid, struct ath_softc *sc)
-{
-	struct ieee80211_hw *hw = sc->hw;
-	const struct ieee80211_regdomain *regd;
-	int error = 0, i;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
-
-	error = ath_init(devid, sc);
-	if (error != 0)
-		return error;
-
-	/* get mac address from hardware and set in mac80211 */
-
-	SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
-
-	ath_set_hw_capab(sc, hw);
-
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
-		setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
-		if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
-			setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
-	}
-
-	/* initialize tx/rx engine */
-	error = ath_tx_init(sc, ATH_TXBUF);
-	if (error != 0)
-		goto error_attach;
-
-	error = ath_rx_init(sc, ATH_RXBUF);
-	if (error != 0)
-		goto error_attach;
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	/* Initialze h/w Rfkill */
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
-
-	/* Initialize s/w rfkill */
-	error = ath_init_sw_rfkill(sc);
-	if (error)
-		goto error_attach;
-#endif
-
-	if (ath9k_is_world_regd(sc->sc_ah)) {
-		/* Anything applied here (prior to wiphy registration) gets
-		 * saved on the wiphy orig_* parameters */
-		regd = ath9k_world_regdomain(sc->sc_ah);
-		hw->wiphy->custom_regulatory = true;
-		hw->wiphy->strict_regulatory = false;
-	} else {
-		/* This gets applied in the case of the absense of CRDA,
-		 * it's our own custom world regulatory domain, similar to
-		 * cfg80211's but we enable passive scanning */
-		regd = ath9k_default_world_regdomain();
-	}
-	wiphy_apply_custom_regulatory(hw->wiphy, regd);
-	ath9k_reg_apply_radar_flags(hw->wiphy);
-	ath9k_reg_apply_world_flags(hw->wiphy, NL80211_REGDOM_SET_BY_DRIVER);
-
-	INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
-	INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
-	sc->wiphy_scheduler_int = msecs_to_jiffies(500);
-
-	error = ieee80211_register_hw(hw);
-
-	if (!ath9k_is_world_regd(sc->sc_ah)) {
-		error = regulatory_hint(hw->wiphy,
-			sc->sc_ah->regulatory.alpha2);
-		if (error)
-			goto error_attach;
-	}
-
-	/* Initialize LED control */
-	ath_init_leds(sc);
-
-
-	return 0;
-
-error_attach:
-	/* cleanup tx queues */
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
-	ath9k_hw_detach(sc->sc_ah);
-	ath9k_exit_debug(sc);
-
-	return error;
-}
-
-int ath_reset(struct ath_softc *sc, bool retry_tx)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ieee80211_hw *hw = sc->hw;
-	int r;
-
-	ath9k_hw_set_interrupts(ah, 0);
-	ath_drain_all_txq(sc, retry_tx);
-	ath_stoprecv(sc);
-	ath_flushrecv(sc);
-
-	spin_lock_bh(&sc->sc_resetlock);
-	r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
-	if (r)
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to reset hardware; reset status %u\n", r);
-	spin_unlock_bh(&sc->sc_resetlock);
-
-	if (ath_startrecv(sc) != 0)
-		DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
-
-	/*
-	 * We may be doing a reset in response to a request
-	 * that changes the channel so update any state that
-	 * might change as a result.
-	 */
-	ath_cache_conf_rate(sc, &hw->conf);
-
-	ath_update_txpow(sc);
-
-	if (sc->sc_flags & SC_OP_BEACONS)
-		ath_beacon_config(sc, NULL);	/* restart beacons */
-
-	ath9k_hw_set_interrupts(ah, sc->imask);
-
-	if (retry_tx) {
-		int i;
-		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-			if (ATH_TXQ_SETUP(sc, i)) {
-				spin_lock_bh(&sc->tx.txq[i].axq_lock);
-				ath_txq_schedule(sc, &sc->tx.txq[i]);
-				spin_unlock_bh(&sc->tx.txq[i].axq_lock);
-			}
-		}
-	}
-
-	return r;
-}
-
-/*
- *  This function will allocate both the DMA descriptor structure, and the
- *  buffers it contains.  These are used to contain the descriptors used
- *  by the system.
-*/
-int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
-		      struct list_head *head, const char *name,
-		      int nbuf, int ndesc)
-{
-#define	DS2PHYS(_dd, _ds)						\
-	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
-
-	struct ath_desc *ds;
-	struct ath_buf *bf;
-	int i, bsize, error;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
-		name, nbuf, ndesc);
-
-	INIT_LIST_HEAD(head);
-	/* ath_desc must be a multiple of DWORDs */
-	if ((sizeof(struct ath_desc) % 4) != 0) {
-		DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n");
-		ASSERT((sizeof(struct ath_desc) % 4) == 0);
-		error = -ENOMEM;
-		goto fail;
-	}
-
-	dd->dd_name = name;
-	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
-
-	/*
-	 * Need additional DMA memory because we can't use
-	 * descriptors that cross the 4K page boundary. Assume
-	 * one skipped descriptor per 4K page.
-	 */
-	if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
-		u32 ndesc_skipped =
-			ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
-		u32 dma_len;
-
-		while (ndesc_skipped) {
-			dma_len = ndesc_skipped * sizeof(struct ath_desc);
-			dd->dd_desc_len += dma_len;
-
-			ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
-		};
-	}
-
-	/* allocate descriptors */
-	dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
-					 &dd->dd_desc_paddr, GFP_KERNEL);
-	if (dd->dd_desc == NULL) {
-		error = -ENOMEM;
-		goto fail;
-	}
-	ds = dd->dd_desc;
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
-		dd->dd_name, ds, (u32) dd->dd_desc_len,
-		ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
-
-	/* allocate buffers */
-	bsize = sizeof(struct ath_buf) * nbuf;
-	bf = kzalloc(bsize, GFP_KERNEL);
-	if (bf == NULL) {
-		error = -ENOMEM;
-		goto fail2;
-	}
-	dd->dd_bufptr = bf;
-
-	for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
-		bf->bf_desc = ds;
-		bf->bf_daddr = DS2PHYS(dd, ds);
-
-		if (!(sc->sc_ah->caps.hw_caps &
-		      ATH9K_HW_CAP_4KB_SPLITTRANS)) {
-			/*
-			 * Skip descriptor addresses which can cause 4KB
-			 * boundary crossing (addr + length) with a 32 dword
-			 * descriptor fetch.
-			 */
-			while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
-				ASSERT((caddr_t) bf->bf_desc <
-				       ((caddr_t) dd->dd_desc +
-					dd->dd_desc_len));
-
-				ds += ndesc;
-				bf->bf_desc = ds;
-				bf->bf_daddr = DS2PHYS(dd, ds);
-			}
-		}
-		list_add_tail(&bf->list, head);
-	}
-	return 0;
-fail2:
-	dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
-			  dd->dd_desc_paddr);
-fail:
-	memset(dd, 0, sizeof(*dd));
-	return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
-}
-
-void ath_descdma_cleanup(struct ath_softc *sc,
-			 struct ath_descdma *dd,
-			 struct list_head *head)
-{
-	dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
-			  dd->dd_desc_paddr);
-
-	INIT_LIST_HEAD(head);
-	kfree(dd->dd_bufptr);
-	memset(dd, 0, sizeof(*dd));
-}
-
-int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case 0:
-		qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO];
-		break;
-	case 1:
-		qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI];
-		break;
-	case 2:
-		qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
-		break;
-	case 3:
-		qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK];
-		break;
-	default:
-		qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
-		break;
-	}
-
-	return qnum;
-}
-
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case ATH9K_WME_AC_VO:
-		qnum = 0;
-		break;
-	case ATH9K_WME_AC_VI:
-		qnum = 1;
-		break;
-	case ATH9K_WME_AC_BE:
-		qnum = 2;
-		break;
-	case ATH9K_WME_AC_BK:
-		qnum = 3;
-		break;
-	default:
-		qnum = -1;
-		break;
-	}
-
-	return qnum;
-}
-
-/* XXX: Remove me once we don't depend on ath9k_channel for all
- * this redundant data */
-void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
-			   struct ath9k_channel *ichan)
-{
-	struct ieee80211_channel *chan = hw->conf.channel;
-	struct ieee80211_conf *conf = &hw->conf;
-
-	ichan->channel = chan->center_freq;
-	ichan->chan = chan;
-
-	if (chan->band == IEEE80211_BAND_2GHZ) {
-		ichan->chanmode = CHANNEL_G;
-		ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
-	} else {
-		ichan->chanmode = CHANNEL_A;
-		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
-	}
-
-	sc->tx_chan_width = ATH9K_HT_MACMODE_20;
-
-	if (conf_is_ht(conf)) {
-		if (conf_is_ht40(conf))
-			sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
-
-		ichan->chanmode = ath_get_extchanmode(sc, chan,
-					    conf->channel_type);
-	}
-}
-
-/**********************/
-/* mac80211 callbacks */
-/**********************/
-
-static int ath9k_start(struct ieee80211_hw *hw)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ieee80211_channel *curchan = hw->conf.channel;
-	struct ath9k_channel *init_channel;
-	int r, pos;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with "
-		"initial channel: %d MHz\n", curchan->center_freq);
-
-	mutex_lock(&sc->mutex);
-
-	if (ath9k_wiphy_started(sc)) {
-		if (sc->chan_idx == curchan->hw_value) {
-			/*
-			 * Already on the operational channel, the new wiphy
-			 * can be marked active.
-			 */
-			aphy->state = ATH_WIPHY_ACTIVE;
-			ieee80211_wake_queues(hw);
-		} else {
-			/*
-			 * Another wiphy is on another channel, start the new
-			 * wiphy in paused state.
-			 */
-			aphy->state = ATH_WIPHY_PAUSED;
-			ieee80211_stop_queues(hw);
-		}
-		mutex_unlock(&sc->mutex);
-		return 0;
-	}
-	aphy->state = ATH_WIPHY_ACTIVE;
-
-	/* setup initial channel */
-
-	pos = curchan->hw_value;
-
-	sc->chan_idx = pos;
-	init_channel = &sc->sc_ah->channels[pos];
-	ath9k_update_ichannel(sc, hw, init_channel);
-
-	/* Reset SERDES registers */
-	ath9k_hw_configpcipowersave(sc->sc_ah, 0);
-
-	/*
-	 * The basic interface to setting the hardware in a good
-	 * state is ``reset''.  On return the hardware is known to
-	 * be powered up and with interrupts disabled.  This must
-	 * be followed by initialization of the appropriate bits
-	 * and then setup of the interrupt mask.
-	 */
-	spin_lock_bh(&sc->sc_resetlock);
-	r = ath9k_hw_reset(sc->sc_ah, init_channel, false);
-	if (r) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to reset hardware; reset status %u "
-			"(freq %u MHz)\n", r,
-			curchan->center_freq);
-		spin_unlock_bh(&sc->sc_resetlock);
-		goto mutex_unlock;
-	}
-	spin_unlock_bh(&sc->sc_resetlock);
-
-	/*
-	 * This is needed only to setup initial state
-	 * but it's best done after a reset.
-	 */
-	ath_update_txpow(sc);
-
-	/*
-	 * Setup the hardware after reset:
-	 * The receive engine is set going.
-	 * Frame transmit is handled entirely
-	 * in the frame output path; there's nothing to do
-	 * here except setup the interrupt mask.
-	 */
-	if (ath_startrecv(sc) != 0) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to start recv logic\n");
-		r = -EIO;
-		goto mutex_unlock;
-	}
-
-	/* Setup our intr mask. */
-	sc->imask = ATH9K_INT_RX | ATH9K_INT_TX
-		| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
-		| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
-
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
-		sc->imask |= ATH9K_INT_GTT;
-
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
-		sc->imask |= ATH9K_INT_CST;
-
-	ath_cache_conf_rate(sc, &hw->conf);
-
-	sc->sc_flags &= ~SC_OP_INVALID;
-
-	/* Disable BMISS interrupt when we're not associated */
-	sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
-
-	ieee80211_wake_queues(hw);
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	r = ath_start_rfkill_poll(sc);
-#endif
-
-mutex_unlock:
-	mutex_unlock(&sc->mutex);
-
-	return r;
-}
-
-static int ath9k_tx(struct ieee80211_hw *hw,
-		    struct sk_buff *skb)
-{
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_tx_control txctl;
-	int hdrlen, padsize;
-
-	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
-		printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state "
-		       "%d\n", wiphy_name(hw->wiphy), aphy->state);
-		goto exit;
-	}
-
-	memset(&txctl, 0, sizeof(struct ath_tx_control));
-
-	/*
-	 * As a temporary workaround, assign seq# here; this will likely need
-	 * to be cleaned up to work better with Beacon transmission and virtual
-	 * BSSes.
-	 */
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
-			sc->tx.seq_no += 0x10;
-		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
-	}
-
-	/* Add the padding after the header if this is not already done */
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	if (hdrlen & 3) {
-		padsize = hdrlen % 4;
-		if (skb_headroom(skb) < padsize)
-			return -1;
-		skb_push(skb, padsize);
-		memmove(skb->data, skb->data + padsize, hdrlen);
-	}
-
-	/* Check if a tx queue is available */
-
-	txctl.txq = ath_test_get_txq(sc, skb);
-	if (!txctl.txq)
-		goto exit;
-
-	DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
-
-	if (ath_tx_start(hw, skb, &txctl) != 0) {
-		DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n");
-		goto exit;
-	}
-
-	return 0;
-exit:
-	dev_kfree_skb_any(skb);
-	return 0;
-}
-
-static void ath9k_stop(struct ieee80211_hw *hw)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	aphy->state = ATH_WIPHY_INACTIVE;
-
-	if (sc->sc_flags & SC_OP_INVALID) {
-		DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
-		return;
-	}
-
-	mutex_lock(&sc->mutex);
-
-	ieee80211_stop_queues(hw);
-
-	if (ath9k_wiphy_started(sc)) {
-		mutex_unlock(&sc->mutex);
-		return; /* another wiphy still in use */
-	}
-
-	/* make sure h/w will not generate any interrupt
-	 * before setting the invalid flag. */
-	ath9k_hw_set_interrupts(sc->sc_ah, 0);
-
-	if (!(sc->sc_flags & SC_OP_INVALID)) {
-		ath_drain_all_txq(sc, false);
-		ath_stoprecv(sc);
-		ath9k_hw_phy_disable(sc->sc_ah);
-	} else
-		sc->rx.rxlink = NULL;
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
-#endif
-	/* disable HAL and put h/w to sleep */
-	ath9k_hw_disable(sc->sc_ah);
-	ath9k_hw_configpcipowersave(sc->sc_ah, 1);
-
-	sc->sc_flags |= SC_OP_INVALID;
-
-	mutex_unlock(&sc->mutex);
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n");
-}
-
-static int ath9k_add_interface(struct ieee80211_hw *hw,
-			       struct ieee80211_if_init_conf *conf)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_vif *avp = (void *)conf->vif->drv_priv;
-	enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
-	int ret = 0;
-
-	mutex_lock(&sc->mutex);
-
-	if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) &&
-	    sc->nvifs > 0) {
-		ret = -ENOBUFS;
-		goto out;
-	}
-
-	switch (conf->type) {
-	case NL80211_IFTYPE_STATION:
-		ic_opmode = NL80211_IFTYPE_STATION;
-		break;
-	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_MESH_POINT:
-		if (sc->nbcnvifs >= ATH_BCBUF) {
-			ret = -ENOBUFS;
-			goto out;
-		}
-		ic_opmode = conf->type;
-		break;
-	default:
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Interface type %d not yet supported\n", conf->type);
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode);
-
-	/* Set the VIF opmode */
-	avp->av_opmode = ic_opmode;
-	avp->av_bslot = -1;
-
-	sc->nvifs++;
-
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		ath9k_set_bssid_mask(hw);
-
-	if (sc->nvifs > 1)
-		goto out; /* skip global settings for secondary vif */
-
-	if (ic_opmode == NL80211_IFTYPE_AP) {
-		ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
-		sc->sc_flags |= SC_OP_TSF_RESET;
-	}
-
-	/* Set the device opmode */
-	sc->sc_ah->opmode = ic_opmode;
-
-	/*
-	 * Enable MIB interrupts when there are hardware phy counters.
-	 * Note we only do this (at the moment) for station mode.
-	 */
-	if ((conf->type == NL80211_IFTYPE_STATION) ||
-	    (conf->type == NL80211_IFTYPE_ADHOC) ||
-	    (conf->type == NL80211_IFTYPE_MESH_POINT)) {
-		if (ath9k_hw_phycounters(sc->sc_ah))
-			sc->imask |= ATH9K_INT_MIB;
-		sc->imask |= ATH9K_INT_TSFOOR;
-	}
-
-	/*
-	 * Some hardware processes the TIM IE and fires an
-	 * interrupt when the TIM bit is set.  For hardware
-	 * that does, if not overridden by configuration,
-	 * enable the TIM interrupt when operating as station.
-	 */
-	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
-	    (conf->type == NL80211_IFTYPE_STATION) &&
-	    !sc->config.swBeaconProcess)
-		sc->imask |= ATH9K_INT_TIM;
-
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
-
-	if (conf->type == NL80211_IFTYPE_AP) {
-		/* TODO: is this a suitable place to start ANI for AP mode? */
-		/* Start ANI */
-		mod_timer(&sc->ani.timer,
-			  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
-	}
-
-out:
-	mutex_unlock(&sc->mutex);
-	return ret;
-}
-
-static void ath9k_remove_interface(struct ieee80211_hw *hw,
-				   struct ieee80211_if_init_conf *conf)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_vif *avp = (void *)conf->vif->drv_priv;
-	int i;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n");
-
-	mutex_lock(&sc->mutex);
-
-	/* Stop ANI */
-	del_timer_sync(&sc->ani.timer);
-
-	/* Reclaim beacon resources */
-	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
-		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-		ath_beacon_return(sc, avp);
-	}
-
-	sc->sc_flags &= ~SC_OP_BEACONS;
-
-	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
-		if (sc->beacon.bslot[i] == conf->vif) {
-			printk(KERN_DEBUG "%s: vif had allocated beacon "
-			       "slot\n", __func__);
-			sc->beacon.bslot[i] = NULL;
-			sc->beacon.bslot_aphy[i] = NULL;
-		}
-	}
-
-	sc->nvifs--;
-
-	mutex_unlock(&sc->mutex);
-}
-
-static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ieee80211_conf *conf = &hw->conf;
-
-	mutex_lock(&sc->mutex);
-
-	if (changed & IEEE80211_CONF_CHANGE_PS) {
-		if (conf->flags & IEEE80211_CONF_PS) {
-			if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
-				sc->imask |= ATH9K_INT_TIM_TIMER;
-				ath9k_hw_set_interrupts(sc->sc_ah,
-						sc->imask);
-			}
-			ath9k_hw_setrxabort(sc->sc_ah, 1);
-			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
-		} else {
-			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
-			ath9k_hw_setrxabort(sc->sc_ah, 0);
-			sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
-			if (sc->imask & ATH9K_INT_TIM_TIMER) {
-				sc->imask &= ~ATH9K_INT_TIM_TIMER;
-				ath9k_hw_set_interrupts(sc->sc_ah,
-						sc->imask);
-			}
-		}
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		struct ieee80211_channel *curchan = hw->conf.channel;
-		int pos = curchan->hw_value;
-
-		aphy->chan_idx = pos;
-		aphy->chan_is_ht = conf_is_ht(conf);
-
-		if (aphy->state == ATH_WIPHY_SCAN ||
-		    aphy->state == ATH_WIPHY_ACTIVE)
-			ath9k_wiphy_pause_all_forced(sc, aphy);
-		else {
-			/*
-			 * Do not change operational channel based on a paused
-			 * wiphy changes.
-			 */
-			goto skip_chan_change;
-		}
-
-		DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
-			curchan->center_freq);
-
-		/* XXX: remove me eventualy */
-		ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
-
-		ath_update_chainmask(sc, conf_is_ht(conf));
-
-		if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
-			DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n");
-			mutex_unlock(&sc->mutex);
-			return -EINVAL;
-		}
-	}
-
-skip_chan_change:
-	if (changed & IEEE80211_CONF_CHANGE_POWER)
-		sc->config.txpowlimit = 2 * conf->power_level;
-
-	/*
-	 * The HW TSF has to be reset when the beacon interval changes.
-	 * We set the flag here, and ath_beacon_config_ap() would take this
-	 * into account when it gets called through the subsequent
-	 * config_interface() call - with IFCC_BEACON in the changed field.
-	 */
-
-	if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
-		sc->sc_flags |= SC_OP_TSF_RESET;
-
-	mutex_unlock(&sc->mutex);
-
-	return 0;
-}
-
-static int ath9k_config_interface(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif,
-				  struct ieee80211_if_conf *conf)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_vif *avp = (void *)vif->drv_priv;
-	u32 rfilt = 0;
-	int error, i;
-
-	mutex_lock(&sc->mutex);
-
-	/* TODO: Need to decide which hw opmode to use for multi-interface
-	 * cases */
-	if (vif->type == NL80211_IFTYPE_AP &&
-	    ah->opmode != NL80211_IFTYPE_AP) {
-		ah->opmode = NL80211_IFTYPE_STATION;
-		ath9k_hw_setopmode(ah);
-		memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN);
-		sc->curaid = 0;
-		ath9k_hw_write_associd(sc);
-		/* Request full reset to get hw opmode changed properly */
-		sc->sc_flags |= SC_OP_FULL_RESET;
-	}
-
-	if ((conf->changed & IEEE80211_IFCC_BSSID) &&
-	    !is_zero_ether_addr(conf->bssid)) {
-		switch (vif->type) {
-		case NL80211_IFTYPE_STATION:
-		case NL80211_IFTYPE_ADHOC:
-		case NL80211_IFTYPE_MESH_POINT:
-			/* Set BSSID */
-			memcpy(sc->curbssid, conf->bssid, ETH_ALEN);
-			memcpy(avp->bssid, conf->bssid, ETH_ALEN);
-			sc->curaid = 0;
-			ath9k_hw_write_associd(sc);
-
-			/* Set aggregation protection mode parameters */
-			sc->config.ath_aggr_prot = 0;
-
-			DPRINTF(sc, ATH_DBG_CONFIG,
-				"RX filter 0x%x bssid %pM aid 0x%x\n",
-				rfilt, sc->curbssid, sc->curaid);
-
-			/* need to reconfigure the beacon */
-			sc->sc_flags &= ~SC_OP_BEACONS ;
-
-			break;
-		default:
-			break;
-		}
-	}
-
-	if ((vif->type == NL80211_IFTYPE_ADHOC) ||
-	    (vif->type == NL80211_IFTYPE_AP) ||
-	    (vif->type == NL80211_IFTYPE_MESH_POINT)) {
-		if ((conf->changed & IEEE80211_IFCC_BEACON) ||
-		    (conf->changed & IEEE80211_IFCC_BEACON_ENABLED &&
-		     conf->enable_beacon)) {
-			/*
-			 * Allocate and setup the beacon frame.
-			 *
-			 * Stop any previous beacon DMA.  This may be
-			 * necessary, for example, when an ibss merge
-			 * causes reconfiguration; we may be called
-			 * with beacon transmission active.
-			 */
-			ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-
-			error = ath_beacon_alloc(aphy, vif);
-			if (error != 0) {
-				mutex_unlock(&sc->mutex);
-				return error;
-			}
-
-			ath_beacon_config(sc, vif);
-		}
-	}
-
-	/* Check for WLAN_CAPABILITY_PRIVACY ? */
-	if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
-		for (i = 0; i < IEEE80211_WEP_NKID; i++)
-			if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
-				ath9k_hw_keysetmac(sc->sc_ah,
-						   (u16)i,
-						   sc->curbssid);
-	}
-
-	/* Only legacy IBSS for now */
-	if (vif->type == NL80211_IFTYPE_ADHOC)
-		ath_update_chainmask(sc, 0);
-
-	mutex_unlock(&sc->mutex);
-
-	return 0;
-}
-
-#define SUPPORTED_FILTERS			\
-	(FIF_PROMISC_IN_BSS |			\
-	FIF_ALLMULTI |				\
-	FIF_CONTROL |				\
-	FIF_OTHER_BSS |				\
-	FIF_BCN_PRBRESP_PROMISC |		\
-	FIF_FCSFAIL)
-
-/* FIXME: sc->sc_full_reset ? */
-static void ath9k_configure_filter(struct ieee80211_hw *hw,
-				   unsigned int changed_flags,
-				   unsigned int *total_flags,
-				   int mc_count,
-				   struct dev_mc_list *mclist)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	u32 rfilt;
-
-	changed_flags &= SUPPORTED_FILTERS;
-	*total_flags &= SUPPORTED_FILTERS;
-
-	sc->rx.rxfilter = *total_flags;
-	rfilt = ath_calcrxfilter(sc);
-	ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter);
-}
-
-static void ath9k_sta_notify(struct ieee80211_hw *hw,
-			     struct ieee80211_vif *vif,
-			     enum sta_notify_cmd cmd,
-			     struct ieee80211_sta *sta)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	switch (cmd) {
-	case STA_NOTIFY_ADD:
-		ath_node_attach(sc, sta);
-		break;
-	case STA_NOTIFY_REMOVE:
-		ath_node_detach(sc, sta);
-		break;
-	default:
-		break;
-	}
-}
-
-static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			 const struct ieee80211_tx_queue_params *params)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath9k_tx_queue_info qi;
-	int ret = 0, qnum;
-
-	if (queue >= WME_NUM_AC)
-		return 0;
-
-	mutex_lock(&sc->mutex);
-
-	qi.tqi_aifs = params->aifs;
-	qi.tqi_cwmin = params->cw_min;
-	qi.tqi_cwmax = params->cw_max;
-	qi.tqi_burstTime = params->txop;
-	qnum = ath_get_hal_qnum(queue, sc);
-
-	DPRINTF(sc, ATH_DBG_CONFIG,
-		"Configure tx [queue/halq] [%d/%d],  "
-		"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
-		queue, qnum, params->aifs, params->cw_min,
-		params->cw_max, params->txop);
-
-	ret = ath_txq_update(sc, qnum, &qi);
-	if (ret)
-		DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n");
-
-	mutex_unlock(&sc->mutex);
-
-	return ret;
-}
-
-static int ath9k_set_key(struct ieee80211_hw *hw,
-			 enum set_key_cmd cmd,
-			 struct ieee80211_vif *vif,
-			 struct ieee80211_sta *sta,
-			 struct ieee80211_key_conf *key)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	int ret = 0;
-
-	if (modparam_nohwcrypt)
-		return -ENOSPC;
-
-	mutex_lock(&sc->mutex);
-	ath9k_ps_wakeup(sc);
-	DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n");
-
-	switch (cmd) {
-	case SET_KEY:
-		ret = ath_key_config(sc, vif, sta, key);
-		if (ret >= 0) {
-			key->hw_key_idx = ret;
-			/* push IV and Michael MIC generation to stack */
-			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-			if (key->alg == ALG_TKIP)
-				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-			if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
-				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
-			ret = 0;
-		}
-		break;
-	case DISABLE_KEY:
-		ath_key_delete(sc, key);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	ath9k_ps_restore(sc);
-	mutex_unlock(&sc->mutex);
-
-	return ret;
-}
-
-static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif,
-				   struct ieee80211_bss_conf *bss_conf,
-				   u32 changed)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	mutex_lock(&sc->mutex);
-
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
-			bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
-		else
-			sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
-	}
-
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
-			bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot &&
-		    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
-			sc->sc_flags |= SC_OP_PROTECT_ENABLE;
-		else
-			sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
-	}
-
-	if (changed & BSS_CHANGED_ASSOC) {
-		DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
-			bss_conf->assoc);
-		ath9k_bss_assoc_info(sc, vif, bss_conf);
-	}
-
-	mutex_unlock(&sc->mutex);
-}
-
-static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
-{
-	u64 tsf;
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	mutex_lock(&sc->mutex);
-	tsf = ath9k_hw_gettsf64(sc->sc_ah);
-	mutex_unlock(&sc->mutex);
-
-	return tsf;
-}
-
-static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	mutex_lock(&sc->mutex);
-	ath9k_hw_settsf64(sc->sc_ah, tsf);
-	mutex_unlock(&sc->mutex);
-}
-
-static void ath9k_reset_tsf(struct ieee80211_hw *hw)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	mutex_lock(&sc->mutex);
-	ath9k_hw_reset_tsf(sc->sc_ah);
-	mutex_unlock(&sc->mutex);
-}
-
-static int ath9k_ampdu_action(struct ieee80211_hw *hw,
-			      enum ieee80211_ampdu_mlme_action action,
-			      struct ieee80211_sta *sta,
-			      u16 tid, u16 *ssn)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	int ret = 0;
-
-	switch (action) {
-	case IEEE80211_AMPDU_RX_START:
-		if (!(sc->sc_flags & SC_OP_RXAGGR))
-			ret = -ENOTSUPP;
-		break;
-	case IEEE80211_AMPDU_RX_STOP:
-		break;
-	case IEEE80211_AMPDU_TX_START:
-		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
-		if (ret < 0)
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Unable to start TX aggregation\n");
-		else
-			ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
-		break;
-	case IEEE80211_AMPDU_TX_STOP:
-		ret = ath_tx_aggr_stop(sc, sta, tid);
-		if (ret < 0)
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Unable to stop TX aggregation\n");
-
-		ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
-		break;
-	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		ath_tx_aggr_resume(sc, sta, tid);
-		break;
-	default:
-		DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n");
-	}
-
-	return ret;
-}
-
-static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	if (ath9k_wiphy_scanning(sc)) {
-		printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the "
-		       "same time\n");
-		/*
-		 * Do not allow the concurrent scanning state for now. This
-		 * could be improved with scanning control moved into ath9k.
-		 */
-		return;
-	}
-
-	aphy->state = ATH_WIPHY_SCAN;
-	ath9k_wiphy_pause_all_forced(sc, aphy);
-
-	mutex_lock(&sc->mutex);
-	sc->sc_flags |= SC_OP_SCANNING;
-	mutex_unlock(&sc->mutex);
-}
-
-static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	mutex_lock(&sc->mutex);
-	aphy->state = ATH_WIPHY_ACTIVE;
-	sc->sc_flags &= ~SC_OP_SCANNING;
-	mutex_unlock(&sc->mutex);
-}
-
-struct ieee80211_ops ath9k_ops = {
-	.tx 		    = ath9k_tx,
-	.start 		    = ath9k_start,
-	.stop 		    = ath9k_stop,
-	.add_interface 	    = ath9k_add_interface,
-	.remove_interface   = ath9k_remove_interface,
-	.config 	    = ath9k_config,
-	.config_interface   = ath9k_config_interface,
-	.configure_filter   = ath9k_configure_filter,
-	.sta_notify         = ath9k_sta_notify,
-	.conf_tx 	    = ath9k_conf_tx,
-	.bss_info_changed   = ath9k_bss_info_changed,
-	.set_key            = ath9k_set_key,
-	.get_tsf 	    = ath9k_get_tsf,
-	.set_tsf 	    = ath9k_set_tsf,
-	.reset_tsf 	    = ath9k_reset_tsf,
-	.ampdu_action       = ath9k_ampdu_action,
-	.sw_scan_start      = ath9k_sw_scan_start,
-	.sw_scan_complete   = ath9k_sw_scan_complete,
-};
-
-static struct {
-	u32 version;
-	const char * name;
-} ath_mac_bb_names[] = {
-	{ AR_SREV_VERSION_5416_PCI,	"5416" },
-	{ AR_SREV_VERSION_5416_PCIE,	"5418" },
-	{ AR_SREV_VERSION_9100,		"9100" },
-	{ AR_SREV_VERSION_9160,		"9160" },
-	{ AR_SREV_VERSION_9280,		"9280" },
-	{ AR_SREV_VERSION_9285,		"9285" }
-};
-
-static struct {
-	u16 version;
-	const char * name;
-} ath_rf_names[] = {
-	{ 0,				"5133" },
-	{ AR_RAD5133_SREV_MAJOR,	"5133" },
-	{ AR_RAD5122_SREV_MAJOR,	"5122" },
-	{ AR_RAD2133_SREV_MAJOR,	"2133" },
-	{ AR_RAD2122_SREV_MAJOR,	"2122" }
-};
-
-/*
- * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
- */
-const char *
-ath_mac_bb_name(u32 mac_bb_version)
-{
-	int i;
-
-	for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
-		if (ath_mac_bb_names[i].version == mac_bb_version) {
-			return ath_mac_bb_names[i].name;
-		}
-	}
-
-	return "????";
-}
-
-/*
- * Return the RF name. "????" is returned if the RF is unknown.
- */
-const char *
-ath_rf_name(u16 rf_version)
-{
-	int i;
-
-	for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
-		if (ath_rf_names[i].version == rf_version) {
-			return ath_rf_names[i].name;
-		}
-	}
-
-	return "????";
-}
-
-static int __init ath9k_init(void)
-{
-	int error;
-
-	/* Register rate control algorithm */
-	error = ath_rate_control_register();
-	if (error != 0) {
-		printk(KERN_ERR
-			"ath9k: Unable to register rate control "
-			"algorithm: %d\n",
-			error);
-		goto err_out;
-	}
-
-	error = ath9k_debug_create_root();
-	if (error) {
-		printk(KERN_ERR
-			"ath9k: Unable to create debugfs root: %d\n",
-			error);
-		goto err_rate_unregister;
-	}
-
-	error = ath_pci_init();
-	if (error < 0) {
-		printk(KERN_ERR
-			"ath9k: No PCI devices found, driver not installed.\n");
-		error = -ENODEV;
-		goto err_remove_root;
-	}
-
-	error = ath_ahb_init();
-	if (error < 0) {
-		error = -ENODEV;
-		goto err_pci_exit;
-	}
-
-	return 0;
-
- err_pci_exit:
-	ath_pci_exit();
-
- err_remove_root:
-	ath9k_debug_remove_root();
- err_rate_unregister:
-	ath_rate_control_unregister();
- err_out:
-	return error;
-}
-module_init(ath9k_init);
-
-static void __exit ath9k_exit(void)
-{
-	ath_ahb_exit();
-	ath_pci_exit();
-	ath9k_debug_remove_root();
-	ath_rate_control_unregister();
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
-}
-module_exit(ath9k_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-ath9k-y +=	hw.o \
-		eeprom.o \
-		mac.o \
-		calib.o \
-		ani.o \
-		phy.o \
-		regd.o \
-		beacon.o \
-		main.o \
-		recv.o \
-		xmit.o \
-		virtual.o \
-		rc.o
-
-ath9k-$(CONFIG_PCI) += pci.o
-ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
-ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o
-
-obj-$(CONFIG_ATH9K) += ath9k.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/pci.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/pci.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/pci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,295 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/nl80211.h>
-#include <linux/pci.h>
-#include "ath9k.h"
-
-static struct pci_device_id ath_pci_id_table[] __devinitdata = {
-	{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI   */
-	{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
-	{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
-	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
-	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
-	{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
-	{ 0 }
-};
-
-/* return bus cachesize in 4B word units */
-static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
-{
-	u8 u8tmp;
-
-	pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE,
-			     (u8 *)&u8tmp);
-	*csz = (int)u8tmp;
-
-	/*
-	 * This check was put in to avoid "unplesant" consequences if
-	 * the bootrom has not fully initialized all PCI devices.
-	 * Sometimes the cache line size register is not set
-	 */
-
-	if (*csz == 0)
-		*csz = DEFAULT_CACHELINE >> 2;   /* Use the default size */
-}
-
-static void ath_pci_cleanup(struct ath_softc *sc)
-{
-	struct pci_dev *pdev = to_pci_dev(sc->dev);
-
-	pci_iounmap(pdev, sc->mem);
-	pci_disable_device(pdev);
-	pci_release_region(pdev, 0);
-}
-
-static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data)
-{
-	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
-
-	if (!ath9k_hw_wait(ah,
-			   AR_EEPROM_STATUS_DATA,
-			   AR_EEPROM_STATUS_DATA_BUSY |
-			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
-			   AH_WAIT_TIMEOUT)) {
-		return false;
-	}
-
-	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
-		   AR_EEPROM_STATUS_DATA_VAL);
-
-	return true;
-}
-
-static struct ath_bus_ops ath_pci_bus_ops = {
-	.read_cachesize = ath_pci_read_cachesize,
-	.cleanup = ath_pci_cleanup,
-	.eeprom_read = ath_pci_eeprom_read,
-};
-
-static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	void __iomem *mem;
-	struct ath_wiphy *aphy;
-	struct ath_softc *sc;
-	struct ieee80211_hw *hw;
-	u8 csz;
-	int ret = 0;
-	struct ath_hw *ah;
-
-	if (pci_enable_device(pdev))
-		return -EIO;
-
-	ret =  pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-
-	if (ret) {
-		printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
-		goto bad;
-	}
-
-	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-
-	if (ret) {
-		printk(KERN_ERR "ath9k: 32-bit DMA consistent "
-			"DMA enable failed\n");
-		goto bad;
-	}
-
-	/*
-	 * Cache line size is used to size and align various
-	 * structures used to communicate with the hardware.
-	 */
-	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
-	if (csz == 0) {
-		/*
-		 * Linux 2.4.18 (at least) writes the cache line size
-		 * register as a 16-bit wide register which is wrong.
-		 * We must have this setup properly for rx buffer
-		 * DMA to work so force a reasonable value here if it
-		 * comes up zero.
-		 */
-		csz = L1_CACHE_BYTES / sizeof(u32);
-		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
-	}
-	/*
-	 * The default setting of latency timer yields poor results,
-	 * set it to the value used by other systems. It may be worth
-	 * tweaking this setting more.
-	 */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
-
-	pci_set_master(pdev);
-
-	ret = pci_request_region(pdev, 0, "ath9k");
-	if (ret) {
-		dev_err(&pdev->dev, "PCI memory region reserve error\n");
-		ret = -ENODEV;
-		goto bad;
-	}
-
-	mem = pci_iomap(pdev, 0, 0);
-	if (!mem) {
-		printk(KERN_ERR "PCI memory map error\n") ;
-		ret = -EIO;
-		goto bad1;
-	}
-
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
-				sizeof(struct ath_softc), &ath9k_ops);
-	if (hw == NULL) {
-		printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n");
-		goto bad2;
-	}
-
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-	pci_set_drvdata(pdev, hw);
-
-	aphy = hw->priv;
-	sc = (struct ath_softc *) (aphy + 1);
-	aphy->sc = sc;
-	aphy->hw = hw;
-	sc->pri_wiphy = aphy;
-	sc->hw = hw;
-	sc->dev = &pdev->dev;
-	sc->mem = mem;
-	sc->bus_ops = &ath_pci_bus_ops;
-
-	if (ath_attach(id->device, sc) != 0) {
-		ret = -ENODEV;
-		goto bad3;
-	}
-
-	/* setup interrupt service routine */
-
-	if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) {
-		printk(KERN_ERR "%s: request_irq failed\n",
-			wiphy_name(hw->wiphy));
-		ret = -EIO;
-		goto bad4;
-	}
-
-	sc->irq = pdev->irq;
-
-	ah = sc->sc_ah;
-	printk(KERN_INFO
-	       "%s: Atheros AR%s MAC/BB Rev:%x "
-	       "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n",
-	       wiphy_name(hw->wiphy),
-	       ath_mac_bb_name(ah->hw_version.macVersion),
-	       ah->hw_version.macRev,
-	       ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
-	       ah->hw_version.phyRev,
-	       (unsigned long)mem, pdev->irq);
-
-	return 0;
-bad4:
-	ath_detach(sc);
-bad3:
-	ieee80211_free_hw(hw);
-bad2:
-	pci_iounmap(pdev, mem);
-bad1:
-	pci_release_region(pdev, 0);
-bad:
-	pci_disable_device(pdev);
-	return ret;
-}
-
-static void ath_pci_remove(struct pci_dev *pdev)
-{
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	ath_cleanup(sc);
-}
-
-#ifdef CONFIG_PM
-
-static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
-#endif
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int ath_pci_resume(struct pci_dev *pdev)
-{
-	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	int err;
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-	pci_restore_state(pdev);
-
-	/* Enable LED */
-	ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
-			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	/*
-	 * check the h/w rfkill state on resume
-	 * and start the rfkill poll timer
-	 */
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		queue_delayed_work(sc->hw->workqueue,
-				   &sc->rf_kill.rfkill_poll, 0);
-#endif
-
-	return 0;
-}
-
-#endif /* CONFIG_PM */
-
-MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
-
-static struct pci_driver ath_pci_driver = {
-	.name       = "ath9k",
-	.id_table   = ath_pci_id_table,
-	.probe      = ath_pci_probe,
-	.remove     = ath_pci_remove,
-#ifdef CONFIG_PM
-	.suspend    = ath_pci_suspend,
-	.resume     = ath_pci_resume,
-#endif /* CONFIG_PM */
-};
-
-int ath_pci_init(void)
-{
-	return pci_register_driver(&ath_pci_driver);
-}
-
-void ath_pci_exit(void)
-{
-	pci_unregister_driver(&ath_pci_driver);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/phy.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/phy.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/phy.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/phy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,424 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-void
-ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex,
-		    int regWrites)
-{
-	REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
-}
-
-bool
-ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	u32 channelSel = 0;
-	u32 bModeSynth = 0;
-	u32 aModeRefSel = 0;
-	u32 reg32 = 0;
-	u16 freq;
-	struct chan_centers centers;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	freq = centers.synth_center;
-
-	if (freq < 4800) {
-		u32 txctl;
-
-		if (((freq - 2192) % 5) == 0) {
-			channelSel = ((freq - 672) * 2 - 3040) / 10;
-			bModeSynth = 0;
-		} else if (((freq - 2224) % 5) == 0) {
-			channelSel = ((freq - 704) * 2 - 3040) / 10;
-			bModeSynth = 1;
-		} else {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-				"Invalid channel %u MHz\n", freq);
-			return false;
-		}
-
-		channelSel = (channelSel << 2) & 0xff;
-		channelSel = ath9k_hw_reverse_bits(channelSel, 8);
-
-		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
-		if (freq == 2484) {
-
-			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
-				  txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
-		} else {
-			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
-				  txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
-		}
-
-	} else if ((freq % 20) == 0 && freq >= 5120) {
-		channelSel =
-		    ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
-		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
-	} else if ((freq % 10) == 0) {
-		channelSel =
-		    ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
-		if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
-			aModeRefSel = ath9k_hw_reverse_bits(2, 2);
-		else
-			aModeRefSel = ath9k_hw_reverse_bits(1, 2);
-	} else if ((freq % 5) == 0) {
-		channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
-		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
-	} else {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			"Invalid channel %u MHz\n", freq);
-		return false;
-	}
-
-	reg32 =
-	    (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
-	    (1 << 5) | 0x1;
-
-	REG_WRITE(ah, AR_PHY(0x37), reg32);
-
-	ah->curchan = chan;
-	ah->curchan_rad_index = -1;
-
-	return true;
-}
-
-bool
-ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
-			    struct ath9k_channel *chan)
-{
-	u16 bMode, fracMode, aModeRefSel = 0;
-	u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
-	struct chan_centers centers;
-	u32 refDivA = 24;
-
-	ath9k_hw_get_channel_centers(ah, chan, &centers);
-	freq = centers.synth_center;
-
-	reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
-	reg32 &= 0xc0000000;
-
-	if (freq < 4800) {
-		u32 txctl;
-
-		bMode = 1;
-		fracMode = 1;
-		aModeRefSel = 0;
-		channelSel = (freq * 0x10000) / 15;
-
-		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
-		if (freq == 2484) {
-
-			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
-				  txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
-		} else {
-			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
-				  txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
-		}
-	} else {
-		bMode = 0;
-		fracMode = 0;
-
-		switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
-		case 0:
-			if ((freq % 20) == 0) {
-				aModeRefSel = 3;
-			} else if ((freq % 10) == 0) {
-				aModeRefSel = 2;
-			}
-			if (aModeRefSel)
-				break;
-		case 1:
-		default:
-			aModeRefSel = 0;
-			fracMode = 1;
-			refDivA = 1;
-			channelSel = (freq * 0x8000) / 15;
-
-			REG_RMW_FIELD(ah, AR_AN_SYNTH9,
-				      AR_AN_SYNTH9_REFDIVA, refDivA);
-
-		}
-
-		if (!fracMode) {
-			ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
-			channelSel = ndiv & 0x1ff;
-			channelFrac = (ndiv & 0xfffffe00) * 2;
-			channelSel = (channelSel << 17) | channelFrac;
-		}
-	}
-
-	reg32 = reg32 |
-	    (bMode << 29) |
-	    (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
-
-	REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
-
-	ah->curchan = chan;
-	ah->curchan_rad_index = -1;
-
-	return true;
-}
-
-static void
-ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
-			   u32 numBits, u32 firstBit,
-			   u32 column)
-{
-	u32 tmp32, mask, arrayEntry, lastBit;
-	int32_t bitPosition, bitsLeft;
-
-	tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
-	arrayEntry = (firstBit - 1) / 8;
-	bitPosition = (firstBit - 1) % 8;
-	bitsLeft = numBits;
-	while (bitsLeft > 0) {
-		lastBit = (bitPosition + bitsLeft > 8) ?
-		    8 : bitPosition + bitsLeft;
-		mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
-		    (column * 8);
-		rfBuf[arrayEntry] &= ~mask;
-		rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
-				      (column * 8)) & mask;
-		bitsLeft -= 8 - bitPosition;
-		tmp32 = tmp32 >> (8 - bitPosition);
-		bitPosition = 0;
-		arrayEntry++;
-	}
-}
-
-bool
-ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
-		     u16 modesIndex)
-{
-	u32 eepMinorRev;
-	u32 ob5GHz = 0, db5GHz = 0;
-	u32 ob2GHz = 0, db2GHz = 0;
-	int regWrites = 0;
-
-	if (AR_SREV_9280_10_OR_LATER(ah))
-		return true;
-
-	eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
-
-	RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1);
-
-	RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1);
-
-	RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1);
-
-	RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3,
-		      modesIndex);
-	{
-		int i;
-		for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
-			ah->analogBank6Data[i] =
-			    INI_RA(&ah->iniBank6TPC, i, modesIndex);
-		}
-	}
-
-	if (eepMinorRev >= 2) {
-		if (IS_CHAN_2GHZ(chan)) {
-			ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);
-			db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2);
-			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
-						   ob2GHz, 3, 197, 0);
-			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
-						   db2GHz, 3, 194, 0);
-		} else {
-			ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5);
-			db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5);
-			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
-						   ob5GHz, 3, 203, 0);
-			ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
-						   db5GHz, 3, 200, 0);
-		}
-	}
-
-	RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1);
-
-	REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
-			   regWrites);
-	REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
-			   regWrites);
-	REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
-			   regWrites);
-	REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
-			   regWrites);
-	REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
-			   regWrites);
-	REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
-			   regWrites);
-
-	return true;
-}
-
-void
-ath9k_hw_rfdetach(struct ath_hw *ah)
-{
-	if (ah->analogBank0Data != NULL) {
-		kfree(ah->analogBank0Data);
-		ah->analogBank0Data = NULL;
-	}
-	if (ah->analogBank1Data != NULL) {
-		kfree(ah->analogBank1Data);
-		ah->analogBank1Data = NULL;
-	}
-	if (ah->analogBank2Data != NULL) {
-		kfree(ah->analogBank2Data);
-		ah->analogBank2Data = NULL;
-	}
-	if (ah->analogBank3Data != NULL) {
-		kfree(ah->analogBank3Data);
-		ah->analogBank3Data = NULL;
-	}
-	if (ah->analogBank6Data != NULL) {
-		kfree(ah->analogBank6Data);
-		ah->analogBank6Data = NULL;
-	}
-	if (ah->analogBank6TPCData != NULL) {
-		kfree(ah->analogBank6TPCData);
-		ah->analogBank6TPCData = NULL;
-	}
-	if (ah->analogBank7Data != NULL) {
-		kfree(ah->analogBank7Data);
-		ah->analogBank7Data = NULL;
-	}
-	if (ah->addac5416_21 != NULL) {
-		kfree(ah->addac5416_21);
-		ah->addac5416_21 = NULL;
-	}
-	if (ah->bank6Temp != NULL) {
-		kfree(ah->bank6Temp);
-		ah->bank6Temp = NULL;
-	}
-}
-
-bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
-{
-	if (!AR_SREV_9280_10_OR_LATER(ah)) {
-		ah->analogBank0Data =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank0.ia_rows), GFP_KERNEL);
-		ah->analogBank1Data =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank1.ia_rows), GFP_KERNEL);
-		ah->analogBank2Data =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank2.ia_rows), GFP_KERNEL);
-		ah->analogBank3Data =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank3.ia_rows), GFP_KERNEL);
-		ah->analogBank6Data =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank6.ia_rows), GFP_KERNEL);
-		ah->analogBank6TPCData =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank6TPC.ia_rows), GFP_KERNEL);
-		ah->analogBank7Data =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank7.ia_rows), GFP_KERNEL);
-
-		if (ah->analogBank0Data == NULL
-		    || ah->analogBank1Data == NULL
-		    || ah->analogBank2Data == NULL
-		    || ah->analogBank3Data == NULL
-		    || ah->analogBank6Data == NULL
-		    || ah->analogBank6TPCData == NULL
-		    || ah->analogBank7Data == NULL) {
-			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"Cannot allocate RF banks\n");
-			*status = -ENOMEM;
-			return false;
-		}
-
-		ah->addac5416_21 =
-		    kzalloc((sizeof(u32) *
-			     ah->iniAddac.ia_rows *
-			     ah->iniAddac.ia_columns), GFP_KERNEL);
-		if (ah->addac5416_21 == NULL) {
-			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"Cannot allocate addac5416_21\n");
-			*status = -ENOMEM;
-			return false;
-		}
-
-		ah->bank6Temp =
-		    kzalloc((sizeof(u32) *
-			     ah->iniBank6.ia_rows), GFP_KERNEL);
-		if (ah->bank6Temp == NULL) {
-			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"Cannot allocate bank6Temp\n");
-			*status = -ENOMEM;
-			return false;
-		}
-	}
-
-	return true;
-}
-
-void
-ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	int i, regWrites = 0;
-	u32 bank6SelMask;
-	u32 *bank6Temp = ah->bank6Temp;
-
-	switch (ah->diversity_control) {
-	case ATH9K_ANT_FIXED_A:
-		bank6SelMask =
-		    (ah->
-		     antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 :
-		    REDUCE_CHAIN_1;
-		break;
-	case ATH9K_ANT_FIXED_B:
-		bank6SelMask =
-		    (ah->
-		     antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 :
-		    REDUCE_CHAIN_0;
-		break;
-	case ATH9K_ANT_VARIABLE:
-		return;
-		break;
-	default:
-		return;
-		break;
-	}
-
-	for (i = 0; i < ah->iniBank6.ia_rows; i++)
-		bank6Temp[i] = ah->analogBank6Data[i];
-
-	REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask);
-
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0);
-	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0);
-
-	REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites);
-
-	REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053);
-#ifdef ALTER_SWITCH
-	REG_WRITE(ah, PHY_SWITCH_CHAIN_0,
-		  (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38)
-		  | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38));
-#endif
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/phy.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/phy.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/phy.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/phy.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,579 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef PHY_H
-#define PHY_H
-
-bool ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
-				 struct ath9k_channel
-				 *chan);
-bool ath9k_hw_set_channel(struct ath_hw *ah,
-			  struct ath9k_channel *chan);
-void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex,
-			 u32 freqIndex, int regWrites);
-bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
-			  struct ath9k_channel *chan,
-			  u16 modesIndex);
-void ath9k_hw_decrease_chain_power(struct ath_hw *ah,
-				   struct ath9k_channel *chan);
-bool ath9k_hw_init_rf(struct ath_hw *ah,
-		      int *status);
-
-#define AR_PHY_BASE     0x9800
-#define AR_PHY(_n)      (AR_PHY_BASE + ((_n)<<2))
-
-#define AR_PHY_TEST             0x9800
-#define PHY_AGC_CLR             0x10000000
-#define RFSILENT_BB             0x00002000
-
-#define AR_PHY_TURBO                0x9804
-#define AR_PHY_FC_TURBO_MODE        0x00000001
-#define AR_PHY_FC_TURBO_SHORT       0x00000002
-#define AR_PHY_FC_DYN2040_EN        0x00000004
-#define AR_PHY_FC_DYN2040_PRI_ONLY  0x00000008
-#define AR_PHY_FC_DYN2040_PRI_CH    0x00000010
-#define AR_PHY_FC_DYN2040_EXT_CH    0x00000020
-#define AR_PHY_FC_HT_EN             0x00000040
-#define AR_PHY_FC_SHORT_GI_40       0x00000080
-#define AR_PHY_FC_WALSH             0x00000100
-#define AR_PHY_FC_SINGLE_HT_LTF1    0x00000200
-#define AR_PHY_FC_ENABLE_DAC_FIFO   0x00000800
-
-#define AR_PHY_TEST2 		    0x9808
-
-#define AR_PHY_TIMING2           0x9810
-#define AR_PHY_TIMING3           0x9814
-#define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000
-#define AR_PHY_TIMING3_DSC_MAN_S 17
-#define AR_PHY_TIMING3_DSC_EXP   0x0001E000
-#define AR_PHY_TIMING3_DSC_EXP_S 13
-
-#define AR_PHY_CHIP_ID            0x9818
-#define AR_PHY_CHIP_ID_REV_0      0x80
-#define AR_PHY_CHIP_ID_REV_1      0x81
-#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
-
-#define AR_PHY_ACTIVE       0x981C
-#define AR_PHY_ACTIVE_EN    0x00000001
-#define AR_PHY_ACTIVE_DIS   0x00000000
-
-#define AR_PHY_RF_CTL2             0x9824
-#define AR_PHY_TX_END_DATA_START   0x000000FF
-#define AR_PHY_TX_END_DATA_START_S 0
-#define AR_PHY_TX_END_PA_ON        0x0000FF00
-#define AR_PHY_TX_END_PA_ON_S      8
-
-#define AR_PHY_RF_CTL3                  0x9828
-#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000
-#define AR_PHY_TX_END_TO_A2_RX_ON_S     16
-
-#define AR_PHY_ADC_CTL                  0x982C
-#define AR_PHY_ADC_CTL_OFF_INBUFGAIN    0x00000003
-#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S  0
-#define AR_PHY_ADC_CTL_OFF_PWDDAC       0x00002000
-#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP   0x00004000
-#define AR_PHY_ADC_CTL_OFF_PWDADC       0x00008000
-#define AR_PHY_ADC_CTL_ON_INBUFGAIN     0x00030000
-#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S   16
-
-#define AR_PHY_ADC_SERIAL_CTL       0x9830
-#define AR_PHY_SEL_INTERNAL_ADDAC   0x00000000
-#define AR_PHY_SEL_EXTERNAL_RADIO   0x00000001
-
-#define AR_PHY_RF_CTL4                    0x9834
-#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF    0xFF000000
-#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S  24
-#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF    0x00FF0000
-#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S  16
-#define AR_PHY_RF_CTL4_FRAME_XPAB_ON      0x0000FF00
-#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S    8
-#define AR_PHY_RF_CTL4_FRAME_XPAA_ON      0x000000FF
-#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S    0
-
-#define AR_PHY_TSTDAC_CONST               0x983c
-
-#define AR_PHY_SETTLING          0x9844
-#define AR_PHY_SETTLING_SWITCH   0x00003F80
-#define AR_PHY_SETTLING_SWITCH_S 7
-
-#define AR_PHY_RXGAIN                   0x9848
-#define AR_PHY_RXGAIN_TXRX_ATTEN        0x0003F000
-#define AR_PHY_RXGAIN_TXRX_ATTEN_S      12
-#define AR_PHY_RXGAIN_TXRX_RF_MAX       0x007C0000
-#define AR_PHY_RXGAIN_TXRX_RF_MAX_S     18
-#define AR9280_PHY_RXGAIN_TXRX_ATTEN    0x00003F80
-#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S  7
-#define AR9280_PHY_RXGAIN_TXRX_MARGIN   0x001FC000
-#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
-
-#define AR_PHY_DESIRED_SZ           0x9850
-#define AR_PHY_DESIRED_SZ_ADC       0x000000FF
-#define AR_PHY_DESIRED_SZ_ADC_S     0
-#define AR_PHY_DESIRED_SZ_PGA       0x0000FF00
-#define AR_PHY_DESIRED_SZ_PGA_S     8
-#define AR_PHY_DESIRED_SZ_TOT_DES   0x0FF00000
-#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
-
-#define AR_PHY_FIND_SIG           0x9858
-#define AR_PHY_FIND_SIG_FIRSTEP   0x0003F000
-#define AR_PHY_FIND_SIG_FIRSTEP_S 12
-#define AR_PHY_FIND_SIG_FIRPWR    0x03FC0000
-#define AR_PHY_FIND_SIG_FIRPWR_S  18
-
-#define AR_PHY_AGC_CTL1                  0x985C
-#define AR_PHY_AGC_CTL1_COARSE_LOW       0x00007F80
-#define AR_PHY_AGC_CTL1_COARSE_LOW_S     7
-#define AR_PHY_AGC_CTL1_COARSE_HIGH      0x003F8000
-#define AR_PHY_AGC_CTL1_COARSE_HIGH_S    15
-
-#define AR_PHY_AGC_CONTROL               0x9860
-#define AR_PHY_AGC_CONTROL_CAL           0x00000001
-#define AR_PHY_AGC_CONTROL_NF            0x00000002
-#define AR_PHY_AGC_CONTROL_ENABLE_NF     0x00008000
-#define AR_PHY_AGC_CONTROL_FLTR_CAL      0x00010000
-#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF  0x00020000
-
-#define AR_PHY_CCA                  0x9864
-#define AR_PHY_MINCCA_PWR           0x0FF80000
-#define AR_PHY_MINCCA_PWR_S         19
-#define AR_PHY_CCA_THRESH62         0x0007F000
-#define AR_PHY_CCA_THRESH62_S       12
-#define AR9280_PHY_MINCCA_PWR       0x1FF00000
-#define AR9280_PHY_MINCCA_PWR_S     20
-#define AR9280_PHY_CCA_THRESH62     0x000FF000
-#define AR9280_PHY_CCA_THRESH62_S   12
-
-#define AR_PHY_SFCORR_LOW                    0x986C
-#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW  0x00000001
-#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW    0x00003F00
-#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S  8
-#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW      0x001FC000
-#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S    14
-#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW      0x0FE00000
-#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S    21
-
-#define AR_PHY_SFCORR                0x9868
-#define AR_PHY_SFCORR_M2COUNT_THR    0x0000001F
-#define AR_PHY_SFCORR_M2COUNT_THR_S  0
-#define AR_PHY_SFCORR_M1_THRESH      0x00FE0000
-#define AR_PHY_SFCORR_M1_THRESH_S    17
-#define AR_PHY_SFCORR_M2_THRESH      0x7F000000
-#define AR_PHY_SFCORR_M2_THRESH_S    24
-
-#define AR_PHY_SLEEP_CTR_CONTROL    0x9870
-#define AR_PHY_SLEEP_CTR_LIMIT      0x9874
-#define AR_PHY_SYNTH_CONTROL        0x9874
-#define AR_PHY_SLEEP_SCAL           0x9878
-
-#define AR_PHY_PLL_CTL          0x987c
-#define AR_PHY_PLL_CTL_40       0xaa
-#define AR_PHY_PLL_CTL_40_5413  0x04
-#define AR_PHY_PLL_CTL_44       0xab
-#define AR_PHY_PLL_CTL_44_2133  0xeb
-#define AR_PHY_PLL_CTL_40_2133  0xea
-
-#define AR_PHY_RX_DELAY           0x9914
-#define AR_PHY_SEARCH_START_DELAY 0x9918
-#define AR_PHY_RX_DELAY_DELAY     0x00003FFF
-
-#define AR_PHY_TIMING_CTRL4(_i)     (0x9920 + ((_i) << 12))
-#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
-#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0
-#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
-#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5
-#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE   0x800
-#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
-#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S   12
-#define AR_PHY_TIMING_CTRL4_DO_CAL    0x10000
-
-#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI	0x80000000
-#define	AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER	0x40000000
-#define	AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK	0x20000000
-#define	AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK	0x10000000
-
-#define AR_PHY_TIMING5               0x9924
-#define AR_PHY_TIMING5_CYCPWR_THR1   0x000000FE
-#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
-
-#define AR_PHY_POWER_TX_RATE1               0x9934
-#define AR_PHY_POWER_TX_RATE2               0x9938
-#define AR_PHY_POWER_TX_RATE_MAX            0x993c
-#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
-
-#define AR_PHY_FRAME_CTL            0x9944
-#define AR_PHY_FRAME_CTL_TX_CLIP    0x00000038
-#define AR_PHY_FRAME_CTL_TX_CLIP_S  3
-
-#define AR_PHY_TXPWRADJ                   0x994C
-#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA    0x00000FC0
-#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S  6
-#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX   0x00FC0000
-#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
-
-#define AR_PHY_RADAR_EXT      0x9940
-#define AR_PHY_RADAR_EXT_ENA  0x00004000
-
-#define AR_PHY_RADAR_0          0x9954
-#define AR_PHY_RADAR_0_ENA      0x00000001
-#define AR_PHY_RADAR_0_FFT_ENA  0x80000000
-#define AR_PHY_RADAR_0_INBAND   0x0000003e
-#define AR_PHY_RADAR_0_INBAND_S 1
-#define AR_PHY_RADAR_0_PRSSI    0x00000FC0
-#define AR_PHY_RADAR_0_PRSSI_S  6
-#define AR_PHY_RADAR_0_HEIGHT   0x0003F000
-#define AR_PHY_RADAR_0_HEIGHT_S 12
-#define AR_PHY_RADAR_0_RRSSI    0x00FC0000
-#define AR_PHY_RADAR_0_RRSSI_S  18
-#define AR_PHY_RADAR_0_FIRPWR   0x7F000000
-#define AR_PHY_RADAR_0_FIRPWR_S 24
-
-#define AR_PHY_RADAR_1                  0x9958
-#define AR_PHY_RADAR_1_RELPWR_ENA       0x00800000
-#define AR_PHY_RADAR_1_USE_FIR128       0x00400000
-#define AR_PHY_RADAR_1_RELPWR_THRESH    0x003F0000
-#define AR_PHY_RADAR_1_RELPWR_THRESH_S  16
-#define AR_PHY_RADAR_1_BLOCK_CHECK      0x00008000
-#define AR_PHY_RADAR_1_MAX_RRSSI        0x00004000
-#define AR_PHY_RADAR_1_RELSTEP_CHECK    0x00002000
-#define AR_PHY_RADAR_1_RELSTEP_THRESH   0x00001F00
-#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
-#define AR_PHY_RADAR_1_MAXLEN           0x000000FF
-#define AR_PHY_RADAR_1_MAXLEN_S         0
-
-#define AR_PHY_SWITCH_CHAIN_0     0x9960
-#define AR_PHY_SWITCH_COM         0x9964
-
-#define AR_PHY_SIGMA_DELTA            0x996C
-#define AR_PHY_SIGMA_DELTA_ADC_SEL    0x00000003
-#define AR_PHY_SIGMA_DELTA_ADC_SEL_S  0
-#define AR_PHY_SIGMA_DELTA_FILT2      0x000000F8
-#define AR_PHY_SIGMA_DELTA_FILT2_S    3
-#define AR_PHY_SIGMA_DELTA_FILT1      0x00001F00
-#define AR_PHY_SIGMA_DELTA_FILT1_S    8
-#define AR_PHY_SIGMA_DELTA_ADC_CLIP   0x01FFE000
-#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
-
-#define AR_PHY_RESTART          0x9970
-#define AR_PHY_RESTART_DIV_GC   0x001C0000
-#define AR_PHY_RESTART_DIV_GC_S 18
-
-#define AR_PHY_RFBUS_REQ        0x997C
-#define AR_PHY_RFBUS_REQ_EN     0x00000001
-
-#define	AR_PHY_TIMING7		        0x9980
-#define	AR_PHY_TIMING8		        0x9984
-#define	AR_PHY_TIMING8_PILOT_MASK_2	0x000FFFFF
-#define	AR_PHY_TIMING8_PILOT_MASK_2_S	0
-
-#define	AR_PHY_BIN_MASK2_1	0x9988
-#define	AR_PHY_BIN_MASK2_2	0x998c
-#define	AR_PHY_BIN_MASK2_3	0x9990
-#define	AR_PHY_BIN_MASK2_4	0x9994
-
-#define	AR_PHY_BIN_MASK_1	0x9900
-#define	AR_PHY_BIN_MASK_2	0x9904
-#define	AR_PHY_BIN_MASK_3	0x9908
-
-#define	AR_PHY_MASK_CTL		0x990c
-
-#define	AR_PHY_BIN_MASK2_4_MASK_4	0x00003FFF
-#define	AR_PHY_BIN_MASK2_4_MASK_4_S	0
-
-#define	AR_PHY_TIMING9		        0x9998
-#define	AR_PHY_TIMING10		        0x999c
-#define	AR_PHY_TIMING10_PILOT_MASK_2	0x000FFFFF
-#define	AR_PHY_TIMING10_PILOT_MASK_2_S	0
-
-#define	AR_PHY_TIMING11			        0x99a0
-#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE	0x000FFFFF
-#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE_S	0
-#define	AR_PHY_TIMING11_SPUR_FREQ_SD		0x3FF00000
-#define	AR_PHY_TIMING11_SPUR_FREQ_SD_S		20
-#define AR_PHY_TIMING11_USE_SPUR_IN_AGC		0x40000000
-#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR	0x80000000
-
-#define AR_PHY_RX_CHAINMASK     0x99a4
-#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
-#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
-#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
-#define AR_PHY_MULTICHAIN_GAIN_CTL  0x99ac
-
-#define AR_PHY_EXT_CCA0             0x99b8
-#define AR_PHY_EXT_CCA0_THRESH62    0x000000FF
-#define AR_PHY_EXT_CCA0_THRESH62_S  0
-
-#define AR_PHY_EXT_CCA                  0x99bc
-#define AR_PHY_EXT_CCA_CYCPWR_THR1      0x0000FE00
-#define AR_PHY_EXT_CCA_CYCPWR_THR1_S    9
-#define AR_PHY_EXT_CCA_THRESH62         0x007F0000
-#define AR_PHY_EXT_CCA_THRESH62_S       16
-#define AR_PHY_EXT_MINCCA_PWR           0xFF800000
-#define AR_PHY_EXT_MINCCA_PWR_S         23
-#define AR9280_PHY_EXT_MINCCA_PWR       0x01FF0000
-#define AR9280_PHY_EXT_MINCCA_PWR_S     16
-
-#define AR_PHY_SFCORR_EXT                 0x99c0
-#define AR_PHY_SFCORR_EXT_M1_THRESH       0x0000007F
-#define AR_PHY_SFCORR_EXT_M1_THRESH_S     0
-#define AR_PHY_SFCORR_EXT_M2_THRESH       0x00003F80
-#define AR_PHY_SFCORR_EXT_M2_THRESH_S     7
-#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW   0x001FC000
-#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
-#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW   0x0FE00000
-#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
-#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S   28
-
-#define AR_PHY_HALFGI           0x99D0
-#define AR_PHY_HALFGI_DSC_MAN   0x0007FFF0
-#define AR_PHY_HALFGI_DSC_MAN_S 4
-#define AR_PHY_HALFGI_DSC_EXP   0x0000000F
-#define AR_PHY_HALFGI_DSC_EXP_S 0
-
-#define AR_PHY_CHAN_INFO_MEMORY               0x99DC
-#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK  0x0001
-
-#define AR_PHY_HEAVY_CLIP_ENABLE         0x99E0
-
-#define AR_PHY_M_SLEEP      0x99f0
-#define AR_PHY_REFCLKDLY    0x99f4
-#define AR_PHY_REFCLKPD     0x99f8
-
-#define AR_PHY_CALMODE      0x99f0
-
-#define AR_PHY_CALMODE_IQ           0x00000000
-#define AR_PHY_CALMODE_ADC_GAIN     0x00000001
-#define AR_PHY_CALMODE_ADC_DC_PER   0x00000002
-#define AR_PHY_CALMODE_ADC_DC_INIT  0x00000003
-
-#define AR_PHY_CAL_MEAS_0(_i)     (0x9c10 + ((_i) << 12))
-#define AR_PHY_CAL_MEAS_1(_i)     (0x9c14 + ((_i) << 12))
-#define AR_PHY_CAL_MEAS_2(_i)     (0x9c18 + ((_i) << 12))
-#define AR_PHY_CAL_MEAS_3(_i)     (0x9c1c + ((_i) << 12))
-
-#define AR_PHY_CURRENT_RSSI 0x9c1c
-#define AR9280_PHY_CURRENT_RSSI 0x9c3c
-
-#define AR_PHY_RFBUS_GRANT       0x9C20
-#define AR_PHY_RFBUS_GRANT_EN    0x00000001
-
-#define AR_PHY_CHAN_INFO_GAIN_DIFF             0x9CF4
-#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
-
-#define AR_PHY_CHAN_INFO_GAIN          0x9CFC
-
-#define AR_PHY_MODE         0xA200
-#define AR_PHY_MODE_AR2133  0x08
-#define AR_PHY_MODE_AR5111  0x00
-#define AR_PHY_MODE_AR5112  0x08
-#define AR_PHY_MODE_DYNAMIC 0x04
-#define AR_PHY_MODE_RF2GHZ  0x02
-#define AR_PHY_MODE_RF5GHZ  0x00
-#define AR_PHY_MODE_CCK     0x01
-#define AR_PHY_MODE_OFDM    0x00
-#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
-
-#define AR_PHY_CCK_TX_CTRL       0xA204
-#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
-#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK         0x0000000C
-#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S       2
-
-#define AR_PHY_CCK_DETECT                           0xA208
-#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F
-#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0
-/* [12:6] settling time for antenna switch */
-#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0
-#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S         6
-#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV    0x2000
-
-#define AR_PHY_GAIN_2GHZ                0xA20C
-#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN    0x00FC0000
-#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S  18
-#define AR_PHY_GAIN_2GHZ_BSW_MARGIN     0x00003C00
-#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S   10
-#define AR_PHY_GAIN_2GHZ_BSW_ATTEN      0x0000001F
-#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S    0
-
-#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN     0x003E0000
-#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S   17
-#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN     0x0001F000
-#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S   12
-#define AR_PHY_GAIN_2GHZ_XATTEN2_DB         0x00000FC0
-#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S       6
-#define AR_PHY_GAIN_2GHZ_XATTEN1_DB         0x0000003F
-#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S       0
-
-#define AR_PHY_CCK_RXCTRL4  0xA21C
-#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT   0x01F80000
-#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
-
-#define AR_PHY_DAG_CTRLCCK  0xA228
-#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200
-#define AR_PHY_DAG_CTRLCCK_RSSI_THR     0x0001FC00
-#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10
-
-#define AR_PHY_FORCE_CLKEN_CCK              0xA22C
-#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX      0x00000040
-
-#define AR_PHY_POWER_TX_RATE3   0xA234
-#define AR_PHY_POWER_TX_RATE4   0xA238
-
-#define AR_PHY_SCRM_SEQ_XR       0xA23C
-#define AR_PHY_HEADER_DETECT_XR  0xA240
-#define AR_PHY_CHIRP_DETECTED_XR 0xA244
-#define AR_PHY_BLUETOOTH         0xA254
-
-#define AR_PHY_TPCRG1   0xA258
-#define AR_PHY_TPCRG1_NUM_PD_GAIN   0x0000c000
-#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
-
-#define AR_PHY_TPCRG1_PD_GAIN_1    0x00030000
-#define AR_PHY_TPCRG1_PD_GAIN_1_S  16
-#define AR_PHY_TPCRG1_PD_GAIN_2    0x000C0000
-#define AR_PHY_TPCRG1_PD_GAIN_2_S  18
-#define AR_PHY_TPCRG1_PD_GAIN_3    0x00300000
-#define AR_PHY_TPCRG1_PD_GAIN_3_S  20
-
-#define AR_PHY_TPCRG1_PD_CAL_ENABLE   0x00400000
-#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
-
-#define AR_PHY_TX_PWRCTRL4       0xa264
-#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID     0x00000001
-#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S   0
-#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT       0x000001FE
-#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S     1
-
-#define AR_PHY_TX_PWRCTRL6_0     0xa270
-#define AR_PHY_TX_PWRCTRL6_1     0xb270
-#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE     0x03000000
-#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S   24
-
-#define AR_PHY_TX_PWRCTRL7       0xa274
-#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000
-#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19
-
-#define AR_PHY_TX_PWRCTRL9       0xa27C
-#define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00
-#define AR_PHY_TX_DESIRED_SCALE_CCK_S      10
-
-#define AR_PHY_TX_GAIN_TBL1      0xa300
-#define AR_PHY_TX_GAIN                     0x0007F000
-#define AR_PHY_TX_GAIN_S                   12
-
-#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
-#define AR_PHY_MASK2_M_31_45     0xa3a4
-#define AR_PHY_MASK2_M_16_30     0xa3a8
-#define AR_PHY_MASK2_M_00_15     0xa3ac
-#define AR_PHY_MASK2_P_15_01     0xa3b8
-#define AR_PHY_MASK2_P_30_16     0xa3bc
-#define AR_PHY_MASK2_P_45_31     0xa3c0
-#define AR_PHY_MASK2_P_61_45     0xa3c4
-#define AR_PHY_SPUR_REG          0x994c
-
-#define AR_PHY_SPUR_REG_MASK_RATE_CNTL       (0xFF << 18)
-#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S     18
-
-#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM      0x20000
-#define AR_PHY_SPUR_REG_MASK_RATE_SELECT     (0xFF << 9)
-#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S   9
-#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
-#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH     0x7F
-#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S   0
-
-#define AR_PHY_PILOT_MASK_01_30   0xa3b0
-#define AR_PHY_PILOT_MASK_31_60   0xa3b4
-
-#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
-#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
-
-#define AR_PHY_ANALOG_SWAP      0xa268
-#define AR_PHY_SWAP_ALT_CHAIN   0x00000040
-
-#define AR_PHY_TPCRG5   0xA26C
-#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP       0x0000000F
-#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S     0
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1    0x000003F0
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S  4
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2    0x0000FC00
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S  10
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003F0000
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0FC00000
-#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22
-
-/* Carrier leak calibration control, do it after AGC calibration */
-#define AR_PHY_CL_CAL_CTL       0xA358
-#define AR_PHY_CL_CAL_ENABLE    0x00000002
-#define AR_PHY_PARALLEL_CAL_ENABLE    0x00000001
-
-#define AR_PHY_POWER_TX_RATE5   0xA38C
-#define AR_PHY_POWER_TX_RATE6   0xA390
-
-#define AR_PHY_CAL_CHAINMASK    0xA39C
-
-#define AR_PHY_POWER_TX_SUB     0xA3C8
-#define AR_PHY_POWER_TX_RATE7   0xA3CC
-#define AR_PHY_POWER_TX_RATE8   0xA3D0
-#define AR_PHY_POWER_TX_RATE9   0xA3D4
-
-#define AR_PHY_XPA_CFG  	0xA3D8
-#define AR_PHY_FORCE_XPA_CFG	0x000000001
-#define AR_PHY_FORCE_XPA_CFG_S	0
-
-#define AR_PHY_CH1_CCA          0xa864
-#define AR_PHY_CH1_MINCCA_PWR   0x0FF80000
-#define AR_PHY_CH1_MINCCA_PWR_S 19
-#define AR9280_PHY_CH1_MINCCA_PWR   0x1FF00000
-#define AR9280_PHY_CH1_MINCCA_PWR_S 20
-
-#define AR_PHY_CH2_CCA          0xb864
-#define AR_PHY_CH2_MINCCA_PWR   0x0FF80000
-#define AR_PHY_CH2_MINCCA_PWR_S 19
-
-#define AR_PHY_CH1_EXT_CCA          0xa9bc
-#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000
-#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
-#define AR9280_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000
-#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
-
-#define AR_PHY_CH2_EXT_CCA          0xb9bc
-#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
-#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
-
-#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do {               \
-		int r;							\
-		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\
-			REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, \
-				"RF 0x%x V 0x%x\n", \
-				INI_RA((iniarray), r, 0), (regData)[r]); \
-			DO_DELAY(regWr);				\
-		}							\
-	} while (0)
-
-#define ATH9K_IS_MIC_ENABLED(ah)					\
-	((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
-
-#define ANTSWAP_AB 0x0001
-#define REDUCE_CHAIN_0 0x00000050
-#define REDUCE_CHAIN_1 0x00000051
-
-#define RF_BANK_SETUP(_bank, _iniarray, _col) do {			\
-		int i;							\
-		for (i = 0; i < (_iniarray)->ia_rows; i++)		\
-			(_bank)[i] = INI_RA((_iniarray), i, _col);;	\
-	} while (0)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/rc.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/rc.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/rc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/rc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1756 +0,0 @@
-/*
- * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2004-2009 Atheros Communications, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-static struct ath_rate_table ar5416_11na_ratetable = {
-	42,
-	{
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 0x0b, 0x00, 12,
-			0, 2, 1, 0, 0, 0, 0, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800,  0x0f, 0x00, 18,
-			0, 3, 1, 1, 1, 1, 1, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 0x0a, 0x00, 24,
-			2, 4, 2, 2, 2, 2, 2, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 0x0e, 0x00, 36,
-			2, 6,  2, 3, 3, 3, 3, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 0x09, 0x00, 48,
-			4, 10, 3, 4, 4, 4, 4, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 0x0d, 0x00, 72,
-			4, 14, 3, 5, 5, 5, 5, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 0x08, 0x00, 96,
-			4, 20, 3, 6, 6, 6, 6, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 0x0c, 0x00, 108,
-			4, 23, 3, 7, 7, 7, 7, 0 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
-			6400, 0x80, 0x00, 0,
-			0, 2, 3, 8, 24, 8, 24, 3216 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
-			12700, 0x81, 0x00, 1,
-			2, 4, 3, 9, 25, 9, 25, 6434 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
-			18800, 0x82, 0x00, 2,
-			2, 6, 3, 10, 26, 10, 26, 9650 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
-			25000, 0x83, 0x00, 3,
-			4, 10, 3, 11, 27, 11, 27, 12868 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
-			36700, 0x84, 0x00, 4,
-			4, 14, 3, 12, 28, 12, 28, 19304 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
-			48100, 0x85, 0x00, 5,
-			4, 20, 3, 13, 29, 13, 29, 25740 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
-			53500, 0x86, 0x00, 6,
-			4, 23, 3, 14, 30, 14, 30,  28956 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
-			59000, 0x87, 0x00, 7,
-			4, 25, 3, 15, 31, 15, 32, 32180 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
-			12700, 0x88, 0x00,
-			8, 0, 2, 3, 16, 33, 16, 33, 6430 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
-			24800, 0x89, 0x00, 9,
-			2, 4, 3, 17, 34, 17, 34, 12860 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
-			36600, 0x8a, 0x00, 10,
-			2, 6, 3, 18, 35, 18, 35, 19300 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
-			48100, 0x8b, 0x00, 11,
-			4, 10, 3, 19, 36, 19, 36, 25736 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
-			69500, 0x8c, 0x00, 12,
-			4, 14, 3, 20, 37, 20, 37, 38600 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
-			89500, 0x8d, 0x00, 13,
-			4, 20, 3, 21, 38, 21, 38, 51472 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
-			98900, 0x8e, 0x00, 14,
-			4, 23, 3, 22, 39, 22, 39, 57890 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
-			108300, 0x8f, 0x00, 15,
-			4, 25, 3, 23, 40, 23, 41, 64320 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
-			13200, 0x80, 0x00, 0,
-			0, 2, 3, 8, 24, 24, 24, 6684 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
-			25900, 0x81, 0x00, 1,
-			2, 4, 3, 9, 25, 25, 25, 13368 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
-			38600, 0x82, 0x00, 2,
-			2, 6, 3, 10, 26, 26, 26, 20052 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
-			49800, 0x83, 0x00, 3,
-			4, 10, 3, 11, 27, 27, 27, 26738 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
-			72200, 0x84, 0x00, 4,
-			4, 14, 3, 12, 28, 28, 28, 40104 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
-			92900, 0x85, 0x00, 5,
-			4, 20, 3, 13, 29, 29, 29, 53476 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
-			102700, 0x86, 0x00, 6,
-			4, 23, 3, 14, 30, 30, 30, 60156 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
-			112000, 0x87, 0x00, 7,
-			4, 25, 3, 15, 31, 32, 32, 66840 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
-			122000, 0x87, 0x00, 7,
-			4, 25, 3, 15, 31, 32, 32, 74200 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
-			25800, 0x88, 0x00, 8,
-			0, 2, 3, 16, 33, 33, 33, 13360 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
-			49800, 0x89, 0x00, 9,
-			2, 4, 3, 17, 34, 34, 34, 26720 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
-			71900, 0x8a, 0x00, 10,
-			2, 6, 3, 18, 35, 35, 35, 40080 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
-			92500, 0x8b, 0x00, 11,
-			4, 10, 3, 19, 36, 36, 36, 53440 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
-			130300, 0x8c, 0x00, 12,
-			4, 14, 3, 20, 37, 37, 37, 80160 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
-			162800, 0x8d, 0x00, 13,
-			4, 20, 3, 21, 38, 38, 38, 106880 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
-			178200, 0x8e, 0x00, 14,
-			4, 23, 3, 22, 39, 39, 39, 120240 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
-			192100, 0x8f, 0x00, 15,
-			4, 25, 3, 23, 40, 41, 41, 133600 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
-			207000, 0x8f, 0x00, 15,
-			4, 25, 3, 23, 40, 41, 41, 148400 },
-	},
-	50,  /* probe interval */
-	50,  /* rssi reduce interval */
-	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
-};
-
-/* 4ms frame limit not used for NG mode.  The values filled
- * for HT are the 64K max aggregate limit */
-
-static struct ath_rate_table ar5416_11ng_ratetable = {
-	46,
-	{
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
-			900, 0x1b, 0x00, 2,
-			0, 0, 1, 0, 0, 0, 0, 0 },
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
-			1900, 0x1a, 0x04, 4,
-			1, 1, 1, 1, 1, 1, 1, 0 },
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
-			4900, 0x19, 0x04, 11,
-			2, 2, 2, 2, 2, 2, 2, 0 },
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
-			8100, 0x18, 0x04, 22,
-			3, 3, 2, 3, 3, 3, 3, 0 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 0x0b, 0x00, 12,
-			4, 2, 1, 4, 4, 4, 4, 0 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800, 0x0f, 0x00, 18,
-			4, 3, 1, 5, 5, 5, 5, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10100, 0x0a, 0x00, 24,
-			6, 4, 1, 6, 6, 6, 6, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			14100,  0x0e, 0x00, 36,
-			6, 6, 2, 7, 7, 7, 7, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17700, 0x09, 0x00, 48,
-			8, 10, 3, 8, 8, 8, 8, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23700, 0x0d, 0x00, 72,
-			8, 14, 3, 9, 9, 9, 9, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 0x08, 0x00, 96,
-			8, 20, 3, 10, 10, 10, 10, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			30900, 0x0c, 0x00, 108,
-			8, 23, 3, 11, 11, 11, 11, 0 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
-			6400, 0x80, 0x00, 0,
-			4, 2, 3, 12, 28, 12, 28, 3216 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
-			12700, 0x81, 0x00, 1,
-			6, 4, 3, 13, 29, 13, 29, 6434 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
-			18800, 0x82, 0x00, 2,
-			6, 6, 3, 14, 30, 14, 30, 9650 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
-			25000, 0x83, 0x00, 3,
-			8, 10, 3, 15, 31, 15, 31, 12868 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
-			36700, 0x84, 0x00, 4,
-			8, 14, 3, 16, 32, 16, 32, 19304 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
-			48100, 0x85, 0x00, 5,
-			8, 20, 3, 17, 33, 17, 33, 25740 },
-		{ INVALID,  VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
-			53500, 0x86, 0x00, 6,
-			8, 23, 3, 18, 34, 18, 34, 28956 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
-			59000, 0x87, 0x00, 7,
-			8, 25, 3, 19, 35, 19, 36, 32180 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
-			12700, 0x88, 0x00, 8,
-			4, 2, 3, 20, 37, 20, 37, 6430 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
-			24800, 0x89, 0x00, 9,
-			6, 4, 3, 21, 38, 21, 38, 12860 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
-			36600, 0x8a, 0x00, 10,
-			6, 6, 3, 22, 39, 22, 39, 19300 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
-			48100, 0x8b, 0x00, 11,
-			8, 10, 3, 23, 40, 23, 40, 25736 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
-			69500, 0x8c, 0x00, 12,
-			8, 14, 3, 24, 41, 24, 41, 38600 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
-			89500, 0x8d, 0x00, 13,
-			8, 20, 3, 25, 42, 25, 42, 51472 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
-			98900, 0x8e, 0x00, 14,
-			8, 23, 3, 26, 43, 26, 44, 57890 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
-			108300, 0x8f, 0x00, 15,
-			8, 25, 3, 27, 44, 27, 45, 64320 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
-			13200, 0x80, 0x00, 0,
-			8, 2, 3, 12, 28, 28, 28, 6684 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
-			25900, 0x81, 0x00, 1,
-			8, 4, 3, 13, 29, 29, 29, 13368 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
-			38600, 0x82, 0x00, 2,
-			8, 6, 3, 14, 30, 30, 30, 20052 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
-			49800, 0x83, 0x00, 3,
-			8, 10, 3, 15, 31, 31, 31, 26738 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
-			72200, 0x84, 0x00, 4,
-			8, 14, 3, 16, 32, 32, 32, 40104 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
-			92900, 0x85, 0x00, 5,
-			8, 20, 3, 17, 33, 33, 33, 53476 },
-		{ INVALID,  VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
-			102700, 0x86, 0x00, 6,
-			8, 23, 3, 18, 34, 34, 34, 60156 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
-			112000, 0x87, 0x00, 7,
-			8, 23, 3, 19, 35, 36, 36, 66840 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
-			122000, 0x87, 0x00, 7,
-			8, 25, 3, 19, 35, 36, 36, 74200 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
-			25800, 0x88, 0x00, 8,
-			8, 2, 3, 20, 37, 37, 37, 13360 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
-			49800, 0x89, 0x00, 9,
-			8, 4, 3, 21, 38, 38, 38, 26720 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
-			71900, 0x8a, 0x00, 10,
-			8, 6, 3, 22, 39, 39, 39, 40080 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
-			92500, 0x8b, 0x00, 11,
-			8, 10, 3, 23, 40, 40, 40, 53440 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
-			130300, 0x8c, 0x00, 12,
-			8, 14, 3, 24, 41, 41, 41, 80160 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
-			162800, 0x8d, 0x00, 13,
-			8, 20, 3, 25, 42, 42, 42, 106880 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
-			178200, 0x8e, 0x00, 14,
-			8, 23, 3, 26, 43, 43, 43, 120240 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
-			192100, 0x8f, 0x00, 15,
-			8, 23, 3, 27, 44, 45, 45, 133600 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
-			207000, 0x8f, 0x00, 15,
-			8, 25, 3, 27, 44, 45, 45, 148400 },
-		},
-	50,  /* probe interval */
-	50,  /* rssi reduce interval */
-	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
-};
-
-static struct ath_rate_table ar5416_11a_ratetable = {
-	8,
-	{
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 0x0b, 0x00, (0x80|12),
-			0, 2, 1, 0, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800, 0x0f, 0x00, 18,
-			0, 3, 1, 1, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 0x0a, 0x00, (0x80|24),
-			2, 4, 2, 2, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 0x0e, 0x00, 36,
-			2, 6, 2, 3, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 0x09, 0x00, (0x80|48),
-			4, 10, 3, 4, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 0x0d, 0x00, 72,
-			4, 14, 3, 5, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 0x08, 0x00, 96,
-			4, 19, 3, 6, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 0x0c, 0x00, 108,
-			4, 23, 3, 7, 0 },
-	},
-	50,  /* probe interval */
-	50,  /* rssi reduce interval */
-	0,   /* Phy rates allowed initially */
-};
-
-static struct ath_rate_table ar5416_11g_ratetable = {
-	12,
-	{
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
-			900, 0x1b, 0x00, 2,
-			0, 0, 1, 0, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
-			1900, 0x1a, 0x04, 4,
-			1, 1, 1, 1, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
-			4900, 0x19, 0x04, 11,
-			2, 2, 2, 2, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
-			8100, 0x18, 0x04, 22,
-			3, 3, 2, 3, 0 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 0x0b, 0x00, 12,
-			4, 2, 1, 4, 0 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800, 0x0f, 0x00, 18,
-			4, 3, 1, 5, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 0x0a, 0x00, 24,
-			6, 4, 1, 6, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 0x0e, 0x00, 36,
-			6, 6, 2, 7, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 0x09, 0x00, 48,
-			8, 10, 3, 8, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 0x0d, 0x00, 72,
-			8, 14, 3, 9, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 0x08, 0x00, 96,
-			8, 19, 3, 10, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 0x0c, 0x00, 108,
-			8, 23, 3, 11, 0 },
-	},
-	50,  /* probe interval */
-	50,  /* rssi reduce interval */
-	0,   /* Phy rates allowed initially */
-};
-
-static struct ath_rate_table ar5416_11b_ratetable = {
-	4,
-	{
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
-			900, 0x1b,  0x00, (0x80|2),
-			0, 0, 1, 0, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
-			1800, 0x1a, 0x04, (0x80|4),
-			1, 1, 1, 1, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
-			4300, 0x19, 0x04, (0x80|11),
-			1, 2, 2, 2, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
-			7100, 0x18, 0x04, (0x80|22),
-			1, 4, 100, 3, 0 },
-	},
-	100, /* probe interval */
-	100, /* rssi reduce interval */
-	0,   /* Phy rates allowed initially */
-};
-
-static inline int8_t median(int8_t a, int8_t b, int8_t c)
-{
-	if (a >= b) {
-		if (b >= c)
-			return b;
-		else if (a > c)
-			return c;
-		else
-			return a;
-	} else {
-		if (a >= c)
-			return a;
-		else if (b >= c)
-			return c;
-		else
-			return b;
-	}
-}
-
-static void ath_rc_sort_validrates(struct ath_rate_table *rate_table,
-				   struct ath_rate_priv *ath_rc_priv)
-{
-	u8 i, j, idx, idx_next;
-
-	for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
-		for (j = 0; j <= i-1; j++) {
-			idx = ath_rc_priv->valid_rate_index[j];
-			idx_next = ath_rc_priv->valid_rate_index[j+1];
-
-			if (rate_table->info[idx].ratekbps >
-				rate_table->info[idx_next].ratekbps) {
-				ath_rc_priv->valid_rate_index[j] = idx_next;
-				ath_rc_priv->valid_rate_index[j+1] = idx;
-			}
-		}
-	}
-}
-
-static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
-{
-	u8 i;
-
-	for (i = 0; i < ath_rc_priv->rate_table_size; i++)
-		ath_rc_priv->valid_rate_index[i] = 0;
-}
-
-static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
-					   u8 index, int valid_tx_rate)
-{
-	ASSERT(index <= ath_rc_priv->rate_table_size);
-	ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
-}
-
-static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv,
-					u8 index)
-{
-	ASSERT(index <= ath_rc_priv->rate_table_size);
-	return ath_rc_priv->valid_rate_index[index];
-}
-
-static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
-					      struct ath_rate_priv *ath_rc_priv,
-					      u8 cur_valid_txrate,
-					      u8 *next_idx)
-{
-	u8 i;
-
-	for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
-		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
-			*next_idx = ath_rc_priv->valid_rate_index[i+1];
-			return 1;
-		}
-	}
-
-	/* No more valid rates */
-	*next_idx = 0;
-
-	return 0;
-}
-
-/* Return true only for single stream */
-
-static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
-{
-	if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
-		return 0;
-	if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
-		return 0;
-	if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
-		return 0;
-	if (!ignore_cw && WLAN_RC_PHY_HT(phy))
-		if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
-			return 0;
-		if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
-			return 0;
-	return 1;
-}
-
-static inline int
-ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table,
-				 struct ath_rate_priv *ath_rc_priv,
-				 u8 cur_valid_txrate, u8 *next_idx)
-{
-	int8_t i;
-
-	for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
-		if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
-			*next_idx = ath_rc_priv->valid_rate_index[i-1];
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
-				 struct ath_rate_table *rate_table,
-				 u32 capflag)
-{
-	u8 i, hi = 0;
-	u32 valid;
-
-	for (i = 0; i < rate_table->rate_cnt; i++) {
-		valid = (ath_rc_priv->single_stream ?
-			 rate_table->info[i].valid_single_stream :
-			 rate_table->info[i].valid);
-		if (valid == 1) {
-			u32 phy = rate_table->info[i].phy;
-			u8 valid_rate_count = 0;
-
-			if (!ath_rc_valid_phyrate(phy, capflag, 0))
-				continue;
-
-			valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
-
-			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
-			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-			ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
-			hi = A_MAX(hi, i);
-		}
-	}
-
-	return hi;
-}
-
-static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
-				struct ath_rate_table *rate_table,
-				struct ath_rateset *rateset,
-				u32 capflag)
-{
-	u8 i, j, hi = 0;
-
-	/* Use intersection of working rates and valid rates */
-	for (i = 0; i < rateset->rs_nrates; i++) {
-		for (j = 0; j < rate_table->rate_cnt; j++) {
-			u32 phy = rate_table->info[j].phy;
-			u32 valid = (ath_rc_priv->single_stream ?
-				rate_table->info[j].valid_single_stream :
-				rate_table->info[j].valid);
-			u8 rate = rateset->rs_rates[i];
-			u8 dot11rate = rate_table->info[j].dot11rate;
-
-			/* We allow a rate only if its valid and the
-			 * capflag matches one of the validity
-			 * (VALID/VALID_20/VALID_40) flags */
-
-			if (((rate & 0x7F) == (dot11rate & 0x7F)) &&
-			    ((valid & WLAN_RC_CAP_MODE(capflag)) ==
-			     WLAN_RC_CAP_MODE(capflag)) &&
-			    !WLAN_RC_PHY_HT(phy)) {
-				u8 valid_rate_count = 0;
-
-				if (!ath_rc_valid_phyrate(phy, capflag, 0))
-					continue;
-
-				valid_rate_count =
-					ath_rc_priv->valid_phy_ratecnt[phy];
-
-				ath_rc_priv->valid_phy_rateidx[phy]
-					[valid_rate_count] = j;
-				ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-				ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
-				hi = A_MAX(hi, j);
-			}
-		}
-	}
-
-	return hi;
-}
-
-static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
-				  struct ath_rate_table *rate_table,
-				  u8 *mcs_set, u32 capflag)
-{
-	struct ath_rateset *rateset = (struct ath_rateset *)mcs_set;
-
-	u8 i, j, hi = 0;
-
-	/* Use intersection of working rates and valid rates */
-	for (i = 0; i < rateset->rs_nrates; i++) {
-		for (j = 0; j < rate_table->rate_cnt; j++) {
-			u32 phy = rate_table->info[j].phy;
-			u32 valid = (ath_rc_priv->single_stream ?
-				     rate_table->info[j].valid_single_stream :
-				     rate_table->info[j].valid);
-			u8 rate = rateset->rs_rates[i];
-			u8 dot11rate = rate_table->info[j].dot11rate;
-
-			if (((rate & 0x7F) != (dot11rate & 0x7F)) ||
-			    !WLAN_RC_PHY_HT(phy) ||
-			    !WLAN_RC_PHY_HT_VALID(valid, capflag))
-				continue;
-
-			if (!ath_rc_valid_phyrate(phy, capflag, 0))
-				continue;
-
-			ath_rc_priv->valid_phy_rateidx[phy]
-				[ath_rc_priv->valid_phy_ratecnt[phy]] = j;
-			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
-			ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
-			hi = A_MAX(hi, j);
-		}
-	}
-
-	return hi;
-}
-
-static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
-			     struct ath_rate_priv *ath_rc_priv,
-			     struct ath_rate_table *rate_table,
-			     int *is_probing)
-{
-	u32 dt, best_thruput, this_thruput, now_msec;
-	u8 rate, next_rate, best_rate, maxindex, minindex;
-	int8_t  rssi_last, rssi_reduce = 0, index = 0;
-
-	*is_probing = 0;
-
-	rssi_last = median(ath_rc_priv->rssi_last,
-			   ath_rc_priv->rssi_last_prev,
-			   ath_rc_priv->rssi_last_prev2);
-
-	/*
-	 * Age (reduce) last ack rssi based on how old it is.
-	 * The bizarre numbers are so the delta is 160msec,
-	 * meaning we divide by 16.
-	 *   0msec   <= dt <= 25msec:   don't derate
-	 *   25msec  <= dt <= 185msec:  derate linearly from 0 to 10dB
-	 *   185msec <= dt:             derate by 10dB
-	 */
-
-	now_msec = jiffies_to_msecs(jiffies);
-	dt = now_msec - ath_rc_priv->rssi_time;
-
-	if (dt >= 185)
-		rssi_reduce = 10;
-	else if (dt >= 25)
-		rssi_reduce = (u8)((dt - 25) >> 4);
-
-	/* Now reduce rssi_last by rssi_reduce */
-	if (rssi_last < rssi_reduce)
-		rssi_last = 0;
-	else
-		rssi_last -= rssi_reduce;
-
-	/*
-	 * Now look up the rate in the rssi table and return it.
-	 * If no rates match then we return 0 (lowest rate)
-	 */
-
-	best_thruput = 0;
-	maxindex = ath_rc_priv->max_valid_rate-1;
-
-	minindex = 0;
-	best_rate = minindex;
-
-	/*
-	 * Try the higher rate first. It will reduce memory moving time
-	 * if we have very good channel characteristics.
-	 */
-	for (index = maxindex; index >= minindex ; index--) {
-		u8 per_thres;
-
-		rate = ath_rc_priv->valid_rate_index[index];
-		if (rate > ath_rc_priv->rate_max_phy)
-			continue;
-
-		/*
-		 * For TCP the average collision rate is around 11%,
-		 * so we ignore PERs less than this.  This is to
-		 * prevent the rate we are currently using (whose
-		 * PER might be in the 10-15 range because of TCP
-		 * collisions) looking worse than the next lower
-		 * rate whose PER has decayed close to 0.  If we
-		 * used to next lower rate, its PER would grow to
-		 * 10-15 and we would be worse off then staying
-		 * at the current rate.
-		 */
-		per_thres = ath_rc_priv->state[rate].per;
-		if (per_thres < 12)
-			per_thres = 12;
-
-		this_thruput = rate_table->info[rate].user_ratekbps *
-			(100 - per_thres);
-
-		if (best_thruput <= this_thruput) {
-			best_thruput = this_thruput;
-			best_rate    = rate;
-		}
-	}
-
-	rate = best_rate;
-	ath_rc_priv->rssi_last_lookup = rssi_last;
-
-	/*
-	 * Must check the actual rate (ratekbps) to account for
-	 * non-monoticity of 11g's rate table
-	 */
-
-	if (rate >= ath_rc_priv->rate_max_phy) {
-		rate = ath_rc_priv->rate_max_phy;
-
-		/* Probe the next allowed phy state */
-		if (ath_rc_get_nextvalid_txrate(rate_table,
-					ath_rc_priv, rate, &next_rate) &&
-		    (now_msec - ath_rc_priv->probe_time >
-		     rate_table->probe_interval) &&
-		    (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
-			rate = next_rate;
-			ath_rc_priv->probe_rate = rate;
-			ath_rc_priv->probe_time = now_msec;
-			ath_rc_priv->hw_maxretry_pktcnt = 0;
-			*is_probing = 1;
-		}
-	}
-
-	if (rate > (ath_rc_priv->rate_table_size - 1))
-		rate = ath_rc_priv->rate_table_size - 1;
-
-	ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) ||
-	       (rate_table->info[rate].valid_single_stream &&
-		ath_rc_priv->single_stream));
-
-	return rate;
-}
-
-static void ath_rc_rate_set_series(struct ath_rate_table *rate_table,
-				   struct ieee80211_tx_rate *rate,
-				   struct ieee80211_tx_rate_control *txrc,
-				   u8 tries, u8 rix, int rtsctsenable)
-{
-	rate->count = tries;
-	rate->idx = rix;
-
-	if (txrc->short_preamble)
-		rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
-	if (txrc->rts || rtsctsenable)
-		rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
-	if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
-		rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
-	if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
-		rate->flags |= IEEE80211_TX_RC_SHORT_GI;
-	if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
-		rate->flags |= IEEE80211_TX_RC_MCS;
-}
-
-static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
-				   struct ath_rate_table *rate_table,
-				   struct ieee80211_tx_info *tx_info)
-{
-	struct ieee80211_tx_rate *rates = tx_info->control.rates;
-	int i = 0, rix = 0, cix, enable_g_protection = 0;
-
-	/* get the cix for the lowest valid rix */
-	for (i = 3; i >= 0; i--) {
-		if (rates[i].count && (rates[i].idx >= 0)) {
-			rix = rates[i].idx;
-			break;
-		}
-	}
-	cix = rate_table->info[rix].ctrl_rate;
-
-	/* All protection frames are transmited at 2Mb/s for 802.11g,
-	 * otherwise we transmit them at 1Mb/s */
-	if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ &&
-	    !conf_is_ht(&sc->hw->conf))
-		enable_g_protection = 1;
-
-	/*
-	 * If 802.11g protection is enabled, determine whether to use RTS/CTS or
-	 * just CTS.  Note that this is only done for OFDM/HT unicast frames.
-	 */
-	if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) &&
-	    !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-	    (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
-	     WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
-		rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
-		cix = rate_table->info[enable_g_protection].ctrl_rate;
-	}
-
-	tx_info->control.rts_cts_rate_idx = cix;
-}
-
-static u8 ath_rc_rate_getidx(struct ath_softc *sc,
-			     struct ath_rate_priv *ath_rc_priv,
-			     struct ath_rate_table *rate_table,
-			     u8 rix, u16 stepdown,
-			     u16 min_rate)
-{
-	u32 j;
-	u8 nextindex;
-
-	if (min_rate) {
-		for (j = RATE_TABLE_SIZE; j > 0; j--) {
-			if (ath_rc_get_nextlowervalid_txrate(rate_table,
-						ath_rc_priv, rix, &nextindex))
-				rix = nextindex;
-			else
-				break;
-		}
-	} else {
-		for (j = stepdown; j > 0; j--) {
-			if (ath_rc_get_nextlowervalid_txrate(rate_table,
-						ath_rc_priv, rix, &nextindex))
-				rix = nextindex;
-			else
-				break;
-		}
-	}
-	return rix;
-}
-
-static void ath_rc_ratefind(struct ath_softc *sc,
-			    struct ath_rate_priv *ath_rc_priv,
-			    struct ieee80211_tx_rate_control *txrc)
-{
-	struct ath_rate_table *rate_table;
-	struct sk_buff *skb = txrc->skb;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_rate *rates = tx_info->control.rates;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	__le16 fc = hdr->frame_control;
-	u8 try_per_rate = 0, i = 0, rix, nrix;
-	int is_probe = 0;
-
-	rate_table = sc->cur_rate_table;
-	rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe);
-	nrix = rix;
-
-	if (is_probe) {
-		/* set one try for probe rates. For the
-		 * probes don't enable rts */
-		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       1, nrix, 0);
-
-		try_per_rate = (ATH_11N_TXMAXTRY/4);
-		/* Get the next tried/allowed rate. No RTS for the next series
-		 * after the probe rate
-		 */
-		nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
-					  rate_table, nrix, 1, 0);
-		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       try_per_rate, nrix, 0);
-
-		tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-	} else {
-		try_per_rate = (ATH_11N_TXMAXTRY/4);
-		/* Set the choosen rate. No RTS for first series entry. */
-		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       try_per_rate, nrix, 0);
-	}
-
-	/* Fill in the other rates for multirate retry */
-	for ( ; i < 4; i++) {
-		u8 try_num;
-		u8 min_rate;
-
-		try_num = ((i + 1) == 4) ?
-			ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ;
-		min_rate = (((i + 1) == 4) && 0);
-
-		nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
-					  rate_table, nrix, 1, min_rate);
-		/* All other rates in the series have RTS enabled */
-		ath_rc_rate_set_series(rate_table, &rates[i], txrc,
-				       try_num, nrix, 1);
-	}
-
-	/*
-	 * NB:Change rate series to enable aggregation when operating
-	 * at lower MCS rates. When first rate in series is MCS2
-	 * in HT40 @ 2.4GHz, series should look like:
-	 *
-	 * {MCS2, MCS1, MCS0, MCS0}.
-	 *
-	 * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should
-	 * look like:
-	 *
-	 * {MCS3, MCS2, MCS1, MCS1}
-	 *
-	 * So, set fourth rate in series to be same as third one for
-	 * above conditions.
-	 */
-	if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
-	    (conf_is_ht(&sc->hw->conf))) {
-		u8 dot11rate = rate_table->info[rix].dot11rate;
-		u8 phy = rate_table->info[rix].phy;
-		if (i == 4 &&
-		    ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
-		     (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
-			rates[3].idx = rates[2].idx;
-			rates[3].flags = rates[2].flags;
-		}
-	}
-
-	/*
-	 * Force hardware to use computed duration for next
-	 * fragment by disabling multi-rate retry, which
-	 * updates duration based on the multi-rate duration table.
-	 *
-	 * FIXME: Fix duration
-	 */
-	if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-	    (ieee80211_has_morefrags(fc) ||
-	     (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) {
-		rates[1].count = rates[2].count = rates[3].count = 0;
-		rates[1].idx = rates[2].idx = rates[3].idx = 0;
-		rates[0].count = ATH_TXMAXTRY;
-	}
-
-	/* Setup RTS/CTS */
-	ath_rc_rate_set_rtscts(sc, rate_table, tx_info);
-}
-
-static bool ath_rc_update_per(struct ath_softc *sc,
-			      struct ath_rate_table *rate_table,
-			      struct ath_rate_priv *ath_rc_priv,
-			      struct ath_tx_info_priv *tx_info_priv,
-			      int tx_rate, int xretries, int retries,
-			      u32 now_msec)
-{
-	bool state_change = false;
-	int count;
-	u8 last_per;
-	static u32 nretry_to_per_lookup[10] = {
-		100 * 0 / 1,
-		100 * 1 / 4,
-		100 * 1 / 2,
-		100 * 3 / 4,
-		100 * 4 / 5,
-		100 * 5 / 6,
-		100 * 6 / 7,
-		100 * 7 / 8,
-		100 * 8 / 9,
-		100 * 9 / 10
-	};
-
-	last_per = ath_rc_priv->state[tx_rate].per;
-
-	if (xretries) {
-		if (xretries == 1) {
-			ath_rc_priv->state[tx_rate].per += 30;
-			if (ath_rc_priv->state[tx_rate].per > 100)
-				ath_rc_priv->state[tx_rate].per = 100;
-		} else {
-			/* xretries == 2 */
-			count = ARRAY_SIZE(nretry_to_per_lookup);
-			if (retries >= count)
-				retries = count - 1;
-
-			/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
-			ath_rc_priv->state[tx_rate].per =
-				(u8)(last_per - (last_per >> 3) + (100 >> 3));
-		}
-
-		/* xretries == 1 or 2 */
-
-		if (ath_rc_priv->probe_rate == tx_rate)
-			ath_rc_priv->probe_rate = 0;
-
-	} else { /* xretries == 0 */
-		count = ARRAY_SIZE(nretry_to_per_lookup);
-		if (retries >= count)
-			retries = count - 1;
-
-		if (tx_info_priv->n_bad_frames) {
-			/* new_PER = 7/8*old_PER + 1/8*(currentPER)
-			 * Assuming that n_frames is not 0.  The current PER
-			 * from the retries is 100 * retries / (retries+1),
-			 * since the first retries attempts failed, and the
-			 * next one worked.  For the one that worked,
-			 * n_bad_frames subframes out of n_frames wored,
-			 * so the PER for that part is
-			 * 100 * n_bad_frames / n_frames, and it contributes
-			 * 100 * n_bad_frames / (n_frames * (retries+1)) to
-			 * the above PER.  The expression below is a
-			 * simplified version of the sum of these two terms.
-			 */
-			if (tx_info_priv->n_frames > 0) {
-				int n_frames, n_bad_frames;
-				u8 cur_per, new_per;
-
-				n_bad_frames = retries * tx_info_priv->n_frames +
-					tx_info_priv->n_bad_frames;
-				n_frames = tx_info_priv->n_frames * (retries + 1);
-				cur_per = (100 * n_bad_frames / n_frames) >> 3;
-				new_per = (u8)(last_per - (last_per >> 3) + cur_per);
-				ath_rc_priv->state[tx_rate].per = new_per;
-			}
-		} else {
-			ath_rc_priv->state[tx_rate].per =
-				(u8)(last_per - (last_per >> 3) +
-				     (nretry_to_per_lookup[retries] >> 3));
-		}
-
-		ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
-		ath_rc_priv->rssi_last_prev  = ath_rc_priv->rssi_last;
-		ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi;
-		ath_rc_priv->rssi_time = now_msec;
-
-		/*
-		 * If we got at most one retry then increase the max rate if
-		 * this was a probe.  Otherwise, ignore the probe.
-		 */
-		if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
-			if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
-				tx_info_priv->n_frames) {
-				/*
-				 * Since we probed with just a single attempt,
-				 * any retries means the probe failed.  Also,
-				 * if the attempt worked, but more than half
-				 * the subframes were bad then also consider
-				 * the probe a failure.
-				 */
-				ath_rc_priv->probe_rate = 0;
-			} else {
-				u8 probe_rate = 0;
-
-				ath_rc_priv->rate_max_phy =
-					ath_rc_priv->probe_rate;
-				probe_rate = ath_rc_priv->probe_rate;
-
-				if (ath_rc_priv->state[probe_rate].per > 30)
-					ath_rc_priv->state[probe_rate].per = 20;
-
-				ath_rc_priv->probe_rate = 0;
-
-				/*
-				 * Since this probe succeeded, we allow the next
-				 * probe twice as soon.  This allows the maxRate
-				 * to move up faster if the probes are
-				 * succesful.
-				 */
-				ath_rc_priv->probe_time =
-					now_msec - rate_table->probe_interval / 2;
-			}
-		}
-
-		if (retries > 0) {
-			/*
-			 * Don't update anything.  We don't know if
-			 * this was because of collisions or poor signal.
-			 *
-			 * Later: if rssi_ack is close to
-			 * ath_rc_priv->state[txRate].rssi_thres and we see lots
-			 * of retries, then we could increase
-			 * ath_rc_priv->state[txRate].rssi_thres.
-			 */
-			ath_rc_priv->hw_maxretry_pktcnt = 0;
-		} else {
-			int32_t rssi_ackAvg;
-			int8_t rssi_thres;
-			int8_t rssi_ack_vmin;
-
-			/*
-			 * It worked with no retries. First ignore bogus (small)
-			 * rssi_ack values.
-			 */
-			if (tx_rate == ath_rc_priv->rate_max_phy &&
-			    ath_rc_priv->hw_maxretry_pktcnt < 255) {
-				ath_rc_priv->hw_maxretry_pktcnt++;
-			}
-
-			if (tx_info_priv->tx.ts_rssi <
-			    rate_table->info[tx_rate].rssi_ack_validmin)
-				goto exit;
-
-			/* Average the rssi */
-			if (tx_rate != ath_rc_priv->rssi_sum_rate) {
-				ath_rc_priv->rssi_sum_rate = tx_rate;
-				ath_rc_priv->rssi_sum =
-					ath_rc_priv->rssi_sum_cnt = 0;
-			}
-
-			ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
-			ath_rc_priv->rssi_sum_cnt++;
-
-			if (ath_rc_priv->rssi_sum_cnt < 4)
-				goto exit;
-
-			rssi_ackAvg =
-				(ath_rc_priv->rssi_sum + 2) / 4;
-			rssi_thres =
-				ath_rc_priv->state[tx_rate].rssi_thres;
-			rssi_ack_vmin =
-				rate_table->info[tx_rate].rssi_ack_validmin;
-
-			ath_rc_priv->rssi_sum =
-				ath_rc_priv->rssi_sum_cnt = 0;
-
-			/* Now reduce the current rssi threshold */
-			if ((rssi_ackAvg < rssi_thres + 2) &&
-			    (rssi_thres > rssi_ack_vmin)) {
-				ath_rc_priv->state[tx_rate].rssi_thres--;
-			}
-
-			state_change = true;
-		}
-	}
-exit:
-	return state_change;
-}
-
-/* Update PER, RSSI and whatever else that the code thinks it is doing.
-   If you can make sense of all this, you really need to go out more. */
-
-static void ath_rc_update_ht(struct ath_softc *sc,
-			     struct ath_rate_priv *ath_rc_priv,
-			     struct ath_tx_info_priv *tx_info_priv,
-			     int tx_rate, int xretries, int retries)
-{
-#define CHK_RSSI(rate)					\
-	((ath_rc_priv->state[(rate)].rssi_thres +	\
-	  rate_table->info[(rate)].rssi_ack_deltamin) > \
-	 ath_rc_priv->state[(rate)+1].rssi_thres)
-
-	u32 now_msec = jiffies_to_msecs(jiffies);
-	int rate;
-	u8 last_per;
-	bool state_change = false;
-	struct ath_rate_table *rate_table = sc->cur_rate_table;
-	int size = ath_rc_priv->rate_table_size;
-
-	if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
-		return;
-
-	/* To compensate for some imbalance between ctrl and ext. channel */
-
-	if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
-		tx_info_priv->tx.ts_rssi =
-			tx_info_priv->tx.ts_rssi < 3 ? 0 :
-			tx_info_priv->tx.ts_rssi - 3;
-
-	last_per = ath_rc_priv->state[tx_rate].per;
-
-	/* Update PER first */
-	state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
-					 tx_info_priv, tx_rate, xretries,
-					 retries, now_msec);
-
-	/*
-	 * If this rate looks bad (high PER) then stop using it for
-	 * a while (except if we are probing).
-	 */
-	if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
-	    rate_table->info[tx_rate].ratekbps <=
-	    rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
-		ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
-				 (u8)tx_rate, &ath_rc_priv->rate_max_phy);
-
-		/* Don't probe for a little while. */
-		ath_rc_priv->probe_time = now_msec;
-	}
-
-	if (state_change) {
-		/*
-		 * Make sure the rates above this have higher rssi thresholds.
-		 * (Note:  Monotonicity is kept within the OFDM rates and
-		 *         within the CCK rates. However, no adjustment is
-		 *         made to keep the rssi thresholds monotonically
-		 *         increasing between the CCK and OFDM rates.)
-		 */
-		for (rate = tx_rate; rate < size - 1; rate++) {
-			if (rate_table->info[rate+1].phy !=
-			    rate_table->info[tx_rate].phy)
-				break;
-
-			if (CHK_RSSI(rate)) {
-				ath_rc_priv->state[rate+1].rssi_thres =
-					ath_rc_priv->state[rate].rssi_thres +
-					rate_table->info[rate].rssi_ack_deltamin;
-			}
-		}
-
-		/* Make sure the rates below this have lower rssi thresholds. */
-		for (rate = tx_rate - 1; rate >= 0; rate--) {
-			if (rate_table->info[rate].phy !=
-			    rate_table->info[tx_rate].phy)
-				break;
-
-			if (CHK_RSSI(rate)) {
-				if (ath_rc_priv->state[rate+1].rssi_thres <
-				    rate_table->info[rate].rssi_ack_deltamin)
-					ath_rc_priv->state[rate].rssi_thres = 0;
-				else {
-					ath_rc_priv->state[rate].rssi_thres =
-					ath_rc_priv->state[rate+1].rssi_thres -
-					rate_table->info[rate].rssi_ack_deltamin;
-				}
-
-				if (ath_rc_priv->state[rate].rssi_thres <
-				    rate_table->info[rate].rssi_ack_validmin) {
-					ath_rc_priv->state[rate].rssi_thres =
-					rate_table->info[rate].rssi_ack_validmin;
-				}
-			}
-		}
-	}
-
-	/* Make sure the rates below this have lower PER */
-	/* Monotonicity is kept only for rates below the current rate. */
-	if (ath_rc_priv->state[tx_rate].per < last_per) {
-		for (rate = tx_rate - 1; rate >= 0; rate--) {
-			if (rate_table->info[rate].phy !=
-			    rate_table->info[tx_rate].phy)
-				break;
-
-			if (ath_rc_priv->state[rate].per >
-			    ath_rc_priv->state[rate+1].per) {
-				ath_rc_priv->state[rate].per =
-					ath_rc_priv->state[rate+1].per;
-			}
-		}
-	}
-
-	/* Maintain monotonicity for rates above the current rate */
-	for (rate = tx_rate; rate < size - 1; rate++) {
-		if (ath_rc_priv->state[rate+1].per <
-		    ath_rc_priv->state[rate].per)
-			ath_rc_priv->state[rate+1].per =
-				ath_rc_priv->state[rate].per;
-	}
-
-	/* Every so often, we reduce the thresholds and
-	 * PER (different for CCK and OFDM). */
-	if (now_msec - ath_rc_priv->rssi_down_time >=
-	    rate_table->rssi_reduce_interval) {
-
-		for (rate = 0; rate < size; rate++) {
-			if (ath_rc_priv->state[rate].rssi_thres >
-			    rate_table->info[rate].rssi_ack_validmin)
-				ath_rc_priv->state[rate].rssi_thres -= 1;
-		}
-		ath_rc_priv->rssi_down_time = now_msec;
-	}
-
-	/* Every so often, we reduce the thresholds
-	 * and PER (different for CCK and OFDM). */
-	if (now_msec - ath_rc_priv->per_down_time >=
-	    rate_table->rssi_reduce_interval) {
-		for (rate = 0; rate < size; rate++) {
-			ath_rc_priv->state[rate].per =
-				7 * ath_rc_priv->state[rate].per / 8;
-		}
-
-		ath_rc_priv->per_down_time = now_msec;
-	}
-
-	ath_debug_stat_retries(sc, tx_rate, xretries, retries,
-			       ath_rc_priv->state[tx_rate].per);
-
-#undef CHK_RSSI
-}
-
-static int ath_rc_get_rateindex(struct ath_rate_table *rate_table,
-				struct ieee80211_tx_rate *rate)
-{
-	int rix;
-
-	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-	    (rate->flags & IEEE80211_TX_RC_SHORT_GI))
-		rix = rate_table->info[rate->idx].ht_index;
-	else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
-		rix = rate_table->info[rate->idx].sgi_index;
-	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-		rix = rate_table->info[rate->idx].cw40index;
-	else
-		rix = rate_table->info[rate->idx].base_index;
-
-	return rix;
-}
-
-static void ath_rc_tx_status(struct ath_softc *sc,
-			     struct ath_rate_priv *ath_rc_priv,
-			     struct ieee80211_tx_info *tx_info,
-			     int final_ts_idx, int xretries, int long_retry)
-{
-	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-	struct ath_rate_table *rate_table;
-	struct ieee80211_tx_rate *rates = tx_info->status.rates;
-	u8 flags;
-	u32 i = 0, rix;
-
-	rate_table = sc->cur_rate_table;
-
-	/*
-	 * If the first rate is not the final index, there
-	 * are intermediate rate failures to be processed.
-	 */
-	if (final_ts_idx != 0) {
-		/* Process intermediate rates that failed.*/
-		for (i = 0; i < final_ts_idx ; i++) {
-			if (rates[i].count != 0 && (rates[i].idx >= 0)) {
-				flags = rates[i].flags;
-
-				/* If HT40 and we have switched mode from
-				 * 40 to 20 => don't update */
-
-				if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-				    (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG))
-					return;
-
-				rix = ath_rc_get_rateindex(rate_table, &rates[i]);
-				ath_rc_update_ht(sc, ath_rc_priv,
-						tx_info_priv, rix,
-						xretries ? 1 : 2,
-						rates[i].count);
-			}
-		}
-	} else {
-		/*
-		 * Handle the special case of MIMO PS burst, where the second
-		 * aggregate is sent out with only one rate and one try.
-		 * Treating it as an excessive retry penalizes the rate
-		 * inordinately.
-		 */
-		if (rates[0].count == 1 && xretries == 1)
-			xretries = 2;
-	}
-
-	flags = rates[i].flags;
-
-	/* If HT40 and we have switched mode from 40 to 20 => don't update */
-	if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-	    (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) {
-		return;
-	}
-
-	rix = ath_rc_get_rateindex(rate_table, &rates[i]);
-	ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
-			 xretries, long_retry);
-}
-
-static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
-						    enum ieee80211_band band,
-						    bool is_ht, bool is_cw_40)
-{
-	int mode = 0;
-
-	switch(band) {
-	case IEEE80211_BAND_2GHZ:
-		mode = ATH9K_MODE_11G;
-		if (is_ht)
-			mode = ATH9K_MODE_11NG_HT20;
-		if (is_cw_40)
-			mode = ATH9K_MODE_11NG_HT40PLUS;
-		break;
-	case IEEE80211_BAND_5GHZ:
-		mode = ATH9K_MODE_11A;
-		if (is_ht)
-			mode = ATH9K_MODE_11NA_HT20;
-		if (is_cw_40)
-			mode = ATH9K_MODE_11NA_HT40PLUS;
-		break;
-	default:
-		DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n");
-		return NULL;
-	}
-
-	BUG_ON(mode >= ATH9K_MODE_MAX);
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode);
-	return sc->hw_rate_table[mode];
-}
-
-static void ath_rc_init(struct ath_softc *sc,
-			struct ath_rate_priv *ath_rc_priv,
-			struct ieee80211_supported_band *sband,
-			struct ieee80211_sta *sta,
-			struct ath_rate_table *rate_table)
-{
-	struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
-	u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
-	u8 i, j, k, hi = 0, hthi = 0;
-
-	if (!rate_table) {
-		DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
-		return;
-	}
-
-	/* Initial rate table size. Will change depending
-	 * on the working rate set */
-	ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
-
-	/* Initialize thresholds according to the global rate table */
-	for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
-		ath_rc_priv->state[i].rssi_thres =
-			rate_table->info[i].rssi_ack_validmin;
-		ath_rc_priv->state[i].per = 0;
-	}
-
-	/* Determine the valid rates */
-	ath_rc_init_valid_txmask(ath_rc_priv);
-
-	for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
-		for (j = 0; j < MAX_TX_RATE_PHY; j++)
-			ath_rc_priv->valid_phy_rateidx[i][j] = 0;
-		ath_rc_priv->valid_phy_ratecnt[i] = 0;
-	}
-	ath_rc_priv->rc_phy_mode = ath_rc_priv->ht_cap & WLAN_RC_40_FLAG;
-
-	/* Set stream capability */
-	ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
-
-	if (!rateset->rs_nrates) {
-		/* No working rate, just initialize valid rates */
-		hi = ath_rc_init_validrates(ath_rc_priv, rate_table,
-					    ath_rc_priv->ht_cap);
-	} else {
-		/* Use intersection of working rates and valid rates */
-		hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table,
-					   rateset, ath_rc_priv->ht_cap);
-		if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
-			hthi = ath_rc_setvalid_htrates(ath_rc_priv,
-						       rate_table,
-						       ht_mcs,
-						       ath_rc_priv->ht_cap);
-		}
-		hi = A_MAX(hi, hthi);
-	}
-
-	ath_rc_priv->rate_table_size = hi + 1;
-	ath_rc_priv->rate_max_phy = 0;
-	ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
-
-	for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
-		for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
-			ath_rc_priv->valid_rate_index[k++] =
-				ath_rc_priv->valid_phy_rateidx[i][j];
-		}
-
-		if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1)
-		    || !ath_rc_priv->valid_phy_ratecnt[i])
-			continue;
-
-		ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
-	}
-	ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
-	ASSERT(k <= RATE_TABLE_SIZE);
-
-	ath_rc_priv->max_valid_rate = k;
-	ath_rc_sort_validrates(rate_table, ath_rc_priv);
-	ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
-	sc->cur_rate_table = rate_table;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n",
-		ath_rc_priv->ht_cap);
-}
-
-static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
-			       bool is_cw40, bool is_sgi40)
-{
-	u8 caps = 0;
-
-	if (sta->ht_cap.ht_supported) {
-		caps = WLAN_RC_HT_FLAG;
-		if (sc->sc_ah->caps.tx_chainmask != 1 &&
-		    ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) {
-			if (sta->ht_cap.mcs.rx_mask[1])
-				caps |= WLAN_RC_DS_FLAG;
-		}
-		if (is_cw40)
-			caps |= WLAN_RC_40_FLAG;
-		if (is_sgi40)
-			caps |= WLAN_RC_SGI_FLAG;
-	}
-
-	return caps;
-}
-
-/***********************************/
-/* mac80211 Rate Control callbacks */
-/***********************************/
-
-static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
-			  struct ieee80211_sta *sta, void *priv_sta,
-			  struct sk_buff *skb)
-{
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-	struct ath_tx_info_priv *tx_info_priv = NULL;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *hdr;
-	int final_ts_idx, tx_status = 0, is_underrun = 0;
-	__le16 fc;
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-	final_ts_idx = tx_info_priv->tx.ts_rateindex;
-
-	if (!priv_sta || !ieee80211_is_data(fc) ||
-	    !tx_info_priv->update_rc)
-		goto exit;
-
-	if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
-		goto exit;
-
-	/*
-	 * If underrun error is seen assume it as an excessive retry only
-	 * if prefetch trigger level have reached the max (0x3f for 5416)
-	 * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
-	 * times. This affects how ratectrl updates PER for the failed rate.
-	 */
-	if (tx_info_priv->tx.ts_flags &
-	    (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
-	    ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) {
-		tx_status = 1;
-		is_underrun = 1;
-	}
-
-	if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
-	    (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
-		tx_status = 1;
-
-	ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
-			 (is_underrun) ? ATH_11N_TXMAXTRY :
-			 tx_info_priv->tx.ts_longretry);
-
-	/* Check if aggregation has to be enabled for this tid */
-	if (conf_is_ht(&sc->hw->conf) &&
-	    !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-		if (ieee80211_is_data_qos(fc)) {
-			u8 *qc, tid;
-			struct ath_node *an;
-
-			qc = ieee80211_get_qos_ctl(hdr);
-			tid = qc[0] & 0xf;
-			an = (struct ath_node *)sta->drv_priv;
-
-			if(ath_tx_aggr_check(sc, an, tid))
-				ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid);
-		}
-	}
-
-	ath_debug_stat_rc(sc, skb);
-exit:
-	kfree(tx_info_priv);
-}
-
-static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
-			 struct ieee80211_tx_rate_control *txrc)
-{
-	struct ieee80211_supported_band *sband = txrc->sband;
-	struct sk_buff *skb = txrc->skb;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-	__le16 fc = hdr->frame_control;
-
-	/* lowest rate for management and multicast/broadcast frames */
-	if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
-	    !sta) {
-		tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
-		tx_info->control.rates[0].count =
-			is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY;
-		return;
-	}
-
-	/* Find tx rate for unicast frames */
-	ath_rc_ratefind(sc, ath_rc_priv, txrc);
-}
-
-static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
-                          struct ieee80211_sta *sta, void *priv_sta)
-{
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-	struct ath_rate_table *rate_table = NULL;
-	bool is_cw40, is_sgi40;
-	int i, j = 0;
-
-	for (i = 0; i < sband->n_bitrates; i++) {
-		if (sta->supp_rates[sband->band] & BIT(i)) {
-			ath_rc_priv->neg_rates.rs_rates[j]
-				= (sband->bitrates[i].bitrate * 2) / 10;
-			j++;
-		}
-	}
-	ath_rc_priv->neg_rates.rs_nrates = j;
-
-	if (sta->ht_cap.ht_supported) {
-		for (i = 0, j = 0; i < 77; i++) {
-			if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
-				ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
-			if (j == ATH_RATE_MAX)
-				break;
-		}
-		ath_rc_priv->neg_ht_rates.rs_nrates = j;
-	}
-
-	is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-	is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
-
-	/* Choose rate table first */
-
-	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
-		rate_table = ath_choose_rate_table(sc, sband->band,
-						   sta->ht_cap.ht_supported,
-						   is_cw40);
-	} else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
-		/* cur_rate_table would be set on init through config() */
-		rate_table = sc->cur_rate_table;
-	}
-
-	ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40);
-	ath_rc_init(sc, priv_sta, sband, sta, rate_table);
-}
-
-static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
-			    struct ieee80211_sta *sta, void *priv_sta,
-			    u32 changed)
-{
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *ath_rc_priv = priv_sta;
-	struct ath_rate_table *rate_table = NULL;
-	bool oper_cw40 = false, oper_sgi40;
-	bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
-		true : false;
-	bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
-		true : false;
-
-	/* FIXME: Handle AP mode later when we support CWM */
-
-	if (changed & IEEE80211_RC_HT_CHANGED) {
-		if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
-			return;
-
-		if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS ||
-		    sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS)
-			oper_cw40 = true;
-
-		oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
-			true : false;
-
-		if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) {
-			rate_table = ath_choose_rate_table(sc, sband->band,
-						   sta->ht_cap.ht_supported,
-						   oper_cw40);
-			ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
-						   oper_cw40, oper_sgi40);
-			ath_rc_init(sc, priv_sta, sband, sta, rate_table);
-
-			DPRINTF(sc, ATH_DBG_CONFIG,
-				"Operating HT Bandwidth changed to: %d\n",
-				sc->hw->conf.channel_type);
-		}
-	}
-}
-
-static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	return aphy->sc;
-}
-
-static void ath_rate_free(void *priv)
-{
-	return;
-}
-
-static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
-{
-	struct ath_softc *sc = priv;
-	struct ath_rate_priv *rate_priv;
-
-	rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
-	if (!rate_priv) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to allocate private rc structure\n");
-		return NULL;
-	}
-
-	rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
-	rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max;
-
-	return rate_priv;
-}
-
-static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
-			      void *priv_sta)
-{
-	struct ath_rate_priv *rate_priv = priv_sta;
-	kfree(rate_priv);
-}
-
-static struct rate_control_ops ath_rate_ops = {
-	.module = NULL,
-	.name = "ath9k_rate_control",
-	.tx_status = ath_tx_status,
-	.get_rate = ath_get_rate,
-	.rate_init = ath_rate_init,
-	.rate_update = ath_rate_update,
-	.alloc = ath_rate_alloc,
-	.free = ath_rate_free,
-	.alloc_sta = ath_rate_alloc_sta,
-	.free_sta = ath_rate_free_sta,
-};
-
-void ath_rate_attach(struct ath_softc *sc)
-{
-	sc->hw_rate_table[ATH9K_MODE_11B] =
-		&ar5416_11b_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11A] =
-		&ar5416_11a_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11G] =
-		&ar5416_11g_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
-		&ar5416_11na_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
-		&ar5416_11ng_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
-		&ar5416_11na_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
-		&ar5416_11na_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
-		&ar5416_11ng_ratetable;
-	sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
-		&ar5416_11ng_ratetable;
-}
-
-int ath_rate_control_register(void)
-{
-	return ieee80211_rate_control_register(&ath_rate_ops);
-}
-
-void ath_rate_control_unregister(void)
-{
-	ieee80211_rate_control_unregister(&ath_rate_ops);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/rc.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/rc.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/rc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/rc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,220 +0,0 @@
-/*
- * Copyright (c) 2004 Sam Leffler, Errno Consulting
- * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef RC_H
-#define RC_H
-
-struct ath_softc;
-
-#define ATH_RATE_MAX     30
-#define RATE_TABLE_SIZE  64
-#define MAX_TX_RATE_PHY  48
-#define WLAN_CTRL_FRAME_SIZE (2+2+6+4)
-
-/* VALID_ALL - valid for 20/40/Legacy,
- * VALID - Legacy only,
- * VALID_20 - HT 20 only,
- * VALID_40 - HT 40 only */
-
-#define INVALID    0x0
-#define VALID      0x1
-#define VALID_20   0x2
-#define VALID_40   0x4
-#define VALID_2040 (VALID_20|VALID_40)
-#define VALID_ALL  (VALID_2040|VALID)
-
-enum {
-	WLAN_RC_PHY_OFDM,
-	WLAN_RC_PHY_CCK,
-	WLAN_RC_PHY_HT_20_SS,
-	WLAN_RC_PHY_HT_20_DS,
-	WLAN_RC_PHY_HT_40_SS,
-	WLAN_RC_PHY_HT_40_DS,
-	WLAN_RC_PHY_HT_20_SS_HGI,
-	WLAN_RC_PHY_HT_20_DS_HGI,
-	WLAN_RC_PHY_HT_40_SS_HGI,
-	WLAN_RC_PHY_HT_40_DS_HGI,
-	WLAN_RC_PHY_MAX
-};
-
-#define WLAN_RC_PHY_DS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_DS)		\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
-#define WLAN_RC_PHY_40(_phy)   ((_phy == WLAN_RC_PHY_HT_40_SS)		\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
-#define WLAN_RC_PHY_SGI(_phy)  ((_phy == WLAN_RC_PHY_HT_20_SS_HGI)      \
-				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
-				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)   \
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
-
-#define WLAN_RC_PHY_HT(_phy)    (_phy >= WLAN_RC_PHY_HT_20_SS)
-
-#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ?	\
-		(capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
-
-/* Return TRUE if flag supports HT20 && client supports HT20 or
- * return TRUE if flag supports HT40 && client supports HT40.
- * This is used becos some rates overlap between HT20/HT40.
- */
-#define WLAN_RC_PHY_HT_VALID(flag, capflag)			\
-	(((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
-	 ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
-
-#define WLAN_RC_DS_FLAG         (0x01)
-#define WLAN_RC_40_FLAG         (0x02)
-#define WLAN_RC_SGI_FLAG        (0x04)
-#define WLAN_RC_HT_FLAG         (0x08)
-
-/**
- * struct ath_rate_table - Rate Control table
- * @valid: valid for use in rate control
- * @valid_single_stream: valid for use in rate control for
- * 	single stream operation
- * @phy: CCK/OFDM
- * @ratekbps: rate in Kbits per second
- * @user_ratekbps: user rate in Kbits per second
- * @ratecode: rate that goes into HW descriptors
- * @short_preamble: Mask for enabling short preamble in ratecode for CCK
- * @dot11rate: value that goes into supported
- * 	rates info element of MLME
- * @ctrl_rate: Index of next lower basic rate, used for duration computation
- * @max_4ms_framelen: maximum frame length(bytes) for tx duration
- * @probe_interval: interval for rate control to probe for other rates
- * @rssi_reduce_interval: interval for rate control to reduce rssi
- * @initial_ratemax: initial ratemax value
- */
-struct ath_rate_table {
-	int rate_cnt;
-	struct {
-		int valid;
-		int valid_single_stream;
-		u8 phy;
-		u32 ratekbps;
-		u32 user_ratekbps;
-		u8 ratecode;
-		u8 short_preamble;
-		u8 dot11rate;
-		u8 ctrl_rate;
-		int8_t rssi_ack_validmin;
-		int8_t rssi_ack_deltamin;
-		u8 base_index;
-		u8 cw40index;
-		u8 sgi_index;
-		u8 ht_index;
-		u32 max_4ms_framelen;
-	} info[RATE_TABLE_SIZE];
-	u32 probe_interval;
-	u32 rssi_reduce_interval;
-	u8 initial_ratemax;
-};
-
-struct ath_tx_ratectrl_state {
-	int8_t rssi_thres;	/* required rssi for this rate (dB) */
-	u8 per;			/* recent estimate of packet error rate (%) */
-};
-
-struct ath_rateset {
-	u8 rs_nrates;
-	u8 rs_rates[ATH_RATE_MAX];
-};
-
-/**
- * struct ath_rate_priv - Rate Control priv data
- * @state: RC state
- * @rssi_last: last ACK rssi
- * @rssi_last_lookup: last ACK rssi used for lookup
- * @rssi_last_prev: previous last ACK rssi
- * @rssi_last_prev2: 2nd previous last ACK rssi
- * @rssi_sum_cnt: count of rssi_sum for averaging
- * @rssi_sum_rate: rate that we are averaging
- * @rssi_sum: running sum of rssi for averaging
- * @probe_rate: rate we are probing at
- * @rssi_time: msec timestamp for last ack rssi
- * @rssi_down_time: msec timestamp for last down step
- * @probe_time: msec timestamp for last probe
- * @hw_maxretry_pktcnt: num of packets since we got HW max retry error
- * @max_valid_rate: maximum number of valid rate
- * @per_down_time: msec timestamp for last PER down step
- * @valid_phy_ratecnt: valid rate count
- * @rate_max_phy: phy index for the max rate
- * @probe_interval: interval for ratectrl to probe for other rates
- * @prev_data_rix: rate idx of last data frame
- * @ht_cap: HT capabilities
- * @single_stream: When TRUE, only single TX stream possible
- * @neg_rates: Negotatied rates
- * @neg_ht_rates: Negotiated HT rates
- */
-struct ath_rate_priv {
-	int8_t rssi_last;
-	int8_t rssi_last_lookup;
-	int8_t rssi_last_prev;
-	int8_t rssi_last_prev2;
-	int32_t rssi_sum_cnt;
-	int32_t rssi_sum_rate;
-	int32_t rssi_sum;
-	u8 rate_table_size;
-	u8 probe_rate;
-	u8 hw_maxretry_pktcnt;
-	u8 max_valid_rate;
-	u8 valid_rate_index[RATE_TABLE_SIZE];
-	u8 ht_cap;
-	u8 single_stream;
-	u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
-	u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
-	u8 rc_phy_mode;
-	u8 rate_max_phy;
-	u32 rssi_time;
-	u32 rssi_down_time;
-	u32 probe_time;
-	u32 per_down_time;
-	u32 probe_interval;
-	u32 prev_data_rix;
-	u32 tx_triglevel_max;
-	struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE];
-	struct ath_rateset neg_rates;
-	struct ath_rateset neg_ht_rates;
-	struct ath_rate_softc *asc;
-};
-
-enum ath9k_internal_frame_type {
-	ATH9K_NOT_INTERNAL,
-	ATH9K_INT_PAUSE,
-	ATH9K_INT_UNPAUSE
-};
-
-struct ath_tx_info_priv {
-	struct ath_wiphy *aphy;
-	struct ath_tx_status tx;
-	int n_frames;
-	int n_bad_frames;
-	bool update_rc;
-	enum ath9k_internal_frame_type frame_type;
-};
-
-#define ATH_TX_INFO_PRIV(tx_info) \
-	((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
-
-void ath_rate_attach(struct ath_softc *sc);
-u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
-int ath_rate_control_register(void);
-void ath_rate_control_unregister(void);
-
-#endif /* RC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/recv.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/recv.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/recv.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/recv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,709 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
-					     struct ieee80211_hdr *hdr)
-{
-	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
-	int i;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy == NULL)
-			continue;
-		if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr)
-		    == 0) {
-			hw = aphy->hw;
-			break;
-		}
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-	return hw;
-}
-
-/*
- * Setup and link descriptors.
- *
- * 11N: we can no longer afford to self link the last descriptor.
- * MAC acknowledges BA status as long as it copies frames to host
- * buffer (or rx fifo). This can incorrectly acknowledge packets
- * to a sender if last desc is self-linked.
- */
-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_desc *ds;
-	struct sk_buff *skb;
-
-	ATH_RXBUF_RESET(bf);
-
-	ds = bf->bf_desc;
-	ds->ds_link = 0; /* link to null */
-	ds->ds_data = bf->bf_buf_addr;
-
-	/* virtual addr of the beginning of the buffer. */
-	skb = bf->bf_mpdu;
-	ASSERT(skb != NULL);
-	ds->ds_vdata = skb->data;
-
-	/* setup rx descriptors. The rx.bufsize here tells the harware
-	 * how much data it can DMA to us and that we are prepared
-	 * to process */
-	ath9k_hw_setuprxdesc(ah, ds,
-			     sc->rx.bufsize,
-			     0);
-
-	if (sc->rx.rxlink == NULL)
-		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
-	else
-		*sc->rx.rxlink = bf->bf_daddr;
-
-	sc->rx.rxlink = &ds->ds_link;
-	ath9k_hw_rxena(ah);
-}
-
-static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
-{
-	/* XXX block beacon interrupts */
-	ath9k_hw_setantenna(sc->sc_ah, antenna);
-	sc->rx.defant = antenna;
-	sc->rx.rxotherant = 0;
-}
-
-/*
- *  Extend 15-bit time stamp from rx descriptor to
- *  a full 64-bit TSF using the current h/w TSF.
-*/
-static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
-{
-	u64 tsf;
-
-	tsf = ath9k_hw_gettsf64(sc->sc_ah);
-	if ((tsf & 0x7fff) < rstamp)
-		tsf -= 0x8000;
-	return (tsf & ~0x7fff) | rstamp;
-}
-
-static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask)
-{
-	struct sk_buff *skb;
-	u32 off;
-
-	/*
-	 * Cache-line-align.  This is important (for the
-	 * 5210 at least) as not doing so causes bogus data
-	 * in rx'd frames.
-	 */
-
-	/* Note: the kernel can allocate a value greater than
-	 * what we ask it to give us. We really only need 4 KB as that
-	 * is this hardware supports and in fact we need at least 3849
-	 * as that is the MAX AMSDU size this hardware supports.
-	 * Unfortunately this means we may get 8 KB here from the
-	 * kernel... and that is actually what is observed on some
-	 * systems :( */
-	skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask);
-	if (skb != NULL) {
-		off = ((unsigned long) skb->data) % sc->cachelsz;
-		if (off != 0)
-			skb_reserve(skb, sc->cachelsz - off);
-	} else {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"skbuff alloc of size %u failed\n", len);
-		return NULL;
-	}
-
-	return skb;
-}
-
-/*
- * For Decrypt or Demic errors, we only mark packet status here and always push
- * up the frame up to let mac80211 handle the actual error case, be it no
- * decryption key or real decryption error. This let us keep statistics there.
- */
-static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
-			  struct ieee80211_rx_status *rx_status, bool *decrypt_error,
-			  struct ath_softc *sc)
-{
-	struct ieee80211_hdr *hdr;
-	u8 ratecode;
-	__le16 fc;
-	struct ieee80211_hw *hw;
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-	memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
-	hw = ath_get_virt_hw(sc, hdr);
-
-	if (ds->ds_rxstat.rs_more) {
-		/*
-		 * Frame spans multiple descriptors; this cannot happen yet
-		 * as we don't support jumbograms. If not in monitor mode,
-		 * discard the frame. Enable this if you want to see
-		 * error frames in Monitor mode.
-		 */
-		if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR)
-			goto rx_next;
-	} else if (ds->ds_rxstat.rs_status != 0) {
-		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
-			rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
-			goto rx_next;
-
-		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
-			*decrypt_error = true;
-		} else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
-			if (ieee80211_is_ctl(fc))
-				/*
-				 * Sometimes, we get invalid
-				 * MIC failures on valid control frames.
-				 * Remove these mic errors.
-				 */
-				ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
-			else
-				rx_status->flag |= RX_FLAG_MMIC_ERROR;
-		}
-		/*
-		 * Reject error frames with the exception of
-		 * decryption and MIC failures. For monitor mode,
-		 * we also ignore the CRC error.
-		 */
-		if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) {
-			if (ds->ds_rxstat.rs_status &
-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
-			      ATH9K_RXERR_CRC))
-				goto rx_next;
-		} else {
-			if (ds->ds_rxstat.rs_status &
-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
-				goto rx_next;
-			}
-		}
-	}
-
-	ratecode = ds->ds_rxstat.rs_rate;
-
-	if (ratecode & 0x80) {
-		/* HT rate */
-		rx_status->flag |= RX_FLAG_HT;
-		if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
-			rx_status->flag |= RX_FLAG_40MHZ;
-		if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
-			rx_status->flag |= RX_FLAG_SHORT_GI;
-		rx_status->rate_idx = ratecode & 0x7f;
-	} else {
-		int i = 0, cur_band, n_rates;
-
-		cur_band = hw->conf.channel->band;
-		n_rates = sc->sbands[cur_band].n_bitrates;
-
-		for (i = 0; i < n_rates; i++) {
-			if (sc->sbands[cur_band].bitrates[i].hw_value ==
-			    ratecode) {
-				rx_status->rate_idx = i;
-				break;
-			}
-
-			if (sc->sbands[cur_band].bitrates[i].hw_value_short ==
-			    ratecode) {
-				rx_status->rate_idx = i;
-				rx_status->flag |= RX_FLAG_SHORTPRE;
-				break;
-			}
-		}
-	}
-
-	rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
-	rx_status->band = hw->conf.channel->band;
-	rx_status->freq = hw->conf.channel->center_freq;
-	rx_status->noise = sc->ani.noise_floor;
-	rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi;
-	rx_status->antenna = ds->ds_rxstat.rs_antenna;
-
-	/* at 45 you will be able to use MCS 15 reliably. A more elaborate
-	 * scheme can be used here but it requires tables of SNR/throughput for
-	 * each possible mode used. */
-	rx_status->qual =  ds->ds_rxstat.rs_rssi * 100 / 45;
-
-	/* rssi can be more than 45 though, anything above that
-	 * should be considered at 100% */
-	if (rx_status->qual > 100)
-		rx_status->qual = 100;
-
-	rx_status->flag |= RX_FLAG_TSFT;
-
-	return 1;
-rx_next:
-	return 0;
-}
-
-static void ath_opmode_init(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	u32 rfilt, mfilt[2];
-
-	/* configure rx filter */
-	rfilt = ath_calcrxfilter(sc);
-	ath9k_hw_setrxfilter(ah, rfilt);
-
-	/* configure bssid mask */
-	if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
-		ath9k_hw_setbssidmask(sc);
-
-	/* configure operational mode */
-	ath9k_hw_setopmode(ah);
-
-	/* Handle any link-level address change. */
-	ath9k_hw_setmac(ah, sc->sc_ah->macaddr);
-
-	/* calculate and install multicast filter */
-	mfilt[0] = mfilt[1] = ~0;
-	ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
-}
-
-int ath_rx_init(struct ath_softc *sc, int nbufs)
-{
-	struct sk_buff *skb;
-	struct ath_buf *bf;
-	int error = 0;
-
-	do {
-		spin_lock_init(&sc->rx.rxflushlock);
-		sc->sc_flags &= ~SC_OP_RXFLUSH;
-		spin_lock_init(&sc->rx.rxbuflock);
-
-		sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
-					   min(sc->cachelsz,
-					       (u16)64));
-
-		DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
-			sc->cachelsz, sc->rx.bufsize);
-
-		/* Initialize rx descriptors */
-
-		error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
-					  "rx", nbufs, 1);
-		if (error != 0) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"failed to allocate rx descriptors: %d\n", error);
-			break;
-		}
-
-		list_for_each_entry(bf, &sc->rx.rxbuf, list) {
-			skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
-			if (skb == NULL) {
-				error = -ENOMEM;
-				break;
-			}
-
-			bf->bf_mpdu = skb;
-			bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
-							 sc->rx.bufsize,
-							 DMA_FROM_DEVICE);
-			if (unlikely(dma_mapping_error(sc->dev,
-				  bf->bf_buf_addr))) {
-				dev_kfree_skb_any(skb);
-				bf->bf_mpdu = NULL;
-				DPRINTF(sc, ATH_DBG_CONFIG,
-					"dma_mapping_error() on RX init\n");
-				error = -ENOMEM;
-				break;
-			}
-			bf->bf_dmacontext = bf->bf_buf_addr;
-		}
-		sc->rx.rxlink = NULL;
-
-	} while (0);
-
-	if (error)
-		ath_rx_cleanup(sc);
-
-	return error;
-}
-
-void ath_rx_cleanup(struct ath_softc *sc)
-{
-	struct sk_buff *skb;
-	struct ath_buf *bf;
-
-	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
-		skb = bf->bf_mpdu;
-		if (skb) {
-			dma_unmap_single(sc->dev,
-					 bf->bf_buf_addr,
-					 sc->rx.bufsize,
-					 DMA_FROM_DEVICE);
-			dev_kfree_skb(skb);
-		}
-	}
-
-	if (sc->rx.rxdma.dd_desc_len != 0)
-		ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
-}
-
-/*
- * Calculate the receive filter according to the
- * operating mode and state:
- *
- * o always accept unicast, broadcast, and multicast traffic
- * o maintain current state of phy error reception (the hal
- *   may enable phy error frames for noise immunity work)
- * o probe request frames are accepted only when operating in
- *   hostap, adhoc, or monitor modes
- * o enable promiscuous mode according to the interface state
- * o accept beacons:
- *   - when operating in adhoc mode so the 802.11 layer creates
- *     node table entries for peers,
- *   - when operating in station mode for collecting rssi data when
- *     the station is otherwise quiet, or
- *   - when operating as a repeater so we see repeater-sta beacons
- *   - when scanning
- */
-
-u32 ath_calcrxfilter(struct ath_softc *sc)
-{
-#define	RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
-
-	u32 rfilt;
-
-	rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
-		| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
-		| ATH9K_RX_FILTER_MCAST;
-
-	/* If not a STA, enable processing of Probe Requests */
-	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
-		rfilt |= ATH9K_RX_FILTER_PROBEREQ;
-
-	/*
-	 * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
-	 * mode interface or when in monitor mode. AP mode does not need this
-	 * since it receives all in-BSS frames anyway.
-	 */
-	if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
-	     (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR))
-		rfilt |= ATH9K_RX_FILTER_PROM;
-
-	if (sc->rx.rxfilter & FIF_CONTROL)
-		rfilt |= ATH9K_RX_FILTER_CONTROL;
-
-	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
-	    !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
-		rfilt |= ATH9K_RX_FILTER_MYBEACON;
-	else
-		rfilt |= ATH9K_RX_FILTER_BEACON;
-
-	/* If in HOSTAP mode, want to enable reception of PSPOLL frames */
-	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP)
-		rfilt |= ATH9K_RX_FILTER_PSPOLL;
-
-	if (sc->sec_wiphy) {
-		/* TODO: only needed if more than one BSSID is in use in
-		 * station/adhoc mode */
-		/* TODO: for older chips, may need to add ATH9K_RX_FILTER_PROM
-		 */
-		rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
-	}
-
-	return rfilt;
-
-#undef RX_FILTER_PRESERVE
-}
-
-int ath_startrecv(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_buf *bf, *tbf;
-
-	spin_lock_bh(&sc->rx.rxbuflock);
-	if (list_empty(&sc->rx.rxbuf))
-		goto start_recv;
-
-	sc->rx.rxlink = NULL;
-	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
-		ath_rx_buf_link(sc, bf);
-	}
-
-	/* We could have deleted elements so the list may be empty now */
-	if (list_empty(&sc->rx.rxbuf))
-		goto start_recv;
-
-	bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
-	ath9k_hw_putrxbuf(ah, bf->bf_daddr);
-	ath9k_hw_rxena(ah);
-
-start_recv:
-	spin_unlock_bh(&sc->rx.rxbuflock);
-	ath_opmode_init(sc);
-	ath9k_hw_startpcureceive(ah);
-
-	return 0;
-}
-
-bool ath_stoprecv(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	bool stopped;
-
-	ath9k_hw_stoppcurecv(ah);
-	ath9k_hw_setrxfilter(ah, 0);
-	stopped = ath9k_hw_stopdmarecv(ah);
-	sc->rx.rxlink = NULL;
-
-	return stopped;
-}
-
-void ath_flushrecv(struct ath_softc *sc)
-{
-	spin_lock_bh(&sc->rx.rxflushlock);
-	sc->sc_flags |= SC_OP_RXFLUSH;
-	ath_rx_tasklet(sc, 1);
-	sc->sc_flags &= ~SC_OP_RXFLUSH;
-	spin_unlock_bh(&sc->rx.rxflushlock);
-}
-
-int ath_rx_tasklet(struct ath_softc *sc, int flush)
-{
-#define PA2DESC(_sc, _pa)                                               \
-	((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc +		\
-			     ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr)))
-
-	struct ath_buf *bf;
-	struct ath_desc *ds;
-	struct sk_buff *skb = NULL, *requeue_skb;
-	struct ieee80211_rx_status rx_status;
-	struct ath_hw *ah = sc->sc_ah;
-	struct ieee80211_hdr *hdr;
-	int hdrlen, padsize, retval;
-	bool decrypt_error = false;
-	u8 keyix;
-	__le16 fc;
-
-	spin_lock_bh(&sc->rx.rxbuflock);
-
-	do {
-		/* If handling rx interrupt and flush is in progress => exit */
-		if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
-			break;
-
-		if (list_empty(&sc->rx.rxbuf)) {
-			sc->rx.rxlink = NULL;
-			break;
-		}
-
-		bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
-		ds = bf->bf_desc;
-
-		/*
-		 * Must provide the virtual address of the current
-		 * descriptor, the physical address, and the virtual
-		 * address of the next descriptor in the h/w chain.
-		 * This allows the HAL to look ahead to see if the
-		 * hardware is done with a descriptor by checking the
-		 * done bit in the following descriptor and the address
-		 * of the current descriptor the DMA engine is working
-		 * on.  All this is necessary because of our use of
-		 * a self-linked list to avoid rx overruns.
-		 */
-		retval = ath9k_hw_rxprocdesc(ah, ds,
-					     bf->bf_daddr,
-					     PA2DESC(sc, ds->ds_link),
-					     0);
-		if (retval == -EINPROGRESS) {
-			struct ath_buf *tbf;
-			struct ath_desc *tds;
-
-			if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
-				sc->rx.rxlink = NULL;
-				break;
-			}
-
-			tbf = list_entry(bf->list.next, struct ath_buf, list);
-
-			/*
-			 * On some hardware the descriptor status words could
-			 * get corrupted, including the done bit. Because of
-			 * this, check if the next descriptor's done bit is
-			 * set or not.
-			 *
-			 * If the next descriptor's done bit is set, the current
-			 * descriptor has been corrupted. Force s/w to discard
-			 * this descriptor and continue...
-			 */
-
-			tds = tbf->bf_desc;
-			retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
-					     PA2DESC(sc, tds->ds_link), 0);
-			if (retval == -EINPROGRESS) {
-				break;
-			}
-		}
-
-		skb = bf->bf_mpdu;
-		if (!skb)
-			continue;
-
-		/*
-		 * Synchronize the DMA transfer with CPU before
-		 * 1. accessing the frame
-		 * 2. requeueing the same buffer to h/w
-		 */
-		dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
-				sc->rx.bufsize,
-				DMA_FROM_DEVICE);
-
-		/*
-		 * If we're asked to flush receive queue, directly
-		 * chain it back at the queue without processing it.
-		 */
-		if (flush)
-			goto requeue;
-
-		if (!ds->ds_rxstat.rs_datalen)
-			goto requeue;
-
-		/* The status portion of the descriptor could get corrupted. */
-		if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen)
-			goto requeue;
-
-		if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
-			goto requeue;
-
-		/* Ensure we always have an skb to requeue once we are done
-		 * processing the current buffer's skb */
-		requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC);
-
-		/* If there is no memory we ignore the current RX'd frame,
-		 * tell hardware it can give us a new frame using the old
-		 * skb and put it at the tail of the sc->rx.rxbuf list for
-		 * processing. */
-		if (!requeue_skb)
-			goto requeue;
-
-		/* Unmap the frame */
-		dma_unmap_single(sc->dev, bf->bf_buf_addr,
-				 sc->rx.bufsize,
-				 DMA_FROM_DEVICE);
-
-		skb_put(skb, ds->ds_rxstat.rs_datalen);
-		skb->protocol = cpu_to_be16(ETH_P_CONTROL);
-
-		/* see if any padding is done by the hw and remove it */
-		hdr = (struct ieee80211_hdr *)skb->data;
-		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-		fc = hdr->frame_control;
-
-		/* The MAC header is padded to have 32-bit boundary if the
-		 * packet payload is non-zero. The general calculation for
-		 * padsize would take into account odd header lengths:
-		 * padsize = (4 - hdrlen % 4) % 4; However, since only
-		 * even-length headers are used, padding can only be 0 or 2
-		 * bytes and we can optimize this a bit. In addition, we must
-		 * not try to remove padding from short control frames that do
-		 * not have payload. */
-		padsize = hdrlen & 3;
-		if (padsize && hdrlen >= 24) {
-			memmove(skb->data + padsize, skb->data, hdrlen);
-			skb_pull(skb, padsize);
-		}
-
-		keyix = ds->ds_rxstat.rs_keyix;
-
-		if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
-			rx_status.flag |= RX_FLAG_DECRYPTED;
-		} else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
-			   && !decrypt_error && skb->len >= hdrlen + 4) {
-			keyix = skb->data[hdrlen + 3] >> 6;
-
-			if (test_bit(keyix, sc->keymap))
-				rx_status.flag |= RX_FLAG_DECRYPTED;
-		}
-		if (ah->sw_mgmt_crypto &&
-		    (rx_status.flag & RX_FLAG_DECRYPTED) &&
-		    ieee80211_is_mgmt(hdr->frame_control)) {
-			/* Use software decrypt for management frames. */
-			rx_status.flag &= ~RX_FLAG_DECRYPTED;
-		}
-
-		/* Send the frame to mac80211 */
-		if (hdr->addr1[5] & 0x01) {
-			int i;
-			/*
-			 * Deliver broadcast/multicast frames to all suitable
-			 * virtual wiphys.
-			 */
-			/* TODO: filter based on channel configuration */
-			for (i = 0; i < sc->num_sec_wiphy; i++) {
-				struct ath_wiphy *aphy = sc->sec_wiphy[i];
-				struct sk_buff *nskb;
-				if (aphy == NULL)
-					continue;
-				nskb = skb_copy(skb, GFP_ATOMIC);
-				if (nskb)
-					__ieee80211_rx(aphy->hw, nskb,
-						       &rx_status);
-			}
-			__ieee80211_rx(sc->hw, skb, &rx_status);
-		} else {
-			/* Deliver unicast frames based on receiver address */
-			__ieee80211_rx(ath_get_virt_hw(sc, hdr), skb,
-				       &rx_status);
-		}
-
-		/* We will now give hardware our shiny new allocated skb */
-		bf->bf_mpdu = requeue_skb;
-		bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
-					 sc->rx.bufsize,
-					 DMA_FROM_DEVICE);
-		if (unlikely(dma_mapping_error(sc->dev,
-			  bf->bf_buf_addr))) {
-			dev_kfree_skb_any(requeue_skb);
-			bf->bf_mpdu = NULL;
-			DPRINTF(sc, ATH_DBG_CONFIG,
-				"dma_mapping_error() on RX\n");
-			break;
-		}
-		bf->bf_dmacontext = bf->bf_buf_addr;
-
-		/*
-		 * change the default rx antenna if rx diversity chooses the
-		 * other antenna 3 times in a row.
-		 */
-		if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
-			if (++sc->rx.rxotherant >= 3)
-				ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
-		} else {
-			sc->rx.rxotherant = 0;
-		}
-
-		if (ieee80211_is_beacon(fc) &&
-				(sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) {
-			sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
-			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
-		}
-requeue:
-		list_move_tail(&bf->list, &sc->rx.rxbuf);
-		ath_rx_buf_link(sc, bf);
-	} while (1);
-
-	spin_unlock_bh(&sc->rx.rxbuflock);
-
-	return 0;
-#undef PA2DESC
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/regd.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/regd.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/regd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/regd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,519 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include "ath9k.h"
-#include "regd_common.h"
-
-/*
- * This is a set of common rules used by our world regulatory domains.
- * We have 12 world regulatory domains. To save space we consolidate
- * the regulatory domains in 5 structures by frequency and change
- * the flags on our reg_notifier() on a case by case basis.
- */
-
-/* Only these channels all allow active scan on all world regulatory domains */
-#define ATH9K_2GHZ_CH01_11	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
-
-/* We enable active scan on these a case by case basis by regulatory domain */
-#define ATH9K_2GHZ_CH12_13	REG_RULE(2467-10, 2472+10, 40, 0, 20,\
-					NL80211_RRF_PASSIVE_SCAN)
-#define ATH9K_2GHZ_CH14		REG_RULE(2484-10, 2484+10, 40, 0, 20,\
-				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
-
-/* We allow IBSS on these on a case by case basis by regulatory domain */
-#define ATH9K_5GHZ_5150_5350	REG_RULE(5150-10, 5350+10, 40, 0, 30,\
-				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
-#define ATH9K_5GHZ_5470_5850	REG_RULE(5470-10, 5850+10, 40, 0, 30,\
-				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
-#define ATH9K_5GHZ_5725_5850	REG_RULE(5725-10, 5850+10, 40, 0, 30,\
-				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
-
-#define ATH9K_2GHZ_ALL		ATH9K_2GHZ_CH01_11, \
-				ATH9K_2GHZ_CH12_13, \
-				ATH9K_2GHZ_CH14
-
-#define ATH9K_5GHZ_ALL		ATH9K_5GHZ_5150_5350, \
-				ATH9K_5GHZ_5470_5850
-/* This one skips what we call "mid band" */
-#define ATH9K_5GHZ_NO_MIDBAND	ATH9K_5GHZ_5150_5350, \
-				ATH9K_5GHZ_5725_5850
-
-/* Can be used for:
- * 0x60, 0x61, 0x62 */
-static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = {
-	.n_reg_rules = 5,
-	.alpha2 =  "99",
-	.reg_rules = {
-		ATH9K_2GHZ_ALL,
-		ATH9K_5GHZ_ALL,
-	}
-};
-
-/* Can be used by 0x63 and 0x65 */
-static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = {
-	.n_reg_rules = 4,
-	.alpha2 =  "99",
-	.reg_rules = {
-		ATH9K_2GHZ_CH01_11,
-		ATH9K_2GHZ_CH12_13,
-		ATH9K_5GHZ_NO_MIDBAND,
-	}
-};
-
-/* Can be used by 0x64 only */
-static const struct ieee80211_regdomain ath9k_world_regdom_64 = {
-	.n_reg_rules = 3,
-	.alpha2 =  "99",
-	.reg_rules = {
-		ATH9K_2GHZ_CH01_11,
-		ATH9K_5GHZ_NO_MIDBAND,
-	}
-};
-
-/* Can be used by 0x66 and 0x69 */
-static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = {
-	.n_reg_rules = 3,
-	.alpha2 =  "99",
-	.reg_rules = {
-		ATH9K_2GHZ_CH01_11,
-		ATH9K_5GHZ_ALL,
-	}
-};
-
-/* Can be used by 0x67, 0x6A and 0x68 */
-static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = {
-	.n_reg_rules = 4,
-	.alpha2 =  "99",
-	.reg_rules = {
-		ATH9K_2GHZ_CH01_11,
-		ATH9K_2GHZ_CH12_13,
-		ATH9K_5GHZ_ALL,
-	}
-};
-
-static inline bool is_wwr_sku(u16 regd)
-{
-	return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
-		(regd == WORLD);
-}
-
-static u16 ath9k_regd_get_eepromRD(struct ath_hw *ah)
-{
-	return ah->regulatory.current_rd & ~WORLDWIDE_ROAMING_FLAG;
-}
-
-bool ath9k_is_world_regd(struct ath_hw *ah)
-{
-	return is_wwr_sku(ath9k_regd_get_eepromRD(ah));
-}
-
-const struct ieee80211_regdomain *ath9k_default_world_regdomain(void)
-{
-	/* this is the most restrictive */
-	return &ath9k_world_regdom_64;
-}
-
-const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah)
-{
-	switch (ah->regulatory.regpair->regDmnEnum) {
-	case 0x60:
-	case 0x61:
-	case 0x62:
-		return &ath9k_world_regdom_60_61_62;
-	case 0x63:
-	case 0x65:
-		return &ath9k_world_regdom_63_65;
-	case 0x64:
-		return &ath9k_world_regdom_64;
-	case 0x66:
-	case 0x69:
-		return &ath9k_world_regdom_66_69;
-	case 0x67:
-	case 0x68:
-	case 0x6A:
-		return &ath9k_world_regdom_67_68_6A;
-	default:
-		WARN_ON(1);
-		return ath9k_default_world_regdomain();
-	}
-}
-
-/* Frequency is one where radar detection is required */
-static bool ath9k_is_radar_freq(u16 center_freq)
-{
-	return (center_freq >= 5260 && center_freq <= 5700);
-}
-
-/*
- * N.B: These exception rules do not apply radar freqs.
- *
- * - We enable adhoc (or beaconing) if allowed by 11d
- * - We enable active scan if the channel is allowed by 11d
- * - If no country IE has been processed and a we determine we have
- *   received a beacon on a channel we can enable active scan and
- *   adhoc (or beaconing).
- */
-static void ath9k_reg_apply_beaconing_flags(
-	struct wiphy *wiphy,
-	enum nl80211_reg_initiator initiator)
-{
-	enum ieee80211_band band;
-	struct ieee80211_supported_band *sband;
-	const struct ieee80211_reg_rule *reg_rule;
-	struct ieee80211_channel *ch;
-	unsigned int i;
-	u32 bandwidth = 0;
-	int r;
-
-	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-
-		if (!wiphy->bands[band])
-			continue;
-
-		sband = wiphy->bands[band];
-
-		for (i = 0; i < sband->n_channels; i++) {
-
-			ch = &sband->channels[i];
-
-			if (ath9k_is_radar_freq(ch->center_freq) ||
-			    (ch->flags & IEEE80211_CHAN_RADAR))
-				continue;
-
-			if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-				r = freq_reg_info(wiphy, ch->center_freq,
-					&bandwidth, &reg_rule);
-				if (r)
-					continue;
-				/*
-				 * If 11d had a rule for this channel ensure
-				 * we enable adhoc/beaconing if it allows us to
-				 * use it. Note that we would have disabled it
-				 * by applying our static world regdomain by
-				 * default during init, prior to calling our
-				 * regulatory_hint().
-				 */
-				if (!(reg_rule->flags &
-				    NL80211_RRF_NO_IBSS))
-					ch->flags &=
-					  ~IEEE80211_CHAN_NO_IBSS;
-				if (!(reg_rule->flags &
-				    NL80211_RRF_PASSIVE_SCAN))
-					ch->flags &=
-					  ~IEEE80211_CHAN_PASSIVE_SCAN;
-			} else {
-				if (ch->beacon_found)
-					ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
-					  IEEE80211_CHAN_PASSIVE_SCAN);
-			}
-		}
-	}
-
-}
-
-/* Allows active scan scan on Ch 12 and 13 */
-static void ath9k_reg_apply_active_scan_flags(
-	struct wiphy *wiphy,
-	enum nl80211_reg_initiator initiator)
-{
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_channel *ch;
-	const struct ieee80211_reg_rule *reg_rule;
-	u32 bandwidth = 0;
-	int r;
-
-	sband = wiphy->bands[IEEE80211_BAND_2GHZ];
-
-	/*
-	 * If no country IE has been received always enable active scan
-	 * on these channels. This is only done for specific regulatory SKUs
-	 */
-	if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-		ch = &sband->channels[11]; /* CH 12 */
-		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-		ch = &sband->channels[12]; /* CH 13 */
-		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-		return;
-	}
-
-	/*
-	 * If a country IE has been recieved check its rule for this
-	 * channel first before enabling active scan. The passive scan
-	 * would have been enforced by the initial processing of our
-	 * custom regulatory domain.
-	 */
-
-	ch = &sband->channels[11]; /* CH 12 */
-	r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule);
-	if (!r) {
-		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-	}
-
-	ch = &sband->channels[12]; /* CH 13 */
-	r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule);
-	if (!r) {
-		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-	}
-}
-
-/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
-void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
-{
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_channel *ch;
-	unsigned int i;
-
-	if (!wiphy->bands[IEEE80211_BAND_5GHZ])
-		return;
-
-	sband = wiphy->bands[IEEE80211_BAND_5GHZ];
-
-	for (i = 0; i < sband->n_channels; i++) {
-		ch = &sband->channels[i];
-		if (!ath9k_is_radar_freq(ch->center_freq))
-			continue;
-		/* We always enable radar detection/DFS on this
-		 * frequency range. Additionally we also apply on
-		 * this frequency range:
-		 * - If STA mode does not yet have DFS supports disable
-		 *   active scanning
-		 * - If adhoc mode does not support DFS yet then
-		 *   disable adhoc in the frequency.
-		 * - If AP mode does not yet support radar detection/DFS
-		 *   do not allow AP mode
-		 */
-		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
-			ch->flags |= IEEE80211_CHAN_RADAR |
-				     IEEE80211_CHAN_NO_IBSS |
-				     IEEE80211_CHAN_PASSIVE_SCAN;
-	}
-}
-
-void ath9k_reg_apply_world_flags(struct wiphy *wiphy,
-				 enum nl80211_reg_initiator initiator)
-{
-	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_hw *ah = sc->sc_ah;
-
-	switch (ah->regulatory.regpair->regDmnEnum) {
-	case 0x60:
-	case 0x63:
-	case 0x66:
-	case 0x67:
-		ath9k_reg_apply_beaconing_flags(wiphy, initiator);
-		break;
-	case 0x68:
-		ath9k_reg_apply_beaconing_flags(wiphy, initiator);
-		ath9k_reg_apply_active_scan_flags(wiphy, initiator);
-		break;
-	}
-	return;
-}
-
-int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
-{
-	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
-	/* We always apply this */
-	ath9k_reg_apply_radar_flags(wiphy);
-
-	switch (request->initiator) {
-	case NL80211_REGDOM_SET_BY_DRIVER:
-	case NL80211_REGDOM_SET_BY_CORE:
-	case NL80211_REGDOM_SET_BY_USER:
-		break;
-	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
-		if (ath9k_is_world_regd(sc->sc_ah))
-			ath9k_reg_apply_world_flags(wiphy, request->initiator);
-		break;
-	}
-
-	return 0;
-}
-
-bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah)
-{
-	u16 rd = ath9k_regd_get_eepromRD(ah);
-	int i;
-
-	if (rd & COUNTRY_ERD_FLAG) {
-		/* EEPROM value is a country code */
-		u16 cc = rd & ~COUNTRY_ERD_FLAG;
-		for (i = 0; i < ARRAY_SIZE(allCountries); i++)
-			if (allCountries[i].countryCode == cc)
-				return true;
-	} else {
-		/* EEPROM value is a regpair value */
-		for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
-			if (regDomainPairs[i].regDmnEnum == rd)
-				return true;
-	}
-	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-		 "invalid regulatory domain/country code 0x%x\n", rd);
-	return false;
-}
-
-/* EEPROM country code to regpair mapping */
-static struct country_code_to_enum_rd*
-ath9k_regd_find_country(u16 countryCode)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
-		if (allCountries[i].countryCode == countryCode)
-			return &allCountries[i];
-	}
-	return NULL;
-}
-
-/* EEPROM rd code to regpair mapping */
-static struct country_code_to_enum_rd*
-ath9k_regd_find_country_by_rd(int regdmn)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
-		if (allCountries[i].regDmnEnum == regdmn)
-			return &allCountries[i];
-	}
-	return NULL;
-}
-
-/* Returns the map of the EEPROM set RD to a country code */
-static u16 ath9k_regd_get_default_country(u16 rd)
-{
-	if (rd & COUNTRY_ERD_FLAG) {
-		struct country_code_to_enum_rd *country = NULL;
-		u16 cc = rd & ~COUNTRY_ERD_FLAG;
-
-		country = ath9k_regd_find_country(cc);
-		if (country != NULL)
-			return cc;
-	}
-
-	return CTRY_DEFAULT;
-}
-
-static struct reg_dmn_pair_mapping*
-ath9k_get_regpair(int regdmn)
-{
-	int i;
-
-	if (regdmn == NO_ENUMRD)
-		return NULL;
-	for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
-		if (regDomainPairs[i].regDmnEnum == regdmn)
-			return &regDomainPairs[i];
-	}
-	return NULL;
-}
-
-int ath9k_regd_init(struct ath_hw *ah)
-{
-	struct country_code_to_enum_rd *country = NULL;
-	u16 regdmn;
-
-	if (!ath9k_regd_is_eeprom_valid(ah)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-			"Invalid EEPROM contents\n");
-		return -EINVAL;
-	}
-
-	regdmn = ath9k_regd_get_eepromRD(ah);
-	ah->regulatory.country_code = ath9k_regd_get_default_country(regdmn);
-
-	if (ah->regulatory.country_code == CTRY_DEFAULT &&
-	    regdmn == CTRY_DEFAULT)
-		ah->regulatory.country_code = CTRY_UNITED_STATES;
-
-	if (ah->regulatory.country_code == CTRY_DEFAULT) {
-		country = NULL;
-	} else {
-		country = ath9k_regd_find_country(ah->regulatory.country_code);
-		if (country == NULL) {
-			DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-				"Country is NULL!!!!, cc= %d\n",
-				ah->regulatory.country_code);
-			return -EINVAL;
-		} else
-			regdmn = country->regDmnEnum;
-	}
-
-	ah->regulatory.regpair = ath9k_get_regpair(regdmn);
-
-	if (!ah->regulatory.regpair) {
-		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-			"No regulatory domain pair found, cannot continue\n");
-		return -EINVAL;
-	}
-
-	if (!country)
-		country = ath9k_regd_find_country_by_rd(regdmn);
-
-	if (country) {
-		ah->regulatory.alpha2[0] = country->isoName[0];
-		ah->regulatory.alpha2[1] = country->isoName[1];
-	} else {
-		ah->regulatory.alpha2[0] = '0';
-		ah->regulatory.alpha2[1] = '0';
-	}
-
-	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-		"Country alpha2 being used: %c%c\n"
-		"Regulatory.Regpair detected: 0x%0x\n",
-		ah->regulatory.alpha2[0], ah->regulatory.alpha2[1],
-		ah->regulatory.regpair->regDmnEnum);
-
-	return 0;
-}
-
-u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	u32 ctl = NO_CTL;
-
-	if (!ah->regulatory.regpair ||
-	    (ah->regulatory.country_code == CTRY_DEFAULT &&
-	     is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) {
-		if (IS_CHAN_B(chan))
-			ctl = SD_NO_CTL | CTL_11B;
-		else if (IS_CHAN_G(chan))
-			ctl = SD_NO_CTL | CTL_11G;
-		else
-			ctl = SD_NO_CTL | CTL_11A;
-		return ctl;
-	}
-
-	if (IS_CHAN_B(chan))
-		ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11B;
-	else if (IS_CHAN_G(chan))
-		ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11G;
-	else
-		ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11A;
-
-	return ctl;
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/regd_common.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/regd_common.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/regd_common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/regd_common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,473 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef REGD_COMMON_H
-#define REGD_COMMON_H
-
-enum EnumRd {
-	NO_ENUMRD = 0x00,
-	NULL1_WORLD = 0x03,
-	NULL1_ETSIB = 0x07,
-	NULL1_ETSIC = 0x08,
-	FCC1_FCCA = 0x10,
-	FCC1_WORLD = 0x11,
-	FCC4_FCCA = 0x12,
-	FCC5_FCCA = 0x13,
-	FCC6_FCCA = 0x14,
-
-	FCC2_FCCA = 0x20,
-	FCC2_WORLD = 0x21,
-	FCC2_ETSIC = 0x22,
-	FCC6_WORLD = 0x23,
-	FRANCE_RES = 0x31,
-	FCC3_FCCA = 0x3A,
-	FCC3_WORLD = 0x3B,
-
-	ETSI1_WORLD = 0x37,
-	ETSI3_ETSIA = 0x32,
-	ETSI2_WORLD = 0x35,
-	ETSI3_WORLD = 0x36,
-	ETSI4_WORLD = 0x30,
-	ETSI4_ETSIC = 0x38,
-	ETSI5_WORLD = 0x39,
-	ETSI6_WORLD = 0x34,
-	ETSI_RESERVED = 0x33,
-
-	MKK1_MKKA = 0x40,
-	MKK1_MKKB = 0x41,
-	APL4_WORLD = 0x42,
-	MKK2_MKKA = 0x43,
-	APL_RESERVED = 0x44,
-	APL2_WORLD = 0x45,
-	APL2_APLC = 0x46,
-	APL3_WORLD = 0x47,
-	MKK1_FCCA = 0x48,
-	APL2_APLD = 0x49,
-	MKK1_MKKA1 = 0x4A,
-	MKK1_MKKA2 = 0x4B,
-	MKK1_MKKC = 0x4C,
-
-	APL3_FCCA = 0x50,
-	APL1_WORLD = 0x52,
-	APL1_FCCA = 0x53,
-	APL1_APLA = 0x54,
-	APL1_ETSIC = 0x55,
-	APL2_ETSIC = 0x56,
-	APL5_WORLD = 0x58,
-	APL6_WORLD = 0x5B,
-	APL7_FCCA = 0x5C,
-	APL8_WORLD = 0x5D,
-	APL9_WORLD = 0x5E,
-
-	WOR0_WORLD = 0x60,
-	WOR1_WORLD = 0x61,
-	WOR2_WORLD = 0x62,
-	WOR3_WORLD = 0x63,
-	WOR4_WORLD = 0x64,
-	WOR5_ETSIC = 0x65,
-
-	WOR01_WORLD = 0x66,
-	WOR02_WORLD = 0x67,
-	EU1_WORLD = 0x68,
-
-	WOR9_WORLD = 0x69,
-	WORA_WORLD = 0x6A,
-	WORB_WORLD = 0x6B,
-
-	MKK3_MKKB = 0x80,
-	MKK3_MKKA2 = 0x81,
-	MKK3_MKKC = 0x82,
-
-	MKK4_MKKB = 0x83,
-	MKK4_MKKA2 = 0x84,
-	MKK4_MKKC = 0x85,
-
-	MKK5_MKKB = 0x86,
-	MKK5_MKKA2 = 0x87,
-	MKK5_MKKC = 0x88,
-
-	MKK6_MKKB = 0x89,
-	MKK6_MKKA2 = 0x8A,
-	MKK6_MKKC = 0x8B,
-
-	MKK7_MKKB = 0x8C,
-	MKK7_MKKA2 = 0x8D,
-	MKK7_MKKC = 0x8E,
-
-	MKK8_MKKB = 0x8F,
-	MKK8_MKKA2 = 0x90,
-	MKK8_MKKC = 0x91,
-
-	MKK14_MKKA1 = 0x92,
-	MKK15_MKKA1 = 0x93,
-
-	MKK10_FCCA = 0xD0,
-	MKK10_MKKA1 = 0xD1,
-	MKK10_MKKC = 0xD2,
-	MKK10_MKKA2 = 0xD3,
-
-	MKK11_MKKA = 0xD4,
-	MKK11_FCCA = 0xD5,
-	MKK11_MKKA1 = 0xD6,
-	MKK11_MKKC = 0xD7,
-	MKK11_MKKA2 = 0xD8,
-
-	MKK12_MKKA = 0xD9,
-	MKK12_FCCA = 0xDA,
-	MKK12_MKKA1 = 0xDB,
-	MKK12_MKKC = 0xDC,
-	MKK12_MKKA2 = 0xDD,
-
-	MKK13_MKKB = 0xDE,
-
-	MKK3_MKKA = 0xF0,
-	MKK3_MKKA1 = 0xF1,
-	MKK3_FCCA = 0xF2,
-	MKK4_MKKA = 0xF3,
-	MKK4_MKKA1 = 0xF4,
-	MKK4_FCCA = 0xF5,
-	MKK9_MKKA = 0xF6,
-	MKK10_MKKA = 0xF7,
-	MKK6_MKKA1 = 0xF8,
-	MKK6_FCCA = 0xF9,
-	MKK7_MKKA1 = 0xFA,
-	MKK7_FCCA = 0xFB,
-	MKK9_FCCA = 0xFC,
-	MKK9_MKKA1 = 0xFD,
-	MKK9_MKKC = 0xFE,
-	MKK9_MKKA2 = 0xFF,
-
-	WORLD = 0x0199,
-	DEBUG_REG_DMN = 0x01ff,
-};
-
-enum ctl_group {
-	CTL_FCC = 0x10,
-	CTL_MKK = 0x40,
-	CTL_ETSI = 0x30,
-};
-
-/* Regpair to CTL band mapping */
-static struct reg_dmn_pair_mapping regDomainPairs[] = {
-	/* regpair, 5 GHz CTL, 2 GHz CTL */
-	{NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN},
-	{NULL1_WORLD, NO_CTL, CTL_ETSI},
-	{NULL1_ETSIB, NO_CTL, CTL_ETSI},
-	{NULL1_ETSIC, NO_CTL, CTL_ETSI},
-
-	{FCC2_FCCA, CTL_FCC, CTL_FCC},
-	{FCC2_WORLD, CTL_FCC, CTL_ETSI},
-	{FCC2_ETSIC, CTL_FCC, CTL_ETSI},
-	{FCC3_FCCA, CTL_FCC, CTL_FCC},
-	{FCC3_WORLD, CTL_FCC, CTL_ETSI},
-	{FCC4_FCCA, CTL_FCC, CTL_FCC},
-	{FCC5_FCCA, CTL_FCC, CTL_FCC},
-	{FCC6_FCCA, CTL_FCC, CTL_FCC},
-	{FCC6_WORLD, CTL_FCC, CTL_ETSI},
-
-	{ETSI1_WORLD, CTL_ETSI, CTL_ETSI},
-	{ETSI2_WORLD, CTL_ETSI, CTL_ETSI},
-	{ETSI3_WORLD, CTL_ETSI, CTL_ETSI},
-	{ETSI4_WORLD, CTL_ETSI, CTL_ETSI},
-	{ETSI5_WORLD, CTL_ETSI, CTL_ETSI},
-	{ETSI6_WORLD, CTL_ETSI, CTL_ETSI},
-
-	/* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */
-	{ETSI3_ETSIA, CTL_ETSI, CTL_ETSI},
-	{FRANCE_RES, CTL_ETSI, CTL_ETSI},
-
-	{FCC1_WORLD, CTL_FCC, CTL_ETSI},
-	{FCC1_FCCA, CTL_FCC, CTL_FCC},
-	{APL1_WORLD, CTL_FCC, CTL_ETSI},
-	{APL2_WORLD, CTL_FCC, CTL_ETSI},
-	{APL3_WORLD, CTL_FCC, CTL_ETSI},
-	{APL4_WORLD, CTL_FCC, CTL_ETSI},
-	{APL5_WORLD, CTL_FCC, CTL_ETSI},
-	{APL6_WORLD, CTL_ETSI, CTL_ETSI},
-	{APL8_WORLD, CTL_ETSI, CTL_ETSI},
-	{APL9_WORLD, CTL_ETSI, CTL_ETSI},
-
-	{APL3_FCCA, CTL_FCC, CTL_FCC},
-	{APL1_ETSIC, CTL_FCC, CTL_ETSI},
-	{APL2_ETSIC, CTL_FCC, CTL_ETSI},
-	{APL2_APLD, CTL_FCC, NO_CTL},
-
-	{MKK1_MKKA, CTL_MKK, CTL_MKK},
-	{MKK1_MKKB, CTL_MKK, CTL_MKK},
-	{MKK1_FCCA, CTL_MKK, CTL_FCC},
-	{MKK1_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK1_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK1_MKKC, CTL_MKK, CTL_MKK},
-
-	{MKK2_MKKA, CTL_MKK, CTL_MKK},
-	{MKK3_MKKA, CTL_MKK, CTL_MKK},
-	{MKK3_MKKB, CTL_MKK, CTL_MKK},
-	{MKK3_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK3_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK3_MKKC, CTL_MKK, CTL_MKK},
-	{MKK3_FCCA, CTL_MKK, CTL_FCC},
-
-	{MKK4_MKKA, CTL_MKK, CTL_MKK},
-	{MKK4_MKKB, CTL_MKK, CTL_MKK},
-	{MKK4_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK4_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK4_MKKC, CTL_MKK, CTL_MKK},
-	{MKK4_FCCA, CTL_MKK, CTL_FCC},
-
-	{MKK5_MKKB, CTL_MKK, CTL_MKK},
-	{MKK5_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK5_MKKC, CTL_MKK, CTL_MKK},
-
-	{MKK6_MKKB, CTL_MKK, CTL_MKK},
-	{MKK6_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK6_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK6_MKKC, CTL_MKK, CTL_MKK},
-	{MKK6_FCCA, CTL_MKK, CTL_FCC},
-
-	{MKK7_MKKB, CTL_MKK, CTL_MKK},
-	{MKK7_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK7_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK7_MKKC, CTL_MKK, CTL_MKK},
-	{MKK7_FCCA, CTL_MKK, CTL_FCC},
-
-	{MKK8_MKKB, CTL_MKK, CTL_MKK},
-	{MKK8_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK8_MKKC, CTL_MKK, CTL_MKK},
-
-	{MKK9_MKKA, CTL_MKK, CTL_MKK},
-	{MKK9_FCCA, CTL_MKK, CTL_FCC},
-	{MKK9_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK9_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK9_MKKC, CTL_MKK, CTL_MKK},
-
-	{MKK10_MKKA, CTL_MKK, CTL_MKK},
-	{MKK10_FCCA, CTL_MKK, CTL_FCC},
-	{MKK10_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK10_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK10_MKKC, CTL_MKK, CTL_MKK},
-
-	{MKK11_MKKA, CTL_MKK, CTL_MKK},
-	{MKK11_FCCA, CTL_MKK, CTL_FCC},
-	{MKK11_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK11_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK11_MKKC, CTL_MKK, CTL_MKK},
-
-	{MKK12_MKKA, CTL_MKK, CTL_MKK},
-	{MKK12_FCCA, CTL_MKK, CTL_FCC},
-	{MKK12_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK12_MKKA2, CTL_MKK, CTL_MKK},
-	{MKK12_MKKC, CTL_MKK, CTL_MKK},
-
-	{MKK13_MKKB, CTL_MKK, CTL_MKK},
-	{MKK14_MKKA1, CTL_MKK, CTL_MKK},
-	{MKK15_MKKA1, CTL_MKK, CTL_MKK},
-
-	{WOR0_WORLD, NO_CTL, NO_CTL},
-	{WOR1_WORLD, NO_CTL, NO_CTL},
-	{WOR2_WORLD, NO_CTL, NO_CTL},
-	{WOR3_WORLD, NO_CTL, NO_CTL},
-	{WOR4_WORLD, NO_CTL, NO_CTL},
-	{WOR5_ETSIC, NO_CTL, NO_CTL},
-	{WOR01_WORLD, NO_CTL, NO_CTL},
-	{WOR02_WORLD, NO_CTL, NO_CTL},
-	{EU1_WORLD, NO_CTL, NO_CTL},
-	{WOR9_WORLD, NO_CTL, NO_CTL},
-	{WORA_WORLD, NO_CTL, NO_CTL},
-	{WORB_WORLD, NO_CTL, NO_CTL},
-};
-
-static struct country_code_to_enum_rd allCountries[] = {
-	{CTRY_DEBUG, NO_ENUMRD, "DB"},
-	{CTRY_DEFAULT, FCC1_FCCA, "CO"},
-	{CTRY_ALBANIA, NULL1_WORLD, "AL"},
-	{CTRY_ALGERIA, NULL1_WORLD, "DZ"},
-	{CTRY_ARGENTINA, APL3_WORLD, "AR"},
-	{CTRY_ARMENIA, ETSI4_WORLD, "AM"},
-	{CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
-	{CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
-	{CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
-	{CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
-	{CTRY_BAHRAIN, APL6_WORLD, "BH"},
-	{CTRY_BELARUS, ETSI1_WORLD, "BY"},
-	{CTRY_BELGIUM, ETSI1_WORLD, "BE"},
-	{CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
-	{CTRY_BELIZE, APL1_ETSIC, "BZ"},
-	{CTRY_BOLIVIA, APL1_ETSIC, "BO"},
-	{CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"},
-	{CTRY_BRAZIL, FCC3_WORLD, "BR"},
-	{CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
-	{CTRY_BULGARIA, ETSI6_WORLD, "BG"},
-	{CTRY_CANADA, FCC2_FCCA, "CA"},
-	{CTRY_CANADA2, FCC6_FCCA, "CA"},
-	{CTRY_CHILE, APL6_WORLD, "CL"},
-	{CTRY_CHINA, APL1_WORLD, "CN"},
-	{CTRY_COLOMBIA, FCC1_FCCA, "CO"},
-	{CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
-	{CTRY_CROATIA, ETSI3_WORLD, "HR"},
-	{CTRY_CYPRUS, ETSI1_WORLD, "CY"},
-	{CTRY_CZECH, ETSI3_WORLD, "CZ"},
-	{CTRY_DENMARK, ETSI1_WORLD, "DK"},
-	{CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"},
-	{CTRY_ECUADOR, FCC1_WORLD, "EC"},
-	{CTRY_EGYPT, ETSI3_WORLD, "EG"},
-	{CTRY_EL_SALVADOR, FCC1_WORLD, "SV"},
-	{CTRY_ESTONIA, ETSI1_WORLD, "EE"},
-	{CTRY_FINLAND, ETSI1_WORLD, "FI"},
-	{CTRY_FRANCE, ETSI1_WORLD, "FR"},
-	{CTRY_GEORGIA, ETSI4_WORLD, "GE"},
-	{CTRY_GERMANY, ETSI1_WORLD, "DE"},
-	{CTRY_GREECE, ETSI1_WORLD, "GR"},
-	{CTRY_GUATEMALA, FCC1_FCCA, "GT"},
-	{CTRY_HONDURAS, NULL1_WORLD, "HN"},
-	{CTRY_HONG_KONG, FCC2_WORLD, "HK"},
-	{CTRY_HUNGARY, ETSI1_WORLD, "HU"},
-	{CTRY_ICELAND, ETSI1_WORLD, "IS"},
-	{CTRY_INDIA, APL6_WORLD, "IN"},
-	{CTRY_INDONESIA, APL1_WORLD, "ID"},
-	{CTRY_IRAN, APL1_WORLD, "IR"},
-	{CTRY_IRELAND, ETSI1_WORLD, "IE"},
-	{CTRY_ISRAEL, NULL1_WORLD, "IL"},
-	{CTRY_ITALY, ETSI1_WORLD, "IT"},
-	{CTRY_JAMAICA, ETSI1_WORLD, "JM"},
-
-	{CTRY_JAPAN, MKK1_MKKA, "JP"},
-	{CTRY_JAPAN1, MKK1_MKKB, "JP"},
-	{CTRY_JAPAN2, MKK1_FCCA, "JP"},
-	{CTRY_JAPAN3, MKK2_MKKA, "JP"},
-	{CTRY_JAPAN4, MKK1_MKKA1, "JP"},
-	{CTRY_JAPAN5, MKK1_MKKA2, "JP"},
-	{CTRY_JAPAN6, MKK1_MKKC, "JP"},
-	{CTRY_JAPAN7, MKK3_MKKB, "JP"},
-	{CTRY_JAPAN8, MKK3_MKKA2, "JP"},
-	{CTRY_JAPAN9, MKK3_MKKC, "JP"},
-	{CTRY_JAPAN10, MKK4_MKKB, "JP"},
-	{CTRY_JAPAN11, MKK4_MKKA2, "JP"},
-	{CTRY_JAPAN12, MKK4_MKKC, "JP"},
-	{CTRY_JAPAN13, MKK5_MKKB, "JP"},
-	{CTRY_JAPAN14, MKK5_MKKA2, "JP"},
-	{CTRY_JAPAN15, MKK5_MKKC, "JP"},
-	{CTRY_JAPAN16, MKK6_MKKB, "JP"},
-	{CTRY_JAPAN17, MKK6_MKKA2, "JP"},
-	{CTRY_JAPAN18, MKK6_MKKC, "JP"},
-	{CTRY_JAPAN19, MKK7_MKKB, "JP"},
-	{CTRY_JAPAN20, MKK7_MKKA2, "JP"},
-	{CTRY_JAPAN21, MKK7_MKKC, "JP"},
-	{CTRY_JAPAN22, MKK8_MKKB, "JP"},
-	{CTRY_JAPAN23, MKK8_MKKA2, "JP"},
-	{CTRY_JAPAN24, MKK8_MKKC, "JP"},
-	{CTRY_JAPAN25, MKK3_MKKA, "JP"},
-	{CTRY_JAPAN26, MKK3_MKKA1, "JP"},
-	{CTRY_JAPAN27, MKK3_FCCA, "JP"},
-	{CTRY_JAPAN28, MKK4_MKKA1, "JP"},
-	{CTRY_JAPAN29, MKK4_FCCA, "JP"},
-	{CTRY_JAPAN30, MKK6_MKKA1, "JP"},
-	{CTRY_JAPAN31, MKK6_FCCA, "JP"},
-	{CTRY_JAPAN32, MKK7_MKKA1, "JP"},
-	{CTRY_JAPAN33, MKK7_FCCA, "JP"},
-	{CTRY_JAPAN34, MKK9_MKKA, "JP"},
-	{CTRY_JAPAN35, MKK10_MKKA, "JP"},
-	{CTRY_JAPAN36, MKK4_MKKA, "JP"},
-	{CTRY_JAPAN37, MKK9_FCCA, "JP"},
-	{CTRY_JAPAN38, MKK9_MKKA1, "JP"},
-	{CTRY_JAPAN39, MKK9_MKKC, "JP"},
-	{CTRY_JAPAN40, MKK9_MKKA2, "JP"},
-	{CTRY_JAPAN41, MKK10_FCCA, "JP"},
-	{CTRY_JAPAN42, MKK10_MKKA1, "JP"},
-	{CTRY_JAPAN43, MKK10_MKKC, "JP"},
-	{CTRY_JAPAN44, MKK10_MKKA2, "JP"},
-	{CTRY_JAPAN45, MKK11_MKKA, "JP"},
-	{CTRY_JAPAN46, MKK11_FCCA, "JP"},
-	{CTRY_JAPAN47, MKK11_MKKA1, "JP"},
-	{CTRY_JAPAN48, MKK11_MKKC, "JP"},
-	{CTRY_JAPAN49, MKK11_MKKA2, "JP"},
-	{CTRY_JAPAN50, MKK12_MKKA, "JP"},
-	{CTRY_JAPAN51, MKK12_FCCA, "JP"},
-	{CTRY_JAPAN52, MKK12_MKKA1, "JP"},
-	{CTRY_JAPAN53, MKK12_MKKC, "JP"},
-	{CTRY_JAPAN54, MKK12_MKKA2, "JP"},
-	{CTRY_JAPAN57, MKK13_MKKB, "JP"},
-	{CTRY_JAPAN58, MKK14_MKKA1, "JP"},
-	{CTRY_JAPAN59, MKK15_MKKA1, "JP"},
-
-	{CTRY_JORDAN, ETSI2_WORLD, "JO"},
-	{CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"},
-	{CTRY_KOREA_NORTH, APL9_WORLD, "KP"},
-	{CTRY_KOREA_ROC, APL9_WORLD, "KR"},
-	{CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
-	{CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
-	{CTRY_KUWAIT, NULL1_WORLD, "KW"},
-	{CTRY_LATVIA, ETSI1_WORLD, "LV"},
-	{CTRY_LEBANON, NULL1_WORLD, "LB"},
-	{CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"},
-	{CTRY_LITHUANIA, ETSI1_WORLD, "LT"},
-	{CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"},
-	{CTRY_MACAU, FCC2_WORLD, "MO"},
-	{CTRY_MACEDONIA, NULL1_WORLD, "MK"},
-	{CTRY_MALAYSIA, APL8_WORLD, "MY"},
-	{CTRY_MALTA, ETSI1_WORLD, "MT"},
-	{CTRY_MEXICO, FCC1_FCCA, "MX"},
-	{CTRY_MONACO, ETSI4_WORLD, "MC"},
-	{CTRY_MOROCCO, NULL1_WORLD, "MA"},
-	{CTRY_NEPAL, APL1_WORLD, "NP"},
-	{CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
-	{CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
-	{CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
-	{CTRY_NORWAY, ETSI1_WORLD, "NO"},
-	{CTRY_OMAN, APL6_WORLD, "OM"},
-	{CTRY_PAKISTAN, NULL1_WORLD, "PK"},
-	{CTRY_PANAMA, FCC1_FCCA, "PA"},
-	{CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
-	{CTRY_PERU, APL1_WORLD, "PE"},
-	{CTRY_PHILIPPINES, APL1_WORLD, "PH"},
-	{CTRY_POLAND, ETSI1_WORLD, "PL"},
-	{CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
-	{CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
-	{CTRY_QATAR, NULL1_WORLD, "QA"},
-	{CTRY_ROMANIA, NULL1_WORLD, "RO"},
-	{CTRY_RUSSIA, NULL1_WORLD, "RU"},
-	{CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
-	{CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"},
-	{CTRY_SINGAPORE, APL6_WORLD, "SG"},
-	{CTRY_SLOVAKIA, ETSI1_WORLD, "SK"},
-	{CTRY_SLOVENIA, ETSI1_WORLD, "SI"},
-	{CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"},
-	{CTRY_SPAIN, ETSI1_WORLD, "ES"},
-	{CTRY_SRI_LANKA, FCC3_WORLD, "LK"},
-	{CTRY_SWEDEN, ETSI1_WORLD, "SE"},
-	{CTRY_SWITZERLAND, ETSI1_WORLD, "CH"},
-	{CTRY_SYRIA, NULL1_WORLD, "SY"},
-	{CTRY_TAIWAN, APL3_FCCA, "TW"},
-	{CTRY_THAILAND, NULL1_WORLD, "TH"},
-	{CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"},
-	{CTRY_TUNISIA, ETSI3_WORLD, "TN"},
-	{CTRY_TURKEY, ETSI3_WORLD, "TR"},
-	{CTRY_UKRAINE, NULL1_WORLD, "UA"},
-	{CTRY_UAE, NULL1_WORLD, "AE"},
-	{CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
-	{CTRY_UNITED_STATES, FCC3_FCCA, "US"},
-	/* This "PS" is for US public safety actually... to support this we
-	 * would need to assign new special alpha2 to CRDA db as with the world
-	 * regdomain and use another alpha2 */
-	{CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"},
-	{CTRY_URUGUAY, APL2_WORLD, "UY"},
-	{CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"},
-	{CTRY_VENEZUELA, APL2_ETSIC, "VE"},
-	{CTRY_VIET_NAM, NULL1_WORLD, "VN"},
-	{CTRY_YEMEN, NULL1_WORLD, "YE"},
-	{CTRY_ZIMBABWE, NULL1_WORLD, "ZW"},
-};
-
-#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/regd.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/regd.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/regd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/regd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef REGD_H
-#define REGD_H
-
-#define COUNTRY_ERD_FLAG        0x8000
-#define WORLDWIDE_ROAMING_FLAG  0x4000
-
-#define MULTI_DOMAIN_MASK 0xFF00
-
-#define WORLD_SKU_MASK          0x00F0
-#define WORLD_SKU_PREFIX        0x0060
-
-#define CHANNEL_HALF_BW         10
-#define CHANNEL_QUARTER_BW      5
-
-struct reg_dmn_pair_mapping {
-	u16 regDmnEnum;
-	u16 reg_5ghz_ctl;
-	u16 reg_2ghz_ctl;
-};
-
-struct country_code_to_enum_rd {
-	u16 countryCode;
-	u16 regDmnEnum;
-	const char *isoName;
-};
-
-struct ath9k_regulatory {
-	char alpha2[2];
-	u16 country_code;
-	u16 max_power_level;
-	u32 tp_scale;
-	u16 current_rd;
-	u16 current_rd_ext;
-	int16_t power_limit;
-	struct reg_dmn_pair_mapping *regpair;
-};
-
-enum CountryCode {
-	CTRY_ALBANIA = 8,
-	CTRY_ALGERIA = 12,
-	CTRY_ARGENTINA = 32,
-	CTRY_ARMENIA = 51,
-	CTRY_AUSTRALIA = 36,
-	CTRY_AUSTRIA = 40,
-	CTRY_AZERBAIJAN = 31,
-	CTRY_BAHRAIN = 48,
-	CTRY_BELARUS = 112,
-	CTRY_BELGIUM = 56,
-	CTRY_BELIZE = 84,
-	CTRY_BOLIVIA = 68,
-	CTRY_BOSNIA_HERZ = 70,
-	CTRY_BRAZIL = 76,
-	CTRY_BRUNEI_DARUSSALAM = 96,
-	CTRY_BULGARIA = 100,
-	CTRY_CANADA = 124,
-	CTRY_CHILE = 152,
-	CTRY_CHINA = 156,
-	CTRY_COLOMBIA = 170,
-	CTRY_COSTA_RICA = 188,
-	CTRY_CROATIA = 191,
-	CTRY_CYPRUS = 196,
-	CTRY_CZECH = 203,
-	CTRY_DENMARK = 208,
-	CTRY_DOMINICAN_REPUBLIC = 214,
-	CTRY_ECUADOR = 218,
-	CTRY_EGYPT = 818,
-	CTRY_EL_SALVADOR = 222,
-	CTRY_ESTONIA = 233,
-	CTRY_FAEROE_ISLANDS = 234,
-	CTRY_FINLAND = 246,
-	CTRY_FRANCE = 250,
-	CTRY_GEORGIA = 268,
-	CTRY_GERMANY = 276,
-	CTRY_GREECE = 300,
-	CTRY_GUATEMALA = 320,
-	CTRY_HONDURAS = 340,
-	CTRY_HONG_KONG = 344,
-	CTRY_HUNGARY = 348,
-	CTRY_ICELAND = 352,
-	CTRY_INDIA = 356,
-	CTRY_INDONESIA = 360,
-	CTRY_IRAN = 364,
-	CTRY_IRAQ = 368,
-	CTRY_IRELAND = 372,
-	CTRY_ISRAEL = 376,
-	CTRY_ITALY = 380,
-	CTRY_JAMAICA = 388,
-	CTRY_JAPAN = 392,
-	CTRY_JORDAN = 400,
-	CTRY_KAZAKHSTAN = 398,
-	CTRY_KENYA = 404,
-	CTRY_KOREA_NORTH = 408,
-	CTRY_KOREA_ROC = 410,
-	CTRY_KOREA_ROC2 = 411,
-	CTRY_KOREA_ROC3 = 412,
-	CTRY_KUWAIT = 414,
-	CTRY_LATVIA = 428,
-	CTRY_LEBANON = 422,
-	CTRY_LIBYA = 434,
-	CTRY_LIECHTENSTEIN = 438,
-	CTRY_LITHUANIA = 440,
-	CTRY_LUXEMBOURG = 442,
-	CTRY_MACAU = 446,
-	CTRY_MACEDONIA = 807,
-	CTRY_MALAYSIA = 458,
-	CTRY_MALTA = 470,
-	CTRY_MEXICO = 484,
-	CTRY_MONACO = 492,
-	CTRY_MOROCCO = 504,
-	CTRY_NEPAL = 524,
-	CTRY_NETHERLANDS = 528,
-	CTRY_NETHERLANDS_ANTILLES = 530,
-	CTRY_NEW_ZEALAND = 554,
-	CTRY_NICARAGUA = 558,
-	CTRY_NORWAY = 578,
-	CTRY_OMAN = 512,
-	CTRY_PAKISTAN = 586,
-	CTRY_PANAMA = 591,
-	CTRY_PAPUA_NEW_GUINEA = 598,
-	CTRY_PARAGUAY = 600,
-	CTRY_PERU = 604,
-	CTRY_PHILIPPINES = 608,
-	CTRY_POLAND = 616,
-	CTRY_PORTUGAL = 620,
-	CTRY_PUERTO_RICO = 630,
-	CTRY_QATAR = 634,
-	CTRY_ROMANIA = 642,
-	CTRY_RUSSIA = 643,
-	CTRY_SAUDI_ARABIA = 682,
-	CTRY_SERBIA_MONTENEGRO = 891,
-	CTRY_SINGAPORE = 702,
-	CTRY_SLOVAKIA = 703,
-	CTRY_SLOVENIA = 705,
-	CTRY_SOUTH_AFRICA = 710,
-	CTRY_SPAIN = 724,
-	CTRY_SRI_LANKA = 144,
-	CTRY_SWEDEN = 752,
-	CTRY_SWITZERLAND = 756,
-	CTRY_SYRIA = 760,
-	CTRY_TAIWAN = 158,
-	CTRY_THAILAND = 764,
-	CTRY_TRINIDAD_Y_TOBAGO = 780,
-	CTRY_TUNISIA = 788,
-	CTRY_TURKEY = 792,
-	CTRY_UAE = 784,
-	CTRY_UKRAINE = 804,
-	CTRY_UNITED_KINGDOM = 826,
-	CTRY_UNITED_STATES = 840,
-	CTRY_UNITED_STATES_FCC49 = 842,
-	CTRY_URUGUAY = 858,
-	CTRY_UZBEKISTAN = 860,
-	CTRY_VENEZUELA = 862,
-	CTRY_VIET_NAM = 704,
-	CTRY_YEMEN = 887,
-	CTRY_ZIMBABWE = 716,
-	CTRY_JAPAN1 = 393,
-	CTRY_JAPAN2 = 394,
-	CTRY_JAPAN3 = 395,
-	CTRY_JAPAN4 = 396,
-	CTRY_JAPAN5 = 397,
-	CTRY_JAPAN6 = 4006,
-	CTRY_JAPAN7 = 4007,
-	CTRY_JAPAN8 = 4008,
-	CTRY_JAPAN9 = 4009,
-	CTRY_JAPAN10 = 4010,
-	CTRY_JAPAN11 = 4011,
-	CTRY_JAPAN12 = 4012,
-	CTRY_JAPAN13 = 4013,
-	CTRY_JAPAN14 = 4014,
-	CTRY_JAPAN15 = 4015,
-	CTRY_JAPAN16 = 4016,
-	CTRY_JAPAN17 = 4017,
-	CTRY_JAPAN18 = 4018,
-	CTRY_JAPAN19 = 4019,
-	CTRY_JAPAN20 = 4020,
-	CTRY_JAPAN21 = 4021,
-	CTRY_JAPAN22 = 4022,
-	CTRY_JAPAN23 = 4023,
-	CTRY_JAPAN24 = 4024,
-	CTRY_JAPAN25 = 4025,
-	CTRY_JAPAN26 = 4026,
-	CTRY_JAPAN27 = 4027,
-	CTRY_JAPAN28 = 4028,
-	CTRY_JAPAN29 = 4029,
-	CTRY_JAPAN30 = 4030,
-	CTRY_JAPAN31 = 4031,
-	CTRY_JAPAN32 = 4032,
-	CTRY_JAPAN33 = 4033,
-	CTRY_JAPAN34 = 4034,
-	CTRY_JAPAN35 = 4035,
-	CTRY_JAPAN36 = 4036,
-	CTRY_JAPAN37 = 4037,
-	CTRY_JAPAN38 = 4038,
-	CTRY_JAPAN39 = 4039,
-	CTRY_JAPAN40 = 4040,
-	CTRY_JAPAN41 = 4041,
-	CTRY_JAPAN42 = 4042,
-	CTRY_JAPAN43 = 4043,
-	CTRY_JAPAN44 = 4044,
-	CTRY_JAPAN45 = 4045,
-	CTRY_JAPAN46 = 4046,
-	CTRY_JAPAN47 = 4047,
-	CTRY_JAPAN48 = 4048,
-	CTRY_JAPAN49 = 4049,
-	CTRY_JAPAN50 = 4050,
-	CTRY_JAPAN51 = 4051,
-	CTRY_JAPAN52 = 4052,
-	CTRY_JAPAN53 = 4053,
-	CTRY_JAPAN54 = 4054,
-	CTRY_JAPAN55 = 4055,
-	CTRY_JAPAN56 = 4056,
-	CTRY_JAPAN57 = 4057,
-	CTRY_JAPAN58 = 4058,
-	CTRY_JAPAN59 = 4059,
-	CTRY_AUSTRALIA2 = 5000,
-	CTRY_CANADA2 = 5001,
-	CTRY_BELGIUM2 = 5002
-};
-
-bool ath9k_is_world_regd(struct ath_hw *ah);
-const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah);
-const struct ieee80211_regdomain *ath9k_default_world_regdomain(void);
-void ath9k_reg_apply_world_flags(struct wiphy *wiphy,
-				 enum nl80211_reg_initiator initiator);
-void ath9k_reg_apply_radar_flags(struct wiphy *wiphy);
-int ath9k_regd_init(struct ath_hw *ah);
-bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah);
-u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan);
-int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
-
-#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/reg.h linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/reg.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/reg.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/reg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1511 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef REG_H
-#define REG_H
-
-#define AR_CR                0x0008
-#define AR_CR_RXE            0x00000004
-#define AR_CR_RXD            0x00000020
-#define AR_CR_SWI            0x00000040
-
-#define AR_RXDP              0x000C
-
-#define AR_CFG               0x0014
-#define AR_CFG_SWTD          0x00000001
-#define AR_CFG_SWTB          0x00000002
-#define AR_CFG_SWRD          0x00000004
-#define AR_CFG_SWRB          0x00000008
-#define AR_CFG_SWRG          0x00000010
-#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
-#define AR_CFG_PHOK          0x00000100
-#define AR_CFG_CLK_GATE_DIS  0x00000400
-#define AR_CFG_EEBS          0x00000200
-#define AR_CFG_PCI_MASTER_REQ_Q_THRESH         0x00060000
-#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S       17
-
-#define AR_MIRT              0x0020
-#define AR_MIRT_VAL          0x0000ffff
-#define AR_MIRT_VAL_S        16
-
-#define AR_IER               0x0024
-#define AR_IER_ENABLE        0x00000001
-#define AR_IER_DISABLE       0x00000000
-
-#define AR_TIMT              0x0028
-#define AR_TIMT_LAST         0x0000ffff
-#define AR_TIMT_LAST_S       0
-#define AR_TIMT_FIRST        0xffff0000
-#define AR_TIMT_FIRST_S      16
-
-#define AR_RIMT              0x002C
-#define AR_RIMT_LAST         0x0000ffff
-#define AR_RIMT_LAST_S       0
-#define AR_RIMT_FIRST        0xffff0000
-#define AR_RIMT_FIRST_S      16
-
-#define AR_DMASIZE_4B        0x00000000
-#define AR_DMASIZE_8B        0x00000001
-#define AR_DMASIZE_16B       0x00000002
-#define AR_DMASIZE_32B       0x00000003
-#define AR_DMASIZE_64B       0x00000004
-#define AR_DMASIZE_128B      0x00000005
-#define AR_DMASIZE_256B      0x00000006
-#define AR_DMASIZE_512B      0x00000007
-
-#define AR_TXCFG             0x0030
-#define AR_TXCFG_DMASZ_MASK  0x00000007
-#define AR_TXCFG_DMASZ_4B    0
-#define AR_TXCFG_DMASZ_8B    1
-#define AR_TXCFG_DMASZ_16B   2
-#define AR_TXCFG_DMASZ_32B   3
-#define AR_TXCFG_DMASZ_64B   4
-#define AR_TXCFG_DMASZ_128B  5
-#define AR_TXCFG_DMASZ_256B  6
-#define AR_TXCFG_DMASZ_512B  7
-#define AR_FTRIG             0x000003F0
-#define AR_FTRIG_S           4
-#define AR_FTRIG_IMMED       0x00000000
-#define AR_FTRIG_64B         0x00000010
-#define AR_FTRIG_128B        0x00000020
-#define AR_FTRIG_192B        0x00000030
-#define AR_FTRIG_256B        0x00000040
-#define AR_FTRIG_512B        0x00000080
-#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800
-
-#define AR_RXCFG             0x0034
-#define AR_RXCFG_CHIRP       0x00000008
-#define AR_RXCFG_ZLFDMA      0x00000010
-#define AR_RXCFG_DMASZ_MASK  0x00000007
-#define AR_RXCFG_DMASZ_4B    0
-#define AR_RXCFG_DMASZ_8B    1
-#define AR_RXCFG_DMASZ_16B   2
-#define AR_RXCFG_DMASZ_32B   3
-#define AR_RXCFG_DMASZ_64B   4
-#define AR_RXCFG_DMASZ_128B  5
-#define AR_RXCFG_DMASZ_256B  6
-#define AR_RXCFG_DMASZ_512B  7
-
-#define AR_MIBC              0x0040
-#define AR_MIBC_COW          0x00000001
-#define AR_MIBC_FMC          0x00000002
-#define AR_MIBC_CMC          0x00000004
-#define AR_MIBC_MCS          0x00000008
-
-#define AR_TOPS              0x0044
-#define AR_TOPS_MASK         0x0000FFFF
-
-#define AR_RXNPTO            0x0048
-#define AR_RXNPTO_MASK       0x000003FF
-
-#define AR_TXNPTO            0x004C
-#define AR_TXNPTO_MASK       0x000003FF
-#define AR_TXNPTO_QCU_MASK   0x000FFC00
-
-#define AR_RPGTO             0x0050
-#define AR_RPGTO_MASK        0x000003FF
-
-#define AR_RPCNT             0x0054
-#define AR_RPCNT_MASK        0x0000001F
-
-#define AR_MACMISC           0x0058
-#define AR_MACMISC_PCI_EXT_FORCE        0x00000010
-#define AR_MACMISC_DMA_OBS              0x000001E0
-#define AR_MACMISC_DMA_OBS_S            5
-#define AR_MACMISC_DMA_OBS_LINE_0       0
-#define AR_MACMISC_DMA_OBS_LINE_1       1
-#define AR_MACMISC_DMA_OBS_LINE_2       2
-#define AR_MACMISC_DMA_OBS_LINE_3       3
-#define AR_MACMISC_DMA_OBS_LINE_4       4
-#define AR_MACMISC_DMA_OBS_LINE_5       5
-#define AR_MACMISC_DMA_OBS_LINE_6       6
-#define AR_MACMISC_DMA_OBS_LINE_7       7
-#define AR_MACMISC_DMA_OBS_LINE_8       8
-#define AR_MACMISC_MISC_OBS             0x00000E00
-#define AR_MACMISC_MISC_OBS_S           9
-#define AR_MACMISC_MISC_OBS_BUS_LSB     0x00007000
-#define AR_MACMISC_MISC_OBS_BUS_LSB_S   12
-#define AR_MACMISC_MISC_OBS_BUS_MSB     0x00038000
-#define AR_MACMISC_MISC_OBS_BUS_MSB_S   15
-#define AR_MACMISC_MISC_OBS_BUS_1       1
-
-#define AR_GTXTO    0x0064
-#define AR_GTXTO_TIMEOUT_COUNTER    0x0000FFFF
-#define AR_GTXTO_TIMEOUT_LIMIT      0xFFFF0000
-#define AR_GTXTO_TIMEOUT_LIMIT_S    16
-
-#define AR_GTTM     0x0068
-#define AR_GTTM_USEC          0x00000001
-#define AR_GTTM_IGNORE_IDLE   0x00000002
-#define AR_GTTM_RESET_IDLE    0x00000004
-#define AR_GTTM_CST_USEC      0x00000008
-
-#define AR_CST         0x006C
-#define AR_CST_TIMEOUT_COUNTER    0x0000FFFF
-#define AR_CST_TIMEOUT_LIMIT      0xFFFF0000
-#define AR_CST_TIMEOUT_LIMIT_S    16
-
-#define AR_ISR               0x0080
-#define AR_ISR_RXOK          0x00000001
-#define AR_ISR_RXDESC        0x00000002
-#define AR_ISR_RXERR         0x00000004
-#define AR_ISR_RXNOPKT       0x00000008
-#define AR_ISR_RXEOL         0x00000010
-#define AR_ISR_RXORN         0x00000020
-#define AR_ISR_TXOK          0x00000040
-#define AR_ISR_TXDESC        0x00000080
-#define AR_ISR_TXERR         0x00000100
-#define AR_ISR_TXNOPKT       0x00000200
-#define AR_ISR_TXEOL         0x00000400
-#define AR_ISR_TXURN         0x00000800
-#define AR_ISR_MIB           0x00001000
-#define AR_ISR_SWI           0x00002000
-#define AR_ISR_RXPHY         0x00004000
-#define AR_ISR_RXKCM         0x00008000
-#define AR_ISR_SWBA          0x00010000
-#define AR_ISR_BRSSI         0x00020000
-#define AR_ISR_BMISS         0x00040000
-#define AR_ISR_BNR           0x00100000
-#define AR_ISR_RXCHIRP       0x00200000
-#define AR_ISR_BCNMISC       0x00800000
-#define AR_ISR_TIM           0x00800000
-#define AR_ISR_QCBROVF       0x02000000
-#define AR_ISR_QCBRURN       0x04000000
-#define AR_ISR_QTRIG         0x08000000
-#define AR_ISR_GENTMR        0x10000000
-
-#define AR_ISR_TXMINTR       0x00080000
-#define AR_ISR_RXMINTR       0x01000000
-#define AR_ISR_TXINTM        0x40000000
-#define AR_ISR_RXINTM        0x80000000
-
-#define AR_ISR_S0               0x0084
-#define AR_ISR_S0_QCU_TXOK      0x000003FF
-#define AR_ISR_S0_QCU_TXOK_S    0
-#define AR_ISR_S0_QCU_TXDESC    0x03FF0000
-#define AR_ISR_S0_QCU_TXDESC_S  16
-
-#define AR_ISR_S1              0x0088
-#define AR_ISR_S1_QCU_TXERR    0x000003FF
-#define AR_ISR_S1_QCU_TXERR_S  0
-#define AR_ISR_S1_QCU_TXEOL    0x03FF0000
-#define AR_ISR_S1_QCU_TXEOL_S  16
-
-#define AR_ISR_S2              0x008c
-#define AR_ISR_S2_QCU_TXURN    0x000003FF
-#define AR_ISR_S2_CST          0x00400000
-#define AR_ISR_S2_GTT          0x00800000
-#define AR_ISR_S2_TIM          0x01000000
-#define AR_ISR_S2_CABEND       0x02000000
-#define AR_ISR_S2_DTIMSYNC     0x04000000
-#define AR_ISR_S2_BCNTO        0x08000000
-#define AR_ISR_S2_CABTO        0x10000000
-#define AR_ISR_S2_DTIM         0x20000000
-#define AR_ISR_S2_TSFOOR       0x40000000
-#define AR_ISR_S2_TBTT_TIME    0x80000000
-
-#define AR_ISR_S3             0x0090
-#define AR_ISR_S3_QCU_QCBROVF    0x000003FF
-#define AR_ISR_S3_QCU_QCBRURN    0x03FF0000
-
-#define AR_ISR_S4              0x0094
-#define AR_ISR_S4_QCU_QTRIG    0x000003FF
-#define AR_ISR_S4_RESV0        0xFFFFFC00
-
-#define AR_ISR_S5                   0x0098
-#define AR_ISR_S5_TIMER_TRIG        0x000000FF
-#define AR_ISR_S5_TIMER_THRESH      0x0007FE00
-#define AR_ISR_S5_TIM_TIMER         0x00000010
-#define AR_ISR_S5_DTIM_TIMER        0x00000020
-#define AR_ISR_S5_S                 0x00d8
-#define AR_IMR_S5                   0x00b8
-#define AR_IMR_S5_TIM_TIMER         0x00000010
-#define AR_IMR_S5_DTIM_TIMER        0x00000020
-
-
-#define AR_IMR               0x00a0
-#define AR_IMR_RXOK          0x00000001
-#define AR_IMR_RXDESC        0x00000002
-#define AR_IMR_RXERR         0x00000004
-#define AR_IMR_RXNOPKT       0x00000008
-#define AR_IMR_RXEOL         0x00000010
-#define AR_IMR_RXORN         0x00000020
-#define AR_IMR_TXOK          0x00000040
-#define AR_IMR_TXDESC        0x00000080
-#define AR_IMR_TXERR         0x00000100
-#define AR_IMR_TXNOPKT       0x00000200
-#define AR_IMR_TXEOL         0x00000400
-#define AR_IMR_TXURN         0x00000800
-#define AR_IMR_MIB           0x00001000
-#define AR_IMR_SWI           0x00002000
-#define AR_IMR_RXPHY         0x00004000
-#define AR_IMR_RXKCM         0x00008000
-#define AR_IMR_SWBA          0x00010000
-#define AR_IMR_BRSSI         0x00020000
-#define AR_IMR_BMISS         0x00040000
-#define AR_IMR_BNR           0x00100000
-#define AR_IMR_RXCHIRP       0x00200000
-#define AR_IMR_BCNMISC       0x00800000
-#define AR_IMR_TIM           0x00800000
-#define AR_IMR_QCBROVF       0x02000000
-#define AR_IMR_QCBRURN       0x04000000
-#define AR_IMR_QTRIG         0x08000000
-#define AR_IMR_GENTMR        0x10000000
-
-#define AR_IMR_TXMINTR       0x00080000
-#define AR_IMR_RXMINTR       0x01000000
-#define AR_IMR_TXINTM        0x40000000
-#define AR_IMR_RXINTM        0x80000000
-
-#define AR_IMR_S0               0x00a4
-#define AR_IMR_S0_QCU_TXOK      0x000003FF
-#define AR_IMR_S0_QCU_TXOK_S    0
-#define AR_IMR_S0_QCU_TXDESC    0x03FF0000
-#define AR_IMR_S0_QCU_TXDESC_S  16
-
-#define AR_IMR_S1              0x00a8
-#define AR_IMR_S1_QCU_TXERR    0x000003FF
-#define AR_IMR_S1_QCU_TXERR_S  0
-#define AR_IMR_S1_QCU_TXEOL    0x03FF0000
-#define AR_IMR_S1_QCU_TXEOL_S  16
-
-#define AR_IMR_S2              0x00ac
-#define AR_IMR_S2_QCU_TXURN    0x000003FF
-#define AR_IMR_S2_QCU_TXURN_S  0
-#define AR_IMR_S2_CST          0x00400000
-#define AR_IMR_S2_GTT          0x00800000
-#define AR_IMR_S2_TIM          0x01000000
-#define AR_IMR_S2_CABEND       0x02000000
-#define AR_IMR_S2_DTIMSYNC     0x04000000
-#define AR_IMR_S2_BCNTO        0x08000000
-#define AR_IMR_S2_CABTO        0x10000000
-#define AR_IMR_S2_DTIM         0x20000000
-#define AR_IMR_S2_TSFOOR       0x40000000
-
-#define AR_IMR_S3                0x00b0
-#define AR_IMR_S3_QCU_QCBROVF    0x000003FF
-#define AR_IMR_S3_QCU_QCBRURN    0x03FF0000
-#define AR_IMR_S3_QCU_QCBRURN_S  16
-
-#define AR_IMR_S4              0x00b4
-#define AR_IMR_S4_QCU_QTRIG    0x000003FF
-#define AR_IMR_S4_RESV0        0xFFFFFC00
-
-#define AR_IMR_S5              0x00b8
-#define AR_IMR_S5_TIMER_TRIG        0x000000FF
-#define AR_IMR_S5_TIMER_THRESH      0x0000FF00
-
-
-#define AR_ISR_RAC            0x00c0
-#define AR_ISR_S0_S           0x00c4
-#define AR_ISR_S0_QCU_TXOK      0x000003FF
-#define AR_ISR_S0_QCU_TXOK_S    0
-#define AR_ISR_S0_QCU_TXDESC    0x03FF0000
-#define AR_ISR_S0_QCU_TXDESC_S  16
-
-#define AR_ISR_S1_S           0x00c8
-#define AR_ISR_S1_QCU_TXERR    0x000003FF
-#define AR_ISR_S1_QCU_TXERR_S  0
-#define AR_ISR_S1_QCU_TXEOL    0x03FF0000
-#define AR_ISR_S1_QCU_TXEOL_S  16
-
-#define AR_ISR_S2_S           0x00cc
-#define AR_ISR_S3_S           0x00d0
-#define AR_ISR_S4_S           0x00d4
-#define AR_ISR_S5_S           0x00d8
-#define AR_DMADBG_0           0x00e0
-#define AR_DMADBG_1           0x00e4
-#define AR_DMADBG_2           0x00e8
-#define AR_DMADBG_3           0x00ec
-#define AR_DMADBG_4           0x00f0
-#define AR_DMADBG_5           0x00f4
-#define AR_DMADBG_6           0x00f8
-#define AR_DMADBG_7           0x00fc
-
-#define AR_NUM_QCU      10
-#define AR_QCU_0        0x0001
-#define AR_QCU_1        0x0002
-#define AR_QCU_2        0x0004
-#define AR_QCU_3        0x0008
-#define AR_QCU_4        0x0010
-#define AR_QCU_5        0x0020
-#define AR_QCU_6        0x0040
-#define AR_QCU_7        0x0080
-#define AR_QCU_8        0x0100
-#define AR_QCU_9        0x0200
-
-#define AR_Q0_TXDP           0x0800
-#define AR_Q1_TXDP           0x0804
-#define AR_Q2_TXDP           0x0808
-#define AR_Q3_TXDP           0x080c
-#define AR_Q4_TXDP           0x0810
-#define AR_Q5_TXDP           0x0814
-#define AR_Q6_TXDP           0x0818
-#define AR_Q7_TXDP           0x081c
-#define AR_Q8_TXDP           0x0820
-#define AR_Q9_TXDP           0x0824
-#define AR_QTXDP(_i)    (AR_Q0_TXDP + ((_i)<<2))
-
-#define AR_Q_TXE             0x0840
-#define AR_Q_TXE_M           0x000003FF
-
-#define AR_Q_TXD             0x0880
-#define AR_Q_TXD_M           0x000003FF
-
-#define AR_Q0_CBRCFG         0x08c0
-#define AR_Q1_CBRCFG         0x08c4
-#define AR_Q2_CBRCFG         0x08c8
-#define AR_Q3_CBRCFG         0x08cc
-#define AR_Q4_CBRCFG         0x08d0
-#define AR_Q5_CBRCFG         0x08d4
-#define AR_Q6_CBRCFG         0x08d8
-#define AR_Q7_CBRCFG         0x08dc
-#define AR_Q8_CBRCFG         0x08e0
-#define AR_Q9_CBRCFG         0x08e4
-#define AR_QCBRCFG(_i)      (AR_Q0_CBRCFG + ((_i)<<2))
-#define AR_Q_CBRCFG_INTERVAL     0x00FFFFFF
-#define AR_Q_CBRCFG_INTERVAL_S   0
-#define AR_Q_CBRCFG_OVF_THRESH   0xFF000000
-#define AR_Q_CBRCFG_OVF_THRESH_S 24
-
-#define AR_Q0_RDYTIMECFG         0x0900
-#define AR_Q1_RDYTIMECFG         0x0904
-#define AR_Q2_RDYTIMECFG         0x0908
-#define AR_Q3_RDYTIMECFG         0x090c
-#define AR_Q4_RDYTIMECFG         0x0910
-#define AR_Q5_RDYTIMECFG         0x0914
-#define AR_Q6_RDYTIMECFG         0x0918
-#define AR_Q7_RDYTIMECFG         0x091c
-#define AR_Q8_RDYTIMECFG         0x0920
-#define AR_Q9_RDYTIMECFG         0x0924
-#define AR_QRDYTIMECFG(_i)       (AR_Q0_RDYTIMECFG + ((_i)<<2))
-#define AR_Q_RDYTIMECFG_DURATION   0x00FFFFFF
-#define AR_Q_RDYTIMECFG_DURATION_S 0
-#define AR_Q_RDYTIMECFG_EN         0x01000000
-
-#define AR_Q_ONESHOTARM_SC       0x0940
-#define AR_Q_ONESHOTARM_SC_M     0x000003FF
-#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00
-
-#define AR_Q_ONESHOTARM_CC       0x0980
-#define AR_Q_ONESHOTARM_CC_M     0x000003FF
-#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00
-
-#define AR_Q0_MISC         0x09c0
-#define AR_Q1_MISC         0x09c4
-#define AR_Q2_MISC         0x09c8
-#define AR_Q3_MISC         0x09cc
-#define AR_Q4_MISC         0x09d0
-#define AR_Q5_MISC         0x09d4
-#define AR_Q6_MISC         0x09d8
-#define AR_Q7_MISC         0x09dc
-#define AR_Q8_MISC         0x09e0
-#define AR_Q9_MISC         0x09e4
-#define AR_QMISC(_i)       (AR_Q0_MISC + ((_i)<<2))
-#define AR_Q_MISC_FSP                     0x0000000F
-#define AR_Q_MISC_FSP_ASAP                0
-#define AR_Q_MISC_FSP_CBR                 1
-#define AR_Q_MISC_FSP_DBA_GATED           2
-#define AR_Q_MISC_FSP_TIM_GATED           3
-#define AR_Q_MISC_FSP_BEACON_SENT_GATED   4
-#define AR_Q_MISC_FSP_BEACON_RCVD_GATED   5
-#define AR_Q_MISC_ONE_SHOT_EN             0x00000010
-#define AR_Q_MISC_CBR_INCR_DIS1           0x00000020
-#define AR_Q_MISC_CBR_INCR_DIS0           0x00000040
-#define AR_Q_MISC_BEACON_USE              0x00000080
-#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN   0x00000100
-#define AR_Q_MISC_RDYTIME_EXP_POLICY      0x00000200
-#define AR_Q_MISC_RESET_CBR_EXP_CTR       0x00000400
-#define AR_Q_MISC_DCU_EARLY_TERM_REQ      0x00000800
-#define AR_Q_MISC_RESV0                   0xFFFFF000
-
-#define AR_Q0_STS         0x0a00
-#define AR_Q1_STS         0x0a04
-#define AR_Q2_STS         0x0a08
-#define AR_Q3_STS         0x0a0c
-#define AR_Q4_STS         0x0a10
-#define AR_Q5_STS         0x0a14
-#define AR_Q6_STS         0x0a18
-#define AR_Q7_STS         0x0a1c
-#define AR_Q8_STS         0x0a20
-#define AR_Q9_STS         0x0a24
-#define AR_QSTS(_i)       (AR_Q0_STS + ((_i)<<2))
-#define AR_Q_STS_PEND_FR_CNT          0x00000003
-#define AR_Q_STS_RESV0                0x000000FC
-#define AR_Q_STS_CBR_EXP_CNT          0x0000FF00
-#define AR_Q_STS_RESV1                0xFFFF0000
-
-#define AR_Q_RDYTIMESHDN    0x0a40
-#define AR_Q_RDYTIMESHDN_M  0x000003FF
-
-
-#define AR_NUM_DCU      10
-#define AR_DCU_0        0x0001
-#define AR_DCU_1        0x0002
-#define AR_DCU_2        0x0004
-#define AR_DCU_3        0x0008
-#define AR_DCU_4        0x0010
-#define AR_DCU_5        0x0020
-#define AR_DCU_6        0x0040
-#define AR_DCU_7        0x0080
-#define AR_DCU_8        0x0100
-#define AR_DCU_9        0x0200
-
-#define AR_D0_QCUMASK     0x1000
-#define AR_D1_QCUMASK     0x1004
-#define AR_D2_QCUMASK     0x1008
-#define AR_D3_QCUMASK     0x100c
-#define AR_D4_QCUMASK     0x1010
-#define AR_D5_QCUMASK     0x1014
-#define AR_D6_QCUMASK     0x1018
-#define AR_D7_QCUMASK     0x101c
-#define AR_D8_QCUMASK     0x1020
-#define AR_D9_QCUMASK     0x1024
-#define AR_DQCUMASK(_i)   (AR_D0_QCUMASK + ((_i)<<2))
-#define AR_D_QCUMASK         0x000003FF
-#define AR_D_QCUMASK_RESV0   0xFFFFFC00
-
-#define AR_D_TXBLK_CMD  0x1038
-#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i))
-
-#define AR_D0_LCL_IFS     0x1040
-#define AR_D1_LCL_IFS     0x1044
-#define AR_D2_LCL_IFS     0x1048
-#define AR_D3_LCL_IFS     0x104c
-#define AR_D4_LCL_IFS     0x1050
-#define AR_D5_LCL_IFS     0x1054
-#define AR_D6_LCL_IFS     0x1058
-#define AR_D7_LCL_IFS     0x105c
-#define AR_D8_LCL_IFS     0x1060
-#define AR_D9_LCL_IFS     0x1064
-#define AR_DLCL_IFS(_i)   (AR_D0_LCL_IFS + ((_i)<<2))
-#define AR_D_LCL_IFS_CWMIN       0x000003FF
-#define AR_D_LCL_IFS_CWMIN_S     0
-#define AR_D_LCL_IFS_CWMAX       0x000FFC00
-#define AR_D_LCL_IFS_CWMAX_S     10
-#define AR_D_LCL_IFS_AIFS        0x0FF00000
-#define AR_D_LCL_IFS_AIFS_S      20
-
-#define AR_D_LCL_IFS_RESV0    0xF0000000
-
-#define AR_D0_RETRY_LIMIT     0x1080
-#define AR_D1_RETRY_LIMIT     0x1084
-#define AR_D2_RETRY_LIMIT     0x1088
-#define AR_D3_RETRY_LIMIT     0x108c
-#define AR_D4_RETRY_LIMIT     0x1090
-#define AR_D5_RETRY_LIMIT     0x1094
-#define AR_D6_RETRY_LIMIT     0x1098
-#define AR_D7_RETRY_LIMIT     0x109c
-#define AR_D8_RETRY_LIMIT     0x10a0
-#define AR_D9_RETRY_LIMIT     0x10a4
-#define AR_DRETRY_LIMIT(_i)   (AR_D0_RETRY_LIMIT + ((_i)<<2))
-#define AR_D_RETRY_LIMIT_FR_SH       0x0000000F
-#define AR_D_RETRY_LIMIT_FR_SH_S     0
-#define AR_D_RETRY_LIMIT_STA_SH      0x00003F00
-#define AR_D_RETRY_LIMIT_STA_SH_S    8
-#define AR_D_RETRY_LIMIT_STA_LG      0x000FC000
-#define AR_D_RETRY_LIMIT_STA_LG_S    14
-#define AR_D_RETRY_LIMIT_RESV0       0xFFF00000
-
-#define AR_D0_CHNTIME     0x10c0
-#define AR_D1_CHNTIME     0x10c4
-#define AR_D2_CHNTIME     0x10c8
-#define AR_D3_CHNTIME     0x10cc
-#define AR_D4_CHNTIME     0x10d0
-#define AR_D5_CHNTIME     0x10d4
-#define AR_D6_CHNTIME     0x10d8
-#define AR_D7_CHNTIME     0x10dc
-#define AR_D8_CHNTIME     0x10e0
-#define AR_D9_CHNTIME     0x10e4
-#define AR_DCHNTIME(_i)   (AR_D0_CHNTIME + ((_i)<<2))
-#define AR_D_CHNTIME_DUR         0x000FFFFF
-#define AR_D_CHNTIME_DUR_S       0
-#define AR_D_CHNTIME_EN          0x00100000
-#define AR_D_CHNTIME_RESV0       0xFFE00000
-
-#define AR_D0_MISC        0x1100
-#define AR_D1_MISC        0x1104
-#define AR_D2_MISC        0x1108
-#define AR_D3_MISC        0x110c
-#define AR_D4_MISC        0x1110
-#define AR_D5_MISC        0x1114
-#define AR_D6_MISC        0x1118
-#define AR_D7_MISC        0x111c
-#define AR_D8_MISC        0x1120
-#define AR_D9_MISC        0x1124
-#define AR_DMISC(_i)      (AR_D0_MISC + ((_i)<<2))
-#define AR_D_MISC_BKOFF_THRESH        0x0000003F
-#define AR_D_MISC_RETRY_CNT_RESET_EN  0x00000040
-#define AR_D_MISC_CW_RESET_EN         0x00000080
-#define AR_D_MISC_FRAG_WAIT_EN        0x00000100
-#define AR_D_MISC_FRAG_BKOFF_EN       0x00000200
-#define AR_D_MISC_CW_BKOFF_EN         0x00001000
-#define AR_D_MISC_VIR_COL_HANDLING    0x0000C000
-#define AR_D_MISC_VIR_COL_HANDLING_S  14
-#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0
-#define AR_D_MISC_VIR_COL_HANDLING_IGNORE  1
-#define AR_D_MISC_BEACON_USE          0x00010000
-#define AR_D_MISC_ARB_LOCKOUT_CNTRL   0x00060000
-#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17
-#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE     0
-#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1
-#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL   2
-#define AR_D_MISC_ARB_LOCKOUT_IGNORE  0x00080000
-#define AR_D_MISC_SEQ_NUM_INCR_DIS    0x00100000
-#define AR_D_MISC_POST_FR_BKOFF_DIS   0x00200000
-#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000
-#define AR_D_MISC_BLOWN_IFS_RETRY_EN  0x00800000
-#define AR_D_MISC_RESV0               0xFF000000
-
-#define AR_D_SEQNUM      0x1140
-
-#define AR_D_GBL_IFS_SIFS         0x1030
-#define AR_D_GBL_IFS_SIFS_M       0x0000FFFF
-#define AR_D_GBL_IFS_SIFS_RESV0   0xFFFFFFFF
-
-#define AR_D_TXBLK_BASE            0x1038
-#define AR_D_TXBLK_WRITE_BITMASK    0x0000FFFF
-#define AR_D_TXBLK_WRITE_BITMASK_S  0
-#define AR_D_TXBLK_WRITE_SLICE      0x000F0000
-#define AR_D_TXBLK_WRITE_SLICE_S    16
-#define AR_D_TXBLK_WRITE_DCU        0x00F00000
-#define AR_D_TXBLK_WRITE_DCU_S      20
-#define AR_D_TXBLK_WRITE_COMMAND    0x0F000000
-#define AR_D_TXBLK_WRITE_COMMAND_S      24
-
-#define AR_D_GBL_IFS_SLOT         0x1070
-#define AR_D_GBL_IFS_SLOT_M       0x0000FFFF
-#define AR_D_GBL_IFS_SLOT_RESV0   0xFFFF0000
-
-#define AR_D_GBL_IFS_EIFS         0x10b0
-#define AR_D_GBL_IFS_EIFS_M       0x0000FFFF
-#define AR_D_GBL_IFS_EIFS_RESV0   0xFFFF0000
-
-#define AR_D_GBL_IFS_MISC        0x10f0
-#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007
-#define AR_D_GBL_IFS_MISC_TURBO_MODE            0x00000008
-#define AR_D_GBL_IFS_MISC_USEC_DURATION         0x000FFC00
-#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY       0x00300000
-#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000
-#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN    0x06000000
-#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000
-#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF        0x10000000
-
-#define AR_D_FPCTL                  0x1230
-#define AR_D_FPCTL_DCU              0x0000000F
-#define AR_D_FPCTL_DCU_S            0
-#define AR_D_FPCTL_PREFETCH_EN      0x00000010
-#define AR_D_FPCTL_BURST_PREFETCH   0x00007FE0
-#define AR_D_FPCTL_BURST_PREFETCH_S 5
-
-#define AR_D_TXPSE                 0x1270
-#define AR_D_TXPSE_CTRL            0x000003FF
-#define AR_D_TXPSE_RESV0           0x0000FC00
-#define AR_D_TXPSE_STATUS          0x00010000
-#define AR_D_TXPSE_RESV1           0xFFFE0000
-
-#define AR_D_TXSLOTMASK            0x12f0
-#define AR_D_TXSLOTMASK_NUM        0x0000000F
-
-#define AR_CFG_LED                     0x1f04
-#define AR_CFG_SCLK_RATE_IND           0x00000003
-#define AR_CFG_SCLK_RATE_IND_S         0
-#define AR_CFG_SCLK_32MHZ              0x00000000
-#define AR_CFG_SCLK_4MHZ               0x00000001
-#define AR_CFG_SCLK_1MHZ               0x00000002
-#define AR_CFG_SCLK_32KHZ              0x00000003
-#define AR_CFG_LED_BLINK_SLOW          0x00000008
-#define AR_CFG_LED_BLINK_THRESH_SEL    0x00000070
-#define AR_CFG_LED_MODE_SEL            0x00000380
-#define AR_CFG_LED_MODE_SEL_S          7
-#define AR_CFG_LED_POWER               0x00000280
-#define AR_CFG_LED_POWER_S             7
-#define AR_CFG_LED_NETWORK             0x00000300
-#define AR_CFG_LED_NETWORK_S           7
-#define AR_CFG_LED_MODE_PROP           0x0
-#define AR_CFG_LED_MODE_RPROP          0x1
-#define AR_CFG_LED_MODE_SPLIT          0x2
-#define AR_CFG_LED_MODE_RAND           0x3
-#define AR_CFG_LED_MODE_POWER_OFF      0x4
-#define AR_CFG_LED_MODE_POWER_ON       0x5
-#define AR_CFG_LED_MODE_NETWORK_OFF    0x4
-#define AR_CFG_LED_MODE_NETWORK_ON     0x6
-#define AR_CFG_LED_ASSOC_CTL           0x00000c00
-#define AR_CFG_LED_ASSOC_CTL_S         10
-#define AR_CFG_LED_ASSOC_NONE          0x0
-#define AR_CFG_LED_ASSOC_ACTIVE        0x1
-#define AR_CFG_LED_ASSOC_PENDING       0x2
-
-#define AR_CFG_LED_BLINK_SLOW          0x00000008
-#define AR_CFG_LED_BLINK_SLOW_S        3
-
-#define AR_CFG_LED_BLINK_THRESH_SEL    0x00000070
-#define AR_CFG_LED_BLINK_THRESH_SEL_S  4
-
-#define AR_MAC_SLEEP                0x1f00
-#define AR_MAC_SLEEP_MAC_AWAKE      0x00000000
-#define AR_MAC_SLEEP_MAC_ASLEEP     0x00000001
-
-#define AR_RC                0x4000
-#define AR_RC_AHB            0x00000001
-#define AR_RC_APB            0x00000002
-#define AR_RC_HOSTIF         0x00000100
-
-#define AR_WA                		0x4004
-#define AR9285_WA_DEFAULT 		0x004a05cb
-#define AR9280_WA_DEFAULT           	0x0040073f
-#define AR_WA_DEFAULT               	0x0000073f
-
-
-#define AR_PM_STATE                 0x4008
-#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
-
-#define AR_HOST_TIMEOUT             0x4018
-#define AR_HOST_TIMEOUT_APB_CNTR    0x0000FFFF
-#define AR_HOST_TIMEOUT_APB_CNTR_S  0
-#define AR_HOST_TIMEOUT_LCL_CNTR    0xFFFF0000
-#define AR_HOST_TIMEOUT_LCL_CNTR_S  16
-
-#define AR_EEPROM                0x401c
-#define AR_EEPROM_ABSENT         0x00000100
-#define AR_EEPROM_CORRUPT        0x00000200
-#define AR_EEPROM_PROT_MASK      0x03FFFC00
-#define AR_EEPROM_PROT_MASK_S    10
-
-#define EEPROM_PROTECT_RP_0_31        0x0001
-#define EEPROM_PROTECT_WP_0_31        0x0002
-#define EEPROM_PROTECT_RP_32_63       0x0004
-#define EEPROM_PROTECT_WP_32_63       0x0008
-#define EEPROM_PROTECT_RP_64_127      0x0010
-#define EEPROM_PROTECT_WP_64_127      0x0020
-#define EEPROM_PROTECT_RP_128_191     0x0040
-#define EEPROM_PROTECT_WP_128_191     0x0080
-#define EEPROM_PROTECT_RP_192_255     0x0100
-#define EEPROM_PROTECT_WP_192_255     0x0200
-#define EEPROM_PROTECT_RP_256_511     0x0400
-#define EEPROM_PROTECT_WP_256_511     0x0800
-#define EEPROM_PROTECT_RP_512_1023    0x1000
-#define EEPROM_PROTECT_WP_512_1023    0x2000
-#define EEPROM_PROTECT_RP_1024_2047   0x4000
-#define EEPROM_PROTECT_WP_1024_2047   0x8000
-
-#define AR_SREV \
-	((AR_SREV_9100(ah)) ? 0x0600 : 0x4020)
-
-#define AR_SREV_ID \
-	((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF)
-#define AR_SREV_VERSION                       0x000000F0
-#define AR_SREV_VERSION_S                     4
-#define AR_SREV_REVISION                      0x00000007
-
-#define AR_SREV_ID2                           0xFFFFFFFF
-#define AR_SREV_VERSION2        	      0xFFFC0000
-#define AR_SREV_VERSION2_S                    18
-#define AR_SREV_TYPE2        	      	      0x0003F000
-#define AR_SREV_TYPE2_S                       12
-#define AR_SREV_TYPE2_CHAIN		      0x00001000
-#define AR_SREV_TYPE2_HOST_MODE		      0x00002000
-#define AR_SREV_REVISION2        	      0x00000F00
-#define AR_SREV_REVISION2_S     	      8
-
-#define AR_SREV_VERSION_5416_PCI               0xD
-#define AR_SREV_VERSION_5416_PCIE              0xC
-#define AR_SREV_REVISION_5416_10               0
-#define AR_SREV_REVISION_5416_20               1
-#define AR_SREV_REVISION_5416_22               2
-#define AR_SREV_VERSION_9100                  0x14
-#define AR_SREV_VERSION_9160        	      0x40
-#define AR_SREV_REVISION_9160_10    	      0
-#define AR_SREV_REVISION_9160_11    	      1
-#define AR_SREV_VERSION_9280                0x80
-#define AR_SREV_REVISION_9280_10            0
-#define AR_SREV_REVISION_9280_20            1
-#define AR_SREV_REVISION_9280_21            2
-#define AR_SREV_VERSION_9285                  0xC0
-#define AR_SREV_REVISION_9285_10              0
-#define AR_SREV_REVISION_9285_11              1
-#define AR_SREV_REVISION_9285_12              2
-
-#define AR_SREV_5416(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
-	 ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
-#define AR_SREV_5416_20_OR_LATER(_ah) \
-	(((AR_SREV_5416(_ah)) && \
-	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
-	 ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
-#define AR_SREV_5416_22_OR_LATER(_ah) \
-	(((AR_SREV_5416(_ah)) && \
-	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
-	 ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
-
-#define AR_SREV_9100(ah) \
-	((ah->hw_version.macVersion) == AR_SREV_VERSION_9100)
-#define AR_SREV_9100_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
-
-#define AR_SREV_9160(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160))
-#define AR_SREV_9160_10_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160))
-#define AR_SREV_9160_11(_ah) \
-	(AR_SREV_9160(_ah) && \
-	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
-#define AR_SREV_9280(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
-#define AR_SREV_9280_10_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
-#define AR_SREV_9280_20(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
-		((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))
-#define AR_SREV_9280_20_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
-	((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)))
-
-#define AR_SREV_9285(_ah) \
-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
-#define AR_SREV_9285_10_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
-#define AR_SREV_9285_11(_ah) \
-	(AR_SREV_9285(ah) && \
-	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11))
-#define AR_SREV_9285_11_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
-	 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
-			       AR_SREV_REVISION_9285_11)))
-#define AR_SREV_9285_12(_ah) \
-	(AR_SREV_9285(ah) && \
-	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12))
-#define AR_SREV_9285_12_OR_LATER(_ah) \
-	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
-	 (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
-			       AR_SREV_REVISION_9285_12)))
-
-#define AR_RADIO_SREV_MAJOR                   0xf0
-#define AR_RAD5133_SREV_MAJOR                 0xc0
-#define AR_RAD2133_SREV_MAJOR                 0xd0
-#define AR_RAD5122_SREV_MAJOR                 0xe0
-#define AR_RAD2122_SREV_MAJOR                 0xf0
-
-#define AR_AHB_MODE                           0x4024
-#define AR_AHB_EXACT_WR_EN                    0x00000000
-#define AR_AHB_BUF_WR_EN                      0x00000001
-#define AR_AHB_EXACT_RD_EN                    0x00000000
-#define AR_AHB_CACHELINE_RD_EN                0x00000002
-#define AR_AHB_PREFETCH_RD_EN                 0x00000004
-#define AR_AHB_PAGE_SIZE_1K                   0x00000000
-#define AR_AHB_PAGE_SIZE_2K                   0x00000008
-#define AR_AHB_PAGE_SIZE_4K                   0x00000010
-
-#define AR_INTR_RTC_IRQ                       0x00000001
-#define AR_INTR_MAC_IRQ                       0x00000002
-#define AR_INTR_EEP_PROT_ACCESS               0x00000004
-#define AR_INTR_MAC_AWAKE                     0x00020000
-#define AR_INTR_MAC_ASLEEP                    0x00040000
-#define AR_INTR_SPURIOUS                      0xFFFFFFFF
-
-
-#define AR_INTR_SYNC_CAUSE_CLR                0x4028
-
-#define AR_INTR_SYNC_CAUSE                    0x4028
-
-#define AR_INTR_SYNC_ENABLE                   0x402c
-#define AR_INTR_SYNC_ENABLE_GPIO              0xFFFC0000
-#define AR_INTR_SYNC_ENABLE_GPIO_S            18
-
-enum {
-	AR_INTR_SYNC_RTC_IRQ = 0x00000001,
-	AR_INTR_SYNC_MAC_IRQ = 0x00000002,
-	AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004,
-	AR_INTR_SYNC_APB_TIMEOUT = 0x00000008,
-	AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010,
-	AR_INTR_SYNC_HOST1_FATAL = 0x00000020,
-	AR_INTR_SYNC_HOST1_PERR = 0x00000040,
-	AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080,
-	AR_INTR_SYNC_RADM_CPL_EP = 0x00000100,
-	AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200,
-	AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400,
-	AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800,
-	AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000,
-	AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000,
-	AR_INTR_SYNC_PM_ACCESS = 0x00004000,
-	AR_INTR_SYNC_MAC_AWAKE = 0x00008000,
-	AR_INTR_SYNC_MAC_ASLEEP = 0x00010000,
-	AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000,
-	AR_INTR_SYNC_ALL = 0x0003FFFF,
-
-
-	AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL |
-				AR_INTR_SYNC_HOST1_PERR |
-				AR_INTR_SYNC_RADM_CPL_EP |
-				AR_INTR_SYNC_RADM_CPL_DLLP_ABORT |
-				AR_INTR_SYNC_RADM_CPL_TLP_ABORT |
-				AR_INTR_SYNC_RADM_CPL_ECRC_ERR |
-				AR_INTR_SYNC_RADM_CPL_TIMEOUT |
-				AR_INTR_SYNC_LOCAL_TIMEOUT |
-				AR_INTR_SYNC_MAC_SLEEP_ACCESS),
-
-	AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
-
-};
-
-#define AR_INTR_ASYNC_MASK                       0x4030
-#define AR_INTR_ASYNC_MASK_GPIO                  0xFFFC0000
-#define AR_INTR_ASYNC_MASK_GPIO_S                18
-
-#define AR_INTR_SYNC_MASK                        0x4034
-#define AR_INTR_SYNC_MASK_GPIO                   0xFFFC0000
-#define AR_INTR_SYNC_MASK_GPIO_S                 18
-
-#define AR_INTR_ASYNC_CAUSE_CLR                  0x4038
-#define AR_INTR_ASYNC_CAUSE                      0x4038
-
-#define AR_INTR_ASYNC_ENABLE                     0x403c
-#define AR_INTR_ASYNC_ENABLE_GPIO                0xFFFC0000
-#define AR_INTR_ASYNC_ENABLE_GPIO_S              18
-
-#define AR_PCIE_SERDES                           0x4040
-#define AR_PCIE_SERDES2                          0x4044
-#define AR_PCIE_PM_CTRL                          0x4014
-#define AR_PCIE_PM_CTRL_ENA                      0x00080000
-
-#define AR_NUM_GPIO                              14
-#define AR928X_NUM_GPIO                          10
-#define AR9285_NUM_GPIO                          12
-
-#define AR_GPIO_IN_OUT                           0x4048
-#define AR_GPIO_IN_VAL                           0x0FFFC000
-#define AR_GPIO_IN_VAL_S                         14
-#define AR928X_GPIO_IN_VAL                       0x000FFC00
-#define AR928X_GPIO_IN_VAL_S                     10
-#define AR9285_GPIO_IN_VAL                       0x00FFF000
-#define AR9285_GPIO_IN_VAL_S                     12
-
-#define AR_GPIO_OE_OUT                           0x404c
-#define AR_GPIO_OE_OUT_DRV                       0x3
-#define AR_GPIO_OE_OUT_DRV_NO                    0x0
-#define AR_GPIO_OE_OUT_DRV_LOW                   0x1
-#define AR_GPIO_OE_OUT_DRV_HI                    0x2
-#define AR_GPIO_OE_OUT_DRV_ALL                   0x3
-
-#define AR_GPIO_INTR_POL                         0x4050
-#define AR_GPIO_INTR_POL_VAL                     0x00001FFF
-#define AR_GPIO_INTR_POL_VAL_S                   0
-
-#define AR_GPIO_INPUT_EN_VAL                     0x4054
-#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF     0x00000004
-#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S       2
-#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF    0x00000008
-#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S      3
-#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF       0x00000010
-#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
-#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
-#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
-#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
-#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
-#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
-#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
-#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000
-#define AR_GPIO_JTAG_DISABLE                     0x00020000
-
-#define AR_GPIO_INPUT_MUX1                       0x4058
-#define AR_GPIO_INPUT_MUX1_BT_ACTIVE             0x000f0000
-#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S           16
-
-#define AR_GPIO_INPUT_MUX2                       0x405c
-#define AR_GPIO_INPUT_MUX2_CLK25                 0x0000000f
-#define AR_GPIO_INPUT_MUX2_CLK25_S               0
-#define AR_GPIO_INPUT_MUX2_RFSILENT              0x000000f0
-#define AR_GPIO_INPUT_MUX2_RFSILENT_S            4
-#define AR_GPIO_INPUT_MUX2_RTC_RESET             0x00000f00
-#define AR_GPIO_INPUT_MUX2_RTC_RESET_S           8
-
-#define AR_GPIO_OUTPUT_MUX1                      0x4060
-#define AR_GPIO_OUTPUT_MUX2                      0x4064
-#define AR_GPIO_OUTPUT_MUX3                      0x4068
-
-#define AR_INPUT_STATE                           0x406c
-
-#define AR_EEPROM_STATUS_DATA                    0x407c
-#define AR_EEPROM_STATUS_DATA_VAL                0x0000ffff
-#define AR_EEPROM_STATUS_DATA_VAL_S              0
-#define AR_EEPROM_STATUS_DATA_BUSY               0x00010000
-#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS        0x00020000
-#define AR_EEPROM_STATUS_DATA_PROT_ACCESS        0x00040000
-#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS      0x00080000
-
-#define AR_OBS                  0x4080
-
-#define AR_PCIE_MSI                              0x4094
-#define AR_PCIE_MSI_ENABLE                       0x00000001
-
-
-#define AR_RTC_9160_PLL_DIV	0x000003ff
-#define AR_RTC_9160_PLL_DIV_S   0
-#define AR_RTC_9160_PLL_REFDIV  0x00003C00
-#define AR_RTC_9160_PLL_REFDIV_S 10
-#define AR_RTC_9160_PLL_CLKSEL	0x0000C000
-#define AR_RTC_9160_PLL_CLKSEL_S 14
-
-#define AR_RTC_BASE             0x00020000
-#define AR_RTC_RC \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000)
-#define AR_RTC_RC_M		0x00000003
-#define AR_RTC_RC_MAC_WARM      0x00000001
-#define AR_RTC_RC_MAC_COLD      0x00000002
-#define AR_RTC_RC_COLD_RESET    0x00000004
-#define AR_RTC_RC_WARM_RESET    0x00000008
-
-#define AR_RTC_PLL_CONTROL \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
-
-#define AR_RTC_PLL_DIV          0x0000001f
-#define AR_RTC_PLL_DIV_S        0
-#define AR_RTC_PLL_DIV2         0x00000020
-#define AR_RTC_PLL_REFDIV_5     0x000000c0
-#define AR_RTC_PLL_CLKSEL       0x00000300
-#define AR_RTC_PLL_CLKSEL_S     8
-
-#define AR_RTC_RESET \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
-#define AR_RTC_RESET_EN		(0x00000001)
-
-#define AR_RTC_STATUS \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044)
-
-#define AR_RTC_STATUS_M \
-	((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f)
-
-#define AR_RTC_PM_STATUS_M      0x0000000f
-
-#define AR_RTC_STATUS_SHUTDOWN  0x00000001
-#define AR_RTC_STATUS_ON        0x00000002
-#define AR_RTC_STATUS_SLEEP     0x00000004
-#define AR_RTC_STATUS_WAKEUP    0x00000008
-
-#define AR_RTC_SLEEP_CLK \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)
-#define AR_RTC_FORCE_DERIVED_CLK    0x2
-
-#define AR_RTC_FORCE_WAKE \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c)
-#define AR_RTC_FORCE_WAKE_EN        0x00000001
-#define AR_RTC_FORCE_WAKE_ON_INT    0x00000002
-
-
-#define AR_RTC_INTR_CAUSE \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050)
-
-#define AR_RTC_INTR_ENABLE \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054)
-
-#define AR_RTC_INTR_MASK \
-	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058)
-
-/* RTC_DERIVED_* - only for AR9100 */
-
-#define AR_RTC_DERIVED_CLK           (AR_RTC_BASE + 0x0038)
-#define AR_RTC_DERIVED_CLK_PERIOD    0x0000fffe
-#define AR_RTC_DERIVED_CLK_PERIOD_S  1
-
-#define	AR_SEQ_MASK	0x8060
-
-#define AR_AN_RF2G1_CH0         0x7810
-#define AR_AN_RF2G1_CH0_OB      0x03800000
-#define AR_AN_RF2G1_CH0_OB_S    23
-#define AR_AN_RF2G1_CH0_DB      0x1C000000
-#define AR_AN_RF2G1_CH0_DB_S    26
-
-#define AR_AN_RF5G1_CH0         0x7818
-#define AR_AN_RF5G1_CH0_OB5     0x00070000
-#define AR_AN_RF5G1_CH0_OB5_S   16
-#define AR_AN_RF5G1_CH0_DB5     0x00380000
-#define AR_AN_RF5G1_CH0_DB5_S   19
-
-#define AR_AN_RF2G1_CH1         0x7834
-#define AR_AN_RF2G1_CH1_OB      0x03800000
-#define AR_AN_RF2G1_CH1_OB_S    23
-#define AR_AN_RF2G1_CH1_DB      0x1C000000
-#define AR_AN_RF2G1_CH1_DB_S    26
-
-#define AR_AN_RF5G1_CH1         0x783C
-#define AR_AN_RF5G1_CH1_OB5     0x00070000
-#define AR_AN_RF5G1_CH1_OB5_S   16
-#define AR_AN_RF5G1_CH1_DB5     0x00380000
-#define AR_AN_RF5G1_CH1_DB5_S   19
-
-#define AR_AN_TOP1                  0x7890
-#define AR_AN_TOP1_DACIPMODE	    0x00040000
-#define AR_AN_TOP1_DACIPMODE_S	    18
-
-#define AR_AN_TOP2                  0x7894
-#define AR_AN_TOP2_XPABIAS_LVL      0xC0000000
-#define AR_AN_TOP2_XPABIAS_LVL_S    30
-#define AR_AN_TOP2_LOCALBIAS        0x00200000
-#define AR_AN_TOP2_LOCALBIAS_S      21
-#define AR_AN_TOP2_PWDCLKIND        0x00400000
-#define AR_AN_TOP2_PWDCLKIND_S      22
-
-#define AR_AN_SYNTH9            0x7868
-#define AR_AN_SYNTH9_REFDIVA    0xf8000000
-#define AR_AN_SYNTH9_REFDIVA_S  27
-
-#define AR9285_AN_RF2G1              0x7820
-#define AR9285_AN_RF2G1_ENPACAL      0x00000800
-#define AR9285_AN_RF2G1_ENPACAL_S    11
-#define AR9285_AN_RF2G1_PDPADRV1     0x02000000
-#define AR9285_AN_RF2G1_PDPADRV1_S   25
-#define AR9285_AN_RF2G1_PDPADRV2     0x01000000
-#define AR9285_AN_RF2G1_PDPADRV2_S   24
-#define AR9285_AN_RF2G1_PDPAOUT      0x00800000
-#define AR9285_AN_RF2G1_PDPAOUT_S    23
-
-
-#define AR9285_AN_RF2G2              0x7824
-#define AR9285_AN_RF2G2_OFFCAL       0x00001000
-#define AR9285_AN_RF2G2_OFFCAL_S     12
-
-#define AR9285_AN_RF2G3             0x7828
-#define AR9285_AN_RF2G3_PDVCCOMP    0x02000000
-#define AR9285_AN_RF2G3_PDVCCOMP_S  25
-#define AR9285_AN_RF2G3_OB_0    0x00E00000
-#define AR9285_AN_RF2G3_OB_0_S    21
-#define AR9285_AN_RF2G3_OB_1    0x001C0000
-#define AR9285_AN_RF2G3_OB_1_S    18
-#define AR9285_AN_RF2G3_OB_2    0x00038000
-#define AR9285_AN_RF2G3_OB_2_S    15
-#define AR9285_AN_RF2G3_OB_3    0x00007000
-#define AR9285_AN_RF2G3_OB_3_S    12
-#define AR9285_AN_RF2G3_OB_4    0x00000E00
-#define AR9285_AN_RF2G3_OB_4_S    9
-
-#define AR9285_AN_RF2G3_DB1_0    0x000001C0
-#define AR9285_AN_RF2G3_DB1_0_S    6
-#define AR9285_AN_RF2G3_DB1_1    0x00000038
-#define AR9285_AN_RF2G3_DB1_1_S    3
-#define AR9285_AN_RF2G3_DB1_2    0x00000007
-#define AR9285_AN_RF2G3_DB1_2_S    0
-#define AR9285_AN_RF2G4         0x782C
-#define AR9285_AN_RF2G4_DB1_3    0xE0000000
-#define AR9285_AN_RF2G4_DB1_3_S    29
-#define AR9285_AN_RF2G4_DB1_4    0x1C000000
-#define AR9285_AN_RF2G4_DB1_4_S    26
-
-#define AR9285_AN_RF2G4_DB2_0    0x03800000
-#define AR9285_AN_RF2G4_DB2_0_S    23
-#define AR9285_AN_RF2G4_DB2_1    0x00700000
-#define AR9285_AN_RF2G4_DB2_1_S    20
-#define AR9285_AN_RF2G4_DB2_2    0x000E0000
-#define AR9285_AN_RF2G4_DB2_2_S    17
-#define AR9285_AN_RF2G4_DB2_3    0x0001C000
-#define AR9285_AN_RF2G4_DB2_3_S    14
-#define AR9285_AN_RF2G4_DB2_4    0x00003800
-#define AR9285_AN_RF2G4_DB2_4_S    11
-
-#define AR9285_AN_RF2G6                 0x7834
-#define AR9285_AN_RF2G6_CCOMP           0x00007800
-#define AR9285_AN_RF2G6_CCOMP_S         11
-#define AR9285_AN_RF2G6_OFFS            0x03f00000
-#define AR9285_AN_RF2G6_OFFS_S          20
-
-#define AR9285_AN_RF2G7                 0x7838
-#define AR9285_AN_RF2G7_PWDDB           0x00000002
-#define AR9285_AN_RF2G7_PWDDB_S         1
-#define AR9285_AN_RF2G7_PADRVGN2TAB0    0xE0000000
-#define AR9285_AN_RF2G7_PADRVGN2TAB0_S  29
-
-#define AR9285_AN_RF2G8                  0x783C
-#define AR9285_AN_RF2G8_PADRVGN2TAB0     0x0001C000
-#define AR9285_AN_RF2G8_PADRVGN2TAB0_S   14
-
-
-#define AR9285_AN_RF2G9          0x7840
-#define AR9285_AN_RXTXBB1              0x7854
-#define AR9285_AN_RXTXBB1_PDRXTXBB1    0x00000020
-#define AR9285_AN_RXTXBB1_PDRXTXBB1_S  5
-#define AR9285_AN_RXTXBB1_PDV2I        0x00000080
-#define AR9285_AN_RXTXBB1_PDV2I_S      7
-#define AR9285_AN_RXTXBB1_PDDACIF      0x00000100
-#define AR9285_AN_RXTXBB1_PDDACIF_S    8
-#define AR9285_AN_RXTXBB1_SPARE9       0x00000001
-#define AR9285_AN_RXTXBB1_SPARE9_S     0
-
-#define AR9285_AN_TOP2           0x7868
-
-#define AR9285_AN_TOP3                  0x786c
-#define AR9285_AN_TOP3_XPABIAS_LVL      0x0000000C
-#define AR9285_AN_TOP3_XPABIAS_LVL_S    2
-#define AR9285_AN_TOP3_PWDDAC           0x00800000
-#define AR9285_AN_TOP3_PWDDAC_S    23
-
-#define AR9285_AN_TOP4           0x7870
-#define AR9285_AN_TOP4_DEFAULT   0x10142c00
-
-#define AR_STA_ID0                 0x8000
-#define AR_STA_ID1                 0x8004
-#define AR_STA_ID1_SADH_MASK       0x0000FFFF
-#define AR_STA_ID1_STA_AP          0x00010000
-#define AR_STA_ID1_ADHOC           0x00020000
-#define AR_STA_ID1_PWR_SAV         0x00040000
-#define AR_STA_ID1_KSRCHDIS        0x00080000
-#define AR_STA_ID1_PCF             0x00100000
-#define AR_STA_ID1_USE_DEFANT      0x00200000
-#define AR_STA_ID1_DEFANT_UPDATE   0x00400000
-#define AR_STA_ID1_RTS_USE_DEF     0x00800000
-#define AR_STA_ID1_ACKCTS_6MB      0x01000000
-#define AR_STA_ID1_BASE_RATE_11B   0x02000000
-#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000
-#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000
-#define AR_STA_ID1_KSRCH_MODE      0x10000000
-#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000
-#define AR_STA_ID1_CBCIV_ENDIAN    0x40000000
-#define AR_STA_ID1_MCAST_KSRCH     0x80000000
-
-#define AR_BSS_ID0          0x8008
-#define AR_BSS_ID1          0x800C
-#define AR_BSS_ID1_U16       0x0000FFFF
-#define AR_BSS_ID1_AID       0x07FF0000
-#define AR_BSS_ID1_AID_S     16
-
-#define AR_BCN_RSSI_AVE      0x8010
-#define AR_BCN_RSSI_AVE_MASK 0x00000FFF
-
-#define AR_TIME_OUT         0x8014
-#define AR_TIME_OUT_ACK      0x00003FFF
-#define AR_TIME_OUT_ACK_S    0
-#define AR_TIME_OUT_CTS      0x3FFF0000
-#define AR_TIME_OUT_CTS_S    16
-
-#define AR_RSSI_THR          0x8018
-#define AR_RSSI_THR_MASK     0x000000FF
-#define AR_RSSI_THR_BM_THR   0x0000FF00
-#define AR_RSSI_THR_BM_THR_S 8
-#define AR_RSSI_BCN_WEIGHT   0x1F000000
-#define AR_RSSI_BCN_WEIGHT_S 24
-#define AR_RSSI_BCN_RSSI_RST 0x20000000
-
-#define AR_USEC              0x801c
-#define AR_USEC_USEC         0x0000007F
-#define AR_USEC_TX_LAT       0x007FC000
-#define AR_USEC_TX_LAT_S     14
-#define AR_USEC_RX_LAT       0x1F800000
-#define AR_USEC_RX_LAT_S     23
-
-#define AR_RESET_TSF        0x8020
-#define AR_RESET_TSF_ONCE   0x01000000
-
-#define AR_MAX_CFP_DUR      0x8038
-#define AR_CFP_VAL          0x0000FFFF
-
-#define AR_RX_FILTER        0x803C
-#define AR_RX_COMPR_BAR     0x00000400
-
-#define AR_MCAST_FIL0       0x8040
-#define AR_MCAST_FIL1       0x8044
-
-#define AR_DIAG_SW                  0x8048
-#define AR_DIAG_CACHE_ACK           0x00000001
-#define AR_DIAG_ACK_DIS             0x00000002
-#define AR_DIAG_CTS_DIS             0x00000004
-#define AR_DIAG_ENCRYPT_DIS         0x00000008
-#define AR_DIAG_DECRYPT_DIS         0x00000010
-#define AR_DIAG_RX_DIS              0x00000020
-#define AR_DIAG_LOOP_BACK           0x00000040
-#define AR_DIAG_CORR_FCS            0x00000080
-#define AR_DIAG_CHAN_INFO           0x00000100
-#define AR_DIAG_SCRAM_SEED          0x0001FE00
-#define AR_DIAG_SCRAM_SEED_S        8
-#define AR_DIAG_FRAME_NV0           0x00020000
-#define AR_DIAG_OBS_PT_SEL1         0x000C0000
-#define AR_DIAG_OBS_PT_SEL1_S       18
-#define AR_DIAG_FORCE_RX_CLEAR      0x00100000
-#define AR_DIAG_IGNORE_VIRT_CS      0x00200000
-#define AR_DIAG_FORCE_CH_IDLE_HIGH  0x00400000
-#define AR_DIAG_EIFS_CTRL_ENA       0x00800000
-#define AR_DIAG_DUAL_CHAIN_INFO     0x01000000
-#define AR_DIAG_RX_ABORT            0x02000000
-#define AR_DIAG_SATURATE_CYCLE_CNT  0x04000000
-#define AR_DIAG_OBS_PT_SEL2         0x08000000
-#define AR_DIAG_RX_CLEAR_CTL_LOW    0x10000000
-#define AR_DIAG_RX_CLEAR_EXT_LOW    0x20000000
-
-#define AR_TSF_L32          0x804c
-#define AR_TSF_U32          0x8050
-
-#define AR_TST_ADDAC        0x8054
-#define AR_DEF_ANTENNA      0x8058
-
-#define AR_AES_MUTE_MASK0       0x805c
-#define AR_AES_MUTE_MASK0_FC    0x0000FFFF
-#define AR_AES_MUTE_MASK0_QOS   0xFFFF0000
-#define AR_AES_MUTE_MASK0_QOS_S 16
-
-#define AR_AES_MUTE_MASK1       0x8060
-#define AR_AES_MUTE_MASK1_SEQ   0x0000FFFF
-#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000
-#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
-
-#define AR_GATED_CLKS       0x8064
-#define AR_GATED_CLKS_TX    0x00000002
-#define AR_GATED_CLKS_RX    0x00000004
-#define AR_GATED_CLKS_REG   0x00000008
-
-#define AR_OBS_BUS_CTRL     0x8068
-#define AR_OBS_BUS_SEL_1    0x00040000
-#define AR_OBS_BUS_SEL_2    0x00080000
-#define AR_OBS_BUS_SEL_3    0x000C0000
-#define AR_OBS_BUS_SEL_4    0x08040000
-#define AR_OBS_BUS_SEL_5    0x08080000
-
-#define AR_OBS_BUS_1               0x806c
-#define AR_OBS_BUS_1_PCU           0x00000001
-#define AR_OBS_BUS_1_RX_END        0x00000002
-#define AR_OBS_BUS_1_RX_WEP        0x00000004
-#define AR_OBS_BUS_1_RX_BEACON     0x00000008
-#define AR_OBS_BUS_1_RX_FILTER     0x00000010
-#define AR_OBS_BUS_1_TX_HCF        0x00000020
-#define AR_OBS_BUS_1_QUIET_TIME    0x00000040
-#define AR_OBS_BUS_1_CHAN_IDLE     0x00000080
-#define AR_OBS_BUS_1_TX_HOLD       0x00000100
-#define AR_OBS_BUS_1_TX_FRAME      0x00000200
-#define AR_OBS_BUS_1_RX_FRAME      0x00000400
-#define AR_OBS_BUS_1_RX_CLEAR      0x00000800
-#define AR_OBS_BUS_1_WEP_STATE     0x0003F000
-#define AR_OBS_BUS_1_WEP_STATE_S   12
-#define AR_OBS_BUS_1_RX_STATE      0x01F00000
-#define AR_OBS_BUS_1_RX_STATE_S    20
-#define AR_OBS_BUS_1_TX_STATE      0x7E000000
-#define AR_OBS_BUS_1_TX_STATE_S    25
-
-#define AR_LAST_TSTP        0x8080
-#define AR_NAV              0x8084
-#define AR_RTS_OK           0x8088
-#define AR_RTS_FAIL         0x808c
-#define AR_ACK_FAIL         0x8090
-#define AR_FCS_FAIL         0x8094
-#define AR_BEACON_CNT       0x8098
-
-#define AR_SLEEP1               0x80d4
-#define AR_SLEEP1_ASSUME_DTIM   0x00080000
-#define AR_SLEEP1_CAB_TIMEOUT   0xFFE00000
-#define AR_SLEEP1_CAB_TIMEOUT_S 21
-
-#define AR_SLEEP2                   0x80d8
-#define AR_SLEEP2_BEACON_TIMEOUT    0xFFE00000
-#define AR_SLEEP2_BEACON_TIMEOUT_S  21
-
-#define AR_BSSMSKL            0x80e0
-#define AR_BSSMSKU            0x80e4
-
-#define AR_TPC                 0x80e8
-#define AR_TPC_ACK             0x0000003f
-#define AR_TPC_ACK_S           0x00
-#define AR_TPC_CTS             0x00003f00
-#define AR_TPC_CTS_S           0x08
-#define AR_TPC_CHIRP           0x003f0000
-#define AR_TPC_CHIRP_S         0x16
-
-#define AR_TFCNT           0x80ec
-#define AR_RFCNT           0x80f0
-#define AR_RCCNT           0x80f4
-#define AR_CCCNT           0x80f8
-
-#define AR_QUIET1          0x80fc
-#define AR_QUIET1_NEXT_QUIET_S         0
-#define AR_QUIET1_NEXT_QUIET_M         0x0000ffff
-#define AR_QUIET1_QUIET_ENABLE         0x00010000
-#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
-#define AR_QUIET2          0x8100
-#define AR_QUIET2_QUIET_PERIOD_S       0
-#define AR_QUIET2_QUIET_PERIOD_M       0x0000ffff
-#define AR_QUIET2_QUIET_DUR_S     16
-#define AR_QUIET2_QUIET_DUR       0xffff0000
-
-#define AR_TSF_PARM        0x8104
-#define AR_TSF_INCREMENT_M     0x000000ff
-#define AR_TSF_INCREMENT_S     0x00
-
-#define AR_QOS_NO_ACK              0x8108
-#define AR_QOS_NO_ACK_TWO_BIT      0x0000000f
-#define AR_QOS_NO_ACK_TWO_BIT_S    0
-#define AR_QOS_NO_ACK_BIT_OFF      0x00000070
-#define AR_QOS_NO_ACK_BIT_OFF_S    4
-#define AR_QOS_NO_ACK_BYTE_OFF     0x00000180
-#define AR_QOS_NO_ACK_BYTE_OFF_S   7
-
-#define AR_PHY_ERR         0x810c
-
-#define AR_PHY_ERR_DCHIRP      0x00000008
-#define AR_PHY_ERR_RADAR       0x00000020
-#define AR_PHY_ERR_OFDM_TIMING 0x00020000
-#define AR_PHY_ERR_CCK_TIMING  0x02000000
-
-#define AR_RXFIFO_CFG          0x8114
-
-
-#define AR_MIC_QOS_CONTROL 0x8118
-#define AR_MIC_QOS_SELECT  0x811c
-
-#define AR_PCU_MISC                0x8120
-#define AR_PCU_FORCE_BSSID_MATCH   0x00000001
-#define AR_PCU_MIC_NEW_LOC_ENA     0x00000004
-#define AR_PCU_TX_ADD_TSF          0x00000008
-#define AR_PCU_CCK_SIFS_MODE       0x00000010
-#define AR_PCU_RX_ANT_UPDT         0x00000800
-#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000
-#define AR_PCU_MISS_BCN_IN_SLEEP   0x00004000
-#define AR_PCU_BUG_12306_FIX_ENA   0x00020000
-#define AR_PCU_FORCE_QUIET_COLL    0x00040000
-#define AR_PCU_TBTT_PROTECT        0x00200000
-#define AR_PCU_CLEAR_VMF           0x01000000
-#define AR_PCU_CLEAR_BA_VALID      0x04000000
-
-
-#define AR_FILT_OFDM           0x8124
-#define AR_FILT_OFDM_COUNT     0x00FFFFFF
-
-#define AR_FILT_CCK            0x8128
-#define AR_FILT_CCK_COUNT      0x00FFFFFF
-
-#define AR_PHY_ERR_1           0x812c
-#define AR_PHY_ERR_1_COUNT     0x00FFFFFF
-#define AR_PHY_ERR_MASK_1      0x8130
-
-#define AR_PHY_ERR_2           0x8134
-#define AR_PHY_ERR_2_COUNT     0x00FFFFFF
-#define AR_PHY_ERR_MASK_2      0x8138
-
-#define AR_PHY_COUNTMAX        (3 << 22)
-#define AR_MIBCNT_INTRMASK     (3 << 22)
-
-#define AR_TSFOOR_THRESHOLD       0x813c
-#define AR_TSFOOR_THRESHOLD_VAL   0x0000FFFF
-
-#define AR_PHY_ERR_EIFS_MASK   8144
-
-#define AR_PHY_ERR_3           0x8168
-#define AR_PHY_ERR_3_COUNT     0x00FFFFFF
-#define AR_PHY_ERR_MASK_3      0x816c
-
-#define AR_TXSIFS              0x81d0
-#define AR_TXSIFS_TIME         0x000000FF
-#define AR_TXSIFS_TX_LATENCY   0x00000F00
-#define AR_TXSIFS_TX_LATENCY_S 8
-#define AR_TXSIFS_ACK_SHIFT    0x00007000
-#define AR_TXSIFS_ACK_SHIFT_S  12
-
-#define AR_TXOP_X          0x81ec
-#define AR_TXOP_X_VAL      0x000000FF
-
-
-#define AR_TXOP_0_3    0x81f0
-#define AR_TXOP_4_7    0x81f4
-#define AR_TXOP_8_11   0x81f8
-#define AR_TXOP_12_15  0x81fc
-
-
-#define AR_NEXT_TBTT_TIMER                  0x8200
-#define AR_NEXT_DMA_BEACON_ALERT            0x8204
-#define AR_NEXT_SWBA                        0x8208
-#define AR_NEXT_CFP                         0x8208
-#define AR_NEXT_HCF                         0x820C
-#define AR_NEXT_TIM                         0x8210
-#define AR_NEXT_DTIM                        0x8214
-#define AR_NEXT_QUIET_TIMER                 0x8218
-#define AR_NEXT_NDP_TIMER                   0x821C
-
-#define AR_BEACON_PERIOD                    0x8220
-#define AR_DMA_BEACON_PERIOD                0x8224
-#define AR_SWBA_PERIOD                      0x8228
-#define AR_HCF_PERIOD                       0x822C
-#define AR_TIM_PERIOD                       0x8230
-#define AR_DTIM_PERIOD                      0x8234
-#define AR_QUIET_PERIOD                     0x8238
-#define AR_NDP_PERIOD                       0x823C
-
-#define AR_TIMER_MODE                       0x8240
-#define AR_TBTT_TIMER_EN                    0x00000001
-#define AR_DBA_TIMER_EN                     0x00000002
-#define AR_SWBA_TIMER_EN                    0x00000004
-#define AR_HCF_TIMER_EN                     0x00000008
-#define AR_TIM_TIMER_EN                     0x00000010
-#define AR_DTIM_TIMER_EN                    0x00000020
-#define AR_QUIET_TIMER_EN                   0x00000040
-#define AR_NDP_TIMER_EN                     0x00000080
-#define AR_TIMER_OVERFLOW_INDEX             0x00000700
-#define AR_TIMER_OVERFLOW_INDEX_S           8
-#define AR_TIMER_THRESH                     0xFFFFF000
-#define AR_TIMER_THRESH_S                   12
-
-#define AR_SLP32_MODE                  0x8244
-#define AR_SLP32_HALF_CLK_LATENCY      0x000FFFFF
-#define AR_SLP32_ENA                   0x00100000
-#define AR_SLP32_TSF_WRITE_STATUS      0x00200000
-
-#define AR_SLP32_WAKE              0x8248
-#define AR_SLP32_WAKE_XTL_TIME     0x0000FFFF
-
-#define AR_SLP32_INC               0x824c
-#define AR_SLP32_TST_INC           0x000FFFFF
-
-#define AR_SLP_CNT         0x8250
-#define AR_SLP_CYCLE_CNT   0x8254
-
-#define AR_SLP_MIB_CTRL    0x8258
-#define AR_SLP_MIB_CLEAR   0x00000001
-#define AR_SLP_MIB_PENDING 0x00000002
-
-#define AR_2040_MODE                0x8318
-#define AR_2040_JOINED_RX_CLEAR 0x00000001
-
-
-#define AR_EXTRCCNT         0x8328
-
-#define AR_SELFGEN_MASK         0x832c
-
-#define AR_PCU_TXBUF_CTRL               0x8340
-#define AR_PCU_TXBUF_CTRL_SIZE_MASK     0x7FF
-#define AR_PCU_TXBUF_CTRL_USABLE_SIZE   0x700
-#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE   0x380
-
-#define AR_PCU_MISC_MODE2               0x8344
-#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE           0x00000002
-#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT   0x00000004
-
-#define AR_KEYTABLE_0           0x8800
-#define AR_KEYTABLE(_n)         (AR_KEYTABLE_0 + ((_n)*32))
-#define AR_KEY_CACHE_SIZE       128
-#define AR_RSVD_KEYTABLE_ENTRIES 4
-#define AR_KEY_TYPE             0x00000007
-#define AR_KEYTABLE_TYPE_40     0x00000000
-#define AR_KEYTABLE_TYPE_104    0x00000001
-#define AR_KEYTABLE_TYPE_128    0x00000003
-#define AR_KEYTABLE_TYPE_TKIP   0x00000004
-#define AR_KEYTABLE_TYPE_AES    0x00000005
-#define AR_KEYTABLE_TYPE_CCM    0x00000006
-#define AR_KEYTABLE_TYPE_CLR    0x00000007
-#define AR_KEYTABLE_ANT         0x00000008
-#define AR_KEYTABLE_VALID       0x00008000
-#define AR_KEYTABLE_KEY0(_n)    (AR_KEYTABLE(_n) + 0)
-#define AR_KEYTABLE_KEY1(_n)    (AR_KEYTABLE(_n) + 4)
-#define AR_KEYTABLE_KEY2(_n)    (AR_KEYTABLE(_n) + 8)
-#define AR_KEYTABLE_KEY3(_n)    (AR_KEYTABLE(_n) + 12)
-#define AR_KEYTABLE_KEY4(_n)    (AR_KEYTABLE(_n) + 16)
-#define AR_KEYTABLE_TYPE(_n)    (AR_KEYTABLE(_n) + 20)
-#define AR_KEYTABLE_MAC0(_n)    (AR_KEYTABLE(_n) + 24)
-#define AR_KEYTABLE_MAC1(_n)    (AR_KEYTABLE(_n) + 28)
-
-#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/virtual.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/virtual.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/virtual.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/virtual.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,662 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-struct ath9k_vif_iter_data {
-	int count;
-	u8 *addr;
-};
-
-static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath9k_vif_iter_data *iter_data = data;
-	u8 *nbuf;
-
-	nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN,
-			GFP_ATOMIC);
-	if (nbuf == NULL)
-		return;
-
-	memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN);
-	iter_data->addr = nbuf;
-	iter_data->count++;
-}
-
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath9k_vif_iter_data iter_data;
-	int i, j;
-	u8 mask[ETH_ALEN];
-
-	/*
-	 * Add primary MAC address even if it is not in active use since it
-	 * will be configured to the hardware as the starting point and the
-	 * BSSID mask will need to be changed if another address is active.
-	 */
-	iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
-	if (iter_data.addr) {
-		memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN);
-		iter_data.count = 1;
-	} else
-		iter_data.count = 0;
-
-	/* Get list of all active MAC addresses */
-	spin_lock_bh(&sc->wiphy_lock);
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
-						   &iter_data);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] == NULL)
-			continue;
-		ieee80211_iterate_active_interfaces_atomic(
-			sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data);
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	/* Generate an address mask to cover all active addresses */
-	memset(mask, 0, ETH_ALEN);
-	for (i = 0; i < iter_data.count; i++) {
-		u8 *a1 = iter_data.addr + i * ETH_ALEN;
-		for (j = i + 1; j < iter_data.count; j++) {
-			u8 *a2 = iter_data.addr + j * ETH_ALEN;
-			mask[0] |= a1[0] ^ a2[0];
-			mask[1] |= a1[1] ^ a2[1];
-			mask[2] |= a1[2] ^ a2[2];
-			mask[3] |= a1[3] ^ a2[3];
-			mask[4] |= a1[4] ^ a2[4];
-			mask[5] |= a1[5] ^ a2[5];
-		}
-	}
-
-	kfree(iter_data.addr);
-
-	/* Invert the mask and configure hardware */
-	sc->bssidmask[0] = ~mask[0];
-	sc->bssidmask[1] = ~mask[1];
-	sc->bssidmask[2] = ~mask[2];
-	sc->bssidmask[3] = ~mask[3];
-	sc->bssidmask[4] = ~mask[4];
-	sc->bssidmask[5] = ~mask[5];
-
-	ath9k_hw_setbssidmask(sc);
-}
-
-int ath9k_wiphy_add(struct ath_softc *sc)
-{
-	int i, error;
-	struct ath_wiphy *aphy;
-	struct ieee80211_hw *hw;
-	u8 addr[ETH_ALEN];
-
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops);
-	if (hw == NULL)
-		return -ENOMEM;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] == NULL)
-			break;
-	}
-
-	if (i == sc->num_sec_wiphy) {
-		/* No empty slot available; increase array length */
-		struct ath_wiphy **n;
-		n = krealloc(sc->sec_wiphy,
-			     (sc->num_sec_wiphy + 1) *
-			     sizeof(struct ath_wiphy *),
-			     GFP_ATOMIC);
-		if (n == NULL) {
-			spin_unlock_bh(&sc->wiphy_lock);
-			ieee80211_free_hw(hw);
-			return -ENOMEM;
-		}
-		n[i] = NULL;
-		sc->sec_wiphy = n;
-		sc->num_sec_wiphy++;
-	}
-
-	SET_IEEE80211_DEV(hw, sc->dev);
-
-	aphy = hw->priv;
-	aphy->sc = sc;
-	aphy->hw = hw;
-	sc->sec_wiphy[i] = aphy;
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN);
-	addr[0] |= 0x02; /* Locally managed address */
-	/*
-	 * XOR virtual wiphy index into the least significant bits to generate
-	 * a different MAC address for each virtual wiphy.
-	 */
-	addr[5] ^= i & 0xff;
-	addr[4] ^= (i & 0xff00) >> 8;
-	addr[3] ^= (i & 0xff0000) >> 16;
-
-	SET_IEEE80211_PERM_ADDR(hw, addr);
-
-	ath_set_hw_capab(sc, hw);
-
-	error = ieee80211_register_hw(hw);
-
-	if (error == 0) {
-		/* Make sure wiphy scheduler is started (if enabled) */
-		ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int);
-	}
-
-	return error;
-}
-
-int ath9k_wiphy_del(struct ath_wiphy *aphy)
-{
-	struct ath_softc *sc = aphy->sc;
-	int i;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (aphy == sc->sec_wiphy[i]) {
-			sc->sec_wiphy[i] = NULL;
-			spin_unlock_bh(&sc->wiphy_lock);
-			ieee80211_unregister_hw(aphy->hw);
-			ieee80211_free_hw(aphy->hw);
-			return 0;
-		}
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-	return -ENOENT;
-}
-
-static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
-			       struct ieee80211_vif *vif, const u8 *bssid,
-			       int ps)
-{
-	struct ath_softc *sc = aphy->sc;
-	struct ath_tx_control txctl;
-	struct sk_buff *skb;
-	struct ieee80211_hdr *hdr;
-	__le16 fc;
-	struct ieee80211_tx_info *info;
-
-	skb = dev_alloc_skb(24);
-	if (skb == NULL)
-		return -ENOMEM;
-	hdr = (struct ieee80211_hdr *) skb_put(skb, 24);
-	memset(hdr, 0, 24);
-	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
-			 IEEE80211_FCTL_TODS);
-	if (ps)
-		fc |= cpu_to_le16(IEEE80211_FCTL_PM);
-	hdr->frame_control = fc;
-	memcpy(hdr->addr1, bssid, ETH_ALEN);
-	memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN);
-	memcpy(hdr->addr3, bssid, ETH_ALEN);
-
-	info = IEEE80211_SKB_CB(skb);
-	memset(info, 0, sizeof(*info));
-	info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS;
-	info->control.vif = vif;
-	info->control.rates[0].idx = 0;
-	info->control.rates[0].count = 4;
-	info->control.rates[1].idx = -1;
-
-	memset(&txctl, 0, sizeof(struct ath_tx_control));
-	txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]];
-	txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE;
-
-	if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
-		goto exit;
-
-	return 0;
-exit:
-	dev_kfree_skb_any(skb);
-	return -1;
-}
-
-static bool __ath9k_wiphy_pausing(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING)
-		return true;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING)
-			return true;
-	}
-	return false;
-}
-
-static bool ath9k_wiphy_pausing(struct ath_softc *sc)
-{
-	bool ret;
-	spin_lock_bh(&sc->wiphy_lock);
-	ret = __ath9k_wiphy_pausing(sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-	return ret;
-}
-
-static bool __ath9k_wiphy_scanning(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state == ATH_WIPHY_SCAN)
-		return true;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN)
-			return true;
-	}
-	return false;
-}
-
-bool ath9k_wiphy_scanning(struct ath_softc *sc)
-{
-	bool ret;
-	spin_lock_bh(&sc->wiphy_lock);
-	ret = __ath9k_wiphy_scanning(sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-	return ret;
-}
-
-static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy);
-
-/* caller must hold wiphy_lock */
-static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy)
-{
-	if (aphy == NULL)
-		return;
-	if (aphy->chan_idx != aphy->sc->chan_idx)
-		return; /* wiphy not on the selected channel */
-	__ath9k_wiphy_unpause(aphy);
-}
-
-static void ath9k_wiphy_unpause_channel(struct ath_softc *sc)
-{
-	int i;
-	spin_lock_bh(&sc->wiphy_lock);
-	__ath9k_wiphy_unpause_ch(sc->pri_wiphy);
-	for (i = 0; i < sc->num_sec_wiphy; i++)
-		__ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]);
-	spin_unlock_bh(&sc->wiphy_lock);
-}
-
-void ath9k_wiphy_chan_work(struct work_struct *work)
-{
-	struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
-	struct ath_wiphy *aphy = sc->next_wiphy;
-
-	if (aphy == NULL)
-		return;
-
-	/*
-	 * All pending interfaces paused; ready to change
-	 * channels.
-	 */
-
-	/* Change channels */
-	mutex_lock(&sc->mutex);
-	/* XXX: remove me eventually */
-	ath9k_update_ichannel(sc, aphy->hw,
-			      &sc->sc_ah->channels[sc->chan_idx]);
-	ath_update_chainmask(sc, sc->chan_is_ht);
-	if (ath_set_channel(sc, aphy->hw,
-			    &sc->sc_ah->channels[sc->chan_idx]) < 0) {
-		printk(KERN_DEBUG "ath9k: Failed to set channel for new "
-		       "virtual wiphy\n");
-		mutex_unlock(&sc->mutex);
-		return;
-	}
-	mutex_unlock(&sc->mutex);
-
-	ath9k_wiphy_unpause_channel(sc);
-}
-
-/*
- * ath9k version of ieee80211_tx_status() for TX frames that are generated
- * internally in the driver.
- */
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-
-	if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE &&
-	    aphy->state == ATH_WIPHY_PAUSING) {
-		if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
-			printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
-			       "frame\n", wiphy_name(hw->wiphy));
-			/*
-			 * The AP did not reply; ignore this to allow us to
-			 * continue.
-			 */
-		}
-		aphy->state = ATH_WIPHY_PAUSED;
-		if (!ath9k_wiphy_pausing(aphy->sc)) {
-			/*
-			 * Drop from tasklet to work to allow mutex for channel
-			 * change.
-			 */
-			queue_work(aphy->sc->hw->workqueue,
-				   &aphy->sc->chan_work);
-		}
-	}
-
-	kfree(tx_info_priv);
-	tx_info->rate_driver_data[0] = NULL;
-
-	dev_kfree_skb(skb);
-}
-
-static void ath9k_mark_paused(struct ath_wiphy *aphy)
-{
-	struct ath_softc *sc = aphy->sc;
-	aphy->state = ATH_WIPHY_PAUSED;
-	if (!__ath9k_wiphy_pausing(sc))
-		queue_work(sc->hw->workqueue, &sc->chan_work);
-}
-
-static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath_wiphy *aphy = data;
-	struct ath_vif *avp = (void *) vif->drv_priv;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		if (!vif->bss_conf.assoc) {
-			ath9k_mark_paused(aphy);
-			break;
-		}
-		/* TODO: could avoid this if already in PS mode */
-		if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) {
-			printk(KERN_DEBUG "%s: failed to send PS nullfunc\n",
-			       __func__);
-			ath9k_mark_paused(aphy);
-		}
-		break;
-	case NL80211_IFTYPE_AP:
-		/* Beacon transmission is paused by aphy->state change */
-		ath9k_mark_paused(aphy);
-		break;
-	default:
-		break;
-	}
-}
-
-/* caller must hold wiphy_lock */
-static int __ath9k_wiphy_pause(struct ath_wiphy *aphy)
-{
-	ieee80211_stop_queues(aphy->hw);
-	aphy->state = ATH_WIPHY_PAUSING;
-	/*
-	 * TODO: handle PAUSING->PAUSED for the case where there are multiple
-	 * active vifs (now we do it on the first vif getting ready; should be
-	 * on the last)
-	 */
-	ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter,
-						   aphy);
-	return 0;
-}
-
-int ath9k_wiphy_pause(struct ath_wiphy *aphy)
-{
-	int ret;
-	spin_lock_bh(&aphy->sc->wiphy_lock);
-	ret = __ath9k_wiphy_pause(aphy);
-	spin_unlock_bh(&aphy->sc->wiphy_lock);
-	return ret;
-}
-
-static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath_wiphy *aphy = data;
-	struct ath_vif *avp = (void *) vif->drv_priv;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		if (!vif->bss_conf.assoc)
-			break;
-		ath9k_send_nullfunc(aphy, vif, avp->bssid, 0);
-		break;
-	case NL80211_IFTYPE_AP:
-		/* Beacon transmission is re-enabled by aphy->state change */
-		break;
-	default:
-		break;
-	}
-}
-
-/* caller must hold wiphy_lock */
-static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy)
-{
-	ieee80211_iterate_active_interfaces_atomic(aphy->hw,
-						   ath9k_unpause_iter, aphy);
-	aphy->state = ATH_WIPHY_ACTIVE;
-	ieee80211_wake_queues(aphy->hw);
-	return 0;
-}
-
-int ath9k_wiphy_unpause(struct ath_wiphy *aphy)
-{
-	int ret;
-	spin_lock_bh(&aphy->sc->wiphy_lock);
-	ret = __ath9k_wiphy_unpause(aphy);
-	spin_unlock_bh(&aphy->sc->wiphy_lock);
-	return ret;
-}
-
-static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE)
-		sc->pri_wiphy->state = ATH_WIPHY_PAUSED;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE)
-			sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED;
-	}
-}
-
-/* caller must hold wiphy_lock */
-static void __ath9k_wiphy_pause_all(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
-		__ath9k_wiphy_pause(sc->pri_wiphy);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
-			__ath9k_wiphy_pause(sc->sec_wiphy[i]);
-	}
-}
-
-int ath9k_wiphy_select(struct ath_wiphy *aphy)
-{
-	struct ath_softc *sc = aphy->sc;
-	bool now;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	if (__ath9k_wiphy_scanning(sc)) {
-		/*
-		 * For now, we are using mac80211 sw scan and it expects to
-		 * have full control over channel changes, so avoid wiphy
-		 * scheduling during a scan. This could be optimized if the
-		 * scanning control were moved into the driver.
-		 */
-		spin_unlock_bh(&sc->wiphy_lock);
-		return -EBUSY;
-	}
-	if (__ath9k_wiphy_pausing(sc)) {
-		if (sc->wiphy_select_failures == 0)
-			sc->wiphy_select_first_fail = jiffies;
-		sc->wiphy_select_failures++;
-		if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2))
-		{
-			printk(KERN_DEBUG "ath9k: Previous wiphy select timed "
-			       "out; disable/enable hw to recover\n");
-			__ath9k_wiphy_mark_all_paused(sc);
-			/*
-			 * TODO: this workaround to fix hardware is unlikely to
-			 * be specific to virtual wiphy changes. It can happen
-			 * on normal channel change, too, and as such, this
-			 * should really be made more generic. For example,
-			 * tricker radio disable/enable on GTT interrupt burst
-			 * (say, 10 GTT interrupts received without any TX
-			 * frame being completed)
-			 */
-			spin_unlock_bh(&sc->wiphy_lock);
-			ath_radio_disable(sc);
-			ath_radio_enable(sc);
-			queue_work(aphy->sc->hw->workqueue,
-				   &aphy->sc->chan_work);
-			return -EBUSY; /* previous select still in progress */
-		}
-		spin_unlock_bh(&sc->wiphy_lock);
-		return -EBUSY; /* previous select still in progress */
-	}
-	sc->wiphy_select_failures = 0;
-
-	/* Store the new channel */
-	sc->chan_idx = aphy->chan_idx;
-	sc->chan_is_ht = aphy->chan_is_ht;
-	sc->next_wiphy = aphy;
-
-	__ath9k_wiphy_pause_all(sc);
-	now = !__ath9k_wiphy_pausing(aphy->sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	if (now) {
-		/* Ready to request channel change immediately */
-		queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work);
-	}
-
-	/*
-	 * wiphys will be unpaused in ath9k_tx_status() once channel has been
-	 * changed if any wiphy needs time to become paused.
-	 */
-
-	return 0;
-}
-
-bool ath9k_wiphy_started(struct ath_softc *sc)
-{
-	int i;
-	spin_lock_bh(&sc->wiphy_lock);
-	if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
-		spin_unlock_bh(&sc->wiphy_lock);
-		return true;
-	}
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) {
-			spin_unlock_bh(&sc->wiphy_lock);
-			return true;
-		}
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-	return false;
-}
-
-static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy,
-				   struct ath_wiphy *selected)
-{
-	if (selected->state == ATH_WIPHY_SCAN) {
-		if (aphy == selected)
-			return;
-		/*
-		 * Pause all other wiphys for the duration of the scan even if
-		 * they are on the current channel now.
-		 */
-	} else if (aphy->chan_idx == selected->chan_idx)
-		return;
-	aphy->state = ATH_WIPHY_PAUSED;
-	ieee80211_stop_queues(aphy->hw);
-}
-
-void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
-				  struct ath_wiphy *selected)
-{
-	int i;
-	spin_lock_bh(&sc->wiphy_lock);
-	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
-		ath9k_wiphy_pause_chan(sc->pri_wiphy, selected);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
-			ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected);
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-}
-
-void ath9k_wiphy_work(struct work_struct *work)
-{
-	struct ath_softc *sc = container_of(work, struct ath_softc,
-					    wiphy_work.work);
-	struct ath_wiphy *aphy = NULL;
-	bool first = true;
-
-	spin_lock_bh(&sc->wiphy_lock);
-
-	if (sc->wiphy_scheduler_int == 0) {
-		/* wiphy scheduler is disabled */
-		spin_unlock_bh(&sc->wiphy_lock);
-		return;
-	}
-
-try_again:
-	sc->wiphy_scheduler_index++;
-	while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) {
-		aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1];
-		if (aphy && aphy->state != ATH_WIPHY_INACTIVE)
-			break;
-
-		sc->wiphy_scheduler_index++;
-		aphy = NULL;
-	}
-	if (aphy == NULL) {
-		sc->wiphy_scheduler_index = 0;
-		if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) {
-			if (first) {
-				first = false;
-				goto try_again;
-			}
-			/* No wiphy is ready to be scheduled */
-		} else
-			aphy = sc->pri_wiphy;
-	}
-
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	if (aphy &&
-	    aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN &&
-	    ath9k_wiphy_select(aphy)) {
-		printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy "
-		       "change\n");
-	}
-
-	queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
-			   sc->wiphy_scheduler_int);
-}
-
-void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
-{
-	cancel_delayed_work_sync(&sc->wiphy_work);
-	sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
-	if (sc->wiphy_scheduler_int)
-		queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
-				   sc->wiphy_scheduler_int);
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/xmit.c linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/xmit.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ath9k/xmit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ath9k/xmit.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2178 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ath9k.h"
-
-#define BITS_PER_BYTE           8
-#define OFDM_PLCP_BITS          22
-#define HT_RC_2_MCS(_rc)        ((_rc) & 0x0f)
-#define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
-#define L_STF                   8
-#define L_LTF                   8
-#define L_SIG                   4
-#define HT_SIG                  8
-#define HT_STF                  4
-#define HT_LTF(_ns)             (4 * (_ns))
-#define SYMBOL_TIME(_ns)        ((_ns) << 2) /* ns * 4 us */
-#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5)  /* ns * 3.6 us */
-#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
-#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
-
-#define OFDM_SIFS_TIME    	    16
-
-static u32 bits_per_symbol[][2] = {
-	/* 20MHz 40MHz */
-	{    26,   54 },     /*  0: BPSK */
-	{    52,  108 },     /*  1: QPSK 1/2 */
-	{    78,  162 },     /*  2: QPSK 3/4 */
-	{   104,  216 },     /*  3: 16-QAM 1/2 */
-	{   156,  324 },     /*  4: 16-QAM 3/4 */
-	{   208,  432 },     /*  5: 64-QAM 2/3 */
-	{   234,  486 },     /*  6: 64-QAM 3/4 */
-	{   260,  540 },     /*  7: 64-QAM 5/6 */
-	{    52,  108 },     /*  8: BPSK */
-	{   104,  216 },     /*  9: QPSK 1/2 */
-	{   156,  324 },     /* 10: QPSK 3/4 */
-	{   208,  432 },     /* 11: 16-QAM 1/2 */
-	{   312,  648 },     /* 12: 16-QAM 3/4 */
-	{   416,  864 },     /* 13: 64-QAM 2/3 */
-	{   468,  972 },     /* 14: 64-QAM 3/4 */
-	{   520, 1080 },     /* 15: 64-QAM 5/6 */
-};
-
-#define IS_HT_RATE(_rate)     ((_rate) & 0x80)
-
-static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
-				  struct ath_atx_tid *tid,
-				  struct list_head *bf_head);
-static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
-				struct list_head *bf_q,
-				int txok, int sendbar);
-static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
-			     struct list_head *head);
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf);
-static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
-			      int txok);
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
-			     int nbad, int txok, bool update_rc);
-
-/*********************/
-/* Aggregation logic */
-/*********************/
-
-static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
-{
-	struct ath_atx_tid *tid;
-	tid = ATH_AN_2_TID(an, tidno);
-
-	if (tid->state & AGGR_ADDBA_COMPLETE ||
-	    tid->state & AGGR_ADDBA_PROGRESS)
-		return 1;
-	else
-		return 0;
-}
-
-static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
-{
-	struct ath_atx_ac *ac = tid->ac;
-
-	if (tid->paused)
-		return;
-
-	if (tid->sched)
-		return;
-
-	tid->sched = true;
-	list_add_tail(&tid->list, &ac->tid_q);
-
-	if (ac->sched)
-		return;
-
-	ac->sched = true;
-	list_add_tail(&ac->list, &txq->axq_acq);
-}
-
-static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-
-	spin_lock_bh(&txq->axq_lock);
-	tid->paused++;
-	spin_unlock_bh(&txq->axq_lock);
-}
-
-static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-
-	ASSERT(tid->paused > 0);
-	spin_lock_bh(&txq->axq_lock);
-
-	tid->paused--;
-
-	if (tid->paused > 0)
-		goto unlock;
-
-	if (list_empty(&tid->buf_q))
-		goto unlock;
-
-	ath_tx_queue_tid(txq, tid);
-	ath_txq_schedule(sc, txq);
-unlock:
-	spin_unlock_bh(&txq->axq_lock);
-}
-
-static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-	struct ath_buf *bf;
-	struct list_head bf_head;
-	INIT_LIST_HEAD(&bf_head);
-
-	ASSERT(tid->paused > 0);
-	spin_lock_bh(&txq->axq_lock);
-
-	tid->paused--;
-
-	if (tid->paused > 0) {
-		spin_unlock_bh(&txq->axq_lock);
-		return;
-	}
-
-	while (!list_empty(&tid->buf_q)) {
-		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-		ASSERT(!bf_isretried(bf));
-		list_move_tail(&bf->list, &bf_head);
-		ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
-	}
-
-	spin_unlock_bh(&txq->axq_lock);
-}
-
-static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-			      int seqno)
-{
-	int index, cindex;
-
-	index  = ATH_BA_INDEX(tid->seq_start, seqno);
-	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-
-	tid->tx_buf[cindex] = NULL;
-
-	while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
-		INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-		INCR(tid->baw_head, ATH_TID_MAX_BUFS);
-	}
-}
-
-static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-			     struct ath_buf *bf)
-{
-	int index, cindex;
-
-	if (bf_isretried(bf))
-		return;
-
-	index  = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
-	cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-
-	ASSERT(tid->tx_buf[cindex] == NULL);
-	tid->tx_buf[cindex] = bf;
-
-	if (index >= ((tid->baw_tail - tid->baw_head) &
-		(ATH_TID_MAX_BUFS - 1))) {
-		tid->baw_tail = cindex;
-		INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
-	}
-}
-
-/*
- * TODO: For frame(s) that are in the retry state, we will reuse the
- * sequence number(s) without setting the retry bit. The
- * alternative is to give up on these and BAR the receiver's window
- * forward.
- */
-static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
-			  struct ath_atx_tid *tid)
-
-{
-	struct ath_buf *bf;
-	struct list_head bf_head;
-	INIT_LIST_HEAD(&bf_head);
-
-	for (;;) {
-		if (list_empty(&tid->buf_q))
-			break;
-
-		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-		list_move_tail(&bf->list, &bf_head);
-
-		if (bf_isretried(bf))
-			ath_tx_update_baw(sc, tid, bf->bf_seqno);
-
-		spin_unlock(&txq->axq_lock);
-		ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
-		spin_lock(&txq->axq_lock);
-	}
-
-	tid->seq_next = tid->seq_start;
-	tid->baw_tail = tid->baw_head;
-}
-
-static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
-{
-	struct sk_buff *skb;
-	struct ieee80211_hdr *hdr;
-
-	bf->bf_state.bf_type |= BUF_RETRY;
-	bf->bf_retries++;
-
-	skb = bf->bf_mpdu;
-	hdr = (struct ieee80211_hdr *)skb->data;
-	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
-}
-
-static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
-{
-	struct ath_buf *tbf;
-
-	spin_lock_bh(&sc->tx.txbuflock);
-	ASSERT(!list_empty((&sc->tx.txbuf)));
-	tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
-	list_del(&tbf->list);
-	spin_unlock_bh(&sc->tx.txbuflock);
-
-	ATH_TXBUF_RESET(tbf);
-
-	tbf->bf_mpdu = bf->bf_mpdu;
-	tbf->bf_buf_addr = bf->bf_buf_addr;
-	*(tbf->bf_desc) = *(bf->bf_desc);
-	tbf->bf_state = bf->bf_state;
-	tbf->bf_dmacontext = bf->bf_dmacontext;
-
-	return tbf;
-}
-
-static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
-				 struct ath_buf *bf, struct list_head *bf_q,
-				 int txok)
-{
-	struct ath_node *an = NULL;
-	struct sk_buff *skb;
-	struct ieee80211_sta *sta;
-	struct ieee80211_hdr *hdr;
-	struct ath_atx_tid *tid = NULL;
-	struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
-	struct ath_desc *ds = bf_last->bf_desc;
-	struct list_head bf_head, bf_pending;
-	u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
-	u32 ba[WME_BA_BMP_SIZE >> 5];
-	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
-	bool rc_update = true;
-
-	skb = (struct sk_buff *)bf->bf_mpdu;
-	hdr = (struct ieee80211_hdr *)skb->data;
-
-	rcu_read_lock();
-
-	sta = ieee80211_find_sta(sc->hw, hdr->addr1);
-	if (!sta) {
-		rcu_read_unlock();
-		return;
-	}
-
-	an = (struct ath_node *)sta->drv_priv;
-	tid = ATH_AN_2_TID(an, bf->bf_tidno);
-
-	isaggr = bf_isaggr(bf);
-	memset(ba, 0, WME_BA_BMP_SIZE >> 3);
-
-	if (isaggr && txok) {
-		if (ATH_DS_TX_BA(ds)) {
-			seq_st = ATH_DS_BA_SEQ(ds);
-			memcpy(ba, ATH_DS_BA_BITMAP(ds),
-			       WME_BA_BMP_SIZE >> 3);
-		} else {
-			/*
-			 * AR5416 can become deaf/mute when BA
-			 * issue happens. Chip needs to be reset.
-			 * But AP code may have sychronization issues
-			 * when perform internal reset in this routine.
-			 * Only enable reset in STA mode for now.
-			 */
-			if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION)
-				needreset = 1;
-		}
-	}
-
-	INIT_LIST_HEAD(&bf_pending);
-	INIT_LIST_HEAD(&bf_head);
-
-	nbad = ath_tx_num_badfrms(sc, bf, txok);
-	while (bf) {
-		txfail = txpending = 0;
-		bf_next = bf->bf_next;
-
-		if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
-			/* transmit completion, subframe is
-			 * acked by block ack */
-			acked_cnt++;
-		} else if (!isaggr && txok) {
-			/* transmit completion */
-			acked_cnt++;
-		} else {
-			if (!(tid->state & AGGR_CLEANUP) &&
-			    ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
-				if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
-					ath_tx_set_retry(sc, bf);
-					txpending = 1;
-				} else {
-					bf->bf_state.bf_type |= BUF_XRETRY;
-					txfail = 1;
-					sendbar = 1;
-					txfail_cnt++;
-				}
-			} else {
-				/*
-				 * cleanup in progress, just fail
-				 * the un-acked sub-frames
-				 */
-				txfail = 1;
-			}
-		}
-
-		if (bf_next == NULL) {
-			INIT_LIST_HEAD(&bf_head);
-		} else {
-			ASSERT(!list_empty(bf_q));
-			list_move_tail(&bf->list, &bf_head);
-		}
-
-		if (!txpending) {
-			/*
-			 * complete the acked-ones/xretried ones; update
-			 * block-ack window
-			 */
-			spin_lock_bh(&txq->axq_lock);
-			ath_tx_update_baw(sc, tid, bf->bf_seqno);
-			spin_unlock_bh(&txq->axq_lock);
-
-			if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
-				ath_tx_rc_status(bf, ds, nbad, txok, true);
-				rc_update = false;
-			} else {
-				ath_tx_rc_status(bf, ds, nbad, txok, false);
-			}
-
-			ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
-		} else {
-			/* retry the un-acked ones */
-			if (bf->bf_next == NULL &&
-			    bf_last->bf_status & ATH_BUFSTATUS_STALE) {
-				struct ath_buf *tbf;
-
-				tbf = ath_clone_txbuf(sc, bf_last);
-				ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc);
-				list_add_tail(&tbf->list, &bf_head);
-			} else {
-				/*
-				 * Clear descriptor status words for
-				 * software retry
-				 */
-				ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc);
-			}
-
-			/*
-			 * Put this buffer to the temporary pending
-			 * queue to retain ordering
-			 */
-			list_splice_tail_init(&bf_head, &bf_pending);
-		}
-
-		bf = bf_next;
-	}
-
-	if (tid->state & AGGR_CLEANUP) {
-		if (tid->baw_head == tid->baw_tail) {
-			tid->state &= ~AGGR_ADDBA_COMPLETE;
-			tid->addba_exchangeattempts = 0;
-			tid->state &= ~AGGR_CLEANUP;
-
-			/* send buffered frames as singles */
-			ath_tx_flush_tid(sc, tid);
-		}
-		rcu_read_unlock();
-		return;
-	}
-
-	/* prepend un-acked frames to the beginning of the pending frame queue */
-	if (!list_empty(&bf_pending)) {
-		spin_lock_bh(&txq->axq_lock);
-		list_splice(&bf_pending, &tid->buf_q);
-		ath_tx_queue_tid(txq, tid);
-		spin_unlock_bh(&txq->axq_lock);
-	}
-
-	rcu_read_unlock();
-
-	if (needreset)
-		ath_reset(sc, false);
-}
-
-static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
-			   struct ath_atx_tid *tid)
-{
-	struct ath_rate_table *rate_table = sc->cur_rate_table;
-	struct sk_buff *skb;
-	struct ieee80211_tx_info *tx_info;
-	struct ieee80211_tx_rate *rates;
-	struct ath_tx_info_priv *tx_info_priv;
-	u32 max_4ms_framelen, frmlen;
-	u16 aggr_limit, legacy = 0, maxampdu;
-	int i;
-
-	skb = (struct sk_buff *)bf->bf_mpdu;
-	tx_info = IEEE80211_SKB_CB(skb);
-	rates = tx_info->control.rates;
-	tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
-
-	/*
-	 * Find the lowest frame length among the rate series that will have a
-	 * 4ms transmit duration.
-	 * TODO - TXOP limit needs to be considered.
-	 */
-	max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
-
-	for (i = 0; i < 4; i++) {
-		if (rates[i].count) {
-			if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) {
-				legacy = 1;
-				break;
-			}
-
-			frmlen = rate_table->info[rates[i].idx].max_4ms_framelen;
-			max_4ms_framelen = min(max_4ms_framelen, frmlen);
-		}
-	}
-
-	/*
-	 * limit aggregate size by the minimum rate if rate selected is
-	 * not a probe rate, if rate selected is a probe rate then
-	 * avoid aggregation of this packet.
-	 */
-	if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
-		return 0;
-
-	aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT);
-
-	/*
-	 * h/w can accept aggregates upto 16 bit lengths (65535).
-	 * The IE, however can hold upto 65536, which shows up here
-	 * as zero. Ignore 65536 since we  are constrained by hw.
-	 */
-	maxampdu = tid->an->maxampdu;
-	if (maxampdu)
-		aggr_limit = min(aggr_limit, maxampdu);
-
-	return aggr_limit;
-}
-
-/*
- * Returns the number of delimiters to be added to
- * meet the minimum required mpdudensity.
- * caller should make sure that the rate is HT rate .
- */
-static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
-				  struct ath_buf *bf, u16 frmlen)
-{
-	struct ath_rate_table *rt = sc->cur_rate_table;
-	struct sk_buff *skb = bf->bf_mpdu;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	u32 nsymbits, nsymbols, mpdudensity;
-	u16 minlen;
-	u8 rc, flags, rix;
-	int width, half_gi, ndelim, mindelim;
-
-	/* Select standard number of delimiters based on frame length alone */
-	ndelim = ATH_AGGR_GET_NDELIM(frmlen);
-
-	/*
-	 * If encryption enabled, hardware requires some more padding between
-	 * subframes.
-	 * TODO - this could be improved to be dependent on the rate.
-	 *      The hardware can keep up at lower rates, but not higher rates
-	 */
-	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR)
-		ndelim += ATH_AGGR_ENCRYPTDELIM;
-
-	/*
-	 * Convert desired mpdu density from microeconds to bytes based
-	 * on highest rate in rate series (i.e. first rate) to determine
-	 * required minimum length for subframe. Take into account
-	 * whether high rate is 20 or 40Mhz and half or full GI.
-	 */
-	mpdudensity = tid->an->mpdudensity;
-
-	/*
-	 * If there is no mpdu density restriction, no further calculation
-	 * is needed.
-	 */
-	if (mpdudensity == 0)
-		return ndelim;
-
-	rix = tx_info->control.rates[0].idx;
-	flags = tx_info->control.rates[0].flags;
-	rc = rt->info[rix].ratecode;
-	width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
-	half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
-
-	if (half_gi)
-		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
-	else
-		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
-
-	if (nsymbols == 0)
-		nsymbols = 1;
-
-	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
-	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
-
-	if (frmlen < minlen) {
-		mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
-		ndelim = max(mindelim, ndelim);
-	}
-
-	return ndelim;
-}
-
-static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
-					     struct ath_atx_tid *tid,
-					     struct list_head *bf_q)
-{
-#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
-	struct ath_buf *bf, *bf_first, *bf_prev = NULL;
-	int rl = 0, nframes = 0, ndelim, prev_al = 0;
-	u16 aggr_limit = 0, al = 0, bpad = 0,
-		al_delta, h_baw = tid->baw_size / 2;
-	enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
-
-	bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
-
-	do {
-		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
-
-		/* do not step over block-ack window */
-		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) {
-			status = ATH_AGGR_BAW_CLOSED;
-			break;
-		}
-
-		if (!rl) {
-			aggr_limit = ath_lookup_rate(sc, bf, tid);
-			rl = 1;
-		}
-
-		/* do not exceed aggregation limit */
-		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen;
-
-		if (nframes &&
-		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
-			status = ATH_AGGR_LIMITED;
-			break;
-		}
-
-		/* do not exceed subframe limit */
-		if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
-			status = ATH_AGGR_LIMITED;
-			break;
-		}
-		nframes++;
-
-		/* add padding for previous frame to aggregation length */
-		al += bpad + al_delta;
-
-		/*
-		 * Get the delimiters needed to meet the MPDU
-		 * density for this node.
-		 */
-		ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
-		bpad = PADBYTES(al_delta) + (ndelim << 2);
-
-		bf->bf_next = NULL;
-		bf->bf_desc->ds_link = 0;
-
-		/* link buffers of this frame to the aggregate */
-		ath_tx_addto_baw(sc, tid, bf);
-		ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
-		list_move_tail(&bf->list, bf_q);
-		if (bf_prev) {
-			bf_prev->bf_next = bf;
-			bf_prev->bf_desc->ds_link = bf->bf_daddr;
-		}
-		bf_prev = bf;
-	} while (!list_empty(&tid->buf_q));
-
-	bf_first->bf_al = al;
-	bf_first->bf_nframes = nframes;
-
-	return status;
-#undef PADBYTES
-}
-
-static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
-			      struct ath_atx_tid *tid)
-{
-	struct ath_buf *bf;
-	enum ATH_AGGR_STATUS status;
-	struct list_head bf_q;
-
-	do {
-		if (list_empty(&tid->buf_q))
-			return;
-
-		INIT_LIST_HEAD(&bf_q);
-
-		status = ath_tx_form_aggr(sc, tid, &bf_q);
-
-		/*
-		 * no frames picked up to be aggregated;
-		 * block-ack window is not open.
-		 */
-		if (list_empty(&bf_q))
-			break;
-
-		bf = list_first_entry(&bf_q, struct ath_buf, list);
-		bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
-
-		/* if only one frame, send as non-aggregate */
-		if (bf->bf_nframes == 1) {
-			bf->bf_state.bf_type &= ~BUF_AGGR;
-			ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
-			ath_buf_set_rate(sc, bf);
-			ath_tx_txqaddbuf(sc, txq, &bf_q);
-			continue;
-		}
-
-		/* setup first desc of aggregate */
-		bf->bf_state.bf_type |= BUF_AGGR;
-		ath_buf_set_rate(sc, bf);
-		ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
-
-		/* anchor last desc of aggregate */
-		ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
-
-		txq->axq_aggr_depth++;
-		ath_tx_txqaddbuf(sc, txq, &bf_q);
-
-	} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
-		 status != ATH_AGGR_BAW_CLOSED);
-}
-
-int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-		      u16 tid, u16 *ssn)
-{
-	struct ath_atx_tid *txtid;
-	struct ath_node *an;
-
-	an = (struct ath_node *)sta->drv_priv;
-
-	if (sc->sc_flags & SC_OP_TXAGGR) {
-		txtid = ATH_AN_2_TID(an, tid);
-		txtid->state |= AGGR_ADDBA_PROGRESS;
-		ath_tx_pause_tid(sc, txtid);
-		*ssn = txtid->seq_start;
-	}
-
-	return 0;
-}
-
-int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
-{
-	struct ath_node *an = (struct ath_node *)sta->drv_priv;
-	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
-	struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
-	struct ath_buf *bf;
-	struct list_head bf_head;
-	INIT_LIST_HEAD(&bf_head);
-
-	if (txtid->state & AGGR_CLEANUP)
-		return 0;
-
-	if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
-		txtid->addba_exchangeattempts = 0;
-		return 0;
-	}
-
-	ath_tx_pause_tid(sc, txtid);
-
-	/* drop all software retried frames and mark this TID */
-	spin_lock_bh(&txq->axq_lock);
-	while (!list_empty(&txtid->buf_q)) {
-		bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
-		if (!bf_isretried(bf)) {
-			/*
-			 * NB: it's based on the assumption that
-			 * software retried frame will always stay
-			 * at the head of software queue.
-			 */
-			break;
-		}
-		list_move_tail(&bf->list, &bf_head);
-		ath_tx_update_baw(sc, txtid, bf->bf_seqno);
-		ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
-	}
-	spin_unlock_bh(&txq->axq_lock);
-
-	if (txtid->baw_head != txtid->baw_tail) {
-		txtid->state |= AGGR_CLEANUP;
-	} else {
-		txtid->state &= ~AGGR_ADDBA_COMPLETE;
-		txtid->addba_exchangeattempts = 0;
-		ath_tx_flush_tid(sc, txtid);
-	}
-
-	return 0;
-}
-
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
-{
-	struct ath_atx_tid *txtid;
-	struct ath_node *an;
-
-	an = (struct ath_node *)sta->drv_priv;
-
-	if (sc->sc_flags & SC_OP_TXAGGR) {
-		txtid = ATH_AN_2_TID(an, tid);
-		txtid->baw_size =
-			IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-		txtid->state |= AGGR_ADDBA_COMPLETE;
-		txtid->state &= ~AGGR_ADDBA_PROGRESS;
-		ath_tx_resume_tid(sc, txtid);
-	}
-}
-
-bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
-{
-	struct ath_atx_tid *txtid;
-
-	if (!(sc->sc_flags & SC_OP_TXAGGR))
-		return false;
-
-	txtid = ATH_AN_2_TID(an, tidno);
-
-	if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
-		if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
-		    (txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
-			txtid->addba_exchangeattempts++;
-			return true;
-		}
-	}
-
-	return false;
-}
-
-/********************/
-/* Queue Management */
-/********************/
-
-static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
-					  struct ath_txq *txq)
-{
-	struct ath_atx_ac *ac, *ac_tmp;
-	struct ath_atx_tid *tid, *tid_tmp;
-
-	list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
-		list_del(&ac->list);
-		ac->sched = false;
-		list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
-			list_del(&tid->list);
-			tid->sched = false;
-			ath_tid_drain(sc, txq, tid);
-		}
-	}
-}
-
-struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath9k_tx_queue_info qi;
-	int qnum;
-
-	memset(&qi, 0, sizeof(qi));
-	qi.tqi_subtype = subtype;
-	qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
-	qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
-	qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
-	qi.tqi_physCompBuf = 0;
-
-	/*
-	 * Enable interrupts only for EOL and DESC conditions.
-	 * We mark tx descriptors to receive a DESC interrupt
-	 * when a tx queue gets deep; otherwise waiting for the
-	 * EOL to reap descriptors.  Note that this is done to
-	 * reduce interrupt load and this only defers reaping
-	 * descriptors, never transmitting frames.  Aside from
-	 * reducing interrupts this also permits more concurrency.
-	 * The only potential downside is if the tx queue backs
-	 * up in which case the top half of the kernel may backup
-	 * due to a lack of tx descriptors.
-	 *
-	 * The UAPSD queue is an exception, since we take a desc-
-	 * based intr on the EOSP frames.
-	 */
-	if (qtype == ATH9K_TX_QUEUE_UAPSD)
-		qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
-	else
-		qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
-			TXQ_FLAG_TXDESCINT_ENABLE;
-	qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
-	if (qnum == -1) {
-		/*
-		 * NB: don't print a message, this happens
-		 * normally on parts with too few tx queues
-		 */
-		return NULL;
-	}
-	if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"qnum %u out of range, max %u!\n",
-			qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
-		ath9k_hw_releasetxqueue(ah, qnum);
-		return NULL;
-	}
-	if (!ATH_TXQ_SETUP(sc, qnum)) {
-		struct ath_txq *txq = &sc->tx.txq[qnum];
-
-		txq->axq_qnum = qnum;
-		txq->axq_link = NULL;
-		INIT_LIST_HEAD(&txq->axq_q);
-		INIT_LIST_HEAD(&txq->axq_acq);
-		spin_lock_init(&txq->axq_lock);
-		txq->axq_depth = 0;
-		txq->axq_aggr_depth = 0;
-		txq->axq_totalqueued = 0;
-		txq->axq_linkbuf = NULL;
-		sc->tx.txqsetup |= 1<<qnum;
-	}
-	return &sc->tx.txq[qnum];
-}
-
-static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
-{
-	int qnum;
-
-	switch (qtype) {
-	case ATH9K_TX_QUEUE_DATA:
-		if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"HAL AC %u out of range, max %zu!\n",
-				haltype, ARRAY_SIZE(sc->tx.hwq_map));
-			return -1;
-		}
-		qnum = sc->tx.hwq_map[haltype];
-		break;
-	case ATH9K_TX_QUEUE_BEACON:
-		qnum = sc->beacon.beaconq;
-		break;
-	case ATH9K_TX_QUEUE_CAB:
-		qnum = sc->beacon.cabq->axq_qnum;
-		break;
-	default:
-		qnum = -1;
-	}
-	return qnum;
-}
-
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
-{
-	struct ath_txq *txq = NULL;
-	int qnum;
-
-	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
-	txq = &sc->tx.txq[qnum];
-
-	spin_lock_bh(&txq->axq_lock);
-
-	if (txq->axq_depth >= (ATH_TXBUF - 20)) {
-		DPRINTF(sc, ATH_DBG_XMIT,
-			"TX queue: %d is full, depth: %d\n",
-			qnum, txq->axq_depth);
-		ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
-		txq->stopped = 1;
-		spin_unlock_bh(&txq->axq_lock);
-		return NULL;
-	}
-
-	spin_unlock_bh(&txq->axq_lock);
-
-	return txq;
-}
-
-int ath_txq_update(struct ath_softc *sc, int qnum,
-		   struct ath9k_tx_queue_info *qinfo)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	int error = 0;
-	struct ath9k_tx_queue_info qi;
-
-	if (qnum == sc->beacon.beaconq) {
-		/*
-		 * XXX: for beacon queue, we just save the parameter.
-		 * It will be picked up by ath_beaconq_config when
-		 * it's necessary.
-		 */
-		sc->beacon.beacon_qi = *qinfo;
-		return 0;
-	}
-
-	ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
-
-	ath9k_hw_get_txq_props(ah, qnum, &qi);
-	qi.tqi_aifs = qinfo->tqi_aifs;
-	qi.tqi_cwmin = qinfo->tqi_cwmin;
-	qi.tqi_cwmax = qinfo->tqi_cwmax;
-	qi.tqi_burstTime = qinfo->tqi_burstTime;
-	qi.tqi_readyTime = qinfo->tqi_readyTime;
-
-	if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to update hardware queue %u!\n", qnum);
-		error = -EIO;
-	} else {
-		ath9k_hw_resettxqueue(ah, qnum);
-	}
-
-	return error;
-}
-
-int ath_cabq_update(struct ath_softc *sc)
-{
-	struct ath9k_tx_queue_info qi;
-	int qnum = sc->beacon.cabq->axq_qnum;
-
-	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
-	/*
-	 * Ensure the readytime % is within the bounds.
-	 */
-	if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
-		sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
-	else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
-		sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
-
-	qi.tqi_readyTime = (sc->hw->conf.beacon_int *
-			    sc->config.cabqReadytime) / 100;
-	ath_txq_update(sc, qnum, &qi);
-
-	return 0;
-}
-
-/*
- * Drain a given TX queue (could be Beacon or Data)
- *
- * This assumes output has been stopped and
- * we do not need to block ath_tx_tasklet.
- */
-void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
-{
-	struct ath_buf *bf, *lastbf;
-	struct list_head bf_head;
-
-	INIT_LIST_HEAD(&bf_head);
-
-	for (;;) {
-		spin_lock_bh(&txq->axq_lock);
-
-		if (list_empty(&txq->axq_q)) {
-			txq->axq_link = NULL;
-			txq->axq_linkbuf = NULL;
-			spin_unlock_bh(&txq->axq_lock);
-			break;
-		}
-
-		bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
-
-		if (bf->bf_status & ATH_BUFSTATUS_STALE) {
-			list_del(&bf->list);
-			spin_unlock_bh(&txq->axq_lock);
-
-			spin_lock_bh(&sc->tx.txbuflock);
-			list_add_tail(&bf->list, &sc->tx.txbuf);
-			spin_unlock_bh(&sc->tx.txbuflock);
-			continue;
-		}
-
-		lastbf = bf->bf_lastbf;
-		if (!retry_tx)
-			lastbf->bf_desc->ds_txstat.ts_flags =
-				ATH9K_TX_SW_ABORTED;
-
-		/* remove ath_buf's of the same mpdu from txq */
-		list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
-		txq->axq_depth--;
-
-		spin_unlock_bh(&txq->axq_lock);
-
-		if (bf_isampdu(bf))
-			ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
-		else
-			ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
-	}
-
-	/* flush any pending frames if aggregation is enabled */
-	if (sc->sc_flags & SC_OP_TXAGGR) {
-		if (!retry_tx) {
-			spin_lock_bh(&txq->axq_lock);
-			ath_txq_drain_pending_buffers(sc, txq);
-			spin_unlock_bh(&txq->axq_lock);
-		}
-	}
-}
-
-void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_txq *txq;
-	int i, npend = 0;
-
-	if (sc->sc_flags & SC_OP_INVALID)
-		return;
-
-	/* Stop beacon queue */
-	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-
-	/* Stop data queues */
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (ATH_TXQ_SETUP(sc, i)) {
-			txq = &sc->tx.txq[i];
-			ath9k_hw_stoptxdma(ah, txq->axq_qnum);
-			npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
-		}
-	}
-
-	if (npend) {
-		int r;
-
-		DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
-
-		spin_lock_bh(&sc->sc_resetlock);
-		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true);
-		if (r)
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Unable to reset hardware; reset status %u\n",
-				r);
-		spin_unlock_bh(&sc->sc_resetlock);
-	}
-
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
-	}
-}
-
-void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
-{
-	ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
-	sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
-}
-
-void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
-{
-	struct ath_atx_ac *ac;
-	struct ath_atx_tid *tid;
-
-	if (list_empty(&txq->axq_acq))
-		return;
-
-	ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
-	list_del(&ac->list);
-	ac->sched = false;
-
-	do {
-		if (list_empty(&ac->tid_q))
-			return;
-
-		tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
-		list_del(&tid->list);
-		tid->sched = false;
-
-		if (tid->paused)
-			continue;
-
-		if ((txq->axq_depth % 2) == 0)
-			ath_tx_sched_aggr(sc, txq, tid);
-
-		/*
-		 * add tid to round-robin queue if more frames
-		 * are pending for the tid
-		 */
-		if (!list_empty(&tid->buf_q))
-			ath_tx_queue_tid(txq, tid);
-
-		break;
-	} while (!list_empty(&ac->tid_q));
-
-	if (!list_empty(&ac->tid_q)) {
-		if (!ac->sched) {
-			ac->sched = true;
-			list_add_tail(&ac->list, &txq->axq_acq);
-		}
-	}
-}
-
-int ath_tx_setup(struct ath_softc *sc, int haltype)
-{
-	struct ath_txq *txq;
-
-	if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"HAL AC %u out of range, max %zu!\n",
-			 haltype, ARRAY_SIZE(sc->tx.hwq_map));
-		return 0;
-	}
-	txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
-	if (txq != NULL) {
-		sc->tx.hwq_map[haltype] = txq->axq_qnum;
-		return 1;
-	} else
-		return 0;
-}
-
-/***********/
-/* TX, DMA */
-/***********/
-
-/*
- * Insert a chain of ath_buf (descriptors) on a txq and
- * assume the descriptors are already chained together by caller.
- */
-static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
-			     struct list_head *head)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_buf *bf;
-
-	/*
-	 * Insert the frame on the outbound list and
-	 * pass it on to the hardware.
-	 */
-
-	if (list_empty(head))
-		return;
-
-	bf = list_first_entry(head, struct ath_buf, list);
-
-	list_splice_tail_init(head, &txq->axq_q);
-	txq->axq_depth++;
-	txq->axq_totalqueued++;
-	txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
-
-	DPRINTF(sc, ATH_DBG_QUEUE,
-		"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
-
-	if (txq->axq_link == NULL) {
-		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-		DPRINTF(sc, ATH_DBG_XMIT,
-			"TXDP[%u] = %llx (%p)\n",
-			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
-	} else {
-		*txq->axq_link = bf->bf_daddr;
-		DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n",
-			txq->axq_qnum, txq->axq_link,
-			ito64(bf->bf_daddr), bf->bf_desc);
-	}
-	txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
-	ath9k_hw_txstart(ah, txq->axq_qnum);
-}
-
-static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
-{
-	struct ath_buf *bf = NULL;
-
-	spin_lock_bh(&sc->tx.txbuflock);
-
-	if (unlikely(list_empty(&sc->tx.txbuf))) {
-		spin_unlock_bh(&sc->tx.txbuflock);
-		return NULL;
-	}
-
-	bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
-	list_del(&bf->list);
-
-	spin_unlock_bh(&sc->tx.txbuflock);
-
-	return bf;
-}
-
-static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
-			      struct list_head *bf_head,
-			      struct ath_tx_control *txctl)
-{
-	struct ath_buf *bf;
-
-	bf = list_first_entry(bf_head, struct ath_buf, list);
-	bf->bf_state.bf_type |= BUF_AMPDU;
-
-	/*
-	 * Do not queue to h/w when any of the following conditions is true:
-	 * - there are pending frames in software queue
-	 * - the TID is currently paused for ADDBA/BAR request
-	 * - seqno is not within block-ack window
-	 * - h/w queue depth exceeds low water mark
-	 */
-	if (!list_empty(&tid->buf_q) || tid->paused ||
-	    !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) ||
-	    txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
-		/*
-		 * Add this frame to software queue for scheduling later
-		 * for aggregation.
-		 */
-		list_move_tail(&bf->list, &tid->buf_q);
-		ath_tx_queue_tid(txctl->txq, tid);
-		return;
-	}
-
-	/* Add sub-frame to BAW */
-	ath_tx_addto_baw(sc, tid, bf);
-
-	/* Queue to h/w without aggregation */
-	bf->bf_nframes = 1;
-	bf->bf_lastbf = bf;
-	ath_buf_set_rate(sc, bf);
-	ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
-}
-
-static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
-				  struct ath_atx_tid *tid,
-				  struct list_head *bf_head)
-{
-	struct ath_buf *bf;
-
-	bf = list_first_entry(bf_head, struct ath_buf, list);
-	bf->bf_state.bf_type &= ~BUF_AMPDU;
-
-	/* update starting sequence number for subsequent ADDBA request */
-	INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-
-	bf->bf_nframes = 1;
-	bf->bf_lastbf = bf;
-	ath_buf_set_rate(sc, bf);
-	ath_tx_txqaddbuf(sc, txq, bf_head);
-}
-
-static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
-			       struct list_head *bf_head)
-{
-	struct ath_buf *bf;
-
-	bf = list_first_entry(bf_head, struct ath_buf, list);
-
-	bf->bf_lastbf = bf;
-	bf->bf_nframes = 1;
-	ath_buf_set_rate(sc, bf);
-	ath_tx_txqaddbuf(sc, txq, bf_head);
-}
-
-static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
-{
-	struct ieee80211_hdr *hdr;
-	enum ath9k_pkt_type htype;
-	__le16 fc;
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-
-	if (ieee80211_is_beacon(fc))
-		htype = ATH9K_PKT_TYPE_BEACON;
-	else if (ieee80211_is_probe_resp(fc))
-		htype = ATH9K_PKT_TYPE_PROBE_RESP;
-	else if (ieee80211_is_atim(fc))
-		htype = ATH9K_PKT_TYPE_ATIM;
-	else if (ieee80211_is_pspoll(fc))
-		htype = ATH9K_PKT_TYPE_PSPOLL;
-	else
-		htype = ATH9K_PKT_TYPE_NORMAL;
-
-	return htype;
-}
-
-static bool is_pae(struct sk_buff *skb)
-{
-	struct ieee80211_hdr *hdr;
-	__le16 fc;
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-
-	if (ieee80211_is_data(fc)) {
-		if (ieee80211_is_nullfunc(fc) ||
-		    /* Port Access Entity (IEEE 802.1X) */
-		    (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-			return true;
-		}
-	}
-
-	return false;
-}
-
-static int get_hw_crypto_keytype(struct sk_buff *skb)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-
-	if (tx_info->control.hw_key) {
-		if (tx_info->control.hw_key->alg == ALG_WEP)
-			return ATH9K_KEY_TYPE_WEP;
-		else if (tx_info->control.hw_key->alg == ALG_TKIP)
-			return ATH9K_KEY_TYPE_TKIP;
-		else if (tx_info->control.hw_key->alg == ALG_CCMP)
-			return ATH9K_KEY_TYPE_AES;
-	}
-
-	return ATH9K_KEY_TYPE_CLEAR;
-}
-
-static void assign_aggr_tid_seqno(struct sk_buff *skb,
-				  struct ath_buf *bf)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *hdr;
-	struct ath_node *an;
-	struct ath_atx_tid *tid;
-	__le16 fc;
-	u8 *qc;
-
-	if (!tx_info->control.sta)
-		return;
-
-	an = (struct ath_node *)tx_info->control.sta->drv_priv;
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-
-	if (ieee80211_is_data_qos(fc)) {
-		qc = ieee80211_get_qos_ctl(hdr);
-		bf->bf_tidno = qc[0] & 0xf;
-	}
-
-	/*
-	 * For HT capable stations, we save tidno for later use.
-	 * We also override seqno set by upper layer with the one
-	 * in tx aggregation state.
-	 *
-	 * If fragmentation is on, the sequence number is
-	 * not overridden, since it has been
-	 * incremented by the fragmentation routine.
-	 *
-	 * FIXME: check if the fragmentation threshold exceeds
-	 * IEEE80211 max.
-	 */
-	tid = ATH_AN_2_TID(an, bf->bf_tidno);
-	hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
-			IEEE80211_SEQ_SEQ_SHIFT);
-	bf->bf_seqno = tid->seq_next;
-	INCR(tid->seq_next, IEEE80211_SEQ_MAX);
-}
-
-static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
-			  struct ath_txq *txq)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	int flags = 0;
-
-	flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
-	flags |= ATH9K_TXDESC_INTREQ;
-
-	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-		flags |= ATH9K_TXDESC_NOACK;
-
-	return flags;
-}
-
-/*
- * rix - rate index
- * pktlen - total bytes (delims + data + fcs + pads + pad delims)
- * width  - 0 for 20 MHz, 1 for 40 MHz
- * half_gi - to use 4us v/s 3.6 us for symbol time
- */
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
-			    int width, int half_gi, bool shortPreamble)
-{
-	struct ath_rate_table *rate_table = sc->cur_rate_table;
-	u32 nbits, nsymbits, duration, nsymbols;
-	u8 rc;
-	int streams, pktlen;
-
-	pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
-	rc = rate_table->info[rix].ratecode;
-
-	/* for legacy rates, use old function to compute packet duration */
-	if (!IS_HT_RATE(rc))
-		return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
-					      rix, shortPreamble);
-
-	/* find number of symbols: PLCP + data */
-	nbits = (pktlen << 3) + OFDM_PLCP_BITS;
-	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
-	nsymbols = (nbits + nsymbits - 1) / nsymbits;
-
-	if (!half_gi)
-		duration = SYMBOL_TIME(nsymbols);
-	else
-		duration = SYMBOL_TIME_HALFGI(nsymbols);
-
-	/* addup duration for legacy/ht training and signal fields */
-	streams = HT_RC_2_STREAMS(rc);
-	duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
-
-	return duration;
-}
-
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
-{
-	struct ath_rate_table *rt = sc->cur_rate_table;
-	struct ath9k_11n_rate_series series[4];
-	struct sk_buff *skb;
-	struct ieee80211_tx_info *tx_info;
-	struct ieee80211_tx_rate *rates;
-	struct ieee80211_hdr *hdr;
-	int i, flags = 0;
-	u8 rix = 0, ctsrate = 0;
-	bool is_pspoll;
-
-	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
-
-	skb = (struct sk_buff *)bf->bf_mpdu;
-	tx_info = IEEE80211_SKB_CB(skb);
-	rates = tx_info->control.rates;
-	hdr = (struct ieee80211_hdr *)skb->data;
-	is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
-
-	/*
-	 * We check if Short Preamble is needed for the CTS rate by
-	 * checking the BSS's global flag.
-	 * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
-	 */
-	if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
-		ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode |
-			rt->info[tx_info->control.rts_cts_rate_idx].short_preamble;
-	else
-		ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode;
-
-	/*
-	 * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive.
-	 * Check the first rate in the series to decide whether RTS/CTS
-	 * or CTS-to-self has to be used.
-	 */
-	if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
-		flags = ATH9K_TXDESC_CTSENA;
-	else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
-		flags = ATH9K_TXDESC_RTSENA;
-
-	/* FIXME: Handle aggregation protection */
-	if (sc->config.ath_aggr_prot &&
-	    (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
-		flags = ATH9K_TXDESC_RTSENA;
-	}
-
-	/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
-	if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
-		flags &= ~(ATH9K_TXDESC_RTSENA);
-
-	for (i = 0; i < 4; i++) {
-		if (!rates[i].count || (rates[i].idx < 0))
-			continue;
-
-		rix = rates[i].idx;
-		series[i].Tries = rates[i].count;
-		series[i].ChSel = sc->tx_chainmask;
-
-		if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-			series[i].Rate = rt->info[rix].ratecode |
-				rt->info[rix].short_preamble;
-		else
-			series[i].Rate = rt->info[rix].ratecode;
-
-		if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)
-			series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-		if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-			series[i].RateFlags |= ATH9K_RATESERIES_2040;
-		if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
-			series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
-
-		series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
-			 (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0,
-			 (rates[i].flags & IEEE80211_TX_RC_SHORT_GI),
-			 (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE));
-	}
-
-	/* set dur_update_en for l-sig computation except for PS-Poll frames */
-	ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
-				     bf->bf_lastbf->bf_desc,
-				     !is_pspoll, ctsrate,
-				     0, series, 4, flags);
-
-	if (sc->config.ath_aggr_prot && flags)
-		ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192);
-}
-
-static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
-				struct sk_buff *skb,
-				struct ath_tx_control *txctl)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ath_tx_info_priv *tx_info_priv;
-	int hdrlen;
-	__le16 fc;
-
-	tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
-	if (unlikely(!tx_info_priv))
-		return -ENOMEM;
-	tx_info->rate_driver_data[0] = tx_info_priv;
-	tx_info_priv->aphy = aphy;
-	tx_info_priv->frame_type = txctl->frame_type;
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	fc = hdr->frame_control;
-
-	ATH_TXBUF_RESET(bf);
-
-	bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
-
-	if (conf_is_ht(&sc->hw->conf) && !is_pae(skb))
-		bf->bf_state.bf_type |= BUF_HT;
-
-	bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
-
-	bf->bf_keytype = get_hw_crypto_keytype(skb);
-	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
-		bf->bf_frmlen += tx_info->control.hw_key->icv_len;
-		bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
-	} else {
-		bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
-	}
-
-	if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR))
-		assign_aggr_tid_seqno(skb, bf);
-
-	bf->bf_mpdu = skb;
-
-	bf->bf_dmacontext = dma_map_single(sc->dev, skb->data,
-					   skb->len, DMA_TO_DEVICE);
-	if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
-		bf->bf_mpdu = NULL;
-		DPRINTF(sc, ATH_DBG_CONFIG,
-			"dma_mapping_error() on TX\n");
-		return -ENOMEM;
-	}
-
-	bf->bf_buf_addr = bf->bf_dmacontext;
-	return 0;
-}
-
-/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
-			     struct ath_tx_control *txctl)
-{
-	struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
-	struct ieee80211_tx_info *tx_info =  IEEE80211_SKB_CB(skb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ath_node *an = NULL;
-	struct list_head bf_head;
-	struct ath_desc *ds;
-	struct ath_atx_tid *tid;
-	struct ath_hw *ah = sc->sc_ah;
-	int frm_type;
-	__le16 fc;
-
-	frm_type = get_hw_packet_type(skb);
-	fc = hdr->frame_control;
-
-	INIT_LIST_HEAD(&bf_head);
-	list_add_tail(&bf->list, &bf_head);
-
-	ds = bf->bf_desc;
-	ds->ds_link = 0;
-	ds->ds_data = bf->bf_buf_addr;
-
-	ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
-			       bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
-
-	ath9k_hw_filltxdesc(ah, ds,
-			    skb->len,	/* segment length */
-			    true,	/* first segment */
-			    true,	/* last segment */
-			    ds);	/* first descriptor */
-
-	spin_lock_bh(&txctl->txq->axq_lock);
-
-	if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
-	    tx_info->control.sta) {
-		an = (struct ath_node *)tx_info->control.sta->drv_priv;
-		tid = ATH_AN_2_TID(an, bf->bf_tidno);
-
-		if (!ieee80211_is_data_qos(fc)) {
-			ath_tx_send_normal(sc, txctl->txq, &bf_head);
-			goto tx_done;
-		}
-
-		if (ath_aggr_query(sc, an, bf->bf_tidno)) {
-			/*
-			 * Try aggregation if it's a unicast data frame
-			 * and the destination is HT capable.
-			 */
-			ath_tx_send_ampdu(sc, tid, &bf_head, txctl);
-		} else {
-			/*
-			 * Send this frame as regular when ADDBA
-			 * exchange is neither complete nor pending.
-			 */
-			ath_tx_send_ht_normal(sc, txctl->txq,
-					      tid, &bf_head);
-		}
-	} else {
-		ath_tx_send_normal(sc, txctl->txq, &bf_head);
-	}
-
-tx_done:
-	spin_unlock_bh(&txctl->txq->axq_lock);
-}
-
-/* Upon failure caller should free skb */
-int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
-		 struct ath_tx_control *txctl)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_buf *bf;
-	int r;
-
-	bf = ath_tx_get_buffer(sc);
-	if (!bf) {
-		DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n");
-		return -1;
-	}
-
-	r = ath_tx_setup_buffer(hw, bf, skb, txctl);
-	if (unlikely(r)) {
-		struct ath_txq *txq = txctl->txq;
-
-		DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n");
-
-		/* upon ath_tx_processq() this TX queue will be resumed, we
-		 * guarantee this will happen by knowing beforehand that
-		 * we will at least have to run TX completionon one buffer
-		 * on the queue */
-		spin_lock_bh(&txq->axq_lock);
-		if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
-			ieee80211_stop_queue(sc->hw,
-				skb_get_queue_mapping(skb));
-			txq->stopped = 1;
-		}
-		spin_unlock_bh(&txq->axq_lock);
-
-		spin_lock_bh(&sc->tx.txbuflock);
-		list_add_tail(&bf->list, &sc->tx.txbuf);
-		spin_unlock_bh(&sc->tx.txbuflock);
-
-		return r;
-	}
-
-	ath_tx_start_dma(sc, bf, txctl);
-
-	return 0;
-}
-
-void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	int hdrlen, padsize;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ath_tx_control txctl;
-
-	memset(&txctl, 0, sizeof(struct ath_tx_control));
-
-	/*
-	 * As a temporary workaround, assign seq# here; this will likely need
-	 * to be cleaned up to work better with Beacon transmission and virtual
-	 * BSSes.
-	 */
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
-			sc->tx.seq_no += 0x10;
-		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
-	}
-
-	/* Add the padding after the header if this is not already done */
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	if (hdrlen & 3) {
-		padsize = hdrlen % 4;
-		if (skb_headroom(skb) < padsize) {
-			DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n");
-			dev_kfree_skb_any(skb);
-			return;
-		}
-		skb_push(skb, padsize);
-		memmove(skb->data, skb->data + padsize, hdrlen);
-	}
-
-	txctl.txq = sc->beacon.cabq;
-
-	DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);
-
-	if (ath_tx_start(hw, skb, &txctl) != 0) {
-		DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n");
-		goto exit;
-	}
-
-	return;
-exit:
-	dev_kfree_skb_any(skb);
-}
-
-/*****************/
-/* TX Completion */
-/*****************/
-
-static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-			    int tx_flags)
-{
-	struct ieee80211_hw *hw = sc->hw;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-	int hdrlen, padsize;
-	int frame_type = ATH9K_NOT_INTERNAL;
-
-	DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
-
-	if (tx_info_priv) {
-		hw = tx_info_priv->aphy->hw;
-		frame_type = tx_info_priv->frame_type;
-	}
-
-	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
-	    tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
-		kfree(tx_info_priv);
-		tx_info->rate_driver_data[0] = NULL;
-	}
-
-	if (tx_flags & ATH_TX_BAR)
-		tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-
-	if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
-		/* Frame was ACKed */
-		tx_info->flags |= IEEE80211_TX_STAT_ACK;
-	}
-
-	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-	padsize = hdrlen & 3;
-	if (padsize && hdrlen >= 24) {
-		/*
-		 * Remove MAC header padding before giving the frame back to
-		 * mac80211.
-		 */
-		memmove(skb->data + padsize, skb->data, hdrlen);
-		skb_pull(skb, padsize);
-	}
-
-	if (frame_type == ATH9K_NOT_INTERNAL)
-		ieee80211_tx_status(hw, skb);
-	else
-		ath9k_tx_status(hw, skb);
-}
-
-static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
-				struct list_head *bf_q,
-				int txok, int sendbar)
-{
-	struct sk_buff *skb = bf->bf_mpdu;
-	unsigned long flags;
-	int tx_flags = 0;
-
-
-	if (sendbar)
-		tx_flags = ATH_TX_BAR;
-
-	if (!txok) {
-		tx_flags |= ATH_TX_ERROR;
-
-		if (bf_isxretried(bf))
-			tx_flags |= ATH_TX_XRETRY;
-	}
-
-	dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
-	ath_tx_complete(sc, skb, tx_flags);
-
-	/*
-	 * Return the list of ath_buf of this mpdu to free queue
-	 */
-	spin_lock_irqsave(&sc->tx.txbuflock, flags);
-	list_splice_tail_init(bf_q, &sc->tx.txbuf);
-	spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
-}
-
-static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
-			      int txok)
-{
-	struct ath_buf *bf_last = bf->bf_lastbf;
-	struct ath_desc *ds = bf_last->bf_desc;
-	u16 seq_st = 0;
-	u32 ba[WME_BA_BMP_SIZE >> 5];
-	int ba_index;
-	int nbad = 0;
-	int isaggr = 0;
-
-	if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
-		return 0;
-
-	isaggr = bf_isaggr(bf);
-	if (isaggr) {
-		seq_st = ATH_DS_BA_SEQ(ds);
-		memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
-	}
-
-	while (bf) {
-		ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno);
-		if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
-			nbad++;
-
-		bf = bf->bf_next;
-	}
-
-	return nbad;
-}
-
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
-			     int nbad, int txok, bool update_rc)
-{
-	struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-	struct ieee80211_hw *hw = tx_info_priv->aphy->hw;
-	u8 i, tx_rateindex;
-
-	if (txok)
-		tx_info->status.ack_signal = ds->ds_txstat.ts_rssi;
-
-	tx_rateindex = ds->ds_txstat.ts_rateindex;
-	WARN_ON(tx_rateindex >= hw->max_rates);
-
-	tx_info_priv->update_rc = update_rc;
-	if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
-		tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-
-	if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
-	    (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
-		if (ieee80211_is_data(hdr->frame_control)) {
-			memcpy(&tx_info_priv->tx, &ds->ds_txstat,
-			       sizeof(tx_info_priv->tx));
-			tx_info_priv->n_frames = bf->bf_nframes;
-			tx_info_priv->n_bad_frames = nbad;
-		}
-	}
-
-	for (i = tx_rateindex + 1; i < hw->max_rates; i++)
-		tx_info->status.rates[i].count = 0;
-
-	tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1;
-}
-
-static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
-{
-	int qnum;
-
-	spin_lock_bh(&txq->axq_lock);
-	if (txq->stopped &&
-	    sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
-		qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
-		if (qnum != -1) {
-			ieee80211_wake_queue(sc->hw, qnum);
-			txq->stopped = 0;
-		}
-	}
-	spin_unlock_bh(&txq->axq_lock);
-}
-
-static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
-{
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_buf *bf, *lastbf, *bf_held = NULL;
-	struct list_head bf_head;
-	struct ath_desc *ds;
-	int txok;
-	int status;
-
-	DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
-		txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
-		txq->axq_link);
-
-	for (;;) {
-		spin_lock_bh(&txq->axq_lock);
-		if (list_empty(&txq->axq_q)) {
-			txq->axq_link = NULL;
-			txq->axq_linkbuf = NULL;
-			spin_unlock_bh(&txq->axq_lock);
-			break;
-		}
-		bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
-
-		/*
-		 * There is a race condition that a BH gets scheduled
-		 * after sw writes TxE and before hw re-load the last
-		 * descriptor to get the newly chained one.
-		 * Software must keep the last DONE descriptor as a
-		 * holding descriptor - software does so by marking
-		 * it with the STALE flag.
-		 */
-		bf_held = NULL;
-		if (bf->bf_status & ATH_BUFSTATUS_STALE) {
-			bf_held = bf;
-			if (list_is_last(&bf_held->list, &txq->axq_q)) {
-				txq->axq_link = NULL;
-				txq->axq_linkbuf = NULL;
-				spin_unlock_bh(&txq->axq_lock);
-
-				/*
-				 * The holding descriptor is the last
-				 * descriptor in queue. It's safe to remove
-				 * the last holding descriptor in BH context.
-				 */
-				spin_lock_bh(&sc->tx.txbuflock);
-				list_move_tail(&bf_held->list, &sc->tx.txbuf);
-				spin_unlock_bh(&sc->tx.txbuflock);
-
-				break;
-			} else {
-				bf = list_entry(bf_held->list.next,
-						struct ath_buf, list);
-			}
-		}
-
-		lastbf = bf->bf_lastbf;
-		ds = lastbf->bf_desc;
-
-		status = ath9k_hw_txprocdesc(ah, ds);
-		if (status == -EINPROGRESS) {
-			spin_unlock_bh(&txq->axq_lock);
-			break;
-		}
-		if (bf->bf_desc == txq->axq_lastdsWithCTS)
-			txq->axq_lastdsWithCTS = NULL;
-		if (ds == txq->axq_gatingds)
-			txq->axq_gatingds = NULL;
-
-		/*
-		 * Remove ath_buf's of the same transmit unit from txq,
-		 * however leave the last descriptor back as the holding
-		 * descriptor for hw.
-		 */
-		lastbf->bf_status |= ATH_BUFSTATUS_STALE;
-		INIT_LIST_HEAD(&bf_head);
-		if (!list_is_singular(&lastbf->list))
-			list_cut_position(&bf_head,
-				&txq->axq_q, lastbf->list.prev);
-
-		txq->axq_depth--;
-		if (bf_isaggr(bf))
-			txq->axq_aggr_depth--;
-
-		txok = (ds->ds_txstat.ts_status == 0);
-		spin_unlock_bh(&txq->axq_lock);
-
-		if (bf_held) {
-			spin_lock_bh(&sc->tx.txbuflock);
-			list_move_tail(&bf_held->list, &sc->tx.txbuf);
-			spin_unlock_bh(&sc->tx.txbuflock);
-		}
-
-		if (!bf_isampdu(bf)) {
-			/*
-			 * This frame is sent out as a single frame.
-			 * Use hardware retry status for this frame.
-			 */
-			bf->bf_retries = ds->ds_txstat.ts_longretry;
-			if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
-				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, ds, 0, txok, true);
-		}
-
-		if (bf_isampdu(bf))
-			ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
-		else
-			ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
-
-		ath_wake_mac80211_queue(sc, txq);
-
-		spin_lock_bh(&txq->axq_lock);
-		if (sc->sc_flags & SC_OP_TXAGGR)
-			ath_txq_schedule(sc, txq);
-		spin_unlock_bh(&txq->axq_lock);
-	}
-}
-
-
-void ath_tx_tasklet(struct ath_softc *sc)
-{
-	int i;
-	u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
-
-	ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
-
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
-			ath_tx_processq(sc, &sc->tx.txq[i]);
-	}
-}
-
-/*****************/
-/* Init, Cleanup */
-/*****************/
-
-int ath_tx_init(struct ath_softc *sc, int nbufs)
-{
-	int error = 0;
-
-	do {
-		spin_lock_init(&sc->tx.txbuflock);
-
-		error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
-			"tx", nbufs, 1);
-		if (error != 0) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Failed to allocate tx descriptors: %d\n",
-				error);
-			break;
-		}
-
-		error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
-					  "beacon", ATH_BCBUF, 1);
-		if (error != 0) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Failed to allocate beacon descriptors: %d\n",
-				error);
-			break;
-		}
-
-	} while (0);
-
-	if (error != 0)
-		ath_tx_cleanup(sc);
-
-	return error;
-}
-
-int ath_tx_cleanup(struct ath_softc *sc)
-{
-	if (sc->beacon.bdma.dd_desc_len != 0)
-		ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
-
-	if (sc->tx.txdma.dd_desc_len != 0)
-		ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
-
-	return 0;
-}
-
-void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
-{
-	struct ath_atx_tid *tid;
-	struct ath_atx_ac *ac;
-	int tidno, acno;
-
-	for (tidno = 0, tid = &an->tid[tidno];
-	     tidno < WME_NUM_TID;
-	     tidno++, tid++) {
-		tid->an        = an;
-		tid->tidno     = tidno;
-		tid->seq_start = tid->seq_next = 0;
-		tid->baw_size  = WME_MAX_BA;
-		tid->baw_head  = tid->baw_tail = 0;
-		tid->sched     = false;
-		tid->paused    = false;
-		tid->state &= ~AGGR_CLEANUP;
-		INIT_LIST_HEAD(&tid->buf_q);
-		acno = TID_TO_WME_AC(tidno);
-		tid->ac = &an->ac[acno];
-		tid->state &= ~AGGR_ADDBA_COMPLETE;
-		tid->state &= ~AGGR_ADDBA_PROGRESS;
-		tid->addba_exchangeattempts = 0;
-	}
-
-	for (acno = 0, ac = &an->ac[acno];
-	     acno < WME_NUM_AC; acno++, ac++) {
-		ac->sched    = false;
-		INIT_LIST_HEAD(&ac->tid_q);
-
-		switch (acno) {
-		case WME_AC_BE:
-			ac->qnum = ath_tx_get_qnum(sc,
-				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
-			break;
-		case WME_AC_BK:
-			ac->qnum = ath_tx_get_qnum(sc,
-				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK);
-			break;
-		case WME_AC_VI:
-			ac->qnum = ath_tx_get_qnum(sc,
-				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI);
-			break;
-		case WME_AC_VO:
-			ac->qnum = ath_tx_get_qnum(sc,
-				   ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO);
-			break;
-		}
-	}
-}
-
-void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
-{
-	int i;
-	struct ath_atx_ac *ac, *ac_tmp;
-	struct ath_atx_tid *tid, *tid_tmp;
-	struct ath_txq *txq;
-
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (ATH_TXQ_SETUP(sc, i)) {
-			txq = &sc->tx.txq[i];
-
-			spin_lock(&txq->axq_lock);
-
-			list_for_each_entry_safe(ac,
-					ac_tmp, &txq->axq_acq, list) {
-				tid = list_first_entry(&ac->tid_q,
-						struct ath_atx_tid, list);
-				if (tid && tid->an != an)
-					continue;
-				list_del(&ac->list);
-				ac->sched = false;
-
-				list_for_each_entry_safe(tid,
-						tid_tmp, &ac->tid_q, list) {
-					list_del(&tid->list);
-					tid->sched = false;
-					ath_tid_drain(sc, txq, tid);
-					tid->state &= ~AGGR_ADDBA_COMPLETE;
-					tid->addba_exchangeattempts = 0;
-					tid->state &= ~AGGR_CLEANUP;
-				}
-			}
-
-			spin_unlock(&txq->axq_lock);
-		}
-	}
-}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/atmel.c linux-libre-2.6.31-gnu/drivers/net/wireless/atmel.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/atmel.c	2012-03-22 19:16:20.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/atmel.c	2012-03-22 20:12:10.000000000 -0400
@@ -818,7 +818,7 @@
 		spin_unlock_irqrestore(&priv->irqlock, flags);
 		spin_unlock_bh(&priv->timerlock);
 		netif_stop_queue(dev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	frame_ctl = IEEE80211_FTYPE_DATA;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/atmel_cs.c linux-libre-2.6.31-gnu/drivers/net/wireless/atmel_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/atmel_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/atmel_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -279,7 +279,7 @@
 	struct pcmcia_device_id *did;
 
 	dev = link->priv;
-	did = handle_to_dev(link).driver_data;
+	did = dev_get_drvdata(&handle_to_dev(link));
 
 	DEBUG(0, "atmel_config(0x%p)\n", link);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/b43.h linux-libre-2.6.31-gnu/drivers/net/wireless/b43/b43.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/b43.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/b43.h	2009-09-09 18:13:59.000000000 -0400
@@ -163,6 +163,7 @@
 #define B43_SHM_SH_WLCOREREV		0x0016	/* 802.11 core revision */
 #define B43_SHM_SH_PCTLWDPOS		0x0008
 #define B43_SHM_SH_RXPADOFF		0x0034	/* RX Padding data offset (PIO only) */
+#define B43_SHM_SH_FWCAPA		0x0042	/* Firmware capabilities (Opensource firmware only) */
 #define B43_SHM_SH_PHYVER		0x0050	/* PHY version */
 #define B43_SHM_SH_PHYTYPE		0x0052	/* PHY type */
 #define B43_SHM_SH_ANTSWAP		0x005C	/* Antenna swap threshold */
@@ -297,6 +298,10 @@
 #define B43_HF_MLADVW		0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
 #define B43_HF_PR45960W		0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
 
+/* Firmware capabilities field in SHM (Opensource firmware only) */
+#define B43_FWCAPA_HWCRYPTO	0x0001
+#define B43_FWCAPA_QOS		0x0002
+
 /* MacFilter offsets. */
 #define B43_MACFILTER_SELF		0x0000
 #define B43_MACFILTER_BSSID		0x0003
@@ -596,6 +601,13 @@
 	/* Pointer to the ieee80211 hardware data structure */
 	struct ieee80211_hw *hw;
 
+	/* The number of queues that were registered with the mac80211 subsystem
+	 * initially. This is a backup copy of hw->queues in case hw->queues has
+	 * to be dynamically lowered at runtime (Firmware does not support QoS).
+	 * hw->queues has to be restored to the original value before unregistering
+	 * from the mac80211 subsystem. */
+	u16 mac80211_initially_registered_queues;
+
 	struct mutex mutex;
 	spinlock_t irq_lock;
 	/* R/W lock for data transmission.
@@ -625,18 +637,18 @@
 	/* Stats about the wireless interface */
 	struct ieee80211_low_level_stats ieee_stats;
 
+#ifdef CONFIG_B43_HWRNG
 	struct hwrng rng;
-	u8 rng_initialized;
+	bool rng_initialized;
 	char rng_name[30 + 1];
-
-	/* The RF-kill button */
-	struct b43_rfkill rfkill;
+#endif /* CONFIG_B43_HWRNG */
 
 	/* List of all wireless devices on this chip */
 	struct list_head devlist;
 	u8 nr_devs;
 
 	bool radiotap_enabled;
+	bool radio_enabled;
 
 	/* The beacon we are currently using (AP or IBSS mode).
 	 * This beacon stuff is protected by the irq_lock. */
@@ -750,6 +762,8 @@
 	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
 	bool suspend_in_progress;	/* TRUE, if we are in a suspend/resume cycle */
+	bool qos_enabled;		/* TRUE, if QoS is used. */
+	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
 
 	/* PHY/Radio device. */
 	struct b43_phy phy;
@@ -776,8 +790,8 @@
 	/* Reason code of the last interrupt. */
 	u32 irq_reason;
 	u32 dma_reason[6];
-	/* saved irq enable/disable state bitfield. */
-	u32 irq_savedstate;
+	/* The currently active generic-interrupt mask. */
+	u32 irq_mask;
 	/* Link Quality calculation context. */
 	struct b43_noise_calculation noisecalc;
 	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/dma.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/dma.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/dma.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/dma.c	2009-09-09 18:13:59.000000000 -0400
@@ -1285,7 +1285,7 @@
 {
 	struct b43_dmaring *ring;
 
-	if (b43_modparam_qos) {
+	if (dev->qos_enabled) {
 		/* 0 = highest priority */
 		switch (queue_prio) {
 		default:
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/b43/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,6 @@
 	depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
 	select SSB
 	select FW_LOADER
-	select HW_RANDOM
 	---help---
 	  b43 is a driver for the Broadcom 43xx series wireless devices.
 
@@ -99,11 +98,11 @@
 	depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43)
 	default y
 
-# This config option automatically enables b43 RFKILL support,
-# if it's possible.
-config B43_RFKILL
+# This config option automatically enables b43 HW-RNG support,
+# if the HW-RNG core is enabled.
+config B43_HWRNG
 	bool
-	depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43)
+	depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43)
 	default y
 
 config B43_DEBUG
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/leds.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/leds.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/leds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/leds.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
 
 #include "b43.h"
 #include "leds.h"
+#include "rfkill.h"
 
 
 static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
@@ -87,7 +88,7 @@
 }
 
 static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
-			    const char *name, char *default_trigger,
+			    const char *name, const char *default_trigger,
 			    u8 led_index, bool activelow)
 {
 	int err;
@@ -164,10 +165,10 @@
 		snprintf(name, sizeof(name),
 			 "b43-%s::radio", wiphy_name(hw->wiphy));
 		b43_register_led(dev, &dev->led_radio, name,
-				 b43_rfkill_led_name(dev),
+				 ieee80211_get_radio_led_name(hw),
 				 led_index, activelow);
-		/* Sync the RF-kill LED state with the switch state. */
-		if (dev->radio_hw_enable)
+		/* Sync the RF-kill LED state with radio and switch states. */
+		if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev))
 			b43_led_turn_on(dev, led_index, activelow);
 		break;
 	case B43_LED_WEIRD:
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/main.c	2012-03-22 19:16:34.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/main.c	2012-03-22 20:12:22.000000000 -0400
@@ -80,8 +80,8 @@
 module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
-int b43_modparam_qos = 1;
-module_param_named(qos, b43_modparam_qos, int, 0444);
+static int modparam_qos = 1;
+module_param_named(qos, modparam_qos, int, 0444);
 MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
 
 static int modparam_btcoex = 1;
@@ -538,6 +538,13 @@
 	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
 }
 
+/* Read the firmware capabilities bitmask (Opensource firmware only) */
+static u16 b43_fwcapa_read(struct b43_wldev *dev)
+{
+	B43_WARN_ON(!dev->fw.opensource);
+	return b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_FWCAPA);
+}
+
 void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
 {
 	u32 low, high;
@@ -673,32 +680,6 @@
 	b43_set_slot_time(dev, 20);
 }
 
-/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
-	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask);
-
-	return old_mask;
-}
-
-/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
-	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
-
-	return old_mask;
-}
-
 /* Synchronize IRQ top- and bottom-half.
  * IRQs must be masked before calling this.
  * This must not be called with the irq_lock held.
@@ -1593,7 +1574,7 @@
 	/* This is the bottom half of the asynchronous beacon update. */
 
 	/* Ignore interrupt in the future. */
-	dev->irq_savedstate &= ~B43_IRQ_BEACON;
+	dev->irq_mask &= ~B43_IRQ_BEACON;
 
 	cmd = b43_read32(dev, B43_MMIO_MACCMD);
 	beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
@@ -1602,7 +1583,7 @@
 	/* Schedule interrupt manually, if busy. */
 	if (beacon0_valid && beacon1_valid) {
 		b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
-		dev->irq_savedstate |= B43_IRQ_BEACON;
+		dev->irq_mask |= B43_IRQ_BEACON;
 		return;
 	}
 
@@ -1641,11 +1622,9 @@
 	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
 		spin_lock_irq(&wl->irq_lock);
 		/* update beacon right away or defer to irq */
-		dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
 		handle_irq_beacon(dev);
 		/* The handler might have updated the IRQ mask. */
-		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
-			    dev->irq_savedstate);
+		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 		mmiowb();
 		spin_unlock_irq(&wl->irq_lock);
 	}
@@ -1879,7 +1858,7 @@
 	if (reason & B43_IRQ_TX_OK)
 		handle_irq_transmit_status(dev);
 
-	b43_interrupt_enable(dev, dev->irq_savedstate);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	mmiowb();
 	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
 }
@@ -1893,7 +1872,9 @@
 	b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
 	b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
 	b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
+/* Unused ring
 	b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
+*/
 }
 
 /* Interrupt handler top-half */
@@ -1903,18 +1884,19 @@
 	struct b43_wldev *dev = dev_id;
 	u32 reason;
 
-	if (!dev)
-		return IRQ_NONE;
+	B43_WARN_ON(!dev);
 
 	spin_lock(&dev->wl->irq_lock);
 
-	if (b43_status(dev) < B43_STAT_STARTED)
+	if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
+		/* This can only happen on shared IRQ lines. */
 		goto out;
+	}
 	reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff)	/* shared IRQ */
 		goto out;
 	ret = IRQ_HANDLED;
-	reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
+	reason &= dev->irq_mask;
 	if (!reason)
 		goto out;
 
@@ -1928,16 +1910,18 @@
 	    & 0x0001DC00;
 	dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
 	    & 0x0000DC00;
+/* Unused ring
 	dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
 	    & 0x0000DC00;
+*/
 
 	b43_interrupt_ack(dev, reason);
 	/* disable all IRQs. They are enabled again in the bottom half. */
-	dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
 	/* save the reason code and call our bottom half. */
 	dev->irq_reason = reason;
 	tasklet_schedule(&dev->isr_tasklet);
-      out:
+out:
 	mmiowb();
 	spin_unlock(&dev->wl->irq_lock);
 
@@ -2327,17 +2311,39 @@
 	dev->fw.patch = fwpatch;
 	dev->fw.opensource = (fwdate == 0xFFFF);
 
+	/* Default to use-all-queues. */
+	dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;
+	dev->qos_enabled = !!modparam_qos;
+	/* Default to firmware/hardware crypto acceleration. */
+	dev->hwcrypto_enabled = 1;
+
 	if (!dev->fw.opensource) {
 		b43err(dev->wl, "Rejected non-Free firmware\n");
 		err = -EOPNOTSUPP;
 		goto error;
 	}
 	if (dev->fw.opensource) {
+		u16 fwcapa;
+
 		/* Patchlevel info is encoded in the "time" field. */
 		dev->fw.patch = fwtime;
-		b43info(dev->wl, "Loading OpenSource firmware version %u.%u%s\n",
-			dev->fw.rev, dev->fw.patch,
-			dev->fw.pcm_request_failed ? " (Hardware crypto not supported)" : "");
+		b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n",
+			dev->fw.rev, dev->fw.patch);
+
+		fwcapa = b43_fwcapa_read(dev);
+		if (!(fwcapa & B43_FWCAPA_HWCRYPTO) || dev->fw.pcm_request_failed) {
+			b43info(dev->wl, "Hardware crypto acceleration not supported by firmware\n");
+			/* Disable hardware crypto and fall back to software crypto. */
+			dev->hwcrypto_enabled = 0;
+		}
+		if (!(fwcapa & B43_FWCAPA_QOS)) {
+			b43info(dev->wl, "QoS not supported by firmware\n");
+			/* Disable QoS. Tweak hw->queues to 1. It will be restored before
+			 * ieee80211_unregister to make sure the networking core can
+			 * properly free possible resources. */
+			dev->wl->hw->queues = 1;
+			dev->qos_enabled = 0;
+		}
 	} else {
 		b43info(dev->wl, "Loading firmware version %u.%u "
 			"(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
@@ -2982,6 +2988,7 @@
 	b43_clear_keys(dev);
 }
 
+#ifdef CONFIG_B43_HWRNG
 static int b43_rng_read(struct hwrng *rng, u32 *data)
 {
 	struct b43_wl *wl = (struct b43_wl *)rng->priv;
@@ -2997,17 +3004,21 @@
 
 	return (sizeof(u16));
 }
+#endif /* CONFIG_B43_HWRNG */
 
 static void b43_rng_exit(struct b43_wl *wl)
 {
+#ifdef CONFIG_B43_HWRNG
 	if (wl->rng_initialized)
 		hwrng_unregister(&wl->rng);
+#endif /* CONFIG_B43_HWRNG */
 }
 
 static int b43_rng_init(struct b43_wl *wl)
 {
-	int err;
+	int err = 0;
 
+#ifdef CONFIG_B43_HWRNG
 	snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
 		 "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
 	wl->rng.name = wl->rng_name;
@@ -3020,6 +3031,7 @@
 		b43err(wl, "Failed to register the random "
 		       "number generator (%d)\n", err);
 	}
+#endif /* CONFIG_B43_HWRNG */
 
 	return err;
 }
@@ -3487,14 +3499,9 @@
 	if (phy->ops->set_rx_antenna)
 		phy->ops->set_rx_antenna(dev, antenna);
 
-	/* Update templates for AP/mesh mode. */
-	if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
-	    b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
-		b43_set_beacon_int(dev, conf->beacon_int);
-
-	if (!!conf->radio_enabled != phy->radio_on) {
-		if (conf->radio_enabled) {
-			b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
+	if (wl->radio_enabled != phy->radio_on) {
+		if (wl->radio_enabled) {
+			b43_software_rfkill(dev, false);
 			b43info(dev->wl, "Radio turned on by software\n");
 			if (!dev->radio_hw_enable) {
 				b43info(dev->wl, "The hardware RF-kill button "
@@ -3502,7 +3509,7 @@
 					"Press the button to turn it on.\n");
 			}
 		} else {
-			b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
+			b43_software_rfkill(dev, true);
 			b43info(dev->wl, "Radio turned off by software\n");
 		}
 	}
@@ -3567,14 +3574,45 @@
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev;
+	unsigned long flags;
 
 	mutex_lock(&wl->mutex);
 
 	dev = wl->current_dev;
 	if (!dev || b43_status(dev) < B43_STAT_STARTED)
 		goto out_unlock_mutex;
+
+	B43_WARN_ON(wl->vif != vif);
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	if (changed & BSS_CHANGED_BSSID) {
+		if (conf->bssid)
+			memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+		else
+			memset(wl->bssid, 0, ETH_ALEN);
+	}
+
+	if (b43_status(dev) >= B43_STAT_INITIALIZED) {
+		if (changed & BSS_CHANGED_BEACON &&
+		    (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+		     b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
+		     b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+			b43_update_templates(wl);
+
+		if (changed & BSS_CHANGED_BSSID)
+			b43_write_mac_bssid_templates(dev);
+	}
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+
 	b43_mac_suspend(dev);
 
+	/* Update templates for AP/mesh mode. */
+	if (changed & BSS_CHANGED_BEACON_INT &&
+	    (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+	     b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
+	     b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+		b43_set_beacon_int(dev, conf->beacon_int);
+
 	if (changed & BSS_CHANGED_BASIC_RATES)
 		b43_update_basic_rates(dev, conf->basic_rates);
 
@@ -3588,8 +3626,6 @@
 	b43_mac_enable(dev);
 out_unlock_mutex:
 	mutex_unlock(&wl->mutex);
-
-	return;
 }
 
 static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -3622,7 +3658,7 @@
 	if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
 		goto out_unlock;
 
-	if (dev->fw.pcm_request_failed) {
+	if (dev->fw.pcm_request_failed || !dev->hwcrypto_enabled) {
 		/* We don't have firmware for the crypto engine.
 		 * Must use software-crypto. */
 		err = -EOPNOTSUPP;
@@ -3632,7 +3668,7 @@
 	err = -EINVAL;
 	switch (key->alg) {
 	case ALG_WEP:
-		if (key->keylen == LEN_WEP40)
+		if (key->keylen == WLAN_KEY_LEN_WEP40)
 			algorithm = B43_SEC_ALGO_WEP40;
 		else
 			algorithm = B43_SEC_ALGO_WEP104;
@@ -3747,41 +3783,6 @@
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 }
 
-static int b43_op_config_interface(struct ieee80211_hw *hw,
-				   struct ieee80211_vif *vif,
-				   struct ieee80211_if_conf *conf)
-{
-	struct b43_wl *wl = hw_to_b43_wl(hw);
-	struct b43_wldev *dev = wl->current_dev;
-	unsigned long flags;
-
-	if (!dev)
-		return -ENODEV;
-	mutex_lock(&wl->mutex);
-	spin_lock_irqsave(&wl->irq_lock, flags);
-	B43_WARN_ON(wl->vif != vif);
-	if (conf->bssid)
-		memcpy(wl->bssid, conf->bssid, ETH_ALEN);
-	else
-		memset(wl->bssid, 0, ETH_ALEN);
-	if (b43_status(dev) >= B43_STAT_INITIALIZED) {
-		if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
-		    b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) {
-			B43_WARN_ON(vif->type != wl->if_type);
-			if (conf->changed & IEEE80211_IFCC_BEACON)
-				b43_update_templates(wl);
-		} else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
-			if (conf->changed & IEEE80211_IFCC_BEACON)
-				b43_update_templates(wl);
-		}
-		b43_write_mac_bssid_templates(dev);
-	}
-	spin_unlock_irqrestore(&wl->irq_lock, flags);
-	mutex_unlock(&wl->mutex);
-
-	return 0;
-}
-
 /* Locking: wl->mutex */
 static void b43_wireless_core_stop(struct b43_wldev *dev)
 {
@@ -3795,7 +3796,7 @@
 	 * setting the status to INITIALIZED, as the interrupt handler
 	 * won't care about IRQs then. */
 	spin_lock_irqsave(&wl->irq_lock, flags);
-	dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
 	b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* flush */
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 	b43_synchronize_irq(dev);
@@ -3836,7 +3837,7 @@
 
 	/* Start data flow (TX/RX). */
 	b43_mac_enable(dev);
-	b43_interrupt_enable(dev, dev->irq_savedstate);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 
 	/* Start maintainance work */
 	b43_periodic_tasks_setup(dev);
@@ -3999,9 +4000,9 @@
 	/* IRQ related flags */
 	dev->irq_reason = 0;
 	memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
-	dev->irq_savedstate = B43_IRQ_MASKTEMPLATE;
+	dev->irq_mask = B43_IRQ_MASKTEMPLATE;
 	if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
-		dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR;
+		dev->irq_mask &= ~B43_IRQ_PHY_TXERR;
 
 	dev->mac_suspended = 1;
 
@@ -4328,7 +4329,6 @@
 	struct b43_wldev *dev = wl->current_dev;
 	int did_init = 0;
 	int err = 0;
-	bool do_rfkill_exit = 0;
 
 	/* Kill all old instance specific information to make sure
 	 * the card won't use it in the short timeframe between start
@@ -4341,19 +4341,14 @@
 	wl->beacon0_uploaded = 0;
 	wl->beacon1_uploaded = 0;
 	wl->beacon_templates_virgin = 1;
-
-	/* First register RFkill.
-	 * LEDs that are registered later depend on it. */
-	b43_rfkill_init(dev);
+	wl->radio_enabled = 1;
 
 	mutex_lock(&wl->mutex);
 
 	if (b43_status(dev) < B43_STAT_INITIALIZED) {
 		err = b43_wireless_core_init(dev);
-		if (err) {
-			do_rfkill_exit = 1;
+		if (err)
 			goto out_mutex_unlock;
-		}
 		did_init = 1;
 	}
 
@@ -4362,17 +4357,16 @@
 		if (err) {
 			if (did_init)
 				b43_wireless_core_exit(dev);
-			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
 		}
 	}
 
+	/* XXX: only do if device doesn't support rfkill irq */
+	wiphy_rfkill_start_polling(hw->wiphy);
+
  out_mutex_unlock:
 	mutex_unlock(&wl->mutex);
 
-	if (do_rfkill_exit)
-		b43_rfkill_exit(dev);
-
 	return err;
 }
 
@@ -4381,13 +4375,13 @@
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev = wl->current_dev;
 
-	b43_rfkill_exit(dev);
 	cancel_work_sync(&(wl->beacon_update_trigger));
 
 	mutex_lock(&wl->mutex);
 	if (b43_status(dev) >= B43_STAT_STARTED)
 		b43_wireless_core_stop(dev);
 	b43_wireless_core_exit(dev);
+	wl->radio_enabled = 0;
 	mutex_unlock(&wl->mutex);
 
 	cancel_work_sync(&(wl->txpower_adjust_work));
@@ -4451,7 +4445,6 @@
 	.remove_interface	= b43_op_remove_interface,
 	.config			= b43_op_config,
 	.bss_info_changed	= b43_op_bss_info_changed,
-	.config_interface	= b43_op_config_interface,
 	.configure_filter	= b43_op_configure_filter,
 	.set_key		= b43_op_set_key,
 	.get_stats		= b43_op_get_stats,
@@ -4464,6 +4457,7 @@
 	.sta_notify		= b43_op_sta_notify,
 	.sw_scan_start		= b43_op_sw_scan_start_notifier,
 	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
+	.rfkill_poll		= b43_rfkill_poll,
 };
 
 /* Hard-reset the chip. Do not call this directly.
@@ -4570,6 +4564,7 @@
 		B43_WARN_ON(1);
 
 	dev->phy.gmode = have_2ghz_phy;
+	dev->phy.radio_on = 1;
 	tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
 	b43_wireless_core_reset(dev, tmp);
 
@@ -4766,6 +4761,7 @@
 		b43err(NULL, "Could not allocate ieee80211 device\n");
 		goto out;
 	}
+	wl = hw_to_b43_wl(hw);
 
 	/* fill hw info */
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
@@ -4779,7 +4775,8 @@
 		BIT(NL80211_IFTYPE_WDS) |
 		BIT(NL80211_IFTYPE_ADHOC);
 
-	hw->queues = b43_modparam_qos ? 4 : 1;
+	hw->queues = modparam_qos ? 4 : 1;
+	wl->mac80211_initially_registered_queues = hw->queues;
 	hw->max_rates = 2;
 	SET_IEEE80211_DEV(hw, dev->dev);
 	if (is_valid_ether_addr(sprom->et1mac))
@@ -4787,9 +4784,7 @@
 	else
 		SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
 
-	/* Get and initialize struct b43_wl */
-	wl = hw_to_b43_wl(hw);
-	memset(wl, 0, sizeof(*wl));
+	/* Initialize struct b43_wl */
 	wl->hw = hw;
 	spin_lock_init(&wl->irq_lock);
 	rwlock_init(&wl->tx_lock);
@@ -4855,8 +4850,13 @@
 	cancel_work_sync(&wldev->restart_work);
 
 	B43_WARN_ON(!wl);
-	if (wl->current_dev == wldev)
+	if (wl->current_dev == wldev) {
+		/* Restore the queues count before unregistering, because firmware detect
+		 * might have modified it. Restoring is important, so the networking
+		 * stack can properly free resources. */
+		wl->hw->queues = wl->mac80211_initially_registered_queues;
 		ieee80211_unregister_hw(wl->hw);
+	}
 
 	b43_one_core_detach(dev);
 
@@ -4951,7 +4951,7 @@
 static void b43_print_driverinfo(void)
 {
 	const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
-		   *feat_leds = "", *feat_rfkill = "";
+		   *feat_leds = "";
 
 #ifdef CONFIG_B43_PCI_AUTOSELECT
 	feat_pci = "P";
@@ -4965,14 +4965,11 @@
 #ifdef CONFIG_B43_LEDS
 	feat_leds = "L";
 #endif
-#ifdef CONFIG_B43_RFKILL
-	feat_rfkill = "R";
-#endif
 	printk(KERN_INFO "Broadcom 43xx driver loaded "
-	       "[ Features: %s%s%s%s%s, Firmware-ID: "
+	       "[ Features: %s%s%s%s, Firmware-ID: "
 	       B43_SUPPORTED_FIRMWARE_ID " ]\n",
 	       feat_pci, feat_pcmcia, feat_nphy,
-	       feat_leds, feat_rfkill);
+	       feat_leds);
 }
 
 static int __init b43_init(void)
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/main.h linux-libre-2.6.31-gnu/drivers/net/wireless/b43/main.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/main.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/main.h	2009-09-09 18:13:59.000000000 -0400
@@ -39,7 +39,6 @@
 #define PAD_BYTES(nr_bytes)		P4D_BYTES( __LINE__ , (nr_bytes))
 
 
-extern int b43_modparam_qos;
 extern int b43_modparam_verbose;
 
 /* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/b43/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -13,7 +13,7 @@
 b43-y				+= wa.o
 b43-y				+= dma.o
 b43-$(CONFIG_B43_PIO)		+= pio.o
-b43-$(CONFIG_B43_RFKILL)	+= rfkill.o
+b43-y				+= rfkill.o
 b43-$(CONFIG_B43_LEDS)		+= leds.o
 b43-$(CONFIG_B43_PCMCIA)	+= pcmcia.o
 b43-$(CONFIG_B43_DEBUG)		+= debugfs.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/pcmcia.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/pcmcia.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/pcmcia.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/pcmcia.c	2009-09-09 18:13:59.000000000 -0400
@@ -35,6 +35,7 @@
 
 static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
+	PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
 	PCMCIA_DEVICE_NULL,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_a.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_a.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_a.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_a.c	2009-09-09 18:13:59.000000000 -0400
@@ -480,11 +480,11 @@
 }
 
 static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
-					enum rfkill_state state)
+					bool blocked)
 {
 	struct b43_phy *phy = &dev->phy;
 
-	if (state == RFKILL_STATE_UNBLOCKED) {
+	if (!blocked) {
 		if (phy->radio_on)
 			return;
 		b43_radio_write16(dev, 0x0004, 0x00C0);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_common.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_common.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_common.c	2009-09-09 18:13:59.000000000 -0400
@@ -84,7 +84,7 @@
 
 	phy->channel = ops->get_default_chan(dev);
 
-	ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
+	ops->software_rfkill(dev, false);
 	err = ops->init(dev);
 	if (err) {
 		b43err(dev->wl, "PHY init failed\n");
@@ -104,7 +104,7 @@
 	if (ops->exit)
 		ops->exit(dev);
 err_block_rf:
-	ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
+	ops->software_rfkill(dev, true);
 
 	return err;
 }
@@ -113,7 +113,7 @@
 {
 	const struct b43_phy_operations *ops = dev->phy.ops;
 
-	ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
+	ops->software_rfkill(dev, true);
 	if (ops->exit)
 		ops->exit(dev);
 }
@@ -295,18 +295,13 @@
 	return err;
 }
 
-void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
+void b43_software_rfkill(struct b43_wldev *dev, bool blocked)
 {
 	struct b43_phy *phy = &dev->phy;
 
-	if (state == RFKILL_STATE_HARD_BLOCKED) {
-		/* We cannot hardware-block the device */
-		state = RFKILL_STATE_SOFT_BLOCKED;
-	}
-
 	b43_mac_suspend(dev);
-	phy->ops->software_rfkill(dev, state);
-	phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
+	phy->ops->software_rfkill(dev, blocked);
+	phy->radio_on = !blocked;
 	b43_mac_enable(dev);
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_common.h linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_common.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_common.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_common.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef LINUX_B43_PHY_COMMON_H_
 #define LINUX_B43_PHY_COMMON_H_
 
-#include <linux/rfkill.h>
+#include <linux/types.h>
 
 struct b43_wldev;
 
@@ -159,7 +159,7 @@
 
 	/* Radio */
 	bool (*supports_hwpctl)(struct b43_wldev *dev);
-	void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state);
+	void (*software_rfkill)(struct b43_wldev *dev, bool blocked);
 	void (*switch_analog)(struct b43_wldev *dev, bool on);
 	int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel);
 	unsigned int (*get_default_chan)(struct b43_wldev *dev);
@@ -364,7 +364,7 @@
 /**
  * b43_software_rfkill - Turn the radio ON or OFF in software.
  */
-void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state);
+void b43_software_rfkill(struct b43_wldev *dev, bool blocked);
 
 /**
  * b43_phy_txpower_check - Check TX power output.
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_g.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_g.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_g.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_g.c	2009-09-09 18:13:59.000000000 -0400
@@ -2592,7 +2592,7 @@
 }
 
 static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
-					enum rfkill_state state)
+					bool blocked)
 {
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy_g *gphy = phy->g;
@@ -2600,7 +2600,7 @@
 
 	might_sleep();
 
-	if (state == RFKILL_STATE_UNBLOCKED) {
+	if (!blocked) {
 		/* Turn radio ON */
 		if (phy->radio_on)
 			return;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_lp.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_lp.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_lp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_lp.c	2009-09-09 18:13:59.000000000 -0400
@@ -488,7 +488,7 @@
 }
 
 static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
-					 enum rfkill_state state)
+					 bool blocked)
 {
 	//TODO
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_n.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_n.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/phy_n.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/phy_n.c	2009-09-09 18:13:59.000000000 -0400
@@ -579,7 +579,7 @@
 }
 
 static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
-					enum rfkill_state state)
+					bool blocked)
 {//TODO
 }
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/pio.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/pio.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/pio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/pio.c	2009-09-09 18:13:59.000000000 -0400
@@ -313,7 +313,7 @@
 {
 	struct b43_pio_txqueue *q;
 
-	if (b43_modparam_qos) {
+	if (dev->qos_enabled) {
 		/* 0 = highest priority */
 		switch (queue_prio) {
 		default:
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/rfkill.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/rfkill.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/rfkill.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/rfkill.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,15 +22,11 @@
 
 */
 
-#include "rfkill.h"
 #include "b43.h"
-#include "phy_common.h"
-
-#include <linux/kmod.h>
 
 
 /* Returns TRUE, if the radio is enabled in hardware. */
-static bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
+bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
 {
 	if (dev->phy.rev >= 3) {
 		if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
@@ -45,166 +41,39 @@
 }
 
 /* The poll callback for the hardware button. */
-static void b43_rfkill_poll(struct input_polled_dev *poll_dev)
+void b43_rfkill_poll(struct ieee80211_hw *hw)
 {
-	struct b43_wldev *dev = poll_dev->private;
-	struct b43_wl *wl = dev->wl;
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+	struct ssb_bus *bus = dev->dev->bus;
 	bool enabled;
-	bool report_change = 0;
+	bool brought_up = false;
 
 	mutex_lock(&wl->mutex);
 	if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
-		mutex_unlock(&wl->mutex);
-		return;
+		if (ssb_bus_powerup(bus, 0)) {
+			mutex_unlock(&wl->mutex);
+			return;
+		}
+		ssb_device_enable(dev->dev, 0);
+		brought_up = true;
 	}
+
 	enabled = b43_is_hw_radio_enabled(dev);
+
 	if (unlikely(enabled != dev->radio_hw_enable)) {
 		dev->radio_hw_enable = enabled;
-		report_change = 1;
 		b43info(wl, "Radio hardware status changed to %s\n",
 			enabled ? "ENABLED" : "DISABLED");
+		wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
+		if (enabled != dev->phy.radio_on)
+			b43_software_rfkill(dev, !enabled);
 	}
-	mutex_unlock(&wl->mutex);
 
-	/* send the radio switch event to the system - note both a key press
-	 * and a release are required */
-	if (unlikely(report_change)) {
-		input_report_key(poll_dev->input, KEY_WLAN, 1);
-		input_report_key(poll_dev->input, KEY_WLAN, 0);
+	if (brought_up) {
+		ssb_device_disable(dev->dev, 0);
+		ssb_bus_may_powerdown(bus);
 	}
-}
-
-/* Called when the RFKILL toggled in software. */
-static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
-{
-	struct b43_wldev *dev = data;
-	struct b43_wl *wl = dev->wl;
-	int err = -EBUSY;
-
-	if (!wl->rfkill.registered)
-		return 0;
 
-	mutex_lock(&wl->mutex);
-	if (b43_status(dev) < B43_STAT_INITIALIZED)
-		goto out_unlock;
-	err = 0;
-	switch (state) {
-	case RFKILL_STATE_UNBLOCKED:
-		if (!dev->radio_hw_enable) {
-			/* No luck. We can't toggle the hardware RF-kill
-			 * button from software. */
-			err = -EBUSY;
-			goto out_unlock;
-		}
-		if (!dev->phy.radio_on)
-			b43_software_rfkill(dev, state);
-		break;
-	case RFKILL_STATE_SOFT_BLOCKED:
-		if (dev->phy.radio_on)
-			b43_software_rfkill(dev, state);
-		break;
-	default:
-		b43warn(wl, "Received unexpected rfkill state %d.\n", state);
-		break;
-	}
-out_unlock:
 	mutex_unlock(&wl->mutex);
-
-	return err;
-}
-
-char *b43_rfkill_led_name(struct b43_wldev *dev)
-{
-	struct b43_rfkill *rfk = &(dev->wl->rfkill);
-
-	if (!rfk->registered)
-		return NULL;
-	return rfkill_get_led_name(rfk->rfkill);
-}
-
-void b43_rfkill_init(struct b43_wldev *dev)
-{
-	struct b43_wl *wl = dev->wl;
-	struct b43_rfkill *rfk = &(wl->rfkill);
-	int err;
-
-	rfk->registered = 0;
-
-	rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
-	if (!rfk->rfkill)
-		goto out_error;
-	snprintf(rfk->name, sizeof(rfk->name),
-		 "b43-%s", wiphy_name(wl->hw->wiphy));
-	rfk->rfkill->name = rfk->name;
-	rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
-	rfk->rfkill->data = dev;
-	rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
-	rfk->rfkill->user_claim_unsupported = 1;
-
-	rfk->poll_dev = input_allocate_polled_device();
-	if (!rfk->poll_dev) {
-		rfkill_free(rfk->rfkill);
-		goto err_freed_rfk;
-	}
-
-	rfk->poll_dev->private = dev;
-	rfk->poll_dev->poll = b43_rfkill_poll;
-	rfk->poll_dev->poll_interval = 1000; /* msecs */
-
-	rfk->poll_dev->input->name = rfk->name;
-	rfk->poll_dev->input->id.bustype = BUS_HOST;
-	rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor;
-	rfk->poll_dev->input->evbit[0] = BIT(EV_KEY);
-	set_bit(KEY_WLAN, rfk->poll_dev->input->keybit);
-
-	err = rfkill_register(rfk->rfkill);
-	if (err)
-		goto err_free_polldev;
-
-#ifdef CONFIG_RFKILL_INPUT_MODULE
-	/* B43 RF-kill isn't useful without the rfkill-input subsystem.
-	 * Try to load the module. */
-	err = request_module("rfkill-input");
-	if (err)
-		b43warn(wl, "Failed to load the rfkill-input module. "
-			"The built-in radio LED will not work.\n");
-#endif /* CONFIG_RFKILL_INPUT */
-
-#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE)
-	b43warn(wl, "The rfkill-input subsystem is not available. "
-		"The built-in radio LED will not work.\n");
-#endif
-
-	err = input_register_polled_device(rfk->poll_dev);
-	if (err)
-		goto err_unreg_rfk;
-
-	rfk->registered = 1;
-
-	return;
-err_unreg_rfk:
-	rfkill_unregister(rfk->rfkill);
-err_free_polldev:
-	input_free_polled_device(rfk->poll_dev);
-	rfk->poll_dev = NULL;
-err_freed_rfk:
-	rfk->rfkill = NULL;
-out_error:
-	rfk->registered = 0;
-	b43warn(wl, "RF-kill button init failed\n");
-}
-
-void b43_rfkill_exit(struct b43_wldev *dev)
-{
-	struct b43_rfkill *rfk = &(dev->wl->rfkill);
-
-	if (!rfk->registered)
-		return;
-	rfk->registered = 0;
-
-	input_unregister_polled_device(rfk->poll_dev);
-	rfkill_unregister(rfk->rfkill);
-	input_free_polled_device(rfk->poll_dev);
-	rfk->poll_dev = NULL;
-	rfk->rfkill = NULL;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/rfkill.h linux-libre-2.6.31-gnu/drivers/net/wireless/b43/rfkill.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/rfkill.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/rfkill.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,52 +1,11 @@
 #ifndef B43_RFKILL_H_
 #define B43_RFKILL_H_
 
+struct ieee80211_hw;
 struct b43_wldev;
 
+void b43_rfkill_poll(struct ieee80211_hw *hw);
 
-#ifdef CONFIG_B43_RFKILL
-
-#include <linux/rfkill.h>
-#include <linux/input-polldev.h>
-
-
-struct b43_rfkill {
-	/* The RFKILL subsystem data structure */
-	struct rfkill *rfkill;
-	/* The poll device for the RFKILL input button */
-	struct input_polled_dev *poll_dev;
-	/* Did initialization succeed? Used for freeing. */
-	bool registered;
-	/* The unique name of this rfkill switch */
-	char name[sizeof("b43-phy4294967295")];
-};
-
-/* The init function returns void, because we are not interested
- * in failing the b43 init process when rfkill init failed. */
-void b43_rfkill_init(struct b43_wldev *dev);
-void b43_rfkill_exit(struct b43_wldev *dev);
-
-char * b43_rfkill_led_name(struct b43_wldev *dev);
-
-
-#else /* CONFIG_B43_RFKILL */
-/* No RFKILL support. */
-
-struct b43_rfkill {
-	/* empty */
-};
-
-static inline void b43_rfkill_init(struct b43_wldev *dev)
-{
-}
-static inline void b43_rfkill_exit(struct b43_wldev *dev)
-{
-}
-static inline char * b43_rfkill_led_name(struct b43_wldev *dev)
-{
-	return NULL;
-}
-
-#endif /* CONFIG_B43_RFKILL */
+bool b43_is_hw_radio_enabled(struct b43_wldev *dev);
 
 #endif /* B43_RFKILL_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43/xmit.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43/xmit.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43/xmit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43/xmit.c	2009-09-09 18:13:59.000000000 -0400
@@ -118,7 +118,6 @@
 void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
 			   const u16 octets, const u8 bitrate)
 {
-	__le32 *data = &(plcp->data);
 	__u8 *raw = plcp->raw;
 
 	if (b43_is_ofdm_rate(bitrate)) {
@@ -127,7 +126,7 @@
 		d = b43_plcp_get_ratecode_ofdm(bitrate);
 		B43_WARN_ON(octets & 0xF000);
 		d |= (octets << 5);
-		*data = cpu_to_le32(d);
+		plcp->data = cpu_to_le32(d);
 	} else {
 		u32 plen;
 
@@ -141,7 +140,7 @@
 				raw[1] = 0x04;
 		} else
 			raw[1] = 0x04;
-		*data |= cpu_to_le32(plen << 16);
+		plcp->data |= cpu_to_le32(plen << 16);
 		raw[0] = b43_plcp_get_ratecode_cck(bitrate);
 	}
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/b43legacy.h linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/b43legacy.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/b43legacy.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/b43legacy.h	2009-09-09 18:13:59.000000000 -0400
@@ -59,7 +59,8 @@
 #define B43legacy_MMIO_XMITSTAT_1		0x174
 #define B43legacy_MMIO_REV3PLUS_TSF_LOW	0x180 /* core rev >= 3 only */
 #define B43legacy_MMIO_REV3PLUS_TSF_HIGH	0x184 /* core rev >= 3 only */
-
+#define B43legacy_MMIO_TSF_CFP_REP	0x188
+#define B43legacy_MMIO_TSF_CFP_START	0x18C
 /* 32-bit DMA */
 #define B43legacy_MMIO_DMA32_BASE0	0x200
 #define B43legacy_MMIO_DMA32_BASE1	0x220
@@ -258,7 +259,6 @@
 
 #define B43legacy_IRQ_ALL		0xFFFFFFFF
 #define B43legacy_IRQ_MASKTEMPLATE	(B43legacy_IRQ_MAC_SUSPENDED |	\
-					 B43legacy_IRQ_BEACON |		\
 					 B43legacy_IRQ_TBTT_INDI |	\
 					 B43legacy_IRQ_ATIM_END |	\
 					 B43legacy_IRQ_PMQ |		\
@@ -596,24 +596,26 @@
 	/* Stats about the wireless interface */
 	struct ieee80211_low_level_stats ieee_stats;
 
+#ifdef CONFIG_B43LEGACY_HWRNG
 	struct hwrng rng;
 	u8 rng_initialized;
 	char rng_name[30 + 1];
-
-	/* The RF-kill button */
-	struct b43legacy_rfkill rfkill;
+#endif
 
 	/* List of all wireless devices on this chip */
 	struct list_head devlist;
 	u8 nr_devs;
 
 	bool radiotap_enabled;
+	bool radio_enabled;
 
 	/* The beacon we are currently using (AP or IBSS mode).
 	 * This beacon stuff is protected by the irq_lock. */
 	struct sk_buff *current_beacon;
 	bool beacon0_uploaded;
 	bool beacon1_uploaded;
+	bool beacon_templates_virgin; /* Never wrote the templates? */
+	struct work_struct beacon_update_trigger;
 };
 
 /* Pointers to the firmware data and meta information about it. */
@@ -690,8 +692,8 @@
 	/* Reason code of the last interrupt. */
 	u32 irq_reason;
 	u32 dma_reason[6];
-	/* saved irq enable/disable state bitfield. */
-	u32 irq_savedstate;
+	/* The currently active generic-interrupt mask. */
+	u32 irq_mask;
 	/* Link Quality calculation context. */
 	struct b43legacy_noise_calculation noisecalc;
 	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -3,7 +3,6 @@
 	depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
 	select SSB
 	select FW_LOADER
-	select HW_RANDOM
 	---help---
 	  b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
 	  BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the
@@ -43,12 +42,11 @@
 	depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY)
 	default y
 
-# RFKILL support
-# This config option automatically enables b43legacy RFKILL support,
-# if it's possible.
-config B43LEGACY_RFKILL
+# This config option automatically enables b43 HW-RNG support,
+# if the HW-RNG core is enabled.
+config B43LEGACY_HWRNG
 	bool
-	depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY)
+	depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY)
 	default y
 
 config B43LEGACY_DEBUG
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/leds.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/leds.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/leds.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/leds.c	2009-09-09 18:13:59.000000000 -0400
@@ -28,6 +28,7 @@
 
 #include "b43legacy.h"
 #include "leds.h"
+#include "rfkill.h"
 
 
 static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
@@ -86,7 +87,8 @@
 
 static int b43legacy_register_led(struct b43legacy_wldev *dev,
 				  struct b43legacy_led *led,
-				  const char *name, char *default_trigger,
+				  const char *name,
+				  const char *default_trigger,
 				  u8 led_index, bool activelow)
 {
 	int err;
@@ -163,10 +165,10 @@
 		snprintf(name, sizeof(name),
 			 "b43legacy-%s::radio", wiphy_name(hw->wiphy));
 		b43legacy_register_led(dev, &dev->led_radio, name,
-				 b43legacy_rfkill_led_name(dev),
+				 ieee80211_get_radio_led_name(hw),
 				 led_index, activelow);
-		/* Sync the RF-kill LED state with the switch state. */
-		if (dev->radio_hw_enable)
+		/* Sync the RF-kill LED state with radio and switch states. */
+		if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
 			b43legacy_led_turn_on(dev, led_index, activelow);
 		break;
 	case B43legacy_LED_WEIRD:
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/main.c	2012-03-22 19:16:39.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/main.c	2012-03-22 20:12:25.000000000 -0400
@@ -583,35 +583,6 @@
 	b43legacy_set_slot_time(dev, 20);
 }
 
-/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43legacy_interrupt_enable(struct b43legacy_wldev *dev,
-					     u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
-	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask |
-			  mask);
-
-	return old_mask;
-}
-
-/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43legacy_interrupt_disable(struct b43legacy_wldev *dev,
-					      u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
-	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
-
-	return old_mask;
-}
-
 /* Synchronize IRQ top- and bottom-half.
  * IRQs must be masked before calling this.
  * This must not be called with the irq_lock held.
@@ -955,23 +926,54 @@
 			      size + sizeof(struct b43legacy_plcp_hdr6));
 }
 
+/* Convert a b43legacy antenna number value to the PHY TX control value. */
+static u16 b43legacy_antenna_to_phyctl(int antenna)
+{
+	switch (antenna) {
+	case B43legacy_ANTENNA0:
+		return B43legacy_TX4_PHY_ANT0;
+	case B43legacy_ANTENNA1:
+		return B43legacy_TX4_PHY_ANT1;
+	}
+	return B43legacy_TX4_PHY_ANTLAST;
+}
+
 static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
 					    u16 ram_offset,
-					    u16 shm_size_offset, u8 rate)
+					    u16 shm_size_offset)
 {
 
 	unsigned int i, len, variable_len;
 	const struct ieee80211_mgmt *bcn;
 	const u8 *ie;
 	bool tim_found = 0;
+	unsigned int rate;
+	u16 ctl;
+	int antenna;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon);
 
 	bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
 	len = min((size_t)dev->wl->current_beacon->len,
 		  0x200 - sizeof(struct b43legacy_plcp_hdr6));
+	rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
 
 	b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
 					shm_size_offset, rate);
 
+	/* Write the PHY TX control parameters. */
+	antenna = B43legacy_ANTENNA_DEFAULT;
+	antenna = b43legacy_antenna_to_phyctl(antenna);
+	ctl = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				   B43legacy_SHM_SH_BEACPHYCTL);
+	/* We can't send beacons with short preamble. Would get PHY errors. */
+	ctl &= ~B43legacy_TX4_PHY_SHORTPRMBL;
+	ctl &= ~B43legacy_TX4_PHY_ANT;
+	ctl &= ~B43legacy_TX4_PHY_ENC;
+	ctl |= antenna;
+	ctl |= B43legacy_TX4_PHY_ENC_CCK;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_BEACPHYCTL, ctl);
+
 	/* Find the position of the TIM and the DTIM_period value
 	 * and write them to SHM. */
 	ie = bcn->u.beacon.variable;
@@ -1013,7 +1015,8 @@
 		b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
 			      "beacon template packet. AP or IBSS operation "
 			      "may be broken.\n");
-	}
+	} else
+		b43legacydbg(dev->wl, "Updated beacon template\n");
 }
 
 static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
@@ -1025,7 +1028,7 @@
 	__le16 dur;
 
 	plcp.data = 0;
-	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
+	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
 					       dev->wl->vif,
 					       size,
@@ -1129,10 +1132,103 @@
 		   0x200 - sizeof(struct b43legacy_plcp_hdr6));
 	b43legacy_write_template_common(dev, probe_resp_data,
 					size, ram_offset,
-					shm_size_offset, rate->bitrate);
+					shm_size_offset, rate->hw_value);
 	kfree(probe_resp_data);
 }
 
+static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+
+	if (wl->beacon0_uploaded)
+		return;
+	b43legacy_write_beacon_template(dev, 0x68, 0x18);
+	/* FIXME: Probe resp upload doesn't really belong here,
+	 *        but we don't use that feature anyway. */
+	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
+				      &__b43legacy_ratetable[3]);
+	wl->beacon0_uploaded = 1;
+}
+
+static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+
+	if (wl->beacon1_uploaded)
+		return;
+	b43legacy_write_beacon_template(dev, 0x468, 0x1A);
+	wl->beacon1_uploaded = 1;
+}
+
+static void handle_irq_beacon(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	u32 cmd, beacon0_valid, beacon1_valid;
+
+	if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
+		return;
+
+	/* This is the bottom half of the asynchronous beacon update. */
+
+	/* Ignore interrupt in the future. */
+	dev->irq_mask &= ~B43legacy_IRQ_BEACON;
+
+	cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+	beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID);
+	beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID);
+
+	/* Schedule interrupt manually, if busy. */
+	if (beacon0_valid && beacon1_valid) {
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON);
+		dev->irq_mask |= B43legacy_IRQ_BEACON;
+		return;
+	}
+
+	if (unlikely(wl->beacon_templates_virgin)) {
+		/* We never uploaded a beacon before.
+		 * Upload both templates now, but only mark one valid. */
+		wl->beacon_templates_virgin = 0;
+		b43legacy_upload_beacon0(dev);
+		b43legacy_upload_beacon1(dev);
+		cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+		cmd |= B43legacy_MACCMD_BEACON0_VALID;
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+	} else {
+		if (!beacon0_valid) {
+			b43legacy_upload_beacon0(dev);
+			cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+			cmd |= B43legacy_MACCMD_BEACON0_VALID;
+			b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+		} else if (!beacon1_valid) {
+			b43legacy_upload_beacon1(dev);
+			cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+			cmd |= B43legacy_MACCMD_BEACON1_VALID;
+			b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+		}
+	}
+}
+
+static void b43legacy_beacon_update_trigger_work(struct work_struct *work)
+{
+	struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl,
+					 beacon_update_trigger);
+	struct b43legacy_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) {
+		spin_lock_irq(&wl->irq_lock);
+		/* Update beacon right away or defer to IRQ. */
+		handle_irq_beacon(dev);
+		/* The handler might have updated the IRQ mask. */
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+				  dev->irq_mask);
+		mmiowb();
+		spin_unlock_irq(&wl->irq_lock);
+	}
+	mutex_unlock(&wl->mutex);
+}
+
 /* Asynchronously update the packet templates in template RAM.
  * Locking: Requires wl->irq_lock to be locked. */
 static void b43legacy_update_templates(struct b43legacy_wl *wl)
@@ -1156,54 +1252,24 @@
 	wl->current_beacon = beacon;
 	wl->beacon0_uploaded = 0;
 	wl->beacon1_uploaded = 0;
+	queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
 }
 
 static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
 				     u16 beacon_int)
 {
 	b43legacy_time_lock(dev);
-	if (dev->dev->id.revision >= 3)
-		b43legacy_write32(dev, 0x188, (beacon_int << 16));
-	else {
+	if (dev->dev->id.revision >= 3) {
+		b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_REP,
+				 (beacon_int << 16));
+		b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_START,
+				 (beacon_int << 10));
+	} else {
 		b43legacy_write16(dev, 0x606, (beacon_int >> 6));
 		b43legacy_write16(dev, 0x610, beacon_int);
 	}
 	b43legacy_time_unlock(dev);
-}
-
-static void handle_irq_beacon(struct b43legacy_wldev *dev)
-{
-	struct b43legacy_wl *wl = dev->wl;
-	u32 cmd;
-
-	if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
-		return;
-
-	/* This is the bottom half of the asynchronous beacon update. */
-
-	cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
-	if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) {
-		if (!wl->beacon0_uploaded) {
-			b43legacy_write_beacon_template(dev, 0x68,
-							B43legacy_SHM_SH_BTL0,
-							B43legacy_CCK_RATE_1MB);
-			b43legacy_write_probe_resp_template(dev, 0x268,
-							    B43legacy_SHM_SH_PRTLEN,
-							    &__b43legacy_ratetable[3]);
-			wl->beacon0_uploaded = 1;
-		}
-		cmd |= B43legacy_MACCMD_BEACON0_VALID;
-	}
-	if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) {
-		if (!wl->beacon1_uploaded) {
-			b43legacy_write_beacon_template(dev, 0x468,
-							B43legacy_SHM_SH_BTL1,
-							B43legacy_CCK_RATE_1MB);
-			wl->beacon1_uploaded = 1;
-		}
-		cmd |= B43legacy_MACCMD_BEACON1_VALID;
-	}
-	b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+	b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
 }
 
 static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
@@ -1302,7 +1368,7 @@
 	if (reason & B43legacy_IRQ_TX_OK)
 		handle_irq_transmit_status(dev);
 
-	b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	mmiowb();
 	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
 }
@@ -1354,18 +1420,18 @@
 	struct b43legacy_wldev *dev = dev_id;
 	u32 reason;
 
-	if (!dev)
-		return IRQ_NONE;
+	B43legacy_WARN_ON(!dev);
 
 	spin_lock(&dev->wl->irq_lock);
 
-	if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+	if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED))
+		/* This can only happen on shared IRQ lines. */
 		goto out;
 	reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff) /* shared IRQ */
 		goto out;
 	ret = IRQ_HANDLED;
-	reason &= b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
+	reason &= dev->irq_mask;
 	if (!reason)
 		goto out;
 
@@ -1389,10 +1455,9 @@
 					      & 0x0000DC00;
 
 	b43legacy_interrupt_ack(dev, reason);
-	/* disable all IRQs. They are enabled again in the bottom half. */
-	dev->irq_savedstate = b43legacy_interrupt_disable(dev,
-							  B43legacy_IRQ_ALL);
-	/* save the reason code and call our bottom half. */
+	/* Disable all IRQs. They are enabled again in the bottom half. */
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+	/* Save the reason code and call our bottom half. */
 	dev->irq_reason = reason;
 	tasklet_schedule(&dev->isr_tasklet);
 out:
@@ -1850,7 +1915,8 @@
 
 		/* Re-enable IRQs. */
 		spin_lock_irq(&dev->wl->irq_lock);
-		b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+				  dev->irq_mask);
 		spin_unlock_irq(&dev->wl->irq_lock);
 	}
 }
@@ -1869,10 +1935,9 @@
 		/* Mask IRQs before suspending MAC. Otherwise
 		 * the MAC stays busy and won't suspend. */
 		spin_lock_irq(&dev->wl->irq_lock);
-		tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
 		spin_unlock_irq(&dev->wl->irq_lock);
 		b43legacy_synchronize_irq(dev);
-		dev->irq_savedstate = tmp;
 
 		b43legacy_power_saving_ctl_bits(dev, -1, 1);
 		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
@@ -2295,6 +2360,7 @@
 				  dev->max_nr_keys - 8);
 }
 
+#ifdef CONFIG_B43LEGACY_HWRNG
 static int b43legacy_rng_read(struct hwrng *rng, u32 *data)
 {
 	struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv;
@@ -2310,17 +2376,21 @@
 
 	return (sizeof(u16));
 }
+#endif
 
 static void b43legacy_rng_exit(struct b43legacy_wl *wl)
 {
+#ifdef CONFIG_B43LEGACY_HWRNG
 	if (wl->rng_initialized)
 		hwrng_unregister(&wl->rng);
+#endif
 }
 
 static int b43legacy_rng_init(struct b43legacy_wl *wl)
 {
-	int err;
+	int err = 0;
 
+#ifdef CONFIG_B43LEGACY_HWRNG
 	snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
 		 "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
 	wl->rng.name = wl->rng_name;
@@ -2334,6 +2404,7 @@
 		       "number generator (%d)\n", err);
 	}
 
+#endif
 	return err;
 }
 
@@ -2555,7 +2626,6 @@
 	int antenna_tx;
 	int antenna_rx;
 	int err = 0;
-	u32 savedirqs;
 
 	antenna_tx = B43legacy_ANTENNA_DEFAULT;
 	antenna_rx = B43legacy_ANTENNA_DEFAULT;
@@ -2595,7 +2665,7 @@
 		spin_unlock_irqrestore(&wl->irq_lock, flags);
 		goto out_unlock_mutex;
 	}
-	savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 	b43legacy_synchronize_irq(dev);
 
@@ -2617,13 +2687,8 @@
 	/* Antennas for RX and management frame TX. */
 	b43legacy_mgmtframe_txantenna(dev, antenna_tx);
 
-	/* Update templates for AP mode. */
-	if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
-		b43legacy_set_beacon_int(dev, conf->beacon_int);
-
-
-	if (!!conf->radio_enabled != phy->radio_on) {
-		if (conf->radio_enabled) {
+	if (wl->radio_enabled != phy->radio_on) {
+		if (wl->radio_enabled) {
 			b43legacy_radio_turn_on(dev);
 			b43legacyinfo(dev->wl, "Radio turned on by software\n");
 			if (!dev->radio_hw_enable)
@@ -2639,7 +2704,7 @@
 	}
 
 	spin_lock_irqsave(&wl->irq_lock, flags);
-	b43legacy_interrupt_enable(dev, savedirqs);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	mmiowb();
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 out_unlock_mutex:
@@ -2702,9 +2767,9 @@
 	struct b43legacy_wldev *dev;
 	struct b43legacy_phy *phy;
 	unsigned long flags;
-	u32 savedirqs;
 
 	mutex_lock(&wl->mutex);
+	B43legacy_WARN_ON(wl->vif != vif);
 
 	dev = wl->current_dev;
 	phy = &dev->phy;
@@ -2717,12 +2782,35 @@
 		spin_unlock_irqrestore(&wl->irq_lock, flags);
 		goto out_unlock_mutex;
 	}
-	savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+
+	if (changed & BSS_CHANGED_BSSID) {
+		b43legacy_synchronize_irq(dev);
+
+		if (conf->bssid)
+			memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+		else
+			memset(wl->bssid, 0, ETH_ALEN);
+	}
+
+	if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
+		if (changed & BSS_CHANGED_BEACON &&
+		    (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) ||
+		     b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+			b43legacy_update_templates(wl);
+
+		if (changed & BSS_CHANGED_BSSID)
+			b43legacy_write_mac_bssid_templates(dev);
+	}
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
-	b43legacy_synchronize_irq(dev);
 
 	b43legacy_mac_suspend(dev);
 
+	if (changed & BSS_CHANGED_BEACON_INT &&
+	    (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) ||
+	     b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+		b43legacy_set_beacon_int(dev, conf->beacon_int);
+
 	if (changed & BSS_CHANGED_BASIC_RATES)
 		b43legacy_update_basic_rates(dev, conf->basic_rates);
 
@@ -2736,14 +2824,12 @@
 	b43legacy_mac_enable(dev);
 
 	spin_lock_irqsave(&wl->irq_lock, flags);
-	b43legacy_interrupt_enable(dev, savedirqs);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	/* XXX: why? */
 	mmiowb();
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
  out_unlock_mutex:
 	mutex_unlock(&wl->mutex);
-
-	return;
 }
 
 static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
@@ -2785,40 +2871,6 @@
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 }
 
-static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
-					 struct ieee80211_vif *vif,
-					 struct ieee80211_if_conf *conf)
-{
-	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
-	struct b43legacy_wldev *dev = wl->current_dev;
-	unsigned long flags;
-
-	if (!dev)
-		return -ENODEV;
-	mutex_lock(&wl->mutex);
-	spin_lock_irqsave(&wl->irq_lock, flags);
-	B43legacy_WARN_ON(wl->vif != vif);
-	if (conf->bssid)
-		memcpy(wl->bssid, conf->bssid, ETH_ALEN);
-	else
-		memset(wl->bssid, 0, ETH_ALEN);
-	if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
-		if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) {
-			B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP);
-			if (conf->changed & IEEE80211_IFCC_BEACON)
-				b43legacy_update_templates(wl);
-		} else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
-			if (conf->changed & IEEE80211_IFCC_BEACON)
-				b43legacy_update_templates(wl);
-		}
-		b43legacy_write_mac_bssid_templates(dev);
-	}
-	spin_unlock_irqrestore(&wl->irq_lock, flags);
-	mutex_unlock(&wl->mutex);
-
-	return 0;
-}
-
 /* Locking: wl->mutex */
 static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
 {
@@ -2832,8 +2884,7 @@
 	 * setting the status to INITIALIZED, as the interrupt handler
 	 * won't care about IRQs then. */
 	spin_lock_irqsave(&wl->irq_lock, flags);
-	dev->irq_savedstate = b43legacy_interrupt_disable(dev,
-							  B43legacy_IRQ_ALL);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
 	b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 	b43legacy_synchronize_irq(dev);
@@ -2873,7 +2924,7 @@
 
 	/* Start data flow (TX/RX) */
 	b43legacy_mac_enable(dev);
-	b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 
 	/* Start maintenance work */
 	b43legacy_periodic_tasks_setup(dev);
@@ -3036,7 +3087,7 @@
 	/* IRQ related flags */
 	dev->irq_reason = 0;
 	memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
-	dev->irq_savedstate = B43legacy_IRQ_MASKTEMPLATE;
+	dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE;
 
 	dev->mac_suspended = 1;
 
@@ -3378,11 +3429,6 @@
 	struct b43legacy_wldev *dev = wl->current_dev;
 	int did_init = 0;
 	int err = 0;
-	bool do_rfkill_exit = 0;
-
-	/* First register RFkill.
-	 * LEDs that are registered later depend on it. */
-	b43legacy_rfkill_init(dev);
 
 	/* Kill all old instance specific information to make sure
 	 * the card won't use it in the short timeframe between start
@@ -3390,15 +3436,17 @@
 	memset(wl->bssid, 0, ETH_ALEN);
 	memset(wl->mac_addr, 0, ETH_ALEN);
 	wl->filter_flags = 0;
+	wl->beacon0_uploaded = 0;
+	wl->beacon1_uploaded = 0;
+	wl->beacon_templates_virgin = 1;
+	wl->radio_enabled = 1;
 
 	mutex_lock(&wl->mutex);
 
 	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
 		err = b43legacy_wireless_core_init(dev);
-		if (err) {
-			do_rfkill_exit = 1;
+		if (err)
 			goto out_mutex_unlock;
-		}
 		did_init = 1;
 	}
 
@@ -3407,17 +3455,15 @@
 		if (err) {
 			if (did_init)
 				b43legacy_wireless_core_exit(dev);
-			do_rfkill_exit = 1;
 			goto out_mutex_unlock;
 		}
 	}
 
+	wiphy_rfkill_start_polling(hw->wiphy);
+
 out_mutex_unlock:
 	mutex_unlock(&wl->mutex);
 
-	if (do_rfkill_exit)
-		b43legacy_rfkill_exit(dev);
-
 	return err;
 }
 
@@ -3426,12 +3472,13 @@
 	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 	struct b43legacy_wldev *dev = wl->current_dev;
 
-	b43legacy_rfkill_exit(dev);
+	cancel_work_sync(&(wl->beacon_update_trigger));
 
 	mutex_lock(&wl->mutex);
 	if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
 		b43legacy_wireless_core_stop(dev);
 	b43legacy_wireless_core_exit(dev);
+	wl->radio_enabled = 0;
 	mutex_unlock(&wl->mutex);
 }
 
@@ -3455,13 +3502,13 @@
 	.remove_interface	= b43legacy_op_remove_interface,
 	.config			= b43legacy_op_dev_config,
 	.bss_info_changed	= b43legacy_op_bss_info_changed,
-	.config_interface	= b43legacy_op_config_interface,
 	.configure_filter	= b43legacy_op_configure_filter,
 	.get_stats		= b43legacy_op_get_stats,
 	.get_tx_stats		= b43legacy_op_get_tx_stats,
 	.start			= b43legacy_op_start,
 	.stop			= b43legacy_op_stop,
 	.set_tim		= b43legacy_op_beacon_set_tim,
+	.rfkill_poll		= b43legacy_rfkill_poll,
 };
 
 /* Hard-reset the chip. Do not call this directly.
@@ -3573,6 +3620,7 @@
 		have_bphy = 1;
 
 	dev->phy.gmode = (have_gphy || have_bphy);
+	dev->phy.radio_on = 1;
 	tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
 	b43legacy_wireless_core_reset(dev, tmp);
 
@@ -3758,6 +3806,7 @@
 	spin_lock_init(&wl->leds_lock);
 	mutex_init(&wl->mutex);
 	INIT_LIST_HEAD(&wl->devlist);
+	INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
 
 	ssb_set_devtypedata(dev, wl);
 	b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -6,7 +6,7 @@
 b43legacy-y				+= sysfs.o
 b43legacy-y				+= xmit.o
 # b43 RFKILL button support
-b43legacy-$(CONFIG_B43LEGACY_RFKILL)	+= rfkill.o
+b43legacy-y				+= rfkill.o
 # b43legacy LED support
 b43legacy-$(CONFIG_B43LEGACY_LEDS)	+= leds.o
 # b43legacy debugging
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/pio.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/pio.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/pio.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/pio.c	2009-09-09 18:13:59.000000000 -0400
@@ -443,7 +443,7 @@
 	pio->queue3 = queue;
 
 	if (dev->dev->id.revision < 3)
-		dev->irq_savedstate |= B43legacy_IRQ_PIO_WORKAROUND;
+		dev->irq_mask |= B43legacy_IRQ_PIO_WORKAROUND;
 
 	b43legacydbg(dev->wl, "PIO initialized\n");
 	err = 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/rfkill.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/rfkill.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/rfkill.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/rfkill.c	2009-09-09 18:13:59.000000000 -0400
@@ -22,15 +22,12 @@
 
 */
 
-#include "rfkill.h"
 #include "radio.h"
 #include "b43legacy.h"
 
-#include <linux/kmod.h>
-
 
 /* Returns TRUE, if the radio is enabled in hardware. */
-static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
+bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
 {
 	if (dev->phy.rev >= 3) {
 		if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
@@ -45,165 +42,43 @@
 }
 
 /* The poll callback for the hardware button. */
-static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
+void b43legacy_rfkill_poll(struct ieee80211_hw *hw)
 {
-	struct b43legacy_wldev *dev = poll_dev->private;
-	struct b43legacy_wl *wl = dev->wl;
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	struct ssb_bus *bus = dev->dev->bus;
 	bool enabled;
-	bool report_change = 0;
+	bool brought_up = false;
 
 	mutex_lock(&wl->mutex);
 	if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
-		mutex_unlock(&wl->mutex);
-		return;
+		if (ssb_bus_powerup(bus, 0)) {
+			mutex_unlock(&wl->mutex);
+			return;
+		}
+		ssb_device_enable(dev->dev, 0);
+		brought_up = true;
 	}
+
 	enabled = b43legacy_is_hw_radio_enabled(dev);
+
 	if (unlikely(enabled != dev->radio_hw_enable)) {
 		dev->radio_hw_enable = enabled;
-		report_change = 1;
 		b43legacyinfo(wl, "Radio hardware status changed to %s\n",
 			enabled ? "ENABLED" : "DISABLED");
-	}
-	mutex_unlock(&wl->mutex);
-
-	/* send the radio switch event to the system - note both a key press
-	 * and a release are required */
-	if (unlikely(report_change)) {
-		input_report_key(poll_dev->input, KEY_WLAN, 1);
-		input_report_key(poll_dev->input, KEY_WLAN, 0);
-	}
-}
-
-/* Called when the RFKILL toggled in software.
- * This is called without locking. */
-static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state)
-{
-	struct b43legacy_wldev *dev = data;
-	struct b43legacy_wl *wl = dev->wl;
-	int err = -EBUSY;
-
-	if (!wl->rfkill.registered)
-		return 0;
-
-	mutex_lock(&wl->mutex);
-	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
-		goto out_unlock;
-	err = 0;
-	switch (state) {
-	case RFKILL_STATE_UNBLOCKED:
-		if (!dev->radio_hw_enable) {
-			/* No luck. We can't toggle the hardware RF-kill
-			 * button from software. */
-			err = -EBUSY;
-			goto out_unlock;
+		wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
+		if (enabled != dev->phy.radio_on) {
+			if (enabled)
+				b43legacy_radio_turn_on(dev);
+			else
+				b43legacy_radio_turn_off(dev, 0);
 		}
-		if (!dev->phy.radio_on)
-			b43legacy_radio_turn_on(dev);
-		break;
-	case RFKILL_STATE_SOFT_BLOCKED:
-		if (dev->phy.radio_on)
-			b43legacy_radio_turn_off(dev, 0);
-		break;
-	default:
-		b43legacywarn(wl, "Received unexpected rfkill state %d.\n",
-			      state);
-		break;
 	}
 
-out_unlock:
-	mutex_unlock(&wl->mutex);
-
-	return err;
-}
-
-char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
-{
-	struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
-
-	if (!rfk->registered)
-		return NULL;
-	return rfkill_get_led_name(rfk->rfkill);
-}
-
-void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
-{
-	struct b43legacy_wl *wl = dev->wl;
-	struct b43legacy_rfkill *rfk = &(wl->rfkill);
-	int err;
-
-	rfk->registered = 0;
-
-	rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
-	if (!rfk->rfkill)
-		goto out_error;
-	snprintf(rfk->name, sizeof(rfk->name),
-		 "b43legacy-%s", wiphy_name(wl->hw->wiphy));
-	rfk->rfkill->name = rfk->name;
-	rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
-	rfk->rfkill->data = dev;
-	rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
-	rfk->rfkill->user_claim_unsupported = 1;
-
-	rfk->poll_dev = input_allocate_polled_device();
-	if (!rfk->poll_dev) {
-		rfkill_free(rfk->rfkill);
-		goto err_freed_rfk;
+	if (brought_up) {
+		ssb_device_disable(dev->dev, 0);
+		ssb_bus_may_powerdown(bus);
 	}
 
-	rfk->poll_dev->private = dev;
-	rfk->poll_dev->poll = b43legacy_rfkill_poll;
-	rfk->poll_dev->poll_interval = 1000; /* msecs */
-
-	rfk->poll_dev->input->name = rfk->name;
-	rfk->poll_dev->input->id.bustype = BUS_HOST;
-	rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor;
-	rfk->poll_dev->input->evbit[0] = BIT(EV_KEY);
-	set_bit(KEY_WLAN, rfk->poll_dev->input->keybit);
-
-	err = rfkill_register(rfk->rfkill);
-	if (err)
-		goto err_free_polldev;
-
-#ifdef CONFIG_RFKILL_INPUT_MODULE
-	/* B43legacy RF-kill isn't useful without the rfkill-input subsystem.
-	 * Try to load the module. */
-	err = request_module("rfkill-input");
-	if (err)
-		b43legacywarn(wl, "Failed to load the rfkill-input module."
-			"The built-in radio LED will not work.\n");
-#endif /* CONFIG_RFKILL_INPUT */
-
-	err = input_register_polled_device(rfk->poll_dev);
-	if (err)
-		goto err_unreg_rfk;
-
-	rfk->registered = 1;
-
-	return;
-err_unreg_rfk:
-	rfkill_unregister(rfk->rfkill);
-err_free_polldev:
-	input_free_polled_device(rfk->poll_dev);
-	rfk->poll_dev = NULL;
-err_freed_rfk:
-	rfk->rfkill = NULL;
-out_error:
-	rfk->registered = 0;
-	b43legacywarn(wl, "RF-kill button init failed\n");
-}
-
-void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
-{
-	struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
-
-	if (!rfk->registered)
-		return;
-	rfk->registered = 0;
-
-	input_unregister_polled_device(rfk->poll_dev);
-	rfkill_unregister(rfk->rfkill);
-	input_free_polled_device(rfk->poll_dev);
-	rfk->poll_dev = NULL;
-	rfk->rfkill = NULL;
+	mutex_unlock(&wl->mutex);
 }
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/rfkill.h linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/rfkill.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/rfkill.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/rfkill.h	2009-09-09 18:13:59.000000000 -0400
@@ -1,59 +1,11 @@
 #ifndef B43legacy_RFKILL_H_
 #define B43legacy_RFKILL_H_
 
+struct ieee80211_hw;
 struct b43legacy_wldev;
 
-#ifdef CONFIG_B43LEGACY_RFKILL
-
-#include <linux/rfkill.h>
-#include <linux/workqueue.h>
-#include <linux/input-polldev.h>
-
-
-
-struct b43legacy_rfkill {
-	/* The RFKILL subsystem data structure */
-	struct rfkill *rfkill;
-	/* The poll device for the RFKILL input button */
-	struct input_polled_dev *poll_dev;
-	/* Did initialization succeed? Used for freeing. */
-	bool registered;
-	/* The unique name of this rfkill switch */
-	char name[sizeof("b43legacy-phy4294967295")];
-};
-
-/* The init function returns void, because we are not interested
- * in failing the b43 init process when rfkill init failed. */
-void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
-void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
-
-char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
-
-
-#else /* CONFIG_B43LEGACY_RFKILL */
-/* No RFKILL support. */
-
-struct b43legacy_rfkill {
-	/* empty */
-};
-
-static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
-{
-}
-static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
-{
-}
-static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
-{
-}
-static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
-{
-}
-static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
-{
-	return NULL;
-}
+void b43legacy_rfkill_poll(struct ieee80211_hw *hw);
 
-#endif /* CONFIG_B43LEGACY_RFKILL */
+bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev);
 
 #endif /* B43legacy_RFKILL_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/xmit.c linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/xmit.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/xmit.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/xmit.c	2009-09-09 18:13:59.000000000 -0400
@@ -274,7 +274,7 @@
 
 	/* PHY TX Control word */
 	if (rate_ofdm)
-		phy_ctl |= B43legacy_TX4_PHY_OFDM;
+		phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM;
 	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
 		phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
 	switch (info->antenna_sel_tx) {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/xmit.h linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/xmit.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/b43legacy/xmit.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/b43legacy/xmit.h	2009-09-09 18:13:59.000000000 -0400
@@ -67,7 +67,9 @@
 #define B43legacy_TX4_EFT_RTSFBOFDM	0x0010 /* RTS/CTS fallback rate type */
 
 /* PHY TX control word */
-#define B43legacy_TX4_PHY_OFDM		0x0001 /* Data frame rate type */
+#define B43legacy_TX4_PHY_ENC		0x0003 /* Data frame encoding */
+#define B43legacy_TX4_PHY_ENC_CCK	0x0000 /* CCK */
+#define B43legacy_TX4_PHY_ENC_OFDM	0x0001 /* Data frame rate type */
 #define B43legacy_TX4_PHY_SHORTPRMBL	0x0010 /* Use short preamble */
 #define B43legacy_TX4_PHY_ANT		0x03C0 /* Antenna selection */
 #define  B43legacy_TX4_PHY_ANT0		0x0000 /* Use antenna 0 */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/hostap_80211_tx.c linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/hostap_80211_tx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/hostap_80211_tx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/hostap_80211_tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -377,7 +377,7 @@
 {
 	struct hostap_interface *iface;
 	local_info_t *local;
-	int ret = 1;
+	int ret = NETDEV_TX_BUSY;
 	u16 fc;
 	struct hostap_tx_data tx;
 	ap_tx_ret tx_ret;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/hostap_hw.c linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/hostap_hw.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/hostap_hw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/hostap_hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -1423,7 +1423,7 @@
 		prism2_check_sta_fw_version(local);
 
 		if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR,
-				    &dev->dev_addr, 6, 1) < 0) {
+				    dev->dev_addr, 6, 1) < 0) {
 			printk("%s: could not get own MAC address\n",
 			       dev->name);
 		}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/hostap_plx.c linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/hostap_plx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/hostap_plx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/hostap_plx.c	2009-09-09 18:13:59.000000000 -0400
@@ -435,7 +435,7 @@
 	unsigned long pccard_attr_mem;
 	unsigned int pccard_attr_len;
 	void __iomem *attr_mem = NULL;
-	unsigned int cor_offset, cor_index;
+	unsigned int cor_offset = 0, cor_index = 0;
 	u32 reg;
 	local_info_t *local = NULL;
 	struct net_device *dev = NULL;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/hostap/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/hostap/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -29,7 +29,7 @@
 	PLX/PCI/CS version of the driver to actually use the driver.
 
 	The driver can be compiled as a module and it will be called
-	"hostap.ko".
+	hostap.
 
 config HOSTAP_FIRMWARE
 	bool "Support downloading firmware images with Host AP driver"
@@ -68,7 +68,7 @@
 	driver.
 
 	The driver can be compiled as a module and will be named
-	"hostap_plx.ko".
+	hostap_plx.
 
 config HOSTAP_PCI
 	tristate "Host AP driver for Prism2.5 PCI adaptors"
@@ -81,7 +81,7 @@
 	driver.
 
 	The driver can be compiled as a module and will be named
-	"hostap_pci.ko".
+	hostap_pci.
 
 config HOSTAP_CS
 	tristate "Host AP driver for Prism2/2.5/3 PC Cards"
@@ -94,4 +94,4 @@
 	driver.
 
 	The driver can be compiled as a module and will be named
-	"hostap_cs.ko".
+	hostap_cs.
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/ipw2100.c linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/ipw2100.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/ipw2100.c	2012-03-22 19:16:48.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/ipw2100.c	2012-03-22 20:12:33.000000000 -0400
@@ -3488,7 +3488,7 @@
 static ssize_t show_cfg(struct device *d, struct device_attribute *attr,
 			char *buf)
 {
-	struct ipw2100_priv *p = d->driver_data;
+	struct ipw2100_priv *p = dev_get_drvdata(d);
 	return sprintf(buf, "0x%08x\n", (int)p->config);
 }
 
@@ -3497,7 +3497,7 @@
 static ssize_t show_status(struct device *d, struct device_attribute *attr,
 			   char *buf)
 {
-	struct ipw2100_priv *p = d->driver_data;
+	struct ipw2100_priv *p = dev_get_drvdata(d);
 	return sprintf(buf, "0x%08x\n", (int)p->status);
 }
 
@@ -3506,7 +3506,7 @@
 static ssize_t show_capability(struct device *d, struct device_attribute *attr,
 			       char *buf)
 {
-	struct ipw2100_priv *p = d->driver_data;
+	struct ipw2100_priv *p = dev_get_drvdata(d);
 	return sprintf(buf, "0x%08x\n", (int)p->capability);
 }
 
@@ -4224,7 +4224,7 @@
 	   1 - SW based RF kill active (sysfs)
 	   2 - HW based RF kill active
 	   3 - Both HW and SW baed RF kill active */
-	struct ipw2100_priv *priv = (struct ipw2100_priv *)d->driver_data;
+	struct ipw2100_priv *priv = dev_get_drvdata(d);
 	int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) |
 	    (rf_kill_active(priv) ? 0x2 : 0x0);
 	return sprintf(buf, "%i\n", val);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/ipw2200.c linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/ipw2200.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/ipw2200.c	2012-03-22 19:16:57.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/ipw2200.c	2012-03-22 20:12:40.000000000 -0400
@@ -1527,7 +1527,7 @@
 static ssize_t show_status(struct device *d,
 			   struct device_attribute *attr, char *buf)
 {
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 	return sprintf(buf, "0x%08x\n", (int)p->status);
 }
 
@@ -1536,7 +1536,7 @@
 static ssize_t show_cfg(struct device *d, struct device_attribute *attr,
 			char *buf)
 {
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 	return sprintf(buf, "0x%08x\n", (int)p->config);
 }
 
@@ -1545,7 +1545,7 @@
 static ssize_t show_nic_type(struct device *d,
 			     struct device_attribute *attr, char *buf)
 {
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 	return sprintf(buf, "TYPE: %d\n", priv->nic_type);
 }
 
@@ -1555,7 +1555,7 @@
 				  struct device_attribute *attr, char *buf)
 {
 	u32 len = sizeof(u32), tmp = 0;
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 
 	if (ipw_get_ordinal(p, IPW_ORD_STAT_UCODE_VERSION, &tmp, &len))
 		return 0;
@@ -1569,7 +1569,7 @@
 			char *buf)
 {
 	u32 len = sizeof(u32), tmp = 0;
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 
 	if (ipw_get_ordinal(p, IPW_ORD_STAT_RTC, &tmp, &len))
 		return 0;
@@ -1586,14 +1586,15 @@
 static ssize_t show_eeprom_delay(struct device *d,
 				 struct device_attribute *attr, char *buf)
 {
-	int n = ((struct ipw_priv *)d->driver_data)->eeprom_delay;
+	struct ipw_priv *p = dev_get_drvdata(d);
+	int n = p->eeprom_delay;
 	return sprintf(buf, "%i\n", n);
 }
 static ssize_t store_eeprom_delay(struct device *d,
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 	sscanf(buf, "%i", &p->eeprom_delay);
 	return strnlen(buf, count);
 }
@@ -1605,7 +1606,7 @@
 				      struct device_attribute *attr, char *buf)
 {
 	u32 reg = 0;
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 
 	reg = ipw_read_reg32(p, IPW_INTERNAL_CMD_EVENT);
 	return sprintf(buf, "0x%08x\n", reg);
@@ -1615,7 +1616,7 @@
 				       const char *buf, size_t count)
 {
 	u32 reg;
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 
 	sscanf(buf, "%x", &reg);
 	ipw_write_reg32(p, IPW_INTERNAL_CMD_EVENT, reg);
@@ -1629,7 +1630,7 @@
 				 struct device_attribute *attr, char *buf)
 {
 	u32 reg = 0;
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 
 	reg = ipw_read_reg32(p, 0x301100);
 	return sprintf(buf, "0x%08x\n", reg);
@@ -1639,7 +1640,7 @@
 				  const char *buf, size_t count)
 {
 	u32 reg;
-	struct ipw_priv *p = d->driver_data;
+	struct ipw_priv *p = dev_get_drvdata(d);
 
 	sscanf(buf, "%x", &reg);
 	ipw_write_reg32(p, 0x301100, reg);
@@ -1653,7 +1654,7 @@
 				   struct device_attribute *attr, char *buf)
 {
 	u32 reg = 0;
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 
 	if (priv->status & STATUS_INDIRECT_DWORD)
 		reg = ipw_read_reg32(priv, priv->indirect_dword);
@@ -1666,7 +1667,7 @@
 				    struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 
 	sscanf(buf, "%x", &priv->indirect_dword);
 	priv->status |= STATUS_INDIRECT_DWORD;
@@ -1680,7 +1681,7 @@
 				  struct device_attribute *attr, char *buf)
 {
 	u8 reg = 0;
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 
 	if (priv->status & STATUS_INDIRECT_BYTE)
 		reg = ipw_read_reg8(priv, priv->indirect_byte);
@@ -1693,7 +1694,7 @@
 				   struct device_attribute *attr,
 				   const char *buf, size_t count)
 {
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 
 	sscanf(buf, "%x", &priv->indirect_byte);
 	priv->status |= STATUS_INDIRECT_BYTE;
@@ -1707,7 +1708,7 @@
 				 struct device_attribute *attr, char *buf)
 {
 	u32 reg = 0;
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 
 	if (priv->status & STATUS_DIRECT_DWORD)
 		reg = ipw_read32(priv, priv->direct_dword);
@@ -1720,7 +1721,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 
 	sscanf(buf, "%x", &priv->direct_dword);
 	priv->status |= STATUS_DIRECT_DWORD;
@@ -1747,7 +1748,7 @@
 	   1 - SW based RF kill active (sysfs)
 	   2 - HW based RF kill active
 	   3 - Both HW and SW baed RF kill active */
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 	int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) |
 	    (rf_kill_active(priv) ? 0x2 : 0x0);
 	return sprintf(buf, "%i\n", val);
@@ -1791,7 +1792,7 @@
 static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	struct ipw_priv *priv = d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 
 	ipw_radio_kill_sw(priv, buf[0] == '1');
 
@@ -1803,7 +1804,7 @@
 static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr,
 			       char *buf)
 {
-	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 	int pos = 0, len = 0;
 	if (priv->config & CFG_SPEED_SCAN) {
 		while (priv->speed_scan[pos] != 0)
@@ -1818,7 +1819,7 @@
 static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 	int channel, pos = 0;
 	const char *p = buf;
 
@@ -1857,14 +1858,14 @@
 static ssize_t show_net_stats(struct device *d, struct device_attribute *attr,
 			      char *buf)
 {
-	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 	return sprintf(buf, "%c\n", (priv->config & CFG_NET_STATS) ? '1' : '0');
 }
 
 static ssize_t store_net_stats(struct device *d, struct device_attribute *attr,
 			       const char *buf, size_t count)
 {
-	struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;
+	struct ipw_priv *priv = dev_get_drvdata(d);
 	if (buf[0] == '1')
 		priv->config |= CFG_NET_STATS;
 	else
@@ -2873,45 +2874,27 @@
 	return 0;
 }
 
-static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
-				 u32 src_phys, u32 dest_address, u32 length)
+static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address,
+				 int nr, u32 dest_address, u32 len)
 {
-	u32 bytes_left = length;
-	u32 src_offset = 0;
-	u32 dest_offset = 0;
-	int status = 0;
+	int ret, i;
+	u32 size;
+
 	IPW_DEBUG_FW(">> \n");
-	IPW_DEBUG_FW_INFO("src_phys=0x%x dest_address=0x%x length=0x%x\n",
-			  src_phys, dest_address, length);
-	while (bytes_left > CB_MAX_LENGTH) {
-		status = ipw_fw_dma_add_command_block(priv,
-						      src_phys + src_offset,
-						      dest_address +
-						      dest_offset,
-						      CB_MAX_LENGTH, 0, 0);
-		if (status) {
+	IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n",
+			  nr, dest_address, len);
+
+	for (i = 0; i < nr; i++) {
+		size = min_t(u32, len - i * CB_MAX_LENGTH, CB_MAX_LENGTH);
+		ret = ipw_fw_dma_add_command_block(priv, src_address[i],
+						   dest_address +
+						   i * CB_MAX_LENGTH, size,
+						   0, 0);
+		if (ret) {
 			IPW_DEBUG_FW_INFO(": Failed\n");
 			return -1;
 		} else
 			IPW_DEBUG_FW_INFO(": Added new cb\n");
-
-		src_offset += CB_MAX_LENGTH;
-		dest_offset += CB_MAX_LENGTH;
-		bytes_left -= CB_MAX_LENGTH;
-	}
-
-	/* add the buffer tail */
-	if (bytes_left > 0) {
-		status =
-		    ipw_fw_dma_add_command_block(priv, src_phys + src_offset,
-						 dest_address + dest_offset,
-						 bytes_left, 0, 0);
-		if (status) {
-			IPW_DEBUG_FW_INFO(": Failed on the buffer tail\n");
-			return -1;
-		} else
-			IPW_DEBUG_FW_INFO
-			    (": Adding new cb - the buffer tail\n");
 	}
 
 	IPW_DEBUG_FW("<< \n");
@@ -3159,62 +3142,91 @@
 
 static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len)
 {
-	int rc = -1;
+	int ret = -1;
 	int offset = 0;
 	struct fw_chunk *chunk;
-	dma_addr_t shared_phys;
-	u8 *shared_virt;
+	int total_nr = 0;
+	int i;
+	struct pci_pool *pool;
+	u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL];
+	dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL];
 
 	IPW_DEBUG_TRACE("<< : \n");
-	shared_virt = pci_alloc_consistent(priv->pci_dev, len, &shared_phys);
 
-	if (!shared_virt)
+	pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0);
+	if (!pool) {
+		IPW_ERROR("pci_pool_create failed\n");
 		return -ENOMEM;
-
-	memmove(shared_virt, data, len);
+	}
 
 	/* Start the Dma */
-	rc = ipw_fw_dma_enable(priv);
+	ret = ipw_fw_dma_enable(priv);
 
-	if (priv->sram_desc.last_cb_index > 0) {
-		/* the DMA is already ready this would be a bug. */
-		BUG();
-		goto out;
-	}
+	/* the DMA is already ready this would be a bug. */
+	BUG_ON(priv->sram_desc.last_cb_index > 0);
 
 	do {
+		u32 chunk_len;
+		u8 *start;
+		int size;
+		int nr = 0;
+
 		chunk = (struct fw_chunk *)(data + offset);
 		offset += sizeof(struct fw_chunk);
+		chunk_len = le32_to_cpu(chunk->length);
+		start = data + offset;
+
+		nr = (chunk_len + CB_MAX_LENGTH - 1) / CB_MAX_LENGTH;
+		for (i = 0; i < nr; i++) {
+			virts[total_nr] = pci_pool_alloc(pool, GFP_KERNEL,
+							 &phys[total_nr]);
+			if (!virts[total_nr]) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			size = min_t(u32, chunk_len - i * CB_MAX_LENGTH,
+				     CB_MAX_LENGTH);
+			memcpy(virts[total_nr], start, size);
+			start += size;
+			total_nr++;
+			/* We don't support fw chunk larger than 64*8K */
+			BUG_ON(total_nr > CB_NUMBER_OF_ELEMENTS_SMALL);
+		}
+
 		/* build DMA packet and queue up for sending */
 		/* dma to chunk->address, the chunk->length bytes from data +
 		 * offeset*/
 		/* Dma loading */
-		rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset,
-					   le32_to_cpu(chunk->address),
-					   le32_to_cpu(chunk->length));
-		if (rc) {
+		ret = ipw_fw_dma_add_buffer(priv, &phys[total_nr - nr],
+					    nr, le32_to_cpu(chunk->address),
+					    chunk_len);
+		if (ret) {
 			IPW_DEBUG_INFO("dmaAddBuffer Failed\n");
 			goto out;
 		}
 
-		offset += le32_to_cpu(chunk->length);
+		offset += chunk_len;
 	} while (offset < len);
 
 	/* Run the DMA and wait for the answer */
-	rc = ipw_fw_dma_kick(priv);
-	if (rc) {
+	ret = ipw_fw_dma_kick(priv);
+	if (ret) {
 		IPW_ERROR("dmaKick Failed\n");
 		goto out;
 	}
 
-	rc = ipw_fw_dma_wait(priv);
-	if (rc) {
+	ret = ipw_fw_dma_wait(priv);
+	if (ret) {
 		IPW_ERROR("dmaWaitSync Failed\n");
 		goto out;
 	}
-      out:
-	pci_free_consistent(priv->pci_dev, len, shared_virt, shared_phys);
-	return rc;
+ out:
+	for (i = 0; i < total_nr; i++)
+		pci_pool_free(pool, virts[i], phys[i]);
+
+	pci_pool_destroy(pool);
+
+	return ret;
 }
 
 /* stop nic */
@@ -6228,7 +6240,7 @@
 			};
 
 			u8 channel;
-			while (channel_index < IPW_SCAN_CHANNELS) {
+			while (channel_index < IPW_SCAN_CHANNELS - 1) {
 				channel =
 				    priv->speed_scan[priv->speed_scan_pos];
 				if (channel == 0) {
@@ -11526,7 +11538,8 @@
 static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	IPW_DEBUG_INFO("prom dev->xmit\n");
-	return -EOPNOTSUPP;
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
 }
 
 static const struct net_device_ops ipw_prom_netdev_ops = {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/libipw_module.c linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/libipw_module.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/libipw_module.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/libipw_module.c	2009-09-09 18:13:59.000000000 -0400
@@ -154,10 +154,6 @@
 		goto failed;
 	}
 	ieee = netdev_priv(dev);
-#ifdef CONFIG_COMPAT_NET_DEV_OPS
-	dev->hard_start_xmit = ieee80211_xmit;
-	dev->change_mtu = ieee80211_change_mtu;
-#endif
 
 	ieee->dev = dev;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/libipw_tx.c linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/libipw_tx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ipw2x00/libipw_tx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ipw2x00/libipw_tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -539,7 +539,7 @@
 	spin_unlock_irqrestore(&ieee->lock, flags);
 	netif_stop_queue(dev);
 	dev->stats.tx_errors++;
-	return 1;
+	return NETDEV_TX_BUSY;
 }
 EXPORT_SYMBOL(ieee80211_xmit);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c	2012-03-22 19:17:03.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c	2012-03-22 20:12:44.000000000 -0400
@@ -95,188 +95,6 @@
 	/* the rest are 0 by default */
 };
 
-/*************** STATION TABLE MANAGEMENT ****
- * mac80211 should be examined to determine if sta_info is duplicating
- * the functionality provided here
- */
-
-/**************************************************************/
-#if 0 /* temporary disable till we add real remove station */
-/**
- * iwl3945_remove_station - Remove driver's knowledge of station.
- *
- * NOTE:  This does not remove station from device's station table.
- */
-static u8 iwl3945_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
-{
-	int index = IWL_INVALID_STATION;
-	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-
-	if (is_ap)
-		index = IWL_AP_ID;
-	else if (is_broadcast_ether_addr(addr))
-		index = priv->hw_params.bcast_sta_id;
-	else
-		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
-			if (priv->stations_39[i].used &&
-			    !compare_ether_addr(priv->stations_39[i].sta.sta.addr,
-						addr)) {
-				index = i;
-				break;
-			}
-
-	if (unlikely(index == IWL_INVALID_STATION))
-		goto out;
-
-	if (priv->stations_39[index].used) {
-		priv->stations_39[index].used = 0;
-		priv->num_stations--;
-	}
-
-	BUG_ON(priv->num_stations < 0);
-
-out:
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-	return 0;
-}
-#endif
-
-/**
- * iwl3945_clear_stations_table - Clear the driver's station table
- *
- * NOTE:  This does not clear or otherwise alter the device's station table.
- */
-static void iwl3945_clear_stations_table(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-
-	priv->num_stations = 0;
-	memset(priv->stations_39, 0, sizeof(priv->stations_39));
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-/**
- * iwl3945_add_station - Add station to station tables in driver and device
- */
-u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
-{
-	int i;
-	int index = IWL_INVALID_STATION;
-	struct iwl3945_station_entry *station;
-	unsigned long flags_spin;
-	u8 rate;
-
-	spin_lock_irqsave(&priv->sta_lock, flags_spin);
-	if (is_ap)
-		index = IWL_AP_ID;
-	else if (is_broadcast_ether_addr(addr))
-		index = priv->hw_params.bcast_sta_id;
-	else
-		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
-			if (!compare_ether_addr(priv->stations_39[i].sta.sta.addr,
-						addr)) {
-				index = i;
-				break;
-			}
-
-			if (!priv->stations_39[i].used &&
-			    index == IWL_INVALID_STATION)
-				index = i;
-		}
-
-	/* These two conditions has the same outcome but keep them separate
-	  since they have different meaning */
-	if (unlikely(index == IWL_INVALID_STATION)) {
-		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-		return index;
-	}
-
-	if (priv->stations_39[index].used &&
-	   !compare_ether_addr(priv->stations_39[index].sta.sta.addr, addr)) {
-		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-		return index;
-	}
-
-	IWL_DEBUG_ASSOC(priv, "Add STA ID %d: %pM\n", index, addr);
-	station = &priv->stations_39[index];
-	station->used = 1;
-	priv->num_stations++;
-
-	/* Set up the REPLY_ADD_STA command to send to device */
-	memset(&station->sta, 0, sizeof(struct iwl3945_addsta_cmd));
-	memcpy(station->sta.sta.addr, addr, ETH_ALEN);
-	station->sta.mode = 0;
-	station->sta.sta.sta_id = index;
-	station->sta.station_flags = 0;
-
-	if (priv->band == IEEE80211_BAND_5GHZ)
-		rate = IWL_RATE_6M_PLCP;
-	else
-		rate =	IWL_RATE_1M_PLCP;
-
-	/* Turn on both antennas for the station... */
-	station->sta.rate_n_flags =
-			iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
-	/* Add station to device's station table */
-	iwl_send_add_sta(priv,
-			 (struct iwl_addsta_cmd *)&station->sta, flags);
-	return index;
-
-}
-
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
-{
-	int rc = 0;
-	struct iwl_rx_packet *res = NULL;
-	struct iwl3945_rxon_assoc_cmd rxon_assoc;
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_RXON_ASSOC,
-		.len = sizeof(rxon_assoc),
-		.meta.flags = CMD_WANT_SKB,
-		.data = &rxon_assoc,
-	};
-	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
-	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
-
-	if ((rxon1->flags == rxon2->flags) &&
-	    (rxon1->filter_flags == rxon2->filter_flags) &&
-	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
-		return 0;
-	}
-
-	rxon_assoc.flags = priv->staging_rxon.flags;
-	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
-	rxon_assoc.reserved = 0;
-
-	rc = iwl_send_cmd_sync(priv, &cmd);
-	if (rc)
-		return rc;
-
-	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
-	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
-		rc = -EIO;
-	}
-
-	priv->alloc_rxb_skb--;
-	dev_kfree_skb_any(cmd.meta.u.skb);
-
-	return rc;
-}
-
 /**
  * iwl3945_get_antenna_flags - Get antenna flags for RXON command
  * @priv: eeprom and antenna fields are used to determine antenna flags
@@ -314,150 +132,6 @@
 	return 0;		/* "diversity" is default if error */
 }
 
-/**
- * iwl3945_commit_rxon - commit staging_rxon to hardware
- *
- * The RXON command in staging_rxon is committed to the hardware and
- * the active_rxon structure is updated with the new data.  This
- * function correctly transitions out of the RXON_ASSOC_MSK state if
- * a HW tune is required based on the RXON structure changes.
- */
-static int iwl3945_commit_rxon(struct iwl_priv *priv)
-{
-	/* cast away the const for active_rxon in this function */
-	struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
-	struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
-	int rc = 0;
-	bool new_assoc =
-		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-	if (!iwl_is_alive(priv))
-		return -1;
-
-	/* always get timestamp with Rx frame */
-	staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
-
-	/* select antenna */
-	staging_rxon->flags &=
-	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
-	staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
-
-	rc = iwl_check_rxon_cmd(priv);
-	if (rc) {
-		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-		return -EINVAL;
-	}
-
-	/* If we don't need to send a full RXON, we can use
-	 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
-	 * and other flags for the current radio configuration. */
-	if (!iwl_full_rxon_required(priv)) {
-		rc = iwl3945_send_rxon_assoc(priv);
-		if (rc) {
-			IWL_ERR(priv, "Error setting RXON_ASSOC "
-				  "configuration (%d).\n", rc);
-			return rc;
-		}
-
-		memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-		return 0;
-	}
-
-	/* If we are currently associated and the new config requires
-	 * an RXON_ASSOC and the new config wants the associated mask enabled,
-	 * we must clear the associated from the active configuration
-	 * before we apply the new config */
-	if (iwl_is_associated(priv) && new_assoc) {
-		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-		/*
-		 * reserved4 and 5 could have been filled by the iwlcore code.
-		 * Let's clear them before pushing to the 3945.
-		 */
-		active_rxon->reserved4 = 0;
-		active_rxon->reserved5 = 0;
-		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-				      sizeof(struct iwl3945_rxon_cmd),
-				      &priv->active_rxon);
-
-		/* If the mask clearing failed then we set
-		 * active_rxon back to what it was previously */
-		if (rc) {
-			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-			IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
-				  "configuration (%d).\n", rc);
-			return rc;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "Sending RXON\n"
-		       "* with%s RXON_FILTER_ASSOC_MSK\n"
-		       "* channel = %d\n"
-		       "* bssid = %pM\n",
-		       (new_assoc ? "" : "out"),
-		       le16_to_cpu(staging_rxon->channel),
-		       staging_rxon->bssid_addr);
-
-	/*
-	 * reserved4 and 5 could have been filled by the iwlcore code.
-	 * Let's clear them before pushing to the 3945.
-	 */
-	staging_rxon->reserved4 = 0;
-	staging_rxon->reserved5 = 0;
-
-	iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
-
-	/* Apply the new configuration */
-	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-			      sizeof(struct iwl3945_rxon_cmd),
-			      staging_rxon);
-	if (rc) {
-		IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
-		return rc;
-	}
-
-	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-	iwl3945_clear_stations_table(priv);
-
-	/* If we issue a new RXON command which required a tune then we must
-	 * send a new TXPOWER command or we won't be able to Tx any frames */
-	rc = priv->cfg->ops->lib->send_tx_power(priv);
-	if (rc) {
-		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
-		return rc;
-	}
-
-	/* Add the broadcast address so we can send broadcast frames */
-	if (iwl3945_add_station(priv, iwl_bcast_addr, 0, 0) ==
-	    IWL_INVALID_STATION) {
-		IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
-		return -EIO;
-	}
-
-	/* If we have set the ASSOC_MSK and we are in BSS mode then
-	 * add the IWL_AP_ID to the station rate table */
-	if (iwl_is_associated(priv) &&
-	    (priv->iw_mode == NL80211_IFTYPE_STATION))
-		if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr,
-					1, 0)
-		    == IWL_INVALID_STATION) {
-			IWL_ERR(priv, "Error adding AP address for transmit\n");
-			return -EIO;
-		}
-
-	/* Init the hardware's rate fallback order based on the band */
-	rc = iwl3945_init_hw_rate_table(priv);
-	if (rc) {
-		IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
-		return -EIO;
-	}
-
-	return 0;
-}
-
 static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
 				   struct ieee80211_key_conf *keyconf,
 				   u8 sta_id)
@@ -477,32 +151,31 @@
 	key_flags &= ~STA_KEY_FLG_INVALID;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
-	priv->stations_39[sta_id].keyinfo.alg = keyconf->alg;
-	priv->stations_39[sta_id].keyinfo.keylen = keyconf->keylen;
-	memcpy(priv->stations_39[sta_id].keyinfo.key, keyconf->key,
+	priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
 	       keyconf->keylen);
 
-	memcpy(priv->stations_39[sta_id].sta.key.key, keyconf->key,
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
 	       keyconf->keylen);
 
-	if ((priv->stations_39[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
 			== STA_KEY_FLG_NO_ENC)
-		priv->stations_39[sta_id].sta.key.key_offset =
+		priv->stations[sta_id].sta.key.key_offset =
 				 iwl_get_free_ucode_key_index(priv);
 	/* else, we are overriding an existing key => no need to allocated room
 	* in uCode. */
 
-	WARN(priv->stations_39[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
 		"no space for a new key");
 
-	priv->stations_39[sta_id].sta.key.key_flags = key_flags;
-	priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
 	IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");
 
-	ret = iwl_send_add_sta(priv,
-		(struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, CMD_ASYNC);
+	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
 
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
@@ -528,17 +201,16 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
-	memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key));
-	memset(&priv->stations_39[sta_id].sta.key, 0,
+	memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
+	memset(&priv->stations[sta_id].sta.key, 0,
 		sizeof(struct iwl4965_keyinfo));
-	priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
-	priv->stations_39[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations_39[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
 	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
-	iwl_send_add_sta(priv,
-		(struct iwl_addsta_cmd *)&priv->stations_39[sta_id].sta, 0);
+	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
 	return 0;
 }
 
@@ -739,7 +411,8 @@
 		priv->rxon_timing.atim_window = 0;
 	} else {
 		priv->rxon_timing.beacon_interval =
-			iwl3945_adjust_beacon_interval(conf->beacon_int);
+			iwl3945_adjust_beacon_interval(
+				priv->vif->bss_conf.beacon_int);
 		/* TODO: we need to get atim_window from upper stack
 		 * for now we set to 0 */
 		priv->rxon_timing.atim_window = 0;
@@ -758,35 +431,6 @@
 		le16_to_cpu(priv->rxon_timing.atim_window));
 }
 
-static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
-{
-	if (mode == NL80211_IFTYPE_ADHOC) {
-		const struct iwl_channel_info *ch_info;
-
-		ch_info = iwl_get_channel_info(priv,
-			priv->band,
-			le16_to_cpu(priv->staging_rxon.channel));
-
-		if (!ch_info || !is_channel_ibss(ch_info)) {
-			IWL_ERR(priv, "channel %d not IBSS channel\n",
-				  le16_to_cpu(priv->staging_rxon.channel));
-			return -EINVAL;
-		}
-	}
-
-	iwl_connection_init_rx_config(priv, mode);
-
-	iwl3945_clear_stations_table(priv);
-
-	/* don't commit rxon if rf-kill is on*/
-	if (!iwl_is_ready_rf(priv))
-		return -EAGAIN;
-
-	iwl3945_commit_rxon(priv);
-
-	return 0;
-}
-
 static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
 				      struct ieee80211_tx_info *info,
 				      struct iwl_cmd *cmd,
@@ -794,8 +438,7 @@
 				      int sta_id)
 {
 	struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-	struct iwl3945_hw_key *keyinfo =
-	    &priv->stations_39[sta_id].keyinfo;
+	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
 
 	switch (keyinfo->alg) {
 	case ALG_CCMP:
@@ -893,64 +536,6 @@
 	tx->next_frame_len = 0;
 }
 
-/**
- * iwl3945_get_sta_id - Find station's index within station table
- */
-static int iwl3945_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
-{
-	int sta_id;
-	u16 fc = le16_to_cpu(hdr->frame_control);
-
-	/* If this frame is broadcast or management, use broadcast station id */
-	if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
-	    is_multicast_ether_addr(hdr->addr1))
-		return priv->hw_params.bcast_sta_id;
-
-	switch (priv->iw_mode) {
-
-	/* If we are a client station in a BSS network, use the special
-	 * AP station entry (that's the only station we communicate with) */
-	case NL80211_IFTYPE_STATION:
-		return IWL_AP_ID;
-
-	/* If we are an AP, then find the station, or use BCAST */
-	case NL80211_IFTYPE_AP:
-		sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
-		if (sta_id != IWL_INVALID_STATION)
-			return sta_id;
-		return priv->hw_params.bcast_sta_id;
-
-	/* If this frame is going out to an IBSS network, find the station,
-	 * or create a new station table entry */
-	case NL80211_IFTYPE_ADHOC: {
-		/* Create new station table entry */
-		sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
-		if (sta_id != IWL_INVALID_STATION)
-			return sta_id;
-
-		sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
-
-		if (sta_id != IWL_INVALID_STATION)
-			return sta_id;
-
-		IWL_DEBUG_DROP(priv, "Station %pM not in station map. "
-			       "Defaulting to broadcast...\n",
-			       hdr->addr1);
-		iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
-		return priv->hw_params.bcast_sta_id;
-	}
-	/* If we are in monitor mode, use BCAST. This is required for
-	 * packet injection. */
-	case NL80211_IFTYPE_MONITOR:
-		return priv->hw_params.bcast_sta_id;
-
-	default:
-		IWL_WARN(priv, "Unknown mode of operation: %d\n",
-			priv->iw_mode);
-		return priv->hw_params.bcast_sta_id;
-	}
-}
-
 /*
  * start REPLY_TX command process
  */
@@ -1004,7 +589,7 @@
 
 	/* drop all data frame if we are not associated */
 	if (ieee80211_is_data(fc) &&
-	    (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */
+	    (!iwl_is_monitor_mode(priv)) && /* packet injection */
 	    (!iwl_is_associated(priv) ||
 	     ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
 		IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
@@ -1016,7 +601,7 @@
 	hdr_len = ieee80211_hdrlen(fc);
 
 	/* Find (or create) index into station table for destination station */
-	sta_id = iwl3945_get_sta_id(priv, hdr);
+	sta_id = iwl_get_sta_id(priv, hdr);
 	if (sta_id == IWL_INVALID_STATION) {
 		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
 			       hdr->addr1);
@@ -1028,7 +613,7 @@
 	if (ieee80211_is_data_qos(fc)) {
 		qc = ieee80211_get_qos_ctl(hdr);
 		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-		seq_number = priv->stations_39[sta_id].tid[tid].seq_number &
+		seq_number = priv->stations[sta_id].tid[tid].seq_number &
 				IEEE80211_SCTL_SEQ;
 		hdr->seq_ctrl = cpu_to_le16(seq_number) |
 			(hdr->seq_ctrl &
@@ -1088,7 +673,7 @@
 	if (!ieee80211_has_morefrags(hdr->frame_control)) {
 		txq->need_update = 1;
 		if (qc)
-			priv->stations_39[sta_id].tid[tid].seq_number = seq_number;
+			priv->stations[sta_id].tid[tid].seq_number = seq_number;
 	} else {
 		wait_write_ptr = 1;
 		txq->need_update = 0;
@@ -1424,18 +1009,12 @@
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-	if (flags & SW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-
 	iwl_scan_cancel(priv);
 
 	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-	    (test_bit(STATUS_RF_KILL_SW, &status) !=
-	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+				test_bit(STATUS_RF_KILL_HW, &priv->status));
 	else
 		wake_up_interruptible(&priv->wait_command_queue);
 }
@@ -1591,7 +1170,7 @@
 
 	/* If we've added more space for the firmware to place data, tell it.
 	 * Increment device's write pointer in multiples of 8. */
-	if ((write != (rxq->write & ~0x7))
+	if ((rxq->write_actual != (rxq->write & ~0x7))
 	    || (abs(rxq->write - rxq->read) > 7)) {
 		spin_lock_irqsave(&rxq->lock, flags);
 		rxq->need_update = 1;
@@ -1612,21 +1191,30 @@
  * Also restock the Rx queue via iwl3945_rx_queue_restock.
  * This is called as a scheduled work item (except for during initialization)
  */
-static void iwl3945_rx_allocate(struct iwl_priv *priv)
+static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
 {
 	struct iwl_rx_queue *rxq = &priv->rxq;
 	struct list_head *element;
 	struct iwl_rx_mem_buffer *rxb;
 	unsigned long flags;
-	spin_lock_irqsave(&rxq->lock, flags);
-	while (!list_empty(&rxq->rx_used)) {
+
+	while (1) {
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			return;
+		}
+
 		element = rxq->rx_used.next;
 		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+		spin_unlock_irqrestore(&rxq->lock, flags);
 
 		/* Alloc a new receive buffer */
 		rxb->skb =
 		    alloc_skb(priv->hw_params.rx_buf_size,
-				__GFP_NOWARN | GFP_ATOMIC);
+				priority);
 		if (!rxb->skb) {
 			if (net_ratelimit())
 				IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
@@ -1644,18 +1232,18 @@
 		 */
 		skb_reserve(rxb->skb, 4);
 
-		priv->alloc_rxb_skb++;
-		list_del(element);
-
 		/* Get physical address of RB/SKB */
 		rxb->real_dma_addr = pci_map_single(priv->pci_dev,
 						rxb->skb->data,
 						priv->hw_params.rx_buf_size,
 						PCI_DMA_FROMDEVICE);
+
+		spin_lock_irqsave(&rxq->lock, flags);
 		list_add_tail(&rxb->list, &rxq->rx_free);
+		priv->alloc_rxb_skb++;
 		rxq->free_count++;
+		spin_unlock_irqrestore(&rxq->lock, flags);
 	}
-	spin_unlock_irqrestore(&rxq->lock, flags);
 }
 
 void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
@@ -1685,33 +1273,30 @@
 	 * not restocked the Rx queue with fresh buffers */
 	rxq->read = rxq->write = 0;
 	rxq->free_count = 0;
+	rxq->write_actual = 0;
 	spin_unlock_irqrestore(&rxq->lock, flags);
 }
 
-/*
- * this should be called while priv->lock is locked
- */
-static void __iwl3945_rx_replenish(void *data)
-{
-	struct iwl_priv *priv = data;
-
-	iwl3945_rx_allocate(priv);
-	iwl3945_rx_queue_restock(priv);
-}
-
-
 void iwl3945_rx_replenish(void *data)
 {
 	struct iwl_priv *priv = data;
 	unsigned long flags;
 
-	iwl3945_rx_allocate(priv);
+	iwl3945_rx_allocate(priv, GFP_KERNEL);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	iwl3945_rx_queue_restock(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+static void iwl3945_rx_replenish_now(struct iwl_priv *priv)
+{
+	iwl3945_rx_allocate(priv, GFP_ATOMIC);
+
+	iwl3945_rx_queue_restock(priv);
+}
+
+
 /* Assumes that the skb field of the buffers in 'pool' is kept accurate.
  * If an SKB has been detached, the POOL needs to have its SKB set to NULL
  * This free routine walks the list of POOL entries and if SKB is set to
@@ -1834,13 +1419,19 @@
 	unsigned long flags;
 	u8 fill_rx = 0;
 	u32 count = 8;
+	int total_empty = 0;
 
 	/* uCode's read index (stored in shared DRAM) indicates the last Rx
 	 * buffer that the driver may process (last buffer filled by ucode). */
 	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
 	i = rxq->read;
 
-	if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+	/* calculate total frames need to be restock after handling RX */
+	total_empty = r - priv->rxq.write_actual;
+	if (total_empty < 0)
+		total_empty += RX_QUEUE_SIZE;
+
+	if (total_empty > (RX_QUEUE_SIZE / 2))
 		fill_rx = 1;
 	/* Rx interrupt, but nothing sent from uCode */
 	if (i == r)
@@ -1879,6 +1470,7 @@
 				"r = %d, i = %d, %s, 0x%02x\n", r, i,
 				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
 			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
 		} else {
 			/* No handling needed */
 			IWL_DEBUG(priv, IWL_DL_HCMD | IWL_DL_RX | IWL_DL_ISR,
@@ -1916,7 +1508,7 @@
 			count++;
 			if (count >= 8) {
 				priv->rxq.read = i;
-				__iwl3945_rx_replenish(priv);
+				iwl3945_rx_replenish_now(priv);
 				count = 0;
 			}
 		}
@@ -1924,7 +1516,10 @@
 
 	/* Backtrack one entry */
 	priv->rxq.read = i;
-	iwl3945_rx_queue_restock(priv);
+	if (fill_rx)
+		iwl3945_rx_replenish_now(priv);
+	else
+		iwl3945_rx_queue_restock(priv);
 }
 
 /* call this function to flush any scheduled tasklet */
@@ -1963,7 +1558,6 @@
 	u32 i;
 	u32 desc, time, count, base, data1;
 	u32 blink1, blink2, ilink1, ilink2;
-	int rc;
 
 	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
 
@@ -1972,11 +1566,6 @@
 		return;
 	}
 
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		IWL_WARN(priv, "Can not read from adapter at this time.\n");
-		return;
-	}
 
 	count = iwl_read_targ_mem(priv, base);
 
@@ -2011,8 +1600,6 @@
 			ilink1, ilink2, data1);
 	}
 
-	iwl_release_nic_access(priv);
-
 }
 
 #define EVENT_START_OFFSET  (6 * sizeof(u32))
@@ -2020,7 +1607,6 @@
 /**
  * iwl3945_print_event_log - Dump error event log to syslog
  *
- * NOTE: Must be called with iwl_grab_nic_access() already obtained!
  */
 static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
 				u32 num_events, u32 mode)
@@ -2063,7 +1649,6 @@
 
 static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
 {
-	int rc;
 	u32 base;       /* SRAM byte address of event log header */
 	u32 capacity;   /* event log capacity in # entries */
 	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
@@ -2077,12 +1662,6 @@
 		return;
 	}
 
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		IWL_WARN(priv, "Can not read from adapter at this time.\n");
-		return;
-	}
-
 	/* event log header */
 	capacity = iwl_read_targ_mem(priv, base);
 	mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
@@ -2094,7 +1673,6 @@
 	/* bail out if nothing in log */
 	if (size == 0) {
 		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-		iwl_release_nic_access(priv);
 		return;
 	}
 
@@ -2110,24 +1688,6 @@
 	/* (then/else) start at top of log */
 	iwl3945_print_event_log(priv, 0, next_entry, mode);
 
-	iwl_release_nic_access(priv);
-}
-
-static void iwl3945_error_recovery(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
-	       sizeof(priv->staging_rxon));
-	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl3945_commit_rxon(priv);
-
-	iwl3945_add_station(priv, priv->bssid, 1, 0);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
-	priv->error_recovering = 0;
-	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static void iwl3945_irq_tasklet(struct iwl_priv *priv)
@@ -2178,6 +1738,7 @@
 		/* Tell the device to stop sending interrupts */
 		iwl_disable_interrupts(priv);
 
+		priv->isr_stats.hw++;
 		iwl_irq_handle_error(priv);
 
 		handled |= CSR_INT_BIT_HW_ERR;
@@ -2190,13 +1751,17 @@
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (priv->debug_level & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_SCD)
+		if (inta & CSR_INT_BIT_SCD) {
 			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
 				      "the frame/frames.\n");
+			priv->isr_stats.sch++;
+		}
 
 		/* Alive notification via Rx interrupt will do the real work */
-		if (inta & CSR_INT_BIT_ALIVE)
+		if (inta & CSR_INT_BIT_ALIVE) {
 			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+			priv->isr_stats.alive++;
+		}
 	}
 #endif
 	/* Safely ignore these bits for debug checks below */
@@ -2206,6 +1771,8 @@
 	if (inta & CSR_INT_BIT_SW_ERR) {
 		IWL_ERR(priv, "Microcode SW error detected. "
 			"Restarting 0x%X.\n", inta);
+		priv->isr_stats.sw++;
+		priv->isr_stats.sw_err = inta;
 		iwl_irq_handle_error(priv);
 		handled |= CSR_INT_BIT_SW_ERR;
 	}
@@ -2221,6 +1788,7 @@
 		iwl_txq_update_write_ptr(priv, &priv->txq[4]);
 		iwl_txq_update_write_ptr(priv, &priv->txq[5]);
 
+		priv->isr_stats.wakeup++;
 		handled |= CSR_INT_BIT_WAKEUP;
 	}
 
@@ -2229,27 +1797,28 @@
 	 * notifications from uCode come through here*/
 	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
 		iwl3945_rx_handle(priv);
+		priv->isr_stats.rx++;
 		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
 	}
 
 	if (inta & CSR_INT_BIT_FH_TX) {
 		IWL_DEBUG_ISR(priv, "Tx interrupt\n");
+		priv->isr_stats.tx++;
 
 		iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
-		if (!iwl_grab_nic_access(priv)) {
-			iwl_write_direct32(priv, FH39_TCSR_CREDIT
-					     (FH39_SRVC_CHNL), 0x0);
-			iwl_release_nic_access(priv);
-		}
+		iwl_write_direct32(priv, FH39_TCSR_CREDIT
+					(FH39_SRVC_CHNL), 0x0);
 		handled |= CSR_INT_BIT_FH_TX;
 	}
 
-	if (inta & ~handled)
+	if (inta & ~handled) {
 		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+		priv->isr_stats.unhandled++;
+	}
 
-	if (inta & ~CSR_INI_SET_MASK) {
+	if (inta & ~priv->inta_mask) {
 		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-			 inta & ~CSR_INI_SET_MASK);
+			 inta & ~priv->inta_mask);
 		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
 	}
 
@@ -2413,10 +1982,6 @@
 
 	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 
-	rc = iwl_grab_nic_access(priv);
-	if (rc)
-		return rc;
-
 	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
 			       IWL39_RTC_INST_LOWER_BOUND);
 
@@ -2437,7 +2002,6 @@
 		}
 	}
 
-	iwl_release_nic_access(priv);
 
 	if (!errcnt)
 		IWL_DEBUG_INFO(priv,
@@ -2461,10 +2025,6 @@
 
 	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 
-	rc = iwl_grab_nic_access(priv);
-	if (rc)
-		return rc;
-
 	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
 		/* read data comes through single port, auto-incr addr */
 		/* NOTE: Use the debugless read so we don't flood kernel log
@@ -2485,8 +2045,6 @@
 		}
 	}
 
-	iwl_release_nic_access(priv);
-
 	return rc;
 }
 
@@ -2810,20 +2368,11 @@
 {
 	dma_addr_t pinst;
 	dma_addr_t pdata;
-	int rc = 0;
-	unsigned long flags;
 
 	/* bits 31:0 for 3945 */
 	pinst = priv->ucode_code.p_addr;
 	pdata = priv->ucode_data_backup.p_addr;
 
-	spin_lock_irqsave(&priv->lock, flags);
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return rc;
-	}
-
 	/* Tell bootstrap uCode where to find image to load */
 	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
 	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
@@ -2835,13 +2384,9 @@
 	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
 				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
 
-	iwl_release_nic_access(priv);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
 
-	return rc;
+	return 0;
 }
 
 /**
@@ -2887,11 +2432,6 @@
 	queue_work(priv->workqueue, &priv->restart);
 }
 
-
-/* temporary */
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
-				     struct sk_buff *skb);
-
 /**
  * iwl3945_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
@@ -2899,7 +2439,6 @@
  */
 static void iwl3945_alive_start(struct iwl_priv *priv)
 {
-	int rc = 0;
 	int thermal_spin = 0;
 	u32 rfkill;
 
@@ -2922,17 +2461,10 @@
 		goto restart;
 	}
 
-	iwl3945_clear_stations_table(priv);
-
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		IWL_WARN(priv, "Can not read RFKILL status from adapter\n");
-		return;
-	}
+	iwl_clear_stations_table(priv);
 
 	rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
 	IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
-	iwl_release_nic_access(priv);
 
 	if (rfkill & 0x1) {
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -2952,9 +2484,6 @@
 	/* After the ALIVE response, we can send commands to 3945 uCode */
 	set_bit(STATUS_ALIVE, &priv->status);
 
-	/* Clear out the uCode error bit if it is set */
-	clear_bit(STATUS_FW_ERROR, &priv->status);
-
 	if (iwl_is_rfkill(priv))
 		return;
 
@@ -2969,8 +2498,7 @@
 		struct iwl3945_rxon_cmd *active_rxon =
 				(struct iwl3945_rxon_cmd *)(&priv->active_rxon);
 
-		memcpy(&priv->staging_rxon, &priv->active_rxon,
-		       sizeof(priv->staging_rxon));
+		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
 		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 	} else {
 		/* Initialize our rx_config data */
@@ -2981,7 +2509,7 @@
 	iwl_send_bt_config(priv);
 
 	/* Configure the adapter for unassociated operation */
-	iwl3945_commit_rxon(priv);
+	iwlcore_commit_rxon(priv);
 
 	iwl3945_reg_txpower_periodic(priv);
 
@@ -2991,17 +2519,17 @@
 	set_bit(STATUS_READY, &priv->status);
 	wake_up_interruptible(&priv->wait_command_queue);
 
-	if (priv->error_recovering)
-		iwl3945_error_recovery(priv);
-
 	/* reassociate for ADHOC mode */
 	if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
 		struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
 								priv->vif);
 		if (beacon)
-			iwl3945_mac_beacon_update(priv->hw, beacon);
+			iwl_mac_beacon_update(priv->hw, beacon);
 	}
 
+	if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
+		iwl_set_mode(priv, priv->iw_mode);
+
 	return;
 
  restart:
@@ -3024,7 +2552,7 @@
 		set_bit(STATUS_EXIT_PENDING, &priv->status);
 
 	iwl3945_led_unregister(priv);
-	iwl3945_clear_stations_table(priv);
+	iwl_clear_stations_table(priv);
 
 	/* Unblock any waiting calls */
 	wake_up_interruptible_all(&priv->wait_command_queue);
@@ -3047,31 +2575,23 @@
 		ieee80211_stop_queues(priv->hw);
 
 	/* If we have not previously called iwl3945_init() then
-	 * clear all bits but the RF Kill and SUSPEND bits and return */
+	 * clear all bits but the RF Kill bits and return */
 	if (!iwl_is_init(priv)) {
 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 					STATUS_RF_KILL_HW |
-			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-					STATUS_RF_KILL_SW |
 			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 					STATUS_GEO_CONFIGURED |
-			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-					STATUS_IN_SUSPEND |
 				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
 					STATUS_EXIT_PENDING;
 		goto exit;
 	}
 
-	/* ...otherwise clear out all the status bits but the RF Kill and
-	 * SUSPEND bits and continue taking the NIC down. */
+	/* ...otherwise clear out all the status bits but the RF Kill
+	 * bit and continue taking the NIC down. */
 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 				STATUS_RF_KILL_HW |
-			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-				STATUS_RF_KILL_SW |
 			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 				STATUS_GEO_CONFIGURED |
-			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-				STATUS_IN_SUSPEND |
 			test_bit(STATUS_FW_ERROR, &priv->status) <<
 				STATUS_FW_ERROR |
 			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -3085,17 +2605,12 @@
 	iwl3945_hw_txq_ctx_stop(priv);
 	iwl3945_hw_rxq_stop(priv);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	if (!iwl_grab_nic_access(priv)) {
-		iwl_write_prph(priv, APMG_CLK_DIS_REG,
-					 APMG_CLK_VAL_DMA_CLK_RQT);
-		iwl_release_nic_access(priv);
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
+	iwl_write_prph(priv, APMG_CLK_DIS_REG,
+				APMG_CLK_VAL_DMA_CLK_RQT);
 
 	udelay(5);
 
-	if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+	if (exit_pending)
 		priv->cfg->ops->lib->apm_ops.stop(priv);
 	else
 		priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -3131,12 +2646,6 @@
 		return -EIO;
 	}
 
-	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-		IWL_WARN(priv, "Radio disabled by SW RF kill (module "
-			    "parameter)\n");
-		return -ENODEV;
-	}
-
 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
 		IWL_ERR(priv, "ucode not available for device bring up\n");
 		return -EIO;
@@ -3148,10 +2657,8 @@
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 	else {
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
-		if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
-			IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-			return -ENODEV;
-		}
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+		return -ENODEV;
 	}
 
 	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
@@ -3187,7 +2694,7 @@
 
 	for (i = 0; i < MAX_HW_RESTARTS; i++) {
 
-		iwl3945_clear_stations_table(priv);
+		iwl_clear_stations_table(priv);
 
 		/* load bootstrap state machine,
 		 * load bootstrap program into processor's memory,
@@ -3255,15 +2762,14 @@
 {
 	struct iwl_priv *priv =
 	    container_of(data, struct iwl_priv, rfkill_poll.work);
-	unsigned long status = priv->status;
 
 	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 	else
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-	if (test_bit(STATUS_RF_KILL_HW, &status) != test_bit(STATUS_RF_KILL_HW, &priv->status))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
 
 	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
 			   round_jiffies_relative(2 * HZ));
@@ -3283,9 +2789,9 @@
 	int rc = 0;
 	struct iwl3945_scan_cmd *scan;
 	struct ieee80211_conf *conf = NULL;
-	u8 n_probes = 2;
+	u8 n_probes = 0;
 	enum ieee80211_band band;
-	DECLARE_SSID_BUF(ssid);
+	bool is_active = false;
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -3386,18 +2892,25 @@
 			       scan_suspend_time, interval);
 	}
 
-	/* We should add the ability for user to lock to PASSIVE ONLY */
-	if (priv->one_direct_scan) {
-		IWL_DEBUG_SCAN(priv, "Kicking off one direct scan for '%s'\n",
-				print_ssid(ssid, priv->direct_ssid,
-				priv->direct_ssid_len));
-		scan->direct_scan[0].id = WLAN_EID_SSID;
-		scan->direct_scan[0].len = priv->direct_ssid_len;
-		memcpy(scan->direct_scan[0].ssid,
-		       priv->direct_ssid, priv->direct_ssid_len);
-		n_probes++;
+	if (priv->scan_request->n_ssids) {
+		int i, p = 0;
+		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+		for (i = 0; i < priv->scan_request->n_ssids; i++) {
+			/* always does wildcard anyway */
+			if (!priv->scan_request->ssids[i].ssid_len)
+				continue;
+			scan->direct_scan[p].id = WLAN_EID_SSID;
+			scan->direct_scan[p].len =
+				priv->scan_request->ssids[i].ssid_len;
+			memcpy(scan->direct_scan[p].ssid,
+			       priv->scan_request->ssids[i].ssid,
+			       priv->scan_request->ssids[i].ssid_len);
+			n_probes++;
+			p++;
+		}
+		is_active = true;
 	} else
-		IWL_DEBUG_SCAN(priv, "Kicking off one indirect scan.\n");
+		IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n");
 
 	/* We don't build a direct scan probe request; the uCode will do
 	 * that based on the direct_mask added to each channel entry */
@@ -3414,7 +2927,12 @@
 		band = IEEE80211_BAND_2GHZ;
 	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
 		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-		scan->good_CRC_th = IWL_GOOD_CRC_TH;
+		/*
+		 * If active scaning is requested but a certain channel
+		 * is marked passive, we can do active scanning if we
+		 * detect transmissions.
+		 */
+		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
 		band = IEEE80211_BAND_5GHZ;
 	} else {
 		IWL_WARN(priv, "Invalid scan band count\n");
@@ -3422,19 +2940,20 @@
 	}
 
 	scan->tx_cmd.len = cpu_to_le16(
-		iwl_fill_probe_req(priv, band,
-				   (struct ieee80211_mgmt *)scan->data,
-				   IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+			iwl_fill_probe_req(priv,
+				(struct ieee80211_mgmt *)scan->data,
+				priv->scan_request->ie,
+				priv->scan_request->ie_len,
+				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
 
 	/* select Rx antennas */
 	scan->flags |= iwl3945_get_antenna_flags(priv);
 
-	if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
+	if (iwl_is_monitor_mode(priv))
 		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
 	scan->channel_count =
-		iwl3945_get_channels_for_scan(priv, band, 1, /* active */
-					      n_probes,
+		iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
 			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
 	if (scan->channel_count == 0) {
@@ -3482,7 +3001,6 @@
 	mutex_lock(&priv->mutex);
 	__iwl3945_up(priv);
 	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl3945_bg_restart(struct work_struct *data)
@@ -3492,8 +3010,17 @@
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	iwl3945_down(priv);
-	queue_work(priv->workqueue, &priv->up);
+	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		mutex_lock(&priv->mutex);
+		priv->vif = NULL;
+		priv->is_open = 0;
+		mutex_unlock(&priv->mutex);
+		iwl3945_down(priv);
+		ieee80211_restart_hw(priv->hw);
+	} else {
+		iwl3945_down(priv);
+		queue_work(priv->workqueue, &priv->up);
+	}
 }
 
 static void iwl3945_bg_rx_replenish(struct work_struct *data)
@@ -3511,7 +3038,7 @@
 
 #define IWL_DELAY_NEXT_SCAN (HZ*2)
 
-static void iwl3945_post_associate(struct iwl_priv *priv)
+void iwl3945_post_associate(struct iwl_priv *priv)
 {
 	int rc = 0;
 	struct ieee80211_conf *conf = NULL;
@@ -3536,7 +3063,7 @@
 	conf = ieee80211_get_hw_conf(priv->hw);
 
 	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl3945_commit_rxon(priv);
+	iwlcore_commit_rxon(priv);
 
 	memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
 	iwl3945_setup_rxon_timing(priv);
@@ -3569,7 +3096,7 @@
 
 	}
 
-	iwl3945_commit_rxon(priv);
+	iwlcore_commit_rxon(priv);
 
 	switch (priv->iw_mode) {
 	case NL80211_IFTYPE_STATION:
@@ -3579,7 +3106,7 @@
 	case NL80211_IFTYPE_ADHOC:
 
 		priv->assoc_id = 1;
-		iwl3945_add_station(priv, priv->bssid, 0, 0);
+		iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL);
 		iwl3945_sync_sta(priv, IWL_STA_ID,
 				 (priv->band == IEEE80211_BAND_5GHZ) ?
 				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
@@ -3601,8 +3128,6 @@
 	priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
-static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
-
 /*****************************************************************************
  *
  * mac80211 entry point functions
@@ -3621,7 +3146,6 @@
 	/* we should be verifying the device is ready to be opened */
 	mutex_lock(&priv->mutex);
 
-	memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
 	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
 	 * ucode filename and max sizes are card-specific. */
 
@@ -3638,16 +3162,11 @@
 
 	mutex_unlock(&priv->mutex);
 
-	iwl_rfkill_set_hw_state(priv);
-
 	if (ret)
 		goto out_release_irq;
 
 	IWL_DEBUG_INFO(priv, "Start UP work.\n");
 
-	if (test_bit(STATUS_IN_SUSPEND, &priv->status))
-		return 0;
-
 	/* Wait for START_ALIVE from ucode. Otherwise callbacks from
 	 * mac80211 will not be run successfully. */
 	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -3726,144 +3245,7 @@
 	return NETDEV_TX_OK;
 }
 
-static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
-				 struct ieee80211_if_init_conf *conf)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-
-	IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
-
-	if (priv->vif) {
-		IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
-		return -EOPNOTSUPP;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->vif = conf->vif;
-	priv->iw_mode = conf->type;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	mutex_lock(&priv->mutex);
-
-	if (conf->mac_addr) {
-		IWL_DEBUG_MAC80211(priv, "Set: %pM\n", conf->mac_addr);
-		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
-	}
-
-	if (iwl_is_ready(priv))
-		iwl3945_set_mode(priv, conf->type);
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return 0;
-}
-
-/**
- * iwl3945_mac_config - mac80211 config callback
- *
- * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
- * be set inappropriately and the driver currently sets the hardware up to
- * use it whenever needed.
- */
-static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct iwl_priv *priv = hw->priv;
-	const struct iwl_channel_info *ch_info;
-	struct ieee80211_conf *conf = &hw->conf;
-	unsigned long flags;
-	int ret = 0;
-
-	mutex_lock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "enter to channel %d\n",
-				conf->channel->hw_value);
-
-	if (!iwl_is_ready(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	if (unlikely(!iwl3945_mod_params.disable_hw_scan &&
-		     test_bit(STATUS_SCANNING, &priv->status))) {
-		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
-		set_bit(STATUS_CONF_PENDING, &priv->status);
-		mutex_unlock(&priv->mutex);
-		return 0;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	ch_info = iwl_get_channel_info(priv, conf->channel->band,
-				       conf->channel->hw_value);
-	if (!is_channel_valid(ch_info)) {
-		IWL_DEBUG_SCAN(priv,
-				"Channel %d [%d] is INVALID for this band.\n",
-				conf->channel->hw_value, conf->channel->band);
-		IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-		spin_unlock_irqrestore(&priv->lock, flags);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	iwl_set_rxon_channel(priv, conf->channel);
-
-	iwl_set_flags_for_band(priv, conf->channel->band);
-
-	/* The list of supported rates and rate mask can be different
-	 * for each phymode; since the phymode may have changed, reset
-	 * the rate mask to what mac80211 lists */
-	iwl_set_rate(priv);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-#ifdef IEEE80211_CONF_CHANNEL_SWITCH
-	if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
-		iwl3945_hw_channel_switch(priv, conf->channel);
-		goto out;
-	}
-#endif
-
-	if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
-		if (conf->radio_enabled &&
-		    iwl_radio_kill_sw_enable_radio(priv)) {
-			IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - "
-						 "waiting for uCode\n");
-			goto out;
-		}
-
-		if (!conf->radio_enabled) {
-			iwl_radio_kill_sw_disable_radio(priv);
-			IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
-			goto out;
-		}
-	}
-
-	if (iwl_is_rfkill(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF kill\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	iwl_set_rate(priv);
-
-	if (memcmp(&priv->active_rxon,
-		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
-		iwl3945_commit_rxon(priv);
-	else
-		IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration\n");
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-out:
-	clear_bit(STATUS_CONF_PENDING, &priv->status);
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-
-static void iwl3945_config_ap(struct iwl_priv *priv)
+void iwl3945_config_ap(struct iwl_priv *priv)
 {
 	int rc = 0;
 
@@ -3875,7 +3257,7 @@
 
 		/* RXON - unassoc (to set timing command) */
 		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv);
+		iwlcore_commit_rxon(priv);
 
 		/* RXON Timing */
 		memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
@@ -3911,8 +3293,8 @@
 		}
 		/* restore RXON assoc */
 		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv);
-		iwl3945_add_station(priv, iwl_bcast_addr, 0, 0);
+		iwlcore_commit_rxon(priv);
+		iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL);
 	}
 	iwl3945_send_beacon_cmd(priv);
 
@@ -3921,189 +3303,6 @@
 	 * clear sta table, add BCAST sta... */
 }
 
-static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
-					struct ieee80211_vif *vif,
-					struct ieee80211_if_conf *conf)
-{
-	struct iwl_priv *priv = hw->priv;
-	int rc;
-
-	if (conf == NULL)
-		return -EIO;
-
-	if (priv->vif != vif) {
-		IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n");
-		return 0;
-	}
-
-	/* handle this temporarily here */
-	if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-	    conf->changed & IEEE80211_IFCC_BEACON) {
-		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-		if (!beacon)
-			return -ENOMEM;
-		mutex_lock(&priv->mutex);
-		rc = iwl3945_mac_beacon_update(hw, beacon);
-		mutex_unlock(&priv->mutex);
-		if (rc)
-			return rc;
-	}
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	mutex_lock(&priv->mutex);
-
-	if (conf->bssid)
-		IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid);
-
-/*
- * very dubious code was here; the probe filtering flag is never set:
- *
-	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
-	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
- */
-
-	if (priv->iw_mode == NL80211_IFTYPE_AP) {
-		if (!conf->bssid) {
-			conf->bssid = priv->mac_addr;
-			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-			IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n",
-					   conf->bssid);
-		}
-		if (priv->ibss_beacon)
-			dev_kfree_skb(priv->ibss_beacon);
-
-		priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
-	}
-
-	if (iwl_is_rfkill(priv))
-		goto done;
-
-	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
-	    !is_multicast_ether_addr(conf->bssid)) {
-		/* If there is currently a HW scan going on in the background
-		 * then we need to cancel it else the RXON below will fail. */
-		if (iwl_scan_cancel_timeout(priv, 100)) {
-			IWL_WARN(priv, "Aborted scan still in progress "
-				    "after 100ms\n");
-			IWL_DEBUG_MAC80211(priv, "leaving:scan abort failed\n");
-			mutex_unlock(&priv->mutex);
-			return -EAGAIN;
-		}
-		memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
-
-		/* TODO: Audit driver for usage of these members and see
-		 * if mac80211 deprecates them (priv->bssid looks like it
-		 * shouldn't be there, but I haven't scanned the IBSS code
-		 * to verify) - jpk */
-		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-
-		if (priv->iw_mode == NL80211_IFTYPE_AP)
-			iwl3945_config_ap(priv);
-		else {
-			rc = iwl3945_commit_rxon(priv);
-			if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
-				iwl3945_add_station(priv,
-					priv->active_rxon.bssid_addr, 1, 0);
-		}
-
-	} else {
-		iwl_scan_cancel_timeout(priv, 100);
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv);
-	}
-
- done:
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-
-static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
-				     struct ieee80211_if_init_conf *conf)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	mutex_lock(&priv->mutex);
-
-	if (iwl_is_ready_rf(priv)) {
-		iwl_scan_cancel_timeout(priv, 100);
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv);
-	}
-	if (priv->vif == conf->vif) {
-		priv->vif = NULL;
-		memset(priv->bssid, 0, ETH_ALEN);
-	}
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-
-static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-				   bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			priv->staging_rxon.flags &=
-				~RXON_FLG_SHORT_PREAMBLE_MSK;
-	}
-
-	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n",
-				   bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
-		else
-			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-	}
-
-	if (changes & BSS_CHANGED_ASSOC) {
-		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-		/* This should never happen as this function should
-		 * never be called from interrupt context. */
-		if (WARN_ON_ONCE(in_interrupt()))
-			return;
-		if (bss_conf->assoc) {
-			priv->assoc_id = bss_conf->aid;
-			priv->beacon_int = bss_conf->beacon_int;
-			priv->timestamp = bss_conf->timestamp;
-			priv->assoc_capability = bss_conf->assoc_capability;
-			priv->power_data.dtim_period = bss_conf->dtim_period;
-			priv->next_scan_jiffies = jiffies +
-					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
-			mutex_lock(&priv->mutex);
-			iwl3945_post_associate(priv);
-			mutex_unlock(&priv->mutex);
-		} else {
-			priv->assoc_id = 0;
-			IWL_DEBUG_MAC80211(priv,
-					"DISASSOC %d\n", bss_conf->assoc);
-		}
-	} else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
-			IWL_DEBUG_MAC80211(priv,
-					"Associated Changes %d\n", changes);
-			iwl3945_send_rxon_assoc(priv);
-	}
-
-}
-
 static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			       struct ieee80211_vif *vif,
 			       struct ieee80211_sta *sta,
@@ -4126,7 +3325,7 @@
 	static_key = !iwl_is_associated(priv);
 
 	if (!static_key) {
-		sta_id = iwl3945_hw_find_station(priv, addr);
+		sta_id = iwl_find_station(priv, addr);
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
 					    addr);
@@ -4162,185 +3361,6 @@
 	return ret;
 }
 
-static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			   const struct ieee80211_tx_queue_params *params)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	int q;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return -EIO;
-	}
-
-	if (queue >= AC_NUM) {
-		IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
-		return 0;
-	}
-
-	q = AC_NUM - 1 - queue;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
-	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
-	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
-	priv->qos_data.def_qos_parm.ac[q].edca_txop =
-			cpu_to_le16((params->txop * 32));
-
-	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
-	priv->qos_data.qos_active = 1;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	mutex_lock(&priv->mutex);
-	if (priv->iw_mode == NL80211_IFTYPE_AP)
-		iwl_activate_qos(priv, 1);
-	else if (priv->assoc_id && iwl_is_associated(priv))
-		iwl_activate_qos(priv, 0);
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return 0;
-}
-
-static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
-				struct ieee80211_tx_queue_stats *stats)
-{
-	struct iwl_priv *priv = hw->priv;
-	int i, avail;
-	struct iwl_tx_queue *txq;
-	struct iwl_queue *q;
-	unsigned long flags;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	for (i = 0; i < AC_NUM; i++) {
-		txq = &priv->txq[i];
-		q = &txq->q;
-		avail = iwl_queue_space(q);
-
-		stats[i].len = q->n_window - avail;
-		stats[i].limit = q->n_window - q->high_mark;
-		stats[i].count = q->n_window;
-
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return 0;
-}
-
-static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-
-	mutex_lock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	iwl_reset_qos(priv);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->assoc_id = 0;
-	priv->assoc_capability = 0;
-
-	/* new association get rid of ibss beacon skb */
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-
-	priv->ibss_beacon = NULL;
-
-	priv->beacon_int = priv->hw->conf.beacon_int;
-	priv->timestamp = 0;
-	if ((priv->iw_mode == NL80211_IFTYPE_STATION))
-		priv->beacon_int = 0;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		mutex_unlock(&priv->mutex);
-		return;
-	}
-
-	/* we are restarting association process
-	 * clear RXON_FILTER_ASSOC_MSK bit
-	*/
-	if (priv->iw_mode != NL80211_IFTYPE_AP) {
-		iwl_scan_cancel_timeout(priv, 100);
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv);
-	}
-
-	/* Per mac80211.h: This is only used in IBSS mode... */
-	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-
-		IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
-		mutex_unlock(&priv->mutex);
-		return;
-	}
-
-	iwl_set_rate(priv);
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-}
-
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	__le64 timestamp;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return -EIO;
-	}
-
-	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-		IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-
-	priv->ibss_beacon = skb;
-
-	priv->assoc_id = 0;
-	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-	priv->timestamp = le64_to_cpu(timestamp);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_reset_qos(priv);
-
-	iwl3945_post_associate(priv);
-
-
-	return 0;
-}
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -4359,7 +3379,7 @@
 static ssize_t show_debug_level(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	return sprintf(buf, "0x%08X\n", priv->debug_level);
 }
@@ -4367,7 +3387,7 @@
 				struct device_attribute *attr,
 				 const char *buf, size_t count)
 {
-	struct iwl_priv *priv = d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	unsigned long val;
 	int ret;
 
@@ -4388,7 +3408,7 @@
 static ssize_t show_temperature(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	if (!iwl_is_alive(priv))
 		return -EAGAIN;
@@ -4401,7 +3421,7 @@
 static ssize_t show_tx_power(struct device *d,
 			     struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
 }
 
@@ -4409,7 +3429,7 @@
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	char *p = (char *)buf;
 	u32 val;
 
@@ -4427,7 +3447,7 @@
 static ssize_t show_flags(struct device *d,
 			  struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
 }
@@ -4436,7 +3456,7 @@
 			   struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	u32 flags = simple_strtoul(buf, NULL, 0);
 
 	mutex_lock(&priv->mutex);
@@ -4448,7 +3468,7 @@
 			IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
 				       flags);
 			priv->staging_rxon.flags = cpu_to_le32(flags);
-			iwl3945_commit_rxon(priv);
+			iwlcore_commit_rxon(priv);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -4461,7 +3481,7 @@
 static ssize_t show_filter_flags(struct device *d,
 				 struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	return sprintf(buf, "0x%04X\n",
 		le32_to_cpu(priv->active_rxon.filter_flags));
@@ -4471,7 +3491,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	u32 filter_flags = simple_strtoul(buf, NULL, 0);
 
 	mutex_lock(&priv->mutex);
@@ -4484,7 +3504,7 @@
 				       "0x%04X\n", filter_flags);
 			priv->staging_rxon.filter_flags =
 				cpu_to_le32(filter_flags);
-			iwl3945_commit_rxon(priv);
+			iwlcore_commit_rxon(priv);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -4623,27 +3643,10 @@
 				struct device_attribute *attr, char *buf)
 {
 	struct iwl_priv *priv = dev_get_drvdata(d);
-	int mode = priv->power_data.user_power_setting;
-	int system = priv->power_data.system_power_setting;
 	int level = priv->power_data.power_mode;
 	char *p = buf;
 
-	switch (system) {
-	case IWL_POWER_SYS_AUTO:
-		p += sprintf(p, "SYSTEM:auto");
-		break;
-	case IWL_POWER_SYS_AC:
-		p += sprintf(p, "SYSTEM:ac");
-		break;
-	case IWL_POWER_SYS_BATTERY:
-		p += sprintf(p, "SYSTEM:battery");
-		break;
-	}
-
-	p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
-			"fixed" : "auto");
-	p += sprintf(p, "\tINDEX:%d", level);
-	p += sprintf(p, "\n");
+	p += sprintf(p, "%d\n", level);
 	return p - buf + 1;
 }
 
@@ -4756,7 +3759,7 @@
 static ssize_t show_status(struct device *d,
 			   struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	if (!iwl_is_alive(priv))
 		return -EAGAIN;
 	return sprintf(buf, "0x%08x\n", (int)priv->status);
@@ -4768,10 +3771,11 @@
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	char *p = (char *)buf;
 
 	if (p[0] == '1')
-		iwl3945_dump_nic_error_log((struct iwl_priv *)d->driver_data);
+		iwl3945_dump_nic_error_log(priv);
 
 	return strnlen(buf, count);
 }
@@ -4782,10 +3786,11 @@
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	char *p = (char *)buf;
 
 	if (p[0] == '1')
-		iwl3945_dump_nic_event_log((struct iwl_priv *)d->driver_data);
+		iwl3945_dump_nic_event_log(priv);
 
 	return strnlen(buf, count);
 }
@@ -4807,7 +3812,6 @@
 	INIT_WORK(&priv->up, iwl3945_bg_up);
 	INIT_WORK(&priv->restart, iwl3945_bg_restart);
 	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
 	INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
@@ -4864,16 +3868,15 @@
 	.tx = iwl3945_mac_tx,
 	.start = iwl3945_mac_start,
 	.stop = iwl3945_mac_stop,
-	.add_interface = iwl3945_mac_add_interface,
-	.remove_interface = iwl3945_mac_remove_interface,
-	.config = iwl3945_mac_config,
-	.config_interface = iwl3945_mac_config_interface,
+	.add_interface = iwl_mac_add_interface,
+	.remove_interface = iwl_mac_remove_interface,
+	.config = iwl_mac_config,
 	.configure_filter = iwl_configure_filter,
 	.set_key = iwl3945_mac_set_key,
-	.get_tx_stats = iwl3945_mac_get_tx_stats,
-	.conf_tx = iwl3945_mac_conf_tx,
-	.reset_tsf = iwl3945_mac_reset_tsf,
-	.bss_info_changed = iwl3945_bss_info_changed,
+	.get_tx_stats = iwl_mac_get_tx_stats,
+	.conf_tx = iwl_mac_conf_tx,
+	.reset_tsf = iwl_mac_reset_tsf,
+	.bss_info_changed = iwl_bss_info_changed,
 	.hw_scan = iwl_mac_hw_scan
 };
 
@@ -4886,7 +3889,6 @@
 	priv->ibss_beacon = NULL;
 
 	spin_lock_init(&priv->lock);
-	spin_lock_init(&priv->power_data.lock);
 	spin_lock_init(&priv->sta_lock);
 	spin_lock_init(&priv->hcmd_lock);
 
@@ -4895,7 +3897,7 @@
 	mutex_init(&priv->mutex);
 
 	/* Clear the driver's (not device's) station table */
-	iwl3945_clear_stations_table(priv);
+	iwl_clear_stations_table(priv);
 
 	priv->data_retry_limit = -1;
 	priv->ieee_channels = NULL;
@@ -4966,13 +3968,16 @@
 
 	hw->wiphy->custom_regulatory = true;
 
-	hw->wiphy->max_scan_ssids = 1; /* WILL FIX */
+	/* Firmware does not support this */
+	hw->wiphy->disable_beacon_hints = true;
+
+	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
+	/* we create the 802.11 header and a zero-length SSID element */
+	hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
 
 	/* Default value; 4 EDCA QOS priorities */
 	hw->queues = 4;
 
-	hw->conf.beacon_int = 100;
-
 	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
 		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 			&priv->bands[IEEE80211_BAND_2GHZ];
@@ -5016,10 +4021,10 @@
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 
 	if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) ||
-	     (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) {
+	     (iwl3945_mod_params.num_of_queues < IWL39_MIN_NUM_QUEUES)) {
 		IWL_ERR(priv,
 			"invalid queues_num, should be between %d and %d\n",
-			IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
+			IWL39_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
 		err = -EINVAL;
 		goto out_ieee80211_free_hw;
 	}
@@ -5037,6 +4042,7 @@
 	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
 	priv->cfg = cfg;
 	priv->pci_dev = pdev;
+	priv->inta_mask = CSR_INI_SET_MASK;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	priv->debug_level = iwl3945_mod_params.debug;
@@ -5083,6 +4089,11 @@
 	 * PCI Tx retries from interfering with C3 CPU state */
 	pci_write_config_byte(pdev, 0x41, 0x00);
 
+	/* this spin lock will be used in apm_ops.init and EEPROM access
+	 * we should init now
+	 */
+	spin_lock_init(&priv->reg_lock);
+
 	/* amp init */
 	err = priv->cfg->ops->lib->apm_ops.init(priv);
 	if (err < 0) {
@@ -5128,20 +4139,8 @@
 	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
 		priv->cfg->name);
 
-	/***********************************
-	 * 7. Initialize Module Parameters
-	 * **********************************/
-
-	/* Initialize module parameter values here */
-	/* Disable radio (SW RF KILL) via parameter when loading driver */
-	if (iwl3945_mod_params.disable) {
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-		IWL_DEBUG_INFO(priv, "Radio disabled.\n");
-	}
-
-
 	/***********************
-	 * 8. Setup Services
+	 * 7. Setup Services
 	 * ********************/
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -5150,8 +4149,8 @@
 
 	pci_enable_msi(priv->pci_dev);
 
-	err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
-			  DRV_NAME, priv);
+	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+			  IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
 		goto out_disable_msi;
@@ -5169,7 +4168,7 @@
 	iwl3945_setup_rx_handlers(priv);
 
 	/*********************************
-	 * 9. Setup and Register mac80211
+	 * 8. Setup and Register mac80211
 	 * *******************************/
 
 	iwl_enable_interrupts(priv);
@@ -5178,12 +4177,9 @@
 	if (err)
 		goto  out_remove_sysfs;
 
-	err = iwl_rfkill_init(priv);
+	err = iwl_dbgfs_register(priv, DRV_NAME);
 	if (err)
-		IWL_ERR(priv, "Unable to initialize RFKILL system. "
-				  "Ignoring error: %d\n", err);
-	else
-		iwl_rfkill_set_hw_state(priv);
+		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
 	/* Start monitoring the killswitch */
 	queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
@@ -5228,6 +4224,8 @@
 
 	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
+	iwl_dbgfs_unregister(priv);
+
 	set_bit(STATUS_EXIT_PENDING, &priv->status);
 
 	if (priv->mac80211_registered) {
@@ -5248,7 +4246,6 @@
 
 	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
-	iwl_rfkill_unregister(priv);
 	cancel_delayed_work_sync(&priv->rfkill_poll);
 
 	iwl3945_dealloc_ucode_pci(priv);
@@ -5258,7 +4255,7 @@
 	iwl3945_hw_txq_ctx_free(priv);
 
 	iwl3945_unset_hw_params(priv);
-	iwl3945_clear_stations_table(priv);
+	iwl_clear_stations_table(priv);
 
 	/*netif_stop_queue(dev); */
 	flush_workqueue(priv->workqueue);
@@ -5286,43 +4283,6 @@
 	ieee80211_free_hw(priv->hw);
 }
 
-#ifdef CONFIG_PM
-
-static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
-
-	if (priv->is_open) {
-		set_bit(STATUS_IN_SUSPEND, &priv->status);
-		iwl3945_mac_stop(priv->hw);
-		priv->is_open = 1;
-	}
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int iwl3945_pci_resume(struct pci_dev *pdev)
-{
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
-	int ret;
-
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-	pci_restore_state(pdev);
-
-	if (priv->is_open)
-		iwl3945_mac_start(priv->hw);
-
-	clear_bit(STATUS_IN_SUSPEND, &priv->status);
-	return 0;
-}
-
-#endif /* CONFIG_PM */
 
 /*****************************************************************************
  *
@@ -5336,8 +4296,8 @@
 	.probe = iwl3945_pci_probe,
 	.remove = __devexit_p(iwl3945_pci_remove),
 #ifdef CONFIG_PM
-	.suspend = iwl3945_pci_suspend,
-	.resume = iwl3945_pci_resume,
+	.suspend = iwl_pci_suspend,
+	.resume = iwl_pci_resume,
 #endif
 };
 
@@ -5378,8 +4338,6 @@
 
 module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl3945_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
 MODULE_PARM_DESC(swcrypto,
 		 "using software crypto (default 1 [software])\n");
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c	2009-09-09 18:13:59.000000000 -0400
@@ -98,7 +98,6 @@
  *   ... and set IWL_EVT_DISABLE to 1. */
 void iwl3945_disable_events(struct iwl_priv *priv)
 {
-	int ret;
 	int i;
 	u32 base;		/* SRAM address of event log header */
 	u32 disable_ptr;	/* SRAM address of event-disable bitmap array */
@@ -159,26 +158,17 @@
 		return;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		IWL_WARN(priv, "Can not read from adapter at this time.\n");
-		return;
-	}
-
 	disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32)));
 	array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32)));
-	iwl_release_nic_access(priv);
 
 	if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) {
 		IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n",
 			       disable_ptr);
-		ret = iwl_grab_nic_access(priv);
 		for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
 			iwl_write_targ_mem(priv,
 					   disable_ptr + (i * sizeof(u32)),
 					   evt_disable[i]);
 
-		iwl_release_nic_access(priv);
 	} else {
 		IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n");
 		IWL_DEBUG_INFO(priv, "  by writing \"1\"s into disable bitmap\n");
@@ -779,35 +769,6 @@
 	return ;
 }
 
-u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr)
-{
-	int i, start = IWL_AP_ID;
-	int ret = IWL_INVALID_STATION;
-	unsigned long flags;
-
-	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
-	    (priv->iw_mode == NL80211_IFTYPE_AP))
-		start = IWL_STA_ID;
-
-	if (is_broadcast_ether_addr(addr))
-		return priv->hw_params.bcast_sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	for (i = start; i < priv->hw_params.max_stations; i++)
-		if ((priv->stations_39[i].used) &&
-		    (!compare_ether_addr
-		     (priv->stations_39[i].sta.sta.addr, addr))) {
-			ret = i;
-			goto out;
-		}
-
-	IWL_DEBUG_INFO(priv, "can not find STA %pM (total %d)\n",
-		       addr, priv->num_stations);
- out:
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-	return ret;
-}
-
 /**
  * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
  *
@@ -885,13 +846,13 @@
 u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
 {
 	unsigned long flags_spin;
-	struct iwl3945_station_entry *station;
+	struct iwl_station_entry *station;
 
 	if (sta_id == IWL_INVALID_STATION)
 		return IWL_INVALID_STATION;
 
 	spin_lock_irqsave(&priv->sta_lock, flags_spin);
-	station = &priv->stations_39[sta_id];
+	station = &priv->stations[sta_id];
 
 	station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
 	station->sta.rate_n_flags = cpu_to_le16(tx_rate);
@@ -899,8 +860,7 @@
 
 	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
 
-	iwl_send_add_sta(priv,
-			 (struct iwl_addsta_cmd *)&station->sta, flags);
+	iwl_send_add_sta(priv, &station->sta, flags);
 	IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
 			sta_id, tx_rate);
 	return sta_id;
@@ -908,55 +868,30 @@
 
 static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
 {
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
-
 	if (src == IWL_PWR_SRC_VAUX) {
 		if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
 			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
 					APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
 					~APMG_PS_CTRL_MSK_PWR_SRC);
-			iwl_release_nic_access(priv);
 
 			iwl_poll_bit(priv, CSR_GPIO_IN,
 				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
 				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
-		} else {
-			iwl_release_nic_access(priv);
 		}
 	} else {
 		iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
 				APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
 				~APMG_PS_CTRL_MSK_PWR_SRC);
 
-		iwl_release_nic_access(priv);
 		iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
 			     CSR_GPIO_IN_BIT_AUX_POWER, 5000);	/* uS */
 	}
-	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return ret;
+	return 0;
 }
 
 static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
 {
-	int rc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return rc;
-	}
-
 	iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr);
 	iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
 	iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
@@ -973,23 +908,11 @@
 	/* fake read to flush all prev I/O */
 	iwl_read_direct32(priv, FH39_RSSR_CTRL);
 
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	return 0;
 }
 
 static int iwl3945_tx_reset(struct iwl_priv *priv)
 {
-	int rc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return rc;
-	}
 
 	/* bypass mode */
 	iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
@@ -1017,8 +940,6 @@
 		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
 		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
 
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
 }
@@ -1061,7 +982,7 @@
 
 static int iwl3945_apm_init(struct iwl_priv *priv)
 {
-	int ret = 0;
+	int ret;
 
 	iwl_power_initialize(priv);
 
@@ -1083,10 +1004,6 @@
 		goto out;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		goto out;
-
 	/* enable DMA */
 	iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
 						APMG_CLK_VAL_BSM_CLK_RQT);
@@ -1097,7 +1014,6 @@
 	iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
 			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 
-	iwl_release_nic_access(priv);
 out:
 	return ret;
 }
@@ -1110,6 +1026,11 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
+	/* Determine HW type */
+	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
+
+	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
+
 	if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
 		IWL_DEBUG_INFO(priv, "RTP type \n");
 	else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
@@ -1163,7 +1084,6 @@
 
 int iwl3945_hw_nic_init(struct iwl_priv *priv)
 {
-	u8 rev_id;
 	int rc;
 	unsigned long flags;
 	struct iwl_rx_queue *rxq = &priv->rxq;
@@ -1172,12 +1092,6 @@
 	priv->cfg->ops->lib->apm_ops.init(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* Determine HW type */
-	rc = pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
-	if (rc)
-		return rc;
-	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
-
 	rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
 	if (rc)
 		return rc;
@@ -1198,22 +1112,13 @@
 
 	iwl3945_rx_init(priv, rxq);
 
-	spin_lock_irqsave(&priv->lock, flags);
 
 	/* Look at using this instead:
 	rxq->need_update = 1;
 	iwl_rx_queue_update_write_ptr(priv, rxq);
 	*/
 
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return rc;
-	}
 	iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
-	iwl_release_nic_access(priv);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
 
 	rc = iwl3945_txq_ctx_reset(priv);
 	if (rc)
@@ -1245,14 +1150,6 @@
 void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
 {
 	int txq_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (iwl_grab_nic_access(priv)) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		iwl3945_hw_txq_ctx_free(priv);
-		return;
-	}
 
 	/* stop SCD */
 	iwl_write_prph(priv, ALM_SCD_MODE_REG, 0);
@@ -1265,9 +1162,6 @@
 				1000);
 	}
 
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	iwl3945_hw_txq_ctx_free(priv);
 }
 
@@ -1312,12 +1206,8 @@
 
 static int iwl3945_apm_reset(struct iwl_priv *priv)
 {
-	int rc;
-	unsigned long flags;
-
 	iwl3945_apm_stop_master(priv);
 
-	spin_lock_irqsave(&priv->lock, flags);
 
 	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
 	udelay(10);
@@ -1327,36 +1217,31 @@
 	iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
 			 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
 
-	rc = iwl_grab_nic_access(priv);
-	if (!rc) {
-		iwl_write_prph(priv, APMG_CLK_CTRL_REG,
-					 APMG_CLK_VAL_BSM_CLK_RQT);
+	iwl_write_prph(priv, APMG_CLK_CTRL_REG,
+				APMG_CLK_VAL_BSM_CLK_RQT);
 
-		iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
-		iwl_write_prph(priv, APMG_RTC_INT_STT_REG,
+	iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
+	iwl_write_prph(priv, APMG_RTC_INT_STT_REG,
 					0xFFFFFFFF);
 
-		/* enable DMA */
-		iwl_write_prph(priv, APMG_CLK_EN_REG,
-					 APMG_CLK_VAL_DMA_CLK_RQT |
-					 APMG_CLK_VAL_BSM_CLK_RQT);
-		udelay(10);
+	/* enable DMA */
+	iwl_write_prph(priv, APMG_CLK_EN_REG,
+				APMG_CLK_VAL_DMA_CLK_RQT |
+				APMG_CLK_VAL_BSM_CLK_RQT);
+	udelay(10);
 
-		iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
+	iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
 				APMG_PS_CTRL_VAL_RESET_REQ);
-		udelay(5);
-		iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+	udelay(5);
+	iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
 				APMG_PS_CTRL_VAL_RESET_REQ);
-		iwl_release_nic_access(priv);
-	}
 
 	/* Clear the 'host command active' bit... */
 	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
 
 	wake_up_interruptible(&priv->wait_command_queue);
-	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return rc;
+	return 0;
 }
 
 /**
@@ -1964,6 +1849,193 @@
 	return 0;
 }
 
+static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
+{
+	int rc = 0;
+	struct iwl_rx_packet *res = NULL;
+	struct iwl3945_rxon_assoc_cmd rxon_assoc;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_RXON_ASSOC,
+		.len = sizeof(rxon_assoc),
+		.meta.flags = CMD_WANT_SKB,
+		.data = &rxon_assoc,
+	};
+	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
+	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+
+	if ((rxon1->flags == rxon2->flags) &&
+	    (rxon1->filter_flags == rxon2->filter_flags) &&
+	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
+	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
+		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
+		return 0;
+	}
+
+	rxon_assoc.flags = priv->staging_rxon.flags;
+	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
+	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
+	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+	rxon_assoc.reserved = 0;
+
+	rc = iwl_send_cmd_sync(priv, &cmd);
+	if (rc)
+		return rc;
+
+	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
+		rc = -EIO;
+	}
+
+	priv->alloc_rxb_skb--;
+	dev_kfree_skb_any(cmd.meta.u.skb);
+
+	return rc;
+}
+
+/**
+ * iwl3945_commit_rxon - commit staging_rxon to hardware
+ *
+ * The RXON command in staging_rxon is committed to the hardware and
+ * the active_rxon structure is updated with the new data.  This
+ * function correctly transitions out of the RXON_ASSOC_MSK state if
+ * a HW tune is required based on the RXON structure changes.
+ */
+static int iwl3945_commit_rxon(struct iwl_priv *priv)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+	struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
+	int rc = 0;
+	bool new_assoc =
+		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (!iwl_is_alive(priv))
+		return -1;
+
+	/* always get timestamp with Rx frame */
+	staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
+
+	/* select antenna */
+	staging_rxon->flags &=
+	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
+	staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
+
+	rc = iwl_check_rxon_cmd(priv);
+	if (rc) {
+		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
+		return -EINVAL;
+	}
+
+	/* If we don't need to send a full RXON, we can use
+	 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration. */
+	if (!iwl_full_rxon_required(priv)) {
+		rc = iwl_send_rxon_assoc(priv);
+		if (rc) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC "
+				  "configuration (%d).\n", rc);
+			return rc;
+		}
+
+		memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+
+		return 0;
+	}
+
+	/* If we are currently associated and the new config requires
+	 * an RXON_ASSOC and the new config wants the associated mask enabled,
+	 * we must clear the associated from the active configuration
+	 * before we apply the new config */
+	if (iwl_is_associated(priv) && new_assoc) {
+		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+		/*
+		 * reserved4 and 5 could have been filled by the iwlcore code.
+		 * Let's clear them before pushing to the 3945.
+		 */
+		active_rxon->reserved4 = 0;
+		active_rxon->reserved5 = 0;
+		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+				      sizeof(struct iwl3945_rxon_cmd),
+				      &priv->active_rxon);
+
+		/* If the mask clearing failed then we set
+		 * active_rxon back to what it was previously */
+		if (rc) {
+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+			IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
+				  "configuration (%d).\n", rc);
+			return rc;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "Sending RXON\n"
+		       "* with%s RXON_FILTER_ASSOC_MSK\n"
+		       "* channel = %d\n"
+		       "* bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(staging_rxon->channel),
+		       staging_rxon->bssid_addr);
+
+	/*
+	 * reserved4 and 5 could have been filled by the iwlcore code.
+	 * Let's clear them before pushing to the 3945.
+	 */
+	staging_rxon->reserved4 = 0;
+	staging_rxon->reserved5 = 0;
+
+	iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
+
+	/* Apply the new configuration */
+	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+			      sizeof(struct iwl3945_rxon_cmd),
+			      staging_rxon);
+	if (rc) {
+		IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
+		return rc;
+	}
+
+	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+
+	iwl_clear_stations_table(priv);
+
+	/* If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames */
+	rc = priv->cfg->ops->lib->send_tx_power(priv);
+	if (rc) {
+		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
+		return rc;
+	}
+
+	/* Add the broadcast address so we can send broadcast frames */
+	if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) ==
+	    IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
+		return -EIO;
+	}
+
+	/* If we have set the ASSOC_MSK and we are in BSS mode then
+	 * add the IWL_AP_ID to the station rate table */
+	if (iwl_is_associated(priv) &&
+	    (priv->iw_mode == NL80211_IFTYPE_STATION))
+		if (iwl_add_station(priv, priv->active_rxon.bssid_addr,
+				true, CMD_SYNC, NULL) == IWL_INVALID_STATION) {
+			IWL_ERR(priv, "Error adding AP address for transmit\n");
+			return -EIO;
+		}
+
+	/* Init the hardware's rate fallback order based on the band */
+	rc = iwl3945_init_hw_rate_table(priv);
+	if (rc) {
+		IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 /* will add 3945 channel switch cmd handling later */
 int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 {
@@ -2314,14 +2386,6 @@
 int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
 {
 	int rc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return rc;
-	}
 
 	iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
 	rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
@@ -2329,28 +2393,17 @@
 	if (rc < 0)
 		IWL_ERR(priv, "Can't stop Rx DMA.\n");
 
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	return 0;
 }
 
 int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 {
-	int rc;
-	unsigned long flags;
 	int txq_id = txq->q.id;
 
 	struct iwl3945_shared *shared_data = priv->shared_virt;
 
 	shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	rc = iwl_grab_nic_access(priv);
-	if (rc) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return rc;
-	}
 	iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
 	iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
 
@@ -2360,11 +2413,9 @@
 		FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
 		FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
 		FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
-	iwl_release_nic_access(priv);
 
 	/* fake read to flush all prev. writes */
 	iwl_read32(priv, FH39_TSSR_CBB_BASE);
-	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
 }
@@ -2384,13 +2435,25 @@
 	}
 }
 
+
 static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
 {
-	u16 size = (u16)sizeof(struct iwl3945_addsta_cmd);
-	memcpy(data, cmd, size);
-	return size;
+	struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data;
+	addsta->mode = cmd->mode;
+	memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
+	memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
+	addsta->station_flags = cmd->station_flags;
+	addsta->station_flags_msk = cmd->station_flags_msk;
+	addsta->tid_disable_tx = cpu_to_le16(0);
+	addsta->rate_n_flags = cmd->rate_n_flags;
+	addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
+	addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
+	addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+
+	return (u16)sizeof(struct iwl3945_addsta_cmd);
 }
 
+
 /**
  * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
  */
@@ -2672,10 +2735,6 @@
 	inst_len = priv->ucode_init.len;
 	data_len = priv->ucode_init_data.len;
 
-	rc = iwl_grab_nic_access(priv);
-	if (rc)
-		return rc;
-
 	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
 	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
 	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
@@ -2689,10 +2748,8 @@
 					  le32_to_cpu(*image));
 
 	rc = iwl3945_verify_bsm(priv);
-	if (rc) {
-		iwl_release_nic_access(priv);
+	if (rc)
 		return rc;
-	}
 
 	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
 	iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
@@ -2724,11 +2781,14 @@
 	iwl_write_prph(priv, BSM_WR_CTRL_REG,
 		BSM_WR_CTRL_REG_BIT_START_EN);
 
-	iwl_release_nic_access(priv);
-
 	return 0;
 }
 
+static struct iwl_hcmd_ops iwl3945_hcmd = {
+	.rxon_assoc = iwl3945_send_rxon_assoc,
+	.commit_rxon = iwl3945_commit_rxon,
+};
+
 static struct iwl_lib_ops iwl3945_lib = {
 	.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
 	.txq_free_tfd = iwl3945_hw_txq_free_tfd,
@@ -2758,6 +2818,9 @@
 	},
 	.send_tx_power	= iwl3945_send_tx_power,
 	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
+	.post_associate = iwl3945_post_associate,
+	.isr = iwl_isr_legacy,
+	.config_ap = iwl3945_config_ap,
 };
 
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
@@ -2767,6 +2830,7 @@
 
 static struct iwl_ops iwl3945_ops = {
 	.lib = &iwl3945_lib,
+	.hcmd = &iwl3945_hcmd,
 	.utils = &iwl3945_hcmd_utils,
 };
 
@@ -2779,7 +2843,8 @@
 	.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
 	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
 	.ops = &iwl3945_ops,
-	.mod_params = &iwl3945_mod_params
+	.mod_params = &iwl3945_mod_params,
+	.use_isr_legacy = true
 };
 
 static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2791,7 +2856,8 @@
 	.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
 	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
 	.ops = &iwl3945_ops,
-	.mod_params = &iwl3945_mod_params
+	.mod_params = &iwl3945_mod_params,
+	.use_isr_legacy = true
 };
 
 struct pci_device_id iwl3945_hw_card_ids[] = {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h	2012-03-22 19:17:06.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h	2012-03-22 20:12:47.000000000 -0400
@@ -36,10 +36,6 @@
 #include <linux/kernel.h>
 #include <net/ieee80211_radiotap.h>
 
-/*used for rfkill*/
-#include <linux/rfkill.h>
-#include <linux/input.h>
-
 /* Hardware specific file defines the PCI IDs table for that hardware module */
 extern struct pci_device_id iwl3945_hw_card_ids[];
 
@@ -116,7 +112,7 @@
 #define IWL_TX_FIFO_NONE	7
 
 /* Minimum number of queues. MAX_NUM is defined in hw specific files */
-#define IWL_MIN_NUM_QUEUES	4
+#define IWL39_MIN_NUM_QUEUES	4
 
 #define IEEE80211_DATA_LEN              2304
 #define IEEE80211_4ADDR_LEN             30
@@ -155,14 +151,12 @@
 #define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
 #define STATUS_INT_ENABLED	2
 #define STATUS_RF_KILL_HW	3
-#define STATUS_RF_KILL_SW	4
 #define STATUS_INIT		5
 #define STATUS_ALIVE		6
 #define STATUS_READY		7
 #define STATUS_TEMPERATURE	8
 #define STATUS_GEO_CONFIGURED	9
 #define STATUS_EXIT_PENDING	10
-#define STATUS_IN_SUSPEND	11
 #define STATUS_STATISTICS	12
 #define STATUS_SCANNING		13
 #define STATUS_SCAN_ABORTING	14
@@ -203,11 +197,6 @@
  * for use by iwl-*.c
  *
  *****************************************************************************/
-struct iwl3945_addsta_cmd;
-extern int iwl3945_send_add_station(struct iwl_priv *priv,
-				struct iwl3945_addsta_cmd *sta, u8 flags);
-extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid,
-			  int is_ap, u8 flags);
 extern int iwl3945_power_init_handle(struct iwl_priv *priv);
 extern int iwl3945_eeprom_init(struct iwl_priv *priv);
 extern int iwl3945_calc_db_from_ratio(int sig_ratio);
@@ -278,6 +267,8 @@
 				 struct iwl_rx_mem_buffer *rxb);
 extern void iwl3945_disable_events(struct iwl_priv *priv);
 extern int iwl4965_get_temperature(const struct iwl_priv *priv);
+extern void iwl3945_post_associate(struct iwl_priv *priv);
+extern void iwl3945_config_ap(struct iwl_priv *priv);
 
 /**
  * iwl3945_hw_find_station - Find station id for a given BSSID
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c	2009-09-09 18:13:59.000000000 -0400
@@ -44,6 +44,15 @@
 #include "iwl-core.h"
 #include "iwl-dev.h"
 
+#ifdef CONFIG_IWLWIFI_DEBUG
+static const char *led_type_str[] = {
+	__stringify(IWL_LED_TRG_TX),
+	__stringify(IWL_LED_TRG_RX),
+	__stringify(IWL_LED_TRG_ASSOC),
+	__stringify(IWL_LED_TRG_RADIO),
+	NULL
+};
+#endif /* CONFIG_IWLWIFI_DEBUG */
 
 static const struct {
 	u16 brightness;
@@ -61,7 +70,7 @@
 	{10, 110, 110},
 	{5, 130, 130},
 	{0, 167, 167},
-	/*SOLID_ON*/
+	/* SOLID_ON */
 	{-1, IWL_LED_SOLID, 0}
 };
 
@@ -143,6 +152,26 @@
 }
 
 /*
+ *  Set led on in case of association
+ *  */
+static int iwl3945_led_associate(struct iwl_priv *priv, int led_id)
+{
+	IWL_DEBUG_LED(priv, "Associated\n");
+
+	priv->allow_blinking = 1;
+	return iwl3945_led_on(priv, led_id);
+}
+/* Set Led off in case of disassociation */
+static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id)
+{
+	IWL_DEBUG_LED(priv, "Disassociated\n");
+
+	priv->allow_blinking = 0;
+
+	return 0;
+}
+
+/*
  * brightness call back function for Tx/Rx LED
  */
 static int iwl3945_led_associated(struct iwl_priv *priv, int led_id)
@@ -165,26 +194,21 @@
 				enum led_brightness brightness)
 {
 	struct iwl_led *led = container_of(led_cdev,
-					       struct iwl_led, led_dev);
+					   struct iwl_led, led_dev);
 	struct iwl_priv *priv = led->priv;
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
+	IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n",
+			led_type_str[led->type], brightness);
+
 	switch (brightness) {
 	case LED_FULL:
-		if (led->type == IWL_LED_TRG_ASSOC) {
-			priv->allow_blinking = 1;
-			IWL_DEBUG_LED(priv, "MAC is  associated\n");
-		}
 		if (led->led_on)
 			led->led_on(priv, IWL_LED_LINK);
 		break;
 	case LED_OFF:
-		if (led->type == IWL_LED_TRG_ASSOC) {
-			priv->allow_blinking = 0;
-			IWL_DEBUG_LED(priv, "MAC is disassociated\n");
-		}
 		if (led->led_off)
 			led->led_off(priv, IWL_LED_LINK);
 		break;
@@ -197,8 +221,6 @@
 	}
 }
 
-
-
 /*
  * Register led class with the system
  */
@@ -237,12 +259,12 @@
 static inline u8 get_blink_rate(struct iwl_priv *priv)
 {
 	int index;
-	u64 current_tpt = priv->rxtxpackets;
-	s64 tpt = current_tpt - priv->led_tpt;
+	s64 tpt = priv->rxtxpackets;
 
 	if (tpt < 0)
 		tpt = -tpt;
-	priv->led_tpt = current_tpt;
+
+	IWL_DEBUG_LED(priv, "tpt %lld \n", (long long)tpt);
 
 	if (!priv->allow_blinking)
 		index = IWL_MAX_BLINK_TBL;
@@ -250,13 +272,9 @@
 		for (index = 0; index < IWL_MAX_BLINK_TBL; index++)
 			if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE))
 				break;
-	return index;
-}
 
-static inline int is_rf_kill(struct iwl_priv *priv)
-{
-	return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-		test_bit(STATUS_RF_KILL_SW, &priv->status);
+	IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", index);
+	return index;
 }
 
 /*
@@ -272,7 +290,7 @@
 		priv->last_blink_time = 0;
 		return;
 	}
-	if (is_rf_kill(priv)) {
+	if (iwl_is_rfkill(priv)) {
 		priv->last_blink_time = 0;
 		return;
 	}
@@ -341,8 +359,8 @@
 				   IWL_LED_TRG_ASSOC, 0, trigger);
 
 	/* for assoc always turn led on */
-	priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on;
-	priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on;
+	priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_associate;
+	priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_disassociate;
 	priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
 
 	if (ret)
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c	2009-09-09 18:13:59.000000000 -0400
@@ -38,6 +38,7 @@
 
 #include "iwl-commands.h"
 #include "iwl-3945.h"
+#include "iwl-sta.h"
 
 #define RS_NAME "iwl-3945-rs"
 
@@ -683,11 +684,10 @@
 	if (sta)
 		rate_mask = sta->supp_rates[sband->band];
 
-	/* Send management frames and broadcast/multicast data using lowest
-	 * rate. */
+	/* Send management frames and NO_ACK data using lowest rate. */
 	fc = le16_to_cpu(hdr->frame_control);
 	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
-	    is_multicast_ether_addr(hdr->addr1) ||
+	    info->flags & IEEE80211_TX_CTL_NO_ACK ||
 	    !sta || !priv_sta) {
 		IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
 		if (!rate_mask)
@@ -696,6 +696,8 @@
 		else
 			info->control.rates[0].idx =
 					rate_lowest_index(sband, sta);
+		if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+			info->control.rates[0].count = 1;
 		return;
 	}
 
@@ -713,13 +715,13 @@
 
 	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
 	    !rs_sta->ibss_sta_added) {
-		u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
+		u8 sta_id = iwl_find_station(priv, hdr->addr1);
 
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n",
 				       hdr->addr1);
-			sta_id = iwl3945_add_station(priv,
-				    hdr->addr1, 0, CMD_ASYNC);
+			sta_id = iwl_add_station(priv, hdr->addr1, false,
+				CMD_ASYNC, NULL);
 		}
 		if (sta_id != IWL_INVALID_STATION)
 			rs_sta->ibss_sta_added = 1;
@@ -974,7 +976,7 @@
 
 	rcu_read_lock();
 
-	sta = ieee80211_find_sta(hw, priv->stations_39[sta_id].sta.sta.addr);
+	sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
 	if (!sta) {
 		rcu_read_unlock();
 		return;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c	2012-03-22 19:17:15.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c	2012-03-22 20:12:53.000000000 -0400
@@ -163,10 +163,6 @@
 	inst_len = priv->ucode_init.len;
 	data_len = priv->ucode_init_data.len;
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		return ret;
-
 	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
 	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
 	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
@@ -179,10 +175,8 @@
 		_iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
 
 	ret = iwl4965_verify_bsm(priv);
-	if (ret) {
-		iwl_release_nic_access(priv);
+	if (ret)
 		return ret;
-	}
 
 	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
 	iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
@@ -211,7 +205,6 @@
 	 *   (e.g. when powering back up after power-save shutdown) */
 	iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
 
-	iwl_release_nic_access(priv);
 
 	return 0;
 }
@@ -229,20 +222,12 @@
 {
 	dma_addr_t pinst;
 	dma_addr_t pdata;
-	unsigned long flags;
 	int ret = 0;
 
 	/* bits 35:4 for 4965 */
 	pinst = priv->ucode_code.p_addr >> 4;
 	pdata = priv->ucode_data_backup.p_addr >> 4;
 
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
-
 	/* Tell bootstrap uCode where to find image to load */
 	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
 	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
@@ -253,10 +238,6 @@
 	 *   that all new ptr/size info is in place */
 	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
 				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
-	iwl_release_nic_access(priv);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
 
 	return ret;
@@ -312,10 +293,12 @@
 	queue_work(priv->workqueue, &priv->restart);
 }
 
-static int is_fat_channel(__le32 rxon_flags)
+static bool is_fat_channel(__le32 rxon_flags)
 {
-	return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
-		(rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK);
+	int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
+				    >> RXON_FLG_CHANNEL_MODE_POS;
+	return ((chan_mod == CHANNEL_MODE_PURE_40) ||
+		  (chan_mod == CHANNEL_MODE_MIXED));
 }
 
 /*
@@ -358,10 +341,6 @@
 		goto out;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		goto out;
-
 	/* enable DMA */
 	iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
 						APMG_CLK_VAL_BSM_CLK_RQT);
@@ -372,7 +351,6 @@
 	iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
 			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 
-	iwl_release_nic_access(priv);
 out:
 	return ret;
 }
@@ -454,11 +432,9 @@
 static int iwl4965_apm_reset(struct iwl_priv *priv)
 {
 	int ret = 0;
-	unsigned long flags;
 
 	iwl4965_apm_stop_master(priv);
 
-	spin_lock_irqsave(&priv->lock, flags);
 
 	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
 
@@ -475,9 +451,6 @@
 
 	udelay(10);
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		goto out;
 	/* Enable DMA and BSM Clock */
 	iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT |
 					      APMG_CLK_VAL_BSM_CLK_RQT);
@@ -488,14 +461,10 @@
 	iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
 			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 
-	iwl_release_nic_access(priv);
-
 	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
 	wake_up_interruptible(&priv->wait_command_queue);
 
 out:
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	return ret;
 }
 
@@ -681,18 +650,11 @@
 {
 	u32 a;
 	unsigned long flags;
-	int ret;
 	int i, chan;
 	u32 reg_val;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
-
 	/* Clear 4965's internal Tx Scheduler data base */
 	priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR);
 	a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET;
@@ -759,10 +721,9 @@
 		iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
 	}
 
-	iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return ret;
+	return 0;
 }
 
 static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
@@ -788,6 +749,12 @@
 	.nrg_th_ofdm = 100,
 };
 
+static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
+{
+	/* want Kelvin */
+	priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
+}
+
 /**
  * iwl4965_hw_set_hw_params
  *
@@ -822,7 +789,8 @@
 	priv->hw_params.rx_chains_num = 2;
 	priv->hw_params.valid_tx_ant = ANT_A | ANT_B;
 	priv->hw_params.valid_rx_ant = ANT_A | ANT_B;
-	priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
+	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
+		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
 
 	priv->hw_params.sens = &iwl4965_sensitivity;
 
@@ -1524,7 +1492,7 @@
 	struct iwl4965_txpowertable_cmd cmd = { 0 };
 	int ret;
 	u8 band = 0;
-	u8 is_fat = 0;
+	bool is_fat = false;
 	u8 ctrl_chan_high = 0;
 
 	if (test_bit(STATUS_SCANNING, &priv->status)) {
@@ -1602,7 +1570,7 @@
 {
 	int rc;
 	u8 band = 0;
-	u8 is_fat = 0;
+	bool is_fat = false;
 	u8 ctrl_chan_high = 0;
 	struct iwl4965_channel_switch_cmd cmd = { 0 };
 	const struct iwl_channel_info *ch_info;
@@ -1833,8 +1801,6 @@
 static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
 				   u16 ssn_idx, u8 tx_fifo)
 {
-	int ret = 0;
-
 	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
 	    (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
 		IWL_WARN(priv,
@@ -1844,10 +1810,6 @@
 		return -EINVAL;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		return ret;
-
 	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
 
 	iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
@@ -1861,8 +1823,6 @@
 	iwl_txq_ctx_deactivate(priv, txq_id);
 	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
 
-	iwl_release_nic_access(priv);
-
 	return 0;
 }
 
@@ -1904,7 +1864,6 @@
 				  int tx_fifo, int sta_id, int tid, u16 ssn_idx)
 {
 	unsigned long flags;
-	int ret;
 	u16 ra_tid;
 
 	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
@@ -1922,11 +1881,6 @@
 	iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
 
 	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
 
 	/* Stop this Tx queue before configuring it */
 	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
@@ -1959,7 +1913,6 @@
 	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
 	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
 
-	iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -2268,9 +2221,10 @@
 	cancel_work_sync(&priv->txpower_work);
 }
 
-
 static struct iwl_hcmd_ops iwl4965_hcmd = {
 	.rxon_assoc = iwl4965_send_rxon_assoc,
+	.commit_rxon = iwl_commit_rxon,
+	.set_rxon_chain = iwl_set_rxon_chain,
 };
 
 static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
@@ -2323,7 +2277,13 @@
 	},
 	.send_tx_power	= iwl4965_send_tx_power,
 	.update_chain_flags = iwl_update_chain_flags,
-	.temperature = iwl4965_temperature_calib,
+	.post_associate = iwl_post_associate,
+	.config_ap = iwl_config_ap,
+	.isr = iwl_isr_legacy,
+	.temp_ops = {
+		.temperature = iwl4965_temperature_calib,
+		.set_ct_kill = iwl4965_set_ct_threshold,
+	},
 };
 
 static struct iwl_ops iwl4965_ops = {
@@ -2343,6 +2303,7 @@
 	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
 	.ops = &iwl4965_ops,
 	.mod_params = &iwl4965_mod_params,
+	.use_isr_legacy = true
 };
 
 /* Module firmware */
@@ -2350,8 +2311,6 @@
 
 module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
 module_param_named(debug, iwl4965_mod_params.debug, uint, 0444);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c	2012-03-22 19:17:18.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c	2012-03-22 20:12:56.000000000 -0400
@@ -124,10 +124,6 @@
 		return ret;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		return ret;
-
 	/* enable DMA */
 	iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
 
@@ -137,8 +133,6 @@
 	iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
 			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
 
-	iwl_release_nic_access(priv);
-
 	return ret;
 }
 
@@ -165,12 +159,9 @@
 static int iwl5000_apm_reset(struct iwl_priv *priv)
 {
 	int ret = 0;
-	unsigned long flags;
 
 	iwl5000_apm_stop_master(priv);
 
-	spin_lock_irqsave(&priv->lock, flags);
-
 	iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
 
 	udelay(10);
@@ -193,10 +184,6 @@
 		goto out;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		goto out;
-
 	/* enable DMA */
 	iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
 
@@ -205,11 +192,7 @@
 	/* disable L1-Active */
 	iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
 			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-
-	iwl_release_nic_access(priv);
-
 out:
-	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return ret;
 }
@@ -252,11 +235,9 @@
 	 * (PCIe power is lost before PERST# is asserted),
 	 * causing ME FW to lose ownership and not being able to obtain it back.
 	 */
-	iwl_grab_nic_access(priv);
 	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
 				APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
 				~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
-	iwl_release_nic_access(priv);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
@@ -434,15 +415,19 @@
 	return &priv->eeprom[address];
 }
 
-static s32 iwl5150_get_ct_threshold(struct iwl_priv *priv)
+static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
 {
-	const s32 volt2temp_coef = -5;
-	u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv,
-						EEPROM_5000_TEMPERATURE);
-	/* offset =  temperate -  voltage / coef */
-	s32 offset = temp_calib[0] - temp_calib[1] / volt2temp_coef;
-	s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) - offset;
-	return threshold * volt2temp_coef;
+	const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
+	s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) -
+			iwl_temp_calib_to_offset(priv);
+
+	priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
+}
+
+static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
+{
+	/* want Celsius */
+	priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
 }
 
 /*
@@ -533,19 +518,9 @@
 				struct fw_desc *image,
 				u32 dst_addr)
 {
-	int ret = 0;
-	unsigned long flags;
-
 	dma_addr_t phy_addr = image->p_addr;
 	u32 byte_cnt = image->len;
 
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
-
 	iwl_write_direct32(priv,
 		FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
 		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
@@ -574,8 +549,6 @@
 		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	|
 		FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
 	return 0;
 }
 
@@ -736,18 +709,11 @@
 {
 	u32 a;
 	unsigned long flags;
-	int ret;
 	int i, chan;
 	u32 reg_val;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
-
 	priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR);
 	a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET;
 	for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET;
@@ -815,7 +781,6 @@
 	iwl_txq_ctx_activate(priv, 8);
 	iwl_txq_ctx_activate(priv, 9);
 
-	iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 
@@ -868,17 +833,8 @@
 	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
 	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
 
-	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
-	case CSR_HW_REV_TYPE_5150:
-		/* 5150 wants in Kelvin */
-		priv->hw_params.ct_kill_threshold =
-				iwl5150_get_ct_threshold(priv);
-		break;
-	default:
-		/* all others want Celsius */
-		priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
-		break;
-	}
+	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
+		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
 
 	/* Set initial calibration set */
 	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
@@ -900,7 +856,6 @@
 		break;
 	}
 
-
 	return 0;
 }
 
@@ -1006,7 +961,6 @@
 				  int tx_fifo, int sta_id, int tid, u16 ssn_idx)
 {
 	unsigned long flags;
-	int ret;
 	u16 ra_tid;
 
 	if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
@@ -1024,11 +978,6 @@
 	iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
 
 	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
 
 	/* Stop this Tx queue before configuring it */
 	iwl5000_tx_queue_stop_scheduler(priv, txq_id);
@@ -1064,7 +1013,6 @@
 	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
 	iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
 
-	iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
@@ -1073,8 +1021,6 @@
 static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
 				   u16 ssn_idx, u8 tx_fifo)
 {
-	int ret;
-
 	if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
 	    (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
 		IWL_ERR(priv,
@@ -1084,10 +1030,6 @@
 		return -EINVAL;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		return ret;
-
 	iwl5000_tx_queue_stop_scheduler(priv, txq_id);
 
 	iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id));
@@ -1101,15 +1043,16 @@
 	iwl_txq_ctx_deactivate(priv, txq_id);
 	iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
 
-	iwl_release_nic_access(priv);
-
 	return 0;
 }
 
 u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
 {
 	u16 size = (u16)sizeof(struct iwl_addsta_cmd);
-	memcpy(data, cmd, size);
+	struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
+	memcpy(addsta, cmd, size);
+	/* resrved in 5000 */
+	addsta->rate_n_flags = cpu_to_le16(0);
 	return size;
 }
 
@@ -1434,6 +1377,17 @@
 	priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
 }
 
+static void iwl5150_temperature(struct iwl_priv *priv)
+{
+	u32 vt = 0;
+	s32 offset =  iwl_temp_calib_to_offset(priv);
+
+	vt = le32_to_cpu(priv->statistics.general.temperature);
+	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
+	/* now vt hold the temperature in Kelvin */
+	priv->temperature = KELVIN_TO_CELSIUS(vt);
+}
+
 /* Calc max signal level (dBm) among 3 possible receivers */
 int iwl5000_calc_rssi(struct iwl_priv *priv,
 			     struct iwl_rx_phy_res *rx_resp)
@@ -1474,6 +1428,8 @@
 
 struct iwl_hcmd_ops iwl5000_hcmd = {
 	.rxon_assoc = iwl5000_send_rxon_assoc,
+	.commit_rxon = iwl_commit_rxon,
+	.set_rxon_chain = iwl_set_rxon_chain,
 };
 
 struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
@@ -1502,7 +1458,6 @@
 	.init_alive_start = iwl5000_init_alive_start,
 	.alive_notify = iwl5000_alive_notify,
 	.send_tx_power = iwl5000_send_tx_power,
-	.temperature = iwl5000_temperature,
 	.update_chain_flags = iwl_update_chain_flags,
 	.apm_ops = {
 		.init =	iwl5000_apm_init,
@@ -1527,6 +1482,63 @@
 		.calib_version	= iwl5000_eeprom_calib_version,
 		.query_addr = iwl5000_eeprom_query_addr,
 	},
+	.post_associate = iwl_post_associate,
+	.isr = iwl_isr_ict,
+	.config_ap = iwl_config_ap,
+	.temp_ops = {
+		.temperature = iwl5000_temperature,
+		.set_ct_kill = iwl5000_set_ct_threshold,
+	 },
+};
+
+static struct iwl_lib_ops iwl5150_lib = {
+	.set_hw_params = iwl5000_hw_set_hw_params,
+	.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
+	.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
+	.txq_set_sched = iwl5000_txq_set_sched,
+	.txq_agg_enable = iwl5000_txq_agg_enable,
+	.txq_agg_disable = iwl5000_txq_agg_disable,
+	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+	.txq_free_tfd = iwl_hw_txq_free_tfd,
+	.txq_init = iwl_hw_tx_queue_init,
+	.rx_handler_setup = iwl5000_rx_handler_setup,
+	.setup_deferred_work = iwl5000_setup_deferred_work,
+	.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+	.load_ucode = iwl5000_load_ucode,
+	.init_alive_start = iwl5000_init_alive_start,
+	.alive_notify = iwl5000_alive_notify,
+	.send_tx_power = iwl5000_send_tx_power,
+	.update_chain_flags = iwl_update_chain_flags,
+	.apm_ops = {
+		.init =	iwl5000_apm_init,
+		.reset = iwl5000_apm_reset,
+		.stop = iwl5000_apm_stop,
+		.config = iwl5000_nic_config,
+		.set_pwr_src = iwl_set_pwr_src,
+	},
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_5000_REG_BAND_1_CHANNELS,
+			EEPROM_5000_REG_BAND_2_CHANNELS,
+			EEPROM_5000_REG_BAND_3_CHANNELS,
+			EEPROM_5000_REG_BAND_4_CHANNELS,
+			EEPROM_5000_REG_BAND_5_CHANNELS,
+			EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
+			EEPROM_5000_REG_BAND_52_FAT_CHANNELS
+		},
+		.verify_signature  = iwlcore_eeprom_verify_signature,
+		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+		.release_semaphore = iwlcore_eeprom_release_semaphore,
+		.calib_version	= iwl5000_eeprom_calib_version,
+		.query_addr = iwl5000_eeprom_query_addr,
+	},
+	.post_associate = iwl_post_associate,
+	.isr = iwl_isr_ict,
+	.config_ap = iwl_config_ap,
+	.temp_ops = {
+		.temperature = iwl5150_temperature,
+		.set_ct_kill = iwl5150_set_ct_threshold,
+	 },
 };
 
 struct iwl_ops iwl5000_ops = {
@@ -1535,6 +1547,12 @@
 	.utils = &iwl5000_hcmd_utils,
 };
 
+static struct iwl_ops iwl5150_ops = {
+	.lib = &iwl5150_lib,
+	.hcmd = &iwl5000_hcmd,
+	.utils = &iwl5000_hcmd_utils,
+};
+
 struct iwl_mod_params iwl50_mod_params = {
 	.num_of_queues = IWL50_NUM_QUEUES,
 	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
@@ -1630,7 +1648,7 @@
 	.ucode_api_max = IWL5150_UCODE_API_MAX,
 	.ucode_api_min = IWL5150_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl5000_ops,
+	.ops = &iwl5150_ops,
 	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
@@ -1642,9 +1660,6 @@
 
 /*(DEBLOBBED)*/
 
-module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable50,
-		  "manually disable the 50XX radio (default 0 [radio on])");
 module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444);
 MODULE_PARM_DESC(swcrypto50,
 		  "using software crypto engine (default 0 [hardware])\n");
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-5000-hw.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-5000-hw.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-5000-hw.h	2009-09-09 18:13:59.000000000 -0400
@@ -87,6 +87,18 @@
 #define IWL50_NUM_AMPDU_QUEUES		  10
 #define IWL50_FIRST_AMPDU_QUEUE		  10
 
+/* 5150 only */
+#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF	(-5)
+
+static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
+{
+	u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv,
+						       EEPROM_5000_TEMPERATURE);
+	/* offset =  temperature -  voltage / coef */
+	s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
+	return offset;
+}
+
 /* Fixed (non-configurable) rx data from phy */
 
 /**
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c	2012-03-22 19:17:11.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c	2012-03-22 20:12:50.000000000 -0400
@@ -102,7 +102,7 @@
  * function correctly transitions out of the RXON_ASSOC_MSK state if
  * a HW tune is required based on the RXON structure changes.
  */
-static int iwl_commit_rxon(struct iwl_priv *priv)
+int iwl_commit_rxon(struct iwl_priv *priv)
 {
 	/* cast away the const for active_rxon in this function */
 	struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
@@ -190,8 +190,7 @@
 
 	iwl_clear_stations_table(priv);
 
-	if (!priv->error_recovering)
-		priv->start_calib = 0;
+	priv->start_calib = 0;
 
 	/* Add the broadcast address so we can send broadcast frames */
 	if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
@@ -246,8 +245,9 @@
 void iwl_update_chain_flags(struct iwl_priv *priv)
 {
 
-	iwl_set_rxon_chain(priv);
-	iwl_commit_rxon(priv);
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+	iwlcore_commit_rxon(priv);
 }
 
 static void iwl_clear_free_frames(struct iwl_priv *priv)
@@ -503,24 +503,12 @@
 int iwl_hw_tx_queue_init(struct iwl_priv *priv,
 			 struct iwl_tx_queue *txq)
 {
-	int ret;
-	unsigned long flags;
 	int txq_id = txq->q.id;
 
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
-
 	/* Circular buffer (TFD queue in DRAM) physical base address */
 	iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
 			     txq->q.dma_addr >> 8);
 
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	return 0;
 }
 
@@ -531,76 +519,6 @@
  *
  ******************************************************************************/
 
-static void iwl_ht_conf(struct iwl_priv *priv,
-			    struct ieee80211_bss_conf *bss_conf)
-{
-	struct ieee80211_sta_ht_cap *ht_conf;
-	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
-	struct ieee80211_sta *sta;
-
-	IWL_DEBUG_MAC80211(priv, "enter: \n");
-
-	if (!iwl_conf->is_ht)
-		return;
-
-
-	/*
-	 * It is totally wrong to base global information on something
-	 * that is valid only when associated, alas, this driver works
-	 * that way and I don't know how to fix it.
-	 */
-
-	rcu_read_lock();
-	sta = ieee80211_find_sta(priv->hw, priv->bssid);
-	if (!sta) {
-		rcu_read_unlock();
-		return;
-	}
-	ht_conf = &sta->ht_cap;
-
-	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
-		iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
-	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
-		iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
-
-	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
-	iwl_conf->max_amsdu_size =
-		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
-
-	iwl_conf->supported_chan_width =
-		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
-
-	/*
-	 * XXX: The HT configuration needs to be moved into iwl_mac_config()
-	 *	to be done there correctly.
-	 */
-
-	iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
-	if (conf_is_ht40_minus(&priv->hw->conf))
-		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-	else if (conf_is_ht40_plus(&priv->hw->conf))
-		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-
-	/* If no above or below channel supplied disable FAT channel */
-	if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
-	    iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
-		iwl_conf->supported_chan_width = 0;
-
-	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
-
-	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
-
-	iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
-	iwl_conf->ht_protection =
-		bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
-	iwl_conf->non_GF_STA_present =
-		!!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-
-	rcu_read_unlock();
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
 #define MAX_UCODE_BEACON_INTERVAL	4096
 
 static u16 iwl_adjust_beacon_interval(u16 beacon_val)
@@ -636,7 +554,8 @@
 		beacon_int = iwl_adjust_beacon_interval(priv->beacon_int);
 		priv->rxon_timing.atim_window = 0;
 	} else {
-		beacon_int = iwl_adjust_beacon_interval(conf->beacon_int);
+		beacon_int = iwl_adjust_beacon_interval(
+			priv->vif->bss_conf.beacon_int);
 
 		/* TODO: we need to get atim_window from upper stack
 		 * for now we set to 0 */
@@ -657,23 +576,6 @@
 			le16_to_cpu(priv->rxon_timing.atim_window));
 }
 
-static int iwl_set_mode(struct iwl_priv *priv, int mode)
-{
-	iwl_connection_init_rx_config(priv, mode);
-	iwl_set_rxon_chain(priv);
-	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
-
-	iwl_clear_stations_table(priv);
-
-	/* dont commit rxon if rf-kill is on*/
-	if (!iwl_is_ready_rf(priv))
-		return -EAGAIN;
-
-	iwl_commit_rxon(priv);
-
-	return 0;
-}
-
 /******************************************************************************
  *
  * Generic RX handler implementations
@@ -795,6 +697,7 @@
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
 	unsigned long status = priv->status;
+	unsigned long reg_flags;
 
 	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
 			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
@@ -806,32 +709,25 @@
 		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
 			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
 
-		if (!iwl_grab_nic_access(priv)) {
-			iwl_write_direct32(
-				priv, HBUS_TARG_MBX_C,
-				HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
-			iwl_release_nic_access(priv);
-		}
+		iwl_write_direct32(priv, HBUS_TARG_MBX_C,
+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
 
 		if (!(flags & RXON_CARD_DISABLED)) {
 			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
 				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-			if (!iwl_grab_nic_access(priv)) {
-				iwl_write_direct32(
-					priv, HBUS_TARG_MBX_C,
+			iwl_write_direct32(priv, HBUS_TARG_MBX_C,
 					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
 
-				iwl_release_nic_access(priv);
-			}
 		}
 
 		if (flags & RF_CARD_DISABLED) {
 			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
 				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
 			iwl_read32(priv, CSR_UCODE_DRV_GP1);
+			spin_lock_irqsave(&priv->reg_lock, reg_flags);
 			if (!iwl_grab_nic_access(priv))
 				iwl_release_nic_access(priv);
+			spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 		}
 	}
 
@@ -841,33 +737,19 @@
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-	if (flags & SW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-
 	if (!(flags & RXON_CARD_DISABLED))
 		iwl_scan_cancel(priv);
 
 	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
-	    (test_bit(STATUS_RF_KILL_SW, &status) !=
-	     test_bit(STATUS_RF_KILL_SW, &priv->status)))
-		queue_work(priv->workqueue, &priv->rf_kill);
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
 	else
 		wake_up_interruptible(&priv->wait_command_queue);
 }
 
 int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
 {
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		goto err;
-
 	if (src == IWL_PWR_SRC_VAUX) {
 		if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
 			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
@@ -879,10 +761,7 @@
 				       ~APMG_PS_CTRL_MSK_PWR_SRC);
 	}
 
-	iwl_release_nic_access(priv);
-err:
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return ret;
+	return 0;
 }
 
 /**
@@ -946,6 +825,7 @@
 	unsigned long flags;
 	u8 fill_rx = 0;
 	u32 count = 8;
+	int total_empty;
 
 	/* uCode's read index (stored in shared DRAM) indicates the last Rx
 	 * buffer that the driver may process (last buffer filled by ucode). */
@@ -956,7 +836,12 @@
 	if (i == r)
 		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
 
-	if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+	/* calculate total frames need to be restock after handling RX */
+	total_empty = r - priv->rxq.write_actual;
+	if (total_empty < 0)
+		total_empty += RX_QUEUE_SIZE;
+
+	if (total_empty > (RX_QUEUE_SIZE / 2))
 		fill_rx = 1;
 
 	while (i != r) {
@@ -995,6 +880,7 @@
 			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
 				i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
 			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
 		} else {
 			/* No handling needed */
 			IWL_DEBUG_RX(priv,
@@ -1032,7 +918,7 @@
 			count++;
 			if (count >= 8) {
 				priv->rxq.read = i;
-				iwl_rx_queue_restock(priv);
+				iwl_rx_replenish_now(priv);
 				count = 0;
 			}
 		}
@@ -1040,7 +926,10 @@
 
 	/* Backtrack one entry */
 	priv->rxq.read = i;
-	iwl_rx_queue_restock(priv);
+	if (fill_rx)
+		iwl_rx_replenish_now(priv);
+	else
+		iwl_rx_queue_restock(priv);
 }
 
 /* call this function to flush any scheduled tasklet */
@@ -1051,24 +940,7 @@
 	tasklet_kill(&priv->irq_tasklet);
 }
 
-static void iwl_error_recovery(struct iwl_priv *priv)
-{
-	unsigned long flags;
-
-	memcpy(&priv->staging_rxon, &priv->recovery_rxon,
-	       sizeof(priv->staging_rxon));
-	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl_commit_rxon(priv);
-
-	iwl_rxon_add_station(priv, priv->bssid, 1);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
-	priv->error_recovering = 0;
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static void iwl_irq_tasklet(struct iwl_priv *priv)
+static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
 {
 	u32 inta, handled = 0;
 	u32 inta_fh;
@@ -1116,6 +988,7 @@
 		/* Tell the device to stop sending interrupts */
 		iwl_disable_interrupts(priv);
 
+		priv->isr_stats.hw++;
 		iwl_irq_handle_error(priv);
 
 		handled |= CSR_INT_BIT_HW_ERR;
@@ -1128,13 +1001,17 @@
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (priv->debug_level & (IWL_DL_ISR)) {
 		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_SCD)
+		if (inta & CSR_INT_BIT_SCD) {
 			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
 				      "the frame/frames.\n");
+			priv->isr_stats.sch++;
+		}
 
 		/* Alive notification via Rx interrupt will do the real work */
-		if (inta & CSR_INT_BIT_ALIVE)
+		if (inta & CSR_INT_BIT_ALIVE) {
 			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+			priv->isr_stats.alive++;
+		}
 	}
 #endif
 	/* Safely ignore these bits for debug checks below */
@@ -1150,6 +1027,8 @@
 		IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
 				hw_rf_kill ? "disable radio" : "enable radio");
 
+		priv->isr_stats.rfkill++;
+
 		/* driver only loads ucode once setting the interface up.
 		 * the driver allows loading the ucode even if the radio
 		 * is killed. Hence update the killswitch state here. The
@@ -1160,7 +1039,7 @@
 				set_bit(STATUS_RF_KILL_HW, &priv->status);
 			else
 				clear_bit(STATUS_RF_KILL_HW, &priv->status);
-			queue_work(priv->workqueue, &priv->rf_kill);
+			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
 		}
 
 		handled |= CSR_INT_BIT_RF_KILL;
@@ -1169,6 +1048,7 @@
 	/* Chip got too hot and stopped itself */
 	if (inta & CSR_INT_BIT_CT_KILL) {
 		IWL_ERR(priv, "Microcode CT kill error detected.\n");
+		priv->isr_stats.ctkill++;
 		handled |= CSR_INT_BIT_CT_KILL;
 	}
 
@@ -1176,6 +1056,8 @@
 	if (inta & CSR_INT_BIT_SW_ERR) {
 		IWL_ERR(priv, "Microcode SW error detected. "
 			" Restarting 0x%X.\n", inta);
+		priv->isr_stats.sw++;
+		priv->isr_stats.sw_err = inta;
 		iwl_irq_handle_error(priv);
 		handled |= CSR_INT_BIT_SW_ERR;
 	}
@@ -1191,6 +1073,8 @@
 		iwl_txq_update_write_ptr(priv, &priv->txq[4]);
 		iwl_txq_update_write_ptr(priv, &priv->txq[5]);
 
+		priv->isr_stats.wakeup++;
+
 		handled |= CSR_INT_BIT_WAKEUP;
 	}
 
@@ -1199,23 +1083,27 @@
 	 * notifications from uCode come through here*/
 	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
 		iwl_rx_handle(priv);
+		priv->isr_stats.rx++;
 		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
 	}
 
 	if (inta & CSR_INT_BIT_FH_TX) {
 		IWL_DEBUG_ISR(priv, "Tx interrupt\n");
+		priv->isr_stats.tx++;
 		handled |= CSR_INT_BIT_FH_TX;
 		/* FH finished to write, send event */
 		priv->ucode_write_complete = 1;
 		wake_up_interruptible(&priv->wait_command_queue);
 	}
 
-	if (inta & ~handled)
+	if (inta & ~handled) {
 		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+		priv->isr_stats.unhandled++;
+	}
 
-	if (inta & ~CSR_INI_SET_MASK) {
+	if (inta & ~(priv->inta_mask)) {
 		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-			 inta & ~CSR_INI_SET_MASK);
+			 inta & ~priv->inta_mask);
 		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
 	}
 
@@ -1236,6 +1124,200 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+/* tasklet for iwlagn interrupt */
+static void iwl_irq_tasklet(struct iwl_priv *priv)
+{
+	u32 inta = 0;
+	u32 handled = 0;
+	unsigned long flags;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	u32 inta_mask;
+#endif
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Ack/clear/reset pending uCode interrupts.
+	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+	 */
+	iwl_write32(priv, CSR_INT, priv->inta);
+
+	inta = priv->inta;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if (priv->debug_level & IWL_DL_ISR) {
+		/* just for debug */
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
+				inta, inta_mask);
+	}
+#endif
+	/* saved interrupt in inta variable now we can reset priv->inta */
+	priv->inta = 0;
+
+	/* Now service all interrupt bits discovered above. */
+	if (inta & CSR_INT_BIT_HW_ERR) {
+		IWL_ERR(priv, "Microcode HW error detected.  Restarting.\n");
+
+		/* Tell the device to stop sending interrupts */
+		iwl_disable_interrupts(priv);
+
+		priv->isr_stats.hw++;
+		iwl_irq_handle_error(priv);
+
+		handled |= CSR_INT_BIT_HW_ERR;
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if (priv->debug_level & (IWL_DL_ISR)) {
+		/* NIC fires this, but we don't use it, redundant with WAKEUP */
+		if (inta & CSR_INT_BIT_SCD) {
+			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
+				      "the frame/frames.\n");
+			priv->isr_stats.sch++;
+		}
+
+		/* Alive notification via Rx interrupt will do the real work */
+		if (inta & CSR_INT_BIT_ALIVE) {
+			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+			priv->isr_stats.alive++;
+		}
+	}
+#endif
+	/* Safely ignore these bits for debug checks below */
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+	/* HW RF KILL switch toggled */
+	if (inta & CSR_INT_BIT_RF_KILL) {
+		int hw_rf_kill = 0;
+		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+			hw_rf_kill = 1;
+
+		IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
+				hw_rf_kill ? "disable radio" : "enable radio");
+
+		priv->isr_stats.rfkill++;
+
+		/* driver only loads ucode once setting the interface up.
+		 * the driver allows loading the ucode even if the radio
+		 * is killed. Hence update the killswitch state here. The
+		 * rfkill handler will care about restarting if needed.
+		 */
+		if (!test_bit(STATUS_ALIVE, &priv->status)) {
+			if (hw_rf_kill)
+				set_bit(STATUS_RF_KILL_HW, &priv->status);
+			else
+				clear_bit(STATUS_RF_KILL_HW, &priv->status);
+			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
+		}
+
+		handled |= CSR_INT_BIT_RF_KILL;
+	}
+
+	/* Chip got too hot and stopped itself */
+	if (inta & CSR_INT_BIT_CT_KILL) {
+		IWL_ERR(priv, "Microcode CT kill error detected.\n");
+		priv->isr_stats.ctkill++;
+		handled |= CSR_INT_BIT_CT_KILL;
+	}
+
+	/* Error detected by uCode */
+	if (inta & CSR_INT_BIT_SW_ERR) {
+		IWL_ERR(priv, "Microcode SW error detected. "
+			" Restarting 0x%X.\n", inta);
+		priv->isr_stats.sw++;
+		priv->isr_stats.sw_err = inta;
+		iwl_irq_handle_error(priv);
+		handled |= CSR_INT_BIT_SW_ERR;
+	}
+
+	/* uCode wakes up after power-down sleep */
+	if (inta & CSR_INT_BIT_WAKEUP) {
+		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
+		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
+		iwl_txq_update_write_ptr(priv, &priv->txq[0]);
+		iwl_txq_update_write_ptr(priv, &priv->txq[1]);
+		iwl_txq_update_write_ptr(priv, &priv->txq[2]);
+		iwl_txq_update_write_ptr(priv, &priv->txq[3]);
+		iwl_txq_update_write_ptr(priv, &priv->txq[4]);
+		iwl_txq_update_write_ptr(priv, &priv->txq[5]);
+
+		priv->isr_stats.wakeup++;
+
+		handled |= CSR_INT_BIT_WAKEUP;
+	}
+
+	/* All uCode command responses, including Tx command responses,
+	 * Rx "responses" (frame-received notification), and other
+	 * notifications from uCode come through here*/
+	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
+			CSR_INT_BIT_RX_PERIODIC)) {
+		IWL_DEBUG_ISR(priv, "Rx interrupt\n");
+		if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
+			handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+			iwl_write32(priv, CSR_FH_INT_STATUS,
+					CSR49_FH_INT_RX_MASK);
+		}
+		if (inta & CSR_INT_BIT_RX_PERIODIC) {
+			handled |= CSR_INT_BIT_RX_PERIODIC;
+			iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC);
+		}
+		/* Sending RX interrupt require many steps to be done in the
+		 * the device:
+		 * 1- write interrupt to current index in ICT table.
+		 * 2- dma RX frame.
+		 * 3- update RX shared data to indicate last write index.
+		 * 4- send interrupt.
+		 * This could lead to RX race, driver could receive RX interrupt
+		 * but the shared data changes does not reflect this.
+		 * this could lead to RX race, RX periodic will solve this race
+		 */
+		iwl_write32(priv, CSR_INT_PERIODIC_REG,
+			    CSR_INT_PERIODIC_DIS);
+		iwl_rx_handle(priv);
+		/* Only set RX periodic if real RX is received. */
+		if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
+			iwl_write32(priv, CSR_INT_PERIODIC_REG,
+				    CSR_INT_PERIODIC_ENA);
+
+		priv->isr_stats.rx++;
+	}
+
+	if (inta & CSR_INT_BIT_FH_TX) {
+		iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK);
+		IWL_DEBUG_ISR(priv, "Tx interrupt\n");
+		priv->isr_stats.tx++;
+		handled |= CSR_INT_BIT_FH_TX;
+		/* FH finished to write, send event */
+		priv->ucode_write_complete = 1;
+		wake_up_interruptible(&priv->wait_command_queue);
+	}
+
+	if (inta & ~handled) {
+		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+		priv->isr_stats.unhandled++;
+	}
+
+	if (inta & ~(priv->inta_mask)) {
+		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
+			 inta & ~priv->inta_mask);
+	}
+
+
+	/* Re-enable all interrupts */
+	/* only Re-enable if diabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_enable_interrupts(priv);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+}
+
+
 /******************************************************************************
  *
  * uCode download functions
@@ -1501,10 +1583,6 @@
 	return ret;
 }
 
-/* temporary */
-static int iwl_mac_beacon_update(struct ieee80211_hw *hw,
-				 struct sk_buff *skb);
-
 /**
  * iwl_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
@@ -1561,7 +1639,10 @@
 	} else {
 		/* Initialize our rx_config data */
 		iwl_connection_init_rx_config(priv, priv->iw_mode);
-		iwl_set_rxon_chain(priv);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv);
+
 		memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 	}
 
@@ -1571,7 +1652,7 @@
 	iwl_reset_run_time_calib(priv);
 
 	/* Configure the adapter for unassociated operation */
-	iwl_commit_rxon(priv);
+	iwlcore_commit_rxon(priv);
 
 	/* At this point, the NIC is initialized and operational */
 	iwl_rf_kill_ct_config(priv);
@@ -1582,9 +1663,6 @@
 	set_bit(STATUS_READY, &priv->status);
 	wake_up_interruptible(&priv->wait_command_queue);
 
-	if (priv->error_recovering)
-		iwl_error_recovery(priv);
-
 	iwl_power_update_mode(priv, 1);
 
 	/* reassociate for ADHOC mode */
@@ -1642,36 +1720,30 @@
 		ieee80211_stop_queues(priv->hw);
 
 	/* If we have not previously called iwl_init() then
-	 * clear all bits but the RF Kill and SUSPEND bits and return */
+	 * clear all bits but the RF Kill bit and return */
 	if (!iwl_is_init(priv)) {
 		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 					STATUS_RF_KILL_HW |
-			       test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-					STATUS_RF_KILL_SW |
 			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 					STATUS_GEO_CONFIGURED |
-			       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-					STATUS_IN_SUSPEND |
 			       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
 					STATUS_EXIT_PENDING;
 		goto exit;
 	}
 
-	/* ...otherwise clear out all the status bits but the RF Kill and
-	 * SUSPEND bits and continue taking the NIC down. */
+	/* ...otherwise clear out all the status bits but the RF Kill
+	 * bit and continue taking the NIC down. */
 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
 				STATUS_RF_KILL_HW |
-			test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-				STATUS_RF_KILL_SW |
 			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
 				STATUS_GEO_CONFIGURED |
-			test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-				STATUS_IN_SUSPEND |
 			test_bit(STATUS_FW_ERROR, &priv->status) <<
 				STATUS_FW_ERROR |
 		       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
 				STATUS_EXIT_PENDING;
 
+	/* device going down, Stop using ICT table */
+	iwl_disable_ict(priv);
 	spin_lock_irqsave(&priv->lock, flags);
 	iwl_clear_bit(priv, CSR_GP_CNTRL,
 			 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -1680,18 +1752,13 @@
 	iwl_txq_ctx_stop(priv);
 	iwl_rxq_stop(priv);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	if (!iwl_grab_nic_access(priv)) {
-		iwl_write_prph(priv, APMG_CLK_DIS_REG,
-					 APMG_CLK_VAL_DMA_CLK_RQT);
-		iwl_release_nic_access(priv);
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
+	iwl_write_prph(priv, APMG_CLK_DIS_REG,
+				APMG_CLK_VAL_DMA_CLK_RQT);
 
 	udelay(5);
 
 	/* FIXME: apm_ops.suspend(priv) */
-	if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+	if (exit_pending)
 		priv->cfg->ops->lib->apm_ops.stop(priv);
 	else
 		priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -1715,6 +1782,49 @@
 	iwl_cancel_deferred_work(priv);
 }
 
+#define HW_READY_TIMEOUT (50)
+
+static int iwl_set_hw_ready(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
+
+	/* See if we got it */
+	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+				HW_READY_TIMEOUT);
+	if (ret != -ETIMEDOUT)
+		priv->hw_ready = true;
+	else
+		priv->hw_ready = false;
+
+	IWL_DEBUG_INFO(priv, "hardware %s\n",
+		      (priv->hw_ready == 1) ? "ready" : "not ready");
+	return ret;
+}
+
+static int iwl_prepare_card_hw(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n");
+
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			CSR_HW_IF_CONFIG_REG_PREPARE);
+
+	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+			~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
+			CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+
+	if (ret != -ETIMEDOUT)
+		iwl_set_hw_ready(priv);
+
+	return ret;
+}
+
 #define MAX_HW_RESTARTS 5
 
 static int __iwl_up(struct iwl_priv *priv)
@@ -1732,6 +1842,13 @@
 		return -EIO;
 	}
 
+	iwl_prepare_card_hw(priv);
+
+	if (!priv->hw_ready) {
+		IWL_WARN(priv, "Exit HW not ready\n");
+		return -EIO;
+	}
+
 	/* If platform's RF_KILL switch is NOT set to KILL */
 	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
 		clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -1739,9 +1856,10 @@
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
 	if (iwl_is_rfkill(priv)) {
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+
 		iwl_enable_interrupts(priv);
-		IWL_WARN(priv, "Radio disabled by %s RF Kill switch\n",
-		    test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
 		return 0;
 	}
 
@@ -1787,9 +1905,6 @@
 			continue;
 		}
 
-		/* Clear out the uCode error bit if it is set */
-		clear_bit(STATUS_FW_ERROR, &priv->status);
-
 		/* start card; "initialize" will load runtime ucode */
 		iwl_nic_start(priv);
 
@@ -1836,6 +1951,9 @@
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
+	/* enable dram interrupt */
+	iwl_reset_ict(priv);
+
 	mutex_lock(&priv->mutex);
 	iwl_alive_start(priv);
 	mutex_unlock(&priv->mutex);
@@ -1874,7 +1992,6 @@
 	mutex_lock(&priv->mutex);
 	__iwl_up(priv);
 	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
 }
 
 static void iwl_bg_restart(struct work_struct *data)
@@ -1884,8 +2001,17 @@
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
-	iwl_down(priv);
-	queue_work(priv->workqueue, &priv->up);
+	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		mutex_lock(&priv->mutex);
+		priv->vif = NULL;
+		priv->is_open = 0;
+		mutex_unlock(&priv->mutex);
+		iwl_down(priv);
+		ieee80211_restart_hw(priv->hw);
+	} else {
+		iwl_down(priv);
+		queue_work(priv->workqueue, &priv->up);
+	}
 }
 
 static void iwl_bg_rx_replenish(struct work_struct *data)
@@ -1903,7 +2029,7 @@
 
 #define IWL_DELAY_NEXT_SCAN (HZ*2)
 
-static void iwl_post_associate(struct iwl_priv *priv)
+void iwl_post_associate(struct iwl_priv *priv)
 {
 	struct ieee80211_conf *conf = NULL;
 	int ret = 0;
@@ -1925,13 +2051,12 @@
 	if (!priv->vif || !priv->is_open)
 		return;
 
-	iwl_power_cancel_timeout(priv);
 	iwl_scan_cancel_timeout(priv, 200);
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
 	priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl_commit_rxon(priv);
+	iwlcore_commit_rxon(priv);
 
 	iwl_setup_rxon_timing(priv);
 	ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
@@ -1944,7 +2069,9 @@
 
 	iwl_set_rxon_ht(priv, &priv->current_ht_config);
 
-	iwl_set_rxon_chain(priv);
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+
 	priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
 
 	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
@@ -1966,7 +2093,7 @@
 
 	}
 
-	iwl_commit_rxon(priv);
+	iwlcore_commit_rxon(priv);
 
 	switch (priv->iw_mode) {
 	case NL80211_IFTYPE_STATION:
@@ -1999,7 +2126,7 @@
 	 * If chain noise has already been run, then we need to enable
 	 * power management here */
 	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
-		iwl_power_enable_management(priv);
+		iwl_power_update_mode(priv, 0);
 
 	/* Enable Rx differential gain and sensitivity calibrations */
 	iwl_chain_noise_reset(priv);
@@ -2025,7 +2152,6 @@
 	/* we should be verifying the device is ready to be opened */
 	mutex_lock(&priv->mutex);
 
-	memset(&priv->staging_rxon, 0, sizeof(struct iwl_rxon_cmd));
 	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
 	 * ucode filename and max sizes are card-specific. */
 
@@ -2042,8 +2168,6 @@
 
 	mutex_unlock(&priv->mutex);
 
-	iwl_rfkill_set_hw_state(priv);
-
 	if (ret)
 		return ret;
 
@@ -2052,9 +2176,6 @@
 
 	IWL_DEBUG_INFO(priv, "Start UP work done.\n");
 
-	if (test_bit(STATUS_IN_SUSPEND, &priv->status))
-		return 0;
-
 	/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
 	 * mac80211 will not be run successfully. */
 	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -2080,10 +2201,8 @@
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
-	if (!priv->is_open) {
-		IWL_DEBUG_MAC80211(priv, "leave - skip\n");
+	if (!priv->is_open)
 		return;
-	}
 
 	priv->is_open = 0;
 
@@ -2123,175 +2242,7 @@
 	return NETDEV_TX_OK;
 }
 
-static int iwl_mac_add_interface(struct ieee80211_hw *hw,
-				 struct ieee80211_if_init_conf *conf)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-
-	IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
-
-	if (priv->vif) {
-		IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
-		return -EOPNOTSUPP;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->vif = conf->vif;
-	priv->iw_mode = conf->type;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	mutex_lock(&priv->mutex);
-
-	if (conf->mac_addr) {
-		IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr);
-		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
-	}
-
-	if (iwl_set_mode(priv, conf->type) == -EAGAIN)
-		/* we are not ready, will run again when ready */
-		set_bit(STATUS_MODE_PENDING, &priv->status);
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return 0;
-}
-
-/**
- * iwl_mac_config - mac80211 config callback
- *
- * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
- * be set inappropriately and the driver currently sets the hardware up to
- * use it whenever needed.
- */
-static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct iwl_priv *priv = hw->priv;
-	const struct iwl_channel_info *ch_info;
-	struct ieee80211_conf *conf = &hw->conf;
-	unsigned long flags = 0;
-	int ret = 0;
-	u16 ch;
-	int scan_active = 0;
-
-	mutex_lock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
-					conf->channel->hw_value, changed);
-
-	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
-			test_bit(STATUS_SCANNING, &priv->status))) {
-		scan_active = 1;
-		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
-	}
-
-
-	/* during scanning mac80211 will delay channel setting until
-	 * scan finish with changed = 0
-	 */
-	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
-		if (scan_active)
-			goto set_ch_out;
-
-		ch = ieee80211_frequency_to_channel(conf->channel->center_freq);
-		ch_info = iwl_get_channel_info(priv, conf->channel->band, ch);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-			ret = -EINVAL;
-			goto set_ch_out;
-		}
-
-		if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-			!is_channel_ibss(ch_info)) {
-			IWL_ERR(priv, "channel %d in band %d not "
-				"IBSS channel\n",
-				conf->channel->hw_value, conf->channel->band);
-			ret = -EINVAL;
-			goto set_ch_out;
-		}
-
-		priv->current_ht_config.is_ht = conf_is_ht(conf);
-
-		spin_lock_irqsave(&priv->lock, flags);
-
-
-		/* if we are switching from ht to 2.4 clear flags
-		 * from any ht related info since 2.4 does not
-		 * support ht */
-		if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
-			priv->staging_rxon.flags = 0;
-
-		iwl_set_rxon_channel(priv, conf->channel);
-
-		iwl_set_flags_for_band(priv, conf->channel->band);
-		spin_unlock_irqrestore(&priv->lock, flags);
- set_ch_out:
-		/* The list of supported rates and rate mask can be different
-		 * for each band; since the band may have changed, reset
-		 * the rate mask to what mac80211 lists */
-		iwl_set_rate(priv);
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_PS) {
-		if (conf->flags & IEEE80211_CONF_PS)
-			ret = iwl_power_set_user_mode(priv, IWL_POWER_INDEX_3);
-		else
-			ret = iwl_power_set_user_mode(priv, IWL_POWER_MODE_CAM);
-		if (ret)
-			IWL_DEBUG_MAC80211(priv, "Error setting power level\n");
-
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
-			priv->tx_power_user_lmt, conf->power_level);
-
-		iwl_set_tx_power(priv, conf->power_level, false);
-	}
-
-	/* call to ensure that 4965 rx_chain is set properly in monitor mode */
-	iwl_set_rxon_chain(priv);
-
-	if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
-		if (conf->radio_enabled &&
-			iwl_radio_kill_sw_enable_radio(priv)) {
-			IWL_DEBUG_MAC80211(priv, "leave - RF-KILL - "
-						"waiting for uCode\n");
-			goto out;
-		}
-
-		if (!conf->radio_enabled)
-			iwl_radio_kill_sw_disable_radio(priv);
-	}
-
-	if (!conf->radio_enabled) {
-		IWL_DEBUG_MAC80211(priv, "leave - radio disabled\n");
-		goto out;
-	}
-
-	if (!iwl_is_ready(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		goto out;
-	}
-
-	if (scan_active)
-		goto out;
-
-	if (memcmp(&priv->active_rxon,
-		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
-		iwl_commit_rxon(priv);
-	else
-		IWL_DEBUG_INFO(priv, "No re-sending same RXON configuration.\n");
-
-
-out:
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-
-static void iwl_config_ap(struct iwl_priv *priv)
+void iwl_config_ap(struct iwl_priv *priv)
 {
 	int ret = 0;
 	unsigned long flags;
@@ -2304,7 +2255,7 @@
 
 		/* RXON - unassoc (to set timing command) */
 		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl_commit_rxon(priv);
+		iwlcore_commit_rxon(priv);
 
 		/* RXON Timing */
 		iwl_setup_rxon_timing(priv);
@@ -2314,7 +2265,8 @@
 			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
 					"Attempting to continue.\n");
 
-		iwl_set_rxon_chain(priv);
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv);
 
 		/* FIXME: what should be the assoc_id for AP? */
 		priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
@@ -2340,7 +2292,7 @@
 		}
 		/* restore RXON assoc */
 		priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwl_commit_rxon(priv);
+		iwlcore_commit_rxon(priv);
 		spin_lock_irqsave(&priv->lock, flags);
 		iwl_activate_qos(priv, 1);
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -2353,194 +2305,6 @@
 	 * clear sta table, add BCAST sta... */
 }
 
-
-static int iwl_mac_config_interface(struct ieee80211_hw *hw,
-					struct ieee80211_vif *vif,
-				    struct ieee80211_if_conf *conf)
-{
-	struct iwl_priv *priv = hw->priv;
-	int rc;
-
-	if (conf == NULL)
-		return -EIO;
-
-	if (priv->vif != vif) {
-		IWL_DEBUG_MAC80211(priv, "leave - priv->vif != vif\n");
-		return 0;
-	}
-
-	if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
-	    conf->changed & IEEE80211_IFCC_BEACON) {
-		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-		if (!beacon)
-			return -ENOMEM;
-		mutex_lock(&priv->mutex);
-		rc = iwl_mac_beacon_update(hw, beacon);
-		mutex_unlock(&priv->mutex);
-		if (rc)
-			return rc;
-	}
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	mutex_lock(&priv->mutex);
-
-	if (conf->bssid)
-		IWL_DEBUG_MAC80211(priv, "bssid: %pM\n", conf->bssid);
-
-/*
- * very dubious code was here; the probe filtering flag is never set:
- *
-	if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
-	    !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
- */
-
-	if (priv->iw_mode == NL80211_IFTYPE_AP) {
-		if (!conf->bssid) {
-			conf->bssid = priv->mac_addr;
-			memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
-			IWL_DEBUG_MAC80211(priv, "bssid was set to: %pM\n",
-					   conf->bssid);
-		}
-		if (priv->ibss_beacon)
-			dev_kfree_skb(priv->ibss_beacon);
-
-		priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
-	}
-
-	if (iwl_is_rfkill(priv))
-		goto done;
-
-	if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
-	    !is_multicast_ether_addr(conf->bssid)) {
-		/* If there is currently a HW scan going on in the background
-		 * then we need to cancel it else the RXON below will fail. */
-		if (iwl_scan_cancel_timeout(priv, 100)) {
-			IWL_WARN(priv, "Aborted scan still in progress "
-				    "after 100ms\n");
-			IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-			mutex_unlock(&priv->mutex);
-			return -EAGAIN;
-		}
-		memcpy(priv->staging_rxon.bssid_addr, conf->bssid, ETH_ALEN);
-
-		/* TODO: Audit driver for usage of these members and see
-		 * if mac80211 deprecates them (priv->bssid looks like it
-		 * shouldn't be there, but I haven't scanned the IBSS code
-		 * to verify) - jpk */
-		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-
-		if (priv->iw_mode == NL80211_IFTYPE_AP)
-			iwl_config_ap(priv);
-		else {
-			rc = iwl_commit_rxon(priv);
-			if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
-				iwl_rxon_add_station(
-					priv, priv->active_rxon.bssid_addr, 1);
-		}
-
-	} else {
-		iwl_scan_cancel_timeout(priv, 100);
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl_commit_rxon(priv);
-	}
-
- done:
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-
-static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
-				     struct ieee80211_if_init_conf *conf)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	mutex_lock(&priv->mutex);
-
-	if (iwl_is_ready_rf(priv)) {
-		iwl_scan_cancel_timeout(priv, 100);
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl_commit_rxon(priv);
-	}
-	if (priv->vif == conf->vif) {
-		priv->vif = NULL;
-		memset(priv->bssid, 0, ETH_ALEN);
-	}
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-}
-
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-static void iwl_bss_info_changed(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-				   bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-	}
-
-	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
-		else
-			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-	}
-
-	if (changes & BSS_CHANGED_HT) {
-		iwl_ht_conf(priv, bss_conf);
-		iwl_set_rxon_chain(priv);
-	}
-
-	if (changes & BSS_CHANGED_ASSOC) {
-		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-		/* This should never happen as this function should
-		 * never be called from interrupt context. */
-		if (WARN_ON_ONCE(in_interrupt()))
-			return;
-		if (bss_conf->assoc) {
-			priv->assoc_id = bss_conf->aid;
-			priv->beacon_int = bss_conf->beacon_int;
-			priv->power_data.dtim_period = bss_conf->dtim_period;
-			priv->timestamp = bss_conf->timestamp;
-			priv->assoc_capability = bss_conf->assoc_capability;
-
-			/* we have just associated, don't start scan too early
-			 * leave time for EAPOL exchange to complete
-			 */
-			priv->next_scan_jiffies = jiffies +
-					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
-			mutex_lock(&priv->mutex);
-			iwl_post_associate(priv);
-			mutex_unlock(&priv->mutex);
-		} else {
-			priv->assoc_id = 0;
-			IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc);
-		}
-	} else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
-			IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes);
-			iwl_send_rxon_assoc(priv);
-	}
-
-}
-
 static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
 			struct ieee80211_key_conf *keyconf, const u8 *addr,
 			u32 iv32, u16 *phase1key)
@@ -2623,49 +2387,6 @@
 	return ret;
 }
 
-static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			   const struct ieee80211_tx_queue_params *params)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	int q;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return -EIO;
-	}
-
-	if (queue >= AC_NUM) {
-		IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
-		return 0;
-	}
-
-	q = AC_NUM - 1 - queue;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
-	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
-	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
-	priv->qos_data.def_qos_parm.ac[q].edca_txop =
-			cpu_to_le16((params->txop * 32));
-
-	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
-	priv->qos_data.qos_active = 1;
-
-	if (priv->iw_mode == NL80211_IFTYPE_AP)
-		iwl_activate_qos(priv, 1);
-	else if (priv->assoc_id && iwl_is_associated(priv))
-		iwl_activate_qos(priv, 0);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return 0;
-}
-
 static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 			     enum ieee80211_ampdu_mlme_action action,
 			     struct ieee80211_sta *sta, u16 tid, u16 *ssn)
@@ -2708,41 +2429,6 @@
 	return 0;
 }
 
-static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
-				struct ieee80211_tx_queue_stats *stats)
-{
-	struct iwl_priv *priv = hw->priv;
-	int i, avail;
-	struct iwl_tx_queue *txq;
-	struct iwl_queue *q;
-	unsigned long flags;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	for (i = 0; i < AC_NUM; i++) {
-		txq = &priv->txq[i];
-		q = &txq->q;
-		avail = iwl_queue_space(q);
-
-		stats[i].len = q->n_window - avail;
-		stats[i].limit = q->n_window - q->high_mark;
-		stats[i].count = q->n_window;
-
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return 0;
-}
-
 static int iwl_mac_get_stats(struct ieee80211_hw *hw,
 			     struct ieee80211_low_level_stats *stats)
 {
@@ -2755,120 +2441,6 @@
 	return 0;
 }
 
-static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-
-	mutex_lock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	spin_lock_irqsave(&priv->lock, flags);
-	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_reset_qos(priv);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->assoc_id = 0;
-	priv->assoc_capability = 0;
-	priv->assoc_station_added = 0;
-
-	/* new association get rid of ibss beacon skb */
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-
-	priv->ibss_beacon = NULL;
-
-	priv->beacon_int = priv->hw->conf.beacon_int;
-	priv->timestamp = 0;
-	if ((priv->iw_mode == NL80211_IFTYPE_STATION))
-		priv->beacon_int = 0;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		mutex_unlock(&priv->mutex);
-		return;
-	}
-
-	/* we are restarting association process
-	 * clear RXON_FILTER_ASSOC_MSK bit
-	 */
-	if (priv->iw_mode != NL80211_IFTYPE_AP) {
-		iwl_scan_cancel_timeout(priv, 100);
-		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl_commit_rxon(priv);
-	}
-
-	iwl_power_update_mode(priv, 0);
-
-	/* Per mac80211.h: This is only used in IBSS mode... */
-	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-
-		/* switch to CAM during association period.
-		 * the ucode will block any association/authentication
-		 * frome during assiciation period if it can not hear
-		 * the AP because of PM. the timer enable PM back is
-		 * association do not complete
-		 */
-		if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN |
-						     IEEE80211_CHAN_RADAR))
-				iwl_power_disable_management(priv, 3000);
-
-		IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
-		mutex_unlock(&priv->mutex);
-		return;
-	}
-
-	iwl_set_rate(priv);
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	__le64 timestamp;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return -EIO;
-	}
-
-	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
-		IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-
-	priv->ibss_beacon = skb;
-
-	priv->assoc_id = 0;
-	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-	priv->timestamp = le64_to_cpu(timestamp);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_reset_qos(priv);
-
-	iwl_post_associate(priv);
-
-
-	return 0;
-}
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -2888,7 +2460,7 @@
 static ssize_t show_debug_level(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	return sprintf(buf, "0x%08X\n", priv->debug_level);
 }
@@ -2896,7 +2468,7 @@
 				struct device_attribute *attr,
 				 const char *buf, size_t count)
 {
-	struct iwl_priv *priv = d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	unsigned long val;
 	int ret;
 
@@ -2919,7 +2491,7 @@
 static ssize_t show_version(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	struct iwl_alive_resp *palive = &priv->card_alive;
 	ssize_t pos = 0;
 	u16 eeprom_ver;
@@ -2936,8 +2508,10 @@
 
 	if (priv->eeprom) {
 		eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-		pos += sprintf(buf + pos, "EEPROM version: 0x%x\n",
-				 eeprom_ver);
+		pos += sprintf(buf + pos, "NVM Type: %s, version: 0x%x\n",
+			       (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
+			       ? "OTP" : "EEPROM", eeprom_ver);
+
 	} else {
 		pos += sprintf(buf + pos, "EEPROM not initialzed\n");
 	}
@@ -2950,7 +2524,7 @@
 static ssize_t show_temperature(struct device *d,
 				struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	if (!iwl_is_alive(priv))
 		return -EAGAIN;
@@ -2963,7 +2537,7 @@
 static ssize_t show_tx_power(struct device *d,
 			     struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	if (!iwl_is_ready_rf(priv))
 		return sprintf(buf, "off\n");
@@ -2975,7 +2549,7 @@
 			      struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	unsigned long val;
 	int ret;
 
@@ -2993,7 +2567,7 @@
 static ssize_t show_flags(struct device *d,
 			  struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
 }
@@ -3002,7 +2576,7 @@
 			   struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	unsigned long val;
 	u32 flags;
 	int ret = strict_strtoul(buf, 0, &val);
@@ -3018,7 +2592,7 @@
 		else {
 			IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags);
 			priv->staging_rxon.flags = cpu_to_le32(flags);
-			iwl_commit_rxon(priv);
+			iwlcore_commit_rxon(priv);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -3031,7 +2605,7 @@
 static ssize_t show_filter_flags(struct device *d,
 				 struct device_attribute *attr, char *buf)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 
 	return sprintf(buf, "0x%04X\n",
 		le32_to_cpu(priv->active_rxon.filter_flags));
@@ -3041,7 +2615,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+	struct iwl_priv *priv = dev_get_drvdata(d);
 	unsigned long val;
 	u32 filter_flags;
 	int ret = strict_strtoul(buf, 0, &val);
@@ -3059,7 +2633,7 @@
 				       "0x%04X\n", filter_flags);
 			priv->staging_rxon.filter_flags =
 				cpu_to_le32(filter_flags);
-			iwl_commit_rxon(priv);
+			iwlcore_commit_rxon(priv);
 		}
 	}
 	mutex_unlock(&priv->mutex);
@@ -3101,33 +2675,36 @@
 				struct device_attribute *attr, char *buf)
 {
 	struct iwl_priv *priv = dev_get_drvdata(d);
-	int mode = priv->power_data.user_power_setting;
-	int system = priv->power_data.system_power_setting;
 	int level = priv->power_data.power_mode;
 	char *p = buf;
 
-	switch (system) {
-	case IWL_POWER_SYS_AUTO:
-		p += sprintf(p, "SYSTEM:auto");
-		break;
-	case IWL_POWER_SYS_AC:
-		p += sprintf(p, "SYSTEM:ac");
-		break;
-	case IWL_POWER_SYS_BATTERY:
-		p += sprintf(p, "SYSTEM:battery");
-		break;
-	}
-
-	p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
-			"fixed" : "auto");
-	p += sprintf(p, "\tINDEX:%d", level);
-	p += sprintf(p, "\n");
+	p += sprintf(p, "%d\n", level);
 	return p - buf + 1;
 }
 
 static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
 		   store_power_level);
 
+static ssize_t show_qos(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	char *p = buf;
+	int   q;
+
+	for (q = 0; q < AC_NUM; q++) {
+		p += sprintf(p, "\tcw_min\tcw_max\taifsn\ttxop\n");
+		p += sprintf(p, "AC[%d]\t%u\t%u\t%u\t%u\n", q,
+			     priv->qos_data.def_qos_parm.ac[q].cw_min,
+			     priv->qos_data.def_qos_parm.ac[q].cw_max,
+			     priv->qos_data.def_qos_parm.ac[q].aifsn,
+			     priv->qos_data.def_qos_parm.ac[q].edca_txop);
+	}
+
+	return p - buf + 1;
+}
+
+static DEVICE_ATTR(qos, S_IRUGO, show_qos, NULL);
 
 static ssize_t show_statistics(struct device *d,
 			       struct device_attribute *attr, char *buf)
@@ -3183,14 +2760,12 @@
 	INIT_WORK(&priv->up, iwl_bg_up);
 	INIT_WORK(&priv->restart, iwl_bg_restart);
 	INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
-	INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
 	INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
 	INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
 
 	iwl_setup_scan_deferred_work(priv);
-	iwl_setup_power_deferred_work(priv);
 
 	if (priv->cfg->ops->lib->setup_deferred_work)
 		priv->cfg->ops->lib->setup_deferred_work(priv);
@@ -3199,8 +2774,12 @@
 	priv->statistics_periodic.data = (unsigned long)priv;
 	priv->statistics_periodic.function = iwl_bg_statistics_periodic;
 
-	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-		     iwl_irq_tasklet, (unsigned long)priv);
+	if (!priv->cfg->use_isr_legacy)
+		tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+			iwl_irq_tasklet, (unsigned long)priv);
+	else
+		tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+			iwl_irq_tasklet_legacy, (unsigned long)priv);
 }
 
 static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -3210,7 +2789,6 @@
 
 	cancel_delayed_work_sync(&priv->init_alive_start);
 	cancel_delayed_work(&priv->scan_check);
-	cancel_delayed_work_sync(&priv->set_power_save);
 	cancel_delayed_work(&priv->alive_start);
 	cancel_work_sync(&priv->beacon_update);
 	del_timer_sync(&priv->statistics_periodic);
@@ -3227,7 +2805,7 @@
 	&dev_attr_debug_level.attr,
 #endif
 	&dev_attr_version.attr,
-
+	&dev_attr_qos.attr,
 	NULL
 };
 
@@ -3243,7 +2821,6 @@
 	.add_interface = iwl_mac_add_interface,
 	.remove_interface = iwl_mac_remove_interface,
 	.config = iwl_mac_config,
-	.config_interface = iwl_mac_config_interface,
 	.configure_filter = iwl_configure_filter,
 	.set_key = iwl_mac_set_key,
 	.update_tkip_key = iwl_mac_update_tkip_key,
@@ -3291,6 +2868,7 @@
 	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
 	priv->cfg = cfg;
 	priv->pci_dev = pdev;
+	priv->inta_mask = CSR_INI_SET_MASK;
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	priv->debug_level = priv->cfg->mod_params->debug;
@@ -3341,6 +2919,10 @@
 		(unsigned long long) pci_resource_len(pdev, 0));
 	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
 
+	/* this spin lock will be used in apm_ops.init and EEPROM access
+	 * we should init now
+	 */
+	spin_lock_init(&priv->reg_lock);
 	iwl_hw_detect(priv);
 	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
 		priv->cfg->name, priv->hw_rev);
@@ -3349,6 +2931,12 @@
 	 * PCI Tx retries from interfering with C3 CPU state */
 	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 
+	iwl_prepare_card_hw(priv);
+	if (!priv->hw_ready) {
+		IWL_WARN(priv, "Failed, HW not ready\n");
+		goto out_iounmap;
+	}
+
 	/* amp init */
 	err = priv->cfg->ops->lib->apm_ops.init(priv);
 	if (err < 0) {
@@ -3390,18 +2978,8 @@
 		goto out_free_eeprom;
 	/* At this point both hw and priv are initialized. */
 
-	/**********************************
-	 * 7. Initialize module parameters
-	 **********************************/
-
-	/* Disable radio (SW RF KILL) via parameter when loading driver */
-	if (priv->cfg->mod_params->disable) {
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-		IWL_DEBUG_INFO(priv, "Radio disabled.\n");
-	}
-
 	/********************
-	 * 8. Setup services
+	 * 7. Setup services
 	 ********************/
 	spin_lock_irqsave(&priv->lock, flags);
 	iwl_disable_interrupts(priv);
@@ -3409,8 +2987,9 @@
 
 	pci_enable_msi(priv->pci_dev);
 
-	err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
-			  DRV_NAME, priv);
+	iwl_alloc_isr_ict(priv);
+	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+			  IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
 		goto out_disable_msi;
@@ -3425,7 +3004,7 @@
 	iwl_setup_rx_handlers(priv);
 
 	/**********************************
-	 * 9. Setup and register mac80211
+	 * 8. Setup and register mac80211
 	 **********************************/
 
 	/* enable interrupts if needed: hw bug w/a */
@@ -3443,7 +3022,7 @@
 
 	err = iwl_dbgfs_register(priv, DRV_NAME);
 	if (err)
-		IWL_ERR(priv, "failed to create debugfs files\n");
+		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
 	/* If platform's RF_KILL switch is NOT set to KILL */
 	if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
@@ -3451,12 +3030,8 @@
 	else
 		set_bit(STATUS_RF_KILL_HW, &priv->status);
 
-	err = iwl_rfkill_init(priv);
-	if (err)
-		IWL_ERR(priv, "Unable to initialize RFKILL system. "
-				  "Ignoring error: %d\n", err);
-	else
-		iwl_rfkill_set_hw_state(priv);
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+		test_bit(STATUS_RF_KILL_HW, &priv->status));
 
 	iwl_power_initialize(priv);
 	return 0;
@@ -3467,6 +3042,7 @@
 	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
  out_free_irq:
 	free_irq(priv->pci_dev->irq, priv);
+	iwl_free_isr_ict(priv);
  out_disable_msi:
 	pci_disable_msi(priv->pci_dev);
 	iwl_uninit_drv(priv);
@@ -3519,7 +3095,6 @@
 
 	iwl_synchronize_irq(priv);
 
-	iwl_rfkill_unregister(priv);
 	iwl_dealloc_ucode_pci(priv);
 
 	if (priv->rxq.bd)
@@ -3548,51 +3123,14 @@
 
 	iwl_uninit_drv(priv);
 
+	iwl_free_isr_ict(priv);
+
 	if (priv->ibss_beacon)
 		dev_kfree_skb(priv->ibss_beacon);
 
 	ieee80211_free_hw(priv->hw);
 }
 
-#ifdef CONFIG_PM
-
-static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
-
-	if (priv->is_open) {
-		set_bit(STATUS_IN_SUSPEND, &priv->status);
-		iwl_mac_stop(priv->hw);
-		priv->is_open = 1;
-	}
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int iwl_pci_resume(struct pci_dev *pdev)
-{
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
-	int ret;
-
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-	pci_restore_state(pdev);
-	iwl_enable_interrupts(priv);
-
-	if (priv->is_open)
-		iwl_mac_start(priv->hw);
-
-	clear_bit(STATUS_IN_SUSPEND, &priv->status);
-	return 0;
-}
-
-#endif /* CONFIG_PM */
 
 /*****************************************************************************
  *
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2009-09-09 18:13:59.000000000 -0400
@@ -52,7 +52,7 @@
 /* max allowed rate miss before sync LQ cmd */
 #define IWL_MISSED_RATE_MAX		15
 /* max time to accum history 2 seconds */
-#define IWL_RATE_SCALE_FLUSH_INTVL   (2*HZ)
+#define IWL_RATE_SCALE_FLUSH_INTVL   (3*HZ)
 
 static u8 rs_ht_to_legacy[] = {
 	IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
@@ -100,6 +100,7 @@
 	u8 is_fat;	/* 1 = 40 MHz channel width */
 	u8 is_dup;	/* 1 = duplicated data streams */
 	u8 action;	/* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
+	u8 max_search;	/* maximun number of tables we can search */
 	s32 *expected_tpt;	/* throughput metrics; expected_tpt_G, etc. */
 	u32 current_rate;  /* rate_n_flags, uCode API format */
 	struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
@@ -135,7 +136,7 @@
 	u32 table_count;
 	u32 total_failed;	/* total failed frames, any/all rates */
 	u32 total_success;	/* total successful frames, any/all rates */
-	u32 flush_timer;	/* time staying in mode before new search */
+	u64 flush_timer;	/* time staying in mode before new search */
 
 	u8 action_counter;	/* # mode-switch actions tried */
 	u8 is_green;
@@ -160,6 +161,7 @@
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct dentry *rs_sta_dbgfs_scale_table_file;
 	struct dentry *rs_sta_dbgfs_stats_table_file;
+	struct dentry *rs_sta_dbgfs_rate_scale_data_file;
 	struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
 	u32 dbg_fixed_rate;
 #endif
@@ -167,10 +169,12 @@
 
 	/* used to be in sta_info */
 	int last_txrate_idx;
+	/* last tx rate_n_flags */
+	u32 last_rate_n_flags;
 };
 
 static void rs_rate_scale_perform(struct iwl_priv *priv,
-				   struct ieee80211_hdr *hdr,
+				   struct sk_buff *skb,
 				   struct ieee80211_sta *sta,
 				   struct iwl_lq_sta *lq_sta);
 static void rs_fill_link_cmd(const struct iwl_priv *priv,
@@ -191,7 +195,7 @@
  * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
  * "G" is the only table that supports CCK (the first 4 rates).
  */
-/*FIXME:RS:need to separate tables for MIMO2/MIMO3*/
+
 static s32 expected_tpt_A[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
 };
@@ -208,11 +212,11 @@
 	0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211
 };
 
-static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251
 };
 
-static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257
 };
 
@@ -224,14 +228,50 @@
 	0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264
 };
 
-static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289
 };
 
-static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
 };
 
+/* Expected throughput metric MIMO3 */
+static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268
+};
+
+static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273
+};
+
+static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297
+};
+
+static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300
+};
+
+/* mbps, mcs */
+const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+  {"1", ""},
+  {"2", ""},
+  {"5.5", ""},
+  {"11", ""},
+  {"6", "BPSK 1/2"},
+  {"9", "BPSK 1/2"},
+  {"12", "QPSK 1/2"},
+  {"18", "QPSK 3/4"},
+  {"24", "16QAM 1/2"},
+  {"36", "16QAM 3/4"},
+  {"48", "64QAM 2/3"},
+  {"54", "64QAM 3/4"},
+  {"60", "64QAM 5/6"}
+};
+
+#define MCS_INDEX_PER_STREAM	(8)
+
 static inline u8 rs_extract_rate(u32 rate_n_flags)
 {
 	return (u8)(rate_n_flags & 0xFF);
@@ -543,6 +583,7 @@
 	tbl->is_dup = 0;
 	tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
 	tbl->lq_type = LQ_NONE;
+	tbl->max_search = IWL_MAX_SEARCH;
 
 	/* legacy rate format */
 	if (!(rate_n_flags & RATE_MCS_HT_MSK)) {
@@ -576,8 +617,10 @@
 				tbl->lq_type = LQ_MIMO2;
 		/* MIMO3 */
 		} else {
-			if (num_of_ant == 3)
+			if (num_of_ant == 3) {
+				tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
 				tbl->lq_type = LQ_MIMO3;
+			}
 		}
 	}
 	return 0;
@@ -611,19 +654,19 @@
 	return 1;
 }
 
-/* FIXME:RS: in 4965 we don't use greenfield at all */
-/* FIXME:RS: don't use greenfield for now in TX */
-#if 0
-static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf)
-{
-	return (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
-		priv->current_ht_config.is_green_field &&
-		!priv->current_ht_config.non_GF_STA_present;
-}
-#endif
-static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf)
+/* in 4965 we don't use greenfield at all */
+static inline u8 rs_use_green(struct iwl_priv *priv,
+			      struct ieee80211_conf *conf)
 {
-	return 0;
+	u8 is_green;
+
+	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
+		is_green = 0;
+	else
+		is_green = (conf_is_ht(conf) &&
+			   priv->current_ht_config.is_green_field &&
+			   !priv->current_ht_config.non_GF_STA_present);
+	return is_green;
 }
 
 /**
@@ -735,6 +778,7 @@
 
 		tbl->is_fat = 0;
 		tbl->is_SGI = 0;
+		tbl->max_search = IWL_MAX_SEARCH;
 	}
 
 	rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type);
@@ -793,7 +837,7 @@
 	IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
 
 	if (!ieee80211_is_data(hdr->frame_control) ||
-	    is_multicast_ether_addr(hdr->addr1))
+	    info->flags & IEEE80211_TX_CTL_NO_ACK)
 		return;
 
 	/* This packet was aggregated but doesn't carry rate scale info */
@@ -902,6 +946,7 @@
 	 * else look up the rate that was, finally, successful.
 	 */
 	tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags);
+	lq_sta->last_rate_n_flags = tx_rate;
 	rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
 
 	/* Update frame history window with "success" if Tx got ACKed ... */
@@ -958,7 +1003,7 @@
 
 	/* See if there's a better rate or modulation mode to try. */
 	if (sta && sta->supp_rates[sband->band])
-		rs_rate_scale_perform(priv, hdr, sta, lq_sta);
+		rs_rate_scale_perform(priv, skb, sta, lq_sta);
 out:
 	return;
 }
@@ -988,6 +1033,8 @@
 	lq_sta->table_count = 0;
 	lq_sta->total_failed = 0;
 	lq_sta->total_success = 0;
+	lq_sta->flush_timer = jiffies;
+	lq_sta->action_counter = 0;
 }
 
 /*
@@ -1011,17 +1058,26 @@
 			tbl->expected_tpt = expected_tpt_siso20MHzSGI;
 		else
 			tbl->expected_tpt = expected_tpt_siso20MHz;
-
-	} else if (is_mimo(tbl->lq_type)) { /* FIXME:need to separate mimo2/3 */
+	} else if (is_mimo2(tbl->lq_type)) {
 		if (tbl->is_fat && !lq_sta->is_dup)
 			if (tbl->is_SGI)
-				tbl->expected_tpt = expected_tpt_mimo40MHzSGI;
+				tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI;
 			else
-				tbl->expected_tpt = expected_tpt_mimo40MHz;
+				tbl->expected_tpt = expected_tpt_mimo2_40MHz;
 		else if (tbl->is_SGI)
-			tbl->expected_tpt = expected_tpt_mimo20MHzSGI;
+			tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI;
 		else
-			tbl->expected_tpt = expected_tpt_mimo20MHz;
+			tbl->expected_tpt = expected_tpt_mimo2_20MHz;
+	} else if (is_mimo3(tbl->lq_type)) {
+		if (tbl->is_fat && !lq_sta->is_dup)
+			if (tbl->is_SGI)
+				tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI;
+			else
+				tbl->expected_tpt = expected_tpt_mimo3_40MHz;
+		else if (tbl->is_SGI)
+			tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI;
+		else
+			tbl->expected_tpt = expected_tpt_mimo3_20MHz;
 	} else
 		tbl->expected_tpt = expected_tpt_G;
 }
@@ -1130,7 +1186,7 @@
 }
 
 /*
- * Set up search table for MIMO
+ * Set up search table for MIMO2
  */
 static int rs_switch_to_mimo2(struct iwl_priv *priv,
 			     struct iwl_lq_sta *lq_sta,
@@ -1158,10 +1214,10 @@
 	tbl->lq_type = LQ_MIMO2;
 	tbl->is_dup = lq_sta->is_dup;
 	tbl->action = 0;
+	tbl->max_search = IWL_MAX_SEARCH;
 	rate_mask = lq_sta->active_mimo2_rate;
 
-	if (priv->current_ht_config.supported_chan_width
-					== IWL_CHANNEL_WIDTH_40MHZ)
+	if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
 		tbl->is_fat = 1;
 	else
 		tbl->is_fat = 0;
@@ -1183,7 +1239,73 @@
 	rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
 
 	IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask);
+	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
+		IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n",
+						rate, rate_mask);
+		return -1;
+	}
+	tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green);
+
+	IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n",
+		     tbl->current_rate, is_green);
+	return 0;
+}
 
+/*
+ * Set up search table for MIMO3
+ */
+static int rs_switch_to_mimo3(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta,
+			     struct ieee80211_conf *conf,
+			     struct ieee80211_sta *sta,
+			     struct iwl_scale_tbl_info *tbl, int index)
+{
+	u16 rate_mask;
+	s32 rate;
+	s8 is_green = lq_sta->is_green;
+
+	if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
+		return -1;
+
+	if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
+						== WLAN_HT_CAP_SM_PS_STATIC)
+		return -1;
+
+	/* Need both Tx chains/antennas to support MIMO */
+	if (priv->hw_params.tx_chains_num < 3)
+		return -1;
+
+	IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n");
+
+	tbl->lq_type = LQ_MIMO3;
+	tbl->is_dup = lq_sta->is_dup;
+	tbl->action = 0;
+	tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
+	rate_mask = lq_sta->active_mimo3_rate;
+
+	if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
+		tbl->is_fat = 1;
+	else
+		tbl->is_fat = 0;
+
+	/* FIXME: - don't toggle SGI here
+	if (tbl->is_fat) {
+		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
+			tbl->is_SGI = 1;
+		else
+			tbl->is_SGI = 0;
+	} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
+		tbl->is_SGI = 1;
+	else
+		tbl->is_SGI = 0;
+	*/
+
+	rs_set_expected_tpt_table(lq_sta, tbl);
+
+	rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
+
+	IWL_DEBUG_RATE(priv, "LQ: MIMO3 best rate %d mask %X\n",
+		rate, rate_mask);
 	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
 		IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n",
 						rate, rate_mask);
@@ -1217,10 +1339,10 @@
 	tbl->is_dup = lq_sta->is_dup;
 	tbl->lq_type = LQ_SISO;
 	tbl->action = 0;
+	tbl->max_search = IWL_MAX_SEARCH;
 	rate_mask = lq_sta->active_siso_rate;
 
-	if (priv->current_ht_config.supported_chan_width
-	    == IWL_CHANNEL_WIDTH_40MHZ)
+	if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap))
 		tbl->is_fat = 1;
 	else
 		tbl->is_fat = 0;
@@ -1274,15 +1396,15 @@
 	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
 	u8 tx_chains_num = priv->hw_params.tx_chains_num;
 	int ret = 0;
+	u8 update_search_tbl_counter = 0;
 
 	for (; ;) {
+		lq_sta->action_counter++;
 		switch (tbl->action) {
 		case IWL_LEGACY_SWITCH_ANTENNA1:
 		case IWL_LEGACY_SWITCH_ANTENNA2:
 			IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n");
 
-			lq_sta->action_counter++;
-
 			if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 &&
 							tx_chains_num <= 1) ||
 			    (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 &&
@@ -1298,6 +1420,7 @@
 
 			if (rs_toggle_antenna(valid_tx_ant,
 				&search_tbl->current_rate, search_tbl)) {
+				update_search_tbl_counter = 1;
 				rs_set_expected_tpt_table(lq_sta, search_tbl);
 				goto out;
 			}
@@ -1342,9 +1465,29 @@
 				goto out;
 			}
 			break;
+
+		case IWL_LEGACY_SWITCH_MIMO3_ABC:
+			IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO3\n");
+
+			/* Set up search table to try MIMO3 */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+
+			search_tbl->ant_type = ANT_ABC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret) {
+				lq_sta->action_counter = 0;
+				goto out;
+			}
+			break;
 		}
 		tbl->action++;
-		if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+		if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
 			tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
 
 		if (tbl->action == start_action)
@@ -1357,8 +1500,10 @@
 out:
 	lq_sta->search_better_tbl = 1;
 	tbl->action++;
-	if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+	if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
 		tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
 	return 0;
 
 }
@@ -1381,6 +1526,7 @@
 	u8 start_action = tbl->action;
 	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
 	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+	u8 update_search_tbl_counter = 0;
 	int ret;
 
 	for (;;) {
@@ -1401,8 +1547,10 @@
 
 			memcpy(search_tbl, tbl, sz);
 			if (rs_toggle_antenna(valid_tx_ant,
-				       &search_tbl->current_rate, search_tbl))
+				       &search_tbl->current_rate, search_tbl)) {
+				update_search_tbl_counter = 1;
 				goto out;
+			}
 			break;
 		case IWL_SISO_SWITCH_MIMO2_AB:
 		case IWL_SISO_SWITCH_MIMO2_AC:
@@ -1456,10 +1604,25 @@
 			search_tbl->current_rate =
 				rate_n_flags_from_tbl(priv, search_tbl,
 						      index, is_green);
+			update_search_tbl_counter = 1;
 			goto out;
+		case IWL_SISO_SWITCH_MIMO3_ABC:
+			IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n");
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			search_tbl->ant_type = ANT_ABC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+			break;
 		}
 		tbl->action++;
-		if (tbl->action > IWL_SISO_SWITCH_GI)
+		if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
 			tbl->action = IWL_SISO_SWITCH_ANTENNA1;
 
 		if (tbl->action == start_action)
@@ -1471,15 +1634,18 @@
  out:
 	lq_sta->search_better_tbl = 1;
 	tbl->action++;
-	if (tbl->action > IWL_SISO_SWITCH_GI)
+	if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC)
 		tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+
 	return 0;
 }
 
 /*
- * Try to switch to new modulation mode from MIMO
+ * Try to switch to new modulation mode from MIMO2
  */
-static int rs_move_mimo_to_other(struct iwl_priv *priv,
+static int rs_move_mimo2_to_other(struct iwl_priv *priv,
 				 struct iwl_lq_sta *lq_sta,
 				 struct ieee80211_conf *conf,
 				 struct ieee80211_sta *sta, int index)
@@ -1494,6 +1660,7 @@
 	u8 start_action = tbl->action;
 	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
 	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+	u8 update_search_tbl_counter = 0;
 	int ret;
 
 	for (;;) {
@@ -1501,7 +1668,7 @@
 		switch (tbl->action) {
 		case IWL_MIMO2_SWITCH_ANTENNA1:
 		case IWL_MIMO2_SWITCH_ANTENNA2:
-			IWL_DEBUG_RATE(priv, "LQ: MIMO toggle Antennas\n");
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n");
 
 			if (tx_chains_num <= 2)
 				break;
@@ -1511,8 +1678,10 @@
 
 			memcpy(search_tbl, tbl, sz);
 			if (rs_toggle_antenna(valid_tx_ant,
-				       &search_tbl->current_rate, search_tbl))
+				       &search_tbl->current_rate, search_tbl)) {
+				update_search_tbl_counter = 1;
 				goto out;
+			}
 			break;
 		case IWL_MIMO2_SWITCH_SISO_A:
 		case IWL_MIMO2_SWITCH_SISO_B:
@@ -1549,9 +1718,9 @@
 						HT_SHORT_GI_40MHZ))
 				break;
 
-			IWL_DEBUG_RATE(priv, "LQ: MIMO toggle SGI/NGI\n");
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
 
-			/* Set up new search table for MIMO */
+			/* Set up new search table for MIMO2 */
 			memcpy(search_tbl, tbl, sz);
 			search_tbl->is_SGI = !tbl->is_SGI;
 			rs_set_expected_tpt_table(lq_sta, search_tbl);
@@ -1569,11 +1738,27 @@
 			search_tbl->current_rate =
 				rate_n_flags_from_tbl(priv, search_tbl,
 						      index, is_green);
+			update_search_tbl_counter = 1;
 			goto out;
 
+		case IWL_MIMO2_SWITCH_MIMO3_ABC:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to MIMO3\n");
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			search_tbl->ant_type = ANT_ABC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
 		}
 		tbl->action++;
-		if (tbl->action > IWL_MIMO2_SWITCH_GI)
+		if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC)
 			tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
 
 		if (tbl->action == start_action)
@@ -1584,8 +1769,153 @@
  out:
 	lq_sta->search_better_tbl = 1;
 	tbl->action++;
-	if (tbl->action > IWL_MIMO2_SWITCH_GI)
+	if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC)
 		tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+
+	return 0;
+
+}
+
+/*
+ * Try to switch to new modulation mode from MIMO3
+ */
+static int rs_move_mimo3_to_other(struct iwl_priv *priv,
+				 struct iwl_lq_sta *lq_sta,
+				 struct ieee80211_conf *conf,
+				 struct ieee80211_sta *sta, int index)
+{
+	s8 is_green = lq_sta->is_green;
+	struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+	struct iwl_scale_tbl_info *search_tbl =
+				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+	u8 start_action = tbl->action;
+	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+	int ret;
+	u8 update_search_tbl_counter = 0;
+
+	for (;;) {
+		lq_sta->action_counter++;
+		switch (tbl->action) {
+		case IWL_MIMO3_SWITCH_ANTENNA1:
+		case IWL_MIMO3_SWITCH_ANTENNA2:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle Antennas\n");
+
+			if (tx_chains_num <= 3)
+				break;
+
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			memcpy(search_tbl, tbl, sz);
+			if (rs_toggle_antenna(valid_tx_ant,
+				       &search_tbl->current_rate, search_tbl))
+				goto out;
+			break;
+		case IWL_MIMO3_SWITCH_SISO_A:
+		case IWL_MIMO3_SWITCH_SISO_B:
+		case IWL_MIMO3_SWITCH_SISO_C:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to SISO\n");
+
+			/* Set up new search table for SISO */
+			memcpy(search_tbl, tbl, sz);
+
+			if (tbl->action == IWL_MIMO3_SWITCH_SISO_A)
+				search_tbl->ant_type = ANT_A;
+			else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B)
+				search_tbl->ant_type = ANT_B;
+			else
+				search_tbl->ant_type = ANT_C;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
+
+		case IWL_MIMO3_SWITCH_MIMO2_AB:
+		case IWL_MIMO3_SWITCH_MIMO2_AC:
+		case IWL_MIMO3_SWITCH_MIMO2_BC:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to MIMO2\n");
+
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB)
+				search_tbl->ant_type = ANT_AB;
+			else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC)
+				search_tbl->ant_type = ANT_AC;
+			else
+				search_tbl->ant_type = ANT_BC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
+
+		case IWL_MIMO3_SWITCH_GI:
+			if (!tbl->is_fat &&
+				!(priv->current_ht_config.sgf &
+						HT_SHORT_GI_20MHZ))
+				break;
+			if (tbl->is_fat &&
+				!(priv->current_ht_config.sgf &
+						HT_SHORT_GI_40MHZ))
+				break;
+
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n");
+
+			/* Set up new search table for MIMO */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = !tbl->is_SGI;
+			rs_set_expected_tpt_table(lq_sta, search_tbl);
+			/*
+			 * If active table already uses the fastest possible
+			 * modulation (dual stream with short guard interval),
+			 * and it's working well, there's no need to look
+			 * for a better type of modulation!
+			 */
+			if (tbl->is_SGI) {
+				s32 tpt = lq_sta->last_tpt / 100;
+				if (tpt >= search_tbl->expected_tpt[index])
+					break;
+			}
+			search_tbl->current_rate =
+				rate_n_flags_from_tbl(priv, search_tbl,
+						      index, is_green);
+			update_search_tbl_counter = 1;
+			goto out;
+		}
+		tbl->action++;
+		if (tbl->action > IWL_MIMO3_SWITCH_GI)
+			tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
+
+		if (tbl->action == start_action)
+			break;
+	}
+	search_tbl->lq_type = LQ_NONE;
+	return 0;
+ out:
+	lq_sta->search_better_tbl = 1;
+	tbl->action++;
+	if (tbl->action > IWL_MIMO3_SWITCH_GI)
+		tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+
 	return 0;
 
 }
@@ -1616,8 +1946,8 @@
 		/* Elapsed time using current modulation mode */
 		if (lq_sta->flush_timer)
 			flush_interval_passed =
-			    time_after(jiffies,
-				       (unsigned long)(lq_sta->flush_timer +
+			time_after(jiffies,
+					(unsigned long)(lq_sta->flush_timer +
 					IWL_RATE_SCALE_FLUSH_INTVL));
 
 		/*
@@ -1676,12 +2006,14 @@
  * Do rate scaling and search for new modulation mode.
  */
 static void rs_rate_scale_perform(struct iwl_priv *priv,
-				  struct ieee80211_hdr *hdr,
+				  struct sk_buff *skb,
 				  struct ieee80211_sta *sta,
 				  struct iwl_lq_sta *lq_sta)
 {
 	struct ieee80211_hw *hw = priv->hw;
 	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	int low = IWL_RATE_INVALID;
 	int high = IWL_RATE_INVALID;
 	int index;
@@ -1707,11 +2039,10 @@
 
 	IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
 
-	/* Send management frames and broadcast/multicast data using
-	 * lowest rate. */
+	/* Send management frames and NO_ACK data using lowest rate. */
 	/* TODO: this could probably be improved.. */
 	if (!ieee80211_is_data(hdr->frame_control) ||
-	    is_multicast_ether_addr(hdr->addr1))
+	    info->flags & IEEE80211_TX_CTL_NO_ACK)
 		return;
 
 	if (!sta || !lq_sta)
@@ -1732,6 +2063,10 @@
 		active_tbl = 1 - lq_sta->active_tbl;
 
 	tbl = &(lq_sta->lq_info[active_tbl]);
+	if (is_legacy(tbl->lq_type))
+		lq_sta->is_green = 0;
+	else
+		lq_sta->is_green = rs_use_green(priv, conf);
 	is_green = lq_sta->is_green;
 
 	/* current tx rate */
@@ -1951,6 +2286,7 @@
 			update_lq = 1;
 			index = low;
 		}
+
 		break;
 	case 1:
 		/* Increase starting rate, update uCode's rate table */
@@ -1997,8 +2333,10 @@
 			rs_move_legacy_other(priv, lq_sta, conf, sta, index);
 		else if (is_siso(tbl->lq_type))
 			rs_move_siso_to_other(priv, lq_sta, conf, sta, index);
+		else if (is_mimo2(tbl->lq_type))
+			rs_move_mimo2_to_other(priv, lq_sta, conf, sta, index);
 		else
-			rs_move_mimo_to_other(priv, lq_sta, conf, sta, index);
+			rs_move_mimo3_to_other(priv, lq_sta, conf, sta, index);
 
 		/* If new "search" mode was selected, set up in uCode table */
 		if (lq_sta->search_better_tbl) {
@@ -2014,8 +2352,11 @@
 				     tbl->current_rate, index);
 			rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
 			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
-		}
+		} else
+			done_search = 1;
+	}
 
+	if (done_search && !lq_sta->stay_in_tbl) {
 		/* If the "active" (non-search) mode was legacy,
 		 * and we've tried switching antennas,
 		 * but we haven't been able to try HT modes (not available),
@@ -2023,8 +2364,7 @@
 		 * before next round of mode comparisons. */
 		tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
 		if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) &&
-		    lq_sta->action_counter >= 1) {
-			lq_sta->action_counter = 0;
+		    lq_sta->action_counter > tbl1->max_search) {
 			IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n");
 			rs_set_stay_in_table(priv, 1, lq_sta);
 		}
@@ -2033,7 +2373,7 @@
 		 * have been tried and compared, stay in this best modulation
 		 * mode for a while before next round of mode comparisons. */
 		if (lq_sta->enable_counter &&
-		    (lq_sta->action_counter >= IWL_ACTION_LIMIT)) {
+		    (lq_sta->action_counter >= tbl1->max_search)) {
 			if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
 			    (lq_sta->tx_agg_tid_en & (1 << tid)) &&
 			    (tid != MAX_TID_COUNT)) {
@@ -2047,20 +2387,8 @@
 							  lq_sta, sta);
 				}
 			}
-			lq_sta->action_counter = 0;
 			rs_set_stay_in_table(priv, 0, lq_sta);
 		}
-
-	/*
-	 * Else, don't search for a new modulation mode.
-	 * Put new timestamp in stay-in-modulation-mode flush timer if:
-	 * 1)  Not changing rates right now
-	 * 2)  Not just finishing up a search
-	 * 3)  flush timer is empty
-	 */
-	} else {
-		if ((!update_lq) && (!done_search) && (!lq_sta->flush_timer))
-			lq_sta->flush_timer = jiffies;
 	}
 
 out:
@@ -2156,16 +2484,17 @@
 	if (sta)
 		mask_bit = sta->supp_rates[sband->band];
 
-	/* Send management frames and broadcast/multicast data using lowest
-	 * rate. */
+	/* Send management frames and NO_ACK data using lowest rate. */
 	if (!ieee80211_is_data(hdr->frame_control) ||
-	    is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) {
+	    info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !lq_sta) {
 		if (!mask_bit)
 			info->control.rates[0].idx =
 					rate_lowest_index(sband, NULL);
 		else
 			info->control.rates[0].idx =
 					rate_lowest_index(sband, sta);
+		if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+			info->control.rates[0].count = 1;
 		return;
 	}
 
@@ -2178,8 +2507,8 @@
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
 				       hdr->addr1);
-			sta_id = iwl_add_station_flags(priv, hdr->addr1,
-							0, CMD_ASYNC, NULL);
+			sta_id = iwl_add_station(priv, hdr->addr1,
+						false, CMD_ASYNC, NULL);
 		}
 		if ((sta_id != IWL_INVALID_STATION)) {
 			lq_sta->lq.sta_id = sta_id;
@@ -2189,12 +2518,33 @@
 		}
 	}
 
-	if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT)
-		rate_idx = rate_lowest_index(sband, sta);
-	else if (sband->band == IEEE80211_BAND_5GHZ)
+	if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
 		rate_idx -= IWL_FIRST_OFDM_RATE;
-
+		/* 6M and 9M shared same MCS index */
+		rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0;
+		if (rs_extract_rate(lq_sta->last_rate_n_flags) >=
+		    IWL_RATE_MIMO3_6M_PLCP)
+			rate_idx = rate_idx + (2 * MCS_INDEX_PER_STREAM);
+		else if (rs_extract_rate(lq_sta->last_rate_n_flags) >=
+			 IWL_RATE_MIMO2_6M_PLCP)
+			rate_idx = rate_idx + MCS_INDEX_PER_STREAM;
+		info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK)
+			info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
+			info->control.rates[0].flags |= IEEE80211_TX_RC_DUP_DATA;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_FAT_MSK)
+			info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
+			info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD;
+	} else {
+		if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT)
+			rate_idx = rate_lowest_index(sband, sta);
+		else if (sband->band == IEEE80211_BAND_5GHZ)
+			rate_idx -= IWL_FIRST_OFDM_RATE;
+	}
 	info->control.rates[0].idx = rate_idx;
+
 }
 
 static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
@@ -2246,15 +2596,16 @@
 
 	lq_sta->ibss_sta_added = 0;
 	if (priv->iw_mode == NL80211_IFTYPE_AP) {
-		u8 sta_id = iwl_find_station(priv, sta->addr);
+		u8 sta_id = iwl_find_station(priv,
+								sta->addr);
 
 		/* for IBSS the call are from tasklet */
 		IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
 
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
-			sta_id = iwl_add_station_flags(priv, sta->addr,
-							0, CMD_ASYNC, NULL);
+			sta_id = iwl_add_station(priv, sta->addr, false,
+						CMD_ASYNC, NULL);
 		}
 		if ((sta_id != IWL_INVALID_STATION)) {
 			lq_sta->lq.sta_id = sta_id;
@@ -2436,9 +2787,10 @@
 		repeat_rate--;
 	}
 
-	lq_cmd->agg_params.agg_frame_cnt_limit = 64;
-	lq_cmd->agg_params.agg_dis_start_th = 3;
-	lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000);
+	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX;
+	lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+	lq_cmd->agg_params.agg_time_limit =
+		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
 }
 
 static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
@@ -2539,6 +2891,7 @@
 	char *buff;
 	int desc = 0;
 	int i = 0;
+	int index = 0;
 	ssize_t ret;
 
 	struct iwl_lq_sta *lq_sta = file->private_data;
@@ -2568,8 +2921,11 @@
 		   ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
 		   desc += sprintf(buff+desc, " %s",
 		   (tbl->is_fat) ? "40MHz" : "20MHz");
-		desc += sprintf(buff+desc, " %s\n", (tbl->is_SGI) ? "SGI" : "");
+		   desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "",
+		   (lq_sta->is_green) ? "GF enabled" : "");
 	}
+	desc += sprintf(buff+desc, "last tx rate=0x%X\n",
+		lq_sta->last_rate_n_flags);
 	desc += sprintf(buff+desc, "general:"
 		"flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
 		lq_sta->lq.general_params.flags,
@@ -2590,10 +2946,19 @@
 			lq_sta->lq.general_params.start_rate_index[2],
 			lq_sta->lq.general_params.start_rate_index[3]);
 
-
-	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
-		desc += sprintf(buff+desc, " rate[%d] 0x%X\n",
-			i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+		index = iwl_hwrate_to_plcp_idx(
+			le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
+		if (is_legacy(tbl->lq_type)) {
+			desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n",
+				i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
+				iwl_rate_mcs[index].mbps);
+		} else {
+			desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps (%s)\n",
+				i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
+				iwl_rate_mcs[index].mbps, iwl_rate_mcs[index].mcs);
+		}
+	}
 
 	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
 	kfree(buff);
@@ -2620,13 +2985,14 @@
 		return -ENOMEM;
 
 	for (i = 0; i < LQ_SIZE; i++) {
-		desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n"
+		desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d GF=%d\n"
 				"rate=0x%X\n",
 				lq_sta->active_tbl == i ? "*" : "x",
 				lq_sta->lq_info[i].lq_type,
 				lq_sta->lq_info[i].is_SGI,
 				lq_sta->lq_info[i].is_fat,
 				lq_sta->lq_info[i].is_dup,
+				lq_sta->is_green,
 				lq_sta->lq_info[i].current_rate);
 		for (j = 0; j < IWL_RATE_COUNT; j++) {
 			desc += sprintf(buff+desc,
@@ -2646,6 +3012,43 @@
 	.open = open_file_generic,
 };
 
+static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char buff[120];
+	int desc = 0;
+	ssize_t ret;
+
+	struct iwl_lq_sta *lq_sta = file->private_data;
+	struct iwl_priv *priv;
+	struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+
+	priv = lq_sta->drv;
+
+	if (is_Ht(tbl->lq_type))
+		desc += sprintf(buff+desc,
+				"Bit Rate= %d Mb/s\n",
+				tbl->expected_tpt[lq_sta->last_txrate_idx]);
+	else
+		desc += sprintf(buff+desc,
+				"Bit Rate= %d Mb/s\n",
+				iwl_rates[lq_sta->last_txrate_idx].ieee >> 1);
+	desc += sprintf(buff+desc,
+			"Signal Level= %d dBm\tNoise Level= %d dBm\n",
+			priv->last_rx_rssi, priv->last_rx_noise);
+	desc += sprintf(buff+desc,
+			"Tsf= 0x%llx\tBeacon time= 0x%08X\n",
+			priv->last_tsf, priv->last_beacon_time);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
+	.read = rs_sta_dbgfs_rate_scale_data_read,
+	.open = open_file_generic,
+};
+
 static void rs_add_debugfs(void *priv, void *priv_sta,
 					struct dentry *dir)
 {
@@ -2656,6 +3059,9 @@
 	lq_sta->rs_sta_dbgfs_stats_table_file =
 		debugfs_create_file("rate_stats_table", 0600, dir,
 			lq_sta, &rs_sta_dbgfs_stats_table_ops);
+	lq_sta->rs_sta_dbgfs_rate_scale_data_file =
+		debugfs_create_file("rate_scale_data", 0600, dir,
+			lq_sta, &rs_sta_dbgfs_rate_scale_data_ops);
 	lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
 		debugfs_create_u8("tx_agg_tid_enable", 0600, dir,
 		&lq_sta->tx_agg_tid_en);
@@ -2667,6 +3073,7 @@
 	struct iwl_lq_sta *lq_sta = priv_sta;
 	debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
 	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+	debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file);
 	debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
 }
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h	2009-09-09 18:13:59.000000000 -0400
@@ -241,6 +241,7 @@
 #define IWL_LEGACY_SWITCH_MIMO2_AB      3
 #define IWL_LEGACY_SWITCH_MIMO2_AC      4
 #define IWL_LEGACY_SWITCH_MIMO2_BC      5
+#define IWL_LEGACY_SWITCH_MIMO3_ABC     6
 
 /* possible actions when in siso mode */
 #define IWL_SISO_SWITCH_ANTENNA1        0
@@ -249,6 +250,8 @@
 #define IWL_SISO_SWITCH_MIMO2_AC        3
 #define IWL_SISO_SWITCH_MIMO2_BC        4
 #define IWL_SISO_SWITCH_GI              5
+#define IWL_SISO_SWITCH_MIMO3_ABC       6
+
 
 /* possible actions when in mimo mode */
 #define IWL_MIMO2_SWITCH_ANTENNA1       0
@@ -257,6 +260,23 @@
 #define IWL_MIMO2_SWITCH_SISO_B         3
 #define IWL_MIMO2_SWITCH_SISO_C         4
 #define IWL_MIMO2_SWITCH_GI             5
+#define IWL_MIMO2_SWITCH_MIMO3_ABC      6
+
+
+/* possible actions when in mimo3 mode */
+#define IWL_MIMO3_SWITCH_ANTENNA1       0
+#define IWL_MIMO3_SWITCH_ANTENNA2       1
+#define IWL_MIMO3_SWITCH_SISO_A         2
+#define IWL_MIMO3_SWITCH_SISO_B         3
+#define IWL_MIMO3_SWITCH_SISO_C         4
+#define IWL_MIMO3_SWITCH_MIMO2_AB       5
+#define IWL_MIMO3_SWITCH_MIMO2_AC       6
+#define IWL_MIMO3_SWITCH_MIMO2_BC       7
+#define IWL_MIMO3_SWITCH_GI             8
+
+
+#define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI
+#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC
 
 /*FIXME:RS:add possible actions for MIMO3*/
 
@@ -307,6 +327,13 @@
 #define ANT_BC		(ANT_B | ANT_C)
 #define ANT_ABC		(ANT_AB | ANT_C)
 
+#define IWL_MAX_MCS_DISPLAY_SIZE	12
+
+struct iwl_rate_mcs_info {
+	char	mbps[IWL_MAX_MCS_DISPLAY_SIZE];
+	char	mcs[IWL_MAX_MCS_DISPLAY_SIZE];
+};
+
 static inline u8 num_of_ant(u8 mask)
 {
 	return  !!((mask) & ANT_A) +
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-calib.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-calib.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-calib.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-calib.c	2009-09-09 18:13:59.000000000 -0400
@@ -857,7 +857,7 @@
 		priv->cfg->ops->lib->update_chain_flags(priv);
 
 	data->state = IWL_CHAIN_NOISE_DONE;
-	iwl_power_enable_management(priv);
+	iwl_power_update_mode(priv, 0);
 }
 EXPORT_SYMBOL(iwl_chain_noise_calibration);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h	2009-09-09 18:13:59.000000000 -0400
@@ -614,8 +614,18 @@
 
 #define RXON_FLG_CHANNEL_MODE_POS		(25)
 #define RXON_FLG_CHANNEL_MODE_MSK		cpu_to_le32(0x3 << 25)
-#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK	cpu_to_le32(0x1 << 25)
-#define RXON_FLG_CHANNEL_MODE_MIXED_MSK		cpu_to_le32(0x2 << 25)
+
+/* channel mode */
+enum {
+	CHANNEL_MODE_LEGACY = 0,
+	CHANNEL_MODE_PURE_40 = 1,
+	CHANNEL_MODE_MIXED = 2,
+	CHANNEL_MODE_RESERVED = 3,
+};
+#define RXON_FLG_CHANNEL_MODE_LEGACY	cpu_to_le32(CHANNEL_MODE_LEGACY << RXON_FLG_CHANNEL_MODE_POS)
+#define RXON_FLG_CHANNEL_MODE_PURE_40	cpu_to_le32(CHANNEL_MODE_PURE_40 << RXON_FLG_CHANNEL_MODE_POS)
+#define RXON_FLG_CHANNEL_MODE_MIXED	cpu_to_le32(CHANNEL_MODE_MIXED << RXON_FLG_CHANNEL_MODE_POS)
+
 /* CTS to self (if spec allows) flag */
 #define RXON_FLG_SELF_CTS_EN			cpu_to_le32(0x1<<30)
 
@@ -1057,7 +1067,7 @@
 	 * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
 	__le16 tid_disable_tx;
 
-	__le16	reserved1;
+	__le16	rate_n_flags;		/* 3945 only */
 
 	/* TID for which to add block-ack support.
 	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
@@ -1903,6 +1913,18 @@
 	u8 start_rate_index[LINK_QUAL_AC_NUM];
 } __attribute__ ((packed));
 
+#define LINK_QUAL_AGG_TIME_LIMIT_DEF	(4000) /* 4 milliseconds */
+#define LINK_QUAL_AGG_TIME_LIMIT_MAX	(65535)
+#define LINK_QUAL_AGG_TIME_LIMIT_MIN	(0)
+
+#define LINK_QUAL_AGG_DISABLE_START_DEF	(3)
+#define LINK_QUAL_AGG_DISABLE_START_MAX	(255)
+#define LINK_QUAL_AGG_DISABLE_START_MIN	(0)
+
+#define LINK_QUAL_AGG_FRAME_LIMIT_DEF	(31)
+#define LINK_QUAL_AGG_FRAME_LIMIT_MAX	(64)
+#define LINK_QUAL_AGG_FRAME_LIMIT_MIN	(0)
+
 /**
  * struct iwl_link_qual_agg_params
  *
@@ -2469,11 +2491,12 @@
 	u8 ssid[32];
 } __attribute__ ((packed));
 
-#define PROBE_OPTION_MAX_API1		0x4
-#define PROBE_OPTION_MAX        	0x14
+#define PROBE_OPTION_MAX_3945		4
+#define PROBE_OPTION_MAX		20
 #define TX_CMD_LIFE_TIME_INFINITE	cpu_to_le32(0xFFFFFFFF)
 #define IWL_GOOD_CRC_TH			cpu_to_le16(1)
 #define IWL_MAX_SCAN_SIZE 1024
+#define IWL_MAX_PROBE_REQUEST		200
 
 /*
  * REPLY_SCAN_CMD = 0x80 (command)
@@ -2552,7 +2575,7 @@
 	struct iwl3945_tx_cmd tx_cmd;
 
 	/* For directed active scans (set to all-0s otherwise) */
-	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1];
+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945];
 
 	/*
 	 * Probe request frame, followed by channel list.
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-core.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-core.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2009-09-09 18:13:59.000000000 -0400
@@ -36,9 +36,9 @@
 #include "iwl-debug.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
-#include "iwl-rfkill.h"
 #include "iwl-power.h"
 #include "iwl-sta.h"
+#include "iwl-helpers.h"
 
 
 MODULE_DESCRIPTION("iwl core");
@@ -59,6 +59,8 @@
 				    IWL_RATE_##pp##M_INDEX,    \
 				    IWL_RATE_##np##M_INDEX }
 
+static irqreturn_t iwl_isr(int irq, void *data);
+
 /*
  * Parameter order:
  *   rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
@@ -273,6 +275,14 @@
 }
 EXPORT_SYMBOL(iwl_activate_qos);
 
+/*
+ * AC        CWmin         CW max      AIFSN      TXOP Limit    TXOP Limit
+ *                                              (802.11b)      (802.11a/g)
+ * AC_BK      15            1023        7           0               0
+ * AC_BE      15            1023        3           0               0
+ * AC_VI       7              15        2          6.016ms       3.008ms
+ * AC_VO       3               7        2          3.264ms       1.504ms
+ */
 void iwl_reset_qos(struct iwl_priv *priv)
 {
 	u16 cw_min = 15;
@@ -304,6 +314,7 @@
 	if (priv->qos_data.qos_active)
 		aifs = 3;
 
+	/* AC_BE */
 	priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
 	priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
 	priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
@@ -311,6 +322,7 @@
 	priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
 
 	if (priv->qos_data.qos_active) {
+		/* AC_BK */
 		i = 1;
 		priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
 		priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
@@ -318,11 +330,12 @@
 		priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
 		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
 
+		/* AC_VI */
 		i = 2;
 		priv->qos_data.def_qos_parm.ac[i].cw_min =
 			cpu_to_le16((cw_min + 1) / 2 - 1);
 		priv->qos_data.def_qos_parm.ac[i].cw_max =
-			cpu_to_le16(cw_max);
+			cpu_to_le16(cw_min);
 		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
 		if (is_legacy)
 			priv->qos_data.def_qos_parm.ac[i].edca_txop =
@@ -332,11 +345,12 @@
 				cpu_to_le16(3008);
 		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
 
+		/* AC_VO */
 		i = 3;
 		priv->qos_data.def_qos_parm.ac[i].cw_min =
 			cpu_to_le16((cw_min + 1) / 4 - 1);
 		priv->qos_data.def_qos_parm.ac[i].cw_max =
-			cpu_to_le16((cw_max + 1) / 2 - 1);
+			cpu_to_le16((cw_min + 1) / 2 - 1);
 		priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
 		priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
 		if (is_legacy)
@@ -591,10 +605,10 @@
 
 	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
 		return !(ch_info->fat_extension_channel &
-					IEEE80211_CHAN_NO_FAT_ABOVE);
+					IEEE80211_CHAN_NO_HT40PLUS);
 	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
 		return !(ch_info->fat_extension_channel &
-					IEEE80211_CHAN_NO_FAT_BELOW);
+					IEEE80211_CHAN_NO_HT40MINUS);
 
 	return 0;
 }
@@ -605,19 +619,19 @@
 	struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
 
 	if ((!iwl_ht_conf->is_ht) ||
-	   (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
-	   (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE))
+	    (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ))
 		return 0;
 
+	/* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
+	 * the bit will not set if it is pure 40MHz case
+	 */
 	if (sta_ht_inf) {
-		if ((!sta_ht_inf->ht_supported) ||
-		   (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)))
+		if (!sta_ht_inf->ht_supported)
 			return 0;
 	}
-
 	return iwl_is_channel_extension(priv, priv->band,
-					le16_to_cpu(priv->staging_rxon.channel),
-					iwl_ht_conf->extension_chan_offset);
+			le16_to_cpu(priv->staging_rxon.channel),
+			iwl_ht_conf->extension_chan_offset);
 }
 EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
 
@@ -735,6 +749,8 @@
 	     priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
 	    (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
 	     priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
+	    (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates !=
+	     priv->active_rxon.ofdm_ht_triple_stream_basic_rates) ||
 	    (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
 		return 1;
 
@@ -785,43 +801,62 @@
 void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
 {
 	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
-	u32 val;
 
 	if (!ht_info->is_ht) {
-		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
-			RXON_FLG_CHANNEL_MODE_PURE_40_MSK |
+		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
 			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
 			RXON_FLG_FAT_PROT_MSK |
 			RXON_FLG_HT_PROT_MSK);
 		return;
 	}
 
-	/* Set up channel bandwidth:  20 MHz only, or 20/40 mixed if fat ok */
-	if (iwl_is_fat_tx_allowed(priv, NULL))
-		rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK;
-	else
-		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
-				 RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
+	/* FIXME: if the definition of ht_protection changed, the "translation"
+	 * will be needed for rxon->flags
+	 */
+	rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
 
-	/* Note: control channel is opposite of extension channel */
-	switch (ht_info->extension_chan_offset) {
-	case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-		rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
-		break;
-	case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-		rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
-		break;
-	case IEEE80211_HT_PARAM_CHA_SEC_NONE:
-	default:
-		rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
-		break;
+	/* Set up channel bandwidth:
+	 * 20 MHz only, 20/40 mixed or pure 40 if fat ok */
+	/* clear the HT channel mode before set the mode */
+	rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+			 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+	if (iwl_is_fat_tx_allowed(priv, NULL)) {
+		/* pure 40 fat */
+		if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
+			rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
+			/* Note: control channel is opposite of extension channel */
+			switch (ht_info->extension_chan_offset) {
+			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+				rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+				break;
+			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+				rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+				break;
+			}
+		} else {
+			/* Note: control channel is opposite of extension channel */
+			switch (ht_info->extension_chan_offset) {
+			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+				rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+				rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+				break;
+			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+				rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+				rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+				break;
+			case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+			default:
+				/* channel location only valid if in Mixed mode */
+				IWL_ERR(priv, "invalid extension channel offset\n");
+				break;
+			}
+		}
+	} else {
+		rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
 	}
 
-	val = ht_info->ht_protection;
-
-	rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
-
-	iwl_set_rxon_chain(priv);
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv);
 
 	IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X "
 			"rxon flags 0x%X operation mode :0x%X "
@@ -901,10 +936,11 @@
  * never called for monitor mode. The only way mac80211 informs us about
  * monitor mode is through configuring filters (call to configure_filter).
  */
-static bool iwl_is_monitor_mode(struct iwl_priv *priv)
+bool iwl_is_monitor_mode(struct iwl_priv *priv)
 {
 	return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK);
 }
+EXPORT_SYMBOL(iwl_is_monitor_mode);
 
 /**
  * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
@@ -956,10 +992,10 @@
 	if (iwl_is_monitor_mode(priv) &&
 	    !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) &&
 	    ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) {
-		rx_chain = 0x07 << RXON_RX_CHAIN_VALID_POS;
-		rx_chain |= 0x06 << RXON_RX_CHAIN_FORCE_SEL_POS;
-		rx_chain |= 0x07 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
-		rx_chain |= 0x01 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+		rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS;
+		rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS;
+		rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+		rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
 	}
 
 	priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
@@ -1068,11 +1104,6 @@
 						  RXON_FILTER_ACCEPT_GRP_MSK;
 		break;
 
-	case NL80211_IFTYPE_MONITOR:
-		priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER;
-		priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
-		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
-		break;
 	default:
 		IWL_ERR(priv, "Unsupported interface type %d\n", mode);
 		break;
@@ -1111,16 +1142,18 @@
 	priv->staging_rxon.cck_basic_rates =
 	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
 
-	priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
-					RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
+	/* clear both MIX and PURE40 mode flag */
+	priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
+					RXON_FLG_CHANNEL_MODE_PURE_40);
 	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
 	memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
 	priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
 	priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
+	priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff;
 }
 EXPORT_SYMBOL(iwl_connection_init_rx_config);
 
-void iwl_set_rate(struct iwl_priv *priv)
+static void iwl_set_rate(struct iwl_priv *priv)
 {
 	const struct ieee80211_supported_band *hw = NULL;
 	struct ieee80211_rate *rate;
@@ -1166,7 +1199,6 @@
 		priv->staging_rxon.ofdm_basic_rates =
 		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
 }
-EXPORT_SYMBOL(iwl_set_rate);
 
 void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 {
@@ -1230,11 +1262,6 @@
 		IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
 			  "Restarting adapter due to uCode error.\n");
 
-		if (iwl_is_associated(priv)) {
-			memcpy(&priv->recovery_rxon, &priv->active_rxon,
-			       sizeof(priv->recovery_rxon));
-			priv->error_recovering = 1;
-		}
 		if (priv->cfg->mod_params->restart_fw)
 			queue_work(priv->workqueue, &priv->restart);
 	}
@@ -1298,19 +1325,23 @@
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_NOISE_DBM |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
-		    IEEE80211_HW_SPECTRUM_MGMT |
-		    IEEE80211_HW_SUPPORTS_PS;
+		    IEEE80211_HW_SPECTRUM_MGMT;
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_ADHOC);
 
 	hw->wiphy->custom_regulatory = true;
-	hw->wiphy->max_scan_ssids = 1;
+
+	/* Firmware does not support this */
+	hw->wiphy->disable_beacon_hints = true;
+
+	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
+	/* we create the 802.11 header and a zero-length SSID element */
+	hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
 
 	/* Default value; 4 EDCA QOS priorities */
 	hw->queues = 4;
 
-	hw->conf.beacon_int = 100;
 	hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
 
 	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
@@ -1357,7 +1388,6 @@
 	priv->ibss_beacon = NULL;
 
 	spin_lock_init(&priv->lock);
-	spin_lock_init(&priv->power_data.lock);
 	spin_lock_init(&priv->sta_lock);
 	spin_lock_init(&priv->hcmd_lock);
 
@@ -1378,7 +1408,9 @@
 	priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
 
 	/* Choose which receivers/antennas to use */
-	iwl_set_rxon_chain(priv);
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+
 	iwl_init_scan_params(priv);
 
 	iwl_reset_qos(priv);
@@ -1475,11 +1507,273 @@
 {
 	IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
 	set_bit(STATUS_INT_ENABLED, &priv->status);
-	iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
+	iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
 }
 EXPORT_SYMBOL(iwl_enable_interrupts);
 
-irqreturn_t iwl_isr(int irq, void *data)
+
+#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
+
+/* Free dram table */
+void iwl_free_isr_ict(struct iwl_priv *priv)
+{
+	if (priv->ict_tbl_vir) {
+		pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) +
+					PAGE_SIZE, priv->ict_tbl_vir,
+					priv->ict_tbl_dma);
+		priv->ict_tbl_vir = NULL;
+	}
+}
+EXPORT_SYMBOL(iwl_free_isr_ict);
+
+
+/* allocate dram shared table it is a PAGE_SIZE aligned
+ * also reset all data related to ICT table interrupt.
+ */
+int iwl_alloc_isr_ict(struct iwl_priv *priv)
+{
+
+	if (priv->cfg->use_isr_legacy)
+		return 0;
+	/* allocate shrared data table */
+	priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) *
+						  ICT_COUNT) + PAGE_SIZE,
+						  &priv->ict_tbl_dma);
+	if (!priv->ict_tbl_vir)
+		return -ENOMEM;
+
+	/* align table to PAGE_SIZE boundry */
+	priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE);
+
+	IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
+			     (unsigned long long)priv->ict_tbl_dma,
+			     (unsigned long long)priv->aligned_ict_tbl_dma,
+			(int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
+
+	priv->ict_tbl =  priv->ict_tbl_vir +
+			  (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma);
+
+	IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
+			     priv->ict_tbl, priv->ict_tbl_vir,
+			(int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
+
+	/* reset table and index to all 0 */
+	memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
+	priv->ict_index = 0;
+
+	/* add periodic RX interrupt */
+	priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
+	return 0;
+}
+EXPORT_SYMBOL(iwl_alloc_isr_ict);
+
+/* Device is going up inform it about using ICT interrupt table,
+ * also we need to tell the driver to start using ICT interrupt.
+ */
+int iwl_reset_ict(struct iwl_priv *priv)
+{
+	u32 val;
+	unsigned long flags;
+
+	if (!priv->ict_tbl_vir)
+		return 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_disable_interrupts(priv);
+
+	memset(&priv->ict_tbl[0],0, sizeof(u32) * ICT_COUNT);
+
+	val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
+
+	val |= CSR_DRAM_INT_TBL_ENABLE;
+	val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
+
+	IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
+			"aligned dma address %Lx\n",
+			val, (unsigned long long)priv->aligned_ict_tbl_dma);
+
+	iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
+	priv->use_ict = true;
+	priv->ict_index = 0;
+	iwl_write32(priv, CSR_INT, priv->inta_mask);
+	iwl_enable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_reset_ict);
+
+/* Device is going down disable ict interrupt usage */
+void iwl_disable_ict(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->use_ict = false;
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+EXPORT_SYMBOL(iwl_disable_ict);
+
+/* interrupt handler using ict table, with this interrupt driver will
+ * stop using INTA register to get device's interrupt, reading this register
+ * is expensive, device will write interrupts in ICT dram table, increment
+ * index then will fire interrupt to driver, driver will OR all ICT table
+ * entries from current index up to table entry with 0 value. the result is
+ * the interrupt we need to service, driver will set the entries back to 0 and
+ * set index.
+ */
+irqreturn_t iwl_isr_ict(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+	u32 val = 0;
+
+	if (!priv)
+		return IRQ_NONE;
+
+	/* dram interrupt table not set yet,
+	 * use legacy interrupt.
+	 */
+	if (!priv->use_ict)
+		return iwl_isr(irq, data);
+
+	spin_lock(&priv->lock);
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 * back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here.
+	 */
+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!priv->ict_tbl[priv->ict_index]) {
+		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
+		goto none;
+	}
+
+	/* read all entries that not 0 start with ict_index */
+	while (priv->ict_tbl[priv->ict_index]) {
+
+		val |= priv->ict_tbl[priv->ict_index];
+		IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
+					priv->ict_index,
+					priv->ict_tbl[priv->ict_index]);
+		priv->ict_tbl[priv->ict_index] = 0;
+		priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
+								ICT_COUNT);
+
+	}
+
+	/* We should not get this value, just ignore it. */
+	if (val == 0xffffffff)
+		val = 0;
+
+	inta = (0xff & val) | ((0xff00 & val) << 16);
+	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
+			inta, inta_mask, val);
+
+	inta &= priv->inta_mask;
+	priv->inta |= inta;
+
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta))
+		tasklet_schedule(&priv->irq_tasklet);
+	else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) {
+		/* Allow interrupt if was disabled by this handler and
+		 * no tasklet was schedules, We should not enable interrupt,
+		 * tasklet will enable it.
+		 */
+		iwl_enable_interrupts(priv);
+	}
+
+	spin_unlock(&priv->lock);
+	return IRQ_HANDLED;
+
+ none:
+	/* re-enable interrupts here since we don't have anything to service.
+	 * only Re-enable if disabled by irq.
+	 */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
+		iwl_enable_interrupts(priv);
+
+	spin_unlock(&priv->lock);
+	return IRQ_NONE;
+}
+EXPORT_SYMBOL(iwl_isr_ict);
+
+
+static irqreturn_t iwl_isr(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	u32 inta_fh;
+#endif
+	if (!priv)
+		return IRQ_NONE;
+
+	spin_lock(&priv->lock);
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 *    back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here. */
+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+	/* Discover which interrupts are active/pending */
+	inta = iwl_read32(priv, CSR_INT);
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!inta) {
+		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
+		goto none;
+	}
+
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised
+		 * an interrupt */
+		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+		goto unplugged;
+	}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if (priv->debug_level & (IWL_DL_ISR)) {
+		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+		IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
+			      "fh 0x%08x\n", inta, inta_mask, inta_fh);
+	}
+#endif
+
+	priv->inta |= inta;
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta))
+		tasklet_schedule(&priv->irq_tasklet);
+	else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
+		iwl_enable_interrupts(priv);
+
+ unplugged:
+	spin_unlock(&priv->lock);
+	return IRQ_HANDLED;
+
+ none:
+	/* re-enable interrupts here since we don't have anything to service. */
+	/* only Re-enable if diabled by irq  and no schedules tasklet. */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
+		iwl_enable_interrupts(priv);
+
+	spin_unlock(&priv->lock);
+	return IRQ_NONE;
+}
+
+irqreturn_t iwl_isr_legacy(int irq, void *data)
 {
 	struct iwl_priv *priv = data;
 	u32 inta, inta_mask;
@@ -1536,7 +1830,7 @@
 	spin_unlock(&priv->lock);
 	return IRQ_NONE;
 }
-EXPORT_SYMBOL(iwl_isr);
+EXPORT_SYMBOL(iwl_isr_legacy);
 
 int iwl_send_bt_config(struct iwl_priv *priv)
 {
@@ -1580,10 +1874,6 @@
 
 	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		return ret;
-
 	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
 		/* read data comes through single port, auto-incr addr */
 		/* NOTE: Use the debugless read so we don't flood kernel log
@@ -1599,8 +1889,6 @@
 		}
 	}
 
-	iwl_release_nic_access(priv);
-
 	return ret;
 }
 
@@ -1618,10 +1906,6 @@
 
 	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret)
-		return ret;
-
 	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
 			   IWL49_RTC_INST_LOWER_BOUND);
 
@@ -1642,8 +1926,6 @@
 		}
 	}
 
-	iwl_release_nic_access(priv);
-
 	if (!errcnt)
 		IWL_DEBUG_INFO(priv,
 		    "ucode image in INSTRUCTION memory is good\n");
@@ -1752,7 +2034,6 @@
 	u32 data2, line;
 	u32 desc, time, count, base, data1;
 	u32 blink1, blink2, ilink1, ilink2;
-	int ret;
 
 	if (priv->ucode_type == UCODE_INIT)
 		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
@@ -1764,12 +2045,6 @@
 		return;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		IWL_WARN(priv, "Can not read from adapter at this time.\n");
-		return;
-	}
-
 	count = iwl_read_targ_mem(priv, base);
 
 	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
@@ -1796,7 +2071,6 @@
 	IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
 		ilink1, ilink2);
 
-	iwl_release_nic_access(priv);
 }
 EXPORT_SYMBOL(iwl_dump_nic_error_log);
 
@@ -1805,7 +2079,6 @@
 /**
  * iwl_print_event_log - Dump error event log to syslog
  *
- * NOTE: Must be called with iwl_grab_nic_access() already obtained!
  */
 static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
 				u32 num_events, u32 mode)
@@ -1851,7 +2124,6 @@
 
 void iwl_dump_nic_event_log(struct iwl_priv *priv)
 {
-	int ret;
 	u32 base;       /* SRAM byte address of event log header */
 	u32 capacity;   /* event log capacity in # entries */
 	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
@@ -1869,12 +2141,6 @@
 		return;
 	}
 
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		IWL_WARN(priv, "Can not read from adapter at this time.\n");
-		return;
-	}
-
 	/* event log header */
 	capacity = iwl_read_targ_mem(priv, base);
 	mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
@@ -1886,7 +2152,6 @@
 	/* bail out if nothing in log */
 	if (size == 0) {
 		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-		iwl_release_nic_access(priv);
 		return;
 	}
 
@@ -1901,7 +2166,6 @@
 	/* (then/else) start at top of log */
 	iwl_print_event_log(priv, 0, next_entry, mode);
 
-	iwl_release_nic_access(priv);
 }
 EXPORT_SYMBOL(iwl_dump_nic_event_log);
 
@@ -1954,161 +2218,706 @@
 }
 EXPORT_SYMBOL(iwl_send_card_state);
 
-void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
+void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
+			   struct iwl_rx_mem_buffer *rxb)
 {
-	unsigned long flags;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
+	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
+		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
+#endif
+}
+EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
 
-	if (test_bit(STATUS_RF_KILL_SW, &priv->status))
-		return;
+void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+				      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
+			"notification for %s:\n",
+			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+}
+EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
 
-	IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO OFF\n");
+void iwl_rx_reply_error(struct iwl_priv *priv,
+			struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
-	iwl_scan_cancel(priv);
-	/* FIXME: This is a workaround for AP */
-	if (priv->iw_mode != NL80211_IFTYPE_AP) {
-		spin_lock_irqsave(&priv->lock, flags);
-		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-			    CSR_UCODE_SW_BIT_RFKILL);
-		spin_unlock_irqrestore(&priv->lock, flags);
-		/* call the host command only if no hw rf-kill set */
-		if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
-		    iwl_is_ready(priv))
-			iwl_send_card_state(priv,
-				CARD_STATE_CMD_DISABLE, 0);
-		set_bit(STATUS_RF_KILL_SW, &priv->status);
-			/* make sure mac80211 stop sending Tx frame */
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
-	}
+	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
+		"seq 0x%04X ser 0x%08X\n",
+		le32_to_cpu(pkt->u.err_resp.error_type),
+		get_cmd_string(pkt->u.err_resp.cmd_id),
+		pkt->u.err_resp.cmd_id,
+		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
+		le32_to_cpu(pkt->u.err_resp.error_info));
 }
-EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio);
+EXPORT_SYMBOL(iwl_rx_reply_error);
 
-int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
+void iwl_clear_isr_stats(struct iwl_priv *priv)
+{
+	memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
+}
+EXPORT_SYMBOL(iwl_clear_isr_stats);
+
+int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			   const struct ieee80211_tx_queue_params *params)
 {
+	struct iwl_priv *priv = hw->priv;
 	unsigned long flags;
+	int q;
 
-	if (!test_bit(STATUS_RF_KILL_SW, &priv->status))
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return -EIO;
+	}
+
+	if (queue >= AC_NUM) {
+		IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
 		return 0;
+	}
 
-	IWL_DEBUG_RF_KILL(priv, "Manual SW RF KILL set to: RADIO ON\n");
+	q = AC_NUM - 1 - queue;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
 
-	/* If the driver is up it will receive CARD_STATE_NOTIFICATION
-	 * notification where it will clear SW rfkill status.
-	 * Setting it here would break the handler. Only if the
-	 * interface is down we can set here since we don't
-	 * receive any further notification.
-	 */
-	if (!priv->is_open)
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-	spin_unlock_irqrestore(&priv->lock, flags);
+	priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
+	priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
+	priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
+	priv->qos_data.def_qos_parm.ac[q].edca_txop =
+			cpu_to_le16((params->txop * 32));
 
-	/* wake up ucode */
-	msleep(10);
+	priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+	priv->qos_data.qos_active = 1;
+
+	if (priv->iw_mode == NL80211_IFTYPE_AP)
+		iwl_activate_qos(priv, 1);
+	else if (priv->assoc_id && iwl_is_associated(priv))
+		iwl_activate_qos(priv, 0);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_read32(priv, CSR_UCODE_DRV_GP1);
-	if (!iwl_grab_nic_access(priv))
-		iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-		IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
-				  "disabled by HW switch\n");
-		return 0;
-	}
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
+}
+EXPORT_SYMBOL(iwl_mac_conf_tx);
 
-	/* when driver is up while rfkill is on, it wont receive
-	 * any CARD_STATE_NOTIFICATION notifications so we have to
-	 * restart it in here
+static void iwl_ht_conf(struct iwl_priv *priv,
+			    struct ieee80211_bss_conf *bss_conf)
+{
+	struct ieee80211_sta_ht_cap *ht_conf;
+	struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
+	struct ieee80211_sta *sta;
+
+	IWL_DEBUG_MAC80211(priv, "enter: \n");
+
+	if (!iwl_conf->is_ht)
+		return;
+
+
+	/*
+	 * It is totally wrong to base global information on something
+	 * that is valid only when associated, alas, this driver works
+	 * that way and I don't know how to fix it.
 	 */
-	if (priv->is_open && !test_bit(STATUS_ALIVE, &priv->status)) {
-		clear_bit(STATUS_RF_KILL_SW, &priv->status);
-		if (!iwl_is_rfkill(priv))
-			queue_work(priv->workqueue, &priv->up);
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(priv->hw, priv->bssid);
+	if (!sta) {
+		rcu_read_unlock();
+		return;
 	}
+	ht_conf = &sta->ht_cap;
 
-	/* If the driver is already loaded, it will receive
-	 * CARD_STATE_NOTIFICATION notifications and the handler will
-	 * call restart to reload the driver.
+	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
+		iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
+	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
+		iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
+
+	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
+	iwl_conf->max_amsdu_size =
+		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
+
+	iwl_conf->supported_chan_width =
+		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+
+	/*
+	 * XXX: The HT configuration needs to be moved into iwl_mac_config()
+	 *	to be done there correctly.
 	 */
-	return 1;
+
+	iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+	if (conf_is_ht40_minus(&priv->hw->conf))
+		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+	else if (conf_is_ht40_plus(&priv->hw->conf))
+		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+
+	/* If no above or below channel supplied disable FAT channel */
+	if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
+	    iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
+		iwl_conf->supported_chan_width = 0;
+
+	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
+
+	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
+
+	iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
+	iwl_conf->ht_protection =
+		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+	iwl_conf->non_GF_STA_present =
+		!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+
+	rcu_read_unlock();
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
-EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
 
-void iwl_bg_rf_kill(struct work_struct *work)
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+void iwl_bss_info_changed(struct ieee80211_hw *hw,
+			  struct ieee80211_vif *vif,
+			  struct ieee80211_bss_conf *bss_conf,
+			  u32 changes)
 {
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+	struct iwl_priv *priv = hw->priv;
+	int ret;
 
-	wake_up_interruptible(&priv->wait_command_queue);
+	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+	if (!iwl_is_alive(priv))
 		return;
 
 	mutex_lock(&priv->mutex);
 
-	if (!iwl_is_rfkill(priv)) {
-		IWL_DEBUG_RF_KILL(priv,
-			  "HW and/or SW RF Kill no longer active, restarting "
-			  "device\n");
-		if (!test_bit(STATUS_EXIT_PENDING, &priv->status) &&
-		    test_bit(STATUS_ALIVE, &priv->status))
-			queue_work(priv->workqueue, &priv->restart);
-	} else {
-		/* make sure mac80211 stop sending Tx frame */
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
+	if (changes & BSS_CHANGED_BEACON &&
+	    priv->iw_mode == NL80211_IFTYPE_AP) {
+		dev_kfree_skb(priv->ibss_beacon);
+		priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
+	}
 
-		if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
-			IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
-					  "disabled by SW switch\n");
+	if (changes & BSS_CHANGED_BEACON_INT) {
+		priv->beacon_int = bss_conf->beacon_int;
+		/* TODO: in AP mode, do something to make this take effect */
+	}
+
+	if (changes & BSS_CHANGED_BSSID) {
+		IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
+
+		/*
+		 * If there is currently a HW scan going on in the
+		 * background then we need to cancel it else the RXON
+		 * below/in post_associate will fail.
+		 */
+		if (iwl_scan_cancel_timeout(priv, 100)) {
+			IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
+			IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
+			mutex_unlock(&priv->mutex);
+			return;
+		}
+
+		/* mac80211 only sets assoc when in STATION mode */
+		if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
+		    bss_conf->assoc) {
+			memcpy(priv->staging_rxon.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+
+			/* currently needed in a few places */
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+		} else {
+			priv->staging_rxon.filter_flags &=
+				~RXON_FILTER_ASSOC_MSK;
+		}
+
+	}
+
+	/*
+	 * This needs to be after setting the BSSID in case
+	 * mac80211 decides to do both changes at once because
+	 * it will invoke post_associate.
+	 */
+	if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
+	    changes & BSS_CHANGED_BEACON) {
+		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+
+		if (beacon)
+			iwl_mac_beacon_update(hw, beacon);
+	}
+
+	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
+				   bss_conf->use_short_preamble);
+		if (bss_conf->use_short_preamble)
+			priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 		else
-			IWL_WARN(priv, "Radio Frequency Kill Switch is On:\n"
-				    "Kill switch must be turned off for "
-				    "wireless networking to work.\n");
+			priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+	}
+
+	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
+		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
+			priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+		else
+			priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
 	}
+
+	if (changes & BSS_CHANGED_BASIC_RATES) {
+		/* XXX use this information
+		 *
+		 * To do that, remove code from iwl_set_rate() and put something
+		 * like this here:
+		 *
+		if (A-band)
+			priv->staging_rxon.ofdm_basic_rates =
+				bss_conf->basic_rates;
+		else
+			priv->staging_rxon.ofdm_basic_rates =
+				bss_conf->basic_rates >> 4;
+			priv->staging_rxon.cck_basic_rates =
+				bss_conf->basic_rates & 0xF;
+		 */
+	}
+
+	if (changes & BSS_CHANGED_HT) {
+		iwl_ht_conf(priv, bss_conf);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv);
+	}
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
+		if (bss_conf->assoc) {
+			priv->assoc_id = bss_conf->aid;
+			priv->beacon_int = bss_conf->beacon_int;
+			priv->power_data.dtim_period = bss_conf->dtim_period;
+			priv->timestamp = bss_conf->timestamp;
+			priv->assoc_capability = bss_conf->assoc_capability;
+
+			/*
+			 * We have just associated, don't start scan too early
+			 * leave time for EAPOL exchange to complete.
+			 *
+			 * XXX: do this in mac80211
+			 */
+			priv->next_scan_jiffies = jiffies +
+					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+			if (!iwl_is_rfkill(priv))
+				priv->cfg->ops->lib->post_associate(priv);
+		} else
+			priv->assoc_id = 0;
+
+	}
+
+	if (changes && iwl_is_associated(priv) && priv->assoc_id) {
+		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
+				   changes);
+		ret = iwl_send_rxon_assoc(priv);
+		if (!ret) {
+			/* Sync active_rxon with latest change. */
+			memcpy((void *)&priv->active_rxon,
+				&priv->staging_rxon,
+				sizeof(struct iwl_rxon_cmd));
+		}
+	}
+
 	mutex_unlock(&priv->mutex);
-	iwl_rfkill_set_hw_state(priv);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
-EXPORT_SYMBOL(iwl_bg_rf_kill);
+EXPORT_SYMBOL(iwl_bss_info_changed);
 
-void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
-			   struct iwl_rx_mem_buffer *rxb)
+int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-#ifdef CONFIG_IWLWIFI_DEBUG
-	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
-	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
-		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
-#endif
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	__le64 timestamp;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return -EIO;
+	}
+
+	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
+		IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n");
+		return -EIO;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->ibss_beacon)
+		dev_kfree_skb(priv->ibss_beacon);
+
+	priv->ibss_beacon = skb;
+
+	priv->assoc_id = 0;
+	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+	priv->timestamp = le64_to_cpu(timestamp);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl_reset_qos(priv);
+
+	priv->cfg->ops->lib->post_associate(priv);
+
+
+	return 0;
 }
-EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
+EXPORT_SYMBOL(iwl_mac_beacon_update);
 
-void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-				      struct iwl_rx_mem_buffer *rxb)
+int iwl_set_mode(struct iwl_priv *priv, int mode)
 {
-	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
-			"notification for %s:\n",
-			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
-	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+	if (mode == NL80211_IFTYPE_ADHOC) {
+		const struct iwl_channel_info *ch_info;
+
+		ch_info = iwl_get_channel_info(priv,
+			priv->band,
+			le16_to_cpu(priv->staging_rxon.channel));
+
+		if (!ch_info || !is_channel_ibss(ch_info)) {
+			IWL_ERR(priv, "channel %d not IBSS channel\n",
+				  le16_to_cpu(priv->staging_rxon.channel));
+			return -EINVAL;
+		}
+	}
+
+	iwl_connection_init_rx_config(priv, mode);
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+
+	memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
+
+	iwl_clear_stations_table(priv);
+
+	/* dont commit rxon if rf-kill is on*/
+	if (!iwl_is_ready_rf(priv))
+		return -EAGAIN;
+
+	iwlcore_commit_rxon(priv);
+
+	return 0;
 }
-EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
+EXPORT_SYMBOL(iwl_set_mode);
 
-void iwl_rx_reply_error(struct iwl_priv *priv,
-			struct iwl_rx_mem_buffer *rxb)
+int iwl_mac_add_interface(struct ieee80211_hw *hw,
+				 struct ieee80211_if_init_conf *conf)
 {
-	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
 
-	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
-		"seq 0x%04X ser 0x%08X\n",
-		le32_to_cpu(pkt->u.err_resp.error_type),
-		get_cmd_string(pkt->u.err_resp.cmd_id),
-		pkt->u.err_resp.cmd_id,
-		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
-		le32_to_cpu(pkt->u.err_resp.error_info));
+	IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type);
+
+	if (priv->vif) {
+		IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
+		return -EOPNOTSUPP;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->vif = conf->vif;
+	priv->iw_mode = conf->type;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	mutex_lock(&priv->mutex);
+
+	if (conf->mac_addr) {
+		IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr);
+		memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+	}
+
+	if (iwl_set_mode(priv, conf->type) == -EAGAIN)
+		/* we are not ready, will run again when ready */
+		set_bit(STATUS_MODE_PENDING, &priv->status);
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
 }
-EXPORT_SYMBOL(iwl_rx_reply_error);
+EXPORT_SYMBOL(iwl_mac_add_interface);
 
+void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+				     struct ieee80211_if_init_conf *conf)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	mutex_lock(&priv->mutex);
+
+	if (iwl_is_ready_rf(priv)) {
+		iwl_scan_cancel_timeout(priv, 100);
+		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv);
+	}
+	if (priv->vif == conf->vif) {
+		priv->vif = NULL;
+		memset(priv->bssid, 0, ETH_ALEN);
+	}
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+}
+EXPORT_SYMBOL(iwl_mac_remove_interface);
+
+/**
+ * iwl_mac_config - mac80211 config callback
+ *
+ * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
+ * be set inappropriately and the driver currently sets the hardware up to
+ * use it whenever needed.
+ */
+int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct iwl_priv *priv = hw->priv;
+	const struct iwl_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
+	unsigned long flags = 0;
+	int ret = 0;
+	u16 ch;
+	int scan_active = 0;
+
+	mutex_lock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
+					conf->channel->hw_value, changed);
+
+	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
+			test_bit(STATUS_SCANNING, &priv->status))) {
+		scan_active = 1;
+		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
+	}
+
+
+	/* during scanning mac80211 will delay channel setting until
+	 * scan finish with changed = 0
+	 */
+	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
+		if (scan_active)
+			goto set_ch_out;
+
+		ch = ieee80211_frequency_to_channel(conf->channel->center_freq);
+		ch_info = iwl_get_channel_info(priv, conf->channel->band, ch);
+		if (!is_channel_valid(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
+			ret = -EINVAL;
+			goto set_ch_out;
+		}
+
+		if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
+			!is_channel_ibss(ch_info)) {
+			IWL_ERR(priv, "channel %d in band %d not "
+				"IBSS channel\n",
+				conf->channel->hw_value, conf->channel->band);
+			ret = -EINVAL;
+			goto set_ch_out;
+		}
+
+		priv->current_ht_config.is_ht = conf_is_ht(conf);
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+
+		/* if we are switching from ht to 2.4 clear flags
+		 * from any ht related info since 2.4 does not
+		 * support ht */
+		if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
+			priv->staging_rxon.flags = 0;
+
+		iwl_set_rxon_channel(priv, conf->channel);
+
+		iwl_set_flags_for_band(priv, conf->channel->band);
+		spin_unlock_irqrestore(&priv->lock, flags);
+ set_ch_out:
+		/* The list of supported rates and rate mask can be different
+		 * for each band; since the band may have changed, reset
+		 * the rate mask to what mac80211 lists */
+		iwl_set_rate(priv);
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_PS &&
+	    priv->iw_mode == NL80211_IFTYPE_STATION) {
+		priv->power_data.power_disabled =
+			!(conf->flags & IEEE80211_CONF_PS);
+		ret = iwl_power_update_mode(priv, 0);
+		if (ret)
+			IWL_DEBUG_MAC80211(priv, "Error setting power level\n");
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
+			priv->tx_power_user_lmt, conf->power_level);
+
+		iwl_set_tx_power(priv, conf->power_level, false);
+	}
+
+	/* call to ensure that 4965 rx_chain is set properly in monitor mode */
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv);
+
+	if (!iwl_is_ready(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		goto out;
+	}
+
+	if (scan_active)
+		goto out;
+
+	if (memcmp(&priv->active_rxon,
+		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
+		iwlcore_commit_rxon(priv);
+	else
+		IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n");
+
+
+out:
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_mac_config);
+
+int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
+			 struct ieee80211_tx_queue_stats *stats)
+{
+	struct iwl_priv *priv = hw->priv;
+	int i, avail;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	unsigned long flags;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return -EIO;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	for (i = 0; i < AC_NUM; i++) {
+		txq = &priv->txq[i];
+		q = &txq->q;
+		avail = iwl_queue_space(q);
+
+		stats[i].len = q->n_window - avail;
+		stats[i].limit = q->n_window - q->high_mark;
+		stats[i].count = q->n_window;
+
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_mac_get_tx_stats);
+
+void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	spin_lock_irqsave(&priv->lock, flags);
+	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl_reset_qos(priv);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->assoc_id = 0;
+	priv->assoc_capability = 0;
+	priv->assoc_station_added = 0;
+
+	/* new association get rid of ibss beacon skb */
+	if (priv->ibss_beacon)
+		dev_kfree_skb(priv->ibss_beacon);
+
+	priv->ibss_beacon = NULL;
+
+	priv->beacon_int = priv->vif->bss_conf.beacon_int;
+	priv->timestamp = 0;
+	if ((priv->iw_mode == NL80211_IFTYPE_STATION))
+		priv->beacon_int = 0;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	/* we are restarting association process
+	 * clear RXON_FILTER_ASSOC_MSK bit
+	 */
+	if (priv->iw_mode != NL80211_IFTYPE_AP) {
+		iwl_scan_cancel_timeout(priv, 100);
+		priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv);
+	}
+
+	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
+		IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n");
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	iwl_set_rate(priv);
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_mac_reset_tsf);
+
+#ifdef CONFIG_PM
+
+int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+	/*
+	 * This function is called when system goes into suspend state
+	 * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
+	 * first but since iwl_mac_stop() has no knowledge of who the caller is,
+	 * it will not call apm_ops.stop() to stop the DMA operation.
+	 * Calling apm_ops.stop here to make sure we stop the DMA.
+	 */
+	priv->cfg->ops->lib->apm_ops.stop(priv);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_pci_suspend);
+
+int iwl_pci_resume(struct pci_dev *pdev)
+{
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+	pci_restore_state(pdev);
+	iwl_enable_interrupts(priv);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_pci_resume);
+
+#endif /* CONFIG_PM */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-core.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-core.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-core.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-core.h	2009-09-09 18:13:59.000000000 -0400
@@ -85,7 +85,10 @@
 
 struct iwl_hcmd_ops {
 	int (*rxon_assoc)(struct iwl_priv *priv);
+	int (*commit_rxon)(struct iwl_priv *priv);
+	void (*set_rxon_chain)(struct iwl_priv *priv);
 };
+
 struct iwl_hcmd_utils_ops {
 	u16 (*get_hcmd_size)(u8 cmd_id, u16 len);
 	u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data);
@@ -100,6 +103,19 @@
 			  struct iwl_rx_phy_res *rx_resp);
 };
 
+struct iwl_apm_ops {
+	int (*init)(struct iwl_priv *priv);
+	int (*reset)(struct iwl_priv *priv);
+	void (*stop)(struct iwl_priv *priv);
+	void (*config)(struct iwl_priv *priv);
+	int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
+};
+
+struct iwl_temp_ops {
+	void (*temperature)(struct iwl_priv *priv);
+	void (*set_ct_kill)(struct iwl_priv *priv);
+};
+
 struct iwl_lib_ops {
 	/* set hw dependent parameters */
 	int (*set_hw_params)(struct iwl_priv *priv);
@@ -137,20 +153,21 @@
 	int (*is_valid_rtc_data_addr)(u32 addr);
 	/* 1st ucode load */
 	int (*load_ucode)(struct iwl_priv *priv);
-	 /* power management */
-	struct {
-		int (*init)(struct iwl_priv *priv);
-		int (*reset)(struct iwl_priv *priv);
-		void (*stop)(struct iwl_priv *priv);
-		void (*config)(struct iwl_priv *priv);
-		int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
-	} apm_ops;
+	/* power management */
+	struct iwl_apm_ops apm_ops;
+
 	/* power */
 	int (*send_tx_power) (struct iwl_priv *priv);
 	void (*update_chain_flags)(struct iwl_priv *priv);
-	void (*temperature) (struct iwl_priv *priv);
+	void (*post_associate) (struct iwl_priv *priv);
+	void (*config_ap) (struct iwl_priv *priv);
+	irqreturn_t (*isr) (int irq, void *data);
+
 	/* eeprom operations (as defined in iwl-eeprom.h) */
 	struct iwl_eeprom_ops eeprom_ops;
+
+	/* temperature */
+	struct iwl_temp_ops temp_ops;
 };
 
 struct iwl_ops {
@@ -160,13 +177,12 @@
 };
 
 struct iwl_mod_params {
-	int disable;		/* def: 0 = enable radio */
 	int sw_crypto;		/* def: 0 = using hardware encryption */
 	u32 debug;		/* def: 0 = minimal debug log messages */
 	int disable_hw_scan;	/* def: 0 = use h/w scan */
 	int num_of_queues;	/* def: HW dependent */
 	int num_of_ampdu_queues;/* def: HW dependent */
-	int disable_11n;	/* def: 0 = disable 11n capabilities */
+	int disable_11n;	/* def: 0 = 11n capabilities enabled */
 	int amsdu_size_8K;	/* def: 1 = enable 8K amsdu size */
 	int antenna;  		/* def: 0 = both antennas (use diversity) */
 	int restart_fw;		/* def: 1 = restart firmware */
@@ -214,6 +230,7 @@
 	u8   valid_tx_ant;
 	u8   valid_rx_ant;
 	bool need_pll_cfg;
+	bool use_isr_legacy;
 };
 
 /***************************
@@ -225,6 +242,8 @@
 void iwl_hw_detect(struct iwl_priv *priv);
 void iwl_reset_qos(struct iwl_priv *priv);
 void iwl_activate_qos(struct iwl_priv *priv, u8 force);
+int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+		    const struct ieee80211_tx_queue_params *params);
 void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt);
 int iwl_check_rxon_cmd(struct iwl_priv *priv);
 int iwl_full_rxon_required(struct iwl_priv *priv);
@@ -249,6 +268,24 @@
 int iwl_set_hw_params(struct iwl_priv *priv);
 int iwl_init_drv(struct iwl_priv *priv);
 void iwl_uninit_drv(struct iwl_priv *priv);
+bool iwl_is_monitor_mode(struct iwl_priv *priv);
+void iwl_post_associate(struct iwl_priv *priv);
+void iwl_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes);
+int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
+int iwl_commit_rxon(struct iwl_priv *priv);
+int iwl_set_mode(struct iwl_priv *priv, int mode);
+int iwl_mac_add_interface(struct ieee80211_hw *hw,
+				 struct ieee80211_if_init_conf *conf);
+void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+				 struct ieee80211_if_init_conf *conf);
+int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
+void iwl_config_ap(struct iwl_priv *priv);
+int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
+			 struct ieee80211_tx_queue_stats *stats);
+void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
 
 /*****************************************************
  * RX handlers.
@@ -271,10 +308,11 @@
 				  struct iwl_rx_queue *q);
 void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
 void iwl_rx_replenish(struct iwl_priv *priv);
+void iwl_rx_replenish_now(struct iwl_priv *priv);
 int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
 int iwl_rx_queue_restock(struct iwl_priv *priv);
 int iwl_rx_queue_space(const struct iwl_rx_queue *q);
-void iwl_rx_allocate(struct iwl_priv *priv);
+void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority);
 void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
 /* Handlers */
@@ -310,14 +348,6 @@
  ****************************************************/
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
 
-/*****************************************************
- * RF -Kill - here and not in iwl-rfkill.h to be available when
- * RF-kill subsystem is not compiled.
- ****************************************************/
-void iwl_bg_rf_kill(struct work_struct *work);
-void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
-int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);
-
 /*******************************************************************************
  * Rate
  ******************************************************************************/
@@ -328,8 +358,6 @@
 
 u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);
 
-void iwl_set_rate(struct iwl_priv *priv);
-
 u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx);
 
 static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
@@ -358,8 +386,8 @@
 int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
 int iwl_scan_initiate(struct iwl_priv *priv);
 int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
-u16 iwl_fill_probe_req(struct iwl_priv *priv, enum ieee80211_band band,
-		       struct ieee80211_mgmt *frame, int left);
+u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
+		       const u8 *ie, int ie_len, int left);
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
 u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
 			      enum ieee80211_band band,
@@ -423,7 +451,13 @@
  *****************************************************/
 void iwl_disable_interrupts(struct iwl_priv *priv);
 void iwl_enable_interrupts(struct iwl_priv *priv);
-irqreturn_t iwl_isr(int irq, void *data);
+irqreturn_t iwl_isr_legacy(int irq, void *data);
+int iwl_reset_ict(struct iwl_priv *priv);
+void iwl_disable_ict(struct iwl_priv *priv);
+int iwl_alloc_isr_ict(struct iwl_priv *priv);
+void iwl_free_isr_ict(struct iwl_priv *priv);
+irqreturn_t iwl_isr_ict(int irq, void *data);
+
 static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
 {
 	int pos;
@@ -432,12 +466,17 @@
 	pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
 	return pci_lnk_ctl;
 }
+#ifdef CONFIG_PM
+int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
+int iwl_pci_resume(struct pci_dev *pdev);
+#endif /* CONFIG_PM */
 
 /*****************************************************
 *  Error Handling Debugging
 ******************************************************/
 void iwl_dump_nic_error_log(struct iwl_priv *priv);
 void iwl_dump_nic_event_log(struct iwl_priv *priv);
+void iwl_clear_isr_stats(struct iwl_priv *priv);
 
 /*****************************************************
 *  GEOS
@@ -451,14 +490,12 @@
 #define STATUS_HCMD_SYNC_ACTIVE	1	/* sync host command in progress */
 #define STATUS_INT_ENABLED	2
 #define STATUS_RF_KILL_HW	3
-#define STATUS_RF_KILL_SW	4
 #define STATUS_INIT		5
 #define STATUS_ALIVE		6
 #define STATUS_READY		7
 #define STATUS_TEMPERATURE	8
 #define STATUS_GEO_CONFIGURED	9
 #define STATUS_EXIT_PENDING	10
-#define STATUS_IN_SUSPEND	11
 #define STATUS_STATISTICS	12
 #define STATUS_SCANNING		13
 #define STATUS_SCAN_ABORTING	14
@@ -487,11 +524,6 @@
 	return test_bit(STATUS_INIT, &priv->status);
 }
 
-static inline int iwl_is_rfkill_sw(struct iwl_priv *priv)
-{
-	return test_bit(STATUS_RF_KILL_SW, &priv->status);
-}
-
 static inline int iwl_is_rfkill_hw(struct iwl_priv *priv)
 {
 	return test_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -499,7 +531,7 @@
 
 static inline int iwl_is_rfkill(struct iwl_priv *priv)
 {
-	return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv);
+	return iwl_is_rfkill_hw(priv);
 }
 
 static inline int iwl_is_ready_rf(struct iwl_priv *priv)
@@ -528,7 +560,14 @@
 {
 	return priv->cfg->ops->hcmd->rxon_assoc(priv);
 }
-
+static inline int iwlcore_commit_rxon(struct iwl_priv *priv)
+{
+	return priv->cfg->ops->hcmd->commit_rxon(priv);
+}
+static inline void iwlcore_config_ap(struct iwl_priv *priv)
+{
+	priv->cfg->ops->lib->config_ap(priv);
+}
 static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
 			struct iwl_priv *priv, enum ieee80211_band band)
 {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h	2009-09-09 18:13:59.000000000 -0400
@@ -89,6 +89,7 @@
 /* EEPROM reads */
 #define CSR_EEPROM_REG          (CSR_BASE+0x02c)
 #define CSR_EEPROM_GP           (CSR_BASE+0x030)
+#define CSR_OTP_GP_REG   	(CSR_BASE+0x034)
 #define CSR_GIO_REG		(CSR_BASE+0x03C)
 #define CSR_GP_UCODE		(CSR_BASE+0x044)
 #define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
@@ -96,8 +97,10 @@
 #define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
 #define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
 #define CSR_LED_REG             (CSR_BASE+0x094)
+#define CSR_DRAM_INT_TBL_REG	(CSR_BASE+0x0A0)
 #define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
 
+#define CSR_INT_PERIODIC_REG	(CSR_BASE+0x005)
 /* Analog phase-lock-loop configuration  */
 #define CSR_ANA_PLL_CFG         (CSR_BASE+0x20c)
 /*
@@ -123,16 +126,18 @@
 
 #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A		(0x00080000)
 #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM		(0x00200000)
-#define CSR_HW_IF_CONFIG_REG_BIT_PCI_OWN_SEM		(0x00400000)
-#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN			(0x02000000)
-#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME		(0x08000000)
+#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY		(0x00400000)
+#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE	(0x02000000)
+#define CSR_HW_IF_CONFIG_REG_PREPARE			(0x08000000)
 
+#define CSR_INT_PERIODIC_DIS			(0x00)
+#define CSR_INT_PERIODIC_ENA			(0xFF)
 
 /* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
  * acknowledged (reset) by host writing "1" to flagged bits. */
 #define CSR_INT_BIT_FH_RX        (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
 #define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
-#define CSR_INT_BIT_DNLD         (1 << 28) /* uCode Download */
+#define CSR_INT_BIT_RX_PERIODIC	 (1 << 28) /* Rx periodic */
 #define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
 #define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
 #define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
@@ -226,6 +231,10 @@
 #define CSR_EEPROM_GP_VALID_MSK		(0x00000007)
 #define CSR_EEPROM_GP_BAD_SIGNATURE	(0x00000000)
 #define CSR_EEPROM_GP_IF_OWNER_MSK	(0x00000180)
+#define CSR_OTP_GP_REG_DEVICE_SELECT	(0x00010000) /* 0 - EEPROM, 1 - OTP */
+#define CSR_OTP_GP_REG_OTP_ACCESS_MODE	(0x00020000) /* 0 - absolute, 1 - relative */
+#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK          (0x00100000) /* bit 20 */
+#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK        (0x00200000) /* bit 21 */
 
 /* CSR GIO */
 #define CSR_GIO_REG_VAL_L0S_ENABLED	(0x00000002)
@@ -251,6 +260,11 @@
 
 /* HPET MEM debug */
 #define CSR_DBG_HPET_MEM_REG_VAL	(0xFFFF0000)
+
+/* DRAM INT TABLE */
+#define CSR_DRAM_INT_TBL_ENABLE		(1 << 31)
+#define CSR_DRAM_INIT_TBL_WRAP_CHECK	(1 << 27)
+
 /*=== HBUS (Host-side Bus) ===*/
 #define HBUS_BASE	(0x400)
 /*
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -172,7 +172,6 @@
 	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 	const size_t bufsz = sizeof(buf);
 
-	iwl_grab_nic_access(priv);
 	for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
 		val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
 					priv->dbgfs->sram_len - i);
@@ -192,7 +191,6 @@
 		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
 	}
 	pos += scnprintf(buf + pos, bufsz - pos, "\n");
-	iwl_release_nic_access(priv);
 
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	return ret;
@@ -292,7 +290,7 @@
 	return ret;
 }
 
-static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
+static ssize_t iwl_dbgfs_nvm_read(struct file *file,
 				       char __user *user_buf,
 				       size_t count,
 				       loff_t *ppos)
@@ -306,18 +304,25 @@
 	buf_size = 4 * eeprom_len + 256;
 
 	if (eeprom_len % 16) {
-		IWL_ERR(priv, "EEPROM size is not multiple of 16.\n");
+		IWL_ERR(priv, "NVM size is not multiple of 16.\n");
 		return -ENODATA;
 	}
 
+	ptr = priv->eeprom;
+	if (!ptr) {
+		IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
+		return -ENOMEM;
+	}
+
 	/* 4 characters for byte 0xYY */
 	buf = kzalloc(buf_size, GFP_KERNEL);
 	if (!buf) {
 		IWL_ERR(priv, "Can not allocate Buffer\n");
 		return -ENOMEM;
 	}
-
-	ptr = priv->eeprom;
+	pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
+			(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
+			? "OTP" : "EEPROM");
 	for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
 		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
 		hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
@@ -375,51 +380,53 @@
 	}
 
 	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
-	channels = supp_band->channels;
-
-	pos += scnprintf(buf + pos, bufsz - pos,
-			"Displaying %d channels in 2.4GHz band 802.11bg):\n",
-			 supp_band->n_channels);
+	if (supp_band) {
+		channels = supp_band->channels;
 
-	for (i = 0; i < supp_band->n_channels; i++)
 		pos += scnprintf(buf + pos, bufsz - pos,
-				"%d: %ddBm: BSS%s%s, %s.\n",
-				ieee80211_frequency_to_channel(
-				channels[i].center_freq),
-				channels[i].max_power,
-				channels[i].flags & IEEE80211_CHAN_RADAR ?
-				" (IEEE 802.11h required)" : "",
-				(!(channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-				|| (channels[i].flags &
-				IEEE80211_CHAN_RADAR)) ? "" :
-				", IBSS",
-				channels[i].flags &
-				IEEE80211_CHAN_PASSIVE_SCAN ?
-				"passive only" : "active/passive");
+				"Displaying %d channels in 2.4GHz band 802.11bg):\n",
+				supp_band->n_channels);
 
+		for (i = 0; i < supp_band->n_channels; i++)
+			pos += scnprintf(buf + pos, bufsz - pos,
+					"%d: %ddBm: BSS%s%s, %s.\n",
+					ieee80211_frequency_to_channel(
+					channels[i].center_freq),
+					channels[i].max_power,
+					channels[i].flags & IEEE80211_CHAN_RADAR ?
+					" (IEEE 802.11h required)" : "",
+					((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+					|| (channels[i].flags &
+					IEEE80211_CHAN_RADAR)) ? "" :
+					", IBSS",
+					channels[i].flags &
+					IEEE80211_CHAN_PASSIVE_SCAN ?
+					"passive only" : "active/passive");
+	}
 	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
-	channels = supp_band->channels;
-
-	pos += scnprintf(buf + pos, bufsz - pos,
-			"Displaying %d channels in 5.2GHz band (802.11a)\n",
-			supp_band->n_channels);
+	if (supp_band) {
+		channels = supp_band->channels;
 
-	for (i = 0; i < supp_band->n_channels; i++)
 		pos += scnprintf(buf + pos, bufsz - pos,
-				"%d: %ddBm: BSS%s%s, %s.\n",
-				ieee80211_frequency_to_channel(
-				channels[i].center_freq),
-				channels[i].max_power,
-				channels[i].flags & IEEE80211_CHAN_RADAR ?
-				" (IEEE 802.11h required)" : "",
-				((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-				|| (channels[i].flags &
-				IEEE80211_CHAN_RADAR)) ? "" :
-				", IBSS",
-				channels[i].flags &
-				IEEE80211_CHAN_PASSIVE_SCAN ?
-				"passive only" : "active/passive");
+				"Displaying %d channels in 5.2GHz band (802.11a)\n",
+				supp_band->n_channels);
 
+		for (i = 0; i < supp_band->n_channels; i++)
+			pos += scnprintf(buf + pos, bufsz - pos,
+					"%d: %ddBm: BSS%s%s, %s.\n",
+					ieee80211_frequency_to_channel(
+					channels[i].center_freq),
+					channels[i].max_power,
+					channels[i].flags & IEEE80211_CHAN_RADAR ?
+					" (IEEE 802.11h required)" : "",
+					((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+					|| (channels[i].flags &
+					IEEE80211_CHAN_RADAR)) ? "" :
+					", IBSS",
+					channels[i].flags &
+					IEEE80211_CHAN_PASSIVE_SCAN ?
+					"passive only" : "active/passive");
+	}
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
 	return ret;
@@ -442,8 +449,6 @@
 		test_bit(STATUS_INT_ENABLED, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
 		test_bit(STATUS_RF_KILL_HW, &priv->status));
-	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_SW:\t %d\n",
-		test_bit(STATUS_RF_KILL_SW, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
 		test_bit(STATUS_INIT, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
@@ -456,8 +461,6 @@
 		test_bit(STATUS_GEO_CONFIGURED, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
 		test_bit(STATUS_EXIT_PENDING, &priv->status));
-	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n",
-		test_bit(STATUS_IN_SUSPEND, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
 		test_bit(STATUS_STATISTICS, &priv->status));
 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
@@ -475,14 +478,104 @@
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
+static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+	int pos = 0;
+	int cnt = 0;
+	char *buf;
+	int bufsz = 24 * 64; /* 24 items * 64 char per item */
+	ssize_t ret;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"Interrupt Statistics Report:\n");
+
+	pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
+		priv->isr_stats.hw);
+	pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
+		priv->isr_stats.sw);
+	if (priv->isr_stats.sw > 0) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+			"\tLast Restarting Code:  0x%X\n",
+			priv->isr_stats.sw_err);
+	}
+#ifdef CONFIG_IWLWIFI_DEBUG
+	pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
+		priv->isr_stats.sch);
+	pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
+		priv->isr_stats.alive);
+#endif
+	pos += scnprintf(buf + pos, bufsz - pos,
+		"HW RF KILL switch toggled:\t %u\n",
+		priv->isr_stats.rfkill);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
+		priv->isr_stats.ctkill);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
+		priv->isr_stats.wakeup);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+		"Rx command responses:\t\t %u\n",
+		priv->isr_stats.rx);
+	for (cnt = 0; cnt < REPLY_MAX; cnt++) {
+		if (priv->isr_stats.rx_handlers[cnt] > 0)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"\tRx handler[%36s]:\t\t %u\n",
+				get_cmd_string(cnt),
+				priv->isr_stats.rx_handlers[cnt]);
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
+		priv->isr_stats.tx);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
+		priv->isr_stats.unhandled);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	u32 reset_flag;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%x", &reset_flag) != 1)
+		return -EFAULT;
+	if (reset_flag == 0)
+		iwl_clear_isr_stats(priv);
+
+	return count;
+}
+
+
 DEBUGFS_READ_WRITE_FILE_OPS(sram);
 DEBUGFS_WRITE_FILE_OPS(log_event);
-DEBUGFS_READ_FILE_OPS(eeprom);
+DEBUGFS_READ_FILE_OPS(nvm);
 DEBUGFS_READ_FILE_OPS(stations);
 DEBUGFS_READ_FILE_OPS(rx_statistics);
 DEBUGFS_READ_FILE_OPS(tx_statistics);
 DEBUGFS_READ_FILE_OPS(channels);
 DEBUGFS_READ_FILE_OPS(status);
+DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 
 /*
  * Create the debugfs files and directories
@@ -510,7 +603,7 @@
 
 	DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
 	DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
-	DEBUGFS_ADD_FILE(eeprom, data);
+	DEBUGFS_ADD_FILE(nvm, data);
 	DEBUGFS_ADD_FILE(sram, data);
 	DEBUGFS_ADD_FILE(log_event, data);
 	DEBUGFS_ADD_FILE(stations, data);
@@ -518,6 +611,7 @@
 	DEBUGFS_ADD_FILE(tx_statistics, data);
 	DEBUGFS_ADD_FILE(channels, data);
 	DEBUGFS_ADD_FILE(status, data);
+	DEBUGFS_ADD_FILE(interrupt, data);
 	DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
 	DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
 			 &priv->disable_chain_noise_cal);
@@ -540,7 +634,7 @@
 	if (!priv->dbgfs)
 		return;
 
-	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
@@ -548,6 +642,7 @@
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
+	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
 	DEBUGFS_REMOVE(priv->dbgfs->dir_data);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
 	DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-debug.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-debug.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-debug.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-debug.h	2009-09-09 18:13:59.000000000 -0400
@@ -68,13 +68,14 @@
 	struct dentry *dir_rf;
 	struct dir_data_files {
 		struct dentry *file_sram;
-		struct dentry *file_eeprom;
+		struct dentry *file_nvm;
 		struct dentry *file_stations;
 		struct dentry *file_rx_statistics;
 		struct dentry *file_tx_statistics;
 		struct dentry *file_log_event;
 		struct dentry *file_channels;
 		struct dentry *file_status;
+		struct dentry *file_interrupt;
 	} dbgfs_data_files;
 	struct dir_rf_files {
 		struct dentry *file_disable_sensitivity;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-09-09 18:13:59.000000000 -0400
@@ -41,7 +41,6 @@
 #include "iwl-prph.h"
 #include "iwl-fh.h"
 #include "iwl-debug.h"
-#include "iwl-rfkill.h"
 #include "iwl-4965-hw.h"
 #include "iwl-3945-hw.h"
 #include "iwl-3945-led.h"
@@ -259,8 +258,10 @@
 #define IWL_TX_FIFO_HCCA_2	6
 #define IWL_TX_FIFO_NONE	7
 
-/* Minimum number of queues. MAX_NUM is defined in hw specific files */
-#define IWL_MIN_NUM_QUEUES	4
+/* Minimum number of queues. MAX_NUM is defined in hw specific files.
+ * Set the minimum to accommodate the 4 standard TX queues, 1 command
+ * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */
+#define IWL_MIN_NUM_QUEUES	10
 
 /* Power management (not Tx power) structures */
 
@@ -289,11 +290,11 @@
 #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
 
 enum {
-	/* CMD_SIZE_NORMAL = 0, */
+	CMD_SYNC = 0,
+	CMD_SIZE_NORMAL = 0,
+	CMD_NO_SKB = 0,
 	CMD_SIZE_HUGE = (1 << 0),
-	/* CMD_SYNC = 0, */
 	CMD_ASYNC = (1 << 1),
-	/* CMD_NO_SKB = 0, */
 	CMD_WANT_SKB = (1 << 2),
 };
 
@@ -381,6 +382,7 @@
 	u32 read;
 	u32 write;
 	u32 free_count;
+	u32 write_actual;
 	struct list_head rx_free;
 	struct list_head rx_used;
 	int need_update;
@@ -498,22 +500,13 @@
 #define STA_PS_STATUS_WAKE             0
 #define STA_PS_STATUS_SLEEP            1
 
-struct iwl3945_tid_data {
-	u16 seq_number;
-};
-
-struct iwl3945_hw_key {
-	enum ieee80211_key_alg alg;
-	int keylen;
-	u8 key[32];
-};
 
 struct iwl3945_station_entry {
 	struct iwl3945_addsta_cmd sta;
-	struct iwl3945_tid_data tid[MAX_TID_COUNT];
+	struct iwl_tid_data tid[MAX_TID_COUNT];
 	u8 used;
 	u8 ps_status;
-	struct iwl3945_hw_key keyinfo;
+	struct iwl_hw_key keyinfo;
 };
 
 struct iwl_station_entry {
@@ -822,6 +815,26 @@
 	MEASUREMENT_ACTIVE = (1 << 1),
 };
 
+enum iwl_nvm_type {
+	NVM_DEVICE_TYPE_EEPROM = 0,
+	NVM_DEVICE_TYPE_OTP,
+};
+
+/* interrupt statistics */
+struct isr_statistics {
+	u32 hw;
+	u32 sw;
+	u32 sw_err;
+	u32 sch;
+	u32 alive;
+	u32 rfkill;
+	u32 ctkill;
+	u32 wakeup;
+	u32 rx;
+	u32 rx_handlers[REPLY_MAX];
+	u32 tx;
+	u32 unhandled;
+};
 
 #define IWL_MAX_NUM_QUEUES	20 /* FIXME: do dynamic allocation */
 
@@ -877,15 +890,14 @@
 	unsigned long scan_start_tsf;
 	void *scan;
 	int scan_bands;
-	int one_direct_scan;
-	u8 direct_ssid_len;
-	u8 direct_ssid[IW_ESSID_MAX_SIZE];
+	struct cfg80211_scan_request *scan_request;
 	u8 scan_tx_ant[IEEE80211_NUM_BANDS];
 	u8 mgmt_tx_ant;
 
 	/* spinlock */
 	spinlock_t lock;	/* protect general shared data */
 	spinlock_t hcmd_lock;	/* protect hcmd */
+	spinlock_t reg_lock;	/* protect hw register access */
 	struct mutex mutex;
 
 	/* basic pci-network driver stuff */
@@ -919,16 +931,12 @@
 	const struct iwl_rxon_cmd active_rxon;
 	struct iwl_rxon_cmd staging_rxon;
 
-	int error_recovering;
 	struct iwl_rxon_cmd recovery_rxon;
 
 	/* 1st responses from initialize and runtime uCode images.
 	 * 4965's initialize alive response contains some calibration data. */
 	struct iwl_init_alive_resp card_alive_init;
 	struct iwl_alive_resp card_alive;
-#if defined(CONFIG_IWLWIFI_RFKILL)
-	struct rfkill *rfkill;
-#endif
 
 #ifdef CONFIG_IWLWIFI_LEDS
 	unsigned long last_blink_time;
@@ -978,6 +986,9 @@
 		u64 bytes;
 	} tx_stats[3], rx_stats[3];
 
+	/* counts interrupts */
+	struct isr_statistics isr_stats;
+
 	struct iwl_power_mgr power_data;
 
 	struct iwl_notif_statistics statistics;
@@ -1017,6 +1028,7 @@
 
 	/* eeprom */
 	u8 *eeprom;
+	int    nvm_device_type;
 	struct iwl_eeprom_calib_info *calib_info;
 
 	enum nl80211_iftype iw_mode;
@@ -1034,7 +1046,16 @@
 	/*End*/
 	struct iwl_hw_params hw_params;
 
+	/* INT ICT Table */
+	u32 *ict_tbl;
+	dma_addr_t ict_tbl_dma;
+	dma_addr_t aligned_ict_tbl_dma;
+	int ict_index;
+	void *ict_tbl_vir;
+	u32 inta;
+	bool use_ict;
 
+	u32 inta_mask;
 	/* Current association information needed to configure the
 	 * hardware */
 	u16 assoc_id;
@@ -1049,7 +1070,6 @@
 	struct work_struct calibrated_work;
 	struct work_struct scan_completed;
 	struct work_struct rx_replenish;
-	struct work_struct rf_kill;
 	struct work_struct abort_scan;
 	struct work_struct update_link_led;
 	struct work_struct auth_work;
@@ -1059,7 +1079,6 @@
 
 	struct tasklet_struct irq_tasklet;
 
-	struct delayed_work set_power_save;
 	struct delayed_work init_alive_start;
 	struct delayed_work alive_start;
 	struct delayed_work scan_check;
@@ -1090,14 +1109,12 @@
 	u32 disable_tx_power_cal;
 	struct work_struct run_time_calib_work;
 	struct timer_list statistics_periodic;
-
+	bool hw_ready;
 	/*For 3945*/
 #define IWL_DEFAULT_TX_POWER 0x0F
 
 	struct iwl3945_notif_statistics statistics_39;
 
-	struct iwl3945_station_entry stations_39[IWL_STATION_COUNT];
-
 	u32 sta_supp_rates;
 }; /*iwl_priv */
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2009-09-09 18:13:59.000000000 -0400
@@ -152,6 +152,32 @@
 }
 EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
 
+static int iwlcore_get_nvm_type(struct iwl_priv *priv)
+{
+	u32 otpgp;
+	int nvm_type;
+
+	/* OTP only valid for CP/PP and after */
+	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+	case CSR_HW_REV_TYPE_3945:
+	case CSR_HW_REV_TYPE_4965:
+	case CSR_HW_REV_TYPE_5300:
+	case CSR_HW_REV_TYPE_5350:
+	case CSR_HW_REV_TYPE_5100:
+	case CSR_HW_REV_TYPE_5150:
+		nvm_type = NVM_DEVICE_TYPE_EEPROM;
+		break;
+	default:
+		otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+		if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
+			nvm_type = NVM_DEVICE_TYPE_OTP;
+		else
+			nvm_type = NVM_DEVICE_TYPE_EEPROM;
+		break;
+	}
+	return  nvm_type;
+}
+
 /*
  * The device's EEPROM semaphore prevents conflicts between driver and uCode
  * when accessing the EEPROM; each access is a series of pulses to/from the
@@ -198,6 +224,31 @@
 }
 EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
 
+static int iwl_init_otp_access(struct iwl_priv *priv)
+{
+	int ret;
+
+	/* Enable 40MHz radio clock */
+	_iwl_write32(priv, CSR_GP_CNTRL,
+		     _iwl_read32(priv, CSR_GP_CNTRL) |
+		     CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+	/* wait for clock to be ready */
+	ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
+				  CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+				  25000);
+	if (ret < 0)
+		IWL_ERR(priv, "Time out access OTP\n");
+	else {
+		iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
+				  APMG_PS_CTRL_VAL_RESET_REQ);
+		udelay(5);
+		iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+				    APMG_PS_CTRL_VAL_RESET_REQ);
+	}
+	return ret;
+}
+
 /**
  * iwl_eeprom_init - read EEPROM contents
  *
@@ -209,11 +260,18 @@
 {
 	u16 *e;
 	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
-	int sz = priv->cfg->eeprom_size;
+	int sz;
 	int ret;
 	u16 addr;
+	u32 otpgp;
+
+	priv->nvm_device_type = iwlcore_get_nvm_type(priv);
 
 	/* allocate eeprom */
+	if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
+		priv->cfg->eeprom_size =
+			OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
+	sz = priv->cfg->eeprom_size;
 	priv->eeprom = kzalloc(sz, GFP_KERNEL);
 	if (!priv->eeprom) {
 		ret = -ENOMEM;
@@ -235,30 +293,77 @@
 		ret = -ENOENT;
 		goto err;
 	}
+	if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
+		ret = iwl_init_otp_access(priv);
+		if (ret) {
+			IWL_ERR(priv, "Failed to initialize OTP access.\n");
+			ret = -ENOENT;
+			goto err;
+		}
+		_iwl_write32(priv, CSR_EEPROM_GP,
+			     iwl_read32(priv, CSR_EEPROM_GP) &
+			     ~CSR_EEPROM_GP_IF_OWNER_MSK);
+		/* clear */
+		_iwl_write32(priv, CSR_OTP_GP_REG,
+			     iwl_read32(priv, CSR_OTP_GP_REG) |
+			     CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
+			     CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
 
-	/* eeprom is an array of 16bit values */
-	for (addr = 0; addr < sz; addr += sizeof(u16)) {
-		u32 r;
+		for (addr = 0; addr < sz; addr += sizeof(u16)) {
+			u32 r;
 
-		_iwl_write32(priv, CSR_EEPROM_REG,
-			     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+			_iwl_write32(priv, CSR_EEPROM_REG,
+				     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
 
-		ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
-					  CSR_EEPROM_REG_READ_VALID_MSK,
-					  IWL_EEPROM_ACCESS_TIMEOUT);
-		if (ret < 0) {
-			IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
-			goto done;
+			ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
+						  CSR_EEPROM_REG_READ_VALID_MSK,
+						  IWL_EEPROM_ACCESS_TIMEOUT);
+			if (ret < 0) {
+				IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+				goto done;
+			}
+			r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
+			/* check for ECC errors: */
+			otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+			if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
+				/* stop in this case */
+				IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n");
+				goto done;
+			}
+			if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
+				/* continue in this case */
+				_iwl_write32(priv, CSR_OTP_GP_REG,
+					     iwl_read32(priv, CSR_OTP_GP_REG) |
+					     CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
+				IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
+			}
+			e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+		}
+	} else {
+		/* eeprom is an array of 16bit values */
+		for (addr = 0; addr < sz; addr += sizeof(u16)) {
+			u32 r;
+
+			_iwl_write32(priv, CSR_EEPROM_REG,
+				     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+
+			ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
+						  CSR_EEPROM_REG_READ_VALID_MSK,
+						  IWL_EEPROM_ACCESS_TIMEOUT);
+			if (ret < 0) {
+				IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
+				goto done;
+			}
+			r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
+			e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
 		}
-		r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
-		e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
 	}
 	ret = 0;
 done:
 	priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
 err:
 	if (ret)
-		kfree(priv->eeprom);
+		iwl_eeprom_free(priv);
 alloc_err:
 	return ret;
 }
@@ -285,7 +390,7 @@
 
 	return 0;
 err:
-	IWL_ERR(priv, "Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
+	IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
 		  eeprom_ver, priv->cfg->eeprom_ver,
 		  calib_ver,  priv->cfg->eeprom_calib_ver);
 	return -EINVAL;
@@ -301,6 +406,8 @@
 
 u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
 {
+	if (!priv->eeprom)
+		return 0;
 	return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
 }
 EXPORT_SYMBOL(iwl_eeprom_query16);
@@ -481,8 +588,8 @@
 			/* First write that fat is not enabled, and then enable
 			 * one by one */
 			ch_info->fat_extension_channel =
-				(IEEE80211_CHAN_NO_FAT_ABOVE |
-				 IEEE80211_CHAN_NO_FAT_BELOW);
+				(IEEE80211_CHAN_NO_HT40PLUS |
+				 IEEE80211_CHAN_NO_HT40MINUS);
 
 			if (!(is_channel_valid(ch_info))) {
 				IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - "
@@ -561,7 +668,7 @@
 				fat_extension_chan = 0;
 			else
 				fat_extension_chan =
-					IEEE80211_CHAN_NO_FAT_BELOW;
+					IEEE80211_CHAN_NO_HT40MINUS;
 
 			/* Set up driver's info for lower half */
 			iwl_set_fat_chan_info(priv, ieeeband,
@@ -573,7 +680,7 @@
 			iwl_set_fat_chan_info(priv, ieeeband,
 						(eeprom_ch_index[ch] + 4),
 						&(eeprom_ch_info[ch]),
-						IEEE80211_CHAN_NO_FAT_ABOVE);
+						IEEE80211_CHAN_NO_HT40PLUS);
 		}
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2009-09-09 18:13:59.000000000 -0400
@@ -179,6 +179,10 @@
 #define EEPROM_5050_TX_POWER_VERSION    (4)
 #define EEPROM_5050_EEPROM_VERSION	(0x21E)
 
+/* OTP */
+#define OTP_LOWER_BLOCKS_TOTAL		(3)
+#define OTP_BLOCK_SIZE			(0x400)
+
 /* 2.4 GHz */
 extern const u8 iwl_eeprom_band_1[14];
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-io.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-io.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-io.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-io.h	2009-09-09 18:13:59.000000000 -0400
@@ -131,9 +131,23 @@
 	IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
 	_iwl_write32(priv, reg, val);
 }
-#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
+static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	__iwl_set_bit(__FILE__, __LINE__, p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
 #else
-#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
+static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	_iwl_set_bit(p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
 #endif
 
 static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
@@ -148,19 +162,30 @@
 	IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
 	_iwl_write32(priv, reg, val);
 }
-#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
+static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	__iwl_clear_bit(__FILE__, __LINE__, p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
 #else
-#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
+static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	_iwl_clear_bit(p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
 #endif
 
 static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
 {
 	int ret;
 	u32 val;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (atomic_read(&priv->restrict_refcnt))
-		return 0;
-#endif
+
 	/* this bit wakes up the NIC */
 	_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 	ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
@@ -170,12 +195,10 @@
 	if (ret < 0) {
 		val = _iwl_read32(priv, CSR_GP_CNTRL);
 		IWL_ERR(priv, "MAC is in deep sleep!.  CSR_GP_CNTRL = 0x%08X\n", val);
+		_iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
 		return -EIO;
 	}
 
-#ifdef CONFIG_IWLWIFI_DEBUG
-	atomic_inc(&priv->restrict_refcnt);
-#endif
 	return 0;
 }
 
@@ -183,9 +206,6 @@
 static inline int __iwl_grab_nic_access(const char *f, u32 l,
 					       struct iwl_priv *priv)
 {
-	if (atomic_read(&priv->restrict_refcnt))
-		IWL_ERR(priv, "Grabbing access while already held %s %d.\n", f, l);
-
 	IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l);
 	return _iwl_grab_nic_access(priv);
 }
@@ -198,18 +218,13 @@
 
 static inline void _iwl_release_nic_access(struct iwl_priv *priv)
 {
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (atomic_dec_and_test(&priv->restrict_refcnt))
-#endif
-		_iwl_clear_bit(priv, CSR_GP_CNTRL,
-			       CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+	_iwl_clear_bit(priv, CSR_GP_CNTRL,
+			CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 }
 #ifdef CONFIG_IWLWIFI_DEBUG
 static inline void __iwl_release_nic_access(const char *f, u32 l,
 					    struct iwl_priv *priv)
 {
-	if (atomic_read(&priv->restrict_refcnt) <= 0)
-		IWL_ERR(priv, "Release unheld nic access at line %s %d.\n", f, l);
 
 	IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l);
 	_iwl_release_nic_access(priv);
@@ -230,16 +245,37 @@
 					struct iwl_priv *priv, u32 reg)
 {
 	u32 value = _iwl_read_direct32(priv, reg);
-	if (!atomic_read(&priv->restrict_refcnt))
-		IWL_ERR(priv, "Nic access not held from %s %d\n", f, l);
 	IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
 		     f, l);
 	return value;
 }
-#define iwl_read_direct32(priv, reg) \
-	__iwl_read_direct32(__FILE__, __LINE__, priv, reg)
+static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg)
+{
+	u32 value;
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
+}
+
 #else
-#define iwl_read_direct32 _iwl_read_direct32
+static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg)
+{
+	u32 value;
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	value = _iwl_read_direct32(priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
+
+}
 #endif
 
 static inline void _iwl_write_direct32(struct iwl_priv *priv,
@@ -247,19 +283,17 @@
 {
 	_iwl_write32(priv, reg, value);
 }
-#ifdef CONFIG_IWLWIFI_DEBUG
-static void __iwl_write_direct32(const char *f , u32 line,
-				   struct iwl_priv *priv, u32 reg, u32 value)
+static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value)
 {
-	if (!atomic_read(&priv->restrict_refcnt))
-		IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
-	_iwl_write_direct32(priv, reg, value);
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_write_direct32(priv, reg, value);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
-#define iwl_write_direct32(priv, reg, value) \
-	__iwl_write_direct32(__func__, __LINE__, priv, reg, value)
-#else
-#define iwl_write_direct32 _iwl_write_direct32
-#endif
 
 static inline void iwl_write_reg_buf(struct iwl_priv *priv,
 					       u32 reg, u32 len, u32 *values)
@@ -268,14 +302,23 @@
 
 	if ((priv != NULL) && (values != NULL)) {
 		for (; 0 < len; len -= count, reg += count, values++)
-			_iwl_write_direct32(priv, reg, *values);
+			iwl_write_direct32(priv, reg, *values);
 	}
 }
 
 static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr,
 				       u32 mask, int timeout)
 {
-	return _iwl_poll_bit(priv, addr, mask, mask, timeout);
+	int t = 0;
+
+	do {
+		if ((iwl_read_direct32(priv, addr) & mask) == mask)
+			return t;
+		udelay(IWL_POLL_INTERVAL);
+		t += IWL_POLL_INTERVAL;
+	} while (t < timeout);
+
+	return -ETIMEDOUT;
 }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -305,20 +348,18 @@
 	rmb();
 	return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
 }
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline u32 __iwl_read_prph(const char *f, u32 line,
-				  struct iwl_priv *priv, u32 reg)
+static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg)
 {
-	if (!atomic_read(&priv->restrict_refcnt))
-		IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
-	return _iwl_read_prph(priv, reg);
-}
+	unsigned long reg_flags;
+	u32 val;
 
-#define iwl_read_prph(priv, reg) \
-	__iwl_read_prph(__func__, __LINE__, priv, reg)
-#else
-#define iwl_read_prph _iwl_read_prph
-#endif
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	val = _iwl_read_prph(priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return val;
+}
 
 static inline void _iwl_write_prph(struct iwl_priv *priv,
 					     u32 addr, u32 val)
@@ -328,83 +369,107 @@
 	wmb();
 	_iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
 }
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_write_prph(const char *f, u32 line,
-				    struct iwl_priv *priv, u32 addr, u32 val)
+
+static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
 {
-	if (!atomic_read(&priv->restrict_refcnt))
-		IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
-	_iwl_write_prph(priv, addr, val);
-}
+	unsigned long reg_flags;
 
-#define iwl_write_prph(priv, addr, val) \
-	__iwl_write_prph(__func__, __LINE__, priv, addr, val);
-#else
-#define iwl_write_prph _iwl_write_prph
-#endif
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_write_prph(priv, addr, val);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
 
 #define _iwl_set_bits_prph(priv, reg, mask) \
 	_iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask))
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_set_bits_prph(const char *f, u32 line,
-				       struct iwl_priv *priv,
-				       u32 reg, u32 mask)
+
+static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
 {
-	if (!atomic_read(&priv->restrict_refcnt))
-		IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
+	unsigned long reg_flags;
 
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
 	_iwl_set_bits_prph(priv, reg, mask);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
-#define iwl_set_bits_prph(priv, reg, mask) \
-	__iwl_set_bits_prph(__func__, __LINE__, priv, reg, mask)
-#else
-#define iwl_set_bits_prph _iwl_set_bits_prph
-#endif
 
 #define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \
 	_iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits))
 
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_set_bits_mask_prph(const char *f, u32 line,
-		struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
+static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
+				u32 bits, u32 mask)
 {
-	if (!atomic_read(&priv->restrict_refcnt))
-		IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
 	_iwl_set_bits_mask_prph(priv, reg, bits, mask);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
-#define iwl_set_bits_mask_prph(priv, reg, bits, mask) \
-	__iwl_set_bits_mask_prph(__func__, __LINE__, priv, reg, bits, mask)
-#else
-#define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph
-#endif
 
 static inline void iwl_clear_bits_prph(struct iwl_priv
 						 *priv, u32 reg, u32 mask)
 {
-	u32 val = _iwl_read_prph(priv, reg);
+	unsigned long reg_flags;
+	u32 val;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	val = _iwl_read_prph(priv, reg);
 	_iwl_write_prph(priv, reg, (val & ~mask));
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
 
 static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
 {
-	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+	unsigned long reg_flags;
+	u32 value;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	_iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
 	rmb();
-	return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+	value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
 }
 
 static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
 {
-	iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-	wmb();
-	iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+		wmb();
+		_iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
 
 static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
 					  u32 len, u32 *values)
 {
-	iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-	wmb();
-	for (; 0 < len; len -= sizeof(u32), values++)
-		iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+		wmb();
+		for (; 0 < len; len -= sizeof(u32), values++)
+			_iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
+
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-led.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-led.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-led.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-led.c	2009-09-09 18:13:59.000000000 -0400
@@ -176,10 +176,6 @@
 static int iwl_led_disassociate(struct iwl_priv *priv, int led_id)
 {
 	priv->allow_blinking = 0;
-	if (iwl_is_rfkill(priv))
-		iwl4965_led_off_reg(priv, led_id);
-	else
-		iwl4965_led_on_reg(priv, led_id);
 
 	return 0;
 }
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-power.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-power.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-power.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-power.c	2009-09-09 18:13:59.000000000 -0400
@@ -41,38 +41,33 @@
 #include "iwl-power.h"
 
 /*
- * Setting power level allow the card to go to sleep when not busy
- * there are three factor that decide the power level to go to, they
- * are list here with its priority
- *  1- critical_power_setting this will be set according to card temperature.
- *  2- system_power_setting this will be set by system PM manager.
- *  3- user_power_setting this will be set by user either by writing to sys or
- *  	mac80211
+ * Setting power level allow the card to go to sleep when not busy.
  *
- * if system_power_setting and user_power_setting is set to auto
- * the power level will be decided according to association status and battery
- * status.
+ * The power level is set to INDEX_1 (the least deep state) by
+ * default, and will, in the future, be the deepest state unless
+ * otherwise required by pm_qos network latency requirements.
  *
+ * Using INDEX_1 without pm_qos is ok because mac80211 will disable
+ * PS when even checking every beacon for the TIM bit would exceed
+ * the required latency.
  */
 
-#define MSEC_TO_USEC 1024
 #define IWL_POWER_RANGE_0_MAX  (2)
 #define IWL_POWER_RANGE_1_MAX  (10)
 
 
-
-#define IWL_POWER_ON_BATTERY		IWL_POWER_INDEX_5
-#define IWL_POWER_ON_AC_DISASSOC	IWL_POWER_MODE_CAM
-#define IWL_POWER_ON_AC_ASSOC		IWL_POWER_MODE_CAM
-
-
-#define IWL_CT_KILL_TEMPERATURE		110
-#define IWL_MIN_POWER_TEMPERATURE	100
-#define IWL_REDUCED_POWER_TEMPERATURE	95
-
+#define NOSLP cpu_to_le16(0), 0, 0
+#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
+#define TU_TO_USEC 1024
+#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC)
+#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
+				     cpu_to_le32(X1), \
+				     cpu_to_le32(X2), \
+				     cpu_to_le32(X3), \
+				     cpu_to_le32(X4)}
 /* default power management (not Tx power) table values */
-/* for TIM  0-10 */
-static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
+/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */
+static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
 	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
@@ -82,8 +77,8 @@
 };
 
 
-/* for TIM = 3-10 */
-static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
+/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */
+static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
 	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
@@ -92,8 +87,8 @@
 	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
 };
 
-/* for TIM > 11 */
-static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = {
+/* for DTIM period > IWL_POWER_RANGE_1_MAX */
+static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
 	{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
 	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
@@ -106,39 +101,15 @@
 /* set card power command */
 static int iwl_set_power(struct iwl_priv *priv, void *cmd)
 {
-	return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD,
-				      sizeof(struct iwl_powertable_cmd),
-				      cmd, NULL);
-}
-/* decide the right power level according to association status
- * and battery status
- */
-static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
-{
-	u16 mode;
-
-	switch (priv->power_data.user_power_setting) {
-	case IWL_POWER_AUTO:
-		/* if running on battery */
-		if (priv->power_data.is_battery_active)
-			mode = IWL_POWER_ON_BATTERY;
-		else if (iwl_is_associated(priv))
-			mode = IWL_POWER_ON_AC_ASSOC;
-		else
-			mode = IWL_POWER_ON_AC_DISASSOC;
-		break;
-	default:
-		mode = priv->power_data.user_power_setting;
-		break;
-	}
-	return mode;
+	return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
+				sizeof(struct iwl_powertable_cmd), cmd);
 }
 
 /* initialize to default */
 static void iwl_power_init_handle(struct iwl_priv *priv)
 {
 	struct iwl_power_mgr *pow_data;
-	int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
+	int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
 	struct iwl_powertable_cmd *cmd;
 	int i;
 	u16 lctl;
@@ -157,7 +128,7 @@
 
 	IWL_DEBUG_POWER(priv, "adjust power command flags\n");
 
-	for (i = 0; i < IWL_POWER_MAX; i++) {
+	for (i = 0; i < IWL_POWER_NUM; i++) {
 		cmd = &pow_data->pwr_range_0[i].cmd;
 
 		if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
@@ -247,33 +218,12 @@
 	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
 			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
 
-	/* If on battery, set to 3,
-	 * if plugged into AC power, set to CAM ("continuously aware mode"),
-	 * else user level */
-
-	switch (setting->system_power_setting) {
-	case IWL_POWER_SYS_AUTO:
-		final_mode = iwl_get_auto_power_mode(priv);
-		break;
-	case IWL_POWER_SYS_BATTERY:
-		final_mode = IWL_POWER_INDEX_3;
-		break;
-	case IWL_POWER_SYS_AC:
-		final_mode = IWL_POWER_MODE_CAM;
-		break;
-	default:
-		final_mode = IWL_POWER_INDEX_3;
-		WARN_ON(1);
-	}
-
-	if (setting->critical_power_setting > final_mode)
-		final_mode = setting->critical_power_setting;
+	final_mode = priv->power_data.user_power_setting;
 
-	/* driver only support CAM for non STA network */
-	if (priv->iw_mode != NL80211_IFTYPE_STATION)
+	if (setting->power_disabled)
 		final_mode = IWL_POWER_MODE_CAM;
 
-	if (iwl_is_ready_rf(priv) && !setting->power_disabled &&
+	if (iwl_is_ready_rf(priv) &&
 	    ((setting->power_mode != final_mode) || force)) {
 		struct iwl_powertable_cmd cmd;
 
@@ -290,8 +240,6 @@
 
 		if (final_mode == IWL_POWER_MODE_CAM)
 			clear_bit(STATUS_POWER_PMI, &priv->status);
-		else
-			set_bit(STATUS_POWER_PMI, &priv->status);
 
 		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
 			priv->cfg->ops->lib->update_chain_flags(priv);
@@ -307,51 +255,10 @@
 }
 EXPORT_SYMBOL(iwl_power_update_mode);
 
-/* Allow other iwl code to disable/enable power management active
- * this will be useful for rate scale to disable PM during heavy
- * Tx/Rx activities
- */
-int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
-{
-	u16 prev_mode;
-	int ret = 0;
-
-	if (priv->power_data.power_disabled)
-		return -EBUSY;
-
-	prev_mode = priv->power_data.user_power_setting;
-	priv->power_data.user_power_setting = IWL_POWER_MODE_CAM;
-	ret = iwl_power_update_mode(priv, 0);
-	priv->power_data.power_disabled = 1;
-	priv->power_data.user_power_setting = prev_mode;
-	cancel_delayed_work(&priv->set_power_save);
-	if (ms)
-		queue_delayed_work(priv->workqueue, &priv->set_power_save,
-				   msecs_to_jiffies(ms));
-
-
-	return ret;
-}
-EXPORT_SYMBOL(iwl_power_disable_management);
-
-/* Allow other iwl code to disable/enable power management active
- * this will be useful for rate scale to disable PM during high
- * volume activities
- */
-int iwl_power_enable_management(struct iwl_priv *priv)
-{
-	int ret = 0;
-
-	priv->power_data.power_disabled = 0;
-	ret = iwl_power_update_mode(priv, 0);
-	return ret;
-}
-EXPORT_SYMBOL(iwl_power_enable_management);
-
 /* set user_power_setting */
 int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
 {
-	if (mode > IWL_POWER_MAX)
+	if (mode >= IWL_POWER_NUM)
 		return -EINVAL;
 
 	priv->power_data.user_power_setting = mode;
@@ -360,86 +267,12 @@
 }
 EXPORT_SYMBOL(iwl_power_set_user_mode);
 
-/* set system_power_setting. This should be set by over all
- * PM application.
- */
-int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode)
-{
-	if (mode < IWL_POWER_SYS_MAX)
-		priv->power_data.system_power_setting = mode;
-	else
-		return -EINVAL;
-	return iwl_power_update_mode(priv, 0);
-}
-EXPORT_SYMBOL(iwl_power_set_system_mode);
-
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
 	iwl_power_init_handle(priv);
-	priv->power_data.user_power_setting = IWL_POWER_AUTO;
-	priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO;
-	priv->power_data.power_disabled = 0;
-	priv->power_data.is_battery_active = 0;
-	priv->power_data.critical_power_setting = 0;
+	priv->power_data.user_power_setting = IWL_POWER_INDEX_1;
+	/* default to disabled until mac80211 says otherwise */
+	priv->power_data.power_disabled = 1;
 }
 EXPORT_SYMBOL(iwl_power_initialize);
-
-/* set critical_power_setting according to temperature value */
-int iwl_power_temperature_change(struct iwl_priv *priv)
-{
-	int ret = 0;
-	s32 temperature = KELVIN_TO_CELSIUS(priv->last_temperature);
-	u16 new_critical = priv->power_data.critical_power_setting;
-
-	if (temperature > IWL_CT_KILL_TEMPERATURE)
-		return 0;
-	else if (temperature > IWL_MIN_POWER_TEMPERATURE)
-		new_critical = IWL_POWER_INDEX_5;
-	else if (temperature > IWL_REDUCED_POWER_TEMPERATURE)
-		new_critical = IWL_POWER_INDEX_3;
-	else
-		new_critical = IWL_POWER_MODE_CAM;
-
-	if (new_critical != priv->power_data.critical_power_setting)
-		priv->power_data.critical_power_setting = new_critical;
-
-	if (priv->power_data.critical_power_setting >
-				priv->power_data.power_mode)
-		ret = iwl_power_update_mode(priv, 0);
-
-	return ret;
-}
-EXPORT_SYMBOL(iwl_power_temperature_change);
-
-static void iwl_bg_set_power_save(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work,
-				struct iwl_priv, set_power_save.work);
-	IWL_DEBUG_POWER(priv, "update power\n");
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	/* on starting association we disable power management
-	 * until association, if association failed then this
-	 * timer will expire and enable PM again.
-	 */
-	if (!iwl_is_associated(priv))
-		iwl_power_enable_management(priv);
-
-	mutex_unlock(&priv->mutex);
-}
-void iwl_setup_power_deferred_work(struct iwl_priv *priv)
-{
-	INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save);
-}
-EXPORT_SYMBOL(iwl_setup_power_deferred_work);
-
-void iwl_power_cancel_timeout(struct iwl_priv *priv)
-{
-	cancel_delayed_work(&priv->set_power_save);
-}
-EXPORT_SYMBOL(iwl_power_cancel_timeout);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-power.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-power.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-power.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-power.h	2009-09-09 18:13:59.000000000 -0400
@@ -40,56 +40,29 @@
 	IWL_POWER_INDEX_3,
 	IWL_POWER_INDEX_4,
 	IWL_POWER_INDEX_5,
-	IWL_POWER_AUTO,
-	IWL_POWER_MAX = IWL_POWER_AUTO,
-};
-
-enum {
-	IWL_POWER_SYS_AUTO,
-	IWL_POWER_SYS_AC,
-	IWL_POWER_SYS_BATTERY,
-	IWL_POWER_SYS_MAX,
+	IWL_POWER_NUM
 };
 
-
 /* Power management (not Tx power) structures */
 
-#define NOSLP cpu_to_le16(0), 0, 0
-#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
-#define SLP_TOUT(T) cpu_to_le32((T) * MSEC_TO_USEC)
-#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
-				     cpu_to_le32(X1), \
-				     cpu_to_le32(X2), \
-				     cpu_to_le32(X3), \
-				     cpu_to_le32(X4)}
 struct iwl_power_vec_entry {
 	struct iwl_powertable_cmd cmd;
 	u8 no_dtim;
 };
 
 struct iwl_power_mgr {
-	spinlock_t lock;
-	struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX];
-	struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX];
-	struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX];
+	struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM];
+	struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM];
+	struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM];
 	u32 dtim_period;
 	/* final power level that used to calculate final power command */
 	u8 power_mode;
-	u8 user_power_setting; /* set by user through mac80211 or sysfs */
-	u8 system_power_setting; /* set by kernel system tools */
-	u8 critical_power_setting; /* set if driver over heated */
-	u8 is_battery_active; /* DC/AC power */
-	u8 power_disabled; /* flag to disable using power saving level */
+	u8 user_power_setting; /* set by user through sysfs */
+	u8 power_disabled; /* set by mac80211's CONF_PS */
 };
 
-void iwl_setup_power_deferred_work(struct iwl_priv *priv);
-void iwl_power_cancel_timeout(struct iwl_priv *priv);
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
-int iwl_power_disable_management(struct iwl_priv *priv, u32 ms);
-int iwl_power_enable_management(struct iwl_priv *priv);
 int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
-int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode);
 void iwl_power_initialize(struct iwl_priv *priv);
-int iwl_power_temperature_change(struct iwl_priv *priv);
 
 #endif  /* __iwl_power_setting_h__ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,145 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <net/mac80211.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-
-/* software rf-kill from user */
-static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
-{
-	struct iwl_priv *priv = data;
-	int err = 0;
-
-	if (!priv->rfkill)
-		return 0;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return 0;
-
-	IWL_DEBUG_RF_KILL(priv, "we received soft RFKILL set to state %d\n", state);
-	mutex_lock(&priv->mutex);
-
-	switch (state) {
-	case RFKILL_STATE_UNBLOCKED:
-		if (iwl_is_rfkill_hw(priv)) {
-			err = -EBUSY;
-			goto out_unlock;
-		}
-		iwl_radio_kill_sw_enable_radio(priv);
-		break;
-	case RFKILL_STATE_SOFT_BLOCKED:
-		iwl_radio_kill_sw_disable_radio(priv);
-		break;
-	default:
-		IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
-			state);
-		break;
-	}
-out_unlock:
-	mutex_unlock(&priv->mutex);
-
-	return err;
-}
-
-int iwl_rfkill_init(struct iwl_priv *priv)
-{
-	struct device *device = wiphy_dev(priv->hw->wiphy);
-	int ret = 0;
-
-	BUG_ON(device == NULL);
-
-	IWL_DEBUG_RF_KILL(priv, "Initializing RFKILL.\n");
-	priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
-	if (!priv->rfkill) {
-		IWL_ERR(priv, "Unable to allocate RFKILL device.\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	priv->rfkill->name = priv->cfg->name;
-	priv->rfkill->data = priv;
-	priv->rfkill->state = RFKILL_STATE_UNBLOCKED;
-	priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
-	priv->rfkill->user_claim_unsupported = 1;
-
-	priv->rfkill->dev.class->suspend = NULL;
-	priv->rfkill->dev.class->resume = NULL;
-
-	ret = rfkill_register(priv->rfkill);
-	if (ret) {
-		IWL_ERR(priv, "Unable to register RFKILL: %d\n", ret);
-		goto free_rfkill;
-	}
-
-	IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
-	return ret;
-
-free_rfkill:
-	if (priv->rfkill != NULL)
-		rfkill_free(priv->rfkill);
-	priv->rfkill = NULL;
-
-error:
-	IWL_DEBUG_RF_KILL(priv, "RFKILL initialization complete.\n");
-	return ret;
-}
-EXPORT_SYMBOL(iwl_rfkill_init);
-
-void iwl_rfkill_unregister(struct iwl_priv *priv)
-{
-
-	if (priv->rfkill)
-		rfkill_unregister(priv->rfkill);
-
-	priv->rfkill = NULL;
-}
-EXPORT_SYMBOL(iwl_rfkill_unregister);
-
-/* set RFKILL to the right state. */
-void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
-{
-	if (!priv->rfkill)
-		return;
-
-	if (iwl_is_rfkill_hw(priv)) {
-		rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
-		return;
-	}
-
-	if (!iwl_is_rfkill_sw(priv))
-		rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
-	else
-		rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
-}
-EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-rfkill.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-#ifndef __iwl_rf_kill_h__
-#define __iwl_rf_kill_h__
-
-struct iwl_priv;
-
-#include <linux/rfkill.h>
-
-#ifdef CONFIG_IWLWIFI_RFKILL
-
-void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
-void iwl_rfkill_unregister(struct iwl_priv *priv);
-int iwl_rfkill_init(struct iwl_priv *priv);
-#else
-static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {}
-static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {}
-static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; }
-#endif
-
-
-
-#endif  /* __iwl_rf_kill_h__ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c	2009-09-09 18:13:59.000000000 -0400
@@ -145,18 +145,14 @@
 			goto exit_unlock;
 		}
 
-		ret = iwl_grab_nic_access(priv);
-		if (ret)
-			goto exit_unlock;
-
-		/* Device expects a multiple of 8 */
-		iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write & ~0x7);
-		iwl_release_nic_access(priv);
+		q->write_actual = (q->write & ~0x7);
+		iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
 
 	/* Else device is assumed to be awake */
 	} else {
 		/* Device expects a multiple of 8 */
-		iwl_write32(priv, rx_wrt_ptr_reg, q->write & ~0x7);
+		q->write_actual = (q->write & ~0x7);
+		iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
 	}
 
 	q->need_update = 0;
@@ -218,7 +214,7 @@
 
 	/* If we've added more space for the firmware to place data, tell it.
 	 * Increment device's write pointer in multiples of 8. */
-	if (write != (rxq->write & ~0x7)) {
+	if (rxq->write_actual != (rxq->write & ~0x7)) {
 		spin_lock_irqsave(&rxq->lock, flags);
 		rxq->need_update = 1;
 		spin_unlock_irqrestore(&rxq->lock, flags);
@@ -238,7 +234,7 @@
  * Also restock the Rx queue via iwl_rx_queue_restock.
  * This is called as a scheduled work item (except for during initialization)
  */
-void iwl_rx_allocate(struct iwl_priv *priv)
+void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
 {
 	struct iwl_rx_queue *rxq = &priv->rxq;
 	struct list_head *element;
@@ -260,7 +256,8 @@
 
 		/* Alloc a new receive buffer */
 		rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
-				     GFP_KERNEL);
+						priority);
+
 		if (!rxb->skb) {
 			IWL_CRIT(priv, "Can not allocate SKB buffers\n");
 			/* We don't reschedule replenish work here -- we will
@@ -295,7 +292,7 @@
 {
 	unsigned long flags;
 
-	iwl_rx_allocate(priv);
+	iwl_rx_allocate(priv, GFP_KERNEL);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	iwl_rx_queue_restock(priv);
@@ -303,6 +300,14 @@
 }
 EXPORT_SYMBOL(iwl_rx_replenish);
 
+void iwl_rx_replenish_now(struct iwl_priv *priv)
+{
+	iwl_rx_allocate(priv, GFP_ATOMIC);
+
+	iwl_rx_queue_restock(priv);
+}
+EXPORT_SYMBOL(iwl_rx_replenish_now);
+
 
 /* Assumes that the skb field of the buffers in 'pool' is kept accurate.
  * If an SKB has been detached, the POOL needs to have its SKB set to NULL
@@ -358,6 +363,7 @@
 	/* Set us so that we have processed and used all buffers, but have
 	 * not restocked the Rx queue with fresh buffers */
 	rxq->read = rxq->write = 0;
+	rxq->write_actual = 0;
 	rxq->free_count = 0;
 	rxq->need_update = 0;
 	return 0;
@@ -396,6 +402,7 @@
 	/* Set us so that we have processed and used all buffers, but have
 	 * not restocked the Rx queue with fresh buffers */
 	rxq->read = rxq->write = 0;
+	rxq->write_actual = 0;
 	rxq->free_count = 0;
 	spin_unlock_irqrestore(&rxq->lock, flags);
 }
@@ -403,18 +410,12 @@
 
 int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
 {
-	int ret;
-	unsigned long flags;
 	u32 rb_size;
 	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
-	const u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT why this stalls RX */
+	u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
 
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (ret) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
+	if (!priv->cfg->use_isr_legacy)
+		rb_timeout = RX_RB_TIMEOUT;
 
 	if (priv->cfg->mod_params->amsdu_size_8K)
 		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
@@ -452,35 +453,19 @@
 			   (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
 			   (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
 
-	iwl_release_nic_access(priv);
-
 	iwl_write32(priv, CSR_INT_COALESCING, 0x40);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	return 0;
 }
 
 int iwl_rxq_stop(struct iwl_priv *priv)
 {
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (unlikely(ret)) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return ret;
-	}
 
 	/* stop Rx DMA */
 	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
 	iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
 			    FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
 
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	return 0;
 }
 EXPORT_SYMBOL(iwl_rxq_stop);
@@ -582,8 +567,8 @@
 
 	iwl_leds_background(priv);
 
-	if (priv->cfg->ops->lib->temperature && change)
-		priv->cfg->ops->lib->temperature(priv);
+	if (priv->cfg->ops->lib->temp_ops.temperature && change)
+		priv->cfg->ops->lib->temp_ops.temperature(priv);
 }
 EXPORT_SYMBOL(iwl_rx_statistics);
 
@@ -1102,13 +1087,6 @@
 	if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
 		rx_status.flag |= RX_FLAG_SHORTPRE;
 
-	/* Take shortcut when only in monitor mode */
-	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
-		iwl_pass_packet_to_mac80211(priv, include_phy,
-						 rxb, &rx_status);
-		return;
-	}
-
 	network_packet = iwl_is_network_packet(priv, header);
 	if (network_packet) {
 		priv->last_rx_rssi = rx_status.signal;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c	2009-09-09 18:13:59.000000000 -0400
@@ -445,13 +445,6 @@
 	unsigned long flags;
 	struct iwl_priv *priv = hw->priv;
 	int ret;
-	u8 *ssid = NULL;
-	size_t ssid_len = 0;
-
-	if (req->n_ssids) {
-		ssid = req->ssids[0].ssid;
-		ssid_len = req->ssids[0].ssid_len;
-	}
 
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
@@ -485,13 +478,7 @@
 		goto out_unlock;
 	}
 
-	if (ssid_len) {
-		priv->one_direct_scan = 1;
-		priv->direct_ssid_len =  ssid_len;
-		memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
-	} else {
-		priv->one_direct_scan = 0;
-	}
+	priv->scan_request = req;
 
 	ret = iwl_scan_initiate(priv);
 
@@ -530,73 +517,14 @@
 EXPORT_SYMBOL(iwl_bg_scan_check);
 
 /**
- * iwl_supported_rate_to_ie - fill in the supported rate in IE field
- *
- * return : set the bit for each supported rate insert in ie
- */
-static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
-				    u16 basic_rate, int *left)
-{
-	u16 ret_rates = 0, bit;
-	int i;
-	u8 *cnt = ie;
-	u8 *rates = ie + 1;
-
-	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
-		if (bit & supported_rate) {
-			ret_rates |= bit;
-			rates[*cnt] = iwl_rates[i].ieee |
-				((bit & basic_rate) ? 0x80 : 0x00);
-			(*cnt)++;
-			(*left)--;
-			if ((*left <= 0) ||
-			    (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
-				break;
-		}
-	}
-
-	return ret_rates;
-}
-
-
-static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
-			     u8 *pos, int *left)
-{
-	struct ieee80211_ht_cap *ht_cap;
-
-	if (!sband || !sband->ht_cap.ht_supported)
-		return;
-
-	if (*left < sizeof(struct ieee80211_ht_cap))
-		return;
-
-	*pos++ = sizeof(struct ieee80211_ht_cap);
-	ht_cap = (struct ieee80211_ht_cap *) pos;
-
-	ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
-	memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16);
-	ht_cap->ampdu_params_info =
-		(sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) |
-		((sband->ht_cap.ampdu_density << 2) &
-			IEEE80211_HT_AMPDU_PARM_DENSITY);
-	*left -= sizeof(struct ieee80211_ht_cap);
-}
-
-/**
  * iwl_fill_probe_req - fill in all required fields and IE for probe request
  */
 
-u16 iwl_fill_probe_req(struct iwl_priv *priv,
-		       enum ieee80211_band band,
-		       struct ieee80211_mgmt *frame,
-		       int left)
+u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
+		       const u8 *ies, int ie_len, int left)
 {
 	int len = 0;
 	u8 *pos = NULL;
-	u16 active_rates, ret_rates, cck_rates, active_rate_basic;
-	const struct ieee80211_supported_band *sband =
-						iwl_get_hw_mode(priv, band);
-
 
 	/* Make sure there is enough space for the probe request,
 	 * two mandatory IEs and the data */
@@ -624,62 +552,12 @@
 
 	len += 2;
 
-	/* fill in supported rate */
-	left -= 2;
-	if (left < 0)
-		return 0;
-
-	*pos++ = WLAN_EID_SUPP_RATES;
-	*pos = 0;
-
-	/* exclude 60M rate */
-	active_rates = priv->rates_mask;
-	active_rates &= ~IWL_RATE_60M_MASK;
-
-	active_rate_basic = active_rates & IWL_BASIC_RATES_MASK;
-
-	cck_rates = IWL_CCK_RATES_MASK & active_rates;
-	ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
-					     active_rate_basic, &left);
-	active_rates &= ~ret_rates;
-
-	ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
-					     active_rate_basic, &left);
-	active_rates &= ~ret_rates;
-
-	len += 2 + *pos;
-	pos += (*pos) + 1;
-
-	if (active_rates == 0)
-		goto fill_end;
-
-	/* fill in supported extended rate */
-	/* ...next IE... */
-	left -= 2;
-	if (left < 0)
-		return 0;
-	/* ... fill it in... */
-	*pos++ = WLAN_EID_EXT_SUPP_RATES;
-	*pos = 0;
-	iwl_supported_rate_to_ie(pos, active_rates, active_rate_basic, &left);
-	if (*pos > 0) {
-		len += 2 + *pos;
-		pos += (*pos) + 1;
-	} else {
-		pos--;
-	}
-
- fill_end:
-
-	left -= 2;
-	if (left < 0)
-		return 0;
+	if (WARN_ON(left < ie_len))
+		return len;
 
-	*pos++ = WLAN_EID_HT_CAPABILITY;
-	*pos = 0;
-	iwl_ht_cap_to_ie(sband, pos, &left);
-	if (*pos > 0)
-		len += 2 + *pos;
+	memcpy(pos, ies, ie_len);
+	len += ie_len;
+	left -= ie_len;
 
 	return (u16)len;
 }
@@ -699,11 +577,13 @@
 	int ret = 0;
 	u32 rate_flags = 0;
 	u16 cmd_len;
+	u16 rx_chain = 0;
 	enum ieee80211_band band;
-	u8 n_probes = 2;
-	u8 rx_chain = priv->hw_params.valid_rx_ant;
+	u8 n_probes = 0;
+	u8 rx_ant = priv->hw_params.valid_rx_ant;
 	u8 rate;
-	DECLARE_SSID_BUF(ssid);
+	bool is_active = false;
+	int  chan_mod;
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 
@@ -795,19 +675,25 @@
 			       scan_suspend_time, interval);
 	}
 
-	/* We should add the ability for user to lock to PASSIVE ONLY */
-	if (priv->one_direct_scan) {
-		IWL_DEBUG_SCAN(priv, "Start direct scan for '%s'\n",
-				print_ssid(ssid, priv->direct_ssid,
-					   priv->direct_ssid_len));
-		scan->direct_scan[0].id = WLAN_EID_SSID;
-		scan->direct_scan[0].len = priv->direct_ssid_len;
-		memcpy(scan->direct_scan[0].ssid,
-		       priv->direct_ssid, priv->direct_ssid_len);
-		n_probes++;
-	} else {
-		IWL_DEBUG_SCAN(priv, "Start indirect scan.\n");
-	}
+	if (priv->scan_request->n_ssids) {
+		int i, p = 0;
+		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+		for (i = 0; i < priv->scan_request->n_ssids; i++) {
+			/* always does wildcard anyway */
+			if (!priv->scan_request->ssids[i].ssid_len)
+				continue;
+			scan->direct_scan[p].id = WLAN_EID_SSID;
+			scan->direct_scan[p].len =
+				priv->scan_request->ssids[i].ssid_len;
+			memcpy(scan->direct_scan[p].ssid,
+			       priv->scan_request->ssids[i].ssid,
+			       priv->scan_request->ssids[i].ssid_len);
+			n_probes++;
+			p++;
+		}
+		is_active = true;
+	} else
+		IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
 
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
 	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
@@ -817,7 +703,9 @@
 	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
 		band = IEEE80211_BAND_2GHZ;
 		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-		if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) {
+		chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
+				       >> RXON_FLG_CHANNEL_MODE_POS;
+		if (chan_mod == CHANNEL_MODE_PURE_40) {
 			rate = IWL_RATE_6M_PLCP;
 		} else {
 			rate = IWL_RATE_1M_PLCP;
@@ -827,13 +715,18 @@
 	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
 		band = IEEE80211_BAND_5GHZ;
 		rate = IWL_RATE_6M_PLCP;
-		scan->good_CRC_th = IWL_GOOD_CRC_TH;
+		/*
+		 * If active scaning is requested but a certain channel
+		 * is marked passive, we can do active scanning if we
+		 * detect transmissions.
+		 */
+		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
 
 		/* Force use of chains B and C (0x6) for scan Rx for 4965
 		 * Avoid A (0x1) because of its off-channel reception on A-band.
 		 */
 		if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
-			rx_chain = 0x6;
+			rx_ant = ANT_BC;
 	} else {
 		IWL_WARN(priv, "Invalid scan band count\n");
 		goto done;
@@ -845,26 +738,27 @@
 	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
 
 	/* MIMO is not used here, but value is required */
-	scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
-				cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
-				(rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) |
-				(0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
-
-	cmd_len = iwl_fill_probe_req(priv, band,
-				     (struct ieee80211_mgmt *)scan->data,
-				     IWL_MAX_SCAN_SIZE - sizeof(*scan));
+	rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS;
+	rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
+	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+	scan->rx_chain = cpu_to_le16(rx_chain);
+	cmd_len = iwl_fill_probe_req(priv,
+				(struct ieee80211_mgmt *)scan->data,
+				priv->scan_request->ie,
+				priv->scan_request->ie_len,
+				IWL_MAX_SCAN_SIZE - sizeof(*scan));
 
 	scan->tx_cmd.len = cpu_to_le16(cmd_len);
 
-	if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
+	if (iwl_is_monitor_mode(priv))
 		scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
 	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
 			       RXON_FILTER_BCON_AWARE_MSK);
 
 	scan->channel_count =
-		iwl_get_channels_for_scan(priv, band, 1, /* active */
-			n_probes,
+		iwl_get_channels_for_scan(priv, band, is_active, n_probes,
 			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
 	if (scan->channel_count == 0) {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c	2009-09-09 18:13:59.000000000 -0400
@@ -86,8 +86,7 @@
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 
-	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
-	    !(priv->stations_39[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
 		IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n",
 			sta_id);
 
@@ -228,15 +227,16 @@
 }
 
 /**
- * iwl_add_station_flags - Add station to tables in driver and device
+ * iwl_add_station - Add station to tables in driver and device
  */
-u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
-			 u8 flags, struct ieee80211_sta_ht_cap *ht_info)
+u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags,
+		struct ieee80211_sta_ht_cap *ht_info)
 {
-	int i;
-	int sta_id = IWL_INVALID_STATION;
 	struct iwl_station_entry *station;
 	unsigned long flags_spin;
+	int i;
+	int sta_id = IWL_INVALID_STATION;
+	u16 rate;
 
 	spin_lock_irqsave(&priv->sta_lock, flags_spin);
 	if (is_ap)
@@ -288,6 +288,12 @@
 	    priv->iw_mode != NL80211_IFTYPE_ADHOC)
 		iwl_set_ht_add_station(priv, sta_id, ht_info);
 
+	/* 3945 only */
+	rate = (priv->band == IEEE80211_BAND_5GHZ) ?
+		IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP;
+	/* Turn on both antennas for the station... */
+	station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK);
+
 	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
 
 	/* Add station to device's station table */
@@ -295,7 +301,7 @@
 	return sta_id;
 
 }
-EXPORT_SYMBOL(iwl_add_station_flags);
+EXPORT_SYMBOL(iwl_add_station);
 
 static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
 {
@@ -408,7 +414,7 @@
 /**
  * iwl_remove_station - Remove driver's knowledge of station.
  */
-int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
 {
 	int sta_id = IWL_INVALID_STATION;
 	int i, ret = -EINVAL;
@@ -490,7 +496,7 @@
 	/* keep track of static keys */
 	for (i = 0; i < WEP_KEYS_MAX ; i++) {
 		if (priv->wep_keys[i].key_size)
-			test_and_set_bit(i, &priv->ucode_key_table);
+			set_bit(i, &priv->ucode_key_table);
 	}
 
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
@@ -560,6 +566,8 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
+	IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
+		      keyconf->keyidx);
 
 	if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
 		IWL_ERR(priv, "index %d not used in uCode key table.\n",
@@ -567,6 +575,11 @@
 
 	priv->default_wep_key--;
 	memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
+	if (iwl_is_rfkill(priv)) {
+		IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
 	ret = iwl_send_static_wepkey_cmd(priv, 1);
 	IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
 		      keyconf->keyidx, ret);
@@ -847,6 +860,11 @@
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
+	if (iwl_is_rfkill(priv)) {
+		IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
 	ret =  iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	return ret;
@@ -946,7 +964,7 @@
  *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
  *       which requires station table entry to exist).
  */
-static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
+static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)
 {
 	int i, r;
 	struct iwl_link_quality_cmd link_cmd = {
@@ -979,8 +997,9 @@
 	link_cmd.general_params.single_stream_ant_msk =
 				first_antenna(priv->hw_params.valid_tx_ant);
 	link_cmd.general_params.dual_stream_ant_msk = 3;
-	link_cmd.agg_params.agg_dis_start_th = 3;
-	link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
+	link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+	link_cmd.agg_params.agg_time_limit =
+		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
 
 	/* Update the rate scaling for control frame Tx to AP */
 	link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
@@ -995,7 +1014,7 @@
  * there is only one AP station with id= IWL_AP_ID
  * NOTE: mutex must be held before calling this function
  */
-int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
 {
 	struct ieee80211_sta *sta;
 	struct ieee80211_sta_ht_cap ht_config;
@@ -1020,8 +1039,7 @@
 		rcu_read_unlock();
 	}
 
-	sta_id = iwl_add_station_flags(priv, addr, is_ap,
-				       0, cur_ht_config);
+	sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config);
 
 	/* Set up default rate scaling table in device's station table */
 	iwl_sta_init_lq(priv, addr, is_ap);
@@ -1067,8 +1085,8 @@
 			return sta_id;
 
 		/* Create new station table entry */
-		sta_id = iwl_add_station_flags(priv, hdr->addr1,
-						   0, CMD_ASYNC, NULL);
+		sta_id = iwl_add_station(priv, hdr->addr1, false,
+					CMD_ASYNC, NULL);
 
 		if (sta_id != IWL_INVALID_STATION)
 			return sta_id;
@@ -1079,11 +1097,6 @@
 		iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
 		return priv->hw_params.bcast_sta_id;
 
-	/* If we are in monitor mode, use BCAST. This is required for
-	 * packet injection. */
-	case NL80211_IFTYPE_MONITOR:
-		return priv->hw_params.bcast_sta_id;
-
 	default:
 		IWL_WARN(priv, "Unknown mode of operation: %d\n",
 			priv->iw_mode);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-sta.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-sta.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-sta.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-sta.h	2009-09-09 18:13:59.000000000 -0400
@@ -51,16 +51,15 @@
 			struct ieee80211_key_conf *keyconf,
 			const u8 *addr, u32 iv32, u16 *phase1key);
 
-int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
-int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
+int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
+int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
 void iwl_clear_stations_table(struct iwl_priv *priv);
 int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
 int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
 int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
 int iwl_send_add_sta(struct iwl_priv *priv,
 		     struct iwl_addsta_cmd *sta, u8 flags);
-u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
-			int is_ap, u8 flags,
+u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags,
 			struct ieee80211_sta_ht_cap *ht_info);
 void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
 int iwl_sta_rx_agg_start(struct iwl_priv *priv,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -102,13 +102,8 @@
 			return ret;
 		}
 
-		/* restore this queue's parameters in nic hardware. */
-		ret = iwl_grab_nic_access(priv);
-		if (ret)
-			return ret;
 		iwl_write_direct32(priv, HBUS_TARG_WRPTR,
 				     txq->q.write_ptr | (txq_id << 8));
-		iwl_release_nic_access(priv);
 
 	/* else not in power-save mode, uCode will never sleep when we're
 	 * trying to tx (during RFKILL, we're not trying to tx). */
@@ -429,11 +424,6 @@
 		goto error_kw;
 	}
 	spin_lock_irqsave(&priv->lock, flags);
-	ret = iwl_grab_nic_access(priv);
-	if (unlikely(ret)) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		goto error_reset;
-	}
 
 	/* Turn off all Tx DMA fifos */
 	priv->cfg->ops->lib->txq_set_sched(priv, 0);
@@ -441,7 +431,6 @@
 	/* Tell NIC where to find the "keep warm" buffer */
 	iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
 
-	iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* Alloc and init all Tx queues, including the command queue (#4) */
@@ -460,7 +449,6 @@
 
  error:
 	iwl_hw_txq_ctx_free(priv);
- error_reset:
 	iwl_free_dma_ptr(priv, &priv->kw);
  error_kw:
 	iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
@@ -478,10 +466,6 @@
 
 	/* Turn off all Tx DMA fifos */
 	spin_lock_irqsave(&priv->lock, flags);
-	if (iwl_grab_nic_access(priv)) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return;
-	}
 
 	priv->cfg->ops->lib->txq_set_sched(priv, 0);
 
@@ -492,7 +476,6 @@
 				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
 				    1000);
 	}
-	iwl_release_nic_access(priv);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* Deallocate memory for all Tx queues */
@@ -728,7 +711,7 @@
 
 	/* drop all data frame if we are not associated */
 	if (ieee80211_is_data(fc) &&
-	    (priv->iw_mode != NL80211_IFTYPE_MONITOR ||
+	    (!iwl_is_monitor_mode(priv) ||
 	    !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */
 	    (!iwl_is_associated(priv) ||
 	     ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
@@ -737,8 +720,6 @@
 		goto drop_unlock;
 	}
 
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	hdr_len = ieee80211_hdrlen(fc);
 
 	/* Find (or create) index into station table for destination station */
@@ -746,7 +727,7 @@
 	if (sta_id == IWL_INVALID_STATION) {
 		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
 			       hdr->addr1);
-		goto drop;
+		goto drop_unlock;
 	}
 
 	IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -767,14 +748,17 @@
 			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
 			swq_id = iwl_virtual_agg_queue_num(swq_id, txq_id);
 		}
-		priv->stations[sta_id].tid[tid].tfds_in_queue++;
 	}
 
 	txq = &priv->txq[txq_id];
 	q = &txq->q;
 	txq->swq_id = swq_id;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	if (unlikely(iwl_queue_space(q) < q->high_mark))
+		goto drop_unlock;
+
+	if (ieee80211_is_data_qos(fc))
+		priv->stations[sta_id].tid[tid].tfds_in_queue++;
 
 	/* Set up driver data for this TFD */
 	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
@@ -889,7 +873,8 @@
 	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
 
 	/* Set up entry for this TFD in Tx byte-count array */
-	priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
+	if (info->flags & IEEE80211_TX_CTL_AMPDU)
+		priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
 						     le16_to_cpu(tx_cmd->len));
 
 	pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
@@ -918,7 +903,6 @@
 
 drop_unlock:
 	spin_unlock_irqrestore(&priv->lock, flags);
-drop:
 	return -1;
 }
 EXPORT_SYMBOL(iwl_tx_skb);
@@ -1183,8 +1167,12 @@
 			__func__, ra, tid);
 
 	sta_id = iwl_find_station(priv, ra);
-	if (sta_id == IWL_INVALID_STATION)
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Start AGG on invalid station\n");
 		return -ENXIO;
+	}
+	if (unlikely(tid >= MAX_TID_COUNT))
+		return -EINVAL;
 
 	if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
 		IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
@@ -1192,8 +1180,10 @@
 	}
 
 	txq_id = iwl_txq_ctx_activate_free(priv);
-	if (txq_id == -1)
+	if (txq_id == -1) {
+		IWL_ERR(priv, "No free aggregation queue available\n");
 		return -ENXIO;
+	}
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
 	tid_data = &priv->stations[sta_id].tid[tid];
@@ -1207,7 +1197,7 @@
 		return ret;
 
 	if (tid_data->tfds_in_queue == 0) {
-		IWL_ERR(priv, "HW queue is empty\n");
+		IWL_DEBUG_HT(priv, "HW queue is empty\n");
 		tid_data->agg.state = IWL_AGG_ON;
 		ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid);
 	} else {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -5,16 +5,11 @@
 	select FW_LOADER
 	select MAC80211_LEDS if IWLWIFI_LEDS
 	select LEDS_CLASS if IWLWIFI_LEDS
-	select RFKILL if IWLWIFI_RFKILL
 
 config IWLWIFI_LEDS
 	bool "Enable LED support in iwlagn and iwl3945 drivers"
 	depends on IWLWIFI
 
-config IWLWIFI_RFKILL
-	bool "Enable RF kill support in iwlagn and iwl3945 drivers"
-	depends on IWLWIFI
-
 config IWLWIFI_SPECTRUM_MEASUREMENT
 	bool "Enable Spectrum Measurement in iwlagn driver"
 	depends on IWLWIFI
@@ -75,7 +70,7 @@
 	  If you want to compile the driver as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
-	  module will be called iwlagn.ko.
+	  module will be called iwlagn.
 
 
 config IWL4965
@@ -113,7 +108,7 @@
 	  If you want to compile the driver as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
-	  module will be called iwl3945.ko.
+	  module will be called iwl3945.
 
 config IWL3945_SPECTRUM_MEASUREMENT
 	bool "Enable Spectrum Measurement in iwl3945 driver"
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwlwifi/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwlwifi/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -4,7 +4,6 @@
 iwlcore-objs 		+= iwl-scan.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
-iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
 iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
 
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/bus.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/bus.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/bus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/bus.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef __IWM_BUS_H__
+#define __IWM_BUS_H__
+
+#include "iwm.h"
+
+struct iwm_if_ops {
+	int (*enable)(struct iwm_priv *iwm);
+	int (*disable)(struct iwm_priv *iwm);
+	int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
+
+	int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
+	void (*debugfs_exit)(struct iwm_priv *iwm);
+
+	const char *umac_name;
+	const char *calib_lmac_name;
+	const char *lmac_name;
+};
+
+static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
+{
+	return iwm->bus_ops->send_chunk(iwm, buf, count);
+}
+
+static inline int iwm_bus_enable(struct iwm_priv *iwm)
+{
+	return iwm->bus_ops->enable(iwm);
+}
+
+static inline int iwm_bus_disable(struct iwm_priv *iwm)
+{
+	return iwm->bus_ops->disable(iwm);
+}
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,409 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+
+#include "iwm.h"
+#include "commands.h"
+#include "cfg80211.h"
+#include "debug.h"
+
+#define RATETAB_ENT(_rate, _rateid, _flags) \
+	{								\
+		.bitrate	= (_rate),				\
+		.hw_value	= (_rateid),				\
+		.flags		= (_flags),				\
+	}
+
+#define CHAN2G(_channel, _freq, _flags) {			\
+	.band			= IEEE80211_BAND_2GHZ,		\
+	.center_freq		= (_freq),			\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+
+#define CHAN5G(_channel, _flags) {				\
+	.band			= IEEE80211_BAND_5GHZ,		\
+	.center_freq		= 5000 + (5 * (_channel)),	\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+
+static struct ieee80211_rate iwm_rates[] = {
+	RATETAB_ENT(10,  0x1,   0),
+	RATETAB_ENT(20,  0x2,   0),
+	RATETAB_ENT(55,  0x4,   0),
+	RATETAB_ENT(110, 0x8,   0),
+	RATETAB_ENT(60,  0x10,  0),
+	RATETAB_ENT(90,  0x20,  0),
+	RATETAB_ENT(120, 0x40,  0),
+	RATETAB_ENT(180, 0x80,  0),
+	RATETAB_ENT(240, 0x100, 0),
+	RATETAB_ENT(360, 0x200, 0),
+	RATETAB_ENT(480, 0x400, 0),
+	RATETAB_ENT(540, 0x800, 0),
+};
+
+#define iwm_a_rates		(iwm_rates + 4)
+#define iwm_a_rates_size	8
+#define iwm_g_rates		(iwm_rates + 0)
+#define iwm_g_rates_size	12
+
+static struct ieee80211_channel iwm_2ghz_channels[] = {
+	CHAN2G(1, 2412, 0),
+	CHAN2G(2, 2417, 0),
+	CHAN2G(3, 2422, 0),
+	CHAN2G(4, 2427, 0),
+	CHAN2G(5, 2432, 0),
+	CHAN2G(6, 2437, 0),
+	CHAN2G(7, 2442, 0),
+	CHAN2G(8, 2447, 0),
+	CHAN2G(9, 2452, 0),
+	CHAN2G(10, 2457, 0),
+	CHAN2G(11, 2462, 0),
+	CHAN2G(12, 2467, 0),
+	CHAN2G(13, 2472, 0),
+	CHAN2G(14, 2484, 0),
+};
+
+static struct ieee80211_channel iwm_5ghz_a_channels[] = {
+	CHAN5G(34, 0),		CHAN5G(36, 0),
+	CHAN5G(38, 0),		CHAN5G(40, 0),
+	CHAN5G(42, 0),		CHAN5G(44, 0),
+	CHAN5G(46, 0),		CHAN5G(48, 0),
+	CHAN5G(52, 0),		CHAN5G(56, 0),
+	CHAN5G(60, 0),		CHAN5G(64, 0),
+	CHAN5G(100, 0),		CHAN5G(104, 0),
+	CHAN5G(108, 0),		CHAN5G(112, 0),
+	CHAN5G(116, 0),		CHAN5G(120, 0),
+	CHAN5G(124, 0),		CHAN5G(128, 0),
+	CHAN5G(132, 0),		CHAN5G(136, 0),
+	CHAN5G(140, 0),		CHAN5G(149, 0),
+	CHAN5G(153, 0),		CHAN5G(157, 0),
+	CHAN5G(161, 0),		CHAN5G(165, 0),
+	CHAN5G(184, 0),		CHAN5G(188, 0),
+	CHAN5G(192, 0),		CHAN5G(196, 0),
+	CHAN5G(200, 0),		CHAN5G(204, 0),
+	CHAN5G(208, 0),		CHAN5G(212, 0),
+	CHAN5G(216, 0),
+};
+
+static struct ieee80211_supported_band iwm_band_2ghz = {
+	.channels = iwm_2ghz_channels,
+	.n_channels = ARRAY_SIZE(iwm_2ghz_channels),
+	.bitrates = iwm_g_rates,
+	.n_bitrates = iwm_g_rates_size,
+};
+
+static struct ieee80211_supported_band iwm_band_5ghz = {
+	.channels = iwm_5ghz_a_channels,
+	.n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
+	.bitrates = iwm_a_rates,
+	.n_bitrates = iwm_a_rates_size,
+};
+
+int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
+{
+	struct wiphy *wiphy = iwm_to_wiphy(iwm);
+	struct iwm_bss_info *bss, *next;
+	struct iwm_umac_notif_bss_info *umac_bss;
+	struct ieee80211_mgmt *mgmt;
+	struct ieee80211_channel *channel;
+	struct ieee80211_supported_band *band;
+	s32 signal;
+	int freq;
+
+	list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
+		umac_bss = bss->bss;
+		mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
+
+		if (umac_bss->band == UMAC_BAND_2GHZ)
+			band = wiphy->bands[IEEE80211_BAND_2GHZ];
+		else if (umac_bss->band == UMAC_BAND_5GHZ)
+			band = wiphy->bands[IEEE80211_BAND_5GHZ];
+		else {
+			IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
+			return -EINVAL;
+		}
+
+		freq = ieee80211_channel_to_frequency(umac_bss->channel);
+		channel = ieee80211_get_channel(wiphy, freq);
+		signal = umac_bss->rssi * 100;
+
+		if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
+					       le16_to_cpu(umac_bss->frame_len),
+					       signal, GFP_KERNEL))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int iwm_cfg80211_change_iface(struct wiphy *wiphy, int ifindex,
+				     enum nl80211_iftype type, u32 *flags,
+				     struct vif_params *params)
+{
+	struct net_device *ndev;
+	struct wireless_dev *wdev;
+	struct iwm_priv *iwm;
+	u32 old_mode;
+
+	/* we're under RTNL */
+	ndev = __dev_get_by_index(&init_net, ifindex);
+	if (!ndev)
+		return -ENODEV;
+
+	wdev = ndev->ieee80211_ptr;
+	iwm = ndev_to_iwm(ndev);
+	old_mode = iwm->conf.mode;
+
+	switch (type) {
+	case NL80211_IFTYPE_STATION:
+		iwm->conf.mode = UMAC_MODE_BSS;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		iwm->conf.mode = UMAC_MODE_IBSS;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	wdev->iftype = type;
+
+	if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
+		return 0;
+
+	iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
+
+	if (iwm->umac_profile_active) {
+		int ret = iwm_invalidate_mlme_profile(iwm);
+		if (ret < 0)
+			IWM_ERR(iwm, "Couldn't invalidate profile\n");
+	}
+
+	return 0;
+}
+
+static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+			     struct cfg80211_scan_request *request)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(ndev);
+	int ret;
+
+	if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
+		IWM_ERR(iwm, "Scan while device is not ready\n");
+		return -EIO;
+	}
+
+	if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
+		IWM_ERR(iwm, "Scanning already\n");
+		return -EAGAIN;
+	}
+
+	if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
+		IWM_ERR(iwm, "Scanning being aborted\n");
+		return -EAGAIN;
+	}
+
+	set_bit(IWM_STATUS_SCANNING, &iwm->status);
+
+	ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
+	if (ret) {
+		clear_bit(IWM_STATUS_SCANNING, &iwm->status);
+		return ret;
+	}
+
+	iwm->scan_request = request;
+	return 0;
+}
+
+static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+	    (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
+		int ret;
+
+		iwm->conf.rts_threshold = wiphy->rts_threshold;
+
+		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+					     CFG_RTS_THRESHOLD,
+					     iwm->conf.rts_threshold);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+	    (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
+		int ret;
+
+		iwm->conf.frag_threshold = wiphy->frag_threshold;
+
+		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
+					     CFG_FRAG_THRESHOLD,
+					     iwm->conf.frag_threshold);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+				  struct cfg80211_ibss_params *params)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+	struct ieee80211_channel *chan = params->channel;
+	struct cfg80211_bss *bss;
+
+	if (!test_bit(IWM_STATUS_READY, &iwm->status))
+		return -EIO;
+
+	/* UMAC doesn't support creating IBSS network with specified bssid.
+	 * This should be removed after we have join only mode supported. */
+	if (params->bssid)
+		return -EOPNOTSUPP;
+
+	bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
+				params->ssid, params->ssid_len);
+	if (!bss) {
+		iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
+		schedule_timeout_interruptible(2 * HZ);
+		bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
+					params->ssid, params->ssid_len);
+	}
+	/* IBSS join only mode is not supported by UMAC ATM */
+	if (bss) {
+		cfg80211_put_bss(bss);
+		return -EOPNOTSUPP;
+	}
+
+	iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
+	iwm->umac_profile->ibss.band = chan->band;
+	iwm->umac_profile->ibss.channel = iwm->channel;
+	iwm->umac_profile->ssid.ssid_len = params->ssid_len;
+	memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
+
+	if (params->bssid)
+		memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
+
+	return iwm_send_mlme_profile(iwm);
+}
+
+static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+	if (iwm->umac_profile_active)
+		return iwm_invalidate_mlme_profile(iwm);
+
+	return 0;
+}
+
+static struct cfg80211_ops iwm_cfg80211_ops = {
+	.change_virtual_intf = iwm_cfg80211_change_iface,
+	.scan = iwm_cfg80211_scan,
+	.set_wiphy_params = iwm_cfg80211_set_wiphy_params,
+	.join_ibss = iwm_cfg80211_join_ibss,
+	.leave_ibss = iwm_cfg80211_leave_ibss,
+};
+
+struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
+{
+	int ret = 0;
+	struct wireless_dev *wdev;
+
+	/*
+	 * We're trying to have the following memory
+	 * layout:
+	 *
+	 * +-------------------------+
+	 * | struct wiphy	     |
+	 * +-------------------------+
+	 * | struct iwm_priv         |
+	 * +-------------------------+
+	 * | bus private data        |
+	 * | (e.g. iwm_priv_sdio)    |
+	 * +-------------------------+
+	 *
+	 */
+
+	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+	if (!wdev) {
+		dev_err(dev, "Couldn't allocate wireless device\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
+				sizeof(struct iwm_priv) + sizeof_bus);
+	if (!wdev->wiphy) {
+		dev_err(dev, "Couldn't allocate wiphy device\n");
+		ret = -ENOMEM;
+		goto out_err_new;
+	}
+
+	set_wiphy_dev(wdev->wiphy, dev);
+	wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
+	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				       BIT(NL80211_IFTYPE_ADHOC);
+	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
+	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
+	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+	ret = wiphy_register(wdev->wiphy);
+	if (ret < 0) {
+		dev_err(dev, "Couldn't register wiphy device\n");
+		goto out_err_register;
+	}
+
+	return wdev;
+
+ out_err_register:
+	wiphy_free(wdev->wiphy);
+
+ out_err_new:
+	kfree(wdev);
+
+	return ERR_PTR(ret);
+}
+
+void iwm_wdev_free(struct iwm_priv *iwm)
+{
+	struct wireless_dev *wdev = iwm_to_wdev(iwm);
+
+	if (!wdev)
+		return;
+
+	wiphy_unregister(wdev->wiphy);
+	wiphy_free(wdev->wiphy);
+	kfree(wdev);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef __IWM_CFG80211_H__
+#define __IWM_CFG80211_H__
+
+int iwm_cfg80211_inform_bss(struct iwm_priv *iwm);
+struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev);
+void iwm_wdev_free(struct iwm_priv *iwm);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/commands.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/commands.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/commands.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/commands.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,921 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <linux/ieee80211.h>
+
+#include "iwm.h"
+#include "bus.h"
+#include "hal.h"
+#include "umac.h"
+#include "commands.h"
+#include "debug.h"
+
+static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm,
+				     u8 lmac_cmd_id,
+				     const void *lmac_payload,
+				     u16 lmac_payload_size,
+				     u8 resp)
+{
+	struct iwm_udma_wifi_cmd udma_cmd = UDMA_LMAC_INIT;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_lmac_cmd lmac_cmd;
+
+	lmac_cmd.id = lmac_cmd_id;
+
+	umac_cmd.id = UMAC_CMD_OPCODE_WIFI_PASS_THROUGH;
+	umac_cmd.resp = resp;
+
+	return iwm_hal_send_host_cmd(iwm, &udma_cmd, &umac_cmd, &lmac_cmd,
+				     lmac_payload, lmac_payload_size);
+}
+
+int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
+			 bool resp)
+{
+	struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
+	struct iwm_umac_cmd umac_cmd;
+
+	umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
+	umac_cmd.resp = resp;
+
+	return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
+				     payload, payload_size);
+}
+
+static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
+{
+	{4, 3, 0, COEX_UNASSOC_IDLE_FLAGS},
+	{4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
+	{4, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
+	{4, 3, 0, COEX_CALIBRATION_FLAGS},
+	{4, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
+	{4, 3, 0, COEX_CONNECTION_ESTAB_FLAGS},
+	{4, 3, 0, COEX_ASSOCIATED_IDLE_FLAGS},
+	{4, 3, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
+	{4, 3, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
+	{4, 3, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
+	{6, 3, 0, COEX_XOR_RF_ON_FLAGS},
+	{4, 3, 0, COEX_RF_OFF_FLAGS},
+	{6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
+	{4, 3, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
+	{4, 3, 0, COEX_RSRVD1_FLAGS},
+	{4, 3, 0, COEX_RSRVD2_FLAGS}
+};
+
+static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] =
+{
+	{1, 1, 0, COEX_UNASSOC_IDLE_FLAGS},
+	{4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
+	{3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
+	{5, 5, 0, COEX_CALIBRATION_FLAGS},
+	{4, 4, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
+	{5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS},
+	{4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
+	{4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
+	{4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
+	{4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
+	{1, 1, 0, COEX_RF_ON_FLAGS},
+	{1, 1, 0, COEX_RF_OFF_FLAGS},
+	{6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
+	{5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
+	{1, 1, 0, COEX_RSRVD1_FLAGS},
+	{1, 1, 0, COEX_RSRVD2_FLAGS}
+};
+
+int iwm_send_prio_table(struct iwm_priv *iwm)
+{
+	struct iwm_coex_prio_table_cmd coex_table_cmd;
+	u32 coex_enabled, mode_enabled;
+
+	memset(&coex_table_cmd, 0, sizeof(struct iwm_coex_prio_table_cmd));
+
+	coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK;
+
+	switch (iwm->conf.coexist_mode) {
+	case COEX_MODE_XOR:
+	case COEX_MODE_CM:
+		coex_enabled = 1;
+		break;
+	default:
+		coex_enabled = 0;
+		break;
+	}
+
+	switch (iwm->conf.mode) {
+	case UMAC_MODE_BSS:
+	case UMAC_MODE_IBSS:
+		mode_enabled = 1;
+		break;
+	default:
+		mode_enabled = 0;
+		break;
+	}
+
+	if (coex_enabled && mode_enabled) {
+		coex_table_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK |
+					COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK |
+					COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK;
+
+		switch (iwm->conf.coexist_mode) {
+		case COEX_MODE_XOR:
+			memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl,
+			       sizeof(iwm_sta_xor_prio_tbl));
+			break;
+		case COEX_MODE_CM:
+			memcpy(coex_table_cmd.sta_prio, iwm_sta_cm_prio_tbl,
+			       sizeof(iwm_sta_cm_prio_tbl));
+			break;
+		default:
+			IWM_ERR(iwm, "Invalid coex_mode 0x%x\n",
+				iwm->conf.coexist_mode);
+			break;
+		}
+	} else
+		IWM_WARN(iwm, "coexistense disabled\n");
+
+	return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD,
+				&coex_table_cmd,
+				sizeof(struct iwm_coex_prio_table_cmd), 1);
+}
+
+int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
+{
+	struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
+
+	memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
+
+	cal_cfg_cmd.ucode_cfg.init.enable = cpu_to_le32(calib_requested);
+	cal_cfg_cmd.ucode_cfg.init.start = cpu_to_le32(calib_requested);
+	cal_cfg_cmd.ucode_cfg.init.send_res = cpu_to_le32(calib_requested);
+	cal_cfg_cmd.ucode_cfg.flags =
+		cpu_to_le32(CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK);
+
+	return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
+				sizeof(struct iwm_lmac_cal_cfg_cmd), 1);
+}
+
+int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
+{
+	struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
+
+	memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
+
+	cal_cfg_cmd.ucode_cfg.periodic.enable = cpu_to_le32(calib_requested);
+	cal_cfg_cmd.ucode_cfg.periodic.start = cpu_to_le32(calib_requested);
+
+	return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
+				sizeof(struct iwm_lmac_cal_cfg_cmd), 0);
+}
+
+int iwm_store_rxiq_calib_result(struct iwm_priv *iwm)
+{
+	struct iwm_calib_rxiq *rxiq;
+	u8 *eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
+	int grplen = sizeof(struct iwm_calib_rxiq_group);
+
+	rxiq = kzalloc(sizeof(struct iwm_calib_rxiq), GFP_KERNEL);
+	if (!rxiq) {
+		IWM_ERR(iwm, "Couldn't alloc memory for RX IQ\n");
+		return -ENOMEM;
+	}
+
+	eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
+	if (IS_ERR(eeprom_rxiq)) {
+		IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n");
+		kfree(rxiq);
+		return PTR_ERR(eeprom_rxiq);
+	}
+
+	iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].buf = (u8 *)rxiq;
+	iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].size = sizeof(*rxiq);
+
+	rxiq->hdr.opcode = SHILOH_PHY_CALIBRATE_RX_IQ_CMD;
+	rxiq->hdr.first_grp = 0;
+	rxiq->hdr.grp_num = 1;
+	rxiq->hdr.all_data_valid = 1;
+
+	memcpy(&rxiq->group[0], eeprom_rxiq, 4 * grplen);
+	memcpy(&rxiq->group[4], eeprom_rxiq + 6 * grplen, grplen);
+
+	return 0;
+}
+
+int iwm_send_calib_results(struct iwm_priv *iwm)
+{
+	int i, ret = 0;
+
+	for (i = PHY_CALIBRATE_OPCODES_NUM; i < CALIBRATION_CMD_NUM; i++) {
+		if (test_bit(i - PHY_CALIBRATE_OPCODES_NUM,
+			     &iwm->calib_done_map)) {
+			IWM_DBG_CMD(iwm, DBG,
+				    "Send calibration %d result\n", i);
+			ret |= iwm_send_lmac_ptrough_cmd(iwm,
+					REPLY_PHY_CALIBRATION_CMD,
+					iwm->calib_res[i].buf,
+					iwm->calib_res[i].size, 0);
+
+			kfree(iwm->calib_res[i].buf);
+			iwm->calib_res[i].buf = NULL;
+			iwm->calib_res[i].size = 0;
+		}
+	}
+
+	return ret;
+}
+
+int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp)
+{
+	struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_umac_cmd_reset reset;
+
+	reset.flags = reset_flags;
+
+	umac_cmd.id = UMAC_CMD_OPCODE_RESET;
+	umac_cmd.resp = resp;
+
+	return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset,
+				     sizeof(struct iwm_umac_cmd_reset));
+}
+
+int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value)
+{
+	struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_umac_cmd_set_param_fix param;
+
+	if ((tbl != UMAC_PARAM_TBL_CFG_FIX) &&
+	    (tbl != UMAC_PARAM_TBL_FA_CFG_FIX))
+		return -EINVAL;
+
+	umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX;
+	umac_cmd.resp = 0;
+
+	param.tbl = cpu_to_le16(tbl);
+	param.key = cpu_to_le16(key);
+	param.value = cpu_to_le32(value);
+
+	return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &param,
+				     sizeof(struct iwm_umac_cmd_set_param_fix));
+}
+
+int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
+			    void *payload, u16 payload_size)
+{
+	struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_umac_cmd_set_param_var *param_hdr;
+	u8 *param;
+	int ret;
+
+	param = kzalloc(payload_size +
+			sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL);
+	if (!param) {
+		IWM_ERR(iwm, "Couldn't allocate param\n");
+		return -ENOMEM;
+	}
+
+	param_hdr = (struct iwm_umac_cmd_set_param_var *)param;
+
+	umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR;
+	umac_cmd.resp = 0;
+
+	param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR);
+	param_hdr->key = cpu_to_le16(key);
+	param_hdr->len = cpu_to_le16(payload_size);
+	memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var),
+	       payload, payload_size);
+
+	ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param,
+				    sizeof(struct iwm_umac_cmd_set_param_var) +
+				    payload_size);
+	kfree(param);
+
+	return ret;
+}
+
+int iwm_send_umac_config(struct iwm_priv *iwm,
+			 __le32 reset_flags)
+{
+	int ret;
+
+	/* Use UMAC default values */
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_POWER_INDEX, iwm->conf.power_index);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
+				      CFG_FRAG_THRESHOLD,
+				      iwm->conf.frag_threshold);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_RTS_THRESHOLD,
+				      iwm->conf.rts_threshold);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_CTS_TO_SELF, iwm->conf.cts_to_self);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_COEX_MODE, iwm->conf.coexist_mode);
+	if (ret < 0)
+		return ret;
+
+	/*
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_ASSOCIATION_TIMEOUT,
+				      iwm->conf.assoc_timeout);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_ROAM_TIMEOUT,
+				      iwm->conf.roam_timeout);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_WIRELESS_MODE,
+				      WIRELESS_MODE_11A | WIRELESS_MODE_11G);
+	if (ret < 0)
+		return ret;
+	*/
+
+	ret = iwm_umac_set_config_var(iwm, CFG_NET_ADDR,
+				      iwm_to_ndev(iwm)->dev_addr, ETH_ALEN);
+	if (ret < 0)
+		return ret;
+
+	/* UMAC PM static configurations */
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_PM_LEGACY_RX_TIMEOUT, 0x12C);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_PM_LEGACY_TX_TIMEOUT, 0x15E);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_PM_CTRL_FLAGS, 0x30001);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				      CFG_PM_KEEP_ALIVE_IN_BEACONS, 0x80);
+	if (ret < 0)
+		return ret;
+
+	/* reset UMAC */
+	ret = iwm_send_umac_reset(iwm, reset_flags, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
+			       WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id)
+{
+	struct iwm_udma_wifi_cmd udma_cmd;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
+
+	udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */
+	udma_cmd.credit_group = pool_id;
+	udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
+	udma_cmd.lmac_offset = 0;
+
+	umac_cmd.id = REPLY_TX;
+	umac_cmd.color = tx_info->color;
+	umac_cmd.resp = 0;
+
+	return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
+				     skb->data, skb->len);
+}
+
+static int iwm_target_read(struct iwm_priv *iwm, __le32 address,
+			   u8 *response, u32 resp_size)
+{
+	struct iwm_udma_nonwifi_cmd target_cmd;
+	struct iwm_nonwifi_cmd *cmd;
+	u16 seq_num;
+	int ret = 0;
+
+	target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ;
+	target_cmd.addr = address;
+	target_cmd.op1_sz = cpu_to_le32(resp_size);
+	target_cmd.op2 = 0;
+	target_cmd.handle_by_hw = 0;
+	target_cmd.resp = 1;
+	target_cmd.eop = 1;
+
+	ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
+	if (ret < 0)
+		IWM_ERR(iwm, "Couldn't send READ command\n");
+
+	/* When succeding, the send_target routine returns the seq number */
+	seq_num = ret;
+
+	ret = wait_event_interruptible_timeout(iwm->nonwifi_queue,
+		(cmd = iwm_get_pending_nonwifi_cmd(iwm, seq_num,
+					  UMAC_HDI_OUT_OPCODE_READ)) != NULL,
+					       2 * HZ);
+
+	if (!ret) {
+		IWM_ERR(iwm, "Didn't receive a target READ answer\n");
+		return ret;
+	}
+
+	memcpy(response, cmd->buf.hdr + sizeof(struct iwm_udma_in_hdr),
+	       resp_size);
+
+	kfree(cmd);
+
+	return ret;
+}
+
+int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
+{
+	int ret;
+	u8 mac_align[ALIGN(ETH_ALEN, 8)];
+
+	ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR),
+			      mac_align, sizeof(mac_align));
+	if (ret < 0)
+		return ret;
+
+	if (is_valid_ether_addr(mac_align))
+		memcpy(mac, mac_align, ETH_ALEN);
+	else {
+		IWM_ERR(iwm, "Invalid EEPROM MAC\n");
+		memcpy(mac, iwm->conf.mac_addr, ETH_ALEN);
+		get_random_bytes(&mac[3], 3);
+	}
+
+	return 0;
+}
+
+int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
+{
+	struct iwm_umac_tx_key_id tx_key_id;
+
+	if (!iwm->default_key || !iwm->default_key->in_use)
+		return -EINVAL;
+
+	tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
+	tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
+					     sizeof(struct iwm_umac_wifi_if));
+
+	tx_key_id.key_idx = key_idx;
+
+	return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
+}
+
+static int iwm_check_profile(struct iwm_priv *iwm)
+{
+	if (!iwm->umac_profile_active)
+		return -EAGAIN;
+
+	if (iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
+	    iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
+	    iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_TKIP &&
+	    iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_CCMP) {
+		IWM_ERR(iwm, "Wrong unicast cipher: 0x%x\n",
+			iwm->umac_profile->sec.ucast_cipher);
+		return -EAGAIN;
+	}
+
+	if (iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
+	    iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
+	    iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_TKIP &&
+	    iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_CCMP) {
+		IWM_ERR(iwm, "Wrong multicast cipher: 0x%x\n",
+			iwm->umac_profile->sec.mcast_cipher);
+		return -EAGAIN;
+	}
+
+	if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
+	     iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
+	    (iwm->umac_profile->sec.ucast_cipher !=
+	     iwm->umac_profile->sec.mcast_cipher)) {
+		IWM_ERR(iwm, "Unicast and multicast ciphers differ for WEP\n");
+	}
+
+	return 0;
+}
+
+int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
+		struct iwm_key *key)
+{
+	int ret;
+	u8 cmd[64], *sta_addr, *key_data, key_len;
+	s8 key_idx;
+	u16 cmd_size = 0;
+	struct iwm_umac_key_hdr *key_hdr = &key->hdr;
+	struct iwm_umac_key_wep40 *wep40 = (struct iwm_umac_key_wep40 *)cmd;
+	struct iwm_umac_key_wep104 *wep104 = (struct iwm_umac_key_wep104 *)cmd;
+	struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd;
+	struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd;
+
+	if (set_tx_key)
+		iwm->default_key = key;
+
+	/*
+	 * We check if our current profile is valid.
+	 * If not, we dont push the key, we just cache them,
+	 * so that with the next siwsessid call, the keys
+	 * will be actually pushed.
+	 */
+	if (!remove) {
+		ret = iwm_check_profile(iwm);
+		if (ret < 0)
+			return ret;
+	}
+
+	sta_addr = key->hdr.mac;
+	key_data = key->key;
+	key_len = key->key_len;
+	key_idx = key->hdr.key_idx;
+
+	if (!remove) {
+		IWM_DBG_WEXT(iwm, DBG, "key_idx:%d set tx key:%d\n",
+			     key_idx, set_tx_key);
+		IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
+		IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
+		       key_hdr->mac, key_hdr->key_idx, key_hdr->multicast);
+
+		IWM_DBG_WEXT(iwm, DBG, "profile: mcast:0x%x, ucast:0x%x\n",
+			     iwm->umac_profile->sec.mcast_cipher,
+			     iwm->umac_profile->sec.ucast_cipher);
+		IWM_DBG_WEXT(iwm, DBG, "profile: auth_type:0x%x, flags:0x%x\n",
+			     iwm->umac_profile->sec.auth_type,
+			     iwm->umac_profile->sec.flags);
+
+		switch (key->alg) {
+		case UMAC_CIPHER_TYPE_WEP_40:
+			wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY;
+			wep40->hdr.buf_size =
+				cpu_to_le16(sizeof(struct iwm_umac_key_wep40) -
+					    sizeof(struct iwm_umac_wifi_if));
+
+			memcpy(&wep40->key_hdr, key_hdr,
+			       sizeof(struct iwm_umac_key_hdr));
+			memcpy(wep40->key, key_data, key_len);
+			wep40->static_key = 1;
+
+			cmd_size = sizeof(struct iwm_umac_key_wep40);
+			break;
+
+		case UMAC_CIPHER_TYPE_WEP_104:
+			wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY;
+			wep104->hdr.buf_size =
+				cpu_to_le16(sizeof(struct iwm_umac_key_wep104) -
+					    sizeof(struct iwm_umac_wifi_if));
+
+			memcpy(&wep104->key_hdr, key_hdr,
+			       sizeof(struct iwm_umac_key_hdr));
+			memcpy(wep104->key, key_data, key_len);
+			wep104->static_key = 1;
+
+			cmd_size = sizeof(struct iwm_umac_key_wep104);
+			break;
+
+		case UMAC_CIPHER_TYPE_CCMP:
+			key_hdr->key_idx++;
+			ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY;
+			ccmp->hdr.buf_size =
+				cpu_to_le16(sizeof(struct iwm_umac_key_ccmp) -
+					    sizeof(struct iwm_umac_wifi_if));
+
+			memcpy(&ccmp->key_hdr, key_hdr,
+			       sizeof(struct iwm_umac_key_hdr));
+
+			memcpy(ccmp->key, key_data, key_len);
+
+			if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
+				memcpy(ccmp->iv_count, key->rx_seq, 6);
+
+			cmd_size = sizeof(struct iwm_umac_key_ccmp);
+			break;
+
+		case UMAC_CIPHER_TYPE_TKIP:
+			key_hdr->key_idx++;
+			tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY;
+			tkip->hdr.buf_size =
+				cpu_to_le16(sizeof(struct iwm_umac_key_tkip) -
+					    sizeof(struct iwm_umac_wifi_if));
+
+			memcpy(&tkip->key_hdr, key_hdr,
+			       sizeof(struct iwm_umac_key_hdr));
+
+			memcpy(tkip->tkip_key, key_data, IWM_TKIP_KEY_SIZE);
+			memcpy(tkip->mic_tx_key, key_data + IWM_TKIP_KEY_SIZE,
+			       IWM_TKIP_MIC_SIZE);
+			memcpy(tkip->mic_rx_key,
+			       key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE,
+			       IWM_TKIP_MIC_SIZE);
+
+			if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
+				memcpy(ccmp->iv_count, key->rx_seq, 6);
+
+			cmd_size = sizeof(struct iwm_umac_key_tkip);
+			break;
+
+		default:
+			return -ENOTSUPP;
+		}
+
+		if ((key->alg == UMAC_CIPHER_TYPE_CCMP) ||
+		    (key->alg == UMAC_CIPHER_TYPE_TKIP))
+			/*
+			 * UGLY_UGLY_UGLY
+			 * Copied HACK from the MWG driver.
+			 * Without it, the key is set before the second
+			 * EAPOL frame is sent, and the latter is thus
+			 * encrypted.
+			 */
+			schedule_timeout_interruptible(usecs_to_jiffies(300));
+
+		ret =  iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1);
+		if (ret < 0)
+			goto err;
+
+		/*
+		 * We need a default key only if it is set and
+		 * if we're doing WEP.
+		 */
+		if (iwm->default_key == key &&
+			((key->alg == UMAC_CIPHER_TYPE_WEP_40) ||
+			 (key->alg == UMAC_CIPHER_TYPE_WEP_104))) {
+			ret = iwm_set_tx_key(iwm, key_idx);
+			if (ret < 0)
+				goto err;
+		}
+	} else {
+		struct iwm_umac_key_remove key_remove;
+
+		key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY;
+		key_remove.hdr.buf_size =
+			cpu_to_le16(sizeof(struct iwm_umac_key_remove) -
+				    sizeof(struct iwm_umac_wifi_if));
+		memcpy(&key_remove.key_hdr, key_hdr,
+		       sizeof(struct iwm_umac_key_hdr));
+
+		ret =  iwm_send_wifi_if_cmd(iwm, &key_remove,
+					    sizeof(struct iwm_umac_key_remove),
+					    1);
+		if (ret < 0)
+			return ret;
+
+		iwm->keys[key_idx].in_use = 0;
+	}
+
+	return 0;
+
+ err:
+	kfree(key);
+	return ret;
+}
+
+
+int iwm_send_mlme_profile(struct iwm_priv *iwm)
+{
+	int ret, i;
+	struct iwm_umac_profile profile;
+
+	memcpy(&profile, iwm->umac_profile, sizeof(profile));
+
+	profile.hdr.oid = UMAC_WIFI_IF_CMD_SET_PROFILE;
+	profile.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_profile) -
+					   sizeof(struct iwm_umac_wifi_if));
+
+	ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Send profile command failed\n");
+		return ret;
+	}
+
+	/* Wait for the profile to be active */
+	ret = wait_event_interruptible_timeout(iwm->mlme_queue,
+					       iwm->umac_profile_active == 1,
+					       3 * HZ);
+	if (!ret)
+		return -EBUSY;
+
+
+	for (i = 0; i < IWM_NUM_KEYS; i++)
+		if (iwm->keys[i].in_use) {
+			int default_key = 0;
+			struct iwm_key *key = &iwm->keys[i];
+
+			if (key == iwm->default_key)
+				default_key = 1;
+
+			/* Wait for the profile before sending the keys */
+			wait_event_interruptible_timeout(iwm->mlme_queue,
+			     (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) ||
+			      test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)),
+							 3 * HZ);
+
+			ret = iwm_set_key(iwm, 0, default_key, key);
+			if (ret < 0)
+				return ret;
+		}
+
+	return 0;
+}
+
+int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
+{
+	int ret;
+	struct iwm_umac_invalidate_profile invalid;
+
+	invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE;
+	invalid.hdr.buf_size =
+		cpu_to_le16(sizeof(struct iwm_umac_invalidate_profile) -
+			    sizeof(struct iwm_umac_wifi_if));
+
+	invalid.reason = WLAN_REASON_UNSPECIFIED;
+
+	ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
+	if (ret < 0)
+		return ret;
+
+	ret = wait_event_interruptible_timeout(iwm->mlme_queue,
+				 (iwm->umac_profile_active == 0),
+					       2 * HZ);
+	if (!ret)
+		return -EBUSY;
+
+	return 0;
+}
+
+int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
+{
+	struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_umac_cmd_stats_req stats_req;
+
+	stats_req.flags = cpu_to_le32(flags);
+
+	umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST;
+	umac_cmd.resp = 0;
+
+	return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req,
+				     sizeof(struct iwm_umac_cmd_stats_req));
+}
+
+int iwm_send_umac_channel_list(struct iwm_priv *iwm)
+{
+	struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_umac_cmd_get_channel_list *ch_list;
+	int size = sizeof(struct iwm_umac_cmd_get_channel_list) +
+		   sizeof(struct iwm_umac_channel_info) * 4;
+	int ret;
+
+	ch_list = kzalloc(size, GFP_KERNEL);
+	if (!ch_list) {
+		IWM_ERR(iwm, "Couldn't allocate channel list cmd\n");
+		return -ENOMEM;
+	}
+
+	ch_list->ch[0].band = UMAC_BAND_2GHZ;
+	ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ;
+	ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID;
+
+	ch_list->ch[1].band = UMAC_BAND_5GHZ;
+	ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ;
+	ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID;
+
+	ch_list->ch[2].band = UMAC_BAND_2GHZ;
+	ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ;
+	ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
+
+	ch_list->ch[3].band = UMAC_BAND_5GHZ;
+	ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ;
+	ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
+
+	ch_list->count = cpu_to_le16(4);
+
+	umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST;
+	umac_cmd.resp = 1;
+
+	ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size);
+
+	kfree(ch_list);
+
+	return ret;
+}
+
+int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
+		   int ssid_num)
+{
+	struct iwm_umac_cmd_scan_request req;
+	int i, ret;
+
+	memset(&req, 0, sizeof(struct iwm_umac_cmd_scan_request));
+
+	req.hdr.oid = UMAC_WIFI_IF_CMD_SCAN_REQUEST;
+	req.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_cmd_scan_request)
+				       - sizeof(struct iwm_umac_wifi_if));
+	req.type = UMAC_WIFI_IF_SCAN_TYPE_USER;
+	req.timeout = 2;
+	req.seq_num = iwm->scan_id;
+	req.ssid_num = min(ssid_num, UMAC_WIFI_IF_PROBE_OPTION_MAX);
+
+	for (i = 0; i < req.ssid_num; i++) {
+		memcpy(req.ssids[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
+		req.ssids[i].ssid_len = ssids[i].ssid_len;
+	}
+
+	ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't send scan request\n");
+		return ret;
+	}
+
+	iwm->scan_id = iwm->scan_id++ % IWM_SCAN_ID_MAX;
+
+	return 0;
+}
+
+int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len)
+{
+	struct cfg80211_ssid one_ssid;
+
+	if (test_and_set_bit(IWM_STATUS_SCANNING, &iwm->status))
+		return 0;
+
+	one_ssid.ssid_len = min(ssid_len, IEEE80211_MAX_SSID_LEN);
+	memcpy(&one_ssid.ssid, ssid, one_ssid.ssid_len);
+
+	return iwm_scan_ssids(iwm, &one_ssid, 1);
+}
+
+int iwm_target_reset(struct iwm_priv *iwm)
+{
+	struct iwm_udma_nonwifi_cmd target_cmd;
+
+	target_cmd.opcode = UMAC_HDI_OUT_OPCODE_REBOOT;
+	target_cmd.addr = 0;
+	target_cmd.op1_sz = 0;
+	target_cmd.op2 = 0;
+	target_cmd.handle_by_hw = 0;
+	target_cmd.resp = 0;
+	target_cmd.eop = 1;
+
+	return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/commands.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/commands.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/commands.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/commands.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,419 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_COMMANDS_H__
+#define __IWM_COMMANDS_H__
+
+#include <linux/ieee80211.h>
+
+#define IWM_BARKER_REBOOT_NOTIFICATION	0xF
+#define IWM_ACK_BARKER_NOTIFICATION	0x10
+
+/* UMAC commands */
+#define UMAC_RST_CTRL_FLG_LARC_CLK_EN	0x0001
+#define UMAC_RST_CTRL_FLG_LARC_RESET	0x0002
+#define UMAC_RST_CTRL_FLG_FUNC_RESET	0x0004
+#define UMAC_RST_CTRL_FLG_DEV_RESET	0x0008
+#define UMAC_RST_CTRL_FLG_WIFI_CORE_EN	0x0010
+#define UMAC_RST_CTRL_FLG_WIFI_LINK_EN	0x0040
+#define UMAC_RST_CTRL_FLG_WIFI_MLME_EN	0x0080
+#define UMAC_RST_CTRL_FLG_NVM_RELOAD	0x0100
+
+struct iwm_umac_cmd_reset {
+	__le32 flags;
+} __attribute__ ((packed));
+
+#define UMAC_PARAM_TBL_ORD_FIX    0x0
+#define UMAC_PARAM_TBL_ORD_VAR    0x1
+#define UMAC_PARAM_TBL_CFG_FIX    0x2
+#define UMAC_PARAM_TBL_CFG_VAR    0x3
+#define UMAC_PARAM_TBL_BSS_TRK    0x4
+#define UMAC_PARAM_TBL_FA_CFG_FIX 0x5
+#define UMAC_PARAM_TBL_STA        0x6
+#define UMAC_PARAM_TBL_CHN        0x7
+#define UMAC_PARAM_TBL_STATISTICS 0x8
+
+/* fast access table */
+enum {
+	CFG_FRAG_THRESHOLD = 0,
+	CFG_FRAME_RETRY_LIMIT,
+	CFG_OS_QUEUE_UTIL_TH,
+	CFG_RX_FILTER,
+	/* <-- LAST --> */
+	FAST_ACCESS_CFG_TBL_FIX_LAST
+};
+
+/* fixed size table */
+enum {
+	CFG_POWER_INDEX = 0,
+	CFG_PM_LEGACY_RX_TIMEOUT,
+	CFG_PM_LEGACY_TX_TIMEOUT,
+	CFG_PM_CTRL_FLAGS,
+	CFG_PM_KEEP_ALIVE_IN_BEACONS,
+	CFG_BT_ON_THRESHOLD,
+	CFG_RTS_THRESHOLD,
+	CFG_CTS_TO_SELF,
+	CFG_COEX_MODE,
+	CFG_WIRELESS_MODE,
+	CFG_ASSOCIATION_TIMEOUT,
+	CFG_ROAM_TIMEOUT,
+	CFG_CAPABILITY_SUPPORTED_RATES,
+	CFG_SCAN_ALLOWED_UNASSOC_FLAGS,
+	CFG_SCAN_ALLOWED_MAIN_ASSOC_FLAGS,
+	CFG_SCAN_ALLOWED_PAN_ASSOC_FLAGS,
+	CFG_SCAN_INTERNAL_PERIODIC_ENABLED,
+	CFG_SCAN_IMM_INTERNAL_PERIODIC_SCAN_ON_INIT,
+	CFG_SCAN_DEFAULT_PERIODIC_FREQ_SEC,
+	CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN,
+	CFG_TLC_SUPPORTED_TX_HT_RATES,
+	CFG_TLC_SUPPORTED_TX_RATES,
+	CFG_TLC_VALID_ANTENNA,
+	CFG_TLC_SPATIAL_STREAM_SUPPORTED,
+	CFG_TLC_RETRY_PER_RATE,
+	CFG_TLC_RETRY_PER_HT_RATE,
+	CFG_TLC_FIXED_RATE,
+	CFG_TLC_FIXED_RATE_FLAGS,
+	CFG_TLC_CONTROL_FLAGS,
+	CFG_TLC_SR_MIN_FAIL,
+	CFG_TLC_SR_MIN_PASS,
+	CFG_TLC_HT_STAY_IN_COL_PASS_THRESH,
+	CFG_TLC_HT_STAY_IN_COL_FAIL_THRESH,
+	CFG_TLC_LEGACY_STAY_IN_COL_PASS_THRESH,
+	CFG_TLC_LEGACY_STAY_IN_COL_FAIL_THRESH,
+	CFG_TLC_HT_FLUSH_STATS_PACKETS,
+	CFG_TLC_LEGACY_FLUSH_STATS_PACKETS,
+	CFG_TLC_LEGACY_FLUSH_STATS_MS,
+	CFG_TLC_HT_FLUSH_STATS_MS,
+	CFG_TLC_STAY_IN_COL_TIME_OUT,
+	CFG_TLC_AGG_SHORT_LIM,
+	CFG_TLC_AGG_LONG_LIM,
+	CFG_TLC_HT_SR_NO_DECREASE,
+	CFG_TLC_LEGACY_SR_NO_DECREASE,
+	CFG_TLC_SR_FORCE_DECREASE,
+	CFG_TLC_SR_ALLOW_INCREASE,
+	CFG_TLC_AGG_SET_LONG,
+	CFG_TLC_AUTO_AGGREGATION,
+	CFG_TLC_AGG_THRESHOLD,
+	CFG_TLC_TID_LOAD_THRESHOLD,
+	CFG_TLC_BLOCK_ACK_TIMEOUT,
+	CFG_TLC_NO_BA_COUNTED_AS_ONE,
+	CFG_TLC_NUM_BA_STREAMS_ALLOWED,
+	CFG_TLC_NUM_BA_STREAMS_PRESENT,
+	CFG_TLC_RENEW_ADDBA_DELAY,
+	CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD,
+	CFG_TLC_IS_STABLE_IN_HT,
+	CFG_RLC_CHAIN_CTRL,
+	CFG_TRK_TABLE_OP_MODE,
+	CFG_TRK_TABLE_RSSI_THRESHOLD,
+	CFG_TX_PWR_TARGET, /* Used By xVT */
+	CFG_TX_PWR_LIMIT_USR,
+	CFG_TX_PWR_LIMIT_BSS, /* 11d limit */
+	CFG_TX_PWR_LIMIT_BSS_CONSTRAINT, /* 11h constraint */
+	CFG_TX_PWR_MODE,
+	CFG_MLME_DBG_NOTIF_BLOCK,
+	CFG_BT_OFF_BECONS_INTERVALS,
+	CFG_BT_FRAG_DURATION,
+
+	/* <-- LAST --> */
+	CFG_TBL_FIX_LAST
+};
+
+/* variable size table */
+enum {
+	CFG_NET_ADDR = 0,
+	CFG_PROFILE,
+	/* <-- LAST --> */
+	CFG_TBL_VAR_LAST
+};
+
+struct iwm_umac_cmd_set_param_fix {
+	__le16 tbl;
+	__le16 key;
+	__le32 value;
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_set_param_var {
+	__le16 tbl;
+	__le16 key;
+	__le16 len;
+	__le16 reserved;
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_get_param {
+	__le16 tbl;
+	__le16 key;
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_get_param_resp {
+	__le16 tbl;
+	__le16 key;
+	__le16 len;
+	__le16 reserved;
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_eeprom_proxy_hdr {
+	__le32 type;
+	__le32 offset;
+	__le32 len;
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_eeprom_proxy {
+	struct iwm_umac_cmd_eeprom_proxy_hdr hdr;
+	u8 buf[0];
+} __attribute__ ((packed));
+
+#define IWM_UMAC_CMD_EEPROM_TYPE_READ       0x1
+#define IWM_UMAC_CMD_EEPROM_TYPE_WRITE      0x2
+
+#define UMAC_CHANNEL_FLAG_VALID		BIT(0)
+#define UMAC_CHANNEL_FLAG_IBSS		BIT(1)
+#define UMAC_CHANNEL_FLAG_ACTIVE	BIT(3)
+#define UMAC_CHANNEL_FLAG_RADAR		BIT(4)
+#define UMAC_CHANNEL_FLAG_DFS		BIT(7)
+
+struct iwm_umac_channel_info {
+	u8 band;
+	u8 type;
+	u8 reserved;
+	u8 flags;
+	__le32 channels_mask;
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_get_channel_list {
+	__le16 count;
+	__le16 reserved;
+	struct iwm_umac_channel_info ch[0];
+} __attribute__ ((packed));
+
+
+/* UMAC WiFi interface commands */
+
+/* Coexistence mode */
+#define COEX_MODE_SA  0x1
+#define COEX_MODE_XOR 0x2
+#define COEX_MODE_CM  0x3
+#define COEX_MODE_MAX 0x4
+
+/* Wireless mode */
+#define WIRELESS_MODE_11A  0x1
+#define WIRELESS_MODE_11G  0x2
+
+#define UMAC_PROFILE_EX_IE_REQUIRED	0x1
+#define UMAC_PROFILE_QOS_ALLOWED	0x2
+
+/* Scanning */
+#define UMAC_WIFI_IF_PROBE_OPTION_MAX        10
+
+#define UMAC_WIFI_IF_SCAN_TYPE_USER          0x0
+#define UMAC_WIFI_IF_SCAN_TYPE_UMAC_RESERVED 0x1
+#define UMAC_WIFI_IF_SCAN_TYPE_HOST_PERIODIC 0x2
+#define UMAC_WIFI_IF_SCAN_TYPE_MAX           0x3
+
+struct iwm_umac_ssid {
+	u8 ssid_len;
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+	u8 reserved[3];
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_scan_request {
+	struct iwm_umac_wifi_if hdr;
+	__le32 type; /* UMAC_WIFI_IF_SCAN_TYPE_* */
+	u8 ssid_num;
+	u8 seq_num;
+	u8 timeout; /* In seconds */
+	u8 reserved;
+	struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX];
+} __attribute__ ((packed));
+
+#define UMAC_CIPHER_TYPE_NONE		0xFF
+#define UMAC_CIPHER_TYPE_USE_GROUPCAST	0x00
+#define UMAC_CIPHER_TYPE_WEP_40		0x01
+#define UMAC_CIPHER_TYPE_WEP_104	0x02
+#define UMAC_CIPHER_TYPE_TKIP		0x04
+#define UMAC_CIPHER_TYPE_CCMP		0x08
+
+/* Supported authentication types - bitmap */
+#define UMAC_AUTH_TYPE_OPEN		0x00
+#define UMAC_AUTH_TYPE_LEGACY_PSK	0x01
+#define UMAC_AUTH_TYPE_8021X		0x02
+#define UMAC_AUTH_TYPE_RSNA_PSK		0x04
+
+/* iwm_umac_security.flag is WPA supported -- bits[0:0] */
+#define UMAC_SEC_FLG_WPA_ON_POS		0
+#define UMAC_SEC_FLG_WPA_ON_SEED	1
+#define UMAC_SEC_FLG_WPA_ON_MSK (UMAC_SEC_FLG_WPA_ON_SEED << \
+				 UMAC_SEC_FLG_WPA_ON_POS)
+
+/* iwm_umac_security.flag is WPA2 supported -- bits [1:1] */
+#define UMAC_SEC_FLG_RSNA_ON_POS	1
+#define UMAC_SEC_FLG_RSNA_ON_SEED	1
+#define UMAC_SEC_FLG_RSNA_ON_MSK        (UMAC_SEC_FLG_RSNA_ON_SEED << \
+					 UMAC_SEC_FLG_RSNA_ON_POS)
+
+/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */
+#define UMAC_SEC_FLG_WSC_ON_POS		2
+#define UMAC_SEC_FLG_WSC_ON_SEED	1
+
+/* Legacy profile can use only WEP40 and WEP104 for encryption and
+ * OPEN or PSK for authentication */
+#define UMAC_SEC_FLG_LEGACY_PROFILE	0
+
+struct iwm_umac_security {
+	u8 auth_type;
+	u8 ucast_cipher;
+	u8 mcast_cipher;
+	u8 flags;
+} __attribute__ ((packed));
+
+struct iwm_umac_ibss {
+	u8 beacon_interval;	/* in millisecond */
+	u8 atim;		/* in millisecond */
+	s8 join_only;
+	u8 band;
+	u8 channel;
+	u8 reserved[3];
+} __attribute__ ((packed));
+
+#define UMAC_MODE_BSS	0
+#define UMAC_MODE_IBSS	1
+
+#define UMAC_BSSID_MAX	4
+
+struct iwm_umac_profile {
+	struct iwm_umac_wifi_if hdr;
+	__le32 mode;
+	struct iwm_umac_ssid ssid;
+	u8 bssid[UMAC_BSSID_MAX][ETH_ALEN];
+	struct iwm_umac_security sec;
+	struct iwm_umac_ibss ibss;
+	__le32 channel_2ghz;
+	__le32 channel_5ghz;
+	__le16 flags;
+	u8 wireless_mode;
+	u8 bss_num;
+} __attribute__ ((packed));
+
+struct iwm_umac_invalidate_profile {
+	struct iwm_umac_wifi_if hdr;
+	u8 reason;
+	u8 reserved[3];
+} __attribute__ ((packed));
+
+/* Encryption key commands */
+struct iwm_umac_key_wep40 {
+	struct iwm_umac_wifi_if hdr;
+	struct iwm_umac_key_hdr key_hdr;
+	u8 key[WLAN_KEY_LEN_WEP40];
+	u8 static_key;
+	u8 reserved[2];
+} __attribute__ ((packed));
+
+struct iwm_umac_key_wep104 {
+	struct iwm_umac_wifi_if hdr;
+	struct iwm_umac_key_hdr key_hdr;
+	u8 key[WLAN_KEY_LEN_WEP104];
+	u8 static_key;
+	u8 reserved[2];
+} __attribute__ ((packed));
+
+#define IWM_TKIP_KEY_SIZE 16
+#define IWM_TKIP_MIC_SIZE 8
+struct iwm_umac_key_tkip {
+	struct iwm_umac_wifi_if hdr;
+	struct iwm_umac_key_hdr key_hdr;
+	u8 iv_count[6];
+	u8 reserved[2];
+	u8 tkip_key[IWM_TKIP_KEY_SIZE];
+	u8 mic_rx_key[IWM_TKIP_MIC_SIZE];
+	u8 mic_tx_key[IWM_TKIP_MIC_SIZE];
+} __attribute__ ((packed));
+
+struct iwm_umac_key_ccmp {
+	struct iwm_umac_wifi_if hdr;
+	struct iwm_umac_key_hdr key_hdr;
+	u8 iv_count[6];
+	u8 reserved[2];
+	u8 key[WLAN_KEY_LEN_CCMP];
+} __attribute__ ((packed));
+
+struct iwm_umac_key_remove {
+	struct iwm_umac_wifi_if hdr;
+	struct iwm_umac_key_hdr key_hdr;
+} __attribute__ ((packed));
+
+struct iwm_umac_tx_key_id {
+	struct iwm_umac_wifi_if hdr;
+	u8 key_idx;
+	u8 reserved[3];
+} __attribute__ ((packed));
+
+struct iwm_umac_cmd_stats_req {
+	__le32 flags;
+} __attribute__ ((packed));
+
+/* LMAC commands */
+int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
+int iwm_send_prio_table(struct iwm_priv *iwm);
+int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
+int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
+int iwm_send_calib_results(struct iwm_priv *iwm);
+int iwm_store_rxiq_calib_result(struct iwm_priv *iwm);
+
+/* UMAC commands */
+int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
+			 bool resp);
+int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp);
+int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value);
+int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
+			    void *payload, u16 payload_size);
+int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags);
+int iwm_send_mlme_profile(struct iwm_priv *iwm);
+int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
+int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
+int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
+int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
+		struct iwm_key *key);
+int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags);
+int iwm_send_umac_channel_list(struct iwm_priv *iwm);
+int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
+		   int ssid_num);
+int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
+
+/* UDMA commands */
+int iwm_target_reset(struct iwm_priv *iwm);
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/debugfs.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/debugfs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/debugfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,453 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+
+#include "iwm.h"
+#include "bus.h"
+#include "rx.h"
+#include "debug.h"
+
+static struct {
+	u8 id;
+	char *name;
+} iwm_debug_module[__IWM_DM_NR] = {
+	 {IWM_DM_BOOT, "boot"},
+	 {IWM_DM_FW,   "fw"},
+	 {IWM_DM_SDIO, "sdio"},
+	 {IWM_DM_NTF,  "ntf"},
+	 {IWM_DM_RX,   "rx"},
+	 {IWM_DM_TX,   "tx"},
+	 {IWM_DM_MLME, "mlme"},
+	 {IWM_DM_CMD,  "cmd"},
+	 {IWM_DM_WEXT,  "wext"},
+};
+
+#define add_dbg_module(dbg, name, id, initlevel) 	\
+do {							\
+	struct dentry *d;				\
+	dbg.dbg_module[id] = (initlevel);		\
+	d = debugfs_create_x8(name, 0600, dbg.dbgdir,	\
+			     &(dbg.dbg_module[id]));	\
+	if (!IS_ERR(d))					\
+		dbg.dbg_module_dentries[id] = d;        \
+} while (0)
+
+static int iwm_debugfs_u32_read(void *data, u64 *val)
+{
+	struct iwm_priv *iwm = data;
+
+	*val = iwm->dbg.dbg_level;
+	return 0;
+}
+
+static int iwm_debugfs_dbg_level_write(void *data, u64 val)
+{
+	struct iwm_priv *iwm = data;
+	int i;
+
+	iwm->dbg.dbg_level = val;
+
+	for (i = 0; i < __IWM_DM_NR; i++)
+		iwm->dbg.dbg_module[i] = val;
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_level,
+			iwm_debugfs_u32_read, iwm_debugfs_dbg_level_write,
+			"%llu\n");
+
+static int iwm_debugfs_dbg_modules_write(void *data, u64 val)
+{
+	struct iwm_priv *iwm = data;
+	int i, bit;
+
+	iwm->dbg.dbg_modules = val;
+
+	for (i = 0; i < __IWM_DM_NR; i++)
+		iwm->dbg.dbg_module[i] = 0;
+
+	for_each_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
+		iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level;
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules,
+			iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
+			"%llu\n");
+
+static int iwm_txrx_open(struct inode *inode, struct file *filp)
+{
+	filp->private_data = inode->i_private;
+	return 0;
+}
+
+
+static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer,
+				   size_t count, loff_t *ppos)
+{
+	struct iwm_priv *iwm = filp->private_data;
+	char *buf;
+	int i, buf_len = 4096;
+	size_t len = 0;
+	ssize_t ret;
+
+	if (*ppos != 0)
+		return 0;
+	if (count < sizeof(buf))
+		return -ENOSPC;
+
+	buf = kzalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (i = 0; i < IWM_TX_QUEUES; i++) {
+		struct iwm_tx_queue *txq = &iwm->txq[i];
+		struct sk_buff *skb;
+		int j;
+		unsigned long flags;
+
+		spin_lock_irqsave(&txq->queue.lock, flags);
+
+		skb = (struct sk_buff *)&txq->queue;
+
+		len += snprintf(buf + len, buf_len - len, "TXQ #%d\n", i);
+		len += snprintf(buf + len, buf_len - len, "\tStopped:     %d\n",
+				__netif_subqueue_stopped(iwm_to_ndev(iwm),
+							 txq->id));
+		len += snprintf(buf + len, buf_len - len, "\tConcat count:%d\n",
+				txq->concat_count);
+		len += snprintf(buf + len, buf_len - len, "\tQueue len:   %d\n",
+				skb_queue_len(&txq->queue));
+		for (j = 0; j < skb_queue_len(&txq->queue); j++) {
+			struct iwm_tx_info *tx_info;
+
+			skb = skb->next;
+			tx_info = skb_to_tx_info(skb);
+
+			len += snprintf(buf + len, buf_len - len,
+					"\tSKB #%d\n", j);
+			len += snprintf(buf + len, buf_len - len,
+					"\t\tsta:   %d\n", tx_info->sta);
+			len += snprintf(buf + len, buf_len - len,
+					"\t\tcolor: %d\n", tx_info->color);
+			len += snprintf(buf + len, buf_len - len,
+					"\t\ttid:   %d\n", tx_info->tid);
+		}
+
+		spin_unlock_irqrestore(&txq->queue.lock, flags);
+	}
+
+	ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
+	kfree(buf);
+
+	return ret;
+}
+
+static ssize_t iwm_debugfs_tx_credit_read(struct file *filp,
+					  char __user *buffer,
+					  size_t count, loff_t *ppos)
+{
+	struct iwm_priv *iwm = filp->private_data;
+	struct iwm_tx_credit *credit = &iwm->tx_credit;
+	char *buf;
+	int i, buf_len = 4096;
+	size_t len = 0;
+	ssize_t ret;
+
+	if (*ppos != 0)
+		return 0;
+	if (count < sizeof(buf))
+		return -ENOSPC;
+
+	buf = kzalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	len += snprintf(buf + len, buf_len - len,
+			"NR pools:  %d\n", credit->pool_nr);
+	len += snprintf(buf + len, buf_len - len,
+			"pools map: 0x%lx\n", credit->full_pools_map);
+
+	len += snprintf(buf + len, buf_len - len, "\n### POOLS ###\n");
+	for (i = 0; i < IWM_MACS_OUT_GROUPS; i++) {
+		len += snprintf(buf + len, buf_len - len,
+				"pools entry #%d\n", i);
+		len += snprintf(buf + len, buf_len - len,
+				"\tid:          %d\n",
+				credit->pools[i].id);
+		len += snprintf(buf + len, buf_len - len,
+				"\tsid:         %d\n",
+				credit->pools[i].sid);
+		len += snprintf(buf + len, buf_len - len,
+				"\tmin_pages:   %d\n",
+				credit->pools[i].min_pages);
+		len += snprintf(buf + len, buf_len - len,
+				"\tmax_pages:   %d\n",
+				credit->pools[i].max_pages);
+		len += snprintf(buf + len, buf_len - len,
+				"\talloc_pages: %d\n",
+				credit->pools[i].alloc_pages);
+		len += snprintf(buf + len, buf_len - len,
+				"\tfreed_pages: %d\n",
+				credit->pools[i].total_freed_pages);
+	}
+
+	len += snprintf(buf + len, buf_len - len, "\n### SPOOLS ###\n");
+	for (i = 0; i < IWM_MACS_OUT_SGROUPS; i++) {
+		len += snprintf(buf + len, buf_len - len,
+				"spools entry #%d\n", i);
+		len += snprintf(buf + len, buf_len - len,
+				"\tid:          %d\n",
+				credit->spools[i].id);
+		len += snprintf(buf + len, buf_len - len,
+				"\tmax_pages:   %d\n",
+				credit->spools[i].max_pages);
+		len += snprintf(buf + len, buf_len - len,
+				"\talloc_pages: %d\n",
+				credit->spools[i].alloc_pages);
+
+	}
+
+	ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
+	kfree(buf);
+
+	return ret;
+}
+
+static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
+					  char __user *buffer,
+					  size_t count, loff_t *ppos)
+{
+	struct iwm_priv *iwm = filp->private_data;
+	struct iwm_rx_ticket_node *ticket, *next;
+	char *buf;
+	int buf_len = 4096, i;
+	size_t len = 0;
+	ssize_t ret;
+
+	if (*ppos != 0)
+		return 0;
+	if (count < sizeof(buf))
+		return -ENOSPC;
+
+	buf = kzalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
+		len += snprintf(buf + len, buf_len - len, "Ticket #%d\n",
+				ticket->ticket->id);
+		len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n",
+				ticket->ticket->action);
+		len += snprintf(buf + len, buf_len - len, "\tflags:  0x%x\n",
+				ticket->ticket->flags);
+	}
+
+	for (i = 0; i < IWM_RX_ID_HASH; i++) {
+		struct iwm_rx_packet *packet, *nxt;
+		struct list_head *pkt_list = &iwm->rx_packets[i];
+		if (!list_empty(pkt_list)) {
+			len += snprintf(buf + len, buf_len - len,
+					"Packet hash #%d\n", i);
+			list_for_each_entry_safe(packet, nxt, pkt_list, node) {
+				len += snprintf(buf + len, buf_len - len,
+						"\tPacket id:     %d\n",
+						packet->id);
+				len += snprintf(buf + len, buf_len - len,
+						"\tPacket length: %lu\n",
+						packet->pkt_size);
+			}
+		}
+	}
+
+	ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
+	kfree(buf);
+
+	return ret;
+}
+
+
+static const struct file_operations iwm_debugfs_txq_fops = {
+	.owner =	THIS_MODULE,
+	.open =		iwm_txrx_open,
+	.read =		iwm_debugfs_txq_read,
+};
+
+static const struct file_operations iwm_debugfs_tx_credit_fops = {
+	.owner =	THIS_MODULE,
+	.open =		iwm_txrx_open,
+	.read =		iwm_debugfs_tx_credit_read,
+};
+
+static const struct file_operations iwm_debugfs_rx_ticket_fops = {
+	.owner =	THIS_MODULE,
+	.open =		iwm_txrx_open,
+	.read =		iwm_debugfs_rx_ticket_read,
+};
+
+int iwm_debugfs_init(struct iwm_priv *iwm)
+{
+	int i, result;
+	char devdir[16];
+
+	iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	result = PTR_ERR(iwm->dbg.rootdir);
+	if (!result || IS_ERR(iwm->dbg.rootdir)) {
+		if (result == -ENODEV) {
+			IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not "
+				"enabled in kernel config\n");
+			result = 0;	/* No debugfs support */
+		}
+		IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result);
+		goto error;
+	}
+
+	snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm)));
+
+	iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir);
+	result = PTR_ERR(iwm->dbg.devdir);
+	if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create devdir: %d\n", result);
+		goto error;
+	}
+
+	iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir);
+	result = PTR_ERR(iwm->dbg.dbgdir);
+	if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result);
+		goto error;
+	}
+
+	iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir);
+	result = PTR_ERR(iwm->dbg.rxdir);
+	if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result);
+		goto error;
+	}
+
+	iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir);
+	result = PTR_ERR(iwm->dbg.txdir);
+	if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result);
+		goto error;
+	}
+
+	iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir);
+	result = PTR_ERR(iwm->dbg.busdir);
+	if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result);
+		goto error;
+	}
+
+	if (iwm->bus_ops->debugfs_init) {
+		result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
+		if (result < 0) {
+			IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result);
+			goto error;
+		}
+	}
+
+
+	iwm->dbg.dbg_level = IWM_DL_NONE;
+	iwm->dbg.dbg_level_dentry =
+		debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,
+				    &fops_iwm_dbg_level);
+	result = PTR_ERR(iwm->dbg.dbg_level_dentry);
+	if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result);
+		goto error;
+	}
+
+
+	iwm->dbg.dbg_modules = IWM_DM_DEFAULT;
+	iwm->dbg.dbg_modules_dentry =
+		debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,
+				    &fops_iwm_dbg_modules);
+	result = PTR_ERR(iwm->dbg.dbg_modules_dentry);
+	if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result);
+		goto error;
+	}
+
+	for (i = 0; i < __IWM_DM_NR; i++)
+		add_dbg_module(iwm->dbg, iwm_debug_module[i].name,
+			       iwm_debug_module[i].id, IWM_DL_DEFAULT);
+
+	iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,
+						  iwm->dbg.txdir, iwm,
+						  &iwm_debugfs_txq_fops);
+	result = PTR_ERR(iwm->dbg.txq_dentry);
+	if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result);
+		goto error;
+	}
+
+	iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,
+						   iwm->dbg.txdir, iwm,
+						   &iwm_debugfs_tx_credit_fops);
+	result = PTR_ERR(iwm->dbg.tx_credit_dentry);
+	if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result);
+		goto error;
+	}
+
+	iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,
+						  iwm->dbg.rxdir, iwm,
+						  &iwm_debugfs_rx_ticket_fops);
+	result = PTR_ERR(iwm->dbg.rx_ticket_dentry);
+	if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result);
+		goto error;
+	}
+
+	return 0;
+
+ error:
+	return result;
+}
+
+void iwm_debugfs_exit(struct iwm_priv *iwm)
+{
+	int i;
+
+	for (i = 0; i < __IWM_DM_NR; i++)
+		debugfs_remove(iwm->dbg.dbg_module_dentries[i]);
+
+	debugfs_remove(iwm->dbg.dbg_modules_dentry);
+	debugfs_remove(iwm->dbg.dbg_level_dentry);
+	debugfs_remove(iwm->dbg.txq_dentry);
+	debugfs_remove(iwm->dbg.tx_credit_dentry);
+	debugfs_remove(iwm->dbg.rx_ticket_dentry);
+	if (iwm->bus_ops->debugfs_exit)
+		iwm->bus_ops->debugfs_exit(iwm);
+
+	debugfs_remove(iwm->dbg.busdir);
+	debugfs_remove(iwm->dbg.dbgdir);
+	debugfs_remove(iwm->dbg.txdir);
+	debugfs_remove(iwm->dbg.rxdir);
+	debugfs_remove(iwm->dbg.devdir);
+	debugfs_remove(iwm->dbg.rootdir);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/debug.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/debug.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/debug.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/debug.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,124 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef __IWM_DEBUG_H__
+#define __IWM_DEBUG_H__
+
+#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a)
+#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a)
+#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a)
+#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a)
+
+#ifdef CONFIG_IWM_DEBUG
+
+#define IWM_DEBUG_MODULE(i, level, module, f, a...)			     \
+do {									     \
+	if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
+		dev_printk(KERN_INFO, (iwm_to_dev(i)),	             \
+			   "%s " f, __func__ , ## a);			     \
+} while (0)
+
+#define IWM_HEXDUMP(i, level, module, pref, buf, len)		             \
+do {									     \
+	if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
+		print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET,	     \
+			       16, 1, buf, len, 1);			     \
+} while (0)
+
+#else
+
+#define IWM_DEBUG_MODULE(i, level, module, f, a...)
+#define IWM_HEXDUMP(i, level, module, pref, buf, len)
+
+#endif /* CONFIG_IWM_DEBUG */
+
+/* Debug modules */
+enum iwm_debug_module_id {
+	IWM_DM_BOOT = 0,
+	IWM_DM_FW,
+	IWM_DM_SDIO,
+	IWM_DM_NTF,
+	IWM_DM_RX,
+	IWM_DM_TX,
+	IWM_DM_MLME,
+	IWM_DM_CMD,
+	IWM_DM_WEXT,
+	__IWM_DM_NR,
+};
+#define IWM_DM_DEFAULT 0
+
+#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a)
+#define IWM_DBG_FW(i, l, f, a...)   IWM_DEBUG_MODULE(i, l, FW, f, ## a)
+#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a)
+#define IWM_DBG_NTF(i, l, f, a...)  IWM_DEBUG_MODULE(i, l, NTF, f, ## a)
+#define IWM_DBG_RX(i, l, f, a...)   IWM_DEBUG_MODULE(i, l, RX, f, ## a)
+#define IWM_DBG_TX(i, l, f, a...)   IWM_DEBUG_MODULE(i, l, TX, f, ## a)
+#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a)
+#define IWM_DBG_CMD(i, l, f, a...)  IWM_DEBUG_MODULE(i, l, CMD, f, ## a)
+#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a)
+
+/* Debug levels */
+enum iwm_debug_level {
+	IWM_DL_NONE = 0,
+	IWM_DL_ERR,
+	IWM_DL_WARN,
+	IWM_DL_INFO,
+	IWM_DL_DBG,
+};
+#define IWM_DL_DEFAULT IWM_DL_ERR
+
+struct iwm_debugfs {
+	struct iwm_priv *iwm;
+	struct dentry *rootdir;
+	struct dentry *devdir;
+	struct dentry *dbgdir;
+	struct dentry *txdir;
+	struct dentry *rxdir;
+	struct dentry *busdir;
+
+	u32 dbg_level;
+	struct dentry *dbg_level_dentry;
+
+	unsigned long dbg_modules;
+	struct dentry *dbg_modules_dentry;
+
+	u8 dbg_module[__IWM_DM_NR];
+	struct dentry *dbg_module_dentries[__IWM_DM_NR];
+
+	struct dentry *txq_dentry;
+	struct dentry *tx_credit_dentry;
+	struct dentry *rx_ticket_dentry;
+};
+
+#ifdef CONFIG_IWM_DEBUG
+int iwm_debugfs_init(struct iwm_priv *iwm);
+void iwm_debugfs_exit(struct iwm_priv *iwm);
+#else
+static inline int iwm_debugfs_init(struct iwm_priv *iwm)
+{
+	return 0;
+}
+static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
+#endif
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include "iwm.h"
+#include "umac.h"
+#include "commands.h"
+#include "eeprom.h"
+
+static struct iwm_eeprom_entry eeprom_map[] = {
+	[IWM_EEPROM_SIG] =
+	{"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN},
+
+	[IWM_EEPROM_VERSION] =
+	{"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN},
+
+	[IWM_EEPROM_OEM_HW_VERSION] =
+	{"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF,
+	 IWM_EEPROM_OEM_HW_VERSION_LEN},
+
+	[IWM_EEPROM_MAC_VERSION] =
+	{"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN},
+
+	[IWM_EEPROM_CARD_ID] =
+	{"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN},
+
+	[IWM_EEPROM_RADIO_CONF] =
+	{"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN},
+
+	[IWM_EEPROM_SKU_CAP] =
+	{"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN},
+
+	[IWM_EEPROM_CALIB_RXIQ_OFFSET] =
+	{"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN},
+
+	[IWM_EEPROM_CALIB_RXIQ] =
+	{"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN},
+};
+
+
+static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id)
+{
+	int ret;
+	u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0;
+	u32 addr;
+	struct iwm_udma_wifi_cmd udma_cmd;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_umac_cmd_eeprom_proxy eeprom_cmd;
+
+	if (eeprom_id > (IWM_EEPROM_LAST - 1))
+		return -EINVAL;
+
+	entry_size = eeprom_map[eeprom_id].length;
+
+	if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) {
+		/* indirect data */
+		u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA +
+			     IWM_EEPROM_INDIRECT_OFFSET;
+
+		eeprom_map[eeprom_id].offset =
+			*(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1;
+	}
+
+	addr = eeprom_map[eeprom_id].offset;
+
+	udma_cmd.eop = 1;
+	udma_cmd.credit_group = 0x4;
+	udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD;
+	udma_cmd.lmac_offset = 0;
+
+	umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY;
+	umac_cmd.resp = 1;
+
+	while (entry_size > 0) {
+		chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN);
+
+		eeprom_cmd.hdr.type =
+			cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ);
+		eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset);
+		eeprom_cmd.hdr.len = cpu_to_le32(chunk_size);
+
+		ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd,
+					    &umac_cmd, &eeprom_cmd,
+				     sizeof(struct iwm_umac_cmd_eeprom_proxy));
+		if (ret < 0) {
+			IWM_ERR(iwm, "Couldn't read eeprom\n");
+			return ret;
+		}
+
+		ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY,
+				       IWM_SRC_UMAC, 2*HZ);
+		if (ret < 0) {
+			IWM_ERR(iwm, "Did not get any eeprom answer\n");
+			return ret;
+		}
+
+		data_offset += chunk_size;
+		addr_offset += chunk_size;
+		entry_size -= chunk_size;
+	}
+
+	return 0;
+}
+
+u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id)
+{
+	if (!iwm->eeprom)
+		return ERR_PTR(-ENODEV);
+
+	return iwm->eeprom + eeprom_map[eeprom_id].offset;
+}
+
+int iwm_eeprom_init(struct iwm_priv *iwm)
+{
+	int i, ret = 0;
+	char name[32];
+
+	iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL);
+	if (!iwm->eeprom)
+		return -ENOMEM;
+
+	for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
+#ifdef CONFIG_IWM_B0_HW_SUPPORT
+		if (iwm->conf.hw_b0 && (i >= IWM_EEPROM_INDIRECT_OFFSET))
+			break;
+#endif
+		ret = iwm_eeprom_read(iwm, i);
+		if (ret < 0) {
+			IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n",
+				i, eeprom_map[i].name);
+			break;
+		}
+	}
+
+	IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n");
+	for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
+		memset(name, 0, 32);
+		sprintf(name, "%s: ", eeprom_map[i].name);
+
+		IWM_HEXDUMP(iwm, DBG, BOOT, name,
+			    iwm->eeprom + eeprom_map[i].offset,
+			    eeprom_map[i].length);
+	}
+
+	return ret;
+}
+
+void iwm_eeprom_exit(struct iwm_priv *iwm)
+{
+	kfree(iwm->eeprom);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/eeprom.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_EEPROM_H__
+#define __IWM_EEPROM_H__
+
+enum {
+	IWM_EEPROM_SIG = 0,
+	IWM_EEPROM_FIRST = IWM_EEPROM_SIG,
+	IWM_EEPROM_VERSION,
+	IWM_EEPROM_OEM_HW_VERSION,
+	IWM_EEPROM_MAC_VERSION,
+	IWM_EEPROM_CARD_ID,
+	IWM_EEPROM_RADIO_CONF,
+	IWM_EEPROM_SKU_CAP,
+
+	IWM_EEPROM_INDIRECT_OFFSET,
+	IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET,
+
+	IWM_EEPROM_INDIRECT_DATA,
+	IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA,
+
+	IWM_EEPROM_LAST,
+};
+
+#define IWM_EEPROM_SIG_OFF             0x00
+#define IWM_EEPROM_VERSION_OFF        (0x54 << 1)
+#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1)
+#define IWM_EEPROM_MAC_VERSION_OFF    (0x30 << 1)
+#define IWM_EEPROM_CARD_ID_OFF        (0x5d << 1)
+#define IWM_EEPROM_RADIO_CONF_OFF     (0x58 << 1)
+#define IWM_EEPROM_SKU_CAP_OFF        (0x55 << 1)
+#define IWM_EEPROM_CALIB_CONFIG_OFF   (0x7c << 1)
+
+#define IWM_EEPROM_SIG_LEN              4
+#define IWM_EEPROM_VERSION_LEN          2
+#define IWM_EEPROM_OEM_HW_VERSION_LEN   2
+#define IWM_EEPROM_MAC_VERSION_LEN      1
+#define IWM_EEPROM_CARD_ID_LEN          2
+#define IWM_EEPROM_RADIO_CONF_LEN       2
+#define IWM_EEPROM_SKU_CAP_LEN          2
+#define IWM_EEPROM_INDIRECT_LEN		2
+
+#define IWM_MAX_EEPROM_DATA_LEN         240
+#define IWM_EEPROM_LEN                  0x800
+
+#define IWM_EEPROM_MIN_ALLOWED_VERSION          0x0610
+#define IWM_EEPROM_MAX_ALLOWED_VERSION          0x0700
+#define IWM_EEPROM_CURRENT_VERSION              0x0612
+
+#define IWM_EEPROM_SKU_CAP_BAND_24GHZ           (1 << 4)
+#define IWM_EEPROM_SKU_CAP_BAND_52GHZ           (1 << 5)
+#define IWM_EEPROM_SKU_CAP_11N_ENABLE           (1 << 6)
+
+enum {
+	IWM_EEPROM_CALIB_CAL_HDR,
+	IWM_EEPROM_CALIB_TX_POWER,
+	IWM_EEPROM_CALIB_XTAL,
+	IWM_EEPROM_CALIB_TEMPERATURE,
+	IWM_EEPROM_CALIB_RX_BB_FILTER,
+	IWM_EEPROM_CALIB_RX_IQ,
+	IWM_EEPROM_CALIB_MAX,
+};
+
+#define IWM_EEPROM_CALIB_RXIQ_OFF	(IWM_EEPROM_CALIB_CONFIG_OFF + \
+					 (IWM_EEPROM_CALIB_RX_IQ << 1))
+#define IWM_EEPROM_CALIB_RXIQ_LEN	sizeof(struct iwm_lmac_calib_rxiq)
+
+struct iwm_eeprom_entry {
+	char *name;
+	u32 offset;
+	u32 length;
+};
+
+int iwm_eeprom_init(struct iwm_priv *iwm);
+void iwm_eeprom_exit(struct iwm_priv *iwm);
+u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/fw.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/fw.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/fw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/fw.c	2012-03-22 20:13:00.000000000 -0400
@@ -0,0 +1,388 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+
+#include "iwm.h"
+#include "bus.h"
+#include "hal.h"
+#include "umac.h"
+#include "debug.h"
+#include "fw.h"
+#include "commands.h"
+
+static const char fw_barker[] = "*WESTOPFORNOONE*";
+
+/*
+ * @op_code: Op code we're looking for.
+ * @index: There can be several instances of the same opcode within
+ *         the firmware. Index specifies which one we're looking for.
+ */
+static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw,
+			    u16 op_code, u32 index)
+{
+	int offset = -EINVAL, fw_offset;
+	u32 op_index = 0;
+	const u8 *fw_ptr;
+	struct iwm_fw_hdr_rec *rec;
+
+	fw_offset = 0;
+	fw_ptr = fw->data;
+
+	/* We first need to look for the firmware barker */
+	if (memcmp(fw_ptr, fw_barker, IWM_HDR_BARKER_LEN)) {
+		IWM_ERR(iwm, "No barker string in this FW\n");
+		return -EINVAL;
+	}
+
+	if (fw->size < IWM_HDR_LEN) {
+		IWM_ERR(iwm, "FW is too small (%zu)\n", fw->size);
+		return -EINVAL;
+	}
+
+	fw_offset += IWM_HDR_BARKER_LEN;
+
+	while (fw_offset < fw->size) {
+		rec = (struct iwm_fw_hdr_rec *)(fw_ptr + fw_offset);
+
+		IWM_DBG_FW(iwm, DBG, "FW: op_code: 0x%x, len: %d @ 0x%x\n",
+			   rec->op_code, rec->len, fw_offset);
+
+		if (rec->op_code == IWM_HDR_REC_OP_INVALID) {
+			IWM_DBG_FW(iwm, DBG, "Reached INVALID op code\n");
+			break;
+		}
+
+		if (rec->op_code == op_code) {
+			if (op_index == index) {
+				fw_offset += sizeof(struct iwm_fw_hdr_rec);
+				offset = fw_offset;
+				goto out;
+			}
+			op_index++;
+		}
+
+		fw_offset += sizeof(struct iwm_fw_hdr_rec) + rec->len;
+	}
+
+ out:
+	return offset;
+}
+
+static int iwm_load_firmware_chunk(struct iwm_priv *iwm,
+				   const struct firmware *fw,
+				   struct iwm_fw_img_desc *img_desc)
+{
+	struct iwm_udma_nonwifi_cmd target_cmd;
+	u32 chunk_size;
+	const u8 *chunk_ptr;
+	int ret = 0;
+
+	IWM_DBG_FW(iwm, INFO, "Loading FW chunk: %d bytes @ 0x%x\n",
+		   img_desc->length, img_desc->address);
+
+	target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
+	target_cmd.handle_by_hw = 1;
+	target_cmd.op2 = 0;
+	target_cmd.resp = 0;
+	target_cmd.eop = 1;
+
+	chunk_size = img_desc->length;
+	chunk_ptr = fw->data + img_desc->offset;
+
+	while (chunk_size > 0) {
+		u32 tmp_chunk_size;
+
+		tmp_chunk_size = min_t(u32, chunk_size,
+				       IWM_MAX_NONWIFI_CMD_BUFF_SIZE);
+
+		target_cmd.addr = cpu_to_le32(img_desc->address +
+				    (chunk_ptr - fw->data - img_desc->offset));
+		target_cmd.op1_sz = cpu_to_le32(tmp_chunk_size);
+
+		IWM_DBG_FW(iwm, DBG, "\t%d bytes @ 0x%x\n",
+			   tmp_chunk_size, target_cmd.addr);
+
+		ret = iwm_hal_send_target_cmd(iwm, &target_cmd, chunk_ptr);
+		if (ret < 0) {
+			IWM_ERR(iwm, "Couldn't load FW chunk\n");
+			break;
+		}
+
+		chunk_size -= tmp_chunk_size;
+		chunk_ptr += tmp_chunk_size;
+	}
+
+	return ret;
+}
+/*
+ * To load a fw image to the target, we basically go through the
+ * fw, looking for OP_MEM_DESC records. Once we found one, we
+ * pass it to iwm_load_firmware_chunk().
+ * The OP_MEM_DESC records contain the actuall memory chunk to be
+ * sent, but also the destination address.
+ */
+static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
+{
+	const struct firmware *fw;
+	struct iwm_fw_img_desc *img_desc;
+	struct iwm_fw_img_ver *ver;
+	int ret = 0, fw_offset;
+	u32 opcode_idx = 0, build_date;
+	char *build_tag;
+
+	ret = reject_firmware(&fw, img_name, iwm_to_dev(iwm));
+	if (ret) {
+		IWM_ERR(iwm, "Request firmware failed");
+		return ret;
+	}
+
+	IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name);
+
+	while (1) {
+		fw_offset = iwm_fw_op_offset(iwm, fw,
+					     IWM_HDR_REC_OP_MEM_DESC,
+					     opcode_idx);
+		if (fw_offset < 0)
+			break;
+
+		img_desc = (struct iwm_fw_img_desc *)(fw->data + fw_offset);
+		ret = iwm_load_firmware_chunk(iwm, fw, img_desc);
+		if (ret < 0)
+			goto err_release_fw;
+		opcode_idx++;
+	};
+
+	/* Read firmware version */
+	fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0);
+	if (fw_offset < 0)
+		goto err_release_fw;
+
+	ver = (struct iwm_fw_img_ver *)(fw->data + fw_offset);
+
+	/* Read build tag */
+	fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_TAG, 0);
+	if (fw_offset < 0)
+		goto err_release_fw;
+
+	build_tag = (char *)(fw->data + fw_offset);
+
+	/* Read build date */
+	fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_DATE, 0);
+	if (fw_offset < 0)
+		goto err_release_fw;
+
+	build_date = *(u32 *)(fw->data + fw_offset);
+
+	IWM_INFO(iwm, "%s:\n", img_name);
+	IWM_INFO(iwm, "\tVersion:    %02X.%02X\n", ver->major, ver->minor);
+	IWM_INFO(iwm, "\tBuild tag:  %s\n", build_tag);
+	IWM_INFO(iwm, "\tBuild date: %x-%x-%x\n",
+		 IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date),
+		 IWM_BUILD_DAY(build_date));
+
+
+ err_release_fw:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static int iwm_load_umac(struct iwm_priv *iwm)
+{
+	struct iwm_udma_nonwifi_cmd target_cmd;
+	int ret;
+
+	ret = iwm_load_img(iwm, iwm->bus_ops->umac_name);
+	if (ret < 0)
+		return ret;
+
+	/* We've loaded the UMAC, we can tell the target to jump there */
+	target_cmd.opcode = UMAC_HDI_OUT_OPCODE_JUMP;
+	target_cmd.addr = cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR);
+	target_cmd.op1_sz = 0;
+	target_cmd.op2 = 0;
+	target_cmd.handle_by_hw = 0;
+	target_cmd.resp = 1 ;
+	target_cmd.eop = 1;
+
+	ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
+	if (ret < 0)
+		IWM_ERR(iwm, "Couldn't send JMP command\n");
+
+	return ret;
+}
+
+static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
+{
+	int ret;
+
+	ret = iwm_load_img(iwm, img_name);
+	if (ret < 0)
+		return ret;
+
+	return iwm_send_umac_reset(iwm,
+			cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0);
+}
+
+/*
+ * We currently have to load 3 FWs:
+ * 1) The UMAC (Upper MAC).
+ * 2) The calibration LMAC (Lower MAC).
+ *    We then send the calibration init command, so that the device can
+ *    run a first calibration round.
+ * 3) The operational LMAC, which replaces the calibration one when it's
+ *    done with the first calibration round.
+ *
+ * Once those 3 FWs have been loaded, we send the periodic calibration
+ * command, and then the device is available for regular 802.11 operations.
+ */
+int iwm_load_fw(struct iwm_priv *iwm)
+{
+	int ret;
+
+	/* We first start downloading the UMAC */
+	ret = iwm_load_umac(iwm);
+	if (ret < 0) {
+		IWM_ERR(iwm, "UMAC loading failed\n");
+		return ret;
+	}
+
+	/* Handle UMAC_ALIVE notification */
+	ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_ALIVE, IWM_SRC_UMAC,
+			       WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Handle UMAC_ALIVE failed: %d\n", ret);
+		return ret;
+	}
+
+	/* UMAC is alive, we can download the calibration LMAC */
+	ret = iwm_load_lmac(iwm, iwm->bus_ops->calib_lmac_name);
+	if (ret) {
+		IWM_ERR(iwm, "Calibration LMAC loading failed\n");
+		return ret;
+	}
+
+	/* Handle UMAC_INIT_COMPLETE notification */
+	ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
+			       IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Handle INIT_COMPLETE failed for calibration "
+			"LMAC: %d\n", ret);
+		return ret;
+	}
+
+	/* Read EEPROM data */
+	ret = iwm_eeprom_init(iwm);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't init eeprom array\n");
+		return ret;
+	}
+
+#ifdef CONFIG_IWM_B0_HW_SUPPORT
+	if (iwm->conf.hw_b0) {
+		clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map);
+		clear_bit(PHY_CALIBRATE_RX_IQ_CMD,
+			  &iwm->conf.periodic_calib_map);
+	}
+#endif
+	/* Read RX IQ calibration result from EEPROM */
+	if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map)) {
+		iwm_store_rxiq_calib_result(iwm);
+		set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
+	}
+
+	iwm_send_prio_table(iwm);
+	iwm_send_init_calib_cfg(iwm, iwm->conf.init_calib_map);
+
+	while (iwm->calib_done_map != iwm->conf.init_calib_map) {
+		ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
+				       IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
+		if (ret) {
+			IWM_ERR(iwm, "Wait for calibration result timeout\n");
+			goto out;
+		}
+		IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
+			   "0x%lx, requested calibrations: 0x%lx\n",
+			   iwm->calib_done_map, iwm->conf.init_calib_map);
+	}
+
+	/* Handle LMAC CALIBRATION_COMPLETE notification */
+	ret = iwm_notif_handle(iwm, CALIBRATION_COMPLETE_NOTIFICATION,
+			       IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Wait for CALIBRATION_COMPLETE timeout\n");
+		goto out;
+	}
+
+	IWM_INFO(iwm, "LMAC calibration done: 0x%lx\n", iwm->calib_done_map);
+
+	iwm_send_umac_reset(iwm, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET), 1);
+
+	ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
+			       WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
+		goto out;
+	}
+
+	/* Download the operational LMAC */
+	ret = iwm_load_lmac(iwm, iwm->bus_ops->lmac_name);
+	if (ret) {
+		IWM_ERR(iwm, "LMAC loading failed\n");
+		goto out;
+	}
+
+	ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
+			       IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret);
+		goto out;
+	}
+
+	iwm_send_prio_table(iwm);
+	iwm_send_calib_results(iwm);
+	iwm_send_periodic_calib_cfg(iwm, iwm->conf.periodic_calib_map);
+
+	return 0;
+
+ out:
+	iwm_eeprom_exit(iwm);
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/fw.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/fw.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/fw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/fw.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_FW_H__
+#define __IWM_FW_H__
+
+/**
+ * struct iwm_fw_hdr_rec - An iwm firmware image is a
+ * concatenation of various records. Each of them is
+ * defined by an ID (aka op code), a length, and the
+ * actual data.
+ * @op_code: The record ID, see IWM_HDR_REC_OP_*
+ *
+ * @len: The record payload length
+ *
+ * @buf: The record payload
+ */
+struct iwm_fw_hdr_rec {
+	u16 op_code;
+	u16 len;
+	u8 buf[0];
+};
+
+/* Header's definitions */
+#define IWM_HDR_LEN                          (512)
+#define IWM_HDR_BARKER_LEN                   (16)
+
+/* Header's opcodes */
+#define IWM_HDR_REC_OP_INVALID             (0x00)
+#define IWM_HDR_REC_OP_BUILD_DATE          (0x01)
+#define IWM_HDR_REC_OP_BUILD_TAG           (0x02)
+#define IWM_HDR_REC_OP_SW_VER              (0x03)
+#define IWM_HDR_REC_OP_HW_SKU              (0x04)
+#define IWM_HDR_REC_OP_BUILD_OPT           (0x05)
+#define IWM_HDR_REC_OP_MEM_DESC            (0x06)
+#define IWM_HDR_REC_USERDEFS               (0x07)
+
+/* Header's records length (in bytes) */
+#define IWM_HDR_REC_LEN_BUILD_DATE           (4)
+#define IWM_HDR_REC_LEN_BUILD_TAG            (64)
+#define IWM_HDR_REC_LEN_SW_VER               (4)
+#define IWM_HDR_REC_LEN_HW_SKU               (4)
+#define IWM_HDR_REC_LEN_BUILD_OPT            (4)
+#define IWM_HDR_REC_LEN_MEM_DESC             (12)
+#define IWM_HDR_REC_LEN_USERDEF              (64)
+
+#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff)
+#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff)
+#define IWM_BUILD_DAY(date) (date & 0xff)
+
+struct iwm_fw_img_desc {
+	u32 offset;
+	u32 address;
+	u32 length;
+};
+
+struct iwm_fw_img_ver {
+	u8 minor;
+	u8 major;
+	u16 reserved;
+};
+
+int iwm_load_fw(struct iwm_priv *iwm);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/hal.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/hal.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/hal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/hal.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,464 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+/*
+ * Hardware Abstraction Layer for iwm.
+ *
+ * This file mostly defines an abstraction API for
+ * sending various commands to the target.
+ *
+ * We have 2 types of commands: wifi and non-wifi ones.
+ *
+ * - wifi commands:
+ *   They are used for sending LMAC and UMAC commands,
+ *   and thus are the most commonly used ones.
+ *   There are 2 different wifi command types, the regular
+ *   one and the LMAC one. The former is used to send
+ *   UMAC commands (see UMAC_CMD_OPCODE_* from umac.h)
+ *   while the latter is used for sending commands to the
+ *   LMAC. If you look at LMAC commands you'll se that they
+ *   are actually regular iwlwifi target commands encapsulated
+ *   into a special UMAC command called UMAC passthrough.
+ *   This is due to the fact the the host talks exclusively
+ *   to the UMAC and so there needs to be a special UMAC
+ *   command for talking to the LMAC.
+ *   This is how a wifi command is layed out:
+ *    ------------------------
+ *   | iwm_udma_out_wifi_hdr  |
+ *    ------------------------
+ *   | SW meta_data (32 bits) |
+ *    ------------------------
+ *   | iwm_dev_cmd_hdr        |
+ *    ------------------------
+ *   | payload                |
+ *   | ....                   |
+ *
+ * - non-wifi, or general commands:
+ *   Those commands are handled by the device's bootrom,
+ *   and are typically sent when the UMAC and the LMAC
+ *   are not yet available.
+ *    *   This is how a non-wifi command is layed out:
+ *    ---------------------------
+ *   | iwm_udma_out_nonwifi_hdr  |
+ *    ---------------------------
+ *   | payload                   |
+ *   | ....                      |
+
+ *
+ * All the commands start with a UDMA header, which is
+ * basically a 32 bits field. The 4 LSB there define
+ * an opcode that allows the target to differentiate
+ * between wifi (opcode is 0xf) and non-wifi commands
+ * (opcode is [0..0xe]).
+ *
+ * When a command (wifi or non-wifi) is supposed to receive
+ * an answer, we queue the command buffer. When we do receive
+ * a command response from the UMAC, we go through the list
+ * of pending command, and pass both the command and the answer
+ * to the rx handler. Each command is sent with a unique
+ * sequence id, and the answer is sent with the same one. This
+ * is how we're supposed to match an answer with its command.
+ * See rx.c:iwm_rx_handle_[non]wifi() and iwm_get_pending_[non]wifi()
+ * for the implementation details.
+ */
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#include "iwm.h"
+#include "bus.h"
+#include "hal.h"
+#include "umac.h"
+#include "debug.h"
+
+static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
+				 struct iwm_nonwifi_cmd *cmd,
+				 struct iwm_udma_nonwifi_cmd *udma_cmd)
+{
+	INIT_LIST_HEAD(&cmd->pending);
+
+	spin_lock(&iwm->cmd_lock);
+
+	cmd->resp_received = 0;
+
+	cmd->seq_num = iwm->nonwifi_seq_num;
+	udma_cmd->seq_num = cpu_to_le16(cmd->seq_num);
+
+	cmd->seq_num = iwm->nonwifi_seq_num++;
+	iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX;
+
+	if (udma_cmd->resp)
+		list_add_tail(&cmd->pending, &iwm->nonwifi_pending_cmd);
+
+	spin_unlock(&iwm->cmd_lock);
+
+	cmd->buf.start = cmd->buf.payload;
+	cmd->buf.len = 0;
+
+	memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
+}
+
+u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm)
+{
+	u16 seq_num = iwm->wifi_seq_num;
+
+	iwm->wifi_seq_num++;
+	iwm->wifi_seq_num %= UMAC_WIFI_SEQ_NUM_MAX;
+
+	return seq_num;
+}
+
+static void iwm_wifi_cmd_init(struct iwm_priv *iwm,
+			      struct iwm_wifi_cmd *cmd,
+			      struct iwm_udma_wifi_cmd *udma_cmd,
+			      struct iwm_umac_cmd *umac_cmd,
+			      struct iwm_lmac_cmd *lmac_cmd,
+			      u16 payload_size)
+{
+	INIT_LIST_HEAD(&cmd->pending);
+
+	spin_lock(&iwm->cmd_lock);
+
+	cmd->seq_num = iwm_alloc_wifi_cmd_seq(iwm);
+	umac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
+
+	if (umac_cmd->resp)
+		list_add_tail(&cmd->pending, &iwm->wifi_pending_cmd);
+
+	spin_unlock(&iwm->cmd_lock);
+
+	cmd->buf.start = cmd->buf.payload;
+	cmd->buf.len = 0;
+
+	if (lmac_cmd) {
+		cmd->buf.start -= sizeof(struct iwm_lmac_hdr);
+
+		lmac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
+		lmac_cmd->count = cpu_to_le16(payload_size);
+
+		memcpy(&cmd->lmac_cmd, lmac_cmd, sizeof(*lmac_cmd));
+
+		umac_cmd->count = cpu_to_le16(sizeof(struct iwm_lmac_hdr));
+	} else
+		umac_cmd->count = 0;
+
+	umac_cmd->count = cpu_to_le16(payload_size +
+				      le16_to_cpu(umac_cmd->count));
+	udma_cmd->count = cpu_to_le16(sizeof(struct iwm_umac_fw_cmd_hdr) +
+				      le16_to_cpu(umac_cmd->count));
+
+	memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
+	memcpy(&cmd->umac_cmd, umac_cmd, sizeof(*umac_cmd));
+}
+
+void iwm_cmd_flush(struct iwm_priv *iwm)
+{
+	struct iwm_wifi_cmd *wcmd, *wnext;
+	struct iwm_nonwifi_cmd *nwcmd, *nwnext;
+
+	list_for_each_entry_safe(wcmd, wnext, &iwm->wifi_pending_cmd, pending) {
+		list_del(&wcmd->pending);
+		kfree(wcmd);
+	}
+
+	list_for_each_entry_safe(nwcmd, nwnext, &iwm->nonwifi_pending_cmd,
+				 pending) {
+		list_del(&nwcmd->pending);
+		kfree(nwcmd);
+	}
+}
+
+struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num)
+{
+	struct iwm_wifi_cmd *cmd, *next;
+
+	list_for_each_entry_safe(cmd, next, &iwm->wifi_pending_cmd, pending)
+		if (cmd->seq_num == seq_num) {
+			list_del(&cmd->pending);
+			return cmd;
+		}
+
+	return NULL;
+}
+
+struct iwm_nonwifi_cmd *
+iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, u8 seq_num, u8 cmd_opcode)
+{
+	struct iwm_nonwifi_cmd *cmd, *next;
+
+	list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending)
+		if ((cmd->seq_num == seq_num) &&
+		    (cmd->udma_cmd.opcode == cmd_opcode) &&
+		    (cmd->resp_received)) {
+			list_del(&cmd->pending);
+			return cmd;
+		}
+
+	return NULL;
+}
+
+static void iwm_build_udma_nonwifi_hdr(struct iwm_priv *iwm,
+				       struct iwm_udma_out_nonwifi_hdr *hdr,
+				       struct iwm_udma_nonwifi_cmd *cmd)
+{
+	memset(hdr, 0, sizeof(*hdr));
+
+	SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, cmd->opcode);
+	SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP, cmd->resp);
+	SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, 1);
+	SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW,
+		  cmd->handle_by_hw);
+	SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
+	SET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM,
+		  le16_to_cpu(cmd->seq_num));
+
+	hdr->addr = cmd->addr;
+	hdr->op1_sz = cmd->op1_sz;
+	hdr->op2 = cmd->op2;
+}
+
+static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm,
+				     struct iwm_nonwifi_cmd *cmd)
+{
+	struct iwm_udma_out_nonwifi_hdr *udma_hdr;
+	struct iwm_nonwifi_cmd_buff *buf;
+	struct iwm_udma_nonwifi_cmd *udma_cmd = &cmd->udma_cmd;
+
+	buf = &cmd->buf;
+
+	buf->start -= sizeof(struct iwm_umac_nonwifi_out_hdr);
+	buf->len += sizeof(struct iwm_umac_nonwifi_out_hdr);
+
+	udma_hdr = (struct iwm_udma_out_nonwifi_hdr *)(buf->start);
+
+	iwm_build_udma_nonwifi_hdr(iwm, udma_hdr, udma_cmd);
+
+	IWM_DBG_CMD(iwm, DBG,
+		    "Send UDMA nonwifi cmd: opcode = 0x%x, resp = 0x%x, "
+		    "hw = 0x%x, seqnum = %d, addr = 0x%x, op1_sz = 0x%x, "
+		    "op2 = 0x%x\n", udma_cmd->opcode, udma_cmd->resp,
+		    udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr,
+		    udma_cmd->op1_sz, udma_cmd->op2);
+
+	return iwm_bus_send_chunk(iwm, buf->start, buf->len);
+}
+
+void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop)
+{
+	struct iwm_udma_out_wifi_hdr *hdr = (struct iwm_udma_out_wifi_hdr *)buf;
+
+	SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, eop);
+}
+
+void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
+			     struct iwm_udma_out_wifi_hdr *hdr,
+			     struct iwm_udma_wifi_cmd *cmd)
+{
+	memset(hdr, 0, sizeof(*hdr));
+
+	SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, UMAC_HDI_OUT_OPCODE_WIFI);
+	SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, cmd->eop);
+	SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
+
+	SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_BYTE_COUNT,
+		  le16_to_cpu(cmd->count));
+	SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_CREDIT_GRP, cmd->credit_group);
+	SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_RATID, cmd->ra_tid);
+	SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_LMAC_OFFSET, cmd->lmac_offset);
+}
+
+void iwm_build_umac_hdr(struct iwm_priv *iwm,
+			struct iwm_umac_fw_cmd_hdr *hdr,
+			struct iwm_umac_cmd *cmd)
+{
+	memset(hdr, 0, sizeof(*hdr));
+
+	SET_VAL32(hdr->meta_data, UMAC_FW_CMD_BYTE_COUNT,
+		  le16_to_cpu(cmd->count));
+	SET_VAL32(hdr->meta_data, UMAC_FW_CMD_TX_STA_COLOR, cmd->color);
+	SET_VAL8(hdr->cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ, cmd->resp);
+
+	hdr->cmd.cmd = cmd->id;
+	hdr->cmd.seq_num = cmd->seq_num;
+}
+
+static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm,
+				  struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_wifi_out_hdr *umac_hdr;
+	struct iwm_wifi_cmd_buff *buf;
+	struct iwm_udma_wifi_cmd *udma_cmd = &cmd->udma_cmd;
+	struct iwm_umac_cmd *umac_cmd = &cmd->umac_cmd;
+	int ret;
+
+	buf = &cmd->buf;
+
+	buf->start -= sizeof(struct iwm_umac_wifi_out_hdr);
+	buf->len += sizeof(struct iwm_umac_wifi_out_hdr);
+
+	umac_hdr = (struct iwm_umac_wifi_out_hdr *)(buf->start);
+
+	iwm_build_udma_wifi_hdr(iwm, &umac_hdr->hw_hdr, udma_cmd);
+	iwm_build_umac_hdr(iwm, &umac_hdr->sw_hdr, umac_cmd);
+
+	IWM_DBG_CMD(iwm, DBG,
+		    "Send UDMA wifi cmd: opcode = 0x%x, UMAC opcode = 0x%x, "
+		    "eop = 0x%x, count = 0x%x, credit_group = 0x%x, "
+		    "ra_tid = 0x%x, lmac_offset = 0x%x, seqnum = %d\n",
+		    UMAC_HDI_OUT_OPCODE_WIFI, umac_cmd->id,
+		    udma_cmd->eop, udma_cmd->count, udma_cmd->credit_group,
+		    udma_cmd->ra_tid, udma_cmd->lmac_offset, cmd->seq_num);
+
+	if (umac_cmd->id == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH)
+		IWM_DBG_CMD(iwm, DBG, "\tLMAC opcode: 0x%x\n",
+			    cmd->lmac_cmd.id);
+
+	ret = iwm_tx_credit_alloc(iwm, udma_cmd->credit_group, buf->len);
+
+	/* We keep sending UMAC reset regardless of the command credits.
+	 * The UMAC is supposed to be reset anyway and the Tx credits are
+	 * reinitialized afterwards. If we are lucky, the reset could
+	 * still be done even though we have run out of credits for the
+	 * command pool at this moment.*/
+	if (ret && (umac_cmd->id != UMAC_CMD_OPCODE_RESET)) {
+		IWM_DBG_TX(iwm, DBG, "Failed to alloc tx credit for cmd %d\n",
+			   umac_cmd->id);
+		return ret;
+	}
+
+	return iwm_bus_send_chunk(iwm, buf->start, buf->len);
+}
+
+/* target_cmd a.k.a udma_nonwifi_cmd can be sent when UMAC is not available */
+int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
+			    struct iwm_udma_nonwifi_cmd *udma_cmd,
+			    const void *payload)
+{
+	struct iwm_nonwifi_cmd *cmd;
+	int ret;
+
+	cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL);
+	if (!cmd) {
+		IWM_ERR(iwm, "Couldn't alloc memory for hal cmd\n");
+		return -ENOMEM;
+	}
+
+	iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd);
+
+	if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE ||
+	    cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) {
+		cmd->buf.len = le32_to_cpu(cmd->udma_cmd.op1_sz);
+		memcpy(&cmd->buf.payload, payload, cmd->buf.len);
+	}
+
+	ret = iwm_send_udma_nonwifi_cmd(iwm, cmd);
+
+	if (!udma_cmd->resp)
+		kfree(cmd);
+
+	if (ret < 0)
+		return ret;
+
+	return cmd->seq_num;
+}
+
+static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr,
+			       struct iwm_lmac_cmd *cmd)
+{
+	memset(hdr, 0, sizeof(*hdr));
+
+	hdr->id = cmd->id;
+	hdr->flags = 0; /* Is this ever used? */
+	hdr->seq_num = cmd->seq_num;
+}
+
+/*
+ * iwm_hal_send_host_cmd(): sends commands to the UMAC or the LMAC.
+ * Sending command to the LMAC is equivalent to sending a
+ * regular UMAC command with the LMAC passtrough or the LMAC
+ * wrapper UMAC command IDs.
+ */
+int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
+			  struct iwm_udma_wifi_cmd *udma_cmd,
+			  struct iwm_umac_cmd *umac_cmd,
+			  struct iwm_lmac_cmd *lmac_cmd,
+			  const void *payload, u16 payload_size)
+{
+	struct iwm_wifi_cmd *cmd;
+	struct iwm_lmac_hdr *hdr;
+	int lmac_hdr_len = 0;
+	int ret;
+
+	cmd = kzalloc(sizeof(struct iwm_wifi_cmd), GFP_KERNEL);
+	if (!cmd) {
+		IWM_ERR(iwm, "Couldn't alloc memory for wifi hal cmd\n");
+		return -ENOMEM;
+	}
+
+	iwm_wifi_cmd_init(iwm, cmd, udma_cmd, umac_cmd, lmac_cmd, payload_size);
+
+	if (lmac_cmd) {
+		hdr = (struct iwm_lmac_hdr *)(cmd->buf.start);
+
+		iwm_build_lmac_hdr(iwm, hdr, &cmd->lmac_cmd);
+		lmac_hdr_len = sizeof(struct iwm_lmac_hdr);
+	}
+
+	memcpy(cmd->buf.payload, payload, payload_size);
+	cmd->buf.len = le16_to_cpu(umac_cmd->count);
+
+	ret = iwm_send_udma_wifi_cmd(iwm, cmd);
+
+	/* We free the cmd if we're not expecting any response */
+	if (!umac_cmd->resp)
+		kfree(cmd);
+	return ret;
+}
+
+/*
+ * iwm_hal_send_umac_cmd(): This is a special case for
+ * iwm_hal_send_host_cmd() to send direct UMAC cmd (without
+ * LMAC involved).
+ */
+int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
+			  struct iwm_udma_wifi_cmd *udma_cmd,
+			  struct iwm_umac_cmd *umac_cmd,
+			  const void *payload, u16 payload_size)
+{
+	return iwm_hal_send_host_cmd(iwm, udma_cmd, umac_cmd, NULL,
+				     payload, payload_size);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/hal.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/hal.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/hal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/hal.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,236 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef _IWM_HAL_H_
+#define _IWM_HAL_H_
+
+#include "umac.h"
+
+#define GET_VAL8(s, name)	((s >> name##_POS) & name##_SEED)
+#define GET_VAL16(s, name)	((le16_to_cpu(s) >> name##_POS) & name##_SEED)
+#define GET_VAL32(s, name)	((le32_to_cpu(s) >> name##_POS) & name##_SEED)
+
+#define SET_VAL8(s, name, val)						  \
+do {									  \
+	s = (s & ~(name##_SEED << name##_POS)) |			  \
+	    ((val & name##_SEED) << name##_POS);			  \
+} while (0)
+
+#define SET_VAL16(s, name, val)						  \
+do {									  \
+	s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
+			((val & name##_SEED) << name##_POS));		  \
+} while (0)
+
+#define SET_VAL32(s, name, val)						  \
+do {									  \
+	s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
+			((val & name##_SEED) << name##_POS));		  \
+} while (0)
+
+
+#define UDMA_UMAC_INIT	{	.eop = 1,				  \
+				.credit_group = 0x4,			  \
+				.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD,  \
+				.lmac_offset = 0 }
+#define UDMA_LMAC_INIT	{	.eop = 1,				  \
+				.credit_group = 0x4,			  \
+				.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD,  \
+				.lmac_offset = 4 }
+
+
+/* UDMA IN OP CODE -- cmd bits [3:0] */
+#define UDMA_IN_OPCODE_MASK			0xF
+
+#define UDMA_IN_OPCODE_GENERAL_RESP		0x0
+#define UDMA_IN_OPCODE_READ_RESP		0x1
+#define UDMA_IN_OPCODE_WRITE_RESP		0x2
+#define UDMA_IN_OPCODE_PERS_WRITE_RESP		0x5
+#define UDMA_IN_OPCODE_PERS_READ_RESP		0x6
+#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP		0x7
+#define UDMA_IN_OPCODE_EP_MNGMT_MSG		0x8
+#define UDMA_IN_OPCODE_CRDT_CHNG_MSG		0x9
+#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG	0xA
+#define UDMA_IN_OPCODE_SW_MSG			0xB
+#define UDMA_IN_OPCODE_WIFI			0xF
+#define UDMA_IN_OPCODE_WIFI_LMAC		0x1F
+#define UDMA_IN_OPCODE_WIFI_UMAC		0x2F
+
+/* HW API: udma_hdi_nonwifi API (OUT and IN) */
+
+/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */
+#define UDMA_HDI_OUT_NW_CMD_RESP_POS		9
+#define UDMA_HDI_OUT_NW_CMD_RESP_SEED		0x1
+
+/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */
+#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS	11
+#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED	0x1
+
+/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */
+#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS		12
+#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED	0xF
+
+/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */
+#define UDMA_IN_NW_HW_SEQ_NUM_POS		12
+#define UDMA_IN_NW_HW_SEQ_NUM_SEED		0xF
+
+/* UDMA IN Non-WIFI HW signature -- bits [16:31] */
+#define UDMA_IN_NW_HW_SIG_POS			16
+#define UDMA_IN_NW_HW_SIG_SEED			0xFFFF
+
+/* fixed signature */
+#define UDMA_IN_NW_HW_SIG			0xCBBC
+
+/* UDMA IN Non-WIFI HW block length -- bits [32:35] */
+#define UDMA_IN_NW_HW_LENGTH_SEED		0xF
+#define UDMA_IN_NW_HW_LENGTH_POS		32
+
+/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */
+
+#define IWM_SDIO_FW_MAX_CHUNK_SIZE	2032
+#define IWM_MAX_WIFI_HEADERS_SIZE	32
+#define IWM_MAX_NONWIFI_HEADERS_SIZE	16
+#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE	(IWM_SDIO_FW_MAX_CHUNK_SIZE - \
+					 IWM_MAX_NONWIFI_HEADERS_SIZE)
+#define IWM_MAX_WIFI_CMD_BUFF_SIZE	(IWM_SDIO_FW_MAX_CHUNK_SIZE - \
+					 IWM_MAX_WIFI_HEADERS_SIZE)
+
+#define IWM_HAL_CONCATENATE_BUF_SIZE	8192
+
+struct iwm_wifi_cmd_buff {
+	u16 len;
+	u8 *start;
+	u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE];
+	u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE];
+};
+
+struct iwm_nonwifi_cmd_buff {
+	u16 len;
+	u8 *start;
+	u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE];
+	u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE];
+};
+
+struct iwm_udma_nonwifi_cmd {
+	u8 opcode;
+	u8 eop;
+	u8 resp;
+	u8 handle_by_hw;
+	__le32 addr;
+	__le32 op1_sz;
+	__le32 op2;
+	__le16 seq_num;
+};
+
+struct iwm_udma_wifi_cmd {
+	__le16 count;
+	u8 eop;
+	u8 credit_group;
+	u8 ra_tid;
+	u8 lmac_offset;
+};
+
+struct iwm_umac_cmd {
+	u8 id;
+	__le16 count;
+	u8 resp;
+	__le16 seq_num;
+	u8 color;
+};
+
+struct iwm_lmac_cmd {
+	u8 id;
+	__le16 count;
+	u8 resp;
+	__le16 seq_num;
+};
+
+struct iwm_nonwifi_cmd {
+	u16 seq_num;
+	bool resp_received;
+	struct list_head pending;
+	struct iwm_udma_nonwifi_cmd udma_cmd;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_lmac_cmd lmac_cmd;
+	struct iwm_nonwifi_cmd_buff buf;
+	u32 flags;
+};
+
+struct iwm_wifi_cmd {
+	u16 seq_num;
+	struct list_head pending;
+	struct iwm_udma_wifi_cmd udma_cmd;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_lmac_cmd lmac_cmd;
+	struct iwm_wifi_cmd_buff buf;
+	u32 flags;
+};
+
+void iwm_cmd_flush(struct iwm_priv *iwm);
+
+struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm,
+					      u16 seq_num);
+struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
+						    u8 seq_num, u8 cmd_opcode);
+
+
+int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
+			    struct iwm_udma_nonwifi_cmd *ucmd,
+			    const void *payload);
+
+int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
+			  struct iwm_udma_wifi_cmd *udma_cmd,
+			  struct iwm_umac_cmd *umac_cmd,
+			  struct iwm_lmac_cmd *lmac_cmd,
+			  const void *payload, u16 payload_size);
+
+int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
+			  struct iwm_udma_wifi_cmd *udma_cmd,
+			  struct iwm_umac_cmd *umac_cmd,
+			  const void *payload, u16 payload_size);
+
+u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm);
+
+void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop);
+void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
+			     struct iwm_udma_out_wifi_hdr *hdr,
+			     struct iwm_udma_wifi_cmd *cmd);
+void iwm_build_umac_hdr(struct iwm_priv *iwm,
+			struct iwm_umac_fw_cmd_hdr *hdr,
+			struct iwm_umac_cmd *cmd);
+#endif /* _IWM_HAL_H_ */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/iwm.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/iwm.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/iwm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/iwm.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,350 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_H__
+#define __IWM_H__
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+
+#include "debug.h"
+#include "hal.h"
+#include "umac.h"
+#include "lmac.h"
+#include "eeprom.h"
+
+#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
+#define IWM_AUTHOR "<ilw@linux.intel.com>"
+
+#define CONFIG_IWM_B0_HW_SUPPORT	1
+
+#define IWM_SRC_LMAC	UMAC_HDI_IN_SOURCE_FHRX
+#define IWM_SRC_UDMA	UMAC_HDI_IN_SOURCE_UDMA
+#define IWM_SRC_UMAC	UMAC_HDI_IN_SOURCE_FW
+#define IWM_SRC_NUM	3
+
+#define IWM_POWER_INDEX_MIN	0
+#define IWM_POWER_INDEX_MAX	5
+#define IWM_POWER_INDEX_DEFAULT	3
+
+struct iwm_conf {
+	u32 sdio_ior_timeout;
+	unsigned long init_calib_map;
+	unsigned long periodic_calib_map;
+	bool reset_on_fatal_err;
+	bool auto_connect;
+	bool wimax_not_present;
+	bool enable_qos;
+	u32 mode;
+
+	u32 power_index;
+	u32 frag_threshold;
+	u32 rts_threshold;
+	bool cts_to_self;
+
+	u32 assoc_timeout;
+	u32 roam_timeout;
+	u32 wireless_mode;
+	u32 coexist_mode;
+
+	u8 ibss_band;
+	u8 ibss_channel;
+
+	u8 mac_addr[ETH_ALEN];
+#ifdef CONFIG_IWM_B0_HW_SUPPORT
+	bool hw_b0;
+#endif
+};
+
+enum {
+	COEX_MODE_SA = 1,
+	COEX_MODE_XOR,
+	COEX_MODE_CM,
+	COEX_MODE_MAX,
+};
+
+struct iwm_if_ops;
+struct iwm_wifi_cmd;
+
+struct pool_entry {
+	int id;		/* group id */
+	int sid;	/* super group id */
+	int min_pages;	/* min capacity in pages */
+	int max_pages;	/* max capacity in pages */
+	int alloc_pages;	/* allocated # of pages. incresed by driver */
+	int total_freed_pages;	/* total freed # of pages. incresed by UMAC */
+};
+
+struct spool_entry {
+	int id;
+	int max_pages;
+	int alloc_pages;
+};
+
+struct iwm_tx_credit {
+	spinlock_t lock;
+	int pool_nr;
+	unsigned long full_pools_map; /* bitmap for # of filled tx pools */
+	struct pool_entry pools[IWM_MACS_OUT_GROUPS];
+	struct spool_entry spools[IWM_MACS_OUT_SGROUPS];
+};
+
+struct iwm_notif {
+	struct list_head pending;
+	u32 cmd_id;
+	void *cmd;
+	u8 src;
+	void *buf;
+	unsigned long buf_size;
+};
+
+struct iwm_sta_info {
+	u8 addr[ETH_ALEN];
+	bool valid;
+	bool qos;
+	u8 color;
+};
+
+struct iwm_tx_info {
+	u8 sta;
+	u8 color;
+	u8 tid;
+};
+
+struct iwm_rx_info {
+	unsigned long rx_size;
+	unsigned long rx_buf_size;
+};
+
+#define IWM_NUM_KEYS 4
+
+struct iwm_umac_key_hdr {
+	u8 mac[ETH_ALEN];
+	u8 key_idx;
+	u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */
+} __attribute__ ((packed));
+
+struct iwm_key {
+	struct iwm_umac_key_hdr hdr;
+	u8 in_use;
+	u8 alg;
+	u32 flags;
+	u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE];
+	u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE];
+	u8 key_len;
+	u8 key[32];
+};
+
+#define IWM_RX_ID_HASH  0xff
+#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH)
+
+#define IWM_STA_TABLE_NUM	16
+#define IWM_TX_LIST_SIZE	64
+#define IWM_RX_LIST_SIZE        256
+
+#define IWM_SCAN_ID_MAX 0xff
+
+#define IWM_STATUS_READY		0
+#define IWM_STATUS_SCANNING		1
+#define IWM_STATUS_SCAN_ABORTING	2
+#define IWM_STATUS_ASSOCIATING		3
+#define IWM_STATUS_ASSOCIATED		4
+
+#define IWM_RADIO_RFKILL_OFF		0
+#define IWM_RADIO_RFKILL_HW		1
+#define IWM_RADIO_RFKILL_SW		2
+
+struct iwm_tx_queue {
+	int id;
+	struct sk_buff_head queue;
+	struct workqueue_struct *wq;
+	struct work_struct worker;
+	u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE];
+	int concat_count;
+	u8 *concat_ptr;
+};
+
+/* Queues 0 ~ 3 for AC data, 5 for iPAN */
+#define IWM_TX_QUEUES		5
+#define IWM_TX_DATA_QUEUES	4
+#define IWM_TX_CMD_QUEUE	4
+
+struct iwm_bss_info {
+	struct list_head node;
+	struct cfg80211_bss *cfg_bss;
+	struct iwm_umac_notif_bss_info *bss;
+};
+
+typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf,
+			   unsigned long buf_size, struct iwm_wifi_cmd *cmd);
+
+#define IWM_WATCHDOG_PERIOD	(6 * HZ)
+
+struct iwm_priv {
+	struct wireless_dev *wdev;
+	struct iwm_if_ops *bus_ops;
+
+	struct iwm_conf conf;
+
+	unsigned long status;
+	unsigned long radio;
+
+	struct list_head pending_notif;
+	wait_queue_head_t notif_queue;
+
+	wait_queue_head_t nonwifi_queue;
+
+	unsigned long calib_done_map;
+	struct {
+		u8 *buf;
+		u32 size;
+	} calib_res[CALIBRATION_CMD_NUM];
+
+	struct iwm_umac_profile *umac_profile;
+	bool umac_profile_active;
+
+	u8 bssid[ETH_ALEN];
+	u8 channel;
+	u16 rate;
+
+	struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM];
+	struct list_head bss_list;
+
+	void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX])
+	(struct iwm_priv *priv, u8 *buf, unsigned long buf_size);
+
+	const iwm_handler *umac_handlers;
+	const iwm_handler *lmac_handlers;
+	DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM);
+	DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM);
+	DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM);
+
+	struct list_head wifi_pending_cmd;
+	struct list_head nonwifi_pending_cmd;
+	u16 wifi_seq_num;
+	u8 nonwifi_seq_num;
+	spinlock_t cmd_lock;
+
+	u32 core_enabled;
+
+	u8 scan_id;
+	struct cfg80211_scan_request *scan_request;
+
+	struct sk_buff_head rx_list;
+	struct list_head rx_tickets;
+	struct list_head rx_packets[IWM_RX_ID_HASH];
+	struct workqueue_struct *rx_wq;
+	struct work_struct rx_worker;
+
+	struct iwm_tx_credit tx_credit;
+	struct iwm_tx_queue txq[IWM_TX_QUEUES];
+
+	struct iwm_key keys[IWM_NUM_KEYS];
+	struct iwm_key *default_key;
+
+	wait_queue_head_t mlme_queue;
+
+	struct iw_statistics wstats;
+	struct delayed_work stats_request;
+
+	struct iwm_debugfs dbg;
+
+	u8 *eeprom;
+	struct timer_list watchdog;
+	struct work_struct reset_worker;
+	struct mutex mutex;
+	struct rfkill *rfkill;
+
+	char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+static inline void *iwm_private(struct iwm_priv *iwm)
+{
+	BUG_ON(!iwm);
+	return &iwm->private;
+}
+
+#define hw_to_iwm(h) (h->iwm)
+#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy))
+#define iwm_to_wiphy(i) (i->wdev->wiphy)
+#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w))
+#define iwm_to_wdev(i) (i->wdev)
+#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w))
+#define iwm_to_ndev(i) (i->wdev->netdev)
+#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr))
+#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb))
+#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb)
+
+extern const struct iw_handler_def iwm_iw_handler_def;
+
+void *iwm_if_alloc(int sizeof_bus, struct device *dev,
+		   struct iwm_if_ops *if_ops);
+void iwm_if_free(struct iwm_priv *iwm);
+int iwm_if_add(struct iwm_priv *iwm);
+void iwm_if_remove(struct iwm_priv *iwm);
+int iwm_mode_to_nl80211_iftype(int mode);
+int iwm_priv_init(struct iwm_priv *iwm);
+void iwm_priv_deinit(struct iwm_priv *iwm);
+void iwm_reset(struct iwm_priv *iwm);
+void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
+			      struct iwm_umac_notif_alive *alive);
+int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);
+int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
+		   u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size);
+int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout);
+void iwm_init_default_profile(struct iwm_priv *iwm,
+			      struct iwm_umac_profile *profile);
+void iwm_link_on(struct iwm_priv *iwm);
+void iwm_link_off(struct iwm_priv *iwm);
+int iwm_up(struct iwm_priv *iwm);
+int iwm_down(struct iwm_priv *iwm);
+
+/* TX API */
+void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages);
+void iwm_tx_worker(struct work_struct *work);
+int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+
+/* RX API */
+void iwm_rx_setup_handlers(struct iwm_priv *iwm);
+int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size);
+int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
+		       struct iwm_wifi_cmd *cmd);
+void iwm_rx_free(struct iwm_priv *iwm);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,32 @@
+config IWM
+	tristate "Intel Wireless Multicomm 3200 WiFi driver"
+	depends on MMC && WLAN_80211 && EXPERIMENTAL
+	depends on CFG80211
+	select WIRELESS_EXT
+	select FW_LOADER
+	help
+	  The Intel Wireless Multicomm 3200 hardware is a combo
+	  card with GPS, Bluetooth, WiMax and 802.11 radios. It
+	  runs over SDIO and is typically found on Moorestown
+	  based platform. This driver takes care of the 802.11
+	  part, which is a fullmac one.
+
+	  If you choose to build it as a module, it'll be called
+	  iwmc3200wifi.ko.
+
+config IWM_DEBUG
+	bool "Enable full debugging output in iwmc3200wifi"
+	depends on IWM && DEBUG_FS
+	---help---
+	  This option will enable debug tracing and setting for iwm
+
+	  You can set the debug level and module through debugfs. By
+	  default all modules are set to the IWL_DL_ERR level.
+	  To see the list of debug modules and levels, see iwm/debug.h
+
+	  For example, if you want the full MLME debug output:
+	  echo 0xff > /debug/iwm/phyN/debug/mlme
+
+	  Or, if you want the full debug, for all modules:
+	  echo 0xff > /debug/iwm/phyN/debug/level
+	  echo 0xff > /debug/iwm/phyN/debug/modules
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/lmac.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/lmac.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/lmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/lmac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,457 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_LMAC_H__
+#define __IWM_LMAC_H__
+
+struct iwm_lmac_hdr {
+	u8 id;
+	u8 flags;
+	__le16 seq_num;
+} __attribute__ ((packed));
+
+/* LMAC commands */
+#define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK  0x1
+
+struct iwm_lmac_cal_cfg_elt {
+	__le32 enable; /* 1 means LMAC needs to do something */
+	__le32 start;  /* 1 to start calibration, 0 to stop */
+	__le32 send_res; /* 1 for sending back results */
+	__le32 apply_res; /* 1 for applying calibration results to HW */
+	__le32 reserved;
+} __attribute__ ((packed));
+
+struct iwm_lmac_cal_cfg_status {
+	struct iwm_lmac_cal_cfg_elt init;
+	struct iwm_lmac_cal_cfg_elt periodic;
+	__le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */
+} __attribute__ ((packed));
+
+struct iwm_lmac_cal_cfg_cmd {
+	struct iwm_lmac_cal_cfg_status ucode_cfg;
+	struct iwm_lmac_cal_cfg_status driver_cfg;
+	__le32 reserved;
+} __attribute__ ((packed));
+
+struct iwm_lmac_cal_cfg_resp {
+	__le32 status;
+} __attribute__ ((packed));
+
+#define IWM_CARD_STATE_SW_HW_ENABLED	0x00
+#define IWM_CARD_STATE_HW_DISABLED	0x01
+#define IWM_CARD_STATE_SW_DISABLED	0x02
+#define IWM_CARD_STATE_CTKILL_DISABLED	0x04
+#define IWM_CARD_STATE_IS_RXON		0x10
+
+struct iwm_lmac_card_state {
+	__le32 flags;
+} __attribute__ ((packed));
+
+/**
+ * COEX_PRIORITY_TABLE_CMD
+ *
+ * Priority entry for each state
+ * Will keep two tables, for STA and WIPAN
+ */
+enum {
+	/* UN-ASSOCIATION PART */
+	COEX_UNASSOC_IDLE = 0,
+	COEX_UNASSOC_MANUAL_SCAN,
+	COEX_UNASSOC_AUTO_SCAN,
+
+	/* CALIBRATION */
+	COEX_CALIBRATION,
+	COEX_PERIODIC_CALIBRATION,
+
+	/* CONNECTION */
+	COEX_CONNECTION_ESTAB,
+
+	/* ASSOCIATION PART */
+	COEX_ASSOCIATED_IDLE,
+	COEX_ASSOC_MANUAL_SCAN,
+	COEX_ASSOC_AUTO_SCAN,
+	COEX_ASSOC_ACTIVE_LEVEL,
+
+	/* RF ON/OFF */
+	COEX_RF_ON,
+	COEX_RF_OFF,
+	COEX_STAND_ALONE_DEBUG,
+
+	/* IPNN */
+	COEX_IPAN_ASSOC_LEVEL,
+
+	/* RESERVED */
+	COEX_RSRVD1,
+	COEX_RSRVD2,
+
+	COEX_EVENTS_NUM
+};
+
+#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK	0x1
+#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK	0x2
+#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK	0x4
+
+struct coex_event {
+	u8 req_prio;
+	u8 win_med_prio;
+	u8 reserved;
+	u8 flags;
+} __attribute__ ((packed));
+
+#define COEX_FLAGS_STA_TABLE_VALID_MSK		0x1
+#define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK	0x4
+#define COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK	0x8
+#define COEX_FLAGS_COEX_ENABLE_MSK		0x80
+
+struct iwm_coex_prio_table_cmd {
+	u8 flags;
+	u8 reserved[3];
+	struct coex_event sta_prio[COEX_EVENTS_NUM];
+} __attribute__ ((packed));
+
+/* Coexistence definitions
+ *
+ * Constants to fill in the Priorities' Tables
+ * RP - Requested Priority
+ * WP - Win Medium Priority: priority assigned when the contention has been won
+ * FLAGS - Combination of COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK and
+ * 	   COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK
+ */
+
+#define COEX_UNASSOC_IDLE_FLAGS		0
+#define COEX_UNASSOC_MANUAL_SCAN_FLAGS	(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+					 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
+#define COEX_UNASSOC_AUTO_SCAN_FLAGS	(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+					 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
+#define COEX_CALIBRATION_FLAGS		(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+					 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
+#define COEX_PERIODIC_CALIBRATION_FLAGS	0
+/* COEX_CONNECTION_ESTAB: we need DELAY_MEDIUM_FREE_NTFY to let WiMAX
+ * disconnect from network. */
+#define COEX_CONNECTION_ESTAB_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+				     COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
+				     COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
+#define COEX_ASSOCIATED_IDLE_FLAGS	0
+#define COEX_ASSOC_MANUAL_SCAN_FLAGS	(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+					 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
+#define COEX_ASSOC_AUTO_SCAN_FLAGS	(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+					 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
+#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS	0
+#define COEX_RF_ON_FLAGS		0
+#define COEX_RF_OFF_FLAGS		0
+#define COEX_STAND_ALONE_DEBUG_FLAGS	(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+					 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
+#define COEX_IPAN_ASSOC_LEVEL_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+				     COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
+				     COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
+#define COEX_RSRVD1_FLAGS		0
+#define COEX_RSRVD2_FLAGS		0
+/* XOR_RF_ON is the event wrapping all radio ownership. We need
+ * DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. */
+#define COEX_XOR_RF_ON_FLAGS	    (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
+				     COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
+				     COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
+
+/* LMAC OP CODES */
+#define REPLY_PAD			0x0
+#define REPLY_ALIVE			0x1
+#define REPLY_ERROR			0x2
+#define REPLY_ECHO			0x3
+#define REPLY_HALT			0x6
+
+/* RXON state commands */
+#define REPLY_RX_ON			0x10
+#define REPLY_RX_ON_ASSOC		0x11
+#define REPLY_RX_OFF			0x12
+#define REPLY_QOS_PARAM			0x13
+#define REPLY_RX_ON_TIMING		0x14
+#define REPLY_INTERNAL_QOS_PARAM	0x15
+#define REPLY_RX_INT_TIMEOUT_CNFG	0x16
+#define REPLY_NULL			0x17
+
+/* Multi-Station support */
+#define REPLY_ADD_STA			0x18
+#define REPLY_REMOVE_STA		0x19
+#define REPLY_RESET_ALL_STA		0x1a
+
+/* RX, TX */
+#define REPLY_ALM_RX			0x1b
+#define REPLY_TX			0x1c
+#define REPLY_TXFIFO_FLUSH		0x1e
+
+/* MISC commands */
+#define REPLY_MGMT_MCAST_KEY		0x1f
+#define REPLY_WEPKEY			0x20
+#define REPLY_INIT_IV			0x21
+#define REPLY_WRITE_MIB			0x22
+#define REPLY_READ_MIB			0x23
+#define REPLY_RADIO_FE			0x24
+#define REPLY_TXFIFO_CFG		0x25
+#define REPLY_WRITE_READ		0x26
+#define REPLY_INSTALL_SEC_KEY		0x27
+
+
+#define REPLY_RATE_SCALE		0x47
+#define REPLY_LEDS_CMD			0x48
+#define REPLY_TX_LINK_QUALITY_CMD	0x4e
+#define REPLY_ANA_MIB_OVERRIDE_CMD	0x4f
+#define REPLY_WRITE2REG_CMD		0x50
+
+/* winfi-wifi coexistence */
+#define COEX_PRIORITY_TABLE_CMD		0x5a
+#define COEX_MEDIUM_NOTIFICATION	0x5b
+#define COEX_EVENT_CMD			0x5c
+
+/* more Protocol and Protocol-test commands */
+#define REPLY_MAX_SLEEP_TIME_CMD	0x61
+#define CALIBRATION_CFG_CMD		0x65
+#define CALIBRATION_RES_NOTIFICATION	0x66
+#define CALIBRATION_COMPLETE_NOTIFICATION	0x67
+
+/* Measurements */
+#define REPLY_QUIET_CMD			0x71
+#define REPLY_CHANNEL_SWITCH		0x72
+#define CHANNEL_SWITCH_NOTIFICATION	0x73
+
+#define REPLY_SPECTRUM_MEASUREMENT_CMD	0x74
+#define SPECTRUM_MEASURE_NOTIFICATION	0x75
+#define REPLY_MEASUREMENT_ABORT_CMD	0x76
+
+/* Power Management */
+#define POWER_TABLE_CMD			0x77
+#define SAVE_RESTORE_ADRESS_CMD		0x78
+#define REPLY_WATERMARK_CMD		0x79
+#define PM_DEBUG_STATISTIC_NOTIFIC	0x7B
+#define PD_FLUSH_N_NOTIFICATION		0x7C
+
+/* Scan commands and notifications */
+#define REPLY_SCAN_REQUEST_CMD		0x80
+#define REPLY_SCAN_ABORT_CMD		0x81
+#define SCAN_START_NOTIFICATION		0x82
+#define SCAN_RESULTS_NOTIFICATION	0x83
+#define SCAN_COMPLETE_NOTIFICATION	0x84
+
+/* Continuous TX commands */
+#define REPLY_CONT_TX_CMD		0x85
+#define END_OF_CONT_TX_NOTIFICATION	0x86
+
+/* Timer/Eeprom commands */
+#define TIMER_CMD			0x87
+#define EEPROM_WRITE_CMD		0x88
+
+/* PAPD commands */
+#define FEEDBACK_REQUEST_NOTIFICATION	0x8b
+#define REPLY_CW_CMD			0x8c
+
+/* IBSS/AP commands Continue */
+#define BEACON_NOTIFICATION		0x90
+#define REPLY_TX_BEACON			0x91
+#define REPLY_REQUEST_ATIM		0x93
+#define WHO_IS_AWAKE_NOTIFICATION	0x94
+#define TX_PWR_DBM_LIMIT_CMD		0x95
+#define QUIET_NOTIFICATION		0x96
+#define TX_PWR_TABLE_CMD		0x97
+#define TX_ANT_CONFIGURATION_CMD	0x98
+#define MEASURE_ABORT_NOTIFICATION	0x99
+#define REPLY_CALIBRATION_TUNE		0x9a
+
+/* bt config command */
+#define REPLY_BT_CONFIG			0x9b
+#define REPLY_STATISTICS_CMD		0x9c
+#define STATISTICS_NOTIFICATION		0x9d
+
+/* RF-KILL commands and notifications */
+#define REPLY_CARD_STATE_CMD		0xa0
+#define CARD_STATE_NOTIFICATION		0xa1
+
+/* Missed beacons notification */
+#define MISSED_BEACONS_NOTIFICATION	0xa2
+#define MISSED_BEACONS_NOTIFICATION_TH_CMD	0xa3
+
+#define REPLY_CT_KILL_CONFIG_CMD	0xa4
+
+/* HD commands and notifications */
+#define REPLY_HD_PARAMS_CMD		0xa6
+#define HD_PARAMS_NOTIFICATION		0xa7
+#define SENSITIVITY_CMD			0xa8
+#define U_APSD_PARAMS_CMD		0xa9
+#define NOISY_PLATFORM_CMD		0xaa
+#define ILLEGAL_CMD			0xac
+#define REPLY_PHY_CALIBRATION_CMD	0xb0
+#define REPLAY_RX_GAIN_CALIB_CMD	0xb1
+
+/* WiPAN commands */
+#define REPLY_WIPAN_PARAMS_CMD		0xb2
+#define REPLY_WIPAN_RX_ON_CMD		0xb3
+#define REPLY_WIPAN_RX_ON_TIMING	0xb4
+#define REPLY_WIPAN_TX_PWR_TABLE_CMD	0xb5
+#define REPLY_WIPAN_RXON_ASSOC_CMD	0xb6
+#define REPLY_WIPAN_QOS_PARAM		0xb7
+#define WIPAN_REPLY_WEPKEY		0xb8
+
+/* BeamForming commands */
+#define BEAMFORMER_CFG_CMD		0xba
+#define BEAMFORMEE_NOTIFICATION		0xbb
+
+/* TGn new Commands */
+#define REPLY_RX_PHY_CMD		0xc0
+#define REPLY_RX_MPDU_CMD		0xc1
+#define REPLY_MULTICAST_HASH		0xc2
+#define REPLY_KDR_RX			0xc3
+#define REPLY_RX_DSP_EXT_INFO		0xc4
+#define REPLY_COMPRESSED_BA		0xc5
+
+/* PNC commands */
+#define PNC_CONFIG_CMD			0xc8
+#define PNC_UPDATE_TABLE_CMD		0xc9
+#define XVT_GENERAL_CTRL_CMD		0xca
+#define REPLY_LEGACY_RADIO_FE		0xdd
+
+/* WoWLAN commands */
+#define WOWLAN_PATTERNS			0xe0
+#define WOWLAN_WAKEUP_FILTER		0xe1
+#define WOWLAN_TSC_RSC_PARAM		0xe2
+#define WOWLAN_TKIP_PARAM		0xe3
+#define WOWLAN_KEK_KCK_MATERIAL		0xe4
+#define WOWLAN_GET_STATUSES		0xe5
+#define WOWLAN_TX_POWER_PER_DB		0xe6
+#define REPLY_WOWLAN_GET_STATUSES       WOWLAN_GET_STATUSES
+
+#define REPLY_DEBUG_CMD			0xf0
+#define REPLY_DSP_DEBUG_CMD		0xf1
+#define REPLY_DEBUG_MONITOR_CMD		0xf2
+#define REPLY_DEBUG_XVT_CMD		0xf3
+#define REPLY_DEBUG_DC_CALIB		0xf4
+#define REPLY_DYNAMIC_BP		0xf5
+
+/* General purpose Commands */
+#define REPLY_GP1_CMD			0xfa
+#define REPLY_GP2_CMD			0xfb
+#define REPLY_GP3_CMD			0xfc
+#define REPLY_GP4_CMD			0xfd
+#define REPLY_REPLAY_WRAPPER		0xfe
+#define REPLY_FRAME_DURATION_CALC_CMD	0xff
+
+#define LMAC_COMMAND_ID_MAX		0xff
+#define LMAC_COMMAND_ID_NUM		(LMAC_COMMAND_ID_MAX + 1)
+
+
+/* Calibration */
+
+enum {
+	PHY_CALIBRATE_DC_CMD			= 0,
+	PHY_CALIBRATE_LO_CMD			= 1,
+	PHY_CALIBRATE_RX_BB_CMD			= 2,
+	PHY_CALIBRATE_TX_IQ_CMD			= 3,
+	PHY_CALIBRATE_RX_IQ_CMD			= 4,
+	PHY_CALIBRATION_NOISE_CMD		= 5,
+	PHY_CALIBRATE_AGC_TABLE_CMD		= 6,
+	PHY_CALIBRATE_CRYSTAL_FRQ_CMD		= 7,
+	PHY_CALIBRATE_OPCODES_NUM,
+	SHILOH_PHY_CALIBRATE_DC_CMD		= 8,
+	SHILOH_PHY_CALIBRATE_LO_CMD		= 9,
+	SHILOH_PHY_CALIBRATE_RX_BB_CMD		= 10,
+	SHILOH_PHY_CALIBRATE_TX_IQ_CMD		= 11,
+	SHILOH_PHY_CALIBRATE_RX_IQ_CMD		= 12,
+	SHILOH_PHY_CALIBRATION_NOISE_CMD	= 13,
+	SHILOH_PHY_CALIBRATE_AGC_TABLE_CMD	= 14,
+	SHILOH_PHY_CALIBRATE_CRYSTAL_FRQ_CMD	= 15,
+	SHILOH_PHY_CALIBRATE_BASE_BAND_CMD	= 16,
+	SHILOH_PHY_CALIBRATE_TXIQ_PERIODIC_CMD	= 17,
+	CALIBRATION_CMD_NUM,
+};
+
+struct iwm_lmac_calib_hdr {
+	u8 opcode;
+	u8 first_grp;
+	u8 grp_num;
+	u8 all_data_valid;
+} __attribute__ ((packed));
+
+#define IWM_LMAC_CALIB_FREQ_GROUPS_NR	7
+#define IWM_CALIB_FREQ_GROUPS_NR	5
+#define IWM_CALIB_DC_MODES_NR		12
+
+struct iwm_calib_rxiq_entry {
+	u16 ptam_postdist_ars;
+	u16 ptam_postdist_arc;
+} __attribute__ ((packed));
+
+struct iwm_calib_rxiq_group {
+	struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR];
+} __attribute__ ((packed));
+
+struct iwm_lmac_calib_rxiq {
+	struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR];
+} __attribute__ ((packed));
+
+struct iwm_calib_rxiq {
+	struct iwm_lmac_calib_hdr hdr;
+	struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR];
+} __attribute__ ((packed));
+
+#define LMAC_STA_ID_SEED	0x0f
+#define LMAC_STA_ID_POS		0
+
+#define LMAC_STA_COLOR_SEED	0x7
+#define LMAC_STA_COLOR_POS	4
+
+struct iwm_lmac_power_report {
+	u8 pa_status;
+	u8 pa_integ_res_A[3];
+	u8 pa_integ_res_B[3];
+	u8 pa_integ_res_C[3];
+} __attribute__ ((packed));
+
+struct iwm_lmac_tx_resp {
+	u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */
+	u8 bt_kill_cnt;
+	__le16 retry_cnt;
+	__le32 initial_tx_rate;
+	__le16 wireless_media_time;
+	struct iwm_lmac_power_report power_report;
+	__le32 tfd_info;
+	__le16 seq_ctl;
+	__le16 byte_cnt;
+	u8 tlc_rate_info;
+	u8 ra_tid;
+	__le16 frame_ctl;
+	__le32 status;
+} __attribute__ ((packed));
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,732 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/ieee80211.h>
+#include <linux/wireless.h>
+
+#include "iwm.h"
+#include "debug.h"
+#include "bus.h"
+#include "umac.h"
+#include "commands.h"
+#include "hal.h"
+#include "fw.h"
+#include "rx.h"
+
+static struct iwm_conf def_iwm_conf = {
+
+	.sdio_ior_timeout	= 5000,
+	.init_calib_map		= BIT(PHY_CALIBRATE_DC_CMD)	|
+				  BIT(PHY_CALIBRATE_LO_CMD)	|
+				  BIT(PHY_CALIBRATE_TX_IQ_CMD)	|
+				  BIT(PHY_CALIBRATE_RX_IQ_CMD),
+	.periodic_calib_map	= BIT(PHY_CALIBRATE_DC_CMD)	|
+				  BIT(PHY_CALIBRATE_LO_CMD)	|
+				  BIT(PHY_CALIBRATE_TX_IQ_CMD)	|
+				  BIT(PHY_CALIBRATE_RX_IQ_CMD)	|
+				  BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
+	.reset_on_fatal_err	= 1,
+	.auto_connect		= 1,
+	.wimax_not_present	= 0,
+	.enable_qos		= 1,
+	.mode			= UMAC_MODE_BSS,
+
+	/* UMAC configuration */
+	.power_index		= 0,
+	.frag_threshold		= IEEE80211_MAX_FRAG_THRESHOLD,
+	.rts_threshold		= IEEE80211_MAX_RTS_THRESHOLD,
+	.cts_to_self		= 0,
+
+	.assoc_timeout		= 2,
+	.roam_timeout		= 10,
+	.wireless_mode		= WIRELESS_MODE_11A | WIRELESS_MODE_11G,
+	.coexist_mode		= COEX_MODE_CM,
+
+	/* IBSS */
+	.ibss_band		= UMAC_BAND_2GHZ,
+	.ibss_channel		= 1,
+
+	.mac_addr		= {0x00, 0x02, 0xb3, 0x01, 0x02, 0x03},
+};
+
+static int modparam_reset;
+module_param_named(reset, modparam_reset, bool, 0644);
+MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])");
+
+int iwm_mode_to_nl80211_iftype(int mode)
+{
+	switch (mode) {
+	case UMAC_MODE_BSS:
+		return NL80211_IFTYPE_STATION;
+	case UMAC_MODE_IBSS:
+		return NL80211_IFTYPE_ADHOC;
+	default:
+		return NL80211_IFTYPE_UNSPECIFIED;
+	}
+
+	return 0;
+}
+
+static void iwm_statistics_request(struct work_struct *work)
+{
+	struct iwm_priv *iwm =
+		container_of(work, struct iwm_priv, stats_request.work);
+
+	iwm_send_umac_stats_req(iwm, 0);
+}
+
+int __iwm_up(struct iwm_priv *iwm);
+int __iwm_down(struct iwm_priv *iwm);
+
+static void iwm_reset_worker(struct work_struct *work)
+{
+	struct iwm_priv *iwm;
+	struct iwm_umac_profile *profile = NULL;
+	int uninitialized_var(ret), retry = 0;
+
+	iwm = container_of(work, struct iwm_priv, reset_worker);
+
+	/*
+	 * XXX: The iwm->mutex is introduced purely for this reset work,
+	 * because the other users for iwm_up and iwm_down are only netdev
+	 * ndo_open and ndo_stop which are already protected by rtnl.
+	 * Please remove iwm->mutex together if iwm_reset_worker() is not
+	 * required in the future.
+	 */
+	if (!mutex_trylock(&iwm->mutex)) {
+		IWM_WARN(iwm, "We are in the middle of interface bringing "
+			 "UP/DOWN. Skip driver resetting.\n");
+		return;
+	}
+
+	if (iwm->umac_profile_active) {
+		profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL);
+		if (profile)
+			memcpy(profile, iwm->umac_profile, sizeof(*profile));
+		else
+			IWM_ERR(iwm, "Couldn't alloc memory for profile\n");
+	}
+
+	__iwm_down(iwm);
+
+	while (retry++ < 3) {
+		ret = __iwm_up(iwm);
+		if (!ret)
+			break;
+
+		schedule_timeout_uninterruptible(10 * HZ);
+	}
+
+	if (ret) {
+		IWM_WARN(iwm, "iwm_up() failed: %d\n", ret);
+
+		kfree(profile);
+		goto out;
+	}
+
+	if (profile) {
+		IWM_DBG_MLME(iwm, DBG, "Resend UMAC profile\n");
+		memcpy(iwm->umac_profile, profile, sizeof(*profile));
+		iwm_send_mlme_profile(iwm);
+		kfree(profile);
+	}
+
+ out:
+	mutex_unlock(&iwm->mutex);
+}
+
+static void iwm_watchdog(unsigned long data)
+{
+	struct iwm_priv *iwm = (struct iwm_priv *)data;
+
+	IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n");
+
+	if (modparam_reset)
+		schedule_work(&iwm->reset_worker);
+}
+
+int iwm_priv_init(struct iwm_priv *iwm)
+{
+	int i;
+	char name[32];
+
+	iwm->status = 0;
+	INIT_LIST_HEAD(&iwm->pending_notif);
+	init_waitqueue_head(&iwm->notif_queue);
+	init_waitqueue_head(&iwm->nonwifi_queue);
+	init_waitqueue_head(&iwm->mlme_queue);
+	memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf));
+	spin_lock_init(&iwm->tx_credit.lock);
+	INIT_LIST_HEAD(&iwm->wifi_pending_cmd);
+	INIT_LIST_HEAD(&iwm->nonwifi_pending_cmd);
+	iwm->wifi_seq_num = UMAC_WIFI_SEQ_NUM_BASE;
+	iwm->nonwifi_seq_num = UMAC_NONWIFI_SEQ_NUM_BASE;
+	spin_lock_init(&iwm->cmd_lock);
+	iwm->scan_id = 1;
+	INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request);
+	INIT_WORK(&iwm->reset_worker, iwm_reset_worker);
+	INIT_LIST_HEAD(&iwm->bss_list);
+
+	skb_queue_head_init(&iwm->rx_list);
+	INIT_LIST_HEAD(&iwm->rx_tickets);
+	for (i = 0; i < IWM_RX_ID_HASH; i++)
+		INIT_LIST_HEAD(&iwm->rx_packets[i]);
+
+	INIT_WORK(&iwm->rx_worker, iwm_rx_worker);
+
+	iwm->rx_wq = create_singlethread_workqueue(KBUILD_MODNAME "_rx");
+	if (!iwm->rx_wq)
+		return -EAGAIN;
+
+	for (i = 0; i < IWM_TX_QUEUES; i++) {
+		INIT_WORK(&iwm->txq[i].worker, iwm_tx_worker);
+		snprintf(name, 32, KBUILD_MODNAME "_tx_%d", i);
+		iwm->txq[i].id = i;
+		iwm->txq[i].wq = create_singlethread_workqueue(name);
+		if (!iwm->txq[i].wq)
+			return -EAGAIN;
+
+		skb_queue_head_init(&iwm->txq[i].queue);
+	}
+
+	for (i = 0; i < IWM_NUM_KEYS; i++)
+		memset(&iwm->keys[i], 0, sizeof(struct iwm_key));
+
+	iwm->default_key = NULL;
+
+	init_timer(&iwm->watchdog);
+	iwm->watchdog.function = iwm_watchdog;
+	iwm->watchdog.data = (unsigned long)iwm;
+	mutex_init(&iwm->mutex);
+
+	return 0;
+}
+
+void iwm_priv_deinit(struct iwm_priv *iwm)
+{
+	int i;
+
+	for (i = 0; i < IWM_TX_QUEUES; i++)
+		destroy_workqueue(iwm->txq[i].wq);
+
+	destroy_workqueue(iwm->rx_wq);
+}
+
+/*
+ * We reset all the structures, and we reset the UMAC.
+ * After calling this routine, you're expected to reload
+ * the firmware.
+ */
+void iwm_reset(struct iwm_priv *iwm)
+{
+	struct iwm_notif *notif, *next;
+
+	if (test_bit(IWM_STATUS_READY, &iwm->status))
+		iwm_target_reset(iwm);
+
+	iwm->status = 0;
+	iwm->scan_id = 1;
+
+	list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
+		list_del(&notif->pending);
+		kfree(notif->buf);
+		kfree(notif);
+	}
+
+	iwm_cmd_flush(iwm);
+
+	flush_workqueue(iwm->rx_wq);
+
+	iwm_link_off(iwm);
+}
+
+/*
+ * Notification code:
+ *
+ * We're faced with the following issue: Any host command can
+ * have an answer or not, and if there's an answer to expect,
+ * it can be treated synchronously or asynchronously.
+ * To work around the synchronous answer case, we implemented
+ * our notification mechanism.
+ * When a code path needs to wait for a command response
+ * synchronously, it calls notif_handle(), which waits for the
+ * right notification to show up, and then process it. Before
+ * starting to wait, it registered as a waiter for this specific
+ * answer (by toggling a bit in on of the handler_map), so that
+ * the rx code knows that it needs to send a notification to the
+ * waiting processes. It does so by calling iwm_notif_send(),
+ * which adds the notification to the pending notifications list,
+ * and then wakes the waiting processes up.
+ */
+int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
+		   u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size)
+{
+	struct iwm_notif *notif;
+
+	notif = kzalloc(sizeof(struct iwm_notif), GFP_KERNEL);
+	if (!notif) {
+		IWM_ERR(iwm, "Couldn't alloc memory for notification\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&notif->pending);
+	notif->cmd = cmd;
+	notif->cmd_id = cmd_id;
+	notif->src = source;
+	notif->buf = kzalloc(buf_size, GFP_KERNEL);
+	if (!notif->buf) {
+		IWM_ERR(iwm, "Couldn't alloc notification buffer\n");
+		kfree(notif);
+		return -ENOMEM;
+	}
+	notif->buf_size = buf_size;
+	memcpy(notif->buf, buf, buf_size);
+	list_add_tail(&notif->pending, &iwm->pending_notif);
+
+	wake_up_interruptible(&iwm->notif_queue);
+
+	return 0;
+}
+
+static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd,
+					u8 source)
+{
+	struct iwm_notif *notif, *next;
+
+	list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
+		if ((notif->cmd_id == cmd) && (notif->src == source)) {
+			list_del(&notif->pending);
+			return notif;
+		}
+	}
+
+	return NULL;
+}
+
+static struct iwm_notif *iwm_notif_wait(struct iwm_priv *iwm, u32 cmd,
+					u8 source, long timeout)
+{
+	int ret;
+	struct iwm_notif *notif;
+	unsigned long *map = NULL;
+
+	switch (source) {
+	case IWM_SRC_LMAC:
+		map = &iwm->lmac_handler_map[0];
+		break;
+	case IWM_SRC_UMAC:
+		map = &iwm->umac_handler_map[0];
+		break;
+	case IWM_SRC_UDMA:
+		map = &iwm->udma_handler_map[0];
+		break;
+	}
+
+	set_bit(cmd, map);
+
+	ret = wait_event_interruptible_timeout(iwm->notif_queue,
+			 ((notif = iwm_notif_find(iwm, cmd, source)) != NULL),
+					       timeout);
+	clear_bit(cmd, map);
+
+	if (!ret)
+		return NULL;
+
+	return notif;
+}
+
+int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout)
+{
+	int ret;
+	struct iwm_notif *notif;
+
+	notif = iwm_notif_wait(iwm, cmd, source, timeout);
+	if (!notif)
+		return -ETIME;
+
+	ret = iwm_rx_handle_resp(iwm, notif->buf, notif->buf_size, notif->cmd);
+	kfree(notif->buf);
+	kfree(notif);
+
+	return ret;
+}
+
+static int iwm_config_boot_params(struct iwm_priv *iwm)
+{
+	struct iwm_udma_nonwifi_cmd target_cmd;
+	int ret;
+
+	/* check Wimax is off and config debug monitor */
+	if (iwm->conf.wimax_not_present) {
+		u32 data1 = 0x1f;
+		u32 addr1 = 0x606BE258;
+
+		u32 data2_set = 0x0;
+		u32 data2_clr = 0x1;
+		u32 addr2 = 0x606BE100;
+
+		u32 data3 = 0x1;
+		u32 addr3 = 0x606BEC00;
+
+		target_cmd.resp = 0;
+		target_cmd.handle_by_hw = 0;
+		target_cmd.eop = 1;
+
+		target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
+		target_cmd.addr = cpu_to_le32(addr1);
+		target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
+		target_cmd.op2 = 0;
+
+		ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
+		if (ret < 0) {
+			IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
+			return ret;
+		}
+
+		target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE;
+		target_cmd.addr = cpu_to_le32(addr2);
+		target_cmd.op1_sz = cpu_to_le32(data2_set);
+		target_cmd.op2 = cpu_to_le32(data2_clr);
+
+		ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
+		if (ret < 0) {
+			IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
+			return ret;
+		}
+
+		target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
+		target_cmd.addr = cpu_to_le32(addr3);
+		target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
+		target_cmd.op2 = 0;
+
+		ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data3);
+		if (ret < 0) {
+			IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+void iwm_init_default_profile(struct iwm_priv *iwm,
+			      struct iwm_umac_profile *profile)
+{
+	memset(profile, 0, sizeof(struct iwm_umac_profile));
+
+	profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
+	profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
+	profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_NONE;
+	profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_NONE;
+
+	if (iwm->conf.enable_qos)
+		profile->flags |= cpu_to_le16(UMAC_PROFILE_QOS_ALLOWED);
+
+	profile->wireless_mode = iwm->conf.wireless_mode;
+	profile->mode = cpu_to_le32(iwm->conf.mode);
+
+	profile->ibss.atim = 0;
+	profile->ibss.beacon_interval = 100;
+	profile->ibss.join_only = 0;
+	profile->ibss.band = iwm->conf.ibss_band;
+	profile->ibss.channel = iwm->conf.ibss_channel;
+}
+
+void iwm_link_on(struct iwm_priv *iwm)
+{
+	netif_carrier_on(iwm_to_ndev(iwm));
+	netif_tx_wake_all_queues(iwm_to_ndev(iwm));
+
+	iwm_send_umac_stats_req(iwm, 0);
+}
+
+void iwm_link_off(struct iwm_priv *iwm)
+{
+	struct iw_statistics *wstats = &iwm->wstats;
+	int i;
+
+	netif_tx_stop_all_queues(iwm_to_ndev(iwm));
+	netif_carrier_off(iwm_to_ndev(iwm));
+
+	for (i = 0; i < IWM_TX_QUEUES; i++) {
+		skb_queue_purge(&iwm->txq[i].queue);
+
+		iwm->txq[i].concat_count = 0;
+		iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf;
+
+		flush_workqueue(iwm->txq[i].wq);
+	}
+
+	iwm_rx_free(iwm);
+
+	cancel_delayed_work_sync(&iwm->stats_request);
+	memset(wstats, 0, sizeof(struct iw_statistics));
+	wstats->qual.updated = IW_QUAL_ALL_INVALID;
+
+	del_timer_sync(&iwm->watchdog);
+}
+
+static void iwm_bss_list_clean(struct iwm_priv *iwm)
+{
+	struct iwm_bss_info *bss, *next;
+
+	list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
+		list_del(&bss->node);
+		kfree(bss->bss);
+		kfree(bss);
+	}
+}
+
+static int iwm_channels_init(struct iwm_priv *iwm)
+{
+	int ret;
+
+#ifdef CONFIG_IWM_B0_HW_SUPPORT
+	if (iwm->conf.hw_b0) {
+		IWM_INFO(iwm, "Workaround EEPROM channels for B0 hardware\n");
+		return 0;
+	}
+#endif
+
+	ret = iwm_send_umac_channel_list(iwm);
+	if (ret) {
+		IWM_ERR(iwm, "Send channel list failed\n");
+		return ret;
+	}
+
+	ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST,
+			       IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Didn't get a channel list notification\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int __iwm_up(struct iwm_priv *iwm)
+{
+	int ret;
+	struct iwm_notif *notif_reboot, *notif_ack = NULL;
+
+	ret = iwm_bus_enable(iwm);
+	if (ret) {
+		IWM_ERR(iwm, "Couldn't enable function\n");
+		return ret;
+	}
+
+	iwm_rx_setup_handlers(iwm);
+
+	/* Wait for initial BARKER_REBOOT from hardware */
+	notif_reboot = iwm_notif_wait(iwm, IWM_BARKER_REBOOT_NOTIFICATION,
+				      IWM_SRC_UDMA, 2 * HZ);
+	if (!notif_reboot) {
+		IWM_ERR(iwm, "Wait for REBOOT_BARKER timeout\n");
+		goto err_disable;
+	}
+
+	/* We send the barker back */
+	ret = iwm_bus_send_chunk(iwm, notif_reboot->buf, 16);
+	if (ret) {
+		IWM_ERR(iwm, "REBOOT barker response failed\n");
+		kfree(notif_reboot);
+		goto err_disable;
+	}
+
+	kfree(notif_reboot->buf);
+	kfree(notif_reboot);
+
+	/* Wait for ACK_BARKER from hardware */
+	notif_ack = iwm_notif_wait(iwm, IWM_ACK_BARKER_NOTIFICATION,
+				   IWM_SRC_UDMA, 2 * HZ);
+	if (!notif_ack) {
+		IWM_ERR(iwm, "Wait for ACK_BARKER timeout\n");
+		goto err_disable;
+	}
+
+	kfree(notif_ack->buf);
+	kfree(notif_ack);
+
+	/* We start to config static boot parameters */
+	ret = iwm_config_boot_params(iwm);
+	if (ret) {
+		IWM_ERR(iwm, "Config boot parameters failed\n");
+		goto err_disable;
+	}
+
+	ret = iwm_read_mac(iwm, iwm_to_ndev(iwm)->dev_addr);
+	if (ret) {
+		IWM_ERR(iwm, "MAC reading failed\n");
+		goto err_disable;
+	}
+
+	/* We can load the FWs */
+	ret = iwm_load_fw(iwm);
+	if (ret) {
+		IWM_ERR(iwm, "FW loading failed\n");
+		goto err_disable;
+	}
+
+	/* We configure the UMAC and enable the wifi module */
+	ret = iwm_send_umac_config(iwm,
+			cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) |
+			cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_LINK_EN) |
+			cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_MLME_EN));
+	if (ret) {
+		IWM_ERR(iwm, "UMAC config failed\n");
+		goto err_fw;
+	}
+
+	ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
+			       IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
+	if (ret) {
+		IWM_ERR(iwm, "Didn't get a wifi core status notification\n");
+		goto err_fw;
+	}
+
+	if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
+				  UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
+		IWM_DBG_BOOT(iwm, DBG, "Not all cores enabled:0x%x\n",
+			     iwm->core_enabled);
+		ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
+			       IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
+		if (ret) {
+			IWM_ERR(iwm, "Didn't get a core status notification\n");
+			goto err_fw;
+		}
+
+		if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
+					  UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
+			IWM_ERR(iwm, "Not all cores enabled: 0x%x\n",
+				iwm->core_enabled);
+			goto err_fw;
+		} else {
+			IWM_INFO(iwm, "All cores enabled\n");
+		}
+	}
+
+	iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile),
+				    GFP_KERNEL);
+	if (!iwm->umac_profile) {
+		IWM_ERR(iwm, "Couldn't alloc memory for profile\n");
+		goto err_fw;
+	}
+
+	iwm_init_default_profile(iwm, iwm->umac_profile);
+
+	ret = iwm_channels_init(iwm);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't init channels\n");
+		goto err_profile;
+	}
+
+	/* Set the READY bit to indicate interface is brought up successfully */
+	set_bit(IWM_STATUS_READY, &iwm->status);
+
+	return 0;
+
+ err_profile:
+	kfree(iwm->umac_profile);
+	iwm->umac_profile = NULL;
+
+ err_fw:
+	iwm_eeprom_exit(iwm);
+
+ err_disable:
+	ret = iwm_bus_disable(iwm);
+	if (ret < 0)
+		IWM_ERR(iwm, "Couldn't disable function\n");
+
+	return -EIO;
+}
+
+int iwm_up(struct iwm_priv *iwm)
+{
+	int ret;
+
+	mutex_lock(&iwm->mutex);
+	ret = __iwm_up(iwm);
+	mutex_unlock(&iwm->mutex);
+
+	return ret;
+}
+
+int __iwm_down(struct iwm_priv *iwm)
+{
+	int ret;
+
+	/* The interface is already down */
+	if (!test_bit(IWM_STATUS_READY, &iwm->status))
+		return 0;
+
+	if (iwm->scan_request) {
+		cfg80211_scan_done(iwm->scan_request, true);
+		iwm->scan_request = NULL;
+	}
+
+	clear_bit(IWM_STATUS_READY, &iwm->status);
+
+	iwm_eeprom_exit(iwm);
+	kfree(iwm->umac_profile);
+	iwm->umac_profile = NULL;
+	iwm_bss_list_clean(iwm);
+
+	iwm->default_key = NULL;
+	iwm->core_enabled = 0;
+
+	ret = iwm_bus_disable(iwm);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't disable function\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int iwm_down(struct iwm_priv *iwm)
+{
+	int ret;
+
+	mutex_lock(&iwm->mutex);
+	ret = __iwm_down(iwm);
+	mutex_unlock(&iwm->mutex);
+
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,5 @@
+obj-$(CONFIG_IWM) := iwmc3200wifi.o
+iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
+iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o
+
+iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/netdev.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/netdev.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/netdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/netdev.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,173 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/*
+ * This is the netdev related hooks for iwm.
+ *
+ * Some interesting code paths:
+ *
+ * iwm_open() (Called at netdev interface bringup time)
+ *  -> iwm_up() (main.c)
+ *      -> iwm_bus_enable()
+ *          -> if_sdio_enable() (In case of an SDIO bus)
+ *              -> sdio_enable_func()
+ *      -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker)
+ *      -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker)
+ *      -> iwm_load_fw() (fw.c)
+ *          -> iwm_load_umac()
+ *          -> iwm_load_lmac() (Calibration LMAC)
+ *          -> iwm_load_lmac() (Operational LMAC)
+ *      -> iwm_send_umac_config()
+ *
+ * iwm_stop() (Called at netdev interface bringdown time)
+ *  -> iwm_down()
+ *      -> iwm_bus_disable()
+ *          -> if_sdio_disable() (In case of an SDIO bus)
+ *              -> sdio_disable_func()
+ */
+#include <linux/netdevice.h>
+
+#include "iwm.h"
+#include "cfg80211.h"
+#include "debug.h"
+
+static int iwm_open(struct net_device *ndev)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(ndev);
+	int ret = 0;
+
+	if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
+		ret = iwm_up(iwm);
+
+	return ret;
+}
+
+static int iwm_stop(struct net_device *ndev)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(ndev);
+	int ret = 0;
+
+	if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
+		ret = iwm_down(iwm);
+
+	return ret;
+}
+
+/*
+ * iwm AC to queue mapping
+ *
+ * AC_VO -> queue 3
+ * AC_VI -> queue 2
+ * AC_BE -> queue 1
+ * AC_BK -> queue 0
+ */
+static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+
+static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	skb->priority = cfg80211_classify8021d(skb);
+
+	return iwm_1d_to_queue[skb->priority];
+}
+
+static const struct net_device_ops iwm_netdev_ops = {
+	.ndo_open		= iwm_open,
+	.ndo_stop		= iwm_stop,
+	.ndo_start_xmit		= iwm_xmit_frame,
+	.ndo_select_queue	= iwm_select_queue,
+};
+
+void *iwm_if_alloc(int sizeof_bus, struct device *dev,
+		   struct iwm_if_ops *if_ops)
+{
+	struct net_device *ndev;
+	struct wireless_dev *wdev;
+	struct iwm_priv *iwm;
+	int ret = 0;
+
+	wdev = iwm_wdev_alloc(sizeof_bus, dev);
+	if (IS_ERR(wdev))
+		return wdev;
+
+	iwm = wdev_to_iwm(wdev);
+	iwm->bus_ops = if_ops;
+	iwm->wdev = wdev;
+
+	ret = iwm_priv_init(iwm);
+	if (ret) {
+		dev_err(dev, "failed to init iwm_priv\n");
+		goto out_wdev;
+	}
+
+	wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode);
+
+	ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
+	if (!ndev) {
+		dev_err(dev, "no memory for network device instance\n");
+		goto out_priv;
+	}
+
+	ndev->netdev_ops = &iwm_netdev_ops;
+	ndev->wireless_handlers = &iwm_iw_handler_def;
+	ndev->ieee80211_ptr = wdev;
+	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+	wdev->netdev = ndev;
+
+	return iwm;
+
+ out_priv:
+	iwm_priv_deinit(iwm);
+
+ out_wdev:
+	iwm_wdev_free(iwm);
+	return ERR_PTR(ret);
+}
+
+void iwm_if_free(struct iwm_priv *iwm)
+{
+	if (!iwm_to_ndev(iwm))
+		return;
+
+	free_netdev(iwm_to_ndev(iwm));
+	iwm_priv_deinit(iwm);
+	iwm_wdev_free(iwm);
+}
+
+int iwm_if_add(struct iwm_priv *iwm)
+{
+	struct net_device *ndev = iwm_to_ndev(iwm);
+	int ret;
+
+	ret = register_netdev(ndev);
+	if (ret < 0) {
+		dev_err(&ndev->dev, "Failed to register netdev: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void iwm_if_remove(struct iwm_priv *iwm)
+{
+	unregister_netdev(iwm_to_ndev(iwm));
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/rx.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/rx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/rx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/rx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1431 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/if_arp.h>
+#include <linux/list.h>
+#include <net/iw_handler.h>
+
+#include "iwm.h"
+#include "debug.h"
+#include "hal.h"
+#include "umac.h"
+#include "lmac.h"
+#include "commands.h"
+#include "rx.h"
+#include "cfg80211.h"
+#include "eeprom.h"
+
+static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr)
+{
+	if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) ||
+	    (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL))
+		return -EINVAL;
+
+	return 0;
+}
+
+static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr)
+{
+	return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr),
+		     16);
+}
+
+/*
+ * Notification handlers:
+ *
+ * For every possible notification we can receive from the
+ * target, we have a handler.
+ * When we get a target notification, and there is no one
+ * waiting for it, it's just processed through the rx code
+ * path:
+ *
+ * iwm_rx_handle()
+ *  -> iwm_rx_handle_umac()
+ *      -> iwm_rx_handle_wifi()
+ *          -> iwm_rx_handle_resp()
+ *              -> iwm_ntf_*()
+ *
+ *      OR
+ *
+ *      -> iwm_rx_handle_non_wifi()
+ *
+ * If there are processes waiting for this notification, then
+ * iwm_rx_handle_wifi() just wakes those processes up and they
+ * grab the pending notification.
+ */
+static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
+			 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_error *error;
+	struct iwm_fw_error_hdr *fw_err;
+
+	error = (struct iwm_umac_notif_error *)buf;
+	fw_err = &error->err;
+
+
+	IWM_ERR(iwm, "%cMAC FW ERROR:\n",
+	 (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
+	IWM_ERR(iwm, "\tCategory:    %d\n", le32_to_cpu(fw_err->category));
+	IWM_ERR(iwm, "\tStatus:      0x%x\n", le32_to_cpu(fw_err->status));
+	IWM_ERR(iwm, "\tPC:          0x%x\n", le32_to_cpu(fw_err->pc));
+	IWM_ERR(iwm, "\tblink1:      %d\n", le32_to_cpu(fw_err->blink1));
+	IWM_ERR(iwm, "\tblink2:      %d\n", le32_to_cpu(fw_err->blink2));
+	IWM_ERR(iwm, "\tilink1:      %d\n", le32_to_cpu(fw_err->ilink1));
+	IWM_ERR(iwm, "\tilink2:      %d\n", le32_to_cpu(fw_err->ilink2));
+	IWM_ERR(iwm, "\tData1:       0x%x\n", le32_to_cpu(fw_err->data1));
+	IWM_ERR(iwm, "\tData2:       0x%x\n", le32_to_cpu(fw_err->data2));
+	IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num));
+	IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status));
+	IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
+	IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
+
+	return 0;
+}
+
+static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf,
+			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_alive *alive_resp =
+			(struct iwm_umac_notif_alive *)(buf);
+	u16 status = le16_to_cpu(alive_resp->status);
+
+	if (status == UMAC_NTFY_ALIVE_STATUS_ERR) {
+		IWM_ERR(iwm, "Receive error UMAC_ALIVE\n");
+		return -EIO;
+	}
+
+	iwm_tx_credit_init_pools(iwm, alive_resp);
+
+	return 0;
+}
+
+static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf,
+				 unsigned long buf_size,
+				 struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_init_complete *init_complete =
+			(struct iwm_umac_notif_init_complete *)(buf);
+	u16 status = le16_to_cpu(init_complete->status);
+
+	if (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR) {
+		IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n");
+		set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
+	} else {
+		IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n");
+		clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
+	}
+
+	return 0;
+}
+
+static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf,
+				    unsigned long buf_size,
+				    struct iwm_wifi_cmd *cmd)
+{
+	int pool_nr, total_freed_pages;
+	unsigned long pool_map;
+	int i, id;
+	struct iwm_umac_notif_page_dealloc *dealloc =
+			(struct iwm_umac_notif_page_dealloc *)buf;
+
+	pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT);
+	pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK);
+
+	IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, "
+		   "update map 0x%lx\n", pool_nr, pool_map);
+
+	spin_lock(&iwm->tx_credit.lock);
+
+	for (i = 0; i < pool_nr; i++) {
+		id = GET_VAL32(dealloc->grp_info[i],
+			       UMAC_DEALLOC_NTFY_GROUP_NUM);
+		if (test_bit(id, &pool_map)) {
+			total_freed_pages = GET_VAL32(dealloc->grp_info[i],
+					      UMAC_DEALLOC_NTFY_PAGE_CNT);
+			iwm_tx_credit_inc(iwm, id, total_freed_pages);
+		}
+	}
+
+	spin_unlock(&iwm->tx_credit.lock);
+
+	return 0;
+}
+
+static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf,
+			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n");
+
+	return 0;
+}
+
+static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf,
+				unsigned long buf_size,
+				struct iwm_wifi_cmd *cmd)
+{
+	IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]);
+
+	return 0;
+}
+
+static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf,
+		      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_lmac_tx_resp *tx_resp;
+	struct iwm_umac_wifi_in_hdr *hdr;
+
+	tx_resp = (struct iwm_lmac_tx_resp *)
+		(buf + sizeof(struct iwm_umac_wifi_in_hdr));
+	hdr = (struct iwm_umac_wifi_in_hdr *)buf;
+
+	IWM_DBG_NTF(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size);
+
+	IWM_DBG_NTF(iwm, DBG, "Seqnum: %d\n",
+		    le16_to_cpu(hdr->sw_hdr.cmd.seq_num));
+	IWM_DBG_NTF(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt);
+	IWM_DBG_NTF(iwm, DBG, "\tRetry cnt: %d\n",
+		    le16_to_cpu(tx_resp->retry_cnt));
+	IWM_DBG_NTF(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl));
+	IWM_DBG_NTF(iwm, DBG, "\tByte cnt: %d\n",
+		    le16_to_cpu(tx_resp->byte_cnt));
+	IWM_DBG_NTF(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status));
+
+	return 0;
+}
+
+
+static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf,
+			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	u8 opcode;
+	u8 *calib_buf;
+	struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *)
+				(buf + sizeof(struct iwm_umac_wifi_in_hdr));
+
+	opcode = hdr->opcode;
+
+	BUG_ON(opcode >= CALIBRATION_CMD_NUM ||
+	       opcode < PHY_CALIBRATE_OPCODES_NUM);
+
+	IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n",
+		    opcode);
+
+	buf_size -= sizeof(struct iwm_umac_wifi_in_hdr);
+	calib_buf = iwm->calib_res[opcode].buf;
+
+	if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) {
+		kfree(calib_buf);
+		calib_buf = kzalloc(buf_size, GFP_KERNEL);
+		if (!calib_buf) {
+			IWM_ERR(iwm, "Memory allocation failed: calib_res\n");
+			return -ENOMEM;
+		}
+		iwm->calib_res[opcode].buf = calib_buf;
+		iwm->calib_res[opcode].size = buf_size;
+	}
+
+	memcpy(calib_buf, hdr, buf_size);
+	set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map);
+
+	return 0;
+}
+
+static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf,
+				  unsigned long buf_size,
+				  struct iwm_wifi_cmd *cmd)
+{
+	IWM_DBG_NTF(iwm, DBG, "Calibration completed\n");
+
+	return 0;
+}
+
+static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf,
+			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_lmac_cal_cfg_resp *cal_resp;
+
+	cal_resp = (struct iwm_lmac_cal_cfg_resp *)
+			(buf + sizeof(struct iwm_umac_wifi_in_hdr));
+
+	IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n",
+		    le32_to_cpu(cal_resp->status));
+
+	return 0;
+}
+
+static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf,
+			       unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_wifi_status *status =
+		(struct iwm_umac_notif_wifi_status *)buf;
+
+	iwm->core_enabled |= le16_to_cpu(status->status);
+
+	return 0;
+}
+
+static struct iwm_rx_ticket_node *
+iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket)
+{
+	struct iwm_rx_ticket_node *ticket_node;
+
+	ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL);
+	if (!ticket_node) {
+		IWM_ERR(iwm, "Couldn't allocate ticket node\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ticket_node->ticket = kzalloc(sizeof(struct iwm_rx_ticket), GFP_KERNEL);
+	if (!ticket_node->ticket) {
+		IWM_ERR(iwm, "Couldn't allocate RX ticket\n");
+		kfree(ticket_node);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	memcpy(ticket_node->ticket, ticket, sizeof(struct iwm_rx_ticket));
+	INIT_LIST_HEAD(&ticket_node->node);
+
+	return ticket_node;
+}
+
+static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node)
+{
+	kfree(ticket_node->ticket);
+	kfree(ticket_node);
+}
+
+static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
+{
+	u8 id_hash = IWM_RX_ID_GET_HASH(id);
+	struct list_head *packet_list;
+	struct iwm_rx_packet *packet, *next;
+
+	packet_list = &iwm->rx_packets[id_hash];
+
+	list_for_each_entry_safe(packet, next, packet_list, node)
+		if (packet->id == id)
+			return packet;
+
+	return NULL;
+}
+
+static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf,
+						 u32 size, u16 id)
+{
+	struct iwm_rx_packet *packet;
+
+	packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL);
+	if (!packet) {
+		IWM_ERR(iwm, "Couldn't allocate packet\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	packet->skb = dev_alloc_skb(size);
+	if (!packet->skb) {
+		IWM_ERR(iwm, "Couldn't allocate packet SKB\n");
+		kfree(packet);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	packet->pkt_size = size;
+
+	skb_put(packet->skb, size);
+	memcpy(packet->skb->data, buf, size);
+	INIT_LIST_HEAD(&packet->node);
+	packet->id = id;
+
+	return packet;
+}
+
+void iwm_rx_free(struct iwm_priv *iwm)
+{
+	struct iwm_rx_ticket_node *ticket, *nt;
+	struct iwm_rx_packet *packet, *np;
+	int i;
+
+	list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
+		list_del(&ticket->node);
+		iwm_rx_ticket_node_free(ticket);
+	}
+
+	for (i = 0; i < IWM_RX_ID_HASH; i++) {
+		list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
+					 node) {
+			list_del(&packet->node);
+			kfree_skb(packet->skb);
+			kfree(packet);
+		}
+	}
+}
+
+static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
+			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_rx_ticket *ntf_rx_ticket =
+		(struct iwm_umac_notif_rx_ticket *)buf;
+	struct iwm_rx_ticket *ticket =
+		(struct iwm_rx_ticket *)ntf_rx_ticket->tickets;
+	int i, schedule_rx = 0;
+
+	for (i = 0; i < ntf_rx_ticket->num_tickets; i++) {
+		struct iwm_rx_ticket_node *ticket_node;
+
+		switch (le16_to_cpu(ticket->action)) {
+		case IWM_RX_TICKET_RELEASE:
+		case IWM_RX_TICKET_DROP:
+			/* We can push the packet to the stack */
+			ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket);
+			if (IS_ERR(ticket_node))
+				return PTR_ERR(ticket_node);
+
+			IWM_DBG_NTF(iwm, DBG, "TICKET RELEASE(%d)\n",
+				    ticket->id);
+			list_add_tail(&ticket_node->node, &iwm->rx_tickets);
+
+			/*
+			 * We received an Rx ticket, most likely there's
+			 * a packet pending for it, it's not worth going
+			 * through the packet hash list to double check.
+			 * Let's just fire the rx worker..
+			 */
+			schedule_rx = 1;
+
+			break;
+
+		default:
+			IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n",
+				ticket->action);
+		}
+
+		ticket++;
+	}
+
+	if (schedule_rx)
+		queue_work(iwm->rx_wq, &iwm->rx_worker);
+
+	return 0;
+}
+
+static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
+			     unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_wifi_in_hdr *wifi_hdr;
+	struct iwm_rx_packet *packet;
+	u16 id, buf_offset;
+	u32 packet_size;
+
+	IWM_DBG_NTF(iwm, DBG, "\n");
+
+	wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
+	id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
+	buf_offset = sizeof(struct iwm_umac_wifi_in_hdr);
+	packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr);
+
+	IWM_DBG_NTF(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n",
+		    wifi_hdr->sw_hdr.cmd.cmd, id, packet_size);
+	IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id);
+	IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size);
+
+	packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id);
+	if (IS_ERR(packet))
+		return PTR_ERR(packet);
+
+	list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]);
+
+	/* We might (unlikely) have received the packet _after_ the ticket */
+	queue_work(iwm->rx_wq, &iwm->rx_worker);
+
+	return 0;
+}
+
+/* MLME handlers */
+static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
+				unsigned long buf_size,
+				struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_assoc_start *start;
+
+	start = (struct iwm_umac_notif_assoc_start *)buf;
+
+	set_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
+
+	IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n",
+		     start->bssid, le32_to_cpu(start->roam_reason));
+
+	wake_up_interruptible(&iwm->mlme_queue);
+
+	return 0;
+}
+
+static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
+				   unsigned long buf_size,
+				   struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_assoc_complete *complete =
+		(struct iwm_umac_notif_assoc_complete *)buf;
+	union iwreq_data wrqu;
+
+	IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
+		     complete->bssid, complete->status);
+
+	memset(&wrqu, 0, sizeof(wrqu));
+
+	clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
+
+	switch (le32_to_cpu(complete->status)) {
+	case UMAC_ASSOC_COMPLETE_SUCCESS:
+		set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
+		memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
+		iwm->channel = complete->channel;
+
+		iwm_link_on(iwm);
+
+		memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN);
+		break;
+	case UMAC_ASSOC_COMPLETE_FAILURE:
+		clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
+		memset(iwm->bssid, 0, ETH_ALEN);
+		iwm->channel = 0;
+
+		iwm_link_off(iwm);
+	default:
+		break;
+	}
+
+	if (iwm->conf.mode == UMAC_MODE_IBSS) {
+		cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
+		return 0;
+	}
+
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL);
+
+	return 0;
+}
+
+static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
+				       unsigned long buf_size,
+				       struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_profile_invalidate *invalid;
+
+	invalid = (struct iwm_umac_notif_profile_invalidate *)buf;
+
+	IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n",
+		     le32_to_cpu(invalid->reason));
+
+	clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
+	clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
+
+	iwm->umac_profile_active = 0;
+	memset(iwm->bssid, 0, ETH_ALEN);
+	iwm->channel = 0;
+
+	iwm_link_off(iwm);
+
+	wake_up_interruptible(&iwm->mlme_queue);
+
+	return 0;
+}
+
+static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf,
+				  unsigned long buf_size,
+				  struct iwm_wifi_cmd *cmd)
+{
+	int ret;
+	struct iwm_umac_notif_scan_complete *scan_complete =
+		(struct iwm_umac_notif_scan_complete *)buf;
+	u32 result = le32_to_cpu(scan_complete->result);
+
+	IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n",
+		     le32_to_cpu(scan_complete->type),
+		     le32_to_cpu(scan_complete->result),
+		     scan_complete->seq_num);
+
+	if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) {
+		IWM_ERR(iwm, "Scan complete while device not scanning\n");
+		return -EIO;
+	}
+	if (!iwm->scan_request)
+		return 0;
+
+	ret = iwm_cfg80211_inform_bss(iwm);
+
+	cfg80211_scan_done(iwm->scan_request,
+			   (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret);
+	iwm->scan_request = NULL;
+
+	return ret;
+}
+
+static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf,
+				     unsigned long buf_size,
+				     struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_sta_info *umac_sta =
+			(struct iwm_umac_notif_sta_info *)buf;
+	struct iwm_sta_info *sta;
+	int i;
+
+	switch (le32_to_cpu(umac_sta->opcode)) {
+	case UMAC_OPCODE_ADD_MODIFY:
+		sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
+
+		IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, "
+			     "addr = %pM, qos = %d\n",
+			     sta->valid ? "Modify" : "Add",
+			     GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
+			     GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
+			     umac_sta->mac_addr,
+			     umac_sta->flags & UMAC_STA_FLAG_QOS);
+
+		sta->valid = 1;
+		sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS;
+		sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR);
+		memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN);
+		break;
+	case UMAC_OPCODE_REMOVE:
+		IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, "
+			     "addr = %pM\n",
+			     GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
+			     GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
+			     umac_sta->mac_addr);
+
+		sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
+
+		if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN))
+			sta->valid = 0;
+
+		break;
+	case UMAC_OPCODE_CLEAR_ALL:
+		for (i = 0; i < IWM_STA_TABLE_NUM; i++)
+			iwm->sta_table[i].valid = 0;
+
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
+				     unsigned long buf_size,
+				     struct iwm_wifi_cmd *cmd)
+{
+	struct wiphy *wiphy = iwm_to_wiphy(iwm);
+	struct ieee80211_mgmt *mgmt;
+	struct iwm_umac_notif_bss_info *umac_bss =
+			(struct iwm_umac_notif_bss_info *)buf;
+	struct ieee80211_channel *channel;
+	struct ieee80211_supported_band *band;
+	struct iwm_bss_info *bss, *next;
+	s32 signal;
+	int freq;
+	u16 frame_len = le16_to_cpu(umac_bss->frame_len);
+	size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len;
+
+	mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
+
+	IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid);
+	IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type));
+	IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n",
+		     le32_to_cpu(umac_bss->timestamp));
+	IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n",
+		     le16_to_cpu(umac_bss->table_idx));
+	IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band);
+	IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel);
+	IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi);
+	IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len);
+
+	list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
+		if (bss->bss->table_idx == umac_bss->table_idx)
+			break;
+
+	if (&bss->node != &iwm->bss_list) {
+		/* Remove the old BSS entry, we will add it back later. */
+		list_del(&bss->node);
+		kfree(bss->bss);
+	} else {
+		/* New BSS entry */
+
+		bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL);
+		if (!bss) {
+			IWM_ERR(iwm, "Couldn't allocate bss_info\n");
+			return -ENOMEM;
+		}
+	}
+
+	bss->bss = kzalloc(bss_len, GFP_KERNEL);
+	if (!bss) {
+		kfree(bss);
+		IWM_ERR(iwm, "Couldn't allocate bss\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&bss->node);
+	memcpy(bss->bss, umac_bss, bss_len);
+
+	if (umac_bss->band == UMAC_BAND_2GHZ)
+		band = wiphy->bands[IEEE80211_BAND_2GHZ];
+	else if (umac_bss->band == UMAC_BAND_5GHZ)
+		band = wiphy->bands[IEEE80211_BAND_5GHZ];
+	else {
+		IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
+		goto err;
+	}
+
+	freq = ieee80211_channel_to_frequency(umac_bss->channel);
+	channel = ieee80211_get_channel(wiphy, freq);
+	signal = umac_bss->rssi * 100;
+
+	bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel,
+						 mgmt, frame_len,
+						 signal, GFP_KERNEL);
+	if (!bss->cfg_bss)
+		goto err;
+
+	list_add_tail(&bss->node, &iwm->bss_list);
+
+	return 0;
+ err:
+	kfree(bss->bss);
+	kfree(bss);
+
+	return -EINVAL;
+}
+
+static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf,
+			       unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_bss_removed *bss_rm =
+		(struct iwm_umac_notif_bss_removed *)buf;
+	struct iwm_bss_info *bss, *next;
+	u16 table_idx;
+	int i;
+
+	for (i = 0; i < le32_to_cpu(bss_rm->count); i++) {
+		table_idx = (le16_to_cpu(bss_rm->entries[i])
+			     & IWM_BSS_REMOVE_INDEX_MSK);
+		list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
+			if (bss->bss->table_idx == cpu_to_le16(table_idx)) {
+				struct ieee80211_mgmt *mgmt;
+
+				mgmt = (struct ieee80211_mgmt *)
+					(bss->bss->frame_buf);
+				IWM_DBG_MLME(iwm, ERR,
+					     "BSS removed: %pM\n",
+					     mgmt->bssid);
+				list_del(&bss->node);
+				kfree(bss->bss);
+				kfree(bss);
+			}
+	}
+
+	return 0;
+}
+
+static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
+			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_mgt_frame *mgt_frame =
+	(struct iwm_umac_notif_mgt_frame *)buf;
+	struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame;
+	u8 *ie;
+	unsigned int event;
+	union iwreq_data wrqu;
+
+	IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame,
+		    le16_to_cpu(mgt_frame->len));
+
+	if (ieee80211_is_assoc_req(mgt->frame_control)) {
+		ie = mgt->u.assoc_req.variable;;
+		event = IWEVASSOCREQIE;
+	} else if (ieee80211_is_reassoc_req(mgt->frame_control)) {
+		ie = mgt->u.reassoc_req.variable;;
+		event = IWEVASSOCREQIE;
+	} else if (ieee80211_is_assoc_resp(mgt->frame_control)) {
+		ie = mgt->u.assoc_resp.variable;;
+		event = IWEVASSOCRESPIE;
+	} else if (ieee80211_is_reassoc_resp(mgt->frame_control)) {
+		ie = mgt->u.reassoc_resp.variable;;
+		event = IWEVASSOCRESPIE;
+	} else {
+		IWM_ERR(iwm, "Unsupported management frame");
+		return 0;
+	}
+
+	wrqu.data.length = le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
+
+	IWM_HEXDUMP(iwm, DBG, MLME, "EVT: ", ie, wrqu.data.length);
+	wireless_send_event(iwm_to_ndev(iwm), event, &wrqu, ie);
+
+	return 0;
+}
+
+static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
+			unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_wifi_if *notif =
+		(struct iwm_umac_notif_wifi_if *)buf;
+
+	switch (notif->status) {
+	case WIFI_IF_NTFY_ASSOC_START:
+		return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd);
+	case WIFI_IF_NTFY_ASSOC_COMPLETE:
+		return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd);
+	case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE:
+		return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd);
+	case WIFI_IF_NTFY_CONNECTION_TERMINATED:
+		IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
+		break;
+	case WIFI_IF_NTFY_SCAN_COMPLETE:
+		return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd);
+	case WIFI_IF_NTFY_STA_TABLE_CHANGE:
+		return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd);
+	case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED:
+		IWM_DBG_MLME(iwm, DBG, "Extended IE required\n");
+		break;
+	case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED:
+		return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd);
+	case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED:
+		return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd);
+		break;
+	case WIFI_IF_NTFY_MGMT_FRAME:
+		return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd);
+	case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START:
+	case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE:
+	case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START:
+	case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT:
+	case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START:
+	case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE:
+	case WIFI_DBG_IF_NTFY_CNCT_ATC_START:
+	case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION:
+	case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP:
+	case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP:
+		IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n",
+			     notif->status);
+		break;
+	default:
+		IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status);
+		break;
+	}
+
+	return 0;
+}
+
+#define IWM_STATS_UPDATE_INTERVAL		(2 * HZ)
+
+static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf,
+			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf;
+	struct iw_statistics *wstats = &iwm->wstats;
+	u16 max_rate = 0;
+	int i;
+
+	IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n");
+
+	if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
+		for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) {
+			max_rate = max_t(u16, max_rate,
+					 max(le16_to_cpu(stats->tx_rate[i]),
+					     le16_to_cpu(stats->rx_rate[i])));
+		}
+		/* UMAC passes rate info multiplies by 2 */
+		iwm->rate = max_rate >> 1;
+	}
+
+	wstats->status = 0;
+
+	wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid);
+	wstats->discard.code = le32_to_cpu(stats->rx_drop_decode);
+	wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly);
+	wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry);
+
+	wstats->miss.beacon = le32_to_cpu(stats->missed_beacons);
+
+	/* according to cfg80211 */
+	if (stats->rssi_dbm < -110)
+		wstats->qual.qual = 0;
+	else if (stats->rssi_dbm > -40)
+		wstats->qual.qual = 70;
+	else
+		wstats->qual.qual = stats->rssi_dbm + 110;
+
+	wstats->qual.level = stats->rssi_dbm;
+	wstats->qual.noise = stats->noise_dbm;
+	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+	schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL);
+
+	mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD));
+
+	return 0;
+}
+
+static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf,
+				unsigned long buf_size,
+				struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy =
+		(struct iwm_umac_cmd_eeprom_proxy *)
+		(buf + sizeof(struct iwm_umac_wifi_in_hdr));
+	struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr;
+	u32 hdr_offset = le32_to_cpu(hdr->offset);
+	u32 hdr_len = le32_to_cpu(hdr->len);
+	u32 hdr_type = le32_to_cpu(hdr->type);
+
+	IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n",
+		    hdr_type, hdr_len, hdr_offset);
+
+	if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN)
+		return -EINVAL;
+
+#ifdef CONFIG_IWM_B0_HW_SUPPORT
+	if (hdr_offset == IWM_EEPROM_SKU_CAP_OFF) {
+		if (eeprom_proxy->buf[0] == 0xff)
+			iwm->conf.hw_b0 = 1;
+	}
+#endif
+
+	switch (hdr_type) {
+	case IWM_UMAC_CMD_EEPROM_TYPE_READ:
+		memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len);
+		break;
+	case IWM_UMAC_CMD_EEPROM_TYPE_WRITE:
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf,
+				     unsigned long buf_size,
+				     struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_cmd_get_channel_list *ch_list =
+			(struct iwm_umac_cmd_get_channel_list *)
+			(buf + sizeof(struct iwm_umac_wifi_in_hdr));
+	struct wiphy *wiphy = iwm_to_wiphy(iwm);
+	struct ieee80211_supported_band *band;
+	int i;
+
+	band = wiphy->bands[IEEE80211_BAND_2GHZ];
+
+	for (i = 0; i < band->n_channels; i++) {
+		unsigned long ch_mask_0 =
+			le32_to_cpu(ch_list->ch[0].channels_mask);
+		unsigned long ch_mask_2 =
+			le32_to_cpu(ch_list->ch[2].channels_mask);
+
+		if (!test_bit(i, &ch_mask_0))
+			band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
+
+		if (!test_bit(i, &ch_mask_2))
+			band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
+	}
+
+	band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+	for (i = 0; i < min(band->n_channels, 32); i++) {
+		unsigned long ch_mask_1 =
+			le32_to_cpu(ch_list->ch[1].channels_mask);
+		unsigned long ch_mask_3 =
+			le32_to_cpu(ch_list->ch[3].channels_mask);
+
+		if (!test_bit(i, &ch_mask_1))
+			band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
+
+		if (!test_bit(i, &ch_mask_3))
+			band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
+	}
+
+	return 0;
+}
+
+static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
+				   unsigned long buf_size,
+				   struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_umac_wifi_if *hdr =
+			(struct iwm_umac_wifi_if *)cmd->buf.payload;
+
+	IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
+		    "oid is %d\n", hdr->oid);
+
+	switch (hdr->oid) {
+	case UMAC_WIFI_IF_CMD_SET_PROFILE:
+		iwm->umac_profile_active = 1;
+		wake_up_interruptible(&iwm->mlme_queue);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
+			      unsigned long buf_size, struct iwm_wifi_cmd *cmd)
+{
+	struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *)
+				(buf + sizeof(struct iwm_umac_wifi_in_hdr));
+	u32 flags = le32_to_cpu(state->flags);
+
+	IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n",
+		 flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
+		 flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
+
+	if (flags & IWM_CARD_STATE_HW_DISABLED)
+		set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
+	else
+		clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
+
+	return 0;
+}
+
+static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
+			      unsigned long buf_size)
+{
+	struct iwm_umac_wifi_in_hdr *wifi_hdr;
+	struct iwm_wifi_cmd *cmd;
+	u8 source, cmd_id;
+	u16 seq_num;
+	u32 count;
+	u8 resp;
+
+	wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
+	cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
+
+	source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
+	if (source >= IWM_SRC_NUM) {
+		IWM_CRIT(iwm, "invalid source %d\n", source);
+		return -EINVAL;
+	}
+
+	count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT));
+	count += sizeof(struct iwm_umac_wifi_in_hdr) -
+		 sizeof(struct iwm_dev_cmd_hdr);
+	if (count > buf_size) {
+		IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size);
+		return -EINVAL;
+	}
+
+	resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS);
+
+	seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
+
+	IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
+		   cmd_id, source, seq_num);
+
+	/*
+	 * If this is a response to a previously sent command, there must
+	 * be a pending command for this sequence number.
+	 */
+	cmd = iwm_get_pending_wifi_cmd(iwm, seq_num);
+
+	/* Notify the caller only for sync commands. */
+	switch (source) {
+	case UMAC_HDI_IN_SOURCE_FHRX:
+		if (iwm->lmac_handlers[cmd_id] &&
+		    test_bit(cmd_id, &iwm->lmac_handler_map[0]))
+			return iwm_notif_send(iwm, cmd, cmd_id, source,
+					      buf, count);
+		break;
+	case UMAC_HDI_IN_SOURCE_FW:
+		if (iwm->umac_handlers[cmd_id] &&
+		    test_bit(cmd_id, &iwm->umac_handler_map[0]))
+			return iwm_notif_send(iwm, cmd, cmd_id, source,
+					      buf, count);
+		break;
+	case UMAC_HDI_IN_SOURCE_UDMA:
+		break;
+	}
+
+	return iwm_rx_handle_resp(iwm, buf, count, cmd);
+}
+
+int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
+		       struct iwm_wifi_cmd *cmd)
+{
+	u8 source, cmd_id;
+	struct iwm_umac_wifi_in_hdr *wifi_hdr;
+	int ret = 0;
+
+	wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
+	cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
+
+	source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
+
+	IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source);
+
+	switch (source) {
+	case UMAC_HDI_IN_SOURCE_FHRX:
+		if (iwm->lmac_handlers[cmd_id])
+			ret = iwm->lmac_handlers[cmd_id]
+					(iwm, buf, buf_size, cmd);
+		break;
+	case UMAC_HDI_IN_SOURCE_FW:
+		if (iwm->umac_handlers[cmd_id])
+			ret = iwm->umac_handlers[cmd_id]
+					(iwm, buf, buf_size, cmd);
+		break;
+	case UMAC_HDI_IN_SOURCE_UDMA:
+		ret = -EINVAL;
+		break;
+	}
+
+	kfree(cmd);
+
+	return ret;
+}
+
+static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
+				 unsigned long buf_size)
+{
+	u8 seq_num;
+	struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
+	struct iwm_nonwifi_cmd *cmd, *next;
+
+	seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
+
+	/*
+	 * We received a non wifi answer.
+	 * Let's check if there's a pending command for it, and if so
+	 * replace the command payload with the buffer, and then wake the
+	 * callers up.
+	 * That means we only support synchronised non wifi command response
+	 * schemes.
+	 */
+	list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending)
+		if (cmd->seq_num == seq_num) {
+			cmd->resp_received = 1;
+			cmd->buf.len = buf_size;
+			memcpy(cmd->buf.hdr, buf, buf_size);
+			wake_up_interruptible(&iwm->nonwifi_queue);
+		}
+
+	return 0;
+}
+
+static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf,
+			      unsigned long buf_size)
+{
+	int ret = 0;
+	u8 op_code;
+	unsigned long buf_offset = 0;
+	struct iwm_udma_in_hdr *hdr;
+
+	/*
+	 * To allow for a more efficient bus usage, UMAC
+	 * messages are encapsulated into UDMA ones. This
+	 * way we can have several UMAC messages in one bus
+	 * transfer.
+	 * A UDMA frame size is always aligned on 16 bytes,
+	 * and a UDMA frame must not start with a UMAC_PAD_TERMINAL
+	 * word. This is how we parse a bus frame into several
+	 * UDMA ones.
+	 */
+	while (buf_offset < buf_size) {
+
+		hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset);
+
+		if (iwm_rx_check_udma_hdr(hdr) < 0) {
+			IWM_DBG_RX(iwm, DBG, "End of frame\n");
+			break;
+		}
+
+		op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE);
+
+		IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code);
+
+		if (op_code == UMAC_HDI_IN_OPCODE_WIFI) {
+			ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset,
+						  buf_size - buf_offset);
+		} else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) {
+			if (GET_VAL32(hdr->cmd,
+				      UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) !=
+			    UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) {
+				IWM_ERR(iwm, "Incorrect hw signature\n");
+				return -EINVAL;
+			}
+			ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset,
+						     buf_size - buf_offset);
+		} else {
+			IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code);
+			ret |= -EINVAL;
+		}
+
+		buf_offset += iwm_rx_resp_size(hdr);
+	}
+
+	return ret;
+}
+
+int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size)
+{
+	struct iwm_udma_in_hdr *hdr;
+
+	hdr = (struct iwm_udma_in_hdr *)buf;
+
+	switch (le32_to_cpu(hdr->cmd)) {
+	case UMAC_REBOOT_BARKER:
+		return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION,
+				      IWM_SRC_UDMA, buf, buf_size);
+	case UMAC_ACK_BARKER:
+		return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION,
+				      IWM_SRC_UDMA, NULL, 0);
+	default:
+		IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd);
+		return iwm_rx_handle_umac(iwm, buf, buf_size);
+	}
+
+	return 0;
+}
+
+static const iwm_handler iwm_umac_handlers[] =
+{
+	[UMAC_NOTIFY_OPCODE_ERROR]		= iwm_ntf_error,
+	[UMAC_NOTIFY_OPCODE_ALIVE]		= iwm_ntf_umac_alive,
+	[UMAC_NOTIFY_OPCODE_INIT_COMPLETE]	= iwm_ntf_init_complete,
+	[UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS]	= iwm_ntf_wifi_status,
+	[UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER]	= iwm_ntf_mlme,
+	[UMAC_NOTIFY_OPCODE_PAGE_DEALLOC]	= iwm_ntf_tx_credit_update,
+	[UMAC_NOTIFY_OPCODE_RX_TICKET]		= iwm_ntf_rx_ticket,
+	[UMAC_CMD_OPCODE_RESET]			= iwm_ntf_umac_reset,
+	[UMAC_NOTIFY_OPCODE_STATS]		= iwm_ntf_statistics,
+	[UMAC_CMD_OPCODE_EEPROM_PROXY]		= iwm_ntf_eeprom_proxy,
+	[UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST]	= iwm_ntf_channel_info_list,
+	[REPLY_RX_MPDU_CMD]			= iwm_ntf_rx_packet,
+	[UMAC_CMD_OPCODE_WIFI_IF_WRAPPER]	= iwm_ntf_wifi_if_wrapper,
+};
+
+static const iwm_handler iwm_lmac_handlers[] =
+{
+	[REPLY_TX]				= iwm_ntf_tx,
+	[REPLY_ALIVE]				= iwm_ntf_lmac_version,
+	[CALIBRATION_RES_NOTIFICATION]		= iwm_ntf_calib_res,
+	[CALIBRATION_COMPLETE_NOTIFICATION]	= iwm_ntf_calib_complete,
+	[CALIBRATION_CFG_CMD]			= iwm_ntf_calib_cfg,
+	[REPLY_RX_MPDU_CMD]			= iwm_ntf_rx_packet,
+	[CARD_STATE_NOTIFICATION]		= iwm_ntf_card_state,
+};
+
+void iwm_rx_setup_handlers(struct iwm_priv *iwm)
+{
+	iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers;
+	iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers;
+}
+
+static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len)
+{
+	struct ieee80211_hdr *hdr;
+	unsigned int hdr_len;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	if (!ieee80211_has_protected(hdr->frame_control))
+		return;
+
+	hdr_len = ieee80211_hdrlen(hdr->frame_control);
+	if (hdr_total_len <= hdr_len)
+		return;
+
+	memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len);
+	skb_pull(skb, (hdr_total_len - hdr_len));
+}
+
+static void iwm_rx_adjust_packet(struct iwm_priv *iwm,
+				 struct iwm_rx_packet *packet,
+				 struct iwm_rx_ticket_node *ticket_node)
+{
+	u32 payload_offset = 0, payload_len;
+	struct iwm_rx_ticket *ticket = ticket_node->ticket;
+	struct iwm_rx_mpdu_hdr *mpdu_hdr;
+	struct ieee80211_hdr *hdr;
+
+	mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data;
+	payload_offset += sizeof(struct iwm_rx_mpdu_hdr);
+	/* Padding is 0 or 2 bytes */
+	payload_len = le16_to_cpu(mpdu_hdr->len) +
+		(le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK);
+	payload_len -= ticket->tail_len;
+
+	IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, "
+		   "ticket offset:%d ticket tail len:%d\n",
+		   payload_len, payload_offset, ticket->payload_offset,
+		   ticket->tail_len);
+
+	IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len);
+
+	skb_pull(packet->skb, payload_offset);
+	skb_trim(packet->skb, payload_len);
+
+	iwm_remove_iv(packet->skb, ticket->payload_offset);
+
+	hdr = (struct ieee80211_hdr *) packet->skb->data;
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		/* UMAC handed QOS_DATA frame with 2 padding bytes appended
+		 * to the qos_ctl field in IEEE 802.11 headers. */
+		memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2,
+			packet->skb->data,
+			ieee80211_hdrlen(hdr->frame_control) -
+			IEEE80211_QOS_CTL_LEN);
+		hdr = (struct ieee80211_hdr *) skb_pull(packet->skb,
+				IEEE80211_QOS_CTL_LEN + 2);
+		hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
+	}
+
+	IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ",
+		    packet->skb->data, packet->skb->len);
+}
+
+static void classify8023(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		/* frame has qos control */
+		skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK;
+	} else {
+		skb->priority = 0;
+	}
+}
+
+static void iwm_rx_process_packet(struct iwm_priv *iwm,
+				  struct iwm_rx_packet *packet,
+				  struct iwm_rx_ticket_node *ticket_node)
+{
+	int ret;
+	struct sk_buff *skb = packet->skb;
+	struct wireless_dev *wdev = iwm_to_wdev(iwm);
+	struct net_device *ndev = iwm_to_ndev(iwm);
+
+	IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id);
+
+	switch (le16_to_cpu(ticket_node->ticket->action)) {
+	case IWM_RX_TICKET_RELEASE:
+		IWM_DBG_RX(iwm, DBG, "RELEASE packet\n");
+		classify8023(skb);
+		iwm_rx_adjust_packet(iwm, packet, ticket_node);
+		ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype);
+		if (ret < 0) {
+			IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - "
+				   "%d\n", ret);
+			break;
+		}
+
+		IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len);
+
+		skb->dev = iwm_to_ndev(iwm);
+		skb->protocol = eth_type_trans(skb, ndev);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		memset(skb->cb, 0, sizeof(skb->cb));
+
+		ndev->stats.rx_packets++;
+		ndev->stats.rx_bytes += skb->len;
+
+		if (netif_rx(skb) == NET_RX_DROP) {
+			IWM_ERR(iwm, "Packet dropped\n");
+			ndev->stats.rx_dropped++;
+		}
+		break;
+	case IWM_RX_TICKET_DROP:
+		IWM_DBG_RX(iwm, DBG, "DROP packet\n");
+		kfree_skb(packet->skb);
+		break;
+	default:
+		IWM_ERR(iwm, "Unknow ticket action: %d\n",
+			le16_to_cpu(ticket_node->ticket->action));
+		kfree_skb(packet->skb);
+	}
+
+	kfree(packet);
+	iwm_rx_ticket_node_free(ticket_node);
+}
+
+/*
+ * Rx data processing:
+ *
+ * We're receiving Rx packet from the LMAC, and Rx ticket from
+ * the UMAC.
+ * To forward a target data packet upstream (i.e. to the
+ * kernel network stack), we must have received an Rx ticket
+ * that tells us we're allowed to release this packet (ticket
+ * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates,
+ * among other things, where valid data actually starts in the Rx
+ * packet.
+ */
+void iwm_rx_worker(struct work_struct *work)
+{
+	struct iwm_priv *iwm;
+	struct iwm_rx_ticket_node *ticket, *next;
+
+	iwm = container_of(work, struct iwm_priv, rx_worker);
+
+	/*
+	 * We go through the tickets list and if there is a pending
+	 * packet for it, we push it upstream.
+	 * We stop whenever a ticket is missing its packet, as we're
+	 * supposed to send the packets in order.
+	 */
+	list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
+		struct iwm_rx_packet *packet =
+			iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
+
+		if (!packet) {
+			IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
+				   "to be handled first\n",
+				   le16_to_cpu(ticket->ticket->id));
+			return;
+		}
+
+		list_del(&ticket->node);
+		list_del(&packet->node);
+		iwm_rx_process_packet(iwm, packet, ticket);
+	}
+}
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/rx.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/rx.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/rx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/rx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_RX_H__
+#define __IWM_RX_H__
+
+#include <linux/skbuff.h>
+
+#include "umac.h"
+
+struct iwm_rx_ticket_node {
+	struct list_head node;
+	struct iwm_rx_ticket *ticket;
+};
+
+struct iwm_rx_packet {
+	struct list_head node;
+	u16 id;
+	struct sk_buff *skb;
+	unsigned long pkt_size;
+};
+
+void iwm_rx_worker(struct work_struct *work);
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/sdio.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/sdio.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/sdio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/sdio.c	2012-03-22 20:13:02.000000000 -0400
@@ -0,0 +1,525 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+/*
+ * This is the SDIO bus specific hooks for iwm.
+ * It also is the module's entry point.
+ *
+ * Interesting code paths:
+ * iwm_sdio_probe() (Called by an SDIO bus scan)
+ *  -> iwm_if_alloc() (netdev.c)
+ *      -> iwm_wdev_alloc() (cfg80211.c, allocates and register our wiphy)
+ *          -> wiphy_new()
+ *          -> wiphy_register()
+ *      -> alloc_netdev_mq()
+ *      -> register_netdev()
+ *
+ * iwm_sdio_remove()
+ *  -> iwm_if_free() (netdev.c)
+ *      -> unregister_netdev()
+ *      -> iwm_wdev_free() (cfg80211.c)
+ *          -> wiphy_unregister()
+ *          -> wiphy_free()
+ *
+ * iwm_sdio_isr() (called in process context from the SDIO core code)
+ *  -> queue_work(.., isr_worker)
+ *      -- [async] --> iwm_sdio_isr_worker()
+ *                      -> iwm_rx_handle()
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+
+#include "iwm.h"
+#include "debug.h"
+#include "bus.h"
+#include "sdio.h"
+
+static void iwm_sdio_isr_worker(struct work_struct *work)
+{
+	struct iwm_sdio_priv *hw;
+	struct iwm_priv *iwm;
+	struct iwm_rx_info *rx_info;
+	struct sk_buff *skb;
+	u8 *rx_buf;
+	unsigned long rx_size;
+
+	hw = container_of(work, struct iwm_sdio_priv, isr_worker);
+	iwm = hw_to_iwm(hw);
+
+	while (!skb_queue_empty(&iwm->rx_list)) {
+		skb = skb_dequeue(&iwm->rx_list);
+		rx_info = skb_to_rx_info(skb);
+		rx_size = rx_info->rx_size;
+		rx_buf = skb->data;
+
+		IWM_HEXDUMP(iwm, DBG, SDIO, "RX: ", rx_buf, rx_size);
+		if (iwm_rx_handle(iwm, rx_buf, rx_size) < 0)
+			IWM_WARN(iwm, "RX error\n");
+
+		kfree_skb(skb);
+	}
+}
+
+static void iwm_sdio_isr(struct sdio_func *func)
+{
+	struct iwm_priv *iwm;
+	struct iwm_sdio_priv *hw;
+	struct iwm_rx_info *rx_info;
+	struct sk_buff *skb;
+	unsigned long buf_size, read_size;
+	int ret;
+	u8 val;
+
+	hw = sdio_get_drvdata(func);
+	iwm = hw_to_iwm(hw);
+
+	buf_size = hw->blk_size;
+
+	/* We're checking the status */
+	val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret);
+	if (val == 0 || ret < 0) {
+		IWM_ERR(iwm, "Wrong INTR_STATUS\n");
+		return;
+	}
+
+	/* See if we have free buffers */
+	if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) {
+		IWM_ERR(iwm, "No buffer for more Rx frames\n");
+		return;
+	}
+
+	/* We first read the transaction size */
+	read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret);
+	read_size = read_size << 8;
+
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't read the xfer size\n");
+		return;
+	}
+
+	/* We need to clear the INT register */
+	sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't clear the INT register\n");
+		return;
+	}
+
+	while (buf_size < read_size)
+		buf_size <<= 1;
+
+	skb = dev_alloc_skb(buf_size);
+	if (!skb) {
+		IWM_ERR(iwm, "Couldn't alloc RX skb\n");
+		return;
+	}
+	rx_info = skb_to_rx_info(skb);
+	rx_info->rx_size = read_size;
+	rx_info->rx_buf_size = buf_size;
+
+	/* Now we can read the actual buffer */
+	ret = sdio_memcpy_fromio(func, skb_put(skb, read_size),
+				 IWM_SDIO_DATA_ADDR, read_size);
+
+	/* The skb is put on a driver's specific Rx SKB list */
+	skb_queue_tail(&iwm->rx_list, skb);
+
+	/* We can now schedule the actual worker */
+	queue_work(hw->isr_wq, &hw->isr_worker);
+}
+
+static void iwm_sdio_rx_free(struct iwm_sdio_priv *hw)
+{
+	struct iwm_priv *iwm = hw_to_iwm(hw);
+
+	flush_workqueue(hw->isr_wq);
+
+	skb_queue_purge(&iwm->rx_list);
+}
+
+/* Bus ops */
+static int if_sdio_enable(struct iwm_priv *iwm)
+{
+	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
+	int ret;
+
+	sdio_claim_host(hw->func);
+
+	ret = sdio_enable_func(hw->func);
+	if (ret) {
+		IWM_ERR(iwm, "Couldn't enable the device: is TOP driver "
+			"loaded and functional?\n");
+		goto release_host;
+	}
+
+	iwm_reset(iwm);
+
+	ret = sdio_claim_irq(hw->func, iwm_sdio_isr);
+	if (ret) {
+		IWM_ERR(iwm, "Failed to claim irq: %d\n", ret);
+		goto release_host;
+	}
+
+	sdio_writeb(hw->func, 1, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't enable INTR: %d\n", ret);
+		goto release_irq;
+	}
+
+	sdio_release_host(hw->func);
+
+	IWM_DBG_SDIO(iwm, INFO, "IWM SDIO enable\n");
+
+	return 0;
+
+ release_irq:
+	sdio_release_irq(hw->func);
+ release_host:
+	sdio_release_host(hw->func);
+
+	return ret;
+}
+
+static int if_sdio_disable(struct iwm_priv *iwm)
+{
+	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
+	int ret;
+
+	iwm_reset(iwm);
+
+	sdio_claim_host(hw->func);
+	sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
+	if (ret < 0)
+		IWM_WARN(iwm, "Couldn't disable INTR: %d\n", ret);
+
+	sdio_release_irq(hw->func);
+	sdio_disable_func(hw->func);
+	sdio_release_host(hw->func);
+
+	iwm_sdio_rx_free(hw);
+
+	IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n");
+
+	return 0;
+}
+
+static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
+{
+	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
+	int aligned_count = ALIGN(count, hw->blk_size);
+	int ret;
+
+	if ((unsigned long)buf & 0x3) {
+		IWM_ERR(iwm, "buf <%p> is not dword aligned\n", buf);
+		/* TODO: Is this a hardware limitation? use get_unligned */
+		return -EINVAL;
+	}
+
+	sdio_claim_host(hw->func);
+	ret = sdio_memcpy_toio(hw->func, IWM_SDIO_DATA_ADDR, buf,
+			       aligned_count);
+	sdio_release_host(hw->func);
+
+	return ret;
+}
+
+/* debugfs hooks */
+static int iwm_debugfs_sdio_open(struct inode *inode, struct file *filp)
+{
+	filp->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer,
+				     size_t count, loff_t *ppos)
+{
+	struct iwm_priv *iwm = filp->private_data;
+	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
+	char *buf;
+	u8 cccr;
+	int buf_len = 4096, ret;
+	size_t len = 0;
+
+	if (*ppos != 0)
+		return 0;
+	if (count < sizeof(buf))
+		return -ENOSPC;
+
+	buf = kzalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	sdio_claim_host(hw->func);
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_IOEx, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_IOEx\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_IOEx:  0x%x\n", cccr);
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_IORx, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_IORx\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_IORx:  0x%x\n", cccr);
+
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_IENx, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_IENx\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_IENx:  0x%x\n", cccr);
+
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_INTx, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_INTx\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_INTx:  0x%x\n", cccr);
+
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_ABORT, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_ABORTx\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_ABORT: 0x%x\n", cccr);
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_IF, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_IF\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_IF:    0x%x\n", cccr);
+
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_CAPS, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_CAPS\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_CAPS:  0x%x\n", cccr);
+
+	cccr =  sdio_f0_readb(hw->func, SDIO_CCCR_CIS, &ret);
+	if (ret) {
+		IWM_ERR(iwm, "Could not read SDIO_CCCR_CIS\n");
+		goto err;
+	}
+	len += snprintf(buf + len, buf_len - len, "CCCR_CIS:   0x%x\n", cccr);
+
+	ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
+err:
+	sdio_release_host(hw->func);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static const struct file_operations iwm_debugfs_sdio_fops = {
+	.owner =	THIS_MODULE,
+	.open =		iwm_debugfs_sdio_open,
+	.read =		iwm_debugfs_sdio_read,
+};
+
+static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
+{
+	int result;
+	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
+
+	hw->cccr_dentry = debugfs_create_file("cccr", 0200,
+					      parent_dir, iwm,
+					      &iwm_debugfs_sdio_fops);
+	result = PTR_ERR(hw->cccr_dentry);
+	if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) {
+		IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void if_sdio_debugfs_exit(struct iwm_priv *iwm)
+{
+	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
+
+	debugfs_remove(hw->cccr_dentry);
+}
+
+static struct iwm_if_ops if_sdio_ops = {
+	.enable = if_sdio_enable,
+	.disable = if_sdio_disable,
+	.send_chunk = if_sdio_send_chunk,
+	.debugfs_init = if_sdio_debugfs_init,
+	.debugfs_exit = if_sdio_debugfs_exit,
+	.umac_name = "/*(DEBLOBBED)*/",
+	.calib_lmac_name = "/*(DEBLOBBED)*/",
+	.lmac_name = "/*(DEBLOBBED)*/",
+};
+
+static int iwm_sdio_probe(struct sdio_func *func,
+			  const struct sdio_device_id *id)
+{
+	struct iwm_priv *iwm;
+	struct iwm_sdio_priv *hw;
+	struct device *dev = &func->dev;
+	int ret;
+
+	/* check if TOP has already initialized the card */
+	sdio_claim_host(func);
+	ret = sdio_enable_func(func);
+	if (ret) {
+		dev_err(dev, "wait for TOP to enable the device\n");
+		sdio_release_host(func);
+		return ret;
+	}
+
+	ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE);
+
+	sdio_disable_func(func);
+	sdio_release_host(func);
+
+	if (ret < 0) {
+		dev_err(dev, "Failed to set block size: %d\n", ret);
+		return ret;
+	}
+
+	iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops);
+	if (IS_ERR(iwm)) {
+		dev_err(dev, "allocate SDIO interface failed\n");
+		return PTR_ERR(iwm);
+	}
+
+	hw = iwm_private(iwm);
+	hw->iwm = iwm;
+
+	ret = iwm_debugfs_init(iwm);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Debugfs registration failed\n");
+		goto if_free;
+	}
+
+	sdio_set_drvdata(func, hw);
+
+	hw->func = func;
+	hw->blk_size = IWM_SDIO_BLK_SIZE;
+
+	hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio");
+	if (!hw->isr_wq) {
+		ret = -ENOMEM;
+		goto debugfs_exit;
+	}
+
+	INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker);
+
+	ret = iwm_if_add(iwm);
+	if (ret) {
+		dev_err(dev, "add SDIO interface failed\n");
+		goto destroy_wq;
+	}
+
+	dev_info(dev, "IWM SDIO probe\n");
+
+	return 0;
+
+ destroy_wq:
+	destroy_workqueue(hw->isr_wq);
+ debugfs_exit:
+	iwm_debugfs_exit(iwm);
+ if_free:
+	iwm_if_free(iwm);
+	return ret;
+}
+
+static void iwm_sdio_remove(struct sdio_func *func)
+{
+	struct iwm_sdio_priv *hw = sdio_get_drvdata(func);
+	struct iwm_priv *iwm = hw_to_iwm(hw);
+	struct device *dev = &func->dev;
+
+	iwm_if_remove(iwm);
+	destroy_workqueue(hw->isr_wq);
+	iwm_debugfs_exit(iwm);
+	iwm_if_free(iwm);
+
+	sdio_set_drvdata(func, NULL);
+
+	dev_info(dev, "IWM SDIO remove\n");
+
+	return;
+}
+
+static const struct sdio_device_id iwm_sdio_ids[] = {
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, SDIO_DEVICE_ID_IWM) },
+	{ /* end: all zeroes */	},
+};
+MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids);
+
+static struct sdio_driver iwm_sdio_driver = {
+	.name		= "iwm_sdio",
+	.id_table	= iwm_sdio_ids,
+	.probe		= iwm_sdio_probe,
+	.remove		= iwm_sdio_remove,
+};
+
+static int __init iwm_sdio_init_module(void)
+{
+	int ret;
+
+	ret = sdio_register_driver(&iwm_sdio_driver);
+
+	return ret;
+}
+
+static void __exit iwm_sdio_exit_module(void)
+{
+	sdio_unregister_driver(&iwm_sdio_driver);
+}
+
+module_init(iwm_sdio_init_module);
+module_exit(iwm_sdio_exit_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(IWM_COPYRIGHT " " IWM_AUTHOR);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/sdio.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/sdio.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/sdio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/sdio.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_SDIO_H__
+#define __IWM_SDIO_H__
+
+#define SDIO_VENDOR_ID_INTEL 0x89
+#define SDIO_DEVICE_ID_IWM   0x1403
+
+#define IWM_SDIO_DATA_ADDR           0x0
+#define IWM_SDIO_INTR_ENABLE_ADDR    0x14
+#define IWM_SDIO_INTR_STATUS_ADDR    0x13
+#define IWM_SDIO_INTR_CLEAR_ADDR     0x13
+#define IWM_SDIO_INTR_GET_SIZE_ADDR  0x2C
+
+#define IWM_SDIO_BLK_SIZE       256
+
+#define iwm_to_if_sdio(i) (struct iwm_sdio_priv *)(iwm->private)
+
+struct iwm_sdio_priv {
+	struct sdio_func *func;
+	struct iwm_priv *iwm;
+
+	struct workqueue_struct *isr_wq;
+	struct work_struct isr_worker;
+
+	struct dentry *cccr_dentry;
+
+	unsigned int blk_size;
+};
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/tx.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/tx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/tx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,492 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+/*
+ * iwm Tx theory of operation:
+ *
+ * 1) We receive a 802.3 frame from the stack
+ * 2) We convert it to a 802.11 frame [iwm_xmit_frame]
+ * 3) We queue it to its corresponding tx queue [iwm_xmit_frame]
+ * 4) We schedule the tx worker. There is one worker per tx
+ *    queue. [iwm_xmit_frame]
+ * 5) The tx worker is scheduled
+ * 6) We go through every queued skb on the tx queue, and for each
+ *    and every one of them: [iwm_tx_worker]
+ *    a) We check if we have enough Tx credits (see below for a Tx
+ *       credits description) for the frame length. [iwm_tx_worker]
+ *    b) If we do, we aggregate the Tx frame into a UDMA one, by
+ *       concatenating one REPLY_TX command per Tx frame. [iwm_tx_worker]
+ *    c) When we run out of credits, or when we reach the maximum
+ *       concatenation size, we actually send the concatenated UDMA
+ *       frame. [iwm_tx_worker]
+ *
+ * When we run out of Tx credits, the skbs are filling the tx queue,
+ * and eventually we will stop the netdev queue. [iwm_tx_worker]
+ * The tx queue is emptied as we're getting new tx credits, by
+ * scheduling the tx_worker. [iwm_tx_credit_inc]
+ * The netdev queue is started again when we have enough tx credits,
+ * and when our tx queue has some reasonable amout of space available
+ * (i.e. half of the max size). [iwm_tx_worker]
+ */
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ieee80211.h>
+
+#include "iwm.h"
+#include "debug.h"
+#include "commands.h"
+#include "hal.h"
+#include "umac.h"
+#include "bus.h"
+
+#define IWM_UMAC_PAGE_ALLOC_WRAP 0xffff
+
+#define BYTES_TO_PAGES(n)	 (1 + ((n) >> ilog2(IWM_UMAC_PAGE_SIZE)) - \
+				 (((n) & (IWM_UMAC_PAGE_SIZE - 1)) == 0))
+
+#define pool_id_to_queue(id)	 ((id < IWM_TX_CMD_QUEUE) ? id : id - 1)
+#define queue_to_pool_id(q)	 ((q < IWM_TX_CMD_QUEUE) ? q : q + 1)
+
+/* require to hold tx_credit lock */
+static int iwm_tx_credit_get(struct iwm_tx_credit *tx_credit, int id)
+{
+	struct pool_entry *pool = &tx_credit->pools[id];
+	struct spool_entry *spool = &tx_credit->spools[pool->sid];
+	int spool_pages;
+
+	/* number of pages can be taken from spool by this pool */
+	spool_pages = spool->max_pages - spool->alloc_pages +
+		      max(pool->min_pages - pool->alloc_pages, 0);
+
+	return min(pool->max_pages - pool->alloc_pages, spool_pages);
+}
+
+static bool iwm_tx_credit_ok(struct iwm_priv *iwm, int id, int nb)
+{
+	u32 npages = BYTES_TO_PAGES(nb);
+
+	if (npages <= iwm_tx_credit_get(&iwm->tx_credit, id))
+		return 1;
+
+	set_bit(id, &iwm->tx_credit.full_pools_map);
+
+	IWM_DBG_TX(iwm, DBG, "LINK: stop txq[%d], available credit: %d\n",
+		   pool_id_to_queue(id),
+		   iwm_tx_credit_get(&iwm->tx_credit, id));
+
+	return 0;
+}
+
+void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages)
+{
+	struct pool_entry *pool;
+	struct spool_entry *spool;
+	int freed_pages;
+	int queue;
+
+	BUG_ON(id >= IWM_MACS_OUT_GROUPS);
+
+	pool = &iwm->tx_credit.pools[id];
+	spool = &iwm->tx_credit.spools[pool->sid];
+
+	freed_pages = total_freed_pages - pool->total_freed_pages;
+	IWM_DBG_TX(iwm, DBG, "Free %d pages for pool[%d]\n", freed_pages, id);
+
+	if (!freed_pages) {
+		IWM_DBG_TX(iwm, DBG, "No pages are freed by UMAC\n");
+		return;
+	} else if (freed_pages < 0)
+		freed_pages += IWM_UMAC_PAGE_ALLOC_WRAP + 1;
+
+	if (pool->alloc_pages > pool->min_pages) {
+		int spool_pages = pool->alloc_pages - pool->min_pages;
+		spool_pages = min(spool_pages, freed_pages);
+		spool->alloc_pages -= spool_pages;
+	}
+
+	pool->alloc_pages -= freed_pages;
+	pool->total_freed_pages = total_freed_pages;
+
+	IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
+		   "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
+		   pool->total_freed_pages, pool->sid, spool->alloc_pages);
+
+	if (test_bit(id, &iwm->tx_credit.full_pools_map) &&
+	    (pool->alloc_pages < pool->max_pages / 2)) {
+		clear_bit(id, &iwm->tx_credit.full_pools_map);
+
+		queue = pool_id_to_queue(id);
+
+		IWM_DBG_TX(iwm, DBG, "LINK: start txq[%d], available "
+			   "credit: %d\n", queue,
+			   iwm_tx_credit_get(&iwm->tx_credit, id));
+		queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
+	}
+}
+
+static void iwm_tx_credit_dec(struct iwm_priv *iwm, int id, int alloc_pages)
+{
+	struct pool_entry *pool;
+	struct spool_entry *spool;
+	int spool_pages;
+
+	IWM_DBG_TX(iwm, DBG, "Allocate %d pages for pool[%d]\n",
+		   alloc_pages, id);
+
+	BUG_ON(id >= IWM_MACS_OUT_GROUPS);
+
+	pool = &iwm->tx_credit.pools[id];
+	spool = &iwm->tx_credit.spools[pool->sid];
+
+	spool_pages = pool->alloc_pages + alloc_pages - pool->min_pages;
+
+	if (pool->alloc_pages >= pool->min_pages)
+		spool->alloc_pages += alloc_pages;
+	else if (spool_pages > 0)
+		spool->alloc_pages += spool_pages;
+
+	pool->alloc_pages += alloc_pages;
+
+	IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
+		   "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
+		   pool->total_freed_pages, pool->sid, spool->alloc_pages);
+}
+
+int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb)
+{
+	u32 npages = BYTES_TO_PAGES(nb);
+	int ret = 0;
+
+	spin_lock(&iwm->tx_credit.lock);
+
+	if (!iwm_tx_credit_ok(iwm, id, nb)) {
+		IWM_DBG_TX(iwm, DBG, "No credit avaliable for pool[%d]\n", id);
+		ret = -ENOSPC;
+		goto out;
+	}
+
+	iwm_tx_credit_dec(iwm, id, npages);
+
+ out:
+	spin_unlock(&iwm->tx_credit.lock);
+	return ret;
+}
+
+/*
+ * Since we're on an SDIO or USB bus, we are not sharing memory
+ * for storing to be transmitted frames. The host needs to push
+ * them upstream. As a consequence there needs to be a way for
+ * the target to let us know if it can actually take more TX frames
+ * or not. This is what Tx credits are for.
+ *
+ * For each Tx HW queue, we have a Tx pool, and then we have one
+ * unique super pool (spool), which is actually a global pool of
+ * all the UMAC pages.
+ * For each Tx pool we have a min_pages, a max_pages fields, and a
+ * alloc_pages fields. The alloc_pages tracks the number of pages
+ * currently allocated from the tx pool.
+ * Here are the rules to check if given a tx frame we have enough
+ * tx credits for it:
+ * 1) We translate the frame length into a number of UMAC pages.
+ *    Let's call them n_pages.
+ * 2) For the corresponding tx pool, we check if n_pages +
+ *    pool->alloc_pages is higher than pool->min_pages. min_pages
+ *    represent a set of pre-allocated pages on the tx pool. If
+ *    that's the case, then we need to allocate those pages from
+ *    the spool. We can do so until we reach spool->max_pages.
+ * 3) Each tx pool is not allowed to allocate more than pool->max_pages
+ *    from the spool, so once we're over min_pages, we can allocate
+ *    pages from the spool, but not more than max_pages.
+ *
+ * When the tx code path needs to send a tx frame, it checks first
+ * if it has enough tx credits, following those rules. [iwm_tx_credit_get]
+ * If it does, it then updates the pool and spool counters and
+ * then send the frame. [iwm_tx_credit_alloc and iwm_tx_credit_dec]
+ * On the other side, when the UMAC is done transmitting frames, it
+ * will send a credit update notification to the host. This is when
+ * the pool and spool counters gets to be decreased. [iwm_tx_credit_inc,
+ * called from rx.c:iwm_ntf_tx_credit_update]
+ *
+ */
+void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
+			      struct iwm_umac_notif_alive *alive)
+{
+	int i, sid, pool_pages;
+
+	spin_lock(&iwm->tx_credit.lock);
+
+	iwm->tx_credit.pool_nr = le16_to_cpu(alive->page_grp_count);
+	iwm->tx_credit.full_pools_map = 0;
+	memset(&iwm->tx_credit.spools[0], 0, sizeof(struct spool_entry));
+
+	IWM_DBG_TX(iwm, DBG, "Pools number is %d\n", iwm->tx_credit.pool_nr);
+
+	for (i = 0; i < iwm->tx_credit.pool_nr; i++) {
+		__le32 page_grp_state = alive->page_grp_state[i];
+
+		iwm->tx_credit.pools[i].id = GET_VAL32(page_grp_state,
+				UMAC_ALIVE_PAGE_STS_GRP_NUM);
+		iwm->tx_credit.pools[i].sid = GET_VAL32(page_grp_state,
+				UMAC_ALIVE_PAGE_STS_SGRP_NUM);
+		iwm->tx_credit.pools[i].min_pages = GET_VAL32(page_grp_state,
+				UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE);
+		iwm->tx_credit.pools[i].max_pages = GET_VAL32(page_grp_state,
+				UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE);
+		iwm->tx_credit.pools[i].alloc_pages = 0;
+		iwm->tx_credit.pools[i].total_freed_pages = 0;
+
+		sid = iwm->tx_credit.pools[i].sid;
+		pool_pages = iwm->tx_credit.pools[i].min_pages;
+
+		if (iwm->tx_credit.spools[sid].max_pages == 0) {
+			iwm->tx_credit.spools[sid].id = sid;
+			iwm->tx_credit.spools[sid].max_pages =
+				GET_VAL32(page_grp_state,
+					  UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE);
+			iwm->tx_credit.spools[sid].alloc_pages = 0;
+		}
+
+		iwm->tx_credit.spools[sid].alloc_pages += pool_pages;
+
+		IWM_DBG_TX(iwm, DBG, "Pool idx: %d, id: %d, sid: %d, capacity "
+			   "min: %d, max: %d, pool alloc: %d, total_free: %d, "
+			   "super poll alloc: %d\n",
+			   i, iwm->tx_credit.pools[i].id,
+			   iwm->tx_credit.pools[i].sid,
+			   iwm->tx_credit.pools[i].min_pages,
+			   iwm->tx_credit.pools[i].max_pages,
+			   iwm->tx_credit.pools[i].alloc_pages,
+			   iwm->tx_credit.pools[i].total_freed_pages,
+			   iwm->tx_credit.spools[sid].alloc_pages);
+	}
+
+	spin_unlock(&iwm->tx_credit.lock);
+}
+
+#define IWM_UDMA_HDR_LEN	sizeof(struct iwm_umac_wifi_out_hdr)
+
+static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
+			       int pool_id, u8 *buf)
+{
+	struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf;
+	struct iwm_udma_wifi_cmd udma_cmd;
+	struct iwm_umac_cmd umac_cmd;
+	struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
+
+	udma_cmd.count = cpu_to_le16(skb->len +
+				     sizeof(struct iwm_umac_fw_cmd_hdr));
+	/* set EOP to 0 here. iwm_udma_wifi_hdr_set_eop() will be
+	 * called later to set EOP for the last packet. */
+	udma_cmd.eop = 0;
+	udma_cmd.credit_group = pool_id;
+	udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
+	udma_cmd.lmac_offset = 0;
+
+	umac_cmd.id = REPLY_TX;
+	umac_cmd.count = cpu_to_le16(skb->len);
+	umac_cmd.color = tx_info->color;
+	umac_cmd.resp = 0;
+	umac_cmd.seq_num = cpu_to_le16(iwm_alloc_wifi_cmd_seq(iwm));
+
+	iwm_build_udma_wifi_hdr(iwm, &hdr->hw_hdr, &udma_cmd);
+	iwm_build_umac_hdr(iwm, &hdr->sw_hdr, &umac_cmd);
+
+	memcpy(buf + sizeof(*hdr), skb->data, skb->len);
+
+	return 0;
+}
+
+static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
+				      struct iwm_tx_queue *txq)
+{
+	int ret;
+
+	if (!txq->concat_count)
+		return 0;
+
+	IWM_DBG_TX(iwm, DBG, "Send concatenated Tx: queue %d, %d bytes\n",
+		   txq->id, txq->concat_count);
+
+	/* mark EOP for the last packet */
+	iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1);
+
+	ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count);
+
+	txq->concat_count = 0;
+	txq->concat_ptr = txq->concat_buf;
+
+	return ret;
+}
+
+#define CONFIG_IWM_TX_CONCATENATED 1
+
+void iwm_tx_worker(struct work_struct *work)
+{
+	struct iwm_priv *iwm;
+	struct iwm_tx_info *tx_info = NULL;
+	struct sk_buff *skb;
+	int cmdlen, ret;
+	struct iwm_tx_queue *txq;
+	int pool_id;
+
+	txq = container_of(work, struct iwm_tx_queue, worker);
+	iwm = container_of(txq, struct iwm_priv, txq[txq->id]);
+
+	pool_id = queue_to_pool_id(txq->id);
+
+	while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
+	       !skb_queue_empty(&txq->queue)) {
+
+		skb = skb_dequeue(&txq->queue);
+		tx_info = skb_to_tx_info(skb);
+		cmdlen = IWM_UDMA_HDR_LEN + skb->len;
+
+		IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: "
+			   "%d, color: %d\n", txq->id, skb, tx_info->sta,
+			   tx_info->color);
+
+#if !CONFIG_IWM_TX_CONCATENATED
+		/* temporarily keep this to comparing the performance */
+		ret = iwm_send_packet(iwm, skb, pool_id);
+#else
+
+		if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE)
+			iwm_tx_send_concat_packets(iwm, txq);
+
+		ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen);
+		if (ret) {
+			IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue "
+				   "%d, Tx worker stopped\n", txq->id);
+			skb_queue_head(&txq->queue, skb);
+			break;
+		}
+
+		txq->concat_ptr = txq->concat_buf + txq->concat_count;
+		iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr);
+		txq->concat_count += ALIGN(cmdlen, 16);
+#endif
+		kfree_skb(skb);
+	}
+
+	iwm_tx_send_concat_packets(iwm, txq);
+
+	if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) &&
+	    !test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
+	    (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) {
+		IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id);
+		netif_wake_subqueue(iwm_to_ndev(iwm), txq->id);
+	}
+}
+
+int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(netdev);
+	struct net_device *ndev = iwm_to_ndev(iwm);
+	struct wireless_dev *wdev = iwm_to_wdev(iwm);
+	u8 *dst_addr;
+	struct iwm_tx_info *tx_info;
+	struct iwm_tx_queue *txq;
+	struct iwm_sta_info *sta_info;
+	u8 sta_id;
+	u16 queue;
+	int ret;
+
+	if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
+		IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: "
+			   "not associated\n");
+		netif_tx_stop_all_queues(netdev);
+		goto drop;
+	}
+
+	queue = skb_get_queue_mapping(skb);
+	BUG_ON(queue >= IWM_TX_DATA_QUEUES); /* no iPAN yet */
+
+	txq = &iwm->txq[queue];
+
+	/* No free space for Tx, tx_worker is too slow */
+	if (skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) {
+		IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue);
+		netif_stop_subqueue(netdev, queue);
+		return NETDEV_TX_BUSY;
+	}
+
+	ret = ieee80211_data_from_8023(skb, netdev->dev_addr, wdev->iftype,
+				       iwm->bssid, 0);
+	if (ret) {
+		IWM_ERR(iwm, "build wifi header failed\n");
+		goto drop;
+	}
+
+	dst_addr = ((struct ieee80211_hdr *)(skb->data))->addr1;
+
+	for (sta_id = 0; sta_id < IWM_STA_TABLE_NUM; sta_id++) {
+		sta_info = &iwm->sta_table[sta_id];
+		if (sta_info->valid &&
+		    !memcmp(dst_addr, sta_info->addr, ETH_ALEN))
+			break;
+	}
+
+	if (sta_id == IWM_STA_TABLE_NUM) {
+		IWM_ERR(iwm, "STA %pM not found in sta_table, Tx ignored\n",
+			dst_addr);
+		goto drop;
+	}
+
+	tx_info = skb_to_tx_info(skb);
+	tx_info->sta = sta_id;
+	tx_info->color = sta_info->color;
+	/* UMAC uses TID 8 (vs. 0) for non QoS packets */
+	if (sta_info->qos)
+		tx_info->tid = skb->priority;
+	else
+		tx_info->tid = IWM_UMAC_MGMT_TID;
+
+	skb_queue_tail(&iwm->txq[queue].queue, skb);
+
+	queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
+
+	ndev->stats.tx_packets++;
+	ndev->stats.tx_bytes += skb->len;
+	return NETDEV_TX_OK;
+
+ drop:
+	ndev->stats.tx_dropped++;
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/umac.h linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/umac.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/umac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/umac.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,744 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ *
+ * Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ */
+
+#ifndef __IWM_UMAC_H__
+#define __IWM_UMAC_H__
+
+struct iwm_udma_in_hdr {
+	__le32 cmd;
+	__le32 size;
+} __attribute__ ((packed));
+
+struct iwm_udma_out_nonwifi_hdr {
+	__le32 cmd;
+	__le32 addr;
+	__le32 op1_sz;
+	__le32 op2;
+} __attribute__ ((packed));
+
+struct iwm_udma_out_wifi_hdr {
+	__le32 cmd;
+	__le32 meta_data;
+} __attribute__ ((packed));
+
+/* Sequence numbering */
+#define UMAC_WIFI_SEQ_NUM_BASE		1
+#define UMAC_WIFI_SEQ_NUM_MAX		0x4000
+#define UMAC_NONWIFI_SEQ_NUM_BASE	1
+#define UMAC_NONWIFI_SEQ_NUM_MAX	0x10
+
+/* MAC address address */
+#define WICO_MAC_ADDRESS_ADDR               0x604008F8
+
+/* RA / TID */
+#define UMAC_HDI_ACT_TBL_IDX_TID_POS                  0
+#define UMAC_HDI_ACT_TBL_IDX_TID_SEED                 0xF
+
+#define UMAC_HDI_ACT_TBL_IDX_RA_POS                   4
+#define UMAC_HDI_ACT_TBL_IDX_RA_SEED                  0xF
+
+#define UMAC_HDI_ACT_TBL_IDX_RA_UMAC                  0xF
+#define UMAC_HDI_ACT_TBL_IDX_TID_UMAC                 0x9
+#define UMAC_HDI_ACT_TBL_IDX_TID_LMAC                 0xA
+
+#define UMAC_HDI_ACT_TBL_IDX_HOST_CMD \
+	((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
+	 (UMAC_HDI_ACT_TBL_IDX_TID_UMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
+#define UMAC_HDI_ACT_TBL_IDX_UMAC_CMD \
+	((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
+	(UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
+
+/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */
+#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS		0
+#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED	0xF
+
+/* iwm_umac_notif_alive.page_grp_state Super group number -- bits [7:4] */
+#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_POS	4
+#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_SEED	0xF
+
+/* iwm_umac_notif_alive.page_grp_state Group min size -- bits [15:8] */
+#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_POS	8
+#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_SEED	0xFF
+
+/* iwm_umac_notif_alive.page_grp_state Group max size -- bits [23:16] */
+#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_POS	16
+#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_SEED	0xFF
+
+/* iwm_umac_notif_alive.page_grp_state Super group max size -- bits [31:24] */
+#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_POS	24
+#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_SEED	0xFF
+
+/* Barkers */
+#define UMAC_REBOOT_BARKER		0xdeadbeef
+#define UMAC_ACK_BARKER			0xfeedbabe
+#define UMAC_PAD_TERMINAL		0xadadadad
+
+/* UMAC JMP address */
+#define UMAC_MU_FW_INST_DATA_12_ADDR    0xBF0000
+
+/* iwm_umac_hdi_out_hdr.cmd OP code -- bits [3:0] */
+#define UMAC_HDI_OUT_CMD_OPCODE_POS	0
+#define UMAC_HDI_OUT_CMD_OPCODE_SEED	0xF
+
+/* iwm_umac_hdi_out_hdr.cmd End-Of-Transfer -- bits [10:10] */
+#define UMAC_HDI_OUT_CMD_EOT_POS	10
+#define UMAC_HDI_OUT_CMD_EOT_SEED	0x1
+
+/* iwm_umac_hdi_out_hdr.cmd UTFD only usage -- bits [11:11] */
+#define UMAC_HDI_OUT_CMD_UTFD_ONLY_POS	11
+#define UMAC_HDI_OUT_CMD_UTFD_ONLY_SEED	0x1
+
+/* iwm_umac_hdi_out_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
+#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_POS   12
+#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_SEED  0xF
+
+/* iwm_umac_hdi_out_hdr.cmd Signature -- bits [31:16] */
+#define UMAC_HDI_OUT_CMD_SIGNATURE_POS	16
+#define UMAC_HDI_OUT_CMD_SIGNATURE_SEED	0xFFFF
+
+/* iwm_umac_hdi_out_hdr.meta_data Byte count -- bits [11:0] */
+#define UMAC_HDI_OUT_BYTE_COUNT_POS	0
+#define UMAC_HDI_OUT_BYTE_COUNT_SEED	0xFFF
+
+/* iwm_umac_hdi_out_hdr.meta_data Credit group -- bits [15:12] */
+#define UMAC_HDI_OUT_CREDIT_GRP_POS	12
+#define UMAC_HDI_OUT_CREDIT_GRP_SEED	0xF
+
+/* iwm_umac_hdi_out_hdr.meta_data RA/TID -- bits [23:16] */
+#define UMAC_HDI_OUT_RATID_POS		16
+#define UMAC_HDI_OUT_RATID_SEED		0xFF
+
+/* iwm_umac_hdi_out_hdr.meta_data LMAC offset -- bits [31:24] */
+#define UMAC_HDI_OUT_LMAC_OFFSET_POS	24
+#define UMAC_HDI_OUT_LMAC_OFFSET_SEED	0xFF
+
+/* Signature */
+#define UMAC_HDI_OUT_SIGNATURE		0xCBBC
+
+/* buffer alignment */
+#define UMAC_HDI_BUF_ALIGN_MSK		0xF
+
+/*  iwm_umac_hdi_in_hdr.cmd OP code -- bits [3:0] */
+#define UMAC_HDI_IN_CMD_OPCODE_POS                0
+#define UMAC_HDI_IN_CMD_OPCODE_SEED               0xF
+
+/*  iwm_umac_hdi_in_hdr.cmd Non-WiFi API response -- bits [6:4] */
+#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_POS         4
+#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_SEED        0x7
+
+/* iwm_umac_hdi_in_hdr.cmd WiFi API source -- bits [5:4] */
+#define UMAC_HDI_IN_CMD_SOURCE_POS                4
+#define UMAC_HDI_IN_CMD_SOURCE_SEED               0x3
+
+/* iwm_umac_hdi_in_hdr.cmd WiFi API EOT -- bits [6:6] */
+#define UMAC_HDI_IN_CMD_EOT_POS                   6
+#define UMAC_HDI_IN_CMD_EOT_SEED                  0x1
+
+/* iwm_umac_hdi_in_hdr.cmd timestamp present -- bits [7:7] */
+#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_POS    7
+#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_SEED   0x1
+
+/* iwm_umac_hdi_in_hdr.cmd WiFi Non-last AMSDU -- bits [8:8] */
+#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_POS        8
+#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_SEED       0x1
+
+/* iwm_umac_hdi_in_hdr.cmd WiFi HW sequence number -- bits [31:9] */
+#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_POS            9
+#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_SEED           0x7FFFFF
+
+/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
+#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_POS   12
+#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_SEED  0xF
+
+/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW signature -- bits [16:31] */
+#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_POS       16
+#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_SEED      0xFFFF
+
+/* Fixed Non-WiFi signature */
+#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG           0xCBBC
+
+/* IN NTFY op-codes */
+#define UMAC_NOTIFY_OPCODE_ALIVE		0xA1
+#define UMAC_NOTIFY_OPCODE_INIT_COMPLETE	0xA2
+#define UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS	0xA3
+#define UMAC_NOTIFY_OPCODE_ERROR		0xA4
+#define UMAC_NOTIFY_OPCODE_DEBUG		0xA5
+#define UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER	0xB0
+#define UMAC_NOTIFY_OPCODE_STATS		0xB1
+#define UMAC_NOTIFY_OPCODE_PAGE_DEALLOC		0xB3
+#define UMAC_NOTIFY_OPCODE_RX_TICKET		0xB4
+#define UMAC_NOTIFY_OPCODE_MAX		        (UMAC_NOTIFY_OPCODE_RX_TICKET -\
+						UMAC_NOTIFY_OPCODE_ALIVE + 1)
+#define UMAC_NOTIFY_OPCODE_FIRST		(UMAC_NOTIFY_OPCODE_ALIVE)
+
+/* HDI OUT OP CODE */
+#define UMAC_HDI_OUT_OPCODE_PING		0x0
+#define UMAC_HDI_OUT_OPCODE_READ		0x1
+#define UMAC_HDI_OUT_OPCODE_WRITE		0x2
+#define UMAC_HDI_OUT_OPCODE_JUMP		0x3
+#define UMAC_HDI_OUT_OPCODE_REBOOT		0x4
+#define UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT	0x5
+#define UMAC_HDI_OUT_OPCODE_READ_PERSISTENT	0x6
+#define UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE	0x7
+/* #define UMAC_HDI_OUT_OPCODE_RESERVED		0x8..0xA */
+#define UMAC_HDI_OUT_OPCODE_WRITE_AUX_REG	0xB
+#define UMAC_HDI_OUT_OPCODE_WIFI		0xF
+
+/* HDI IN OP CODE -- Non WiFi*/
+#define UMAC_HDI_IN_OPCODE_PING			0x0
+#define UMAC_HDI_IN_OPCODE_READ			0x1
+#define UMAC_HDI_IN_OPCODE_WRITE		0x2
+#define UMAC_HDI_IN_OPCODE_WRITE_PERSISTENT	0x5
+#define UMAC_HDI_IN_OPCODE_READ_PERSISTENT	0x6
+#define UMAC_HDI_IN_OPCODE_READ_MODIFY_WRITE	0x7
+#define UMAC_HDI_IN_OPCODE_EP_MGMT		0x8
+#define UMAC_HDI_IN_OPCODE_CREDIT_CHANGE	0x9
+#define UMAC_HDI_IN_OPCODE_CTRL_DATABASE	0xA
+#define UMAC_HDI_IN_OPCODE_WRITE_AUX_REG	0xB
+#define UMAC_HDI_IN_OPCODE_NONWIFI_MAX \
+		(UMAC_HDI_IN_OPCODE_WRITE_AUX_REG + 1)
+#define UMAC_HDI_IN_OPCODE_WIFI			0xF
+
+/* HDI IN SOURCE */
+#define UMAC_HDI_IN_SOURCE_FHRX			0x0
+#define UMAC_HDI_IN_SOURCE_UDMA			0x1
+#define UMAC_HDI_IN_SOURCE_FW			0x2
+#define UMAC_HDI_IN_SOURCE_RESERVED		0x3
+
+/* OUT CMD op-codes */
+#define UMAC_CMD_OPCODE_ECHO                    0x01
+#define UMAC_CMD_OPCODE_HALT                    0x02
+#define UMAC_CMD_OPCODE_RESET                   0x03
+#define UMAC_CMD_OPCODE_BULK_EP_INACT_TIMEOUT   0x09
+#define UMAC_CMD_OPCODE_URB_CANCEL_ACK          0x0A
+#define UMAC_CMD_OPCODE_DCACHE_FLUSH            0x0B
+#define UMAC_CMD_OPCODE_EEPROM_PROXY            0x0C
+#define UMAC_CMD_OPCODE_TX_ECHO                 0x0D
+#define UMAC_CMD_OPCODE_DBG_MON                 0x0E
+#define UMAC_CMD_OPCODE_INTERNAL_TX             0x0F
+#define UMAC_CMD_OPCODE_SET_PARAM_FIX           0x10
+#define UMAC_CMD_OPCODE_SET_PARAM_VAR           0x11
+#define UMAC_CMD_OPCODE_GET_PARAM               0x12
+#define UMAC_CMD_OPCODE_DBG_EVENT_WRAPPER       0x13
+#define UMAC_CMD_OPCODE_TARGET                  0x14
+#define UMAC_CMD_OPCODE_STATISTIC_REQUEST       0x15
+#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST	0x16
+#define UMAC_CMD_OPCODE_SET_PARAM_LIST		0x17
+#define UMAC_CMD_OPCODE_GET_PARAM_LIST		0x18
+#define UMAC_CMD_OPCODE_BASE_WRAPPER            0xFA
+#define UMAC_CMD_OPCODE_LMAC_WRAPPER            0xFB
+#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER         0xFC
+#define UMAC_CMD_OPCODE_WIFI_IF_WRAPPER         0xFD
+#define UMAC_CMD_OPCODE_WIFI_WRAPPER            0xFE
+#define UMAC_CMD_OPCODE_WIFI_PASS_THROUGH       0xFF
+
+/* UMAC WiFi interface op-codes */
+#define UMAC_WIFI_IF_CMD_SET_PROFILE                     0x11
+#define UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE              0x12
+#define UMAC_WIFI_IF_CMD_SET_EXCLUDE_LIST                0x13
+#define UMAC_WIFI_IF_CMD_SCAN_REQUEST                    0x14
+#define UMAC_WIFI_IF_CMD_SCAN_CONFIG                     0x15
+#define UMAC_WIFI_IF_CMD_ADD_WEP40_KEY                   0x16
+#define UMAC_WIFI_IF_CMD_ADD_WEP104_KEY                  0x17
+#define UMAC_WIFI_IF_CMD_ADD_TKIP_KEY                    0x18
+#define UMAC_WIFI_IF_CMD_ADD_CCMP_KEY                    0x19
+#define UMAC_WIFI_IF_CMD_REMOVE_KEY                      0x1A
+#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID                0x1B
+#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE            0x1C
+#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS          0x1E
+#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER                  0x20
+
+/* UMAC WiFi interface ports */
+#define UMAC_WIFI_IF_FLG_PORT_DEF                        0x00
+#define UMAC_WIFI_IF_FLG_PORT_PAN                        0x01
+#define UMAC_WIFI_IF_FLG_PORT_PAN_INVALID                WIFI_IF_FLG_PORT_DEF
+
+/* UMAC WiFi interface actions */
+#define UMAC_WIFI_IF_FLG_ACT_GET                         0x10
+#define UMAC_WIFI_IF_FLG_ACT_SET                         0x20
+
+/* iwm_umac_fw_cmd_hdr.meta_data byte count -- bits [11:0] */
+#define UMAC_FW_CMD_BYTE_COUNT_POS            0
+#define UMAC_FW_CMD_BYTE_COUNT_SEED           0xFFF
+
+/* iwm_umac_fw_cmd_hdr.meta_data status -- bits [15:12] */
+#define UMAC_FW_CMD_STATUS_POS                12
+#define UMAC_FW_CMD_STATUS_SEED               0xF
+
+/* iwm_umac_fw_cmd_hdr.meta_data full TX command by Driver -- bits [16:16] */
+#define UMAC_FW_CMD_TX_DRV_FULL_CMD_POS       16
+#define UMAC_FW_CMD_TX_DRV_FULL_CMD_SEED      0x1
+
+/* iwm_umac_fw_cmd_hdr.meta_data TX command by FW -- bits [17:17] */
+#define UMAC_FW_CMD_TX_FW_CMD_POS             17
+#define UMAC_FW_CMD_TX_FW_CMD_SEED            0x1
+
+/* iwm_umac_fw_cmd_hdr.meta_data TX plaintext mode -- bits [18:18] */
+#define UMAC_FW_CMD_TX_PLAINTEXT_POS          18
+#define UMAC_FW_CMD_TX_PLAINTEXT_SEED         0x1
+
+/* iwm_umac_fw_cmd_hdr.meta_data STA color -- bits [22:20] */
+#define UMAC_FW_CMD_TX_STA_COLOR_POS          20
+#define UMAC_FW_CMD_TX_STA_COLOR_SEED         0x7
+
+/* iwm_umac_fw_cmd_hdr.meta_data TX life time (TU) -- bits [31:24] */
+#define UMAC_FW_CMD_TX_LIFETIME_TU_POS        24
+#define UMAC_FW_CMD_TX_LIFETIME_TU_SEED       0xFF
+
+/* iwm_dev_cmd_hdr.flags Response required -- bits [5:5] */
+#define UMAC_DEV_CMD_FLAGS_RESP_REQ_POS		5
+#define UMAC_DEV_CMD_FLAGS_RESP_REQ_SEED	0x1
+
+/* iwm_dev_cmd_hdr.flags Aborted command -- bits [6:6] */
+#define UMAC_DEV_CMD_FLAGS_ABORT_POS		6
+#define UMAC_DEV_CMD_FLAGS_ABORT_SEED		0x1
+
+/* iwm_dev_cmd_hdr.flags Internal command -- bits [7:7] */
+#define DEV_CMD_FLAGS_FLD_INTERNAL_POS		7
+#define DEV_CMD_FLAGS_FLD_INTERNAL_SEED		0x1
+
+/* Rx */
+/* Rx actions */
+#define IWM_RX_TICKET_DROP           0x0
+#define IWM_RX_TICKET_RELEASE        0x1
+#define IWM_RX_TICKET_SNIFFER        0x2
+#define IWM_RX_TICKET_ENQUEUE        0x3
+
+/* Rx flags */
+#define IWM_RX_TICKET_PAD_SIZE_MSK        0x2
+#define IWM_RX_TICKET_SPECIAL_SNAP_MSK    0x4
+#define IWM_RX_TICKET_AMSDU_MSK           0x8
+#define IWM_RX_TICKET_DROP_REASON_POS       4
+#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << RX_TICKET_FLAGS_DROP_REASON_POS)
+
+#define IWM_RX_DROP_NO_DROP                          0x0
+#define IWM_RX_DROP_BAD_CRC                          0x1
+/* L2P no address match */
+#define IWM_RX_DROP_LMAC_ADDR_FILTER                 0x2
+/* Multicast address not in list */
+#define IWM_RX_DROP_MCAST_ADDR_FILTER                0x3
+/* Control frames are not sent to the driver */
+#define IWM_RX_DROP_CTL_FRAME                        0x4
+/* Our frame is back */
+#define IWM_RX_DROP_OUR_TX                           0x5
+/* Association class filtering */
+#define IWM_RX_DROP_CLASS_FILTER                     0x6
+/* Duplicated frame */
+#define IWM_RX_DROP_DUPLICATE_FILTER                 0x7
+/* Decryption error */
+#define IWM_RX_DROP_SEC_ERR                          0x8
+/* Unencrypted frame while encryption is on */
+#define IWM_RX_DROP_SEC_NO_ENCRYPTION                0x9
+/* Replay check failure */
+#define IWM_RX_DROP_SEC_REPLAY_ERR                   0xa
+/* uCode and FW key color mismatch, check before replay */
+#define IWM_RX_DROP_SEC_KEY_COLOR_MISMATCH           0xb
+#define IWM_RX_DROP_SEC_TKIP_COUNTER_MEASURE         0xc
+/* No fragmentations Db is found */
+#define IWM_RX_DROP_FRAG_NO_RESOURCE                 0xd
+/* Fragmention Db has seqCtl mismatch Vs. non-1st frag */
+#define IWM_RX_DROP_FRAG_ERR                         0xe
+#define IWM_RX_DROP_FRAG_LOST                        0xf
+#define IWM_RX_DROP_FRAG_COMPLETE                    0x10
+/* Should be handled by UMAC */
+#define IWM_RX_DROP_MANAGEMENT                       0x11
+/* STA not found by UMAC */
+#define IWM_RX_DROP_NO_STATION                       0x12
+/* NULL or QoS NULL */
+#define IWM_RX_DROP_NULL_DATA                        0x13
+#define IWM_RX_DROP_BA_REORDER_OLD_SEQCTL            0x14
+#define IWM_RX_DROP_BA_REORDER_DUPLICATE             0x15
+
+struct iwm_rx_ticket {
+	__le16 action;
+	__le16 id;
+	__le16 flags;
+	u8 payload_offset; /* includes: MAC header, pad, IV */
+	u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */
+} __attribute__ ((packed));
+
+struct iwm_rx_mpdu_hdr {
+	__le16 len;
+	__le16 reserved;
+} __attribute__ ((packed));
+
+/* UMAC SW WIFI API */
+
+struct iwm_dev_cmd_hdr {
+	u8 cmd;
+	u8 flags;
+	__le16 seq_num;
+} __attribute__ ((packed));
+
+struct iwm_umac_fw_cmd_hdr {
+	__le32 meta_data;
+	struct iwm_dev_cmd_hdr cmd;
+} __attribute__ ((packed));
+
+struct iwm_umac_wifi_out_hdr {
+	struct iwm_udma_out_wifi_hdr hw_hdr;
+	struct iwm_umac_fw_cmd_hdr sw_hdr;
+} __attribute__ ((packed));
+
+struct iwm_umac_nonwifi_out_hdr {
+	struct iwm_udma_out_nonwifi_hdr hw_hdr;
+} __attribute__ ((packed));
+
+struct iwm_umac_wifi_in_hdr {
+	struct iwm_udma_in_hdr hw_hdr;
+	struct iwm_umac_fw_cmd_hdr sw_hdr;
+} __attribute__ ((packed));
+
+struct iwm_umac_nonwifi_in_hdr {
+	struct iwm_udma_in_hdr hw_hdr;
+	__le32 time_stamp;
+} __attribute__ ((packed));
+
+#define IWM_UMAC_PAGE_SIZE	0x200
+
+/* Notify structures */
+struct iwm_fw_version {
+	u8 minor;
+	u8 major;
+	__le16 id;
+};
+
+struct iwm_fw_build {
+	u8 type;
+	u8 subtype;
+	u8 platform;
+	u8 opt;
+};
+
+struct iwm_fw_alive_hdr {
+	struct iwm_fw_version ver;
+	struct iwm_fw_build build;
+	__le32 os_build;
+	__le32 log_hdr_addr;
+	__le32 log_buf_addr;
+	__le32 sys_timer_addr;
+};
+
+#define WAIT_NOTIF_TIMEOUT     (2 * HZ)
+#define SCAN_COMPLETE_TIMEOUT  (3 * HZ)
+
+#define UMAC_NTFY_ALIVE_STATUS_ERR		0xDEAD
+#define UMAC_NTFY_ALIVE_STATUS_OK		0xCAFE
+
+#define UMAC_NTFY_INIT_COMPLETE_STATUS_ERR	0xDEAD
+#define UMAC_NTFY_INIT_COMPLETE_STATUS_OK	0xCAFE
+
+#define UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN      0x40
+#define UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN      0x80
+
+#define IWM_MACS_OUT_GROUPS	6
+#define IWM_MACS_OUT_SGROUPS	1
+
+
+#define WIFI_IF_NTFY_ASSOC_START			0x80
+#define WIFI_IF_NTFY_ASSOC_COMPLETE			0x81
+#define WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE	0x82
+#define WIFI_IF_NTFY_CONNECTION_TERMINATED		0x83
+#define WIFI_IF_NTFY_SCAN_COMPLETE			0x84
+#define WIFI_IF_NTFY_STA_TABLE_CHANGE			0x85
+#define WIFI_IF_NTFY_EXTENDED_IE_REQUIRED		0x86
+#define WIFI_IF_NTFY_RADIO_PREEMPTION			0x87
+#define WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED		0x88
+#define WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED		0x89
+#define WIFI_IF_NTFY_LINK_QUALITY_STATISTICS		0x8A
+#define WIFI_IF_NTFY_MGMT_FRAME				0x8B
+
+/* DEBUG INDICATIONS */
+#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START		0xE0
+#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE	0xE1
+#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START		0xE2
+#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT		0xE3
+#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START		0xE4
+#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE		0xE5
+#define WIFI_DBG_IF_NTFY_CNCT_ATC_START			0xE6
+#define WIFI_DBG_IF_NTFY_COEX_NOTIFICATION		0xE7
+#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP		0xE8
+#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP	0xE9
+
+/* Notification structures */
+struct iwm_umac_notif_wifi_if {
+	struct iwm_umac_wifi_in_hdr hdr;
+	u8 status;
+	u8 flags;
+	__le16 buf_size;
+} __attribute__ ((packed));
+
+#define UMAC_ROAM_REASON_FIRST_SELECTION	0x1
+#define UMAC_ROAM_REASON_AP_DEAUTH		0x2
+#define UMAC_ROAM_REASON_AP_CONNECT_LOST	0x3
+#define UMAC_ROAM_REASON_RSSI			0x4
+#define UMAC_ROAM_REASON_AP_ASSISTED_ROAM	0x5
+#define UMAC_ROAM_REASON_IBSS_COALESCING	0x6
+
+struct iwm_umac_notif_assoc_start {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le32 roam_reason;
+	u8 bssid[ETH_ALEN];
+	u8 reserved[2];
+} __attribute__ ((packed));
+
+#define UMAC_ASSOC_COMPLETE_SUCCESS		0x0
+#define UMAC_ASSOC_COMPLETE_FAILURE		0x1
+
+struct iwm_umac_notif_assoc_complete {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le32 status;
+	u8 bssid[ETH_ALEN];
+	u8 band;
+	u8 channel;
+} __attribute__ ((packed));
+
+#define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT	0x0
+#define UMAC_PROFILE_INVALID_ROAM_TIMEOUT	0x1
+#define UMAC_PROFILE_INVALID_REQUEST		0x2
+#define UMAC_PROFILE_INVALID_RF_PREEMPTED	0x3
+
+struct iwm_umac_notif_profile_invalidate {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le32 reason;
+} __attribute__ ((packed));
+
+#define UMAC_SCAN_RESULT_SUCCESS  0x0
+#define UMAC_SCAN_RESULT_ABORTED  0x1
+#define UMAC_SCAN_RESULT_REJECTED 0x2
+#define UMAC_SCAN_RESULT_FAILED   0x3
+
+struct iwm_umac_notif_scan_complete {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le32 type;
+	__le32 result;
+	u8 seq_num;
+} __attribute__ ((packed));
+
+#define UMAC_OPCODE_ADD_MODIFY	0x0
+#define UMAC_OPCODE_REMOVE	0x1
+#define UMAC_OPCODE_CLEAR_ALL	0x2
+
+#define UMAC_STA_FLAG_QOS	0x1
+
+struct iwm_umac_notif_sta_info {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le32 opcode;
+	u8 mac_addr[ETH_ALEN];
+	u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */
+	u8 flags;
+} __attribute__ ((packed));
+
+#define UMAC_BAND_2GHZ 0
+#define UMAC_BAND_5GHZ 1
+
+#define UMAC_CHANNEL_WIDTH_20MHZ 0
+#define UMAC_CHANNEL_WIDTH_40MHZ 1
+
+struct iwm_umac_notif_bss_info {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le32 type;
+	__le32 timestamp;
+	__le16 table_idx;
+	__le16 frame_len;
+	u8 band;
+	u8 channel;
+	s8 rssi;
+	u8 reserved;
+	u8 frame_buf[1];
+} __attribute__ ((packed));
+
+#define IWM_BSS_REMOVE_INDEX_MSK           0x0fff
+#define IWM_BSS_REMOVE_FLAGS_MSK           0xfc00
+
+#define IWM_BSS_REMOVE_FLG_AGE             0x1000
+#define IWM_BSS_REMOVE_FLG_TIMEOUT         0x2000
+#define IWM_BSS_REMOVE_FLG_TABLE_FULL      0x4000
+
+struct iwm_umac_notif_bss_removed {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le32 count;
+	__le16 entries[0];
+} __attribute__ ((packed));
+
+struct iwm_umac_notif_mgt_frame {
+	struct iwm_umac_notif_wifi_if mlme_hdr;
+	__le16 len;
+	u8 frame[1];
+} __attribute__ ((packed));
+
+struct iwm_umac_notif_alive {
+	struct iwm_umac_wifi_in_hdr hdr;
+	__le16 status;
+	__le16 reserved1;
+	struct iwm_fw_alive_hdr alive_data;
+	__le16 reserved2;
+	__le16 page_grp_count;
+	__le32 page_grp_state[IWM_MACS_OUT_GROUPS];
+} __attribute__ ((packed));
+
+struct iwm_umac_notif_init_complete {
+	__le16 status;
+	__le16 reserved;
+} __attribute__ ((packed));
+
+/* error categories */
+enum {
+	UMAC_SYS_ERR_CAT_NONE = 0,
+	UMAC_SYS_ERR_CAT_BOOT,
+	UMAC_SYS_ERR_CAT_UMAC,
+	UMAC_SYS_ERR_CAT_UAXM,
+	UMAC_SYS_ERR_CAT_LMAC,
+	UMAC_SYS_ERR_CAT_MAX
+};
+
+struct iwm_fw_error_hdr {
+	__le32 category;
+	__le32 status;
+	__le32 pc;
+	__le32 blink1;
+	__le32 blink2;
+	__le32 ilink1;
+	__le32 ilink2;
+	__le32 data1;
+	__le32 data2;
+	__le32 line_num;
+	__le32 umac_status;
+	__le32 lmac_status;
+	__le32 sdio_status;
+} __attribute__ ((packed));
+
+struct iwm_umac_notif_error {
+	struct iwm_umac_wifi_in_hdr hdr;
+	struct iwm_fw_error_hdr err;
+} __attribute__ ((packed));
+
+#define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS	0
+#define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED	0xff
+#define UMAC_DEALLOC_NTFY_CHANGES_MSK_POS	8
+#define UMAC_DEALLOC_NTFY_CHANGES_MSK_SEED	0xffffff
+#define UMAC_DEALLOC_NTFY_PAGE_CNT_POS		0
+#define UMAC_DEALLOC_NTFY_PAGE_CNT_SEED		0xffffff
+#define UMAC_DEALLOC_NTFY_GROUP_NUM_POS		24
+#define UMAC_DEALLOC_NTFY_GROUP_NUM_SEED	0xf
+
+struct iwm_umac_notif_page_dealloc {
+	struct iwm_umac_wifi_in_hdr hdr;
+	__le32 changes;
+	__le32 grp_info[IWM_MACS_OUT_GROUPS];
+} __attribute__ ((packed));
+
+struct iwm_umac_notif_wifi_status {
+	struct iwm_umac_wifi_in_hdr hdr;
+	__le16 status;
+	__le16 reserved;
+} __attribute__ ((packed));
+
+struct iwm_umac_notif_rx_ticket {
+	struct iwm_umac_wifi_in_hdr hdr;
+	u8 num_tickets;
+	u8 reserved[3];
+	struct iwm_rx_ticket tickets[1];
+} __attribute__ ((packed));
+
+/* Tx/Rx rates window (number of max of last update window per second) */
+#define UMAC_NTF_RATE_SAMPLE_NR	4
+
+#define IWM_UMAC_MGMT_TID	8
+#define IWM_UMAC_TID_NR		8
+
+struct iwm_umac_notif_stats {
+	struct iwm_umac_wifi_in_hdr hdr;
+	__le32 flags;
+	__le32 timestamp;
+	__le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */
+	__le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR];
+	__le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR];
+	s32 rssi_dbm;
+	s32 noise_dbm;
+	__le32 supp_rates;
+	__le32 missed_beacons;
+	__le32 rx_beacons;
+	__le32 rx_dir_pkts;
+	__le32 rx_nondir_pkts;
+	__le32 rx_multicast;
+	__le32 rx_errors;
+	__le32 rx_drop_other_bssid;
+	__le32 rx_drop_decode;
+	__le32 rx_drop_reassembly;
+	__le32 rx_drop_bad_len;
+	__le32 rx_drop_overflow;
+	__le32 rx_drop_crc;
+	__le32 rx_drop_missed;
+	__le32 tx_dir_pkts;
+	__le32 tx_nondir_pkts;
+	__le32 tx_failure;
+	__le32 tx_errors;
+	__le32 tx_drop_max_retry;
+	__le32 tx_err_abort;
+	__le32 tx_err_carrier;
+	__le32 rx_bytes;
+	__le32 tx_bytes;
+	__le32 tx_power;
+	__le32 tx_max_power;
+	__le32 roam_threshold;
+	__le32 ap_assoc_nr;
+	__le32 scan_full;
+	__le32 scan_abort;
+	__le32 ap_nr;
+	__le32 roam_nr;
+	__le32 roam_missed_beacons;
+	__le32 roam_rssi;
+	__le32 roam_unassoc;
+	__le32 roam_deauth;
+	__le32 roam_ap_loadblance;
+} __attribute__ ((packed));
+
+/* WiFi interface wrapper header */
+struct iwm_umac_wifi_if {
+	u8 oid;
+	u8 flags;
+	__le16 buf_size;
+} __attribute__ ((packed));
+
+#define IWM_SEQ_NUM_HOST_MSK	0x0000
+#define IWM_SEQ_NUM_UMAC_MSK	0x4000
+#define IWM_SEQ_NUM_LMAC_MSK	0x8000
+#define IWM_SEQ_NUM_MSK		0xC000
+
+#endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/wext.c linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/wext.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/iwmc3200wifi/wext.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/iwmc3200wifi/wext.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,723 @@
+/*
+ * Intel Wireless Multicomm 3200 WiFi driver
+ *
+ * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
+ * Samuel Ortiz <samuel.ortiz@intel.com>
+ * Zhu Yi <yi.zhu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <net/cfg80211.h>
+#include <net/iw_handler.h>
+
+#include "iwm.h"
+#include "umac.h"
+#include "commands.h"
+#include "debug.h"
+
+static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+	struct iw_statistics *wstats = &iwm->wstats;
+
+	if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
+		memset(wstats, 0, sizeof(struct iw_statistics));
+		wstats->qual.updated = IW_QUAL_ALL_INVALID;
+	}
+
+	return wstats;
+}
+
+static int iwm_wext_siwfreq(struct net_device *dev,
+			    struct iw_request_info *info,
+			    struct iw_freq *freq, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+
+	if (freq->flags == IW_FREQ_AUTO)
+		return 0;
+
+	/* frequency/channel can only be set in IBSS mode */
+	if (iwm->conf.mode != UMAC_MODE_IBSS)
+		return -EOPNOTSUPP;
+
+	return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
+}
+
+static int iwm_wext_giwfreq(struct net_device *dev,
+			    struct iw_request_info *info,
+			    struct iw_freq *freq, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+
+	if (iwm->conf.mode == UMAC_MODE_IBSS)
+		return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
+
+	freq->e = 0;
+	freq->m = iwm->channel;
+
+	return 0;
+}
+
+static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
+			  struct sockaddr *ap_addr, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+
+	if (iwm->conf.mode == UMAC_MODE_IBSS)
+		return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
+
+	if (!test_bit(IWM_STATUS_READY, &iwm->status))
+		return -EIO;
+
+	if (is_zero_ether_addr(ap_addr->sa_data) ||
+	    is_broadcast_ether_addr(ap_addr->sa_data)) {
+		IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n",
+			     iwm->umac_profile->bssid[0]);
+		memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
+		iwm->umac_profile->bss_num = 0;
+	} else {
+		IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n",
+			     ap_addr->sa_data);
+		memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data,
+		       ETH_ALEN);
+		iwm->umac_profile->bss_num = 1;
+	}
+
+	if (iwm->umac_profile_active) {
+		if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN))
+			return 0;
+
+		iwm_invalidate_mlme_profile(iwm);
+	}
+
+	if (iwm->umac_profile->ssid.ssid_len)
+		return iwm_send_mlme_profile(iwm);
+
+	return 0;
+}
+
+static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
+			  struct sockaddr *ap_addr, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+
+	switch (iwm->conf.mode) {
+	case UMAC_MODE_IBSS:
+		return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
+	case UMAC_MODE_BSS:
+		if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
+			ap_addr->sa_family = ARPHRD_ETHER;
+			memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN);
+		} else
+			memset(&ap_addr->sa_data, 0, ETH_ALEN);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int iwm_wext_siwessid(struct net_device *dev,
+			     struct iw_request_info *info,
+			     struct iw_point *data, char *ssid)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+	size_t len = data->length;
+	int ret;
+
+	if (iwm->conf.mode == UMAC_MODE_IBSS)
+		return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
+
+	if (!test_bit(IWM_STATUS_READY, &iwm->status))
+		return -EIO;
+
+	if (len > 0 && ssid[len - 1] == '\0')
+		len--;
+
+	if (iwm->umac_profile_active) {
+		if (iwm->umac_profile->ssid.ssid_len == len &&
+		    !memcmp(iwm->umac_profile->ssid.ssid, ssid, len))
+			return 0;
+
+		ret = iwm_invalidate_mlme_profile(iwm);
+		if (ret < 0) {
+			IWM_ERR(iwm, "Couldn't invalidate profile\n");
+			return ret;
+		}
+	}
+
+	iwm->umac_profile->ssid.ssid_len = len;
+	memcpy(iwm->umac_profile->ssid.ssid, ssid, len);
+
+	return iwm_send_mlme_profile(iwm);
+}
+
+static int iwm_wext_giwessid(struct net_device *dev,
+			     struct iw_request_info *info,
+			     struct iw_point *data, char *ssid)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+
+	if (iwm->conf.mode == UMAC_MODE_IBSS)
+		return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
+
+	if (!test_bit(IWM_STATUS_READY, &iwm->status))
+		return -EIO;
+
+	data->length = iwm->umac_profile->ssid.ssid_len;
+	if (data->length) {
+		memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length);
+		data->flags = 1;
+	} else
+		data->flags = 0;
+
+	return 0;
+}
+
+static struct iwm_key *
+iwm_key_init(struct iwm_priv *iwm, u8 key_idx, bool in_use,
+	     struct iw_encode_ext *ext, u8 alg)
+{
+	struct iwm_key *key = &iwm->keys[key_idx];
+
+	memset(key, 0, sizeof(struct iwm_key));
+	memcpy(key->hdr.mac, ext->addr.sa_data, ETH_ALEN);
+	key->hdr.key_idx = key_idx;
+	if (is_broadcast_ether_addr(ext->addr.sa_data))
+		key->hdr.multicast = 1;
+
+	key->in_use = in_use;
+	key->flags = ext->ext_flags;
+	key->alg = alg;
+	key->key_len = ext->key_len;
+	memcpy(key->key, ext->key, ext->key_len);
+
+	return key;
+}
+
+static int iwm_wext_giwrate(struct net_device *dev,
+			    struct iw_request_info *info,
+			    struct iw_param *rate, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+
+	rate->value = iwm->rate * 1000000;
+
+	return 0;
+}
+
+static int iwm_wext_siwencode(struct net_device *dev,
+			      struct iw_request_info *info,
+			      struct iw_point *erq, char *key_buf)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+	struct iwm_key *uninitialized_var(key);
+	int idx, i, uninitialized_var(alg), remove = 0, ret;
+
+	IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", erq->length);
+	IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
+
+	if (!iwm->umac_profile) {
+		IWM_ERR(iwm, "UMAC profile not allocated yet\n");
+		return -ENODEV;
+	}
+
+	if (erq->length == WLAN_KEY_LEN_WEP40) {
+		alg = UMAC_CIPHER_TYPE_WEP_40;
+		iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_40;
+		iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_40;
+	} else if (erq->length == WLAN_KEY_LEN_WEP104) {
+		alg = UMAC_CIPHER_TYPE_WEP_104;
+		iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_104;
+		iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_104;
+	}
+
+	if (erq->flags & IW_ENCODE_RESTRICTED)
+		iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
+	else
+		iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
+
+	idx = erq->flags & IW_ENCODE_INDEX;
+	if (idx == 0) {
+		if (iwm->default_key)
+			for (i = 0; i < IWM_NUM_KEYS; i++) {
+				if (iwm->default_key == &iwm->keys[i]) {
+					idx = i;
+					break;
+				}
+			}
+		else
+			iwm->default_key = &iwm->keys[idx];
+	} else if (idx < 1 || idx > 4) {
+		return -EINVAL;
+	} else
+		idx--;
+
+	if (erq->flags & IW_ENCODE_DISABLED)
+		remove = 1;
+	else if (erq->length == 0) {
+		if (!iwm->keys[idx].in_use)
+			return -EINVAL;
+		iwm->default_key = &iwm->keys[idx];
+	}
+
+	if (erq->length) {
+		key = &iwm->keys[idx];
+		memset(key, 0, sizeof(struct iwm_key));
+		memset(key->hdr.mac, 0xff, ETH_ALEN);
+		key->hdr.key_idx = idx;
+		key->hdr.multicast = 1;
+		key->in_use = !remove;
+		key->alg = alg;
+		key->key_len = erq->length;
+		memcpy(key->key, key_buf, erq->length);
+
+		IWM_DBG_WEXT(iwm, DBG, "Setting key %d, default: %d\n",
+			     idx, !!iwm->default_key);
+	}
+
+	if (remove) {
+		if ((erq->flags & IW_ENCODE_NOKEY) || (erq->length == 0)) {
+			int j;
+			for (j = 0; j < IWM_NUM_KEYS; j++)
+				if (iwm->keys[j].in_use) {
+					struct iwm_key *k = &iwm->keys[j];
+
+					k->in_use = 0;
+					ret = iwm_set_key(iwm, remove, 0, k);
+					if (ret < 0)
+						return ret;
+				}
+
+			iwm->umac_profile->sec.ucast_cipher =
+							UMAC_CIPHER_TYPE_NONE;
+			iwm->umac_profile->sec.mcast_cipher =
+							UMAC_CIPHER_TYPE_NONE;
+			iwm->umac_profile->sec.auth_type =
+							UMAC_AUTH_TYPE_OPEN;
+
+			return 0;
+		} else {
+			key->in_use = 0;
+			return iwm_set_key(iwm, remove, 0, key);
+		}
+	}
+
+	/*
+	 * If we havent set a profile yet, we cant set keys.
+	 * Keys will be pushed after we're associated.
+	 */
+	if (!iwm->umac_profile_active)
+		return 0;
+
+	/*
+	 * If there is a current active profile, but no
+	 * default key, it's not worth trying to associate again.
+	 */
+	if (!iwm->default_key)
+		return 0;
+
+	/*
+	 * Here we have an active profile, but a key setting changed.
+	 * We thus have to invalidate the current profile, and push the
+	 * new one. Keys will be pushed when association takes place.
+	 */
+	ret = iwm_invalidate_mlme_profile(iwm);
+	if (ret < 0) {
+		IWM_ERR(iwm, "Couldn't invalidate profile\n");
+		return ret;
+	}
+
+	return iwm_send_mlme_profile(iwm);
+}
+
+static int iwm_wext_giwencode(struct net_device *dev,
+			      struct iw_request_info *info,
+			      struct iw_point *erq, char *key)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+	int idx, i;
+
+	idx = erq->flags & IW_ENCODE_INDEX;
+	if (idx < 1 || idx > 4) {
+		idx = -1;
+		if (!iwm->default_key) {
+			erq->length = 0;
+			erq->flags |= IW_ENCODE_NOKEY;
+			return 0;
+		} else
+			for (i = 0; i < IWM_NUM_KEYS; i++) {
+				if (iwm->default_key == &iwm->keys[i]) {
+					idx = i;
+					break;
+				}
+			}
+		if (idx < 0)
+			return -EINVAL;
+	} else
+		idx--;
+
+	erq->flags = idx + 1;
+
+	if (!iwm->keys[idx].in_use) {
+		erq->length = 0;
+		erq->flags |= IW_ENCODE_DISABLED;
+		return 0;
+	}
+
+	memcpy(key, iwm->keys[idx].key,
+	       min_t(int, erq->length, iwm->keys[idx].key_len));
+	erq->length = iwm->keys[idx].key_len;
+	erq->flags |= IW_ENCODE_ENABLED;
+
+	if (iwm->umac_profile->mode == UMAC_MODE_BSS) {
+		switch (iwm->umac_profile->sec.auth_type) {
+		case UMAC_AUTH_TYPE_OPEN:
+			erq->flags |= IW_ENCODE_OPEN;
+			break;
+		default:
+			erq->flags |= IW_ENCODE_RESTRICTED;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
+{
+	if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
+		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
+	else if (wpa_version & IW_AUTH_WPA_VERSION_WPA)
+		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
+	else
+		iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
+
+	return 0;
+}
+
+static int iwm_wext_siwpower(struct net_device *dev,
+			     struct iw_request_info *info,
+			     struct iw_param *wrq, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+	u32 power_index;
+
+	if (wrq->disabled) {
+		power_index = IWM_POWER_INDEX_MIN;
+		goto set;
+	} else
+		power_index = IWM_POWER_INDEX_DEFAULT;
+
+	switch (wrq->flags & IW_POWER_MODE) {
+	case IW_POWER_ON:
+	case IW_POWER_MODE:
+	case IW_POWER_ALL_R:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+ set:
+	if (power_index == iwm->conf.power_index)
+		return 0;
+
+	iwm->conf.power_index = power_index;
+
+	return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+				       CFG_POWER_INDEX, iwm->conf.power_index);
+}
+
+static int iwm_wext_giwpower(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+
+	wrqu->power.disabled = (iwm->conf.power_index == IWM_POWER_INDEX_MIN);
+
+	return 0;
+}
+
+static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
+{
+	u8 *auth_type = &iwm->umac_profile->sec.auth_type;
+
+	if (key_mgt == IW_AUTH_KEY_MGMT_802_1X)
+		*auth_type = UMAC_AUTH_TYPE_8021X;
+	else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) {
+		if (iwm->umac_profile->sec.flags &
+		    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
+			*auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
+		else
+			*auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
+	} else {
+		IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast)
+{
+	u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
+		&iwm->umac_profile->sec.mcast_cipher;
+
+	switch (cipher) {
+	case IW_AUTH_CIPHER_NONE:
+		*profile_cipher = UMAC_CIPHER_TYPE_NONE;
+		break;
+	case IW_AUTH_CIPHER_WEP40:
+		*profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
+		break;
+	case IW_AUTH_CIPHER_TKIP:
+		*profile_cipher = UMAC_CIPHER_TYPE_TKIP;
+		break;
+	case IW_AUTH_CIPHER_CCMP:
+		*profile_cipher = UMAC_CIPHER_TYPE_CCMP;
+		break;
+	case IW_AUTH_CIPHER_WEP104:
+		*profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
+		break;
+	default:
+		IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
+{
+	u8 *auth_type = &iwm->umac_profile->sec.auth_type;
+
+	switch (auth_alg) {
+	case IW_AUTH_ALG_OPEN_SYSTEM:
+		*auth_type = UMAC_AUTH_TYPE_OPEN;
+		break;
+	case IW_AUTH_ALG_SHARED_KEY:
+		if (iwm->umac_profile->sec.flags &
+		    (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
+			if (*auth_type == UMAC_AUTH_TYPE_8021X)
+				return -EINVAL;
+			*auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
+		} else {
+			*auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
+		}
+		break;
+	case IW_AUTH_ALG_LEAP:
+	default:
+		IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg);
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int iwm_wext_siwauth(struct net_device *dev,
+			    struct iw_request_info *info,
+			    struct iw_param *data, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+	int ret;
+
+	if ((data->flags) &
+	    (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT |
+	     IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) {
+		/* We need to invalidate the current profile */
+		if (iwm->umac_profile_active) {
+			ret = iwm_invalidate_mlme_profile(iwm);
+			if (ret < 0) {
+				IWM_ERR(iwm, "Couldn't invalidate profile\n");
+				return ret;
+			}
+		}
+	}
+
+	switch (data->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_WPA_VERSION:
+		return iwm_set_wpa_version(iwm, data->value);
+		break;
+	case IW_AUTH_CIPHER_PAIRWISE:
+		return iwm_set_cipher(iwm, data->value, 1);
+		break;
+	case IW_AUTH_CIPHER_GROUP:
+		return iwm_set_cipher(iwm, data->value, 0);
+		break;
+	case IW_AUTH_KEY_MGMT:
+		return iwm_set_key_mgt(iwm, data->value);
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		return iwm_set_auth_alg(iwm, data->value);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int iwm_wext_giwauth(struct net_device *dev,
+			    struct iw_request_info *info,
+			    struct iw_param *data, char *extra)
+{
+	return 0;
+}
+
+static int iwm_wext_siwencodeext(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_point *erq, char *extra)
+{
+	struct iwm_priv *iwm = ndev_to_iwm(dev);
+	struct iwm_key *key;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+	int uninitialized_var(alg), idx, i, remove = 0;
+
+	IWM_DBG_WEXT(iwm, DBG, "alg: 0x%x\n", ext->alg);
+	IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", ext->key_len);
+	IWM_DBG_WEXT(iwm, DBG, "ext_flags: 0x%x\n", ext->ext_flags);
+	IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
+	IWM_DBG_WEXT(iwm, DBG, "length: 0x%x\n", erq->length);
+
+	switch (ext->alg) {
+	case IW_ENCODE_ALG_NONE:
+		remove = 1;
+		break;
+	case IW_ENCODE_ALG_WEP:
+		if (ext->key_len == WLAN_KEY_LEN_WEP40)
+			alg = UMAC_CIPHER_TYPE_WEP_40;
+		else if (ext->key_len == WLAN_KEY_LEN_WEP104)
+			alg = UMAC_CIPHER_TYPE_WEP_104;
+		else {
+			IWM_ERR(iwm, "Invalid key length: %d\n", ext->key_len);
+			return -EINVAL;
+		}
+
+		break;
+	case IW_ENCODE_ALG_TKIP:
+		alg = UMAC_CIPHER_TYPE_TKIP;
+		break;
+	case IW_ENCODE_ALG_CCMP:
+		alg = UMAC_CIPHER_TYPE_CCMP;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	idx = erq->flags & IW_ENCODE_INDEX;
+
+	if (idx == 0) {
+		if (iwm->default_key)
+			for (i = 0; i < IWM_NUM_KEYS; i++) {
+				if (iwm->default_key == &iwm->keys[i]) {
+					idx = i;
+					break;
+				}
+			}
+	} else if (idx < 1 || idx > 4) {
+		return -EINVAL;
+	} else
+		idx--;
+
+	if (erq->flags & IW_ENCODE_DISABLED)
+		remove = 1;
+	else if ((erq->length == 0) ||
+		 (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
+		iwm->default_key = &iwm->keys[idx];
+		if (iwm->umac_profile_active && ext->alg == IW_ENCODE_ALG_WEP)
+			return iwm_set_tx_key(iwm, idx);
+	}
+
+	key = iwm_key_init(iwm, idx, !remove, ext, alg);
+
+	return iwm_set_key(iwm, remove, !iwm->default_key, key);
+}
+
+static const iw_handler iwm_handlers[] =
+{
+	(iw_handler) NULL,				/* SIOCSIWCOMMIT */
+	(iw_handler) cfg80211_wext_giwname,		/* SIOCGIWNAME */
+	(iw_handler) NULL,				/* SIOCSIWNWID */
+	(iw_handler) NULL,				/* SIOCGIWNWID */
+	(iw_handler) iwm_wext_siwfreq,			/* SIOCSIWFREQ */
+	(iw_handler) iwm_wext_giwfreq,			/* SIOCGIWFREQ */
+	(iw_handler) cfg80211_wext_siwmode,		/* SIOCSIWMODE */
+	(iw_handler) cfg80211_wext_giwmode,		/* SIOCGIWMODE */
+	(iw_handler) NULL,				/* SIOCSIWSENS */
+	(iw_handler) NULL,				/* SIOCGIWSENS */
+	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */
+	(iw_handler) cfg80211_wext_giwrange,		/* SIOCGIWRANGE */
+	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */
+	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */
+	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */
+	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS */
+	(iw_handler) NULL,				/* SIOCSIWSPY */
+	(iw_handler) NULL,				/* SIOCGIWSPY */
+	(iw_handler) NULL,				/* SIOCSIWTHRSPY */
+	(iw_handler) NULL,				/* SIOCGIWTHRSPY */
+	(iw_handler) iwm_wext_siwap,	                /* SIOCSIWAP */
+	(iw_handler) iwm_wext_giwap,			/* SIOCGIWAP */
+	(iw_handler) NULL,			        /* SIOCSIWMLME */
+	(iw_handler) NULL,				/* SIOCGIWAPLIST */
+	(iw_handler) cfg80211_wext_siwscan,		/* SIOCSIWSCAN */
+	(iw_handler) cfg80211_wext_giwscan,		/* SIOCGIWSCAN */
+	(iw_handler) iwm_wext_siwessid,			/* SIOCSIWESSID */
+	(iw_handler) iwm_wext_giwessid,			/* SIOCGIWESSID */
+	(iw_handler) NULL,				/* SIOCSIWNICKN */
+	(iw_handler) NULL,				/* SIOCGIWNICKN */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* SIOCSIWRATE */
+	(iw_handler) iwm_wext_giwrate,			/* SIOCGIWRATE */
+	(iw_handler) cfg80211_wext_siwrts,		/* SIOCSIWRTS */
+	(iw_handler) cfg80211_wext_giwrts,		/* SIOCGIWRTS */
+	(iw_handler) cfg80211_wext_siwfrag,	        /* SIOCSIWFRAG */
+	(iw_handler) cfg80211_wext_giwfrag,		/* SIOCGIWFRAG */
+	(iw_handler) NULL,				/* SIOCSIWTXPOW */
+	(iw_handler) NULL,				/* SIOCGIWTXPOW */
+	(iw_handler) NULL,				/* SIOCSIWRETRY */
+	(iw_handler) NULL,				/* SIOCGIWRETRY */
+	(iw_handler) iwm_wext_siwencode,		/* SIOCSIWENCODE */
+	(iw_handler) iwm_wext_giwencode,		/* SIOCGIWENCODE */
+	(iw_handler) iwm_wext_siwpower,			/* SIOCSIWPOWER */
+	(iw_handler) iwm_wext_giwpower,			/* SIOCGIWPOWER */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,                              /* SIOCSIWGENIE */
+	(iw_handler) NULL,				/* SIOCGIWGENIE */
+	(iw_handler) iwm_wext_siwauth,			/* SIOCSIWAUTH */
+	(iw_handler) iwm_wext_giwauth,			/* SIOCGIWAUTH */
+	(iw_handler) iwm_wext_siwencodeext,	        /* SIOCSIWENCODEEXT */
+	(iw_handler) NULL,				/* SIOCGIWENCODEEXT */
+	(iw_handler) NULL,				/* SIOCSIWPMKSA */
+	(iw_handler) NULL,				/* -- hole -- */
+};
+
+const struct iw_handler_def iwm_iw_handler_def = {
+	.num_standard	= ARRAY_SIZE(iwm_handlers),
+	.standard	= (iw_handler *) iwm_handlers,
+	.get_wireless_stats = iwm_get_wireless_stats,
+};
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/Kconfig	2012-03-22 19:17:57.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/Kconfig	2012-03-22 20:14:03.000000000 -0400
@@ -146,14 +146,14 @@
 	  A driver for Marvell Libertas 8385 CompactFlash devices.
 
 config LIBERTAS_SDIO
-	tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards"
+	tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
 	depends on LIBERTAS && MMC
 	---help---
-	  A driver for Marvell Libertas 8385 and 8686 SDIO devices.
+	  A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
 
 config LIBERTAS_SPI
 	tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
-	depends on LIBERTAS && SPI && GENERIC_GPIO
+	depends on LIBERTAS && SPI
 	---help---
 	  A driver for Marvell Libertas 8686 SPI devices.
 
@@ -303,7 +303,7 @@
 	  If you want to compile the driver as a module ( = code which can be
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read <file:Documentation/kbuild/modules.txt>.
-	  The module will be called prism54.ko.
+	  The module will be called prism54.
 
 config USB_ZD1201
 	tristate "USB ZD1201 based Wireless device support"
@@ -326,6 +326,7 @@
 config USB_NET_RNDIS_WLAN
 	tristate "Wireless RNDIS USB support"
 	depends on USB && WLAN_80211 && EXPERIMENTAL
+	depends on CFG80211
 	select USB_USBNET
 	select USB_NET_CDCETHER
 	select USB_NET_RNDIS_HOST
@@ -427,6 +428,13 @@
 
 	  Thanks to Realtek for their support!
 
+# If possible, automatically enable LEDs for RTL8187.
+
+config RTL8187_LEDS
+	bool
+	depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187)
+	default y
+
 config ADM8211
 	tristate "ADMtek ADM8211 support"
 	depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
@@ -477,9 +485,7 @@
 	  will be called mwl8k.  If unsure, say N.
 
 source "drivers/net/wireless/p54/Kconfig"
-source "drivers/net/wireless/ath5k/Kconfig"
-source "drivers/net/wireless/ath9k/Kconfig"
-source "drivers/net/wireless/ar9170/Kconfig"
+source "drivers/net/wireless/ath/Kconfig"
 source "drivers/net/wireless/ipw2x00/Kconfig"
 source "drivers/net/wireless/iwlwifi/Kconfig"
 source "drivers/net/wireless/hostap/Kconfig"
@@ -488,5 +494,7 @@
 source "drivers/net/wireless/zd1211rw/Kconfig"
 source "drivers/net/wireless/rt2x00/Kconfig"
 source "drivers/net/wireless/orinoco/Kconfig"
+source "drivers/net/wireless/wl12xx/Kconfig"
+source "drivers/net/wireless/iwmc3200wifi/Kconfig"
 
 endmenu
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/11d.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/11d.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/11d.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/11d.c	2009-09-09 18:13:59.000000000 -0400
@@ -47,7 +47,7 @@
 {
 	u8 i;
 
-	for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
+	for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++)
 		region[i] = toupper(region[i]);
 
 	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
@@ -207,7 +207,7 @@
 	lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
 	lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo,
 		COUNTRY_CODE_LEN + 1 +
-		sizeof(struct ieeetypes_subbandset) * nr_subband);
+		sizeof(struct ieee_subbandset) * nr_subband);
 	return 0;
 }
 
@@ -302,11 +302,9 @@
  *  @param parsed_region_chan   pointer to parsed_region_chan_11d
  *  @return 	                0
 */
-static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
-				 countryinfo,
+static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo,
 				 u8 band,
-				 struct parsed_region_chan_11d *
-				 parsed_region_chan)
+				 struct parsed_region_chan_11d *parsed_region_chan)
 {
 	u8 nr_subband, nrchan;
 	u8 lastchan, firstchan;
@@ -331,7 +329,7 @@
 	lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30);
 
 	if ((*(countryinfo->countrycode)) == 0
-	    || (countryinfo->len <= COUNTRY_CODE_LEN)) {
+	    || (countryinfo->header.len <= COUNTRY_CODE_LEN)) {
 		/* No region Info or Wrong region info: treat as No 11D info */
 		goto done;
 	}
@@ -349,8 +347,8 @@
 	memcpy(parsed_region_chan->countrycode, countryinfo->countrycode,
 	       COUNTRY_CODE_LEN);
 
-	nr_subband = (countryinfo->len - COUNTRY_CODE_LEN) /
-	    sizeof(struct ieeetypes_subbandset);
+	nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) /
+	    sizeof(struct ieee_subbandset);
 
 	for (j = 0, lastchan = 0; j < nr_subband; j++) {
 
@@ -502,7 +500,7 @@
 {
 	struct cmd_ds_802_11d_domain_info *pdomaininfo =
 	    &cmd->params.domaininfo;
-	struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain;
+	struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
 	u8 nr_subband = priv->domainreg.nr_subband;
 
 	lbs_deb_enter(LBS_DEB_11D);
@@ -524,16 +522,16 @@
 	       sizeof(domain->countrycode));
 
 	domain->header.len =
-	    cpu_to_le16(nr_subband * sizeof(struct ieeetypes_subbandset) +
+	    cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) +
 			     sizeof(domain->countrycode));
 
 	if (nr_subband) {
 		memcpy(domain->subband, priv->domainreg.subband,
-		       nr_subband * sizeof(struct ieeetypes_subbandset));
+		       nr_subband * sizeof(struct ieee_subbandset));
 
 		cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
 					     le16_to_cpu(domain->header.len) +
-					     sizeof(struct mrvlietypesheader) +
+					     sizeof(struct mrvl_ie_header) +
 					     S_DS_GEN);
 	} else {
 		cmd->size =
@@ -556,7 +554,7 @@
 int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
 {
 	struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
-	struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
+	struct mrvl_ie_domain_param_set *domain = &domaininfo->domain;
 	u16 action = le16_to_cpu(domaininfo->action);
 	s16 ret = 0;
 	u8 nr_subband = 0;
@@ -567,7 +565,7 @@
 		(int)le16_to_cpu(resp->size));
 
 	nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
-		      sizeof(struct ieeetypes_subbandset);
+		      sizeof(struct ieee_subbandset);
 
 	lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/11d.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/11d.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/11d.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/11d.h	2009-09-09 18:13:59.000000000 -0400
@@ -20,35 +20,36 @@
 struct cmd_ds_command;
 
 /** Data structure for Country IE*/
-struct ieeetypes_subbandset {
+struct ieee_subbandset {
 	u8 firstchan;
 	u8 nrchan;
 	u8 maxtxpwr;
 } __attribute__ ((packed));
 
-struct ieeetypes_countryinfoset {
-	u8 element_id;
-	u8 len;
+struct ieee_ie_country_info_set {
+	struct ieee_ie_header header;
+
 	u8 countrycode[COUNTRY_CODE_LEN];
-	struct ieeetypes_subbandset subband[1];
+	struct ieee_subbandset subband[1];
 };
 
-struct ieeetypes_countryinfofullset {
-	u8 element_id;
-	u8 len;
+struct ieee_ie_country_info_full_set {
+	struct ieee_ie_header header;
+
 	u8 countrycode[COUNTRY_CODE_LEN];
-	struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
+	struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
 } __attribute__ ((packed));
 
-struct mrvlietypes_domainparamset {
-	struct mrvlietypesheader header;
+struct mrvl_ie_domain_param_set {
+	struct mrvl_ie_header header;
+
 	u8 countrycode[COUNTRY_CODE_LEN];
-	struct ieeetypes_subbandset subband[1];
+	struct ieee_subbandset subband[1];
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11d_domain_info {
 	__le16 action;
-	struct mrvlietypes_domainparamset domain;
+	struct mrvl_ie_domain_param_set domain;
 } __attribute__ ((packed));
 
 /** domain regulatory information */
@@ -57,7 +58,7 @@
 	u8 countrycode[COUNTRY_CODE_LEN];
 	/** No. of subband*/
 	u8 nr_subband;
-	struct ieeetypes_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
+	struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
 };
 
 struct chan_power_11d {
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/assoc.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/assoc.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/assoc.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/assoc.c	2009-09-09 18:13:59.000000000 -0400
@@ -12,15 +12,14 @@
 #include "scan.h"
 #include "cmd.h"
 
-static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp);
-
 static const u8 bssid_any[ETH_ALEN]  __attribute__ ((aligned (2))) =
 	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 static const u8 bssid_off[ETH_ALEN]  __attribute__ ((aligned (2))) =
 	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-/* The firmware needs certain bits masked out of the beacon-derviced capability
- * field when associating/joining to BSSs.
+/* The firmware needs the following bits masked out of the beacon-derived
+ * capability field when associating/joining to a BSS:
+ *  9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused)
  */
 #define CAPINFO_MASK	(~(0xda00))
 
@@ -102,6 +101,295 @@
 }
 
 
+static u8 iw_auth_to_ieee_auth(u8 auth)
+{
+	if (auth == IW_AUTH_ALG_OPEN_SYSTEM)
+		return 0x00;
+	else if (auth == IW_AUTH_ALG_SHARED_KEY)
+		return 0x01;
+	else if (auth == IW_AUTH_ALG_LEAP)
+		return 0x80;
+
+	lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth);
+	return 0;
+}
+
+/**
+ *  @brief This function prepares the authenticate command.  AUTHENTICATE only
+ *  sets the authentication suite for future associations, as the firmware
+ *  handles authentication internally during the ASSOCIATE command.
+ *
+ *  @param priv      A pointer to struct lbs_private structure
+ *  @param bssid     The peer BSSID with which to authenticate
+ *  @param auth      The authentication mode to use (from wireless.h)
+ *
+ *  @return         0 or -1
+ */
+static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth)
+{
+	struct cmd_ds_802_11_authenticate cmd;
+	int ret = -1;
+	DECLARE_MAC_BUF(mac);
+
+	lbs_deb_enter(LBS_DEB_JOIN);
+
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	memcpy(cmd.bssid, bssid, ETH_ALEN);
+
+	cmd.authtype = iw_auth_to_ieee_auth(auth);
+
+	lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
+		print_mac(mac, bssid), cmd.authtype);
+
+	ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
+
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+	return ret;
+}
+
+
+static int lbs_assoc_post(struct lbs_private *priv,
+			  struct cmd_ds_802_11_associate_response *resp)
+{
+	int ret = 0;
+	union iwreq_data wrqu;
+	struct bss_descriptor *bss;
+	u16 status_code;
+
+	lbs_deb_enter(LBS_DEB_ASSOC);
+
+	if (!priv->in_progress_assoc_req) {
+		lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
+		ret = -1;
+		goto done;
+	}
+	bss = &priv->in_progress_assoc_req->bss;
+
+	/*
+	 * Older FW versions map the IEEE 802.11 Status Code in the association
+	 * response to the following values returned in resp->statuscode:
+	 *
+	 *    IEEE Status Code                Marvell Status Code
+	 *    0                       ->      0x0000 ASSOC_RESULT_SUCCESS
+	 *    13                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    14                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    15                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    16                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
+	 *    others                  ->      0x0003 ASSOC_RESULT_REFUSED
+	 *
+	 * Other response codes:
+	 *    0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
+	 *    0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
+	 *                                    association response from the AP)
+	 */
+
+	status_code = le16_to_cpu(resp->statuscode);
+	if (priv->fwrelease < 0x09000000) {
+		switch (status_code) {
+		case 0x00:
+			break;
+		case 0x01:
+			lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
+			break;
+		case 0x02:
+			lbs_deb_assoc("ASSOC_RESP: internal timer "
+				"expired while waiting for the AP\n");
+			break;
+		case 0x03:
+			lbs_deb_assoc("ASSOC_RESP: association "
+				"refused by AP\n");
+			break;
+		case 0x04:
+			lbs_deb_assoc("ASSOC_RESP: authentication "
+				"refused by AP\n");
+			break;
+		default:
+			lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
+				" unknown\n", status_code);
+			break;
+		}
+	} else {
+		/* v9+ returns the AP's association response */
+		lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code);
+	}
+
+	if (status_code) {
+		lbs_mac_event_disconnected(priv);
+		ret = -1;
+		goto done;
+	}
+
+	lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP",
+		    (void *) (resp + sizeof (resp->hdr)),
+		    le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr));
+
+	/* Send a Media Connected event, according to the Spec */
+	priv->connect_status = LBS_CONNECTED;
+
+	/* Update current SSID and BSSID */
+	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+	priv->curbssparams.ssid_len = bss->ssid_len;
+	memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
+
+	priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
+	priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
+
+	memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
+	memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
+	priv->nextSNRNF = 0;
+	priv->numSNRNF = 0;
+
+	netif_carrier_on(priv->dev);
+	if (!priv->tx_pending_len)
+		netif_wake_queue(priv->dev);
+
+	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief This function prepares an association-class command.
+ *
+ *  @param priv      A pointer to struct lbs_private structure
+ *  @param assoc_req The association request describing the BSS to associate
+ *                   or reassociate with
+ *  @param command   The actual command, either CMD_802_11_ASSOCIATE or
+ *                   CMD_802_11_REASSOCIATE
+ *
+ *  @return         0 or -1
+ */
+static int lbs_associate(struct lbs_private *priv,
+			 struct assoc_request *assoc_req,
+			 u16 command)
+{
+	struct cmd_ds_802_11_associate cmd;
+	int ret = 0;
+	struct bss_descriptor *bss = &assoc_req->bss;
+	u8 *pos = &(cmd.iebuf[0]);
+	u16 tmpcap, tmplen, tmpauth;
+	struct mrvl_ie_ssid_param_set *ssid;
+	struct mrvl_ie_ds_param_set *ds;
+	struct mrvl_ie_cf_param_set *cf;
+	struct mrvl_ie_rates_param_set *rates;
+	struct mrvl_ie_rsn_param_set *rsn;
+	struct mrvl_ie_auth_type *auth;
+
+	lbs_deb_enter(LBS_DEB_ASSOC);
+
+	BUG_ON((command != CMD_802_11_ASSOCIATE) &&
+		(command != CMD_802_11_REASSOCIATE));
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.command = cpu_to_le16(command);
+
+	/* Fill in static fields */
+	memcpy(cmd.bssid, bss->bssid, ETH_ALEN);
+	cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
+
+	/* Capability info */
+	tmpcap = (bss->capability & CAPINFO_MASK);
+	if (bss->mode == IW_MODE_INFRA)
+		tmpcap |= WLAN_CAPABILITY_ESS;
+	cmd.capability = cpu_to_le16(tmpcap);
+	lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
+
+	/* SSID */
+	ssid = (struct mrvl_ie_ssid_param_set *) pos;
+	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
+	tmplen = bss->ssid_len;
+	ssid->header.len = cpu_to_le16(tmplen);
+	memcpy(ssid->ssid, bss->ssid, tmplen);
+	pos += sizeof(ssid->header) + tmplen;
+
+	ds = (struct mrvl_ie_ds_param_set *) pos;
+	ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
+	ds->header.len = cpu_to_le16(1);
+	ds->channel = bss->phy.ds.channel;
+	pos += sizeof(ds->header) + 1;
+
+	cf = (struct mrvl_ie_cf_param_set *) pos;
+	cf->header.type = cpu_to_le16(TLV_TYPE_CF);
+	tmplen = sizeof(*cf) - sizeof (cf->header);
+	cf->header.len = cpu_to_le16(tmplen);
+	/* IE payload should be zeroed, firmware fills it in for us */
+	pos += sizeof(*cf);
+
+	rates = (struct mrvl_ie_rates_param_set *) pos;
+	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
+	memcpy(&rates->rates, &bss->rates, MAX_RATES);
+	tmplen = MAX_RATES;
+	if (get_common_rates(priv, rates->rates, &tmplen)) {
+		ret = -1;
+		goto done;
+	}
+	pos += sizeof(rates->header) + tmplen;
+	rates->header.len = cpu_to_le16(tmplen);
+	lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
+
+	/* Copy the infra. association rates into Current BSS state structure */
+	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+	memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
+
+	/* Set MSB on basic rates as the firmware requires, but _after_
+	 * copying to current bss rates.
+	 */
+	lbs_set_basic_rate_flags(rates->rates, tmplen);
+
+	/* Firmware v9+ indicate authentication suites as a TLV */
+	if (priv->fwrelease >= 0x09000000) {
+		DECLARE_MAC_BUF(mac);
+
+		auth = (struct mrvl_ie_auth_type *) pos;
+		auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
+		auth->header.len = cpu_to_le16(2);
+		tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode);
+		auth->auth = cpu_to_le16(tmpauth);
+		pos += sizeof(auth->header) + 2;
+
+		lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
+			print_mac(mac, bss->bssid), priv->secinfo.auth_mode);
+	}
+
+	/* WPA/WPA2 IEs */
+	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
+		rsn = (struct mrvl_ie_rsn_param_set *) pos;
+		/* WPA_IE or WPA2_IE */
+		rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
+		tmplen = (u16) assoc_req->wpa_ie[1];
+		rsn->header.len = cpu_to_le16(tmplen);
+		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
+		lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn,
+			sizeof(rsn->header) + tmplen);
+		pos += sizeof(rsn->header) + tmplen;
+	}
+
+	cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) +
+				   (u16)(pos - (u8 *) &cmd.iebuf));
+
+	/* update curbssparams */
+	priv->curbssparams.channel = bss->phy.ds.channel;
+
+	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
+		ret = -1;
+		goto done;
+	}
+
+	ret = lbs_cmd_with_response(priv, command, &cmd);
+	if (ret == 0) {
+		ret = lbs_assoc_post(priv,
+			(struct cmd_ds_802_11_associate_response *) &cmd);
+	}
+
+done:
+	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+	return ret;
+}
+
 /**
  *  @brief Associate to a specific BSS discovered in a scan
  *
@@ -110,7 +398,7 @@
  *
  *  @return          0-success, otherwise fail
  */
-static int lbs_associate(struct lbs_private *priv,
+static int lbs_try_associate(struct lbs_private *priv,
 	struct assoc_request *assoc_req)
 {
 	int ret;
@@ -118,11 +406,15 @@
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
-				    0, CMD_OPTION_WAITFORRSP,
-				    0, assoc_req->bss.bssid);
-	if (ret)
-		goto out;
+	/* FW v9 and higher indicate authentication suites as a TLV in the
+	 * association command, not as a separate authentication command.
+	 */
+	if (priv->fwrelease < 0x09000000) {
+		ret = lbs_set_authentication(priv, assoc_req->bss.bssid,
+					     priv->secinfo.auth_mode);
+		if (ret)
+			goto out;
+	}
 
 	/* Use short preamble only when both the BSS and firmware support it */
 	if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
@@ -133,14 +425,78 @@
 	if (ret)
 		goto out;
 
-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
-				    0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
+	ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE);
 
 out:
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
 	return ret;
 }
 
+static int lbs_adhoc_post(struct lbs_private *priv,
+			  struct cmd_ds_802_11_ad_hoc_result *resp)
+{
+	int ret = 0;
+	u16 command = le16_to_cpu(resp->hdr.command);
+	u16 result = le16_to_cpu(resp->hdr.result);
+	union iwreq_data wrqu;
+	struct bss_descriptor *bss;
+	DECLARE_SSID_BUF(ssid);
+
+	lbs_deb_enter(LBS_DEB_JOIN);
+
+	if (!priv->in_progress_assoc_req) {
+		lbs_deb_join("ADHOC_RESP: no in-progress association "
+			"request\n");
+		ret = -1;
+		goto done;
+	}
+	bss = &priv->in_progress_assoc_req->bss;
+
+	/*
+	 * Join result code 0 --> SUCCESS
+	 */
+	if (result) {
+		lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
+		if (priv->connect_status == LBS_CONNECTED)
+			lbs_mac_event_disconnected(priv);
+		ret = -1;
+		goto done;
+	}
+
+	/* Send a Media Connected event, according to the Spec */
+	priv->connect_status = LBS_CONNECTED;
+
+	if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
+		/* Update the created network descriptor with the new BSSID */
+		memcpy(bss->bssid, resp->bssid, ETH_ALEN);
+	}
+
+	/* Set the BSSID from the joined/started descriptor */
+	memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
+
+	/* Set the new SSID to current SSID */
+	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+	priv->curbssparams.ssid_len = bss->ssid_len;
+
+	netif_carrier_on(priv->dev);
+	if (!priv->tx_pending_len)
+		netif_wake_queue(priv->dev);
+
+	memset(&wrqu, 0, sizeof(wrqu));
+	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+
+	lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
+		     print_ssid(ssid, bss->ssid, bss->ssid_len),
+		     priv->curbssparams.bssid,
+		     priv->curbssparams.channel);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+	return ret;
+}
+
 /**
  *  @brief Join an adhoc network found in a previous scan
  *
@@ -219,11 +575,10 @@
 	memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
 	memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
 
-	memcpy(&cmd.bss.phyparamset, &bss->phyparamset,
-	       sizeof(union ieeetypes_phyparamset));
+	memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set));
 
-	memcpy(&cmd.bss.ssparamset, &bss->ssparamset,
-	       sizeof(union IEEEtypes_ssparamset));
+	memcpy(&cmd.bss.ibss, &bss->ss.ibss,
+	       sizeof(struct ieee_ie_ibss_param_set));
 
 	cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
 	lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
@@ -260,7 +615,7 @@
 	 */
 	lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
 
-	cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow);
+	cmd.bss.ibss.atimwindow = bss->atimwindow;
 
 	if (assoc_req->secinfo.wep_enabled) {
 		u16 tmp = le16_to_cpu(cmd.bss.capability);
@@ -287,8 +642,10 @@
 	}
 
 	ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
-	if (ret == 0)
-		ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
+	if (ret == 0) {
+		ret = lbs_adhoc_post(priv,
+				     (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
+	}
 
 out:
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -343,22 +700,24 @@
 	WARN_ON(!assoc_req->channel);
 
 	/* set Physical parameter set */
-	cmd.phyparamset.dsparamset.elementid = WLAN_EID_DS_PARAMS;
-	cmd.phyparamset.dsparamset.len = 1;
-	cmd.phyparamset.dsparamset.currentchan = assoc_req->channel;
+	cmd.ds.header.id = WLAN_EID_DS_PARAMS;
+	cmd.ds.header.len = 1;
+	cmd.ds.channel = assoc_req->channel;
 
 	/* set IBSS parameter set */
-	cmd.ssparamset.ibssparamset.elementid = WLAN_EID_IBSS_PARAMS;
-	cmd.ssparamset.ibssparamset.len = 2;
-	cmd.ssparamset.ibssparamset.atimwindow = 0;
+	cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS;
+	cmd.ibss.header.len = 2;
+	cmd.ibss.atimwindow = cpu_to_le16(0);
 
 	/* set capability info */
 	tmpcap = WLAN_CAPABILITY_IBSS;
-	if (assoc_req->secinfo.wep_enabled) {
-		lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n");
+	if (assoc_req->secinfo.wep_enabled ||
+	    assoc_req->secinfo.WPAenabled ||
+	    assoc_req->secinfo.WPA2enabled) {
+		lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n");
 		tmpcap |= WLAN_CAPABILITY_PRIVACY;
 	} else
-		lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n");
+		lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n");
 
 	cmd.capability = cpu_to_le16(tmpcap);
 
@@ -395,7 +754,8 @@
 
 	ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
 	if (ret == 0)
-		ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
+		ret = lbs_adhoc_post(priv,
+				     (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
 
 out:
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -720,7 +1080,7 @@
 				assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
 		if (bss != NULL) {
 			memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
-			ret = lbs_associate(priv, assoc_req);
+			ret = lbs_try_associate(priv, assoc_req);
 		} else {
 			lbs_deb_assoc("SSID not found; cannot associate\n");
 		}
@@ -772,8 +1132,9 @@
 
 	memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
 	if (assoc_req->mode == IW_MODE_INFRA) {
-		ret = lbs_associate(priv, assoc_req);
-		lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
+		ret = lbs_try_associate(priv, assoc_req);
+		lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n",
+			      ret);
 	} else if (assoc_req->mode == IW_MODE_ADHOC) {
 		lbs_adhoc_join(priv, assoc_req);
 	}
@@ -1467,57 +1828,6 @@
 
 
 /**
- *  @brief This function prepares command of authenticate.
- *
- *  @param priv      A pointer to struct lbs_private structure
- *  @param cmd       A pointer to cmd_ds_command structure
- *  @param pdata_buf Void cast of pointer to a BSSID to authenticate with
- *
- *  @return         0 or -1
- */
-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
-				 struct cmd_ds_command *cmd,
-				 void *pdata_buf)
-{
-	struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
-	int ret = -1;
-	u8 *bssid = pdata_buf;
-
-	lbs_deb_enter(LBS_DEB_JOIN);
-
-	cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
-			+ S_DS_GEN);
-
-	/* translate auth mode to 802.11 defined wire value */
-	switch (priv->secinfo.auth_mode) {
-	case IW_AUTH_ALG_OPEN_SYSTEM:
-		pauthenticate->authtype = 0x00;
-		break;
-	case IW_AUTH_ALG_SHARED_KEY:
-		pauthenticate->authtype = 0x01;
-		break;
-	case IW_AUTH_ALG_LEAP:
-		pauthenticate->authtype = 0x80;
-		break;
-	default:
-		lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
-			priv->secinfo.auth_mode);
-		goto out;
-	}
-
-	memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
-
-	lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
-		bssid, pauthenticate->authtype);
-	ret = 0;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-	return ret;
-}
-
-/**
  *  @brief Deauthenticate from a specific BSS
  *
  *  @param priv        A pointer to struct lbs_private structure
@@ -1550,285 +1860,3 @@
 	return ret;
 }
 
-int lbs_cmd_80211_associate(struct lbs_private *priv,
-			      struct cmd_ds_command *cmd, void *pdata_buf)
-{
-	struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
-	int ret = 0;
-	struct assoc_request *assoc_req = pdata_buf;
-	struct bss_descriptor *bss = &assoc_req->bss;
-	u8 *pos;
-	u16 tmpcap, tmplen;
-	struct mrvlietypes_ssidparamset *ssid;
-	struct mrvlietypes_phyparamset *phy;
-	struct mrvlietypes_ssparamset *ss;
-	struct mrvlietypes_ratesparamset *rates;
-	struct mrvlietypes_rsnparamset *rsn;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	pos = (u8 *) passo;
-
-	if (!priv) {
-		ret = -1;
-		goto done;
-	}
-
-	cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
-
-	memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
-	pos += sizeof(passo->peerstaaddr);
-
-	/* set the listen interval */
-	passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
-
-	pos += sizeof(passo->capability);
-	pos += sizeof(passo->listeninterval);
-	pos += sizeof(passo->bcnperiod);
-	pos += sizeof(passo->dtimperiod);
-
-	ssid = (struct mrvlietypes_ssidparamset *) pos;
-	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
-	tmplen = bss->ssid_len;
-	ssid->header.len = cpu_to_le16(tmplen);
-	memcpy(ssid->ssid, bss->ssid, tmplen);
-	pos += sizeof(ssid->header) + tmplen;
-
-	phy = (struct mrvlietypes_phyparamset *) pos;
-	phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
-	tmplen = sizeof(phy->fh_ds.dsparamset);
-	phy->header.len = cpu_to_le16(tmplen);
-	memcpy(&phy->fh_ds.dsparamset,
-	       &bss->phyparamset.dsparamset.currentchan,
-	       tmplen);
-	pos += sizeof(phy->header) + tmplen;
-
-	ss = (struct mrvlietypes_ssparamset *) pos;
-	ss->header.type = cpu_to_le16(TLV_TYPE_CF);
-	tmplen = sizeof(ss->cf_ibss.cfparamset);
-	ss->header.len = cpu_to_le16(tmplen);
-	pos += sizeof(ss->header) + tmplen;
-
-	rates = (struct mrvlietypes_ratesparamset *) pos;
-	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
-	memcpy(&rates->rates, &bss->rates, MAX_RATES);
-	tmplen = MAX_RATES;
-	if (get_common_rates(priv, rates->rates, &tmplen)) {
-		ret = -1;
-		goto done;
-	}
-	pos += sizeof(rates->header) + tmplen;
-	rates->header.len = cpu_to_le16(tmplen);
-	lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
-
-	/* Copy the infra. association rates into Current BSS state structure */
-	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-	memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
-
-	/* Set MSB on basic rates as the firmware requires, but _after_
-	 * copying to current bss rates.
-	 */
-	lbs_set_basic_rate_flags(rates->rates, tmplen);
-
-	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
-		rsn = (struct mrvlietypes_rsnparamset *) pos;
-		/* WPA_IE or WPA2_IE */
-		rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
-		tmplen = (u16) assoc_req->wpa_ie[1];
-		rsn->header.len = cpu_to_le16(tmplen);
-		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
-		lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
-			sizeof(rsn->header) + tmplen);
-		pos += sizeof(rsn->header) + tmplen;
-	}
-
-	/* update curbssparams */
-	priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
-
-	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
-		ret = -1;
-		goto done;
-	}
-
-	cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
-
-	/* set the capability info */
-	tmpcap = (bss->capability & CAPINFO_MASK);
-	if (bss->mode == IW_MODE_INFRA)
-		tmpcap |= WLAN_CAPABILITY_ESS;
-	passo->capability = cpu_to_le16(tmpcap);
-	lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-int lbs_ret_80211_associate(struct lbs_private *priv,
-			      struct cmd_ds_command *resp)
-{
-	int ret = 0;
-	union iwreq_data wrqu;
-	struct ieeetypes_assocrsp *passocrsp;
-	struct bss_descriptor *bss;
-	u16 status_code;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	if (!priv->in_progress_assoc_req) {
-		lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
-		ret = -1;
-		goto done;
-	}
-	bss = &priv->in_progress_assoc_req->bss;
-
-	passocrsp = (struct ieeetypes_assocrsp *) &resp->params;
-
-	/*
-	 * Older FW versions map the IEEE 802.11 Status Code in the association
-	 * response to the following values returned in passocrsp->statuscode:
-	 *
-	 *    IEEE Status Code                Marvell Status Code
-	 *    0                       ->      0x0000 ASSOC_RESULT_SUCCESS
-	 *    13                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    14                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    15                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    16                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    others                  ->      0x0003 ASSOC_RESULT_REFUSED
-	 *
-	 * Other response codes:
-	 *    0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
-	 *    0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
-	 *                                    association response from the AP)
-	 */
-
-	status_code = le16_to_cpu(passocrsp->statuscode);
-	switch (status_code) {
-	case 0x00:
-		break;
-	case 0x01:
-		lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
-		break;
-	case 0x02:
-		lbs_deb_assoc("ASSOC_RESP: internal timer "
-			"expired while waiting for the AP\n");
-		break;
-	case 0x03:
-		lbs_deb_assoc("ASSOC_RESP: association "
-			"refused by AP\n");
-		break;
-	case 0x04:
-		lbs_deb_assoc("ASSOC_RESP: authentication "
-			"refused by AP\n");
-		break;
-	default:
-		lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
-			" unknown\n", status_code);
-		break;
-	}
-
-	if (status_code) {
-		lbs_mac_event_disconnected(priv);
-		ret = -1;
-		goto done;
-	}
-
-	lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
-		le16_to_cpu(resp->size) - S_DS_GEN);
-
-	/* Send a Media Connected event, according to the Spec */
-	priv->connect_status = LBS_CONNECTED;
-
-	/* Update current SSID and BSSID */
-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
-	priv->curbssparams.ssid_len = bss->ssid_len;
-	memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
-	priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
-	priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
-
-	memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
-	memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
-	priv->nextSNRNF = 0;
-	priv->numSNRNF = 0;
-
-	netif_carrier_on(priv->dev);
-	if (!priv->tx_pending_len)
-		netif_wake_queue(priv->dev);
-
-	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
-{
-	int ret = 0;
-	u16 command = le16_to_cpu(resp->command);
-	u16 result = le16_to_cpu(resp->result);
-	struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
-	union iwreq_data wrqu;
-	struct bss_descriptor *bss;
-	DECLARE_SSID_BUF(ssid);
-
-	lbs_deb_enter(LBS_DEB_JOIN);
-
-	adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp;
-
-	if (!priv->in_progress_assoc_req) {
-		lbs_deb_join("ADHOC_RESP: no in-progress association "
-			"request\n");
-		ret = -1;
-		goto done;
-	}
-	bss = &priv->in_progress_assoc_req->bss;
-
-	/*
-	 * Join result code 0 --> SUCCESS
-	 */
-	if (result) {
-		lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
-		if (priv->connect_status == LBS_CONNECTED)
-			lbs_mac_event_disconnected(priv);
-		ret = -1;
-		goto done;
-	}
-
-	/* Send a Media Connected event, according to the Spec */
-	priv->connect_status = LBS_CONNECTED;
-
-	if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
-		/* Update the created network descriptor with the new BSSID */
-		memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN);
-	}
-
-	/* Set the BSSID from the joined/started descriptor */
-	memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
-	/* Set the new SSID to current SSID */
-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
-	priv->curbssparams.ssid_len = bss->ssid_len;
-
-	netif_carrier_on(priv->dev);
-	if (!priv->tx_pending_len)
-		netif_wake_queue(priv->dev);
-
-	memset(&wrqu, 0, sizeof(wrqu));
-	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
-	lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
-		     print_ssid(ssid, bss->ssid, bss->ssid_len),
-		     priv->curbssparams.bssid,
-		     priv->curbssparams.channel);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-	return ret;
-}
-
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/assoc.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/assoc.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/assoc.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/assoc.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,22 +8,9 @@
 void lbs_association_worker(struct work_struct *work);
 struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
 
-struct cmd_ds_command;
-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
-					struct cmd_ds_command *cmd,
-					void *pdata_buf);
-
 int lbs_adhoc_stop(struct lbs_private *priv);
 
 int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
 				 u8 bssid[ETH_ALEN], u16 reason);
-int lbs_cmd_80211_associate(struct lbs_private *priv,
-				     struct cmd_ds_command *cmd,
-				     void *pdata_buf);
-
-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
-					struct cmd_ds_command *resp);
-int lbs_ret_80211_associate(struct lbs_private *priv,
-				     struct cmd_ds_command *resp);
 
 #endif /* _LBS_ASSOC_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/cmd.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/cmd.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/cmd.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/cmd.c	2009-09-09 18:13:59.000000000 -0400
@@ -119,11 +119,30 @@
 	lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
 		    cmd.hwifversion, cmd.version);
 
+	/* Determine mesh_fw_ver from fwrelease and fwcapinfo */
+	/* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */
+	/* 5.110.22 have mesh command with 0xa3 command id */
+	/* 10.0.0.p0 FW brings in mesh config command with different id */
+	/* Check FW version MSB and initialize mesh_fw_ver */
+	if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
+		priv->mesh_fw_ver = MESH_FW_OLD;
+	else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
+		(priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK))
+		priv->mesh_fw_ver = MESH_FW_NEW;
+	else
+		priv->mesh_fw_ver = MESH_NONE;
+
 	/* Clamp region code to 8-bit since FW spec indicates that it should
 	 * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
 	 * returns non-zero high 8 bits here.
+	 *
+	 * Firmware version 4.0.102 used in CF8381 has region code shifted.  We
+	 * need to check for this problem and handle it properly.
 	 */
-	priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
+	if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4)
+		priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF;
+	else
+		priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
 
 	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
 		/* use the region code to search for the index */
@@ -1036,17 +1055,26 @@
 				  uint16_t action, uint16_t type)
 {
 	int ret;
+	u16 command = CMD_MESH_CONFIG_OLD;
 
 	lbs_deb_enter(LBS_DEB_CMD);
 
-	cmd->hdr.command = cpu_to_le16(CMD_MESH_CONFIG);
+	/*
+	 * Command id is 0xac for v10 FW along with mesh interface
+	 * id in bits 14-13-12.
+	 */
+	if (priv->mesh_fw_ver == MESH_FW_NEW)
+		command = CMD_MESH_CONFIG |
+			  (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
+
+	cmd->hdr.command = cpu_to_le16(command);
 	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
 	cmd->hdr.result = 0;
 
 	cmd->type = cpu_to_le16(type);
 	cmd->action = cpu_to_le16(action);
 
-	ret = lbs_cmd_with_response(priv, CMD_MESH_CONFIG, cmd);
+	ret = lbs_cmd_with_response(priv, command, cmd);
 
 	lbs_deb_leave(LBS_DEB_CMD);
 	return ret;
@@ -1198,8 +1226,7 @@
 	command = le16_to_cpu(cmd->command);
 
 	/* These commands take longer */
-	if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE ||
-	    command == CMD_802_11_AUTHENTICATE)
+	if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE)
 		timeo = 5 * HZ;
 
 	lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
@@ -1393,15 +1420,6 @@
 		ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
 		break;
 
-	case CMD_802_11_ASSOCIATE:
-	case CMD_802_11_REASSOCIATE:
-		ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
-		break;
-
-	case CMD_802_11_AUTHENTICATE:
-		ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
-		break;
-
 	case CMD_MAC_REG_ACCESS:
 	case CMD_BBP_REG_ACCESS:
 	case CMD_RF_REG_ACCESS:
@@ -1448,8 +1466,8 @@
 		break;
 	case CMD_802_11_LED_GPIO_CTRL:
 		{
-			struct mrvlietypes_ledgpio *gpio =
-			    (struct mrvlietypes_ledgpio*)
+			struct mrvl_ie_ledgpio *gpio =
+			    (struct mrvl_ie_ledgpio*)
 			    cmdptr->params.ledgpio.data;
 
 			memmove(&cmdptr->params.ledgpio,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/cmdresp.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/cmdresp.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/cmdresp.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/cmdresp.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,7 +5,7 @@
 #include <linux/delay.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
-
+#include <asm/unaligned.h>
 #include <net/iw_handler.h>
 
 #include "host.h"
@@ -154,11 +154,11 @@
 	lbs_deb_enter(LBS_DEB_CMD);
 
 	/* store the non average value */
-	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
-	priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
+	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
+	priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor);
 
-	priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
-	priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
+	priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
+	priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor);
 
 	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
 	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
@@ -210,12 +210,6 @@
 		ret = lbs_ret_reg_access(priv, respcmd, resp);
 		break;
 
-	case CMD_RET_802_11_ASSOCIATE:
-	case CMD_RET(CMD_802_11_ASSOCIATE):
-	case CMD_RET(CMD_802_11_REASSOCIATE):
-		ret = lbs_ret_80211_associate(priv, resp);
-		break;
-
 	case CMD_RET(CMD_802_11_SET_AFC):
 	case CMD_RET(CMD_802_11_GET_AFC):
 		spin_lock_irqsave(&priv->driver_lock, flags);
@@ -225,7 +219,6 @@
 
 		break;
 
-	case CMD_RET(CMD_802_11_AUTHENTICATE):
 	case CMD_RET(CMD_802_11_BEACON_STOP):
 		break;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/debugfs.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/debugfs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/debugfs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/debugfs.c	2009-09-09 18:13:59.000000000 -0400
@@ -183,12 +183,12 @@
  */
 static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
 {
-	struct mrvlietypesheader *tlv_h;
+	struct mrvl_ie_header *tlv_h;
 	uint16_t length;
 	ssize_t pos = 0;
 
 	while (pos < size) {
-		tlv_h = (struct mrvlietypesheader *) tlv;
+		tlv_h = (struct mrvl_ie_header *) tlv;
 		if (!tlv_h->len)
 			return NULL;
 		if (tlv_h->type == cpu_to_le16(tlv_type))
@@ -206,7 +206,7 @@
 				  size_t count, loff_t *ppos)
 {
 	struct cmd_ds_802_11_subscribe_event *subscribed;
-	struct mrvlietypes_thresholds *got;
+	struct mrvl_ie_thresholds *got;
 	struct lbs_private *priv = file->private_data;
 	ssize_t ret = 0;
 	size_t pos = 0;
@@ -259,7 +259,7 @@
 				   loff_t *ppos)
 {
 	struct cmd_ds_802_11_subscribe_event *events;
-	struct mrvlietypes_thresholds *tlv;
+	struct mrvl_ie_thresholds *tlv;
 	struct lbs_private *priv = file->private_data;
 	ssize_t buf_size;
 	int value, freq, new_mask;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/defs.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/defs.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/defs.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/defs.h	2009-09-09 18:13:59.000000000 -0400
@@ -227,6 +227,22 @@
 #define TxPD_CONTROL_WDS_FRAME (1<<17)
 #define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME
 
+/** Mesh interface ID */
+#define MESH_IFACE_ID					0x0001
+/** Mesh id should be in bits 14-13-12 */
+#define MESH_IFACE_BIT_OFFSET				0x000c
+/** Mesh enable bit in FW capability */
+#define MESH_CAPINFO_ENABLE_MASK			(1<<16)
+
+/** FW definition from Marvell v4 */
+#define MRVL_FW_V4					(0x04)
+/** FW definition from Marvell v5 */
+#define MRVL_FW_V5					(0x05)
+/** FW definition from Marvell v10 */
+#define MRVL_FW_V10					(0x0a)
+/** FW major revision definition */
+#define MRVL_FW_MAJOR_REV(x)				((x)>>24)
+
 /** RxPD status */
 
 #define MRVDRV_RXPD_STATUS_OK                0x0001
@@ -380,6 +396,13 @@
 	KEY_INFO_WPA_ENABLED = 0x04
 };
 
+/** mesh_fw_ver */
+enum _mesh_fw_ver {
+	MESH_NONE = 0, /* MESH is not supported */
+	MESH_FW_OLD,   /* MESH is supported in FW V5 */
+	MESH_FW_NEW,   /* MESH is supported in FW V10 and newer */
+};
+
 /* Default values for fwt commands. */
 #define FWT_DEFAULT_METRIC 0
 #define FWT_DEFAULT_DIR 1
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/dev.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/dev.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/dev.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/dev.h	2009-09-09 18:13:59.000000000 -0400
@@ -101,6 +101,7 @@
 /** Private structure for the MV device */
 struct lbs_private {
 	int mesh_open;
+	int mesh_fw_ver;
 	int infra_open;
 	int mesh_autostart_enabled;
 
@@ -337,7 +338,7 @@
 	u32 rssi;
 	u32 channel;
 	u16 beaconperiod;
-	u32 atimwindow;
+	__le16 atimwindow;
 
 	/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
 	u8 mode;
@@ -347,10 +348,10 @@
 
 	unsigned long last_scanned;
 
-	union ieeetypes_phyparamset phyparamset;
-	union IEEEtypes_ssparamset ssparamset;
+	union ieee_phy_param_set phy;
+	union ieee_ss_param_set ss;
 
-	struct ieeetypes_countryinfofullset countryinfo;
+	struct ieee_ie_country_info_full_set countryinfo;
 
 	u8 wpa_ie[MAX_WPA_IE_LEN];
 	size_t wpa_ie_len;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/hostcmd.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/hostcmd.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/hostcmd.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/hostcmd.h	2009-09-09 18:13:59.000000000 -0400
@@ -13,8 +13,19 @@
 
 /* TxPD descriptor */
 struct txpd {
-	/* Current Tx packet status */
-	__le32 tx_status;
+	/* union to cope up with later FW revisions */
+	union {
+		/* Current Tx packet status */
+		__le32 tx_status;
+		struct {
+			/* BSS type: client, AP, etc. */
+			u8 bss_type;
+			/* BSS number */
+			u8 bss_num;
+			/* Reserved */
+			__le16 reserved;
+		} bss;
+	} u;
 	/* Tx control */
 	__le32 tx_control;
 	__le32 tx_packet_location;
@@ -36,8 +47,17 @@
 
 /* RxPD Descriptor */
 struct rxpd {
-	/* Current Rx packet status */
-	__le16 status;
+	/* union to cope up with later FW revisions */
+	union {
+		/* Current Rx packet status */
+		__le16 status;
+		struct {
+			/* BSS type: client, AP, etc. */
+			u8 bss_type;
+			/* BSS number */
+			u8 bss_num;
+		} __attribute__ ((packed)) bss;
+	} __attribute__ ((packed)) u;
 
 	/* SNR */
 	u8 snr;
@@ -230,7 +250,9 @@
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_authenticate {
-	u8 macaddr[ETH_ALEN];
+	struct cmd_header hdr;
+
+	u8 bssid[ETH_ALEN];
 	u8 authtype;
 	u8 reserved[10];
 } __attribute__ ((packed));
@@ -243,22 +265,23 @@
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_associate {
-	u8 peerstaaddr[6];
+	struct cmd_header hdr;
+
+	u8 bssid[6];
 	__le16 capability;
 	__le16 listeninterval;
 	__le16 bcnperiod;
 	u8 dtimperiod;
-
-#if 0
-	mrvlietypes_ssidparamset_t ssidParamSet;
-	mrvlietypes_phyparamset_t phyparamset;
-	mrvlietypes_ssparamset_t ssparamset;
-	mrvlietypes_ratesparamset_t ratesParamSet;
-#endif
+	u8 iebuf[512];    /* Enough for required and most optional IEs */
 } __attribute__ ((packed));
 
-struct cmd_ds_802_11_associate_rsp {
-	struct ieeetypes_assocrsp assocRsp;
+struct cmd_ds_802_11_associate_response {
+	struct cmd_header hdr;
+
+	__le16 capability;
+	__le16 statuscode;
+	__le16 aid;
+	u8 iebuf[512];
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_set_wep {
@@ -515,9 +538,11 @@
 	u8 bsstype;
 	__le16 beaconperiod;
 	u8 dtimperiod;   /* Reserved on v9 and later */
-	union IEEEtypes_ssparamset ssparamset;
-	union ieeetypes_phyparamset phyparamset;
-	__le16 probedelay;
+	struct ieee_ie_ibss_param_set ibss;
+	u8 reserved1[4];
+	struct ieee_ie_ds_param_set ds;
+	u8 reserved2[4];
+	__le16 probedelay;  /* Reserved on v9 and later */
 	__le16 capability;
 	u8 rates[MAX_RATES];
 	u8 tlv_memory_size_pad[100];
@@ -538,8 +563,10 @@
 	u8 dtimperiod;
 	__le64 timestamp;
 	__le64 localtime;
-	union ieeetypes_phyparamset phyparamset;
-	union IEEEtypes_ssparamset ssparamset;
+	struct ieee_ie_ds_param_set ds;
+	u8 reserved1[4];
+	struct ieee_ie_ibss_param_set ibss;
+	u8 reserved2[4];
 	__le16 capability;
 	u8 rates[MAX_RATES];
 
@@ -745,8 +772,6 @@
 	/* command Body */
 	union {
 		struct cmd_ds_802_11_ps_mode psmode;
-		struct cmd_ds_802_11_associate associate;
-		struct cmd_ds_802_11_authenticate auth;
 		struct cmd_ds_802_11_get_stat gstat;
 		struct cmd_ds_802_3_get_stat gstat_8023;
 		struct cmd_ds_802_11_rf_antenna rant;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/host.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/host.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/host.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/host.h	2009-09-09 18:13:59.000000000 -0400
@@ -83,8 +83,11 @@
 #define CMD_FWT_ACCESS				0x0095
 #define CMD_802_11_MONITOR_MODE			0x0098
 #define CMD_MESH_ACCESS				0x009b
-#define CMD_MESH_CONFIG				0x00a3
+#define CMD_MESH_CONFIG_OLD			0x00a3
+#define CMD_MESH_CONFIG				0x00ac
 #define	CMD_SET_BOOT2_VER			0x00a5
+#define	CMD_FUNC_INIT				0x00a9
+#define	CMD_FUNC_SHUTDOWN			0x00aa
 #define CMD_802_11_BEACON_CTRL			0x00b0
 
 /* For the IEEE Power Save */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_cs.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_cs.c	2012-03-22 19:17:25.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_cs.c	2012-03-22 20:13:04.000000000 -0400
@@ -273,7 +273,28 @@
  */
 #define IF_CS_PRODUCT_ID		0x0000001C
 #define IF_CS_CF8385_B1_REV		0x12
+#define IF_CS_CF8381_B3_REV		0x04
 
+/*
+ * Used to detect other cards than CF8385 since their revisions of silicon
+ * doesn't match those from CF8385, eg. CF8381 B3 works with this driver.
+ */
+#define CF8381_MANFID		0x02db
+#define CF8381_CARDID		0x6064
+#define CF8385_MANFID		0x02df
+#define CF8385_CARDID		0x8103
+
+static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev)
+{
+	return (p_dev->manf_id == CF8381_MANFID &&
+		p_dev->card_id == CF8381_CARDID);
+}
+
+static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev)
+{
+	return (p_dev->manf_id == CF8385_MANFID &&
+		p_dev->card_id == CF8385_CARDID);
+}
 
 /********************************************************************/
 /* I/O and interrupt handling                                       */
@@ -757,6 +778,7 @@
 static int if_cs_probe(struct pcmcia_device *p_dev)
 {
 	int ret = -ENOMEM;
+	unsigned int prod_id;
 	struct lbs_private *priv;
 	struct if_cs_card *card;
 	/* CIS parsing */
@@ -859,7 +881,14 @@
 	       p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1);
 
 	/* Check if we have a current silicon */
-	if (if_cs_read8(card, IF_CS_PRODUCT_ID) < IF_CS_CF8385_B1_REV) {
+	prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
+	if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) {
+		lbs_pr_err("old chips like 8381 rev B3 aren't supported\n");
+		ret = -ENODEV;
+		goto out2;
+	}
+
+	if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) {
 		lbs_pr_err("old chips like 8385 rev B1 aren't supported\n");
 		ret = -ENODEV;
 		goto out2;
@@ -950,7 +979,8 @@
 /********************************************************************/
 
 static struct pcmcia_device_id if_cs_ids[] = {
-	PCMCIA_DEVICE_MANF_CARD(0x02df, 0x8103),
+	PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID),
+	PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID),
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_sdio.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_sdio.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_sdio.c	2012-03-22 19:17:28.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_sdio.c	2012-03-22 20:13:06.000000000 -0400
@@ -39,8 +39,24 @@
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
+#include "cmd.h"
 #include "if_sdio.h"
 
+/* The if_sdio_remove() callback function is called when
+ * user removes this module from kernel space or ejects
+ * the card from the slot. The driver handles these 2 cases
+ * differently for SD8688 combo chip.
+ * If the user is removing the module, the FUNC_SHUTDOWN
+ * command for SD8688 is sent to the firmware.
+ * If the card is removed, there is no need to send this command.
+ *
+ * The variable 'user_rmmod' is used to distinguish these two
+ * scenarios. This flag is initialized as FALSE in case the card
+ * is removed, and will be set to TRUE for module removal when
+ * module_exit function is called.
+ */
+static u8 user_rmmod;
+
 static char *lbs_helper_name = NULL;
 module_param_named(helper_name, lbs_helper_name, charp, 0644);
 
@@ -48,8 +64,11 @@
 module_param_named(fw_name, lbs_fw_name, charp, 0644);
 
 static const struct sdio_device_id if_sdio_ids[] = {
-	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
-	{ /* end: all zeroes */						},
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL,
+			SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
+	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL,
+			SDIO_DEVICE_ID_MARVELL_8688WLAN) },
+	{ /* end: all zeroes */				},
 };
 
 MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
@@ -63,12 +82,17 @@
 static struct if_sdio_model if_sdio_models[] = {
 	{
 		/* 8385 */
-		.model = 0x04,
+		.model = IF_SDIO_MODEL_8385,
 		.helper = "/*(DEBLOBBED)*/",
 	},
 	{
 		/* 8686 */
-		.model = 0x0B,
+		.model = IF_SDIO_MODEL_8686,
+		.helper = "/*(DEBLOBBED)*/",
+	},
+	{
+		/* 8688 */
+		.model = IF_SDIO_MODEL_8688,
 		.helper = "/*(DEBLOBBED)*/",
 	},
 };
@@ -85,6 +109,7 @@
 
 	int			model;
 	unsigned long		ioport;
+	unsigned int		scratch_reg;
 
 	const char		*helper;
 	const char		*firmware;
@@ -96,25 +121,29 @@
 
 	struct workqueue_struct	*workqueue;
 	struct work_struct	packet_worker;
+
+	u8			rx_unit;
 };
 
 /********************************************************************/
 /* I/O                                                              */
 /********************************************************************/
 
+/*
+ *  For SD8385/SD8686, this function reads firmware status after
+ *  the image is downloaded, or reads RX packet length when
+ *  interrupt (with IF_SDIO_H_INT_UPLD bit set) is received.
+ *  For SD8688, this function reads firmware status only.
+ */
 static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
 {
-	int ret, reg;
+	int ret;
 	u16 scratch;
 
-	if (card->model == 0x04)
-		reg = IF_SDIO_SCRATCH_OLD;
-	else
-		reg = IF_SDIO_SCRATCH;
-
-	scratch = sdio_readb(card->func, reg, &ret);
+	scratch = sdio_readb(card->func, card->scratch_reg, &ret);
 	if (!ret)
-		scratch |= sdio_readb(card->func, reg + 1, &ret) << 8;
+		scratch |= sdio_readb(card->func, card->scratch_reg + 1,
+					&ret) << 8;
 
 	if (err)
 		*err = ret;
@@ -125,6 +154,46 @@
 	return scratch;
 }
 
+static u8 if_sdio_read_rx_unit(struct if_sdio_card *card)
+{
+	int ret;
+	u8 rx_unit;
+
+	rx_unit = sdio_readb(card->func, IF_SDIO_RX_UNIT, &ret);
+
+	if (ret)
+		rx_unit = 0;
+
+	return rx_unit;
+}
+
+static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err)
+{
+	int ret;
+	u16 rx_len;
+
+	switch (card->model) {
+	case IF_SDIO_MODEL_8385:
+	case IF_SDIO_MODEL_8686:
+		rx_len = if_sdio_read_scratch(card, &ret);
+		break;
+	case IF_SDIO_MODEL_8688:
+	default: /* for newer chipsets */
+		rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret);
+		if (!ret)
+			rx_len <<= card->rx_unit;
+		else
+			rx_len = 0xffff;	/* invalid length */
+
+		break;
+	}
+
+	if (err)
+		*err = ret;
+
+	return rx_len;
+}
+
 static int if_sdio_handle_cmd(struct if_sdio_card *card,
 		u8 *buffer, unsigned size)
 {
@@ -205,7 +274,7 @@
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	if (card->model == 0x04) {
+	if (card->model == IF_SDIO_MODEL_8385) {
 		event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
 		if (ret)
 			goto out;
@@ -243,7 +312,7 @@
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
-	size = if_sdio_read_scratch(card, &ret);
+	size = if_sdio_read_rx_len(card, &ret);
 	if (ret)
 		goto out;
 
@@ -486,7 +555,6 @@
 	ret = 0;
 
 release:
-	sdio_set_block_size(card->func, 0);
 	sdio_release_host(card->func);
 	kfree(chunk_buffer);
 release_fw:
@@ -622,7 +690,6 @@
 	ret = 0;
 
 release:
-	sdio_set_block_size(card->func, 0);
 	sdio_release_host(card->func);
 	kfree(chunk_buffer);
 release_fw:
@@ -651,6 +718,8 @@
 	if (ret)
 		goto out;
 
+	lbs_deb_sdio("firmware status = %#x\n", scratch);
+
 	if (scratch == IF_SDIO_FIRMWARE_OK) {
 		lbs_deb_sdio("firmware already loaded\n");
 		goto success;
@@ -665,6 +734,9 @@
 		goto out;
 
 success:
+	sdio_claim_host(card->func);
+	sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
+	sdio_release_host(card->func);
 	ret = 0;
 
 out:
@@ -818,10 +890,10 @@
 		if (sscanf(func->card->info[i],
 				"ID: %x", &model) == 1)
 			break;
-               if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
-                       model = 4;
-                       break;
-               }
+		if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
+			model = IF_SDIO_MODEL_8385;
+			break;
+		}
 	}
 
 	if (i == func->card->num_info) {
@@ -835,6 +907,20 @@
 
 	card->func = func;
 	card->model = model;
+
+	switch (card->model) {
+	case IF_SDIO_MODEL_8385:
+		card->scratch_reg = IF_SDIO_SCRATCH_OLD;
+		break;
+	case IF_SDIO_MODEL_8686:
+		card->scratch_reg = IF_SDIO_SCRATCH;
+		break;
+	case IF_SDIO_MODEL_8688:
+	default: /* for newer chipsets */
+		card->scratch_reg = IF_SDIO_FW_STATUS;
+		break;
+	}
+
 	spin_lock_init(&card->lock);
 	card->workqueue = create_workqueue("libertas_sdio");
 	INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
@@ -912,15 +998,40 @@
 
 	priv->fw_ready = 1;
 
+	sdio_claim_host(func);
+
+	/*
+	 * Get rx_unit if the chip is SD8688 or newer.
+	 * SD8385 & SD8686 do not have rx_unit.
+	 */
+	if ((card->model != IF_SDIO_MODEL_8385)
+			&& (card->model != IF_SDIO_MODEL_8686))
+		card->rx_unit = if_sdio_read_rx_unit(card);
+	else
+		card->rx_unit = 0;
+
 	/*
 	 * Enable interrupts now that everything is set up
 	 */
-	sdio_claim_host(func);
 	sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
 	sdio_release_host(func);
 	if (ret)
 		goto reclaim;
 
+	/*
+	 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
+	 */
+	if (card->model == IF_SDIO_MODEL_8688) {
+		struct cmd_header cmd;
+
+		memset(&cmd, 0, sizeof(cmd));
+
+		lbs_deb_sdio("send function INIT command\n");
+		if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
+				lbs_cmd_copyback, (unsigned long) &cmd))
+			lbs_pr_alert("CMD_FUNC_INIT cmd failed\n");
+	}
+
 	ret = lbs_start_card(priv);
 	if (ret)
 		goto err_activate_card;
@@ -966,6 +1077,22 @@
 
 	card = sdio_get_drvdata(func);
 
+	if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) {
+		/*
+		 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
+		 * multiple functions
+		 */
+		struct cmd_header cmd;
+
+		memset(&cmd, 0, sizeof(cmd));
+
+		lbs_deb_sdio("send function SHUTDOWN command\n");
+		if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN,
+				&cmd, sizeof(cmd), lbs_cmd_copyback,
+				(unsigned long) &cmd))
+			lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n");
+	}
+
 	card->priv->surpriseremoved = 1;
 
 	lbs_deb_sdio("call remove card\n");
@@ -1013,6 +1140,9 @@
 
 	ret = sdio_register_driver(&if_sdio_driver);
 
+	/* Clear the flag in case user removes the card. */
+	user_rmmod = 0;
+
 	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
 
 	return ret;
@@ -1022,6 +1152,9 @@
 {
 	lbs_deb_enter(LBS_DEB_SDIO);
 
+	/* Set the flag as user is removing this module. */
+	user_rmmod = 1;
+
 	sdio_unregister_driver(&if_sdio_driver);
 
 	lbs_deb_leave(LBS_DEB_SDIO);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_sdio.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_sdio.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_sdio.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_sdio.h	2009-09-09 18:13:59.000000000 -0400
@@ -12,6 +12,10 @@
 #ifndef _LBS_IF_SDIO_H
 #define _LBS_IF_SDIO_H
 
+#define IF_SDIO_MODEL_8385	0x04
+#define IF_SDIO_MODEL_8686	0x0b
+#define IF_SDIO_MODEL_8688	0x10
+
 #define IF_SDIO_IOPORT		0x00
 
 #define IF_SDIO_H_INT_MASK	0x04
@@ -38,8 +42,14 @@
 
 #define IF_SDIO_SCRATCH		0x34
 #define IF_SDIO_SCRATCH_OLD	0x80fe
+#define IF_SDIO_FW_STATUS	0x40
 #define   IF_SDIO_FIRMWARE_OK	0xfedc
 
+#define IF_SDIO_RX_LEN		0x42
+#define IF_SDIO_RX_UNIT		0x43
+
 #define IF_SDIO_EVENT           0x80fc
 
+#define IF_SDIO_BLOCK_SIZE	256
+
 #endif
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_spi.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_spi.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_spi.c	2012-03-22 19:17:31.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_spi.c	2012-03-22 20:13:09.000000000 -0400
@@ -19,7 +19,6 @@
 
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
-#include <linux/gpio.h>
 #include <linux/jiffies.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
@@ -44,20 +43,13 @@
 	struct lbs_private		*priv;
 	struct libertas_spi_platform_data *pdata;
 
-	char				helper_fw_name[FIRMWARE_NAME_MAX];
-	char				main_fw_name[FIRMWARE_NAME_MAX];
+	char				helper_fw_name[IF_SPI_FW_NAME_MAX];
+	char				main_fw_name[IF_SPI_FW_NAME_MAX];
 
 	/* The card ID and card revision, as reported by the hardware. */
 	u16				card_id;
 	u8				card_rev;
 
-	/* Pin number for our GPIO chip-select. */
-	/* TODO: Once the generic SPI layer has some additional features, we
-	 * should take this out and use the normal chip select here.
-	 * We need support for chip select delays, and not dropping chipselect
-	 * after each word. */
-	int				gpio_cs;
-
 	/* The last time that we initiated an SPU operation */
 	unsigned long			prev_xfer_time;
 
@@ -119,9 +111,6 @@
  * First we have to put a SPU register name on the bus. Then we can
  * either read from or write to that register.
  *
- * For 16-bit transactions, byte order on the bus is big-endian.
- * We don't have to worry about that here, though.
- * The translation takes place in the SPI routines.
  */
 
 static void spu_transaction_init(struct if_spi_card *card)
@@ -133,12 +122,10 @@
 		 * If not, we have to busy-wait to be on the safe side. */
 		ndelay(400);
 	}
-	gpio_set_value(card->gpio_cs, 0); /* assert CS */
 }
 
 static void spu_transaction_finish(struct if_spi_card *card)
 {
-	gpio_set_value(card->gpio_cs, 1); /* drop CS */
 	card->prev_xfer_time = jiffies;
 }
 
@@ -147,7 +134,14 @@
 static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
 {
 	int err = 0;
-	u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK;
+	u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
+	struct spi_message m;
+	struct spi_transfer reg_trans;
+	struct spi_transfer data_trans;
+
+	spi_message_init(&m);
+	memset(&reg_trans, 0, sizeof(reg_trans));
+	memset(&data_trans, 0, sizeof(data_trans));
 
 	/* You must give an even number of bytes to the SPU, even if it
 	 * doesn't care about the last one.  */
@@ -156,29 +150,26 @@
 	spu_transaction_init(card);
 
 	/* write SPU register index */
-	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
-	if (err)
-		goto out;
+	reg_trans.tx_buf = &reg_out;
+	reg_trans.len = sizeof(reg_out);
 
-	err = spi_write(card->spi, buf, len);
+	data_trans.tx_buf = buf;
+	data_trans.len = len;
 
-out:
+	spi_message_add_tail(&reg_trans, &m);
+	spi_message_add_tail(&data_trans, &m);
+
+	err = spi_sync(card->spi, &m);
 	spu_transaction_finish(card);
 	return err;
 }
 
 static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
 {
-	return spu_write(card, reg, (u8 *)&val, sizeof(u16));
-}
+	u16 buff;
 
-static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val)
-{
-	/* The lower 16 bits are written first. */
-	u16 out[2];
-	out[0] = val & 0xffff;
-	out[1] = (val & 0xffff0000) >> 16;
-	return spu_write(card, reg, (u8 *)&out, sizeof(u32));
+	buff = cpu_to_le16(val);
+	return spu_write(card, reg, (u8 *)&buff, sizeof(u16));
 }
 
 static inline int spu_reg_is_port_reg(u16 reg)
@@ -195,10 +186,13 @@
 
 static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
 {
-	unsigned int i, delay;
+	unsigned int delay;
 	int err = 0;
-	u16 zero = 0;
-	u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
+	u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
+	struct spi_message m;
+	struct spi_transfer reg_trans;
+	struct spi_transfer dummy_trans;
+	struct spi_transfer data_trans;
 
 	/* You must take an even number of bytes from the SPU, even if you
 	 * don't care about the last one.  */
@@ -206,29 +200,34 @@
 
 	spu_transaction_init(card);
 
+	spi_message_init(&m);
+	memset(&reg_trans, 0, sizeof(reg_trans));
+	memset(&dummy_trans, 0, sizeof(dummy_trans));
+	memset(&data_trans, 0, sizeof(data_trans));
+
 	/* write SPU register index */
-	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
-	if (err)
-		goto out;
+	reg_trans.tx_buf = &reg_out;
+	reg_trans.len = sizeof(reg_out);
+	spi_message_add_tail(&reg_trans, &m);
 
 	delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
 						card->spu_reg_delay;
 	if (card->use_dummy_writes) {
 		/* Clock in dummy cycles while the SPU fills the FIFO */
-		for (i = 0; i < delay / 16; ++i) {
-			err = spi_write(card->spi, (u8 *)&zero, sizeof(u16));
-			if (err)
-				return err;
-		}
+		dummy_trans.len = delay / 8;
+		spi_message_add_tail(&dummy_trans, &m);
 	} else {
 		/* Busy-wait while the SPU fills the FIFO */
-		ndelay(100 + (delay * 10));
+		reg_trans.delay_usecs =
+			DIV_ROUND_UP((100 + (delay * 10)), 1000);
 	}
 
 	/* read in data */
-	err = spi_read(card->spi, buf, len);
+	data_trans.rx_buf = buf;
+	data_trans.len = len;
+	spi_message_add_tail(&data_trans, &m);
 
-out:
+	err = spi_sync(card->spi, &m);
 	spu_transaction_finish(card);
 	return err;
 }
@@ -236,18 +235,25 @@
 /* Read 16 bits from an SPI register */
 static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
 {
-	return spu_read(card, reg, (u8 *)val, sizeof(u16));
+	u16 buf;
+	int ret;
+
+	ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
+	if (ret == 0)
+		*val = le16_to_cpup(&buf);
+	return ret;
 }
 
 /* Read 32 bits from an SPI register.
  * The low 16 bits are read first. */
 static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
 {
-	u16 buf[2];
+	u32 buf;
 	int err;
-	err = spu_read(card, reg, (u8 *)buf, sizeof(u32));
+
+	err = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
 	if (!err)
-		*val = buf[0] | (buf[1] << 16);
+		*val = le32_to_cpup(&buf);
 	return err;
 }
 
@@ -731,7 +737,7 @@
 		goto out;
 	} else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
 		lbs_pr_err("%s: error: card has %d bytes of data, but "
-			   "our maximum skb size is %u\n",
+			   "our maximum skb size is %lu\n",
 			   __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
 		err = -EINVAL;
 		goto out;
@@ -806,7 +812,6 @@
 static void if_spi_e2h(struct if_spi_card *card)
 {
 	int err = 0;
-	unsigned long flags;
 	u32 cause;
 	struct lbs_private *priv = card->priv;
 
@@ -814,10 +819,14 @@
 	if (err)
 		goto out;
 
-	spin_lock_irqsave(&priv->driver_lock, flags);
-	lbs_queue_event(priv, cause & 0xff);
-	spin_unlock_irqrestore(&priv->driver_lock, flags);
+	/* re-enable the card event interrupt */
+	spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+			~IF_SPI_HICU_CARD_EVENT);
+
+	/* generate a card interrupt */
+	spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT);
 
+	lbs_queue_event(priv, cause & 0xff);
 out:
 	if (err)
 		lbs_pr_err("%s: error %d\n", __func__, err);
@@ -862,7 +871,12 @@
 			err = if_spi_c2h_data(card);
 			if (err)
 				goto err;
-		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) {
+
+		/* workaround: in PS mode, the card does not set the Command
+		 * Download Ready bit, but it sets TX Download Ready. */
+		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
+		   (card->priv->psstate != PS_STATE_FULL_POWER &&
+		    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
 			/* This means two things. First of all,
 			 * if there was a previous command sent, the card has
 			 * successfully received it.
@@ -1006,9 +1020,9 @@
 		lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
 		return -EAFNOSUPPORT;
 	}
-	snprintf(helper_fw, FIRMWARE_NAME_MAX, "/*(DEBLOBBED)*/",
+	snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "/*(DEBLOBBED)*/",
 		 chip_id_to_device_name[i].name);
-	snprintf(main_fw, FIRMWARE_NAME_MAX, "/*(DEBLOBBED)*/",
+	snprintf(main_fw, IF_SPI_FW_NAME_MAX, "/*(DEBLOBBED)*/",
 		 chip_id_to_device_name[i].name);
 	return 0;
 }
@@ -1020,6 +1034,7 @@
 	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
 	int err = 0;
 	u32 scratch;
+	struct sched_param param = { .sched_priority = 1 };
 
 	lbs_deb_enter(LBS_DEB_SPI);
 
@@ -1043,7 +1058,6 @@
 	spi_set_drvdata(spi, card);
 	card->pdata = pdata;
 	card->spi = spi;
-	card->gpio_cs = pdata->gpio_cs;
 	card->prev_xfer_time = jiffies;
 
 	sema_init(&card->spi_ready, 0);
@@ -1052,26 +1066,18 @@
 	INIT_LIST_HEAD(&card->data_packet_list);
 	spin_lock_init(&card->buffer_lock);
 
-	/* set up GPIO CS line. TODO: use  regular CS line */
-	err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
-	if (err)
-		goto free_card;
-	err = gpio_direction_output(card->gpio_cs, 1);
-	if (err)
-		goto free_gpio;
-
 	/* Initialize the SPI Interface Unit */
 	err = spu_init(card, pdata->use_dummy_writes);
 	if (err)
-		goto free_gpio;
+		goto free_card;
 	err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
 	if (err)
-		goto free_gpio;
+		goto free_card;
 
 	/* Firmware load */
 	err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
 	if (err)
-		goto free_gpio;
+		goto free_card;
 	if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
 		lbs_deb_spi("Firmware is already loaded for "
 			    "Marvell WLAN 802.11 adapter\n");
@@ -1079,7 +1085,7 @@
 		err = if_spi_calculate_fw_names(card->card_id,
 				card->helper_fw_name, card->main_fw_name);
 		if (err)
-			goto free_gpio;
+			goto free_card;
 
 		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
 				"(chip_id = 0x%04x, chip_rev = 0x%02x) "
@@ -1090,23 +1096,23 @@
 				spi->max_speed_hz);
 		err = if_spi_prog_helper_firmware(card);
 		if (err)
-			goto free_gpio;
+			goto free_card;
 		err = if_spi_prog_main_firmware(card);
 		if (err)
-			goto free_gpio;
+			goto free_card;
 		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
 	}
 
 	err = spu_set_interrupt_mode(card, 0, 1);
 	if (err)
-		goto free_gpio;
+		goto free_card;
 
 	/* Register our card with libertas.
 	 * This will call alloc_etherdev */
 	priv = lbs_add_card(card, &spi->dev);
 	if (!priv) {
 		err = -ENOMEM;
-		goto free_gpio;
+		goto free_card;
 	}
 	card->priv = priv;
 	priv->card = card;
@@ -1123,6 +1129,9 @@
 		lbs_pr_err("error creating SPI thread: err=%d\n", err);
 		goto remove_card;
 	}
+	if (sched_setscheduler(card->spi_thread, SCHED_FIFO, &param))
+		lbs_pr_err("Error setting scheduler, using default.\n");
+
 	err = request_irq(spi->irq, if_spi_host_interrupt,
 			IRQF_TRIGGER_FALLING, "libertas_spi", card);
 	if (err) {
@@ -1148,8 +1157,6 @@
 	if_spi_terminate_spi_thread(card);
 remove_card:
 	lbs_remove_card(priv); /* will call free_netdev */
-free_gpio:
-	gpio_free(card->gpio_cs);
 free_card:
 	free_if_spi_card(card);
 out:
@@ -1170,7 +1177,6 @@
 	free_irq(spi->irq, card);
 	if_spi_terminate_spi_thread(card);
 	lbs_remove_card(priv); /* will call free_netdev */
-	gpio_free(card->gpio_cs);
 	if (card->pdata->teardown)
 		card->pdata->teardown(spi);
 	free_if_spi_card(card);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_spi.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_spi.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_spi.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_spi.h	2009-09-09 18:13:59.000000000 -0400
@@ -22,6 +22,9 @@
 #define IF_SPI_CMD_BUF_SIZE 2400
 
 /***************** Firmware *****************/
+
+#define IF_SPI_FW_NAME_MAX 30
+
 struct chip_ident {
 	u16 chip_id;
 	u16 name;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/if_usb.c	2012-03-22 19:17:34.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/if_usb.c	2012-03-22 20:13:12.000000000 -0400
@@ -61,11 +61,9 @@
 {
 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
 	struct if_usb_card *cardp = priv->card;
-	char fwname[FIRMWARE_NAME_MAX];
 	int ret;
 
-	sscanf(buf, "%29s", fwname); /* FIRMWARE_NAME_MAX - 1 = 29 */
-	ret = if_usb_prog_firmware(cardp, fwname, BOOT_CMD_UPDATE_FW);
+	ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW);
 	if (ret == 0)
 		return count;
 
@@ -83,11 +81,9 @@
 {
 	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
 	struct if_usb_card *cardp = priv->card;
-	char fwname[FIRMWARE_NAME_MAX];
 	int ret;
 
-	sscanf(buf, "%29s", fwname); /* FIRMWARE_NAME_MAX - 1 = 29 */
-	ret = if_usb_prog_firmware(cardp, fwname, BOOT_CMD_UPDATE_BOOT2);
+	ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2);
 	if (ret == 0)
 		return count;
 
@@ -676,8 +672,7 @@
 		return;
 	}
 
-	if (!in_interrupt())
-		BUG();
+	BUG_ON(!in_interrupt());
 
 	spin_lock(&priv->driver_lock);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -1307,8 +1307,10 @@
 
 	lbs_update_channel(priv);
 
-	/* 5.0.16p0 is known to NOT support any mesh */
-	if (priv->fwrelease > 0x05001000) {
+	/* Check mesh FW version and appropriately send the mesh start
+	 * command
+	 */
+	if (priv->mesh_fw_ver == MESH_FW_OLD) {
 		/* Enable mesh, if supported, and work out which TLV it uses.
 		   0x100 + 291 is an unofficial value used in 5.110.20.pXX
 		   0x100 + 37 is the official value used in 5.110.21.pXX
@@ -1322,27 +1324,35 @@
 		   It's just that 5.110.20.pXX will not have done anything
 		   useful */
 
-		priv->mesh_tlv = 0x100 + 291;
+		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
 		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
 				    priv->curbssparams.channel)) {
-			priv->mesh_tlv = 0x100 + 37;
+			priv->mesh_tlv = TLV_TYPE_MESH_ID;
 			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
 					    priv->curbssparams.channel))
 				priv->mesh_tlv = 0;
 		}
-		if (priv->mesh_tlv) {
-			lbs_add_mesh(priv);
+	} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+		/* 10.0.0.pXX new firmwares should succeed with TLV
+		 * 0x100+37; Do not invoke command with old TLV.
+		 */
+		priv->mesh_tlv = TLV_TYPE_MESH_ID;
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+				    priv->curbssparams.channel))
+			priv->mesh_tlv = 0;
+	}
+	if (priv->mesh_tlv) {
+		lbs_add_mesh(priv);
 
-			if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
-				lbs_pr_err("cannot register lbs_mesh attribute\n");
+		if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
+			lbs_pr_err("cannot register lbs_mesh attribute\n");
 
-			/* While rtap isn't related to mesh, only mesh-enabled
-			 * firmware implements the rtap functionality via
-			 * CMD_802_11_MONITOR_MODE.
-			 */
-			if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
-				lbs_pr_err("cannot register lbs_rtap attribute\n");
-		}
+		/* While rtap isn't related to mesh, only mesh-enabled
+		 * firmware implements the rtap functionality via
+		 * CMD_802_11_MONITOR_MODE.
+		 */
+		if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
+			lbs_pr_err("cannot register lbs_rtap attribute\n");
 	}
 
 	lbs_debugfs_init_one(priv, dev);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/README linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/README
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/README	2012-03-22 19:17:36.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/README	2012-03-22 20:13:14.000000000 -0400
@@ -72,7 +72,7 @@
 	location that is to be read.  This parameter must be specified in
 	hexadecimal (its possible to preceed preceding the number with a "0x").
 
-	Path: /debugfs/libertas_wireless/ethX/registers/
+	Path: /sys/kernel/debug/libertas_wireless/ethX/registers/
 
 	Usage:
 		echo "0xa123" > rdmac ; cat rdmac
@@ -95,7 +95,7 @@
 sleepparams
 	This command is used to set the sleepclock configurations
 
-	Path: /debugfs/libertas_wireless/ethX/
+	Path: /sys/kernel/debug/libertas_wireless/ethX/
 
 	Usage:
 		cat sleepparams: reads the current sleepclock configuration
@@ -115,7 +115,7 @@
 	The subscribed_events directory contains the interface for the
 	subscribed events API.
 
-	Path: /debugfs/libertas_wireless/ethX/subscribed_events/
+	Path: /sys/kernel/debug/libertas_wireless/ethX/subscribed_events/
 
 	Each event is represented by a filename. Each filename consists of the
 	following three fields:
@@ -165,7 +165,7 @@
 extscan
 	This command is used to do a specific scan.
 
-	Path: /debugfs/libertas_wireless/ethX/
+	Path: /sys/kernel/debug/libertas_wireless/ethX/
 
 	Usage: echo "SSID" > extscan
 
@@ -179,7 +179,7 @@
 	Display the current contents of the driver scan table (ie. get the
 	scan results).
 
-	Path: /debugfs/libertas_wireless/ethX/
+	Path: /sys/kernel/debug/libertas_wireless/ethX/
 
 	Usage:
 		cat getscantable
@@ -188,7 +188,7 @@
 	Initiate a customized scan and retrieve the results
 
 
-	Path: /debugfs/libertas_wireless/ethX/
+	Path: /sys/kernel/debug/libertas_wireless/ethX/
 
     Usage:
        echo "[ARGS]" > setuserscan
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/rx.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/rx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/rx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/rx.c	2009-09-09 18:13:59.000000000 -0400
@@ -25,7 +25,6 @@
 } __attribute__ ((packed));
 
 struct rxpackethdr {
-	struct rxpd rx_pd;
 	struct eth803hdr eth803_hdr;
 	struct rfc1042hdr rfc1042_hdr;
 } __attribute__ ((packed));
@@ -158,10 +157,18 @@
 	if (priv->monitormode)
 		return process_rxed_802_11_packet(priv, skb);
 
-	p_rx_pkt = (struct rxpackethdr *) skb->data;
-	p_rx_pd = &p_rx_pkt->rx_pd;
-	if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME))
-		dev = priv->mesh_dev;
+	p_rx_pd = (struct rxpd *) skb->data;
+	p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
+		le32_to_cpu(p_rx_pd->pkt_ptr));
+	if (priv->mesh_dev) {
+		if (priv->mesh_fw_ver == MESH_FW_OLD) {
+			if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
+				dev = priv->mesh_dev;
+		} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+			if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID)
+				dev = priv->mesh_dev;
+		}
+	}
 
 	lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
 		 min_t(unsigned int, skb->len, 100));
@@ -174,20 +181,9 @@
 		goto done;
 	}
 
-	/*
-	 * Check rxpd status and update 802.3 stat,
-	 */
-	if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
-		lbs_deb_rx("rx err: frame received with bad status\n");
-		lbs_pr_alert("rxpd not ok\n");
-		dev->stats.rx_errors++;
-		ret = 0;
-		dev_kfree_skb(skb);
-		goto done;
-	}
-
-	lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
-	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
+	lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n",
+		skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr),
+		skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr));
 
 	lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
 		sizeof(p_rx_pkt->eth803_hdr.dest_addr));
@@ -221,14 +217,14 @@
 		/* Chop off the rxpd + the excess memory from the 802.2/llc/snap header
 		 *   that was removed
 		 */
-		hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt;
+		hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd;
 	} else {
 		lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
 			(u8 *) & p_rx_pkt->rfc1042_hdr,
 			sizeof(p_rx_pkt->rfc1042_hdr));
 
 		/* Chop off the rxpd */
-		hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt;
+		hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd;
 	}
 
 	/* Chop off the leading header bytes so the skb points to the start of
@@ -334,14 +330,6 @@
 		goto done;
 	}
 
-	/*
-	 * Check rxpd status and update 802.3 stat,
-	 */
-	if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
-		//lbs_deb_rx("rx err: frame received with bad status\n");
-		dev->stats.rx_errors++;
-	}
-
 	lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
 	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
 
@@ -353,8 +341,6 @@
 	radiotap_hdr.hdr.it_pad = 0;
 	radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
 	radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
-	if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
-		radiotap_hdr.flags |= IEEE80211_RADIOTAP_F_BADFCS;
 	radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
 	/* XXX must check no carryout */
 	radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/scan.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/scan.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/scan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/scan.c	2009-09-09 18:13:59.000000000 -0400
@@ -5,6 +5,7 @@
   *  for sending scan commands to the firmware.
   */
 #include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <asm/unaligned.h>
@@ -27,12 +28,12 @@
                              + 40)	/* 40 for WPAIE */
 
 //! Memory needed to store a max sized channel List TLV for a firmware scan
-#define CHAN_TLV_MAX_SIZE  (sizeof(struct mrvlietypesheader)    \
+#define CHAN_TLV_MAX_SIZE  (sizeof(struct mrvl_ie_header)    \
                             + (MRVDRV_MAX_CHANNELS_PER_SCAN     \
                                * sizeof(struct chanscanparamset)))
 
 //! Memory needed to store a max number/size SSID TLV for a firmware scan
-#define SSID_TLV_MAX_SIZE  (1 * sizeof(struct mrvlietypes_ssidparamset))
+#define SSID_TLV_MAX_SIZE  (1 * sizeof(struct mrvl_ie_ssid_param_set))
 
 //! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
 #define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan)	\
@@ -211,7 +212,7 @@
  */
 static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
 {
-	struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
+	struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
 
 	ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
 	ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
@@ -249,7 +250,7 @@
 				     int chan_count)
 {
 	size_t size = sizeof(struct chanscanparamset) *chan_count;
-	struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv;
+	struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv;
 
 	chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
 	memcpy(chan_tlv->chanscanparam, chan_list, size);
@@ -270,7 +271,7 @@
 static int lbs_scan_add_rates_tlv(uint8_t *tlv)
 {
 	int i;
-	struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv;
+	struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
 
 	rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
 	tlv += sizeof(rate_tlv->header);
@@ -513,12 +514,12 @@
 static int lbs_process_bss(struct bss_descriptor *bss,
 			   uint8_t **pbeaconinfo, int *bytesleft)
 {
-	struct ieeetypes_fhparamset *pFH;
-	struct ieeetypes_dsparamset *pDS;
-	struct ieeetypes_cfparamset *pCF;
-	struct ieeetypes_ibssparamset *pibss;
+	struct ieee_ie_fh_param_set *fh;
+	struct ieee_ie_ds_param_set *ds;
+	struct ieee_ie_cf_param_set *cf;
+	struct ieee_ie_ibss_param_set *ibss;
 	DECLARE_SSID_BUF(ssid);
-	struct ieeetypes_countryinfoset *pcountryinfo;
+	struct ieee_ie_country_info_set *pcountryinfo;
 	uint8_t *pos, *end, *p;
 	uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
 	uint16_t beaconsize = 0;
@@ -616,50 +617,49 @@
 			break;
 
 		case WLAN_EID_FH_PARAMS:
-			pFH = (struct ieeetypes_fhparamset *) pos;
-			memmove(&bss->phyparamset.fhparamset, pFH,
-				sizeof(struct ieeetypes_fhparamset));
+			fh = (struct ieee_ie_fh_param_set *) pos;
+			memcpy(&bss->phy.fh, fh, sizeof(*fh));
 			lbs_deb_scan("got FH IE\n");
 			break;
 
 		case WLAN_EID_DS_PARAMS:
-			pDS = (struct ieeetypes_dsparamset *) pos;
-			bss->channel = pDS->currentchan;
-			memcpy(&bss->phyparamset.dsparamset, pDS,
-			       sizeof(struct ieeetypes_dsparamset));
+			ds = (struct ieee_ie_ds_param_set *) pos;
+			bss->channel = ds->channel;
+			memcpy(&bss->phy.ds, ds, sizeof(*ds));
 			lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
 			break;
 
 		case WLAN_EID_CF_PARAMS:
-			pCF = (struct ieeetypes_cfparamset *) pos;
-			memcpy(&bss->ssparamset.cfparamset, pCF,
-			       sizeof(struct ieeetypes_cfparamset));
+			cf = (struct ieee_ie_cf_param_set *) pos;
+			memcpy(&bss->ss.cf, cf, sizeof(*cf));
 			lbs_deb_scan("got CF IE\n");
 			break;
 
 		case WLAN_EID_IBSS_PARAMS:
-			pibss = (struct ieeetypes_ibssparamset *) pos;
-			bss->atimwindow = le16_to_cpu(pibss->atimwindow);
-			memmove(&bss->ssparamset.ibssparamset, pibss,
-				sizeof(struct ieeetypes_ibssparamset));
+			ibss = (struct ieee_ie_ibss_param_set *) pos;
+			bss->atimwindow = ibss->atimwindow;
+			memcpy(&bss->ss.ibss, ibss, sizeof(*ibss));
 			lbs_deb_scan("got IBSS IE\n");
 			break;
 
 		case WLAN_EID_COUNTRY:
-			pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
+			pcountryinfo = (struct ieee_ie_country_info_set *) pos;
 			lbs_deb_scan("got COUNTRY IE\n");
-			if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
-			    || pcountryinfo->len > 254) {
-				lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n",
-					     pcountryinfo->len, sizeof(pcountryinfo->countrycode));
+			if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode)
+			    || pcountryinfo->header.len > 254) {
+				lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n",
+					     __func__,
+					     pcountryinfo->header.len,
+					     sizeof(pcountryinfo->countrycode));
 				ret = -1;
 				goto done;
 			}
 
-			memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2);
+			memcpy(&bss->countryinfo, pcountryinfo,
+				pcountryinfo->header.len + 2);
 			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
 				    (uint8_t *) pcountryinfo,
-				    (int) (pcountryinfo->len + 2));
+				    (int) (pcountryinfo->header.len + 2));
 			break;
 
 		case WLAN_EID_EXT_SUPP_RATES:
@@ -877,7 +877,7 @@
 	iwe.u.bitrate.disabled = 0;
 	iwe.u.bitrate.value = 0;
 
-	for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
+	for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) {
 		/* Bit rate given in 500 kb/s units */
 		iwe.u.bitrate.value = bss->rates[j] * 500000;
 		current_val = iwe_stream_add_value(info, start, current_val,
@@ -1130,7 +1130,7 @@
 		goto done;
 	}
 
-	bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
+	bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize);
 	lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
 
 	scanrespsize = le16_to_cpu(resp->size);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/tx.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/tx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/tx.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/tx.c	2009-09-09 18:13:59.000000000 -0400
@@ -132,8 +132,12 @@
 	txpd->tx_packet_length = cpu_to_le16(pkt_len);
 	txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
 
-	if (dev == priv->mesh_dev)
-		txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+	if (dev == priv->mesh_dev) {
+		if (priv->mesh_fw_ver == MESH_FW_OLD)
+			txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+		else if (priv->mesh_fw_ver == MESH_FW_NEW)
+			txpd->u.bss.bss_num = MESH_IFACE_ID;
+	}
 
 	lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/types.h linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/types.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas/types.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas/types.h	2009-09-09 18:13:59.000000000 -0400
@@ -8,9 +8,14 @@
 #include <asm/byteorder.h>
 #include <linux/wireless.h>
 
-struct ieeetypes_cfparamset {
-	u8 elementid;
+struct ieee_ie_header {
+	u8 id;
 	u8 len;
+} __attribute__ ((packed));
+
+struct ieee_ie_cf_param_set {
+	struct ieee_ie_header header;
+
 	u8 cfpcnt;
 	u8 cfpperiod;
 	__le16 cfpmaxduration;
@@ -18,42 +23,35 @@
 } __attribute__ ((packed));
 
 
-struct ieeetypes_ibssparamset {
-	u8 elementid;
-	u8 len;
+struct ieee_ie_ibss_param_set {
+	struct ieee_ie_header header;
+
 	__le16 atimwindow;
 } __attribute__ ((packed));
 
-union IEEEtypes_ssparamset {
-	struct ieeetypes_cfparamset cfparamset;
-	struct ieeetypes_ibssparamset ibssparamset;
+union ieee_ss_param_set {
+	struct ieee_ie_cf_param_set cf;
+	struct ieee_ie_ibss_param_set ibss;
 } __attribute__ ((packed));
 
-struct ieeetypes_fhparamset {
-	u8 elementid;
-	u8 len;
+struct ieee_ie_fh_param_set {
+	struct ieee_ie_header header;
+
 	__le16 dwelltime;
 	u8 hopset;
 	u8 hoppattern;
 	u8 hopindex;
 } __attribute__ ((packed));
 
-struct ieeetypes_dsparamset {
-	u8 elementid;
-	u8 len;
-	u8 currentchan;
-} __attribute__ ((packed));
+struct ieee_ie_ds_param_set {
+	struct ieee_ie_header header;
 
-union ieeetypes_phyparamset {
-	struct ieeetypes_fhparamset fhparamset;
-	struct ieeetypes_dsparamset dsparamset;
+	u8 channel;
 } __attribute__ ((packed));
 
-struct ieeetypes_assocrsp {
-	__le16 capability;
-	__le16 statuscode;
-	__le16 aid;
-	u8 iebuffer[1];
+union ieee_phy_param_set {
+	struct ieee_ie_fh_param_set fh;
+	struct ieee_ie_ds_param_set ds;
 } __attribute__ ((packed));
 
 /** TLV  type ID definition */
@@ -94,30 +92,33 @@
 #define TLV_TYPE_TSFTIMESTAMP	    (PROPRIETARY_TLV_BASE_ID + 19)
 #define TLV_TYPE_RSSI_HIGH          (PROPRIETARY_TLV_BASE_ID + 22)
 #define TLV_TYPE_SNR_HIGH           (PROPRIETARY_TLV_BASE_ID + 23)
+#define TLV_TYPE_AUTH_TYPE          (PROPRIETARY_TLV_BASE_ID + 31)
+#define TLV_TYPE_MESH_ID            (PROPRIETARY_TLV_BASE_ID + 37)
+#define TLV_TYPE_OLD_MESH_ID        (PROPRIETARY_TLV_BASE_ID + 291)
 
 /** TLV related data structures*/
-struct mrvlietypesheader {
+struct mrvl_ie_header {
 	__le16 type;
 	__le16 len;
 } __attribute__ ((packed));
 
-struct mrvlietypes_data {
-	struct mrvlietypesheader header;
+struct mrvl_ie_data {
+	struct mrvl_ie_header header;
 	u8 Data[1];
 } __attribute__ ((packed));
 
-struct mrvlietypes_ratesparamset {
-	struct mrvlietypesheader header;
+struct mrvl_ie_rates_param_set {
+	struct mrvl_ie_header header;
 	u8 rates[1];
 } __attribute__ ((packed));
 
-struct mrvlietypes_ssidparamset {
-	struct mrvlietypesheader header;
+struct mrvl_ie_ssid_param_set {
+	struct mrvl_ie_header header;
 	u8 ssid[1];
 } __attribute__ ((packed));
 
-struct mrvlietypes_wildcardssidparamset {
-	struct mrvlietypesheader header;
+struct mrvl_ie_wildcard_ssid_param_set {
+	struct mrvl_ie_header header;
 	u8 MaxSsidlength;
 	u8 ssid[1];
 } __attribute__ ((packed));
@@ -142,91 +143,72 @@
 	__le16 maxscantime;
 } __attribute__ ((packed));
 
-struct mrvlietypes_chanlistparamset {
-	struct mrvlietypesheader header;
+struct mrvl_ie_chanlist_param_set {
+	struct mrvl_ie_header header;
 	struct chanscanparamset chanscanparam[1];
 } __attribute__ ((packed));
 
-struct cfparamset {
+struct mrvl_ie_cf_param_set {
+	struct mrvl_ie_header header;
 	u8 cfpcnt;
 	u8 cfpperiod;
 	__le16 cfpmaxduration;
 	__le16 cfpdurationremaining;
 } __attribute__ ((packed));
 
-struct ibssparamset {
-	__le16 atimwindow;
-} __attribute__ ((packed));
-
-struct mrvlietypes_ssparamset {
-	struct mrvlietypesheader header;
-	union {
-		struct cfparamset cfparamset[1];
-		struct ibssparamset ibssparamset[1];
-	} cf_ibss;
-} __attribute__ ((packed));
-
-struct fhparamset {
-	__le16 dwelltime;
-	u8 hopset;
-	u8 hoppattern;
-	u8 hopindex;
-} __attribute__ ((packed));
-
-struct dsparamset {
-	u8 currentchan;
-} __attribute__ ((packed));
-
-struct mrvlietypes_phyparamset {
-	struct mrvlietypesheader header;
-	union {
-		struct fhparamset fhparamset[1];
-		struct dsparamset dsparamset[1];
-	} fh_ds;
+struct mrvl_ie_ds_param_set {
+	struct mrvl_ie_header header;
+	u8 channel;
 } __attribute__ ((packed));
 
-struct mrvlietypes_rsnparamset {
-	struct mrvlietypesheader header;
+struct mrvl_ie_rsn_param_set {
+	struct mrvl_ie_header header;
 	u8 rsnie[1];
 } __attribute__ ((packed));
 
-struct mrvlietypes_tsftimestamp {
-	struct mrvlietypesheader header;
+struct mrvl_ie_tsf_timestamp {
+	struct mrvl_ie_header header;
 	__le64 tsftable[1];
 } __attribute__ ((packed));
 
+/* v9 and later firmware only */
+struct mrvl_ie_auth_type {
+	struct mrvl_ie_header header;
+	__le16 auth;
+} __attribute__ ((packed));
+
 /**  Local Power capability */
-struct mrvlietypes_powercapability {
-	struct mrvlietypesheader header;
+struct mrvl_ie_power_capability {
+	struct mrvl_ie_header header;
 	s8 minpower;
 	s8 maxpower;
 } __attribute__ ((packed));
 
 /* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
-struct mrvlietypes_thresholds {
-	struct mrvlietypesheader header;
+struct mrvl_ie_thresholds {
+	struct mrvl_ie_header header;
 	u8 value;
 	u8 freq;
 } __attribute__ ((packed));
 
-struct mrvlietypes_beaconsmissed {
-	struct mrvlietypesheader header;
+struct mrvl_ie_beacons_missed {
+	struct mrvl_ie_header header;
 	u8 beaconmissed;
 	u8 reserved;
 } __attribute__ ((packed));
 
-struct mrvlietypes_numprobes {
-	struct mrvlietypesheader header;
+struct mrvl_ie_num_probes {
+	struct mrvl_ie_header header;
 	__le16 numprobes;
 } __attribute__ ((packed));
 
-struct mrvlietypes_bcastprobe {
-	struct mrvlietypesheader header;
+struct mrvl_ie_bcast_probe {
+	struct mrvl_ie_header header;
 	__le16 bcastprobe;
 } __attribute__ ((packed));
 
-struct mrvlietypes_numssidprobe {
-	struct mrvlietypesheader header;
+struct mrvl_ie_num_ssid_probe {
+	struct mrvl_ie_header header;
 	__le16 numssidprobe;
 } __attribute__ ((packed));
 
@@ -235,8 +217,8 @@
 	u8 pin;
 } __attribute__ ((packed));
 
-struct mrvlietypes_ledgpio {
-	struct mrvlietypesheader header;
+struct mrvl_ie_ledgpio {
+	struct mrvl_ie_header header;
 	struct led_pin ledpin[1];
 } __attribute__ ((packed));
 
@@ -248,8 +230,8 @@
 } __attribute__ ((packed));
 
 
-struct mrvlietypes_ledbhv {
-	struct mrvlietypesheader header;
+struct mrvl_ie_ledbhv {
+	struct mrvl_ie_header header;
 	struct led_bhv ledbhv[1];
 } __attribute__ ((packed));
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas_tf/if_usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas_tf/if_usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas_tf/if_usb.c	2012-03-22 19:17:40.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas_tf/if_usb.c	2012-03-22 20:13:16.000000000 -0400
@@ -461,8 +461,7 @@
 		return;
 	}
 
-	if (!in_interrupt())
-		BUG();
+	BUG_ON(!in_interrupt());
 
 	spin_lock(&priv->driver_lock);
 	memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/libertas_tf/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/libertas_tf/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/libertas_tf/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/libertas_tf/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -366,36 +366,6 @@
 	return 0;
 }
 
-static int lbtf_op_config_interface(struct ieee80211_hw *hw,
-			struct ieee80211_vif *vif,
-			struct ieee80211_if_conf *conf)
-{
-	struct lbtf_private *priv = hw->priv;
-	struct sk_buff *beacon;
-
-	switch (priv->vif->type) {
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_MESH_POINT:
-		beacon = ieee80211_beacon_get(hw, vif);
-		if (beacon) {
-			lbtf_beacon_set(priv, beacon);
-			kfree_skb(beacon);
-			lbtf_beacon_ctrl(priv, 1, hw->conf.beacon_int);
-		}
-		break;
-	default:
-		break;
-	}
-
-	if (conf->bssid) {
-		u8 null_bssid[ETH_ALEN] = {0};
-		bool activate = compare_ether_addr(conf->bssid, null_bssid);
-		lbtf_set_bssid(priv, activate, conf->bssid);
-	}
-
-	return 0;
-}
-
 #define SUPPORTED_FIF_FLAGS  (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)
 static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
 			unsigned int changed_flags,
@@ -451,6 +421,29 @@
 			u32 changes)
 {
 	struct lbtf_private *priv = hw->priv;
+	struct sk_buff *beacon;
+
+	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
+		switch (priv->vif->type) {
+		case NL80211_IFTYPE_AP:
+		case NL80211_IFTYPE_MESH_POINT:
+			beacon = ieee80211_beacon_get(hw, vif);
+			if (beacon) {
+				lbtf_beacon_set(priv, beacon);
+				kfree_skb(beacon);
+				lbtf_beacon_ctrl(priv, 1,
+						 bss_conf->beacon_int);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (changes & BSS_CHANGED_BSSID) {
+		bool activate = !is_zero_ether_addr(bss_conf->bssid);
+		lbtf_set_bssid(priv, activate, bss_conf->bssid);
+	}
 
 	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
 		if (bss_conf->use_short_preamble)
@@ -459,8 +452,6 @@
 			priv->preamble = CMD_TYPE_LONG_PREAMBLE;
 		lbtf_set_radio_control(priv);
 	}
-
-	return;
 }
 
 static const struct ieee80211_ops lbtf_ops = {
@@ -470,7 +461,6 @@
 	.add_interface		= lbtf_op_add_interface,
 	.remove_interface	= lbtf_op_remove_interface,
 	.config			= lbtf_op_config,
-	.config_interface	= lbtf_op_config_interface,
 	.configure_filter	= lbtf_op_configure_filter,
 	.bss_info_changed	= lbtf_op_bss_info_changed,
 };
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/mac80211_hwsim.c linux-libre-2.6.31-gnu/drivers/net/wireless/mac80211_hwsim.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/mac80211_hwsim.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/mac80211_hwsim.c	2009-09-09 18:13:59.000000000 -0400
@@ -280,7 +280,6 @@
 	struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)];
 
 	struct ieee80211_channel *channel;
-	int radio_enabled;
 	unsigned long beacon_int; /* in jiffies unit */
 	unsigned int rx_filter;
 	int started;
@@ -291,6 +290,14 @@
 	bool ps_poll_pending;
 	struct dentry *debugfs;
 	struct dentry *debugfs_ps;
+
+	/*
+	 * Only radios in the same group can communicate together (the
+	 * channel has to match too). Each bit represents a group. A
+	 * radio can be in more then one group.
+	 */
+	u64 group;
+	struct dentry *debugfs_group;
 };
 
 
@@ -410,9 +417,10 @@
 		if (data == data2)
 			continue;
 
-		if (!data2->started || !data2->radio_enabled ||
-		    !hwsim_ps_rx_ok(data2, skb) ||
-		    data->channel->center_freq != data2->channel->center_freq)
+		if (!data2->started || !hwsim_ps_rx_ok(data2, skb) ||
+		    !data->channel || !data2->channel ||
+		    data->channel->center_freq != data2->channel->center_freq ||
+		    !(data->group & data2->group))
 			continue;
 
 		nskb = skb_copy(skb, GFP_ATOMIC);
@@ -432,7 +440,6 @@
 
 static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-	struct mac80211_hwsim_data *data = hw->priv;
 	bool ack;
 	struct ieee80211_tx_info *txi;
 
@@ -444,13 +451,6 @@
 		return NETDEV_TX_OK;
 	}
 
-	if (!data->radio_enabled) {
-		printk(KERN_DEBUG "%s: dropped TX frame since radio "
-		       "disabled\n", wiphy_name(hw->wiphy));
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
 	ack = mac80211_hwsim_tx_frame(hw, skb);
 
 	txi = IEEE80211_SKB_CB(skb);
@@ -537,7 +537,7 @@
 	struct ieee80211_hw *hw = (struct ieee80211_hw *) arg;
 	struct mac80211_hwsim_data *data = hw->priv;
 
-	if (!data->started || !data->radio_enabled)
+	if (!data->started)
 		return;
 
 	ieee80211_iterate_active_interfaces_atomic(
@@ -553,18 +553,14 @@
 	struct mac80211_hwsim_data *data = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 
-	printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n",
+	printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n",
 	       wiphy_name(hw->wiphy), __func__,
-	       conf->channel->center_freq, conf->radio_enabled,
-	       conf->beacon_int);
+	       conf->channel->center_freq,
+	       !!(conf->flags & IEEE80211_CONF_IDLE),
+	       !!(conf->flags & IEEE80211_CONF_PS));
 
 	data->channel = conf->channel;
-	data->radio_enabled = conf->radio_enabled;
-	data->beacon_int = 1024 * conf->beacon_int / 1000 * HZ / 1000;
-	if (data->beacon_int < 1)
-		data->beacon_int = 1;
-
-	if (!data->started || !data->radio_enabled)
+	if (!data->started || !data->beacon_int)
 		del_timer(&data->beacon_timer);
 	else
 		mod_timer(&data->beacon_timer, jiffies + data->beacon_int);
@@ -592,35 +588,26 @@
 	*total_flags = data->rx_filter;
 }
 
-static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw,
-					   struct ieee80211_vif *vif,
-					   struct ieee80211_if_conf *conf)
-{
-	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
-
-	hwsim_check_magic(vif);
-	if (conf->changed & IEEE80211_IFCC_BSSID) {
-		DECLARE_MAC_BUF(mac);
-		printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n",
-		       wiphy_name(hw->wiphy), __func__,
-		       conf->bssid);
-		memcpy(vp->bssid, conf->bssid, ETH_ALEN);
-	}
-	return 0;
-}
-
 static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
 					    struct ieee80211_vif *vif,
 					    struct ieee80211_bss_conf *info,
 					    u32 changed)
 {
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+	struct mac80211_hwsim_data *data = hw->priv;
 
 	hwsim_check_magic(vif);
 
 	printk(KERN_DEBUG "%s:%s(changed=0x%x)\n",
 	       wiphy_name(hw->wiphy), __func__, changed);
 
+	if (changed & BSS_CHANGED_BSSID) {
+		printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n",
+		       wiphy_name(hw->wiphy), __func__,
+		       info->bssid);
+		memcpy(vp->bssid, info->bssid, ETH_ALEN);
+	}
+
 	if (changed & BSS_CHANGED_ASSOC) {
 		printk(KERN_DEBUG "  %s: ASSOC: assoc=%d aid=%d\n",
 		       wiphy_name(hw->wiphy), info->assoc, info->aid);
@@ -628,6 +615,14 @@
 		vp->aid = info->aid;
 	}
 
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		printk(KERN_DEBUG "  %s: BCNINT: %d\n",
+		       wiphy_name(hw->wiphy), info->beacon_int);
+		data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000;
+		if (WARN_ON(!data->beacon_int))
+			data->beacon_int = 1;
+	}
+
 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
 		printk(KERN_DEBUG "  %s: ERP_CTS_PROT: %d\n",
 		       wiphy_name(hw->wiphy), info->use_cts_prot);
@@ -646,7 +641,7 @@
 	if (changed & BSS_CHANGED_HT) {
 		printk(KERN_DEBUG "  %s: HT: op_mode=0x%x\n",
 		       wiphy_name(hw->wiphy),
-		       info->ht.operation_mode);
+		       info->ht_operation_mode);
 	}
 
 	if (changed & BSS_CHANGED_BASIC_RATES) {
@@ -704,7 +699,6 @@
 	.remove_interface = mac80211_hwsim_remove_interface,
 	.config = mac80211_hwsim_config,
 	.configure_filter = mac80211_hwsim_configure_filter,
-	.config_interface = mac80211_hwsim_config_interface,
 	.bss_info_changed = mac80211_hwsim_bss_info_changed,
 	.sta_notify = mac80211_hwsim_sta_notify,
 	.set_tim = mac80211_hwsim_set_tim,
@@ -715,7 +709,7 @@
 static void mac80211_hwsim_free(void)
 {
 	struct list_head tmplist, *i, *tmp;
-	struct mac80211_hwsim_data *data;
+	struct mac80211_hwsim_data *data, *tmpdata;
 
 	INIT_LIST_HEAD(&tmplist);
 
@@ -724,7 +718,8 @@
 		list_move(i, &tmplist);
 	spin_unlock_bh(&hwsim_radio_lock);
 
-	list_for_each_entry(data, &tmplist, list) {
+	list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
+		debugfs_remove(data->debugfs_group);
 		debugfs_remove(data->debugfs_ps);
 		debugfs_remove(data->debugfs);
 		ieee80211_unregister_hw(data->hw);
@@ -782,8 +777,7 @@
 	pspoll->aid = cpu_to_le16(0xc000 | vp->aid);
 	memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
 	memcpy(pspoll->ta, mac, ETH_ALEN);
-	if (data->radio_enabled &&
-	    !mac80211_hwsim_tx_frame(data->hw, skb))
+	if (!mac80211_hwsim_tx_frame(data->hw, skb))
 		printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__);
 	dev_kfree_skb(skb);
 }
@@ -814,8 +808,7 @@
 	memcpy(hdr->addr1, vp->bssid, ETH_ALEN);
 	memcpy(hdr->addr2, mac, ETH_ALEN);
 	memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
-	if (data->radio_enabled &&
-	    !mac80211_hwsim_tx_frame(data->hw, skb))
+	if (!mac80211_hwsim_tx_frame(data->hw, skb))
 		printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
 	dev_kfree_skb(skb);
 }
@@ -877,6 +870,24 @@
 			"%llu\n");
 
 
+static int hwsim_fops_group_read(void *dat, u64 *val)
+{
+	struct mac80211_hwsim_data *data = dat;
+	*val = data->group;
+	return 0;
+}
+
+static int hwsim_fops_group_write(void *dat, u64 val)
+{
+	struct mac80211_hwsim_data *data = dat;
+	data->group = val;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group,
+			hwsim_fops_group_read, hwsim_fops_group_write,
+			"%llx\n");
+
 static int __init init_mac80211_hwsim(void)
 {
 	int i, err = 0;
@@ -981,6 +992,8 @@
 
 			hw->wiphy->bands[band] = sband;
 		}
+		/* By default all radios are belonging to the first group */
+		data->group = 1;
 
 		/* Work to be done prior to ieee80211_register_hw() */
 		switch (regtest) {
@@ -1105,6 +1118,9 @@
 		data->debugfs_ps = debugfs_create_file("ps", 0666,
 						       data->debugfs, data,
 						       &hwsim_fops_ps);
+		data->debugfs_group = debugfs_create_file("group", 0666,
+							data->debugfs, data,
+							&hwsim_fops_group);
 
 		setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
 			    (unsigned long) hw);
@@ -1151,8 +1167,8 @@
 {
 	printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
 
-	unregister_netdev(hwsim_mon);
 	mac80211_hwsim_free();
+	unregister_netdev(hwsim_mon);
 }
 
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -55,8 +55,10 @@
 
 obj-$(CONFIG_P54_COMMON)	+= p54/
 
-obj-$(CONFIG_ATH5K)	+= ath5k/
-obj-$(CONFIG_ATH9K)	+= ath9k/
-obj-$(CONFIG_AR9170_USB)	+= ar9170/
+obj-$(CONFIG_ATH_COMMON)	+= ath/
 
 obj-$(CONFIG_MAC80211_HWSIM)	+= mac80211_hwsim.o
+
+obj-$(CONFIG_WL12XX)	+= wl12xx/
+
+obj-$(CONFIG_IWM)	+= iwmc3200wifi/
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/mwl8k.c linux-libre-2.6.31-gnu/drivers/net/wireless/mwl8k.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/mwl8k.c	2012-03-22 19:17:44.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/mwl8k.c	2012-03-22 20:13:20.000000000 -0400
@@ -261,7 +261,7 @@
 	 */
 };
 
-#define MWL8K_VIF(_vif) (struct mwl8k_vif *)(&((_vif)->drv_priv))
+#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
 
 static const struct ieee80211_channel mwl8k_channels[] = {
 	{ .center_freq = 2412, .hw_value = 1, },
@@ -1012,6 +1012,8 @@
 		rmb();
 
 		skb = rxq->rx_skb[rxq->rx_head];
+		if (skb == NULL)
+			break;
 		rxq->rx_skb[rxq->rx_head] = NULL;
 
 		rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS;
@@ -1591,6 +1593,9 @@
 	timeout = wait_for_completion_timeout(&cmd_wait,
 				msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
 
+	pci_unmap_single(priv->pdev, dma_addr, dma_size,
+					PCI_DMA_BIDIRECTIONAL);
+
 	result = &cmd->result;
 	if (!timeout) {
 		spin_lock_irq(&priv->fw_lock);
@@ -1610,8 +1615,6 @@
 			       *result);
 	}
 
-	pci_unmap_single(priv->pdev, dma_addr, dma_size,
-					PCI_DMA_BIDIRECTIONAL);
 	return rc;
 }
 
@@ -1654,18 +1657,18 @@
 	memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
 	cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
 	cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma);
-	cmd->num_tx_queues = MWL8K_TX_QUEUES;
+	cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
 	for (i = 0; i < MWL8K_TX_QUEUES; i++)
 		cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma);
-	cmd->num_tx_desc_per_queue = MWL8K_TX_DESCS;
-	cmd->total_rx_desc = MWL8K_RX_DESCS;
+	cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
+	cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS);
 
 	rc = mwl8k_post_cmd(hw, &cmd->header);
 
 	if (!rc) {
 		SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
 		priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
-		priv->fw_rev = cmd->fw_rev;
+		priv->fw_rev = le32_to_cpu(cmd->fw_rev);
 		priv->hw_rev = cmd->hw_rev;
 		priv->region_code = le16_to_cpu(cmd->region_code);
 	}
@@ -2369,7 +2372,7 @@
 	if (info->use_cts_prot) {
 		prot_mode = MWL8K_FRAME_PROT_11G;
 	} else {
-		switch (info->ht.operation_mode &
+		switch (info->ht_operation_mode &
 			IEEE80211_HT_OP_MODE_PROTECTION) {
 		case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
 			prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY;
@@ -3089,19 +3092,6 @@
 	return rc ? -EINVAL : 0;
 }
 
-static int mwl8k_config_interface(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif,
-				  struct ieee80211_if_conf *conf)
-{
-	struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
-	u32 changed = conf->changed;
-
-	if (changed & IEEE80211_IFCC_BSSID)
-		memcpy(mv_vif->bssid, conf->bssid, IEEE80211_ADDR_LEN);
-
-	return 0;
-}
-
 struct mwl8k_bss_info_changed_worker {
 	struct mwl8k_work_struct header;
 	struct ieee80211_vif *vif;
@@ -3183,8 +3173,12 @@
 {
 	struct mwl8k_bss_info_changed_worker *worker;
 	struct mwl8k_priv *priv = hw->priv;
+	struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
 	int rc;
 
+	if (changed & BSS_CHANGED_BSSID)
+		memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN);
+
 	if ((changed & BSS_CHANGED_ASSOC) == 0)
 		return;
 
@@ -3225,15 +3219,19 @@
 	struct dev_addr_list *mclist = worker->mclist;
 
 	struct mwl8k_priv *priv = hw->priv;
-	struct mwl8k_vif *mv_vif;
 	int rc = 0;
 
 	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
 		if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
 			rc = mwl8k_cmd_set_pre_scan(hw);
 		else {
-			mv_vif = MWL8K_VIF(priv->vif);
-			rc = mwl8k_cmd_set_post_scan(hw, mv_vif->bssid);
+			u8 *bssid;
+
+			bssid = "\x00\x00\x00\x00\x00\x00";
+			if (priv->vif != NULL)
+				bssid = MWL8K_VIF(priv->vif)->bssid;
+
+			rc = mwl8k_cmd_set_post_scan(hw, bssid);
 		}
 	}
 
@@ -3442,7 +3440,6 @@
 	.add_interface		= mwl8k_add_interface,
 	.remove_interface	= mwl8k_remove_interface,
 	.config			= mwl8k_config,
-	.config_interface	= mwl8k_config_interface,
 	.bss_info_changed	= mwl8k_bss_info_changed,
 	.configure_filter	= mwl8k_configure_filter,
 	.set_rts_threshold	= mwl8k_set_rts_threshold,
@@ -3736,6 +3733,8 @@
 
 	ieee80211_stop_queues(hw);
 
+	ieee80211_unregister_hw(hw);
+
 	/* Remove tx reclaim tasklet */
 	tasklet_kill(&priv->tx_reclaim_task);
 
@@ -3749,8 +3748,6 @@
 	for (i = 0; i < MWL8K_TX_QUEUES; i++)
 		mwl8k_txq_reclaim(hw, i, 1);
 
-	ieee80211_unregister_hw(hw);
-
 	for (i = 0; i < MWL8K_TX_QUEUES; i++)
 		mwl8k_txq_deinit(hw, i);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/orinoco/hw.c linux-libre-2.6.31-gnu/drivers/net/wireless/orinoco/hw.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/orinoco/hw.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/orinoco/hw.c	2009-09-09 18:13:59.000000000 -0400
@@ -70,7 +70,7 @@
 	int err = 0;
 	u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
 
-	if ((key < 0) || (key > 4))
+	if ((key < 0) || (key >= 4))
 		return -EINVAL;
 
 	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/orinoco/main.c linux-libre-2.6.31-gnu/drivers/net/wireless/orinoco/main.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/orinoco/main.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/orinoco/main.c	2009-09-09 18:13:59.000000000 -0400
@@ -2521,6 +2521,8 @@
 	.ndo_start_xmit		= orinoco_xmit,
 	.ndo_set_multicast_list	= orinoco_set_multicast_list,
 	.ndo_change_mtu		= orinoco_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= orinoco_tx_timeout,
 	.ndo_get_stats		= orinoco_get_stats,
 };
@@ -2555,7 +2557,6 @@
 	priv->wireless_data.spy_data = &priv->spy_data;
 	dev->wireless_data = &priv->wireless_data;
 #endif
-	/* we use the default eth_mac_addr for setting the MAC addr */
 
 	/* Reserve space in skb for the SNAP header */
 	dev->hard_header_len += ENCAPS_OVERHEAD;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54common.c linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54common.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54common.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54common.c	2009-09-09 18:13:59.000000000 -0400
@@ -249,7 +249,7 @@
 		dev->queues = P54_QUEUE_AC_NUM;
 	}
 
-	if (!modparam_nohwcrypt)
+	if (!modparam_nohwcrypt) {
 		printk(KERN_INFO "%s: cryptographic accelerator "
 				 "WEP:%s, TKIP:%s, CCMP:%s\n",
 			wiphy_name(dev->wiphy),
@@ -259,6 +259,26 @@
 			(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ?
 			"YES" : "no");
 
+		if (priv->rx_keycache_size) {
+			/*
+			 * NOTE:
+			 *
+			 * The firmware provides at most 255 (0 - 254) slots
+			 * for keys which are then used to offload decryption.
+			 * As a result the 255 entry (aka 0xff) can be used
+			 * safely by the driver to mark keys that didn't fit
+			 * into the full cache. This trick saves us from
+			 * keeping a extra list for uploaded keys.
+			 */
+
+			priv->used_rxkeys = kzalloc(BITS_TO_LONGS(
+				priv->rx_keycache_size), GFP_KERNEL);
+
+			if (!priv->used_rxkeys)
+				return -ENOMEM;
+		}
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(p54_parse_firmware);
@@ -749,8 +769,6 @@
 
 	rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi);
 	rx_status.noise = priv->noise;
-	/* XX correct? */
-	rx_status.qual = (100 * hdr->rssi) / 127;
 	if (hdr->rate & 0x10)
 		rx_status.flag |= RX_FLAG_SHORTPRE;
 	if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
@@ -804,7 +822,6 @@
 	struct ieee80211_tx_info *info;
 	struct p54_tx_info *range;
 	unsigned long flags;
-	u32 freed = 0, last_addr = priv->rx_start;
 
 	if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
 		return;
@@ -824,7 +841,6 @@
 
 		ni = IEEE80211_SKB_CB(skb->prev);
 		mr = (struct p54_tx_info *)ni->rate_driver_data;
-		last_addr = mr->end_addr;
 	}
 	if (skb->next != (struct sk_buff *)&priv->tx_queue) {
 		struct ieee80211_tx_info *ni;
@@ -832,16 +848,11 @@
 
 		ni = IEEE80211_SKB_CB(skb->next);
 		mr = (struct p54_tx_info *)ni->rate_driver_data;
-		freed = mr->start_addr - last_addr;
-	} else
-		freed = priv->rx_end - last_addr;
+	}
 	__skb_unlink(skb, &priv->tx_queue);
 	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 	dev_kfree_skb_any(skb);
-
-	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
-		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
-		p54_wake_free_queues(dev);
+	p54_wake_free_queues(dev);
 }
 EXPORT_SYMBOL_GPL(p54_free_skb);
 
@@ -875,8 +886,6 @@
 	struct sk_buff *entry;
 	u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
 	struct p54_tx_info *range = NULL;
-	u32 freed = 0;
-	u32 last_addr = priv->rx_start;
 	unsigned long flags;
 	int count, idx;
 
@@ -890,7 +899,6 @@
 
 		range = (void *)info->rate_driver_data;
 		if (range->start_addr != addr) {
-			last_addr = range->end_addr;
 			entry = entry->next;
 			continue;
 		}
@@ -901,19 +909,17 @@
 
 			ni = IEEE80211_SKB_CB(entry->next);
 			mr = (struct p54_tx_info *)ni->rate_driver_data;
-			freed = mr->start_addr - last_addr;
-		} else
-			freed = priv->rx_end - last_addr;
+		}
 
-		last_addr = range->end_addr;
 		__skb_unlink(entry, &priv->tx_queue);
-		spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 
 		frame_len = entry->len;
 		entry_hdr = (struct p54_hdr *) entry->data;
 		entry_data = (struct p54_tx_data *) entry_hdr->data;
-		priv->tx_stats[entry_data->hw_queue].len--;
+		if (priv->tx_stats[entry_data->hw_queue].len)
+			priv->tx_stats[entry_data->hw_queue].len--;
 		priv->stats.dot11ACKFailureCount += payload->tries - 1;
+		spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 
 		/*
 		 * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are
@@ -992,9 +998,7 @@
 	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 
 out:
-	if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
-		     IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
-		p54_wake_free_queues(dev);
+	p54_wake_free_queues(dev);
 }
 
 static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
@@ -1044,6 +1048,7 @@
 
 static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
+	struct p54_common *priv = dev->priv;
 	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
 	struct p54_trap *trap = (struct p54_trap *) hdr->data;
 	u16 event = le16_to_cpu(trap->event);
@@ -1057,6 +1062,8 @@
 			wiphy_name(dev->wiphy), freq);
 		break;
 	case P54_TRAP_NO_BEACON:
+		if (priv->vif)
+			ieee80211_beacon_loss(priv->vif);
 		break;
 	case P54_TRAP_SCAN:
 		break;
@@ -1452,7 +1459,8 @@
 
 		if (info->control.sta)
 			*aid = info->control.sta->aid;
-		else
+
+		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
 			*flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
 		break;
 	}
@@ -1939,7 +1947,8 @@
 	int i;
 
 	if (dev->conf.flags & IEEE80211_CONF_PS)
-		mode = P54_PSM | P54_PSM_DTIM | P54_PSM_MCBC;
+		mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM |
+		       P54_PSM_CHECKSUM | P54_PSM_MCBC;
 	else
 		mode = P54_PSM_CAM;
 
@@ -1957,9 +1966,10 @@
 		psm->intervals[i].periods = cpu_to_le16(1);
 	}
 
-	psm->beacon_rssi_skip_max = 60;
+	psm->beacon_rssi_skip_max = 200;
 	psm->rssi_delta_threshold = 0;
-	psm->nr = 0;
+	psm->nr = 10;
+	psm->exclude[0] = 0;
 
 	priv->tx(dev, skb);
 
@@ -2088,6 +2098,9 @@
 	priv->softled_state = 0;
 	p54_set_leds(dev);
 
+#ifdef CONFIG_P54_LEDS
+	cancel_delayed_work_sync(&priv->led_work);
+#endif /* CONFIG_P54_LEDS */
 	cancel_delayed_work_sync(&priv->work);
 	if (priv->cached_beacon)
 		p54_tx_cancel(dev, priv->cached_beacon);
@@ -2111,6 +2124,8 @@
 		return -EOPNOTSUPP;
 	}
 
+	priv->vif = conf->vif;
+
 	switch (conf->type) {
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
@@ -2135,6 +2150,7 @@
 	struct p54_common *priv = dev->priv;
 
 	mutex_lock(&priv->conf_mutex);
+	priv->vif = NULL;
 	if (priv->cached_beacon)
 		p54_tx_cancel(dev, priv->cached_beacon);
 	priv->mode = NL80211_IFTYPE_MONITOR;
@@ -2174,41 +2190,6 @@
 	return ret;
 }
 
-static int p54_config_interface(struct ieee80211_hw *dev,
-				struct ieee80211_vif *vif,
-				struct ieee80211_if_conf *conf)
-{
-	struct p54_common *priv = dev->priv;
-	int ret = 0;
-
-	mutex_lock(&priv->conf_mutex);
-	if (conf->changed & IEEE80211_IFCC_BSSID) {
-		memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-		ret = p54_setup_mac(dev);
-		if (ret)
-			goto out;
-	}
-
-	if (conf->changed & IEEE80211_IFCC_BEACON) {
-		ret = p54_scan(dev, P54_SCAN_EXIT, 0);
-		if (ret)
-			goto out;
-		ret = p54_setup_mac(dev);
-		if (ret)
-			goto out;
-		ret = p54_beacon_update(dev, vif);
-		if (ret)
-			goto out;
-		ret = p54_set_edcf(dev);
-		if (ret)
-			goto out;
-	}
-
-out:
-	mutex_unlock(&priv->conf_mutex);
-	return ret;
-}
-
 static void p54_configure_filter(struct ieee80211_hw *dev,
 				 unsigned int changed_flags,
 				 unsigned int *total_flags,
@@ -2312,8 +2293,32 @@
 				 u32 changed)
 {
 	struct p54_common *priv = dev->priv;
+	int ret;
 
-	if (changed & BSS_CHANGED_ERP_SLOT) {
+	mutex_lock(&priv->conf_mutex);
+	if (changed & BSS_CHANGED_BSSID) {
+		memcpy(priv->bssid, info->bssid, ETH_ALEN);
+		ret = p54_setup_mac(dev);
+		if (ret)
+			goto out;
+	}
+
+	if (changed & BSS_CHANGED_BEACON) {
+		ret = p54_scan(dev, P54_SCAN_EXIT, 0);
+		if (ret)
+			goto out;
+		ret = p54_setup_mac(dev);
+		if (ret)
+			goto out;
+		ret = p54_beacon_update(dev, vif);
+		if (ret)
+			goto out;
+	}
+	/* XXX: this mimics having two callbacks... clean up */
+ out:
+	mutex_unlock(&priv->conf_mutex);
+
+	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) {
 		priv->use_short_slot = info->use_short_slot;
 		p54_set_edcf(dev);
 	}
@@ -2334,7 +2339,6 @@
 			p54_setup_mac(dev);
 		}
 	}
-
 }
 
 static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
@@ -2344,61 +2348,84 @@
 	struct p54_common *priv = dev->priv;
 	struct sk_buff *skb;
 	struct p54_keycache *rxkey;
+	int slot, ret = 0;
 	u8 algo = 0;
 
 	if (modparam_nohwcrypt)
 		return -EOPNOTSUPP;
 
-	if (cmd == DISABLE_KEY)
-		algo = 0;
-	else {
+	mutex_lock(&priv->conf_mutex);
+	if (cmd == SET_KEY) {
 		switch (key->alg) {
 		case ALG_TKIP:
 			if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
-			      BR_DESC_PRIV_CAP_TKIP)))
-				return -EOPNOTSUPP;
+			      BR_DESC_PRIV_CAP_TKIP))) {
+				ret = -EOPNOTSUPP;
+				goto out_unlock;
+			}
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 			algo = P54_CRYPTO_TKIPMICHAEL;
 			break;
 		case ALG_WEP:
-			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP))
-				return -EOPNOTSUPP;
+			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {
+				ret = -EOPNOTSUPP;
+				goto out_unlock;
+			}
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 			algo = P54_CRYPTO_WEP;
 			break;
 		case ALG_CCMP:
-			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP))
-				return -EOPNOTSUPP;
+			if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {
+				ret = -EOPNOTSUPP;
+				goto out_unlock;
+			}
 			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 			algo = P54_CRYPTO_AESCCMP;
 			break;
 		default:
-			return -EOPNOTSUPP;
+			ret = -EOPNOTSUPP;
+			goto out_unlock;
 		}
-	}
+		slot = bitmap_find_free_region(priv->used_rxkeys,
+					       priv->rx_keycache_size, 0);
 
-	if (key->keyidx > priv->rx_keycache_size) {
-		/*
-		 * The device supports the choosen algorithm, but the firmware
-		 * does not provide enough key slots to store all of them.
-		 * So, incoming frames have to be decoded by the mac80211 stack,
-		 * but we can still offload encryption for outgoing frames.
-		 */
+		if (slot < 0) {
+			/*
+			 * The device supports the choosen algorithm, but the
+			 * firmware does not provide enough key slots to store
+			 * all of them.
+			 * But encryption offload for outgoing frames is always
+			 * possible, so we just pretend that the upload was
+			 * successful and do the decryption in software.
+			 */
 
-		return 0;
+			/* mark the key as invalid. */
+			key->hw_key_idx = 0xff;
+			goto out_unlock;
+		}
+	} else {
+		slot = key->hw_key_idx;
+
+		if (slot == 0xff) {
+			/* This key was not uploaded into the rx key cache. */
+
+			goto out_unlock;
+		}
+
+		bitmap_release_region(priv->used_rxkeys, slot, 0);
+		algo = 0;
 	}
 
-	mutex_lock(&priv->conf_mutex);
 	skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey),
-			    P54_CONTROL_TYPE_RX_KEYCACHE, GFP_ATOMIC);
+			    P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL);
 	if (!skb) {
-		mutex_unlock(&priv->conf_mutex);
-		return -ENOMEM;
+		bitmap_release_region(priv->used_rxkeys, slot, 0);
+		ret = -ENOSPC;
+		goto out_unlock;
 	}
 
-	/* TODO: some devices have 4 more free slots for rx keys */
 	rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey));
-	rxkey->entry = key->keyidx;
+	rxkey->entry = slot;
 	rxkey->key_id = key->keyidx;
 	rxkey->key_type = algo;
 	if (sta)
@@ -2416,11 +2443,51 @@
 	}
 
 	priv->tx(dev, skb);
+	key->hw_key_idx = slot;
+
+out_unlock:
 	mutex_unlock(&priv->conf_mutex);
-	return 0;
+	return ret;
 }
 
 #ifdef CONFIG_P54_LEDS
+static void p54_update_leds(struct work_struct *work)
+{
+	struct p54_common *priv = container_of(work, struct p54_common,
+					       led_work.work);
+	int err, i, tmp, blink_delay = 400;
+	bool rerun = false;
+
+	/* Don't toggle the LED, when the device is down. */
+	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+		return ;
+
+	for (i = 0; i < ARRAY_SIZE(priv->leds); i++)
+		if (priv->leds[i].toggled) {
+			priv->softled_state |= BIT(i);
+
+			tmp = 70 + 200 / (priv->leds[i].toggled);
+			if (tmp < blink_delay)
+				blink_delay = tmp;
+
+			if (priv->leds[i].led_dev.brightness == LED_OFF)
+				rerun = true;
+
+			priv->leds[i].toggled =
+				!!priv->leds[i].led_dev.brightness;
+		} else
+			priv->softled_state &= ~BIT(i);
+
+	err = p54_set_leds(priv->hw);
+	if (err && net_ratelimit())
+		printk(KERN_ERR "%s: failed to update LEDs.\n",
+			wiphy_name(priv->hw->wiphy));
+
+	if (rerun)
+		queue_delayed_work(priv->hw->workqueue, &priv->led_work,
+			msecs_to_jiffies(blink_delay));
+}
+
 static void p54_led_brightness_set(struct led_classdev *led_dev,
 				   enum led_brightness brightness)
 {
@@ -2428,28 +2495,23 @@
 					       led_dev);
 	struct ieee80211_hw *dev = led->hw_dev;
 	struct p54_common *priv = dev->priv;
-	int err;
 
-	/* Don't toggle the LED, when the device is down. */
 	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
 		return ;
 
-	if (brightness != LED_OFF)
-		priv->softled_state |= BIT(led->index);
-	else
-		priv->softled_state &= ~BIT(led->index);
-
-	err = p54_set_leds(dev);
-	if (err && net_ratelimit())
-		printk(KERN_ERR "%s: failed to update %s LED.\n",
-			wiphy_name(dev->wiphy), led_dev->name);
+	if (brightness) {
+		led->toggled++;
+		queue_delayed_work(priv->hw->workqueue, &priv->led_work,
+				   HZ/10);
+	}
 }
 
 static int p54_register_led(struct ieee80211_hw *dev,
-			    struct p54_led_dev *led,
 			    unsigned int led_index,
 			    char *name, char *trigger)
 {
+	struct p54_common *priv = dev->priv;
+	struct p54_led_dev *led = &priv->leds[led_index];
 	int err;
 
 	if (led->registered)
@@ -2482,19 +2544,30 @@
 	 * TODO:
 	 * Figure out if the EEPROM contains some hints about the number
 	 * of available/programmable LEDs of the device.
-	 * But for now, we can assume that we have two programmable LEDs.
 	 */
 
-	err = p54_register_led(dev, &priv->assoc_led, 0, "assoc",
+	INIT_DELAYED_WORK(&priv->led_work, p54_update_leds);
+
+	err = p54_register_led(dev, 0, "assoc",
 			       ieee80211_get_assoc_led_name(dev));
 	if (err)
 		return err;
 
-	err = p54_register_led(dev, &priv->tx_led, 1, "tx",
+	err = p54_register_led(dev, 1, "tx",
 			       ieee80211_get_tx_led_name(dev));
 	if (err)
 		return err;
 
+	err = p54_register_led(dev, 2, "rx",
+			       ieee80211_get_rx_led_name(dev));
+	if (err)
+		return err;
+
+	err = p54_register_led(dev, 3, "radio",
+			       ieee80211_get_radio_led_name(dev));
+	if (err)
+		return err;
+
 	err = p54_set_leds(dev);
 	return err;
 }
@@ -2502,11 +2575,11 @@
 static void p54_unregister_leds(struct ieee80211_hw *dev)
 {
 	struct p54_common *priv = dev->priv;
+	int i;
 
-	if (priv->tx_led.registered)
-		led_classdev_unregister(&priv->tx_led.led_dev);
-	if (priv->assoc_led.registered)
-		led_classdev_unregister(&priv->assoc_led.led_dev);
+	for (i = 0; i < ARRAY_SIZE(priv->leds); i++)
+		if (priv->leds[i].registered)
+			led_classdev_unregister(&priv->leds[i].led_dev);
 }
 #endif /* CONFIG_P54_LEDS */
 
@@ -2520,7 +2593,6 @@
 	.sta_notify		= p54_sta_notify,
 	.set_key		= p54_set_key,
 	.config			= p54_config,
-	.config_interface	= p54_config_interface,
 	.bss_info_changed	= p54_bss_info_changed,
 	.configure_filter	= p54_configure_filter,
 	.conf_tx		= p54_conf_tx,
@@ -2607,21 +2679,10 @@
 	kfree(priv->iq_autocal);
 	kfree(priv->output_limit);
 	kfree(priv->curve_data);
+	kfree(priv->used_rxkeys);
 
 #ifdef CONFIG_P54_LEDS
 	p54_unregister_leds(dev);
 #endif /* CONFIG_P54_LEDS */
 }
 EXPORT_SYMBOL_GPL(p54_free_common);
-
-static int __init p54_init(void)
-{
-	return 0;
-}
-
-static void __exit p54_exit(void)
-{
-}
-
-module_init(p54_init);
-module_exit(p54_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54.h linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54.h	2009-09-09 18:13:59.000000000 -0400
@@ -125,6 +125,7 @@
 	struct led_classdev led_dev;
 	char name[P54_LED_MAX_NAME_LEN + 1];
 
+	unsigned int toggled;
 	unsigned int index;
 	unsigned int registered;
 };
@@ -133,55 +134,74 @@
 
 struct p54_common {
 	struct ieee80211_hw *hw;
-	u32 rx_start;
-	u32 rx_end;
-	struct sk_buff_head tx_queue;
+	struct ieee80211_vif *vif;
 	void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb);
 	int (*open)(struct ieee80211_hw *dev);
 	void (*stop)(struct ieee80211_hw *dev);
-	int mode;
+	struct sk_buff_head tx_queue;
+	struct mutex conf_mutex;
+
+	/* memory management (as seen by the firmware) */
+	u32 rx_start;
+	u32 rx_end;
 	u16 rx_mtu;
 	u8 headroom;
 	u8 tailroom;
-	struct mutex conf_mutex;
-	u8 mac_addr[ETH_ALEN];
-	u8 bssid[ETH_ALEN];
+
+	/* firmware/hardware info */
+	unsigned int tx_hdr_len;
+	unsigned int fw_var;
+	unsigned int fw_interface;
+	u8 version;
+
+	/* (e)DCF / QOS state */
+	bool use_short_slot;
+	struct ieee80211_tx_queue_stats tx_stats[8];
+	struct p54_edcf_queue_param qos_params[8];
+
+	/* Radio data */
+	u16 rxhw;
 	u8 rx_diversity_mask;
 	u8 tx_diversity_mask;
+	unsigned int output_power;
+	int noise;
+	/* calibration, output power limit and rssi<->dBm conversation data */
 	struct pda_iq_autocal_entry *iq_autocal;
 	unsigned int iq_autocal_len;
-	struct p54_cal_database *output_limit;
 	struct p54_cal_database *curve_data;
+	struct p54_cal_database *output_limit;
 	struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS];
+
+	/* BBP/MAC state */
+	u8 mac_addr[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
+	u16 wakeup_timer;
 	unsigned int filter_flags;
-	bool use_short_slot;
-	u16 rxhw;
-	u8 version;
-	unsigned int tx_hdr_len;
-	unsigned int fw_var;
-	unsigned int fw_interface;
-	unsigned int output_power;
-	u32 tsf_low32;
-	u32 tsf_high32;
+	int mode;
+	u32 tsf_low32, tsf_high32;
 	u32 basic_rate_mask;
-	u16 wakeup_timer;
 	u16 aid;
-	struct ieee80211_tx_queue_stats tx_stats[8];
-	struct p54_edcf_queue_param qos_params[8];
-	struct ieee80211_low_level_stats stats;
-	struct delayed_work work;
 	struct sk_buff *cached_beacon;
-	int noise;
-	void *eeprom;
-	struct completion eeprom_comp;
+
+	/* cryptographic engine information */
 	u8 privacy_caps;
 	u8 rx_keycache_size;
+	unsigned long *used_rxkeys;
+
 	/* LED management */
 #ifdef CONFIG_P54_LEDS
-	struct p54_led_dev assoc_led;
-	struct p54_led_dev tx_led;
+	struct p54_led_dev leds[4];
+	struct delayed_work led_work;
 #endif /* CONFIG_P54_LEDS */
 	u16 softled_state;		/* bit field of glowing LEDs */
+
+	/* statistics */
+	struct ieee80211_low_level_stats stats;
+	struct delayed_work work;
+
+	/* eeprom handling */
+	void *eeprom;
+	struct completion eeprom_comp;
 };
 
 int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54spi.c linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54spi.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54spi.c	2012-03-22 19:17:49.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54spi.c	2012-03-22 20:13:55.000000000 -0400
@@ -96,7 +96,7 @@
 	spi_message_add_tail(&t[0], &m);
 
 	t[1].tx_buf = buf;
-	t[1].len = len;
+	t[1].len = len & ~1;
 	spi_message_add_tail(&t[1], &m);
 
 	if (len % 2) {
@@ -167,15 +167,31 @@
 static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
 {
 	int i;
-	__le32 buffer;
 
 	for (i = 0; i < 2000; i++) {
-		p54spi_spi_read(priv, reg, &buffer, sizeof(buffer));
-		if (buffer == bits)
+		__le32 buffer = p54spi_read32(priv, reg);
+		if ((buffer & bits) == bits)
 			return 1;
+	}
+	return 0;
+}
 
-		msleep(1);
+static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base,
+				const void *buf, size_t len)
+{
+	if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL,
+			     cpu_to_le32(HOST_ALLOWED))) {
+		dev_err(&priv->spi->dev, "spi_write_dma not allowed "
+			"to DMA write.\n");
+		return -EAGAIN;
 	}
+
+	p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL,
+		       cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE));
+
+	p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len));
+	p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base);
+	p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len);
 	return 0;
 }
 
@@ -228,8 +244,15 @@
 static int p54spi_upload_firmware(struct ieee80211_hw *dev)
 {
 	struct p54s_priv *priv = dev->priv;
-	unsigned long fw_len, fw_addr;
-	long _fw_len;
+	unsigned long fw_len, _fw_len;
+	unsigned int offset = 0;
+	int err = 0;
+	u8 *fw;
+
+	fw_len = priv->firmware->size;
+	fw = kmemdup(priv->firmware->data, fw_len, GFP_KERNEL);
+	if (!fw)
+		return -ENOMEM;
 
 	/* stop the device */
 	p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
@@ -244,36 +267,17 @@
 
 	msleep(TARGET_BOOT_SLEEP);
 
-	fw_addr = ISL38XX_DEV_FIRMWARE_ADDR;
-	fw_len = priv->firmware->size;
-
 	while (fw_len > 0) {
 		_fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE);
 
-		p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL,
-			       cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE));
-
-		if (p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL,
-				    cpu_to_le32(HOST_ALLOWED)) == 0) {
-			dev_err(&priv->spi->dev, "fw_upload not allowed "
-				"to DMA write.");
-			return -EAGAIN;
-		}
-
-		p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN,
-			       cpu_to_le16(_fw_len));
-		p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE,
-			       cpu_to_le32(fw_addr));
-
-		p54spi_spi_write(priv, SPI_ADRS_DMA_DATA,
-				 &priv->firmware->data, _fw_len);
+		err = p54spi_spi_write_dma(priv, cpu_to_le32(
+					   ISL38XX_DEV_FIRMWARE_ADDR + offset),
+					   (fw + offset), _fw_len);
+		if (err < 0)
+			goto out;
 
 		fw_len -= _fw_len;
-		fw_addr += _fw_len;
-
-		/* FIXME: I think this doesn't work if firmware is large,
-		 * this loop goes to second round. fw->data is not
-		 * increased at all! */
+		offset += _fw_len;
 	}
 
 	BUG_ON(fw_len != 0);
@@ -292,7 +296,10 @@
 	p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
 		       SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT));
 	msleep(TARGET_BOOT_SLEEP);
-	return 0;
+
+out:
+	kfree(fw);
+	return err;
 }
 
 static void p54spi_power_off(struct p54s_priv *priv)
@@ -318,29 +325,21 @@
 	p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val));
 }
 
-static void p54spi_wakeup(struct p54s_priv *priv)
+static int p54spi_wakeup(struct p54s_priv *priv)
 {
-	unsigned long timeout;
-	u32 ints;
-
 	/* wake the chip */
 	p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS,
 		       cpu_to_le32(SPI_TARGET_INT_WAKEUP));
 
 	/* And wait for the READY interrupt */
-	timeout = jiffies + HZ;
-
-	ints =  p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
-	while (!(ints & SPI_HOST_INT_READY)) {
-		if (time_after(jiffies, timeout))
-				goto out;
-		ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+	if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
+			     cpu_to_le32(SPI_HOST_INT_READY))) {
+		dev_err(&priv->spi->dev, "INT_READY timeout\n");
+		return -EBUSY;
 	}
 
 	p54spi_int_ack(priv, SPI_HOST_INT_READY);
-
-out:
-	return;
+	return 0;
 }
 
 static inline void p54spi_sleep(struct p54s_priv *priv)
@@ -372,27 +371,48 @@
 {
 	struct sk_buff *skb;
 	u16 len;
+	u16 rx_head[2];
+#define READAHEAD_SZ (sizeof(rx_head)-sizeof(u16))
 
-	p54spi_wakeup(priv);
-
-	/* dummy read to flush SPI DMA controller bug */
-	p54spi_read16(priv, SPI_ADRS_GEN_PURP_1);
+	if (p54spi_wakeup(priv) < 0)
+		return -EBUSY;
 
-	len = p54spi_read16(priv, SPI_ADRS_DMA_DATA);
+	/* Read data size and first data word in one SPI transaction
+	 * This is workaround for firmware/DMA bug,
+	 * when first data word gets lost under high load.
+	 */
+	p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, rx_head, sizeof(rx_head));
+	len = rx_head[0];
 
 	if (len == 0) {
-		dev_err(&priv->spi->dev, "rx request of zero bytes");
+		p54spi_sleep(priv);
+		dev_err(&priv->spi->dev, "rx request of zero bytes\n");
 		return 0;
 	}
 
-	skb = dev_alloc_skb(len);
+	/* Firmware may insert up to 4 padding bytes after the lmac header,
+	 * but it does not amend the size of SPI data transfer.
+	 * Such packets has correct data size in header, thus referencing
+	 * past the end of allocated skb. Reserve extra 4 bytes for this case */
+	skb = dev_alloc_skb(len + 4);
 	if (!skb) {
+		p54spi_sleep(priv);
 		dev_err(&priv->spi->dev, "could not alloc skb");
-		return 0;
+		return -ENOMEM;
 	}
 
-	p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, skb_put(skb, len), len);
+	if (len <= READAHEAD_SZ) {
+		memcpy(skb_put(skb, len), rx_head + 1, len);
+	} else {
+		memcpy(skb_put(skb, READAHEAD_SZ), rx_head + 1, READAHEAD_SZ);
+		p54spi_spi_read(priv, SPI_ADRS_DMA_DATA,
+				skb_put(skb, len - READAHEAD_SZ),
+				len - READAHEAD_SZ);
+	}
 	p54spi_sleep(priv);
+	/* Put additional bytes to compensate for the possible
+	 * alignment-caused truncation */
+	skb_put(skb, 4);
 
 	if (p54_rx(priv->hw, skb) == 0)
 		dev_kfree_skb(skb);
@@ -414,39 +434,28 @@
 static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
 {
 	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
-	struct p54s_dma_regs dma_regs;
-	unsigned long timeout;
 	int ret = 0;
-	u32 ints;
-
-	p54spi_wakeup(priv);
 
-	dma_regs.cmd = cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE);
-	dma_regs.len = cpu_to_le16(skb->len);
-	dma_regs.addr = hdr->req_id;
-
-	p54spi_spi_write(priv, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs,
-			   sizeof(dma_regs));
+	if (p54spi_wakeup(priv) < 0)
+		return -EBUSY;
 
-	p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, skb->data, skb->len);
+	ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len);
+	if (ret < 0)
+		goto out;
 
-	timeout = jiffies + 2 * HZ;
-	ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
-	while (!(ints & SPI_HOST_INT_WR_READY)) {
-		if (time_after(jiffies, timeout)) {
-			dev_err(&priv->spi->dev, "WR_READY timeout");
-			ret = -1;
-			goto out;
-		}
-		ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
+	if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
+			     cpu_to_le32(SPI_HOST_INT_WR_READY))) {
+		dev_err(&priv->spi->dev, "WR_READY timeout\n");
+		ret = -EAGAIN;
+		goto out;
 	}
 
 	p54spi_int_ack(priv, SPI_HOST_INT_WR_READY);
-	p54spi_sleep(priv);
 
-out:
 	if (FREE_AFTER_TX(skb))
 		p54_free_skb(priv->hw, skb);
+out:
+	p54spi_sleep(priv);
 	return ret;
 }
 
@@ -516,8 +525,7 @@
 
 	mutex_lock(&priv->mutex);
 
-	if (priv->fw_state == FW_STATE_OFF &&
-	    priv->fw_state == FW_STATE_RESET)
+	if (priv->fw_state == FW_STATE_OFF)
 		goto out;
 
 	ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
@@ -544,11 +552,6 @@
 	}
 
 	ret = p54spi_wq_tx(priv);
-	if (ret < 0)
-		goto out;
-
-	ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
-
 out:
 	mutex_unlock(&priv->mutex);
 }
@@ -632,7 +635,7 @@
 
 	hw = p54_init_common(sizeof(*priv));
 	if (!hw) {
-		dev_err(&priv->spi->dev, "could not alloc ieee80211_hw");
+		dev_err(&spi->dev, "could not alloc ieee80211_hw");
 		return -ENOMEM;
 	}
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54usb.c	2012-03-22 19:17:52.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54usb.c	2012-03-22 20:13:58.000000000 -0400
@@ -80,6 +80,29 @@
 
 MODULE_DEVICE_TABLE(usb, p54u_table);
 
+static const struct {
+	u32 intf;
+	enum p54u_hw_type type;
+	const char *fw;
+	const char *fw_legacy;
+	char hw[20];
+} p54u_fwlist[__NUM_P54U_HWTYPES] = {
+	{
+		.type = P54U_NET2280,
+		.intf = FW_LM86,
+		.fw = "/*(DEBLOBBED)*/",
+		.fw_legacy = "/*(DEBLOBBED)*/",
+		.hw = "ISL3886 + net2280",
+	},
+	{
+		.type = P54U_3887,
+		.intf = FW_LM87,
+		.fw = "/*(DEBLOBBED)*/",
+		.fw_legacy = "/*(DEBLOBBED)*/",
+		.hw = "ISL3887",
+	},
+};
+
 static void p54u_rx_cb(struct urb *urb)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
@@ -124,11 +147,7 @@
 		}
 		skb_reset_tail_pointer(skb);
 		skb_trim(skb, 0);
-		if (urb->transfer_buffer != skb_tail_pointer(skb)) {
-			/* this should not happen */
-			WARN_ON(1);
-			urb->transfer_buffer = skb_tail_pointer(skb);
-		}
+		urb->transfer_buffer = skb_tail_pointer(skb);
 	}
 	skb_queue_tail(&priv->rx_queue, skb);
 	usb_anchor_urb(urb, &priv->submitted);
@@ -205,53 +224,6 @@
 	return ret;
 }
 
-static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb)
-{
-	struct p54u_priv *priv = dev->priv;
-	struct urb *addr_urb, *data_urb;
-	int err = 0;
-
-	addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!addr_urb)
-		return;
-
-	data_urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!data_urb) {
-		usb_free_urb(addr_urb);
-		return;
-	}
-
-	usb_fill_bulk_urb(addr_urb, priv->udev,
-			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
-			  &((struct p54_hdr *)skb->data)->req_id, 4,
-			  p54u_tx_dummy_cb, dev);
-	usb_fill_bulk_urb(data_urb, priv->udev,
-			  usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
-			  skb->data, skb->len, FREE_AFTER_TX(skb) ?
-			  p54u_tx_cb : p54u_tx_dummy_cb, skb);
-	addr_urb->transfer_flags |= URB_ZERO_PACKET;
-	data_urb->transfer_flags |= URB_ZERO_PACKET;
-
-	usb_anchor_urb(addr_urb, &priv->submitted);
-	err = usb_submit_urb(addr_urb, GFP_ATOMIC);
-	if (err) {
-		usb_unanchor_urb(addr_urb);
-		goto out;
-	}
-
-	usb_anchor_urb(data_urb, &priv->submitted);
-	err = usb_submit_urb(data_urb, GFP_ATOMIC);
-	if (err)
-		usb_unanchor_urb(data_urb);
-
- out:
-	usb_free_urb(addr_urb);
-	usb_free_urb(data_urb);
-
-	if (err)
-		p54_free_skb(dev, skb);
-}
-
 static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
 {
 	u32 chk = 0;
@@ -424,20 +396,16 @@
 			    data, len, &alen, 2000);
 }
 
-static const char p54u_romboot_3887[] = "~~~~";
-static const char p54u_firmware_upload_3887[] = "<\r";
-
-static int p54u_device_reset_3887(struct ieee80211_hw *dev)
+static int p54u_device_reset(struct ieee80211_hw *dev)
 {
 	struct p54u_priv *priv = dev->priv;
 	int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING);
-	u8 buf[4];
 
 	if (lock) {
 		ret = usb_lock_device_for_reset(priv->udev, priv->intf);
 		if (ret < 0) {
 			dev_err(&priv->udev->dev, "(p54usb) unable to lock "
-				" device for reset: %d\n", ret);
+				"device for reset (%d)!\n", ret);
 			return ret;
 		}
 	}
@@ -446,26 +414,34 @@
 	if (lock)
 		usb_unlock_device(priv->udev);
 
-	if (ret) {
+	if (ret)
 		dev_err(&priv->udev->dev, "(p54usb) unable to reset "
-			"device: %d\n", ret);
-		return ret;
-	}
+			"device (%d)!\n", ret);
+
+	return ret;
+}
+
+static const char p54u_romboot_3887[] = "~~~~";
+static int p54u_firmware_reset_3887(struct ieee80211_hw *dev)
+{
+	struct p54u_priv *priv = dev->priv;
+	u8 buf[4];
+	int ret;
 
 	memcpy(&buf, p54u_romboot_3887, sizeof(buf));
 	ret = p54u_bulk_msg(priv, P54U_PIPE_DATA,
 			    buf, sizeof(buf));
 	if (ret)
 		dev_err(&priv->udev->dev, "(p54usb) unable to jump to "
-			"boot ROM: %d\n", ret);
+			"boot ROM (%d)!\n", ret);
 
 	return ret;
 }
 
+static const char p54u_firmware_upload_3887[] = "<\r";
 static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
 {
 	struct p54u_priv *priv = dev->priv;
-	const struct firmware *fw_entry = NULL;
 	int err, alen;
 	u8 carry = 0;
 	u8 *buf, *tmp;
@@ -474,51 +450,29 @@
 	struct x2_header *hdr;
 	unsigned long timeout;
 
+	err = p54u_firmware_reset_3887(dev);
+	if (err)
+		return err;
+
 	tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
 	if (!buf) {
 		dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
 					  "upload buffer!\n");
-		err = -ENOMEM;
-		goto err_bufalloc;
-	}
-
-	err = p54u_device_reset_3887(dev);
-	if (err)
-		goto err_reset;
-
-	err = reject_firmware(&fw_entry, "/*(DEBLOBBED)*/", &priv->udev->dev);
-	if (err) {
-		dev_err(&priv->udev->dev, "p54usb: cannot find firmware "
-					  "(/*(DEBLOBBED)*/)\n");
-		err = reject_firmware(&fw_entry, "/*(DEBLOBBED)*/",
-			&priv->udev->dev);
-		if (err)
-			goto err_req_fw_failed;
-	}
-
-	err = p54_parse_firmware(dev, fw_entry);
-	if (err)
-		goto err_upload_failed;
-
-	if (priv->common.fw_interface != FW_LM87) {
-		dev_err(&priv->udev->dev, "wrong firmware, "
-			"please get a LM87 firmware and try again.\n");
-		err = -EINVAL;
-		goto err_upload_failed;
+		return -ENOMEM;
 	}
 
-	left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
+	left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size);
 	strcpy(buf, p54u_firmware_upload_3887);
 	left -= strlen(p54u_firmware_upload_3887);
 	tmp += strlen(p54u_firmware_upload_3887);
 
-	data = fw_entry->data;
-	remains = fw_entry->size;
+	data = priv->fw->data;
+	remains = priv->fw->size;
 
 	hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887));
 	memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
 	hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
-	hdr->fw_length = cpu_to_le32(fw_entry->size);
+	hdr->fw_length = cpu_to_le32(priv->fw->size);
 	hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
 					 sizeof(u32)*2));
 	left -= sizeof(*hdr);
@@ -560,7 +514,8 @@
 		left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
 	}
 
-	*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
+	*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data,
+						 priv->fw->size));
 	err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
 	if (err) {
 		dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
@@ -611,19 +566,14 @@
 	if (err)
 		goto err_upload_failed;
 
-  err_upload_failed:
-	release_firmware(fw_entry);
-  err_req_fw_failed:
-  err_reset:
+err_upload_failed:
 	kfree(buf);
-  err_bufalloc:
 	return err;
 }
 
 static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
 {
 	struct p54u_priv *priv = dev->priv;
-	const struct firmware *fw_entry = NULL;
 	const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
 	int err, alen;
 	void *buf;
@@ -638,33 +588,6 @@
 		return -ENOMEM;
 	}
 
-	err = reject_firmware(&fw_entry, "/*(DEBLOBBED)*/", &priv->udev->dev);
-	if (err) {
-		dev_err(&priv->udev->dev, "(p54usb) cannot find firmware "
-					  "(/*(DEBLOBBED)*/)\n");
-		err = reject_firmware(&fw_entry, "/*(DEBLOBBED)*/",
-			&priv->udev->dev);
-		if (err) {
-			kfree(buf);
-			return err;
-			}
-	}
-
-	err = p54_parse_firmware(dev, fw_entry);
-	if (err) {
-		kfree(buf);
-		release_firmware(fw_entry);
-		return err;
-	}
-
-	if (priv->common.fw_interface != FW_LM86) {
-		dev_err(&priv->udev->dev, "wrong firmware, "
-			"please get a LM86(USB) firmware and try again.\n");
-		kfree(buf);
-		release_firmware(fw_entry);
-		return -EINVAL;
-	}
-
 #define P54U_WRITE(type, addr, data) \
 	do {\
 		err = p54u_write(priv, buf, type,\
@@ -764,8 +687,8 @@
 	P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
 
 	/* finally, we can upload firmware now! */
-	remains = fw_entry->size;
-	data = fw_entry->data;
+	remains = priv->fw->size;
+	data = priv->fw->data;
 	offset = ISL38XX_DEV_FIRMWARE_ADDR;
 
 	while (remains) {
@@ -874,12 +797,54 @@
 #undef P54U_WRITE
 #undef P54U_READ
 
- fail:
-	release_firmware(fw_entry);
+fail:
 	kfree(buf);
 	return err;
 }
 
+static int p54u_load_firmware(struct ieee80211_hw *dev)
+{
+	struct p54u_priv *priv = dev->priv;
+	int err, i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);
+
+	for (i = 0; i < __NUM_P54U_HWTYPES; i++)
+		if (p54u_fwlist[i].type == priv->hw_type)
+			break;
+
+	if (i == __NUM_P54U_HWTYPES)
+		return -EOPNOTSUPP;
+
+	err = reject_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev);
+	if (err) {
+		dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
+					  "(%d)!\n", p54u_fwlist[i].fw, err);
+
+		err = reject_firmware(&priv->fw, p54u_fwlist[i].fw_legacy,
+				       &priv->udev->dev);
+		if (err)
+			return err;
+	}
+
+	err = p54_parse_firmware(dev, priv->fw);
+	if (err)
+		goto out;
+
+	if (priv->common.fw_interface != p54u_fwlist[i].intf) {
+		dev_err(&priv->udev->dev, "wrong firmware, please get "
+			"a firmware for \"%s\" and try again.\n",
+			p54u_fwlist[i].hw);
+		err = -EINVAL;
+	}
+
+out:
+	if (err)
+		release_firmware(priv->fw);
+
+	return err;
+}
+
 static int p54u_open(struct ieee80211_hw *dev)
 {
 	struct p54u_priv *priv = dev->priv;
@@ -921,6 +886,7 @@
 	}
 
 	priv = dev->priv;
+	priv->hw_type = P54U_INVALID_HW;
 
 	SET_IEEE80211_DEV(dev, &intf->dev);
 	usb_set_intfdata(intf, dev);
@@ -952,37 +918,48 @@
 	priv->common.open = p54u_open;
 	priv->common.stop = p54u_stop;
 	if (recognized_pipes < P54U_PIPE_NUMBER) {
+#ifdef CONFIG_PM
+		/* ISL3887 needs a full reset on resume */
+		udev->reset_resume = 1;
+		err = p54u_device_reset(dev);
+#endif
+
 		priv->hw_type = P54U_3887;
-		err = p54u_upload_firmware_3887(dev);
-		if (priv->common.fw_interface == FW_LM87) {
-			dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
-			priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
-			priv->common.tx = p54u_tx_lm87;
-		} else
-			priv->common.tx = p54u_tx_3887;
+		dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
+		priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr);
+		priv->common.tx = p54u_tx_lm87;
+		priv->upload_fw = p54u_upload_firmware_3887;
 	} else {
 		priv->hw_type = P54U_NET2280;
 		dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
 		priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
 		priv->common.tx = p54u_tx_net2280;
-		err = p54u_upload_firmware_net2280(dev);
+		priv->upload_fw = p54u_upload_firmware_net2280;
 	}
+	err = p54u_load_firmware(dev);
 	if (err)
 		goto err_free_dev;
 
+	err = priv->upload_fw(dev);
+	if (err)
+		goto err_free_fw;
+
 	p54u_open(dev);
 	err = p54_read_eeprom(dev);
 	p54u_stop(dev);
 	if (err)
-		goto err_free_dev;
+		goto err_free_fw;
 
 	err = p54_register_common(dev, &udev->dev);
 	if (err)
-		goto err_free_dev;
+		goto err_free_fw;
 
 	return 0;
 
- err_free_dev:
+err_free_fw:
+	release_firmware(priv->fw);
+
+err_free_dev:
 	ieee80211_free_hw(dev);
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(udev);
@@ -1001,20 +978,64 @@
 
 	priv = dev->priv;
 	usb_put_dev(interface_to_usbdev(intf));
+	release_firmware(priv->fw);
 	p54_free_common(dev);
 	ieee80211_free_hw(dev);
 }
 
 static int p54u_pre_reset(struct usb_interface *intf)
 {
+	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+
+	if (!dev)
+		return -ENODEV;
+
+	p54u_stop(dev);
 	return 0;
 }
 
+static int p54u_resume(struct usb_interface *intf)
+{
+	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+	struct p54u_priv *priv;
+
+	if (!dev)
+		return -ENODEV;
+
+	priv = dev->priv;
+	if (unlikely(!(priv->upload_fw && priv->fw)))
+		return 0;
+
+	return priv->upload_fw(dev);
+}
+
 static int p54u_post_reset(struct usb_interface *intf)
 {
+	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+	struct p54u_priv *priv;
+	int err;
+
+	err = p54u_resume(intf);
+	if (err)
+		return err;
+
+	/* reinitialize old device state */
+	priv = dev->priv;
+	if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED)
+		ieee80211_restart_hw(dev);
+
 	return 0;
 }
 
+#ifdef CONFIG_PM
+
+static int p54u_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	return p54u_pre_reset(intf);
+}
+
+#endif /* CONFIG_PM */
+
 static struct usb_driver p54u_driver = {
 	.name	= "p54usb",
 	.id_table = p54u_table,
@@ -1022,6 +1043,11 @@
 	.disconnect = p54u_disconnect,
 	.pre_reset = p54u_pre_reset,
 	.post_reset = p54u_post_reset,
+#ifdef CONFIG_PM
+	.suspend = p54u_suspend,
+	.resume = p54u_resume,
+	.reset_resume = p54u_resume,
+#endif /* CONFIG_PM */
 	.soft_unbind = 1,
 };
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54usb.h linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54usb.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/p54/p54usb.h	2012-03-22 19:17:54.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/p54/p54usb.h	2012-03-22 20:14:00.000000000 -0400
@@ -123,18 +123,26 @@
 	struct ieee80211_hw *dev;
 };
 
+enum p54u_hw_type {
+	P54U_INVALID_HW,
+	P54U_NET2280,
+	P54U_3887,
+
+	/* keep last */
+	__NUM_P54U_HWTYPES,
+};
+
 struct p54u_priv {
 	struct p54_common common;
 	struct usb_device *udev;
 	struct usb_interface *intf;
-	enum {
-		P54U_NET2280 = 0,
-		P54U_3887
-	} hw_type;
+	int (*upload_fw)(struct ieee80211_hw *dev);
 
+	enum p54u_hw_type hw_type;
 	spinlock_t lock;
 	struct sk_buff_head rx_queue;
 	struct usb_anchor submitted;
+	const struct firmware *fw;
 };
 
 #endif /* P54USB_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/prism54/islpci_eth.c linux-libre-2.6.31-gnu/drivers/net/wireless/prism54/islpci_eth.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/prism54/islpci_eth.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/prism54/islpci_eth.c	2009-09-09 18:13:59.000000000 -0400
@@ -87,7 +87,6 @@
 	unsigned long flags;
 	unsigned char wds_mac[6];
 	u32 curr_frag;
-	int err = 0;
 
 #if VERBOSE > SHOW_ERROR_MESSAGES
 	DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n");
@@ -107,8 +106,6 @@
 		isl38xx_w32_flush(priv->device_base, ISL38XX_DEV_INT_UPDATE,
 				  ISL38XX_DEV_INT_REG);
 		udelay(ISL38XX_WRITEIO_DELAY);
-
-		err = -EBUSY;
 		goto drop_free;
 	}
 	/* Check alignment and WDS frame formatting. The start of the packet should
@@ -152,7 +149,6 @@
 			if (unlikely(newskb == NULL)) {
 				printk(KERN_ERR "%s: Cannot allocate skb\n",
 				       ndev->name);
-				err = -ENOMEM;
 				goto drop_free;
 			}
 			newskb_offset = (4 - (long) newskb->data) & 0x03;
@@ -197,8 +193,6 @@
 	if (unlikely(pci_map_address == 0)) {
 		printk(KERN_WARNING "%s: cannot map buffer to PCI\n",
 		       ndev->name);
-
-		err = -EIO;
 		goto drop_free;
 	}
 	/* Place the fragment in the control block structure. */
@@ -246,7 +240,7 @@
 	ndev->stats.tx_dropped++;
 	spin_unlock_irqrestore(&priv->slock, flags);
 	dev_kfree_skb(skb);
-	return err;
+	return NETDEV_TX_OK;
 }
 
 static inline int
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/ray_cs.c linux-libre-2.6.31-gnu/drivers/net/wireless/ray_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/ray_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/ray_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -892,7 +892,7 @@
 #endif /* RAY_IMMEDIATE_INIT */
 
 	/* copy mac and broadcast addresses to linux device */
-	memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN);
+	memcpy(dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN);
 	memset(dev->broadcast, 0xff, ETH_ALEN);
 
 	DEBUG(2, "ray_dev_init ending\n");
@@ -923,7 +923,7 @@
 
 	if (!(pcmcia_dev_present(link))) {
 		DEBUG(2, "ray_dev_start_xmit - device not present\n");
-		return -1;
+		return NETDEV_TX_LOCKED;
 	}
 	DEBUG(3, "ray_dev_start_xmit(skb=%p, dev=%p)\n", skb, dev);
 	if (local->authentication_state == NEED_TO_AUTH) {
@@ -931,7 +931,7 @@
 		if (!build_auth_frame(local, local->auth_id, OPEN_AUTH_REQUEST)) {
 			local->authentication_state = AUTHENTICATED;
 			netif_stop_queue(dev);
-			return 1;
+			return NETDEV_TX_BUSY;
 		}
 	}
 
@@ -944,7 +944,7 @@
 	case XMIT_NO_CCS:
 	case XMIT_NEED_AUTH:
 		netif_stop_queue(dev);
-		return 1;
+		return NETDEV_TX_BUSY;
 	case XMIT_NO_INTR:
 	case XMIT_MSG_BAD:
 	case XMIT_OK:
@@ -2427,11 +2427,10 @@
 
 #ifdef PCMCIA_DEBUG
 	if (pc_debug > 3) {
-		int i;
-		printk(KERN_DEBUG "skb->data before untranslate");
-		for (i = 0; i < 64; i++)
-			printk("%02x ", skb->data[i]);
-		printk("\n" KERN_DEBUG
+		print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ",
+			       DUMP_PREFIX_NONE, 16, 1,
+			       skb->data, 64, true);
+		printk(KERN_DEBUG
 		       "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n",
 		       ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl,
 		       psnap->org[0], psnap->org[1], psnap->org[2]);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rndis_wlan.c linux-libre-2.6.31-gnu/drivers/net/wireless/rndis_wlan.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rndis_wlan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rndis_wlan.c	2009-09-09 18:13:59.000000000 -0400
@@ -2,7 +2,7 @@
  * Driver for RNDIS based wireless USB devices.
  *
  * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
- * Copyright (C) 2008 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
  *
  * 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
@@ -42,6 +42,7 @@
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
 #include <net/iw_handler.h>
+#include <net/cfg80211.h>
 #include <linux/usb/usbnet.h>
 #include <linux/usb/rndis_host.h>
 
@@ -156,43 +157,55 @@
 #define NDIS_802_11_LENGTH_RATES_EX 16
 
 enum ndis_80211_net_type {
-	ndis_80211_type_freq_hop,
-	ndis_80211_type_direct_seq,
-	ndis_80211_type_ofdm_a,
-	ndis_80211_type_ofdm_g
+	NDIS_80211_TYPE_FREQ_HOP,
+	NDIS_80211_TYPE_DIRECT_SEQ,
+	NDIS_80211_TYPE_OFDM_A,
+	NDIS_80211_TYPE_OFDM_G
 };
 
 enum ndis_80211_net_infra {
-	ndis_80211_infra_adhoc,
-	ndis_80211_infra_infra,
-	ndis_80211_infra_auto_unknown
+	NDIS_80211_INFRA_ADHOC,
+	NDIS_80211_INFRA_INFRA,
+	NDIS_80211_INFRA_AUTO_UNKNOWN
 };
 
 enum ndis_80211_auth_mode {
-	ndis_80211_auth_open,
-	ndis_80211_auth_shared,
-	ndis_80211_auth_auto_switch,
-	ndis_80211_auth_wpa,
-	ndis_80211_auth_wpa_psk,
-	ndis_80211_auth_wpa_none,
-	ndis_80211_auth_wpa2,
-	ndis_80211_auth_wpa2_psk
+	NDIS_80211_AUTH_OPEN,
+	NDIS_80211_AUTH_SHARED,
+	NDIS_80211_AUTH_AUTO_SWITCH,
+	NDIS_80211_AUTH_WPA,
+	NDIS_80211_AUTH_WPA_PSK,
+	NDIS_80211_AUTH_WPA_NONE,
+	NDIS_80211_AUTH_WPA2,
+	NDIS_80211_AUTH_WPA2_PSK
 };
 
 enum ndis_80211_encr_status {
-	ndis_80211_encr_wep_enabled,
-	ndis_80211_encr_disabled,
-	ndis_80211_encr_wep_key_absent,
-	ndis_80211_encr_not_supported,
-	ndis_80211_encr_tkip_enabled,
-	ndis_80211_encr_tkip_key_absent,
-	ndis_80211_encr_ccmp_enabled,
-	ndis_80211_encr_ccmp_key_absent
+	NDIS_80211_ENCR_WEP_ENABLED,
+	NDIS_80211_ENCR_DISABLED,
+	NDIS_80211_ENCR_WEP_KEY_ABSENT,
+	NDIS_80211_ENCR_NOT_SUPPORTED,
+	NDIS_80211_ENCR_TKIP_ENABLED,
+	NDIS_80211_ENCR_TKIP_KEY_ABSENT,
+	NDIS_80211_ENCR_CCMP_ENABLED,
+	NDIS_80211_ENCR_CCMP_KEY_ABSENT
 };
 
 enum ndis_80211_priv_filter {
-	ndis_80211_priv_accept_all,
-	ndis_80211_priv_8021x_wep
+	NDIS_80211_PRIV_ACCEPT_ALL,
+	NDIS_80211_PRIV_8021X_WEP
+};
+
+enum ndis_80211_addkey_bits {
+	NDIS_80211_ADDKEY_8021X_AUTH = cpu_to_le32(1 << 28),
+	NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ = cpu_to_le32(1 << 29),
+	NDIS_80211_ADDKEY_PAIRWISE_KEY = cpu_to_le32(1 << 30),
+	NDIS_80211_ADDKEY_TRANSMIT_KEY = cpu_to_le32(1 << 31)
+};
+
+enum ndis_80211_addwep_bits {
+	NDIS_80211_ADDWEP_PERCLIENT_KEY = cpu_to_le32(1 << 30),
+	NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31)
 };
 
 struct ndis_80211_ssid {
@@ -308,7 +321,6 @@
 #define CAP_MODE_80211B		2
 #define CAP_MODE_80211G		4
 #define CAP_MODE_MASK		7
-#define CAP_SUPPORT_TXPOWER	8
 
 #define WORK_LINK_UP		(1<<0)
 #define WORK_LINK_DOWN		(1<<1)
@@ -316,25 +328,61 @@
 
 #define COMMAND_BUFFER_SIZE	(CONTROL_BUFFER_SIZE + sizeof(struct rndis_set))
 
-/* RNDIS device private data */
-struct rndis_wext_private {
-	char name[32];
+static const struct ieee80211_channel rndis_channels[] = {
+	{ .center_freq = 2412 },
+	{ .center_freq = 2417 },
+	{ .center_freq = 2422 },
+	{ .center_freq = 2427 },
+	{ .center_freq = 2432 },
+	{ .center_freq = 2437 },
+	{ .center_freq = 2442 },
+	{ .center_freq = 2447 },
+	{ .center_freq = 2452 },
+	{ .center_freq = 2457 },
+	{ .center_freq = 2462 },
+	{ .center_freq = 2467 },
+	{ .center_freq = 2472 },
+	{ .center_freq = 2484 },
+};
 
+static const struct ieee80211_rate rndis_rates[] = {
+	{ .bitrate = 10 },
+	{ .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+	{ .bitrate = 60 },
+	{ .bitrate = 90 },
+	{ .bitrate = 120 },
+	{ .bitrate = 180 },
+	{ .bitrate = 240 },
+	{ .bitrate = 360 },
+	{ .bitrate = 480 },
+	{ .bitrate = 540 }
+};
+
+/* RNDIS device private data */
+struct rndis_wlan_private {
 	struct usbnet *usbdev;
 
+	struct wireless_dev wdev;
+
+	struct cfg80211_scan_request *scan_request;
+
 	struct workqueue_struct *workqueue;
 	struct delayed_work stats_work;
+	struct delayed_work scan_work;
 	struct work_struct work;
 	struct mutex command_lock;
 	spinlock_t stats_lock;
 	unsigned long work_pending;
 
+	struct ieee80211_supported_band band;
+	struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)];
+	struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)];
+
 	struct iw_statistics iwstats;
 	struct iw_statistics privstats;
 
-	int  nick_len;
-	char nick[32];
-
 	int caps;
 	int multicast_size;
 
@@ -357,6 +405,7 @@
 	int  encr_tx_key_index;
 	char encr_keys[4][32];
 	int  encr_key_len[4];
+	char encr_key_wpa[4];
 	int  wpa_version;
 	int  wpa_keymgmt;
 	int  wpa_authalg;
@@ -368,8 +417,22 @@
 	u8 command_buffer[COMMAND_BUFFER_SIZE];
 };
 
+/*
+ * cfg80211 ops
+ */
+static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex,
+					enum nl80211_iftype type, u32 *flags,
+					struct vif_params *params);
 
-static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 };
+static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_scan_request *request);
+
+static struct cfg80211_ops rndis_config_ops = {
+	.change_virtual_intf = rndis_change_virtual_intf,
+	.scan = rndis_scan,
+};
+
+static void *rndis_wiphy_privid = &rndis_wiphy_privid;
 
 static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
 
@@ -378,13 +441,13 @@
 							0xff, 0xff, 0xff };
 
 
-static struct rndis_wext_private *get_rndis_wext_priv(struct usbnet *dev)
+static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev)
 {
-	return (struct rndis_wext_private *)dev->driver_priv;
+	return (struct rndis_wlan_private *)dev->driver_priv;
 }
 
 
-static u32 get_bcm4320_power(struct rndis_wext_private *priv)
+static u32 get_bcm4320_power(struct rndis_wlan_private *priv)
 {
 	return BCM4320_DEFAULT_TXPOWER *
 		bcm4320_power_output[priv->param_power_output] / 100;
@@ -417,7 +480,7 @@
 
 static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
 	union {
 		void			*buf;
 		struct rndis_msg_hdr	*header;
@@ -463,7 +526,7 @@
 
 static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev);
 	union {
 		void			*buf;
 		struct rndis_msg_hdr	*header;
@@ -584,7 +647,7 @@
 	ret = rndis_set_oid(dev, OID_GEN_RNDIS_CONFIG_PARAMETER,
 							infobuf, info_len);
 	if (ret != 0)
-		devdbg(dev, "setting rndis config paramater failed, %d.", ret);
+		devdbg(dev, "setting rndis config parameter failed, %d.", ret);
 
 	kfree(infobuf);
 	return ret;
@@ -684,7 +747,7 @@
 
 static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	int ret;
 
 	ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid));
@@ -731,7 +794,7 @@
 
 static int disassociate(struct usbnet *usbdev, int reset_ssid)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_ssid ssid;
 	int i, ret = 0;
 
@@ -763,7 +826,7 @@
 
 static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	__le32 tmp;
 	int auth_mode, ret;
 
@@ -772,23 +835,23 @@
 
 	if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
 		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
-			auth_mode = ndis_80211_auth_wpa2;
+			auth_mode = NDIS_80211_AUTH_WPA2;
 		else
-			auth_mode = ndis_80211_auth_wpa2_psk;
+			auth_mode = NDIS_80211_AUTH_WPA2_PSK;
 	} else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
 		if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
-			auth_mode = ndis_80211_auth_wpa;
+			auth_mode = NDIS_80211_AUTH_WPA;
 		else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
-			auth_mode = ndis_80211_auth_wpa_psk;
+			auth_mode = NDIS_80211_AUTH_WPA_PSK;
 		else
-			auth_mode = ndis_80211_auth_wpa_none;
+			auth_mode = NDIS_80211_AUTH_WPA_NONE;
 	} else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
 		if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
-			auth_mode = ndis_80211_auth_auto_switch;
+			auth_mode = NDIS_80211_AUTH_AUTO_SWITCH;
 		else
-			auth_mode = ndis_80211_auth_shared;
+			auth_mode = NDIS_80211_AUTH_SHARED;
 	} else
-		auth_mode = ndis_80211_auth_open;
+		auth_mode = NDIS_80211_AUTH_OPEN;
 
 	tmp = cpu_to_le32(auth_mode);
 	ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
@@ -806,16 +869,16 @@
 
 static int set_priv_filter(struct usbnet *usbdev)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	__le32 tmp;
 
 	devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version);
 
 	if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
 	    priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
-		tmp = cpu_to_le32(ndis_80211_priv_8021x_wep);
+		tmp = cpu_to_le32(NDIS_80211_PRIV_8021X_WEP);
 	else
-		tmp = cpu_to_le32(ndis_80211_priv_accept_all);
+		tmp = cpu_to_le32(NDIS_80211_PRIV_ACCEPT_ALL);
 
 	return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp,
 								sizeof(tmp));
@@ -824,7 +887,7 @@
 
 static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	__le32 tmp;
 	int encr_mode, ret;
 
@@ -833,18 +896,18 @@
 		groupwise);
 
 	if (pairwise & IW_AUTH_CIPHER_CCMP)
-		encr_mode = ndis_80211_encr_ccmp_enabled;
+		encr_mode = NDIS_80211_ENCR_CCMP_ENABLED;
 	else if (pairwise & IW_AUTH_CIPHER_TKIP)
-		encr_mode = ndis_80211_encr_tkip_enabled;
+		encr_mode = NDIS_80211_ENCR_TKIP_ENABLED;
 	else if (pairwise &
 		 (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
-		encr_mode = ndis_80211_encr_wep_enabled;
+		encr_mode = NDIS_80211_ENCR_WEP_ENABLED;
 	else if (groupwise & IW_AUTH_CIPHER_CCMP)
-		encr_mode = ndis_80211_encr_ccmp_enabled;
+		encr_mode = NDIS_80211_ENCR_CCMP_ENABLED;
 	else if (groupwise & IW_AUTH_CIPHER_TKIP)
-		encr_mode = ndis_80211_encr_tkip_enabled;
+		encr_mode = NDIS_80211_ENCR_TKIP_ENABLED;
 	else
-		encr_mode = ndis_80211_encr_disabled;
+		encr_mode = NDIS_80211_ENCR_DISABLED;
 
 	tmp = cpu_to_le32(encr_mode);
 	ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp,
@@ -862,7 +925,7 @@
 
 static int set_assoc_params(struct usbnet *usbdev)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	set_auth_mode(usbdev, priv->wpa_version, priv->wpa_authalg);
 	set_priv_filter(usbdev);
@@ -874,7 +937,7 @@
 
 static int set_infra_mode(struct usbnet *usbdev, int mode)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	__le32 tmp;
 	int ret, i;
 
@@ -894,7 +957,7 @@
 	if (priv->wpa_keymgmt == 0 ||
 		priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
 		for (i = 0; i < 4; i++) {
-			if (priv->encr_key_len[i] > 0)
+			if (priv->encr_key_len[i] > 0 && !priv->encr_key_wpa[i])
 				add_wep_key(usbdev, priv->encr_keys[i],
 						priv->encr_key_len[i], i);
 		}
@@ -907,12 +970,12 @@
 
 static void set_default_iw_params(struct usbnet *usbdev)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	priv->wpa_keymgmt = 0;
 	priv->wpa_version = 0;
 
-	set_infra_mode(usbdev, ndis_80211_infra_infra);
+	set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA);
 	set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
 				IW_AUTH_ALG_OPEN_SYSTEM);
 	set_priv_filter(usbdev);
@@ -933,7 +996,7 @@
 /* index must be 0 - N, as per NDIS  */
 static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_wep_key ndis_key;
 	int ret;
 
@@ -948,7 +1011,7 @@
 	memcpy(&ndis_key.material, key, key_len);
 
 	if (index == priv->encr_tx_key_index) {
-		ndis_key.index |= cpu_to_le32(1 << 31);
+		ndis_key.index |= NDIS_80211_ADDWEP_TRANSMIT_KEY;
 		ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
 						IW_AUTH_CIPHER_NONE);
 		if (ret)
@@ -965,16 +1028,85 @@
 	}
 
 	priv->encr_key_len[index] = key_len;
+	priv->encr_key_wpa[index] = 0;
 	memcpy(&priv->encr_keys[index], key, key_len);
 
 	return 0;
 }
 
 
+static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
+			int index, const struct sockaddr *addr,
+			const u8 *rx_seq, int alg, int flags)
+{
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+	struct ndis_80211_key ndis_key;
+	int ret;
+
+	if (index < 0 || index >= 4)
+		return -EINVAL;
+	if (key_len > sizeof(ndis_key.material) || key_len < 0)
+		return -EINVAL;
+	if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq)
+		return -EINVAL;
+	if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !addr)
+		return -EINVAL;
+
+	devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index,
+			!!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY),
+			!!(flags & NDIS_80211_ADDKEY_PAIRWISE_KEY),
+			!!(flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ));
+
+	memset(&ndis_key, 0, sizeof(ndis_key));
+
+	ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
+				sizeof(ndis_key.material) + key_len);
+	ndis_key.length = cpu_to_le32(key_len);
+	ndis_key.index = cpu_to_le32(index) | flags;
+
+	if (alg == IW_ENCODE_ALG_TKIP && key_len == 32) {
+		/* wpa_supplicant gives us the Michael MIC RX/TX keys in
+		 * different order than NDIS spec, so swap the order here. */
+		memcpy(ndis_key.material, key, 16);
+		memcpy(ndis_key.material + 16, key + 24, 8);
+		memcpy(ndis_key.material + 24, key + 16, 8);
+	} else
+		memcpy(ndis_key.material, key, key_len);
+
+	if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ)
+		memcpy(ndis_key.rsc, rx_seq, 6);
+
+	if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) {
+		/* pairwise key */
+		memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN);
+	} else {
+		/* group key */
+		if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
+			memset(ndis_key.bssid, 0xff, ETH_ALEN);
+		else
+			get_bssid(usbdev, ndis_key.bssid);
+	}
+
+	ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
+					le32_to_cpu(ndis_key.size));
+	devdbg(usbdev, "add_wpa_key: OID_802_11_ADD_KEY -> %08X", ret);
+	if (ret != 0)
+		return ret;
+
+	priv->encr_key_len[index] = key_len;
+	priv->encr_key_wpa[index] = 1;
+
+	if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY)
+		priv->encr_tx_key_index = index;
+
+	return 0;
+}
+
+
 /* remove_key is for both wep and wpa */
 static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct ndis_80211_remove_key remove_key;
 	__le32 keyindex;
 	int ret;
@@ -983,6 +1115,7 @@
 		return 0;
 
 	priv->encr_key_len[index] = 0;
+	priv->encr_key_wpa[index] = 0;
 	memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
 
 	if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP ||
@@ -994,7 +1127,8 @@
 		if (bssid) {
 			/* pairwise key */
 			if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
-				remove_key.index |= cpu_to_le32(1 << 30);
+				remove_key.index |=
+					NDIS_80211_ADDKEY_PAIRWISE_KEY;
 			memcpy(remove_key.bssid, bssid,
 					sizeof(remove_key.bssid));
 		} else
@@ -1027,7 +1161,7 @@
 
 static void set_multicast_list(struct usbnet *usbdev)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct dev_mc_list *mclist;
 	__le32 filter;
 	int ret, i, size;
@@ -1086,131 +1220,180 @@
 
 
 /*
- * wireless extension handlers
+ * cfg80211 ops
  */
-
-static int rndis_iw_commit(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+static int rndis_change_virtual_intf(struct wiphy *wiphy, int ifindex,
+					enum nl80211_iftype type, u32 *flags,
+					struct vif_params *params)
 {
-	/* dummy op */
-	return 0;
+	struct net_device *dev;
+	struct usbnet *usbdev;
+	int mode;
+
+	/* we're under RTNL */
+	dev = __dev_get_by_index(&init_net, ifindex);
+	if (!dev)
+		return -ENODEV;
+	usbdev = netdev_priv(dev);
+
+	switch (type) {
+	case NL80211_IFTYPE_ADHOC:
+		mode = NDIS_80211_INFRA_ADHOC;
+		break;
+	case NL80211_IFTYPE_STATION:
+		mode = NDIS_80211_INFRA_INFRA;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return set_infra_mode(usbdev, mode);
 }
 
 
-static int rndis_iw_get_range(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+#define SCAN_DELAY_JIFFIES (HZ)
+static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
+			struct cfg80211_scan_request *request)
 {
-	struct iw_range *range = (struct iw_range *)extra;
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-	int len, ret, i, j, num, has_80211g_rates;
-	u8 rates[8];
-	__le32 tx_power;
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+	int ret;
+	__le32 tmp;
 
-	devdbg(usbdev, "SIOCGIWRANGE");
+	devdbg(usbdev, "cfg80211.scan");
 
-	/* clear iw_range struct */
-	memset(range, 0, sizeof(*range));
-	wrqu->data.length = sizeof(*range);
+	if (!request)
+		return -EINVAL;
 
-	range->txpower_capa = IW_TXPOW_MWATT;
-	range->num_txpower = 1;
-	if (priv->caps & CAP_SUPPORT_TXPOWER) {
-		len = sizeof(tx_power);
-		ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
-						&tx_power, &len);
-		if (ret == 0 && le32_to_cpu(tx_power) != 0xFF)
-			range->txpower[0] = le32_to_cpu(tx_power);
-		else
-			range->txpower[0] = get_bcm4320_power(priv);
-	} else
-		range->txpower[0] = get_bcm4320_power(priv);
+	if (priv->scan_request && priv->scan_request != request)
+		return -EBUSY;
 
-	len = sizeof(rates);
-	ret = rndis_query_oid(usbdev, OID_802_11_SUPPORTED_RATES, &rates,
-								&len);
-	has_80211g_rates = 0;
+	priv->scan_request = request;
+
+	tmp = cpu_to_le32(1);
+	ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
+							sizeof(tmp));
 	if (ret == 0) {
-		j = 0;
-		for (i = 0; i < len; i++) {
-			if (rates[i] == 0)
-				break;
-			range->bitrate[j] = (rates[i] & 0x7f) * 500000;
-			/* check for non 802.11b rates */
-			if (range->bitrate[j] == 6000000 ||
-				range->bitrate[j] == 9000000 ||
-				(range->bitrate[j] >= 12000000 &&
-				range->bitrate[j] != 22000000))
-				has_80211g_rates = 1;
-			j++;
-		}
-		range->num_bitrates = j;
-	} else
-		range->num_bitrates = 0;
+		/* Wait before retrieving scan results from device */
+		queue_delayed_work(priv->workqueue, &priv->scan_work,
+			SCAN_DELAY_JIFFIES);
+	}
 
-	/* fill in 802.11g rates */
-	if (has_80211g_rates) {
-		num = range->num_bitrates;
-		for (i = 0; i < ARRAY_SIZE(rates_80211g); i++) {
-			for (j = 0; j < num; j++) {
-				if (range->bitrate[j] ==
-					rates_80211g[i] * 1000000)
-					break;
-			}
-			if (j == num)
-				range->bitrate[range->num_bitrates++] =
-					rates_80211g[i] * 1000000;
-			if (range->num_bitrates == IW_MAX_BITRATES)
-				break;
-		}
+	return ret;
+}
 
-		/* estimated max real througput in bps */
-		range->throughput = 54 * 1000 * 1000 / 2;
 
-		/* ~35%	more with afterburner */
-		if (priv->param_afterburner)
-			range->throughput = range->throughput / 100 * 135;
-	} else {
-		/* estimated max real througput in bps */
-		range->throughput = 11 * 1000 * 1000 / 2;
+static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
+					struct ndis_80211_bssid_ex *bssid)
+{
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+	struct ieee80211_channel *channel;
+	s32 signal;
+	u64 timestamp;
+	u16 capability;
+	u16 beacon_interval;
+	struct ndis_80211_fixed_ies *fixed;
+	int ie_len, bssid_len;
+	u8 *ie;
+
+	/* parse bssid structure */
+	bssid_len = le32_to_cpu(bssid->length);
+
+	if (bssid_len < sizeof(struct ndis_80211_bssid_ex) +
+			sizeof(struct ndis_80211_fixed_ies))
+		return NULL;
+
+	fixed = (struct ndis_80211_fixed_ies *)bssid->ies;
+
+	ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies));
+	ie_len = min(bssid_len - (int)sizeof(*bssid),
+					(int)le32_to_cpu(bssid->ie_length));
+	ie_len -= sizeof(struct ndis_80211_fixed_ies);
+	if (ie_len < 0)
+		return NULL;
+
+	/* extract data for cfg80211_inform_bss */
+	channel = ieee80211_get_channel(priv->wdev.wiphy,
+			KHZ_TO_MHZ(le32_to_cpu(bssid->config.ds_config)));
+	if (!channel)
+		return NULL;
+
+	signal = level_to_qual(le32_to_cpu(bssid->rssi));
+	timestamp = le64_to_cpu(*(__le64 *)fixed->timestamp);
+	capability = le16_to_cpu(fixed->capabilities);
+	beacon_interval = le16_to_cpu(fixed->beacon_interval);
+
+	return cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac,
+		timestamp, capability, beacon_interval, ie, ie_len, signal,
+		GFP_KERNEL);
+}
+
+
+static int rndis_check_bssid_list(struct usbnet *usbdev)
+{
+	void *buf = NULL;
+	struct ndis_80211_bssid_list_ex *bssid_list;
+	struct ndis_80211_bssid_ex *bssid;
+	int ret = -EINVAL, len, count, bssid_len;
+
+	devdbg(usbdev, "check_bssid_list");
+
+	len = CONTROL_BUFFER_SIZE;
+	buf = kmalloc(len, GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto out;
 	}
 
-	range->num_channels = 14;
+	ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
+	if (ret != 0)
+		goto out;
 
-	for (i = 0; (i < 14) && (i < IW_MAX_FREQUENCIES); i++) {
-		range->freq[i].i = i + 1;
-		range->freq[i].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
-		range->freq[i].e = 1;
+	bssid_list = buf;
+	bssid = bssid_list->bssid;
+	bssid_len = le32_to_cpu(bssid->length);
+	count = le32_to_cpu(bssid_list->num_items);
+	devdbg(usbdev, "check_bssid_list: %d BSSIDs found", count);
+
+	while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
+		rndis_bss_info_update(usbdev, bssid);
+
+		bssid = (void *)bssid + bssid_len;
+		bssid_len = le32_to_cpu(bssid->length);
+		count--;
 	}
-	range->num_frequency = i;
 
-	range->min_rts = 0;
-	range->max_rts = 2347;
-	range->min_frag = 256;
-	range->max_frag = 2346;
+out:
+	kfree(buf);
+	return ret;
+}
 
-	range->max_qual.qual = 100;
-	range->max_qual.level = 154;
-	range->max_qual.updated = IW_QUAL_QUAL_UPDATED
-				| IW_QUAL_LEVEL_UPDATED
-				| IW_QUAL_NOISE_INVALID;
 
-	range->we_version_compiled = WIRELESS_EXT;
-	range->we_version_source = WIRELESS_EXT;
+static void rndis_get_scan_results(struct work_struct *work)
+{
+	struct rndis_wlan_private *priv =
+		container_of(work, struct rndis_wlan_private, scan_work.work);
+	struct usbnet *usbdev = priv->usbdev;
+	int ret;
 
-	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
-			IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-	return 0;
+	devdbg(usbdev, "get_scan_results");
+
+	ret = rndis_check_bssid_list(usbdev);
+
+	cfg80211_scan_done(priv->scan_request, ret < 0);
+
+	priv->scan_request = NULL;
 }
 
 
-static int rndis_iw_get_name(struct net_device *dev,
+/*
+ * wireless extension handlers
+ */
+
+static int rndis_iw_commit(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-
-	strcpy(wrqu->name, priv->name);
+	/* dummy op */
 	return 0;
 }
 
@@ -1314,7 +1497,7 @@
 {
 	struct iw_param *p = &wrqu->param;
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	int ret = -ENOTSUPP;
 
 	switch (p->flags & IW_AUTH_INDEX) {
@@ -1395,7 +1578,7 @@
 {
 	struct iw_param *p = &wrqu->param;
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	switch (p->flags & IW_AUTH_INDEX) {
 	case IW_AUTH_WPA_VERSION:
@@ -1422,60 +1605,11 @@
 }
 
 
-static int rndis_iw_get_mode(struct net_device *dev,
-				struct iw_request_info *info,
-				union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-
-	switch (priv->infra_mode) {
-	case ndis_80211_infra_adhoc:
-		wrqu->mode = IW_MODE_ADHOC;
-		break;
-	case ndis_80211_infra_infra:
-		wrqu->mode = IW_MODE_INFRA;
-		break;
-	/*case ndis_80211_infra_auto_unknown:*/
-	default:
-		wrqu->mode = IW_MODE_AUTO;
-		break;
-	}
-	devdbg(usbdev, "SIOCGIWMODE: %08x", wrqu->mode);
-	return 0;
-}
-
-
-static int rndis_iw_set_mode(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	int mode;
-
-	devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode);
-
-	switch (wrqu->mode) {
-	case IW_MODE_ADHOC:
-		mode = ndis_80211_infra_adhoc;
-		break;
-	case IW_MODE_INFRA:
-		mode = ndis_80211_infra_infra;
-		break;
-	/*case IW_MODE_AUTO:*/
-	default:
-		mode = ndis_80211_infra_auto_unknown;
-		break;
-	}
-
-	return set_infra_mode(usbdev, mode);
-}
-
-
 static int rndis_iw_set_encode(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	int ret, index, key_len;
 	u8 *key;
 
@@ -1538,10 +1672,8 @@
 {
 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-	struct ndis_80211_key ndis_key;
-	int keyidx, ret;
-	u8 *addr;
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
+	int keyidx, flags;
 
 	keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
 
@@ -1564,250 +1696,16 @@
 	    ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
 		return remove_key(usbdev, keyidx, NULL);
 
-	if (ext->key_len > sizeof(ndis_key.material))
-		return -1;
-
-	memset(&ndis_key, 0, sizeof(ndis_key));
-
-	ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
-				sizeof(ndis_key.material) + ext->key_len);
-	ndis_key.length = cpu_to_le32(ext->key_len);
-	ndis_key.index = cpu_to_le32(keyidx);
-
-	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-		memcpy(ndis_key.rsc, ext->rx_seq, 6);
-		ndis_key.index |= cpu_to_le32(1 << 29);
-	}
-
-	addr = ext->addr.sa_data;
-	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
-		/* group key */
-		if (priv->infra_mode == ndis_80211_infra_adhoc)
-			memset(ndis_key.bssid, 0xff, ETH_ALEN);
-		else
-			get_bssid(usbdev, ndis_key.bssid);
-	} else {
-		/* pairwise key */
-		ndis_key.index |= cpu_to_le32(1 << 30);
-		memcpy(ndis_key.bssid, addr, ETH_ALEN);
-	}
-
-	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
-		ndis_key.index |= cpu_to_le32(1 << 31);
-
-	if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
-		/* wpa_supplicant gives us the Michael MIC RX/TX keys in
-		 * different order than NDIS spec, so swap the order here. */
-		memcpy(ndis_key.material, ext->key, 16);
-		memcpy(ndis_key.material + 16, ext->key + 24, 8);
-		memcpy(ndis_key.material + 24, ext->key + 16, 8);
-	} else
-		memcpy(ndis_key.material, ext->key, ext->key_len);
-
-	ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
-					le32_to_cpu(ndis_key.size));
-	devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
-	if (ret != 0)
-		return ret;
-
-	priv->encr_key_len[keyidx] = ext->key_len;
-	memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len);
+	flags = 0;
+	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
+		flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ;
+	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
+		flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
 	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
-		priv->encr_tx_key_index = keyidx;
-
-	return 0;
-}
-
-
-static int rndis_iw_set_scan(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	union iwreq_data evt;
-	int ret = -EINVAL;
-	__le32 tmp;
-
-	devdbg(usbdev, "SIOCSIWSCAN");
-
-	if (wrqu->data.flags == 0) {
-		tmp = cpu_to_le32(1);
-		ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
-								sizeof(tmp));
-		evt.data.flags = 0;
-		evt.data.length = 0;
-		wireless_send_event(dev, SIOCGIWSCAN, &evt, NULL);
-	}
-	return ret;
-}
-
-
-static char *rndis_translate_scan(struct net_device *dev,
-				  struct iw_request_info *info, char *cev,
-				  char *end_buf,
-				  struct ndis_80211_bssid_ex *bssid)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	u8 *ie;
-	char *current_val;
-	int bssid_len, ie_len, i;
-	u32 beacon, atim;
-	struct iw_event iwe;
-	unsigned char sbuf[32];
-
-	bssid_len = le32_to_cpu(bssid->length);
-
-	devdbg(usbdev, "BSSID %pM", bssid->mac);
-	iwe.cmd = SIOCGIWAP;
-	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-	memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
-	cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_ADDR_LEN);
-
-	devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length),
-						bssid->ssid.essid);
-	iwe.cmd = SIOCGIWESSID;
-	iwe.u.essid.length = le32_to_cpu(bssid->ssid.length);
-	iwe.u.essid.flags = 1;
-	cev = iwe_stream_add_point(info, cev, end_buf, &iwe, bssid->ssid.essid);
-
-	devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra));
-	iwe.cmd = SIOCGIWMODE;
-	switch (le32_to_cpu(bssid->net_infra)) {
-	case ndis_80211_infra_adhoc:
-		iwe.u.mode = IW_MODE_ADHOC;
-		break;
-	case ndis_80211_infra_infra:
-		iwe.u.mode = IW_MODE_INFRA;
-		break;
-	/*case ndis_80211_infra_auto_unknown:*/
-	default:
-		iwe.u.mode = IW_MODE_AUTO;
-		break;
-	}
-	cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_UINT_LEN);
-
-	devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config));
-	iwe.cmd = SIOCGIWFREQ;
-	dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq);
-	cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_FREQ_LEN);
-
-	devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi));
-	iwe.cmd = IWEVQUAL;
-	iwe.u.qual.qual  = level_to_qual(le32_to_cpu(bssid->rssi));
-	iwe.u.qual.level = le32_to_cpu(bssid->rssi);
-	iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
-			| IW_QUAL_LEVEL_UPDATED
-			| IW_QUAL_NOISE_INVALID;
-	cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_QUAL_LEN);
-
-	devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy));
-	iwe.cmd = SIOCGIWENCODE;
-	iwe.u.data.length = 0;
-	if (le32_to_cpu(bssid->privacy) == ndis_80211_priv_accept_all)
-		iwe.u.data.flags = IW_ENCODE_DISABLED;
-	else
-		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-
-	cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL);
-
-	devdbg(usbdev, "RATES:");
-	current_val = cev + iwe_stream_lcp_len(info);
-	iwe.cmd = SIOCGIWRATE;
-	for (i = 0; i < sizeof(bssid->rates); i++) {
-		if (bssid->rates[i] & 0x7f) {
-			iwe.u.bitrate.value =
-				((bssid->rates[i] & 0x7f) *
-				500000);
-			devdbg(usbdev, " %d", iwe.u.bitrate.value);
-			current_val = iwe_stream_add_value(info, cev,
-				current_val, end_buf, &iwe,
-				IW_EV_PARAM_LEN);
-		}
-	}
-
-	if ((current_val - cev) > iwe_stream_lcp_len(info))
-		cev = current_val;
-
-	beacon = le32_to_cpu(bssid->config.beacon_period);
-	devdbg(usbdev, "BCN_INT %d", beacon);
-	iwe.cmd = IWEVCUSTOM;
-	snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon);
-	iwe.u.data.length = strlen(sbuf);
-	cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf);
-
-	atim = le32_to_cpu(bssid->config.atim_window);
-	devdbg(usbdev, "ATIM %d", atim);
-	iwe.cmd = IWEVCUSTOM;
-	snprintf(sbuf, sizeof(sbuf), "atim=%u", atim);
-	iwe.u.data.length = strlen(sbuf);
-	cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf);
-
-	ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies));
-	ie_len = min(bssid_len - (int)sizeof(*bssid),
-					(int)le32_to_cpu(bssid->ie_length));
-	ie_len -= sizeof(struct ndis_80211_fixed_ies);
-	while (ie_len >= 2 && 2 + ie[1] <= ie_len) {
-		if ((ie[0] == WLAN_EID_GENERIC && ie[1] >= 4 &&
-		     memcmp(ie + 2, "\x00\x50\xf2\x01", 4) == 0) ||
-		    ie[0] == WLAN_EID_RSN) {
-			devdbg(usbdev, "IE: WPA%d",
-					(ie[0] == WLAN_EID_RSN) ? 2 : 1);
-			iwe.cmd = IWEVGENIE;
-			/* arbitrary cut-off at 64 */
-			iwe.u.data.length = min(ie[1] + 2, 64);
-			cev = iwe_stream_add_point(info, cev, end_buf, &iwe, ie);
-		}
-
-		ie_len -= 2 + ie[1];
-		ie += 2 + ie[1];
-	}
-
-	return cev;
-}
-
-
-static int rndis_iw_get_scan(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	void *buf = NULL;
-	char *cev = extra;
-	struct ndis_80211_bssid_list_ex *bssid_list;
-	struct ndis_80211_bssid_ex *bssid;
-	int ret = -EINVAL, len, count, bssid_len;
-
-	devdbg(usbdev, "SIOCGIWSCAN");
-
-	len = CONTROL_BUFFER_SIZE;
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
-
-	if (ret != 0)
-		goto out;
-
-	bssid_list = buf;
-	bssid = bssid_list->bssid;
-	bssid_len = le32_to_cpu(bssid->length);
-	count = le32_to_cpu(bssid_list->num_items);
-	devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count);
-
-	while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
-		cev = rndis_translate_scan(dev, info, cev,
-					   extra + IW_SCAN_MAX_DATA, bssid);
-		bssid = (void *)bssid + bssid_len;
-		bssid_len = le32_to_cpu(bssid->length);
-		count--;
-	}
+		flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;
 
-out:
-	wrqu->data.length = cev - extra;
-	wrqu->data.flags = 0;
-	kfree(buf);
-	return ret;
+	return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr,
+				ext->rx_seq, ext->alg, flags);
 }
 
 
@@ -1815,7 +1713,7 @@
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	int ret = 0;
 
 #ifdef DEBUG
@@ -1849,7 +1747,7 @@
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	devdbg(usbdev, "SIOCGIWGENIE");
 
@@ -1936,39 +1834,6 @@
 }
 
 
-static int rndis_iw_set_nick(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-
-	devdbg(usbdev, "SIOCSIWNICK");
-
-	priv->nick_len = wrqu->data.length;
-	if (priv->nick_len > 32)
-		priv->nick_len = 32;
-
-	memcpy(priv->nick, extra, priv->nick_len);
-	return 0;
-}
-
-
-static int rndis_iw_get_nick(struct net_device *dev,
-    struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
-{
-	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-
-	wrqu->data.flags = 1;
-	wrqu->data.length = priv->nick_len;
-	memcpy(extra, priv->nick, priv->nick_len);
-
-	devdbg(usbdev, "SIOCGIWNICK: '%s'", priv->nick);
-
-	return 0;
-}
-
-
 static int rndis_iw_set_freq(struct net_device *dev,
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
@@ -2021,20 +1886,12 @@
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	__le32 tx_power;
-	int ret = 0, len;
 
 	if (priv->radio_on) {
-		if (priv->caps & CAP_SUPPORT_TXPOWER) {
-			len = sizeof(tx_power);
-			ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
-							&tx_power, &len);
-			if (ret != 0)
-				return ret;
-		} else
-			/* fake incase not supported */
-			tx_power = cpu_to_le32(get_bcm4320_power(priv));
+		/* fake since changing tx_power (by userlevel) not supported */
+		tx_power = cpu_to_le32(get_bcm4320_power(priv));
 
 		wrqu->txpower.flags = IW_TXPOW_MWATT;
 		wrqu->txpower.value = le32_to_cpu(tx_power);
@@ -2047,7 +1904,7 @@
 
 	devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value);
 
-	return ret;
+	return 0;
 }
 
 
@@ -2055,9 +1912,8 @@
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	__le32 tx_power = 0;
-	int ret = 0;
 
 	if (!wrqu->txpower.disabled) {
 		if (wrqu->txpower.flags == IW_TXPOW_MWATT)
@@ -2080,22 +1936,10 @@
 	devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power));
 
 	if (le32_to_cpu(tx_power) != 0) {
-		if (priv->caps & CAP_SUPPORT_TXPOWER) {
-			/* turn radio on first */
-			if (!priv->radio_on)
-				disassociate(usbdev, 1);
-
-			ret = rndis_set_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
-						&tx_power, sizeof(tx_power));
-			if (ret != 0)
-				ret = -EOPNOTSUPP;
-			return ret;
-		} else {
-			/* txpower unsupported, just turn radio on */
-			if (!priv->radio_on)
-				return disassociate(usbdev, 1);
-			return 0; /* all ready on */
-		}
+		/* txpower unsupported, just turn radio on */
+		if (!priv->radio_on)
+			return disassociate(usbdev, 1);
+		return 0; /* all ready on */
 	}
 
 	/* tx_power == 0, turn off radio */
@@ -2125,7 +1969,7 @@
     struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	struct iw_mlme *mlme = (struct iw_mlme *)extra;
 	unsigned char bssid[ETH_ALEN];
 
@@ -2150,7 +1994,7 @@
 static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->stats_lock, flags);
@@ -2165,20 +2009,18 @@
 static const iw_handler rndis_iw_handler[] =
 {
 	IW_IOCTL(SIOCSIWCOMMIT)    = rndis_iw_commit,
-	IW_IOCTL(SIOCGIWNAME)      = rndis_iw_get_name,
+	IW_IOCTL(SIOCGIWNAME)      = (iw_handler) cfg80211_wext_giwname,
 	IW_IOCTL(SIOCSIWFREQ)      = rndis_iw_set_freq,
 	IW_IOCTL(SIOCGIWFREQ)      = rndis_iw_get_freq,
-	IW_IOCTL(SIOCSIWMODE)      = rndis_iw_set_mode,
-	IW_IOCTL(SIOCGIWMODE)      = rndis_iw_get_mode,
-	IW_IOCTL(SIOCGIWRANGE)     = rndis_iw_get_range,
+	IW_IOCTL(SIOCSIWMODE)      = (iw_handler) cfg80211_wext_siwmode,
+	IW_IOCTL(SIOCGIWMODE)      = (iw_handler) cfg80211_wext_giwmode,
+	IW_IOCTL(SIOCGIWRANGE)     = (iw_handler) cfg80211_wext_giwrange,
 	IW_IOCTL(SIOCSIWAP)        = rndis_iw_set_bssid,
 	IW_IOCTL(SIOCGIWAP)        = rndis_iw_get_bssid,
-	IW_IOCTL(SIOCSIWSCAN)      = rndis_iw_set_scan,
-	IW_IOCTL(SIOCGIWSCAN)      = rndis_iw_get_scan,
+	IW_IOCTL(SIOCSIWSCAN)      = (iw_handler) cfg80211_wext_siwscan,
+	IW_IOCTL(SIOCGIWSCAN)      = (iw_handler) cfg80211_wext_giwscan,
 	IW_IOCTL(SIOCSIWESSID)     = rndis_iw_set_essid,
 	IW_IOCTL(SIOCGIWESSID)     = rndis_iw_get_essid,
-	IW_IOCTL(SIOCSIWNICKN)     = rndis_iw_set_nick,
-	IW_IOCTL(SIOCGIWNICKN)     = rndis_iw_get_nick,
 	IW_IOCTL(SIOCGIWRATE)      = rndis_iw_get_rate,
 	IW_IOCTL(SIOCSIWRTS)       = rndis_iw_set_rts,
 	IW_IOCTL(SIOCGIWRTS)       = rndis_iw_get_rts,
@@ -2195,28 +2037,28 @@
 	IW_IOCTL(SIOCSIWMLME)      = rndis_iw_set_mlme,
 };
 
-static const iw_handler rndis_wext_private_handler[] = {
+static const iw_handler rndis_wlan_private_handler[] = {
 };
 
-static const struct iw_priv_args rndis_wext_private_args[] = {
+static const struct iw_priv_args rndis_wlan_private_args[] = {
 };
 
 
 static const struct iw_handler_def rndis_iw_handlers = {
 	.num_standard = ARRAY_SIZE(rndis_iw_handler),
-	.num_private  = ARRAY_SIZE(rndis_wext_private_handler),
-	.num_private_args = ARRAY_SIZE(rndis_wext_private_args),
+	.num_private  = ARRAY_SIZE(rndis_wlan_private_handler),
+	.num_private_args = ARRAY_SIZE(rndis_wlan_private_args),
 	.standard = (iw_handler *)rndis_iw_handler,
-	.private  = (iw_handler *)rndis_wext_private_handler,
-	.private_args = (struct iw_priv_args *)rndis_wext_private_args,
+	.private  = (iw_handler *)rndis_wlan_private_handler,
+	.private_args = (struct iw_priv_args *)rndis_wlan_private_args,
 	.get_wireless_stats = rndis_get_wireless_stats,
 };
 
 
-static void rndis_wext_worker(struct work_struct *work)
+static void rndis_wlan_worker(struct work_struct *work)
 {
-	struct rndis_wext_private *priv =
-		container_of(work, struct rndis_wext_private, work);
+	struct rndis_wlan_private *priv =
+		container_of(work, struct rndis_wlan_private, work);
 	struct usbnet *usbdev = priv->usbdev;
 	union iwreq_data evt;
 	unsigned char bssid[ETH_ALEN];
@@ -2277,10 +2119,10 @@
 		set_multicast_list(usbdev);
 }
 
-static void rndis_wext_set_multicast_list(struct net_device *dev)
+static void rndis_wlan_set_multicast_list(struct net_device *dev)
 {
 	struct usbnet *usbdev = netdev_priv(dev);
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	if (test_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
 		return;
@@ -2289,9 +2131,9 @@
 	queue_work(priv->workqueue, &priv->work);
 }
 
-static void rndis_wext_link_change(struct usbnet *usbdev, int state)
+static void rndis_wlan_link_change(struct usbnet *usbdev, int state)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	/* queue work to avoid recursive calls into rndis_command */
 	set_bit(state ? WORK_LINK_UP : WORK_LINK_DOWN, &priv->work_pending);
@@ -2299,22 +2141,14 @@
 }
 
 
-static int rndis_wext_get_caps(struct usbnet *usbdev)
+static int rndis_wlan_get_caps(struct usbnet *usbdev)
 {
 	struct {
 		__le32	num_items;
 		__le32	items[8];
 	} networks_supported;
 	int len, retval, i, n;
-	__le32 tx_power;
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-
-	/* determine if supports setting txpower */
-	len = sizeof(tx_power);
-	retval = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, &tx_power,
-									&len);
-	if (retval == 0 && le32_to_cpu(tx_power) != 0xFF)
-		priv->caps |= CAP_SUPPORT_TXPOWER;
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	/* determine supported modes */
 	len = sizeof(networks_supported);
@@ -2326,24 +2160,18 @@
 			n = 8;
 		for (i = 0; i < n; i++) {
 			switch (le32_to_cpu(networks_supported.items[i])) {
-			case ndis_80211_type_freq_hop:
-			case ndis_80211_type_direct_seq:
+			case NDIS_80211_TYPE_FREQ_HOP:
+			case NDIS_80211_TYPE_DIRECT_SEQ:
 				priv->caps |= CAP_MODE_80211B;
 				break;
-			case ndis_80211_type_ofdm_a:
+			case NDIS_80211_TYPE_OFDM_A:
 				priv->caps |= CAP_MODE_80211A;
 				break;
-			case ndis_80211_type_ofdm_g:
+			case NDIS_80211_TYPE_OFDM_G:
 				priv->caps |= CAP_MODE_80211G;
 				break;
 			}
 		}
-		if (priv->caps & CAP_MODE_80211A)
-			strcat(priv->name, "a");
-		if (priv->caps & CAP_MODE_80211B)
-			strcat(priv->name, "b");
-		if (priv->caps & CAP_MODE_80211G)
-			strcat(priv->name, "g");
 	}
 
 	return retval;
@@ -2353,8 +2181,8 @@
 #define STATS_UPDATE_JIFFIES (HZ)
 static void rndis_update_wireless_stats(struct work_struct *work)
 {
-	struct rndis_wext_private *priv =
-		container_of(work, struct rndis_wext_private, stats_work.work);
+	struct rndis_wlan_private *priv =
+		container_of(work, struct rndis_wlan_private, stats_work.work);
 	struct usbnet *usbdev = priv->usbdev;
 	struct iw_statistics iwstats;
 	__le32 rssi, tmp;
@@ -2387,7 +2215,7 @@
 	if (ret == 0) {
 		memset(&iwstats.qual, 0, sizeof(iwstats.qual));
 		iwstats.qual.qual  = level_to_qual(le32_to_cpu(rssi));
-		iwstats.qual.level = le32_to_cpu(rssi);
+		iwstats.qual.level = level_to_qual(le32_to_cpu(rssi));
 		iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
 				| IW_QUAL_LEVEL_UPDATED
 				| IW_QUAL_NOISE_INVALID;
@@ -2457,9 +2285,19 @@
 }
 
 
-static int bcm4320_early_init(struct usbnet *usbdev)
+static int bcm4320a_early_init(struct usbnet *usbdev)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	/* bcm4320a doesn't handle configuration parameters well. Try
+	 * set any and you get partially zeroed mac and broken device.
+	 */
+
+	return 0;
+}
+
+
+static int bcm4320b_early_init(struct usbnet *usbdev)
+{
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 	char buf[8];
 
 	/* Early initialization settings, setting these won't have effect
@@ -2525,33 +2363,41 @@
 }
 
 /* same as rndis_netdev_ops but with local multicast handler */
-static const struct net_device_ops rndis_wext_netdev_ops = {
+static const struct net_device_ops rndis_wlan_netdev_ops = {
 	.ndo_open		= usbnet_open,
 	.ndo_stop		= usbnet_stop,
 	.ndo_start_xmit		= usbnet_start_xmit,
 	.ndo_tx_timeout		= usbnet_tx_timeout,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_multicast_list	= rndis_wext_set_multicast_list,
+	.ndo_set_multicast_list	= rndis_wlan_set_multicast_list,
 };
 
 
-static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
+static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
 {
-	struct rndis_wext_private *priv;
+	struct wiphy *wiphy;
+	struct rndis_wlan_private *priv;
 	int retval, len;
 	__le32 tmp;
 
-	/* allocate rndis private data */
-	priv = kzalloc(sizeof(struct rndis_wext_private), GFP_KERNEL);
-	if (!priv)
+	/* allocate wiphy and rndis private data
+	 * NOTE: We only support a single virtual interface, so wiphy
+	 * and wireless_dev are somewhat synonymous for this device.
+	 */
+	wiphy = wiphy_new(&rndis_config_ops, sizeof(struct rndis_wlan_private));
+	if (!wiphy)
 		return -ENOMEM;
 
+	priv = wiphy_priv(wiphy);
+	usbdev->net->ieee80211_ptr = &priv->wdev;
+	priv->wdev.wiphy = wiphy;
+	priv->wdev.iftype = NL80211_IFTYPE_STATION;
+
 	/* These have to be initialized before calling generic_rndis_bind().
-	 * Otherwise we'll be in big trouble in rndis_wext_early_init().
+	 * Otherwise we'll be in big trouble in rndis_wlan_early_init().
 	 */
 	usbdev->driver_priv = priv;
-	strcpy(priv->name, "IEEE802.11");
 	usbdev->net->wireless_handlers = &rndis_iw_handlers;
 	priv->usbdev = usbdev;
 
@@ -2560,8 +2406,9 @@
 
 	/* because rndis_command() sleeps we need to use workqueue */
 	priv->workqueue = create_singlethread_workqueue("rndis_wlan");
-	INIT_WORK(&priv->work, rndis_wext_worker);
+	INIT_WORK(&priv->work, rndis_wlan_worker);
 	INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
+	INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results);
 
 	/* try bind rndis_host */
 	retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS);
@@ -2573,9 +2420,9 @@
 	 * picks up rssi to closest station instead of to access point).
 	 *
 	 * rndis_host wants to avoid all OID as much as possible
-	 * so do promisc/multicast handling in rndis_wext.
+	 * so do promisc/multicast handling in rndis_wlan.
 	 */
-	usbdev->net->netdev_ops = &rndis_wext_netdev_ops;
+	usbdev->net->netdev_ops = &rndis_wlan_netdev_ops;
 
 	tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST;
 	retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp,
@@ -2600,7 +2447,32 @@
 					| IW_QUAL_QUAL_INVALID
 					| IW_QUAL_LEVEL_INVALID;
 
-	rndis_wext_get_caps(usbdev);
+	/* fill-out wiphy structure and register w/ cfg80211 */
+	memcpy(wiphy->perm_addr, usbdev->net->dev_addr, ETH_ALEN);
+	wiphy->privid = rndis_wiphy_privid;
+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
+					| BIT(NL80211_IFTYPE_ADHOC);
+	wiphy->max_scan_ssids = 1;
+
+	/* TODO: fill-out band information based on priv->caps */
+	rndis_wlan_get_caps(usbdev);
+
+	memcpy(priv->channels, rndis_channels, sizeof(rndis_channels));
+	memcpy(priv->rates, rndis_rates, sizeof(rndis_rates));
+	priv->band.channels = priv->channels;
+	priv->band.n_channels = ARRAY_SIZE(rndis_channels);
+	priv->band.bitrates = priv->rates;
+	priv->band.n_bitrates = ARRAY_SIZE(rndis_rates);
+	wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
+
+	set_wiphy_dev(wiphy, &usbdev->udev->dev);
+
+	if (wiphy_register(wiphy)) {
+		retval = -ENODEV;
+		goto fail;
+	}
+
 	set_default_iw_params(usbdev);
 
 	/* turn radio on */
@@ -2615,36 +2487,40 @@
 
 fail:
 	cancel_delayed_work_sync(&priv->stats_work);
+	cancel_delayed_work_sync(&priv->scan_work);
 	cancel_work_sync(&priv->work);
 	flush_workqueue(priv->workqueue);
 	destroy_workqueue(priv->workqueue);
 
-	kfree(priv);
+	wiphy_free(wiphy);
 	return retval;
 }
 
 
-static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf)
+static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf)
 {
-	struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+	struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
 
 	/* turn radio off */
 	disassociate(usbdev, 0);
 
 	cancel_delayed_work_sync(&priv->stats_work);
+	cancel_delayed_work_sync(&priv->scan_work);
 	cancel_work_sync(&priv->work);
 	flush_workqueue(priv->workqueue);
 	destroy_workqueue(priv->workqueue);
 
 	if (priv && priv->wpa_ie_len)
 		kfree(priv->wpa_ie);
-	kfree(priv);
 
 	rndis_unbind(usbdev, intf);
+
+	wiphy_unregister(priv->wdev.wiphy);
+	wiphy_free(priv->wdev.wiphy);
 }
 
 
-static int rndis_wext_reset(struct usbnet *usbdev)
+static int rndis_wlan_reset(struct usbnet *usbdev)
 {
 	return deauthenticate(usbdev);
 }
@@ -2653,40 +2529,40 @@
 static const struct driver_info	bcm4320b_info = {
 	.description =	"Wireless RNDIS device, BCM4320b based",
 	.flags =	FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
-	.bind =		rndis_wext_bind,
-	.unbind =	rndis_wext_unbind,
+	.bind =		rndis_wlan_bind,
+	.unbind =	rndis_wlan_unbind,
 	.status =	rndis_status,
 	.rx_fixup =	rndis_rx_fixup,
 	.tx_fixup =	rndis_tx_fixup,
-	.reset =	rndis_wext_reset,
-	.early_init =	bcm4320_early_init,
-	.link_change =	rndis_wext_link_change,
+	.reset =	rndis_wlan_reset,
+	.early_init =	bcm4320b_early_init,
+	.link_change =	rndis_wlan_link_change,
 };
 
 static const struct driver_info	bcm4320a_info = {
 	.description =	"Wireless RNDIS device, BCM4320a based",
 	.flags =	FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
-	.bind =		rndis_wext_bind,
-	.unbind =	rndis_wext_unbind,
+	.bind =		rndis_wlan_bind,
+	.unbind =	rndis_wlan_unbind,
 	.status =	rndis_status,
 	.rx_fixup =	rndis_rx_fixup,
 	.tx_fixup =	rndis_tx_fixup,
-	.reset =	rndis_wext_reset,
-	.early_init =	bcm4320_early_init,
-	.link_change =	rndis_wext_link_change,
+	.reset =	rndis_wlan_reset,
+	.early_init =	bcm4320a_early_init,
+	.link_change =	rndis_wlan_link_change,
 };
 
-static const struct driver_info rndis_wext_info = {
+static const struct driver_info rndis_wlan_info = {
 	.description =	"Wireless RNDIS device",
 	.flags =	FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
-	.bind =		rndis_wext_bind,
-	.unbind =	rndis_wext_unbind,
+	.bind =		rndis_wlan_bind,
+	.unbind =	rndis_wlan_unbind,
 	.status =	rndis_status,
 	.rx_fixup =	rndis_rx_fixup,
 	.tx_fixup =	rndis_tx_fixup,
-	.reset =	rndis_wext_reset,
-	.early_init =	bcm4320_early_init,
-	.link_change =	rndis_wext_link_change,
+	.reset =	rndis_wlan_reset,
+	.early_init =	bcm4320a_early_init,
+	.link_change =	rndis_wlan_link_change,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -2796,11 +2672,11 @@
 {
 	/* RNDIS is MSFT's un-official variant of CDC ACM */
 	USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
-	.driver_info = (unsigned long) &rndis_wext_info,
+	.driver_info = (unsigned long) &rndis_wlan_info,
 }, {
 	/* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
 	USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
-	.driver_info = (unsigned long) &rndis_wext_info,
+	.driver_info = (unsigned long) &rndis_wlan_info,
 },
 	{ },		// END
 };
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/Kconfig linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/Kconfig
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/Kconfig	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/Kconfig	2009-09-09 18:13:59.000000000 -0400
@@ -9,11 +9,11 @@
 
 	  When building one of the individual drivers, the rt2x00 library
 	  will also be created. That library (when the driver is built as
-	  a module) will be called "rt2x00lib.ko".
+	  a module) will be called rt2x00lib.
 
 	  Additionally PCI and USB libraries will also be build depending
 	  on the types of drivers being selected, these libraries will be
-	  called "rt2x00pci.ko" and "rt2x00usb.ko".
+	  called rt2x00pci and rt2x00usb.
 
 if RT2X00
 
@@ -26,7 +26,7 @@
 	  This adds support for rt2400 wireless chipset family.
 	  Supported chips: RT2460.
 
-	  When compiled as a module, this driver will be called "rt2400pci.ko".
+	  When compiled as a module, this driver will be called rt2400pci.
 
 config RT2500PCI
 	tristate "Ralink rt2500 (PCI/PCMCIA) support"
@@ -37,7 +37,7 @@
 	  This adds support for rt2500 wireless chipset family.
 	  Supported chips: RT2560.
 
-	  When compiled as a module, this driver will be called "rt2500pci.ko".
+	  When compiled as a module, this driver will be called rt2500pci.
 
 config RT61PCI
 	tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"
@@ -51,7 +51,7 @@
 	  This adds support for rt2501 wireless chipset family.
 	  Supported chips: RT2561, RT2561S & RT2661.
 
-	  When compiled as a module, this driver will be called "rt61pci.ko".
+	  When compiled as a module, this driver will be called rt61pci.
 
 config RT2500USB
 	tristate "Ralink rt2500 (USB) support"
@@ -62,7 +62,7 @@
 	  This adds support for rt2500 wireless chipset family.
 	  Supported chips: RT2571 & RT2572.
 
-	  When compiled as a module, this driver will be called "rt2500usb.ko".
+	  When compiled as a module, this driver will be called rt2500usb.
 
 config RT73USB
 	tristate "Ralink rt2501/rt73 (USB) support"
@@ -75,7 +75,21 @@
 	  This adds support for rt2501 wireless chipset family.
 	  Supported chips: RT2571W, RT2573 & RT2671.
 
-	  When compiled as a module, this driver will be called "rt73usb.ko".
+	  When compiled as a module, this driver will be called rt73usb.
+
+config RT2800USB
+	tristate "Ralink rt2800 (USB) support"
+	depends on USB
+	select RT2X00_LIB_USB
+	select RT2X00_LIB_HT
+	select RT2X00_LIB_FIRMWARE
+	select RT2X00_LIB_CRYPTO
+	select CRC_CCITT
+	---help---
+	  This adds support for rt2800 wireless chipset family.
+	  Supported chips: RT2770, RT2870 & RT3070.
+
+	  When compiled as a module, this driver will be called "rt2800usb.ko".
 
 config RT2X00_LIB_PCI
 	tristate
@@ -88,6 +102,9 @@
 config RT2X00_LIB
 	tristate
 
+config RT2X00_LIB_HT
+	boolean
+
 config RT2X00_LIB_FIRMWARE
 	boolean
 	select FW_LOADER
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -8,6 +8,7 @@
 rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL)	+= rt2x00rfkill.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o
+rt2x00lib-$(CONFIG_RT2X00_LIB_HT)	+= rt2x00ht.o
 
 obj-$(CONFIG_RT2X00_LIB)		+= rt2x00lib.o
 obj-$(CONFIG_RT2X00_LIB_PCI)		+= rt2x00pci.o
@@ -17,3 +18,4 @@
 obj-$(CONFIG_RT61PCI)			+= rt61pci.o
 obj-$(CONFIG_RT2500USB)			+= rt2500usb.o
 obj-$(CONFIG_RT73USB)			+= rt73usb.o
+obj-$(CONFIG_RT2800USB)			+= rt2800usb.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2400pci.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2400pci.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2400pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2400pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -335,10 +335,11 @@
 	preamble_mask = erp->short_preamble << 3;
 
 	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT,
-			   erp->ack_timeout);
+	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, erp->ack_timeout);
 	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
 			   erp->ack_consume_time);
+	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
 	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
 
 	rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
@@ -371,6 +372,11 @@
 	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
 	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 
+	rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+	rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
+	rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
+	rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+
 	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
 	rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
 	rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
@@ -503,24 +509,6 @@
 	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 }
 
-static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
-				      struct rt2x00lib_conf *libconf)
-{
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
-	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
-
-	rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
-	rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
-			   libconf->conf->beacon_int * 16);
-	rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
-			   libconf->conf->beacon_int * 16);
-	rt2x00pci_register_write(rt2x00dev, CSR12, reg);
-}
-
 static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
 				struct rt2x00lib_conf *libconf)
 {
@@ -532,7 +520,7 @@
 	if (state == STATE_SLEEP) {
 		rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
 		rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
-				   (libconf->conf->beacon_int - 20) * 16);
+				   (rt2x00dev->beacon_int - 20) * 16);
 		rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
 				   libconf->conf->listen_interval - 1);
 
@@ -558,8 +546,6 @@
 					 libconf->conf->power_level);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		rt2400pci_config_retry_limit(rt2x00dev, libconf);
-	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
-		rt2400pci_config_duration(rt2x00dev, libconf);
 	if (flags & IEEE80211_CONF_CHANGE_PS)
 		rt2400pci_config_ps(rt2x00dev, libconf);
 }
@@ -1361,7 +1347,7 @@
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
-	rt2x00_set_chip(rt2x00dev, RT2460, value, reg);
+	rt2x00_set_chip_rf(rt2x00dev, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2421)) {
@@ -1580,7 +1566,6 @@
 	.add_interface		= rt2x00mac_add_interface,
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
-	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
 	.get_stats		= rt2x00mac_get_stats,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2500pci.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2500pci.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2500pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2500pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -341,10 +341,11 @@
 	preamble_mask = erp->short_preamble << 3;
 
 	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT,
-			   erp->ack_timeout);
+	rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, erp->ack_timeout);
 	rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
 			   erp->ack_consume_time);
+	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
 	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
 
 	rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
@@ -377,6 +378,11 @@
 	rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
 	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 
+	rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+	rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
+	rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
+	rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+
 	rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
 	rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
 	rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
@@ -552,24 +558,6 @@
 	rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 }
 
-static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
-				      struct rt2x00lib_conf *libconf)
-{
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-	rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
-	rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
-
-	rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
-	rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
-			   libconf->conf->beacon_int * 16);
-	rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
-			   libconf->conf->beacon_int * 16);
-	rt2x00pci_register_write(rt2x00dev, CSR12, reg);
-}
-
 static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
 				struct rt2x00lib_conf *libconf)
 {
@@ -581,7 +569,7 @@
 	if (state == STATE_SLEEP) {
 		rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
 		rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
-				   (libconf->conf->beacon_int - 20) * 16);
+				   (rt2x00dev->beacon_int - 20) * 16);
 		rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
 				   libconf->conf->listen_interval - 1);
 
@@ -609,8 +597,6 @@
 					 libconf->conf->power_level);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		rt2500pci_config_retry_limit(rt2x00dev, libconf);
-	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
-		rt2500pci_config_duration(rt2x00dev, libconf);
 	if (flags & IEEE80211_CONF_CHANGE_PS)
 		rt2500pci_config_ps(rt2x00dev, libconf);
 }
@@ -1525,7 +1511,7 @@
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
-	rt2x00_set_chip(rt2x00dev, RT2560, value, reg);
+	rt2x00_set_chip_rf(rt2x00dev, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
@@ -1879,7 +1865,6 @@
 	.add_interface		= rt2x00mac_add_interface,
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
-	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
 	.get_stats		= rt2x00mac_get_stats,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2500usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2500usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2500usb.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2500usb.c	2009-09-09 18:13:59.000000000 -0400
@@ -503,6 +503,10 @@
 
 	rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates);
 
+	rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+	rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL, erp->beacon_int * 4);
+	rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+
 	rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
 	rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
 	rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
@@ -632,17 +636,6 @@
 	rt2500usb_rf_write(rt2x00dev, 3, rf3);
 }
 
-static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
-				      struct rt2x00lib_conf *libconf)
-{
-	u16 reg;
-
-	rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
-	rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
-			   libconf->conf->beacon_int * 4);
-	rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
-}
-
 static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
 				struct rt2x00lib_conf *libconf)
 {
@@ -654,7 +647,7 @@
 	if (state == STATE_SLEEP) {
 		rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
 		rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
-				   libconf->conf->beacon_int - 20);
+				   rt2x00dev->beacon_int - 20);
 		rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
 				   libconf->conf->listen_interval - 1);
 
@@ -680,8 +673,6 @@
 	    !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
 		rt2500usb_config_txpower(rt2x00dev,
 					 libconf->conf->power_level);
-	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
-		rt2500usb_config_duration(rt2x00dev, libconf);
 	if (flags & IEEE80211_CONF_CHANGE_PS)
 		rt2500usb_config_ps(rt2x00dev, libconf);
 }
@@ -1559,7 +1550,9 @@
 	rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
 
-	if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) {
+	if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
+	    rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
+
 		ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
 		return -ENODEV;
 	}
@@ -1908,7 +1901,6 @@
 	.add_interface		= rt2x00mac_add_interface,
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
-	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
 	.set_key		= rt2x00mac_set_key,
 	.get_stats		= rt2x00mac_get_stats,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2800usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2800usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	2012-03-22 20:14:21.000000000 -0400
@@ -0,0 +1,3078 @@
+/*
+	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.com>
+
+	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.
+ */
+
+/*
+	Module: rt2800usb
+	Abstract: rt2800usb device specific routines.
+	Supported chipsets: RT2800U.
+ */
+
+#include <linux/crc-ccitt.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "rt2x00.h"
+#include "rt2x00usb.h"
+#include "rt2800usb.h"
+
+/*
+ * Allow hardware encryption to be disabled.
+ */
+static int modparam_nohwcrypt = 1;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
+ * Register access.
+ * All access to the CSR registers will go through the methods
+ * rt2x00usb_register_read and rt2x00usb_register_write.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers BBPCSR and RFCSR to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attampt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ * The _lock versions must be used if you already hold the csr_mutex
+ */
+#define WAIT_FOR_BBP(__dev, __reg) \
+	rt2x00usb_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
+#define WAIT_FOR_RFCSR(__dev, __reg) \
+	rt2x00usb_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+	rt2x00usb_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
+#define WAIT_FOR_MCU(__dev, __reg) \
+	rt2x00usb_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+			       H2M_MAILBOX_CSR_OWNER, (__reg))
+
+static void rt2800usb_bbp_write(struct rt2x00_dev *rt2x00dev,
+				const unsigned int word, const u8 value)
+{
+	u32 reg;
+
+	mutex_lock(&rt2x00dev->csr_mutex);
+
+	/*
+	 * Wait until the BBP becomes available, afterwards we
+	 * can safely write the new data into the register.
+	 */
+	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+		reg = 0;
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_VALUE, value);
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
+
+		rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
+	}
+
+	mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800usb_bbp_read(struct rt2x00_dev *rt2x00dev,
+			       const unsigned int word, u8 *value)
+{
+	u32 reg;
+
+	mutex_lock(&rt2x00dev->csr_mutex);
+
+	/*
+	 * Wait until the BBP becomes available, afterwards we
+	 * can safely write the read request into the register.
+	 * After the data has been written, we wait until hardware
+	 * returns the correct value, if at any time the register
+	 * doesn't become available in time, reg will be 0xffffffff
+	 * which means we return 0xff to the caller.
+	 */
+	if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+		reg = 0;
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
+
+		rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
+
+		WAIT_FOR_BBP(rt2x00dev, &reg);
+	}
+
+	*value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
+
+	mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800usb_rfcsr_write(struct rt2x00_dev *rt2x00dev,
+				  const unsigned int word, const u8 value)
+{
+	u32 reg;
+
+	mutex_lock(&rt2x00dev->csr_mutex);
+
+	/*
+	 * Wait until the RFCSR becomes available, afterwards we
+	 * can safely write the new data into the register.
+	 */
+	if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+		reg = 0;
+		rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
+		rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+		rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
+		rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
+
+		rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
+	}
+
+	mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800usb_rfcsr_read(struct rt2x00_dev *rt2x00dev,
+				 const unsigned int word, u8 *value)
+{
+	u32 reg;
+
+	mutex_lock(&rt2x00dev->csr_mutex);
+
+	/*
+	 * Wait until the RFCSR becomes available, afterwards we
+	 * can safely write the read request into the register.
+	 * After the data has been written, we wait until hardware
+	 * returns the correct value, if at any time the register
+	 * doesn't become available in time, reg will be 0xffffffff
+	 * which means we return 0xff to the caller.
+	 */
+	if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+		reg = 0;
+		rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+		rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
+		rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
+
+		rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
+
+		WAIT_FOR_RFCSR(rt2x00dev, &reg);
+	}
+
+	*value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
+
+	mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800usb_rf_write(struct rt2x00_dev *rt2x00dev,
+			       const unsigned int word, const u32 value)
+{
+	u32 reg;
+
+	mutex_lock(&rt2x00dev->csr_mutex);
+
+	/*
+	 * Wait until the RF becomes available, afterwards we
+	 * can safely write the new data into the register.
+	 */
+	if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+		reg = 0;
+		rt2x00_set_field32(&reg, RF_CSR_CFG0_REG_VALUE_BW, value);
+		rt2x00_set_field32(&reg, RF_CSR_CFG0_STANDBYMODE, 0);
+		rt2x00_set_field32(&reg, RF_CSR_CFG0_SEL, 0);
+		rt2x00_set_field32(&reg, RF_CSR_CFG0_BUSY, 1);
+
+		rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg);
+		rt2x00_rf_write(rt2x00dev, word, value);
+	}
+
+	mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800usb_mcu_request(struct rt2x00_dev *rt2x00dev,
+				  const u8 command, const u8 token,
+				  const u8 arg0, const u8 arg1)
+{
+	u32 reg;
+
+	mutex_lock(&rt2x00dev->csr_mutex);
+
+	/*
+	 * Wait until the MCU becomes available, afterwards we
+	 * can safely write the new data into the register.
+	 */
+	if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
+		rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
+		rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
+		rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
+		rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
+		rt2x00usb_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
+
+		reg = 0;
+		rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
+		rt2x00usb_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
+	}
+
+	mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+static const struct rt2x00debug rt2800usb_rt2x00debug = {
+	.owner	= THIS_MODULE,
+	.csr	= {
+		.read		= rt2x00usb_register_read,
+		.write		= rt2x00usb_register_write,
+		.flags		= RT2X00DEBUGFS_OFFSET,
+		.word_base	= CSR_REG_BASE,
+		.word_size	= sizeof(u32),
+		.word_count	= CSR_REG_SIZE / sizeof(u32),
+	},
+	.eeprom	= {
+		.read		= rt2x00_eeprom_read,
+		.write		= rt2x00_eeprom_write,
+		.word_base	= EEPROM_BASE,
+		.word_size	= sizeof(u16),
+		.word_count	= EEPROM_SIZE / sizeof(u16),
+	},
+	.bbp	= {
+		.read		= rt2800usb_bbp_read,
+		.write		= rt2800usb_bbp_write,
+		.word_base	= BBP_BASE,
+		.word_size	= sizeof(u8),
+		.word_count	= BBP_SIZE / sizeof(u8),
+	},
+	.rf	= {
+		.read		= rt2x00_rf_read,
+		.write		= rt2800usb_rf_write,
+		.word_base	= RF_BASE,
+		.word_size	= sizeof(u32),
+		.word_count	= RF_SIZE / sizeof(u32),
+	},
+};
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+#ifdef CONFIG_RT2X00_LIB_RFKILL
+static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+
+	rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+	return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
+}
+#else
+#define rt2800usb_rfkill_poll	NULL
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt2800usb_brightness_set(struct led_classdev *led_cdev,
+				     enum led_brightness brightness)
+{
+	struct rt2x00_led *led =
+	    container_of(led_cdev, struct rt2x00_led, led_dev);
+	unsigned int enabled = brightness != LED_OFF;
+	unsigned int bg_mode =
+	    (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+	unsigned int polarity =
+		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
+				   EEPROM_FREQ_LED_POLARITY);
+	unsigned int ledmode =
+		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
+				   EEPROM_FREQ_LED_MODE);
+
+	if (led->type == LED_TYPE_RADIO) {
+		rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+				      enabled ? 0x20 : 0);
+	} else if (led->type == LED_TYPE_ASSOC) {
+		rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+				      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
+	} else if (led->type == LED_TYPE_QUALITY) {
+		/*
+		 * The brightness is divided into 6 levels (0 - 5),
+		 * The specs tell us the following levels:
+		 *	0, 1 ,3, 7, 15, 31
+		 * to determine the level in a simple way we can simply
+		 * work with bitshifting:
+		 *	(1 << level) - 1
+		 */
+		rt2800usb_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+				      (1 << brightness / (LED_FULL / 6)) - 1,
+				      polarity);
+	}
+}
+
+static int rt2800usb_blink_set(struct led_classdev *led_cdev,
+			       unsigned long *delay_on,
+			       unsigned long *delay_off)
+{
+	struct rt2x00_led *led =
+	    container_of(led_cdev, struct rt2x00_led, led_dev);
+	u32 reg;
+
+	rt2x00usb_register_read(led->rt2x00dev, LED_CFG, &reg);
+	rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
+	rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
+	rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
+	rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
+	rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 12);
+	rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
+	rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
+	rt2x00usb_register_write(led->rt2x00dev, LED_CFG, reg);
+
+	return 0;
+}
+
+static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev,
+			       struct rt2x00_led *led,
+			       enum led_type type)
+{
+	led->rt2x00dev = rt2x00dev;
+	led->type = type;
+	led->led_dev.brightness_set = rt2800usb_brightness_set;
+	led->led_dev.blink_set = rt2800usb_blink_set;
+	led->flags = LED_INITIALIZED;
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00lib_crypto *crypto,
+				       struct ieee80211_key_conf *key)
+{
+	struct mac_wcid_entry wcid_entry;
+	struct mac_iveiv_entry iveiv_entry;
+	u32 offset;
+	u32 reg;
+
+	offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
+
+	rt2x00usb_register_read(rt2x00dev, offset, &reg);
+	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
+			   !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
+	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER,
+			   (crypto->cmd == SET_KEY) * crypto->cipher);
+	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
+			   (crypto->cmd == SET_KEY) * crypto->bssidx);
+	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
+	rt2x00usb_register_write(rt2x00dev, offset, reg);
+
+	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
+
+	memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+	if ((crypto->cipher == CIPHER_TKIP) ||
+	    (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
+	    (crypto->cipher == CIPHER_AES))
+		iveiv_entry.iv[3] |= 0x20;
+	iveiv_entry.iv[3] |= key->keyidx << 6;
+	rt2x00usb_register_multiwrite(rt2x00dev, offset,
+				      &iveiv_entry, sizeof(iveiv_entry));
+
+	offset = MAC_WCID_ENTRY(key->hw_key_idx);
+
+	memset(&wcid_entry, 0, sizeof(wcid_entry));
+	if (crypto->cmd == SET_KEY)
+		memcpy(&wcid_entry, crypto->address, ETH_ALEN);
+	rt2x00usb_register_multiwrite(rt2x00dev, offset,
+				      &wcid_entry, sizeof(wcid_entry));
+}
+
+static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00lib_crypto *crypto,
+				       struct ieee80211_key_conf *key)
+{
+	struct hw_key_entry key_entry;
+	struct rt2x00_field32 field;
+	int timeout;
+	u32 offset;
+	u32 reg;
+
+	if (crypto->cmd == SET_KEY) {
+		key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx;
+
+		memcpy(key_entry.key, crypto->key,
+		       sizeof(key_entry.key));
+		memcpy(key_entry.tx_mic, crypto->tx_mic,
+		       sizeof(key_entry.tx_mic));
+		memcpy(key_entry.rx_mic, crypto->rx_mic,
+		       sizeof(key_entry.rx_mic));
+
+		offset = SHARED_KEY_ENTRY(key->hw_key_idx);
+		timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+		rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+						    USB_VENDOR_REQUEST_OUT,
+						    offset, &key_entry,
+						    sizeof(key_entry),
+						    timeout);
+	}
+
+	/*
+	 * The cipher types are stored over multiple registers
+	 * starting with SHARED_KEY_MODE_BASE each word will have
+	 * 32 bits and contains the cipher types for 2 bssidx each.
+	 * Using the correct defines correctly will cause overhead,
+	 * so just calculate the correct offset.
+	 */
+	field.bit_offset = 4 * (key->hw_key_idx % 8);
+	field.bit_mask = 0x7 << field.bit_offset;
+
+	offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
+
+	rt2x00usb_register_read(rt2x00dev, offset, &reg);
+	rt2x00_set_field32(&reg, field,
+			   (crypto->cmd == SET_KEY) * crypto->cipher);
+	rt2x00usb_register_write(rt2x00dev, offset, reg);
+
+	/*
+	 * Update WCID information
+	 */
+	rt2800usb_config_wcid_attr(rt2x00dev, crypto, key);
+
+	return 0;
+}
+
+static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+					 struct rt2x00lib_crypto *crypto,
+					 struct ieee80211_key_conf *key)
+{
+	struct hw_key_entry key_entry;
+	int timeout;
+	u32 offset;
+
+	if (crypto->cmd == SET_KEY) {
+		/*
+		 * 1 pairwise key is possible per AID, this means that the AID
+		 * equals our hw_key_idx. Make sure the WCID starts _after_ the
+		 * last possible shared key entry.
+		 */
+		if (crypto->aid > (256 - 32))
+			return -ENOSPC;
+
+		key->hw_key_idx = 32 + crypto->aid;
+
+		memcpy(key_entry.key, crypto->key,
+		       sizeof(key_entry.key));
+		memcpy(key_entry.tx_mic, crypto->tx_mic,
+		       sizeof(key_entry.tx_mic));
+		memcpy(key_entry.rx_mic, crypto->rx_mic,
+		       sizeof(key_entry.rx_mic));
+
+		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+		timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+		rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+						    USB_VENDOR_REQUEST_OUT,
+						    offset, &key_entry,
+						    sizeof(key_entry),
+						    timeout);
+	}
+
+	/*
+	 * Update WCID information
+	 */
+	rt2800usb_config_wcid_attr(rt2x00dev, crypto, key);
+
+	return 0;
+}
+
+static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev,
+				    const unsigned int filter_flags)
+{
+	u32 reg;
+
+	/*
+	 * Start configuration steps.
+	 * Note that the version error will always be dropped
+	 * and broadcast frames will always be accepted since
+	 * there is no filter for it at this time.
+	 */
+	rt2x00usb_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
+			   !(filter_flags & FIF_FCSFAIL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
+			   !(filter_flags & FIF_PLCPFAIL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME,
+			   !(filter_flags & FIF_PROMISC_IN_BSS));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
+			   !(filter_flags & FIF_ALLMULTI));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BROADCAST, 0);
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_DUPLICATE, 1);
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END_ACK,
+			   !(filter_flags & FIF_CONTROL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END,
+			   !(filter_flags & FIF_CONTROL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_ACK,
+			   !(filter_flags & FIF_CONTROL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CTS,
+			   !(filter_flags & FIF_CONTROL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
+			   !(filter_flags & FIF_CONTROL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
+			   !(filter_flags & FIF_CONTROL));
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 1);
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR, 0);
+	rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
+			   !(filter_flags & FIF_CONTROL));
+	rt2x00usb_register_write(rt2x00dev, RX_FILTER_CFG, reg);
+}
+
+static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev,
+				  struct rt2x00_intf *intf,
+				  struct rt2x00intf_conf *conf,
+				  const unsigned int flags)
+{
+	unsigned int beacon_base;
+	u32 reg;
+
+	if (flags & CONFIG_UPDATE_TYPE) {
+		/*
+		 * Clear current synchronisation setup.
+		 * For the Beacon base registers we only need to clear
+		 * the first byte since that byte contains the VALID and OWNER
+		 * bits which (when set to 0) will invalidate the entire beacon.
+		 */
+		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
+		rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
+
+		/*
+		 * Enable synchronisation.
+		 */
+		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
+		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+	}
+
+	if (flags & CONFIG_UPDATE_MAC) {
+		reg = le32_to_cpu(conf->mac[1]);
+		rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
+		conf->mac[1] = cpu_to_le32(reg);
+
+		rt2x00usb_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
+					      conf->mac, sizeof(conf->mac));
+	}
+
+	if (flags & CONFIG_UPDATE_BSSID) {
+		reg = le32_to_cpu(conf->bssid[1]);
+		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 0);
+		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
+		conf->bssid[1] = cpu_to_le32(reg);
+
+		rt2x00usb_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
+					      conf->bssid, sizeof(conf->bssid));
+	}
+}
+
+static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev,
+				 struct rt2x00lib_erp *erp)
+{
+	u32 reg;
+
+	rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT,
+			   DIV_ROUND_UP(erp->ack_timeout, erp->slot_time));
+	rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+	rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
+			   !!erp->short_preamble);
+	rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
+			   !!erp->short_preamble);
+	rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
+			   erp->cts_protection ? 2 : 0);
+	rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+	rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE,
+				 erp->basic_rates);
+	rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+
+	rt2x00usb_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+	rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time);
+	rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
+	rt2x00usb_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+	rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs);
+	rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs);
+	rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
+	rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
+	rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
+	rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+			   erp->beacon_int * 16);
+	rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+}
+
+static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev,
+				 struct antenna_setup *ant)
+{
+	u8 r1;
+	u8 r3;
+
+	rt2800usb_bbp_read(rt2x00dev, 1, &r1);
+	rt2800usb_bbp_read(rt2x00dev, 3, &r3);
+
+	/*
+	 * Configure the TX antenna.
+	 */
+	switch ((int)ant->tx) {
+	case 1:
+		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
+		break;
+	case 2:
+		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+		break;
+	case 3:
+		/* Do nothing */
+		break;
+	}
+
+	/*
+	 * Configure the RX antenna.
+	 */
+	switch ((int)ant->rx) {
+	case 1:
+		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
+		break;
+	case 2:
+		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+		break;
+	case 3:
+		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
+		break;
+	}
+
+	rt2800usb_bbp_write(rt2x00dev, 3, r3);
+	rt2800usb_bbp_write(rt2x00dev, 1, r1);
+}
+
+static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+				      struct rt2x00lib_conf *libconf)
+{
+	u16 eeprom;
+	short lna_gain;
+
+	if (libconf->rf.channel <= 14) {
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
+	} else if (libconf->rf.channel <= 64) {
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
+	} else if (libconf->rf.channel <= 128) {
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1);
+	} else {
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2);
+	}
+
+	rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev,
+					  struct ieee80211_conf *conf,
+					  struct rf_channel *rf,
+					  struct channel_info *info)
+{
+	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+	if (rt2x00dev->default_ant.tx == 1)
+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
+
+	if (rt2x00dev->default_ant.rx == 1) {
+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
+	} else if (rt2x00dev->default_ant.rx == 2)
+		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
+
+	if (rf->channel > 14) {
+		/*
+		 * When TX power is below 0, we should increase it by 7 to
+		 * make it a positive value (Minumum value is -7).
+		 * However this means that values between 0 and 7 have
+		 * double meaning, and we should set a 7DBm boost flag.
+		 */
+		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
+				   (info->tx_power1 >= 0));
+
+		if (info->tx_power1 < 0)
+			info->tx_power1 += 7;
+
+		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A,
+				   TXPOWER_A_TO_DEV(info->tx_power1));
+
+		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
+				   (info->tx_power2 >= 0));
+
+		if (info->tx_power2 < 0)
+			info->tx_power2 += 7;
+
+		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A,
+				   TXPOWER_A_TO_DEV(info->tx_power2));
+	} else {
+		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G,
+				   TXPOWER_G_TO_DEV(info->tx_power1));
+		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G,
+				   TXPOWER_G_TO_DEV(info->tx_power2));
+	}
+
+	rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
+
+	rt2800usb_rf_write(rt2x00dev, 1, rf->rf1);
+	rt2800usb_rf_write(rt2x00dev, 2, rf->rf2);
+	rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+	rt2800usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+	udelay(200);
+
+	rt2800usb_rf_write(rt2x00dev, 1, rf->rf1);
+	rt2800usb_rf_write(rt2x00dev, 2, rf->rf2);
+	rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+	rt2800usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+	udelay(200);
+
+	rt2800usb_rf_write(rt2x00dev, 1, rf->rf1);
+	rt2800usb_rf_write(rt2x00dev, 2, rf->rf2);
+	rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+	rt2800usb_rf_write(rt2x00dev, 4, rf->rf4);
+}
+
+static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
+					  struct ieee80211_conf *conf,
+					  struct rf_channel *rf,
+					  struct channel_info *info)
+{
+	u8 rfcsr;
+
+	rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf1);
+	rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf3);
+
+	rt2800usb_rfcsr_read(rt2x00dev, 6, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
+	rt2800usb_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+	rt2800usb_rfcsr_read(rt2x00dev, 12, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+			  TXPOWER_G_TO_DEV(info->tx_power1));
+	rt2800usb_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+	rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+	rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+	rt2800usb_rfcsr_write(rt2x00dev, 24,
+			      rt2x00dev->calibration[conf_is_ht40(conf)]);
+
+	rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+	rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr);
+}
+
+static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_conf *conf,
+				     struct rf_channel *rf,
+				     struct channel_info *info)
+{
+	u32 reg;
+	unsigned int tx_pin;
+	u8 bbp;
+
+	if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
+		rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info);
+	else
+		rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info);
+
+	/*
+	 * Change BBP settings
+	 */
+	rt2800usb_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+	rt2800usb_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+	rt2800usb_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+	rt2800usb_bbp_write(rt2x00dev, 86, 0);
+
+	if (rf->channel <= 14) {
+		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+			rt2800usb_bbp_write(rt2x00dev, 82, 0x62);
+			rt2800usb_bbp_write(rt2x00dev, 75, 0x46);
+		} else {
+			rt2800usb_bbp_write(rt2x00dev, 82, 0x84);
+			rt2800usb_bbp_write(rt2x00dev, 75, 0x50);
+		}
+	} else {
+		rt2800usb_bbp_write(rt2x00dev, 82, 0xf2);
+
+		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+			rt2800usb_bbp_write(rt2x00dev, 75, 0x46);
+		else
+			rt2800usb_bbp_write(rt2x00dev, 75, 0x50);
+	}
+
+	rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
+	rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
+	rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
+	rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg);
+
+	tx_pin = 0;
+
+	/* Turn on unused PA or LNA when not using 1T or 1R */
+	if (rt2x00dev->default_ant.tx != 1) {
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+	}
+
+	/* Turn on unused PA or LNA when not using 1T or 1R */
+	if (rt2x00dev->default_ant.rx != 1) {
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
+		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
+	}
+
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
+	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
+
+	rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+
+	rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
+	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
+	rt2800usb_bbp_write(rt2x00dev, 4, bbp);
+
+	rt2800usb_bbp_read(rt2x00dev, 3, &bbp);
+	rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
+	rt2800usb_bbp_write(rt2x00dev, 3, bbp);
+
+	if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
+		if (conf_is_ht40(conf)) {
+			rt2800usb_bbp_write(rt2x00dev, 69, 0x1a);
+			rt2800usb_bbp_write(rt2x00dev, 70, 0x0a);
+			rt2800usb_bbp_write(rt2x00dev, 73, 0x16);
+		} else {
+			rt2800usb_bbp_write(rt2x00dev, 69, 0x16);
+			rt2800usb_bbp_write(rt2x00dev, 70, 0x08);
+			rt2800usb_bbp_write(rt2x00dev, 73, 0x11);
+		}
+	}
+
+	msleep(1);
+}
+
+static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev,
+				     const int txpower)
+{
+	u32 reg;
+	u32 value = TXPOWER_G_TO_DEV(txpower);
+	u8 r1;
+
+	rt2800usb_bbp_read(rt2x00dev, 1, &r1);
+	rt2x00_set_field8(&reg, BBP1_TX_POWER, 0);
+	rt2800usb_bbp_write(rt2x00dev, 1, r1);
+
+	rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_1MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_2MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_55MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_11MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_6MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_9MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_12MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_0_18MBS, value);
+	rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_0, reg);
+
+	rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_1, &reg);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_24MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_36MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_48MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_54MBS, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS0, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS1, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS2, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS3, value);
+	rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_1, reg);
+
+	rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_2, &reg);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS4, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS5, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS6, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS7, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS8, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS9, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS10, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS11, value);
+	rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_2, reg);
+
+	rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_3, &reg);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS12, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS13, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS14, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS15, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN1, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN2, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN3, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN4, value);
+	rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_3, reg);
+
+	rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_4, &reg);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN5, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN6, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN7, value);
+	rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN8, value);
+	rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_4, reg);
+}
+
+static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+					 struct rt2x00lib_conf *libconf)
+{
+	u32 reg;
+
+	rt2x00usb_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
+			   libconf->conf->short_frame_max_tx_count);
+	rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
+			   libconf->conf->long_frame_max_tx_count);
+	rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
+	rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
+	rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
+	rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
+	rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg);
+}
+
+static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev,
+				struct rt2x00lib_conf *libconf)
+{
+	enum dev_state state =
+	    (libconf->conf->flags & IEEE80211_CONF_PS) ?
+		STATE_SLEEP : STATE_AWAKE;
+	u32 reg;
+
+	if (state == STATE_SLEEP) {
+		rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
+
+		rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
+				   libconf->conf->listen_interval - 1);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 1);
+		rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+
+		rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+	} else {
+		rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+
+		rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
+		rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
+		rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+	}
+}
+
+static void rt2800usb_config(struct rt2x00_dev *rt2x00dev,
+			     struct rt2x00lib_conf *libconf,
+			     const unsigned int flags)
+{
+	/* Always recalculate LNA gain before changing configuration */
+	rt2800usb_config_lna_gain(rt2x00dev, libconf);
+
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+		rt2800usb_config_channel(rt2x00dev, libconf->conf,
+					 &libconf->rf, &libconf->channel);
+	if (flags & IEEE80211_CONF_CHANGE_POWER)
+		rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level);
+	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		rt2800usb_config_retry_limit(rt2x00dev, libconf);
+	if (flags & IEEE80211_CONF_CHANGE_PS)
+		rt2800usb_config_ps(rt2x00dev, libconf);
+}
+
+/*
+ * Link tuning
+ */
+static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev,
+				 struct link_qual *qual)
+{
+	u32 reg;
+
+	/*
+	 * Update FCS error count from register.
+	 */
+	rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+	qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
+}
+
+static u8 rt2800usb_get_default_vgc(struct rt2x00_dev *rt2x00dev)
+{
+	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
+		if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION)
+			return 0x1c + (2 * rt2x00dev->lna_gain);
+		else
+			return 0x2e + rt2x00dev->lna_gain;
+	}
+
+	if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+		return 0x32 + (rt2x00dev->lna_gain * 5) / 3;
+	else
+		return 0x3a + (rt2x00dev->lna_gain * 5) / 3;
+}
+
+static inline void rt2800usb_set_vgc(struct rt2x00_dev *rt2x00dev,
+				     struct link_qual *qual, u8 vgc_level)
+{
+	if (qual->vgc_level != vgc_level) {
+		rt2800usb_bbp_write(rt2x00dev, 66, vgc_level);
+		qual->vgc_level = vgc_level;
+		qual->vgc_level_reg = vgc_level;
+	}
+}
+
+static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+				  struct link_qual *qual)
+{
+	rt2800usb_set_vgc(rt2x00dev, qual,
+			  rt2800usb_get_default_vgc(rt2x00dev));
+}
+
+static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev,
+				 struct link_qual *qual, const u32 count)
+{
+	if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION)
+		return;
+
+	/*
+	 * When RSSI is better then -80 increase VGC level with 0x10
+	 */
+	rt2800usb_set_vgc(rt2x00dev, qual,
+			  rt2800usb_get_default_vgc(rt2x00dev) +
+			  ((qual->rssi > -80) * 0x10));
+}
+
+/*
+ * Firmware functions
+ */
+static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+{
+	return FIRMWARE_RT2870;
+}
+
+static bool rt2800usb_check_crc(const u8 *data, const size_t len)
+{
+	u16 fw_crc;
+	u16 crc;
+
+	/*
+	 * The last 2 bytes in the firmware array are the crc checksum itself,
+	 * this means that we should never pass those 2 bytes to the crc
+	 * algorithm.
+	 */
+	fw_crc = (data[len - 2] << 8 | data[len - 1]);
+
+	/*
+	 * Use the crc ccitt algorithm.
+	 * This will return the same value as the legacy driver which
+	 * used bit ordering reversion on the both the firmware bytes
+	 * before input input as well as on the final output.
+	 * Obviously using crc ccitt directly is much more efficient.
+	 */
+	crc = crc_ccitt(~0, data, len - 2);
+
+	/*
+	 * There is a small difference between the crc-itu-t + bitrev and
+	 * the crc-ccitt crc calculation. In the latter method the 2 bytes
+	 * will be swapped, use swab16 to convert the crc to the correct
+	 * value.
+	 */
+	crc = swab16(crc);
+
+	return fw_crc == crc;
+}
+
+static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
+				    const u8 *data, const size_t len)
+{
+	u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff;
+	size_t offset = 0;
+
+	/*
+	 * Firmware files:
+	 * There are 2 variations of the rt2870 firmware.
+	 * a) size: 4kb
+	 * b) size: 8kb
+	 * Note that (b) contains 2 seperate firmware blobs of 4k
+	 * within the file. The first blob is the same firmware as (a),
+	 * but the second blob is for the additional chipsets.
+	 */
+	if (len != 4096 && len != 8192)
+		return FW_BAD_LENGTH;
+
+	/*
+	 * Check if we need the upper 4kb firmware data or not.
+	 */
+	if ((len == 4096) &&
+	    (chipset != 0x2860) &&
+	    (chipset != 0x2872) &&
+	    (chipset != 0x3070))
+		return FW_BAD_VERSION;
+
+	/*
+	 * 8kb firmware files must be checked as if it were
+	 * 2 seperate firmware files.
+	 */
+	while (offset < len) {
+		if (!rt2800usb_check_crc(data + offset, 4096))
+			return FW_BAD_CRC;
+
+		offset += 4096;
+	}
+
+	return FW_OK;
+}
+
+static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
+				   const u8 *data, const size_t len)
+{
+	unsigned int i;
+	int status;
+	u32 reg;
+	u32 offset;
+	u32 length;
+	u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff;
+
+	/*
+	 * Check which section of the firmware we need.
+	 */
+	if ((chipset == 0x2860) ||
+	    (chipset == 0x2872) ||
+	    (chipset == 0x3070)) {
+		offset = 0;
+		length = 4096;
+	} else {
+		offset = 4096;
+		length = 4096;
+	}
+
+	/*
+	 * Wait for stable hardware.
+	 */
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+		if (reg && reg != ~0)
+			break;
+		msleep(1);
+	}
+
+	if (i == REGISTER_BUSY_COUNT) {
+		ERROR(rt2x00dev, "Unstable hardware.\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Write firmware to device.
+	 */
+	rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+					    USB_VENDOR_REQUEST_OUT,
+					    FIRMWARE_IMAGE_BASE,
+					    data + offset, length,
+					    REGISTER_TIMEOUT32(length));
+
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+
+	/*
+	 * Send firmware request to device to load firmware,
+	 * we need to specify a long timeout time.
+	 */
+	status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
+					     0, USB_MODE_FIRMWARE,
+					     REGISTER_TIMEOUT_FIRMWARE);
+	if (status < 0) {
+		ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
+		return status;
+	}
+
+	msleep(10);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+
+	/*
+	 * Send signal to firmware during boot time.
+	 */
+	rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0);
+
+	if ((chipset == 0x3070) ||
+	    (chipset == 0x3071) ||
+	    (chipset == 0x3572)) {
+		udelay(200);
+		rt2800usb_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
+		udelay(10);
+	}
+
+	/*
+	 * Wait for device to stabilize.
+	 */
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+		if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
+			break;
+		msleep(1);
+	}
+
+	if (i == REGISTER_BUSY_COUNT) {
+		ERROR(rt2x00dev, "PBF system register not ready.\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Initialize firmware.
+	 */
+	rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	msleep(1);
+
+	return 0;
+}
+
+/*
+ * Initialization functions.
+ */
+static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	unsigned int i;
+
+	/*
+	 * Wait untill BBP and RF are ready.
+	 */
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+		if (reg && reg != ~0)
+			break;
+		msleep(1);
+	}
+
+	if (i == REGISTER_BUSY_COUNT) {
+		ERROR(rt2x00dev, "Unstable hardware.\n");
+		return -EBUSY;
+	}
+
+	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+
+	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
+
+	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+				    USB_MODE_RESET, REGISTER_TIMEOUT);
+
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+
+	rt2x00usb_register_read(rt2x00dev, BCN_OFFSET0, &reg);
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */
+	rt2x00usb_register_write(rt2x00dev, BCN_OFFSET0, reg);
+
+	rt2x00usb_register_read(rt2x00dev, BCN_OFFSET1, &reg);
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */
+	rt2x00usb_register_write(rt2x00dev, BCN_OFFSET1, reg);
+
+	rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
+	rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+
+	rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
+	rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+	if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
+		rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+		rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+		rt2x00usb_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+	} else {
+		rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
+		rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+	}
+
+	rt2x00usb_register_read(rt2x00dev, TX_LINK_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
+	rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
+	rt2x00usb_register_write(rt2x00dev, TX_LINK_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
+	rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
+	rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+	rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
+	if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION &&
+	    rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION)
+		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
+	else
+		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
+	rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 0);
+	rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 0);
+	rt2x00usb_register_write(rt2x00dev, MAX_LEN_CFG, reg);
+
+	rt2x00usb_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
+
+	rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+	rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
+	rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
+	rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
+	rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
+	rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
+	rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 8);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+	rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 8);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+	rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+	rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+	rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+	rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+	rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+
+	rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+
+	rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_BIG_ENDIAN, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);
+	rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+	rt2x00usb_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f);
+	rt2x00usb_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
+
+	rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
+	rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
+			   IEEE80211_MAX_RTS_THRESHOLD);
+	rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_FBK_EN, 0);
+	rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg);
+
+	rt2x00usb_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
+	rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
+	/*
+	 * ASIC will keep garbage value after boot, clear encryption keys.
+	 */
+	for (i = 0; i < 256; i++) {
+		u32 wcid[2] = { 0xffffffff, 0x00ffffff };
+		rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
+					      wcid, sizeof(wcid));
+
+		rt2x00usb_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1);
+		rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+	}
+
+	for (i = 0; i < 16; i++)
+		rt2x00usb_register_write(rt2x00dev,
+					 SHARED_KEY_MODE_ENTRY(i), 0);
+
+	/*
+	 * Clear all beacons
+	 * For the Beacon base registers we only need to clear
+	 * the first byte since that byte contains the VALID and OWNER
+	 * bits which (when set to 0) will invalidate the entire beacon.
+	 */
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE4, 0);
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE5, 0);
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
+	rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
+
+	rt2x00usb_register_read(rt2x00dev, USB_CYC_CFG, &reg);
+	rt2x00_set_field32(&reg, USB_CYC_CFG_CLOCK_CYCLE, 30);
+	rt2x00usb_register_write(rt2x00dev, USB_CYC_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS3FBK, 2);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS4FBK, 3);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS5FBK, 4);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS6FBK, 5);
+	rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
+	rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG0, reg);
+
+	rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS11FBK, 10);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS12FBK, 11);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS13FBK, 12);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS14FBK, 13);
+	rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
+	rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG1, reg);
+
+	rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 3);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS3FBK, 10);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS5FBK, 12);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS6FBK, 13);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
+	rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG0, reg);
+
+	rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
+	rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS3FBK, 2);
+	rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG1, reg);
+
+	/*
+	 * We must clear the error counters.
+	 * These registers are cleared on read,
+	 * so we may pass a useless variable to store the value.
+	 */
+	rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+	rt2x00usb_register_read(rt2x00dev, RX_STA_CNT1, &reg);
+	rt2x00usb_register_read(rt2x00dev, RX_STA_CNT2, &reg);
+	rt2x00usb_register_read(rt2x00dev, TX_STA_CNT0, &reg);
+	rt2x00usb_register_read(rt2x00dev, TX_STA_CNT1, &reg);
+	rt2x00usb_register_read(rt2x00dev, TX_STA_CNT2, &reg);
+
+	return 0;
+}
+
+static int rt2800usb_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
+{
+	unsigned int i;
+	u32 reg;
+
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2x00usb_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
+		if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
+			return 0;
+
+		udelay(REGISTER_BUSY_DELAY);
+	}
+
+	ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n");
+	return -EACCES;
+}
+
+static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+	unsigned int i;
+	u8 value;
+
+	/*
+	 * BBP was enabled after firmware was loaded,
+	 * but we need to reactivate it now.
+	 */
+	rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	msleep(1);
+
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2800usb_bbp_read(rt2x00dev, 0, &value);
+		if ((value != 0xff) && (value != 0x00))
+			return 0;
+		udelay(REGISTER_BUSY_DELAY);
+	}
+
+	ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+	return -EACCES;
+}
+
+static int rt2800usb_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+	unsigned int i;
+	u16 eeprom;
+	u8 reg_id;
+	u8 value;
+
+	if (unlikely(rt2800usb_wait_bbp_rf_ready(rt2x00dev) ||
+		     rt2800usb_wait_bbp_ready(rt2x00dev)))
+		return -EACCES;
+
+	rt2800usb_bbp_write(rt2x00dev, 65, 0x2c);
+	rt2800usb_bbp_write(rt2x00dev, 66, 0x38);
+	rt2800usb_bbp_write(rt2x00dev, 69, 0x12);
+	rt2800usb_bbp_write(rt2x00dev, 70, 0x0a);
+	rt2800usb_bbp_write(rt2x00dev, 73, 0x10);
+	rt2800usb_bbp_write(rt2x00dev, 81, 0x37);
+	rt2800usb_bbp_write(rt2x00dev, 82, 0x62);
+	rt2800usb_bbp_write(rt2x00dev, 83, 0x6a);
+	rt2800usb_bbp_write(rt2x00dev, 84, 0x99);
+	rt2800usb_bbp_write(rt2x00dev, 86, 0x00);
+	rt2800usb_bbp_write(rt2x00dev, 91, 0x04);
+	rt2800usb_bbp_write(rt2x00dev, 92, 0x00);
+	rt2800usb_bbp_write(rt2x00dev, 103, 0x00);
+	rt2800usb_bbp_write(rt2x00dev, 105, 0x05);
+
+	if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
+		rt2800usb_bbp_write(rt2x00dev, 69, 0x16);
+		rt2800usb_bbp_write(rt2x00dev, 73, 0x12);
+	}
+
+	if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) {
+		rt2800usb_bbp_write(rt2x00dev, 84, 0x19);
+	}
+
+	if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
+		rt2800usb_bbp_write(rt2x00dev, 70, 0x0a);
+		rt2800usb_bbp_write(rt2x00dev, 84, 0x99);
+		rt2800usb_bbp_write(rt2x00dev, 105, 0x05);
+	}
+
+	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+		if (eeprom != 0xffff && eeprom != 0x0000) {
+			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+			value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+			rt2800usb_bbp_write(rt2x00dev, reg_id, value);
+		}
+	}
+
+	return 0;
+}
+
+static u8 rt2800usb_init_rx_filter(struct rt2x00_dev *rt2x00dev,
+				   bool bw40, u8 rfcsr24, u8 filter_target)
+{
+	unsigned int i;
+	u8 bbp;
+	u8 rfcsr;
+	u8 passband;
+	u8 stopband;
+	u8 overtuned = 0;
+
+	rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24);
+
+	rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
+	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
+	rt2800usb_bbp_write(rt2x00dev, 4, bbp);
+
+	rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
+	rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+	/*
+	 * Set power & frequency of passband test tone
+	 */
+	rt2800usb_bbp_write(rt2x00dev, 24, 0);
+
+	for (i = 0; i < 100; i++) {
+		rt2800usb_bbp_write(rt2x00dev, 25, 0x90);
+		msleep(1);
+
+		rt2800usb_bbp_read(rt2x00dev, 55, &passband);
+		if (passband)
+			break;
+	}
+
+	/*
+	 * Set power & frequency of stopband test tone
+	 */
+	rt2800usb_bbp_write(rt2x00dev, 24, 0x06);
+
+	for (i = 0; i < 100; i++) {
+		rt2800usb_bbp_write(rt2x00dev, 25, 0x90);
+		msleep(1);
+
+		rt2800usb_bbp_read(rt2x00dev, 55, &stopband);
+
+		if ((passband - stopband) <= filter_target) {
+			rfcsr24++;
+			overtuned += ((passband - stopband) == filter_target);
+		} else
+			break;
+
+		rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24);
+	}
+
+	rfcsr24 -= !!overtuned;
+
+	rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24);
+	return rfcsr24;
+}
+
+static int rt2800usb_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+{
+	u8 rfcsr;
+	u8 bbp;
+
+	if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
+		return 0;
+
+	/*
+	 * Init RF calibration.
+	 */
+	rt2800usb_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+	rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr);
+	msleep(1);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
+	rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	rt2800usb_rfcsr_write(rt2x00dev, 4, 0x40);
+	rt2800usb_rfcsr_write(rt2x00dev, 5, 0x03);
+	rt2800usb_rfcsr_write(rt2x00dev, 6, 0x02);
+	rt2800usb_rfcsr_write(rt2x00dev, 7, 0x70);
+	rt2800usb_rfcsr_write(rt2x00dev, 9, 0x0f);
+	rt2800usb_rfcsr_write(rt2x00dev, 10, 0x71);
+	rt2800usb_rfcsr_write(rt2x00dev, 11, 0x21);
+	rt2800usb_rfcsr_write(rt2x00dev, 12, 0x7b);
+	rt2800usb_rfcsr_write(rt2x00dev, 14, 0x90);
+	rt2800usb_rfcsr_write(rt2x00dev, 15, 0x58);
+	rt2800usb_rfcsr_write(rt2x00dev, 16, 0xb3);
+	rt2800usb_rfcsr_write(rt2x00dev, 17, 0x92);
+	rt2800usb_rfcsr_write(rt2x00dev, 18, 0x2c);
+	rt2800usb_rfcsr_write(rt2x00dev, 19, 0x02);
+	rt2800usb_rfcsr_write(rt2x00dev, 20, 0xba);
+	rt2800usb_rfcsr_write(rt2x00dev, 21, 0xdb);
+	rt2800usb_rfcsr_write(rt2x00dev, 24, 0x16);
+	rt2800usb_rfcsr_write(rt2x00dev, 25, 0x01);
+	rt2800usb_rfcsr_write(rt2x00dev, 27, 0x03);
+	rt2800usb_rfcsr_write(rt2x00dev, 29, 0x1f);
+
+	/*
+	 * Set RX Filter calibration for 20MHz and 40MHz
+	 */
+	rt2x00dev->calibration[0] =
+	    rt2800usb_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
+	rt2x00dev->calibration[1] =
+	    rt2800usb_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
+
+	/*
+	 * Set back to initial state
+	 */
+	rt2800usb_bbp_write(rt2x00dev, 24, 0);
+
+	rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
+	rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+	/*
+	 * set BBP back to BW20
+	 */
+	rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
+	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
+	rt2800usb_bbp_write(rt2x00dev, 4, bbp);
+
+	return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
+				enum dev_state state)
+{
+	u32 reg;
+
+	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
+			   (state == STATE_RADIO_RX_ON) ||
+			   (state == STATE_RADIO_RX_ON_LINK));
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+}
+
+static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
+{
+	unsigned int i;
+	u32 reg;
+
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+		if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
+		    !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
+			return 0;
+
+		msleep(1);
+	}
+
+	ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
+	return -EACCES;
+}
+
+static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u16 word;
+
+	/*
+	 * Initialize all registers.
+	 */
+	if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) ||
+		     rt2800usb_init_registers(rt2x00dev) ||
+		     rt2800usb_init_bbp(rt2x00dev) ||
+		     rt2800usb_init_rfcsr(rt2x00dev)))
+		return -EIO;
+
+	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+	udelay(50);
+
+	rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
+	rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+
+	rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
+	rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
+	/* Don't use bulk in aggregation when working with USB 1.1 */
+	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN,
+			   (rt2x00dev->rx->usb_maxpacket == 512));
+	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
+	/*
+	 * Total room for RX frames in kilobytes, PBF might still exceed
+	 * this limit so reduce the number to prevent errors.
+	 */
+	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
+			   ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3);
+	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
+	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
+	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+	/*
+	 * Initialize LED control
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
+	rt2800usb_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
+			      word & 0xff, (word >> 8) & 0xff);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
+	rt2800usb_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
+			      word & 0xff, (word >> 8) & 0xff);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
+	rt2800usb_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
+			      word & 0xff, (word >> 8) & 0xff);
+
+	return 0;
+}
+
+static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+
+	rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+	rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
+	rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+	rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, 0);
+
+	/* Wait for DMA, ignore error */
+	rt2800usb_wait_wpdma_ready(rt2x00dev);
+
+	rt2x00usb_disable_radio(rt2x00dev);
+}
+
+static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
+			       enum dev_state state)
+{
+	if (state == STATE_AWAKE)
+		rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
+	else
+		rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
+
+	return 0;
+}
+
+static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+				      enum dev_state state)
+{
+	int retval = 0;
+
+	switch (state) {
+	case STATE_RADIO_ON:
+		/*
+		 * Before the radio can be enabled, the device first has
+		 * to be woken up. After that it needs a bit of time
+		 * to be fully awake and the radio can be enabled.
+		 */
+		rt2800usb_set_state(rt2x00dev, STATE_AWAKE);
+		msleep(1);
+		retval = rt2800usb_enable_radio(rt2x00dev);
+		break;
+	case STATE_RADIO_OFF:
+		/*
+		 * After the radio has been disablee, the device should
+		 * be put to sleep for powersaving.
+		 */
+		rt2800usb_disable_radio(rt2x00dev);
+		rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
+		break;
+	case STATE_RADIO_RX_ON:
+	case STATE_RADIO_RX_ON_LINK:
+	case STATE_RADIO_RX_OFF:
+	case STATE_RADIO_RX_OFF_LINK:
+		rt2800usb_toggle_rx(rt2x00dev, state);
+		break;
+	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_OFF:
+		/* No support, but no error either */
+		break;
+	case STATE_DEEP_SLEEP:
+	case STATE_SLEEP:
+	case STATE_STANDBY:
+	case STATE_AWAKE:
+		retval = rt2800usb_set_state(rt2x00dev, state);
+		break;
+	default:
+		retval = -ENOTSUPP;
+		break;
+	}
+
+	if (unlikely(retval))
+		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
+		      state, retval);
+
+	return retval;
+}
+
+/*
+ * TX descriptor initialization
+ */
+static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+				    struct sk_buff *skb,
+				    struct txentry_desc *txdesc)
+{
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+	__le32 *txi = skbdesc->desc;
+	__le32 *txwi = &txi[TXINFO_DESC_SIZE / sizeof(__le32)];
+	u32 word;
+
+	/*
+	 * Initialize TX Info descriptor
+	 */
+	rt2x00_desc_read(txwi, 0, &word);
+	rt2x00_set_field32(&word, TXWI_W0_FRAG,
+			   test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0);
+	rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
+	rt2x00_set_field32(&word, TXWI_W0_TS,
+			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W0_AMPDU,
+			   test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
+	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs);
+	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
+	rt2x00_set_field32(&word, TXWI_W0_BW,
+			   test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
+			   test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc);
+	rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
+	rt2x00_desc_write(txwi, 0, word);
+
+	rt2x00_desc_read(txwi, 1, &word);
+	rt2x00_set_field32(&word, TXWI_W1_ACK,
+			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W1_NSEQ,
+			   test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
+	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
+	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
+			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
+			       txdesc->key_idx : 0xff);
+	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
+			   skb->len - txdesc->l2pad);
+	rt2x00_set_field32(&word, TXWI_W1_PACKETID,
+			   skbdesc->entry->entry_idx);
+	rt2x00_desc_write(txwi, 1, word);
+
+	/*
+	 * Always write 0 to IV/EIV fields, hardware will insert the IV
+	 * from the IVEIV register when TXINFO_W0_WIV is set to 0.
+	 * When TXINFO_W0_WIV is set to 1 it will use the IV data
+	 * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
+	 * crypto entry in the registers should be used to encrypt the frame.
+	 */
+	_rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
+	_rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
+
+	/*
+	 * Initialize TX descriptor
+	 */
+	rt2x00_desc_read(txi, 0, &word);
+	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
+			   skb->len + TXWI_DESC_SIZE);
+	rt2x00_set_field32(&word, TXINFO_W0_WIV,
+			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
+	rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
+	rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0);
+	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0);
+	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST,
+			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+	rt2x00_desc_write(txi, 0, word);
+}
+
+/*
+ * TX data initialization
+ */
+static void rt2800usb_write_beacon(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	unsigned int beacon_base;
+	u32 reg;
+
+	/*
+	 * Add the descriptor in front of the skb.
+	 */
+	skb_push(entry->skb, entry->queue->desc_size);
+	memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
+	skbdesc->desc = entry->skb->data;
+
+	/*
+	 * Disable beaconing while we are reloading the beacon data,
+	 * otherwise we might be sending out invalid data.
+	 */
+	rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+	rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+	/*
+	 * Write entire beacon with descriptor to register.
+	 */
+	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+	rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+					    USB_VENDOR_REQUEST_OUT, beacon_base,
+					    entry->skb->data, entry->skb->len,
+					    REGISTER_TIMEOUT32(entry->skb->len));
+
+	/*
+	 * Clean up the beacon skb.
+	 */
+	dev_kfree_skb(entry->skb);
+	entry->skb = NULL;
+}
+
+static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
+{
+	int length;
+
+	/*
+	 * The length _must_ include 4 bytes padding,
+	 * it should always be multiple of 4,
+	 * but it must _not_ be a multiple of the USB packet size.
+	 */
+	length = roundup(entry->skb->len + 4, 4);
+	length += (4 * !(length % entry->queue->usb_maxpacket));
+
+	return length;
+}
+
+static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+				    const enum data_queue_qid queue)
+{
+	u32 reg;
+
+	if (queue != QID_BEACON) {
+		rt2x00usb_kick_tx_queue(rt2x00dev, queue);
+		return;
+	}
+
+	rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) {
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
+		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+	}
+}
+
+/*
+ * RX control handlers
+ */
+static void rt2800usb_fill_rxdone(struct queue_entry *entry,
+				  struct rxdone_entry_desc *rxdesc)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+	__le32 *rxd = (__le32 *)entry->skb->data;
+	__le32 *rxwi;
+	u32 rxd0;
+	u32 rxwi0;
+	u32 rxwi1;
+	u32 rxwi2;
+	u32 rxwi3;
+
+	/*
+	 * Copy descriptor to the skbdesc->desc buffer, making it safe from
+	 * moving of frame data in rt2x00usb.
+	 */
+	memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
+	rxd = (__le32 *)skbdesc->desc;
+	rxwi = &rxd[RXD_DESC_SIZE / sizeof(__le32)];
+
+	/*
+	 * It is now safe to read the descriptor on all architectures.
+	 */
+	rt2x00_desc_read(rxd, 0, &rxd0);
+	rt2x00_desc_read(rxwi, 0, &rxwi0);
+	rt2x00_desc_read(rxwi, 1, &rxwi1);
+	rt2x00_desc_read(rxwi, 2, &rxwi2);
+	rt2x00_desc_read(rxwi, 3, &rxwi3);
+
+	if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR))
+		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+		rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
+		rxdesc->cipher_status =
+		    rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR);
+	}
+
+	if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) {
+		/*
+		 * Hardware has stripped IV/EIV data from 802.11 frame during
+		 * decryption. Unfortunately the descriptor doesn't contain
+		 * any fields with the EIV/IV data either, so they can't
+		 * be restored by rt2x00lib.
+		 */
+		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+			rxdesc->flags |= RX_FLAG_DECRYPTED;
+		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+	}
+
+	if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS))
+		rxdesc->dev_flags |= RXDONE_MY_BSS;
+
+	if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD))
+		rxdesc->dev_flags |= RXDONE_L2PAD;
+
+	if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
+		rxdesc->flags |= RX_FLAG_SHORT_GI;
+
+	if (rt2x00_get_field32(rxwi1, RXWI_W1_BW))
+		rxdesc->flags |= RX_FLAG_40MHZ;
+
+	/*
+	 * Detect RX rate, always use MCS as signal type.
+	 */
+	rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;
+	rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE);
+	rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS);
+
+	/*
+	 * Mask of 0x8 bit to remove the short preamble flag.
+	 */
+	if (rxdesc->rate_mode == RATE_MODE_CCK)
+		rxdesc->signal &= ~0x8;
+
+	rxdesc->rssi =
+	    (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
+	     rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
+
+	rxdesc->noise =
+	    (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) +
+	     rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2;
+
+	rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
+
+	/*
+	 * Remove RXWI descriptor from start of buffer.
+	 */
+	skb_pull(entry->skb, skbdesc->desc_len);
+	skb_trim(entry->skb, rxdesc->size);
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+	u16 word;
+	u8 *mac;
+	u8 default_lna_gain;
+
+	rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
+
+	/*
+	 * Start validation of the data that has been read.
+	 */
+	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+	if (!is_valid_ether_addr(mac)) {
+		DECLARE_MAC_BUF(macbuf);
+
+		random_ether_addr(mac);
+		EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+	}
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+	if (word == 0xffff) {
+		rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
+		rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
+		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+	} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
+		/*
+		 * There is a max of 2 RX streams for RT2870 series
+		 */
+		if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
+			rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+	}
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+	if (word == 0xffff) {
+		rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
+		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+	}
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+	if ((word & 0x00ff) == 0x00ff) {
+		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
+		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
+				   LED_MODE_TXRX_ACTIVITY);
+		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
+		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+	}
+
+	/*
+	 * During the LNA validation we are going to use
+	 * lna0 as correct value. Note that EEPROM_LNA
+	 * is never validated.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
+	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
+	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
+	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
+				   default_lna_gain);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
+	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
+	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
+				   default_lna_gain);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+
+	return 0;
+}
+
+static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u16 value;
+	u16 eeprom;
+
+	/*
+	 * Read EEPROM word for configuration.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+	/*
+	 * Identify RF chipset.
+	 */
+	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+	rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(rt2x00dev, RT2870, value, reg);
+
+	/*
+	 * The check for rt2860 is not a typo, some rt2870 hardware
+	 * identifies itself as rt2860 in the CSR register.
+	 */
+	if (!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28600000) &&
+	    !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28700000) &&
+	    !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28800000) &&
+	    !rt2x00_check_rev(&rt2x00dev->chip, 0xffff0000, 0x30700000)) {
+		ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
+		return -ENODEV;
+	}
+
+	if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2850) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2720) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2750) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF3020) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2020)) {
+		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Identify default antenna configuration.
+	 */
+	rt2x00dev->default_ant.tx =
+	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
+	rt2x00dev->default_ant.rx =
+	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
+
+	/*
+	 * Read frequency offset and RF programming sequence.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
+
+	/*
+	 * Read external LNA informations.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
+		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
+		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+
+	/*
+	 * Detect if this device has an hardware controlled radio.
+	 */
+#ifdef CONFIG_RT2X00_LIB_RFKILL
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
+		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
+
+	/*
+	 * Store led settings, for correct led behaviour.
+	 */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+	rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+	rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+	rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ,
+			   &rt2x00dev->led_mcu_reg);
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+	return 0;
+}
+
+/*
+ * RF value list for rt2870
+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
+ */
+static const struct rf_channel rf_vals[] = {
+	{ 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
+	{ 2,  0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
+	{ 3,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
+	{ 4,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
+	{ 5,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
+	{ 6,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
+	{ 7,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
+	{ 8,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
+	{ 9,  0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
+	{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
+	{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
+	{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
+	{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
+	{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
+
+	/* 802.11 UNI / HyperLan 2 */
+	{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
+	{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
+	{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
+	{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
+	{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
+	{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
+	{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
+	{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
+	{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
+	{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
+	{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
+	{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
+
+	/* 802.11 HyperLan 2 */
+	{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
+	{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
+	{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
+	{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
+	{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
+	{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
+	{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
+	{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
+	{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
+	{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
+	{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
+	{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
+	{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
+	{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
+	{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
+	{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
+
+	/* 802.11 UNII */
+	{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
+	{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
+	{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
+	{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
+	{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
+	{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
+	{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
+	{ 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },
+	{ 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },
+	{ 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },
+	{ 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },
+
+	/* 802.11 Japan */
+	{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
+	{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
+	{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
+	{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
+	{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
+	{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
+	{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
+};
+
+/*
+ * RF value list for rt3070
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_3070[] = {
+	{1,  241, 2, 2 },
+	{2,  241, 2, 7 },
+	{3,  242, 2, 2 },
+	{4,  242, 2, 7 },
+	{5,  243, 2, 2 },
+	{6,  243, 2, 7 },
+	{7,  244, 2, 2 },
+	{8,  244, 2, 7 },
+	{9,  245, 2, 2 },
+	{10, 245, 2, 7 },
+	{11, 246, 2, 2 },
+	{12, 246, 2, 7 },
+	{13, 247, 2, 2 },
+	{14, 248, 2, 4 },
+};
+
+static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+	struct hw_mode_spec *spec = &rt2x00dev->spec;
+	struct channel_info *info;
+	char *tx_power1;
+	char *tx_power2;
+	unsigned int i;
+	u16 eeprom;
+
+	/*
+	 * Initialize all hw fields.
+	 */
+	rt2x00dev->hw->flags =
+	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+	    IEEE80211_HW_SIGNAL_DBM |
+	    IEEE80211_HW_SUPPORTS_PS |
+	    IEEE80211_HW_PS_NULLFUNC_STACK;
+	rt2x00dev->hw->extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
+
+	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+				rt2x00_eeprom_addr(rt2x00dev,
+						   EEPROM_MAC_ADDR_0));
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+	/*
+	 * Initialize HT information.
+	 */
+	spec->ht.ht_supported = true;
+	spec->ht.cap =
+	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+	    IEEE80211_HT_CAP_GRN_FLD |
+	    IEEE80211_HT_CAP_SGI_20 |
+	    IEEE80211_HT_CAP_SGI_40 |
+	    IEEE80211_HT_CAP_TX_STBC |
+	    IEEE80211_HT_CAP_RX_STBC |
+	    IEEE80211_HT_CAP_PSMP_SUPPORT;
+	spec->ht.ampdu_factor = 3;
+	spec->ht.ampdu_density = 4;
+	spec->ht.mcs.tx_params =
+	    IEEE80211_HT_MCS_TX_DEFINED |
+	    IEEE80211_HT_MCS_TX_RX_DIFF |
+	    ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
+		IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+
+	switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
+	case 3:
+		spec->ht.mcs.rx_mask[2] = 0xff;
+	case 2:
+		spec->ht.mcs.rx_mask[1] = 0xff;
+	case 1:
+		spec->ht.mcs.rx_mask[0] = 0xff;
+		spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
+		break;
+	}
+
+	/*
+	 * Initialize hw_mode information.
+	 */
+	spec->supported_bands = SUPPORT_BAND_2GHZ;
+	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+
+	if (rt2x00_rf(&rt2x00dev->chip, RF2820) ||
+	    rt2x00_rf(&rt2x00dev->chip, RF2720)) {
+		spec->num_channels = 14;
+		spec->channels = rf_vals;
+	} else if (rt2x00_rf(&rt2x00dev->chip, RF2850) ||
+		   rt2x00_rf(&rt2x00dev->chip, RF2750)) {
+		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+		spec->num_channels = ARRAY_SIZE(rf_vals);
+		spec->channels = rf_vals;
+	} else if (rt2x00_rf(&rt2x00dev->chip, RF3020) ||
+		   rt2x00_rf(&rt2x00dev->chip, RF2020)) {
+		spec->num_channels = ARRAY_SIZE(rf_vals_3070);
+		spec->channels = rf_vals_3070;
+	}
+
+	/*
+	 * Create channel information array
+	 */
+	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	spec->channels_info = info;
+
+	tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
+	tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
+
+	for (i = 0; i < 14; i++) {
+		info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
+		info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
+	}
+
+	if (spec->num_channels > 14) {
+		tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
+		tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
+
+		for (i = 14; i < spec->num_channels; i++) {
+			info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
+			info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
+		}
+	}
+
+	return 0;
+}
+
+static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+	int retval;
+
+	/*
+	 * Allocate eeprom data.
+	 */
+	retval = rt2800usb_validate_eeprom(rt2x00dev);
+	if (retval)
+		return retval;
+
+	retval = rt2800usb_init_eeprom(rt2x00dev);
+	if (retval)
+		return retval;
+
+	/*
+	 * Initialize hw specifications.
+	 */
+	retval = rt2800usb_probe_hw_mode(rt2x00dev);
+	if (retval)
+		return retval;
+
+	/*
+	 * This device requires firmware.
+	 */
+	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
+	if (!modparam_nohwcrypt)
+		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
+
+	/*
+	 * Set the rssi offset.
+	 */
+	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
+	return 0;
+}
+
+/*
+ * IEEE80211 stack callback functions.
+ */
+static void rt2800usb_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
+				   u32 *iv32, u16 *iv16)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct mac_iveiv_entry iveiv_entry;
+	u32 offset;
+
+	offset = MAC_IVEIV_ENTRY(hw_key_idx);
+	rt2x00usb_register_multiread(rt2x00dev, offset,
+				      &iveiv_entry, sizeof(iveiv_entry));
+
+	memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16));
+	memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32));
+}
+
+static int rt2800usb_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	u32 reg;
+	bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
+
+	rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+	rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
+	rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
+	rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
+	rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
+	rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
+	rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
+	rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
+	rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+
+	return 0;
+}
+
+static int rt2800usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+			     const struct ieee80211_tx_queue_params *params)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct data_queue *queue;
+	struct rt2x00_field32 field;
+	int retval;
+	u32 reg;
+	u32 offset;
+
+	/*
+	 * First pass the configuration through rt2x00lib, that will
+	 * update the queue settings and validate the input. After that
+	 * we are free to update the registers based on the value
+	 * in the queue parameter.
+	 */
+	retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+	if (retval)
+		return retval;
+
+	/*
+	 * We only need to perform additional register initialization
+	 * for WMM queues/
+	 */
+	if (queue_idx >= 4)
+		return 0;
+
+	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+
+	/* Update WMM TXOP register */
+	offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
+	field.bit_offset = (queue_idx & 1) * 16;
+	field.bit_mask = 0xffff << field.bit_offset;
+
+	rt2x00usb_register_read(rt2x00dev, offset, &reg);
+	rt2x00_set_field32(&reg, field, queue->txop);
+	rt2x00usb_register_write(rt2x00dev, offset, reg);
+
+	/* Update WMM registers */
+	field.bit_offset = queue_idx * 4;
+	field.bit_mask = 0xf << field.bit_offset;
+
+	rt2x00usb_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
+	rt2x00_set_field32(&reg, field, queue->aifs);
+	rt2x00usb_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
+	rt2x00_set_field32(&reg, field, queue->cw_min);
+	rt2x00usb_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
+
+	rt2x00usb_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
+	rt2x00_set_field32(&reg, field, queue->cw_max);
+	rt2x00usb_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
+
+	/* Update EDCA registers */
+	offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
+
+	rt2x00usb_register_read(rt2x00dev, offset, &reg);
+	rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
+	rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
+	rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
+	rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMAX, queue->cw_max);
+	rt2x00usb_register_write(rt2x00dev, offset, reg);
+
+	return 0;
+}
+
+static u64 rt2800usb_get_tsf(struct ieee80211_hw *hw)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	u64 tsf;
+	u32 reg;
+
+	rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
+	tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
+	rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
+	tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
+
+	return tsf;
+}
+
+static const struct ieee80211_ops rt2800usb_mac80211_ops = {
+	.tx			= rt2x00mac_tx,
+	.start			= rt2x00mac_start,
+	.stop			= rt2x00mac_stop,
+	.add_interface		= rt2x00mac_add_interface,
+	.remove_interface	= rt2x00mac_remove_interface,
+	.config			= rt2x00mac_config,
+	.configure_filter	= rt2x00mac_configure_filter,
+	.set_key		= rt2x00mac_set_key,
+	.get_stats		= rt2x00mac_get_stats,
+	.get_tkip_seq		= rt2800usb_get_tkip_seq,
+	.set_rts_threshold	= rt2800usb_set_rts_threshold,
+	.bss_info_changed	= rt2x00mac_bss_info_changed,
+	.conf_tx		= rt2800usb_conf_tx,
+	.get_tx_stats		= rt2x00mac_get_tx_stats,
+	.get_tsf		= rt2800usb_get_tsf,
+};
+
+static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
+	.probe_hw		= rt2800usb_probe_hw,
+	.get_firmware_name	= rt2800usb_get_firmware_name,
+	.check_firmware		= rt2800usb_check_firmware,
+	.load_firmware		= rt2800usb_load_firmware,
+	.initialize		= rt2x00usb_initialize,
+	.uninitialize		= rt2x00usb_uninitialize,
+	.clear_entry		= rt2x00usb_clear_entry,
+	.set_device_state	= rt2800usb_set_device_state,
+	.rfkill_poll		= rt2800usb_rfkill_poll,
+	.link_stats		= rt2800usb_link_stats,
+	.reset_tuner		= rt2800usb_reset_tuner,
+	.link_tuner		= rt2800usb_link_tuner,
+	.write_tx_desc		= rt2800usb_write_tx_desc,
+	.write_tx_data		= rt2x00usb_write_tx_data,
+	.write_beacon		= rt2800usb_write_beacon,
+	.get_tx_data_len	= rt2800usb_get_tx_data_len,
+	.kick_tx_queue		= rt2800usb_kick_tx_queue,
+	.kill_tx_queue		= rt2x00usb_kill_tx_queue,
+	.fill_rxdone		= rt2800usb_fill_rxdone,
+	.config_shared_key	= rt2800usb_config_shared_key,
+	.config_pairwise_key	= rt2800usb_config_pairwise_key,
+	.config_filter		= rt2800usb_config_filter,
+	.config_intf		= rt2800usb_config_intf,
+	.config_erp		= rt2800usb_config_erp,
+	.config_ant		= rt2800usb_config_ant,
+	.config			= rt2800usb_config,
+};
+
+static const struct data_queue_desc rt2800usb_queue_rx = {
+	.entry_num		= RX_ENTRIES,
+	.data_size		= AGGREGATION_SIZE,
+	.desc_size		= RXD_DESC_SIZE + RXWI_DESC_SIZE,
+	.priv_size		= sizeof(struct queue_entry_priv_usb),
+};
+
+static const struct data_queue_desc rt2800usb_queue_tx = {
+	.entry_num		= TX_ENTRIES,
+	.data_size		= AGGREGATION_SIZE,
+	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
+	.priv_size		= sizeof(struct queue_entry_priv_usb),
+};
+
+static const struct data_queue_desc rt2800usb_queue_bcn = {
+	.entry_num		= 8 * BEACON_ENTRIES,
+	.data_size		= MGMT_FRAME_SIZE,
+	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
+	.priv_size		= sizeof(struct queue_entry_priv_usb),
+};
+
+static const struct rt2x00_ops rt2800usb_ops = {
+	.name		= KBUILD_MODNAME,
+	.max_sta_intf	= 1,
+	.max_ap_intf	= 8,
+	.eeprom_size	= EEPROM_SIZE,
+	.rf_size	= RF_SIZE,
+	.tx_queues	= NUM_TX_QUEUES,
+	.rx		= &rt2800usb_queue_rx,
+	.tx		= &rt2800usb_queue_tx,
+	.bcn		= &rt2800usb_queue_bcn,
+	.lib		= &rt2800usb_rt2x00_ops,
+	.hw		= &rt2800usb_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+	.debugfs	= &rt2800usb_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * rt2800usb module information.
+ */
+static struct usb_device_id rt2800usb_device_table[] = {
+	/* Abocom */
+	{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* AirTies */
+	{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Amigo */
+	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Amit */
+	{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* ASUS */
+	{ USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* AzureWave */
+	{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Belkin */
+	{ USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Buffalo */
+	{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Conceptronic */
+	{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Corega */
+	{ USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* D-Link */
+	{ USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Edimax */
+	{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Encore */
+	{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* EnGenius */
+	{ USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Gemtek */
+	{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Gigabyte */
+	{ USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Hawking */
+	{ USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* I-O DATA */
+	{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* LevelOne */
+	{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Linksys */
+	{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Logitec */
+	{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Motorola */
+	{ USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Ovislink */
+	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Pegatron */
+	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Philips */
+	{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Planex */
+	{ USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Qcom */
+	{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Quanta */
+	{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Ralink */
+	{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Samsung */
+	{ USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Siemens */
+	{ USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Sitecom */
+	{ USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* SMC */
+	{ USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Sparklan */
+	{ USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Sweex */
+	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* U-Media*/
+	{ USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* ZCOM */
+	{ USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Zinwell */
+	{ USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Zyxel */
+	{ USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ 0, }
+};
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards");
+MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
+/*(DEBLOBBED)*/
+MODULE_LICENSE("GPL");
+
+static struct usb_driver rt2800usb_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= rt2800usb_device_table,
+	.probe		= rt2x00usb_probe,
+	.disconnect	= rt2x00usb_disconnect,
+	.suspend	= rt2x00usb_suspend,
+	.resume		= rt2x00usb_resume,
+};
+
+static int __init rt2800usb_init(void)
+{
+	return usb_register(&rt2800usb_driver);
+}
+
+static void __exit rt2800usb_exit(void)
+{
+	usb_deregister(&rt2800usb_driver);
+}
+
+module_init(rt2800usb_init);
+module_exit(rt2800usb_exit);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2800usb.h linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2800usb.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2800usb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2800usb.h	2012-03-22 20:14:17.000000000 -0400
@@ -0,0 +1,1945 @@
+/*
+	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.com>
+
+	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.
+ */
+
+/*
+	Module: rt2800usb
+	Abstract: Data structures and registers for the rt2800usb module.
+	Supported chipsets: RT2800U.
+ */
+
+#ifndef RT2800USB_H
+#define RT2800USB_H
+
+/*
+ * RF chip defines.
+ *
+ * RF2820 2.4G 2T3R
+ * RF2850 2.4G/5G 2T3R
+ * RF2720 2.4G 1T2R
+ * RF2750 2.4G/5G 1T2R
+ * RF3020 2.4G 1T1R
+ * RF2020 2.4G B/G
+ */
+#define RF2820				0x0001
+#define RF2850				0x0002
+#define RF2720				0x0003
+#define RF2750				0x0004
+#define RF3020				0x0005
+#define RF2020				0x0006
+
+/*
+ * RT2870 version
+ */
+#define RT2860C_VERSION			0x28600100
+#define RT2860D_VERSION			0x28600101
+#define RT2880E_VERSION			0x28720200
+#define RT2883_VERSION			0x28830300
+#define RT3070_VERSION			0x30700200
+
+/*
+ * Signal information.
+ * Defaul offset is required for RSSI <-> dBm conversion.
+ */
+#define DEFAULT_RSSI_OFFSET		120 /* FIXME */
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE			0x1000
+#define CSR_REG_SIZE			0x0800
+#define EEPROM_BASE			0x0000
+#define EEPROM_SIZE			0x0110
+#define BBP_BASE			0x0000
+#define BBP_SIZE			0x0080
+#define RF_BASE				0x0004
+#define RF_SIZE				0x0010
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES			4
+
+/*
+ * USB registers.
+ */
+
+/*
+ * HOST-MCU shared memory
+ */
+#define HOST_CMD_CSR			0x0404
+#define HOST_CMD_CSR_HOST_COMMAND	FIELD32(0x000000ff)
+
+/*
+ * INT_SOURCE_CSR: Interrupt source register.
+ * Write one to clear corresponding bit.
+ * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c
+ */
+#define INT_SOURCE_CSR			0x0200
+#define INT_SOURCE_CSR_RXDELAYINT	FIELD32(0x00000001)
+#define INT_SOURCE_CSR_TXDELAYINT	FIELD32(0x00000002)
+#define INT_SOURCE_CSR_RX_DONE		FIELD32(0x00000004)
+#define INT_SOURCE_CSR_AC0_DMA_DONE	FIELD32(0x00000008)
+#define INT_SOURCE_CSR_AC1_DMA_DONE	FIELD32(0x00000010)
+#define INT_SOURCE_CSR_AC2_DMA_DONE	FIELD32(0x00000020)
+#define INT_SOURCE_CSR_AC3_DMA_DONE	FIELD32(0x00000040)
+#define INT_SOURCE_CSR_HCCA_DMA_DONE	FIELD32(0x00000080)
+#define INT_SOURCE_CSR_MGMT_DMA_DONE	FIELD32(0x00000100)
+#define INT_SOURCE_CSR_MCU_COMMAND	FIELD32(0x00000200)
+#define INT_SOURCE_CSR_RXTX_COHERENT	FIELD32(0x00000400)
+#define INT_SOURCE_CSR_TBTT		FIELD32(0x00000800)
+#define INT_SOURCE_CSR_PRE_TBTT		FIELD32(0x00001000)
+#define INT_SOURCE_CSR_TX_FIFO_STATUS	FIELD32(0x00002000)
+#define INT_SOURCE_CSR_AUTO_WAKEUP	FIELD32(0x00004000)
+#define INT_SOURCE_CSR_GPTIMER		FIELD32(0x00008000)
+#define INT_SOURCE_CSR_RX_COHERENT	FIELD32(0x00010000)
+#define INT_SOURCE_CSR_TX_COHERENT	FIELD32(0x00020000)
+
+/*
+ * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
+ */
+#define INT_MASK_CSR			0x0204
+#define INT_MASK_CSR_RXDELAYINT		FIELD32(0x00000001)
+#define INT_MASK_CSR_TXDELAYINT		FIELD32(0x00000002)
+#define INT_MASK_CSR_RX_DONE		FIELD32(0x00000004)
+#define INT_MASK_CSR_AC0_DMA_DONE	FIELD32(0x00000008)
+#define INT_MASK_CSR_AC1_DMA_DONE	FIELD32(0x00000010)
+#define INT_MASK_CSR_AC2_DMA_DONE	FIELD32(0x00000020)
+#define INT_MASK_CSR_AC3_DMA_DONE	FIELD32(0x00000040)
+#define INT_MASK_CSR_HCCA_DMA_DONE	FIELD32(0x00000080)
+#define INT_MASK_CSR_MGMT_DMA_DONE	FIELD32(0x00000100)
+#define INT_MASK_CSR_MCU_COMMAND	FIELD32(0x00000200)
+#define INT_MASK_CSR_RXTX_COHERENT	FIELD32(0x00000400)
+#define INT_MASK_CSR_TBTT		FIELD32(0x00000800)
+#define INT_MASK_CSR_PRE_TBTT		FIELD32(0x00001000)
+#define INT_MASK_CSR_TX_FIFO_STATUS	FIELD32(0x00002000)
+#define INT_MASK_CSR_AUTO_WAKEUP	FIELD32(0x00004000)
+#define INT_MASK_CSR_GPTIMER		FIELD32(0x00008000)
+#define INT_MASK_CSR_RX_COHERENT	FIELD32(0x00010000)
+#define INT_MASK_CSR_TX_COHERENT	FIELD32(0x00020000)
+
+/*
+ * WPDMA_GLO_CFG
+ */
+#define WPDMA_GLO_CFG 			0x0208
+#define WPDMA_GLO_CFG_ENABLE_TX_DMA	FIELD32(0x00000001)
+#define WPDMA_GLO_CFG_TX_DMA_BUSY    	FIELD32(0x00000002)
+#define WPDMA_GLO_CFG_ENABLE_RX_DMA	FIELD32(0x00000004)
+#define WPDMA_GLO_CFG_RX_DMA_BUSY	FIELD32(0x00000008)
+#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE	FIELD32(0x00000030)
+#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE	FIELD32(0x00000040)
+#define WPDMA_GLO_CFG_BIG_ENDIAN	FIELD32(0x00000080)
+#define WPDMA_GLO_CFG_RX_HDR_SCATTER	FIELD32(0x0000ff00)
+#define WPDMA_GLO_CFG_HDR_SEG_LEN	FIELD32(0xffff0000)
+
+/*
+ * WPDMA_RST_IDX
+ */
+#define WPDMA_RST_IDX 			0x020c
+#define WPDMA_RST_IDX_DTX_IDX0		FIELD32(0x00000001)
+#define WPDMA_RST_IDX_DTX_IDX1		FIELD32(0x00000002)
+#define WPDMA_RST_IDX_DTX_IDX2		FIELD32(0x00000004)
+#define WPDMA_RST_IDX_DTX_IDX3		FIELD32(0x00000008)
+#define WPDMA_RST_IDX_DTX_IDX4		FIELD32(0x00000010)
+#define WPDMA_RST_IDX_DTX_IDX5		FIELD32(0x00000020)
+#define WPDMA_RST_IDX_DRX_IDX0		FIELD32(0x00010000)
+
+/*
+ * DELAY_INT_CFG
+ */
+#define DELAY_INT_CFG			0x0210
+#define DELAY_INT_CFG_RXMAX_PTIME	FIELD32(0x000000ff)
+#define DELAY_INT_CFG_RXMAX_PINT	FIELD32(0x00007f00)
+#define DELAY_INT_CFG_RXDLY_INT_EN	FIELD32(0x00008000)
+#define DELAY_INT_CFG_TXMAX_PTIME	FIELD32(0x00ff0000)
+#define DELAY_INT_CFG_TXMAX_PINT	FIELD32(0x7f000000)
+#define DELAY_INT_CFG_TXDLY_INT_EN	FIELD32(0x80000000)
+
+/*
+ * WMM_AIFSN_CFG: Aifsn for each EDCA AC
+ * AIFSN0: AC_BE
+ * AIFSN1: AC_BK
+ * AIFSN1: AC_VI
+ * AIFSN1: AC_VO
+ */
+#define WMM_AIFSN_CFG			0x0214
+#define WMM_AIFSN_CFG_AIFSN0		FIELD32(0x0000000f)
+#define WMM_AIFSN_CFG_AIFSN1		FIELD32(0x000000f0)
+#define WMM_AIFSN_CFG_AIFSN2		FIELD32(0x00000f00)
+#define WMM_AIFSN_CFG_AIFSN3		FIELD32(0x0000f000)
+
+/*
+ * WMM_CWMIN_CSR: CWmin for each EDCA AC
+ * CWMIN0: AC_BE
+ * CWMIN1: AC_BK
+ * CWMIN1: AC_VI
+ * CWMIN1: AC_VO
+ */
+#define WMM_CWMIN_CFG			0x0218
+#define WMM_CWMIN_CFG_CWMIN0		FIELD32(0x0000000f)
+#define WMM_CWMIN_CFG_CWMIN1		FIELD32(0x000000f0)
+#define WMM_CWMIN_CFG_CWMIN2		FIELD32(0x00000f00)
+#define WMM_CWMIN_CFG_CWMIN3		FIELD32(0x0000f000)
+
+/*
+ * WMM_CWMAX_CSR: CWmax for each EDCA AC
+ * CWMAX0: AC_BE
+ * CWMAX1: AC_BK
+ * CWMAX1: AC_VI
+ * CWMAX1: AC_VO
+ */
+#define WMM_CWMAX_CFG			0x021c
+#define WMM_CWMAX_CFG_CWMAX0		FIELD32(0x0000000f)
+#define WMM_CWMAX_CFG_CWMAX1		FIELD32(0x000000f0)
+#define WMM_CWMAX_CFG_CWMAX2		FIELD32(0x00000f00)
+#define WMM_CWMAX_CFG_CWMAX3		FIELD32(0x0000f000)
+
+/*
+ * AC_TXOP0: AC_BK/AC_BE TXOP register
+ * AC0TXOP: AC_BK in unit of 32us
+ * AC1TXOP: AC_BE in unit of 32us
+ */
+#define WMM_TXOP0_CFG			0x0220
+#define WMM_TXOP0_CFG_AC0TXOP		FIELD32(0x0000ffff)
+#define WMM_TXOP0_CFG_AC1TXOP		FIELD32(0xffff0000)
+
+/*
+ * AC_TXOP1: AC_VO/AC_VI TXOP register
+ * AC2TXOP: AC_VI in unit of 32us
+ * AC3TXOP: AC_VO in unit of 32us
+ */
+#define WMM_TXOP1_CFG			0x0224
+#define WMM_TXOP1_CFG_AC2TXOP		FIELD32(0x0000ffff)
+#define WMM_TXOP1_CFG_AC3TXOP		FIELD32(0xffff0000)
+
+/*
+ * GPIO_CTRL_CFG:
+ */
+#define GPIO_CTRL_CFG			0x0228
+#define GPIO_CTRL_CFG_BIT0		FIELD32(0x00000001)
+#define GPIO_CTRL_CFG_BIT1		FIELD32(0x00000002)
+#define GPIO_CTRL_CFG_BIT2		FIELD32(0x00000004)
+#define GPIO_CTRL_CFG_BIT3		FIELD32(0x00000008)
+#define GPIO_CTRL_CFG_BIT4		FIELD32(0x00000010)
+#define GPIO_CTRL_CFG_BIT5		FIELD32(0x00000020)
+#define GPIO_CTRL_CFG_BIT6		FIELD32(0x00000040)
+#define GPIO_CTRL_CFG_BIT7		FIELD32(0x00000080)
+#define GPIO_CTRL_CFG_BIT8		FIELD32(0x00000100)
+
+/*
+ * MCU_CMD_CFG
+ */
+#define MCU_CMD_CFG			0x022c
+
+/*
+ * AC_BK register offsets
+ */
+#define TX_BASE_PTR0			0x0230
+#define TX_MAX_CNT0			0x0234
+#define TX_CTX_IDX0			0x0238
+#define TX_DTX_IDX0			0x023c
+
+/*
+ * AC_BE register offsets
+ */
+#define TX_BASE_PTR1			0x0240
+#define TX_MAX_CNT1			0x0244
+#define TX_CTX_IDX1			0x0248
+#define TX_DTX_IDX1			0x024c
+
+/*
+ * AC_VI register offsets
+ */
+#define TX_BASE_PTR2			0x0250
+#define TX_MAX_CNT2			0x0254
+#define TX_CTX_IDX2			0x0258
+#define TX_DTX_IDX2			0x025c
+
+/*
+ * AC_VO register offsets
+ */
+#define TX_BASE_PTR3			0x0260
+#define TX_MAX_CNT3			0x0264
+#define TX_CTX_IDX3			0x0268
+#define TX_DTX_IDX3			0x026c
+
+/*
+ * HCCA register offsets
+ */
+#define TX_BASE_PTR4			0x0270
+#define TX_MAX_CNT4			0x0274
+#define TX_CTX_IDX4			0x0278
+#define TX_DTX_IDX4			0x027c
+
+/*
+ * MGMT register offsets
+ */
+#define TX_BASE_PTR5			0x0280
+#define TX_MAX_CNT5			0x0284
+#define TX_CTX_IDX5			0x0288
+#define TX_DTX_IDX5			0x028c
+
+/*
+ * RX register offsets
+ */
+#define RX_BASE_PTR			0x0290
+#define RX_MAX_CNT			0x0294
+#define RX_CRX_IDX			0x0298
+#define RX_DRX_IDX			0x029c
+
+/*
+ * USB_DMA_CFG
+ * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns.
+ * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes.
+ * PHY_CLEAR: phy watch dog enable.
+ * TX_CLEAR: Clear USB DMA TX path.
+ * TXOP_HALT: Halt TXOP count down when TX buffer is full.
+ * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation.
+ * RX_BULK_EN: Enable USB DMA Rx.
+ * TX_BULK_EN: Enable USB DMA Tx.
+ * EP_OUT_VALID: OUT endpoint data valid.
+ * RX_BUSY: USB DMA RX FSM busy.
+ * TX_BUSY: USB DMA TX FSM busy.
+ */
+#define USB_DMA_CFG			0x02a0
+#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT	FIELD32(0x000000ff)
+#define USB_DMA_CFG_RX_BULK_AGG_LIMIT	FIELD32(0x0000ff00)
+#define USB_DMA_CFG_PHY_CLEAR		FIELD32(0x00010000)
+#define USB_DMA_CFG_TX_CLEAR		FIELD32(0x00080000)
+#define USB_DMA_CFG_TXOP_HALT		FIELD32(0x00100000)
+#define USB_DMA_CFG_RX_BULK_AGG_EN	FIELD32(0x00200000)
+#define USB_DMA_CFG_RX_BULK_EN		FIELD32(0x00400000)
+#define USB_DMA_CFG_TX_BULK_EN		FIELD32(0x00800000)
+#define USB_DMA_CFG_EP_OUT_VALID	FIELD32(0x3f000000)
+#define USB_DMA_CFG_RX_BUSY		FIELD32(0x40000000)
+#define USB_DMA_CFG_TX_BUSY		FIELD32(0x80000000)
+
+/*
+ * USB_CYC_CFG
+ */
+#define USB_CYC_CFG			0x02a4
+#define USB_CYC_CFG_CLOCK_CYCLE		FIELD32(0x000000ff)
+
+/*
+ * PBF_SYS_CTRL
+ * HOST_RAM_WRITE: enable Host program ram write selection
+ */
+#define PBF_SYS_CTRL			0x0400
+#define PBF_SYS_CTRL_READY		FIELD32(0x00000080)
+#define PBF_SYS_CTRL_HOST_RAM_WRITE	FIELD32(0x00010000)
+
+/*
+ * PBF registers
+ * Most are for debug. Driver doesn't touch PBF register.
+ */
+#define PBF_CFG				0x0408
+#define PBF_MAX_PCNT			0x040c
+#define PBF_CTRL			0x0410
+#define PBF_INT_STA			0x0414
+#define PBF_INT_ENA			0x0418
+
+/*
+ * BCN_OFFSET0:
+ */
+#define BCN_OFFSET0			0x042c
+#define BCN_OFFSET0_BCN0		FIELD32(0x000000ff)
+#define BCN_OFFSET0_BCN1		FIELD32(0x0000ff00)
+#define BCN_OFFSET0_BCN2		FIELD32(0x00ff0000)
+#define BCN_OFFSET0_BCN3		FIELD32(0xff000000)
+
+/*
+ * BCN_OFFSET1:
+ */
+#define BCN_OFFSET1			0x0430
+#define BCN_OFFSET1_BCN4		FIELD32(0x000000ff)
+#define BCN_OFFSET1_BCN5		FIELD32(0x0000ff00)
+#define BCN_OFFSET1_BCN6		FIELD32(0x00ff0000)
+#define BCN_OFFSET1_BCN7		FIELD32(0xff000000)
+
+/*
+ * PBF registers
+ * Most are for debug. Driver doesn't touch PBF register.
+ */
+#define TXRXQ_PCNT			0x0438
+#define PBF_DBG				0x043c
+
+/*
+ * RF registers
+ */
+#define	RF_CSR_CFG			0x0500
+#define RF_CSR_CFG_DATA			FIELD32(0x000000ff)
+#define RF_CSR_CFG_REGNUM		FIELD32(0x00001f00)
+#define RF_CSR_CFG_WRITE		FIELD32(0x00010000)
+#define RF_CSR_CFG_BUSY			FIELD32(0x00020000)
+
+/*
+ * MAC Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * MAC_CSR0: ASIC revision number.
+ * ASIC_REV: 0
+ * ASIC_VER: 2870
+ */
+#define MAC_CSR0			0x1000
+#define MAC_CSR0_ASIC_REV		FIELD32(0x0000ffff)
+#define MAC_CSR0_ASIC_VER		FIELD32(0xffff0000)
+
+/*
+ * MAC_SYS_CTRL:
+ */
+#define MAC_SYS_CTRL			0x1004
+#define MAC_SYS_CTRL_RESET_CSR		FIELD32(0x00000001)
+#define MAC_SYS_CTRL_RESET_BBP		FIELD32(0x00000002)
+#define MAC_SYS_CTRL_ENABLE_TX		FIELD32(0x00000004)
+#define MAC_SYS_CTRL_ENABLE_RX		FIELD32(0x00000008)
+#define MAC_SYS_CTRL_CONTINUOUS_TX	FIELD32(0x00000010)
+#define MAC_SYS_CTRL_LOOPBACK		FIELD32(0x00000020)
+#define MAC_SYS_CTRL_WLAN_HALT		FIELD32(0x00000040)
+#define MAC_SYS_CTRL_RX_TIMESTAMP	FIELD32(0x00000080)
+
+/*
+ * MAC_ADDR_DW0: STA MAC register 0
+ */
+#define MAC_ADDR_DW0			0x1008
+#define MAC_ADDR_DW0_BYTE0		FIELD32(0x000000ff)
+#define MAC_ADDR_DW0_BYTE1		FIELD32(0x0000ff00)
+#define MAC_ADDR_DW0_BYTE2		FIELD32(0x00ff0000)
+#define MAC_ADDR_DW0_BYTE3		FIELD32(0xff000000)
+
+/*
+ * MAC_ADDR_DW1: STA MAC register 1
+ * UNICAST_TO_ME_MASK:
+ * Used to mask off bits from byte 5 of the MAC address
+ * to determine the UNICAST_TO_ME bit for RX frames.
+ * The full mask is complemented by BSS_ID_MASK:
+ *    MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+ */
+#define MAC_ADDR_DW1			0x100c
+#define MAC_ADDR_DW1_BYTE4		FIELD32(0x000000ff)
+#define MAC_ADDR_DW1_BYTE5		FIELD32(0x0000ff00)
+#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK	FIELD32(0x00ff0000)
+
+/*
+ * MAC_BSSID_DW0: BSSID register 0
+ */
+#define MAC_BSSID_DW0			0x1010
+#define MAC_BSSID_DW0_BYTE0		FIELD32(0x000000ff)
+#define MAC_BSSID_DW0_BYTE1		FIELD32(0x0000ff00)
+#define MAC_BSSID_DW0_BYTE2		FIELD32(0x00ff0000)
+#define MAC_BSSID_DW0_BYTE3		FIELD32(0xff000000)
+
+/*
+ * MAC_BSSID_DW1: BSSID register 1
+ * BSS_ID_MASK:
+ *     0: 1-BSSID mode (BSS index = 0)
+ *     1: 2-BSSID mode (BSS index: Byte5, bit 0)
+ *     2: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+ *     3: 8-BSSID mode (BSS index: byte5, bit 0 - 2)
+ * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the
+ * BSSID. This will make sure that those bits will be ignored
+ * when determining the MY_BSS of RX frames.
+ */
+#define MAC_BSSID_DW1			0x1014
+#define MAC_BSSID_DW1_BYTE4		FIELD32(0x000000ff)
+#define MAC_BSSID_DW1_BYTE5		FIELD32(0x0000ff00)
+#define MAC_BSSID_DW1_BSS_ID_MASK	FIELD32(0x00030000)
+#define MAC_BSSID_DW1_BSS_BCN_NUM	FIELD32(0x001c0000)
+
+/*
+ * MAX_LEN_CFG: Maximum frame length register.
+ * MAX_MPDU: rt2860b max 16k bytes
+ * MAX_PSDU: Maximum PSDU length
+ *	(power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
+ */
+#define MAX_LEN_CFG			0x1018
+#define MAX_LEN_CFG_MAX_MPDU		FIELD32(0x00000fff)
+#define MAX_LEN_CFG_MAX_PSDU		FIELD32(0x00003000)
+#define MAX_LEN_CFG_MIN_PSDU		FIELD32(0x0000c000)
+#define MAX_LEN_CFG_MIN_MPDU		FIELD32(0x000f0000)
+
+/*
+ * BBP_CSR_CFG: BBP serial control register
+ * VALUE: Register value to program into BBP
+ * REG_NUM: Selected BBP register
+ * READ_CONTROL: 0 write BBP, 1 read BBP
+ * BUSY: ASIC is busy executing BBP commands
+ * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks
+ * BBP_RW_MODE: 0 serial, 1 paralell
+ */
+#define BBP_CSR_CFG			0x101c
+#define BBP_CSR_CFG_VALUE		FIELD32(0x000000ff)
+#define BBP_CSR_CFG_REGNUM		FIELD32(0x0000ff00)
+#define BBP_CSR_CFG_READ_CONTROL	FIELD32(0x00010000)
+#define BBP_CSR_CFG_BUSY		FIELD32(0x00020000)
+#define BBP_CSR_CFG_BBP_PAR_DUR		FIELD32(0x00040000)
+#define BBP_CSR_CFG_BBP_RW_MODE		FIELD32(0x00080000)
+
+/*
+ * RF_CSR_CFG0: RF control register
+ * REGID_AND_VALUE: Register value to program into RF
+ * BITWIDTH: Selected RF register
+ * STANDBYMODE: 0 high when standby, 1 low when standby
+ * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate
+ * BUSY: ASIC is busy executing RF commands
+ */
+#define RF_CSR_CFG0			0x1020
+#define RF_CSR_CFG0_REGID_AND_VALUE	FIELD32(0x00ffffff)
+#define RF_CSR_CFG0_BITWIDTH		FIELD32(0x1f000000)
+#define RF_CSR_CFG0_REG_VALUE_BW	FIELD32(0x1fffffff)
+#define RF_CSR_CFG0_STANDBYMODE		FIELD32(0x20000000)
+#define RF_CSR_CFG0_SEL			FIELD32(0x40000000)
+#define RF_CSR_CFG0_BUSY		FIELD32(0x80000000)
+
+/*
+ * RF_CSR_CFG1: RF control register
+ * REGID_AND_VALUE: Register value to program into RF
+ * RFGAP: Gap between BB_CONTROL_RF and RF_LE
+ *        0: 3 system clock cycle (37.5usec)
+ *        1: 5 system clock cycle (62.5usec)
+ */
+#define RF_CSR_CFG1			0x1024
+#define RF_CSR_CFG1_REGID_AND_VALUE	FIELD32(0x00ffffff)
+#define RF_CSR_CFG1_RFGAP		FIELD32(0x1f000000)
+
+/*
+ * RF_CSR_CFG2: RF control register
+ * VALUE: Register value to program into RF
+ * RFGAP: Gap between BB_CONTROL_RF and RF_LE
+ *        0: 3 system clock cycle (37.5usec)
+ *        1: 5 system clock cycle (62.5usec)
+ */
+#define RF_CSR_CFG2			0x1028
+#define RF_CSR_CFG2_VALUE		FIELD32(0x00ffffff)
+
+/*
+ * LED_CFG: LED control
+ * color LED's:
+ *   0: off
+ *   1: blinking upon TX2
+ *   2: periodic slow blinking
+ *   3: always on
+ * LED polarity:
+ *   0: active low
+ *   1: active high
+ */
+#define LED_CFG				0x102c
+#define LED_CFG_ON_PERIOD		FIELD32(0x000000ff)
+#define LED_CFG_OFF_PERIOD		FIELD32(0x0000ff00)
+#define LED_CFG_SLOW_BLINK_PERIOD	FIELD32(0x003f0000)
+#define LED_CFG_R_LED_MODE		FIELD32(0x03000000)
+#define LED_CFG_G_LED_MODE		FIELD32(0x0c000000)
+#define LED_CFG_Y_LED_MODE		FIELD32(0x30000000)
+#define LED_CFG_LED_POLAR		FIELD32(0x40000000)
+
+/*
+ * XIFS_TIME_CFG: MAC timing
+ * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
+ * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
+ * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX
+ *	when MAC doesn't reference BBP signal BBRXEND
+ * EIFS: unit 1us
+ * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer
+ *
+ */
+#define XIFS_TIME_CFG			0x1100
+#define XIFS_TIME_CFG_CCKM_SIFS_TIME	FIELD32(0x000000ff)
+#define XIFS_TIME_CFG_OFDM_SIFS_TIME	FIELD32(0x0000ff00)
+#define XIFS_TIME_CFG_OFDM_XIFS_TIME	FIELD32(0x000f0000)
+#define XIFS_TIME_CFG_EIFS		FIELD32(0x1ff00000)
+#define XIFS_TIME_CFG_BB_RXEND_ENABLE	FIELD32(0x20000000)
+
+/*
+ * BKOFF_SLOT_CFG:
+ */
+#define BKOFF_SLOT_CFG			0x1104
+#define BKOFF_SLOT_CFG_SLOT_TIME	FIELD32(0x000000ff)
+#define BKOFF_SLOT_CFG_CC_DELAY_TIME	FIELD32(0x0000ff00)
+
+/*
+ * NAV_TIME_CFG:
+ */
+#define NAV_TIME_CFG			0x1108
+#define NAV_TIME_CFG_SIFS		FIELD32(0x000000ff)
+#define NAV_TIME_CFG_SLOT_TIME		FIELD32(0x0000ff00)
+#define NAV_TIME_CFG_EIFS		FIELD32(0x01ff0000)
+#define NAV_TIME_ZERO_SIFS		FIELD32(0x02000000)
+
+/*
+ * CH_TIME_CFG: count as channel busy
+ */
+#define CH_TIME_CFG     	        0x110c
+
+/*
+ * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us
+ */
+#define PBF_LIFE_TIMER     	        0x1110
+
+/*
+ * BCN_TIME_CFG:
+ * BEACON_INTERVAL: in unit of 1/16 TU
+ * TSF_TICKING: Enable TSF auto counting
+ * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
+ * BEACON_GEN: Enable beacon generator
+ */
+#define BCN_TIME_CFG			0x1114
+#define BCN_TIME_CFG_BEACON_INTERVAL	FIELD32(0x0000ffff)
+#define BCN_TIME_CFG_TSF_TICKING	FIELD32(0x00010000)
+#define BCN_TIME_CFG_TSF_SYNC		FIELD32(0x00060000)
+#define BCN_TIME_CFG_TBTT_ENABLE	FIELD32(0x00080000)
+#define BCN_TIME_CFG_BEACON_GEN		FIELD32(0x00100000)
+#define BCN_TIME_CFG_TX_TIME_COMPENSATE	FIELD32(0xf0000000)
+
+/*
+ * TBTT_SYNC_CFG:
+ */
+#define TBTT_SYNC_CFG			0x1118
+
+/*
+ * TSF_TIMER_DW0: Local lsb TSF timer, read-only
+ */
+#define TSF_TIMER_DW0			0x111c
+#define TSF_TIMER_DW0_LOW_WORD		FIELD32(0xffffffff)
+
+/*
+ * TSF_TIMER_DW1: Local msb TSF timer, read-only
+ */
+#define TSF_TIMER_DW1			0x1120
+#define TSF_TIMER_DW1_HIGH_WORD		FIELD32(0xffffffff)
+
+/*
+ * TBTT_TIMER: TImer remains till next TBTT, read-only
+ */
+#define TBTT_TIMER			0x1124
+
+/*
+ * INT_TIMER_CFG:
+ */
+#define INT_TIMER_CFG			0x1128
+
+/*
+ * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
+ */
+#define INT_TIMER_EN			0x112c
+
+/*
+ * CH_IDLE_STA: channel idle time
+ */
+#define CH_IDLE_STA			0x1130
+
+/*
+ * CH_BUSY_STA: channel busy time
+ */
+#define CH_BUSY_STA			0x1134
+
+/*
+ * MAC_STATUS_CFG:
+ * BBP_RF_BUSY: When set to 0, BBP and RF are stable.
+ *	if 1 or higher one of the 2 registers is busy.
+ */
+#define MAC_STATUS_CFG			0x1200
+#define MAC_STATUS_CFG_BBP_RF_BUSY	FIELD32(0x00000003)
+
+/*
+ * PWR_PIN_CFG:
+ */
+#define PWR_PIN_CFG			0x1204
+
+/*
+ * AUTOWAKEUP_CFG: Manual power control / status register
+ * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set
+ * AUTOWAKE: 0:sleep, 1:awake
+ */
+#define AUTOWAKEUP_CFG			0x1208
+#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME	FIELD32(0x000000ff)
+#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE	FIELD32(0x00007f00)
+#define AUTOWAKEUP_CFG_AUTOWAKE		FIELD32(0x00008000)
+
+/*
+ * EDCA_AC0_CFG:
+ */
+#define EDCA_AC0_CFG			0x1300
+#define EDCA_AC0_CFG_TX_OP		FIELD32(0x000000ff)
+#define EDCA_AC0_CFG_AIFSN		FIELD32(0x00000f00)
+#define EDCA_AC0_CFG_CWMIN		FIELD32(0x0000f000)
+#define EDCA_AC0_CFG_CWMAX		FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC1_CFG:
+ */
+#define EDCA_AC1_CFG			0x1304
+#define EDCA_AC1_CFG_TX_OP		FIELD32(0x000000ff)
+#define EDCA_AC1_CFG_AIFSN		FIELD32(0x00000f00)
+#define EDCA_AC1_CFG_CWMIN		FIELD32(0x0000f000)
+#define EDCA_AC1_CFG_CWMAX		FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC2_CFG:
+ */
+#define EDCA_AC2_CFG			0x1308
+#define EDCA_AC2_CFG_TX_OP		FIELD32(0x000000ff)
+#define EDCA_AC2_CFG_AIFSN		FIELD32(0x00000f00)
+#define EDCA_AC2_CFG_CWMIN		FIELD32(0x0000f000)
+#define EDCA_AC2_CFG_CWMAX		FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC3_CFG:
+ */
+#define EDCA_AC3_CFG			0x130c
+#define EDCA_AC3_CFG_TX_OP		FIELD32(0x000000ff)
+#define EDCA_AC3_CFG_AIFSN		FIELD32(0x00000f00)
+#define EDCA_AC3_CFG_CWMIN		FIELD32(0x0000f000)
+#define EDCA_AC3_CFG_CWMAX		FIELD32(0x000f0000)
+
+/*
+ * EDCA_TID_AC_MAP:
+ */
+#define EDCA_TID_AC_MAP			0x1310
+
+/*
+ * TX_PWR_CFG_0:
+ */
+#define TX_PWR_CFG_0			0x1314
+#define TX_PWR_CFG_0_1MBS		FIELD32(0x0000000f)
+#define TX_PWR_CFG_0_2MBS		FIELD32(0x000000f0)
+#define TX_PWR_CFG_0_55MBS		FIELD32(0x00000f00)
+#define TX_PWR_CFG_0_11MBS		FIELD32(0x0000f000)
+#define TX_PWR_CFG_0_6MBS		FIELD32(0x000f0000)
+#define TX_PWR_CFG_0_9MBS		FIELD32(0x00f00000)
+#define TX_PWR_CFG_0_12MBS		FIELD32(0x0f000000)
+#define TX_PWR_CFG_0_18MBS		FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_1:
+ */
+#define TX_PWR_CFG_1			0x1318
+#define TX_PWR_CFG_1_24MBS		FIELD32(0x0000000f)
+#define TX_PWR_CFG_1_36MBS		FIELD32(0x000000f0)
+#define TX_PWR_CFG_1_48MBS		FIELD32(0x00000f00)
+#define TX_PWR_CFG_1_54MBS		FIELD32(0x0000f000)
+#define TX_PWR_CFG_1_MCS0		FIELD32(0x000f0000)
+#define TX_PWR_CFG_1_MCS1		FIELD32(0x00f00000)
+#define TX_PWR_CFG_1_MCS2		FIELD32(0x0f000000)
+#define TX_PWR_CFG_1_MCS3		FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_2:
+ */
+#define TX_PWR_CFG_2			0x131c
+#define TX_PWR_CFG_2_MCS4		FIELD32(0x0000000f)
+#define TX_PWR_CFG_2_MCS5		FIELD32(0x000000f0)
+#define TX_PWR_CFG_2_MCS6		FIELD32(0x00000f00)
+#define TX_PWR_CFG_2_MCS7		FIELD32(0x0000f000)
+#define TX_PWR_CFG_2_MCS8		FIELD32(0x000f0000)
+#define TX_PWR_CFG_2_MCS9		FIELD32(0x00f00000)
+#define TX_PWR_CFG_2_MCS10		FIELD32(0x0f000000)
+#define TX_PWR_CFG_2_MCS11		FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_3:
+ */
+#define TX_PWR_CFG_3			0x1320
+#define TX_PWR_CFG_3_MCS12		FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_MCS13		FIELD32(0x000000f0)
+#define TX_PWR_CFG_3_MCS14		FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_MCS15		FIELD32(0x0000f000)
+#define TX_PWR_CFG_3_UKNOWN1		FIELD32(0x000f0000)
+#define TX_PWR_CFG_3_UKNOWN2		FIELD32(0x00f00000)
+#define TX_PWR_CFG_3_UKNOWN3		FIELD32(0x0f000000)
+#define TX_PWR_CFG_3_UKNOWN4		FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_4:
+ */
+#define TX_PWR_CFG_4			0x1324
+#define TX_PWR_CFG_4_UKNOWN5		FIELD32(0x0000000f)
+#define TX_PWR_CFG_4_UKNOWN6		FIELD32(0x000000f0)
+#define TX_PWR_CFG_4_UKNOWN7		FIELD32(0x00000f00)
+#define TX_PWR_CFG_4_UKNOWN8		FIELD32(0x0000f000)
+
+/*
+ * TX_PIN_CFG:
+ */
+#define TX_PIN_CFG			0x1328
+#define TX_PIN_CFG_PA_PE_A0_EN		FIELD32(0x00000001)
+#define TX_PIN_CFG_PA_PE_G0_EN		FIELD32(0x00000002)
+#define TX_PIN_CFG_PA_PE_A1_EN		FIELD32(0x00000004)
+#define TX_PIN_CFG_PA_PE_G1_EN		FIELD32(0x00000008)
+#define TX_PIN_CFG_PA_PE_A0_POL		FIELD32(0x00000010)
+#define TX_PIN_CFG_PA_PE_G0_POL		FIELD32(0x00000020)
+#define TX_PIN_CFG_PA_PE_A1_POL		FIELD32(0x00000040)
+#define TX_PIN_CFG_PA_PE_G1_POL		FIELD32(0x00000080)
+#define TX_PIN_CFG_LNA_PE_A0_EN		FIELD32(0x00000100)
+#define TX_PIN_CFG_LNA_PE_G0_EN		FIELD32(0x00000200)
+#define TX_PIN_CFG_LNA_PE_A1_EN		FIELD32(0x00000400)
+#define TX_PIN_CFG_LNA_PE_G1_EN		FIELD32(0x00000800)
+#define TX_PIN_CFG_LNA_PE_A0_POL	FIELD32(0x00001000)
+#define TX_PIN_CFG_LNA_PE_G0_POL	FIELD32(0x00002000)
+#define TX_PIN_CFG_LNA_PE_A1_POL	FIELD32(0x00004000)
+#define TX_PIN_CFG_LNA_PE_G1_POL	FIELD32(0x00008000)
+#define TX_PIN_CFG_RFTR_EN		FIELD32(0x00010000)
+#define TX_PIN_CFG_RFTR_POL		FIELD32(0x00020000)
+#define TX_PIN_CFG_TRSW_EN		FIELD32(0x00040000)
+#define TX_PIN_CFG_TRSW_POL		FIELD32(0x00080000)
+
+/*
+ * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
+ */
+#define TX_BAND_CFG			0x132c
+#define TX_BAND_CFG_HT40_PLUS		FIELD32(0x00000001)
+#define TX_BAND_CFG_A			FIELD32(0x00000002)
+#define TX_BAND_CFG_BG			FIELD32(0x00000004)
+
+/*
+ * TX_SW_CFG0:
+ */
+#define TX_SW_CFG0			0x1330
+
+/*
+ * TX_SW_CFG1:
+ */
+#define TX_SW_CFG1			0x1334
+
+/*
+ * TX_SW_CFG2:
+ */
+#define TX_SW_CFG2			0x1338
+
+/*
+ * TXOP_THRES_CFG:
+ */
+#define TXOP_THRES_CFG			0x133c
+
+/*
+ * TXOP_CTRL_CFG:
+ */
+#define TXOP_CTRL_CFG			0x1340
+
+/*
+ * TX_RTS_CFG:
+ * RTS_THRES: unit:byte
+ * RTS_FBK_EN: enable rts rate fallback
+ */
+#define TX_RTS_CFG			0x1344
+#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT	FIELD32(0x000000ff)
+#define TX_RTS_CFG_RTS_THRES		FIELD32(0x00ffff00)
+#define TX_RTS_CFG_RTS_FBK_EN		FIELD32(0x01000000)
+
+/*
+ * TX_TIMEOUT_CFG:
+ * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us
+ * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure
+ * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation.
+ *                it is recommended that:
+ *                (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
+ */
+#define TX_TIMEOUT_CFG			0x1348
+#define TX_TIMEOUT_CFG_MPDU_LIFETIME	FIELD32(0x000000f0)
+#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT	FIELD32(0x0000ff00)
+#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT	FIELD32(0x00ff0000)
+
+/*
+ * TX_RTY_CFG:
+ * SHORT_RTY_LIMIT: short retry limit
+ * LONG_RTY_LIMIT: long retry limit
+ * LONG_RTY_THRE: Long retry threshoold
+ * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode
+ *                   0:expired by retry limit, 1: expired by mpdu life timer
+ * AGG_RTY_MODE: Aggregate MPDU retry mode
+ *               0:expired by retry limit, 1: expired by mpdu life timer
+ * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable
+ */
+#define TX_RTY_CFG			0x134c
+#define TX_RTY_CFG_SHORT_RTY_LIMIT	FIELD32(0x000000ff)
+#define TX_RTY_CFG_LONG_RTY_LIMIT	FIELD32(0x0000ff00)
+#define TX_RTY_CFG_LONG_RTY_THRE	FIELD32(0x0fff0000)
+#define TX_RTY_CFG_NON_AGG_RTY_MODE	FIELD32(0x10000000)
+#define TX_RTY_CFG_AGG_RTY_MODE		FIELD32(0x20000000)
+#define TX_RTY_CFG_TX_AUTO_FB_ENABLE	FIELD32(0x40000000)
+
+/*
+ * TX_LINK_CFG:
+ * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us
+ * MFB_ENABLE: TX apply remote MFB 1:enable
+ * REMOTE_UMFS_ENABLE: remote unsolicit  MFB enable
+ *                     0: not apply remote remote unsolicit (MFS=7)
+ * TX_MRQ_EN: MCS request TX enable
+ * TX_RDG_EN: RDG TX enable
+ * TX_CF_ACK_EN: Piggyback CF-ACK enable
+ * REMOTE_MFB: remote MCS feedback
+ * REMOTE_MFS: remote MCS feedback sequence number
+ */
+#define TX_LINK_CFG			0x1350
+#define TX_LINK_CFG_REMOTE_MFB_LIFETIME	FIELD32(0x000000ff)
+#define TX_LINK_CFG_MFB_ENABLE		FIELD32(0x00000100)
+#define TX_LINK_CFG_REMOTE_UMFS_ENABLE	FIELD32(0x00000200)
+#define TX_LINK_CFG_TX_MRQ_EN		FIELD32(0x00000400)
+#define TX_LINK_CFG_TX_RDG_EN		FIELD32(0x00000800)
+#define TX_LINK_CFG_TX_CF_ACK_EN	FIELD32(0x00001000)
+#define TX_LINK_CFG_REMOTE_MFB		FIELD32(0x00ff0000)
+#define TX_LINK_CFG_REMOTE_MFS		FIELD32(0xff000000)
+
+/*
+ * HT_FBK_CFG0:
+ */
+#define HT_FBK_CFG0			0x1354
+#define HT_FBK_CFG0_HTMCS0FBK		FIELD32(0x0000000f)
+#define HT_FBK_CFG0_HTMCS1FBK		FIELD32(0x000000f0)
+#define HT_FBK_CFG0_HTMCS2FBK		FIELD32(0x00000f00)
+#define HT_FBK_CFG0_HTMCS3FBK		FIELD32(0x0000f000)
+#define HT_FBK_CFG0_HTMCS4FBK		FIELD32(0x000f0000)
+#define HT_FBK_CFG0_HTMCS5FBK		FIELD32(0x00f00000)
+#define HT_FBK_CFG0_HTMCS6FBK		FIELD32(0x0f000000)
+#define HT_FBK_CFG0_HTMCS7FBK		FIELD32(0xf0000000)
+
+/*
+ * HT_FBK_CFG1:
+ */
+#define HT_FBK_CFG1			0x1358
+#define HT_FBK_CFG1_HTMCS8FBK		FIELD32(0x0000000f)
+#define HT_FBK_CFG1_HTMCS9FBK		FIELD32(0x000000f0)
+#define HT_FBK_CFG1_HTMCS10FBK		FIELD32(0x00000f00)
+#define HT_FBK_CFG1_HTMCS11FBK		FIELD32(0x0000f000)
+#define HT_FBK_CFG1_HTMCS12FBK		FIELD32(0x000f0000)
+#define HT_FBK_CFG1_HTMCS13FBK		FIELD32(0x00f00000)
+#define HT_FBK_CFG1_HTMCS14FBK		FIELD32(0x0f000000)
+#define HT_FBK_CFG1_HTMCS15FBK		FIELD32(0xf0000000)
+
+/*
+ * LG_FBK_CFG0:
+ */
+#define LG_FBK_CFG0			0x135c
+#define LG_FBK_CFG0_OFDMMCS0FBK		FIELD32(0x0000000f)
+#define LG_FBK_CFG0_OFDMMCS1FBK		FIELD32(0x000000f0)
+#define LG_FBK_CFG0_OFDMMCS2FBK		FIELD32(0x00000f00)
+#define LG_FBK_CFG0_OFDMMCS3FBK		FIELD32(0x0000f000)
+#define LG_FBK_CFG0_OFDMMCS4FBK		FIELD32(0x000f0000)
+#define LG_FBK_CFG0_OFDMMCS5FBK		FIELD32(0x00f00000)
+#define LG_FBK_CFG0_OFDMMCS6FBK		FIELD32(0x0f000000)
+#define LG_FBK_CFG0_OFDMMCS7FBK		FIELD32(0xf0000000)
+
+/*
+ * LG_FBK_CFG1:
+ */
+#define LG_FBK_CFG1			0x1360
+#define LG_FBK_CFG0_CCKMCS0FBK		FIELD32(0x0000000f)
+#define LG_FBK_CFG0_CCKMCS1FBK		FIELD32(0x000000f0)
+#define LG_FBK_CFG0_CCKMCS2FBK		FIELD32(0x00000f00)
+#define LG_FBK_CFG0_CCKMCS3FBK		FIELD32(0x0000f000)
+
+/*
+ * CCK_PROT_CFG: CCK Protection
+ * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)
+ * PROTECT_CTRL: Protection control frame type for CCK TX
+ *               0:none, 1:RTS/CTS, 2:CTS-to-self
+ * PROTECT_NAV: TXOP protection type for CCK TX
+ *              0:none, 1:ShortNAVprotect, 2:LongNAVProtect
+ * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow
+ * RTS_TH_EN: RTS threshold enable on CCK TX
+ */
+#define CCK_PROT_CFG			0x1364
+#define CCK_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
+#define CCK_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
+#define CCK_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_MM40	FIELD32(0x00800000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_GF20	FIELD32(0x01000000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_GF40	FIELD32(0x02000000)
+#define CCK_PROT_CFG_RTS_TH_EN		FIELD32(0x04000000)
+
+/*
+ * OFDM_PROT_CFG: OFDM Protection
+ */
+#define OFDM_PROT_CFG			0x1368
+#define OFDM_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
+#define OFDM_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
+#define OFDM_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40	FIELD32(0x00800000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20	FIELD32(0x01000000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40	FIELD32(0x02000000)
+#define OFDM_PROT_CFG_RTS_TH_EN		FIELD32(0x04000000)
+
+/*
+ * MM20_PROT_CFG: MM20 Protection
+ */
+#define MM20_PROT_CFG			0x136c
+#define MM20_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
+#define MM20_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
+#define MM20_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_MM40	FIELD32(0x00800000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_GF20	FIELD32(0x01000000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_GF40	FIELD32(0x02000000)
+#define MM20_PROT_CFG_RTS_TH_EN		FIELD32(0x04000000)
+
+/*
+ * MM40_PROT_CFG: MM40 Protection
+ */
+#define MM40_PROT_CFG			0x1370
+#define MM40_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
+#define MM40_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
+#define MM40_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_MM40	FIELD32(0x00800000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_GF20	FIELD32(0x01000000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_GF40	FIELD32(0x02000000)
+#define MM40_PROT_CFG_RTS_TH_EN		FIELD32(0x04000000)
+
+/*
+ * GF20_PROT_CFG: GF20 Protection
+ */
+#define GF20_PROT_CFG			0x1374
+#define GF20_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
+#define GF20_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
+#define GF20_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_MM40	FIELD32(0x00800000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_GF20	FIELD32(0x01000000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_GF40	FIELD32(0x02000000)
+#define GF20_PROT_CFG_RTS_TH_EN		FIELD32(0x04000000)
+
+/*
+ * GF40_PROT_CFG: GF40 Protection
+ */
+#define GF40_PROT_CFG			0x1378
+#define GF40_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
+#define GF40_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
+#define GF40_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_MM40	FIELD32(0x00800000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_GF20	FIELD32(0x01000000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_GF40	FIELD32(0x02000000)
+#define GF40_PROT_CFG_RTS_TH_EN		FIELD32(0x04000000)
+
+/*
+ * EXP_CTS_TIME:
+ */
+#define EXP_CTS_TIME			0x137c
+
+/*
+ * EXP_ACK_TIME:
+ */
+#define EXP_ACK_TIME			0x1380
+
+/*
+ * RX_FILTER_CFG: RX configuration register.
+ */
+#define RX_FILTER_CFG			0x1400
+#define RX_FILTER_CFG_DROP_CRC_ERROR	FIELD32(0x00000001)
+#define RX_FILTER_CFG_DROP_PHY_ERROR	FIELD32(0x00000002)
+#define RX_FILTER_CFG_DROP_NOT_TO_ME	FIELD32(0x00000004)
+#define RX_FILTER_CFG_DROP_NOT_MY_BSSD	FIELD32(0x00000008)
+#define RX_FILTER_CFG_DROP_VER_ERROR	FIELD32(0x00000010)
+#define RX_FILTER_CFG_DROP_MULTICAST	FIELD32(0x00000020)
+#define RX_FILTER_CFG_DROP_BROADCAST	FIELD32(0x00000040)
+#define RX_FILTER_CFG_DROP_DUPLICATE	FIELD32(0x00000080)
+#define RX_FILTER_CFG_DROP_CF_END_ACK	FIELD32(0x00000100)
+#define RX_FILTER_CFG_DROP_CF_END	FIELD32(0x00000200)
+#define RX_FILTER_CFG_DROP_ACK		FIELD32(0x00000400)
+#define RX_FILTER_CFG_DROP_CTS		FIELD32(0x00000800)
+#define RX_FILTER_CFG_DROP_RTS		FIELD32(0x00001000)
+#define RX_FILTER_CFG_DROP_PSPOLL	FIELD32(0x00002000)
+#define RX_FILTER_CFG_DROP_BA		FIELD32(0x00004000)
+#define RX_FILTER_CFG_DROP_BAR		FIELD32(0x00008000)
+#define RX_FILTER_CFG_DROP_CNTL		FIELD32(0x00010000)
+
+/*
+ * AUTO_RSP_CFG:
+ * AUTORESPONDER: 0: disable, 1: enable
+ * BAC_ACK_POLICY: 0:long, 1:short preamble
+ * CTS_40_MMODE: Response CTS 40MHz duplicate mode
+ * CTS_40_MREF: Response CTS 40MHz duplicate mode
+ * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble
+ * DUAL_CTS_EN: Power bit value in control frame
+ * ACK_CTS_PSM_BIT:Power bit value in control frame
+ */
+#define AUTO_RSP_CFG			0x1404
+#define AUTO_RSP_CFG_AUTORESPONDER	FIELD32(0x00000001)
+#define AUTO_RSP_CFG_BAC_ACK_POLICY	FIELD32(0x00000002)
+#define AUTO_RSP_CFG_CTS_40_MMODE	FIELD32(0x00000004)
+#define AUTO_RSP_CFG_CTS_40_MREF	FIELD32(0x00000008)
+#define AUTO_RSP_CFG_AR_PREAMBLE	FIELD32(0x00000010)
+#define AUTO_RSP_CFG_DUAL_CTS_EN	FIELD32(0x00000040)
+#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT	FIELD32(0x00000080)
+
+/*
+ * LEGACY_BASIC_RATE:
+ */
+#define LEGACY_BASIC_RATE		0x1408
+
+/*
+ * HT_BASIC_RATE:
+ */
+#define HT_BASIC_RATE			0x140c
+
+/*
+ * HT_CTRL_CFG:
+ */
+#define HT_CTRL_CFG			0x1410
+
+/*
+ * SIFS_COST_CFG:
+ */
+#define SIFS_COST_CFG			0x1414
+
+/*
+ * RX_PARSER_CFG:
+ * Set NAV for all received frames
+ */
+#define RX_PARSER_CFG			0x1418
+
+/*
+ * TX_SEC_CNT0:
+ */
+#define TX_SEC_CNT0			0x1500
+
+/*
+ * RX_SEC_CNT0:
+ */
+#define RX_SEC_CNT0			0x1504
+
+/*
+ * CCMP_FC_MUTE:
+ */
+#define CCMP_FC_MUTE			0x1508
+
+/*
+ * TXOP_HLDR_ADDR0:
+ */
+#define TXOP_HLDR_ADDR0			0x1600
+
+/*
+ * TXOP_HLDR_ADDR1:
+ */
+#define TXOP_HLDR_ADDR1			0x1604
+
+/*
+ * TXOP_HLDR_ET:
+ */
+#define TXOP_HLDR_ET			0x1608
+
+/*
+ * QOS_CFPOLL_RA_DW0:
+ */
+#define QOS_CFPOLL_RA_DW0		0x160c
+
+/*
+ * QOS_CFPOLL_RA_DW1:
+ */
+#define QOS_CFPOLL_RA_DW1		0x1610
+
+/*
+ * QOS_CFPOLL_QC:
+ */
+#define QOS_CFPOLL_QC			0x1614
+
+/*
+ * RX_STA_CNT0: RX PLCP error count & RX CRC error count
+ */
+#define RX_STA_CNT0			0x1700
+#define RX_STA_CNT0_CRC_ERR		FIELD32(0x0000ffff)
+#define RX_STA_CNT0_PHY_ERR		FIELD32(0xffff0000)
+
+/*
+ * RX_STA_CNT1: RX False CCA count & RX LONG frame count
+ */
+#define RX_STA_CNT1			0x1704
+#define RX_STA_CNT1_FALSE_CCA		FIELD32(0x0000ffff)
+#define RX_STA_CNT1_PLCP_ERR		FIELD32(0xffff0000)
+
+/*
+ * RX_STA_CNT2:
+ */
+#define RX_STA_CNT2			0x1708
+#define RX_STA_CNT2_RX_DUPLI_COUNT	FIELD32(0x0000ffff)
+#define RX_STA_CNT2_RX_FIFO_OVERFLOW	FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT0: TX Beacon count
+ */
+#define TX_STA_CNT0			0x170c
+#define TX_STA_CNT0_TX_FAIL_COUNT	FIELD32(0x0000ffff)
+#define TX_STA_CNT0_TX_BEACON_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT1: TX tx count
+ */
+#define TX_STA_CNT1			0x1710
+#define TX_STA_CNT1_TX_SUCCESS		FIELD32(0x0000ffff)
+#define TX_STA_CNT1_TX_RETRANSMIT	FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT2: TX tx count
+ */
+#define TX_STA_CNT2			0x1714
+#define TX_STA_CNT2_TX_ZERO_LEN_COUNT	FIELD32(0x0000ffff)
+#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_STA_FIFO: TX Result for specific PID status fifo register
+ */
+#define TX_STA_FIFO			0x1718
+#define TX_STA_FIFO_VALID		FIELD32(0x00000001)
+#define TX_STA_FIFO_PID_TYPE		FIELD32(0x0000001e)
+#define TX_STA_FIFO_TX_SUCCESS		FIELD32(0x00000020)
+#define TX_STA_FIFO_TX_AGGRE		FIELD32(0x00000040)
+#define TX_STA_FIFO_TX_ACK_REQUIRED	FIELD32(0x00000080)
+#define TX_STA_FIFO_WCID		FIELD32(0x0000ff00)
+#define TX_STA_FIFO_SUCCESS_RATE	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT: Debug counter
+ */
+#define TX_AGG_CNT			0x171c
+#define TX_AGG_CNT_NON_AGG_TX_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT_AGG_TX_COUNT		FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT0:
+ */
+#define TX_AGG_CNT0			0x1720
+#define TX_AGG_CNT0_AGG_SIZE_1_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT0_AGG_SIZE_2_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT1:
+ */
+#define TX_AGG_CNT1			0x1724
+#define TX_AGG_CNT1_AGG_SIZE_3_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT1_AGG_SIZE_4_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT2:
+ */
+#define TX_AGG_CNT2			0x1728
+#define TX_AGG_CNT2_AGG_SIZE_5_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT2_AGG_SIZE_6_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT3:
+ */
+#define TX_AGG_CNT3			0x172c
+#define TX_AGG_CNT3_AGG_SIZE_7_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT3_AGG_SIZE_8_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT4:
+ */
+#define TX_AGG_CNT4			0x1730
+#define TX_AGG_CNT4_AGG_SIZE_9_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT4_AGG_SIZE_10_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT5:
+ */
+#define TX_AGG_CNT5			0x1734
+#define TX_AGG_CNT5_AGG_SIZE_11_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT5_AGG_SIZE_12_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT6:
+ */
+#define TX_AGG_CNT6			0x1738
+#define TX_AGG_CNT6_AGG_SIZE_13_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT6_AGG_SIZE_14_COUNT	FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT7:
+ */
+#define TX_AGG_CNT7			0x173c
+#define TX_AGG_CNT7_AGG_SIZE_15_COUNT	FIELD32(0x0000ffff)
+#define TX_AGG_CNT7_AGG_SIZE_16_COUNT	FIELD32(0xffff0000)
+
+/*
+ * MPDU_DENSITY_CNT:
+ * TX_ZERO_DEL: TX zero length delimiter count
+ * RX_ZERO_DEL: RX zero length delimiter count
+ */
+#define MPDU_DENSITY_CNT		0x1740
+#define MPDU_DENSITY_CNT_TX_ZERO_DEL	FIELD32(0x0000ffff)
+#define MPDU_DENSITY_CNT_RX_ZERO_DEL	FIELD32(0xffff0000)
+
+/*
+ * Security key table memory.
+ * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
+ * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
+ * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
+ * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
+ * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry
+ * SHARED_KEY_MODE_BASE: 4-byte * 16-entry
+ */
+#define MAC_WCID_BASE			0x1800
+#define PAIRWISE_KEY_TABLE_BASE		0x4000
+#define MAC_IVEIV_TABLE_BASE		0x6000
+#define MAC_WCID_ATTRIBUTE_BASE		0x6800
+#define SHARED_KEY_TABLE_BASE		0x6c00
+#define SHARED_KEY_MODE_BASE		0x7000
+
+#define MAC_WCID_ENTRY(__idx) \
+	( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+	( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
+#define MAC_IVEIV_ENTRY(__idx) \
+	( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) )
+#define MAC_WCID_ATTR_ENTRY(__idx) \
+	( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) )
+#define SHARED_KEY_ENTRY(__idx) \
+	( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
+#define SHARED_KEY_MODE_ENTRY(__idx) \
+	( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) )
+
+struct mac_wcid_entry {
+	u8 mac[6];
+	u8 reserved[2];
+} __attribute__ ((packed));
+
+struct hw_key_entry {
+	u8 key[16];
+	u8 tx_mic[8];
+	u8 rx_mic[8];
+} __attribute__ ((packed));
+
+struct mac_iveiv_entry {
+	u8 iv[8];
+} __attribute__ ((packed));
+
+/*
+ * MAC_WCID_ATTRIBUTE:
+ */
+#define MAC_WCID_ATTRIBUTE_KEYTAB	FIELD32(0x00000001)
+#define MAC_WCID_ATTRIBUTE_CIPHER	FIELD32(0x0000000e)
+#define MAC_WCID_ATTRIBUTE_BSS_IDX	FIELD32(0x00000070)
+#define MAC_WCID_ATTRIBUTE_RX_WIUDF	FIELD32(0x00000380)
+
+/*
+ * SHARED_KEY_MODE:
+ */
+#define SHARED_KEY_MODE_BSS0_KEY0	FIELD32(0x00000007)
+#define SHARED_KEY_MODE_BSS0_KEY1	FIELD32(0x00000070)
+#define SHARED_KEY_MODE_BSS0_KEY2	FIELD32(0x00000700)
+#define SHARED_KEY_MODE_BSS0_KEY3	FIELD32(0x00007000)
+#define SHARED_KEY_MODE_BSS1_KEY0	FIELD32(0x00070000)
+#define SHARED_KEY_MODE_BSS1_KEY1	FIELD32(0x00700000)
+#define SHARED_KEY_MODE_BSS1_KEY2	FIELD32(0x07000000)
+#define SHARED_KEY_MODE_BSS1_KEY3	FIELD32(0x70000000)
+
+/*
+ * HOST-MCU communication
+ */
+
+/*
+ * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
+ */
+#define H2M_MAILBOX_CSR			0x7010
+#define H2M_MAILBOX_CSR_ARG0		FIELD32(0x000000ff)
+#define H2M_MAILBOX_CSR_ARG1		FIELD32(0x0000ff00)
+#define H2M_MAILBOX_CSR_CMD_TOKEN	FIELD32(0x00ff0000)
+#define H2M_MAILBOX_CSR_OWNER		FIELD32(0xff000000)
+
+/*
+ * H2M_MAILBOX_CID:
+ */
+#define H2M_MAILBOX_CID			0x7014
+#define H2M_MAILBOX_CID_CMD0		FIELD32(0x000000ff)
+#define H2M_MAILBOX_CID_CMD1		FIELD32(0x0000ff00)
+#define H2M_MAILBOX_CID_CMD2		FIELD32(0x00ff0000)
+#define H2M_MAILBOX_CID_CMD3		FIELD32(0xff000000)
+
+/*
+ * H2M_MAILBOX_STATUS:
+ */
+#define H2M_MAILBOX_STATUS		0x701c
+
+/*
+ * H2M_INT_SRC:
+ */
+#define H2M_INT_SRC			0x7024
+
+/*
+ * H2M_BBP_AGENT:
+ */
+#define H2M_BBP_AGENT			0x7028
+
+/*
+ * MCU_LEDCS: LED control for MCU Mailbox.
+ */
+#define MCU_LEDCS_LED_MODE		FIELD8(0x1f)
+#define MCU_LEDCS_POLARITY		FIELD8(0x01)
+
+/*
+ * HW_CS_CTS_BASE:
+ * Carrier-sense CTS frame base address.
+ * It's where mac stores carrier-sense frame for carrier-sense function.
+ */
+#define HW_CS_CTS_BASE			0x7700
+
+/*
+ * HW_DFS_CTS_BASE:
+ * FS CTS frame base address. It's where mac stores CTS frame for DFS.
+ */
+#define HW_DFS_CTS_BASE			0x7780
+
+/*
+ * TXRX control registers - base address 0x3000
+ */
+
+/*
+ * TXRX_CSR1:
+ * rt2860b  UNKNOWN reg use R/O Reg Addr 0x77d0 first..
+ */
+#define TXRX_CSR1			0x77d0
+
+/*
+ * HW_DEBUG_SETTING_BASE:
+ * since NULL frame won't be that long (256 byte)
+ * We steal 16 tail bytes to save debugging settings
+ */
+#define HW_DEBUG_SETTING_BASE		0x77f0
+#define HW_DEBUG_SETTING_BASE2		0x7770
+
+/*
+ * HW_BEACON_BASE
+ * In order to support maximum 8 MBSS and its maximum length
+ * is 512 bytes for each beacon
+ * Three section discontinue memory segments will be used.
+ * 1. The original region for BCN 0~3
+ * 2. Extract memory from FCE table for BCN 4~5
+ * 3. Extract memory from Pair-wise key table for BCN 6~7
+ *    It occupied those memory of wcid 238~253 for BCN 6
+ *    and wcid 222~237 for BCN 7
+ *
+ * IMPORTANT NOTE: Not sure why legacy driver does this,
+ * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
+ */
+#define HW_BEACON_BASE0			0x7800
+#define HW_BEACON_BASE1			0x7a00
+#define HW_BEACON_BASE2			0x7c00
+#define HW_BEACON_BASE3			0x7e00
+#define HW_BEACON_BASE4			0x7200
+#define HW_BEACON_BASE5			0x7400
+#define HW_BEACON_BASE6			0x5dc0
+#define HW_BEACON_BASE7			0x5bc0
+
+#define HW_BEACON_OFFSET(__index) \
+	( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \
+	  (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \
+	  (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) )
+
+/*
+ * 8051 firmware image.
+ */
+#define FIRMWARE_RT2870			"/*(DEBLOBBED)*/"
+#define FIRMWARE_IMAGE_BASE		0x3000
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * BBP 1: TX Antenna
+ */
+#define BBP1_TX_POWER			FIELD8(0x07)
+#define BBP1_TX_ANTENNA			FIELD8(0x18)
+
+/*
+ * BBP 3: RX Antenna
+ */
+#define BBP3_RX_ANTENNA			FIELD8(0x18)
+#define BBP3_HT40_PLUS			FIELD8(0x20)
+
+/*
+ * BBP 4: Bandwidth
+ */
+#define BBP4_TX_BF			FIELD8(0x01)
+#define BBP4_BANDWIDTH			FIELD8(0x18)
+
+/*
+ * RFCSR registers
+ * The wordsize of the RFCSR is 8 bits.
+ */
+
+/*
+ * RFCSR 6:
+ */
+#define RFCSR6_R			FIELD8(0x03)
+
+/*
+ * RFCSR 7:
+ */
+#define RFCSR7_RF_TUNING		FIELD8(0x01)
+
+/*
+ * RFCSR 12:
+ */
+#define RFCSR12_TX_POWER		FIELD8(0x1f)
+
+/*
+ * RFCSR 22:
+ */
+#define RFCSR22_BASEBAND_LOOPBACK	FIELD8(0x01)
+
+/*
+ * RFCSR 23:
+ */
+#define RFCSR23_FREQ_OFFSET		FIELD8(0x7f)
+
+/*
+ * RFCSR 30:
+ */
+#define RFCSR30_RF_CALIBRATION		FIELD8(0x80)
+
+/*
+ * RF registers
+ */
+
+/*
+ * RF 2
+ */
+#define RF2_ANTENNA_RX2			FIELD32(0x00000040)
+#define RF2_ANTENNA_TX1			FIELD32(0x00004000)
+#define RF2_ANTENNA_RX1			FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
+#define RF3_TXPOWER_G			FIELD32(0x00003e00)
+#define RF3_TXPOWER_A_7DBM_BOOST	FIELD32(0x00000200)
+#define RF3_TXPOWER_A			FIELD32(0x00003c00)
+
+/*
+ * RF 4
+ */
+#define RF4_TXPOWER_G			FIELD32(0x000007c0)
+#define RF4_TXPOWER_A_7DBM_BOOST	FIELD32(0x00000040)
+#define RF4_TXPOWER_A			FIELD32(0x00000780)
+#define RF4_FREQ_OFFSET			FIELD32(0x001f8000)
+#define RF4_HT40			FIELD32(0x00200000)
+
+/*
+ * EEPROM content.
+ * The wordsize of the EEPROM is 16 bits.
+ */
+
+/*
+ * EEPROM Version
+ */
+#define EEPROM_VERSION			0x0001
+#define EEPROM_VERSION_FAE		FIELD16(0x00ff)
+#define EEPROM_VERSION_VERSION		FIELD16(0xff00)
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0		0x0002
+#define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_1		0x0003
+#define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0004
+#define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+
+/*
+ * EEPROM ANTENNA config
+ * RXPATH: 1: 1R, 2: 2R, 3: 3R
+ * TXPATH: 1: 1T, 2: 2T
+ */
+#define	EEPROM_ANTENNA			0x001a
+#define EEPROM_ANTENNA_RXPATH		FIELD16(0x000f)
+#define EEPROM_ANTENNA_TXPATH		FIELD16(0x00f0)
+#define EEPROM_ANTENNA_RF_TYPE		FIELD16(0x0f00)
+
+/*
+ * EEPROM NIC config
+ * CARDBUS_ACCEL: 0 - enable, 1 - disable
+ */
+#define	EEPROM_NIC			0x001b
+#define EEPROM_NIC_HW_RADIO		FIELD16(0x0001)
+#define EEPROM_NIC_DYNAMIC_TX_AGC	FIELD16(0x0002)
+#define EEPROM_NIC_EXTERNAL_LNA_BG	FIELD16(0x0004)
+#define EEPROM_NIC_EXTERNAL_LNA_A	FIELD16(0x0008)
+#define EEPROM_NIC_CARDBUS_ACCEL	FIELD16(0x0010)
+#define EEPROM_NIC_BW40M_SB_BG		FIELD16(0x0020)
+#define EEPROM_NIC_BW40M_SB_A		FIELD16(0x0040)
+#define EEPROM_NIC_WPS_PBC		FIELD16(0x0080)
+#define EEPROM_NIC_BW40M_BG		FIELD16(0x0100)
+#define EEPROM_NIC_BW40M_A		FIELD16(0x0200)
+
+/*
+ * EEPROM frequency
+ */
+#define	EEPROM_FREQ			0x001d
+#define EEPROM_FREQ_OFFSET		FIELD16(0x00ff)
+#define EEPROM_FREQ_LED_MODE		FIELD16(0x7f00)
+#define EEPROM_FREQ_LED_POLARITY	FIELD16(0x1000)
+
+/*
+ * EEPROM LED
+ * POLARITY_RDY_G: Polarity RDY_G setting.
+ * POLARITY_RDY_A: Polarity RDY_A setting.
+ * POLARITY_ACT: Polarity ACT setting.
+ * POLARITY_GPIO_0: Polarity GPIO0 setting.
+ * POLARITY_GPIO_1: Polarity GPIO1 setting.
+ * POLARITY_GPIO_2: Polarity GPIO2 setting.
+ * POLARITY_GPIO_3: Polarity GPIO3 setting.
+ * POLARITY_GPIO_4: Polarity GPIO4 setting.
+ * LED_MODE: Led mode.
+ */
+#define EEPROM_LED1			0x001e
+#define EEPROM_LED2			0x001f
+#define EEPROM_LED3			0x0020
+#define EEPROM_LED_POLARITY_RDY_BG	FIELD16(0x0001)
+#define EEPROM_LED_POLARITY_RDY_A	FIELD16(0x0002)
+#define EEPROM_LED_POLARITY_ACT		FIELD16(0x0004)
+#define EEPROM_LED_POLARITY_GPIO_0	FIELD16(0x0008)
+#define EEPROM_LED_POLARITY_GPIO_1	FIELD16(0x0010)
+#define EEPROM_LED_POLARITY_GPIO_2	FIELD16(0x0020)
+#define EEPROM_LED_POLARITY_GPIO_3	FIELD16(0x0040)
+#define EEPROM_LED_POLARITY_GPIO_4	FIELD16(0x0080)
+#define EEPROM_LED_LED_MODE		FIELD16(0x1f00)
+
+/*
+ * EEPROM LNA
+ */
+#define EEPROM_LNA			0x0022
+#define EEPROM_LNA_BG			FIELD16(0x00ff)
+#define EEPROM_LNA_A0			FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI BG offset
+ */
+#define EEPROM_RSSI_BG			0x0023
+#define EEPROM_RSSI_BG_OFFSET0		FIELD16(0x00ff)
+#define EEPROM_RSSI_BG_OFFSET1		FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI BG2 offset
+ */
+#define EEPROM_RSSI_BG2			0x0024
+#define EEPROM_RSSI_BG2_OFFSET2		FIELD16(0x00ff)
+#define EEPROM_RSSI_BG2_LNA_A1		FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI A offset
+ */
+#define EEPROM_RSSI_A			0x0025
+#define EEPROM_RSSI_A_OFFSET0		FIELD16(0x00ff)
+#define EEPROM_RSSI_A_OFFSET1		FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI A2 offset
+ */
+#define EEPROM_RSSI_A2			0x0026
+#define EEPROM_RSSI_A2_OFFSET2		FIELD16(0x00ff)
+#define EEPROM_RSSI_A2_LNA_A2		FIELD16(0xff00)
+
+/*
+ * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
+ *	This is delta in 40MHZ.
+ * VALUE: Tx Power dalta value (MAX=4)
+ * TYPE: 1: Plus the delta value, 0: minus the delta value
+ * TXPOWER: Enable:
+ */
+#define EEPROM_TXPOWER_DELTA		0x0028
+#define EEPROM_TXPOWER_DELTA_VALUE	FIELD16(0x003f)
+#define EEPROM_TXPOWER_DELTA_TYPE	FIELD16(0x0040)
+#define EEPROM_TXPOWER_DELTA_TXPOWER	FIELD16(0x0080)
+
+/*
+ * EEPROM TXPOWER 802.11BG
+ */
+#define	EEPROM_TXPOWER_BG1		0x0029
+#define	EEPROM_TXPOWER_BG2		0x0030
+#define EEPROM_TXPOWER_BG_SIZE		7
+#define EEPROM_TXPOWER_BG_1		FIELD16(0x00ff)
+#define EEPROM_TXPOWER_BG_2		FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER 802.11A
+ */
+#define EEPROM_TXPOWER_A1		0x003c
+#define EEPROM_TXPOWER_A2		0x0053
+#define EEPROM_TXPOWER_A_SIZE		6
+#define EEPROM_TXPOWER_A_1		FIELD16(0x00ff)
+#define EEPROM_TXPOWER_A_2		FIELD16(0xff00)
+
+/*
+ * EEPROM TXpower byrate: 20MHZ power
+ */
+#define EEPROM_TXPOWER_BYRATE		0x006f
+
+/*
+ * EEPROM BBP.
+ */
+#define	EEPROM_BBP_START		0x0078
+#define EEPROM_BBP_SIZE			16
+#define EEPROM_BBP_VALUE		FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID		FIELD16(0xff00)
+
+/*
+ * MCU mailbox commands.
+ */
+#define MCU_SLEEP			0x30
+#define MCU_WAKEUP			0x31
+#define MCU_RADIO_OFF			0x35
+#define MCU_CURRENT			0x36
+#define MCU_LED				0x50
+#define MCU_LED_STRENGTH		0x51
+#define MCU_LED_1			0x52
+#define MCU_LED_2			0x53
+#define MCU_LED_3			0x54
+#define MCU_RADAR			0x60
+#define MCU_BOOT_SIGNAL			0x72
+#define MCU_BBP_SIGNAL			0x80
+#define MCU_POWER_SAVE			0x83
+
+/*
+ * MCU mailbox tokens
+ */
+#define TOKEN_WAKUP			3
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE			( 4 * sizeof(__le32) )
+#define TXINFO_DESC_SIZE		( 1 * sizeof(__le32) )
+#define TXWI_DESC_SIZE			( 4 * sizeof(__le32) )
+#define RXD_DESC_SIZE			( 1 * sizeof(__le32) )
+#define RXWI_DESC_SIZE			( 4 * sizeof(__le32) )
+
+/*
+ * TX descriptor format for TX, PRIO and Beacon Ring.
+ */
+
+/*
+ * Word0
+ */
+#define TXD_W0_SD_PTR0			FIELD32(0xffffffff)
+
+/*
+ * Word1
+ */
+#define TXD_W1_SD_LEN1			FIELD32(0x00003fff)
+#define TXD_W1_LAST_SEC1		FIELD32(0x00004000)
+#define TXD_W1_BURST			FIELD32(0x00008000)
+#define TXD_W1_SD_LEN0			FIELD32(0x3fff0000)
+#define TXD_W1_LAST_SEC0		FIELD32(0x40000000)
+#define TXD_W1_DMA_DONE			FIELD32(0x80000000)
+
+/*
+ * Word2
+ */
+#define TXD_W2_SD_PTR1			FIELD32(0xffffffff)
+
+/*
+ * Word3
+ * WIV: Wireless Info Valid. 1: Driver filled WI,  0: DMA needs to copy WI
+ * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
+ *       0:MGMT, 1:HCCA 2:EDCA
+ */
+#define TXD_W3_WIV			FIELD32(0x01000000)
+#define TXD_W3_QSEL			FIELD32(0x06000000)
+#define TXD_W3_TCO			FIELD32(0x20000000)
+#define TXD_W3_UCO			FIELD32(0x40000000)
+#define TXD_W3_ICO			FIELD32(0x80000000)
+
+/*
+ * TX Info structure
+ */
+
+/*
+ * Word0
+ * WIV: Wireless Info Valid. 1: Driver filled WI,  0: DMA needs to copy WI
+ * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
+ *       0:MGMT, 1:HCCA 2:EDCA
+ * USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid
+ * DMA_TX_BURST: used ONLY in USB bulk Aggregation.
+ *               Force USB DMA transmit frame from current selected endpoint
+ */
+#define TXINFO_W0_USB_DMA_TX_PKT_LEN	FIELD32(0x0000ffff)
+#define TXINFO_W0_WIV			FIELD32(0x01000000)
+#define TXINFO_W0_QSEL			FIELD32(0x06000000)
+#define TXINFO_W0_SW_USE_LAST_ROUND	FIELD32(0x08000000)
+#define TXINFO_W0_USB_DMA_NEXT_VALID	FIELD32(0x40000000)
+#define TXINFO_W0_USB_DMA_TX_BURST	FIELD32(0x80000000)
+
+/*
+ * TX WI structure
+ */
+
+/*
+ * Word0
+ * FRAG: 1 To inform TKIP engine this is a fragment.
+ * MIMO_PS: The remote peer is in dynamic MIMO-PS mode
+ * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
+ * BW: Channel bandwidth 20MHz or 40 MHz
+ * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
+ */
+#define TXWI_W0_FRAG			FIELD32(0x00000001)
+#define TXWI_W0_MIMO_PS			FIELD32(0x00000002)
+#define TXWI_W0_CF_ACK			FIELD32(0x00000004)
+#define TXWI_W0_TS			FIELD32(0x00000008)
+#define TXWI_W0_AMPDU			FIELD32(0x00000010)
+#define TXWI_W0_MPDU_DENSITY		FIELD32(0x000000e0)
+#define TXWI_W0_TX_OP			FIELD32(0x00000300)
+#define TXWI_W0_MCS			FIELD32(0x007f0000)
+#define TXWI_W0_BW			FIELD32(0x00800000)
+#define TXWI_W0_SHORT_GI		FIELD32(0x01000000)
+#define TXWI_W0_STBC			FIELD32(0x06000000)
+#define TXWI_W0_IFS			FIELD32(0x08000000)
+#define TXWI_W0_PHYMODE			FIELD32(0xc0000000)
+
+/*
+ * Word1
+ */
+#define TXWI_W1_ACK			FIELD32(0x00000001)
+#define TXWI_W1_NSEQ			FIELD32(0x00000002)
+#define TXWI_W1_BW_WIN_SIZE		FIELD32(0x000000fc)
+#define TXWI_W1_WIRELESS_CLI_ID		FIELD32(0x0000ff00)
+#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT	FIELD32(0x0fff0000)
+#define TXWI_W1_PACKETID		FIELD32(0xf0000000)
+
+/*
+ * Word2
+ */
+#define TXWI_W2_IV			FIELD32(0xffffffff)
+
+/*
+ * Word3
+ */
+#define TXWI_W3_EIV			FIELD32(0xffffffff)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ * UNICAST_TO_ME: This RX frame is unicast to me.
+ * MULTICAST: This is a multicast frame.
+ * BROADCAST: This is a broadcast frame.
+ * MY_BSS: this frame belongs to the same BSSID.
+ * CRC_ERROR: CRC error.
+ * CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid.
+ * AMSDU: rx with 802.3 header, not 802.11 header.
+ */
+
+#define RXD_W0_BA			FIELD32(0x00000001)
+#define RXD_W0_DATA			FIELD32(0x00000002)
+#define RXD_W0_NULLDATA			FIELD32(0x00000004)
+#define RXD_W0_FRAG			FIELD32(0x00000008)
+#define RXD_W0_UNICAST_TO_ME		FIELD32(0x00000010)
+#define RXD_W0_MULTICAST		FIELD32(0x00000020)
+#define RXD_W0_BROADCAST		FIELD32(0x00000040)
+#define RXD_W0_MY_BSS			FIELD32(0x00000080)
+#define RXD_W0_CRC_ERROR		FIELD32(0x00000100)
+#define RXD_W0_CIPHER_ERROR		FIELD32(0x00000600)
+#define RXD_W0_AMSDU			FIELD32(0x00000800)
+#define RXD_W0_HTC			FIELD32(0x00001000)
+#define RXD_W0_RSSI			FIELD32(0x00002000)
+#define RXD_W0_L2PAD			FIELD32(0x00004000)
+#define RXD_W0_AMPDU			FIELD32(0x00008000)
+#define RXD_W0_DECRYPTED		FIELD32(0x00010000)
+#define RXD_W0_PLCP_RSSI		FIELD32(0x00020000)
+#define RXD_W0_CIPHER_ALG		FIELD32(0x00040000)
+#define RXD_W0_LAST_AMSDU		FIELD32(0x00080000)
+#define RXD_W0_PLCP_SIGNAL		FIELD32(0xfff00000)
+
+/*
+ * RX WI structure
+ */
+
+/*
+ * Word0
+ */
+#define RXWI_W0_WIRELESS_CLI_ID		FIELD32(0x000000ff)
+#define RXWI_W0_KEY_INDEX		FIELD32(0x00000300)
+#define RXWI_W0_BSSID			FIELD32(0x00001c00)
+#define RXWI_W0_UDF			FIELD32(0x0000e000)
+#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT	FIELD32(0x0fff0000)
+#define RXWI_W0_TID			FIELD32(0xf0000000)
+
+/*
+ * Word1
+ */
+#define RXWI_W1_FRAG			FIELD32(0x0000000f)
+#define RXWI_W1_SEQUENCE		FIELD32(0x0000fff0)
+#define RXWI_W1_MCS			FIELD32(0x007f0000)
+#define RXWI_W1_BW			FIELD32(0x00800000)
+#define RXWI_W1_SHORT_GI		FIELD32(0x01000000)
+#define RXWI_W1_STBC			FIELD32(0x06000000)
+#define RXWI_W1_PHYMODE			FIELD32(0xc0000000)
+
+/*
+ * Word2
+ */
+#define RXWI_W2_RSSI0			FIELD32(0x000000ff)
+#define RXWI_W2_RSSI1			FIELD32(0x0000ff00)
+#define RXWI_W2_RSSI2			FIELD32(0x00ff0000)
+
+/*
+ * Word3
+ */
+#define RXWI_W3_SNR0			FIELD32(0x000000ff)
+#define RXWI_W3_SNR1			FIELD32(0x0000ff00)
+
+/*
+ * Macro's for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ */
+#define MIN_G_TXPOWER	0
+#define MIN_A_TXPOWER	-7
+#define MAX_G_TXPOWER	31
+#define MAX_A_TXPOWER	15
+#define DEFAULT_TXPOWER	5
+
+#define TXPOWER_G_FROM_DEV(__txpower) \
+	((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_G_TO_DEV(__txpower) \
+	clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER)
+
+#define TXPOWER_A_FROM_DEV(__txpower) \
+	((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_A_TO_DEV(__txpower) \
+	clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
+
+#endif /* RT2800USB_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00config.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00config.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00config.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00config.c	2009-09-09 18:13:59.000000000 -0400
@@ -106,6 +106,10 @@
 	}
 
 	erp.basic_rates = bss_conf->basic_rates;
+	erp.beacon_int = bss_conf->beacon_int;
+
+	/* Update global beacon interval time, this is needed for PS support */
+	rt2x00dev->beacon_int = bss_conf->beacon_int;
 
 	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
 }
@@ -173,6 +177,11 @@
 	libconf.conf = conf;
 
 	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
+		if (conf_is_ht40(conf))
+			__set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+		else
+			__clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+
 		memcpy(&libconf.rf,
 		       &rt2x00dev->spec.channels[conf->channel->hw_value],
 		       sizeof(libconf.rf));
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c	2009-09-09 18:13:59.000000000 -0400
@@ -33,7 +33,7 @@
 {
 	switch (key->alg) {
 	case ALG_WEP:
-		if (key->keylen == LEN_WEP40)
+		if (key->keylen == WLAN_KEY_LEN_WEP40)
 			return CIPHER_WEP64;
 		else
 			return CIPHER_WEP128;
@@ -65,7 +65,8 @@
 		__set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
 
 	txdesc->key_idx = hw_key->hw_key_idx;
-	txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb);
+	txdesc->iv_offset = txdesc->header_length;
+	txdesc->iv_len = hw_key->iv_len;
 
 	if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
 		__set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
@@ -103,47 +104,44 @@
 	return overhead;
 }
 
-void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len)
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
 {
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
 
-	if (unlikely(!iv_len))
+	if (unlikely(!txdesc->iv_len))
 		return;
 
 	/* Copy IV/EIV data */
-	memcpy(skbdesc->iv, skb->data + header_length, iv_len);
+	memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
 }
 
-void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len)
+void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
 {
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
 
-	if (unlikely(!iv_len))
+	if (unlikely(!txdesc->iv_len))
 		return;
 
 	/* Copy IV/EIV data */
-	memcpy(skbdesc->iv, skb->data + header_length, iv_len);
+	memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
 
 	/* Move ieee80211 header */
-	memmove(skb->data + iv_len, skb->data, header_length);
+	memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset);
 
 	/* Pull buffer to correct size */
-	skb_pull(skb, iv_len);
+	skb_pull(skb, txdesc->iv_len);
 
 	/* IV/EIV data has officially be stripped */
-	skbdesc->flags |= FRAME_DESC_IV_STRIPPED;
+	skbdesc->flags |= SKBDESC_IV_STRIPPED;
 }
 
-void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
+void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
 {
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-	unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
 	const unsigned int iv_len =
 	    ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
 
-	if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED))
+	if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
 		return;
 
 	skb_push(skb, iv_len);
@@ -155,14 +153,15 @@
 	memcpy(skb->data + header_length, skbdesc->iv, iv_len);
 
 	/* IV/EIV data has returned into the frame */
-	skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED;
+	skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
 }
 
-void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
+void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
 			       unsigned int header_length,
 			       struct rxdone_entry_desc *rxdesc)
 {
 	unsigned int payload_len = rxdesc->size - header_length;
+	unsigned int align = ALIGN_SIZE(skb, header_length);
 	unsigned int iv_len;
 	unsigned int icv_len;
 	unsigned int transfer = 0;
@@ -192,32 +191,48 @@
 	}
 
 	/*
-	 * Make room for new data, note that we increase both
-	 * headsize and tailsize when required. The tailsize is
-	 * only needed when ICV data needs to be inserted and
-	 * the padding is smaller than the ICV data.
-	 * When alignment requirements is greater than the
-	 * ICV data we must trim the skb to the correct size
-	 * because we need to remove the extra bytes.
+	 * Make room for new data. There are 2 possibilities
+	 * either the alignment is already present between
+	 * the 802.11 header and payload. In that case we
+	 * we have to move the header less then the iv_len
+	 * since we can use the already available l2pad bytes
+	 * for the iv data.
+	 * When the alignment must be added manually we must
+	 * move the header more then iv_len since we must
+	 * make room for the payload move as well.
 	 */
-	skb_push(skb, iv_len + align);
-	if (align < icv_len)
-		skb_put(skb, icv_len - align);
-	else if (align > icv_len)
-		skb_trim(skb, rxdesc->size + iv_len + icv_len);
+	if (l2pad) {
+		skb_push(skb, iv_len - align);
+		skb_put(skb, icv_len);
 
-	/* Move ieee80211 header */
-	memmove(skb->data + transfer,
-		skb->data + transfer + iv_len + align,
-		header_length);
-	transfer += header_length;
+		/* Move ieee80211 header */
+		memmove(skb->data + transfer,
+			skb->data + transfer + (iv_len - align),
+			header_length);
+		transfer += header_length;
+	} else {
+		skb_push(skb, iv_len + align);
+		if (align < icv_len)
+			skb_put(skb, icv_len - align);
+		else if (align > icv_len)
+			skb_trim(skb, rxdesc->size + iv_len + icv_len);
+
+		/* Move ieee80211 header */
+		memmove(skb->data + transfer,
+			skb->data + transfer + iv_len + align,
+			header_length);
+		transfer += header_length;
+	}
 
 	/* Copy IV/EIV data */
 	memcpy(skb->data + transfer, rxdesc->iv, iv_len);
 	transfer += iv_len;
 
-	/* Move payload */
-	if (align) {
+	/*
+	 * Move payload for alignment purposes. Note that
+	 * this is only needed when no l2 padding is present.
+	 */
+	if (!l2pad) {
 		memmove(skb->data + transfer,
 			skb->data + transfer + align,
 			payload_len);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2009-09-09 18:13:59.000000000 -0400
@@ -227,6 +227,7 @@
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 	enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
+	unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
 	u8 rate_idx, rate_flags;
 
 	/*
@@ -235,13 +236,19 @@
 	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
 
 	/*
+	 * Remove L2 padding which was added during
+	 */
+	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+		rt2x00queue_payload_align(entry->skb, true, header_length);
+
+	/*
 	 * If the IV/EIV data was stripped from the frame before it was
 	 * passed to the hardware, we should now reinsert it again because
 	 * mac80211 will expect the the same data to be present it the
 	 * frame as it was passed to us.
 	 */
 	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
-		rt2x00crypto_tx_insert_iv(entry->skb);
+		rt2x00crypto_tx_insert_iv(entry->skb, header_length);
 
 	/*
 	 * Send frame to debugfs immediately, after this call is completed
@@ -253,7 +260,8 @@
 	 * Update TX statistics.
 	 */
 	rt2x00dev->link.qual.tx_success +=
-	    test_bit(TXDONE_SUCCESS, &txdesc->flags);
+	    test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
+	    test_bit(TXDONE_UNKNOWN, &txdesc->flags);
 	rt2x00dev->link.qual.tx_failed +=
 	    test_bit(TXDONE_FAILURE, &txdesc->flags);
 
@@ -271,14 +279,16 @@
 	tx_info->status.rates[1].idx = -1; /* terminate */
 
 	if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-		if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
+		if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
+				test_bit(TXDONE_UNKNOWN, &txdesc->flags))
 			tx_info->flags |= IEEE80211_TX_STAT_ACK;
 		else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
 	}
 
 	if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-		if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
+		if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
+				test_bit(TXDONE_UNKNOWN, &txdesc->flags))
 			rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
 		else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
 			rt2x00dev->low_level_stats.dot11RTSFailureCount++;
@@ -316,19 +326,54 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
 
+static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
+					struct rxdone_entry_desc *rxdesc)
+{
+	struct ieee80211_supported_band *sband;
+	const struct rt2x00_rate *rate;
+	unsigned int i;
+	int signal;
+	int type;
+
+	/*
+	 * For non-HT rates the MCS value needs to contain the
+	 * actually used rate modulation (CCK or OFDM).
+	 */
+	if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
+		signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal);
+	else
+		signal = rxdesc->signal;
+
+	type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
+
+	sband = &rt2x00dev->bands[rt2x00dev->curr_band];
+	for (i = 0; i < sband->n_bitrates; i++) {
+		rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
+
+		if (((type == RXDONE_SIGNAL_PLCP) &&
+		     (rate->plcp == signal)) ||
+		    ((type == RXDONE_SIGNAL_BITRATE) &&
+		      (rate->bitrate == signal)) ||
+		    ((type == RXDONE_SIGNAL_MCS) &&
+		      (rate->mcs == signal))) {
+			return i;
+		}
+	}
+
+	WARNING(rt2x00dev, "Frame received with unrecognized signal, "
+		"signal=0x%.4x, type=%d.\n", signal, type);
+	return 0;
+}
+
 void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 		      struct queue_entry *entry)
 {
 	struct rxdone_entry_desc rxdesc;
 	struct sk_buff *skb;
 	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
-	struct ieee80211_supported_band *sband;
-	const struct rt2x00_rate *rate;
 	unsigned int header_length;
-	unsigned int align;
-	unsigned int i;
-	int idx = -1;
-
+	bool l2pad;
+	int rate_idx;
 	/*
 	 * Allocate a new sk_buffer. If no new buffer available, drop the
 	 * received frame and reuse the existing buffer.
@@ -348,12 +393,15 @@
 	memset(&rxdesc, 0, sizeof(rxdesc));
 	rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
 
+	/* Trim buffer to correct size */
+	skb_trim(entry->skb, rxdesc.size);
+
 	/*
 	 * The data behind the ieee80211 header must be
 	 * aligned on a 4 byte boundary.
 	 */
 	header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
-	align = ((unsigned long)(entry->skb->data + header_length)) & 3;
+	l2pad = !!(rxdesc.dev_flags & RXDONE_L2PAD);
 
 	/*
 	 * Hardware might have stripped the IV/EIV/ICV data,
@@ -362,40 +410,24 @@
 	 * in which case we should reinsert the data into the frame.
 	 */
 	if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
-	    (rxdesc.flags & RX_FLAG_IV_STRIPPED)) {
-		rt2x00crypto_rx_insert_iv(entry->skb, align,
-					  header_length, &rxdesc);
-	} else if (align) {
-		skb_push(entry->skb, align);
-		/* Move entire frame in 1 command */
-		memmove(entry->skb->data, entry->skb->data + align,
-			rxdesc.size);
-	}
-
-	/* Update data pointers, trim buffer to correct size */
-	skb_trim(entry->skb, rxdesc.size);
+	    (rxdesc.flags & RX_FLAG_IV_STRIPPED))
+		rt2x00crypto_rx_insert_iv(entry->skb, l2pad, header_length,
+					  &rxdesc);
+	else
+		rt2x00queue_payload_align(entry->skb, l2pad, header_length);
 
 	/*
-	 * Update RX statistics.
+	 * Check if the frame was received using HT. In that case,
+	 * the rate is the MCS index and should be passed to mac80211
+	 * directly. Otherwise we need to translate the signal to
+	 * the correct bitrate index.
 	 */
-	sband = &rt2x00dev->bands[rt2x00dev->curr_band];
-	for (i = 0; i < sband->n_bitrates; i++) {
-		rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
-
-		if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
-		     (rate->plcp == rxdesc.signal)) ||
-		    ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) &&
-		      (rate->bitrate == rxdesc.signal))) {
-			idx = i;
-			break;
-		}
-	}
-
-	if (idx < 0) {
-		WARNING(rt2x00dev, "Frame received with unrecognized signal,"
-			"signal=0x%.2x, type=%d.\n", rxdesc.signal,
-			(rxdesc.dev_flags & RXDONE_SIGNAL_MASK));
-		idx = 0;
+	if (rxdesc.rate_mode == RATE_MODE_CCK ||
+	    rxdesc.rate_mode == RATE_MODE_OFDM) {
+		rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
+	} else {
+		rxdesc.flags |= RX_FLAG_HT;
+		rate_idx = rxdesc.signal;
 	}
 
 	/*
@@ -405,7 +437,7 @@
 	rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
 
 	rx_status->mactime = rxdesc.timestamp;
-	rx_status->rate_idx = idx;
+	rx_status->rate_idx = rate_idx;
 	rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi);
 	rx_status->signal = rxdesc.rssi;
 	rx_status->noise = rxdesc.noise;
@@ -440,72 +472,84 @@
 		.bitrate = 10,
 		.ratemask = BIT(0),
 		.plcp = 0x00,
+		.mcs = RATE_MCS(RATE_MODE_CCK, 0),
 	},
 	{
 		.flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
 		.bitrate = 20,
 		.ratemask = BIT(1),
 		.plcp = 0x01,
+		.mcs = RATE_MCS(RATE_MODE_CCK, 1),
 	},
 	{
 		.flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
 		.bitrate = 55,
 		.ratemask = BIT(2),
 		.plcp = 0x02,
+		.mcs = RATE_MCS(RATE_MODE_CCK, 2),
 	},
 	{
 		.flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
 		.bitrate = 110,
 		.ratemask = BIT(3),
 		.plcp = 0x03,
+		.mcs = RATE_MCS(RATE_MODE_CCK, 3),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 60,
 		.ratemask = BIT(4),
 		.plcp = 0x0b,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 0),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 90,
 		.ratemask = BIT(5),
 		.plcp = 0x0f,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 1),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 120,
 		.ratemask = BIT(6),
 		.plcp = 0x0a,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 2),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 180,
 		.ratemask = BIT(7),
 		.plcp = 0x0e,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 3),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 240,
 		.ratemask = BIT(8),
 		.plcp = 0x09,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 4),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 360,
 		.ratemask = BIT(9),
 		.plcp = 0x0d,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 5),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 480,
 		.ratemask = BIT(10),
 		.plcp = 0x08,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 6),
 	},
 	{
 		.flags = DEV_RATE_OFDM,
 		.bitrate = 540,
 		.ratemask = BIT(11),
 		.plcp = 0x0c,
+		.mcs = RATE_MCS(RATE_MODE_OFDM, 7),
 	},
 };
 
@@ -581,6 +625,8 @@
 		rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
 		    &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
+		memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap,
+		       &spec->ht, sizeof(spec->ht));
 	}
 
 	/*
@@ -597,6 +643,8 @@
 		rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 		    &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
+		memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap,
+		       &spec->ht, sizeof(spec->ht));
 	}
 
 	return 0;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00.h linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00.h	2009-09-09 18:13:59.000000000 -0400
@@ -103,6 +103,15 @@
 #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate))
 
 /*
+ * Determine the alignment requirement,
+ * to make sure the 802.11 payload is padded to a 4-byte boundrary
+ * we must determine the address of the payload and calculate the
+ * amount of bytes needed to move the data.
+ */
+#define ALIGN_SIZE(__skb, __header) \
+	(  ((unsigned long)((__skb)->data + (__header))) & 3 )
+
+/*
  * Standard timing and size defines.
  * These values should follow the ieee80211 specifications.
  */
@@ -138,6 +147,7 @@
 #define RT2561		0x0302
 #define RT2661		0x0401
 #define RT2571		0x1300
+#define RT2870		0x1600
 
 	u16 rf;
 	u32 rev;
@@ -357,6 +367,7 @@
  *	for @tx_power_a, @tx_power_bg and @channels.
  * @channels: Device/chipset specific channel values (See &struct rf_channel).
  * @channels_info: Additional information for channels (See &struct channel_info).
+ * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
  */
 struct hw_mode_spec {
 	unsigned int supported_bands;
@@ -370,6 +381,8 @@
 	unsigned int num_channels;
 	const struct rf_channel *channels;
 	const struct channel_info *channels_info;
+
+	struct ieee80211_sta_ht_cap ht;
 };
 
 /*
@@ -404,6 +417,8 @@
 	short pifs;
 	short difs;
 	short eifs;
+
+	u16 beacon_int;
 };
 
 /*
@@ -590,6 +605,7 @@
 	DRIVER_REQUIRE_SCHEDULED,
 	DRIVER_REQUIRE_DMA,
 	DRIVER_REQUIRE_COPY_IV,
+	DRIVER_REQUIRE_L2PAD,
 
 	/*
 	 * Driver features
@@ -606,6 +622,7 @@
 	CONFIG_EXTERNAL_LNA_BG,
 	CONFIG_DOUBLE_ANTENNA,
 	CONFIG_DISABLE_LINK_TUNING,
+	CONFIG_CHANNEL_HT40,
 };
 
 /*
@@ -672,6 +689,12 @@
 	unsigned long flags;
 
 	/*
+	 * Device information, Bus IRQ and name (PCI, SoC)
+	 */
+	int irq;
+	const char *name;
+
+	/*
 	 * Chipset identification.
 	 */
 	struct rt2x00_chip chip;
@@ -772,6 +795,18 @@
 	u8 freq_offset;
 
 	/*
+	 * Calibration information (for rt2800usb & rt2800pci).
+	 * [0] -> BW20
+	 * [1] -> BW40
+	 */
+	u8 calibration[2];
+
+	/*
+	 * Beacon interval.
+	 */
+	u16 beacon_int;
+
+	/*
 	 * Low level statistics which will have
 	 * to be kept up to date while device is running.
 	 */
@@ -814,13 +849,15 @@
 static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
 				  const unsigned int word, u32 *data)
 {
-	*data = rt2x00dev->rf[word];
+	BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+	*data = rt2x00dev->rf[word - 1];
 }
 
 static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
 				   const unsigned int word, u32 data)
 {
-	rt2x00dev->rf[word] = data;
+	BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+	rt2x00dev->rf[word - 1] = data;
 }
 
 /*
@@ -860,6 +897,18 @@
 	rt2x00dev->chip.rev = rev;
 }
 
+static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev,
+				      const u16 rt)
+{
+	rt2x00dev->chip.rt = rt;
+}
+
+static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev,
+				      const u16 rf, const u32 rev)
+{
+	rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev);
+}
+
 static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
 {
 	return (chipset->rt == chip);
@@ -875,11 +924,10 @@
 	return chipset->rev;
 }
 
-static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset,
-				   const u32 rev)
+static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset,
+				    const u32 mask, const u32 rev)
 {
-	return (((chipset->rev & 0xffff0) == rev) &&
-		!!(chipset->rev & 0x0000f));
+	return ((chipset->rev & mask) == rev);
 }
 
 /**
@@ -925,9 +973,6 @@
 void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
 				struct ieee80211_if_init_conf *conf);
 int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
-int rt2x00mac_config_interface(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       struct ieee80211_if_conf *conf);
 void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
 				unsigned int changed_flags,
 				unsigned int *total_flags,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,69 @@
+/*
+	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.com>
+
+	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.
+ */
+
+/*
+	Module: rt2x00lib
+	Abstract: rt2x00 HT specific routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
+				   struct txentry_desc *txdesc,
+				   const struct rt2x00_rate *hwrate)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+
+	if (tx_info->control.sta)
+		txdesc->mpdu_density =
+		    tx_info->control.sta->ht_cap.ampdu_density;
+	else
+		txdesc->mpdu_density = 0;
+
+	txdesc->ba_size = 7;	/* FIXME: What value is needed? */
+	txdesc->stbc = 0;	/* FIXME: What value is needed? */
+
+	txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+	if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+		txdesc->mcs |= 0x08;
+
+	/*
+	 * Convert flags
+	 */
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
+
+	/*
+	 * Determine HT Mix/Greenfield rate mode
+	 */
+	if (txrate->flags & IEEE80211_TX_RC_MCS)
+		txdesc->rate_mode = RATE_MODE_HT_MIX;
+	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+		txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
+	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
+	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h	2009-09-09 18:13:59.000000000 -0400
@@ -32,8 +32,8 @@
  * Interval defines
  * Both the link tuner as the rfkill will be called once per second.
  */
-#define LINK_TUNE_INTERVAL	( round_jiffies_relative(HZ) )
-#define RFKILL_POLL_INTERVAL	( 1000 )
+#define LINK_TUNE_INTERVAL	round_jiffies_relative(HZ)
+#define RFKILL_POLL_INTERVAL	1000
 
 /*
  * rt2x00_rate: Per rate device information
@@ -48,6 +48,7 @@
 	unsigned short ratemask;
 
 	unsigned short plcp;
+	unsigned short mcs;
 };
 
 extern const struct rt2x00_rate rt2x00_supported_rates[12];
@@ -57,6 +58,14 @@
 	return &rt2x00_supported_rates[hw_value & 0xff];
 }
 
+#define RATE_MCS(__mode, __mcs) \
+	( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) )
+
+static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
+{
+	return (mcs_value & 0x00ff);
+}
+
 /*
  * Radio control handlers.
  */
@@ -113,6 +122,23 @@
 void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
 
 /**
+ * rt2x00queue_payload_align - Align 802.11 payload to 4-byte boundary
+ * @skb: The skb to align
+ * @l2pad: Should L2 padding be used
+ * @header_length: Length of 802.11 header
+ *
+ * This function prepares the @skb to be send to the device or mac80211.
+ * If @l2pad is set to true padding will occur between the 802.11 header
+ * and payload. Otherwise the padding will be done in front of the 802.11
+ * header.
+ * When @l2pad is set the function will check for the &SKBDESC_L2_PADDED
+ * flag in &skb_frame_desc. If that flag is set, the padding is removed
+ * and the flag cleared. Otherwise the padding is added and the flag is set.
+ */
+void rt2x00queue_payload_align(struct sk_buff *skb,
+			       bool l2pad, unsigned int header_length);
+
+/**
  * rt2x00queue_write_tx_frame - Write TX frame to hardware
  * @queue: Queue over which the frame should be send
  * @skb: The skb to send
@@ -235,7 +261,7 @@
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  *
  * Initialize work structure and all link tuning related
- * paramters. This will not start the link tuning process itself.
+ * parameters. This will not start the link tuning process itself.
  */
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
 
@@ -295,10 +321,12 @@
 				       struct txentry_desc *txdesc);
 unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
 				      struct sk_buff *skb);
-void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len);
-void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len);
-void rt2x00crypto_tx_insert_iv(struct sk_buff *skb);
-void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
+			     struct txentry_desc *txdesc);
+void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
+			       struct txentry_desc *txdesc);
+void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length);
+void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
 			       unsigned int header_length,
 			       struct rxdone_entry_desc *rxdesc);
 #else
@@ -319,21 +347,21 @@
 }
 
 static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
-					   unsigned int iv_len)
+					   struct txentry_desc *txdesc)
 {
 }
 
 static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
-					     unsigned int iv_len)
+					     struct txentry_desc *txdesc)
 {
 }
 
-static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
+static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb,
+					     unsigned int header_length)
 {
 }
 
-static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
-					     unsigned int align,
+static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
 					     unsigned int header_length,
 					     struct rxdone_entry_desc *rxdesc)
 {
@@ -341,6 +369,21 @@
 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
 
 /*
+ * HT handlers.
+ */
+#ifdef CONFIG_RT2X00_LIB_HT
+void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
+				   struct txentry_desc *txdesc,
+				   const struct rt2x00_rate *hwrate);
+#else
+static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
+						 struct txentry_desc *txdesc,
+						 const struct rt2x00_rate *hwrate)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_HT */
+
+/*
  * RFkill handlers.
  */
 #ifdef CONFIG_RT2X00_LIB_RFKILL
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00link.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00link.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00link.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00link.c	2009-09-09 18:13:59.000000000 -0400
@@ -387,7 +387,7 @@
 		rt2x00link_antenna_reset(rt2x00dev);
 }
 
-void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev)
+static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev)
 {
 	struct link_qual *qual = &rt2x00dev->link.qual;
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c	2009-09-09 18:13:59.000000000 -0400
@@ -390,56 +390,6 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_config);
 
-int rt2x00mac_config_interface(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       struct ieee80211_if_conf *conf)
-{
-	struct rt2x00_dev *rt2x00dev = hw->priv;
-	struct rt2x00_intf *intf = vif_to_intf(vif);
-	int update_bssid = 0;
-	int status = 0;
-
-	/*
-	 * Mac80211 might be calling this function while we are trying
-	 * to remove the device or perhaps suspending it.
-	 */
-	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-		return 0;
-
-	spin_lock(&intf->lock);
-
-	/*
-	 * conf->bssid can be NULL if coming from the internal
-	 * beacon update routine.
-	 */
-	if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
-		update_bssid = 1;
-		memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
-	}
-
-	spin_unlock(&intf->lock);
-
-	/*
-	 * Call rt2x00_config_intf() outside of the spinlock context since
-	 * the call will sleep for USB drivers. By using the ieee80211_if_conf
-	 * values as arguments we make keep access to rt2x00_intf thread safe
-	 * even without the lock.
-	 */
-	rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
-			      update_bssid ? conf->bssid : NULL);
-
-	/*
-	 * Update the beacon.
-	 */
-	if (conf->changed & (IEEE80211_IFCC_BEACON |
-			     IEEE80211_IFCC_BEACON_ENABLED))
-		status = rt2x00queue_update_beacon(rt2x00dev, vif,
-						   conf->enable_beacon);
-
-	return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
-
 void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
 				unsigned int changed_flags,
 				unsigned int *total_flags,
@@ -623,6 +573,44 @@
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct rt2x00_intf *intf = vif_to_intf(vif);
 	unsigned int delayed = 0;
+	int update_bssid = 0;
+
+	/*
+	 * Mac80211 might be calling this function while we are trying
+	 * to remove the device or perhaps suspending it.
+	 */
+	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+		return;
+
+	spin_lock(&intf->lock);
+
+	/*
+	 * conf->bssid can be NULL if coming from the internal
+	 * beacon update routine.
+	 */
+	if (changes & BSS_CHANGED_BSSID) {
+		update_bssid = 1;
+		memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN);
+	}
+
+	spin_unlock(&intf->lock);
+
+	/*
+	 * Call rt2x00_config_intf() outside of the spinlock context since
+	 * the call will sleep for USB drivers. By using the ieee80211_if_conf
+	 * values as arguments we make keep access to rt2x00_intf thread safe
+	 * even without the lock.
+	 */
+	if (changes & BSS_CHANGED_BSSID)
+		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
+				      update_bssid ? bss_conf->bssid : NULL);
+
+	/*
+	 * Update the beacon.
+	 */
+	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED))
+		rt2x00queue_update_beacon(rt2x00dev, vif,
+					  bss_conf->enable_beacon);
 
 	/*
 	 * When the association status has changed we must reset the link
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c	2009-09-09 18:13:59.000000000 -0400
@@ -170,7 +170,6 @@
 
 int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
 {
-	struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev);
 	struct data_queue *queue;
 	int status;
 
@@ -186,11 +185,11 @@
 	/*
 	 * Register interrupt handler.
 	 */
-	status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler,
-			     IRQF_SHARED, pci_name(pci_dev), rt2x00dev);
+	status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler,
+			     IRQF_SHARED, rt2x00dev->name, rt2x00dev);
 	if (status) {
 		ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
-		      pci_dev->irq, status);
+		      rt2x00dev->irq, status);
 		goto exit;
 	}
 
@@ -270,6 +269,7 @@
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
+	u16 chip;
 
 	retval = pci_request_regions(pci_dev, pci_name(pci_dev));
 	if (retval) {
@@ -307,6 +307,14 @@
 	rt2x00dev->dev = &pci_dev->dev;
 	rt2x00dev->ops = ops;
 	rt2x00dev->hw = hw;
+	rt2x00dev->irq = pci_dev->irq;
+	rt2x00dev->name = pci_name(pci_dev);
+
+	/*
+	 * Determine RT chipset by reading PCI header.
+	 */
+	pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
+	rt2x00_set_chip_rt(rt2x00dev, chip);
 
 	retval = rt2x00pci_alloc_reg(rt2x00dev);
 	if (retval)
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c	2009-09-09 18:13:59.000000000 -0400
@@ -148,6 +148,35 @@
 	dev_kfree_skb_any(skb);
 }
 
+void rt2x00queue_payload_align(struct sk_buff *skb,
+			       bool l2pad, unsigned int header_length)
+{
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+	unsigned int frame_length = skb->len;
+	unsigned int align = ALIGN_SIZE(skb, header_length);
+
+	if (!align)
+		return;
+
+	if (l2pad) {
+		if (skbdesc->flags & SKBDESC_L2_PADDED) {
+			/* Remove L2 padding */
+			memmove(skb->data + align, skb->data, header_length);
+			skb_pull(skb, align);
+			skbdesc->flags &= ~SKBDESC_L2_PADDED;
+		} else {
+			/* Add L2 padding */
+			skb_push(skb, align);
+			memmove(skb->data, skb->data + align, header_length);
+			skbdesc->flags |= SKBDESC_L2_PADDED;
+		}
+	} else {
+		/* Generic payload alignment to 4-byte boundary */
+		skb_push(skb, align);
+		memmove(skb->data, skb->data + align, frame_length);
+	}
+}
+
 static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
 						 struct txentry_desc *txdesc)
 {
@@ -259,6 +288,12 @@
 	txdesc->aifs = entry->queue->aifs;
 
 	/*
+	 * Header and alignment information.
+	 */
+	txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+	txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length);
+
+	/*
 	 * Check whether this frame is to be acked.
 	 */
 	if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
@@ -326,6 +361,7 @@
 	 * Apply TX descriptor handling by components
 	 */
 	rt2x00crypto_create_tx_descriptor(entry, txdesc);
+	rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
 	rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
 	rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
@@ -368,7 +404,6 @@
 	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
 	struct txentry_desc txdesc;
 	struct skb_frame_desc *skbdesc;
-	unsigned int iv_len = 0;
 	u8 rate_idx, rate_flags;
 
 	if (unlikely(rt2x00queue_full(queue)))
@@ -390,9 +425,6 @@
 	entry->skb = skb;
 	rt2x00queue_create_tx_descriptor(entry, &txdesc);
 
-	if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)
-		iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
-
 	/*
 	 * All information is retrieved from the skb->cb array,
 	 * now we should claim ownership of the driver part of that
@@ -415,11 +447,15 @@
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
 	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
 		if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
-			rt2x00crypto_tx_copy_iv(skb, iv_len);
+			rt2x00crypto_tx_copy_iv(skb, &txdesc);
 		else
-			rt2x00crypto_tx_remove_iv(skb, iv_len);
+			rt2x00crypto_tx_remove_iv(skb, &txdesc);
 	}
 
+	if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
+		rt2x00queue_payload_align(entry->skb, true,
+					  txdesc.header_length);
+
 	/*
 	 * It could be possible that the queue was corrupted and this
 	 * call failed. Since we always return NETDEV_TX_OK to mac80211,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h	2009-09-09 18:13:59.000000000 -0400
@@ -35,9 +35,12 @@
  * for USB devices this restriction does not apply, but the value of
  * 2432 makes sense since it is big enough to contain the maximum fragment
  * size according to the ieee802.11 specs.
+ * The aggregation size depends on support from the driver, but should
+ * be something around 3840 bytes.
  */
-#define DATA_FRAME_SIZE	2432
-#define MGMT_FRAME_SIZE	256
+#define DATA_FRAME_SIZE		2432
+#define MGMT_FRAME_SIZE		256
+#define AGGREGATION_SIZE	3840
 
 /**
  * DOC: Number of entries per queue
@@ -87,13 +90,16 @@
  *
  * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX
  * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX
- * @FRAME_DESC_IV_STRIPPED: Frame contained a IV/EIV provided by
+ * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by
  *	mac80211 but was stripped for processing by the driver.
+ * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment,
+ *	the padded bytes are located between header and payload.
  */
 enum skb_frame_desc_flags {
 	SKBDESC_DMA_MAPPED_RX = 1 << 0,
 	SKBDESC_DMA_MAPPED_TX = 1 << 1,
-	FRAME_DESC_IV_STRIPPED = 1 << 2,
+	SKBDESC_IV_STRIPPED = 1 << 2,
+	SKBDESC_L2_PADDED = 1 << 3
 };
 
 /**
@@ -145,16 +151,20 @@
  *
  * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
  * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
+ * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value.
  * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
  * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
  * @RXDONE_CRYPTO_ICV: Driver provided ICV data.
+ * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary.
  */
 enum rxdone_entry_desc_flags {
-	RXDONE_SIGNAL_PLCP = 1 << 0,
-	RXDONE_SIGNAL_BITRATE = 1 << 1,
-	RXDONE_MY_BSS = 1 << 2,
-	RXDONE_CRYPTO_IV = 1 << 3,
-	RXDONE_CRYPTO_ICV = 1 << 4,
+	RXDONE_SIGNAL_PLCP = BIT(0),
+	RXDONE_SIGNAL_BITRATE = BIT(1),
+	RXDONE_SIGNAL_MCS = BIT(2),
+	RXDONE_MY_BSS = BIT(3),
+	RXDONE_CRYPTO_IV = BIT(4),
+	RXDONE_CRYPTO_ICV = BIT(5),
+	RXDONE_L2PAD = BIT(6),
 };
 
 /**
@@ -163,7 +173,7 @@
  * from &rxdone_entry_desc to a signal value type.
  */
 #define RXDONE_SIGNAL_MASK \
-       ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE )
+	( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS )
 
 /**
  * struct rxdone_entry_desc: RX Entry descriptor
@@ -177,6 +187,7 @@
  * @size: Data size of the received frame.
  * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
  * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
+ * @rate_mode: Rate mode (See @enum rate_modulation).
  * @cipher: Cipher type used during decryption.
  * @cipher_status: Decryption status.
  * @iv: IV/EIV data used during decryption.
@@ -190,6 +201,7 @@
 	int size;
 	int flags;
 	int dev_flags;
+	u16 rate_mode;
 	u8 cipher;
 	u8 cipher_status;
 
@@ -243,6 +255,9 @@
  * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared).
  * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware.
  * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware.
+ * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU.
+ * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth.
+ * @ENTRY_TXD_HT_SHORT_GI: Use short GI.
  */
 enum txentry_desc_flags {
 	ENTRY_TXD_RTS_FRAME,
@@ -258,6 +273,9 @@
 	ENTRY_TXD_ENCRYPT_PAIRWISE,
 	ENTRY_TXD_ENCRYPT_IV,
 	ENTRY_TXD_ENCRYPT_MMIC,
+	ENTRY_TXD_HT_AMPDU,
+	ENTRY_TXD_HT_BW_40,
+	ENTRY_TXD_HT_SHORT_GI,
 };
 
 /**
@@ -267,11 +285,17 @@
  *
  * @flags: Descriptor flags (See &enum queue_entry_flags).
  * @queue: Queue identification (See &enum data_queue_qid).
+ * @header_length: Length of 802.11 header.
+ * @l2pad: Amount of padding to align 802.11 payload to 4-byte boundrary.
  * @length_high: PLCP length high word.
  * @length_low: PLCP length low word.
  * @signal: PLCP signal.
  * @service: PLCP service.
+ * @msc: MCS.
+ * @stbc: STBC.
+ * @ba_size: BA size.
  * @rate_mode: Rate mode (See @enum rate_modulation).
+ * @mpdu_density: MDPU density.
  * @retry_limit: Max number of retries.
  * @aifs: AIFS value.
  * @ifs: IFS value.
@@ -280,18 +304,26 @@
  * @cipher: Cipher type used for encryption.
  * @key_idx: Key index used for encryption.
  * @iv_offset: Position where IV should be inserted by hardware.
+ * @iv_len: Length of IV data.
  */
 struct txentry_desc {
 	unsigned long flags;
 
 	enum data_queue_qid queue;
 
+	u16 header_length;
+	u16 l2pad;
+
 	u16 length_high;
 	u16 length_low;
 	u16 signal;
 	u16 service;
 
+	u16 mcs;
+	u16 stbc;
+	u16 ba_size;
 	u16 rate_mode;
+	u16 mpdu_density;
 
 	short retry_limit;
 	short aifs;
@@ -302,6 +334,7 @@
 	enum cipher cipher;
 	u16 key_idx;
 	u16 iv_offset;
+	u16 iv_len;
 };
 
 /**
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt61pci.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt61pci.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt61pci.c	2012-03-22 19:18:05.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt61pci.c	2012-03-22 20:14:09.000000000 -0400
@@ -603,15 +603,22 @@
 
 	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
+	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 
 	rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
 	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
 			   !!erp->short_preamble);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
 
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
 
+	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+			   erp->beacon_int * 16);
+	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
 	rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
 	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
 	rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
@@ -938,25 +945,6 @@
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
 }
 
-static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
-				    struct rt2x00lib_conf *libconf)
-{
-	u32 reg;
-
-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
-
-	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-			   libconf->conf->beacon_int * 16);
-	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
-}
-
 static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
 				struct rt2x00lib_conf *libconf)
 {
@@ -968,7 +956,7 @@
 	if (state == STATE_SLEEP) {
 		rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
 		rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
-				   libconf->conf->beacon_int - 10);
+				   rt2x00dev->beacon_int - 10);
 		rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
 				   libconf->conf->listen_interval - 1);
 		rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
@@ -1016,8 +1004,6 @@
 		rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		rt61pci_config_retry_limit(rt2x00dev, libconf);
-	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
-		rt61pci_config_duration(rt2x00dev, libconf);
 	if (flags & IEEE80211_CONF_CHANGE_PS)
 		rt61pci_config_ps(rt2x00dev, libconf);
 }
@@ -2308,7 +2294,6 @@
 	u32 reg;
 	u16 value;
 	u16 eeprom;
-	u16 device;
 
 	/*
 	 * Read EEPROM word for configuration.
@@ -2317,14 +2302,10 @@
 
 	/*
 	 * Identify RF chipset.
-	 * To determine the RT chip we have to read the
-	 * PCI header of the device.
 	 */
-	pci_read_config_word(to_pci_dev(rt2x00dev->dev),
-			     PCI_CONFIG_HEADER_DEVICE, &device);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
-	rt2x00_set_chip(rt2x00dev, device, value, reg);
+	rt2x00_set_chip_rf(rt2x00dev, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
@@ -2740,7 +2721,6 @@
 	.add_interface		= rt2x00mac_add_interface,
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
-	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
 	.set_key		= rt2x00mac_set_key,
 	.get_stats		= rt2x00mac_get_stats,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt61pci.h linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt61pci.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt61pci.h	2012-03-22 19:18:00.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt61pci.h	2012-03-22 20:14:05.000000000 -0400
@@ -63,12 +63,6 @@
  */
 
 /*
- * PCI Configuration Header
- */
-#define PCI_CONFIG_HEADER_VENDOR	0x0000
-#define PCI_CONFIG_HEADER_DEVICE	0x0002
-
-/*
  * HOST_CMD_CSR: For HOST to interrupt embedded processor
  */
 #define HOST_CMD_CSR			0x0008
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt73usb.c linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt73usb.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rt2x00/rt73usb.c	2012-03-22 19:18:13.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rt2x00/rt73usb.c	2012-03-22 20:14:14.000000000 -0400
@@ -566,15 +566,22 @@
 
 	rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
+	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
 	rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
 	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
 			   !!erp->short_preamble);
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
 
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
 
+	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+			   erp->beacon_int * 16);
+	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
 	rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
 	rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
 	rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
@@ -834,25 +841,6 @@
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
 }
 
-static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
-				    struct rt2x00lib_conf *libconf)
-{
-	u32 reg;
-
-	rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-	rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-	rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-
-	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-			   libconf->conf->beacon_int * 16);
-	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-}
-
 static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
 				struct rt2x00lib_conf *libconf)
 {
@@ -864,7 +852,7 @@
 	if (state == STATE_SLEEP) {
 		rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
 		rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
-				   libconf->conf->beacon_int - 10);
+				   rt2x00dev->beacon_int - 10);
 		rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
 				   libconf->conf->listen_interval - 1);
 		rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
@@ -906,8 +894,6 @@
 		rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		rt73usb_config_retry_limit(rt2x00dev, libconf);
-	if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
-		rt73usb_config_duration(rt2x00dev, libconf);
 	if (flags & IEEE80211_CONF_CHANGE_PS)
 		rt73usb_config_ps(rt2x00dev, libconf);
 }
@@ -1846,7 +1832,8 @@
 	rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
 
-	if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) {
+	if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
+	    rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
 		ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
 		return -ENODEV;
 	}
@@ -2259,7 +2246,6 @@
 	.add_interface		= rt2x00mac_add_interface,
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
-	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
 	.set_key		= rt2x00mac_set_key,
 	.get_stats		= rt2x00mac_get_stats,
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/Makefile linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/Makefile
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/Makefile	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/Makefile	2009-09-09 18:13:59.000000000 -0400
@@ -1,5 +1,5 @@
 rtl8180-objs		:= rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
-rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o
+rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o
 
 obj-$(CONFIG_RTL8180)	+= rtl8180.o
 obj-$(CONFIG_RTL8187)	+= rtl8187.o
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8180_dev.c linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8180_dev.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8180_dev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8180_dev.c	2009-09-09 18:13:59.000000000 -0400
@@ -702,30 +702,26 @@
 	return 0;
 }
 
-static int rtl8180_config_interface(struct ieee80211_hw *dev,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_if_conf *conf)
-{
-	struct rtl8180_priv *priv = dev->priv;
-	int i;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
-
-	if (is_valid_ether_addr(conf->bssid))
-		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
-	else
-		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
-
-	return 0;
-}
-
 static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *info,
 				     u32 changed)
 {
 	struct rtl8180_priv *priv = dev->priv;
+	int i;
+
+	if (changed & BSS_CHANGED_BSSID) {
+		for (i = 0; i < ETH_ALEN; i++)
+			rtl818x_iowrite8(priv, &priv->map->BSSID[i],
+					 info->bssid[i]);
+
+		if (is_valid_ether_addr(info->bssid))
+			rtl818x_iowrite8(priv, &priv->map->MSR,
+					 RTL818X_MSR_INFRA);
+		else
+			rtl818x_iowrite8(priv, &priv->map->MSR,
+					 RTL818X_MSR_NO_LINK);
+	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
 	        priv->rf->conf_erp(dev, info);
@@ -770,7 +766,6 @@
 	.add_interface		= rtl8180_add_interface,
 	.remove_interface	= rtl8180_remove_interface,
 	.config			= rtl8180_config,
-	.config_interface	= rtl8180_config_interface,
 	.bss_info_changed	= rtl8180_bss_info_changed,
 	.configure_filter	= rtl8180_configure_filter,
 };
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187_dev.c linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187_dev.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187_dev.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187_dev.c	2009-09-09 18:13:59.000000000 -0400
@@ -29,6 +29,9 @@
 
 #include "rtl8187.h"
 #include "rtl8187_rtl8225.h"
+#ifdef CONFIG_RTL8187_LEDS
+#include "rtl8187_leds.h"
+#endif
 
 MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
 MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
@@ -320,12 +323,7 @@
 	unsigned long f;
 
 	spin_lock_irqsave(&priv->rx_queue.lock, f);
-	if (skb->next)
-		__skb_unlink(skb, &priv->rx_queue);
-	else {
-		spin_unlock_irqrestore(&priv->rx_queue.lock, f);
-		return;
-	}
+	__skb_unlink(skb, &priv->rx_queue);
 	spin_unlock_irqrestore(&priv->rx_queue.lock, f);
 	skb_put(skb, urb->actual_length);
 
@@ -736,10 +734,10 @@
 	{0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0},
 	{0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0},
 	{0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0},
-	{0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0},
+	{0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2},
 
-	{0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0},
-	{0x8E, 0x08, 0}, {0x8F, 0x00, 0}
+	{0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0},
+	{0x8F, 0x00, 0}
 };
 
 static int rtl8187b_init_hw(struct ieee80211_hw *dev)
@@ -871,6 +869,9 @@
 	priv->aifsn[3] = 3; /* AIFSN[AC_BE] */
 	rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
 
+	/* ENEDCA flag must always be set, transmit issues? */
+	rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA);
+
 	return 0;
 }
 
@@ -1089,32 +1090,6 @@
 	return 0;
 }
 
-static int rtl8187_config_interface(struct ieee80211_hw *dev,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_if_conf *conf)
-{
-	struct rtl8187_priv *priv = dev->priv;
-	int i;
-	u8 reg;
-
-	mutex_lock(&priv->conf_mutex);
-	for (i = 0; i < ETH_ALEN; i++)
-		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
-
-	if (is_valid_ether_addr(conf->bssid)) {
-		reg = RTL818X_MSR_INFRA;
-		if (priv->is_rtl8187b)
-			reg |= RTL818X_MSR_ENEDCA;
-		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-	} else {
-		reg = RTL818X_MSR_NO_LINK;
-		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
-	}
-
-	mutex_unlock(&priv->conf_mutex);
-	return 0;
-}
-
 /*
  * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for
  * example. Thus we have to use raw values for AC_*_PARAM register addresses.
@@ -1192,6 +1167,30 @@
 				     u32 changed)
 {
 	struct rtl8187_priv *priv = dev->priv;
+	int i;
+	u8 reg;
+
+	if (changed & BSS_CHANGED_BSSID) {
+		mutex_lock(&priv->conf_mutex);
+		for (i = 0; i < ETH_ALEN; i++)
+			rtl818x_iowrite8(priv, &priv->map->BSSID[i],
+					 info->bssid[i]);
+
+		if (priv->is_rtl8187b)
+			reg = RTL818X_MSR_ENEDCA;
+		else
+			reg = 0;
+
+		if (is_valid_ether_addr(info->bssid)) {
+			reg |= RTL818X_MSR_INFRA;
+			rtl818x_iowrite8(priv, &priv->map->MSR, reg);
+		} else {
+			reg |= RTL818X_MSR_NO_LINK;
+			rtl818x_iowrite8(priv, &priv->map->MSR, reg);
+		}
+
+		mutex_unlock(&priv->conf_mutex);
+	}
 
 	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
 		rtl8187_conf_erp(priv, info->use_short_slot,
@@ -1273,7 +1272,6 @@
 	.add_interface		= rtl8187_add_interface,
 	.remove_interface	= rtl8187_remove_interface,
 	.config			= rtl8187_config,
-	.config_interface	= rtl8187_config_interface,
 	.bss_info_changed	= rtl8187_bss_info_changed,
 	.configure_filter	= rtl8187_configure_filter,
 	.conf_tx		= rtl8187_conf_tx
@@ -1480,9 +1478,6 @@
 		(*channel++).hw_value = txpwr >> 8;
 	}
 
-	if (priv->is_rtl8187b)
-		printk(KERN_WARNING "rtl8187: 8187B chip detected.\n");
-
 	/*
 	 * XXX: Once this driver supports anything that requires
 	 *	beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ.
@@ -1514,6 +1509,12 @@
 	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
 	       chip_name, priv->asic_rev, priv->rf->name);
 
+#ifdef CONFIG_RTL8187_LEDS
+	eeprom_93cx6_read(&eeprom, 0x3F, &reg);
+	reg &= 0xFF;
+	rtl8187_leds_init(dev, reg);
+#endif
+
 	return 0;
 
  err_free_dmabuf:
@@ -1533,6 +1534,9 @@
 	if (!dev)
 		return;
 
+#ifdef CONFIG_RTL8187_LEDS
+	rtl8187_leds_exit(dev);
+#endif
 	ieee80211_unregister_hw(dev);
 
 	priv = dev->priv;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187.h linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187.h	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187.h	2009-09-09 18:13:59.000000000 -0400
@@ -16,6 +16,7 @@
 #define RTL8187_H
 
 #include "rtl818x.h"
+#include "rtl8187_leds.h"
 
 #define RTL8187_EEPROM_TXPWR_BASE	0x05
 #define RTL8187_EEPROM_MAC_ADDR		0x07
@@ -102,6 +103,12 @@
 	struct usb_anchor anchored;
 	struct delayed_work work;
 	struct ieee80211_hw *dev;
+#ifdef CONFIG_RTL8187_LEDS
+	struct rtl8187_led led_tx;
+	struct rtl8187_led led_rx;
+	struct delayed_work led_on;
+	struct delayed_work led_off;
+#endif
 	u16 txpwr_base;
 	u8 asic_rev;
 	u8 is_rtl8187b;
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.c linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,219 @@
+/*
+ * Linux LED driver for RTL8187
+ *
+ * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Based on the LED handling in the r8187 driver, which is:
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * 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.
+ */
+
+#ifdef CONFIG_RTL8187_LEDS
+
+#include <net/mac80211.h>
+#include <linux/usb.h>
+#include <linux/eeprom_93cx6.h>
+
+#include "rtl8187.h"
+#include "rtl8187_leds.h"
+
+static void led_turn_on(struct work_struct *work)
+{
+	/* As this routine does read/write operations on the hardware, it must
+	 * be run from a work queue.
+	 */
+	u8 reg;
+	struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
+				    led_on.work);
+	struct rtl8187_led *led = &priv->led_tx;
+
+	/* Don't change the LED, when the device is down. */
+	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+		return ;
+
+	/* Skip if the LED is not registered. */
+	if (!led->dev)
+		return;
+	mutex_lock(&priv->conf_mutex);
+	switch (led->ledpin) {
+	case LED_PIN_GPIO0:
+		rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
+		rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00);
+		break;
+	case LED_PIN_LED0:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_LED1:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_HW:
+	default:
+		break;
+	}
+	mutex_unlock(&priv->conf_mutex);
+}
+
+static void led_turn_off(struct work_struct *work)
+{
+	/* As this routine does read/write operations on the hardware, it must
+	 * be run from a work queue.
+	 */
+	u8 reg;
+	struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
+				    led_off.work);
+	struct rtl8187_led *led = &priv->led_tx;
+
+	/* Don't change the LED, when the device is down. */
+	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+		return ;
+
+	/* Skip if the LED is not registered. */
+	if (!led->dev)
+		return;
+	mutex_lock(&priv->conf_mutex);
+	switch (led->ledpin) {
+	case LED_PIN_GPIO0:
+		rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
+		rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01);
+		break;
+	case LED_PIN_LED0:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_LED1:
+		reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5);
+		rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+		break;
+	case LED_PIN_HW:
+	default:
+		break;
+	}
+	mutex_unlock(&priv->conf_mutex);
+}
+
+/* Callback from the LED subsystem. */
+static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
+				   enum led_brightness brightness)
+{
+	struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
+					       led_dev);
+	struct ieee80211_hw *hw = led->dev;
+	struct rtl8187_priv *priv = hw->priv;
+
+	if (brightness == LED_OFF) {
+		queue_delayed_work(hw->workqueue, &priv->led_off, 0);
+		/* The LED is off for 1/20 sec so that it just blinks. */
+		queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20);
+	} else
+		queue_delayed_work(hw->workqueue, &priv->led_on, 0);
+}
+
+static int rtl8187_register_led(struct ieee80211_hw *dev,
+				struct rtl8187_led *led, const char *name,
+				const char *default_trigger, u8 ledpin)
+{
+	int err;
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (led->dev)
+		return -EEXIST;
+	if (!default_trigger)
+		return -EINVAL;
+	led->dev = dev;
+	led->ledpin = ledpin;
+	strncpy(led->name, name, sizeof(led->name));
+
+	led->led_dev.name = led->name;
+	led->led_dev.default_trigger = default_trigger;
+	led->led_dev.brightness_set = rtl8187_led_brightness_set;
+
+	err = led_classdev_register(&priv->udev->dev, &led->led_dev);
+	if (err) {
+		printk(KERN_INFO "LEDs: Failed to register %s\n", name);
+		led->dev = NULL;
+		return err;
+	}
+	return 0;
+}
+
+static void rtl8187_unregister_led(struct rtl8187_led *led)
+{
+	led_classdev_unregister(&led->led_dev);
+	led->dev = NULL;
+}
+
+void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	char name[RTL8187_LED_MAX_NAME_LEN + 1];
+	u8 ledpin;
+	int err;
+
+	/* According to the vendor driver, the LED operation depends on the
+	 * customer ID encoded in the EEPROM
+	 */
+	printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid);
+	switch (custid) {
+	case EEPROM_CID_RSVD0:
+	case EEPROM_CID_RSVD1:
+	case EEPROM_CID_SERCOMM_PS:
+	case EEPROM_CID_QMI:
+	case EEPROM_CID_DELL:
+	case EEPROM_CID_TOSHIBA:
+		ledpin = LED_PIN_GPIO0;
+		break;
+	case EEPROM_CID_ALPHA0:
+		ledpin = LED_PIN_LED0;
+		break;
+	case EEPROM_CID_HW:
+		ledpin = LED_PIN_HW;
+		break;
+	default:
+		ledpin = LED_PIN_GPIO0;
+	}
+
+	INIT_DELAYED_WORK(&priv->led_on, led_turn_on);
+	INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
+
+	snprintf(name, sizeof(name),
+		 "rtl8187-%s::tx", wiphy_name(dev->wiphy));
+	err = rtl8187_register_led(dev, &priv->led_tx, name,
+			 ieee80211_get_tx_led_name(dev), ledpin);
+	if (err)
+		goto error;
+	snprintf(name, sizeof(name),
+		 "rtl8187-%s::rx", wiphy_name(dev->wiphy));
+	err = rtl8187_register_led(dev, &priv->led_rx, name,
+			 ieee80211_get_rx_led_name(dev), ledpin);
+	if (!err) {
+		queue_delayed_work(dev->workqueue, &priv->led_on, 0);
+		return;
+	}
+	/* registration of RX LED failed - unregister TX */
+	rtl8187_unregister_led(&priv->led_tx);
+error:
+	/* If registration of either failed, cancel delayed work */
+	cancel_delayed_work_sync(&priv->led_off);
+	cancel_delayed_work_sync(&priv->led_on);
+}
+
+void rtl8187_leds_exit(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	/* turn the LED off before exiting */
+	queue_delayed_work(dev->workqueue, &priv->led_off, 0);
+	cancel_delayed_work_sync(&priv->led_off);
+	cancel_delayed_work_sync(&priv->led_on);
+	rtl8187_unregister_led(&priv->led_rx);
+	rtl8187_unregister_led(&priv->led_tx);
+}
+#endif /* def CONFIG_RTL8187_LED */
+
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.h linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/rtl818x/rtl8187_leds.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * Definitions for RTL8187 leds
+ *
+ * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ * Based on the LED handling in the r8187 driver, which is:
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ *
+ * 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.
+ */
+
+#ifndef RTL8187_LED_H
+#define RTL8187_LED_H
+
+#ifdef CONFIG_RTL8187_LEDS
+
+#define RTL8187_LED_MAX_NAME_LEN	21
+
+#include <linux/leds.h>
+#include <linux/types.h>
+
+enum {
+	LED_PIN_LED0,
+	LED_PIN_LED1,
+	LED_PIN_GPIO0,
+	LED_PIN_HW
+};
+
+enum {
+	EEPROM_CID_RSVD0 = 0x00,
+	EEPROM_CID_RSVD1 = 0xFF,
+	EEPROM_CID_ALPHA0 = 0x01,
+	EEPROM_CID_SERCOMM_PS = 0x02,
+	EEPROM_CID_HW = 0x03,
+	EEPROM_CID_TOSHIBA = 0x04,
+	EEPROM_CID_QMI = 0x07,
+	EEPROM_CID_DELL = 0x08
+};
+
+struct rtl8187_led {
+	struct ieee80211_hw *dev;
+	/* The LED class device */
+	struct led_classdev led_dev;
+	/* The pin/method used to control the led */
+	u8 ledpin;
+	/* The unique name string for this LED device. */
+	char name[RTL8187_LED_MAX_NAME_LEN + 1];
+};
+
+void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);
+void rtl8187_leds_exit(struct ieee80211_hw *dev);
+
+#endif /* def CONFIG_RTL8187_LED */
+
+#endif /* RTL8187_LED_H */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/strip.c linux-libre-2.6.31-gnu/drivers/net/wireless/strip.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/strip.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/strip.c	2009-09-09 18:13:59.000000000 -0400
@@ -1540,7 +1540,7 @@
 	if (!netif_running(dev)) {
 		printk(KERN_ERR "%s: xmit call when iface is down\n",
 		       dev->name);
-		return (1);
+		return NETDEV_TX_BUSY;
 	}
 
 	netif_stop_queue(dev);
@@ -2509,7 +2509,7 @@
 	 *  netdev_priv(dev) Already holds a pointer to our struct strip
 	 */
 
-	*(MetricomAddress *) & dev->broadcast = broadcast_address;
+	*(MetricomAddress *)dev->broadcast = broadcast_address;
 	dev->dev_addr[0] = 0;
 	dev->addr_len = sizeof(MetricomAddress);
 
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/wavelan.c linux-libre-2.6.31-gnu/drivers/net/wireless/wavelan.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/wavelan.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/wavelan.c	2009-09-09 18:13:59.000000000 -0400
@@ -2867,12 +2867,8 @@
 		spin_unlock_irqrestore(&lp->spinlock, flags);
 		/* Check that we can continue */
 		if (lp->tx_n_in_use == (NTXBLOCKS - 1))
-			return 1;
+			return NETDEV_TX_BUSY;
 	}
-#ifdef DEBUG_TX_ERROR
-	if (skb->next)
-		printk(KERN_INFO "skb has next\n");
-#endif
 
 	/* Do we need some padding? */
 	/* Note : on wireless the propagation time is in the order of 1us,
@@ -2884,10 +2880,10 @@
 		skb_copy_from_linear_data(skb, data, skb->len);
 		/* Write packet on the card */
 		if(wv_packet_write(dev, data, ETH_ZLEN))
-			return 1;	/* We failed */
+			return NETDEV_TX_BUSY;	/* We failed */
 	}
 	else if(wv_packet_write(dev, skb->data, skb->len))
-		return 1;	/* We failed */
+		return NETDEV_TX_BUSY;	/* We failed */
 
 
 	dev_kfree_skb(skb);
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/wavelan_cs.c linux-libre-2.6.31-gnu/drivers/net/wireless/wavelan_cs.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/wavelan_cs.c	2009-06-09 23:05:27.000000000 -0400
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/wavelan_cs.c	2009-09-09 18:13:59.000000000 -0400
@@ -138,7 +138,7 @@
 
 /*------------------------------------------------------------------*/
 /*
- * Write the Paramter Storage Area to the WaveLAN card's memory
+ * Write the Parameter Storage Area to the WaveLAN card's memory
  */
 static void
 psa_write(struct net_device *	dev,
@@ -3107,11 +3107,6 @@
        * so the Tx buffer is now free */
     }
 
-#ifdef DEBUG_TX_ERROR
-	if (skb->next)
-		printk(KERN_INFO "skb has next\n");
-#endif
-
 	/* Check if we need some padding */
 	/* Note : on wireless the propagation time is in the order of 1us,
 	 * and we don't have the Ethernet specific requirement of beeing
@@ -3561,17 +3556,8 @@
   cfblk.rcvstop = TRUE; 	/* Enable Receive Stop Register */
 
 #ifdef DEBUG_I82593_SHOW
-  {
-    u_char *c = (u_char *) &cfblk;
-    int i;
-    printk(KERN_DEBUG "wavelan_cs: config block:");
-    for(i = 0; i < sizeof(struct i82593_conf_block); i++,c++)
-      {
-	if((i % 16) == 0) printk("\n" KERN_DEBUG);
-	printk("%02x ", *c);
-      }
-    printk("\n");
-  }
+  print_hex_dump(KERN_DEBUG, "wavelan_cs: config block: ", DUMP_PREFIX_NONE,
+		 16, 1, &cfblk, sizeof(struct i82593_conf_block), false);
 #endif
 
   /* Copy the config block to the i82593 */
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/wl12xx/acx.c linux-libre-2.6.31-gnu/drivers/net/wireless/wl12xx/acx.c
--- linux-libre-2.6.30-gnu/drivers/net/wireless/wl12xx/acx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/wl12xx/acx.c	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,689 @@
+#include "acx.h"
+
+#include <linux/module.h>
+#include <linux/crc7.h>
+#include <linux/spi/spi.h>
+
+#include "wl12xx.h"
+#include "wl12xx_80211.h"
+#include "reg.h"
+#include "spi.h"
+#include "ps.h"
+
+int wl12xx_acx_frame_rates(struct wl12xx *wl, u8 ctrl_rate, u8 ctrl_mod,
+			   u8 mgt_rate, u8 mgt_mod)
+{
+	int ret;
+	struct acx_fw_gen_frame_rates rates;
+
+	wl12xx_debug(DEBUG_ACX, "acx frame rates");
+
+	rates.header.id = ACX_FW_GEN_FRAME_RATES;
+	rates.header.len = sizeof(struct acx_fw_gen_frame_rates) -
+		sizeof(struct acx_header);
+
+	rates.tx_ctrl_frame_rate = ctrl_rate;
+	rates.tx_ctrl_frame_mod = ctrl_mod;
+	rates.tx_mgt_frame_rate = mgt_rate;
+	rates.tx_mgt_frame_mod = mgt_mod;
+
+	ret = wl12xx_cmd_configure(wl, &rates, sizeof(rates));
+	if (ret < 0) {
+		wl12xx_error("Failed to set FW rates and modulation");
+		return ret;
+	}
+
+	return 0;
+}
+
+
+int wl12xx_acx_station_id(struct wl12xx *wl)
+{
+	int ret, i;
+	struct dot11_station_id mac;
+
+	wl12xx_debug(DEBUG_ACX, "acx dot11_station_id");
+
+	mac.header.id = DOT11_STATION_ID;
+	mac.header.len = sizeof(mac) - sizeof(struct acx_header);
+
+	for (i = 0; i < ETH_ALEN; i++)
+		mac.mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
+
+	ret = wl12xx_cmd_configure(wl, &mac, sizeof(mac));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl12xx_acx_default_key(struct wl12xx *wl, u8 key_id)
+{
+	struct acx_dot11_default_key default_key;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
+
+	default_key.header.id = DOT11_DEFAULT_KEY;
+	default_key.header.len = sizeof(default_key) -
+		sizeof(struct acx_header);
+
+	default_key.id = key_id;
+
+	ret = wl12xx_cmd_configure(wl, &default_key, sizeof(default_key));
+	if (ret < 0) {
+		wl12xx_error("Couldnt set default key");
+		return ret;
+	}
+
+	wl->default_key = key_id;
+
+	return 0;
+}
+
+int wl12xx_acx_wake_up_conditions(struct wl12xx *wl, u8 listen_interval)
+{
+	struct acx_wake_up_condition wake_up;
+
+	wl12xx_debug(DEBUG_ACX, "acx wake up conditions");
+
+	wake_up.header.id = ACX_WAKE_UP_CONDITIONS;
+	wake_up.header.len = sizeof(wake_up) - sizeof(struct acx_header);
+
+	wake_up.wake_up_event = WAKE_UP_EVENT_DTIM_BITMAP;
+	wake_up.listen_interval = listen_interval;
+
+	return wl12xx_cmd_configure(wl, &wake_up, sizeof(wake_up));
+}
+
+int wl12xx_acx_sleep_auth(struct wl12xx *wl, u8 sleep_auth)
+{
+	int ret;
+	struct acx_sleep_auth auth;
+
+	wl12xx_debug(DEBUG_ACX, "acx sleep auth");
+
+	auth.header.id = ACX_SLEEP_AUTH;
+	auth.header.len = sizeof(auth) - sizeof(struct acx_header);
+
+	auth.sleep_auth = sleep_auth;
+
+	ret = wl12xx_cmd_configure(wl, &auth, sizeof(auth));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int wl12xx_acx_fw_version(struct wl12xx *wl, char *buf, size_t len)
+{
+	struct wl12xx_command cmd;
+	struct acx_revision *rev;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx fw rev");
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	ret = wl12xx_cmd_interrogate(wl, ACX_FW_REV, sizeof(*rev), &cmd);
+	if (ret < 0) {
+		wl12xx_warning("ACX_FW_REV interrogate failed");
+		return ret;
+	}
+
+	rev = (struct acx_revision *) &cmd.parameters;
+
+	/* be careful with the buffer sizes */
+	strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
+
+	/*
+	 * if the firmware version string is exactly
+	 * sizeof(rev->fw_version) long or fw_len is less than
+	 * sizeof(rev->fw_version) it won't be null terminated
+	 */
+	buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
+
+	return 0;
+}
+
+int wl12xx_acx_tx_power(struct wl12xx *wl, int power)
+{
+	struct acx_current_tx_power ie;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
+
+	if (power < 0 || power > 25)
+		return -EINVAL;
+
+	memset(&ie, 0, sizeof(ie));
+
+	ie.header.id = DOT11_CUR_TX_PWR;
+	ie.header.len = sizeof(ie) - sizeof(struct acx_header);
+	ie.current_tx_power = power * 10;
+
+	ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
+	if (ret < 0) {
+		wl12xx_warning("configure of tx power failed: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_feature_cfg(struct wl12xx *wl)
+{
+	struct acx_feature_config feature;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx feature cfg");
+
+	memset(&feature, 0, sizeof(feature));
+
+	feature.header.id = ACX_FEATURE_CFG;
+	feature.header.len = sizeof(feature) - sizeof(struct acx_header);
+
+	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
+	feature.data_flow_options = 0;
+	feature.options = 0;
+
+	ret = wl12xx_cmd_configure(wl, &feature, sizeof(feature));
+	if (ret < 0)
+		wl12xx_error("Couldnt set HW encryption");
+
+	return ret;
+}
+
+int wl12xx_acx_mem_map(struct wl12xx *wl, void *mem_map, size_t len)
+{
+	struct wl12xx_command cmd;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx mem map");
+
+	ret = wl12xx_cmd_interrogate(wl, ACX_MEM_MAP, len, &cmd);
+	if (ret < 0)
+		return ret;
+	else if (cmd.status != CMD_STATUS_SUCCESS)
+		return -EIO;
+
+	memcpy(mem_map, &cmd.parameters, len);
+
+	return 0;
+}
+
+int wl12xx_acx_data_path_params(struct wl12xx *wl,
+				struct acx_data_path_params_resp *data_path)
+{
+	struct acx_data_path_params params;
+	struct wl12xx_command cmd;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx data path params");
+
+	params.rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
+	params.tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
+
+	params.rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM;
+	params.tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM;
+
+	params.tx_complete_threshold = 1;
+
+	params.tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE;
+
+	params.tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT;
+
+	params.header.id = ACX_DATA_PATH_PARAMS;
+	params.header.len = sizeof(params) - sizeof(struct acx_header);
+
+	ret = wl12xx_cmd_configure(wl, &params, sizeof(params));
+	if (ret < 0)
+		return ret;
+
+
+	ret = wl12xx_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS,
+				     sizeof(struct acx_data_path_params_resp),
+				     &cmd);
+
+	if (ret < 0) {
+		wl12xx_warning("failed to read data path parameters: %d", ret);
+		return ret;
+	} else if (cmd.status != CMD_STATUS_SUCCESS) {
+		wl12xx_warning("data path parameter acx status failed");
+		return -EIO;
+	}
+
+	memcpy(data_path, &cmd.parameters, sizeof(*data_path));
+
+	return 0;
+}
+
+int wl12xx_acx_rx_msdu_life_time(struct wl12xx *wl, u32 life_time)
+{
+	struct rx_msdu_lifetime msdu_lifetime;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx rx msdu life time");
+
+	msdu_lifetime.header.id = DOT11_RX_MSDU_LIFE_TIME;
+	msdu_lifetime.header.len = sizeof(msdu_lifetime) -
+		sizeof(struct acx_header);
+	msdu_lifetime.lifetime = life_time;
+
+	ret = wl12xx_cmd_configure(wl, &msdu_lifetime, sizeof(msdu_lifetime));
+	if (ret < 0) {
+		wl12xx_warning("failed to set rx msdu life time: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_rx_config(struct wl12xx *wl, u32 config, u32 filter)
+{
+	struct acx_rx_config rx_config;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx rx config");
+
+	rx_config.header.id = ACX_RX_CFG;
+	rx_config.header.len = sizeof(rx_config) - sizeof(struct acx_header);
+	rx_config.config_options = config;
+	rx_config.filter_options = filter;
+
+	ret = wl12xx_cmd_configure(wl, &rx_config, sizeof(rx_config));
+	if (ret < 0) {
+		wl12xx_warning("failed to set rx config: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_pd_threshold(struct wl12xx *wl)
+{
+	struct acx_packet_detection packet_detection;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx data pd threshold");
+
+	/* FIXME: threshold value not set */
+	packet_detection.header.id = ACX_PD_THRESHOLD;
+	packet_detection.header.len = sizeof(packet_detection) -
+		sizeof(struct acx_header);
+
+	ret = wl12xx_cmd_configure(wl, &packet_detection,
+				   sizeof(packet_detection));
+	if (ret < 0) {
+		wl12xx_warning("failed to set pd threshold: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_slot(struct wl12xx *wl, enum acx_slot_type slot_time)
+{
+	struct acx_slot slot;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx slot");
+
+	slot.header.id = ACX_SLOT;
+	slot.header.len = sizeof(slot) - sizeof(struct acx_header);
+
+	slot.wone_index = STATION_WONE_INDEX;
+	slot.slot_time = slot_time;
+
+	ret = wl12xx_cmd_configure(wl, &slot, sizeof(slot));
+	if (ret < 0) {
+		wl12xx_warning("failed to set slot time: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_group_address_tbl(struct wl12xx *wl)
+{
+	struct multicast_grp_addr_start multicast;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx group address tbl");
+
+	/* MAC filtering */
+	multicast.header.id = DOT11_GROUP_ADDRESS_TBL;
+	multicast.header.len = sizeof(multicast) - sizeof(struct acx_header);
+
+	multicast.enabled = 0;
+	multicast.num_groups = 0;
+	memset(multicast.mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+
+	ret = wl12xx_cmd_configure(wl, &multicast, sizeof(multicast));
+	if (ret < 0) {
+		wl12xx_warning("failed to set group addr table: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_service_period_timeout(struct wl12xx *wl)
+{
+	struct acx_rx_timeout rx_timeout;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx service period timeout");
+
+	/* RX timeout */
+	rx_timeout.header.id = ACX_SERVICE_PERIOD_TIMEOUT;
+	rx_timeout.header.len = sizeof(rx_timeout) - sizeof(struct acx_header);
+
+	rx_timeout.ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
+	rx_timeout.upsd_timeout = RX_TIMEOUT_UPSD_DEF;
+
+	ret = wl12xx_cmd_configure(wl, &rx_timeout, sizeof(rx_timeout));
+	if (ret < 0) {
+		wl12xx_warning("failed to set service period timeout: %d",
+			       ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_rts_threshold(struct wl12xx *wl, u16 rts_threshold)
+{
+	struct acx_rts_threshold rts;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx rts threshold");
+
+	rts.header.id = DOT11_RTS_THRESHOLD;
+	rts.header.len = sizeof(rts) - sizeof(struct acx_header);
+
+	rts.threshold = rts_threshold;
+
+	ret = wl12xx_cmd_configure(wl, &rts, sizeof(rts));
+	if (ret < 0) {
+		wl12xx_warning("failed to set rts threshold: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_beacon_filter_opt(struct wl12xx *wl)
+{
+	struct acx_beacon_filter_option beacon_filter;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx beacon filter opt");
+
+	beacon_filter.header.id = ACX_BEACON_FILTER_OPT;
+	beacon_filter.header.len = sizeof(beacon_filter) -
+		sizeof(struct acx_header);
+
+	beacon_filter.enable = 0;
+	beacon_filter.max_num_beacons = 0;
+
+	ret = wl12xx_cmd_configure(wl, &beacon_filter, sizeof(beacon_filter));
+	if (ret < 0) {
+		wl12xx_warning("failed to set beacon filter opt: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_beacon_filter_table(struct wl12xx *wl)
+{
+	struct acx_beacon_filter_ie_table ie_table;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx beacon filter table");
+
+	ie_table.header.id = ACX_BEACON_FILTER_TABLE;
+	ie_table.header.len = sizeof(ie_table) - sizeof(struct acx_header);
+
+	ie_table.num_ie = 0;
+	memset(ie_table.table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
+
+	ret = wl12xx_cmd_configure(wl, &ie_table, sizeof(ie_table));
+	if (ret < 0) {
+		wl12xx_warning("failed to set beacon filter table: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_sg_enable(struct wl12xx *wl)
+{
+	struct acx_bt_wlan_coex pta;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx sg enable");
+
+	pta.header.id = ACX_SG_ENABLE;
+	pta.header.len = sizeof(pta) - sizeof(struct acx_header);
+
+	pta.enable = SG_ENABLE;
+
+	ret = wl12xx_cmd_configure(wl, &pta, sizeof(pta));
+	if (ret < 0) {
+		wl12xx_warning("failed to set softgemini enable: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_sg_cfg(struct wl12xx *wl)
+{
+	struct acx_bt_wlan_coex_param param;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx sg cfg");
+
+	/* BT-WLAN coext parameters */
+	param.header.id = ACX_SG_CFG;
+	param.header.len = sizeof(param) - sizeof(struct acx_header);
+
+	param.min_rate = RATE_INDEX_24MBPS;
+	param.bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
+	param.wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
+	param.sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
+	param.rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
+	param.tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
+	param.rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
+	param.tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
+	param.wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
+	param.bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
+	param.next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
+	param.wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
+	param.hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
+	param.next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
+	param.antenna_type = PTA_ANTENNA_TYPE_DEF;
+	param.signal_type = PTA_SIGNALING_TYPE_DEF;
+	param.afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
+	param.quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
+	param.max_cts = PTA_MAX_NUM_CTS_DEF;
+	param.wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
+	param.bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
+	param.missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
+	param.wlan_elp_hp = PTA_ELP_HP_DEF;
+	param.bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
+	param.ack_mode_dual_ant = PTA_ACK_MODE_DEF;
+	param.pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
+	param.pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
+	param.bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
+
+	ret = wl12xx_cmd_configure(wl, &param, sizeof(param));
+	if (ret < 0) {
+		wl12xx_warning("failed to set sg config: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_cca_threshold(struct wl12xx *wl)
+{
+	struct acx_energy_detection detection;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx cca threshold");
+
+	detection.header.id = ACX_CCA_THRESHOLD;
+	detection.header.len = sizeof(detection) - sizeof(struct acx_header);
+
+	detection.rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
+	detection.tx_energy_detection = 0;
+
+	ret = wl12xx_cmd_configure(wl, &detection, sizeof(detection));
+	if (ret < 0) {
+		wl12xx_warning("failed to set cca threshold: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_bcn_dtim_options(struct wl12xx *wl)
+{
+	struct acx_beacon_broadcast bb;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx bcn dtim options");
+
+	bb.header.id = ACX_BCN_DTIM_OPTIONS;
+	bb.header.len = sizeof(bb) - sizeof(struct acx_header);
+
+	bb.beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
+	bb.broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
+	bb.rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
+	bb.ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
+
+	ret = wl12xx_cmd_configure(wl, &bb, sizeof(bb));
+	if (ret < 0) {
+		wl12xx_warning("failed to set rx config: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_aid(struct wl12xx *wl, u16 aid)
+{
+	struct acx_aid acx_aid;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx aid");
+
+	acx_aid.header.id = ACX_AID;
+	acx_aid.header.len = sizeof(acx_aid) - sizeof(struct acx_header);
+
+	acx_aid.aid = aid;
+
+	ret = wl12xx_cmd_configure(wl, &acx_aid, sizeof(acx_aid));
+	if (ret < 0) {
+		wl12xx_warning("failed to set aid: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_event_mbox_mask(struct wl12xx *wl, u32 event_mask)
+{
+	struct acx_event_mask mask;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx event mbox mask");
+
+	mask.header.id = ACX_EVENT_MBOX_MASK;
+	mask.header.len = sizeof(mask) - sizeof(struct acx_header);
+
+	/* high event mask is unused */
+	mask.high_event_mask = 0xffffffff;
+
+	mask.event_mask = event_mask;
+
+	ret = wl12xx_cmd_configure(wl, &mask, sizeof(mask));
+	if (ret < 0) {
+		wl12xx_warning("failed to set aid: %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int wl12xx_acx_set_preamble(struct wl12xx *wl, enum acx_preamble_type preamble)
+{
+	struct acx_preamble ie;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx_set_preamble");
+
+	memset(&ie, 0, sizeof(ie));
+
+	ie.header.id = ACX_PREAMBLE_TYPE;
+	ie.header.len = sizeof(ie) - sizeof(struct acx_header);
+	ie.preamble = preamble;
+	ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
+	if (ret < 0) {
+		wl12xx_warning("Setting of preamble failed: %d", ret);
+		return ret;
+	}
+	return 0;
+}
+
+int wl12xx_acx_cts_protect(struct wl12xx *wl,
+			   enum acx_ctsprotect_type ctsprotect)
+{
+	struct acx_ctsprotect ie;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx_set_ctsprotect");
+
+	memset(&ie, 0, sizeof(ie));
+
+	ie.header.id = ACX_CTS_PROTECTION;
+	ie.header.len = sizeof(ie) - sizeof(struct acx_header);
+	ie.ctsprotect = ctsprotect;
+	ret = wl12xx_cmd_configure(wl, &ie, sizeof(ie));
+	if (ret < 0) {
+		wl12xx_warning("Setting of ctsprotect failed: %d", ret);
+		return ret;
+	}
+	return 0;
+}
+
+int wl12xx_acx_statistics(struct wl12xx *wl, struct acx_statistics *stats)
+{
+	struct wl12xx_command *answer;
+	int ret;
+
+	wl12xx_debug(DEBUG_ACX, "acx statistics");
+
+	answer = kmalloc(sizeof(*answer), GFP_KERNEL);
+	if (!answer) {
+		wl12xx_warning("could not allocate memory for acx statistics");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = wl12xx_cmd_interrogate(wl, ACX_STATISTICS, sizeof(*answer),
+				     answer);
+	if (ret < 0) {
+		wl12xx_warning("acx statistics failed: %d", ret);
+		goto out;
+	}
+
+	memcpy(stats, answer->parameters, sizeof(*stats));
+
+out:
+	kfree(answer);
+	return ret;
+}
diff -druN linux-libre-2.6.30-gnu/drivers/net/wireless/wl12xx/acx.h linux-libre-2.6.31-gnu/drivers/net/wireless/wl12xx/acx.h
--- linux-libre-2.6.30-gnu/drivers/net/wireless/wl12xx/acx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.31-gnu/drivers/net/wireless/wl12xx/acx.h	2009-09-09 18:13:59.000000000 -0400
@@ -0,0 +1,1245 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (c) 1998-2007 Texas Instruments Incorporated
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <kalle.valo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL12XX_ACX_H__
+#define __WL12XX_ACX_H__
+
+#include "wl12xx.h"
+
+/* Target's information element */
+struct acx_header {
+	u16 id;
+	u16 len;
+};
+
+struct acx_error_counter {
+	struct acx_header header